Repository: scylladb/dpdk Branch: master Commit: cc7e6ed22c0f Files: 1234 Total size: 45.3 MB Directory structure: gitextract__og3d0td/ ├── .gitignore ├── GNUmakefile ├── LICENSE.GPL ├── LICENSE.LGPL ├── MAINTAINERS ├── Makefile ├── app/ │ ├── Makefile │ ├── cmdline_test/ │ │ ├── Makefile │ │ ├── cmdline_test.c │ │ ├── cmdline_test.h │ │ ├── cmdline_test.py │ │ ├── cmdline_test_data.py │ │ └── commands.c │ ├── proc_info/ │ │ ├── Makefile │ │ └── main.c │ ├── test/ │ │ ├── Makefile │ │ ├── autotest.py │ │ ├── autotest_data.py │ │ ├── autotest_runner.py │ │ ├── autotest_test_funcs.py │ │ ├── commands.c │ │ ├── packet_burst_generator.c │ │ ├── packet_burst_generator.h │ │ ├── process.h │ │ ├── test.c │ │ ├── test.h │ │ ├── test_acl.c │ │ ├── test_acl.h │ │ ├── test_alarm.c │ │ ├── test_atomic.c │ │ ├── test_byteorder.c │ │ ├── test_cmdline.c │ │ ├── test_cmdline.h │ │ ├── test_cmdline_cirbuf.c │ │ ├── test_cmdline_etheraddr.c │ │ ├── test_cmdline_ipaddr.c │ │ ├── test_cmdline_lib.c │ │ ├── test_cmdline_num.c │ │ ├── test_cmdline_portlist.c │ │ ├── test_cmdline_string.c │ │ ├── test_common.c │ │ ├── test_cpuflags.c │ │ ├── test_cycles.c │ │ ├── test_debug.c │ │ ├── test_devargs.c │ │ ├── test_distributor.c │ │ ├── test_distributor_perf.c │ │ ├── test_eal_flags.c │ │ ├── test_eal_fs.c │ │ ├── test_errno.c │ │ ├── test_func_reentrancy.c │ │ ├── test_hash.c │ │ ├── test_hash_functions.c │ │ ├── test_hash_perf.c │ │ ├── test_hash_scaling.c │ │ ├── test_interrupts.c │ │ ├── test_ivshmem.c │ │ ├── test_kni.c │ │ ├── test_kvargs.c │ │ ├── test_link_bonding.c │ │ ├── test_link_bonding_mode4.c │ │ ├── test_logs.c │ │ ├── test_lpm.c │ │ ├── test_lpm6.c │ │ ├── test_lpm6_routes.h │ │ ├── test_lpm_routes.h │ │ ├── test_malloc.c │ │ ├── test_mbuf.c │ │ ├── test_memcpy.c │ │ ├── test_memcpy_perf.c │ │ ├── test_memory.c │ │ ├── test_mempool.c │ │ ├── test_mempool_perf.c │ │ ├── test_memzone.c │ │ ├── test_meter.c │ │ ├── test_mp_secondary.c │ │ ├── test_pci.c │ │ ├── test_per_lcore.c │ │ ├── test_pmd_perf.c │ │ ├── test_pmd_ring.c │ │ ├── test_power.c │ │ ├── test_power_acpi_cpufreq.c │ │ ├── test_power_kvm_vm.c │ │ ├── test_prefetch.c │ │ ├── test_red.c │ │ ├── test_reorder.c │ │ ├── test_ring.c │ │ ├── test_ring_perf.c │ │ ├── test_rwlock.c │ │ ├── test_sched.c │ │ ├── test_spinlock.c │ │ ├── test_string_fns.c │ │ ├── test_table.c │ │ ├── test_table.h │ │ ├── test_table_acl.c │ │ ├── test_table_acl.h │ │ ├── test_table_combined.c │ │ ├── test_table_combined.h │ │ ├── test_table_pipeline.c │ │ ├── test_table_pipeline.h │ │ ├── test_table_ports.c │ │ ├── test_table_ports.h │ │ ├── test_table_tables.c │ │ ├── test_table_tables.h │ │ ├── test_tailq.c │ │ ├── test_thash.c │ │ ├── test_timer.c │ │ ├── test_timer_perf.c │ │ ├── test_timer_racecond.c │ │ ├── test_version.c │ │ ├── virtual_pmd.c │ │ └── virtual_pmd.h │ ├── test-acl/ │ │ ├── Makefile │ │ └── main.c │ ├── test-pipeline/ │ │ ├── Makefile │ │ ├── config.c │ │ ├── init.c │ │ ├── main.c │ │ ├── main.h │ │ ├── pipeline_acl.c │ │ ├── pipeline_hash.c │ │ ├── pipeline_lpm.c │ │ ├── pipeline_lpm_ipv6.c │ │ ├── pipeline_stub.c │ │ └── runtime.c │ └── test-pmd/ │ ├── Makefile │ ├── cmdline.c │ ├── config.c │ ├── csumonly.c │ ├── flowgen.c │ ├── icmpecho.c │ ├── ieee1588fwd.c │ ├── iofwd.c │ ├── macfwd-retry.c │ ├── macfwd.c │ ├── macswap.c │ ├── mempool_anon.c │ ├── mempool_osdep.h │ ├── parameters.c │ ├── rxonly.c │ ├── testpmd.c │ ├── testpmd.h │ └── txonly.c ├── config/ │ ├── common_bsdapp │ ├── common_linuxapp │ ├── defconfig_i686-native-linuxapp-gcc │ ├── defconfig_i686-native-linuxapp-icc │ ├── defconfig_ppc_64-power8-linuxapp-gcc │ ├── defconfig_tile-tilegx-linuxapp-gcc │ ├── defconfig_x86_64-ivshmem-linuxapp-gcc │ ├── defconfig_x86_64-ivshmem-linuxapp-icc │ ├── defconfig_x86_64-native-bsdapp-clang │ ├── defconfig_x86_64-native-bsdapp-gcc │ ├── defconfig_x86_64-native-linuxapp-clang │ ├── defconfig_x86_64-native-linuxapp-gcc │ ├── defconfig_x86_64-native-linuxapp-icc │ └── defconfig_x86_x32-native-linuxapp-gcc ├── doc/ │ ├── api/ │ │ ├── doxy-api-index.md │ │ ├── doxy-api.conf │ │ └── doxy-html-custom.sh │ ├── build-sdk-quick.txt │ └── guides/ │ ├── conf.py │ ├── contributing/ │ │ ├── coding_style.rst │ │ ├── design.rst │ │ ├── documentation.rst │ │ ├── index.rst │ │ └── versioning.rst │ ├── faq/ │ │ ├── faq.rst │ │ └── index.rst │ ├── freebsd_gsg/ │ │ ├── build_dpdk.rst │ │ ├── build_sample_apps.rst │ │ ├── index.rst │ │ ├── install_from_ports.rst │ │ └── intro.rst │ ├── index.rst │ ├── linux_gsg/ │ │ ├── build_dpdk.rst │ │ ├── build_sample_apps.rst │ │ ├── enable_func.rst │ │ ├── index.rst │ │ ├── intro.rst │ │ ├── quick_start.rst │ │ └── sys_reqs.rst │ ├── nics/ │ │ ├── cxgbe.rst │ │ ├── e1000em.rst │ │ ├── index.rst │ │ ├── intel_vf.rst │ │ ├── ixgbe.rst │ │ ├── mlx4.rst │ │ ├── pcap_ring.rst │ │ ├── virtio.rst │ │ └── vmxnet3.rst │ ├── prog_guide/ │ │ ├── build_app.rst │ │ ├── dev_kit_build_system.rst │ │ ├── dev_kit_root_make_help.rst │ │ ├── env_abstraction_layer.rst │ │ ├── ext_app_lib_make_help.rst │ │ ├── extend_intel_dpdk.rst │ │ ├── glossary.rst │ │ ├── hash_lib.rst │ │ ├── index.rst │ │ ├── intro.rst │ │ ├── ip_fragment_reassembly_lib.rst │ │ ├── ivshmem_lib.rst │ │ ├── kernel_nic_interface.rst │ │ ├── link_bonding_poll_mode_drv_lib.rst │ │ ├── lpm6_lib.rst │ │ ├── lpm_lib.rst │ │ ├── mbuf_lib.rst │ │ ├── mempool_lib.rst │ │ ├── multi_proc_support.rst │ │ ├── overview.rst │ │ ├── packet_classif_access_ctrl.rst │ │ ├── packet_distrib_lib.rst │ │ ├── packet_framework.rst │ │ ├── perf_opt_guidelines.rst │ │ ├── poll_mode_drv.rst │ │ ├── port_hotplug_framework.rst │ │ ├── power_man.rst │ │ ├── profile_app.rst │ │ ├── qos_framework.rst │ │ ├── reorder_lib.rst │ │ ├── ring_lib.rst │ │ ├── source_org.rst │ │ ├── thread_safety_intel_dpdk_functions.rst │ │ ├── timer_lib.rst │ │ ├── vhost_lib.rst │ │ └── writing_efficient_code.rst │ ├── rel_notes/ │ │ ├── deprecation.rst │ │ ├── index.rst │ │ ├── known_issues.rst │ │ ├── rel_description.rst │ │ ├── release_1_8.rst │ │ ├── release_2_0.rst │ │ ├── release_2_1.rst │ │ └── supported_os.rst │ ├── sample_app_ug/ │ │ ├── cmd_line.rst │ │ ├── dist_app.rst │ │ ├── exception_path.rst │ │ ├── hello_world.rst │ │ ├── index.rst │ │ ├── intel_quickassist.rst │ │ ├── intro.rst │ │ ├── ip_frag.rst │ │ ├── ip_pipeline.rst │ │ ├── ip_reassembly.rst │ │ ├── ipv4_multicast.rst │ │ ├── kernel_nic_interface.rst │ │ ├── l2_forward_job_stats.rst │ │ ├── l2_forward_real_virtual.rst │ │ ├── l3_forward.rst │ │ ├── l3_forward_access_ctrl.rst │ │ ├── l3_forward_power_man.rst │ │ ├── l3_forward_virtual.rst │ │ ├── link_status_intr.rst │ │ ├── load_balancer.rst │ │ ├── multi_process.rst │ │ ├── netmap_compatibility.rst │ │ ├── packet_ordering.rst │ │ ├── proc_info.rst │ │ ├── qos_metering.rst │ │ ├── qos_scheduler.rst │ │ ├── quota_watermark.rst │ │ ├── rxtx_callbacks.rst │ │ ├── skeleton.rst │ │ ├── tep_termination.rst │ │ ├── test_pipeline.rst │ │ ├── timer.rst │ │ ├── vhost.rst │ │ ├── vm_power_management.rst │ │ └── vmdq_dcb_forwarding.rst │ ├── testpmd_app_ug/ │ │ ├── build_app.rst │ │ ├── index.rst │ │ ├── intro.rst │ │ ├── overview.rst │ │ ├── run_app.rst │ │ └── testpmd_funcs.rst │ └── xen/ │ ├── index.rst │ └── pkt_switch.rst ├── drivers/ │ ├── Makefile │ └── net/ │ ├── Makefile │ ├── af_packet/ │ │ ├── Makefile │ │ ├── rte_eth_af_packet.c │ │ └── rte_eth_af_packet.h │ ├── bnx2x/ │ │ ├── Makefile │ │ ├── bnx2x.c │ │ ├── bnx2x.h │ │ ├── bnx2x_ethdev.c │ │ ├── bnx2x_ethdev.h │ │ ├── bnx2x_logs.h │ │ ├── bnx2x_rxtx.c │ │ ├── bnx2x_rxtx.h │ │ ├── bnx2x_stats.c │ │ ├── bnx2x_stats.h │ │ ├── bnx2x_vfpf.c │ │ ├── bnx2x_vfpf.h │ │ ├── debug.c │ │ ├── ecore_fw_defs.h │ │ ├── ecore_hsi.h │ │ ├── ecore_init.h │ │ ├── ecore_init_ops.h │ │ ├── ecore_mfw_req.h │ │ ├── ecore_reg.h │ │ ├── ecore_sp.c │ │ ├── ecore_sp.h │ │ ├── elink.c │ │ └── elink.h │ ├── bonding/ │ │ ├── Makefile │ │ ├── rte_eth_bond.h │ │ ├── rte_eth_bond_8023ad.c │ │ ├── rte_eth_bond_8023ad.h │ │ ├── rte_eth_bond_8023ad_private.h │ │ ├── rte_eth_bond_alb.c │ │ ├── rte_eth_bond_alb.h │ │ ├── rte_eth_bond_api.c │ │ ├── rte_eth_bond_args.c │ │ ├── rte_eth_bond_pmd.c │ │ └── rte_eth_bond_private.h │ ├── cxgbe/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── adapter.h │ │ │ ├── common.h │ │ │ ├── t4_chip_type.h │ │ │ ├── t4_hw.c │ │ │ ├── t4_hw.h │ │ │ ├── t4_msg.h │ │ │ ├── t4_pci_id_tbl.h │ │ │ ├── t4_regs.h │ │ │ ├── t4_regs_values.h │ │ │ └── t4fw_interface.h │ │ ├── cxgbe.h │ │ ├── cxgbe_compat.h │ │ ├── cxgbe_ethdev.c │ │ ├── cxgbe_main.c │ │ └── sge.c │ ├── e1000/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── README │ │ │ ├── e1000_80003es2lan.c │ │ │ ├── e1000_80003es2lan.h │ │ │ ├── e1000_82540.c │ │ │ ├── e1000_82541.c │ │ │ ├── e1000_82541.h │ │ │ ├── e1000_82542.c │ │ │ ├── e1000_82543.c │ │ │ ├── e1000_82543.h │ │ │ ├── e1000_82571.c │ │ │ ├── e1000_82571.h │ │ │ ├── e1000_82575.c │ │ │ ├── e1000_82575.h │ │ │ ├── e1000_api.c │ │ │ ├── e1000_api.h │ │ │ ├── e1000_defines.h │ │ │ ├── e1000_hw.h │ │ │ ├── e1000_i210.c │ │ │ ├── e1000_i210.h │ │ │ ├── e1000_ich8lan.c │ │ │ ├── e1000_ich8lan.h │ │ │ ├── e1000_mac.c │ │ │ ├── e1000_mac.h │ │ │ ├── e1000_manage.c │ │ │ ├── e1000_manage.h │ │ │ ├── e1000_mbx.c │ │ │ ├── e1000_mbx.h │ │ │ ├── e1000_nvm.c │ │ │ ├── e1000_nvm.h │ │ │ ├── e1000_osdep.c │ │ │ ├── e1000_osdep.h │ │ │ ├── e1000_phy.c │ │ │ ├── e1000_phy.h │ │ │ ├── e1000_regs.h │ │ │ ├── e1000_vf.c │ │ │ └── e1000_vf.h │ │ ├── e1000_ethdev.h │ │ ├── e1000_logs.h │ │ ├── em_ethdev.c │ │ ├── em_rxtx.c │ │ ├── igb_ethdev.c │ │ ├── igb_pf.c │ │ ├── igb_regs.h │ │ └── igb_rxtx.c │ ├── enic/ │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── cq_desc.h │ │ │ ├── cq_enet_desc.h │ │ │ ├── rq_enet_desc.h │ │ │ ├── vnic_cq.c │ │ │ ├── vnic_cq.h │ │ │ ├── vnic_dev.c │ │ │ ├── vnic_dev.h │ │ │ ├── vnic_devcmd.h │ │ │ ├── vnic_enet.h │ │ │ ├── vnic_intr.c │ │ │ ├── vnic_intr.h │ │ │ ├── vnic_nic.h │ │ │ ├── vnic_resource.h │ │ │ ├── vnic_rq.c │ │ │ ├── vnic_rq.h │ │ │ ├── vnic_rss.c │ │ │ ├── vnic_rss.h │ │ │ ├── vnic_stats.h │ │ │ ├── vnic_wq.c │ │ │ ├── vnic_wq.h │ │ │ └── wq_enet_desc.h │ │ ├── enic.h │ │ ├── enic_clsf.c │ │ ├── enic_compat.h │ │ ├── enic_ethdev.c │ │ ├── enic_main.c │ │ ├── enic_res.c │ │ └── enic_res.h │ ├── fm10k/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── fm10k_api.c │ │ │ ├── fm10k_api.h │ │ │ ├── fm10k_common.c │ │ │ ├── fm10k_common.h │ │ │ ├── fm10k_mbx.c │ │ │ ├── fm10k_mbx.h │ │ │ ├── fm10k_osdep.h │ │ │ ├── fm10k_pf.c │ │ │ ├── fm10k_pf.h │ │ │ ├── fm10k_tlv.c │ │ │ ├── fm10k_tlv.h │ │ │ ├── fm10k_type.h │ │ │ ├── fm10k_vf.c │ │ │ └── fm10k_vf.h │ │ ├── fm10k.h │ │ ├── fm10k_ethdev.c │ │ ├── fm10k_logs.h │ │ └── fm10k_rxtx.c │ ├── i40e/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── i40e_adminq.c │ │ │ ├── i40e_adminq.h │ │ │ ├── i40e_adminq_cmd.h │ │ │ ├── i40e_alloc.h │ │ │ ├── i40e_common.c │ │ │ ├── i40e_dcb.c │ │ │ ├── i40e_dcb.h │ │ │ ├── i40e_diag.c │ │ │ ├── i40e_diag.h │ │ │ ├── i40e_hmc.c │ │ │ ├── i40e_hmc.h │ │ │ ├── i40e_lan_hmc.c │ │ │ ├── i40e_lan_hmc.h │ │ │ ├── i40e_nvm.c │ │ │ ├── i40e_osdep.h │ │ │ ├── i40e_prototype.h │ │ │ ├── i40e_register.h │ │ │ ├── i40e_status.h │ │ │ ├── i40e_type.h │ │ │ └── i40e_virtchnl.h │ │ ├── i40e_ethdev.c │ │ ├── i40e_ethdev.h │ │ ├── i40e_ethdev_vf.c │ │ ├── i40e_fdir.c │ │ ├── i40e_logs.h │ │ ├── i40e_pf.c │ │ ├── i40e_pf.h │ │ ├── i40e_rxtx.c │ │ └── i40e_rxtx.h │ ├── ixgbe/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── README │ │ │ ├── ixgbe_82598.c │ │ │ ├── ixgbe_82598.h │ │ │ ├── ixgbe_82599.c │ │ │ ├── ixgbe_82599.h │ │ │ ├── ixgbe_api.c │ │ │ ├── ixgbe_api.h │ │ │ ├── ixgbe_common.c │ │ │ ├── ixgbe_common.h │ │ │ ├── ixgbe_dcb.c │ │ │ ├── ixgbe_dcb.h │ │ │ ├── ixgbe_dcb_82598.c │ │ │ ├── ixgbe_dcb_82598.h │ │ │ ├── ixgbe_dcb_82599.c │ │ │ ├── ixgbe_dcb_82599.h │ │ │ ├── ixgbe_mbx.c │ │ │ ├── ixgbe_mbx.h │ │ │ ├── ixgbe_osdep.h │ │ │ ├── ixgbe_phy.c │ │ │ ├── ixgbe_phy.h │ │ │ ├── ixgbe_type.h │ │ │ ├── ixgbe_vf.c │ │ │ ├── ixgbe_vf.h │ │ │ ├── ixgbe_x540.c │ │ │ ├── ixgbe_x540.h │ │ │ ├── ixgbe_x550.c │ │ │ └── ixgbe_x550.h │ │ ├── ixgbe_82599_bypass.c │ │ ├── ixgbe_bypass.c │ │ ├── ixgbe_bypass.h │ │ ├── ixgbe_bypass_api.h │ │ ├── ixgbe_bypass_defines.h │ │ ├── ixgbe_ethdev.c │ │ ├── ixgbe_ethdev.h │ │ ├── ixgbe_fdir.c │ │ ├── ixgbe_logs.h │ │ ├── ixgbe_pf.c │ │ ├── ixgbe_regs.h │ │ ├── ixgbe_rxtx.c │ │ ├── ixgbe_rxtx.h │ │ └── ixgbe_rxtx_vec.c │ ├── mlx4/ │ │ ├── Makefile │ │ ├── mlx4.c │ │ └── mlx4.h │ ├── mpipe/ │ │ ├── Makefile │ │ └── mpipe_tilegx.c │ ├── null/ │ │ ├── Makefile │ │ └── rte_eth_null.c │ ├── pcap/ │ │ ├── Makefile │ │ └── rte_eth_pcap.c │ ├── ring/ │ │ ├── Makefile │ │ ├── rte_eth_ring.c │ │ └── rte_eth_ring.h │ ├── virtio/ │ │ ├── Makefile │ │ ├── virtio_ethdev.c │ │ ├── virtio_ethdev.h │ │ ├── virtio_logs.h │ │ ├── virtio_pci.c │ │ ├── virtio_pci.h │ │ ├── virtio_ring.h │ │ ├── virtio_rxtx.c │ │ ├── virtqueue.c │ │ └── virtqueue.h │ ├── vmxnet3/ │ │ ├── Makefile │ │ ├── base/ │ │ │ ├── README │ │ │ ├── includeCheck.h │ │ │ ├── upt1_defs.h │ │ │ ├── vmware_pack_begin.h │ │ │ ├── vmware_pack_end.h │ │ │ ├── vmxnet3_defs.h │ │ │ └── vmxnet3_osdep.h │ │ ├── vmxnet3_ethdev.c │ │ ├── vmxnet3_ethdev.h │ │ ├── vmxnet3_logs.h │ │ ├── vmxnet3_ring.h │ │ └── vmxnet3_rxtx.c │ └── xenvirt/ │ ├── Makefile │ ├── rte_eth_xenvirt.c │ ├── rte_eth_xenvirt.h │ ├── rte_mempool_gntalloc.c │ ├── rte_xen_lib.c │ ├── rte_xen_lib.h │ ├── virtio_logs.h │ └── virtqueue.h ├── examples/ │ ├── Makefile │ ├── bond/ │ │ ├── Makefile │ │ ├── main.c │ │ └── main.h │ ├── cmdline/ │ │ ├── Makefile │ │ ├── commands.c │ │ ├── commands.h │ │ ├── main.c │ │ ├── parse_obj_list.c │ │ └── parse_obj_list.h │ ├── distributor/ │ │ ├── Makefile │ │ └── main.c │ ├── dpdk_qat/ │ │ ├── Makefile │ │ ├── config_files/ │ │ │ ├── coleto/ │ │ │ │ └── dh895xcc_qa_dev0.conf │ │ │ ├── shumway/ │ │ │ │ ├── dh89xxcc_qa_dev0.conf │ │ │ │ └── dh89xxcc_qa_dev1.conf │ │ │ └── stargo/ │ │ │ └── dh89xxcc_qa_dev0.conf │ │ ├── crypto.c │ │ ├── crypto.h │ │ └── main.c │ ├── exception_path/ │ │ ├── Makefile │ │ └── main.c │ ├── helloworld/ │ │ ├── Makefile │ │ └── main.c │ ├── ip_fragmentation/ │ │ ├── Makefile │ │ └── main.c │ ├── ip_pipeline/ │ │ ├── Makefile │ │ ├── app.h │ │ ├── config/ │ │ │ ├── ip_pipeline.cfg │ │ │ ├── ip_pipeline.sh │ │ │ └── tm_profile.cfg │ │ ├── config_check.c │ │ ├── config_parse.c │ │ ├── config_parse_tm.c │ │ ├── cpu_core_map.c │ │ ├── cpu_core_map.h │ │ ├── init.c │ │ ├── main.c │ │ ├── pipeline/ │ │ │ ├── hash_func.h │ │ │ ├── pipeline_actions_common.h │ │ │ ├── pipeline_common_be.c │ │ │ ├── pipeline_common_be.h │ │ │ ├── pipeline_common_fe.c │ │ │ ├── pipeline_common_fe.h │ │ │ ├── pipeline_firewall.c │ │ │ ├── pipeline_firewall.h │ │ │ ├── pipeline_firewall_be.c │ │ │ ├── pipeline_firewall_be.h │ │ │ ├── pipeline_flow_classification.c │ │ │ ├── pipeline_flow_classification.h │ │ │ ├── pipeline_flow_classification_be.c │ │ │ ├── pipeline_flow_classification_be.h │ │ │ ├── pipeline_master.c │ │ │ ├── pipeline_master.h │ │ │ ├── pipeline_master_be.c │ │ │ ├── pipeline_master_be.h │ │ │ ├── pipeline_passthrough.c │ │ │ ├── pipeline_passthrough.h │ │ │ ├── pipeline_passthrough_be.c │ │ │ ├── pipeline_passthrough_be.h │ │ │ ├── pipeline_routing.c │ │ │ ├── pipeline_routing.h │ │ │ ├── pipeline_routing_be.c │ │ │ └── pipeline_routing_be.h │ │ ├── pipeline.h │ │ ├── pipeline_be.h │ │ └── thread.c │ ├── ip_reassembly/ │ │ ├── Makefile │ │ └── main.c │ ├── ipv4_multicast/ │ │ ├── Makefile │ │ └── main.c │ ├── kni/ │ │ ├── Makefile │ │ └── main.c │ ├── l2fwd/ │ │ ├── Makefile │ │ └── main.c │ ├── l2fwd-ivshmem/ │ │ ├── Makefile │ │ ├── guest/ │ │ │ ├── Makefile │ │ │ └── guest.c │ │ ├── host/ │ │ │ ├── Makefile │ │ │ └── host.c │ │ └── include/ │ │ └── common.h │ ├── l2fwd-jobstats/ │ │ ├── Makefile │ │ └── main.c │ ├── l3fwd/ │ │ ├── Makefile │ │ └── main.c │ ├── l3fwd-acl/ │ │ ├── Makefile │ │ └── main.c │ ├── l3fwd-power/ │ │ ├── Makefile │ │ └── main.c │ ├── l3fwd-vf/ │ │ ├── Makefile │ │ └── main.c │ ├── link_status_interrupt/ │ │ ├── Makefile │ │ └── main.c │ ├── load_balancer/ │ │ ├── Makefile │ │ ├── config.c │ │ ├── init.c │ │ ├── main.c │ │ ├── main.h │ │ └── runtime.c │ ├── multi_process/ │ │ ├── Makefile │ │ ├── client_server_mp/ │ │ │ ├── Makefile │ │ │ ├── mp_client/ │ │ │ │ ├── Makefile │ │ │ │ └── client.c │ │ │ ├── mp_server/ │ │ │ │ ├── Makefile │ │ │ │ ├── args.c │ │ │ │ ├── args.h │ │ │ │ ├── init.c │ │ │ │ ├── init.h │ │ │ │ └── main.c │ │ │ └── shared/ │ │ │ └── common.h │ │ ├── l2fwd_fork/ │ │ │ ├── Makefile │ │ │ ├── flib.c │ │ │ ├── flib.h │ │ │ └── main.c │ │ ├── simple_mp/ │ │ │ ├── Makefile │ │ │ ├── main.c │ │ │ ├── mp_commands.c │ │ │ └── mp_commands.h │ │ └── symmetric_mp/ │ │ ├── Makefile │ │ └── main.c │ ├── netmap_compat/ │ │ ├── Makefile │ │ ├── bridge/ │ │ │ ├── Makefile │ │ │ └── bridge.c │ │ ├── lib/ │ │ │ ├── compat_netmap.c │ │ │ └── compat_netmap.h │ │ └── netmap/ │ │ ├── netmap.h │ │ └── netmap_user.h │ ├── packet_ordering/ │ │ ├── Makefile │ │ └── main.c │ ├── qos_meter/ │ │ ├── Makefile │ │ ├── main.c │ │ ├── main.h │ │ ├── rte_policer.c │ │ └── rte_policer.h │ ├── qos_sched/ │ │ ├── Makefile │ │ ├── app_thread.c │ │ ├── args.c │ │ ├── cfg_file.c │ │ ├── cfg_file.h │ │ ├── cmdline.c │ │ ├── init.c │ │ ├── main.c │ │ ├── main.h │ │ ├── profile.cfg │ │ ├── profile_ov.cfg │ │ └── stats.c │ ├── quota_watermark/ │ │ ├── Makefile │ │ ├── include/ │ │ │ └── conf.h │ │ ├── qw/ │ │ │ ├── Makefile │ │ │ ├── args.c │ │ │ ├── args.h │ │ │ ├── init.c │ │ │ ├── init.h │ │ │ ├── main.c │ │ │ └── main.h │ │ └── qwctl/ │ │ ├── Makefile │ │ ├── commands.c │ │ ├── commands.h │ │ ├── qwctl.c │ │ └── qwctl.h │ ├── rxtx_callbacks/ │ │ ├── Makefile │ │ └── main.c │ ├── skeleton/ │ │ ├── Makefile │ │ └── basicfwd.c │ ├── tep_termination/ │ │ ├── Makefile │ │ ├── main.c │ │ ├── main.h │ │ ├── vxlan.c │ │ ├── vxlan.h │ │ ├── vxlan_setup.c │ │ └── vxlan_setup.h │ ├── timer/ │ │ ├── Makefile │ │ └── main.c │ ├── vhost/ │ │ ├── Makefile │ │ ├── main.c │ │ └── main.h │ ├── vhost_xen/ │ │ ├── Makefile │ │ ├── main.c │ │ ├── main.h │ │ ├── vhost_monitor.c │ │ ├── virtio-net.h │ │ ├── xen_vhost.h │ │ └── xenstore_parse.c │ ├── vm_power_manager/ │ │ ├── Makefile │ │ ├── channel_manager.c │ │ ├── channel_manager.h │ │ ├── channel_monitor.c │ │ ├── channel_monitor.h │ │ ├── guest_cli/ │ │ │ ├── Makefile │ │ │ ├── main.c │ │ │ ├── vm_power_cli_guest.c │ │ │ └── vm_power_cli_guest.h │ │ ├── main.c │ │ ├── power_manager.c │ │ ├── power_manager.h │ │ ├── vm_power_cli.c │ │ └── vm_power_cli.h │ ├── vmdq/ │ │ ├── Makefile │ │ └── main.c │ └── vmdq_dcb/ │ ├── Makefile │ └── main.c ├── lib/ │ ├── Makefile │ ├── librte_acl/ │ │ ├── Makefile │ │ ├── acl.h │ │ ├── acl_bld.c │ │ ├── acl_gen.c │ │ ├── acl_run.h │ │ ├── acl_run_avx2.c │ │ ├── acl_run_avx2.h │ │ ├── acl_run_scalar.c │ │ ├── acl_run_sse.c │ │ ├── acl_run_sse.h │ │ ├── acl_vect.h │ │ ├── rte_acl.c │ │ ├── rte_acl.h │ │ ├── rte_acl_osdep.h │ │ ├── tb_mem.c │ │ └── tb_mem.h │ ├── librte_cfgfile/ │ │ ├── Makefile │ │ ├── rte_cfgfile.c │ │ └── rte_cfgfile.h │ ├── librte_cmdline/ │ │ ├── Makefile │ │ ├── cmdline.c │ │ ├── cmdline.h │ │ ├── cmdline_cirbuf.c │ │ ├── cmdline_cirbuf.h │ │ ├── cmdline_parse.c │ │ ├── cmdline_parse.h │ │ ├── cmdline_parse_etheraddr.c │ │ ├── cmdline_parse_etheraddr.h │ │ ├── cmdline_parse_ipaddr.c │ │ ├── cmdline_parse_ipaddr.h │ │ ├── cmdline_parse_num.c │ │ ├── cmdline_parse_num.h │ │ ├── cmdline_parse_portlist.c │ │ ├── cmdline_parse_portlist.h │ │ ├── cmdline_parse_string.c │ │ ├── cmdline_parse_string.h │ │ ├── cmdline_rdline.c │ │ ├── cmdline_rdline.h │ │ ├── cmdline_socket.c │ │ ├── cmdline_socket.h │ │ ├── cmdline_vt100.c │ │ └── cmdline_vt100.h │ ├── librte_compat/ │ │ ├── Makefile │ │ └── rte_compat.h │ ├── librte_distributor/ │ │ ├── Makefile │ │ ├── rte_distributor.c │ │ └── rte_distributor.h │ ├── librte_eal/ │ │ ├── Makefile │ │ ├── bsdapp/ │ │ │ ├── Makefile │ │ │ ├── contigmem/ │ │ │ │ ├── BSDmakefile │ │ │ │ ├── Makefile │ │ │ │ └── contigmem.c │ │ │ ├── eal/ │ │ │ │ ├── Makefile │ │ │ │ ├── eal.c │ │ │ │ ├── eal_alarm.c │ │ │ │ ├── eal_debug.c │ │ │ │ ├── eal_hugepage_info.c │ │ │ │ ├── eal_interrupts.c │ │ │ │ ├── eal_lcore.c │ │ │ │ ├── eal_log.c │ │ │ │ ├── eal_memory.c │ │ │ │ ├── eal_pci.c │ │ │ │ ├── eal_thread.c │ │ │ │ ├── eal_timer.c │ │ │ │ └── include/ │ │ │ │ └── exec-env/ │ │ │ │ ├── rte_dom0_common.h │ │ │ │ └── rte_interrupts.h │ │ │ └── nic_uio/ │ │ │ ├── BSDmakefile │ │ │ ├── Makefile │ │ │ └── nic_uio.c │ │ ├── common/ │ │ │ ├── Makefile │ │ │ ├── eal_common_cpuflags.c │ │ │ ├── eal_common_dev.c │ │ │ ├── eal_common_devargs.c │ │ │ ├── eal_common_errno.c │ │ │ ├── eal_common_hexdump.c │ │ │ ├── eal_common_launch.c │ │ │ ├── eal_common_lcore.c │ │ │ ├── eal_common_log.c │ │ │ ├── eal_common_memory.c │ │ │ ├── eal_common_memzone.c │ │ │ ├── eal_common_options.c │ │ │ ├── eal_common_pci.c │ │ │ ├── eal_common_pci_uio.c │ │ │ ├── eal_common_string_fns.c │ │ │ ├── eal_common_tailqs.c │ │ │ ├── eal_common_thread.c │ │ │ ├── eal_common_timer.c │ │ │ ├── eal_filesystem.h │ │ │ ├── eal_hugepages.h │ │ │ ├── eal_internal_cfg.h │ │ │ ├── eal_options.h │ │ │ ├── eal_private.h │ │ │ ├── eal_thread.h │ │ │ ├── include/ │ │ │ │ ├── arch/ │ │ │ │ │ ├── ppc_64/ │ │ │ │ │ │ ├── rte_atomic.h │ │ │ │ │ │ ├── rte_byteorder.h │ │ │ │ │ │ ├── rte_cpuflags.h │ │ │ │ │ │ ├── rte_cycles.h │ │ │ │ │ │ ├── rte_memcpy.h │ │ │ │ │ │ ├── rte_prefetch.h │ │ │ │ │ │ ├── rte_rwlock.h │ │ │ │ │ │ └── rte_spinlock.h │ │ │ │ │ ├── tile/ │ │ │ │ │ │ ├── rte_atomic.h │ │ │ │ │ │ ├── rte_byteorder.h │ │ │ │ │ │ ├── rte_cpuflags.h │ │ │ │ │ │ ├── rte_cycles.h │ │ │ │ │ │ ├── rte_memcpy.h │ │ │ │ │ │ ├── rte_prefetch.h │ │ │ │ │ │ ├── rte_rwlock.h │ │ │ │ │ │ └── rte_spinlock.h │ │ │ │ │ └── x86/ │ │ │ │ │ ├── rte_atomic.h │ │ │ │ │ ├── rte_atomic_32.h │ │ │ │ │ ├── rte_atomic_64.h │ │ │ │ │ ├── rte_byteorder.h │ │ │ │ │ ├── rte_byteorder_32.h │ │ │ │ │ ├── rte_byteorder_64.h │ │ │ │ │ ├── rte_cpuflags.h │ │ │ │ │ ├── rte_cycles.h │ │ │ │ │ ├── rte_memcpy.h │ │ │ │ │ ├── rte_prefetch.h │ │ │ │ │ ├── rte_rtm.h │ │ │ │ │ ├── rte_rwlock.h │ │ │ │ │ ├── rte_spinlock.h │ │ │ │ │ └── rte_vect.h │ │ │ │ ├── generic/ │ │ │ │ │ ├── rte_atomic.h │ │ │ │ │ ├── rte_byteorder.h │ │ │ │ │ ├── rte_cpuflags.h │ │ │ │ │ ├── rte_cycles.h │ │ │ │ │ ├── rte_memcpy.h │ │ │ │ │ ├── rte_prefetch.h │ │ │ │ │ ├── rte_rwlock.h │ │ │ │ │ └── rte_spinlock.h │ │ │ │ ├── rte_alarm.h │ │ │ │ ├── rte_branch_prediction.h │ │ │ │ ├── rte_common.h │ │ │ │ ├── rte_debug.h │ │ │ │ ├── rte_dev.h │ │ │ │ ├── rte_devargs.h │ │ │ │ ├── rte_eal.h │ │ │ │ ├── rte_eal_memconfig.h │ │ │ │ ├── rte_errno.h │ │ │ │ ├── rte_hexdump.h │ │ │ │ ├── rte_interrupts.h │ │ │ │ ├── rte_launch.h │ │ │ │ ├── rte_lcore.h │ │ │ │ ├── rte_log.h │ │ │ │ ├── rte_malloc.h │ │ │ │ ├── rte_malloc_heap.h │ │ │ │ ├── rte_memory.h │ │ │ │ ├── rte_memzone.h │ │ │ │ ├── rte_pci.h │ │ │ │ ├── rte_pci_dev_feature_defs.h │ │ │ │ ├── rte_pci_dev_features.h │ │ │ │ ├── rte_pci_dev_ids.h │ │ │ │ ├── rte_per_lcore.h │ │ │ │ ├── rte_random.h │ │ │ │ ├── rte_string_fns.h │ │ │ │ ├── rte_tailq.h │ │ │ │ ├── rte_version.h │ │ │ │ └── rte_warnings.h │ │ │ ├── malloc_elem.c │ │ │ ├── malloc_elem.h │ │ │ ├── malloc_heap.c │ │ │ ├── malloc_heap.h │ │ │ └── rte_malloc.c │ │ └── linuxapp/ │ │ ├── Makefile │ │ ├── eal/ │ │ │ ├── Makefile │ │ │ ├── eal.c │ │ │ ├── eal_alarm.c │ │ │ ├── eal_debug.c │ │ │ ├── eal_hugepage_info.c │ │ │ ├── eal_interrupts.c │ │ │ ├── eal_ivshmem.c │ │ │ ├── eal_lcore.c │ │ │ ├── eal_log.c │ │ │ ├── eal_memory.c │ │ │ ├── eal_pci.c │ │ │ ├── eal_pci_init.h │ │ │ ├── eal_pci_uio.c │ │ │ ├── eal_pci_vfio.c │ │ │ ├── eal_pci_vfio_mp_sync.c │ │ │ ├── eal_thread.c │ │ │ ├── eal_timer.c │ │ │ ├── eal_vfio.h │ │ │ ├── eal_xen_memory.c │ │ │ └── include/ │ │ │ └── exec-env/ │ │ │ ├── rte_dom0_common.h │ │ │ ├── rte_interrupts.h │ │ │ └── rte_kni_common.h │ │ ├── igb_uio/ │ │ │ ├── Makefile │ │ │ ├── compat.h │ │ │ └── igb_uio.c │ │ ├── kni/ │ │ │ ├── Makefile │ │ │ ├── compat.h │ │ │ ├── ethtool/ │ │ │ │ ├── README │ │ │ │ ├── igb/ │ │ │ │ │ ├── COPYING │ │ │ │ │ ├── e1000_82575.c │ │ │ │ │ ├── e1000_82575.h │ │ │ │ │ ├── e1000_api.c │ │ │ │ │ ├── e1000_api.h │ │ │ │ │ ├── e1000_defines.h │ │ │ │ │ ├── e1000_hw.h │ │ │ │ │ ├── e1000_i210.c │ │ │ │ │ ├── e1000_i210.h │ │ │ │ │ ├── e1000_mac.c │ │ │ │ │ ├── e1000_mac.h │ │ │ │ │ ├── e1000_manage.c │ │ │ │ │ ├── e1000_manage.h │ │ │ │ │ ├── e1000_mbx.c │ │ │ │ │ ├── e1000_mbx.h │ │ │ │ │ ├── e1000_nvm.c │ │ │ │ │ ├── e1000_nvm.h │ │ │ │ │ ├── e1000_osdep.h │ │ │ │ │ ├── e1000_phy.c │ │ │ │ │ ├── e1000_phy.h │ │ │ │ │ ├── e1000_regs.h │ │ │ │ │ ├── igb.h │ │ │ │ │ ├── igb_debugfs.c │ │ │ │ │ ├── igb_ethtool.c │ │ │ │ │ ├── igb_hwmon.c │ │ │ │ │ ├── igb_main.c │ │ │ │ │ ├── igb_param.c │ │ │ │ │ ├── igb_procfs.c │ │ │ │ │ ├── igb_ptp.c │ │ │ │ │ ├── igb_regtest.h │ │ │ │ │ ├── igb_vmdq.c │ │ │ │ │ ├── igb_vmdq.h │ │ │ │ │ ├── kcompat.c │ │ │ │ │ ├── kcompat.h │ │ │ │ │ └── kcompat_ethtool.c │ │ │ │ └── ixgbe/ │ │ │ │ ├── COPYING │ │ │ │ ├── ixgbe.h │ │ │ │ ├── ixgbe_82598.c │ │ │ │ ├── ixgbe_82598.h │ │ │ │ ├── ixgbe_82599.c │ │ │ │ ├── ixgbe_82599.h │ │ │ │ ├── ixgbe_api.c │ │ │ │ ├── ixgbe_api.h │ │ │ │ ├── ixgbe_common.c │ │ │ │ ├── ixgbe_common.h │ │ │ │ ├── ixgbe_dcb.h │ │ │ │ ├── ixgbe_ethtool.c │ │ │ │ ├── ixgbe_fcoe.h │ │ │ │ ├── ixgbe_main.c │ │ │ │ ├── ixgbe_mbx.h │ │ │ │ ├── ixgbe_osdep.h │ │ │ │ ├── ixgbe_phy.c │ │ │ │ ├── ixgbe_phy.h │ │ │ │ ├── ixgbe_sriov.h │ │ │ │ ├── ixgbe_type.h │ │ │ │ ├── ixgbe_x540.c │ │ │ │ ├── ixgbe_x540.h │ │ │ │ ├── kcompat.c │ │ │ │ └── kcompat.h │ │ │ ├── kni_dev.h │ │ │ ├── kni_ethtool.c │ │ │ ├── kni_fifo.h │ │ │ ├── kni_misc.c │ │ │ ├── kni_net.c │ │ │ └── kni_vhost.c │ │ └── xen_dom0/ │ │ ├── Makefile │ │ ├── compat.h │ │ ├── dom0_mm_dev.h │ │ └── dom0_mm_misc.c │ ├── librte_ether/ │ │ ├── Makefile │ │ ├── rte_dev_info.h │ │ ├── rte_eth_ctrl.h │ │ ├── rte_ethdev.c │ │ ├── rte_ethdev.h │ │ └── rte_ether.h │ ├── librte_hash/ │ │ ├── Makefile │ │ ├── rte_cmp_x86.h │ │ ├── rte_cuckoo_hash.c │ │ ├── rte_fbk_hash.c │ │ ├── rte_fbk_hash.h │ │ ├── rte_hash.h │ │ ├── rte_hash_crc.h │ │ ├── rte_jhash.h │ │ └── rte_thash.h │ ├── librte_ip_frag/ │ │ ├── Makefile │ │ ├── ip_frag_common.h │ │ ├── ip_frag_internal.c │ │ ├── rte_ip_frag.h │ │ ├── rte_ip_frag_common.c │ │ ├── rte_ipv4_fragmentation.c │ │ ├── rte_ipv4_reassembly.c │ │ ├── rte_ipv6_fragmentation.c │ │ └── rte_ipv6_reassembly.c │ ├── librte_ivshmem/ │ │ ├── Makefile │ │ ├── rte_ivshmem.c │ │ └── rte_ivshmem.h │ ├── librte_jobstats/ │ │ ├── Makefile │ │ ├── rte_jobstats.c │ │ └── rte_jobstats.h │ ├── librte_kni/ │ │ ├── Makefile │ │ ├── rte_kni.c │ │ ├── rte_kni.h │ │ └── rte_kni_fifo.h │ ├── librte_kvargs/ │ │ ├── Makefile │ │ ├── rte_kvargs.c │ │ └── rte_kvargs.h │ ├── librte_lpm/ │ │ ├── Makefile │ │ ├── rte_lpm.c │ │ ├── rte_lpm.h │ │ ├── rte_lpm6.c │ │ └── rte_lpm6.h │ ├── librte_malloc/ │ │ ├── Makefile │ │ └── rte_malloc_empty.c │ ├── librte_mbuf/ │ │ ├── Makefile │ │ ├── rte_mbuf.c │ │ └── rte_mbuf.h │ ├── librte_mempool/ │ │ ├── Makefile │ │ ├── rte_dom0_mempool.c │ │ ├── rte_mempool.c │ │ └── rte_mempool.h │ ├── librte_meter/ │ │ ├── Makefile │ │ ├── rte_meter.c │ │ └── rte_meter.h │ ├── librte_net/ │ │ ├── Makefile │ │ ├── rte_arp.h │ │ ├── rte_icmp.h │ │ ├── rte_ip.h │ │ ├── rte_sctp.h │ │ ├── rte_tcp.h │ │ └── rte_udp.h │ ├── librte_pipeline/ │ │ ├── Makefile │ │ ├── rte_pipeline.c │ │ └── rte_pipeline.h │ ├── librte_port/ │ │ ├── Makefile │ │ ├── rte_port.h │ │ ├── rte_port_ethdev.c │ │ ├── rte_port_ethdev.h │ │ ├── rte_port_frag.c │ │ ├── rte_port_frag.h │ │ ├── rte_port_ras.c │ │ ├── rte_port_ras.h │ │ ├── rte_port_ring.c │ │ ├── rte_port_ring.h │ │ ├── rte_port_sched.c │ │ ├── rte_port_sched.h │ │ ├── rte_port_source_sink.c │ │ └── rte_port_source_sink.h │ ├── librte_power/ │ │ ├── Makefile │ │ ├── channel_commands.h │ │ ├── guest_channel.c │ │ ├── guest_channel.h │ │ ├── rte_power.c │ │ ├── rte_power.h │ │ ├── rte_power_acpi_cpufreq.c │ │ ├── rte_power_acpi_cpufreq.h │ │ ├── rte_power_common.h │ │ ├── rte_power_kvm_vm.c │ │ └── rte_power_kvm_vm.h │ ├── librte_reorder/ │ │ ├── Makefile │ │ ├── rte_reorder.c │ │ └── rte_reorder.h │ ├── librte_ring/ │ │ ├── Makefile │ │ ├── rte_ring.c │ │ └── rte_ring.h │ ├── librte_sched/ │ │ ├── Makefile │ │ ├── rte_approx.c │ │ ├── rte_approx.h │ │ ├── rte_bitmap.h │ │ ├── rte_red.c │ │ ├── rte_red.h │ │ ├── rte_sched.c │ │ ├── rte_sched.h │ │ └── rte_sched_common.h │ ├── librte_table/ │ │ ├── Makefile │ │ ├── rte_lru.h │ │ ├── rte_table.h │ │ ├── rte_table_acl.c │ │ ├── rte_table_acl.h │ │ ├── rte_table_array.c │ │ ├── rte_table_array.h │ │ ├── rte_table_hash.h │ │ ├── rte_table_hash_ext.c │ │ ├── rte_table_hash_key16.c │ │ ├── rte_table_hash_key32.c │ │ ├── rte_table_hash_key8.c │ │ ├── rte_table_hash_lru.c │ │ ├── rte_table_lpm.c │ │ ├── rte_table_lpm.h │ │ ├── rte_table_lpm_ipv6.c │ │ ├── rte_table_lpm_ipv6.h │ │ ├── rte_table_stub.c │ │ └── rte_table_stub.h │ ├── librte_timer/ │ │ ├── Makefile │ │ ├── rte_timer.c │ │ └── rte_timer.h │ └── librte_vhost/ │ ├── Makefile │ ├── eventfd_link/ │ │ ├── Makefile │ │ ├── eventfd_link.c │ │ └── eventfd_link.h │ ├── libvirt/ │ │ └── qemu-wrap.py │ ├── rte_virtio_net.h │ ├── vhost-net.h │ ├── vhost_cuse/ │ │ ├── eventfd_copy.c │ │ ├── eventfd_copy.h │ │ ├── vhost-net-cdev.c │ │ ├── virtio-net-cdev.c │ │ └── virtio-net-cdev.h │ ├── vhost_rxtx.c │ ├── vhost_user/ │ │ ├── fd_man.c │ │ ├── fd_man.h │ │ ├── vhost-net-user.c │ │ ├── vhost-net-user.h │ │ ├── virtio-net-user.c │ │ └── virtio-net-user.h │ ├── virtio-net.c │ └── virtio-net.h ├── mk/ │ ├── arch/ │ │ ├── i686/ │ │ │ └── rte.vars.mk │ │ ├── ppc_64/ │ │ │ └── rte.vars.mk │ │ ├── tile/ │ │ │ └── rte.vars.mk │ │ ├── x86_64/ │ │ │ └── rte.vars.mk │ │ └── x86_x32/ │ │ └── rte.vars.mk │ ├── exec-env/ │ │ ├── bsdapp/ │ │ │ ├── rte.app.mk │ │ │ └── rte.vars.mk │ │ └── linuxapp/ │ │ ├── rte.app.mk │ │ └── rte.vars.mk │ ├── internal/ │ │ ├── rte.build-post.mk │ │ ├── rte.build-pre.mk │ │ ├── rte.clean-post.mk │ │ ├── rte.clean-pre.mk │ │ ├── rte.compile-post.mk │ │ ├── rte.compile-pre.mk │ │ ├── rte.depdirs-post.mk │ │ ├── rte.depdirs-pre.mk │ │ ├── rte.extvars.mk │ │ ├── rte.install-post.mk │ │ └── rte.install-pre.mk │ ├── machine/ │ │ ├── atm/ │ │ │ └── rte.vars.mk │ │ ├── default/ │ │ │ └── rte.vars.mk │ │ ├── hsw/ │ │ │ └── rte.vars.mk │ │ ├── ivb/ │ │ │ └── rte.vars.mk │ │ ├── native/ │ │ │ └── rte.vars.mk │ │ ├── nhm/ │ │ │ └── rte.vars.mk │ │ ├── power8/ │ │ │ └── rte.vars.mk │ │ ├── snb/ │ │ │ └── rte.vars.mk │ │ ├── tilegx/ │ │ │ └── rte.vars.mk │ │ └── wsm/ │ │ └── rte.vars.mk │ ├── rte.app.mk │ ├── rte.bsdmodule.mk │ ├── rte.cpuflags.mk │ ├── rte.extapp.mk │ ├── rte.extlib.mk │ ├── rte.extobj.mk │ ├── rte.extshared.mk │ ├── rte.extsubdir.mk │ ├── rte.gnuconfigure.mk │ ├── rte.hostapp.mk │ ├── rte.hostlib.mk │ ├── rte.install.mk │ ├── rte.lib.mk │ ├── rte.module.mk │ ├── rte.obj.mk │ ├── rte.sdkbuild.mk │ ├── rte.sdkconfig.mk │ ├── rte.sdkdepdirs.mk │ ├── rte.sdkdoc.mk │ ├── rte.sdkexamples.mk │ ├── rte.sdkgcov.mk │ ├── rte.sdkinstall.mk │ ├── rte.sdkroot.mk │ ├── rte.sdktest.mk │ ├── rte.sdktestall.mk │ ├── rte.shared.mk │ ├── rte.sharelib.mk │ ├── rte.subdir.mk │ ├── rte.vars.mk │ ├── target/ │ │ └── generic/ │ │ ├── rte.app.mk │ │ └── rte.vars.mk │ └── toolchain/ │ ├── clang/ │ │ ├── rte.toolchain-compat.mk │ │ └── rte.vars.mk │ ├── gcc/ │ │ ├── rte.toolchain-compat.mk │ │ └── rte.vars.mk │ └── icc/ │ ├── rte.toolchain-compat.mk │ └── rte.vars.mk ├── pkg/ │ └── dpdk.spec ├── scripts/ │ ├── auto-config-h.sh │ ├── check-maintainers.sh │ ├── cocci/ │ │ └── mtod-offset.cocci │ ├── cocci.sh │ ├── depdirs-rule.sh │ ├── gen-build-mk.sh │ ├── gen-config-h.sh │ ├── relpath.sh │ ├── test-null.sh │ └── validate-abi.sh └── tools/ ├── cpu_layout.py ├── dpdk_nic_bind.py └── setup.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ================================================ FILE: GNUmakefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Head Makefile for compiling rte SDK # RTE_SDK := $(CURDIR) export RTE_SDK # # directory list # ROOTDIRS-y := lib drivers app include $(RTE_SDK)/mk/rte.sdkroot.mk ================================================ FILE: LICENSE.GPL ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: MAINTAINERS ================================================ DPDK Maintainers ================ The intention of this file is to provide a set of names that we can rely on for helping in patch reviews and questions. These names are additional recipients for emails sent to dev@dpdk.org. Please avoid private emails. Descriptions of section entries: M: Maintainer's Full Name T: Git tree location. F: Files and directories with wildcard patterns. A trailing slash includes all files and subdirectory files. A wildcard includes all files but not subdirectories. One pattern per line. Multiple F: lines acceptable. X: Files and directories exclusion, same rules as F: K: Keyword regex pattern to match content. One regex pattern per line. Multiple K: lines acceptable. General Project Administration ------------------------------ M: Thomas Monjalon T: git://dpdk.org/dpdk F: MAINTAINERS F: scripts/check-maintainers.sh Security Issues --------------- M: maintainers@dpdk.org Documentation (with overlaps) ------------- M: Siobhan Butler M: John McNamara F: doc/ Build System ------------ M: Olivier Matz F: GNUmakefile F: Makefile F: config/ F: mk/ F: pkg/ F: scripts/auto-config-h.sh F: scripts/depdirs-rule.sh F: scripts/gen-build-mk.sh F: scripts/gen-config-h.sh F: scripts/relpath.sh F: doc/build-sdk-quick.txt F: doc/guides/prog_guide/build_app.rst F: doc/guides/prog_guide/dev_kit_* F: doc/guides/prog_guide/ext_app_lib_make_help.rst ABI versioning M: Neil Horman F: lib/librte_compat/ F: doc/guides/rel_notes/deprecation.rst F: scripts/validate-abi.sh Environment Abstraction Layer ----------------------------- EAL API and common code M: David Marchand F: lib/librte_eal/common/* F: lib/librte_eal/common/include/* F: lib/librte_eal/common/include/generic/ F: doc/guides/prog_guide/env_abstraction_layer.rst F: app/test/test_alarm.c F: app/test/test_atomic.c F: app/test/test_byteorder.c F: app/test/test_common.c F: app/test/test_cpuflags.c F: app/test/test_cycles.c F: app/test/test_debug.c F: app/test/test_devargs.c F: app/test/test_eal* F: app/test/test_errno.c F: app/test/test_interrupts.c F: app/test/test_logs.c F: app/test/test_memcpy* F: app/test/test_pci.c F: app/test/test_per_lcore.c F: app/test/test_prefetch.c F: app/test/test_rwlock.c F: app/test/test_spinlock.c F: app/test/test_string_fns.c F: app/test/test_tailq.c F: app/test/test_version.c Memory Allocation M: Sergio Gonzalez Monroy F: lib/librte_eal/common/include/rte_mem* F: lib/librte_eal/common/include/rte_malloc.h F: lib/librte_eal/common/*malloc* F: lib/librte_eal/common/eal_common_mem* F: lib/librte_eal/common/eal_hugepages.h F: lib/librte_malloc/ F: doc/guides/prog_guide/env_abstraction_layer.rst F: app/test/test_func_reentrancy.c F: app/test/test_malloc.c F: app/test/test_memory.c F: app/test/test_memzone.c Secondary process K: RTE_PROC_ F: doc/guides/prog_guide/multi_proc_support.rst F: app/test/test_mp_secondary.c F: examples/multi_process/ F: doc/guides/sample_app_ug/multi_process.rst EZchip TILE-Gx M: Zhigang Lu F: lib/librte_eal/common/include/arch/tile/ F: drivers/net/mpipe/ IBM POWER M: Chao Zhu F: lib/librte_eal/common/include/arch/ppc_64/ Intel x86 M: Bruce Richardson M: Konstantin Ananyev F: lib/librte_eal/common/include/arch/x86/ Linux EAL (with overlaps) M: David Marchand F: lib/librte_eal/linuxapp/Makefile F: lib/librte_eal/linuxapp/eal/ F: doc/guides/linux_gsg/ Linux UIO F: lib/librte_eal/linuxapp/igb_uio/ F: lib/librte_eal/linuxapp/eal/*uio* Linux VFIO M: Anatoly Burakov F: lib/librte_eal/linuxapp/eal/*vfio* Linux Xen F: lib/librte_eal/linuxapp/xen_dom0/ F: lib/librte_eal/linuxapp/eal/*xen* F: lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h F: lib/librte_mempool/rte_dom0_mempool.c F: drivers/net/xenvirt/ F: doc/guides/xen/ F: app/test-pmd/mempool_* F: examples/vhost_xen/ FreeBSD EAL (with overlaps) M: Bruce Richardson F: lib/librte_eal/bsdapp/Makefile F: lib/librte_eal/bsdapp/eal/ F: doc/guides/freebsd_gsg/ FreeBSD contigmem M: Bruce Richardson F: lib/librte_eal/bsdapp/contigmem/ FreeBSD UIO M: Bruce Richardson F: lib/librte_eal/bsdapp/nic_uio/ Core Libraries -------------- Memory pool M: Olivier Matz F: lib/librte_mempool/ F: doc/guides/prog_guide/mempool_lib.rst F: app/test/test_mempool* F: app/test/test_func_reentrancy.c Ring queue M: Olivier Matz F: lib/librte_ring/ F: doc/guides/prog_guide/ring_lib.rst F: app/test/test_ring* F: app/test/test_func_reentrancy.c Packet buffer M: Olivier Matz F: lib/librte_mbuf/ F: doc/guides/prog_guide/mbuf_lib.rst F: app/test/test_mbuf.c Ethernet API M: Thomas Monjalon F: lib/librte_ether/ F: scripts/test-null.sh Drivers ------- Link bonding M: Declan Doherty F: drivers/net/bonding/ F: doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst F: app/test/test_link_bonding* F: examples/bond/ Linux KNI M: Helin Zhang F: lib/librte_eal/linuxapp/kni/ F: lib/librte_kni/ F: doc/guides/prog_guide/kernel_nic_interface.rst F: app/test/test_kni.c F: examples/kni/ F: doc/guides/sample_app_ug/kernel_nic_interface.rst Linux AF_PACKET M: John W. Linville F: drivers/net/af_packet/ Chelsio cxgbe M: Rahul Lakkireddy F: drivers/net/cxgbe/ F: doc/guides/nics/cxgbe.rst Cisco enic F: drivers/net/enic/ Intel e1000 M: Wenzhuo Lu F: drivers/net/e1000/ F: doc/guides/nics/e1000em.rst F: doc/guides/nics/intel_vf.rst Intel ixgbe M: Helin Zhang M: Konstantin Ananyev F: drivers/net/ixgbe/ F: doc/guides/nics/ixgbe.rst F: doc/guides/nics/intel_vf.rst Intel i40e M: Helin Zhang F: drivers/net/i40e/ F: doc/guides/nics/intel_vf.rst Intel fm10k M: Jing Chen F: drivers/net/fm10k/ Mellanox mlx4 M: Adrien Mazarguil F: drivers/net/mlx4/ F: doc/guides/nics/mlx4.rst RedHat virtio M: Huawei Xie M: Changchun Ouyang F: drivers/net/virtio/ F: doc/guides/nics/virtio.rst F: lib/librte_vhost/ F: doc/guides/prog_guide/vhost_lib.rst F: examples/vhost/ F: doc/guides/sample_app_ug/vhost.rst VMware vmxnet3 M: Yong Wang F: drivers/net/vmxnet3/ F: doc/guides/nics/vmxnet3.rst PCAP PMD M: Nicolás Pernas Maradei M: John McNamara F: drivers/net/pcap/ F: doc/guides/nics/pcap_ring.rst QLogic/Broadcom bnx2x F: drivers/net/bnx2x/ Ring PMD M: Bruce Richardson F: drivers/net/ring/ F: doc/guides/nics/pcap_ring.rst F: app/test/test_pmd_ring.c Null PMD M: Tetsuya Mukawa F: drivers/net/null/ Packet processing ----------------- Network headers F: lib/librte_net/ IP fragmentation & reassembly M: Konstantin Ananyev F: lib/librte_ip_frag/ F: doc/guides/prog_guide/ip_fragment_reassembly_lib.rst F: examples/ip_fragmentation/ F: doc/guides/sample_app_ug/ip_frag.rst F: examples/ip_reassembly/ F: doc/guides/sample_app_ug/ip_reassembly.rst Distributor M: Bruce Richardson F: lib/librte_distributor/ F: doc/guides/prog_guide/packet_distrib_lib.rst F: app/test/test_distributor* F: examples/distributor/ F: doc/guides/sample_app_ug/dist_app.rst Reorder M: Sergio Gonzalez Monroy F: lib/librte_reorder/ F: doc/guides/prog_guide/reorder_lib.rst F: app/test/test_reorder* F: examples/packet_ordering/ F: doc/guides/sample_app_ug/packet_ordering.rst Hierarchical scheduler M: Cristian Dumitrescu F: lib/librte_sched/ F: doc/guides/prog_guide/qos_framework.rst F: app/test/test_red.c F: app/test/test_sched.c F: examples/qos_sched/ F: doc/guides/sample_app_ug/qos_scheduler.rst Packet Framework ---------------- M: Cristian Dumitrescu F: lib/librte_pipeline/ F: lib/librte_port/ F: lib/librte_table/ F: doc/guides/prog_guide/packet_framework.rst F: app/test/test_table* F: app/test-pipeline/ F: doc/guides/sample_app_ug/test_pipeline.rst F: examples/ip_pipeline/ F: doc/guides/sample_app_ug/ip_pipeline.rst Algorithms ---------- ACL M: Konstantin Ananyev F: lib/librte_acl/ F: doc/guides/prog_guide/packet_classif_access_ctrl.rst F: app/test-acl/ F: app/test/test_acl.* F: examples/l3fwd-acl/ F: doc/guides/sample_app_ug/l3_forward_access_ctrl.rst Hashes M: Bruce Richardson M: Pablo de Lara F: lib/librte_hash/ F: doc/guides/prog_guide/hash_lib.rst F: app/test/test_*hash* F: app/test/test_func_reentrancy.c LPM M: Bruce Richardson F: lib/librte_lpm/ F: doc/guides/prog_guide/lpm* F: app/test/test_lpm* F: app/test/test_func_reentrancy.c Traffic metering M: Cristian Dumitrescu F: lib/librte_meter/ F: doc/guides/sample_app_ug/qos_scheduler.rst F: app/test/test_meter.c F: examples/qos_meter/ F: doc/guides/sample_app_ug/qos_metering.rst Other libraries --------------- Configuration file M: Cristian Dumitrescu F: lib/librte_cfgfile/ Interactive command line M: Olivier Matz F: lib/librte_cmdline/ F: app/cmdline_test/ F: app/test/test_cmdline* F: examples/cmdline/ F: doc/guides/sample_app_ug/cmd_line.rst Qemu IVSHMEM M: Anatoly Burakov F: lib/librte_ivshmem/ F: lib/librte_eal/linuxapp/eal/eal_ivshmem.c F: doc/guides/prog_guide/ivshmem_lib.rst F: app/test/test_ivshmem.c F: examples/l2fwd-ivshmem/ Key/Value parsing M: Olivier Matz F: lib/librte_kvargs/ F: app/test/test_kvargs.c Power management F: lib/librte_power/ F: doc/guides/prog_guide/power_man.rst F: app/test/test_power* F: examples/l3fwd-power/ F: doc/guides/sample_app_ug/l3_forward_power_man.rst F: examples/vm_power_manager/ F: doc/guides/sample_app_ug/vm_power_management.rst Timers M: Robert Sanford F: lib/librte_timer/ F: doc/guides/prog_guide/timer_lib.rst F: app/test/test_timer* F: examples/timer/ F: doc/guides/sample_app_ug/timer.rst Job statistics M: Pawel Wodkowski F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst Test Applications ----------------- Unit tests framework F: app/test/autotest* F: app/test/commands.c F: app/test/packet_burst_generator.c F: app/test/packet_burst_generator.h F: app/test/process.h F: app/test/test.c F: app/test/test.h F: app/test/test_pmd_perf.c F: app/test/virtual_pmd.c F: app/test/virtual_pmd.h Driver testing tool M: Pablo de Lara F: app/test-pmd/ F: doc/guides/testpmd_app_ug/ Dump tool M: Maryam Tahhan M: John McNamara F: app/proc_info/ Other Example Applications -------------------------- M: Bruce Richardson F: examples/dpdk_qat/ F: doc/guides/sample_app_ug/intel_quickassist.rst F: examples/exception_path/ F: doc/guides/sample_app_ug/exception_path.rst M: Bruce Richardson F: examples/helloworld/ F: doc/guides/sample_app_ug/hello_world.rst F: examples/ipv4_multicast/ F: doc/guides/sample_app_ug/ipv4_multicast.rst M: Bruce Richardson F: examples/l2fwd/ F: doc/guides/sample_app_ug/l2_forward_real_virtual.rst F: examples/l3fwd/ F: doc/guides/sample_app_ug/l3_forward.rst F: examples/l3fwd-vf/ F: doc/guides/sample_app_ug/l3_forward_virtual.rst F: examples/link_status_interrupt/ F: doc/guides/sample_app_ug/link_status_intr.rst F: examples/load_balancer/ F: doc/guides/sample_app_ug/load_balancer.rst F: examples/netmap_compat/ F: doc/guides/sample_app_ug/netmap_compatibility.rst F: examples/quota_watermark/ F: doc/guides/sample_app_ug/quota_watermark.rst M: Bruce Richardson M: John McNamara F: examples/rxtx_callbacks/ F: doc/guides/sample_app_ug/rxtx_callbacks.rst M: Bruce Richardson M: John McNamara F: examples/skeleton/ F: doc/guides/sample_app_ug/skeleton.rst M: Jijiang Liu F: examples/tep_termination/ F: examples/vmdq/ F: examples/vmdq_dcb/ F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst ================================================ FILE: Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .error Error please compile using GNU Make (gmake) ================================================ FILE: app/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_APP_TEST) += test DIRS-$(CONFIG_RTE_LIBRTE_ACL) += test-acl DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test-pipeline DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_test DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += proc_info include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: app/cmdline_test/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y) # # library name # APP = cmdline_test # # all sources are stored in SRCS-y # SRCS-y += cmdline_test.c SRCS-y += commands.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: app/cmdline_test/cmdline_test.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cmdline_test.h" int main(int __attribute__((unused)) argc, char __attribute__((unused)) ** argv) { struct cmdline *cl; cl = cmdline_stdin_new(main_ctx, "CMDLINE_TEST>>"); if (cl == NULL) { return -1; } cmdline_interact(cl); cmdline_stdin_exit(cl); return 0; } ================================================ FILE: app/cmdline_test/cmdline_test.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CMDLINE_TEST_H_ #define _CMDLINE_TEST_H_ extern cmdline_parse_ctx_t main_ctx[]; #endif ================================================ FILE: app/cmdline_test/cmdline_test.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Script that runs cmdline_test app and feeds keystrokes into it. import sys, pexpect, string, os, cmdline_test_data # # function to run test # def runTest(child,test): child.send(test["Sequence"]) if test["Result"] == None: return 0 child.expect(test["Result"],1) # # history test is a special case # # This test does the following: # 1) fills the history with garbage up to its full capacity # (just enough to remove last entry) # 2) scrolls back history to the very beginning # 3) checks if the output is as expected, that is, the first # number in the sequence (not the last entry before it) # # This is a self-contained test, it needs only a pexpect child # def runHistoryTest(child): # find out history size child.sendline(cmdline_test_data.CMD_GET_BUFSIZE) child.expect("History buffer size: \\d+", timeout=1) history_size = int(child.after[len(cmdline_test_data.BUFSIZE_TEMPLATE):]) i = 0 # fill the history with numbers while i < history_size / 10: # add 1 to prevent from parsing as octals child.send("1" + str(i).zfill(8) + cmdline_test_data.ENTER) # the app will simply print out the number child.expect(str(i + 100000000), timeout=1) i += 1 # scroll back history child.send(cmdline_test_data.UP * (i + 2) + cmdline_test_data.ENTER) child.expect("100000000", timeout=1) # the path to cmdline_test executable is supplied via command-line. if len(sys.argv) < 2: print "Error: please supply cmdline_test app path" sys.exit(1) test_app_path = sys.argv[1] if not os.path.exists(test_app_path): print "Error: please supply cmdline_test app path" sys.exit(1) child = pexpect.spawn(test_app_path) print "Running command-line tests..." for test in cmdline_test_data.tests: print (test["Name"] + ":").ljust(30), try: runTest(child,test) print "PASS" except: print "FAIL" print child sys.exit(1) # since last test quits the app, run new instance child = pexpect.spawn(test_app_path) print ("History fill test:").ljust(30), try: runHistoryTest(child) print "PASS" except: print "FAIL" print child sys.exit(1) child.close() sys.exit(0) ================================================ FILE: app/cmdline_test/cmdline_test_data.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # collection of static data import sys # keycode constants CTRL_A = chr(1) CTRL_B = chr(2) CTRL_C = chr(3) CTRL_D = chr(4) CTRL_E = chr(5) CTRL_F = chr(6) CTRL_K = chr(11) CTRL_L = chr(12) CTRL_N = chr(14) CTRL_P = chr(16) CTRL_W = chr(23) CTRL_Y = chr(25) ALT_B = chr(27) + chr(98) ALT_D = chr(27) + chr(100) ALT_F = chr(27) + chr(102) ALT_BKSPACE = chr(27) + chr(127) DEL = chr(27) + chr(91) + chr(51) + chr(126) TAB = chr(9) HELP = chr(63) BKSPACE = chr(127) RIGHT = chr(27) + chr(91) + chr(67) DOWN = chr(27) + chr(91) + chr(66) LEFT = chr(27) + chr(91) + chr(68) UP = chr(27) + chr(91) + chr(65) ENTER2 = '\r' ENTER = '\n' # expected result constants NOT_FOUND = "Command not found" BAD_ARG = "Bad arguments" AMBIG = "Ambiguous command" CMD1 = "Command 1 parsed!" CMD2 = "Command 2 parsed!" SINGLE = "Single word command parsed!" SINGLE_LONG = "Single long word command parsed!" AUTO1 = "Autocomplete command 1 parsed!" AUTO2 = "Autocomplete command 2 parsed!" # misc defines CMD_QUIT = "quit" CMD_GET_BUFSIZE = "get_history_bufsize" BUFSIZE_TEMPLATE = "History buffer size: " PROMPT = "CMDLINE_TEST>>" # test defines # each test tests progressively diverse set of keys. this way for example # if we want to use some key sequence in the test, we first need to test # that it itself does what it is expected to do. Most of the tests are # designed that way. # # example: "arrows & delete test 1". we enter a partially valid command, # then move 3 chars left and use delete three times. this way we get to # know that "delete", "left" and "ctrl+B" all work (because if any of # them fails, the whole test will fail and next tests won't be run). # # each test consists of name, character sequence to send to child, # and expected output (if any). tests = [ # test basic commands {"Name" : "command test 1", "Sequence" : "ambiguous first" + ENTER, "Result" : CMD1}, {"Name" : "command test 2", "Sequence" : "ambiguous second" + ENTER, "Result" : CMD2}, {"Name" : "command test 3", "Sequence" : "ambiguous ambiguous" + ENTER, "Result" : AMBIG}, {"Name" : "command test 4", "Sequence" : "ambiguous ambiguous2" + ENTER, "Result" : AMBIG}, {"Name" : "invalid command test 1", "Sequence" : "ambiguous invalid" + ENTER, "Result" : BAD_ARG}, # test invalid commands {"Name" : "invalid command test 2", "Sequence" : "invalid" + ENTER, "Result" : NOT_FOUND}, {"Name" : "invalid command test 3", "Sequence" : "ambiguousinvalid" + ENTER2, "Result" : NOT_FOUND}, # test arrows and deletes {"Name" : "arrows & delete test 1", "Sequence" : "singlebad" + LEFT*2 + CTRL_B + DEL*3 + ENTER, "Result" : SINGLE}, {"Name" : "arrows & delete test 2", "Sequence" : "singlebad" + LEFT*5 + RIGHT + CTRL_F + DEL*3 + ENTER, "Result" : SINGLE}, # test backspace {"Name" : "backspace test", "Sequence" : "singlebad" + BKSPACE*3 + ENTER, "Result" : SINGLE}, # test goto left and goto right {"Name" : "goto left test", "Sequence" : "biguous first" + CTRL_A + "am" + ENTER, "Result" : CMD1}, {"Name" : "goto right test", "Sequence" : "biguous fir" + CTRL_A + "am" + CTRL_E + "st" + ENTER, "Result" : CMD1}, # test goto words {"Name" : "goto left word test", "Sequence" : "ambiguous st" + ALT_B + "fir" + ENTER, "Result" : CMD1}, {"Name" : "goto right word test", "Sequence" : "ambig first" + CTRL_A + ALT_F + "uous" + ENTER, "Result" : CMD1}, # test removing words {"Name" : "remove left word 1", "Sequence" : "single invalid" + CTRL_W + ENTER, "Result" : SINGLE}, {"Name" : "remove left word 2", "Sequence" : "single invalid" + ALT_BKSPACE + ENTER, "Result" : SINGLE}, {"Name" : "remove right word", "Sequence" : "single invalid" + ALT_B + ALT_D + ENTER, "Result" : SINGLE}, # test kill buffer (copy and paste) {"Name" : "killbuffer test 1", "Sequence" : "ambiguous" + CTRL_A + CTRL_K + " first" + CTRL_A + CTRL_Y + ENTER, "Result" : CMD1}, {"Name" : "killbuffer test 2", "Sequence" : "ambiguous" + CTRL_A + CTRL_K + CTRL_Y*26 + ENTER, "Result" : NOT_FOUND}, # test newline {"Name" : "newline test", "Sequence" : "invalid" + CTRL_C + "single" + ENTER, "Result" : SINGLE}, # test redisplay (nothing should really happen) {"Name" : "redisplay test", "Sequence" : "single" + CTRL_L + ENTER, "Result" : SINGLE}, # test autocomplete {"Name" : "autocomplete test 1", "Sequence" : "si" + TAB + ENTER, "Result" : SINGLE}, {"Name" : "autocomplete test 2", "Sequence" : "si" + TAB + "_" + TAB + ENTER, "Result" : SINGLE_LONG}, {"Name" : "autocomplete test 3", "Sequence" : "in" + TAB + ENTER, "Result" : NOT_FOUND}, {"Name" : "autocomplete test 4", "Sequence" : "am" + TAB + ENTER, "Result" : BAD_ARG}, {"Name" : "autocomplete test 5", "Sequence" : "am" + TAB + "fir" + TAB + ENTER, "Result" : CMD1}, {"Name" : "autocomplete test 6", "Sequence" : "am" + TAB + "fir" + TAB + TAB + ENTER, "Result" : CMD1}, {"Name" : "autocomplete test 7", "Sequence" : "am" + TAB + "fir" + TAB + " " + TAB + ENTER, "Result" : CMD1}, {"Name" : "autocomplete test 8", "Sequence" : "am" + TAB + " am" + TAB + " " + ENTER, "Result" : AMBIG}, {"Name" : "autocomplete test 9", "Sequence" : "am" + TAB + "inv" + TAB + ENTER, "Result" : BAD_ARG}, {"Name" : "autocomplete test 10", "Sequence" : "au" + TAB + ENTER, "Result" : NOT_FOUND}, {"Name" : "autocomplete test 11", "Sequence" : "au" + TAB + "1" + ENTER, "Result" : AUTO1}, {"Name" : "autocomplete test 12", "Sequence" : "au" + TAB + "2" + ENTER, "Result" : AUTO2}, {"Name" : "autocomplete test 13", "Sequence" : "au" + TAB + "2" + TAB + ENTER, "Result" : AUTO2}, {"Name" : "autocomplete test 14", "Sequence" : "au" + TAB + "2 " + TAB + ENTER, "Result" : AUTO2}, {"Name" : "autocomplete test 15", "Sequence" : "24" + TAB + ENTER, "Result" : "24"}, # test history {"Name" : "history test 1", "Sequence" : "invalid" + ENTER + "single" + ENTER + "invalid" + ENTER + UP + CTRL_P + ENTER, "Result" : SINGLE}, {"Name" : "history test 2", "Sequence" : "invalid" + ENTER + "ambiguous first" + ENTER + "invalid" + ENTER + "single" + ENTER + UP * 3 + CTRL_N + DOWN + ENTER, "Result" : SINGLE}, # # tests that improve coverage # # empty space tests {"Name" : "empty space test 1", "Sequence" : RIGHT + LEFT + CTRL_B + CTRL_F + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 2", "Sequence" : BKSPACE + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 3", "Sequence" : CTRL_E*2 + CTRL_A*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 4", "Sequence" : ALT_F*2 + ALT_B*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 5", "Sequence" : " " + CTRL_E*2 + CTRL_A*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 6", "Sequence" : " " + CTRL_A + ALT_F*2 + ALT_B*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 7", "Sequence" : " " + CTRL_A + CTRL_D + CTRL_E + CTRL_D + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 8", "Sequence" : " space" + CTRL_W*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 9", "Sequence" : " space" + ALT_BKSPACE*2 + ENTER, "Result" : PROMPT}, {"Name" : "empty space test 10", "Sequence" : " space " + CTRL_A + ALT_D*3 + ENTER, "Result" : PROMPT}, # non-printable char tests {"Name" : "non-printable test 1", "Sequence" : chr(27) + chr(47) + ENTER, "Result" : PROMPT}, {"Name" : "non-printable test 2", "Sequence" : chr(27) + chr(128) + ENTER*7, "Result" : PROMPT}, {"Name" : "non-printable test 3", "Sequence" : chr(27) + chr(91) + chr(127) + ENTER*6, "Result" : PROMPT}, # miscellaneous tests {"Name" : "misc test 1", "Sequence" : ENTER, "Result" : PROMPT}, {"Name" : "misc test 2", "Sequence" : "single #comment" + ENTER, "Result" : SINGLE}, {"Name" : "misc test 3", "Sequence" : "#empty line" + ENTER, "Result" : PROMPT}, {"Name" : "misc test 4", "Sequence" : " single " + ENTER, "Result" : SINGLE}, {"Name" : "misc test 5", "Sequence" : "single#" + ENTER, "Result" : SINGLE}, {"Name" : "misc test 6", "Sequence" : 'a' * 257 + ENTER, "Result" : NOT_FOUND}, {"Name" : "misc test 7", "Sequence" : "clear_history" + UP*5 + DOWN*5 + ENTER, "Result" : PROMPT}, {"Name" : "misc test 8", "Sequence" : "a" + HELP + CTRL_C, "Result" : PROMPT}, {"Name" : "misc test 9", "Sequence" : CTRL_D*3, "Result" : None}, ] ================================================ FILE: app/cmdline_test/commands.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "cmdline_test.h" /*** quit ***/ /* exit application */ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_tok = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "exit application", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_tok, NULL, }, }; /*** single ***/ /* a simple single-word command */ struct cmd_single_result { cmdline_fixed_string_t single; }; static void cmd_single_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Single word command parsed!\n"); } cmdline_parse_token_string_t cmd_single_tok = TOKEN_STRING_INITIALIZER(struct cmd_single_result, single, "single"); cmdline_parse_inst_t cmd_single = { .f = cmd_single_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "a simple single-word command", .tokens = { /* token list, NULL terminated */ (void *)&cmd_single_tok, NULL, }, }; /*** single_long ***/ /* a variant of "single" command. useful to test autocomplete */ struct cmd_single_long_result { cmdline_fixed_string_t single_long; }; static void cmd_single_long_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Single long word command parsed!\n"); } cmdline_parse_token_string_t cmd_single_long_tok = TOKEN_STRING_INITIALIZER(struct cmd_single_long_result, single_long, "single_long"); cmdline_parse_inst_t cmd_single_long = { .f = cmd_single_long_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "a variant of \"single\" command, useful to test autocomplete", .tokens = { /* token list, NULL terminated */ (void *)&cmd_single_long_tok, NULL, }, }; /*** autocomplete_1 ***/ /* first command to test autocomplete when multiple commands have chars * in common but none should complete due to ambiguity */ struct cmd_autocomplete_1_result { cmdline_fixed_string_t token; }; static void cmd_autocomplete_1_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Autocomplete command 1 parsed!\n"); } cmdline_parse_token_string_t cmd_autocomplete_1_tok = TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_1_result, token, "autocomplete_1"); cmdline_parse_inst_t cmd_autocomplete_1 = { .f = cmd_autocomplete_1_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "first ambiguous autocomplete command", .tokens = { /* token list, NULL terminated */ (void *)&cmd_autocomplete_1_tok, NULL, }, }; /*** autocomplete_2 ***/ /* second command to test autocomplete when multiple commands have chars * in common but none should complete due to ambiguity */ struct cmd_autocomplete_2_result { cmdline_fixed_string_t token; }; static void cmd_autocomplete_2_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Autocomplete command 2 parsed!\n"); } cmdline_parse_token_string_t cmd_autocomplete_2_tok = TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_2_result, token, "autocomplete_2"); cmdline_parse_inst_t cmd_autocomplete_2 = { .f = cmd_autocomplete_2_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "second ambiguous autocomplete command", .tokens = { /* token list, NULL terminated */ (void *)&cmd_autocomplete_2_tok, NULL, }, }; /*** number command ***/ /* a command that simply returns whatever (uint32) number is supplied to it */ struct cmd_num_result { unsigned num; }; static void cmd_num_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { unsigned result = ((struct cmd_num_result*)parsed_result)->num; cmdline_printf(cl, "%u\n", result); } cmdline_parse_token_num_t cmd_num_tok = TOKEN_NUM_INITIALIZER(struct cmd_num_result, num, UINT32); cmdline_parse_inst_t cmd_num = { .f = cmd_num_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "a command that simply returns whatever number is entered", .tokens = { /* token list, NULL terminated */ (void *)&cmd_num_tok, NULL, }, }; /*** ambiguous first|ambiguous ***/ /* first command used to test command ambiguity */ struct cmd_ambig_result_1 { cmdline_fixed_string_t common_part; cmdline_fixed_string_t ambig_part; }; static void cmd_ambig_1_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Command 1 parsed!\n"); } cmdline_parse_token_string_t cmd_ambig_common_1 = TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, common_part, "ambiguous"); cmdline_parse_token_string_t cmd_ambig_ambig_1 = TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, ambig_part, "first#ambiguous#ambiguous2"); cmdline_parse_inst_t cmd_ambig_1 = { .f = cmd_ambig_1_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "first command used to test command ambiguity", .tokens = { /* token list, NULL terminated */ (void *)&cmd_ambig_common_1, (void*)&cmd_ambig_ambig_1, NULL, }, }; /*** ambiguous second|ambiguous ***/ /* second command used to test command ambiguity */ struct cmd_ambig_result_2 { cmdline_fixed_string_t common_part; cmdline_fixed_string_t ambig_part; }; static void cmd_ambig_2_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Command 2 parsed!\n"); } cmdline_parse_token_string_t cmd_ambig_common_2 = TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, common_part, "ambiguous"); cmdline_parse_token_string_t cmd_ambig_ambig_2 = TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, ambig_part, "second#ambiguous#ambiguous2"); cmdline_parse_inst_t cmd_ambig_2 = { .f = cmd_ambig_2_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "second command used to test command ambiguity", .tokens = { /* token list, NULL terminated */ (void *)&cmd_ambig_common_2, (void*)&cmd_ambig_ambig_2, NULL, }, }; /*** get_history_bufsize ***/ /* command that displays total space in history buffer * this will be useful for testing history (to fill it up just enough to * remove the last entry, we need to know how big it is). */ struct cmd_get_history_bufsize_result { cmdline_fixed_string_t str; }; static void cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "History buffer size: %zu\n", sizeof(cl->rdl.history_buf)); } cmdline_parse_token_string_t cmd_get_history_bufsize_tok = TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str, "get_history_bufsize"); cmdline_parse_inst_t cmd_get_history_bufsize = { .f = cmd_get_history_bufsize_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "command that displays total space in history buffer", .tokens = { /* token list, NULL terminated */ (void *)&cmd_get_history_bufsize_tok, NULL, }, }; /*** clear_history ***/ /* clears history buffer */ struct cmd_clear_history_result { cmdline_fixed_string_t str; }; static void cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { rdline_clear_history(&cl->rdl); } cmdline_parse_token_string_t cmd_clear_history_tok = TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str, "clear_history"); cmdline_parse_inst_t cmd_clear_history = { .f = cmd_clear_history_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "clear command history", .tokens = { /* token list, NULL terminated */ (void *)&cmd_clear_history_tok, NULL, }, }; /****************/ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_ambig_1, (cmdline_parse_inst_t *)&cmd_ambig_2, (cmdline_parse_inst_t *)&cmd_single, (cmdline_parse_inst_t *)&cmd_single_long, (cmdline_parse_inst_t *)&cmd_num, (cmdline_parse_inst_t *)&cmd_get_history_bufsize, (cmdline_parse_inst_t *)&cmd_clear_history, (cmdline_parse_inst_t *)&cmd_autocomplete_1, (cmdline_parse_inst_t *)&cmd_autocomplete_2, NULL, }; ================================================ FILE: app/proc_info/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk APP = proc_info CFLAGS += $(WERROR_FLAGS) # all source are stored in SRCS-y SRCS-y := main.c # this application needs libraries first DEPDIRS-y += lib include $(RTE_SDK)/mk/rte.app.mk ================================================ FILE: app/proc_info/main.c ================================================ /* * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 /**< mask of enabled ports */ static uint32_t enabled_port_mask; /**< Enable stats. */ static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ static uint32_t reset_xstats; /**< Enable memory info. */ static uint32_t mem_info; /**< display usage */ static void proc_info_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK\n" " -m to display DPDK memory zones, segments and TAILQ information\n" " -p PORTMASK: hexadecimal bitmask of ports to retrieve stats for\n" " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); } /* * Parse the portmask provided at run time. */ static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; errno = 0; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { printf("%s ERROR parsing the port mask\n", __func__); return -1; } if (pm == 0) return -1; return pm; } /* Parse the argument given in the command line of the application */ static int proc_info_parse_args(int argc, char **argv) { int opt; int option_index; char *prgname = argv[0]; static struct option long_option[] = { {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; if (argc == 1) proc_info_usage(prgname); /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:m", long_option, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); proc_info_usage(prgname); return -1; } break; case 'm': mem_info = 1; break; case 0: /* Print stats */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) enable_stats = 1; /* Print xstats */ else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) reset_stats = 1; /* Reset xstats */ else if (!strncmp(long_option[option_index].name, "xstats-reset", MAX_LONG_OPT_SZ)) reset_xstats = 1; break; default: proc_info_usage(prgname); return -1; } } return 0; } static void meminfo_display(void) { printf("----------- MEMORY_SEGMENTS -----------\n"); rte_dump_physmem_layout(stdout); printf("--------- END_MEMORY_SEGMENTS ---------\n"); printf("------------ MEMORY_ZONES -------------\n"); rte_memzone_dump(stdout); printf("---------- END_MEMORY_ZONES -----------\n"); printf("------------- TAIL_QUEUES -------------\n"); rte_dump_tailq(stdout); printf("---------- END_TAIL_QUEUES ------------\n"); } static void nic_stats_display(uint8_t port_id) { struct rte_eth_stats stats; uint8_t i; static const char *nic_stats_border = "########################"; rte_eth_stats_get(port_id, &stats); printf("\n %s NIC statistics for port %-2d %s\n", nic_stats_border, port_id, nic_stats_border); printf(" RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64 " RX-bytes: %-10"PRIu64"\n", stats.ipackets, stats.ierrors, stats.ibytes); printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf); printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64 " TX-bytes: %-10"PRIu64"\n", stats.opackets, stats.oerrors, stats.obytes); printf("\n"); for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d RX-packets: %-10"PRIu64 " RX-errors: %-10"PRIu64 " RX-bytes: %-10"PRIu64"\n", i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]); } printf("\n"); for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d TX-packets: %-10"PRIu64 " TX-bytes: %-10"PRIu64"\n", i, stats.q_opackets[i], stats.q_obytes[i]); } printf(" %s############################%s\n", nic_stats_border, nic_stats_border); } static void nic_stats_clear(uint8_t port_id) { printf("\n Clearing NIC stats for port %d\n", port_id); rte_eth_stats_reset(port_id); printf("\n NIC statistics for port %d cleared\n", port_id); } static void nic_xstats_display(uint8_t port_id) { struct rte_eth_xstats *xstats; int len, ret, i; static const char *nic_stats_border = "########################"; len = rte_eth_xstats_get(port_id, NULL, 0); if (len < 0) { printf("Cannot get xstats count\n"); return; } xstats = malloc(sizeof(xstats[0]) * len); if (xstats == NULL) { printf("Cannot allocate memory for xstats\n"); return; } printf("###### NIC extended statistics for port %-2d #########\n", port_id); printf("%s############################\n", nic_stats_border); ret = rte_eth_xstats_get(port_id, xstats, len); if (ret < 0 || ret > len) { printf("Cannot get xstats\n"); free(xstats); return; } for (i = 0; i < len; i++) printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value); printf("%s############################\n", nic_stats_border); free(xstats); } static void nic_xstats_clear(uint8_t port_id) { printf("\n Clearing NIC xstats for port %d\n", port_id); rte_eth_xstats_reset(port_id); printf("\n NIC extended statistics for port %d cleared\n", port_id); } int main(int argc, char **argv) { int ret; int i; char c_flag[] = "-c1"; char n_flag[] = "-n4"; char mp_flag[] = "--proc-type=secondary"; char *argp[argc + 3]; uint8_t nb_ports; argp[0] = argv[0]; argp[1] = c_flag; argp[2] = n_flag; argp[3] = mp_flag; for (i = 1; i < argc; i++) argp[i + 3] = argv[i]; argc += 3; ret = rte_eal_init(argc, argp); if (ret < 0) rte_panic("Cannot init EAL\n"); argc -= ret; argv += (ret - 3); /* parse app arguments */ ret = proc_info_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid argument\n"); if (mem_info) { meminfo_display(); return 0; } nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* If no port mask was specified*/ if (enabled_port_mask == 0) enabled_port_mask = 0xffff; for (i = 0; i < nb_ports; i++) { if (enabled_port_mask & (1 << i)) { if (enable_stats) nic_stats_display(i); else if (enable_xstats) nic_xstats_display(i); else if (reset_stats) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); } } return 0; } ================================================ FILE: app/test/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_APP_TEST),y) # # library name # APP = test # # all sources are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c SRCS-y += test.c SRCS-y += test_pci.c SRCS-y += test_prefetch.c SRCS-y += test_byteorder.c SRCS-y += test_per_lcore.c SRCS-y += test_atomic.c SRCS-y += test_malloc.c SRCS-y += test_cycles.c SRCS-y += test_spinlock.c SRCS-y += test_memory.c SRCS-y += test_memzone.c SRCS-y += test_ring.c SRCS-y += test_ring_perf.c SRCS-y += test_pmd_perf.c ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y) SRCS-y += test_table.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test_table_pipeline.c SRCS-y += test_table_tables.c SRCS-y += test_table_ports.c SRCS-y += test_table_combined.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_table_acl.c endif SRCS-y += test_rwlock.c SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer.c SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_perf.c SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_racecond.c SRCS-y += test_mempool.c SRCS-y += test_mempool_perf.c SRCS-y += test_mbuf.c SRCS-y += test_logs.c SRCS-y += test_memcpy.c SRCS-y += test_memcpy_perf.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_thash.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_scaling.c SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c SRCS-y += test_debug.c SRCS-y += test_errno.c SRCS-y += test_tailq.c SRCS-y += test_string_fns.c SRCS-y += test_cpuflags.c SRCS-y += test_mp_secondary.c SRCS-y += test_eal_flags.c SRCS-y += test_eal_fs.c SRCS-y += test_alarm.c SRCS-y += test_interrupts.c SRCS-y += test_version.c SRCS-y += test_func_reentrancy.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c ifeq ($(CONFIG_RTE_LIBRTE_SCHED),y) SRCS-y += test_red.c SRCS-$(CONFIG_RTE_ARCH_X86_64) += test_sched.c endif SRCS-$(CONFIG_RTE_LIBRTE_METER) += test_meter.c SRCS-$(CONFIG_RTE_LIBRTE_KNI) += test_kni.c SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power.c test_power_acpi_cpufreq.c SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power_kvm_vm.c SRCS-y += test_common.c SRCS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += test_ivshmem.c SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor.c SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor_perf.c SRCS-$(CONFIG_RTE_LIBRTE_REORDER) += test_reorder.c SRCS-y += test_devargs.c SRCS-y += virtual_pmd.c SRCS-y += packet_burst_generator.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_acl.c ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y) SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding_mode4.c endif SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring.c SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # Disable warnings of deprecated-declarations in test_kni.c ifeq ($(CC), icc) CFLAGS_test_kni.o += -wd1478 else CFLAGS_test_kni.o += -Wno-deprecated-declarations endif CFLAGS += -D_GNU_SOURCE # Disable VTA for memcpy test ifeq ($(CC), gcc) ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS_test_memcpy.o += -fno-var-tracking-assignments CFLAGS_test_memcpy_perf.o += -fno-var-tracking-assignments endif endif # this application needs libraries first DEPDIRS-y += lib drivers # Link against shared libraries when needed ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y) ifneq ($(CONFIG_RTE_LIBRTE_PMD_RING),y) $(error Link bonding tests require CONFIG_RTE_LIBRTE_PMD_RING=y) else ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) LDLIBS += -lrte_pmd_ring endif endif endif include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: app/test/autotest.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Script that uses either test app or qemu controlled by python-pexpect import sys, autotest_data, autotest_runner def usage(): print"Usage: autotest.py [test app|test iso image]", print "[target] [whitelist|-blacklist]" if len(sys.argv) < 3: usage() sys.exit(1) target = sys.argv[2] test_whitelist=None test_blacklist=None # get blacklist/whitelist if len(sys.argv) > 3: testlist = sys.argv[3].split(',') testlist = [test.lower() for test in testlist] if testlist[0].startswith('-'): testlist[0] = testlist[0].lstrip('-') test_blacklist = testlist else: test_whitelist = testlist cmdline = "%s -c f -n 4"%(sys.argv[1]) print cmdline runner = autotest_runner.AutotestRunner(cmdline, target, test_blacklist, test_whitelist) for test_group in autotest_data.parallel_test_group_list: runner.add_parallel_test_group(test_group) for test_group in autotest_data.non_parallel_test_group_list: runner.add_non_parallel_test_group(test_group) num_fails = runner.run_all_tests() sys.exit(num_fails) ================================================ FILE: app/test/autotest_data.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Test data for autotests from glob import glob from autotest_test_funcs import * # quick and dirty function to find out number of sockets def num_sockets(): result = len(glob("/sys/devices/system/node/node*")) if result == 0: return 1 return result # Assign given number to each socket # e.g. 32 becomes 32,32 or 32,32,32,32 def per_sockets(num): return ",".join([str(num)] * num_sockets()) # groups of tests that can be run in parallel # the grouping has been found largely empirically parallel_test_group_list = [ { "Prefix": "group_1", "Memory" : per_sockets(8), "Tests" : [ { "Name" : "Timer autotest", "Command" : "timer_autotest", "Func" : timer_autotest, "Report" : None, }, { "Name" : "Debug autotest", "Command" : "debug_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Errno autotest", "Command" : "errno_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Meter autotest", "Command" : "meter_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Common autotest", "Command" : "common_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Dump log history", "Command" : "dump_log_history", "Func" : dump_autotest, "Report" : None, }, { "Name" : "Dump rings", "Command" : "dump_ring", "Func" : dump_autotest, "Report" : None, }, { "Name" : "Dump mempools", "Command" : "dump_mempool", "Func" : dump_autotest, "Report" : None, }, ] }, { "Prefix": "group_2", "Memory" : "32", "Tests" : [ { "Name" : "Memory autotest", "Command" : "memory_autotest", "Func" : memory_autotest, "Report" : None, }, { "Name" : "Read/write lock autotest", "Command" : "rwlock_autotest", "Func" : rwlock_autotest, "Report" : None, }, { "Name" : "Logs autotest", "Command" : "logs_autotest", "Func" : logs_autotest, "Report" : None, }, { "Name" : "CPU flags autotest", "Command" : "cpuflags_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Version autotest", "Command" : "version_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "EAL filesystem autotest", "Command" : "eal_fs_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "EAL flags autotest", "Command" : "eal_flags_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Hash autotest", "Command" : "hash_autotest", "Func" : default_autotest, "Report" : None, }, ], }, { "Prefix": "group_3", "Memory" : per_sockets(1024), "Tests" : [ { "Name" : "LPM autotest", "Command" : "lpm_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "IVSHMEM autotest", "Command" : "ivshmem_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Memcpy autotest", "Command" : "memcpy_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Memzone autotest", "Command" : "memzone_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "String autotest", "Command" : "string_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Alarm autotest", "Command" : "alarm_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "group_4", "Memory" : per_sockets(128), "Tests" : [ { "Name" : "PCI autotest", "Command" : "pci_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Malloc autotest", "Command" : "malloc_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Multi-process autotest", "Command" : "multiprocess_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Mbuf autotest", "Command" : "mbuf_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Per-lcore autotest", "Command" : "per_lcore_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Ring autotest", "Command" : "ring_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "group_5", "Memory" : "32", "Tests" : [ { "Name" : "Spinlock autotest", "Command" : "spinlock_autotest", "Func" : spinlock_autotest, "Report" : None, }, { "Name" : "Byte order autotest", "Command" : "byteorder_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "TAILQ autotest", "Command" : "tailq_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Command-line autotest", "Command" : "cmdline_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Interrupts autotest", "Command" : "interrupt_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "group_6", "Memory" : per_sockets(620), "Tests" : [ { "Name" : "Function reentrancy autotest", "Command" : "func_reentrancy_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Mempool autotest", "Command" : "mempool_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Atomics autotest", "Command" : "atomic_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Prefetch autotest", "Command" : "prefetch_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" :"Red autotest", "Command" : "red_autotest", "Func" :default_autotest, "Report" :None, }, ] }, { "Prefix" : "group_7", "Memory" : "400", "Tests" : [ { "Name" : "PMD ring autotest", "Command" : "ring_pmd_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Access list control autotest", "Command" : "acl_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" :"Sched autotest", "Command" : "sched_autotest", "Func" :default_autotest, "Report" :None, }, ] }, ] # tests that should not be run when any other tests are running non_parallel_test_group_list = [ { "Prefix" : "kni", "Memory" : "512", "Tests" : [ { "Name" : "KNI autotest", "Command" : "kni_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "mempool_perf", "Memory" : per_sockets(256), "Tests" : [ { "Name" : "Cycles autotest", "Command" : "cycles_autotest", "Func" : default_autotest, "Report" : None, }, { "Name" : "Mempool performance autotest", "Command" : "mempool_perf_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "memcpy_perf", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Memcpy performance autotest", "Command" : "memcpy_perf_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "hash_perf", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Hash performance autotest", "Command" : "hash_perf_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix" : "power", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Power autotest", "Command" : "power_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix" : "power_acpi_cpufreq", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Power ACPI cpufreq autotest", "Command" : "power_acpi_cpufreq_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix" : "power_kvm_vm", "Memory" : "512", "Tests" : [ { "Name" : "Power KVM VM autotest", "Command" : "power_kvm_vm_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix" : "lpm6", "Memory" : "512", "Tests" : [ { "Name" : "LPM6 autotest", "Command" : "lpm6_autotest", "Func" : default_autotest, "Report" : None, }, ] }, { "Prefix": "timer_perf", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Timer performance autotest", "Command" : "timer_perf_autotest", "Func" : default_autotest, "Report" : None, }, ] }, # # Please always make sure that ring_perf is the last test! # { "Prefix": "ring_perf", "Memory" : per_sockets(512), "Tests" : [ { "Name" : "Ring performance autotest", "Command" : "ring_perf_autotest", "Func" : default_autotest, "Report" : None, }, ] }, ] ================================================ FILE: app/test/autotest_runner.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # The main logic behind running autotests in parallel import multiprocessing, sys, pexpect, time, os, StringIO, csv # wait for prompt def wait_prompt(child): try: child.sendline() result = child.expect(["RTE>>", pexpect.TIMEOUT, pexpect.EOF], timeout = 120) except: return False if result == 0: return True else: return False # run a test group # each result tuple in results list consists of: # result value (0 or -1) # result string # test name # total test run time (double) # raw test log # test report (if not available, should be None) # # this function needs to be outside AutotestRunner class # because otherwise Pool won't work (or rather it will require # quite a bit of effort to make it work). def run_test_group(cmdline, test_group): results = [] child = None start_time = time.time() startuplog = None # run test app try: # prepare logging of init startuplog = StringIO.StringIO() print >>startuplog, "\n%s %s\n" % ("="*20, test_group["Prefix"]) child = pexpect.spawn(cmdline, logfile=startuplog) # wait for target to boot if not wait_prompt(child): child.close() results.append((-1, "Fail [No prompt]", "Start %s" % test_group["Prefix"], time.time() - start_time, startuplog.getvalue(), None)) # mark all tests as failed for test in test_group["Tests"]: results.append((-1, "Fail [No prompt]", test["Name"], time.time() - start_time, "", None)) # exit test return results except: results.append((-1, "Fail [Can't run]", "Start %s" % test_group["Prefix"], time.time() - start_time, startuplog.getvalue(), None)) # mark all tests as failed for t in test_group["Tests"]: results.append((-1, "Fail [Can't run]", t["Name"], time.time() - start_time, "", None)) # exit test return results # startup was successful results.append((0, "Success", "Start %s" % test_group["Prefix"], time.time() - start_time, startuplog.getvalue(), None)) # run all tests in test group for test in test_group["Tests"]: # create log buffer for each test # in multiprocessing environment, the logging would be # interleaved and will create a mess, hence the buffering logfile = StringIO.StringIO() child.logfile = logfile result = () # make a note when the test started start_time = time.time() try: # print test name to log buffer print >>logfile, "\n%s %s\n" % ("-"*20, test["Name"]) # run test function associated with the test result = test["Func"](child, test["Command"]) # make a note when the test was finished end_time = time.time() # append test data to the result tuple result += (test["Name"], end_time - start_time, logfile.getvalue()) # call report function, if any defined, and supply it with # target and complete log for test run if test["Report"]: report = test["Report"](self.target, log) # append report to results tuple result += (report,) else: # report is None result += (None,) except: # make a note when the test crashed end_time = time.time() # mark test as failed result = (-1, "Fail [Crash]", test["Name"], end_time - start_time, logfile.getvalue(), None) finally: # append the results to the results list results.append(result) # regardless of whether test has crashed, try quitting it try: child.sendline("quit") child.close() # if the test crashed, just do nothing instead except: # nop pass # return test results return results # class representing an instance of autotests run class AutotestRunner: cmdline = "" parallel_test_groups = [] non_parallel_test_groups = [] logfile = None csvwriter = None target = "" start = None n_tests = 0 fails = 0 log_buffers = [] blacklist = [] whitelist = [] def __init__(self, cmdline, target, blacklist, whitelist): self.cmdline = cmdline self.target = target self.blacklist = blacklist self.whitelist = whitelist # log file filename logfile = "%s.log" % target csvfile = "%s.csv" % target self.logfile = open(logfile, "w") csvfile = open(csvfile, "w") self.csvwriter = csv.writer(csvfile) # prepare results table self.csvwriter.writerow(["test_name","test_result","result_str"]) # set up cmdline string def __get_cmdline(self, test): cmdline = self.cmdline # append memory limitations for each test # otherwise tests won't run in parallel if not "i686" in self.target: cmdline += " --socket-mem=%s"% test["Memory"] else: # affinitize startup so that tests don't fail on i686 cmdline = "taskset 1 " + cmdline cmdline += " -m " + str(sum(map(int,test["Memory"].split(",")))) # set group prefix for autotest group # otherwise they won't run in parallel cmdline += " --file-prefix=%s"% test["Prefix"] return cmdline def add_parallel_test_group(self,test_group): self.parallel_test_groups.append(test_group) def add_non_parallel_test_group(self,test_group): self.non_parallel_test_groups.append(test_group) def __process_results(self, results): # this iterates over individual test results for i, result in enumerate(results): # increase total number of tests that were run # do not include "start" test if i > 0: self.n_tests += 1 # unpack result tuple test_result, result_str, test_name, \ test_time, log, report = result # get total run time cur_time = time.time() total_time = int(cur_time - self.start) # print results, test run time and total time since start print ("%s:" % test_name).ljust(30), print result_str.ljust(29), print "[%02dm %02ds]" % (test_time / 60, test_time % 60), # don't print out total time every line, it's the same anyway if i == len(results) - 1: print "[%02dm %02ds]" % (total_time / 60, total_time % 60) else: print "" # if test failed and it wasn't a "start" test if test_result < 0 and not i == 0: self.fails += 1 # collect logs self.log_buffers.append(log) # create report if it exists if report: try: f = open("%s_%s_report.rst" % (self.target,test_name), "w") except IOError: print "Report for %s could not be created!" % test_name else: with f: f.write(report) # write test result to CSV file if i != 0: self.csvwriter.writerow([test_name, test_result, result_str]) # this function iterates over test groups and removes each # test that is not in whitelist/blacklist def __filter_groups(self, test_groups): groups_to_remove = [] # filter out tests from parallel test groups for i, test_group in enumerate(test_groups): # iterate over a copy so that we could safely delete individual tests for test in test_group["Tests"][:]: test_id = test["Command"] # dump tests are specified in full e.g. "Dump_mempool" if "_autotest" in test_id: test_id = test_id[:-len("_autotest")] # filter out blacklisted/whitelisted tests if self.blacklist and test_id in self.blacklist: test_group["Tests"].remove(test) continue if self.whitelist and test_id not in self.whitelist: test_group["Tests"].remove(test) continue # modify or remove original group if len(test_group["Tests"]) > 0: test_groups[i] = test_group else: # remember which groups should be deleted # put the numbers backwards so that we start # deleting from the end, not from the beginning groups_to_remove.insert(0, i) # remove test groups that need to be removed for i in groups_to_remove: del test_groups[i] return test_groups # iterate over test groups and run tests associated with them def run_all_tests(self): # filter groups self.parallel_test_groups = \ self.__filter_groups(self.parallel_test_groups) self.non_parallel_test_groups = \ self.__filter_groups(self.non_parallel_test_groups) # create a pool of worker threads pool = multiprocessing.Pool(processes=1) results = [] # whatever happens, try to save as much logs as possible try: # create table header print "" print "Test name".ljust(30), print "Test result".ljust(29), print "Test".center(9), print "Total".center(9) print "=" * 80 # make a note of tests start time self.start = time.time() # assign worker threads to run test groups for test_group in self.parallel_test_groups: result = pool.apply_async(run_test_group, [self.__get_cmdline(test_group), test_group]) results.append(result) # iterate while we have group execution results to get while len(results) > 0: # iterate over a copy to be able to safely delete results # this iterates over a list of group results for group_result in results[:]: # if the thread hasn't finished yet, continue if not group_result.ready(): continue res = group_result.get() self.__process_results(res) # remove result from results list once we're done with it results.remove(group_result) # run non_parallel tests. they are run one by one, synchronously for test_group in self.non_parallel_test_groups: group_result = run_test_group(self.__get_cmdline(test_group), test_group) self.__process_results(group_result) # get total run time cur_time = time.time() total_time = int(cur_time - self.start) # print out summary print "=" * 80 print "Total run time: %02dm %02ds" % (total_time / 60, total_time % 60) if self.fails != 0: print "Number of failed tests: %s" % str(self.fails) # write summary to logfile self.logfile.write("Summary\n") self.logfile.write("Target: ".ljust(15) + "%s\n" % self.target) self.logfile.write("Tests: ".ljust(15) + "%i\n" % self.n_tests) self.logfile.write("Failed tests: ".ljust(15) + "%i\n" % self.fails) except: print "Exception occured" print sys.exc_info() self.fails = 1 # drop logs from all executions to a logfile for buf in self.log_buffers: self.logfile.write(buf.replace("\r","")) log_buffers = [] return self.fails ================================================ FILE: app/test/autotest_test_funcs.py ================================================ #!/usr/bin/python # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Test functions import sys, pexpect, time, os, re # default autotest, used to run most tests # waits for "Test OK" def default_autotest(child, test_name): child.sendline(test_name) result = child.expect(["Test OK", "Test Failed", "Command not found", pexpect.TIMEOUT], timeout = 900) if result == 1: return -1, "Fail" elif result == 2: return -1, "Fail [Not found]" elif result == 3: return -1, "Fail [Timeout]" return 0, "Success" # autotest used to run dump commands # just fires the command def dump_autotest(child, test_name): child.sendline(test_name) return 0, "Success" # memory autotest # reads output and waits for Test OK def memory_autotest(child, test_name): child.sendline(test_name) regexp = "phys:0x[0-9a-f]*, len:([0-9]*), virt:0x[0-9a-f]*, socket_id:[0-9]*" index = child.expect([regexp, pexpect.TIMEOUT], timeout = 180) if index != 0: return -1, "Fail [Timeout]" size = int(child.match.groups()[0], 16) if size <= 0: return -1, "Fail [Bad size]" index = child.expect(["Test OK", "Test Failed", pexpect.TIMEOUT], timeout = 10) if index == 1: return -1, "Fail" elif index == 2: return -1, "Fail [Timeout]" return 0, "Success" def spinlock_autotest(child, test_name): i = 0 ir = 0 child.sendline(test_name) while True: index = child.expect(["Test OK", "Test Failed", "Hello from core ([0-9]*) !", "Hello from within recursive locks from ([0-9]*) !", pexpect.TIMEOUT], timeout = 20) # ok if index == 0: break # message, check ordering elif index == 2: if int(child.match.groups()[0]) < i: return -1, "Fail [Bad order]" i = int(child.match.groups()[0]) elif index == 3: if int(child.match.groups()[0]) < ir: return -1, "Fail [Bad order]" ir = int(child.match.groups()[0]) # fail elif index == 4: return -1, "Fail [Timeout]" elif index == 1: return -1, "Fail" return 0, "Success" def rwlock_autotest(child, test_name): i = 0 child.sendline(test_name) while True: index = child.expect(["Test OK", "Test Failed", "Hello from core ([0-9]*) !", "Global write lock taken on master core ([0-9]*)", pexpect.TIMEOUT], timeout = 10) # ok if index == 0: if i != 0xffff: return -1, "Fail [Message is missing]" break # message, check ordering elif index == 2: if int(child.match.groups()[0]) < i: return -1, "Fail [Bad order]" i = int(child.match.groups()[0]) # must be the last message, check ordering elif index == 3: i = 0xffff elif index == 4: return -1, "Fail [Timeout]" # fail else: return -1, "Fail" return 0, "Success" def logs_autotest(child, test_name): i = 0 child.sendline(test_name) log_list = [ "TESTAPP1: this is a debug level message", "TESTAPP1: this is a info level message", "TESTAPP1: this is a warning level message", "TESTAPP2: this is a info level message", "TESTAPP2: this is a warning level message", "TESTAPP1: this is a debug level message", "TESTAPP1: this is a debug level message", "TESTAPP1: this is a info level message", "TESTAPP1: this is a warning level message", "TESTAPP2: this is a info level message", "TESTAPP2: this is a warning level message", "TESTAPP1: this is a debug level message", ] for log_msg in log_list: index = child.expect([log_msg, "Test OK", "Test Failed", pexpect.TIMEOUT], timeout = 10) if index == 3: return -1, "Fail [Timeout]" # not ok elif index != 0: return -1, "Fail" index = child.expect(["Test OK", "Test Failed", pexpect.TIMEOUT], timeout = 10) return 0, "Success" def timer_autotest(child, test_name): i = 0 child.sendline(test_name) index = child.expect(["Start timer stress tests \(20 seconds\)", "Test Failed", pexpect.TIMEOUT], timeout = 10) if index == 1: return -1, "Fail" elif index == 2: return -1, "Fail [Timeout]" index = child.expect(["Start timer stress tests 2", "Test Failed", pexpect.TIMEOUT], timeout = 40) if index == 1: return -1, "Fail" elif index == 2: return -1, "Fail [Timeout]" index = child.expect(["Start timer basic tests \(20 seconds\)", "Test Failed", pexpect.TIMEOUT], timeout = 20) if index == 1: return -1, "Fail" elif index == 2: return -1, "Fail [Timeout]" prev_lcore_timer1 = -1 lcore_tim0 = -1 lcore_tim1 = -1 lcore_tim2 = -1 lcore_tim3 = -1 while True: index = child.expect(["TESTTIMER: ([0-9]*): callback id=([0-9]*) count=([0-9]*) on core ([0-9]*)", "Test OK", "Test Failed", pexpect.TIMEOUT], timeout = 10) if index == 1: break if index == 2: return -1, "Fail" elif index == 3: return -1, "Fail [Timeout]" try: t = int(child.match.groups()[0]) id = int(child.match.groups()[1]) cnt = int(child.match.groups()[2]) lcore = int(child.match.groups()[3]) except: return -1, "Fail [Cannot parse]" # timer0 always expires on the same core when cnt < 20 if id == 0: if lcore_tim0 == -1: lcore_tim0 = lcore elif lcore != lcore_tim0 and cnt < 20: return -1, "Fail [lcore != lcore_tim0 (%d, %d)]"%(lcore, lcore_tim0) if cnt > 21: return -1, "Fail [tim0 cnt > 21]" # timer1 each time expires on a different core if id == 1: if lcore == lcore_tim1: return -1, "Fail [lcore == lcore_tim1 (%d, %d)]"%(lcore, lcore_tim1) lcore_tim1 = lcore if cnt > 10: return -1, "Fail [tim1 cnt > 30]" # timer0 always expires on the same core if id == 2: if lcore_tim2 == -1: lcore_tim2 = lcore elif lcore != lcore_tim2: return -1, "Fail [lcore != lcore_tim2 (%d, %d)]"%(lcore, lcore_tim2) if cnt > 30: return -1, "Fail [tim2 cnt > 30]" # timer0 always expires on the same core if id == 3: if lcore_tim3 == -1: lcore_tim3 = lcore elif lcore != lcore_tim3: return -1, "Fail [lcore_tim3 changed (%d -> %d)]"%(lcore, lcore_tim3) if cnt > 30: return -1, "Fail [tim3 cnt > 30]" # must be 2 different cores if lcore_tim0 == lcore_tim3: return -1, "Fail [lcore_tim0 (%d) == lcore_tim3 (%d)]"%(lcore_tim0, lcore_tim3) return 0, "Success" def ring_autotest(child, test_name): child.sendline(test_name) index = child.expect(["Test OK", "Test Failed", pexpect.TIMEOUT], timeout = 15) if index == 1: return -1, "Fail" elif index == 2: return -1, "Fail [Timeout]" child.sendline("set_watermark test 100") child.sendline("dump_ring test") index = child.expect([" watermark=100", pexpect.TIMEOUT], timeout = 1) if index != 0: return -1, "Fail [Bad watermark]" return 0, "Success" ================================================ FILE: app/test/commands.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #ifndef __linux__ #ifndef __FreeBSD__ #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /****************/ static struct test_commands_list commands_list = TAILQ_HEAD_INITIALIZER(commands_list); void add_test_command(struct test_command *t) { TAILQ_INSERT_TAIL(&commands_list, t, next); } struct cmd_autotest_result { cmdline_fixed_string_t autotest; }; static void cmd_autotest_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct test_command *t; struct cmd_autotest_result *res = parsed_result; int ret = 0; TAILQ_FOREACH(t, &commands_list, next) { if (!strcmp(res->autotest, t->command)) ret = t->callback(); } if (ret == 0) printf("Test OK\n"); else printf("Test Failed\n"); fflush(stdout); } cmdline_parse_token_string_t cmd_autotest_autotest = TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest, ""); cmdline_parse_inst_t cmd_autotest = { .f = cmd_autotest_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "launch autotest", .tokens = { /* token list, NULL terminated */ (void *)&cmd_autotest_autotest, NULL, }, }; /****************/ struct cmd_dump_result { cmdline_fixed_string_t dump; }; static void dump_struct_sizes(void) { #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t)); DUMP_SIZE(struct rte_mbuf); DUMP_SIZE(struct rte_mempool); DUMP_SIZE(struct rte_ring); #undef DUMP_SIZE } static void cmd_dump_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_dump_result *res = parsed_result; if (!strcmp(res->dump, "dump_physmem")) rte_dump_physmem_layout(stdout); else if (!strcmp(res->dump, "dump_memzone")) rte_memzone_dump(stdout); else if (!strcmp(res->dump, "dump_log_history")) rte_log_dump_history(stdout); else if (!strcmp(res->dump, "dump_struct_sizes")) dump_struct_sizes(); else if (!strcmp(res->dump, "dump_ring")) rte_ring_list_dump(stdout); else if (!strcmp(res->dump, "dump_mempool")) rte_mempool_list_dump(stdout); else if (!strcmp(res->dump, "dump_devargs")) rte_eal_devargs_dump(stdout); } cmdline_parse_token_string_t cmd_dump_dump = TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, "dump_physmem#dump_memzone#dump_log_history#" "dump_struct_sizes#dump_ring#dump_mempool#" "dump_devargs"); cmdline_parse_inst_t cmd_dump = { .f = cmd_dump_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "dump status", .tokens = { /* token list, NULL terminated */ (void *)&cmd_dump_dump, NULL, }, }; /****************/ struct cmd_dump_one_result { cmdline_fixed_string_t dump; cmdline_fixed_string_t name; }; static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_dump_one_result *res = parsed_result; if (!strcmp(res->dump, "dump_ring")) { struct rte_ring *r; r = rte_ring_lookup(res->name); if (r == NULL) { cmdline_printf(cl, "Cannot find ring\n"); return; } rte_ring_dump(stdout, r); } else if (!strcmp(res->dump, "dump_mempool")) { struct rte_mempool *mp; mp = rte_mempool_lookup(res->name); if (mp == NULL) { cmdline_printf(cl, "Cannot find mempool\n"); return; } rte_mempool_dump(stdout, mp); } } cmdline_parse_token_string_t cmd_dump_one_dump = TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump, "dump_ring#dump_mempool"); cmdline_parse_token_string_t cmd_dump_one_name = TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL); cmdline_parse_inst_t cmd_dump_one = { .f = cmd_dump_one_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "dump one ring/mempool: dump_ring|dump_mempool ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_dump_one_dump, (void *)&cmd_dump_one_name, NULL, }, }; /****************/ struct cmd_set_ring_result { cmdline_fixed_string_t set; cmdline_fixed_string_t name; uint32_t value; }; static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_ring_result *res = parsed_result; struct rte_ring *r; int ret; r = rte_ring_lookup(res->name); if (r == NULL) { cmdline_printf(cl, "Cannot find ring\n"); return; } if (!strcmp(res->set, "set_watermark")) { ret = rte_ring_set_water_mark(r, res->value); if (ret != 0) cmdline_printf(cl, "Cannot set water mark\n"); } } cmdline_parse_token_string_t cmd_set_ring_set = TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set, "set_watermark"); cmdline_parse_token_string_t cmd_set_ring_name = TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL); cmdline_parse_token_num_t cmd_set_ring_value = TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32); cmdline_parse_inst_t cmd_set_ring = { .f = cmd_set_ring_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "set watermark: " "set_watermark ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_set_ring_set, (void *)&cmd_set_ring_name, (void *)&cmd_set_ring_value, NULL, }, }; /****************/ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "exit application", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_quit, NULL, }, }; /****************/ struct cmd_set_rxtx_result { cmdline_fixed_string_t set; cmdline_fixed_string_t mode; }; static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_rxtx_result *res = parsed_result; if (test_set_rxtx_conf(res->mode) < 0) cmdline_printf(cl, "Cannot find such mode\n"); } cmdline_parse_token_string_t cmd_set_rxtx_set = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set, "set_rxtx_mode"); cmdline_parse_token_string_t cmd_set_rxtx_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL); cmdline_parse_inst_t cmd_set_rxtx = { .f = cmd_set_rxtx_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "set rxtx routine: " "set_rxtx ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_set_rxtx_set, (void *)&cmd_set_rxtx_mode, NULL, }, }; /****************/ struct cmd_set_rxtx_anchor { cmdline_fixed_string_t set; cmdline_fixed_string_t type; }; static void cmd_set_rxtx_anchor_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_rxtx_anchor *res = parsed_result; if (test_set_rxtx_anchor(res->type) < 0) cmdline_printf(cl, "Cannot find such anchor\n"); } cmdline_parse_token_string_t cmd_set_rxtx_anchor_set = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set, "set_rxtx_anchor"); cmdline_parse_token_string_t cmd_set_rxtx_anchor_type = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL); cmdline_parse_inst_t cmd_set_rxtx_anchor = { .f = cmd_set_rxtx_anchor_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "set rxtx anchor: " "set_rxtx_anchor ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_set_rxtx_anchor_set, (void *)&cmd_set_rxtx_anchor_type, NULL, }, }; /****************/ /* for stream control */ struct cmd_set_rxtx_sc { cmdline_fixed_string_t set; cmdline_fixed_string_t type; }; static void cmd_set_rxtx_sc_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_rxtx_sc *res = parsed_result; if (test_set_rxtx_sc(res->type) < 0) cmdline_printf(cl, "Cannot find such stream control\n"); } cmdline_parse_token_string_t cmd_set_rxtx_sc_set = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set, "set_rxtx_sc"); cmdline_parse_token_string_t cmd_set_rxtx_sc_type = TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL); cmdline_parse_inst_t cmd_set_rxtx_sc = { .f = cmd_set_rxtx_sc_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "set rxtx stream control: " "set_rxtx_sc ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_set_rxtx_sc_set, (void *)&cmd_set_rxtx_sc_type, NULL, }, }; /****************/ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_autotest, (cmdline_parse_inst_t *)&cmd_dump, (cmdline_parse_inst_t *)&cmd_dump_one, (cmdline_parse_inst_t *)&cmd_set_ring, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_set_rxtx, (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor, (cmdline_parse_inst_t *)&cmd_set_rxtx_sc, NULL, }; int commands_init(void) { struct test_command *t; char *commands, *ptr; int commands_len = 0; TAILQ_FOREACH(t, &commands_list, next) { commands_len += strlen(t->command) + 1; } commands = malloc(commands_len); if (!commands) return -1; ptr = commands; TAILQ_FOREACH(t, &commands_list, next) { ptr += sprintf(ptr, "%s#", t->command); } ptr--; ptr[0] = '\0'; cmd_autotest_autotest.string_data.str = commands; return 0; } ================================================ FILE: app/test/packet_burst_generator.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "packet_burst_generator.h" #define UDP_SRC_PORT 1024 #define UDP_DST_PORT 1024 #define IP_DEFTTL 64 /* from RFC 1340. */ #define IP_VERSION 0x40 #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) static void copy_buf_to_pkt_segs(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset) { struct rte_mbuf *seg; void *seg_buf; unsigned copy_len; seg = pkt; while (offset >= seg->data_len) { offset -= seg->data_len; seg = seg->next; } copy_len = seg->data_len - offset; seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset); while (len > copy_len) { rte_memcpy(seg_buf, buf, (size_t) copy_len); len -= copy_len; buf = ((char *) buf + copy_len); seg = seg->next; seg_buf = rte_pktmbuf_mtod(seg, void *); } rte_memcpy(seg_buf, buf, (size_t) len); } static inline void copy_buf_to_pkt(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset) { if (offset + len <= pkt->data_len) { rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset), buf, (size_t) len); return; } copy_buf_to_pkt_segs(buf, len, pkt, offset); } void initialize_eth_header(struct ether_hdr *eth_hdr, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t ether_type, uint8_t vlan_enabled, uint16_t van_id) { ether_addr_copy(dst_mac, ð_hdr->d_addr); ether_addr_copy(src_mac, ð_hdr->s_addr); if (vlan_enabled) { struct vlan_hdr *vhdr = (struct vlan_hdr *)((uint8_t *)eth_hdr + sizeof(struct ether_hdr)); eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vhdr->eth_proto = rte_cpu_to_be_16(ether_type); vhdr->vlan_tci = van_id; } else { eth_hdr->ether_type = rte_cpu_to_be_16(ether_type); } } void initialize_arp_header(struct arp_hdr *arp_hdr, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint32_t src_ip, uint32_t dst_ip, uint32_t opcode) { arp_hdr->arp_hrd = rte_cpu_to_be_16(ARP_HRD_ETHER); arp_hdr->arp_pro = rte_cpu_to_be_16(ETHER_TYPE_IPv4); arp_hdr->arp_hln = ETHER_ADDR_LEN; arp_hdr->arp_pln = sizeof(uint32_t); arp_hdr->arp_op = rte_cpu_to_be_16(opcode); ether_addr_copy(src_mac, &arp_hdr->arp_data.arp_sha); arp_hdr->arp_data.arp_sip = src_ip; ether_addr_copy(dst_mac, &arp_hdr->arp_data.arp_tha); arp_hdr->arp_data.arp_tip = dst_ip; } uint16_t initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port, uint16_t dst_port, uint16_t pkt_data_len) { uint16_t pkt_len; pkt_len = (uint16_t) (pkt_data_len + sizeof(struct udp_hdr)); udp_hdr->src_port = rte_cpu_to_be_16(src_port); udp_hdr->dst_port = rte_cpu_to_be_16(dst_port); udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len); udp_hdr->dgram_cksum = 0; /* No UDP checksum. */ return pkt_len; } uint16_t initialize_ipv6_header(struct ipv6_hdr *ip_hdr, uint8_t *src_addr, uint8_t *dst_addr, uint16_t pkt_data_len) { ip_hdr->vtc_flow = 0; ip_hdr->payload_len = pkt_data_len; ip_hdr->proto = IPPROTO_UDP; ip_hdr->hop_limits = IP_DEFTTL; rte_memcpy(ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr)); rte_memcpy(ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr)); return (uint16_t) (pkt_data_len + sizeof(struct ipv6_hdr)); } uint16_t initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr, uint32_t dst_addr, uint16_t pkt_data_len) { uint16_t pkt_len; unaligned_uint16_t *ptr16; uint32_t ip_cksum; /* * Initialize IP header. */ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct ipv4_hdr)); ip_hdr->version_ihl = IP_VHL_DEF; ip_hdr->type_of_service = 0; ip_hdr->fragment_offset = 0; ip_hdr->time_to_live = IP_DEFTTL; ip_hdr->next_proto_id = IPPROTO_UDP; ip_hdr->packet_id = 0; ip_hdr->total_length = rte_cpu_to_be_16(pkt_len); ip_hdr->src_addr = rte_cpu_to_be_32(src_addr); ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr); /* * Compute IP header checksum. */ ptr16 = (unaligned_uint16_t *)ip_hdr; ip_cksum = 0; ip_cksum += ptr16[0]; ip_cksum += ptr16[1]; ip_cksum += ptr16[2]; ip_cksum += ptr16[3]; ip_cksum += ptr16[4]; ip_cksum += ptr16[6]; ip_cksum += ptr16[7]; ip_cksum += ptr16[8]; ip_cksum += ptr16[9]; /* * Reduce 32 bit checksum to 16 bits and complement it. */ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) + (ip_cksum & 0x0000FFFF); ip_cksum %= 65536; ip_cksum = (~ip_cksum) & 0x0000FFFF; if (ip_cksum == 0) ip_cksum = 0xFFFF; ip_hdr->hdr_checksum = (uint16_t) ip_cksum; return pkt_len; } /* * The maximum number of segments per packet is used when creating * scattered transmit packets composed of a list of mbufs. */ #define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */ int generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst, struct ether_hdr *eth_hdr, uint8_t vlan_enabled, void *ip_hdr, uint8_t ipv4, struct udp_hdr *udp_hdr, int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs) { int i, nb_pkt = 0; size_t eth_hdr_size; struct rte_mbuf *pkt_seg; struct rte_mbuf *pkt; for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) { pkt = rte_pktmbuf_alloc(mp); if (pkt == NULL) { nomore_mbuf: if (nb_pkt == 0) return -1; break; } pkt->data_len = pkt_len; pkt_seg = pkt; for (i = 1; i < nb_pkt_segs; i++) { pkt_seg->next = rte_pktmbuf_alloc(mp); if (pkt_seg->next == NULL) { pkt->nb_segs = i; rte_pktmbuf_free(pkt); goto nomore_mbuf; } pkt_seg = pkt_seg->next; pkt_seg->data_len = pkt_len; } pkt_seg->next = NULL; /* Last segment of packet. */ /* * Copy headers in first packet segment(s). */ if (vlan_enabled) eth_hdr_size = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr); else eth_hdr_size = sizeof(struct ether_hdr); copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0); if (ipv4) { copy_buf_to_pkt(ip_hdr, sizeof(struct ipv4_hdr), pkt, eth_hdr_size); copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt, eth_hdr_size + sizeof(struct ipv4_hdr)); } else { copy_buf_to_pkt(ip_hdr, sizeof(struct ipv6_hdr), pkt, eth_hdr_size); copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt, eth_hdr_size + sizeof(struct ipv6_hdr)); } /* * Complete first mbuf of packet and append it to the * burst of packets to be transmitted. */ pkt->nb_segs = nb_pkt_segs; pkt->pkt_len = pkt_len; pkt->l2_len = eth_hdr_size; if (ipv4) { pkt->vlan_tci = ETHER_TYPE_IPv4; pkt->l3_len = sizeof(struct ipv4_hdr); #ifndef RTE_NEXT_ABI if (vlan_enabled) pkt->ol_flags = PKT_RX_IPV4_HDR | PKT_RX_VLAN_PKT; else pkt->ol_flags = PKT_RX_IPV4_HDR; #endif } else { pkt->vlan_tci = ETHER_TYPE_IPv6; pkt->l3_len = sizeof(struct ipv6_hdr); #ifndef RTE_NEXT_ABI if (vlan_enabled) pkt->ol_flags = PKT_RX_IPV6_HDR | PKT_RX_VLAN_PKT; else pkt->ol_flags = PKT_RX_IPV6_HDR; #endif } pkts_burst[nb_pkt] = pkt; } return nb_pkt; } ================================================ FILE: app/test/packet_burst_generator.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef PACKET_BURST_GENERATOR_H_ #define PACKET_BURST_GENERATOR_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #define IPV4_ADDR(a, b, c, d)(((a & 0xff) << 24) | ((b & 0xff) << 16) | \ ((c & 0xff) << 8) | (d & 0xff)) #define PACKET_BURST_GEN_PKT_LEN 60 #define PACKET_BURST_GEN_PKT_LEN_128 128 void initialize_eth_header(struct ether_hdr *eth_hdr, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t ether_type, uint8_t vlan_enabled, uint16_t van_id); void initialize_arp_header(struct arp_hdr *arp_hdr, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint32_t src_ip, uint32_t dst_ip, uint32_t opcode); uint16_t initialize_udp_header(struct udp_hdr *udp_hdr, uint16_t src_port, uint16_t dst_port, uint16_t pkt_data_len); uint16_t initialize_ipv6_header(struct ipv6_hdr *ip_hdr, uint8_t *src_addr, uint8_t *dst_addr, uint16_t pkt_data_len); uint16_t initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr, uint32_t dst_addr, uint16_t pkt_data_len); int generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst, struct ether_hdr *eth_hdr, uint8_t vlan_enabled, void *ip_hdr, uint8_t ipv4, struct udp_hdr *udp_hdr, int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs); #ifdef __cplusplus } #endif #endif /* PACKET_BURST_GENERATOR_H_ */ ================================================ FILE: app/test/process.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PROCESS_H_ #define _PROCESS_H_ #ifdef RTE_EXEC_ENV_BSDAPP #define self "curproc" #define exe "file" #else #define self "self" #define exe "exe" #endif /* * launches a second copy of the test process using the given argv parameters, * which should include argv[0] as the process name. To identify in the * subprocess the source of the call, the env_value parameter is set in the * environment as $RTE_TEST */ static inline int process_dup(const char *const argv[], int numargs, const char *env_value) { int num; #ifdef RTE_LIBRTE_XEN_DOM0 char *argv_cpy[numargs + 2]; #else char *argv_cpy[numargs + 1]; #endif int i, fd, status; char path[32]; pid_t pid = fork(); if (pid < 0) return -1; else if (pid == 0) { /* make a copy of the arguments to be passed to exec */ for (i = 0; i < numargs; i++) argv_cpy[i] = strdup(argv[i]); #ifdef RTE_LIBRTE_XEN_DOM0 argv_cpy[i] = strdup("--xen-dom0"); argv_cpy[i + 1] = NULL; num = numargs + 1; #else argv_cpy[i] = NULL; num = numargs; #endif /* close all open file descriptors, check /proc/self/fd to only * call close on open fds. Exclude fds 0, 1 and 2*/ for (fd = getdtablesize(); fd > 2; fd-- ) { snprintf(path, sizeof(path), "/proc/" exe "/fd/%d", fd); if (access(path, F_OK) == 0) close(fd); } printf("Running binary with argv[]:"); for (i = 0; i < num; i++) printf("'%s' ", argv_cpy[i]); printf("\n"); /* set the environment variable */ if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0) rte_panic("Cannot export environment variable\n"); if (execv("/proc/" self "/" exe, argv_cpy) < 0) rte_panic("Cannot exec\n"); } /* parent process does a wait */ while (wait(&status) != pid) ; return status; } #endif /* _PROCESS_H_ */ ================================================ FILE: app/test/test.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_CMDLINE #include #include #include #include extern cmdline_parse_ctx_t main_ctx[]; #endif #include #include #include #include #include #include #ifdef RTE_LIBRTE_TIMER #include #endif #include "test.h" #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 const char *prgname; /* to be set to argv[0] */ static const char *recursive_call; /* used in linuxapp for MP and other tests */ static int no_action(void){ return 0; } static int do_recursive_call(void) { unsigned i; struct { const char *env_var; int (*action_fn)(void); } actions[] = { { "run_secondary_instances", test_mp_secondary }, { "test_missing_c_flag", no_action }, { "test_master_lcore_flag", no_action }, { "test_missing_n_flag", no_action }, { "test_no_hpet_flag", no_action }, { "test_whitelist_flag", no_action }, { "test_invalid_b_flag", no_action }, { "test_invalid_vdev_flag", no_action }, { "test_invalid_r_flag", no_action }, #ifdef RTE_LIBRTE_XEN_DOM0 { "test_dom0_misc_flags", no_action }, #else { "test_misc_flags", no_action }, #endif { "test_memory_flags", no_action }, { "test_file_prefix", no_action }, { "test_no_huge_flag", no_action }, #ifdef RTE_LIBRTE_IVSHMEM { "test_ivshmem", test_ivshmem }, #endif }; if (recursive_call == NULL) return -1; for (i = 0; i < sizeof(actions)/sizeof(actions[0]); i++) { if (strcmp(actions[i].env_var, recursive_call) == 0) return (actions[i].action_fn)(); } printf("ERROR - missing action to take for %s\n", recursive_call); return -1; } int main(int argc, char **argv) { #ifdef RTE_LIBRTE_CMDLINE struct cmdline *cl; #endif int ret; ret = rte_eal_init(argc, argv); if (ret < 0) return -1; #ifdef RTE_LIBRTE_TIMER rte_timer_subsystem_init(); #endif if (commands_init() < 0) return -1; argv += ret; prgname = argv[0]; if ((recursive_call = getenv(RECURSIVE_ENV_VAR)) != NULL) return do_recursive_call(); #ifdef RTE_LIBEAL_USE_HPET if (rte_eal_hpet_init(1) < 0) #endif RTE_LOG(INFO, APP, "HPET is not enabled, using TSC as default timer\n"); #ifdef RTE_LIBRTE_CMDLINE cl = cmdline_stdin_new(main_ctx, "RTE>>"); if (cl == NULL) { return -1; } cmdline_interact(cl); cmdline_stdin_exit(cl); #endif return 0; } int unit_test_suite_runner(struct unit_test_suite *suite) { int retval, i = 0; if (suite->suite_name) printf("Test Suite : %s\n", suite->suite_name); if (suite->setup) if (suite->setup() != 0) return -1; while (suite->unit_test_cases[i].testcase) { /* Run test case setup */ if (suite->unit_test_cases[i].setup) { retval = suite->unit_test_cases[i].setup(); if (retval != 0) return retval; } /* Run test case */ if (suite->unit_test_cases[i].testcase() == 0) { printf("TestCase %2d: %s\n", i, suite->unit_test_cases[i].success_msg ? suite->unit_test_cases[i].success_msg : "passed"); } else { printf("TestCase %2d: %s\n", i, suite->unit_test_cases[i].fail_msg ? suite->unit_test_cases[i].fail_msg : "failed"); return -1; } /* Run test case teardown */ if (suite->unit_test_cases[i].teardown) { retval = suite->unit_test_cases[i].teardown(); if (retval != 0) return retval; } i++; } /* Run test suite teardown */ if (suite->teardown) if (suite->teardown() != 0) return -1; return 0; } ================================================ FILE: app/test/test.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _TEST_H_ #define _TEST_H_ #include #define TEST_SUCCESS (0) #define TEST_FAILED (-1) /* Before including test.h file you can define * TEST_TRACE_FAILURE(_file, _line, _func) macro to better trace/debug test * failures. Mostly useful in test development phase. */ #ifndef TEST_TRACE_FAILURE # define TEST_TRACE_FAILURE(_file, _line, _func) #endif #define TEST_ASSERT(cond, msg, ...) do { \ if (!(cond)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_EQUAL(a, b, msg, ...) do { \ if (!(a == b)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_NOT_EQUAL(a, b, msg, ...) do { \ if (!(a != b)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_SUCCESS(val, msg, ...) do { \ typeof(val) _val = (val); \ if (!(_val == 0)) { \ printf("TestCase %s() line %d failed (err %d): " \ msg "\n", __func__, __LINE__, _val, \ ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_FAIL(val, msg, ...) do { \ if (!(val != 0)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_NULL(val, msg, ...) do { \ if (!(val == NULL)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) #define TEST_ASSERT_NOT_NULL(val, msg, ...) do { \ if (!(val != NULL)) { \ printf("TestCase %s() line %d failed: " \ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \ return TEST_FAILED; \ } \ } while (0) struct unit_test_case { int (*setup)(void); int (*teardown)(void); int (*testcase)(void); const char *success_msg; const char *fail_msg; }; #define TEST_CASE(fn) { NULL, NULL, fn, #fn " succeeded", #fn " failed"} #define TEST_CASE_NAMED(name, fn) { NULL, NULL, fn, name " succeeded", \ name " failed"} #define TEST_CASE_ST(setup, teardown, testcase) \ { setup, teardown, testcase, #testcase " succeeded", \ #testcase " failed "} #define TEST_CASES_END() { NULL, NULL, NULL, NULL, NULL } struct unit_test_suite { const char *suite_name; int (*setup)(void); int (*teardown)(void); struct unit_test_case unit_test_cases[]; }; int unit_test_suite_runner(struct unit_test_suite *suite); #define RECURSIVE_ENV_VAR "RTE_TEST_RECURSIVE" #include #include extern const char *prgname; int commands_init(void); int test_pci(void); int test_pci_run; int test_mp_secondary(void); int test_ivshmem(void); int test_set_rxtx_conf(cmdline_fixed_string_t mode); int test_set_rxtx_anchor(cmdline_fixed_string_t type); int test_set_rxtx_sc(cmdline_fixed_string_t type); typedef int (test_callback)(void); TAILQ_HEAD(test_commands_list, test_command); struct test_command { TAILQ_ENTRY(test_command) next; const char *command; test_callback *callback; }; void add_test_command(struct test_command *t); #define REGISTER_TEST_COMMAND(t) \ static void __attribute__((used)) testfn_##t(void);\ void __attribute__((constructor, used)) testfn_##t(void)\ {\ add_test_command(&t);\ } #endif ================================================ FILE: app/test/test_acl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "test.h" #include #include #include #include #include #include #include "test_acl.h" #define LEN RTE_ACL_MAX_CATEGORIES RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS); struct rte_acl_param acl_param = { .name = "acl_ctx", .socket_id = SOCKET_ID_ANY, .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ, .max_rule_num = 0x30000, }; struct rte_acl_ipv4vlan_rule acl_rule = { .data = { .priority = 1, .category_mask = 0xff }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 0, .dst_port_high = UINT16_MAX, }; const uint32_t ipv4_7tuple_layout[RTE_ACL_IPV4VLAN_NUM] = { offsetof(struct ipv4_7tuple, proto), offsetof(struct ipv4_7tuple, vlan), offsetof(struct ipv4_7tuple, ip_src), offsetof(struct ipv4_7tuple, ip_dst), offsetof(struct ipv4_7tuple, port_src), }; /* byteswap to cpu or network order */ static void bswap_test_data(struct ipv4_7tuple *data, int len, int to_be) { int i; for (i = 0; i < len; i++) { if (to_be) { /* swap all bytes so that they are in network order */ data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst); data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src); data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst); data[i].port_src = rte_cpu_to_be_16(data[i].port_src); data[i].vlan = rte_cpu_to_be_16(data[i].vlan); data[i].domain = rte_cpu_to_be_16(data[i].domain); } else { data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst); data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src); data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst); data[i].port_src = rte_be_to_cpu_16(data[i].port_src); data[i].vlan = rte_be_to_cpu_16(data[i].vlan); data[i].domain = rte_be_to_cpu_16(data[i].domain); } } } /* * Test scalar and SSE ACL lookup. */ static int test_classify_run(struct rte_acl_ctx *acx) { int ret, i; uint32_t result, count; uint32_t results[RTE_DIM(acl_test_data) * RTE_ACL_MAX_CATEGORIES]; const uint8_t *data[RTE_DIM(acl_test_data)]; /* swap all bytes in the data to network order */ bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 1); /* store pointers to test data */ for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) data[i] = (uint8_t *)&acl_test_data[i]; /** * these will run quite a few times, it's necessary to test code paths * from num=0 to num>8 */ for (count = 0; count <= RTE_DIM(acl_test_data); count++) { ret = rte_acl_classify(acx, data, results, count, RTE_ACL_MAX_CATEGORIES); if (ret != 0) { printf("Line %i: SSE classify failed!\n", __LINE__); goto err; } /* check if we allow everything we should allow */ for (i = 0; i < (int) count; i++) { result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW]; if (result != acl_test_data[i].allow) { printf("Line %i: Error in allow results at %i " "(expected %"PRIu32" got %"PRIu32")!\n", __LINE__, i, acl_test_data[i].allow, result); ret = -EINVAL; goto err; } } /* check if we deny everything we should deny */ for (i = 0; i < (int) count; i++) { result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY]; if (result != acl_test_data[i].deny) { printf("Line %i: Error in deny results at %i " "(expected %"PRIu32" got %"PRIu32")!\n", __LINE__, i, acl_test_data[i].deny, result); ret = -EINVAL; goto err; } } } /* make a quick check for scalar */ ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(acl_test_data), RTE_ACL_MAX_CATEGORIES, RTE_ACL_CLASSIFY_SCALAR); if (ret != 0) { printf("Line %i: scalar classify failed!\n", __LINE__); goto err; } /* check if we allow everything we should allow */ for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) { result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW]; if (result != acl_test_data[i].allow) { printf("Line %i: Error in allow results at %i " "(expected %"PRIu32" got %"PRIu32")!\n", __LINE__, i, acl_test_data[i].allow, result); ret = -EINVAL; goto err; } } /* check if we deny everything we should deny */ for (i = 0; i < (int) RTE_DIM(acl_test_data); i++) { result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY]; if (result != acl_test_data[i].deny) { printf("Line %i: Error in deny results at %i " "(expected %"PRIu32" got %"PRIu32")!\n", __LINE__, i, acl_test_data[i].deny, result); ret = -EINVAL; goto err; } } ret = 0; err: /* swap data back to cpu order so that next time tests don't fail */ bswap_test_data(acl_test_data, RTE_DIM(acl_test_data), 0); return ret; } static int test_classify_buid(struct rte_acl_ctx *acx, const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) { int ret; /* add rules to the context */ ret = rte_acl_ipv4vlan_add_rules(acx, rules, num); if (ret != 0) { printf("Line %i: Adding rules to ACL context failed!\n", __LINE__); return ret; } /* try building the context */ ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); if (ret != 0) { printf("Line %i: Building ACL context failed!\n", __LINE__); return ret; } return 0; } #define TEST_CLASSIFY_ITER 4 /* * Test scalar and SSE ACL lookup. */ static int test_classify(void) { struct rte_acl_ctx *acx; int i, ret; acx = rte_acl_create(&acl_param); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } ret = 0; for (i = 0; i != TEST_CLASSIFY_ITER; i++) { if ((i & 1) == 0) rte_acl_reset(acx); else rte_acl_reset_rules(acx); ret = test_classify_buid(acx, acl_test_rules, RTE_DIM(acl_test_rules)); if (ret != 0) { printf("Line %i, iter: %d: " "Adding rules to ACL context failed!\n", __LINE__, i); break; } ret = test_classify_run(acx); if (ret != 0) { printf("Line %i, iter: %d: %s failed!\n", __LINE__, i, __func__); break; } /* reset rules and make sure that classify still works ok. */ rte_acl_reset_rules(acx); ret = test_classify_run(acx); if (ret != 0) { printf("Line %i, iter: %d: %s failed!\n", __LINE__, i, __func__); break; } } rte_acl_free(acx); return ret; } static int test_build_ports_range(void) { static const struct rte_acl_ipv4vlan_rule test_rules[] = { { /* match all packets. */ .data = { .userdata = 1, .category_mask = ACL_ALLOW_MASK, .priority = 101, }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 0, .dst_port_high = UINT16_MAX, }, { /* match all packets with dst ports [54-65280]. */ .data = { .userdata = 2, .category_mask = ACL_ALLOW_MASK, .priority = 102, }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 54, .dst_port_high = 65280, }, { /* match all packets with dst ports [0-52]. */ .data = { .userdata = 3, .category_mask = ACL_ALLOW_MASK, .priority = 103, }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 0, .dst_port_high = 52, }, { /* match all packets with dst ports [53]. */ .data = { .userdata = 4, .category_mask = ACL_ALLOW_MASK, .priority = 99, }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 53, .dst_port_high = 53, }, { /* match all packets with dst ports [65279-65535]. */ .data = { .userdata = 5, .category_mask = ACL_ALLOW_MASK, .priority = 98, }, .src_port_low = 0, .src_port_high = UINT16_MAX, .dst_port_low = 65279, .dst_port_high = UINT16_MAX, }, }; static struct ipv4_7tuple test_data[] = { { .proto = 6, .ip_src = IPv4(10, 1, 1, 1), .ip_dst = IPv4(192, 168, 0, 33), .port_dst = 53, .allow = 1, }, { .proto = 6, .ip_src = IPv4(127, 84, 33, 1), .ip_dst = IPv4(1, 2, 3, 4), .port_dst = 65281, .allow = 1, }, }; struct rte_acl_ctx *acx; int32_t ret, i, j; uint32_t results[RTE_DIM(test_data)]; const uint8_t *data[RTE_DIM(test_data)]; acx = rte_acl_create(&acl_param); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } /* swap all bytes in the data to network order */ bswap_test_data(test_data, RTE_DIM(test_data), 1); /* store pointers to test data */ for (i = 0; i != RTE_DIM(test_data); i++) data[i] = (uint8_t *)&test_data[i]; for (i = 0; i != RTE_DIM(test_rules); i++) { rte_acl_reset(acx); ret = test_classify_buid(acx, test_rules, i + 1); if (ret != 0) { printf("Line %i, iter: %d: " "Adding rules to ACL context failed!\n", __LINE__, i); break; } ret = rte_acl_classify(acx, data, results, RTE_DIM(data), 1); if (ret != 0) { printf("Line %i, iter: %d: classify failed!\n", __LINE__, i); break; } /* check results */ for (j = 0; j != RTE_DIM(results); j++) { if (results[j] != test_data[j].allow) { printf("Line %i: Error in allow results at %i " "(expected %"PRIu32" got %"PRIu32")!\n", __LINE__, j, test_data[j].allow, results[j]); ret = -EINVAL; } } } bswap_test_data(test_data, RTE_DIM(test_data), 0); rte_acl_free(acx); return ret; } static void convert_rule(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { ro->data = ri->data; ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto; ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan; ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr; ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low; ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low; ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask; ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask; ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 = ri->domain_mask; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = ri->src_mask_len; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len; ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 = ri->src_port_high; ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 = ri->dst_port_high; } /* * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to * RTE_ACL_FIELD_TYPE_BITMASK. */ static void convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { uint32_t v; convert_rule(ri, ro); v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v)); v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v)); } /* * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to * RTE_ACL_FIELD_TYPE_RANGE. */ static void convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { uint32_t hi, lo, mask; convert_rule(ri, ro); mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32; mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask)); lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask; hi = lo + ~mask; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi; mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32; mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask)); lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask; hi = lo + ~mask; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi; } /* * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields. */ static void convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { struct rte_acl_field t1, t2; convert_rule(ri, ro); t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD]; t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD]; ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] = ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD]; ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] = ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD]; ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1; ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2; } /* * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules. */ static void convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { struct rte_acl_field t; convert_rule(ri, ro); t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD]; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD]; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t; } static void ipv4vlan_config(struct rte_acl_config *cfg, const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], uint32_t num_categories) { static const struct rte_acl_field_def ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD, .input_index = RTE_ACL_IPV4VLAN_PROTO, }, { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD, .input_index = RTE_ACL_IPV4VLAN_VLAN, }, { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD, .input_index = RTE_ACL_IPV4VLAN_VLAN, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD, .input_index = RTE_ACL_IPV4VLAN_SRC, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = RTE_ACL_IPV4VLAN_DST_FIELD, .input_index = RTE_ACL_IPV4VLAN_DST, }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD, .input_index = RTE_ACL_IPV4VLAN_PORTS, }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD, .input_index = RTE_ACL_IPV4VLAN_PORTS, }, }; memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs)); cfg->num_fields = RTE_DIM(ipv4_defs); cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PROTO]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset = layout[RTE_ACL_IPV4VLAN_VLAN]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset = layout[RTE_ACL_IPV4VLAN_VLAN] + cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size; cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset = layout[RTE_ACL_IPV4VLAN_SRC]; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = layout[RTE_ACL_IPV4VLAN_DST]; cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PORTS]; cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PORTS] + cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size; cfg->num_categories = num_categories; } static int convert_rules(struct rte_acl_ctx *acx, void (*convert)(const struct rte_acl_ipv4vlan_rule *, struct acl_ipv4vlan_rule *), const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) { int32_t rc; uint32_t i; struct acl_ipv4vlan_rule r; for (i = 0; i != num; i++) { convert(rules + i, &r); rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1); if (rc != 0) { printf("Line %i: Adding rule %u to ACL context " "failed with error code: %d\n", __LINE__, i, rc); return rc; } } return 0; } static void convert_config(struct rte_acl_config *cfg) { ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); } /* * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK. */ static void convert_config_1(struct rte_acl_config *cfg) { ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK; } /* * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE. */ static void convert_config_2(struct rte_acl_config *cfg) { ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE; } /* * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions. */ static void convert_config_3(struct rte_acl_config *cfg) { struct rte_acl_field_def t1, t2; ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD]; t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD]; /* swap VLAN1 and SRCP rule definition. */ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] = cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index; cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index; /* swap VLAN2 and DSTP rule definition. */ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] = cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index; cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index; cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type; cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size; cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset; cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type; cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size; cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset; } /* * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions. */ static void convert_config_4(struct rte_acl_config *cfg) { struct rte_acl_field_def t; ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES); t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD]; cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] = cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD]; cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index; cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset; } static int build_convert_rules(struct rte_acl_ctx *acx, void (*config)(struct rte_acl_config *), size_t max_size) { struct rte_acl_config cfg; memset(&cfg, 0, sizeof(cfg)); config(&cfg); cfg.max_size = max_size; return rte_acl_build(acx, &cfg); } static int test_convert_rules(const char *desc, void (*config)(struct rte_acl_config *), void (*convert)(const struct rte_acl_ipv4vlan_rule *, struct acl_ipv4vlan_rule *)) { struct rte_acl_ctx *acx; int32_t rc; uint32_t i; static const size_t mem_sizes[] = {0, -1}; printf("running %s(%s)\n", __func__, desc); acx = rte_acl_create(&acl_param); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } rc = convert_rules(acx, convert, acl_test_rules, RTE_DIM(acl_test_rules)); if (rc != 0) printf("Line %i: Error converting ACL rules!\n", __LINE__); for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) { rc = build_convert_rules(acx, config, mem_sizes[i]); if (rc != 0) { printf("Line %i: Error @ build_convert_rules(%zu)!\n", __LINE__, mem_sizes[i]); break; } rc = test_classify_run(acx); if (rc != 0) printf("%s failed at line %i, max_size=%zu\n", __func__, __LINE__, mem_sizes[i]); } rte_acl_free(acx); return rc; } static int test_convert(void) { static const struct { const char *desc; void (*config)(struct rte_acl_config *); void (*convert)(const struct rte_acl_ipv4vlan_rule *, struct acl_ipv4vlan_rule *); } convert_param[] = { { "acl_ipv4vlan_tuple", convert_config, convert_rule, }, { "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type " "for IPv4", convert_config_1, convert_rule_1, }, { "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type " "for IPv4", convert_config_2, convert_rule_2, }, { "acl_ipv4vlan_tuple: swap VLAN and PORTs order", convert_config_3, convert_rule_3, }, { "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order", convert_config_4, convert_rule_4, }, }; uint32_t i; int32_t rc; for (i = 0; i != RTE_DIM(convert_param); i++) { rc = test_convert_rules(convert_param[i].desc, convert_param[i].config, convert_param[i].convert); if (rc != 0) { printf("%s for test-case: %s failed, error code: %d;\n", __func__, convert_param[i].desc, rc); return rc; } } return 0; } /* * Test wrong layout behavior * This test supplies the ACL context with invalid layout, which results in * ACL matching the wrong stuff. However, it should match the wrong stuff * the right way. We switch around source and destination addresses, * source and destination ports, and protocol will point to first byte of * destination port. */ static int test_invalid_layout(void) { struct rte_acl_ctx *acx; int ret, i; uint32_t results[RTE_DIM(invalid_layout_data)]; const uint8_t *data[RTE_DIM(invalid_layout_data)]; const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = { /* proto points to destination port's first byte */ offsetof(struct ipv4_7tuple, port_dst), 0, /* VLAN not used */ /* src and dst addresses are swapped */ offsetof(struct ipv4_7tuple, ip_dst), offsetof(struct ipv4_7tuple, ip_src), /* * we can't swap ports here, so we will swap * them in the data */ offsetof(struct ipv4_7tuple, port_src), }; acx = rte_acl_create(&acl_param); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } /* putting a lot of rules into the context results in greater * coverage numbers. it doesn't matter if they are identical */ for (i = 0; i < 1000; i++) { /* add rules to the context */ ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules, RTE_DIM(invalid_layout_rules)); if (ret != 0) { printf("Line %i: Adding rules to ACL context failed!\n", __LINE__); rte_acl_free(acx); return -1; } } /* try building the context */ ret = rte_acl_ipv4vlan_build(acx, layout, 1); if (ret != 0) { printf("Line %i: Building ACL context failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* swap all bytes in the data to network order */ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1); /* prepare data */ for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) { data[i] = (uint8_t *)&invalid_layout_data[i]; } /* classify tuples */ ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR); if (ret != 0) { printf("Line %i: SSE classify failed!\n", __LINE__); rte_acl_free(acx); return -1; } for (i = 0; i < (int) RTE_DIM(results); i++) { if (results[i] != invalid_layout_data[i].allow) { printf("Line %i: Wrong results at %i " "(result=%u, should be %u)!\n", __LINE__, i, results[i], invalid_layout_data[i].allow); goto err; } } /* classify tuples (scalar) */ ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR); if (ret != 0) { printf("Line %i: Scalar classify failed!\n", __LINE__); rte_acl_free(acx); return -1; } for (i = 0; i < (int) RTE_DIM(results); i++) { if (results[i] != invalid_layout_data[i].allow) { printf("Line %i: Wrong results at %i " "(result=%u, should be %u)!\n", __LINE__, i, results[i], invalid_layout_data[i].allow); goto err; } } rte_acl_free(acx); /* swap data back to cpu order so that next time tests don't fail */ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0); return 0; err: /* swap data back to cpu order so that next time tests don't fail */ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0); rte_acl_free(acx); return -1; } /* * Test creating and finding ACL contexts, and adding rules */ static int test_create_find_add(void) { struct rte_acl_param param; struct rte_acl_ctx *acx, *acx2, *tmp; struct rte_acl_ipv4vlan_rule rules[LEN]; const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0}; const char *acx_name = "acx"; const char *acx2_name = "acx2"; int i, ret; /* create two contexts */ memcpy(¶m, &acl_param, sizeof(param)); param.max_rule_num = 2; param.name = acx_name; acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: Error creating %s!\n", __LINE__, acx_name); return -1; } param.name = acx2_name; acx2 = rte_acl_create(¶m); if (acx2 == NULL || acx2 == acx) { printf("Line %i: Error creating %s!\n", __LINE__, acx2_name); rte_acl_free(acx); return -1; } /* try to create third one, with an existing name */ param.name = acx_name; tmp = rte_acl_create(¶m); if (tmp != acx) { printf("Line %i: Creating context with existing name " "test failed!\n", __LINE__); if (tmp) rte_acl_free(tmp); goto err; } param.name = acx2_name; tmp = rte_acl_create(¶m); if (tmp != acx2) { printf("Line %i: Creating context with existing " "name test 2 failed!\n", __LINE__); if (tmp) rte_acl_free(tmp); goto err; } /* try to find existing ACL contexts */ tmp = rte_acl_find_existing(acx_name); if (tmp != acx) { printf("Line %i: Finding %s failed!\n", __LINE__, acx_name); if (tmp) rte_acl_free(tmp); goto err; } tmp = rte_acl_find_existing(acx2_name); if (tmp != acx2) { printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name); if (tmp) rte_acl_free(tmp); goto err; } /* try to find non-existing context */ tmp = rte_acl_find_existing("invalid"); if (tmp != NULL) { printf("Line %i: Non-existent ACL context found!\n", __LINE__); goto err; } /* free context */ rte_acl_free(acx); /* create valid (but severely limited) acx */ memcpy(¶m, &acl_param, sizeof(param)); param.max_rule_num = LEN; acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: Error creating %s!\n", __LINE__, param.name); goto err; } /* create dummy acl */ for (i = 0; i < LEN; i++) { memcpy(&rules[i], &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule)); /* skip zero */ rules[i].data.userdata = i + 1; /* one rule per category */ rules[i].data.category_mask = 1 << i; } /* try filling up the context */ ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN); if (ret != 0) { printf("Line %i: Adding %i rules to ACL context failed!\n", __LINE__, LEN); goto err; } /* try adding to a (supposedly) full context */ ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1); if (ret == 0) { printf("Line %i: Adding rules to full ACL context should" "have failed!\n", __LINE__); goto err; } /* try building the context */ ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES); if (ret != 0) { printf("Line %i: Building ACL context failed!\n", __LINE__); goto err; } rte_acl_free(acx); rte_acl_free(acx2); return 0; err: rte_acl_free(acx); rte_acl_free(acx2); return -1; } /* * test various invalid rules */ static int test_invalid_rules(void) { struct rte_acl_ctx *acx; int ret; struct rte_acl_ipv4vlan_rule rule; acx = rte_acl_create(&acl_param); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } /* test inverted high/low source and destination ports. * originally, there was a problem with memory consumption when using * such rules. */ /* create dummy acl */ memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule)); rule.data.userdata = 1; rule.dst_port_low = 0xfff0; rule.dst_port_high = 0x0010; /* add rules to context and try to build it */ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (ret == 0) { printf("Line %i: Adding rules to ACL context " "should have failed!\n", __LINE__); goto err; } rule.dst_port_low = 0x0; rule.dst_port_high = 0xffff; rule.src_port_low = 0xfff0; rule.src_port_high = 0x0010; /* add rules to context and try to build it */ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (ret == 0) { printf("Line %i: Adding rules to ACL context " "should have failed!\n", __LINE__); goto err; } rule.dst_port_low = 0x0; rule.dst_port_high = 0xffff; rule.src_port_low = 0x0; rule.src_port_high = 0xffff; rule.dst_mask_len = 33; /* add rules to context and try to build it */ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (ret == 0) { printf("Line %i: Adding rules to ACL context " "should have failed!\n", __LINE__); goto err; } rule.dst_mask_len = 0; rule.src_mask_len = 33; /* add rules to context and try to build it */ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (ret == 0) { printf("Line %i: Adding rules to ACL context " "should have failed!\n", __LINE__); goto err; } rule.dst_mask_len = 0; rule.src_mask_len = 0; rule.data.userdata = 0; /* try adding this rule (it should fail because userdata is invalid) */ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (ret == 0) { printf("Line %i: Adding a rule with invalid user data " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } rte_acl_free(acx); return 0; err: rte_acl_free(acx); return -1; } /* * test functions by passing invalid or * non-workable parameters. * * we do very limited testing of classify functions here * because those are performance-critical and * thus don't do much parameter checking. */ static int test_invalid_parameters(void) { struct rte_acl_param param; struct rte_acl_ctx *acx; struct rte_acl_ipv4vlan_rule rule; int result; uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0}; /** * rte_ac_create() */ /* NULL param */ acx = rte_acl_create(NULL); if (acx != NULL) { printf("Line %i: ACL context creation with NULL param " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* zero rule size */ memcpy(¶m, &acl_param, sizeof(param)); param.rule_size = 0; acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: ACL context creation with zero rule len " "failed!\n", __LINE__); return -1; } else rte_acl_free(acx); /* zero max rule num */ memcpy(¶m, &acl_param, sizeof(param)); param.max_rule_num = 0; acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: ACL context creation with zero rule num " "failed!\n", __LINE__); return -1; } else rte_acl_free(acx); /* invalid NUMA node */ memcpy(¶m, &acl_param, sizeof(param)); param.socket_id = RTE_MAX_NUMA_NODES + 1; acx = rte_acl_create(¶m); if (acx != NULL) { printf("Line %i: ACL context creation with invalid NUMA " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* NULL name */ memcpy(¶m, &acl_param, sizeof(param)); param.name = NULL; acx = rte_acl_create(¶m); if (acx != NULL) { printf("Line %i: ACL context creation with NULL name " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /** * rte_acl_find_existing */ acx = rte_acl_find_existing(NULL); if (acx != NULL) { printf("Line %i: NULL ACL context found!\n", __LINE__); rte_acl_free(acx); return -1; } /** * rte_acl_ipv4vlan_add_rules */ /* initialize everything */ memcpy(¶m, &acl_param, sizeof(param)); acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: ACL context creation failed!\n", __LINE__); return -1; } memcpy(&rule, &acl_rule, sizeof(rule)); /* NULL context */ result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1); if (result == 0) { printf("Line %i: Adding rules with NULL ACL context " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* NULL rule */ result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1); if (result == 0) { printf("Line %i: Adding NULL rule to ACL context " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* zero count (should succeed) */ result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0); if (result != 0) { printf("Line %i: Adding 0 rules to ACL context failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* free ACL context */ rte_acl_free(acx); /* set wrong rule_size so that adding any rules would fail */ param.rule_size = RTE_ACL_IPV4VLAN_RULE_SZ + 4; acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: ACL context creation failed!\n", __LINE__); return -1; } /* try adding a rule with size different from context rule_size */ result = rte_acl_ipv4vlan_add_rules(acx, &rule, 1); if (result == 0) { printf("Line %i: Adding an invalid sized rule " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* free ACL context */ rte_acl_free(acx); /** * rte_acl_ipv4vlan_build */ /* reinitialize context */ memcpy(¶m, &acl_param, sizeof(param)); acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: ACL context creation failed!\n", __LINE__); return -1; } /* NULL context */ result = rte_acl_ipv4vlan_build(NULL, layout, 1); if (result == 0) { printf("Line %i: Building with NULL context " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* NULL layout */ result = rte_acl_ipv4vlan_build(acx, NULL, 1); if (result == 0) { printf("Line %i: Building with NULL layout " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* zero categories (should not fail) */ result = rte_acl_ipv4vlan_build(acx, layout, 0); if (result == 0) { printf("Line %i: Building with 0 categories should fail!\n", __LINE__); rte_acl_free(acx); return -1; } /* SSE classify test */ /* cover zero categories in classify (should not fail) */ result = rte_acl_classify(acx, NULL, NULL, 0, 0); if (result != 0) { printf("Line %i: SSE classify with zero categories " "failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* cover invalid but positive categories in classify */ result = rte_acl_classify(acx, NULL, NULL, 0, 3); if (result == 0) { printf("Line %i: SSE classify with 3 categories " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* scalar classify test */ /* cover zero categories in classify (should not fail) */ result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0, RTE_ACL_CLASSIFY_SCALAR); if (result != 0) { printf("Line %i: Scalar classify with zero categories " "failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* cover invalid but positive categories in classify */ result = rte_acl_classify(acx, NULL, NULL, 0, 3); if (result == 0) { printf("Line %i: Scalar classify with 3 categories " "should have failed!\n", __LINE__); rte_acl_free(acx); return -1; } /* free ACL context */ rte_acl_free(acx); /** * make sure void functions don't crash with NULL parameters */ rte_acl_free(NULL); rte_acl_dump(NULL); return 0; } /** * Various tests that don't test much but improve coverage */ static int test_misc(void) { struct rte_acl_param param; struct rte_acl_ctx *acx; /* create context */ memcpy(¶m, &acl_param, sizeof(param)); acx = rte_acl_create(¶m); if (acx == NULL) { printf("Line %i: Error creating ACL context!\n", __LINE__); return -1; } /* dump context with rules - useful for coverage */ rte_acl_list_dump(); rte_acl_dump(acx); rte_acl_free(acx); return 0; } static int test_acl(void) { if (test_invalid_parameters() < 0) return -1; if (test_invalid_rules() < 0) return -1; if (test_create_find_add() < 0) return -1; if (test_invalid_layout() < 0) return -1; if (test_misc() < 0) return -1; if (test_classify() < 0) return -1; if (test_build_ports_range() < 0) return -1; if (test_convert() < 0) return -1; return 0; } static struct test_command acl_cmd = { .command = "acl_autotest", .callback = test_acl, }; REGISTER_TEST_COMMAND(acl_cmd); ================================================ FILE: app/test/test_acl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TEST_ACL_H_ #define TEST_ACL_H_ struct ipv4_7tuple { uint16_t vlan; uint16_t domain; uint8_t proto; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t allow; uint32_t deny; }; /* rules for invalid layout test */ struct rte_acl_ipv4vlan_rule invalid_layout_rules[] = { /* test src and dst address */ { .data = {.userdata = 1, .category_mask = 1}, .src_addr = IPv4(10,0,0,0), .src_mask_len = 24, }, { .data = {.userdata = 2, .category_mask = 1}, .dst_addr = IPv4(10,0,0,0), .dst_mask_len = 24, }, /* test src and dst ports */ { .data = {.userdata = 3, .category_mask = 1}, .dst_port_low = 100, .dst_port_high = 100, }, { .data = {.userdata = 4, .category_mask = 1}, .src_port_low = 100, .src_port_high = 100, }, /* test proto */ { .data = {.userdata = 5, .category_mask = 1}, .proto = 0xf, .proto_mask = 0xf }, { .data = {.userdata = 6, .category_mask = 1}, .dst_port_low = 0xf, .dst_port_high = 0xf, } }; /* these might look odd because they don't match up the rules. This is * intentional, as the invalid layout test presumes returning the correct * results using the wrong data layout. */ struct ipv4_7tuple invalid_layout_data[] = { {.ip_src = IPv4(10,0,1,0)}, /* should not match */ {.ip_src = IPv4(10,0,0,1), .allow = 2}, /* should match 2 */ {.port_src = 100, .allow = 4}, /* should match 4 */ {.port_dst = 0xf, .allow = 6}, /* should match 6 */ }; #define ACL_ALLOW 0 #define ACL_DENY 1 #define ACL_ALLOW_MASK 0x1 #define ACL_DENY_MASK 0x2 /* ruleset for ACL unit test */ struct rte_acl_ipv4vlan_rule acl_test_rules[] = { /* destination IP addresses */ /* matches all packets traveling to 192.168.0.0/16 */ { .data = {.userdata = 1, .category_mask = ACL_ALLOW_MASK, .priority = 230}, .dst_addr = IPv4(192,168,0,0), .dst_mask_len = 16, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets traveling to 192.168.1.0/24 */ { .data = {.userdata = 2, .category_mask = ACL_ALLOW_MASK, .priority = 330}, .dst_addr = IPv4(192,168,1,0), .dst_mask_len = 24, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets traveling to 192.168.1.50 */ { .data = {.userdata = 3, .category_mask = ACL_DENY_MASK, .priority = 230}, .dst_addr = IPv4(192,168,1,50), .dst_mask_len = 32, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* source IP addresses */ /* matches all packets traveling from 10.0.0.0/8 */ { .data = {.userdata = 4, .category_mask = ACL_ALLOW_MASK, .priority = 240}, .src_addr = IPv4(10,0,0,0), .src_mask_len = 8, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets traveling from 10.1.1.0/24 */ { .data = {.userdata = 5, .category_mask = ACL_ALLOW_MASK, .priority = 340}, .src_addr = IPv4(10,1,1,0), .src_mask_len = 24, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets traveling from 10.1.1.1 */ { .data = {.userdata = 6, .category_mask = ACL_DENY_MASK, .priority = 240}, .src_addr = IPv4(10,1,1,1), .src_mask_len = 32, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* VLAN tag */ /* matches all packets with lower 7 bytes of VLAN tag equal to 0x64 */ { .data = {.userdata = 7, .category_mask = ACL_ALLOW_MASK, .priority = 260}, .vlan = 0x64, .vlan_mask = 0x7f, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with VLAN tags that have 0x5 in them */ { .data = {.userdata = 8, .category_mask = ACL_ALLOW_MASK, .priority = 260}, .vlan = 0x5, .vlan_mask = 0x5, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with VLAN tag 5 */ { .data = {.userdata = 9, .category_mask = ACL_DENY_MASK, .priority = 360}, .vlan = 0x5, .vlan_mask = 0xffff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* VLAN domain */ /* matches all packets with lower 7 bytes of domain equal to 0x64 */ { .data = {.userdata = 10, .category_mask = ACL_ALLOW_MASK, .priority = 250}, .domain = 0x64, .domain_mask = 0x7f, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with domains that have 0x5 in them */ { .data = {.userdata = 11, .category_mask = ACL_ALLOW_MASK, .priority = 350}, .domain = 0x5, .domain_mask = 0x5, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with domain 5 */ { .data = {.userdata = 12, .category_mask = ACL_DENY_MASK, .priority = 350}, .domain = 0x5, .domain_mask = 0xffff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* destination port */ /* matches everything with dst port 80 */ { .data = {.userdata = 13, .category_mask = ACL_ALLOW_MASK, .priority = 310}, .dst_port_low = 80, .dst_port_high = 80, .src_port_low = 0, .src_port_high = 0xffff, }, /* matches everything with dst port 22-1023 */ { .data = {.userdata = 14, .category_mask = ACL_ALLOW_MASK, .priority = 210}, .dst_port_low = 22, .dst_port_high = 1023, .src_port_low = 0, .src_port_high = 0xffff, }, /* matches everything with dst port 1020 */ { .data = {.userdata = 15, .category_mask = ACL_DENY_MASK, .priority = 310}, .dst_port_low = 1020, .dst_port_high = 1020, .src_port_low = 0, .src_port_high = 0xffff, }, /* matches everything with dst portrange 1000-2000 */ { .data = {.userdata = 16, .category_mask = ACL_DENY_MASK, .priority = 210}, .dst_port_low = 1000, .dst_port_high = 2000, .src_port_low = 0, .src_port_high = 0xffff, }, /* source port */ /* matches everything with src port 80 */ { .data = {.userdata = 17, .category_mask = ACL_ALLOW_MASK, .priority = 320}, .src_port_low = 80, .src_port_high = 80, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches everything with src port 22-1023 */ { .data = {.userdata = 18, .category_mask = ACL_ALLOW_MASK, .priority = 220}, .src_port_low = 22, .src_port_high = 1023, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches everything with src port 1020 */ { .data = {.userdata = 19, .category_mask = ACL_DENY_MASK, .priority = 320}, .src_port_low = 1020, .src_port_high = 1020, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches everything with src portrange 1000-2000 */ { .data = {.userdata = 20, .category_mask = ACL_DENY_MASK, .priority = 220}, .src_port_low = 1000, .src_port_high = 2000, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* protocol number */ /* matches all packets with protocol number either 0x64 or 0xE4 */ { .data = {.userdata = 21, .category_mask = ACL_ALLOW_MASK, .priority = 270}, .proto = 0x64, .proto_mask = 0x7f, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with protocol that have 0x5 in them */ { .data = {.userdata = 22, .category_mask = ACL_ALLOW_MASK, .priority = 1}, .proto = 0x5, .proto_mask = 0x5, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* matches all packets with protocol 5 */ { .data = {.userdata = 23, .category_mask = ACL_DENY_MASK, .priority = 370}, .proto = 0x5, .proto_mask = 0xff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 0, .dst_port_high = 0xffff, }, /* rules combining various fields */ { .data = {.userdata = 24, .category_mask = ACL_ALLOW_MASK, .priority = 400}, /** make sure that unmasked bytes don't fail! */ .dst_addr = IPv4(1,2,3,4), .dst_mask_len = 16, .src_addr = IPv4(5,6,7,8), .src_mask_len = 24, .proto = 0x5, .proto_mask = 0xff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 22, .dst_port_high = 1024, .vlan = 0x8100, .vlan_mask = 0xffff, .domain = 0x64, .domain_mask = 0xffff, }, { .data = {.userdata = 25, .category_mask = ACL_DENY_MASK, .priority = 400}, .dst_addr = IPv4(5,6,7,8), .dst_mask_len = 24, .src_addr = IPv4(1,2,3,4), .src_mask_len = 16, .proto = 0x5, .proto_mask = 0xff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 22, .dst_port_high = 1024, .vlan = 0x8100, .vlan_mask = 0xffff, .domain = 0x64, .domain_mask = 0xffff, }, { .data = {.userdata = 26, .category_mask = ACL_ALLOW_MASK, .priority = 500}, .dst_addr = IPv4(1,2,3,4), .dst_mask_len = 8, .src_addr = IPv4(5,6,7,8), .src_mask_len = 32, .proto = 0x5, .proto_mask = 0xff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 22, .dst_port_high = 1024, .vlan = 0x64, .vlan_mask = 0xffff, }, { .data = {.userdata = 27, .category_mask = ACL_DENY_MASK, .priority = 500}, .dst_addr = IPv4(5,6,7,8), .dst_mask_len = 32, .src_addr = IPv4(1,2,3,4), .src_mask_len = 8, .proto = 0x5, .proto_mask = 0xff, .src_port_low = 0, .src_port_high = 0xffff, .dst_port_low = 22, .dst_port_high = 1024, .vlan = 0x64, .vlan_mask = 0xffff, }, }; /* data for ACL unit test */ struct ipv4_7tuple acl_test_data[] = { /* testing single rule aspects */ {.ip_src = IPv4(10,0,0,0), .allow = 4}, /* should match 4 */ {.ip_src = IPv4(10,1,1,2), .allow = 5}, /* should match 5 */ {.ip_src = IPv4(10,1,1,1), .allow = 5, .deny = 6}, /* should match 5, 6 */ {.ip_dst = IPv4(10,0,0,0)}, /* should not match */ {.ip_dst = IPv4(10,1,1,2)}, /* should not match */ {.ip_dst = IPv4(10,1,1,1)}, /* should not match */ {.ip_src = IPv4(192,168,2,50)}, /* should not match */ {.ip_src = IPv4(192,168,1,2)}, /* should not match */ {.ip_src = IPv4(192,168,1,50)}, /* should not match */ {.ip_dst = IPv4(192,168,2,50), .allow = 1}, /* should match 1 */ {.ip_dst = IPv4(192,168,1,49), .allow = 2}, /* should match 2 */ {.ip_dst = IPv4(192,168,1,50), .allow = 2, .deny = 3}, /* should match 2, 3 */ {.vlan = 0x64, .allow = 7}, /* should match 7 */ {.vlan = 0xfE4, .allow = 7}, /* should match 7 */ {.vlan = 0xE2}, /* should not match */ {.vlan = 0xD, .allow = 8}, /* should match 8 */ {.vlan = 0x6}, /* should not match */ {.vlan = 0x5, .allow = 8, .deny = 9}, /* should match 8, 9 */ {.domain = 0x64, .allow = 10}, /* should match 10 */ {.domain = 0xfE4, .allow = 10}, /* should match 10 */ {.domain = 0xE2}, /* should not match */ {.domain = 0xD, .allow = 11}, /* should match 11 */ {.domain = 0x6}, /* should not match */ {.domain = 0x5, .allow = 11, .deny = 12}, /* should match 11, 12 */ {.port_dst = 80, .allow = 13}, /* should match 13 */ {.port_dst = 79, .allow = 14}, /* should match 14 */ {.port_dst = 81, .allow = 14}, /* should match 14 */ {.port_dst = 21}, /* should not match */ {.port_dst = 1024, .deny = 16}, /* should match 16 */ {.port_dst = 1020, .allow = 14, .deny = 15}, /* should match 14, 15 */ {.port_src = 80, .allow = 17}, /* should match 17 */ {.port_src = 79, .allow = 18}, /* should match 18 */ {.port_src = 81, .allow = 18}, /* should match 18 */ {.port_src = 21}, /* should not match */ {.port_src = 1024, .deny = 20}, /* should match 20 */ {.port_src = 1020, .allow = 18, .deny = 19}, /* should match 18, 19 */ {.proto = 0x64, .allow = 21}, /* should match 21 */ {.proto = 0xE4, .allow = 21}, /* should match 21 */ {.proto = 0xE2}, /* should not match */ {.proto = 0xD, .allow = 22}, /* should match 22 */ {.proto = 0x6}, /* should not match */ {.proto = 0x5, .allow = 22, .deny = 23}, /* should match 22, 23 */ /* testing matching multiple rules at once */ {.vlan = 0x5, .ip_src = IPv4(10,1,1,1), .allow = 5, .deny = 9}, /* should match 5, 9 */ {.vlan = 0x5, .ip_src = IPv4(192,168,2,50), .allow = 8, .deny = 9}, /* should match 8, 9 */ {.vlan = 0x55, .ip_src = IPv4(192,168,1,49), .allow = 8}, /* should match 8 */ {.port_dst = 80, .port_src = 1024, .allow = 13, .deny = 20}, /* should match 13,20 */ {.port_dst = 79, .port_src = 1024, .allow = 14, .deny = 20}, /* should match 14,20 */ {.proto = 0x5, .ip_dst = IPv4(192,168,2,50), .allow = 1, .deny = 23}, /* should match 1, 23 */ {.proto = 0x5, .ip_dst = IPv4(192,168,1,50), .allow = 2, .deny = 23}, /* should match 2, 23 */ {.vlan = 0x64, .domain = 0x5, .allow = 11, .deny = 12}, /* should match 11, 12 */ {.proto = 0x5, .port_src = 80, .allow = 17, .deny = 23}, /* should match 17, 23 */ {.proto = 0x5, .port_dst = 80, .allow = 13, .deny = 23}, /* should match 13, 23 */ {.proto = 0x51, .port_src = 5000}, /* should not match */ {.ip_src = IPv4(192,168,1,50), .ip_dst = IPv4(10,0,0,0), .proto = 0x51, .port_src = 5000, .port_dst = 5000}, /* should not match */ /* test full packet rules */ { .ip_dst = IPv4(1,2,100,200), .ip_src = IPv4(5,6,7,254), .proto = 0x5, .vlan = 0x8100, .domain = 0x64, .port_src = 12345, .port_dst = 80, .allow = 24, .deny = 23 }, /* should match 23, 24 */ { .ip_dst = IPv4(5,6,7,254), .ip_src = IPv4(1,2,100,200), .proto = 0x5, .vlan = 0x8100, .domain = 0x64, .port_src = 12345, .port_dst = 80, .allow = 13, .deny = 25 }, /* should match 13, 25 */ { .ip_dst = IPv4(1,10,20,30), .ip_src = IPv4(5,6,7,8), .proto = 0x5, .vlan = 0x64, .port_src = 12345, .port_dst = 80, .allow = 26, .deny = 23 }, /* should match 23, 26 */ { .ip_dst = IPv4(5,6,7,8), .ip_src = IPv4(1,10,20,30), .proto = 0x5, .vlan = 0x64, .port_src = 12345, .port_dst = 80, .allow = 13, .deny = 27 }, /* should match 13, 27 */ { .ip_dst = IPv4(2,2,3,4), .ip_src = IPv4(4,6,7,8), .proto = 0x5, .vlan = 0x64, .port_src = 12345, .port_dst = 80, .allow = 13, .deny = 23 }, /* should match 13, 23 */ { .ip_dst = IPv4(1,2,3,4), .ip_src = IPv4(4,6,7,8), .proto = 0x5, .vlan = 0x64, .port_src = 12345, .port_dst = 80, .allow = 13, .deny = 23 }, /* should match 13, 23 */ /* visual separator! */ { .ip_dst = IPv4(1,2,100,200), .ip_src = IPv4(5,6,7,254), .proto = 0x55, .vlan = 0x8000, .domain = 0x6464, .port_src = 12345, .port_dst = 8080, .allow = 10 }, /* should match 10 */ { .ip_dst = IPv4(5,6,7,254), .ip_src = IPv4(1,2,100,200), .proto = 0x55, .vlan = 0x8100, .domain = 0x6464, .port_src = 12345, .port_dst = 180, .allow = 10 }, /* should match 10 */ { .ip_dst = IPv4(1,10,20,30), .ip_src = IPv4(5,6,7,8), .proto = 0x55, .vlan = 0x64, .port_src = 12345, .port_dst = 180, .allow = 7 }, /* should match 7 */ { .ip_dst = IPv4(5,6,7,8), .ip_src = IPv4(1,10,20,30), .proto = 0x55, .vlan = 0x64, .port_src = 12345, .port_dst = 180, .allow = 7 }, /* should match 7 */ { .ip_dst = IPv4(2,2,3,4), .ip_src = IPv4(4,6,7,8), .proto = 0x55, .vlan = 0x64, .port_src = 12345, .port_dst = 180, .allow = 7 }, /* should match 7 */ { .ip_dst = IPv4(1,2,3,4), .ip_src = IPv4(4,6,7,8), .proto = 0x50, .vlan = 0x6466, .port_src = 12345, .port_dst = 12345, }, /* should not match */ }; #endif /* TEST_ACL_H_ */ ================================================ FILE: app/test/test_alarm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "test.h" #define US_PER_MS 1000 #define RTE_TEST_ALARM_TIMEOUT 3000 /* ms */ #define RTE_TEST_CHECK_PERIOD 1000 /* ms */ static volatile int flag; static void test_alarm_callback(void *cb_arg) { flag = 1; printf("Callback setting flag - OK. [cb_arg = %p]\n", cb_arg); } static rte_atomic32_t cb_count; static void test_multi_cb(void *arg) { rte_atomic32_inc(&cb_count); printf("In %s - arg = %p\n", __func__, arg); } static volatile int recursive_error = 0; static void test_remove_in_callback(void *arg) { printf("In %s - arg = %p\n", __func__, arg); if (rte_eal_alarm_cancel(test_remove_in_callback, arg) || rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1)) { printf("Error - cancelling callback from within function succeeded!\n"); recursive_error = 1; } flag = (int)((uintptr_t)arg); } static volatile int flag_2; static void test_remove_in_callback_2(void *arg) { if (rte_eal_alarm_cancel(test_remove_in_callback_2, arg) || rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1)) { printf("Error - cancelling callback of test_remove_in_callback_2\n"); return; } flag_2 = 1; } static int test_multi_alarms(void) { int rm_count = 0; cb_count.cnt = 0; printf("Expect 6 callbacks in order...\n"); /* add two alarms in order */ rte_eal_alarm_set(1000 * US_PER_MS, test_multi_cb, (void *)1); rte_eal_alarm_set(2000 * US_PER_MS, test_multi_cb, (void *)2); /* now add in reverse order */ rte_eal_alarm_set(6000 * US_PER_MS, test_multi_cb, (void *)6); rte_eal_alarm_set(5000 * US_PER_MS, test_multi_cb, (void *)5); rte_eal_alarm_set(4000 * US_PER_MS, test_multi_cb, (void *)4); rte_eal_alarm_set(3000 * US_PER_MS, test_multi_cb, (void *)3); /* wait for expiry */ rte_delay_ms(6500); if (cb_count.cnt != 6) { printf("Missing callbacks\n"); /* remove any callbacks that might remain */ rte_eal_alarm_cancel(test_multi_cb, (void *)-1); return -1; } cb_count.cnt = 0; printf("Expect only callbacks with args 1 and 3...\n"); /* Add 3 flags, then delete one */ rte_eal_alarm_set(3000 * US_PER_MS, test_multi_cb, (void *)3); rte_eal_alarm_set(2000 * US_PER_MS, test_multi_cb, (void *)2); rte_eal_alarm_set(1000 * US_PER_MS, test_multi_cb, (void *)1); rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *)2); rte_delay_ms(3500); if (cb_count.cnt != 2 || rm_count != 1) { printf("Error: invalid flags count or alarm removal failure" " - flags value = %d, expected = %d\n", (int)cb_count.cnt, 2); /* remove any callbacks that might remain */ rte_eal_alarm_cancel(test_multi_cb, (void *)-1); return -1; } printf("Testing adding and then removing multiple alarms\n"); /* finally test that no callbacks are called if we delete them all*/ rte_eal_alarm_set(1000 * US_PER_MS, test_multi_cb, (void *)1); rte_eal_alarm_set(1000 * US_PER_MS, test_multi_cb, (void *)2); rte_eal_alarm_set(1000 * US_PER_MS, test_multi_cb, (void *)3); rm_count = rte_eal_alarm_cancel(test_alarm_callback, (void *)-1); if (rm_count != 0) { printf("Error removing non-existant alarm succeeded\n"); rte_eal_alarm_cancel(test_multi_cb, (void *) -1); return -1; } rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *) -1); if (rm_count != 3) { printf("Error removing all pending alarm callbacks\n"); return -1; } /* Test that we cannot cancel an alarm from within the callback itself * Also test that we can cancel head-of-line callbacks ok.*/ flag = 0; recursive_error = 0; rte_eal_alarm_set(1000 * US_PER_MS, test_remove_in_callback, (void *)1); rte_eal_alarm_set(2000 * US_PER_MS, test_remove_in_callback, (void *)2); rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)1); if (rm_count != 1) { printf("Error cancelling head-of-list callback\n"); return -1; } rte_delay_ms(1500); if (flag != 0) { printf("Error, cancelling head-of-list leads to premature callback\n"); return -1; } rte_delay_ms(1000); if (flag != 2) { printf("Error - expected callback not called\n"); rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1); return -1; } if (recursive_error == 1) return -1; /* Check if it can cancel all for the same callback */ printf("Testing canceling all for the same callback\n"); flag_2 = 0; rte_eal_alarm_set(1000 * US_PER_MS, test_remove_in_callback, (void *)1); rte_eal_alarm_set(2000 * US_PER_MS, test_remove_in_callback_2, (void *)2); rte_eal_alarm_set(3000 * US_PER_MS, test_remove_in_callback_2, (void *)3); rte_eal_alarm_set(4000 * US_PER_MS, test_remove_in_callback, (void *)4); rm_count = rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1); if (rm_count != 2) { printf("Error, cannot cancel all for the same callback\n"); return -1; } rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1); if (rm_count != 2) { printf("Error, cannot cancel all for the same callback\n"); return -1; } return 0; } static int test_alarm(void) { int count = 0; /* check if the callback will be called */ printf("check if the callback will be called\n"); flag = 0; if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT * US_PER_MS, test_alarm_callback, NULL) < 0) { printf("fail to set alarm callback\n"); return -1; } while (flag == 0 && count ++ < 6) rte_delay_ms(RTE_TEST_CHECK_PERIOD); if (flag == 0){ printf("Callback not called\n"); return -1; } /* check if it will fail to set alarm with wrong us value */ printf("check if it will fail to set alarm with wrong ms values\n"); if (rte_eal_alarm_set(0, test_alarm_callback, NULL) >= 0) { printf("should not be successful with 0 us value\n"); return -1; } if (rte_eal_alarm_set(UINT64_MAX - 1, test_alarm_callback, NULL) >= 0) { printf("should not be successful with (UINT64_MAX-1) us value\n"); return -1; } /* check if it will fail to set alarm with null callback parameter */ printf("check if it will fail to set alarm with null callback parameter\n"); if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT, NULL, NULL) >= 0) { printf("should not be successful to set alarm with null callback parameter\n"); return -1; } /* check if it will fail to remove alarm with null callback parameter */ printf("check if it will fail to remove alarm with null callback parameter\n"); if (rte_eal_alarm_cancel(NULL, NULL) == 0) { printf("should not be successful to remove alarm with null callback parameter"); return -1; } if (test_multi_alarms() != 0) return -1; return 0; } static struct test_command alarm_cmd = { .command = "alarm_autotest", .callback = test_alarm, }; REGISTER_TEST_COMMAND(alarm_cmd); ================================================ FILE: app/test/test_atomic.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Atomic Variables * ================ * * - The main test function performs three subtests. The first test * checks that the usual inc/dec/add/sub functions are working * correctly: * * - Initialize 16-bit, 32-bit and 64-bit atomic variables to specific * values. * * - These variables are incremented and decremented on each core at * the same time in ``test_atomic_usual()``. * * - The function checks that once all lcores finish their function, * the value of the atomic variables are still the same. * * - The second test verifies the behavior of "test and set" functions. * * - Initialize 16-bit, 32-bit and 64-bit atomic variables to zero. * * - Invoke ``test_atomic_tas()`` on each lcore: before doing anything * else. The cores are waiting a synchro using ``while * (rte_atomic32_read(&val) == 0)`` which is triggered by the main test * function. Then all cores do a * ``rte_atomicXX_test_and_set()`` at the same time. If it is successful, * it increments another atomic counter. * * - The main function checks that the atomic counter was incremented * twice only (one for 16-bit, one for 32-bit and one for 64-bit values). * * - Test "add/sub and return" * * - Initialize 16-bit, 32-bit and 64-bit atomic variables to zero. * * - Invoke ``test_atomic_addsub_return()`` on each lcore. Before doing * anything else, the cores are waiting a synchro. Each lcore does * this operation several times:: * * tmp = rte_atomicXX_add_return(&a, 1); * atomic_add(&count, tmp); * tmp = rte_atomicXX_sub_return(&a, 1); * atomic_sub(&count, tmp+1); * * - At the end of the test, the *count* value must be 0. */ #define NUM_ATOMIC_TYPES 3 #define N 10000 static rte_atomic16_t a16; static rte_atomic32_t a32; static rte_atomic64_t a64; static rte_atomic64_t count; static rte_atomic32_t synchro; static int test_atomic_usual(__attribute__((unused)) void *arg) { unsigned i; while (rte_atomic32_read(&synchro) == 0) ; for (i = 0; i < N; i++) rte_atomic16_inc(&a16); for (i = 0; i < N; i++) rte_atomic16_dec(&a16); for (i = 0; i < (N / 5); i++) rte_atomic16_add(&a16, 5); for (i = 0; i < (N / 5); i++) rte_atomic16_sub(&a16, 5); for (i = 0; i < N; i++) rte_atomic32_inc(&a32); for (i = 0; i < N; i++) rte_atomic32_dec(&a32); for (i = 0; i < (N / 5); i++) rte_atomic32_add(&a32, 5); for (i = 0; i < (N / 5); i++) rte_atomic32_sub(&a32, 5); for (i = 0; i < N; i++) rte_atomic64_inc(&a64); for (i = 0; i < N; i++) rte_atomic64_dec(&a64); for (i = 0; i < (N / 5); i++) rte_atomic64_add(&a64, 5); for (i = 0; i < (N / 5); i++) rte_atomic64_sub(&a64, 5); return 0; } static int test_atomic_tas(__attribute__((unused)) void *arg) { while (rte_atomic32_read(&synchro) == 0) ; if (rte_atomic16_test_and_set(&a16)) rte_atomic64_inc(&count); if (rte_atomic32_test_and_set(&a32)) rte_atomic64_inc(&count); if (rte_atomic64_test_and_set(&a64)) rte_atomic64_inc(&count); return 0; } static int test_atomic_addsub_and_return(__attribute__((unused)) void *arg) { uint32_t tmp16; uint32_t tmp32; uint64_t tmp64; unsigned i; while (rte_atomic32_read(&synchro) == 0) ; for (i = 0; i < N; i++) { tmp16 = rte_atomic16_add_return(&a16, 1); rte_atomic64_add(&count, tmp16); tmp16 = rte_atomic16_sub_return(&a16, 1); rte_atomic64_sub(&count, tmp16+1); tmp32 = rte_atomic32_add_return(&a32, 1); rte_atomic64_add(&count, tmp32); tmp32 = rte_atomic32_sub_return(&a32, 1); rte_atomic64_sub(&count, tmp32+1); tmp64 = rte_atomic64_add_return(&a64, 1); rte_atomic64_add(&count, tmp64); tmp64 = rte_atomic64_sub_return(&a64, 1); rte_atomic64_sub(&count, tmp64+1); } return 0; } /* * rte_atomic32_inc_and_test() would increase a 32 bits counter by one and then * test if that counter is equal to 0. It would return true if the counter is 0 * and false if the counter is not 0. rte_atomic64_inc_and_test() could do the * same thing but for a 64 bits counter. * Here checks that if the 32/64 bits counter is equal to 0 after being atomically * increased by one. If it is, increase the variable of "count" by one which would * be checked as the result later. * */ static int test_atomic_inc_and_test(__attribute__((unused)) void *arg) { while (rte_atomic32_read(&synchro) == 0) ; if (rte_atomic16_inc_and_test(&a16)) { rte_atomic64_inc(&count); } if (rte_atomic32_inc_and_test(&a32)) { rte_atomic64_inc(&count); } if (rte_atomic64_inc_and_test(&a64)) { rte_atomic64_inc(&count); } return 0; } /* * rte_atomicXX_dec_and_test() should decrease a 32 bits counter by one and then * test if that counter is equal to 0. It should return true if the counter is 0 * and false if the counter is not 0. * This test checks if the counter is equal to 0 after being atomically * decreased by one. If it is, increase the value of "count" by one which is to * be checked as the result later. */ static int test_atomic_dec_and_test(__attribute__((unused)) void *arg) { while (rte_atomic32_read(&synchro) == 0) ; if (rte_atomic16_dec_and_test(&a16)) rte_atomic64_inc(&count); if (rte_atomic32_dec_and_test(&a32)) rte_atomic64_inc(&count); if (rte_atomic64_dec_and_test(&a64)) rte_atomic64_inc(&count); return 0; } static int test_atomic(void) { rte_atomic16_init(&a16); rte_atomic32_init(&a32); rte_atomic64_init(&a64); rte_atomic64_init(&count); rte_atomic32_init(&synchro); rte_atomic16_set(&a16, 1UL << 10); rte_atomic32_set(&a32, 1UL << 10); rte_atomic64_set(&a64, 1ULL << 33); printf("usual inc/dec/add/sub functions\n"); rte_eal_mp_remote_launch(test_atomic_usual, NULL, SKIP_MASTER); rte_atomic32_set(&synchro, 1); rte_eal_mp_wait_lcore(); rte_atomic32_set(&synchro, 0); if (rte_atomic16_read(&a16) != 1UL << 10) { printf("Atomic16 usual functions failed\n"); return -1; } if (rte_atomic32_read(&a32) != 1UL << 10) { printf("Atomic32 usual functions failed\n"); return -1; } if (rte_atomic64_read(&a64) != 1ULL << 33) { printf("Atomic64 usual functions failed\n"); return -1; } printf("test and set\n"); rte_atomic64_set(&a64, 0); rte_atomic32_set(&a32, 0); rte_atomic16_set(&a16, 0); rte_atomic64_set(&count, 0); rte_eal_mp_remote_launch(test_atomic_tas, NULL, SKIP_MASTER); rte_atomic32_set(&synchro, 1); rte_eal_mp_wait_lcore(); rte_atomic32_set(&synchro, 0); if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) { printf("Atomic test and set failed\n"); return -1; } printf("add/sub and return\n"); rte_atomic64_set(&a64, 0); rte_atomic32_set(&a32, 0); rte_atomic16_set(&a16, 0); rte_atomic64_set(&count, 0); rte_eal_mp_remote_launch(test_atomic_addsub_and_return, NULL, SKIP_MASTER); rte_atomic32_set(&synchro, 1); rte_eal_mp_wait_lcore(); rte_atomic32_set(&synchro, 0); if (rte_atomic64_read(&count) != 0) { printf("Atomic add/sub+return failed\n"); return -1; } /* * Set a64, a32 and a16 with the same value of minus "number of slave * lcores", launch all slave lcores to atomically increase by one and * test them respectively. * Each lcore should have only one chance to increase a64 by one and * then check if it is equal to 0, but there should be only one lcore * that finds that it is 0. It is similar for a32 and a16. * Then a variable of "count", initialized to zero, is increased by * one if a64, a32 or a16 is 0 after being increased and tested * atomically. * We can check if "count" is finally equal to 3 to see if all slave * lcores performed "atomic inc and test" right. */ printf("inc and test\n"); rte_atomic64_clear(&a64); rte_atomic32_clear(&a32); rte_atomic16_clear(&a16); rte_atomic32_clear(&synchro); rte_atomic64_clear(&count); rte_atomic64_set(&a64, (int64_t)(1 - (int64_t)rte_lcore_count())); rte_atomic32_set(&a32, (int32_t)(1 - (int32_t)rte_lcore_count())); rte_atomic16_set(&a16, (int16_t)(1 - (int16_t)rte_lcore_count())); rte_eal_mp_remote_launch(test_atomic_inc_and_test, NULL, SKIP_MASTER); rte_atomic32_set(&synchro, 1); rte_eal_mp_wait_lcore(); rte_atomic32_clear(&synchro); if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) { printf("Atomic inc and test failed %d\n", (int)count.cnt); return -1; } /* * Same as above, but this time we set the values to "number of slave * lcores", and decrement instead of increment. */ printf("dec and test\n"); rte_atomic32_clear(&synchro); rte_atomic64_clear(&count); rte_atomic64_set(&a64, (int64_t)(rte_lcore_count() - 1)); rte_atomic32_set(&a32, (int32_t)(rte_lcore_count() - 1)); rte_atomic16_set(&a16, (int16_t)(rte_lcore_count() - 1)); rte_eal_mp_remote_launch(test_atomic_dec_and_test, NULL, SKIP_MASTER); rte_atomic32_set(&synchro, 1); rte_eal_mp_wait_lcore(); rte_atomic32_clear(&synchro); if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) { printf("Atomic dec and test failed\n"); return -1; } return 0; } static struct test_command atomic_cmd = { .command = "atomic_autotest", .callback = test_atomic, }; REGISTER_TEST_COMMAND(atomic_cmd); ================================================ FILE: app/test/test_byteorder.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" static volatile uint16_t u16 = 0x1337; static volatile uint32_t u32 = 0xdeadbeefUL; static volatile uint64_t u64 = 0xdeadcafebabefaceULL; /* * Byteorder functions * =================== * * - check that optimized byte swap functions are working for each * size (16, 32, 64 bits) */ static int test_byteorder(void) { uint16_t res_u16; uint32_t res_u32; uint64_t res_u64; res_u16 = rte_bswap16(u16); printf("%"PRIx16" -> %"PRIx16"\n", u16, res_u16); if (res_u16 != 0x3713) return -1; res_u32 = rte_bswap32(u32); printf("%"PRIx32" -> %"PRIx32"\n", u32, res_u32); if (res_u32 != 0xefbeaddeUL) return -1; res_u64 = rte_bswap64(u64); printf("%"PRIx64" -> %"PRIx64"\n", u64, res_u64); if (res_u64 != 0xcefabebafecaaddeULL) return -1; res_u16 = rte_bswap16(0x1337); printf("const %"PRIx16" -> %"PRIx16"\n", 0x1337, res_u16); if (res_u16 != 0x3713) return -1; res_u32 = rte_bswap32(0xdeadbeefUL); printf("const %"PRIx32" -> %"PRIx32"\n", (uint32_t) 0xdeadbeef, res_u32); if (res_u32 != 0xefbeaddeUL) return -1; res_u64 = rte_bswap64(0xdeadcafebabefaceULL); printf("const %"PRIx64" -> %"PRIx64"\n", (uint64_t) 0xdeadcafebabefaceULL, res_u64); if (res_u64 != 0xcefabebafecaaddeULL) return -1; return 0; } static struct test_command byteorder_cmd = { .command = "byteorder_autotest", .callback = test_byteorder, }; REGISTER_TEST_COMMAND(byteorder_cmd); ================================================ FILE: app/test/test_cmdline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "test.h" #include "test_cmdline.h" static int test_cmdline(void) { printf("Testind parsing ethernet addresses...\n"); if (test_parse_etheraddr_valid() < 0) return -1; if (test_parse_etheraddr_invalid_data() < 0) return -1; if (test_parse_etheraddr_invalid_param() < 0) return -1; printf("Testind parsing port lists...\n"); if (test_parse_portlist_valid() < 0) return -1; if (test_parse_portlist_invalid_data() < 0) return -1; if (test_parse_portlist_invalid_param() < 0) return -1; printf("Testind parsing numbers...\n"); if (test_parse_num_valid() < 0) return -1; if (test_parse_num_invalid_data() < 0) return -1; if (test_parse_num_invalid_param() < 0) return -1; printf("Testing parsing IP addresses...\n"); if (test_parse_ipaddr_valid() < 0) return -1; if (test_parse_ipaddr_invalid_data() < 0) return -1; if (test_parse_ipaddr_invalid_param() < 0) return -1; printf("Testing parsing strings...\n"); if (test_parse_string_valid() < 0) return -1; if (test_parse_string_invalid_data() < 0) return -1; if (test_parse_string_invalid_param() < 0) return -1; printf("Testing circular buffer...\n"); if (test_cirbuf_char() < 0) return -1; if (test_cirbuf_string() < 0) return -1; if (test_cirbuf_align() < 0) return -1; if (test_cirbuf_invalid_param() < 0) return -1; printf("Testing library functions...\n"); if (test_cmdline_lib() < 0) return -1; return 0; } static struct test_command cmdline_cmd = { .command = "cmdline_autotest", .callback = test_cmdline, }; REGISTER_TEST_COMMAND(cmdline_cmd); ================================================ FILE: app/test/test_cmdline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TEST_CMDLINE_H_ #define TEST_CMDLINE_H_ #define CMDLINE_TEST_BUFSIZE 64 /* cmdline_parse_num tests */ int test_parse_num_valid(void); int test_parse_num_invalid_data(void); int test_parse_num_invalid_param(void); /* cmdline_parse_etheraddr tests */ int test_parse_etheraddr_valid(void); int test_parse_etheraddr_invalid_data(void); int test_parse_etheraddr_invalid_param(void); /* cmdline_parse_portlist tests */ int test_parse_portlist_valid(void); int test_parse_portlist_invalid_data(void); int test_parse_portlist_invalid_param(void); /* cmdline_parse_ipaddr tests */ int test_parse_ipaddr_valid(void); int test_parse_ipaddr_invalid_data(void); int test_parse_ipaddr_invalid_param(void); /* cmdline_parse_string tests */ int test_parse_string_valid(void); int test_parse_string_invalid_data(void); int test_parse_string_invalid_param(void); /* cmdline_cirbuf tests */ int test_cirbuf_invalid_param(void); int test_cirbuf_char(void); int test_cirbuf_string(void); int test_cirbuf_align(void); /* test the rest of the library */ int test_cmdline_lib(void); #endif /* TEST_CMDLINE_H_ */ ================================================ FILE: app/test/test_cmdline_cirbuf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test_cmdline.h" /* different length strings */ #define CIRBUF_STR_HEAD " HEAD" #define CIRBUF_STR_TAIL "TAIL" /* miscelaneous tests - they make bullseye happy */ static int test_cirbuf_string_misc(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* initialize buffers */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* * add strings to head and tail, but read only tail * this results in read operation that does not transcend * from buffer end to buffer beginning (in other words, * strlen <= cb->maxlen - cb->end) */ /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* add string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to add string to head!\n"); return -1; } /* read string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to get string from tail!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: tail strings do not match!\n"); return -1; } /* clear buffers */ memset(tmp, 0, sizeof(tmp)); memset(buf, 0, sizeof(buf)); /* * add a string to buffer when start/end is at end of buffer */ /* * reinitialize circular buffer with start at the end of cirbuf */ if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to add string to tail!\n"); return -1; } /* read string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to get string from tail!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: tail strings do not match!\n"); return -1; } /* clear tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* read string from tail */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to get string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { printf("Error: headstrings do not match!\n"); return -1; } return 0; } /* test adding and deleting strings */ static int test_cirbuf_string_add_del(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* initialize buffers */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* read string from head */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to get string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { printf("Error: head strings do not match!\n"); return -1; } /* clear tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* read string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to get string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) { printf("Error: head strings do not match!\n"); return -1; } /* delete string from head*/ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { printf("Error: failed to delete string from head!\n"); return -1; } /* verify string was deleted */ if (cirbuf_del_head_safe(&cb) == 0) { printf("Error: buffer should have been empty!\n"); return -1; } /* clear tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to add string to tail!\n"); return -1; } /* get string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to get string from tail!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: tail strings do not match!\n"); return -1; } /* clear tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* get string from head */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to get string from tail!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: tail strings do not match!\n"); return -1; } /* delete string from tail */ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to delete string from tail!\n"); return -1; } /* verify string was deleted */ if (cirbuf_del_tail_safe(&cb) == 0) { printf("Error: buffer should have been empty!\n"); return -1; } return 0; } /* test adding from head and deleting from tail, and vice versa */ static int test_cirbuf_string_add_del_reverse(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* initialize buffers */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* delete string from tail */ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) { printf("Error: failed to delete string from tail!\n"); return -1; } /* verify string was deleted */ if (cirbuf_del_tail_safe(&cb) == 0) { printf("Error: buffer should have been empty!\n"); return -1; } /* clear tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to add string to tail!\n"); return -1; } /* delete string from head */ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to delete string from head!\n"); return -1; } /* verify string was deleted */ if (cirbuf_del_head_safe(&cb) == 0) { printf("Error: buffer should have been empty!\n"); return -1; } return 0; } /* try to write more than available */ static int test_cirbuf_string_add_boundaries(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; unsigned i; /* initialize buffers */ memset(buf, 0, sizeof(buf)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* fill the buffer from tail */ for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++) cirbuf_add_tail_safe(&cb, 't'); /* try adding a string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > 0) { printf("Error: buffer should have been full!\n"); return -1; } /* try adding a string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) > 0) { printf("Error: buffer should have been full!\n"); return -1; } /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* fill the buffer from head */ for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++) cirbuf_add_head_safe(&cb, 'h'); /* try adding a string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > 0) { printf("Error: buffer should have been full!\n"); return -1; } /* try adding a string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) > 0) { printf("Error: buffer should have been full!\n"); return -1; } return 0; } /* try to read/delete more than written */ static int test_cirbuf_string_get_del_boundaries(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* initialize buffers */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* read more than written (head) */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) != sizeof(CIRBUF_STR_HEAD)) { printf("Error: unexpected result when reading too much data!\n"); return -1; } /* read more than written (tail) */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1) != sizeof(CIRBUF_STR_HEAD)) { printf("Error: unexpected result when reading too much data!\n"); return -1; } /* delete more than written (head) */ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { printf("Error: unexpected result when deleting too much data!\n"); return -1; } /* delete more than written (tail) */ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) { printf("Error: unexpected result when deleting too much data!\n"); return -1; } /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != (sizeof(CIRBUF_STR_TAIL))) { printf("Error: failed to add string to tail!\n"); return -1; } /* read more than written (tail) */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) != sizeof(CIRBUF_STR_TAIL)) { printf("Error: unexpected result when reading too much data!\n"); return -1; } /* read more than written (head) */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1) != sizeof(CIRBUF_STR_TAIL)) { printf("Error: unexpected result when reading too much data!\n"); return -1; } /* delete more than written (tail) */ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { printf("Error: unexpected result when deleting too much data!\n"); return -1; } /* delete more than written (head) */ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) { printf("Error: unexpected result when deleting too much data!\n"); return -1; } return 0; } /* try to read/delete less than written */ static int test_cirbuf_string_get_del_partial(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; char tmp2[CMDLINE_TEST_BUFSIZE]; /* initialize buffers */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); memset(tmp2, 0, sizeof(tmp)); snprintf(tmp2, sizeof(tmp2), "%s", CIRBUF_STR_HEAD); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* add string to head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != (sizeof(CIRBUF_STR_HEAD))) { printf("Error: failed to add string to head!\n"); return -1; } /* read less than written (head) */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) != sizeof(CIRBUF_STR_HEAD) - 1) { printf("Error: unexpected result when reading from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) { printf("Error: strings mismatch!\n"); return -1; } memset(tmp, 0, sizeof(tmp)); /* read less than written (tail) */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) != sizeof(CIRBUF_STR_HEAD) - 1) { printf("Error: unexpected result when reading from tail!\n"); return -1; } /* verify string */ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { printf("Error: strings mismatch!\n"); return -1; } /* * verify correct deletion */ /* clear buffer */ memset(tmp, 0, sizeof(tmp)); /* delete less than written (head) */ if (cirbuf_del_buf_head(&cb, 1) != 0) { printf("Error: delete from head failed!\n"); return -1; } /* read from head */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1) != sizeof(CIRBUF_STR_HEAD) - 1) { printf("Error: unexpected result when reading from head!\n"); return -1; } /* since we deleted from head, first char should be deleted */ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) { printf("Error: strings mismatch!\n"); return -1; } /* clear buffer */ memset(tmp, 0, sizeof(tmp)); /* delete less than written (tail) */ if (cirbuf_del_buf_tail(&cb, 1) != 0) { printf("Error: delete from tail failed!\n"); return -1; } /* read from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2) != sizeof(CIRBUF_STR_HEAD) - 2) { printf("Error: unexpected result when reading from head!\n"); return -1; } /* since we deleted from tail, last char should be deleted */ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) { printf("Error: strings mismatch!\n"); return -1; } return 0; } /* test cmdline_cirbuf char add/del functions */ static int test_cirbuf_char_add_del(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; /* clear buffer */ memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* * try to delete something from cirbuf. since it's empty, * these should fail. */ if (cirbuf_del_head_safe(&cb) == 0) { printf("Error: deleting from empty cirbuf head succeeded!\n"); return -1; } if (cirbuf_del_tail_safe(&cb) == 0) { printf("Error: deleting from empty cirbuf tail succeeded!\n"); return -1; } /* * add, verify and delete. these should pass. */ if (cirbuf_add_head_safe(&cb,'h') < 0) { printf("Error: adding to cirbuf head failed!\n"); return -1; } if (cirbuf_get_head(&cb) != 'h') { printf("Error: wrong head content!\n"); return -1; } if (cirbuf_del_head_safe(&cb) < 0) { printf("Error: deleting from cirbuf head failed!\n"); return -1; } if (cirbuf_add_tail_safe(&cb,'t') < 0) { printf("Error: adding to cirbuf tail failed!\n"); return -1; } if (cirbuf_get_tail(&cb) != 't') { printf("Error: wrong tail content!\n"); return -1; } if (cirbuf_del_tail_safe(&cb) < 0) { printf("Error: deleting from cirbuf tail failed!\n"); return -1; } /* do the same for unsafe versions. those are void. */ cirbuf_add_head(&cb,'h'); if (cirbuf_get_head(&cb) != 'h') { printf("Error: wrong head content!\n"); return -1; } cirbuf_del_head(&cb); /* test if char has been deleted. we can't call cirbuf_get_head * because it's unsafe, but we can call cirbuf_get_buf_head. */ if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) { printf("Error: buffer should have been empty!\n"); return -1; } cirbuf_add_tail(&cb,'t'); if (cirbuf_get_tail(&cb) != 't') { printf("Error: wrong tail content!\n"); return -1; } cirbuf_del_tail(&cb); /* test if char has been deleted. we can't call cirbuf_get_tail * because it's unsafe, but we can call cirbuf_get_buf_tail. */ if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) { printf("Error: buffer should have been empty!\n"); return -1; } return 0; } /* test filling up buffer with chars */ static int test_cirbuf_char_fill(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; unsigned i; /* clear buffer */ memset(buf, 0, sizeof(buf)); /* * initialize circular buffer */ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* * fill the buffer from head or tail, verify contents, test boundaries * and clear the buffer */ /* fill the buffer from tail */ for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) cirbuf_add_tail_safe(&cb, 't'); /* verify that contents of the buffer are what they are supposed to be */ for (i = 0; i < sizeof(buf); i++) { if (buf[i] != 't') { printf("Error: wrong content in buffer!\n"); return -1; } } /* try to add to a full buffer from tail */ if (cirbuf_add_tail_safe(&cb, 't') == 0) { printf("Error: buffer should have been full!\n"); return -1; } /* try to add to a full buffer from head */ if (cirbuf_add_head_safe(&cb, 'h') == 0) { printf("Error: buffer should have been full!\n"); return -1; } /* delete buffer from tail */ for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) cirbuf_del_tail_safe(&cb); /* try to delete from an empty buffer */ if (cirbuf_del_tail_safe(&cb) >= 0) { printf("Error: buffer should have been empty!\n"); return -1; } /* fill the buffer from head */ for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++) cirbuf_add_head_safe(&cb, 'h'); /* verify that contents of the buffer are what they are supposed to be */ for (i = 0; i < sizeof(buf); i++) { if (buf[i] != 'h') { printf("Error: wrong content in buffer!\n"); return -1; } } /* try to add to a full buffer from head */ if (cirbuf_add_head_safe(&cb,'h') >= 0) { printf("Error: buffer should have been full!\n"); return -1; } /* try to add to a full buffer from tail */ if (cirbuf_add_tail_safe(&cb, 't') == 0) { printf("Error: buffer should have been full!\n"); return -1; } /* delete buffer from head */ for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++) cirbuf_del_head_safe(&cb); /* try to delete from an empty buffer */ if (cirbuf_del_head_safe(&cb) >= 0) { printf("Error: buffer should have been empty!\n"); return -1; } /* * fill the buffer from both head and tail, with alternating characters, * verify contents and clear the buffer */ /* fill half of buffer from tail */ for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T')); /* fill other half of the buffer from head */ for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++) cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */ /* verify that contents of the buffer are what they are supposed to be */ for (i = 0; i < sizeof(buf) / 2; i++) { if (buf[i] != (char) (i % 2 ? 't' : 'T')) { printf("Error: wrong content in buffer at %u!\n", i); return -1; } } for (i = sizeof(buf) / 2; i < sizeof(buf); i++) { if (buf[i] != (char) (i % 2 ? 'h' : 'H')) { printf("Error: wrong content in buffer %u!\n", i); return -1; } } return 0; } /* test left alignment */ static int test_cirbuf_align_left(void) { #define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2 #define SMALL_OFFSET HALF_OFFSET / 2 /* resulting buffer lengths for each of the test cases */ #define LEN1 HALF_OFFSET - SMALL_OFFSET - 1 #define LEN2 HALF_OFFSET + SMALL_OFFSET + 2 #define LEN3 HALF_OFFSET - SMALL_OFFSET #define LEN4 HALF_OFFSET + SMALL_OFFSET - 1 struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; unsigned i; /* * align left when start < end and start in left half */ /* * initialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* push end into left half */ for (i = 0; i < HALF_OFFSET - 1; i++) cirbuf_add_tail_safe(&cb, 't'); /* push start into left half < end */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_del_head_safe(&cb); /* align */ if (cirbuf_align_left(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* verify result */ if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) { printf("Error: buffer alignment is wrong!\n"); return -1; } /* * align left when start > end and start in left half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into left half */ for (i = 0; i < HALF_OFFSET + 2; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half > start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_add_tail_safe(&cb, 't'); /* align */ if (cirbuf_align_left(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* verify result */ if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) { printf("Error: buffer alignment is wrong!"); return -1; } /* * align left when start < end and start in right half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into the right half */ for (i = 0; i < HALF_OFFSET; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half > start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_del_tail_safe(&cb); /* align */ if (cirbuf_align_left(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* verify result */ if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) { printf("Error: buffer alignment is wrong!"); return -1; } /* * align left when start > end and start in right half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into the right half */ for (i = 0; i < HALF_OFFSET - 1; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half < start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_add_tail_safe(&cb, 't'); /* align */ if (cirbuf_align_left(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* verify result */ if (cb.start != 0 || cb.len != LEN4 || cb.end != cb.len - 1) { printf("Error: buffer alignment is wrong!"); return -1; } /* * Verify that alignment doesn't corrupt data */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail and head */ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to add strings!\n"); return -1; } /* align */ if (cirbuf_align_left(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* get string from head */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to read string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: strings mismatch!\n"); return -1; } /* reset tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* get string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to read string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: strings mismatch!\n"); return -1; } return 0; } /* test right alignment */ static int test_cirbuf_align_right(void) { #define END_OFFSET CMDLINE_TEST_BUFSIZE - 1 struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; char tmp[CMDLINE_TEST_BUFSIZE]; unsigned i; /* * align right when start < end and start in left half */ /* * initialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to initialize circular buffer!\n"); return -1; } /* push end into left half */ for (i = 0; i < HALF_OFFSET - 1; i++) cirbuf_add_tail_safe(&cb, 't'); /* push start into left half < end */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_del_head_safe(&cb); /* align */ cirbuf_align_right(&cb); /* verify result */ if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) { printf("Error: buffer alignment is wrong!\n"); return -1; } /* * align right when start > end and start in left half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into left half */ for (i = 0; i < HALF_OFFSET + 2; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half > start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_add_tail_safe(&cb, 't'); /* align */ cirbuf_align_right(&cb); /* verify result */ if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) { printf("Error: buffer alignment is wrong!"); return -1; } /* * align right when start < end and start in right half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into the right half */ for (i = 0; i < HALF_OFFSET; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half > start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_del_tail_safe(&cb); /* align */ cirbuf_align_right(&cb); /* verify result */ if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) { printf("Error: buffer alignment is wrong!"); return -1; } /* * align right when start > end and start in right half */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* push start into the right half */ for (i = 0; i < HALF_OFFSET - 1; i++) cirbuf_add_head_safe(&cb, 'h'); /* push end into left half < start */ for (i = 0; i < SMALL_OFFSET; i++) cirbuf_add_tail_safe(&cb, 't'); /* align */ cirbuf_align_right(&cb); /* verify result */ if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) { printf("Error: buffer alignment is wrong!"); return -1; } /* * Verify that alignment doesn't corrupt data */ /* * reinitialize circular buffer */ memset(buf, 0, sizeof(buf)); if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) { printf("Error: failed to reinitialize circular buffer!\n"); return -1; } /* add string to tail and head */ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) { printf("Error: failed to add strings!\n"); return -1; } /* align */ if (cirbuf_align_right(&cb) < 0) { printf("Error: alignment failed!\n"); return -1; } /* get string from head */ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to read string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: strings mismatch!\n"); return -1; } /* reset tmp buffer */ memset(tmp, 0, sizeof(tmp)); /* get string from tail */ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) { printf("Error: failed to read string from head!\n"); return -1; } /* verify string */ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) { printf("Error: strings mismatch!\n"); return -1; } return 0; } /* call functions with invalid parameters */ int test_cirbuf_invalid_param(void) { struct cirbuf cb; char buf[CMDLINE_TEST_BUFSIZE]; /* null cirbuf */ if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0) return -1; /* null buffer */ if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0) return -1; /* null cirbuf */ if (cirbuf_add_head_safe(0, 'h') == 0) return -1; if (cirbuf_add_tail_safe(0, 't') == 0) return -1; if (cirbuf_del_head_safe(0) == 0) return -1; if (cirbuf_del_tail_safe(0) == 0) return -1; /* null buffer */ if (cirbuf_add_buf_head(&cb, 0, 0) == 0) return -1; if (cirbuf_add_buf_tail(&cb, 0, 0) == 0) return -1; /* null cirbuf */ if (cirbuf_add_buf_head(0, buf, 0) == 0) return -1; if (cirbuf_add_buf_tail(0, buf, 0) == 0) return -1; /* null size */ if (cirbuf_add_buf_head(&cb, buf, 0) == 0) return -1; if (cirbuf_add_buf_tail(&cb, buf, 0) == 0) return -1; /* null cirbuf */ if (cirbuf_del_buf_head(0, 0) == 0) return -1; if (cirbuf_del_buf_tail(0, 0) == 0) return -1; /* null size */ if (cirbuf_del_buf_head(&cb, 0) == 0) return -1; if (cirbuf_del_buf_tail(&cb, 0) == 0) return -1; /* null cirbuf */ if (cirbuf_get_buf_head(0, 0, 0) == 0) return -1; if (cirbuf_get_buf_tail(0, 0, 0) == 0) return -1; /* null buffer */ if (cirbuf_get_buf_head(&cb, 0, 0) == 0) return -1; if (cirbuf_get_buf_tail(&cb, 0, 0) == 0) return -1; /* null size, this is valid but should return 0 */ if (cirbuf_get_buf_head(&cb, buf, 0) != 0) return -1; if (cirbuf_get_buf_tail(&cb, buf, 0) != 0) return -1; /* null cirbuf */ if (cirbuf_align_left(0) == 0) return -1; if (cirbuf_align_right(0) == 0) return -1; return 0; } /* test cmdline_cirbuf char functions */ int test_cirbuf_char(void) { int ret; ret = test_cirbuf_char_add_del(); if (ret < 0) return -1; ret = test_cirbuf_char_fill(); if (ret < 0) return -1; return 0; } /* test cmdline_cirbuf string functions */ int test_cirbuf_string(void) { if (test_cirbuf_string_add_del() < 0) return -1; if (test_cirbuf_string_add_del_reverse() < 0) return -1; if (test_cirbuf_string_add_boundaries() < 0) return -1; if (test_cirbuf_string_get_del_boundaries() < 0) return -1; if (test_cirbuf_string_get_del_partial() < 0) return -1; if (test_cirbuf_string_misc() < 0) return -1; return 0; } /* test cmdline_cirbuf align functions */ int test_cirbuf_align(void) { if (test_cirbuf_align_left() < 0) return -1; if (test_cirbuf_align_right() < 0) return -1; return 0; } ================================================ FILE: app/test/test_cmdline_etheraddr.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "test_cmdline.h" struct ether_addr_str { const char * str; uint64_t address; }; /* valid strings */ const struct ether_addr_str ether_addr_valid_strs[] = { {"01:23:45:67:89:AB", 0xAB8967452301ULL}, {"4567:89AB:CDEF", 0xEFCDAB896745ULL}, }; /* valid strings with various garbage at the end. * these strings are still valid because parser checks for * end of token, which is either space chars, null char or * a hash sign. */ const char * ether_addr_garbage_strs[] = { "00:11:22:33:44:55\0garbage", "00:11:22:33:44:55#garbage", "00:11:22:33:44:55 garbage", "00:11:22:33:44:55\tgarbage", "00:11:22:33:44:55\ngarbage", "00:11:22:33:44:55\rgarbage", "00:11:22:33:44:55#", "00:11:22:33:44:55 ", "00:11:22:33:44:55\t", "00:11:22:33:44:55\n", "00:11:22:33:44:55\r", }; #define GARBAGE_ETHERADDR 0x554433221100ULL /* corresponding address */ const char * ether_addr_invalid_strs[] = { /* valid chars, invalid syntax */ "0123:45:67:89:AB", "01:23:4567:89:AB", "01:23:45:67:89AB", "012:345:678:9AB", "01:23:45:67:89:ABC", "01:23:45:67:89:A", "01:23:45:67:89", "01:23:45:67:89:AB:CD", /* invalid chars, valid syntax */ "IN:VA:LI:DC:HA:RS", "INVA:LIDC:HARS", /* misc */ "01 23 45 67 89 AB", "01.23.45.67.89.AB", "01,23,45,67,89,AB", "01:23:45\0:67:89:AB", "01:23:45#:67:89:AB", "random invalid text", "random text", "", "\0", " ", }; #define ETHERADDR_VALID_STRS_SIZE \ (sizeof(ether_addr_valid_strs) / sizeof(ether_addr_valid_strs[0])) #define ETHERADDR_GARBAGE_STRS_SIZE \ (sizeof(ether_addr_garbage_strs) / sizeof(ether_addr_garbage_strs[0])) #define ETHERADDR_INVALID_STRS_SIZE \ (sizeof(ether_addr_invalid_strs) / sizeof(ether_addr_invalid_strs[0])) static int is_addr_different(const struct ether_addr addr, uint64_t num) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++, num >>= 8) if (addr.addr_bytes[i] != (num & 0xFF)) { return 1; } return 0; } /* test invalid parameters */ int test_parse_etheraddr_invalid_param(void) { char buf[CMDLINE_TEST_BUFSIZE]; struct ether_addr result; int ret = 0; /* try all null */ ret = cmdline_parse_etheraddr(NULL, NULL, NULL, 0); if (ret != -1) { printf("Error: parser accepted null parameters!\n"); return -1; } /* try null buf */ ret = cmdline_parse_etheraddr(NULL, NULL, (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parser accepted null string!\n"); return -1; } /* try null result */ /* copy string to buffer */ snprintf(buf, sizeof(buf), "%s", ether_addr_valid_strs[0].str); ret = cmdline_parse_etheraddr(NULL, buf, NULL, 0); if (ret == -1) { printf("Error: parser rejected null result!\n"); return -1; } /* token is not used in ether_parse anyway so there's no point in * testing it */ /* test help function */ memset(&buf, 0, sizeof(buf)); /* coverage! */ ret = cmdline_get_help_etheraddr(NULL, buf, sizeof(buf)); if (ret < 0) { printf("Error: help function failed with valid parameters!\n"); return -1; } return 0; } /* test valid parameters but invalid data */ int test_parse_etheraddr_invalid_data(void) { int ret = 0; unsigned i; struct ether_addr result; /* test full strings */ for (i = 0; i < ETHERADDR_INVALID_STRS_SIZE; i++) { memset(&result, 0, sizeof(struct ether_addr)); ret = cmdline_parse_etheraddr(NULL, ether_addr_invalid_strs[i], (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parsing %s succeeded!\n", ether_addr_invalid_strs[i]); return -1; } } return 0; } /* test valid parameters and data */ int test_parse_etheraddr_valid(void) { int ret = 0; unsigned i; struct ether_addr result; /* test full strings */ for (i = 0; i < ETHERADDR_VALID_STRS_SIZE; i++) { memset(&result, 0, sizeof(struct ether_addr)); ret = cmdline_parse_etheraddr(NULL, ether_addr_valid_strs[i].str, (void*)&result, sizeof(result)); if (ret < 0) { printf("Error: parsing %s failed!\n", ether_addr_valid_strs[i].str); return -1; } if (is_addr_different(result, ether_addr_valid_strs[i].address)) { printf("Error: parsing %s failed: address mismatch!\n", ether_addr_valid_strs[i].str); return -1; } } /* test garbage strings */ for (i = 0; i < ETHERADDR_GARBAGE_STRS_SIZE; i++) { memset(&result, 0, sizeof(struct ether_addr)); ret = cmdline_parse_etheraddr(NULL, ether_addr_garbage_strs[i], (void*)&result, sizeof(result)); if (ret < 0) { printf("Error: parsing %s failed!\n", ether_addr_garbage_strs[i]); return -1; } if (is_addr_different(result, GARBAGE_ETHERADDR)) { printf("Error: parsing %s failed: address mismatch!\n", ether_addr_garbage_strs[i]); return -1; } } return 0; } ================================================ FILE: app/test/test_cmdline_ipaddr.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #ifndef __linux__ #ifndef __FreeBSD__ #include #else #include #endif #endif #include #include #include #include "test_cmdline.h" #define IP4(a,b,c,d) {((uint32_t)(((a) & 0xff)) | \ (((b) & 0xff) << 8) | \ (((c) & 0xff) << 16) | \ ((d) & 0xff) << 24)} #define U16_SWAP(x) \ (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)) /* create IPv6 address, swapping bytes where needed */ #ifndef s6_addr16 # define s6_addr16 __u6_addr.__u6_addr16 #endif #define IP6(a,b,c,d,e,f,g,h) .ipv6 = \ {.s6_addr16 = \ {U16_SWAP(a),U16_SWAP(b),U16_SWAP(c),U16_SWAP(d),\ U16_SWAP(e),U16_SWAP(f),U16_SWAP(g),U16_SWAP(h)}} /** these are defined in netinet/in.h but not present in linux headers */ #ifndef NIPQUAD #define NIPQUAD_FMT "%u.%u.%u.%u" #define NIPQUAD(addr) \ (unsigned)((unsigned char *)&addr)[0], \ (unsigned)((unsigned char *)&addr)[1], \ (unsigned)((unsigned char *)&addr)[2], \ (unsigned)((unsigned char *)&addr)[3] #define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define NIP6(addr) \ (unsigned)((addr).s6_addr[0]), \ (unsigned)((addr).s6_addr[1]), \ (unsigned)((addr).s6_addr[2]), \ (unsigned)((addr).s6_addr[3]), \ (unsigned)((addr).s6_addr[4]), \ (unsigned)((addr).s6_addr[5]), \ (unsigned)((addr).s6_addr[6]), \ (unsigned)((addr).s6_addr[7]), \ (unsigned)((addr).s6_addr[8]), \ (unsigned)((addr).s6_addr[9]), \ (unsigned)((addr).s6_addr[10]), \ (unsigned)((addr).s6_addr[11]), \ (unsigned)((addr).s6_addr[12]), \ (unsigned)((addr).s6_addr[13]), \ (unsigned)((addr).s6_addr[14]), \ (unsigned)((addr).s6_addr[15]) #endif struct ipaddr_str { const char * str; cmdline_ipaddr_t addr; unsigned flags; }; const struct ipaddr_str ipaddr_valid_strs[] = { {"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0}, CMDLINE_IPADDR_V4}, {"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0}, CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, {"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24}, CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, {"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24}, CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, {"012.34.56.78/24", {AF_INET, {IP4(12,34,56,78)}, 24}, CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, {"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1}, CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK}, {"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0}, CMDLINE_IPADDR_V6}, {"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0}, CMDLINE_IPADDR_V6}, {"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, {"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, /* RFC5952 requests that only lowercase should be used */ {"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6, {IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)}, 0}, CMDLINE_IPADDR_V6}, {"1234::1234/64", {AF_INET6, {IP6(0x1234,0,0,0,0,0,0,0x1234)}, 64}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, {"1234::/64", {AF_INET6, {IP6(0x1234,0,0,0,0,0,0,0)}, 64}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, {"1:1::1/32", {AF_INET6, {IP6(1,1,0,0,0,0,0,1)}, 32}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, {"1:2:3:4::/64", {AF_INET6, {IP6(1,2,3,4,0,0,0,0)}, 64}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, {"::ffff:192.168.1.0/64", {AF_INET6, {IP6(0,0,0,0,0,0xFFFF,0xC0A8,0x100)}, 64}, CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK}, /* RFC5952 requests not using :: to skip one block of zeros*/ {"1::2:3:4:5:6:7", {AF_INET6, {IP6(1,0,2,3,4,5,6,7)}, 0}, CMDLINE_IPADDR_V6}, }; const char * ipaddr_garbage_addr4_strs[] = { /* IPv4 */ "192.168.1.0 garbage", "192.168.1.0\0garbage", "192.168.1.0#garbage", "192.168.1.0\tgarbage", "192.168.1.0\rgarbage", "192.168.1.0\ngarbage", }; #define IPv4_GARBAGE_ADDR IP4(192,168,1,0) const char * ipaddr_garbage_addr6_strs[] = { /* IPv6 */ "1:2:3:4::8 garbage", "1:2:3:4::8#garbage", "1:2:3:4::8\0garbage", "1:2:3:4::8\rgarbage", "1:2:3:4::8\ngarbage", "1:2:3:4::8\tgarbage", }; #define IPv6_GARBAGE_ADDR {IP6(1,2,3,4,0,0,0,8)} const char * ipaddr_garbage_network4_strs[] = { /* IPv4 */ "192.168.1.0/24 garbage", "192.168.1.0/24\0garbage", "192.168.1.0/24#garbage", "192.168.1.0/24\tgarbage", "192.168.1.0/24\rgarbage", "192.168.1.0/24\ngarbage", }; #define IPv4_GARBAGE_PREFIX 24 const char * ipaddr_garbage_network6_strs[] = { /* IPv6 */ "1:2:3:4::8/64 garbage", "1:2:3:4::8/64#garbage", "1:2:3:4::8/64\0garbage", "1:2:3:4::8/64\rgarbage", "1:2:3:4::8/64\ngarbage", "1:2:3:4::8/64\tgarbage", }; #define IPv6_GARBAGE_PREFIX 64 const char * ipaddr_invalid_strs[] = { /** IPv4 **/ /* invalid numbers */ "0.0.0.-1", "0.0.-1.0", "0.-1.0.0", "-1.0.0.0", "0.0.0.-1/24", "256.123.123.123", "255.256.123.123", "255.255.256.123", "255.255.255.256", "256.123.123.123/24", "255.256.123.123/24", "255.255.256.123/24", "255.255.255.256/24", /* invalid network mask */ "1.2.3.4/33", "1.2.3.4/33231313", "1.2.3.4/-1", "1.2.3.4/24/33", "1.2.3.4/24/-1", "1.2.3.4/24/", /* wrong format */ "1/24" "/24" "123.123.123", "123.123.123.", "123.123.123.123.", "123.123.123..123", "123.123.123.123.123", ".123.123.123", ".123.123.123.123", "123.123.123/24", "123.123.123./24", "123.123.123.123./24", "123.123.123..123/24", "123.123.123.123.123/24", ".123.123.123/24", ".123.123.123.123/24", /* invalid characters */ "123.123.123.12F", "123.123.12F.123", "123.12F.123.123", "12F.123.123.123", "12J.123.123.123", "123,123,123,123", "123!123!123!12F", "123.123.123.123/4F", /** IPv6 **/ /* wrong format */ "::fffff", "ffff:", "1:2:3:4:5:6:7:192.168.1.1", "1234:192.168.1.1:ffff::", "1:2:3:4:5:6:7:890ab", "1:2:3:4:5:6:7890a:b", "1:2:3:4:5:67890:a:b", "1:2:3:4:56789:0:a:b", "1:2:3:45678:9:0:a:b", "1:2:34567:8:9:0:a:b", "1:23456:7:8:9:0:a:b", "12345:6:7:8:9:0:a:b", "1:::2", "1::::2", "::fffff/64", "1::2::3", "1::2::3/64", ":1:2", ":1:2/64", ":1::2", ":1::2/64", "1::2:3:4:5:6:7:8/64", /* invalid network mask */ "1:2:3:4:5:6:7:8/129", "1:2:3:4:5:6:7:8/-1", /* invalid characters */ "a:b:c:d:e:f:g::", /** misc **/ /* too long */ "1234:1234:1234:1234:1234:1234:1234:1234:1234:1234:1234" "random invalid text", "", "\0", " ", }; #define IPADDR_VALID_STRS_SIZE \ (sizeof(ipaddr_valid_strs) / sizeof(ipaddr_valid_strs[0])) #define IPADDR_GARBAGE_ADDR4_STRS_SIZE \ (sizeof(ipaddr_garbage_addr4_strs) / sizeof(ipaddr_garbage_addr4_strs[0])) #define IPADDR_GARBAGE_ADDR6_STRS_SIZE \ (sizeof(ipaddr_garbage_addr6_strs) / sizeof(ipaddr_garbage_addr6_strs[0])) #define IPADDR_GARBAGE_NETWORK4_STRS_SIZE \ (sizeof(ipaddr_garbage_network4_strs) / sizeof(ipaddr_garbage_network4_strs[0])) #define IPADDR_GARBAGE_NETWORK6_STRS_SIZE \ (sizeof(ipaddr_garbage_network6_strs) / sizeof(ipaddr_garbage_network6_strs[0])) #define IPADDR_INVALID_STRS_SIZE \ (sizeof(ipaddr_invalid_strs) / sizeof(ipaddr_invalid_strs[0])) static void dump_addr(cmdline_ipaddr_t addr) { switch (addr.family) { case AF_INET: { printf(NIPQUAD_FMT " prefixlen=%u\n", NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen); break; } case AF_INET6: { printf(NIP6_FMT " prefixlen=%u\n", NIP6(addr.addr.ipv6), addr.prefixlen); break; } default: printf("Can't dump: unknown address family.\n"); return; } } static int is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2) { if (addr1.family != addr2.family) return 1; if (addr1.prefixlen != addr2.prefixlen) return 1; switch (addr1.family) { /* IPv4 */ case AF_INET: if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4, sizeof(struct in_addr)) != 0) return 1; break; /* IPv6 */ case AF_INET6: { if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6, sizeof(struct in6_addr)) != 0) return 1; break; } /* thing that should not be */ default: return -1; } return 0; } static int can_parse_addr(unsigned addr_flags, unsigned test_flags) { if ((test_flags & addr_flags) == addr_flags) { /* if we are not trying to parse network addresses */ if (test_flags < CMDLINE_IPADDR_NETWORK) return 1; /* if this is a network address */ else if (addr_flags & CMDLINE_IPADDR_NETWORK) return 1; } return 0; } int test_parse_ipaddr_valid(void) { cmdline_parse_token_ipaddr_t token; char buf[CMDLINE_TEST_BUFSIZE]; cmdline_ipaddr_t result; unsigned i; uint8_t flags; int ret; /* cover all cases in help */ for (flags = 0x1; flags < 0x8; flags++) { token.ipaddr_data.flags = flags; memset(buf, 0, sizeof(buf)); if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)) == -1) { printf("Error: help rejected valid parameters!\n"); return -1; } } /* test valid strings */ for (i = 0; i < IPADDR_VALID_STRS_SIZE; i++) { /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&result, 0, sizeof(result)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_valid_strs[i].str, (void*)&result, sizeof(result)); /* if should have passed, or should have failed */ if ((ret < 0) == (can_parse_addr(ipaddr_valid_strs[i].flags, flags))) { printf("Error: unexpected behavior when parsing %s as %s!\n", ipaddr_valid_strs[i].str, buf); printf("Parsed result: "); dump_addr(result); printf("Expected result: "); dump_addr(ipaddr_valid_strs[i].addr); return -1; } if (ret != -1 && is_addr_different(result, ipaddr_valid_strs[i].addr)) { printf("Error: result mismatch when parsing %s as %s!\n", ipaddr_valid_strs[i].str, buf); printf("Parsed result: "); dump_addr(result); printf("Expected result: "); dump_addr(ipaddr_valid_strs[i].addr); return -1; } } } /* test garbage ipv4 address strings */ for (i = 0; i < IPADDR_GARBAGE_ADDR4_STRS_SIZE; i++) { struct in_addr tmp = IPv4_GARBAGE_ADDR; /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&result, 0, sizeof(result)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_garbage_addr4_strs[i], (void*)&result, sizeof(result)); /* if should have passed, or should have failed */ if ((ret < 0) == (can_parse_addr(CMDLINE_IPADDR_V4, flags))) { printf("Error: unexpected behavior when parsing %s as %s!\n", ipaddr_garbage_addr4_strs[i], buf); return -1; } if (ret != -1 && memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { printf("Error: result mismatch when parsing %s as %s!\n", ipaddr_garbage_addr4_strs[i], buf); return -1; } } } /* test garbage ipv6 address strings */ for (i = 0; i < IPADDR_GARBAGE_ADDR6_STRS_SIZE; i++) { cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&result, 0, sizeof(result)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_garbage_addr6_strs[i], (void*)&result, sizeof(result)); /* if should have passed, or should have failed */ if ((ret < 0) == (can_parse_addr(CMDLINE_IPADDR_V6, flags))) { printf("Error: unexpected behavior when parsing %s as %s!\n", ipaddr_garbage_addr6_strs[i], buf); return -1; } if (ret != -1 && memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { printf("Error: result mismatch when parsing %s as %s!\n", ipaddr_garbage_addr6_strs[i], buf); return -1; } } } /* test garbage ipv4 network strings */ for (i = 0; i < IPADDR_GARBAGE_NETWORK4_STRS_SIZE; i++) { struct in_addr tmp = IPv4_GARBAGE_ADDR; /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&result, 0, sizeof(result)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_garbage_network4_strs[i], (void*)&result, sizeof(result)); /* if should have passed, or should have failed */ if ((ret < 0) == (can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) { printf("Error: unexpected behavior when parsing %s as %s!\n", ipaddr_garbage_network4_strs[i], buf); return -1; } if (ret != -1 && memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) { printf("Error: result mismatch when parsing %s as %s!\n", ipaddr_garbage_network4_strs[i], buf); return -1; } } } /* test garbage ipv6 address strings */ for (i = 0; i < IPADDR_GARBAGE_NETWORK6_STRS_SIZE; i++) { cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR}; /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&result, 0, sizeof(result)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_garbage_network6_strs[i], (void*)&result, sizeof(result)); /* if should have passed, or should have failed */ if ((ret < 0) == (can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) { printf("Error: unexpected behavior when parsing %s as %s!\n", ipaddr_garbage_network6_strs[i], buf); return -1; } if (ret != -1 && memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) { printf("Error: result mismatch when parsing %s as %s!\n", ipaddr_garbage_network6_strs[i], buf); return -1; } } } return 0; } int test_parse_ipaddr_invalid_data(void) { cmdline_parse_token_ipaddr_t token; char buf[CMDLINE_TEST_BUFSIZE]; cmdline_ipaddr_t result; unsigned i; uint8_t flags; int ret; memset(&result, 0, sizeof(result)); /* test invalid strings */ for (i = 0; i < IPADDR_INVALID_STRS_SIZE; i++) { /* test each valid string against different flags */ for (flags = 1; flags < 0x8; flags++) { /* skip bad flag */ if (flags == CMDLINE_IPADDR_NETWORK) continue; /* clear out everything */ memset(buf, 0, sizeof(buf)); memset(&token, 0, sizeof(token)); token.ipaddr_data.flags = flags; cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, ipaddr_invalid_strs[i], (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parsing %s as %s succeeded!\n", ipaddr_invalid_strs[i], buf); printf("Parsed result: "); dump_addr(result); return -1; } } } return 0; } int test_parse_ipaddr_invalid_param(void) { cmdline_parse_token_ipaddr_t token; char buf[CMDLINE_TEST_BUFSIZE]; cmdline_ipaddr_t result; snprintf(buf, sizeof(buf), "1.2.3.4"); token.ipaddr_data.flags = CMDLINE_IPADDR_V4; /* null token */ if (cmdline_parse_ipaddr(NULL, buf, (void*)&result, sizeof(result)) != -1) { printf("Error: parser accepted invalid parameters!\n"); return -1; } /* null buffer */ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, NULL, (void*)&result, sizeof(result)) != -1) { printf("Error: parser accepted invalid parameters!\n"); return -1; } /* empty buffer */ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, "", (void*)&result, sizeof(result)) != -1) { printf("Error: parser accepted invalid parameters!\n"); return -1; } /* null result */ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) { printf("Error: parser rejected null result!\n"); return -1; } /* null token */ if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) { printf("Error: help accepted invalid parameters!\n"); return -1; } /* null buffer */ if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) { printf("Error: help accepted invalid parameters!\n"); return -1; } return 0; } ================================================ FILE: app/test/test_cmdline_lib.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test_cmdline.h" /****************************************************************/ /* static functions required for some tests */ static void valid_buffer(__attribute__((unused))struct rdline *rdl, __attribute__((unused))const char *buf, __attribute__((unused)) unsigned int size) { } static int complete_buffer(__attribute__((unused)) struct rdline *rdl, __attribute__((unused)) const char *buf, __attribute__((unused)) char *dstbuf, __attribute__((unused)) unsigned int dstsize, __attribute__((unused)) int *state) { return 0; } /****************************************************************/ static int test_cmdline_parse_fns(void) { struct cmdline cl; int i = 0; char dst[CMDLINE_TEST_BUFSIZE]; if (cmdline_parse(NULL, "buffer") >= 0) goto error; if (cmdline_parse(&cl, NULL) >= 0) goto error; if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0) goto error; if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0) goto error; if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0) goto error; if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0) goto error; return 0; error: printf("Error: function accepted null parameter!\n"); return -1; } static int test_cmdline_rdline_fns(void) { struct rdline rdl; rdline_write_char_t *wc = &cmdline_write_char; rdline_validate_t *v = &valid_buffer; rdline_complete_t *c = &complete_buffer; if (rdline_init(NULL, wc, v, c) >= 0) goto error; if (rdline_init(&rdl, NULL, v, c) >= 0) goto error; if (rdline_init(&rdl, wc, NULL, c) >= 0) goto error; if (rdline_init(&rdl, wc, v, NULL) >= 0) goto error; if (rdline_char_in(NULL, 0) >= 0) goto error; if (rdline_get_buffer(NULL) != NULL) goto error; if (rdline_add_history(NULL, "history") >= 0) goto error; if (rdline_add_history(&rdl, NULL) >= 0) goto error; if (rdline_get_history_item(NULL, 0) != NULL) goto error; /* void functions */ rdline_newline(NULL, "prompt"); rdline_newline(&rdl, NULL); rdline_stop(NULL); rdline_quit(NULL); rdline_restart(NULL); rdline_redisplay(NULL); rdline_reset(NULL); rdline_clear_history(NULL); return 0; error: printf("Error: function accepted null parameter!\n"); return -1; } static int test_cmdline_vt100_fns(void) { if (vt100_parser(NULL, 0) >= 0) { printf("Error: function accepted null parameter!\n"); return -1; } /* void functions */ vt100_init(NULL); return 0; } static int test_cmdline_socket_fns(void) { cmdline_parse_ctx_t ctx; if (cmdline_stdin_new(NULL, "prompt") != NULL) goto error; if (cmdline_stdin_new(&ctx, NULL) != NULL) goto error; if (cmdline_file_new(NULL, "prompt", "/dev/null") != NULL) goto error; if (cmdline_file_new(&ctx, NULL, "/dev/null") != NULL) goto error; if (cmdline_file_new(&ctx, "prompt", NULL) != NULL) goto error; if (cmdline_file_new(&ctx, "prompt", "-/invalid/~/path") != NULL) { printf("Error: succeeded in opening invalid file for reading!"); return -1; } if (cmdline_file_new(&ctx, "prompt", "/dev/null") == NULL) { printf("Error: failed to open /dev/null for reading!"); return -1; } /* void functions */ cmdline_stdin_exit(NULL); return 0; error: printf("Error: function accepted null parameter!\n"); return -1; } static int test_cmdline_fns(void) { cmdline_parse_ctx_t ctx; struct cmdline cl, *tmp; memset(&ctx, 0, sizeof(ctx)); tmp = cmdline_new(&ctx, "test", -1, -1); if (tmp == NULL) goto error; if (cmdline_new(NULL, "prompt", 0, 0) != NULL) goto error; if (cmdline_new(&ctx, NULL, 0, 0) != NULL) goto error; if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0) goto error; if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0) goto error; if (cmdline_write_char(NULL, 0) >= 0) goto error; /* void functions */ cmdline_set_prompt(NULL, "prompt"); cmdline_free(NULL); cmdline_printf(NULL, "format"); /* this should fail as stream handles are invalid */ cmdline_printf(tmp, "format"); cmdline_interact(NULL); cmdline_quit(NULL); /* check if void calls change anything when they should fail */ cl = *tmp; cmdline_printf(&cl, NULL); if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; cmdline_set_prompt(&cl, NULL); if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE); if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch; cmdline_free(tmp); return 0; error: printf("Error: function accepted null parameter!\n"); return -1; mismatch: printf("Error: data changed!\n"); return -1; } /* test library functions. the point of these tests is not so much to test * functions' behaviour as it is to make sure there are no segfaults if * they are called with invalid parameters. */ int test_cmdline_lib(void) { if (test_cmdline_parse_fns() < 0) return -1; if (test_cmdline_rdline_fns() < 0) return -1; if (test_cmdline_vt100_fns() < 0) return -1; if (test_cmdline_socket_fns() < 0) return -1; if (test_cmdline_fns() < 0) return -1; return 0; } ================================================ FILE: app/test/test_cmdline_num.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "test_cmdline.h" struct num_unsigned_str { const char * str; uint64_t result; }; struct num_signed_str { const char * str; int64_t result; }; const struct num_unsigned_str num_valid_positive_strs[] = { /* decimal positive */ {"0", 0 }, {"127", INT8_MAX }, {"128", INT8_MAX + 1 }, {"255", UINT8_MAX }, {"256", UINT8_MAX + 1 }, {"32767", INT16_MAX }, {"32768", INT16_MAX + 1 }, {"65535", UINT16_MAX }, {"65536", UINT16_MAX + 1 }, {"2147483647", INT32_MAX }, {"2147483648", INT32_MAX + 1U }, {"4294967295", UINT32_MAX }, {"4294967296", UINT32_MAX + 1ULL }, {"9223372036854775807", INT64_MAX }, {"9223372036854775808", INT64_MAX + 1ULL}, {"18446744073709551615", UINT64_MAX }, /* hexadecimal (no leading zeroes) */ {"0x0", 0 }, {"0x7F", INT8_MAX }, {"0x80", INT8_MAX + 1 }, {"0xFF", UINT8_MAX }, {"0x100", UINT8_MAX + 1 }, {"0x7FFF", INT16_MAX }, {"0x8000", INT16_MAX + 1 }, {"0xFFFF", UINT16_MAX }, {"0x10000", UINT16_MAX + 1 }, {"0x7FFFFFFF", INT32_MAX }, {"0x80000000", INT32_MAX + 1U }, {"0xFFFFFFFF", UINT32_MAX }, {"0x100000000", UINT32_MAX + 1ULL }, {"0x7FFFFFFFFFFFFFFF", INT64_MAX }, {"0x8000000000000000", INT64_MAX + 1ULL}, {"0xFFFFFFFFFFFFFFFF", UINT64_MAX }, /* hexadecimal (with leading zeroes) */ {"0x00", 0 }, {"0x7F", INT8_MAX }, {"0x80", INT8_MAX + 1 }, {"0xFF", UINT8_MAX }, {"0x0100", UINT8_MAX + 1 }, {"0x7FFF", INT16_MAX }, {"0x8000", INT16_MAX + 1 }, {"0xFFFF", UINT16_MAX }, {"0x00010000", UINT16_MAX + 1 }, {"0x7FFFFFFF", INT32_MAX }, {"0x80000000", INT32_MAX + 1U }, {"0xFFFFFFFF", UINT32_MAX }, {"0x0000000100000000", UINT32_MAX + 1ULL }, {"0x7FFFFFFFFFFFFFFF", INT64_MAX }, {"0x8000000000000000", INT64_MAX + 1ULL}, {"0xFFFFFFFFFFFFFFFF", UINT64_MAX }, /* check all characters */ {"0x1234567890ABCDEF", 0x1234567890ABCDEFULL }, {"0x1234567890abcdef", 0x1234567890ABCDEFULL }, /* binary (no leading zeroes) */ {"0b0", 0 }, {"0b1111111", INT8_MAX }, {"0b10000000", INT8_MAX + 1 }, {"0b11111111", UINT8_MAX }, {"0b100000000", UINT8_MAX + 1 }, {"0b111111111111111", INT16_MAX }, {"0b1000000000000000", INT16_MAX + 1 }, {"0b1111111111111111", UINT16_MAX }, {"0b10000000000000000", UINT16_MAX + 1 }, {"0b1111111111111111111111111111111", INT32_MAX }, {"0b10000000000000000000000000000000", INT32_MAX + 1U }, {"0b11111111111111111111111111111111", UINT32_MAX }, {"0b100000000000000000000000000000000", UINT32_MAX + 1ULL }, {"0b111111111111111111111111111111111111111111111111111111111111111", INT64_MAX }, {"0b1000000000000000000000000000000000000000000000000000000000000000", INT64_MAX + 1ULL}, {"0b1111111111111111111111111111111111111111111111111111111111111111", UINT64_MAX }, /* binary (with leading zeroes) */ {"0b01111111", INT8_MAX }, {"0b0000000100000000", UINT8_MAX + 1 }, {"0b0111111111111111", INT16_MAX }, {"0b00000000000000010000000000000000", UINT16_MAX + 1 }, {"0b01111111111111111111111111111111", INT32_MAX }, {"0b0000000000000000000000000000000100000000000000000000000000000000", UINT32_MAX + 1ULL }, {"0b0111111111111111111111111111111111111111111111111111111111111111", INT64_MAX }, /* octal */ {"00", 0 }, {"0177", INT8_MAX }, {"0200", INT8_MAX + 1 }, {"0377", UINT8_MAX }, {"0400", UINT8_MAX + 1 }, {"077777", INT16_MAX }, {"0100000", INT16_MAX + 1 }, {"0177777", UINT16_MAX }, {"0200000", UINT16_MAX + 1 }, {"017777777777", INT32_MAX }, {"020000000000", INT32_MAX + 1U }, {"037777777777", UINT32_MAX }, {"040000000000", UINT32_MAX + 1ULL }, {"0777777777777777777777", INT64_MAX }, {"01000000000000000000000", INT64_MAX + 1ULL}, {"01777777777777777777777", UINT64_MAX }, /* check all numbers */ {"012345670", 012345670 }, {"076543210", 076543210 }, }; const struct num_signed_str num_valid_negative_strs[] = { /* deciman negative */ {"-128", INT8_MIN }, {"-129", INT8_MIN - 1 }, {"-32768", INT16_MIN }, {"-32769", INT16_MIN - 1 }, {"-2147483648", INT32_MIN }, {"-2147483649", INT32_MIN - 1LL }, {"-9223372036854775808", INT64_MIN }, }; const struct num_unsigned_str num_garbage_positive_strs[] = { /* valid strings with garbage on the end, should still be valid */ /* decimal */ {"9223372036854775807\0garbage", INT64_MAX }, {"9223372036854775807\tgarbage", INT64_MAX }, {"9223372036854775807\rgarbage", INT64_MAX }, {"9223372036854775807\ngarbage", INT64_MAX }, {"9223372036854775807#garbage", INT64_MAX }, {"9223372036854775807 garbage", INT64_MAX }, /* hex */ {"0x7FFFFFFFFFFFFFFF\0garbage", INT64_MAX }, {"0x7FFFFFFFFFFFFFFF\tgarbage", INT64_MAX }, {"0x7FFFFFFFFFFFFFFF\rgarbage", INT64_MAX }, {"0x7FFFFFFFFFFFFFFF\ngarbage", INT64_MAX }, {"0x7FFFFFFFFFFFFFFF#garbage", INT64_MAX }, {"0x7FFFFFFFFFFFFFFF garbage", INT64_MAX }, /* binary */ {"0b1111111111111111111111111111111\0garbage", INT32_MAX }, {"0b1111111111111111111111111111111\rgarbage", INT32_MAX }, {"0b1111111111111111111111111111111\tgarbage", INT32_MAX }, {"0b1111111111111111111111111111111\ngarbage", INT32_MAX }, {"0b1111111111111111111111111111111#garbage", INT32_MAX }, {"0b1111111111111111111111111111111 garbage", INT32_MAX }, /* octal */ {"01777777777777777777777\0garbage", UINT64_MAX }, {"01777777777777777777777\rgarbage", UINT64_MAX }, {"01777777777777777777777\tgarbage", UINT64_MAX }, {"01777777777777777777777\ngarbage", UINT64_MAX }, {"01777777777777777777777#garbage", UINT64_MAX }, {"01777777777777777777777 garbage", UINT64_MAX }, }; const struct num_signed_str num_garbage_negative_strs[] = { /* valid strings with garbage on the end, should still be valid */ {"-9223372036854775808\0garbage", INT64_MIN }, {"-9223372036854775808\rgarbage", INT64_MIN }, {"-9223372036854775808\tgarbage", INT64_MIN }, {"-9223372036854775808\ngarbage", INT64_MIN }, {"-9223372036854775808#garbage", INT64_MIN }, {"-9223372036854775808 garbage", INT64_MIN }, }; const char * num_invalid_strs[] = { "18446744073709551616", /* out of range unsigned */ "-9223372036854775809", /* out of range negative signed */ "0x10000000000000000", /* out of range hex */ /* out of range binary */ "0b10000000000000000000000000000000000000000000000000000000000000000", "020000000000000000000000", /* out of range octal */ /* wrong chars */ "0123456239", "0x1234580AGE", "0b0111010101g001", "0b01110101017001", /* false negative numbers */ "-12345F623", "-0x1234580A", "-0b0111010101", /* too long (128+ chars) */ "0b1111000011110000111100001111000011110000111100001111000011110000" "1111000011110000111100001111000011110000111100001111000011110000", "1E3", "0A", "-B", "+4", "1.23G", "", " ", "#", "\r", "\t", "\n", "\0", }; #define NUM_POSITIVE_STRS_SIZE \ (sizeof(num_valid_positive_strs) / sizeof(num_valid_positive_strs[0])) #define NUM_NEGATIVE_STRS_SIZE \ (sizeof(num_valid_negative_strs) / sizeof(num_valid_negative_strs[0])) #define NUM_POSITIVE_GARBAGE_STRS_SIZE \ (sizeof(num_garbage_positive_strs) / sizeof(num_garbage_positive_strs[0])) #define NUM_NEGATIVE_GARBAGE_STRS_SIZE \ (sizeof(num_garbage_negative_strs) / sizeof(num_garbage_negative_strs[0])) #define NUM_INVALID_STRS_SIZE \ (sizeof(num_invalid_strs) / sizeof(num_invalid_strs[0])) static int can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type) { switch (type) { case UINT8: if (expected_result > UINT8_MAX) return 0; break; case UINT16: if (expected_result > UINT16_MAX) return 0; break; case UINT32: if (expected_result > UINT32_MAX) return 0; break; case INT8: if (expected_result > INT8_MAX) return 0; break; case INT16: if (expected_result > INT16_MAX) return 0; break; case INT32: if (expected_result > INT32_MAX) return 0; break; case INT64: if (expected_result > INT64_MAX) return 0; break; default: return 1; } return 1; } static int can_parse_signed(int64_t expected_result, enum cmdline_numtype type) { switch (type) { case UINT8: if (expected_result > UINT8_MAX || expected_result < 0) return 0; break; case UINT16: if (expected_result > UINT16_MAX || expected_result < 0) return 0; break; case UINT32: if (expected_result > UINT32_MAX || expected_result < 0) return 0; break; case UINT64: if (expected_result < 0) return 0; case INT8: if (expected_result > INT8_MAX || expected_result < INT8_MIN) return 0; break; case INT16: if (expected_result > INT16_MAX || expected_result < INT16_MIN) return 0; break; case INT32: if (expected_result > INT32_MAX || expected_result < INT32_MIN) return 0; break; default: return 1; } return 1; } /* test invalid parameters */ int test_parse_num_invalid_param(void) { char buf[CMDLINE_TEST_BUFSIZE]; uint32_t result; cmdline_parse_token_num_t token; int ret = 0; /* set up a token */ token.num_data.type = UINT32; /* copy string to buffer */ snprintf(buf, sizeof(buf), "%s", num_valid_positive_strs[0].str); /* try all null */ ret = cmdline_parse_num(NULL, NULL, NULL, 0); if (ret != -1) { printf("Error: parser accepted null parameters!\n"); return -1; } /* try null token */ ret = cmdline_parse_num(NULL, buf, (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parser accepted null token!\n"); return -1; } /* try null buf */ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL, (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parser accepted null string!\n"); return -1; } /* try null result */ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf, NULL, 0); if (ret == -1) { printf("Error: parser rejected null result!\n"); return -1; } /* test help function */ memset(&buf, 0, sizeof(buf)); /* try all null */ ret = cmdline_get_help_num(NULL, NULL, 0); if (ret != -1) { printf("Error: help function accepted null parameters!\n"); return -1; } /* try null token */ ret = cmdline_get_help_num(NULL, buf, sizeof(buf)); if (ret != -1) { printf("Error: help function accepted null token!\n"); return -1; } /* coverage! */ ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); if (ret < 0) { printf("Error: help function failed with valid parameters!\n"); return -1; } return 0; } /* test valid parameters but invalid data */ int test_parse_num_invalid_data(void) { enum cmdline_numtype type; int ret = 0; unsigned i; char buf[CMDLINE_TEST_BUFSIZE]; uint64_t result; /* pick largest buffer */ cmdline_parse_token_num_t token; /* cycle through all possible parsed types */ for (type = UINT8; type <= INT64; type++) { token.num_data.type = type; /* test full strings */ for (i = 0; i < NUM_INVALID_STRS_SIZE; i++) { memset(&result, 0, sizeof(uint64_t)); memset(&buf, 0, sizeof(buf)); ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, num_invalid_strs[i], (void*)&result, sizeof(result)); if (ret != -1) { /* get some info about what we are trying to parse */ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); printf("Error: parsing %s as %s succeeded!\n", num_invalid_strs[i], buf); return -1; } } } return 0; } /* test valid parameters and data */ int test_parse_num_valid(void) { int ret = 0; enum cmdline_numtype type; unsigned i; char buf[CMDLINE_TEST_BUFSIZE]; uint64_t result; cmdline_parse_token_num_t token; /** valid strings **/ /* cycle through all possible parsed types */ for (type = UINT8; type <= INT64; type++) { token.num_data.type = type; /* test positive strings */ for (i = 0; i < NUM_POSITIVE_STRS_SIZE; i++) { result = 0; memset(&buf, 0, sizeof(buf)); cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_valid_positive_strs[i].str, (void*)&result, sizeof(result)); /* if it should have passed but didn't, or if it should have failed but didn't */ if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) { printf("Error: parser behaves unexpectedly when parsing %s as %s!\n", num_valid_positive_strs[i].str, buf); return -1; } /* check if result matches what it should have matched * since unsigned numbers don't care about number of bits, we can just convert * everything to uint64_t without any worries. */ if (ret > 0 && num_valid_positive_strs[i].result != result) { printf("Error: parsing %s as %s failed: result mismatch!\n", num_valid_positive_strs[i].str, buf); return -1; } } /* test negative strings */ for (i = 0; i < NUM_NEGATIVE_STRS_SIZE; i++) { result = 0; memset(&buf, 0, sizeof(buf)); cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_valid_negative_strs[i].str, (void*)&result, sizeof(result)); /* if it should have passed but didn't, or if it should have failed but didn't */ if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) { printf("Error: parser behaves unexpectedly when parsing %s as %s!\n", num_valid_negative_strs[i].str, buf); return -1; } /* check if result matches what it should have matched * the result is signed in this case, so we have to account for that */ if (ret > 0) { /* detect negative */ switch (type) { case INT8: result = (int8_t) result; break; case INT16: result = (int16_t) result; break; case INT32: result = (int32_t) result; break; default: break; } if (num_valid_negative_strs[i].result == (int64_t) result) continue; printf("Error: parsing %s as %s failed: result mismatch!\n", num_valid_negative_strs[i].str, buf); return -1; } } } /** garbage strings **/ /* cycle through all possible parsed types */ for (type = UINT8; type <= INT64; type++) { token.num_data.type = type; /* test positive garbage strings */ for (i = 0; i < NUM_POSITIVE_GARBAGE_STRS_SIZE; i++) { result = 0; memset(&buf, 0, sizeof(buf)); cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_garbage_positive_strs[i].str, (void*)&result, sizeof(result)); /* if it should have passed but didn't, or if it should have failed but didn't */ if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) { printf("Error: parser behaves unexpectedly when parsing %s as %s!\n", num_garbage_positive_strs[i].str, buf); return -1; } /* check if result matches what it should have matched * since unsigned numbers don't care about number of bits, we can just convert * everything to uint64_t without any worries. */ if (ret > 0 && num_garbage_positive_strs[i].result != result) { printf("Error: parsing %s as %s failed: result mismatch!\n", num_garbage_positive_strs[i].str, buf); return -1; } } /* test negative strings */ for (i = 0; i < NUM_NEGATIVE_GARBAGE_STRS_SIZE; i++) { result = 0; memset(&buf, 0, sizeof(buf)); cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_garbage_negative_strs[i].str, (void*)&result, sizeof(result)); /* if it should have passed but didn't, or if it should have failed but didn't */ if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) { printf("Error: parser behaves unexpectedly when parsing %s as %s!\n", num_garbage_negative_strs[i].str, buf); return -1; } /* check if result matches what it should have matched * the result is signed in this case, so we have to account for that */ if (ret > 0) { /* detect negative */ switch (type) { case INT8: if (result & (INT8_MAX + 1)) result |= 0xFFFFFFFFFFFFFF00ULL; break; case INT16: if (result & (INT16_MAX + 1)) result |= 0xFFFFFFFFFFFF0000ULL; break; case INT32: if (result & (INT32_MAX + 1ULL)) result |= 0xFFFFFFFF00000000ULL; break; default: break; } if (num_garbage_negative_strs[i].result == (int64_t) result) continue; printf("Error: parsing %s as %s failed: result mismatch!\n", num_garbage_negative_strs[i].str, buf); return -1; } } } memset(&buf, 0, sizeof(buf)); /* coverage! */ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf)); return 0; } ================================================ FILE: app/test/test_cmdline_portlist.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test_cmdline.h" struct portlist_str { const char * str; uint32_t portmap; }; /* valid strings */ const struct portlist_str portlist_valid_strs[] = { {"0", 0x1U }, {"0-10", 0x7FFU}, {"10-20", 0x1FFC00U}, {"all", UINT32_MAX}, {"0,1,2,3", 0xFU}, {"0,1-5", 0x3FU}, {"0,0,0", 0x1U}, {"31,0-10,15", 0x800087FFU}, {"0000", 0x1U}, {"00,01,02,03", 0xFU}, {"000,001,002,003", 0xFU}, }; /* valid strings but with garbage at the end. * these strings should still be valid because parser checks * for end of token, which is either a space/tab, a newline/return, * or a hash sign. */ const char * portlist_garbage_strs[] = { "0-31 garbage", "0-31#garbage", "0-31\0garbage", "0-31\ngarbage", "0-31\rgarbage", "0-31\tgarbage", "0,1,2,3-31 garbage", "0,1,2,3-31#garbage", "0,1,2,3-31\0garbage", "0,1,2,3-31\ngarbage", "0,1,2,3-31\rgarbage", "0,1,2,3-31\tgarbage", "all garbage", "all#garbage", "all\0garbage", "all\ngarbage", "all\rgarbage", "all\tgarbage", }; /* invalid strings */ const char * portlist_invalid_strs[] = { /* valid syntax, invalid chars */ "A-B", "0-S", "1,2,3,4,Q", "A-4,3-15", "0-31invalid", /* valid chars, invalid syntax */ "1, 2", "1- 4", ",2", ",2 ", "-1, 4", "5-1", "2-", /* misc */ "-" "a", "A", ",", "#", " ", "\0", "", /* too long */ "0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1," "0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2", }; #define PORTLIST_VALID_STRS_SIZE \ (sizeof(portlist_valid_strs) / sizeof(portlist_valid_strs[0])) #define PORTLIST_GARBAGE_STRS_SIZE \ (sizeof(portlist_garbage_strs) / sizeof(portlist_garbage_strs[0])) #define PORTLIST_INVALID_STRS_SIZE \ (sizeof(portlist_invalid_strs) / sizeof(portlist_invalid_strs[0])) /* test invalid parameters */ int test_parse_portlist_invalid_param(void) { cmdline_portlist_t result; char buf[CMDLINE_TEST_BUFSIZE]; int ret; memset(&buf, 0, sizeof(buf)); memset(&result, 0, sizeof(cmdline_portlist_t)); /* try all null */ ret = cmdline_parse_portlist(NULL, NULL, NULL, 0); if (ret != -1) { printf("Error: parser accepted null parameters!\n"); return -1; } /* try null buf */ ret = cmdline_parse_portlist(NULL, NULL, (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parser accepted null string!\n"); return -1; } /* try null result */ ret = cmdline_parse_portlist(NULL, portlist_valid_strs[0].str, NULL, 0); if (ret == -1) { printf("Error: parser rejected null result!\n"); return -1; } /* token is not used in ether_parse anyway so there's no point in * testing it */ /* test help function */ /* coverage! */ ret = cmdline_get_help_portlist(NULL, buf, sizeof(buf)); if (ret < 0) { printf("Error: help function failed with valid parameters!\n"); return -1; } return 0; } /* test valid parameters but invalid data */ int test_parse_portlist_invalid_data(void) { int ret = 0; unsigned i; cmdline_portlist_t result; /* test invalid strings */ for (i = 0; i < PORTLIST_INVALID_STRS_SIZE; i++) { memset(&result, 0, sizeof(cmdline_portlist_t)); ret = cmdline_parse_portlist(NULL, portlist_invalid_strs[i], (void*)&result, sizeof(result)); if (ret != -1) { printf("Error: parsing %s succeeded!\n", portlist_invalid_strs[i]); return -1; } } return 0; } /* test valid parameters and data */ int test_parse_portlist_valid(void) { int ret = 0; unsigned i; cmdline_portlist_t result; /* test full strings */ for (i = 0; i < PORTLIST_VALID_STRS_SIZE; i++) { memset(&result, 0, sizeof(cmdline_portlist_t)); ret = cmdline_parse_portlist(NULL, portlist_valid_strs[i].str, (void*)&result, sizeof(result)); if (ret < 0) { printf("Error: parsing %s failed!\n", portlist_valid_strs[i].str); return -1; } if (result.map != portlist_valid_strs[i].portmap) { printf("Error: parsing %s failed: map mismatch!\n", portlist_valid_strs[i].str); return -1; } } /* test garbage strings */ for (i = 0; i < PORTLIST_GARBAGE_STRS_SIZE; i++) { memset(&result, 0, sizeof(cmdline_portlist_t)); ret = cmdline_parse_portlist(NULL, portlist_garbage_strs[i], (void*)&result, sizeof(result)); if (ret < 0) { printf("Error: parsing %s failed!\n", portlist_garbage_strs[i]); return -1; } if (result.map != UINT32_MAX) { printf("Error: parsing %s failed: map mismatch!\n", portlist_garbage_strs[i]); return -1; } } return 0; } ================================================ FILE: app/test/test_cmdline_string.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "test_cmdline.h" /* structures needed to run tests */ struct string_elt_str { const char * str; /* parsed string */ const char * result; /* expected string */ int idx; /* position at which result is expected to be */ }; struct string_elt_str string_elt_strs[] = { {"one#two#three", "three", 2}, {"one#two with spaces#three", "three", 2}, {"one#two\twith\ttabs#three", "three", 2}, {"one#two\rwith\rreturns#three", "three", 2}, {"one#two\nwith\nnewlines#three", "three", 2}, {"one#two#three", "one", 0}, {"one#two#three", "two", 1}, {"one#two\0three", "two", 1}, {"one#two with spaces#three", "two with spaces", 1}, {"one#two\twith\ttabs#three", "two\twith\ttabs", 1}, {"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1}, {"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1}, }; #if CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE #undef CMDLINE_TEST_BUFSIZE #define CMDLINE_TEST_BUFSIZE STR_TOKEN_SIZE #endif struct string_nb_str { const char * str; /* parsed string */ int nb_strs; /* expected number of strings in str */ }; struct string_nb_str string_nb_strs[] = { {"one#two#three", 3}, {"one", 1}, {"one# \t two \r # three \n #four", 4}, }; struct string_parse_str { const char * str; /* parsed string */ const char * fixed_str; /* parsing mode (any, fixed or multi) */ const char * result; /* expected result */ }; struct string_parse_str string_parse_strs[] = { {"one", NULL, "one"}, /* any string */ {"two", "one#two#three", "two"}, /* multiple choice string */ {"three", "three", "three"}, /* fixed string */ {"three", "one#two with\rgarbage\tcharacters\n#three", "three"}, {"two with\rgarbage\tcharacters\n", "one#two with\rgarbage\tcharacters\n#three", "two with\rgarbage\tcharacters\n"}, }; struct string_invalid_str { const char * str; /* parsed string */ const char * fixed_str; /* parsing mode (any, fixed or multi) */ }; struct string_invalid_str string_invalid_strs[] = { {"invalid", "one"}, /* fixed string */ {"invalid", "one#two#three"}, /* multiple choice string */ {"invalid", "invalidone"}, /* string that starts the same */ {"invalidone", "invalid"}, /* string that starts the same */ {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!", NULL }, {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!", "fixed" }, {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!", "multi#choice#string" }, {"invalid", "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!" "toolong!!!" }, {"invalid", ""}, {"", "invalid"} }; const char * string_help_strs[] = { NULL, "fixed_str", "multi#str", }; #define STRING_PARSE_STRS_SIZE \ (sizeof(string_parse_strs) / sizeof(string_parse_strs[0])) #define STRING_HELP_STRS_SIZE \ (sizeof(string_help_strs) / sizeof(string_help_strs[0])) #define STRING_ELT_STRS_SIZE \ (sizeof(string_elt_strs) / sizeof(string_elt_strs[0])) #define STRING_NB_STRS_SIZE \ (sizeof(string_nb_strs) / sizeof(string_nb_strs[0])) #define STRING_INVALID_STRS_SIZE \ (sizeof(string_invalid_strs) / sizeof(string_invalid_strs[0])) #define SMALL_BUF 8 /* test invalid parameters */ int test_parse_string_invalid_param(void) { cmdline_parse_token_string_t token; int result; char buf[CMDLINE_TEST_BUFSIZE]; memset(&token, 0, sizeof(token)); snprintf(buf, sizeof(buf), "buffer"); /* test null token */ if (cmdline_get_help_string( NULL, buf, 0) != -1) { printf("Error: function accepted null token!\n"); return -1; } if (cmdline_complete_get_elt_string( NULL, 0, buf, 0) != -1) { printf("Error: function accepted null token!\n"); return -1; } if (cmdline_complete_get_nb_string(NULL) != -1) { printf("Error: function accepted null token!\n"); return -1; } if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) { printf("Error: function accepted null token!\n"); return -1; } /* test null buffer */ if (cmdline_complete_get_elt_string( (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) { printf("Error: function accepted null buffer!\n"); return -1; } if (cmdline_parse_string( (cmdline_parse_token_hdr_t*)&token, NULL, (void*)&result, sizeof(result)) != -1) { printf("Error: function accepted null buffer!\n"); return -1; } if (cmdline_get_help_string( (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) { printf("Error: function accepted null buffer!\n"); return -1; } /* test null result */ if (cmdline_parse_string( (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) { printf("Error: function rejected null result!\n"); return -1; } /* test negative index */ if (cmdline_complete_get_elt_string( (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) { printf("Error: function accepted negative index!\n"); return -1; } return 0; } /* test valid parameters but invalid data */ int test_parse_string_invalid_data(void) { cmdline_parse_token_string_t token; cmdline_parse_token_string_t help_token; char buf[CMDLINE_TEST_BUFSIZE]; char help_str[CMDLINE_TEST_BUFSIZE]; char small_buf[SMALL_BUF]; unsigned i; /* test parsing invalid strings */ for (i = 0; i < STRING_INVALID_STRS_SIZE; i++) { memset(&token, 0, sizeof(token)); memset(buf, 0, sizeof(buf)); /* prepare test token data */ token.string_data.str = string_invalid_strs[i].fixed_str; if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, string_invalid_strs[i].str, (void*)buf, sizeof(buf)) != -1) { memset(help_str, 0, sizeof(help_str)); memset(&help_token, 0, sizeof(help_token)); help_token.string_data.str = string_invalid_strs[i].fixed_str; /* get parse type so we can give a good error message */ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, sizeof(help_str)); printf("Error: parsing %s as %s succeeded!\n", string_invalid_strs[i].str, help_str); return -1; } } /* misc tests (big comments signify test cases) */ memset(&token, 0, sizeof(token)); memset(small_buf, 0, sizeof(small_buf)); /* * try to get element from a null token */ token.string_data.str = NULL; if (cmdline_complete_get_elt_string( (cmdline_parse_token_hdr_t*)&token, 1, buf, sizeof(buf)) != -1) { printf("Error: getting token from null token string!\n"); return -1; } /* * try to get element into a buffer that is too small */ token.string_data.str = "too_small_buffer"; if (cmdline_complete_get_elt_string( (cmdline_parse_token_hdr_t*)&token, 0, small_buf, sizeof(small_buf)) != -1) { printf("Error: writing token into too small a buffer succeeded!\n"); return -1; } /* * get help string written into a buffer smaller than help string * truncation should occur */ token.string_data.str = NULL; if (cmdline_get_help_string( (cmdline_parse_token_hdr_t*)&token, small_buf, sizeof(small_buf)) == -1) { printf("Error: writing help string into too small a buffer failed!\n"); return -1; } /* get help string for "any string" so we can compare it with small_buf */ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, sizeof(help_str)); if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) { printf("Error: help string mismatch!\n"); return -1; } /* check null terminator */ if (small_buf[sizeof(small_buf) - 1] != '\0') { printf("Error: small buffer doesn't have a null terminator!\n"); return -1; } /* * try to count tokens in a null token */ token.string_data.str = NULL; if (cmdline_complete_get_nb_string( (cmdline_parse_token_hdr_t*)&token) != 0) { printf("Error: getting token count from null token succeeded!\n"); return -1; } return 0; } /* test valid parameters and data */ int test_parse_string_valid(void) { cmdline_parse_token_string_t token; cmdline_parse_token_string_t help_token; char buf[CMDLINE_TEST_BUFSIZE]; char help_str[CMDLINE_TEST_BUFSIZE]; unsigned i; /* test parsing strings */ for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) { memset(&token, 0, sizeof(token)); memset(buf, 0, sizeof(buf)); token.string_data.str = string_parse_strs[i].fixed_str; if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token, string_parse_strs[i].str, (void*)buf, sizeof(buf)) < 0) { /* clean help data */ memset(&help_token, 0, sizeof(help_token)); memset(help_str, 0, sizeof(help_str)); /* prepare help token */ help_token.string_data.str = string_parse_strs[i].fixed_str; /* get help string so that we get an informative error message */ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str, sizeof(help_str)); printf("Error: parsing %s as %s failed!\n", string_parse_strs[i].str, help_str); return -1; } if (strncmp(buf, string_parse_strs[i].result, sizeof(string_parse_strs[i].result) - 1) != 0) { printf("Error: result mismatch!\n"); return -1; } } /* get number of string tokens and verify it's correct */ for (i = 0; i < STRING_NB_STRS_SIZE; i++) { memset(&token, 0, sizeof(token)); token.string_data.str = string_nb_strs[i].str; if (cmdline_complete_get_nb_string( (cmdline_parse_token_hdr_t*)&token) < string_nb_strs[i].nb_strs) { printf("Error: strings count mismatch!\n"); return -1; } } /* get token at specified position and verify it's correct */ for (i = 0; i < STRING_ELT_STRS_SIZE; i++) { memset(&token, 0, sizeof(token)); memset(buf, 0, sizeof(buf)); token.string_data.str = string_elt_strs[i].str; if (cmdline_complete_get_elt_string( (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx, buf, sizeof(buf)) < 0) { printf("Error: getting string element failed!\n"); return -1; } if (strncmp(buf, string_elt_strs[i].result, sizeof(buf)) != 0) { printf("Error: result mismatch!\n"); return -1; } } /* cover all cases with help strings */ for (i = 0; i < STRING_HELP_STRS_SIZE; i++) { memset(&help_token, 0, sizeof(help_token)); memset(help_str, 0, sizeof(help_str)); help_token.string_data.str = string_help_strs[i]; if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token, help_str, sizeof(help_str)) < 0) { printf("Error: help operation failed!\n"); return -1; } } return 0; } ================================================ FILE: app/test/test_common.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "test.h" #define MAX_NUM 1 << 20 #define FAIL(x)\ {printf(x "() test failed!\n");\ return -1;} /* this is really a sanity check */ static int test_macros(int __rte_unused unused_parm) { #define SMALLER 0x1000U #define BIGGER 0x2000U #define PTR_DIFF BIGGER - SMALLER #define FAIL_MACRO(x)\ {printf(#x "() test failed!\n");\ return -1;} uintptr_t unused = 0; RTE_SET_USED(unused); if ((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF) != BIGGER) FAIL_MACRO(RTE_PTR_ADD); if ((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF) != SMALLER) FAIL_MACRO(RTE_PTR_SUB); if (RTE_PTR_DIFF(BIGGER, SMALLER) != PTR_DIFF) FAIL_MACRO(RTE_PTR_DIFF); if (RTE_MAX(SMALLER, BIGGER) != BIGGER) FAIL_MACRO(RTE_MAX); if (RTE_MIN(SMALLER, BIGGER) != SMALLER) FAIL_MACRO(RTE_MIN); if (strncmp(RTE_STR(test), "test", sizeof("test"))) FAIL_MACRO(RTE_STR); return 0; } static int test_misc(void) { char memdump[] = "memdump_test"; if (rte_bsf32(129)) FAIL("rte_bsf32"); rte_memdump(stdout, "test", memdump, sizeof(memdump)); rte_hexdump(stdout, "test", memdump, sizeof(memdump)); rte_pause(); return 0; } static int test_align(void) { #define FAIL_ALIGN(x, i, p)\ {printf(x "() test failed: %u %u\n", i, p);\ return -1;} #define ERROR_FLOOR(res, i, pow) \ (res % pow) || /* check if not aligned */ \ ((res / pow) != (i / pow)) /* check if correct alignment */ #define ERROR_CEIL(res, i, pow) \ (res % pow) || /* check if not aligned */ \ ((i % pow) == 0 ? /* check if ceiling is invoked */ \ val / pow != i / pow : /* if aligned */ \ val / pow != (i / pow) + 1) /* if not aligned, hence +1 */ uint32_t i, p, val; for (i = 1, p = 1; i <= MAX_NUM; i ++) { if (rte_align32pow2(i) != p) FAIL_ALIGN("rte_align32pow2", i, p); if (i == p) p <<= 1; } for (p = 2; p <= MAX_NUM; p <<= 1) { if (!rte_is_power_of_2(p)) FAIL("rte_is_power_of_2"); for (i = 1; i <= MAX_NUM; i++) { /* align floor */ if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p) FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p); if (ERROR_FLOOR(val, i, p)) FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p); val = RTE_ALIGN_FLOOR(i, p); if (ERROR_FLOOR(val, i, p)) FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); /* align ceiling */ val = RTE_PTR_ALIGN((uintptr_t) i, p); if (ERROR_CEIL(val, i, p)) FAIL_ALIGN("RTE_PTR_ALIGN", i, p); val = RTE_ALIGN(i, p); if (ERROR_CEIL(val, i, p)) FAIL_ALIGN("RTE_ALIGN", i, p); val = RTE_ALIGN_CEIL(i, p); if (ERROR_CEIL(val, i, p)) FAIL_ALIGN("RTE_ALIGN_CEIL", i, p); val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p); if (ERROR_CEIL(val, i, p)) FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p); /* by this point we know that val is aligned to p */ if (!rte_is_aligned((void*)(uintptr_t) val, p)) FAIL("rte_is_aligned"); } } return 0; } static int test_common(void) { int ret = 0; ret |= test_align(); ret |= test_macros(0); ret |= test_misc(); return ret; } static struct test_command common_cmd = { .command = "common_autotest", .callback = test_common, }; REGISTER_TEST_COMMAND(common_cmd); ================================================ FILE: app/test/test_cpuflags.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" /* convenience define */ #define CHECK_FOR_FLAG(x) \ result = rte_cpu_get_flag_enabled(x); \ printf("%s\n", cpu_flag_result(result)); \ if (result == -ENOENT) \ return -1; /* * Helper function to display result */ static inline const char * cpu_flag_result(int result) { switch (result) { case 0: return "NOT PRESENT"; case 1: return "OK"; default: return "ERROR"; } } /* * CPUID test * =========== * * - Check flags from different registers with rte_cpu_get_flag_enabled() * - Check if register and CPUID functions fail properly */ static int test_cpuflags(void) { int result; printf("\nChecking for flags from different registers...\n"); #ifdef RTE_ARCH_PPC_64 printf("Check for PPC64:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_PPC64); printf("Check for PPC32:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_PPC32); printf("Check for VSX:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_VSX); printf("Check for DFP:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_DFP); printf("Check for FPU:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_FPU); printf("Check for SMT:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SMT); printf("Check for MMU:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_MMU); printf("Check for ALTIVEC:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_ALTIVEC); printf("Check for ARCH_2_06:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_06); printf("Check for ARCH_2_07:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_07); printf("Check for ICACHE_SNOOP:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP); #endif #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) printf("Check for SSE:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SSE); printf("Check for SSE2:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SSE2); printf("Check for SSE3:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SSE3); printf("Check for SSE4.1:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_1); printf("Check for SSE4.2:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_2); printf("Check for AVX:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_AVX); printf("Check for AVX2:\t\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_AVX2); printf("Check for TRBOBST:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_TRBOBST); printf("Check for ENERGY_EFF:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_ENERGY_EFF); printf("Check for LAHF_SAHF:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_LAHF_SAHF); printf("Check for 1GB_PG:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_1GB_PG); printf("Check for INVTSC:\t"); CHECK_FOR_FLAG(RTE_CPUFLAG_INVTSC); #endif /* * Check if invalid data is handled properly */ printf("\nCheck for invalid flag:\t"); result = rte_cpu_get_flag_enabled(RTE_CPUFLAG_NUMFLAGS); printf("%s\n", cpu_flag_result(result)); if (result != -ENOENT) return -1; return 0; } static struct test_command cpuflags_cmd = { .command = "cpuflags_autotest", .callback = test_cpuflags, }; REGISTER_TEST_COMMAND(cpuflags_cmd); ================================================ FILE: app/test/test_cycles.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "test.h" #define N 10000 /* * Cycles test * =========== * * - Loop N times and check that the timer always increments and * never decrements during this loop. * * - Wait one second using rte_usleep() and check that the increment * of cycles is correct with regard to the frequency of the timer. */ static int test_cycles(void) { unsigned i; uint64_t start_cycles, cycles, prev_cycles; uint64_t hz = rte_get_timer_hz(); uint64_t max_inc = (hz / 100); /* 10 ms max between 2 reads */ /* check that the timer is always incrementing */ start_cycles = rte_get_timer_cycles(); prev_cycles = start_cycles; for (i=0; i max_inc) { printf("increment too high or going backwards\n"); return -1; } prev_cycles = cycles; } /* check that waiting 1 second is precise */ prev_cycles = rte_get_timer_cycles(); rte_delay_us(1000000); cycles = rte_get_timer_cycles(); if ((uint64_t)(cycles - prev_cycles) > (hz + max_inc)) { printf("delay_us is not accurate: too long\n"); return -1; } if ((uint64_t)(cycles - prev_cycles) < (hz - max_inc)) { printf("delay_us is not accurate: too short\n"); return -1; } return 0; } static struct test_command cycles_cmd = { .command = "cycles_autotest", .callback = test_cycles, }; REGISTER_TEST_COMMAND(cycles_cmd); ================================================ FILE: app/test/test_debug.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "test.h" /* * Debug test * ========== */ /* use fork() to test rte_panic() */ static int test_panic(void) { int pid; int status; pid = fork(); if (pid == 0) rte_panic("Test Debug\n"); else if (pid < 0){ printf("Fork Failed\n"); return -1; } wait(&status); if(status == 0){ printf("Child process terminated normally!\n"); return -1; } else printf("Child process terminated as expected - Test passed!\n"); return 0; } /* use fork() to test rte_exit() */ static int test_exit_val(int exit_val) { int pid; int status; pid = fork(); if (pid == 0) rte_exit(exit_val, __func__); else if (pid < 0){ printf("Fork Failed\n"); return -1; } wait(&status); printf("Child process status: %d\n", status); #ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR if(!WIFEXITED(status) || WEXITSTATUS(status) != (uint8_t)exit_val){ printf("Child process terminated with incorrect status (expected = %d)!\n", exit_val); return -1; } #endif return 0; } static int test_exit(void) { int test_vals[] = { 0, 1, 2, 255, -1 }; unsigned i; for (i = 0; i < sizeof(test_vals) / sizeof(test_vals[0]); i++){ if (test_exit_val(test_vals[i]) < 0) return -1; } printf("%s Passed\n", __func__); return 0; } static void dummy_app_usage(const char *progname) { RTE_SET_USED(progname); } static int test_usage(void) { if (rte_set_application_usage_hook(dummy_app_usage) != NULL) { printf("Non-NULL value returned for initial usage hook\n"); return -1; } if (rte_set_application_usage_hook(NULL) != dummy_app_usage) { printf("Incorrect value returned for application usage hook\n"); return -1; } return 0; } static int test_debug(void) { rte_dump_stack(); rte_dump_registers(); if (test_panic() < 0) return -1; if (test_exit() < 0) return -1; if (test_usage() < 0) return -1; return 0; } static struct test_command debug_cmd = { .command = "debug_autotest", .callback = test_debug, }; REGISTER_TEST_COMMAND(debug_cmd); ================================================ FILE: app/test/test_devargs.c ================================================ /*- * BSD LICENSE * * Copyright 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "test.h" /* clear devargs list that was modified by the test */ static void free_devargs_list(void) { struct rte_devargs *devargs; while (!TAILQ_EMPTY(&devargs_list)) { devargs = TAILQ_FIRST(&devargs_list); TAILQ_REMOVE(&devargs_list, devargs, next); if (devargs->args) free(devargs->args); free(devargs); } } static int test_devargs(void) { struct rte_devargs_list save_devargs_list; struct rte_devargs *devargs; /* save the real devargs_list, it is restored at the end of the test */ save_devargs_list = devargs_list; TAILQ_INIT(&devargs_list); /* test valid cases */ if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "08:00.1") < 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "0000:5:00.0") < 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, "04:00.0,arg=val") < 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, "0000:01:00.1") < 0) goto fail; if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 2) goto fail; if (rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 2) goto fail; if (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, "eth_ring0") < 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, "eth_ring1,key=val,k2=val2") < 0) goto fail; if (rte_eal_devargs_type_count(RTE_DEVTYPE_VIRTUAL) != 2) goto fail; free_devargs_list(); /* check virtual device with argument parsing */ if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, "eth_ring1,k1=val,k2=val2") < 0) goto fail; devargs = TAILQ_FIRST(&devargs_list); if (strncmp(devargs->virtual.drv_name, "eth_ring1", sizeof(devargs->virtual.drv_name)) != 0) goto fail; if (!devargs->args || strcmp(devargs->args, "k1=val,k2=val2") != 0) goto fail; free_devargs_list(); /* check PCI device with empty argument parsing */ if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "04:00.1") < 0) goto fail; devargs = TAILQ_FIRST(&devargs_list); if (devargs->pci.addr.domain != 0 || devargs->pci.addr.bus != 4 || devargs->pci.addr.devid != 0 || devargs->pci.addr.function != 1) goto fail; if (!devargs->args || strcmp(devargs->args, "") != 0) goto fail; free_devargs_list(); /* test error case: bad PCI address */ if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "08:1") == 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "00.1") == 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "foo") == 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, ",") == 0) goto fail; if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, "000f:0:0") == 0) goto fail; devargs_list = save_devargs_list; return 0; fail: free_devargs_list(); devargs_list = save_devargs_list; return -1; } static struct test_command devargs_cmd = { .command = "devargs_autotest", .callback = test_devargs, }; REGISTER_TEST_COMMAND(devargs_cmd); ================================================ FILE: app/test/test_distributor.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include #include #include #include #include #include #include #define ITER_POWER 20 /* log 2 of how many iterations we do when timing. */ #define BURST 32 #define BIG_BATCH 1024 /* statics - all zero-initialized by default */ static volatile int quit; /**< general quit variable for all threads */ static volatile int zero_quit; /**< var for when we just want thr0 to quit*/ static volatile unsigned worker_idx; struct worker_stats { volatile unsigned handled_packets; } __rte_cache_aligned; struct worker_stats worker_stats[RTE_MAX_LCORE]; /* returns the total count of the number of packets handled by the worker * functions given below. */ static inline unsigned total_packet_count(void) { unsigned i, count = 0; for (i = 0; i < worker_idx; i++) count += worker_stats[i].handled_packets; return count; } /* resets the packet counts for a new test */ static inline void clear_packet_count(void) { memset(&worker_stats, 0, sizeof(worker_stats)); } /* this is the basic worker function for sanity test * it does nothing but return packets and count them. */ static int handle_work(void *arg) { struct rte_mbuf *pkt = NULL; struct rte_distributor *d = arg; unsigned count = 0; unsigned id = __sync_fetch_and_add(&worker_idx, 1); pkt = rte_distributor_get_pkt(d, id, NULL); while (!quit) { worker_stats[id].handled_packets++, count++; pkt = rte_distributor_get_pkt(d, id, pkt); } worker_stats[id].handled_packets++, count++; rte_distributor_return_pkt(d, id, pkt); return 0; } /* do basic sanity testing of the distributor. This test tests the following: * - send 32 packets through distributor with the same tag and ensure they * all go to the one worker * - send 32 packets throught the distributor with two different tags and * verify that they go equally to two different workers. * - send 32 packets with different tags through the distributors and * just verify we get all packets back. * - send 1024 packets through the distributor, gathering the returned packets * as we go. Then verify that we correctly got all 1024 pointers back again, * not necessarily in the same order (as different flows). */ static int sanity_test(struct rte_distributor *d, struct rte_mempool *p) { struct rte_mbuf *bufs[BURST]; unsigned i; printf("=== Basic distributor sanity tests ===\n"); clear_packet_count(); if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) { printf("line %d: Error getting mbufs from pool\n", __LINE__); return -1; } /* now set all hash values in all buffers to zero, so all pkts go to the * one worker thread */ for (i = 0; i < BURST; i++) bufs[i]->hash.usr = 0; rte_distributor_process(d, bufs, BURST); rte_distributor_flush(d); if (total_packet_count() != BURST) { printf("Line %d: Error, not all packets flushed. " "Expected %u, got %u\n", __LINE__, BURST, total_packet_count()); return -1; } for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Sanity test with all zero hashes done.\n"); if (worker_stats[0].handled_packets != BURST) return -1; /* pick two flows and check they go correctly */ if (rte_lcore_count() >= 3) { clear_packet_count(); for (i = 0; i < BURST; i++) bufs[i]->hash.usr = (i & 1) << 8; rte_distributor_process(d, bufs, BURST); rte_distributor_flush(d); if (total_packet_count() != BURST) { printf("Line %d: Error, not all packets flushed. " "Expected %u, got %u\n", __LINE__, BURST, total_packet_count()); return -1; } for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Sanity test with two hash values done\n"); if (worker_stats[0].handled_packets != 16 || worker_stats[1].handled_packets != 16) return -1; } /* give a different hash value to each packet, * so load gets distributed */ clear_packet_count(); for (i = 0; i < BURST; i++) bufs[i]->hash.usr = i; rte_distributor_process(d, bufs, BURST); rte_distributor_flush(d); if (total_packet_count() != BURST) { printf("Line %d: Error, not all packets flushed. " "Expected %u, got %u\n", __LINE__, BURST, total_packet_count()); return -1; } for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Sanity test with non-zero hashes done\n"); rte_mempool_put_bulk(p, (void *)bufs, BURST); /* sanity test with BIG_BATCH packets to ensure they all arrived back * from the returned packets function */ clear_packet_count(); struct rte_mbuf *many_bufs[BIG_BATCH], *return_bufs[BIG_BATCH]; unsigned num_returned = 0; /* flush out any remaining packets */ rte_distributor_flush(d); rte_distributor_clear_returns(d); if (rte_mempool_get_bulk(p, (void *)many_bufs, BIG_BATCH) != 0) { printf("line %d: Error getting mbufs from pool\n", __LINE__); return -1; } for (i = 0; i < BIG_BATCH; i++) many_bufs[i]->hash.usr = i << 2; for (i = 0; i < BIG_BATCH/BURST; i++) { rte_distributor_process(d, &many_bufs[i*BURST], BURST); num_returned += rte_distributor_returned_pkts(d, &return_bufs[num_returned], BIG_BATCH - num_returned); } rte_distributor_flush(d); num_returned += rte_distributor_returned_pkts(d, &return_bufs[num_returned], BIG_BATCH - num_returned); if (num_returned != BIG_BATCH) { printf("line %d: Number returned is not the same as " "number sent\n", __LINE__); return -1; } /* big check - make sure all packets made it back!! */ for (i = 0; i < BIG_BATCH; i++) { unsigned j; struct rte_mbuf *src = many_bufs[i]; for (j = 0; j < BIG_BATCH; j++) if (return_bufs[j] == src) break; if (j == BIG_BATCH) { printf("Error: could not find source packet #%u\n", i); return -1; } } printf("Sanity test of returned packets done\n"); rte_mempool_put_bulk(p, (void *)many_bufs, BIG_BATCH); printf("\n"); return 0; } /* to test that the distributor does not lose packets, we use this worker * function which frees mbufs when it gets them. The distributor thread does * the mbuf allocation. If distributor drops packets we'll eventually run out * of mbufs. */ static int handle_work_with_free_mbufs(void *arg) { struct rte_mbuf *pkt = NULL; struct rte_distributor *d = arg; unsigned count = 0; unsigned id = __sync_fetch_and_add(&worker_idx, 1); pkt = rte_distributor_get_pkt(d, id, NULL); while (!quit) { worker_stats[id].handled_packets++, count++; rte_pktmbuf_free(pkt); pkt = rte_distributor_get_pkt(d, id, pkt); } worker_stats[id].handled_packets++, count++; rte_distributor_return_pkt(d, id, pkt); return 0; } /* Perform a sanity test of the distributor with a large number of packets, * where we allocate a new set of mbufs for each burst. The workers then * free the mbufs. This ensures that we don't have any packet leaks in the * library. */ static int sanity_test_with_mbuf_alloc(struct rte_distributor *d, struct rte_mempool *p) { unsigned i; struct rte_mbuf *bufs[BURST]; printf("=== Sanity test with mbuf alloc/free ===\n"); clear_packet_count(); for (i = 0; i < ((1<hash.usr = (i+j) << 1; rte_mbuf_refcnt_set(bufs[j], 1); } rte_distributor_process(d, bufs, BURST); } rte_distributor_flush(d); if (total_packet_count() < (1<hash.usr = 0; rte_distributor_process(d, bufs, BURST); /* at this point, we will have processed some packets and have a full * backlog for the other ones at worker 0. */ /* get more buffers to queue up, again setting them to the same flow */ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) { printf("line %d: Error getting mbufs from pool\n", __LINE__); return -1; } for (i = 0; i < BURST; i++) bufs[i]->hash.usr = 0; /* get worker zero to quit */ zero_quit = 1; rte_distributor_process(d, bufs, BURST); /* flush the distributor */ rte_distributor_flush(d); if (total_packet_count() != BURST * 2) { printf("Line %d: Error, not all packets flushed. " "Expected %u, got %u\n", __LINE__, BURST * 2, total_packet_count()); return -1; } for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Sanity test with worker shutdown passed\n\n"); return 0; } /* Test that the flush function is able to move packets between workers when * one worker shuts down.. */ static int test_flush_with_worker_shutdown(struct rte_distributor *d, struct rte_mempool *p) { struct rte_mbuf *bufs[BURST]; unsigned i; printf("=== Test flush fn with worker shutdown ===\n"); clear_packet_count(); if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) { printf("line %d: Error getting mbufs from pool\n", __LINE__); return -1; } /* now set all hash values in all buffers to zero, so all pkts go to the * one worker thread */ for (i = 0; i < BURST; i++) bufs[i]->hash.usr = 0; rte_distributor_process(d, bufs, BURST); /* at this point, we will have processed some packets and have a full * backlog for the other ones at worker 0. */ /* get worker zero to quit */ zero_quit = 1; /* flush the distributor */ rte_distributor_flush(d); zero_quit = 0; if (total_packet_count() != BURST) { printf("Line %d: Error, not all packets flushed. " "Expected %u, got %u\n", __LINE__, BURST, total_packet_count()); return -1; } for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Flush test with worker shutdown passed\n\n"); return 0; } static int test_error_distributor_create_name(void) { struct rte_distributor *d = NULL; char *name = NULL; d = rte_distributor_create(name, rte_socket_id(), rte_lcore_count() - 1); if (d != NULL || rte_errno != EINVAL) { printf("ERROR: No error on create() with NULL name param\n"); return -1; } return 0; } static int test_error_distributor_create_numworkers(void) { struct rte_distributor *d = NULL; d = rte_distributor_create("test_numworkers", rte_socket_id(), RTE_MAX_LCORE + 10); if (d != NULL || rte_errno != EINVAL) { printf("ERROR: No error on create() with num_workers > MAX\n"); return -1; } return 0; } /* Useful function which ensures that all worker functions terminate */ static void quit_workers(struct rte_distributor *d, struct rte_mempool *p) { const unsigned num_workers = rte_lcore_count() - 1; unsigned i; struct rte_mbuf *bufs[RTE_MAX_LCORE]; rte_mempool_get_bulk(p, (void *)bufs, num_workers); zero_quit = 0; quit = 1; for (i = 0; i < num_workers; i++) bufs[i]->hash.usr = i << 1; rte_distributor_process(d, bufs, num_workers); rte_mempool_put_bulk(p, (void *)bufs, num_workers); rte_distributor_process(d, NULL, 0); rte_distributor_flush(d); rte_eal_mp_wait_lcore(); quit = 0; worker_idx = 0; } static int test_distributor(void) { static struct rte_distributor *d; static struct rte_mempool *p; if (rte_lcore_count() < 2) { printf("ERROR: not enough cores to test distributor\n"); return -1; } if (d == NULL) { d = rte_distributor_create("Test_distributor", rte_socket_id(), rte_lcore_count() - 1); if (d == NULL) { printf("Error creating distributor\n"); return -1; } } else { rte_distributor_flush(d); rte_distributor_clear_returns(d); } const unsigned nb_bufs = (511 * rte_lcore_count()) < BIG_BATCH ? (BIG_BATCH * 2) - 1 : (511 * rte_lcore_count()); if (p == NULL) { p = rte_pktmbuf_pool_create("DT_MBUF_POOL", nb_bufs, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (p == NULL) { printf("Error creating mempool\n"); return -1; } } rte_eal_mp_remote_launch(handle_work, d, SKIP_MASTER); if (sanity_test(d, p) < 0) goto err; quit_workers(d, p); rte_eal_mp_remote_launch(handle_work_with_free_mbufs, d, SKIP_MASTER); if (sanity_test_with_mbuf_alloc(d, p) < 0) goto err; quit_workers(d, p); if (rte_lcore_count() > 2) { rte_eal_mp_remote_launch(handle_work_for_shutdown_test, d, SKIP_MASTER); if (sanity_test_with_worker_shutdown(d, p) < 0) goto err; quit_workers(d, p); rte_eal_mp_remote_launch(handle_work_for_shutdown_test, d, SKIP_MASTER); if (test_flush_with_worker_shutdown(d, p) < 0) goto err; quit_workers(d, p); } else { printf("Not enough cores to run tests for worker shutdown\n"); } if (test_error_distributor_create_numworkers() == -1 || test_error_distributor_create_name() == -1) { printf("rte_distributor_create parameter check tests failed"); return -1; } return 0; err: quit_workers(d, p); return -1; } static struct test_command distributor_cmd = { .command = "distributor_autotest", .callback = test_distributor, }; REGISTER_TEST_COMMAND(distributor_cmd); ================================================ FILE: app/test/test_distributor_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include #include #include #include #include #include #include #define ITER_POWER 20 /* log 2 of how many iterations we do when timing. */ #define BURST 32 #define BIG_BATCH 1024 /* static vars - zero initialized by default */ static volatile int quit; static volatile unsigned worker_idx; struct worker_stats { volatile unsigned handled_packets; } __rte_cache_aligned; struct worker_stats worker_stats[RTE_MAX_LCORE]; /* worker thread used for testing the time to do a round-trip of a cache * line between two cores and back again */ static void flip_bit(volatile uint64_t *arg) { uint64_t old_val = 0; while (old_val != 2) { while (!*arg) rte_pause(); old_val = *arg; *arg = 0; } } /* test case to time the number of cycles to round-trip a cache line between * two cores and back again. */ static void time_cache_line_switch(void) { /* allocate a full cache line for data, we use only first byte of it */ uint64_t data[RTE_CACHE_LINE_SIZE*3 / sizeof(uint64_t)]; unsigned i, slaveid = rte_get_next_lcore(rte_lcore_id(), 0, 0); volatile uint64_t *pdata = &data[0]; *pdata = 1; rte_eal_remote_launch((lcore_function_t *)flip_bit, &data[0], slaveid); while (*pdata) rte_pause(); const uint64_t start_time = rte_rdtsc(); for (i = 0; i < (1 << ITER_POWER); i++) { while (*pdata) rte_pause(); *pdata = 1; } const uint64_t end_time = rte_rdtsc(); while (*pdata) rte_pause(); *pdata = 2; rte_eal_wait_lcore(slaveid); printf("==== Cache line switch test ===\n"); printf("Time for %u iterations = %"PRIu64" ticks\n", (1<> ITER_POWER); } /* returns the total count of the number of packets handled by the worker * functions given below. */ static unsigned total_packet_count(void) { unsigned i, count = 0; for (i = 0; i < worker_idx; i++) count += worker_stats[i].handled_packets; return count; } /* resets the packet counts for a new test */ static void clear_packet_count(void) { memset(&worker_stats, 0, sizeof(worker_stats)); } /* this is the basic worker function for performance tests. * it does nothing but return packets and count them. */ static int handle_work(void *arg) { struct rte_mbuf *pkt = NULL; struct rte_distributor *d = arg; unsigned count = 0; unsigned id = __sync_fetch_and_add(&worker_idx, 1); pkt = rte_distributor_get_pkt(d, id, NULL); while (!quit) { worker_stats[id].handled_packets++, count++; pkt = rte_distributor_get_pkt(d, id, pkt); } worker_stats[id].handled_packets++, count++; rte_distributor_return_pkt(d, id, pkt); return 0; } /* this basic performance test just repeatedly sends in 32 packets at a time * to the distributor and verifies at the end that we got them all in the worker * threads and finally how long per packet the processing took. */ static inline int perf_test(struct rte_distributor *d, struct rte_mempool *p) { unsigned i; uint64_t start, end; struct rte_mbuf *bufs[BURST]; clear_packet_count(); if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) { printf("Error getting mbufs from pool\n"); return -1; } /* ensure we have different hash value for each pkt */ for (i = 0; i < BURST; i++) bufs[i]->hash.usr = i; start = rte_rdtsc(); for (i = 0; i < (1<> ITER_POWER); printf("Time per packet: %"PRIu64"\n\n", ((end - start) >> ITER_POWER)/BURST); rte_mempool_put_bulk(p, (void *)bufs, BURST); for (i = 0; i < rte_lcore_count() - 1; i++) printf("Worker %u handled %u packets\n", i, worker_stats[i].handled_packets); printf("Total packets: %u (%x)\n", total_packet_count(), total_packet_count()); printf("=== Perf test done ===\n\n"); return 0; } /* Useful function which ensures that all worker functions terminate */ static void quit_workers(struct rte_distributor *d, struct rte_mempool *p) { const unsigned num_workers = rte_lcore_count() - 1; unsigned i; struct rte_mbuf *bufs[RTE_MAX_LCORE]; rte_mempool_get_bulk(p, (void *)bufs, num_workers); quit = 1; for (i = 0; i < num_workers; i++) bufs[i]->hash.usr = i << 1; rte_distributor_process(d, bufs, num_workers); rte_mempool_put_bulk(p, (void *)bufs, num_workers); rte_distributor_process(d, NULL, 0); rte_eal_mp_wait_lcore(); quit = 0; worker_idx = 0; } static int test_distributor_perf(void) { static struct rte_distributor *d; static struct rte_mempool *p; if (rte_lcore_count() < 2) { printf("ERROR: not enough cores to test distributor\n"); return -1; } /* first time how long it takes to round-trip a cache line */ time_cache_line_switch(); if (d == NULL) { d = rte_distributor_create("Test_perf", rte_socket_id(), rte_lcore_count() - 1); if (d == NULL) { printf("Error creating distributor\n"); return -1; } } else { rte_distributor_flush(d); rte_distributor_clear_returns(d); } const unsigned nb_bufs = (511 * rte_lcore_count()) < BIG_BATCH ? (BIG_BATCH * 2) - 1 : (511 * rte_lcore_count()); if (p == NULL) { p = rte_pktmbuf_pool_create("DPT_MBUF_POOL", nb_bufs, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (p == NULL) { printf("Error creating mempool\n"); return -1; } } rte_eal_mp_remote_launch(handle_work, d, SKIP_MASTER); if (perf_test(d, p) < 0) return -1; quit_workers(d, p); return 0; } static struct test_command distributor_perf_cmd = { .command = "distributor_perf_autotest", .callback = test_distributor_perf, }; REGISTER_TEST_COMMAND(distributor_perf_cmd); ================================================ FILE: app/test/test_eal_flags.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "test.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "process.h" #ifdef RTE_LIBRTE_XEN_DOM0 #define DEFAULT_MEM_SIZE "30" #else #define DEFAULT_MEM_SIZE "18" #endif #define mp_flag "--proc-type=secondary" #define no_hpet "--no-hpet" #define no_huge "--no-huge" #define no_shconf "--no-shconf" #define pci_whitelist "--pci-whitelist" #define vdev "--vdev" #define memtest "memtest" #define memtest1 "memtest1" #define memtest2 "memtest2" #define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10) #define launch_proc(ARGV) process_dup(ARGV, \ sizeof(ARGV)/(sizeof(ARGV[0])), __func__) enum hugepage_action { HUGEPAGE_CHECK_EXISTS = 0, HUGEPAGE_CHECK_LOCKED, HUGEPAGE_DELETE, HUGEPAGE_INVALID }; /* if string contains a hugepage path */ static int get_hugepage_path(char * src, int src_len, char * dst, int dst_len) { #define NUM_TOKENS 4 char *tokens[NUM_TOKENS]; /* if we couldn't properly split the string */ if (rte_strsplit(src, src_len, tokens, NUM_TOKENS, ' ') < NUM_TOKENS) return 0; if (strncmp(tokens[2], "hugetlbfs", sizeof("hugetlbfs")) == 0) { snprintf(dst, dst_len, "%s", tokens[1]); return 1; } return 0; } /* * Cycles through hugepage directories and looks for hugepage * files associated with a given prefix. Depending on value of * action, the hugepages are checked if they exist, checked if * they can be locked, or are simply deleted. * * Returns 1 if it finds at least one hugepage matching the action * Returns 0 if no matching hugepages were found * Returns -1 if it encounters an error */ static int process_hugefiles(const char * prefix, enum hugepage_action action) { FILE * hugedir_handle = NULL; DIR * hugepage_dir = NULL; struct dirent *dirent = NULL; char hugefile_prefix[PATH_MAX] = {0}; char hugedir[PATH_MAX] = {0}; char line[PATH_MAX] = {0}; int fd, lck_result, result = 0; const int prefix_len = snprintf(hugefile_prefix, sizeof(hugefile_prefix), "%smap_", prefix); if (prefix_len <= 0 || prefix_len >= (int)sizeof(hugefile_prefix) || prefix_len >= (int)sizeof(dirent->d_name)) { printf("Error creating hugefile filename prefix\n"); return -1; } /* get hugetlbfs mountpoints from /proc/mounts */ hugedir_handle = fopen("/proc/mounts", "r"); if (hugedir_handle == NULL) { printf("Error parsing /proc/mounts!\n"); return -1; } /* read and parse script output */ while (fgets(line, sizeof(line), hugedir_handle) != NULL) { /* check if we have a hugepage filesystem path */ if (!get_hugepage_path(line, sizeof(line), hugedir, sizeof(hugedir))) continue; /* check if directory exists */ if ((hugepage_dir = opendir(hugedir)) == NULL) { fclose(hugedir_handle); printf("Error reading %s: %s\n", hugedir, strerror(errno)); return -1; } while ((dirent = readdir(hugepage_dir)) != NULL) { if (memcmp(dirent->d_name, hugefile_prefix, prefix_len) != 0) continue; switch (action) { case HUGEPAGE_CHECK_EXISTS: { /* file exists, return */ result = 1; goto end; } break; case HUGEPAGE_DELETE: { char file_path[PATH_MAX] = {0}; snprintf(file_path, sizeof(file_path), "%s/%s", hugedir, dirent->d_name); /* remove file */ if (remove(file_path) < 0) { printf("Error deleting %s - %s!\n", dirent->d_name, strerror(errno)); closedir(hugepage_dir); result = -1; goto end; } result = 1; } break; case HUGEPAGE_CHECK_LOCKED: { /* try and lock the file */ fd = openat(dirfd(hugepage_dir), dirent->d_name, O_RDONLY); /* this shouldn't happen */ if (fd == -1) { printf("Error opening %s - %s!\n", dirent->d_name, strerror(errno)); closedir(hugepage_dir); result = -1; goto end; } /* non-blocking lock */ lck_result = flock(fd, LOCK_EX | LOCK_NB); /* if lock succeeds, there's something wrong */ if (lck_result != -1) { result = 0; /* unlock the resulting lock */ flock(fd, LOCK_UN); close(fd); closedir(hugepage_dir); goto end; } result = 1; close(fd); } break; /* shouldn't happen */ default: goto end; } /* switch */ } /* read hugepage directory */ closedir(hugepage_dir); } /* read /proc/mounts */ end: fclose(hugedir_handle); return result; } #ifdef RTE_EXEC_ENV_LINUXAPP /* * count the number of "node*" files in /sys/devices/system/node/ */ static int get_number_of_sockets(void) { struct dirent *dirent = NULL; const char * nodedir = "/sys/devices/system/node/"; DIR * dir = NULL; int result = 0; /* check if directory exists */ if ((dir = opendir(nodedir)) == NULL) { /* if errno==ENOENT this means we don't have NUMA support */ if (errno == ENOENT) { printf("No NUMA nodes detected: assuming 1 available socket\n"); return 1; } printf("Error opening %s: %s\n", nodedir, strerror(errno)); return -1; } while ((dirent = readdir(dir)) != NULL) if (strncmp(dirent->d_name, "node", sizeof("node") - 1) == 0) result++; closedir(dir); return result; } #endif static char* get_current_prefix(char * prefix, int size) { char path[PATH_MAX] = {0}; char buf[PATH_MAX] = {0}; /* get file for config (fd is always 3) */ snprintf(path, sizeof(path), "/proc/self/fd/%d", 3); /* return NULL on error */ if (readlink(path, buf, sizeof(buf)) == -1) return NULL; /* get the basename */ snprintf(buf, sizeof(buf), "%s", basename(buf)); /* copy string all the way from second char up to start of _config */ snprintf(prefix, size, "%.*s", (int)(strnlen(buf, sizeof(buf)) - sizeof("_config")), &buf[1]); return prefix; } /* * Test that the app doesn't run with invalid whitelist option. * Final tests ensures it does run with valid options as sanity check (one * test for with Domain+BDF, second for just with BDF) */ static int test_whitelist_flag(void) { unsigned i; #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif const char *wlinval[][11] = { {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "error", "", ""}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "0:0:0", "", ""}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "0:error:0.1", "", ""}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "0:0:0.1error", "", ""}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "error0:0:0.1", "", ""}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "0:0:0.1.2", "", ""}, }; /* Test with valid whitelist option */ const char *wlval1[] = {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "00FF:09:0B.3"}; const char *wlval2[] = {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "09:0B.3", pci_whitelist, "0a:0b.1"}; const char *wlval3[] = {prgname, prefix, mp_flag, "-n", "1", "-c", "1", pci_whitelist, "09:0B.3,type=test", pci_whitelist, "08:00.1,type=normal", }; for (i = 0; i < sizeof(wlinval) / sizeof(wlinval[0]); i++) { if (launch_proc(wlinval[i]) == 0) { printf("Error - process did run ok with invalid " "whitelist parameter\n"); return -1; } } if (launch_proc(wlval1) != 0 ) { printf("Error - process did not run ok with valid whitelist\n"); return -1; } if (launch_proc(wlval2) != 0 ) { printf("Error - process did not run ok with valid whitelist value set\n"); return -1; } if (launch_proc(wlval3) != 0 ) { printf("Error - process did not run ok with valid whitelist + args\n"); return -1; } return 0; } /* * Test that the app doesn't run with invalid blacklist option. * Final test ensures it does run with valid options as sanity check */ static int test_invalid_b_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif const char *blinval[][9] = { {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "error"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "0:0:0"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "0:error:0.1"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "0:0:0.1error"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "error0:0:0.1"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "0:0:0.1.2"}, }; /* Test with valid blacklist option */ const char *blval[] = {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-b", "FF:09:0B.3"}; int i; for (i = 0; i != sizeof (blinval) / sizeof (blinval[0]); i++) { if (launch_proc(blinval[i]) == 0) { printf("Error - process did run ok with invalid " "blacklist parameter\n"); return -1; } } if (launch_proc(blval) != 0) { printf("Error - process did not run ok with valid blacklist value\n"); return -1; } return 0; } /* * Test that the app doesn't run with invalid vdev option. * Final test ensures it does run with valid options as sanity check */ #ifdef RTE_LIBRTE_PMD_RING static int test_invalid_vdev_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point, and we also need to * run another primary process here */ const char * prefix = no_shconf; #else const char * prefix = "--file-prefix=vdev"; #endif /* Test with invalid vdev option */ const char *vdevinval[] = {prgname, prefix, "-n", "1", "-c", "1", vdev, "eth_dummy"}; /* Test with valid vdev option */ const char *vdevval1[] = {prgname, prefix, "-n", "1", "-c", "1", vdev, "eth_ring0"}; const char *vdevval2[] = {prgname, prefix, "-n", "1", "-c", "1", vdev, "eth_ring0,args=test"}; const char *vdevval3[] = {prgname, prefix, "-n", "1", "-c", "1", vdev, "eth_ring0,nodeaction=r1:0:CREATE"}; if (launch_proc(vdevinval) == 0) { printf("Error - process did run ok with invalid " "vdev parameter\n"); return -1; } if (launch_proc(vdevval1) != 0) { printf("Error - process did not run ok with valid vdev value\n"); return -1; } if (launch_proc(vdevval2) != 0) { printf("Error - process did not run ok with valid vdev value," "with dummy args\n"); return -1; } if (launch_proc(vdevval3) != 0) { printf("Error - process did not run ok with valid vdev value," "with valid args\n"); return -1; } return 0; } #endif /* * Test that the app doesn't run with invalid -r option. */ static int test_invalid_r_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif const char *rinval[][9] = { {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-r", "error"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-r", "0"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-r", "-1"}, {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-r", "17"}, }; /* Test with valid blacklist option */ const char *rval[] = {prgname, prefix, mp_flag, "-n", "1", "-c", "1", "-r", "16"}; int i; for (i = 0; i != sizeof (rinval) / sizeof (rinval[0]); i++) { if (launch_proc(rinval[i]) == 0) { printf("Error - process did run ok with invalid " "-r (rank) parameter\n"); return -1; } } if (launch_proc(rval) != 0) { printf("Error - process did not run ok with valid -r (rank) value\n"); return -1; } return 0; } /* * Test that the app doesn't run without the coremask/corelist flags. In all cases * should give an error and fail to run */ static int test_missing_c_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif /* -c flag but no coremask value */ const char *argv1[] = { prgname, prefix, mp_flag, "-n", "3", "-c"}; /* No -c, -l or --lcores flag at all */ const char *argv2[] = { prgname, prefix, mp_flag, "-n", "3"}; /* bad coremask value */ const char *argv3[] = { prgname, prefix, mp_flag, "-n", "3", "-c", "error" }; /* sanity check of tests - valid coremask value */ const char *argv4[] = { prgname, prefix, mp_flag, "-n", "3", "-c", "1" }; /* -l flag but no corelist value */ const char *argv5[] = { prgname, prefix, mp_flag, "-n", "3", "-l"}; const char *argv6[] = { prgname, prefix, mp_flag, "-n", "3", "-l", " " }; /* bad corelist values */ const char *argv7[] = { prgname, prefix, mp_flag, "-n", "3", "-l", "error" }; const char *argv8[] = { prgname, prefix, mp_flag, "-n", "3", "-l", "1-" }; const char *argv9[] = { prgname, prefix, mp_flag, "-n", "3", "-l", "1," }; const char *argv10[] = { prgname, prefix, mp_flag, "-n", "3", "-l", "1#2" }; /* sanity check test - valid corelist value */ const char *argv11[] = { prgname, prefix, mp_flag, "-n", "3", "-l", "1-2,3" }; /* --lcores flag but no lcores value */ const char *argv12[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores" }; const char *argv13[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", " " }; /* bad lcores value */ const char *argv14[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "1-3-5" }; const char *argv15[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "0-1,,2" }; const char *argv16[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "0-,1" }; const char *argv17[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "(0-,2-4)" }; const char *argv18[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "(-1,2)" }; const char *argv19[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "(2-4)@(2-4-6)" }; const char *argv20[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "(a,2)" }; const char *argv21[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "1-3@(1,3)" }; const char *argv22[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "3@((1,3)" }; const char *argv23[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "(4-7)=(1,3)" }; const char *argv24[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "[4-7]@(1,3)" }; /* sanity check of tests - valid lcores value */ const char *argv25[] = { prgname, prefix, mp_flag, "-n", "3", "--lcores", "0-1,2@(5-7),(3-5)@(0,2),(0,6),7"}; if (launch_proc(argv1) == 0 || launch_proc(argv2) == 0 || launch_proc(argv3) == 0) { printf("Error - " "process ran without error when missing -c flag\n"); return -1; } if (launch_proc(argv4) != 0) { printf("Error - " "process did not run ok with valid coremask value\n"); return -1; } /* start -l test */ if (launch_proc(argv5) == 0 || launch_proc(argv6) == 0 || launch_proc(argv7) == 0 || launch_proc(argv8) == 0 || launch_proc(argv9) == 0 || launch_proc(argv10) == 0) { printf("Error - " "process ran without error with invalid -l flag\n"); return -1; } if (launch_proc(argv11) != 0) { printf("Error - " "process did not run ok with valid corelist value\n"); return -1; } /* start --lcores tests */ if (launch_proc(argv12) == 0 || launch_proc(argv13) == 0 || launch_proc(argv14) == 0 || launch_proc(argv15) == 0 || launch_proc(argv16) == 0 || launch_proc(argv17) == 0 || launch_proc(argv18) == 0 || launch_proc(argv19) == 0 || launch_proc(argv20) == 0 || launch_proc(argv21) == 0 || launch_proc(argv21) == 0 || launch_proc(argv22) == 0 || launch_proc(argv23) == 0 || launch_proc(argv24) == 0) { printf("Error - " "process ran without error with invalid --lcore flag\n"); return -1; } if (launch_proc(argv25) != 0) { printf("Error - " "process did not run ok with valid corelist value\n"); return -1; } return 0; } /* * Test --master-lcore option with matching coremask */ static int test_master_lcore_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char *prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif /* --master-lcore flag but no value */ const char *argv1[] = { prgname, prefix, mp_flag, "-n", "1", "-c", "3", "--master-lcore"}; /* --master-lcore flag with invalid value */ const char *argv2[] = { prgname, prefix, mp_flag, "-n", "1", "-c", "3", "--master-lcore", "-1"}; const char *argv3[] = { prgname, prefix, mp_flag, "-n", "1", "-c", "3", "--master-lcore", "X"}; /* master lcore not in coremask */ const char *argv4[] = { prgname, prefix, mp_flag, "-n", "1", "-c", "3", "--master-lcore", "2"}; /* valid value */ const char *argv5[] = { prgname, prefix, mp_flag, "-n", "1", "-c", "3", "--master-lcore", "1"}; /* valid value set before coremask */ const char *argv6[] = { prgname, prefix, mp_flag, "-n", "1", "--master-lcore", "1", "-c", "3"}; if (launch_proc(argv1) == 0 || launch_proc(argv2) == 0 || launch_proc(argv3) == 0 || launch_proc(argv4) == 0) { printf("Error - process ran without error with wrong --master-lcore\n"); return -1; } if (launch_proc(argv5) != 0 || launch_proc(argv6) != 0) { printf("Error - process did not run ok with valid --master-lcore\n"); return -1; } return 0; } /* * Test that the app doesn't run without the -n flag. In all cases * should give an error and fail to run. * Since -n is not compulsory for MP, we instead use --no-huge and --no-shconf * flags. */ static int test_missing_n_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif /* -n flag but no value */ const char *argv1[] = { prgname, prefix, no_huge, no_shconf, "-c", "1", "-n"}; /* No -n flag at all */ const char *argv2[] = { prgname, prefix, no_huge, no_shconf, "-c", "1"}; /* bad numeric value */ const char *argv3[] = { prgname, prefix, no_huge, no_shconf, "-c", "1", "-n", "e" }; /* out-of-range value */ const char *argv4[] = { prgname, prefix, no_huge, no_shconf, "-c", "1", "-n", "9" }; /* sanity test - check with good value */ const char *argv5[] = { prgname, prefix, no_huge, no_shconf, "-c", "1", "-n", "2" }; if (launch_proc(argv1) == 0 || launch_proc(argv2) == 0 || launch_proc(argv3) == 0 || launch_proc(argv4) == 0) { printf("Error - process ran without error when missing -n flag\n"); return -1; } if (launch_proc(argv5) != 0) { printf("Error - process did not run ok with valid num-channel value\n"); return -1; } return 0; } /* * Test that the app runs with HPET, and without HPET */ static int test_no_hpet_flag(void) { char prefix[PATH_MAX], tmp[PATH_MAX]; #ifdef RTE_EXEC_ENV_BSDAPP return 0; #endif if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); /* With --no-hpet */ const char *argv1[] = {prgname, prefix, mp_flag, no_hpet, "-c", "1", "-n", "2"}; /* Without --no-hpet */ const char *argv2[] = {prgname, prefix, mp_flag, "-c", "1", "-n", "2"}; if (launch_proc(argv1) != 0) { printf("Error - process did not run ok with --no-hpet flag\n"); return -1; } if (launch_proc(argv2) != 0) { printf("Error - process did not run ok without --no-hpet flag\n"); return -1; } return 0; } /* * Test that the app runs with --no-huge and doesn't run when --socket-mem are * specified with --no-huge. */ static int test_no_huge_flag(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point, and we also need to * run another primary process here */ const char * prefix = no_shconf; #else const char * prefix = "--file-prefix=nohuge"; #endif /* With --no-huge */ const char *argv1[] = {prgname, prefix, no_huge, "-c", "1", "-n", "2"}; /* With --no-huge and -m */ const char *argv2[] = {prgname, prefix, no_huge, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE}; /* With --no-huge and --socket-mem */ const char *argv3[] = {prgname, prefix, no_huge, "-c", "1", "-n", "2", "--socket-mem=" DEFAULT_MEM_SIZE}; /* With --no-huge, -m and --socket-mem */ const char *argv4[] = {prgname, prefix, no_huge, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--socket-mem=" DEFAULT_MEM_SIZE}; if (launch_proc(argv1) != 0) { printf("Error - process did not run ok with --no-huge flag\n"); return -1; } if (launch_proc(argv2) != 0) { printf("Error - process did not run ok with --no-huge and -m flags\n"); return -1; } #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target does not support NUMA, hence no --socket-mem tests */ return 0; #endif if (launch_proc(argv3) == 0) { printf("Error - process run ok with --no-huge and --socket-mem " "flags\n"); return -1; } if (launch_proc(argv4) == 0) { printf("Error - process run ok with --no-huge, -m and " "--socket-mem flags\n"); return -1; } return 0; } #ifdef RTE_LIBRTE_XEN_DOM0 static int test_dom0_misc_flags(void) { char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); /* check that some general flags don't prevent things from working. * All cases, apart from the first, app should run. * No futher testing of output done. */ /* sanity check - failure with invalid option */ const char *argv0[] = {prgname, prefix, mp_flag, "-c", "1", "--invalid-opt"}; /* With --no-pci */ const char *argv1[] = {prgname, prefix, mp_flag, "-c", "1", "--no-pci"}; /* With -v */ const char *argv2[] = {prgname, prefix, mp_flag, "-c", "1", "-v"}; /* With valid --syslog */ const char *argv3[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog", "syslog"}; /* With empty --syslog (should fail) */ const char *argv4[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog"}; /* With invalid --syslog */ const char *argv5[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog", "error"}; /* With no-sh-conf */ const char *argv6[] = {prgname, "-c", "1", "-n", "2", "-m", "20", "--no-shconf", "--file-prefix=noshconf" }; if (launch_proc(argv0) == 0) { printf("Error - process ran ok with invalid flag\n"); return -1; } if (launch_proc(argv1) != 0) { printf("Error - process did not run ok with --no-pci flag\n"); return -1; } if (launch_proc(argv2) != 0) { printf("Error - process did not run ok with -v flag\n"); return -1; } if (launch_proc(argv3) != 0) { printf("Error - process did not run ok with --syslog flag\n"); return -1; } if (launch_proc(argv4) == 0) { printf("Error - process run ok with empty --syslog flag\n"); return -1; } if (launch_proc(argv5) == 0) { printf("Error - process run ok with invalid --syslog flag\n"); return -1; } if (launch_proc(argv6) != 0) { printf("Error - process did not run ok with --no-shconf flag\n"); return -1; } return 0; } #else static int test_misc_flags(void) { char hugepath[PATH_MAX] = {0}; #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; const char * nosh_prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; const char * nosh_prefix = "--file-prefix=noshconf"; FILE * hugedir_handle = NULL; char line[PATH_MAX] = {0}; unsigned i, isempty = 1; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); /* * get first valid hugepage path */ /* get hugetlbfs mountpoints from /proc/mounts */ hugedir_handle = fopen("/proc/mounts", "r"); if (hugedir_handle == NULL) { printf("Error opening /proc/mounts!\n"); return -1; } /* read /proc/mounts */ while (fgets(line, sizeof(line), hugedir_handle) != NULL) { /* find first valid hugepath */ if (get_hugepage_path(line, sizeof(line), hugepath, sizeof(hugepath))) break; } fclose(hugedir_handle); /* check if path is not empty */ for (i = 0; i < sizeof(hugepath); i++) if (hugepath[i] != '\0') isempty = 0; if (isempty) { printf("No mounted hugepage dir found!\n"); return -1; } #endif /* check that some general flags don't prevent things from working. * All cases, apart from the first, app should run. * No futher testing of output done. */ /* sanity check - failure with invalid option */ const char *argv0[] = {prgname, prefix, mp_flag, "-c", "1", "--invalid-opt"}; /* With --no-pci */ const char *argv1[] = {prgname, prefix, mp_flag, "-c", "1", "--no-pci"}; /* With -v */ const char *argv2[] = {prgname, prefix, mp_flag, "-c", "1", "-v"}; /* With valid --syslog */ const char *argv3[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog", "syslog"}; /* With empty --syslog (should fail) */ const char *argv4[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog"}; /* With invalid --syslog */ const char *argv5[] = {prgname, prefix, mp_flag, "-c", "1", "--syslog", "error"}; /* With no-sh-conf */ const char *argv6[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, no_shconf, nosh_prefix }; #ifdef RTE_EXEC_ENV_BSDAPP return 0; #endif /* With --huge-dir */ const char *argv7[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=hugedir", "--huge-dir", hugepath}; /* With empty --huge-dir (should fail) */ const char *argv8[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=hugedir", "--huge-dir"}; /* With invalid --huge-dir */ const char *argv9[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=hugedir", "--huge-dir", "invalid"}; /* Secondary process with invalid --huge-dir (should run as flag has no * effect on secondary processes) */ const char *argv10[] = {prgname, prefix, mp_flag, "-c", "1", "--huge-dir", "invalid"}; /* try running with base-virtaddr param */ const char *argv11[] = {prgname, "--file-prefix=virtaddr", "-c", "1", "-n", "2", "--base-virtaddr=0x12345678"}; /* try running with --vfio-intr INTx flag */ const char *argv12[] = {prgname, "--file-prefix=intr", "-c", "1", "-n", "2", "--vfio-intr=legacy"}; /* try running with --vfio-intr MSI flag */ const char *argv13[] = {prgname, "--file-prefix=intr", "-c", "1", "-n", "2", "--vfio-intr=msi"}; /* try running with --vfio-intr MSI-X flag */ const char *argv14[] = {prgname, "--file-prefix=intr", "-c", "1", "-n", "2", "--vfio-intr=msix"}; /* try running with --vfio-intr invalid flag */ const char *argv15[] = {prgname, "--file-prefix=intr", "-c", "1", "-n", "2", "--vfio-intr=invalid"}; if (launch_proc(argv0) == 0) { printf("Error - process ran ok with invalid flag\n"); return -1; } if (launch_proc(argv1) != 0) { printf("Error - process did not run ok with --no-pci flag\n"); return -1; } if (launch_proc(argv2) != 0) { printf("Error - process did not run ok with -v flag\n"); return -1; } if (launch_proc(argv3) != 0) { printf("Error - process did not run ok with --syslog flag\n"); return -1; } if (launch_proc(argv4) == 0) { printf("Error - process run ok with empty --syslog flag\n"); return -1; } if (launch_proc(argv5) == 0) { printf("Error - process run ok with invalid --syslog flag\n"); return -1; } if (launch_proc(argv6) != 0) { printf("Error - process did not run ok with --no-shconf flag\n"); return -1; } #ifdef RTE_EXEC_ENV_BSDAPP return 0; #endif if (launch_proc(argv7) != 0) { printf("Error - process did not run ok with --huge-dir flag\n"); return -1; } if (launch_proc(argv8) == 0) { printf("Error - process run ok with empty --huge-dir flag\n"); return -1; } if (launch_proc(argv9) == 0) { printf("Error - process run ok with invalid --huge-dir flag\n"); return -1; } if (launch_proc(argv10) != 0) { printf("Error - secondary process did not run ok with invalid --huge-dir flag\n"); return -1; } if (launch_proc(argv11) != 0) { printf("Error - process did not run ok with --base-virtaddr parameter\n"); return -1; } if (launch_proc(argv12) != 0) { printf("Error - process did not run ok with " "--vfio-intr INTx parameter\n"); return -1; } if (launch_proc(argv13) != 0) { printf("Error - process did not run ok with " "--vfio-intr MSI parameter\n"); return -1; } if (launch_proc(argv14) != 0) { printf("Error - process did not run ok with " "--vfio-intr MSI-X parameter\n"); return -1; } if (launch_proc(argv15) == 0) { printf("Error - process run ok with " "--vfio-intr invalid parameter\n"); return -1; } return 0; } #endif static int test_file_prefix(void) { /* * 1. check if current process hugefiles are locked * 2. try to run secondary process without a corresponding primary process * (while failing to run, it will also remove any unused hugepage files) * 3. check if current process hugefiles are still in place and are locked * 4. run a primary process with memtest1 prefix * 5. check if memtest1 hugefiles are created * 6. run a primary process with memtest2 prefix * 7. check that only memtest2 hugefiles are present in the hugedir */ #ifdef RTE_EXEC_ENV_BSDAPP return 0; #endif /* this should fail unless the test itself is run with "memtest" prefix */ const char *argv0[] = {prgname, mp_flag, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=" memtest }; /* primary process with memtest1 */ const char *argv1[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=" memtest1 }; /* primary process with memtest2 */ const char *argv2[] = {prgname, "-c", "1", "-n", "2", "-m", DEFAULT_MEM_SIZE, "--file-prefix=" memtest2 }; char prefix[32]; if (get_current_prefix(prefix, sizeof(prefix)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } #ifdef RTE_LIBRTE_XEN_DOM0 return 0; #endif /* check if files for current prefix are present */ if (process_hugefiles(prefix, HUGEPAGE_CHECK_EXISTS) != 1) { printf("Error - hugepage files for %s were not created!\n", prefix); return -1; } /* checks if files for current prefix are locked */ if (process_hugefiles(prefix, HUGEPAGE_CHECK_LOCKED) != 1) { printf("Error - hugepages for current process aren't locked!\n"); return -1; } /* check if files for secondary process are present */ if (process_hugefiles(memtest, HUGEPAGE_CHECK_EXISTS) == 1) { /* check if they are not locked */ if (process_hugefiles(memtest, HUGEPAGE_CHECK_LOCKED) == 1) { printf("Error - hugepages for current process are locked!\n"); return -1; } /* they aren't locked, delete them */ else { if (process_hugefiles(memtest, HUGEPAGE_DELETE) != 1) { printf("Error - deleting hugepages failed!\n"); return -1; } } } if (launch_proc(argv0) == 0) { printf("Error - secondary process ran ok without primary process\n"); return -1; } /* check if files for current prefix are present */ if (process_hugefiles(prefix, HUGEPAGE_CHECK_EXISTS) != 1) { printf("Error - hugepage files for %s were not created!\n", prefix); return -1; } /* checks if files for current prefix are locked */ if (process_hugefiles(prefix, HUGEPAGE_CHECK_LOCKED) != 1) { printf("Error - hugepages for current process aren't locked!\n"); return -1; } if (launch_proc(argv1) != 0) { printf("Error - failed to run with --file-prefix=%s\n", memtest); return -1; } /* check if memtest1_map0 is present */ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 1) { printf("Error - hugepage files for %s were not created!\n", memtest1); return -1; } if (launch_proc(argv2) != 0) { printf("Error - failed to run with --file-prefix=%s\n", memtest2); return -1; } /* check if hugefiles for memtest2 are present */ if (process_hugefiles(memtest2, HUGEPAGE_CHECK_EXISTS) != 1) { printf("Error - hugepage files for %s were not created!\n", memtest2); return -1; } /* check if hugefiles for memtest1 are present */ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) { printf("Error - hugepage files for %s were not deleted!\n", memtest1); return -1; } return 0; } /* * Tests for correct handling of -m and --socket-mem flags */ static int test_memory_flags(void) { #ifdef RTE_EXEC_ENV_BSDAPP /* BSD target doesn't support prefixes at this point */ const char * prefix = ""; #else char prefix[PATH_MAX], tmp[PATH_MAX]; if (get_current_prefix(tmp, sizeof(tmp)) == NULL) { printf("Error - unable to get current prefix!\n"); return -1; } snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #endif /* valid -m flag and mp flag */ const char *argv0[] = {prgname, prefix, mp_flag, "-c", "10", "-n", "2", "-m", DEFAULT_MEM_SIZE}; /* valid -m flag */ const char *argv1[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "-m", DEFAULT_MEM_SIZE}; /* invalid (zero) --socket-mem flag */ const char *argv2[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem=0,0,0,0"}; /* invalid (incomplete) --socket-mem flag */ const char *argv3[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem=2,2,"}; /* invalid (mixed with invalid data) --socket-mem flag */ const char *argv4[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem=2,2,Fred"}; /* invalid (with numeric value as last character) --socket-mem flag */ const char *argv5[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem=2,2,Fred0"}; /* invalid (with empty socket) --socket-mem flag */ const char *argv6[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem=2,,2"}; /* invalid (null) --socket-mem flag */ const char *argv7[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "--socket-mem="}; /* valid --socket-mem specified together with -m flag */ const char *argv8[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, "-m", DEFAULT_MEM_SIZE, "--socket-mem=2,2"}; /* construct an invalid socket mask with 2 megs on each socket plus * extra 2 megs on socket that doesn't exist on current system */ char invalid_socket_mem[SOCKET_MEM_STRLEN]; char buf[SOCKET_MEM_STRLEN]; /* to avoid copying string onto itself */ #ifdef RTE_EXEC_ENV_BSDAPP int i, num_sockets = 1; #else int i, num_sockets = get_number_of_sockets(); #endif if (num_sockets <= 0 || num_sockets > RTE_MAX_NUMA_NODES) { printf("Error - cannot get number of sockets!\n"); return -1; } snprintf(invalid_socket_mem, sizeof(invalid_socket_mem), "--socket-mem="); /* add one extra socket */ for (i = 0; i < num_sockets + 1; i++) { snprintf(buf, sizeof(buf), "%s%s", invalid_socket_mem, DEFAULT_MEM_SIZE); snprintf(invalid_socket_mem, sizeof(invalid_socket_mem), "%s", buf); if (num_sockets + 1 - i > 1) { snprintf(buf, sizeof(buf), "%s,", invalid_socket_mem); snprintf(invalid_socket_mem, sizeof(invalid_socket_mem), "%s", buf); } } /* construct a valid socket mask with 2 megs on each existing socket */ char valid_socket_mem[SOCKET_MEM_STRLEN]; snprintf(valid_socket_mem, sizeof(valid_socket_mem), "--socket-mem="); /* add one extra socket */ for (i = 0; i < num_sockets; i++) { snprintf(buf, sizeof(buf), "%s%s", valid_socket_mem, DEFAULT_MEM_SIZE); snprintf(valid_socket_mem, sizeof(valid_socket_mem), "%s", buf); if (num_sockets - i > 1) { snprintf(buf, sizeof(buf), "%s,", valid_socket_mem); snprintf(valid_socket_mem, sizeof(valid_socket_mem), "%s", buf); } } /* invalid --socket-mem flag (with extra socket) */ const char *argv9[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, invalid_socket_mem}; /* valid --socket-mem flag */ const char *argv10[] = {prgname, "-c", "10", "-n", "2", "--file-prefix=" memtest, valid_socket_mem}; if (launch_proc(argv0) != 0) { printf("Error - secondary process failed with valid -m flag !\n"); return -1; } #ifdef RTE_EXEC_ENV_BSDAPP /* no other tests are applicable to BSD */ return 0; #endif if (launch_proc(argv1) != 0) { printf("Error - process failed with valid -m flag!\n"); return -1; } #ifdef RTE_LIBRTE_XEN_DOM0 return 0; #endif if (launch_proc(argv2) == 0) { printf("Error - process run ok with invalid (zero) --socket-mem!\n"); return -1; } if (launch_proc(argv3) == 0) { printf("Error - process run ok with invalid " "(incomplete) --socket-mem!\n"); return -1; } if (launch_proc(argv4) == 0) { printf("Error - process run ok with invalid " "(mixed with invalid input) --socket-mem!\n"); return -1; } if (launch_proc(argv5) == 0) { printf("Error - process run ok with invalid " "(mixed with invalid input with a numeric value as " "last character) --socket-mem!\n"); return -1; } if (launch_proc(argv6) == 0) { printf("Error - process run ok with invalid " "(with empty socket) --socket-mem!\n"); return -1; } if (launch_proc(argv7) == 0) { printf("Error - process run ok with invalid (null) --socket-mem!\n"); return -1; } if (launch_proc(argv8) == 0) { printf("Error - process run ok with --socket-mem and -m specified!\n"); return -1; } if (launch_proc(argv9) == 0) { printf("Error - process run ok with extra socket in --socket-mem!\n"); return -1; } if (launch_proc(argv10) != 0) { printf("Error - process failed with valid --socket-mem!\n"); return -1; } return 0; } static int test_eal_flags(void) { int ret = 0; ret = test_missing_c_flag(); if (ret < 0) { printf("Error in test_missing_c_flag()\n"); return ret; } ret = test_master_lcore_flag(); if (ret < 0) { printf("Error in test_master_lcore_flag()\n"); return ret; } ret = test_missing_n_flag(); if (ret < 0) { printf("Error in test_missing_n_flag()\n"); return ret; } ret = test_no_hpet_flag(); if (ret < 0) { printf("Error in test_no_hpet_flag()\n"); return ret; } ret = test_no_huge_flag(); if (ret < 0) { printf("Error in test_no_huge_flag()\n"); return ret; } ret = test_whitelist_flag(); if (ret < 0) { printf("Error in test_invalid_whitelist_flag()\n"); return ret; } ret = test_invalid_b_flag(); if (ret < 0) { printf("Error in test_invalid_b_flag()\n"); return ret; } #ifdef RTE_LIBRTE_PMD_RING ret = test_invalid_vdev_flag(); if (ret < 0) { printf("Error in test_invalid_vdev_flag()\n"); return ret; } #endif ret = test_invalid_r_flag(); if (ret < 0) { printf("Error in test_invalid_r_flag()\n"); return ret; } ret = test_memory_flags(); if (ret < 0) { printf("Error in test_memory_flags()\n"); return ret; } ret = test_file_prefix(); if (ret < 0) { printf("Error in test_file_prefix()\n"); return ret; } #ifdef RTE_LIBRTE_XEN_DOM0 ret = test_dom0_misc_flags(); #else ret = test_misc_flags(); #endif if (ret < 0) { printf("Error in test_misc_flags()"); return ret; } return ret; } static struct test_command eal_flags_cmd = { .command = "eal_flags_autotest", .callback = test_eal_flags, }; REGISTER_TEST_COMMAND(eal_flags_cmd); ================================================ FILE: app/test/test_eal_fs.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include #include #include #include /* eal_filesystem.h is not a public header file, so use relative path */ #include "../../lib/librte_eal/common/eal_filesystem.h" static int test_parse_sysfs_value(void) { char filename[PATH_MAX] = ""; char proc_path[PATH_MAX]; char file_template[] = "/tmp/eal_test_XXXXXX"; int tmp_file_handle = -1; FILE *fd = NULL; unsigned valid_number; unsigned long retval = 0; #ifdef RTE_EXEC_ENV_BSDAPP /* BSD doesn't have /proc/pid/fd */ return 0; #endif printf("Testing function eal_parse_sysfs_value()\n"); /* get a temporary filename to use for all tests - create temp file handle and then * use /proc to get the actual file that we can open */ tmp_file_handle = mkstemp(file_template); if (tmp_file_handle == -1) { perror("mkstemp() failure"); goto error; } snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", tmp_file_handle); if (readlink(proc_path, filename, sizeof(filename)) < 0) { perror("readlink() failure"); goto error; } printf("Temporary file is: %s\n", filename); /* test we get an error value if we use file before it's created */ printf("Test reading a missing file ...\n"); if (eal_parse_sysfs_value("/dev/not-quite-null", &retval) == 0) { printf("Error with eal_parse_sysfs_value() - returned success on reading empty file\n"); goto error; } printf("Confirmed return error when reading empty file\n"); /* test reading a valid number value with "\n" on the end */ printf("Test reading valid values ...\n"); valid_number = 15; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%u\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) < 0) { printf("eal_parse_sysfs_value() returned error - test failed\n"); goto error; } if (retval != valid_number) { printf("Invalid value read by eal_parse_sysfs_value() - test failed\n"); goto error; } printf("Read '%u\\n' ok\n", valid_number); /* test reading a valid hex number value with "\n" on the end */ valid_number = 25; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"0x%x\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) < 0) { printf("eal_parse_sysfs_value() returned error - test failed\n"); goto error; } if (retval != valid_number) { printf("Invalid value read by eal_parse_sysfs_value() - test failed\n"); goto error; } printf("Read '0x%x\\n' ok\n", valid_number); printf("Test reading invalid values ...\n"); /* test reading an empty file - expect failure!*/ fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a valid number value *without* "\n" on the end - expect failure!*/ valid_number = 3; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%u", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a valid number value followed by string - expect failure!*/ valid_number = 3; fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"%uJ\n", valid_number); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } /* test reading a non-numeric value - expect failure!*/ fd = fopen(filename,"w"); if (fd == NULL) { printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno)); goto error; } fprintf(fd,"error\n"); fclose(fd); fd = NULL; if (eal_parse_sysfs_value(filename, &retval) == 0) { printf("eal_parse_sysfs_value() read invalid value - test failed\n"); goto error; } close(tmp_file_handle); unlink(filename); printf("eal_parse_sysfs_value() - OK\n"); return 0; error: if (fd) fclose(fd); if (tmp_file_handle > 0) close(tmp_file_handle); if (filename[0] != '\0') unlink(filename); return -1; } static int test_eal_fs(void) { if (test_parse_sysfs_value() < 0) return -1; return 0; } static struct test_command eal_fs_cmd = { .command = "eal_fs_autotest", .callback = test_eal_fs, }; REGISTER_TEST_COMMAND(eal_fs_cmd); ================================================ FILE: app/test/test_errno.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "test.h" static int test_errno(void) { const char *rte_retval; const char *libc_retval; #ifdef RTE_EXEC_ENV_BSDAPP /* BSD has a colon in the string, unlike linux */ const char unknown_code_result[] = "Unknown error: %d"; #else const char unknown_code_result[] = "Unknown error %d"; #endif char expected_libc_retval[sizeof(unknown_code_result)+3]; /* use a small selection of standard errors for testing */ int std_errs[] = {EAGAIN, EBADF, EACCES, EINTR, EINVAL}; /* test ALL registered RTE error codes for overlap */ int rte_errs[] = {E_RTE_SECONDARY, E_RTE_NO_CONFIG}; unsigned i; rte_errno = 0; if (rte_errno != 0) return -1; /* check for standard errors we return the same as libc */ for (i = 0; i < sizeof(std_errs)/sizeof(std_errs[0]); i++){ rte_retval = rte_strerror(std_errs[i]); libc_retval = strerror(std_errs[i]); printf("rte_strerror: '%s', strerror: '%s'\n", rte_retval, libc_retval); if (strcmp(rte_retval, libc_retval) != 0) return -1; } /* for rte-specific errors ensure we return a different string * and that the string for libc is for an unknown error */ for (i = 0; i < sizeof(rte_errs)/sizeof(rte_errs[0]); i++){ rte_retval = rte_strerror(rte_errs[i]); libc_retval = strerror(rte_errs[i]); printf("rte_strerror: '%s', strerror: '%s'\n", rte_retval, libc_retval); if (strcmp(rte_retval, libc_retval) == 0) return -1; /* generate appropriate error string for unknown error number * and then check that this is what we got back. If not, we have * a duplicate error number that conflicts with errno.h */ snprintf(expected_libc_retval, sizeof(expected_libc_retval), unknown_code_result, rte_errs[i]); if ((strcmp(expected_libc_retval, libc_retval) != 0) && (strcmp("", libc_retval) != 0)){ printf("Error, duplicate error code %d\n", rte_errs[i]); return -1; } } /* ensure that beyond RTE_MAX_ERRNO, we always get an unknown code */ rte_retval = rte_strerror(RTE_MAX_ERRNO + 1); libc_retval = strerror(RTE_MAX_ERRNO + 1); snprintf(expected_libc_retval, sizeof(expected_libc_retval), unknown_code_result, RTE_MAX_ERRNO + 1); printf("rte_strerror: '%s', strerror: '%s'\n", rte_retval, libc_retval); if ((strcmp(rte_retval, libc_retval) != 0) || (strcmp(expected_libc_retval, libc_retval) != 0)){ if (strcmp("", libc_retval) != 0){ printf("Failed test for RTE_MAX_ERRNO + 1 value\n"); return -1; } } return 0; } static struct test_command errno_cmd = { .command = "errno_autotest", .callback = test_errno, }; REGISTER_TEST_COMMAND(errno_cmd); ================================================ FILE: app/test/test_func_reentrancy.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_HASH #include #include #include #endif /* RTE_LIBRTE_HASH */ #ifdef RTE_LIBRTE_LPM #include #endif /* RTE_LIBRTE_LPM */ #include #include "test.h" typedef int (*case_func_t)(void* arg); typedef void (*case_clean_t)(unsigned lcore_id); #define MAX_STRING_SIZE (256) #define MAX_ITER_TIMES (16) #define MAX_LPM_ITER_TIMES (8) #define MEMPOOL_ELT_SIZE (0) #define MEMPOOL_SIZE (4) #define MAX_LCORES RTE_MAX_MEMZONE / (MAX_ITER_TIMES * 4U) static rte_atomic32_t synchro = RTE_ATOMIC32_INIT(0); #define WAIT_SYNCHRO_FOR_SLAVES() do{ \ if (lcore_self != rte_get_master_lcore()) \ while (rte_atomic32_read(&synchro) == 0); \ } while(0) /* * rte_eal_init only init once */ static int test_eal_init_once(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); WAIT_SYNCHRO_FOR_SLAVES(); if (rte_eal_init(0, NULL) != -1) return -1; return 0; } /* * ring create/lookup reentrancy test */ static int ring_create_lookup(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); struct rte_ring * rp; char ring_name[MAX_STRING_SIZE]; int i; WAIT_SYNCHRO_FOR_SLAVES(); /* create the same ring simultaneously on all threads */ for (i = 0; i < MAX_ITER_TIMES; i++) { rp = rte_ring_create("fr_test_once", 4096, SOCKET_ID_ANY, 0); if ((NULL == rp) && (rte_ring_lookup("fr_test_once") == NULL)) return -1; } /* create/lookup new ring several times */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(ring_name, sizeof(ring_name), "fr_test_%d_%d", lcore_self, i); rp = rte_ring_create(ring_name, 4096, SOCKET_ID_ANY, 0); if (NULL == rp) return -1; if (rte_ring_lookup(ring_name) != rp) return -1; } /* verify all ring created sucessful */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(ring_name, sizeof(ring_name), "fr_test_%d_%d", lcore_self, i); if (rte_ring_lookup(ring_name) == NULL) return -1; } return 0; } static void my_obj_init(struct rte_mempool *mp, __attribute__((unused)) void *arg, void *obj, unsigned i) { uint32_t *objnum = obj; memset(obj, 0, mp->elt_size); *objnum = i; } static int mempool_create_lookup(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); struct rte_mempool * mp; char mempool_name[MAX_STRING_SIZE]; int i; WAIT_SYNCHRO_FOR_SLAVES(); /* create the same mempool simultaneously on all threads */ for (i = 0; i < MAX_ITER_TIMES; i++) { mp = rte_mempool_create("fr_test_once", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if ((NULL == mp) && (rte_mempool_lookup("fr_test_once") == NULL)) return -1; } /* create/lookup new ring several times */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(mempool_name, sizeof(mempool_name), "fr_test_%d_%d", lcore_self, i); mp = rte_mempool_create(mempool_name, MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if (NULL == mp) return -1; if (rte_mempool_lookup(mempool_name) != mp) return -1; } /* verify all ring created sucessful */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(mempool_name, sizeof(mempool_name), "fr_test_%d_%d", lcore_self, i); if (rte_mempool_lookup(mempool_name) == NULL) return -1; } return 0; } #ifdef RTE_LIBRTE_HASH static void hash_clean(unsigned lcore_id) { char hash_name[MAX_STRING_SIZE]; struct rte_hash *handle; int i; for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(hash_name, sizeof(hash_name), "fr_test_%d_%d", lcore_id, i); if ((handle = rte_hash_find_existing(hash_name)) != NULL) rte_hash_free(handle); } } static int hash_create_free(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); struct rte_hash *handle; char hash_name[MAX_STRING_SIZE]; int i; struct rte_hash_parameters hash_params = { .name = NULL, .entries = 16, .key_len = 4, .hash_func = (rte_hash_function)rte_jhash_32b, .hash_func_init_val = 0, .socket_id = 0, }; WAIT_SYNCHRO_FOR_SLAVES(); /* create the same hash simultaneously on all threads */ hash_params.name = "fr_test_once"; for (i = 0; i < MAX_ITER_TIMES; i++) { handle = rte_hash_create(&hash_params); if ((NULL == handle) && (rte_hash_find_existing("fr_test_once") == NULL)) return -1; } /* create mutiple times simultaneously */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(hash_name, sizeof(hash_name), "fr_test_%d_%d", lcore_self, i); hash_params.name = hash_name; handle = rte_hash_create(&hash_params); if (NULL == handle) return -1; /* verify correct existing and then free all */ if (handle != rte_hash_find_existing(hash_name)) return -1; rte_hash_free(handle); } /* verify free correct */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(hash_name, sizeof(hash_name), "fr_test_%d_%d", lcore_self, i); if (NULL != rte_hash_find_existing(hash_name)) return -1; } return 0; } static void fbk_clean(unsigned lcore_id) { char fbk_name[MAX_STRING_SIZE]; struct rte_fbk_hash_table *handle; int i; for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(fbk_name, sizeof(fbk_name), "fr_test_%d_%d", lcore_id, i); if ((handle = rte_fbk_hash_find_existing(fbk_name)) != NULL) rte_fbk_hash_free(handle); } } static int fbk_create_free(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); struct rte_fbk_hash_table *handle; char fbk_name[MAX_STRING_SIZE]; int i; struct rte_fbk_hash_params fbk_params = { .name = NULL, .entries = 4, .entries_per_bucket = 4, .socket_id = 0, .hash_func = rte_jhash_1word, .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT, }; WAIT_SYNCHRO_FOR_SLAVES(); /* create the same fbk hash table simultaneously on all threads */ fbk_params.name = "fr_test_once"; for (i = 0; i < MAX_ITER_TIMES; i++) { handle = rte_fbk_hash_create(&fbk_params); if ((NULL == handle) && (rte_fbk_hash_find_existing("fr_test_once") == NULL)) return -1; } /* create mutiple fbk tables simultaneously */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(fbk_name, sizeof(fbk_name), "fr_test_%d_%d", lcore_self, i); fbk_params.name = fbk_name; handle = rte_fbk_hash_create(&fbk_params); if (NULL == handle) return -1; /* verify correct existing and then free all */ if (handle != rte_fbk_hash_find_existing(fbk_name)) return -1; rte_fbk_hash_free(handle); } /* verify free correct */ for (i = 0; i < MAX_ITER_TIMES; i++) { snprintf(fbk_name, sizeof(fbk_name), "fr_test_%d_%d", lcore_self, i); if (NULL != rte_fbk_hash_find_existing(fbk_name)) return -1; } return 0; } #endif /* RTE_LIBRTE_HASH */ #ifdef RTE_LIBRTE_LPM static void lpm_clean(unsigned lcore_id) { char lpm_name[MAX_STRING_SIZE]; struct rte_lpm *lpm; int i; for (i = 0; i < MAX_LPM_ITER_TIMES; i++) { snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", lcore_id, i); if ((lpm = rte_lpm_find_existing(lpm_name)) != NULL) rte_lpm_free(lpm); } } static int lpm_create_free(__attribute__((unused)) void *arg) { unsigned lcore_self = rte_lcore_id(); struct rte_lpm *lpm; char lpm_name[MAX_STRING_SIZE]; int i; WAIT_SYNCHRO_FOR_SLAVES(); /* create the same lpm simultaneously on all threads */ for (i = 0; i < MAX_ITER_TIMES; i++) { lpm = rte_lpm_create("fr_test_once", SOCKET_ID_ANY, 4, RTE_LPM_HEAP); if ((NULL == lpm) && (rte_lpm_find_existing("fr_test_once") == NULL)) return -1; } /* create mutiple fbk tables simultaneously */ for (i = 0; i < MAX_LPM_ITER_TIMES; i++) { snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", lcore_self, i); lpm = rte_lpm_create(lpm_name, SOCKET_ID_ANY, 4, RTE_LPM_HEAP); if (NULL == lpm) return -1; /* verify correct existing and then free all */ if (lpm != rte_lpm_find_existing(lpm_name)) return -1; rte_lpm_free(lpm); } /* verify free correct */ for (i = 0; i < MAX_LPM_ITER_TIMES; i++) { snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", lcore_self, i); if (NULL != rte_lpm_find_existing(lpm_name)) return -1; } return 0; } #endif /* RTE_LIBRTE_LPM */ struct test_case{ case_func_t func; void* arg; case_clean_t clean; char name[MAX_STRING_SIZE]; }; /* All test cases in the test suite */ struct test_case test_cases[] = { { test_eal_init_once, NULL, NULL, "eal init once" }, { ring_create_lookup, NULL, NULL, "ring create/lookup" }, { mempool_create_lookup, NULL, NULL, "mempool create/lookup" }, #ifdef RTE_LIBRTE_HASH { hash_create_free, NULL, hash_clean, "hash create/free" }, { fbk_create_free, NULL, fbk_clean, "fbk create/free" }, #endif /* RTE_LIBRTE_HASH */ #ifdef RTE_LIBRTE_LPM { lpm_create_free, NULL, lpm_clean, "lpm create/free" }, #endif /* RTE_LIBRTE_LPM */ }; /** * launch test case in two separate thread */ static int launch_test(struct test_case *pt_case) { int ret = 0; unsigned lcore_id; unsigned cores_save = rte_lcore_count(); unsigned cores = RTE_MIN(cores_save, MAX_LCORES); if (pt_case->func == NULL) return -1; rte_atomic32_set(&synchro, 0); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (cores == 1) break; cores--; rte_eal_remote_launch(pt_case->func, pt_case->arg, lcore_id); } rte_atomic32_set(&synchro, 1); if (pt_case->func(pt_case->arg) < 0) ret = -1; cores = cores_save; RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (cores == 1) break; cores--; if (rte_eal_wait_lcore(lcore_id) < 0) ret = -1; if (pt_case->clean != NULL) pt_case->clean(lcore_id); } return ret; } /** * Main entry of func_reentrancy test */ static int test_func_reentrancy(void) { uint32_t case_id; struct test_case *pt_case = NULL; if (rte_lcore_count() <= 1) { printf("Not enough lcore for testing\n"); return -1; } else if (rte_lcore_count() > MAX_LCORES) printf("Too many lcores, some cores will be disabled\n"); for (case_id = 0; case_id < sizeof(test_cases)/sizeof(struct test_case); case_id ++) { pt_case = &test_cases[case_id]; if (pt_case->func == NULL) continue; if (launch_test(pt_case) < 0) { printf("Func-ReEnt CASE %"PRIu32": %s FAIL\n", case_id, pt_case->name); return -1; } printf("Func-ReEnt CASE %"PRIu32": %s PASS\n", case_id, pt_case->name); } return 0; } static struct test_command func_reentrancy_cmd = { .command = "func_reentrancy_autotest", .callback = test_func_reentrancy, }; REGISTER_TEST_COMMAND(func_reentrancy_cmd); ================================================ FILE: app/test/test_hash.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #include #include #include #include /******************************************************************************* * Hash function performance test configuration section. Each performance test * will be performed HASHTEST_ITERATIONS times. * * The five arrays below control what tests are performed. Every combination * from the array entries is tested. */ static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc}; static uint32_t hashtest_initvals[] = {0}; static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21, 31, 32, 33, 63, 64}; /******************************************************************************/ #define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15) /* * Check condition and return an error if true. Assumes that "handle" is the * name of the hash structure pointer to be freed. */ #define RETURN_IF_ERROR(cond, str, ...) do { \ if (cond) { \ printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ if (handle) rte_hash_free(handle); \ return -1; \ } \ } while(0) #define RETURN_IF_ERROR_FBK(cond, str, ...) do { \ if (cond) { \ printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ if (handle) rte_fbk_hash_free(handle); \ return -1; \ } \ } while(0) /* 5-tuple key type */ struct flow_key { uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; uint8_t proto; } __attribute__((packed)); /* * Hash function that always returns the same value, to easily test what * happens when a bucket is full. */ static uint32_t pseudo_hash(__attribute__((unused)) const void *keys, __attribute__((unused)) uint32_t key_len, __attribute__((unused)) uint32_t init_val) { return 3; } /* * Print out result of unit test hash operation. */ #if defined(UNIT_TEST_HASH_VERBOSE) static void print_key_info(const char *msg, const struct flow_key *key, int32_t pos) { uint8_t *p = (uint8_t *)key; unsigned i; printf("%s key:0x", msg); for (i = 0; i < sizeof(struct flow_key); i++) { printf("%02X", p[i]); } printf(" @ pos %d\n", pos); } #else static void print_key_info(__attribute__((unused)) const char *msg, __attribute__((unused)) const struct flow_key *key, __attribute__((unused)) int32_t pos) { } #endif /* Keys used by unit test functions */ static struct flow_key keys[5] = { { .ip_src = IPv4(0x03, 0x02, 0x01, 0x00), .ip_dst = IPv4(0x07, 0x06, 0x05, 0x04), .port_src = 0x0908, .port_dst = 0x0b0a, .proto = 0x0c, }, { .ip_src = IPv4(0x13, 0x12, 0x11, 0x10), .ip_dst = IPv4(0x17, 0x16, 0x15, 0x14), .port_src = 0x1918, .port_dst = 0x1b1a, .proto = 0x1c, }, { .ip_src = IPv4(0x23, 0x22, 0x21, 0x20), .ip_dst = IPv4(0x27, 0x26, 0x25, 0x24), .port_src = 0x2928, .port_dst = 0x2b2a, .proto = 0x2c, }, { .ip_src = IPv4(0x33, 0x32, 0x31, 0x30), .ip_dst = IPv4(0x37, 0x36, 0x35, 0x34), .port_src = 0x3938, .port_dst = 0x3b3a, .proto = 0x3c, }, { .ip_src = IPv4(0x43, 0x42, 0x41, 0x40), .ip_dst = IPv4(0x47, 0x46, 0x45, 0x44), .port_src = 0x4948, .port_dst = 0x4b4a, .proto = 0x4c, } }; /* Parameters used for hash table in unit test functions. Name set later. */ static struct rte_hash_parameters ut_params = { .entries = 64, .key_len = sizeof(struct flow_key), /* 13 */ .hash_func = rte_jhash, .hash_func_init_val = 0, .socket_id = 0, }; #define CRC32_ITERATIONS (1U << 20) #define CRC32_DWORDS (1U << 6) /* * Test if all CRC32 implementations yield the same hash value */ static int test_crc32_hash_alg_equiv(void) { uint32_t hash_val; uint32_t init_val; uint64_t data64[CRC32_DWORDS]; unsigned i, j; size_t data_len; printf("\n# CRC32 implementations equivalence test\n"); for (i = 0; i < CRC32_ITERATIONS; i++) { /* Randomizing data_len of data set */ data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1); init_val = (uint32_t) rte_rand(); /* Fill the data set */ for (j = 0; j < CRC32_DWORDS; j++) data64[j] = rte_rand(); /* Calculate software CRC32 */ rte_hash_crc_set_alg(CRC32_SW); hash_val = rte_hash_crc(data64, data_len, init_val); /* Check against 4-byte-operand sse4.2 CRC32 if available */ rte_hash_crc_set_alg(CRC32_SSE42); if (hash_val != rte_hash_crc(data64, data_len, init_val)) { printf("Failed checking CRC32_SW against CRC32_SSE42\n"); break; } /* Check against 8-byte-operand sse4.2 CRC32 if available */ rte_hash_crc_set_alg(CRC32_SSE42_x64); if (hash_val != rte_hash_crc(data64, data_len, init_val)) { printf("Failed checking CRC32_SW against CRC32_SSE42_x64\n"); break; } } /* Resetting to best available algorithm */ rte_hash_crc_set_alg(CRC32_SSE42_x64); if (i == CRC32_ITERATIONS) return 0; printf("Failed test data (hex, %zu bytes total):\n", data_len); for (j = 0; j < data_len; j++) printf("%02X%c", ((uint8_t *)data64)[j], ((j+1) % 16 == 0 || j == data_len - 1) ? '\n' : ' '); return -1; } /* * Test a hash function. */ static void run_hash_func_test(rte_hash_function f, uint32_t init_val, uint32_t key_len) { static uint8_t key[RTE_HASH_KEY_LENGTH_MAX]; unsigned i; for (i = 0; i < key_len; i++) key[i] = (uint8_t) rte_rand(); /* just to be on the safe side */ if (!f) return; f(key, key_len, init_val); } /* * Test all hash functions. */ static void run_hash_func_tests(void) { unsigned i, j, k; for (i = 0; i < sizeof(hashtest_funcs) / sizeof(rte_hash_function); i++) { for (j = 0; j < sizeof(hashtest_initvals) / sizeof(uint32_t); j++) { for (k = 0; k < sizeof(hashtest_key_lens) / sizeof(uint32_t); k++) { run_hash_func_test(hashtest_funcs[i], hashtest_initvals[j], hashtest_key_lens[k]); } } } } /* * Basic sequence of operations for a single key: * - add * - lookup (hit) * - delete * - lookup (miss) */ static int test_add_delete(void) { struct rte_hash *handle; /* test with standard add/lookup/delete functions */ int pos0, expectedPos0; ut_params.name = "test1"; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); pos0 = rte_hash_add_key(handle, &keys[0]); print_key_info("Add", &keys[0], pos0); RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0); expectedPos0 = pos0; pos0 = rte_hash_lookup(handle, &keys[0]); print_key_info("Lkp", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to find key (pos0=%d)", pos0); pos0 = rte_hash_del_key(handle, &keys[0]); print_key_info("Del", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to delete key (pos0=%d)", pos0); pos0 = rte_hash_lookup(handle, &keys[0]); print_key_info("Lkp", &keys[0], pos0); RETURN_IF_ERROR(pos0 != -ENOENT, "fail: found key after deleting! (pos0=%d)", pos0); rte_hash_free(handle); /* repeat test with precomputed hash functions */ hash_sig_t hash_value; int pos1, expectedPos1; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); hash_value = rte_hash_hash(handle, &keys[0]); pos1 = rte_hash_add_key_with_hash(handle, &keys[0], hash_value); print_key_info("Add", &keys[0], pos1); RETURN_IF_ERROR(pos1 < 0, "failed to add key (pos1=%d)", pos1); expectedPos1 = pos1; pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value); print_key_info("Lkp", &keys[0], pos1); RETURN_IF_ERROR(pos1 != expectedPos1, "failed to find key (pos1=%d)", pos1); pos1 = rte_hash_del_key_with_hash(handle, &keys[0], hash_value); print_key_info("Del", &keys[0], pos1); RETURN_IF_ERROR(pos1 != expectedPos1, "failed to delete key (pos1=%d)", pos1); pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value); print_key_info("Lkp", &keys[0], pos1); RETURN_IF_ERROR(pos1 != -ENOENT, "fail: found key after deleting! (pos1=%d)", pos1); rte_hash_free(handle); return 0; } /* * Sequence of operations for a single key: * - delete: miss * - add * - lookup: hit * - add: update * - lookup: hit (updated data) * - delete: hit * - delete: miss * - lookup: miss */ static int test_add_update_delete(void) { struct rte_hash *handle; int pos0, expectedPos0; ut_params.name = "test2"; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); pos0 = rte_hash_del_key(handle, &keys[0]); print_key_info("Del", &keys[0], pos0); RETURN_IF_ERROR(pos0 != -ENOENT, "fail: found non-existent key (pos0=%d)", pos0); pos0 = rte_hash_add_key(handle, &keys[0]); print_key_info("Add", &keys[0], pos0); RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0); expectedPos0 = pos0; pos0 = rte_hash_lookup(handle, &keys[0]); print_key_info("Lkp", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to find key (pos0=%d)", pos0); pos0 = rte_hash_add_key(handle, &keys[0]); print_key_info("Add", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to re-add key (pos0=%d)", pos0); pos0 = rte_hash_lookup(handle, &keys[0]); print_key_info("Lkp", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to find key (pos0=%d)", pos0); pos0 = rte_hash_del_key(handle, &keys[0]); print_key_info("Del", &keys[0], pos0); RETURN_IF_ERROR(pos0 != expectedPos0, "failed to delete key (pos0=%d)", pos0); pos0 = rte_hash_del_key(handle, &keys[0]); print_key_info("Del", &keys[0], pos0); RETURN_IF_ERROR(pos0 != -ENOENT, "fail: deleted already deleted key (pos0=%d)", pos0); pos0 = rte_hash_lookup(handle, &keys[0]); print_key_info("Lkp", &keys[0], pos0); RETURN_IF_ERROR(pos0 != -ENOENT, "fail: found key after deleting! (pos0=%d)", pos0); rte_hash_free(handle); return 0; } /* * Sequence of operations for find existing hash table * * - create table * - find existing table: hit * - find non-existing table: miss * */ static int test_hash_find_existing(void) { struct rte_hash *handle = NULL, *result = NULL; /* Create hash table. */ ut_params.name = "hash_find_existing"; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); /* Try to find existing hash table */ result = rte_hash_find_existing("hash_find_existing"); RETURN_IF_ERROR(result != handle, "could not find existing hash table"); /* Try to find non-existing hash table */ result = rte_hash_find_existing("hash_find_non_existing"); RETURN_IF_ERROR(!(result == NULL), "found table that shouldn't exist"); /* Cleanup. */ rte_hash_free(handle); return 0; } /* * Sequence of operations for 5 keys * - add keys * - lookup keys: hit * - add keys (update) * - lookup keys: hit (updated data) * - delete keys : hit * - lookup keys: miss */ static int test_five_keys(void) { struct rte_hash *handle; const void *key_array[5] = {0}; int pos[5]; int expected_pos[5]; unsigned i; int ret; ut_params.name = "test3"; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); /* Add */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_add_key(handle, &keys[i]); print_key_info("Add", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] < 0, "failed to add key (pos[%u]=%d)", i, pos[i]); expected_pos[i] = pos[i]; } /* Lookup */ for(i = 0; i < 5; i++) key_array[i] = &keys[i]; ret = rte_hash_lookup_multi(handle, &key_array[0], 5, (int32_t *)pos); if(ret == 0) for(i = 0; i < 5; i++) { print_key_info("Lkp", key_array[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to find key (pos[%u]=%d)", i, pos[i]); } /* Add - update */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_add_key(handle, &keys[i]); print_key_info("Add", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to add key (pos[%u]=%d)", i, pos[i]); } /* Lookup */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_lookup(handle, &keys[i]); print_key_info("Lkp", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to find key (pos[%u]=%d)", i, pos[i]); } /* Delete */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_del_key(handle, &keys[i]); print_key_info("Del", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to delete key (pos[%u]=%d)", i, pos[i]); } /* Lookup */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_lookup(handle, &keys[i]); print_key_info("Lkp", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != -ENOENT, "found non-existent key (pos[%u]=%d)", i, pos[i]); } /* Lookup multi */ ret = rte_hash_lookup_multi(handle, &key_array[0], 5, (int32_t *)pos); if (ret == 0) for (i = 0; i < 5; i++) { print_key_info("Lkp", key_array[i], pos[i]); RETURN_IF_ERROR(pos[i] != -ENOENT, "found not-existent key (pos[%u]=%d)", i, pos[i]); } rte_hash_free(handle); return 0; } /* * Add keys to the same bucket until bucket full. * - add 5 keys to the same bucket (hash created with 4 keys per bucket): * first 4 successful, 5th successful, pushing existing item in bucket * - lookup the 5 keys: 5 hits * - add the 5 keys again: 5 OK * - lookup the 5 keys: 5 hits (updated data) * - delete the 5 keys: 5 OK * - lookup the 5 keys: 5 misses */ static int test_full_bucket(void) { struct rte_hash_parameters params_pseudo_hash = { .name = "test4", .entries = 64, .key_len = sizeof(struct flow_key), /* 13 */ .hash_func = pseudo_hash, .hash_func_init_val = 0, .socket_id = 0, }; struct rte_hash *handle; int pos[5]; int expected_pos[5]; unsigned i; handle = rte_hash_create(¶ms_pseudo_hash); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); /* Fill bucket */ for (i = 0; i < 4; i++) { pos[i] = rte_hash_add_key(handle, &keys[i]); print_key_info("Add", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] < 0, "failed to add key (pos[%u]=%d)", i, pos[i]); expected_pos[i] = pos[i]; } /* * This should work and will push one of the items * in the bucket because it is full */ pos[4] = rte_hash_add_key(handle, &keys[4]); print_key_info("Add", &keys[4], pos[4]); RETURN_IF_ERROR(pos[4] < 0, "failed to add key (pos[4]=%d)", pos[4]); expected_pos[4] = pos[4]; /* Lookup */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_lookup(handle, &keys[i]); print_key_info("Lkp", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to find key (pos[%u]=%d)", i, pos[i]); } /* Add - update */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_add_key(handle, &keys[i]); print_key_info("Add", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to add key (pos[%u]=%d)", i, pos[i]); } /* Lookup */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_lookup(handle, &keys[i]); print_key_info("Lkp", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to find key (pos[%u]=%d)", i, pos[i]); } /* Delete 1 key, check other keys are still found */ pos[1] = rte_hash_del_key(handle, &keys[1]); print_key_info("Del", &keys[1], pos[1]); RETURN_IF_ERROR(pos[1] != expected_pos[1], "failed to delete key (pos[1]=%d)", pos[1]); pos[3] = rte_hash_lookup(handle, &keys[3]); print_key_info("Lkp", &keys[3], pos[3]); RETURN_IF_ERROR(pos[3] != expected_pos[3], "failed lookup after deleting key from same bucket " "(pos[3]=%d)", pos[3]); /* Go back to previous state */ pos[1] = rte_hash_add_key(handle, &keys[1]); print_key_info("Add", &keys[1], pos[1]); expected_pos[1] = pos[1]; RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]); /* Delete */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_del_key(handle, &keys[i]); print_key_info("Del", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != expected_pos[i], "failed to delete key (pos[%u]=%d)", i, pos[i]); } /* Lookup */ for (i = 0; i < 5; i++) { pos[i] = rte_hash_lookup(handle, &keys[i]); print_key_info("Lkp", &keys[i], pos[i]); RETURN_IF_ERROR(pos[i] != -ENOENT, "fail: found non-existent key (pos[%u]=%d)", i, pos[i]); } rte_hash_free(handle); /* Cover the NULL case. */ rte_hash_free(0); return 0; } /******************************************************************************/ static int fbk_hash_unit_test(void) { struct rte_fbk_hash_params params = { .name = "fbk_hash_test", .entries = LOCAL_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_1 = { .name = "invalid_1", .entries = LOCAL_FBK_HASH_ENTRIES_MAX + 1, /* Not power of 2 */ .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_2 = { .name = "invalid_2", .entries = 4, .entries_per_bucket = 3, /* Not power of 2 */ .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_3 = { .name = "invalid_3", .entries = 0, /* Entries is 0 */ .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_4 = { .name = "invalid_4", .entries = LOCAL_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 0, /* Entries per bucket is 0 */ .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_5 = { .name = "invalid_5", .entries = 4, .entries_per_bucket = 8, /* Entries per bucket > entries */ .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_6 = { .name = "invalid_6", .entries = RTE_FBK_HASH_ENTRIES_MAX * 2, /* Entries > max allowed */ .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_7 = { .name = "invalid_7", .entries = RTE_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX * 2, /* Entries > max allowed */ .socket_id = 0, }; struct rte_fbk_hash_params invalid_params_8 = { .name = "invalid_7", .entries = RTE_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = RTE_MAX_NUMA_NODES + 1, /* invalid socket */ }; /* try to create two hashes with identical names * in this case, trying to create a second one will not * fail but will simply return pointer to the existing * hash with that name. sort of like a "find hash by name" :-) */ struct rte_fbk_hash_params invalid_params_same_name_1 = { .name = "same_name", /* hash with identical name */ .entries = 4, .entries_per_bucket = 2, .socket_id = 0, }; /* trying to create this hash should return a pointer to an existing hash */ struct rte_fbk_hash_params invalid_params_same_name_2 = { .name = "same_name", /* hash with identical name */ .entries = RTE_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, }; /* this is a sanity check for "same name" test * creating this hash will check if we are actually able to create * multiple hashes with different names (instead of having just one). */ struct rte_fbk_hash_params different_name = { .name = "different_name", /* different name */ .entries = RTE_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_params params_jhash = { .name = "valid", .entries = LOCAL_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, .hash_func = rte_jhash_1word, /* Tests for different hash_func */ .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT, }; struct rte_fbk_hash_params params_nohash = { .name = "valid nohash", .entries = LOCAL_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, .hash_func = NULL, /* Tests for null hash_func */ .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT, }; struct rte_fbk_hash_table *handle, *tmp; uint32_t keys[5] = {0xc6e18639, 0xe67c201c, 0xd4c8cffd, 0x44728691, 0xd5430fa9}; uint16_t vals[5] = {28108, 5699, 38490, 2166, 61571}; int status; unsigned i; double used_entries; /* Try creating hashes with invalid parameters */ printf("# Testing hash creation with invalid parameters " "- expect error msgs\n"); handle = rte_fbk_hash_create(&invalid_params_1); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_2); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_3); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_4); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_5); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_6); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_7); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_8); RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); handle = rte_fbk_hash_create(&invalid_params_same_name_1); RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded"); tmp = rte_fbk_hash_create(&invalid_params_same_name_2); RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded"); if (tmp != handle) { printf("ERROR line %d: hashes should have been the same\n", __LINE__); rte_fbk_hash_free(handle); rte_fbk_hash_free(tmp); return -1; } /* we are not freeing tmp or handle here because we need a hash list * to be not empty for the next test */ /* create a hash in non-empty list - good for coverage */ tmp = rte_fbk_hash_create(&different_name); RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded"); /* free both hashes */ rte_fbk_hash_free(handle); rte_fbk_hash_free(tmp); /* Create empty jhash hash. */ handle = rte_fbk_hash_create(¶ms_jhash); RETURN_IF_ERROR_FBK(handle == NULL, "fbk jhash hash creation failed"); /* Cleanup. */ rte_fbk_hash_free(handle); /* Create empty jhash hash. */ handle = rte_fbk_hash_create(¶ms_nohash); RETURN_IF_ERROR_FBK(handle == NULL, "fbk nohash hash creation failed"); /* Cleanup. */ rte_fbk_hash_free(handle); /* Create empty hash. */ handle = rte_fbk_hash_create(¶ms); RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed"); used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \ "load factor right after creation is not zero but it should be"); /* Add keys. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_add_key(handle, keys[i], vals[i]); RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed"); } used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; RETURN_IF_ERROR_FBK((unsigned)used_entries != (unsigned)((((double)5)/LOCAL_FBK_HASH_ENTRIES_MAX)*LOCAL_FBK_HASH_ENTRIES_MAX), \ "load factor now is not as expected"); /* Find value of added keys. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_lookup(handle, keys[i]); RETURN_IF_ERROR_FBK(status != vals[i], "fbk hash lookup failed"); } /* Change value of added keys. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_add_key(handle, keys[i], vals[4 - i]); RETURN_IF_ERROR_FBK(status != 0, "fbk hash update failed"); } /* Find new values. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_lookup(handle, keys[i]); RETURN_IF_ERROR_FBK(status != vals[4-i], "fbk hash lookup failed"); } /* Delete keys individually. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_delete_key(handle, keys[i]); RETURN_IF_ERROR_FBK(status != 0, "fbk hash delete failed"); } used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \ "load factor right after deletion is not zero but it should be"); /* Lookup should now fail. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_lookup(handle, keys[i]); RETURN_IF_ERROR_FBK(status == 0, "fbk hash lookup should have failed"); } /* Add keys again. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_add_key(handle, keys[i], vals[i]); RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed"); } /* Make sure they were added. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_lookup(handle, keys[i]); RETURN_IF_ERROR_FBK(status != vals[i], "fbk hash lookup failed"); } /* Clear all entries. */ rte_fbk_hash_clear_all(handle); /* Lookup should fail. */ for (i = 0; i < 5; i++) { status = rte_fbk_hash_lookup(handle, keys[i]); RETURN_IF_ERROR_FBK(status == 0, "fbk hash lookup should have failed"); } /* coverage */ /* fill up the hash_table */ for (i = 0; i < RTE_FBK_HASH_ENTRIES_MAX + 1; i++) rte_fbk_hash_add_key(handle, i, (uint16_t) i); /* Find non-existent key in a full hashtable */ status = rte_fbk_hash_lookup(handle, RTE_FBK_HASH_ENTRIES_MAX + 1); RETURN_IF_ERROR_FBK(status != -ENOENT, "fbk hash lookup succeeded"); /* Delete non-existent key in a full hashtable */ status = rte_fbk_hash_delete_key(handle, RTE_FBK_HASH_ENTRIES_MAX + 1); RETURN_IF_ERROR_FBK(status != -ENOENT, "fbk hash delete succeeded"); /* Delete one key from a full hashtable */ status = rte_fbk_hash_delete_key(handle, 1); RETURN_IF_ERROR_FBK(status != 0, "fbk hash delete failed"); /* Clear all entries. */ rte_fbk_hash_clear_all(handle); /* Cleanup. */ rte_fbk_hash_free(handle); /* Cover the NULL case. */ rte_fbk_hash_free(0); return 0; } /* * Sequence of operations for find existing fbk hash table * * - create table * - find existing table: hit * - find non-existing table: miss * */ static int test_fbk_hash_find_existing(void) { struct rte_fbk_hash_params params = { .name = "fbk_hash_find_existing", .entries = LOCAL_FBK_HASH_ENTRIES_MAX, .entries_per_bucket = 4, .socket_id = 0, }; struct rte_fbk_hash_table *handle = NULL, *result = NULL; /* Create hash table. */ handle = rte_fbk_hash_create(¶ms); RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed"); /* Try to find existing fbk hash table */ result = rte_fbk_hash_find_existing("fbk_hash_find_existing"); RETURN_IF_ERROR_FBK(result != handle, "could not find existing fbk hash table"); /* Try to find non-existing fbk hash table */ result = rte_fbk_hash_find_existing("fbk_hash_find_non_existing"); RETURN_IF_ERROR_FBK(!(result == NULL), "found fbk table that shouldn't exist"); /* Cleanup. */ rte_fbk_hash_free(handle); return 0; } #define BUCKET_ENTRIES 4 /* * Do tests for hash creation with bad parameters. */ static int test_hash_creation_with_bad_parameters(void) { struct rte_hash *handle; struct rte_hash_parameters params; handle = rte_hash_create(NULL); if (handle != NULL) { rte_hash_free(handle); printf("Impossible creating hash sucessfully without any parameter\n"); return -1; } memcpy(¶ms, &ut_params, sizeof(params)); params.name = "creation_with_bad_parameters_0"; params.entries = RTE_HASH_ENTRIES_MAX + 1; handle = rte_hash_create(¶ms); if (handle != NULL) { rte_hash_free(handle); printf("Impossible creating hash sucessfully with entries in parameter exceeded\n"); return -1; } memcpy(¶ms, &ut_params, sizeof(params)); params.name = "creation_with_bad_parameters_2"; params.entries = BUCKET_ENTRIES - 1; handle = rte_hash_create(¶ms); if (handle != NULL) { rte_hash_free(handle); printf("Impossible creating hash sucessfully if entries less than bucket_entries in parameter\n"); return -1; } memcpy(¶ms, &ut_params, sizeof(params)); params.name = "creation_with_bad_parameters_3"; params.key_len = 0; handle = rte_hash_create(¶ms); if (handle != NULL) { rte_hash_free(handle); printf("Impossible creating hash sucessfully if key_len in parameter is zero\n"); return -1; } memcpy(¶ms, &ut_params, sizeof(params)); params.name = "creation_with_bad_parameters_4"; params.socket_id = RTE_MAX_NUMA_NODES + 1; handle = rte_hash_create(¶ms); if (handle != NULL) { rte_hash_free(handle); printf("Impossible creating hash sucessfully with invalid socket\n"); return -1; } rte_hash_free(handle); printf("# Test successful. No more errors expected\n"); return 0; } /* * Do tests for hash creation with parameters that look incorrect * but are actually valid. */ static int test_hash_creation_with_good_parameters(void) { struct rte_hash *handle, *tmp; struct rte_hash_parameters params; /* create with null hash function - should choose DEFAULT_HASH_FUNC */ memcpy(¶ms, &ut_params, sizeof(params)); params.name = "same_name"; params.hash_func = NULL; handle = rte_hash_create(¶ms); if (handle == NULL) { printf("Creating hash with null hash_func failed\n"); return -1; } /* this test is trying to create a hash with the same name as previous one. * this should return a pointer to the hash we previously created. * the previous hash isn't freed exactly for the purpose of it being in * the hash list. */ memcpy(¶ms, &ut_params, sizeof(params)); params.name = "same_name"; tmp = rte_hash_create(¶ms); /* check if the returned handle is actually equal to the previous hash */ if (handle != tmp) { rte_hash_free(handle); rte_hash_free(tmp); printf("Creating hash with existing name was successful\n"); return -1; } /* try creating hash when there already are hashes in the list. * the previous hash is not freed to have a non-empty hash list. * the other hash that's in the list is still pointed to by "handle" var. */ memcpy(¶ms, &ut_params, sizeof(params)); params.name = "different_name"; tmp = rte_hash_create(¶ms); if (tmp == NULL) { rte_hash_free(handle); printf("Creating hash with valid parameters failed\n"); return -1; } rte_hash_free(tmp); rte_hash_free(handle); return 0; } #define ITERATIONS 50 /* * Test to see the average table utilization (entries added/max entries) * before hitting a random entry that cannot be added */ static int test_average_table_utilization(void) { struct rte_hash *handle; uint8_t simple_key[RTE_HASH_KEY_LENGTH_MAX]; unsigned i, j; unsigned added_keys, average_keys_added = 0; int ret; printf("\n# Running test to determine average utilization" "\n before adding elements begins to fail\n"); printf("Measuring performance, please wait"); fflush(stdout); ut_params.entries = 1 << 20; ut_params.name = "test_average_utilization"; ut_params.hash_func = rte_jhash; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); for (j = 0; j < ITERATIONS; j++) { ret = 0; /* Add random entries until key cannot be added */ for (added_keys = 0; ret >= 0; added_keys++) { for (i = 0; i < ut_params.key_len; i++) simple_key[i] = rte_rand() % 255; ret = rte_hash_add_key(handle, simple_key); } if (ret != -ENOSPC) { printf("Unexpected error when adding keys\n"); rte_hash_free(handle); return -1; } average_keys_added += added_keys; /* Reset the table */ rte_hash_reset(handle); /* Print a dot to show progress on operations */ printf("."); fflush(stdout); } average_keys_added /= ITERATIONS; printf("\nAverage table utilization = %.2f%% (%u/%u)\n", ((double) average_keys_added / ut_params.entries * 100), average_keys_added, ut_params.entries); rte_hash_free(handle); return 0; } #define NUM_ENTRIES 1024 static int test_hash_iteration(void) { struct rte_hash *handle; unsigned i; uint8_t keys[NUM_ENTRIES][RTE_HASH_KEY_LENGTH_MAX]; const void *next_key; void *next_data; void *data[NUM_ENTRIES]; unsigned added_keys; uint32_t iter = 0; int ret = 0; ut_params.entries = NUM_ENTRIES; ut_params.name = "test_hash_iteration"; ut_params.hash_func = rte_jhash; ut_params.key_len = 16; handle = rte_hash_create(&ut_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); /* Add random entries until key cannot be added */ for (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) { data[added_keys] = (void *) ((uintptr_t) rte_rand()); for (i = 0; i < ut_params.key_len; i++) keys[added_keys][i] = rte_rand() % 255; ret = rte_hash_add_key_data(handle, keys[added_keys], data[added_keys]); if (ret < 0) break; } /* Iterate through the hash table */ while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) { /* Search for the key in the list of keys added */ for (i = 0; i < NUM_ENTRIES; i++) { if (memcmp(next_key, keys[i], ut_params.key_len) == 0) { if (next_data != data[i]) { printf("Data found in the hash table is" "not the data added with the key\n"); goto err; } added_keys--; break; } } if (i == NUM_ENTRIES) { printf("Key found in the hash table was not added\n"); goto err; } } /* Check if all keys have been iterated */ if (added_keys != 0) { printf("There were still %u keys to iterate\n", added_keys); goto err; } rte_hash_free(handle); return 0; err: rte_hash_free(handle); return -1; } static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; static struct rte_hash_parameters hash_params_ex = { .name = NULL, .entries = 64, .key_len = 0, .hash_func = NULL, .hash_func_init_val = 0, .socket_id = 0, }; /* * add/delete key with jhash2 */ static int test_hash_add_delete_jhash2(void) { int ret = -1; struct rte_hash *handle; int32_t pos1, pos2; hash_params_ex.name = "hash_test_jhash2"; hash_params_ex.key_len = 4; hash_params_ex.hash_func = (rte_hash_function)rte_jhash_32b; handle = rte_hash_create(&hash_params_ex); if (handle == NULL) { printf("test_hash_add_delete_jhash2 fail to create hash\n"); goto fail_jhash2; } pos1 = rte_hash_add_key(handle, (void *)&key[0]); if (pos1 < 0) { printf("test_hash_add_delete_jhash2 fail to add hash key\n"); goto fail_jhash2; } pos2 = rte_hash_del_key(handle, (void *)&key[0]); if (pos2 < 0 || pos1 != pos2) { printf("test_hash_add_delete_jhash2 delete different key from being added\n"); goto fail_jhash2; } ret = 0; fail_jhash2: if (handle != NULL) rte_hash_free(handle); return ret; } /* * add/delete (2) key with jhash2 */ static int test_hash_add_delete_2_jhash2(void) { int ret = -1; struct rte_hash *handle; int32_t pos1, pos2; hash_params_ex.name = "hash_test_2_jhash2"; hash_params_ex.key_len = 8; hash_params_ex.hash_func = (rte_hash_function)rte_jhash_32b; handle = rte_hash_create(&hash_params_ex); if (handle == NULL) goto fail_2_jhash2; pos1 = rte_hash_add_key(handle, (void *)&key[0]); if (pos1 < 0) goto fail_2_jhash2; pos2 = rte_hash_del_key(handle, (void *)&key[0]); if (pos2 < 0 || pos1 != pos2) goto fail_2_jhash2; ret = 0; fail_2_jhash2: if (handle != NULL) rte_hash_free(handle); return ret; } static uint32_t test_hash_jhash_1word(const void *key, uint32_t length, uint32_t initval) { const uint32_t *k = key; RTE_SET_USED(length); return rte_jhash_1word(k[0], initval); } static uint32_t test_hash_jhash_2word(const void *key, uint32_t length, uint32_t initval) { const uint32_t *k = key; RTE_SET_USED(length); return rte_jhash_2words(k[0], k[1], initval); } static uint32_t test_hash_jhash_3word(const void *key, uint32_t length, uint32_t initval) { const uint32_t *k = key; RTE_SET_USED(length); return rte_jhash_3words(k[0], k[1], k[2], initval); } /* * add/delete key with jhash 1word */ static int test_hash_add_delete_jhash_1word(void) { int ret = -1; struct rte_hash *handle; int32_t pos1, pos2; hash_params_ex.name = "hash_test_jhash_1word"; hash_params_ex.key_len = 4; hash_params_ex.hash_func = test_hash_jhash_1word; handle = rte_hash_create(&hash_params_ex); if (handle == NULL) goto fail_jhash_1word; pos1 = rte_hash_add_key(handle, (void *)&key[0]); if (pos1 < 0) goto fail_jhash_1word; pos2 = rte_hash_del_key(handle, (void *)&key[0]); if (pos2 < 0 || pos1 != pos2) goto fail_jhash_1word; ret = 0; fail_jhash_1word: if (handle != NULL) rte_hash_free(handle); return ret; } /* * add/delete key with jhash 2word */ static int test_hash_add_delete_jhash_2word(void) { int ret = -1; struct rte_hash *handle; int32_t pos1, pos2; hash_params_ex.name = "hash_test_jhash_2word"; hash_params_ex.key_len = 8; hash_params_ex.hash_func = test_hash_jhash_2word; handle = rte_hash_create(&hash_params_ex); if (handle == NULL) goto fail_jhash_2word; pos1 = rte_hash_add_key(handle, (void *)&key[0]); if (pos1 < 0) goto fail_jhash_2word; pos2 = rte_hash_del_key(handle, (void *)&key[0]); if (pos2 < 0 || pos1 != pos2) goto fail_jhash_2word; ret = 0; fail_jhash_2word: if (handle != NULL) rte_hash_free(handle); return ret; } /* * add/delete key with jhash 3word */ static int test_hash_add_delete_jhash_3word(void) { int ret = -1; struct rte_hash *handle; int32_t pos1, pos2; hash_params_ex.name = "hash_test_jhash_3word"; hash_params_ex.key_len = 12; hash_params_ex.hash_func = test_hash_jhash_3word; handle = rte_hash_create(&hash_params_ex); if (handle == NULL) goto fail_jhash_3word; pos1 = rte_hash_add_key(handle, (void *)&key[0]); if (pos1 < 0) goto fail_jhash_3word; pos2 = rte_hash_del_key(handle, (void *)&key[0]); if (pos2 < 0 || pos1 != pos2) goto fail_jhash_3word; ret = 0; fail_jhash_3word: if (handle != NULL) rte_hash_free(handle); return ret; } /* * Do all unit and performance tests. */ static int test_hash(void) { if (test_add_delete() < 0) return -1; if (test_hash_add_delete_jhash2() < 0) return -1; if (test_hash_add_delete_2_jhash2() < 0) return -1; if (test_hash_add_delete_jhash_1word() < 0) return -1; if (test_hash_add_delete_jhash_2word() < 0) return -1; if (test_hash_add_delete_jhash_3word() < 0) return -1; if (test_hash_find_existing() < 0) return -1; if (test_add_update_delete() < 0) return -1; if (test_five_keys() < 0) return -1; if (test_full_bucket() < 0) return -1; if (test_fbk_hash_find_existing() < 0) return -1; if (fbk_hash_unit_test() < 0) return -1; if (test_hash_creation_with_bad_parameters() < 0) return -1; if (test_hash_creation_with_good_parameters() < 0) return -1; if (test_average_table_utilization() < 0) return -1; if (test_hash_iteration() < 0) return -1; run_hash_func_tests(); if (test_crc32_hash_alg_equiv() < 0) return -1; return 0; } static struct test_command hash_cmd = { .command = "hash_autotest", .callback = test_hash, }; REGISTER_TEST_COMMAND(hash_cmd); ================================================ FILE: app/test/test_hash_functions.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Hash values calculated for key sizes from array "hashtest_key_lens" * and for initial values from array "hashtest_initvals. * Each key will be formed by increasing each byte by 1: * e.g.: key size = 4, key = 0x03020100 * key size = 8, key = 0x0706050403020100 */ static uint32_t hash_values_jhash[2][10] = {{ 0xe4cf1d42, 0xd4ccb93c, 0x5e84eafc, 0x21362cfe, 0x2f4775ab, 0x9ff036cc, 0xeca51474, 0xbc9d6816, 0x12926a31, 0x1c9fa888 }, { 0x8270ac65, 0x05fa6668, 0x762df861, 0xda088f2f, 0x59614cd4, 0x7a94f690, 0xdc1e4993, 0x30825494, 0x91d0e462, 0x768087fc } }; static uint32_t hash_values_crc[2][10] = {{ 0x91545164, 0x06040eb1, 0x9bb99201, 0xcc4c4fe4, 0x14a90993, 0xf8a5dd8c, 0xc62beb31, 0x32bf340e, 0x72f9d22b, 0x4a11475e }, { 0x98cd4c70, 0xd52c702f, 0x41fc0e1c, 0x3905f65c, 0x94bff47f, 0x1bab102d, 0xd2911ed7, 0xe8faa813, 0x6bea184b, 0x53028d3e } }; /******************************************************************************* * Hash function performance test configuration section. Each performance test * will be performed HASHTEST_ITERATIONS times. * * The three arrays below control what tests are performed. Every combination * from the array entries is tested. */ #define HASHTEST_ITERATIONS 1000000 static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc}; static uint32_t hashtest_initvals[] = {0, 0xdeadbeef}; static uint32_t hashtest_key_lens[] = { 4, 8, 16, 32, 48, 64, /* standard key sizes */ 9, /* IPv4 SRC + DST + protocol, unpadded */ 13, /* IPv4 5-tuple, unpadded */ 37, /* IPv6 5-tuple, unpadded */ 40 /* IPv6 5-tuple, padded to 8-byte boundary */ }; /******************************************************************************/ /* * To help print out name of hash functions. */ static const char * get_hash_name(rte_hash_function f) { if (f == rte_jhash) return "jhash"; if (f == rte_hash_crc) return "rte_hash_crc"; return "UnknownHash"; } /* * Test a hash function. */ static void run_hash_func_perf_test(uint32_t key_len, uint32_t init_val, rte_hash_function f) { static uint8_t key[HASHTEST_ITERATIONS][RTE_HASH_KEY_LENGTH_MAX]; uint64_t ticks, start, end; unsigned i, j; for (i = 0; i < HASHTEST_ITERATIONS; i++) { for (j = 0; j < key_len; j++) key[i][j] = (uint8_t) rte_rand(); } start = rte_rdtsc(); for (i = 0; i < HASHTEST_ITERATIONS; i++) f(key[i], key_len, init_val); end = rte_rdtsc(); ticks = end - start; printf("%-12s, %-18u, %-13u, %.02f\n", get_hash_name(f), (unsigned) key_len, (unsigned) init_val, (double)ticks / HASHTEST_ITERATIONS); } /* * Test all hash functions. */ static void run_hash_func_perf_tests(void) { unsigned i, j, k; printf(" *** Hash function performance test results ***\n"); printf(" Number of iterations for each test = %d\n", HASHTEST_ITERATIONS); printf("Hash Func. , Key Length (bytes), Initial value, Ticks/Op.\n"); for (i = 0; i < RTE_DIM(hashtest_initvals); i++) { for (j = 0; j < RTE_DIM(hashtest_key_lens); j++) { for (k = 0; k < RTE_DIM(hashtest_funcs); k++) { run_hash_func_perf_test(hashtest_key_lens[j], hashtest_initvals[i], hashtest_funcs[k]); } } } } /* * Verify that hash functions return what they are expected to return * (using precalculated values stored above) */ static int verify_precalculated_hash_func_tests(void) { unsigned i, j; uint8_t key[64]; uint32_t hash; for (i = 0; i < 64; i++) key[i] = (uint8_t) i; for (i = 0; i < sizeof(hashtest_key_lens) / sizeof(uint32_t); i++) { for (j = 0; j < sizeof(hashtest_initvals) / sizeof(uint32_t); j++) { hash = rte_jhash(key, hashtest_key_lens[i], hashtest_initvals[j]); if (hash != hash_values_jhash[j][i]) { printf("jhash for %u bytes with initial value 0x%x." "Expected 0x%x, but got 0x%x\n", hashtest_key_lens[i], hashtest_initvals[j], hash_values_jhash[j][i], hash); return -1; } hash = rte_hash_crc(key, hashtest_key_lens[i], hashtest_initvals[j]); if (hash != hash_values_crc[j][i]) { printf("CRC for %u bytes with initial value 0x%x." "Expected 0x%x, but got 0x%x\n", hashtest_key_lens[i], hashtest_initvals[j], hash_values_crc[j][i], hash); return -1; } } } return 0; } /* * Verify that rte_jhash and rte_jhash_32b return the same */ static int verify_jhash_32bits(void) { unsigned i, j; uint8_t key[64]; uint32_t hash, hash32; for (i = 0; i < 64; i++) key[i] = rand() & 0xff; for (i = 0; i < sizeof(hashtest_key_lens) / sizeof(uint32_t); i++) { for (j = 0; j < sizeof(hashtest_initvals) / sizeof(uint32_t); j++) { /* Key size must be multiple of 4 (32 bits) */ if ((hashtest_key_lens[i] & 0x3) == 0) { hash = rte_jhash(key, hashtest_key_lens[i], hashtest_initvals[j]); /* Divide key length by 4 in rte_jhash for 32 bits */ hash32 = rte_jhash_32b((const unaligned_uint32_t *)key, hashtest_key_lens[i] >> 2, hashtest_initvals[j]); if (hash != hash32) { printf("rte_jhash returns different value (0x%x)" "than rte_jhash_32b (0x%x)\n", hash, hash32); return -1; } } } } return 0; } /* * Verify that rte_jhash and rte_jhash_1word, rte_jhash_2words * and rte_jhash_3words return the same */ static int verify_jhash_words(void) { unsigned i; uint32_t key[3]; uint32_t hash, hash_words; for (i = 0; i < 3; i++) key[i] = rand(); /* Test rte_jhash_1word */ hash = rte_jhash(key, 4, 0); hash_words = rte_jhash_1word(key[0], 0); if (hash != hash_words) { printf("rte_jhash returns different value (0x%x)" "than rte_jhash_1word (0x%x)\n", hash, hash_words); return -1; } /* Test rte_jhash_2words */ hash = rte_jhash(key, 8, 0); hash_words = rte_jhash_2words(key[0], key[1], 0); if (hash != hash_words) { printf("rte_jhash returns different value (0x%x)" "than rte_jhash_2words (0x%x)\n", hash, hash_words); return -1; } /* Test rte_jhash_3words */ hash = rte_jhash(key, 12, 0); hash_words = rte_jhash_3words(key[0], key[1], key[2], 0); if (hash != hash_words) { printf("rte_jhash returns different value (0x%x)" "than rte_jhash_3words (0x%x)\n", hash, hash_words); return -1; } return 0; } /* * Run all functional tests for hash functions */ static int run_hash_func_tests(void) { if (verify_precalculated_hash_func_tests() != 0) return -1; if (verify_jhash_32bits() != 0) return -1; if (verify_jhash_words() != 0) return -1; return 0; } static int test_hash_functions(void) { if (run_hash_func_tests() != 0) return -1; run_hash_func_perf_tests(); return 0; } static struct test_command hash_functions_cmd = { .command = "hash_functions_autotest", .callback = test_hash_functions, }; REGISTER_TEST_COMMAND(hash_functions_cmd); ================================================ FILE: app/test/test_hash_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #define MAX_ENTRIES (1 << 19) #define KEYS_TO_ADD (MAX_ENTRIES * 3 / 4) /* 75% table utilization */ #define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */ #define BUCKET_SIZE 4 #define NUM_BUCKETS (MAX_ENTRIES / BUCKET_SIZE) #define MAX_KEYSIZE 64 #define NUM_KEYSIZES 10 #define NUM_SHUFFLES 10 #define BURST_SIZE 16 enum operations { ADD = 0, LOOKUP, LOOKUP_MULTI, DELETE, NUM_OPERATIONS }; static uint32_t hashtest_key_lens[] = { /* standard key sizes */ 4, 8, 16, 32, 48, 64, /* IPv4 SRC + DST + protocol, unpadded */ 9, /* IPv4 5-tuple, unpadded */ 13, /* IPv6 5-tuple, unpadded */ 37, /* IPv6 5-tuple, padded to 8-byte boundary */ 40 }; struct rte_hash *h[NUM_KEYSIZES]; /* Array that stores if a slot is full */ uint8_t slot_taken[MAX_ENTRIES]; /* Array to store number of cycles per operation */ uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS][2][2]; /* Array to store all input keys */ uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE]; /* Array to store the precomputed hash for 'keys' */ hash_sig_t signatures[KEYS_TO_ADD]; /* Array to store how many busy entries have each bucket */ uint8_t buckets[NUM_BUCKETS]; /* Array to store the positions where keys are added */ int32_t positions[KEYS_TO_ADD]; /* Parameters used for hash table in unit test functions. */ static struct rte_hash_parameters ut_params = { .entries = MAX_ENTRIES, .hash_func = rte_jhash, .hash_func_init_val = 0, }; static int create_table(unsigned with_data, unsigned table_index) { char name[RTE_HASH_NAMESIZE]; if (with_data) /* Table will store 8-byte data */ sprintf(name, "test_hash%d_data", hashtest_key_lens[table_index]); else sprintf(name, "test_hash%d", hashtest_key_lens[table_index]); ut_params.name = name; ut_params.key_len = hashtest_key_lens[table_index]; ut_params.socket_id = rte_socket_id(); h[table_index] = rte_hash_find_existing(name); if (h[table_index] != NULL) /* * If table was already created, free it to create it again, * so we force it is empty */ rte_hash_free(h[table_index]); h[table_index] = rte_hash_create(&ut_params); if (h[table_index] == NULL) { printf("Error creating table\n"); return -1; } return 0; } /* Shuffle the keys that have been added, so lookups will be totally random */ static void shuffle_input_keys(unsigned table_index) { unsigned i; uint32_t swap_idx; uint8_t temp_key[RTE_HASH_KEY_LENGTH_MAX]; hash_sig_t temp_signature; int32_t temp_position; for (i = KEYS_TO_ADD - 1; i > 0; i--) { swap_idx = rte_rand() % i; memcpy(temp_key, keys[i], hashtest_key_lens[table_index]); temp_signature = signatures[i]; temp_position = positions[i]; memcpy(keys[i], keys[swap_idx], hashtest_key_lens[table_index]); signatures[i] = signatures[swap_idx]; positions[i] = positions[swap_idx]; memcpy(keys[swap_idx], temp_key, hashtest_key_lens[table_index]); signatures[swap_idx] = temp_signature; positions[swap_idx] = temp_position; } } /* * Looks for random keys which * ALL can fit in hash table (no errors) */ static int get_input_keys(unsigned with_pushes, unsigned table_index) { unsigned i, j; unsigned bucket_idx, incr, success = 1; uint8_t k = 0; int32_t ret; const uint32_t bucket_bitmask = NUM_BUCKETS - 1; /* Reset all arrays */ for (i = 0; i < MAX_ENTRIES; i++) slot_taken[i] = 0; for (i = 0; i < NUM_BUCKETS; i++) buckets[i] = 0; for (j = 0; j < hashtest_key_lens[table_index]; j++) keys[0][j] = 0; /* * Add only entries that are not duplicated and that fits in the table * (cannot store more than BUCKET_SIZE entries in a bucket). * Regardless a key has been added correctly or not (success), * the next one to try will be increased by 1. */ for (i = 0; i < KEYS_TO_ADD;) { incr = 0; if (i != 0) { keys[i][0] = ++k; /* Overflow, need to increment the next byte */ if (keys[i][0] == 0) incr = 1; for (j = 1; j < hashtest_key_lens[table_index]; j++) { /* Do not increase next byte */ if (incr == 0) if (success == 1) keys[i][j] = keys[i - 1][j]; else keys[i][j] = keys[i][j]; /* Increase next byte by one */ else { if (success == 1) keys[i][j] = keys[i-1][j] + 1; else keys[i][j] = keys[i][j] + 1; if (keys[i][j] == 0) incr = 1; else incr = 0; } } } success = 0; signatures[i] = rte_hash_hash(h[table_index], keys[i]); bucket_idx = signatures[i] & bucket_bitmask; /* * If we are not inserting keys in secondary location, * when bucket is full, do not try to insert the key */ if (with_pushes == 0) if (buckets[bucket_idx] == BUCKET_SIZE) continue; /* If key can be added, leave in successful key arrays "keys" */ ret = rte_hash_add_key_with_hash(h[table_index], keys[i], signatures[i]); if (ret >= 0) { /* If key is already added, ignore the entry and do not store */ if (slot_taken[ret]) continue; else { /* Store the returned position and mark slot as taken */ slot_taken[ret] = 1; positions[i] = ret; buckets[bucket_idx]++; success = 1; i++; } } } /* Reset the table, so we can measure the time to add all the entries */ rte_hash_free(h[table_index]); h[table_index] = rte_hash_create(&ut_params); return 0; } static int timed_adds(unsigned with_hash, unsigned with_data, unsigned table_index) { unsigned i; const uint64_t start_tsc = rte_rdtsc(); void *data; int32_t ret; for (i = 0; i < KEYS_TO_ADD; i++) { data = (void *) ((uintptr_t) signatures[i]); if (with_hash && with_data) { ret = rte_hash_add_key_with_hash_data(h[table_index], (const void *) keys[i], signatures[i], data); if (ret < 0) { printf("Failed to add key number %u\n", ret); return -1; } } else if (with_hash && !with_data) { ret = rte_hash_add_key_with_hash(h[table_index], (const void *) keys[i], signatures[i]); if (ret >= 0) positions[i] = ret; else { printf("Failed to add key number %u\n", ret); return -1; } } else if (!with_hash && with_data) { ret = rte_hash_add_key_data(h[table_index], (const void *) keys[i], data); if (ret < 0) { printf("Failed to add key number %u\n", ret); return -1; } } else { ret = rte_hash_add_key(h[table_index], keys[i]); if (ret >= 0) positions[i] = ret; else { printf("Failed to add key number %u\n", ret); return -1; } } } const uint64_t end_tsc = rte_rdtsc(); const uint64_t time_taken = end_tsc - start_tsc; cycles[table_index][ADD][with_hash][with_data] = time_taken/KEYS_TO_ADD; return 0; } static int timed_lookups(unsigned with_hash, unsigned with_data, unsigned table_index) { unsigned i, j; const uint64_t start_tsc = rte_rdtsc(); void *ret_data; void *expected_data; int32_t ret; for (i = 0; i < NUM_LOOKUPS/KEYS_TO_ADD; i++) { for (j = 0; j < KEYS_TO_ADD; j++) { if (with_hash && with_data) { ret = rte_hash_lookup_with_hash_data(h[table_index], (const void *) keys[j], signatures[j], &ret_data); if (ret < 0) { printf("Key number %u was not found\n", j); return -1; } expected_data = (void *) ((uintptr_t) signatures[j]); if (ret_data != expected_data) { printf("Data returned for key number %u is %p," " but should be %p\n", j, ret_data, expected_data); return -1; } } else if (with_hash && !with_data) { ret = rte_hash_lookup_with_hash(h[table_index], (const void *) keys[j], signatures[j]); if (ret < 0 || ret != positions[j]) { printf("Key looked up in %d, should be in %d\n", ret, positions[j]); return -1; } } else if (!with_hash && with_data) { ret = rte_hash_lookup_data(h[table_index], (const void *) keys[j], &ret_data); if (ret < 0) { printf("Key number %u was not found\n", j); return -1; } expected_data = (void *) ((uintptr_t) signatures[j]); if (ret_data != expected_data) { printf("Data returned for key number %u is %p," " but should be %p\n", j, ret_data, expected_data); return -1; } } else { ret = rte_hash_lookup(h[table_index], keys[j]); if (ret < 0 || ret != positions[j]) { printf("Key looked up in %d, should be in %d\n", ret, positions[j]); return -1; } } } } const uint64_t end_tsc = rte_rdtsc(); const uint64_t time_taken = end_tsc - start_tsc; cycles[table_index][LOOKUP][with_hash][with_data] = time_taken/NUM_LOOKUPS; return 0; } static int timed_lookups_multi(unsigned with_data, unsigned table_index) { unsigned i, j, k; int32_t positions_burst[BURST_SIZE]; const void *keys_burst[BURST_SIZE]; void *expected_data[BURST_SIZE]; void *ret_data[BURST_SIZE]; uint64_t hit_mask; int ret; const uint64_t start_tsc = rte_rdtsc(); for (i = 0; i < NUM_LOOKUPS/KEYS_TO_ADD; i++) { for (j = 0; j < KEYS_TO_ADD/BURST_SIZE; j++) { for (k = 0; k < BURST_SIZE; k++) keys_burst[k] = keys[j * BURST_SIZE + k]; if (with_data) { ret = rte_hash_lookup_bulk_data(h[table_index], (const void **) keys_burst, BURST_SIZE, &hit_mask, ret_data); if (ret != BURST_SIZE) { printf("Expect to find %u keys," " but found %d\n", BURST_SIZE, ret); return -1; } for (k = 0; k < BURST_SIZE; k++) { if ((hit_mask & (1ULL << k)) == 0) { printf("Key number %u not found\n", j * BURST_SIZE + k); return -1; } expected_data[k] = (void *) ((uintptr_t) signatures[j * BURST_SIZE + k]); if (ret_data[k] != expected_data[k]) { printf("Data returned for key number %u is %p," " but should be %p\n", j * BURST_SIZE + k, ret_data[k], expected_data[k]); return -1; } } } else { rte_hash_lookup_bulk(h[table_index], (const void **) keys_burst, BURST_SIZE, positions_burst); for (k = 0; k < BURST_SIZE; k++) { if (positions_burst[k] != positions[j * BURST_SIZE + k]) { printf("Key looked up in %d, should be in %d\n", positions_burst[k], positions[j * BURST_SIZE + k]); return -1; } } } } } const uint64_t end_tsc = rte_rdtsc(); const uint64_t time_taken = end_tsc - start_tsc; cycles[table_index][LOOKUP_MULTI][0][with_data] = time_taken/NUM_LOOKUPS; return 0; } static int timed_deletes(unsigned with_hash, unsigned with_data, unsigned table_index) { unsigned i; const uint64_t start_tsc = rte_rdtsc(); int32_t ret; for (i = 0; i < KEYS_TO_ADD; i++) { /* There are no delete functions with data, so just call two functions */ if (with_hash) ret = rte_hash_del_key_with_hash(h[table_index], (const void *) keys[i], signatures[i]); else ret = rte_hash_del_key(h[table_index], (const void *) keys[i]); if (ret >= 0) positions[i] = ret; else { printf("Failed to add key number %u\n", ret); return -1; } } const uint64_t end_tsc = rte_rdtsc(); const uint64_t time_taken = end_tsc - start_tsc; cycles[table_index][DELETE][with_hash][with_data] = time_taken/KEYS_TO_ADD; return 0; } static void free_table(unsigned table_index) { rte_hash_free(h[table_index]); } static void reset_table(unsigned table_index) { rte_hash_reset(h[table_index]); } static int run_all_tbl_perf_tests(unsigned with_pushes) { unsigned i, j, with_data, with_hash; printf("Measuring performance, please wait"); fflush(stdout); for (with_data = 0; with_data <= 1; with_data++) { for (i = 0; i < NUM_KEYSIZES; i++) { if (create_table(with_data, i) < 0) return -1; if (get_input_keys(with_pushes, i) < 0) return -1; for (with_hash = 0; with_hash <= 1; with_hash++) { if (timed_adds(with_hash, with_data, i) < 0) return -1; for (j = 0; j < NUM_SHUFFLES; j++) shuffle_input_keys(i); if (timed_lookups(with_hash, with_data, i) < 0) return -1; if (timed_lookups_multi(with_data, i) < 0) return -1; if (timed_deletes(with_hash, with_data, i) < 0) return -1; /* Print a dot to show progress on operations */ printf("."); fflush(stdout); reset_table(i); } free_table(i); } } printf("\nResults (in CPU cycles/operation)\n"); printf("-----------------------------------\n"); for (with_data = 0; with_data <= 1; with_data++) { if (with_data) printf("\n Operations with 8-byte data\n"); else printf("\n Operations without data\n"); for (with_hash = 0; with_hash <= 1; with_hash++) { if (with_hash) printf("\nWith pre-computed hash values\n"); else printf("\nWithout pre-computed hash values\n"); printf("\n%-18s%-18s%-18s%-18s%-18s\n", "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete"); for (i = 0; i < NUM_KEYSIZES; i++) { printf("%-18d", hashtest_key_lens[i]); for (j = 0; j < NUM_OPERATIONS; j++) printf("%-18"PRIu64, cycles[i][j][with_hash][with_data]); printf("\n"); } } } return 0; } /* Control operation of performance testing of fbk hash. */ #define LOAD_FACTOR 0.667 /* How full to make the hash table. */ #define TEST_SIZE 1000000 /* How many operations to time. */ #define TEST_ITERATIONS 30 /* How many measurements to take. */ #define ENTRIES (1 << 15) /* How many entries. */ static int fbk_hash_perf_test(void) { struct rte_fbk_hash_params params = { .name = "fbk_hash_test", .entries = ENTRIES, .entries_per_bucket = 4, .socket_id = rte_socket_id(), }; struct rte_fbk_hash_table *handle = NULL; uint32_t *keys = NULL; unsigned indexes[TEST_SIZE]; uint64_t lookup_time = 0; unsigned added = 0; unsigned value = 0; uint32_t key; uint16_t val; unsigned i, j; handle = rte_fbk_hash_create(¶ms); if (handle == NULL) { printf("Error creating table\n"); return -1; } keys = rte_zmalloc(NULL, ENTRIES * sizeof(*keys), 0); if (keys == NULL) { printf("fbk hash: memory allocation for key store failed\n"); return -1; } /* Generate random keys and values. */ for (i = 0; i < ENTRIES; i++) { key = (uint32_t)rte_rand(); key = ((uint64_t)key << 32) | (uint64_t)rte_rand(); val = (uint16_t)rte_rand(); if (rte_fbk_hash_add_key(handle, key, val) == 0) { keys[added] = key; added++; } if (added > (LOAD_FACTOR * ENTRIES)) break; } for (i = 0; i < TEST_ITERATIONS; i++) { uint64_t begin; uint64_t end; /* Generate random indexes into keys[] array. */ for (j = 0; j < TEST_SIZE; j++) indexes[j] = rte_rand() % added; begin = rte_rdtsc(); /* Do lookups */ for (j = 0; j < TEST_SIZE; j++) value += rte_fbk_hash_lookup(handle, keys[indexes[j]]); end = rte_rdtsc(); lookup_time += (double)(end - begin); } printf("\n\n *** FBK Hash function performance test results ***\n"); /* * The use of the 'value' variable ensures that the hash lookup is not * being optimised out by the compiler. */ if (value != 0) printf("Number of ticks per lookup = %g\n", (double)lookup_time / ((double)TEST_ITERATIONS * (double)TEST_SIZE)); rte_fbk_hash_free(handle); return 0; } static int test_hash_perf(void) { unsigned with_pushes; for (with_pushes = 0; with_pushes <= 1; with_pushes++) { if (with_pushes == 0) printf("\nALL ELEMENTS IN PRIMARY LOCATION\n"); else printf("\nELEMENTS IN PRIMARY OR SECONDARY LOCATION\n"); if (run_all_tbl_perf_tests(with_pushes) < 0) return -1; } if (fbk_hash_perf_test() < 0) return -1; return 0; } static struct test_command hash_perf_cmd = { .command = "hash_perf_autotest", .callback = test_hash_perf, }; REGISTER_TEST_COMMAND(hash_perf_cmd); ================================================ FILE: app/test/test_hash_scaling.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" /* * Check condition and return an error if true. Assumes that "handle" is the * name of the hash structure pointer to be freed. */ #define RETURN_IF_ERROR(cond, str, ...) do { \ if (cond) { \ printf("ERROR line %d: " str "\n", __LINE__, \ ##__VA_ARGS__); \ if (handle) \ rte_hash_free(handle); \ return -1; \ } \ } while (0) enum locking_mode_t { NORMAL_LOCK, LOCK_ELISION, NULL_LOCK }; struct { uint32_t num_iterations; struct rte_hash *h; rte_spinlock_t *lock; int locking_mode; } tbl_scaling_test_params; static rte_atomic64_t gcycles; static int test_hash_scaling_worker(__attribute__((unused)) void *arg) { uint64_t i, key; uint32_t thr_id = rte_sys_gettid(); uint64_t begin, cycles = 0; switch (tbl_scaling_test_params.locking_mode) { case NORMAL_LOCK: for (i = 0; i < tbl_scaling_test_params.num_iterations; i++) { /* different threads get different keys because we use the thread-id in the key computation */ key = rte_hash_crc(&i, sizeof(i), thr_id); begin = rte_rdtsc_precise(); rte_spinlock_lock(tbl_scaling_test_params.lock); rte_hash_add_key(tbl_scaling_test_params.h, &key); rte_spinlock_unlock(tbl_scaling_test_params.lock); cycles += rte_rdtsc_precise() - begin; } break; case LOCK_ELISION: for (i = 0; i < tbl_scaling_test_params.num_iterations; i++) { key = rte_hash_crc(&i, sizeof(i), thr_id); begin = rte_rdtsc_precise(); rte_spinlock_lock_tm(tbl_scaling_test_params.lock); rte_hash_add_key(tbl_scaling_test_params.h, &key); rte_spinlock_unlock_tm(tbl_scaling_test_params.lock); cycles += rte_rdtsc_precise() - begin; } break; default: for (i = 0; i < tbl_scaling_test_params.num_iterations; i++) { key = rte_hash_crc(&i, sizeof(i), thr_id); begin = rte_rdtsc_precise(); rte_hash_add_key(tbl_scaling_test_params.h, &key); cycles += rte_rdtsc_precise() - begin; } } rte_atomic64_add(&gcycles, cycles); return 0; } /* * Do scalability perf tests. */ static int test_hash_scaling(int locking_mode) { static unsigned calledCount = 1; uint32_t num_iterations = 1024*1024; uint64_t i, key; struct rte_hash_parameters hash_params = { .entries = num_iterations*2, .key_len = sizeof(key), .hash_func = rte_hash_crc, .hash_func_init_val = 0, .socket_id = rte_socket_id(), }; struct rte_hash *handle; char name[RTE_HASH_NAMESIZE]; rte_spinlock_t lock; rte_spinlock_init(&lock); snprintf(name, 32, "test%u", calledCount++); hash_params.name = name; handle = rte_hash_create(&hash_params); RETURN_IF_ERROR(handle == NULL, "hash creation failed"); tbl_scaling_test_params.num_iterations = num_iterations/rte_lcore_count(); tbl_scaling_test_params.h = handle; tbl_scaling_test_params.lock = &lock; tbl_scaling_test_params.locking_mode = locking_mode; rte_atomic64_init(&gcycles); rte_atomic64_clear(&gcycles); /* fill up to initial size */ for (i = 0; i < num_iterations; i++) { key = rte_hash_crc(&i, sizeof(i), 0xabcdabcd); rte_hash_add_key(tbl_scaling_test_params.h, &key); } rte_eal_mp_remote_launch(test_hash_scaling_worker, NULL, CALL_MASTER); rte_eal_mp_wait_lcore(); unsigned long long int cycles_per_operation = rte_atomic64_read(&gcycles)/ (tbl_scaling_test_params.num_iterations*rte_lcore_count()); const char *lock_name; switch (locking_mode) { case NORMAL_LOCK: lock_name = "normal spinlock"; break; case LOCK_ELISION: lock_name = "lock elision"; break; default: lock_name = "null lock"; } printf("--------------------------------------------------------\n"); printf("Cores: %d; %s mode -> cycles per operation: %llu\n", rte_lcore_count(), lock_name, cycles_per_operation); printf("--------------------------------------------------------\n"); /* CSV output */ printf(">>>%d,%s,%llu\n", rte_lcore_count(), lock_name, cycles_per_operation); rte_hash_free(handle); return 0; } static int test_hash_scaling_main(void) { int r = 0; if (rte_lcore_count() == 1) r = test_hash_scaling(NULL_LOCK); if (r == 0) r = test_hash_scaling(NORMAL_LOCK); if (!rte_tm_supported()) { printf("Hardware transactional memory (lock elision) is NOT supported\n"); return r; } printf("Hardware transactional memory (lock elision) is supported\n"); if (r == 0) r = test_hash_scaling(LOCK_ELISION); return r; } static struct test_command hash_scaling_cmd = { .command = "hash_scaling_autotest", .callback = test_hash_scaling_main, }; REGISTER_TEST_COMMAND(hash_scaling_cmd); ================================================ FILE: app/test/test_interrupts.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "test.h" #define TEST_INTERRUPT_CHECK_INTERVAL 1000 /* ms */ /* predefined interrupt handle types */ enum test_interrupt_handle_type { TEST_INTERRUPT_HANDLE_INVALID, TEST_INTERRUPT_HANDLE_VALID, TEST_INTERRUPT_HANDLE_VALID_UIO, TEST_INTERRUPT_HANDLE_VALID_ALARM, TEST_INTERRUPT_HANDLE_CASE1, TEST_INTERRUPT_HANDLE_MAX }; /* flag of if callback is called */ static volatile int flag; static struct rte_intr_handle intr_handles[TEST_INTERRUPT_HANDLE_MAX]; static enum test_interrupt_handle_type test_intr_type = TEST_INTERRUPT_HANDLE_MAX; #ifdef RTE_EXEC_ENV_LINUXAPP union intr_pipefds{ struct { int pipefd[2]; }; struct { int readfd; int writefd; }; }; static union intr_pipefds pfds; /** * Check if the interrupt handle is valid. */ static inline int test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle) { if (!intr_handle || intr_handle->fd < 0) return -1; return 0; } /** * Initialization for interrupt test. */ static int test_interrupt_init(void) { if (pipe(pfds.pipefd) < 0) return -1; intr_handles[TEST_INTERRUPT_HANDLE_INVALID].fd = -1; intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type = RTE_INTR_HANDLE_UNKNOWN; intr_handles[TEST_INTERRUPT_HANDLE_VALID].fd = pfds.readfd; intr_handles[TEST_INTERRUPT_HANDLE_VALID].type = RTE_INTR_HANDLE_UNKNOWN; intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].fd = pfds.readfd; intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].type = RTE_INTR_HANDLE_UIO; intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].fd = pfds.readfd; intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].type = RTE_INTR_HANDLE_ALARM; intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.writefd; intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_UIO; return 0; } /** * Deinitialization for interrupt test. */ static int test_interrupt_deinit(void) { close(pfds.pipefd[0]); close(pfds.pipefd[1]); return 0; } /** * Write the pipe to simulate an interrupt. */ static int test_interrupt_trigger_interrupt(void) { if (write(pfds.writefd, "1", 1) < 0) return -1; return 0; } /** * Check if two interrupt handles are the same. */ static int test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, struct rte_intr_handle *intr_handle_r) { if (!intr_handle_l || !intr_handle_r) return -1; if (intr_handle_l->fd != intr_handle_r->fd || intr_handle_l->type != intr_handle_r->type) return -1; return 0; } #else /* to be implemented for bsd later */ static inline int test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); return 0; } static int test_interrupt_init(void) { return 0; } static int test_interrupt_deinit(void) { return 0; } static int test_interrupt_trigger_interrupt(void) { return 0; } static int test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, struct rte_intr_handle *intr_handle_r) { (void)intr_handle_l; (void)intr_handle_r; return 0; } #endif /* RTE_EXEC_ENV_LINUXAPP */ /** * Callback for the test interrupt. */ static void test_interrupt_callback(struct rte_intr_handle *intr_handle, void *arg) { if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) { printf("invalid interrupt type\n"); flag = -1; return; } if (test_interrupt_handle_sanity_check(intr_handle) < 0) { printf("null or invalid intr_handle for %s\n", __func__); flag = -1; return; } if (rte_intr_callback_unregister(intr_handle, test_interrupt_callback, arg) >= 0) { printf("%s: unexpectedly able to unregister itself\n", __func__); flag = -1; return; } if (test_interrupt_handle_compare(intr_handle, &(intr_handles[test_intr_type])) == 0) flag = 1; } /** * Callback for the test interrupt. */ static void test_interrupt_callback_1(struct rte_intr_handle *intr_handle, __attribute__((unused)) void *arg) { if (test_interrupt_handle_sanity_check(intr_handle) < 0) { printf("null or invalid intr_handle for %s\n", __func__); flag = -1; return; } } /** * Tests for rte_intr_enable(). */ static int test_interrupt_enable(void) { struct rte_intr_handle test_intr_handle; /* check with null intr_handle */ if (rte_intr_enable(NULL) == 0) { printf("unexpectedly enable null intr_handle successfully\n"); return -1; } /* check with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_enable(&test_intr_handle) == 0) { printf("unexpectedly enable invalid intr_handle " "successfully\n"); return -1; } /* check with valid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; if (rte_intr_enable(&test_intr_handle) == 0) { printf("unexpectedly enable a specific intr_handle " "successfully\n"); return -1; } /* check with specific valid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; if (rte_intr_enable(&test_intr_handle) == 0) { printf("unexpectedly enable a specific intr_handle " "successfully\n"); return -1; } /* check with valid handler and its type */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1]; if (rte_intr_enable(&test_intr_handle) < 0) { printf("fail to enable interrupt on a simulated handler\n"); return -1; } test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; if (rte_intr_enable(&test_intr_handle) == 0) { printf("unexpectedly enable a specific intr_handle " "successfully\n"); return -1; } return 0; } /** * Tests for rte_intr_disable(). */ static int test_interrupt_disable(void) { struct rte_intr_handle test_intr_handle; /* check with null intr_handle */ if (rte_intr_disable(NULL) == 0) { printf("unexpectedly disable null intr_handle " "successfully\n"); return -1; } /* check with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_disable(&test_intr_handle) == 0) { printf("unexpectedly disable invalid intr_handle " "successfully\n"); return -1; } /* check with valid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; if (rte_intr_disable(&test_intr_handle) == 0) { printf("unexpectedly disable a specific intr_handle " "successfully\n"); return -1; } /* check with specific valid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; if (rte_intr_disable(&test_intr_handle) == 0) { printf("unexpectedly disable a specific intr_handle " "successfully\n"); return -1; } /* check with valid handler and its type */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1]; if (rte_intr_disable(&test_intr_handle) < 0) { printf("fail to disable interrupt on a simulated handler\n"); return -1; } test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; if (rte_intr_disable(&test_intr_handle) == 0) { printf("unexpectedly disable a specific intr_handle " "successfully\n"); return -1; } return 0; } /** * Check the full path of a specified type of interrupt simulated. */ static int test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type) { int count; struct rte_intr_handle test_intr_handle; flag = 0; test_intr_handle = intr_handles[intr_type]; test_intr_type = intr_type; if (rte_intr_callback_register(&test_intr_handle, test_interrupt_callback, NULL) < 0) { printf("fail to register callback\n"); return -1; } if (test_interrupt_trigger_interrupt() < 0) return -1; /* check flag in 3 seconds */ for (count = 0; flag == 0 && count < 3; count++) rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, NULL) < 0) return -1; if (flag == 0) { printf("callback has not been called\n"); return -1; } else if (flag < 0) { printf("it has internal error in callback\n"); return -1; } return 0; } /** * Main function of testing interrupt. */ static int test_interrupt(void) { int ret = -1; struct rte_intr_handle test_intr_handle; if (test_interrupt_init() < 0) { printf("fail to initialize for testing interrupt\n"); return -1; } printf("Check unknown valid interrupt full path\n"); if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) { printf("failure occured during checking unknown valid " "interrupt full path\n"); goto out; } printf("Check valid UIO interrupt full path\n"); if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO) < 0) { printf("failure occured during checking valid UIO interrupt " "full path\n"); goto out; } printf("Check valid alarm interrupt full path\n"); if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) { printf("failure occured during checking valid alarm " "interrupt full path\n"); goto out; } printf("start register/unregister test\n"); /* check if it will fail to register cb with intr_handle = NULL */ if (rte_intr_callback_register(NULL, test_interrupt_callback, NULL) == 0) { printf("unexpectedly register successfully with null " "intr_handle\n"); goto out; } /* check if it will fail to register cb with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_callback_register(&test_intr_handle, test_interrupt_callback, NULL) == 0) { printf("unexpectedly register successfully with invalid " "intr_handle\n"); goto out; } /* check if it will fail to register without callback */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; if (rte_intr_callback_register(&test_intr_handle, NULL, NULL) == 0) { printf("unexpectedly register successfully with " "null callback\n"); goto out; } /* check if it will fail to unregister cb with intr_handle = NULL */ if (rte_intr_callback_unregister(NULL, test_interrupt_callback, NULL) > 0) { printf("unexpectedly unregister successfully with " "null intr_handle\n"); goto out; } /* check if it will fail to unregister cb with invalid intr_handle */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID]; if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, NULL) > 0) { printf("unexpectedly unregister successfully with " "invalid intr_handle\n"); goto out; } /* check if it is ok to register the same intr_handle twice */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; if (rte_intr_callback_register(&test_intr_handle, test_interrupt_callback, NULL) < 0) { printf("it fails to register test_interrupt_callback\n"); goto out; } if (rte_intr_callback_register(&test_intr_handle, test_interrupt_callback_1, NULL) < 0) { printf("it fails to register test_interrupt_callback_1\n"); goto out; } /* check if it will fail to unregister with invalid parameter */ if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, (void *)0xff) != 0) { printf("unexpectedly unregisters successfully with " "invalid arg\n"); goto out; } if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, NULL) <= 0) { printf("it fails to unregister test_interrupt_callback\n"); goto out; } if (rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback_1, (void *)-1) <= 0) { printf("it fails to unregister test_interrupt_callback_1 " "for all\n"); goto out; } rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); printf("start interrupt enable/disable test\n"); /* check interrupt enable/disable functions */ if (test_interrupt_enable() < 0) { printf("fail to check interrupt enabling\n"); goto out; } rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); if (test_interrupt_disable() < 0) { printf("fail to check interrupt disabling\n"); goto out; } rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); ret = 0; out: printf("Clearing for interrupt tests\n"); /* clear registered callbacks */ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID]; rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, (void *)-1); rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback_1, (void *)-1); test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO]; rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, (void *)-1); rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback_1, (void *)-1); test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM]; rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback, (void *)-1); rte_intr_callback_unregister(&test_intr_handle, test_interrupt_callback_1, (void *)-1); rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL); /* deinit */ test_interrupt_deinit(); return ret; } static struct test_command interrupt_cmd = { .command = "interrupt_autotest", .callback = test_interrupt, }; REGISTER_TEST_COMMAND(interrupt_cmd); ================================================ FILE: app/test/test_ivshmem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "test.h" #include #include #include #include "process.h" #define DUPLICATE_METADATA "duplicate" #define METADATA_NAME "metadata" #define NONEXISTENT_METADATA "nonexistent" #define FIRST_TEST 'a' #define launch_proc(ARGV) process_dup(ARGV, \ sizeof(ARGV)/(sizeof(ARGV[0])), "test_ivshmem") #define ASSERT(cond,msg) do { \ if (!(cond)) { \ printf("**** TEST %s() failed: %s\n", \ __func__, msg); \ return -1; \ } \ } while(0) static char* get_current_prefix(char * prefix, int size) { char path[PATH_MAX] = {0}; char buf[PATH_MAX] = {0}; /* get file for config (fd is always 3) */ snprintf(path, sizeof(path), "/proc/self/fd/%d", 3); /* return NULL on error */ if (readlink(path, buf, sizeof(buf)) == -1) return NULL; /* get the basename */ snprintf(buf, sizeof(buf), "%s", basename(buf)); /* copy string all the way from second char up to start of _config */ snprintf(prefix, size, "%.*s", (int)(strnlen(buf, sizeof(buf)) - sizeof("_config")), &buf[1]); return prefix; } static struct rte_ivshmem_metadata* mmap_metadata(const char *name) { int fd; char pathname[PATH_MAX]; struct rte_ivshmem_metadata *metadata; snprintf(pathname, sizeof(pathname), "/var/run/.dpdk_ivshmem_metadata_%s", name); fd = open(pathname, O_RDWR, 0660); if (fd < 0) return NULL; metadata = (struct rte_ivshmem_metadata*) mmap(NULL, sizeof(struct rte_ivshmem_metadata), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (metadata == MAP_FAILED) return NULL; close(fd); return metadata; } static int create_duplicate(void) { /* create a metadata that another process will then try to overwrite */ ASSERT (rte_ivshmem_metadata_create(DUPLICATE_METADATA) == 0, "Creating metadata failed"); return 0; } static int test_ivshmem_create_lots_of_memzones(void) { int i; char name[IVSHMEM_NAME_LEN]; const struct rte_memzone *mz; ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0, "Failed to create metadata"); for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_ENTRIES; i++) { snprintf(name, sizeof(name), "mz_%i", i); mz = rte_memzone_reserve(name, RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0); ASSERT(mz != NULL, "Failed to reserve memzone"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0, "Failed to add memzone"); } mz = rte_memzone_reserve("one too many", RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0); ASSERT(mz != NULL, "Failed to reserve memzone"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) < 0, "Metadata should have been full"); return 0; } static int test_ivshmem_create_duplicate_memzone(void) { const struct rte_memzone *mz; ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0, "Failed to create metadata"); mz = rte_memzone_reserve("mz", RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0); ASSERT(mz != NULL, "Failed to reserve memzone"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0, "Failed to add memzone"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) < 0, "Added the same memzone twice"); return 0; } static int test_ivshmem_api_test(void) { const struct rte_memzone * mz; struct rte_mempool * mp; struct rte_ring * r; char buf[BUFSIZ]; memset(buf, 0, sizeof(buf)); r = rte_ring_create("ring", 1, SOCKET_ID_ANY, 0); mp = rte_mempool_create("mempool", 1, 1, 1, 1, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); mz = rte_memzone_reserve("memzone", 64, SOCKET_ID_ANY, 0); ASSERT(r != NULL, "Failed to create ring"); ASSERT(mp != NULL, "Failed to create mempool"); ASSERT(mz != NULL, "Failed to reserve memzone"); /* try to create NULL metadata */ ASSERT(rte_ivshmem_metadata_create(NULL) < 0, "Created metadata with NULL name"); /* create valid metadata to do tests on */ ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0, "Failed to create metadata"); /* test adding memzone */ ASSERT(rte_ivshmem_metadata_add_memzone(NULL, NULL) < 0, "Added NULL memzone to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_memzone(NULL, METADATA_NAME) < 0, "Added NULL memzone"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, NULL) < 0, "Added memzone to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_memzone(mz, NONEXISTENT_METADATA) < 0, "Added memzone to nonexistent metadata"); /* test adding ring */ ASSERT(rte_ivshmem_metadata_add_ring(NULL, NULL) < 0, "Added NULL ring to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_ring(NULL, METADATA_NAME) < 0, "Added NULL ring"); ASSERT(rte_ivshmem_metadata_add_ring(r, NULL) < 0, "Added ring to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_ring(r, NONEXISTENT_METADATA) < 0, "Added ring to nonexistent metadata"); /* test adding mempool */ ASSERT(rte_ivshmem_metadata_add_mempool(NULL, NULL) < 0, "Added NULL mempool to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_mempool(NULL, METADATA_NAME) < 0, "Added NULL mempool"); ASSERT(rte_ivshmem_metadata_add_mempool(mp, NULL) < 0, "Added mempool to NULL metadata"); ASSERT(rte_ivshmem_metadata_add_mempool(mp, NONEXISTENT_METADATA) < 0, "Added mempool to nonexistent metadata"); /* test creating command line */ ASSERT(rte_ivshmem_metadata_cmdline_generate(NULL, sizeof(buf), METADATA_NAME) < 0, "Written command line into NULL buffer"); ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty"); ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, 0, METADATA_NAME) < 0, "Written command line into small buffer"); ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty"); ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf), NULL) < 0, "Written command line for NULL metadata"); ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty"); ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf), NONEXISTENT_METADATA) < 0, "Writen command line for nonexistent metadata"); ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty"); /* add stuff to config */ ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0, "Failed to add memzone to valid config"); ASSERT(rte_ivshmem_metadata_add_ring(r, METADATA_NAME) == 0, "Failed to add ring to valid config"); ASSERT(rte_ivshmem_metadata_add_mempool(mp, METADATA_NAME) == 0, "Failed to add mempool to valid config"); /* create config */ ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf), METADATA_NAME) == 0, "Failed to write command-line"); /* check if something was written */ ASSERT(strnlen(buf, sizeof(buf)) != 0, "Buffer is empty"); /* make sure we don't segfault */ rte_ivshmem_metadata_dump(stdout, NULL); /* dump our metadata */ rte_ivshmem_metadata_dump(stdout, METADATA_NAME); return 0; } static int test_ivshmem_create_duplicate_metadata(void) { ASSERT(rte_ivshmem_metadata_create(DUPLICATE_METADATA) < 0, "Creating duplicate metadata should have failed"); return 0; } static int test_ivshmem_create_metadata_config(void) { struct rte_ivshmem_metadata *metadata; rte_ivshmem_metadata_create(METADATA_NAME); metadata = mmap_metadata(METADATA_NAME); ASSERT(metadata != MAP_FAILED, "Metadata mmaping failed"); ASSERT(metadata->magic_number == IVSHMEM_MAGIC, "Magic number is not that magic"); ASSERT(strncmp(metadata->name, METADATA_NAME, sizeof(metadata->name)) == 0, "Name has not been set up"); ASSERT(metadata->entry[0].offset == 0, "Offest is not initialized"); ASSERT(metadata->entry[0].mz.addr == 0, "mz.addr is not initialized"); ASSERT(metadata->entry[0].mz.len == 0, "mz.len is not initialized"); return 0; } static int test_ivshmem_create_multiple_metadata_configs(void) { int i; char name[IVSHMEM_NAME_LEN]; struct rte_ivshmem_metadata *metadata; for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES / 2; i++) { snprintf(name, sizeof(name), "test_%d", i); rte_ivshmem_metadata_create(name); metadata = mmap_metadata(name); ASSERT(metadata->magic_number == IVSHMEM_MAGIC, "Magic number is not that magic"); ASSERT(strncmp(metadata->name, name, sizeof(metadata->name)) == 0, "Name has not been set up"); } return 0; } static int test_ivshmem_create_too_many_metadata_configs(void) { int i; char name[IVSHMEM_NAME_LEN]; for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES; i++) { snprintf(name, sizeof(name), "test_%d", i); ASSERT(rte_ivshmem_metadata_create(name) == 0, "Create config file failed"); } ASSERT(rte_ivshmem_metadata_create(name) < 0, "Create config file didn't fail"); return 0; } enum rte_ivshmem_tests { _test_ivshmem_api_test = 0, _test_ivshmem_create_metadata_config, _test_ivshmem_create_multiple_metadata_configs, _test_ivshmem_create_too_many_metadata_configs, _test_ivshmem_create_duplicate_metadata, _test_ivshmem_create_lots_of_memzones, _test_ivshmem_create_duplicate_memzone, _last_test, }; #define RTE_IVSHMEM_TEST_ID "RTE_IVSHMEM_TEST_ID" static int launch_all_tests_on_secondary_processes(void) { int ret = 0; char id; char testid; char tmp[PATH_MAX] = {0}; char prefix[PATH_MAX] = {0}; get_current_prefix(tmp, sizeof(tmp)); snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); const char *argv[] = { prgname, "-c", "1", "-n", "3", "--proc-type=secondary", prefix }; for (id = 0; id < _last_test; id++) { testid = (char)(FIRST_TEST + id); setenv(RTE_IVSHMEM_TEST_ID, &testid, 1); if (launch_proc(argv) != 0) return -1; } return ret; } int test_ivshmem(void) { int testid; /* We want to have a clean execution for every test without exposing * private global data structures in rte_ivshmem so we launch each test * on a different secondary process. */ if (rte_eal_process_type() == RTE_PROC_PRIMARY) { /* first, create metadata */ ASSERT(create_duplicate() == 0, "Creating metadata failed"); return launch_all_tests_on_secondary_processes(); } testid = *(getenv(RTE_IVSHMEM_TEST_ID)) - FIRST_TEST; printf("Secondary process running test %d \n", testid); switch (testid) { case _test_ivshmem_api_test: return test_ivshmem_api_test(); case _test_ivshmem_create_metadata_config: return test_ivshmem_create_metadata_config(); case _test_ivshmem_create_multiple_metadata_configs: return test_ivshmem_create_multiple_metadata_configs(); case _test_ivshmem_create_too_many_metadata_configs: return test_ivshmem_create_too_many_metadata_configs(); case _test_ivshmem_create_duplicate_metadata: return test_ivshmem_create_duplicate_metadata(); case _test_ivshmem_create_lots_of_memzones: return test_ivshmem_create_lots_of_memzones(); case _test_ivshmem_create_duplicate_memzone: return test_ivshmem_create_duplicate_memzone(); default: break; } return -1; } static struct test_command ivshmem_cmd = { .command = "ivshmem_autotest", .callback = test_ivshmem, }; REGISTER_TEST_COMMAND(ivshmem_cmd); ================================================ FILE: app/test/test_kni.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" #include #include #include #include #include #define NB_MBUF 8192 #define MAX_PACKET_SZ 2048 #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) #define PKT_BURST_SZ 32 #define MEMPOOL_CACHE_SZ PKT_BURST_SZ #define SOCKET 0 #define NB_RXD 128 #define NB_TXD 512 #define KNI_TIMEOUT_MS 5000 /* ms */ #define IFCONFIG "/sbin/ifconfig " #define TEST_KNI_PORT "test_kni_port" #define KNI_TEST_MAX_PORTS 4 /* The threshold number of mbufs to be transmitted or received. */ #define KNI_NUM_MBUF_THRESHOLD 100 static int kni_pkt_mtu = 0; struct test_kni_stats { volatile uint64_t ingress; volatile uint64_t egress; }; static const struct rte_eth_rxconf rx_conf = { .rx_thresh = { .pthresh = 8, .hthresh = 8, .wthresh = 4, }, .rx_free_thresh = 0, }; static const struct rte_eth_txconf tx_conf = { .tx_thresh = { .pthresh = 36, .hthresh = 0, .wthresh = 0, }, .tx_free_thresh = 0, .tx_rs_thresh = 0, }; static const struct rte_eth_conf port_conf = { .rxmode = { .header_split = 0, .hw_ip_checksum = 0, .hw_vlan_filter = 0, .jumbo_frame = 0, .hw_strip_crc = 0, }, .txmode = { .mq_mode = ETH_DCB_NONE, }, }; static struct rte_kni_ops kni_ops = { .change_mtu = NULL, .config_network_if = NULL, }; static unsigned lcore_master, lcore_ingress, lcore_egress; static struct rte_kni *test_kni_ctx; static struct test_kni_stats stats; static volatile uint32_t test_kni_processing_flag; static struct rte_mempool * test_kni_create_mempool(void) { struct rte_mempool * mp; mp = rte_mempool_lookup("kni_mempool"); if (!mp) mp = rte_pktmbuf_pool_create("kni_mempool", NB_MBUF, MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, SOCKET); return mp; } static struct rte_mempool * test_kni_lookup_mempool(void) { return rte_mempool_lookup("kni_mempool"); } /* Callback for request of changing MTU */ static int kni_change_mtu(uint8_t port_id, unsigned new_mtu) { printf("Change MTU of port %d to %u\n", port_id, new_mtu); kni_pkt_mtu = new_mtu; printf("Change MTU of port %d to %i successfully.\n", port_id, kni_pkt_mtu); return 0; } /** * This loop fully tests the basic functions of KNI. e.g. transmitting, * receiving to, from kernel space, and kernel requests. * * This is the loop to transmit/receive mbufs to/from kernel interface with * supported by KNI kernel module. The ingress lcore will allocate mbufs and * transmit them to kernel space; while the egress lcore will receive the mbufs * from kernel space and free them. * On the master lcore, several commands will be run to check handling the * kernel requests. And it will finally set the flag to exit the KNI * transmitting/receiving to/from the kernel space. * * Note: To support this testing, the KNI kernel module needs to be insmodded * in one of its loopback modes. */ static int test_kni_loop(__rte_unused void *arg) { int ret = 0; unsigned nb_rx, nb_tx, num, i; const unsigned lcore_id = rte_lcore_id(); struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; if (lcore_id == lcore_master) { rte_delay_ms(KNI_TIMEOUT_MS); /* tests of handling kernel request */ if (system(IFCONFIG TEST_KNI_PORT" up") == -1) ret = -1; if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1) ret = -1; if (system(IFCONFIG TEST_KNI_PORT" down") == -1) ret = -1; rte_delay_ms(KNI_TIMEOUT_MS); test_kni_processing_flag = 1; } else if (lcore_id == lcore_ingress) { struct rte_mempool *mp = test_kni_lookup_mempool(); if (mp == NULL) return -1; while (1) { if (test_kni_processing_flag) break; for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) { pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp); if (!pkts_burst[nb_rx]) break; } num = rte_kni_tx_burst(test_kni_ctx, pkts_burst, nb_rx); stats.ingress += num; rte_kni_handle_request(test_kni_ctx); if (num < nb_rx) { for (i = num; i < nb_rx; i++) { rte_pktmbuf_free(pkts_burst[i]); } } rte_delay_ms(10); } } else if (lcore_id == lcore_egress) { while (1) { if (test_kni_processing_flag) break; num = rte_kni_rx_burst(test_kni_ctx, pkts_burst, PKT_BURST_SZ); stats.egress += num; for (nb_tx = 0; nb_tx < num; nb_tx++) rte_pktmbuf_free(pkts_burst[nb_tx]); rte_delay_ms(10); } } return ret; } static int test_kni_allocate_lcores(void) { unsigned i, count = 0; lcore_master = rte_get_master_lcore(); printf("master lcore: %u\n", lcore_master); for (i = 0; i < RTE_MAX_LCORE; i++) { if (count >=2 ) break; if (rte_lcore_is_enabled(i) && i != lcore_master) { count ++; if (count == 1) lcore_ingress = i; else if (count == 2) lcore_egress = i; } } printf("count: %u\n", count); return (count == 2 ? 0 : -1); } static int test_kni_register_handler_mp(void) { #define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */ #define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */ #define TEST_KNI_MTU 1450 #define TEST_KNI_MTU_STR " 1450" int pid; pid = fork(); if (pid < 0) { printf("Failed to fork a process\n"); return -1; } else if (pid == 0) { int i; struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT); struct rte_kni_ops ops = { .change_mtu = kni_change_mtu, .config_network_if = NULL, }; if (!kni) { printf("Failed to get KNI named %s\n", TEST_KNI_PORT); exit(-1); } kni_pkt_mtu = 0; /* Check with the invalid parameters */ if (rte_kni_register_handlers(kni, NULL) == 0) { printf("Unexpectedly register successuflly " "with NULL ops pointer\n"); exit(-1); } if (rte_kni_register_handlers(NULL, &ops) == 0) { printf("Unexpectedly register successfully " "to NULL KNI device pointer\n"); exit(-1); } if (rte_kni_register_handlers(kni, &ops)) { printf("Fail to register ops\n"); exit(-1); } /* Check registering again after it has been registered */ if (rte_kni_register_handlers(kni, &ops) == 0) { printf("Unexpectedly register successfully after " "it has already been registered\n"); exit(-1); } /** * Handle the request of setting MTU, * with registered handlers. */ for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) { rte_kni_handle_request(kni); if (kni_pkt_mtu == TEST_KNI_MTU) break; rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); } if (i >= TEST_KNI_HANDLE_REQ_COUNT) { printf("MTU has not been set\n"); exit(-1); } kni_pkt_mtu = 0; if (rte_kni_unregister_handlers(kni) < 0) { printf("Fail to unregister ops\n"); exit(-1); } /* Check with invalid parameter */ if (rte_kni_unregister_handlers(NULL) == 0) { exit(-1); } /** * Handle the request of setting MTU, * without registered handlers. */ for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) { rte_kni_handle_request(kni); if (kni_pkt_mtu != 0) break; rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL); } if (kni_pkt_mtu != 0) { printf("MTU shouldn't be set\n"); exit(-1); } exit(0); } else { int p_ret, status; rte_delay_ms(1000); if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) == -1) return -1; rte_delay_ms(1000); if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR) == -1) return -1; p_ret = wait(&status); if (!WIFEXITED(status)) { printf("Child process (%d) exit abnormally\n", p_ret); return -1; } if (WEXITSTATUS(status) != 0) { printf("Child process exit with failure\n"); return -1; } } return 0; } static int test_kni_processing(uint8_t port_id, struct rte_mempool *mp) { int ret = 0; unsigned i; struct rte_kni *kni; struct rte_kni_conf conf; struct rte_eth_dev_info info; struct rte_kni_ops ops; if (!mp) return -1; memset(&conf, 0, sizeof(conf)); memset(&info, 0, sizeof(info)); memset(&ops, 0, sizeof(ops)); rte_eth_dev_info_get(port_id, &info); conf.addr = info.pci_dev->addr; conf.id = info.pci_dev->id; snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT); /* core id 1 configured for kernel thread */ conf.core_id = 1; conf.force_bind = 1; conf.mbuf_size = MAX_PACKET_SZ; conf.group_id = (uint16_t)port_id; ops = kni_ops; ops.port_id = port_id; /* basic test of kni processing */ kni = rte_kni_alloc(mp, &conf, &ops); if (!kni) { printf("fail to create kni\n"); return -1; } if (rte_kni_get_port_id(kni) != port_id) { printf("fail to get port id\n"); ret = -1; goto fail_kni; } if (rte_kni_info_get(RTE_MAX_ETHPORTS)) { printf("Unexpectedly get a KNI successfully\n"); ret = -1; goto fail_kni; } test_kni_ctx = kni; test_kni_processing_flag = 0; stats.ingress = 0; stats.egress = 0; /** * Check multiple processes support on * registerring/unregisterring handlers. */ if (test_kni_register_handler_mp() < 0) { printf("fail to check multiple process support\n"); ret = -1; goto fail_kni; } rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(i) { if (rte_eal_wait_lcore(i) < 0) { ret = -1; goto fail_kni; } } /** * Check if the number of mbufs received from kernel space is equal * to that of transmitted to kernel space */ if (stats.ingress < KNI_NUM_MBUF_THRESHOLD || stats.egress < KNI_NUM_MBUF_THRESHOLD) { printf("The ingress/egress number should not be " "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD); ret = -1; goto fail_kni; } if (rte_kni_release(kni) < 0) { printf("fail to release kni\n"); return -1; } test_kni_ctx = NULL; /* test of releasing a released kni device */ if (rte_kni_release(kni) == 0) { printf("should not release a released kni device\n"); return -1; } /* test of reusing memzone */ kni = rte_kni_alloc(mp, &conf, &ops); if (!kni) { printf("fail to create kni\n"); return -1; } /* Release the kni for following testing */ if (rte_kni_release(kni) < 0) { printf("fail to release kni\n"); return -1; } return ret; fail_kni: if (rte_kni_release(kni) < 0) { printf("fail to release kni\n"); ret = -1; } return ret; } static int test_kni(void) { int ret = -1; uint8_t nb_ports, port_id; struct rte_kni *kni; struct rte_mempool *mp; struct rte_kni_conf conf; struct rte_eth_dev_info info; struct rte_kni_ops ops; /* Initialize KNI subsytem */ rte_kni_init(KNI_TEST_MAX_PORTS); if (test_kni_allocate_lcores() < 0) { printf("No enough lcores for kni processing\n"); return -1; } mp = test_kni_create_mempool(); if (!mp) { printf("fail to create mempool for kni\n"); return -1; } nb_ports = rte_eth_dev_count(); if (nb_ports == 0) { printf("no supported nic port found\n"); return -1; } /* configuring port 0 for the test is enough */ port_id = 0; ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); if (ret < 0) { printf("fail to configure port %d\n", port_id); return -1; } ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp); if (ret < 0) { printf("fail to setup rx queue for port %d\n", port_id); return -1; } ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf); if (ret < 0) { printf("fail to setup tx queue for port %d\n", port_id); return -1; } ret = rte_eth_dev_start(port_id); if (ret < 0) { printf("fail to start port %d\n", port_id); return -1; } rte_eth_promiscuous_enable(port_id); /* basic test of kni processing */ ret = test_kni_processing(port_id, mp); if (ret < 0) goto fail; /* test of allocating KNI with NULL mempool pointer */ memset(&info, 0, sizeof(info)); memset(&conf, 0, sizeof(conf)); memset(&ops, 0, sizeof(ops)); rte_eth_dev_info_get(port_id, &info); conf.addr = info.pci_dev->addr; conf.id = info.pci_dev->id; conf.group_id = (uint16_t)port_id; conf.mbuf_size = MAX_PACKET_SZ; ops = kni_ops; ops.port_id = port_id; kni = rte_kni_alloc(NULL, &conf, &ops); if (kni) { ret = -1; printf("unexpectedly creates kni successfully with NULL " "mempool pointer\n"); goto fail; } /* test of allocating KNI without configurations */ kni = rte_kni_alloc(mp, NULL, NULL); if (kni) { ret = -1; printf("Unexpectedly allocate KNI device successfully " "without configurations\n"); goto fail; } /* test of allocating KNI without a name */ memset(&conf, 0, sizeof(conf)); memset(&info, 0, sizeof(info)); memset(&ops, 0, sizeof(ops)); rte_eth_dev_info_get(port_id, &info); conf.addr = info.pci_dev->addr; conf.id = info.pci_dev->id; conf.group_id = (uint16_t)port_id; conf.mbuf_size = MAX_PACKET_SZ; ops = kni_ops; ops.port_id = port_id; kni = rte_kni_alloc(mp, &conf, &ops); if (kni) { ret = -1; printf("Unexpectedly allocate a KNI device successfully " "without a name\n"); goto fail; } /* test of getting port id according to NULL kni context */ if (rte_kni_get_port_id(NULL) < RTE_MAX_ETHPORTS) { ret = -1; printf("unexpectedly get port id successfully by NULL kni " "pointer\n"); goto fail; } /* test of releasing NULL kni context */ ret = rte_kni_release(NULL); if (ret == 0) { ret = -1; printf("unexpectedly release kni successfully\n"); goto fail; } /* test of handling request on NULL device pointer */ ret = rte_kni_handle_request(NULL); if (ret == 0) { ret = -1; printf("Unexpectedly handle request on NULL device pointer\n"); goto fail; } /* test of getting KNI device with pointer to NULL */ kni = rte_kni_get(NULL); if (kni) { ret = -1; printf("Unexpectedly get a KNI device with " "NULL name pointer\n"); goto fail; } /* test of getting KNI device with an zero length name string */ memset(&conf, 0, sizeof(conf)); kni = rte_kni_get(conf.name); if (kni) { ret = -1; printf("Unexpectedly get a KNI device with " "zero length name string\n"); goto fail; } /* test of getting KNI device with an invalid string name */ memset(&conf, 0, sizeof(conf)); snprintf(conf.name, sizeof(conf.name), "testing"); kni = rte_kni_get(conf.name); if (kni) { ret = -1; printf("Unexpectedly get a KNI device with " "a never used name string\n"); goto fail; } /* test the interface of creating a KNI, for backward compatibility */ memset(&ops, 0, sizeof(ops)); ops = kni_ops; kni = rte_kni_create(port_id, MAX_PACKET_SZ, mp, &ops); if (!kni) { ret = -1; printf("Fail to create a KNI device for port %d\n", port_id); goto fail; } ret = rte_kni_release(kni); if (ret < 0) { printf("Fail to release a KNI device\n"); goto fail; } ret = 0; fail: rte_eth_dev_stop(port_id); return ret; } static struct test_command kni_cmd = { .command = "kni_autotest", .callback = test_kni, }; REGISTER_TEST_COMMAND(kni_cmd); ================================================ FILE: app/test/test_kvargs.c ================================================ /* * Copyright 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * - Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" /* incrementd in handler, to check it is properly called once per * key/value association */ static unsigned count; /* this handler increment the "count" variable at each call and check * that the key is "check" and the value is "value%d" */ static int check_handler(const char *key, const char *value, __rte_unused void *opaque) { char buf[16]; /* we check that the value is "check" */ if (strcmp(key, "check")) return -1; /* we check that the value is "value$(count)" */ snprintf(buf, sizeof(buf), "value%d", count); if (strncmp(buf, value, sizeof(buf))) return -1; count ++; return 0; } /* test a valid case */ static int test_valid_kvargs(void) { struct rte_kvargs *kvlist; const char *args; const char *valid_keys_list[] = { "foo", "check", NULL }; const char **valid_keys; /* empty args is valid */ args = ""; valid_keys = NULL; kvlist = rte_kvargs_parse(args, valid_keys); if (kvlist == NULL) { printf("rte_kvargs_parse() error"); goto fail; } rte_kvargs_free(kvlist); /* first test without valid_keys */ args = "foo=1234,check=value0,check=value1"; valid_keys = NULL; kvlist = rte_kvargs_parse(args, valid_keys); if (kvlist == NULL) { printf("rte_kvargs_parse() error"); goto fail; } /* call check_handler() for all entries with key="check" */ count = 0; if (rte_kvargs_process(kvlist, "check", check_handler, NULL) < 0) { printf("rte_kvargs_process() error\n"); rte_kvargs_free(kvlist); goto fail; } if (count != 2) { printf("invalid count value %d after rte_kvargs_process(check)\n", count); rte_kvargs_free(kvlist); goto fail; } count = 0; /* call check_handler() for all entries with key="unexistant_key" */ if (rte_kvargs_process(kvlist, "unexistant_key", check_handler, NULL) < 0) { printf("rte_kvargs_process() error\n"); rte_kvargs_free(kvlist); goto fail; } if (count != 0) { printf("invalid count value %d after rte_kvargs_process(unexistant_key)\n", count); rte_kvargs_free(kvlist); goto fail; } /* count all entries with key="foo" */ count = rte_kvargs_count(kvlist, "foo"); if (count != 1) { printf("invalid count value %d after rte_kvargs_count(foo)\n", count); rte_kvargs_free(kvlist); goto fail; } /* count all entries */ count = rte_kvargs_count(kvlist, NULL); if (count != 3) { printf("invalid count value %d after rte_kvargs_count(NULL)\n", count); rte_kvargs_free(kvlist); goto fail; } /* count all entries with key="unexistant_key" */ count = rte_kvargs_count(kvlist, "unexistant_key"); if (count != 0) { printf("invalid count value %d after rte_kvargs_count(unexistant_key)\n", count); rte_kvargs_free(kvlist); goto fail; } rte_kvargs_free(kvlist); /* second test using valid_keys */ args = "foo=droids,check=value0,check=value1,check=wrong_value"; valid_keys = valid_keys_list; kvlist = rte_kvargs_parse(args, valid_keys); if (kvlist == NULL) { printf("rte_kvargs_parse() error"); goto fail; } /* call check_handler() on all entries with key="check", it * should fail as the value is not recognized by the handler */ if (rte_kvargs_process(kvlist, "check", check_handler, NULL) == 0) { printf("rte_kvargs_process() is success bu should not\n"); rte_kvargs_free(kvlist); goto fail; } count = rte_kvargs_count(kvlist, "check"); if (count != 3) { printf("invalid count value %d after rte_kvargs_count(check)\n", count); rte_kvargs_free(kvlist); goto fail; } rte_kvargs_free(kvlist); return 0; fail: printf("while processing <%s>", args); if (valid_keys != NULL && *valid_keys != NULL) { printf(" using valid_keys=<%s", *valid_keys); while (*(++valid_keys) != NULL) printf(",%s", *valid_keys); printf(">"); } printf("\n"); return -1; } /* test several error cases */ static int test_invalid_kvargs(void) { struct rte_kvargs *kvlist; /* list of argument that should fail */ const char *args_list[] = { "wrong-key=x", /* key not in valid_keys_list */ "foo=1,foo=", /* empty value */ "foo=1,,foo=2", /* empty key/value */ "foo=1,foo", /* no value */ "foo=1,=2", /* no key */ ",=", /* also test with a smiley */ NULL }; const char **args; const char *valid_keys_list[] = { "foo", "check", NULL }; const char **valid_keys = valid_keys_list; for (args = args_list; *args != NULL; args++) { kvlist = rte_kvargs_parse(*args, valid_keys); if (kvlist != NULL) { printf("rte_kvargs_parse() returned 0 (but should not)\n"); rte_kvargs_free(kvlist); goto fail; } return 0; } fail: printf("while processing <%s>", *args); if (valid_keys != NULL && *valid_keys != NULL) { printf(" using valid_keys=<%s", *valid_keys); while (*(++valid_keys) != NULL) printf(",%s", *valid_keys); printf(">"); } printf("\n"); return -1; } static int test_kvargs(void) { printf("== test valid case ==\n"); if (test_valid_kvargs() < 0) return -1; printf("== test invalid case ==\n"); if (test_invalid_kvargs() < 0) return -1; return 0; } static struct test_command kvargs_cmd = { .command = "kvargs_autotest", .callback = test_kvargs, }; REGISTER_TEST_COMMAND(kvargs_cmd); ================================================ FILE: app/test/test_link_bonding.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "unistd.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "virtual_pmd.h" #include "packet_burst_generator.h" #include "test.h" #define TEST_MAX_NUMBER_OF_PORTS (6) #define RX_RING_SIZE 128 #define RX_FREE_THRESH 32 #define RX_PTHRESH 8 #define RX_HTHRESH 8 #define RX_WTHRESH 0 #define TX_RING_SIZE 512 #define TX_FREE_THRESH 32 #define TX_PTHRESH 32 #define TX_HTHRESH 0 #define TX_WTHRESH 0 #define TX_RSBIT_THRESH 32 #define TX_Q_FLAGS (ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOVLANOFFL |\ ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ ETH_TXQ_FLAGS_NOXSUMTCP) #define MBUF_CACHE_SIZE (250) #define BURST_SIZE (32) #define RTE_TEST_RX_DESC_MAX (2048) #define RTE_TEST_TX_DESC_MAX (2048) #define MAX_PKT_BURST (512) #define DEF_PKT_BURST (16) #define BONDED_DEV_NAME ("unit_test_bonded_device") #define INVALID_SOCKET_ID (-1) #define INVALID_PORT_ID (-1) #define INVALID_BONDING_MODE (-1) uint8_t slave_mac[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 }; uint8_t bonded_mac[] = {0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; struct link_bonding_unittest_params { int8_t bonded_port_id; int8_t slave_port_ids[TEST_MAX_NUMBER_OF_PORTS]; uint8_t bonded_slave_count; uint8_t bonding_mode; uint16_t nb_rx_q; uint16_t nb_tx_q; struct rte_mempool *mbuf_pool; struct ether_addr *default_slave_mac; struct ether_addr *default_bonded_mac; /* Packet Headers */ struct ether_hdr *pkt_eth_hdr; struct ipv4_hdr *pkt_ipv4_hdr; struct ipv6_hdr *pkt_ipv6_hdr; struct udp_hdr *pkt_udp_hdr; }; static struct ipv4_hdr pkt_ipv4_hdr; static struct ipv6_hdr pkt_ipv6_hdr; static struct udp_hdr pkt_udp_hdr; static struct link_bonding_unittest_params default_params = { .bonded_port_id = -1, .slave_port_ids = { -1 }, .bonded_slave_count = 0, .bonding_mode = BONDING_MODE_ROUND_ROBIN, .nb_rx_q = 1, .nb_tx_q = 1, .mbuf_pool = NULL, .default_slave_mac = (struct ether_addr *)slave_mac, .default_bonded_mac = (struct ether_addr *)bonded_mac, .pkt_eth_hdr = NULL, .pkt_ipv4_hdr = &pkt_ipv4_hdr, .pkt_ipv6_hdr = &pkt_ipv6_hdr, .pkt_udp_hdr = &pkt_udp_hdr }; static struct link_bonding_unittest_params *test_params = &default_params; static uint8_t src_mac[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; static uint8_t dst_mac_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; static uint8_t dst_mac_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAB }; static uint32_t src_addr = IPV4_ADDR(192, 168, 1, 98); static uint32_t dst_addr_0 = IPV4_ADDR(192, 168, 1, 98); static uint32_t dst_addr_1 = IPV4_ADDR(193, 166, 10, 97); static uint8_t src_ipv6_addr[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA }; static uint8_t dst_ipv6_addr_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA, 0xFF, 0xAA }; static uint8_t dst_ipv6_addr_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA , 0xFF, 0xAB }; static uint16_t src_port = 1024; static uint16_t dst_port_0 = 1024; static uint16_t dst_port_1 = 2024; static uint16_t vlan_id = 0x100; struct rte_eth_rxmode rx_mode = { .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */ .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled. */ .hw_ip_checksum = 0, /**< IP checksum offload disabled. */ .hw_vlan_filter = 1, /**< VLAN filtering enabled. */ .hw_vlan_strip = 1, /**< VLAN strip enabled. */ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */ .hw_strip_crc = 0, /**< CRC stripping by hardware disabled. */ }; struct rte_fdir_conf fdir_conf = { .mode = RTE_FDIR_MODE_NONE, .pballoc = RTE_FDIR_PBALLOC_64K, .status = RTE_FDIR_REPORT_STATUS, .drop_queue = 127, }; static struct rte_eth_conf default_pmd_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .lpbk_mode = 0, }; static const struct rte_eth_rxconf rx_conf_default = { .rx_thresh = { .pthresh = RX_PTHRESH, .hthresh = RX_HTHRESH, .wthresh = RX_WTHRESH, }, .rx_free_thresh = RX_FREE_THRESH, .rx_drop_en = 0, }; static struct rte_eth_txconf tx_conf_default = { .tx_thresh = { .pthresh = TX_PTHRESH, .hthresh = TX_HTHRESH, .wthresh = TX_WTHRESH, }, .tx_free_thresh = TX_FREE_THRESH, .tx_rs_thresh = TX_RSBIT_THRESH, .txq_flags = TX_Q_FLAGS }; static int configure_ethdev(uint8_t port_id, uint8_t start, uint8_t en_isr) { int q_id; if (en_isr) default_pmd_conf.intr_conf.lsc = 1; else default_pmd_conf.intr_conf.lsc = 0; TEST_ASSERT_SUCCESS(rte_eth_dev_configure(port_id, test_params->nb_rx_q, test_params->nb_tx_q, &default_pmd_conf), "rte_eth_dev_configure for port %d failed", port_id); for (q_id = 0; q_id < test_params->nb_rx_q; q_id++) TEST_ASSERT_SUCCESS(rte_eth_rx_queue_setup(port_id, q_id, RX_RING_SIZE, rte_eth_dev_socket_id(port_id), &rx_conf_default, test_params->mbuf_pool) , "rte_eth_rx_queue_setup for port %d failed", port_id); for (q_id = 0; q_id < test_params->nb_tx_q; q_id++) TEST_ASSERT_SUCCESS(rte_eth_tx_queue_setup(port_id, q_id, TX_RING_SIZE, rte_eth_dev_socket_id(port_id), &tx_conf_default), "rte_eth_tx_queue_setup for port %d failed", port_id); if (start) TEST_ASSERT_SUCCESS(rte_eth_dev_start(port_id), "rte_eth_dev_start for port %d failed", port_id); return 0; } static int slaves_initialized; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER; static int test_setup(void) { int i, nb_mbuf_per_pool; struct ether_addr *mac_addr = (struct ether_addr *)slave_mac; /* Allocate ethernet packet header with space for VLAN header */ if (test_params->pkt_eth_hdr == NULL) { test_params->pkt_eth_hdr = malloc(sizeof(struct ether_hdr) + sizeof(struct vlan_hdr)); TEST_ASSERT_NOT_NULL(test_params->pkt_eth_hdr, "Ethernet header struct allocation failed!"); } nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + DEF_PKT_BURST + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; if (test_params->mbuf_pool == NULL) { test_params->mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); TEST_ASSERT_NOT_NULL(test_params->mbuf_pool, "rte_mempool_create failed"); } /* Create / Initialize virtual eth devs */ if (!slaves_initialized) { for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) { char pmd_name[RTE_ETH_NAME_MAX_LEN]; mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i; snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_%d", i); test_params->slave_port_ids[i] = virtual_ethdev_create(pmd_name, mac_addr, rte_socket_id(), 1); TEST_ASSERT(test_params->slave_port_ids[i] >= 0, "Failed to create virtual virtual ethdev %s", pmd_name); TEST_ASSERT_SUCCESS(configure_ethdev( test_params->slave_port_ids[i], 1, 0), "Failed to configure virtual ethdev %s", pmd_name); } slaves_initialized = 1; } return 0; } static int test_create_bonded_device(void) { int current_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; /* Don't try to recreate bonded device if re-running test suite*/ if (test_params->bonded_port_id == -1) { test_params->bonded_port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode, rte_socket_id()); TEST_ASSERT(test_params->bonded_port_id >= 0, "Failed to create bonded ethdev %s", BONDED_DEV_NAME); TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0), "Failed to configure bonded ethdev %s", BONDED_DEV_NAME); } TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id, test_params->bonding_mode), "Failed to set ethdev %d to mode %d", test_params->bonded_port_id, test_params->bonding_mode); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, 0, "Number of slaves %d is great than expected %d.", current_slave_count, 0); current_slave_count = rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, 0, "Number of active slaves %d is great than expected %d.", current_slave_count, 0); return 0; } static int test_create_bonded_device_with_invalid_params(void) { int port_id; test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN; /* Invalid name */ port_id = rte_eth_bond_create(NULL, test_params->bonding_mode, rte_socket_id()); TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly"); test_params->bonding_mode = INVALID_BONDING_MODE; /* Invalid bonding mode */ port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode, rte_socket_id()); TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly."); test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN; /* Invalid socket id */ port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode, INVALID_SOCKET_ID); TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly."); return 0; } static int test_add_slave_to_bonded_device(void) { int current_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id, test_params->slave_port_ids[test_params->bonded_slave_count]), "Failed to add slave (%d) to bonded port (%d).", test_params->slave_port_ids[test_params->bonded_slave_count], test_params->bonded_port_id); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count + 1, "Number of slaves (%d) is greater than expected (%d).", current_slave_count, test_params->bonded_slave_count + 1); current_slave_count = rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, 0, "Number of active slaves (%d) is not as expected (%d).\n", current_slave_count, 0); test_params->bonded_slave_count++; return 0; } static int test_add_slave_to_invalid_bonded_device(void) { /* Invalid port ID */ TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->bonded_port_id + 5, test_params->slave_port_ids[test_params->bonded_slave_count]), "Expected call to failed as invalid port specified."); /* Non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->slave_port_ids[0], test_params->slave_port_ids[test_params->bonded_slave_count]), "Expected call to failed as invalid port specified."); return 0; } static int test_remove_slave_from_bonded_device(void) { int current_slave_count; struct ether_addr read_mac_addr, *mac_addr; uint8_t slaves[RTE_MAX_ETHPORTS]; TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params->bonded_port_id, test_params->slave_port_ids[test_params->bonded_slave_count-1]), "Failed to remove slave %d from bonded port (%d).", test_params->slave_port_ids[test_params->bonded_slave_count-1], test_params->bonded_port_id); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count - 1, "Number of slaves (%d) is great than expected (%d).\n", current_slave_count, test_params->bonded_slave_count - 1); mac_addr = (struct ether_addr *)slave_mac; mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = test_params->bonded_slave_count-1; rte_eth_macaddr_get( test_params->slave_port_ids[test_params->bonded_slave_count-1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not set to that of primary port\n"); rte_eth_stats_reset( test_params->slave_port_ids[test_params->bonded_slave_count-1]); virtual_ethdev_simulate_link_status_interrupt(test_params->bonded_port_id, 0); test_params->bonded_slave_count--; return 0; } static int test_remove_slave_from_invalid_bonded_device(void) { /* Invalid port ID */ TEST_ASSERT_FAIL(rte_eth_bond_slave_remove( test_params->bonded_port_id + 5, test_params->slave_port_ids[test_params->bonded_slave_count - 1]), "Expected call to failed as invalid port specified."); /* Non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_slave_remove( test_params->slave_port_ids[0], test_params->slave_port_ids[test_params->bonded_slave_count - 1]), "Expected call to failed as invalid port specified."); return 0; } static int bonded_id = 2; static int test_add_already_bonded_slave_to_bonded_device(void) { int port_id, current_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; char pmd_name[RTE_ETH_NAME_MAX_LEN]; test_add_slave_to_bonded_device(); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, 1, "Number of slaves (%d) is not that expected (%d).", current_slave_count, 1); snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "%s_%d", BONDED_DEV_NAME, ++bonded_id); port_id = rte_eth_bond_create(pmd_name, test_params->bonding_mode, rte_socket_id()); TEST_ASSERT(port_id >= 0, "Failed to create bonded device."); TEST_ASSERT(rte_eth_bond_slave_add(port_id, test_params->slave_port_ids[test_params->bonded_slave_count - 1]) < 0, "Added slave (%d) to bonded port (%d) unexpectedly.", test_params->slave_port_ids[test_params->bonded_slave_count-1], port_id); return test_remove_slave_from_bonded_device(); } static int test_get_slaves_from_bonded_device(void) { int current_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave to bonded device"); /* Invalid port id */ current_slave_count = rte_eth_bond_slaves_get(INVALID_PORT_ID, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid port id unexpectedly succeeded"); current_slave_count = rte_eth_bond_active_slaves_get(INVALID_PORT_ID, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid port id unexpectedly succeeded"); /* Invalid slaves pointer */ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, NULL, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid slave array unexpectedly succeeded"); current_slave_count = rte_eth_bond_active_slaves_get( test_params->bonded_port_id, NULL, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid slave array unexpectedly succeeded"); /* non bonded device*/ current_slave_count = rte_eth_bond_slaves_get( test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid port id unexpectedly succeeded"); current_slave_count = rte_eth_bond_active_slaves_get( test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS); TEST_ASSERT(current_slave_count < 0, "Invalid port id unexpectedly succeeded"); TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(), "Failed to remove slaves from bonded device"); return 0; } static int test_add_remove_multiple_slaves_to_from_bonded_device(void) { int i; for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave to bonded device"); for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(), "Failed to remove slaves from bonded device"); return 0; } static void enable_bonded_slaves(void) { int i; for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_tx_burst_fn_set_success(test_params->slave_port_ids[i], 1); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 1); } } static int test_start_bonded_device(void) { struct rte_eth_link link_status; int current_slave_count, current_bonding_mode, primary_port; uint8_t slaves[RTE_MAX_ETHPORTS]; /* Add slave to bonded device*/ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave to bonded device"); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded pmd eth device %d.", test_params->bonded_port_id); /* Change link status of virtual pmd so it will be added to the active * slave list of the bonded device*/ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[test_params->bonded_slave_count-1], 1); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count, "Number of slaves (%d) is not expected value (%d).", current_slave_count, test_params->bonded_slave_count); current_slave_count = rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count, "Number of active slaves (%d) is not expected value (%d).", current_slave_count, test_params->bonded_slave_count); current_bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(current_bonding_mode, test_params->bonding_mode, "Bonded device mode (%d) is not expected value (%d).\n", current_bonding_mode, test_params->bonding_mode); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0], "Primary port (%d) is not expected value (%d).", primary_port, test_params->slave_port_ids[0]); rte_eth_link_get(test_params->bonded_port_id, &link_status); TEST_ASSERT_EQUAL(link_status.link_status, 1, "Bonded port (%d) status (%d) is not expected value (%d).\n", test_params->bonded_port_id, link_status.link_status, 1); return 0; } static int test_stop_bonded_device(void) { int current_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; struct rte_eth_link link_status; rte_eth_dev_stop(test_params->bonded_port_id); rte_eth_link_get(test_params->bonded_port_id, &link_status); TEST_ASSERT_EQUAL(link_status.link_status, 0, "Bonded port (%d) status (%d) is not expected value (%d).", test_params->bonded_port_id, link_status.link_status, 0); current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count, "Number of slaves (%d) is not expected value (%d).", current_slave_count, test_params->bonded_slave_count); current_slave_count = rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(current_slave_count, 0, "Number of active slaves (%d) is not expected value (%d).", current_slave_count, 0); return 0; } static int remove_slaves_and_stop_bonded_device(void) { /* Clean up and remove slaves from bonded device */ while (test_params->bonded_slave_count > 0) TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(), "test_remove_slave_from_bonded_device failed"); rte_eth_dev_stop(test_params->bonded_port_id); rte_eth_stats_reset(test_params->bonded_port_id); rte_eth_bond_mac_address_reset(test_params->bonded_port_id); return 0; } static int test_set_bonding_mode(void) { int i, bonding_mode; int bonding_modes[] = { BONDING_MODE_ROUND_ROBIN, BONDING_MODE_ACTIVE_BACKUP, BONDING_MODE_BALANCE, BONDING_MODE_BROADCAST }; /* Test supported link bonding modes */ for (i = 0; i < (int)RTE_DIM(bonding_modes); i++) { /* Invalid port ID */ TEST_ASSERT_FAIL(rte_eth_bond_mode_set(INVALID_PORT_ID, bonding_modes[i]), "Expected call to failed as invalid port (%d) specified.", INVALID_PORT_ID); /* Non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_mode_set(test_params->slave_port_ids[0], bonding_modes[i]), "Expected call to failed as invalid port (%d) specified.", test_params->slave_port_ids[0]); TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id, bonding_modes[i]), "Failed to set link bonding mode on port (%d) to (%d).", test_params->bonded_port_id, bonding_modes[i]); bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(bonding_mode, bonding_modes[i], "Link bonding mode (%d) of port (%d) is not expected value (%d).", bonding_mode, test_params->bonded_port_id, bonding_modes[i]); /* Invalid port ID */ bonding_mode = rte_eth_bond_mode_get(INVALID_PORT_ID); TEST_ASSERT(bonding_mode < 0, "Expected call to failed as invalid port (%d) specified.", INVALID_PORT_ID); /* Non bonded device */ bonding_mode = rte_eth_bond_mode_get(test_params->slave_port_ids[0]); TEST_ASSERT(bonding_mode < 0, "Expected call to failed as invalid port (%d) specified.", test_params->slave_port_ids[0]); } return remove_slaves_and_stop_bonded_device(); } static int test_set_primary_slave(void) { int i, j, retval; struct ether_addr read_mac_addr; struct ether_addr *expected_mac_addr; /* Add 4 slaves to bonded device */ for (i = test_params->bonded_slave_count; i < 4; i++) TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave to bonded device."); TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN), "Failed to set link bonding mode on port (%d) to (%d).", test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN); /* Invalid port ID */ TEST_ASSERT_FAIL(rte_eth_bond_primary_set(INVALID_PORT_ID, test_params->slave_port_ids[i]), "Expected call to failed as invalid port specified."); /* Non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_primary_set(test_params->slave_port_ids[i], test_params->slave_port_ids[i]), "Expected call to failed as invalid port specified."); /* Set slave as primary * Verify slave it is now primary slave * Verify that MAC address of bonded device is that of primary slave * Verify that MAC address of all bonded slaves are that of primary slave */ for (i = 0; i < 4; i++) { TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[i]), "Failed to set bonded port (%d) primary port to (%d)", test_params->bonded_port_id, test_params->slave_port_ids[i]); retval = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT(retval >= 0, "Failed to read primary port from bonded port (%d)\n", test_params->bonded_port_id); TEST_ASSERT_EQUAL(retval, test_params->slave_port_ids[i], "Bonded port (%d) primary port (%d) not expected value (%d)\n", test_params->bonded_port_id, retval, test_params->slave_port_ids[i]); /* stop/start bonded eth dev to apply new MAC */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded port %d", test_params->bonded_port_id); expected_mac_addr = (struct ether_addr *)&slave_mac; expected_mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i; /* Check primary slave MAC */ rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not set to that of primary port\n"); /* Check bonded MAC */ rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&read_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not set to that of primary port\n"); /* Check other slaves MACs */ for (j = 0; j < 4; j++) { if (j != i) { rte_eth_macaddr_get(test_params->slave_port_ids[j], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port mac address not set to that of primary " "port"); } } } /* Test with none existent port */ TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->bonded_port_id + 10), "read primary port from expectedly"); /* Test with slave port */ TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->slave_port_ids[0]), "read primary port from expectedly\n"); TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(), "Failed to stop and remove slaves from bonded device"); /* No slaves */ TEST_ASSERT(rte_eth_bond_primary_get(test_params->bonded_port_id) < 0, "read primary port from expectedly\n"); return 0; } static int test_set_explicit_bonded_mac(void) { int i; struct ether_addr read_mac_addr; struct ether_addr *mac_addr; uint8_t explicit_bonded_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01 }; mac_addr = (struct ether_addr *)explicit_bonded_mac; /* Invalid port ID */ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(INVALID_PORT_ID, mac_addr), "Expected call to failed as invalid port specified."); /* Non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set( test_params->slave_port_ids[0], mac_addr), "Expected call to failed as invalid port specified."); /* NULL MAC address */ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set( test_params->bonded_port_id, NULL), "Expected call to failed as NULL MAC specified"); TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, mac_addr), "Failed to set MAC address on bonded port (%d)", test_params->bonded_port_id); /* Add 4 slaves to bonded device */ for (i = test_params->bonded_slave_count; i < 4; i++) { TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave to bonded device.\n"); } /* Check bonded MAC */ rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not set to that of primary port"); /* Check other slaves MACs */ for (i = 0; i < 4; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port mac address not set to that of primary port"); } /* test resetting mac address on bonded device */ TEST_ASSERT_SUCCESS( rte_eth_bond_mac_address_reset(test_params->bonded_port_id), "Failed to reset MAC address on bonded port (%d)", test_params->bonded_port_id); TEST_ASSERT_FAIL( rte_eth_bond_mac_address_reset(test_params->slave_port_ids[0]), "Reset MAC address on bonded port (%d) unexpectedly", test_params->slave_port_ids[1]); /* test resetting mac address on bonded device with no slaves */ TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(), "Failed to remove slaves and stop bonded device"); TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_reset(test_params->bonded_port_id), "Failed to reset MAC address on bonded port (%d)", test_params->bonded_port_id); return 0; } #define BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT (3) static int test_set_bonded_port_initialization_mac_assignment(void) { int i, slave_count, bonded_port_id; uint8_t slaves[RTE_MAX_ETHPORTS]; int slave_port_ids[BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT]; struct ether_addr slave_mac_addr, bonded_mac_addr, read_mac_addr; /* Initialize default values for MAC addresses */ memcpy(&slave_mac_addr, slave_mac, sizeof(struct ether_addr)); memcpy(&bonded_mac_addr, slave_mac, sizeof(struct ether_addr)); /* * 1. a - Create / configure bonded / slave ethdevs */ bonded_port_id = rte_eth_bond_create("ethdev_bond_mac_ass_test", BONDING_MODE_ACTIVE_BACKUP, rte_socket_id()); TEST_ASSERT(bonded_port_id > 0, "failed to create bonded device"); TEST_ASSERT_SUCCESS(configure_ethdev(bonded_port_id, 0, 0), "Failed to configure bonded ethdev"); for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { char pmd_name[RTE_ETH_NAME_MAX_LEN]; slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = i + 100; snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_slave_%d", i); slave_port_ids[i] = virtual_ethdev_create(pmd_name, &slave_mac_addr, rte_socket_id(), 1); TEST_ASSERT(slave_port_ids[i] >= 0, "Failed to create slave ethdev %s", pmd_name); TEST_ASSERT_SUCCESS(configure_ethdev(slave_port_ids[i], 1, 0), "Failed to configure virtual ethdev %s", pmd_name); } /* * 2. Add slave ethdevs to bonded device */ for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(bonded_port_id, slave_port_ids[i]), "Failed to add slave (%d) to bonded port (%d).", slave_port_ids[i], bonded_port_id); } slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT, slave_count, "Number of slaves (%d) is not as expected (%d)", slave_count, BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT); /* * 3. Set explicit MAC address on bonded ethdev */ bonded_mac_addr.addr_bytes[ETHER_ADDR_LEN-2] = 0xFF; bonded_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0xAA; TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( bonded_port_id, &bonded_mac_addr), "Failed to set MAC address on bonded port (%d)", bonded_port_id); /* 4. a - Start bonded ethdev * b - Enable slave devices * c - Verify bonded/slaves ethdev MAC addresses */ TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id), "Failed to start bonded pmd eth device %d.", bonded_port_id); for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { virtual_ethdev_simulate_link_status_interrupt( slave_port_ids[i], 1); } rte_eth_macaddr_get(bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not as expected"); rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 0 mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 1 mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 2 + 100; rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 2 mac address not as expected"); /* 7. a - Change primary port * b - Stop / Start bonded port * d - Verify slave ethdev MAC addresses */ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(bonded_port_id, slave_port_ids[2]), "failed to set primary port on bonded device."); rte_eth_dev_stop(bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id), "Failed to start bonded pmd eth device %d.", bonded_port_id); rte_eth_macaddr_get(bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "bonded port mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0 + 100; rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 0 mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 1 mac address not as expected"); rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 2 mac address not as expected"); /* 6. a - Stop bonded ethdev * b - remove slave ethdevs * c - Verify slave ethdevs MACs are restored */ rte_eth_dev_stop(bonded_port_id); for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) { TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(bonded_port_id, slave_port_ids[i]), "Failed to remove slave %d from bonded port (%d).", slave_port_ids[i], bonded_port_id); } slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 0, "Number of slaves (%d) is great than expected (%d).", slave_count, 0); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 0 + 100; rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 0 mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 1 + 100; rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 1 mac address not as expected"); slave_mac_addr.addr_bytes[ETHER_ADDR_LEN-1] = 2 + 100; rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr, sizeof(read_mac_addr)), "slave port 2 mac address not as expected"); return 0; } static int initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr, uint8_t number_of_slaves, uint8_t enable_slave) { /* Configure bonded device */ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, bond_en_isr), "Failed to configure bonding port (%d) in mode %d " "with (%d) slaves.", test_params->bonded_port_id, bonding_mode, number_of_slaves); /* Add slaves to bonded device */ while (number_of_slaves > test_params->bonded_slave_count) TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(), "Failed to add slave (%d to bonding port (%d).", test_params->bonded_slave_count - 1, test_params->bonded_port_id); /* Set link bonding mode */ TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id, bonding_mode), "Failed to set link bonding mode on port (%d) to (%d).", test_params->bonded_port_id, bonding_mode); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded pmd eth device %d.", test_params->bonded_port_id); if (enable_slave) enable_bonded_slaves(); return 0; } static int test_adding_slave_after_bonded_device_started(void) { int i; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 4, 0), "Failed to add slaves to bonded device"); /* Enabled slave devices */ for (i = 0; i < test_params->bonded_slave_count + 1; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 1); } TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id, test_params->slave_port_ids[test_params->bonded_slave_count]), "Failed to add slave to bonded port.\n"); rte_eth_stats_reset( test_params->slave_port_ids[test_params->bonded_slave_count]); test_params->bonded_slave_count++; return remove_slaves_and_stop_bonded_device(); } #define TEST_STATUS_INTERRUPT_SLAVE_COUNT 4 #define TEST_LSC_WAIT_TIMEOUT_MS 500 int test_lsc_interrupt_count; static void test_bonding_lsc_event_callback(uint8_t port_id __rte_unused, enum rte_eth_event_type type __rte_unused, void *param __rte_unused) { pthread_mutex_lock(&mutex); test_lsc_interrupt_count++; pthread_cond_signal(&cvar); pthread_mutex_unlock(&mutex); } static inline int lsc_timeout(int wait_us) { int retval = 0; struct timespec ts; struct timeval tp; gettimeofday(&tp, NULL); /* Convert from timeval to timespec */ ts.tv_sec = tp.tv_sec; ts.tv_nsec = tp.tv_usec * 1000; ts.tv_nsec += wait_us * 1000; pthread_mutex_lock(&mutex); if (test_lsc_interrupt_count < 1) retval = pthread_cond_timedwait(&cvar, &mutex, &ts); pthread_mutex_unlock(&mutex); if (retval == 0 && test_lsc_interrupt_count < 1) return -1; return retval; } static int test_status_interrupt(void) { int slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; /* initialized bonding device with T slaves */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 1, TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1), "Failed to initialise bonded device"); test_lsc_interrupt_count = 0; /* register link status change interrupt callback */ rte_eth_dev_callback_register(test_params->bonded_port_id, RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback, &test_params->bonded_port_id); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT, "Number of active slaves (%d) is not as expected (%d)", slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT); /* Bring all 4 slaves link status to down and test that we have received a * lsc interrupts */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[2], 0); TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0, "Received a link status change interrupt unexpectedly"); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0, "timed out waiting for interrupt"); TEST_ASSERT(test_lsc_interrupt_count > 0, "Did not receive link status change interrupt"); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 0, "Number of active slaves (%d) is not as expected (%d)", slave_count, 0); /* bring one slave port up so link status will change */ test_lsc_interrupt_count = 0; virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 1); TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0, "timed out waiting for interrupt"); /* test that we have received another lsc interrupt */ TEST_ASSERT(test_lsc_interrupt_count > 0, "Did not receive link status change interrupt"); /* Verify that calling the same slave lsc interrupt doesn't cause another * lsc interrupt from bonded device */ test_lsc_interrupt_count = 0; virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 1); TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) != 0, "received unexpected interrupt"); TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0, "Did not receive link status change interrupt"); /* unregister lsc callback before exiting */ rte_eth_dev_callback_unregister(test_params->bonded_port_id, RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback, &test_params->bonded_port_id); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size, uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac, uint8_t toggle_ip_addr, uint8_t toggle_udp_port) { uint16_t pktlen, generated_burst_size, ether_type; void *ip_hdr; if (ipv4) ether_type = ETHER_TYPE_IPv4; else ether_type = ETHER_TYPE_IPv6; if (toggle_dst_mac) initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, ether_type, vlan, vlan_id); else initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, ether_type, vlan, vlan_id); if (toggle_udp_port) pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_1, 64); else pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 64); if (ipv4) { if (toggle_ip_addr) pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_1, pktlen); else pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_0, pktlen); ip_hdr = test_params->pkt_ipv4_hdr; } else { if (toggle_ip_addr) pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr, (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_1, pktlen); else pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr, (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_0, pktlen); ip_hdr = test_params->pkt_ipv6_hdr; } /* Generate burst of packets to transmit */ generated_burst_size = generate_packet_burst(test_params->mbuf_pool, pkts_burst, test_params->pkt_eth_hdr, vlan, ip_hdr, ipv4, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN_128, 1); TEST_ASSERT_EQUAL(generated_burst_size, burst_size, "Failed to generate packet burst"); return generated_burst_size; } /** Round Robin Mode Tests */ static int test_roundrobin_tx_burst(void) { int i, burst_size; struct rte_mbuf *pkt_burst[MAX_PKT_BURST]; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 2, 1), "Failed to intialise bonded device"); burst_size = 20 * test_params->bonded_slave_count; TEST_ASSERT(burst_size <= MAX_PKT_BURST, "Burst size specified is greater than supported."); /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0), burst_size, "failed to generate test burst"); /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, pkt_burst, burst_size), burst_size, "tx burst failed"); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "Bonded Port (%d) opackets value (%u) not as expected (%d)\n", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size); /* Verify slave ports tx stats */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size / test_params->bonded_slave_count, "Slave Port (%d) opackets value (%u) not as expected (%d)\n", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size / test_params->bonded_slave_count); } /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst, burst_size), 0, "tx burst return unexpected value"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val) { int i, refcnt; for (i = 0; i < nb_mbufs; i++) { refcnt = rte_mbuf_refcnt_read(mbufs[i]); TEST_ASSERT_EQUAL(refcnt, val, "mbuf ref count (%d)is not the expected value (%d)", refcnt, val); } return 0; } static void free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs) { int i; for (i = 0; i < nb_mbufs; i++) rte_pktmbuf_free(mbufs[i]); } #define TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT (2) #define TEST_RR_SLAVE_TX_FAIL_BURST_SIZE (64) #define TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT (22) #define TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (1) static int test_roundrobin_tx_burst_slave_tx_fail(void) { struct rte_mbuf *pkt_burst[MAX_PKT_BURST]; struct rte_mbuf *expected_tx_fail_pkts[MAX_PKT_BURST]; struct rte_eth_stats port_stats; int i, first_fail_idx, tx_count; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT, 1), "Failed to intialise bonded device"); /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE, 0, 1, 0, 0, 0), TEST_RR_SLAVE_TX_FAIL_BURST_SIZE, "Failed to generate test packet burst"); /* Copy references to packets which we expect not to be transmitted */ first_fail_idx = (TEST_RR_SLAVE_TX_FAIL_BURST_SIZE - (TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)) + TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX; for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) { expected_tx_fail_pkts[i] = pkt_burst[first_fail_idx + (i * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)]; } /* Set virtual slave to only fail transmission of * TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT packets in burst */ virtual_ethdev_tx_burst_fn_set_success( test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX], 0); virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count( test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT); tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE); TEST_ASSERT_EQUAL(tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE - TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, "Transmitted (%d) an unexpected (%d) number of packets", tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE - TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT); /* Verify that failed packet are expected failed packets */ for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) { TEST_ASSERT_EQUAL(expected_tx_fail_pkts[i], pkt_burst[i + tx_count], "expected mbuf (%d) pointer %p not expected pointer %p", i, expected_tx_fail_pkts[i], pkt_burst[i + tx_count]); } /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)TEST_RR_SLAVE_TX_FAIL_BURST_SIZE - TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE - TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT); /* Verify slave ports tx stats */ for (i = 0; i < test_params->bonded_slave_count; i++) { int slave_expected_tx_count; rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats); slave_expected_tx_count = TEST_RR_SLAVE_TX_FAIL_BURST_SIZE / test_params->bonded_slave_count; if (i == TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX) slave_expected_tx_count = slave_expected_tx_count - TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)slave_expected_tx_count, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[i], (unsigned int)port_stats.opackets, slave_expected_tx_count); } /* Verify that all mbufs have a ref value of zero */ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1), "mbufs refcnts not as expected"); free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_roundrobin_rx_burst_on_single_slave(void) { struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int i, j, burst_size = 25; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 4, 1), "Failed to initialize bonded device with slaves"); /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst( gen_pkt_burst, burst_size, 0, 1, 0, 0, 0), burst_size, "burst generation failed"); for (i = 0; i < test_params->bonded_slave_count; i++) { /* Add rx data to slave */ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[0], burst_size); /* Call rx burst on bonded device */ /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_rx_burst( test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size, "round-robin rx burst failed"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Bonded Port (%d) ipackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size); /* Verify bonded slave devices rx count */ /* Verify slave ports tx stats */ for (j = 0; j < test_params->bonded_slave_count; j++) { rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats); if (i == j) { TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Slave Port (%d) ipackets value (%u) not as expected" " (%d)", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, burst_size); } else { TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as expected" " (%d)", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, 0); } /* Reset bonded slaves stats */ rte_eth_stats_reset(test_params->slave_port_ids[j]); } /* reset bonded device stats */ rte_eth_stats_reset(test_params->bonded_port_id); } /* free mbufs */ for (i = 0; i < MAX_PKT_BURST; i++) { if (gen_pkt_burst[i] != NULL) rte_pktmbuf_free(gen_pkt_burst[i]); if (rx_pkt_burst[i] != NULL) rte_pktmbuf_free(rx_pkt_burst[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT (3) static int test_roundrobin_rx_burst_on_multiple_slaves(void) { struct rte_mbuf *gen_pkt_burst[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int burst_size[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT] = { 15, 13, 36 }; int i, nb_rx; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 4, 1), "Failed to initialize bonded device with slaves"); /* Generate test bursts of packets to transmit */ for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[i][0], burst_size[i], 0, 1, 0, 0, 0), burst_size[i], "burst generation failed"); } /* Add rx data to slaves */ for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) { virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[i][0], burst_size[i]); } /* Call rx burst on bonded device */ /* Send burst on bonded port */ nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST); TEST_ASSERT_EQUAL(nb_rx , burst_size[0] + burst_size[1] + burst_size[2], "round-robin rx burst failed (%d != %d)\n", nb_rx, burst_size[0] + burst_size[1] + burst_size[2]); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]), "Bonded Port (%d) ipackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size[0] + burst_size[1] + burst_size[2]); /* Verify bonded slave devices rx counts */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets, burst_size[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets, burst_size[1]); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets, burst_size[2]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets, 0); /* free mbufs */ for (i = 0; i < MAX_PKT_BURST; i++) { if (rx_pkt_burst[i] != NULL) rte_pktmbuf_free(rx_pkt_burst[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_roundrobin_verify_mac_assignment(void) { struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_2; int i; rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0); rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_2); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 4, 1), "Failed to initialize bonded device with slaves"); /* Verify that all MACs are the same as first slave added to bonded dev */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[i]); } /* change primary and verify that MAC addresses haven't changed */ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[2]), "Failed to set bonded port (%d) primary port to (%d)", test_params->bonded_port_id, test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address has changed to that of primary" " port without stop/start toggle of bonded device", test_params->slave_port_ids[i]); } /* stop / start bonded device and verify that primary MAC address is * propagate to bonded device and slaves */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded device"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS( memcmp(&expected_mac_addr_2, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of new primary port", test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_2, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of new primary" " port", test_params->slave_port_ids[i]); } /* Set explicit MAC address */ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, (struct ether_addr *)bonded_mac), "Failed to set MAC"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of new primary port", test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to" " that of new primary port\n", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_roundrobin_verify_promiscuous_enable_disable(void) { int i, promiscuous_en; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, 4, 1), "Failed to initialize bonded device with slaves"); rte_eth_promiscuous_enable(test_params->bonded_port_id); promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(promiscuous_en, 1, "Port (%d) promiscuous mode not enabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); TEST_ASSERT_EQUAL(promiscuous_en, 1, "slave port (%d) promiscuous mode not enabled", test_params->slave_port_ids[i]); } rte_eth_promiscuous_disable(test_params->bonded_port_id); promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(promiscuous_en, 0, "Port (%d) promiscuous mode not disabled\n", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); TEST_ASSERT_EQUAL(promiscuous_en, 0, "Port (%d) promiscuous mode not disabled\n", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_RR_LINK_STATUS_SLAVE_COUNT (4) #define TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT (2) static int test_roundrobin_verify_slave_link_status_change_behaviour(void) { struct rte_mbuf *tx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_mbuf *gen_pkt_burst[TEST_RR_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; uint8_t slaves[RTE_MAX_ETHPORTS]; int i, burst_size, slave_count; /* NULL all pointers in array to simplify cleanup */ memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst)); /* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves * in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ROUND_ROBIN, 0, TEST_RR_LINK_STATUS_SLAVE_COUNT, 1), "Failed to initialize bonded device with slaves"); /* Verify Current Slaves Count /Active Slave Count is */ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT, "Number of slaves (%d) is not as expected (%d).", slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT, "Number of active slaves (%d) is not as expected (%d).", slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT); /* Set 2 slaves eth_devs link status to down */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT, "Number of active slaves (%d) is not as expected (%d).\n", slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT); burst_size = 20; /* Verify that pkts are not sent on slaves with link status down: * * 1. Generate test burst of traffic * 2. Transmit burst on bonded eth_dev * 3. Verify stats for bonded eth_dev (opackets = burst_size) * 4. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0) */ TEST_ASSERT_EQUAL( generate_test_burst(tx_pkt_burst, burst_size, 0, 1, 0, 0, 0), burst_size, "generate_test_burst failed"); rte_eth_stats_reset(test_params->bonded_port_id); TEST_ASSERT_EQUAL( rte_eth_tx_burst(test_params->bonded_port_id, 0, tx_pkt_burst, burst_size), burst_size, "rte_eth_tx_burst failed"); rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "Port (%d) opackets stats (%d) not expected (%d) value", test_params->bonded_port_id, (int)port_stats.opackets, burst_size); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10, "Port (%d) opackets stats (%d) not expected (%d) value", test_params->slave_port_ids[0], (int)port_stats.opackets, 10); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0, "Port (%d) opackets stats (%d) not expected (%d) value", test_params->slave_port_ids[1], (int)port_stats.opackets, 0); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10, "Port (%d) opackets stats (%d) not expected (%d) value", test_params->slave_port_ids[2], (int)port_stats.opackets, 10); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0, "Port (%d) opackets stats (%d) not expected (%d) value", test_params->slave_port_ids[3], (int)port_stats.opackets, 0); /* Verify that pkts are not sent on slaves with link status down: * * 1. Generate test bursts of traffic * 2. Add bursts on to virtual eth_devs * 3. Rx burst on bonded eth_dev, expected (burst_ size * * TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) received * 4. Verify stats for bonded eth_dev * 6. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0) */ for (i = 0; i < TEST_RR_LINK_STATUS_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size, "failed to generate packet burst"); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[i][0], burst_size); } TEST_ASSERT_EQUAL(rte_eth_rx_burst( test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size + burst_size, "rte_eth_rx_burst failed"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets , (uint64_t)(burst_size + burst_size), "(%d) port_stats.ipackets not as expected\n", test_params->bonded_port_id); /* free mbufs */ for (i = 0; i < MAX_PKT_BURST; i++) { if (rx_pkt_burst[i] != NULL) rte_pktmbuf_free(rx_pkt_burst[i]); if (gen_pkt_burst[1][i] != NULL) rte_pktmbuf_free(gen_pkt_burst[1][i]); if (gen_pkt_burst[3][i] != NULL) rte_pktmbuf_free(gen_pkt_burst[1][i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT (2) uint8_t polling_slave_mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00 }; int polling_test_slaves[TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT] = { -1, -1 }; static int test_roundrobin_verfiy_polling_slave_link_status_change(void) { struct ether_addr *mac_addr = (struct ether_addr *)polling_slave_mac; char slave_name[RTE_ETH_NAME_MAX_LEN]; int i; for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) { /* Generate slave name / MAC address */ snprintf(slave_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_poll_%d", i); mac_addr->addr_bytes[ETHER_ADDR_LEN-1] = i; /* Create slave devices with no ISR Support */ if (polling_test_slaves[i] == -1) { polling_test_slaves[i] = virtual_ethdev_create(slave_name, mac_addr, rte_socket_id(), 0); TEST_ASSERT(polling_test_slaves[i] >= 0, "Failed to create virtual virtual ethdev %s\n", slave_name); /* Configure slave */ TEST_ASSERT_SUCCESS(configure_ethdev(polling_test_slaves[i], 0, 0), "Failed to configure virtual ethdev %s(%d)", slave_name, polling_test_slaves[i]); } /* Add slave to bonded device */ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id, polling_test_slaves[i]), "Failed to add slave %s(%d) to bonded device %d", slave_name, polling_test_slaves[i], test_params->bonded_port_id); } /* Initialize bonded device */ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 1, 1), "Failed to configure bonded device %d", test_params->bonded_port_id); /* Register link status change interrupt callback */ rte_eth_dev_callback_register(test_params->bonded_port_id, RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback, &test_params->bonded_port_id); /* link status change callback for first slave link up */ test_lsc_interrupt_count = 0; virtual_ethdev_set_link_status(polling_test_slaves[0], 1); TEST_ASSERT_SUCCESS(lsc_timeout(15000), "timed out waiting for interrupt"); /* no link status change callback for second slave link up */ test_lsc_interrupt_count = 0; virtual_ethdev_set_link_status(polling_test_slaves[1], 1); TEST_ASSERT_FAIL(lsc_timeout(15000), "unexpectedly succeeded"); /* link status change callback for both slave links down */ test_lsc_interrupt_count = 0; virtual_ethdev_set_link_status(polling_test_slaves[0], 0); virtual_ethdev_set_link_status(polling_test_slaves[1], 0); TEST_ASSERT_SUCCESS(lsc_timeout(20000), "timed out waiting for interrupt"); /* Un-Register link status change interrupt callback */ rte_eth_dev_callback_unregister(test_params->bonded_port_id, RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback, &test_params->bonded_port_id); /* Clean up and remove slaves from bonded device */ for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) { TEST_ASSERT_SUCCESS( rte_eth_bond_slave_remove(test_params->bonded_port_id, polling_test_slaves[i]), "Failed to remove slave %d from bonded port (%d)", polling_test_slaves[i], test_params->bonded_port_id); } return remove_slaves_and_stop_bonded_device(); } /** Active Backup Mode Tests */ static int test_activebackup_tx_burst(void) { int i, pktlen, primary_port, burst_size; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, 1, 1), "Failed to initialize bonded device with slaves"); initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 0, 0); pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 16); pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_0, pktlen); burst_size = 20 * test_params->bonded_slave_count; TEST_ASSERT(burst_size < MAX_PKT_BURST, "Burst size specified is greater than supported."); /* Generate a burst of packets to transmit */ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, pkts_burst, test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1), burst_size, "failed to generate burst correctly"); /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst, burst_size), burst_size, "tx burst failed"); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); /* Verify slave ports tx stats */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats); if (test_params->slave_port_ids[i] == primary_port) { TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size / test_params->bonded_slave_count); } else { TEST_ASSERT_EQUAL(port_stats.opackets, 0, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, 0); } } /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst, burst_size), 0, "Sending empty burst failed"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT (4) static int test_activebackup_rx_burst(void) { struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int primary_port; int i, j, burst_size = 17; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1), "Failed to initialize bonded device with slaves"); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT(primary_port >= 0, "failed to get primary slave for bonded port (%d)", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0), burst_size, "burst generation failed"); /* Add rx data to slave */ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[0], burst_size); /* Call rx burst on bonded device */ TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0, &rx_pkt_burst[0], MAX_PKT_BURST), burst_size, "rte_eth_rx_burst failed"); if (test_params->slave_port_ids[i] == primary_port) { /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Bonded Port (%d) ipackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size); /* Verify bonded slave devices rx count */ for (j = 0; j < test_params->bonded_slave_count; j++) { rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats); if (i == j) { TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Slave Port (%d) ipackets value (%u) not as " "expected (%d)", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, burst_size); } else { TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as " "expected (%d)\n", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, 0); } } } else { for (j = 0; j < test_params->bonded_slave_count; j++) { rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as expected " "(%d)", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, 0); } } /* free mbufs */ for (i = 0; i < MAX_PKT_BURST; i++) { if (rx_pkt_burst[i] != NULL) { rte_pktmbuf_free(rx_pkt_burst[i]); rx_pkt_burst[i] = NULL; } } /* reset bonded device stats */ rte_eth_stats_reset(test_params->bonded_port_id); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_activebackup_verify_promiscuous_enable_disable(void) { int i, primary_port, promiscuous_en; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, 4, 1), "Failed to initialize bonded device with slaves"); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT(primary_port >= 0, "failed to get primary slave for bonded port (%d)", test_params->bonded_port_id); rte_eth_promiscuous_enable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1, "Port (%d) promiscuous mode not enabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); if (primary_port == test_params->slave_port_ids[i]) { TEST_ASSERT_EQUAL(promiscuous_en, 1, "slave port (%d) promiscuous mode not enabled", test_params->slave_port_ids[i]); } else { TEST_ASSERT_EQUAL(promiscuous_en, 0, "slave port (%d) promiscuous mode enabled", test_params->slave_port_ids[i]); } } rte_eth_promiscuous_disable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0, "Port (%d) promiscuous mode not disabled\n", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); TEST_ASSERT_EQUAL(promiscuous_en, 0, "slave port (%d) promiscuous mode not disabled\n", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_activebackup_verify_mac_assignment(void) { struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1; rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0); rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1); /* Initialize bonded device with 2 slaves in active backup mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1), "Failed to initialize bonded device with slaves"); /* Verify that bonded MACs is that of first slave and that the other slave * MAC hasn't been changed */ rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[1]); /* change primary and verify that MAC addresses haven't changed */ TEST_ASSERT_EQUAL(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[1]), 0, "Failed to set bonded port (%d) primary port to (%d)", test_params->bonded_port_id, test_params->slave_port_ids[1]); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[1]); /* stop / start bonded device and verify that primary MAC address is * propagated to bonded device and slaves */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start device"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[1]); /* Set explicit MAC address */ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, (struct ether_addr *)bonded_mac), "failed to set MAC address"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of bonded port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of bonded port", test_params->slave_port_ids[1]); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_activebackup_verify_slave_link_status_change_failover(void) { struct rte_mbuf *pkt_burst[TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; uint8_t slaves[RTE_MAX_ETHPORTS]; int i, j, burst_size, slave_count, primary_port; burst_size = 21; memset(pkt_burst, 0, sizeof(pkt_burst)); /* Generate packet burst for testing */ TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size, "generate_test_burst failed"); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1), "Failed to initialize bonded device with slaves"); /* Verify Current Slaves Count /Active Slave Count is */ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 4, "Number of slaves (%d) is not as expected (%d).", slave_count, 4); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 4, "Number of active slaves (%d) is not as expected (%d).", slave_count, 4); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0], "Primary port not as expected"); /* Bring 2 slaves down and verify active slave count */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2, "Number of active slaves (%d) is not as expected (%d).", slave_count, 2); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 1); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 1); /* Bring primary port down, verify that active slave count is 3 and primary * has changed */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 3, "Number of active slaves (%d) is not as expected (%d).", slave_count, 3); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[2], "Primary port not as expected"); /* Verify that pkts are sent on new primary slave */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size), burst_size, "rte_eth_tx_burst failed"); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[2]); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[1]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[3]); /* Generate packet burst for testing */ for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size, "generate_test_burst failed"); virtual_ethdev_add_mbufs_to_rx_queue( test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size); } TEST_ASSERT_EQUAL(rte_eth_rx_burst( test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size, "rte_eth_rx_burst\n"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "(%d) port_stats.ipackets not as expected", test_params->bonded_port_id); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[2]); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[1]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[3]); /* free mbufs */ for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (pkt_burst[i][j] != NULL) { rte_pktmbuf_free(pkt_burst[i][j]); pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } /** Balance Mode Tests */ static int test_balance_xmit_policy_configuration(void) { TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1), "Failed to initialize_bonded_device_with_slaves."); /* Invalid port id */ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set( INVALID_PORT_ID, BALANCE_XMIT_POLICY_LAYER2), "Expected call to failed as invalid port specified."); /* Set xmit policy on non bonded device */ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set( test_params->slave_port_ids[0], BALANCE_XMIT_POLICY_LAYER2), "Expected call to failed as invalid port specified."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2), "Failed to set balance xmit policy."); TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id), BALANCE_XMIT_POLICY_LAYER2, "balance xmit policy not as expected."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23), "Failed to set balance xmit policy."); TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id), BALANCE_XMIT_POLICY_LAYER23, "balance xmit policy not as expected."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34), "Failed to set balance xmit policy."); TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id), BALANCE_XMIT_POLICY_LAYER34, "balance xmit policy not as expected."); /* Invalid port id */ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_get(INVALID_PORT_ID), "Expected call to failed as invalid port specified."); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT (2) static int test_balance_l2_tx_burst(void) { struct rte_mbuf *pkts_burst[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST]; int burst_size[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT] = { 10, 15 }; uint16_t pktlen; int i; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1), "Failed to initialize_bonded_device_with_slaves."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2), "Failed to set balance xmit policy."); initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 0, 0); pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 16); pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_0, pktlen); /* Generate a burst 1 of packets to transmit */ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[0][0], test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1, test_params->pkt_udp_hdr, burst_size[0], PACKET_BURST_GEN_PKT_LEN, 1), burst_size[0], "failed to generate packet burst"); initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_1, ETHER_TYPE_IPv4, 0, 0); /* Generate a burst 2 of packets to transmit */ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[1][0], test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1, test_params->pkt_udp_hdr, burst_size[1], PACKET_BURST_GEN_PKT_LEN, 1), burst_size[1], "failed to generate packet burst"); /* Send burst 1 on bonded port */ for (i = 0; i < TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkts_burst[i][0], burst_size[i]), burst_size[i], "Failed to transmit packet burst"); } /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size[0] + burst_size[1]), "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size[0] + burst_size[1]); /* Verify slave ports tx stats */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[0], "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.opackets, burst_size[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[1], "Slave Port (%d) opackets value (%u) not as expected (%d)\n", test_params->slave_port_ids[1], (unsigned int)port_stats.opackets, burst_size[1]); /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkts_burst[0][0], burst_size[0]), 0, "Expected zero packet"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4, uint8_t toggle_mac_addr, uint8_t toggle_ip_addr) { int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2; struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST]; struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST]; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, 2, 1), "Failed to initialize_bonded_device_with_slaves."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23), "Failed to set balance xmit policy."); burst_size_1 = 20; burst_size_2 = 10; TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST, "Burst size specified is greater than supported."); /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst( pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0), burst_size_1, "failed to generate packet burst"); TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4, toggle_mac_addr, toggle_ip_addr, 0), burst_size_2, "failed to generate packet burst"); /* Send burst 1 on bonded port */ nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1, burst_size_1); TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed"); /* Send burst 2 on bonded port */ nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2, burst_size_2); TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed"); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2), "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2); /* Verify slave ports tx stats */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.opackets, nb_tx_1); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[1], (unsigned int)port_stats.opackets, nb_tx_2); /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, pkts_burst_1, burst_size_1), 0, "Expected zero packet"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_balance_l23_tx_burst_ipv4_toggle_ip_addr(void) { return balance_l23_tx_burst(0, 1, 1, 0); } static int test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr(void) { return balance_l23_tx_burst(1, 1, 0, 1); } static int test_balance_l23_tx_burst_ipv6_toggle_ip_addr(void) { return balance_l23_tx_burst(0, 0, 0, 1); } static int test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr(void) { return balance_l23_tx_burst(1, 0, 0, 1); } static int test_balance_l23_tx_burst_toggle_mac_addr(void) { return balance_l23_tx_burst(0, 0, 1, 0); } static int balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4, uint8_t toggle_mac_addr, uint8_t toggle_ip_addr, uint8_t toggle_udp_port) { int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2; struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST]; struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST]; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, 2, 1), "Failed to initialize_bonded_device_with_slaves."); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34), "Failed to set balance xmit policy."); burst_size_1 = 20; burst_size_2 = 10; TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST, "Burst size specified is greater than supported."); /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst( pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0), burst_size_1, "failed to generate burst"); TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4, toggle_mac_addr, toggle_ip_addr, toggle_udp_port), burst_size_2, "failed to generate burst"); /* Send burst 1 on bonded port */ nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1, burst_size_1); TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed"); /* Send burst 2 on bonded port */ nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2, burst_size_2); TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed"); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2), "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, nb_tx_1 + nb_tx_2); /* Verify slave ports tx stats */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.opackets, nb_tx_1); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[1], (unsigned int)port_stats.opackets, nb_tx_2); /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, pkts_burst_1, burst_size_1), 0, "Expected zero packet"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_balance_l34_tx_burst_ipv4_toggle_ip_addr(void) { return balance_l34_tx_burst(0, 1, 0, 1, 0); } static int test_balance_l34_tx_burst_ipv4_toggle_udp_port(void) { return balance_l34_tx_burst(0, 1, 0, 0, 1); } static int test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr(void) { return balance_l34_tx_burst(1, 1, 0, 1, 0); } static int test_balance_l34_tx_burst_ipv6_toggle_ip_addr(void) { return balance_l34_tx_burst(0, 0, 0, 1, 0); } static int test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr(void) { return balance_l34_tx_burst(1, 0, 0, 1, 0); } static int test_balance_l34_tx_burst_ipv6_toggle_udp_port(void) { return balance_l34_tx_burst(0, 0, 0, 0, 1); } #define TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT (2) #define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 (40) #define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2 (20) #define TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT (25) #define TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (0) static int test_balance_tx_burst_slave_tx_fail(void) { struct rte_mbuf *pkts_burst_1[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1]; struct rte_mbuf *pkts_burst_2[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2]; struct rte_mbuf *expected_fail_pkts[TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT]; struct rte_eth_stats port_stats; int i, first_tx_fail_idx, tx_count_1, tx_count_2; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT, 1), "Failed to intialise bonded device"); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2), "Failed to set balance xmit policy."); /* Generate test bursts for transmission */ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, 0, 0, 0, 0, 0), TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, "Failed to generate test packet burst 1"); first_tx_fail_idx = TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; /* copy mbuf referneces for expected transmission failures */ for (i = 0; i < TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; i++) expected_fail_pkts[i] = pkts_burst_1[i + first_tx_fail_idx]; TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, 0, 0, 1, 0, 0), TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, "Failed to generate test packet burst 2"); /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */ virtual_ethdev_tx_burst_fn_set_success( test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX], 0); virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count( test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX], TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT); /* Transmit burst 1 */ tx_count_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1); TEST_ASSERT_EQUAL(tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, "Transmitted (%d) packets, expected to transmit (%d) packets", tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT); /* Verify that failed packet are expected failed packets */ for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) { TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst_1[i + tx_count_1], "expected mbuf (%d) pointer %p not expected pointer %p", i, expected_fail_pkts[i], pkts_burst_1[i + tx_count_1]); } /* Transmit burst 2 */ tx_count_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2); TEST_ASSERT_EQUAL(tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, "Transmitted (%d) packets, expected to transmit (%d) packets", tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)((TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) + TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2), "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, (TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) + TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2); /* Verify slave ports tx stats */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t) TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.opackets, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 - TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, "Slave Port (%d) opackets value (%u) not as expected (%d)", test_params->slave_port_ids[1], (unsigned int)port_stats.opackets, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2); /* Verify that all mbufs have a ref value of zero */ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1], TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1), "mbufs refcnts not as expected"); free_mbufs(&pkts_burst_1[tx_count_1], TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3) static int test_balance_rx_burst(void) { struct rte_mbuf *gen_pkt_burst[TEST_BALANCE_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int burst_size[TEST_BALANCE_RX_BURST_SLAVE_COUNT] = { 10, 5, 30 }; int i, j; memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst)); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, 3, 1), "Failed to intialise bonded device"); /* Generate test bursts of packets to transmit */ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0, 0), burst_size[i], "failed to generate packet burst"); } /* Add rx data to slaves */ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) { virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[i][0], burst_size[i]); } /* Call rx burst on bonded device */ /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size[0] + burst_size[1] + burst_size[2], "balance rx burst failed\n"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]), "Bonded Port (%d) ipackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size[0] + burst_size[1] + burst_size[2]); /* Verify bonded slave devices rx counts */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets, burst_size[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets, burst_size[1]); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets, burst_size[2]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets, 0); /* free mbufs */ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (gen_pkt_burst[i][j] != NULL) { rte_pktmbuf_free(gen_pkt_burst[i][j]); gen_pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_balance_verify_promiscuous_enable_disable(void) { int i; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, 4, 1), "Failed to intialise bonded device"); rte_eth_promiscuous_enable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1, "Port (%d) promiscuous mode not enabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { TEST_ASSERT_EQUAL(rte_eth_promiscuous_get( test_params->slave_port_ids[i]), 1, "Port (%d) promiscuous mode not enabled", test_params->slave_port_ids[i]); } rte_eth_promiscuous_disable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0, "Port (%d) promiscuous mode not disabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { TEST_ASSERT_EQUAL(rte_eth_promiscuous_get( test_params->slave_port_ids[i]), 0, "Port (%d) promiscuous mode not disabled", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_balance_verify_mac_assignment(void) { struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1; rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0); rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1); /* Initialize bonded device with 2 slaves in active backup mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, 2, 1), "Failed to intialise bonded device"); /* Verify that bonded MACs is that of first slave and that the other slave * MAC hasn't been changed */ rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[1]); /* change primary and verify that MAC addresses haven't changed */ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[1]), "Failed to set bonded port (%d) primary port to (%d)\n", test_params->bonded_port_id, test_params->slave_port_ids[1]); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[1]); /* stop / start bonded device and verify that primary MAC address is * propagated to bonded device and slaves */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded device"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[1]); /* Set explicit MAC address */ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, (struct ether_addr *)bonded_mac), "failed to set MAC"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of bonded port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected\n", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of bonded port", test_params->slave_port_ids[1]); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_BALANCE_LINK_STATUS_SLAVE_COUNT (4) static int test_balance_verify_slave_link_status_change_behaviour(void) { struct rte_mbuf *pkt_burst[TEST_BALANCE_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; uint8_t slaves[RTE_MAX_ETHPORTS]; int i, j, burst_size, slave_count; memset(pkt_burst, 0, sizeof(pkt_burst)); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BALANCE, 0, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1), "Failed to intialise bonded device"); TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set( test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2), "Failed to set balance xmit policy."); /* Verify Current Slaves Count /Active Slave Count is */ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, "Number of slaves (%d) is not as expected (%d).", slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, "Number of active slaves (%d) is not as expected (%d).", slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT); /* Set 2 slaves link status to down */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2, "Number of active slaves (%d) is not as expected (%d).", slave_count, 2); /* Send to sets of packet burst and verify that they are balanced across * slaves */ burst_size = 21; TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size, "generate_test_burst failed"); TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0), burst_size, "generate_test_burst failed"); TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size), burst_size, "rte_eth_tx_burst failed"); TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size), burst_size, "rte_eth_tx_burst failed"); rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size), "(%d) port_stats.opackets (%d) not as expected (%d).", test_params->bonded_port_id, (int)port_stats.opackets, burst_size + burst_size); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets (%d) not as expected (%d).", test_params->slave_port_ids[0], (int)port_stats.opackets, burst_size); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets (%d) not as expected (%d).", test_params->slave_port_ids[2], (int)port_stats.opackets, burst_size); /* verify that all packets get send on primary slave when no other slaves * are available */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[2], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 1, "Number of active slaves (%d) is not as expected (%d).", slave_count, 1); TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0), burst_size, "generate_test_burst failed"); TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size), burst_size, "rte_eth_tx_burst failed"); rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size + burst_size), "(%d) port_stats.opackets (%d) not as expected (%d).\n", test_params->bonded_port_id, (int)port_stats.opackets, burst_size + burst_size + burst_size); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size), "(%d) port_stats.opackets (%d) not as expected (%d).", test_params->slave_port_ids[0], (int)port_stats.opackets, burst_size + burst_size); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 1); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[2], 1); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 1); for (i = 0; i < TEST_BALANCE_LINK_STATUS_SLAVE_COUNT; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size, "Failed to generate packet burst"); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size); } /* Verify that pkts are not received on slaves with link status down */ rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size * 3), "(%d) port_stats.ipackets (%d) not as expected (%d)\n", test_params->bonded_port_id, (int)port_stats.ipackets, burst_size * 3); /* free mbufs allocate for rx testing */ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (pkt_burst[i][j] != NULL) { rte_pktmbuf_free(pkt_burst[i][j]); pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_broadcast_tx_burst(void) { int i, pktlen, burst_size; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_eth_stats port_stats; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, 2, 1), "Failed to intialise bonded device"); initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 0, 0); pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 16); pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_0, pktlen); burst_size = 20 * test_params->bonded_slave_count; TEST_ASSERT(burst_size < MAX_PKT_BURST, "Burst size specified is greater than supported."); /* Generate a burst of packets to transmit */ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, pkts_burst, test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1), burst_size, "Failed to generate packet burst"); /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst, burst_size), burst_size, "Bonded Port (%d) rx burst failed, packets transmitted value " "not as expected (%d)", test_params->bonded_port_id, burst_size); /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size * test_params->bonded_slave_count, "Bonded Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size); /* Verify slave ports tx stats */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "Slave Port (%d) opackets value (%u) not as expected (%d)\n", test_params->bonded_port_id, (unsigned int)port_stats.opackets, burst_size); } /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, pkts_burst, burst_size), 0, "transmitted an unexpected number of packets"); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT (3) #define TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE (40) #define TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT (15) #define TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT (10) static int test_broadcast_tx_burst_slave_tx_fail(void) { struct rte_mbuf *pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE]; struct rte_mbuf *expected_fail_pkts[TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT]; struct rte_eth_stats port_stats; int i, tx_count; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT, 1), "Failed to intialise bonded device"); /* Generate test bursts for transmission */ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, 0, 0, 0, 0, 0), TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, "Failed to generate test packet burst"); for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) { expected_fail_pkts[i] = pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT + i]; } /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */ virtual_ethdev_tx_burst_fn_set_success( test_params->slave_port_ids[0], 0); virtual_ethdev_tx_burst_fn_set_success( test_params->slave_port_ids[1], 0); virtual_ethdev_tx_burst_fn_set_success( test_params->slave_port_ids[2], 0); virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count( test_params->slave_port_ids[0], TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT); virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count( test_params->slave_port_ids[1], TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT); virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count( test_params->slave_port_ids[2], TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT); /* Transmit burst */ tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE); TEST_ASSERT_EQUAL(tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, "Transmitted (%d) packets, expected to transmit (%d) packets", tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT); /* Verify that failed packet are expected failed packets */ for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) { TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst[i + tx_count], "expected mbuf (%d) pointer %p not expected pointer %p", i, expected_fail_pkts[i], pkts_burst[i + tx_count]); } /* Verify slave ports tx stats */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT, "Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, "Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT, "Port (%d) opackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.opackets, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE - TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT); /* Verify that all mbufs who transmission failed have a ref value of one */ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst[tx_count], TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, 1), "mbufs refcnts not as expected"); free_mbufs(&pkts_burst[tx_count], TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define BROADCAST_RX_BURST_NUM_OF_SLAVES (3) static int test_broadcast_rx_burst(void) { struct rte_mbuf *gen_pkt_burst[BROADCAST_RX_BURST_NUM_OF_SLAVES][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int burst_size[BROADCAST_RX_BURST_NUM_OF_SLAVES] = { 10, 5, 30 }; int i, j; memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst)); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, 3, 1), "Failed to intialise bonded device"); /* Generate test bursts of packets to transmit */ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0, 0), burst_size[i], "failed to generate packet burst"); } /* Add rx data to slave 0 */ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) { virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[i][0], burst_size[i]); } /* Call rx burst on bonded device */ /* Send burst on bonded port */ TEST_ASSERT_EQUAL(rte_eth_rx_burst( test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size[0] + burst_size[1] + burst_size[2], "rx burst failed"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]), "Bonded Port (%d) ipackets value (%u) not as expected (%d)", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size[0] + burst_size[1] + burst_size[2]); /* Verify bonded slave devices rx counts */ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets, burst_size[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets, burst_size[1]); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2], "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets, burst_size[2]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, 0, "Slave Port (%d) ipackets value (%u) not as expected (%d)", test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets, 0); /* free mbufs allocate for rx testing */ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (gen_pkt_burst[i][j] != NULL) { rte_pktmbuf_free(gen_pkt_burst[i][j]); gen_pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_broadcast_verify_promiscuous_enable_disable(void) { int i; /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, 4, 1), "Failed to intialise bonded device"); rte_eth_promiscuous_enable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1, "Port (%d) promiscuous mode not enabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { TEST_ASSERT_EQUAL(rte_eth_promiscuous_get( test_params->slave_port_ids[i]), 1, "Port (%d) promiscuous mode not enabled", test_params->slave_port_ids[i]); } rte_eth_promiscuous_disable(test_params->bonded_port_id); TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0, "Port (%d) promiscuous mode not disabled", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { TEST_ASSERT_EQUAL(rte_eth_promiscuous_get( test_params->slave_port_ids[i]), 0, "Port (%d) promiscuous mode not disabled", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_broadcast_verify_mac_assignment(void) { struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1; int i; rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0); rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, 4, 1), "Failed to intialise bonded device"); /* Verify that all MACs are the same as first slave added to bonded * device */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[i]); } /* change primary and verify that MAC addresses haven't changed */ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[2]), "Failed to set bonded port (%d) primary port to (%d)", test_params->bonded_port_id, test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address has changed to that of primary " "port without stop/start toggle of bonded device", test_params->slave_port_ids[i]); } /* stop / start bonded device and verify that primary MAC address is * propagated to bonded device and slaves */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start bonded device"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of new primary port", test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of new primary " "port", test_params->slave_port_ids[i]); } /* Set explicit MAC address */ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, (struct ether_addr *)bonded_mac), "Failed to set MAC address"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of new primary port", test_params->slave_port_ids[i]); for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of new primary " "port", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define BROADCAST_LINK_STATUS_NUM_OF_SLAVES (4) static int test_broadcast_verify_slave_link_status_change_behaviour(void) { struct rte_mbuf *pkt_burst[BROADCAST_LINK_STATUS_NUM_OF_SLAVES][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; uint8_t slaves[RTE_MAX_ETHPORTS]; int i, j, burst_size, slave_count; memset(pkt_burst, 0, sizeof(pkt_burst)); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_BROADCAST, 0, BROADCAST_LINK_STATUS_NUM_OF_SLAVES, 1), "Failed to intialise bonded device"); /* Verify Current Slaves Count /Active Slave Count is */ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 4, "Number of slaves (%d) is not as expected (%d).", slave_count, 4); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 4, "Number of active slaves (%d) is not as expected (%d).", slave_count, 4); /* Set 2 slaves link status to down */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 2, "Number of active slaves (%d) is not as expected (%d).", slave_count, 2); for (i = 0; i < test_params->bonded_slave_count; i++) rte_eth_stats_reset(test_params->slave_port_ids[i]); /* Verify that pkts are not sent on slaves with link status down */ burst_size = 21; TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[0][0], burst_size, 0, 0, 1, 0, 0), burst_size, "generate_test_burst failed"); TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size), burst_size, "rte_eth_tx_burst failed\n"); rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size * slave_count), "(%d) port_stats.opackets (%d) not as expected (%d)\n", test_params->bonded_port_id, (int)port_stats.opackets, burst_size * slave_count); rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[1]); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[2]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, 0, "(%d) port_stats.opackets not as expected", test_params->slave_port_ids[3]); for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[i][0], burst_size, 0, 0, 1, 0, 0), burst_size, "failed to generate packet burst"); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size); } /* Verify that pkts are not received on slaves with link status down */ TEST_ASSERT_EQUAL(rte_eth_rx_burst( test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST), burst_size + burst_size, "rte_eth_rx_burst failed"); /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size + burst_size), "(%d) port_stats.ipackets not as expected\n", test_params->bonded_port_id); /* free mbufs allocate for rx testing */ for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (pkt_burst[i][j] != NULL) { rte_pktmbuf_free(pkt_burst[i][j]); pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_reconfigure_bonded_device(void) { test_params->nb_rx_q = 4; test_params->nb_tx_q = 4; TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0), "failed to reconfigure bonded device"); test_params->nb_rx_q = 2; test_params->nb_tx_q = 2; TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0), "failed to reconfigure bonded device with less rx/tx queues"); return 0; } static int test_close_bonded_device(void) { rte_eth_dev_close(test_params->bonded_port_id); return 0; } static int testsuite_teardown(void) { if (test_params->pkt_eth_hdr != NULL) { free(test_params->pkt_eth_hdr); test_params->pkt_eth_hdr = NULL; } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static void free_virtualpmd_tx_queue(void) { int i, slave_port, to_free_cnt; struct rte_mbuf *pkts_to_free[MAX_PKT_BURST]; /* Free tx queue of virtual pmd */ for (slave_port = 0; slave_port < test_params->bonded_slave_count; slave_port++) { to_free_cnt = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_port], pkts_to_free, MAX_PKT_BURST); for (i = 0; i < to_free_cnt; i++) rte_pktmbuf_free(pkts_to_free[i]); } } static int test_tlb_tx_burst(void) { int i, burst_size, nb_tx; uint64_t nb_tx2 = 0; struct rte_mbuf *pkt_burst[MAX_PKT_BURST]; struct rte_eth_stats port_stats[32]; uint64_t sum_ports_opackets = 0, all_bond_opackets = 0, all_bond_obytes = 0; uint16_t pktlen; TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves (BONDING_MODE_TLB, 1, 3, 1), "Failed to initialise bonded device"); burst_size = 20 * test_params->bonded_slave_count; TEST_ASSERT(burst_size < MAX_PKT_BURST, "Burst size specified is greater than supported.\n"); /* Generate bursts of packets */ for (i = 0; i < 400000; i++) { /*test two types of mac src own(bonding) and others */ if (i % 2 == 0) { initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 0, 0); } else { initialize_eth_header(test_params->pkt_eth_hdr, (struct ether_addr *)test_params->default_slave_mac, (struct ether_addr *)dst_mac_0, ETHER_TYPE_IPv4, 0, 0); } pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port, dst_port_0, 16); pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr, dst_addr_0, pktlen); generate_packet_burst(test_params->mbuf_pool, pkt_burst, test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1, test_params->pkt_udp_hdr, burst_size, 60, 1); /* Send burst on bonded port */ nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst, burst_size); nb_tx2 += nb_tx; free_virtualpmd_tx_queue(); TEST_ASSERT_EQUAL(nb_tx, burst_size, "number of packet not equal burst size"); rte_delay_us(5); } /* Verify bonded port tx stats */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats[0]); all_bond_opackets = port_stats[0].opackets; all_bond_obytes = port_stats[0].obytes; TEST_ASSERT_EQUAL(port_stats[0].opackets, (uint64_t)nb_tx2, "Bonded Port (%d) opackets value (%u) not as expected (%d)\n", test_params->bonded_port_id, (unsigned int)port_stats[0].opackets, burst_size); /* Verify slave ports tx stats */ for (i = 0; i < test_params->bonded_slave_count; i++) { rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats[i]); sum_ports_opackets += port_stats[i].opackets; } TEST_ASSERT_EQUAL(sum_ports_opackets, (uint64_t)all_bond_opackets, "Total packets sent by slaves is not equal to packets sent by bond interface"); /* checking if distribution of packets is balanced over slaves */ for (i = 0; i < test_params->bonded_slave_count; i++) { TEST_ASSERT(port_stats[i].obytes > 0 && port_stats[i].obytes < all_bond_obytes, "Packets are not balanced over slaves"); } /* Put all slaves down and try and transmit */ for (i = 0; i < test_params->bonded_slave_count; i++) { virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[i], 0); } /* Send burst on bonded port */ nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst, burst_size); TEST_ASSERT_EQUAL(nb_tx, 0, " bad number of packet in burst"); /* Clean ugit checkout masterp and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT (4) static int test_tlb_rx_burst(void) { struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; int primary_port; uint16_t i, j, nb_rx, burst_size = 17; /* Initialize bonded device with 4 slaves in transmit load balancing mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_TLB, TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT, 1, 1), "Failed to initialize bonded device"); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT(primary_port >= 0, "failed to get primary slave for bonded port (%d)", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { /* Generate test bursts of packets to transmit */ TEST_ASSERT_EQUAL(generate_test_burst( &gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0), burst_size, "burst generation failed"); /* Add rx data to slave */ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i], &gen_pkt_burst[0], burst_size); /* Call rx burst on bonded device */ nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, &rx_pkt_burst[0], MAX_PKT_BURST); TEST_ASSERT_EQUAL(nb_rx, burst_size, "rte_eth_rx_burst failed\n"); if (test_params->slave_port_ids[i] == primary_port) { /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Bonded Port (%d) ipackets value (%u) not as expected (%d)\n", test_params->bonded_port_id, (unsigned int)port_stats.ipackets, burst_size); /* Verify bonded slave devices rx count */ for (j = 0; j < test_params->bonded_slave_count; j++) { rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats); if (i == j) { TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "Slave Port (%d) ipackets value (%u) not as expected (%d)\n", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, burst_size); } else { TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)0, "Slave Port (%d) ipackets value (%u) not as expected (%d)\n", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, 0); } } } else { for (j = 0; j < test_params->bonded_slave_count; j++) { rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)0, "Slave Port (%d) ipackets value (%u) not as expected (%d)\n", test_params->slave_port_ids[i], (unsigned int)port_stats.ipackets, 0); } } /* free mbufs */ for (i = 0; i < burst_size; i++) rte_pktmbuf_free(rx_pkt_burst[i]); /* reset bonded device stats */ rte_eth_stats_reset(test_params->bonded_port_id); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_tlb_verify_promiscuous_enable_disable(void) { int i, primary_port, promiscuous_en; /* Initialize bonded device with 4 slaves in transmit load balancing mode */ TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves( BONDING_MODE_TLB, 0, 4, 1), "Failed to initialize bonded device"); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT(primary_port >= 0, "failed to get primary slave for bonded port (%d)", test_params->bonded_port_id); rte_eth_promiscuous_enable(test_params->bonded_port_id); promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(promiscuous_en, (int)1, "Port (%d) promiscuous mode not enabled\n", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); if (primary_port == test_params->slave_port_ids[i]) { TEST_ASSERT_EQUAL(promiscuous_en, (int)1, "Port (%d) promiscuous mode not enabled\n", test_params->bonded_port_id); } else { TEST_ASSERT_EQUAL(promiscuous_en, (int)0, "Port (%d) promiscuous mode enabled\n", test_params->bonded_port_id); } } rte_eth_promiscuous_disable(test_params->bonded_port_id); promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(promiscuous_en, (int)0, "Port (%d) promiscuous mode not disabled\n", test_params->bonded_port_id); for (i = 0; i < test_params->bonded_slave_count; i++) { promiscuous_en = rte_eth_promiscuous_get( test_params->slave_port_ids[i]); TEST_ASSERT_EQUAL(promiscuous_en, (int)0, "slave port (%d) promiscuous mode not disabled\n", test_params->slave_port_ids[i]); } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_tlb_verify_mac_assignment(void) { struct ether_addr read_mac_addr, expected_mac_addr_0, expected_mac_addr_1; rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0); rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1); /* Initialize bonded device with 2 slaves in active backup mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_TLB, 0, 2, 1), "Failed to initialize bonded device"); /* Verify that bonded MACs is that of first slave and that the other slave * MAC hasn't been changed */ rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[1]); /* change primary and verify that MAC addresses haven't changed */ TEST_ASSERT_EQUAL(rte_eth_bond_primary_set(test_params->bonded_port_id, test_params->slave_port_ids[1]), 0, "Failed to set bonded port (%d) primary port to (%d)", test_params->bonded_port_id, test_params->slave_port_ids[1]); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[1]); /* stop / start bonded device and verify that primary MAC address is * propagated to bonded device and slaves */ rte_eth_dev_stop(test_params->bonded_port_id); TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id), "Failed to start device"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of primary port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of primary port", test_params->slave_port_ids[1]); /* Set explicit MAC address */ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set( test_params->bonded_port_id, (struct ether_addr *)bonded_mac), "failed to set MAC addres"); rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "bonded port (%d) mac address not set to that of bonded port", test_params->bonded_port_id); rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not as expected", test_params->slave_port_ids[0]); rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr); TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr, sizeof(read_mac_addr)), "slave port (%d) mac address not set to that of bonded port", test_params->slave_port_ids[1]); /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } static int test_tlb_verify_slave_link_status_change_failover(void) { struct rte_mbuf *pkt_burst[TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST]; struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL }; struct rte_eth_stats port_stats; uint8_t slaves[RTE_MAX_ETHPORTS]; int i, j, burst_size, slave_count, primary_port; burst_size = 21; memset(pkt_burst, 0, sizeof(pkt_burst)); /* Initialize bonded device with 4 slaves in round robin mode */ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves( BONDING_MODE_TLB, 0, TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT, 1), "Failed to initialize bonded device with slaves"); /* Verify Current Slaves Count /Active Slave Count is */ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, 4, "Number of slaves (%d) is not as expected (%d).\n", slave_count, 4); slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS); TEST_ASSERT_EQUAL(slave_count, (int)4, "Number of slaves (%d) is not as expected (%d).\n", slave_count, 4); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0], "Primary port not as expected"); /* Bring 2 slaves down and verify active slave count */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 0); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2, "Number of active slaves (%d) is not as expected (%d).", slave_count, 2); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[1], 1); virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[3], 1); /* Bring primary port down, verify that active slave count is 3 and primary * has changed */ virtual_ethdev_simulate_link_status_interrupt( test_params->slave_port_ids[0], 0); TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get( test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 3, "Number of active slaves (%d) is not as expected (%d).", slave_count, 3); primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id); TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[2], "Primary port not as expected"); rte_delay_us(500000); /* Verify that pkts are sent on new primary slave */ for (i = 0; i < 4; i++) { TEST_ASSERT_EQUAL(generate_test_burst( &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size, "generate_test_burst failed\n"); TEST_ASSERT_EQUAL(rte_eth_tx_burst( test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size), burst_size, "rte_eth_tx_burst failed\n"); rte_delay_us(11000); } rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats); TEST_ASSERT_EQUAL(port_stats.opackets, (int8_t)0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[0]); rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats); TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[1]); rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats); TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[2]); rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats); TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0, "(%d) port_stats.opackets not as expected\n", test_params->slave_port_ids[3]); /* Generate packet burst for testing */ for (i = 0; i < TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT; i++) { if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) != burst_size) return -1; virtual_ethdev_add_mbufs_to_rx_queue( test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size); } if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST) != burst_size) { printf("rte_eth_rx_burst\n"); return -1; } /* Verify bonded device rx count */ rte_eth_stats_get(test_params->bonded_port_id, &port_stats); TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size, "(%d) port_stats.ipackets not as expected\n", test_params->bonded_port_id); /* free mbufs */ for (i = 0; i < TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT; i++) { for (j = 0; j < MAX_PKT_BURST; j++) { if (pkt_burst[i][j] != NULL) { rte_pktmbuf_free(pkt_burst[i][j]); pkt_burst[i][j] = NULL; } } } /* Clean up and remove slaves from bonded device */ return remove_slaves_and_stop_bonded_device(); } #define TEST_ALB_SLAVE_COUNT 2 static uint8_t mac_client1[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 1}; static uint8_t mac_client2[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 2}; static uint8_t mac_client3[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 3}; static uint8_t mac_client4[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 4}; static uint32_t ip_host = IPV4_ADDR(192, 168, 0, 0); static uint32_t ip_client1 = IPV4_ADDR(192, 168, 0, 1); static uint32_t ip_client2 = IPV4_ADDR(192, 168, 0, 2); static uint32_t ip_client3 = IPV4_ADDR(192, 168, 0, 3); static uint32_t ip_client4 = IPV4_ADDR(192, 168, 0, 4); static int test_alb_change_mac_in_reply_sent(void) { struct rte_mbuf *pkt; struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; struct ether_hdr *eth_pkt; struct arp_hdr *arp_pkt; int slave_idx, nb_pkts, pkt_idx; int retval = 0; struct ether_addr bond_mac, client_mac; struct ether_addr *slave_mac1, *slave_mac2; TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(BONDING_MODE_ALB, 0, TEST_ALB_SLAVE_COUNT, 1), "Failed to initialize_bonded_device_with_slaves."); /* Flush tx queue */ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); } ether_addr_copy( rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, &bond_mac); /* * Generating four packets with different mac and ip addresses and sending * them through the bonding port. */ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client1, ARP_OP_REPLY); rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client2, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client2, ARP_OP_REPLY); rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client3, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client3, ARP_OP_REPLY); rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client4, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client4, ARP_OP_REPLY); rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1); slave_mac1 = rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs; slave_mac2 = rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs; /* * Checking if packets are properly distributed on bonding ports. Packets * 0 and 2 should be sent on port 0 and packets 1 and 3 on port 1. */ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); if (slave_idx%2 == 0) { if (!is_same_ether_addr(slave_mac1, &arp_pkt->arp_data.arp_sha)) { retval = -1; goto test_end; } } else { if (!is_same_ether_addr(slave_mac2, &arp_pkt->arp_data.arp_sha)) { retval = -1; goto test_end; } } } } test_end: retval += remove_slaves_and_stop_bonded_device(); return retval; } static int test_alb_reply_from_client(void) { struct ether_hdr *eth_pkt; struct arp_hdr *arp_pkt; struct rte_mbuf *pkt; struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; int slave_idx, nb_pkts, pkt_idx, nb_pkts_sum = 0; int retval = 0; struct ether_addr bond_mac, client_mac; struct ether_addr *slave_mac1, *slave_mac2; TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(BONDING_MODE_ALB, 0, TEST_ALB_SLAVE_COUNT, 1), "Failed to initialize_bonded_device_with_slaves."); /* Flush tx queue */ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); } ether_addr_copy( rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, &bond_mac); /* * Generating four packets with different mac and ip addresses and placing * them in the rx queue to be received by the bonding driver on rx_burst. */ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host, ARP_OP_REPLY); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client2, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client2, ip_host, ARP_OP_REPLY); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client3, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client3, ip_host, ARP_OP_REPLY); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, 1); pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client4, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_ARP, 0, 0); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client4, ip_host, ARP_OP_REPLY); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, 1); /* * Issue rx_burst and tx_burst to force bonding driver to send update ARP * packets to every client in alb table. */ rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST); rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); slave_mac1 = rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs; slave_mac2 = rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs; /* * Checking if update ARP packets were properly send on slave ports. */ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); nb_pkts_sum += nb_pkts; for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); arp_pkt = (struct arp_hdr *)((char *)eth_pkt + sizeof(struct ether_hdr)); if (slave_idx%2 == 0) { if (!is_same_ether_addr(slave_mac1, &arp_pkt->arp_data.arp_sha)) { retval = -1; goto test_end; } } else { if (!is_same_ether_addr(slave_mac2, &arp_pkt->arp_data.arp_sha)) { retval = -1; goto test_end; } } } } /* Check if proper number of packets was send */ if (nb_pkts_sum < 4) { retval = -1; goto test_end; } test_end: retval += remove_slaves_and_stop_bonded_device(); return retval; } static int test_alb_receive_vlan_reply(void) { struct ether_hdr *eth_pkt; struct vlan_hdr *vlan_pkt; struct arp_hdr *arp_pkt; struct rte_mbuf *pkt; struct rte_mbuf *pkts_sent[MAX_PKT_BURST]; int slave_idx, nb_pkts, pkt_idx; int retval = 0; struct ether_addr bond_mac, client_mac; TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(BONDING_MODE_ALB, 0, TEST_ALB_SLAVE_COUNT, 1), "Failed to initialize_bonded_device_with_slaves."); /* Flush tx queue */ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); } ether_addr_copy( rte_eth_devices[test_params->bonded_port_id].data->mac_addrs, &bond_mac); /* * Generating packet with double VLAN header and placing it in the rx queue. */ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool); memcpy(client_mac.addr_bytes, mac_client1, ETHER_ADDR_LEN); eth_pkt = rte_pktmbuf_mtod(pkt, struct ether_hdr *); initialize_eth_header(eth_pkt, &bond_mac, &client_mac, ETHER_TYPE_VLAN, 0, 0); vlan_pkt = (struct vlan_hdr *)((char *)(eth_pkt + 1)); vlan_pkt->vlan_tci = rte_cpu_to_be_16(1); vlan_pkt->eth_proto = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vlan_pkt = vlan_pkt+1; vlan_pkt->vlan_tci = rte_cpu_to_be_16(2); vlan_pkt->eth_proto = rte_cpu_to_be_16(ETHER_TYPE_ARP); arp_pkt = (struct arp_hdr *)((char *)(vlan_pkt + 1)); initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host, ARP_OP_REPLY); virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt, 1); rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST); rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0); /* * Checking if VLAN headers in generated ARP Update packet are correct. */ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) { nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue( test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST); for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) { eth_pkt = rte_pktmbuf_mtod(pkts_sent[pkt_idx], struct ether_hdr *); vlan_pkt = (struct vlan_hdr *)((char *)(eth_pkt + 1)); if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(1)) { retval = -1; goto test_end; } if (vlan_pkt->eth_proto != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) { retval = -1; goto test_end; } vlan_pkt = vlan_pkt+1; if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(2)) { retval = -1; goto test_end; } if (vlan_pkt->eth_proto != rte_cpu_to_be_16(ETHER_TYPE_ARP)) { retval = -1; goto test_end; } } } test_end: retval += remove_slaves_and_stop_bonded_device(); return retval; } static int test_alb_ipv4_tx(void) { int burst_size, retval, pkts_send; struct rte_mbuf *pkt_burst[MAX_PKT_BURST]; retval = 0; TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(BONDING_MODE_ALB, 0, TEST_ALB_SLAVE_COUNT, 1), "Failed to initialize_bonded_device_with_slaves."); burst_size = 32; /* Generate test bursts of packets to transmit */ if (generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0) != burst_size) { retval = -1; goto test_end; } /* * Checking if ipv4 traffic is transmitted via TLB policy. */ pkts_send = rte_eth_tx_burst( test_params->bonded_port_id, 0, pkt_burst, burst_size); if (pkts_send != burst_size) { retval = -1; goto test_end; } test_end: retval += remove_slaves_and_stop_bonded_device(); return retval; } static struct unit_test_suite link_bonding_test_suite = { .suite_name = "Link Bonding Unit Test Suite", .setup = test_setup, .teardown = testsuite_teardown, .unit_test_cases = { TEST_CASE(test_create_bonded_device), TEST_CASE(test_create_bonded_device_with_invalid_params), TEST_CASE(test_add_slave_to_bonded_device), TEST_CASE(test_add_slave_to_invalid_bonded_device), TEST_CASE(test_remove_slave_from_bonded_device), TEST_CASE(test_remove_slave_from_invalid_bonded_device), TEST_CASE(test_get_slaves_from_bonded_device), TEST_CASE(test_add_already_bonded_slave_to_bonded_device), TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device), TEST_CASE(test_start_bonded_device), TEST_CASE(test_stop_bonded_device), TEST_CASE(test_set_bonding_mode), TEST_CASE(test_set_primary_slave), TEST_CASE(test_set_explicit_bonded_mac), TEST_CASE(test_set_bonded_port_initialization_mac_assignment), TEST_CASE(test_status_interrupt), TEST_CASE(test_adding_slave_after_bonded_device_started), TEST_CASE(test_roundrobin_tx_burst), TEST_CASE(test_roundrobin_tx_burst_slave_tx_fail), TEST_CASE(test_roundrobin_rx_burst_on_single_slave), TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves), TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable), TEST_CASE(test_roundrobin_verify_mac_assignment), TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour), TEST_CASE(test_roundrobin_verfiy_polling_slave_link_status_change), TEST_CASE(test_activebackup_tx_burst), TEST_CASE(test_activebackup_rx_burst), TEST_CASE(test_activebackup_verify_promiscuous_enable_disable), TEST_CASE(test_activebackup_verify_mac_assignment), TEST_CASE(test_activebackup_verify_slave_link_status_change_failover), TEST_CASE(test_balance_xmit_policy_configuration), TEST_CASE(test_balance_l2_tx_burst), TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr), TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr), TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr), TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr), TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr), TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr), TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port), TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr), TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr), TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr), TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port), TEST_CASE(test_balance_tx_burst_slave_tx_fail), TEST_CASE(test_balance_rx_burst), TEST_CASE(test_balance_verify_promiscuous_enable_disable), TEST_CASE(test_balance_verify_mac_assignment), TEST_CASE(test_balance_verify_slave_link_status_change_behaviour), TEST_CASE(test_tlb_tx_burst), TEST_CASE(test_tlb_rx_burst), TEST_CASE(test_tlb_verify_mac_assignment), TEST_CASE(test_tlb_verify_promiscuous_enable_disable), TEST_CASE(test_tlb_verify_slave_link_status_change_failover), TEST_CASE(test_alb_change_mac_in_reply_sent), TEST_CASE(test_alb_reply_from_client), TEST_CASE(test_alb_receive_vlan_reply), TEST_CASE(test_alb_ipv4_tx), TEST_CASE(test_broadcast_tx_burst), TEST_CASE(test_broadcast_tx_burst_slave_tx_fail), TEST_CASE(test_broadcast_rx_burst), TEST_CASE(test_broadcast_verify_promiscuous_enable_disable), TEST_CASE(test_broadcast_verify_mac_assignment), TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour), TEST_CASE(test_reconfigure_bonded_device), TEST_CASE(test_close_bonded_device), { NULL, NULL, NULL, NULL, NULL } /**< NULL terminate unit test array */ } }; static int test_link_bonding(void) { return unit_test_suite_runner(&link_bonding_test_suite); } static struct test_command link_bonding_cmd = { .command = "link_bonding_autotest", .callback = test_link_bonding, }; REGISTER_TEST_COMMAND(link_bonding_cmd); ================================================ FILE: app/test/test_link_bonding_mode4.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "packet_burst_generator.h" #include "test.h" #define SLAVE_COUNT (4) #define RX_RING_SIZE 128 #define TX_RING_SIZE 512 #define MBUF_CACHE_SIZE (250) #define BURST_SIZE (32) #define TEST_RX_DESC_MAX (2048) #define TEST_TX_DESC_MAX (2048) #define MAX_PKT_BURST (32) #define DEF_PKT_BURST (16) #define BONDED_DEV_NAME ("unit_test_mode4_bond_dev") #define SLAVE_DEV_NAME_FMT ("unit_test_mode4_slave_%d") #define SLAVE_RX_QUEUE_FMT ("unit_test_mode4_slave_%d_rx") #define SLAVE_TX_QUEUE_FMT ("unit_test_mode4_slave_%d_tx") #define INVALID_SOCKET_ID (-1) #define INVALID_PORT_ID (0xFF) #define INVALID_BONDING_MODE (-1) static const struct ether_addr slave_mac_default = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; static const struct ether_addr parnter_mac_default = { { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 } }; static const struct ether_addr parnter_system = { { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 } }; static const struct ether_addr slow_protocol_mac_addr = { { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 } }; struct slave_conf { struct rte_ring *rx_queue; struct rte_ring *tx_queue; uint8_t port_id; uint8_t bonded : 1; uint8_t lacp_parnter_state; }; struct ether_vlan_hdr { struct ether_hdr pkt_eth_hdr; struct vlan_hdr vlan_hdr; }; struct link_bonding_unittest_params { uint8_t bonded_port_id; struct slave_conf slave_ports[SLAVE_COUNT]; struct rte_mempool *mbuf_pool; }; #define TEST_DEFAULT_SLAVE_COUNT RTE_DIM(test_params.slave_ports) #define TEST_RX_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT #define TEST_TX_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT #define TEST_MARKER_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT #define TEST_EXPIRED_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT #define TEST_PROMISC_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT static struct link_bonding_unittest_params test_params = { .bonded_port_id = INVALID_PORT_ID, .slave_ports = { [0 ... SLAVE_COUNT - 1] = { .port_id = INVALID_PORT_ID} }, .mbuf_pool = NULL, }; static struct rte_eth_conf default_pmd_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .lpbk_mode = 0, }; #define FOR_EACH(_i, _item, _array, _size) \ for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++) /* Macro for iterating over every port that can be used as a slave * in this test. * _i variable used as an index in test_params->slave_ports * _slave pointer to &test_params->slave_ports[_idx] */ #define FOR_EACH_PORT(_i, _port) \ FOR_EACH(_i, _port, test_params.slave_ports, \ RTE_DIM(test_params.slave_ports)) /* Macro for iterating over every port that can be used as a slave * in this test and satisfy given condition. * * _i variable used as an index in test_params->slave_ports * _slave pointer to &test_params->slave_ports[_idx] * _condition condition that need to be checked */ #define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \ if (!!(_condition)) /* Macro for iterating over every port that is currently a slave of a bonded * device. * _i variable used as an index in test_params->slave_ports * _slave pointer to &test_params->slave_ports[_idx] * */ #define FOR_EACH_SLAVE(_i, _slave) \ FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0) /* * Returns packets from slaves TX queue. * slave slave port * buffer for packets * size size of buffer * return number of packets or negative error number */ static int slave_get_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) { return rte_ring_dequeue_burst(slave->tx_queue, (void **)buf, size); } /* * Injects given packets into slaves RX queue. * slave slave port * buffer for packets * size number of packets to be injected * return number of queued packets or negative error number */ static int slave_put_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size) { return rte_ring_enqueue_burst(slave->rx_queue, (void **)buf, size); } static uint16_t bond_rx(struct rte_mbuf **buf, uint16_t size) { return rte_eth_rx_burst(test_params.bonded_port_id, 0, buf, size); } static uint16_t bond_tx(struct rte_mbuf **buf, uint16_t size) { return rte_eth_tx_burst(test_params.bonded_port_id, 0, buf, size); } static void free_pkts(struct rte_mbuf **pkts, uint16_t count) { uint16_t i; for (i = 0; i < count; i++) { if (pkts[i] != NULL) rte_pktmbuf_free(pkts[i]); } } static int configure_ethdev(uint8_t port_id, uint8_t start) { TEST_ASSERT(rte_eth_dev_configure(port_id, 1, 1, &default_pmd_conf) == 0, "Failed to configure device %u", port_id); TEST_ASSERT(rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE, rte_eth_dev_socket_id(port_id), NULL, test_params.mbuf_pool) == 0, "Failed to setup rx queue."); TEST_ASSERT(rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE, rte_eth_dev_socket_id(port_id), NULL) == 0, "Failed to setup tx queue."); if (start) { TEST_ASSERT(rte_eth_dev_start(port_id) == 0, "Failed to start device (%d).", port_id); } return 0; } static int add_slave(struct slave_conf *slave, uint8_t start) { struct ether_addr addr, addr_check; /* Some sanity check */ RTE_VERIFY(test_params.slave_ports <= slave && slave - test_params.slave_ports < (int)RTE_DIM(test_params.slave_ports)); RTE_VERIFY(slave->bonded == 0); RTE_VERIFY(slave->port_id != INVALID_PORT_ID); ether_addr_copy(&slave_mac_default, &addr); addr.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id; rte_eth_dev_mac_addr_remove(slave->port_id, &addr); TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave->port_id, &addr, 0), "Failed to set slave MAC address"); TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bonded_port_id, slave->port_id), "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)", (uint8_t)(slave - test_params.slave_ports), slave->port_id, test_params.bonded_port_id); slave->bonded = 1; if (start) { TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave->port_id), "Failed to start slave %u", slave->port_id); } rte_eth_macaddr_get(slave->port_id, &addr_check); TEST_ASSERT_EQUAL(is_same_ether_addr(&addr, &addr_check), 1, "Slave MAC address is not as expected"); RTE_VERIFY(slave->lacp_parnter_state == 0); return 0; } static int remove_slave(struct slave_conf *slave) { ptrdiff_t slave_idx = slave - test_params.slave_ports; RTE_VERIFY(test_params.slave_ports <= slave && slave_idx < (ptrdiff_t)RTE_DIM(test_params.slave_ports)); RTE_VERIFY(slave->bonded == 1); RTE_VERIFY(slave->port_id != INVALID_PORT_ID); TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, "Slave %u tx queue not empty while removing from bonding.", slave->port_id); TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0, "Slave %u tx queue not empty while removing from bonding.", slave->port_id); TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params.bonded_port_id, slave->port_id), 0, "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)", (uint8_t)slave_idx, slave->port_id, test_params.bonded_port_id); slave->bonded = 0; slave->lacp_parnter_state = 0; return 0; } static int initialize_bonded_device_with_slaves(uint8_t slave_count, uint8_t start) { uint8_t i; RTE_VERIFY(test_params.bonded_port_id != INVALID_PORT_ID); for (i = 0; i < slave_count; i++) { TEST_ASSERT_SUCCESS(add_slave(&test_params.slave_ports[i], 1), "Failed to add port %u to bonded device.\n", test_params.slave_ports[i].port_id); } /* Reset mode 4 configuration */ rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL); rte_eth_promiscuous_disable(test_params.bonded_port_id); if (start) TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id), "Failed to start bonded device"); return TEST_SUCCESS; } static int remove_slaves_and_stop_bonded_device(void) { struct slave_conf *slave; int retval; uint8_t slaves[RTE_MAX_ETHPORTS]; uint8_t i; rte_eth_dev_stop(test_params.bonded_port_id); FOR_EACH_SLAVE(i, slave) remove_slave(slave); retval = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves, RTE_DIM(slaves)); TEST_ASSERT_EQUAL(retval, 0, "Expected bonded device %u have 0 slaves but returned %d.", test_params.bonded_port_id, retval); FOR_EACH_PORT(i, slave) { rte_eth_dev_stop(slave->port_id); TEST_ASSERT(slave->bonded == 0, "Port id=%u is still marked as enslaved.", slave->port_id); } return TEST_SUCCESS; } static int test_setup(void) { int retval, nb_mbuf_per_pool; char name[RTE_ETH_NAME_MAX_LEN]; struct slave_conf *port; const uint8_t socket_id = rte_socket_id(); uint8_t i; if (test_params.mbuf_pool == NULL) { nb_mbuf_per_pool = TEST_RX_DESC_MAX + DEF_PKT_BURST + TEST_TX_DESC_MAX + MAX_PKT_BURST; test_params.mbuf_pool = rte_pktmbuf_pool_create("TEST_MODE4", nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket_id); TEST_ASSERT(test_params.mbuf_pool != NULL, "rte_mempool_create failed\n"); } /* Create / initialize ring eth devs. */ FOR_EACH_PORT(i, port) { port = &test_params.slave_ports[i]; if (port->rx_queue == NULL) { retval = snprintf(name, RTE_DIM(name), SLAVE_RX_QUEUE_FMT, i); TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); port->rx_queue = rte_ring_create(name, RX_RING_SIZE, socket_id, 0); TEST_ASSERT(port->rx_queue != NULL, "Failed to allocate rx ring '%s': %s", name, rte_strerror(rte_errno)); } if (port->tx_queue == NULL) { retval = snprintf(name, RTE_DIM(name), SLAVE_TX_QUEUE_FMT, i); TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long"); port->tx_queue = rte_ring_create(name, TX_RING_SIZE, socket_id, 0); TEST_ASSERT_NOT_NULL(port->tx_queue, "Failed to allocate tx ring '%s': %s", name, rte_strerror(rte_errno)); } if (port->port_id == INVALID_PORT_ID) { retval = snprintf(name, RTE_DIM(name), SLAVE_DEV_NAME_FMT, i); TEST_ASSERT(retval < (int)RTE_DIM(name) - 1, "Name too long"); retval = rte_eth_from_rings(name, &port->rx_queue, 1, &port->tx_queue, 1, socket_id); TEST_ASSERT(retval >= 0, "Failed to create ring ethdev '%s'\n", name); port->port_id = rte_eth_dev_count() - 1; } retval = configure_ethdev(port->port_id, 1); TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n", name); } if (test_params.bonded_port_id == INVALID_PORT_ID) { retval = rte_eth_bond_create(BONDED_DEV_NAME, BONDING_MODE_8023AD, socket_id); TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s", BONDED_DEV_NAME); test_params.bonded_port_id = retval; TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bonded_port_id, 0), "Failed to configure bonded ethdev %s", BONDED_DEV_NAME); } else if (rte_eth_bond_mode_get(test_params.bonded_port_id) != BONDING_MODE_8023AD) { TEST_ASSERT(rte_eth_bond_mode_set(test_params.bonded_port_id, BONDING_MODE_8023AD) == 0, "Failed to set ethdev %d to mode %d", test_params.bonded_port_id, BONDING_MODE_8023AD); } return 0; } static int testsuite_teardown(void) { struct slave_conf *port; uint8_t i; /* Only stop ports. * Any cleanup/reset state is done when particular test is * started. */ rte_eth_dev_stop(test_params.bonded_port_id); FOR_EACH_PORT(i, port) rte_eth_dev_stop(port->port_id); return 0; } /* * Check if given LACP packet. If it is, make make replay packet to force * COLLECTING state. * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow * frame but not LACP */ static int make_lacp_reply(struct slave_conf *slave, struct rte_mbuf *pkt) { struct ether_hdr *hdr; struct slow_protocol_frame *slow_hdr; struct lacpdu *lacp; /* look for LACP */ hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); if (hdr->ether_type != rte_cpu_to_be_16(ETHER_TYPE_SLOW)) return 1; slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); /* ignore packets of other types */ if (slow_hdr->slow_protocol.subtype != SLOW_SUBTYPE_LACP) return 2; slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *); /* Change source address to partner address */ ether_addr_copy(&parnter_mac_default, &slow_hdr->eth_hdr.s_addr); slow_hdr->eth_hdr.s_addr.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id; lacp = (struct lacpdu *) &slow_hdr->slow_protocol; /* Save last received state */ slave->lacp_parnter_state = lacp->actor.state; /* Change it into LACP replay by matching parameters. */ memcpy(&lacp->partner.port_params, &lacp->actor.port_params, sizeof(struct port_params)); lacp->partner.state = lacp->actor.state; ether_addr_copy(&parnter_system, &lacp->actor.port_params.system); lacp->actor.state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION | STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING; return 0; } /* * Reads packets from given slave, search for LACP packet and reply them. * * Receives burst of packets from slave. Looks for LACP packet. Drops * all other packets. Prepares response LACP and sends it back. * * return number of LACP received and replied, -1 on error. */ static int bond_handshake_reply(struct slave_conf *slave) { int retval; struct rte_mbuf *rx_buf[MAX_PKT_BURST]; struct rte_mbuf *lacp_tx_buf[MAX_PKT_BURST]; uint16_t lacp_tx_buf_cnt = 0, i; retval = slave_get_pkts(slave, rx_buf, RTE_DIM(rx_buf)); TEST_ASSERT(retval >= 0, "Getting slave %u packets failed.", slave->port_id); for (i = 0; i < (uint16_t)retval; i++) { if (make_lacp_reply(slave, rx_buf[i]) == 0) { /* reply with actor's LACP */ lacp_tx_buf[lacp_tx_buf_cnt++] = rx_buf[i]; } else rte_pktmbuf_free(rx_buf[i]); } if (lacp_tx_buf_cnt == 0) return 0; retval = slave_put_pkts(slave, lacp_tx_buf, lacp_tx_buf_cnt); if (retval <= lacp_tx_buf_cnt) { /* retval might be negative */ for (i = RTE_MAX(0, retval); retval < lacp_tx_buf_cnt; retval++) rte_pktmbuf_free(lacp_tx_buf[i]); } TEST_ASSERT_EQUAL(retval, lacp_tx_buf_cnt, "Failed to equeue lacp packets into slave %u tx queue.", slave->port_id); return lacp_tx_buf_cnt; } /* * Function check if given slave tx queue contains packets that make mode 4 * handshake complete. It will drain slave queue. * return 0 if handshake not completed, 1 if handshake was complete, */ static int bond_handshake_done(struct slave_conf *slave) { const uint8_t expected_state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION | STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING; return slave->lacp_parnter_state == expected_state; } static unsigned bond_get_update_timeout_ms(void) { struct rte_eth_bond_8023ad_conf conf; rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf); return conf.update_timeout_ms; } /* * Exchanges LACP packets with partner to achieve dynamic port configuration. * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise. */ static int bond_handshake(void) { struct slave_conf *slave; struct rte_mbuf *buf[MAX_PKT_BURST]; uint16_t nb_pkts; uint8_t all_slaves_done, i, j; uint8_t status[RTE_DIM(test_params.slave_ports)] = { 0 }; const unsigned delay = bond_get_update_timeout_ms(); /* Exchange LACP frames */ all_slaves_done = 0; for (i = 0; i < 30 && all_slaves_done == 0; ++i) { rte_delay_ms(delay); all_slaves_done = 1; FOR_EACH_SLAVE(j, slave) { /* If response already send, skip slave */ if (status[j] != 0) continue; if (bond_handshake_reply(slave) < 0) { all_slaves_done = 0; break; } status[j] = bond_handshake_done(slave); if (status[j] == 0) all_slaves_done = 0; } nb_pkts = bond_tx(NULL, 0); TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly"); nb_pkts = bond_rx(buf, RTE_DIM(buf)); free_pkts(buf, nb_pkts); TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly"); } /* If response didn't send - report failure */ TEST_ASSERT_EQUAL(all_slaves_done, 1, "Bond handshake failed\n"); /* If flags doesn't match - report failure */ return all_slaves_done = 1 ? TEST_SUCCESS : TEST_FAILED; } #define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports) static int test_mode4_lacp(void) { int retval; retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 1); TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); /* Test LACP handshake function */ retval = bond_handshake(); TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); retval = remove_slaves_and_stop_bonded_device(); TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); return TEST_SUCCESS; } static int generate_packets(struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t count, struct rte_mbuf **buf) { uint16_t pktlen = PACKET_BURST_GEN_PKT_LEN; uint8_t vlan_enable = 0; uint16_t vlan_id = 0; uint8_t ip4_type = 1; /* 0 - ipv6 */ uint16_t src_port = 10, dst_port = 20; uint32_t ip_src[4] = { [0 ... 2] = 0xDEADBEEF, [3] = IPv4(192, 168, 0, 1) }; uint32_t ip_dst[4] = { [0 ... 2] = 0xFEEDFACE, [3] = IPv4(192, 168, 0, 2) }; struct ether_hdr pkt_eth_hdr; struct udp_hdr pkt_udp_hdr; union { struct ipv4_hdr v4; struct ipv6_hdr v6; } pkt_ip_hdr; int retval; initialize_eth_header(&pkt_eth_hdr, src_mac, dst_mac, ip4_type, vlan_enable, vlan_id); if (ip4_type) initialize_ipv4_header(&pkt_ip_hdr.v4, ip_src[3], ip_dst[3], pktlen); else initialize_ipv6_header(&pkt_ip_hdr.v6, (uint8_t *)ip_src, (uint8_t *)&ip_dst, pktlen); initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 16); retval = generate_packet_burst(test_params.mbuf_pool, buf, &pkt_eth_hdr, vlan_enable, &pkt_ip_hdr, 1, &pkt_udp_hdr, count, pktlen, 1); if (retval > 0 && retval != count) free_pkts(&buf[count - retval], retval); TEST_ASSERT_EQUAL(retval, count, "Failed to generate %u packets", count); return count; } static int generate_and_put_packets(struct slave_conf *slave, struct ether_addr *src_mac, struct ether_addr *dst_mac, uint16_t count) { struct rte_mbuf *pkts[MAX_PKT_BURST]; int retval; retval = generate_packets(src_mac, dst_mac, count, pkts); if (retval != (int)count) return retval; retval = slave_put_pkts(slave, pkts, count); if (retval > 0 && retval != count) free_pkts(&pkts[retval], count - retval); TEST_ASSERT_EQUAL(retval, count, "Failed to enqueue packets into slave %u RX queue", slave->port_id); return TEST_SUCCESS; } static int test_mode4_rx(void) { struct slave_conf *slave; uint16_t i, j; uint16_t expected_pkts_cnt; struct rte_mbuf *pkts[MAX_PKT_BURST]; int retval; unsigned delay; struct ether_hdr *hdr; struct ether_addr src_mac = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; struct ether_addr dst_mac; struct ether_addr bonded_mac; retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT, 1); TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); retval = bond_handshake(); TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); ether_addr_copy(&bonded_mac, &dst_mac); /* Assert that dst address is not bonding address */ dst_mac.addr_bytes[0]++; /* First try with promiscuous mode enabled. * Add 2 packets to each slave. First with bonding MAC address, second with * different. Check if we received all of them. */ rte_eth_promiscuous_enable(test_params.bonded_port_id); expected_pkts_cnt = 0; FOR_EACH_SLAVE(i, slave) { retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", slave->port_id); retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", slave->port_id); /* Expect 2 packets per slave */ expected_pkts_cnt += 2; } retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, RTE_DIM(pkts)); if (retval == expected_pkts_cnt) { int cnt[2] = { 0, 0 }; for (i = 0; i < expected_pkts_cnt; i++) { hdr = rte_pktmbuf_mtod(pkts[i], struct ether_hdr *); cnt[is_same_ether_addr(&hdr->d_addr, &bonded_mac)]++; } free_pkts(pkts, expected_pkts_cnt); /* For division by 2 expected_pkts_cnt must be even */ RTE_VERIFY((expected_pkts_cnt & 1) == 0); TEST_ASSERT(cnt[0] == expected_pkts_cnt / 2 && cnt[1] == expected_pkts_cnt / 2, "Expected %u packets with the same MAC and %u with different but " "got %u with the same and %u with diffrent MAC", expected_pkts_cnt / 2, expected_pkts_cnt / 2, cnt[1], cnt[0]); } else if (retval > 0) free_pkts(pkts, retval); TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, "Expected %u packets but received only %d", expected_pkts_cnt, retval); /* Now, disable promiscuous mode. When promiscuous mode is disabled we * expect to receive only packets that are directed to bonding port. */ rte_eth_promiscuous_disable(test_params.bonded_port_id); expected_pkts_cnt = 0; FOR_EACH_SLAVE(i, slave) { retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", slave->port_id); retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u", slave->port_id); /* Expect only one packet per slave */ expected_pkts_cnt += 1; } retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, RTE_DIM(pkts)); if (retval == expected_pkts_cnt) { int eq_cnt = 0; for (i = 0; i < expected_pkts_cnt; i++) { hdr = rte_pktmbuf_mtod(pkts[i], struct ether_hdr *); eq_cnt += is_same_ether_addr(&hdr->d_addr, &bonded_mac); } free_pkts(pkts, expected_pkts_cnt); TEST_ASSERT_EQUAL(eq_cnt, expected_pkts_cnt, "Packet address mismatch"); } else if (retval > 0) free_pkts(pkts, retval); TEST_ASSERT_EQUAL(retval, expected_pkts_cnt, "Expected %u packets but received only %d", expected_pkts_cnt, retval); /* Link down test: simulate link down for first slave. */ delay = bond_get_update_timeout_ms(); uint8_t slave_down_id = INVALID_PORT_ID; /* Find first slave and make link down on it*/ FOR_EACH_SLAVE(i, slave) { rte_eth_dev_set_link_down(slave->port_id); slave_down_id = slave->port_id; break; } RTE_VERIFY(slave_down_id != INVALID_PORT_ID); /* Give some time to rearrange bonding */ for (i = 0; i < 3; i++) { rte_delay_ms(delay); bond_handshake(); } TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); /* Put packet to each slave */ FOR_EACH_SLAVE(i, slave) { void *pkt = NULL; dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id; retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); src_mac.addr_bytes[ETHER_ADDR_LEN - 1] = slave->port_id; retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1); TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst."); retval = bond_rx(pkts, RTE_DIM(pkts)); /* Clean anything */ if (retval > 0) free_pkts(pkts, retval); while (rte_ring_dequeue(slave->rx_queue, (void **)&pkt) == 0) rte_pktmbuf_free(pkt); if (slave_down_id == slave->port_id) TEST_ASSERT_EQUAL(retval, 0, "Packets received unexpectedly."); else TEST_ASSERT_NOT_EQUAL(retval, 0, "Expected to receive some packets on slave %u.", slave->port_id); rte_eth_dev_start(slave->port_id); for (j = 0; j < 5; j++) { TEST_ASSERT(bond_handshake_reply(slave) >= 0, "Handshake after link up"); if (bond_handshake_done(slave) == 1) break; } TEST_ASSERT(j < 5, "Failed to agregate slave after link up"); } remove_slaves_and_stop_bonded_device(); return TEST_SUCCESS; } static int test_mode4_tx_burst(void) { struct slave_conf *slave; uint16_t i, j; uint16_t exp_pkts_cnt, pkts_cnt = 0; struct rte_mbuf *pkts[MAX_PKT_BURST]; int retval; unsigned delay; struct ether_addr dst_mac = { { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }; struct ether_addr bonded_mac; retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1); TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); retval = bond_handshake(); TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac); /* Prepare burst */ for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = pkts_cnt; retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); if (retval != 1) free_pkts(pkts, pkts_cnt); TEST_ASSERT_EQUAL(retval, 1, "Failed to generate packet %u", pkts_cnt); } exp_pkts_cnt = pkts_cnt; /* Transmit packets on bonded device */ retval = bond_tx(pkts, pkts_cnt); if (retval > 0 && retval < pkts_cnt) free_pkts(&pkts[retval], pkts_cnt - retval); TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); /* Check if packets were transmitted properly. Every slave should have * at least one packet, and sum must match. Under normal operation * there should be no LACP nor MARKER frames. */ pkts_cnt = 0; FOR_EACH_SLAVE(i, slave) { uint16_t normal_cnt, slow_cnt; retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); normal_cnt = 0; slow_cnt = 0; for (j = 0; j < retval; j++) { if (make_lacp_reply(slave, pkts[j]) == 1) normal_cnt++; else slow_cnt++; } free_pkts(pkts, normal_cnt + slow_cnt); TEST_ASSERT_EQUAL(slow_cnt, 0, "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id, slow_cnt); TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, "slave %u did not transmitted any packets", slave->port_id); pkts_cnt += normal_cnt; } TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); /* Link down test: * simulate link down for first slave. */ delay = bond_get_update_timeout_ms(); uint8_t slave_down_id = INVALID_PORT_ID; FOR_EACH_SLAVE(i, slave) { rte_eth_dev_set_link_down(slave->port_id); slave_down_id = slave->port_id; break; } RTE_VERIFY(slave_down_id != INVALID_PORT_ID); /* Give some time to rearrange bonding. */ for (i = 0; i < 3; i++) { bond_handshake(); rte_delay_ms(delay); } TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed"); /* Prepare burst. */ for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) { dst_mac.addr_bytes[ETHER_ADDR_LEN - 1] = pkts_cnt; retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]); if (retval != 1) free_pkts(pkts, pkts_cnt); TEST_ASSERT_EQUAL(retval, 1, "Failed to generate test packet %u", pkts_cnt); } exp_pkts_cnt = pkts_cnt; /* Transmit packets on bonded device. */ retval = bond_tx(pkts, pkts_cnt); if (retval > 0 && retval < pkts_cnt) free_pkts(&pkts[retval], pkts_cnt - retval); TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed"); /* Check if packets was transmitted properly. Every slave should have * at least one packet, and sum must match. Under normal operation * there should be no LACP nor MARKER frames. */ pkts_cnt = 0; FOR_EACH_SLAVE(i, slave) { uint16_t normal_cnt, slow_cnt; retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts)); normal_cnt = 0; slow_cnt = 0; for (j = 0; j < retval; j++) { if (make_lacp_reply(slave, pkts[j]) == 1) normal_cnt++; else slow_cnt++; } free_pkts(pkts, normal_cnt + slow_cnt); if (slave_down_id == slave->port_id) { TEST_ASSERT_EQUAL(normal_cnt + slow_cnt, 0, "slave %u enexpectedly transmitted %u packets", normal_cnt + slow_cnt, slave->port_id); } else { TEST_ASSERT_EQUAL(slow_cnt, 0, "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id, slow_cnt); TEST_ASSERT_NOT_EQUAL(normal_cnt, 0, "slave %u did not transmitted any packets", slave->port_id); } pkts_cnt += normal_cnt; } TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt, "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt); return remove_slaves_and_stop_bonded_device(); } static void init_marker(struct rte_mbuf *pkt, struct slave_conf *slave) { struct marker_header *marker_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *); /* Copy multicast destination address */ ether_addr_copy(&slow_protocol_mac_addr, &marker_hdr->eth_hdr.d_addr); /* Init source address */ ether_addr_copy(&parnter_mac_default, &marker_hdr->eth_hdr.s_addr); marker_hdr->eth_hdr.s_addr.addr_bytes[ETHER_ADDR_LEN-1] = slave->port_id; marker_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW); marker_hdr->marker.subtype = SLOW_SUBTYPE_MARKER; marker_hdr->marker.version_number = 1; marker_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_INFO; marker_hdr->marker.info_length = offsetof(struct marker, reserved_90) - offsetof(struct marker, requester_port); RTE_VERIFY(marker_hdr->marker.info_length == 16); marker_hdr->marker.requester_port = slave->port_id + 1; marker_hdr->marker.tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION; marker_hdr->marker.terminator_length = 0; } static int test_mode4_marker(void) { struct slave_conf *slave; struct rte_mbuf *pkts[MAX_PKT_BURST]; struct rte_mbuf *marker_pkt; struct marker_header *marker_hdr; unsigned delay; int retval; uint16_t nb_pkts; uint8_t i, j; const uint16_t ethtype_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW); retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT, 1); TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device"); /* Test LACP handshake function */ retval = bond_handshake(); TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); delay = bond_get_update_timeout_ms(); FOR_EACH_SLAVE(i, slave) { marker_pkt = rte_pktmbuf_alloc(test_params.mbuf_pool); TEST_ASSERT_NOT_NULL(marker_pkt, "Failed to allocate marker packet"); init_marker(marker_pkt, slave); retval = slave_put_pkts(slave, &marker_pkt, 1); if (retval != 1) rte_pktmbuf_free(marker_pkt); TEST_ASSERT_EQUAL(retval, 1, "Failed to send marker packet to slave %u", slave->port_id); for (j = 0; j < 20; ++j) { rte_delay_ms(delay); retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts, RTE_DIM(pkts)); if (retval > 0) free_pkts(pkts, retval); TEST_ASSERT_EQUAL(retval, 0, "Received packets unexpectedly"); retval = rte_eth_tx_burst(test_params.bonded_port_id, 0, NULL, 0); TEST_ASSERT_EQUAL(retval, 0, "Requested TX of 0 packets but %d transmitted", retval); /* Check if LACP packet was send by state machines First and only packet must be a maker response */ retval = slave_get_pkts(slave, pkts, MAX_PKT_BURST); if (retval == 0) continue; if (retval > 1) free_pkts(pkts, retval); TEST_ASSERT_EQUAL(retval, 1, "failed to get slave packets"); nb_pkts = retval; marker_hdr = rte_pktmbuf_mtod(pkts[0], struct marker_header *); /* Check if it's slow packet*/ if (marker_hdr->eth_hdr.ether_type != ethtype_slow_be) retval = -1; /* Check if it's marker packet */ else if (marker_hdr->marker.subtype != SLOW_SUBTYPE_MARKER) retval = -2; else if (marker_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_RESP) retval = -3; free_pkts(pkts, nb_pkts); TEST_ASSERT_NOT_EQUAL(retval, -1, "Unexpected protocol type"); TEST_ASSERT_NOT_EQUAL(retval, -2, "Unexpected sub protocol type"); TEST_ASSERT_NOT_EQUAL(retval, -3, "Unexpected marker type"); break; } TEST_ASSERT(j < 20, "Marker response not found"); } retval = remove_slaves_and_stop_bonded_device(); TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); return TEST_SUCCESS; } static int test_mode4_expired(void) { struct slave_conf *slave, *exp_slave = NULL; struct rte_mbuf *pkts[MAX_PKT_BURST]; int retval; uint32_t old_delay; uint8_t i; uint16_t j; struct rte_eth_bond_8023ad_conf conf; retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT, 1); /* Set custom timeouts to make test last shorter. */ rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf); conf.fast_periodic_ms = 100; conf.slow_periodic_ms = 600; conf.short_timeout_ms = 300; conf.long_timeout_ms = 900; conf.aggregate_wait_timeout_ms = 200; conf.tx_period_ms = 100; old_delay = conf.update_timeout_ms; conf.update_timeout_ms = 10; rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf); /* Wait for new settings to be applied. */ for (i = 0; i < old_delay/conf.update_timeout_ms * 2; i++) { FOR_EACH_SLAVE(j, slave) bond_handshake_reply(slave); rte_delay_ms(conf.update_timeout_ms); } retval = bond_handshake(); TEST_ASSERT_SUCCESS(retval, "Initial handshake failed"); /* Find first slave */ FOR_EACH_SLAVE(i, slave) { exp_slave = slave; break; } RTE_VERIFY(exp_slave != NULL); /* When one of partners do not send or respond to LACP frame in * conf.long_timeout_ms time, internal state machines should detect this * and transit to expired state. */ for (j = 0; j < conf.long_timeout_ms/conf.update_timeout_ms + 2; j++) { rte_delay_ms(conf.update_timeout_ms); retval = bond_tx(NULL, 0); TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets", retval); FOR_EACH_SLAVE(i, slave) { retval = bond_handshake_reply(slave); TEST_ASSERT(retval >= 0, "Handshake failed"); /* Remove replay for slave that supose to be expired. */ if (slave == exp_slave) { while (rte_ring_count(slave->rx_queue) > 0) { void *pkt = NULL; rte_ring_dequeue(slave->rx_queue, &pkt); rte_pktmbuf_free(pkt); } } } retval = bond_rx(pkts, RTE_DIM(pkts)); if (retval > 0) free_pkts(pkts, retval); TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets", retval); } /* After test only expected slave should be in EXPIRED state */ FOR_EACH_SLAVE(i, slave) { if (slave == exp_slave) TEST_ASSERT(slave->lacp_parnter_state & STATE_EXPIRED, "Slave %u should be in expired.", slave->port_id); else TEST_ASSERT_EQUAL(bond_handshake_done(slave), 1, "Slave %u should be operational.", slave->port_id); } retval = remove_slaves_and_stop_bonded_device(); TEST_ASSERT_SUCCESS(retval, "Test cleanup failed."); return TEST_SUCCESS; } static int check_environment(void) { struct slave_conf *port; uint8_t i, env_state; uint8_t slaves[RTE_DIM(test_params.slave_ports)]; int slaves_count; env_state = 0; FOR_EACH_PORT(i, port) { if (rte_ring_count(port->rx_queue) != 0) env_state |= 0x01; if (rte_ring_count(port->tx_queue) != 0) env_state |= 0x02; if (port->bonded != 0) env_state |= 0x04; if (port->lacp_parnter_state != 0) env_state |= 0x08; if (env_state != 0) break; } slaves_count = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves, RTE_DIM(slaves)); if (slaves_count != 0) env_state |= 0x10; TEST_ASSERT_EQUAL(env_state, 0, "Environment not clean (port %u):%s%s%s%s%s", port->port_id, env_state & 0x01 ? " slave rx queue not clean" : "", env_state & 0x02 ? " slave tx queue not clean" : "", env_state & 0x04 ? " port marked as enslaved" : "", env_state & 0x80 ? " slave state is not reset" : "", env_state & 0x10 ? " slave count not equal 0" : "."); return TEST_SUCCESS; } static int test_mode4_executor(int (*test_func)(void)) { struct slave_conf *port; int test_result; uint8_t i; void *pkt; /* Check if environment is clean. Fail to launch a test if there was * a critical error before that prevented to reset environment. */ TEST_ASSERT_SUCCESS(check_environment(), "Refusing to launch test in dirty environment."); RTE_VERIFY(test_func != NULL); test_result = (*test_func)(); /* If test succeed check if environment wast left in good condition. */ if (test_result == TEST_SUCCESS) test_result = check_environment(); /* Reset environment in case test failed to do that. */ if (test_result != TEST_SUCCESS) { TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(), "Failed to stop bonded device"); FOR_EACH_PORT(i, port) { while (rte_ring_count(port->rx_queue) != 0) { if (rte_ring_dequeue(port->rx_queue, &pkt) == 0) rte_pktmbuf_free(pkt); } while (rte_ring_count(port->tx_queue) != 0) { if (rte_ring_dequeue(port->tx_queue, &pkt) == 0) rte_pktmbuf_free(pkt); } } } return test_result; } static int test_mode4_lacp_wrapper(void) { return test_mode4_executor(&test_mode4_lacp); } static int test_mode4_marker_wrapper(void) { return test_mode4_executor(&test_mode4_marker); } static int test_mode4_rx_wrapper(void) { return test_mode4_executor(&test_mode4_rx); } static int test_mode4_tx_burst_wrapper(void) { return test_mode4_executor(&test_mode4_tx_burst); } static int test_mode4_expired_wrapper(void) { return test_mode4_executor(&test_mode4_expired); } static struct unit_test_suite link_bonding_mode4_test_suite = { .suite_name = "Link Bonding mode 4 Unit Test Suite", .setup = test_setup, .teardown = testsuite_teardown, .unit_test_cases = { TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper), TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper), TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper), TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper), TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper), { NULL, NULL, NULL, NULL, NULL } /**< NULL terminate unit test array */ } }; static int test_link_bonding_mode4(void) { return unit_test_suite_runner(&link_bonding_mode4_test_suite); } static struct test_command link_bonding_cmd = { .command = "link_bonding_mode4_autotest", .callback = test_link_bonding_mode4, }; REGISTER_TEST_COMMAND(link_bonding_cmd); ================================================ FILE: app/test/test_logs.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #define RTE_LOGTYPE_TESTAPP1 RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_TESTAPP2 RTE_LOGTYPE_USER2 /* * Logs * ==== * * - Enable log types. * - Set log level. * - Send logs with different types and levels, some should not be displayed. */ static int test_logs(void) { /* enable these logs type */ rte_set_log_type(RTE_LOGTYPE_TESTAPP1, 1); rte_set_log_type(RTE_LOGTYPE_TESTAPP2, 1); /* log in debug level */ rte_set_log_level(RTE_LOG_DEBUG); RTE_LOG(DEBUG, TESTAPP1, "this is a debug level message\n"); RTE_LOG(INFO, TESTAPP1, "this is a info level message\n"); RTE_LOG(WARNING, TESTAPP1, "this is a warning level message\n"); /* log in info level */ rte_set_log_level(RTE_LOG_INFO); RTE_LOG(DEBUG, TESTAPP2, "debug level message (not displayed)\n"); RTE_LOG(INFO, TESTAPP2, "this is a info level message\n"); RTE_LOG(WARNING, TESTAPP2, "this is a warning level message\n"); /* disable one log type */ rte_set_log_type(RTE_LOGTYPE_TESTAPP2, 0); /* log in debug level */ rte_set_log_level(RTE_LOG_DEBUG); RTE_LOG(DEBUG, TESTAPP1, "this is a debug level message\n"); RTE_LOG(DEBUG, TESTAPP2, "debug level message (not displayed)\n"); rte_log_dump_history(stdout); return 0; } static struct test_command logs_cmd = { .command = "logs_autotest", .callback = test_logs, }; REGISTER_TEST_COMMAND(logs_cmd); ================================================ FILE: app/test/test_lpm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #include "rte_lpm.h" #include "test_lpm_routes.h" #define TEST_LPM_ASSERT(cond) do { \ if (!(cond)) { \ printf("Error at line %d: \n", __LINE__); \ return -1; \ } \ } while(0) typedef int32_t (* rte_lpm_test)(void); static int32_t test0(void); static int32_t test1(void); static int32_t test2(void); static int32_t test3(void); static int32_t test4(void); static int32_t test5(void); static int32_t test6(void); static int32_t test7(void); static int32_t test8(void); static int32_t test9(void); static int32_t test10(void); static int32_t test11(void); static int32_t test12(void); static int32_t test13(void); static int32_t test14(void); static int32_t test15(void); static int32_t test16(void); static int32_t test17(void); static int32_t perf_test(void); rte_lpm_test tests[] = { /* Test Cases */ test0, test1, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11, test12, test13, test14, test15, test16, test17, perf_test, }; #define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0])) #define MAX_DEPTH 32 #define MAX_RULES 256 #define PASS 0 /* * Check that rte_lpm_create fails gracefully for incorrect user input * arguments */ int32_t test0(void) { struct rte_lpm *lpm = NULL; /* rte_lpm_create: lpm name == NULL */ lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm == NULL); /* rte_lpm_create: max_rules = 0 */ /* Note: __func__ inserts the function name, in this case "test0". */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 0, 0); TEST_LPM_ASSERT(lpm == NULL); /* socket_id < -1 is invalid */ lpm = rte_lpm_create(__func__, -2, MAX_RULES, 0); TEST_LPM_ASSERT(lpm == NULL); return PASS; } /* * Create lpm table then delete lpm table 100 times * Use a slightly different rules size each time * */ int32_t test1(void) { struct rte_lpm *lpm = NULL; int32_t i; /* rte_lpm_free: Free NULL */ for (i = 0; i < 100; i++) { lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES - i, 0); TEST_LPM_ASSERT(lpm != NULL); rte_lpm_free(lpm); } /* Can not test free so return success */ return PASS; } /* * Call rte_lpm_free for NULL pointer user input. Note: free has no return and * therefore it is impossible to check for failure but this test is added to * increase function coverage metrics and to validate that freeing null does * not crash. */ int32_t test2(void) { struct rte_lpm *lpm = NULL; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP); TEST_LPM_ASSERT(lpm != NULL); rte_lpm_free(lpm); rte_lpm_free(NULL); return PASS; } /* * Check that rte_lpm_add fails gracefully for incorrect user input arguments */ int32_t test3(void) { struct rte_lpm *lpm = NULL; uint32_t ip = IPv4(0, 0, 0, 0); uint8_t depth = 24, next_hop = 100; int32_t status = 0; /* rte_lpm_add: lpm == NULL */ status = rte_lpm_add(NULL, ip, depth, next_hop); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm_add: depth < 1 */ status = rte_lpm_add(lpm, ip, 0, next_hop); TEST_LPM_ASSERT(status < 0); /* rte_lpm_add: depth > MAX_DEPTH */ status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop); TEST_LPM_ASSERT(status < 0); rte_lpm_free(lpm); return PASS; } /* * Check that rte_lpm_delete fails gracefully for incorrect user input * arguments */ int32_t test4(void) { struct rte_lpm *lpm = NULL; uint32_t ip = IPv4(0, 0, 0, 0); uint8_t depth = 24; int32_t status = 0; /* rte_lpm_delete: lpm == NULL */ status = rte_lpm_delete(NULL, ip, depth); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm_delete: depth < 1 */ status = rte_lpm_delete(lpm, ip, 0); TEST_LPM_ASSERT(status < 0); /* rte_lpm_delete: depth > MAX_DEPTH */ status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1)); TEST_LPM_ASSERT(status < 0); rte_lpm_free(lpm); return PASS; } /* * Check that rte_lpm_lookup fails gracefully for incorrect user input * arguments */ int32_t test5(void) { #if defined(RTE_LIBRTE_LPM_DEBUG) struct rte_lpm *lpm = NULL; uint32_t ip = IPv4(0, 0, 0, 0); uint8_t next_hop_return = 0; int32_t status = 0; /* rte_lpm_lookup: lpm == NULL */ status = rte_lpm_lookup(NULL, ip, &next_hop_return); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm_lookup: depth < 1 */ status = rte_lpm_lookup(lpm, ip, NULL); TEST_LPM_ASSERT(status < 0); rte_lpm_free(lpm); #endif return PASS; } /* * Call add, lookup and delete for a single rule with depth <= 24 */ int32_t test6(void) { struct rte_lpm *lpm = NULL; uint32_t ip = IPv4(0, 0, 0, 0); uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * Call add, lookup and delete for a single rule with depth > 24 */ int32_t test7(void) { __m128i ipx4; uint16_t hop[4]; struct rte_lpm *lpm = NULL; uint32_t ip = IPv4(0, 0, 0, 0); uint8_t depth = 32, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ipx4 = _mm_set_epi32(ip, ip + 0x100, ip - 0x100, ip); rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX); TEST_LPM_ASSERT(hop[0] == next_hop_add); TEST_LPM_ASSERT(hop[1] == UINT16_MAX); TEST_LPM_ASSERT(hop[2] == UINT16_MAX); TEST_LPM_ASSERT(hop[3] == next_hop_add); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * Use rte_lpm_add to add rules which effect only the second half of the lpm * table. Use all possible depths ranging from 1..32. Set the next hop = to the * depth. Check lookup hit for on every add and check for lookup miss on the * first half of the lpm table after each add. Finally delete all rules going * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each * delete. The lookup should return the next_hop_add value related to the * previous depth value (i.e. depth -1). */ int32_t test8(void) { __m128i ipx4; uint16_t hop[4]; struct rte_lpm *lpm = NULL; uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0); uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); /* Loop with rte_lpm_add. */ for (depth = 1; depth <= 32; depth++) { /* Let the next_hop_add value = depth. Just for change. */ next_hop_add = depth; status = rte_lpm_add(lpm, ip2, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); /* Check IP in first half of tbl24 which should be empty. */ status = rte_lpm_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); status = rte_lpm_lookup(lpm, ip2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ipx4 = _mm_set_epi32(ip2, ip1, ip2, ip1); rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX); TEST_LPM_ASSERT(hop[0] == UINT16_MAX); TEST_LPM_ASSERT(hop[1] == next_hop_add); TEST_LPM_ASSERT(hop[2] == UINT16_MAX); TEST_LPM_ASSERT(hop[3] == next_hop_add); } /* Loop with rte_lpm_delete. */ for (depth = 32; depth >= 1; depth--) { next_hop_add = (uint8_t) (depth - 1); status = rte_lpm_delete(lpm, ip2, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip2, &next_hop_return); if (depth != 1) { TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } else { TEST_LPM_ASSERT(status == -ENOENT); } status = rte_lpm_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); ipx4 = _mm_set_epi32(ip1, ip1, ip2, ip2); rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX); if (depth != 1) { TEST_LPM_ASSERT(hop[0] == next_hop_add); TEST_LPM_ASSERT(hop[1] == next_hop_add); } else { TEST_LPM_ASSERT(hop[0] == UINT16_MAX); TEST_LPM_ASSERT(hop[1] == UINT16_MAX); } TEST_LPM_ASSERT(hop[2] == UINT16_MAX); TEST_LPM_ASSERT(hop[3] == UINT16_MAX); } rte_lpm_free(lpm); return PASS; } /* * - Add & lookup to hit invalid TBL24 entry * - Add & lookup to hit valid TBL24 entry not extended * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry * */ int32_t test9(void) { struct rte_lpm *lpm = NULL; uint32_t ip, ip_1, ip_2; uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return; int32_t status = 0; /* Add & lookup to hit invalid TBL24 entry */ ip = IPv4(128, 0, 0, 0); depth = 24; next_hop_add = 100; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Add & lookup to hit valid TBL24 entry not extended */ ip = IPv4(128, 0, 0, 0); depth = 23; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 23; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8 * entry */ ip = IPv4(128, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ip = IPv4(128, 0, 0, 5); depth = 32; next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); ip = IPv4(128, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with valid TBL8 * entry */ ip_1 = IPv4(128, 0, 0, 0); depth_1 = 25; next_hop_add_1 = 101; ip_2 = IPv4(128, 0, 0, 5); depth_2 = 32; next_hop_add_2 = 102; next_hop_return = 0; status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2)); status = rte_lpm_delete(lpm, ip_2, depth_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm_delete(lpm, ip_1, depth_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * - Add rule that covers a TBL24 range previously invalid & lookup (& delete & * lookup) * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup) * - Add rule that extends a TBL24 valid entry & lookup for both rules (& * delete & lookup) * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup) * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup) * - Delete a rule that is not present in the TBL24 & lookup * - Delete a rule that is not present in the TBL8 & lookup * */ int32_t test10(void) { struct rte_lpm *lpm = NULL; uint32_t ip; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; /* Add rule that covers a TBL24 range previously invalid & lookup * (& delete & lookup) */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, RTE_LPM_HEAP); TEST_LPM_ASSERT(lpm != NULL); ip = IPv4(128, 0, 0, 0); depth = 16; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); ip = IPv4(128, 0, 0, 0); depth = 25; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); rte_lpm_delete_all(lpm); /* Add rule that extends a TBL24 valid entry & lookup for both rules * (& delete & lookup) */ ip = IPv4(128, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); ip = IPv4(128, 0, 0, 10); depth = 32; next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ip = IPv4(128, 0, 0, 0); next_hop_add = 100; status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ip = IPv4(128, 0, 0, 0); depth = 24; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); ip = IPv4(128, 0, 0, 10); depth = 32; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Add rule that updates the next hop in TBL24 & lookup * (& delete & lookup) */ ip = IPv4(128, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Add rule that updates the next hop in TBL8 & lookup * (& delete & lookup) */ ip = IPv4(128, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Delete a rule that is not present in the TBL24 & lookup */ ip = IPv4(128, 0, 0, 0); depth = 24; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_delete_all(lpm); /* Delete a rule that is not present in the TBL8 & lookup */ ip = IPv4(128, 0, 0, 0); depth = 32; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * Add two rules, lookup to hit the more specific one, lookup to hit the less * specific one delete the less specific rule and lookup previous values again; * add a more specific rule than the existing rule, lookup again * * */ int32_t test11(void) { struct rte_lpm *lpm = NULL; uint32_t ip; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); ip = IPv4(128, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); ip = IPv4(128, 0, 0, 10); depth = 32; next_hop_add = 101; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ip = IPv4(128, 0, 0, 0); next_hop_add = 100; status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ip = IPv4(128, 0, 0, 0); depth = 24; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); ip = IPv4(128, 0, 0, 10); depth = 32; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete, * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension * and contraction. * * */ int32_t test12(void) { __m128i ipx4; uint16_t hop[4]; struct rte_lpm *lpm = NULL; uint32_t ip, i; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); ip = IPv4(128, 0, 0, 0); depth = 32; next_hop_add = 100; for (i = 0; i < 1000; i++) { status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); ipx4 = _mm_set_epi32(ip, ip + 1, ip, ip - 1); rte_lpm_lookupx4(lpm, ipx4, hop, UINT16_MAX); TEST_LPM_ASSERT(hop[0] == UINT16_MAX); TEST_LPM_ASSERT(hop[1] == next_hop_add); TEST_LPM_ASSERT(hop[2] == UINT16_MAX); TEST_LPM_ASSERT(hop[3] == next_hop_add); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); } rte_lpm_free(lpm); return PASS; } /* * Add a rule to tbl24, lookup (hit), then add a rule that will extend this * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension, * lookup (miss) and repeat for loop of 1000 times. This will check tbl8 * extension and contraction. * * */ int32_t test13(void) { struct rte_lpm *lpm = NULL; uint32_t ip, i; uint8_t depth, next_hop_add_1, next_hop_add_2, next_hop_return; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); ip = IPv4(128, 0, 0, 0); depth = 24; next_hop_add_1 = 100; status = rte_lpm_add(lpm, ip, depth, next_hop_add_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); depth = 32; next_hop_add_2 = 101; for (i = 0; i < 1000; i++) { status = rte_lpm_add(lpm, ip, depth, next_hop_add_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2)); status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); } depth = 24; status = rte_lpm_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm_free(lpm); return PASS; } /* * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension. * No more tbl8 extensions will be allowed. Now add one more rule that required * a tbl8 extension and get fail. * */ int32_t test14(void) { /* We only use depth = 32 in the loop below so we must make sure * that we have enough storage for all rules at that depth*/ struct rte_lpm *lpm = NULL; uint32_t ip; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; /* Add enough space for 256 rules for every depth */ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 256 * 32, 0); TEST_LPM_ASSERT(lpm != NULL); depth = 32; next_hop_add = 100; ip = IPv4(0, 0, 0, 0); /* Add 256 rules that require a tbl8 extension */ for (; ip <= IPv4(0, 0, 255, 0); ip += 256) { status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } /* All tbl8 extensions have been used above. Try to add one more and * we get a fail */ ip = IPv4(1, 0, 0, 0); depth = 32; status = rte_lpm_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status < 0); rte_lpm_free(lpm); return PASS; } /* * Sequence of operations for find existing lpm table * * - create table * - find existing table: hit * - find non-existing table: miss * */ int32_t test15(void) { struct rte_lpm *lpm = NULL, *result = NULL; /* Create lpm */ lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, 256 * 32, 0); TEST_LPM_ASSERT(lpm != NULL); /* Try to find existing lpm */ result = rte_lpm_find_existing("lpm_find_existing"); TEST_LPM_ASSERT(result == lpm); /* Try to find non-existing lpm */ result = rte_lpm_find_existing("lpm_find_non_existing"); TEST_LPM_ASSERT(result == NULL); /* Cleanup. */ rte_lpm_delete_all(lpm); rte_lpm_free(lpm); return PASS; } /* * test failure condition of overloading the tbl8 so no more will fit * Check we get an error return value in that case */ int32_t test16(void) { uint32_t ip; struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 256 * 32, 0); /* ip loops through all possibilities for top 24 bits of address */ for (ip = 0; ip < 0xFFFFFF; ip++){ /* add an entry within a different tbl8 each time, since * depth >24 and the top 24 bits are different */ if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0) break; } if (ip != RTE_LPM_TBL8_NUM_GROUPS) { printf("Error, unexpected failure with filling tbl8 groups\n"); printf("Failed after %u additions, expected after %u\n", (unsigned)ip, (unsigned)RTE_LPM_TBL8_NUM_GROUPS); } rte_lpm_free(lpm); return 0; } /* * Test for overwriting of tbl8: * - add rule /32 and lookup * - add new rule /24 and lookup * - add third rule /25 and lookup * - lookup /32 and /24 rule to ensure the table has not been overwritten. */ int32_t test17(void) { struct rte_lpm *lpm = NULL; const uint32_t ip_10_32 = IPv4(10, 10, 10, 2); const uint32_t ip_10_24 = IPv4(10, 10, 10, 0); const uint32_t ip_20_25 = IPv4(10, 10, 20, 2); const uint8_t d_ip_10_32 = 32, d_ip_10_24 = 24, d_ip_20_25 = 25; const uint8_t next_hop_ip_10_32 = 100, next_hop_ip_10_24 = 105, next_hop_ip_20_25 = 111; uint8_t next_hop_return = 0; int32_t status = 0; lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0); TEST_LPM_ASSERT(lpm != NULL); if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32)) < 0) return -1; status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return); uint8_t test_hop_10_32 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24)) < 0) return -1; status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return); uint8_t test_hop_10_24 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25)) < 0) return -1; status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return); uint8_t test_hop_20_25 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25); if (test_hop_10_32 == test_hop_10_24) { printf("Next hop return equal\n"); return -1; } if (test_hop_10_24 == test_hop_20_25){ printf("Next hop return equal\n"); return -1; } status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); rte_lpm_free(lpm); return PASS; } /* * Lookup performance test */ #define ITERATIONS (1 << 10) #define BATCH_SIZE (1 << 12) #define BULK_SIZE 32 static void print_route_distribution(const struct route_rule *table, uint32_t n) { unsigned i, j; printf("Route distribution per prefix width: \n"); printf("DEPTH QUANTITY (PERCENT)\n"); printf("--------------------------- \n"); /* Count depths. */ for(i = 1; i <= 32; i++) { unsigned depth_counter = 0; double percent_hits; for (j = 0; j < n; j++) if (table[j].depth == (uint8_t) i) depth_counter++; percent_hits = ((double)depth_counter)/((double)n) * 100; printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits); } printf("\n"); } int32_t perf_test(void) { struct rte_lpm *lpm = NULL; uint64_t begin, total_time, lpm_used_entries = 0; unsigned i, j; uint8_t next_hop_add = 0xAA, next_hop_return = 0; int status = 0; uint64_t cache_line_counter = 0; int64_t count = 0; rte_srand(rte_rdtsc()); printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES); print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES); lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 1000000, 0); TEST_LPM_ASSERT(lpm != NULL); /* Measue add. */ begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { if (rte_lpm_add(lpm, large_route_table[i].ip, large_route_table[i].depth, next_hop_add) == 0) status++; } /* End Timer. */ total_time = rte_rdtsc() - begin; printf("Unique added entries = %d\n", status); /* Obtain add statistics. */ for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) { if (lpm->tbl24[i].valid) lpm_used_entries++; if (i % 32 == 0){ if ((uint64_t)count < lpm_used_entries) { cache_line_counter++; count = lpm_used_entries; } } } printf("Used table 24 entries = %u (%g%%)\n", (unsigned) lpm_used_entries, (lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES); printf("64 byte Cache entries used = %u (%u bytes)\n", (unsigned) cache_line_counter, (unsigned) cache_line_counter * 64); printf("Average LPM Add: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); /* Measure single Lookup */ total_time = 0; count = 0; for (i = 0; i < ITERATIONS; i ++) { static uint32_t ip_batch[BATCH_SIZE]; for (j = 0; j < BATCH_SIZE; j ++) ip_batch[j] = rte_rand(); /* Lookup per batch */ begin = rte_rdtsc(); for (j = 0; j < BATCH_SIZE; j ++) { if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0) count++; } total_time += rte_rdtsc() - begin; } printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Measure bulk Lookup */ total_time = 0; count = 0; for (i = 0; i < ITERATIONS; i ++) { static uint32_t ip_batch[BATCH_SIZE]; uint16_t next_hops[BULK_SIZE]; /* Create array of random IP addresses */ for (j = 0; j < BATCH_SIZE; j ++) ip_batch[j] = rte_rand(); /* Lookup per batch */ begin = rte_rdtsc(); for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) { unsigned k; rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE); for (k = 0; k < BULK_SIZE; k++) if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS))) count++; } total_time += rte_rdtsc() - begin; } printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Measure LookupX4 */ total_time = 0; count = 0; for (i = 0; i < ITERATIONS; i++) { static uint32_t ip_batch[BATCH_SIZE]; uint16_t next_hops[4]; /* Create array of random IP addresses */ for (j = 0; j < BATCH_SIZE; j++) ip_batch[j] = rte_rand(); /* Lookup per batch */ begin = rte_rdtsc(); for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) { unsigned k; __m128i ipx4; ipx4 = _mm_loadu_si128((__m128i *)(ip_batch + j)); ipx4 = *(__m128i *)(ip_batch + j); rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT16_MAX); for (k = 0; k < RTE_DIM(next_hops); k++) if (unlikely(next_hops[k] == UINT16_MAX)) count++; } total_time += rte_rdtsc() - begin; } printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Delete */ status = 0; begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { /* rte_lpm_delete(lpm, ip, depth) */ status += rte_lpm_delete(lpm, large_route_table[i].ip, large_route_table[i].depth); } total_time += rte_rdtsc() - begin; printf("Average LPM Delete: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); rte_lpm_delete_all(lpm); rte_lpm_free(lpm); return PASS; } /* * Do all unit and performance tests. */ static int test_lpm(void) { unsigned i; int status, global_status = 0; for (i = 0; i < NUM_LPM_TESTS; i++) { status = tests[i](); if (status < 0) { printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i])); global_status = status; } } return global_status; } static struct test_command lpm_cmd = { .command = "lpm_autotest", .callback = test_lpm, }; REGISTER_TEST_COMMAND(lpm_cmd); ================================================ FILE: app/test/test_lpm6.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "test.h" #include #include #include #include #include #include #include "rte_lpm6.h" #include "test_lpm6_routes.h" #define TEST_LPM_ASSERT(cond) do { \ if (!(cond)) { \ printf("Error at line %d: \n", __LINE__); \ return -1; \ } \ } while(0) typedef int32_t (* rte_lpm6_test)(void); static int32_t test0(void); static int32_t test1(void); static int32_t test2(void); static int32_t test3(void); static int32_t test4(void); static int32_t test5(void); static int32_t test6(void); static int32_t test7(void); static int32_t test8(void); static int32_t test9(void); static int32_t test10(void); static int32_t test11(void); static int32_t test12(void); static int32_t test13(void); static int32_t test14(void); static int32_t test15(void); static int32_t test16(void); static int32_t test17(void); static int32_t test18(void); static int32_t test19(void); static int32_t test20(void); static int32_t test21(void); static int32_t test22(void); static int32_t test23(void); static int32_t test24(void); static int32_t test25(void); static int32_t test26(void); static int32_t test27(void); static int32_t perf_test(void); rte_lpm6_test tests6[] = { /* Test Cases */ test0, test1, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11, test12, test13, test14, test15, test16, test17, test18, test19, test20, test21, test22, test23, test24, test25, test26, test27, perf_test, }; #define NUM_LPM6_TESTS (sizeof(tests6)/sizeof(tests6[0])) #define RTE_LPM6_TBL24_NUM_ENTRIES (1 << 24) #define RTE_LPM6_LOOKUP_SUCCESS 0x04000000 #define MAX_DEPTH 128 #define MAX_RULES 1000000 #define NUMBER_TBL8S (1 << 16) #define MAX_NUM_TBL8S (1 << 21) #define PASS 0 static void IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10, uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15, uint8_t b16) { ip[0] = b1; ip[1] = b2; ip[2] = b3; ip[3] = b4; ip[4] = b5; ip[5] = b6; ip[6] = b7; ip[7] = b8; ip[8] = b9; ip[9] = b10; ip[10] = b11; ip[11] = b12; ip[12] = b13; ip[13] = b14; ip[14] = b15; ip[15] = b16; } /* * Check that rte_lpm6_create fails gracefully for incorrect user input * arguments */ int32_t test0(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_create: lpm name == NULL */ lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm == NULL); /* rte_lpm6_create: max_rules = 0 */ /* Note: __func__ inserts the function name, in this case "test0". */ config.max_rules = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm == NULL); /* socket_id < -1 is invalid */ config.max_rules = MAX_RULES; lpm = rte_lpm6_create(__func__, -2, &config); TEST_LPM_ASSERT(lpm == NULL); /* rte_lpm6_create: number_tbl8s is bigger than the maximum */ config.number_tbl8s = MAX_NUM_TBL8S + 1; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm == NULL); /* rte_lpm6_create: config = NULL */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL); TEST_LPM_ASSERT(lpm == NULL); return PASS; } /* * Creates two different LPM tables. Tries to create a third one with the same * name as the first one and expects the create function to return the same * pointer. */ int32_t test1(void) { struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL; struct rte_lpm6_config config; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_create: lpm name == LPM1 */ lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm1 != NULL); /* rte_lpm6_create: lpm name == LPM2 */ lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm2 != NULL); /* rte_lpm6_create: lpm name == LPM2 */ lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm3 == lpm1); rte_lpm6_free(lpm1); rte_lpm6_free(lpm2); return PASS; } /* * Create lpm table then delete lpm table 100 times * Use a slightly different rules size each time */ int32_t test2(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; int32_t i; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_free: Free NULL */ for (i = 0; i < 100; i++) { config.max_rules = MAX_RULES - i; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); rte_lpm6_free(lpm); } /* Can not test free so return success */ return PASS; } /* * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and * therefore it is impossible to check for failure but this test is added to * increase function coverage metrics and to validate that freeing null does * not crash. */ int32_t test3(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); rte_lpm6_free(lpm); rte_lpm6_free(NULL); return PASS; } /* * Check that rte_lpm6_add fails gracefully for incorrect user input arguments */ int32_t test4(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 24, next_hop = 100; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_add: lpm == NULL */ status = rte_lpm6_add(NULL, ip, depth, next_hop); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm6_add: depth < 1 */ status = rte_lpm6_add(lpm, ip, 0, next_hop); TEST_LPM_ASSERT(status < 0); /* rte_lpm6_add: depth > MAX_DEPTH */ status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; } /* * Check that rte_lpm6_delete fails gracefully for incorrect user input * arguments */ int32_t test5(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 24; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm_delete: lpm == NULL */ status = rte_lpm6_delete(NULL, ip, depth); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm_delete: depth < 1 */ status = rte_lpm6_delete(lpm, ip, 0); TEST_LPM_ASSERT(status < 0); /* rte_lpm_delete: depth > MAX_DEPTH */ status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1)); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; } /* * Check that rte_lpm6_lookup fails gracefully for incorrect user input * arguments */ int32_t test6(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_lookup: lpm == NULL */ status = rte_lpm6_lookup(NULL, ip, &next_hop_return); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm6_lookup: ip = NULL */ status = rte_lpm6_lookup(lpm, NULL, &next_hop_return); TEST_LPM_ASSERT(status < 0); /* rte_lpm6_lookup: next_hop = NULL */ status = rte_lpm6_lookup(lpm, ip, NULL); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; } /* * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user * input arguments */ int32_t test7(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[10][16]; int16_t next_hop_return[10]; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_lookup: lpm == NULL */ status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm6_lookup: ip = NULL */ status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10); TEST_LPM_ASSERT(status < 0); /* rte_lpm6_lookup: next_hop = NULL */ status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; } /* * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user * input arguments */ int32_t test8(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[10][16]; uint8_t depth[10]; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* rte_lpm6_delete: lpm == NULL */ status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10); TEST_LPM_ASSERT(status < 0); /*Create vaild lpm to use in rest of test. */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* rte_lpm6_delete: ip = NULL */ status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10); TEST_LPM_ASSERT(status < 0); /* rte_lpm6_delete: next_hop = NULL */ status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10); TEST_LPM_ASSERT(status < 0); rte_lpm6_free(lpm); return PASS; } /* * Call add, lookup and delete for a single rule with depth < 24. * Check all the combinations for the first three bytes that result in a hit. * Delete the rule and check that the same test returs a miss. */ int32_t test9(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; uint8_t i; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); for (i = 0; i < UINT8_MAX; i++) { ip[2] = i; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); for (i = 0; i < UINT8_MAX; i++) { ip[2] = i; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); } rte_lpm6_free(lpm); return PASS; } /* * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds * another one and expects success. */ int32_t test10(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add = 100; int32_t status = 0; int i; config.max_rules = 127; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); for (i = 1; i < 128; i++) { depth = (uint8_t)i; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); } depth = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == -ENOSPC); depth = 127; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); rte_lpm6_free(lpm); return PASS; } /* * Creates an LPM table with a small number of tbl8s and exhaust them in the * middle of the process of creating a rule. */ int32_t test11(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add = 100; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = 16; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); depth = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); ip[0] = 1; depth = 25; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 33; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 41; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 49; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == -ENOSPC); depth = 41; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); rte_lpm6_free(lpm); return PASS; } /* * Creates an LPM table with a small number of tbl8s and exhaust them in the * middle of the process of adding a rule when there is already an existing rule * in that position and needs to be extended. */ int32_t test12(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add = 100; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = 16; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); depth = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); ip[0] = 1; depth = 41; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); depth = 49; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == -ENOSPC); rte_lpm6_free(lpm); return PASS; } /* * Creates an LPM table with max_rules = 2 and tries to add 3 rules. * Delete one of the rules and tries to add the third one again. */ int32_t test13(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add = 100; int32_t status = 0; config.max_rules = 2; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); depth = 1; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); depth = 2; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); depth = 3; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == -ENOSPC); depth = 2; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 3; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); rte_lpm6_free(lpm); return PASS; } /* * Add 2^16 routes with different first 16 bits and depth 25. * Add one more route with the same depth and check that results in a failure. * After that delete the last rule and create the one that was attempted to be * created. This checks tbl8 exhaustion. */ int32_t test14(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 25, next_hop_add = 100; int32_t status = 0; int i, j; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); for (i = 0; i < 256; i++) { ip[0] = (uint8_t)i; for (j = 0; j < 256; j++) { ip[1] = (uint8_t)j; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); } } ip[0] = 255; ip[1] = 255; ip[2] = 1; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == -ENOSPC); ip[0] = 255; ip[1] = 255; ip[2] = 0; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); ip[0] = 255; ip[1] = 255; ip[2] = 1; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); rte_lpm6_free(lpm); return PASS; } /* * Call add, lookup and delete for a single rule with depth = 24 */ int32_t test15(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; } /* * Call add, lookup and delete for a single rule with depth > 24 */ int32_t test16(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; } /* * Use rte_lpm6_add to add rules which effect only the second half of the lpm * table. Use all possible depths ranging from 1..32. Set the next hop = to the * depth. Check lookup hit for on every add and check for lookup miss on the * first half of the lpm table after each add. Finally delete all rules going * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each * delete. The lookup should return the next_hop_add value related to the * previous depth value (i.e. depth -1). */ int32_t test17(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip1[] = {127,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255}; uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Loop with rte_lpm6_add. */ for (depth = 1; depth <= 128; depth++) { /* Let the next_hop_add value = depth. Just for change. */ next_hop_add = depth; status = rte_lpm6_add(lpm, ip2, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); /* Check IP in first half of tbl24 which should be empty. */ status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } /* Loop with rte_lpm6_delete. */ for (depth = 128; depth >= 1; depth--) { next_hop_add = (uint8_t) (depth - 1); status = rte_lpm6_delete(lpm, ip2, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip2, &next_hop_return); if (depth != 1) { TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); } else { TEST_LPM_ASSERT(status == -ENOENT); } status = rte_lpm6_lookup(lpm, ip1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); } rte_lpm6_free(lpm); return PASS; } /* * - Add & lookup to hit invalid TBL24 entry * - Add & lookup to hit valid TBL24 entry not extended * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry */ int32_t test18(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16], ip_1[16], ip_2[16]; uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* Add & lookup to hit invalid TBL24 entry */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid TBL24 entry not extended */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 23; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); depth = 24; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); depth = 23; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8 * entry. */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Add & lookup to hit valid extended TBL24 entry with valid TBL8 * entry */ IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth_1 = 25; next_hop_add_1 = 101; IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth_2 = 32; next_hop_add_2 = 102; next_hop_return = 0; status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2)); status = rte_lpm6_delete(lpm, ip_2, depth_2); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1)); status = rte_lpm6_delete(lpm, ip_1, depth_1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; } /* * - Add rule that covers a TBL24 range previously invalid & lookup (& delete & * lookup) * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup) * - Add rule that extends a TBL24 valid entry & lookup for both rules (& * delete & lookup) * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup) * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup) * - Delete a rule that is not present in the TBL24 & lookup * - Delete a rule that is not present in the TBL8 & lookup */ int32_t test19(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* Add rule that covers a TBL24 range previously invalid & lookup * (& delete & lookup) */ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 16; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 25; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); rte_lpm6_delete_all(lpm); /* * Add rule that extends a TBL24 valid entry & lookup for both rules * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); next_hop_add = 100; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* * Add rule that updates the next hop in TBL24 & lookup * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* * Add rule that updates the next hop in TBL8 & lookup * (& delete & lookup) */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Delete a rule that is not present in the TBL24 & lookup */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_delete_all(lpm); /* Delete a rule that is not present in the TBL8 & lookup */ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 32; next_hop_add = 100; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status < 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; } /* * Add two rules, lookup to hit the more specific one, lookup to hit the less * specific one delete the less specific rule and lookup previous values again; * add a more specific rule than the existing rule, lookup again */ int32_t test20(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; next_hop_add = 100; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10); depth = 128; next_hop_add = 101; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); next_hop_add = 100; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 24; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10); depth = 128; status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); rte_lpm6_free(lpm); return PASS; } /* * Adds 3 rules and look them up through the lookup_bulk function. * Includes in the lookup a fourth IP address that won't match * and checks that the result is as expected. */ int32_t test21(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_batch[4][16]; uint8_t depth, next_hop_add; int16_t next_hop_return[4]; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 48; next_hop_add = 100; status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 48; next_hop_add = 101; status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 48; next_hop_add = 102; status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 4); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100 && next_hop_return[1] == 101 && next_hop_return[2] == 102 && next_hop_return[3] == -1); rte_lpm6_free(lpm); return PASS; } /* * Adds 5 rules and look them up. * Use the delete_bulk function to delete two of them. Lookup again. * Use the delete_bulk function to delete one more. Lookup again. * Use the delete_bulk function to delete two more, one invalid. Lookup again. * Use the delete_bulk function to delete the remaining one. Lookup again. */ int32_t test22(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_batch[5][16]; uint8_t depth[5], next_hop_add; int16_t next_hop_return[5]; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Adds 5 rules and look them up */ IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth[0] = 48; next_hop_add = 101; status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth[1] = 48; next_hop_add = 102; status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth[2] = 48; next_hop_add = 103; status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth[3] = 48; next_hop_add = 104; status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth[4] = 48; next_hop_add = 105; status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 5); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101 && next_hop_return[1] == 102 && next_hop_return[2] == 103 && next_hop_return[3] == 104 && next_hop_return[4] == 105); /* Use the delete_bulk function to delete two of them. Lookup again */ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 5); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 && next_hop_return[1] == -1 && next_hop_return[2] == 103 && next_hop_return[3] == 104 && next_hop_return[4] == 105); /* Use the delete_bulk function to delete one more. Lookup again */ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 5); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 && next_hop_return[1] == -1 && next_hop_return[2] == -1 && next_hop_return[3] == 104 && next_hop_return[4] == 105); /* Use the delete_bulk function to delete two, one invalid. Lookup again */ IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2); TEST_LPM_ASSERT(status == 0); IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 5); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 && next_hop_return[1] == -1 && next_hop_return[2] == -1 && next_hop_return[3] == -1 && next_hop_return[4] == 105); /* Use the delete_bulk function to delete the remaining one. Lookup again */ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hop_return, 5); TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1 && next_hop_return[1] == -1 && next_hop_return[2] == -1 && next_hop_return[3] == -1 && next_hop_return[4] == -1); rte_lpm6_free(lpm); return PASS; } /* * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete, * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension * and contraction. */ int32_t test23(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint32_t i; uint8_t ip[16]; uint8_t depth, next_hop_add, next_hop_return; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); depth = 128; next_hop_add = 100; for (i = 0; i < 1000; i++) { status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add)); status = rte_lpm6_delete(lpm, ip, depth); TEST_LPM_ASSERT(status == 0); status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT(status == -ENOENT); } rte_lpm6_free(lpm); return PASS; } /* * Sequence of operations for find existing lpm table * * - create table * - find existing table: hit * - find non-existing table: miss */ int32_t test24(void) { struct rte_lpm6 *lpm = NULL, *result = NULL; struct rte_lpm6_config config; config.max_rules = 256 * 32; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; /* Create lpm */ lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Try to find existing lpm */ result = rte_lpm6_find_existing("lpm_find_existing"); TEST_LPM_ASSERT(result == lpm); /* Try to find non-existing lpm */ result = rte_lpm6_find_existing("lpm_find_non_existing"); TEST_LPM_ASSERT(result == NULL); /* Cleanup. */ rte_lpm6_delete_all(lpm); rte_lpm6_free(lpm); return PASS; } /* * Add a set of random routes with random depths. * Lookup different IP addresses that match the routes previously added. * Checks that the next hop is the expected one. * The routes, IP addresses and expected result for every case have been * precalculated by using a python script and stored in a .h file. */ int32_t test25(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[16]; uint32_t i; uint8_t depth, next_hop_add, next_hop_return, next_hop_expected; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); for (i = 0; i < 1000; i++) { memcpy(ip, large_route_table[i].ip, 16); depth = large_route_table[i].depth; next_hop_add = large_route_table[i].next_hop; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); } for (i = 0; i < 100000; i++) { memcpy(ip, large_ips_table[i].ip, 16); next_hop_expected = large_ips_table[i].next_hop; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_expected)); } rte_lpm6_free(lpm); return PASS; } /* * Test for overwriting of tbl8: * - add rule /32 and lookup * - add new rule /24 and lookup * - add third rule /25 and lookup * - lookup /32 and /24 rule to ensure the table has not been overwritten. */ int32_t test26(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t d_ip_10_32 = 32; uint8_t d_ip_10_24 = 24; uint8_t d_ip_20_25 = 25; uint8_t next_hop_ip_10_32 = 100; uint8_t next_hop_ip_10_24 = 105; uint8_t next_hop_ip_20_25 = 111; uint8_t next_hop_return = 0; int32_t status = 0; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32, next_hop_ip_10_32)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); uint8_t test_hop_10_32 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24, next_hop_ip_10_24)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); uint8_t test_hop_10_24 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25, next_hop_ip_20_25)) < 0) return -1; status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return); uint8_t test_hop_20_25 = next_hop_return; TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25); if (test_hop_10_32 == test_hop_10_24) { printf("Next hop return equal\n"); return -1; } if (test_hop_10_24 == test_hop_20_25){ printf("Next hop return equal\n"); return -1; } status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32); status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return); TEST_LPM_ASSERT(status == 0); TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24); rte_lpm6_free(lpm); return PASS; } /* * Add a rule that reaches the end of the tree. * Add a rule that is more generic than the first one. * Check every possible combination that produces a match for the second rule. * This tests tbl expansion. */ int32_t test27(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0}; uint8_t depth = 128, next_hop_add = 100, next_hop_return; int32_t status = 0; int i, j; config.max_rules = MAX_RULES; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); depth = 128; next_hop_add = 128; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); depth = 112; next_hop_add = 112; status = rte_lpm6_add(lpm, ip, depth, next_hop_add); TEST_LPM_ASSERT(status == 0); for (i = 0; i < 256; i++) { ip[14] = (uint8_t)i; for (j = 0; j < 256; j++) { ip[15] = (uint8_t)j; status = rte_lpm6_lookup(lpm, ip, &next_hop_return); if (i == 0 && j == 0) TEST_LPM_ASSERT(status == 0 && next_hop_return == 128); else TEST_LPM_ASSERT(status == 0 && next_hop_return == 112); } } rte_lpm6_free(lpm); return PASS; } /* * Lookup performance test */ #define ITERATIONS (1 << 10) #define BATCH_SIZE 100000 static void print_route_distribution(const struct rules_tbl_entry *table, uint32_t n) { unsigned i, j; printf("Route distribution per prefix width: \n"); printf("DEPTH QUANTITY (PERCENT)\n"); printf("--------------------------- \n"); /* Count depths. */ for(i = 1; i <= 128; i++) { unsigned depth_counter = 0; double percent_hits; for (j = 0; j < n; j++) if (table[j].depth == (uint8_t) i) depth_counter++; percent_hits = ((double)depth_counter)/((double)n) * 100; printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits); } printf("\n"); } int32_t perf_test(void) { struct rte_lpm6 *lpm = NULL; struct rte_lpm6_config config; uint64_t begin, total_time; unsigned i, j; uint8_t next_hop_add = 0xAA, next_hop_return = 0; int status = 0; int64_t count = 0; config.max_rules = 1000000; config.number_tbl8s = NUMBER_TBL8S; config.flags = 0; rte_srand(rte_rdtsc()); printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES); print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES); lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); TEST_LPM_ASSERT(lpm != NULL); /* Measure add. */ begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { if (rte_lpm6_add(lpm, large_route_table[i].ip, large_route_table[i].depth, next_hop_add) == 0) status++; } /* End Timer. */ total_time = rte_rdtsc() - begin; printf("Unique added entries = %d\n", status); printf("Average LPM Add: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); /* Measure single Lookup */ total_time = 0; count = 0; for (i = 0; i < ITERATIONS; i ++) { begin = rte_rdtsc(); for (j = 0; j < NUM_IPS_ENTRIES; j ++) { if (rte_lpm6_lookup(lpm, large_ips_table[j].ip, &next_hop_return) != 0) count++; } total_time += rte_rdtsc() - begin; } printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Measure bulk Lookup */ total_time = 0; count = 0; uint8_t ip_batch[NUM_IPS_ENTRIES][16]; int16_t next_hops[NUM_IPS_ENTRIES]; for (i = 0; i < NUM_IPS_ENTRIES; i++) memcpy(ip_batch[i], large_ips_table[i].ip, 16); for (i = 0; i < ITERATIONS; i ++) { /* Lookup per batch */ begin = rte_rdtsc(); rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES); total_time += rte_rdtsc() - begin; for (j = 0; j < NUM_IPS_ENTRIES; j++) if (next_hops[j] < 0) count++; } printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n", (double)total_time / ((double)ITERATIONS * BATCH_SIZE), (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); /* Delete */ status = 0; begin = rte_rdtsc(); for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { /* rte_lpm_delete(lpm, ip, depth) */ status += rte_lpm6_delete(lpm, large_route_table[i].ip, large_route_table[i].depth); } total_time += rte_rdtsc() - begin; printf("Average LPM Delete: %g cycles\n", (double)total_time / NUM_ROUTE_ENTRIES); rte_lpm6_delete_all(lpm); rte_lpm6_free(lpm); return PASS; } /* * Do all unit and performance tests. */ static int test_lpm6(void) { unsigned i; int status = -1, global_status = 0; for (i = 0; i < NUM_LPM6_TESTS; i++) { status = tests6[i](); if (status < 0) { printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i])); global_status = status; } } return global_status; } static struct test_command lpm6_cmd = { .command = "lpm6_autotest", .callback = test_lpm6, }; REGISTER_TEST_COMMAND(lpm6_cmd); ================================================ FILE: app/test/test_lpm6_routes.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _TEST_LPM_ROUTES_H_ #define _TEST_LPM_ROUTES_H_ struct rules_tbl_entry { uint8_t ip[16]; uint8_t depth; uint8_t next_hop; }; struct ips_tbl_entry { uint8_t ip[16]; uint8_t next_hop; }; static struct rules_tbl_entry large_route_table[] = { {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 146}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 141}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 23}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 97, 252}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 6}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 137}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 82, 9}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 120, 163}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 79, 197}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 249}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 88}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 104}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 36}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 239}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 201}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 94}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 241}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 239}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 151}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 137}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 231}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 11}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 96, 20}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 68}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 101, 64}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 217}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 101}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 58}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 254}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 148}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126, 126}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 123, 76}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 240}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 33}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 47}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 109, 41}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 72}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 43}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 68, 26}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 139}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 219}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 105}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 210}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 151}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 28}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 64}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 121, 9}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 92, 250}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 200}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 127, 132}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 71, 182}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 102, 7}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 100, 146}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 70, 98}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 86, 179}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 77, 245}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 169}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 52}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 177}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 74}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 122, 212}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 122, 238}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 18}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 75, 155}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 123}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 92, 11}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 211}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 116}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 57}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 108, 178}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 102, 93}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 92, 3}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 121, 162}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 109, 125}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 33}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 254}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 74, 66}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 4}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 86, 122}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 59}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 117, 99}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 41}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 112}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 85, 255}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 106}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 170}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 86}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 79, 155}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 65}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 39}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 90, 162}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 69}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 163}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 90, 116}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 19}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 48}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 230}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 78, 155}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 96, 158}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 113, 252}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 110, 176}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 66, 211}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 15}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 95}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 169}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 249}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 105, 61}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 63}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 43}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 81, 228}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 78, 165}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 211}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 210}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 99, 61}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 120}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 94}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 153}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 221}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 87, 163}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 106, 188}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 124, 15}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 28}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 84, 240}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 93, 59}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 90, 195}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 10}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 88, 206}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 137}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 225}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 223}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 29}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 103, 166}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 80, 178}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 38}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 141}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 116, 230}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 99, 124}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 118, 54}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 162}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 32}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 102, 237}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 215}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 138}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 118, 73}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 90, 43}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 112, 88}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 119, 91}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 69, 140}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 65}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 122, 201}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 72, 69}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 170}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 192}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 89, 21}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 35}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 71, 235}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 240}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 136}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 186}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 95, 174}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 79, 153}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 118}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 113}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 58}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 101, 206}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 111, 42}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 6}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 254}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 108, 214}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 107, 43}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 178}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 179}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 87, 236}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 98, 184}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 91, 95}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 127, 152}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 113}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 108, 137}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 224}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 61}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 205}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 124, 170}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 117}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 70, 225}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 72, 34}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 92}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 112, 61}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 117, 221}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 121, 105}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 181}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 79, 110}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 86, 103}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 123, 218}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 146}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 90}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 108, 197}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 103, 158}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 81, 118}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 95}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 239}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 48}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 228}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 247}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 85, 12}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 129}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 50}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 128, 250}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 77, 249}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 92, 228}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 181}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 206}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 122}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 72, 81}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 95, 175}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 118, 170}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 174}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 104}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 114, 113}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 80, 89}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 113, 151}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 108}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 224}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 95}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 173}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 93, 176}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 119, 84}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 78, 104}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 236}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 116, 153}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 190}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 202}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 54}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 156}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 126, 245}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 218}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 93, 72}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 112, 183}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 183}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 241}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 106}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 180}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 96, 142}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 100, 6}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 118, 33}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 224}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 78, 14}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 149}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 108, 131}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 121, 133}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 89, 33}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 204}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 43}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 168}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 180}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 112, 208}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 90, 25}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 111, 50}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 109, 110}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 109, 21}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 147}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 56}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 117, 144}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 100, 198}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 90, 235}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 105}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 138}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 122}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 65, 193}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 231}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 250}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 86, 24}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 191}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 117, 111}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 111, 205}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 133}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122, 122}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 87, 227}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 53}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 72, 224}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 199}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 79}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 19}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 96, 211}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 120, 6}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 121, 143}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 135}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 109, 21}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 220}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 151}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 111}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 63}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 112}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 48}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 126, 100}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 156}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 95, 120}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 5}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 103}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 84}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 101, 24}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 86, 81}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 96}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 121, 6}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 119, 40}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 143}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 69}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 92, 48}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 115}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 115, 130}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 86, 57}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 97}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 146}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 117, 194}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 114, 129}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 97, 159}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 117, 242}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 104, 162}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 102, 140}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 113, 77}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 82, 121}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 69, 102}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 28}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 89, 154}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 76, 39}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 78, 163}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 68, 42}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 92, 207}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 25}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 150}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 76, 103}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 71, 155}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 96, 142}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 112, 2}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 59}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 112}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 166}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 73, 62}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 176}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 100, 6}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 26}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 6}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 13}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 41}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 135}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 93, 171}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 20}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 89, 119}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 112, 49}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 141}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 132}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 105, 176}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 186}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 93}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 111, 242}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 163}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 184}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 188}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 126, 193}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 78, 63}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 115, 160}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 117, 251}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 72, 228}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 72, 168}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 194}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 166}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 122, 210}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 89, 254}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 75, 49}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 96, 95}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 193}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 155}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 133}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 10}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 31}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 127, 98}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 96, 22}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 214}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 217}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 98, 102}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 83, 169}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 152}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 103, 214}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 99, 178}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 164}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 15}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 76, 94}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 70, 239}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 73, 82}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 98, 47}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 84, 214}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 215}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 84, 153}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 122, 245}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 118}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 123, 128}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 7}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 80, 152}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 114, 248}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 85, 143}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 159}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 11}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 110}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 97, 181}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 121, 4}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 101}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 38}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 78, 57}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 142}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 184}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 91}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 224}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 78, 114}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 118, 184}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 215}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 120, 167}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 89, 233}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 101}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 67, 139}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 79, 32}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 57}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 91, 151}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 0}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 227}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 118, 124}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 104, 228}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 179}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 107}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 104, 206}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 95}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 96, 219}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 119, 138}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 84}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 161}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 25}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 107, 113}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 46}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 72}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 93, 230}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 117, 142}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 134}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 112, 100}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 109, 45}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 219}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 52}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 83, 240}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 90, 13}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 84, 191}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 106, 95}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 65}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 195}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 103, 21}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 114}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 92}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 237}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 125, 172}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 98, 116}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 203}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 74}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 96, 220}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 219}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 179}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 194}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 187}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 79}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 87}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 126}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 106}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 96}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 45}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 110, 8}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 226}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 222}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 71, 218}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 116, 59}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 80}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 177}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 98, 44}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 93, 206}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 96, 236}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 101}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 49}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 179}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 109, 112}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 96, 31}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 111}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 86, 65}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 78, 222}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 4}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 67}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 109, 197}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 121}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 167}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 140}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 106, 193}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 90, 47}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 187}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 102}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 103, 237}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 107, 115}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 84, 217}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 79, 21}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 113, 3}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 62}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 80}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 184}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 80, 197}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 63}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 99, 62}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 114, 231}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 158}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 101, 118}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 237}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 79, 15}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 122, 84}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 119, 205}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 82, 220}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 42}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 144}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 74}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 89}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 88, 77}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 94, 2}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 75}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 18}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 246}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 114, 10}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 207}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 41}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 89, 102}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118, 118}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 146}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 104, 122}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 107, 6}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 18}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 83}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 99, 90}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 140}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 242}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 111, 9}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 50}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 34}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 11}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 71}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 146}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 124, 249}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 143}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 110, 17}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 119, 60}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 162}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 5}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 139}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 8}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 114, 246}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 171}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 88, 206}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 163}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 166}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 128}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 59}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 179}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 124, 87}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 114, 29}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 91, 184}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 45}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 144}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 114, 119}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 113}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 82, 50}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 207}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 3}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 13}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 42}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 94, 30}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 94}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 71, 190}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 238}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 20}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 84}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 108}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 89, 136}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 93, 196}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 67}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 104}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 15}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 128, 237}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 116, 224}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 179}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 84}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 65}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 178}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 154}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 106}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 125}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 118}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 73, 52}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 173}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 113, 8}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 74, 211}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 253}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 47}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 112, 73}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 192}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 128, 55}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 94, 147}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 125, 86}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 82, 16}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 111, 167}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 148}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 66}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 104, 70}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 166}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 109}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 226}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 85, 218}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 78, 54}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 67, 48}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 244}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 74, 50}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 173}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 84, 245}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 121, 54}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 113, 86}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 115}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 144}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 89, 171}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 93, 231}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 88, 34}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 225}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 174}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 113, 37}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 121, 39}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 59}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 96}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 147}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 110, 56}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 111, 234}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 199}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 69, 191}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 235}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 45}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 67, 164}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 121, 130}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 166}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 140}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 118, 47}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 111, 148}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 103}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 116, 94}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 85}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 109, 250}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 153}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 125, 182}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 94, 23}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 108, 38}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 110, 121}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 87, 146}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 138}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 94, 149}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 88, 232}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 255}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 148}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 117}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 237}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 113}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 162}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 225}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 92, 210}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 34}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 224}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 143}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 216}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 120, 239}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 111, 54}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 35}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 119, 230}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 234}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 115, 70}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 246}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 127, 217}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 128, 201}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 49}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 2}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 64}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 239}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 116, 47}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 80, 43}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 94, 17}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 5}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 81, 240}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 197}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 84, 192}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 160}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 84, 199}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 127, 217}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 83, 75}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 106, 222}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 85, 39}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 9}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 217}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 142}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 18}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 104, 180}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 205}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 251}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 178}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 198}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 84}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 128}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 97, 75}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 101, 192}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 114, 60}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 169}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 10}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 118, 64}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 127, 182}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 29}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 39}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 93}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 75, 228}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 236}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 190}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 217}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 93, 74}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 180}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 91}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 230}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 175}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 75, 171}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 120, 202}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 113}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 96, 187}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 120, 38}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 35}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 115}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 18}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 34}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 87, 75}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 232}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 91, 154}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 195}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 70, 122}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 220}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 80}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 77, 133}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 93}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 110, 176}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 95, 68}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 103, 247}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 240}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 74, 83}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 132}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 217}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 214}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 193}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 71, 61}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 65}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 91, 108}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 244}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 95, 194}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 124, 82}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 116, 45}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 224}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 17}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 133}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 85, 125}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 42}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 96, 140}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 91}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 92}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 125}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 106, 249}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 202}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 107}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 124}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 57}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 92, 181}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 107}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 128, 101}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 102}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 136}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 114}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 215}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 79, 249}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 88, 29}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 71}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 127, 112}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 72}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 73, 155}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 66}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 91, 77}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 109}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 72, 37}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 91, 56}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 103, 5}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 15}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 183}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 105, 171}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 112, 202}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 136}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 107}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 87, 193}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 4}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 96, 68}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 40}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 255}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 108}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 219}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 108, 12}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 84}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 96, 33}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 91, 199}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 52}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 113, 184}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 124}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 109, 128}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 255}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 105, 146}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 172}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 70, 116}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 189}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 70, 10}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 98, 184}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 98}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 37}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 174}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 251}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 115}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 107, 252}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 176}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 91, 155}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 124, 36}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 88, 202}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 208}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 77, 158}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 136}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 191}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 120, 126}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 128, 139}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 216}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 93}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 196}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 81, 119}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 104, 93}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 96, 183}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 207}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 102}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 36}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 93, 41}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 70}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 218}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 120, 226}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 114, 25}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 98, 6}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 26}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 149}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 127}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 144}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 213}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 115}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 83, 146}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 58}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 222}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 16}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 169}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 175}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 3}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 96, 2}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 193}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 118, 151}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 182}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 148}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 53}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 87}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 73, 235}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 51}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 116, 11}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 68, 28}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 96, 73}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 216}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 99}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 35}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 127, 195}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 108, 176}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 87, 217}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 126, 244}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 125}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 219}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 165}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 117, 6}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 47}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 73}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 98}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 21}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 142}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 93, 34}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 74, 41}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 80}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 11}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 254}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 95}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 8}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 212}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 95, 217}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 15}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 84, 66}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 122}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 97, 12}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 71, 171}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 106, 42}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 194}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 107, 237}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 93, 151}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 109, 238}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 128}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 227}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 127, 138}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 60}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 148}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 128, 129}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 202}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 81, 88}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 90, 3}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 108, 243}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 80, 95}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 87, 255}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 48}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 38}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 115, 20}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 41}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 92, 133}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 95, 189}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 95, 151}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 100}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 118}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 164}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 98, 71}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 251}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 51}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 185}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 144}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 84, 51}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 87, 32}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 70, 137}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 2}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 163}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 100, 162}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 192}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 185}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 51}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 93}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 159}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 189}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 248}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 123, 38}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 76, 167}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 28}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 125, 37}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 107, 234}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 70}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 108, 50}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 171}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 113, 236}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 3}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 86, 64}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 108, 213}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 15}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 145}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 27}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 127, 75}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 123, 76}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 113, 247}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 121}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 214}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 221}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 102}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 191}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 197}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 79, 106}, }; static struct ips_tbl_entry large_ips_table[] = { {{66, 70, 154, 143, 197, 233, 0, 0, 0, 194, 147, 115, 142, 16, 127, 8}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 229, 23, 195, 4, 249, 2}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 84, 128, 8, 36, 26}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 203, 219, 206}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 136, 152, 202, 50}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 5, 152, 190, 60, 210, 175, 81, 101}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 72, 237, 205, 48, 61}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 141, 41, 73, 9, 48, 30, 122, 18}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 43, 198, 176, 9, 240, 180}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 219, 60, 216, 227, 85, 97, 202, 243}, 146}, {{66, 70, 154, 143, 197, 233, 0, 185, 206, 43, 179, 129, 115, 166, 131, 102}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 88, 13, 78}, 146}, {{66, 70, 154, 143, 197, 233, 0, 216, 146, 183, 156, 118, 54, 250, 238, 4}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 2, 79}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 61, 9, 147, 80}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 217, 179, 60, 30, 230, 203}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 86, 177, 17, 57, 191, 148}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 183, 12, 211, 118, 249, 169, 219}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 119, 197, 52, 238, 81, 191, 112}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 100, 145, 120}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 230, 252}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 51, 116}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 69, 132, 25, 226}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 29, 50, 25, 251, 126, 167}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 105, 206, 38, 242, 19, 169}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 241, 65, 232, 169}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 98, 218, 119, 149, 192}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 182, 103}, 146}, {{66, 70, 154, 143, 197, 233, 0, 63, 60, 122, 11, 248, 145, 149, 224, 39}, 146}, {{66, 70, 154, 143, 197, 233, 0, 154, 104, 241, 221, 216, 89, 163, 74, 77}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 87, 149}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 217, 248, 111, 129, 119, 118}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 114, 29, 173, 243, 47, 62, 112}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 165, 58, 168, 164}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 8, 20, 67, 95, 80}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 230, 234, 164, 55, 21, 105, 115, 227}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 242, 114, 211, 159, 242}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 23, 36, 201, 102, 160, 208}, 146}, {{66, 70, 154, 143, 197, 233, 0, 5, 252, 137, 97, 245, 7, 115, 20, 51}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 249, 106, 198, 190, 23, 28, 20, 24, 214}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 12, 2, 115, 42}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 156, 225, 23}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 6, 253, 87, 178, 67, 237}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 238, 6, 238, 63}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 46, 212, 97, 16}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 141, 110, 89, 188, 166, 68}, 146}, {{66, 70, 154, 143, 197, 233, 0, 239, 190, 110, 60, 81, 148, 203, 221, 214}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 171, 145, 15, 135}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 146, 194}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 252, 81, 209, 1, 127, 134}, 146}, {{66, 70, 154, 143, 197, 233, 0, 244, 124, 19, 48, 19, 179, 32, 169, 72}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 216, 65, 92, 84}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 204, 126}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 45, 240, 229, 141, 221, 111}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 81, 244, 218, 21, 42, 248}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 190, 2, 138, 170, 49, 96}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 25, 212, 101, 84, 241}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 222, 35, 234, 212}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 31, 253, 169}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 39, 101}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 165, 183, 69, 28}, 146}, {{66, 70, 154, 143, 197, 233, 0, 19, 125, 169, 46, 44, 137, 1, 136, 111}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 122, 168, 211, 57, 14, 162, 55, 211}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 161, 107, 124}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 126, 35, 107, 201, 21, 140, 15, 246}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 70, 233, 179, 218, 33}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 199, 202, 185, 226, 209}, 146}, {{66, 70, 154, 143, 197, 233, 0, 245, 205, 239, 116, 228, 171, 199, 226, 214}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 11, 44, 36, 55, 249, 213, 120}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 28, 193, 217, 220, 104, 255}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 124, 197, 195}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 80, 124, 199}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 103, 30}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 181, 183, 49, 182, 210, 82, 135, 16}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 183, 182}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 249, 91, 47, 60}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 51, 228, 125, 220, 71, 10}, 146}, {{66, 70, 154, 143, 197, 233, 0, 20, 10, 247, 72, 120, 44, 79, 150, 118}, 146}, {{66, 70, 154, 143, 197, 233, 0, 123, 72, 190, 210, 143, 29, 197, 249, 169}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 0, 239, 246, 133, 146, 235, 153, 223}, 146}, {{66, 70, 154, 143, 197, 233, 0, 0, 207, 124, 153, 121, 5, 242, 157, 173}, 146}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 23, 185, 140, 139, 103, 142, 106}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 185, 15, 51, 2, 207, 128, 233}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 252, 177, 6}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 217, 157, 143, 150}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 164, 17, 162, 72, 176, 60, 79}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 165, 219, 227, 69, 234, 211}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 155, 93, 182, 88, 109}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 40, 180, 73, 180, 154, 67, 254, 51}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 231, 179, 32, 174, 173, 96, 36, 53}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 56, 168, 98, 111}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 239, 60, 33, 23, 217}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 99, 247}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 74, 90, 7, 5, 71, 46, 75}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 193, 240, 139, 99, 182, 157, 108}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 144, 159, 7}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 141}, {{107, 79, 18, 235, 142, 84, 80, 149, 168, 187, 209, 186, 15, 23, 185, 46}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 85, 105, 215, 122, 146}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 253, 123, 24, 192, 161}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 58, 253, 77, 222, 34}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 239, 32, 67, 206, 156, 187}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 188, 68, 182, 43, 122, 149, 93, 183}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 63, 23, 17, 133, 247, 150, 13}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 238, 84}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 34, 58, 184, 194, 11, 119, 165, 244}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 9, 195, 194, 222, 80, 28, 20}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 53, 32, 179, 2, 203, 84, 204, 56}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 196, 167, 118}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 34, 116, 134, 156, 29, 92, 178}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 224, 104, 226, 104, 168}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 167, 190, 234, 157, 115, 238, 4, 193}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 144, 199, 189}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 122, 250, 151, 194, 106}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 77, 157, 57, 89, 21, 168}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 78, 31, 174, 130, 146, 52, 56, 74}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 91, 125, 201, 35, 116, 188, 164, 252}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 245, 31}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 27, 55, 108}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 120, 215}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 153, 175, 0, 89}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 95, 210, 157}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 187, 43, 158, 70, 171, 33, 205}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 152, 70, 141, 31, 221, 103, 174}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 243, 33, 81, 214, 37, 116, 228}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 211, 126}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 138, 208, 196, 178, 255}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 216, 169, 43, 121, 215, 65, 200, 82}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 141}, {{107, 79, 18, 235, 142, 84, 80, 26, 17, 43, 72, 37, 99, 10, 168, 98}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 254, 199, 57, 240}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 30, 64, 213, 26, 221, 132, 12, 59}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 74, 13, 197, 157, 100, 175, 194, 224}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 176, 81, 26, 37}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 7, 218, 171, 158, 176, 85, 57}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 52, 206}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 252, 122}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 82, 206}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 230, 211, 109, 58, 219, 165}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 72, 155, 98}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 17, 222, 31, 151}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 236, 182}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 132, 252, 246, 173, 253}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 132, 199, 200, 117, 150, 141}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 189, 113, 154, 76, 249}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 143, 4, 77, 201, 223, 120}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 204, 55, 76}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 41, 155, 198, 49, 25, 201}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 26, 132, 211, 6, 57, 251, 37, 211}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 158, 233}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 164, 71, 141, 193, 223}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 202, 200}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 92, 110, 137, 158, 112, 255}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 163, 167, 14, 36, 59, 58}, 141}, {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 110, 197, 154}, 141}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 180, 250, 184, 27, 86, 91}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 143, 254, 149}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 195, 197, 228}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 237, 101, 21, 175, 105}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 86, 164, 92, 85, 60}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 23}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 192, 220, 99, 80}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 202, 0, 167}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 43, 96, 151, 166, 39}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 25, 217, 213, 232, 190, 106, 17}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 239, 86, 149, 133}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 184}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 35, 65, 32, 131, 169, 32}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 36, 58, 147, 71, 141, 4}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 248, 65, 211, 179, 206, 85}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 95, 236, 202, 248}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 192, 175, 60, 105, 148}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 204, 201, 176}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 192, 45}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 72, 147}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 192, 45, 131, 232, 28}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 17, 77, 199, 129, 99}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 170, 233, 63, 187}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 141, 209, 134, 233, 198}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 114}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 175, 158, 25, 163, 230, 24, 233}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 21, 243, 104, 20, 64, 129, 69}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 172, 66, 53, 209}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 176, 210, 235, 5}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 34, 125, 189}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 254}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 20, 67}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 163, 119, 83}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 122, 205, 65, 128, 233, 10, 136}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 204, 52, 24, 71}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 135, 215, 40, 133, 253, 42, 29}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 32, 167, 28, 223}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 1, 232}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 15, 195, 45, 100, 206}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 214, 82, 203, 3}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 99}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 239, 213, 185, 226, 120, 186}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 198, 119, 227, 110}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 201, 141, 27, 99}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 244}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 154}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 173, 9, 76, 225, 199, 160}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 45, 204, 81, 211}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 77, 84, 167, 164, 243, 3, 12}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 174, 47}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 169}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 152, 104, 155, 52, 188}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 179, 99, 140}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 166, 61, 219, 47, 68, 69}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 206, 9, 124, 78, 117}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 84, 158}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 27, 243, 93, 225}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 189, 22, 24}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 172, 139, 224, 173}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 14, 208, 208, 144, 211, 98}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 42, 30, 148}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 21, 161, 36}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 144, 247, 65}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 173, 12, 131, 36, 16, 200}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 247, 61}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 137, 65, 227, 212, 117}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 191}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 247, 173, 74, 168}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 51, 44, 35, 114, 105, 175, 71}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 11, 96, 90, 42, 72, 205, 83}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 196, 8, 106, 99, 151}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 86, 245, 24, 209}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 182}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 135, 172, 217, 250, 57}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 141}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 43, 152, 244}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 91, 172, 104, 36}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 164}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 81}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 36, 217, 78, 46, 137, 197}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 32}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 82}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 225, 147}, 23}, {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 23}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 85, 160}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 115}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 1, 244}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 198}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 98, 57, 127}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 15, 18, 26}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 241, 79}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 129}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 14, 129, 101}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 17, 64}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 186}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 207, 231}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 72, 118}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 202, 75}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 79, 202, 136}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 147, 188}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 26}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 212, 68}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 203}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 28, 89, 18}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 126}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 175, 244}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 186}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 242, 217, 242}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 246, 239}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 185, 134, 190}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 238, 227}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 50}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 41, 189, 65}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 141, 189, 141}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 201, 122, 55}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 31, 205, 118}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 122, 104}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 252}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 190, 9}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 169, 168, 251}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 113, 241, 133}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 247, 119}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 71, 100}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 224}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 178, 59, 195}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 128, 203, 86}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 8, 41, 235}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 16, 197}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 123}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 165, 2}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 27, 229}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 63, 158}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 244, 44}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 125, 33}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 222, 11}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 194, 191}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 40, 252, 201}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 61, 105, 128}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 10, 26}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 188, 225}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 177, 106}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 206, 53}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 2, 22, 95}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 218}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 188, 127, 40}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 111, 158}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 195, 150, 178}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 104, 1, 27}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 222}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 50}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 33, 112}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 68, 5}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 213, 44, 7}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 8}, 252}, {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 18}, 252}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 160, 126, 159, 189, 251, 157, 4}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 46, 99, 76, 221, 248, 157, 78}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 219, 170, 221, 145}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 140, 180, 70, 51, 253, 59, 197, 2}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 155, 17, 148, 91, 79, 55, 184, 129}, 6}, {{5, 70, 208, 170, 19, 0, 116, 64, 244, 22, 187, 211, 6, 167, 107, 214}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 226, 222}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 62, 16, 53, 47, 161, 159, 193}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 55, 152, 181, 157}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 28, 224, 188, 69, 120, 84}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 147, 161, 198}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 181, 228, 170, 121, 204, 247}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 237, 69, 91, 180, 38, 104, 143}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 221, 145, 208, 217}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 169, 255, 172, 182, 203}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 145, 203, 184}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 28, 160, 146}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 88, 44, 236, 84, 63, 58, 9, 66}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 17, 0, 107, 195, 141}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 7, 93, 86, 46, 8, 175, 144}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 8, 236, 137, 219, 194, 71}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 141, 240, 125, 157, 221, 143, 146, 237}, 6}, {{5, 70, 208, 170, 19, 0, 116, 85, 38, 93, 11, 172, 63, 240, 86, 229}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 58, 173, 12}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 27, 233, 163}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 46, 132}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 126, 16, 235, 31}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 107, 43, 144, 93, 210, 164, 155, 191}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 108, 82}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 65, 68, 116, 217, 194, 202}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 185, 168, 18, 247}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 141, 220, 223, 91}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 84, 215, 108, 189, 67}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 170, 100, 146, 135, 9, 197, 62}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 246, 171, 35, 61, 245}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 227, 50, 78, 110, 178, 238, 241}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 76, 155, 124, 238, 79, 226}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 109, 167, 163, 53, 248}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 129, 53, 219, 24, 140, 114}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 72, 128, 25, 8, 218, 90, 72}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 45, 201, 53, 254, 150, 161}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 197, 238}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 49, 91, 218, 100, 17, 119, 31}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 31, 70, 200, 125}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 8, 54, 2, 3, 81, 94, 56, 45}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 51, 69, 170, 250, 8, 85, 181}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 116, 113, 183, 163, 26, 48, 103}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 54, 136, 156, 80, 8, 30, 142, 219}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 2, 227, 102}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 46, 9, 90, 100, 125, 108, 141}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 146, 25, 220, 214, 40, 194, 156, 126}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 100, 80, 104}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 89, 169, 143, 55, 86}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 211, 229}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 133, 151}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 142, 3, 5}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 157, 253, 71, 85, 89, 23, 21, 186}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 141, 222, 11, 124, 182, 165, 184}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 79, 44, 251, 19, 23, 185, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 8, 42, 236}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 2, 237, 145, 124, 206, 41}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 229, 254, 54}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 17, 175, 208, 32, 57, 95, 161}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 208, 205, 157}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 201, 210, 111, 227, 103, 248, 54, 225, 96}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 79, 145, 224, 247, 201, 42, 134, 148}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 207, 29, 32, 157, 98, 75, 86}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 4, 111, 63, 133, 4}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 127, 116, 94, 247, 108, 197, 47, 167}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 8, 122, 204, 245, 84}, 6}, {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 149, 221, 33, 92}, 6}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 26, 202, 126, 207}, 137}, {{1, 0, 0, 0, 0, 0, 0, 152, 23, 119, 35, 158, 137, 196, 202, 143}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 141, 132, 60, 168, 17, 121, 48}, 137}, {{1, 0, 0, 0, 0, 0, 47, 72, 65, 68, 107, 192, 67, 125, 110, 16}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 114, 253, 200}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 211}, 137}, {{1, 0, 0, 189, 178, 25, 10, 102, 117, 30, 95, 106, 167, 200, 28, 4}, 137}, {{1, 0, 0, 0, 0, 0, 183, 128, 193, 70, 212, 12, 102, 86, 239, 44}, 137}, {{1, 0, 0, 125, 109, 248, 123, 97, 195, 100, 47, 147, 207, 150, 84, 69}, 137}, {{1, 0, 0, 0, 0, 0, 139, 248, 221, 32, 147, 173, 186, 229, 218, 199}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 171, 228, 69, 23, 9, 182, 178, 169}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 97}, 137}, {{1, 0, 0, 0, 65, 75, 138, 130, 29, 57, 180, 1, 52, 237, 57, 27}, 137}, {{1, 0, 0, 0, 0, 0, 0, 144, 100, 64, 90, 143, 215, 237, 193, 129}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 224, 36, 68, 219}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 189, 61}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 6, 154, 80, 92}, 137}, {{1, 0, 30, 6, 115, 81, 20, 120, 187, 153, 141, 64, 210, 218, 120, 213}, 137}, {{1, 0, 0, 0, 0, 211, 23, 76, 209, 36, 48, 25, 88, 126, 100, 203}, 137}, {{1, 0, 0, 0, 0, 57, 132, 73, 91, 128, 211, 1, 108, 85, 3, 236}, 137}, {{1, 0, 0, 0, 0, 0, 0, 129, 218, 58, 64, 117, 40, 112, 54, 53}, 137}, {{1, 0, 0, 0, 0, 0, 0, 14, 184, 56, 117, 18, 239, 211, 235, 248}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 88, 10, 30}, 137}, {{1, 0, 0, 0, 89, 75, 149, 114, 6, 84, 63, 89, 176, 199, 1, 122}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 137}, {{1, 0, 0, 0, 0, 0, 0, 254, 173, 101, 204, 138, 223, 106, 17, 130}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 94, 88}, 137}, {{1, 0, 0, 216, 224, 79, 242, 94, 39, 83, 100, 26, 79, 61, 144, 236}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 121}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 253, 48, 242, 173, 112, 71, 254}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 132}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 166, 1, 134, 96, 222}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 121, 122, 120, 70, 179}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 71, 27}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 67, 195, 168, 248}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 10, 85, 132, 225, 224, 48, 196, 66, 224}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 165, 89, 177, 144, 198, 57, 149, 3, 56, 213}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 170, 99, 166, 123}, 137}, {{1, 0, 0, 0, 0, 0, 0, 141, 98, 238, 9, 251, 194, 206, 113, 158}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 47, 96, 181, 205, 139, 227, 211}, 137}, {{1, 0, 0, 73, 32, 235, 233, 92, 184, 3, 153, 24, 250, 11, 109, 199}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 64}, 137}, {{1, 0, 0, 0, 0, 0, 207, 158, 60, 29, 206, 104, 20, 225, 83, 176}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 17, 71, 177, 22}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 245, 245, 63, 250, 195, 139, 232}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 38, 86, 59, 153, 53, 34, 16, 28, 21, 166, 22}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 143, 250, 23}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 92, 202, 187}, 137}, {{1, 0, 0, 0, 0, 0, 155, 119, 5, 230, 144, 128, 158, 139, 92, 91}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 228, 51, 79, 161, 100, 251, 193}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 114, 229}, 137}, {{1, 0, 0, 0, 236, 163, 225, 226, 35, 135, 122, 179, 2, 209, 67, 22}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 140, 14, 246}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 59, 61, 22, 244}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 93, 23, 80, 25, 127, 251, 17}, 137}, {{1, 0, 0, 0, 0, 0, 183, 32, 122, 115, 142, 101, 71, 239, 197, 26}, 137}, {{1, 0, 0, 0, 112, 236, 94, 178, 254, 201, 120, 240, 93, 58, 37, 230}, 137}, {{1, 0, 0, 0, 0, 0, 0, 219, 173, 97, 3, 113, 227, 248, 23, 55}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 164}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 34, 106, 69, 113, 66}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 155, 129, 254}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 199, 174, 52, 243}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 107, 174, 63}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 98}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 84, 180, 49, 188}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 172, 185, 175}, 137}, {{1, 0, 0, 0, 243, 49, 203, 199, 69, 222, 234, 170, 16, 224, 37, 244}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 201, 135, 156, 109}, 137}, {{1, 0, 0, 0, 0, 107, 220, 206, 41, 70, 187, 178, 64, 79, 165, 74}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 85, 254, 68, 224, 11, 104, 189}, 137}, {{1, 0, 0, 168, 8, 62, 41, 41, 240, 178, 229, 191, 176, 41, 216, 180}, 137}, {{1, 0, 0, 0, 0, 0, 0, 241, 253, 37, 46, 120, 224, 16, 201, 40}, 137}, {{1, 0, 0, 0, 217, 48, 2, 246, 191, 226, 2, 7, 92, 202, 140, 97}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 179, 176, 24, 142, 178, 34, 227}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 13}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 244, 208, 190, 159, 253}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 255, 23, 255, 213, 17, 98, 30, 216}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 137}, {{1, 0, 0, 0, 0, 0, 0, 132, 173, 193, 251, 1, 247, 226, 5, 122}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 137}, {{1, 0, 0, 0, 0, 0, 0, 47, 138, 17, 100, 255, 113, 65, 244, 171}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 231, 31, 102, 71, 143, 82}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 137}, {{12, 188, 26, 18, 0, 0, 0, 93, 161, 248, 97, 91, 37, 42, 217, 30}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 110, 145}, 9}, {{12, 188, 26, 18, 0, 0, 63, 201, 143, 114, 238, 32, 35, 120, 248, 32}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 57}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 54, 246, 15, 248, 250, 117, 149}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 238}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 224, 218, 62, 128}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 116, 253, 85, 230, 75}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 119, 204, 207, 183}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 173, 19}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 51, 242, 8, 150, 198, 58, 26, 87, 111}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 50, 155, 108, 136, 144, 37, 189}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 87, 33, 71, 231, 3, 172, 210}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 156}, 9}, {{12, 188, 26, 18, 0, 0, 199, 31, 235, 22, 225, 103, 213, 204, 205, 221}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 221, 33, 255, 15, 196, 35, 16}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 17}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 87, 5, 38, 162, 165, 64, 106, 75}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 117, 228, 19, 79}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 71, 69, 245, 231, 180, 182, 134, 131}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 9}, {{12, 188, 26, 18, 0, 0, 0, 90, 175, 31, 58, 38, 78, 110, 247, 249}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 230, 197, 182, 6}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 220, 216}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 40, 154, 3, 60, 162, 26}, 9}, {{12, 188, 26, 18, 0, 136, 172, 244, 138, 85, 113, 233, 232, 37, 166, 216}, 9}, {{12, 188, 26, 18, 0, 0, 0, 207, 237, 92, 110, 61, 179, 200, 112, 252}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 253, 51, 122, 208, 149, 57}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 84}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 4, 176}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 122, 85, 227, 147}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 239, 60, 217, 221, 120, 118, 47, 87}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 249, 62, 128, 243, 87, 201, 243, 70}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 241, 196, 119, 39, 85, 219, 54, 171}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 238, 6, 178, 142, 14, 82, 79}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 13, 188, 112, 82, 83, 172, 217, 180}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 29}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 130, 247}, 9}, {{12, 188, 26, 18, 0, 0, 97, 234, 171, 195, 79, 18, 108, 13, 192, 234}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 112, 167, 68, 166, 243}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 170, 251, 211, 241, 153, 195, 39, 41}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 3, 90, 149, 113}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 9}, {{12, 188, 26, 18, 0, 0, 0, 132, 117, 27, 33, 79, 38, 113, 200, 96}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 84, 233, 80, 148, 92}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 177, 179, 127, 13, 157}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 166, 247}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 67, 206}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 219, 74, 218, 247, 117, 241, 158, 74}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 27, 220, 38, 200}, 9}, {{12, 188, 26, 18, 0, 0, 45, 20, 19, 140, 74, 81, 2, 247, 16, 207}, 9}, {{12, 188, 26, 18, 0, 0, 28, 202, 227, 156, 60, 230, 225, 21, 70, 236}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 176, 115, 138, 176, 207, 101, 247, 250}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 253}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 241, 80, 73, 176}, 9}, {{12, 188, 26, 18, 0, 0, 0, 170, 119, 248, 161, 12, 114, 49, 44, 172}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 140, 107, 83, 230, 115, 156, 220}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 165, 152, 42, 175, 140, 162}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 140, 83, 84, 57}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 159, 61, 46, 112}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 32, 53, 67, 63, 181, 231}, 9}, {{12, 188, 26, 18, 0, 46, 84, 44, 231, 151, 9, 8, 184, 2, 77, 55}, 9}, {{12, 188, 26, 18, 0, 0, 0, 148, 150, 51, 36, 219, 75, 212, 81, 125}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 184, 110, 82, 210, 227, 2}, 9}, {{12, 188, 26, 18, 0, 0, 52, 209, 95, 150, 123, 249, 125, 28, 215, 126}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 81, 193, 83, 204, 35, 252}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 82}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 248, 152}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 250, 123, 201, 37, 238}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 113, 150, 22, 94, 76, 9}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 199, 87}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 161}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 42, 67, 161, 227, 142, 23, 218}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 150, 51}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 188, 67, 17, 199, 92, 24, 232}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 154, 35, 64, 251}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 11, 97, 167, 5, 134}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 56}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 17, 53}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 184, 216, 5, 159, 164}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 9}, {{12, 188, 26, 18, 0, 0, 1, 20, 241, 26, 48, 129, 12, 232, 243, 126}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 51, 131, 13, 52, 111, 59, 105}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 135, 118}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 124, 5, 132, 241}, 9}, {{12, 188, 26, 18, 0, 206, 163, 116, 153, 252, 1, 168, 241, 64, 255, 60}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 147, 6, 197, 143}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{12, 188, 26, 18, 0, 0, 195, 232, 192, 182, 32, 169, 17, 149, 10, 62}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 179, 35, 234, 55, 233}, 9}, {{12, 188, 26, 18, 0, 33, 236, 106, 253, 166, 10, 229, 21, 11, 76, 77}, 9}, {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 88, 38, 206, 100, 108}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 33, 229}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 10, 125, 12, 76, 74}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 160}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 238, 95, 240, 9, 139}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 111}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 82}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 175, 126, 253, 232, 24}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 171, 234}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 84, 97}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 80, 83, 173, 11}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 166}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 16, 166}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 83, 20, 135}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 144, 42, 61}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 35, 26, 213}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 150, 175, 249}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 103, 113, 52, 222, 56}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 19, 68}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 27, 100, 253, 67, 91}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 210, 39, 96, 229}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 25, 65}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 84, 46}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 40}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 66, 251, 254, 189}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 172, 237}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 142, 216}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 244, 28}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 14}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 158, 253, 73}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 24, 201, 252, 179}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 161, 31, 77, 132}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 79, 60}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 252}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 252}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 63, 50}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 215, 206, 4}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 115}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 42}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 143}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 70, 110, 237}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 3, 136}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 51, 130, 116}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 114, 207}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 38}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 16, 125, 162}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 157, 83, 181, 171}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 154, 160, 39, 134, 138}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 129, 96}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 205}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 85, 200, 142, 196, 175}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 43, 194}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 132, 63}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 187, 126, 44, 86, 42}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 78, 225}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 210, 12, 64, 129, 108}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 238, 116, 68, 82, 239}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 167, 159}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 115}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 243, 67, 14, 23, 211}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 5}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 226, 245, 27}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 118, 190}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 231, 96}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 94, 81, 16}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 235, 43}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 30}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 43, 148, 70, 17}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 209, 187, 145}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 247, 68, 69}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 36, 22, 59, 234, 236}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 222, 108, 195}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 249, 183, 52}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 29}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 50, 198}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 70, 155}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 45, 7, 54, 237}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 68, 206, 54}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 118, 235, 86, 82, 8}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 107, 110, 247, 59}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 253, 175, 14, 116, 121}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 28}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 51, 193}, 9}, {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 64}, 9}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 163}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 190, 251, 174, 110, 15}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 113, 244, 191}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 223, 20, 210, 31}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 109, 68, 76, 246, 147}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 53, 240}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 180, 79, 203, 43}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 123, 145}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 143, 8, 213, 179}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 123, 59}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 135, 92, 201, 156, 65}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 246, 164, 69}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 159, 240, 85}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 173, 232, 162, 228, 254}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 163, 57}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 143, 17, 110, 47, 163}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 216, 243}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 45, 126, 104, 109, 55}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 22, 23}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 182}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 73, 41, 155, 208, 57}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 225, 53, 88, 117}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 4}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 157, 62, 233, 3}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 26}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 204, 187, 64}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 25, 194, 192, 108}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 225, 94, 61, 171, 221}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 183}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 76, 231}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 74, 177, 241, 27}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 237}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 226, 212, 18}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 108, 218}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 44, 213, 77}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 167, 218, 188, 75, 241}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 119, 70, 77, 168, 212}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 227, 152, 188, 7}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 216, 110}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 75, 233}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 97, 198, 118, 156, 155}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 124, 51, 144, 180, 189}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 233, 185, 247, 186, 98}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 23, 100}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 211, 90}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 229, 150, 170}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 34}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 192, 230, 104}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 158, 190, 169}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 243}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 38, 227, 66, 102}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 128, 170, 96}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 203, 105}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 110, 209, 243, 123}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 208}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 197, 75, 214}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 162, 21, 252}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 221, 235, 170}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 253, 204, 21, 233}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 102, 118, 218}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 10, 27, 106, 60}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 112, 250, 224, 169}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 253, 149}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 171}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 157}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 60, 151}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 204}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 237, 99}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 42, 240, 154}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 248, 10, 14, 47, 135}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 213, 115}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 205}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 197, 117, 30, 30}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 5, 238}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 22, 144, 186}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 104, 44, 246, 190, 235}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 18, 115, 87, 63, 240}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 53, 18, 115, 79}, 197}, {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 93}, 197}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 24, 248, 47}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 163, 46, 109}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 88, 248, 245, 194, 198, 156, 1}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 4, 219, 136}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 234, 73}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 90, 46, 243, 239, 104, 46, 174}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 167, 90, 13, 106}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 228, 191, 24}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 178, 120, 230, 253, 195, 173, 127}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 77, 145, 138, 12}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 69, 242, 182, 193}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 217, 167, 201, 86, 197, 198}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 43, 250, 5, 49, 22, 15, 54}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 14, 78}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 214, 48, 227, 130}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 137, 174, 87}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 171, 87, 246}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 220, 198, 99, 108, 166, 85, 138, 192}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 213, 43, 241, 252}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 251, 21}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 116, 234, 81, 30, 20, 11, 111, 246}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 88, 55, 194}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 7, 134}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 140, 232, 134, 17, 127, 175, 103}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 112, 131, 233, 65, 121}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 55, 162}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 212, 84, 213, 114, 105, 95}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 1, 238, 169, 5}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 162, 230, 56, 155, 128, 52, 124, 196}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 214, 32, 120}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 50, 110}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 144, 139}, 249}, {{212, 39, 158, 71, 253, 98, 248, 25, 147, 39, 67, 71, 117, 20, 15, 194}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 156, 53, 128, 47}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 34, 71, 79, 166}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 112, 239, 57, 139, 240, 227}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 188, 113, 172, 56}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 39, 249, 145, 67, 95}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 82, 31, 76}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 134, 26, 122, 13, 187, 1, 209}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 90, 28, 191, 92, 88, 57, 15, 4}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 208, 153, 100, 77}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 59, 1, 219, 220, 221}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 123, 119, 153, 40, 187, 135}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 110, 54, 33, 124, 240, 168, 84}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 32, 242, 127, 199, 71, 34, 189, 41}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 254, 96, 31, 217, 163, 67, 1}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 21, 238, 228}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 10, 70, 13, 250}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 153, 26, 78, 210, 24, 108, 211, 165}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 137, 32, 128, 233, 57, 229, 237}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 5, 201, 187, 193, 240, 237, 115}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 128, 244, 245, 59, 201}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 112, 7, 236, 231, 7, 195, 80}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 237, 226}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 219, 187, 29}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 101, 2}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 249, 163, 87, 39, 75, 130, 92, 221}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 24, 161, 209, 215}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 129, 85}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 143, 178, 19, 73, 151, 95, 149, 191}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 8, 94}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 206, 221, 26, 186}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 87, 106, 187, 79, 50, 113, 185}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 150, 85, 238, 30, 16, 236, 128, 71}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 101, 83, 33, 241, 154, 215, 103}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 64, 106, 57}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 226, 225, 218, 69, 238, 109, 194}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 191, 255, 215, 29, 119, 244, 67}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 125, 127, 201, 34, 196, 41, 194}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 86, 85, 195}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 212, 168, 223, 95, 209, 150}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 175, 55, 27, 235, 255, 208, 89}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 6, 227, 129, 112}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 6, 23, 2, 89, 157, 118, 146, 15}, 249}, {{212, 39, 158, 71, 253, 98, 248, 0, 0, 90, 74, 63, 194, 210, 94, 187}, 249}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 169, 181, 122}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 238, 211, 206, 190, 144, 21}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 57, 23, 41, 202, 141}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 79, 210, 49}, 88}, {{92, 58, 159, 130, 105, 56, 0, 133, 176, 79, 92, 247, 51, 93, 154, 32}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 148, 190, 220, 172, 121, 26, 18, 48}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 88, 66, 221}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 139, 88, 12, 248, 0, 234, 217, 235}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 154, 165, 152, 85, 90, 70, 90, 132}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 239, 101, 78, 173, 50, 240, 187, 187}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 13, 152, 244, 245, 144, 2, 58}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 236, 55, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 44, 117, 194, 211, 177, 130, 55, 189}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 122, 129, 203}, 88}, {{92, 58, 159, 130, 105, 56, 0, 79, 96, 164, 207, 122, 88, 78, 150, 43}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 40, 183, 247, 255, 84, 41}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 212, 14, 15, 120, 147, 199, 104}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 102, 251, 188, 254, 185}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 28, 176, 254, 240, 251, 164}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 215, 26, 94, 185}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 35, 87}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 182, 58, 81, 54, 176}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 57, 117, 119}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 42, 126, 68}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 53, 82, 116, 3, 170}, 88}, {{92, 58, 159, 130, 105, 56, 0, 83, 203, 238, 201, 55, 168, 132, 225, 251}, 88}, {{92, 58, 159, 130, 105, 56, 0, 252, 138, 129, 93, 234, 247, 3, 248, 171}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 15, 5, 78, 39}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 212, 117, 32}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 64, 17, 166, 167}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 153, 83, 29, 161, 94, 12, 8, 18}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 148, 46}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 184, 40, 246, 99}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 218, 166, 147, 79, 246, 219, 153, 192, 212}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 71, 206, 209}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 187, 213, 150, 147, 241, 125, 68}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 247, 118, 241, 110, 84}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 226, 232}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 69, 40, 210, 243, 220, 78}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 29, 131, 209, 206, 94, 117}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 116, 44, 138, 102, 240}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 248, 244, 85, 117}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 217, 93, 58, 25, 14, 235, 161, 11}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 238, 89, 46, 31, 173}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 112, 9}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 222, 176, 227, 236, 241}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 95, 47, 62, 144}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 122, 38, 19, 138, 241}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 122, 166}, 88}, {{92, 58, 159, 130, 105, 56, 0, 121, 118, 226, 169, 26, 141, 62, 35, 54}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 186, 102, 135, 194, 198, 35}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 168, 66}, 88}, {{92, 58, 159, 130, 105, 56, 0, 18, 128, 139, 93, 195, 104, 120, 152, 112}, 88}, {{92, 58, 159, 130, 105, 56, 202, 125, 96, 25, 143, 200, 105, 87, 149, 15}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 33, 112, 114, 219, 219, 85}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 176, 153}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 64, 207, 67, 41, 72}, 88}, {{92, 58, 159, 130, 105, 56, 0, 207, 99, 42, 112, 177, 104, 233, 171, 82}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 206, 49, 46, 244}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 120, 77, 245, 40, 41, 123, 107}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 170, 241, 93, 144, 160, 238}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 13, 223, 170, 153}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 189, 240}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 112, 115, 129, 203, 173, 17, 116, 215}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 101, 89, 205, 229, 212, 193}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 2, 191}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 93, 114}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 120, 8, 34, 170, 74, 205, 169, 11}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 158, 177, 209, 154, 229, 45, 222, 215}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 174, 242, 167, 137}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 120, 121}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 148, 247, 65}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 88}, {{92, 58, 159, 130, 105, 56, 0, 47, 100, 159, 254, 236, 253, 70, 103, 56}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 75, 123, 63, 243, 216, 167}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 146, 51, 212, 65, 109}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 227, 135, 210, 10, 200, 9}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 175, 108, 42, 233, 99, 26}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 88}, {{92, 58, 159, 130, 105, 56, 196, 7, 105, 44, 65, 96, 41, 197, 56, 30}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 146, 228, 128, 81, 7, 129, 4, 85}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 130, 228, 104, 152}, 88}, {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 80, 96}, 88}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 104}, {{118, 140, 65, 198, 212, 93, 144, 17, 211, 249, 68, 140, 53, 97, 115, 111}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 132, 246}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 220, 51, 254, 225, 199, 251, 158}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 211, 145, 24, 37, 139, 184}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 126, 198, 100}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 41, 229, 77, 253, 60, 204}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 13, 114, 134, 126}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 38, 123, 241, 147, 195, 152, 23}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 200, 61, 0, 96, 35, 219}, 104}, {{118, 140, 65, 198, 212, 93, 144, 107, 250, 123, 9, 240, 236, 47, 126, 239}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 205, 110, 185, 253, 4}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 193, 240, 91, 56, 37, 91}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 151, 194, 45}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 12, 11, 219}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 67, 77, 93}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 249, 71, 182, 1, 231}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 198, 2, 225, 76, 237, 89, 244}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 253, 198}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 32, 218, 210, 43, 228, 171, 112, 159}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 217, 91, 189, 37}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 156, 5, 100, 232, 141, 218}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 70, 52}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 94, 117, 0, 241, 152}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 236, 191, 125, 184, 32}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 125, 142, 123}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 161, 116, 11, 205, 169}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 3, 152, 206, 54, 121, 63, 145, 7}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 155, 116, 246, 207, 25, 48, 220, 53}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 210, 46, 85, 43}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 141, 160, 72, 246, 132}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 201, 134, 133, 162, 76, 11, 185, 26}, 104}, {{118, 140, 65, 198, 212, 93, 144, 38, 95, 120, 233, 178, 124, 146, 193, 172}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 77, 36, 104, 242}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 160, 230, 203, 149, 49, 187, 245}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 120, 189}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 39, 246}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 152, 106, 36, 219, 19, 228}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 208, 80, 142, 236}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 57, 45}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 19, 253, 185, 113, 11, 32, 156}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 225, 71}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 235, 151, 132, 162, 161, 252, 76}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 177, 110, 171, 135, 149}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 192, 115}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 211, 12, 81, 200, 212, 235, 101, 83, 221}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 144, 137, 203, 255, 40, 65}, 104}, {{118, 140, 65, 198, 212, 93, 144, 247, 222, 145, 26, 152, 78, 166, 189, 111}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 67, 37}, 104}, {{118, 140, 65, 198, 212, 93, 144, 116, 163, 12, 119, 78, 129, 204, 226, 193}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 151, 114, 253, 17, 29, 38}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 41, 209, 195, 244, 70, 56, 22, 113}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 5, 125, 198, 106, 137, 125, 40, 132}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 213, 72, 145, 159, 88, 42, 162, 65}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 73, 124, 52, 54, 73}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 214, 225, 255, 231, 253}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 175, 144, 132, 64, 116, 181, 56, 142}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 255, 33, 35, 56}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 17, 45, 201, 89, 211, 72, 100, 183}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 103, 151, 216, 197, 4}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 6, 141, 50, 51, 202, 163, 210, 244}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 164, 63}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 152, 184, 101, 58}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 209, 178, 139, 125}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 21, 104, 233, 212, 106, 253, 187, 74}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 50, 184, 13, 9}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 15, 149}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 224, 48, 245, 249, 1, 125, 146, 167}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 213, 9, 13, 170, 169, 26}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 250, 79, 132}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 180, 211, 157, 92, 186, 126, 86}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 2, 0, 31, 11, 185, 23, 223, 37}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 57, 126, 57, 212}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 115, 151, 11, 223, 254, 166}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 10, 151, 181, 177}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 129, 89, 174, 49, 235}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 130, 180, 20, 217}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 196, 49, 67, 9, 73, 222, 42}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 76, 214, 168}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 99, 105}, 104}, {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 35, 6, 57, 185, 234, 4}, 104}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 46, 103, 232, 6, 22, 12}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 27}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 193, 175, 170, 235, 210, 189, 247}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 151, 130, 211, 190, 104, 51, 128}, 36}, {{86, 64, 0, 50, 237, 255, 240, 48, 176, 208, 192, 155, 27, 146, 247, 55}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 210, 134}, 36}, {{86, 64, 0, 0, 193, 143, 112, 130, 185, 133, 145, 43, 251, 228, 162, 94}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 146, 192, 56, 77, 97, 210, 215, 202, 169}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 118, 64, 8, 22}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 81, 35}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 220, 12, 142, 255, 243, 221, 96, 57}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 221, 107, 108, 63, 39, 164, 122, 7}, 36}, {{86, 64, 0, 0, 0, 132, 209, 112, 167, 176, 187, 37, 105, 96, 222, 30}, 36}, {{86, 64, 0, 0, 34, 84, 158, 243, 232, 78, 217, 210, 8, 225, 71, 71}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 209}, 36}, {{86, 64, 0, 0, 0, 238, 85, 22, 118, 145, 239, 186, 140, 221, 189, 125}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 71, 111, 79, 240, 61, 72}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 190, 232, 3, 222, 218, 0, 41}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 84, 63, 237, 22}, 36}, {{86, 64, 0, 0, 0, 0, 18, 80, 41, 148, 78, 176, 162, 130, 66, 108}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 144, 136, 39, 227}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 21, 232, 16, 179, 205, 154}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 136, 245, 241, 142, 4, 31, 57, 170}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 194, 48, 232, 23, 160, 114, 55, 140}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 138}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 50, 120, 252, 4, 140, 59, 170}, 36}, {{86, 64, 0, 0, 173, 237, 124, 128, 32, 40, 153, 137, 215, 147, 1, 91}, 36}, {{86, 64, 0, 195, 93, 210, 55, 63, 163, 123, 238, 46, 85, 109, 125, 206}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 236, 182}, 36}, {{86, 64, 0, 0, 0, 0, 231, 116, 153, 74, 239, 241, 2, 39, 192, 97}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 84, 172, 106, 109}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 59, 125, 163, 216, 132, 241, 245, 95}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 206, 78, 177}, 36}, {{86, 64, 0, 0, 224, 59, 179, 30, 217, 123, 153, 222, 126, 150, 139, 194}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 5, 215, 54, 151, 52, 215, 198, 236, 1, 111, 230}, 36}, {{86, 64, 0, 0, 213, 199, 96, 15, 253, 154, 240, 35, 203, 86, 65, 123}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 144, 180, 231, 192, 91, 161, 22, 206, 189}, 36}, {{86, 64, 0, 0, 0, 0, 0, 162, 30, 185, 131, 182, 102, 105, 21, 2}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 28, 161, 250, 206, 50, 52, 72, 97, 141, 71, 16, 109, 183, 168}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 99}, 36}, {{86, 64, 70, 199, 173, 6, 48, 156, 176, 164, 249, 232, 229, 76, 65, 113}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 156}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 144, 42, 179, 64, 141, 54}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 2}, 36}, {{86, 64, 0, 0, 0, 0, 0, 121, 151, 210, 55, 93, 239, 214, 18, 22}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 63, 175, 137, 42, 4, 218, 83, 221, 213, 147, 115}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 111, 164}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 66, 148, 115, 134}, 36}, {{86, 64, 0, 0, 0, 0, 0, 76, 192, 141, 117, 126, 69, 198, 135, 72}, 36}, {{86, 64, 0, 0, 0, 0, 0, 156, 199, 195, 48, 165, 109, 231, 13, 61}, 36}, {{86, 64, 0, 16, 128, 127, 164, 248, 164, 201, 53, 64, 216, 140, 203, 13}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 188, 242, 180, 177, 226, 94}, 36}, {{86, 64, 0, 201, 107, 91, 91, 11, 168, 51, 157, 254, 183, 160, 201, 59}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 33, 162, 159, 89}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 1, 143}, 36}, {{86, 64, 183, 47, 122, 128, 213, 138, 163, 167, 131, 127, 21, 119, 166, 139}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 86, 169, 119, 29, 33, 251}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 236, 115, 228, 181, 161, 61, 24, 82, 32}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 193, 198, 3}, 36}, {{86, 64, 0, 0, 0, 0, 0, 18, 238, 17, 96, 63, 98, 205, 161, 48}, 36}, {{86, 64, 0, 0, 0, 0, 0, 226, 89, 68, 176, 66, 136, 190, 146, 239}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 76, 171, 103}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 132}, 36}, {{86, 64, 0, 0, 0, 0, 11, 148, 35, 184, 176, 234, 227, 177, 132, 164}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 132, 242, 173}, 36}, {{86, 64, 0, 0, 29, 240, 144, 20, 243, 27, 72, 183, 169, 32, 157, 88}, 36}, {{86, 64, 0, 0, 225, 81, 10, 194, 212, 13, 21, 205, 47, 18, 243, 129}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 144, 100, 70, 61}, 36}, {{86, 64, 0, 0, 181, 118, 214, 198, 173, 167, 4, 28, 95, 191, 67, 240}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 212, 134, 168, 52, 41, 95, 242, 189, 26, 128, 78, 214, 52}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{86, 64, 0, 0, 93, 70, 120, 21, 83, 1, 78, 38, 24, 162, 67, 29}, 36}, {{86, 64, 0, 0, 0, 0, 0, 196, 145, 231, 44, 141, 187, 145, 90, 222}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 112, 82, 253, 233, 162, 238, 205, 7}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 86}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 121, 172, 168, 230, 200, 98, 192, 109}, 36}, {{86, 64, 0, 76, 66, 150, 107, 41, 6, 186, 221, 150, 29, 2, 242, 202}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 141, 27}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 5, 19, 50, 31}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 23}, 36}, {{86, 64, 73, 42, 126, 207, 187, 72, 14, 52, 238, 1, 29, 103, 131, 126}, 36}, {{86, 64, 0, 0, 0, 0, 0, 69, 157, 202, 12, 66, 16, 94, 229, 161}, 36}, {{86, 64, 248, 105, 187, 184, 51, 201, 20, 71, 178, 122, 234, 76, 224, 130}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 161, 176, 10, 145, 129, 10, 233}, 36}, {{86, 64, 0, 0, 0, 0, 0, 0, 0, 141, 156, 66, 249, 240, 166, 184}, 36}, {{86, 64, 0, 0, 0, 0, 122, 187, 111, 66, 134, 182, 178, 45, 71, 3}, 36}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 47, 73, 60, 100, 211, 198}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 195, 168, 141, 165, 96, 67, 83, 67}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 230, 71, 77, 38, 245, 220}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 36, 195, 149, 235, 218}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 205, 157, 26, 83, 146, 191}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 79, 151, 245, 208}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 142, 29, 207, 76, 96, 228}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 148, 173, 251, 39, 32, 9, 201}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 170, 201}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 82, 206}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 164, 100, 129, 63, 87, 10, 147}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 32, 4, 17, 67, 61, 103}, 239}, {{79, 135, 242, 193, 197, 11, 200, 112, 214, 51, 114, 154, 63, 28, 125, 71}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 195, 10, 42, 220, 179}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 113, 247, 186, 172}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 114, 34}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 159, 218}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 244, 98, 142, 34}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 104, 87, 115, 250, 142, 244, 192}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 242, 124, 225, 166, 190}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 199, 173, 45, 120, 145, 208, 229}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 39, 153, 62, 54, 152, 165, 167}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 3, 38, 166}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 165, 148}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 239, 13, 32}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 196, 167, 14, 93, 14, 58, 190}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 236, 140, 60, 117, 184}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 1, 194, 195, 227, 98}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 137, 224, 238, 246, 191}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 243, 154, 142}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 91, 20, 39, 88, 42, 154, 131}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 89, 107, 4, 151, 152}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 17, 195, 94, 107, 239}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 190, 103, 192, 111, 8, 144}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 113, 234, 156, 4}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 133, 182, 178, 197, 145, 49, 15, 158}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 131, 255, 236, 173, 108}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 32, 159, 24, 104, 119}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 176, 78}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 216, 150}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 193, 197, 11}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 234, 44, 230, 42, 223, 31}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 38, 81, 8, 127, 118, 208}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 42, 73, 234, 185, 247, 166, 117, 135}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 210, 232, 97}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 30, 42, 254, 120, 144, 174, 138, 108}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 105, 36, 174, 118, 228, 35, 52, 57}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 76, 104, 177, 145, 78, 79, 87}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 245, 206, 14}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 182, 161, 128, 231, 37}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 181, 147, 129, 6, 139, 94, 58, 39}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 81, 147, 65, 176, 155, 113}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 165, 195, 227, 132}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 86, 39, 123, 106}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 29, 146}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 139, 153, 255}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 133, 70, 138, 221}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 132, 180, 202, 136, 57, 234}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 108, 13, 61, 41, 222, 70, 134, 13}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 177, 145, 112, 224, 100, 174}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 49, 56, 168, 139, 40, 208, 212}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 97, 234, 32}, 239}, {{79, 135, 242, 193, 197, 11, 200, 200, 138, 116, 230, 157, 36, 223, 252, 68}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 239, 153, 94, 146}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 175, 127, 166, 183}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 84, 96}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 211, 219, 96, 181}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 125, 226, 235, 186, 79, 50, 71}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 156, 187, 181, 208, 139, 193}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 105, 204, 77, 160, 175, 73}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 4, 162, 242}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 175, 232, 49, 38, 179}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 21, 145, 108, 248, 123}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 112, 182, 171, 156}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 102, 143, 51, 175, 192, 122, 173}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 10, 245, 197, 231, 186}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 32, 132, 93, 176, 102, 158, 72, 94}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 70, 8}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 2, 19, 43, 245, 58, 147, 175}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 141, 32, 112, 223, 9, 70, 36, 13}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 193, 187, 236}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 67, 194, 24, 73, 202, 148, 168}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 25, 211, 112, 112, 188, 42}, 239}, {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 106, 142}, 239}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 12, 32}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 145, 143, 97, 204, 109, 78, 25}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 46, 249, 217, 44, 24}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 94, 94, 192, 222, 94, 107}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 244, 246, 119, 176, 57, 164, 82}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 235, 140, 30, 201, 225}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 118, 109, 242}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 78, 206}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 16, 35, 232, 61, 76, 155, 69}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 176, 64, 128}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 165, 232, 34}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 29}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 160, 114}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 158, 35}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 69, 26, 129, 227, 172}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 89, 187, 195, 69, 28, 190}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 41}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 70, 166, 83, 142, 191}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 161, 183, 155, 92}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 85, 81, 128, 220, 88}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 151, 249, 46, 10, 137}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 54, 60, 51, 190, 72}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 187, 229, 225, 141, 192, 117, 192}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 198, 30, 156, 228, 50, 129, 22}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 37}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 174, 221, 2, 114, 55}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 144, 182, 183}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 191, 69, 157}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 38, 106, 34}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 241, 191, 98, 32, 143, 182}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 214, 239, 190, 179, 104}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 144, 185}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 68, 7, 72, 126}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 230, 187, 33, 75, 71, 167}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 183, 193, 162, 149, 50, 211}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 19, 216, 61, 17, 222}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 59, 32, 122}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 8, 74, 136, 52, 1}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 94, 12, 99, 123, 153, 174}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 232, 50, 97, 245, 150}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 34, 108, 10, 143, 177}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 170, 157, 30, 43, 94, 157, 169}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 111, 89, 96, 108, 188, 138, 100}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 4, 95, 165, 138, 39}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 224, 152, 32, 90}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 128}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 37}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 230, 53, 230, 229, 246, 40, 67}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 222}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 72, 161}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 105}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 196}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 174, 47, 226, 101}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 43, 100, 180, 22, 75}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 241, 145, 92, 226, 32}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 58, 203, 10}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 240, 207, 11, 167, 173}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 5, 119}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 24, 177, 217, 254, 8}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 39, 31}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 101, 211, 111, 210, 120, 149}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 245, 234}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 107, 158, 35, 51}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 248, 14, 141, 12, 79}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 163, 5}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 66, 41, 40, 175, 160, 226, 119}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 105, 122, 16, 4, 17, 149}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 143}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 190, 226, 14, 250, 154}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 175, 224, 127, 74, 148}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 90, 176}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 135, 42, 62, 137}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 58, 244, 81, 165, 231, 225}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 139, 2, 104}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 34, 163}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 34, 240, 92, 61, 150}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 132}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 38, 184, 214}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 89, 123, 39, 116, 226, 194, 170}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 155, 190}, 201}, {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 239, 31, 226, 173, 86, 174}, 201}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 230}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 216, 129}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 145, 67, 23, 248, 188, 207}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 106, 247}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 8, 41, 133, 113, 221, 204}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 56, 68, 146, 56, 16, 219, 107, 115}, 94}, {{31, 9, 231, 42, 0, 0, 0, 156, 104, 158, 70, 166, 73, 215, 84, 162}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 141, 155, 93, 140}, 94}, {{31, 9, 231, 42, 0, 0, 0, 230, 40, 40, 205, 204, 58, 241, 227, 177}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 25}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 132, 154, 116, 46, 176}, 94}, {{31, 9, 231, 42, 0, 0, 53, 3, 127, 32, 234, 114, 182, 56, 9, 198}, 94}, {{31, 9, 231, 42, 0, 0, 0, 133, 39, 107, 33, 244, 86, 201, 26, 112}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 2}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 94}, {{31, 9, 231, 42, 0, 0, 0, 56, 139, 250, 208, 28, 82, 252, 216, 28}, 94}, {{31, 9, 231, 42, 0, 0, 100, 215, 171, 242, 68, 124, 87, 30, 54, 99}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 59, 154, 248, 191, 31, 169}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 217}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 78, 154}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 11, 136, 106, 218, 215, 248, 242}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 45, 232, 77, 158, 151}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 191, 223, 83, 230, 51, 1, 107}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 121, 185, 154, 46, 31, 9, 237, 18}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 144, 105, 186, 233}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 156, 137, 12, 119, 41}, 94}, {{31, 9, 231, 42, 0, 0, 0, 244, 105, 2, 109, 88, 4, 31, 78, 219}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 229, 240, 151, 10, 67}, 94}, {{31, 9, 231, 42, 0, 158, 55, 20, 87, 9, 144, 226, 63, 114, 88, 228}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 204, 92}, 94}, {{31, 9, 231, 42, 0, 0, 166, 140, 220, 64, 41, 136, 213, 47, 154, 167}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 157, 172, 70, 28, 181, 174}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 170}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 36}, 94}, {{31, 9, 231, 42, 0, 0, 169, 234, 178, 13, 156, 249, 113, 45, 71, 176}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 107, 159, 52, 1}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 197, 218, 23, 60}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 120}, 94}, {{31, 9, 231, 42, 0, 0, 33, 49, 7, 90, 0, 226, 231, 248, 20, 200}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 222}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 193, 220, 112, 81, 83, 214, 42, 230}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 56, 118, 183, 208, 119, 248, 213, 130}, 94}, {{31, 9, 231, 42, 0, 0, 210, 61, 50, 40, 86, 159, 0, 31, 250, 156}, 94}, {{31, 9, 231, 42, 0, 0, 0, 119, 135, 78, 17, 11, 0, 48, 247, 69}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 189, 251, 27, 205, 253, 206, 47, 208, 242, 3}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 243}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 18, 15, 149, 26, 78, 243, 67}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 113, 148, 184, 85, 145, 107, 68, 106}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 172, 117, 6, 208, 54, 72}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 191, 172, 159, 66}, 94}, {{31, 9, 231, 42, 0, 94, 70, 17, 160, 1, 60, 93, 17, 194, 73, 182}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 121, 47, 94, 10, 24, 57, 111, 4}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 121, 115, 225, 210}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 34, 215, 168, 55, 202, 65, 121, 129}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 106, 138, 247, 152, 254}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 8, 114}, 94}, {{31, 9, 231, 42, 0, 0, 0, 172, 164, 232, 105, 108, 151, 133, 67, 120}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 150, 1}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 200, 63, 131, 198, 220, 30, 164}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 40, 164, 73, 119, 90, 205, 172}, 94}, {{31, 9, 231, 42, 0, 0, 0, 47, 199, 189, 91, 143, 81, 253, 229, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 35, 112, 68, 107, 227, 161, 214, 181}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 219, 78, 217, 42, 99, 81, 13}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 152, 144}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 219}, 94}, {{31, 9, 231, 42, 0, 181, 180, 57, 252, 219, 155, 61, 229, 26, 160, 203}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 74, 194}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 54, 82, 208, 19, 237, 69}, 94}, {{31, 9, 231, 42, 0, 0, 0, 196, 227, 97, 63, 54, 49, 77, 66, 74}, 94}, {{31, 9, 231, 42, 0, 0, 160, 246, 94, 99, 116, 53, 101, 186, 170, 183}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 181, 109, 250, 196, 114, 154, 244}, 94}, {{31, 9, 231, 42, 0, 0, 131, 235, 211, 229, 9, 240, 242, 167, 148, 43}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 127, 231, 229, 253, 93, 8, 85, 110}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 61, 136, 213, 189}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 251, 112}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 224, 5}, 94}, {{31, 9, 231, 42, 0, 0, 187, 115, 188, 59, 175, 121, 55, 91, 163, 140}, 94}, {{31, 9, 231, 42, 0, 0, 0, 145, 106, 54, 83, 89, 198, 75, 167, 193}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 132, 88, 43, 94, 86, 202, 53, 218}, 94}, {{31, 9, 231, 42, 0, 0, 0, 143, 188, 141, 63, 157, 41, 244, 182, 147}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 34}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 156, 89, 97, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 236, 31}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 62, 159, 10, 112, 143}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 86, 133, 214, 112, 47, 52, 191, 1}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 214, 153, 246, 46, 146}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 57}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{31, 9, 231, 42, 0, 0, 0, 110, 52, 186, 32, 254, 73, 207, 2, 53}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 94}, {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 160, 147, 37, 161}, 94}, {{31, 9, 231, 42, 0, 0, 0, 230, 32, 236, 121, 136, 10, 127, 138, 137}, 94}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 94, 142, 154, 19, 204, 114, 205}, 241}, {{108, 144, 205, 39, 215, 26, 96, 115, 71, 107, 3, 18, 249, 158, 159, 89}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 127, 246}, 241}, {{108, 144, 205, 39, 215, 26, 96, 3, 169, 59, 202, 191, 63, 78, 66, 241}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 90, 26, 225, 87}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 213, 215, 122, 56, 253}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 15, 10, 113, 136, 183}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 193, 9, 234, 62, 155, 121, 49, 162}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 50, 50}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 35, 187, 19, 41, 248, 62}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 20, 62}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 192, 228}, 241}, {{108, 144, 205, 39, 215, 26, 96, 11, 51, 199, 180, 239, 91, 249, 198, 112}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 168, 237}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 40, 230, 151, 242, 54}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 92, 210, 54, 51}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 64, 212, 92, 98, 29, 244, 73}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 247, 57, 119, 195, 132, 244, 164}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 163, 187, 213, 27, 40, 46}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 109, 200, 99, 141, 41, 207}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 55, 202, 244, 151, 19, 238, 173}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 41, 211, 79, 29, 17, 69}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 177, 138, 112, 234, 115, 207}, 241}, {{108, 144, 205, 39, 215, 26, 96, 171, 239, 176, 179, 86, 183, 13, 205, 245}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 94, 88, 96, 181}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 113, 134, 216, 220}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 37, 196, 95, 97, 7, 36, 15}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 143, 117, 121, 252, 46, 83, 110}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 10, 71}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 151, 221}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 92, 64, 206, 226, 129}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 124, 129, 161, 6, 134, 84, 82, 127}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 79, 87, 151}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 204, 196, 242, 8, 245, 167, 227, 226, 122}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 225, 79}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 9, 245, 225, 142, 44, 43, 17}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 23, 21}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 146, 231, 1, 17, 239}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 240, 206, 9, 88, 3, 192, 40, 194}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 99, 224}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 32, 90}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 62, 219, 49, 131, 153, 48, 145}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 200, 202, 11, 87, 9, 154, 112, 228}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 26, 202, 63, 104, 136, 229}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 130, 50, 190, 223, 108, 1, 130, 59}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 33, 189, 226, 249, 89, 220, 236}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 160, 51, 127, 30, 112, 136, 209}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 49, 133}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 154, 159, 117}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 15, 255, 144, 187, 243, 208}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 213, 34, 109, 136, 195}, 241}, {{108, 144, 205, 39, 215, 26, 96, 227, 162, 137, 133, 9, 171, 196, 10, 34}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 14, 55, 198, 186, 146, 93}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 177, 180, 153, 126, 211, 180}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 82, 25, 152, 194, 86}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 148, 95, 52, 78, 230, 94, 76}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 129, 80, 240, 226, 116, 46, 91}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 219, 148, 114, 226}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 167, 53}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 157, 34, 235, 117}, 241}, {{108, 144, 205, 39, 215, 26, 96, 54, 159, 30, 53, 221, 128, 9, 61, 22}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 2, 73, 254, 19}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 3, 238, 135, 155, 40, 199, 229}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 225, 222, 140}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 225, 47, 109, 43, 33, 63}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 96, 221}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 241}, {{108, 144, 205, 39, 215, 26, 96, 98, 82, 211, 44, 165, 226, 4, 128, 176}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 49, 190, 32, 110, 99, 217, 159, 120}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 156, 144, 138, 233, 229}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 24, 154, 145, 24, 64, 140, 50, 212, 212}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 167, 114, 22, 92, 63, 172, 74}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 37, 110, 104}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 217, 193}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 91, 79, 183, 86, 37, 153, 33}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 239, 65}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 127, 67, 227, 92, 254}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 169, 13, 129}, 241}, {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 222, 212, 144, 44}, 241}, {{247, 217, 172, 0, 0, 0, 0, 17, 70, 130, 136, 120, 54, 96, 241, 39}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 38, 208}, 239}, {{247, 217, 172, 0, 244, 4, 22, 163, 92, 34, 165, 216, 210, 229, 132, 25}, 239}, {{247, 217, 172, 0, 0, 0, 0, 200, 164, 142, 253, 68, 223, 89, 208, 253}, 239}, {{247, 217, 172, 0, 0, 0, 110, 126, 45, 56, 107, 58, 85, 166, 159, 18}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 239}, {{247, 217, 172, 0, 0, 0, 101, 159, 79, 60, 162, 199, 249, 53, 72, 24}, 239}, {{247, 217, 172, 0, 198, 178, 30, 32, 62, 201, 123, 186, 47, 24, 39, 12}, 239}, {{247, 217, 172, 0, 119, 167, 172, 112, 35, 70, 129, 58, 143, 28, 91, 207}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 19, 32}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 49, 153, 201}, 239}, {{247, 217, 172, 0, 135, 69, 76, 85, 8, 18, 3, 20, 176, 102, 99, 113}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 254, 11}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 215, 127}, 239}, {{247, 217, 172, 0, 0, 0, 234, 182, 170, 172, 120, 205, 51, 119, 4, 127}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 42, 90, 31, 51, 239, 13}, 239}, {{247, 217, 172, 0, 0, 66, 84, 26, 169, 164, 39, 214, 218, 89, 119, 216}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 196, 170, 103, 139, 146, 200}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 71, 109}, 239}, {{247, 217, 172, 0, 0, 0, 109, 40, 63, 113, 60, 199, 107, 9, 21, 70}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 172, 51, 114, 48, 58}, 239}, {{247, 217, 172, 0, 0, 0, 0, 191, 52, 54, 164, 225, 233, 115, 128, 1}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 224, 14, 80, 85, 12, 9, 109}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 246, 246, 221, 133, 24, 218}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 20}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 194, 117, 41, 243, 198}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 164, 24, 137, 186, 50, 239, 133}, 239}, {{247, 217, 172, 0, 0, 0, 116, 224, 55, 9, 215, 81, 85, 42, 243, 169}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 19, 223, 14}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 97, 95, 213, 122, 201}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 209, 78, 192, 167, 173}, 239}, {{247, 217, 172, 0, 0, 67, 139, 166, 58, 172, 192, 221, 85, 204, 243, 133}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 193}, 239}, {{247, 217, 172, 0, 0, 21, 117, 75, 179, 223, 54, 111, 81, 6, 90, 179}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 96, 203}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 222}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 192, 89, 178, 151, 18, 57, 11, 53}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 135}, 239}, {{247, 217, 172, 0, 0, 0, 14, 88, 70, 156, 73, 101, 199, 254, 182, 171}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 171, 191, 251, 19, 150, 23, 66, 104}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 148, 103, 212, 70, 66}, 239}, {{247, 217, 172, 0, 0, 0, 210, 174, 74, 99, 31, 49, 7, 110, 246, 40}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 250, 194, 34, 30, 81, 162, 25}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 25, 82, 51, 79, 138}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 239}, {{247, 217, 172, 0, 0, 133, 69, 139, 192, 131, 178, 39, 126, 117, 127, 41}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 148}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 226, 137, 99, 7, 200}, 239}, {{247, 217, 172, 0, 0, 173, 158, 253, 29, 122, 71, 165, 59, 28, 255, 55}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 254}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 148, 175, 65, 2, 241, 135, 143, 103}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 181}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 167, 71, 145, 84, 102, 207, 82}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 119, 63, 23}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 244}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 227}, 239}, {{247, 217, 172, 0, 0, 0, 0, 176, 70, 21, 111, 6, 60, 106, 115, 148}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 27, 193, 127, 80, 137}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 188, 18, 102, 42, 115, 124, 114, 66}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 207, 165, 188, 166, 211}, 239}, {{247, 217, 172, 0, 0, 222, 144, 221, 86, 194, 99, 159, 11, 248, 62, 112}, 239}, {{247, 217, 172, 0, 248, 180, 246, 12, 207, 207, 191, 117, 217, 254, 201, 225}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 86, 164, 83, 175, 109, 202}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 0, 243, 120, 210, 177, 224, 191, 140, 128, 250, 72}, 239}, {{247, 217, 172, 0, 0, 0, 0, 67, 131, 121, 128, 43, 184, 90, 67, 187}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 252}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 36, 218, 250, 38, 239, 192}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 239}, {{247, 217, 172, 0, 189, 42, 175, 105, 241, 105, 189, 151, 23, 222, 9, 101}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 132, 151, 109, 151, 137, 184}, 239}, {{247, 217, 172, 0, 0, 147, 53, 69, 126, 162, 164, 106, 162, 96, 134, 141}, 239}, {{247, 217, 172, 0, 0, 59, 115, 190, 214, 30, 174, 191, 213, 149, 204, 210}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 69, 105}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 205, 135, 152, 113, 229, 160}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 58}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 168, 40, 9, 95, 241, 198, 125}, 239}, {{247, 217, 172, 0, 0, 0, 0, 83, 171, 199, 6, 5, 17, 201, 88, 246}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 72, 105, 244, 215, 31}, 239}, {{247, 217, 172, 0, 0, 0, 10, 96, 17, 157, 251, 4, 93, 208, 210, 11}, 239}, {{247, 217, 172, 0, 0, 0, 0, 16, 77, 213, 157, 94, 203, 90, 45, 28}, 239}, {{247, 217, 172, 0, 0, 223, 145, 197, 79, 194, 31, 143, 192, 36, 113, 9}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{247, 217, 172, 0, 0, 164, 65, 59, 55, 159, 14, 200, 26, 57, 233, 44}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 95, 1, 95, 215, 148}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 170, 158, 73, 197, 18, 207}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 6, 218, 132}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 103, 67, 166, 185, 69, 234, 113, 55}, 239}, {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 45}, 239}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 28, 166, 210}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 66, 13, 88, 252}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 115, 49, 216, 188, 51, 182}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 255, 68, 32, 84}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 245, 224, 150, 162, 14, 55, 175}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 7, 59, 17, 183, 16, 166}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 220}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 210, 62, 110, 217, 206, 139}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 67, 105, 146, 134, 163}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 187, 86, 137, 255, 221}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 208, 162, 188, 125, 229, 96, 56}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 101, 221, 65, 250, 132}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 99}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 150, 164, 169, 153, 147, 203}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 135, 206, 163}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 174, 197}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 236}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 193, 205, 50, 210, 67, 181}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 179, 116}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 159, 150, 17, 91}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 84, 220, 160, 224, 99, 230}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 206}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 152}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 233, 140, 187, 72, 13, 235}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 158}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 40, 158, 222, 35, 95, 125, 122}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 26, 50, 165, 71, 77, 21, 62}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 201, 103, 25, 171}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 153, 117, 55, 56, 218, 84}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 157, 75}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 6, 2}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 99}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 119, 200, 143, 66, 227, 112}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 27, 229, 181, 220, 242, 77, 137}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 40, 6, 28, 10, 168}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 70, 127, 3, 208, 149}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 218, 95, 143, 45, 57, 75}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 158, 236, 173}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 99, 249, 180, 104}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 136, 210}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 199, 44, 185, 243, 140}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 4}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 77, 1, 29}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 133, 233, 118, 124, 7, 56, 207}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 81, 237, 255}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 157}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 151, 102}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 190, 189, 209}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 8, 246, 161}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 151, 109, 121, 69}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 1, 222, 223}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 63, 120, 127}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 225, 37, 126, 100, 26, 225}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 142, 149, 147}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 5, 205, 221}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 200, 112, 72, 178}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 155, 113, 171}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 50, 200, 243}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 243, 57, 63, 50}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 241, 104}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 16, 195, 227}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 37}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 222, 137, 7, 8, 119, 54, 96}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 189, 238, 52, 76, 168}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 237, 167, 101, 184, 201, 203}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 14, 22, 13, 238, 147, 210, 208}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 94, 199}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 240, 87, 222}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 222, 164, 143, 12}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 109, 224, 234, 129}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 180, 52}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 13, 225, 203, 183, 220, 128}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 97, 136, 50, 44, 34, 29}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 33, 93, 65, 213, 85}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 49, 70}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 226, 94, 81, 128}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 173, 237, 223, 65}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 86, 27, 193, 194}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 74, 242, 23, 210, 46, 218, 229}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 112, 33, 25, 6, 128, 192}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 8, 241, 94, 102, 42}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 1, 193, 7}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 162, 131, 51}, 151}, {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 128, 103}, 151}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 115, 81, 177, 8, 86, 50, 58}, 137}, {{245, 112, 0, 0, 0, 16, 215, 156, 108, 221, 92, 108, 16, 199, 194, 113}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 130, 137}, 137}, {{245, 112, 0, 0, 0, 67, 135, 40, 77, 201, 46, 205, 117, 26, 200, 124}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 135, 4, 239, 76}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 60, 94, 96, 129, 177, 39}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 198, 62, 14, 207}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 74, 28, 77, 145, 75, 104}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 112, 242, 146, 246, 93, 28, 141}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 191}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 145, 139, 48, 251, 246, 177}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 52, 2, 164, 40}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 223, 158, 200, 54, 231, 51, 203, 191}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 166, 165, 223, 45, 151, 187, 92, 51}, 137}, {{245, 112, 0, 0, 0, 0, 0, 197, 5, 86, 228, 16, 172, 93, 70, 64}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 223}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 106, 83, 194, 95, 194, 174, 113, 21}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 137}, {{245, 112, 0, 0, 0, 0, 0, 159, 179, 176, 227, 15, 121, 235, 202, 80}, 137}, {{245, 112, 0, 0, 0, 0, 90, 227, 203, 141, 123, 177, 184, 236, 243, 32}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 203, 37, 129, 0, 60, 184, 170}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 188, 230}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 166, 237, 182, 70}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 0, 0, 0, 180, 123, 125, 115, 121, 7, 113, 29, 193, 126}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 99, 222, 133, 201, 45, 209}, 137}, {{245, 112, 198, 218, 144, 2, 16, 201, 29, 99, 27, 234, 107, 61, 88, 188}, 137}, {{245, 112, 0, 0, 0, 0, 0, 148, 69, 49, 42, 105, 73, 123, 40, 134}, 137}, {{245, 112, 0, 0, 0, 0, 1, 85, 155, 249, 241, 131, 86, 4, 65, 100}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 60}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 222, 116, 131, 62, 200, 123, 56}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 141, 234, 115, 57, 95, 201, 64, 196}, 137}, {{245, 112, 0, 0, 51, 147, 14, 245, 22, 208, 53, 106, 136, 127, 153, 156}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 117, 208, 227}, 137}, {{245, 112, 0, 0, 0, 0, 194, 85, 40, 222, 226, 90, 205, 52, 200, 205}, 137}, {{245, 112, 0, 90, 6, 188, 52, 134, 178, 202, 246, 130, 62, 155, 120, 111}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 0, 0, 102, 90, 157, 90, 103, 94, 8, 87, 57, 205, 69}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 134, 217, 23, 61}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 211, 234, 193, 195}, 137}, {{245, 112, 0, 0, 0, 212, 157, 132, 80, 195, 37, 8, 36, 211, 178, 99}, 137}, {{245, 112, 0, 0, 0, 0, 0, 120, 4, 227, 62, 82, 78, 113, 243, 166}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 253, 91, 9, 88, 198, 185}, 137}, {{245, 112, 0, 0, 0, 63, 157, 131, 36, 108, 198, 197, 149, 78, 52, 192}, 137}, {{245, 112, 0, 0, 0, 83, 79, 96, 58, 125, 209, 205, 49, 26, 167, 38}, 137}, {{245, 112, 0, 17, 57, 251, 226, 107, 229, 114, 44, 167, 152, 37, 229, 176}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 40, 163}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 253, 6, 224, 65, 7, 133, 120, 4, 50, 122, 165, 244, 88}, 137}, {{245, 112, 0, 0, 188, 162, 49, 233, 43, 204, 81, 96, 189, 77, 82, 60}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 226}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 137}, {{245, 112, 0, 0, 180, 139, 20, 120, 155, 76, 12, 197, 200, 191, 96, 41}, 137}, {{245, 112, 0, 0, 0, 0, 0, 114, 98, 129, 189, 216, 153, 246, 106, 22}, 137}, {{245, 112, 0, 0, 0, 25, 138, 238, 179, 172, 201, 67, 209, 25, 175, 130}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 105, 62, 106, 63}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 180, 121}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 214, 10, 165, 0, 79, 82, 157, 65}, 137}, {{245, 112, 0, 0, 0, 97, 148, 165, 48, 51, 229, 113, 104, 183, 104, 94}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 165, 253, 45, 47}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 215}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 182, 54}, 137}, {{245, 112, 0, 0, 16, 174, 66, 128, 92, 48, 168, 15, 14, 104, 129, 66}, 137}, {{245, 112, 0, 248, 144, 17, 33, 175, 84, 227, 35, 250, 24, 90, 116, 219}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 63, 234}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 125, 105}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 154, 169, 192, 180, 244, 166, 26, 185}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 255, 49, 155, 82}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 214}, 137}, {{245, 112, 0, 0, 0, 173, 147, 153, 111, 29, 227, 112, 10, 25, 159, 228}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 133, 81, 65, 145}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 214}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 137}, {{245, 112, 0, 0, 0, 0, 246, 73, 205, 79, 236, 50, 244, 204, 190, 38}, 137}, {{245, 112, 0, 0, 0, 0, 0, 40, 255, 128, 169, 185, 10, 4, 159, 67}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 125, 72, 88, 193, 215, 36, 20, 145}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 164, 178, 130, 1}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 0}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 191, 11, 154, 186, 99, 244, 27, 66}, 137}, {{245, 112, 154, 237, 29, 76, 120, 218, 37, 102, 157, 143, 35, 188, 156, 238}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 31, 217, 100}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 79, 114, 182}, 137}, {{245, 112, 0, 0, 19, 56, 17, 105, 143, 32, 50, 112, 193, 57, 91, 167}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 137}, {{245, 112, 0, 0, 0, 0, 0, 16, 51, 172, 241, 189, 77, 186, 152, 90}, 137}, {{245, 112, 0, 0, 0, 0, 0, 179, 169, 162, 30, 241, 21, 84, 245, 209}, 137}, {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 244, 63, 11, 224, 243, 230}, 137}, {{245, 112, 0, 10, 88, 209, 190, 151, 28, 97, 74, 160, 38, 83, 22, 170}, 137}, {{245, 112, 0, 0, 117, 111, 75, 146, 119, 170, 72, 179, 172, 127, 197, 45}, 137}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 43, 220, 58, 78, 17, 175, 14}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 109, 75, 193, 85, 75, 233}, 231}, {{44, 94, 138, 224, 168, 0, 0, 234, 8, 113, 40, 35, 21, 156, 24, 9}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 139}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 215, 60, 165}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 206, 23, 203, 34}, 231}, {{44, 94, 138, 224, 168, 0, 0, 149, 167, 233, 42, 58, 135, 167, 12, 191}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 56, 12, 186}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 216, 67, 147, 241, 166, 8, 191, 54, 175, 146}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 197}, 231}, {{44, 94, 138, 224, 168, 0, 39, 184, 253, 4, 23, 254, 253, 7, 211, 210}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 111, 110, 70, 51, 211, 178, 56, 119}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 124, 14, 209, 155, 20}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 218, 27, 43, 235, 225}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 219, 173, 157}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 20}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 29, 184, 73, 198}, 231}, {{44, 94, 138, 224, 168, 0, 114, 142, 102, 28, 130, 99, 236, 14, 87, 178}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 114, 241, 238, 149, 76, 234, 138}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 244, 225, 123, 98, 129, 170, 203}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 177, 241, 162, 210, 244, 67, 237, 41}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 133, 214, 116}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 81, 238, 146, 2}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 115, 239, 101}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 248, 31, 194, 6, 145}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 83}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 117, 232, 183, 18, 34}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 60, 75, 45, 169, 157, 28, 128, 199}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 190, 167, 190}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 184, 31, 184, 113}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 28, 34, 130, 152, 128, 2, 201, 130}, 231}, {{44, 94, 138, 224, 168, 0, 0, 64, 217, 205, 71, 57, 233, 195, 89, 188}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 150, 166, 50, 191, 149}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 234, 166, 68, 156}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 149, 236, 133, 92, 202, 154, 174, 123}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 7, 99, 70, 102}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 246}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 242, 34, 21, 5, 130, 214}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 47, 245, 62, 106, 201}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 212, 194, 212}, 231}, {{44, 94, 138, 224, 168, 0, 202, 153, 60, 89, 147, 157, 34, 132, 46, 119}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 125, 116, 77}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 179, 168, 180, 5, 220, 226, 34}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 164, 82, 93, 1, 60, 2, 155, 155, 172, 110}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 170, 195, 188, 93, 182, 193, 17}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 132, 86, 0, 98, 171, 69, 61}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 16, 124, 58, 163, 60, 24}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 90, 223, 148, 61, 139, 72, 252}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 82, 22, 176, 93, 40, 35, 216}, 231}, {{44, 94, 138, 224, 168, 0, 0, 253, 93, 85, 215, 200, 83, 174, 130, 19}, 231}, {{44, 94, 138, 224, 168, 0, 163, 0, 90, 129, 136, 163, 236, 204, 253, 121}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 103}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 7, 144, 35, 222, 21, 84}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 25, 217, 228, 87, 64, 199}, 231}, {{44, 94, 138, 224, 168, 0, 69, 94, 82, 167, 83, 238, 112, 17, 16, 139}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 242, 45, 175, 33, 5}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 198, 113, 223, 124, 159, 125, 225}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 78, 56, 97, 188, 204, 196, 107, 238, 249}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 217, 191, 211, 168, 229, 216, 212, 188}, 231}, {{44, 94, 138, 224, 168, 0, 216, 38, 61, 59, 22, 52, 66, 100, 213, 2}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 164, 176, 37, 58, 232}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 94, 228, 244, 162}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 201, 42, 92}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 82, 104, 244, 141, 103, 195, 7, 139}, 231}, {{44, 94, 138, 224, 168, 0, 0, 151, 4, 164, 207, 253, 14, 148, 221, 54}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 176, 191, 124, 69, 131}, 231}, {{44, 94, 138, 224, 168, 0, 0, 234, 255, 229, 30, 238, 127, 125, 89, 209}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 48, 146, 88, 243, 115, 54}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 115}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 235, 223, 233, 139, 182, 116, 141, 119}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 45, 31, 219, 9}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 241, 46, 17, 114, 58}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 211, 135, 131}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 116, 185, 228, 240}, 231}, {{44, 94, 138, 224, 168, 0, 55, 175, 94, 110, 75, 11, 73, 235, 243, 233}, 231}, {{44, 94, 138, 224, 168, 0, 80, 77, 188, 47, 232, 225, 159, 151, 129, 27}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 31, 86, 108, 72}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 194}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 220, 224, 151, 70, 25, 139, 2}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 56, 229, 249, 2, 125, 232, 169, 32}, 231}, {{44, 94, 138, 224, 168, 0, 134, 206, 38, 83, 103, 122, 160, 116, 71, 110}, 231}, {{44, 94, 138, 224, 168, 0, 0, 106, 164, 175, 206, 103, 65, 78, 173, 180}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 186, 148, 234, 91, 221, 240, 35}, 231}, {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 207, 200, 157, 122, 253}, 231}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 114, 52, 108, 236, 35, 129}, 11}, {{184, 221, 109, 135, 225, 32, 0, 165, 237, 2, 192, 37, 168, 82, 89, 43}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 29, 222, 182}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 90, 218, 196, 144}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 39, 56, 15, 23}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 11}, {{184, 221, 109, 135, 225, 32, 0, 142, 89, 161, 222, 56, 24, 89, 43, 206}, 11}, {{184, 221, 109, 135, 225, 32, 0, 199, 60, 45, 49, 225, 203, 115, 197, 6}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 164, 219, 16, 255, 27, 174, 102, 199}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 106, 170, 224, 54, 27}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 243, 203, 12, 252}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 171, 58, 144, 89, 137, 157, 120, 176}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 64, 184, 143}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 123, 14, 89, 12, 150, 223, 68, 225}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 225, 116, 8, 77, 102}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 39, 194, 216, 177}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 172, 116, 168}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 14, 163, 153, 231}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 186, 33, 250, 233, 87, 229, 220, 164}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 141, 109, 56}, 11}, {{184, 221, 109, 135, 225, 32, 0, 21, 232, 10, 190, 51, 175, 39, 136, 99}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 2, 113, 162, 44, 73, 240, 229, 185, 14, 35}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 238, 116, 219, 145, 24, 252, 106, 241}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 254, 223, 55, 107, 59, 140, 174}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 180, 117, 114, 76, 193}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 68, 152, 110, 152, 197, 167}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 124, 15}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 140, 36, 178}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 6, 130, 208, 81}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 226, 123, 134}, 11}, {{184, 221, 109, 135, 225, 32, 0, 88, 55, 218, 1, 237, 185, 228, 35, 127}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 191, 29, 50, 251, 65, 154, 23, 97}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 245, 156}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 190, 86, 107, 107, 90, 105, 241}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 149, 94, 187, 68, 84, 39, 128}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 54, 1, 61}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 53, 233, 230, 191, 27, 215, 226, 203}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 120, 16, 174, 157, 44, 174, 240, 145}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 241, 89}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 124, 191, 20}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 152, 130, 86, 25}, 11}, {{184, 221, 109, 135, 225, 32, 68, 14, 172, 203, 249, 250, 210, 234, 105, 37}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 37, 65, 205, 207, 105, 84}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 112, 59, 93, 178}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 160, 189}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 120, 26, 135, 178, 233, 150, 73}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 99, 229, 200, 4, 6, 63}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 245, 95, 3, 45, 47, 16, 187, 45, 204, 120}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 128, 148, 233}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 90, 84, 101, 111, 177, 57, 64, 242}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 207, 214, 22, 65, 134, 36, 195}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 199, 186, 208, 104, 89, 157, 170, 180}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 255, 8, 216, 31}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 168, 225}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 116, 167}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 249, 250, 84, 147, 224, 248, 94, 13, 229}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 231, 209, 34, 172, 120, 62, 65}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 137, 190, 106, 211, 128, 13, 59}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 171, 86, 219, 14, 132, 250, 96}, 11}, {{184, 221, 109, 135, 225, 32, 0, 123, 88, 255, 31, 115, 255, 23, 42, 17}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 89, 52, 9, 14}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 70, 222, 207, 148, 183}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 178, 193, 163, 231, 249}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 38, 167, 133}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 192, 251, 92}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 116, 224, 55, 0, 18, 253, 44, 3}, 11}, {{184, 221, 109, 135, 225, 32, 195, 167, 137, 244, 85, 140, 197, 183, 98, 49}, 11}, {{184, 221, 109, 135, 225, 32, 0, 184, 200, 206, 241, 17, 27, 40, 255, 164}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 40, 84}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 73, 68, 193, 184, 27, 225}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 39, 203}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 157, 173, 22, 251, 28, 48, 160, 168}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 198, 93, 123}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 116, 234, 139, 224, 223, 61}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 9, 93, 186, 51, 35, 146}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 100, 108, 77, 104, 247, 230, 179, 169}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 228, 60, 122, 179, 16, 248, 34}, 11}, {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 11}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 61, 198}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 243, 27, 46}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 67, 73}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 227, 183, 15}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 219, 212, 160}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 57, 6}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 253, 20, 61}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 8}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 144, 133, 233}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 240, 55}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 58, 21}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 230, 87}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 230, 134}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 1, 30}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 206, 81}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 205}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 165, 253}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 109, 213}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 187, 152, 119}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 167, 58}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 116, 67, 145}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 81, 73}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 230}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 148, 102, 46}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 14}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 240, 16}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 225, 221}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 247, 41}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 128}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 14, 188, 71}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 59, 19, 243}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 102, 122}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 220}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 91, 249}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 89, 94, 10}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 87, 122}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 144, 118, 209}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 59, 185, 77}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 106, 234, 16}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 253, 146}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 100, 63, 177}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 246}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 233, 101}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 178, 218, 12}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 100}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 43}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 241}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 15}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 92, 110, 188}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 72}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 44, 244, 101}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 111, 86, 144}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 177}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 112}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 144, 180, 230}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 219}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 26, 187, 117}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 55}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 2}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 144, 172, 146}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 208}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 205, 161, 1}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 173}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 185, 210}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 183, 234, 28}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 107, 173, 165}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 138}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 57, 103, 39}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 135, 16}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 141, 55}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 196}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 20}, {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 123, 185}, 20}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 221, 12, 9, 238, 86, 227}, 68}, {{48, 46, 0, 0, 0, 203, 57, 10, 203, 53, 37, 21, 38, 135, 219, 107}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 24, 7, 31, 193, 75, 35, 4, 12, 49}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 50, 145}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 69, 51, 198, 162, 79, 24, 143, 117}, 68}, {{48, 46, 0, 0, 0, 53, 137, 201, 30, 182, 226, 46, 244, 44, 2, 108}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 64, 71, 9}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 243}, 68}, {{48, 46, 0, 0, 0, 0, 0, 88, 9, 154, 103, 140, 199, 154, 56, 174}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 103, 211, 38}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 41}, 68}, {{48, 46, 0, 0, 0, 240, 104, 168, 105, 222, 152, 114, 158, 96, 47, 82}, 68}, {{48, 46, 0, 0, 41, 232, 124, 80, 44, 138, 212, 88, 30, 163, 245, 97}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 246, 233, 44, 42, 47, 154}, 68}, {{48, 46, 0, 0, 0, 0, 0, 66, 109, 105, 160, 227, 73, 115, 79, 8}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 11, 227}, 68}, {{48, 46, 0, 0, 43, 236, 82, 249, 86, 73, 148, 99, 192, 105, 171, 248}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 2, 106, 65, 35, 109, 237, 123}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 58, 163, 150, 74, 38, 97}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 207, 59}, 68}, {{48, 46, 0, 125, 144, 36, 245, 52, 16, 215, 101, 50, 86, 90, 174, 234}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 224, 214, 128, 135, 29, 39}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 181, 85, 79, 134}, 68}, {{48, 46, 0, 0, 0, 0, 17, 131, 198, 1, 198, 143, 184, 219, 45, 226}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 33, 81, 96, 168, 130, 4, 97}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 151, 102, 138, 15, 185, 153, 57}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 27, 188, 236, 176, 179, 217}, 68}, {{48, 46, 0, 0, 116, 146, 105, 243, 220, 65, 135, 172, 232, 254, 94, 235}, 68}, {{48, 46, 0, 0, 0, 0, 117, 158, 201, 11, 220, 138, 47, 129, 22, 54}, 68}, {{48, 46, 0, 0, 0, 125, 196, 95, 138, 163, 139, 43, 13, 209, 234, 162}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 121}, 68}, {{48, 46, 0, 0, 234, 190, 137, 169, 233, 69, 29, 47, 139, 174, 247, 193}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 25, 150}, 68}, {{48, 46, 0, 32, 117, 212, 4, 135, 137, 12, 80, 235, 244, 218, 24, 220}, 68}, {{48, 46, 0, 0, 0, 0, 4, 153, 35, 20, 103, 95, 103, 46, 104, 49}, 68}, {{48, 46, 0, 80, 96, 66, 255, 49, 58, 22, 51, 190, 86, 133, 2, 91}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 198, 190, 26, 122, 181, 164, 160, 33}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 237, 69, 174}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 33, 203, 239, 136, 196, 38, 33}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 36, 119, 210, 225, 0, 122, 22, 172}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 97, 131, 195, 188, 119, 111, 194, 41, 247, 206, 110, 90}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 96, 234}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 65, 216}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 59, 124, 3, 100, 232, 92, 192, 104}, 68}, {{48, 46, 0, 0, 0, 73, 106, 2, 23, 168, 61, 226, 209, 101, 74, 73}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 3, 159}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 5, 160, 38, 229, 82, 7, 134}, 68}, {{48, 46, 0, 0, 0, 224, 185, 122, 103, 45, 5, 135, 253, 75, 104, 61}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 123}, 68}, {{48, 46, 0, 171, 183, 104, 225, 119, 71, 116, 214, 125, 4, 212, 196, 60}, 68}, {{48, 46, 0, 0, 0, 212, 238, 204, 61, 38, 180, 65, 75, 151, 103, 158}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 211, 120, 217}, 68}, {{48, 46, 0, 252, 83, 64, 230, 127, 132, 71, 90, 128, 137, 71, 105, 50}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 5}, 68}, {{48, 46, 0, 174, 99, 251, 57, 123, 140, 15, 168, 97, 207, 204, 95, 186}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 51, 174}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 176, 146, 62, 129, 27, 138, 72}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 14, 173, 210, 18, 72, 153, 181}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 64, 9}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 156, 7}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 36, 29, 153, 224}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 163, 150, 224, 69, 182, 77, 91}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 125, 10, 165}, 68}, {{48, 46, 0, 0, 0, 0, 52, 190, 158, 222, 92, 224, 212, 221, 41, 156}, 68}, {{48, 46, 0, 0, 188, 4, 192, 199, 181, 179, 219, 201, 230, 209, 51, 247}, 68}, {{48, 46, 0, 0, 0, 0, 0, 105, 137, 118, 198, 128, 145, 238, 222, 172}, 68}, {{48, 46, 0, 0, 19, 36, 30, 15, 10, 98, 33, 152, 143, 174, 238, 92}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 219, 252}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44}, 68}, {{48, 46, 0, 0, 252, 24, 226, 107, 187, 136, 124, 129, 17, 216, 179, 66}, 68}, {{48, 46, 0, 0, 0, 0, 48, 72, 8, 128, 171, 223, 60, 14, 219, 95}, 68}, {{48, 46, 0, 0, 0, 0, 250, 49, 153, 251, 205, 24, 157, 184, 40, 214}, 68}, {{48, 46, 0, 0, 63, 169, 23, 150, 222, 127, 182, 9, 99, 153, 200, 50}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 244, 77}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 222, 9, 168, 70, 60, 52, 150, 204}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 250}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 85, 122, 128, 132, 204, 55, 234}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 6, 51}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 226, 159, 36}, 68}, {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 68}, {{48, 46, 0, 0, 0, 176, 165, 143, 144, 232, 106, 21, 154, 198, 153, 178}, 68}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 227}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 219, 171}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 95}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 95}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 74, 110}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 41, 220, 158}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 223}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 102, 207, 239}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 7, 131}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 55}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 229, 148}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 54, 146, 63}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 230}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 161}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 75, 165}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 238}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 214, 43}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 158, 209, 43}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 167, 28, 79}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 80, 107}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 239}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 147, 85}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 187, 212, 109}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 12, 201, 235}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 48, 142}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 171}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 244, 243}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 186}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 190, 17}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 89, 166}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 114, 158, 131}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 200, 41, 101}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 216, 243}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 97, 140}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 49}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 145}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 81, 46, 153}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 147, 45}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 42}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 190}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 228, 27}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 114, 152}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 19, 210}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 225}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 102, 115}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 225, 244}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 81, 28}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 152}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 162, 204}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 126, 226, 84}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 95}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 106}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 47}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 8}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 19, 5}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 190, 127}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 175}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 254, 68, 222}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 172, 98}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 141, 184, 199}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 49, 87}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 122, 66, 88}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 77}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 98, 157}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 107, 119}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 153}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 168}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 129}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 223, 220}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 246, 252}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 241}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 179}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 11}, 64}, {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 236, 132}, 64}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 167, 228, 61, 250, 115, 161}, 152}, {{121, 190, 90, 177, 128, 0, 29, 173, 80, 159, 106, 45, 17, 141, 39, 249}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 2, 167, 6, 9, 103, 151}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 117, 115, 170, 11, 56, 178, 47, 58}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 178, 13, 52, 129, 193, 144, 103}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 31, 157, 120, 159, 237, 254}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 66}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 138, 93, 100, 244, 64}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 67, 9, 103, 159}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 149, 51, 18, 115}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 12, 188, 2, 74, 47, 160, 135}, 152}, {{121, 190, 90, 177, 128, 38, 141, 144, 76, 74, 98, 166, 131, 96, 230, 74}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 166, 222, 10}, 152}, {{121, 190, 90, 177, 128, 163, 10, 156, 242, 15, 233, 185, 94, 143, 213, 106}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 9}, 152}, {{121, 190, 90, 177, 128, 0, 0, 75, 152, 100, 34, 79, 155, 166, 243, 167}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 251, 36, 122}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 94, 205, 68, 50, 185, 232, 208}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 160, 93, 50}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 244, 52, 29, 49}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 174, 197, 11, 57, 93, 246, 235}, 152}, {{121, 190, 90, 177, 128, 0, 197, 155, 80, 93, 84, 250, 225, 231, 114, 47}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 240, 43, 159, 76, 236, 28}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 16, 12, 129, 184, 33, 34, 215}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 233, 21, 14, 140, 107, 149, 62, 34}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 109, 0, 66, 220, 3, 42, 14}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 15, 102, 59, 96, 78, 69, 73, 137}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 234}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 234, 188, 210, 210, 91, 110, 213, 25}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 211}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 55, 12, 217, 144, 63, 97, 201, 246, 77}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 61, 139, 101, 238, 155}, 152}, {{121, 190, 90, 177, 128, 0, 0, 40, 140, 195, 47, 110, 12, 203, 165, 158}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 94, 161, 216, 82, 152, 82}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 183}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 31}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 56, 156, 170, 227}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 179, 99, 163, 75, 88}, 152}, {{121, 190, 90, 177, 128, 0, 185, 211, 101, 132, 208, 218, 143, 207, 176, 75}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 64, 12, 3, 142}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 113, 146, 155, 81, 84}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 9, 178, 224, 45, 78, 190, 170, 234, 137, 144}, 152}, {{121, 190, 90, 177, 128, 121, 29, 170, 2, 181, 182, 180, 210, 111, 136, 113}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 219, 231, 176, 200, 63, 152, 48, 50, 186, 206}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 74, 154, 183, 159, 44}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 75, 92, 20, 60, 59, 97}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 93, 86, 248, 116}, 152}, {{121, 190, 90, 177, 128, 0, 144, 254, 238, 149, 123, 210, 180, 181, 81, 153}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 245, 121, 239, 243, 89, 21}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 240, 241, 50, 137, 31, 173}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 126, 1, 129, 3, 142, 233}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 192}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 254, 167, 193, 246, 210}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 70, 249, 233, 236, 0, 8, 148, 107, 47, 92}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 133}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 45, 42, 203, 190, 49, 49, 142, 198, 223}, 152}, {{121, 190, 90, 177, 128, 9, 5, 34, 99, 38, 213, 40, 78, 182, 32, 67}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 140, 175, 107, 242, 177, 24, 168, 147}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 157, 251, 128, 245, 56, 112, 71, 197}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 28, 140, 38, 121, 239, 176, 176}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 160, 115, 217, 94, 205, 14, 91}, 152}, {{121, 190, 90, 177, 128, 0, 0, 43, 13, 86, 12, 143, 83, 6, 178, 240}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 112, 143, 19, 127, 176, 159}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 13, 231, 97, 150, 78}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 22, 234, 29}, 152}, {{121, 190, 90, 177, 128, 0, 0, 23, 222, 114, 179, 88, 146, 255, 73, 14}, 152}, {{121, 190, 90, 177, 128, 0, 247, 106, 22, 194, 178, 25, 87, 152, 28, 230}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 24, 84, 75, 182, 84}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 106, 166, 38}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 58, 82, 199, 14, 111, 67, 0, 176, 174}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 134, 254, 213}, 152}, {{121, 190, 90, 177, 128, 0, 0, 96, 89, 129, 56, 241, 56, 249, 230, 29}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 100, 168, 25, 124, 147, 220, 249, 237}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 11, 92, 222}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 171, 180, 194, 156, 68, 124, 209}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 181, 86, 254, 179}, 152}, {{121, 190, 90, 177, 128, 0, 0, 163, 132, 185, 208, 149, 181, 250, 53, 173}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 80, 69, 20, 131, 12, 208, 203, 218}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 240, 106, 180, 157, 126, 62}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 246, 155, 99, 235, 242}, 152}, {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 152}, {{121, 190, 90, 177, 128, 232, 225, 126, 152, 199, 252, 102, 48, 92, 166, 253}, 152}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 218, 47, 253}, 218}, {{128, 0, 105, 170, 78, 198, 254, 172, 85, 253, 0, 12, 220, 175, 2, 190}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 170}, 218}, {{128, 0, 0, 0, 0, 171, 43, 71, 250, 17, 10, 217, 114, 131, 185, 65}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 224}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 227, 128}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 250, 126, 177, 193, 152, 38, 198}, 218}, {{128, 0, 0, 0, 0, 0, 189, 118, 93, 198, 146, 79, 9, 46, 39, 39}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 248, 170, 23, 229, 90}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 15, 40, 255, 148, 26, 217, 207}, 218}, {{128, 0, 0, 0, 0, 0, 0, 5, 225, 228, 118, 255, 215, 75, 158, 161}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 72, 209}, 218}, {{128, 0, 0, 0, 0, 35, 68, 160, 138, 56, 248, 43, 10, 176, 161, 75}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 113, 136, 90, 181}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 50, 202, 107, 250, 31, 60, 250, 209}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 19, 197, 23, 178, 116}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 78, 165, 77, 184, 212, 13, 200, 54, 164, 124}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 174, 66, 41, 8, 104}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 211, 175, 168, 19}, 218}, {{128, 0, 92, 72, 42, 195, 226, 217, 197, 101, 102, 64, 48, 11, 201, 241}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 218}, {{128, 0, 0, 0, 0, 0, 0, 26, 80, 55, 106, 181, 167, 63, 228, 120}, 218}, {{128, 0, 0, 0, 47, 9, 169, 243, 253, 46, 166, 87, 216, 20, 189, 112}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 230, 123, 57, 246, 212}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 143, 197, 213, 29, 104, 170, 11}, 218}, {{128, 0, 0, 0, 0, 104, 192, 232, 136, 206, 72, 92, 143, 185, 17, 200}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 173, 138}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 155, 124, 255, 88, 44, 225, 82, 248, 33, 218, 179, 5, 124, 228}, 218}, {{128, 0, 0, 244, 150, 69, 108, 70, 129, 203, 74, 128, 19, 27, 209, 206}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 73, 201, 80, 101, 135}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 100, 112, 109, 197, 231, 132, 92}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 223, 217, 134, 172}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 247, 30, 66}, 218}, {{128, 0, 0, 0, 0, 0, 0, 150, 94, 210, 225, 3, 201, 88, 62, 2}, 218}, {{128, 0, 0, 95, 47, 162, 171, 96, 82, 3, 234, 153, 3, 4, 157, 164}, 218}, {{128, 0, 0, 0, 0, 174, 68, 163, 250, 89, 181, 222, 16, 112, 2, 183}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 51, 122, 90, 157, 180, 107, 51}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 90, 109, 77, 95}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 11, 180, 103, 255, 156, 143, 5, 225}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 159, 244, 21, 67, 255, 126, 249}, 218}, {{128, 0, 0, 211, 158, 243, 40, 116, 233, 224, 200, 12, 212, 36, 162, 53}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 206, 62, 169, 247, 218, 191, 28, 183}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 126, 67, 227, 36, 5, 216, 163}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 168, 17, 111, 118, 225}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 42, 93, 32, 0, 144}, 218}, {{128, 0, 0, 0, 0, 0, 181, 17, 44, 80, 242, 56, 151, 92, 131, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 216, 149, 71, 172}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 129}, 218}, {{128, 0, 0, 0, 0, 0, 0, 85, 60, 44, 195, 139, 40, 1, 151, 56}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 83, 89, 105, 133, 32, 102, 5, 32, 163, 251, 207, 204, 123}, 218}, {{128, 0, 0, 0, 0, 0, 0, 46, 193, 219, 33, 227, 0, 5, 43, 65}, 218}, {{128, 0, 7, 248, 56, 33, 123, 188, 122, 129, 236, 78, 128, 223, 91, 202}, 218}, {{128, 0, 0, 0, 180, 243, 16, 76, 251, 16, 48, 196, 116, 121, 38, 48}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 146, 102, 159, 186, 162, 239, 77, 178}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 126}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 141, 154, 27, 19, 221, 58, 10, 95, 176, 138, 189}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 75, 193, 255, 120}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 233, 131, 107, 60, 191, 159, 47, 111}, 218}, {{128, 0, 0, 0, 0, 0, 0, 194, 78, 239, 130, 204, 141, 62, 175, 56}, 218}, {{128, 0, 0, 0, 0, 0, 0, 137, 123, 24, 1, 132, 127, 148, 123, 92}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 109, 128, 155, 114}, 218}, {{128, 0, 0, 0, 223, 15, 169, 235, 103, 232, 208, 65, 92, 20, 221, 247}, 218}, {{128, 0, 0, 0, 46, 244, 114, 146, 119, 244, 99, 127, 53, 40, 69, 177}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 140, 234}, 218}, {{128, 0, 0, 0, 0, 215, 239, 186, 54, 202, 152, 149, 87, 25, 239, 182}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 123, 221, 85, 40, 55}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 195, 104, 126, 246, 163, 153, 159, 101}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 6, 168, 45}, 218}, {{128, 0, 0, 0, 0, 94, 5, 234, 133, 127, 51, 218, 2, 229, 208, 31}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 157, 68, 21, 87}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 218}, {{128, 0, 0, 107, 19, 226, 241, 122, 140, 50, 136, 100, 115, 179, 249, 119}, 218}, {{128, 117, 120, 215, 217, 15, 117, 20, 145, 69, 219, 214, 223, 203, 204, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 199, 201, 41, 19, 53, 124, 63, 160, 13}, 218}, {{128, 0, 0, 0, 0, 0, 130, 171, 170, 38, 27, 156, 200, 141, 237, 69}, 218}, {{128, 0, 0, 0, 0, 107, 220, 39, 144, 172, 19, 185, 193, 162, 75, 112}, 218}, {{128, 0, 120, 171, 236, 163, 184, 180, 144, 77, 244, 247, 196, 170, 71, 13}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 23, 9, 11, 127, 51, 157, 169, 55}, 218}, {{128, 0, 0, 0, 0, 113, 241, 18, 102, 175, 4, 188, 209, 250, 206, 78}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 27, 245, 129, 57, 225}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 8, 139, 32, 202, 188, 224, 14, 65, 199}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 22, 239, 246, 66, 10, 118, 183, 147}, 218}, {{128, 0, 0, 0, 174, 23, 0, 95, 125, 139, 158, 187, 20, 184, 243, 27}, 218}, {{128, 0, 0, 0, 121, 221, 16, 246, 5, 129, 173, 44, 146, 41, 146, 164}, 218}, {{128, 0, 0, 0, 0, 0, 61, 51, 100, 95, 181, 66, 233, 161, 59, 239}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 45, 252, 128, 228, 58}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 123, 101, 242, 175}, 218}, {{128, 79, 39, 87, 254, 32, 62, 112, 197, 249, 194, 4, 224, 251, 2, 35}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 60}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 192, 117, 168, 33, 23, 139, 84, 29, 62, 239, 176, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 218}, {{128, 0, 0, 0, 255, 115, 252, 1, 54, 206, 61, 77, 249, 153, 3, 146}, 218}, {{128, 0, 0, 0, 0, 0, 249, 175, 87, 143, 123, 172, 206, 223, 49, 66}, 218}, {{128, 0, 252, 234, 64, 192, 199, 37, 90, 76, 33, 172, 217, 53, 235, 232}, 218}, {{128, 0, 0, 0, 0, 49, 132, 153, 110, 165, 133, 121, 52, 197, 79, 183}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 60, 130, 86, 35, 96, 194, 128}, 218}, {{128, 0, 0, 108, 80, 201, 104, 122, 249, 49, 32, 164, 233, 174, 255, 60}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 90}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 183, 171, 148, 70, 15, 186, 226}, 218}, {{128, 0, 0, 0, 0, 0, 0, 24, 86, 18, 251, 199, 251, 17, 4, 20}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 252, 87, 57, 98, 122}, 218}, {{128, 0, 87, 45, 136, 4, 221, 237, 240, 23, 125, 29, 116, 31, 12, 107}, 218}, {{128, 0, 0, 0, 0, 212, 83, 17, 50, 160, 168, 17, 223, 67, 112, 177}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 212, 58, 184, 102, 136, 211, 247, 95}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 36, 109, 22, 222}, 218}, {{128, 0, 0, 176, 5, 48, 82, 71, 246, 165, 196, 137, 134, 177, 207, 89}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 131, 105, 193, 125}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 2, 114}, 218}, {{128, 0, 0, 0, 90, 29, 119, 108, 143, 76, 198, 135, 181, 131, 116, 16}, 218}, {{128, 0, 0, 120, 148, 94, 123, 45, 66, 58, 16, 10, 29, 130, 53, 26}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 69, 86, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 137, 110, 54, 104, 161, 131, 101, 252, 29}, 218}, {{128, 0, 0, 0, 65, 253, 235, 1, 128, 210, 180, 33, 112, 146, 242, 211}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 150, 91, 201, 226, 109, 31, 26}, 218}, {{128, 0, 0, 0, 0, 0, 190, 118, 207, 240, 160, 187, 173, 4, 219, 229}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 93, 134, 225, 104}, 218}, {{128, 0, 0, 0, 0, 0, 0, 188, 27, 159, 104, 126, 215, 52, 128, 95}, 218}, {{128, 0, 0, 0, 0, 0, 37, 19, 199, 217, 108, 148, 147, 35, 98, 62}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 194, 250, 5, 2}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 185, 22, 231, 126}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 42}, 218}, {{128, 0, 0, 76, 135, 170, 16, 158, 78, 182, 15, 19, 175, 212, 50, 144}, 218}, {{128, 0, 0, 0, 0, 157, 176, 47, 66, 66, 63, 53, 229, 188, 12, 111}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 34, 252, 222, 98}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 148, 153, 254}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 218}, {{128, 0, 0, 0, 117, 56, 77, 186, 202, 239, 241, 34, 71, 229, 82, 186}, 218}, {{128, 0, 0, 0, 0, 26, 24, 126, 157, 201, 156, 242, 245, 4, 147, 58}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 189}, 218}, {{128, 0, 0, 130, 100, 102, 244, 242, 33, 78, 56, 214, 66, 155, 22, 108}, 218}, {{128, 0, 0, 0, 0, 0, 245, 173, 88, 107, 101, 157, 155, 24, 144, 160}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 247, 51}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 41, 77, 160}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 138, 227, 108, 172, 205, 26, 163}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 70, 204, 231, 165, 184}, 218}, {{128, 35, 120, 52, 159, 210, 136, 210, 182, 227, 151, 9, 210, 38, 92, 113}, 218}, {{128, 0, 0, 0, 83, 233, 90, 135, 201, 34, 201, 121, 38, 61, 15, 132}, 218}, {{128, 0, 0, 0, 0, 0, 0, 233, 222, 97, 157, 27, 244, 26, 140, 140}, 218}, {{128, 0, 0, 0, 0, 0, 116, 50, 198, 114, 25, 31, 219, 64, 104, 204}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 184, 0, 38, 133, 158, 155, 251, 73}, 218}, {{128, 0, 197, 113, 199, 165, 3, 124, 138, 50, 193, 49, 94, 207, 120, 118}, 218}, {{128, 0, 0, 0, 220, 99, 54, 107, 229, 116, 227, 197, 153, 174, 254, 57}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 156, 243, 52, 149}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 112, 129, 183, 1}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 236}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 65, 13, 121, 10, 223, 140, 145, 56}, 218}, {{128, 0, 0, 0, 0, 0, 154, 155, 156, 130, 69, 54, 13, 241, 252, 82}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 231, 216, 161, 253, 79, 233, 71}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 107, 141, 64}, 218}, {{128, 0, 0, 21, 166, 170, 104, 28, 200, 75, 235, 68, 224, 13, 192, 33}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 176, 97, 181}, 218}, {{128, 0, 0, 0, 0, 0, 5, 64, 185, 27, 175, 68, 78, 233, 169, 41}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 12, 138, 237, 118, 9}, 218}, {{128, 0, 0, 0, 0, 0, 0, 193, 38, 228, 49, 94, 122, 196, 225, 111}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 122, 212, 38, 32, 245, 176, 197, 76}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 203, 47}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 84, 172, 218, 254, 34, 112, 133, 189}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 203, 208, 149, 161, 146}, 218}, {{128, 0, 0, 0, 109, 103, 168, 147, 154, 126, 135, 187, 62, 136, 24, 251}, 218}, {{128, 109, 162, 128, 148, 64, 177, 14, 66, 193, 250, 157, 33, 52, 127, 28}, 218}, {{128, 155, 71, 143, 62, 97, 44, 100, 93, 69, 84, 224, 156, 155, 159, 166}, 218}, {{128, 0, 247, 109, 199, 205, 158, 8, 220, 98, 46, 197, 64, 97, 219, 130}, 218}, {{128, 0, 0, 0, 0, 0, 0, 236, 195, 134, 165, 146, 218, 98, 94, 221}, 218}, {{128, 0, 0, 0, 126, 121, 58, 155, 69, 4, 16, 180, 196, 38, 50, 244}, 218}, {{128, 0, 0, 15, 41, 242, 125, 128, 161, 67, 84, 84, 62, 23, 99, 131}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 112, 101, 229}, 218}, {{128, 0, 0, 249, 166, 125, 48, 110, 205, 238, 193, 217, 39, 186, 229, 178}, 218}, {{128, 0, 0, 146, 205, 172, 151, 215, 32, 224, 200, 2, 254, 157, 167, 82}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 45, 196, 222, 80}, 218}, {{128, 0, 0, 0, 0, 181, 240, 8, 117, 242, 102, 180, 121, 223, 67, 86}, 218}, {{128, 69, 202, 249, 2, 28, 230, 51, 126, 173, 170, 32, 116, 210, 112, 99}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 148, 108}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 154}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 228, 59, 187, 81, 207, 190, 105, 171}, 218}, {{128, 0, 0, 0, 127, 71, 186, 33, 243, 104, 15, 71, 157, 234, 17, 198}, 218}, {{128, 0, 0, 221, 254, 155, 191, 204, 131, 14, 109, 161, 2, 194, 149, 168}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{111, 214, 0, 0, 121, 4, 28, 7, 123, 41, 115, 31, 91, 141, 163, 57}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 150, 196, 105, 123}, 58}, {{111, 214, 0, 0, 160, 27, 218, 189, 24, 30, 6, 92, 255, 26, 66, 64}, 58}, {{111, 214, 0, 0, 0, 0, 205, 73, 2, 28, 70, 201, 109, 194, 223, 107}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 78, 94, 0, 161, 227, 128}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 180, 115, 5, 111, 219, 190}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 136, 255, 253}, 58}, {{111, 214, 0, 84, 33, 209, 98, 179, 219, 211, 49, 55, 225, 2, 68, 47}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 153, 27, 30}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 168, 59}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 41, 104, 106, 215, 208, 43, 113}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 80, 196, 149, 165, 89, 107, 211}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 53, 222}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 176, 207, 238, 230, 70, 65}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 114, 34, 119, 193, 137, 2, 137}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 27, 253, 169, 102, 29, 233}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 114, 121, 178, 219, 117, 93, 138, 43, 171, 88, 74}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 23, 51, 204, 239, 1, 19, 145, 93}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 110, 231, 147, 216}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 187, 28, 99}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 15, 212, 45, 219, 89, 47, 104, 209, 41, 91, 93, 227, 172}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 184, 35, 198, 57}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 234, 160, 168, 16, 143, 5}, 58}, {{111, 214, 0, 0, 0, 110, 186, 64, 3, 181, 38, 144, 57, 142, 28, 203}, 58}, {{111, 214, 0, 128, 201, 47, 142, 164, 65, 229, 67, 128, 52, 140, 91, 42}, 58}, {{111, 214, 0, 149, 1, 225, 152, 3, 211, 143, 210, 119, 121, 50, 15, 43}, 58}, {{111, 214, 0, 0, 174, 165, 145, 43, 197, 13, 168, 4, 164, 133, 183, 110}, 58}, {{111, 214, 0, 0, 0, 161, 163, 153, 148, 250, 64, 143, 11, 167, 149, 108}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 121, 238, 48, 158}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 136, 196, 27, 78, 94, 172}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 16, 154, 93, 245, 245, 185, 96, 97}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 235}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 175}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 58}, {{111, 214, 0, 0, 0, 0, 237, 241, 172, 161, 134, 139, 153, 134, 50, 113}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 31, 113, 23, 52, 57, 104, 107}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 207, 221, 206, 245, 165, 214, 128}, 58}, {{111, 214, 0, 38, 192, 11, 225, 46, 223, 68, 85, 193, 158, 8, 105, 185}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 120, 253, 221, 213, 216, 169, 204, 135}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 72}, 58}, {{111, 214, 0, 0, 0, 236, 97, 132, 109, 176, 208, 243, 18, 113, 110, 88}, 58}, {{111, 214, 0, 0, 0, 17, 158, 0, 99, 33, 27, 184, 150, 202, 11, 43}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 216, 196, 114, 220, 158, 75, 156}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 133, 122, 54, 138, 138, 52}, 58}, {{111, 214, 0, 0, 141, 183, 37, 88, 162, 96, 31, 110, 180, 96, 41, 118}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 245, 20, 22}, 58}, {{111, 214, 0, 0, 0, 113, 211, 51, 72, 188, 104, 26, 18, 116, 101, 211}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 131, 101, 204}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 221, 113, 77, 199, 250, 49, 51, 227, 237, 135, 197, 23, 173}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 144, 232, 93}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 58}, {{111, 214, 0, 182, 151, 225, 12, 194, 139, 150, 138, 73, 145, 193, 226, 96}, 58}, {{111, 214, 0, 0, 0, 0, 174, 72, 103, 0, 191, 214, 184, 6, 21, 88}, 58}, {{111, 214, 0, 0, 0, 64, 84, 225, 209, 133, 109, 69, 250, 97, 229, 8}, 58}, {{111, 214, 0, 64, 254, 142, 56, 17, 182, 220, 232, 197, 16, 103, 148, 75}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 9, 82, 100, 223, 168, 115}, 58}, {{111, 214, 0, 0, 0, 0, 0, 140, 13, 95, 23, 244, 4, 107, 50, 244}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 126, 131, 16, 43, 93, 17, 189, 79}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 58}, {{111, 214, 0, 0, 0, 0, 199, 142, 10, 47, 204, 66, 90, 50, 159, 132}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 2, 34, 182}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 163, 133, 73, 223, 230, 18, 62}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 242, 82, 99}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 73, 131, 165, 171, 233, 148}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 94, 35, 2}, 58}, {{111, 214, 0, 0, 0, 239, 41, 243, 129, 222, 121, 177, 222, 208, 190, 96}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 198}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 101, 180, 84, 146}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 236, 245, 195, 219, 72, 17, 236}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 48, 194}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 114, 131, 109, 8}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 11, 105, 201, 117, 134, 8, 51, 119}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 161, 169, 148, 46, 216, 22, 14, 25}, 58}, {{111, 214, 0, 151, 19, 146, 225, 171, 26, 192, 198, 239, 221, 143, 55, 172}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 29, 2, 215, 49, 24, 65, 60, 133}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 236, 45, 73, 214}, 58}, {{111, 214, 0, 0, 0, 0, 173, 92, 11, 16, 28, 231, 41, 35, 68, 233}, 58}, {{111, 214, 0, 16, 197, 51, 107, 111, 46, 102, 171, 254, 130, 181, 116, 224}, 58}, {{111, 214, 0, 0, 144, 33, 9, 41, 37, 48, 230, 32, 210, 28, 106, 219}, 58}, {{111, 214, 0, 156, 30, 176, 90, 110, 99, 70, 167, 102, 162, 213, 164, 171}, 58}, {{111, 214, 0, 0, 15, 108, 115, 240, 223, 111, 213, 96, 90, 83, 183, 113}, 58}, {{111, 214, 0, 99, 115, 10, 224, 140, 81, 50, 188, 128, 61, 24, 197, 73}, 58}, {{111, 214, 0, 0, 0, 0, 0, 61, 81, 189, 237, 180, 27, 6, 173, 167}, 58}, {{111, 214, 0, 0, 34, 200, 139, 60, 210, 60, 235, 103, 240, 128, 5, 36}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 186, 138, 39, 183, 229, 113, 214, 153}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 166, 23, 234, 33, 232, 18}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 44, 182, 132}, 58}, {{111, 214, 0, 0, 0, 97, 127, 13, 211, 39, 119, 90, 166, 32, 5, 252}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 242, 199, 184, 232}, 58}, {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 97}, 58}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 178, 75, 221, 23, 87, 225}, 254}, {{162, 23, 52, 64, 0, 150, 186, 146, 135, 28, 50, 114, 13, 119, 74, 91}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 174, 174, 145, 162, 41, 57, 242}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 89, 36, 233, 136, 189, 169, 56}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 149, 221, 125, 26, 16}, 254}, {{162, 23, 52, 64, 0, 0, 70, 162, 48, 65, 135, 151, 64, 42, 127, 32}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 21}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 33, 207, 109, 84}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 180, 237, 247, 164, 125}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 221, 10, 82, 176, 104, 238, 137}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 44, 253, 138, 58, 204, 64}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 30, 58, 100, 218, 66, 81, 120}, 254}, {{162, 23, 52, 64, 3, 5, 236, 208, 10, 156, 199, 169, 205, 56, 247, 115}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 103, 48, 216, 163, 25, 172, 152, 227}, 254}, {{162, 23, 52, 64, 0, 0, 0, 90, 15, 115, 41, 61, 63, 150, 77, 56}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 36, 119, 82, 90, 189, 138}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 73, 38, 184, 158, 145, 108}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 118, 69, 35, 139}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 76, 234, 240, 7, 167, 236, 28}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 40, 106, 31, 172, 147, 51, 49, 203}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 136, 196, 247, 23}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 198, 35, 189, 71, 4}, 254}, {{162, 23, 52, 64, 0, 0, 0, 87, 58, 136, 60, 215, 204, 76, 101, 238}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 53, 250, 124, 232, 45}, 254}, {{162, 23, 52, 64, 0, 0, 39, 88, 218, 207, 225, 143, 251, 181, 33, 182}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 71, 176, 119, 71, 232}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 43}, 254}, {{162, 23, 52, 64, 0, 0, 0, 243, 148, 76, 46, 28, 233, 88, 28, 151}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 44, 141, 14, 193}, 254}, {{162, 23, 52, 64, 162, 117, 222, 113, 71, 246, 123, 153, 149, 92, 40, 19}, 254}, {{162, 23, 52, 64, 0, 0, 199, 166, 204, 224, 186, 156, 58, 35, 220, 190}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 177}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 126, 57, 75, 89, 5, 23, 91}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 108}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 161, 22, 142, 55, 179, 38, 100}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 128, 34, 226, 88, 132, 114}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 66, 1}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 26, 217, 51, 23, 239, 231, 28, 161}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 195, 92, 11, 177}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 184}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 16, 188, 90, 207, 179, 14}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 55, 157, 5, 16, 80, 91, 186, 139}, 254}, {{162, 23, 52, 64, 0, 0, 0, 130, 53, 194, 124, 66, 20, 222, 128, 213}, 254}, {{162, 23, 52, 64, 0, 0, 219, 235, 90, 240, 174, 119, 169, 119, 77, 100}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 250, 160, 52, 158, 5, 182, 113, 89}, 254}, {{162, 23, 52, 64, 0, 165, 54, 36, 174, 59, 157, 53, 12, 10, 55, 139}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 114, 69}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 124, 22}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 170, 8, 191, 12, 224, 221, 17, 145, 113}, 254}, {{162, 23, 52, 64, 0, 0, 245, 175, 70, 120, 225, 142, 234, 113, 155, 196}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 142, 71, 233, 193}, 254}, {{162, 23, 52, 64, 0, 0, 13, 252, 129, 239, 206, 246, 96, 81, 244, 250}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 157, 203, 193, 133, 5, 21, 238}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 34, 54, 111, 184, 195, 121, 240}, 254}, {{162, 23, 52, 64, 0, 0, 52, 106, 3, 77, 90, 117, 193, 157, 144, 83}, 254}, {{162, 23, 52, 64, 0, 0, 0, 216, 76, 47, 177, 134, 182, 145, 74, 253}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 6, 93, 113, 119, 229, 177, 66, 17}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 248, 62, 10, 219, 144, 247}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 70, 140, 10, 10, 81, 96, 149, 137}, 254}, {{162, 23, 52, 64, 0, 161, 103, 184, 176, 79, 74, 35, 116, 127, 241, 249}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 170, 76, 76, 103, 95, 230, 65, 115, 73}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 235, 74, 53, 144, 61, 179, 104, 9}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 120, 149, 113, 247, 236}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 45, 246, 51, 228, 57}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 208, 219, 8, 43, 134, 136, 48}, 254}, {{162, 23, 52, 64, 0, 0, 0, 121, 153, 108, 5, 63, 92, 25, 82, 139}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 155, 122, 8, 77, 200}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 87, 51, 126, 195, 231, 143, 211}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{162, 23, 52, 64, 0, 0, 0, 72, 176, 59, 156, 6, 39, 226, 254, 164}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 131, 176}, 254}, {{162, 23, 52, 64, 167, 246, 183, 187, 82, 175, 187, 18, 253, 184, 254, 62}, 254}, {{162, 23, 52, 64, 0, 0, 0, 31, 212, 254, 26, 194, 223, 65, 219, 165}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 242, 66, 242, 63, 200}, 254}, {{162, 23, 52, 64, 93, 246, 189, 72, 230, 19, 114, 168, 61, 27, 81, 13}, 254}, {{162, 23, 52, 64, 44, 148, 49, 122, 151, 253, 31, 108, 233, 205, 84, 218}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 58, 140, 246, 154, 203, 195}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 253, 153, 253, 149, 46, 113, 146}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 33, 169, 136, 42, 234, 140, 237, 235}, 254}, {{162, 23, 52, 64, 0, 0, 125, 128, 235, 235, 122, 10, 97, 142, 148, 219}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 3, 50, 95, 75, 43, 224}, 254}, {{162, 23, 52, 64, 73, 81, 136, 7, 128, 150, 39, 103, 111, 162, 207, 25}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 55, 54, 165, 248, 102, 153, 52, 17}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 144, 154, 1, 18, 115}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 222, 154, 16, 11, 140, 242, 195}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 196, 220, 11, 157, 101, 101}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 111, 75, 36, 150}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 29, 0, 39, 124, 164, 113, 45}, 254}, {{162, 23, 52, 64, 0, 0, 0, 110, 202, 160, 210, 99, 245, 2, 134, 145}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 254}, {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 254}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 242}, 148}, {{76, 103, 44, 79, 0, 0, 106, 178, 10, 117, 75, 248, 93, 202, 19, 151}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 36, 133, 31, 134, 25, 161, 232, 90, 80}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 33, 81, 225, 245}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 245, 40, 220, 50, 119, 42}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 218, 137, 0, 88}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 172, 27, 233, 42, 36, 253, 86, 58}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 214, 7, 71, 5, 230}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 45, 245, 192, 150, 30, 220, 164}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 210, 11, 136, 212, 67}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 154, 20, 134, 220}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 66}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 95, 103, 207, 4, 161, 246, 78, 218}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 41, 207, 196, 60, 204, 203}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 177, 241}, 148}, {{76, 103, 44, 79, 0, 0, 53, 211, 139, 32, 189, 242, 211, 197, 126, 126}, 148}, {{76, 103, 44, 79, 0, 0, 0, 255, 224, 228, 126, 217, 229, 13, 62, 103}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 27}, 148}, {{76, 103, 44, 79, 0, 0, 85, 112, 190, 25, 51, 19, 143, 155, 253, 144}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 169, 20}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 33}, 148}, {{76, 103, 44, 79, 0, 0, 0, 27, 155, 204, 24, 95, 251, 120, 84, 54}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 228, 156, 48, 77, 4}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 214, 69}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 99, 104, 240, 80}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 95, 188}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 41, 237, 182, 136, 205, 98}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 108, 108, 181, 226, 237, 23}, 148}, {{76, 103, 44, 79, 0, 134, 143, 171, 252, 222, 15, 165, 216, 80, 214, 239}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 237, 190, 210, 22, 150, 211, 158}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 167, 127, 177, 141, 200}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 28, 8, 221, 226, 77, 217}, 148}, {{76, 103, 44, 79, 0, 0, 196, 15, 168, 69, 88, 226, 231, 120, 112, 217}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 145, 40}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 123, 128}, 148}, {{76, 103, 44, 79, 0, 0, 0, 95, 70, 169, 153, 9, 175, 162, 45, 199}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 126, 42}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 59}, 148}, {{76, 103, 44, 79, 0, 0, 0, 247, 245, 42, 185, 140, 34, 155, 239, 226}, 148}, {{76, 103, 44, 79, 0, 242, 5, 86, 63, 6, 194, 111, 12, 25, 91, 96}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 187, 156}, 148}, {{76, 103, 44, 79, 0, 0, 101, 5, 105, 99, 13, 196, 44, 63, 84, 132}, 148}, {{76, 103, 44, 79, 0, 0, 0, 175, 66, 185, 182, 253, 23, 18, 74, 84}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 138}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 22, 15, 223, 218, 134, 32, 224}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 243, 141, 62, 209}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 228, 107, 50, 115, 79, 243, 163, 53}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 132, 33, 195, 215, 112, 165, 170, 215, 156, 85}, 148}, {{76, 103, 44, 79, 0, 0, 142, 16, 233, 208, 193, 39, 70, 207, 126, 80}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 188, 230, 187, 10, 120, 46, 207}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 144, 116}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 145, 230, 16, 184, 231, 210, 64}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 171, 26, 93, 188, 220, 150, 180}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 136, 168, 238, 88, 78, 90, 54}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 147, 91, 33, 2, 80, 184, 141, 181}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 234, 134, 105, 74, 83, 191, 234, 233, 45, 225}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 61, 191, 199, 54, 212}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 49, 230, 201, 79, 80, 141, 21}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 44}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 197, 43, 89, 212, 214, 235, 201, 131, 86, 142}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 106, 206, 24, 227, 215, 138, 198, 247, 175, 95}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 229, 122, 88, 151, 198}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 93, 69}, 148}, {{76, 103, 44, 79, 0, 0, 45, 136, 59, 44, 163, 253, 176, 122, 89, 79}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 51, 187}, 148}, {{76, 103, 44, 79, 0, 90, 41, 142, 40, 3, 230, 126, 119, 185, 240, 62}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 213}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 132, 34, 50, 164, 162, 44, 67, 241}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 222}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 79, 100, 76, 239, 225}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 52, 75, 187, 217}, 148}, {{76, 103, 44, 79, 0, 0, 0, 222, 172, 122, 190, 47, 158, 140, 13, 197}, 148}, {{76, 103, 44, 79, 0, 0, 98, 77, 172, 126, 98, 89, 164, 24, 27, 60}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 29}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 197, 224, 61, 241, 179}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{76, 103, 44, 79, 0, 80, 159, 112, 49, 18, 246, 69, 72, 49, 78, 182}, 148}, {{76, 103, 44, 79, 0, 0, 0, 120, 216, 83, 143, 228, 57, 199, 63, 243}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 88, 123, 142, 229, 216, 215, 24}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 226, 107}, 148}, {{76, 103, 44, 79, 0, 0, 0, 0, 87, 226, 46, 153, 199, 187, 188, 162}, 148}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 76}, {{39, 232, 237, 103, 191, 188, 36, 0, 236, 22, 156, 13, 228, 251, 121, 235}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 88, 58}, 240}, {{39, 232, 237, 103, 191, 188, 36, 142, 12, 227, 71, 95, 170, 55, 245, 59}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 44, 239, 48, 39, 88}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 168, 189, 238, 20}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 68, 57}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 71, 161, 239, 15, 11, 127, 125, 217}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 167, 152, 113}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 19, 230, 28, 72, 11, 139, 74}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 114, 58, 55, 28, 204, 85, 184, 24}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 200, 213, 211}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 221, 205}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 15, 224, 166, 84, 85, 58, 44}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 36, 82, 118, 95, 213, 56}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 33, 130}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 9, 1}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 233, 166, 218}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 160, 103}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 244, 250, 239, 242}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 91, 219, 170, 180, 179, 139}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 126, 30}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 237, 203, 146, 229, 183, 112, 218, 195}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 228, 2}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 131, 233, 234, 233, 36}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 162, 32, 10, 197, 44}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 98, 41, 115, 5, 154, 251, 206, 5}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 173, 190, 170, 132, 53}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 229, 224, 203, 120, 57, 1, 212, 196}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 110, 140, 231, 100}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 240, 133, 151, 252, 57, 194, 177}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 13, 78, 9}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 47, 39, 151, 34}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 173, 129, 196, 163, 142, 155, 141}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 40, 43, 213, 221, 173, 159, 140, 190}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 216, 206}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 51, 198, 1, 53, 233, 177, 167}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 220, 190, 48}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 144, 116, 6, 87, 13, 114, 50, 121}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 25, 181, 3, 68, 208, 3, 197}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 13, 16, 61, 236, 78, 189}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 64, 87, 26, 78}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 83, 58, 36, 42, 168, 163, 150, 53}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 139, 50, 76, 87, 250, 96, 207}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 227, 27}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 25, 24}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 237, 179, 88, 69, 48, 98}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 92, 229, 95}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 42, 249}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 77, 181, 50}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 238, 96, 33, 153}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 129, 120, 38, 123}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 206, 177, 154, 221, 231, 230, 184, 174}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 76, 206, 238, 76, 231, 57, 70, 146}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 175, 17}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 39, 110, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 214, 178, 185, 199}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 183, 47, 28, 66, 139, 48, 36, 165}, 240}, {{39, 232, 237, 103, 191, 188, 36, 98, 157, 36, 241, 194, 132, 67, 123, 114}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 218, 74, 34}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 122, 191, 142, 129, 133, 37, 146}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 105, 157, 49, 81, 251, 137, 206, 30}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 46, 44, 41, 222, 26, 194}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 161, 125, 155, 240, 118, 147}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 57, 155, 6, 163, 219}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 13, 213, 249, 161}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 128, 188, 35, 224, 222, 210}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 7, 44, 115, 0, 64}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 191, 201, 28, 221}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 225, 245, 156, 184, 174, 170, 231, 66}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 112, 109, 205, 62, 172, 72, 122}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 94, 208, 61, 222, 183, 88}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 140, 224}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 205, 170, 59}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 185, 198, 62}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 82, 174}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 225, 113, 148, 162}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 47, 222, 79, 26, 65, 110, 178}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 226, 176, 22, 213, 49, 92, 90}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 247, 103, 147}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 116, 210, 56, 112, 100}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 151, 135, 223, 129, 41, 48}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 89, 190, 224, 33}, 240}, {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 206, 248}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 139, 155, 44}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 218, 11, 237}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 114, 5, 58, 58}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 198, 11, 255, 218, 14, 27}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 3, 173, 59, 80, 27, 226, 218}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 144, 157}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 174, 14, 193}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 199, 11, 243, 168, 252, 241, 134, 3}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 118, 239}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 117, 145, 175, 81}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 159, 171, 83, 146, 201, 102, 85, 94}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 203, 118, 177, 36, 187, 118}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 196, 177, 102, 199, 237}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 77, 196, 98, 32}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 34, 45}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 111, 202, 156, 25}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 72, 108, 163}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 247, 51, 20, 252}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 246, 204, 205, 108, 228, 165, 83}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 96, 113, 149, 32, 200, 162, 248, 66}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 241, 124, 114, 20, 95}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 200, 0, 21, 211, 114}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 15, 4, 241, 25}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 49, 77, 73}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 159, 74, 60, 149}, 33}, {{20, 231, 89, 210, 167, 173, 80, 166, 29, 162, 32, 235, 136, 216, 24, 179}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 4, 50, 78, 204, 23, 2, 59, 90}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 185, 229}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 142, 138, 218, 162}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 158, 199, 211, 240, 4, 125, 56, 107}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 6, 7}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 194, 222, 0, 195, 225}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 137, 21, 152, 17, 157, 162}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 117, 94}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 154, 32}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 172, 133, 97, 52, 141}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 19, 15, 255}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 62, 133, 86, 130}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 78, 104, 140, 88, 27, 143, 181, 160}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 151, 160, 150, 155, 253, 43}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 135, 43, 220, 108, 160, 211}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 225, 71}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 142, 253, 188, 27, 147, 93, 43, 132}, 33}, {{20, 231, 89, 210, 167, 173, 80, 41, 129, 87, 79, 183, 126, 45, 218, 116}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 125, 218, 190, 136, 198, 136, 180, 113}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 91, 201, 10, 126, 132, 184, 99}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 217, 126}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 74, 180, 22, 62, 239, 125, 28}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 33}, {{20, 231, 89, 210, 167, 173, 80, 86, 67, 188, 15, 6, 167, 26, 70, 36}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 35, 9, 193}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 247, 151, 38, 107}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 246, 212, 193, 189, 178, 138, 135}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 211, 212, 2, 149, 202, 219, 211}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 138, 208, 247, 38, 54}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 33, 121, 176, 243, 216, 147, 104}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 66, 145, 42, 176, 4, 64, 30, 14}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 215, 30, 91, 242, 255, 72}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 47, 84}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 77, 25, 215, 39, 117, 39, 194}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 250, 38}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 109, 146}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 9, 169, 121, 84, 65, 180}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 93, 38, 143, 150, 26, 123, 236}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 190, 104, 148, 34}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 196, 133, 139}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 220, 208, 235, 4, 58, 14, 243, 103}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 45, 221, 162, 105, 55, 230, 211}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 153, 203, 245, 163, 180, 96, 217, 55}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 214, 103, 169, 162, 216, 154, 202}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 233, 44, 10}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 175, 167}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 202, 161, 34, 139, 227, 201}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 254, 27}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 175, 214}, 33}, {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 119, 233, 149, 201}, 33}, {{125, 67, 198, 128, 0, 51, 236, 50, 245, 53, 235, 175, 239, 223, 210, 197}, 47}, {{125, 67, 198, 128, 0, 123, 130, 151, 79, 15, 162, 141, 183, 139, 116, 109}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 103}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 200, 182, 110, 217, 79, 65}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 83}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 61, 139, 195, 163}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 245, 175, 109, 154, 84, 107}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 155, 179, 57, 123, 236, 13, 72}, 47}, {{125, 67, 198, 128, 0, 176, 60, 244, 130, 230, 212, 183, 244, 127, 153, 122}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 191, 165, 129, 83, 121, 117, 200, 109}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 121, 164, 12, 224, 219, 157, 146}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 98}, 47}, {{125, 67, 198, 128, 0, 0, 0, 143, 114, 198, 133, 234, 130, 63, 196, 239}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 30, 175, 166, 221, 139}, 47}, {{125, 67, 198, 128, 0, 41, 219, 66, 241, 9, 37, 146, 173, 73, 28, 4}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 114, 193, 59, 113, 210, 165, 233, 22}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 143, 182, 47, 49, 74}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 155, 185}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 165, 228}, 47}, {{125, 67, 198, 128, 112, 21, 4, 158, 195, 45, 163, 62, 20, 100, 186, 5}, 47}, {{125, 67, 198, 128, 0, 0, 0, 211, 2, 25, 253, 94, 74, 109, 170, 38}, 47}, {{125, 67, 198, 128, 0, 0, 159, 153, 156, 168, 53, 238, 255, 146, 137, 29}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 4, 231, 171, 85, 109}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 231, 186, 10, 86, 24, 123, 200, 55}, 47}, {{125, 67, 198, 128, 140, 239, 17, 231, 130, 166, 2, 163, 83, 208, 173, 160}, 47}, {{125, 67, 198, 128, 0, 0, 95, 172, 121, 175, 29, 83, 8, 248, 194, 131}, 47}, {{125, 67, 198, 128, 0, 8, 88, 167, 92, 52, 230, 243, 136, 43, 79, 205}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 194, 145, 242, 6, 236, 41, 251}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 255, 73, 219, 185, 234, 37, 245}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 229, 34}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 12, 49}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 203, 248}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 97, 252, 211, 247, 47, 241, 153, 191}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 200, 77, 114, 204}, 47}, {{125, 67, 198, 128, 0, 0, 79, 128, 27, 62, 112, 234, 178, 121, 249, 226}, 47}, {{125, 67, 198, 128, 0, 116, 159, 77, 238, 160, 17, 236, 106, 118, 41, 77}, 47}, {{125, 67, 198, 128, 0, 0, 0, 49, 165, 62, 55, 25, 161, 106, 130, 130}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 147, 2, 180, 66, 19, 156, 155}, 47}, {{125, 67, 198, 128, 0, 168, 200, 112, 70, 206, 145, 101, 253, 239, 57, 158}, 47}, {{125, 67, 198, 128, 0, 0, 142, 93, 28, 245, 23, 128, 250, 95, 142, 45}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 111}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 110, 98, 113, 217, 155, 120, 230}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 206, 110, 72, 194, 185}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 194, 80, 227, 214, 74, 169, 232, 221}, 47}, {{125, 67, 198, 128, 0, 108, 79, 7, 96, 93, 204, 175, 199, 136, 30, 224}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 27, 129, 119, 241, 67}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 118, 209, 111, 44, 98, 98, 251}, 47}, {{125, 67, 198, 128, 0, 0, 0, 99, 156, 235, 243, 70, 8, 55, 245, 59}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 244}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 141, 24, 241, 193, 135, 206}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 24, 216, 15, 16, 151, 155, 153, 195}, 47}, {{125, 67, 198, 128, 0, 0, 121, 207, 72, 33, 10, 2, 156, 189, 247, 247}, 47}, {{125, 67, 198, 128, 0, 0, 69, 84, 217, 50, 169, 88, 186, 140, 13, 206}, 47}, {{125, 67, 198, 128, 214, 24, 110, 56, 93, 254, 217, 223, 3, 24, 22, 58}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 3, 107, 158, 73, 244, 214, 97, 208}, 47}, {{125, 67, 198, 128, 0, 0, 0, 185, 232, 236, 19, 253, 146, 149, 148, 215}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 177, 185}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 54, 224, 19, 143, 58, 82, 95}, 47}, {{125, 67, 198, 128, 0, 0, 0, 172, 113, 231, 218, 49, 51, 254, 70, 240}, 47}, {{125, 67, 198, 128, 127, 3, 105, 9, 142, 172, 73, 124, 196, 16, 4, 36}, 47}, {{125, 67, 198, 128, 0, 0, 0, 153, 134, 214, 8, 162, 253, 205, 17, 54}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 243, 232, 25, 139, 31, 211, 91}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 44, 239}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 237, 224, 201, 62}, 47}, {{125, 67, 198, 128, 193, 76, 184, 147, 146, 166, 231, 127, 33, 18, 32, 211}, 47}, {{125, 67, 198, 128, 0, 0, 0, 182, 122, 2, 44, 196, 226, 37, 232, 118}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 63, 150}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 123, 130, 2, 103, 121}, 47}, {{125, 67, 198, 128, 0, 0, 210, 18, 175, 3, 214, 18, 102, 22, 187, 103}, 47}, {{125, 67, 198, 128, 0, 0, 0, 127, 56, 47, 115, 46, 24, 200, 148, 189}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 144, 108, 131, 120, 194, 251}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 12, 192, 114, 130, 135, 172}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 198, 31, 46, 234, 211, 255}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 50, 125, 118, 154, 54, 42}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 42, 170, 112, 26, 123}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 39}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 60, 248, 73, 174, 194, 55, 132, 104}, 47}, {{125, 67, 198, 128, 0, 0, 0, 203, 14, 80, 114, 175, 109, 239, 187, 31}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 28, 244}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 254, 237, 13, 159, 168, 227, 235, 31}, 47}, {{125, 67, 198, 128, 50, 197, 56, 239, 139, 144, 243, 166, 221, 153, 107, 90}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 51}, 47}, {{125, 67, 198, 128, 0, 0, 19, 240, 125, 35, 174, 76, 57, 31, 74, 31}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 173, 0, 66, 107, 8, 40, 23}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 210, 92, 109, 199, 163, 32}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 214}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 97}, 47}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 123}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 98}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 126}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 97, 106}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 241}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 102}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 165}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 135}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 157}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 249}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 47}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 5}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 53}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 10}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 31, 80}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 238, 230}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 213}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 157}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 67}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 205}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 250}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 116}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 36}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 157, 231}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 105}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 255}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 88, 183}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 118}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 73, 128}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 130}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 64}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 175}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 23}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 158, 212}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 190}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 109, 33}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 214}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 174}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 203}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 183}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 23, 133}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 73}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 40}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 130, 172}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 206}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 191, 138}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 148}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 96}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 11}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 42}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 14}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 227}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 18}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 247}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 48, 134}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 90}, 41}, {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 252, 96}, 41}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 83}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 195, 167, 229, 0, 231}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 74, 212, 71}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 104, 16, 246, 32}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 192, 32, 4, 165, 46, 103, 106}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 167, 203, 226, 115, 126, 48, 97}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 22, 37, 52, 89, 222, 47}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 54, 233, 50, 108, 241, 231}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 112, 188, 199, 116}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 107, 205, 98, 184, 17}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 220, 46, 140, 183, 17, 50}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 190, 44, 105, 240, 40}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 160}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 202, 197}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 184}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 196, 73, 35, 53, 85}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 249, 252, 248}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 215}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 14, 4, 241, 138, 246, 164, 136}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 141, 244, 242, 32}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 36, 75, 10, 207, 99, 77}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 182, 228, 205, 84, 14, 132}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 150, 28, 21, 41, 142}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 107, 134, 3}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 112}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 140, 18, 0, 127, 2, 189, 86, 112}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 237, 110, 206}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 211, 113, 207}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 59, 51, 19, 1, 21}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 248, 91}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 33}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 252, 57, 103, 39}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 177, 220, 145, 147, 100, 88, 249}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 52}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 53, 76, 7, 96, 57, 23}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 58, 190, 228}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 224}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 107, 182, 78, 93}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 52}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 245, 179, 236, 109, 103, 157}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 73, 47, 133, 50}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 59, 63, 58, 159, 94, 215}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 194, 140, 14, 69}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 76}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 188, 123, 140, 179, 172}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 195}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 113, 184, 207, 15, 222}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 116, 140, 238, 179, 194, 219}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 133, 173, 234, 10, 86}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 47, 233, 224, 141, 105}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 135, 245}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 34, 220, 113, 163, 1}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 64, 11, 120}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 50, 209}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 169, 68, 76, 239, 234, 104, 183}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 243, 187, 243, 56, 155}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 200, 184, 75, 31, 251, 150, 209, 86}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 58, 158, 160, 7, 130, 197}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 154, 242, 156, 107, 159, 26}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 8, 210, 33, 182}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 216, 144, 10}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 166, 99, 53, 72}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 112, 201}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 195}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 152, 146, 100, 3, 22, 59, 206}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 163}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 254, 172, 108, 78, 197, 84}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 123, 12, 20, 132, 33, 104, 252, 224}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 242, 120, 116, 224, 184}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 74, 15}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 81, 90, 150, 192, 166, 6, 85}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 252}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 197, 157}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 172, 245}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 111}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 228, 202, 24}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 101, 80, 152, 37, 44, 123, 170}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 105}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 65}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 70, 155, 46, 118, 133, 196}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 43}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 216, 62, 179}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 170, 217, 141}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 160, 213, 211, 57, 92}, 72}, {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 86}, 72}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 251, 74, 117, 181, 138, 180, 43, 77}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 95, 166}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 171, 70, 221, 173}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 72, 25}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 8, 153, 79, 221, 45, 149}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 124, 25, 103, 228, 100, 66, 189, 72, 213}, 43}, {{85, 181, 241, 127, 3, 44, 0, 220, 182, 154, 28, 237, 182, 42, 77, 85}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 114, 184, 209}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 228, 0, 189, 153, 157, 229, 180}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 125, 16}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 127, 80, 141, 82, 7}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 243, 81, 80, 199, 141}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 9, 183, 69, 158, 66, 233, 111}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 220, 94, 35, 251, 104}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 22, 195, 83, 232, 255, 120, 106, 211}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 182, 20, 113, 254, 132, 201}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 201, 246, 223, 234, 143}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 240, 88, 162, 175, 138, 160, 145, 109}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 119, 196, 139, 163, 216, 215, 184, 24}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 254, 51, 206, 91, 133, 56, 252, 71}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 30, 250, 231, 206}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 85, 241, 93, 255, 55}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 52, 190, 220, 98}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 180, 147}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 74, 242}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 106, 41, 108, 84, 168, 7, 24, 170}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 175, 141}, 43}, {{85, 181, 241, 127, 3, 44, 0, 119, 61, 102, 102, 186, 116, 102, 4, 122}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 68, 163, 19}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 119, 195, 248, 106}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 64, 230, 11, 34, 182}, 43}, {{85, 181, 241, 127, 3, 44, 115, 251, 62, 149, 150, 149, 81, 206, 10, 12}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 119, 38, 167, 103, 41, 209, 82, 227}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 175, 174, 128, 236, 97, 19, 113}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 63, 238, 215}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 215, 5, 143, 3}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 153, 69, 56, 96, 68, 44, 7}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 146, 69, 162, 195, 69, 50, 101, 185}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 118, 155, 180, 201, 159, 100, 14, 122}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 182, 53, 141, 44, 116, 161, 96, 55}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 155, 130}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 25, 63}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 98, 219, 149, 225, 66, 107}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 154, 133, 70, 10, 11, 146, 85, 202}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 195, 222, 136, 247, 124, 47, 23, 90}, 43}, {{85, 181, 241, 127, 3, 44, 0, 22, 222, 244, 73, 49, 72, 223, 31, 236}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 113, 175, 252, 21}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 134, 18, 159}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 43}, {{85, 181, 241, 127, 3, 44, 0, 218, 223, 225, 244, 210, 150, 26, 104, 236}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 88, 240, 186}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 13, 152, 56, 207}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 84, 241, 8, 190, 169, 37}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 151, 47, 121, 48, 53, 3, 68, 229, 51}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 56, 154, 141, 52, 210}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 48, 146, 108}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 208, 47, 162, 64, 40, 176, 141, 78}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 160, 137, 96, 169, 89, 188, 183}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 193, 105, 80}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 183, 85, 0, 110}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 245, 52, 196, 98, 196, 255}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 32, 44, 14, 189, 250, 211}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 199, 187, 100, 173, 201, 48}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 71, 224, 240, 150, 53, 238, 36}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 62, 149, 79}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 100, 176, 36, 67, 165, 127, 220}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 117, 163, 89, 227, 180, 133, 86, 132, 15}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 140, 235, 246, 49, 20, 163}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 173, 11, 172, 98, 46}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 92, 73}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 147, 8, 35}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 234, 220, 42, 44}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 201, 112, 209, 1, 78, 149, 33, 84}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 71, 194, 204}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 214, 34, 111, 50, 20, 74, 33, 166}, 43}, {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 43}, {{85, 181, 241, 127, 3, 44, 0, 250, 232, 174, 149, 130, 250, 135, 253, 182}, 43}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 22, 171, 129, 71, 184, 231, 14}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 81, 133, 6, 84, 146, 99, 6}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 162, 77, 88, 119}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 58, 61, 160, 206, 150}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 126, 192, 250}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 194, 84}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 211, 146, 29, 191, 138}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 213, 125, 204}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 198}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 91}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 183, 44, 51, 16, 110, 120}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 154, 230, 17, 184}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 24, 185}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 240, 139, 214, 60}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 206, 139, 243}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 226, 254}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 93, 96, 250, 240}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 42, 129}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 4, 180, 80, 2}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 153, 178, 222}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 126, 167, 185}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 43}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 100, 161, 60}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 134, 212, 224, 248, 130}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 242, 78, 181, 65, 111}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 134, 134, 0, 50}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 213, 179, 88, 226, 160}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 220, 94, 169}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 1, 205, 201, 78, 163}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 206, 27, 3, 115, 174, 248}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 156, 80, 100}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 85, 8, 44, 60, 49, 124}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 86, 236, 172, 54, 206}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 88, 64, 171, 132, 59, 214, 3}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 34, 199, 146, 126, 178, 137}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 240, 86}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 65, 22}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 244}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 161}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 118, 221, 2, 177}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 217}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 181, 6, 94, 18}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 129}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 170}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 1, 157, 35, 205, 154, 128}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 9, 74, 209, 21, 102, 26}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 248, 63, 2, 205, 176}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 180, 183, 123}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 35, 232, 250, 3, 191}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 68, 130, 251, 75, 149, 126, 222}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 18, 143, 52, 2}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 175, 167, 63, 80, 7}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 206, 235}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 177, 20, 126, 64, 152}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 170, 233, 190}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 33, 177, 248, 20, 226, 42, 64}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 181, 147}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 97, 14, 164, 52, 50, 86}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 89, 105, 39, 125}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 176, 247, 74, 7, 184, 2, 174}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 21, 114, 251, 68, 67}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 185, 201, 113, 236, 192, 7}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 87, 176, 112, 51}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 27, 92, 34, 132, 22, 71}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 64, 41, 70, 78}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 98, 4, 102, 136, 208}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 178}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 220, 162, 162, 250, 78, 107}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 245, 80, 48, 72, 232}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 100, 121, 222, 107, 191, 245}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 36, 117, 56, 35, 205}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 152, 218, 211, 162, 208, 81}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 182, 207}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 14, 84, 235, 54, 179, 117, 44}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 236, 190, 198, 182, 103, 246, 196}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 236, 82, 97}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 109, 35, 145, 125}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 155, 51, 243, 91}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 251, 190, 117, 138}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 103, 214, 146, 8, 142, 184, 104}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 202, 123, 53, 85}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 146, 2, 147, 62, 72, 17}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 15, 235, 39, 104, 235, 63}, 26}, {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 25, 140, 18}, 26}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 196, 118, 233, 149}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 113, 136, 60, 156, 221}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 83, 229, 95, 229, 224, 137, 60}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 204, 27}, 139}, {{0, 143, 160, 184, 162, 192, 167, 216, 55, 204, 199, 49, 207, 154, 113, 176}, 139}, {{0, 143, 160, 184, 162, 192, 0, 202, 148, 117, 218, 189, 147, 230, 111, 81}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 110, 19, 42, 88, 62, 181}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 117, 78, 191, 241, 11}, 139}, {{0, 143, 160, 184, 162, 192, 0, 72, 216, 225, 38, 13, 201, 214, 98, 89}, 139}, {{0, 143, 160, 184, 162, 192, 5, 236, 22, 190, 99, 222, 168, 78, 215, 209}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 168, 79, 218, 86}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 139}, {{0, 143, 160, 184, 162, 192, 0, 245, 151, 56, 40, 219, 88, 228, 46, 24}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 147, 97}, 139}, {{0, 143, 160, 184, 162, 192, 189, 117, 254, 89, 111, 110, 155, 213, 245, 139}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 139}, {{0, 143, 160, 184, 162, 192, 0, 200, 13, 115, 249, 128, 153, 69, 253, 92}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 95, 116, 65, 195, 160, 76, 61, 174}, 139}, {{0, 143, 160, 184, 162, 192, 97, 227, 187, 148, 219, 178, 107, 66, 13, 212}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 112, 128}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 59, 43, 176, 121, 136, 116, 206, 169, 254}, 139}, {{0, 143, 160, 184, 162, 192, 0, 45, 209, 74, 21, 76, 186, 0, 191, 43}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 28, 223, 225, 200}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 172, 202, 23, 197, 37, 148}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 139}, {{0, 143, 160, 184, 162, 192, 0, 30, 145, 148, 208, 120, 151, 150, 254, 249}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 139}, {{0, 143, 160, 184, 162, 192, 102, 44, 118, 226, 215, 231, 29, 232, 33, 176}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 172, 89, 7, 104, 169}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 158, 177, 35}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 210, 194, 175}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 221, 148, 78, 174, 156, 53}, 139}, {{0, 143, 160, 184, 162, 192, 0, 140, 216, 245, 114, 169, 125, 221, 93, 217}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 31, 255, 169, 123, 172, 62, 151, 57}, 139}, {{0, 143, 160, 184, 162, 192, 0, 38, 81, 9, 172, 90, 194, 119, 246, 188}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 246, 79, 157, 102, 187, 177, 139, 111}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 145, 123}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 38, 228, 110, 241, 98, 72}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 139}, {{0, 143, 160, 184, 162, 192, 0, 126, 12, 30, 28, 30, 5, 51, 16, 4}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 139, 4, 4, 124}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 204, 164, 65}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 122, 150, 131, 207}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 160, 230, 201, 110, 68, 141, 194, 28, 112}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 34, 116, 44, 59, 134, 146}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 199, 23, 48}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 100, 97, 69, 129, 10, 151, 255}, 139}, {{0, 143, 160, 184, 162, 192, 59, 30, 142, 69, 244, 73, 185, 215, 192, 29}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 191, 207, 22, 153, 235}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 242, 91, 19}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 73, 225, 102, 242, 231}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 254, 21, 36, 243, 207, 85, 133}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 123, 230, 186, 148}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 229, 229, 191, 141, 14, 116, 52}, 139}, {{0, 143, 160, 184, 162, 192, 0, 158, 149, 65, 183, 240, 62, 137, 6, 70}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 82, 112, 24, 0, 209, 143, 28, 251, 226}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 38, 161, 96, 32, 66}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 224, 171}, 139}, {{0, 143, 160, 184, 162, 192, 0, 16, 162, 99, 151, 27, 38, 229, 150, 191}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 21, 5, 224, 101, 95, 204, 91, 53}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 215, 147, 145, 63, 75, 220, 98, 90}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 128, 0, 45, 209}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 88, 51, 160}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 225, 76, 166, 234, 52, 150, 15}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 183, 187, 153, 154, 11, 29, 158}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 168, 28}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 10, 114, 14, 211, 214, 27, 195, 250, 156, 134}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 139}, {{0, 143, 160, 184, 162, 192, 55, 124, 67, 78, 119, 67, 108, 4, 233, 4}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 161, 11, 3, 103}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 199, 35, 227}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 139}, {{0, 143, 160, 184, 162, 192, 208, 92, 246, 169, 99, 254, 203, 53, 184, 252}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 55, 201, 19}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 145, 63, 151, 79, 12}, 139}, {{0, 143, 160, 184, 162, 192, 23, 209, 206, 187, 170, 48, 187, 229, 169, 254}, 139}, {{0, 143, 160, 184, 162, 192, 0, 192, 133, 135, 36, 232, 156, 247, 224, 123}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 39, 165, 80, 82, 42}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 16, 74, 168, 58, 245, 247, 75}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 29, 124, 27, 249, 36}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 253, 55, 226, 211, 166, 124}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 13, 35, 68, 151, 54, 6, 60, 190}, 139}, {{0, 143, 160, 184, 162, 192, 0, 241, 71, 30, 21, 59, 122, 64, 204, 250}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 91, 71}, 139}, {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 139}, {{170, 24, 0, 0, 0, 0, 78, 106, 202, 236, 223, 135, 43, 67, 157, 56}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 170, 219, 114, 61}, 219}, {{170, 24, 0, 0, 69, 117, 217, 95, 180, 100, 219, 166, 22, 23, 228, 204}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 243, 67, 130, 232, 66, 69, 122, 167}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 60, 40, 106, 136, 158, 68, 167}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 205, 165, 88, 239, 56, 241, 130, 122}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 66, 202}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 190, 77, 119, 165}, 219}, {{170, 24, 0, 0, 84, 29, 49, 206, 146, 171, 238, 74, 203, 250, 57, 213}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 152, 51, 239}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 137, 174}, 219}, {{170, 24, 0, 0, 0, 0, 81, 6, 117, 184, 6, 199, 148, 52, 218, 85}, 219}, {{170, 24, 0, 47, 210, 240, 198, 120, 253, 242, 163, 162, 237, 26, 231, 77}, 219}, {{170, 24, 0, 0, 196, 162, 113, 51, 150, 156, 253, 29, 253, 175, 123, 190}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 201, 252, 159, 35}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 46, 245, 75, 88}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 161, 124, 151, 199, 241, 246, 79, 120}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 117, 104, 159}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 108, 255, 142, 224, 114, 28, 201, 90, 138, 11, 128, 137}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 219}, {{170, 24, 19, 76, 22, 171, 224, 78, 29, 172, 161, 88, 23, 96, 219, 29}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 163, 166}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 240}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 136, 239, 37, 153, 254, 210}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 85}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 102, 118, 127, 186, 166, 102, 45, 96}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 145, 92, 27, 108, 235, 34, 236, 141, 82, 172, 13, 153, 219, 95}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 32, 245, 80, 108}, 219}, {{170, 24, 48, 247, 31, 124, 139, 34, 199, 194, 50, 51, 116, 182, 23, 53}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 146, 102, 21, 225, 163, 129, 160}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 42, 81, 67, 200, 4, 75, 10}, 219}, {{170, 24, 0, 0, 0, 0, 0, 94, 163, 84, 68, 77, 30, 238, 45, 181}, 219}, {{170, 24, 0, 19, 113, 41, 129, 107, 62, 181, 236, 88, 125, 250, 153, 88}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 174, 137, 233}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 63, 10, 103, 35, 151, 211, 28, 235}, 219}, {{170, 24, 0, 153, 138, 9, 11, 176, 30, 99, 235, 68, 201, 84, 69, 196}, 219}, {{170, 24, 0, 193, 184, 221, 88, 55, 251, 39, 32, 67, 23, 55, 125, 249}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 143, 151}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 121}, 219}, {{170, 24, 0, 130, 192, 212, 69, 204, 59, 137, 122, 6, 7, 130, 157, 186}, 219}, {{170, 24, 0, 0, 0, 0, 135, 31, 90, 40, 51, 218, 163, 120, 152, 111}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 102, 172, 12, 130}, 219}, {{170, 24, 0, 0, 0, 0, 43, 93, 195, 22, 30, 58, 2, 207, 65, 27}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 3, 22, 134, 171, 135, 12, 194, 184, 53}, 219}, {{170, 24, 0, 0, 0, 131, 181, 47, 67, 206, 89, 55, 135, 57, 139, 98}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 40, 188, 235, 186, 145, 178, 137}, 219}, {{170, 24, 0, 0, 2, 127, 24, 121, 21, 38, 56, 163, 215, 97, 118, 245}, 219}, {{170, 24, 0, 0, 0, 0, 0, 31, 189, 85, 198, 136, 241, 26, 168, 209}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 9, 212, 248, 165, 207, 47, 174, 24, 20}, 219}, {{170, 24, 0, 44, 176, 112, 132, 24, 140, 48, 185, 4, 179, 148, 196, 3}, 219}, {{170, 24, 0, 0, 189, 154, 143, 174, 204, 99, 226, 76, 239, 129, 37, 158}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 148}, 219}, {{170, 24, 0, 0, 0, 0, 0, 170, 14, 211, 141, 115, 133, 125, 115, 112}, 219}, {{170, 24, 0, 229, 19, 168, 8, 98, 36, 64, 25, 233, 22, 17, 54, 208}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 88, 128, 176, 159, 26, 194, 29, 21}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 220, 48, 28, 73, 72, 16, 2}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 12, 230, 99, 140, 30, 128}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 144, 227, 153, 15, 3, 198, 4, 51, 71, 198}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 213, 147, 4, 211, 69, 123}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 98, 213, 176, 6, 51, 170, 218}, 219}, {{170, 24, 0, 5, 199, 15, 10, 191, 30, 207, 188, 221, 117, 110, 35, 244}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 116, 142, 251, 137, 174, 45}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 217, 168}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 93, 133, 66, 80, 14, 65, 184, 79, 245, 44, 82, 248}, 219}, {{170, 24, 0, 0, 0, 0, 0, 136, 88, 14, 31, 230, 33, 154, 147, 86}, 219}, {{170, 24, 0, 0, 0, 0, 103, 25, 143, 148, 195, 147, 114, 62, 153, 71}, 219}, {{170, 24, 0, 0, 0, 0, 149, 31, 168, 18, 190, 123, 1, 242, 181, 148}, 219}, {{170, 24, 0, 0, 0, 49, 223, 103, 219, 203, 97, 174, 133, 180, 171, 170}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{170, 24, 0, 0, 0, 0, 0, 162, 56, 8, 185, 233, 144, 212, 159, 106}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 193, 141, 57, 218, 9, 214, 95}, 219}, {{170, 24, 0, 0, 0, 0, 145, 104, 68, 251, 90, 94, 241, 23, 80, 81}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 38}, 219}, {{170, 24, 0, 0, 73, 3, 159, 223, 120, 72, 38, 94, 241, 226, 223, 139}, 219}, {{170, 24, 0, 175, 53, 185, 223, 1, 162, 219, 66, 92, 233, 72, 99, 75}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 219}, {{170, 24, 0, 0, 0, 198, 125, 178, 130, 71, 1, 39, 132, 217, 53, 95}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 208, 77, 222, 247, 37, 172}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 137}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 141, 240, 155}, 219}, {{170, 24, 0, 0, 0, 0, 0, 197, 108, 212, 123, 150, 191, 107, 1, 196}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 39, 75}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 238}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 46, 4, 121, 154, 224, 156, 229, 80}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 132, 108, 31}, 219}, {{170, 24, 0, 0, 75, 40, 27, 44, 63, 185, 236, 39, 31, 141, 65, 201}, 219}, {{170, 24, 0, 0, 0, 0, 0, 0, 0, 16, 246, 90, 37, 49, 38, 102}, 219}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 235}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 188, 47, 221, 234}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 43, 250, 176, 154, 76, 57, 165, 175}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 133, 92}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 165, 203, 129, 41, 46, 170, 135}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 216, 35, 34, 49, 4, 26, 204}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 170, 214}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 123, 216}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 132, 54, 142}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 254, 135, 12}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 47}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 192, 61, 170, 247, 51, 133, 42, 176}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 215, 47, 35, 249, 53}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 236, 229, 233, 229, 145}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 201, 161, 165, 252}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 59}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 142, 22, 173, 220, 155}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 177, 162, 49, 84, 206, 113, 170, 106}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 225, 135, 143, 230, 29, 74, 109, 49}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 13}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 13, 74, 151}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 107, 12, 84, 233, 188}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 3, 31, 249}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 109, 249}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 73, 177, 98, 237, 11, 206}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 37, 169, 206, 123}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 236}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 16, 246, 246, 55}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 248, 208}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 80, 246, 245, 138, 164}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 189, 218, 16, 220, 254}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 20, 47, 101, 119, 19, 255, 136}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 40, 31}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 130}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 188, 237, 31, 51, 131}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 79, 244, 0, 179, 234}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 218, 169, 156, 146, 87, 132, 6}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 202, 148}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 143, 35, 130}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 2, 96, 152, 52, 78, 179, 227}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 214}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 194, 25}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 246, 125, 95}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 126, 228, 66, 168, 1, 121, 192}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 181, 144, 24, 11, 192, 163}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 228, 75, 36, 9, 105, 34, 152, 103}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 186}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 59, 149, 98}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 240, 155, 52, 183}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 184, 185, 223, 203}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 242, 12}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 33, 151, 48}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 71, 79}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 173, 167, 40, 98, 74, 83, 3, 146}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 22, 105, 199, 89, 169}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 112, 156, 80, 181}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 15}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 195}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 241, 164, 122, 129, 55, 225, 81, 64}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 255, 38, 108, 82, 225, 96, 247}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 5, 127, 147, 137, 159}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 1, 173, 56, 98, 254, 89, 63}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 33}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 194, 22}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 236, 25, 20, 136, 54}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 138, 28, 90}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 8, 122, 101}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 116}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 53, 52, 86, 240, 58, 76, 178}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 18, 175, 23, 181, 5, 124}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 182, 65}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 77, 8, 92, 57}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 111, 169, 195}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 160, 8}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 23, 91}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 133, 193, 60}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 184, 128, 16, 62, 28, 107, 152}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 104, 13, 60, 192, 180, 194}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 195, 153, 8}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 169, 73, 151}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 247, 2, 157, 73}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 206, 209, 184, 169, 246, 56, 146, 139}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 181, 126, 25, 17, 90, 96}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 36, 112, 153, 237, 232, 21, 193}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 169}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 31, 170, 148, 152}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 225, 64, 250, 150}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 135, 182, 15, 11, 66}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 197, 243, 230, 217, 130, 237, 168}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 26, 9, 116, 16}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 81, 104, 25, 131, 63}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 38, 221, 231, 223, 41, 218, 108}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 116, 193, 78, 154, 78}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 195, 222, 73}, 105}, {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 124, 105, 204, 69}, 105}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 174, 136}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 83, 194, 136, 28, 163}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 80, 230}, 210}, {{33, 219, 226, 3, 180, 190, 0, 93, 64, 22, 71, 188, 207, 50, 22, 175}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 51, 173, 2, 124}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 89, 183, 132, 216, 181}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 28, 14, 141, 70, 135, 186, 48}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 29, 180, 24, 182, 48, 194, 73}, 210}, {{33, 219, 226, 3, 180, 190, 0, 43, 5, 59, 139, 207, 9, 203, 230, 213}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 222, 243, 144}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 170, 100, 10, 244}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 181, 2, 42}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 134, 179, 69}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 235, 126, 165, 122, 246, 0, 237, 127}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 5, 179, 18}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 58, 200, 228}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 120, 232, 205, 227, 65}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 128, 25, 223, 18, 134, 76, 174, 208}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 149, 87, 173, 40, 1, 76, 33}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 79, 200, 90}, 210}, {{33, 219, 226, 3, 180, 190, 0, 251, 216, 112, 246, 48, 175, 146, 33, 86}, 210}, {{33, 219, 226, 3, 180, 190, 0, 30, 7, 253, 0, 33, 118, 165, 241, 187}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 245, 139, 129, 172, 174, 231}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 176, 98, 249, 32, 208, 55, 81, 207}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 177, 242, 182}, 210}, {{33, 219, 226, 3, 180, 190, 0, 24, 165, 143, 171, 226, 153, 190, 191, 113}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 101, 56, 202, 7, 130, 226}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 184, 15, 9}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 4, 1, 227}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 170, 52, 76, 56, 196, 156}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 83, 228, 214}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 9, 82, 116, 15, 188, 58, 241}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 79, 175, 146}, 210}, {{33, 219, 226, 3, 180, 190, 0, 132, 110, 81, 110, 58, 118, 220, 22, 227}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 59, 251, 198, 216, 179, 204, 216, 225}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 166, 56, 120, 234, 165, 158, 214}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 68, 100, 58, 208, 191, 140, 151, 157}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 5, 22, 163, 102}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 222, 187, 250, 38, 199, 89, 148, 77}, 210}, {{33, 219, 226, 3, 180, 190, 0, 73, 242, 23, 61, 130, 217, 32, 251, 130}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 133, 130, 63, 234, 66, 112, 170}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 159, 221, 9, 157, 177, 4, 4, 80}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 177, 205, 194, 159, 239, 200, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 232, 101, 247, 198, 38, 251, 24, 157}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 39, 67}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 235, 163, 144, 185, 21, 226}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 83, 98, 99, 53, 81, 31, 51}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 234, 182}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 250, 224, 124, 157, 138, 92, 45, 157}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 215, 58, 22, 196, 210, 37}, 210}, {{33, 219, 226, 3, 180, 190, 0, 150, 85, 165, 34, 5, 74, 74, 33, 62}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 207, 51, 138, 19, 113, 162, 102, 78, 76}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 91, 6}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 209, 167, 229, 230, 141, 113, 64}, 210}, {{33, 219, 226, 3, 180, 190, 0, 39, 217, 110, 69, 192, 43, 149, 143, 29}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 233, 237, 132, 2}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 253, 179, 43, 98}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 186, 62, 35, 88, 108}, 210}, {{33, 219, 226, 3, 180, 190, 177, 164, 29, 29, 53, 130, 112, 178, 84, 53}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 172, 46, 46, 253, 40, 2}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 114, 225, 227, 123, 102, 56, 4, 197}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 1, 227, 144, 25, 172, 87, 176, 165}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 225, 105, 73, 207, 209, 34, 204, 217, 24}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 16, 232, 169, 40, 176}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 98, 40, 228}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 114, 137, 41, 34, 169, 126, 74}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 189, 157, 62, 58, 144, 77, 91, 84}, 210}, {{33, 219, 226, 3, 180, 190, 0, 75, 229, 239, 120, 88, 124, 60, 223, 199}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 150, 84}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 185, 88, 220}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 127, 196, 94, 180, 2, 216, 175, 69}, 210}, {{33, 219, 226, 3, 180, 190, 0, 251, 156, 19, 148, 34, 102, 207, 242, 222}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 101, 158, 40, 40, 225, 36}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 79, 50, 148, 104, 34, 24, 82, 242}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 192, 84, 72, 238, 129, 70, 44, 84}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 100, 158, 11}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 210}, {{33, 219, 226, 3, 180, 190, 0, 211, 246, 97, 26, 77, 79, 51, 137, 217}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 174, 221}, 210}, {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 59, 236, 44}, 210}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 181, 58, 236, 212, 247, 202, 250}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 175, 230, 238, 108, 224, 88, 129}, 151}, {{51, 251, 0, 0, 0, 0, 0, 111, 182, 39, 193, 203, 25, 101, 108, 87}, 151}, {{51, 251, 0, 0, 73, 209, 174, 209, 90, 72, 152, 163, 62, 130, 229, 158}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 33, 88, 221, 67, 21, 212, 18, 78}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 84, 36, 4, 245, 140, 9}, 151}, {{51, 251, 0, 0, 0, 149, 16, 143, 255, 179, 139, 143, 97, 125, 125, 197}, 151}, {{51, 251, 0, 0, 0, 0, 168, 203, 245, 93, 189, 81, 238, 251, 43, 229}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 151, 219, 21, 189, 137, 253}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 4, 175, 242, 251, 169, 157, 113, 135}, 151}, {{51, 251, 0, 0, 43, 35, 206, 229, 184, 186, 78, 234, 170, 207, 159, 123}, 151}, {{51, 251, 0, 36, 73, 138, 191, 40, 134, 231, 103, 193, 245, 36, 254, 127}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 223}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 62, 46, 108}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 14, 163, 106, 111, 196, 79, 205}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 54, 45}, 151}, {{51, 251, 0, 0, 0, 0, 0, 197, 160, 101, 246, 127, 184, 172, 49, 173}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 94, 50, 9, 1, 18, 231, 167, 244}, 151}, {{51, 251, 0, 0, 0, 0, 129, 192, 223, 250, 216, 2, 75, 240, 184, 131}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 131, 101}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 119, 156, 161, 101, 5, 186}, 151}, {{51, 251, 0, 0, 100, 49, 2, 79, 150, 65, 230, 153, 44, 248, 173, 187}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 106, 179, 155, 225, 74, 8, 11, 39, 117, 239, 198}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 191, 232, 134, 187, 172, 19, 36, 191}, 151}, {{51, 251, 0, 0, 0, 0, 35, 55, 245, 182, 71, 105, 31, 108, 80, 204}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 172, 145}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 162}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 151}, {{51, 251, 0, 0, 0, 240, 144, 48, 54, 184, 119, 49, 97, 58, 182, 240}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 103, 151}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 45, 22, 108, 209, 96, 224, 134, 45, 183, 199, 209, 220}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 69, 228, 161, 249, 13, 104, 138}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 230, 41, 216}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 141, 33, 105, 142, 75, 69}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 245, 23, 104, 118, 36, 103}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 253, 173, 39, 116}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 126, 79, 178, 51, 23, 7, 237}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 51, 186, 132}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 27, 111, 130, 81, 7, 30, 171}, 151}, {{51, 251, 0, 0, 60, 48, 24, 6, 247, 213, 169, 28, 6, 47, 117, 174}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 210, 217, 67, 58, 152, 216, 40}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 150, 117}, 151}, {{51, 251, 0, 225, 6, 187, 67, 221, 194, 192, 73, 81, 246, 54, 90, 214}, 151}, {{51, 251, 0, 208, 229, 34, 5, 151, 211, 48, 0, 227, 71, 89, 232, 99}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 151}, 151}, {{51, 251, 0, 24, 123, 71, 125, 202, 182, 91, 212, 216, 186, 241, 129, 36}, 151}, {{51, 251, 0, 0, 0, 57, 79, 227, 68, 175, 35, 151, 160, 70, 9, 78}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 223}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 57, 241, 125, 142, 213, 49, 27}, 151}, {{51, 251, 0, 0, 0, 220, 210, 75, 90, 16, 13, 67, 183, 210, 80, 75}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 4, 137, 99, 31, 215, 151, 253, 14}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 74, 117, 74, 202, 152, 141, 74, 252}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 251, 94, 6}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 0, 0, 0, 0, 164, 176, 120, 137, 184, 97, 114, 28, 195}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 172, 79, 37, 3, 234, 161}, 151}, {{51, 251, 0, 69, 76, 55, 17, 162, 38, 69, 145, 119, 71, 246, 180, 10}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 106, 26, 188, 107, 102, 223, 165}, 151}, {{51, 251, 0, 0, 0, 51, 191, 162, 158, 10, 131, 195, 24, 250, 80, 78}, 151}, {{51, 251, 0, 199, 155, 4, 227, 188, 24, 56, 197, 192, 83, 16, 233, 7}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 89}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 151}, {{51, 251, 0, 56, 131, 94, 98, 244, 214, 191, 71, 165, 88, 105, 76, 154}, 151}, {{51, 251, 0, 238, 58, 126, 144, 241, 249, 224, 75, 51, 77, 23, 191, 224}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 211}, 151}, {{51, 251, 0, 0, 0, 0, 0, 21, 78, 149, 31, 108, 34, 172, 246, 88}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 91, 217, 60, 13, 54, 253, 120, 155}, 151}, {{51, 251, 0, 0, 0, 166, 214, 12, 217, 51, 92, 223, 212, 118, 197, 52}, 151}, {{51, 251, 0, 0, 0, 0, 0, 175, 137, 231, 246, 67, 201, 70, 240, 219}, 151}, {{51, 251, 0, 228, 249, 46, 154, 132, 15, 112, 52, 124, 70, 160, 73, 56}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 42, 181}, 151}, {{51, 251, 0, 0, 186, 43, 31, 97, 65, 135, 140, 55, 244, 3, 36, 175}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 226}, 151}, {{51, 251, 0, 0, 0, 230, 71, 185, 153, 245, 26, 217, 212, 131, 21, 54}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 1, 180, 220}, 151}, {{51, 251, 0, 0, 0, 163, 238, 15, 42, 141, 22, 204, 37, 215, 107, 167}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 121, 151, 250, 224, 147, 33, 246, 64}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 163, 154, 146, 136}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 19, 15, 111, 187, 230, 26}, 151}, {{51, 251, 0, 0, 0, 0, 110, 118, 80, 88, 213, 67, 203, 141, 160, 66}, 151}, {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 128, 162}, 151}, {{51, 251, 0, 0, 0, 0, 57, 84, 156, 22, 168, 95, 175, 76, 5, 94}, 151}, {{51, 251, 0, 0, 0, 0, 18, 81, 16, 153, 149, 248, 98, 165, 216, 238}, 151}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 81, 195}, 28}, {{106, 185, 11, 122, 197, 192, 167, 28, 156, 216, 3, 51, 236, 86, 51, 197}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 155, 27, 38, 97}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 109, 172, 124, 12, 237, 26, 119, 176}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 219, 173, 47, 94, 59, 83, 203, 183}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 24, 166}, 28}, {{106, 185, 11, 122, 197, 192, 0, 154, 89, 172, 92, 203, 22, 58, 205, 104}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 28}, {{106, 185, 11, 122, 197, 192, 0, 207, 69, 4, 80, 63, 189, 4, 247, 190}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 75, 165, 29, 161, 207, 66, 105, 250}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 106, 59}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 122, 91, 188, 233}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 31, 124, 246, 132, 123}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 183, 162, 156, 167, 86, 186}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 225, 237, 107, 228, 25, 124, 44}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 249, 220, 241, 17, 49, 92}, 28}, {{106, 185, 11, 122, 197, 192, 175, 81, 172, 162, 212, 6, 48, 84, 51, 6}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 17, 46, 61}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 215, 132, 220, 255, 160}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 107, 1, 226, 181, 188, 85, 46, 191}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 69, 47, 59, 116, 212, 186, 27}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 89, 208, 74, 232, 16, 173}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 148, 203, 64, 61, 184, 35}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 65, 155, 204, 65, 147, 119}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 125, 27, 59, 208, 44}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 195, 159, 117}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 53, 56, 235}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 252, 167, 0, 28, 154, 72, 251, 131}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 22, 158, 196, 34}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 65, 105, 183, 224, 190}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 67, 187, 55}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 202, 186, 233, 0, 196}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 103, 165, 149}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 28}, {{106, 185, 11, 122, 197, 192, 0, 230, 68, 212, 187, 230, 251, 43, 12, 166}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 40, 34, 10, 246, 192, 188, 121, 50}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 17, 42, 9, 162, 15, 44}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 106, 82}, 28}, {{106, 185, 11, 122, 197, 192, 0, 41, 170, 253, 66, 22, 114, 209, 200, 85}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 22, 101}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 239, 245, 202, 183}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 108, 198, 50, 194, 97}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 28, 181, 162, 193, 15, 190}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 215, 133, 8, 239, 144}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 124, 85}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 143, 172, 246, 201, 22}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 162, 27, 2, 233, 224, 21}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 8, 37, 250, 117, 189}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 251, 246, 210, 163, 27}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 35, 22, 136, 236, 15}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 174, 184, 95, 50, 32, 123}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 156, 39, 167}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 223, 172, 127}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 165, 81, 31}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 101, 118, 149, 209, 51, 217, 155}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 34, 0, 206, 233, 243, 182}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 18, 66, 67, 35, 233}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 95, 204, 251}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 135, 245, 198, 103, 75}, 28}, {{106, 185, 11, 122, 197, 192, 234, 90, 127, 52, 72, 19, 146, 59, 154, 123}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 207, 141}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 17, 168, 251, 71, 41, 77}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 78, 223, 199, 119, 242, 30}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 12, 100, 12, 121, 201, 185, 148, 244}, 28}, {{106, 185, 11, 122, 197, 192, 0, 52, 162, 216, 64, 9, 139, 161, 94, 106}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 244, 146, 185, 139, 106, 36, 234, 32}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 113, 9, 55, 225, 123, 25, 201, 44}, 28}, {{106, 185, 11, 122, 197, 192, 0, 46, 74, 186, 11, 52, 204, 8, 245, 67}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 134, 151, 46, 42, 92, 24, 240}, 28}, {{106, 185, 11, 122, 197, 192, 0, 152, 55, 89, 131, 136, 213, 40, 194, 245}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 247, 53, 80, 160, 214, 171, 119, 57, 172}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 100, 224}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 69, 217, 146, 97, 50}, 28}, {{106, 185, 11, 122, 197, 192, 0, 18, 158, 240, 184, 234, 123, 129, 44, 20}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 116, 254, 86}, 28}, {{106, 185, 11, 122, 197, 192, 0, 133, 84, 222, 222, 222, 194, 74, 214, 219}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 162, 207, 148, 210, 41, 107, 146}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 143, 237, 224, 240, 167, 193, 11}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 165, 70, 227, 2}, 28}, {{106, 185, 11, 122, 197, 192, 0, 242, 44, 156, 199, 152, 17, 52, 191, 161}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 62, 220, 160, 177, 174, 23, 194, 2}, 28}, {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 191, 93, 6, 33, 102}, 28}, {{192, 0, 0, 0, 0, 0, 0, 0, 173, 95, 55, 208, 191, 193, 22, 64}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 72, 224, 223, 129, 154, 6, 91, 129}, 64}, {{192, 0, 0, 0, 0, 226, 234, 7, 22, 243, 59, 163, 108, 48, 138, 102}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 100, 92, 165, 126, 254, 185, 255, 125}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 27, 237, 220, 209, 158, 175, 34, 185, 21, 92, 65, 79, 109, 234}, 64}, {{192, 0, 0, 212, 125, 6, 72, 153, 110, 196, 23, 188, 144, 240, 97, 239}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 232, 146, 185, 133, 186, 102, 30}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 212, 118, 99, 59, 255}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 75, 152, 236}, 64}, {{192, 0, 0, 0, 0, 234, 209, 47, 173, 213, 186, 93, 245, 231, 176, 39}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 45, 98}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 10, 138, 194, 211}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 61, 198, 8}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 28, 226}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 38, 161, 52}, 64}, {{192, 0, 0, 0, 0, 0, 119, 48, 91, 158, 122, 8, 84, 191, 129, 157}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 137}, 64}, {{192, 0, 0, 0, 0, 0, 5, 68, 72, 129, 26, 229, 96, 88, 90, 146}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 115}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 173, 0, 133, 74, 130}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 19, 32, 130, 147, 161}, 64}, {{192, 0, 0, 0, 0, 0, 172, 35, 185, 117, 197, 99, 83, 49, 52, 73}, 64}, {{192, 0, 0, 0, 0, 122, 219, 208, 46, 90, 205, 189, 187, 108, 203, 97}, 64}, {{192, 0, 0, 0, 0, 28, 115, 163, 108, 218, 249, 100, 235, 47, 237, 128}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 150, 227, 94, 65, 107, 128, 28, 163}, 64}, {{192, 0, 0, 0, 90, 92, 41, 185, 35, 167, 202, 115, 186, 87, 25, 68}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 250, 60, 109}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 153, 165}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 225, 135, 103, 97, 219}, 64}, {{192, 0, 0, 0, 0, 77, 122, 106, 230, 232, 148, 232, 3, 151, 211, 212}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 91, 25, 176}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 23, 142, 199, 35, 155}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 205, 84, 118, 191}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 64}, {{192, 0, 0, 0, 0, 0, 62, 212, 121, 129, 130, 221, 232, 200, 126, 59}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 143}, 64}, {{192, 0, 0, 130, 152, 242, 239, 69, 235, 144, 130, 91, 190, 175, 223, 131}, 64}, {{192, 0, 0, 0, 117, 46, 201, 92, 74, 125, 199, 234, 124, 151, 21, 250}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 82, 53, 254, 101, 69, 36, 103}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 189, 123, 234, 12, 164, 27, 245, 156}, 64}, {{192, 0, 0, 0, 0, 0, 39, 233, 69, 201, 245, 83, 197, 246, 115, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 44, 108, 192, 77, 56, 253, 141, 233, 166}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 3, 5}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 69, 42, 78, 237, 47, 104, 51, 6, 2}, 64}, {{192, 0, 0, 0, 0, 151, 205, 17, 10, 126, 1, 223, 132, 190, 167, 50}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 146, 197, 110, 242}, 64}, {{192, 0, 185, 124, 143, 83, 86, 6, 226, 92, 168, 219, 58, 106, 81, 249}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 243, 229, 230, 143, 117}, 64}, {{192, 0, 0, 0, 229, 15, 184, 10, 28, 78, 26, 43, 159, 241, 155, 222}, 64}, {{192, 0, 0, 0, 0, 0, 228, 40, 55, 187, 242, 225, 84, 58, 128, 5}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 64}, {{192, 0, 0, 29, 108, 103, 4, 8, 195, 158, 193, 128, 237, 226, 221, 247}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 24, 53}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 108, 142, 76, 24}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 245, 165, 150, 40, 176, 182, 152, 65, 117, 27, 222, 158, 190}, 64}, {{192, 0, 0, 253, 227, 254, 8, 189, 147, 39, 23, 251, 81, 154, 79, 187}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 249, 176, 202}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 209, 217, 76, 213, 47, 34, 201, 19, 128}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 201, 114, 236, 177, 84, 135, 175, 144, 45, 193}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 144, 212, 234}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 251, 114}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 207}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 133, 156, 86, 131, 176, 47, 65}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 177, 115, 231}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 67, 246, 199, 143, 143}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 7, 22}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 53, 8, 9, 235}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 82, 130}, 64}, {{192, 0, 0, 0, 0, 0, 105, 53, 49, 110, 210, 173, 193, 41, 39, 91}, 64}, {{192, 0, 0, 0, 0, 46, 60, 103, 192, 192, 100, 38, 176, 25, 253, 190}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 103, 204, 124, 32}, 64}, {{192, 0, 68, 152, 151, 122, 27, 22, 96, 10, 177, 180, 58, 104, 131, 145}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 126, 92, 58, 181, 69}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 18, 205, 178, 158, 25}, 64}, {{192, 0, 0, 0, 0, 0, 0, 171, 134, 94, 64, 127, 226, 130, 48, 99}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 183, 141, 229}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 147, 129, 238}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 242, 158}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 38, 132, 33, 88, 13}, 64}, {{192, 0, 135, 221, 237, 114, 233, 43, 185, 25, 116, 194, 51, 109, 100, 203}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 131, 176}, 64}, {{192, 0, 0, 0, 0, 238, 24, 80, 213, 146, 156, 210, 200, 21, 234, 66}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 210}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 64}, {{192, 0, 0, 0, 0, 214, 158, 245, 178, 238, 254, 138, 136, 19, 222, 244}, 64}, {{192, 0, 0, 0, 0, 0, 136, 101, 186, 45, 90, 126, 199, 96, 34, 176}, 64}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 9}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 38, 153, 139}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 75, 222, 209, 241}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 1}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 57, 132, 96}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 202, 54, 59}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 59}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 237, 194, 59}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 149, 133}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 223, 111, 113, 211}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 7, 28, 186}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 242}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 242, 205}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 77, 245, 170}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 184, 44, 130}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 77}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 187, 104, 141}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 26, 163, 65}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 62}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 2, 46, 227, 145}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 44, 226}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 52}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 226}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 2, 89, 80}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 104, 117, 106}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 9}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 206, 82, 155}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 138, 89, 53}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 115, 57, 70, 23}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 58, 48, 132}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 76}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 133, 46}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 251}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 158, 118, 148}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 128, 16, 244}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 101, 196, 188}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 241, 8, 231}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 51, 175}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 12}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 111, 96, 38, 99}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 200, 215, 76, 180}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 172}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 144, 242, 199}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 81, 28}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 35, 144}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 154, 100, 239, 243}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 134, 97, 234}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 139, 215, 220, 21}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 112}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 38, 53}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 57, 37, 66}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 219, 124}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 28, 19}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 194, 239, 88}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 140}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 139, 14, 191, 6}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 153, 81, 173}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 62, 63}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 1}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 235, 174}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 167, 200, 244}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 105}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 235, 186, 174}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 232, 159, 169, 132}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 183, 142}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 26, 187}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 223, 109}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 108}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 34, 200, 200}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 228, 91, 241}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 101, 202}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 172}, 250}, {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 152, 188}, 250}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 85, 14, 173, 131}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 232}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 183, 125}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 165, 237, 174, 98, 128, 250, 202}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 196, 79}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 199, 170, 183, 207, 171, 49, 228}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 177, 141, 217, 189, 125, 102, 24}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 22, 34, 90, 105}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 166, 74}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 114, 205, 82, 33, 47, 176}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 40, 233, 153, 199, 217, 20, 21}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 70}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 158, 90, 207, 255, 195, 155}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 90, 6, 40}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 122, 38, 67, 24, 205, 156, 209}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 64}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 59, 92}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 137, 207}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 161}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 131, 115}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 101}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 30, 48, 72, 106, 53}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 199, 191}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 193, 11}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 199}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 167, 96}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 242, 150, 123, 159}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 72, 48, 250, 46, 239}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 127, 159, 105}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 228, 229}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 24, 11, 57, 139, 231, 238}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 150, 53, 28}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 163, 249, 195, 147}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 144, 91}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 136, 192, 55}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 38}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 120, 188, 14, 116}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 205, 248, 35, 34}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 79, 204, 170, 197, 126, 213}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 71, 120, 254, 40, 233, 156, 81}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 36, 153, 94, 17, 3, 243, 102}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 17, 99}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 127, 187, 254, 103}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 103, 199, 147, 37, 207, 26, 132}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 97}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 119, 148, 137, 96, 141, 44, 32}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 69, 159}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 27, 154, 136, 117, 12, 66}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 245, 26, 201, 104, 157, 171, 113}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 131, 96, 165, 197, 35, 221}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 162, 216, 16, 122, 36, 80, 55}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 102, 98, 118, 19, 198, 185, 99}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 140, 63, 161, 129}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 151, 219}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 212, 217, 223, 177, 76}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 34, 69, 229, 14, 203, 34}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 93, 74, 127, 171, 61, 97}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 13}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 239, 207, 160, 101, 139}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 78, 73, 206, 160}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 222}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 120, 157, 240, 182, 164}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 118, 41, 111, 75, 252}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 251, 76, 78, 167, 6}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 8}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 98}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 84, 196, 54, 224, 99}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 236, 248, 168, 165}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 203, 237, 113, 103, 190}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 115}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 211}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 135, 60, 112, 31, 150, 196}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 60, 108, 216, 224, 137, 103}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 249, 55}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 186}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 20, 32, 132, 25, 244, 71, 236}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 74, 147, 59, 172, 119, 137, 19}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 49, 240, 41}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 4, 222, 215, 135, 80}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 7, 248, 250, 162, 118}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 60, 216, 248, 91, 175, 23}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 136, 95, 1}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 70, 251, 36, 191, 225, 255}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 41, 51, 109, 200, 162}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 40, 173}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 200}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 132}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 101, 148, 230, 236, 56}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 179}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 181, 116}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 231, 62, 51, 193, 114, 83}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 233, 2, 129, 72, 155, 112}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 229, 217, 101}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 49, 219, 184}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 93, 253, 192, 67}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 27, 222, 229, 134, 7}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 71, 117, 167, 9, 92, 149}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 19}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 72, 239, 55}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 160, 192, 62, 147, 73, 137}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 137, 247, 4}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 145, 6, 173}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 129, 245, 242, 99, 82, 97}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 147, 97, 105, 34, 144, 20}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 223, 211, 250, 145, 98}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 169, 29, 241}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 64, 38, 10}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 100, 39, 17, 149, 24, 117}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 55, 71, 39}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 217, 170, 209}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 172, 92}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 45, 224, 228}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 231, 235, 71, 169, 196}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 198, 114, 135, 200, 214}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 58}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 46, 139, 166, 166}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 126, 9, 121, 207, 221}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 227, 219, 164, 224, 128}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 155, 20, 4, 235}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 250, 178, 56, 1}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 182, 139}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 45, 23, 97, 25}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 61, 146, 231}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 27, 219, 107, 14}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 39, 85}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 227, 247, 11, 86}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 247, 155, 249}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 89, 46, 90}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 18, 102, 85, 32}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 178, 69, 197}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 137, 130}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 221, 32, 183}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 145, 52, 116, 16, 63, 28}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 201, 70, 77}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 49, 116, 37, 195}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 65}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 210}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 217, 38}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 127, 157, 242, 26, 126, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 213, 253, 113}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 10, 73}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 171, 47, 48, 223}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 199, 24, 237}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 96, 223, 183, 2, 109}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 255, 14, 184, 18, 43}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 252}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 231, 149, 156, 193}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 66, 123, 191, 225}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 96, 113, 22}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 19}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 143, 158, 122, 195, 63, 254}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 235, 49, 159, 220, 67}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 159}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 97}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 63, 18}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 244}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 141, 231}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 253}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 183, 254, 228}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 236, 225}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 253}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 254, 253}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 146, 155}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 128, 219, 178, 196, 47, 91}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 197, 183, 81, 176, 116}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 204, 238, 106, 29, 133, 97}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 104, 85, 243}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 6, 167, 89, 228, 22}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 123, 124, 40}, 182}, {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 152, 164, 31}, 182}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 45}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 66, 254}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 245, 44}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 148}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 229, 42}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 26}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 149, 248}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 253}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 221, 24}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 89, 168}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 223}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 90, 156}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 245}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 177, 199}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 241, 35}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 78}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 170, 99}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 19}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 76}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 63, 79, 159}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 136, 141}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 223}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 210, 166}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 180}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 191, 16}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 71, 78}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 63, 238}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 255}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 50, 107}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 103, 145}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 102, 167}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 17, 1}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 210, 129}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 103}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 114}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 182}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 16}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 1, 69, 52}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 49, 17, 162}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 134, 183}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 80}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 91, 243}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 76}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 212, 24}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 157, 197}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 219, 147}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 203}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 4, 171}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 249}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 8}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 142, 228}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 30, 223}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 115}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 47}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 234}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 228, 41}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 107}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 43, 185}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 54}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 244, 67}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 92}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 74}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 248, 184, 167}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 236}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 7}, {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 20}, 7}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 171, 189, 205}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 71}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 167}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 222}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 248}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 7}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 213}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 156, 223}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 98, 210, 245}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 151}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 137}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 220}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 10, 56, 28}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 166, 130, 190}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 215, 153}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 16, 56}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 244, 123, 146}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 120}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 232, 163, 122}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 128}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 201, 245}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 77, 25}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 197}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 153, 34, 135}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 209}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 14, 117, 211}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 130}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 149}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 127, 207, 141}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 163}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 196, 126}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 76}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 240, 226, 161}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 160}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 84, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 185, 74}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 249}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 187, 124}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 30, 139}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 100, 57, 57}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 47, 180}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 23}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 244, 87, 238}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 49, 174}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 88}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 46}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 37, 98}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 227}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 179, 103}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 13}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 191, 240, 101}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 41, 127}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 49, 81, 41}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 138, 67}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 135}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 211}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 27}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 110}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 37}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 88, 116, 127}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 203}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 245, 137}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 175}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 229, 102, 241}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 193}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 164}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 163, 64}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 145}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 229, 42}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 59, 60}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 44}, 146}, {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 146}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 12}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 3}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 132, 23, 1, 200, 245, 24}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 27, 244, 175}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 198, 172, 197, 161, 211, 94}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 217, 158, 19, 9, 70}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 81}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 231, 191, 193, 63, 145}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 118, 87, 188, 189, 165, 210, 48}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 52, 192, 208, 103, 85}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 195, 115}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 140, 119, 217, 189, 72, 56, 224}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 198, 193, 135, 251, 80, 99, 180}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 171, 50, 254, 187}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 239, 137, 123}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 130, 166, 252, 11, 162, 123, 128}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 19, 42, 148, 57, 244}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 41}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 124}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 103, 1, 79, 255}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 41, 117}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 156, 163, 161, 20, 57, 38}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 47, 126, 105, 75, 177, 22}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 192, 76, 127}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 190, 201, 147, 219, 56}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 96, 81, 60}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 143, 255, 8, 193, 16}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 75, 29, 153, 223, 18, 14}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 163, 193, 89, 101, 58}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 237}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 202, 155, 245, 152, 106, 197}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 149, 45, 4, 230, 129}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 153}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 87, 14, 249, 50, 79}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 140, 215}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 236}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 211, 126, 202, 238, 196, 192}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 212, 209, 23, 202, 142, 253}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 27, 28, 92, 34, 217, 98}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 6, 250, 66}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 208, 85, 128, 146}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 31, 209}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 53, 250, 56, 245, 195, 218}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 190, 180}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 20, 203, 58, 135, 33, 163}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 17}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 23, 159, 183, 132, 174, 119}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 195, 66, 42, 142}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 81}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 228, 58, 203, 109}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 12}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 65, 31, 164}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 152, 161}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 127, 109, 3, 77, 217}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 156, 51, 126, 251}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 175, 150, 118, 192, 83, 212}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 137, 252}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 40, 202, 123, 138, 4, 203}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 103, 179, 50, 253}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 4, 90, 91, 103, 173}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 171, 57, 80}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 19, 199, 155, 179}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 152, 87, 77, 189, 141}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 125, 169, 195, 150, 46, 223}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 171, 34}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 169, 124, 21, 184, 9}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 182, 57, 139, 28, 198, 35}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 169, 54, 249}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 74, 108, 12}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 85, 62, 124, 27}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 156, 41, 168, 63, 12, 211, 72}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 10, 164, 119, 133, 231, 119}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 109}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 36, 237}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 103, 140}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 35, 34, 200, 196, 78}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 132, 19, 129, 187, 150}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 97, 187, 161, 82}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 115}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 15, 254, 121, 206, 229, 228}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 173, 120, 181, 95}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 81, 124, 204, 211, 89}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 10, 25, 64, 203, 27}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 146, 159, 103, 194, 46, 165}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 152, 13, 153, 234}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 221, 88, 94, 199, 78}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 179, 13, 176, 66, 249}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 234, 20, 76, 169}, 98}, {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 203, 244, 141, 128, 186}, 98}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 218, 177, 243, 233}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 196, 76, 199}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 80}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 18, 180, 30}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 72, 188}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 96, 97, 137}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 121, 232}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 115, 182, 167, 176}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 111, 176, 180, 177, 176}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 146, 241, 47}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 152}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 187}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 41, 149, 128, 118}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 216, 46, 133}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 84}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 23, 224}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 90, 228, 218, 42}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 226, 42, 141}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 128, 182}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 26}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 91}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 180, 85, 71, 126}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 119}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 108, 219, 19}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 91, 191, 104}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 88}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 18}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 72, 121}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 13}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 113, 45, 77, 147}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 140, 192}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 117}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 213, 67, 229, 80}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 121, 32, 142, 185, 132}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 4, 139, 183, 76}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 108}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 65, 28, 119}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 102, 71, 232, 2}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 231, 232, 66, 131}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 241}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 105, 232, 98}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 78}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 37, 16, 106, 245}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 34}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 125, 203, 236, 122, 51}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 65, 158}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 25}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 120}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 67, 221, 154, 64, 166}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 124, 152, 56}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 178, 153}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 184}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 2, 172, 130, 3}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 17, 144, 61}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 249, 105}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 6}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 205, 242, 219}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 97, 12}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 167, 117, 62, 219}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 55}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 181}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 85, 94, 74, 164, 229}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 64, 192}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 139, 60, 123}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 43, 234, 94, 87}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 120, 212, 170, 106}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 254, 25, 88, 7}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 71, 244, 183, 208}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 255, 138, 118}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 2, 152, 164}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 179}, {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 18, 135, 93, 192, 90}, 179}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 30, 219}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 213}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 128, 170, 68, 136, 138}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 64}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 189, 124, 118, 181, 207, 236}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 137}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 131, 77, 136, 55, 31, 185}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 21, 47, 207, 120}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 149, 109, 55}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 221, 239, 148}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 179}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 175, 50, 33}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 79, 37, 12, 114}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 182}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 118, 178, 10, 42}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 38}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 222, 228, 128, 155}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 120, 205}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 160, 145, 242, 91}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 76, 190, 69, 83}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 74, 107, 217, 232}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 192, 93, 5}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 23, 157, 68, 221}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 151, 147, 133, 115}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 217, 1, 49}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 28, 164, 3}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 151, 233, 255, 35}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 228, 56, 20, 154, 191, 151}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 91, 211, 55, 155, 109}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 200, 36, 112, 122, 13, 27}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 156, 162, 179}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 105, 33, 222}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 126}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 62, 255, 32}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 58, 140, 122, 206, 235}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 122, 242, 132, 152, 252}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 214, 75, 195, 166, 165}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 252, 61, 216, 137}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 131, 45}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 67, 209}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 202, 102, 231, 57, 213}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 253, 167, 114}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 37, 62, 109}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 106, 252, 31, 20, 249, 111}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 153, 179}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 134, 40, 184, 137, 69}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 155, 101, 130, 191}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 176, 193, 235, 228, 63}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 202, 222}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 66, 227, 250, 65, 48}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 14, 112, 1, 53}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 55, 217}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 238, 18, 92, 189}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 40, 56}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 184, 117}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 208, 139, 19, 26, 211}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 180}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 111, 209, 202, 73, 141, 11}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 64, 177}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 176, 220, 15, 233, 164}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 156, 239, 49}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 169, 144, 148, 197, 157}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 111, 226, 12, 172, 179}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 253, 187, 26}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 203}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 132, 9, 90, 55, 57, 158}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 152, 114, 146, 207}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 175, 197, 208}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 68, 118, 190}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 200}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 157, 183, 186, 61, 173}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 206}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 49, 113, 113}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 105, 30, 143, 249}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 60, 196, 60, 150}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 114, 48, 97, 170, 32}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 115, 171, 233, 236, 13}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 164, 78, 4, 135, 194}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 73, 197, 105, 238, 79}, 245}, {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 232, 44, 72, 59, 21, 71}, 245}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 230, 128, 78, 28}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 75, 23, 233, 252}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 240, 94, 117, 114, 129, 101, 232}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 46}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 58, 168, 171, 153, 116, 245}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 72, 26, 253, 161, 98, 104, 129}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 21}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 243, 36, 92, 191}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 230, 160, 86, 31, 252, 229, 144}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 169, 214, 57, 1}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 9, 75, 179, 199, 175, 175}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 57, 3, 174, 225, 131, 55, 185}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 26, 122}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 81, 235, 81, 119, 124}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 131, 61}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 240, 217, 63, 107, 50, 223, 157}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 49, 93, 109, 82, 90, 94}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 246}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 178, 246, 73, 110, 246, 164, 96}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 187, 89, 20, 52, 0, 60, 195}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 21, 126, 16, 70}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 22, 200, 93, 126}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 85, 123, 66}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 128}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 15, 63, 182, 172, 248, 10, 220}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 83, 66, 8, 25}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 204, 148, 170, 221, 150, 168, 109}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 16, 51}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 213, 251, 142}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 239, 162, 2, 7, 70}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 227, 34, 139, 51, 207, 251, 157}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 195, 94, 105, 57, 129, 57}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 137, 245, 164, 208, 68, 229, 165}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 104}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 36, 215}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 69}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 236}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 34, 187, 150}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 88, 102}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 65}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 163, 119, 186, 38, 70}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 80, 80, 208}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 46, 28, 76, 30, 22, 219, 204}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 66}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 44}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 129}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 126, 206, 68}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 156, 74, 240, 198, 195, 99}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 25, 176, 62, 164, 242}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 5, 224, 119, 148}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 4, 103, 117, 46, 150}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 2, 38, 148}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 23, 234, 167, 34, 24}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 20, 181, 4, 227, 85, 81}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 239, 108, 139, 121, 6, 8}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 12, 140}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 185, 204, 220, 64, 192}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 96, 4}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 172, 102}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 48}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 143, 72, 210, 248, 137, 218}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 239, 72, 231, 27, 23}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 106, 40, 236}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 107, 41, 82, 16, 224, 147, 224}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 151, 51, 79}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 135, 92, 176, 155, 92, 217}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 32, 167, 210}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 67, 227, 53, 53}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 46, 193, 255, 58, 70, 203}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 45, 126, 151, 155}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 41, 97, 98, 205, 167, 159}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 168, 174, 96}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 31}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 162, 204, 19, 64, 31}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 143, 153}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 37, 10}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 133, 164, 139, 168, 209, 242, 133}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 255, 212}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 124, 202, 153, 46, 238, 28}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 125, 25, 248, 35, 14, 12, 19}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 146}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 145, 139, 142}, 2}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 102, 154, 91, 92, 245, 185}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 101, 113, 221, 12, 47, 98, 196}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 184}, 5}, {{241, 59, 128, 153, 49, 46, 107, 116, 98, 211, 15, 31, 12, 255, 123, 82}, 5}, {{241, 59, 128, 0, 0, 0, 0, 124, 170, 199, 165, 120, 162, 200, 92, 209}, 5}, {{241, 59, 128, 0, 229, 39, 28, 234, 118, 177, 240, 92, 40, 98, 22, 96}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 165, 127, 38}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 165, 248, 52}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 177, 21}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 222, 77, 48, 30, 21, 138, 54}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 207, 126}, 5}, {{241, 59, 128, 0, 244, 58, 3, 88, 232, 48, 180, 230, 83, 39, 9, 172}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 105, 53, 229}, 5}, {{241, 59, 128, 88, 185, 84, 82, 11, 235, 100, 25, 11, 207, 130, 99, 65}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 97, 203, 54, 143, 104, 34, 52, 113}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 98, 99}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 105, 62, 71, 203, 202, 124}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 149, 49, 242}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 68, 224, 18, 229, 246, 132, 145, 25}, 5}, {{241, 59, 128, 0, 0, 0, 210, 48, 139, 69, 81, 158, 97, 26, 144, 182}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 176, 87, 116}, 5}, {{241, 59, 128, 0, 0, 235, 161, 47, 55, 14, 136, 89, 113, 45, 87, 122}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 209}, 5}, {{241, 59, 128, 0, 58, 96, 162, 15, 202, 186, 78, 89, 13, 172, 184, 126}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 19, 129, 54}, 5}, {{241, 59, 128, 0, 0, 0, 127, 23, 147, 107, 49, 234, 69, 114, 57, 106}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 179, 234, 36, 152, 21}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 10, 247, 60, 3, 156, 134}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 188, 152, 216, 236, 56, 83, 128, 96, 217}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 115, 155, 119, 14, 171, 89}, 5}, {{241, 59, 128, 0, 232, 66, 8, 100, 63, 171, 221, 72, 180, 32, 241, 218}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 226, 220, 116}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 252, 84, 175, 94}, 5}, {{241, 59, 128, 0, 0, 224, 200, 241, 161, 85, 193, 117, 66, 160, 46, 250}, 5}, {{241, 59, 128, 0, 0, 0, 235, 78, 74, 130, 250, 94, 206, 187, 83, 118}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 223, 238, 191}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 5}, {{241, 59, 128, 0, 234, 216, 50, 86, 198, 93, 73, 85, 51, 27, 190, 110}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 69, 113, 222, 181, 205, 214, 8, 70}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 103, 220, 60, 222, 214, 107, 193}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 138, 38}, 5}, {{241, 59, 128, 0, 0, 111, 14, 168, 45, 149, 81, 194, 38, 45, 109, 50}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 61, 243, 149, 151, 192, 155, 162, 27}, 5}, {{241, 59, 128, 0, 49, 191, 243, 239, 213, 90, 182, 213, 247, 142, 168, 196}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 30, 61, 171, 117, 74, 223}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 227, 181, 103}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 228, 8}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 132, 68, 32, 145, 153, 158, 248, 187, 224, 69, 202, 115, 16}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 142, 13, 46, 10, 62, 71, 211, 137}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 82, 200}, 5}, {{241, 59, 128, 46, 215, 189, 40, 210, 212, 158, 238, 120, 78, 14, 113, 226}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 172, 210, 26}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 145, 230, 227, 210, 172, 32, 229}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 226, 236, 121, 211, 17, 27, 254, 128, 18}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 5}, {{241, 59, 128, 0, 36, 177, 76, 11, 190, 192, 124, 199, 174, 192, 193, 18}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 47, 9, 71}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 35, 242, 52, 20, 241, 255}, 5}, {{241, 59, 128, 0, 0, 93, 12, 140, 151, 194, 234, 121, 249, 43, 58, 196}, 5}, {{241, 59, 128, 151, 100, 28, 70, 101, 153, 47, 77, 56, 171, 93, 210, 67}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 88, 21, 178, 100, 158}, 5}, {{241, 59, 128, 0, 0, 0, 0, 10, 30, 212, 203, 209, 235, 91, 108, 113}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 150, 18, 43, 18, 124}, 5}, {{241, 59, 128, 0, 0, 187, 184, 6, 179, 134, 110, 85, 81, 143, 9, 7}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 230, 92, 34, 49, 43}, 5}, {{241, 59, 128, 9, 61, 250, 30, 168, 50, 202, 104, 200, 80, 136, 250, 151}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 22}, 5}, {{241, 59, 128, 0, 236, 34, 108, 76, 88, 128, 77, 43, 213, 119, 117, 205}, 5}, {{241, 59, 128, 0, 0, 0, 0, 194, 70, 220, 126, 200, 49, 18, 211, 123}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 134, 65, 186}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 132, 111, 99, 54, 250, 63, 195}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 249, 144, 34}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 13, 201, 24, 131, 213}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 95, 0, 105, 109, 180, 168}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 194, 210, 141, 30, 115}, 5}, {{241, 59, 128, 0, 191, 245, 29, 57, 116, 227, 16, 72, 5, 191, 114, 208}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 96}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 75, 0, 2, 116, 63, 206, 169, 90}, 5}, {{241, 59, 128, 23, 101, 236, 69, 151, 15, 150, 3, 108, 95, 78, 178, 0}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 102, 204, 69, 119, 166}, 5}, {{241, 59, 128, 0, 0, 91, 46, 131, 154, 141, 47, 21, 190, 122, 2, 32}, 5}, {{241, 59, 128, 0, 0, 0, 194, 16, 176, 48, 91, 19, 224, 144, 65, 107}, 5}, {{241, 59, 128, 0, 0, 0, 0, 0, 33, 14, 175, 113, 32, 146, 234, 95}, 5}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 175, 203, 118, 70, 58, 74, 158}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 148, 193, 55, 97, 67, 59, 38}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 41}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 217, 105, 163, 235, 27, 90, 80}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 144, 42, 239, 222, 250, 178}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 203, 48, 154}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 48}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 247, 91, 213, 141}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 138, 236, 47}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 150}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 76, 174}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 57, 82, 235, 116, 107, 173}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 203, 18, 7, 192, 222, 255, 69}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 236}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 4, 3, 250, 131}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 177, 157, 40, 189}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 232, 119, 164}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 127, 40, 179, 171}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 255, 115, 239, 78, 50, 122, 106}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 90}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 193, 61, 169, 187}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 246, 123, 120, 19, 61, 192, 11}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 160, 181, 50, 32, 125, 62, 38}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 10, 146, 59, 153, 6}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 116, 172, 48, 192, 197}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 245, 153, 118, 192, 162, 192}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 90, 17, 108, 243, 58}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 124, 103, 39, 23, 59, 27, 111}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 242, 24, 222, 136, 142}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 93, 241, 158, 137, 92}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 157, 157, 84, 77, 15, 174}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 228, 214, 112}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 255, 227, 112, 219}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 31, 169, 167, 88, 252, 34}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 251, 82, 12, 57, 117, 173, 217}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 186, 15}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 99, 128, 182}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 163, 185, 95}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 153, 195, 2}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 106, 123}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 36, 199, 19}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 214, 135, 172, 75, 134}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 253, 250, 125, 205, 249}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 173, 189}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 223, 0, 216, 73}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 114, 20, 223, 64}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 89, 250, 40}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 168, 15}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 205, 103, 142, 150, 154, 9}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 65, 255, 231, 149, 212, 142}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 255, 42, 133, 184, 196}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 108, 81}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 4, 222, 70, 58}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 206, 46, 250}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 28, 85, 216}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 15, 73, 13}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 229, 43, 200}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 171, 128, 65}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 252, 196, 14, 63, 58, 104, 100}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 230}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 27, 134, 62, 209}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 223, 218, 38, 34, 119}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 191, 70, 40, 1}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 171}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 120, 76, 208}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 13}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 225, 50, 9}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 36, 217, 118, 181, 244}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 234, 211}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 105, 161}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 186, 190, 57, 114, 14, 19}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 212}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 252, 43, 58, 24}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 1, 28}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 54, 101}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 21, 147, 52, 249}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 197, 171, 147, 28, 18, 52, 103}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 219, 238, 197}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 104, 173, 153, 51, 96}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 245, 136, 72}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 171}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 161, 46, 224, 74, 65, 146, 69}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 124, 102, 208, 43, 94}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 195, 6, 52, 44}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 202, 213, 107, 65, 67}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 194, 7, 175, 240, 233}, 169}, {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{167, 180, 226, 144, 0, 49, 48, 196, 28, 75, 141, 198, 177, 193, 29, 186}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 78, 85}, 52}, {{167, 180, 226, 144, 0, 192, 108, 166, 128, 59, 213, 246, 224, 88, 251, 17}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 20, 72, 159, 87}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 229, 106, 82, 99, 14, 54, 146, 55, 53, 201}, 52}, {{167, 180, 226, 144, 0, 148, 83, 190, 33, 206, 92, 167, 48, 17, 172, 120}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 191, 134, 15, 134, 3, 33, 38, 199}, 52}, {{167, 180, 226, 144, 0, 0, 1, 231, 212, 205, 157, 176, 56, 156, 237, 212}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 218, 60, 152, 16, 167, 79}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 60}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 166, 42, 11, 14}, 52}, {{167, 180, 226, 144, 0, 0, 23, 106, 46, 168, 104, 185, 151, 116, 211, 170}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 200, 245, 243, 236, 42, 181, 77, 22}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 219, 70}, 52}, {{167, 180, 226, 144, 0, 0, 96, 108, 25, 250, 93, 200, 142, 221, 87, 132}, 52}, {{167, 180, 226, 144, 0, 232, 161, 71, 170, 6, 247, 15, 83, 109, 98, 253}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 9}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 253, 4, 30, 150}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 158}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 53, 174, 72, 216, 82, 62}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 147, 197, 105, 242, 23, 73, 100, 124}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 233, 122, 236, 3, 74, 115}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 52}, {{167, 180, 226, 144, 0, 0, 164, 112, 63, 143, 208, 187, 146, 185, 42, 75}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 80, 118, 213, 81, 247, 128, 37}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 71, 193, 227, 85, 145, 86, 120}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 52}, {{167, 180, 226, 144, 0, 0, 0, 143, 146, 113, 1, 22, 247, 170, 85, 70}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 52}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 87}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 179, 232, 114, 0}, 52}, {{167, 180, 226, 144, 0, 233, 120, 108, 85, 67, 116, 86, 108, 179, 130, 142}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 46, 203, 153, 193, 178, 56, 5}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 91, 227, 238, 219, 93, 151, 171, 191}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 179, 158, 17, 81, 57, 149, 197}, 52}, {{167, 180, 226, 144, 0, 154, 231, 55, 55, 58, 142, 79, 75, 176, 2, 117}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 235}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 216, 218, 130, 229}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 181, 95, 33, 91, 203}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 95, 111, 59, 232, 206, 161, 170}, 52}, {{167, 180, 226, 144, 0, 0, 0, 210, 182, 122, 44, 195, 35, 1, 173, 16}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 74, 239, 224, 180, 229, 235, 150, 176}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 69, 126}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 171, 246, 176, 204, 189, 45}, 52}, {{167, 180, 226, 144, 0, 0, 188, 184, 218, 245, 227, 82, 118, 95, 11, 102}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 119}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 38, 209, 233, 97, 116, 37, 236, 95}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 202, 189, 80, 26, 79, 24, 166, 106}, 52}, {{167, 180, 226, 144, 0, 0, 0, 51, 221, 242, 213, 64, 107, 46, 38, 248}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 119}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 212, 131}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 166, 46, 236, 245, 7, 108}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 125, 71, 161, 68, 177, 168, 41, 254, 88}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 52}, {{167, 180, 226, 144, 0, 0, 255, 151, 243, 147, 25, 169, 33, 73, 73, 235}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 246, 99}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 118, 220, 162, 12}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 137, 132}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 66, 145, 96, 146, 252, 8, 86, 164}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 229, 91, 118, 212}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 25, 218, 22, 1, 75, 130}, 52}, {{167, 180, 226, 144, 0, 9, 62, 245, 200, 178, 44, 122, 199, 13, 143, 201}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 52}, {{167, 180, 226, 144, 0, 0, 0, 5, 10, 219, 159, 203, 88, 9, 181, 212}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 34, 56, 217, 157, 30}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 211, 0, 80, 35, 106, 101, 225, 109}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 95, 138, 226, 180, 250, 38, 161, 118}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 189, 213, 1, 56}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 167, 226}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 28, 157}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 47, 48, 221, 105, 234, 226}, 52}, {{167, 180, 226, 144, 0, 0, 227, 52, 161, 43, 80, 12, 202, 110, 225, 200}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 64, 215}, 52}, {{167, 180, 226, 144, 0, 173, 55, 48, 211, 254, 249, 212, 91, 129, 107, 253}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 82}, 52}, {{167, 180, 226, 144, 0, 0, 33, 228, 181, 174, 24, 148, 2, 243, 53, 182}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 35, 115, 38, 103, 254, 134}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 142, 84}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 49, 229, 246, 114, 229, 37}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 199, 154}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 116, 186}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 73, 75}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 27, 74, 170, 85, 184, 100, 130, 122}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 254, 180, 167, 2, 68}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 167, 74, 38, 240}, 52}, {{167, 180, 226, 144, 0, 172, 76, 195, 165, 206, 160, 68, 8, 196, 244, 64}, 52}, {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 55, 216}, 52}, {{241, 0, 0, 211, 24, 250, 230, 57, 204, 33, 116, 248, 12, 187, 115, 249}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 220, 240, 127, 248, 216, 57, 71}, 149}, {{241, 0, 154, 218, 55, 105, 197, 102, 251, 123, 2, 237, 221, 249, 167, 209}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 213, 149, 209, 32}, 149}, {{241, 0, 0, 0, 111, 112, 8, 101, 45, 184, 144, 41, 46, 155, 151, 31}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 165, 33, 237, 211, 184, 126, 178}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 30, 22, 128, 109, 62, 237, 242, 181}, 149}, {{241, 0, 0, 19, 205, 184, 7, 134, 148, 67, 238, 209, 18, 188, 127, 126}, 149}, {{241, 0, 0, 217, 118, 38, 186, 176, 39, 160, 215, 35, 197, 17, 52, 240}, 149}, {{241, 0, 239, 245, 109, 214, 88, 154, 158, 204, 86, 190, 230, 214, 198, 99}, 149}, {{241, 0, 0, 86, 224, 176, 184, 62, 75, 166, 205, 66, 213, 219, 39, 208}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 83, 175, 90, 245, 118, 111, 60}, 149}, {{241, 0, 0, 0, 0, 0, 0, 26, 237, 255, 30, 201, 0, 174, 50, 9}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 117, 125, 49}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 55}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 242, 133}, 149}, {{241, 0, 0, 0, 64, 175, 146, 146, 136, 219, 201, 144, 184, 20, 127, 114}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 56, 116, 80, 243, 165, 9, 73, 138, 96, 111, 117, 183, 173, 117}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 166, 15, 197, 225}, 149}, {{241, 0, 0, 196, 36, 122, 250, 83, 105, 160, 67, 226, 243, 190, 55, 197}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 92, 119, 12, 62, 83, 244, 140}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 174, 205, 51}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 232, 86, 236, 192}, 149}, {{241, 0, 0, 160, 130, 75, 170, 198, 157, 117, 36, 137, 216, 77, 135, 194}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 11, 138, 124, 14, 91, 97, 192, 238}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 37, 101, 119, 227, 83, 202, 171, 116}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 210, 245, 201, 52}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 47, 239, 86, 150}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 253, 201, 89}, 149}, {{241, 0, 75, 132, 108, 205, 78, 136, 75, 137, 229, 109, 116, 101, 250, 22}, 149}, {{241, 0, 241, 199, 176, 75, 48, 196, 81, 36, 241, 44, 74, 203, 103, 76}, 149}, {{241, 0, 0, 0, 0, 122, 99, 150, 19, 20, 135, 212, 141, 245, 144, 17}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 199}, 149}, {{241, 0, 0, 160, 184, 188, 250, 70, 4, 154, 118, 47, 163, 139, 205, 180}, 149}, {{241, 0, 0, 0, 0, 86, 170, 217, 226, 20, 33, 251, 6, 235, 177, 49}, 149}, {{241, 0, 217, 39, 99, 47, 126, 129, 135, 60, 251, 24, 250, 14, 49, 246}, 149}, {{241, 0, 0, 0, 0, 0, 123, 13, 119, 161, 76, 252, 209, 28, 14, 171}, 149}, {{241, 0, 0, 0, 20, 195, 101, 106, 250, 21, 28, 81, 96, 45, 83, 163}, 149}, {{241, 0, 0, 0, 0, 0, 0, 72, 184, 221, 240, 43, 116, 99, 244, 160}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 17, 11}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 108}, 149}, {{241, 0, 0, 174, 160, 122, 237, 108, 186, 103, 230, 100, 182, 166, 134, 204}, 149}, {{241, 0, 0, 0, 0, 74, 206, 23, 55, 135, 55, 108, 154, 132, 227, 22}, 149}, {{241, 0, 0, 0, 0, 0, 57, 57, 131, 253, 66, 191, 109, 212, 72, 166}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 149}, {{241, 0, 83, 41, 174, 102, 101, 181, 42, 226, 179, 208, 163, 18, 159, 1}, 149}, {{241, 0, 0, 0, 124, 91, 169, 93, 147, 33, 255, 136, 176, 25, 244, 204}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 15, 210, 143, 154, 32, 47, 212}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 177, 85, 9, 101, 231}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 46, 154, 58, 240}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 36, 205}, 149}, {{241, 0, 0, 0, 0, 188, 27, 207, 213, 5, 114, 57, 212, 213, 72, 59}, 149}, {{241, 0, 0, 0, 0, 110, 105, 188, 152, 166, 111, 38, 190, 10, 251, 174}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 192, 92, 248, 163, 93, 168, 228, 76, 168, 216, 233, 50, 42}, 149}, {{241, 0, 0, 0, 0, 0, 183, 17, 235, 94, 224, 167, 124, 111, 242, 231}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 21, 135, 173, 120}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 137, 188, 199, 199, 162, 41, 207, 191}, 149}, {{241, 0, 0, 101, 74, 226, 212, 197, 129, 208, 90, 205, 240, 56, 216, 34}, 149}, {{241, 0, 0, 0, 0, 109, 137, 35, 181, 131, 92, 142, 115, 144, 165, 210}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 44, 201, 128, 155, 166, 168, 124}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 124, 40, 205}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 70}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 155, 166, 158}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 141, 54, 196, 51, 253}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 157, 212, 248, 182, 209, 141, 200, 232}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 30, 53, 131, 214}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 189, 73, 40}, 149}, {{241, 0, 0, 0, 248, 187, 148, 166, 6, 241, 73, 92, 127, 110, 202, 119}, 149}, {{241, 0, 0, 0, 0, 154, 33, 0, 171, 177, 30, 239, 186, 105, 169, 216}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 16, 59, 165, 221, 56, 69, 31, 105, 91, 210, 112, 242, 207}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 2, 206, 123}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 121, 238, 236, 175, 194, 148, 73, 66}, 149}, {{241, 0, 0, 0, 0, 0, 166, 146, 56, 110, 176, 158, 195, 32, 170, 36}, 149}, {{241, 0, 0, 78, 0, 73, 232, 191, 167, 249, 225, 136, 197, 173, 150, 149}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 244, 230, 3, 170}, 149}, {{241, 0, 0, 0, 0, 144, 65, 23, 102, 117, 92, 107, 76, 130, 77, 45}, 149}, {{241, 0, 0, 0, 198, 80, 89, 84, 248, 192, 8, 99, 132, 86, 229, 178}, 149}, {{241, 0, 0, 0, 238, 230, 146, 213, 0, 107, 196, 125, 50, 10, 94, 115}, 149}, {{241, 0, 0, 0, 0, 200, 159, 230, 84, 169, 200, 50, 152, 47, 167, 63}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 48, 120, 128}, 149}, {{241, 0, 0, 0, 230, 200, 178, 21, 244, 30, 122, 246, 216, 218, 9, 242}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 135, 44, 82, 76, 42, 175, 94, 209, 74}, 149}, {{241, 0, 0, 0, 0, 0, 0, 80, 241, 114, 127, 31, 81, 45, 134, 254}, 149}, {{241, 0, 0, 182, 36, 81, 171, 218, 184, 73, 82, 154, 85, 72, 36, 182}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 213, 47, 142, 69, 175, 141, 39}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 229, 11, 223}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 83, 64, 103, 132, 128, 200, 195, 137}, 149}, {{241, 0, 0, 56, 179, 42, 14, 46, 26, 202, 111, 5, 160, 117, 221, 251}, 149}, {{238, 9, 168, 96, 0, 137, 68, 34, 36, 32, 203, 246, 76, 207, 51, 215}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 164, 238}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 33, 184, 201, 188, 82, 73}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 39}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 156, 241, 100, 32, 185, 231, 98}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 57, 242, 106, 16, 140, 34}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 223, 33, 59, 195, 156, 22}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 28, 250, 254, 19, 191, 193, 186, 17}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 60, 131, 70, 20, 63, 129, 200, 99}, 74}, {{238, 9, 168, 96, 3, 185, 95, 111, 189, 156, 67, 25, 101, 84, 191, 197}, 74}, {{238, 9, 168, 96, 0, 0, 162, 175, 251, 247, 26, 57, 235, 103, 247, 113}, 74}, {{238, 9, 168, 96, 0, 0, 0, 172, 59, 119, 203, 127, 103, 18, 3, 82}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 66, 121, 74, 4, 27, 75, 244, 107}, 74}, {{238, 9, 168, 96, 0, 0, 0, 123, 89, 239, 6, 19, 21, 15, 71, 31}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 35}, 74}, {{238, 9, 168, 96, 0, 0, 96, 59, 124, 71, 133, 199, 98, 217, 231, 181}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 160, 27, 172, 103, 113, 206, 184}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 125, 46, 213, 118, 205, 161, 200}, 74}, {{238, 9, 168, 96, 0, 0, 0, 240, 254, 197, 61, 209, 32, 10, 87, 118}, 74}, {{238, 9, 168, 96, 0, 0, 0, 42, 6, 48, 79, 25, 179, 223, 49, 254}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 189, 29, 113, 79, 119, 138, 33}, 74}, {{238, 9, 168, 96, 0, 0, 0, 187, 90, 62, 203, 40, 115, 35, 161, 112}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 255, 103}, 74}, {{238, 9, 168, 96, 17, 223, 176, 161, 237, 187, 24, 151, 16, 9, 218, 194}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 204, 87}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 56, 195, 81, 174}, 74}, {{238, 9, 168, 96, 32, 57, 67, 191, 163, 163, 149, 202, 24, 179, 248, 11}, 74}, {{238, 9, 168, 96, 0, 0, 209, 247, 53, 64, 5, 57, 51, 100, 224, 12}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 123, 170}, 74}, {{238, 9, 168, 96, 0, 0, 182, 146, 59, 124, 203, 30, 195, 106, 13, 66}, 74}, {{238, 9, 168, 96, 0, 0, 205, 88, 253, 210, 70, 234, 162, 191, 220, 149}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 33, 222, 169, 165, 150, 223, 93, 71}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 23, 46}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 255, 40}, 74}, {{238, 9, 168, 96, 0, 0, 0, 73, 77, 54, 28, 30, 231, 152, 151, 111}, 74}, {{238, 9, 168, 96, 0, 0, 179, 95, 119, 146, 221, 183, 46, 23, 27, 251}, 74}, {{238, 9, 168, 96, 0, 0, 0, 198, 251, 82, 164, 36, 113, 73, 91, 197}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 82, 176, 71, 44, 209, 57, 151, 231, 201, 156, 227, 175}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 24, 149, 8, 63, 227}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 127, 138, 40, 130}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 83, 81}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 21, 90, 78, 251, 92, 118, 29, 121}, 74}, {{238, 9, 168, 96, 0, 0, 51, 215, 117, 208, 109, 13, 169, 35, 183, 176}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 202, 148, 112, 210, 80, 252}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 142, 72}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 218, 98, 244, 231, 119, 236, 248}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 124, 0, 10, 254, 244, 33, 55, 74}, 74}, {{238, 9, 168, 96, 1, 149, 194, 222, 195, 212, 28, 177, 80, 213, 6, 248}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 113, 243}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 116, 34, 15, 24, 134, 91, 182}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 63, 23, 75, 79, 76, 84, 159}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 51, 234}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 222, 232, 4, 48}, 74}, {{238, 9, 168, 96, 0, 84, 59, 154, 247, 56, 122, 65, 213, 4, 28, 129}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 139, 231, 34, 104, 252, 63, 129}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 137, 81, 89, 251, 176}, 74}, {{238, 9, 168, 96, 0, 0, 0, 93, 202, 45, 131, 95, 37, 49, 47, 50}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 131, 141}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 67, 6, 251, 251, 178, 106, 203}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 74}, {{238, 9, 168, 96, 0, 0, 174, 156, 87, 68, 210, 248, 184, 15, 234, 134}, 74}, {{238, 9, 168, 96, 10, 123, 255, 81, 197, 194, 58, 94, 135, 112, 135, 231}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 71, 6, 143, 170, 114, 153, 14, 248, 5, 162, 125}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 57, 239, 177, 217, 138}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 12, 176, 243, 58, 130, 110}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 74}, {{238, 9, 168, 96, 0, 24, 177, 170, 160, 38, 231, 63, 227, 20, 70, 146}, 74}, {{238, 9, 168, 96, 0, 0, 51, 173, 23, 225, 10, 137, 42, 42, 215, 81}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 1, 17, 201, 117, 195, 3, 251, 217, 139, 226, 237}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 196, 88, 246, 231, 151, 200}, 74}, {{238, 9, 168, 96, 0, 212, 11, 234, 19, 31, 54, 98, 52, 73, 0, 191}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 240, 13, 247, 34}, 74}, {{238, 9, 168, 96, 0, 0, 24, 27, 35, 57, 189, 126, 168, 146, 82, 39}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 126, 132}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 74}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 116, 26}, 74}, {{238, 9, 168, 96, 0, 7, 186, 159, 130, 190, 87, 195, 47, 251, 213, 222}, 74}, {{238, 9, 168, 96, 0, 0, 199, 8, 180, 160, 145, 205, 132, 49, 146, 119}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 219, 46, 21, 199}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 135, 67, 224, 148, 253, 31, 164, 143}, 74}, {{238, 9, 168, 96, 0, 50, 33, 235, 125, 57, 107, 1, 77, 89, 217, 241}, 74}, {{238, 9, 168, 96, 167, 42, 21, 100, 88, 14, 112, 161, 73, 47, 38, 131}, 74}, {{238, 9, 168, 96, 0, 17, 71, 170, 211, 13, 148, 92, 78, 67, 219, 148}, 74}, {{238, 9, 168, 96, 0, 0, 0, 0, 0, 213, 168, 180, 94, 252, 61, 63}, 74}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 212}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 238}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 196, 65, 144, 228, 20, 170}, 18}, {{59, 144, 0, 0, 102, 163, 220, 197, 18, 236, 117, 18, 114, 130, 231, 134}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 18}, {{59, 144, 0, 0, 0, 74, 197, 147, 1, 37, 107, 67, 126, 181, 25, 162}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 69}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 197, 54, 104, 92, 212, 135, 232, 197}, 18}, {{59, 144, 0, 0, 161, 186, 79, 187, 107, 163, 126, 245, 165, 207, 124, 243}, 18}, {{59, 144, 0, 0, 0, 0, 174, 190, 49, 37, 133, 95, 239, 194, 130, 59}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 176, 221}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 17}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 144, 228, 96, 27, 87, 18, 135, 74, 245, 129, 201}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 242, 181, 221, 22}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 18}, {{59, 144, 0, 0, 0, 203, 184, 188, 65, 253, 149, 76, 168, 158, 130, 189}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 196, 88, 54, 107, 102, 179, 253, 73}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 212, 11, 158, 126}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 77, 217, 58, 118, 25, 108}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 235, 227, 61, 189}, 18}, {{59, 144, 0, 0, 131, 200, 105, 51, 133, 81, 210, 80, 40, 214, 201, 36}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 223, 122, 226}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 235}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 52, 122, 175, 3}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 9, 246, 82}, 18}, {{59, 144, 0, 0, 0, 0, 58, 12, 11, 97, 6, 197, 124, 126, 147, 160}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 19, 103, 64, 164, 72, 175, 126}, 18}, {{59, 144, 0, 0, 0, 0, 0, 120, 80, 195, 201, 54, 162, 94, 99, 104}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 74, 194, 66, 175, 48, 60, 84, 217, 72, 199}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 253, 97, 146, 231, 156, 14, 165, 22, 48, 123, 67, 183}, 18}, {{59, 144, 0, 156, 162, 205, 178, 73, 222, 99, 55, 153, 85, 248, 251, 234}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 182, 4, 134, 54, 100, 125, 16, 164}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 123, 166, 177, 39}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 110, 100, 244, 62, 50, 254}, 18}, {{59, 144, 0, 0, 0, 42, 142, 64, 136, 98, 157, 112, 84, 19, 44, 145}, 18}, {{59, 144, 0, 0, 0, 0, 142, 173, 27, 117, 50, 243, 5, 253, 210, 31}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 152, 223, 205, 140, 36, 169}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 163, 44, 254, 51}, 18}, {{59, 144, 0, 0, 0, 0, 66, 35, 12, 51, 81, 105, 96, 209, 97, 82}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 82, 124, 250}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 184, 76, 179}, 18}, {{59, 144, 0, 0, 0, 42, 39, 144, 255, 219, 58, 57, 178, 153, 107, 130}, 18}, {{59, 144, 0, 0, 0, 0, 0, 77, 42, 115, 159, 186, 230, 236, 160, 16}, 18}, {{59, 144, 0, 0, 0, 0, 34, 63, 60, 67, 29, 191, 245, 216, 221, 117}, 18}, {{59, 144, 0, 0, 0, 0, 0, 42, 216, 15, 221, 182, 57, 198, 218, 82}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 136, 204, 222, 144}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 118, 201, 243}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 172}, 18}, {{59, 144, 0, 0, 0, 0, 0, 45, 98, 185, 215, 100, 248, 27, 183, 34}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 249, 239}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 47, 213}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 144, 7, 120, 138, 174, 195, 110, 147}, 18}, {{59, 144, 0, 0, 0, 0, 163, 126, 189, 197, 23, 145, 63, 10, 231, 64}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 97, 180, 201, 78, 69, 29, 33, 50, 115, 89, 60}, 18}, {{59, 144, 0, 0, 56, 106, 216, 28, 238, 112, 95, 27, 82, 93, 106, 201}, 18}, {{59, 144, 0, 0, 105, 192, 36, 205, 179, 32, 113, 165, 225, 182, 96, 105}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 239, 116}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 109}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 102, 230, 193, 189, 177, 193, 201, 160}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 202, 7, 128, 30, 76, 76, 204}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 22, 231, 8}, 18}, {{59, 144, 0, 0, 0, 0, 0, 37, 37, 43, 162, 148, 169, 56, 236, 4}, 18}, {{59, 144, 0, 0, 124, 184, 96, 128, 146, 11, 242, 238, 74, 232, 254, 120}, 18}, {{59, 144, 0, 0, 0, 0, 120, 244, 6, 159, 122, 3, 26, 71, 8, 171}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 84, 132, 243, 226, 233, 135, 71, 137}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 71, 216, 179, 126, 122, 82}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 71, 104, 69}, 18}, {{59, 144, 0, 0, 0, 0, 170, 139, 119, 192, 162, 63, 93, 226, 194, 136}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 229, 19, 66, 188, 138, 246, 89}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 78}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 168, 186, 126, 141, 31, 97, 9, 69}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 176}, 18}, {{59, 144, 0, 0, 0, 205, 134, 86, 243, 151, 22, 233, 176, 95, 176, 9}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 100, 203}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 127, 125, 251, 23, 240, 44, 215}, 18}, {{59, 144, 0, 0, 237, 25, 2, 7, 117, 186, 132, 204, 99, 155, 163, 123}, 18}, {{59, 144, 0, 171, 177, 209, 41, 228, 161, 248, 134, 194, 224, 104, 60, 121}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 53, 55}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 118, 72, 14, 129, 253, 89}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 185, 17, 226, 41, 199, 11}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 154, 244, 84, 251}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 86, 13, 127, 203, 24, 81, 14, 64}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 151, 111, 176}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 165, 212}, 18}, {{59, 144, 0, 0, 0, 64, 124, 233, 167, 115, 8, 155, 27, 98, 70, 212}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 138, 78, 211, 243, 179, 143}, 18}, {{59, 144, 0, 0, 0, 0, 0, 0, 180, 38, 9, 160, 88, 24, 90, 105}, 18}, {{59, 144, 0, 0, 89, 239, 22, 122, 128, 131, 203, 215, 205, 178, 190, 105}, 18}, {{59, 144, 0, 0, 0, 0, 255, 154, 120, 107, 225, 230, 146, 71, 179, 120}, 18}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 49, 238, 164}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 158, 178, 114, 47, 101, 203}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 36, 136}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 32}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 226}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 19, 80, 100, 37, 206, 218}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 191, 219, 32, 69, 54}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 79}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 34}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 197, 66, 230, 244, 99, 30}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 113, 212, 172, 170}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 151, 253, 111, 185}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 135, 233}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 77, 108, 72, 183, 29}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 38}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 28, 94, 230, 108, 122}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 35, 75, 202}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 3, 120, 226, 206, 181, 158}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 228, 157, 228, 53}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 23, 62, 23}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 175, 203}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 135, 21, 204, 95, 86}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 247}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 40, 55, 175, 162, 162}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 90}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 57}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 68, 23, 153, 173}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 198, 8, 194, 14}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 86, 181, 70}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 240, 50}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 166, 128, 29}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 211, 227, 108, 102, 158}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 186, 207, 56, 186, 22}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 158, 23, 127, 94, 248}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 175, 128}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 237}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 124, 218}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 207, 65}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 140, 132, 49, 182}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 14, 75, 140}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 67, 154, 177, 194}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 189, 46, 22, 119, 125, 80}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 252, 96, 44, 184, 244}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 234, 154, 189, 87, 126}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 147, 191}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 118, 237}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 156, 67}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 250, 123, 202, 94, 144}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 63, 126, 138, 134}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 94, 180, 58, 63, 191, 191}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 150, 70, 136, 80, 234, 153}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 30}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 51, 158, 13, 19, 250}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 136, 169, 184, 18}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 202, 11, 61, 51, 176, 77}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 16}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 129}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 204, 73, 151, 87, 101}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 126, 72, 241, 137, 1, 23}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 242, 200}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 226, 152, 91}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 45, 195}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 51, 197, 181, 44}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 113, 169, 97, 222, 90}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 207}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 217, 92}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 83, 112, 141, 194, 77}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 131, 58, 228, 14, 227}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 137, 69, 18}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 72, 172, 251}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 167, 129, 140, 212}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 29, 215}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 219, 199, 179, 157, 138, 171}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 253}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 180, 233, 27, 204}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 49, 99, 123, 47}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 166, 10, 251, 33}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 213, 202, 148, 218}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 58, 80, 60, 93, 17, 225}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 14}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 107, 25, 220, 31}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 16}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 76, 82, 73, 146}, 155}, {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 102, 176, 41, 140}, 155}, {{152, 79, 219, 0, 0, 208, 83, 188, 96, 181, 55, 63, 95, 37, 49, 233}, 97}, {{152, 79, 219, 0, 86, 133, 47, 231, 225, 51, 130, 214, 70, 160, 195, 202}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 40, 191, 167, 36, 243, 171}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 155, 224, 166, 215, 41, 214, 52}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 86, 132}, 97}, {{152, 79, 219, 0, 0, 0, 0, 153, 107, 179, 13, 120, 78, 56, 92, 47}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 251}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 175, 210, 245, 224, 232, 57, 199}, 97}, {{152, 79, 219, 0, 0, 0, 123, 43, 177, 185, 229, 84, 103, 223, 112, 42}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 31, 172, 205}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 17, 213, 187, 52, 203, 143, 213}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 110, 47, 143, 49, 226, 66, 91}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 226, 233, 213, 43, 215, 250, 75, 61}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 231, 243, 146, 180, 101, 233}, 97}, {{152, 79, 219, 0, 0, 229, 178, 229, 181, 199, 190, 253, 136, 109, 79, 151}, 97}, {{152, 79, 219, 0, 0, 0, 0, 150, 111, 16, 24, 13, 92, 139, 68, 109}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 98, 79, 53, 58, 220}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 248, 199, 151, 139, 39, 227, 132}, 97}, {{152, 79, 219, 0, 0, 0, 0, 247, 42, 17, 121, 184, 207, 32, 117, 183}, 97}, {{152, 79, 219, 0, 0, 45, 106, 223, 114, 156, 41, 141, 12, 236, 219, 183}, 97}, {{152, 79, 219, 0, 0, 0, 105, 202, 246, 78, 149, 84, 142, 63, 6, 166}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 93, 3, 162, 160, 217, 158, 230, 106}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 168}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 236, 157, 121, 203, 213, 154}, 97}, {{152, 79, 219, 0, 0, 0, 54, 96, 119, 26, 156, 212, 75, 18, 36, 75}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 71, 74, 177, 241, 14, 6, 178}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 102, 58, 144, 40, 251, 24}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 222, 76, 109, 6, 22, 181, 21, 24}, 97}, {{152, 79, 219, 0, 218, 104, 245, 140, 27, 108, 53, 53, 139, 148, 79, 214}, 97}, {{152, 79, 219, 0, 0, 254, 17, 21, 8, 215, 126, 179, 116, 49, 228, 136}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 27, 176, 122, 58, 197, 192, 199, 3}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 182}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 205, 227, 102}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 120, 41, 70}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 147, 158, 212, 199, 112, 111, 209}, 97}, {{152, 79, 219, 0, 0, 164, 93, 50, 214, 182, 102, 180, 28, 167, 139, 112}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 110, 61, 219, 48, 246, 20}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 23, 4, 175, 180, 91, 38}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 204, 244}, 97}, {{152, 79, 219, 0, 0, 0, 0, 126, 18, 10, 134, 88, 116, 150, 184, 146}, 97}, {{152, 79, 219, 0, 0, 0, 97, 189, 183, 69, 19, 190, 210, 24, 75, 192}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 232, 117, 24, 37, 85}, 97}, {{152, 79, 219, 0, 244, 117, 244, 14, 83, 58, 15, 127, 6, 178, 147, 2}, 97}, {{152, 79, 219, 0, 0, 0, 28, 121, 233, 131, 255, 110, 97, 72, 45, 66}, 97}, {{152, 79, 219, 0, 0, 0, 0, 237, 44, 106, 1, 68, 177, 83, 80, 16}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 27, 62, 86, 119, 73, 55, 115, 19}, 97}, {{152, 79, 219, 0, 0, 59, 31, 240, 208, 246, 143, 20, 63, 240, 191, 190}, 97}, {{152, 79, 219, 0, 224, 2, 187, 230, 149, 36, 185, 157, 30, 189, 31, 176}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 119, 136, 216}, 97}, {{152, 79, 219, 0, 219, 51, 170, 161, 28, 190, 54, 198, 165, 139, 101, 19}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 180, 180, 155, 35, 125, 88, 180, 254, 68, 63, 221, 190}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 248, 150, 241, 52, 59, 133}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 178, 196, 15}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 126, 28, 103, 178, 192, 76, 236, 30}, 97}, {{152, 79, 219, 0, 0, 216, 234, 178, 206, 203, 150, 117, 148, 93, 86, 178}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 67, 83, 41, 147, 206, 141}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 173, 208, 76, 96, 225, 112, 153}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 224, 156}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 111, 145, 132, 211, 255}, 97}, {{152, 79, 219, 0, 0, 0, 152, 9, 7, 178, 58, 146, 54, 206, 101, 42}, 97}, {{152, 79, 219, 0, 190, 157, 182, 184, 87, 111, 47, 0, 202, 100, 54, 244}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 97}, {{152, 79, 219, 0, 0, 59, 183, 74, 71, 180, 237, 232, 179, 22, 155, 224}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 172, 136, 79, 174, 250, 96}, 97}, {{152, 79, 219, 0, 0, 0, 0, 139, 28, 145, 209, 185, 251, 217, 150, 161}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 213, 180}, 97}, {{152, 79, 219, 0, 112, 104, 242, 58, 152, 139, 95, 12, 35, 87, 153, 94}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 200, 76, 211}, 97}, {{152, 79, 219, 0, 0, 0, 0, 116, 189, 111, 135, 155, 31, 245, 193, 86}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 119, 221, 251, 64, 158, 168}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 92}, 97}, {{152, 79, 219, 0, 0, 0, 123, 64, 166, 219, 36, 239, 154, 232, 78, 113}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 251, 223, 197, 200, 188, 186, 4, 134}, 97}, {{152, 79, 219, 0, 0, 111, 185, 13, 17, 28, 200, 200, 120, 30, 216, 142}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 97}, {{152, 79, 219, 0, 40, 135, 69, 131, 153, 48, 222, 85, 44, 104, 25, 69}, 97}, {{152, 79, 219, 0, 0, 0, 0, 91, 217, 249, 206, 248, 77, 92, 177, 214}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 23, 117}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 234, 168, 209, 95, 70, 0, 105}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 83}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 198, 192, 51, 96, 86}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 97}, {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 226, 117, 12, 72, 19, 153}, 97}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 82, 222, 227, 178, 82, 20, 190}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 132, 54}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 71, 183, 86, 188, 45, 224}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 219, 75}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 133, 107, 60, 54, 74}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 209, 13, 217, 39, 46, 162, 240, 90}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 148}, 8}, {{118, 186, 157, 248, 0, 0, 0, 184, 112, 74, 109, 12, 88, 233, 152, 231}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 187, 17}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 82, 243, 29, 238, 38}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 193, 201, 227, 141, 240, 203}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 49, 235, 126, 20, 206, 72, 206}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 108}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 69, 25, 162, 252, 189}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 14, 198, 144, 247, 0, 13, 170}, 8}, {{118, 186, 157, 248, 0, 86, 183, 41, 26, 30, 170, 13, 229, 143, 62, 111}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 158}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 53, 176, 167, 3, 225, 72}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 182, 141}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 58, 142, 69, 247, 83}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 198, 22, 162, 96, 226, 87, 225}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 28, 150, 57, 41, 75, 243, 240}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 218, 229, 203, 118, 0, 242}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 157}, 8}, {{118, 186, 157, 248, 0, 0, 183, 61, 232, 87, 182, 200, 86, 68, 129, 255}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 85}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 89, 233, 134, 20}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 223}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 174, 165, 121, 171, 7, 231, 184, 218}, 8}, {{118, 186, 157, 248, 0, 74, 8, 103, 189, 148, 251, 235, 43, 214, 171, 173}, 8}, {{118, 186, 157, 248, 0, 0, 0, 97, 73, 248, 80, 204, 181, 205, 108, 65}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 225, 142, 205, 130, 24}, 8}, {{118, 186, 157, 248, 0, 0, 248, 62, 5, 232, 52, 54, 148, 42, 1, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 133, 89, 213, 146, 59, 245, 191, 167, 219}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 57, 99, 240, 31, 54}, 8}, {{118, 186, 157, 248, 0, 0, 0, 177, 57, 11, 205, 103, 60, 132, 205, 238}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 233, 16, 78, 90, 80, 98, 167, 125}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 54, 101, 153, 101, 253, 152, 227, 225}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 86, 24, 139, 59, 128, 178, 198, 50}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 8}, {{118, 186, 157, 248, 0, 1, 253, 215, 134, 136, 94, 150, 18, 114, 220, 68}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 221, 165, 137, 125, 214}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 248}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 90, 95, 105, 180, 21}, 8}, {{118, 186, 157, 248, 0, 120, 186, 217, 126, 182, 105, 146, 252, 251, 117, 248}, 8}, {{118, 186, 157, 248, 0, 108, 135, 227, 235, 111, 249, 54, 185, 121, 82, 18}, 8}, {{118, 186, 157, 248, 0, 58, 126, 121, 35, 205, 1, 12, 20, 151, 200, 23}, 8}, {{118, 186, 157, 248, 0, 0, 111, 144, 231, 93, 123, 226, 184, 188, 3, 26}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 118, 253}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 93, 211}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 8}, {{118, 186, 157, 248, 0, 127, 179, 200, 153, 197, 60, 217, 29, 125, 144, 158}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 85, 142, 235, 83, 12, 39, 124}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 74, 240, 147, 93, 253, 203}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 71, 213, 60, 85, 34}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 126, 139}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 23, 198, 96, 25, 69, 52, 235, 45}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 76, 147}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 141, 225, 194, 98, 89, 54, 189, 32, 42, 220, 251}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 119}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 193, 162, 77, 113, 94, 7, 202}, 8}, {{118, 186, 157, 248, 0, 9, 6, 194, 139, 159, 83, 48, 225, 220, 49, 232}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 170, 99, 103, 235, 228}, 8}, {{118, 186, 157, 248, 0, 177, 19, 61, 123, 97, 108, 220, 96, 24, 1, 206}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 86, 138, 65, 177, 222, 224}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 220, 112, 2, 23, 176, 92, 35, 9}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 242, 21, 37, 199, 139, 177, 201}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 86, 169}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 42, 234, 158, 15, 132}, 8}, {{118, 186, 157, 248, 0, 0, 0, 2, 83, 108, 239, 38, 246, 172, 198, 72}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 0, 140, 128, 190, 176, 93, 248, 4, 166, 99, 85}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 65, 12, 111, 8}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 117, 232}, 8}, {{118, 186, 157, 248, 0, 0, 0, 230, 10, 125, 131, 3, 237, 74, 132, 85}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 207, 211, 145, 254}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 69, 206, 240, 243}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 137, 194}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 133, 80, 49, 173}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 215, 171, 79, 45, 235, 234}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 166, 58, 127, 223, 35, 126, 20}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 30, 178, 247, 177}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 8}, {{118, 186, 157, 248, 0, 110, 242, 102, 22, 164, 136, 88, 40, 131, 81, 120}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 8, 107, 113, 201, 0}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 164, 113}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 162, 23, 211, 0, 224, 81, 31, 36}, 8}, {{118, 186, 157, 248, 0, 0, 0, 91, 241, 251, 187, 197, 155, 240, 39, 216}, 8}, {{118, 186, 157, 248, 0, 232, 144, 136, 230, 239, 197, 58, 54, 62, 170, 139}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 59, 254, 78, 244, 90, 51}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 182}, 8}, {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 238, 184}, 8}, {{118, 186, 157, 248, 0, 0, 47, 39, 73, 171, 99, 158, 116, 174, 233, 233}, 8}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 94, 221}, 123}, {{70, 128, 0, 0, 0, 0, 0, 128, 162, 207, 209, 113, 22, 97, 95, 0}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 96, 34, 133, 119, 20, 35, 161}, 123}, {{70, 128, 0, 0, 0, 222, 14, 236, 201, 171, 208, 181, 97, 175, 147, 234}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 60, 32, 203, 41, 89, 102, 48}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 251, 194, 255, 235, 255, 183, 159, 192}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 226, 124, 255, 1, 160, 202, 136}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 123, 80}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 43, 21, 234, 41, 140, 199}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 17}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 253, 100, 10, 194}, 123}, {{70, 128, 0, 0, 0, 209, 74, 140, 214, 70, 119, 70, 138, 66, 0, 164}, 123}, {{70, 128, 0, 178, 152, 16, 64, 130, 211, 206, 93, 196, 151, 70, 75, 56}, 123}, {{70, 128, 0, 0, 175, 23, 150, 33, 144, 94, 108, 52, 90, 205, 139, 144}, 123}, {{70, 128, 28, 201, 85, 103, 58, 50, 130, 241, 128, 112, 219, 123, 219, 205}, 123}, {{70, 128, 0, 0, 0, 42, 51, 192, 21, 194, 125, 236, 112, 146, 108, 44}, 123}, {{70, 128, 0, 0, 204, 195, 120, 74, 125, 226, 245, 91, 238, 67, 6, 23}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 161, 244, 128, 119}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 63, 173, 195, 105, 155, 5, 6, 85}, 123}, {{70, 128, 0, 0, 0, 11, 215, 17, 237, 121, 149, 17, 109, 22, 15, 60}, 123}, {{70, 128, 0, 0, 0, 0, 144, 14, 21, 207, 68, 77, 139, 44, 247, 211}, 123}, {{70, 128, 0, 0, 0, 0, 131, 197, 249, 242, 61, 196, 192, 127, 105, 97}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 14, 236, 113, 29, 183, 76, 157, 5, 67, 98, 161, 12, 100}, 123}, {{70, 128, 0, 0, 0, 0, 0, 67, 246, 86, 92, 232, 36, 171, 89, 202}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 181, 248}, 123}, {{70, 128, 0, 0, 0, 0, 101, 6, 222, 17, 220, 184, 146, 81, 74, 130}, 123}, {{70, 128, 0, 0, 0, 245, 145, 44, 249, 85, 168, 4, 252, 205, 170, 169}, 123}, {{70, 128, 0, 0, 0, 173, 87, 80, 131, 66, 169, 68, 159, 153, 227, 239}, 123}, {{70, 128, 0, 12, 15, 111, 1, 105, 149, 185, 169, 65, 82, 33, 76, 73}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 54, 252, 237, 4, 158, 69, 12}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 152, 70, 178, 152, 49, 145, 87}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 12, 0, 237, 193, 212, 242, 119, 248}, 123}, {{70, 128, 0, 0, 242, 182, 30, 155, 128, 39, 242, 223, 206, 53, 136, 6}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 45, 183}, 123}, {{70, 128, 0, 0, 0, 0, 142, 153, 48, 181, 104, 136, 111, 239, 119, 238}, 123}, {{70, 128, 0, 0, 0, 0, 186, 26, 108, 94, 147, 160, 117, 65, 49, 100}, 123}, {{70, 128, 0, 0, 0, 50, 49, 69, 61, 64, 161, 113, 76, 205, 96, 23}, 123}, {{70, 128, 0, 0, 0, 255, 239, 168, 254, 98, 61, 182, 70, 17, 124, 167}, 123}, {{70, 128, 69, 97, 171, 66, 181, 10, 59, 36, 38, 66, 5, 53, 41, 63}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 84}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 126, 72, 27, 34}, 123}, {{70, 128, 0, 0, 70, 141, 78, 39, 172, 185, 155, 166, 122, 165, 53, 114}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 170, 142, 158, 156, 147, 61}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 221, 94, 135, 25, 20, 233, 195, 151}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 160, 223, 230, 27}, 123}, {{70, 128, 0, 0, 0, 0, 55, 193, 189, 23, 58, 255, 241, 109, 252, 61}, 123}, {{70, 128, 0, 0, 0, 0, 0, 90, 92, 27, 220, 148, 141, 196, 3, 55}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 28, 160}, 123}, {{70, 128, 0, 22, 146, 90, 209, 10, 135, 163, 54, 139, 240, 198, 237, 246}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 235, 186, 188, 34, 49, 23}, 123}, {{70, 128, 0, 0, 0, 108, 151, 147, 165, 89, 75, 173, 156, 148, 192, 35}, 123}, {{70, 128, 0, 0, 0, 0, 0, 251, 240, 158, 182, 117, 120, 119, 104, 156}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 223, 79, 11, 226, 105, 202}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 214, 244, 214, 85, 0, 234, 5}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 212, 68, 118, 10, 191, 28}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 109, 9, 52, 229, 215, 233, 233, 100}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 149, 16, 24, 66, 17, 95}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 168, 163}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 6, 156, 198, 206, 163, 44, 70, 181, 184, 3, 171}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 136, 235}, 123}, {{70, 128, 0, 34, 216, 175, 173, 235, 244, 42, 62, 74, 169, 139, 186, 1}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 111, 12, 154, 157, 175, 10, 172, 102}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 128, 1, 218, 39}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 210, 154, 119, 82, 55, 177, 229}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 155, 147, 234, 245, 131, 81}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 49}, 123}, {{70, 128, 0, 0, 0, 0, 85, 213, 226, 71, 155, 89, 81, 193, 229, 95}, 123}, {{70, 128, 36, 114, 112, 189, 159, 85, 68, 194, 101, 204, 63, 64, 155, 89}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 82, 84, 21, 13, 223, 105, 159, 100}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 24, 156, 147, 248, 31, 185, 137}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 1}, 123}, {{70, 128, 0, 0, 0, 100, 226, 245, 223, 167, 116, 170, 235, 177, 9, 73}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 123}, {{70, 128, 0, 0, 0, 0, 188, 35, 32, 191, 127, 27, 111, 180, 7, 139}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 181, 203}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 142}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 124, 212}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 109, 23, 212, 235, 147, 79}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 159, 229, 183, 58, 65, 66, 205, 230}, 123}, {{70, 128, 0, 0, 0, 124, 182, 25, 130, 134, 220, 27, 218, 232, 28, 152}, 123}, {{70, 128, 0, 0, 45, 250, 51, 228, 121, 236, 184, 124, 0, 182, 241, 111}, 123}, {{70, 128, 0, 0, 36, 205, 9, 71, 193, 70, 188, 226, 207, 19, 211, 88}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 186, 121}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 196, 51}, 123}, {{70, 128, 0, 0, 0, 0, 160, 98, 250, 126, 170, 3, 155, 50, 247, 243}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 4, 92, 173, 130, 142, 243}, 123}, {{70, 128, 0, 0, 49, 149, 220, 51, 237, 113, 146, 189, 9, 210, 166, 9}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 100, 3, 64}, 123}, {{70, 128, 130, 179, 96, 32, 179, 5, 115, 61, 51, 14, 219, 144, 28, 13}, 123}, {{70, 128, 0, 252, 196, 253, 7, 151, 106, 96, 120, 217, 79, 59, 28, 18}, 123}, {{70, 128, 0, 0, 0, 91, 170, 244, 233, 43, 241, 184, 33, 68, 116, 138}, 123}, {{70, 128, 0, 199, 149, 58, 32, 6, 86, 21, 229, 200, 149, 167, 132, 138}, 123}, {{70, 128, 0, 0, 0, 0, 0, 0, 131, 42, 58, 141, 215, 53, 107, 117}, 123}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 41}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 164, 50, 229}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 63}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 122, 165, 8, 212}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 74, 64, 71}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 67, 82, 135}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 50, 140}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 4}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 77}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 72, 25}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 184, 166}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 8, 37, 183, 186}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 50, 153, 47}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 53, 189, 195, 152}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 56}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 62, 15, 131}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 134, 220}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 67, 169, 96, 209}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 156, 27}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 168}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 250, 79}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 5}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 19, 212}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 95}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 39}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 42, 107, 111, 206}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 106, 186, 69, 122}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 199, 224}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 159}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 129, 138, 64, 167}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 82}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 80}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 107, 155, 161}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 206}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 122, 105, 164, 219}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 12, 173, 157, 9}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 165, 27}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 243, 156, 116}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 143, 113}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 192}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 181, 51}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 99, 217, 78}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 13, 28}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 70}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 184, 30, 132}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 219, 114, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 121, 215, 156, 185}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 171, 27, 169}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 126, 95, 126}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 66}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 219, 89}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 117, 131}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 211, 243, 66}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 191}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 146}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 241, 95}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 17}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 90}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 177}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 144}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 127, 87}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 2, 47, 62}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 37, 43, 89}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 50, 226, 102}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 117}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 36, 238}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 112}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 48, 109}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 36}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 126}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 105}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 143, 247}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 53}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 71, 19, 75}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 212, 98, 2}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 89, 240}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 11}, {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 224, 116}, 11}, {{166, 112, 0, 190, 25, 219, 187, 102, 1, 20, 198, 20, 249, 174, 23, 231}, 211}, {{166, 112, 0, 0, 0, 26, 149, 172, 231, 217, 23, 103, 106, 23, 201, 71}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 108}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 67, 225}, 211}, {{166, 112, 0, 0, 223, 83, 171, 151, 74, 177, 6, 37, 219, 69, 233, 89}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 99, 172, 97, 16, 56, 254}, 211}, {{166, 112, 251, 98, 181, 225, 36, 127, 73, 56, 209, 248, 89, 88, 56, 232}, 211}, {{166, 112, 0, 0, 155, 125, 94, 147, 14, 171, 60, 115, 189, 236, 170, 37}, 211}, {{166, 112, 0, 0, 0, 0, 0, 17, 186, 4, 170, 165, 5, 195, 236, 113}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 99}, 211}, {{166, 112, 0, 0, 0, 0, 0, 4, 155, 138, 214, 36, 100, 218, 159, 62}, 211}, {{166, 112, 0, 0, 0, 0, 0, 255, 246, 113, 11, 169, 196, 183, 16, 82}, 211}, {{166, 112, 0, 0, 0, 0, 182, 201, 231, 123, 201, 59, 194, 111, 196, 36}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 5, 16, 86, 246, 155, 190, 226}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 202, 107, 206, 79}, 211}, {{166, 112, 0, 0, 0, 0, 109, 72, 212, 197, 239, 205, 226, 255, 171, 206}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 110}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 120, 94, 219, 65, 229, 115, 224}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 153}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 245, 35, 77, 39, 53, 110, 241}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 87}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 42, 85, 80, 45}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 191}, 211}, {{166, 112, 117, 222, 211, 118, 157, 76, 25, 57, 131, 235, 241, 64, 153, 93}, 211}, {{166, 112, 0, 188, 14, 166, 43, 100, 147, 185, 88, 216, 19, 60, 255, 27}, 211}, {{166, 112, 0, 0, 0, 52, 205, 96, 67, 187, 91, 251, 14, 146, 49, 184}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 74, 252, 104, 145, 82, 15, 10, 165, 63}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 142, 15, 77, 99, 83, 5}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 100, 49, 65}, 211}, {{166, 112, 0, 0, 0, 0, 248, 95, 47, 30, 133, 176, 232, 103, 100, 249}, 211}, {{166, 112, 0, 0, 0, 0, 145, 26, 126, 199, 212, 212, 49, 56, 201, 59}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 114, 53, 203, 79, 128, 251}, 211}, {{166, 112, 0, 0, 0, 0, 0, 232, 160, 102, 226, 6, 22, 90, 130, 104}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 158, 42, 226, 127}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 114, 110, 8}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 80, 217, 190, 2, 224, 155, 173}, 211}, {{166, 112, 0, 0, 124, 110, 152, 102, 80, 47, 177, 54, 19, 45, 181, 82}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 42, 67, 135, 11}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 195, 123, 142, 106}, 211}, {{166, 112, 0, 223, 83, 153, 34, 10, 138, 243, 3, 107, 166, 34, 106, 38}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 31, 238, 172}, 211}, {{166, 112, 0, 0, 0, 0, 0, 192, 216, 79, 227, 79, 224, 10, 147, 116}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 186, 153, 48, 62}, 211}, {{166, 112, 0, 0, 0, 0, 181, 36, 208, 169, 208, 11, 199, 154, 7, 147}, 211}, {{166, 112, 0, 0, 0, 49, 69, 200, 203, 57, 181, 36, 155, 151, 68, 171}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 254, 26, 98, 191}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 102, 223, 107, 250}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 104}, 211}, {{166, 112, 0, 0, 0, 197, 59, 20, 247, 70, 201, 193, 9, 222, 155, 60}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 117, 105, 193, 168, 19, 113, 34}, 211}, {{166, 112, 0, 0, 0, 0, 119, 159, 4, 228, 81, 3, 223, 111, 112, 246}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 35, 91, 126, 119}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 186, 116, 231, 255, 30, 168, 110}, 211}, {{166, 112, 0, 0, 169, 192, 89, 202, 9, 172, 152, 16, 126, 232, 18, 34}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 46, 110, 7, 212}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 205, 115, 54, 127, 211, 59, 237, 187, 31, 225}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 185, 74, 104}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 233, 153, 86, 162}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 62, 131, 195, 140, 119, 146, 18}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 60, 111, 201, 219, 120, 110}, 211}, {{166, 112, 221, 51, 5, 181, 16, 89, 16, 110, 223, 189, 124, 1, 243, 100}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 5, 201, 249, 194}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 182}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 140, 181, 40}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 24, 60, 124, 120, 193, 232}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 25, 179, 90, 55, 109, 247}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 27, 135, 100, 201, 227, 165}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 211}, {{166, 112, 0, 0, 0, 81, 20, 100, 163, 154, 205, 96, 183, 228, 246, 115}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 48}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 151}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 211}, {{166, 112, 0, 105, 52, 149, 99, 246, 131, 46, 223, 109, 76, 168, 4, 183}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 87, 66, 170, 228, 32, 6}, 211}, {{166, 112, 0, 0, 0, 0, 0, 38, 184, 208, 234, 85, 120, 58, 135, 125}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 10, 2, 99, 110, 190, 166, 24, 98}, 211}, {{166, 112, 0, 243, 253, 123, 2, 4, 142, 28, 20, 49, 30, 142, 82, 49}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 232, 23, 240, 154, 214, 81, 95}, 211}, {{166, 112, 0, 0, 0, 0, 0, 32, 99, 88, 237, 67, 185, 47, 101, 190}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 223, 108, 45}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 220, 245, 132}, 211}, {{166, 112, 0, 0, 0, 0, 0, 224, 8, 178, 218, 122, 214, 108, 90, 57}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 145, 138, 248, 146, 185, 208, 150}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 125, 148}, 211}, {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{43, 95, 224, 0, 186, 235, 217, 42, 160, 69, 219, 155, 93, 209, 163, 175}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 231, 124, 215, 178, 244, 97}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 174, 4, 109, 203, 209, 132, 128, 129, 172, 162}, 116}, {{43, 95, 224, 0, 0, 0, 183, 81, 118, 30, 40, 141, 221, 103, 148, 223}, 116}, {{43, 95, 224, 0, 0, 0, 65, 82, 102, 236, 221, 45, 157, 74, 148, 104}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 116}, {{43, 95, 224, 0, 94, 176, 48, 101, 185, 96, 57, 109, 67, 30, 3, 76}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 45}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 246, 194, 245}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 83, 59, 100, 112, 255, 109, 206}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 100, 84, 170, 39, 92}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 235}, 116}, {{43, 95, 224, 0, 84, 205, 85, 41, 51, 212, 43, 213, 113, 226, 156, 170}, 116}, {{43, 95, 224, 0, 50, 140, 108, 38, 24, 206, 159, 126, 16, 121, 66, 85}, 116}, {{43, 95, 224, 204, 234, 128, 248, 83, 242, 203, 231, 216, 142, 123, 32, 228}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 33, 201, 230, 1, 109, 28, 162}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 101, 83, 106, 159, 147}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 138, 158, 113, 3, 149}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 63, 161, 155, 221, 77, 11}, 116}, {{43, 95, 224, 0, 0, 0, 154, 228, 149, 116, 76, 232, 73, 204, 232, 158}, 116}, {{43, 95, 224, 0, 0, 70, 2, 220, 17, 179, 137, 122, 249, 72, 82, 166}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 155, 89, 239}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 249, 1}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 47, 155, 166, 227, 147, 135, 221, 15}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 246, 146}, 116}, {{43, 95, 224, 0, 79, 152, 19, 161, 202, 162, 13, 178, 80, 149, 55, 51}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 237, 16, 89, 161, 237, 144}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 64, 240, 242, 112, 20, 136}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 61}, 116}, {{43, 95, 224, 0, 0, 149, 122, 157, 98, 57, 64, 142, 217, 191, 115, 55}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 44, 75}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 230, 136, 254}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 219, 102, 216, 185, 153, 43}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 3, 109, 213, 239, 177, 233}, 116}, {{43, 95, 224, 0, 0, 0, 110, 89, 253, 39, 21, 200, 213, 16, 243, 24}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 230, 153, 36, 130, 18, 184, 102}, 116}, {{43, 95, 224, 0, 0, 229, 248, 74, 52, 115, 176, 82, 211, 236, 198, 37}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 133, 215, 73}, 116}, {{43, 95, 224, 0, 0, 0, 0, 91, 242, 21, 145, 39, 30, 57, 254, 144}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 232, 146, 101, 6, 228, 154, 113, 253, 51, 183}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 129, 78, 49, 74, 26, 31, 232, 199, 110, 149, 99}, 116}, {{43, 95, 224, 0, 59, 107, 143, 254, 40, 214, 163, 9, 177, 103, 167, 212}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 31, 251, 63, 153, 143}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 143, 189}, 116}, {{43, 95, 224, 0, 49, 231, 173, 119, 192, 239, 236, 70, 67, 91, 254, 246}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 222, 135, 30, 37, 59}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 190, 150, 191}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 157, 138}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 246, 83, 94, 22, 110}, 116}, {{43, 95, 224, 0, 17, 54, 112, 187, 164, 198, 165, 216, 236, 139, 214, 169}, 116}, {{43, 95, 224, 203, 30, 87, 207, 20, 113, 36, 250, 57, 228, 147, 213, 171}, 116}, {{43, 95, 224, 0, 2, 229, 57, 221, 122, 230, 142, 165, 182, 169, 227, 2}, 116}, {{43, 95, 224, 0, 93, 17, 21, 187, 3, 130, 28, 44, 36, 116, 180, 175}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 34, 163, 12}, 116}, {{43, 95, 224, 0, 0, 0, 19, 203, 111, 81, 7, 112, 130, 158, 233, 67}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 195}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 69, 136}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138}, 116}, {{43, 95, 224, 0, 0, 128, 217, 201, 99, 177, 1, 63, 47, 22, 170, 229}, 116}, {{43, 95, 224, 0, 0, 0, 0, 155, 210, 153, 12, 240, 46, 46, 21, 34}, 116}, {{43, 95, 224, 85, 50, 51, 150, 54, 171, 165, 12, 255, 210, 170, 25, 140}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 35, 109, 165, 153, 213, 193, 154, 38}, 116}, {{43, 95, 224, 187, 47, 16, 66, 232, 172, 167, 35, 145, 233, 238, 1, 164}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 140, 84, 236, 224, 232, 84}, 116}, {{43, 95, 224, 0, 0, 0, 0, 199, 89, 241, 94, 144, 154, 31, 122, 140}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 42, 195, 137}, 116}, {{43, 95, 224, 0, 0, 251, 251, 143, 174, 206, 155, 169, 145, 91, 28, 80}, 116}, {{43, 95, 224, 0, 0, 106, 167, 73, 175, 43, 36, 125, 40, 160, 118, 82}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 183, 151, 66, 62, 223}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 183, 17}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 146, 27, 233, 156, 235, 7, 187}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 20, 244}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 157, 130, 49, 174, 241, 205, 14, 208}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 47, 201, 156, 0, 224, 96, 135}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 199, 90, 227, 153, 37}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 27, 108}, 116}, {{43, 95, 224, 157, 163, 245, 141, 37, 97, 76, 126, 223, 17, 79, 26, 241}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 227, 108}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 50, 76}, 116}, {{43, 95, 224, 0, 0, 0, 104, 94, 124, 244, 79, 159, 199, 70, 228, 252}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 106, 209}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 76, 31, 217}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 29, 180, 114, 135, 116, 78, 40, 195}, 116}, {{43, 95, 224, 0, 0, 0, 0, 0, 236, 102, 157, 38, 124, 73, 149, 127}, 116}, {{43, 95, 224, 0, 0, 0, 0, 40, 116, 43, 160, 242, 215, 17, 85, 234}, 116}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 41, 247}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 57}, {{94, 128, 0, 0, 0, 0, 144, 229, 92, 66, 45, 124, 193, 59, 19, 75}, 57}, {{94, 128, 0, 116, 105, 185, 240, 49, 241, 238, 249, 15, 218, 37, 218, 189}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 181, 155, 80, 6}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 36, 8, 191}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 6, 93, 162, 70, 41, 131, 102, 168}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 242}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 57}, {{94, 128, 0, 0, 0, 0, 0, 73, 232, 220, 10, 218, 142, 74, 159, 114}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 121, 59, 242, 191, 126, 92, 71}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 117, 244, 14}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 223, 67, 125, 31, 134, 42, 228, 140}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 130, 253, 165, 232}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 174, 37, 227, 218, 13, 254, 33, 181, 176, 36, 178}, 57}, {{94, 128, 0, 0, 36, 238, 17, 199, 230, 160, 125, 77, 214, 102, 56, 209}, 57}, {{94, 128, 0, 0, 0, 23, 177, 92, 130, 8, 109, 192, 155, 7, 152, 8}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 108, 198}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 57}, {{94, 128, 0, 0, 0, 0, 0, 190, 115, 66, 25, 241, 132, 185, 15, 87}, 57}, {{94, 128, 0, 0, 28, 29, 57, 235, 136, 233, 107, 163, 167, 89, 108, 155}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 57}, {{94, 128, 0, 0, 0, 0, 230, 198, 51, 88, 102, 229, 33, 84, 128, 66}, 57}, {{94, 128, 0, 0, 238, 254, 36, 230, 62, 52, 144, 136, 158, 77, 13, 190}, 57}, {{94, 128, 0, 0, 0, 0, 0, 9, 92, 118, 55, 147, 54, 203, 73, 62}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 15, 149, 166, 149, 197, 131, 78, 68, 171, 165}, 57}, {{94, 128, 0, 211, 89, 38, 56, 21, 128, 26, 18, 60, 213, 113, 241, 83}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 131, 197, 66, 87, 46, 197}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 23, 114, 199, 186}, 57}, {{94, 128, 0, 0, 0, 0, 0, 89, 184, 134, 100, 248, 12, 78, 109, 121}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 250, 59, 140, 48, 54, 198}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 245, 255, 218}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 182, 65, 233, 145, 209, 210, 134, 56}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 63, 121, 164, 192, 187, 171, 58, 190, 212, 67, 222}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 197, 238, 0, 55, 53, 81, 184, 185}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 191, 210, 137, 60}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 162, 144, 178, 21, 226, 63, 152, 195}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 231, 207}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 30, 236, 153, 90}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 196, 167, 206, 176, 26, 237}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 159, 5}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 201, 63}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 241, 176, 149, 40, 156, 10}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 14, 89, 166, 139, 219, 65, 188, 133}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 255, 206, 3}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 87}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 92, 155}, 57}, {{94, 128, 103, 246, 140, 201, 218, 30, 2, 61, 214, 51, 248, 10, 165, 62}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 57}, {{94, 128, 0, 0, 0, 0, 55, 101, 9, 93, 45, 124, 62, 221, 21, 172}, 57}, {{94, 128, 0, 0, 182, 25, 190, 224, 76, 36, 212, 40, 174, 188, 193, 12}, 57}, {{94, 128, 0, 0, 0, 0, 0, 138, 26, 57, 32, 187, 204, 53, 63, 226}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 9, 74, 134, 16}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 34, 95, 191, 61, 251, 236, 67}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 71, 136}, 57}, {{94, 128, 0, 91, 69, 22, 228, 37, 185, 35, 1, 186, 212, 90, 29, 21}, 57}, {{94, 128, 0, 0, 147, 122, 61, 151, 9, 177, 217, 101, 182, 211, 159, 184}, 57}, {{94, 128, 0, 0, 0, 0, 0, 255, 155, 176, 230, 74, 166, 161, 187, 61}, 57}, {{94, 128, 0, 0, 0, 0, 7, 141, 74, 190, 207, 55, 219, 225, 93, 88}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 236, 166}, 57}, {{94, 128, 0, 0, 0, 0, 88, 192, 48, 55, 194, 72, 155, 7, 177, 231}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 70}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 47, 33, 188, 187, 40, 117, 182, 70}, 57}, {{94, 128, 0, 0, 0, 0, 212, 77, 28, 226, 165, 115, 199, 120, 237, 109}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 126, 255, 94, 17, 25, 242}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 148, 85, 89, 229}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 158, 16}, 57}, {{94, 128, 0, 251, 144, 212, 27, 183, 1, 138, 233, 230, 10, 105, 85, 91}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 162, 96, 248, 101, 19, 154, 32}, 57}, {{94, 128, 0, 0, 77, 115, 3, 224, 55, 202, 223, 16, 189, 61, 182, 160}, 57}, {{94, 128, 0, 0, 107, 8, 182, 54, 0, 16, 26, 224, 238, 151, 177, 181}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 57}, {{94, 128, 0, 0, 0, 175, 232, 29, 206, 234, 27, 50, 142, 170, 194, 173}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 38, 86, 79, 134}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 228, 39, 216, 70, 26, 127, 237}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 142, 23, 184, 80, 32, 14, 117, 254}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 57}, {{94, 128, 0, 0, 0, 0, 0, 135, 29, 249, 212, 43, 47, 166, 236, 156}, 57}, {{94, 128, 0, 57, 216, 160, 34, 162, 188, 121, 140, 127, 172, 224, 67, 226}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 104, 13, 144, 123, 168, 13, 132, 17}, 57}, {{94, 128, 0, 0, 0, 87, 40, 253, 246, 210, 81, 45, 131, 18, 232, 175}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 183, 119}, 57}, {{94, 128, 0, 0, 177, 165, 178, 131, 178, 207, 45, 130, 177, 219, 119, 245}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 220, 250}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 64, 59, 152, 39, 10, 8}, 57}, {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 171}, 57}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 69}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 196}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 205}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 233, 133}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 101}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 149, 231}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 253}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 33}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 180}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 182}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 66, 89}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 66, 52}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 217}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 88}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 245}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 212}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 107}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 92}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 10}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 232}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 62, 102}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 255}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 67}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 145}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 122, 29}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 214}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 120, 242}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 110}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 152}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 187}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 107}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 214, 171}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 97}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 168}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 60, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 141}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 208, 121}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 46}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 32}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 75, 208}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 60}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 65, 45}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 94, 93}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 214}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 104}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 119}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 217}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 97, 200}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 47}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 139, 159}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 100, 17}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 24}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 181, 225}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 205}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 142}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 21}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 31, 139}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 178}, {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 218}, 178}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 106, 198}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 45, 255}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 106, 161}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 63, 86}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 230}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 127, 178}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 60, 208}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 171}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 147}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 199}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 188, 61}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 216, 110}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 8}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 159, 49}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 247, 12}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 84, 138}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 194}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 191}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 62}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 107}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 9}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 16}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 59, 47}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 7, 72, 119}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 3, 163}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 237, 30}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 212, 51}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 110}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 171, 146, 68}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 88, 212, 127}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 51, 174}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 245, 0, 194}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 30, 233}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 19, 189}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 254, 20, 236}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 54, 154, 48}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 145}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 131, 158}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 214}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 170, 204}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 141}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 29}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 84}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 224, 186}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 180}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 124}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 152, 72}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 218}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 21, 19}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 193}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 154}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 184, 143}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 86, 158}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 10, 56}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 245, 82}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 16}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 71, 203}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 159}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 64}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 59, 91}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 141}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 42, 152}, 93}, {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 55, 107}, 93}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 109, 89, 5}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 92, 125}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 138, 158, 217, 32}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 140, 54}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 189, 210, 124}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 215, 151}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 207, 96}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 112, 192, 177, 29}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 93, 224, 203}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 133, 130, 173, 189}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 142, 216, 122}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 186, 85, 140}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 254, 229, 240, 107}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 238, 65, 120}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 181, 83, 229}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 185, 30}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 51, 56}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 236}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 118}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 44, 243, 143, 242}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 138, 144, 78, 13}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 190, 197, 47}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 182, 13}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 39, 165}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 110, 197, 82, 248}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 241, 31}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 30, 62, 119, 130}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 60}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 21}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 12, 59, 78}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 240, 204, 115}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 64, 4, 215}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 227, 39}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 65, 226}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 149}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 69}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 156, 119, 238, 106}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 180, 196, 122}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 231}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 123}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 206, 247, 238}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 15}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 110, 69}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 201, 42, 76}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 156}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 175}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 252}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 19, 26, 213, 176}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 119, 155, 56}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 145, 119, 54}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 139, 11, 224}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 89, 37, 148, 164}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 184, 123}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 115, 150, 248}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 188}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 182}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 221, 80}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 253, 253}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 137, 45, 189}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 228}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 48, 254, 46, 208}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 109, 138, 226}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 102, 187, 182}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 61, 37}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 50}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 183, 59, 254}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 50, 252}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 196, 80}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 93, 74}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 57, 56}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 135, 18, 111}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 89, 203, 238, 57}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 236, 119}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 240, 65, 10}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 244}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 133}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 161, 225}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 100, 107, 2}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 82}, 3}, {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 3}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 162}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 160, 142}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 251, 194}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 196, 188}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 237}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 241}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 173}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 84, 90}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 86, 139}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 83}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 5}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 225}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 248}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 150}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 181}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 47}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 129}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 158}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 231}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 190}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 244, 144}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 17, 74}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 59, 34}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 68}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 159, 252}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 20}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 225}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 164}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 54}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 126}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 104}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 228}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 189}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 250, 160}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 252}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 60}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 145}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 76}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 80, 181}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 158}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 162}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 27}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 100, 88}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 20}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 189}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 217}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 107}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 135}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 160}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 36}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 23}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 145, 174}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 208}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 176}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 235}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 125}, {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 196, 189}, 125}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 21, 186, 154, 209, 54, 75, 167}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 25, 119, 116, 142, 51, 124}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 251, 92, 240, 64, 49}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 16, 187, 186, 210, 226, 152, 166}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 191, 149, 31, 206, 165, 131}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 116, 13, 84, 159}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 90, 54, 134, 34, 212}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 214, 74, 132, 47, 215}, 33}, {{106, 197, 83, 151, 64, 0, 0, 68, 47, 242, 131, 43, 255, 233, 146, 173}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 235, 218, 3, 134, 81, 212, 9}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 88, 178, 219, 53, 136}, 33}, {{106, 197, 83, 151, 64, 0, 71, 64, 93, 203, 238, 143, 159, 184, 224, 111}, 33}, {{106, 197, 83, 151, 64, 4, 109, 151, 90, 97, 9, 229, 93, 118, 129, 234}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 249}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 177}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 33}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 222}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 82}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 255, 172, 226, 161, 126, 96, 141, 237}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 108}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 66, 53, 229, 112, 227, 94}, 33}, {{106, 197, 83, 151, 64, 0, 0, 152, 195, 0, 249, 199, 176, 245, 189, 106}, 33}, {{106, 197, 83, 151, 64, 92, 87, 239, 8, 246, 122, 115, 65, 197, 206, 185}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 117, 24, 236, 80, 209, 253}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 13, 23, 191, 229, 40, 232, 53}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 109}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 145, 11, 172, 98, 20}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 28, 97, 17, 95, 194, 139}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 71, 41, 168, 222, 9, 252}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 57, 108, 111, 227, 194}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 3, 36, 173}, 33}, {{106, 197, 83, 151, 64, 0, 254, 11, 83, 111, 156, 247, 112, 180, 55, 84}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 70, 64, 131, 127, 80, 132, 174, 179}, 33}, {{106, 197, 83, 151, 64, 0, 0, 21, 83, 177, 218, 145, 16, 39, 220, 125}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 204, 131, 120, 43, 212}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 30, 196, 227, 86, 134, 99}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 102, 92, 10, 93, 122, 55}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 161, 63, 63, 96, 110, 95, 101, 145, 197, 168}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 35, 223, 198, 141, 63, 233}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 220}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 213, 72, 60, 60, 239, 98, 187}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 29, 146, 48, 214, 139, 51, 52}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 19, 17, 56, 164, 140, 221, 237, 22}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 75, 170, 164, 42, 87, 70, 2, 211}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 221}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 8}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 108, 92, 126, 8}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 77, 213, 171, 183, 182, 39}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 129, 68, 44, 252, 35, 249, 214}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 49}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 124, 195, 208, 59}, 33}, {{106, 197, 83, 151, 64, 0, 0, 108, 204, 162, 86, 244, 246, 112, 238, 77}, 33}, {{106, 197, 83, 151, 64, 0, 0, 136, 193, 111, 117, 254, 118, 32, 22, 169}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 52, 171, 248, 90, 151, 81, 1, 23}, 33}, {{106, 197, 83, 151, 64, 248, 132, 46, 141, 72, 230, 115, 40, 29, 138, 77}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 125, 106, 76}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 24}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 167, 218, 95, 38, 110}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 48, 0, 253, 115, 226}, 33}, {{106, 197, 83, 151, 64, 0, 184, 197, 109, 46, 16, 16, 219, 251, 99, 201}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 73, 30, 194}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 109, 242, 83, 53}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 144, 188, 71}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 168, 239, 55, 240, 4}, 33}, {{106, 197, 83, 151, 64, 0, 165, 199, 252, 39, 68, 147, 223, 11, 212, 44}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 47, 90, 47, 119, 104}, 33}, {{106, 197, 83, 151, 64, 0, 0, 231, 33, 67, 218, 121, 137, 182, 50, 98}, 33}, {{106, 197, 83, 151, 64, 35, 51, 94, 210, 97, 114, 175, 18, 182, 67, 140}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 33}, {{106, 197, 83, 151, 64, 0, 0, 38, 80, 64, 204, 128, 207, 160, 156, 34}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 178, 63, 227, 9}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 153, 75, 214, 201, 19, 70}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 50, 131, 128, 14, 63}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 198, 179, 70, 185, 52, 18, 136, 134}, 33}, {{106, 197, 83, 151, 64, 0, 0, 181, 104, 88, 125, 35, 20, 226, 227, 235}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 144, 184, 89}, 33}, {{106, 197, 83, 151, 64, 0, 139, 15, 164, 17, 2, 98, 159, 28, 142, 40}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 26}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 249, 54, 157, 211}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 38, 169, 189}, 33}, {{106, 197, 83, 151, 64, 0, 0, 221, 14, 78, 171, 178, 158, 100, 144, 222}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 41, 120, 138, 157, 111, 221, 89, 35}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 164, 34, 122, 16, 246, 145, 205, 90}, 33}, {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33}, {{106, 197, 83, 151, 64, 0, 0, 120, 227, 26, 93, 106, 225, 135, 173, 170}, 33}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 70, 81}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 159, 207, 251, 185, 138}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 119, 183, 43, 147, 138}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{190, 0, 156, 206, 135, 248, 76, 115, 174, 113, 88, 192, 228, 71, 241, 30}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 179, 131}, 254}, {{190, 0, 0, 0, 215, 19, 155, 224, 24, 90, 65, 43, 60, 39, 209, 219}, 254}, {{190, 0, 0, 0, 151, 62, 171, 23, 100, 15, 142, 137, 86, 225, 148, 54}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 47, 53}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 224, 61}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 76}, 254}, {{190, 0, 0, 0, 0, 166, 36, 64, 42, 15, 139, 4, 216, 166, 145, 172}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 30, 6, 75, 202, 39, 2, 18}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 9}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 228, 171}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 97, 177, 242, 71, 77, 226, 37}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 78, 164, 46}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 158}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 246}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 254}, {{190, 0, 0, 0, 0, 0, 0, 194, 106, 245, 88, 121, 104, 217, 228, 252}, 254}, {{190, 0, 0, 0, 0, 0, 210, 78, 255, 35, 249, 103, 28, 213, 247, 248}, 254}, {{190, 0, 168, 33, 105, 204, 90, 24, 73, 132, 192, 18, 235, 185, 220, 145}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 239, 88, 89, 85}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 154, 23}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 196, 123, 222, 83, 143, 86, 20, 62}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 114, 250, 116, 85}, 254}, {{190, 0, 0, 0, 0, 190, 249, 113, 38, 178, 87, 241, 228, 23, 10, 230}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 225}, 254}, {{190, 0, 0, 0, 102, 127, 227, 43, 8, 235, 11, 31, 223, 121, 136, 250}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 243, 175, 181, 224, 134, 31, 50, 45}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 50, 40}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 242, 93, 254, 45}, 254}, {{190, 0, 123, 26, 222, 100, 255, 236, 4, 137, 112, 8, 220, 11, 201, 198}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 66, 199, 247}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 98, 217, 168}, 254}, {{190, 0, 0, 0, 197, 189, 150, 240, 228, 213, 63, 140, 91, 69, 2, 53}, 254}, {{190, 0, 0, 19, 132, 172, 254, 98, 157, 80, 105, 32, 31, 78, 86, 217}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 156, 56}, 254}, {{190, 0, 0, 0, 0, 159, 112, 222, 184, 142, 204, 183, 63, 67, 181, 38}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 74, 229, 189}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 50}, 254}, {{190, 0, 0, 0, 0, 0, 43, 208, 91, 15, 28, 240, 7, 162, 60, 246}, 254}, {{190, 0, 0, 52, 203, 175, 117, 174, 23, 254, 140, 116, 174, 152, 149, 140}, 254}, {{190, 0, 0, 0, 0, 0, 71, 91, 251, 61, 171, 66, 210, 179, 229, 17}, 254}, {{190, 0, 75, 3, 104, 53, 225, 50, 179, 1, 235, 128, 67, 141, 67, 64}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 193, 166, 0}, 254}, {{190, 0, 0, 77, 38, 61, 184, 147, 227, 151, 87, 78, 129, 231, 111, 217}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 92, 54, 110, 4, 36, 103, 60, 116}, 254}, {{190, 0, 0, 0, 111, 23, 138, 79, 245, 111, 107, 1, 205, 230, 14, 15}, 254}, {{190, 0, 0, 0, 0, 88, 24, 228, 189, 70, 197, 61, 31, 112, 116, 77}, 254}, {{190, 0, 0, 0, 0, 139, 250, 82, 77, 37, 107, 118, 92, 83, 156, 47}, 254}, {{190, 0, 0, 0, 171, 131, 157, 15, 150, 26, 39, 161, 7, 195, 155, 128}, 254}, {{190, 0, 0, 0, 0, 0, 0, 110, 131, 107, 176, 146, 98, 194, 106, 9}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 180, 177, 244, 187}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 2, 14}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 151, 253, 150, 8}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 127}, 254}, {{190, 0, 99, 175, 181, 38, 172, 177, 232, 94, 62, 82, 153, 198, 187, 70}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 12, 129, 160, 114, 179, 199, 161, 43}, 254}, {{190, 0, 0, 0, 0, 0, 113, 252, 43, 151, 114, 30, 182, 40, 251, 78}, 254}, {{190, 0, 95, 104, 204, 77, 75, 220, 37, 15, 111, 2, 125, 164, 46, 59}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 64, 47, 28, 104, 121}, 254}, {{190, 0, 0, 107, 38, 208, 193, 153, 235, 202, 179, 245, 227, 184, 15, 29}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 232, 161, 50, 4, 166, 1, 241}, 254}, {{190, 0, 0, 0, 0, 0, 41, 19, 39, 167, 251, 212, 41, 202, 165, 190}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 16, 240, 66, 20, 113, 225, 128, 26}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 90, 121, 121, 150, 58}, 254}, {{190, 0, 121, 233, 2, 4, 76, 73, 111, 37, 55, 208, 32, 147, 62, 255}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 120, 158, 211}, 254}, {{190, 0, 0, 0, 0, 94, 50, 22, 198, 203, 188, 219, 143, 248, 130, 194}, 254}, {{190, 0, 0, 0, 0, 192, 146, 68, 176, 226, 142, 78, 7, 12, 173, 38}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 100, 52, 138}, 254}, {{190, 0, 0, 130, 60, 177, 131, 118, 19, 211, 137, 211, 249, 68, 37, 48}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 154}, 254}, {{190, 0, 0, 0, 0, 118, 221, 6, 51, 161, 198, 186, 146, 89, 139, 183}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 66, 23}, 254}, {{190, 0, 242, 65, 164, 46, 222, 178, 72, 113, 245, 162, 59, 67, 66, 206}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 106}, 254}, {{190, 0, 0, 0, 0, 0, 27, 95, 223, 142, 202, 64, 138, 178, 58, 159}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 87, 210, 89, 83, 123}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 177, 109, 15, 209, 200, 74, 64, 48}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 94, 227, 84, 24, 182}, 254}, {{190, 0, 0, 0, 0, 27, 209, 147, 25, 64, 96, 66, 19, 93, 93, 37}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 165}, 254}, {{190, 0, 0, 0, 0, 208, 225, 46, 19, 56, 17, 247, 100, 188, 136, 141}, 254}, {{190, 0, 0, 0, 89, 33, 197, 129, 220, 148, 59, 10, 86, 0, 201, 48}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 207, 254, 164, 240}, 254}, {{190, 0, 157, 16, 172, 6, 128, 181, 184, 159, 133, 96, 220, 99, 151, 238}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 254}, {{190, 0, 0, 0, 0, 0, 0, 0, 0, 19, 202, 54, 180, 15, 195, 139}, 254}, {{190, 0, 0, 127, 115, 114, 184, 218, 224, 133, 177, 103, 75, 219, 190, 176}, 254}, {{190, 0, 100, 96, 18, 167, 33, 84, 49, 82, 95, 161, 0, 75, 230, 81}, 254}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 9}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 58}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 153, 106, 14, 110, 26, 28}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 103, 107, 11, 130}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 174, 79, 81, 32, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 131}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 174, 241, 183, 28, 59}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 31, 50, 96, 212}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 199, 45, 190, 190, 45}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 154, 191, 144, 113, 246}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 207, 9, 123, 115}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 186, 7, 107, 203, 170}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 189, 182}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 131, 42, 98, 142, 199, 78}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 174, 44}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 171, 161, 133, 42}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 22, 37}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 36}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 96, 65}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 177, 110}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 1, 223, 41}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 159, 238}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 204, 194, 175, 83}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 44, 102, 107, 163, 59, 230}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 116, 167, 86, 248, 102}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 183, 130, 198}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 216, 92, 145}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 114, 180, 153}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 182, 41, 104, 194, 172}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 201, 76, 139, 187}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 168, 35, 126, 94, 63}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 164, 144, 216, 215, 99}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 153, 118, 240, 37, 135, 175}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 136}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 86, 122, 195, 58}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 184, 25, 13, 172}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 237}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 214, 53, 115}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 194, 99, 173, 35}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 100, 15, 185, 187, 115, 229}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 200}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 107, 92, 239}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 217, 68, 221}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 15, 86, 84, 57, 235}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 129, 240, 209, 106}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 11, 155, 100, 7, 199}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 173, 125, 208, 213, 38, 59}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 185}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 242, 242, 154, 98, 119, 242}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 120, 230, 144, 56, 190, 252}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 19, 195, 193}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 48, 159, 5, 145}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 227}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 17, 72, 85}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 95, 236, 159}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 115, 174, 160, 17}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 213, 191, 207, 40}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 88, 85, 157}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 100, 3, 15, 72, 109}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 180, 59, 120, 50, 167}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 240, 140, 54}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 74, 140, 92, 240}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 39, 90}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 105, 29, 249}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 68, 56}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 187}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 43, 136, 134, 198}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 232, 211, 176}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 70, 28}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 213, 73}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 72, 179, 81, 154, 23}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 240, 123, 217, 144, 45, 50}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 21, 196, 158}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 69}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 104, 188, 213, 2, 220}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 85, 122, 34, 92}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 107, 74, 111, 203}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 91, 193}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 38, 228, 198}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 221, 44, 149}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 75, 219, 164, 5, 114, 106}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 241, 238, 149, 78, 252, 13}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 66, 183}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 37, 29}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 130, 181, 250, 85}, 66}, {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 213, 118, 193, 22, 29, 146}, 66}, {{64, 107, 36, 120, 0, 0, 0, 80, 199, 85, 29, 58, 18, 156, 159, 120}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 31}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 106, 124, 84, 212, 76, 16}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 163, 199, 111, 170, 12, 67, 107, 170}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 30, 140, 153, 145}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 57}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 226, 253, 161, 202}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 219, 192, 94, 25, 142}, 4}, {{64, 107, 36, 120, 0, 186, 66, 162, 234, 119, 244, 192, 19, 213, 43, 219}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 15, 156}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 20, 101, 63, 56, 114, 18, 232, 104, 53}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 193, 125, 218, 131, 108}, 4}, {{64, 107, 36, 120, 0, 22, 220, 119, 47, 48, 54, 177, 253, 195, 74, 198}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 186}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 103, 241, 254, 111}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 185, 176, 17, 167, 191, 13, 114, 206}, 4}, {{64, 107, 36, 120, 0, 0, 194, 146, 145, 139, 171, 40, 212, 60, 127, 206}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 225, 251, 111, 121, 62, 175, 234, 59, 114}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 212, 150, 173, 245, 117, 24, 103}, 4}, {{64, 107, 36, 120, 0, 0, 0, 18, 31, 215, 36, 137, 250, 242, 172, 26}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 78, 249, 212, 44, 225, 112, 79, 108, 141, 119, 219, 173}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 69, 2, 162, 197, 91, 16}, 4}, {{64, 107, 36, 120, 192, 179, 60, 25, 204, 228, 113, 175, 244, 195, 131, 247}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 190}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 238, 237}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 28, 240}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 188, 126, 214, 55, 67, 75, 211, 64}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 55, 209, 106, 211, 60, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 65, 215, 175, 41}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 57, 128, 244, 138, 173, 197, 87}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 67, 184, 242, 198}, 4}, {{64, 107, 36, 120, 0, 0, 0, 49, 80, 168, 30, 35, 64, 167, 99, 30}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 248, 144, 124, 170}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 176, 144, 91, 110, 62, 158}, 4}, {{64, 107, 36, 120, 0, 232, 84, 34, 9, 1, 33, 126, 210, 226, 127, 199}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 73, 226, 188, 93, 98, 96, 130, 42}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 86, 128, 164, 87, 175, 118}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 122, 0, 46, 251, 109, 176, 186}, 4}, {{64, 107, 36, 120, 220, 133, 95, 233, 49, 236, 44, 42, 189, 226, 170, 54}, 4}, {{64, 107, 36, 120, 0, 0, 0, 248, 65, 68, 235, 144, 181, 123, 204, 126}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 172, 112, 138, 93, 189, 166}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 96, 10}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 44, 17, 109, 136}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 78, 100, 5, 188, 79, 68, 244}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 130, 92, 91, 17, 102, 239, 86}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 197, 63, 71, 219, 225, 103, 188, 96}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 219, 189, 121, 126, 249, 233}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 52, 28, 95, 228, 200, 175, 195}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 96, 24, 200, 233}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 225, 89, 67, 57, 179, 172}, 4}, {{64, 107, 36, 120, 0, 155, 249, 60, 119, 34, 47, 73, 60, 150, 155, 138}, 4}, {{64, 107, 36, 120, 0, 0, 0, 248, 205, 41, 49, 45, 79, 66, 253, 125}, 4}, {{64, 107, 36, 120, 0, 0, 122, 14, 167, 162, 195, 230, 62, 173, 16, 144}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 17, 70, 117, 86}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 248}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 153, 221, 194, 12, 206, 50, 179, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 41}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 211, 43, 38, 60, 151, 18}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 104, 3, 85, 19, 89, 98}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 244, 252, 253, 207, 19, 157, 29, 213}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 96, 138, 63, 50, 36, 215}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 154, 108, 22, 38, 227, 219, 188}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 81}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 95}, 4}, {{64, 107, 36, 120, 0, 0, 0, 109, 129, 173, 206, 99, 148, 94, 24, 134}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 11, 115, 155, 9}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 111, 72, 188, 157, 14, 128, 174, 199}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 156}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 203, 24, 202, 143, 208, 223, 140, 175}, 4}, {{64, 107, 36, 120, 0, 29, 170, 14, 137, 24, 169, 52, 8, 168, 93, 133}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 4}, {{64, 107, 36, 120, 0, 0, 166, 191, 205, 127, 80, 251, 5, 218, 161, 57}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 121, 163, 65, 195, 103, 110, 136}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 28, 233, 95, 12, 12, 208}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 217}, 4}, {{64, 107, 36, 120, 0, 0, 14, 3, 76, 115, 223, 171, 26, 230, 235, 114}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 158, 60, 166, 234, 138, 135, 243, 96}, 4}, {{64, 107, 36, 120, 0, 0, 0, 0, 0, 198, 203, 196, 224, 187, 195, 201}, 4}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 242}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 41, 85, 183}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 91, 176, 200}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 9}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 201, 103, 247, 151, 97}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 240, 240, 197}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 151, 182, 82, 110}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 149, 27, 219}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 48}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 171}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 92, 56}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 220}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 159, 145}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 47, 233, 228}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 157, 11, 214, 194}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 106, 232, 195, 138, 39}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 66}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 253, 140, 166, 169}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 89, 121, 58, 39}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 62, 211, 105, 123}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 187, 34, 42, 93}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 78}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 51, 38, 231, 254}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 38, 124, 97, 112}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 25, 189, 196}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 207, 198, 50, 113}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 168}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 149, 103, 193}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 11}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 114}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 151, 209, 35, 171, 230}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 88}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 227, 2, 236, 200, 9}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 199, 214, 235, 12, 94}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 68, 203, 14}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 231}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 198, 140, 35, 251, 135}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 164}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 119, 6}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 51}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 33, 166, 64, 120}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 59, 111, 239}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 238, 144}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 171, 205, 175, 6}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 205, 33, 96}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 213}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 37, 48}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 8, 93, 41, 127}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 87}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 43, 248, 35, 88}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 138, 99}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 177, 170, 115, 48}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 64, 167, 157, 108}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 38}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 31, 165}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 163, 233, 17}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 125, 80}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 200}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 105}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 20}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 252, 104, 78, 99, 251}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 108, 54, 242, 143, 200}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 79, 254, 85, 100, 24}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 59, 126, 226}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 25}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 106, 28, 236, 82}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 142, 38, 208}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 103, 168, 76, 110}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 85}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 16, 28}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 59}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 44, 146, 60}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 136}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 228, 133, 54, 92}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 66, 72, 45}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 21, 195}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 81}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 138}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 30, 243, 56}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 23, 95, 85, 25}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 86}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 47}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 87, 166, 220, 223, 214}, 122}, {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 68, 87}, 122}, {{18, 139, 152, 44, 38, 88, 0, 0, 109, 223, 185, 181, 20, 181, 113, 56}, 59}, {{18, 139, 152, 44, 38, 88, 0, 229, 145, 185, 176, 120, 236, 233, 122, 66}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 104, 144, 112}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 198, 98}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 171, 76, 46, 135, 204}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 59}, {{18, 139, 152, 44, 38, 88, 239, 46, 123, 130, 59, 7, 179, 231, 75, 20}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 159, 144, 87, 252}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 123, 10, 54, 233}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 84, 248, 39, 183, 56, 42}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 253, 206, 161, 214, 40, 16, 193, 66, 250}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 59}, {{18, 139, 152, 44, 38, 88, 244, 16, 24, 91, 32, 49, 176, 40, 206, 189}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 140, 236, 87}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 148, 152, 195, 190, 208}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 173, 97, 135, 123}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 87, 50, 13, 210, 82}, 59}, {{18, 139, 152, 44, 38, 88, 0, 141, 34, 7, 232, 6, 141, 207, 61, 235}, 59}, {{18, 139, 152, 44, 38, 88, 0, 17, 172, 50, 218, 44, 251, 61, 244, 219}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 127, 149}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 100, 255, 25, 91, 251}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 221, 78, 203}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 218, 181, 158, 26, 226, 42, 83}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 62, 254, 16, 226, 233, 153, 86, 139}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 220, 220, 139, 35, 74, 100, 51, 226}, 59}, {{18, 139, 152, 44, 38, 88, 0, 114, 13, 109, 35, 207, 145, 128, 73, 121}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 152, 222, 129, 73, 82, 69, 247, 177}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 202, 210}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 64, 153, 179}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 240, 175, 66, 210, 172, 155, 205}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 193, 205, 19, 180, 52, 188, 85, 237}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 15, 144, 194, 5, 48}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 147, 153}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 131, 152, 246, 225, 154, 3, 96}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 152, 114, 169, 155, 154, 232, 239, 210}, 59}, {{18, 139, 152, 44, 38, 88, 0, 171, 201, 160, 20, 98, 53, 116, 63, 115}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 64, 212}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 228, 98, 246, 49, 86}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 14, 91, 135, 229, 202}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 179, 74, 44, 119}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 42, 222, 181, 14, 208, 227, 34}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 169, 142, 30}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 234, 71, 243}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 51, 50, 98, 203, 199, 132, 48, 158}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 27, 6, 198, 8}, 59}, {{18, 139, 152, 44, 38, 88, 0, 235, 50, 218, 116, 91, 159, 226, 11, 102}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 29, 178, 83, 114}, 59}, {{18, 139, 152, 44, 38, 88, 243, 75, 34, 46, 36, 222, 131, 38, 155, 43}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 122, 43, 197, 114}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 17, 50, 32, 223, 133, 128}, 59}, {{18, 139, 152, 44, 38, 88, 0, 176, 40, 92, 254, 130, 121, 41, 27, 175}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 218, 41, 130}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 128, 6, 100, 80, 161, 202, 186}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 211, 175}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 129, 174}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 192, 154, 197, 248, 94, 189, 149}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 182, 254, 133, 227, 145}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 41, 62}, 59}, {{18, 139, 152, 44, 38, 88, 155, 113, 131, 99, 221, 41, 5, 28, 146, 122}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 51, 87, 214, 21, 91, 171, 221, 197}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 247, 49, 145, 211}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 93, 121, 55, 195, 6}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 57, 227, 211, 160, 149, 214, 72}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 21, 201, 201, 195, 223}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 153, 214, 254, 142, 146}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 172, 235, 221, 236, 85, 125, 178}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 75, 223, 34, 252, 176, 200, 182}, 59}, {{18, 139, 152, 44, 38, 88, 0, 201, 216, 255, 149, 245, 139, 126, 131, 121}, 59}, {{18, 139, 152, 44, 38, 88, 0, 175, 173, 219, 217, 149, 236, 204, 106, 168}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 169, 231, 72, 147}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 37, 228}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 50, 57, 48, 234, 196}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 29, 9, 18, 140, 235, 197, 181, 215}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 223, 112, 37, 36, 29}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 73, 231, 90, 239}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 242, 248, 102, 42}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 78, 189, 29, 244}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 103, 245, 207}, 59}, {{18, 139, 152, 44, 38, 88, 0, 129, 129, 63, 141, 208, 74, 108, 170, 116}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 163, 222}, 59}, {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{18, 139, 152, 44, 38, 88, 0, 193, 253, 132, 146, 6, 34, 17, 223, 124}, 59}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 224}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 77}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 127}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 20}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 70}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 125}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 29}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 129}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 23}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 87}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 170}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 35}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 130}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 170}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 171}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 127}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 104}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 219}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 88}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 185}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 218}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 216}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 91}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 173}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 99}, {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 21}, 99}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 53, 76}, 41}, {{153, 211, 3, 96, 0, 0, 0, 224, 18, 6, 198, 204, 113, 105, 211, 193}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 87, 0}, 41}, {{153, 211, 3, 96, 0, 66, 148, 128, 170, 38, 29, 59, 25, 184, 219, 149}, 41}, {{153, 211, 3, 96, 0, 0, 83, 103, 73, 50, 114, 64, 135, 238, 238, 208}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 18}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 130, 63}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 129, 3, 196, 74, 75, 25}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 224}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 252, 133, 109, 49, 224, 90}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 109, 173, 164, 194, 87, 13, 157, 154}, 41}, {{153, 211, 3, 96, 0, 164, 105, 167, 25, 182, 177, 180, 105, 202, 82, 111}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 2, 6, 72, 4, 117, 125, 16, 154}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 216, 56}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 40, 114, 80, 216}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 30, 35, 183, 188, 85, 56, 207, 137}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 80, 129}, 41}, {{153, 211, 3, 96, 0, 0, 0, 140, 251, 71, 5, 195, 5, 74, 201, 110}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 174, 149, 193, 88, 97, 212, 235}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 140, 162, 83, 214, 196, 27}, 41}, {{153, 211, 3, 96, 0, 78, 71, 28, 173, 142, 108, 240, 214, 123, 41, 179}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 1, 184}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 73, 82, 129, 239, 20, 83, 215, 152, 104, 206}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 48, 137, 28, 47, 199, 124, 152, 135}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 44, 48, 135, 41, 167, 33, 63}, 41}, {{153, 211, 3, 96, 0, 0, 136, 133, 86, 60, 246, 193, 176, 167, 31, 17}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 91, 240, 160, 169, 101, 144}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 105, 218, 215, 165}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 103, 131, 86, 64}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 2, 71}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 206, 79, 172, 31, 60, 47, 52, 170}, 41}, {{153, 211, 3, 96, 0, 0, 42, 198, 22, 0, 65, 225, 233, 113, 13, 229}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 193, 72, 158, 183, 69}, 41}, {{153, 211, 3, 96, 0, 141, 15, 126, 230, 143, 191, 208, 153, 116, 44, 71}, 41}, {{153, 211, 3, 96, 0, 0, 52, 59, 82, 73, 50, 179, 229, 229, 128, 52}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 41}, {{153, 211, 3, 96, 0, 0, 67, 8, 110, 58, 44, 85, 167, 138, 65, 179}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 150, 202, 224, 184, 228, 70}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 54, 174, 219, 46, 104, 200, 201, 211}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 95, 187, 31, 155, 198, 244, 69, 239}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 218, 200, 32, 46, 56, 67, 113, 85, 148, 182}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 40, 98, 144, 97, 199, 234, 227, 187, 101, 199, 75}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 213, 76}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 128, 113, 24, 64, 234, 122, 198}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 183, 238, 230, 63}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 185}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 52, 126, 115, 69}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 216, 217, 148, 249, 89, 107, 5}, 41}, {{153, 211, 3, 96, 0, 0, 0, 201, 223, 239, 19, 152, 17, 198, 33, 127}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 241, 90, 30, 91, 50, 33, 238, 85}, 41}, {{153, 211, 3, 96, 0, 5, 194, 150, 57, 157, 194, 236, 210, 237, 183, 124}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 211, 140, 137, 132, 207, 214, 14, 93, 139, 177}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 13, 118}, 41}, {{153, 211, 3, 96, 91, 111, 160, 35, 205, 9, 227, 61, 94, 207, 133, 180}, 41}, {{153, 211, 3, 96, 0, 0, 0, 94, 81, 168, 26, 155, 174, 118, 117, 4}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 204, 78, 134, 233, 129, 135, 228}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 157, 92, 40, 52, 167, 226}, 41}, {{153, 211, 3, 96, 0, 0, 0, 53, 238, 36, 207, 176, 175, 157, 71, 132}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 2, 131, 215, 130, 121, 115}, 41}, {{153, 211, 3, 96, 0, 0, 0, 169, 252, 154, 233, 68, 69, 144, 232, 9}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 217, 154, 17, 29}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 233}, 41}, {{153, 211, 3, 96, 0, 0, 0, 193, 13, 38, 25, 181, 215, 103, 249, 246}, 41}, {{153, 211, 3, 96, 0, 136, 156, 110, 179, 190, 4, 223, 101, 162, 59, 22}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 183, 233, 0, 137, 254, 173, 170, 129, 71, 89, 69}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 167, 101, 185, 158, 152, 248}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 74, 46, 45, 4}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 161, 243, 160, 94, 55, 202, 216, 221}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 212, 42}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 108, 209, 217, 245, 84, 30}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 200, 181, 201, 231, 241, 245, 27, 85}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 32, 165}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 70, 99}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 133, 168}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 41}, {{153, 211, 3, 96, 0, 0, 0, 138, 103, 95, 114, 126, 82, 90, 226, 23}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 79, 210, 59, 16, 149, 88, 138}, 41}, {{153, 211, 3, 96, 0, 219, 174, 158, 236, 188, 42, 64, 82, 42, 184, 203}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 207}, 41}, {{153, 211, 3, 96, 217, 114, 129, 24, 1, 137, 225, 22, 60, 255, 166, 55}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 41}, {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 197, 99, 80, 140}, 137}, {{1, 0, 231, 101, 27, 71, 216, 95, 98, 77, 161, 110, 63, 147, 21, 117}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 137}, {{1, 0, 0, 52, 166, 34, 96, 218, 194, 201, 233, 91, 205, 205, 151, 54}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 49, 142, 149}, 137}, {{1, 0, 0, 31, 90, 12, 247, 229, 182, 135, 220, 221, 253, 106, 44, 150}, 137}, {{1, 0, 0, 0, 131, 96, 95, 120, 214, 138, 206, 159, 165, 168, 10, 44}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 232, 185, 221, 218, 112, 97, 17}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 47, 123, 255, 214}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 29, 204, 17, 102, 122, 20, 68}, 137}, {{1, 0, 0, 0, 0, 173, 33, 89, 216, 174, 202, 21, 112, 49, 191, 159}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 107, 176}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 173, 136, 155, 233, 93}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 11, 79, 202, 17, 203, 178, 243, 181, 142, 58, 1, 248, 217}, 137}, {{1, 0, 193, 175, 94, 138, 4, 117, 31, 249, 36, 46, 89, 94, 90, 206}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 82, 94, 240, 22, 20, 95, 151, 103, 97, 166, 225, 26}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 27}, 137}, {{1, 0, 170, 151, 7, 242, 10, 2, 148, 37, 133, 79, 247, 34, 32, 219}, 137}, {{1, 0, 0, 0, 0, 0, 92, 188, 135, 200, 32, 29, 185, 188, 166, 153}, 137}, {{1, 0, 245, 9, 192, 242, 178, 177, 130, 37, 81, 19, 115, 148, 164, 39}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 42, 7, 88, 30, 242}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 48, 178, 83}, 137}, {{1, 0, 0, 171, 71, 163, 67, 120, 185, 161, 149, 77, 215, 67, 103, 199}, 137}, {{1, 0, 249, 172, 190, 219, 4, 28, 50, 159, 130, 70, 38, 140, 144, 115}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 167, 208, 145, 187, 29, 36, 76, 85}, 137}, {{1, 0, 0, 0, 0, 0, 153, 123, 232, 18, 241, 224, 30, 19, 50, 247}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 35, 81, 64, 78, 191, 26, 164, 26, 142, 146, 154, 163}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 45, 148, 135}, 137}, {{1, 0, 0, 0, 0, 0, 0, 47, 108, 118, 247, 74, 238, 176, 86, 11}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 180, 117, 96, 102, 190}, 137}, {{1, 0, 0, 0, 148, 239, 244, 75, 247, 125, 135, 71, 162, 255, 143, 109}, 137}, {{1, 0, 143, 112, 158, 172, 16, 200, 63, 84, 175, 107, 169, 30, 53, 131}, 137}, {{1, 0, 33, 12, 242, 6, 4, 96, 42, 160, 186, 134, 118, 60, 248, 255}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 137}, {{1, 0, 221, 45, 216, 87, 79, 238, 68, 134, 209, 153, 98, 120, 28, 241}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 223, 115, 184, 178, 72, 192, 149, 244}, 137}, {{1, 0, 0, 0, 127, 101, 222, 38, 58, 81, 230, 97, 248, 112, 4, 57}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 22, 172, 161, 142, 77, 176, 253}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 71, 5, 83, 169, 204, 53, 80, 24}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 164, 61}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 99, 143, 32, 224, 153}, 137}, {{1, 0, 167, 32, 148, 106, 219, 2, 231, 169, 28, 163, 171, 27, 100, 36}, 137}, {{1, 0, 0, 0, 0, 126, 5, 224, 243, 240, 16, 56, 242, 160, 101, 119}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 150, 241, 34, 109, 119}, 137}, {{1, 0, 0, 48, 193, 33, 194, 97, 159, 95, 90, 195, 34, 185, 176, 228}, 137}, {{1, 0, 0, 0, 0, 0, 168, 192, 42, 214, 215, 184, 186, 94, 240, 155}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 68, 203, 147, 162}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 255, 143, 216, 206, 47, 229, 69, 15}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 23, 173}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 137}, {{1, 0, 0, 0, 0, 0, 0, 249, 36, 144, 127, 93, 195, 211, 174, 80}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 227}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 6, 163, 216, 51, 172, 213, 83, 132, 111, 184, 179}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 239, 81, 228, 75, 142, 162, 210}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 102, 86, 19, 3, 211, 0, 102}, 137}, {{1, 0, 0, 0, 0, 204, 252, 166, 10, 6, 230, 116, 6, 254, 206, 132}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 62, 93}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 85, 122, 136, 32, 94, 56, 154}, 137}, {{1, 0, 0, 0, 0, 0, 189, 61, 245, 172, 64, 48, 75, 193, 77, 234}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 111, 23, 109, 152, 252, 76, 177}, 137}, {{1, 0, 0, 0, 0, 0, 0, 203, 212, 208, 135, 236, 123, 48, 190, 97}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 222}, 137}, {{1, 0, 97, 195, 96, 138, 182, 69, 246, 118, 33, 106, 105, 150, 251, 40}, 137}, {{1, 0, 0, 0, 0, 159, 47, 159, 166, 204, 50, 209, 76, 60, 3, 187}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 216, 208, 52, 108, 85, 206, 230, 172}, 137}, {{1, 0, 0, 0, 0, 156, 133, 124, 149, 42, 80, 150, 181, 232, 179, 184}, 137}, {{1, 0, 0, 0, 27, 156, 201, 250, 202, 75, 129, 251, 29, 19, 150, 79}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 25, 66, 53, 109, 125, 19, 109}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 246, 226}, 137}, {{1, 0, 0, 0, 0, 18, 59, 213, 76, 27, 138, 122, 188, 117, 253, 230}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 153, 104}, 137}, {{1, 0, 0, 0, 106, 200, 114, 24, 154, 36, 106, 89, 141, 33, 34, 212}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 61, 174, 108, 191, 155, 170, 214, 206}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 137}, {{1, 0, 0, 0, 212, 129, 26, 199, 132, 221, 102, 145, 161, 231, 249, 35}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 179, 236, 67, 134, 9, 97, 127}, 137}, {{1, 0, 0, 146, 186, 182, 103, 82, 4, 49, 13, 142, 156, 41, 241, 61}, 137}, {{1, 0, 0, 0, 5, 149, 75, 223, 69, 41, 21, 133, 2, 33, 103, 52}, 137}, {{1, 0, 180, 69, 7, 172, 160, 185, 14, 52, 189, 84, 114, 183, 117, 93}, 137}, {{1, 0, 59, 168, 228, 29, 119, 119, 124, 100, 47, 185, 176, 24, 121, 231}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 89, 49, 243}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 24}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 77, 27, 164}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 137}, {{1, 0, 0, 0, 0, 0, 0, 142, 199, 49, 51, 42, 223, 191, 64, 98}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 231, 199}, 137}, {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 118}, 137}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 86, 140, 70, 133}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 148, 100, 234, 25}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 84, 150, 35, 224}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 125}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 177, 13}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 103, 153}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 41}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 250}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 76, 175}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 146, 71}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 206, 29}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 44}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 202, 212, 205, 21}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 31, 232}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 197}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 203, 191}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 144}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 15, 202}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 109}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 46, 89, 17, 76, 207}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 229}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 238, 46, 183}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 23, 154, 46, 139}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 193, 214}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 15}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 89, 80}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 72, 67}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 192, 1, 245, 4}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 62, 78, 22, 53}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 251, 7, 44}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 197, 226, 163, 143}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 239, 11}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 167, 157, 1, 175}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 76, 214}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 176, 245, 25, 206, 167}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 97}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 154, 151, 234}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 26, 155, 15, 191}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 40, 58, 234}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 64}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 251, 176}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 149, 134, 14, 90}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 123, 130, 151, 234}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 84}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 165, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 73}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 198, 166, 138}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 36, 24, 127, 188}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 179, 195, 178, 197}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 44, 33, 197, 164}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 69}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 97, 65, 100}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 190}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 100}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 237, 79, 157, 95}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 226, 250, 191, 121}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 38, 145}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 179, 76, 34, 176}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 165, 46, 35, 252, 113}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 97, 214}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 20, 20, 233, 255}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 169, 93, 192, 154}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 7, 28, 36, 75, 216}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 36, 223}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 59}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 14}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 72, 158, 31}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 227, 205}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 64, 79, 98, 139, 183}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 104, 42, 35}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 182, 16}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 111, 102}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 237}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 237, 180, 151}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 83, 57, 155, 192}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 75, 116}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 116}, 255}, {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 51}, 255}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 197, 163}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 253, 202, 147, 27, 57, 174, 204}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 139, 168}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 66, 110, 185, 205, 126, 237}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 122, 64, 220, 168, 46, 44, 122, 78}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 107, 211}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 20, 12, 60, 198, 188, 101, 184, 239}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 167, 202, 120, 53, 4}, 106}, {{201, 143, 240, 240, 209, 224, 0, 199, 223, 75, 157, 218, 45, 177, 1, 161}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 114, 114}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 74, 110, 50, 255}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 5, 42, 44, 53}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 162, 150, 187, 197, 78, 175, 61, 113}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 81, 184, 175, 186, 40, 188}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 115, 61, 38, 172, 218, 199, 89}, 106}, {{201, 143, 240, 240, 209, 224, 0, 138, 92, 165, 156, 138, 45, 62, 126, 9}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 199, 126, 64}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 35, 28, 197, 73, 84}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 164, 40, 70, 218, 104, 247}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 150, 72, 99, 101, 241}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 181, 162, 195, 171}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 201, 118, 191, 77, 248, 84, 123, 173}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 110, 242, 180, 74, 104, 191, 30, 80}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 46, 84, 9, 49}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 129, 87, 146, 183, 155}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 104, 158, 63, 51, 141, 32, 55, 193}, 106}, {{201, 143, 240, 240, 209, 224, 0, 123, 185, 102, 38, 63, 213, 50, 158, 215}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 160, 209, 227}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 66, 246, 147}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 226, 137, 34, 9}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 28, 29, 247, 238, 122, 72}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 162, 138, 104, 149, 104, 242}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 144, 198}, 106}, {{201, 143, 240, 240, 209, 224, 145, 28, 179, 129, 243, 162, 72, 135, 27, 46}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 117, 42, 3, 30, 47, 46}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 167, 104, 213, 156, 125, 211, 202, 110}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 62, 44, 176, 100}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 104, 106, 237, 75, 156}, 106}, {{201, 143, 240, 240, 209, 224, 142, 219, 198, 23, 162, 113, 63, 161, 113, 223}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 77, 198, 22, 222, 149, 162, 182}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 216, 248, 82, 133, 175, 40, 50}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 3, 129, 11, 250, 79, 134, 88, 213, 217}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 81, 111, 140, 249}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 26, 245, 64}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 151, 138, 62}, 106}, {{201, 143, 240, 240, 209, 224, 58, 0, 239, 137, 148, 197, 71, 50, 97, 167}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 198, 176, 42}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 83, 165, 90, 101, 11}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 192, 239, 228, 204, 40}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 106}, {{201, 143, 240, 240, 209, 224, 0, 229, 34, 23, 40, 60, 234, 159, 177, 107}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 119, 191, 70}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 223, 102}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 88, 10, 251}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 64, 113, 237}, 106}, {{201, 143, 240, 240, 209, 224, 0, 131, 184, 2, 54, 18, 234, 173, 193, 179}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 207, 118, 27, 101}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 23, 202, 178, 218, 186, 138, 77}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 83, 164, 217, 67, 228, 109}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 101, 198}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 221, 110, 80, 215}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 86, 18, 5, 104}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 112, 223}, 106}, {{201, 143, 240, 240, 209, 224, 15, 36, 202, 255, 6, 145, 220, 151, 1, 58}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 224, 81, 102}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 200, 250}, 106}, {{201, 143, 240, 240, 209, 224, 0, 8, 244, 33, 122, 176, 11, 112, 218, 172}, 106}, {{201, 143, 240, 240, 209, 224, 0, 9, 8, 165, 174, 99, 130, 5, 132, 151}, 106}, {{201, 143, 240, 240, 209, 224, 0, 184, 88, 241, 155, 236, 1, 182, 154, 231}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 255, 116, 251, 170, 98, 228}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 136, 196, 59, 75, 95}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 97, 224, 106, 7, 254, 108, 112}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 22, 212, 194, 47, 198, 119}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 113, 66, 182}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 106}, {{201, 143, 240, 240, 209, 224, 0, 124, 89, 250, 187, 36, 70, 86, 18, 29}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 112, 151}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 169, 73, 152}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 184, 157, 64, 29, 151, 32, 111, 62}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 126, 34, 21, 83}, 106}, {{201, 143, 240, 240, 209, 224, 103, 227, 128, 136, 20, 184, 151, 78, 149, 193}, 106}, {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 135, 10, 145, 172}, 106}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 18}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 19, 100}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 191, 129}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 82, 114, 120}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 8, 209, 11, 234, 143, 109, 63}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 133}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 222, 240, 144, 224, 56}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 72, 156, 99, 151}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 93, 109}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 113, 77, 186, 38, 32, 72, 166}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 173, 12, 111, 189, 129, 214, 26}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 168, 17, 117, 226}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 6, 60, 23}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 139, 53}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 38}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 84}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 13, 107}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 186}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 63, 208, 89, 149, 170, 146}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 229, 131, 253, 11}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 137, 180, 12, 178, 52}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 133, 101, 178, 70, 24}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 34, 102}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 216, 143, 53}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 76, 230, 123, 214, 232, 100, 15}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 79, 10, 197, 128, 243, 172}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 194, 95, 15, 83, 161, 200, 117}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 175, 208, 85}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 8, 136, 178, 135, 23, 13}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 73, 175}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 140, 232, 49, 181, 14}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 95, 220, 60, 171, 190, 236}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 231, 92, 207, 152, 245, 147}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 174, 100, 248}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 127, 119, 48, 18}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 92, 86, 102}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 238}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 58, 80, 7, 117, 241, 177}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 177, 9, 228}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 204, 51, 78, 196, 5, 173, 117}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 219, 19, 37}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 193, 50, 125}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 14, 208, 224, 52, 100}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 254, 218, 18, 218, 175}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 17, 115, 60, 210, 184, 39, 163}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 108}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 155}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 133, 132, 250, 235}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 118, 242, 67, 159}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 228, 248, 213, 142, 147, 233, 153}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 67, 222, 8, 119, 133, 42}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 135, 44, 118, 228}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 71, 3, 184, 86}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 20, 109, 73, 210}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 22, 46, 131, 116}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 131, 25, 152, 33, 156, 224, 135}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 89, 30, 98, 179, 140, 200}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 129, 63, 162, 218, 82, 254}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 104, 54}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 98}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 94, 226, 72, 214, 71}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 54, 77}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 98}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 186, 7, 154, 138, 166, 79, 219}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 179}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 153, 219, 52, 146, 4, 172}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 28, 128, 190}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 68, 12, 9, 21, 198}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 25, 129}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 144, 179, 132, 47, 16, 55}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 74, 146, 115, 6, 129, 36}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 29}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 244, 171, 162, 207, 168, 248}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 46, 100, 50, 25, 7}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 207, 208, 19, 166, 109, 37}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 7, 85, 195, 212, 198, 121}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 10, 250, 99, 102, 160, 200, 113}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 176, 43}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 40, 235, 28, 144, 85, 162, 69}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 46, 246, 163, 84, 98, 22}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 115, 59, 195, 120, 48, 209, 96, 55}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 152, 202, 139}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 108, 207, 27, 192, 82, 224}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 89, 87, 90, 44}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 131, 134, 141}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 92, 169, 205, 113, 62}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 136, 205, 158, 254, 39, 46}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 84}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 74, 127, 56, 91}, 170}, {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 21, 119, 7, 160}, 170}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 150, 46, 238, 164}, 86}, {{5, 114, 0, 0, 0, 0, 91, 210, 74, 139, 141, 144, 93, 27, 178, 25}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 15, 143, 130, 47, 147, 19, 175, 132, 149, 188, 237, 100, 135}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 212, 43, 75, 50, 53, 225, 189}, 86}, {{5, 114, 0, 0, 208, 105, 242, 201, 168, 41, 92, 79, 192, 86, 255, 110}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 1, 186}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 18, 130, 243}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 162, 70, 123, 23, 193, 14}, 86}, {{5, 114, 0, 0, 0, 0, 0, 184, 49, 141, 12, 77, 194, 140, 108, 235}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 170, 46, 194}, 86}, {{5, 114, 0, 51, 237, 36, 43, 96, 213, 102, 201, 138, 92, 30, 248, 175}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 112}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 218, 25}, 86}, {{5, 114, 0, 248, 182, 60, 232, 69, 250, 123, 35, 113, 129, 138, 92, 156}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 59, 21, 192}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 124, 170, 205, 163, 146, 28, 232}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 251, 235, 0, 12, 189, 133, 227, 167}, 86}, {{5, 114, 0, 0, 101, 121, 108, 191, 29, 86, 167, 40, 13, 162, 142, 101}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 149, 164, 118}, 86}, {{5, 114, 0, 0, 0, 0, 0, 202, 242, 92, 66, 168, 60, 133, 121, 170}, 86}, {{5, 114, 0, 0, 0, 0, 236, 173, 172, 160, 186, 22, 195, 99, 104, 182}, 86}, {{5, 114, 0, 0, 0, 0, 0, 52, 124, 168, 109, 137, 40, 160, 19, 254}, 86}, {{5, 114, 0, 0, 0, 0, 235, 174, 91, 215, 210, 198, 54, 236, 229, 68}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 86}, {{5, 114, 0, 0, 199, 28, 253, 223, 25, 167, 202, 82, 32, 8, 214, 154}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 14, 173, 128, 230, 219, 70}, 86}, {{5, 114, 0, 0, 122, 41, 92, 114, 186, 150, 239, 222, 14, 143, 163, 212}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 238, 246, 123, 189, 170, 163}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 37, 186, 47, 23}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 129, 7, 57, 103, 118, 3, 247}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 149, 142, 234, 226, 96, 40, 45, 13}, 86}, {{5, 114, 0, 176, 185, 238, 95, 209, 88, 18, 172, 220, 236, 160, 240, 126}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 130, 40, 78, 243, 158, 120, 94, 106, 29, 217}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 191}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 2, 147}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 13, 72, 60, 241, 198, 148, 17}, 86}, {{5, 114, 0, 0, 0, 0, 130, 222, 22, 142, 108, 25, 148, 30, 37, 119}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 149, 67}, 86}, {{5, 114, 0, 0, 0, 0, 12, 160, 236, 44, 242, 19, 237, 188, 175, 91}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 138}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 79}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 207, 153, 171, 184, 249, 24, 31, 250}, 86}, {{5, 114, 0, 0, 0, 0, 192, 163, 38, 79, 251, 121, 156, 111, 13, 89}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 184, 203}, 86}, {{5, 114, 0, 0, 0, 0, 237, 193, 0, 35, 197, 251, 51, 180, 221, 196}, 86}, {{5, 114, 0, 154, 41, 11, 111, 178, 233, 46, 230, 74, 129, 168, 43, 22}, 86}, {{5, 114, 0, 0, 0, 0, 0, 196, 81, 51, 149, 24, 16, 154, 101, 103}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 89, 138, 218, 4, 37, 139, 93}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 238, 128, 227}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 203}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 173, 38, 87, 137, 227, 160, 216}, 86}, {{5, 114, 0, 201, 110, 175, 244, 73, 126, 79, 32, 54, 179, 159, 164, 54}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 167, 92, 66, 89}, 86}, {{5, 114, 0, 0, 0, 0, 252, 39, 38, 51, 226, 190, 73, 18, 90, 155}, 86}, {{5, 114, 0, 0, 0, 0, 244, 65, 143, 18, 164, 243, 100, 159, 95, 51}, 86}, {{5, 114, 0, 0, 0, 0, 0, 159, 18, 0, 24, 201, 40, 130, 148, 188}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 135, 235, 171, 125, 113, 84, 15}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 254, 113, 8, 79, 174, 202, 154, 146, 60, 211}, 86}, {{5, 114, 0, 0, 0, 0, 0, 105, 126, 133, 232, 142, 130, 96, 26, 5}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 199, 90, 22, 6}, 86}, {{5, 114, 0, 65, 226, 6, 126, 75, 221, 69, 97, 184, 130, 53, 89, 243}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 35}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 219, 144, 87}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 86}, {{5, 114, 0, 0, 0, 110, 96, 81, 115, 214, 161, 170, 80, 217, 141, 164}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 77, 80, 22, 211, 91, 68}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 251, 145, 232, 82}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 11, 175, 49, 219, 151, 187, 148, 40}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 65}, 86}, {{5, 114, 0, 0, 137, 21, 242, 194, 79, 88, 2, 216, 116, 221, 24, 25}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 179, 78}, 86}, {{5, 114, 0, 0, 0, 74, 70, 16, 54, 227, 239, 205, 3, 243, 195, 104}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 86}, {{5, 114, 0, 0, 0, 0, 161, 229, 99, 44, 49, 100, 70, 20, 128, 233}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 168, 66, 116, 43, 75, 146}, 86}, {{5, 114, 0, 0, 0, 24, 62, 230, 126, 75, 244, 41, 247, 126, 69, 102}, 86}, {{5, 114, 0, 0, 0, 0, 0, 103, 145, 47, 233, 81, 158, 28, 162, 106}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 252, 245, 123, 84, 85, 63, 172, 102}, 86}, {{5, 114, 0, 0, 0, 252, 229, 208, 127, 195, 86, 75, 237, 17, 81, 143}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 234, 106, 158, 119, 241, 235}, 86}, {{5, 114, 0, 223, 180, 0, 79, 122, 89, 107, 133, 241, 244, 155, 39, 151}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 25, 175, 179}, 86}, {{5, 114, 0, 0, 0, 76, 63, 239, 7, 222, 125, 241, 0, 54, 24, 210}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 153, 169, 237, 22, 193, 164, 142, 3}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 230, 85}, 86}, {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 229, 161, 7}, 86}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 200, 50, 202, 109}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 145, 232, 99}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 107, 32, 146, 171, 100}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 146, 224}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 21, 103, 76, 11, 34}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 158, 161, 241, 188}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 43, 80, 134}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 108, 142}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 34, 73, 87, 73}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 9, 154}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 109, 55}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 59, 237, 85, 71, 15}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 85, 246, 120}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 119, 174, 146, 199, 190}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 139, 92, 64, 84}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 107, 155, 49, 163, 121}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 14, 52, 12, 6}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 110, 159}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 106, 34}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 219, 225, 55, 77}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 210}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 158}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 125, 102, 185, 123}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 3, 3}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 104, 84, 196, 251, 254}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 83, 91}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 189}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 149, 242, 74, 149, 203}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 222, 242}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 82, 152, 166, 220}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 212, 175}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 229}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 64, 22, 185, 226, 187}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 167, 210, 149}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 120}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 159, 81}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 175, 70, 56}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 229}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 106, 46, 255, 148}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 211, 46, 82}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 91}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 20, 153}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 183}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 110}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 165, 151, 5}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 169, 46, 131}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 144, 253}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 153, 195, 1}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 41, 22}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 207}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 83, 48, 46}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 88, 116, 211, 222}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 158, 246, 30}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 232, 15, 138}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 214, 235, 4}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 186, 179}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 24, 207, 98}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 88, 3}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 123, 251, 10, 48, 242}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 228, 128, 224}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 176, 63, 176, 62, 145}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 84, 11, 148, 159, 231}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 52, 196}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 111}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 109, 6}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 185, 202, 224}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 84, 31, 251, 15, 199, 74}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 247, 161}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 169, 66, 129, 104, 148}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 43, 81, 165, 247}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 206, 191, 102, 98}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 73, 234}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 147, 114}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 81, 15, 76, 247}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 96, 245, 238}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 32}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 248, 244}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 6, 135}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 222}, 155}, {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 164, 220, 108, 89}, 155}, {{21, 52, 9, 86, 224, 221, 10, 137, 203, 67, 29, 49, 200, 107, 252, 103}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 59, 79, 244, 121, 76, 78}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 124, 38, 117, 27, 107}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 150, 38, 239, 219, 39, 255}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 66}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 141}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 210, 116, 109, 197, 114, 160}, 65}, {{21, 52, 9, 86, 224, 192, 137, 98, 86, 11, 251, 146, 167, 106, 144, 99}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 66, 42, 28, 241, 190, 52, 81, 37}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 80, 27, 8}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 231, 45, 79}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 7}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 220, 40, 26, 142}, 65}, {{21, 52, 9, 86, 224, 151, 135, 108, 57, 36, 156, 28, 94, 170, 18, 116}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 212, 8, 65, 108, 230, 14}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 95, 15, 115, 182, 150}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 141, 202, 224, 91, 134}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 98, 160, 139, 148, 26}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 47, 15, 135, 110}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 198, 127, 72, 6, 165, 70, 20}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 65}, {{21, 52, 9, 86, 224, 107, 161, 143, 51, 10, 163, 42, 152, 51, 215, 105}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 145, 199, 233, 14, 239, 168, 154}, 65}, {{21, 52, 9, 86, 224, 0, 0, 249, 205, 245, 181, 239, 115, 116, 181, 67}, 65}, {{21, 52, 9, 86, 224, 0, 0, 57, 192, 152, 129, 19, 149, 154, 124, 198}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 251, 66, 218, 254, 42, 17}, 65}, {{21, 52, 9, 86, 224, 0, 0, 156, 219, 216, 151, 4, 109, 136, 185, 238}, 65}, {{21, 52, 9, 86, 224, 0, 11, 228, 247, 3, 58, 140, 6, 101, 143, 47}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 186}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 215, 113, 156, 134, 231, 132}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 32, 106, 3}, 65}, {{21, 52, 9, 86, 224, 0, 0, 140, 123, 17, 188, 29, 192, 255, 17, 48}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 238, 187, 98, 53, 193}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 241, 107, 166, 21, 119, 3}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 233, 197, 184, 124, 67, 19, 136, 28}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 192, 41, 113, 45, 195}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 106}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 93, 228, 130, 118, 237}, 65}, {{21, 52, 9, 86, 224, 0, 223, 3, 133, 184, 136, 223, 122, 173, 148, 128}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 55, 221, 202, 119, 114, 157, 140, 76, 22}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 109, 51, 233, 248, 72, 206, 203}, 65}, {{21, 52, 9, 86, 224, 0, 223, 133, 85, 41, 228, 104, 111, 39, 197, 136}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 172, 251, 2}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 163, 151, 124}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 62, 148, 218, 211}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 174, 64, 238, 91, 59, 97}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 91, 209, 125}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 74, 213, 150, 100}, 65}, {{21, 52, 9, 86, 224, 0, 114, 153, 23, 230, 243, 60, 179, 113, 243, 142}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 217, 14, 245, 120, 179, 222}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 175, 164, 222, 245, 81, 176}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 104, 124, 75, 18, 82, 155, 185}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 93}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 5, 78, 72, 8}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 238, 84, 253, 60, 76}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 184, 73, 144, 191, 129, 101}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 140, 2, 193, 205, 61}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 67, 54, 22, 121}, 65}, {{21, 52, 9, 86, 224, 0, 0, 29, 183, 135, 131, 211, 194, 198, 28, 152}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 180, 193, 138, 189, 152}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 213, 220, 255}, 65}, {{21, 52, 9, 86, 224, 0, 0, 188, 169, 0, 109, 181, 54, 32, 65, 231}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 91, 52, 212, 26, 164, 11}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 229, 58, 74, 116, 9, 202, 2, 41}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 251, 237, 74, 233, 116, 112}, 65}, {{21, 52, 9, 86, 224, 4, 251, 103, 32, 6, 12, 60, 184, 118, 3, 197}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 143, 174, 247}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 119, 7, 209, 160, 233, 159, 157, 4}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{21, 52, 9, 86, 224, 217, 32, 42, 6, 249, 92, 183, 14, 37, 101, 148}, 65}, {{21, 52, 9, 86, 224, 0, 150, 188, 18, 49, 216, 0, 21, 254, 161, 184}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 15, 239, 111, 220, 213, 63, 169}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 65}, {{21, 52, 9, 86, 224, 0, 67, 130, 242, 236, 0, 64, 63, 189, 180, 156}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 70, 216, 181, 117, 169, 189, 8, 40}, 65}, {{21, 52, 9, 86, 224, 38, 149, 190, 38, 226, 253, 111, 229, 56, 81, 80}, 65}, {{21, 52, 9, 86, 224, 0, 0, 180, 174, 30, 23, 80, 88, 173, 155, 67}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 34, 168, 161, 60}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 131, 119, 72, 97, 109, 124}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 64, 239, 114, 164, 192, 114, 255}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 14, 2, 159, 209, 219, 4, 104}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 172, 64, 23, 229, 206, 134, 249, 26}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 189, 92, 133}, 65}, {{21, 52, 9, 86, 224, 0, 211, 92, 68, 14, 78, 223, 121, 122, 219, 197}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 113, 15, 168, 202}, 65}, {{21, 52, 9, 86, 224, 0, 0, 186, 221, 84, 67, 172, 118, 13, 127, 1}, 65}, {{21, 52, 9, 86, 224, 0, 0, 0, 0, 129, 167, 239, 82, 141, 177, 94}, 65}, {{203, 81, 49, 171, 224, 0, 0, 16, 135, 71, 130, 161, 145, 197, 16, 151}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 76, 226, 251, 146, 98}, 39}, {{203, 81, 49, 171, 224, 203, 219, 116, 30, 214, 186, 66, 128, 229, 33, 176}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 160, 128, 131}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 35, 34, 92}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 164, 235, 0, 174}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 196, 99, 178, 149, 104}, 39}, {{203, 81, 49, 171, 224, 0, 0, 156, 255, 60, 189, 86, 64, 200, 190, 213}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 226, 185, 175, 252, 96, 122, 152}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 254, 64, 26, 9, 41, 172, 17, 188}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 176, 167, 105, 73}, 39}, {{203, 81, 49, 171, 224, 0, 51, 248, 140, 139, 197, 27, 96, 234, 166, 132}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 144, 151, 97}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 39}, {{203, 81, 49, 171, 224, 118, 185, 227, 3, 85, 48, 157, 4, 136, 102, 64}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 22, 16, 42, 157}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 53, 136, 2, 193, 217, 106}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 207}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 113, 27, 52, 246, 45}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 103, 119, 13, 41, 239, 169, 79}, 39}, {{203, 81, 49, 171, 224, 0, 198, 0, 135, 37, 234, 116, 148, 250, 242, 218}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 125, 183, 24, 43, 24, 62, 201}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 45}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 81, 224, 120, 136, 34, 11, 194, 27, 108, 129, 109}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 10, 97, 136, 114, 39, 99, 215}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 241, 35, 163, 211, 204, 214}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 69, 30, 109, 112, 50}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 67, 57, 221, 139, 18, 41, 21, 103}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 14, 88, 229, 58}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 150, 149, 239}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 69, 167, 18}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 30, 159, 40, 109, 122, 25}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 82, 131, 134, 219, 66}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 211, 167, 51, 250, 59, 32, 229}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 103}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 145, 100, 93}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 169}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 140, 204, 83, 211, 213, 168}, 39}, {{203, 81, 49, 171, 224, 193, 76, 143, 127, 45, 37, 35, 165, 173, 43, 87}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 93, 85, 128, 42, 69, 45}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 174, 120, 168}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 51, 151, 93, 9, 8, 243, 79}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 138}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 99, 50, 157}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 202}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 12, 250, 132, 229, 51, 67}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 119, 222, 0, 29, 132}, 39}, {{203, 81, 49, 171, 224, 0, 0, 138, 249, 120, 53, 176, 73, 148, 109, 82}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 19, 219, 12, 94, 48}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 57, 148, 238, 227, 16, 173}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 44, 165, 190, 244, 89}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 137, 141, 226, 114, 255, 198, 26}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 95, 29, 18, 97, 151, 187}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 11, 230, 182, 175, 130}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 178}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 81, 163, 151}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 69}, 39}, {{203, 81, 49, 171, 224, 0, 0, 58, 18, 41, 193, 49, 129, 72, 34, 27}, 39}, {{203, 81, 49, 171, 224, 33, 36, 62, 193, 26, 92, 153, 222, 212, 61, 148}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39}, {{203, 81, 49, 171, 224, 122, 28, 161, 3, 139, 87, 78, 31, 86, 96, 159}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 120, 193, 74, 24, 151}, 39}, {{203, 81, 49, 171, 224, 0, 93, 41, 101, 238, 24, 116, 164, 110, 98, 19}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 21, 186, 188, 206, 20}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 196}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 222, 86, 44, 105, 220, 240}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 104}, 39}, {{203, 81, 49, 171, 224, 39, 235, 140, 157, 202, 10, 36, 101, 127, 121, 179}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 149, 48, 203, 255, 232}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 191, 182, 110}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 71, 12, 170}, 39}, {{203, 81, 49, 171, 224, 0, 236, 175, 158, 245, 210, 3, 11, 65, 188, 156}, 39}, {{203, 81, 49, 171, 224, 0, 51, 242, 133, 207, 145, 101, 14, 59, 13, 111}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 147}, 39}, {{203, 81, 49, 171, 224, 66, 179, 4, 176, 85, 112, 95, 71, 153, 91, 203}, 39}, {{203, 81, 49, 171, 224, 0, 59, 59, 206, 203, 215, 173, 213, 84, 182, 229}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 222, 162, 140, 52, 48, 205}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 3, 42, 156, 86}, 39}, {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 69, 21, 212}, 39}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 168, 1, 200}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 209, 142}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 119, 244, 164}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 68, 194, 221, 142}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 178, 207, 126}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 235, 7, 138, 10}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 128, 31, 25}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 117, 243, 196}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 99, 140, 52}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 193, 147, 67}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 124, 184, 37}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 224, 89}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 164}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 164, 214, 143}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 42, 212}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 125, 230, 18}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 69}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 157, 118, 127}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 89, 239}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 108, 16, 174, 32}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 18}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 236, 60, 134}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 146}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 216, 112}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 160, 10}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 247, 102, 82}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 115}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 55, 114}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 153, 103, 0, 216}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 13}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 103}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 128, 101}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 50, 5, 60}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 30, 7, 92, 138}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 159, 68, 207}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 61}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 183, 177}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 127}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 11, 7}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 37}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 98}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 7}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 220, 65}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 145}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 227, 255, 229, 58}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 237, 67, 173}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 164}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 245, 248, 185}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 72, 253, 173, 252}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 147, 78, 170, 69}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 201}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 91, 178, 204, 237}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 204}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 18, 45, 64, 226}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 219, 27}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 235, 10}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 26}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 123}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 11, 178, 29}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 125, 8}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 135}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 163, 128}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 75, 241, 201}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 102, 204}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 149, 116, 83}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 68}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 118}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 22}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 142, 154, 227}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 4, 223, 107, 192}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 53}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 212}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 107}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 183}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 165, 234, 12, 132}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 253, 141}, 162}, {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 70, 129}, 162}, {{77, 64, 0, 0, 0, 0, 0, 165, 234, 71, 48, 174, 146, 240, 112, 2}, 69}, {{77, 64, 0, 0, 0, 232, 191, 31, 22, 206, 179, 104, 86, 254, 81, 120}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 166, 4, 108, 65, 136, 186, 144, 5}, 69}, {{77, 64, 0, 0, 0, 0, 90, 203, 103, 108, 76, 100, 76, 109, 181, 219}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 57, 22, 37}, 69}, {{77, 64, 0, 0, 0, 0, 0, 47, 199, 101, 157, 191, 174, 194, 108, 113}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 42}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 111, 69, 108, 0, 242, 226, 45}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 69}, {{77, 64, 0, 0, 0, 36, 107, 213, 229, 54, 252, 240, 8, 131, 21, 45}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 71, 4, 199}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 192, 106, 252}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 96, 124, 130, 104, 249, 249}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 37, 160, 127}, 69}, {{77, 64, 0, 0, 0, 80, 0, 249, 49, 193, 233, 104, 139, 11, 17, 198}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 234, 132, 103, 8}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 245, 9, 242, 216}, 69}, {{77, 64, 0, 17, 204, 206, 73, 13, 225, 94, 182, 79, 100, 61, 21, 125}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 208}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 140, 124, 219, 104}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 143, 12, 158, 89, 233, 234}, 69}, {{77, 64, 0, 0, 0, 134, 174, 168, 25, 79, 181, 206, 122, 251, 247, 176}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 167, 21, 150, 44, 57, 207, 154, 30, 22, 175, 182, 226, 78, 117}, 69}, {{77, 64, 0, 0, 0, 151, 112, 98, 23, 11, 132, 123, 75, 237, 239, 69}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 131, 53, 96, 244, 57, 34, 191, 149}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 17, 136, 216, 67}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 71, 83, 105, 87, 25, 250, 199}, 69}, {{77, 64, 0, 225, 185, 124, 222, 127, 231, 17, 67, 145, 165, 31, 158, 104}, 69}, {{77, 64, 0, 0, 0, 0, 0, 130, 241, 13, 22, 45, 25, 205, 160, 56}, 69}, {{77, 64, 0, 0, 0, 0, 0, 50, 174, 208, 219, 24, 157, 49, 45, 145}, 69}, {{77, 64, 0, 0, 0, 0, 128, 187, 132, 156, 4, 211, 49, 77, 64, 71}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 48, 109, 53, 241, 191, 175, 179, 41, 221, 173, 120, 225, 70, 87}, 69}, {{77, 64, 0, 0, 164, 13, 161, 60, 227, 152, 93, 20, 89, 49, 209, 33}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 43, 118, 139, 81, 29, 27, 56, 11}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 48, 68, 176, 233, 248, 161, 102}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 212, 8, 228}, 69}, {{77, 64, 0, 0, 131, 110, 171, 117, 216, 251, 12, 208, 58, 80, 199, 163}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 53, 203, 150}, 69}, {{77, 64, 0, 0, 0, 43, 51, 8, 187, 220, 129, 116, 3, 159, 66, 42}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 201, 103, 240, 228, 26, 183, 96, 158}, 69}, {{77, 64, 0, 0, 0, 0, 84, 217, 57, 110, 150, 2, 167, 171, 60, 71}, 69}, {{77, 64, 147, 217, 187, 7, 18, 211, 32, 123, 51, 71, 139, 85, 184, 186}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 141, 41, 148, 245, 190, 48}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 104, 223}, 69}, {{77, 64, 0, 0, 0, 0, 0, 98, 26, 47, 15, 157, 160, 73, 112, 167}, 69}, {{77, 64, 0, 141, 117, 47, 115, 44, 92, 128, 246, 61, 253, 71, 174, 179}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 122, 156, 120, 227, 210, 216, 18}, 69}, {{77, 64, 0, 0, 0, 0, 254, 205, 119, 150, 5, 27, 114, 251, 124, 108}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 228, 74, 189, 28, 236, 184, 189, 137}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 251, 97, 202, 8}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 188, 145, 70, 192, 141, 199, 107, 141, 69, 235, 234, 72, 197}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 199, 38, 34, 197}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 82, 39}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 94}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 221, 134, 231}, 69}, {{77, 64, 0, 253, 128, 227, 30, 209, 134, 74, 215, 110, 106, 165, 178, 13}, 69}, {{77, 64, 0, 0, 128, 52, 185, 200, 219, 211, 120, 164, 177, 225, 62, 164}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 246, 98, 123, 115}, 69}, {{77, 64, 228, 240, 14, 49, 201, 141, 185, 79, 45, 113, 230, 224, 137, 233}, 69}, {{77, 64, 0, 0, 0, 0, 134, 199, 92, 35, 148, 132, 16, 112, 114, 126}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 215, 78, 79, 153, 51, 92}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 122, 199}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 156, 4, 112}, 69}, {{77, 64, 129, 7, 132, 191, 61, 212, 150, 209, 17, 206, 241, 214, 101, 142}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 254, 248}, 69}, {{77, 64, 0, 0, 0, 0, 0, 227, 52, 139, 22, 25, 61, 199, 250, 166}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 141, 183, 72, 175, 2, 194, 86, 144}, 69}, {{77, 64, 0, 20, 217, 125, 53, 61, 7, 77, 72, 75, 35, 98, 248, 129}, 69}, {{77, 64, 230, 123, 155, 33, 164, 118, 129, 109, 131, 202, 96, 97, 18, 125}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 2, 222}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 166, 123, 224, 227, 201, 170, 163}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 248, 246, 94}, 69}, {{77, 64, 225, 228, 243, 104, 236, 3, 227, 203, 214, 196, 174, 109, 171, 207}, 69}, {{77, 64, 0, 0, 0, 0, 98, 202, 184, 6, 67, 22, 213, 153, 41, 135}, 69}, {{77, 64, 0, 29, 134, 90, 105, 135, 254, 135, 249, 30, 161, 97, 48, 199}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 63, 227}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 231}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 110, 29, 99, 62, 41, 113, 227, 150}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 144, 45, 4, 215, 222, 11, 227, 83}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 69}, {{77, 64, 0, 0, 0, 0, 0, 85, 118, 9, 208, 129, 184, 131, 87, 105}, 69}, {{77, 64, 0, 0, 201, 143, 1, 202, 83, 201, 157, 151, 175, 167, 249, 167}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 219, 54, 13, 197}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 145, 165, 192, 167, 29, 226}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 160, 209, 232}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 0, 105, 224, 64, 255, 179, 163, 51}, 69}, {{77, 64, 0, 0, 0, 0, 0, 0, 21, 173, 146, 181, 6, 137, 136, 219}, 69}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 129, 132, 122}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 58}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 116, 32, 55}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 173, 25, 60}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 70, 57, 44, 0, 215}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 213, 65, 217}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 153, 246, 54}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 72}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 100}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 152, 45, 129, 87, 1, 92, 26}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 88}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 64, 120, 66}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 147}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 112, 53, 157, 142}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 225, 226, 129}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 152, 162, 70, 116, 173, 247}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 49, 196}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 171}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 87, 82}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 205}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 94, 202, 12, 84, 221, 216}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 161, 225, 227}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 81, 242}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 223, 49, 33, 254, 154, 116, 183}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 32}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 79, 153, 245, 226, 63, 75, 230}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 187}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 230, 73, 197, 88, 233}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 249, 107, 81, 235, 214}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 110, 193, 243, 108, 135, 44, 189}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 120, 199, 220}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 140, 11, 28, 113, 26, 139, 242}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 122, 62, 160, 44, 149}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 218, 65, 171, 233, 170, 139, 119}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 162, 248, 85}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 19}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 90, 195, 10, 135, 16, 90, 16}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 208, 60, 208, 109}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 156, 237}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 37}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 219, 193, 122}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 227, 120, 237, 141, 242, 153, 94}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 117, 217, 31, 184, 28, 126, 45}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 137, 67, 20, 155}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 114, 166}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 53, 186, 115, 95, 243, 53, 185}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 157, 242}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 7, 157, 29, 104, 135}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 61, 141, 164}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 236, 6, 95, 108}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 230, 21, 11, 204, 19, 10, 105}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 155, 249}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 134}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 42}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 254, 135}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 11, 26, 17}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 43, 221, 9}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 202, 206, 170, 110, 12, 15}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 115, 70}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 141, 67, 145, 193, 88}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 227, 106, 30}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 12, 179, 221, 194, 20, 180, 218}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 69, 47, 245}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 31, 203}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 75, 253, 30, 22}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 44, 182, 141, 82}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 190, 69, 194, 161, 82, 71, 21}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 83, 83}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 76}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 137, 105, 252, 182, 94, 161}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 165, 128, 251, 153, 119, 113}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 152, 98, 174}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 138, 252, 222, 48, 250, 28, 189}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 181, 88, 60, 204, 84, 163, 252}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 231, 123, 145, 203}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 58, 11, 97, 142}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 28, 154, 2, 168}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 74, 139, 116, 255, 197, 243}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 19, 142, 42}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 33, 45}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 162, 86, 31, 108, 19, 210}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 123, 153, 179, 57}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 177, 101, 77, 253, 131}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 145, 58, 17, 110, 141}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 163}, 163}, {{158, 219, 219, 39, 4, 219, 100, 63, 0, 138, 80, 52, 159, 111, 218, 219}, 163}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 222, 117, 141}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 75, 237}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 13, 228}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 26, 28, 207}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 82, 181, 109}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 213, 172}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 197}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 75}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 242}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 157}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 104, 39, 118, 49}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 37, 149, 202, 226}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 164}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 6, 203, 6, 147}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 96, 189}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 226, 194, 209}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 50}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 1, 84}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 41, 23, 127}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 90, 114}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 7, 164}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 107, 19, 175}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 192, 49, 116}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 141}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 212}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 87, 34, 108}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 206, 188, 103, 60}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 220, 146, 73}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 205, 77, 244, 11}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 16, 89}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 124, 211, 85, 251}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 223, 62}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 48, 238, 160}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 181, 155}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 200}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 252, 80, 253}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 99, 97, 175}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 253, 40, 24, 48}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 101, 80, 18, 95}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 201, 47}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 204, 138, 152}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 32}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 192, 119}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 43, 96, 110}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 31, 216}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 248}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 72, 66, 150}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 140}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 155, 10, 132, 212}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 165, 108, 197}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 16, 59, 2}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 154, 41, 151, 106}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 116, 128, 73, 95}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 79, 29, 186, 128}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 72, 253}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 175, 177, 103}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 120}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 224, 124, 209, 185}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 28, 121, 48, 25}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 80, 92}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 221, 234, 124}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 145}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 108, 51, 162}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 123, 103}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 167}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 2}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 222}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 54, 124, 113, 164}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 141, 192, 92}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 228, 112, 183}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 63}, 116}, {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 178, 221, 240}, 116}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 90, 89, 18, 131, 8, 219, 115}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 154, 11, 2, 179, 70}, 19}, {{241, 143, 33, 19, 247, 55, 32, 123, 246, 85, 115, 13, 18, 153, 136, 75}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 62, 67, 40, 94, 23, 225, 182, 127, 33}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 105, 103, 180, 97}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 208, 252, 220, 233, 20}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 235, 82, 146}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 229, 51, 134, 213, 2, 206, 111, 73}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 25, 43, 97, 22, 10, 239}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 250, 142, 158, 5, 6}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 160, 15, 42, 163}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 126, 225, 128, 47, 67, 46, 36}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 125, 46, 91, 107}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 212, 216, 127}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 215, 10, 17, 146, 252}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 230, 231, 78, 52, 64}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 215, 210, 25, 48, 184, 227}, 19}, {{241, 143, 33, 19, 247, 55, 32, 147, 147, 20, 136, 11, 193, 119, 188, 163}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 93, 173}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 181, 113}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 81, 205, 136, 92, 101, 175}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 22, 123, 95, 249, 16, 191}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 131, 97, 170}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 47, 8}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 253, 186, 217, 183}, 19}, {{241, 143, 33, 19, 247, 55, 32, 92, 51, 39, 100, 80, 39, 199, 47, 35}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 34, 164, 125, 84, 121, 80}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 179, 182, 210, 73, 155, 255, 101}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 226, 50, 91, 77}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 125, 14, 143, 94, 113, 119, 207}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 202, 55}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 171, 153, 136, 69, 196}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 167, 39, 190}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 42, 41, 208, 228, 228, 84, 90}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 43, 35}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 19}, {{241, 143, 33, 19, 247, 55, 32, 170, 223, 121, 200, 130, 69, 100, 244, 190}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 210, 155, 77, 4}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 186, 161, 192, 226, 6, 103}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 163, 3, 209, 205, 82}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 221, 178, 7}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 139, 17, 253, 135}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 56, 26, 153}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 139, 217, 161, 189}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 165, 2, 157, 16, 53, 7, 1, 179}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 105, 35, 8, 173, 247, 241, 224, 196}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 195, 133}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 252, 155, 2, 128, 150}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 94, 3, 67, 208, 33, 79, 81, 154}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 114, 33, 26, 238}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 70, 77, 134, 66, 112}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 187, 204}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 212, 127, 85}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 219, 142}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 38, 214, 145, 168, 230, 23}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 249, 168, 141, 10, 41, 129, 212}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 126, 56, 161, 190, 82, 129, 231, 252}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 2, 86, 116}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 82, 41, 76, 245, 207, 160, 56, 157}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 108, 157, 207}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 117, 132, 193, 245, 109, 119, 55}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 209, 118, 138, 210, 94, 11}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 208, 64, 87, 39, 82, 120, 219}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 1, 193, 228, 184, 13, 10, 255, 134}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 123, 87, 148, 171}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 145, 138, 42, 255, 20, 189, 24, 142}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 92, 91, 149, 66, 89}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 80, 221, 155, 158, 200, 230}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 90, 138, 178, 108, 94, 62}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 90, 183, 183, 20}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 46, 247, 226, 251}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 76, 191, 138}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 21, 253, 109, 255, 174, 25, 113}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 232, 203}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 165, 77, 185}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 68, 109, 14, 93, 181, 119, 50, 244}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 238, 118, 220, 211, 33, 234}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 186, 141, 115, 196}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 135, 1, 104, 6, 57, 132, 2}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 159, 43, 36, 57, 69}, 19}, {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{61, 28, 61, 252, 32, 0, 0, 193, 42, 192, 42, 57, 183, 244, 90, 150}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 236, 50, 37, 97, 144, 173, 183}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 252, 116, 40}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 47}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 32}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 176, 139, 139, 76, 8}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 178, 190, 35, 141}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 70}, 48}, {{61, 28, 61, 252, 32, 0, 0, 124, 122, 144, 3, 20, 240, 233, 209, 85}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 191, 201, 229, 138, 111, 127, 241}, 48}, {{61, 28, 61, 252, 32, 62, 202, 154, 145, 219, 67, 196, 241, 25, 158, 224}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 217, 158, 219, 228, 44, 187}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 252, 9, 218, 156, 70}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 131, 37, 29, 231, 189, 28, 108, 44}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 209, 137, 203, 85, 70, 42}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 29, 94, 113, 235, 158, 186, 4, 116}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 181, 70, 40, 46, 7, 162, 30, 172}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 25, 38, 229, 9, 71, 129}, 48}, {{61, 28, 61, 252, 32, 0, 0, 144, 130, 165, 11, 190, 50, 142, 163, 120}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 238, 43, 218, 168, 89, 182}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 248, 86, 154, 227}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 111, 238, 245, 59, 108}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 183, 84, 209, 151}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 45, 235, 180, 93, 245}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 147, 27, 202, 220, 243, 167, 215, 196}, 48}, {{61, 28, 61, 252, 32, 0, 53, 24, 102, 217, 140, 162, 180, 249, 14, 47}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 212}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 238, 85, 146, 140, 136, 199}, 48}, {{61, 28, 61, 252, 32, 0, 67, 89, 144, 121, 52, 168, 108, 79, 236, 9}, 48}, {{61, 28, 61, 252, 32, 0, 0, 166, 156, 123, 65, 133, 7, 237, 126, 74}, 48}, {{61, 28, 61, 252, 32, 0, 151, 13, 81, 42, 90, 60, 131, 40, 15, 155}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 17, 241, 182, 95, 229, 25}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 200, 180, 58, 116, 165, 247}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 220}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 21, 160, 139, 57, 136, 137, 129, 53}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 96, 253, 16}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 172, 33, 162, 66, 219, 33}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 132, 14, 133, 14, 164, 181, 245, 162}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 66, 120, 239, 153}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 221, 232, 164, 145}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 48}, {{61, 28, 61, 252, 32, 0, 0, 238, 230, 236, 223, 101, 174, 222, 135, 113}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 84, 27, 105, 34, 27}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 66, 30, 137, 116, 21, 22, 205, 149, 206}, 48}, {{61, 28, 61, 252, 32, 0, 0, 108, 79, 165, 26, 88, 140, 25, 100, 203}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 22, 27, 140, 85, 152, 221, 215}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 39, 64, 17, 57, 41, 85}, 48}, {{61, 28, 61, 252, 32, 91, 177, 166, 253, 15, 36, 15, 202, 134, 101, 107}, 48}, {{61, 28, 61, 252, 32, 0, 227, 131, 82, 154, 130, 166, 236, 162, 113, 196}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 131}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 180}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 123, 74, 8, 224, 87, 188, 196}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 19, 188, 112, 217, 53, 36}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 102}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 117}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 25, 197, 238, 63, 88}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 34, 25, 127}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 83}, 48}, {{61, 28, 61, 252, 32, 0, 126, 96, 102, 119, 34, 96, 79, 63, 205, 202}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 148, 103, 254}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 181}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 6}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 95, 59, 147}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 253, 84, 180, 176, 80, 104, 94, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 158, 90, 241, 56, 5, 155, 123, 64}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 60, 126, 130, 43, 108, 240, 167}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 24}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 197, 94, 211}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 237, 20, 86, 4}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 165, 250, 218, 17, 248, 71, 120}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 154, 110, 216, 235}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 144}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 9, 95, 209}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 107, 148, 21, 123, 17, 95, 11, 139}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 83, 16, 37, 103}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 182, 20, 115, 200, 151, 214}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 226, 229, 175, 36, 101}, 48}, {{61, 28, 61, 252, 32, 70, 192, 176, 128, 196, 116, 226, 37, 235, 14, 67}, 48}, {{61, 28, 61, 252, 32, 0, 0, 170, 203, 221, 215, 137, 190, 110, 49, 179}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 247, 48, 252, 235, 73, 246, 40}, 48}, {{61, 28, 61, 252, 32, 0, 117, 227, 153, 131, 94, 36, 108, 26, 155, 83}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 47, 2, 101, 191, 84}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 255, 36, 143, 237, 213, 79, 255, 130}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 54, 134, 198, 104, 83, 211, 214}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 42, 27, 106, 48, 208, 57, 120, 244}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 91, 6, 93}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 48}, {{61, 28, 61, 252, 32, 0, 61, 172, 29, 245, 112, 175, 75, 99, 89, 198}, 48}, {{61, 28, 61, 252, 32, 0, 0, 0, 0, 110, 11, 108, 207, 102, 2, 220}, 48}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 41, 69, 20, 63, 206}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 91, 105, 72, 62, 179, 94, 180}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 178, 40, 137, 244}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 51, 187, 58, 8, 156, 36, 115}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 123, 234, 89, 70, 33, 71}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 169, 108}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 185, 95, 145, 110, 225}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 243, 244}, 230}, {{102, 112, 194, 108, 90, 253, 128, 150, 204, 18, 198, 8, 50, 251, 203, 23}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 151, 152, 62, 253, 20, 77, 85}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 71, 160, 177, 162, 189, 8}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 224, 34, 103, 255}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 207, 255, 19, 87, 105, 164, 88}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 50, 51}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 110, 85, 118, 205, 6}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 215, 98, 60, 202, 63, 144, 72}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 161, 105, 223, 61, 253}, 230}, {{102, 112, 194, 108, 90, 253, 128, 60, 115, 179, 65, 140, 68, 21, 230, 200}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 41, 40, 9, 133}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 200, 111, 223, 90, 49, 162}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 80, 61, 94, 139, 248}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 189, 243, 15, 184, 141, 88, 67}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 197, 6}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 169, 219, 238}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 231, 94, 110, 213, 196, 125, 138}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 190, 110, 94, 218, 17, 67, 82}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 178, 64, 101}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 159, 66, 75}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 64, 177, 81, 12}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 49, 152, 54, 18, 77}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 247, 151, 12, 14}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 91, 226, 96, 240, 101, 231, 202}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 223, 226, 190, 139, 41, 190, 10, 216}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 195, 212, 68, 246, 22, 38}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 59, 244, 151, 184, 143, 115, 129, 169, 233}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 142, 191, 14, 232}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 161, 45, 225, 25}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 134, 187, 4, 116, 195, 208}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 71, 92, 76, 191, 12, 88}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 39, 37}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 38, 145, 22}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 44, 148, 56, 122, 189, 2, 43}, 230}, {{102, 112, 194, 108, 90, 253, 128, 138, 191, 47, 148, 206, 214, 37, 102, 187}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 230}, {{102, 112, 194, 108, 90, 253, 128, 202, 201, 171, 193, 251, 184, 85, 101, 151}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 137, 131, 251, 52, 90, 179}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 42, 48, 177, 184}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 158, 17, 55, 118}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 110, 72}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 203, 1, 31, 240}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 76, 39, 219, 186, 187, 174, 95, 62}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 62, 184}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 134, 223, 90, 232, 234, 68}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 126, 22, 16, 182, 216}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 34, 96, 243, 98, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 246, 130}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 33, 134, 207, 191, 218, 91}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 153, 118, 57}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 148, 138, 148, 80, 121, 194}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 112, 164, 121, 113, 95}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 251, 177, 186, 14}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 208, 171, 113, 249, 99, 203}, 230}, {{102, 112, 194, 108, 90, 253, 128, 196, 237, 49, 183, 85, 132, 166, 240, 123}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 126, 175}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 213, 132, 150, 4, 83}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 71, 196, 16, 127, 10, 31}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 163, 101, 127, 179, 92, 146}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 51, 91, 163, 19, 31}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 135, 216}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 57, 186, 231, 86, 77, 109}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 87, 110, 181, 3, 138, 210}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 115, 172, 192, 27, 203, 235, 184}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 203, 198, 137, 182, 116, 157, 204}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 7, 94, 88, 143, 145, 159, 215}, 230}, {{102, 112, 194, 108, 90, 253, 128, 87, 174, 118, 41, 167, 4, 117, 93, 155}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 246, 53, 1, 125, 250}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 97, 189}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 35, 36, 243}, 230}, {{102, 112, 194, 108, 90, 253, 128, 0, 150, 135, 159, 90, 101, 136, 29, 93}, 230}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 185}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 152}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 77}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 234, 174, 218}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 155, 219, 70}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 150, 174, 172, 242}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 214, 204, 57, 16, 161}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 15, 42, 9, 2, 92}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 30}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 86}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 205, 44, 109, 195}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 62}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 126, 227, 143, 43, 112, 101}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 33, 102, 136}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 174, 61, 103, 251}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 210, 33, 93, 88, 136}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 35, 96, 79, 11}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 202}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 77}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 155, 180, 239, 196}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 171, 47, 17}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 234, 168, 182}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 67, 207, 131, 58, 123}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 193}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 124}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 92, 176, 76, 122}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 45, 171}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 203}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 251}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 15, 212, 201, 76, 58}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 17, 53}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 3, 187, 210, 8, 153}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 172, 70, 139, 92}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 229, 44, 90}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 178}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 99}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 173, 142, 64}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 205, 103, 251, 212, 240, 149}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 58, 221, 17, 157, 218, 91}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 208, 185}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 192, 213, 197}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 116, 110, 126, 48}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 148, 155, 38, 125, 238}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 235, 75, 53}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 9, 144, 36}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 76, 110}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 134, 177, 156, 160}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 210, 201, 203, 23, 89}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 144, 189, 47, 116, 168}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 9, 162, 40, 93}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 12, 161, 189}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 58, 46, 195, 163, 70}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 183, 191}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 13, 161, 68, 172, 61}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 200, 138, 13, 79, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 192, 17}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 229, 44, 86, 224, 99}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 182}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 103, 75, 249, 63}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 160, 139, 148, 244, 89, 26}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 138, 52, 47, 74}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 214, 224, 51}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 241}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 104, 144, 59, 36, 248}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 245, 120}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 91, 99, 145, 49, 167}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 187, 186, 147}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 220, 112, 86, 121}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 196}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 153, 245, 57}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 251, 130, 215}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 170, 77}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 7, 160, 80, 185}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 141, 226, 45, 60}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 225, 216, 12, 93, 34}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 17, 146}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 253, 29, 1}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 72, 196}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 1}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 99, 133}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 244, 191, 56, 6}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 49, 145, 82}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 17, 4, 173, 71, 163}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 200, 16}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 137, 78, 176}, 155}, {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 35, 133, 29, 2, 180}, 155}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 6, 174, 34}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 255}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 122}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 67, 34}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 175, 23}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 99}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 56, 155, 100}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 89, 38, 93}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 41, 202}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 63, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 89, 115}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 158}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 165}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 65, 223}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 188, 128}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 163, 36, 136}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 244}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 73}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 3, 200, 171}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 46, 41}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 1, 87, 65}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 183}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 87, 182, 98}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 22, 244, 32}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 245, 242, 58}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 132, 224, 191}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 209}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 71}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 149, 39}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 185, 154}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 63}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 146}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 21}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 128, 197, 77}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 213, 11}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 212, 157}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 114, 109, 21}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 122}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 84, 218}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 189}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 218, 5}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 91, 123}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 55, 143, 3}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 35}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 159}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 9, 117, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 68, 251, 213}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 154}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 82}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 212}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 212}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 59, 179}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 195, 183, 139}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 104}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 142, 168, 231}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 76}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 106}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 63}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 7, 18}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 68, 64, 250}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 215}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 217}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 65, 115, 83}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 171, 195, 110}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 147, 181, 238}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 239}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 158}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 247}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 227}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 228}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 2}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 79}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 122}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 247}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 97}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 216}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 168}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 134}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 99}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 219}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 107}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 106}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 98}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 195}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 171}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 87}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 213}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 143}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 242}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 137}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 85}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 32}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 130}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 29}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 31}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 64}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 50}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 226}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 93}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 74}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 128}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 241}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 54}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 6}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 6}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 86}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 111}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 88}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 81}, 252}, {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 85}, 252}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 242}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 137, 67}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 61, 219}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 120}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 235}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 156}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 97}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 70, 151}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 235}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 99}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 143}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 199}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 3}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 161, 57}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 175}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 213}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 49, 202}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 105, 30}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 43}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 173}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 111}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 245, 111}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 23}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 220}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 209}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 17}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 150}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 77}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 212}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 41}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 11}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 130}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 69, 4}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 5}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 215}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 106, 75}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 1, 25}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 246}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 10}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 254, 52}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 31}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 199}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 66}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 36}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 20, 179}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 176}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 223}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 244, 103, 188, 138, 148, 90}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 26, 255, 79, 17, 99, 112}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 89, 244, 64}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 6, 68, 117, 11, 135}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 229, 122, 225, 180, 233, 30, 40}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 85}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 56, 15}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 83, 155, 189, 63, 255, 135}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 99, 34, 204, 133, 91}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 84, 32, 144, 220}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 220, 11, 110, 126}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 104, 73, 228}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 148, 112}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 50, 24, 231}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 223}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 20, 185, 164, 5, 129, 82}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 104}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 122, 81, 54, 227}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 56}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 162, 4, 36, 103, 147, 83}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 211}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 242, 204, 78, 87, 160, 252, 174}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 181, 57}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 211, 43, 85, 10}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 64, 25, 222, 56, 2, 162}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 9, 105, 84, 31, 80}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 1, 169, 176, 22, 232, 155, 182}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 68}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 165}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 103, 187, 66, 32, 60, 194, 224}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 249}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 210, 30, 107, 229, 30, 108}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 253, 188, 139, 217}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 248}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 203, 159, 40}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 93}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 218, 110}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 210}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 36, 112, 202, 216, 32, 82, 59}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 218, 241, 142, 166, 164}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 213, 176, 20, 119, 232}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 237, 168, 58, 142}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 87, 185, 123}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 220, 98, 236, 28, 145, 223}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 64, 224, 9, 101, 36, 25, 6}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 253, 146, 90, 9, 153, 17, 247}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 104}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 4, 38, 18, 151}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 179}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 94, 142, 154, 82, 23}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 236, 227, 195, 121, 160, 5}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 3, 31, 201, 202}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 82, 66, 32, 184, 21, 83, 201}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 248, 145}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 121, 249, 184, 84, 187, 212}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 175, 246, 239, 151, 120, 184, 164}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 222, 65, 87}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 222, 180, 49, 7}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 117, 157}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 83, 200, 192}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 60, 187, 150, 251, 227, 233, 73}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 246}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 15}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 45}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 99, 96, 249, 55, 231}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 210, 73}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 71, 164, 50}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 161, 39, 205, 200, 255}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 190, 70, 79, 193}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 254}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 120, 63, 124, 218, 97}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 126, 97}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 234}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 164, 51, 185, 58, 140}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 161}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 101, 118}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 96, 15, 69, 183, 9, 51}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 72}, 211}, {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 79, 28, 205}, 211}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 168, 212, 63, 217, 114}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 184, 11, 45, 175, 102, 162, 129}, 15}, {{158, 165, 2, 144, 0, 0, 164, 190, 2, 69, 8, 229, 42, 246, 94, 193}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 135, 226, 50, 109, 49}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 105, 112, 0, 57, 22, 74, 106}, 15}, {{158, 165, 2, 144, 0, 99, 52, 105, 55, 99, 196, 103, 118, 251, 125, 10}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 112, 81, 62, 136, 229, 117}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 51}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 196, 176, 6, 157, 228}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 242, 187, 19, 183, 48}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 140, 165, 250, 100, 209, 58, 31}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 139, 44, 229, 214, 149}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 214, 196, 118, 127, 243, 146}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 122}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 33, 3, 250, 127, 202, 80, 136}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 97, 206, 143, 179, 122, 145, 209}, 15}, {{158, 165, 2, 144, 0, 114, 203, 135, 37, 219, 86, 157, 53, 198, 142, 145}, 15}, {{158, 165, 2, 144, 0, 0, 0, 60, 122, 162, 173, 238, 168, 69, 54, 134}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 62}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 208, 155, 72, 156}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 57}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 65}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 206, 45, 131, 27, 109}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 23, 203, 230, 21, 178, 110, 233}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 156, 88, 59, 172, 4}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 215}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 139, 167}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 236, 172, 59, 220, 74}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 103, 189, 61, 222, 216, 53}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 54, 48, 108, 144, 28, 109, 36, 22}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 15}, {{158, 165, 2, 144, 0, 0, 34, 237, 164, 160, 9, 49, 3, 181, 134, 70}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 211, 204, 65, 142, 59, 99}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 44, 246, 168, 202, 142, 23, 118}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 43, 38, 227, 60, 214, 98, 234, 158}, 15}, {{158, 165, 2, 144, 0, 0, 0, 120, 92, 177, 216, 77, 9, 10, 181, 118}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 129, 78, 46, 65, 249, 17}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 65, 190, 63, 107, 33}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 71}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 195, 80, 190, 224, 69, 53, 186, 111, 65, 233, 242}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 194, 206, 222, 241, 51, 180, 199}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 58, 187, 173, 203, 158, 5, 91, 189}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 135, 121, 135, 33}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 180, 184, 89, 232, 184, 147, 125, 172}, 15}, {{158, 165, 2, 144, 0, 0, 240, 221, 200, 172, 252, 77, 29, 174, 241, 132}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 245, 77, 217, 59, 112}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 34, 42, 208, 8, 169}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 56, 109}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 86, 134, 20, 49, 43, 96}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 231, 218, 108, 72, 117, 38, 139, 181, 127}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 131, 46}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 20, 47, 77, 124, 176, 168, 52, 89}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 126, 247, 81, 21, 153}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 251, 14, 38, 22, 77, 152}, 15}, {{158, 165, 2, 144, 0, 0, 121, 121, 113, 73, 14, 116, 14, 143, 182, 72}, 15}, {{158, 165, 2, 144, 0, 140, 161, 29, 203, 84, 31, 9, 130, 186, 184, 154}, 15}, {{158, 165, 2, 144, 0, 0, 0, 190, 200, 16, 238, 68, 158, 139, 106, 73}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 12, 203, 141, 0, 194, 11, 250}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 188, 221, 255, 214}, 15}, {{158, 165, 2, 144, 0, 0, 0, 133, 229, 55, 89, 86, 211, 107, 128, 180}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 159, 2, 171, 193, 86, 223, 23, 82}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 189, 154, 113, 26, 7, 3}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 85, 233, 6, 231}, 15}, {{158, 165, 2, 144, 4, 71, 57, 2, 118, 14, 18, 88, 74, 68, 10, 222}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 65}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 167, 182, 198, 1, 55}, 15}, {{158, 165, 2, 144, 0, 0, 232, 17, 7, 172, 232, 22, 76, 63, 30, 64}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 191, 211, 187, 149, 173, 0}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 78, 195, 36, 128, 241, 79}, 15}, {{158, 165, 2, 144, 0, 0, 0, 80, 149, 90, 83, 129, 236, 89, 226, 219}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 74, 170, 156, 116, 62}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 55}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 151, 166, 89, 128, 194, 47, 241, 120}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 78, 162, 16, 85, 143, 22}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 13, 197}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 109, 104}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 216, 120, 10, 251, 35}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 251, 181, 72, 247, 5, 130}, 15}, {{158, 165, 2, 144, 161, 121, 51, 99, 220, 53, 183, 198, 229, 31, 225, 50}, 15}, {{158, 165, 2, 144, 0, 80, 180, 182, 193, 160, 244, 3, 194, 117, 58, 27}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 141, 153}, 15}, {{158, 165, 2, 144, 0, 0, 0, 249, 73, 8, 159, 113, 176, 231, 166, 8}, 15}, {{158, 165, 2, 144, 0, 0, 182, 102, 92, 6, 116, 200, 236, 14, 52, 252}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 168, 196}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 175, 55, 39, 9, 186, 65, 150, 225}, 15}, {{158, 165, 2, 144, 0, 0, 108, 29, 229, 171, 34, 45, 196, 117, 200, 216}, 15}, {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 103, 68, 96, 74}, 15}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 86, 249, 27, 85, 25}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 34, 206, 24, 232}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 184, 245, 40, 21}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 201, 203, 41}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 82}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 63, 92, 141, 57, 194}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 185, 242, 250}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 156}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 210, 42, 75, 214, 119}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 198, 100, 16, 171, 246}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 47, 160, 116}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 163, 240, 207}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 214, 97, 130, 240, 92, 99, 241}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 245, 228, 113, 31, 189}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 46, 215, 119, 5, 8, 111, 98}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 15, 203, 117, 235, 169, 133, 180}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 242, 120, 185, 161, 125, 203, 198}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 96, 100, 163, 57, 71, 61}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 189, 6, 48, 141, 244, 216}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 74, 181}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 74, 254, 10}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 197, 26, 92, 182}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 249, 66, 128, 216, 166}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 251, 225, 84, 65, 78}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 126, 186, 118, 6}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 241, 247, 192}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 212, 188}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 115, 20, 73, 246, 195}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 129, 246, 149, 16}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 138, 179, 123, 19}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 229, 190, 71, 205, 181}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 97, 27, 115, 247}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 66, 250, 161}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 62, 80, 64, 110, 178, 122, 245}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 214, 8, 183, 147, 139}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 143, 34}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 189, 155, 46, 129, 235, 76}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 56, 35, 102, 98}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 161}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 127, 104, 138}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 140, 71, 185, 50, 152, 18}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 244, 245, 176}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 95, 201}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 54, 224, 59, 162, 128, 95}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 16, 162, 57, 156}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 184, 195, 105, 110}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 128, 255, 116, 111, 6, 2}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 199, 250, 73, 166}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 191, 91, 221, 140, 88, 186, 27}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 202, 252, 186, 141, 145, 151}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 25, 92, 79, 57, 196, 80, 76}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 248, 83, 133}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 185}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 174, 254, 154, 188}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 223, 139, 183, 105}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 244, 26, 219}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 185, 223, 61, 173, 149, 62}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 232, 208, 221, 101}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 122, 169}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 165, 42, 86, 12, 124}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 164, 67, 168}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 224, 213, 71, 177, 163, 253}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 99}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 166, 1, 159, 182, 170, 237, 233}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 182, 193, 215}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 10, 183, 64, 181, 235}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 51, 144, 61}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 104, 190}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 122, 105, 38, 217, 197}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 35, 207, 67, 255, 145}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 33, 10}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 133, 78, 7}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 120, 189}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 211, 159, 101, 17}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 212}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 81, 166, 7, 13, 13}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 193, 100, 174, 245}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 123, 184, 100}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 8, 25, 224, 150}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 25}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 32, 59, 154, 255, 85}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 155, 172, 4, 68, 130, 242}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 189, 251, 184, 203}, 95}, {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 34, 89, 31, 164, 146, 168}, 95}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 106, 210, 86}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 98, 203, 127, 167, 0, 240, 177, 254}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 187, 168, 10, 92}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 144, 238, 207, 4, 214, 170, 155, 136}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 79, 217, 93}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 127, 156, 136}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 10, 107, 5, 131, 2, 181, 226, 173}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 193, 14, 190, 180, 132}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 212, 188, 89}, 169}, {{181, 134, 25, 87, 128, 0, 195, 66, 207, 96, 74, 235, 91, 224, 173, 247}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 91, 157, 211, 239, 160, 159, 128, 67, 51}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 191, 79, 183, 8, 124}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 59, 34, 91, 94, 83, 22}, 169}, {{181, 134, 25, 87, 128, 0, 0, 31, 204, 106, 49, 203, 103, 26, 78, 193}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 144, 30, 124, 86, 106, 220, 74}, 169}, {{181, 134, 25, 87, 128, 0, 0, 86, 255, 112, 118, 137, 105, 70, 174, 6}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 254, 100, 61, 128, 161, 88, 56}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 53, 180, 11}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 27, 190, 117, 179, 99}, 169}, {{181, 134, 25, 87, 128, 0, 50, 123, 29, 100, 62, 252, 240, 115, 95, 12}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 162, 181, 255}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 254, 74, 198, 11, 98, 186}, 169}, {{181, 134, 25, 87, 128, 0, 252, 75, 102, 252, 41, 159, 42, 155, 176, 217}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 224, 157, 86, 12, 139}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 34}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 243, 9, 207, 210, 221, 155}, 169}, {{181, 134, 25, 87, 128, 0, 0, 215, 138, 68, 66, 242, 169, 129, 247, 45}, 169}, {{181, 134, 25, 87, 128, 0, 0, 218, 121, 24, 126, 56, 92, 144, 163, 93}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 58, 205, 245, 92, 37, 48, 170}, 169}, {{181, 134, 25, 87, 128, 0, 0, 224, 18, 32, 96, 240, 78, 155, 138, 153}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 163, 31, 208, 211, 5, 225, 49, 184}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 198, 13, 21}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 162, 201, 62}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 67, 199, 79, 91, 116}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 67, 246, 24, 243, 134}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 164}, 169}, {{181, 134, 25, 87, 128, 0, 84, 12, 129, 244, 2, 166, 215, 170, 142, 243}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 25, 76, 253, 13, 156, 160}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 35, 158, 21, 193, 243, 231, 182, 121}, 169}, {{181, 134, 25, 87, 128, 0, 162, 183, 125, 226, 165, 130, 153, 150, 58, 100}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 184, 145, 94, 53, 46}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 191, 147, 78, 196, 158, 195, 116, 59}, 169}, {{181, 134, 25, 87, 128, 113, 174, 85, 73, 238, 65, 161, 177, 176, 196, 16}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 159, 195, 194, 188, 241, 165, 198, 91}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 58, 175, 229, 96, 169, 113, 195, 247}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 101, 200, 130, 95, 234, 74}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 42, 129, 199, 120, 169, 168, 110, 222}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 37, 133, 20, 205, 11, 30}, 169}, {{181, 134, 25, 87, 128, 0, 0, 169, 223, 117, 79, 240, 45, 112, 134, 162}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 55, 200, 220}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 184, 204, 124, 6, 46, 135}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 249, 84, 89, 105, 134}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 229, 19, 99, 20}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 95, 80, 174, 247, 206}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 161}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 164, 73, 128, 73}, 169}, {{181, 134, 25, 87, 128, 0, 0, 99, 154, 126, 98, 67, 17, 126, 54, 129}, 169}, {{181, 134, 25, 87, 128, 0, 0, 211, 229, 195, 222, 250, 4, 107, 158, 216}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 247, 255, 31}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 51, 225, 243, 242, 7, 245, 145}, 169}, {{181, 134, 25, 87, 128, 0, 0, 171, 177, 182, 153, 34, 221, 58, 207, 244}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 41, 29, 103, 252, 183}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 9, 26, 184}, 169}, {{181, 134, 25, 87, 128, 0, 0, 151, 75, 87, 57, 248, 178, 187, 100, 34}, 169}, {{181, 134, 25, 87, 128, 0, 0, 175, 191, 37, 68, 189, 31, 60, 209, 85}, 169}, {{181, 134, 25, 87, 128, 0, 0, 186, 167, 55, 50, 217, 222, 129, 254, 91}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 9, 148, 171, 104}, 169}, {{181, 134, 25, 87, 128, 0, 129, 67, 202, 16, 246, 6, 135, 238, 111, 2}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 32, 181, 165, 81, 129, 198, 151, 22}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 32, 123, 4}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 228, 230, 146, 113, 90, 33, 132, 210}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 112, 13, 147, 117, 103, 45, 35}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 14, 188, 9}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 169}, {{181, 134, 25, 87, 128, 239, 182, 61, 163, 201, 111, 222, 15, 235, 220, 135}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 80, 107, 167, 143, 237, 142, 17}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 242, 206, 239, 10, 114}, 169}, {{181, 134, 25, 87, 128, 0, 237, 173, 173, 92, 221, 88, 126, 111, 249, 151}, 169}, {{181, 134, 25, 87, 128, 225, 62, 29, 218, 67, 218, 224, 27, 125, 80, 185}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 2, 180, 180, 85}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 124, 225, 188, 15, 0, 177}, 169}, {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 64, 248, 15, 253, 84, 137}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 48, 109, 137, 120, 229, 57, 26, 240}, 249}, {{26, 230, 61, 36, 79, 192, 195, 231, 51, 66, 238, 62, 84, 179, 46, 221}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 177, 196, 252, 101, 225, 245}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 174, 153, 216, 65}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 85, 146, 227}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 114, 210}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 85, 51, 53, 195}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 201, 251}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 164, 29, 89, 252}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 69, 118, 219, 128}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 197, 68, 134, 61, 137, 231, 157, 106}, 249}, {{26, 230, 61, 36, 79, 192, 0, 51, 51, 57, 13, 152, 103, 220, 199, 212}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 87, 201, 200, 196, 110, 207, 60}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 116, 64, 43, 94}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 1, 56, 18, 165, 91}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 173, 140, 11, 251}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 69, 241, 100, 159}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 233, 122, 113, 91, 250, 3, 217, 143}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 6, 112, 38, 225, 97, 248, 170}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 100, 248, 214, 119, 188, 70, 167, 253}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 77, 126}, 249}, {{26, 230, 61, 36, 79, 192, 116, 211, 184, 157, 233, 44, 194, 183, 131, 196}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 56, 79, 109, 1, 8, 128}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 69, 54, 155, 132}, 249}, {{26, 230, 61, 36, 79, 192, 0, 25, 16, 93, 4, 50, 34, 102, 169, 208}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 192, 92, 58, 168, 253, 23, 108}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 171, 159, 214}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 184, 197, 123}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 135, 110, 38, 201, 178, 11}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 46, 250, 56, 65}, 249}, {{26, 230, 61, 36, 79, 192, 0, 179, 25, 204, 107, 33, 229, 0, 195, 144}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 224, 135}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 33, 107, 243, 129, 213, 11, 55}, 249}, {{26, 230, 61, 36, 79, 192, 206, 141, 232, 252, 252, 159, 176, 188, 111, 162}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 117, 102, 221, 197, 102, 13, 18}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 197, 40, 10, 100, 221, 66, 41, 103}, 249}, {{26, 230, 61, 36, 79, 192, 0, 3, 0, 101, 77, 242, 113, 82, 238, 215}, 249}, {{26, 230, 61, 36, 79, 192, 0, 195, 75, 64, 204, 162, 253, 116, 251, 90}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 67, 115, 51, 71}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 44, 196, 187, 249, 245, 139, 91}, 249}, {{26, 230, 61, 36, 79, 192, 70, 95, 166, 157, 99, 56, 205, 115, 178, 164}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 163, 156, 251, 102, 224, 198, 9}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 7, 145, 222, 112, 23, 204, 160, 207, 149}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 125, 88}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 238, 181, 177}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 234, 114, 72, 74}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 181, 38, 136, 121, 227}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 105, 49, 153, 151, 174}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 206, 164, 95, 101, 126, 195}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 187, 206, 200, 147, 140, 159}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 132, 2, 235, 57, 122, 9}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 255, 123, 56, 9, 238}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 253, 252, 148, 52}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 24, 152, 184, 33, 129, 84, 109}, 249}, {{26, 230, 61, 36, 79, 192, 0, 135, 206, 149, 85, 184, 191, 133, 44, 72}, 249}, {{26, 230, 61, 36, 79, 192, 0, 245, 29, 241, 209, 207, 118, 131, 201, 70}, 249}, {{26, 230, 61, 36, 79, 192, 0, 128, 115, 32, 149, 184, 213, 145, 131, 215}, 249}, {{26, 230, 61, 36, 79, 192, 32, 226, 254, 2, 72, 119, 234, 164, 232, 7}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 83, 8, 238, 170, 9, 184}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 141, 77, 128}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 238, 88, 186, 104, 251, 62, 191, 225}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 104, 214, 171, 56}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 40, 85, 1, 161, 145, 3}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 155, 78, 9, 98, 222, 111}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 102, 174, 141, 110}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 14, 52, 117, 95, 146}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 196, 144}, 249}, {{26, 230, 61, 36, 79, 192, 0, 211, 46, 129, 34, 106, 169, 157, 159, 113}, 249}, {{26, 230, 61, 36, 79, 192, 0, 71, 172, 121, 18, 50, 192, 72, 64, 42}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 48, 75, 114, 236}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 152, 110, 182, 25, 21, 24}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 34, 87, 103, 186, 193}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 128, 32, 100}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 236, 72, 4, 196, 86}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 50, 181, 123, 174, 47, 201, 43}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 132, 24}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 120, 224, 59, 219, 4, 56, 112, 158}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 234, 234, 43, 199}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 166, 99, 164, 146, 71, 124, 105}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 219, 68, 123, 47}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 115, 246, 131, 162, 118, 138}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 162, 88, 135, 60}, 249}, {{26, 230, 61, 36, 79, 192, 0, 186, 180, 230, 58, 194, 46, 38, 28, 251}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 243, 106, 231, 54, 77, 50, 40}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 75, 130, 12, 186, 242}, 249}, {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 85, 51}, 249}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 136, 88}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 18}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 62, 158}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 195}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 110}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 203}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 154, 123}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 41, 136}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 253}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 5}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 57}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 193}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 68}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 240}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 1}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 42}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 39, 53}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 240}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 208, 12}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 161}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 234, 42}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 239, 218}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 225, 244}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 57, 42}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 47, 59}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 225, 142}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 37, 253}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 239}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 38}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 225}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 216, 88}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 173, 132}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 188}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 91, 236}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 45, 174}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 121, 228}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 115, 18}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 49, 24}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 187, 86}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 252}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 138, 243}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 68, 42}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 157, 147}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 235}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 155, 139}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 252, 25}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 100, 233}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 134, 115}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 33}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 124}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 233, 206}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 251, 146}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 103}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 208, 229}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 148, 88}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 30, 16}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 26}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 199, 168}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 139, 165}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 43, 170}, 61}, {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 59, 203}, 61}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 77, 31, 186, 99, 78, 84, 130}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 106, 221, 15, 176, 161, 73, 15}, 63}, {{211, 245, 62, 0, 74, 129, 113, 228, 87, 44, 251, 62, 19, 17, 28, 68}, 63}, {{211, 245, 62, 0, 0, 0, 60, 95, 180, 109, 150, 224, 124, 246, 185, 34}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 144, 84, 198, 138, 239, 151, 165}, 63}, {{211, 245, 62, 59, 77, 227, 198, 205, 105, 37, 178, 147, 86, 157, 144, 134}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 234, 76, 217, 131, 247, 142, 23}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 170}, 63}, {{211, 245, 62, 0, 0, 0, 56, 193, 232, 120, 157, 45, 124, 235, 37, 196}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 229}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 39}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 73, 204, 44, 209, 57, 165, 187, 203}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 123, 175, 40, 70, 246, 186, 190, 27}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 78, 86, 89}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 208, 80, 70, 142, 103, 203, 3}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 63}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 195}, 63}, {{211, 245, 62, 0, 0, 0, 0, 217, 127, 44, 238, 234, 252, 80, 83, 44}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 243, 171, 123, 227, 123, 162, 213, 137}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 120, 170, 29}, 63}, {{211, 245, 62, 104, 162, 47, 62, 132, 152, 62, 12, 248, 253, 78, 66, 37}, 63}, {{211, 245, 62, 0, 0, 0, 208, 13, 97, 108, 142, 179, 219, 55, 167, 65}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 166}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 172, 60}, 63}, {{211, 245, 62, 0, 0, 34, 39, 177, 213, 119, 205, 110, 191, 144, 187, 81}, 63}, {{211, 245, 62, 0, 177, 97, 226, 17, 9, 114, 201, 1, 31, 68, 80, 36}, 63}, {{211, 245, 62, 0, 0, 0, 0, 155, 19, 65, 219, 255, 5, 23, 59, 140}, 63}, {{211, 245, 62, 0, 0, 88, 250, 94, 26, 46, 108, 17, 133, 237, 202, 166}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 3, 135, 51, 59, 48}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 251, 22, 115, 100, 12, 112, 9}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 187, 244, 224, 24, 237, 141, 123, 232, 196, 146, 71}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 198, 87, 61, 232, 246, 71, 111, 70, 243}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 60}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 204, 208, 170, 16, 197, 45, 183, 57, 252, 210, 163}, 63}, {{211, 245, 62, 0, 0, 0, 222, 9, 97, 128, 221, 248, 44, 90, 159, 94}, 63}, {{211, 245, 62, 0, 0, 59, 26, 115, 130, 190, 152, 186, 1, 137, 177, 75}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 162, 194, 189, 209, 136}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 250, 93, 13}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 90, 79, 230, 55, 244}, 63}, {{211, 245, 62, 0, 0, 0, 0, 131, 209, 111, 14, 243, 92, 73, 118, 73}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 78}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 182, 150, 54}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 63}, {{211, 245, 62, 0, 0, 0, 227, 169, 206, 84, 38, 230, 44, 243, 200, 210}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 135, 228, 110, 206, 212}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 66, 246, 33}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 115, 198, 165, 190, 55}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 249, 99, 101, 239, 73, 183}, 63}, {{211, 245, 62, 0, 0, 0, 163, 161, 152, 158, 37, 55, 206, 171, 207, 116}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 244, 93, 224, 3, 113, 132, 160}, 63}, {{211, 245, 62, 0, 0, 0, 20, 115, 144, 17, 110, 37, 173, 229, 178, 211}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 184, 88, 125, 150, 45, 194, 86}, 63}, {{211, 245, 62, 0, 0, 0, 0, 149, 93, 67, 235, 234, 38, 199, 100, 188}, 63}, {{211, 245, 62, 0, 0, 0, 0, 214, 178, 221, 17, 64, 61, 64, 86, 56}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 121, 151, 88}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 207, 61}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 89, 203, 138, 191, 177, 42, 102, 28}, 63}, {{211, 245, 62, 0, 0, 0, 119, 21, 45, 175, 179, 182, 143, 117, 72, 19}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 213, 127, 57, 122, 137, 44}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 157, 67, 23}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 203, 7, 178, 35, 60, 3, 88, 171}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 80, 237, 32, 25, 18, 40, 142}, 63}, {{211, 245, 62, 0, 0, 0, 69, 9, 162, 140, 10, 52, 65, 94, 73, 37}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 227, 184, 225, 210, 146}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 165, 133, 251, 87, 90, 89, 1}, 63}, {{211, 245, 62, 0, 0, 0, 0, 133, 10, 107, 27, 88, 22, 237, 211, 252}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 31, 64, 114, 197, 187, 84, 137, 51}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 169, 201, 95, 13, 209, 69, 178}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 68, 161}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 21, 220, 205, 39, 2, 246, 85}, 63}, {{211, 245, 62, 0, 56, 115, 112, 25, 111, 90, 185, 108, 170, 119, 46, 238}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 168, 89}, 63}, {{211, 245, 62, 0, 0, 241, 196, 174, 234, 161, 250, 101, 47, 46, 176, 238}, 63}, {{211, 245, 62, 0, 0, 235, 139, 208, 229, 208, 221, 176, 251, 10, 113, 246}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 133, 194, 0, 123, 255, 135}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 0, 242, 82, 46, 119, 15, 18, 130, 181, 0, 56, 11}, 63}, {{211, 245, 62, 0, 239, 223, 194, 136, 70, 141, 154, 23, 174, 191, 21, 20}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 135, 156, 239, 162, 153, 58}, 63}, {{211, 245, 62, 0, 226, 229, 210, 218, 96, 169, 11, 81, 95, 219, 112, 171}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{211, 245, 62, 0, 164, 17, 135, 211, 34, 216, 147, 67, 35, 188, 179, 54}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 69, 178, 37, 106, 234, 135}, 63}, {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 63}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 175, 185}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 206, 93, 15, 167, 243, 44, 99, 214}, 43}, {{117, 68, 0, 0, 0, 0, 0, 188, 6, 139, 178, 86, 48, 234, 246, 223}, 43}, {{117, 68, 0, 0, 0, 0, 205, 103, 61, 235, 239, 44, 142, 252, 179, 160}, 43}, {{117, 68, 0, 225, 104, 90, 11, 47, 115, 110, 63, 14, 75, 111, 169, 54}, 43}, {{117, 68, 0, 0, 0, 0, 0, 180, 176, 14, 166, 49, 7, 66, 233, 132}, 43}, {{117, 68, 0, 132, 219, 230, 175, 153, 250, 192, 221, 74, 131, 211, 127, 252}, 43}, {{117, 68, 0, 0, 0, 0, 0, 119, 3, 235, 77, 14, 104, 3, 224, 16}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 72}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 0}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 61, 79, 28, 33, 77, 192, 209, 11}, 43}, {{117, 68, 0, 0, 0, 200, 160, 94, 147, 19, 183, 11, 142, 204, 194, 25}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 148}, 43}, {{117, 68, 0, 102, 105, 90, 57, 142, 170, 98, 123, 70, 221, 145, 84, 251}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 81, 32, 229}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 241}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 199, 246}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 45}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 112, 134, 215, 206, 7, 247, 2, 219}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 188, 27, 20, 158, 249, 188}, 43}, {{117, 68, 0, 0, 0, 232, 247, 4, 125, 45, 163, 183, 95, 199, 42, 79}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 1, 250, 15}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 147, 100, 193}, 43}, {{117, 68, 0, 241, 40, 247, 152, 174, 24, 165, 208, 106, 223, 205, 75, 28}, 43}, {{117, 68, 0, 0, 0, 0, 64, 128, 215, 218, 27, 205, 41, 150, 236, 93}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 8, 162, 161, 157, 184, 160, 30}, 43}, {{117, 68, 0, 0, 0, 77, 200, 58, 105, 210, 138, 181, 245, 124, 6, 104}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 172, 183, 227, 191, 8, 253, 214}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 20, 24}, 43}, {{117, 68, 0, 0, 0, 0, 138, 137, 85, 236, 189, 219, 197, 59, 119, 10}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 199, 237, 70}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 39}, 43}, {{117, 68, 0, 0, 0, 0, 0, 56, 80, 16, 59, 241, 146, 147, 78, 98}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 184, 13, 49, 164, 244, 59}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 172, 128, 105}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 145, 169, 83, 193, 69, 166, 202, 238}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 69, 114, 113, 168, 249, 114}, 43}, {{117, 68, 0, 0, 80, 189, 252, 25, 46, 254, 242, 170, 167, 128, 164, 63}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 111, 80, 152, 205, 214, 180, 98}, 43}, {{117, 68, 0, 239, 48, 15, 182, 228, 13, 113, 105, 200, 20, 204, 116, 236}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 21, 137, 66, 143, 249, 161}, 43}, {{117, 68, 0, 0, 128, 110, 17, 234, 177, 124, 62, 65, 35, 78, 248, 175}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 246, 213}, 43}, {{117, 68, 0, 19, 47, 184, 153, 201, 104, 183, 166, 237, 166, 88, 55, 178}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 43}, {{117, 68, 0, 0, 46, 2, 199, 41, 37, 58, 57, 123, 101, 15, 202, 47}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 185, 99, 180, 6}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 167, 95}, 43}, {{117, 68, 0, 0, 0, 8, 12, 226, 1, 147, 44, 48, 86, 224, 84, 25}, 43}, {{117, 68, 0, 0, 232, 230, 10, 249, 86, 115, 134, 73, 255, 21, 130, 242}, 43}, {{117, 68, 0, 0, 0, 0, 72, 255, 219, 168, 181, 56, 24, 241, 226, 200}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 121, 28, 226, 122, 41, 254, 206, 170}, 43}, {{117, 68, 0, 227, 128, 195, 54, 161, 147, 2, 56, 51, 49, 231, 188, 185}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 2, 177, 223, 192, 152, 170}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 242, 11, 246}, 43}, {{117, 68, 0, 0, 16, 1, 57, 67, 78, 9, 245, 164, 17, 191, 183, 127}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 192, 12}, 43}, {{117, 68, 0, 173, 182, 255, 179, 31, 4, 153, 47, 115, 191, 138, 142, 154}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 249, 176, 9}, 43}, {{117, 68, 0, 0, 0, 0, 104, 121, 236, 35, 51, 38, 83, 249, 11, 32}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 43}, {{117, 68, 0, 0, 0, 0, 0, 229, 117, 247, 249, 151, 16, 169, 37, 206}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 45, 35, 194, 99, 55, 3, 122}, 43}, {{117, 68, 0, 0, 0, 0, 0, 15, 0, 254, 107, 12, 82, 148, 210, 90}, 43}, {{117, 68, 0, 0, 0, 31, 159, 96, 76, 42, 237, 195, 153, 37, 170, 27}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 47, 12, 232, 77, 77, 94, 38, 212}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 15, 47, 137, 87, 227, 238, 133, 132}, 43}, {{117, 68, 0, 23, 180, 78, 30, 102, 175, 202, 41, 199, 10, 219, 104, 84}, 43}, {{117, 68, 0, 0, 0, 68, 26, 211, 147, 122, 13, 2, 178, 125, 140, 186}, 43}, {{117, 68, 0, 0, 140, 114, 43, 73, 167, 173, 123, 94, 102, 227, 120, 113}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 136, 68, 149, 177}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 24, 164}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 251, 117, 237, 92, 45, 216}, 43}, {{117, 68, 0, 0, 0, 0, 26, 244, 77, 254, 58, 191, 42, 91, 19, 143}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 100}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 38, 16}, 43}, {{117, 68, 0, 0, 0, 0, 0, 34, 52, 68, 112, 123, 110, 200, 46, 235}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 11, 69, 197, 104, 106, 240, 124, 198}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 172, 202, 189, 72, 5, 52, 7, 180}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 102, 81, 177, 219, 47, 81, 142, 31}, 43}, {{117, 68, 0, 0, 152, 89, 166, 116, 108, 170, 138, 63, 113, 187, 101, 17}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{117, 68, 0, 0, 191, 180, 5, 106, 239, 113, 141, 116, 7, 149, 141, 76}, 43}, {{117, 68, 0, 0, 13, 99, 253, 47, 35, 65, 35, 70, 73, 167, 191, 160}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 7, 103, 77, 245, 166, 171}, 43}, {{117, 68, 224, 60, 43, 48, 62, 142, 215, 141, 74, 49, 178, 15, 103, 32}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 78}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 97, 248, 64, 27}, 43}, {{117, 68, 0, 0, 0, 171, 148, 35, 199, 227, 158, 52, 188, 83, 120, 60}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 52, 54, 190}, 43}, {{117, 68, 0, 0, 119, 57, 243, 201, 253, 31, 122, 222, 231, 165, 40, 120}, 43}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 61, 137}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 213}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 204}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 210, 102, 164}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 118, 71, 210}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 16, 159, 24, 214, 61}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 117}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 74, 183}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 4, 60, 111, 253, 148}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 95, 6, 45}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 100, 128}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 91, 33, 11, 77}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 94, 33}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 141}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 247, 139, 7}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 161, 212, 248, 249}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 137, 4, 179}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 57, 57, 91}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 140, 210, 169}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 70, 205}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 96, 176, 154}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 48}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 98}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 76}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 5, 31, 13, 219, 58}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 141, 199}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 73}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 55, 190, 143, 164, 111}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 57, 95, 142, 70}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 214, 119, 191, 134}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 217, 139}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 16}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 229, 50}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 14}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 136, 216, 188}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 48}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 106, 233, 32, 49, 6}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 53, 178, 187, 106}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 107, 227, 121}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 196, 215, 25, 26, 27}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 123, 123, 92, 139}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 172, 230, 73}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 78, 11}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 67, 114, 167, 94}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 11, 182}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 38}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 129, 1, 119}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 40, 99, 218, 87, 5}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 71}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 87}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 76, 188, 183, 214, 169}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 112, 190, 29, 179, 9}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 34}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 81}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 185, 194, 211, 55}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 198, 11, 68}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 61, 223, 52, 175, 91}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 181, 2}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 235, 173}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 74, 222, 156, 73, 168}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 97, 39, 183}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 40, 33, 232, 236}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 143}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 117, 34, 13, 122, 10}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 28, 229, 63, 185}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 3, 116, 127, 199, 2}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 51, 57, 175, 244}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 193}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 213, 194, 125, 233, 106}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 153, 165, 64}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 90, 156, 240, 63}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 222, 108, 98, 140, 105}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 38}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 75, 246, 77}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 248, 130, 110}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 244, 197, 243, 185}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 125, 107, 34, 33, 111}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 191, 10}, 228}, {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 228}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 128, 38, 148, 75, 180}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 75, 47, 221, 28, 123}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 38, 244, 55, 55}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 66, 44, 195}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 80}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 132}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 127, 4}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 193, 16, 245}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 173, 200, 59, 179, 234}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 107, 19, 188, 4, 16}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 65, 185, 9}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 138}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 227, 122, 166}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 45, 101, 197}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 83}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 25, 130, 69, 89}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 73}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 148, 206, 119}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 234, 106, 241, 74}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 9}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 249}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 217, 88, 202, 89}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 27}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 132, 38, 30, 115}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 175, 207}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 37, 88, 120, 225}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 2, 90, 108, 237}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 133, 139, 166, 55}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 99, 184, 204, 59, 234}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 46, 254, 215}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 228, 41, 177, 187, 227}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 124, 18, 201, 209}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 134, 96, 47, 201}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 108, 150}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 201, 91, 158}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 107, 214, 149, 143, 137}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 169, 173, 253, 133, 222}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 50}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 45, 179, 45}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 13, 244, 134, 247}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 229, 125}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 136}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 253, 187, 244, 242, 105, 251}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 217, 189, 48, 219}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 44, 97, 217, 25}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 45}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 4, 92, 150, 219}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 43, 151}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 233, 188}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 20}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 13, 37, 119}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 75}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 222, 69, 244, 98, 190}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 134, 206}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 245, 210, 160, 188, 86}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 90, 242, 218, 146}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 33, 194}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 148, 236, 39, 126}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 114, 235, 179}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 15, 157}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 9}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 173, 219}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 160, 21, 191}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 52, 85, 97, 94}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 188}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 80, 127, 161}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 107, 181, 116, 124, 250}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 238, 7, 43, 17, 236}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 200, 55, 249, 184, 91}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 240}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 83, 151, 113, 209, 27, 27}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 76}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 23, 105, 253}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 105}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 195}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 38, 181, 114, 6}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 13, 27, 82}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 98, 91, 78, 132, 136}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 86, 125, 127, 65}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 119}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 72}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 130}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 251, 36, 132}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 75, 187}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 147}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 94, 230}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 94, 83, 171}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 193, 164, 179}, 165}, {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 27, 210, 240, 26, 104}, 165}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 219, 238, 9}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 205, 28, 142}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 161, 200, 144, 48, 255, 234}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 161, 86, 168, 204, 56, 197}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 167, 159}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 143, 129, 19, 64}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 13, 27, 105, 103, 161}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 19}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 101, 254, 214, 22, 99}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 4, 235, 71, 250, 243, 127}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 201, 5, 138, 38, 253, 73, 2}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 213, 191}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 213}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 31, 225, 242}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 180}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 80, 53, 45, 237}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 164, 42}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 51}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 208, 241, 193, 136, 20, 207, 71}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 75, 134, 35, 38, 236, 196}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 28, 83, 178, 114, 194, 255}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 138, 231, 155, 226}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 159, 160}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 137, 80, 153, 81, 246, 75}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 117, 112, 8, 72, 227}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 243, 220, 78, 154, 108, 228, 21}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 97, 107, 232}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 155, 31, 105, 205}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 76, 142, 15, 34, 75}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 51, 106, 135, 70, 227}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 123}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 90, 210, 172}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 140, 250, 12, 184, 64, 33, 243}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 231, 149, 44, 183, 225, 105, 115}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 157, 201, 86, 78, 47}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 4, 7, 27, 237}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 221, 38, 21, 206, 225, 10}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 193}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 131, 55, 197, 106, 67, 151, 176}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 57, 24, 145, 223, 122, 71}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 102, 83, 79, 162}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 77, 119}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 243, 115, 60, 98}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 187, 253, 237, 196, 198, 159, 239}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 143, 231}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 168, 38, 47}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 4, 50, 128, 78}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 126}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 2, 127, 153, 165, 80, 104}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 180, 61, 26, 126, 149, 200, 168}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 145}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 161, 148, 62, 72, 212, 201}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 55}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 159, 135, 86}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 95}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 51, 43, 60, 140}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 105, 5, 244, 3, 99, 142, 103}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 127, 185}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 156, 69, 225, 148}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 44, 26}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 85}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 102, 24, 73, 53, 98, 175}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 59, 247, 252, 149, 106, 41}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 46, 76, 79, 11, 45, 68, 244}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 35, 204}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 34, 216, 27, 73, 198}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 71}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 255, 120, 178}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 239, 62}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 121}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 3, 56, 144, 129, 149, 150, 132}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 182}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 248}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 35, 245, 124}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 144, 198, 150, 102, 108}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 186}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 245, 83, 189}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 199, 175, 8, 21, 170, 65, 86}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 211, 71, 217, 53}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 230, 39, 42, 52}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 160, 158, 147, 61, 30, 50}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 78, 25, 81, 105}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 112, 8, 131, 3, 120, 81, 56}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 233, 218, 25, 128, 17, 147, 9}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 193}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 148, 37}, 3}, {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 198, 249, 43, 215, 93, 62}, 3}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 92, 246}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 161, 142}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 157, 70, 136, 185, 247, 179}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 186, 36}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 192, 164, 237}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 171, 97}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 68, 138, 38}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 56, 137, 34, 111, 199}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 189, 185, 44, 248, 143, 178}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 233, 200, 71, 222, 255, 210}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 186, 232, 140, 11, 149, 48, 184}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 124, 41, 224, 226, 64, 201, 84, 141}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 168, 211, 87, 131, 231}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 31, 142, 140, 157, 16}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 160, 201, 67, 117, 153, 32, 235, 229}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 123, 54}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 240, 54, 195, 139, 196, 224}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 199, 59, 88, 89, 63}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 6, 122}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 240, 182, 31, 199}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 149, 111, 192, 167, 122}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 140, 126}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 141, 144}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 24, 171, 40, 151, 108}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 135, 202, 59, 77, 11, 104, 253}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 55, 169, 45}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 146, 64, 199, 191, 110}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 41, 39}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 201, 130, 232}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 252, 158, 209, 20}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 113, 157, 240, 196, 7, 186}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 7, 95, 57, 63, 108}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 235, 111, 77}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 64, 80, 34, 78}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 200, 99, 220, 106, 153, 19}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 87, 147, 119, 69, 97, 142}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 63, 170}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 125, 1, 37, 62, 210}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 107, 27}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 212, 167, 174, 66, 68}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 242, 145, 170, 20}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 152, 185, 9, 213}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 43, 142, 148}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 245, 251, 227}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 15, 50, 161, 163, 154, 190, 14, 20}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 160, 203}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 206, 221, 49, 190, 214, 176}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 169, 45, 181, 89, 104}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 3, 222, 113, 65, 175, 88}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 91, 71, 148, 78, 79, 221}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 224, 94}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 113, 236}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 164, 173, 184, 85, 253}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 90, 207, 25, 165, 131, 167, 114}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 125, 192, 87, 118, 199, 158}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 243, 221, 146, 200}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 151, 99, 5}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 61, 244}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 56, 242, 243, 143, 42}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 133, 237, 10, 129, 197, 15, 255}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 181, 7, 57, 198, 52, 78, 193}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 214, 209, 42}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 113, 157, 244}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 174, 251}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 208, 35, 248, 22, 85, 231}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 220, 243, 212}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 106, 217}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 175, 77, 157, 187}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 203, 126, 15, 118}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 249, 229, 183}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 155, 18}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 187, 35}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 171, 15, 219, 142, 141, 241, 29, 48}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 254, 98, 223, 93, 255, 37, 94}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 186, 153}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 252, 182, 120, 41, 89}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 249, 78}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 42, 52, 29, 151, 23, 229, 130}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 0, 181, 166, 204, 225, 132, 152, 144}, 211}, {{157, 230, 79, 162, 57, 125, 152, 0, 102, 52, 226, 134, 18, 72, 146, 220}, 211}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 146, 24, 88, 122, 38, 199}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 94, 7, 160, 207, 83, 124, 106}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 213, 16, 159, 210, 31, 199, 225}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 111, 182, 67}, 210}, {{27, 67, 64, 235, 128, 0, 214, 207, 238, 102, 201, 27, 143, 189, 204, 127}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 55}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 12, 58, 98, 29, 79, 104, 206, 219}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 172, 61, 119}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 112, 146, 58, 31, 15, 78, 220}, 210}, {{27, 67, 64, 235, 128, 0, 0, 229, 195, 125, 157, 156, 60, 166, 142, 78}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 48, 127, 17, 129, 167, 144, 227}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 252, 193, 61, 183}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 67}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 220, 125, 22, 107, 45, 218}, 210}, {{27, 67, 64, 235, 128, 0, 0, 98, 101, 20, 46, 114, 248, 227, 21, 52}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 89, 113, 106}, 210}, {{27, 67, 64, 235, 128, 162, 19, 230, 214, 39, 123, 241, 31, 58, 152, 237}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 210}, {{27, 67, 64, 235, 128, 0, 0, 215, 202, 60, 76, 60, 134, 4, 82, 69}, 210}, {{27, 67, 64, 235, 128, 232, 106, 69, 252, 88, 12, 113, 11, 152, 245, 176}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 145, 28, 173, 104, 204, 182, 102, 45}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 73, 132, 20, 186, 152}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 163, 197, 22, 107}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 30, 211, 229, 162, 161, 35}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 45, 255, 19, 134, 30, 174, 202}, 210}, {{27, 67, 64, 235, 128, 0, 0, 168, 198, 162, 195, 195, 86, 35, 40, 212}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 210}, {{27, 67, 64, 235, 128, 0, 0, 6, 224, 115, 205, 163, 168, 224, 205, 21}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 232, 205, 50}, 210}, {{27, 67, 64, 235, 128, 0, 13, 210, 14, 55, 44, 30, 249, 253, 224, 226}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 99, 87, 170}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 102, 157, 127, 19}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 2, 186, 3, 8}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 190, 48, 189, 207, 250, 115}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 130, 15, 183, 151, 247, 173, 93, 216}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 208, 45, 237, 156, 188, 178, 227}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 91}, 210}, {{27, 67, 64, 235, 128, 152, 175, 191, 13, 218, 10, 77, 84, 25, 121, 183}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 31, 218, 60, 193, 243}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 109, 22, 98, 187, 81, 138, 175}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 221, 74, 226, 44, 115}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 210}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 172, 115, 206, 204}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 241, 114, 170, 47, 215, 172, 148}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 210}, {{27, 67, 64, 235, 128, 151, 187, 252, 226, 16, 12, 224, 143, 44, 214, 247}, 210}, {{27, 67, 64, 235, 128, 0, 0, 249, 186, 86, 69, 8, 84, 70, 128, 31}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 17, 30, 119, 95, 140, 69}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 131, 235, 22, 198, 137, 227, 21, 227}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 254, 209, 76, 198, 159, 228}, 210}, {{27, 67, 64, 235, 128, 0, 0, 121, 76, 157, 68, 152, 230, 111, 67, 26}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 48}, 210}, {{27, 67, 64, 235, 128, 107, 239, 128, 161, 171, 241, 11, 249, 133, 92, 240}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 70, 55, 78, 29, 90, 235}, 210}, {{27, 67, 64, 235, 128, 0, 0, 16, 94, 77, 189, 216, 66, 194, 117, 10}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 157, 61, 101, 112, 108}, 210}, {{27, 67, 64, 235, 128, 95, 63, 98, 40, 103, 225, 57, 196, 228, 233, 5}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 38, 150, 60, 96}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 36, 134, 23, 53, 56, 4, 11}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 235}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 210}, {{27, 67, 64, 235, 128, 0, 136, 75, 239, 28, 65, 0, 216, 87, 87, 172}, 210}, {{27, 67, 64, 235, 128, 0, 23, 135, 45, 141, 44, 241, 45, 34, 69, 176}, 210}, {{27, 67, 64, 235, 128, 0, 194, 160, 77, 35, 109, 115, 2, 15, 173, 73}, 210}, {{27, 67, 64, 235, 128, 0, 0, 26, 104, 223, 15, 210, 236, 84, 25, 173}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 213, 107, 116, 125, 39}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 232, 29, 42, 208}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 210}, {{27, 67, 64, 235, 128, 93, 200, 251, 108, 203, 10, 216, 147, 44, 156, 162}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 109, 70, 118, 62, 211}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 252, 14, 182, 189, 226}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 176, 18, 171, 230, 197, 227}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 63, 73, 40, 184, 245, 124}, 210}, {{27, 67, 64, 235, 128, 57, 53, 209, 107, 152, 244, 255, 246, 55, 184, 19}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 63, 195, 238, 251, 17, 203}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 129, 55, 70, 82, 74, 193}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 78}, 210}, {{27, 67, 64, 235, 128, 0, 221, 186, 182, 155, 44, 218, 145, 237, 54, 232}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 11, 161, 156, 110}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 232}, 210}, {{27, 67, 64, 235, 128, 0, 238, 117, 56, 221, 97, 46, 249, 232, 245, 58}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 40}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 223, 86, 128}, 210}, {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 46, 121, 41, 119, 88}, 210}, {{27, 67, 64, 235, 128, 0, 133, 215, 91, 225, 168, 61, 126, 191, 28, 75}, 210}, {{27, 67, 64, 235, 128, 0, 214, 222, 47, 216, 80, 17, 7, 22, 70, 101}, 210}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 143, 177}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 14, 94}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 27, 94}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 44}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 52, 118}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 222}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 250}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 152}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 70, 2, 30}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 46, 153}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 21, 103}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 174}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 105}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 22, 155, 243}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 19, 4, 201}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 61, 188, 6}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 65, 54}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 182, 72}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 228, 127, 3}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 161, 222, 212}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 84, 57}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 38, 231}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 115, 201, 232}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 220, 133}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 40, 164, 150}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 241, 47, 89}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 189, 233}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 69, 214}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 87, 128, 155}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 207, 73}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 96, 49, 127}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 72, 38, 169}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 175, 251, 116}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 252}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 161}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 138, 248, 159}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 46}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 7, 133, 89}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 157, 2, 21}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 182, 126, 158}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 160, 246}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 56}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 120, 77}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 139}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 140, 112}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 239, 101}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 241, 212}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 190, 214}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 246, 237}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 233, 149}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 130}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 43}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 114, 134, 54}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 215, 49}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 228, 16}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 190, 94, 37}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 210, 74}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 146}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 82, 118}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 203}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 118, 180, 141}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 30, 168, 95}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 204, 96}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 27, 181, 75}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 151}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 231, 13, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 214, 166, 125}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 199, 110}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 90}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 128, 49, 36}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 29}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 55, 94}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 150}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 228, 42, 118}, 61}, {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 197, 143, 31}, 61}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 249}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 65, 22, 205, 193, 161, 153, 59, 231}, 120}, {{34, 192, 0, 177, 163, 136, 90, 227, 4, 157, 179, 64, 78, 37, 155, 227}, 120}, {{34, 192, 0, 0, 0, 44, 159, 76, 55, 222, 163, 156, 13, 166, 214, 180}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 187, 37, 240, 113, 90, 79, 67, 130}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 243, 179, 135}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 165, 20, 12, 136}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 50, 85, 70, 154}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 166}, 120}, {{34, 192, 0, 44, 101, 200, 243, 95, 97, 48, 123, 56, 202, 151, 118, 81}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 120}, {{34, 192, 0, 0, 0, 0, 0, 101, 203, 247, 126, 126, 235, 185, 35, 138}, 120}, {{34, 192, 0, 0, 22, 190, 147, 88, 85, 123, 167, 136, 31, 227, 249, 200}, 120}, {{34, 192, 0, 0, 0, 0, 0, 14, 225, 108, 188, 171, 214, 173, 21, 146}, 120}, {{34, 192, 0, 0, 0, 128, 92, 242, 83, 93, 12, 6, 175, 34, 141, 126}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 143}, 120}, {{34, 192, 0, 0, 0, 0, 0, 240, 154, 185, 129, 116, 149, 198, 243, 33}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 54, 52, 199, 67, 254, 45, 10}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 216}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 213, 6, 124, 180}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 141, 178, 81, 35, 239, 248}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 176, 104, 89}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 41, 113, 195, 104}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 241}, 120}, {{34, 192, 0, 0, 0, 0, 0, 20, 33, 165, 68, 204, 121, 44, 216, 191}, 120}, {{34, 192, 0, 0, 0, 0, 91, 93, 4, 228, 242, 253, 63, 2, 1, 205}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 146, 124, 113, 160}, 120}, {{34, 192, 0, 0, 0, 0, 0, 148, 246, 202, 96, 221, 88, 145, 132, 253}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 59, 125}, 120}, {{34, 192, 0, 0, 0, 73, 54, 230, 182, 9, 165, 56, 101, 193, 231, 240}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 203, 106, 90, 8}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 74, 232, 142, 96, 187, 202, 67}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 34, 147, 200}, 120}, {{34, 192, 0, 0, 0, 0, 171, 38, 199, 160, 52, 96, 207, 220, 58, 21}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 17, 149, 73, 134}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 16, 109, 116, 14}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 120}, {{34, 192, 38, 227, 131, 115, 239, 51, 86, 148, 23, 96, 60, 229, 177, 184}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 177, 189, 98, 24}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 194, 8, 26}, 120}, {{34, 192, 99, 200, 87, 153, 114, 61, 177, 195, 91, 32, 204, 146, 188, 72}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 208, 84, 68, 129}, 120}, {{34, 192, 0, 0, 0, 0, 29, 223, 248, 192, 36, 186, 136, 207, 65, 41}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 199, 152, 180, 191, 21, 30, 133, 89}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 120}, {{34, 192, 0, 0, 0, 0, 0, 155, 9, 12, 113, 11, 242, 60, 156, 114}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 86}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 151, 176, 241}, 120}, {{34, 192, 0, 0, 218, 218, 188, 186, 247, 120, 162, 67, 47, 205, 221, 127}, 120}, {{34, 192, 0, 0, 0, 135, 199, 54, 182, 41, 107, 101, 143, 34, 250, 75}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 50, 81, 254}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 84, 37, 99, 223}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 126, 245, 62}, 120}, {{34, 192, 0, 0, 0, 0, 0, 242, 130, 16, 128, 73, 247, 5, 129, 230}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 235, 20, 174, 23, 84, 113}, 120}, {{34, 192, 0, 0, 0, 0, 0, 107, 140, 156, 140, 185, 212, 225, 224, 39}, 120}, {{34, 192, 0, 251, 147, 181, 13, 100, 45, 175, 181, 27, 164, 229, 81, 7}, 120}, {{34, 192, 69, 17, 9, 58, 58, 115, 63, 219, 244, 143, 168, 50, 158, 235}, 120}, {{34, 192, 0, 0, 0, 0, 0, 31, 36, 193, 240, 12, 108, 21, 83, 117}, 120}, {{34, 192, 0, 0, 0, 104, 251, 189, 69, 39, 219, 252, 14, 245, 73, 31}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 220}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 129, 196, 57, 22, 6, 241, 176}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 122, 74, 146}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 70, 216, 90, 38, 34, 45, 239, 98, 149, 165, 39, 188}, 120}, {{34, 192, 242, 201, 249, 250, 137, 139, 119, 233, 189, 207, 27, 177, 72, 42}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 226, 205, 207}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 234, 30, 153, 185, 230, 217, 26}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 234, 239, 134, 242, 190, 24, 154, 32}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 6}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 21, 98, 95, 46, 48, 81, 203, 106}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 88, 200, 120, 239, 72, 51, 132, 223}, 120}, {{34, 192, 0, 0, 0, 0, 222, 221, 17, 43, 13, 81, 171, 79, 78, 181}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 130, 247, 77, 1, 211, 64}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 137, 119}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 144, 226}, 120}, {{34, 192, 9, 100, 77, 9, 81, 30, 0, 17, 205, 28, 233, 123, 62, 135}, 120}, {{34, 192, 0, 0, 0, 0, 0, 176, 196, 60, 7, 85, 233, 15, 84, 109}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 12, 205, 213, 171, 37, 123}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 243, 192, 44, 58, 144, 109, 165, 197}, 120}, {{34, 192, 0, 0, 0, 0, 94, 158, 237, 240, 27, 93, 95, 137, 137, 114}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 97, 172, 98, 140, 47, 158, 74}, 120}, {{34, 192, 0, 0, 0, 167, 214, 144, 127, 164, 81, 9, 152, 218, 148, 117}, 120}, {{34, 192, 0, 0, 0, 0, 24, 236, 42, 5, 216, 74, 145, 57, 73, 233}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 71}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 164, 230, 236, 233}, 120}, {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 115, 21}, 120}, {{34, 192, 0, 0, 0, 0, 179, 123, 176, 177, 33, 152, 218, 230, 47, 185}, 120}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 19, 103, 90, 147, 229, 247}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 89, 181, 18, 131, 77, 7, 151}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 94}, {{215, 141, 95, 192, 189, 62, 0, 83, 131, 177, 245, 75, 244, 149, 212, 2}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 245, 150, 119, 81, 50}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 216, 128, 164, 213, 38, 15, 210, 114, 41}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 104, 232, 131, 140, 131}, 94}, {{215, 141, 95, 192, 189, 62, 0, 139, 237, 119, 165, 80, 66, 212, 243, 249}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 221, 40, 255, 86, 235, 238, 2}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 199, 188, 226, 216}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 35, 225, 233, 65, 110, 17}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 16, 221, 3, 168, 118, 103, 4, 145}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 239, 255}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 241, 158, 116, 128, 253, 228, 229, 15}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 18, 119}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 16, 199, 18, 186}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 177, 75, 70, 224, 193, 160, 170}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 177, 216, 65, 199, 50, 189}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 76, 242}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 83, 115, 67, 166, 22}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 76, 1, 5, 169, 58, 242, 23}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 152, 201, 109, 167, 197, 164, 8, 221}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 22, 74, 18, 42}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 13, 87, 186, 161, 42}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 33, 12, 79, 43, 229, 19, 240}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 174, 183}, 94}, {{215, 141, 95, 192, 189, 62, 80, 152, 106, 120, 212, 212, 250, 153, 112, 125}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 81, 209, 232, 143, 13, 85, 224, 170}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 76, 13, 211, 31, 156, 197, 225, 2}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 213, 120, 118, 213, 47, 253}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 164, 216, 245, 56, 195, 216}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 117, 47}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 105, 86, 157, 108, 59, 188}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 193, 140}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 118, 60, 194, 222, 252}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 181, 139, 206, 116}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 34, 145, 250}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 143, 47, 178, 239, 131, 174, 134}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 144, 15}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 221, 17, 52}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 77, 135, 151, 114, 191}, 94}, {{215, 141, 95, 192, 189, 62, 0, 245, 49, 133, 127, 58, 103, 20, 229, 62}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 232, 181, 111, 176}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 122, 33, 16, 238, 61}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 90, 71, 4, 160, 151}, 94}, {{215, 141, 95, 192, 189, 62, 0, 155, 218, 64, 49, 77, 227, 49, 205, 139}, 94}, {{215, 141, 95, 192, 189, 62, 0, 178, 35, 133, 230, 171, 239, 160, 174, 187}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 255, 125, 239, 219, 179}, 94}, {{215, 141, 95, 192, 189, 62, 0, 186, 208, 177, 105, 115, 70, 252, 210, 68}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 138, 205}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 231, 172, 168}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 9, 61, 170, 124, 211}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 5, 75, 162, 147, 46}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 239, 31, 11, 208}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 120, 183, 158}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 238, 229, 213, 236, 10, 57, 68, 132}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 66, 246, 180, 27, 19}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 118, 214, 202, 60, 158}, 94}, {{215, 141, 95, 192, 189, 62, 0, 145, 212, 214, 112, 61, 19, 141, 52, 227}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 255, 229, 194, 165, 67}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 101, 160, 187}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 130, 6}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 91, 195, 59, 64, 142, 88}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 45, 247, 72, 227}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 192, 216, 105, 125, 88, 62, 54}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 203, 126, 143, 45, 136, 150, 142}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 208, 56, 237, 57, 127, 6}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 188, 19, 109, 253, 123, 4, 207, 7}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 181, 255, 206}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 29, 140, 2, 30, 142}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 86, 12, 205}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 163, 29, 110, 45, 90}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 85, 198, 244}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 111, 203, 0, 2, 109, 68, 145, 244}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 203, 27, 187, 180, 38, 235, 75, 219}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 238, 106, 100, 26, 121, 151, 187, 208}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 191, 67, 96}, 94}, {{215, 141, 95, 192, 189, 62, 0, 190, 52, 31, 229, 249, 193, 213, 29, 42}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 118, 40, 200, 207, 104}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 99, 242, 244, 100, 162}, 94}, {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 94}, {{215, 141, 95, 192, 189, 62, 0, 107, 170, 3, 54, 121, 246, 95, 56, 208}, 94}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 4, 30}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 17, 162}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 193, 19, 201, 103}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 113, 185, 235}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 219, 29, 110, 245}, 153}, {{31, 181, 56, 141, 120, 128, 0, 255, 84, 106, 105, 194, 74, 23, 167, 54}, 153}, {{31, 181, 56, 141, 120, 128, 0, 144, 154, 93, 204, 105, 133, 173, 234, 92}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 109, 132, 222, 10, 141, 104}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 159, 51, 143, 50, 61, 167, 189}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 187, 237, 36}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 91, 224, 13, 109, 153, 129, 22}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 209, 106, 20}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 11, 221, 167}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 144, 163, 10, 95, 245, 218, 151, 2, 115, 247}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 84, 138, 187, 94, 240, 108, 136}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 15, 248, 58, 178, 192, 10}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 140, 225, 87, 37, 50, 221, 160, 187}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 106, 249, 226, 225, 98, 160, 248}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 146, 29, 62, 107, 127, 14, 176, 203}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 52, 150, 180, 60, 207}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 134, 49, 92, 40, 58}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 224, 129, 114, 253, 169, 66, 249}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 197, 108, 175, 202, 244}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 215, 177}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 131, 86, 31, 68, 109, 166, 39, 14}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 52, 206, 144}, 153}, {{31, 181, 56, 141, 120, 128, 125, 89, 68, 209, 58, 201, 199, 54, 1, 118}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 98, 24, 18}, 153}, {{31, 181, 56, 141, 120, 128, 0, 112, 222, 0, 117, 228, 15, 218, 240, 33}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 187, 166, 216, 251, 220, 170}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 152, 204}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 113, 19}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 181, 163}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 255, 189, 97, 212, 7}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 221, 153, 170, 162, 224, 63}, 153}, {{31, 181, 56, 141, 120, 128, 160, 108, 68, 37, 143, 168, 149, 167, 193, 120}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 9, 175, 143, 92, 67, 210}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 140, 123}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 198, 220}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 122, 59, 226}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 97, 31}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 87, 41, 96, 145, 199}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 45, 193, 147, 200, 245, 33, 176, 196}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 54, 43, 152}, 153}, {{31, 181, 56, 141, 120, 128, 0, 64, 108, 126, 249, 184, 13, 152, 133, 8}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 116, 121, 188, 51, 23, 82, 156}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 252, 180, 78, 169}, 153}, {{31, 181, 56, 141, 120, 128, 0, 160, 35, 162, 5, 89, 202, 99, 36, 84}, 153}, {{31, 181, 56, 141, 120, 128, 115, 49, 70, 19, 12, 13, 177, 43, 178, 191}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 110, 218, 30, 120, 148, 13, 192, 24, 90, 47}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 159, 59, 94, 219}, 153}, {{31, 181, 56, 141, 120, 128, 0, 229, 243, 53, 94, 50, 40, 118, 235, 188}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 20, 164, 185, 163, 35, 6, 65, 112}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 132, 212, 128}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 22, 76, 105, 243, 40, 60, 229}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 163, 34, 141, 34, 98, 57, 204, 163}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 236, 168}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 110, 172}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 190, 126, 231, 71, 155, 62}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 227, 186, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 205, 107, 130, 119, 61}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 10, 52, 246, 53}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 236, 202, 249, 141, 170, 178}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 33, 36, 17, 217, 99, 143, 102, 16}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 247, 178, 186}, 153}, {{31, 181, 56, 141, 120, 128, 0, 221, 31, 172, 141, 175, 22, 208, 202, 255}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 140, 119, 77, 208, 88, 214, 56}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 108, 18, 82, 2, 76, 46, 123, 227}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 153}, {{31, 181, 56, 141, 120, 128, 0, 237, 137, 27, 221, 138, 116, 116, 181, 68}, 153}, {{31, 181, 56, 141, 120, 128, 40, 34, 169, 167, 12, 62, 99, 7, 224, 15}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 14, 238, 198, 9, 228}, 153}, {{31, 181, 56, 141, 120, 128, 0, 241, 53, 129, 135, 201, 245, 167, 135, 57}, 153}, {{31, 181, 56, 141, 120, 128, 240, 83, 136, 171, 113, 146, 62, 127, 150, 194}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 141, 242}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 170, 187, 233, 102, 173}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 114, 215, 244}, 153}, {{31, 181, 56, 141, 120, 128, 145, 53, 68, 181, 223, 210, 234, 178, 128, 236}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 139, 152, 227, 231, 242, 25, 43, 68}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 137, 184, 215, 201}, 153}, {{31, 181, 56, 141, 120, 128, 0, 0, 0, 66, 207, 192, 210, 207, 1, 250}, 153}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 40, 127, 15, 197, 198, 80, 87}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 109, 242, 222, 127, 118, 92, 118}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 227, 117, 204, 104, 136}, 221}, {{153, 73, 128, 0, 10, 212, 117, 252, 244, 31, 121, 8, 113, 125, 235, 12}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 210, 247, 153}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 30, 251, 20, 110, 5, 20, 39, 107}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 238, 199, 205, 103, 112, 165, 165}, 221}, {{153, 73, 128, 111, 172, 83, 53, 247, 101, 241, 202, 39, 165, 251, 54, 98}, 221}, {{153, 73, 128, 0, 0, 0, 0, 21, 51, 231, 189, 195, 134, 222, 40, 44}, 221}, {{153, 73, 128, 0, 48, 239, 213, 142, 82, 86, 14, 94, 157, 225, 146, 255}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 215}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 220, 46, 188, 146, 179, 194, 162}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 9, 80, 16, 105, 58, 96, 99, 138}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 104, 100, 20}, 221}, {{153, 73, 128, 0, 40, 76, 144, 118, 103, 111, 122, 156, 44, 111, 25, 94}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 9, 252, 109, 25, 255}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 239, 92, 73, 208, 212, 4, 175}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 175, 228, 212, 215, 251}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 243}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 228, 106, 25, 85, 65, 99, 74, 93}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 182, 37, 233, 62, 235, 114}, 221}, {{153, 73, 128, 0, 0, 149, 158, 176, 139, 148, 126, 142, 94, 126, 13, 126}, 221}, {{153, 73, 128, 0, 0, 0, 0, 183, 37, 127, 134, 105, 2, 182, 254, 151}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 184}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 149, 209, 59, 170, 96}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 249, 249}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 206, 145, 103, 146, 251}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 139}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 178, 44, 198, 56, 93, 197, 14}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 104, 26, 203, 80, 108, 174, 208}, 221}, {{153, 73, 128, 68, 159, 150, 172, 150, 4, 222, 44, 124, 121, 221, 127, 217}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 196, 40, 40}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 90, 39, 239, 29, 3, 105, 110}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 146, 223}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 124, 62, 157}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 180, 82, 75}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 206}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 19, 190}, 221}, {{153, 73, 128, 0, 0, 0, 205, 140, 212, 47, 175, 71, 11, 189, 110, 86}, 221}, {{153, 73, 128, 0, 20, 62, 79, 221, 183, 43, 58, 160, 70, 90, 155, 125}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 24}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 215, 8}, 221}, {{153, 73, 128, 0, 0, 246, 74, 138, 219, 78, 164, 55, 239, 47, 229, 19}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 179, 27, 212}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 20, 116, 114}, 221}, {{153, 73, 128, 0, 0, 13, 203, 108, 104, 224, 194, 73, 163, 7, 136, 6}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 189, 98, 232, 51, 224, 213, 100, 246}, 221}, {{153, 73, 128, 0, 165, 249, 20, 184, 156, 78, 180, 248, 144, 106, 158, 3}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 108}, 221}, {{153, 73, 128, 0, 105, 227, 82, 154, 84, 120, 86, 72, 195, 64, 6, 62}, 221}, {{153, 73, 128, 0, 0, 233, 220, 137, 157, 149, 173, 22, 2, 191, 164, 200}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 224, 135}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 252, 110}, 221}, {{153, 73, 128, 0, 0, 0, 234, 251, 114, 106, 79, 216, 174, 130, 93, 120}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 30, 220, 225}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 35, 201, 176, 180, 196, 171}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 63, 160, 38, 30, 192, 157, 36, 101}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 108, 133, 124, 4, 8, 150}, 221}, {{153, 73, 128, 40, 176, 227, 252, 69, 88, 221, 225, 109, 101, 202, 94, 198}, 221}, {{153, 73, 128, 0, 0, 250, 207, 91, 31, 37, 82, 68, 145, 93, 179, 211}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 206, 140, 78, 136, 138, 190}, 221}, {{153, 73, 128, 0, 0, 0, 108, 93, 41, 226, 251, 56, 26, 219, 247, 179}, 221}, {{153, 73, 128, 0, 0, 0, 0, 164, 113, 183, 230, 140, 124, 240, 225, 121}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 42}, 221}, {{153, 73, 128, 0, 121, 148, 41, 145, 132, 45, 69, 158, 136, 148, 151, 209}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 171, 122}, 221}, {{153, 73, 128, 0, 225, 122, 218, 122, 14, 51, 171, 39, 206, 245, 101, 79}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 20, 65, 165, 169, 102, 198}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 92, 27, 83}, 221}, {{153, 73, 128, 0, 0, 0, 115, 18, 116, 122, 88, 180, 213, 102, 0, 140}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 54, 201, 120, 55, 30, 95, 25, 252}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 61}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 182, 188, 106, 144, 126}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 61, 19, 177, 20, 21, 17, 150}, 221}, {{153, 73, 128, 0, 0, 142, 167, 94, 91, 62, 3, 108, 149, 103, 40, 77}, 221}, {{153, 73, 128, 0, 0, 0, 0, 134, 31, 174, 38, 44, 57, 196, 16, 121}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 12}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 249}, 221}, {{153, 73, 128, 0, 0, 0, 206, 34, 83, 208, 249, 43, 108, 25, 18, 65}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 29, 1}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 148}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 119, 5}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 180, 214, 113, 198, 105, 154, 70}, 221}, {{153, 73, 128, 0, 162, 213, 22, 197, 211, 253, 164, 194, 23, 132, 15, 231}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 151, 143, 221, 228, 107, 36, 41}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 252, 231, 198, 224, 75, 108, 58, 165}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{153, 73, 128, 0, 0, 0, 0, 0, 203, 150, 243, 50, 140, 143, 53, 194}, 221}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 252, 31, 132, 72}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 142, 206, 82, 67, 122}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 195, 30, 170}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 177, 4}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 188, 100, 143}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 89, 127, 204, 93}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 61, 122}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 122, 230, 119, 88}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 50, 36, 111, 47}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 14, 216, 134, 167}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 1}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 48, 68}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 60}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 242}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 91, 212, 20}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 98, 89}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 220, 136, 208, 254}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 242, 189, 225}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 136, 212, 151, 93}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 1, 5}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 190, 200, 89, 75}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 51, 40, 112}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 25, 28}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 153, 178}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 206, 215}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 128, 123}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 212, 177, 88}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 219, 131, 66}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 202, 44}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 131, 17, 159, 195}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 249}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 58, 220, 111, 69}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 71, 232, 219}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 38}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 87, 188}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 97, 116}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 217, 182, 41}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 159, 169}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 14}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 184, 103, 43, 249}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 69, 139, 30}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 205}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 26, 137}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 14, 138, 199, 79}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 36, 129, 212}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 225, 65}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 36}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 97, 18, 29, 92, 108}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 233}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 2, 5, 244, 253}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 117}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 193, 24}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 69, 16, 236, 224}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 193, 96}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 140}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 3, 172, 229, 235, 67}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 194}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 17, 181, 160}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 252}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 63, 204, 174, 55}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 253, 136, 83, 180}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 139, 216}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 46, 123}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 105, 153, 237, 114}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 154}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 251, 10, 234}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 133, 31, 94, 63}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 16, 56, 160, 186}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 253, 137, 178}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 151, 142}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 64, 47, 100, 177}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 158, 18, 200, 156}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 184, 97, 54}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 11, 103, 236}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 117}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 230, 168, 28, 246, 82}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 99}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 159, 35, 133}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 174, 100}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 122, 141}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 73}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 124}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 163}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 64, 82}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 9, 205}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 158, 221}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 88}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 62}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 227, 183}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 50}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 191}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 254, 193}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 162}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 147}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 210, 92}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 122}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 132, 79}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 86, 131}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 151}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 140, 161}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 16, 217}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 132, 140}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 18}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 212, 102}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 255, 88}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 158}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 93}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 250, 35}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 111}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 135, 74}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 164}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 128, 173}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 82}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 84}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 207, 13}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 164}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 6, 77}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 45}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 241, 135}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 32, 47}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 115, 79}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 173}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 23}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 101, 176}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 32, 162}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 178}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 18}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 230}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 85}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 84, 32}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 171}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 135}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 213, 17}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 47}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 71}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 112, 95}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 101}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 2}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 31, 123}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 167, 41}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 190, 48}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 228, 148}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 35, 201}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 70, 189}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 225}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 248}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 152}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 67}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 90}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 111}, 188}, {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 91, 47}, 188}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 15}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 163}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 22, 72, 93}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 251, 153, 219, 253, 249, 79, 140}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 146}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 142, 139, 62, 245}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 251, 43, 127}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 244, 94}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 183, 220, 116, 72, 107, 163}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 224, 236, 132, 91}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 81, 244, 245, 70}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 218, 77, 210, 174, 156, 52, 160}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 170, 160, 194, 57, 85, 6, 50}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 153, 166, 245, 213, 216, 139, 158}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 35, 123, 65, 201, 178, 83, 189}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 162}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 55, 37, 100}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 214, 233, 188, 111, 23, 199, 138}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 208, 114, 126, 235, 238, 206, 79}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 212, 52, 223}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 84, 138, 151, 107, 88}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 236, 54, 72, 242}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 245, 252, 201, 137, 123}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 103, 99, 208, 118, 180, 212, 124}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 87, 234, 132, 211, 71}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 145, 157, 255, 197, 7}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 151, 5, 192}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 161, 47, 5, 253, 42}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 121}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 101, 25, 217}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 90, 170, 214, 77, 175}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 234, 172, 134, 144, 25, 106, 78, 56}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 111, 89, 134, 59, 241}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 210, 181, 113, 67, 42, 76}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 255, 145, 233}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 130, 108, 228, 75}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 58, 167}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 199, 28, 66, 207, 215, 214}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 2, 63, 153, 197}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 26, 4, 5, 155, 161, 50, 123}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 144, 231, 128, 251}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 129, 38, 159}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 72, 108, 172}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 129, 94, 209, 85}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 73, 138}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 187, 198, 211}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 250, 111, 4, 50, 184, 197}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 99, 113, 224, 158, 102}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 7, 235, 204}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 126, 188}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 221, 120, 240, 24, 183, 183, 129}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 189, 83, 170, 119}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 227, 180, 77, 3, 98, 252}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 175, 159, 88, 154, 3, 51}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 166, 160, 7}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 220, 231, 233, 202}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 152, 104}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 15, 114, 125}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 197, 74, 132, 87, 54}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 118, 107, 80}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 173}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 131, 1}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 229, 137, 129, 116, 4, 249, 122, 169}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 240, 228, 100, 191}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 159, 106, 151, 84, 222}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 33}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 245, 32, 155}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 202, 26, 98, 219}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 185}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 249, 238, 215, 62, 17, 254, 214}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 217, 93, 189, 36, 239, 136}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 178, 10}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 155, 233, 112, 23, 128}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 158, 125}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 243, 190, 148, 116}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 28}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 171, 191, 35, 94}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 99, 78}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 186, 235, 163, 254}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 49, 76}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 211}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 204, 212, 82, 91, 115, 89, 193}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 71, 210, 54, 138, 26, 135, 93}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 132, 213, 198}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 179}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 195, 221}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 5, 244, 57}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 212}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 74, 13, 76, 91, 89}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 134, 76, 18, 167, 163, 58, 202}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 11, 152, 183}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 186, 109, 60}, 28}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 142, 167, 68, 96}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 104}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 228, 36, 77, 28, 24}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 16, 89, 167, 126, 91}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 119}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 97, 188, 48, 1}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 226, 3, 112, 144}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 206, 51, 230, 80}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 194, 161}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 207, 165, 124, 146, 245}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 219}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 186}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 111, 138, 73, 236, 199}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 27}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 129, 146, 207, 96, 245}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 254, 5}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 154, 140}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 228, 234}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 40, 243, 240, 251, 71}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 155, 110, 146}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 52}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 6, 197, 40, 214}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 58}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 147, 90, 201}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 9, 92, 200, 225}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 65, 149, 198}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 130}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 99}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 165, 39, 77, 46}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 45, 143}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 38, 86, 188, 112, 36}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 90, 105}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 141}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 71}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 120, 32, 138, 180, 19}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 71}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 230, 135, 112}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 165}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 211, 129, 8, 57}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 236, 167, 100, 29}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 169, 155, 247, 168}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 136}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 195, 58, 165, 126}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 75}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 3, 107, 148, 94}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 253, 63}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 19, 131, 250}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 106, 205, 13, 232}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 213, 208, 39}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 87, 135, 107, 57}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 26, 14, 12}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 112, 161}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 57, 150}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 78}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 239, 63, 176}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 103, 186, 149, 60}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 40, 251, 103}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 154, 36, 178, 30}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 57, 108}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 173, 195, 213}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 48, 240, 37, 241}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 112}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 105}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 32}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 183, 139, 50, 106}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 215}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 178}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 75}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 101, 107, 76, 105}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 120, 120}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 74, 89}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 98, 153}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 108}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 29, 247}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 152, 16, 224, 43, 22}, 240}, {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 240}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 7}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 31, 216}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 165, 144, 62}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 87, 1, 83, 104}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 46, 253}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 177, 50, 106, 174}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 75, 125}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 41, 17, 238}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 154, 100}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 101, 168}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 255, 208}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 172, 165, 159, 184}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 210, 221, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 213, 193, 156, 110}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 18, 102}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 253, 145, 224}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 33, 184, 232, 119}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 82, 16}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 158, 19}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 127, 14}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 28}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 233}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 29}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 215, 59}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 116, 218, 232}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 208, 158, 9, 98}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 136, 49, 89}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 131, 48, 46, 157}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 215}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 230, 99, 134}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 177, 164, 225, 159}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 16}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 134, 82, 205}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 2}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 61, 170, 83}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 198}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 99, 79, 220, 156}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 33, 234}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 193, 154, 231}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 63}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 108, 191}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 33}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 196, 59}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 35}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 120, 22}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 132}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 223, 148, 178}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 131, 68}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 222}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 172, 142}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 176}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 9}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 187}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 205, 253}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 24, 91}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 115}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 15, 217, 233}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 33}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 206, 145, 45}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 252, 4, 58}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 55}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 175, 179, 174}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 252}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 134, 107, 196}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 116}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 106, 44}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 79, 62}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 23}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 34}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 163}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 29, 17}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 208, 144, 132}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 158}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 30, 101, 31}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 195}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 254, 6, 133}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 242, 28, 55}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 84}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 105, 61}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 59}, {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 139}, 59}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 111, 184}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 75, 58, 238, 174}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 34, 143}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 63, 50, 163}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 90, 182, 188, 19}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 227}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 56, 216}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 229, 26, 131}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 12, 28, 167, 249}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 220, 240, 168}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 114}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 17, 79, 186, 192}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 118, 171, 173}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 148, 139, 30}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 242, 239, 164}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 89, 161, 60, 62}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 52, 33}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 100}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 35, 114, 102}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 23, 157, 214, 120}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 152, 124, 216}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 34}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 184, 165}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 225}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 120, 166}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 106, 88, 242, 147}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 91}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 62, 136}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 231, 161, 123}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 221, 12, 244}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 83, 253, 252, 128}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 171, 22, 255}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 255, 49, 221}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 18, 240}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 112, 209, 217}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 209, 64}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 71, 50, 1, 253}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 203}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 123}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 202}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 223}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 32, 181, 5, 11}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 100}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 187, 197, 6, 10}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 255, 42}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 179}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 56, 26, 155, 4}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 215, 179}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 230, 126}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 2, 194, 125}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 59}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 220, 238}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 217, 93, 45, 161}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 80, 33, 51, 84}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 198}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 175, 90}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 80, 255, 174}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 164, 220, 177, 196}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 110, 7, 129}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 114, 22, 114}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 189}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 190}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 248, 118, 30}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 200, 240}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 194}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 97, 157}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 61, 75}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 144, 52}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 85, 75, 81}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 46, 14}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 216, 44, 202, 23}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 19, 235, 49}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 200, 92, 49, 53}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 97, 112, 85, 249}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 69, 82, 237, 156}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 226, 177, 104, 201}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 209, 43, 69, 2}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 144, 126}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 228, 98}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 80, 57}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 195}, {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 9}, 195}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 193, 145, 246, 45, 142, 150}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 143, 15, 226, 129}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 148}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 127, 18, 42, 231, 49}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 111, 240, 179, 168, 1, 199, 155}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 108, 205, 230}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 63, 242, 220, 89, 65}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 248, 93, 55, 150}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 14, 239, 151, 3, 90, 107, 244}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 41, 79, 80}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 249, 117, 14}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 176, 183, 220, 117, 236, 19}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 248, 188, 106, 219, 212, 96}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 222}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 206, 92, 15, 141, 213}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 148, 92, 126}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 230, 227, 199}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 197, 226, 100, 187}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 249, 40, 227, 244}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 28, 222, 153, 117, 95, 90, 247}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 226, 93, 59, 73, 35, 211}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 250, 219, 28, 88}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 106, 12, 168, 180, 4, 171}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 206, 38, 124, 215}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 55, 106, 194, 5}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 195, 147, 224, 214}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 211, 235, 79, 164}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 227, 214}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 217, 87, 102, 49, 151}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 173, 233, 12}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 39, 86, 226, 160, 187, 105, 28}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 55, 45, 123}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 53, 159, 210}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 97, 78, 240, 235, 208, 89, 25}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 102, 41, 160}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 59, 88, 157, 33, 217, 30}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 228, 31, 220, 148}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 142, 250}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 185, 234, 187, 174, 107}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 171, 20, 84, 139, 77}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 10, 61, 84, 96, 30}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 158, 140, 117, 168, 182, 210, 232}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 172, 147}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 33, 214, 165}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 178}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 141, 226, 105, 108, 38, 9, 107}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 193, 28, 168, 61, 67, 76}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 94, 90}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 174}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 121, 44, 24, 195, 64, 51, 233}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 213, 99, 75}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 2, 29, 218, 186, 87}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 70, 208, 127}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 242, 181, 222, 216, 197, 114}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 197, 172, 123, 186, 228, 111}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 93, 190, 210, 54}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 144, 119, 242, 57, 4}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 164}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 157, 193}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 171, 132, 140}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 143, 36, 239, 93, 174, 208}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 220, 145}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 211, 200, 197, 203, 153}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 152, 211, 45, 14, 203, 137}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 224, 245, 39}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 103, 66, 25, 235}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 156, 253}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 57, 213, 227}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 111, 204, 59}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 253, 94, 105, 53, 106, 253, 14}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 24, 217, 79, 184}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 247, 241, 111}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 161, 178, 131, 182}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 138, 8, 170, 163, 61, 163}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 161, 173, 20, 146}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 107, 60, 28, 195, 70, 93, 149}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 128, 98, 100, 8, 185, 133, 154}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 100, 230, 93, 37, 84}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 250, 105, 184, 111, 156, 191}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 72, 14, 107, 192, 219, 213}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 36, 168, 41}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 249, 75}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 144, 93, 59, 245, 88}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 80, 89}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 138, 23, 234, 53, 196}, 10}, {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 10}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 141, 140}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 128, 175, 138}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 17, 32, 176}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 155}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 39, 106, 227}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 38, 202, 80}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 149}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 214}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 119, 3, 86, 243}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 94, 107}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 38, 179, 191, 227}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 179, 158, 148}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 81}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 35, 186, 214, 169}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 89, 164, 147, 46}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 220, 31}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 213, 63, 240, 247}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 124, 79, 30}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 207, 79, 59, 64}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 176, 109, 242}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 209, 241, 138}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 237, 108, 209, 2}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 149, 58}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 36, 127}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 71, 102}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 223}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 186, 89, 218}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 223, 89, 140, 243}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 64}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 159, 121}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 124, 9, 184, 29}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 92, 243}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 173, 157}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 174, 78}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 71}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 120, 108}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 41, 254, 83}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 63, 177, 135}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 147, 89, 181}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 57}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 94}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 66, 151, 202, 190}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 192, 216, 173}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 95, 180, 133}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 222}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 64, 70, 65}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 183, 59, 70}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 160}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 192, 155, 102, 208}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 168, 56, 13}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 236, 104}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 128, 8, 78, 21}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 34, 155, 120}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 229, 120}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 94, 174, 200}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 43}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 48, 28}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 229, 114}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 72, 45}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 67, 73, 194}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 22, 235, 159}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 84}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 129, 186, 101, 145}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 11, 100}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 231, 148, 147}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 41, 98}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 34, 177}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 175, 220, 252}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 128, 42, 19, 60}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 80, 23}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 243, 76, 99}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 252}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 88, 238}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 34, 250}, 206}, {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 144, 214, 30}, 206}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 255}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 124, 101, 207, 199}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 12, 233, 85, 154, 204, 13}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 117, 65}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 48, 130, 105, 49}, 61}, {{0, 0, 0, 114, 140, 201, 116, 122, 158, 70, 136, 193, 156, 81, 229, 185}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 30, 67, 83}, 61}, {{0, 0, 0, 0, 0, 160, 163, 245, 22, 211, 158, 202, 22, 157, 176, 166}, 61}, {{0, 0, 0, 0, 252, 108, 68, 173, 199, 166, 43, 163, 228, 0, 53, 166}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 118}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 153, 85, 125, 7}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 62, 55}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 122, 94, 117, 89, 158, 49}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 95, 147, 175, 67, 66, 129, 245, 136, 110}, 61}, {{0, 0, 0, 0, 0, 0, 244, 28, 242, 27, 235, 91, 81, 115, 3, 147}, 61}, {{0, 0, 0, 0, 0, 0, 0, 125, 189, 209, 76, 234, 97, 254, 18, 68}, 61}, {{0, 173, 242, 202, 12, 65, 85, 160, 121, 198, 14, 75, 241, 38, 147, 150}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 61}, {{0, 0, 0, 0, 0, 2, 80, 215, 165, 150, 99, 153, 246, 67, 124, 7}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 198, 218, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 69, 156, 206, 0, 149, 111, 65, 9}, 61}, {{0, 0, 0, 0, 0, 0, 0, 171, 211, 26, 215, 21, 48, 130, 16, 155}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 129, 198, 248, 224, 83, 153, 126, 184}, 61}, {{0, 0, 0, 2, 153, 124, 225, 165, 1, 252, 30, 56, 66, 118, 8, 105}, 61}, {{0, 0, 0, 0, 0, 0, 49, 108, 154, 125, 4, 167, 103, 206, 129, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 32, 232, 45, 178, 60, 230}, 61}, {{0, 0, 222, 150, 124, 81, 189, 200, 40, 245, 108, 158, 6, 166, 140, 62}, 61}, {{0, 0, 0, 246, 78, 85, 157, 19, 84, 179, 76, 113, 39, 221, 62, 199}, 61}, {{0, 0, 0, 172, 44, 199, 12, 181, 230, 20, 182, 209, 49, 244, 110, 24}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 135}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 89, 11}, 61}, {{0, 0, 0, 0, 0, 0, 0, 212, 239, 89, 191, 67, 17, 244, 162, 225}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 253, 28, 167, 96, 87}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 200, 203, 23}, 61}, {{0, 0, 144, 101, 70, 50, 78, 237, 163, 4, 245, 177, 179, 240, 109, 80}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 89, 253, 107, 25, 250}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 112, 4, 79, 178}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 15, 72}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 80, 85, 82}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 131, 225}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 92, 114, 161, 33, 184}, 61}, {{0, 0, 0, 0, 0, 0, 0, 210, 143, 4, 37, 240, 240, 108, 184, 247}, 61}, {{0, 0, 0, 0, 98, 126, 50, 222, 88, 49, 11, 185, 106, 2, 47, 146}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 123, 76}, 61}, {{0, 0, 164, 55, 100, 21, 174, 71, 221, 227, 76, 248, 54, 173, 176, 55}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 117, 214, 31, 27, 105}, 61}, {{0, 0, 0, 0, 0, 0, 0, 26, 50, 37, 225, 109, 97, 50, 14, 39}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 45}, 61}, {{0, 0, 0, 0, 0, 0, 185, 9, 90, 109, 115, 215, 89, 13, 128, 52}, 61}, {{0, 0, 0, 0, 235, 195, 134, 60, 201, 238, 109, 33, 188, 61, 56, 169}, 61}, {{0, 0, 0, 0, 0, 0, 172, 253, 185, 159, 103, 7, 16, 184, 224, 191}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 126, 173, 54, 33, 107}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 197, 166, 185, 105, 84, 199, 0, 183}, 61}, {{0, 0, 0, 0, 0, 0, 0, 98, 132, 253, 13, 184, 70, 219, 32, 124}, 61}, {{0, 0, 218, 117, 125, 83, 16, 134, 174, 192, 210, 195, 187, 225, 221, 182}, 61}, {{0, 152, 238, 186, 251, 153, 32, 16, 117, 124, 35, 151, 182, 248, 138, 191}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 21, 233, 160, 51}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 215, 238, 113, 23, 232}, 61}, {{0, 0, 0, 0, 233, 3, 177, 96, 233, 4, 97, 124, 129, 119, 255, 244}, 61}, {{0, 132, 189, 22, 113, 103, 152, 4, 115, 24, 121, 60, 69, 74, 228, 233}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 164, 244, 102, 82, 9, 152, 12, 124}, 61}, {{0, 0, 0, 0, 0, 201, 167, 240, 163, 86, 156, 15, 23, 120, 29, 235}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 46, 155, 164}, 61}, {{0, 215, 30, 37, 154, 255, 210, 76, 22, 176, 107, 52, 35, 88, 212, 192}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 24}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 195, 132, 63, 234, 4, 18, 2, 99}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 125}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 61}, {{0, 0, 0, 0, 0, 253, 1, 138, 126, 247, 190, 241, 215, 111, 91, 226}, 61}, {{0, 0, 0, 0, 0, 0, 146, 169, 9, 154, 128, 52, 18, 8, 135, 59}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 27, 57, 195, 146, 56, 167, 92, 162}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 61, 140, 83, 64}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 214, 119}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 209, 51, 192, 178, 241, 12, 193, 141}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 148, 92, 105, 161}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 107, 199, 244, 215, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 70, 231, 188}, 61}, {{0, 0, 0, 0, 0, 0, 220, 21, 255, 198, 103, 34, 163, 90, 101, 1}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 116, 240, 157, 233}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 64, 182, 33, 221, 33, 42, 93, 244}, 61}, {{0, 0, 0, 0, 0, 0, 18, 234, 233, 158, 21, 246, 65, 93, 3, 199}, 61}, {{0, 0, 0, 0, 0, 87, 234, 165, 93, 191, 8, 215, 87, 109, 130, 143}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 112, 1, 246, 50, 10, 115, 62, 99}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 131}, 61}, {{0, 0, 0, 114, 124, 157, 211, 62, 164, 8, 33, 49, 118, 238, 75, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 102, 47, 223, 155, 32}, 61}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 138}, 225}, {{3, 119, 148, 0, 0, 0, 199, 254, 193, 211, 90, 213, 182, 208, 232, 5}, 225}, {{3, 119, 148, 0, 0, 0, 0, 1, 18, 239, 238, 97, 145, 236, 135, 213}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 55, 185}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 47, 2, 77, 88, 150, 159, 169, 245}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 105, 82}, 225}, {{3, 119, 148, 0, 0, 0, 85, 100, 235, 50, 37, 64, 122, 194, 116, 236}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 228, 225, 42, 242, 94, 147, 225, 180}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 247}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 115, 31, 49, 19, 150, 49, 235}, 225}, {{3, 119, 148, 0, 0, 0, 141, 70, 42, 196, 19, 12, 120, 190, 199, 22}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 211, 219, 86, 106, 43}, 225}, {{3, 119, 148, 0, 0, 145, 85, 200, 128, 12, 148, 158, 132, 102, 226, 58}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 84, 154, 250, 8, 101, 150}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 242, 191, 141}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 52, 32, 98}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 49, 148, 4, 144, 192}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 132}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 44, 17, 253, 200, 140, 225, 158, 194}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 63, 45, 210}, 225}, {{3, 119, 148, 0, 0, 30, 138, 139, 217, 36, 94, 78, 94, 205, 146, 95}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 173, 128, 228, 195, 61, 252, 101, 118}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 203}, 225}, {{3, 119, 148, 0, 0, 0, 0, 102, 170, 173, 131, 104, 236, 84, 209, 20}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 160, 227, 135}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 124, 128, 174, 165, 142}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 145, 233, 64, 172, 56, 139}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 225}, {{3, 119, 148, 0, 0, 16, 36, 71, 99, 227, 249, 171, 106, 106, 4, 229}, 225}, {{3, 119, 148, 0, 128, 111, 4, 127, 12, 139, 220, 118, 9, 87, 185, 199}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 90, 62}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 236, 59, 126, 17, 198, 119, 240}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 165}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 180, 176, 225, 221, 123, 57, 126, 7}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 223}, 225}, {{3, 119, 148, 0, 0, 0, 200, 196, 208, 182, 89, 219, 146, 99, 117, 243}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 247}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 44, 54, 9, 169, 216, 161, 34}, 225}, {{3, 119, 148, 0, 0, 170, 65, 154, 62, 226, 156, 152, 102, 57, 71, 115}, 225}, {{3, 119, 148, 0, 0, 0, 4, 14, 26, 28, 241, 1, 208, 121, 200, 44}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 209, 118, 203, 47, 104, 182}, 225}, {{3, 119, 148, 7, 13, 129, 59, 125, 182, 158, 204, 56, 178, 7, 55, 39}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 37}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 223, 217, 102, 129, 99, 62}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 223, 247, 151, 122, 201, 176, 165, 47}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 138, 126, 69}, 225}, {{3, 119, 148, 0, 0, 35, 13, 208, 34, 41, 61, 98, 32, 21, 186, 108}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 225}, {{3, 119, 148, 0, 0, 253, 235, 251, 244, 248, 188, 130, 249, 88, 220, 86}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 141, 123, 120, 77, 236, 47, 222, 15}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 135, 87, 168, 23, 56, 67, 236}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 51, 114, 46, 128, 6, 38, 86, 90}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 168, 231, 76, 215, 65, 200, 224, 182}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 92, 107, 110, 99, 178}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{3, 119, 148, 0, 0, 0, 78, 180, 108, 38, 234, 94, 31, 237, 49, 39}, 225}, {{3, 119, 148, 0, 0, 0, 0, 199, 230, 153, 113, 189, 57, 230, 131, 251}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 226, 222, 196, 44, 236}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 57}, 225}, {{3, 119, 148, 0, 0, 0, 62, 172, 255, 215, 52, 97, 179, 37, 198, 193}, 225}, {{3, 119, 148, 0, 40, 157, 56, 32, 132, 110, 188, 42, 177, 72, 211, 231}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 95, 158, 167}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 225}, {{3, 119, 148, 0, 0, 0, 0, 142, 116, 183, 197, 40, 214, 232, 102, 218}, 225}, {{3, 119, 148, 0, 0, 0, 174, 205, 38, 248, 44, 221, 236, 66, 199, 210}, 225}, {{3, 119, 148, 0, 0, 0, 210, 227, 205, 231, 252, 205, 203, 168, 164, 155}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 102, 141, 54}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 9}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 73, 0, 30, 130, 93, 193}, 225}, {{3, 119, 148, 0, 0, 11, 238, 41, 65, 114, 24, 246, 30, 123, 33, 244}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 227, 123}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 144, 141, 27, 154, 201, 11, 116, 214}, 225}, {{3, 119, 148, 0, 0, 0, 0, 197, 217, 41, 240, 173, 10, 92, 54, 228}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 241, 166, 225, 185, 120, 168, 49}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 145, 41, 7, 55, 213, 108}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 118, 176, 246, 219, 133, 209}, 225}, {{3, 119, 148, 0, 0, 0, 213, 220, 199, 48, 112, 200, 35, 59, 186, 118}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 88, 240, 110}, 225}, {{3, 119, 148, 0, 0, 0, 0, 7, 251, 218, 150, 63, 195, 137, 235, 59}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 15, 207, 209, 36, 30, 58}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 28, 118}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 218, 24, 191}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 180, 3, 196, 41, 132}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 233, 61}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 130, 137}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 126, 173, 52, 93, 83, 243, 27}, 225}, {{3, 119, 148, 0, 0, 0, 0, 253, 56, 40, 109, 160, 34, 142, 66, 116}, 225}, {{3, 119, 148, 0, 0, 157, 100, 0, 251, 199, 245, 28, 195, 15, 162, 97}, 225}, {{3, 119, 148, 0, 0, 0, 0, 237, 15, 89, 205, 180, 150, 210, 63, 251}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 115, 15, 192, 226, 131, 205}, 225}, {{3, 119, 148, 0, 63, 85, 38, 96, 37, 43, 84, 193, 61, 243, 156, 12}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 63}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 219, 132, 197}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 209, 220, 231, 214, 154, 226, 254, 1}, 225}, {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{3, 119, 148, 0, 0, 0, 0, 187, 154, 242, 162, 162, 42, 227, 78, 85}, 225}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 62, 232, 131, 169, 74, 195, 133}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 230, 191, 189, 10}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 249}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 223}, {{13, 192, 0, 0, 0, 0, 0, 118, 33, 214, 255, 28, 59, 142, 134, 55}, 223}, {{13, 192, 0, 166, 156, 18, 168, 82, 121, 83, 162, 98, 50, 195, 164, 233}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 100, 97, 34, 178, 4, 62}, 223}, {{13, 192, 0, 0, 0, 0, 0, 230, 252, 221, 220, 127, 134, 28, 148, 71}, 223}, {{13, 192, 0, 0, 0, 0, 0, 201, 233, 192, 182, 213, 87, 200, 252, 44}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 223}, {{13, 192, 0, 0, 131, 157, 185, 172, 221, 103, 140, 243, 95, 223, 49, 40}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 142, 201, 178, 165, 209, 174, 200, 201}, 223}, {{13, 192, 225, 220, 6, 119, 61, 185, 75, 43, 137, 31, 184, 179, 127, 102}, 223}, {{13, 192, 0, 0, 0, 114, 241, 254, 106, 173, 176, 218, 183, 207, 133, 244}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 62, 222, 184}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 40, 150, 88, 26, 205, 1}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 66}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 190, 6, 57}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 5, 38}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 70}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 18}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 141, 59, 152, 184, 211, 229}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 76, 177, 56, 211, 112, 107, 57, 119}, 223}, {{13, 192, 0, 0, 0, 194, 136, 47, 191, 179, 40, 187, 14, 246, 223, 145}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 190, 252, 219}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 94, 67, 76, 146, 213, 249, 39, 28}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 159, 200, 245, 61, 17, 139, 128}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 182, 199, 214, 185, 222, 149, 237, 122}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 10, 203, 61, 72}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 243, 144, 226, 69, 195, 122}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 223}, {{13, 192, 0, 116, 234, 3, 250, 37, 96, 13, 181, 64, 40, 88, 76, 217}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 232, 121, 17, 203, 102, 141, 36}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 18, 227, 218}, 223}, {{13, 192, 122, 13, 92, 228, 4, 105, 133, 46, 142, 255, 199, 220, 146, 22}, 223}, {{13, 192, 0, 0, 0, 0, 0, 182, 121, 92, 227, 228, 175, 204, 230, 55}, 223}, {{13, 192, 0, 0, 0, 179, 114, 92, 25, 88, 34, 23, 14, 17, 110, 2}, 223}, {{13, 192, 0, 28, 237, 22, 207, 168, 92, 142, 230, 94, 125, 222, 71, 235}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 68, 255, 159, 240, 249, 77, 249}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 145, 16, 107}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 231, 146, 90, 100, 86, 161}, 223}, {{13, 192, 0, 0, 0, 0, 68, 9, 203, 179, 138, 137, 183, 61, 45, 71}, 223}, {{13, 192, 250, 51, 52, 19, 168, 188, 165, 33, 63, 135, 39, 40, 53, 88}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 175, 80, 201, 90, 143, 233}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 112}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 243, 98, 136, 208, 179, 57, 116}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 53, 164, 81}, 223}, {{13, 192, 0, 0, 47, 106, 85, 81, 164, 111, 9, 40, 18, 237, 74, 35}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 14, 0, 150, 92}, 223}, {{13, 192, 0, 180, 1, 162, 138, 193, 177, 80, 215, 111, 223, 41, 155, 91}, 223}, {{13, 192, 0, 81, 73, 91, 55, 184, 135, 29, 236, 62, 145, 34, 29, 54}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 56, 218, 8, 119, 119, 166, 28}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 134}, 223}, {{13, 192, 0, 0, 0, 0, 0, 154, 8, 157, 190, 212, 15, 30, 109, 254}, 223}, {{13, 192, 0, 0, 0, 0, 198, 216, 124, 131, 214, 43, 91, 224, 164, 38}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 75, 163, 186, 164}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 175, 103, 11, 209, 254, 230, 169, 120}, 223}, {{13, 192, 20, 162, 59, 202, 252, 62, 140, 124, 72, 82, 18, 87, 213, 33}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 111, 186}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 88, 207}, 223}, {{13, 192, 0, 0, 0, 0, 16, 12, 80, 219, 202, 30, 83, 107, 78, 52}, 223}, {{13, 192, 0, 0, 0, 0, 116, 177, 254, 85, 214, 27, 162, 68, 55, 2}, 223}, {{13, 192, 0, 0, 0, 0, 0, 127, 65, 63, 26, 142, 71, 29, 174, 189}, 223}, {{13, 192, 0, 0, 0, 0, 0, 222, 102, 22, 1, 141, 202, 200, 198, 193}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 141, 169, 252, 103, 140, 119}, 223}, {{13, 192, 0, 0, 166, 225, 200, 177, 233, 232, 182, 91, 150, 124, 216, 174}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 175, 115, 245, 123, 121, 72, 58}, 223}, {{13, 192, 0, 0, 0, 0, 142, 182, 153, 184, 195, 40, 210, 202, 115, 80}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 141, 170, 6, 223}, 223}, {{13, 192, 36, 74, 7, 182, 249, 33, 116, 80, 76, 55, 101, 158, 96, 199}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 230, 171, 255}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 221, 67, 140, 217, 148, 4, 38}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 217, 122, 27, 151, 23, 193, 255, 69}, 223}, {{13, 192, 0, 0, 0, 181, 178, 232, 165, 66, 111, 106, 243, 9, 121, 2}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 176, 230, 237}, 223}, {{13, 192, 0, 0, 0, 0, 0, 214, 209, 229, 113, 49, 203, 128, 57, 141}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 152, 14, 56, 156}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 235}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 63, 218, 59}, 223}, {{13, 192, 0, 0, 0, 0, 109, 141, 142, 111, 146, 242, 9, 110, 94, 24}, 223}, {{13, 192, 0, 219, 81, 226, 63, 72, 51, 226, 84, 61, 119, 182, 94, 238}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 223}, 223}, {{13, 192, 131, 59, 192, 52, 174, 178, 61, 218, 175, 230, 158, 35, 101, 230}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 223}, {{13, 192, 0, 0, 221, 20, 237, 226, 50, 188, 85, 11, 53, 248, 72, 179}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 192, 220, 207}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 82, 110, 247}, 223}, {{13, 192, 14, 94, 252, 120, 55, 204, 67, 207, 41, 154, 235, 136, 178, 58}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 149, 139, 147, 136}, 223}, {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 185, 63, 92, 251}, 223}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 118, 0, 32}, 29}, {{117, 28, 0, 0, 0, 0, 172, 176, 141, 63, 80, 223, 58, 31, 6, 76}, 29}, {{117, 28, 0, 226, 225, 147, 85, 47, 216, 21, 225, 144, 216, 150, 105, 205}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 220, 158, 97}, 29}, {{117, 28, 0, 0, 0, 0, 0, 100, 244, 242, 227, 186, 247, 158, 205, 106}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 126, 161, 155, 45, 215, 91, 126, 235}, 29}, {{117, 28, 0, 0, 166, 239, 123, 30, 230, 227, 221, 80, 166, 132, 45, 119}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 19, 26, 172, 189, 15, 149, 153, 172}, 29}, {{117, 28, 0, 226, 74, 122, 16, 87, 254, 244, 2, 172, 122, 3, 28, 238}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 3, 45, 197, 114, 198, 224}, 29}, {{117, 28, 0, 0, 0, 241, 154, 122, 37, 115, 214, 250, 122, 241, 171, 22}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 6, 10, 171, 92, 57, 191, 14, 25, 103, 151, 113}, 29}, {{117, 28, 0, 0, 0, 141, 11, 218, 57, 44, 197, 229, 205, 182, 172, 35}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 13, 99, 224, 131, 236, 29}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 29}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 28, 201, 50, 223, 129, 99}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 81}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 208, 110, 148, 147, 37, 94, 18, 220}, 29}, {{117, 28, 0, 137, 156, 225, 254, 31, 94, 24, 5, 97, 15, 150, 29, 92}, 29}, {{117, 28, 0, 0, 0, 0, 0, 97, 29, 19, 147, 26, 124, 211, 206, 137}, 29}, {{117, 28, 0, 0, 0, 0, 125, 129, 0, 208, 91, 41, 179, 82, 187, 174}, 29}, {{117, 28, 0, 0, 0, 11, 92, 159, 89, 68, 74, 153, 44, 67, 152, 144}, 29}, {{117, 28, 0, 240, 223, 114, 154, 221, 132, 150, 84, 38, 233, 114, 185, 76}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 79, 220, 118, 204, 67, 236}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 88, 185, 33, 19}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 62, 45}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 177, 70}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 29}, {{117, 28, 0, 0, 0, 0, 0, 244, 20, 145, 147, 155, 52, 248, 222, 28}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 114, 171, 123, 170}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 103, 57, 150, 22}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 48, 96, 89, 48, 12, 217, 133, 57, 164, 133, 87, 255}, 29}, {{117, 28, 0, 0, 0, 0, 219, 233, 81, 140, 148, 132, 240, 237, 209, 187}, 29}, {{117, 28, 0, 0, 139, 199, 16, 24, 223, 88, 145, 145, 159, 10, 24, 109}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 203, 224, 31, 106, 191, 79}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 225}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 52, 58, 103, 21, 164, 112}, 29}, {{117, 28, 0, 0, 0, 0, 240, 202, 15, 182, 107, 90, 146, 247, 174, 112}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 220}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 29}, {{117, 28, 0, 0, 0, 0, 0, 212, 214, 149, 50, 219, 51, 219, 167, 177}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 247, 200, 190, 10, 101, 1, 192, 217}, 29}, {{117, 28, 0, 212, 141, 226, 76, 137, 136, 143, 32, 178, 38, 138, 56, 72}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 50, 93, 190, 52, 55, 182}, 29}, {{117, 28, 0, 0, 127, 104, 194, 118, 44, 78, 141, 78, 251, 96, 244, 56}, 29}, {{117, 28, 0, 0, 0, 0, 229, 191, 78, 235, 13, 86, 26, 116, 144, 168}, 29}, {{117, 28, 0, 0, 0, 0, 0, 221, 191, 9, 85, 196, 210, 193, 104, 228}, 29}, {{117, 28, 0, 121, 13, 222, 154, 7, 26, 91, 228, 55, 54, 153, 235, 217}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 57, 59, 35}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 69, 42}, 29}, {{117, 28, 0, 0, 0, 45, 178, 23, 124, 177, 61, 57, 58, 51, 149, 160}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 189, 41}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 252}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 251, 129, 128}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{117, 28, 0, 0, 0, 0, 0, 130, 9, 246, 12, 190, 209, 99, 110, 131}, 29}, {{117, 28, 0, 0, 0, 0, 115, 89, 163, 164, 62, 124, 202, 215, 228, 70}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 232, 8, 202, 190, 53, 175, 71}, 29}, {{117, 28, 0, 0, 0, 38, 193, 155, 208, 116, 230, 152, 89, 230, 124, 170}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 130, 83, 182, 170, 10, 125}, 29}, {{117, 28, 0, 154, 33, 199, 52, 110, 2, 253, 100, 227, 250, 36, 156, 252}, 29}, {{117, 28, 0, 57, 200, 189, 251, 171, 83, 203, 186, 237, 121, 129, 26, 231}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 29}, {{117, 28, 139, 182, 45, 81, 249, 53, 63, 94, 113, 173, 164, 33, 243, 59}, 29}, {{117, 28, 0, 0, 0, 70, 129, 180, 217, 154, 226, 45, 36, 129, 104, 126}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 133, 27, 118, 172}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 167, 219, 108, 175, 165, 89, 171, 79}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 207}, 29}, {{117, 28, 0, 0, 0, 134, 202, 248, 125, 199, 235, 45, 125, 93, 247, 10}, 29}, {{117, 28, 0, 135, 163, 6, 106, 92, 204, 59, 185, 14, 205, 247, 95, 190}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 230}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 178, 130, 130, 81, 109, 9, 1, 186}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 252, 25, 159, 44}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 210, 80, 215}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 202, 148, 16}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 138}, 29}, {{117, 28, 0, 201, 53, 133, 99, 143, 11, 248, 60, 194, 32, 93, 90, 207}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 141, 135, 134, 105, 97, 77}, 29}, {{117, 28, 0, 39, 166, 70, 101, 10, 164, 253, 97, 214, 245, 227, 196, 255}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 75, 206, 143, 98, 227, 210}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 121, 29}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 226, 241}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 141, 222, 162, 156, 139, 18}, 29}, {{117, 28, 0, 0, 0, 243, 78, 237, 187, 248, 205, 62, 131, 177, 152, 62}, 29}, {{117, 28, 0, 0, 0, 0, 0, 10, 175, 30, 10, 183, 182, 50, 228, 43}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 33}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 226, 226, 45, 157}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 63, 20, 208, 217, 64, 218, 147, 56}, 29}, {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 229}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 254}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 74, 195}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 5, 133}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 20}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 135, 78}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 100, 64}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 209, 186}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 151, 239}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 13, 4}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 55, 145}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 133, 150, 37}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 132}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 36, 47}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 92}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 130, 149}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 133}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 239, 248}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 51}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 63, 207}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 62}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 120}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 153}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 192, 93}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 30, 16}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 3, 32}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 4, 246}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 251, 134}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 194}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 243}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 5, 147}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 57}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 106}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 214}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 59, 77}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 20}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 109}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 146, 124}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 150}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 222, 160}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 215}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 165}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 157}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 115}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 13}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 171, 181}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 89}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 99}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 182, 119}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 95}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 25, 10}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 174}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 216}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 168}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 197, 3, 14}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 216}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 214, 95}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 171}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 88, 243}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 133}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 148}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 77}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 135, 150}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 96}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 22}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 200, 184}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 135, 147}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 216}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 166}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 148, 201, 220, 172, 50}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 101}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 34, 210, 43}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 178, 48, 69, 17}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 55}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 35, 81, 149, 101, 116}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 48, 198}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 42}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 38, 174, 146}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 211}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 162, 56, 48, 77}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 82, 211, 209, 46}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 219, 33, 167, 195}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 180, 68, 67, 61, 199}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 249}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 83, 136}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 164, 124, 179, 245}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 10}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 74, 135, 235, 25}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 129, 87, 49, 228, 43}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 184, 193}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 77, 55, 32, 82}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 78}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 145}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 190, 171, 210, 211, 148}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 41}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 249, 58, 141}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 203, 194, 221, 209}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 32}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 174, 160, 139}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 222, 42, 121, 236}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 113, 148, 1}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 228, 43, 94, 182, 223}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 175}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 110, 100, 113, 138, 24}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 232}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 153, 38, 131, 42}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 203, 8}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 19, 88, 139}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 59, 13, 93, 139, 87}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 36}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 86, 208}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 164}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 84, 134}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 148, 171, 95, 248, 65}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 187, 83, 62, 140}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 248, 14, 35}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 158, 59, 194, 189, 98}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 175, 237}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 183, 88, 156}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 210}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 120}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 117, 112}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 189, 207, 231, 179}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 178}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 55, 77}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 111, 203, 56, 209}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 144, 44, 180, 155, 254}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 8, 72}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 8}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 254, 181, 211}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 97, 105, 238}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 115}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 165, 46, 220, 165, 156}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 104}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 168, 247, 139, 0, 133}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 164, 37, 71, 77}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 68, 219, 96}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 49}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 137, 37, 2, 132, 247}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 103, 30, 212, 179}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 150, 139, 115, 145, 9}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 113, 120}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 106, 39}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 22, 75, 51}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 239, 141, 97}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 92, 53, 20, 219, 190}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 127, 145}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 117, 71, 152, 253, 254}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 45, 67, 46, 232, 145}, 178}, {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 60, 157, 76}, 178}, {{222, 151, 166, 97, 129, 250, 140, 148, 251, 245, 45, 46, 248, 51, 3, 112}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 233, 92, 212}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 156, 185, 233, 37, 147}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 125, 222, 163, 61, 208}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 75, 112, 34, 236, 151, 228, 134, 77}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 142, 106, 237, 41, 57, 71, 139}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 26, 151}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 29, 77, 67, 87, 18, 168, 188, 162}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 145, 179, 141, 196, 238}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 105, 33, 250, 192, 61, 204, 88}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 14, 54, 33, 35, 176, 17}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 236, 52, 28}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 137, 67, 24, 190, 1, 26, 44, 83}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 250, 29, 74, 46, 204, 4, 218}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 116, 218, 100, 153, 23, 89}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 116, 119, 226, 55}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 60, 49, 124, 76}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 91, 99, 206, 132, 20, 221}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 9, 249, 29, 149}, 38}, {{222, 151, 166, 97, 129, 250, 140, 38, 179, 184, 196, 145, 193, 137, 185, 2}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 245, 193, 18, 1, 152}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 29, 73, 96, 117, 172, 135}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 87, 190, 64, 239, 184, 227, 98, 42}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 196, 89, 171, 180, 129}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 35, 179, 33, 192, 199}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 180, 210, 91, 250, 227}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 224, 29}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 240, 82, 142, 213, 187}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 108, 16, 254, 0, 171, 52, 197, 172}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 33, 49, 185, 27, 83, 255, 236, 138, 214}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 151, 230, 165, 123, 3}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 182, 127}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 225, 117}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 210, 153, 66, 39, 121, 42, 72, 182}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 98, 113, 232, 9, 42}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 196, 15, 15, 193, 75, 237, 135}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 198, 103}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 178, 47, 159, 24, 25}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 134, 8, 106, 93, 169}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 95, 216, 155, 119, 48, 3, 171, 208}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 75, 122, 16, 234, 113, 102, 204, 170}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 108, 145, 3, 116, 25, 170, 52, 214}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 71, 77}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 52, 155, 208, 31, 1, 57, 186, 44}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 232, 89, 71, 184}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 233, 251, 212, 95, 134, 112, 27, 218}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 51, 195, 150, 90, 139, 175}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 8, 57, 108, 22, 113}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 33, 172}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 20, 250, 38, 120}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 112, 14, 197}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 137, 131, 149}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 224, 215, 212}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 78, 168, 150, 176, 200}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 111, 137, 83, 51, 21, 35}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 199, 215, 36, 68, 117, 205, 39, 216}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 105, 8, 46, 150, 100}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 235, 255}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 51, 36, 89}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 91, 238}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 238, 150, 9, 189, 151, 52, 118}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 227, 130, 174, 42, 147, 185, 9, 127}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 160, 182, 7}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 87, 60, 104, 119, 75}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 102, 1, 58, 173, 34, 22, 156}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 159, 204, 235, 202}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 125, 234, 148, 121, 11, 16}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 109, 117, 101, 93, 149, 189, 83, 86}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 2, 162, 132}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 64, 74, 232, 79, 97, 249, 3}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 218, 38, 155}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 42, 214, 12, 83, 249}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 239, 188, 8, 143, 243, 65}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 252, 147}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 54, 167, 147, 46, 209, 12, 122}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 67, 35, 59, 17, 166}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 255, 205, 118, 202, 179, 160, 173, 110}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 247, 23, 195}, 38}, {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 87, 188, 176, 199}, 38}, {{174, 128, 0, 51, 120, 228, 150, 109, 139, 177, 234, 42, 141, 145, 109, 71}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 113, 85}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 120}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 109}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 173, 22}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 41, 190, 4, 102, 94, 84, 254}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 11, 114, 169, 153}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 37, 52, 23, 209, 234, 176, 113}, 141}, {{174, 128, 0, 0, 0, 232, 229, 109, 227, 112, 113, 67, 48, 184, 60, 184}, 141}, {{174, 128, 0, 11, 147, 238, 44, 195, 236, 233, 238, 124, 66, 191, 58, 25}, 141}, {{174, 128, 0, 0, 0, 0, 238, 20, 19, 249, 5, 199, 81, 138, 75, 37}, 141}, {{174, 128, 0, 174, 53, 159, 72, 182, 222, 198, 137, 84, 1, 67, 188, 56}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 185, 22}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 53, 13, 55, 116, 13, 121, 55, 114}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 67}, 141}, {{174, 128, 0, 255, 138, 80, 241, 67, 79, 112, 129, 40, 196, 90, 125, 10}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 47, 143, 145, 178, 17, 179, 156, 69, 247, 112, 198, 10}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 37, 54, 23, 21, 59, 251, 165}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 182, 137, 19, 157, 203, 212, 224}, 141}, {{174, 128, 0, 0, 0, 0, 85, 245, 69, 135, 181, 225, 150, 185, 220, 153}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 247}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 211, 129, 196, 247}, 141}, {{174, 128, 0, 0, 238, 174, 143, 187, 117, 17, 156, 154, 28, 248, 0, 154}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 59, 197, 91}, 141}, {{174, 128, 0, 0, 27, 98, 71, 208, 213, 236, 42, 17, 172, 88, 160, 180}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 100, 237, 3, 105, 5, 177, 78, 182}, 141}, {{174, 128, 0, 0, 231, 223, 66, 48, 246, 74, 49, 145, 253, 190, 61, 4}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 87, 196, 165, 74}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 30, 64, 94}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 84, 114, 236, 36}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 44, 21, 200, 124, 81, 10, 23, 216, 120, 217}, 141}, {{174, 128, 13, 90, 189, 214, 38, 163, 242, 97, 180, 194, 113, 24, 202, 12}, 141}, {{174, 128, 0, 0, 239, 95, 244, 234, 174, 51, 240, 174, 130, 1, 163, 159}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 129, 56, 212, 27, 108, 244, 119}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 249}, 141}, {{174, 128, 0, 212, 234, 203, 144, 4, 201, 201, 227, 200, 22, 84, 173, 228}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 237, 13, 144, 135, 10, 5}, 141}, {{174, 128, 0, 0, 0, 0, 0, 177, 222, 156, 200, 12, 178, 199, 248, 6}, 141}, {{174, 128, 0, 0, 138, 249, 128, 64, 242, 1, 202, 37, 4, 248, 38, 131}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 205, 33, 71, 255}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 3, 85, 218, 4, 109, 222, 124, 130, 130, 205, 5, 215, 30, 165}, 141}, {{174, 128, 0, 231, 191, 57, 147, 56, 237, 245, 21, 199, 231, 85, 34, 128}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 141}, {{174, 128, 0, 16, 226, 213, 90, 159, 19, 171, 165, 212, 160, 219, 168, 171}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 92, 153, 191, 85}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 241, 232, 162}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 72, 239}, 141}, {{174, 128, 0, 0, 0, 0, 20, 118, 128, 87, 224, 7, 222, 27, 122, 171}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 233, 94}, 141}, {{174, 128, 0, 0, 2, 66, 187, 124, 180, 86, 231, 111, 29, 177, 27, 110}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 177, 90, 144, 137, 169, 101, 235}, 141}, {{174, 128, 0, 0, 0, 97, 41, 137, 88, 240, 115, 250, 240, 233, 149, 195}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 64, 131}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 215, 181, 17}, 141}, {{174, 128, 0, 0, 0, 213, 104, 175, 66, 140, 213, 140, 36, 61, 220, 134}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 83, 190}, 141}, {{174, 128, 0, 0, 0, 0, 0, 123, 213, 172, 92, 191, 219, 28, 132, 162}, 141}, {{174, 128, 0, 0, 0, 0, 216, 211, 49, 125, 70, 70, 82, 143, 252, 60}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 184, 236, 204, 248, 58, 5, 42, 187}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 167}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 113}, 141}, {{174, 128, 206, 4, 173, 178, 29, 59, 211, 49, 221, 179, 48, 251, 84, 191}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 165, 81, 255, 222, 61, 246, 14}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 63, 139, 154, 188, 239, 60, 59, 114}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 44}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 141}, {{174, 128, 0, 0, 0, 134, 67, 91, 123, 25, 45, 66, 97, 75, 124, 252}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 94, 147, 161}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 74, 81, 160, 172, 114, 34, 153}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 197, 181, 166, 28, 64, 164, 26}, 141}, {{174, 128, 0, 241, 1, 242, 208, 184, 75, 243, 34, 251, 150, 193, 80, 118}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 141}, {{174, 128, 0, 0, 236, 130, 8, 221, 196, 254, 98, 70, 180, 223, 30, 28}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 43, 11, 100, 249, 199, 163, 145, 94, 150, 173, 221}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 188, 50, 208, 174}, 141}, {{174, 128, 0, 0, 0, 0, 0, 51, 43, 148, 189, 138, 178, 222, 199, 124}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 67, 112, 69, 70, 113, 214}, 141}, {{174, 128, 0, 0, 40, 238, 217, 255, 236, 201, 5, 144, 141, 231, 84, 35}, 141}, {{174, 128, 0, 0, 0, 0, 0, 69, 179, 113, 250, 212, 227, 8, 95, 77}, 141}, {{174, 128, 0, 0, 0, 27, 212, 241, 198, 188, 44, 65, 108, 49, 74, 112}, 141}, {{174, 128, 0, 0, 0, 0, 0, 73, 61, 191, 184, 185, 52, 156, 59, 136}, 141}, {{174, 128, 0, 0, 0, 0, 86, 118, 121, 9, 98, 51, 190, 103, 117, 214}, 141}, {{174, 128, 0, 0, 0, 0, 0, 62, 190, 47, 116, 10, 157, 97, 41, 187}, 141}, {{174, 128, 0, 0, 0, 0, 174, 2, 37, 19, 123, 46, 93, 78, 149, 242}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 40, 58, 222, 135, 36, 206, 100}, 141}, {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 141}, {{174, 128, 0, 166, 42, 140, 193, 255, 203, 78, 23, 158, 77, 95, 28, 106}, 141}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 90}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 199}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 37}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 174}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 221}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 22}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 217}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 163}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 33}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 64}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 179}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 200}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 27}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 150}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 229}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 9}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 48}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 58}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 52}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 7}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 119}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 185}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 19}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 245}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 177}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 201}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 32}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 249}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 43}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 247}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 38}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 251}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 194}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 181}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 92}, 230}, {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 160}, 230}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 165}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 185}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 115, 57, 180}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 65, 223, 192}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 99, 186, 89}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 242}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 167}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 109, 189}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 174, 9}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 53, 108}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 108, 79}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 140, 53}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 208, 182, 52}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 161, 147}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 87, 156}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 184}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 62}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 196, 205, 197}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 227, 79}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 6, 99}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 51, 128}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 198}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 13}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 159, 107}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 126, 226, 81}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 114, 61}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 48}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 73, 212}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 223, 184}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 159, 165}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 84}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 209}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 186, 120}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 112, 153, 94}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 253, 175}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 117}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 116, 191}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 187, 103}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 174}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 49, 153}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 216}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 35, 214, 65}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 191}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 21, 86}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 192}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 57, 149, 16}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 204}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 177}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 127, 111}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 69, 190}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 57}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 48, 246}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 20}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 53, 75}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 126, 50, 97}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 245}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 43, 161}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 97, 190, 28}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 154}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 131}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 176, 67}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 118}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 98}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 55, 76}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 49, 188}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 59}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 64}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 108}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 79}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 54}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 15, 179}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 125, 248, 159}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 107, 201}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 97, 49}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 230, 43}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 116, 245, 246}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 232, 212}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 53}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 83}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 46, 185}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 38}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 124}, {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 105}, 124}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 34}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 118}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 181}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 68}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 19}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 219}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 60}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 43}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 68}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 120}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 60}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 189}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 29}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 221}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 182}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 54}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 143}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 198, 123, 111, 127}, 162}, {{111, 119, 169, 51, 0, 210, 248, 45, 11, 25, 193, 165, 203, 125, 253, 231}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 98, 114, 147, 245, 116, 104, 104, 30}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 125, 221, 10, 190, 238, 205}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 63, 180, 153, 208, 93, 173, 7, 184}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 11, 46, 249, 28}, 162}, {{111, 119, 169, 51, 0, 0, 0, 173, 216, 212, 57, 200, 131, 77, 137, 97}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 203}, 162}, {{111, 119, 169, 51, 0, 0, 154, 75, 31, 114, 145, 237, 138, 3, 67, 91}, 162}, {{111, 119, 169, 51, 0, 0, 218, 54, 201, 99, 170, 165, 155, 249, 197, 31}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 60, 128, 173, 126, 133, 173}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 185, 63}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 125}, 162}, {{111, 119, 169, 51, 0, 0, 0, 83, 29, 212, 9, 160, 220, 191, 207, 124}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 208, 221, 240, 164, 104, 222, 106, 81}, 162}, {{111, 119, 169, 51, 0, 0, 45, 200, 65, 55, 253, 170, 63, 95, 54, 120}, 162}, {{111, 119, 169, 51, 0, 0, 81, 149, 36, 1, 63, 218, 177, 209, 82, 72}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 180}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 1, 73}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 56, 251, 225, 166, 52}, 162}, {{111, 119, 169, 51, 0, 0, 0, 3, 9, 190, 54, 127, 8, 239, 143, 28}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 57, 33}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 35, 188, 174, 70, 185}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 24, 92, 35, 62, 39, 198, 205}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 171, 249, 20, 249}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 77, 236, 32, 147}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 60, 37, 95, 2, 249, 232}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 16}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 69, 209, 70, 15}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 90}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 164}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 90, 80, 199, 107, 79, 160, 154}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 197}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 236}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 226, 174, 211, 148}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 89, 132, 94, 2, 4, 128, 232, 252}, 162}, {{111, 119, 169, 51, 0, 0, 165, 98, 179, 108, 51, 239, 54, 135, 132, 33}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 20, 117, 232, 236, 42, 28}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 67, 23, 24, 209, 223}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 67, 122, 88, 208, 52, 238, 67}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 65}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 105, 216, 87, 178, 160, 255, 15}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 95, 56, 71, 109, 48, 249, 236, 32}, 162}, {{111, 119, 169, 51, 0, 160, 81, 239, 50, 155, 67, 23, 77, 200, 255, 253}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 165, 7, 179, 145, 201, 241, 229, 227}, 162}, {{111, 119, 169, 51, 0, 0, 0, 250, 18, 52, 59, 174, 61, 48, 180, 252}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 70, 203, 200, 250, 232, 162, 29}, 162}, {{111, 119, 169, 51, 0, 0, 65, 234, 167, 120, 111, 68, 19, 139, 157, 41}, 162}, {{111, 119, 169, 51, 0, 0, 236, 156, 108, 80, 117, 201, 128, 211, 157, 79}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 238, 7, 174, 139, 82, 31}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 26, 255, 250, 116, 102, 252, 61, 183}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 17, 188, 206, 167, 98, 45, 88, 22}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 68, 167}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 43, 10, 17, 219}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 52, 217}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 1, 32, 106, 7, 44, 252, 187}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 49, 182, 240, 201, 176}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 246, 249, 247, 139, 250}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 23, 68, 232, 127}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 125, 163, 108, 221, 108}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 207, 62, 4, 152, 237, 38}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 255, 196}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 151, 248, 55, 97}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 74, 26, 44, 144}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 204, 27, 43, 197, 237, 45, 24, 66}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 137, 190, 232, 176}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 162}, {{111, 119, 169, 51, 0, 190, 201, 34, 210, 26, 187, 141, 45, 97, 63, 70}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 112, 76, 230, 46, 183}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 63}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 126, 140, 222, 10, 186, 239, 53}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 240, 33, 115, 78, 237, 136}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 191, 205}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 138, 29, 153, 241, 106, 189, 149}, 162}, {{111, 119, 169, 51, 0, 0, 0, 25, 88, 12, 201, 68, 203, 201, 88, 59}, 162}, {{111, 119, 169, 51, 0, 0, 0, 202, 159, 188, 244, 15, 23, 216, 14, 16}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 165, 143, 166, 53, 210, 114, 149}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 76, 81, 58, 47, 173, 10, 132}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 238, 162, 30, 187, 73, 122}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 117, 209, 142, 1, 189, 82, 92, 15}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 198}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 176, 177, 75, 240, 161, 167}, 162}, {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 162}, {{105, 128, 0, 0, 0, 0, 0, 0, 208, 201, 251, 235, 207, 97, 80, 135}, 32}, {{105, 128, 0, 0, 0, 0, 205, 170, 53, 155, 8, 82, 241, 85, 124, 53}, 32}, {{105, 128, 0, 0, 0, 0, 44, 59, 233, 156, 246, 79, 154, 31, 67, 29}, 32}, {{105, 128, 0, 0, 0, 0, 231, 11, 171, 243, 133, 246, 69, 51, 72, 176}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 13, 83, 214, 214}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 141, 199}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 154, 203, 239, 8, 104, 26}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 232, 116}, 32}, {{105, 128, 0, 0, 0, 95, 170, 16, 20, 26, 74, 118, 167, 5, 71, 35}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 32}, {{105, 128, 190, 197, 26, 56, 35, 133, 146, 201, 81, 205, 61, 200, 195, 33}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 83, 203, 71, 86}, 32}, {{105, 128, 0, 198, 21, 118, 208, 180, 1, 52, 167, 69, 59, 172, 205, 158}, 32}, {{105, 128, 0, 0, 0, 0, 0, 242, 72, 168, 46, 242, 206, 145, 193, 78}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 3, 69, 36, 28}, 32}, {{105, 128, 0, 0, 0, 59, 185, 202, 124, 51, 2, 129, 145, 137, 122, 230}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 27}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 32}, {{105, 128, 0, 0, 0, 229, 189, 154, 191, 46, 86, 239, 213, 48, 215, 93}, 32}, {{105, 128, 0, 0, 0, 47, 115, 65, 67, 163, 203, 112, 147, 88, 93, 37}, 32}, {{105, 128, 0, 0, 22, 134, 140, 13, 128, 0, 153, 39, 26, 234, 126, 201}, 32}, {{105, 128, 0, 0, 0, 48, 102, 210, 233, 136, 106, 53, 237, 199, 59, 221}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 197, 82, 52, 143, 181, 152, 146, 193}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 201}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 66, 16}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 216, 130}, 32}, {{105, 128, 0, 0, 0, 0, 216, 70, 244, 57, 135, 66, 233, 132, 252, 191}, 32}, {{105, 128, 0, 0, 77, 123, 222, 133, 193, 76, 75, 24, 99, 234, 222, 223}, 32}, {{105, 128, 0, 0, 0, 0, 37, 234, 145, 229, 167, 163, 232, 124, 109, 238}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 32}, {{105, 128, 0, 0, 0, 0, 0, 135, 23, 198, 152, 69, 69, 134, 189, 8}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 173, 242, 89, 222}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 70, 118, 144, 227}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 50, 215, 35, 48, 208, 238, 167, 219, 66, 67, 122, 209}, 32}, {{105, 128, 77, 37, 9, 165, 227, 181, 191, 171, 120, 94, 153, 168, 215, 9}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 34, 111}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 201, 2}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 58, 68, 229, 211, 171, 32, 147, 209, 26, 224, 17, 175, 78}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 110, 24, 44}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 234}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31, 214, 119, 93, 227, 247}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 59, 178, 84, 7, 79, 210}, 32}, {{105, 128, 0, 0, 0, 0, 59, 32, 43, 189, 176, 177, 50, 113, 86, 53}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 199}, 32}, {{105, 128, 0, 0, 156, 64, 113, 119, 93, 164, 206, 62, 201, 62, 115, 131}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 135, 164, 46, 81, 124, 36, 174, 227}, 32}, {{105, 128, 0, 0, 0, 0, 0, 200, 133, 110, 187, 0, 37, 2, 77, 151}, 32}, {{105, 128, 0, 0, 0, 0, 0, 142, 173, 35, 113, 169, 159, 155, 21, 31}, 32}, {{105, 128, 0, 183, 127, 244, 245, 36, 246, 142, 34, 123, 95, 194, 77, 130}, 32}, {{105, 128, 0, 0, 0, 0, 139, 62, 144, 241, 239, 189, 213, 156, 181, 53}, 32}, {{105, 128, 0, 0, 0, 0, 0, 11, 64, 114, 11, 230, 156, 166, 1, 71}, 32}, {{105, 128, 0, 0, 0, 0, 57, 112, 121, 25, 137, 29, 126, 139, 79, 31}, 32}, {{105, 128, 104, 93, 130, 41, 4, 189, 227, 227, 172, 75, 182, 34, 33, 197}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 58, 137, 144, 213, 69, 90, 251, 204}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 60, 166, 181, 34}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 111}, 32}, {{105, 128, 0, 137, 86, 150, 3, 240, 128, 34, 8, 209, 168, 88, 69, 254}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 234, 61, 36, 186, 61, 141, 61}, 32}, {{105, 128, 0, 0, 197, 134, 231, 147, 209, 130, 198, 212, 126, 222, 93, 37}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 192, 89, 41, 84, 220, 110}, 32}, {{105, 128, 0, 0, 0, 109, 249, 241, 93, 203, 110, 109, 148, 94, 29, 131}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 12, 34, 105, 81, 185, 60, 184}, 32}, {{105, 128, 0, 0, 0, 60, 114, 70, 50, 103, 63, 48, 173, 102, 91, 214}, 32}, {{105, 128, 56, 172, 246, 39, 67, 225, 208, 216, 242, 134, 246, 207, 59, 250}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 30, 114, 193, 171, 120, 39, 86, 161}, 32}, {{105, 128, 0, 8, 25, 253, 3, 67, 193, 142, 75, 38, 255, 170, 9, 175}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 49}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 114}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 142, 148, 208, 120, 168, 148, 19}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 204, 133, 227}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 223}, 32}, {{105, 128, 0, 54, 157, 7, 54, 139, 151, 93, 211, 190, 85, 85, 216, 127}, 32}, {{105, 128, 0, 0, 0, 0, 0, 39, 122, 138, 180, 149, 75, 34, 149, 75}, 32}, {{105, 128, 0, 0, 126, 154, 168, 177, 108, 129, 154, 128, 47, 159, 137, 22}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 37, 64, 57, 72, 143, 245, 140}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 87, 247, 14, 63, 249, 40, 116, 155}, 32}, {{105, 128, 0, 0, 0, 0, 0, 14, 128, 18, 212, 50, 97, 146, 231, 193}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 32}, {{105, 128, 0, 0, 0, 0, 0, 223, 7, 27, 22, 34, 222, 93, 144, 196}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 29, 95, 219, 110}, 32}, {{105, 128, 0, 0, 0, 29, 139, 7, 149, 215, 14, 103, 40, 45, 198, 7}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32}, {{105, 128, 0, 0, 0, 0, 147, 67, 205, 70, 30, 144, 182, 140, 149, 88}, 32}, {{105, 128, 0, 157, 94, 153, 128, 168, 142, 238, 189, 123, 138, 246, 67, 57}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 82, 241, 43}, 32}, {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 138, 97, 241, 26, 175, 118}, 32}, {{105, 128, 0, 0, 0, 0, 191, 127, 77, 56, 21, 173, 199, 249, 165, 253}, 32}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 99}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 15}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 130, 125}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 44, 30}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 76, 127}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 41, 61}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 179, 124}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 2, 245}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 155}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 3}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 91}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 214}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 252, 53}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 221, 23}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 201}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 48, 240}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 53}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 48}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 97}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 49, 233}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 74, 109, 252}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 89, 162}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 30, 209, 196}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 10, 200}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 165}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 39}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 175, 50}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 201, 147}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 207, 37}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 79, 155, 50}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 137}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 35, 234}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 173}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 60, 218}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 66}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 30, 168}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 10, 172}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 91}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 241, 34}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 70, 141}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 19}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 93, 241, 184}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 60}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 45}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 235, 59, 150}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 139, 205}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 245, 200}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 32}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 188}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 1, 110, 180}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 74}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 140}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 222, 50}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 186}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 78, 210, 52}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 196, 23}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 243}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 229}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 214, 2, 21}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 194}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 108, 191}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 83, 122}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 118, 125, 94}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 116}, 237}, {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 237}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 215}, {{30, 0, 0, 0, 0, 220, 210, 91, 47, 5, 120, 229, 241, 133, 56, 81}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 217}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 228, 99, 252, 105, 158, 113, 190, 74}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 174, 144}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 72, 114, 26}, 215}, {{30, 0, 0, 0, 0, 0, 127, 11, 244, 90, 79, 211, 108, 240, 175, 50}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 110, 165, 117, 99, 124}, 215}, {{30, 0, 0, 0, 0, 83, 225, 148, 51, 173, 196, 64, 112, 86, 231, 226}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 215}, {{30, 0, 0, 184, 70, 181, 86, 85, 108, 73, 91, 41, 189, 96, 187, 181}, 215}, {{30, 0, 0, 0, 0, 231, 123, 157, 140, 153, 14, 18, 188, 194, 110, 132}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 41, 145, 43, 227, 56, 54, 17}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 29, 254, 207, 47, 236}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 255, 222}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 221, 56, 231, 88, 244, 99, 88}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 225, 232, 23, 190, 145, 114, 12, 17}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 211, 216, 125, 172, 207}, 215}, {{30, 0, 0, 0, 0, 0, 0, 100, 252, 215, 239, 126, 70, 23, 8, 199}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 194, 54, 250, 108, 131, 125, 100}, 215}, {{30, 0, 29, 170, 205, 156, 183, 2, 89, 33, 169, 224, 206, 218, 20, 5}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 167, 150, 156, 79, 153, 58, 166}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 115, 155, 221, 227}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 241, 134, 33, 20, 180}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 235, 133, 240}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 6, 80, 61, 5, 157}, 215}, {{30, 0, 3, 97, 43, 84, 169, 53, 250, 230, 225, 213, 204, 20, 247, 130}, 215}, {{30, 0, 189, 222, 157, 97, 221, 120, 168, 28, 5, 238, 185, 112, 195, 12}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 39, 0, 233, 202, 240}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 218, 239, 91, 116, 125}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 116, 253, 99, 133, 196, 195, 27}, 215}, {{30, 0, 0, 0, 0, 0, 157, 53, 222, 56, 151, 91, 130, 44, 167, 131}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 146, 39, 175}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 44, 128, 202, 142, 108, 158, 243}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 162, 241, 37, 227, 73}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 143, 12, 228, 246}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 176, 237, 115, 213, 54, 83, 127, 67}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 92, 212, 204, 234}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 166, 65, 40, 42, 189, 211, 82}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 88, 110, 154, 177, 32, 109, 109}, 215}, {{30, 0, 0, 71, 68, 197, 247, 26, 197, 200, 36, 135, 35, 3, 200, 25}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 59, 28}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 141, 244, 38, 156, 21, 122, 188}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 131, 133}, 215}, {{30, 0, 0, 0, 0, 240, 199, 175, 73, 47, 123, 27, 175, 230, 72, 11}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 194, 95, 66, 118, 11, 54, 185, 151}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 33, 245, 185}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 215}, {{30, 0, 0, 0, 0, 0, 99, 126, 40, 0, 58, 167, 130, 109, 155, 101}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 23, 20, 30, 85, 30}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 63, 141, 92, 203}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 66}, 215}, {{30, 0, 0, 0, 0, 0, 0, 235, 149, 56, 198, 191, 10, 224, 110, 148}, 215}, {{30, 0, 0, 0, 0, 250, 216, 62, 55, 184, 95, 122, 59, 95, 154, 104}, 215}, {{30, 0, 0, 84, 107, 151, 201, 175, 89, 8, 54, 227, 126, 114, 224, 217}, 215}, {{30, 0, 244, 58, 249, 116, 169, 76, 119, 45, 20, 87, 235, 51, 85, 112}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 187, 168, 56, 141, 56, 228, 198}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 215, 219, 127}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 30}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 137, 33, 235, 219}, 215}, {{30, 0, 0, 0, 0, 0, 0, 142, 151, 184, 94, 68, 110, 206, 36, 155}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 27, 42, 205}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 176, 4, 79, 126, 103, 177, 252, 220, 130}, 215}, {{30, 0, 0, 0, 0, 0, 105, 166, 208, 208, 7, 200, 240, 190, 236, 55}, 215}, {{30, 0, 165, 18, 51, 187, 46, 213, 107, 126, 73, 210, 242, 114, 209, 65}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 49, 170, 62, 213, 171, 84, 253, 39}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 84, 70}, 215}, {{30, 0, 0, 0, 0, 0, 23, 200, 8, 170, 41, 124, 199, 166, 40, 57}, 215}, {{30, 0, 119, 162, 158, 204, 84, 171, 129, 125, 66, 243, 90, 135, 60, 136}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 219, 195, 152, 60, 110}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 144, 241}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 175}, 215}, {{30, 0, 0, 0, 115, 118, 72, 57, 123, 159, 171, 54, 184, 188, 129, 69}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 19, 16, 201, 203, 12, 16, 207, 253}, 215}, {{30, 0, 26, 124, 188, 57, 23, 156, 167, 216, 55, 58, 157, 29, 129, 7}, 215}, {{30, 0, 0, 0, 0, 0, 0, 48, 150, 186, 129, 65, 3, 172, 29, 85}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 244, 148, 242}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 174, 47, 144, 150}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 206, 182, 41, 201, 97, 103, 5, 60}, 215}, {{30, 0, 0, 0, 0, 0, 0, 184, 14, 111, 165, 165, 226, 178, 32, 165}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 9}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 206, 186, 223, 177}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 19, 248, 108, 196}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 203, 64, 87, 115, 58}, 215}, {{30, 0, 0, 0, 0, 0, 0, 220, 119, 155, 159, 234, 132, 229, 117, 91}, 215}, {{30, 0, 12, 172, 90, 5, 208, 83, 32, 92, 70, 167, 145, 111, 242, 203}, 215}, {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 112, 27, 160}, 215}, {{30, 0, 18, 98, 16, 14, 64, 74, 164, 205, 161, 113, 182, 233, 160, 158}, 215}, {{30, 0, 0, 0, 0, 0, 0, 5, 145, 129, 105, 156, 71, 42, 107, 51}, 215}, {{14, 232, 48, 0, 0, 0, 0, 0, 190, 37, 182, 11, 226, 146, 107, 147}, 138}, {{14, 232, 48, 0, 28, 229, 52, 164, 77, 121, 90, 172, 25, 126, 124, 136}, 138}, {{14, 232, 48, 0, 0, 148, 179, 122, 94, 159, 207, 19, 198, 193, 2, 190}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 199}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 115, 202, 89}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 98, 240, 54, 34, 46}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 221, 87, 5, 226, 102, 60, 2, 58, 17, 214, 39}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 37, 206, 189, 94, 93, 246, 188}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 250, 215, 18, 250, 191, 19, 193, 157, 198, 182, 79}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 138}, {{14, 232, 48, 0, 0, 164, 189, 193, 49, 237, 208, 141, 120, 17, 49, 221}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 213, 162, 41}, 138}, {{14, 232, 48, 0, 0, 0, 63, 251, 9, 118, 107, 129, 47, 195, 113, 82}, 138}, {{14, 232, 48, 0, 0, 0, 0, 84, 178, 159, 46, 76, 168, 221, 8, 55}, 138}, {{14, 232, 48, 0, 0, 0, 0, 212, 140, 109, 56, 57, 143, 146, 30, 66}, 138}, {{14, 232, 48, 0, 0, 0, 0, 132, 222, 108, 108, 19, 34, 124, 8, 208}, 138}, {{14, 232, 48, 0, 0, 42, 156, 181, 2, 82, 3, 136, 211, 197, 152, 142}, 138}, {{14, 232, 48, 0, 0, 0, 0, 226, 65, 131, 182, 216, 145, 52, 82, 230}, 138}, {{14, 232, 48, 55, 245, 170, 21, 72, 67, 216, 77, 163, 216, 138, 179, 83}, 138}, {{14, 232, 48, 0, 211, 159, 18, 147, 212, 213, 91, 7, 126, 136, 134, 77}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 214, 105}, 138}, {{14, 232, 48, 0, 0, 0, 9, 127, 223, 74, 249, 237, 239, 56, 13, 88}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 111, 40}, 138}, {{14, 232, 48, 0, 0, 0, 0, 206, 129, 36, 188, 91, 134, 96, 117, 215}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 42, 233, 249, 161, 227}, 138}, {{14, 232, 48, 0, 0, 0, 137, 6, 110, 128, 14, 98, 188, 229, 207, 48}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 107, 76, 93, 254, 34}, 138}, {{14, 232, 48, 0, 154, 92, 22, 16, 46, 246, 22, 6, 111, 111, 236, 6}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 170}, 138}, {{14, 232, 48, 0, 0, 218, 151, 63, 210, 103, 20, 101, 118, 206, 233, 92}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 186, 67, 41, 236, 73, 85, 147, 8}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 68, 109, 205, 157, 239, 189}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 138}, {{14, 232, 48, 0, 0, 0, 0, 159, 123, 12, 164, 163, 103, 201, 110, 86}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 138}, {{14, 232, 48, 0, 91, 15, 61, 250, 224, 95, 98, 201, 124, 64, 120, 148}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 183, 87, 237, 109, 197, 73, 187}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 82, 37, 171}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 96, 213, 118, 194, 44, 17, 20, 12}, 138}, {{14, 232, 48, 229, 122, 50, 88, 179, 74, 57, 204, 135, 226, 165, 10, 52}, 138}, {{14, 232, 48, 0, 60, 20, 164, 157, 131, 250, 22, 55, 115, 254, 186, 221}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 85}, 138}, {{14, 232, 48, 0, 0, 172, 148, 124, 151, 201, 150, 40, 209, 218, 72, 96}, 138}, {{14, 232, 48, 0, 0, 0, 0, 247, 182, 165, 150, 127, 5, 85, 224, 108}, 138}, {{14, 232, 48, 0, 0, 0, 50, 195, 32, 57, 67, 75, 152, 79, 61, 37}, 138}, {{14, 232, 48, 0, 0, 0, 177, 182, 142, 175, 3, 128, 190, 157, 191, 204}, 138}, {{14, 232, 48, 0, 0, 0, 60, 108, 232, 33, 49, 58, 137, 29, 214, 141}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 88, 236, 234, 224, 166}, 138}, {{14, 232, 48, 0, 0, 0, 0, 230, 46, 158, 78, 121, 75, 233, 90, 23}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 190, 74, 199}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 176, 157, 9, 207, 41, 30, 25}, 138}, {{14, 232, 48, 0, 209, 150, 139, 11, 20, 33, 164, 63, 41, 203, 142, 243}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 58, 33, 234}, 138}, {{14, 232, 48, 0, 0, 0, 0, 34, 230, 23, 249, 233, 212, 51, 63, 222}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 124}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 113, 123, 97, 131, 206}, 138}, {{14, 232, 48, 0, 216, 77, 110, 172, 148, 5, 81, 11, 172, 120, 37, 81}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{14, 232, 48, 0, 0, 0, 0, 139, 194, 59, 71, 157, 83, 161, 253, 227}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 79, 87, 170, 138, 241, 13, 68}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 136, 107, 237, 151, 103, 166}, 138}, {{14, 232, 48, 0, 0, 0, 111, 156, 127, 115, 132, 254, 143, 121, 45, 10}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 9, 154}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 238, 14}, 138}, {{14, 232, 48, 0, 0, 0, 128, 131, 191, 62, 233, 136, 205, 149, 194, 157}, 138}, {{14, 232, 48, 0, 0, 0, 30, 240, 158, 172, 216, 163, 55, 209, 120, 74}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 228}, 138}, {{14, 232, 48, 0, 0, 0, 0, 90, 250, 159, 151, 86, 235, 105, 149, 30}, 138}, {{14, 232, 48, 0, 0, 0, 105, 191, 109, 117, 143, 213, 161, 111, 156, 132}, 138}, {{14, 232, 48, 0, 41, 121, 80, 153, 194, 63, 236, 115, 196, 226, 22, 29}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 57}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 128, 8, 184, 127, 64, 216, 151}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 247}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 48, 98, 35, 151, 42, 255}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 236, 199, 37, 232, 141, 55, 25, 221}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 93, 51, 204, 48, 251}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 60, 138, 119, 10, 91, 244}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 129, 3, 35, 19, 255, 32}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 21, 1, 53, 56, 100, 77, 114, 164}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 44, 7, 15, 67, 68, 115, 19, 2}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 122}, 138}, {{14, 232, 48, 0, 0, 157, 138, 158, 71, 149, 252, 110, 203, 233, 2, 26}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 165, 177, 248, 101, 156, 25, 51}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 147, 219, 47, 214, 126, 68, 245, 69}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 125, 36, 208, 240, 147, 253, 28}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 37, 122}, 138}, {{14, 232, 48, 0, 158, 219, 110, 14, 151, 26, 124, 166, 61, 94, 233, 86}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 62, 37, 202, 248, 33, 67, 251, 221}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 184, 217, 104, 240, 6, 136}, 138}, {{14, 232, 48, 0, 0, 0, 157, 139, 134, 215, 117, 163, 129, 251, 158, 155}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 192, 81, 138, 96, 84, 188}, 138}, {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 138}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 202}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 248}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 110}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 40}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 113}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 3}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 33}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 73}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 242}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 101}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 219}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 9}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 40}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 247}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 47}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 28}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 34}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 109}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 142}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 36}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 73}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 127}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 13}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 106, 157, 151}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 92, 54}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 100, 70, 186, 36}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 236}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 84, 123, 80}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 247}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 165, 221}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 204, 118}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 179, 233, 182}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 112}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 125, 253}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 70}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 237, 72, 234}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 119, 253}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 113, 176}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 14, 23}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 136, 19, 225, 202}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 170, 232, 148, 60}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 110}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 101, 76, 72}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 236, 91, 50}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 165}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 62, 98, 194}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 114, 205, 225}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 121, 115}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 204, 209, 254, 110}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 72, 103}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 193, 252}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 3, 45, 95, 26}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 8, 80}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 95, 29}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 82, 211}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 28, 197}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 179, 94, 230}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 253}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 75, 106, 230}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 218, 180, 85, 209}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 208}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 139, 19}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 220, 216, 133}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 130}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 130}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 104, 45}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 200, 168}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 120, 86, 133, 74}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 119, 215}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 79, 151, 133}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 40}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 198, 108}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 227, 197}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 53}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 205, 232}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 89}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 140, 9}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 181, 243}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 114, 245, 50, 112}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 224, 44}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 89, 112}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 19, 201, 202, 203}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 192, 53, 70}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 254}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 22}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 84}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 82, 214, 88}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 238, 229, 160}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 21, 169, 215}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 202}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 222, 208, 9, 178}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 218, 133, 29}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 37, 169, 251}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 110}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 187}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 247, 108}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 208, 33}, 43}, {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 73, 196}, 43}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 107}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 220}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 146}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 14}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 29}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 61}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 193}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 175}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 125}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 118}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 184}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 221}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 172}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 142}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 4}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 165}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 53}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 255}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 104}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 207}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 126}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 161}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 213}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 203}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 202}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 102}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 39}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 119}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 148}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 213}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 100}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 244}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 10}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 204}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 99}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 119}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 167}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 153}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 147}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 16}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 188}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 98}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 14}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 75}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 74}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 51}, 88}, {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 88}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 142}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 6}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 184}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 255}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 244}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 169}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 79}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 91}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 11, 99}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 34}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 213, 183, 205, 43}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 161, 75, 11}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 1}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 224, 193, 120, 60}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 200}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 112, 76, 235}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 171, 182, 155, 97, 2, 127}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 117, 119, 186, 125}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 154, 43}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 119, 163}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 67, 211, 210}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 215, 199, 223, 179, 116}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 38, 41, 198, 231, 112, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 31, 58}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 200, 62, 80, 21, 235}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 176, 8, 211, 75, 191, 88}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 197, 90, 173, 110, 238}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 120, 92}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 185, 20, 214}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 35}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 109, 66, 2, 5, 67}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 152, 66}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 166, 240, 88}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 10, 93, 84, 183, 155, 129, 38}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 171, 217, 69, 254, 48, 20}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 10, 102, 225, 39}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 166, 91, 202}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 30, 252, 36, 121}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 51, 186, 133, 251, 124}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 172}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 202, 168, 154, 100, 66, 108}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 146}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 23, 112, 127}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 13, 109, 120}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 235, 145}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 229}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 192, 153, 6}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 9, 126, 141, 45, 111, 115}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 60, 62, 32, 42}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 200, 231, 14}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 158, 45, 17, 115, 88, 223}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 252}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 161, 54, 13, 238}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 228, 189, 232, 141, 133}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 97, 179}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 127, 137, 132, 64, 198}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 9, 111, 65, 133, 37, 30}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 165, 70, 15, 2, 167, 215}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 249, 226, 195, 13, 137, 48}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 144, 160, 38, 252, 43, 53}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 197, 215}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 211}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 188, 180, 230, 59}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 137, 247, 116, 41}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 61, 24, 134}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 18, 11, 113, 206, 14}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 133, 242, 220, 115, 121}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 69, 58, 37, 26}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 189, 80, 26, 170}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 197, 56, 22, 35, 113}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 145, 239, 94}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 177, 216, 92}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 215}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 31, 175, 61}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 157, 208, 46, 197, 234, 3}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 23, 176}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 215}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 235}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 128, 57, 44, 210}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 51, 25, 188}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 238, 215, 241, 213}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 116, 145, 29, 133, 55, 79, 223}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 66, 49}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 68, 38, 161, 109, 235, 214, 8}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 32}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 199, 166, 251, 30, 41, 33}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 208, 134, 141, 103, 156}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 22, 218}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 23, 236, 188, 12, 37}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 162, 132, 20}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 68, 171, 140, 183, 65, 83, 2}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 125}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 195}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 42}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 178, 137, 115}, 140}, {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 237, 221, 245, 178, 213}, 140}, {{0, 213, 77, 244, 64, 0, 0, 0, 79, 241, 103, 108, 137, 252, 89, 17}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 130, 169, 156, 110, 74, 218, 191}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 184, 3, 89, 206, 198, 108, 141, 73}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 26, 25, 96, 255, 25, 67, 193}, 65}, {{0, 213, 77, 244, 64, 232, 55, 134, 59, 108, 161, 78, 104, 234, 99, 199}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 139, 201, 227, 18, 38, 225, 204, 68, 132}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 95, 173, 177, 237, 26, 106, 187}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 160, 243, 119, 135, 143}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 63, 55, 50, 239, 87, 208}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 144, 149, 165}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 108, 38, 55, 134, 137, 38, 194, 216}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 223, 61, 252, 18, 150, 252, 235}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 206, 69, 89, 44, 105}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 118, 171, 43, 153, 13, 112, 125}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 95, 136, 28, 192}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 29, 43, 142}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 245, 217, 247, 36, 240}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 48}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 48, 63, 127, 30, 76, 184, 196, 199}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 149, 240, 180, 188, 60, 130, 22, 221}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 72, 146, 0, 123, 158, 206, 3, 181, 157}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 174, 115, 79}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 46, 103, 64, 77, 242, 182}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 187, 55, 19, 233, 245, 247}, 65}, {{0, 213, 77, 244, 64, 0, 0, 82, 238, 158, 0, 168, 178, 67, 132, 165}, 65}, {{0, 213, 77, 244, 64, 0, 0, 227, 187, 146, 166, 142, 99, 250, 3, 66}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 170, 146, 168, 55, 134}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 216, 66, 96, 144, 19, 52}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 146, 128, 238, 203, 62, 220, 23}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 63, 83, 226, 249, 234, 84, 221, 229}, 65}, {{0, 213, 77, 244, 64, 0, 213, 227, 254, 82, 78, 19, 228, 119, 57, 142}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 65}, {{0, 213, 77, 244, 64, 0, 35, 249, 145, 158, 118, 231, 38, 221, 112, 147}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 254, 50, 99, 190, 109, 218}, 65}, {{0, 213, 77, 244, 64, 0, 101, 233, 125, 207, 47, 244, 133, 220, 48, 238}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 116, 64, 101, 40}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 66, 247, 89, 8, 135, 99}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 124}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 149, 172, 191, 72, 128, 127}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 107, 233, 23}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 82, 254, 162}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 238, 103, 206, 49}, 65}, {{0, 213, 77, 244, 64, 0, 218, 181, 157, 100, 31, 51, 115, 47, 40, 51}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 69, 117, 42, 3, 19, 178}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 100, 86, 111, 25, 184, 208, 218}, 65}, {{0, 213, 77, 244, 64, 0, 0, 33, 170, 155, 93, 34, 14, 107, 34, 39}, 65}, {{0, 213, 77, 244, 64, 0, 29, 126, 254, 30, 128, 59, 179, 62, 99, 156}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 123, 204, 42, 234, 249}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 65}, {{0, 213, 77, 244, 64, 0, 0, 109, 255, 71, 106, 29, 134, 237, 157, 166}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 65}, {{0, 213, 77, 244, 64, 0, 124, 198, 137, 163, 24, 156, 169, 215, 220, 35}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 11, 79, 127, 12, 136, 152, 87}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 73, 9, 204, 126, 171, 193, 81, 5}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 19, 65, 157, 234, 27, 98, 158}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 85, 52, 94, 182, 186, 113, 51, 71}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 182, 80, 40, 166, 126, 254}, 65}, {{0, 213, 77, 244, 64, 0, 0, 242, 72, 211, 151, 200, 139, 31, 42, 181}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 154}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 8, 237, 64, 35, 170, 117}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 203, 138, 145, 16, 195, 127, 222}, 65}, {{0, 213, 77, 244, 64, 0, 0, 20, 64, 204, 235, 31, 250, 142, 77, 206}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 188}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{0, 213, 77, 244, 64, 0, 0, 80, 240, 92, 84, 95, 233, 20, 127, 45}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 175, 185, 167, 103}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 20, 249, 244, 176, 7, 250, 59}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 96, 230, 56, 50, 236, 15, 49, 96}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 62, 103, 1, 53, 135, 79, 243, 2}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 11, 101, 68}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 65}, {{0, 213, 77, 244, 64, 0, 86, 229, 59, 122, 191, 31, 30, 92, 5, 96}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 219, 18, 112, 197, 181}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 166, 85, 170, 41, 1, 224, 175, 46}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 203, 11, 0, 10}, 65}, {{0, 213, 77, 244, 64, 0, 211, 12, 153, 166, 186, 63, 77, 237, 254, 255}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 28, 54, 155}, 65}, {{0, 213, 77, 244, 64, 0, 0, 5, 50, 118, 190, 199, 238, 77, 26, 199}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 108, 191, 157, 255, 53, 167}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 81}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 249, 171, 74, 124, 42}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 221, 123, 122, 213}, 65}, {{0, 213, 77, 244, 64, 0, 143, 133, 200, 141, 91, 50, 95, 10, 244, 205}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 65}, {{0, 213, 77, 244, 64, 0, 0, 0, 58, 91, 223, 213, 187, 2, 177, 16}, 65}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 201}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 61, 76, 188}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 61, 29, 190}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 184, 179, 97, 208, 185}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 40, 26, 7, 219, 28, 103}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 143}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 47, 16, 176, 202, 188, 250}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 95, 133, 17, 60}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 209, 152, 9, 175, 193}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 7, 10, 23, 22, 202}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 202}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 195, 157}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 8, 252, 59, 222, 26, 129}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 104, 71, 55, 189}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 22, 236}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 126, 254, 160}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 186, 210, 224}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 242, 20, 226}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 240, 89}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 208, 152}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 23, 120}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 226, 111}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 192, 58, 150}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 194}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 207, 118, 116, 224}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 117, 96}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 37}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 136, 155, 241, 212}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 64, 172, 130, 75, 139}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 115, 185, 173, 212, 160}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 19, 126, 208}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 165, 225, 30, 191, 192}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 52}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 106, 65, 192, 240, 194}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 86, 23, 221, 120}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 11, 107, 238, 63}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 147, 25, 164, 172, 193, 118}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 72}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 83}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 74, 41, 130, 54}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 104, 21, 218, 134, 143, 74}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 255, 77}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 29, 219, 78}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 232, 238, 85, 108}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 125}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 120}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 30, 1, 232, 3, 237}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 82}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 127, 152}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 251, 223, 61, 208, 226, 36}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 175, 49, 141, 27, 19, 65}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 81, 151, 250, 12, 37, 154}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 111, 244, 192, 237, 45, 54}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 125, 212, 189, 82, 14}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 251, 179, 30}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 109, 99, 192, 25}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 85, 112, 168, 163, 10}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 221, 48, 193, 154}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 62, 83, 66, 217, 74, 111}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 66, 199, 32}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 9}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 191, 219, 88, 231}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 106, 33}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 2, 18, 171}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 224, 152, 104, 199, 3}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 111, 159}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 182, 187}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 99, 96, 191}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 160, 203, 206, 93, 136}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 18, 32, 1, 125, 72, 11}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 202, 145, 57}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 197}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 125, 131}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 194, 79, 21}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 54, 89, 193, 100, 5}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 39, 132, 117}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 74, 176, 100, 200, 30}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 62, 193}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 61, 66}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 129, 126, 187, 164, 97, 161}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 154, 220, 220, 53, 89}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 175}, 69}, {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 94, 169, 23}, 69}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 23, 169, 64, 126, 26, 130, 155}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 56, 154, 210, 230, 168, 19, 161, 50}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 16, 49, 33, 118, 20, 17, 104, 232}, 170}, {{21, 253, 4, 47, 0, 0, 168, 66, 201, 122, 154, 216, 190, 97, 167, 228}, 170}, {{21, 253, 4, 47, 0, 0, 165, 78, 199, 127, 199, 51, 232, 7, 158, 143}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 4, 35, 180, 13, 83, 164, 155}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 92, 64, 228, 25}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 125, 40, 23, 112, 57}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 123, 39}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 29, 78, 32, 49, 63, 201}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 76, 15, 102, 112}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 60, 245, 224, 172}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 139, 75, 81, 233, 45, 49, 236, 172, 93, 37, 131}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 133, 130, 51, 121, 214, 211, 109, 41}, 170}, {{21, 253, 4, 47, 0, 0, 0, 232, 35, 211, 101, 190, 8, 185, 250, 146}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 65, 19, 148, 152, 69}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 184, 17, 206, 228, 221}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 143, 171, 122, 188, 223, 75}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 150, 38}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 52, 132, 156, 43, 50, 117, 32, 2}, 170}, {{21, 253, 4, 47, 0, 0, 0, 229, 81, 213, 227, 124, 24, 249, 170, 81}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 88, 61, 239, 192, 253, 199, 65}, 170}, {{21, 253, 4, 47, 0, 0, 146, 250, 212, 11, 50, 1, 249, 37, 77, 157}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2, 106, 147}, 170}, {{21, 253, 4, 47, 0, 0, 0, 92, 223, 193, 159, 183, 224, 57, 75, 172}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 69, 10, 62, 206, 205, 138, 67}, 170}, {{21, 253, 4, 47, 0, 0, 0, 2, 212, 50, 83, 7, 65, 216, 149, 21}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 103, 243, 80, 94, 142}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 171, 189, 169, 187, 209}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 55, 175, 140, 178}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 170}, {{21, 253, 4, 47, 0, 0, 76, 17, 41, 186, 2, 140, 29, 21, 83, 245}, 170}, {{21, 253, 4, 47, 0, 0, 0, 101, 103, 91, 108, 201, 69, 99, 107, 133}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 217, 157, 248, 13, 87}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 190, 210, 186, 147, 34, 44}, 170}, {{21, 253, 4, 47, 0, 137, 255, 193, 200, 253, 156, 121, 163, 116, 48, 199}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 63}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 66, 114, 45, 22}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 149, 53, 8, 47}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 170}, {{21, 253, 4, 47, 0, 0, 0, 105, 211, 151, 184, 14, 201, 29, 141, 12}, 170}, {{21, 253, 4, 47, 0, 89, 170, 0, 170, 143, 87, 177, 66, 240, 225, 87}, 170}, {{21, 253, 4, 47, 0, 0, 6, 105, 30, 118, 172, 12, 147, 102, 156, 24}, 170}, {{21, 253, 4, 47, 0, 0, 0, 124, 118, 13, 43, 42, 134, 246, 148, 246}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 183, 8, 97, 236, 142}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 148, 6, 7, 209, 21}, 170}, {{21, 253, 4, 47, 0, 0, 0, 77, 66, 204, 209, 142, 1, 34, 110, 157}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 172, 157, 212, 39, 192}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 188, 178, 23, 75, 194, 139}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 32, 160, 62, 45}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 161, 64, 36, 113, 242}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 226, 147, 20, 118}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 93, 231, 93, 203, 224, 76}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 114}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 238, 93, 93, 144, 230, 153, 237, 24, 110, 14, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 12, 195, 161, 229}, 170}, {{21, 253, 4, 47, 0, 70, 2, 250, 158, 184, 233, 230, 149, 72, 211, 38}, 170}, {{21, 253, 4, 47, 0, 22, 104, 183, 32, 229, 232, 232, 37, 3, 249, 183}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 26, 31, 214, 17, 141, 102}, 170}, {{21, 253, 4, 47, 0, 0, 0, 59, 17, 89, 135, 141, 147, 38, 23, 18}, 170}, {{21, 253, 4, 47, 0, 0, 0, 188, 78, 154, 91, 62, 94, 192, 230, 163}, 170}, {{21, 253, 4, 47, 0, 3, 252, 224, 238, 45, 250, 101, 111, 244, 147, 135}, 170}, {{21, 253, 4, 47, 0, 0, 0, 237, 54, 9, 228, 249, 191, 163, 118, 77}, 170}, {{21, 253, 4, 47, 0, 0, 0, 160, 219, 198, 174, 44, 234, 16, 134, 109}, 170}, {{21, 253, 4, 47, 0, 0, 0, 182, 111, 94, 233, 97, 78, 248, 242, 97}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 151, 59}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 69, 104}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 99, 166, 118, 49, 69, 243}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 9}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 26, 38, 123, 213, 160, 165, 218}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 242}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 188, 56}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 23}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 155, 185, 217, 181, 50, 154, 169, 35}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 70, 170, 208, 252, 239}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 105}, 170}, {{21, 253, 4, 47, 0, 78, 60, 160, 117, 146, 191, 244, 2, 84, 109, 36}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 133, 7, 132, 217, 42, 125, 57, 47}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 137, 3, 35, 51, 133}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 75, 10, 210, 16, 229, 39, 103}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 22, 227, 86, 51}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 216, 174, 33, 97, 114, 96, 152}, 170}, {{21, 253, 4, 47, 0, 0, 0, 80, 80, 68, 2, 95, 137, 229, 205, 193}, 170}, {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 50}, 170}, {{21, 253, 4, 47, 0, 0, 212, 138, 198, 36, 126, 122, 63, 85, 163, 118}, 170}, {{5, 249, 186, 133, 68, 0, 0, 0, 230, 56, 109, 216, 113, 133, 196, 94}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 135}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 39, 88, 132}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 57, 70, 207}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 213, 175, 35, 203, 223}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 76, 50, 23, 86, 245, 194, 234, 63}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 85, 125, 208, 180, 107, 6, 208, 63}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 36, 230, 8, 244, 79, 47}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 195, 89, 197, 106}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 99, 144, 4, 122}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 1, 9, 134, 174, 113, 197, 178, 73}, 192}, {{5, 249, 186, 133, 68, 0, 145, 165, 39, 153, 70, 84, 164, 156, 229, 224}, 192}, {{5, 249, 186, 133, 68, 0, 145, 118, 0, 65, 198, 140, 203, 243, 105, 44}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 127, 143, 206}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 99, 97, 232}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 5, 241, 11, 87, 85, 170}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 116, 73, 64, 106, 175, 167}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 205, 64, 73, 247, 72}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 195, 6, 29, 146, 62, 234, 76, 147}, 192}, {{5, 249, 186, 133, 68, 0, 151, 106, 205, 37, 110, 215, 253, 248, 21, 113}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 247, 114, 127, 235, 146, 181, 81}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 162, 51, 72, 213, 107, 60, 24, 244}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 179, 251, 26, 248}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 132, 116, 94, 219, 237}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 187, 107, 62}, 192}, {{5, 249, 186, 133, 68, 0, 0, 79, 210, 142, 169, 22, 222, 103, 8, 58}, 192}, {{5, 249, 186, 133, 68, 0, 226, 171, 156, 51, 71, 73, 195, 201, 50, 201}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 27, 150, 133, 16, 51}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 88, 144, 156, 112, 46}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 24, 78, 143, 227, 132}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 7, 147, 229, 8, 177, 95, 242, 167, 57}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 177, 225, 139, 5, 43, 16, 190}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 134, 205, 117, 190}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 71, 216, 20, 16, 207, 234, 132}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 134, 196, 209, 53}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 42, 159, 119, 14, 248, 255, 2}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 248, 106, 149, 172}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 75, 229, 71, 237, 254}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 53, 154, 93, 210, 35, 63, 197}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 121, 194, 187, 2, 22}, 192}, {{5, 249, 186, 133, 68, 0, 224, 51, 185, 235, 169, 102, 254, 105, 148, 68}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 227, 186, 44, 162}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 180, 233, 46, 205, 141, 117}, 192}, {{5, 249, 186, 133, 68, 0, 139, 72, 188, 14, 249, 226, 234, 26, 168, 190}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 4, 37, 210, 232}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 156, 249, 185, 239, 141, 252, 123}, 192}, {{5, 249, 186, 133, 68, 0, 0, 142, 82, 26, 42, 103, 107, 157, 41, 217}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 245, 154, 171, 2}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 215, 181, 175, 238, 123, 187}, 192}, {{5, 249, 186, 133, 68, 0, 0, 23, 194, 3, 131, 122, 102, 170, 246, 188}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 241, 169, 2, 82, 184, 254, 33, 251, 13}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 39, 224, 94, 196, 137, 136}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 199, 73, 58, 30}, 192}, {{5, 249, 186, 133, 68, 0, 0, 211, 125, 241, 218, 220, 247, 33, 45, 83}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 195, 179, 89, 135}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 224, 132, 72}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 96, 246, 159, 144, 190, 18, 157, 45}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 108}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 127, 141, 142, 2, 235}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 183, 180, 99, 121, 197, 64}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 163, 71, 173, 21, 93}, 192}, {{5, 249, 186, 133, 68, 0, 25, 137, 222, 102, 225, 8, 204, 11, 49, 228}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 15}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 119, 226, 252, 33, 137, 39, 243}, 192}, {{5, 249, 186, 133, 68, 0, 140, 176, 110, 25, 178, 197, 197, 148, 137, 112}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 172}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 51, 151, 187, 94, 133, 155, 15, 48}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 176, 205, 184, 142, 228, 160, 54}, 192}, {{5, 249, 186, 133, 68, 0, 0, 7, 212, 131, 85, 195, 192, 195, 170, 139}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 160, 96, 198, 249, 9}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 148, 178, 49, 190, 46, 112, 136, 223}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 37, 80, 83, 223, 232, 144, 73, 193}, 192}, {{5, 249, 186, 133, 68, 0, 0, 88, 83, 194, 242, 148, 181, 191, 250, 188}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 76, 128, 101}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 160, 224, 144}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 122, 255, 17}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 173, 25, 138, 110}, 192}, {{5, 249, 186, 133, 68, 0, 95, 119, 7, 206, 110, 174, 61, 234, 238, 209}, 192}, {{5, 249, 186, 133, 68, 0, 0, 183, 195, 55, 50, 3, 66, 3, 182, 196}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 50, 43, 146, 10}, 192}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 227, 210, 206}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 248}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 34, 57}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 25, 147, 22, 251}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 81, 62, 144, 25}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 228, 153, 180}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 26, 180, 127, 76}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 138, 173, 173, 220}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 219, 222}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 232, 20, 3, 128}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 182, 150, 144, 8}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 53, 178}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 57, 102}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 60, 98}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 235}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 37, 250}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 125, 64}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 190}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 38, 149}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 118, 15, 184}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 37, 82}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 61, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 248, 53}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 55}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 198}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 61, 189}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 127, 92, 242, 78}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 104, 185, 219, 203}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 149, 115, 245, 78}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 172}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 36, 44}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 212, 158, 14, 79}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 137, 71, 41}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 122, 120, 176, 128}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 214, 157, 20}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 73, 148}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 186, 206, 26}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 244, 30, 6}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 20}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 202}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 190, 245, 114}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 140, 190, 198, 22}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 89, 101}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 134, 70, 240, 125}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 176}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 55, 41, 186}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 218, 99, 143, 67}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 203, 59, 228, 112}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 184}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 12}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 149}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 190, 81}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 180, 94}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 9, 214, 238, 211}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 129}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 102, 213, 164, 74}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 251, 227}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 108, 91, 83}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 247, 96, 30, 22}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 106, 159}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 225, 6}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 153, 140, 95, 14}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 75, 36, 239}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 155}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 125, 144, 230, 213}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 66, 199}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 172, 59, 189}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 109, 63, 75}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 158, 115, 124, 201}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 154, 33, 123}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 115}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 39, 175}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 144, 167}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 128, 84}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 164, 249}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 39}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 146, 161}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 42, 31, 207}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 248, 86, 58}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 10}, 21}, {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 109, 167}, 21}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 34, 195, 38, 41, 131, 11, 60}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 86, 82, 179, 198}, 35}, {{242, 227, 20, 73, 150, 196, 0, 240, 53, 23, 178, 225, 255, 142, 39, 179}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 164, 59, 135, 220, 13, 159, 177, 91}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 165, 93, 251, 214, 58, 143, 209}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 106, 27, 20, 46, 193}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 39, 136, 184, 228, 15, 171}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 11, 99, 240, 67, 214}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 99, 218, 202, 25, 229, 195, 250}, 35}, {{242, 227, 20, 73, 150, 196, 0, 142, 219, 237, 156, 184, 152, 191, 151, 163}, 35}, {{242, 227, 20, 73, 150, 196, 0, 12, 149, 71, 171, 121, 252, 12, 105, 141}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 23, 136}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 8, 7, 50, 135, 28}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 249, 85, 161, 227, 74, 129}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 178, 172, 74, 153, 10, 251}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 240, 73, 168, 149, 180}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 205, 62}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 135, 230, 44, 238, 159, 6, 118}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 73, 102}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 88, 250}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 59, 194, 14, 240, 42, 100, 121, 24}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 147, 123, 75, 247, 59, 163, 252}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 63, 104, 218, 188}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 103, 169}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 32, 235, 107, 1, 209}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 226, 209, 145, 172, 66, 194}, 35}, {{242, 227, 20, 73, 150, 196, 0, 241, 20, 201, 157, 235, 173, 62, 197, 161}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 139, 34, 168, 74, 91, 137}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 1, 147, 188, 239, 24, 129, 218, 39}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 170, 29, 115, 216}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 115, 46, 170, 23}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 76, 73, 43, 226, 138}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 252, 182, 13, 163, 70, 164, 123}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 40, 70}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 145, 30, 68, 70}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 153, 95, 172, 111, 197, 122, 39}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 160, 23, 205}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 40, 203, 115, 108, 235, 65, 238}, 35}, {{242, 227, 20, 73, 150, 196, 0, 209, 156, 235, 11, 225, 223, 116, 200, 19}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 52, 192, 100, 199, 14, 49, 118, 6}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 155, 82, 109, 32}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 101, 171, 174, 241}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 214, 95, 141, 188, 159}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 238, 154, 158, 85, 223}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 70, 102, 252, 56, 253, 205}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 43, 214, 73, 75}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 125, 231, 63, 11, 169, 131, 194, 121}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 40, 140, 196, 177, 144}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 240, 111, 227, 177}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 62, 232}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 127, 53, 129, 86, 29, 232, 87, 151, 230}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 147, 231, 167, 12}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 156, 227, 30, 139, 159}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 230, 173, 7, 110, 144}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 130, 167, 89}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 173, 39, 103, 98, 16}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 110, 47}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 143, 210, 221, 160, 194, 19, 225}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 186, 36, 76, 43, 205, 156}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 45, 234}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 191, 144, 221, 127, 122, 253}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 27, 117, 77, 235, 116}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 18, 224, 226, 232, 25, 213}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 221, 171, 180, 167, 203, 137, 128}, 35}, {{242, 227, 20, 73, 150, 196, 162, 23, 239, 97, 183, 199, 84, 78, 225, 139}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 21, 160, 221, 126, 101}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 159, 101, 53, 22, 110, 54, 247}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 234, 239, 66, 64, 180, 176}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 230, 118, 147}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 186, 38, 206, 13, 48, 6, 215, 55}, 35}, {{242, 227, 20, 73, 150, 196, 0, 208, 219, 64, 132, 106, 161, 35, 210, 66}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 107, 46, 175}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 228, 154, 133, 141}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 87, 99, 49, 235, 154, 181, 19, 92}, 35}, {{242, 227, 20, 73, 150, 196, 0, 97, 143, 15, 31, 196, 135, 11, 87, 241}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 138, 135, 54}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 211, 69, 246, 183, 182}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 105, 121, 235, 245, 107}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 227, 241}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 194, 64, 121, 208, 152, 168}, 35}, {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 83, 108, 82, 170}, 35}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 151, 191, 89, 150}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 114, 8, 249}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 249}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 255, 238, 54, 197, 84}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 127, 88, 76}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 228, 51, 5}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 192, 234, 187}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 253, 37}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 150, 75}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 122, 240, 222, 46}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 131}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 187, 36}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 183, 131}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 133}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 152, 114}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 160, 79, 16, 240}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 29}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 39}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 252, 51, 65, 104}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 79}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 153, 27, 149, 68}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 199}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 98, 114, 185, 28, 253, 173}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 210, 9}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 55, 115, 66, 127}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 251, 225, 219, 208}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 120}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 59}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 117, 178, 147, 91}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 4, 254, 89, 96}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 49, 191}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 57, 189, 49, 80}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 243, 228}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 14, 88}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 124, 51, 6}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 91, 143, 219}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 38, 47, 216}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 253}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 115, 79, 69, 61, 253, 233}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 223, 27}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 87, 176, 194, 157, 121, 201}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 203}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 45, 20, 46, 155, 133, 160}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 102, 171}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 146, 160}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 221, 152}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 49, 134}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 130, 90, 51, 80, 210}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 130}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 81, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 32, 252}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 27, 211, 121, 251}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 90, 127, 67, 36, 4, 183}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 177, 66, 7}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 225, 47, 177, 230, 212}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 205, 230, 46, 1, 207}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 162, 15}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 78, 42, 142, 222}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 200, 220, 110, 10, 194, 56}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 232, 146, 14, 130, 180}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 53, 37, 59}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 1}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 66, 90, 60, 169}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 202, 181, 10, 83, 230}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 20, 156, 151, 138}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 80, 191, 217}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 237, 248, 132, 153, 173, 159}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 215, 214, 213}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 10}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 40}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 236, 252, 99, 101}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 14, 1, 177}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 84}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 31, 152, 59, 154}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 65, 191, 105}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 101, 60, 195}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 57, 55, 115, 213, 199, 30, 112}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 26}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 244, 119, 215, 64, 45}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 184, 151, 168, 121, 72}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 49, 235}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 141, 195, 17, 23, 25}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 93, 238, 232, 51}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 36, 120, 154}, 235}, {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 226, 171, 245, 224}, 235}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 111, 1, 126, 210, 175}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 142}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 100, 165, 196, 164, 54, 23, 204, 125}, 240}, {{9, 138, 192, 0, 0, 0, 0, 5, 51, 254, 119, 58, 246, 50, 249, 7}, 240}, {{9, 138, 192, 0, 0, 0, 235, 76, 3, 252, 178, 135, 218, 87, 40, 201}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 151, 52, 39, 205, 161}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 108, 208, 218, 48, 126}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 186, 46, 21, 42, 50, 217, 192, 117}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 180, 231, 8, 188, 202, 43, 131}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 238, 119, 11, 194, 51, 65, 177, 2}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 3, 116, 39, 54, 137, 102, 170, 169}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 200, 165}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 69, 13, 131, 85, 59, 227}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 233, 54, 146, 152, 166, 35, 255}, 240}, {{9, 138, 192, 0, 0, 0, 116, 174, 96, 181, 64, 186, 167, 211, 173, 142}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 172, 188, 242, 155, 177, 39, 161}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 72}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 240}, {{9, 138, 192, 0, 0, 88, 96, 53, 162, 99, 235, 142, 88, 98, 103, 73}, 240}, {{9, 138, 192, 211, 172, 98, 220, 229, 153, 245, 166, 98, 29, 188, 124, 2}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 230, 84, 199, 105, 163, 35, 141, 217}, 240}, {{9, 138, 192, 0, 0, 40, 101, 83, 61, 82, 189, 248, 19, 52, 34, 119}, 240}, {{9, 138, 192, 0, 0, 0, 0, 141, 211, 161, 212, 252, 203, 44, 218, 27}, 240}, {{9, 138, 192, 0, 0, 0, 0, 52, 147, 64, 23, 243, 87, 203, 50, 44}, 240}, {{9, 138, 192, 0, 0, 0, 98, 187, 37, 215, 84, 119, 145, 99, 35, 218}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 97, 61, 3, 26, 148, 164}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 43}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 64, 167, 225, 155, 132, 191}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 86, 8, 130}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 203, 59, 5, 229, 179}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 0, 0, 0, 134, 100, 27, 230, 242, 208, 234, 55, 138, 166}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 68, 102, 25, 188, 247}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 53, 177, 201}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 244, 211, 26, 250, 94, 54, 231, 0}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 72, 95, 185, 36, 12, 112}, 240}, {{9, 138, 192, 0, 36, 29, 6, 46, 1, 250, 83, 33, 108, 173, 19, 61}, 240}, {{9, 138, 192, 0, 0, 187, 128, 74, 163, 63, 191, 195, 82, 196, 226, 244}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 187, 66, 73, 181, 174, 121, 58}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 248, 44}, 240}, {{9, 138, 192, 0, 102, 251, 174, 221, 89, 33, 116, 205, 255, 175, 90, 237}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 75, 91, 103}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 136, 166, 156, 113, 162, 239, 192, 208, 160, 176, 76, 139, 228}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 184, 254, 189}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 245}, 240}, {{9, 138, 192, 0, 0, 0, 244, 195, 86, 179, 42, 205, 223, 118, 135, 58}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 116, 145, 91, 184, 20, 191, 158}, 240}, {{9, 138, 192, 0, 0, 192, 158, 201, 16, 24, 168, 247, 165, 52, 180, 238}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 50, 76, 18}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 166, 139, 67, 128, 45, 69, 62}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 58, 32, 71, 73, 252}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 154, 177}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 70, 175, 133, 48, 9, 198, 250}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 208, 246, 84}, 240}, {{9, 138, 192, 0, 159, 236, 226, 227, 228, 197, 156, 26, 13, 103, 110, 189}, 240}, {{9, 138, 192, 0, 0, 205, 64, 221, 9, 77, 162, 220, 234, 246, 11, 80}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 0, 0, 0, 0, 76, 6, 84, 221, 142, 76, 193, 164, 3}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 238, 15, 4}, 240}, {{9, 138, 192, 0, 251, 143, 75, 48, 217, 155, 224, 67, 197, 201, 189, 213}, 240}, {{9, 138, 192, 0, 0, 0, 157, 42, 192, 118, 83, 47, 251, 8, 178, 80}, 240}, {{9, 138, 192, 0, 0, 0, 94, 187, 10, 205, 45, 72, 89, 18, 107, 75}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 240}, {{9, 138, 192, 0, 0, 113, 75, 251, 87, 203, 93, 149, 30, 202, 236, 238}, 240}, {{9, 138, 192, 0, 181, 12, 219, 81, 203, 23, 179, 211, 124, 136, 255, 206}, 240}, {{9, 138, 192, 0, 0, 0, 0, 151, 115, 130, 36, 130, 102, 99, 121, 36}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 228, 240, 202, 147, 118, 243, 111}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 220, 98}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 240}, {{9, 138, 192, 0, 0, 0, 169, 35, 231, 250, 73, 250, 226, 85, 93, 20}, 240}, {{9, 138, 192, 0, 195, 69, 223, 226, 235, 125, 17, 133, 120, 76, 87, 150}, 240}, {{9, 138, 192, 0, 0, 63, 169, 144, 25, 200, 242, 192, 245, 175, 93, 32}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 85, 35}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 79, 88}, 240}, {{9, 138, 192, 0, 70, 139, 124, 214, 53, 200, 177, 200, 77, 56, 210, 129}, 240}, {{9, 138, 192, 0, 0, 0, 0, 6, 68, 211, 115, 125, 185, 12, 69, 83}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 110}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 224, 105, 191, 92, 244}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 33}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 240}, {{9, 138, 192, 102, 49, 77, 35, 25, 37, 142, 20, 205, 152, 99, 212, 63}, 240}, {{9, 138, 192, 0, 0, 0, 116, 143, 149, 41, 187, 35, 187, 147, 27, 189}, 240}, {{9, 138, 192, 0, 0, 163, 109, 21, 144, 144, 5, 13, 170, 113, 12, 125}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 162}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 154}, 240}, {{9, 138, 192, 0, 226, 18, 89, 140, 213, 75, 250, 173, 136, 25, 172, 129}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 112, 117, 198, 190, 146}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 159, 198, 8}, 240}, {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 84, 161}, 240}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 77, 9, 167, 93}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 87, 56, 3, 221, 123, 100, 131}, 136}, {{45, 173, 14, 72, 67, 135, 148, 202, 80, 160, 172, 55, 251, 127, 77, 31}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 23}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 77}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 119, 34, 227, 89, 220, 115}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 31, 130, 179, 79, 50}, 136}, {{45, 173, 14, 72, 0, 0, 42, 65, 44, 208, 178, 8, 20, 213, 166, 198}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 74, 26, 60, 97, 42, 207}, 136}, {{45, 173, 14, 72, 0, 0, 164, 133, 3, 140, 154, 73, 61, 86, 142, 139}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 131, 113, 24, 159, 100}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 120, 165}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 154}, 136}, {{45, 173, 14, 72, 0, 0, 100, 81, 83, 70, 59, 85, 162, 79, 235, 113}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 112, 211, 210, 161}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 19, 213}, 136}, {{45, 173, 14, 72, 0, 95, 156, 84, 153, 115, 176, 160, 11, 209, 114, 200}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 96, 189, 6, 184, 3}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 39, 199}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 36}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 53, 210, 12, 89, 45}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 155, 149}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 5, 7}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 244}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 15, 249, 218, 193}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 249, 2, 6, 113, 59, 189}, 136}, {{45, 173, 14, 72, 0, 0, 131, 94, 231, 43, 142, 23, 214, 45, 156, 161}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 95, 222, 91, 71, 9, 27, 19}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 255, 91, 125, 47, 120, 102, 78, 100}, 136}, {{45, 173, 14, 72, 0, 0, 129, 32, 184, 249, 19, 18, 5, 116, 199, 245}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 221, 45, 78, 97, 240, 174, 209, 203}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 92}, 136}, {{45, 173, 14, 72, 0, 0, 0, 82, 102, 195, 63, 131, 58, 171, 94, 162}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 44, 239, 159, 146}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 136}, {{45, 173, 14, 72, 0, 0, 0, 135, 193, 238, 77, 210, 194, 64, 82, 41}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 136}, {{45, 173, 14, 72, 0, 0, 127, 145, 234, 220, 207, 181, 223, 194, 40, 210}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 187, 1, 73, 58, 6, 17, 130, 58, 175, 252, 153}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 82, 225, 244, 123, 64, 93, 35, 113}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 53}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 205, 218, 166, 138, 185}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 200, 173}, 136}, {{45, 173, 14, 72, 0, 104, 247, 84, 230, 246, 166, 90, 37, 213, 31, 51}, 136}, {{45, 173, 14, 72, 0, 0, 131, 121, 138, 215, 160, 227, 164, 9, 51, 100}, 136}, {{45, 173, 14, 72, 0, 0, 0, 28, 117, 24, 81, 161, 236, 48, 242, 138}, 136}, {{45, 173, 14, 72, 0, 177, 109, 219, 17, 208, 41, 42, 146, 126, 81, 241}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 138, 71, 102, 123, 16, 19, 75}, 136}, {{45, 173, 14, 72, 0, 10, 89, 199, 6, 19, 87, 115, 58, 15, 246, 40}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 44, 190}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 206, 21, 255, 25, 233, 103, 51}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 136}, {{45, 173, 14, 72, 185, 249, 251, 206, 54, 100, 41, 106, 40, 176, 144, 6}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 5, 46, 196, 198, 87}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 148, 226, 204, 146, 51, 122, 123, 77}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 250, 108, 246, 28, 41}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 148, 119, 61, 113, 218, 146, 244, 1}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 182, 21, 189, 224}, 136}, {{45, 173, 14, 72, 0, 159, 176, 168, 100, 249, 124, 213, 6, 115, 62, 52}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 108}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 178, 255, 219, 95, 252}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 252, 203, 70, 102, 113, 114}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 205, 35, 9, 32}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 121, 163, 245, 91, 129, 240, 130, 32}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 209, 233, 91, 67, 244, 61, 62, 204}, 136}, {{45, 173, 14, 72, 0, 0, 79, 150, 71, 62, 179, 86, 50, 228, 23, 205}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 156, 87}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 36}, 136}, {{45, 173, 14, 72, 0, 0, 36, 159, 136, 48, 40, 193, 91, 27, 219, 166}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 44, 39, 107, 157, 27, 106}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 246, 30, 53, 115, 150, 119, 22, 224}, 136}, {{45, 173, 14, 72, 0, 0, 0, 177, 137, 36, 146, 114, 19, 216, 27, 151}, 136}, {{45, 173, 14, 72, 0, 0, 0, 42, 232, 183, 83, 153, 65, 253, 110, 7}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 249, 214, 177, 237, 83, 112}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 240, 14, 54, 235, 146, 171}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 195}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{45, 173, 14, 72, 0, 110, 132, 108, 67, 127, 56, 38, 234, 114, 144, 132}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 230, 11, 28, 43, 236}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 152, 184, 255, 85}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 82, 169}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 72}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 227, 232, 250, 250}, 136}, {{45, 173, 14, 72, 0, 0, 82, 232, 89, 63, 152, 155, 200, 72, 217, 160}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 35, 102}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 39, 234, 51, 104}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 15, 146}, 136}, {{45, 173, 14, 72, 0, 41, 255, 82, 185, 103, 127, 6, 174, 45, 126, 181}, 136}, {{45, 173, 14, 72, 0, 0, 242, 82, 33, 152, 77, 72, 193, 79, 112, 100}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 23, 219, 235, 113}, 136}, {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 69, 97}, 136}, {{45, 173, 14, 72, 0, 0, 122, 115, 142, 231, 119, 156, 249, 251, 228, 97}, 136}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 186}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 178}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 97, 17, 210, 210, 221}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 8, 175, 206, 247, 124}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 121, 162, 234}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 82, 124, 145, 222, 247, 107, 73, 244}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 65, 249}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 204, 31, 145, 210, 37}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 73, 98, 90, 137, 59, 171, 84}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 111, 92, 60, 75, 224, 5}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 87, 174}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 87, 207, 154}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 212, 180, 12, 172, 236, 49, 224}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 207, 50, 35, 33, 2, 45, 191}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 76}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 27, 191, 37, 133, 163, 35}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 253, 89, 102, 241, 117, 122, 253, 193}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 215, 24, 41, 39, 55, 35}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 23, 57}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 16}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 158}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 17, 165, 93, 202, 250, 69}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 91, 243, 67, 133}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 7, 210, 125, 218}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 61, 152, 143, 142, 201, 154}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 62, 237, 168, 212, 112, 244, 223, 100}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 78, 35}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 91, 133, 157, 175, 187, 115, 81, 180}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 12, 15, 6, 185, 244, 100, 179, 202}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 138, 106, 192, 64, 233, 165, 186}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 180, 108, 75}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 40, 228}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 119, 246, 165, 2, 74, 75}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 18, 128, 44, 126, 126}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 65, 82, 47, 195, 217}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 157, 90, 12, 216, 190}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 218, 200, 8}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 218, 249, 68}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 37, 67, 150, 243, 238, 173}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 218, 237}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 31, 253, 126, 227, 67}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 176, 185, 75, 157, 111, 81}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 156, 245, 210, 65}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 74, 208}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 68, 246, 85, 88, 193, 215, 220}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 32}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 184, 126, 96, 71, 34, 100}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 239, 162, 34, 39, 13, 62}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 130}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 92, 1, 40}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 175, 13, 101, 188, 248}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 245}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 125, 202, 239, 77, 112, 223, 43}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 220}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 177, 109, 38, 39, 218, 19, 125}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 171}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 237, 171, 185, 238, 19}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 42, 73, 138, 202, 8, 181}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 78, 181, 250, 1, 40}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 116}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 36, 44, 14, 97, 30, 232, 120}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 149, 53, 67, 240, 127, 88}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 170, 14}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 14, 162, 46, 11, 96}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 199, 231, 16, 31}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 88, 9, 53}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 4}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 207, 4, 252}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 96, 190, 81}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 217}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 118, 73, 10, 251, 130, 136, 137}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 56, 193, 2, 102, 218, 142}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 221, 88}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 246}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 165, 178, 4, 163, 249}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 213, 170, 153, 28, 113}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 230, 90, 205, 216, 88, 38, 227, 154}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 90}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 108, 241, 24, 152, 239, 42, 57}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 164}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 77, 127}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 27}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 194, 158, 65, 179}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 88, 31, 196, 147, 2}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 68, 166, 99}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 78, 163, 98}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 120}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 17, 52, 136, 227}, 186}, {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 248, 197, 150}, 186}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 67, 97}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 91}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 214, 17}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 247, 43, 159}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 63}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 141, 108, 243}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 242, 45}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 79, 125}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 1, 145, 210}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 174, 55}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 233}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 104, 45}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 138}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 203, 226, 55, 215}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 37, 92, 86}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 103, 16}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 60, 117, 87}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 99}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 101}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 151}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 228, 52}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 25, 70}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 140, 47}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 101, 151, 189}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 67, 110}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 226}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 162}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 204, 181}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 138, 17}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 213, 115, 225}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 244, 100, 99}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 41, 18}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 52, 180, 109}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 93, 192}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 58, 84, 223}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 101, 170}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 42, 156, 200}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 203, 209, 210}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 4}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 75, 30, 152}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 217, 102}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 120, 151, 217}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 54}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 118, 254}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 202}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 96}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 45, 44, 225}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 72, 62}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 58, 151}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 237}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 214, 201, 183}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 218, 139}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 36}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 37, 225, 220, 78}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 208}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 222, 225}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 78, 214}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 174}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 190, 87}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 129, 116, 26}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 67, 74}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 95, 81, 93}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 132, 106, 57}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 67, 206, 138, 138}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 114, 162, 88}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 233, 133, 60}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 38}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 61, 14}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 152, 177, 32, 196}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 157}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 226}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 28}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 114, 216}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 54, 141, 61, 69}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 104, 37, 87}, 174}, {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 174}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 64, 99}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 135}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 194}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 12, 134, 20, 219}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 159, 231, 216, 102}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 128, 176}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 168, 167, 168, 128}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 143, 108, 114}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 116, 82, 208, 93, 60}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 101, 36}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 108, 228, 121}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 68, 9, 80}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 96}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 182, 186}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 175, 45, 140}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 68, 84}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 219, 241, 136, 20, 206}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 3, 32}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 171, 249}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 239}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 79, 192, 18}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 183, 99, 197, 201, 227}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 115, 57, 237, 39, 99}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 80}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 165, 140, 44}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 50, 218, 229}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 104, 232, 167, 227}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 34, 63, 127, 22}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 224, 187, 183, 156, 215}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 129, 86, 225, 184, 194, 104}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 95}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 180, 155}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 109, 136, 2}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 227, 102, 201, 250}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 143, 182, 158}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 192, 176, 108, 129}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 234, 250, 163}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 243, 247, 240}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 243, 249, 196, 166}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 86, 27, 30}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 70, 255}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 234, 116}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 65}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 165, 57, 120, 220}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 145, 218}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 216, 14, 85, 125}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 190, 126, 199, 163, 110}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 137, 40, 33}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 162, 52, 184}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 35, 44, 103}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 197, 172, 74}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 50, 250, 86, 28, 49}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 150, 71, 192}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 227, 43, 161, 221, 1}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 249, 170}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 76, 179, 244}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 41, 149}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 203, 158, 7}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 124, 11, 21, 58, 31}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 10, 190, 246, 42}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 92}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 85, 12, 180}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 21, 147, 115, 235, 159}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 95, 214, 46, 22, 123}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 136, 147}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 158, 38, 239, 242, 45}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 220, 82, 146, 166}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 126, 176, 69}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 67, 188, 112, 56, 189}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 108, 11, 88}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 113}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 140, 136, 180, 170}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 84, 183}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 213, 151, 113, 99, 120}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 32, 136, 251}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 157, 150}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 69}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 48, 75, 228, 92, 247}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 222}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 153}, {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 117, 60, 205, 247}, 153}, {{3, 163, 107, 228, 192, 0, 37, 174, 219, 248, 179, 90, 165, 20, 22, 113}, 118}, {{3, 163, 107, 228, 192, 35, 115, 176, 116, 76, 84, 57, 8, 111, 45, 158}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 137, 130, 83, 74, 193}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 215, 173, 85, 104}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 77, 223, 248}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 59}, 118}, {{3, 163, 107, 228, 192, 0, 27, 166, 177, 233, 51, 179, 118, 10, 68, 252}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 93, 137, 79}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 75}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 225, 209, 244, 212, 168, 124, 125, 91, 89}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 3, 146, 170, 126, 235, 90}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 126, 103, 82, 152, 11}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 105, 114, 201, 35, 12}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 45, 46, 114, 143, 4}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 79, 251, 101, 188, 165, 146, 151, 137}, 118}, {{3, 163, 107, 228, 192, 210, 69, 81, 30, 58, 175, 102, 88, 152, 17, 254}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 14, 72, 213, 215, 175, 245, 219}, 118}, {{3, 163, 107, 228, 192, 0, 0, 208, 145, 63, 200, 244, 132, 20, 141, 19}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 99, 89, 99, 251, 254, 135, 51}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 84, 239, 13, 138, 226, 176, 6, 121}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 247, 227, 157, 134}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 57, 34, 31, 56, 87, 55, 80}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 118}, {{3, 163, 107, 228, 192, 117, 205, 220, 243, 83, 237, 151, 155, 4, 208, 51}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 153, 145, 217, 78}, 118}, {{3, 163, 107, 228, 192, 0, 0, 130, 13, 44, 218, 115, 250, 218, 76, 234}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 46, 198, 125, 26}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 243, 153, 192}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 18, 54, 104, 171, 219, 174, 120, 113}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 173, 94, 76, 68, 113, 100, 219, 208, 75}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 249, 85, 244, 128, 231, 82, 180}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 20, 96, 126, 95, 27, 208}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 69, 115, 165, 59, 208, 184, 55, 69, 237, 213, 24}, 118}, {{3, 163, 107, 228, 192, 0, 0, 230, 9, 141, 67, 219, 169, 190, 110, 27}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 198, 98, 18, 105, 188, 56, 244, 45}, 118}, {{3, 163, 107, 228, 192, 13, 246, 111, 215, 109, 4, 148, 209, 239, 54, 232}, 118}, {{3, 163, 107, 228, 192, 0, 172, 68, 16, 127, 30, 32, 108, 224, 254, 110}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 226}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 190, 181, 127, 222, 4}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 104, 69, 193, 185}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 41, 58, 13, 5, 46}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 225, 155, 38, 161}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 144, 107, 128, 40, 79, 174}, 118}, {{3, 163, 107, 228, 192, 93, 167, 166, 216, 91, 206, 37, 241, 138, 41, 113}, 118}, {{3, 163, 107, 228, 192, 0, 0, 81, 213, 233, 154, 83, 173, 44, 60, 134}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 45, 79, 31, 102, 221, 34, 131, 50}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 51, 62, 44, 195, 21, 72, 204, 56}, 118}, {{3, 163, 107, 228, 192, 0, 0, 87, 207, 206, 183, 84, 200, 200, 174, 220}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 43, 13, 42, 197, 115, 16, 37, 10, 170, 115}, 118}, {{3, 163, 107, 228, 192, 0, 190, 109, 60, 232, 41, 203, 49, 131, 241, 162}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 0, 0, 28, 117, 86, 96, 61, 248, 176, 186, 150}, 118}, {{3, 163, 107, 228, 192, 113, 101, 94, 160, 24, 145, 151, 11, 45, 252, 44}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 112, 74, 227, 171, 153, 103}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 51, 134, 132, 122}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 192}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 136, 242, 236, 223, 108, 100}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 186, 153, 5, 175}, 118}, {{3, 163, 107, 228, 192, 125, 97, 186, 27, 206, 91, 63, 234, 140, 27, 206}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 155, 157, 14, 248, 160}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 118, 158, 68}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{3, 163, 107, 228, 192, 150, 59, 30, 94, 139, 199, 194, 26, 91, 177, 85}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 120, 22, 48, 248, 7, 181, 235, 160}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 64, 77, 228, 26, 253, 244, 44, 158}, 118}, {{3, 163, 107, 228, 192, 0, 124, 124, 186, 15, 76, 84, 145, 127, 58, 195}, 118}, {{3, 163, 107, 228, 192, 173, 100, 158, 118, 27, 103, 138, 129, 125, 222, 41}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 150, 141, 47}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 35, 147, 133, 214, 135}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 25, 213, 250}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 36, 55, 242, 63, 239, 0, 127}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 216, 84, 248}, 118}, {{3, 163, 107, 228, 192, 0, 134, 230, 224, 247, 227, 54, 151, 227, 124, 115}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 78, 8, 190, 159, 135, 40, 224, 22}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 120, 152, 185}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 62, 203, 189, 39}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 118}, {{3, 163, 107, 228, 192, 0, 98, 166, 219, 20, 119, 115, 88, 133, 240, 191}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 131, 12, 8, 237, 27, 199, 112, 0}, 118}, {{3, 163, 107, 228, 192, 156, 95, 41, 154, 65, 110, 71, 129, 13, 63, 30}, 118}, {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 223}, 118}, {{3, 163, 107, 228, 192, 188, 223, 84, 39, 217, 215, 127, 243, 39, 174, 249}, 118}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 41, 216, 173, 157}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 139}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 252, 107, 225, 207}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 201, 242, 88, 60}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 101, 162, 107, 70, 135, 178, 46, 146}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 209, 233, 30}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 55, 238}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 63, 8, 255, 195, 120, 80}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 82, 54, 105}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 246, 204}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 41}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 92, 190, 177}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 147, 34, 183, 215, 245, 230, 21, 222}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 229, 148, 103}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 217, 1, 110, 75}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 130, 225, 42, 250, 220, 127, 9, 30}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 63, 198, 37, 65, 102, 129, 165}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 53, 57, 95}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 97}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 36}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 164, 222, 152}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 213, 34}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 16, 108, 71, 222, 234, 187, 187}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 238, 112, 161, 23, 42, 230, 15}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 124, 12, 157, 21}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 47, 243, 129, 101, 177, 40, 111, 96}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 207, 56, 2, 235, 87}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 112, 218, 123, 68, 144, 230, 235, 193}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 129, 234}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 36, 208, 42, 122, 108, 252, 208}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 249, 108}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 128, 22, 6, 160, 146, 11}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 140, 15, 154, 89}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 83, 100, 39, 39}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 249, 207, 111, 154, 216, 9}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 18, 90, 143}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 92, 19, 59, 186, 28, 232, 196}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 81}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 91, 183, 175, 90, 236}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 8, 37, 6, 160, 4, 178}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 104}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 132}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 235, 115, 143}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 211, 11, 230, 176, 116, 162}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 250, 82, 130, 210}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 48, 60, 133, 100, 128, 191}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 116, 198, 12, 41, 109}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 191, 96, 206}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 21, 156}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 175, 236, 131}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 251, 17, 152}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 82, 48}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 57, 155, 56, 30, 23}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 70, 186, 201, 14, 125, 245, 18, 64}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 189, 51, 164, 77}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 87, 56, 199, 33, 148, 236, 22}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 196, 85}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 42, 218, 204, 109, 139, 227, 189}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 20}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 88, 32}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 78, 235, 186, 108}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 63, 54}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 121, 226}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 65, 205, 251, 87}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 255, 195, 189, 251, 51, 235, 134, 78}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 119, 9, 212}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 39, 223, 155, 1, 9, 78}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 2, 143, 142, 78}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 154, 87, 204, 43, 29, 136}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 255, 215, 252}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 179, 85, 246, 139, 179, 160, 194, 87}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 52, 76, 50, 68, 229, 72}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 16, 231}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 105, 209, 163, 197, 222, 222, 203}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 158, 162, 242, 22, 161, 114, 225}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 146, 96, 29, 194, 26, 43}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 210, 205}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 250, 108, 254, 68, 205, 242, 254, 52}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 224, 42, 187, 53}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 75, 149, 177}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 61, 108, 184, 233, 65, 217}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 123, 17, 93, 105, 23, 73, 187}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 200, 121, 252, 171, 49, 151, 25}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 107, 178, 233}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 102, 170, 225, 108, 186}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 70, 152, 163, 107}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{167, 109, 2, 95, 11, 62, 45, 128, 103, 217, 172, 110, 226, 147, 74, 58}, 113}, {{76, 0, 0, 0, 0, 125, 40, 62, 88, 127, 161, 74, 191, 8, 241, 71}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 77, 246, 115, 96, 157, 68, 239}, 58}, {{76, 0, 0, 0, 172, 17, 67, 91, 252, 180, 11, 155, 110, 145, 126, 66}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 245}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 154, 13, 229, 82, 174, 78, 40, 140}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 101, 108, 137, 26, 173, 208, 200, 143}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 155, 113, 25}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 24, 70, 46, 7}, 58}, {{76, 0, 0, 0, 116, 248, 7, 171, 143, 246, 207, 120, 9, 219, 25, 66}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 236}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 58}, {{76, 0, 0, 0, 0, 33, 117, 197, 37, 78, 87, 110, 131, 59, 125, 184}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 20, 140, 243, 106, 212, 170, 96, 22}, 58}, {{76, 0, 114, 254, 75, 98, 176, 212, 162, 153, 221, 122, 163, 196, 148, 56}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 16, 232, 134, 206}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 236, 64, 88, 162, 112}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 177, 54, 54, 209, 198, 223, 46}, 58}, {{76, 0, 0, 0, 0, 18, 134, 149, 33, 67, 192, 15, 123, 70, 104, 245}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 254, 128, 164, 127, 95}, 58}, {{76, 0, 0, 171, 196, 154, 106, 198, 139, 169, 81, 59, 111, 80, 154, 53}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 181, 26, 177}, 58}, {{76, 0, 0, 22, 30, 54, 52, 206, 70, 86, 7, 147, 183, 113, 122, 93}, 58}, {{76, 0, 0, 232, 54, 22, 242, 231, 42, 70, 87, 160, 216, 24, 120, 198}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 224, 104, 59, 58, 128, 66, 60}, 58}, {{76, 0, 0, 6, 159, 206, 192, 234, 152, 219, 33, 23, 254, 198, 96, 250}, 58}, {{76, 0, 0, 0, 0, 154, 124, 54, 245, 157, 103, 155, 166, 132, 83, 201}, 58}, {{76, 0, 0, 0, 0, 0, 196, 153, 81, 113, 171, 98, 13, 161, 9, 25}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 92, 244, 17, 246, 146, 126, 160, 148}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 58}, {{76, 0, 0, 0, 3, 1, 223, 100, 113, 219, 213, 143, 215, 174, 125, 193}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 26, 4}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 171, 114, 213, 75, 129, 86, 70, 6}, 58}, {{76, 0, 0, 0, 0, 53, 135, 108, 218, 8, 97, 239, 152, 230, 217, 204}, 58}, {{76, 0, 0, 240, 229, 237, 3, 103, 23, 23, 83, 220, 91, 36, 23, 106}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 24, 172, 118, 13}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 59, 134, 52}, 58}, {{76, 0, 189, 87, 128, 62, 248, 59, 158, 213, 189, 221, 57, 170, 165, 87}, 58}, {{76, 0, 0, 0, 233, 77, 69, 160, 221, 226, 174, 107, 123, 237, 54, 252}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 52, 22, 144, 84}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 106, 116, 57}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 58}, {{76, 0, 0, 0, 0, 162, 141, 206, 91, 153, 91, 6, 18, 201, 14, 39}, 58}, {{76, 0, 0, 44, 13, 91, 50, 224, 146, 113, 22, 135, 98, 137, 0, 82}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 36, 144, 180, 132, 182, 176, 221}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 97, 227, 152}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 13, 81}, 58}, {{76, 0, 0, 209, 56, 255, 37, 70, 233, 148, 114, 192, 122, 208, 16, 78}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 99, 220}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 220, 203, 44, 19, 253}, 58}, {{76, 0, 0, 39, 22, 95, 137, 2, 145, 91, 188, 52, 80, 224, 79, 97}, 58}, {{76, 0, 0, 0, 0, 0, 0, 43, 228, 63, 95, 122, 251, 197, 6, 246}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 196, 191, 87, 67}, 58}, {{76, 0, 0, 0, 0, 0, 0, 51, 72, 113, 96, 61, 30, 64, 1, 237}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 126}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 129, 91}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 119, 198, 94, 101, 112}, 58}, {{76, 0, 0, 50, 35, 67, 153, 16, 65, 57, 9, 103, 237, 17, 221, 179}, 58}, {{76, 0, 0, 195, 56, 81, 80, 123, 56, 80, 183, 171, 170, 222, 216, 26}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 133, 154, 235}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 209, 143, 241, 234, 241, 173, 220, 246}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 196, 50}, 58}, {{76, 0, 144, 209, 148, 20, 210, 86, 38, 212, 25, 50, 231, 154, 178, 103}, 58}, {{76, 0, 0, 0, 0, 0, 147, 37, 133, 49, 213, 46, 255, 156, 183, 2}, 58}, {{76, 0, 0, 0, 0, 220, 17, 179, 138, 79, 174, 21, 5, 43, 153, 5}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 237, 106, 26, 231, 206, 227, 122, 178, 172, 169, 243, 160, 80}, 58}, {{76, 0, 0, 147, 76, 135, 223, 153, 97, 67, 0, 134, 249, 59, 223, 129}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 149, 196, 91, 68, 82, 47, 79, 216}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 101, 107, 36, 81, 22, 28, 243}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 123, 121, 93}, 58}, {{76, 0, 0, 0, 168, 153, 141, 132, 229, 114, 197, 13, 148, 152, 234, 35}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 53, 173, 35, 29, 3}, 58}, {{76, 0, 86, 102, 109, 226, 124, 207, 224, 35, 97, 178, 21, 127, 72, 193}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 224, 49, 166, 132, 30}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 195, 122, 222, 242, 254, 156, 30}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 183, 48, 154, 34, 23}, 58}, {{76, 0, 0, 225, 1, 197, 6, 237, 235, 68, 15, 154, 201, 230, 248, 213}, 58}, {{76, 0, 86, 186, 185, 124, 244, 186, 99, 66, 31, 78, 44, 98, 101, 38}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 208, 73, 83}, 58}, {{76, 0, 0, 0, 0, 111, 173, 65, 242, 187, 5, 7, 112, 237, 5, 226}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 211, 186}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 62, 92, 127, 196, 93, 30, 164}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 144, 7, 166, 20}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 154, 166, 76, 111, 209}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 219, 140, 125, 174}, 58}, {{76, 0, 0, 0, 0, 230, 8, 242, 39, 184, 105, 82, 122, 210, 170, 100}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 160, 18, 173, 63}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 6, 99, 46}, 58}, {{76, 0, 35, 13, 33, 0, 30, 218, 234, 0, 159, 160, 249, 151, 57, 52}, 58}, {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 40}, 58}, {{76, 0, 0, 186, 79, 65, 86, 52, 192, 212, 57, 97, 238, 225, 235, 62}, 58}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 85}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 188, 189, 129}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 205, 126}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 221, 154, 11}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 132, 87}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 177}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 126, 238}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 224}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 12, 167}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 116, 22}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 31, 161}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 79, 148}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 72, 205}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 79}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 38}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 203}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 123, 166, 56}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 11, 234, 46}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 186}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 199, 131, 193}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 75}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 14, 63}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 236}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 238, 11, 71}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 119, 106}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 45, 131, 114}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 223}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 32, 141}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 37, 91}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 143, 32, 10}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 95}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 239}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 82, 161, 129}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 100, 95}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 80, 50}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 229, 172}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 30}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 13}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 14, 199}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 173, 51}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 155, 250, 34}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 61}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 171}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 211}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 64, 174, 162}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 123, 209}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 244}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 247, 57}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 10, 188, 126}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 164, 146}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 127}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 190, 191, 151}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 137}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 72}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 153, 173, 39}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 104, 21, 67}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 76, 144}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 60, 158}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 215, 56}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 32}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 111}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 45}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 48, 39}, 206}, {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 206}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 138}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 214}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 69}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 36}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 198}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 132}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 162}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 1}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 120}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 254, 56}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 146}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 202}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 158}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 70}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 53}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 42}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 237}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 222}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 56}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 204}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 72, 252}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 234}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 11}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 85}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 31}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 8}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 172}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 109}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 206}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 235, 218}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 114}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 106}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 195}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 55}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 240, 205}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 219}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 233}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 77}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 213}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 94}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 189, 113}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 232}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 36}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 99}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 37}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 84}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 222}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 164}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 129}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 103}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 211}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 1}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 251}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 57}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 199, 25}, 42}, {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 90}, 42}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 83, 184, 153, 102, 143}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 255, 14, 143, 170, 228, 185, 137, 131}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 119, 164}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 162, 197, 223, 91, 80}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 13, 240}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 204, 233, 100, 148, 246}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 195, 245, 25, 124, 107}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 44, 154, 178, 4, 131, 163, 109, 92}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 42, 197, 34, 109, 31, 127, 60}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 89, 199, 167, 218}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 51, 172, 221, 51, 18}, 230}, {{77, 156, 8, 209, 181, 37, 70, 118, 239, 12, 7, 240, 133, 170, 61, 107}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 39, 163, 179, 186}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 165, 116}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 89, 127}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 226, 251, 19, 49, 225}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 251, 73, 96, 214, 241, 130, 117, 218}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 88, 216, 235, 189, 204, 88}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 62, 235}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 126, 147, 180, 175, 96, 222, 202, 21}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 36, 53, 158, 87, 65, 202}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 247, 188, 186, 194, 252, 216, 237}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 138, 138, 24, 37, 246, 135, 129, 218}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 78, 91, 169, 4}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 144, 104, 207, 163}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 2, 155, 242, 174}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 236, 234, 217, 27}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 126, 133}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 17, 226, 27, 134, 250}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 71, 161, 166, 43}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 103, 203}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 236, 217}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 43, 163, 203, 179}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 179, 111}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 249, 140, 117, 181, 4, 228}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 2, 226, 110, 10, 5}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 22, 148, 15, 167, 135}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 107, 248, 11}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 201, 134, 164, 249, 205, 236}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 114, 31, 113, 21, 126, 13, 70}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 47, 196}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 26, 118, 21, 104, 254}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 225, 251, 146, 234, 180}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 222, 84, 55, 78}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 176, 53, 91, 210, 113, 150}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 216, 98, 176, 64, 12, 112, 124, 160}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 105, 89, 101, 137, 103, 169}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 18, 228, 82, 24, 172, 125, 64}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 253, 85, 149, 240}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 173, 240, 195, 135, 80, 9}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 77, 147, 113, 105}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 146, 128, 170, 158}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 213, 20, 3}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 122, 4, 249, 176}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 48, 39, 101, 167, 44, 193, 27}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 206, 16, 6, 102}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 199, 224, 58, 204, 16}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 109, 219, 18}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 129, 116, 92, 3, 131, 152}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 244, 134, 89, 74}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 20, 80, 148, 200, 29, 42, 130, 220}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 5, 204, 206}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 201, 33, 224, 133, 160}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 251, 179, 66, 207, 96, 188, 232, 125}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 148, 196, 13, 101}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 203, 250, 146}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 229, 214, 182, 36, 154, 146}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 51, 247, 128, 88}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 123, 109}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 250, 19, 187, 204, 74, 64, 63, 99}, 230}, {{77, 156, 8, 209, 181, 37, 70, 232, 133, 210, 201, 182, 59, 185, 181, 204}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 18, 160, 81, 246, 148, 131}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 125, 55, 160, 252}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 35, 84, 230, 6}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 253, 110}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 32, 176}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 155, 134, 204, 205, 223, 30, 142}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 201, 212, 142, 81, 26}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 56, 168, 44, 183, 10}, 230}, {{77, 156, 8, 209, 181, 37, 70, 0, 0, 178, 24, 213, 195, 226, 173, 44}, 230}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 103, 173}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 175, 45, 209, 77, 251}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 173}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 28, 230, 194}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 83, 124}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 110, 159, 109}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 120, 235, 26, 245}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 125, 176}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 173}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 170, 68, 17, 140, 101}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 210, 243, 50, 162}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 164, 120, 70, 246, 193, 132, 134}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 153, 128, 204, 120, 19}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 174, 177, 144, 63, 99}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 46, 106, 92, 236}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 41, 170}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 177}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 87, 24, 99, 187, 79}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 116, 193, 229, 234}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 249, 74, 174}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 125, 142, 198, 175}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 77, 193, 143, 133}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 240, 234, 160}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 5, 176, 129}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 121, 40, 10, 123, 48, 201}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 156, 72}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 113}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 83, 57, 63}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 229, 154, 124, 69, 41, 104}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 158}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 226, 250, 249}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 214, 176, 6}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 153, 156}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 26, 160, 20, 3, 164, 6}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 154, 173}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 201, 81, 182, 122, 173, 36}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 133, 151, 208, 109, 185, 1, 187}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 233, 71, 222}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 235, 161, 178}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 185, 94, 3}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 174, 96}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 103, 214, 125, 102, 233, 252}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 118, 17, 177, 184, 120, 124, 91}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 34, 181, 84, 209, 31}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 210}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 39, 114, 63}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 186}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 72, 200, 212, 247}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 159, 249, 43, 46, 172}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 103}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 8, 56, 95, 236}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 163, 215, 154, 232, 71, 95, 75}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 64, 226, 25, 86}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 91, 134, 99, 73}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 30}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 202, 238, 173, 169, 160}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 153, 124, 34, 223, 63, 24, 127}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 92}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 96, 83, 68, 60, 111, 123, 48}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 166}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 10, 206}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 75, 173}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 1, 173, 220, 202, 209, 145, 241}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 168, 183, 146, 236, 177}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 185}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 178, 84}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 61, 3, 34, 203, 200, 210}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 241, 254}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 105}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 193, 185, 91, 97, 90, 251, 10}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 59, 43, 101, 24, 106, 193, 139}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 103, 229, 81, 113, 139, 176}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 145, 27, 242, 54, 132, 237}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 99, 39}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 118, 217, 106, 254}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 126, 78, 199, 74, 86, 139, 155}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 229, 237, 232, 52, 41}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 251, 107, 63, 19, 166, 148, 205}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 86, 28, 137, 172, 68, 11, 84}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 179, 99, 218, 172, 29, 168}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 24}, 6}, {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 235, 6, 9, 220}, 6}, {{47, 232, 0, 0, 0, 228, 168, 178, 36, 168, 138, 55, 207, 29, 220, 134}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 189, 107}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 254}, {{47, 232, 0, 0, 72, 27, 182, 17, 125, 251, 49, 33, 252, 29, 68, 161}, 254}, {{47, 232, 0, 240, 159, 240, 170, 63, 47, 138, 65, 103, 22, 95, 242, 50}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 15, 13, 181, 64, 155, 130}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 64, 188, 199}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 218, 40, 94, 75, 103, 46}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 184, 65, 158, 106, 72, 128}, 254}, {{47, 232, 0, 0, 0, 197, 231, 66, 124, 81, 213, 178, 209, 223, 230, 20}, 254}, {{47, 232, 0, 0, 0, 0, 76, 152, 65, 140, 7, 18, 86, 169, 61, 18}, 254}, {{47, 232, 0, 0, 30, 25, 78, 112, 254, 136, 95, 133, 59, 29, 153, 155}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 184, 146, 232, 73, 153, 221, 207}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 185, 12, 235}, 254}, {{47, 232, 0, 0, 0, 63, 129, 129, 94, 207, 27, 166, 106, 141, 230, 196}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 222, 74, 138}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 100, 113, 94, 57, 18, 73, 206}, 254}, {{47, 232, 0, 0, 0, 0, 0, 197, 223, 117, 183, 159, 28, 180, 185, 20}, 254}, {{47, 232, 0, 0, 0, 0, 11, 138, 214, 202, 65, 33, 174, 247, 60, 60}, 254}, {{47, 232, 0, 0, 0, 4, 111, 55, 87, 203, 90, 235, 111, 252, 94, 15}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 26, 92, 29, 184}, 254}, {{47, 232, 186, 106, 47, 81, 168, 16, 9, 51, 114, 103, 154, 139, 27, 236}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 79, 29, 126, 64, 178, 130, 164, 63}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 27, 8, 170, 23, 162, 44, 37}, 254}, {{47, 232, 0, 0, 0, 0, 183, 192, 227, 14, 168, 63, 193, 26, 151, 1}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 20, 219, 83, 160, 107, 216}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 231, 96, 147, 111}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 50, 116, 8}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 248, 75, 174, 189, 118, 99}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 189, 244}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 18, 139, 127, 180, 114, 131}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 76, 147, 67, 173, 236, 202, 221, 165}, 254}, {{47, 232, 0, 0, 0, 19, 54, 27, 255, 154, 202, 78, 143, 236, 219, 16}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 105, 128, 52}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 47, 174, 197, 153, 211, 78, 214, 113, 199, 88, 254, 147}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 219, 40, 255, 139, 24, 166, 182}, 254}, {{47, 232, 0, 0, 139, 26, 170, 148, 138, 251, 173, 240, 1, 154, 4, 100}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 10}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 220, 124, 64}, 254}, {{47, 232, 0, 0, 0, 0, 0, 172, 162, 50, 152, 185, 150, 180, 255, 110}, 254}, {{47, 232, 0, 149, 88, 165, 70, 228, 131, 183, 172, 9, 101, 59, 64, 105}, 254}, {{47, 232, 0, 138, 49, 86, 194, 52, 221, 71, 49, 247, 111, 187, 164, 45}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 198, 131, 17, 120, 59, 25, 195, 180, 133}, 254}, {{47, 232, 0, 181, 232, 72, 148, 47, 133, 12, 145, 127, 150, 48, 131, 196}, 254}, {{47, 232, 0, 43, 10, 14, 35, 218, 101, 180, 254, 122, 248, 105, 38, 153}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 78, 229, 40, 133}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 254}, {{47, 232, 0, 0, 0, 159, 7, 191, 57, 68, 10, 167, 30, 43, 183, 188}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 10, 130, 155, 67, 33, 81, 49, 43, 216, 131, 94, 89, 219}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 149, 81, 221, 82}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 161}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 101, 71, 234, 199, 66, 89, 195, 85}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 138, 212, 38, 205}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 130, 107, 243, 72, 214, 74, 152, 198}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 117, 227, 156}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 33, 18, 57, 35, 108, 44, 76, 88}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 22, 188, 156, 160}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 192, 204}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 176, 39, 150, 14, 164, 95, 54, 118, 52, 243, 185, 52, 24}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 137, 11, 210, 135, 179, 142, 246, 87, 10, 66, 114, 239}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 228, 55, 75, 182}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 239, 113, 124}, 254}, {{47, 232, 0, 0, 0, 147, 172, 111, 236, 138, 124, 30, 4, 142, 30, 148}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 189, 123, 158, 126}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 122, 136, 181, 233, 2, 182, 207}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 138, 203, 87}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{47, 232, 0, 0, 0, 36, 48, 101, 152, 171, 206, 116, 140, 190, 161, 2}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 71}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 53, 226, 13, 7, 154, 156, 237, 26}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 219}, 254}, {{47, 232, 35, 47, 79, 84, 51, 217, 194, 54, 67, 253, 165, 249, 251, 111}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 149, 44}, 254}, {{47, 232, 0, 0, 0, 0, 88, 23, 84, 78, 102, 133, 241, 149, 154, 25}, 254}, {{47, 232, 0, 0, 0, 0, 0, 132, 251, 233, 29, 55, 85, 225, 94, 240}, 254}, {{47, 232, 0, 0, 113, 81, 231, 71, 118, 106, 238, 91, 152, 55, 87, 130}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 88, 32, 210}, 254}, {{47, 232, 0, 0, 0, 0, 240, 93, 6, 222, 11, 128, 51, 77, 8, 103}, 254}, {{47, 232, 0, 0, 0, 0, 0, 238, 67, 240, 164, 177, 171, 91, 92, 136}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 254}, {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 221, 119, 33, 72}, 254}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 43, 205}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 219}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 209}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 173, 36}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 19}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 93}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 176, 226}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 121, 93}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 176}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 51}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 227}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 114, 104}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 151}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 1}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 63}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 116}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 128, 50}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 125}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 1}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 53}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 84}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 143, 159}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 2}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 204}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 115, 157}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 205}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 219}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 114}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 154}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 74}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 114, 55}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 203}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 203}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 229}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 202, 235}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 212, 116}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 233}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 131, 157}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 1}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 134}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 217}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 113}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 213, 12}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 237}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 115}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 121, 205}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 253, 56}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 177}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 11, 156}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 211}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 186}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 164, 63}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 33}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 107}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 94}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 148, 106}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 120, 190}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 253}, 214}, {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 214}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 254, 209}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 246, 90}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 20, 48}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 153, 234}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 108}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 195}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 190, 187}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 167}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 246}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 191}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 154}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 122}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 221}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 87}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 32}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 150}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 105}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 227, 118}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 34, 15}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 159, 33}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 3}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 41, 131}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 106, 13}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 5}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 98, 151}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 241, 205}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 168, 18}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 139, 88}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 112, 65}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 144, 200}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 78, 186}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 211}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 55, 124}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 67, 36}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 187, 245}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 211}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 191}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 52, 21}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 43}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 158}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 9, 25}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 13}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 212, 234}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 105}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 118}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 38, 187}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 220}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 59}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 54, 131}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 74}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 38, 255}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 206, 88}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 3, 19}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 185}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 79}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 77}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 148}, 43}, {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 190}, 43}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 58, 109, 150}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 211, 16}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 103, 114}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 110, 166, 59, 188}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 218, 230, 109, 245, 64}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 116, 211, 135, 167, 27, 110}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 64, 200, 253}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 49, 42, 70, 84}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 199, 223, 85, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 222}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 242, 224, 151, 204, 3, 59, 253}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 127, 221, 50, 157, 206, 151, 83}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 52, 177, 73, 138, 143, 98, 162}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 136, 219}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 222}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 22, 199, 186, 100}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 151, 56, 2, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 116}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 196}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 174, 196, 248, 32, 232}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 18}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 248, 247, 70, 207, 113, 22}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 206}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 174}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 152}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 231, 169}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 29}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 171, 121, 51, 90}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 114, 48, 115, 176}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 53, 117, 42, 127, 13, 4, 143}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 217, 43, 22, 181}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 121, 127, 83, 178, 142}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 4, 238, 158, 146, 17, 47}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 140, 159, 20, 124, 154}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 206}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 20, 48, 131}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 117, 149, 140, 224, 101, 237, 95}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 222}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 74}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 102}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 15}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 23, 68, 28, 133, 230, 212}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 22, 255, 251, 87, 103, 237}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 227, 218, 140, 56, 106, 94, 217}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 72, 106, 7}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 218, 132, 46}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 53, 136, 132}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 150, 16, 68, 157}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 37}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 102, 107, 161}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 39, 105}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 246, 100}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 94}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 66, 12, 94, 243, 15, 14}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 133, 164, 171, 168}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 111, 30, 185}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 93, 108, 105, 160, 218, 42, 10}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 172, 175, 88, 240, 75, 216}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 98, 204}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 54, 195, 7, 124, 202}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 244, 75, 165, 181, 31, 254}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 182, 43, 146, 131, 12, 139}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 24, 101}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 125, 11, 81, 245, 39}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 188, 11, 249, 13, 93, 214}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 170, 28, 84, 53, 29}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 207, 229, 40}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 80, 213, 38, 45, 127}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 176, 41, 183, 159, 193, 248, 56}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 234, 220}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 95, 237, 92, 214, 167}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 154, 39, 86, 53, 1, 100, 99}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 99, 226, 184, 104, 237}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 9, 199}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 223, 180, 153, 76}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 212, 205}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 35}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 71, 175, 189, 161, 106, 131, 44}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 51, 148, 233, 51, 7, 156, 97}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 52, 154, 25}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 59}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 65, 196, 44, 115}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 121, 51}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 76, 185, 56}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 146, 222, 40, 113, 227, 78}, 178}, {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 41, 99, 71}, 178}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 181, 233, 32, 215, 68, 50, 149}, 179}, {{178, 130, 0, 0, 145, 62, 123, 157, 251, 109, 76, 131, 134, 239, 179, 98}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 198}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 204, 202, 210, 124, 227, 34}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 234, 95, 221, 140, 1, 34, 67, 29, 172}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 7, 91, 123}, 179}, {{178, 130, 0, 0, 0, 0, 145, 175, 224, 56, 111, 52, 150, 90, 30, 86}, 179}, {{178, 130, 0, 0, 245, 163, 203, 105, 151, 216, 170, 231, 109, 215, 193, 214}, 179}, {{178, 130, 0, 230, 4, 41, 23, 202, 108, 17, 145, 197, 101, 29, 33, 64}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 250, 47, 251}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 5}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 147}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 153, 186, 29, 181}, 179}, {{178, 130, 0, 109, 116, 132, 7, 54, 119, 71, 212, 19, 105, 141, 181, 164}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 209, 9}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 163}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 105, 78, 77, 121, 68, 164, 53}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 166, 27, 88, 34, 86, 68}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 89, 84, 61, 162, 34, 211, 228}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 24, 4}, 179}, {{178, 130, 0, 0, 0, 86, 78, 228, 155, 129, 31, 156, 16, 210, 116, 238}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 238}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 9, 174, 199, 62, 139, 234}, 179}, {{178, 130, 0, 0, 214, 227, 131, 210, 142, 166, 43, 130, 108, 129, 118, 5}, 179}, {{178, 130, 0, 202, 193, 53, 4, 3, 235, 231, 142, 18, 196, 213, 254, 194}, 179}, {{178, 130, 0, 239, 158, 1, 12, 158, 46, 222, 237, 64, 75, 221, 45, 144}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 194, 16, 223}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 50, 218, 232, 156, 181, 35, 5}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 222, 206, 228, 114, 76, 239, 105, 224, 129, 246}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 197}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 141}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 193, 159, 230, 62}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 137, 77, 73, 228, 124, 198, 107, 131}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 43}, 179}, {{178, 130, 0, 0, 0, 0, 108, 237, 168, 129, 79, 232, 102, 101, 218, 136}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 212, 50}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 224, 131, 187, 204, 122, 204, 219}, 179}, {{178, 130, 0, 0, 116, 227, 174, 133, 188, 160, 182, 136, 94, 23, 234, 39}, 179}, {{178, 130, 0, 0, 0, 0, 0, 87, 227, 36, 237, 120, 199, 144, 140, 126}, 179}, {{178, 130, 0, 0, 54, 220, 93, 176, 190, 97, 204, 122, 182, 245, 74, 196}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 87, 91, 83, 186, 133, 183}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 124, 84, 0, 170, 7, 77, 3, 115, 176}, 179}, {{178, 130, 0, 0, 0, 0, 173, 239, 30, 62, 70, 228, 168, 35, 134, 160}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 58, 77}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 147, 189, 40, 24, 199, 145, 8, 4, 61, 104}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 183, 160, 34, 209, 23, 219}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 123, 28}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 179}, {{178, 130, 0, 0, 0, 177, 210, 62, 179, 139, 91, 224, 236, 57, 144, 230}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 207, 6, 166, 45}, 179}, {{178, 130, 0, 0, 0, 0, 0, 9, 165, 213, 94, 234, 72, 23, 156, 226}, 179}, {{178, 130, 0, 158, 141, 59, 222, 117, 197, 236, 187, 198, 89, 32, 229, 211}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 194, 202, 165, 109, 120, 143, 224}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 158, 205, 124, 134, 195, 13, 96, 143}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 165, 15}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 37}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 179}, {{178, 130, 0, 90, 166, 242, 59, 109, 77, 181, 12, 171, 169, 120, 201, 238}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 33, 12, 55, 1, 171, 50, 165, 233}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 192, 155, 84, 155, 32, 2, 123, 17, 46, 166, 247, 103}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 186}, 179}, {{178, 130, 0, 0, 241, 247, 104, 160, 9, 92, 39, 83, 159, 156, 156, 75}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 38, 24, 166, 146, 206, 17, 60, 2}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 208}, 179}, {{178, 130, 0, 0, 0, 0, 213, 239, 141, 249, 148, 233, 217, 183, 198, 32}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 46, 210, 255}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 104, 66, 74, 172, 51, 140, 41, 255}, 179}, {{178, 130, 0, 0, 0, 215, 171, 167, 74, 183, 35, 104, 52, 74, 119, 236}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 161, 56, 188, 105, 116, 99, 91, 88}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 200, 56, 255, 148}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 60, 245}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 6}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 150, 93, 235, 85, 209, 65}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 126, 26, 229, 162, 133, 158, 83}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 58, 228, 107, 122, 60, 84, 209}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{178, 130, 0, 0, 0, 119, 2, 223, 227, 43, 16, 33, 174, 29, 101, 11}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 62, 125, 216, 21}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 11}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 204}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 156, 138, 246}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 56}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 191, 146, 33, 122, 7, 86, 244, 114}, 179}, {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 47, 71, 99}, 179}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 138}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 217, 233}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 123}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 40, 242, 255, 143}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 216, 61}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 136, 50, 40}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 29}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 39}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 208, 217, 212, 232}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 98}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 200, 218, 73}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 36}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 120, 48, 173}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 92, 33, 37, 224, 7}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 239, 100}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 167, 209}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 221, 83, 97}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 229, 169, 33}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 138, 17, 38}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 60, 24, 219, 77}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 158, 124}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 82}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 24, 244, 114}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 91, 29, 249}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 166}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 91, 137}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 167, 154, 59}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 253, 41, 172}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 38, 123}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 12, 220}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 71, 140, 71, 34}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 33, 55}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 188, 157, 61}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 143}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 169, 152}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 249, 126}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 31, 52, 236, 242, 229}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 201, 247, 93}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 113, 6}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 117}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 13, 68, 26}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 206, 151, 180, 86}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 95, 83}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 76}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 62}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 92}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 141}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 107}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 86}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 230, 120, 216, 145}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 161}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 186, 125}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 68, 138}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 17}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 169, 138}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 32, 48}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 219, 144, 116, 75}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 92, 37, 138, 251}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 129, 128, 61}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 23, 82, 138}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 40, 141}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 100, 86, 224, 120}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 203}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 58, 54, 189, 144}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 239, 154, 140}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 13}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 84, 143, 19}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 186, 167, 45, 238}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 200, 91, 251}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 227}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 250, 110, 205, 171}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 247, 133}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 212}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 79, 81}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 199}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 118, 95}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 82, 19, 246}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 129}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 224}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 133, 71, 226}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 172, 190, 126, 214}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 169, 244}, 236}, {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 131, 194, 120, 85}, 236}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 193, 129}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 255}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 107, 159}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 117, 203, 122}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 76, 188}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 174, 43}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 220}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 48, 114, 4}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 143, 167, 145}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 209}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 239, 40}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 181}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 227}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 128}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 14, 25}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 118, 167}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 42, 187}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 181}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 181, 164, 117}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 169, 226}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 243}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 195}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 245}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 139, 81}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 53}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 67, 159, 126}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 176, 152, 96}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 74}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 165}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 75, 28, 255}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 29}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 201, 248}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 22}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 198}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 133, 197, 11}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 167}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 100, 24}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 161, 62, 255}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 238}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 156, 24, 132}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 150}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 119, 218}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 228, 38}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 38, 99}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 204}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 211}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 86}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 182}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 56}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 75}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 38, 151, 126}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 217, 148}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 185}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 75, 163, 158}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 220, 41}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 38, 19}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 3}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 244, 148}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 70}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 41}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 115}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 96, 65}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 54}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 110}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 63}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 198, 90, 237}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 17, 178, 232}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 148, 189}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 7, 0}, 184}, {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 30}, 184}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 207, 246}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 194}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 185}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 221}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 11}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 14, 85, 191}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 174, 9, 185}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 255, 21}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 119, 125, 152}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 175, 209, 202}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 235, 5}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 83, 232, 211}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 233, 241, 255}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 159}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 56, 47, 191}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 215}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 143}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 171, 187}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 159, 123, 152}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 36, 48, 83, 245}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 107, 75, 141}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 123, 9, 107}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 84}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 117}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 204}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 136}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 158}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 238, 44, 175}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 147, 65}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 248, 198}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 60, 253}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 135}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 10}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 62}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 2}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 60, 63, 94, 15}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 183, 77, 182, 190}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 141, 157}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 138}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 4, 51}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 174, 213}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 173, 176, 98}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 227, 136, 206, 227}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 37}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 244}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 195}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 67, 75, 31, 42}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 133, 91, 83}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 117, 4, 233}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 84, 42}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 64}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 42, 201, 23}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 55}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 94, 46}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 107, 219, 3}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 28, 43, 226}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 121, 212}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 217, 27, 241}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 108, 67}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 16, 227, 96}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 101, 233}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 21}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 13, 237}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 239}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 192, 233}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 205, 27}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 204, 77, 63, 246}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 112}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 138}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 193, 116, 169}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 231}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 116, 152}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 247}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 107}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 198, 191, 136}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 17}, 95}, {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 223}, 95}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 152}, {{64, 0, 0, 0, 0, 0, 0, 0, 188, 2, 50, 189, 32, 193, 16, 67}, 84}, {{64, 0, 240, 79, 27, 61, 108, 140, 10, 144, 205, 204, 108, 21, 178, 39}, 84}, {{64, 0, 0, 0, 167, 93, 84, 244, 103, 80, 13, 174, 161, 210, 15, 201}, 84}, {{64, 0, 0, 0, 0, 0, 32, 76, 80, 104, 232, 229, 205, 85, 152, 187}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 221, 22, 17, 177, 235, 184, 155}, 84}, {{64, 0, 0, 0, 0, 43, 200, 211, 246, 157, 217, 197, 151, 114, 132, 181}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 6, 44, 51, 63, 10, 25, 81, 176}, 84}, {{64, 0, 0, 0, 0, 0, 0, 199, 168, 134, 149, 86, 17, 49, 251, 146}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 205}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 108, 45, 141, 195, 98, 195, 39}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 23}, 84}, {{64, 0, 95, 161, 207, 75, 88, 144, 105, 151, 125, 73, 118, 229, 21, 55}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 168, 168, 57, 230, 76}, 84}, {{64, 0, 0, 0, 0, 135, 192, 33, 57, 241, 29, 68, 108, 232, 197, 81}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 8, 46, 102, 181, 216}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 122, 152, 192, 243}, 84}, {{64, 0, 0, 0, 0, 194, 75, 60, 232, 221, 151, 122, 249, 45, 37, 14}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 234}, 84}, {{64, 0, 0, 0, 0, 11, 211, 55, 56, 153, 148, 233, 236, 217, 99, 235}, 84}, {{64, 247, 218, 113, 36, 122, 237, 82, 122, 173, 20, 164, 32, 205, 124, 42}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 181, 145, 223, 50, 190}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 84}, {{64, 0, 0, 0, 43, 172, 167, 124, 136, 62, 134, 21, 93, 85, 22, 233}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 140, 105, 63, 160, 28, 141, 130, 172}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 183, 253, 44, 11, 83}, 84}, {{64, 107, 159, 210, 73, 143, 208, 188, 78, 57, 13, 111, 31, 190, 229, 220}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 208, 107, 90, 80, 2}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 226, 221, 226, 254, 87, 29, 24, 196, 115, 136, 201, 53}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 84}, {{64, 0, 0, 166, 171, 206, 252, 172, 155, 191, 160, 214, 206, 110, 122, 220}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 236, 38, 165, 109, 104, 140, 187, 98, 141, 83}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 119}, 84}, {{64, 0, 0, 0, 0, 0, 0, 21, 110, 88, 123, 85, 189, 235, 68, 242}, 84}, {{64, 242, 83, 50, 117, 229, 211, 55, 163, 102, 188, 214, 76, 170, 48, 200}, 84}, {{64, 0, 0, 0, 0, 0, 0, 51, 45, 250, 11, 235, 216, 49, 193, 205}, 84}, {{64, 0, 0, 0, 0, 0, 236, 140, 75, 247, 189, 143, 138, 88, 78, 219}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 125, 138}, 84}, {{64, 0, 0, 0, 0, 0, 22, 182, 216, 234, 78, 153, 63, 3, 186, 136}, 84}, {{64, 0, 0, 0, 0, 159, 79, 17, 1, 179, 109, 247, 73, 248, 106, 16}, 84}, {{64, 0, 242, 143, 3, 182, 193, 67, 244, 146, 89, 60, 156, 184, 225, 147}, 84}, {{64, 0, 0, 0, 0, 4, 136, 85, 173, 164, 169, 145, 49, 44, 12, 255}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 208, 115, 178, 84}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 84}, {{64, 0, 0, 0, 0, 0, 116, 161, 95, 154, 7, 209, 229, 210, 187, 43}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 120, 8, 109, 204, 137}, 84}, {{64, 0, 0, 0, 0, 0, 0, 86, 186, 150, 94, 88, 129, 18, 144, 202}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 137, 7, 179, 210, 89, 137, 203}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 43, 55, 198, 119, 30, 167, 117, 1}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 108, 103, 176, 244, 5, 181, 27}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 121, 136, 84, 225, 226, 212, 239, 71, 98, 91, 87, 14, 83, 191}, 84}, {{64, 153, 100, 144, 145, 12, 242, 204, 120, 178, 46, 223, 33, 81, 36, 138}, 84}, {{64, 0, 0, 0, 0, 0, 0, 2, 58, 214, 72, 109, 121, 229, 110, 194}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 125, 22, 106}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 64, 10, 50}, 84}, {{64, 0, 0, 0, 225, 86, 218, 201, 174, 164, 58, 252, 51, 0, 248, 177}, 84}, {{64, 0, 108, 126, 8, 252, 134, 162, 76, 46, 129, 86, 46, 225, 234, 84}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 52, 175, 246, 133, 145, 227, 240, 235, 98, 60, 66, 14, 225, 166}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 78, 174, 234, 221, 91}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 142, 128, 141, 163, 154}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 84, 3, 167, 133}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 254, 237, 250, 137, 61}, 84}, {{64, 0, 228, 130, 148, 127, 144, 103, 176, 90, 14, 56, 154, 133, 233, 103}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 227, 18}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 73, 199, 121, 33, 212, 130, 200, 212, 11, 14, 97, 4, 5, 67}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 119, 108}, 84}, {{64, 0, 0, 0, 247, 114, 143, 34, 139, 83, 144, 88, 192, 149, 254, 53}, 84}, {{64, 0, 52, 70, 54, 230, 160, 4, 203, 194, 231, 81, 64, 71, 103, 91}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 45, 108, 88}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 112, 13, 90, 120, 111, 252, 121}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 11, 159, 44}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 242, 204, 92, 207, 91, 240, 228, 65}, 84}, {{64, 212, 102, 109, 230, 24, 245, 40, 248, 217, 224, 36, 247, 120, 199, 2}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 3}, 84}, {{64, 0, 0, 0, 0, 0, 115, 243, 23, 142, 141, 95, 7, 151, 146, 124}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 164, 66, 94, 36, 75}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 113, 124, 151, 190, 224, 172, 138}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 44, 125, 197, 197, 86, 184, 233, 89, 10, 30}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 181}, 84}, {{64, 0, 14, 249, 233, 170, 40, 79, 172, 92, 245, 53, 67, 196, 97, 158}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 120, 120, 166, 230}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 163, 85, 43, 24, 138, 103, 95, 92}, 84}, {{64, 0, 0, 0, 87, 197, 238, 6, 131, 153, 202, 165, 236, 87, 216, 167}, 84}, {{64, 175, 245, 164, 121, 58, 114, 224, 105, 113, 238, 68, 42, 239, 205, 0}, 84}, {{64, 0, 0, 49, 234, 247, 67, 129, 63, 184, 66, 36, 76, 41, 66, 227}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 223, 108, 211, 206, 182, 15, 30, 83}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 205, 141, 157, 88, 24, 104, 24}, 84}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 226}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 56}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 90, 178}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 53}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 254}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 129}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 205}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 32}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 219, 180}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 146}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 255, 31}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 202}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 101, 90}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 65}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 110}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 187, 121}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 152, 4}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 159}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 88}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 97, 38}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 182, 149}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 90}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 55}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 164}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 33}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 112, 14}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 176}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 101}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 240}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 59}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 65}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 193, 229}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 62, 17}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 14, 145}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 162}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 44}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 8, 157}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 209}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 162}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 33}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 54}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 234, 107}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 164}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 8, 93}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 177}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 79}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 33}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 175}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 168, 193}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 83}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 131, 203}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 237}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 89}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 233}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 7}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 121}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 12, 12}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 233, 98}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 3}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 26, 69}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 65, 95}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 206}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 248}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 242}, 137}, {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 81}, 137}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 163, 73, 248, 59, 208, 167}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 246, 50, 104}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 62, 210, 85, 110, 223, 90}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 226, 219, 169, 101, 9, 62}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 107, 220}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 29, 91}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 24, 80, 57, 79, 173, 51, 40}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 92, 195, 23, 134, 144, 23, 223}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 83, 38, 253, 5, 81, 137, 235}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 69, 197}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 49, 187, 227}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 20, 82, 221, 157, 75, 74, 71}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 252, 19, 114, 20, 145, 199, 200, 167}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 224}, {{104, 46, 25, 71, 86, 220, 0, 252, 16, 90, 187, 126, 88, 178, 59, 19}, 224}, {{104, 46, 25, 71, 86, 220, 155, 192, 55, 67, 26, 205, 36, 101, 105, 119}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 6, 207, 239, 133, 35, 152, 52}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 13, 98}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 66, 158}, 224}, {{104, 46, 25, 71, 86, 220, 2, 53, 164, 160, 37, 232, 204, 205, 202, 248}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 61, 62, 174, 129, 44, 189, 71, 229}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 246, 95, 11, 71}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 77, 43}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 97, 9, 25}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 79, 240, 72, 231, 241, 51, 201}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 51, 134, 189, 149, 123, 4, 116}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 140, 105, 148}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 93, 2}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 198, 215}, 224}, {{104, 46, 25, 71, 86, 220, 0, 18, 61, 240, 192, 59, 184, 101, 89, 180}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 212, 248, 166, 96, 130, 174, 13, 158}, 224}, {{104, 46, 25, 71, 86, 220, 0, 216, 119, 126, 116, 43, 26, 12, 213, 101}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 41, 10, 98, 23, 168, 63, 45, 59}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 146, 157, 224, 79, 37}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 17, 90, 70, 163, 59, 239}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 46, 109, 120, 26, 105, 155, 181, 166}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 125, 44}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 112, 219, 25, 181, 13, 193, 133}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 139, 143, 121, 164, 250, 39}, 224}, {{104, 46, 25, 71, 86, 220, 0, 251, 64, 4, 0, 12, 198, 139, 235, 254}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 65, 221}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 251, 158, 150, 84, 133, 211}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 199, 223, 47, 225, 115, 213, 81, 68, 44}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 165, 195, 147, 213, 96, 17, 230}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 140, 195, 153, 15, 60, 171, 81, 251}, 224}, {{104, 46, 25, 71, 86, 220, 0, 236, 12, 63, 158, 238, 231, 8, 78, 123}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 1, 41, 119, 98}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 217, 236, 119, 23}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 131, 191, 0, 92, 181, 83, 240, 67}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 218, 177, 74, 197, 68, 196, 72, 149}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 39, 155}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 182, 221}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 49, 92, 75, 203, 71, 4, 240, 61}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 16, 183, 200, 237, 155, 34, 180, 169}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 186, 166, 155, 156, 238}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 199, 130, 69, 245, 77, 116, 186, 10, 129}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 151, 134, 188}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 97, 240, 129, 82, 80, 194}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 69, 229, 42, 22}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 35, 144, 220, 123}, 224}, {{104, 46, 25, 71, 86, 220, 0, 241, 193, 254, 219, 145, 151, 252, 167, 65}, 224}, {{104, 46, 25, 71, 86, 220, 0, 75, 187, 218, 229, 253, 239, 171, 249, 113}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 46, 195, 210, 7, 183, 50}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 221, 27, 24, 89, 167, 255, 232}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 63, 102, 57, 10, 253, 201, 14, 112}, 224}, {{104, 46, 25, 71, 86, 220, 0, 174, 244, 137, 225, 14, 172, 251, 47, 252}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 21, 240, 70, 113}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 53, 189, 49}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 28, 97, 195, 215, 120}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 1, 224, 0, 172, 15, 235}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 170, 43, 182, 178, 16}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 203, 128, 38, 36}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 88, 130, 235, 59, 219, 48, 229, 217, 12}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 196, 106, 30, 234, 203, 148, 167}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 44, 21, 213, 199, 31, 81, 78}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 20, 154, 65, 104, 156}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 9, 224, 183, 114}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 130, 254, 179, 190, 179}, 224}, {{104, 46, 25, 71, 86, 220, 0, 241, 62, 155, 104, 133, 238, 37, 179, 119}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{104, 46, 25, 71, 86, 220, 0, 0, 71, 221, 0, 220, 22, 175, 64, 252}, 224}, {{104, 46, 25, 71, 86, 220, 0, 75, 223, 198, 82, 28, 254, 175, 133, 76}, 224}, {{0, 0, 0, 0, 0, 0, 247, 48, 239, 34, 6, 131, 144, 5, 119, 109}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 202, 26, 209, 3, 121, 194}, 61}, {{0, 0, 0, 0, 0, 179, 89, 74, 250, 222, 111, 117, 103, 193, 101, 45}, 61}, {{0, 0, 0, 0, 0, 0, 200, 108, 98, 122, 215, 242, 189, 40, 209, 218}, 61}, {{0, 0, 0, 0, 0, 0, 39, 153, 13, 51, 254, 222, 72, 229, 217, 107}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 65, 138, 58, 179, 254, 163, 82, 73}, 61}, {{0, 0, 0, 0, 0, 0, 196, 252, 122, 215, 19, 84, 9, 237, 31, 193}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 162, 81, 122}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 74, 45, 106, 196, 183, 64}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 61}, {{0, 0, 0, 0, 141, 163, 204, 83, 126, 21, 92, 53, 51, 42, 104, 250}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 61}, {{0, 0, 0, 0, 94, 91, 27, 191, 71, 207, 143, 192, 174, 55, 241, 231}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 185, 173}, 61}, {{0, 25, 22, 107, 194, 244, 209, 205, 123, 47, 73, 147, 111, 223, 59, 129}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 145, 90, 82}, 61}, {{0, 0, 0, 0, 0, 191, 219, 129, 154, 140, 22, 36, 143, 174, 104, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 211}, 61}, {{0, 0, 0, 0, 0, 0, 0, 68, 205, 194, 29, 123, 154, 95, 46, 176}, 61}, {{0, 0, 0, 0, 0, 157, 242, 185, 84, 146, 30, 152, 11, 125, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 61}, {{0, 0, 0, 75, 147, 197, 88, 1, 78, 253, 93, 75, 60, 198, 149, 47}, 61}, {{0, 0, 0, 27, 255, 177, 209, 74, 46, 113, 50, 161, 83, 146, 252, 241}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 154, 196, 42, 61, 204, 236}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 61}, {{0, 0, 0, 0, 0, 0, 0, 2, 181, 128, 182, 245, 53, 120, 37, 164}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 197, 14, 190}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 124, 243, 63}, 61}, {{0, 0, 0, 0, 0, 2, 206, 147, 106, 151, 50, 165, 107, 191, 108, 244}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 213, 38, 186}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 61}, {{0, 0, 0, 0, 0, 0, 215, 217, 27, 216, 241, 219, 5, 42, 128, 80}, 61}, {{0, 0, 0, 0, 0, 50, 237, 230, 189, 154, 122, 254, 8, 28, 233, 115}, 61}, {{0, 0, 0, 202, 158, 121, 10, 204, 47, 26, 206, 45, 29, 9, 32, 181}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 61}, {{0, 0, 0, 0, 0, 0, 83, 213, 40, 246, 73, 35, 30, 89, 221, 154}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 61, 95}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 202, 23, 174, 77}, 61}, {{0, 0, 202, 212, 164, 44, 179, 95, 199, 81, 33, 121, 78, 172, 24, 224}, 61}, {{0, 0, 0, 0, 0, 0, 187, 117, 6, 177, 175, 236, 161, 4, 192, 168}, 61}, {{0, 0, 0, 0, 213, 248, 199, 191, 158, 220, 9, 186, 110, 75, 225, 197}, 61}, {{0, 0, 0, 0, 0, 0, 0, 252, 61, 135, 75, 75, 0, 88, 22, 54}, 61}, {{0, 0, 0, 0, 0, 198, 28, 36, 117, 90, 144, 129, 251, 104, 117, 92}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 242, 168, 199, 158, 238, 166}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 130, 41, 150, 50, 66, 129, 156, 163, 40, 150, 250}, 61}, {{0, 0, 0, 0, 117, 233, 14, 132, 187, 0, 228, 84, 141, 54, 192, 60}, 61}, {{0, 0, 0, 0, 0, 0, 51, 89, 254, 164, 197, 70, 196, 104, 82, 53}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 209, 131, 201}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 66}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 76, 135, 202, 1, 156, 16}, 61}, {{0, 0, 0, 0, 0, 244, 138, 235, 216, 229, 114, 112, 9, 101, 99, 179}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 55, 194, 253}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 18, 162, 161, 139, 110, 190, 242, 184}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 28, 204, 59}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 143, 66, 52, 249}, 61}, {{0, 0, 0, 0, 0, 0, 0, 132, 150, 164, 85, 165, 99, 225, 18, 159}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 230, 44, 162, 173, 148, 245, 123, 72}, 61}, {{0, 0, 0, 158, 228, 142, 173, 2, 166, 255, 170, 245, 11, 109, 26, 110}, 61}, {{0, 0, 243, 213, 101, 130, 175, 72, 72, 8, 209, 248, 255, 58, 17, 178}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 103, 86, 76, 17, 12, 75, 194, 226}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 108, 183, 183, 98, 204, 158}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 192}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 86, 115, 191}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 57, 216, 122}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 121, 156, 15, 178, 224, 215}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 172, 217}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 158, 211, 58, 91, 53}, 61}, {{0, 0, 0, 0, 0, 0, 0, 136, 84, 177, 84, 198, 146, 186, 114, 92}, 61}, {{0, 0, 0, 0, 0, 0, 0, 134, 141, 12, 56, 60, 19, 227, 222, 236}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 92, 54, 254, 76, 141, 88, 10, 159}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 151}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 197, 109}, 61}, {{0, 0, 0, 0, 0, 0, 185, 26, 107, 251, 146, 178, 136, 194, 169, 249}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 14, 88, 148, 0, 81, 116}, 61}, {{0, 0, 0, 0, 0, 0, 173, 166, 51, 114, 107, 79, 46, 27, 46, 36}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 71, 145, 179, 145}, 61}, {{0, 0, 0, 0, 0, 237, 205, 42, 18, 28, 234, 157, 100, 60, 225, 82}, 61}, {{0, 0, 0, 189, 211, 93, 219, 220, 210, 224, 213, 77, 110, 160, 93, 242}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 115, 245}, 61}, {{0, 0, 0, 0, 0, 0, 152, 157, 200, 192, 179, 143, 117, 252, 179, 30}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 243, 227, 111, 45}, 61}, {{0, 0, 0, 0, 0, 182, 70, 169, 180, 132, 31, 29, 86, 208, 135, 211}, 61}, {{0, 0, 0, 0, 41, 190, 200, 141, 155, 78, 221, 241, 46, 89, 165, 110}, 61}, {{0, 0, 0, 0, 0, 208, 174, 78, 157, 245, 237, 66, 88, 142, 147, 189}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 46}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 156, 119, 24, 27}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 80, 167, 41, 120, 235, 173, 45, 195}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 222, 175, 93, 58, 43, 29}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 77, 234, 124, 76, 58}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 107, 33, 128, 200, 108}, 61}, {{0, 0, 0, 19, 75, 149, 79, 157, 87, 111, 148, 120, 247, 255, 195, 187}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 87, 224, 171, 181, 204, 49, 159, 37}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 236, 255, 49}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 54, 234, 223}, 61}, {{0, 0, 0, 0, 0, 0, 246, 9, 77, 115, 142, 244, 231, 179, 156, 65}, 61}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 154, 0, 120, 85}, 205}, {{241, 113, 254, 106, 53, 128, 0, 69, 139, 11, 21, 183, 95, 153, 171, 49}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 136, 142, 254, 38, 249, 105, 109, 209}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 113, 48, 81, 29}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 52, 244}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 82, 68, 34, 235, 201, 197, 117}, 205}, {{241, 113, 254, 106, 53, 128, 93, 238, 33, 59, 55, 91, 204, 205, 104, 202}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 69, 177, 21, 116}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 23, 75}, 205}, {{241, 113, 254, 106, 53, 128, 0, 77, 33, 250, 134, 112, 104, 48, 84, 253}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 252, 120, 180, 226, 43, 80, 88, 122}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 116, 215}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 21, 247, 33}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 73, 148, 186, 96, 178, 167}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 118, 62, 25, 226, 166, 94, 245}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 189, 244, 69, 135, 44}, 205}, {{241, 113, 254, 106, 53, 128, 0, 192, 89, 155, 30, 227, 249, 74, 114, 42}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 181, 163, 40, 215}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 236, 113, 165, 89, 169, 242}, 205}, {{241, 113, 254, 106, 53, 128, 0, 3, 68, 97, 92, 164, 69, 205, 200, 217}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 142, 51, 135, 134, 253, 53}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 9, 211, 181, 129, 193, 178, 154}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 30, 151, 27, 142, 131, 128}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 209, 6, 72, 22, 174, 150, 243}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 52, 238, 125, 94, 187, 144, 16, 230}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 181, 132, 201, 197, 115, 251, 127, 178}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 27, 230, 87, 154, 0, 209, 19}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 176, 57, 132, 225, 176, 80}, 205}, {{241, 113, 254, 106, 53, 128, 0, 247, 80, 202, 115, 183, 82, 128, 161, 184}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 53, 28, 170, 62}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 239, 206, 92, 224, 200, 189, 138}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 51, 56, 57, 132, 229, 104, 126, 15, 68, 5}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 179, 209, 75}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 177, 55, 235, 79}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 217, 20, 235, 149, 211, 162, 150}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 29, 191, 66}, 205}, {{241, 113, 254, 106, 53, 128, 96, 182, 223, 181, 177, 40, 73, 215, 80, 51}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 211, 142, 111, 1}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 150, 106, 31}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 134, 27}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 60, 130, 217}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 209, 116, 61}, 205}, {{241, 113, 254, 106, 53, 128, 0, 66, 194, 49, 204, 32, 19, 196, 26, 148}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 205}, {{241, 113, 254, 106, 53, 128, 0, 215, 34, 89, 178, 187, 157, 15, 78, 165}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 17, 83, 25, 239, 20, 230}, 205}, {{241, 113, 254, 106, 53, 128, 0, 136, 130, 52, 53, 218, 93, 26, 204, 28}, 205}, {{241, 113, 254, 106, 53, 128, 0, 83, 253, 152, 50, 88, 125, 133, 12, 183}, 205}, {{241, 113, 254, 106, 53, 128, 0, 41, 53, 38, 236, 164, 19, 128, 84, 16}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 195, 201}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 144, 192, 184, 45, 180}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 137, 119, 97, 3, 172, 34, 76, 122}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 20, 130, 217, 155, 147}, 205}, {{241, 113, 254, 106, 53, 128, 0, 204, 148, 92, 222, 163, 214, 214, 5, 166}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 157, 65}, 205}, {{241, 113, 254, 106, 53, 128, 0, 33, 145, 254, 217, 243, 59, 59, 57, 141}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 233, 212}, 205}, {{241, 113, 254, 106, 53, 128, 0, 153, 252, 154, 255, 243, 92, 103, 142, 212}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 102, 244, 171}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 38, 168, 83, 152}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 23, 211, 212, 15, 116, 11}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 110, 123, 222, 108, 78, 200}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 48, 89, 118, 56, 11, 214}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 230, 89}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 41, 146, 4}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 87, 191, 102, 170, 169, 166}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 151, 145, 0, 194, 64, 74, 52}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 143, 65, 180, 240, 65, 83, 195, 158}, 205}, {{241, 113, 254, 106, 53, 128, 92, 224, 145, 108, 4, 9, 155, 35, 245, 135}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 132, 27, 107, 88, 66, 77}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 172, 182, 82, 212, 185}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 97, 144, 221, 58, 184}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 73, 90, 173, 58}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 59, 15, 26, 163, 78, 221, 107, 253}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 40, 193, 84, 239, 29, 114, 144}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 92, 233, 208, 255}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 74, 122}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 47, 100, 21, 184, 190, 214, 167, 1}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 230, 36, 72}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 150, 139, 188, 122}, 205}, {{241, 113, 254, 106, 53, 128, 0, 110, 191, 238, 164, 6, 220, 156, 20, 72}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 138, 97, 112}, 205}, {{241, 113, 254, 106, 53, 128, 0, 0, 217, 57, 231, 10, 94, 202, 224, 189}, 205}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 170}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 73, 247, 25, 34, 26}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 94, 178, 5, 221, 29, 75, 88}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 128, 138, 254}, 117}, {{58, 29, 129, 94, 43, 139, 224, 86, 85, 179, 128, 223, 245, 105, 158, 66}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 39, 193, 49}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 218, 184, 132, 3, 110}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 226, 95, 130, 234, 30, 12}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 184, 29, 47, 244, 42, 58, 187}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 67, 48, 34}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 239, 123, 209, 115}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 111, 76, 62, 92, 162, 193, 113, 236}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 79, 142, 9, 13, 74, 81, 155}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 38, 148}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 76, 56, 219, 174, 245, 73, 98}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 253, 48, 14, 67, 84, 201, 153}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 58, 9}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 82, 206, 160, 148, 98, 50, 81}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 119, 108}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 67, 202, 103, 75}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 21, 112, 194, 126, 6, 168, 80, 28}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 124, 232, 180, 188, 193, 100, 229, 181, 42}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 106, 54, 74}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 179, 94, 12, 244, 64, 161, 150}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 93, 186, 206}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 62, 0, 179, 114, 192, 240, 128}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 188, 63, 253, 52, 28, 148, 62, 219}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 97, 117, 5, 162, 67}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 163, 111, 133, 68, 250, 20, 84}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 248, 18, 177}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 101, 86, 200}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 180, 106, 49, 171, 69, 49}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 206, 98, 89, 195, 95}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 75, 107}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 155, 216, 231, 108, 84, 12}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 179, 147, 47, 109, 187}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 64, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 172, 155, 138, 66, 99, 146}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 215, 168, 97, 203, 136, 139, 44}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 112, 1, 226, 74}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 139, 236, 146, 65, 85, 177}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 202, 111, 79, 166, 130, 23}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 211, 200, 190}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 126, 111, 214, 82, 168, 31}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 214, 29, 76, 115, 197, 43, 8}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 152, 245, 167, 41, 57, 126, 9}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 122, 152, 40, 10}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 213, 93, 1}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 47, 61, 255}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 65, 77, 25, 152}, 117}, {{58, 29, 129, 94, 43, 139, 224, 94, 159, 0, 165, 130, 189, 133, 52, 176}, 117}, {{58, 29, 129, 94, 43, 139, 224, 149, 21, 97, 147, 127, 212, 160, 101, 19}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 6, 153, 111, 13, 76, 93}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 197, 153, 187, 25}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 171, 1, 161, 146, 144, 85, 187, 192}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 158, 167, 31, 204, 114}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 124, 134, 197, 230, 69}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 203, 197}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 95, 249}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 3, 246, 125, 91, 254, 60}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 111, 233, 253, 148}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 112, 24, 197, 2, 203}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 33, 217, 143, 60, 134, 25}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 57, 49, 98, 235, 235, 7, 230, 118}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 173, 174, 61, 54, 215}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 254, 179, 123, 200, 167, 97, 181}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 202, 235, 173, 181}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 188, 198, 167}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 134, 222, 154, 241}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 197, 118}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 113, 124, 156, 63, 72}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 223, 135, 68}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 151, 121, 100}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 231, 246, 199}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 151, 101, 96, 177}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 194, 14, 7}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 33, 69, 211, 129, 102, 29}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 226, 174, 202, 187, 204, 86}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 147, 4}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 98, 191, 34, 159, 157}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 194, 248, 225, 143, 67, 203, 117}, 117}, {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 219, 253, 253, 53, 49}, 117}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 246, 237, 248}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 68, 40, 24, 149}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 140, 51, 0, 124}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 81, 39, 210, 24, 32, 147}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 22, 167}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 139}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 53, 0, 222}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 131}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 201, 196, 15, 220}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 7, 55}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 154, 102, 205}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 139, 227}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 200, 71}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 102, 19, 213, 126, 250, 244}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 126, 15, 158}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 55, 197, 35, 119, 197, 16, 89}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 216, 233}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 63, 85, 163, 219}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 165}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 51, 93, 78, 91, 50, 105}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 98, 12, 121, 43, 171}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 223, 237, 246, 57, 12}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 131, 46}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 78, 171, 72, 166}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 43, 111, 10, 192, 82, 205}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 170}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 184, 189, 105, 191}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 2}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 97}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 166, 206, 92}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 8, 35, 226, 123, 208}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 138}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 29, 204, 172, 51, 141, 205}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 74, 45, 196, 61}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 181, 248, 97, 219}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 42}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 93, 234}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 246, 40}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 158, 134, 133, 157}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 234, 219, 190}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 161, 35}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 60}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 9, 112, 247, 108, 74, 155}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 223, 36, 192, 118, 97, 222, 31}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 143, 68, 210, 202}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 83, 12, 5}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 135, 129, 182}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 155, 121}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 45}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 145}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 222, 92, 141, 203, 141, 184}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 175, 13}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 60, 91, 5}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 31, 7, 100}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 112}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 187, 185, 85, 93, 122, 126, 146}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 218, 167, 118, 219}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 217, 74, 246, 70}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 118, 43, 168, 145}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 165, 113}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 66, 159, 98}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 92, 66, 205}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 233, 39, 80, 147, 172}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 156, 133, 211, 150, 132, 164}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 202, 27, 89, 121, 142, 46}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 188}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 146, 150, 212}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 186, 188, 162}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 16, 100}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 250, 163, 56, 155}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 242, 254, 32}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 44}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 69, 162, 159, 102, 156, 138, 81}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 90, 35, 20, 225, 176}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 196, 202, 171}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 138, 172, 158, 90, 227}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 16, 43, 49, 127, 236}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 98, 217}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 14, 69, 143}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 182}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 209, 113, 5, 118, 171, 45}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 205, 56, 229, 11}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 104, 188, 189, 11, 155}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 66, 225, 83, 240, 94, 189}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 134, 152, 55, 192, 207, 17}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 80, 28, 196, 127, 59}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 77, 11, 71, 242, 46, 131, 128}, 225}, {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 247, 138, 245}, 225}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 154, 76, 231, 52, 55}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 55, 25}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 47, 117}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 35, 170, 86, 128, 198}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 111, 211, 254, 103, 246}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 249, 123}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 163, 218, 117}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 150, 97, 30}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 201, 65}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 56, 133, 177, 73}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 133, 23, 192, 102}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 66, 223, 155, 48}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 42, 197, 218, 69, 186, 38}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 124, 242, 122, 147, 118}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 158, 233, 72}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 154, 206, 62, 217, 104, 255}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 21, 228}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 11, 165}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 83, 105}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 88, 68, 18, 222, 140}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 116}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 181, 36}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 230, 122, 108, 95, 173, 89}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 127, 105, 121, 214, 129, 166}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 3}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 234}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 3, 208}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 187, 157, 205, 181, 27}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 73, 220, 59, 41}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 135, 126, 18, 95}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 158}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 118, 94, 125, 26, 21}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 49}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 3, 96, 57, 158, 224, 174}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 194, 214, 2, 226}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 147, 127}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 149, 191, 22, 88, 178}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 113, 60, 144, 22, 107, 254}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 161}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 204, 213, 40, 41, 109}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 23}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 194, 7, 24, 182}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 85, 101, 7, 175}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 178, 240, 181, 135}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 242, 59, 17}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 119, 107}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 187, 10, 5, 11, 199}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 44, 202, 10, 216, 213}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 16, 97, 239, 169, 187}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 56, 205, 249}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 215}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 6, 130}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 68, 170, 170, 156}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 5, 148, 159, 180, 229, 165}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 31, 174, 225, 185}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 122, 76, 248, 88}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 163, 249}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 72, 251, 78, 50}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 237, 189, 5}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 204, 215, 71, 68}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 243}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 9, 79, 235}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 68, 193, 158, 246, 238, 115}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 68, 203, 3, 28, 74, 24}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 189}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 104, 183, 35, 227}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 120, 132}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 188, 68, 51, 210, 96}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 245, 233, 93}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 154, 22, 181, 193, 224}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 209, 220}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 158, 120, 204, 151, 164, 239}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 137, 127, 141, 228, 43, 66}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 241}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 6, 143, 175, 135, 74}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 140, 82}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 128, 237, 144}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 224}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 207, 255, 189}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 37, 112}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 122, 113, 245, 70, 18, 136}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 31}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 198}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 87, 174, 86, 13, 31}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 129, 209, 118}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 15, 160, 210, 52, 45, 5}, 34}, {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 93, 196, 178, 115, 84, 217}, 34}, {{186, 142, 128, 0, 0, 0, 0, 42, 58, 113, 181, 155, 54, 145, 207, 111}, 5}, {{186, 142, 128, 0, 207, 129, 175, 88, 22, 67, 49, 191, 159, 238, 254, 109}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 56, 73}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 19, 146, 41, 75, 5}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 99, 55, 14, 214, 107, 171}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 81, 134, 182, 217, 120, 81, 81, 103}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 212, 156, 193}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 141, 62, 56, 91, 54, 67, 121, 94}, 5}, {{186, 142, 128, 0, 0, 25, 249, 44, 162, 217, 21, 187, 156, 29, 198, 172}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 117, 23}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 142, 127}, 5}, {{186, 142, 128, 0, 84, 165, 201, 225, 43, 72, 214, 99, 2, 112, 184, 99}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 27, 105, 65, 58, 248}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 152, 102, 188, 116, 221, 22}, 5}, {{186, 142, 128, 0, 0, 0, 167, 191, 91, 133, 191, 191, 96, 29, 183, 211}, 5}, {{186, 142, 128, 0, 0, 0, 164, 96, 26, 236, 174, 125, 219, 129, 206, 144}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 0, 171, 169, 61, 39, 189, 19, 66, 214, 155}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 14, 255, 30}, 5}, {{186, 142, 128, 0, 152, 246, 213, 221, 241, 192, 79, 25, 68, 117, 14, 61}, 5}, {{186, 142, 128, 0, 0, 48, 65, 0, 72, 178, 200, 196, 115, 106, 128, 217}, 5}, {{186, 142, 128, 0, 0, 0, 255, 58, 148, 181, 188, 83, 154, 88, 93, 101}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 49}, 5}, {{186, 142, 128, 0, 108, 194, 35, 48, 161, 204, 77, 233, 26, 208, 185, 251}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 80, 101}, 5}, {{186, 142, 128, 0, 0, 139, 116, 4, 239, 163, 165, 178, 255, 212, 6, 162}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 91}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 186, 157, 132}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 64, 199, 61, 216, 231, 242, 39, 56}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 183, 247, 222, 251, 228}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 2, 253, 5, 93, 221, 37}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 243, 42, 108}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 32}, 5}, {{186, 142, 128, 0, 61, 253, 249, 102, 98, 62, 79, 120, 219, 144, 124, 228}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 225, 216, 35}, 5}, {{186, 142, 128, 0, 163, 174, 56, 14, 247, 237, 17, 148, 124, 57, 135, 56}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 130}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 30, 14, 151, 31, 219, 129}, 5}, {{186, 142, 128, 0, 73, 77, 206, 118, 74, 224, 48, 110, 58, 219, 119, 77}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 124, 241, 99}, 5}, {{186, 142, 128, 61, 133, 139, 184, 184, 181, 115, 183, 34, 33, 155, 219, 250}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 163, 7}, 5}, {{186, 142, 128, 0, 0, 0, 16, 132, 215, 188, 193, 159, 74, 130, 245, 189}, 5}, {{186, 142, 128, 0, 54, 146, 39, 30, 97, 142, 211, 50, 118, 249, 194, 197}, 5}, {{186, 142, 128, 0, 0, 0, 0, 12, 243, 166, 99, 104, 185, 20, 76, 8}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 242, 255, 221, 79, 26}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 30}, 5}, {{186, 142, 128, 0, 0, 166, 31, 46, 245, 43, 251, 81, 75, 198, 165, 18}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 49, 222, 133}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 220, 86, 65, 199, 37, 136, 234, 170}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 180}, 5}, {{186, 142, 128, 0, 0, 0, 118, 81, 118, 222, 250, 9, 166, 99, 121, 183}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 5}, {{186, 142, 128, 142, 215, 201, 120, 60, 228, 6, 101, 102, 96, 37, 144, 11}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 229, 23, 3, 151, 216}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 222, 252}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 132, 234, 119}, 5}, {{186, 142, 128, 0, 0, 0, 223, 215, 182, 123, 165, 201, 233, 54, 112, 253}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 89, 54, 215, 9, 158, 69, 32}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 145, 52, 135}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 42}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 28, 43, 216, 17, 25, 72, 184, 11, 167, 151}, 5}, {{186, 142, 128, 0, 0, 174, 1, 73, 18, 229, 27, 253, 112, 3, 148, 8}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 160, 179, 110, 22, 224, 77}, 5}, {{186, 142, 128, 0, 0, 0, 212, 178, 51, 205, 90, 48, 1, 208, 12, 186}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 110, 28, 157, 250, 49, 163, 222, 48}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 132, 47}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 249, 214, 213, 202, 92, 137}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 92}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 32, 37, 161, 247, 196, 15, 217, 77}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 112, 59, 173, 92, 37, 206, 132}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 103, 151, 98, 235, 244}, 5}, {{186, 142, 128, 0, 51, 90, 217, 140, 248, 82, 217, 165, 117, 172, 228, 168}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 19, 199, 95, 154, 104, 177, 197}, 5}, {{186, 142, 128, 0, 0, 35, 180, 174, 89, 128, 211, 32, 55, 81, 106, 151}, 5}, {{186, 142, 128, 0, 0, 0, 225, 223, 11, 113, 152, 226, 15, 18, 80, 219}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 38, 109, 217, 107, 65, 76, 151, 109}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 54, 36, 143}, 5}, {{186, 142, 128, 0, 0, 0, 99, 127, 65, 31, 213, 171, 90, 114, 84, 78}, 5}, {{186, 142, 128, 24, 160, 248, 135, 249, 153, 60, 222, 130, 60, 36, 233, 71}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 64, 96}, 5}, {{186, 142, 128, 179, 27, 161, 125, 24, 247, 235, 229, 183, 214, 75, 2, 10}, 5}, {{186, 142, 128, 42, 243, 151, 245, 217, 55, 69, 255, 209, 221, 135, 164, 9}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 190, 121, 26, 143, 89, 32, 167}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 153, 12, 182}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 85, 204, 248, 220, 55, 173, 161, 179}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 197, 118}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 190}, 5}, {{186, 142, 128, 0, 0, 236, 110, 141, 10, 120, 131, 244, 151, 253, 135, 92}, 5}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 143, 59, 246, 51, 76, 173, 99, 16}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 206, 235, 134, 112, 241, 61, 108}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 251, 111, 88, 238, 52, 3}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 173, 116, 131, 27}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 83, 106, 44, 177, 56, 132, 191, 107}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 12, 222, 127, 178}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 115, 71}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 178, 219, 175, 184, 193, 196, 209}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 70, 18, 204}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 3, 43, 34, 180}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 121, 142, 77, 153, 19, 75, 160, 46}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 179, 204, 81, 167, 65, 212, 129, 43}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 76, 84, 134, 21, 207, 244, 217}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 171, 3}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 215, 203, 25, 163, 112, 241, 223}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 231, 23, 141, 191, 78, 62, 58}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 14, 174, 229, 219, 171, 254, 114, 44}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 81, 130, 147, 74, 175, 115}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 174, 90, 25, 209}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 198, 224, 148, 212, 211, 91}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 15, 246, 199, 114, 173, 102, 20, 100}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 176, 32}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 106, 244, 54, 176, 165, 112, 8}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 59, 194, 41}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 163, 11, 181}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 40, 197, 60, 37, 255}, 92}, {{237, 249, 9, 70, 247, 97, 64, 203, 207, 104, 232, 152, 123, 168, 210, 57}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 8, 150, 206, 64, 133, 169, 203}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 211, 76, 248, 75, 104, 127, 157, 232}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 126, 61, 247, 155, 80, 20, 236, 25}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 215, 134, 49, 208}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 23, 217, 192, 54, 49, 8}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 155, 192, 102, 76, 110}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 211, 79}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 208, 18, 19, 0, 245}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 255, 104, 140, 144, 208, 177, 93, 196}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 124, 253, 118, 235, 19, 225, 72, 95}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 50, 137, 59, 226}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 72, 117, 88, 78, 76, 196, 219}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 104, 246, 221, 88}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 120, 250, 39, 79, 61, 50, 153, 154}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 93, 46, 25, 123, 76, 222, 192}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 45, 176, 115}, 92}, {{237, 249, 9, 70, 247, 97, 64, 158, 221, 186, 109, 216, 197, 89, 75, 103}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 181, 124, 185, 210, 212}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 90, 116, 249, 142, 131, 177}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 242, 152, 74, 56, 120, 245, 116, 166}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 191, 126, 248, 133, 104}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 148, 136, 238, 248, 245}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 186, 215, 27, 72, 197}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 199, 20}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 107, 166, 249}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 111, 166, 36}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 82, 70}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 167, 107, 215, 198}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 204, 215, 78}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 214, 66}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 115, 116, 29, 253}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 114, 27, 70, 148, 220, 218}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 112, 141, 223, 17, 194, 98, 64}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 255, 100}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 189, 136, 185, 99, 42, 59}, 92}, {{237, 249, 9, 70, 247, 97, 64, 249, 244, 83, 27, 216, 31, 223, 33, 168}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 28, 189, 228, 170, 12, 38}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 105, 0, 175, 28, 32}, 92}, {{237, 249, 9, 70, 247, 97, 64, 153, 122, 107, 45, 65, 141, 97, 247, 123}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 32, 125}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 58, 119}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 78, 40, 106, 66, 52}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 5, 107, 108}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 8, 72, 21, 239, 78, 169, 76, 163}, 92}, {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 58, 21, 29, 161, 184}, 92}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 38, 17, 0, 235, 35, 98, 191, 143}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 19, 113}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 115, 16}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 39, 74, 200, 39}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 209, 21}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 219, 35, 205, 125, 91, 174}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 142, 154, 148, 153, 90, 77}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 242, 84, 59, 206, 14, 226, 33}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 151, 3}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 10, 70, 64, 203}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 137, 234, 104, 169, 38, 121, 149, 122}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 173, 152, 200, 203, 237}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 182, 165, 131, 45, 247, 66, 197, 161}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 41, 126}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 168, 143, 207, 221, 79, 1, 109}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 105, 187, 31, 37, 89, 197, 206}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 195, 27, 156, 67}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 18, 9, 151, 99}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 139, 110}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 120, 19, 30, 234, 76, 255, 248}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 66, 41, 247, 233, 135}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 53, 138, 126, 167, 177}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 79, 213}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 61, 161, 123}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 73, 85, 103, 227}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 170, 32, 86}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 166, 121, 237, 70, 67, 248}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 33, 234, 114, 228, 215, 83, 253, 193}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 112, 209, 249, 41, 80, 180}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 179, 58}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 216, 15, 170, 120, 185, 192, 8, 91}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 244, 53, 31, 161, 19, 172, 71}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 38, 254, 123, 200, 0, 242, 128}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 134, 94, 83, 111, 158, 205, 87}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 169, 47, 146, 217, 208}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 240, 116, 115, 62, 149}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 182, 141, 156, 42, 126, 192, 230, 164}, 230}, {{155, 92, 145, 218, 125, 226, 226, 187, 249, 127, 158, 129, 24, 226, 255, 24}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 192, 226, 86, 173, 25, 7, 96}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 156, 176, 207, 71, 137, 160}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 164, 225, 178, 161, 135, 146, 102, 213}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 237, 81, 79, 156}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 97, 72, 179, 241, 207}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 105, 208, 229, 60, 30, 14, 147, 25}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 227, 70, 244, 97, 4, 29, 168}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 125, 75}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 93, 249, 110, 19, 251}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 93, 44, 5}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 202, 166, 56, 62, 146, 2, 164}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 206, 116}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 156, 202, 82, 103, 157, 120, 162, 24}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 112, 173}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 154, 97, 93, 192}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 40, 220, 97, 127, 213, 174, 157}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 42, 239, 34, 184}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 246, 203, 241, 218, 173, 202, 228, 117}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 84, 225, 38, 28, 52, 135, 77}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 70, 126, 59, 69, 108, 22, 174, 87}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 78, 248, 128, 39, 169, 201, 37, 178}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 131, 49}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 109, 100, 222, 50, 157, 232, 14}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 111, 206, 146}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 72, 69, 180, 202, 221, 236}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 196, 153, 24, 49, 87, 67, 228, 34}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 164, 210, 175, 98, 14, 3}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 47, 37, 53, 66, 129, 16}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 211, 58}, 230}, {{155, 92, 145, 218, 125, 226, 226, 122, 246, 216, 154, 127, 196, 67, 253, 102}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 128, 238, 207, 4, 9}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 112, 25, 202, 140}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 220, 44, 54, 52, 155, 192}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 88, 7, 38, 168, 104, 58, 131, 212}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 248, 51, 164, 89}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 238, 219}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 53, 134, 9, 96, 37, 111, 157}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 123, 10, 79}, 230}, {{155, 92, 145, 218, 125, 226, 226, 0, 196, 60, 202, 67, 26, 100, 243, 139}, 230}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 78}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 177}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 123}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 196}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 55}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 97}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 213}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 234}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 139}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 66}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 29}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 249}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 173}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 19}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 133}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 136}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 175}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 142}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 81}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 118}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 72}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 187}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 62}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 116}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 135}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 166}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 66}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 148}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 179}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 155}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 206}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 206}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 77}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 247}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 177}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 144}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 55}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 87}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 26}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 184}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 212}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 60}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 193}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 26}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 61}, {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 249}, 61}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 103}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 191}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 46}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 205}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 206}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 193}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 50}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 153}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 48}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 101}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 71}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 19}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 238}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 117}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 229}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 39}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 213}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 24}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 79}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 161}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 221}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 105}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 75}, 181}, {{104, 64, 0, 0, 224, 73, 208, 64, 31, 142, 3, 190, 111, 85, 91, 24}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 68, 204}, 181}, {{104, 64, 0, 0, 0, 5, 68, 109, 92, 8, 239, 137, 161, 192, 215, 221}, 181}, {{104, 64, 0, 0, 243, 55, 162, 167, 202, 92, 224, 188, 95, 167, 233, 224}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 145, 241, 40, 254}, 181}, {{104, 64, 0, 199, 223, 53, 117, 190, 182, 39, 217, 197, 140, 35, 26, 90}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 144, 1, 172, 50, 172, 48, 137, 167}, 181}, {{104, 64, 0, 0, 0, 0, 0, 39, 61, 56, 150, 114, 123, 5, 109, 14}, 181}, {{104, 64, 0, 0, 0, 0, 76, 187, 68, 241, 103, 209, 134, 95, 59, 22}, 181}, {{104, 64, 0, 0, 201, 4, 8, 242, 1, 151, 3, 158, 130, 160, 214, 89}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 219, 174, 215, 60}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 60, 89, 71, 221}, 181}, {{104, 64, 206, 5, 198, 84, 91, 207, 97, 203, 80, 162, 87, 245, 193, 230}, 181}, {{104, 64, 0, 0, 0, 0, 73, 72, 65, 57, 104, 207, 143, 88, 117, 201}, 181}, {{104, 64, 0, 0, 0, 173, 6, 35, 93, 67, 59, 83, 122, 214, 73, 186}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 175}, 181}, {{104, 64, 0, 114, 164, 129, 157, 27, 100, 44, 11, 195, 0, 54, 203, 3}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 181}, {{104, 64, 0, 0, 0, 180, 101, 184, 88, 80, 103, 229, 77, 145, 39, 50}, 181}, {{104, 64, 0, 0, 8, 92, 235, 136, 92, 234, 175, 115, 1, 24, 61, 91}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 202, 202}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 49, 162, 19, 114, 213, 138, 102, 119}, 181}, {{104, 64, 0, 0, 0, 0, 0, 171, 164, 165, 174, 3, 230, 244, 16, 186}, 181}, {{104, 64, 0, 216, 123, 50, 138, 47, 4, 118, 7, 221, 143, 48, 68, 183}, 181}, {{104, 64, 0, 204, 200, 236, 92, 6, 148, 126, 22, 246, 193, 83, 53, 190}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 219, 5, 9, 238, 162, 206, 77, 17, 124, 196, 187}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 244, 180}, 181}, {{104, 64, 0, 92, 30, 100, 21, 209, 10, 159, 184, 144, 120, 140, 90, 130}, 181}, {{104, 64, 0, 0, 141, 25, 52, 189, 255, 0, 40, 12, 140, 80, 50, 167}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 181}, {{104, 64, 0, 0, 0, 0, 0, 253, 117, 49, 162, 17, 165, 33, 86, 174}, 181}, {{104, 64, 0, 0, 0, 0, 247, 203, 151, 231, 161, 16, 117, 225, 122, 8}, 181}, {{104, 64, 0, 0, 0, 39, 245, 139, 38, 27, 3, 198, 20, 50, 65, 225}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 242, 105, 168, 72}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 85, 70, 82, 214}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 22, 63}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 10, 129, 6, 254, 72, 104}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 56, 178, 218, 218}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 138, 105, 6}, 181}, {{104, 64, 0, 0, 0, 0, 78, 233, 219, 158, 228, 78, 209, 171, 254, 150}, 181}, {{104, 64, 111, 199, 193, 45, 5, 159, 44, 169, 182, 44, 15, 211, 250, 24}, 181}, {{104, 64, 0, 23, 148, 193, 27, 16, 100, 71, 95, 38, 223, 153, 203, 213}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 245, 177, 215, 57, 153, 108}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 113, 214, 216, 165}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 154, 163, 60, 149, 139, 73, 174, 168, 30, 183, 47, 106, 97}, 181}, {{104, 64, 0, 0, 0, 197, 158, 33, 83, 11, 2, 124, 250, 168, 201, 237}, 181}, {{104, 64, 0, 98, 104, 45, 81, 196, 233, 134, 179, 197, 66, 249, 167, 9}, 181}, {{104, 64, 0, 0, 1, 177, 105, 66, 230, 91, 166, 27, 168, 150, 150, 109}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 75, 185, 213}, 181}, {{104, 64, 0, 0, 0, 172, 167, 163, 157, 206, 233, 151, 245, 82, 171, 56}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 190, 190, 245, 80, 177, 16, 187, 125}, 181}, {{104, 64, 0, 0, 182, 21, 112, 59, 41, 151, 71, 170, 207, 174, 9, 21}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 242, 30}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 198, 181, 23}, 181}, {{104, 64, 0, 0, 0, 0, 0, 169, 13, 228, 136, 90, 193, 158, 58, 138}, 181}, {{104, 64, 0, 211, 216, 60, 54, 117, 77, 124, 82, 36, 94, 207, 151, 244}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 61}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 98, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 70, 94, 171, 219}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 235, 14}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 89, 175}, 181}, {{104, 64, 0, 0, 0, 121, 161, 154, 101, 50, 241, 250, 191, 239, 126, 253}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 22, 64, 1, 103, 196, 230, 21}, 181}, {{104, 64, 0, 253, 161, 229, 79, 232, 146, 39, 24, 203, 249, 189, 239, 32}, 181}, {{104, 64, 68, 174, 112, 245, 0, 16, 211, 77, 208, 34, 235, 188, 155, 182}, 181}, {{104, 64, 0, 0, 0, 0, 0, 155, 121, 158, 118, 83, 115, 4, 129, 73}, 181}, {{104, 64, 101, 112, 33, 36, 141, 128, 126, 77, 113, 154, 216, 76, 241, 19}, 181}, {{104, 64, 0, 180, 251, 87, 117, 124, 66, 222, 148, 163, 234, 217, 203, 185}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 92, 54, 88}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 130}, 181}, {{104, 64, 0, 0, 0, 0, 163, 165, 50, 112, 76, 28, 208, 232, 33, 24}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 82, 103}, 181}, {{104, 64, 0, 0, 133, 18, 0, 235, 217, 92, 248, 8, 107, 252, 0, 153}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 230}, 181}, {{104, 64, 0, 0, 0, 0, 0, 190, 78, 23, 205, 94, 206, 103, 244, 251}, 181}, {{104, 64, 161, 2, 168, 151, 17, 158, 72, 103, 46, 57, 30, 200, 118, 123}, 181}, {{104, 64, 0, 0, 217, 10, 18, 243, 172, 201, 207, 26, 12, 194, 143, 240}, 181}, {{104, 64, 0, 0, 0, 0, 202, 147, 18, 145, 240, 95, 186, 35, 4, 212}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 141, 250, 248, 254, 3, 203, 118}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 149, 50, 36, 115, 27, 86, 241, 241}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 234, 111, 187, 86, 141, 198, 213, 94}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 221, 67}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 67, 24}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 153, 226, 162}, 181}, {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 202, 106, 38, 37, 169, 73}, 181}, {{104, 64, 0, 0, 208, 245, 94, 247, 244, 145, 26, 254, 133, 201, 222, 132}, 181}, {{104, 64, 0, 0, 116, 200, 104, 203, 236, 11, 141, 88, 85, 127, 129, 17}, 181}, {{104, 64, 0, 0, 0, 0, 155, 163, 103, 75, 250, 78, 99, 57, 5, 41}, 181}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 184, 194, 86}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 84, 84}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 29, 0, 10, 101}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 204, 198, 2, 23, 151}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 148, 246}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 204, 39, 125}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 227}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 67, 123}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 110}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 237, 188, 244}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 95, 41, 170}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 153, 135, 173, 85}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 251, 175}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 217}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 126, 255, 242, 136}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 111, 65, 162}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 166, 48, 67}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 134, 91, 137, 222}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 242}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 114, 35, 238, 81, 187}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 173, 97, 20, 230, 112, 81}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 212, 84, 247}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 239, 148, 142, 83, 212}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 116, 6, 49}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 119, 145, 210, 108}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 29, 130, 10, 235}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 53, 154, 145, 227}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 56, 55, 33}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 62, 252}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 175, 142, 209, 137, 62}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 159, 207, 145, 225}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 118, 238, 172, 195, 183}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 170, 162}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 141, 104, 39}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 248}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 204, 69, 240, 125, 7}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 173, 165}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 79, 35, 38}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 53, 10, 199}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 224, 127}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 185, 154, 130, 93}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 189, 65, 176}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 73}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 247}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 40, 187, 53}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 152, 178, 21}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 253}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 246, 239, 71}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 158, 22}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 55, 182, 46, 58}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 100, 167, 150, 6}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 31, 185, 225, 53}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 250}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 63, 86, 76}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 176, 65}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 218, 138}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 229}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 118, 7}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 177, 131, 139, 123, 101}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 152}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 63}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 210, 90, 52, 203}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 69}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 173, 203, 83, 201}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 113, 82, 90, 170}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 64}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 77, 95, 209, 41, 61}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 31, 24, 190, 56}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 153}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 154, 68, 100, 180}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 231, 153}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 6, 61, 58, 223}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 144, 195, 224, 18}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 188, 39, 203, 55, 191}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 234, 185}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 173, 198}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 161, 68, 65, 198, 121}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 242}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 172, 124, 167}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 6, 69, 165, 173}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 110}, {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 146, 201, 246, 118}, 110}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 124}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 231, 80, 84, 170}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 76, 25, 181}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 80, 29, 76, 147}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 57, 0, 84}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 79, 206, 190, 165}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 57, 171, 223}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 82, 203, 72}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 136, 32, 208, 36, 23}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 153, 54}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 4, 97, 180}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 144, 206, 132}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 67, 200, 31, 233}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 99, 24, 21, 82}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 229, 128, 208}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 29}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 130}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 81, 23}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 139}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 4}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 233, 228, 136}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 97, 212, 91}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 103}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 241, 130, 101}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 125, 84}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 86, 48, 4, 106}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 188}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 226, 229, 30}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 79, 121}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 7}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 107, 223, 231}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 127, 131, 101, 155}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 138, 74, 108}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 255}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 16, 18, 30, 249}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 100, 1, 230}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 121}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 11, 111}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 133, 179, 174, 177}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 96}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 233}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 163, 50, 85}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 253, 145, 37}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 137, 72}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 206, 210, 254}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 20, 134, 221, 159}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 37, 192, 228, 126}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 136, 158}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 68, 58}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 138, 228, 24}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 87, 53}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 23, 73, 106}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 27}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 118, 116}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 25, 147, 137, 32}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 182, 53, 34, 144}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 161, 194, 142}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 216}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 134, 170, 142, 83}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 187, 21, 6}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 1, 76, 74, 252}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 130}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 223, 201, 51, 80, 78}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 91}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 255, 202}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 52, 210}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 220, 23}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 215, 95, 84, 255}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 100}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 192, 179, 159}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 198}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 48, 23, 188, 92}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 251}, 103}, {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 128, 226, 215}, 103}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 218}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 64, 162, 120, 240, 225}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 136, 168, 27, 78, 29}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 213, 204, 155, 145, 135}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 188, 81}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 152, 153}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 194, 42, 73, 74}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 204, 224, 181, 33, 32, 59, 215, 151}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 125, 145, 16, 250, 194, 126}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 200, 152, 108, 178}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 76, 196, 217, 173, 104}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 74, 167, 48, 251}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 76, 146, 154, 131}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 93, 234, 196, 198}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 95, 115, 91, 36}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 180, 196, 134, 76, 158, 122}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 207, 156, 216}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 209, 41, 194, 73, 42, 208, 29, 80}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 51, 82, 8, 148}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 254, 179}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 223, 115, 25, 58, 232, 44}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 33, 214}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 218, 93}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 62, 201, 224, 23}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 89, 207, 106, 124, 142, 170, 245}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 101, 22, 165, 43, 21, 48, 132, 145}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 109, 157, 216}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 237, 229, 9}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 16, 122, 153}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 115, 117, 21, 73}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 200, 89, 27, 156, 103, 100, 12, 178}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 252, 247, 239, 215, 91, 171, 27}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 236, 131, 76}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 52, 130, 124, 100, 26, 44, 69, 226}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 76, 201, 123, 177, 63}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 211, 124, 53}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 22, 72, 104, 165}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 84, 26, 20, 151, 35, 113, 72, 83}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 177, 39}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 11, 127}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 141, 243, 66, 116, 27, 29}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 230, 145, 136, 147, 133, 57, 5, 224}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 207, 21, 31, 233, 181, 239, 59, 68}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 33, 118}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 222, 18}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 68, 138}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 12, 191, 129}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 93, 154, 254, 36, 231}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 138, 203, 50}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 43, 20, 231, 213}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 121, 143, 109, 120, 59, 192, 70}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 54, 98, 199, 246, 5, 253, 56, 193}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 216, 226, 233, 94, 254, 126}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 146, 93, 122, 89, 3, 116}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 104, 244, 37, 180, 252}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 242, 131, 203, 138, 112}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 23, 58, 120, 129, 61, 33, 31}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 48, 46, 106, 221, 109}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 206, 250}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 58, 25, 168, 236, 14, 163, 89}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 47, 123, 239, 55, 183, 129, 158}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 242, 22, 116, 104, 26}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 65, 2, 176, 9, 34}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 234, 6, 93, 11, 62, 92, 150}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 32, 169, 87, 46}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 239, 186, 55, 191, 84, 21}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 223, 224, 226, 179, 187, 191}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 242, 15, 93, 217, 244, 232, 211}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 79, 20, 35}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 239, 115, 185}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 213, 229, 111, 31, 166, 5, 118}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 95, 137}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 6, 242, 105, 93}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 252, 239, 156, 199, 9}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 101, 124}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 101, 240, 222}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 4, 34, 216, 13}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 49, 142, 218}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 123, 194, 219, 69, 48}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 154, 63, 82, 231, 52, 186, 135}, 146}, {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 7, 207, 20, 190}, 146}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 39, 188, 32, 199, 128, 156}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 151, 192, 247, 242, 97}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 129, 202}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 131, 167, 186, 70, 181}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 24}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 180, 80}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 235, 31, 1}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 165, 205, 218, 81, 26, 123}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 10, 188, 7}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 79, 63, 123}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 51, 6, 113, 71, 185, 25}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 97, 19, 122, 220}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 160}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 95, 248, 39, 249, 225}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 196, 245}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 151, 168}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 62, 176}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 138, 200, 170, 227, 181, 60}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 31, 118, 199, 182}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 228}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 54}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 6, 158, 31, 36, 114, 49}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 134, 97, 102, 45, 85, 149}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 222, 193, 65, 28}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 17, 101, 192, 145, 115, 210}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 166, 19, 224, 227, 185, 168}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 88, 149, 180, 20, 41}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 44, 250, 15}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 39, 46, 5, 82, 36, 156}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 1, 229}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 64, 226, 128, 11, 178, 175}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 184, 113}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 195, 144, 28, 66, 173, 241}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 48, 173, 140, 25}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 250, 90, 119, 185, 30, 26, 199}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 125, 140}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 61, 171, 123, 76, 164}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 141, 203, 67, 117, 75, 173, 27}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 59, 25, 253}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 42, 230, 32}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 171, 232, 2, 197}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 152}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 8, 183, 28, 88}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 123, 84, 122, 60}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 106, 180, 200, 219, 86}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 114, 63, 75, 21, 132, 226}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 242, 38, 82}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 114, 32, 117, 58, 148, 19}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 169, 20, 173}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 155, 17, 151, 147, 68, 151, 242}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 166}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 144, 53}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 24, 250, 23, 114, 188, 94, 130}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 7, 232, 210, 255, 218, 85}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 29}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 99, 19}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 235, 185, 247, 156}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 251, 150, 147, 22}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 111, 27}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 164, 233, 21, 190, 251, 34}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 204, 166, 204, 243, 79}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 135, 169, 158, 92}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 206, 26}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 105}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 230}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 251, 86, 93, 98, 137, 135}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 163, 179, 223}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 187, 23, 114, 165}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 219}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 49}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 245, 87}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 55, 130, 197, 81, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 142, 150, 209, 249, 107, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 174, 134, 152, 37, 241}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 239}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 181, 116, 18}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 202, 153}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 38, 237, 202, 11, 180, 115}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 107, 173}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 210, 231, 200}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 32, 17}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 94, 87, 63, 3, 216}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 97, 7, 212}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 39, 20, 57}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 113, 190}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 16, 192, 219, 160, 58}, 90}, {{11, 98, 146, 110, 95, 96, 80, 142, 224, 62, 138, 243, 156, 201, 138, 79}, 90}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 159}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 91}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 136}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 198, 231}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 64, 153}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 50}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 251}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 168}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 19}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 43}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 26, 11}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 127, 84}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 68, 78}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 129}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 183}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 44, 214}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 134}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 215}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 174, 243}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 113}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 31}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 103}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 133, 181}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 153}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 13}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 159}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 204}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 113}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 231, 162}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 246, 234}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 73}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 67}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 135}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 124}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 7}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 215}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 6, 254}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 122}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 52}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 121}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 75}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 63, 10}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 164}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 90, 157}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 57}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 210, 153}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 20}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 242, 148}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 166}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 45}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 111}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 226}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 199}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 55}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 35}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 56}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 29}, 197}, {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 109, 166}, 197}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 255, 105}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 121, 213}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 185, 95}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 194}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 35, 194}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 95, 195}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 246, 45}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 227}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 81, 117}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 58}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 68}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 231, 72}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 161, 63}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 39}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 127}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 37, 198}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 93}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 67, 50}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 252}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 230, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 230, 124}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 62, 213}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 249}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 155}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 38}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 135, 167}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 155}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 108, 228}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 204}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 48}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 202}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 242}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 153}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 7}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 118, 143}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 118, 244}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 186}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 131, 232}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 113, 173}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 167, 76}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 29, 187}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 33, 133}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 89}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 221, 42}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 109, 110}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 85, 30}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 87}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 126, 194}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 70}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 148}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 48}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 31, 135}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 131}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 79, 177, 170}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 74}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 56, 229, 251}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 28, 146}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 91}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 62, 254}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 219, 64}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 246, 146}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 98}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 77, 146}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 40}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 50}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 25, 199}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 35}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 88}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 246, 111}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 15, 225, 230}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 158}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 196, 102}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 11, 142, 83}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 226, 124, 18}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 158, 28}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 67, 163, 84, 224}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 25, 242, 222, 21}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 27}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 152, 136, 119, 162, 51}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 181, 61}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 8, 95}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 59}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 143, 84, 244, 212}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 50, 238, 95, 246}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 111, 228}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 205, 84}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 50, 196, 80, 122}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 197, 125, 34}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 178, 178}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 21, 244, 174, 181}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 30, 116}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 109}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 158, 65, 25, 4}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 224}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 179, 254}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 246, 220, 36, 48, 254}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 149, 177, 63, 123}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 241, 178, 247}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 253, 193, 248, 82}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 21, 162}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 94, 226, 129, 115}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 6, 58, 231}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 36, 125, 9, 15, 74}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 146, 166, 236}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 221, 159, 164}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 208, 245, 219, 9}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 195, 35}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 70}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 160, 38, 231, 166}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 101, 22, 51, 158}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 16, 42, 154, 159, 170}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 22, 151}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 31, 222, 218, 111}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 218, 214, 157, 223, 33}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 105, 135}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 204, 251, 237, 186, 17}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 177, 182, 167, 243}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 226}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 122, 193, 225}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 207, 119, 102, 3, 248}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 63}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 134, 46}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 129, 196, 103}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 229, 201, 51}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 207, 114, 169, 8}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 200}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 188, 239, 86}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 229}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 178, 105}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 93, 164}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 116, 240, 201}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 255, 40}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 178, 58, 219}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 212, 120, 130, 253}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 189}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 204}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 155, 194, 145}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 254, 164}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 172, 255, 253, 12}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 243}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 137, 67, 57, 40, 50}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 121, 84, 25}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 160, 168}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 108, 207, 90}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 220, 51, 123, 135, 237}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 163, 252, 239}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 5, 178, 238}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 106, 247, 113, 71, 77}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 7, 91, 151, 192}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 90, 46, 172, 37}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 227, 186, 208, 255}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 118}, {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 152}, 118}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 26, 184, 12, 216, 134, 71, 176}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 40, 95, 41, 194}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 202, 185, 218, 117, 46, 207}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 24, 69, 63, 186, 182}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 54, 247, 8, 244, 42, 148}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 136, 183, 101, 194, 249}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 88, 159, 106}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 39}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 108, 111, 78, 128, 53, 51, 218}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 79}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 48, 243, 191, 10, 118, 251, 164}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 199, 57, 145, 255, 34, 236}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 20, 108, 251}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 99, 200, 230, 3}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 74, 158, 50, 202, 15, 201}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 139, 16, 249, 121, 83, 0, 113}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 142, 165, 56, 60, 149, 203, 171}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 43, 170, 26, 90, 172, 251}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 142, 253, 27}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 109, 76, 215, 146}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 89, 76, 172, 212, 141, 80, 160}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 166, 7, 135, 75, 107, 52}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 127, 225, 106}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 52, 16, 56, 242, 130, 28, 41}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 222, 221, 178, 7, 0, 139, 79}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 26, 185, 151}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 241, 107, 21, 54, 67, 118, 234}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 144, 33, 51, 101}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 180, 199, 97, 146, 241}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 83, 150, 233}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 227, 16, 31, 254, 1, 234}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 65, 206, 1, 252, 207, 190}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 231, 5}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 13, 207}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 122, 193, 88, 219}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 42, 205, 193}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 70, 233, 220, 229, 39, 51}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 28, 42}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 152, 24, 108, 220, 155, 193, 134, 103}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 196, 123}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 13, 240, 60, 127, 71, 206, 193}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 187, 225, 95, 66, 27}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 243, 116, 219}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 220, 176, 25}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 138, 207, 185}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 110, 133, 207, 47, 225, 171}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 72, 235, 212, 47, 229}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 25, 40, 202, 4, 60}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 56, 209, 93, 157, 128, 255, 33, 68}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 48, 173, 244, 213, 182, 1}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 141, 183}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 100, 233, 147, 70, 129, 153, 218, 197}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 83}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 136, 200, 68, 188}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 9, 134, 221, 94, 211}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 195, 61, 58, 59}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 226, 156, 254, 108, 232}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 208, 84}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 244, 170}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 26, 35, 80, 99, 244, 245, 86}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 14, 220, 230, 107, 165, 59}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 244, 217, 252, 61}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 175, 124, 82, 143}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 213, 10, 92, 1}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 235, 27, 128, 39, 75}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 196, 83, 59, 229, 193}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 163}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 34, 153, 194, 14, 10, 115, 160}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 97, 132}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 95, 141, 38, 52, 85}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 205, 104, 93, 140, 121}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 198}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 86, 62, 34, 250, 163, 203, 50}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 55}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 180, 45, 210}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 169, 78}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 115, 97, 169, 13, 21}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 253, 135, 21, 13}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 150}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 100}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 30, 122, 189}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 233, 58, 241, 38, 87, 112}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 207, 85, 102}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 82, 92, 32, 158}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 207, 8, 164}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 181, 140, 226}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 141, 31, 10, 102, 148, 32}, 95}, {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 80, 152, 172, 248, 206, 231}, 95}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 82, 166, 177}, 152}, {{253, 117, 135, 98, 128, 0, 0, 209, 53, 231, 16, 126, 110, 249, 179, 190}, 152}, {{253, 117, 135, 98, 128, 1, 123, 168, 114, 207, 183, 76, 96, 255, 130, 118}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 130}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 50, 234, 0, 182, 213}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 212, 219, 83, 16, 206, 45}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 48, 49, 105, 7, 173, 212}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 104}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 156, 110, 43, 184, 248, 225, 5, 73}, 152}, {{253, 117, 135, 98, 128, 151, 166, 193, 16, 92, 174, 32, 28, 237, 49, 235}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 200, 144, 4}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 171, 163, 26, 118}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 201, 41, 218, 152, 27}, 152}, {{253, 117, 135, 98, 128, 0, 238, 106, 150, 82, 35, 73, 73, 91, 67, 198}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 109, 94, 220, 234}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 1, 237, 39, 138, 240, 97, 34}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 102, 32, 49, 75}, 152}, {{253, 117, 135, 98, 128, 0, 0, 151, 34, 102, 20, 2, 18, 149, 227, 148}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 110, 179, 119, 218, 177, 159, 52}, 152}, {{253, 117, 135, 98, 128, 0, 202, 198, 246, 118, 175, 137, 77, 137, 88, 63}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 245, 219, 209, 198, 48, 15, 25, 123, 147}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 144, 229, 128, 62, 33, 124, 240, 235, 105, 198}, 152}, {{253, 117, 135, 98, 128, 0, 0, 172, 144, 57, 123, 7, 170, 174, 121, 241}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 48, 181, 93, 192, 59, 172, 34, 97}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 52}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 42, 127, 61, 46, 161, 119}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 181, 144, 7, 201}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 190, 36, 206, 116, 92, 210}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 229, 117, 180, 148, 65, 105, 25}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 78, 250, 106, 79}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 39, 22, 222, 251, 72, 239, 226}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 132, 80, 227, 45}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 157, 32, 184, 254, 73}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 126, 193, 113, 213, 169}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 108}, 152}, {{253, 117, 135, 98, 128, 0, 19, 172, 48, 17, 176, 202, 44, 76, 199, 157}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 52, 191, 218}, 152}, {{253, 117, 135, 98, 128, 0, 201, 180, 101, 168, 155, 49, 38, 30, 88, 27}, 152}, {{253, 117, 135, 98, 128, 69, 130, 81, 248, 211, 22, 148, 113, 49, 143, 207}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 178, 91, 48}, 152}, {{253, 117, 135, 98, 128, 69, 75, 185, 88, 221, 209, 39, 196, 40, 224, 11}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 128, 130, 142, 140, 12, 236, 66, 147}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 82, 196, 218, 172, 60}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 156, 128, 234, 73, 168, 106, 8, 215, 95, 135, 208}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 137, 158, 30}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 232, 232, 239, 18, 32, 167, 172}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 162, 186, 113, 64, 164, 106}, 152}, {{253, 117, 135, 98, 128, 205, 48, 4, 27, 90, 183, 116, 238, 193, 98, 220}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 15, 26, 254, 211}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 137, 227, 143, 58, 2, 136}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 138}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 20, 99, 163, 234}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 148, 212, 251, 108, 15, 200}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 211, 102, 112, 204, 91, 206, 211}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 48, 79, 185, 166, 26}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 133, 212, 175, 29}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 69, 48, 82, 112, 38}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 160}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 240}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 178, 148, 7}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 108, 83, 62, 183, 63, 108, 148, 139}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 221, 1, 182, 95, 89, 149, 185, 65}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 20, 115, 67, 245}, 152}, {{253, 117, 135, 98, 128, 0, 208, 81, 213, 216, 86, 2, 59, 136, 52, 138}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 53, 48, 46, 227}, 152}, {{253, 117, 135, 98, 128, 0, 0, 210, 117, 30, 177, 87, 165, 30, 44, 40}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 248, 80, 217, 49, 37, 192}, 152}, {{253, 117, 135, 98, 128, 107, 53, 76, 121, 68, 203, 0, 233, 40, 115, 114}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 109, 20, 114}, 152}, {{253, 117, 135, 98, 128, 0, 0, 63, 43, 75, 201, 1, 20, 167, 157, 120}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 170, 225, 172, 96, 155}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 215, 11, 250, 91, 87, 103, 140}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 130, 97, 170, 150}, 152}, {{253, 117, 135, 98, 128, 39, 112, 78, 144, 51, 69, 53, 197, 76, 111, 208}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 168, 192, 191, 87, 36}, 152}, {{253, 117, 135, 98, 128, 0, 22, 144, 253, 232, 138, 123, 70, 69, 145, 72}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 15, 205, 65, 101, 182}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 152}, {{253, 117, 135, 98, 128, 58, 208, 25, 223, 43, 108, 226, 71, 147, 127, 44}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 203, 174, 177, 11}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 142, 202, 30, 236, 60}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 23, 73, 205}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 158, 128, 168}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 190}, 152}, {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 152}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 117, 64, 104, 125, 123, 57}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 214, 213, 59, 30}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 239}, {{111, 115, 188, 184, 130, 0, 0, 222, 93, 30, 171, 224, 244, 166, 102, 135}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 234, 94, 251, 127, 247, 16, 100, 76}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 12, 173, 54, 190, 42}, 239}, {{111, 115, 188, 184, 130, 0, 0, 86, 84, 8, 94, 230, 198, 190, 120, 172}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 102, 176, 57, 141, 58, 238}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 76, 255, 230, 129, 96, 133, 11}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 247, 41, 201, 61}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 204, 177, 54, 9, 233, 38}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 115, 212, 235, 193, 35, 73, 235, 123}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 204}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 226, 16, 124, 38, 184, 32}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 166, 97, 137, 44, 70, 36, 100, 249, 159}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 175}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 143, 208, 195, 167, 6, 174, 157, 22}, 239}, {{111, 115, 188, 184, 130, 0, 0, 147, 122, 178, 184, 201, 229, 109, 14, 110}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 5, 132, 139}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 95, 193, 55, 254, 233, 225, 78, 10}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 17, 197, 40}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 250, 167, 198, 119, 162}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 161, 35, 183, 145, 98, 11, 154}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 233, 52, 163, 85, 168, 140}, 239}, {{111, 115, 188, 184, 130, 0, 0, 48, 171, 124, 197, 23, 73, 171, 18, 189}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 86, 111, 11, 231, 111, 210}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 142, 93, 195, 59, 201, 176}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 103}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 169, 241, 39}, 239}, {{111, 115, 188, 184, 130, 0, 61, 237, 4, 54, 120, 77, 226, 86, 39, 128}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 79, 229, 152, 44, 75, 160, 20}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 152, 1, 9, 154}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 44, 27, 177, 63, 218, 161}, 239}, {{111, 115, 188, 184, 130, 0, 0, 138, 186, 227, 184, 128, 241, 129, 104, 120}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 162, 156, 14, 3, 214, 183}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 152, 86, 168}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 252, 244, 152, 212, 184, 222}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 237, 73, 12, 1, 219, 119}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 114, 186, 184, 88}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 134, 11, 97, 106}, 239}, {{111, 115, 188, 184, 130, 0, 0, 210, 203, 215, 26, 212, 239, 143, 103, 158}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 87, 62, 133, 101}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 45}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 118, 12, 20}, 239}, {{111, 115, 188, 184, 130, 0, 0, 184, 13, 207, 41, 154, 106, 39, 104, 108}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 249}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 2, 166, 66, 51, 235, 76, 118, 43}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 226, 241, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 12, 23, 101}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 197, 238, 143, 232, 87}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 62, 85, 75, 153}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 36, 240, 55, 46, 156, 6, 246}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 236, 160, 75}, 239}, {{111, 115, 188, 184, 130, 0, 0, 69, 206, 34, 213, 49, 56, 95, 28, 190}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 10, 32, 235, 113, 239}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 239}, {{111, 115, 188, 184, 130, 0, 0, 133, 102, 168, 199, 89, 34, 31, 247, 52}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 128, 63, 254, 27, 203, 51, 242}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 172, 105, 80, 56}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 148}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 196}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 17, 25, 5, 6, 48}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 25}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 205, 0, 210, 116, 147, 49, 248}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 12, 135, 180, 100}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 99, 110, 147, 66, 181, 253, 72, 77}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 42}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 34, 217, 38, 58}, 239}, {{111, 115, 188, 184, 130, 0, 208, 110, 186, 89, 45, 135, 192, 209, 118, 195}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 163, 238, 108, 125, 151, 48}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 229, 215, 73, 206, 134, 10}, 239}, {{111, 115, 188, 184, 130, 0, 0, 34, 44, 46, 162, 218, 112, 39, 96, 196}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 224, 155, 14}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 73, 86, 5, 103, 125}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 48, 70, 39, 85, 105}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 24, 38, 62, 4, 113, 162}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 239}, {{111, 115, 188, 184, 130, 0, 0, 0, 150, 107, 213, 106, 166, 139, 224, 139}, 239}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 107, 152, 222, 117, 83, 224}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 2, 219, 254, 49, 116, 134}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 248, 81, 212, 94}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 60, 36, 246, 249}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 2, 137}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 58, 215, 162, 48, 128, 200, 134}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 85, 28}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 48}, {{202, 24, 89, 9, 149, 45, 64, 33, 194, 120, 177, 252, 111, 250, 26, 190}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 93, 63, 104, 227, 121, 100, 104}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 2, 158, 114, 41, 193, 252, 98}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 42, 71, 184, 85, 114}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 104, 193, 192, 45, 210, 223, 38}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 225, 105}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 230, 109, 255, 44, 223, 68, 244, 170}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 49, 218, 227}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 46, 244, 253, 222, 164, 110, 183, 20}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 131, 128, 202, 122, 227, 45}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 118, 91}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 203, 196, 149, 159, 23, 243}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 99, 174, 82, 248, 16, 215}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 109, 82, 246, 214, 226, 15, 25}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 85, 162, 66, 217}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 156, 237, 8, 215, 204}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 220, 223, 67, 239, 37, 217}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 25, 104, 34, 111}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 171, 94}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 68, 21, 248}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 245, 160, 80, 84}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 33, 38}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 190, 197, 137}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 174, 119}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 48}, {{202, 24, 89, 9, 149, 45, 64, 103, 1, 148, 146, 108, 164, 130, 127, 17}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 225, 39, 98}, 48}, {{202, 24, 89, 9, 149, 45, 64, 164, 72, 24, 87, 143, 22, 225, 13, 125}, 48}, {{202, 24, 89, 9, 149, 45, 64, 59, 213, 49, 88, 140, 2, 78, 212, 135}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 102, 88, 46}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 1, 24, 131, 121, 191, 22, 126, 54}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 48, 87}, 48}, {{202, 24, 89, 9, 149, 45, 64, 40, 229, 139, 184, 254, 182, 21, 92, 207}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 173, 247, 222, 143, 182, 67, 84, 222, 119}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 115, 232, 213, 133, 165, 60, 234}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 162, 67, 59}, 48}, {{202, 24, 89, 9, 149, 45, 64, 160, 191, 154, 93, 51, 29, 12, 58, 241}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 10, 254, 170, 229, 162, 54, 4, 14}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 165, 246, 14, 94}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 216, 122, 34, 161}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 155, 51, 170, 55, 30, 73, 227, 58}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 176, 181, 57, 169, 241, 10, 184}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 153, 171, 132, 133, 151, 33, 89}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 3, 38, 2, 251, 235, 67, 92, 99}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 75, 41, 15, 72, 104, 176}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 155, 130, 41, 48, 66, 70}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 120, 253, 24, 253}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 145, 26, 40, 76, 10}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 175, 115, 187, 102, 238}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 92, 205, 187, 189, 156, 142}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 23, 212, 47, 95}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 75, 2}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 60, 145, 214}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 255, 2}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 48, 77, 139, 100, 193, 5}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 117, 247, 142, 56, 113}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 102, 207, 33}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 202, 247, 172, 158, 218, 4}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 115, 38, 10, 97, 189, 35}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 143, 94, 14, 48, 114}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 84, 98, 169, 224, 31, 7, 169, 216}, 48}, {{202, 24, 89, 9, 149, 45, 64, 69, 237, 92, 66, 107, 34, 151, 171, 228}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 90, 169, 137, 252, 166, 32, 179, 250}, 48}, {{202, 24, 89, 9, 149, 45, 64, 174, 155, 212, 150, 221, 155, 182, 124, 41}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 210, 47, 57, 145, 205, 247, 107, 142}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 43, 20, 16, 222, 147, 145}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 119, 125, 120, 231, 196, 165}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 109, 50, 141, 173, 233, 172}, 48}, {{202, 24, 89, 9, 149, 45, 64, 31, 71, 84, 229, 199, 93, 83, 148, 65}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 137, 45, 155, 99, 221}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 103, 71, 0, 218, 169, 164}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 101, 50, 216, 144, 72, 108, 119, 54}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 15, 99, 133, 173, 248, 34}, 48}, {{202, 24, 89, 9, 149, 45, 64, 164, 232, 148, 25, 109, 211, 60, 171, 217}, 48}, {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 137, 12, 130}, 48}, {{202, 24, 89, 9, 149, 45, 64, 191, 54, 230, 239, 1, 90, 40, 128, 199}, 48}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 182, 181, 90, 176, 145, 117}, 61}, {{0, 0, 0, 0, 0, 0, 0, 166, 133, 212, 4, 181, 170, 169, 120, 53}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 106, 126}, 61}, {{0, 0, 89, 235, 254, 0, 4, 110, 97, 168, 51, 166, 54, 210, 11, 60}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 19, 131}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 28, 138, 248, 197, 158}, 61}, {{0, 0, 6, 173, 6, 167, 179, 13, 181, 207, 224, 128, 36, 117, 21, 218}, 61}, {{0, 0, 0, 0, 0, 178, 113, 92, 82, 76, 227, 60, 40, 206, 90, 52}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 9, 240, 165}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 61}, {{0, 0, 0, 0, 8, 61, 130, 211, 122, 64, 123, 78, 244, 238, 241, 172}, 61}, {{0, 0, 0, 187, 83, 173, 113, 104, 85, 25, 18, 87, 28, 144, 217, 87}, 61}, {{0, 0, 0, 0, 0, 0, 104, 196, 231, 158, 144, 139, 186, 184, 209, 52}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 164}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 117, 229, 66, 174}, 61}, {{0, 0, 0, 0, 24, 131, 44, 226, 10, 187, 36, 198, 254, 58, 203, 214}, 61}, {{0, 0, 0, 0, 0, 0, 179, 113, 194, 134, 136, 38, 43, 9, 171, 119}, 61}, {{0, 0, 0, 0, 0, 160, 106, 255, 7, 81, 123, 234, 147, 86, 74, 32}, 61}, {{0, 0, 0, 0, 148, 164, 143, 90, 210, 178, 92, 150, 140, 1, 219, 238}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 61}, {{0, 0, 0, 0, 233, 92, 97, 94, 76, 132, 35, 15, 231, 13, 81, 137}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 232, 49, 102, 48}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 97}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 10, 240, 95, 151, 63, 72, 62, 67}, 61}, {{0, 0, 0, 0, 0, 47, 1, 25, 7, 146, 52, 146, 117, 196, 111, 238}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 228, 245, 197, 174, 233, 176}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 21, 249, 228}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 7, 168, 219, 239}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 131, 181, 242, 17, 189, 182, 67, 201}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 12}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 107, 192, 170, 99, 29}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 147, 139, 124, 50, 235}, 61}, {{0, 0, 237, 209, 185, 171, 36, 247, 117, 250, 58, 129, 77, 7, 188, 254}, 61}, {{0, 0, 0, 0, 0, 74, 198, 137, 179, 49, 27, 105, 120, 220, 18, 66}, 61}, {{0, 0, 157, 189, 237, 162, 87, 216, 11, 92, 48, 182, 79, 101, 78, 49}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 230, 120}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 141}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 185, 28, 213}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 13, 178, 4, 45, 29}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 137, 184}, 61}, {{0, 0, 0, 0, 0, 0, 222, 20, 51, 92, 245, 149, 75, 4, 254, 104}, 61}, {{0, 0, 0, 0, 141, 70, 110, 173, 214, 23, 17, 92, 131, 254, 246, 136}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 206, 191, 147, 210}, 61}, {{0, 0, 0, 0, 0, 147, 67, 72, 118, 58, 145, 69, 207, 103, 179, 218}, 61}, {{0, 0, 0, 0, 235, 215, 53, 96, 148, 217, 78, 66, 41, 150, 60, 76}, 61}, {{0, 0, 0, 0, 113, 30, 52, 243, 247, 142, 189, 125, 31, 194, 41, 150}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 78, 253, 138, 127, 130, 62}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 43, 184, 82, 6, 252, 65}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 246, 230, 214, 30, 205, 17, 91, 219}, 61}, {{0, 0, 0, 0, 0, 0, 0, 34, 132, 82, 218, 95, 77, 239, 3, 209}, 61}, {{0, 201, 138, 114, 50, 0, 8, 219, 6, 34, 74, 11, 87, 114, 89, 232}, 61}, {{0, 0, 230, 195, 78, 142, 143, 86, 192, 34, 168, 253, 37, 29, 53, 213}, 61}, {{0, 0, 0, 139, 73, 229, 191, 127, 217, 113, 230, 237, 156, 8, 235, 129}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 61}, {{0, 0, 0, 0, 33, 97, 174, 235, 50, 76, 12, 93, 72, 79, 216, 120}, 61}, {{0, 23, 231, 43, 50, 86, 171, 71, 156, 107, 152, 140, 60, 109, 198, 182}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 6, 155}, 61}, {{0, 0, 0, 0, 103, 13, 253, 250, 53, 118, 230, 192, 234, 110, 157, 48}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 107, 255, 178, 232, 247, 225, 119, 77, 76, 192, 77, 162}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 116, 207, 169, 205, 183, 60, 17, 250}, 61}, {{0, 0, 0, 0, 0, 0, 11, 246, 224, 240, 130, 26, 249, 48, 111, 82}, 61}, {{0, 0, 0, 0, 0, 0, 0, 30, 57, 187, 22, 215, 149, 197, 109, 80}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 234, 200}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 240, 169, 115, 53, 155}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 61}, {{0, 0, 0, 0, 0, 62, 182, 81, 239, 58, 184, 68, 223, 126, 68, 15}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 240, 73, 255, 46, 44}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 7, 169}, 61}, {{0, 0, 0, 0, 97, 161, 198, 232, 78, 239, 34, 143, 232, 151, 47, 236}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 88, 228, 90, 240}, 61}, {{0, 0, 0, 227, 28, 227, 219, 96, 150, 225, 52, 38, 194, 134, 231, 87}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 128, 42, 243, 179, 119, 40, 116, 124, 121}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 251, 123, 153, 183}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 24, 132, 178, 185, 187, 13}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 196, 119, 226, 232, 131}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 208, 160, 104, 52, 163, 222}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 9, 144, 24}, 61}, {{0, 0, 189, 2, 168, 56, 236, 115, 156, 206, 17, 126, 94, 125, 86, 218}, 61}, {{0, 0, 0, 0, 232, 216, 25, 46, 122, 147, 255, 72, 144, 56, 46, 240}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 61}, {{0, 0, 0, 145, 126, 64, 15, 153, 195, 56, 60, 8, 106, 141, 169, 135}, 61}, {{0, 0, 0, 0, 0, 0, 0, 153, 163, 4, 237, 72, 140, 188, 30, 8}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 119, 62, 124}, 61}, {{0, 0, 128, 46, 155, 236, 98, 164, 179, 59, 139, 53, 213, 18, 84, 106}, 61}, {{0, 0, 0, 0, 0, 226, 140, 68, 43, 32, 212, 171, 36, 182, 244, 161}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 50, 50, 10}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 61}, {{0, 0, 0, 0, 0, 0, 0, 121, 188, 42, 128, 53, 170, 132, 98, 216}, 61}, {{0, 0, 0, 0, 0, 196, 76, 5, 109, 191, 92, 13, 100, 131, 122, 206}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 169, 198, 154, 34, 187, 18}, 61}, {{0, 0, 0, 0, 0, 0, 0, 60, 48, 242, 238, 1, 49, 84, 78, 47}, 61}, {{0, 0, 0, 0, 0, 0, 152, 191, 42, 94, 223, 112, 52, 53, 97, 42}, 61}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 253, 147, 83, 213, 96, 141, 41}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 50, 196, 234, 143}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 63}, 247}, {{244, 98, 52, 140, 0, 17, 99, 71, 210, 83, 156, 167, 185, 94, 238, 73}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 232, 88, 125, 44}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 233, 12, 234, 224, 236, 224, 196, 45}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 237, 150, 149, 44}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 2, 20}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 44, 71, 172, 205, 97, 47}, 247}, {{244, 98, 52, 140, 0, 0, 65, 216, 2, 77, 160, 5, 107, 187, 26, 245}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 183, 225, 34, 14, 68, 38, 46, 149}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 22, 213, 11, 34, 143, 117, 34}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 233, 70, 212, 196}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 109, 111, 175, 232, 251}, 247}, {{244, 98, 52, 140, 0, 0, 0, 92, 217, 245, 244, 153, 21, 58, 128, 254}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 131, 156, 103, 70}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 176, 201}, 247}, {{244, 98, 52, 140, 0, 180, 79, 197, 24, 159, 58, 173, 137, 77, 119, 253}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 14, 185, 79, 143, 213}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 58, 143, 70, 117}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 244, 96, 115, 189}, 247}, {{244, 98, 52, 140, 0, 235, 84, 137, 224, 163, 47, 20, 32, 220, 119, 152}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 91, 238}, 247}, {{244, 98, 52, 140, 0, 0, 91, 125, 202, 217, 214, 93, 58, 234, 238, 43}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 29, 255, 28, 68, 179, 173, 88}, 247}, {{244, 98, 52, 140, 248, 255, 170, 251, 198, 233, 247, 219, 42, 48, 30, 221}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 178, 70, 142, 230, 156, 159}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 52}, 247}, {{244, 98, 52, 140, 0, 147, 232, 190, 58, 5, 146, 255, 30, 14, 124, 162}, 247}, {{244, 98, 52, 140, 129, 69, 131, 33, 126, 240, 131, 2, 173, 188, 125, 217}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 73, 62, 177, 67}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 67, 218, 15, 254, 155, 83}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 55, 167, 61, 99}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 80}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 80, 252, 186, 189}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 235, 156, 65, 57, 32}, 247}, {{244, 98, 52, 140, 0, 250, 65, 79, 33, 236, 180, 83, 86, 30, 220, 5}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 141, 165, 186, 177}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 210, 46, 193, 34, 69}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 77}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 107, 150, 161, 105, 130, 104, 112, 38}, 247}, {{244, 98, 52, 140, 0, 106, 148, 151, 32, 4, 10, 216, 135, 66, 224, 152}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 198, 103, 139, 126, 40, 129}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 26, 1, 70, 246, 140, 108}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 204, 235, 36, 11, 12, 158, 128, 161}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 240, 167, 68, 224, 120, 208}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 232, 100}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 89}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 163, 175, 239, 122, 238, 104, 58}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 208, 169, 37, 143}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 217}, 247}, {{244, 98, 52, 140, 0, 0, 0, 127, 37, 50, 183, 174, 165, 227, 43, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 123}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 53, 80, 252, 240, 69}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 228, 123, 188, 234, 147, 252, 69, 214, 9}, 247}, {{244, 98, 52, 140, 0, 0, 244, 164, 92, 19, 116, 52, 181, 214, 104, 180}, 247}, {{244, 98, 52, 140, 0, 0, 0, 235, 191, 223, 178, 141, 184, 53, 151, 58}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 77, 31, 78, 90}, 247}, {{244, 98, 52, 140, 0, 0, 0, 4, 54, 56, 139, 77, 160, 59, 146, 246}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 163, 254}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 113, 205, 79, 100}, 247}, {{244, 98, 52, 140, 0, 0, 180, 171, 58, 209, 223, 225, 127, 120, 109, 210}, 247}, {{244, 98, 52, 140, 0, 0, 220, 243, 232, 153, 122, 177, 82, 147, 112, 224}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 243, 152, 233, 131, 185, 153}, 247}, {{244, 98, 52, 140, 0, 0, 102, 242, 105, 42, 187, 205, 191, 82, 71, 32}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 88, 81, 105, 55, 78, 237, 115, 203}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 213, 173}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 2, 57}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 7, 94}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 183, 171}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 105, 98, 193, 74, 197}, 247}, {{244, 98, 52, 140, 0, 142, 150, 88, 236, 182, 175, 132, 242, 45, 74, 253}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 246, 172, 113, 96, 12, 161, 11}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 181, 55, 116, 97, 247, 169, 24, 103}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 61, 175, 130, 225}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 57, 203}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 199, 215, 71, 230, 36, 227, 115, 59}, 247}, {{244, 98, 52, 140, 58, 251, 10, 230, 249, 228, 63, 7, 67, 0, 74, 152}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 202}, 247}, {{244, 98, 52, 140, 0, 116, 139, 45, 151, 137, 171, 93, 146, 226, 216, 80}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 110}, 247}, {{244, 98, 52, 140, 0, 0, 0, 52, 210, 100, 201, 161, 45, 101, 3, 79}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 60, 236, 174, 115}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 154, 27, 66, 227, 89, 223, 63, 133}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 253, 195, 201, 242, 103, 164, 251, 38}, 247}, {{244, 98, 52, 140, 171, 129, 92, 216, 157, 85, 130, 4, 184, 100, 244, 44}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 164, 92, 255, 39, 103}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 17, 10, 123, 251, 56, 192}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 76, 19, 19, 41, 51}, 247}, {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 23}, 247}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 159, 48, 218}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 170}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 23, 143, 105, 53}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 67, 15, 235, 87}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 179, 207}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 18, 55, 219}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 114, 236, 34, 72}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 204, 55, 118}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 107, 60}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 128, 166, 30}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 202}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 102}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 113}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 239, 137, 192}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 61, 160, 31}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 111}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 111, 236, 6, 28, 132}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 225, 81, 192}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 98, 214, 56, 167, 246}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 57, 230, 84, 140}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 10}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 164, 199, 43}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 99, 142}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 86, 60}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 177, 193, 122, 127}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 13, 88, 200, 223}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 239, 122, 93, 47}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 204, 83}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 92, 126, 159}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 188, 194, 170, 108}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 169, 255, 25, 49}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 243, 81, 185, 142}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 62, 237, 200, 8, 250}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 235, 197, 69, 59, 219}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 153, 203, 210}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 18, 227}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 207}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 9, 186, 26, 175}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 207, 255, 163}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 172, 17, 239, 9, 107}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 34, 183, 40}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 97, 28, 29}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 18, 124, 99, 185}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 36, 244, 130}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 166, 87, 73, 175, 193}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 13}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 4, 48}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 113, 107, 166, 139, 34}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 4, 216}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 162, 162, 121, 125}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 127, 209}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 226, 231, 83, 138}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 55, 228, 241}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 169, 239, 38}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 97, 23}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 176}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 86}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 241, 41, 98, 136}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 250, 59, 134}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 250, 254, 8, 91}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 192, 59}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 146, 133, 118}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 96, 12, 245}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 81}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 153, 180}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 176, 83, 165, 138}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 147}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 124, 51, 101}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 235, 137, 103}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 66, 29, 9, 82}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 253, 3, 212, 56}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 58, 44, 84, 91, 92}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 89, 81}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 155, 5, 211}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 124, 235, 74, 250}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 233, 232, 186, 241}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 72, 209, 132, 114}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 43}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 60, 237}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 159, 16, 246, 161, 37}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 69, 90}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 109, 225, 204}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 240}, 12}, {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 120}, 12}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 155, 149, 171, 90, 185, 132}, 129}, {{60, 64, 0, 0, 0, 0, 0, 67, 173, 8, 133, 144, 161, 130, 170, 21}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 180, 195, 22, 43, 167, 147, 55, 181, 135, 49, 181, 182, 58, 177}, 129}, {{60, 64, 0, 0, 0, 0, 0, 197, 114, 142, 38, 89, 154, 7, 235, 160}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 23, 246, 103, 167}, 129}, {{60, 64, 0, 0, 0, 0, 0, 194, 15, 159, 165, 51, 16, 20, 160, 11}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 104, 8, 105, 79, 180, 57, 150, 252}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 189, 101, 33, 161, 106, 123, 111, 141}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 129}, {{60, 64, 0, 208, 111, 142, 188, 38, 100, 10, 13, 225, 78, 110, 87, 195}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 190, 2, 127, 49, 236, 237, 23}, 129}, {{60, 64, 0, 0, 0, 51, 220, 163, 106, 196, 185, 153, 102, 47, 54, 148}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 4, 123, 107, 116, 28, 242}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 192, 219, 164, 243, 244, 50}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 49, 98}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 232, 100, 12, 181, 167, 111, 227, 197}, 129}, {{60, 64, 0, 0, 0, 0, 0, 220, 50, 199, 255, 193, 195, 96, 46, 31}, 129}, {{60, 64, 0, 0, 0, 14, 126, 151, 46, 172, 237, 77, 172, 113, 199, 27}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 22}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 132, 11, 131, 234, 51, 200, 32}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 207, 223, 116, 20, 34, 140, 45}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 229, 209}, 129}, {{60, 64, 0, 0, 0, 0, 0, 116, 106, 152, 179, 100, 114, 90, 115, 33}, 129}, {{60, 64, 0, 0, 0, 0, 9, 134, 16, 162, 195, 4, 181, 141, 172, 161}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 56}, 129}, {{60, 64, 0, 0, 234, 73, 72, 119, 67, 182, 237, 77, 219, 208, 201, 44}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 29, 233, 233, 47, 238, 243, 75, 210}, 129}, {{60, 64, 0, 184, 224, 12, 126, 188, 198, 109, 66, 208, 24, 216, 71, 40}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 57, 30, 204, 33, 56, 177, 57}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 214, 190, 24, 37}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 117, 161, 102, 6, 40, 146, 122, 214, 183, 190, 11}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 155, 173, 150, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 168, 160, 2, 229, 133, 194, 139, 138}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 22, 86, 59, 152}, 129}, {{60, 64, 0, 0, 0, 0, 192, 177, 25, 74, 72, 114, 204, 248, 241, 181}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 251}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 54, 71}, 129}, {{60, 64, 0, 47, 174, 227, 17, 206, 79, 141, 26, 118, 119, 54, 45, 178}, 129}, {{60, 64, 0, 125, 196, 203, 30, 125, 212, 151, 212, 199, 4, 140, 128, 96}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 192}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 52, 17, 91}, 129}, {{60, 64, 0, 0, 0, 0, 173, 162, 45, 14, 155, 54, 143, 114, 109, 95}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 201, 89, 37, 6}, 129}, {{60, 64, 0, 122, 182, 173, 245, 112, 239, 62, 119, 136, 206, 101, 59, 48}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 72, 126, 209, 43, 140, 110}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 5, 98}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 67, 226, 135, 22, 85, 248, 48, 255}, 129}, {{60, 64, 0, 228, 210, 13, 57, 215, 114, 163, 0, 95, 185, 82, 233, 255}, 129}, {{60, 64, 0, 0, 102, 31, 193, 55, 72, 241, 30, 127, 102, 95, 146, 55}, 129}, {{60, 64, 0, 0, 0, 0, 9, 2, 229, 180, 122, 46, 144, 219, 34, 55}, 129}, {{60, 64, 0, 0, 167, 140, 141, 184, 23, 243, 211, 245, 176, 83, 126, 220}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 37, 98, 207}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 102, 232, 20, 98, 175, 169, 64}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 129}, {{60, 64, 0, 0, 0, 0, 0, 223, 178, 206, 115, 75, 199, 254, 145, 242}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 128}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 214, 124}, 129}, {{60, 64, 0, 0, 0, 0, 0, 38, 123, 22, 190, 110, 24, 61, 91, 207}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 55, 15, 88, 249, 166, 73, 124}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 11, 141, 246, 21, 220, 217, 37, 44}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 121}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 129}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 103, 38, 147, 21, 100, 31, 124, 238}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 99, 176, 225, 58, 147, 240, 162}, 129}, {{60, 64, 0, 0, 0, 214, 132, 228, 51, 210, 23, 70, 120, 139, 176, 5}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 119}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 96, 154, 181, 163, 105, 64, 30, 100}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 83, 36, 41, 74, 142, 72, 18, 61}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 26, 2, 92, 204, 61, 5, 96}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 122, 81, 87, 64}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 129}, {{60, 64, 0, 0, 0, 0, 0, 122, 77, 12, 24, 17, 37, 70, 15, 245}, 129}, {{60, 64, 0, 0, 11, 145, 28, 161, 98, 57, 10, 4, 169, 68, 44, 5}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 129}, {{60, 64, 0, 26, 161, 122, 213, 213, 33, 235, 33, 26, 40, 233, 97, 178}, 129}, {{60, 64, 0, 92, 239, 76, 108, 6, 220, 199, 30, 234, 250, 196, 213, 195}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 15, 236, 46, 178, 74, 83, 229, 28}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 41, 66}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 129}, {{60, 64, 0, 0, 193, 100, 214, 161, 164, 130, 84, 68, 234, 108, 134, 34}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 165, 8, 219, 232, 86, 227, 162, 92}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 127}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 46, 34, 15, 198}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 161}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 30, 73, 67, 224, 223, 63, 60, 248}, 129}, {{60, 64, 0, 0, 0, 30, 123, 136, 76, 187, 100, 68, 132, 110, 180, 14}, 129}, {{60, 64, 0, 187, 119, 19, 117, 59, 22, 201, 206, 242, 67, 188, 223, 194}, 129}, {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 190, 128}, 129}, {{60, 64, 109, 95, 139, 155, 85, 84, 7, 193, 67, 193, 238, 30, 210, 172}, 129}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 196, 204, 205}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 251, 112, 150, 174}, 50}, {{208, 0, 0, 0, 0, 161, 171, 48, 177, 38, 53, 116, 206, 47, 249, 59}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 247, 160}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 155, 5, 185, 62, 218, 5, 41, 195}, 50}, {{208, 0, 27, 239, 179, 206, 142, 150, 78, 41, 235, 114, 135, 106, 71, 205}, 50}, {{208, 0, 0, 14, 124, 76, 159, 71, 182, 170, 107, 123, 40, 159, 40, 116}, 50}, {{208, 0, 0, 0, 0, 78, 116, 138, 140, 58, 100, 73, 157, 10, 107, 95}, 50}, {{208, 0, 0, 197, 219, 1, 248, 38, 124, 37, 15, 248, 6, 242, 12, 191}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 219, 192, 66, 145, 92}, 50}, {{208, 0, 0, 0, 0, 0, 178, 136, 199, 34, 88, 237, 29, 251, 6, 203}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 59, 132, 216}, 50}, {{208, 0, 0, 0, 0, 0, 0, 210, 141, 53, 0, 70, 40, 40, 161, 247}, 50}, {{208, 0, 0, 0, 0, 0, 0, 100, 208, 196, 243, 191, 16, 73, 159, 8}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 153, 221, 75, 119, 239, 32, 40}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 248, 242}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 197, 233, 93, 210, 125}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 49, 121, 1, 111, 244}, 50}, {{208, 0, 0, 0, 77, 19, 195, 141, 213, 29, 141, 120, 223, 222, 26, 174}, 50}, {{208, 0, 0, 0, 226, 35, 254, 55, 251, 178, 7, 23, 26, 15, 161, 203}, 50}, {{208, 0, 0, 0, 0, 156, 224, 152, 138, 59, 244, 224, 229, 210, 140, 104}, 50}, {{208, 0, 0, 0, 0, 71, 33, 29, 15, 36, 113, 57, 58, 76, 135, 127}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 109, 92, 177, 243, 36}, 50}, {{208, 0, 247, 151, 31, 193, 251, 43, 217, 214, 195, 2, 185, 204, 132, 35}, 50}, {{208, 0, 62, 158, 139, 238, 149, 125, 92, 114, 131, 24, 163, 13, 242, 189}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 116}, 50}, {{208, 0, 186, 230, 126, 134, 20, 12, 196, 45, 178, 126, 34, 15, 108, 210}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 28}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 208, 169}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 200}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, 44, 249, 18, 121}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 200, 214, 98}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 198, 46}, 50}, {{208, 83, 185, 153, 233, 127, 167, 13, 0, 109, 210, 121, 208, 91, 119, 236}, 50}, {{208, 0, 0, 0, 0, 0, 0, 6, 128, 105, 214, 50, 111, 187, 101, 53}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 2, 2, 211, 15, 241, 22, 70, 204}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 196, 7, 241, 118, 1, 99, 223}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 32}, 50}, {{208, 0, 0, 0, 0, 0, 123, 62, 237, 218, 186, 176, 34, 8, 76, 124}, 50}, {{208, 0, 72, 250, 135, 189, 123, 16, 162, 37, 115, 140, 202, 70, 57, 18}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 222, 213, 231, 255, 37, 185, 172, 206}, 50}, {{208, 0, 0, 0, 0, 0, 0, 177, 47, 113, 55, 155, 106, 75, 82, 77}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 72, 196, 54, 208, 197, 197, 54, 126}, 50}, {{208, 0, 0, 0, 32, 230, 47, 43, 180, 151, 102, 227, 36, 174, 38, 109}, 50}, {{208, 0, 0, 0, 0, 0, 34, 159, 237, 148, 134, 78, 21, 97, 244, 89}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 59, 243}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 49, 194}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 145, 22}, 50}, {{208, 0, 182, 42, 249, 156, 45, 174, 179, 244, 86, 46, 60, 186, 48, 181}, 50}, {{208, 0, 0, 0, 0, 158, 40, 161, 129, 81, 227, 225, 27, 58, 134, 80}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 57, 176, 78}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 206, 160, 218, 66, 189, 110, 123}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 170, 17, 28, 191, 77, 81, 250, 42}, 50}, {{208, 0, 0, 89, 3, 15, 54, 199, 44, 151, 20, 222, 246, 37, 106, 15}, 50}, {{208, 0, 117, 58, 90, 211, 216, 193, 1, 140, 83, 34, 111, 116, 254, 228}, 50}, {{208, 0, 0, 0, 105, 59, 228, 110, 184, 250, 37, 116, 61, 27, 199, 168}, 50}, {{208, 0, 0, 0, 0, 27, 154, 161, 150, 17, 189, 117, 126, 209, 4, 86}, 50}, {{208, 0, 0, 0, 0, 0, 107, 100, 8, 84, 82, 211, 54, 250, 26, 155}, 50}, {{208, 0, 0, 0, 0, 0, 113, 122, 248, 204, 2, 8, 83, 243, 174, 137}, 50}, {{208, 0, 0, 0, 0, 70, 21, 129, 236, 146, 64, 247, 18, 237, 156, 240}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 231, 241, 17, 14, 32, 223, 74, 49}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 223, 54, 220, 54, 232, 30, 5}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 81, 157, 208, 111, 27}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 165, 58, 125, 96, 33, 150, 127}, 50}, {{208, 0, 0, 0, 0, 50, 119, 7, 201, 179, 148, 205, 14, 113, 220, 29}, 50}, {{208, 0, 0, 0, 0, 0, 229, 38, 163, 13, 193, 53, 109, 47, 162, 107}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 237, 109, 191, 212}, 50}, {{208, 0, 0, 232, 189, 93, 49, 32, 152, 106, 210, 237, 92, 89, 141, 206}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 6, 183, 88}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 24, 202}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 50}, {{208, 0, 0, 0, 0, 172, 205, 137, 51, 35, 49, 6, 114, 107, 41, 223}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 221}, 50}, {{208, 0, 0, 0, 0, 0, 243, 88, 182, 199, 110, 96, 17, 58, 109, 111}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 240, 13, 60, 16, 179, 74, 7, 32}, 50}, {{208, 0, 0, 31, 91, 169, 203, 19, 109, 84, 80, 9, 208, 12, 227, 185}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 100, 29, 35}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 97, 26, 5}, 50}, {{208, 0, 0, 17, 14, 155, 250, 109, 143, 18, 66, 20, 174, 213, 56, 155}, 50}, {{208, 0, 0, 0, 0, 176, 24, 110, 244, 124, 186, 9, 16, 251, 30, 127}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 38, 215, 144, 149, 193}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 252, 231, 6, 131, 20, 65, 147}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 179, 131, 139, 1, 142, 157, 69}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 47, 100, 0, 127, 198}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 35, 54, 196, 91}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 253, 124}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 219, 77, 230}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 226, 141, 86, 147, 22, 4, 121, 0}, 50}, {{208, 0, 0, 0, 0, 0, 0, 0, 0, 204, 173, 84, 178, 153, 231, 127}, 50}, {{208, 0, 0, 0, 0, 53, 35, 125, 117, 135, 60, 238, 52, 225, 78, 118}, 50}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 250}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 194, 226}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 137, 164, 229, 41, 25}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 187, 183, 1, 167, 204}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 243}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 186, 37, 240, 205, 181}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 155, 163, 14, 47, 233}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 223, 37, 226, 134, 27}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 3}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 58, 39}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 60, 152}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 177, 189, 241, 180, 215, 109}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 167}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 238, 109, 230, 164, 43, 144}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 113, 157, 71, 12}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 242}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 172, 116, 32, 119}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 121, 227, 227}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 6, 101}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 168}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 105}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 27, 234, 41, 73}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 16}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 56, 69, 170}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 146, 216, 184}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 195, 0, 93}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 63, 2}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 51}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 127, 229, 207, 25, 176, 222}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 165, 85, 242, 144}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 237, 54, 111, 204, 207}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 87, 56, 232, 108, 67, 248}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 96, 235, 225, 164, 238}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 72, 3, 113, 145}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 110, 22, 84}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 190, 226, 119, 65}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 196, 152, 155}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 222, 232, 254, 130, 124, 1}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 129, 66, 56, 32}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 74, 104}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 13}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 189, 147, 126, 169}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 217}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 245, 37, 227, 241}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 216}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 217, 210, 208, 155, 155}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 226, 15, 165, 197, 1}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 226, 140}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 45, 119}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 169}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 108}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 17, 27, 109}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 196, 228, 206}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 177, 60, 180, 231, 197}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 253, 241}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 224, 47}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 46, 17}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 90, 224, 219, 129, 141}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 48, 39, 106, 22, 139}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 180, 241, 163, 119}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 82, 35, 64}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 198, 252}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 175, 39, 60, 176}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 107, 33, 45}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 153, 94}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 239, 122, 159, 186, 175}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 96, 131}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 132, 253, 87}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 54, 245, 176, 83}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 207, 96, 146, 173}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 79}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 190}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 242}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 23, 92}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 179, 36, 97, 52}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 250, 166, 196}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 187}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 17, 252, 128, 78}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 108}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 56, 23, 54, 211, 136}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 23, 155, 117, 195}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 166, 211}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 131, 112}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 114, 191, 53, 242, 201, 36}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 62, 198, 239}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 55, 18, 67}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 56}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 174, 170}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 127, 174, 120, 127, 223}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 249}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 224, 185, 59, 177, 183, 151, 172, 213, 141, 230}, 218}, {{128, 0, 84, 139, 26, 38, 16, 43, 227, 13, 247, 98, 118, 196, 96, 145}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 69, 23, 184, 117, 207, 236, 152}, 218}, {{128, 0, 0, 0, 0, 0, 0, 7, 130, 78, 121, 232, 143, 85, 112, 255}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 136, 93, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 29, 169, 252, 182, 201, 209, 159, 240, 129}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 240, 104, 175, 73, 144}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 122, 181}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 218}, {{128, 0, 0, 0, 0, 0, 0, 112, 185, 215, 101, 54, 219, 145, 178, 237}, 218}, {{128, 0, 249, 40, 246, 184, 221, 92, 102, 76, 210, 181, 45, 19, 154, 81}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 165, 130}, 218}, {{128, 0, 0, 181, 227, 148, 161, 244, 74, 159, 64, 101, 60, 240, 123, 229}, 218}, {{128, 0, 0, 0, 0, 147, 210, 253, 232, 106, 84, 226, 70, 36, 197, 157}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 218, 14, 43, 110}, 218}, {{128, 193, 5, 238, 21, 205, 91, 77, 50, 117, 94, 153, 249, 34, 197, 38}, 218}, {{128, 0, 0, 0, 0, 0, 241, 158, 88, 210, 203, 75, 237, 159, 218, 12}, 218}, {{128, 99, 215, 237, 150, 234, 166, 143, 88, 172, 114, 126, 17, 1, 1, 248}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 253, 200, 176, 86}, 218}, {{128, 0, 0, 0, 155, 43, 129, 107, 135, 10, 38, 2, 244, 133, 213, 45}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 76, 175}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 243, 94, 222, 73, 116, 55, 100}, 218}, {{128, 0, 0, 0, 122, 29, 34, 58, 77, 36, 182, 133, 21, 199, 28, 84}, 218}, {{128, 0, 0, 0, 0, 166, 138, 145, 218, 177, 33, 160, 150, 192, 28, 212}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 37, 39}, 218}, {{128, 0, 0, 0, 0, 0, 0, 79, 189, 241, 244, 101, 246, 163, 219, 87}, 218}, {{128, 223, 180, 73, 207, 248, 237, 83, 213, 37, 21, 31, 87, 136, 98, 167}, 218}, {{128, 0, 0, 0, 19, 254, 1, 214, 105, 181, 140, 253, 255, 137, 130, 158}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 76, 171, 50, 68, 148}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 152, 26, 245}, 218}, {{128, 0, 0, 0, 0, 0, 35, 6, 131, 9, 67, 57, 46, 191, 175, 63}, 218}, {{128, 0, 0, 59, 18, 61, 12, 193, 146, 59, 96, 27, 144, 38, 114, 197}, 218}, {{128, 48, 182, 53, 69, 115, 164, 16, 235, 160, 213, 209, 164, 175, 137, 135}, 218}, {{128, 0, 189, 34, 226, 210, 166, 155, 6, 82, 43, 209, 92, 212, 62, 20}, 218}, {{128, 0, 0, 0, 0, 0, 0, 56, 89, 43, 182, 107, 121, 87, 236, 125}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 73, 58, 7, 73, 40, 108, 239}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 163, 11, 230, 99, 243, 38, 14, 252}, 218}, {{128, 0, 52, 21, 111, 54, 147, 187, 202, 228, 132, 31, 49, 141, 218, 251}, 218}, {{128, 0, 249, 25, 225, 181, 222, 135, 170, 127, 148, 178, 109, 74, 221, 61}, 218}, {{128, 65, 181, 66, 215, 193, 105, 13, 218, 166, 128, 79, 16, 234, 55, 138}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 121, 81, 161, 161}, 218}, {{128, 0, 0, 0, 0, 180, 123, 81, 88, 212, 155, 207, 57, 163, 79, 230}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 161, 221, 44, 196}, 218}, {{128, 0, 0, 0, 9, 165, 151, 102, 81, 120, 107, 207, 218, 135, 56, 60}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 149, 190, 1, 107}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 235, 155, 133, 167}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 57}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 127, 56, 153, 219, 208, 138, 102, 81, 244, 94, 157, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 227, 105, 64, 213}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 24, 87, 62, 137, 93, 164, 102, 158, 12, 10, 24, 188, 206}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 99, 10, 44, 218, 11}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 64, 2, 247, 27, 28, 212, 214, 177}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 218}, {{128, 0, 0, 0, 0, 0, 0, 83, 111, 96, 210, 23, 217, 26, 94, 111}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 214, 51, 206, 207, 190, 36, 16, 128, 132, 243}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 19}, 218}, {{128, 0, 0, 190, 248, 238, 168, 41, 178, 30, 121, 241, 11, 190, 167, 13}, 218}, {{128, 0, 0, 0, 225, 192, 109, 109, 24, 249, 110, 106, 176, 239, 14, 14}, 218}, {{128, 0, 169, 0, 189, 132, 175, 127, 68, 11, 222, 247, 196, 142, 203, 71}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 68, 14, 206, 27, 65, 206, 87, 221}, 218}, {{128, 0, 27, 137, 115, 82, 246, 90, 35, 102, 92, 32, 98, 244, 210, 39}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 231, 139, 79, 27}, 218}, {{128, 0, 0, 0, 0, 0, 146, 69, 90, 85, 91, 123, 31, 206, 171, 29}, 218}, {{128, 178, 167, 247, 16, 190, 6, 121, 58, 249, 205, 74, 61, 138, 182, 3}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 204, 173, 12, 232, 210}, 218}, {{128, 0, 0, 193, 127, 159, 21, 136, 118, 244, 109, 136, 200, 235, 204, 72}, 218}, {{128, 0, 0, 228, 156, 220, 213, 87, 241, 26, 205, 134, 57, 227, 219, 8}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 139, 244, 122, 211, 53, 226, 181, 216}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 63, 209, 222}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 143, 228, 60, 185, 134, 77, 243}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 108, 185, 173}, 218}, {{128, 53, 0, 188, 6, 210, 64, 37, 122, 174, 43, 112, 99, 50, 107, 65}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 147, 154, 172, 88}, 218}, {{128, 0, 0, 0, 0, 0, 0, 108, 48, 250, 39, 17, 203, 88, 229, 99}, 218}, {{128, 0, 0, 0, 0, 0, 31, 18, 28, 104, 244, 11, 87, 80, 205, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 239, 27, 236, 207, 188, 195, 91}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 163, 208, 113}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 181}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 147, 93, 232, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 179, 241, 255, 15, 61, 28, 122, 180, 34, 76, 170, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 99, 127, 234, 129, 187, 55, 253, 183, 175, 120, 210, 6, 25, 111}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 41, 207, 101, 184, 60, 158, 177}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 236, 219, 134, 55, 63}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 204}, 218}, {{128, 0, 0, 0, 37, 140, 177, 79, 210, 7, 14, 57, 32, 20, 65, 75}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 155, 252}, 218}, {{128, 0, 0, 0, 115, 15, 204, 154, 64, 72, 12, 2, 138, 83, 66, 231}, 218}, {{128, 0, 22, 135, 233, 209, 131, 217, 112, 16, 59, 131, 151, 84, 205, 212}, 218}, {{128, 0, 0, 0, 0, 0, 184, 77, 35, 223, 216, 16, 144, 137, 9, 46}, 218}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 58}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 32}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 13, 170, 131}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 24, 165}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 143, 57, 60}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 143, 69}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 239, 58, 198}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 13}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 69}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 12, 127, 160}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 110, 1}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 103, 185, 86, 178}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 249, 150, 233}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 55, 225, 231}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 16, 104}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 201, 49, 8, 240}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 50, 56, 63}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 54, 28, 56, 184}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 167, 34}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 136}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 227, 78, 238}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 62}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 75, 232, 218, 177}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 7, 164, 58}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 74, 194, 126}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 68}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 146}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 6, 199, 211, 254}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 104, 97}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 109, 26, 209}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 45, 213, 153, 217}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 21}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 76, 169}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 12}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 130, 45}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 208, 43, 91}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 243, 89}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 213, 218, 24, 40}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 97, 177, 2, 18}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 57, 7, 107, 235}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 213, 218, 198}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 197}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 58}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 29, 118, 166}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 4, 194, 231}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 43}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 24, 205}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 77, 18}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 22, 103}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 35}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 245, 136}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 43}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 223, 177, 54, 205}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 86, 58}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 108, 249, 121}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 22, 239}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 219, 84, 2, 152}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 128}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 220}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 222, 139}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 215}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 122, 209, 179, 187}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 26, 137, 149, 234}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 76}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 108, 68, 67, 138}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 201, 130}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 155}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 142, 90}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 220, 243, 182, 113}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 181}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 128, 249, 209}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 100, 109}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 67, 145}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 44, 5}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 27, 179, 125}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 16}, 228}, {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 236, 51}, 228}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 213}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 90}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 21, 56, 228, 91}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 7, 23, 86}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 237, 29, 22}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 112, 188}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 18, 217, 173, 174, 205, 189, 228}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 239, 168, 60}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 11, 160, 50}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 150, 87, 163, 135, 29}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 105, 161, 4, 239}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 31}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 95, 205}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 194, 189}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 184, 40}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 245, 238, 100, 166, 56, 187, 167}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 240}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 8}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 91}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 5, 236, 83}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 27, 137, 50, 122, 182, 210, 73}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 166, 65}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 152, 50, 63, 12, 99}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 30, 54}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 146, 177, 164}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 183}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 52, 169, 173, 237, 130, 250, 162}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 56}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 55, 65, 75, 119, 185, 238, 134}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 25, 235, 226}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 2, 93, 176}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 156, 39, 185, 140}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 32}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 168, 217, 211, 162, 46}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 103, 173, 27, 134, 111, 111, 17}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 136, 114, 109}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 244}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 110, 226, 188, 153, 255, 134}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 38, 132}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 252}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 10, 86, 72, 190}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 90, 254}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 145, 176, 246}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 131}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 26, 205, 125}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 28, 129}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 187, 28, 243}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 96, 194}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 71, 255}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 249, 79, 193, 58, 62}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 124, 115, 130}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 189}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 85, 198, 140, 188, 143, 2}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 240}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 22, 100, 188, 155, 108}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 68}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 198, 48, 201, 176, 73}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 181, 224}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 252, 100, 168, 131, 115, 123}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 28, 185, 74, 53}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 98, 99}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 104, 165, 12}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 120, 155, 81, 232, 238, 234, 168}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 103, 121, 95, 71, 60}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 94}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 246, 191, 149, 245}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 188, 105, 194, 188, 30}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 200}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 40, 53, 183, 63, 197, 116}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 122, 234, 61, 21, 14}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 16, 98, 48}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 135, 59, 80, 154, 40}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 105}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 127, 25, 58, 226}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 49, 62, 33, 137, 112, 92, 179}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 204, 130, 250, 193, 203, 114}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 151, 137, 10, 183, 149, 137}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 164, 155, 199}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 189, 253, 15, 12, 240, 155, 208}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 139, 72}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 55}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 170, 117, 145, 168, 159, 134}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 197, 240}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 228}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 138}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 46}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 95, 141, 87, 185, 155, 134}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 61, 101, 139, 186, 218, 133, 75}, 181}, {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 104}, 181}, {{153, 61, 0, 0, 0, 0, 0, 136, 99, 223, 130, 129, 163, 49, 213, 49}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 17, 147}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 109, 105, 189, 107, 221, 49, 92, 119}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 171, 39, 189, 79, 143, 100}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 137, 94}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 116, 56, 147, 194}, 206}, {{153, 61, 0, 0, 0, 0, 0, 208, 101, 40, 169, 45, 225, 237, 219, 75}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 255, 89, 203, 58, 89, 161, 227, 26}, 206}, {{153, 61, 0, 0, 0, 0, 132, 16, 121, 255, 174, 65, 23, 172, 251, 212}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 2, 150, 80, 110}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 251, 186, 110, 177, 72, 191, 226}, 206}, {{153, 61, 0, 0, 0, 195, 200, 69, 96, 41, 121, 119, 75, 237, 228, 227}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 206}, {{153, 61, 0, 0, 0, 42, 171, 91, 195, 21, 241, 191, 114, 185, 206, 79}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 35, 23, 13}, 206}, {{153, 61, 0, 0, 102, 127, 111, 16, 25, 204, 107, 235, 41, 110, 21, 84}, 206}, {{153, 61, 0, 0, 80, 151, 242, 195, 110, 165, 230, 241, 55, 95, 160, 179}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 218, 221, 210}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 164, 16, 225, 37, 240, 185, 182, 41}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 101, 239, 85, 82, 174, 68, 229}, 206}, {{153, 61, 0, 0, 0, 0, 39, 242, 202, 169, 31, 230, 140, 223, 132, 190}, 206}, {{153, 61, 0, 0, 0, 175, 10, 196, 124, 181, 39, 10, 90, 191, 196, 4}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 72, 207, 189, 89}, 206}, {{153, 61, 0, 0, 0, 0, 250, 61, 195, 221, 147, 81, 229, 176, 69, 1}, 206}, {{153, 61, 0, 92, 186, 194, 177, 141, 56, 73, 123, 133, 79, 25, 175, 12}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 219, 229, 202, 198}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 219, 79, 32, 105, 56, 119, 158}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 211, 219, 53, 69}, 206}, {{153, 61, 0, 0, 0, 0, 0, 225, 70, 83, 110, 181, 120, 20, 172, 231}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 123, 27}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 66, 46, 86, 116, 244, 230, 6}, 206}, {{153, 61, 0, 0, 93, 115, 125, 125, 183, 94, 183, 16, 15, 192, 63, 182}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 214, 95, 126, 79}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 71, 237, 161, 71, 45, 18, 74}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 164, 202, 192}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 206}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 167, 141, 185, 207, 11, 138, 179, 212}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 26, 33}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 145}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 206}, {{153, 61, 0, 214, 3, 158, 196, 5, 23, 211, 78, 90, 80, 157, 197, 205}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 231, 176, 220, 192}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 21, 115, 37}, 206}, {{153, 61, 0, 0, 0, 0, 0, 225, 200, 29, 96, 14, 65, 110, 116, 42}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 200, 111, 93, 232, 22, 203, 5, 81, 244, 193}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 45, 70}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 143, 210, 208, 103}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 247, 28, 193, 238, 98, 15}, 206}, {{153, 61, 0, 0, 120, 89, 82, 229, 108, 191, 171, 142, 62, 232, 132, 6}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 6}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 206}, {{153, 61, 0, 0, 222, 234, 181, 72, 2, 7, 76, 56, 80, 31, 244, 149}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 226, 72, 115, 82}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 161, 99}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 189, 2, 145, 99}, 206}, {{153, 61, 0, 0, 0, 68, 218, 31, 126, 2, 125, 146, 152, 170, 180, 209}, 206}, {{153, 61, 0, 0, 0, 184, 46, 203, 67, 112, 73, 220, 158, 168, 245, 152}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 222, 204, 117}, 206}, {{153, 61, 0, 0, 0, 83, 56, 178, 196, 211, 92, 33, 98, 220, 45, 96}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 25, 237}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 137}, 206}, {{153, 61, 0, 0, 0, 0, 0, 235, 208, 142, 64, 200, 218, 71, 184, 66}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 155, 59, 38}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 51, 23, 118, 67, 76, 177, 61, 94}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 167, 47, 21, 188, 33, 47}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 185, 176, 216, 247, 182, 24, 42, 244}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 24, 232, 167, 35, 241, 104}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 58, 89, 183, 72, 5, 36, 9, 136}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 91, 233, 232, 89}, 206}, {{153, 61, 0, 0, 0, 0, 68, 47, 70, 133, 247, 92, 201, 168, 91, 149}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 250, 13}, 206}, {{153, 61, 0, 0, 46, 2, 226, 157, 137, 51, 215, 247, 113, 110, 197, 185}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 123, 122, 236, 185, 228, 209, 176}, 206}, {{153, 61, 0, 0, 196, 105, 243, 109, 208, 202, 75, 51, 179, 204, 73, 160}, 206}, {{153, 61, 0, 0, 0, 160, 7, 205, 120, 251, 27, 221, 176, 105, 64, 208}, 206}, {{153, 61, 0, 0, 181, 58, 77, 18, 110, 210, 252, 48, 85, 179, 226, 183}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 163, 70, 189, 113, 80, 140, 247}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 172, 177}, 206}, {{153, 61, 0, 0, 0, 0, 0, 202, 50, 53, 51, 129, 148, 220, 21, 57}, 206}, {{153, 61, 0, 0, 0, 0, 111, 203, 213, 202, 95, 91, 91, 149, 51, 175}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 219, 108, 106, 148}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 90, 229}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 19, 185}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 42, 74, 56, 38}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 84, 178, 197}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 129, 37, 82, 179, 255, 5, 77, 118}, 206}, {{153, 61, 0, 0, 0, 0, 0, 0, 0, 126, 240, 115, 23, 46, 74, 160}, 206}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 253, 31}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 8, 9, 252, 248, 250, 197}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 202, 97}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 249, 75, 229, 154, 54, 49, 222, 58}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 241, 90, 73, 162, 158}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 68, 252}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 5, 25, 159, 129, 199, 211, 63}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 76, 225}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 91, 247, 252, 192}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 115, 61, 30, 62, 164, 200}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 138, 21}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 242, 222, 13, 75, 236, 253, 169}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 245, 74}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 136, 231, 158, 80}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 84, 24}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 75, 77, 190, 126, 237, 38, 224}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 244, 168, 133}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 40, 46, 68, 145, 199, 241}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 242, 80}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 172, 37, 22, 204, 4}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 158, 175, 138}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 143, 88, 166}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 8, 185, 253, 39, 190, 38, 24, 137}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 81, 139, 77}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 59, 227, 145, 95, 254, 169, 198, 135}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 17}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 137, 124, 117, 65, 39, 225}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 151}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 142}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 192, 198, 155, 122}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 51, 77, 30}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 148, 36, 243, 207, 105, 185}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 254}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 115, 61, 199, 178, 112}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 111, 207, 69}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 196, 172, 231}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 65, 15, 131, 185}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 33}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 171}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 57, 239, 4, 220, 208, 146, 38}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 79, 42, 173}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 229, 50, 139, 50}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 88, 49, 138, 143}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 197, 166, 26, 155}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 255, 251, 60, 213, 190}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 230, 111, 27}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 224, 122}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 144, 103, 176, 141, 154, 104}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 125, 178, 60, 113, 158}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 110, 45, 107, 185, 164}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 188}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 1, 53, 188, 22, 193, 138, 146}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 192, 176}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 16}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 96, 60, 3, 185}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 2, 180, 238}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 4, 233, 30, 36, 87, 122}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 141, 32, 193, 222, 153, 204, 17}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 134, 235, 49, 25, 218, 29, 111}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 183}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 89, 184, 249}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 162, 3}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 125, 142, 99, 93}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 73, 26}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 83, 209, 10, 209, 219}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 10, 131, 228, 116}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 5}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 37, 3, 137, 125, 124}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 129, 212, 76}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 74, 245}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 180, 129}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 82, 245}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 23, 39, 162, 179}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 215}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 206, 85, 144, 6, 89, 72}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 213, 192, 98, 228, 221}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 203, 178, 66}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 93, 45, 249, 181, 176, 204, 39}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 43}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 112, 192}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 217, 3, 134, 157, 243}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 67, 81, 160}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 12, 95, 86, 205, 35, 5, 95}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 83, 152, 99, 175, 185, 131}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 179}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 142, 9, 168, 81, 192, 229}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 91, 251, 211, 203, 246}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 127, 99, 188, 1, 57}, 122}, {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 211, 75, 201, 107, 211, 235}, 122}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 84, 172, 138, 165, 142, 245}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 113}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 51, 115}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 245, 2, 159}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 138, 96, 125}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 85, 212, 15}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 188, 89}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 220}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 1, 236, 251, 92, 72}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 75, 37, 205}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 50, 195, 46}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 237, 125}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 91, 12, 126, 32}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 45, 222}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 220, 234, 156, 235, 171}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 154, 99, 174, 211, 136}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 230, 43}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 175, 240, 253, 191, 118}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 212, 111, 92, 230, 208}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 11, 2, 40}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 175, 152, 89, 27}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 69, 183, 198, 104, 239, 134}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 42}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 93, 197, 219, 235, 38}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 247, 89, 91}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 195}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 55, 37}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 170, 104, 16}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 122, 50}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 31, 144, 110, 112}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 147, 81, 173, 42, 11, 226}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 231}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 20, 177, 92, 159}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 18, 203, 84, 254}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 102, 13}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 197, 131}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 248, 198}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 101, 58}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 146, 76, 171, 187, 38}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 128, 152}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 80}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 209, 6}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 206, 63, 88, 180}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 203, 51, 164, 50}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 53, 119, 6, 205, 50, 231}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 253, 135, 19, 15, 40, 250}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 18, 206, 13, 221, 186}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 161, 57, 166}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 220, 206}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 31}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 94, 3}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 9, 118, 209, 112, 207, 110}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 72, 224, 174}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 89, 50, 251, 52, 227, 46}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 157, 250, 181, 53}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 134, 217, 217, 229, 159}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 253, 169, 35, 168, 19}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 87, 153}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 172}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 53, 8}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 14}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 115, 97, 115, 41}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 92, 201, 248, 108}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 11, 57, 154, 254, 70}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 62, 243, 64, 48, 221, 216}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 230, 62, 145, 35, 253}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 58, 37, 89, 10}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 76, 227, 136, 153, 229, 149}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 123, 35, 83, 188, 187}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 93, 103}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 228}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 138, 181, 30, 111, 124, 30}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 19, 161, 19, 75}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 252, 204}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 197, 228, 248, 123, 78, 209}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 239, 75, 164, 140, 203, 121}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 83}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 149, 253, 183}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 61, 184}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 6}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 201, 229, 94, 163}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 242, 234, 81, 117}, 81}, {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 39, 86, 209, 64}, 81}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 196, 71}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 93}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 56, 135, 55}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 219, 143, 228}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 69, 48}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 241}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 66, 187}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 72, 200, 113}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 36}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 36}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 116}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 235, 235}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 178, 116, 242}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 223, 32, 46}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 209, 240, 154}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 94, 178, 82}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 255, 251}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 163, 192}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 215, 211}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 83, 236, 186}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 214, 90, 169}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 102}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 140, 28}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 6}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 207}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 225}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 40, 122}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 139, 150, 38}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 176, 165}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 7, 183}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 72, 218, 211}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 57, 170, 29}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 245, 38}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 219}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 7, 105}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 32}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 93, 29}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 230, 165, 56}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 60}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 55, 241}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 106, 240, 189}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 221, 124}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 112, 226, 1}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 115, 41}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 1, 26, 145}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 53}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 176, 242}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 155}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 202, 155}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 140}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 193, 52, 250}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 177, 231}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 60}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 226}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 98, 15, 236}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 194, 128}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 34, 150}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 249, 219, 206}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 189, 38}, 175}, {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 175}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 152}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 161}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 50}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 150}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 117}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 159}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 246}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 115}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 249}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 248}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 164}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 151}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 135}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 176}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 208}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 1}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 15}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 74}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 212}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 31}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 181}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 57}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 10}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 100}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 169}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 132}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 175}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 170}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 144, 113, 109}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 84, 156, 248, 138, 222}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 165, 164, 23, 252, 36, 152, 46}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 99, 251, 61}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 196, 162}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 94, 40}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 241, 255, 47, 109, 24, 59, 71}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 36, 140, 124, 16, 31, 25}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 4, 231, 72, 205, 225, 156, 36}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 74, 210}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 101, 200, 226, 198, 60, 88, 95, 177}, 174}, {{187, 42, 31, 144, 236, 70, 0, 209, 44, 200, 27, 209, 89, 50, 71, 135}, 174}, {{187, 42, 31, 144, 236, 70, 0, 74, 72, 201, 58, 205, 217, 24, 100, 126}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 220, 25, 199, 47, 142, 230, 48, 210}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 7, 135, 34, 241, 132, 219, 166}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 38, 216, 154, 44, 172}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 74, 151, 254, 83, 252, 63}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 174}, {{187, 42, 31, 144, 236, 70, 0, 98, 127, 94, 189, 97, 20, 178, 65, 119}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 188, 23, 69, 80, 78, 2, 222, 86}, 174}, {{187, 42, 31, 144, 236, 70, 0, 25, 31, 121, 110, 34, 39, 52, 219, 24}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 45, 127, 198}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 142, 45, 38, 242, 195, 133, 202}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 43, 169, 71, 206, 177, 41}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 18, 33, 129, 242, 230, 195}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 28, 93, 100, 219, 213, 5, 8}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 214, 103, 208}, 174}, {{187, 42, 31, 144, 236, 70, 0, 217, 58, 171, 57, 65, 228, 152, 41, 225}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 198, 1, 93, 245, 232, 100, 133, 50}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 14, 43, 98, 45, 84, 24, 115}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 178, 117, 129, 254, 220, 205}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 213, 149, 5}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 233, 94, 45, 101, 70}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 146, 164, 178}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 105, 34, 234, 131, 121}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 202, 158}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 150, 23, 84, 22}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 203, 38, 135, 192, 136, 244, 227}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 150, 33, 245, 193}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 150, 253}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 222, 172, 188, 122, 178, 86, 21, 58}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 209, 146, 47, 244, 144, 207, 110}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 159, 79, 48, 150}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 35, 63, 114, 226, 227, 130, 125, 50}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 61, 224, 139, 156}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 192, 94, 22}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 137, 28, 65, 215, 180, 210, 36}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 178, 196, 90, 29, 71, 27, 212, 119}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 129, 40, 185, 47, 66, 122, 39}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 49, 133, 134, 171, 114}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 94, 212, 217, 125, 223, 145, 126}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 30, 120, 155, 134, 67}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 243, 85, 197}, 174}, {{187, 42, 31, 144, 236, 70, 0, 197, 184, 117, 104, 158, 151, 125, 125, 186}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 189, 204, 69}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 3, 53, 89, 141, 180, 52, 161}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 174}, {{187, 42, 31, 144, 236, 70, 0, 235, 166, 24, 64, 157, 246, 33, 191, 142}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 138, 46, 39, 195, 36, 207, 47}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 63, 39, 110, 164, 8, 230, 165}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 135, 162, 226, 217, 125, 218}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 154, 227, 77, 153, 113, 82, 23, 212}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 105, 9, 142, 93}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 114, 100}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 124, 233, 188, 137}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 16, 124, 70, 81, 181}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 129, 87, 241, 178, 68}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 222, 197, 78, 143, 248}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 66, 255, 144, 178, 147, 153, 210}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 212, 206, 247, 250, 206, 154, 95, 52}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 174}, {{187, 42, 31, 144, 236, 70, 0, 73, 199, 158, 94, 229, 117, 144, 55, 60}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 43, 251}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 225, 36, 201, 15, 3, 181, 21, 126}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 172, 156, 196, 178, 174, 68, 213}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 250, 207, 74, 226, 219, 67}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 74, 44}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 53, 153, 109, 190, 127}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 155, 179, 66}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 64, 179, 242, 156, 77, 103, 178, 99}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 107, 253, 132, 83}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 62, 204, 11, 204, 108, 144}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 231, 61, 233, 32, 29}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 199, 196}, 174}, {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 198, 214, 90, 24, 37, 240}, 174}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 100, 243, 97, 180, 73, 226, 149}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 64, 140, 159, 97}, 104}, {{90, 214, 185, 128, 0, 0, 224, 28, 106, 189, 216, 213, 186, 195, 126, 243}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 104}, {{90, 214, 185, 128, 0, 0, 40, 100, 48, 55, 198, 101, 152, 183, 33, 237}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 248, 85, 170, 210, 231}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 239, 149, 112, 246, 212, 187}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 42, 115, 13, 21}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 122, 140}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 215, 227, 122, 197, 42, 192, 105, 22}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 118, 26, 96, 238, 70, 11, 90}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 32}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 155, 107, 99, 211, 145, 15, 176, 186}, 104}, {{90, 214, 185, 128, 0, 85, 31, 31, 7, 252, 77, 61, 254, 189, 61, 20}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 74}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 142, 243}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 104}, {{90, 214, 185, 128, 0, 0, 167, 71, 190, 70, 145, 169, 190, 143, 147, 43}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 231, 82, 18, 235}, 104}, {{90, 214, 185, 128, 0, 0, 162, 26, 63, 242, 172, 71, 117, 227, 45, 81}, 104}, {{90, 214, 185, 128, 178, 194, 181, 89, 224, 101, 67, 238, 225, 122, 62, 254}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 219, 64, 248, 189, 221}, 104}, {{90, 214, 185, 128, 0, 254, 44, 73, 127, 23, 226, 40, 126, 42, 170, 236}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 103, 207, 38, 180, 39, 237, 171}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 137}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 89, 75}, 104}, {{90, 214, 185, 128, 0, 161, 213, 172, 157, 132, 120, 10, 122, 0, 9, 218}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 179, 91, 54, 161, 147, 228, 226, 12}, 104}, {{90, 214, 185, 128, 0, 84, 228, 146, 211, 139, 74, 151, 44, 225, 14, 85}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 164, 248, 4, 90, 180, 26, 1}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 229, 122, 184, 38, 188, 131, 153, 56, 119, 167}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 177, 212}, 104}, {{90, 214, 185, 128, 0, 76, 158, 185, 88, 148, 2, 189, 78, 5, 123, 109}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 251, 228}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 40, 25, 88, 94, 70, 69}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 217}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 39, 160, 239, 103, 23, 149, 139, 97}, 104}, {{90, 214, 185, 128, 0, 0, 0, 136, 40, 126, 9, 213, 20, 53, 248, 67}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 188, 160, 195, 187, 228}, 104}, {{90, 214, 185, 128, 68, 226, 194, 24, 92, 131, 45, 208, 49, 57, 64, 221}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 171}, 104}, {{90, 214, 185, 128, 0, 41, 100, 22, 136, 69, 227, 43, 66, 67, 216, 199}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 88, 170, 14, 33, 102}, 104}, {{90, 214, 185, 128, 0, 0, 0, 65, 68, 221, 117, 90, 180, 187, 158, 54}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 83, 200, 36, 193, 213, 236, 12}, 104}, {{90, 214, 185, 128, 0, 160, 70, 126, 108, 182, 175, 197, 214, 109, 12, 236}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 193, 23}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 148, 230}, 104}, {{90, 214, 185, 128, 241, 122, 9, 138, 154, 50, 152, 83, 77, 78, 41, 114}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 206, 159, 141, 135}, 104}, {{90, 214, 185, 128, 0, 215, 122, 103, 38, 172, 10, 138, 92, 154, 69, 120}, 104}, {{90, 214, 185, 128, 129, 23, 161, 72, 168, 125, 170, 69, 241, 206, 87, 80}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 101}, 104}, {{90, 214, 185, 128, 0, 0, 0, 57, 233, 73, 2, 30, 160, 77, 163, 179}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 104}, {{90, 214, 185, 128, 0, 62, 12, 55, 148, 247, 52, 36, 15, 206, 126, 31}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 198, 250, 98, 16, 168, 6, 114, 145, 123, 97}, 104}, {{90, 214, 185, 128, 0, 0, 143, 204, 246, 100, 4, 199, 0, 249, 126, 133}, 104}, {{90, 214, 185, 128, 0, 0, 18, 74, 123, 57, 97, 70, 188, 226, 43, 214}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 214, 8}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 216, 16, 161, 97}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 80, 103, 214, 240}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 110, 168, 205, 228, 16, 1, 231, 92}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 226, 199}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 126, 156, 105, 82, 246, 204}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 0, 181, 250, 253, 36, 32, 218, 217, 192, 172}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 164, 197, 101, 24}, 104}, {{90, 214, 185, 128, 0, 0, 184, 173, 218, 85, 141, 243, 173, 239, 83, 220}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 104}, {{90, 214, 185, 128, 0, 0, 200, 100, 182, 64, 85, 183, 71, 172, 21, 154}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 140, 212, 42, 254, 82, 31}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 231}, 104}, {{90, 214, 185, 128, 0, 0, 0, 3, 191, 242, 224, 195, 57, 6, 212, 242}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 158, 161, 158, 177, 197, 23}, 104}, {{90, 214, 185, 128, 0, 0, 206, 31, 171, 188, 238, 33, 81, 58, 108, 32}, 104}, {{90, 214, 185, 128, 0, 0, 113, 163, 228, 220, 191, 32, 121, 98, 129, 174}, 104}, {{90, 214, 185, 128, 115, 160, 230, 151, 0, 33, 87, 179, 1, 14, 80, 168}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 142, 4}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 218, 132, 230, 46, 67, 108, 157, 162, 64, 247}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 192, 20, 66, 80, 93}, 104}, {{90, 214, 185, 128, 0, 0, 72, 130, 187, 119, 54, 187, 47, 92, 237, 5}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 126}, 104}, {{90, 214, 185, 128, 0, 0, 5, 41, 159, 164, 51, 213, 124, 76, 249, 250}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{90, 214, 185, 128, 0, 0, 236, 29, 58, 231, 131, 32, 132, 210, 72, 158}, 104}, {{90, 214, 185, 128, 0, 0, 16, 192, 132, 9, 14, 6, 118, 252, 109, 89}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 166, 61, 190}, 104}, {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 104}, {{90, 214, 185, 128, 0, 0, 222, 213, 77, 113, 41, 141, 34, 60, 198, 60}, 104}, {{90, 214, 185, 128, 0, 0, 191, 160, 92, 166, 146, 9, 153, 37, 158, 179}, 104}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 255}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 181}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 169}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 206}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 80}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 125}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 207}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 188}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 14}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 76}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 206}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 244}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 201}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 47}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 64}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 44}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 117}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 60}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 53}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 180}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 207}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 155}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 250}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 70}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 177}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 216}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 142}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 163}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 2}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 250}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 116}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 244}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 137}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 54}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 33}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 229}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 245}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 23}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 14}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 50}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 75}, 113}, {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 137}, 113}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 73, 105}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 55, 192, 203, 193, 187}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 153, 160, 31, 76, 132}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 191}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 236, 131, 240}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 219, 154, 105, 169, 155}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 234, 28}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 120, 135, 178}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 186, 254}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 57, 238, 100}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 198, 156, 56, 8, 123}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 135}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 49, 239, 68, 73, 46}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 200, 241, 135, 62}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 80, 122, 242, 121}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 42, 171}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 150, 255}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 93, 230, 120, 35}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 45, 186, 142, 213}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 219}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 210, 218, 54}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 92, 216}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 100, 158, 148, 38}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 4, 187, 67}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 52, 234, 46, 187, 138}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 2}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 4, 58, 206}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 172, 61, 148}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 122, 3, 93}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 120, 127}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 54, 24, 137, 51, 51}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 94, 80, 142, 139}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 61, 56, 139}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 176, 28, 244, 253}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 133, 150, 47}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 241, 133, 33, 125, 72}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 176, 146, 169, 236, 110}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 222, 144, 82, 8}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 249}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 157, 103, 112, 49}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 123, 251, 173}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 20}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 25, 40, 160, 231}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 24, 58, 158, 74, 152}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 78, 47, 33, 115, 232}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 112, 206, 51, 49}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 34, 36}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 189, 140, 133, 224, 31}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 249, 215}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 111, 27, 239, 139}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 102, 5, 226, 144, 80}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 51, 197, 119}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 193, 67, 34}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 85, 100}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 96, 199, 132, 58, 86}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 63, 216, 190}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 136, 2, 249}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 23}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 103, 74}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 138}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 166}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 155, 3, 210}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 45, 179, 107, 73, 36}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 45, 216, 168, 24, 81}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 170, 195, 76, 241, 209}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 228, 69}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 160, 128, 76, 128}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 113, 49, 58, 124, 178}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 16, 210}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 125, 165, 56}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 34, 253, 171, 141, 145}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 15, 195, 163, 117, 207}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 44, 221, 114}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 159, 52}, 89}, {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 214, 140, 78, 113, 42}, 89}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 182}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 127}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 43}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 174}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 106}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 125}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 218}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 149}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 127}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 118}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 136}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 130}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 83}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 178}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 104}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 89}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 149}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 112}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 193}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 188}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 186}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 160}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 142}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 77}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 169}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 36}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 34}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 110}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 172}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 16}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 250}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 163}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 253}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 135}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 213}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 229}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 103}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 77}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 55}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 113}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 151}, {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 69}, 151}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 114, 88, 188}, 108}, {{225, 96, 0, 0, 0, 0, 0, 86, 118, 38, 88, 62, 47, 187, 202, 168}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 83, 210, 241, 233, 22, 183, 123, 89, 197, 111, 199, 31}, 108}, {{225, 96, 239, 10, 17, 7, 60, 92, 175, 224, 192, 20, 197, 222, 213, 76}, 108}, {{225, 96, 0, 0, 0, 0, 125, 207, 23, 9, 88, 72, 229, 126, 91, 107}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 39}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 139, 220, 100, 133, 112, 204, 226, 103}, 108}, {{225, 96, 0, 0, 172, 120, 200, 159, 210, 106, 202, 203, 219, 78, 225, 249}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 244, 7, 180, 150, 57, 239, 88}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 202, 28, 154, 125, 100, 246}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 122, 154, 116, 56, 164, 242, 176, 142}, 108}, {{225, 96, 0, 0, 0, 0, 0, 12, 204, 82, 14, 183, 35, 174, 240, 113}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 56, 252, 37, 234, 97, 184}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 17, 188, 218, 37, 38, 37, 33, 131}, 108}, {{225, 96, 0, 0, 0, 0, 0, 239, 47, 62, 174, 132, 252, 151, 174, 15}, 108}, {{225, 96, 0, 0, 0, 0, 0, 125, 116, 220, 189, 204, 67, 195, 154, 108}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 108}, {{225, 96, 0, 37, 212, 164, 46, 137, 250, 143, 103, 181, 252, 29, 89, 247}, 108}, {{225, 96, 46, 56, 27, 179, 87, 21, 58, 111, 80, 127, 43, 183, 153, 10}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 6, 42, 213, 216, 68, 9, 115, 158}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 240, 234, 158}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 252, 7, 83, 11, 21, 203, 139}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 16, 191}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 24, 223, 222, 47, 206, 118}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 25, 5, 227}, 108}, {{225, 96, 0, 0, 0, 8, 176, 152, 67, 97, 174, 131, 9, 179, 43, 41}, 108}, {{225, 96, 0, 0, 0, 145, 110, 67, 89, 144, 96, 135, 120, 146, 144, 131}, 108}, {{225, 96, 0, 0, 0, 0, 0, 115, 84, 86, 29, 62, 43, 245, 39, 255}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 232, 73}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 54, 212}, 108}, {{225, 96, 0, 0, 0, 58, 143, 208, 91, 255, 204, 31, 253, 148, 169, 23}, 108}, {{225, 96, 0, 0, 0, 240, 112, 150, 249, 125, 34, 13, 152, 214, 113, 124}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 108}, {{225, 96, 0, 9, 144, 112, 111, 105, 168, 161, 47, 124, 126, 187, 113, 150}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 115, 207, 4, 60, 219, 236, 62}, 108}, {{225, 96, 0, 0, 0, 0, 0, 41, 105, 193, 54, 122, 225, 144, 122, 183}, 108}, {{225, 96, 115, 139, 240, 166, 251, 206, 191, 96, 115, 120, 211, 51, 121, 148}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 56, 132, 125}, 108}, {{225, 96, 0, 36, 61, 48, 173, 155, 31, 66, 52, 6, 255, 87, 169, 176}, 108}, {{225, 96, 0, 0, 0, 0, 0, 33, 55, 155, 55, 210, 218, 46, 202, 120}, 108}, {{225, 96, 0, 0, 0, 0, 0, 131, 171, 114, 252, 1, 226, 69, 235, 249}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 61}, 108}, {{225, 96, 0, 0, 0, 0, 116, 11, 77, 229, 69, 83, 149, 164, 24, 1}, 108}, {{225, 96, 0, 0, 125, 78, 166, 126, 57, 23, 95, 14, 99, 169, 18, 219}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 105}, 108}, {{225, 96, 0, 0, 0, 119, 148, 6, 101, 188, 193, 176, 98, 160, 82, 188}, 108}, {{225, 96, 0, 6, 38, 51, 176, 250, 115, 196, 88, 248, 52, 227, 97, 63}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 89, 24, 134}, 108}, {{225, 96, 0, 186, 32, 137, 128, 242, 143, 118, 255, 61, 127, 147, 41, 6}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 60, 221, 144}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 174, 113, 221}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 222, 51, 190, 207, 17, 155, 12}, 108}, {{225, 96, 97, 222, 76, 196, 162, 197, 175, 18, 133, 201, 64, 219, 13, 55}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 173, 148}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 152}, 108}, {{225, 96, 0, 0, 0, 207, 189, 193, 193, 158, 27, 60, 170, 220, 129, 56}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 25, 35}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 172, 67, 218, 202, 124, 190, 250, 115}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 221}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 194, 62, 62}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 12, 113, 51, 149}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 19, 253}, 108}, {{225, 96, 0, 0, 0, 0, 0, 249, 25, 124, 70, 114, 204, 208, 19, 200}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 126, 97, 73, 72, 50, 237}, 108}, {{225, 96, 0, 0, 209, 123, 143, 182, 163, 210, 63, 69, 228, 144, 41, 163}, 108}, {{225, 96, 0, 171, 203, 240, 145, 17, 122, 236, 226, 96, 198, 132, 95, 110}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 164, 179, 185, 251, 226, 141}, 108}, {{225, 96, 0, 0, 0, 0, 139, 160, 97, 17, 85, 55, 146, 75, 193, 95}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 40, 200, 200}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 172}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 56, 61, 95, 12, 97, 229}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 108}, {{225, 96, 132, 110, 236, 77, 20, 232, 163, 89, 224, 188, 24, 204, 148, 112}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 108}, {{225, 96, 14, 167, 95, 123, 93, 168, 70, 244, 118, 178, 158, 37, 216, 192}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 108}, {{225, 96, 207, 110, 31, 243, 204, 129, 16, 67, 98, 32, 11, 164, 165, 42}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 108}, {{225, 96, 0, 0, 0, 173, 210, 45, 188, 98, 63, 181, 247, 218, 87, 99}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 103, 249, 4, 101}, 108}, {{225, 96, 0, 14, 179, 86, 51, 92, 39, 88, 191, 82, 217, 64, 68, 44}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 161, 60, 127}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 124, 29, 125, 28, 130, 22, 158, 94}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 240, 124, 54}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 101, 18, 82, 56}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 147, 201}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 206, 17}, 108}, {{225, 96, 0, 0, 0, 84, 151, 42, 49, 18, 50, 126, 246, 23, 128, 109}, 108}, {{225, 96, 0, 0, 0, 96, 134, 116, 188, 250, 178, 106, 249, 41, 13, 184}, 108}, {{136, 0, 0, 0, 0, 0, 0, 0, 91, 39, 51, 15, 229, 169, 5, 37}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 244, 138, 61, 254}, 224}, {{136, 0, 0, 0, 0, 153, 159, 180, 131, 190, 34, 166, 186, 217, 238, 149}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 230, 148, 178, 114, 44}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 125, 209}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 253, 103, 81, 107, 197, 15, 169, 49}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 60, 168, 42, 192, 43}, 224}, {{136, 0, 0, 78, 142, 242, 168, 70, 28, 137, 250, 74, 136, 32, 7, 168}, 224}, {{136, 0, 0, 0, 0, 191, 44, 188, 27, 187, 187, 35, 130, 157, 60, 124}, 224}, {{136, 0, 0, 0, 0, 0, 89, 87, 44, 224, 203, 32, 29, 103, 11, 125}, 224}, {{136, 0, 0, 0, 0, 66, 144, 237, 26, 117, 171, 60, 145, 14, 195, 57}, 224}, {{136, 0, 0, 0, 0, 244, 157, 85, 117, 20, 82, 173, 36, 76, 238, 218}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 231, 138, 136, 123, 23, 127, 240}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 16, 40, 151}, 224}, {{136, 0, 0, 63, 59, 157, 174, 55, 82, 205, 214, 162, 160, 221, 77, 77}, 224}, {{136, 0, 0, 36, 189, 67, 204, 191, 177, 236, 21, 30, 22, 233, 199, 148}, 224}, {{136, 0, 0, 0, 0, 119, 235, 10, 21, 2, 244, 61, 88, 215, 248, 46}, 224}, {{136, 0, 0, 0, 46, 209, 156, 16, 103, 77, 136, 29, 220, 85, 48, 210}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 194}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 47, 37, 195, 239, 120, 215, 130, 162, 245, 55, 105}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 224}, {{136, 0, 0, 57, 68, 223, 147, 29, 196, 7, 9, 45, 210, 179, 176, 6}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 36, 107, 69, 128, 18, 221, 97}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 201}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 113, 163, 103, 179, 195, 99, 129, 72}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 45, 240, 177, 175, 86, 63, 214, 151}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 224}, {{136, 0, 177, 137, 255, 180, 231, 247, 217, 185, 184, 56, 175, 178, 143, 98}, 224}, {{136, 0, 0, 0, 2, 34, 7, 10, 214, 73, 229, 63, 212, 151, 65, 216}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 229, 68, 149, 56, 155, 162, 160, 1}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 121, 242}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 84, 45}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 88, 2, 120, 185}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 247, 226, 143, 50, 237, 201, 146, 208, 184, 103, 11, 226, 38, 125}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 224}, {{136, 0, 0, 0, 0, 160, 162, 144, 64, 53, 14, 71, 177, 248, 18, 214}, 224}, {{136, 0, 0, 0, 113, 29, 244, 132, 135, 117, 136, 72, 94, 207, 73, 181}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 247, 212, 250}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 176, 91, 97, 37, 77, 201, 154, 65}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 226}, 224}, {{136, 0, 0, 0, 171, 101, 23, 71, 254, 138, 142, 73, 85, 172, 145, 48}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 62, 143, 180, 173}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 5, 63, 159, 252, 181, 122, 17}, 224}, {{136, 0, 0, 0, 0, 0, 0, 77, 174, 163, 129, 51, 215, 35, 211, 104}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 255}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 247}, 224}, {{136, 0, 0, 0, 0, 0, 38, 233, 102, 234, 43, 94, 139, 100, 211, 174}, 224}, {{136, 0, 0, 167, 173, 148, 157, 16, 114, 193, 105, 24, 121, 124, 247, 47}, 224}, {{136, 0, 201, 130, 90, 208, 48, 120, 62, 120, 176, 249, 53, 176, 7, 193}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 100, 81, 214, 134, 224, 247, 229, 195}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 161, 34, 98, 113, 161, 233, 221}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 100}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 66, 129, 178}, 224}, {{136, 0, 0, 247, 37, 129, 7, 9, 255, 244, 40, 177, 99, 8, 186, 161}, 224}, {{136, 0, 0, 0, 0, 203, 46, 214, 94, 157, 116, 225, 31, 6, 157, 64}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 10, 97, 236, 127, 38, 232, 235}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 94, 75, 213, 85, 187, 73, 95}, 224}, {{136, 0, 0, 0, 0, 58, 188, 21, 49, 214, 47, 86, 157, 76, 101, 144}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 73, 137}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 226, 161, 151, 234, 161, 133, 31, 184, 221}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 213, 226, 0, 21, 255, 223, 38, 216}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 50, 100, 83, 142, 84, 5, 238, 34}, 224}, {{136, 0, 0, 0, 0, 0, 0, 75, 223, 33, 233, 12, 147, 50, 210, 145}, 224}, {{136, 0, 0, 0, 0, 165, 25, 145, 91, 144, 182, 237, 69, 21, 59, 199}, 224}, {{136, 0, 0, 152, 219, 100, 192, 11, 202, 90, 161, 14, 22, 60, 160, 161}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 31, 175, 168, 88, 181, 104, 143}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 121, 76, 103, 7, 207}, 224}, {{136, 0, 120, 218, 86, 184, 36, 155, 110, 190, 231, 144, 106, 34, 119, 208}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 208}, 224}, {{136, 0, 0, 175, 45, 104, 217, 158, 84, 248, 24, 121, 146, 198, 97, 71}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 158, 208, 225, 250}, 224}, {{136, 0, 0, 0, 0, 0, 0, 76, 215, 71, 69, 113, 252, 4, 93, 33}, 224}, {{136, 0, 0, 0, 0, 155, 188, 148, 13, 247, 169, 176, 156, 228, 149, 172}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 165, 117, 75}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 211, 155, 223}, 224}, {{136, 0, 0, 0, 0, 0, 132, 46, 225, 184, 212, 165, 186, 238, 176, 62}, 224}, {{136, 0, 0, 208, 80, 217, 58, 202, 83, 37, 202, 102, 191, 217, 98, 106}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 4, 99}, 224}, {{136, 0, 0, 0, 122, 31, 1, 39, 246, 161, 202, 227, 125, 149, 105, 57}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 248, 39, 254, 239, 15}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 207, 111, 115, 67, 244, 80, 36}, 224}, {{136, 0, 0, 0, 0, 0, 101, 51, 55, 11, 7, 238, 86, 76, 188, 221}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 97, 186, 74, 4, 149, 104, 198}, 224}, {{136, 0, 78, 21, 233, 94, 143, 239, 47, 61, 172, 80, 76, 109, 122, 155}, 224}, {{136, 0, 0, 0, 0, 0, 0, 243, 101, 236, 5, 5, 47, 105, 219, 228}, 224}, {{136, 0, 0, 0, 0, 0, 0, 70, 173, 212, 166, 191, 178, 130, 103, 37}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 149, 12, 249, 131, 131, 84, 177, 187}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 248, 142, 209, 110, 229, 66, 184}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 237, 118, 68, 58, 199}, 224}, {{136, 38, 35, 218, 136, 15, 137, 170, 56, 218, 86, 49, 16, 158, 114, 219}, 224}, {{250, 128, 0, 0, 0, 0, 40, 87, 237, 227, 167, 139, 9, 38, 42, 55}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 146}, {{250, 128, 78, 90, 214, 208, 20, 211, 26, 166, 51, 253, 223, 159, 255, 3}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 237, 232}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 100, 154, 199, 36, 113, 214, 57, 72, 99, 70, 203, 20, 191, 128}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 64, 59, 44, 56, 7, 109, 107}, 146}, {{250, 128, 0, 0, 205, 179, 148, 245, 248, 230, 152, 66, 211, 82, 72, 35}, 146}, {{250, 128, 0, 0, 0, 0, 0, 126, 227, 105, 186, 64, 82, 135, 107, 46}, 146}, {{250, 128, 0, 0, 232, 232, 101, 76, 90, 31, 72, 91, 203, 123, 33, 105}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 90, 40, 66, 47, 93, 7, 160}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 20, 12}, 146}, {{250, 128, 0, 0, 0, 0, 255, 155, 170, 132, 239, 125, 185, 120, 129, 148}, 146}, {{250, 128, 0, 133, 93, 9, 194, 162, 1, 225, 13, 13, 248, 179, 203, 72}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 66, 42, 195, 114, 36, 204}, 146}, {{250, 128, 103, 201, 231, 191, 0, 203, 204, 24, 69, 167, 94, 129, 96, 155}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 64, 25, 49, 212}, 146}, {{250, 128, 0, 0, 0, 122, 190, 118, 83, 224, 80, 17, 15, 137, 186, 73}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 21, 200, 143, 1, 192, 50}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 146}, {{250, 128, 198, 232, 169, 71, 128, 231, 175, 151, 69, 198, 52, 236, 240, 38}, 146}, {{250, 128, 0, 0, 39, 214, 59, 197, 45, 69, 209, 240, 3, 75, 53, 82}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 166, 165, 38, 120, 118, 232, 162, 254, 146, 244, 240, 168, 177}, 146}, {{250, 128, 0, 0, 0, 0, 221, 121, 238, 96, 27, 11, 84, 231, 3, 174}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 146}, {{250, 128, 0, 0, 242, 208, 175, 113, 232, 32, 60, 132, 165, 30, 145, 198}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 254, 179, 120, 53, 5, 178, 251, 160}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 167, 30}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 136, 80, 21}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 128, 20}, 146}, {{250, 128, 0, 0, 168, 15, 55, 186, 118, 254, 133, 53, 2, 148, 79, 149}, 146}, {{250, 128, 0, 0, 0, 51, 165, 248, 235, 3, 173, 219, 248, 102, 26, 247}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 146}, {{250, 128, 0, 0, 0, 0, 242, 12, 116, 185, 35, 149, 186, 37, 220, 249}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 3, 123, 6, 113, 99, 231}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 49, 221, 20, 148, 216, 242}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 16, 145, 123, 188, 99, 150, 81}, 146}, {{250, 128, 0, 0, 0, 0, 230, 44, 167, 126, 148, 148, 82, 106, 62, 38}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 231, 14, 102, 135, 25, 227, 24}, 146}, {{250, 128, 0, 0, 10, 214, 184, 61, 240, 85, 81, 148, 209, 213, 67, 39}, 146}, {{250, 128, 0, 0, 0, 0, 211, 70, 34, 154, 99, 241, 85, 145, 171, 201}, 146}, {{250, 128, 182, 85, 197, 212, 118, 229, 12, 183, 174, 213, 23, 197, 7, 186}, 146}, {{250, 128, 0, 167, 190, 243, 173, 129, 106, 91, 0, 244, 31, 188, 153, 38}, 146}, {{250, 128, 0, 0, 109, 160, 183, 219, 241, 17, 166, 46, 113, 27, 137, 38}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 162, 78}, 146}, {{250, 128, 0, 0, 0, 0, 0, 91, 76, 199, 18, 193, 28, 226, 233, 41}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 182}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 196, 49, 47, 188, 242, 81, 252, 102}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 210, 189, 127, 80, 228, 19, 136, 235}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 54}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 51, 57, 91}, 146}, {{250, 128, 0, 0, 41, 8, 151, 163, 20, 144, 82, 81, 144, 100, 212, 35}, 146}, {{250, 128, 0, 0, 0, 0, 17, 191, 150, 208, 191, 19, 119, 41, 122, 218}, 146}, {{250, 128, 0, 0, 0, 0, 0, 41, 115, 59, 74, 112, 12, 150, 157, 122}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 124, 1, 136, 162, 140, 211, 201}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 122, 14, 191, 11}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 224, 101, 156, 45}, 146}, {{250, 128, 0, 0, 0, 225, 122, 213, 136, 240, 3, 130, 184, 13, 7, 254}, 146}, {{250, 128, 0, 0, 0, 230, 18, 204, 158, 143, 16, 160, 233, 127, 58, 122}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 244, 53, 8, 39}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 197, 40, 87, 202, 57, 109, 77}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 25, 49, 45, 139}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 101}, 146}, {{250, 128, 0, 0, 0, 0, 0, 96, 241, 32, 178, 203, 200, 106, 190, 105}, 146}, {{250, 128, 0, 180, 73, 249, 172, 122, 176, 128, 175, 98, 54, 17, 30, 193}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 206, 249}, 146}, {{250, 128, 0, 144, 211, 153, 53, 231, 195, 79, 142, 115, 138, 199, 132, 222}, 146}, {{250, 128, 0, 0, 0, 82, 65, 179, 249, 149, 60, 136, 129, 134, 23, 200}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 15, 242, 232, 169, 4, 6, 204, 121}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 97, 222, 3}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 184, 210}, 146}, {{250, 128, 0, 0, 157, 188, 207, 220, 114, 193, 130, 97, 208, 201, 4, 147}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 121, 39, 138}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 85, 115, 100, 31, 112, 79, 156}, 146}, {{250, 128, 0, 0, 0, 0, 44, 250, 85, 86, 141, 87, 96, 251, 24, 26}, 146}, {{250, 128, 0, 0, 0, 0, 190, 137, 169, 69, 86, 187, 26, 15, 186, 124}, 146}, {{250, 128, 0, 0, 0, 0, 0, 116, 174, 47, 49, 63, 18, 107, 173, 80}, 146}, {{250, 128, 0, 26, 111, 189, 74, 186, 189, 210, 58, 1, 130, 84, 117, 135}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 251, 39, 225}, 146}, {{250, 128, 0, 0, 232, 169, 215, 0, 24, 47, 188, 23, 152, 197, 34, 209}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 230, 40, 165, 189, 171, 74, 222}, 146}, {{250, 128, 0, 0, 0, 0, 198, 64, 55, 39, 195, 117, 155, 226, 194, 165}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 77, 211, 184, 185, 242, 1}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 25, 205, 213, 76, 16, 143}, 146}, {{250, 128, 0, 0, 0, 0, 79, 19, 6, 117, 156, 93, 170, 171, 234, 83}, 146}, {{250, 128, 40, 107, 111, 97, 183, 11, 130, 207, 55, 235, 45, 33, 65, 126}, 146}, {{250, 128, 0, 0, 0, 0, 0, 214, 253, 164, 53, 0, 107, 170, 118, 18}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 96, 30, 97, 14, 163, 131, 38, 100}, 146}, {{250, 128, 0, 0, 0, 0, 0, 136, 59, 254, 199, 184, 129, 46, 102, 230}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 225}, 146}, {{72, 168, 0, 0, 0, 0, 0, 0, 125, 24, 199, 174, 39, 41, 213, 39}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 45, 64, 229}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 146}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 210}, 173}, {{72, 168, 0, 0, 55, 28, 218, 189, 205, 234, 131, 108, 194, 253, 227, 251}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 12, 100, 245, 208}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 167, 105}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 67, 145, 251, 233, 123, 85, 251, 29, 243, 95, 172, 182}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 68, 155, 202, 0, 104, 239, 40}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 216, 218, 82, 70, 92, 142, 238, 198}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 41, 78}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 73, 9, 135, 85, 150, 125, 191, 26, 118, 136, 46, 14, 217}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 91, 177, 151}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 111, 175, 62, 17, 38, 76, 55, 174}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 201, 3, 93}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 132, 234, 33}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 204, 91, 190}, 173}, {{72, 168, 0, 76, 63, 188, 13, 37, 129, 49, 158, 213, 220, 82, 59, 86}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 220, 190, 82, 171, 215, 52, 129, 218, 177, 239}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 57, 112, 136, 128}, 173}, {{72, 168, 0, 200, 204, 118, 174, 249, 217, 145, 200, 139, 35, 40, 161, 44}, 173}, {{72, 168, 0, 0, 0, 0, 247, 119, 205, 168, 150, 35, 59, 84, 159, 23}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 8}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 173}, {{72, 168, 0, 0, 196, 13, 178, 108, 226, 227, 14, 104, 210, 27, 184, 199}, 173}, {{72, 168, 0, 0, 0, 0, 54, 79, 232, 9, 192, 113, 190, 92, 102, 164}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 206, 179, 129}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 117, 32, 60, 56, 141, 248}, 173}, {{72, 168, 0, 0, 0, 0, 100, 237, 206, 187, 214, 114, 190, 160, 2, 145}, 173}, {{72, 168, 0, 150, 153, 155, 171, 130, 84, 41, 143, 253, 41, 223, 154, 199}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 6, 206}, 173}, {{72, 168, 0, 0, 0, 0, 0, 76, 92, 19, 38, 228, 129, 243, 217, 61}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 145, 59, 243, 173, 236, 26, 3, 132}, 173}, {{72, 168, 0, 0, 0, 0, 0, 31, 160, 128, 39, 31, 200, 97, 39, 183}, 173}, {{72, 168, 0, 0, 45, 180, 121, 177, 124, 237, 249, 95, 108, 143, 178, 27}, 173}, {{72, 168, 0, 183, 184, 156, 28, 212, 64, 111, 124, 247, 168, 79, 178, 101}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 224, 72, 111, 222, 211, 248, 69}, 173}, {{72, 168, 0, 0, 0, 0, 63, 64, 9, 96, 19, 235, 168, 21, 34, 10}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 38, 128, 140}, 173}, {{72, 168, 0, 0, 0, 0, 101, 179, 163, 148, 148, 37, 163, 36, 147, 134}, 173}, {{72, 168, 0, 0, 0, 0, 0, 109, 129, 195, 78, 244, 22, 171, 70, 152}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 253, 160}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 173}, {{72, 168, 0, 0, 166, 8, 40, 21, 91, 214, 195, 113, 152, 157, 251, 144}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 174, 22, 44, 77, 28, 121, 1, 106}, 173}, {{72, 168, 0, 109, 248, 193, 255, 252, 227, 154, 218, 172, 26, 75, 42, 142}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 193, 15, 159}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 185}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 133, 232}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 173, 22, 242, 173}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 41}, 173}, {{72, 168, 0, 0, 79, 77, 211, 244, 188, 194, 64, 16, 43, 219, 226, 247}, 173}, {{72, 168, 0, 215, 110, 46, 45, 19, 227, 5, 126, 144, 153, 146, 177, 232}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 37}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 160, 208, 140, 178, 130, 168, 130, 43}, 173}, {{72, 168, 0, 0, 0, 251, 179, 96, 114, 49, 254, 248, 18, 186, 139, 225}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 11, 147, 196, 123, 118, 76, 8}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 249, 94, 57}, 173}, {{72, 168, 0, 0, 0, 221, 200, 114, 122, 233, 229, 18, 165, 55, 162, 217}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 240, 45, 231}, 173}, {{72, 168, 55, 232, 93, 125, 177, 62, 183, 54, 195, 189, 92, 208, 231, 226}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 186}, 173}, {{72, 168, 0, 0, 0, 0, 0, 1, 166, 145, 241, 30, 122, 132, 208, 4}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 109, 4, 113, 154, 110, 6, 65, 37}, 173}, {{72, 168, 0, 0, 0, 102, 80, 166, 189, 171, 152, 52, 148, 120, 61, 217}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 184, 189, 101, 105, 105, 225, 185}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 160, 240}, 173}, {{72, 168, 0, 0, 0, 254, 141, 185, 145, 165, 223, 254, 96, 161, 106, 204}, 173}, {{72, 168, 0, 194, 21, 192, 39, 150, 139, 197, 175, 75, 135, 171, 73, 178}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 26}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 124, 3, 157, 86, 49, 129}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 69, 77, 88, 220, 35, 236}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 47}, 173}, {{72, 168, 56, 73, 165, 96, 101, 238, 234, 134, 228, 217, 40, 28, 118, 181}, 173}, {{72, 168, 0, 0, 10, 254, 100, 153, 225, 161, 39, 23, 214, 81, 244, 62}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 79, 28, 98, 107, 248, 47}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 169, 51, 190, 9, 35, 33, 220, 145}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 111, 155, 243, 240, 244, 33, 126, 141}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 213, 200, 97, 37, 235, 146, 154, 132}, 173}, {{72, 168, 0, 0, 0, 0, 203, 59, 118, 239, 181, 5, 15, 80, 40, 217}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 108}, 173}, {{72, 168, 0, 0, 168, 169, 50, 90, 166, 64, 215, 136, 99, 54, 221, 116}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 100, 219, 113, 65, 188, 179}, 173}, {{72, 168, 0, 226, 81, 36, 44, 138, 161, 7, 253, 242, 129, 113, 83, 150}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 17, 103}, 173}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 184}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 44, 120, 29, 46}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 138}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 253, 221}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 123, 230, 65}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 7, 144}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 176, 233}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 28}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 14, 81, 118, 85}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 138, 105}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 27}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 171, 161, 42}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 16, 18}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 201, 109}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 30}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 226, 164}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 140, 184, 70}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 240}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 32, 209, 91}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 32, 111, 164, 76}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 171, 2}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 149, 89, 237, 22}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 164}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 3, 255, 66}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 35, 35, 254}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 65, 195, 95, 150}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 124, 244, 126}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 44}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 19, 229}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 84, 6}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 253}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 138, 5}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 205, 194, 201}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 122, 38}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 13, 61}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 205, 155, 69, 207}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 93, 21}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 193, 218, 83}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 20, 135}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 84}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 31, 161, 248}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 204}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 239}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 10, 90, 5}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 178, 244}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 19}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 123, 184}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 39, 237, 154}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 113, 101, 163}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 158}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 241, 218, 224, 130}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 223}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 45}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 77}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 34, 252, 56}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 213, 80, 201}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 105}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 130, 106}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 198}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 100, 176, 222}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 223, 245, 232}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 70, 8}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 33}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 209, 237, 27, 7}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 176, 130, 105, 235}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 180, 0, 233}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 168, 136, 252}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 30, 130}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 152, 225}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 219, 176, 86}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 177, 128, 140, 123}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 25, 235}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 167, 161}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 176, 65, 162, 61}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 124}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 59}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 107, 132}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 102}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 78, 139}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 88}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 176}, {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 94, 63, 59}, 176}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 23}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 45}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 113}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 148}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 59}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 30}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 181}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 84}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 95, 175, 90, 36, 72, 195}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 196, 150, 244}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 99, 15, 213, 73, 44}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 104}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 36, 135, 214, 147}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 181, 61, 241, 56, 101, 72}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 168, 34, 197, 63, 8, 155}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 184, 24, 21, 179}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 33, 8, 153, 187}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 5, 57, 190}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 148, 128, 140, 186}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 157, 82}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 198}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 210}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 63, 65, 27, 176}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 57, 216}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 227, 95, 103, 112}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 118, 250, 214, 235}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 152, 230, 147, 12}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 197, 30, 198}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 153, 237, 186, 253, 243}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 238, 253, 236, 150}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 52}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 37, 104, 137, 103, 73}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 122, 23, 166, 233, 212, 247}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 6, 241, 44, 56, 150, 42}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 68, 213, 233}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 102, 61, 45, 181}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 241, 49}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 235, 28}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 112, 67}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 186}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 198, 89, 131, 24}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 232, 17}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 226, 80}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 32}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 60, 140, 243, 179}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 24, 180}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 190, 19, 21, 9}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 100}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 186, 202, 92, 30}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 177, 156}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 155, 106, 198}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 4, 28, 39, 7, 212}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 43, 225, 45}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 183, 136, 113, 156}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 208, 153, 162, 26, 86}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 12, 229}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 149}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 156, 192, 196, 76, 60}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 141, 129, 16, 51, 120}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 183, 88, 242, 240}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 170, 227, 3, 88, 9}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 14, 99, 255}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 138, 163, 49, 154, 96}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 151}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 97, 220, 14}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 32, 185, 136}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 150, 210, 63}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 123, 62}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 142, 245, 83, 216, 108}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 246, 163}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 125, 83}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 136, 30}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 243, 23, 200}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 29, 217, 246}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 228, 201, 232, 201}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 116, 211, 208, 74}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 187, 82}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 214}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 253, 194}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 237}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 50}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 15, 25, 104, 157}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 105, 202, 32, 52}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 104}, {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 93, 189, 195}, 104}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 87, 56, 87, 189, 92, 208, 143}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 215, 74, 248, 160, 174, 43}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 37, 97, 55, 129, 35}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 249, 168, 85, 226}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 72, 92}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 189, 143, 204, 91, 40, 213, 175, 161}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 167, 230, 166, 45, 111, 100, 95}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 144, 98, 112, 90}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 9, 27, 203, 11, 157, 1, 48}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 75, 10, 209}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 15, 72, 223}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 65, 118, 145, 71, 144, 126}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 196, 56, 38, 236}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 129, 76, 25, 215, 32, 227, 5}, 236}, {{247, 202, 176, 76, 69, 40, 0, 252, 215, 218, 94, 134, 135, 71, 67, 233}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 85, 94, 113, 25, 240, 76, 125, 89}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 236}, {{247, 202, 176, 76, 69, 40, 0, 71, 12, 47, 252, 188, 113, 42, 111, 231}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 193, 113, 112, 13, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 119, 244, 11}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 148, 241, 37, 185, 98, 15, 253, 117}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 6, 79, 20, 184, 35, 159, 127}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 160, 108, 159, 68, 162, 103, 84, 255}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 53, 211, 84, 208, 7, 36, 50}, 236}, {{247, 202, 176, 76, 69, 40, 0, 218, 121, 15, 44, 139, 229, 64, 3, 218}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 27, 170, 205, 64}, 236}, {{247, 202, 176, 76, 69, 40, 0, 152, 226, 216, 136, 122, 23, 61, 93, 108}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 44, 202, 203, 173, 249, 192, 126}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 44, 208}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 88, 250, 6, 20, 63}, 236}, {{247, 202, 176, 76, 69, 40, 0, 70, 27, 203, 124, 86, 81, 84, 69, 51}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 76, 199, 2, 78}, 236}, {{247, 202, 176, 76, 69, 40, 0, 147, 124, 192, 80, 159, 132, 209, 181, 8}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 251, 135, 85, 93, 138}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 164, 104, 155, 54, 110, 117, 181, 113}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 165, 81}, 236}, {{247, 202, 176, 76, 69, 40, 0, 126, 172, 170, 202, 179, 88, 16, 163, 157}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 140, 43, 106, 44, 126, 196, 215, 17, 193}, 236}, {{247, 202, 176, 76, 69, 40, 0, 32, 176, 248, 135, 198, 182, 61, 59, 159}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 226, 60, 144, 32, 101, 98, 183, 210}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 10, 232, 29, 89}, 236}, {{247, 202, 176, 76, 69, 40, 0, 151, 117, 214, 122, 233, 225, 1, 92, 224}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 237, 126, 215}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 14, 217, 90, 116, 200}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 194, 40, 124}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 197, 196, 105, 213, 192}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 115, 208, 132, 95, 173, 46, 129, 48}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 193, 166, 137, 134, 159}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 202, 4, 58, 248, 153}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 236}, {{247, 202, 176, 76, 69, 40, 0, 92, 204, 224, 24, 15, 144, 88, 55, 55}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 248, 12}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 53, 243, 230, 61, 187, 95, 225}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 127, 55, 2, 36, 93, 76}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 227, 216, 55, 203, 38}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 211, 105, 61, 224, 118, 88}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 245, 240, 177, 251, 33, 214}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 55, 170, 197, 16}, 236}, {{247, 202, 176, 76, 69, 40, 0, 159, 40, 189, 225, 20, 23, 20, 153, 236}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 60, 191, 85, 146, 197}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 123, 221, 90}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 131, 49, 227, 220}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 63, 230, 163, 55, 53}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 170, 29, 100, 18, 168, 15, 129, 213}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 10, 113, 232, 163, 193, 119}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 67, 137, 251, 84, 230}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 164, 81, 127, 215, 198, 170, 189, 53}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 36, 62, 98}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 246, 253, 163, 71, 4, 126, 37}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 241, 147, 80, 126, 35}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 255, 15}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 91, 181, 44, 76}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 151, 250, 126, 183, 156, 202, 46}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 236, 134, 40, 87, 198, 42}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 164, 229, 198, 235, 233, 39, 4, 195}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 152, 147, 205, 74, 236}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 198, 177, 87, 35}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 98, 146, 81}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 128, 57, 115, 185, 25, 193}, 236}, {{247, 202, 176, 76, 69, 40, 0, 235, 167, 235, 138, 187, 220, 25, 81, 36}, 236}, {{247, 202, 176, 76, 69, 40, 0, 0, 0, 231, 215, 166, 88, 27, 14, 55}, 236}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 86}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 156}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 124}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 145}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 78}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 49}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 195}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 138}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 165}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 76}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 17}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 103}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 72}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 53}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 99}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 59}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 157}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 120}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 104}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 64}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 109}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 229}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 161}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 126}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 6}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 220}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 153}, {{62, 192, 160, 24, 235, 189, 233, 137, 34, 20, 38, 148, 229, 171, 156, 138}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 92, 118, 17, 5}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 91, 185, 168}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 204, 203, 223, 181}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 17}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 151, 200, 116}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 220, 240, 76, 145}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 147, 87}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 107, 160, 29, 242, 23, 50, 253}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 190}, {{62, 192, 0, 0, 0, 0, 0, 172, 114, 223, 114, 146, 46, 240, 3, 85}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 210, 225, 242}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 120, 94}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 99, 224, 189}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 92, 145, 80, 252, 35, 47}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 83, 163, 214, 40, 102, 199}, 190}, {{62, 192, 0, 0, 0, 123, 77, 24, 144, 64, 4, 176, 87, 87, 72, 168}, 190}, {{62, 192, 0, 107, 80, 221, 21, 253, 116, 253, 223, 91, 187, 196, 157, 90}, 190}, {{62, 192, 0, 0, 175, 103, 140, 103, 45, 218, 146, 54, 218, 58, 180, 48}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 65, 82, 72, 85, 39, 42, 242, 130}, 190}, {{62, 192, 0, 0, 0, 205, 85, 81, 124, 85, 52, 86, 48, 161, 17, 212}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 174, 7, 104, 123, 153, 127, 85, 244}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 222, 188, 205}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 2, 90}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 54, 121, 235, 206, 118, 254}, 190}, {{62, 192, 0, 0, 0, 0, 0, 112, 184, 254, 119, 96, 30, 128, 203, 198}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 219, 8, 216, 115, 1, 126, 148, 234}, 190}, {{62, 192, 57, 232, 18, 215, 217, 109, 245, 158, 244, 210, 191, 216, 175, 249}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 211, 48}, 190}, {{62, 192, 0, 0, 0, 0, 175, 185, 70, 129, 157, 12, 121, 63, 120, 141}, 190}, {{62, 192, 0, 0, 0, 0, 151, 156, 249, 242, 67, 236, 204, 19, 20, 112}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 100, 181, 252, 13, 15, 190, 241}, 190}, {{62, 192, 0, 154, 2, 5, 51, 122, 234, 19, 88, 131, 41, 67, 26, 127}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 190}, {{62, 192, 0, 0, 0, 73, 12, 139, 61, 215, 126, 11, 39, 30, 14, 212}, 190}, {{62, 192, 0, 0, 0, 167, 230, 168, 62, 148, 10, 156, 233, 212, 191, 135}, 190}, {{62, 192, 0, 0, 0, 0, 0, 99, 42, 254, 208, 144, 38, 50, 135, 34}, 190}, {{62, 192, 0, 0, 61, 242, 30, 204, 202, 107, 178, 48, 9, 158, 171, 113}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 136, 23, 153, 148, 174, 14, 67}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 147, 229, 181, 14, 35, 120}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 124, 234, 113, 158}, 190}, {{62, 192, 0, 0, 0, 0, 157, 152, 109, 114, 112, 181, 205, 142, 20, 90}, 190}, {{62, 192, 0, 0, 75, 24, 90, 57, 68, 177, 141, 138, 223, 247, 153, 57}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 207, 126, 11, 14, 165, 172, 102}, 190}, {{62, 192, 0, 0, 0, 0, 0, 120, 241, 223, 1, 179, 116, 216, 149, 190}, 190}, {{62, 192, 172, 68, 18, 157, 227, 172, 78, 115, 29, 248, 122, 62, 5, 86}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 27, 56, 92, 9, 89, 59}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 183}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 196, 119, 29, 15, 247, 94, 81}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 185, 109, 141}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 190}, {{62, 192, 0, 0, 0, 0, 0, 77, 108, 120, 95, 9, 186, 18, 98, 118}, 190}, {{62, 192, 0, 0, 0, 0, 0, 213, 185, 240, 137, 234, 143, 174, 164, 66}, 190}, {{62, 192, 0, 127, 0, 133, 55, 126, 95, 149, 200, 94, 222, 14, 221, 42}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 206, 73, 197, 104, 164, 109}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 101, 8, 99, 106, 127, 100, 216, 220}, 190}, {{62, 192, 0, 0, 0, 0, 166, 201, 250, 9, 128, 91, 188, 161, 47, 83}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 145, 175, 217, 73, 45, 240, 208}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 190}, {{62, 192, 0, 0, 151, 248, 48, 232, 17, 207, 51, 128, 241, 0, 110, 23}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 150, 55, 200, 110, 186, 180, 191}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 160, 102, 215}, 190}, {{62, 192, 0, 0, 17, 73, 34, 38, 41, 35, 66, 230, 180, 92, 146, 46}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{62, 192, 0, 0, 0, 0, 173, 59, 33, 240, 80, 0, 176, 116, 49, 173}, 190}, {{62, 192, 0, 0, 18, 152, 173, 219, 24, 150, 17, 144, 6, 225, 67, 15}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 206, 68}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 243, 158, 5}, 190}, {{62, 192, 0, 0, 135, 155, 2, 254, 180, 94, 255, 242, 159, 135, 123, 126}, 190}, {{62, 192, 0, 0, 0, 0, 0, 124, 252, 18, 9, 160, 243, 47, 24, 165}, 190}, {{62, 192, 0, 50, 224, 199, 57, 113, 217, 167, 187, 203, 166, 125, 239, 1}, 190}, {{62, 192, 36, 209, 175, 156, 40, 111, 183, 191, 136, 194, 167, 115, 92, 91}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 125, 38, 240}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 228, 138, 49, 154}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 11, 12, 243, 206, 105, 61, 197, 116}, 190}, {{62, 192, 0, 0, 0, 0, 220, 141, 48, 151, 181, 7, 216, 137, 32, 107}, 190}, {{62, 192, 0, 0, 0, 0, 0, 223, 152, 77, 126, 132, 183, 159, 26, 90}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 190, 131, 222}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 244, 134, 88, 40}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 53, 171, 75, 1, 134, 164}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 227, 132}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 169}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 190}, {{62, 192, 0, 0, 15, 50, 248, 71, 56, 101, 147, 32, 207, 78, 207, 234}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 16, 224}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 116, 123, 205, 150, 246, 117, 51}, 190}, {{62, 192, 0, 0, 0, 0, 103, 127, 244, 207, 182, 77, 229, 24, 14, 61}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 74, 93, 57, 252}, 190}, {{62, 192, 0, 0, 0, 12, 83, 6, 149, 154, 87, 131, 167, 224, 255, 124}, 190}, {{62, 192, 0, 0, 0, 0, 12, 235, 20, 247, 158, 250, 141, 215, 222, 64}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 52, 174}, 190}, {{62, 192, 0, 0, 0, 0, 0, 6, 221, 36, 192, 165, 54, 53, 2, 0}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 74, 134, 135, 179}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 165, 65, 169, 209, 118, 207, 38}, 190}, {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 153, 152, 94}, 190}, {{53, 96, 0, 0, 0, 0, 0, 136, 57, 205, 136, 88, 195, 126, 29, 78}, 202}, {{53, 96, 0, 0, 86, 81, 13, 202, 240, 175, 152, 23, 205, 84, 46, 120}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 93, 177, 30, 136, 113, 200}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 58, 234, 132, 200, 80, 102}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 85, 255, 242, 167, 145, 7}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 86, 61, 229, 220, 52, 87, 239, 108, 253}, 202}, {{53, 96, 0, 0, 0, 0, 0, 94, 184, 210, 167, 177, 219, 68, 197, 92}, 202}, {{53, 96, 0, 0, 0, 0, 0, 161, 216, 72, 147, 82, 249, 211, 67, 15}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 73}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 118, 119, 121, 215, 222, 240, 245}, 202}, {{53, 96, 0, 63, 247, 63, 127, 80, 233, 212, 167, 104, 255, 218, 80, 166}, 202}, {{53, 96, 0, 0, 0, 211, 157, 27, 28, 88, 167, 95, 112, 135, 237, 18}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 232, 173, 95, 189}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 224, 254, 145, 139, 132, 134}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 181, 31, 15}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 131, 139, 213, 234, 24, 252}, 202}, {{53, 96, 0, 0, 0, 0, 0, 33, 24, 176, 55, 5, 24, 49, 32, 183}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 220, 50, 96, 36, 102, 131, 198}, 202}, {{53, 96, 0, 0, 0, 0, 111, 106, 248, 124, 239, 243, 190, 178, 64, 73}, 202}, {{53, 96, 0, 91, 138, 53, 203, 214, 73, 220, 232, 87, 158, 226, 184, 213}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 163, 98, 24, 149, 251, 32}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 160, 18, 87, 91, 248, 149, 179, 183}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 74}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 250, 93, 5, 110, 173, 105, 103}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 9}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 130, 167, 220, 58, 78, 25, 177, 235}, 202}, {{53, 96, 0, 0, 0, 0, 0, 163, 108, 213, 230, 127, 156, 169, 90, 29}, 202}, {{53, 96, 0, 0, 0, 0, 85, 155, 237, 5, 244, 184, 156, 155, 60, 97}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 160, 240}, 202}, {{53, 96, 0, 0, 0, 0, 0, 29, 209, 70, 129, 77, 164, 133, 6, 135}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 87, 96, 120, 63, 149, 255}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 189, 252, 221, 193, 60, 59}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 84, 104, 242, 66, 216, 113}, 202}, {{53, 96, 0, 0, 0, 0, 0, 218, 165, 180, 175, 163, 34, 128, 161, 154}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 17, 253}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 77, 131, 184, 230, 221, 97, 67}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 18, 17, 51, 157, 229, 214, 176}, 202}, {{53, 96, 0, 0, 0, 0, 0, 56, 82, 149, 204, 235, 18, 236, 103, 129}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 185, 163, 159}, 202}, {{53, 96, 0, 0, 0, 170, 44, 147, 121, 118, 183, 3, 178, 69, 53, 43}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 222, 12, 204, 209}, 202}, {{53, 96, 0, 0, 0, 0, 0, 20, 170, 107, 214, 78, 196, 15, 67, 43}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 202}, {{53, 96, 0, 0, 0, 0, 0, 141, 209, 185, 37, 226, 124, 162, 32, 118}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 100}, 202}, {{53, 96, 0, 0, 0, 39, 102, 184, 46, 103, 118, 83, 29, 43, 71, 9}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 202}, {{53, 96, 0, 0, 0, 0, 0, 53, 11, 95, 100, 203, 84, 5, 152, 70}, 202}, {{53, 96, 0, 0, 0, 0, 85, 203, 145, 110, 126, 48, 159, 133, 182, 159}, 202}, {{53, 96, 0, 0, 0, 0, 0, 32, 253, 95, 128, 30, 64, 179, 64, 191}, 202}, {{53, 96, 0, 0, 0, 0, 0, 44, 72, 103, 172, 136, 137, 95, 201, 186}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 136, 172, 16, 217}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 128, 61}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 59, 85, 152, 97, 129, 233, 253, 20, 116, 57, 154, 183}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 82, 63}, 202}, {{53, 96, 0, 0, 193, 105, 162, 139, 103, 175, 198, 143, 33, 14, 245, 24}, 202}, {{53, 96, 0, 0, 0, 0, 0, 187, 29, 44, 136, 19, 163, 147, 194, 45}, 202}, {{53, 96, 0, 0, 0, 0, 0, 171, 75, 137, 71, 25, 102, 4, 231, 178}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 5, 83, 133, 95}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 42, 40, 74, 219, 56, 157}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 127, 226, 162, 136, 156, 178, 204, 33, 121, 11, 132}, 202}, {{53, 96, 0, 0, 0, 0, 144, 7, 233, 218, 220, 250, 112, 246, 175, 18}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 189, 9, 233, 53}, 202}, {{53, 96, 0, 0, 0, 0, 181, 241, 12, 99, 89, 144, 111, 102, 14, 179}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 221, 251, 86, 69, 0, 226}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 206, 132, 6, 250, 56, 89, 37, 102, 128, 139, 72}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 226, 51}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 181, 180, 201, 240}, 202}, {{53, 96, 145, 186, 179, 37, 71, 55, 148, 34, 181, 10, 223, 81, 13, 125}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 117, 151}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 47, 110, 200, 232}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 196, 188, 0, 36, 79, 151}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 93, 207, 112, 6}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 231, 145, 192, 43, 91, 134, 75}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 0, 252, 17, 105, 73, 178, 17, 27, 144, 13}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 80}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 30, 84, 11, 30, 237, 71, 190, 160}, 202}, {{53, 96, 0, 0, 0, 0, 0, 235, 254, 94, 118, 231, 129, 52, 79, 98}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 117, 211, 225, 251, 250, 123, 63}, 202}, {{53, 96, 0, 0, 0, 0, 26, 4, 209, 108, 72, 5, 248, 39, 22, 108}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{53, 96, 0, 0, 0, 0, 87, 192, 200, 119, 95, 133, 81, 97, 14, 89}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 49, 187}, 202}, {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 229, 39, 170}, 202}, {{53, 96, 0, 0, 36, 157, 86, 212, 254, 125, 250, 2, 12, 148, 175, 50}, 202}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 138, 218, 203, 109, 237, 130, 139}, 54}, {{198, 0, 159, 248, 224, 165, 74, 65, 249, 101, 117, 73, 57, 212, 3, 34}, 54}, {{198, 0, 0, 0, 0, 213, 119, 229, 248, 186, 80, 187, 180, 20, 135, 182}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 34, 202, 100}, 54}, {{198, 0, 0, 16, 134, 137, 159, 172, 35, 168, 164, 3, 197, 24, 181, 213}, 54}, {{198, 0, 4, 202, 134, 201, 224, 129, 165, 56, 79, 103, 14, 9, 176, 121}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 121, 108, 165}, 54}, {{198, 0, 126, 75, 135, 194, 80, 62, 246, 111, 206, 244, 66, 222, 94, 186}, 54}, {{198, 0, 0, 0, 0, 0, 226, 234, 241, 125, 27, 9, 228, 124, 153, 42}, 54}, {{198, 0, 0, 0, 0, 0, 0, 91, 99, 0, 36, 99, 49, 252, 108, 73}, 54}, {{198, 0, 0, 233, 134, 145, 27, 250, 193, 167, 47, 179, 176, 222, 137, 166}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 238, 92, 51, 208, 52, 118, 116}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 126, 56}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 54}, {{198, 0, 0, 0, 122, 62, 240, 197, 163, 101, 39, 180, 69, 9, 125, 124}, 54}, {{198, 0, 0, 0, 0, 0, 0, 175, 55, 163, 249, 249, 121, 83, 79, 108}, 54}, {{198, 0, 0, 0, 0, 0, 102, 22, 163, 6, 71, 72, 157, 14, 89, 181}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 6, 143, 119, 101, 34, 106, 95, 194}, 54}, {{198, 0, 0, 0, 45, 226, 115, 109, 23, 187, 19, 24, 53, 183, 190, 35}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 187, 216, 33, 30}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 107}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 228, 112}, 54}, {{198, 0, 0, 0, 0, 78, 19, 2, 73, 89, 6, 54, 166, 197, 153, 212}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 205, 75, 23, 12, 251, 138, 79}, 54}, {{198, 0, 0, 0, 0, 0, 249, 99, 40, 67, 161, 95, 243, 85, 141, 234}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 255, 95, 158}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 150, 204, 161, 46, 25, 117, 7, 122, 240, 18, 60, 145}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 213, 85, 114, 137}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 4, 195}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 184, 225, 191}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 1, 59}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 89, 178, 34, 118, 169, 81, 147}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 202, 23, 163, 210, 182, 182, 220, 45}, 54}, {{198, 0, 0, 208, 24, 195, 50, 63, 189, 236, 8, 40, 153, 91, 182, 109}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 54}, {{198, 0, 0, 0, 0, 0, 0, 238, 246, 122, 164, 2, 109, 52, 123, 56}, 54}, {{198, 0, 0, 1, 173, 156, 65, 213, 177, 36, 167, 10, 245, 112, 34, 32}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 103, 149, 193, 18, 124}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 217, 207, 145, 12, 195, 120, 229}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 137, 251, 72}, 54}, {{198, 0, 0, 0, 0, 0, 188, 159, 165, 19, 34, 10, 173, 232, 40, 251}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 216}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 227, 89, 203, 32}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 24}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 119, 118, 2}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 45, 15, 208}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 54}, {{198, 0, 0, 0, 204, 193, 253, 212, 25, 92, 190, 156, 141, 2, 84, 254}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 212, 128, 23, 169, 60, 166, 225, 50, 20, 36}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 123, 104, 242, 202, 81, 78, 232, 95}, 54}, {{198, 0, 0, 0, 161, 16, 114, 52, 166, 156, 101, 117, 163, 224, 152, 77}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 174, 202}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 54}, {{198, 0, 0, 0, 227, 90, 33, 224, 26, 104, 212, 177, 91, 3, 179, 223}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 146, 238, 167, 61, 48, 53, 178, 163, 249, 18, 105, 237, 36}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 161, 113, 200, 190}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 232}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 5, 52, 65, 141, 139, 207, 235, 227}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 143, 169}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 210, 46, 12, 11, 75, 86, 155}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 7, 147, 68, 20, 114, 61, 165, 170}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 190, 30, 5, 190, 235, 171, 146, 11}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 11, 21, 19, 7, 12, 247, 174, 227}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 54}, {{198, 0, 0, 0, 63, 95, 86, 182, 41, 248, 3, 140, 129, 70, 230, 156}, 54}, {{198, 0, 0, 161, 201, 70, 91, 237, 86, 219, 51, 20, 228, 181, 56, 231}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 54}, {{198, 0, 0, 0, 0, 62, 220, 202, 225, 48, 186, 19, 79, 2, 244, 121}, 54}, {{198, 0, 121, 105, 199, 242, 50, 136, 101, 2, 157, 110, 171, 138, 17, 103}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 227, 145, 216, 206}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 252}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 117}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 40, 54, 244, 138, 115, 174, 133, 25}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 144, 178, 88, 78, 230}, 54}, {{198, 0, 0, 0, 0, 0, 0, 152, 147, 104, 172, 245, 25, 252, 8, 71}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 209, 238, 191, 250, 97, 178, 122}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 121, 168, 50, 6, 222, 122, 242}, 54}, {{198, 0, 0, 0, 0, 0, 150, 156, 155, 56, 230, 232, 148, 179, 186, 162}, 54}, {{198, 0, 0, 0, 0, 0, 110, 157, 110, 201, 11, 22, 43, 86, 17, 14}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 1, 80, 248}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 14, 220, 40, 43}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 6, 13, 213, 42, 248, 132, 84, 197}, 54}, {{198, 0, 0, 0, 0, 0, 0, 92, 194, 182, 123, 20, 239, 206, 187, 148}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 43, 154, 99, 147, 193, 200, 117, 62}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 138, 222, 105, 116}, 54}, {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 54}, {{189, 234, 106, 247, 64, 0, 0, 0, 46, 9, 169, 126, 125, 175, 121, 177}, 156}, {{189, 234, 106, 247, 64, 0, 0, 47, 227, 86, 242, 210, 126, 225, 83, 233}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 91, 0, 104, 26, 172, 193, 183}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 56, 2, 6, 54, 72, 102, 57, 155, 3, 39}, 156}, {{189, 234, 106, 247, 64, 0, 232, 53, 234, 231, 87, 65, 238, 163, 213, 47}, 156}, {{189, 234, 106, 247, 64, 80, 209, 163, 27, 248, 58, 39, 23, 194, 86, 254}, 156}, {{189, 234, 106, 247, 64, 196, 219, 111, 214, 79, 26, 14, 159, 13, 50, 33}, 156}, {{189, 234, 106, 247, 64, 0, 248, 81, 120, 36, 62, 33, 178, 234, 79, 42}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 19, 46, 254, 208, 178, 220, 130, 140}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 156}, {{189, 234, 106, 247, 64, 0, 102, 75, 60, 20, 45, 196, 106, 231, 223, 185}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 26, 110, 200, 149, 55}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 223, 178, 83, 173, 131, 86, 234}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 110, 202, 131}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 22, 141, 164, 17, 219, 207}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 190, 93, 56, 112, 245, 164, 52}, 156}, {{189, 234, 106, 247, 64, 0, 0, 252, 158, 57, 182, 21, 201, 235, 176, 9}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 179}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 156}, {{189, 234, 106, 247, 64, 0, 0, 213, 139, 221, 135, 251, 208, 51, 242, 192}, 156}, {{189, 234, 106, 247, 64, 0, 0, 118, 125, 6, 42, 5, 63, 188, 123, 23}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 125}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 118, 229, 47}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 42, 219, 45}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 146}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 35, 192, 126, 7, 117}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 242, 62, 105}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 10}, 156}, {{189, 234, 106, 247, 64, 0, 0, 146, 122, 39, 133, 199, 188, 205, 6, 27}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 243, 120, 13, 56, 85, 253}, 156}, {{189, 234, 106, 247, 64, 151, 154, 230, 23, 86, 126, 92, 190, 64, 235, 169}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 253, 119, 51}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 74, 204, 225, 168, 117, 45, 138, 106}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 95, 208, 105, 17, 92, 109, 111}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 20, 3, 112, 237, 182, 231}, 156}, {{189, 234, 106, 247, 64, 0, 169, 206, 84, 237, 44, 230, 177, 177, 111, 233}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 73, 146, 157, 224, 237, 23}, 156}, {{189, 234, 106, 247, 64, 130, 60, 142, 125, 152, 40, 152, 241, 148, 95, 226}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 25, 134, 218, 160, 35, 203, 255}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 201, 97, 155, 132, 148, 177, 16}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 159, 225, 175, 229}, 156}, {{189, 234, 106, 247, 64, 0, 127, 219, 77, 112, 178, 158, 200, 181, 68, 9}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 23}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 124, 138, 242, 204, 178}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 0, 162, 61, 210, 153, 160, 205, 42, 97, 100}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 252, 210, 31, 161, 61, 177, 238, 230}, 156}, {{189, 234, 106, 247, 64, 0, 0, 109, 165, 248, 2, 150, 223, 214, 159, 78}, 156}, {{189, 234, 106, 247, 64, 60, 231, 145, 141, 36, 156, 96, 217, 196, 201, 165}, 156}, {{189, 234, 106, 247, 64, 0, 0, 90, 28, 254, 151, 181, 228, 219, 120, 112}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 163, 187, 172, 165, 194, 123, 121, 91}, 156}, {{189, 234, 106, 247, 64, 0, 0, 100, 203, 150, 254, 53, 99, 110, 121, 167}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 32, 142, 72, 245}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 186, 88, 249, 124, 247, 176, 106}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 174, 188, 189, 143, 15}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 70, 2, 109, 212, 107}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 148, 195, 219}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 152, 206, 153, 111, 21}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 79, 254, 111}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 118, 170, 17, 87}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 196, 50, 117, 242, 113, 69}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 141, 203, 114, 38, 142, 116}, 156}, {{189, 234, 106, 247, 64, 0, 0, 56, 249, 2, 74, 137, 114, 198, 144, 167}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 149, 30, 200, 98, 132, 80, 237}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 94}, 156}, {{189, 234, 106, 247, 64, 0, 168, 214, 107, 236, 53, 237, 134, 112, 196, 139}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 82, 118, 159, 63, 126}, 156}, {{189, 234, 106, 247, 64, 0, 191, 203, 246, 206, 36, 139, 12, 59, 45, 43}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 24, 211, 31, 156, 10, 108, 180}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 134, 7, 132, 184, 148}, 156}, {{189, 234, 106, 247, 64, 142, 164, 30, 26, 128, 68, 99, 60, 80, 48, 142}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 91, 221, 143, 175, 223, 186}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 205, 13, 180, 61}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 195, 88, 232}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 97}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 138, 21, 237, 215, 214, 110, 6}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 214}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 242, 166, 30, 249, 8, 103}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 104, 18, 164}, 156}, {{189, 234, 106, 247, 64, 0, 146, 140, 148, 235, 40, 104, 39, 58, 22, 72}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 93, 43, 144, 144}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{189, 234, 106, 247, 64, 0, 159, 3, 191, 110, 255, 87, 61, 245, 78, 17}, 156}, {{189, 234, 106, 247, 64, 0, 65, 85, 1, 93, 246, 111, 187, 178, 218, 153}, 156}, {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 170, 146, 31, 226}, 156}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 245}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 122, 131, 134, 95, 127, 72, 245}, 218}, {{128, 0, 0, 0, 0, 0, 0, 176, 184, 8, 34, 133, 129, 7, 24, 152}, 218}, {{128, 94, 54, 22, 224, 122, 97, 99, 124, 127, 234, 158, 47, 171, 144, 185}, 218}, {{128, 0, 0, 0, 0, 36, 63, 208, 141, 24, 171, 119, 204, 7, 13, 214}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 40, 144, 99, 45, 235, 159, 237, 68}, 218}, {{128, 0, 0, 0, 0, 0, 34, 58, 16, 117, 9, 46, 44, 139, 75, 119}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 152, 12, 15, 233, 88}, 218}, {{128, 0, 0, 0, 0, 0, 142, 166, 193, 38, 246, 116, 31, 26, 107, 8}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 213, 168, 181, 145}, 218}, {{128, 0, 0, 0, 0, 0, 192, 189, 18, 34, 119, 76, 160, 220, 183, 234}, 218}, {{128, 0, 0, 95, 90, 21, 204, 217, 100, 159, 246, 155, 101, 52, 209, 211}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 221, 3, 114, 151, 255, 181, 145, 92}, 218}, {{128, 0, 0, 59, 246, 175, 78, 189, 9, 57, 112, 215, 121, 199, 43, 168}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 58, 47, 162, 48, 244, 165, 220}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 101, 245, 209, 163, 34, 166, 101, 234, 56, 146, 124, 70, 125}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 202, 60, 149}, 218}, {{128, 0, 115, 161, 18, 101, 51, 169, 60, 61, 62, 133, 201, 25, 130, 99}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 94, 217, 233, 49}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 174, 33, 219, 155, 7, 50, 211, 128, 18}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 241, 144}, 218}, {{128, 0, 0, 0, 111, 226, 160, 120, 180, 141, 229, 165, 121, 217, 114, 179}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 41, 208, 231, 81, 122, 35, 104}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 57, 35, 224, 244, 176, 240, 211, 15}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 219}, 218}, {{128, 0, 19, 65, 223, 170, 14, 136, 255, 175, 98, 246, 159, 49, 82, 63}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 211, 115, 158, 135, 52, 123, 118, 58}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 169, 234, 143, 216, 69, 197, 153, 175}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 74, 127}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 113, 220, 98, 102, 154, 237, 28, 116}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 255}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 103, 144}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 215, 215, 63}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 77}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 218}, {{128, 0, 0, 0, 0, 0, 0, 112, 127, 135, 42, 99, 28, 74, 125, 217}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 199, 245, 189, 223, 35}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 141}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 138, 219, 18, 110, 19, 31, 153}, 218}, {{128, 0, 0, 0, 0, 83, 38, 60, 223, 73, 205, 4, 109, 136, 253, 174}, 218}, {{128, 0, 0, 0, 209, 220, 35, 7, 55, 206, 25, 251, 139, 195, 51, 57}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 144, 53, 143, 213, 49, 104, 125}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 42, 36, 99, 74, 199}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 93, 124, 192, 248, 163}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 7, 210, 227, 39, 151, 119, 53, 106}, 218}, {{128, 0, 0, 0, 102, 38, 254, 128, 206, 244, 166, 253, 149, 46, 70, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 220, 57, 72, 202, 214, 165, 5, 172}, 218}, {{128, 0, 0, 0, 0, 0, 51, 56, 55, 51, 129, 185, 215, 111, 25, 172}, 218}, {{128, 0, 132, 215, 38, 118, 36, 111, 152, 193, 177, 254, 182, 159, 173, 168}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 8, 177, 88, 227, 247}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 49, 196, 105, 23, 222}, 218}, {{128, 0, 0, 99, 202, 255, 200, 127, 205, 240, 205, 16, 33, 213, 132, 233}, 218}, {{128, 0, 0, 0, 0, 35, 183, 201, 212, 129, 83, 100, 10, 92, 48, 221}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 171}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 112}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 190, 84, 11, 76, 186}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 185, 154, 117, 230}, 218}, {{128, 0, 0, 0, 196, 59, 86, 187, 47, 20, 125, 249, 149, 144, 144, 223}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 248, 77, 175, 0, 232}, 218}, {{128, 0, 214, 22, 76, 187, 207, 194, 75, 1, 87, 135, 236, 166, 144, 142}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 46, 210, 138, 61}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 59}, 218}, {{128, 0, 0, 0, 0, 0, 0, 24, 163, 68, 43, 44, 180, 254, 143, 88}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 197}, 218}, {{128, 0, 0, 83, 239, 28, 204, 184, 136, 8, 102, 161, 157, 31, 4, 168}, 218}, {{128, 0, 0, 0, 0, 0, 0, 235, 206, 69, 241, 66, 126, 167, 88, 203}, 218}, {{128, 0, 0, 0, 0, 0, 109, 168, 216, 128, 110, 126, 245, 54, 125, 198}, 218}, {{128, 0, 0, 0, 0, 201, 18, 187, 168, 172, 228, 57, 249, 127, 171, 76}, 218}, {{128, 0, 0, 0, 67, 242, 206, 131, 167, 241, 42, 29, 29, 253, 101, 49}, 218}, {{128, 0, 0, 0, 0, 0, 0, 116, 7, 8, 159, 179, 219, 35, 83, 77}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 113, 107, 83, 140, 59, 136, 45}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 119}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 179, 18}, 218}, {{128, 0, 0, 0, 0, 0, 0, 66, 9, 188, 170, 134, 53, 49, 250, 95}, 218}, {{128, 0, 0, 0, 0, 0, 122, 63, 13, 177, 197, 239, 51, 52, 208, 193}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 85, 249}, 218}, {{128, 0, 0, 0, 0, 0, 0, 72, 206, 13, 24, 74, 243, 197, 194, 85}, 218}, {{128, 0, 0, 0, 0, 0, 60, 228, 184, 139, 60, 95, 21, 140, 99, 109}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 109, 20, 207, 110, 68}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 115, 23, 242, 9, 98}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 186, 77, 110, 201}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 67, 219, 34, 13, 228, 173, 11}, 218}, {{128, 0, 0, 0, 0, 0, 58, 222, 233, 60, 184, 86, 96, 36, 5, 103}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 122}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 155, 39, 50, 119}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 48, 113, 220, 132, 115, 16, 206}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 226, 140, 5, 246, 142, 125, 120}, 218}, {{128, 0, 0, 0, 0, 120, 222, 31, 10, 212, 176, 9, 122, 177, 208, 249}, 218}, {{128, 0, 0, 0, 0, 0, 0, 69, 161, 178, 205, 203, 19, 132, 181, 90}, 218}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 192, 245}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 163, 104, 52}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 106, 216}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 73, 206}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 155, 36}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 88, 14, 190, 13}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 67, 106, 64}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 112, 230}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 125}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 41}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 221, 59, 134}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 233, 179, 129}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 14}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 186}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 191, 231, 224}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 107, 135, 151}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 165, 250}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 38, 116, 88}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 5, 109}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 61, 182, 102}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 214, 78, 72}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 16, 122, 123}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 116}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 15, 126, 165}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 154, 21, 49}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 210, 123}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 233, 93}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 151, 189}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 98, 99, 104}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 74, 72, 25}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 178}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 32}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 6, 199}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 109, 80, 89}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 22, 32, 194}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 210, 162, 215}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 90}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 24, 30, 213, 91}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 19}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 133, 178, 50}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 11}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 108, 115}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 62, 208, 154}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 227, 255, 137}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 60, 162, 44}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 57, 78, 67}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 248}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 136}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 248}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 144, 161, 42}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 95, 144, 186}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 205, 176}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 23, 31, 167, 1}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 158, 103, 192, 93}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 64, 42}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 160, 250, 156}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 246, 97, 114}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 222}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 102, 45, 42}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 15, 43, 75}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 30, 27}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 118, 15, 82}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 200, 221, 192}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 42}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 152}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 210, 58}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 207, 137, 21}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 222, 207, 76, 190}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 146}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 59}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 201, 230}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 114}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 177, 213, 102, 180}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 216, 57}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 106, 173, 116}, 72}, {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 10}, 72}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 157}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 27}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 243}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 167}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 58}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 178}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 81}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 221}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 87}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 194}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 7}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 18}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 65}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 169}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 174}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 28}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 91}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 28}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 200}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 178}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 21}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 222}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 60}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 70}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 28}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 51}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 11}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 252}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 150}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 225}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 103}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 137}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 179}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 71}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 180}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 10}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 32}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 200}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 182}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 200}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 129}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 217}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 183}, {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 76}, 183}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 118, 94, 38}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 61, 29, 105, 157, 200, 222, 99}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 25, 153, 151, 57, 127}, 218}, {{128, 0, 0, 0, 0, 0, 201, 161, 59, 50, 30, 114, 125, 59, 158, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 115, 168, 169, 84, 122, 180, 106, 84}, 218}, {{128, 0, 0, 0, 0, 0, 181, 42, 145, 179, 15, 130, 99, 150, 237, 169}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 135, 66, 216, 172, 4, 92, 95}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 171, 127, 124, 57, 80, 160, 170, 230}, 218}, {{128, 0, 0, 0, 0, 0, 0, 122, 111, 109, 197, 151, 110, 197, 23, 189}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 197, 27, 83, 183}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 245, 197, 15, 95, 188, 16, 208}, 218}, {{128, 174, 88, 169, 71, 224, 110, 64, 234, 26, 133, 178, 184, 125, 121, 41}, 218}, {{128, 81, 221, 218, 172, 57, 199, 73, 128, 138, 74, 103, 169, 163, 116, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 49, 98, 209, 39}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 178, 130, 180}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 116, 96, 221, 69, 241}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 85, 168, 216, 116}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 203, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 33, 48, 174, 87, 248, 166, 241, 128, 165, 29, 39, 146}, 218}, {{128, 0, 0, 0, 155, 11, 137, 84, 52, 41, 32, 130, 195, 201, 62, 55}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 124}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 111, 97, 196, 159, 255, 156, 198, 82}, 218}, {{128, 0, 0, 0, 0, 255, 222, 42, 195, 230, 221, 3, 212, 233, 10, 121}, 218}, {{128, 0, 0, 0, 0, 0, 117, 180, 115, 163, 124, 32, 17, 189, 34, 157}, 218}, {{128, 0, 0, 0, 0, 0, 112, 204, 17, 139, 198, 35, 196, 36, 111, 123}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 164, 229, 132, 117, 25}, 218}, {{128, 0, 0, 0, 230, 201, 68, 159, 205, 8, 188, 98, 165, 19, 7, 14}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 72, 249, 23, 150, 199, 225, 125, 88}, 218}, {{128, 0, 0, 0, 152, 159, 201, 165, 94, 86, 144, 167, 47, 60, 179, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 100, 148, 146, 196}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 169, 124, 97, 224, 4, 213, 34}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 85, 238}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 174, 252, 108, 59, 94, 153, 164}, 218}, {{128, 0, 0, 0, 0, 176, 133, 71, 75, 66, 255, 2, 245, 154, 128, 114}, 218}, {{128, 0, 246, 56, 76, 85, 62, 192, 16, 141, 65, 188, 73, 102, 201, 72}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 91}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 201}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 218}, {{128, 0, 0, 0, 0, 0, 230, 134, 152, 101, 92, 80, 107, 122, 240, 56}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 204}, 218}, {{128, 0, 0, 0, 42, 42, 145, 79, 210, 142, 40, 214, 176, 72, 115, 34}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 68}, 218}, {{128, 102, 249, 138, 108, 245, 93, 25, 169, 228, 32, 44, 190, 140, 92, 166}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 93, 142, 46, 131, 192}, 218}, {{128, 0, 0, 0, 0, 175, 80, 197, 159, 212, 202, 148, 238, 71, 17, 30}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 139, 194, 146, 9, 175, 225, 228, 69, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 245, 103, 221, 216, 142, 237, 173, 77}, 218}, {{128, 201, 105, 7, 68, 30, 114, 217, 157, 166, 179, 220, 72, 125, 112, 13}, 218}, {{128, 0, 212, 236, 145, 215, 83, 182, 116, 46, 177, 204, 122, 33, 196, 18}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 107, 161}, 218}, {{128, 0, 45, 158, 139, 28, 167, 6, 91, 232, 58, 215, 216, 36, 187, 126}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 16, 198, 109}, 218}, {{128, 0, 0, 0, 59, 166, 6, 48, 210, 111, 114, 214, 28, 69, 115, 58}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 11}, 218}, {{128, 0, 0, 0, 0, 57, 198, 71, 234, 131, 10, 38, 71, 154, 1, 89}, 218}, {{128, 121, 133, 61, 105, 86, 156, 130, 208, 178, 75, 237, 113, 60, 138, 54}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 218}, {{128, 38, 184, 222, 235, 112, 115, 138, 211, 21, 77, 124, 107, 131, 13, 66}, 218}, {{128, 0, 224, 175, 241, 74, 98, 203, 215, 94, 14, 143, 106, 5, 133, 169}, 218}, {{128, 82, 28, 60, 175, 255, 167, 190, 6, 73, 119, 229, 195, 97, 62, 108}, 218}, {{128, 0, 0, 0, 236, 144, 103, 72, 160, 223, 165, 130, 240, 232, 110, 226}, 218}, {{128, 0, 0, 0, 0, 0, 134, 16, 44, 116, 87, 142, 200, 98, 38, 22}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 181, 153, 206, 113}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 192, 28, 80, 49, 138}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 84, 32, 68, 231, 143, 21, 26}, 218}, {{128, 0, 0, 45, 237, 158, 44, 224, 228, 237, 134, 89, 17, 103, 202, 134}, 218}, {{128, 0, 0, 37, 157, 227, 134, 202, 69, 245, 152, 137, 231, 90, 141, 209}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 218}, {{128, 0, 190, 77, 255, 127, 147, 109, 93, 164, 233, 186, 65, 73, 137, 131}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 58, 10, 32, 243, 198, 76, 201, 105}, 218}, {{128, 0, 0, 0, 0, 171, 167, 91, 121, 140, 134, 232, 27, 113, 230, 182}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 147, 188}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 180, 154, 106, 111, 208, 140, 13, 124}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 37, 6, 48, 85, 146, 157, 233, 238}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 1, 143, 169, 169, 182, 81, 75}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 111, 165, 30, 246, 183, 142, 42, 209}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 193, 72, 184, 224, 68, 110, 181}, 218}, {{128, 125, 78, 153, 231, 79, 104, 58, 121, 205, 131, 223, 222, 129, 19, 234}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 46, 10, 232, 46, 30, 116, 72}, 218}, {{128, 0, 0, 229, 18, 145, 116, 137, 184, 193, 62, 212, 243, 135, 101, 7}, 218}, {{128, 0, 0, 0, 226, 7, 93, 146, 75, 202, 131, 35, 131, 122, 150, 157}, 218}, {{128, 0, 137, 242, 112, 206, 41, 150, 2, 251, 2, 164, 65, 178, 78, 220}, 218}, {{128, 0, 204, 64, 249, 95, 19, 154, 191, 9, 134, 46, 81, 51, 56, 115}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 152, 209}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 141, 67, 41, 96}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 41, 249, 95, 234, 187, 176, 57, 129, 15, 99}, 218}, {{63, 37, 46, 158, 139, 128, 220, 38, 100, 58, 79, 45, 20, 140, 44, 43}, 241}, {{63, 37, 46, 158, 139, 128, 119, 200, 232, 167, 21, 139, 157, 93, 150, 109}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 67, 74, 231, 35, 214, 229, 65}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 72, 197, 14, 39, 219, 217}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 2, 230, 195, 144, 165, 242}, 241}, {{63, 37, 46, 158, 139, 128, 0, 167, 158, 38, 158, 137, 75, 230, 234, 84}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 31, 155, 113, 54, 25}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 99, 233, 23, 50, 109, 216, 112, 212}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 229, 145}, 241}, {{63, 37, 46, 158, 139, 128, 64, 108, 221, 18, 213, 38, 113, 29, 110, 71}, 241}, {{63, 37, 46, 158, 139, 128, 0, 249, 215, 249, 180, 36, 139, 131, 127, 121}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 85, 175, 248, 183, 109, 52}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 105, 70}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 175, 113, 111, 133}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 98, 231, 6, 76, 219}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 222, 185, 62, 54}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 43, 174}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 83, 99, 70}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 84, 110, 231, 33, 193, 22, 24, 251, 107}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 16, 98, 56}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 72, 147, 66, 220, 172, 100, 77}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 184, 0, 53, 71}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 100, 107}, 241}, {{63, 37, 46, 158, 139, 128, 0, 184, 141, 155, 194, 55, 32, 232, 244, 173}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 196, 114}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 136, 14, 193, 67, 30}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 72, 23}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 236, 194, 173, 240, 177, 115, 111, 207}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 147, 250, 123, 34, 60, 99, 125, 120}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 136, 5, 244, 106, 137, 32, 206, 236}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 208, 101, 142, 67}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 123, 51}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 180, 55, 202, 49}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 130, 34, 93, 91, 100, 72, 66}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 100, 76, 17, 23, 160, 10}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 79, 118, 229}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 141, 99, 26, 40, 99, 129, 42, 175, 253, 18}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 42, 164, 99}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 163, 93, 185, 237, 93, 184, 47, 71}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 176, 187, 19, 207, 18, 74, 173}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 137, 98, 132, 208, 143, 109, 20, 64}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 14, 103, 50, 47, 148}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 82, 221}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 124, 106, 154, 41, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 251, 251}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 40, 144, 63, 206, 186, 110, 241}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 36, 173, 166}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 123, 129, 240, 189, 91, 84, 81, 135}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 56, 227}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 176, 185, 98}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 128, 222, 243, 161}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 26, 54, 231, 142, 24, 66, 82}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 206, 85, 240, 204}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 162, 245, 93, 220}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 204, 255, 194, 191, 217}, 241}, {{63, 37, 46, 158, 139, 128, 0, 183, 73, 196, 89, 193, 2, 226, 31, 99}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 199, 83, 78, 10}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 7, 2, 213, 216}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 71, 201, 126}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 67, 138, 99}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 16, 50, 237, 85, 38, 7, 4, 193}, 241}, {{63, 37, 46, 158, 139, 128, 0, 181, 27, 130, 214, 58, 20, 200, 192, 118}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 232, 57, 19, 166, 21, 139}, 241}, {{63, 37, 46, 158, 139, 128, 65, 67, 200, 137, 43, 92, 245, 118, 80, 234}, 241}, {{63, 37, 46, 158, 139, 128, 0, 17, 237, 96, 182, 69, 46, 189, 217, 254}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 62, 224, 41}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 241, 118, 69, 109, 130, 150, 83, 121}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 165, 73}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 57, 195, 107, 102, 4}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 121, 159, 37}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 6, 221, 32}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 58, 200, 12, 167}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 199, 12, 237, 71, 128, 167}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 241}, {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 83, 26, 60, 244, 20, 153}, 241}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 169, 186}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 235, 72, 254, 63, 77, 4}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 79, 101}, 106}, {{53, 209, 59, 13, 202, 70, 0, 150, 98, 212, 139, 245, 62, 168, 249, 129}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 36, 186}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 10, 197, 18, 72, 129}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 11, 39, 174, 150, 207, 95, 10, 197}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 202, 107, 113, 3, 145, 94, 116, 219}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 160, 132}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 237, 186, 229, 226}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 143, 60, 35}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 210, 53, 9, 135, 160, 116}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 25, 127}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 242, 253, 111, 55}, 106}, {{53, 209, 59, 13, 202, 70, 0, 188, 129, 29, 150, 1, 251, 218, 86, 82}, 106}, {{53, 209, 59, 13, 202, 70, 0, 123, 149, 203, 51, 59, 10, 8, 94, 98}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 130, 3, 154, 236, 139}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 163, 32, 166}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 18, 76, 168, 225, 202, 65, 26, 92}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 122, 168, 239, 45, 158}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 15, 227, 133, 240, 166, 213, 250, 28}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 19, 254}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 222, 88, 154, 205}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 117, 125, 32, 250}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 17, 14, 44, 221, 243}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 69, 229, 32, 161}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 246, 2, 99, 61, 23, 126, 156, 13, 217, 20}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 179, 129, 18, 20, 90, 218, 34, 179, 110}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 203, 98, 175, 181, 249, 10, 87, 243}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 196, 187}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 82, 244, 156, 10}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 22, 213, 190, 240, 167, 80, 234}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 98, 139, 180}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 185, 152, 233, 140, 225, 74, 200}, 106}, {{53, 209, 59, 13, 202, 70, 15, 81, 230, 52, 169, 56, 97, 32, 96, 65}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 107, 155, 193, 161, 108}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 62, 31, 96}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 30, 246, 225, 192, 94}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 97, 36, 248, 76, 46, 173, 174, 124}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 148, 31}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 202, 211, 129, 92}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 81, 151, 45, 17, 197, 126, 69}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 172, 58, 134, 110, 146, 174, 9, 90, 81}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 116, 107, 128}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 34, 99, 156, 35, 189, 240}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 170, 182, 253, 102, 247}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 79, 227, 142}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 250, 38, 104, 253}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 235, 149, 182, 61, 161, 112}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 200, 204, 154}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 128, 88}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 208, 48, 90, 219, 9}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 155, 181, 210, 129, 192}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 246, 185, 44, 180, 114, 251, 47, 146}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 187, 245, 183, 158, 189}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 37, 15, 82}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 119, 231}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 226, 160, 65, 114, 54}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 234, 193, 145, 19, 149}, 106}, {{53, 209, 59, 13, 202, 70, 0, 254, 228, 73, 249, 158, 197, 103, 40, 197}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 11, 58, 201, 175, 36, 183}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 159, 61, 10, 108, 199}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 71, 72}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 20, 115, 143, 31, 66, 110, 198}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 76, 146, 129, 161, 179}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 37, 205, 246, 183, 175, 1, 175}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 233, 168, 147}, 106}, {{53, 209, 59, 13, 202, 70, 0, 139, 186, 13, 202, 105, 85, 67, 49, 222}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 152, 56}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 149, 75, 85, 171, 152, 56, 28}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 78, 19, 105, 130, 52, 149}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 152, 76, 230, 163, 111, 42, 240}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 170, 34, 201, 142, 163, 234}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 175, 13, 131, 16, 189}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 224, 38, 91, 222}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 216, 224}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 178, 11, 126, 250, 233, 36}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 222, 85}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 72, 52, 196, 160, 98, 243}, 106}, {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 188, 161, 138, 148}, 106}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 60, 232, 160, 153}, 180}, {{184, 44, 149, 221, 180, 0, 103, 185, 180, 16, 204, 106, 131, 201, 47, 35}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 46, 39, 181, 45}, 180}, {{184, 44, 149, 221, 180, 0, 163, 71, 119, 100, 206, 14, 47, 216, 2, 173}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 184, 5, 77, 247, 167}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 209, 159, 55, 34, 224, 133}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 180}, {{184, 44, 149, 221, 180, 0, 0, 229, 203, 184, 107, 119, 113, 60, 106, 48}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 245, 183, 88, 121, 191}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 187, 233, 208, 119, 156, 122}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 184}, 180}, {{184, 44, 149, 221, 180, 0, 202, 124, 61, 104, 194, 56, 132, 47, 1, 64}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 63, 174, 137, 148, 123, 85}, 180}, {{184, 44, 149, 221, 180, 0, 194, 41, 10, 132, 202, 234, 0, 230, 70, 109}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 230, 116, 100, 42, 202, 180, 109, 215}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 154, 67, 15, 54, 60, 46}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 243, 242, 186, 219, 204, 82, 177}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 214, 177, 92, 223, 142, 112}, 180}, {{184, 44, 149, 221, 180, 0, 146, 15, 17, 38, 220, 52, 198, 14, 165, 133}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 142, 10, 230}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 9, 102, 195}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 215}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 109, 24, 23, 61}, 180}, {{184, 44, 149, 221, 180, 0, 73, 71, 199, 40, 251, 189, 44, 243, 136, 203}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 82, 49, 135, 178, 200, 224, 126, 242}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 167, 232, 69, 205, 42}, 180}, {{184, 44, 149, 221, 180, 0, 105, 209, 185, 21, 112, 147, 26, 113, 220, 20}, 180}, {{184, 44, 149, 221, 180, 0, 0, 181, 99, 98, 64, 65, 90, 207, 63, 204}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 27, 171, 105, 177}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 128, 129, 122, 54, 0, 249, 154, 1}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 152, 8, 29, 109, 163, 183, 178}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 58, 242, 11, 161, 32, 87, 241, 130}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 206, 167, 141, 167}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 245}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 91, 121, 240, 108, 105, 52, 191}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 72, 241, 170, 39, 104, 72}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 132, 170, 33}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 238}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 21, 214, 230, 158, 151, 253, 131, 163}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 214, 195, 82, 98, 60, 190, 148}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 206, 23, 17}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 51}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 73, 6, 117, 167, 83}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 245}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 24}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 77, 44, 116, 236, 254, 63, 70, 46, 81}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 149, 159, 252, 234, 224, 150, 147, 253}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 114, 45, 103, 200, 139, 118, 70, 91}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 202, 200, 44, 77, 47, 74}, 180}, {{184, 44, 149, 221, 180, 0, 0, 136, 242, 20, 190, 58, 197, 3, 76, 86}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 230, 198, 222, 189, 33, 243, 108, 62, 239}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 117, 43, 222, 75}, 180}, {{184, 44, 149, 221, 180, 0, 0, 196, 10, 244, 28, 219, 55, 207, 254, 191}, 180}, {{184, 44, 149, 221, 180, 0, 160, 148, 111, 94, 171, 11, 59, 159, 78, 100}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 148, 246, 161, 82, 244, 49, 53}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 233, 41, 59, 244, 224}, 180}, {{184, 44, 149, 221, 180, 0, 248, 101, 34, 173, 95, 217, 199, 241, 44, 220}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 126, 186, 142, 223, 235}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 212, 72, 203, 113, 133, 36}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 231, 77, 44, 220}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 125, 174, 240, 43, 171, 169, 89, 46}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 43, 8, 106, 53, 126}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 4, 82, 210, 71, 49, 186, 239, 106}, 180}, {{184, 44, 149, 221, 180, 0, 81, 250, 171, 22, 84, 66, 7, 42, 60, 170}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 115, 81, 157, 250, 100, 79, 240}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 94, 204, 133, 19, 242, 141}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 133, 70, 138}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 172, 70, 224, 193, 36}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 69, 162, 68, 112, 249}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 126, 250, 169}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 76}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 163, 115, 103}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 161, 73, 16, 100}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 194, 163, 95, 72, 167, 99, 131}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 164, 248, 221}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 122, 192, 85, 81, 249, 186, 39, 244}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 46, 204, 193}, 180}, {{184, 44, 149, 221, 180, 0, 0, 217, 148, 198, 175, 131, 20, 140, 251, 226}, 180}, {{184, 44, 149, 221, 180, 0, 0, 0, 37, 77, 168, 207, 55, 18, 159, 134}, 180}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 200}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 227, 177, 21}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 7, 175}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 232, 33}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 112, 146}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 181, 43}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 106, 146}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 80, 68, 159}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 45, 174}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 234, 184}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 158, 187}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 196}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 140}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 94, 66, 177}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 23, 127, 39}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 168, 208}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 52, 118}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 9, 133, 115}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 66, 43, 160}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 11}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 90, 3}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 198, 7, 154}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 77}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 230}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 14, 32}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 135, 87}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 53, 64, 209}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 83}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 135, 200, 47}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 114, 253, 74}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 91, 15}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 55, 146, 243}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 98, 215}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 251}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 26, 217}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 235, 212}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 205, 189}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 33}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 51}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 168}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 251, 216, 158}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 225}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 235}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 188, 217}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 88, 5, 226}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 143}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 104, 214, 27}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 52, 119}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 7, 146}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 164}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 94}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 46}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 136}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 217, 201, 190}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 174, 229, 238}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 57, 240, 35}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 226, 58}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 229, 54, 19}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 166, 235, 115}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 68, 136}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 28, 77}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 59}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 109, 249}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 233, 11, 176}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 126}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 186}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 163, 86}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 203}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 41, 45}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 74, 97, 18}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 58, 109, 45}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 15, 24, 14}, 142}, {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 142}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 108}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 184}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 45, 222, 12}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 2, 163}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 29}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 70, 249}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 57}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 135, 99}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 62, 143}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 231, 59, 46}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 25, 161}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 195}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 139, 223}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 227, 15, 126}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 6, 66}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 218}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 145, 135}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 136}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 39, 152}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 24, 210, 82}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 163, 210}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 199, 147}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 105}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 70, 32}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 49}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 192}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 135}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 63, 120}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 163, 167}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 68, 173}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 2, 154}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 117}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 225}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 250, 254}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 178}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 143}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 68, 255, 77}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 102, 53, 24}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 215}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 86}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 55, 44, 234}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 73}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 35}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 40}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 136, 190, 23}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 103, 38}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 47}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 176, 135}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 57, 169, 98}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 108, 123}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 199}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 242, 98}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 54, 206}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 67, 148}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 41, 178}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 6}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 138, 216, 200}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 197, 8, 93}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 101}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 176}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 42, 232}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 11, 186}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 191, 94}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 205, 34, 232}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 63}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 106, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 40, 229}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 44, 60}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 138, 109}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 3}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 193}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 6}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 210}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 12}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 123}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 5}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 24}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 130}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 58}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 80}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 54}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 68}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 11}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 113}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 16}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 88}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 9}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 33}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 42}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 73, 130, 154, 189, 201, 113, 27}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 6}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 152, 62, 122, 208, 200, 148, 104, 81}, 224}, {{33, 166, 10, 174, 64, 26, 179, 216, 56, 81, 50, 31, 127, 11, 77, 39}, 224}, {{33, 166, 10, 174, 64, 0, 0, 148, 20, 90, 127, 25, 197, 99, 15, 248}, 224}, {{33, 166, 10, 174, 64, 0, 22, 128, 202, 234, 63, 74, 201, 64, 50, 65}, 224}, {{33, 166, 10, 174, 64, 0, 0, 223, 195, 238, 37, 238, 55, 24, 217, 17}, 224}, {{33, 166, 10, 174, 64, 0, 0, 60, 131, 220, 166, 213, 1, 246, 240, 176}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 154, 152, 151, 159, 232, 34, 30}, 224}, {{33, 166, 10, 174, 64, 0, 86, 100, 28, 62, 242, 117, 110, 123, 17, 199}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 197, 0, 231, 207}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 24, 253, 65}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 39}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 86, 61, 246, 145, 77, 244}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 232, 179, 11, 9}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 43, 93, 213}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 224}, {{33, 166, 10, 174, 64, 0, 0, 157, 137, 143, 248, 53, 53, 169, 93, 122}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 203, 35, 134, 99}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 94, 58, 192, 145, 0, 255, 107, 13}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 249, 84, 32}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 252, 10, 118, 229}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 139, 231, 7, 50}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 23}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 91, 123, 129, 205, 117}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 92, 103, 30, 96, 93}, 224}, {{33, 166, 10, 174, 64, 102, 48, 150, 62, 42, 85, 57, 169, 121, 113, 133}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 35, 51, 201, 81}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 58, 181, 192, 155, 175, 201, 102}, 224}, {{33, 166, 10, 174, 64, 221, 249, 70, 87, 196, 20, 102, 170, 145, 33, 24}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 143, 78, 178, 14, 134, 43, 123}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 174, 155, 223, 98, 142}, 224}, {{33, 166, 10, 174, 64, 0, 0, 187, 105, 16, 126, 254, 90, 245, 101, 147}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 223, 17, 190, 186, 240, 182, 88, 140}, 224}, {{33, 166, 10, 174, 64, 0, 77, 81, 228, 11, 23, 50, 90, 110, 154, 148}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 156, 96, 189, 10, 205, 132, 176, 2}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 119, 56, 203, 197, 10, 213, 30}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 251, 195, 176, 232, 23, 226}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 141, 125, 52, 151, 152, 220, 18}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 198}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 141}, 224}, {{33, 166, 10, 174, 64, 13, 99, 181, 32, 62, 62, 21, 186, 154, 237, 16}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 86, 44, 92, 86, 194}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 141, 38, 177, 117, 179, 16}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 128, 81, 128, 121}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 185, 42, 152, 246, 60, 182}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 220, 238, 110, 60}, 224}, {{33, 166, 10, 174, 64, 0, 0, 127, 250, 157, 158, 18, 70, 28, 157, 76}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 137, 30, 12, 232, 247}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 224}, {{33, 166, 10, 174, 64, 0, 0, 2, 63, 144, 251, 13, 80, 185, 230, 209}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 212, 50, 6, 167, 167, 71, 202, 89}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 95, 228, 185}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 136}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 16, 170, 133, 78, 209, 219}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 77, 184, 102}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 8, 214, 75, 37, 82, 42, 134, 144}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 176}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 80}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 13, 100, 189}, 224}, {{33, 166, 10, 174, 64, 167, 184, 48, 132, 108, 209, 167, 6, 223, 220, 85}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 244, 241, 237, 17, 4, 214}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 121, 40, 232, 249}, 224}, {{33, 166, 10, 174, 64, 20, 117, 102, 55, 238, 138, 67, 66, 234, 6, 95}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 189, 197, 143}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 195, 31, 210}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 131, 236, 66}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 217, 110, 73, 228}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 233, 221, 14, 30, 112, 186}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 207, 87, 98, 115, 83}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 56, 161, 244}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 213, 137, 135, 71}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 218, 11, 199, 162, 2, 159, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 161, 202, 208, 236, 151}, 224}, {{33, 166, 10, 174, 64, 222, 76, 24, 6, 90, 193, 120, 45, 224, 132, 115}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 52}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 167, 34, 112, 83, 172, 7, 22}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 105}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 191, 46, 108, 254}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 205, 108, 23, 150, 200}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 200}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 77, 194, 163}, 224}, {{33, 166, 10, 174, 64, 225, 20, 70, 214, 27, 111, 67, 81, 215, 173, 199}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 224}, {{33, 166, 10, 174, 64, 0, 0, 31, 97, 240, 182, 21, 4, 166, 124, 222}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 145, 203, 201, 119, 95, 185, 196, 47}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 31, 17, 16, 36}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 70}, 224}, {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 224}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 113}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 159, 147, 211, 210, 37, 99}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 28, 78, 21}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 44, 19, 141, 158}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 172}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 204, 181}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 77, 1, 43}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 187, 227}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 99, 90, 70}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 143, 86, 106, 202}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 229, 13}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 129, 129, 97, 225}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 71, 95}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 227, 83, 102, 237, 141}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 201}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 128, 162, 245, 234, 233}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 227}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 160, 72, 134, 173, 40, 159}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 180, 21, 123, 225}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 183}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 60}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 88, 147, 119}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 27, 125}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 158, 148, 77}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 43, 31, 142}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 165, 179}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 171, 253, 65}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 200, 26, 67, 103, 124}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 246, 134, 78, 231, 188}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 43, 213}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 202, 187, 215, 55, 14}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 133, 186}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 204, 107, 137}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 172, 149}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 104, 216, 29, 191}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 174, 17}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 37, 230, 24, 155}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 57, 144}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 173, 116}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 1}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 48, 97, 194, 204, 211}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 232, 214, 5}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 210}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 151, 105, 255}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 214, 150, 118}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 131}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 215, 214, 11, 92, 10}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 145, 226, 162}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 38, 196}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 244, 37, 65, 39}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 155, 84}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 44, 86, 17, 74}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 222, 57}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 216, 233, 28, 29, 56, 141}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 116, 143}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 65}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 214, 105, 5}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 187, 37, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 71}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 169, 230}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 224, 114}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 205, 226}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 82, 228, 19, 106, 155}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 233, 74}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 177, 64}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 221}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 96, 121, 167, 10}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 76, 106}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 139, 148, 68, 87}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 252, 57, 84, 131}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 194}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 30}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 158, 188, 72}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 52, 5, 215, 223, 79}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 243}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 109}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 140}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 182, 207, 218}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 161, 195, 104}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 3, 118, 228, 238, 189}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 11, 18, 111, 221, 23}, 14}, {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 43, 246, 209}, 14}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 16, 15, 243, 91}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 145, 151, 51, 26}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 165, 49, 130, 40, 36}, 149}, {{241, 0, 0, 84, 211, 229, 8, 91, 47, 174, 63, 122, 102, 116, 121, 174}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 96, 99}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 243, 106, 234, 144, 120}, 149}, {{241, 0, 0, 118, 62, 242, 180, 190, 32, 193, 2, 67, 15, 233, 37, 251}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 188, 153, 18, 251, 156}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 24, 13}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 161, 204}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 146, 42, 65, 20, 171, 120, 38, 150}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 78, 126, 5, 87}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 169, 163, 128, 3, 75, 2, 99, 18}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 156, 93, 232, 88, 180, 134, 250}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 85, 6, 164, 150, 138, 44, 63}, 149}, {{241, 0, 0, 0, 123, 225, 141, 130, 64, 20, 71, 187, 17, 222, 152, 231}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 43, 63, 81, 167, 244, 95, 223}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 196, 133, 246, 251, 10, 16, 245, 62, 57}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 150, 47}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 149}, {{241, 0, 0, 0, 0, 0, 206, 136, 152, 218, 179, 222, 109, 201, 139, 79}, 149}, {{241, 0, 152, 248, 103, 155, 161, 29, 50, 220, 146, 65, 13, 194, 21, 67}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 135, 221, 176, 163, 7, 218, 14, 121}, 149}, {{241, 0, 0, 0, 93, 15, 37, 171, 185, 118, 114, 178, 202, 254, 242, 139}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 37, 71, 157, 190, 48}, 149}, {{241, 0, 128, 139, 74, 15, 250, 96, 211, 96, 188, 106, 211, 4, 34, 52}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 105, 237, 222, 163, 239}, 149}, {{241, 0, 0, 0, 0, 0, 0, 66, 17, 208, 25, 214, 44, 76, 3, 137}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 48, 185, 235, 44}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 126, 58, 215, 217, 73}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 58, 119}, 149}, {{241, 0, 0, 0, 0, 0, 207, 186, 190, 245, 23, 135, 141, 133, 115, 21}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 137, 206, 73, 91, 38, 84, 113, 55}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 171, 119, 55, 73, 211}, 149}, {{241, 0, 0, 86, 72, 159, 199, 162, 169, 197, 36, 216, 88, 77, 203, 104}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 94}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 154, 32, 175}, 149}, {{241, 0, 0, 0, 0, 212, 175, 35, 61, 212, 233, 70, 9, 189, 48, 128}, 149}, {{241, 0, 183, 49, 78, 251, 96, 71, 128, 43, 90, 228, 152, 116, 101, 33}, 149}, {{241, 0, 0, 0, 0, 245, 119, 115, 47, 53, 102, 210, 169, 229, 232, 34}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 163, 199}, 149}, {{241, 0, 0, 0, 0, 92, 44, 219, 91, 67, 174, 82, 59, 25, 127, 82}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 154, 242, 89, 54, 111, 226, 80, 37, 87, 112, 82, 133, 62, 235}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 223, 66, 10}, 149}, {{241, 0, 0, 0, 123, 238, 112, 144, 160, 145, 230, 46, 143, 231, 56, 51}, 149}, {{241, 0, 0, 0, 0, 88, 18, 145, 53, 89, 219, 196, 223, 176, 253, 149}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 239, 157, 5}, 149}, {{241, 0, 0, 0, 0, 0, 0, 143, 23, 118, 23, 244, 178, 87, 53, 38}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{241, 0, 0, 0, 150, 123, 202, 56, 208, 73, 110, 225, 69, 138, 252, 2}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 124, 142, 7, 193, 126, 121, 127}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 156, 12, 78, 40, 172}, 149}, {{241, 0, 246, 121, 146, 29, 214, 197, 235, 50, 45, 103, 162, 98, 138, 222}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 185, 54, 86, 170, 226, 97, 141, 134}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 64, 81, 239, 72}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 160, 231, 39}, 149}, {{241, 0, 0, 0, 0, 73, 44, 23, 202, 235, 120, 32, 67, 179, 82, 132}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 38, 28}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 123, 95, 59, 35, 11, 190, 89, 60}, 149}, {{241, 0, 0, 0, 0, 0, 23, 122, 211, 31, 46, 24, 158, 171, 91, 146}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 254, 86}, 149}, {{241, 0, 0, 0, 0, 0, 0, 119, 18, 183, 49, 116, 199, 109, 191, 226}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 3, 12, 65}, 149}, {{241, 0, 0, 0, 0, 0, 0, 71, 177, 167, 130, 101, 118, 27, 188, 105}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 141, 31, 76, 194, 117, 168, 135, 10}, 149}, {{241, 0, 0, 0, 0, 0, 0, 82, 139, 207, 183, 207, 170, 251, 8, 190}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 5}, 149}, {{241, 0, 0, 0, 235, 198, 225, 198, 184, 114, 124, 44, 108, 32, 128, 106}, 149}, {{241, 0, 0, 0, 2, 227, 148, 45, 22, 171, 14, 37, 142, 60, 209, 248}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 91, 9, 39, 250}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 23, 223, 197, 147, 219, 123, 170, 85}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 117, 161, 229, 41}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 128, 37, 213, 254}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 24}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 124, 173, 118, 212, 217, 108, 9, 48}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 149}, {{241, 0, 0, 0, 0, 0, 253, 170, 172, 198, 167, 98, 233, 94, 133, 148}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 74, 161, 65}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 38, 42}, 149}, {{241, 0, 0, 0, 0, 0, 0, 4, 249, 81, 126, 117, 43, 145, 128, 30}, 149}, {{241, 0, 0, 140, 136, 100, 109, 189, 20, 236, 244, 72, 246, 217, 244, 98}, 149}, {{241, 0, 0, 0, 0, 0, 36, 193, 87, 92, 54, 67, 110, 58, 98, 86}, 149}, {{241, 0, 0, 0, 0, 0, 69, 10, 64, 247, 207, 68, 57, 31, 129, 94}, 149}, {{241, 0, 0, 0, 0, 0, 0, 52, 47, 191, 223, 194, 185, 84, 255, 51}, 149}, {{241, 0, 0, 0, 0, 0, 91, 115, 80, 72, 124, 184, 163, 35, 247, 74}, 149}, {{241, 0, 0, 0, 0, 208, 191, 170, 218, 186, 35, 2, 244, 117, 137, 48}, 149}, {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 247}, 149}, {{241, 0, 0, 0, 0, 0, 0, 97, 211, 121, 217, 183, 66, 62, 216, 36}, 149}, {{241, 0, 0, 0, 0, 0, 207, 253, 150, 58, 80, 126, 74, 158, 218, 224}, 149}, {{241, 0, 0, 0, 0, 0, 123, 187, 197, 220, 236, 210, 193, 87, 182, 97}, 149}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 16}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 90, 24}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 152}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 77}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 245}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 62}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 245}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 175}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 142, 72}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 73, 37}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 145}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 220}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 31, 155}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 133, 177}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 188}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 33}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 67, 117}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 6}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 115}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 13, 9}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 112}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 251}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 235}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 31}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 242, 33}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 159}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 122}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 205}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 66}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 150, 195}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 218}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 61}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 66}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 148}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 191}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 76}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 206}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 87}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 84}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 159, 91}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 132, 56}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 61}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 155, 250}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 204}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 229}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 165}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 43}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 113, 221}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 235, 216}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 188}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 199}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 184, 201}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 162}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 142, 19}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 144, 132}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 43}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 181}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 95, 199}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 38}, 131}, {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 131}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 133}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 95}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 115, 93}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 245}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 167, 190, 11, 14}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 66, 115}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 10, 184, 246}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 112}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 18, 77, 199}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 173, 186, 24}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 115, 136, 100}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 32}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 41, 103, 30, 202}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 228, 113, 161}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 144}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 102, 224, 224}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 187, 178, 115}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 155, 69}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 197, 145, 47, 5}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 6}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 78}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 48, 73, 38, 7}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 91, 101, 198}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 134}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 121, 23, 218, 128}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 10, 161, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 198}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 80, 60}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 144, 18, 144, 119}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 189, 225, 154, 140}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 21}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 133}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 6, 192, 191, 38}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 75, 12, 138}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 36, 231}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 106}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 232, 79, 76}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 228, 90, 253, 5}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 121, 40, 248}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 131}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 182}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 20, 48}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 73}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 134, 102, 239}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 244, 72, 234, 221}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 229, 176}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 195, 5, 134, 11}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 160}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 104, 85, 65, 190}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 227, 205, 61}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 67}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 248, 152, 85, 218}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 246}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 89, 173, 152}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 40, 185, 152, 78}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 201, 59, 126, 30}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 25, 184, 16}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 62}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 103, 150, 239, 88}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 73, 201, 241}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 215}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 88}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 219, 222}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 11, 79}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 231, 245, 231}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 99, 43, 121, 74}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 110}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 129, 196, 230}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 100, 200}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 91, 45, 247, 116}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 84, 176, 134, 181}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 4, 82, 9, 31}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 207, 228, 180, 38}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 159, 201, 117}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 222, 147, 50}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 43, 196, 116, 62}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 201}, 33}, {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 188, 209, 122, 115}, 33}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 77, 136}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 107, 161, 131, 67, 173, 190}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 131}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 182, 14, 203, 253}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 7, 87, 46, 87, 236, 93, 32}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 108, 105, 188, 75, 65, 11, 133, 56}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 3}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 71, 61}, 204}, {{54, 25, 70, 80, 0, 0, 148, 255, 240, 160, 182, 39, 228, 228, 138, 134}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 204}, {{54, 25, 70, 80, 0, 15, 146, 207, 14, 243, 210, 239, 106, 234, 199, 178}, 204}, {{54, 25, 70, 80, 0, 0, 0, 198, 119, 125, 58, 11, 114, 205, 154, 148}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 7, 57, 69, 115, 27, 63}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 16}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 232, 137, 49, 36, 97, 70, 220, 173}, 204}, {{54, 25, 70, 80, 0, 0, 85, 94, 214, 229, 46, 138, 7, 24, 244, 77}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 171, 199, 15, 194, 135, 127, 156, 205}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 124, 184, 4, 245, 53, 60, 21, 110}, 204}, {{54, 25, 70, 80, 0, 0, 0, 40, 98, 26, 226, 4, 75, 61, 65, 57}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 230, 127, 105, 181, 216, 217, 116}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 69, 124, 81, 209, 35, 229, 90}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 19, 199}, 204}, {{54, 25, 70, 80, 0, 0, 25, 56, 106, 36, 172, 53, 9, 250, 157, 143}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 204}, {{54, 25, 70, 80, 0, 0, 0, 243, 186, 77, 240, 17, 234, 145, 126, 52}, 204}, {{54, 25, 70, 80, 0, 54, 24, 50, 176, 138, 113, 247, 227, 181, 147, 73}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 12, 115, 38, 230, 20}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 155, 30, 22, 57, 96, 168, 49, 25}, 204}, {{54, 25, 70, 80, 0, 0, 53, 53, 96, 45, 46, 161, 222, 185, 211, 90}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 224, 174}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 147, 105, 11, 180, 63, 114, 150, 150, 114, 99}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 90, 23, 144, 163}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 136, 108, 161, 39, 17, 201, 197, 70}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 169}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 127, 114, 42, 61, 122}, 204}, {{54, 25, 70, 80, 0, 0, 0, 230, 172, 140, 19, 208, 207, 132, 97, 196}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 179, 163, 31, 212}, 204}, {{54, 25, 70, 80, 157, 187, 90, 236, 226, 105, 167, 86, 35, 179, 131, 75}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 77, 132}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 54, 122}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 177, 203, 40, 187, 138, 216, 207}, 204}, {{54, 25, 70, 80, 0, 0, 103, 40, 161, 228, 33, 97, 9, 242, 201, 38}, 204}, {{54, 25, 70, 80, 0, 0, 0, 69, 202, 104, 90, 158, 122, 71, 90, 39}, 204}, {{54, 25, 70, 80, 0, 0, 0, 144, 30, 126, 77, 95, 162, 6, 197, 95}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 21, 157, 188, 89, 231, 184, 112}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 52, 203, 132, 133, 225}, 204}, {{54, 25, 70, 80, 0, 181, 90, 148, 142, 215, 198, 95, 97, 240, 212, 179}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 106, 67, 207, 89}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 48, 145}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 210}, 204}, {{54, 25, 70, 80, 0, 0, 72, 144, 231, 104, 45, 71, 109, 207, 179, 90}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 39}, 204}, {{54, 25, 70, 80, 0, 0, 190, 87, 21, 76, 214, 12, 116, 103, 153, 151}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 240, 26, 148, 142, 136, 225, 63, 113}, 204}, {{54, 25, 70, 80, 0, 0, 0, 130, 95, 129, 138, 70, 24, 25, 101, 233}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 86, 180, 133, 60, 69}, 204}, {{54, 25, 70, 80, 0, 0, 5, 162, 238, 28, 199, 0, 134, 85, 239, 36}, 204}, {{54, 25, 70, 80, 0, 34, 186, 48, 185, 226, 91, 84, 157, 196, 3, 151}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 217, 79, 132, 129}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 75, 89, 55, 134, 71, 201, 139, 218}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 125, 64, 210, 148}, 204}, {{54, 25, 70, 80, 0, 0, 0, 221, 62, 79, 243, 12, 135, 64, 217, 113}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 70, 229, 12, 174, 206, 180, 250, 75}, 204}, {{54, 25, 70, 80, 173, 21, 156, 215, 109, 147, 13, 1, 74, 155, 179, 81}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 215, 18, 70, 150, 215, 40, 35}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 224, 254, 116, 240, 188}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 222, 210, 22, 219, 235, 77, 159, 188}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 150, 2, 7, 201, 104, 121, 127, 79}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 207, 233, 233, 48, 232, 179}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 204}, {{54, 25, 70, 80, 0, 157, 225, 142, 240, 112, 14, 203, 208, 55, 182, 177}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 167, 2, 86, 202, 245, 21}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 9, 231, 168, 196, 57, 45, 245}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 241, 194}, 204}, {{54, 25, 70, 80, 0, 0, 5, 5, 208, 91, 17, 23, 0, 91, 11, 156}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 200, 23, 42, 20}, 204}, {{54, 25, 70, 80, 67, 85, 94, 138, 45, 57, 246, 200, 8, 100, 26, 106}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 207, 39}, 204}, {{54, 25, 70, 80, 0, 0, 0, 142, 58, 204, 150, 196, 28, 217, 248, 104}, 204}, {{54, 25, 70, 80, 0, 0, 223, 66, 244, 121, 82, 52, 10, 170, 234, 177}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 129, 111, 254, 111, 218, 54, 110}, 204}, {{54, 25, 70, 80, 0, 0, 55, 167, 21, 195, 106, 87, 166, 242, 66, 204}, 204}, {{54, 25, 70, 80, 0, 0, 0, 138, 161, 6, 152, 59, 16, 24, 100, 22}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 173, 161, 155, 103, 47, 61}, 204}, {{54, 25, 70, 80, 0, 0, 0, 184, 222, 202, 132, 188, 46, 146, 179, 77}, 204}, {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 128}, 204}, {{54, 25, 70, 80, 50, 71, 241, 226, 23, 197, 211, 11, 52, 145, 48, 233}, 204}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 124, 141, 227, 93}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 220, 3, 147, 46, 185, 212, 176, 67}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 26, 125, 118, 123, 37, 201}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 25, 180, 130, 87, 198, 198}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 248, 140}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 56, 44, 196, 211}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 66, 236, 137}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 129, 114}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 252, 84, 89, 97, 91, 47}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 13, 56, 242, 100, 198, 83}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 100, 203, 238, 81, 188}, 43}, {{149, 211, 242, 14, 112, 219, 176, 29, 180, 97, 47, 153, 110, 102, 6, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 133, 190, 239, 28}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 248, 222, 233, 13}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 183, 229, 214, 210, 45, 203, 10}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 242, 223, 249, 117, 221, 211}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 119, 219, 163, 193, 174, 92, 42, 160}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 67, 220, 214, 92, 167, 219}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 183, 48, 231}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 70, 159, 91, 26, 110, 172, 231, 190}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 125, 234, 200, 134, 239, 42}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 46, 120}, 43}, {{149, 211, 242, 14, 112, 219, 176, 118, 9, 17, 197, 35, 4, 189, 115, 96}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 110, 140, 198, 201, 211, 226, 128, 90}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 83, 56, 194, 76, 116, 191}, 43}, {{149, 211, 242, 14, 112, 219, 176, 157, 183, 110, 156, 64, 255, 97, 131, 67}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 237, 174, 189, 165, 41, 32, 8, 209}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 111, 164, 152, 10, 215, 204, 14, 252, 85}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 173, 161, 46, 210, 67, 90, 71, 152}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 28, 168, 74, 156, 240}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 165, 115, 158, 166, 171, 43, 37, 124}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 161, 217, 27}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 40, 113, 196}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 160, 139}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 160, 136, 168, 0, 35, 223, 24, 54}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 70, 14, 20, 234, 200}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 135, 143, 57}, 43}, {{149, 211, 242, 14, 112, 219, 176, 5, 210, 228, 136, 180, 238, 45, 182, 207}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 179, 225, 200, 99, 229}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 126, 17, 221, 111}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 107, 10, 28, 218, 206}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 61, 89, 203}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 226, 90, 188, 98, 241, 95, 83, 135}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 234, 152, 155}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 84, 58, 241, 72, 125, 147, 242}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 41, 8, 125, 196, 106, 131, 146, 7}, 43}, {{149, 211, 242, 14, 112, 219, 176, 150, 105, 75, 245, 57, 181, 86, 203, 202}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 56, 154, 143, 235}, 43}, {{149, 211, 242, 14, 112, 219, 176, 89, 93, 224, 248, 156, 183, 79, 73, 214}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 99, 6, 61, 144, 90, 99}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 60, 70, 142, 61, 26, 6, 17}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 45, 132}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 137, 255, 99, 112}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 194, 155, 216, 233, 88}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 156, 18, 104, 173, 174}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 71, 94, 231, 112, 206, 131, 36}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 127, 40, 191, 60}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 104, 135, 141, 108, 219, 187, 168}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 1, 226, 216, 94, 244, 70, 179, 39}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 199, 18}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 17, 65, 46, 222, 167, 26, 96}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 61, 15, 173}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 80, 237}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 225, 206, 125, 124, 15, 144}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 121, 158, 241, 159, 93, 125}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 175, 143, 80, 152}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 95, 250, 132, 169, 233, 68}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 67, 144, 161, 204, 92, 255}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 234, 46, 47, 236, 239, 41, 121}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 176, 165, 191, 41, 143, 253}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 52, 65, 100, 133, 60, 255, 183}, 43}, {{149, 211, 242, 14, 112, 219, 176, 31, 176, 71, 49, 175, 96, 241, 70, 164}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 101, 99, 150}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 190, 4, 10, 160, 144}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 39, 146, 3, 84, 17, 46}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 59, 41, 132, 44}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 152, 46, 62, 230, 133, 48, 12, 215}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 76, 181, 75, 1, 147, 155, 190}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 192, 112, 110}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 198, 252}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 89, 98, 88, 193}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 215, 180, 218, 77}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 220, 145, 192, 55, 144, 32, 100}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 242, 5, 234}, 43}, {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 43}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 200, 10, 128, 254, 173, 200, 4, 12}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 100, 210, 248, 243, 8}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 65, 98, 20}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 38, 13, 79, 183, 22, 44}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 153, 128, 175, 2, 189, 140, 99, 45}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 196, 41, 116, 161}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 80, 183, 139, 102, 252, 119}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 222, 85, 87, 34, 196, 70, 37, 129}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 78, 25, 46, 67, 222, 229, 123}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 23, 243, 34}, 168}, {{95, 26, 143, 193, 8, 76, 64, 91, 165, 168, 117, 247, 62, 171, 21, 131}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 176, 176, 44, 167}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 94, 8, 176, 15, 209, 9, 157}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 143, 53, 250, 43, 16}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 107, 108, 90, 58, 185, 8, 105}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 75, 227, 225, 21, 79}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 51, 14, 57}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 24, 18, 54, 23, 30, 81, 110}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 120, 96, 153, 120}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 232, 33, 159, 66, 82, 6, 66, 28}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 157, 117}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 79, 232, 90, 186}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 124, 34, 222, 150, 52, 238}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 229, 65, 215, 38, 16, 232, 95}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 234, 161, 44, 42, 169, 126, 181, 230, 200}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 89, 209, 29}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 207, 203, 125, 92}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 46, 165, 27, 150}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 73, 252, 21, 240, 84}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 3, 242, 202, 88, 138, 189, 153, 228}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 114, 29, 98, 117, 254, 242, 244}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 224, 111, 51, 171}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 168, 31}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 218, 186, 198, 173, 27}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 59, 156, 211, 201, 83, 140}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 89, 248, 120, 225}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 162, 1, 112, 37}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 132, 48, 148, 149, 238, 228}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 121, 219, 254, 166, 44, 142, 28}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 206, 235, 26, 41, 191, 111, 93, 7}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 251, 92, 216, 78, 203, 44}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 60, 152, 77, 12, 138, 88}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 119, 43, 82, 195, 9, 1, 216, 48}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 63, 40}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 159, 211, 108}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 145, 86, 72, 235}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 209, 239, 3, 80, 231, 115}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 179, 221, 83}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 243, 81, 158}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 90, 121, 11, 176, 104}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 169, 159, 220, 20, 24, 128, 227, 45}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 250, 149, 180, 184, 207, 251, 64}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 26, 173, 211, 57, 82, 230, 109}, 168}, {{95, 26, 143, 193, 8, 76, 64, 99, 84, 160, 246, 144, 43, 7, 200, 55}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 90, 52, 10, 89, 76, 245, 93, 138}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 234, 234}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 86, 222}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 184, 58, 45, 8}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 122, 178, 172, 248, 16, 226, 193, 163}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 206, 150}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 145, 229, 246, 2}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 136, 113, 199, 233, 195, 79}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 19, 81, 70, 111, 254, 171, 22}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 188, 165, 207, 194, 115, 135, 119}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 49, 177, 58, 64}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 106, 202, 14, 10}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 79, 169, 167, 92, 168, 122, 79, 193}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 83, 209, 87, 64, 217, 147, 45, 174, 26}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 203, 145}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 66, 67, 211, 104, 236, 175}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 148, 236, 41, 112, 94, 4, 143, 218}, 168}, {{95, 26, 143, 193, 8, 76, 64, 84, 66, 117, 183, 248, 94, 198, 141, 46}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 65, 167, 121, 221, 96, 146, 242, 135}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 168}, {{95, 26, 143, 193, 8, 76, 64, 189, 18, 12, 24, 4, 51, 104, 225, 145}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 143, 102, 187, 243, 228, 124, 97}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 212, 93, 145, 202, 132}, 168}, {{95, 26, 143, 193, 8, 76, 64, 24, 123, 196, 113, 128, 197, 65, 90, 29}, 168}, {{95, 26, 143, 193, 8, 76, 64, 0, 0, 1, 249, 64, 169, 130, 35, 198}, 168}, {{63, 102, 244, 176, 0, 0, 0, 0, 166, 192, 32, 214, 117, 193, 138, 56}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 214, 170, 167, 90}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 246, 244, 171, 191, 186, 84}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 54, 77, 138, 236}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 77}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 180}, {{63, 102, 244, 176, 0, 175, 159, 46, 198, 83, 63, 11, 17, 105, 94, 46}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 18, 79}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 81, 43, 103, 160}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 211, 35}, 180}, {{63, 102, 244, 176, 0, 0, 233, 22, 81, 70, 11, 69, 132, 28, 139, 182}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 52, 68, 247, 221, 179, 121, 100}, 180}, {{63, 102, 244, 176, 207, 220, 242, 22, 179, 184, 166, 41, 106, 136, 175, 93}, 180}, {{63, 102, 244, 176, 0, 147, 193, 229, 149, 13, 0, 251, 21, 45, 45, 82}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 57, 99, 112, 248, 244, 141}, 180}, {{63, 102, 244, 176, 2, 233, 220, 134, 198, 130, 9, 95, 75, 115, 186, 151}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 8}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 180}, {{63, 102, 244, 176, 235, 255, 241, 131, 142, 173, 57, 102, 160, 69, 35, 119}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 161, 212, 94, 82, 62, 72, 151, 249}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 70, 135, 162, 222, 64}, 180}, {{63, 102, 244, 176, 0, 0, 225, 59, 65, 216, 197, 18, 115, 74, 126, 38}, 180}, {{63, 102, 244, 176, 0, 0, 22, 160, 116, 85, 146, 81, 78, 142, 176, 33}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 81}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 100, 182}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 180}, {{63, 102, 244, 176, 0, 0, 0, 202, 213, 232, 229, 47, 20, 29, 8, 188}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 185, 19, 96, 165, 119, 43, 165}, 180}, {{63, 102, 244, 176, 0, 0, 108, 96, 170, 243, 160, 26, 242, 242, 226, 228}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 175, 106}, 180}, {{63, 102, 244, 176, 131, 110, 109, 207, 169, 76, 92, 122, 123, 183, 237, 98}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 18, 45, 197, 251, 221, 3}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 14}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 5, 206}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 163, 114, 87, 251, 160, 36, 101}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 146, 43, 176, 188}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 93, 201}, 180}, {{63, 102, 244, 176, 0, 102, 23, 154, 157, 181, 162, 146, 236, 60, 154, 161}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 83, 126, 174, 140, 211}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 216}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 119, 82, 155, 54, 155, 239, 247, 243}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 204}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 141, 250, 251, 236, 76, 162, 78, 57}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 143, 34, 255, 158, 213, 208}, 180}, {{63, 102, 244, 176, 0, 0, 98, 155, 62, 94, 42, 100, 200, 65, 12, 155}, 180}, {{63, 102, 244, 176, 0, 0, 77, 163, 216, 200, 79, 242, 188, 138, 152, 167}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 153, 21, 26, 0, 202, 123}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 87, 105, 184, 240, 195, 107, 153}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 16, 7, 27, 130}, 180}, {{63, 102, 244, 176, 0, 0, 203, 180, 222, 112, 134, 160, 138, 159, 68, 122}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 223, 117, 65, 213}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 40, 16, 21, 242, 131, 252}, 180}, {{63, 102, 244, 176, 0, 0, 0, 192, 22, 68, 227, 125, 37, 207, 156, 7}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 148, 137, 175, 165, 138, 90}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 85, 252, 66, 38, 201, 128}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 106, 122, 221, 112, 176, 149}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 24}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 14, 193, 246, 72, 243, 144, 178, 88}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 82, 242, 218, 50, 221, 92}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 147, 89, 2, 181}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 219, 143, 110, 253, 170, 1, 27}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 180}, {{63, 102, 244, 176, 34, 117, 166, 57, 54, 89, 134, 248, 62, 214, 232, 105}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 233, 223, 146, 204, 51, 99}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 91}, 180}, {{63, 102, 244, 176, 0, 0, 0, 18, 87, 244, 41, 197, 179, 57, 198, 251}, 180}, {{63, 102, 244, 176, 0, 195, 177, 117, 96, 69, 7, 202, 9, 249, 177, 255}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 144, 113, 5, 195}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{63, 102, 244, 176, 0, 0, 106, 155, 158, 134, 192, 10, 45, 244, 63, 67}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 205, 81, 223, 216, 239}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 94}, 180}, {{63, 102, 244, 176, 248, 128, 176, 121, 93, 74, 85, 30, 9, 157, 191, 107}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 32, 52, 50, 208}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 74, 190, 115, 120, 47, 54, 19}, 180}, {{63, 102, 244, 176, 0, 0, 0, 88, 20, 17, 170, 11, 50, 9, 10, 154}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 180}, {{63, 102, 244, 176, 135, 187, 1, 60, 215, 93, 237, 131, 98, 59, 179, 180}, 180}, {{63, 102, 244, 176, 0, 175, 22, 94, 172, 99, 48, 54, 150, 131, 164, 107}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 135, 228, 184, 99, 138}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 114, 250, 197, 113, 206, 203, 103}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 4, 42}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 38}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 193, 9, 164, 16, 232, 123, 150}, 180}, {{63, 102, 244, 176, 0, 0, 73, 118, 230, 15, 116, 202, 8, 45, 120, 57}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 244, 27, 132, 76, 92}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 2, 93, 177, 64}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 183, 90, 194, 236, 170}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 183, 110, 162, 36, 175, 49, 147}, 180}, {{63, 102, 244, 176, 12, 137, 176, 217, 37, 4, 174, 222, 115, 169, 36, 90}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 180}, {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 86, 251, 53, 69, 206, 120}, 180}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 39}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 78}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 252}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 19}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 207}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 158}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 145}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 12}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 12}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 220}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 47}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 51}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 105}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 117}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 143}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 169}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 60}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 112}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 48}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 173}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 32}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 56}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 46}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 78}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 116}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 119}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 224}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 68}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 7}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 107}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 223}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 204}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 42}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 77}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 249}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 220}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 77}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 139}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 215}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 126}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 136}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 73}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 173}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 221}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 12}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 194}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 30}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 28}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 208}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 205, 138, 56}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 68, 16}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 113, 125}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 244, 99, 140, 227}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 67, 237}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 241, 26, 196, 80}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 7, 81, 50}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 10, 59, 36, 70}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 223, 229}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 83, 22}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 204, 233, 162}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 125}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 94, 249, 114}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 246, 69, 126}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 12, 5, 23}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 13, 15, 83}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 254, 201}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 175, 139, 215, 250}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 162, 213, 80}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 126, 120}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 84}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 174, 58}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 53, 163}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 78, 227, 120, 209}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 17, 23, 50, 52}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 130}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 147}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 188}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 247}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 193, 142, 198, 47}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 135, 193}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 116, 48, 59, 130}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 9}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 133, 9}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 142, 130}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 7, 236, 146}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 150, 239, 250, 248}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 249, 233}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 170, 73}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 183, 251, 208, 250}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 88}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 59, 62}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 144, 151, 227}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 159, 248, 67, 218}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 121, 92}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 63, 174, 38}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 185, 238, 204, 41}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 87, 80, 162, 82}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 194, 83, 116, 199}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 110, 76, 31, 192}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 211}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 87, 108}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 173}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 203}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 176, 98, 103, 8}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 124, 18, 155, 109}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 11, 27, 26}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 199}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 221, 63, 97}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 152, 244, 131}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 52, 120, 211}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 234}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 160}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 142, 169}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 2, 229, 189, 105}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 8}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 114, 26, 186}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 95, 60}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 50}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 182}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 24, 55, 6}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 227, 146, 181}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 120}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 124}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 253, 78, 72}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 90, 135, 127, 25}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 111, 128}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 25}, {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 147, 168}, 25}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 103}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 22}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 143}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 164}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 202}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 62}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 152}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 150, 14}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 39}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 47}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 44, 240}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 200}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 183}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 150}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 105}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 164}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 61}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 72}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 26}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 187}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 203, 113}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 193}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 18}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 251}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 247}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 166}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 233}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 22}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 159}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 78}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 117}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 168}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 192}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 87}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 153}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 35}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 190}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 19}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 187}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 153}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 7}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 49, 242}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 135}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 210}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 96}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 141}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 12}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 5}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 106}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 88}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 124}, 50}, {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 88}, 50}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 70}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 249}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 175, 227}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 201}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 201}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 143, 180}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 99}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 44}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 214}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 24, 99}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 231}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 234, 121}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 150}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 53, 127}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 210}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 242}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 59}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 94}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 92, 230}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 134}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 140}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 13}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 225}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 142}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 57}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 71}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 92, 221}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 243}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 200}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 136}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 13}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 181, 210}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 104}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 91}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 246}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 168, 145}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 86}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 9}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 27}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 88}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 15, 138}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 24, 233}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 55}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 117}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 192}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 106}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 239}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 146}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 225}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 71}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 94}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 72}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 250, 13}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 230, 96}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 62}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 158}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 113}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 222}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 156}, 110}, {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 76, 18}, 110}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 115}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 4, 182}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 156}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 171}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 104}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 56, 247}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 31}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 234}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 98}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 47, 249}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 31}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 204}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 31, 197}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 137, 95}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 118}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 179, 10}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 201}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 200}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 186, 141}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 203}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 118, 167}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 4}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 214}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 168, 6}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 202}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 234}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 131}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 52}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 254}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 135, 49}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 194, 252}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 11}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 143, 155}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 81}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 184, 71}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 79}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 49}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 228}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 52, 228}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 104}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 103}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 107}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 186}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 225}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 30}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 79, 192}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 54}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 235}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 126, 141}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 179}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 55}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 176}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 95}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 61}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 108}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 206}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 85}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 17}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 235}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 78}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 45, 86}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 225}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 128, 196}, 21}, {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 23}, 21}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 84}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 223, 121, 251, 66, 221, 38, 205, 25}, 147}, {{136, 77, 164, 161, 192, 0, 101, 128, 233, 130, 108, 39, 124, 123, 131, 43}, 147}, {{136, 77, 164, 161, 192, 0, 0, 9, 96, 41, 71, 54, 6, 230, 85, 170}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 187, 211, 30, 121, 155}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 185, 90, 39, 26, 252, 222, 78, 139}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 47, 56, 134, 48, 175, 159, 178}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 81, 23, 49, 99, 206, 148, 255, 84}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 193, 248, 247}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 175, 18, 108, 55, 45}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 68, 247, 164, 138, 110}, 147}, {{136, 77, 164, 161, 192, 77, 209, 147, 245, 129, 114, 28, 10, 253, 170, 8}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 183}, 147}, {{136, 77, 164, 161, 192, 0, 233, 100, 135, 197, 159, 236, 83, 65, 191, 226}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 242, 251, 254, 198}, 147}, {{136, 77, 164, 161, 192, 0, 219, 211, 251, 93, 65, 146, 116, 219, 146, 220}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 200, 229, 153, 151, 153}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 14, 90, 232, 15, 173, 255}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 208, 92, 233, 248, 156, 249}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 141, 114, 138, 104}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 185, 125, 16, 151, 210, 159}, 147}, {{136, 77, 164, 161, 192, 0, 0, 119, 255, 81, 14, 200, 61, 255, 155, 138}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 69, 231, 203, 132, 78, 173}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 124}, 147}, {{136, 77, 164, 161, 192, 0, 175, 76, 48, 129, 123, 121, 44, 127, 190, 230}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 35, 207, 217}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 42, 179, 116, 231}, 147}, {{136, 77, 164, 161, 192, 36, 228, 79, 129, 55, 27, 77, 113, 15, 179, 142}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 186, 187, 86, 151, 122, 187, 195, 112, 172}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 176, 27, 130, 228, 15, 67}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 22, 131, 48, 213, 107}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 94, 158, 145}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 174, 198, 251, 181, 68, 232, 217}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 164, 106, 82, 1}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 130, 24, 124, 243, 170, 236}, 147}, {{136, 77, 164, 161, 192, 0, 0, 151, 79, 10, 48, 140, 213, 134, 69, 196}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 216, 231, 185, 60, 157, 196, 232, 153, 65, 153, 130}, 147}, {{136, 77, 164, 161, 192, 196, 2, 43, 108, 203, 108, 151, 123, 87, 91, 73}, 147}, {{136, 77, 164, 161, 192, 0, 65, 146, 168, 130, 4, 128, 54, 167, 63, 60}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 222, 138, 149, 168, 205}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 171}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 167, 246, 189, 131}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 155, 92, 68, 185}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 122, 155, 70, 223, 163, 200}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 85, 224, 36, 166, 10}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 71, 19, 191}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 116, 187, 3, 233, 61, 153, 236, 128}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 95, 136, 167, 197, 225, 215, 129}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 59, 10, 234}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 40, 168, 37, 113, 182}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 60, 39, 27, 147}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 46}, 147}, {{136, 77, 164, 161, 192, 0, 207, 61, 153, 122, 10, 89, 243, 213, 54, 187}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 59, 96, 176, 75}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 99, 38, 115, 8, 7, 20, 179}, 147}, {{136, 77, 164, 161, 192, 18, 20, 19, 217, 237, 126, 131, 91, 227, 151, 185}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 180, 117, 22, 21, 79, 253}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 69, 81, 34, 239}, 147}, {{136, 77, 164, 161, 192, 0, 0, 136, 152, 191, 65, 132, 123, 113, 215, 121}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 22, 175, 28, 135, 252}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 33}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 220, 171, 117, 46, 127, 195, 223, 197}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 61, 249, 218, 61, 132, 108, 14}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 183, 171, 204, 69, 223, 87, 82}, 147}, {{136, 77, 164, 161, 192, 164, 232, 123, 150, 114, 196, 92, 21, 14, 168, 183}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 89, 186, 182}, 147}, {{136, 77, 164, 161, 192, 0, 134, 118, 121, 74, 70, 40, 116, 7, 191, 112}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 68, 235, 84}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 210, 242, 103, 156, 210}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 196, 1, 11}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 220, 252, 226}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 93, 87, 157, 195, 6, 56, 7, 64}, 147}, {{136, 77, 164, 161, 192, 0, 193, 116, 100, 140, 207, 153, 160, 176, 198, 167}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 97, 229, 75}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 211}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 47, 88, 166, 101}, 147}, {{136, 77, 164, 161, 192, 0, 0, 174, 124, 134, 151, 127, 203, 24, 190, 89}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 41, 93, 29, 97, 56, 146}, 147}, {{136, 77, 164, 161, 192, 0, 82, 34, 176, 91, 250, 201, 160, 180, 54, 86}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 147}, {{136, 77, 164, 161, 192, 173, 15, 127, 15, 10, 167, 243, 42, 138, 75, 219}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 85, 61, 54, 162, 165, 32, 48, 6}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 190, 21, 114}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 0, 208, 60, 149, 231, 244, 135, 232}, 147}, {{136, 77, 164, 161, 192, 0, 0, 0, 179, 8, 29, 254, 213, 176, 100, 134}, 147}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 44, 101, 237}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 255, 140, 232, 250, 171, 181, 116}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 105, 188, 130}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 157, 80, 190, 125, 42, 96}, 56}, {{1, 33, 66, 254, 144, 128, 0, 140, 177, 141, 70, 106, 47, 110, 147, 138}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 45, 133, 240, 181, 15, 80}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 231, 57, 172, 16, 23, 170}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 117, 140}, 56}, {{1, 33, 66, 254, 144, 128, 126, 186, 131, 174, 177, 181, 254, 170, 135, 159}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 207, 62, 158, 2}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 237, 90, 70, 134}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 195, 37, 49}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 129, 209, 35, 234, 251, 216, 148}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 127, 110, 255, 14}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 108, 53, 74, 2}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 234, 143, 8, 49, 236, 27, 139}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 201, 165, 205, 199, 220}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 243, 7, 215, 151, 197, 17}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 82, 78}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 32, 40, 166, 166, 84, 10, 170, 54}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 56}, {{1, 33, 66, 254, 144, 128, 0, 29, 222, 193, 147, 22, 170, 241, 10, 212}, 56}, {{1, 33, 66, 254, 144, 128, 0, 106, 54, 2, 255, 117, 18, 204, 21, 78}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 26, 131, 156}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 214, 224}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 189, 134, 206, 229}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 231, 122, 9, 108, 216, 146, 155, 90, 52, 104}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 93, 223, 175, 47, 41, 104, 104}, 56}, {{1, 33, 66, 254, 144, 128, 0, 59, 207, 127, 64, 85, 159, 247, 226, 218}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 176, 196, 236, 219, 141, 29, 165}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 85, 177, 15, 40, 80, 114, 227, 195}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 41, 231, 0, 255, 118, 87, 123, 140}, 56}, {{1, 33, 66, 254, 144, 128, 243, 118, 8, 131, 136, 253, 109, 59, 213, 136}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 142, 202, 26}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 76, 99}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 129, 177}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 180, 170, 236, 8}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 89, 96, 246, 33}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 128, 245, 122, 73, 175, 110}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 251, 15, 13, 176, 49, 249, 176}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 51, 62, 113, 38}, 56}, {{1, 33, 66, 254, 144, 128, 15, 248, 103, 247, 90, 138, 114, 185, 243, 79}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 147, 15, 71}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 50, 179, 254, 173, 10}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 56, 220, 136, 50, 1, 124, 63, 20, 48}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 56}, {{1, 33, 66, 254, 144, 128, 20, 169, 120, 72, 64, 172, 184, 3, 8, 109}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 76, 228}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 44, 63}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 13, 90, 190, 159, 41, 65, 37}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 93, 117, 191, 32, 169, 103, 219}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 242, 184, 123, 181, 173}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 115, 179, 184, 158, 71, 71}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 27, 227, 55, 35, 108, 233, 155}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 38, 45, 3, 211, 125, 40, 240, 180}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 14, 10, 117, 222, 250, 225, 112}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 243, 218, 115}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 40, 174, 165, 163, 163, 170, 16}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 41, 200, 141, 23}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 136, 34, 12, 92, 180, 35, 214, 188}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 184, 75}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 252, 205, 107}, 56}, {{1, 33, 66, 254, 144, 128, 0, 37, 4, 54, 29, 169, 200, 181, 203, 185}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 208, 112, 129}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 42, 213, 94, 231, 64, 178, 18, 63}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 193, 96, 35, 204}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 25, 85, 201}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 232, 129}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 164, 220, 115, 154}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 114, 105, 77, 156, 183}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 13, 135, 203}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 80, 237, 4, 159, 134, 157, 124}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 30, 146, 169}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 236, 137, 115, 137, 151, 218, 101, 247}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 191, 135, 28, 89, 56, 185, 47, 6}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 8, 11, 82, 23, 137, 247}, 56}, {{1, 33, 66, 254, 144, 128, 0, 1, 159, 235, 67, 120, 16, 116, 183, 73}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 60, 60, 180, 140, 213, 187}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 206, 99, 12}, 56}, {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 22}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 174}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 15}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 180}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 221}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 250}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 53}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 10}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 184}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 47}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 211}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 99}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 107}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 222}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 245}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 251}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 186}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 76}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 57}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 80}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 21}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 184}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 184}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 121}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 82}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 190}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 124}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 92}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 144}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 50}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 211, 22}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 21, 68, 210}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 118}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 113, 192}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 180, 245}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 108, 148, 163}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 205}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 66, 75}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 197}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 120, 153}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 15, 73, 208}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 248, 194, 95}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 112, 158}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 80, 177, 112}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 128}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 92, 207}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 76, 182}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 250, 47}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 167}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 232, 117}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 187, 116}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 137, 161}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 251, 1, 66}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 84}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 38}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 169}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 4, 24, 26}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 173}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 173, 1}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 158}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 164, 3, 151}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 226, 203}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 83}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 116, 156}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 108, 32}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 68, 36}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 134, 16}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 250}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 88}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 247}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 152, 48, 14}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 131, 240, 32}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 136, 202, 16}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 136, 182, 47}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 247}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 242, 157}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 91}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 224, 118}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 135, 37}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 100}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 187}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 80, 135, 47}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 111, 69}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 45, 78}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 72}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 116}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 72, 252, 166}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 6, 207}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 143, 72, 127}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 109}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 59}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 178}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 6}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 37, 203}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 100}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 70, 71}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 50, 37}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 31, 202}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 116}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 68}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 50, 73}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 201, 64}, 198}, {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 52, 1}, 198}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 63, 10, 255, 78}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 66, 231}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 120, 73, 132}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 176, 76, 86}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 183, 73, 246, 118}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 13, 92, 164}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 94, 103}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 76}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 81, 91, 77}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 68, 70, 51, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 95}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 183}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 125}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 109, 130}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 24}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 167, 99}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 111, 180, 26, 5}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 131, 195, 137, 215}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 101, 185}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 128, 97, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 207}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 44, 237}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 17, 103, 18}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 9, 63}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 149, 101, 60}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 185, 146, 177}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 173, 28}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 1, 29, 39, 1}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 16, 116}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 103, 125}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 192, 215, 53}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 19}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 214, 94, 22}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 165, 183}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 15, 55, 33, 67}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 138, 247, 85}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 99, 183, 120}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 59, 116}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 66, 185, 10, 4}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 245, 200, 204}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 224, 237}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 8, 135, 227, 115}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 116, 50, 87, 161}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 37, 91}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 94, 215, 237, 83}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 100}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 111, 135}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 178}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 143, 184}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 12}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 206, 57, 203, 35}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 68, 78}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 253, 162}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 121}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 45}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 42, 74, 66}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 126, 112}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 142, 217, 123}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 213, 208}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 181, 228, 235}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 216}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 156, 163, 104}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 82, 78, 218}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 174, 201, 19, 145}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 173, 113, 127, 33}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 209, 253}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 39, 73}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 196, 253}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 161, 20, 112, 109}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 241, 201, 69, 12}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 7, 164}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 39}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 68}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 250, 141, 145, 81}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 112, 227, 224}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 228, 169, 196}, 235}, {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 167, 5}, 235}, {{143, 226, 190, 50, 252, 0, 0, 223, 184, 242, 11, 163, 170, 154, 244, 46}, 105}, {{143, 226, 190, 50, 252, 0, 0, 72, 209, 22, 245, 198, 107, 197, 190, 141}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 252, 78, 134, 131, 156, 245}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 58, 162, 248, 110, 32, 113}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 41, 209, 132, 105}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 72, 112, 13, 104, 1, 57}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 30, 143, 60, 148}, 105}, {{143, 226, 190, 50, 252, 0, 0, 108, 227, 248, 96, 220, 76, 32, 233, 36}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51}, 105}, {{143, 226, 190, 50, 252, 0, 136, 150, 242, 6, 65, 225, 64, 158, 111, 235}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 186, 34, 232, 111, 134, 164}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 10}, 105}, {{143, 226, 190, 50, 252, 52, 60, 211, 214, 139, 102, 198, 78, 20, 53, 124}, 105}, {{143, 226, 190, 50, 252, 28, 155, 227, 2, 129, 50, 82, 183, 226, 233, 207}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 141, 86, 237, 214, 77, 149}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 2, 151, 196, 179, 136, 239}, 105}, {{143, 226, 190, 50, 252, 0, 0, 195, 181, 136, 57, 72, 221, 241, 72, 13}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 54, 69, 153, 227, 143, 187}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 110, 234, 149, 230, 230}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 220, 65, 196, 135, 138, 71}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 155, 73, 204}, 105}, {{143, 226, 190, 50, 252, 191, 242, 101, 122, 230, 58, 249, 73, 39, 188, 161}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 198, 19, 156, 78}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 17, 138, 115, 27, 49, 88, 99}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 123}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 62, 198, 120}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 105}, {{143, 226, 190, 50, 252, 0, 98, 159, 47, 174, 39, 251, 98, 96, 213, 18}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 58, 166, 200, 178, 108, 164, 121, 67}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 204, 115, 82, 191, 55, 149, 173}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 20, 26, 252, 125, 10, 144}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 235, 147, 150, 76, 195}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 238, 40, 15}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 75, 189, 70, 208, 102, 142, 238, 96}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 48, 76, 230, 174, 43, 129}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 176, 232, 189, 182}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 60}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 144, 68, 159}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 176}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 214}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 175, 162, 103, 28}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 118, 143, 69, 81, 50}, 105}, {{143, 226, 190, 50, 252, 0, 0, 42, 244, 159, 38, 41, 29, 214, 47, 99}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 242, 139, 61, 27}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 176, 120, 68}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 63, 41, 160}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 150}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 193}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 252, 212, 30, 159, 213}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 47, 2, 1, 16, 210, 180, 183, 42}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 53, 5, 57, 89, 70, 62, 236}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 91, 28, 204, 42}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 239, 189, 186, 92}, 105}, {{143, 226, 190, 50, 252, 0, 160, 128, 19, 24, 30, 200, 25, 179, 101, 123}, 105}, {{143, 226, 190, 50, 252, 0, 210, 226, 178, 131, 181, 209, 141, 92, 175, 125}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 30, 63, 199, 140, 243, 92, 101}, 105}, {{143, 226, 190, 50, 252, 0, 0, 172, 140, 188, 218, 69, 120, 24, 24, 185}, 105}, {{143, 226, 190, 50, 252, 0, 0, 10, 51, 68, 174, 186, 242, 52, 239, 154}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 84, 121, 18}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 85, 237, 244}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 7, 33, 68, 36, 102, 0, 161, 249}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 35, 133, 172}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 56, 187, 95, 85, 23}, 105}, {{143, 226, 190, 50, 252, 0, 0, 52, 165, 138, 220, 226, 81, 149, 61, 97}, 105}, {{143, 226, 190, 50, 252, 0, 0, 191, 143, 119, 197, 109, 183, 154, 46, 89}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 98, 76, 206, 17, 38, 199}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 200, 245, 21}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 65, 127, 72, 215, 98, 31}, 105}, {{143, 226, 190, 50, 252, 0, 51, 14, 46, 227, 250, 3, 195, 168, 230, 243}, 105}, {{143, 226, 190, 50, 252, 26, 237, 34, 53, 239, 250, 241, 86, 187, 141, 60}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 61, 200, 236, 137, 111, 156, 37}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 16, 240, 56}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 113, 85, 168, 162, 53, 181}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 67, 239, 215}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 143, 7, 44, 178, 199, 69, 113, 140}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 21, 91, 118, 166, 224}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 105, 72, 226, 155, 81}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 38, 21, 65, 226, 7}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 146, 71, 31, 3}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 126, 84, 193, 35, 163, 36}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 131, 81, 125, 100, 28, 47, 80, 102}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 105}, {{143, 226, 190, 50, 252, 0, 0, 0, 30, 154, 64, 0, 54, 8, 128, 77}, 105}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 77, 44, 102, 224, 175}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 174, 71, 167, 121, 29}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 205, 181, 141, 71, 196, 242}, 138}, {{65, 168, 226, 36, 201, 80, 0, 129, 228, 87, 153, 70, 212, 5, 73, 95}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 56, 87, 248, 226}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 70, 236, 214}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 104, 84, 11}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 90, 203, 161}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 99, 157, 181, 166, 205, 83, 29, 164}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 129, 250, 118, 243}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 79, 18, 25, 36}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 186, 254, 167, 178, 206, 4, 239, 82}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 15, 197, 117}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 106, 233, 161, 141, 246, 20, 125, 216}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 17, 146, 114, 33, 166}, 138}, {{65, 168, 226, 36, 201, 80, 124, 224, 178, 67, 118, 237, 138, 93, 191, 105}, 138}, {{65, 168, 226, 36, 201, 80, 0, 195, 78, 240, 176, 34, 53, 136, 138, 209}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 120, 40, 39}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 142, 192, 44, 61, 78, 195, 226}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 116, 126, 162, 165}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 135, 155, 63, 246}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 128, 111, 213, 113}, 138}, {{65, 168, 226, 36, 201, 80, 0, 94, 199, 138, 125, 113, 10, 38, 93, 60}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 71, 139, 107}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 218, 209, 61, 125, 224, 106}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 250, 55, 204, 90, 149, 188, 71, 250}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 41, 216, 57, 44, 151, 93, 98, 53}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 225, 116, 188, 15, 33, 118, 107}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 213, 219, 170, 111}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 167, 215}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 238, 15, 161, 133, 190, 209, 76, 202}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 59, 61, 31, 176}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 30, 115, 131, 109}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 130, 246}, 138}, {{65, 168, 226, 36, 201, 80, 0, 52, 45, 186, 181, 188, 119, 208, 87, 20}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 80, 244, 19}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 117, 48, 25, 229, 167, 89}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 96, 155, 223, 16, 117, 131, 77, 92}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 224, 157, 219, 40, 152, 201, 109}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 227, 183, 111}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 26, 152, 107, 141, 193, 114, 1, 169}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 23, 151, 188, 63}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 107, 165, 102, 22}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 25, 212, 183, 185, 213}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 19, 209, 15, 227, 191, 109, 203, 225}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 166, 84}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 193, 214, 197, 197}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 225, 210}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 75, 175, 150, 146, 63, 107, 200, 13}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 86, 142, 106, 183, 23, 238, 203, 81}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 182, 40, 208, 154}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 154, 181, 195, 156, 213, 65, 224}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 17, 86}, 138}, {{65, 168, 226, 36, 201, 80, 0, 72, 12, 253, 108, 238, 128, 76, 0, 182}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 35, 248, 238}, 138}, {{65, 168, 226, 36, 201, 80, 145, 32, 132, 9, 66, 158, 60, 215, 82, 38}, 138}, {{65, 168, 226, 36, 201, 80, 0, 218, 231, 130, 134, 85, 181, 126, 162, 196}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 159, 192, 168, 37, 247}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 70, 139, 18, 110}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 236, 136, 124, 174, 233, 96, 192, 233, 95}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 142, 210, 179, 63, 172, 221, 8, 161, 226}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 24, 30}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 132, 94, 171, 79, 18, 3, 63, 111}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 253, 202, 202, 161, 160, 40}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 62, 2}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 230, 249}, 138}, {{65, 168, 226, 36, 201, 80, 0, 205, 244, 169, 91, 254, 95, 129, 254, 95}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 246, 235}, 138}, {{65, 168, 226, 36, 201, 80, 0, 43, 133, 94, 57, 82, 35, 17, 242, 79}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 26, 166, 208, 146, 241, 44, 197}, 138}, {{65, 168, 226, 36, 201, 80, 159, 47, 193, 69, 57, 124, 90, 117, 215, 172}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 158, 202, 98, 171, 209}, 138}, {{65, 168, 226, 36, 201, 80, 0, 172, 203, 29, 208, 188, 143, 204, 255, 170}, 138}, {{65, 168, 226, 36, 201, 80, 0, 234, 155, 157, 39, 52, 238, 67, 28, 193}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 159, 39}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 49, 107}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 5, 34, 68, 228, 97, 20, 57, 69}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 207, 39, 104, 164, 210, 249, 41}, 138}, {{65, 168, 226, 36, 201, 80, 0, 0, 0, 152, 41, 147, 135, 224, 20, 30}, 138}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 24, 238, 223, 237, 246, 55}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 106, 44, 183, 152}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 2, 42}, 122}, {{136, 40, 65, 90, 47, 16, 128, 242, 169, 117, 156, 71, 23, 36, 89, 38}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 196, 152, 97, 149, 111}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 248, 1, 88, 243, 108, 39, 112}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 255, 126, 52, 96, 185, 233, 251}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 97, 167, 115, 161}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 91, 3, 30, 233, 100, 188}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 200, 40, 158, 86}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 161, 231, 169, 153, 64, 125, 255}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 195, 160, 237}, 122}, {{136, 40, 65, 90, 47, 16, 128, 55, 9, 158, 65, 246, 106, 203, 27, 187}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 87, 28, 252, 13, 203, 162}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 102, 35, 56, 213, 22, 71, 53, 209}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 98, 63, 161, 72, 70}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 51, 203, 215, 225, 125}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 82, 110}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 188, 142, 88}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 195, 98, 132}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 170, 155, 130}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 28, 233, 200, 166, 150, 88, 170, 216}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 27, 145, 240, 109}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 35, 156, 93, 4, 141, 175, 82, 211}, 122}, {{136, 40, 65, 90, 47, 16, 128, 106, 155, 156, 84, 121, 196, 3, 170, 140}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 243, 246, 166, 45}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 248, 40}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 209, 34, 161, 158, 219, 72, 245, 225}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 255, 48, 174, 241, 121}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 178, 131, 45, 217, 201, 59, 53, 190}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 161, 43, 245, 71, 174, 183, 4, 23}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 2, 38}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 142, 36, 126}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 212, 219, 169, 195}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 224, 245, 140, 176, 9, 76, 243, 68}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 149, 11, 181, 222, 136}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 134, 147, 161, 134, 57, 23, 144}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 62, 140, 72, 4, 165, 105, 222}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 200, 33, 66, 114}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 104, 116, 21, 140, 218, 181, 190, 244}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 173, 85, 223, 76, 72}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 70, 57, 89, 55}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 64, 210, 83, 142, 251, 242}, 122}, {{136, 40, 65, 90, 47, 16, 128, 241, 128, 125, 52, 211, 179, 15, 171, 29}, 122}, {{136, 40, 65, 90, 47, 16, 128, 52, 73, 126, 39, 199, 176, 87, 185, 140}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 140, 63, 97, 79, 196}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 195, 136, 171}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 196, 157, 69, 212, 121}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 96, 78, 185, 181}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 191, 124, 195, 91, 38, 124}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 60, 43, 184, 103, 133, 113, 96}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 156, 140, 227, 177}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 1, 192, 233, 155, 89}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 150, 135, 37, 134, 230, 27, 140, 96}, 122}, {{136, 40, 65, 90, 47, 16, 128, 82, 7, 203, 76, 171, 51, 186, 198, 86}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 102, 86}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 4, 77, 71, 148, 129, 131}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 165, 138}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 202, 14, 75, 111, 255, 69, 185}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 122}, {{136, 40, 65, 90, 47, 16, 128, 30, 239, 112, 192, 196, 32, 26, 235, 135}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 67, 242}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 43, 248, 172, 77, 29, 209}, 122}, {{136, 40, 65, 90, 47, 16, 128, 54, 3, 59, 64, 46, 76, 57, 168, 96}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 122}, {{136, 40, 65, 90, 47, 16, 128, 74, 7, 175, 237, 140, 11, 32, 101, 121}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 221, 221, 246, 31, 216, 137, 39}, 122}, {{136, 40, 65, 90, 47, 16, 128, 56, 59, 115, 160, 191, 239, 209, 29, 87}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 51, 64, 210}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 173, 196}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 99, 67, 180, 203, 182}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 48, 76, 54, 45, 61, 86, 141, 26}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 41, 146}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 45, 193, 173, 99, 229, 10}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 217, 40, 144, 141, 116}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 222, 240, 212, 47, 71, 57}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 129, 20, 124, 242}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 16, 249, 221, 167, 199, 150, 89}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 140, 130, 161, 131}, 122}, {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 239, 244, 38, 127}, 122}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 51, 199, 230, 146, 13}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 34, 228, 3}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 38, 85, 93, 233, 26, 174, 103}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 70, 200}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 21, 245}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 195, 218, 73, 143}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 55, 153}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 241, 173, 22}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 254, 14, 187, 196, 114}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 44, 227, 236, 69, 110}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 229, 246}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 157, 132, 254, 25, 132}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 125}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 5, 186}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 176, 143, 28, 173, 190}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 241, 88, 248, 116, 221, 20}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 236, 34, 100, 242, 234}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 185, 224, 69, 78}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 78, 198, 84, 62}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 240, 255, 93, 218}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 60, 37, 122}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 169, 5, 162, 133, 14, 104}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 120}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 155, 176, 236, 170}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 109, 56, 97, 56, 238, 160, 220}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 223, 191, 207, 13, 129}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 83, 173, 72, 177, 116}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 149, 23, 69, 228, 240, 20, 87}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 26, 104, 81}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 3, 138, 219, 84, 144, 86}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 252, 111, 170, 106, 147, 31}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 112, 67, 248, 137, 52}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 57, 17, 6, 22, 126}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 193, 25, 124}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 100, 202}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 150, 86, 47, 132}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 49, 17, 71, 96, 87, 210, 185}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 144, 80}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 26}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 4, 181, 32, 138, 6}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 121, 115}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 121, 205, 87, 254, 107, 81, 239}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 252, 230}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 251, 167, 153, 13}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 39}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 22, 5, 78, 140, 89, 237}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 34, 126}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 146, 223, 62, 65, 102, 43}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 233, 197}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 104}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 67, 233, 200, 170, 137}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 31, 94, 12, 117, 130, 234}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 245}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 20, 2, 191, 20, 139, 236}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 203, 34, 185, 23, 134}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 106, 154, 245, 152, 10, 105, 28}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 125, 195, 167, 209, 54}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 23, 226, 154, 48}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 35}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 198, 134, 208, 19, 70, 118, 7}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 135, 17, 157, 87, 65}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 225, 221, 237, 250, 159}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 78, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 145, 157, 214}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 189, 238, 6, 46, 139, 97}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 24, 109, 156, 118}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 81, 173, 80}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 159, 78, 183}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 124, 209, 255, 144, 39, 29}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 32, 90, 135}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 38, 66, 162, 15, 210, 211, 125}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 227, 124, 61, 228}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 63, 171, 166, 197, 40}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 64, 31, 109, 128, 196, 220, 128}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 102, 43, 186, 197, 97, 140, 61}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 21, 185, 169, 231, 89, 69, 78}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 128, 138, 12}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 121, 68, 108, 17, 32, 76, 217}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 222, 57, 149, 198, 48, 87, 150}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 236}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 94, 103}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 155, 16, 160}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 249, 216, 197, 164, 6, 222, 201}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 110, 113, 72, 75, 138, 128, 197}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 15, 82, 220}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 19, 77, 95, 105, 123, 39, 188}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 169, 0}, 193}, {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 134, 64, 47, 228}, 193}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 122, 75, 124, 233, 20, 81, 93, 40}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 44, 74, 37, 151, 98, 145, 53, 173}, 231}, {{236, 41, 169, 234, 14, 128, 0, 150, 228, 107, 64, 165, 51, 40, 146, 236}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 146, 45, 217, 101, 37, 49}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 207, 40, 35, 175, 158, 231}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 231, 132, 83, 62, 216, 74, 77, 4}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 214, 142, 206, 72, 75, 174, 61, 191}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 156, 69, 105, 220, 203, 84, 19, 179}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 35, 107, 247, 145}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 206, 104, 45, 29}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 237, 16, 231, 241, 32, 123, 122}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 250, 66, 37, 82, 109, 40, 137, 56}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 6, 190, 240}, 231}, {{236, 41, 169, 234, 14, 128, 0, 223, 82, 214, 1, 156, 57, 30, 118, 194}, 231}, {{236, 41, 169, 234, 14, 128, 0, 64, 42, 98, 91, 154, 197, 134, 234, 46}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 246, 132, 39, 197, 125, 6}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 142, 107, 151, 171, 114, 112}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 125, 204, 22}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 48, 67, 49, 212, 119, 50, 7, 97}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 112, 175, 108, 209}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 227, 187, 16, 144, 100, 127}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 128, 49, 206, 202}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 141, 56, 244, 174, 155, 45, 252}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 134, 56, 247}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 229, 146, 186, 210, 23, 71, 235}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 125, 78, 194}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 82, 185, 47, 41, 143}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 215, 84, 134, 235, 44, 3, 159}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 238, 71, 228, 191, 77}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 132, 198}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 8, 197, 49, 22, 31, 9, 154, 5}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 224, 206, 98, 26, 2, 57}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 109, 110, 60, 139, 44}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 249, 234, 100, 93, 156, 72, 154, 9}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 135, 99, 143, 166, 21, 71, 18}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 198, 135, 119, 18, 125}, 231}, {{236, 41, 169, 234, 14, 128, 191, 2, 117, 93, 169, 80, 95, 182, 134, 159}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 72, 158, 178, 41, 104}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 190, 25, 40, 254, 246, 134}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 30, 160, 199, 91, 217, 97}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 167, 254, 25, 166, 232, 202, 180}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 143, 175, 183, 196, 81, 104, 8}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 231}, {{236, 41, 169, 234, 14, 128, 0, 84, 196, 75, 243, 153, 56, 53, 59, 124}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 96, 187, 7, 76, 248, 129}, 231}, {{236, 41, 169, 234, 14, 128, 0, 42, 10, 231, 150, 110, 249, 161, 138, 131}, 231}, {{236, 41, 169, 234, 14, 128, 0, 101, 14, 22, 187, 127, 197, 89, 32, 184}, 231}, {{236, 41, 169, 234, 14, 128, 0, 16, 94, 220, 46, 242, 224, 175, 246, 22}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 17, 94, 17, 255, 109, 42, 186, 118}, 231}, {{236, 41, 169, 234, 14, 128, 0, 119, 31, 139, 89, 219, 63, 6, 184, 23}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 90, 160}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 99, 201}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 186, 242, 35, 76}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 90, 54, 137, 168, 75}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 131, 57, 179, 69, 172}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 30, 46, 191, 158, 71, 231, 181, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 74, 50, 21}, 231}, {{236, 41, 169, 234, 14, 128, 19, 5, 100, 29, 112, 121, 146, 90, 64, 243}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 253, 115, 76, 25, 91, 208, 5, 79}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 202, 23}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 197, 75, 225, 33, 22, 112}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 66, 42, 106, 140, 144, 148, 106}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 41, 143, 91}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 76, 198, 197, 149}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 119, 44, 93, 114}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 25, 125, 96, 250, 28}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 90, 48}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 190, 87, 251, 170, 136, 79, 61, 224}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 158, 28, 17, 225, 134}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 243, 67, 94, 250, 117, 213, 173}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 231}, {{236, 41, 169, 234, 14, 128, 0, 124, 175, 119, 163, 97, 191, 123, 213, 128}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 238, 163, 45, 95, 209}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 126, 232}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 154, 145, 239, 89, 167, 78}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 196, 154, 35}, 231}, {{236, 41, 169, 234, 14, 128, 2, 157, 116, 244, 136, 115, 45, 156, 216, 32}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 24, 29, 43, 147, 115}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 2, 109}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 25, 78, 225, 24, 223}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 247, 95, 240, 12, 171, 72, 145}, 231}, {{236, 41, 169, 234, 14, 128, 0, 230, 130, 235, 78, 43, 11, 33, 2, 100}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 118, 87, 26, 251}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 81, 136, 113, 29, 183, 188, 181}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 20, 136, 84, 35, 45, 220}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 41, 174, 159, 212, 88, 141, 143, 132}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 66, 172, 104}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 226, 180, 16, 139, 120, 55}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 42, 75}, 231}, {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 141, 196, 101}, 231}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 247, 119, 232, 102}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 40, 233, 86, 116, 140, 139}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 42, 8, 4, 110, 159, 229, 253}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 248}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 231, 137, 138}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 100, 48, 108, 205, 53, 171, 107}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 102, 140, 123, 141, 164, 59, 196}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 56, 223, 58, 103, 243, 149}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 76, 107, 111, 33, 105, 214, 252}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 165, 229, 86}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 228, 87, 97, 81}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 129, 160}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 164, 107, 232, 122, 35, 86, 222}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 147, 254}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 138, 10, 16, 146}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 97, 223, 210, 52}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 169, 210, 72}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 192, 208, 195}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 142, 114, 155, 86, 69}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 35, 78, 187}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 174, 124, 43, 80, 211}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 178, 164, 250, 168}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 76, 19, 234, 145, 12}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 21, 138, 245, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 132, 229, 98, 121, 196}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 2, 174}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 233, 178, 96, 90, 12, 155, 230}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 37, 180, 84, 205}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 62, 146, 223, 148}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 233}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 41, 149, 137, 232, 114, 174, 18}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 95, 70, 147, 225}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 79, 249, 60, 5, 239}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 194, 149, 184}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 197, 73, 50, 37, 219}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 166, 99, 137, 52, 8}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 173}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 120, 39, 157, 150, 155, 248}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 140, 222}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 7, 149, 55}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 170, 218, 125, 127, 20}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 136, 80, 17}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 59}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 50, 151, 61, 86, 178}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 71}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 58, 70, 18, 45, 54, 212}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 225, 132, 158, 59}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 14, 210, 178}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 117, 170, 104, 58, 64, 211}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 171}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 98, 16, 39, 45}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 73, 186, 39, 175}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 212, 204}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 25, 147}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 203, 102, 250, 29, 155}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 51, 138, 163, 242}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 93, 206, 160, 165, 36}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 190, 84, 11, 81}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 72, 220}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 243, 58, 129, 15, 223}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 95, 195, 115, 13, 128, 23, 85}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 79, 82, 46, 175, 3, 233, 223}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 18}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 140}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 131, 162, 107, 92, 50}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 200, 152}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 36, 248, 110, 46}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 188, 156, 152, 73, 215, 163, 182}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 161, 228, 25, 2, 7}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 199, 160, 198, 150, 8, 12}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 129, 112, 2, 41, 191, 180}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 23, 92}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 9}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 237, 149}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 121, 30, 215}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 28}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 113, 23, 111}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 63, 52}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 159, 57, 174, 225, 197}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 47, 149, 67}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 234}, 250}, {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 138, 199, 108, 66, 222, 101}, 250}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 187, 167, 126, 179}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 240, 222, 160}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 170, 183}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 116, 108, 245, 208}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 190, 182}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 96, 150, 246, 243}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 37, 227}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 163, 126, 117}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 153, 131}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 2}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 248, 97}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 136}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 123, 10, 94, 102, 187}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 81, 140, 123}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 174, 122, 207}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 22}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 235, 105, 7}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 51, 210, 81}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 223, 12, 68}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 197, 67, 28}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 176}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 103, 138, 134, 11}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 29, 130, 83}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 117, 43}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 58, 5, 127}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 219}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 108}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 43, 46, 53, 56, 201}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 57, 50}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 99}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 32, 251, 219}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 191}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 112, 253, 38}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 29, 201, 90, 145}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 100}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 36, 80, 203}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 54, 193, 1, 141, 214}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 104}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 104, 133, 81, 70}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 63}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 242, 14, 228, 118}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 246, 41, 149, 24, 249}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 17, 156, 89, 48, 34}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 27}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 202, 142, 147, 72}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 207}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 218}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 208, 247, 106}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 60, 69, 39}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 232, 125, 122, 222, 216}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 105, 86, 30}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 44, 51, 32}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 130, 112, 72, 206}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 97, 10}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 47, 176, 2}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 53, 126, 3}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 42, 32}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 157, 123, 22}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 175, 172, 205}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 43, 37}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 91, 176, 11, 181}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 53, 122, 147, 227}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 24}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 78, 220}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 4}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 165, 241, 63}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 206, 193, 28}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 154}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 77, 183}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 26, 100, 185}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 89, 51, 158, 184, 217}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 129, 159, 203}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 229, 222}, 24}, {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 14, 239, 147, 2}, 24}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 94, 55, 101, 148, 218, 171, 43}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 123, 169, 200, 247, 174, 73, 89}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 119, 94, 42, 58, 44, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 106, 181}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 241, 241, 110, 236, 83, 55}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 205, 137, 19, 159, 174}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 211, 162, 77}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 174, 93, 229}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 170, 207, 141, 243, 143, 50}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 70, 234, 144, 81}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 220, 156, 101, 150, 113}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 12, 99, 230, 150, 172, 163, 238}, 191}, {{76, 125, 228, 249, 243, 160, 106, 122, 164, 39, 169, 244, 160, 8, 12, 249}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 186, 14, 43, 171, 144, 181}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 199, 55, 123, 180, 28, 7, 92}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 102, 233, 237}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 179, 153}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 225, 37}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 158, 113, 78, 63, 180, 131, 25, 76}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 97, 241, 107, 154, 1, 171, 24, 39}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 2, 191, 9, 54}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 153, 152, 24, 15, 40}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 251, 12, 76, 56, 47, 246, 131}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 221, 212, 155, 144, 157}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 190, 80, 93, 183, 51, 126, 8, 72}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 16, 113}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 179, 252, 61, 143, 190, 140}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 16, 53, 148}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 251, 228}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 125, 193, 226}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 203, 234, 190, 11, 198, 228, 18}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 9, 60, 19, 102, 135, 225, 227, 157}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 35, 225, 66, 103}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 39, 76}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 39, 113, 227, 63, 48, 114, 212, 135}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 254, 146, 70, 37}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 100, 161, 28, 164, 163, 116, 78}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 40, 5, 178}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 97, 1, 221, 124, 75}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 137, 87, 90, 238}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 37, 10, 21}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 50, 18, 205, 170, 173, 209, 139}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 187, 241, 31, 18, 232, 238, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 223, 195, 156, 51, 177, 9, 129}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 43, 203, 246, 221, 36, 149}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 153, 4, 17, 38, 144, 61}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 150, 5, 57, 247, 34, 252}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 86, 187, 23, 134, 218, 17}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 222, 76, 66, 247, 156}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 248, 163, 82, 9, 185, 59}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 197, 22, 169, 84}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 34, 45, 59, 193, 222, 4, 216, 23}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 201, 26}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 50, 77, 42, 0, 27}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 161, 106, 162, 40, 235, 86, 213}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 23, 90, 237, 172, 181}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 102, 91, 88, 160}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 228, 100, 174, 78, 45, 150}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 217, 155, 84, 212, 119}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 52, 202, 191, 195, 70, 52}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 235, 48, 187, 17}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 105, 11}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 245, 54}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 191, 189, 6, 170, 124, 97, 251, 220}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 45, 107, 125, 245, 29}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 88, 6, 78, 189, 162}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 171, 252, 253}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 123, 22, 244, 227, 192}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 213, 61}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 42, 222, 212, 104, 233}, 191}, {{76, 125, 228, 249, 243, 160, 106, 242, 43, 19, 122, 229, 102, 29, 152, 67}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 80, 85, 139, 70, 83, 102, 229, 229}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 69, 158, 243, 67, 236}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 176, 207, 80, 76}, 191}, {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 26, 240, 7}, 191}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 85}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 102}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 171}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 208}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 171}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 49}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 239}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 195}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 39}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 204}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 22}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 215}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 99}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 36}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 213}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 153}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 129}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 96}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 134}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 132}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 4}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 111}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 238}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 82}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 125}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 112}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 190}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 207}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 235}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 16}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 17}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 227}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 250}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 85}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 131}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 135, 134}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 159}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 218}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 194}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 162}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 119}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 39}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 161}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 129}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 149}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 100}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 69}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 175}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 80, 165}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 116}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 52}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 93}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 133}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 147}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 126}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 115, 149}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 246}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 175, 76}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 107}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 21}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 243}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 184}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 163}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 169}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 52}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 4}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 230}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 152}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 138}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 45}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 194}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 216}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 61}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 205}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 214, 32, 147, 127, 196}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 121, 134, 244, 30, 247, 23}, 61}, {{0, 0, 0, 0, 0, 173, 241, 237, 28, 138, 98, 52, 255, 184, 131, 2}, 61}, {{0, 0, 0, 0, 0, 0, 208, 52, 194, 226, 62, 231, 12, 251, 181, 102}, 61}, {{0, 218, 210, 5, 32, 204, 175, 200, 35, 15, 212, 240, 35, 207, 19, 94}, 61}, {{0, 0, 0, 0, 0, 0, 1, 92, 52, 68, 238, 45, 247, 172, 80, 149}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 19, 117, 145, 255, 111, 84, 142, 37}, 61}, {{0, 0, 0, 0, 0, 0, 0, 209, 244, 19, 139, 227, 15, 142, 124, 9}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 86, 12, 83, 90, 176, 235}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 212, 254, 199, 240}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 125, 208}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 132, 179, 124, 138}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 105, 148, 74}, 61}, {{0, 0, 0, 134, 129, 174, 213, 143, 199, 114, 177, 244, 186, 253, 96, 163}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 9, 84, 44, 69, 85, 194, 60, 100, 194, 11, 14}, 61}, {{0, 0, 0, 0, 0, 70, 94, 72, 19, 219, 1, 181, 18, 150, 246, 254}, 61}, {{0, 0, 0, 0, 39, 189, 148, 235, 76, 129, 228, 6, 49, 42, 21, 193}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 210, 106}, 61}, {{0, 0, 0, 0, 0, 0, 0, 185, 31, 205, 108, 144, 134, 72, 43, 83}, 61}, {{0, 0, 114, 146, 151, 242, 44, 151, 91, 210, 16, 6, 25, 158, 241, 33}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 61}, {{0, 0, 0, 0, 0, 192, 73, 110, 204, 4, 134, 167, 42, 225, 203, 214}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 61}, {{0, 0, 0, 0, 0, 0, 0, 219, 164, 48, 149, 216, 47, 48, 21, 162}, 61}, {{0, 0, 130, 52, 17, 163, 221, 39, 162, 79, 203, 107, 219, 163, 210, 156}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 21, 66, 127, 85, 79, 55, 124, 196}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 229, 57, 129, 123, 119}, 61}, {{0, 10, 139, 44, 224, 12, 135, 125, 223, 170, 95, 224, 208, 207, 229, 47}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 199, 86, 111, 25, 8}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 60, 85}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 208, 27, 49}, 61}, {{0, 0, 0, 149, 115, 187, 92, 18, 223, 49, 36, 199, 12, 77, 167, 198}, 61}, {{0, 0, 0, 0, 0, 0, 0, 160, 215, 68, 99, 155, 126, 103, 255, 38}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 135, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 33, 162, 20, 133, 158}, 61}, {{0, 0, 0, 0, 0, 56, 136, 244, 225, 40, 164, 242, 158, 99, 214, 193}, 61}, {{0, 0, 0, 0, 28, 147, 208, 238, 164, 176, 181, 203, 185, 34, 115, 19}, 61}, {{0, 0, 224, 115, 221, 149, 159, 197, 111, 178, 158, 136, 176, 16, 155, 84}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 52, 243, 73, 68, 125, 151, 229, 90}, 61}, {{0, 0, 0, 0, 0, 239, 221, 27, 188, 100, 174, 183, 89, 36, 112, 157}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 61}, {{0, 0, 0, 0, 0, 0, 211, 154, 178, 67, 31, 79, 99, 223, 24, 164}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 117, 114, 58, 68, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 47}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 61, 143}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 225, 159, 191, 80, 176, 219}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 139, 169, 118, 102}, 61}, {{0, 0, 0, 0, 0, 0, 249, 217, 23, 253, 216, 217, 211, 44, 153, 250}, 61}, {{0, 0, 138, 52, 133, 49, 150, 254, 39, 157, 127, 81, 199, 241, 50, 62}, 61}, {{0, 0, 0, 0, 0, 0, 0, 255, 166, 226, 214, 242, 186, 43, 184, 77}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 1, 117, 250, 216, 81}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 161, 213, 142, 90, 120}, 61}, {{0, 0, 0, 0, 226, 193, 123, 15, 45, 20, 106, 235, 107, 98, 134, 9}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 227, 146}, 61}, {{0, 0, 0, 0, 3, 225, 242, 143, 178, 29, 28, 44, 125, 101, 192, 39}, 61}, {{0, 0, 0, 0, 92, 210, 83, 90, 62, 104, 88, 76, 183, 54, 60, 247}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 111, 177}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 79, 42, 65, 113, 15, 115}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 31, 142}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 171, 134, 80, 236, 137, 145}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 164, 108}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 78, 108, 9, 125}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 52}, 61}, {{0, 0, 0, 0, 0, 0, 77, 127, 164, 172, 138, 222, 168, 38, 109, 94}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 61}, {{0, 0, 0, 0, 159, 100, 175, 250, 115, 35, 45, 185, 166, 148, 105, 251}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 235, 30, 73, 215, 12}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 253, 96, 59, 213, 88, 118}, 61}, {{0, 0, 0, 0, 0, 88, 137, 52, 17, 51, 107, 10, 117, 132, 218, 13}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 230, 255, 160, 18}, 61}, {{0, 0, 42, 81, 229, 126, 141, 31, 115, 173, 156, 102, 44, 30, 69, 155}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 120, 107, 165, 242, 162}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 196}, 61}, {{0, 0, 12, 152, 245, 8, 136, 131, 157, 171, 48, 237, 214, 210, 97, 211}, 61}, {{0, 0, 0, 220, 129, 89, 11, 21, 63, 246, 52, 5, 248, 83, 196, 146}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 226, 183, 175, 185, 130, 120}, 61}, {{0, 0, 0, 0, 0, 201, 160, 41, 145, 161, 245, 193, 162, 188, 243, 226}, 61}, {{0, 0, 0, 0, 25, 237, 57, 182, 57, 123, 238, 255, 102, 105, 67, 37}, 61}, {{0, 91, 66, 227, 225, 15, 156, 134, 137, 33, 6, 47, 49, 255, 103, 223}, 61}, {{0, 0, 0, 94, 241, 73, 194, 145, 65, 86, 165, 149, 36, 168, 63, 204}, 61}, {{0, 0, 117, 22, 6, 94, 7, 85, 245, 38, 247, 5, 233, 210, 7, 243}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 61}, {{0, 180, 11, 165, 201, 190, 234, 114, 165, 9, 6, 125, 248, 55, 198, 171}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 200, 78, 1, 123}, 61}, {{0, 239, 101, 98, 55, 248, 195, 157, 179, 105, 187, 30, 76, 75, 89, 70}, 61}, {{0, 0, 0, 0, 178, 9, 239, 82, 0, 159, 1, 3, 157, 84, 125, 63}, 61}, {{0, 0, 0, 0, 0, 0, 0, 128, 3, 23, 155, 239, 24, 238, 6, 251}, 61}, {{0, 0, 0, 0, 0, 0, 0, 212, 54, 200, 217, 62, 71, 72, 116, 44}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 254, 50, 253}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 85, 240, 220, 47, 13}, 61}, {{0, 0, 0, 0, 0, 0, 0, 104, 239, 98, 248, 51, 165, 99, 187, 136}, 61}, {{0, 0, 0, 0, 100, 12, 220, 6, 68, 58, 130, 155, 74, 21, 95, 238}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 158, 191}, 61}, {{0, 0, 245, 217, 18, 218, 168, 168, 64, 181, 111, 254, 119, 126, 59, 98}, 61}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 76, 88, 105}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 162, 235}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 33, 230, 219}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 46, 94, 30, 107}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 38}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 2, 220, 84}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 17, 110, 31, 147}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 144, 19, 171}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 252}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 36, 10, 92}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 137}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 202}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 235, 112}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 183}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 49, 78, 31}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 89, 2, 176, 165}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 196}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 121, 41}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 134}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 221, 248}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 66, 223}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 242, 0, 222, 112}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 2, 189}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 239, 157, 222, 217}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 1}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 215, 62, 102, 51}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 184, 168}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 231}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 228}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 114, 82, 129}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 93, 166}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 14, 249}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 243, 174, 181, 50}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 145, 66}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 106}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 113, 193}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 122, 98}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 89}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 209, 228, 220}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 199}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 198}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 177, 244, 99}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 157, 243, 24, 81}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 81}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 73, 155}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 200, 252, 102, 11}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 31, 124}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 249, 117, 83, 24}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 244, 143, 243}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 93}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 187, 18, 131, 81}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 210, 252, 103, 2}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 233, 245, 28, 11}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 168}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 228}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 159, 18}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 244, 42}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 204}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 93}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 34, 122, 247, 192}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 96, 249}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 103, 102, 41}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 74}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 127, 33}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 166, 186, 29}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 12, 145}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 239}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 109}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 12, 151, 81}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 47, 133, 98, 243}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 206, 112, 118}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 88, 190, 230}, 227}, {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 179}, 227}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 106, 239, 63, 180, 93, 198, 38}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 162, 130}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 120, 106}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 199, 66, 151, 92, 16, 155, 225, 27}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 145, 98, 163, 63, 217, 43, 53}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 134, 13, 87, 188}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 234, 128, 243}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 15, 188, 146, 188, 139, 105}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 61, 232, 87, 140, 191, 145, 178}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 147, 79, 201, 110, 45, 206, 128}, 53}, {{147, 171, 63, 145, 47, 160, 0, 222, 203, 24, 75, 174, 144, 99, 103, 21}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 27, 120, 122, 88, 128, 56, 245}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 145, 207, 241}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 251, 228, 198}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 85, 235, 9, 246, 252}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 189, 134, 66, 208}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 162, 100}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 9, 98, 194, 123, 63, 208}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 55, 149, 121, 8, 20}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 223, 162, 89}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 156, 24, 76, 238, 133}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 59, 27, 0, 172, 165, 225, 48}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 177, 73, 55}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 155, 35}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 180, 44}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 115, 148, 157, 182, 45, 37, 33, 207, 201}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 171, 194, 129, 21, 238, 176, 64, 92}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 44, 29, 66, 147, 157, 181, 99, 175}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 234, 190, 74, 72, 203, 241}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 252, 95, 38, 206}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 241, 239, 127}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 197, 229, 139, 21, 202}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 248, 119, 107, 65, 99, 204, 143, 65}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 74, 60, 168, 178, 239, 252, 144, 44}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 85, 5, 34, 25, 148, 150, 167}, 53}, {{147, 171, 63, 145, 47, 160, 0, 48, 58, 226, 35, 124, 221, 225, 223, 87}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 184, 176, 17, 140}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 78, 124, 10, 66, 63, 223, 212}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 43, 56, 181, 28, 240, 0, 39}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 49, 23}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 143, 139, 18, 176}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 148, 120, 242, 153, 56, 255, 241}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 57, 118, 108, 103, 185}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 82, 249, 253, 39, 172, 105, 27, 71}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 207, 219, 200, 142, 223, 216, 205}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 52, 189, 31, 1}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 224, 91}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 140, 19, 234, 116}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 154, 15, 12, 99, 77, 140, 237}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 254, 40, 16, 111, 161, 46, 160, 11}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 110, 214, 128, 200, 137}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 131, 100, 149}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 214, 241, 78, 227, 27, 212, 144}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 93, 87, 1, 74, 95, 133}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 117, 206, 49, 83, 251, 26}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 118, 189, 82, 187, 7, 170, 159}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 44, 22, 212, 27, 208, 224}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 189, 171}, 53}, {{147, 171, 63, 145, 47, 160, 0, 224, 162, 106, 214, 68, 163, 23, 190, 43}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 128, 44, 31, 91, 165, 95}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 190, 158, 148, 8}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 56, 172, 13, 92}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 242, 111, 30, 148, 254}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 151, 15, 200, 118, 203, 207, 163, 230}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 247, 150}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 77, 154}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 189, 171, 85, 232}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 70, 45, 164, 15, 25, 194, 205, 238}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 8, 76, 56, 64, 193, 43, 157, 51}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 63, 118, 138, 59, 215, 174, 174}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 231, 176, 42, 8, 54, 225}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 33, 162, 87, 112, 213, 194, 5}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 119, 23, 189}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 211, 120, 136, 241}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 125, 92, 215, 89, 204, 194}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 30, 138, 66, 12, 176, 148, 23, 193}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 212, 213}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 53, 211, 49, 184}, 53}, {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 53}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 92}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 14}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 228, 135, 166}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 85, 222, 249, 179}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 91, 21}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 233, 0, 161, 143, 41}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 112}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 239, 31, 186, 179}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 19, 230, 21, 51}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 22, 232, 22, 99, 143}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 215, 127, 198, 146, 146}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 75, 163, 150, 168, 43}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 105, 213, 48, 91, 137}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 131}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 69, 157, 112, 55, 115, 196}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 137, 94, 15}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 201, 183, 90, 6, 200}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 33, 165, 91, 245}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 209, 89, 4, 9, 200, 51}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 192, 255, 115}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 197, 186, 27, 19, 60, 119}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 51, 115, 137, 6, 125}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 12, 9, 65, 76, 119, 25}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 117, 46, 241, 26, 203}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 143, 195}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 1, 192}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 45, 231}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 49, 219, 35, 124, 147, 187}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 32, 10, 187, 200, 252}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 59, 102, 146, 86, 87, 70}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 7}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 126}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 196, 22, 194}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 15, 18}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 82, 19, 212, 215}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 96, 156, 126, 117, 186, 241}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 189, 43, 50, 74, 60}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 5, 2, 215}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 171, 2}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 23, 5, 169, 85}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 44, 80, 206, 137, 74, 240}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 154, 212, 202, 90}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 170, 14}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 223, 12}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 133, 185, 43, 16, 251}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 157, 130, 35, 101, 119}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 77}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 198, 126}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 29, 201}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 167}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 196, 180, 41, 208, 236}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 217, 175, 214, 190, 182, 113}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 28, 145, 238, 40}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 168, 127, 30}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 44, 143, 126}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 226}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 133, 229, 182, 69, 220, 237}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 84}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 122}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 217}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 24, 228, 125}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 114, 185, 208, 109}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 17}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 83}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 22, 147, 7, 222}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 241, 43, 225, 86}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 4, 215, 55}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 227, 158, 35}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 190, 35}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 89, 219, 146, 157, 2, 78}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 52, 123, 2, 40, 67}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 125, 94, 242, 136, 78}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 224, 212, 42, 105, 253, 232}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 34}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 175, 241, 142, 61}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 109, 254, 244, 62, 194}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 236, 26}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 172}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 229, 36, 52}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 215, 174}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 109, 91, 141, 249}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 224, 152, 147, 162, 30}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 220, 119, 23, 236, 32, 142}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 50, 91, 132, 50}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 85, 97, 169, 133}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 122}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 191, 117, 138, 180, 178}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 249}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 105, 9, 222, 238, 186, 172}, 224}, {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 190, 117}, 224}, {{144, 121, 41, 64, 0, 97, 217, 212, 135, 55, 12, 91, 147, 253, 123, 227}, 199}, {{144, 121, 41, 64, 0, 0, 245, 219, 186, 48, 151, 27, 238, 165, 169, 161}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 161}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 85}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 115, 98, 72, 81, 213, 22, 202}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 76, 15, 238, 175, 228, 222, 225}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 98, 45, 74, 120, 175, 130}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 253, 48, 157, 155, 131, 72}, 199}, {{144, 121, 41, 64, 0, 0, 0, 12, 231, 162, 192, 202, 0, 250, 190, 120}, 199}, {{144, 121, 41, 64, 0, 17, 183, 100, 151, 225, 3, 160, 192, 152, 73, 184}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 33, 180}, 199}, {{144, 121, 41, 64, 0, 0, 198, 230, 49, 250, 232, 22, 207, 69, 122, 114}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 236, 131, 57, 255, 5}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 48, 148}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 63, 193}, 199}, {{144, 121, 41, 64, 0, 0, 113, 146, 31, 38, 243, 61, 39, 7, 63, 165}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 130, 32, 120, 238, 246, 31, 53, 12}, 199}, {{144, 121, 41, 64, 0, 0, 0, 127, 110, 176, 12, 156, 249, 187, 185, 69}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 115, 21, 227, 51, 149}, 199}, {{144, 121, 41, 64, 0, 0, 229, 29, 172, 36, 197, 13, 203, 237, 177, 14}, 199}, {{144, 121, 41, 64, 0, 179, 62, 102, 212, 28, 43, 233, 83, 197, 80, 153}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 155, 243, 224, 116, 113, 137, 68}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 50, 52, 106, 36, 16, 20, 204, 174}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 165, 89, 146, 205, 161, 227}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 236, 246, 26, 5, 186}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 230, 151, 208, 73}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 49, 129}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 19, 204, 55, 148, 2, 20, 51}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 206, 41, 74, 22, 49, 43, 165}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 140, 52, 41, 212, 205, 106, 148}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 227, 200}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 123, 12, 70, 85, 65, 174}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 40, 239, 148, 195, 218}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 117, 24, 232, 167, 151, 222, 146, 213}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 121, 25, 164, 214}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 199}, {{144, 121, 41, 64, 0, 0, 4, 95, 94, 159, 163, 139, 45, 94, 50, 12}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 247, 41}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 117, 72, 186, 53}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 15, 200, 194, 82, 207, 110, 182, 95, 116, 153}, 199}, {{144, 121, 41, 64, 0, 0, 0, 195, 9, 50, 227, 141, 117, 82, 2, 236}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 255, 130, 125, 108, 133, 169}, 199}, {{144, 121, 41, 64, 239, 39, 120, 212, 174, 11, 199, 37, 243, 42, 184, 187}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 17, 19}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 81, 247, 66, 164, 235}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 175}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 184, 89, 236, 243, 251, 13, 49, 136, 246, 162, 140, 72}, 199}, {{144, 121, 41, 64, 0, 0, 192, 84, 30, 113, 119, 205, 162, 88, 88, 226}, 199}, {{144, 121, 41, 64, 0, 0, 49, 239, 237, 233, 108, 240, 64, 148, 133, 152}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 42, 70, 17, 229, 196, 126, 212}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 66, 162, 53, 153, 148, 127, 227, 111}, 199}, {{144, 121, 41, 64, 0, 0, 243, 206, 135, 135, 195, 37, 186, 212, 75, 100}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 18, 188}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 20}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 60, 4, 214, 213}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 45, 52, 173, 169, 209, 106, 123, 121, 123, 150, 61}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 77, 87, 213, 174, 165, 187}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 227}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 51, 27, 58, 135, 217, 133, 31}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 129, 123, 140, 193, 185, 77, 45, 125}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 29, 15, 249, 236, 13}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 58, 155, 197, 200, 90, 180, 23}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 116, 180, 60, 202, 88, 9}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 248, 158, 5, 254, 51, 243, 246, 31}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 123}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 170, 221, 122, 187, 48, 95}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 156, 250, 10, 79, 179, 128}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 165}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 27, 11, 74, 94, 48, 154, 49}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 212, 62, 158, 46, 134, 202, 120, 91}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 7, 247, 19, 38, 46}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 191, 7, 142, 106, 84, 218}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 9, 252, 159, 205, 185, 171, 65}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 120, 64, 50, 184, 170, 156}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 1, 234, 93, 77, 105, 207, 208, 97}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 212}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 190, 27, 68, 186, 132}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 220, 212, 145, 67, 206, 144}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 201, 110, 54, 183, 37, 88, 103, 253}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 62, 253, 181, 6}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 39, 110}, 199}, {{144, 121, 41, 64, 0, 0, 0, 129, 212, 213, 107, 196, 214, 106, 64, 100}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 98, 169, 124, 87, 124}, 199}, {{144, 121, 41, 64, 0, 0, 0, 0, 175, 65, 145, 140, 59, 93, 68, 247}, 199}, {{144, 121, 41, 64, 0, 0, 0, 174, 61, 30, 188, 27, 35, 231, 217, 131}, 199}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 109}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 184, 231, 197, 168, 33, 250}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 181, 166, 38}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 111, 10, 227, 108, 147, 12}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 79}, {{116, 105, 128, 0, 0, 0, 0, 54, 124, 217, 134, 94, 246, 203, 198, 136}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 133, 22}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 40, 188, 151}, 79}, {{116, 105, 128, 0, 0, 0, 0, 207, 164, 245, 24, 135, 184, 231, 216, 18}, 79}, {{116, 105, 128, 0, 0, 0, 0, 3, 16, 195, 131, 80, 141, 234, 238, 155}, 79}, {{116, 105, 128, 0, 0, 173, 168, 201, 131, 110, 198, 163, 87, 190, 36, 34}, 79}, {{116, 105, 128, 0, 0, 0, 0, 188, 174, 46, 97, 38, 187, 11, 64, 4}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 253, 121, 167, 163, 185, 84, 215}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 49}, 79}, {{116, 105, 128, 0, 140, 6, 220, 112, 140, 15, 45, 247, 138, 178, 46, 156}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 168, 0, 248, 160, 86, 2}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 22, 49, 126, 62, 97}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 102, 89}, 79}, {{116, 105, 128, 48, 136, 103, 132, 212, 37, 215, 186, 30, 109, 52, 54, 177}, 79}, {{116, 105, 128, 0, 0, 0, 0, 2, 18, 89, 228, 200, 64, 170, 139, 71}, 79}, {{116, 105, 128, 0, 0, 0, 0, 155, 75, 9, 122, 139, 24, 148, 235, 19}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 239, 132, 66}, 79}, {{116, 105, 128, 191, 89, 228, 46, 210, 66, 250, 28, 34, 29, 206, 188, 33}, 79}, {{116, 105, 128, 0, 0, 0, 121, 101, 172, 108, 161, 24, 92, 35, 133, 104}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 32, 31, 125, 26, 33, 240}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 53, 114, 223, 248, 191, 70, 205}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 133, 12, 138, 79, 137, 12}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 194, 45, 110, 237, 83, 241, 247, 254}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 183, 47, 198, 77, 150, 226, 109, 94}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 217, 85, 225, 13, 208, 98, 225, 227}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 79}, {{116, 105, 128, 0, 0, 135, 58, 146, 169, 33, 52, 152, 122, 104, 163, 48}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 73, 137, 139}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 51, 133, 197, 201, 147, 157, 234}, 79}, {{116, 105, 128, 0, 0, 0, 214, 85, 157, 145, 224, 31, 245, 253, 188, 239}, 79}, {{116, 105, 128, 0, 0, 167, 89, 249, 143, 80, 236, 70, 152, 247, 133, 183}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 181}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 219, 113}, 79}, {{116, 105, 128, 0, 244, 167, 127, 146, 39, 208, 103, 99, 38, 232, 20, 17}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 11, 77, 184}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 81}, 79}, {{116, 105, 128, 0, 34, 71, 81, 200, 37, 152, 26, 128, 237, 30, 51, 128}, 79}, {{116, 105, 128, 0, 70, 67, 216, 111, 182, 129, 248, 208, 34, 215, 241, 189}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 242, 211, 82, 66, 20}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 38}, 79}, {{116, 105, 128, 0, 0, 218, 208, 227, 180, 137, 213, 174, 66, 208, 255, 9}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 91, 163, 189, 40, 139, 160, 156, 81}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 92, 41, 251, 150, 192, 123, 138, 136}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 61, 81, 10, 239, 155, 156, 152}, 79}, {{116, 105, 128, 0, 0, 0, 91, 18, 160, 245, 196, 121, 191, 46, 166, 251}, 79}, {{116, 105, 128, 87, 167, 107, 125, 192, 14, 101, 50, 89, 144, 250, 180, 151}, 79}, {{116, 105, 128, 111, 169, 119, 32, 82, 31, 65, 197, 49, 237, 27, 64, 207}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 1, 141, 188, 44, 147, 177, 184}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 47, 193, 72, 226, 96, 72}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 58}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 57, 190, 90}, 79}, {{116, 105, 128, 211, 23, 57, 193, 195, 171, 127, 44, 126, 127, 142, 189, 221}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 148}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 253}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 127}, 79}, {{116, 105, 128, 0, 0, 0, 0, 77, 157, 149, 221, 31, 45, 10, 52, 37}, 79}, {{116, 105, 128, 0, 0, 0, 0, 126, 224, 121, 206, 170, 25, 208, 6, 23}, 79}, {{116, 105, 128, 0, 0, 0, 0, 92, 166, 158, 229, 27, 46, 212, 18, 230}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{116, 105, 128, 174, 132, 43, 165, 96, 82, 190, 100, 189, 132, 150, 194, 206}, 79}, {{116, 105, 128, 0, 0, 0, 12, 11, 251, 124, 201, 143, 56, 100, 17, 204}, 79}, {{116, 105, 128, 0, 0, 106, 150, 13, 117, 226, 57, 192, 99, 61, 49, 5}, 79}, {{116, 105, 128, 0, 0, 160, 77, 85, 221, 130, 174, 104, 132, 162, 216, 48}, 79}, {{116, 105, 128, 0, 0, 104, 19, 200, 91, 229, 24, 183, 111, 119, 254, 100}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 102, 57, 99, 101, 122, 57, 64}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 96, 230, 209, 232, 35, 245, 6}, 79}, {{116, 105, 128, 0, 254, 28, 102, 22, 130, 13, 2, 232, 175, 4, 89, 59}, 79}, {{116, 105, 128, 0, 0, 125, 53, 100, 83, 16, 18, 115, 66, 243, 173, 12}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 237}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 101, 87, 200, 122, 209, 56, 228, 169}, 79}, {{116, 105, 128, 0, 103, 232, 222, 112, 86, 42, 43, 212, 105, 29, 248, 78}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 56, 42, 124, 132, 115}, 79}, {{116, 105, 128, 0, 0, 0, 49, 72, 115, 117, 34, 113, 238, 201, 194, 29}, 79}, {{116, 105, 128, 0, 0, 0, 0, 141, 127, 80, 221, 151, 18, 38, 140, 181}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 122, 142, 254, 85, 31, 12, 39, 129}, 79}, {{116, 105, 128, 0, 0, 0, 153, 149, 164, 241, 124, 120, 179, 168, 217, 195}, 79}, {{116, 105, 128, 0, 0, 0, 25, 245, 73, 143, 171, 185, 112, 249, 11, 214}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 31}, 79}, {{116, 105, 128, 138, 249, 206, 66, 202, 40, 7, 51, 241, 64, 204, 72, 226}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 252, 75, 16, 112, 250}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 5, 48, 191}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 50, 199, 207, 84, 199}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 181, 48, 39}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 63, 89, 82, 158, 0, 88}, 79}, {{116, 105, 128, 0, 0, 0, 0, 159, 166, 182, 14, 197, 8, 30, 3, 122}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 76, 192, 35, 123, 119, 30, 127, 54}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 79}, {{116, 105, 128, 0, 237, 145, 204, 118, 163, 83, 180, 87, 195, 48, 6, 102}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 79, 52, 35, 118, 28, 176, 55}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 206, 225, 167, 77, 122, 229, 115, 253}, 79}, {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 40, 14, 129, 228, 30, 242}, 79}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 66, 84, 107}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 34, 5, 214}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 22, 84}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 47, 128, 85, 220, 135}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 162, 45}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 20}, 19}, {{142, 149, 24, 0, 0, 0, 204, 173, 216, 43, 242, 254, 192, 156, 252, 149}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 195, 145, 144, 17, 176, 130, 32, 197}, 19}, {{142, 149, 24, 0, 0, 0, 0, 233, 184, 227, 170, 213, 143, 36, 153, 71}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 0, 0, 117, 182, 240, 126, 184, 69, 116, 201, 28}, 19}, {{142, 149, 24, 0, 0, 0, 147, 67, 50, 235, 226, 113, 126, 125, 131, 6}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 124, 123}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 167}, 19}, {{142, 149, 24, 0, 0, 92, 213, 181, 180, 33, 4, 3, 73, 230, 227, 84}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 224, 11, 53}, 19}, {{142, 149, 24, 0, 50, 66, 71, 210, 79, 83, 191, 5, 17, 222, 216, 99}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 250, 28, 27, 78, 15}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 150, 144, 36}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 79, 93, 146}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 97, 92, 101, 91, 207, 224, 46}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 182, 245, 161, 51, 227, 120, 118, 26}, 19}, {{142, 149, 24, 0, 0, 0, 85, 178, 26, 21, 199, 171, 226, 103, 53, 156}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 19}, {{142, 149, 24, 0, 0, 0, 142, 190, 107, 192, 145, 198, 139, 31, 88, 116}, 19}, {{142, 149, 24, 0, 87, 202, 19, 11, 12, 120, 79, 229, 20, 138, 158, 3}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 150, 103}, 19}, {{142, 149, 24, 0, 0, 0, 74, 159, 45, 197, 82, 254, 204, 24, 247, 129}, 19}, {{142, 149, 24, 0, 0, 218, 2, 228, 215, 33, 109, 164, 211, 74, 125, 196}, 19}, {{142, 149, 24, 0, 0, 97, 32, 207, 233, 20, 154, 204, 136, 49, 196, 175}, 19}, {{142, 149, 24, 0, 0, 0, 173, 79, 42, 232, 244, 16, 1, 217, 242, 80}, 19}, {{142, 149, 24, 0, 0, 221, 136, 230, 255, 169, 147, 144, 205, 97, 9, 16}, 19}, {{142, 149, 24, 0, 14, 60, 64, 214, 118, 62, 13, 168, 163, 49, 143, 180}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 56, 68, 65, 171, 175, 212, 21, 77}, 19}, {{142, 149, 24, 0, 0, 203, 225, 177, 131, 100, 162, 25, 86, 244, 10, 180}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 0, 118, 177, 168, 106, 6, 201, 122, 240, 122, 48}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 81, 80, 173}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 184, 72}, 19}, {{142, 149, 24, 0, 0, 0, 62, 31, 226, 23, 47, 76, 113, 11, 145, 187}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 150}, 19}, {{142, 149, 24, 161, 251, 194, 223, 183, 153, 49, 170, 143, 182, 76, 86, 98}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 116, 107, 79, 189, 202, 154, 184, 215}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 153, 228, 244, 204, 250, 244, 4}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 106, 13, 154, 177, 254, 173, 236}, 19}, {{142, 149, 24, 0, 181, 170, 99, 122, 242, 25, 67, 7, 41, 52, 42, 112}, 19}, {{142, 149, 24, 0, 0, 0, 0, 21, 17, 107, 81, 98, 232, 65, 70, 99}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 11}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 9, 112, 67}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 221, 219, 182}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 107, 6, 40, 236, 68, 176, 221, 127}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 68, 130, 84, 2, 198, 19, 164, 12, 87, 215, 237}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 129, 191, 143, 198, 178}, 19}, {{142, 149, 24, 0, 0, 231, 28, 90, 24, 2, 27, 208, 94, 219, 37, 252}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 6, 212}, 19}, {{142, 149, 24, 0, 150, 234, 114, 236, 207, 223, 19, 186, 5, 182, 83, 186}, 19}, {{142, 149, 24, 0, 0, 12, 238, 0, 29, 189, 84, 112, 141, 190, 176, 217}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 238, 220, 50, 34, 110, 173, 214}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 207, 205, 4, 61, 88, 75, 192, 93}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 8, 193, 101, 34, 115, 151, 198, 113}, 19}, {{142, 149, 24, 0, 0, 112, 207, 255, 115, 112, 40, 166, 105, 72, 160, 60}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 32, 219, 234, 255, 46, 148, 4}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 59, 1, 209, 174, 250}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 153, 148, 241, 242, 7}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 106, 45}, 19}, {{142, 149, 24, 0, 0, 0, 0, 1, 14, 10, 225, 40, 158, 115, 232, 29}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 141, 246, 127, 57, 163}, 19}, {{142, 149, 24, 0, 59, 197, 99, 37, 194, 201, 202, 124, 81, 153, 73, 3}, 19}, {{142, 149, 24, 0, 0, 207, 223, 104, 44, 5, 254, 76, 14, 77, 234, 121}, 19}, {{142, 149, 24, 0, 0, 43, 78, 68, 241, 103, 220, 72, 151, 32, 90, 69}, 19}, {{142, 149, 24, 0, 0, 0, 0, 216, 16, 162, 1, 113, 163, 62, 128, 179}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 90, 140, 113}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 108, 50, 168, 181, 10}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 79, 2, 21, 84, 216, 25}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 29, 18, 78, 160, 249, 53}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 57, 137, 197, 202, 99, 18, 118, 244}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 177, 94, 87, 169, 255, 195, 48, 199}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19}, {{142, 149, 24, 0, 0, 0, 0, 86, 128, 123, 225, 111, 231, 191, 235, 156}, 19}, {{142, 149, 24, 0, 146, 143, 227, 6, 198, 194, 3, 171, 89, 245, 158, 62}, 19}, {{142, 149, 24, 0, 0, 0, 0, 30, 36, 106, 45, 15, 58, 101, 47, 84}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 202, 116, 254, 115, 192, 145, 169}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 60, 248, 25, 191, 239}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 178, 80, 67, 119, 216, 89}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 178}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 226}, 19}, {{142, 149, 24, 147, 99, 239, 230, 152, 189, 135, 108, 224, 4, 146, 66, 36}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 34, 193, 226, 40, 0, 110, 104}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 17, 97, 64, 211, 18, 255}, 19}, {{142, 149, 24, 0, 0, 0, 0, 0, 0, 152, 214, 51, 32, 131, 26, 254}, 19}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 87, 156, 137}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 154, 184}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 234, 194, 205}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 7, 42, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 135, 41, 54}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 1, 230, 231}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 148}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 174, 50}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 67, 56}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 68, 48}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 17, 27, 174}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 178, 42}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 147, 47, 4}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 17, 71}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 55}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 78, 115}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 114}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 187, 118}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 11, 63, 106}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 63, 69}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 203, 8, 110}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 73, 175}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 192}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 188, 134, 117}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 141}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 67, 223, 209}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 79, 96, 132}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 68}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 157, 121}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 103}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 145}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 229, 119}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 141, 124, 211}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 159}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 96, 147, 160}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 55, 205}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 159, 29}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 60, 36}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 95}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 177}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 174, 39}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 255}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 35, 77}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 177}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 46}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 81, 98}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 40, 239}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 183, 167, 61}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 148, 132}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 41, 198, 179}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 226, 13}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 1, 175}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 74, 71}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 54, 150, 36}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 20, 133, 14}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 62, 14}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 160, 207}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 37}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 121, 180, 23}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 160}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 213}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 101, 177}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 97, 123, 106}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 218, 79, 210}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 241, 86, 46}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 39}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 185}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 151}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 65}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 121}, 211}, {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 211}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 6}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 143}, {{139, 219, 92, 224, 0, 0, 0, 11, 9, 223, 26, 195, 115, 186, 59, 133}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 93, 182, 61, 28, 206}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 222, 133, 237, 107, 242}, 135}, {{139, 219, 92, 224, 0, 0, 0, 88, 213, 112, 59, 45, 77, 133, 211, 112}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 198, 164, 98, 42}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 121, 193, 34, 165, 190, 25, 201, 137}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 21}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 96, 214}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 81, 170, 217, 127, 80, 140, 104}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 146, 65, 225, 38}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 240, 145, 253, 179, 112, 211}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 33}, 135}, {{139, 219, 92, 224, 0, 0, 136, 248, 120, 17, 164, 47, 240, 8, 53, 193}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 79, 174, 190, 127, 72, 54}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 243, 152, 106, 241, 20}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 135}, {{139, 219, 92, 224, 0, 79, 133, 126, 221, 69, 63, 184, 168, 45, 4, 80}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 227}, 135}, {{139, 219, 92, 224, 0, 91, 78, 190, 190, 13, 17, 74, 3, 203, 172, 7}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 203, 194, 127, 252}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 230, 97, 43, 168, 150, 208, 45}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 210, 18, 100, 247}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 45, 0, 164, 240, 163, 225}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 72, 55, 85, 68, 239}, 135}, {{139, 219, 92, 224, 0, 159, 86, 206, 193, 1, 198, 111, 12, 18, 178, 153}, 135}, {{139, 219, 92, 224, 0, 0, 0, 140, 92, 164, 150, 47, 211, 135, 171, 198}, 135}, {{139, 219, 92, 224, 0, 105, 210, 114, 83, 158, 144, 216, 10, 109, 190, 36}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 232, 210}, 135}, {{139, 219, 92, 224, 0, 19, 135, 108, 50, 137, 203, 109, 153, 174, 98, 169}, 135}, {{139, 219, 92, 224, 0, 0, 0, 79, 76, 111, 12, 71, 89, 75, 152, 203}, 135}, {{139, 219, 92, 224, 0, 8, 131, 194, 99, 64, 61, 68, 15, 219, 37, 242}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 105, 255, 246, 253, 118, 217, 133, 122}, 135}, {{139, 219, 92, 224, 0, 0, 185, 44, 104, 89, 232, 7, 117, 30, 68, 147}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 179, 149}, 135}, {{139, 219, 92, 224, 0, 0, 194, 147, 50, 148, 18, 184, 192, 79, 130, 160}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 250, 32, 125, 180, 168}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 92, 214, 6, 228, 112}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 155, 243, 254, 145}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 135}, {{139, 219, 92, 224, 0, 0, 0, 102, 249, 7, 227, 223, 221, 144, 41, 210}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 135}, {{139, 219, 92, 224, 0, 0, 0, 17, 160, 116, 147, 210, 150, 45, 129, 162}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 175, 73, 191, 72, 230, 34, 92}, 135}, {{139, 219, 92, 224, 0, 88, 187, 76, 136, 38, 77, 0, 232, 114, 28, 228}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 65, 96, 21, 64, 73, 93, 146, 23, 53, 40, 1}, 135}, {{139, 219, 92, 224, 0, 0, 0, 130, 79, 169, 191, 138, 234, 38, 3, 216}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 98, 155, 110, 6, 26, 4, 49}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 144}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 104, 243}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 214, 36, 99, 65}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 212, 106, 48, 60, 122, 58}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 90, 22, 171, 49, 150, 149, 147}, 135}, {{139, 219, 92, 224, 0, 0, 0, 84, 212, 50, 171, 84, 35, 245, 138, 250}, 135}, {{139, 219, 92, 224, 0, 132, 127, 92, 11, 157, 148, 30, 11, 194, 251, 6}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 43, 222, 39, 82, 83, 159, 203}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 163, 123, 215, 94, 29, 124}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 53, 180, 133, 48, 208, 47, 97, 159, 240, 100}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 7, 32, 174, 23, 23, 75, 172, 228}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 3}, 135}, {{139, 219, 92, 224, 0, 0, 77, 37, 238, 14, 245, 112, 99, 241, 158, 166}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 5, 126}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 4, 150, 250, 76, 145, 92, 33}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 135}, {{139, 219, 92, 224, 0, 0, 0, 187, 26, 161, 26, 67, 117, 248, 1, 116}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 124, 32, 163, 37, 155, 177, 238}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 163, 114, 109, 85, 73, 228}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 71, 152, 36, 235, 238, 14, 247}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 151, 102}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 156, 125, 206, 26, 135, 200}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 224, 224, 16, 29, 49, 132}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 197, 169, 253, 207}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 49, 201, 189, 246}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 138, 26}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 135}, {{139, 219, 92, 224, 116, 14, 253, 130, 147, 159, 247, 128, 137, 167, 253, 95}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 206, 250, 84, 52, 56}, 135}, {{139, 219, 92, 224, 0, 208, 2, 180, 161, 159, 254, 93, 16, 97, 26, 250}, 135}, {{139, 219, 92, 224, 0, 0, 232, 124, 235, 250, 245, 66, 79, 118, 68, 234}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 60, 5, 33, 117, 65, 138}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 92, 2, 20, 21, 84, 104, 54, 151}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 150, 210, 228, 216, 55, 201, 249, 145}, 135}, {{139, 219, 92, 224, 0, 0, 0, 237, 30, 192, 94, 38, 62, 53, 254, 207}, 135}, {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 101}, 135}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 53, 206}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 115}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 236, 131}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 221}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 167}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 110}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 231, 247}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 88}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 83, 183}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 99}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 138}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 134, 49}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 226}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 139}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 179, 54}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 120}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 213, 153}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 63, 34}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 186}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 156}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 79, 186}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 98, 204}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 126}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 179}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 11}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 217}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 38}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 249}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 119, 93}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 166}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 249, 241}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 34}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 149}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 44, 86}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 131}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 71}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 218}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 220}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 225, 106}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 96, 137}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 167}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 111}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 15}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 92, 62}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 106}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 169, 223}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 1}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 233}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 123}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 187}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 195}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 68}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 156, 207}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 92}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 52}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 223}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 93}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 253, 81}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 159}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 21}, {{237, 186, 88, 254, 124, 0, 0, 0, 234, 109, 226, 180, 17, 42, 163, 95}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 89}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 215, 103, 145, 40, 80}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 80}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 101}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 101}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 241, 53, 68, 167, 184, 197}, 220}, {{237, 186, 88, 254, 124, 0, 222, 164, 176, 80, 215, 244, 89, 53, 110, 173}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 59, 11, 78, 145, 171, 151, 111}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 21, 129, 90, 10, 64, 147, 248}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 152, 248, 213, 254}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 238, 52, 181, 250, 246, 153, 88}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 179, 186, 134, 64}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 71, 107, 147, 209, 229, 200}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 12, 31, 154, 72, 249}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 132}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 160, 179, 130, 109}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 189, 141, 181, 114, 233, 186, 249}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 14, 148, 246, 112}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 249, 56, 177, 8}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 220}, {{237, 186, 88, 254, 124, 0, 164, 11, 119, 215, 41, 96, 200, 61, 51, 93}, 220}, {{237, 186, 88, 254, 124, 0, 0, 225, 38, 2, 151, 2, 240, 145, 107, 68}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 73}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 146, 183, 170}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 67, 20, 136}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 82, 199, 76, 190, 19, 57, 35}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 112, 137, 120, 215}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 146, 167, 168}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 178, 119, 222, 61}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 49, 63, 252, 254, 184}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 231, 233, 209}, 220}, {{237, 186, 88, 254, 124, 25, 157, 128, 215, 64, 199, 200, 129, 134, 177, 163}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 12, 248, 220, 134, 231, 66}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 81, 46, 165}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 181, 234, 148, 210, 172, 243, 183, 197, 67}, 220}, {{237, 186, 88, 254, 124, 0, 214, 253, 96, 112, 85, 169, 167, 185, 74, 228}, 220}, {{237, 186, 88, 254, 124, 0, 202, 169, 32, 164, 9, 144, 173, 158, 111, 42}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 116, 68, 116}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 9, 21, 184, 162, 205, 236, 25, 251}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 52, 189, 205, 36, 233, 103}, 220}, {{237, 186, 88, 254, 124, 0, 63, 6, 87, 50, 247, 93, 189, 161, 43, 170}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 93, 182, 198, 190, 58, 244, 177, 168, 243}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 108, 165, 168}, 220}, {{237, 186, 88, 254, 124, 0, 182, 142, 72, 13, 79, 220, 167, 239, 189, 241}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 254, 187, 123, 171, 2, 8, 235, 85, 134, 243}, 220}, {{237, 186, 88, 254, 124, 0, 27, 233, 61, 128, 136, 228, 17, 105, 236, 108}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 246, 101, 193, 53, 90, 28}, 220}, {{237, 186, 88, 254, 124, 0, 0, 28, 237, 11, 24, 255, 34, 79, 252, 92}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 141, 33, 71, 90}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 245, 252, 182, 21}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 55, 129, 172, 189, 163, 56, 197, 119}, 220}, {{237, 186, 88, 254, 124, 0, 0, 52, 166, 46, 35, 31, 193, 9, 0, 101}, 220}, {{237, 186, 88, 254, 124, 0, 136, 248, 33, 131, 40, 64, 48, 90, 89, 147}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 103, 235, 13, 146, 18, 233, 39}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 32}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 63, 22, 98, 74, 156, 128, 207, 120}, 220}, {{237, 186, 88, 254, 124, 0, 72, 39, 215, 101, 238, 222, 88, 225, 80, 126}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 200}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 169, 36, 77, 234, 30}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 188, 202, 102, 58}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 129, 210, 123, 149, 152}, 220}, {{237, 186, 88, 254, 124, 0, 30, 1, 83, 230, 131, 245, 89, 57, 195, 29}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 131, 209, 128, 242}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 153, 77, 206, 248, 245}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 116, 22, 158, 37, 19, 19, 144}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 175, 225, 68, 58, 93}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 23}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 187, 197, 103, 90}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 58, 153, 4, 143, 86}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 112, 110, 50, 190, 231}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 108, 24, 51, 54, 204, 141, 205}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 28, 97, 173, 246, 46, 219}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 157, 192, 81, 166, 109}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 220}, {{237, 186, 88, 254, 124, 214, 124, 106, 41, 101, 142, 242, 249, 242, 18, 240}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 87, 184, 191, 212}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 18, 114, 17}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 61, 8, 236, 131, 198, 40, 182, 170}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 14, 9, 212}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 103, 69, 208, 59, 130, 76}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 21}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 78, 255}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 174, 248, 187, 24}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 171, 119}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 205, 212}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 44, 119, 43, 193, 29, 189}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 125, 149}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 186, 229}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 251, 48, 52, 224, 43}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 223, 20, 208, 191, 31, 51, 195}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 170, 101, 230, 213, 190, 236, 42}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 2, 211, 218, 237, 141}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 50, 179}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 19, 202, 242, 79}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 205, 180, 209, 41, 10}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 54, 251, 90, 211}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 181, 26, 230, 64, 27}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 19, 91, 81}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 40, 209, 70}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 23, 229, 84}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 242, 212, 206, 162, 5}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 101}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 20, 104}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 164, 75, 173, 188, 145}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 191, 189, 6, 53}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 102, 233, 203, 177}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 135, 162}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 99, 96}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 9, 167}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 87, 170, 48, 64, 248, 69, 211}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 144, 215, 232, 163, 29, 27}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 170}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 206, 157, 12, 157, 90, 48}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 173, 142, 176, 23, 130}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 179}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 196, 31, 170, 239, 142, 34, 114}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 83, 30, 117, 92, 73}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 76, 172, 245}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 32, 34, 211, 108, 251, 49}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 64}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 151, 88, 148, 14, 24}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 137, 65, 220, 165}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 192}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 223, 242, 242, 182, 126, 101, 99}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 112}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 29, 174, 231, 196, 176}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 163, 145, 216, 71}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 53, 96, 45, 150}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 124, 209, 84}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 8}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 198, 207, 163, 127, 162, 207}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 19, 152, 147, 218}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 171, 252, 148, 202, 222}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 178, 91, 71, 179, 166, 126, 178}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 212}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 21, 64, 22, 149}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 114}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 128, 3, 232}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 70}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 109, 16, 81, 216, 157, 242}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 137, 34, 233, 148, 234}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 21, 43}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 209, 71, 163}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 12, 148, 159, 40, 229}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 229, 187, 72, 10, 100, 211, 130}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 11, 171, 11, 85}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 142, 33}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 203, 106, 25, 154, 45, 169, 85}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 52, 124}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 53, 224}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 206, 136, 147, 205, 63}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 87, 143}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 46, 79}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 128, 112, 52, 112, 249, 38, 83}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 237, 51}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 33, 8, 28, 180}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 68, 188, 116, 246}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 166, 103, 196, 245, 90, 198}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 157, 179, 69, 89, 70, 182}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 32, 182, 95}, 151}, {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 104, 33, 12}, 151}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 119, 191, 215, 86, 228, 181}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 99, 106, 1, 73, 184, 240, 138}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 73, 55, 69, 209}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 151, 34, 178, 11, 56, 56}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 34, 250}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 178, 223, 186}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 180, 83}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 9, 231, 82}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 45, 120, 150, 62}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 193}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 130, 163}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 98, 73, 38}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 171, 136, 182, 242, 200, 211, 19}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 34, 7, 97, 25, 28}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 241, 74, 111, 114}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 127, 54, 7, 47, 188, 96, 67, 35}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 18}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 155, 231, 253, 117, 48}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 129, 175, 8, 241, 29, 56, 136}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 113, 28, 50, 249, 228, 198}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 88, 242, 132, 195}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 146, 12, 122, 91, 220, 169, 0, 134}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 182, 57, 148, 139, 207, 190}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 225, 175, 139, 13, 90, 36, 175}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 48, 227, 183, 72, 159}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 77, 132}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 198, 184, 235, 10}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 113, 113, 2, 236}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 194, 189, 113, 113}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 184, 253, 172, 82, 74, 144}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 63, 195, 199, 23, 20, 253, 255}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 205, 76, 201, 14, 61, 119, 120}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 11, 197, 234}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 178, 28, 14, 59, 134, 74, 38, 147}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 53, 47, 12, 176, 14, 169}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 217, 49, 6, 184, 230, 166, 134}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 200, 250, 99, 32, 201}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 178, 40, 172, 183, 175, 78, 93}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 62, 9, 27, 148, 78, 8}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 171, 221, 189, 17}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 124, 45, 8}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 223}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 121}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 22, 12, 149, 78, 164, 106, 124}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 251, 72, 163, 100, 107}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 167, 9, 98, 39, 157, 2, 8, 70}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 209, 47, 5}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 169, 132, 60, 28, 28, 98, 47}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 231, 102, 212, 21, 144, 32, 143}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 113, 68}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 122, 168}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 59}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 67, 249, 69, 47, 128, 109}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 90}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 70, 133, 205}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 174, 128, 194, 184}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 208, 26, 218, 138}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 10, 57, 20, 45, 226, 56, 244}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 23, 84, 189, 196}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 214, 26, 174}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 243, 43, 72, 204, 48, 250, 36}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 48}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 10, 182, 16, 112, 69, 127, 229, 170}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 121, 229, 69, 231, 40, 197}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 194, 87, 142}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 173, 61, 139, 75, 115, 165}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 159, 53, 64, 180}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 210, 136, 52, 210, 43, 120, 208}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 82, 27, 14, 112, 246}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 88, 131, 126, 216, 11}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 71, 6, 0, 95, 215}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 20, 105, 17, 122, 161, 54, 222}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 10}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 128, 184, 69}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 7, 34, 215, 194, 231}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 78, 52, 103, 45, 116, 201}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 45, 185}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 5, 52, 152, 81}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 52}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 245, 176}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 173, 203, 251, 100, 202, 203, 90}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 91, 65, 118, 43}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 199, 64, 77, 13, 229}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 163, 76, 13, 73, 241, 81}, 111}, {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 51, 204, 0, 91, 252, 22, 216}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 243, 180, 118, 79, 174, 237}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 242, 140, 215, 196, 240}, 63}, {{107, 229, 240, 160, 247, 145, 29, 48, 1, 69, 180, 70, 133, 164, 98, 136}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 175, 95, 160, 169, 129, 34}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 152, 122, 193, 104, 35, 111, 152, 154, 176, 118, 172}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 9}, 63}, {{107, 229, 240, 100, 52, 183, 48, 159, 145, 209, 188, 63, 49, 0, 216, 156}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 153, 175, 89}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 143, 101, 61}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 57, 110, 187, 34, 31, 88}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 48, 233, 7, 110, 160, 171}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 173}, 63}, {{107, 229, 240, 0, 71, 185, 152, 112, 164, 34, 24, 126, 251, 172, 27, 114}, 63}, {{107, 229, 240, 0, 0, 0, 141, 10, 197, 9, 25, 251, 160, 125, 30, 203}, 63}, {{107, 229, 240, 0, 0, 31, 3, 83, 15, 199, 138, 195, 40, 218, 173, 133}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 220, 161, 151}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 229, 125, 29}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 194, 210, 104, 222, 120, 109, 179}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 54, 248, 47, 196, 67}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 145, 111, 45}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 152, 254, 234, 139, 109, 48}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 213, 15, 232}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 8, 59, 24, 197, 54, 23, 15, 179}, 63}, {{107, 229, 240, 0, 0, 104, 147, 165, 20, 68, 188, 145, 3, 46, 235, 230}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 109}, 63}, {{107, 229, 240, 121, 68, 61, 35, 167, 57, 163, 192, 30, 64, 71, 228, 45}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 29, 61}, 63}, {{107, 229, 240, 157, 219, 245, 189, 79, 191, 141, 62, 141, 107, 34, 80, 138}, 63}, {{107, 229, 240, 0, 0, 201, 47, 7, 219, 133, 99, 238, 195, 43, 71, 82}, 63}, {{107, 229, 240, 0, 0, 0, 79, 21, 203, 240, 36, 243, 3, 138, 101, 47}, 63}, {{107, 229, 240, 0, 0, 66, 115, 115, 117, 112, 51, 123, 103, 157, 183, 207}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 73, 49, 60, 3, 91, 19, 245, 58}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 42, 226}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 34, 227, 156, 47, 16, 156}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 17}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 195, 100, 97, 11, 8, 110, 17, 50}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 121}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 158, 103, 166}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 82, 247, 139, 74, 164, 205, 249}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 32}, 63}, {{107, 229, 240, 0, 112, 90, 83, 95, 234, 94, 162, 143, 135, 33, 111, 9}, 63}, {{107, 229, 240, 0, 0, 0, 0, 94, 187, 97, 152, 163, 134, 36, 210, 179}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 127}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 107, 90, 180, 174, 251, 109, 254}, 63}, {{107, 229, 240, 0, 0, 0, 175, 203, 119, 151, 220, 188, 153, 201, 3, 44}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 22}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 182, 22, 96}, 63}, {{107, 229, 240, 86, 199, 2, 200, 167, 248, 54, 174, 115, 37, 111, 144, 52}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 70, 139, 123, 68, 74, 237}, 63}, {{107, 229, 240, 0, 0, 0, 22, 216, 93, 150, 248, 251, 156, 158, 81, 227}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 63}, {{107, 229, 240, 0, 0, 233, 208, 165, 150, 59, 2, 221, 18, 113, 209, 234}, 63}, {{107, 229, 240, 0, 0, 191, 174, 107, 109, 42, 123, 103, 25, 120, 73, 83}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 26, 152, 84, 1, 236, 188, 219, 9, 251, 217, 176}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 47, 212, 170}, 63}, {{107, 229, 240, 0, 0, 53, 139, 180, 182, 42, 55, 138, 31, 68, 51, 121}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 131, 9, 246, 8, 25, 215, 125, 83, 112, 114, 169, 192}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 185, 42, 88, 28, 14, 217, 246, 137}, 63}, {{107, 229, 240, 0, 0, 176, 198, 152, 135, 252, 44, 221, 4, 232, 212, 119}, 63}, {{107, 229, 240, 0, 0, 0, 0, 108, 69, 228, 196, 224, 232, 66, 215, 217}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 103, 226, 34, 17, 83}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 176}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 197, 77, 4, 55, 216, 155, 128, 155}, 63}, {{107, 229, 240, 0, 0, 0, 0, 237, 49, 75, 95, 227, 204, 73, 185, 255}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 233}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 124, 207}, 63}, {{107, 229, 240, 0, 0, 169, 40, 206, 189, 149, 149, 6, 214, 149, 112, 73}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 84}, 63}, {{107, 229, 240, 217, 21, 187, 154, 196, 153, 94, 112, 124, 83, 57, 223, 37}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 75, 195, 208, 176, 207, 223, 206, 112, 231, 26}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 66, 182, 14, 80, 16}, 63}, {{107, 229, 240, 0, 0, 0, 0, 210, 138, 85, 42, 84, 35, 44, 30, 88}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 236, 11, 127, 132, 10, 198, 109}, 63}, {{107, 229, 240, 0, 0, 139, 110, 217, 168, 21, 255, 108, 9, 76, 207, 143}, 63}, {{107, 229, 240, 0, 0, 0, 87, 166, 161, 158, 221, 61, 52, 209, 151, 113}, 63}, {{107, 229, 240, 135, 130, 107, 61, 204, 54, 160, 119, 93, 10, 137, 136, 95}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 96, 145, 16}, 63}, {{107, 229, 240, 0, 0, 0, 49, 105, 186, 85, 51, 97, 26, 14, 96, 60}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 157, 59, 122, 236, 47, 59, 93, 127}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 168, 67, 83, 16, 78, 64}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 67, 243, 218, 83, 32}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 149, 187, 95, 33, 84, 197, 208, 96}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 243, 254, 76, 39, 33, 183}, 63}, {{107, 229, 240, 0, 0, 218, 67, 159, 69, 119, 46, 164, 127, 41, 170, 205}, 63}, {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 8, 247, 137, 35, 105, 42}, 63}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 5, 126, 226, 207, 196, 193}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 153, 106, 142, 119, 232}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 234, 248, 105, 74}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 31, 67}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 205, 227, 138, 118, 167, 228}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 38, 179, 175, 103, 175, 163}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 160, 131, 12, 128, 237, 99, 163, 194}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 114, 209, 175, 220, 132}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 7, 24, 55, 61}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 23, 77, 163, 22, 196, 109}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 21, 167, 176, 111, 202}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 250, 239}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 235, 25, 215, 53, 105}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 244, 180, 229, 95, 74}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 53, 59, 156, 177}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 242, 176}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 205, 83, 206, 130, 244}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 164, 201, 232, 208, 171, 223, 111}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 160, 156, 227, 140, 104, 190, 228, 107}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 77, 177, 180, 137, 9, 63}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 163, 152, 174, 36, 131, 227}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 36, 68, 95}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 185, 6}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 117, 110, 162, 209, 159, 28}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 9, 78, 221, 242, 200, 216, 93, 42}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 41, 144}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 45, 230, 135, 107, 121}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 249, 135, 94, 217}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 209, 208, 107, 42, 120, 239, 189, 126}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 201, 170, 43, 232, 119}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 183, 56}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 113, 48, 154, 161, 234, 49}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 70, 152, 136, 110, 174, 15, 86}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 218, 193, 128, 207, 25, 85}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 183, 139, 239, 64}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 116, 168, 3}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 106, 98, 197, 218, 11}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 190, 51, 119, 173, 59, 141}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 28, 229, 64, 200, 171, 42}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 143, 97, 169, 62, 186, 134}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 3, 135}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 117, 86, 243, 53, 66, 65}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 187, 33, 0, 169, 104, 215, 98, 233}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 60, 161, 5, 34, 228, 102}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 129, 250, 201, 145, 146, 75, 146}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 108, 72, 93, 115, 122, 114, 222, 32}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 44, 89, 113, 197, 115, 29}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 39, 123, 154, 215, 215, 79, 226}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 92, 82, 71, 252}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 36, 72, 19}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 45, 114, 178, 160, 22}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 199, 137, 74, 191}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 48, 157}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 104, 176, 233, 138, 214, 125, 78, 229}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 139, 30, 156}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 55, 80, 106, 247, 207, 26, 247}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 8, 0, 152, 154, 54, 31}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 94, 32}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 103, 131, 210, 9, 224, 19, 239}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 50, 40, 66, 210, 62, 12}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 81, 155, 103}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 188, 210}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 1, 45, 47, 220, 129, 87, 132}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 251, 254, 18}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 59, 197}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 172, 49, 240}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 20, 203, 138, 167, 154, 4}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 29, 88, 105, 61, 229, 217, 15}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 206, 217, 48, 55, 65}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 112}, {{119, 208, 177, 235, 222, 252, 219, 0, 39, 160, 89, 170, 195, 89, 16, 163}, 112}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 235, 96, 166, 81}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 50, 131, 78, 153, 140, 134, 211}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 35, 106, 148, 78, 38, 187, 232}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 47, 16}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 147, 33, 37, 208, 154, 16, 129, 195}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 87, 98, 45}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 63, 11, 215, 14, 204, 254}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 148, 86, 140, 204, 235, 75, 174, 78, 114, 88}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 239, 152, 179, 190, 25}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 175, 195, 166, 92, 235}, 48}, {{178, 151, 220, 162, 120, 128, 209, 241, 55, 150, 73, 31, 255, 138, 63, 73}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 28, 185, 94, 193, 165, 138, 37, 136}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 243, 53}, 48}, {{178, 151, 220, 162, 120, 128, 242, 142, 212, 5, 205, 99, 6, 138, 113, 82}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 232, 225, 150, 55, 177, 229, 121, 36}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 163, 138, 27, 159, 176, 175, 175, 208}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 19, 5, 114, 162}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 94, 143}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 211, 223}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 35, 84, 139, 86, 72, 181}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 139, 100, 175, 101}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 251, 35, 231, 123, 122}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 176, 17, 57, 54, 20, 10, 85}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 62, 76}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 184, 156, 253, 198, 220}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 132, 193, 237, 68, 129, 190, 217}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 178, 105, 235, 103, 188, 51, 172}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 75, 134}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 88, 244, 32, 144, 157}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 13, 70, 188}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 244, 98, 210, 251, 70, 143, 56, 11}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 95, 68, 36, 122, 128, 221}, 48}, {{178, 151, 220, 162, 120, 128, 0, 190, 93, 153, 133, 162, 207, 88, 214, 8}, 48}, {{178, 151, 220, 162, 120, 128, 35, 206, 179, 254, 198, 87, 155, 231, 109, 65}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 45, 90, 176, 107, 61, 250}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 24, 207, 253, 63, 133, 71, 89, 215}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 243, 43, 240, 198, 51, 160, 16}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 6, 222, 210, 79}, 48}, {{178, 151, 220, 162, 120, 128, 0, 184, 80, 64, 162, 244, 171, 85, 36, 22}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 163, 197, 85}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 191, 192, 226}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 102, 18, 122, 176, 227}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 33, 32, 173, 215, 150}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 219, 76, 88, 211}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 156, 148, 4, 200, 225, 1, 67, 49}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 133, 105, 54, 127, 102}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 204, 201, 201, 18}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 5, 39, 215, 136, 186, 138, 238, 96}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 60, 69, 185, 37, 174, 95, 56}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 68, 227, 54, 92, 78}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 114, 99}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 111, 248, 99, 52, 138, 200, 119, 81}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 118, 111, 221, 20, 233, 178, 214}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 222, 154, 194, 74, 13, 245, 47, 44}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 232, 107, 81, 68, 252}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 72, 87, 140, 211}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 197, 0, 230, 232, 51, 3, 252}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 60, 163, 157, 69, 191, 80}, 48}, {{178, 151, 220, 162, 120, 128, 29, 166, 251, 217, 239, 218, 117, 8, 239, 178}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 60, 63}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 111, 238, 18, 171}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 91, 249, 69, 17, 197}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 237, 70, 156, 176, 197, 239, 175}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 201, 124, 137, 33, 124, 90, 35, 93}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 48}, {{178, 151, 220, 162, 120, 128, 0, 211, 64, 17, 2, 50, 235, 25, 151, 27}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 40, 109, 54, 152}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 83, 67, 151, 101}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 100, 151, 122, 183, 18, 112, 28}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 131, 113, 224}, 48}, {{178, 151, 220, 162, 120, 128, 0, 102, 86, 253, 103, 30, 243, 131, 208, 33}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 114, 21, 153, 152, 169, 181, 145, 145}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 171, 109, 6, 181, 56, 153, 206}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 67, 223, 28}, 48}, {{178, 151, 220, 162, 120, 128, 0, 100, 243, 43, 233, 123, 21, 235, 199, 248}, 48}, {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 123, 131, 197}, 48}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 100}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 45, 96, 129, 30, 181}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 120, 167, 31}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 218}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 155}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 168, 160, 77}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 226}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 30, 22, 175}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 174, 242, 52, 229}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 219, 95}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 105, 153, 114}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 187, 52, 179, 159, 230, 189, 24}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 231, 144, 198, 189, 130, 38, 108, 127}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 108, 70, 44, 73}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 207, 1, 150, 58, 242}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 195, 12, 187, 104}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 129, 30, 101, 34}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 214, 44}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 177}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 198, 165, 152, 107, 20, 23, 176}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 130, 34, 216, 15}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 195, 180, 11}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 11, 1, 213, 140, 226, 59}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 224, 30, 127, 138}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 70}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 83, 198, 197, 150, 251, 214, 9}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 180, 159, 247, 155, 95, 189}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 123, 38}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 58}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 118, 68, 19, 218}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 13, 174, 172, 214, 97, 225, 32, 169}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 67, 71, 86, 148, 49, 138, 255}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 53, 232, 113, 9, 47, 128, 177, 96}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 113, 122}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 69}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 79, 170, 14, 194}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 238, 164, 212}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 5, 127, 4, 12, 156, 194, 35, 125}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 244, 146, 95, 198, 143}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 21, 176}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 103}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 170, 187, 70, 30, 10}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 139}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 48, 228}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 7, 195}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 149, 249, 111, 235, 28, 68, 85}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 180, 171, 221, 186}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 96, 136, 44, 195, 177}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 169, 144, 128}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 114, 9, 56, 85, 166}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 43, 98, 48, 214, 118, 98}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 44, 111, 9}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 178, 45, 80, 105, 250}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 136, 198, 14, 60, 255}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 184, 11, 169, 198, 205, 242}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 82, 22, 255, 24, 58, 111, 217}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 83, 100, 113, 228, 240}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 94, 35, 58, 93, 241, 50}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 252, 239, 66, 155, 79, 85, 76}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 84, 20, 204, 180, 121}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 132, 49, 237, 68}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 179, 32, 130, 187, 199, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 58, 44, 11, 170, 245}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 165, 207, 219}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 23, 142, 3, 126, 215}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 91, 121, 87, 33}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 137}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 30, 2, 97, 5, 244, 162, 84}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 135, 91, 6}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 247, 210, 125, 69, 217, 166, 221}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 126, 32}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 193, 144, 151, 42}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 119}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 120}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 72, 83, 100}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 249, 24, 72}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 154, 109, 94, 137, 225, 85, 48, 201}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 197, 101, 225, 220, 159, 6}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 72, 140, 101}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 154, 145, 155, 230, 140, 51}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 126, 160}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 180, 83, 180}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 52, 233, 165}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 202, 112, 151, 153, 102, 1}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 26, 40, 17, 63, 119, 34, 173, 227}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 141, 111, 61, 177, 49}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 156}, {{126, 27, 252, 19, 219, 129, 121, 48, 0, 198, 39, 204, 2, 7, 200, 229}, 156}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 229, 18, 229}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 193, 72}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 15, 106, 50}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 173, 165, 113}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 103}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 206, 5}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 72, 222}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 228, 105}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 16, 207, 248}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 128}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 173, 65}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 144, 174, 82}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 217, 130, 63}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 228}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 228}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 201, 34, 196}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 89, 165, 43}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 99, 48, 124, 12}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 194}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 88, 217, 82, 253}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 107, 132, 93}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 24, 217, 98}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 148}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 228}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 32, 134, 252}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 182}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 79}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 224, 236}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 79}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 190}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 95, 202}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 122, 150, 120}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 59, 44, 206}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 17, 51, 13}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 132, 78, 217}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 224}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 128, 63, 137}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 202, 237, 199}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 149}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 210, 159}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 53, 234, 217}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 173, 240, 190}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 23, 99, 46}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 111, 14}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 245, 242, 244}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 69}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 221, 150}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 137, 107, 135}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 145, 91, 70}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 134, 43}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 170}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 20, 36}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 169, 110}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 190, 25, 50}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 88}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 196, 61, 226}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 5}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 115, 246}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 38}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 30}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 73, 199, 51}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 245}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 105, 103}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 158}, 120}, {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 67}, 120}, {{252, 107, 0, 0, 0, 0, 0, 216, 122, 18, 58, 178, 28, 181, 112, 71}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 160, 153, 91, 5, 67, 184, 35}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 126}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 137, 218}, 5}, {{252, 107, 0, 0, 0, 0, 57, 210, 122, 253, 195, 26, 110, 26, 100, 181}, 5}, {{252, 107, 0, 0, 0, 6, 37, 226, 122, 7, 245, 60, 171, 59, 27, 196}, 5}, {{252, 107, 0, 0, 0, 112, 39, 154, 174, 218, 137, 225, 175, 149, 38, 91}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 201}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 180, 85}, 5}, {{252, 107, 0, 0, 0, 65, 1, 20, 52, 239, 171, 233, 15, 144, 116, 217}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 228, 44, 70, 233, 55, 125, 198}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 131}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 50, 196, 19, 3, 163, 52, 252}, 5}, {{252, 107, 0, 0, 0, 0, 159, 31, 51, 180, 113, 129, 145, 116, 117, 42}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 133}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 89, 108, 85, 194}, 5}, {{252, 107, 0, 0, 0, 0, 0, 255, 143, 125, 115, 90, 77, 236, 182, 145}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 158, 241, 221}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 210, 191, 71, 117}, 5}, {{252, 107, 0, 0, 0, 230, 177, 134, 114, 194, 85, 113, 65, 224, 167, 194}, 5}, {{252, 107, 0, 0, 0, 203, 46, 253, 192, 157, 234, 4, 29, 41, 133, 236}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 87, 157}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 83}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 12, 30, 199, 130}, 5}, {{252, 107, 0, 50, 219, 12, 41, 249, 158, 142, 178, 190, 206, 154, 224, 141}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 167, 120}, 5}, {{252, 107, 0, 0, 0, 0, 80, 124, 228, 171, 122, 35, 60, 57, 107, 249}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 216, 191, 29, 62, 198, 111}, 5}, {{252, 107, 0, 0, 0, 160, 85, 165, 39, 236, 37, 31, 151, 113, 175, 156}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 183}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 215, 153, 2, 196, 11, 94, 174}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 62, 6, 236, 236, 50, 176}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 52, 47, 48}, 5}, {{252, 107, 0, 0, 0, 0, 0, 243, 43, 20, 67, 56, 171, 95, 170, 70}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 195, 233, 239, 68, 239, 45, 80}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 245, 106, 252, 119, 173, 238, 113}, 5}, {{252, 107, 0, 0, 0, 0, 0, 95, 84, 128, 77, 182, 164, 62, 171, 68}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 205, 173, 4}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 227, 116, 66, 94}, 5}, {{252, 107, 0, 130, 5, 235, 183, 194, 92, 24, 29, 238, 42, 207, 196, 122}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 241, 181, 24}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 61, 105, 190}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 229, 25, 145, 192, 180, 71}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 134, 121, 8, 96, 2, 204}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 67, 205, 65, 202}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 15, 166, 149, 253, 250, 131, 7, 169, 245, 6, 137, 183}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 103}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 5, 48, 56}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 192, 166, 71}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 153, 209, 239, 127, 49, 236, 108, 32, 141, 243}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 5}, {{252, 107, 0, 150, 74, 239, 22, 30, 219, 249, 102, 60, 24, 197, 251, 249}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 75}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 187, 200}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 30, 181, 92, 155, 239, 133}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 100, 19, 86}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 37, 91, 28, 111, 141, 82}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 231}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 100, 9, 65}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 65, 154, 97, 213, 164, 252, 252, 43}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 11, 88, 111}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 219, 241, 112, 21, 194, 106, 51}, 5}, {{252, 107, 0, 0, 0, 147, 232, 108, 63, 187, 124, 222, 46, 1, 117, 243}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 77, 139, 193}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 167, 141, 90, 128, 64, 21}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 39, 255, 46, 243, 32, 17}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 154}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 57, 253, 24, 152, 193, 122, 18, 240, 211}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 202, 4}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 25, 132}, 5}, {{252, 107, 0, 0, 0, 0, 0, 242, 192, 188, 2, 225, 12, 1, 194, 219}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 59, 72}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 250, 231, 0, 29, 173, 149, 5, 220}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 5}, {{252, 107, 0, 63, 146, 119, 228, 239, 230, 152, 207, 58, 191, 0, 187, 140}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 101, 44, 193}, 5}, {{252, 107, 0, 0, 0, 0, 0, 183, 130, 72, 218, 120, 201, 167, 248, 34}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 119, 21}, 5}, {{252, 107, 0, 203, 44, 89, 154, 46, 129, 95, 84, 74, 117, 206, 223, 176}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 9, 33}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 88, 173, 57, 101, 203, 95, 241}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 5}, {{252, 107, 0, 0, 0, 0, 139, 117, 75, 42, 91, 135, 224, 8, 246, 83}, 5}, {{252, 107, 0, 0, 0, 12, 254, 253, 81, 17, 232, 198, 11, 250, 242, 56}, 5}, {{252, 107, 0, 0, 0, 0, 56, 202, 81, 173, 137, 238, 40, 249, 152, 126}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 128}, 5}, {{252, 107, 0, 0, 0, 0, 165, 147, 123, 186, 187, 10, 48, 53, 23, 222}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{252, 107, 0, 0, 0, 0, 0, 0, 0, 150, 61, 22, 209, 19, 233, 245}, 5}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 30, 188, 62}, 64}, {{192, 0, 0, 0, 0, 0, 42, 235, 53, 132, 128, 99, 169, 223, 191, 28}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 145, 243, 131, 193, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 220, 233, 54, 2, 191}, 64}, {{192, 0, 0, 87, 160, 126, 152, 66, 38, 181, 9, 143, 128, 183, 97, 134}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 82, 21, 91, 158, 70, 247, 229}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 188}, 64}, {{192, 0, 0, 0, 0, 0, 136, 21, 34, 253, 13, 127, 182, 161, 7, 25}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 211, 139, 221}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 140, 135, 248, 27}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 81, 236, 88, 118, 133, 218, 85}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 171}, 64}, {{192, 0, 0, 0, 0, 0, 0, 162, 100, 223, 126, 236, 51, 7, 171, 176}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 64, 139, 15, 68, 52, 22, 170}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 199, 41, 98, 196, 243, 33, 101}, 64}, {{192, 0, 0, 118, 227, 149, 23, 53, 69, 54, 131, 58, 94, 81, 44, 189}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 131, 56, 203, 23, 119, 212, 253}, 64}, {{192, 0, 0, 0, 0, 0, 127, 181, 10, 227, 56, 235, 212, 26, 60, 56}, 64}, {{192, 0, 0, 131, 88, 13, 92, 24, 186, 46, 130, 125, 92, 138, 64, 25}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 234, 181}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 50, 255, 96, 111, 82, 108, 42}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 244, 33, 159, 46}, 64}, {{192, 0, 0, 0, 0, 0, 93, 96, 161, 117, 52, 166, 82, 165, 47, 106}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 175}, 64}, {{192, 0, 0, 0, 0, 0, 0, 241, 177, 75, 103, 57, 232, 121, 244, 21}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 165, 117, 119, 35}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 244, 200, 29, 179, 224}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 181, 78, 112, 85, 134, 11, 149}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 247, 68, 255, 54, 194, 148, 224}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 240, 110, 25, 87, 140}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 170, 33, 94, 180, 206, 64, 250}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 224, 193, 112, 142, 121, 147, 89, 246}, 64}, {{192, 0, 0, 0, 0, 0, 0, 76, 14, 203, 133, 62, 20, 58, 134, 226}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 208, 62}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 8, 174, 159, 17, 150, 50, 73}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 213, 99, 180, 133, 167, 224, 157, 68}, 64}, {{192, 0, 92, 244, 223, 25, 23, 59, 172, 124, 76, 121, 198, 136, 229, 112}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 223, 49}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 173, 68, 213}, 64}, {{192, 0, 0, 0, 144, 121, 105, 106, 66, 163, 12, 22, 125, 219, 49, 158}, 64}, {{192, 0, 0, 0, 67, 8, 124, 151, 181, 32, 42, 209, 30, 238, 98, 59}, 64}, {{192, 0, 0, 0, 0, 114, 3, 89, 205, 33, 114, 200, 182, 117, 52, 234}, 64}, {{192, 0, 0, 0, 0, 28, 97, 238, 98, 130, 66, 65, 184, 31, 148, 28}, 64}, {{192, 0, 0, 0, 0, 26, 40, 14, 85, 157, 92, 144, 181, 135, 63, 176}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 112, 50, 254, 104, 48, 127, 86, 33}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 204, 249}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 210, 10, 0, 162, 248, 198, 134, 114}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 2, 135, 23, 180, 249}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 93, 237, 43, 195}, 64}, {{192, 0, 0, 0, 190, 35, 64, 2, 209, 102, 202, 65, 25, 97, 120, 108}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 175}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 64}, {{192, 0, 0, 0, 0, 0, 172, 108, 198, 114, 111, 207, 135, 255, 61, 114}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 243, 105, 190}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 22, 163, 121, 192, 246, 113, 137}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 64}, {{192, 0, 0, 0, 0, 116, 107, 84, 48, 87, 243, 45, 29, 124, 60, 232}, 64}, {{192, 0, 0, 134, 51, 222, 83, 201, 76, 215, 148, 209, 71, 88, 130, 76}, 64}, {{192, 0, 0, 0, 0, 0, 14, 214, 123, 56, 82, 62, 60, 200, 111, 83}, 64}, {{192, 1, 88, 149, 84, 141, 104, 88, 170, 198, 106, 183, 67, 165, 52, 188}, 64}, {{192, 0, 224, 235, 113, 177, 158, 9, 195, 35, 206, 125, 204, 181, 40, 45}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 52, 58, 193, 234, 52, 74, 115, 171}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 145, 3}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 171, 6}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 62, 85}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 31, 89, 229, 69, 95}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 68}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 169, 65, 85, 95, 119}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 225, 71, 107, 56, 239, 217, 248, 142}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 72, 190, 214, 236, 215, 119, 54, 70}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 43, 212, 4, 96}, 64}, {{192, 0, 0, 0, 189, 22, 39, 164, 230, 232, 147, 73, 176, 133, 151, 128}, 64}, {{192, 0, 0, 0, 0, 0, 14, 201, 24, 200, 84, 166, 12, 255, 86, 139}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 56, 47, 58, 0, 227, 114, 224, 11}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 223, 131}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 202, 24, 230}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 53, 25, 234, 41, 197, 200, 235}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 144, 8, 113}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 24, 105}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 106, 72, 14, 114, 167, 54, 59, 89, 73, 3, 144, 41, 27}, 64}, {{192, 0, 93, 206, 25, 165, 120, 250, 125, 151, 215, 45, 163, 138, 70, 82}, 64}, {{192, 0, 0, 0, 42, 218, 149, 25, 39, 117, 125, 6, 154, 230, 96, 127}, 64}, {{192, 0, 0, 0, 14, 32, 30, 221, 47, 205, 30, 56, 70, 95, 128, 176}, 64}, {{192, 0, 0, 0, 137, 148, 160, 0, 151, 53, 243, 33, 53, 25, 127, 122}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 201, 92, 156, 67, 135, 3, 170, 52, 117, 156, 83, 109, 151, 240}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{64, 0, 0, 0, 0, 0, 69, 244, 146, 54, 122, 96, 46, 102, 47, 233}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 243, 218, 102}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 114, 225, 44}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 220, 213, 172, 175, 55, 216, 196, 96, 191, 92, 110, 10}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 76, 4}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 3, 238, 135, 228}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 247, 78}, 84}, {{64, 8, 10, 47, 228, 96, 102, 212, 168, 18, 56, 77, 27, 92, 183, 66}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 146, 222, 80, 210, 110, 22, 229}, 84}, {{64, 0, 0, 0, 0, 179, 152, 169, 61, 208, 74, 162, 77, 38, 242, 93}, 84}, {{64, 0, 0, 0, 0, 0, 118, 227, 60, 191, 38, 204, 37, 28, 22, 89}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 84}, {{64, 0, 0, 0, 0, 0, 10, 75, 114, 202, 143, 54, 54, 198, 170, 217}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 200}, 84}, {{64, 0, 0, 0, 0, 0, 0, 169, 1, 7, 26, 79, 63, 75, 98, 105}, 84}, {{64, 0, 0, 0, 205, 241, 64, 135, 134, 92, 222, 143, 172, 6, 232, 197}, 84}, {{64, 0, 0, 0, 0, 0, 65, 46, 1, 206, 164, 30, 89, 169, 218, 58}, 84}, {{64, 0, 0, 0, 0, 0, 0, 172, 253, 174, 135, 64, 107, 135, 45, 138}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 52, 131}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 55}, 84}, {{64, 0, 0, 75, 155, 247, 23, 74, 224, 243, 249, 164, 242, 104, 83, 227}, 84}, {{64, 0, 54, 13, 118, 45, 190, 114, 139, 33, 174, 122, 254, 1, 144, 64}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 48, 48}, 84}, {{64, 0, 0, 0, 0, 149, 26, 161, 29, 13, 127, 191, 52, 102, 250, 213}, 84}, {{64, 0, 0, 0, 0, 19, 159, 161, 175, 169, 10, 137, 90, 55, 84, 187}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 181, 175, 186, 186, 119, 166, 224, 31}, 84}, {{64, 0, 0, 0, 0, 47, 141, 54, 229, 219, 55, 177, 40, 235, 160, 144}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 13, 65, 134, 171, 103, 84, 82}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 185, 198, 56, 93, 124, 153, 189, 74}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 117, 122, 160, 46, 156, 119, 194, 251}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 103}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 247}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 49, 171, 233}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 109, 120, 43, 75, 85, 169, 192}, 84}, {{64, 0, 0, 0, 0, 0, 0, 11, 186, 94, 77, 193, 105, 215, 246, 201}, 84}, {{64, 0, 0, 0, 0, 0, 0, 230, 244, 142, 168, 55, 196, 94, 23, 94}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 40, 203, 176}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 246, 173, 227, 138, 180, 202, 34}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 44, 190, 28, 167, 231, 34, 155}, 84}, {{64, 0, 0, 0, 0, 0, 0, 23, 221, 85, 74, 166, 109, 193, 177, 174}, 84}, {{64, 0, 0, 70, 117, 186, 91, 15, 20, 141, 35, 234, 240, 3, 63, 59}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 224, 11}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 198, 9, 33, 228, 115, 187, 232}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 184, 122}, 84}, {{64, 0, 0, 240, 214, 154, 180, 252, 31, 124, 97, 182, 131, 4, 48, 101}, 84}, {{64, 0, 0, 0, 0, 0, 0, 168, 148, 188, 13, 8, 164, 150, 73, 2}, 84}, {{64, 0, 0, 0, 0, 0, 91, 105, 96, 177, 79, 70, 214, 246, 113, 188}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 84}, {{64, 0, 0, 0, 0, 0, 0, 28, 197, 115, 219, 52, 46, 63, 1, 232}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 144, 120, 1, 211, 98, 154, 185}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 251}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 182, 116, 14, 116, 137, 207, 8}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 52}, 84}, {{64, 0, 0, 0, 0, 71, 22, 118, 89, 91, 174, 102, 177, 68, 11, 197}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 54, 35}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 148, 243, 61, 22, 94, 98, 50}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 123, 85, 245, 166, 170, 65, 23}, 84}, {{64, 0, 53, 146, 214, 254, 143, 68, 210, 102, 91, 228, 205, 29, 219, 180}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 231, 0, 159}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 190, 109, 211, 31, 165}, 84}, {{64, 0, 0, 0, 82, 153, 247, 15, 39, 13, 107, 210, 163, 231, 123, 0}, 84}, {{64, 0, 15, 172, 111, 34, 2, 157, 176, 166, 58, 43, 128, 225, 8, 223}, 84}, {{64, 77, 232, 16, 196, 218, 247, 195, 19, 75, 248, 233, 1, 126, 119, 126}, 84}, {{64, 0, 0, 0, 204, 230, 182, 249, 21, 14, 180, 251, 72, 198, 255, 25}, 84}, {{64, 0, 0, 0, 0, 0, 0, 197, 225, 189, 233, 191, 74, 202, 165, 246}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 5, 255}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 196}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 252, 83, 244}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 214, 180, 165, 117, 172}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 158, 127, 52, 159, 222}, 84}, {{64, 0, 159, 159, 217, 248, 215, 134, 73, 76, 104, 241, 227, 83, 88, 69}, 84}, {{64, 0, 0, 0, 0, 0, 224, 69, 231, 235, 27, 133, 111, 102, 22, 209}, 84}, {{64, 0, 0, 0, 155, 120, 105, 68, 39, 92, 202, 78, 14, 130, 201, 34}, 84}, {{64, 0, 0, 165, 190, 100, 212, 46, 250, 136, 169, 22, 1, 195, 148, 78}, 84}, {{64, 0, 8, 100, 183, 166, 243, 227, 234, 151, 139, 76, 203, 10, 124, 100}, 84}, {{64, 0, 0, 0, 170, 103, 197, 108, 253, 198, 254, 131, 101, 166, 254, 126}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 142, 79, 156, 20, 224}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 250}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 84}, {{64, 182, 89, 43, 93, 4, 239, 27, 57, 14, 70, 231, 246, 73, 163, 151}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 70, 1, 220, 103}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 76, 186, 202}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 139, 235, 153, 107, 143, 80, 35, 120}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 198, 168, 0, 220, 58}, 84}, {{64, 0, 0, 0, 0, 0, 0, 161, 46, 34, 178, 28, 72, 31, 163, 232}, 84}, {{64, 42, 130, 132, 90, 221, 202, 67, 58, 153, 136, 126, 31, 255, 3, 30}, 84}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 158, 156, 222}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 109}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 140}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 109, 43}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 35, 206}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 12, 39}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 129}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 182, 16}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 125, 90}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 222}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 144}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 110, 69}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 243, 101}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 65}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 242, 145, 178}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 143}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 7, 166, 247}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 44, 199}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 225, 19}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 124, 95}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 189}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 241}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 35}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 17}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 245, 78}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 169}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 33, 209}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 137}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 179}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 103, 192}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 191, 235}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 9, 171}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 232, 245}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 176, 80}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 249, 69}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 101, 204}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 137, 12, 120}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 16, 25}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 150, 34}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 214}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 226}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 197, 182}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 124}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 6}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 56}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 166, 246}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 104, 192}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 82, 88, 101}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 195}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 70, 106}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 156}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 88}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 196, 148, 155}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 42}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 222, 158}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 235, 172}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 183, 44, 148}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 251, 47}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 86, 156, 140}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 33}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 142}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 179, 192, 139}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 111}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 67}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 219, 172}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 24}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 231}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 52}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 93, 22, 75}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 232, 100}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 222}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 118, 182, 111, 229}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 109, 59}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 87, 46, 215, 113}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 144, 84, 37}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 236, 112, 237, 33}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 148}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 206, 206}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 49, 134, 41}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 19, 101}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 114, 142}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 65}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 23, 23, 182, 106}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 5, 6}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 140}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 180}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 156, 150}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 90, 170, 195, 127}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 17}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 94, 37, 183}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 60, 39, 251, 135}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 167, 154, 98}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 47, 73, 148, 238}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 114, 23, 63}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 253, 231}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 57, 249}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 82}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 43}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 154, 178, 142}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 45}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 35, 204}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 226, 54}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 104, 158, 66}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 37}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 43, 1, 63}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 15, 75, 61, 187}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 184, 241, 192, 190}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 73}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 9, 86, 20, 220}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 163, 243}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 91, 203, 35}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 44, 187}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 182, 176, 245}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 178, 49}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 117}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 7, 148}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 238, 115}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 216}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 208}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 223, 114, 162}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 69, 230, 190}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 119, 130, 203}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 88}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 75, 11}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 228}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 252, 246, 167, 80}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 170, 181, 84, 56}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 92, 152}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 228, 218}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 7, 20, 226, 240, 11}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 174}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 80, 10, 135, 92}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 124, 152, 9}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 10, 31, 98, 194}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 52, 193, 50}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 93, 61, 214, 161}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 88, 110}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 35, 93, 228, 202, 203}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 136, 154, 84, 19}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 231}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 76, 24}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 208, 251}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 109}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 97}, 81}, {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 81}, {{178, 144, 203, 104, 0, 0, 38, 104, 139, 202, 1, 163, 174, 7, 20, 57}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 188, 38}, 96}, {{178, 144, 203, 104, 0, 0, 135, 36, 242, 97, 100, 6, 185, 196, 150, 209}, 96}, {{178, 144, 203, 104, 0, 0, 0, 167, 190, 194, 114, 25, 197, 133, 191, 180}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 250}, 96}, {{178, 144, 203, 104, 0, 0, 33, 39, 172, 73, 77, 223, 146, 127, 240, 147}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 242, 215, 232, 22, 202, 165, 219}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 116, 162, 81, 36, 153}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 199, 17, 172, 91, 74, 27, 0}, 96}, {{178, 144, 203, 104, 0, 81, 240, 46, 15, 223, 112, 211, 108, 218, 16, 206}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 206, 3}, 96}, {{178, 144, 203, 104, 168, 186, 57, 239, 254, 93, 128, 254, 37, 0, 254, 141}, 96}, {{178, 144, 203, 104, 0, 0, 0, 120, 176, 95, 213, 37, 116, 224, 182, 82}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 18, 255, 42, 135, 49}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 74, 37, 152, 30, 177, 195, 252}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 172, 13, 64, 178, 164}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 128, 63, 34, 59, 82, 140, 60}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 42, 75, 126, 235, 91, 2, 142}, 96}, {{178, 144, 203, 104, 0, 0, 111, 61, 42, 89, 129, 42, 7, 153, 220, 152}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 61, 129, 182, 175}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 102, 12}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 146, 29, 141, 155, 160, 255, 230}, 96}, {{178, 144, 203, 104, 0, 35, 17, 135, 97, 152, 32, 3, 132, 57, 58, 232}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 120}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 181, 8}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 33, 22, 33, 26, 126, 151, 22}, 96}, {{178, 144, 203, 104, 0, 0, 193, 97, 16, 127, 187, 50, 106, 6, 235, 111}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 88, 168}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 0, 155, 53, 91, 246, 5, 33, 198, 224, 189, 85}, 96}, {{178, 144, 203, 104, 0, 0, 160, 86, 27, 93, 236, 54, 184, 13, 55, 100}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 131, 191, 96, 26, 237, 39}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 37, 208}, 96}, {{178, 144, 203, 104, 0, 0, 9, 192, 161, 247, 103, 202, 132, 249, 115, 175}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 176, 136, 102, 123}, 96}, {{178, 144, 203, 104, 0, 0, 64, 7, 150, 88, 157, 54, 13, 110, 0, 56}, 96}, {{178, 144, 203, 104, 0, 253, 71, 181, 6, 254, 123, 232, 219, 88, 94, 78}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 93, 146, 181, 67, 22, 19}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 64, 8, 87, 66, 226, 197, 139}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 96}, {{178, 144, 203, 104, 85, 18, 172, 243, 155, 201, 211, 158, 97, 114, 187, 164}, 96}, {{178, 144, 203, 104, 0, 0, 148, 0, 249, 87, 127, 128, 12, 44, 85, 162}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 60, 118, 63, 138, 97}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 223, 136, 156, 144, 97, 236}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 96}, {{178, 144, 203, 104, 0, 0, 0, 50, 147, 14, 43, 83, 235, 243, 11, 213}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 208, 254, 81, 204, 240, 172, 174, 170}, 96}, {{178, 144, 203, 104, 0, 22, 233, 186, 45, 135, 209, 140, 23, 136, 114, 76}, 96}, {{178, 144, 203, 104, 0, 150, 108, 156, 1, 230, 193, 37, 159, 214, 140, 222}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 66}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 0, 0, 208, 233, 229, 147, 58, 110, 11, 79, 128}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 31, 49, 9, 79, 194}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 74}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 118, 224}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 162, 27, 14, 167}, 96}, {{178, 144, 203, 104, 0, 0, 238, 41, 250, 48, 173, 119, 159, 131, 215, 135}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 145, 56, 226, 142, 112, 151, 37}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 171, 107}, 96}, {{178, 144, 203, 104, 170, 105, 98, 34, 122, 64, 198, 149, 188, 78, 254, 141}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 160, 201, 231, 174, 148}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 42, 216, 230, 164}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 69, 190, 77, 46, 60, 228, 52, 231}, 96}, {{178, 144, 203, 104, 0, 0, 1, 148, 36, 59, 193, 16, 140, 73, 125, 79}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 157}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 32, 129, 12, 185, 100, 89, 57, 223}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 46, 210, 236, 151, 122, 54}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 0, 0, 96, 18, 36, 26, 170, 227, 12, 16, 102}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 252}, 96}, {{178, 144, 203, 104, 0, 0, 0, 151, 106, 17, 85, 22, 210, 145, 169, 152}, 96}, {{178, 144, 203, 104, 0, 0, 233, 106, 192, 141, 140, 204, 229, 243, 231, 239}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 43}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 98, 1, 20, 58, 217}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 129}, 96}, {{178, 144, 203, 104, 160, 184, 181, 251, 166, 108, 151, 86, 200, 241, 241, 15}, 96}, {{178, 144, 203, 104, 0, 0, 182, 50, 4, 114, 247, 161, 177, 6, 111, 144}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 122, 136}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 83, 104}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 173}, 96}, {{178, 144, 203, 104, 0, 0, 84, 240, 89, 143, 247, 116, 80, 137, 52, 23}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 158, 19, 207, 89}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 24, 183, 31, 113}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 226, 163, 211, 235, 60}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 194, 82}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 22, 177, 35, 244, 136, 7}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 120, 71, 203, 197, 179, 97, 25, 168, 164, 143, 238}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 125, 49}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 18}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 92, 193, 153, 133, 88, 65, 40, 154}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 92, 0, 169, 44, 227, 221, 220, 252}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 96}, {{178, 144, 203, 104, 0, 0, 63, 53, 227, 61, 45, 44, 183, 153, 98, 190}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{178, 144, 203, 104, 0, 0, 243, 117, 106, 246, 243, 0, 58, 84, 1, 161}, 96}, {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 214, 67, 152, 33}, 96}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 6}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 115}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 127}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 135}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 125}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 210}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 82}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 212}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 219}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 226}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 123}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 41}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 102}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 40}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 203, 232, 155, 94}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 190, 163, 119}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 57}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 228}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 204, 100, 45, 139, 101, 82, 20}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 6, 196, 239, 159, 241, 226, 49}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 134, 69, 166, 47, 91}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 138, 199, 97, 52, 238, 40, 249}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 183, 172, 156, 237, 213, 184, 83}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 88}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 118, 101, 130, 91}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 5, 104, 182}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 77, 102, 115, 116, 169, 219}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 211, 15, 213}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 140, 175, 214, 163, 45}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 4, 144, 231, 190, 192}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 85, 164, 97, 125, 101, 46}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 148}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 240, 143}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 193, 2, 209, 122, 179, 245}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 149, 167, 219, 225, 243}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 221, 207, 105, 215, 155, 51}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 26, 85}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 100}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 242, 63, 142, 78, 155, 67}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 170, 188, 83, 185, 209, 115, 32, 144}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 149, 146, 5, 47}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 13, 60, 203, 46, 237}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 246, 188, 107, 54, 11}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 79, 195, 205, 221, 119, 196}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 155, 80, 87, 79}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 145, 21, 48, 106, 225, 118}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 237}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 217, 92, 173, 2, 222, 71}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 213, 117, 229, 140}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 43, 76}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 87, 44, 29, 114, 214, 31}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 142, 58, 165, 184, 127, 79, 252}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 39, 242, 101, 225, 233, 150, 149}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 71, 78, 91, 170, 76, 165}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 113, 229, 41}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 241, 21, 171, 217}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 163}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 222, 209, 216, 79}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 177, 25, 15, 141, 188}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 73, 37, 246, 180, 247, 56, 201}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 150}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 177, 128, 69, 39}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 96, 114, 59, 150, 223, 251, 20, 170}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 121}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 198, 211}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 101, 170, 34, 133, 4}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 132}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 138, 202}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 64, 161, 222, 42, 219}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 116}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 198, 241, 62, 194}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 13, 19, 51, 108, 121, 108, 125}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 247, 119, 239}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 100, 56, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 50, 170, 72}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 201, 24, 217, 41, 79, 172, 126}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 149, 124, 76}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 202, 141, 111, 204, 16, 6}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 24, 222, 211}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 246}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 22}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 23, 99}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 76, 61}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 28, 216, 48, 20, 83, 224, 164, 178}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 96}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 149, 90, 166, 204, 42}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 59, 93, 60, 149, 154, 77, 105, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 34}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 235, 210, 177, 26, 245}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 151, 114}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 45, 204, 1, 112, 66, 182, 227}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 102, 197, 124, 43, 21, 239, 84}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 6, 212, 192}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 217, 204, 136, 136}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 183, 112}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 21, 229, 171, 200, 72, 209, 226}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 190, 207}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 212, 201, 39}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 161}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 205, 232, 6}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 132, 28}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 191, 113, 123, 167, 118}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 9, 33, 202}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 74, 238, 179, 90}, 143}, {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 4, 152, 63, 158, 254, 212}, 143}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 130, 127}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 228, 160, 177, 99, 177, 180}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 218}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 234, 109, 70, 78, 195}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 98, 85}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 84, 207, 95, 2}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 188, 17, 230, 61, 94, 10}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 151}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 46, 208, 60, 76, 211, 157}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 175, 166, 106, 47, 71, 112}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 64, 232, 24, 74, 173}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 61}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 185, 104}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 43, 51, 188, 243, 102, 74, 212}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 137, 93}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 98, 34, 210, 103, 124, 121, 249}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 8, 70, 151}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 127, 67, 3}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 2, 159}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 17, 105, 98, 207}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 254}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 88, 141, 154, 79, 153}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 142, 45, 171, 126, 73, 74}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 74, 147, 211}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 127, 131}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 62, 154, 153, 186, 200, 155}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 45, 137, 8, 208}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 160, 40, 194, 190, 53}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 181, 101}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 254, 72, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 28, 236, 210, 234, 93}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 46, 235, 4, 252}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 232}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 4, 170, 150, 101, 144, 31, 243}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 35, 112, 96, 154, 177}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 116}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 105, 226, 166, 175, 223}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 160}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 243}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 19, 9, 197, 173}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 194, 118, 94}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 191}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 246, 55, 0, 69, 45, 82}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 28, 50, 66, 33}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 157, 68, 14, 151, 38}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 117, 67, 199, 37, 98, 40}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 116, 19, 176, 149, 220}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 254, 80, 20, 5, 162, 132}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 132, 20, 190, 47}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 4, 93, 133, 34}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 236, 122, 46}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 7, 103, 209}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 157, 234, 90}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 157, 25}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 245}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 33, 58, 213, 100}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 39, 255, 252, 37}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 2, 255, 4}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 102}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 47, 72, 159, 209, 56}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 126, 235, 221, 217}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 219, 194, 14, 231}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 222, 146, 252, 116, 210}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 173, 38}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 73, 43, 5, 86, 132, 77, 250}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 168, 49, 183, 144, 77}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 49, 70, 139, 38, 168, 41}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 32, 72, 30, 103, 173}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 16, 35, 99, 237, 118}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 70, 14, 228, 191}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 157, 171, 177, 164}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 147, 228, 198, 76, 150}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 242, 241, 27}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 229, 13}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 148}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 20, 140, 33, 227, 208, 29}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 119, 21, 215, 73}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 189}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 110, 95, 252}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 233, 152, 189, 131, 145}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 213, 26, 154}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 119, 116}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 13, 70, 224, 199}, 69}, {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 52, 39, 102, 31, 20, 241}, 69}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 197}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 255, 148, 206, 117}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 145, 75}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 225}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 194, 161, 87, 133}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 38, 206, 239}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 146}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 127}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 197, 218, 98}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 220, 126}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 13}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 142, 142}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 106}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 133, 142}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 105, 62, 118, 131}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 53, 96, 206}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 117, 190}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 79, 156, 189}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 235}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 240, 242, 59}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 229}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 69, 66, 149}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 148}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 149, 119}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 233, 153, 50}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 183}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 7}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 74, 57, 26}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 174}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 41}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 51, 94}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 207, 137}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 206, 38, 183}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 4, 121, 35}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 229, 136}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 226, 227}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 104, 137}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 252, 107, 107}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 52, 102}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 130, 249, 122, 51}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 217, 209}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 138, 201}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 167, 143}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 162, 218, 20, 11}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 107, 68, 187, 47}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 236, 175}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 185, 204}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 15, 152, 138}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 39, 65}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 71, 203}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 186, 10}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 140, 182}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 99, 129}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 137, 156, 69}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 53}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 8, 92}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 213, 198, 94, 153}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 110, 1}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 20, 21, 190}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 5, 125, 240, 88}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 216, 228, 59}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 163, 218, 158}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 224, 253}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 117}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 203, 208, 73, 57}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 174}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 217}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 172, 53, 68, 141}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 87, 157, 231, 92}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 4, 43, 164}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 93}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 182, 159}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 50, 88, 106}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 34, 181, 28}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 53, 111, 242, 18}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 89, 181}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 167, 136}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 221, 6, 68}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 48}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 147, 109, 12, 51, 247}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 71, 109, 183, 180}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 107, 90, 48, 226, 19}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 253, 142}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 124, 100, 92, 174, 85, 39, 181}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 80}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 193, 131, 4, 102, 119, 223}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 31, 192, 1, 80, 38}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 129, 96, 24, 146, 30, 226, 32}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 4}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 57, 97}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 242, 107, 165, 103, 179}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 244, 214, 21, 80}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 238, 139, 157}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 207}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 213, 141, 173}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 135, 24, 213, 108, 156}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 115, 132, 85, 190, 20, 181, 242}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 174, 17, 24, 32, 91, 195}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 255, 118, 205, 81}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 29, 165, 201, 183, 132, 152}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 175, 48, 204, 87, 220, 52, 41}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 189, 141, 232}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 153, 254, 147, 59, 62, 160, 184}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 33, 56, 39}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 27, 5, 229, 237, 137, 199}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 148, 18, 23, 44, 76, 111}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 134, 241, 51, 157}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 158, 95, 91, 158, 253}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 127, 253, 1, 104, 118, 195}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 118, 32, 10, 253}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 218, 79, 5, 44}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 196, 118, 105, 50}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 239, 78, 100, 12, 249}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 174}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 5, 15, 204, 29}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 116, 169, 7, 54, 179, 182}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 151, 90, 52, 4, 50}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 120, 35}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 59, 210, 148}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 225}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 137, 45, 46, 93, 104, 214, 65}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 212, 102, 4, 66, 158, 181}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 129}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 154, 189, 216, 93}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 57, 210, 220, 187, 45, 213}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 109, 143, 238, 200}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 155, 87, 159, 198, 231}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 112, 145, 63}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 243, 3, 182, 213, 163}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 42, 233, 109, 170}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 230, 55}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 66, 42, 206, 104}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 49, 109, 248, 113}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 193, 79}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 123, 77, 40, 175, 10, 252}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 27, 136, 243, 126, 213}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 122, 163, 43, 49, 207}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 127, 250, 163, 174}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 58, 51, 203}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 35, 26, 237, 77, 157, 147, 8}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 57, 141, 234, 110, 62, 119}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 12, 216, 187, 101, 228}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 173, 55}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 152, 159, 113, 8}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 143}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 56, 110, 102}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 107, 85, 36}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 185, 126, 93, 90}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 113, 115, 71, 246}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 55, 89}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 29, 67, 240, 166, 11, 27}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 7, 84, 36, 12, 89, 253, 151}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 148, 112, 161}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 98}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 58, 157, 181, 159, 153}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 129, 34, 150, 150, 74}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 227, 36, 241}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 72, 95, 178, 225}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 75, 187, 14, 207}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 88, 157, 250, 28, 139}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 42, 11, 171, 77}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 145, 84, 218}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 80, 65, 80}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 180, 145, 39, 118, 158, 252}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 4, 209, 135}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 35}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 178, 98, 142, 121, 87, 94, 156}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 155, 249, 223}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 127, 229, 163}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 75, 103, 32, 217, 7, 224, 231}, 115}, {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 161}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 140}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 50}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 224}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 253}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 52}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 120}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 83}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 59}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 112}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 75}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 207}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 245}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 254}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 20}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 113}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 55}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 19}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 203}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 252}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 174}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 8}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 204}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 101}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 178}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 79}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 132}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 169}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 67}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 250}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 123}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 29}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 178}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 208}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 130}, {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 81}, 130}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 242, 248, 135, 248}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 149, 140, 189, 151, 112}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 87, 174, 161, 255}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 80}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 230}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 184}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 196, 104, 240, 245}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 242, 169, 27, 211}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 196}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 207, 243}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 112, 253, 91, 98}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 177}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 84, 108}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 236}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 125, 88, 163}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 29, 85, 122, 142}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 59, 54, 31}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 81, 252, 203, 235}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 107, 188, 89}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 62, 140, 110}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 82}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 249, 84, 138}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 40, 64, 67, 209}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 211, 230}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 238, 202, 117, 224}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 231, 149, 124}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 3, 142, 164}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 213, 152, 226}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 192}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 222}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 5}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 247, 173, 17, 60}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 213, 146}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 251}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 108, 52}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 122, 43, 154, 71, 239}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 161, 48, 251}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 159, 200, 163, 235}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 104, 91, 71}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 92, 34, 26, 255}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 94, 20, 63}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 91, 137, 249, 190}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 244}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 246, 19, 155}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 57, 164, 131, 72}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 106, 219}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 42, 227, 189, 53}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 31, 124}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 194, 18}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 139}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 230}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 11}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 95, 209, 20}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 91, 138}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 251, 242, 194}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 255}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 46, 233, 249}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 222, 173, 190}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 184, 106, 60, 209}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 208, 153}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 165, 192}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 25, 183, 40, 202}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 230, 177, 162}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 138, 139, 252}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 145, 206, 222, 109, 38}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 56, 106, 4}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 12, 176, 138, 54, 24}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 242, 15, 183}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 255}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 205, 4, 204, 134}, 57}, {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 177, 61, 158}, 57}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 140, 214, 237, 123, 190, 46, 59}, 97}, {{247, 0, 0, 0, 0, 43, 51, 191, 144, 161, 81, 224, 168, 217, 141, 102}, 97}, {{247, 0, 0, 0, 21, 178, 93, 193, 183, 26, 232, 93, 206, 187, 207, 169}, 97}, {{247, 0, 0, 0, 0, 0, 162, 28, 121, 30, 202, 206, 95, 233, 141, 208}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 167, 132, 156, 33, 149, 234, 236, 90}, 97}, {{247, 0, 214, 103, 36, 163, 177, 175, 202, 21, 230, 114, 239, 41, 79, 216}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 114, 52, 86, 85}, 97}, {{247, 0, 0, 0, 0, 27, 58, 22, 3, 75, 108, 38, 223, 20, 241, 55}, 97}, {{247, 0, 0, 186, 39, 235, 78, 44, 255, 103, 227, 151, 129, 120, 219, 114}, 97}, {{247, 0, 0, 0, 253, 153, 174, 114, 174, 36, 87, 149, 255, 139, 243, 193}, 97}, {{247, 0, 0, 0, 239, 209, 174, 7, 125, 94, 172, 168, 80, 79, 198, 137}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 94, 248, 233, 159, 58, 107, 112, 191}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 33, 140, 128}, 97}, {{247, 0, 0, 0, 0, 0, 0, 27, 198, 247, 54, 42, 67, 245, 151, 101}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 103, 35}, 97}, {{247, 0, 0, 0, 0, 0, 0, 102, 30, 131, 151, 25, 99, 3, 120, 106}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 19, 5, 212}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 129, 200, 138, 213}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 33, 185, 54, 108, 103}, 97}, {{247, 0, 0, 0, 0, 213, 104, 176, 75, 168, 39, 206, 70, 246, 23, 111}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 14, 56, 50, 32, 161}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 97}, {{247, 0, 0, 0, 0, 0, 20, 34, 34, 50, 236, 227, 62, 38, 40, 19}, 97}, {{247, 0, 0, 0, 219, 85, 32, 91, 171, 195, 116, 6, 247, 9, 54, 228}, 97}, {{247, 0, 0, 0, 0, 0, 7, 244, 212, 216, 114, 139, 127, 222, 164, 224}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 139, 161, 19, 186, 129, 246, 254}, 97}, {{247, 0, 0, 0, 0, 0, 0, 25, 15, 188, 241, 244, 128, 26, 223, 93}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 236, 222, 35, 235}, 97}, {{247, 0, 0, 0, 0, 0, 24, 120, 176, 18, 74, 82, 5, 25, 205, 181}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 116, 36, 148, 12}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 234, 244, 125}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 183, 53}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 163, 188, 234}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 21, 119, 55, 143, 96}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 128, 137, 154, 156, 58, 13, 66, 249}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 96, 202, 91, 176, 231}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 151, 150, 9, 87, 247, 46, 10, 150}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 197, 220}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 63, 231, 80}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 200, 255, 18, 82, 172, 15, 205, 219}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 231, 183}, 97}, {{247, 0, 0, 0, 0, 0, 194, 32, 99, 203, 247, 240, 38, 121, 111, 223}, 97}, {{247, 0, 0, 0, 0, 159, 95, 113, 133, 241, 43, 182, 112, 14, 150, 47}, 97}, {{247, 0, 0, 0, 0, 0, 106, 19, 17, 183, 127, 17, 161, 74, 2, 227}, 97}, {{247, 0, 0, 0, 0, 0, 0, 108, 223, 28, 237, 6, 135, 130, 150, 116}, 97}, {{247, 0, 143, 159, 71, 35, 125, 194, 27, 52, 39, 94, 57, 68, 44, 210}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 198, 251, 181, 231}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 143}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 173, 28, 135, 38, 29, 211, 242, 86}, 97}, {{247, 0, 0, 0, 0, 0, 0, 31, 242, 213, 9, 177, 51, 70, 207, 143}, 97}, {{247, 0, 0, 153, 30, 48, 216, 95, 213, 107, 226, 198, 81, 117, 171, 32}, 97}, {{247, 0, 0, 0, 0, 0, 0, 160, 62, 151, 7, 235, 123, 142, 227, 100}, 97}, {{247, 0, 0, 0, 220, 179, 16, 25, 54, 119, 203, 175, 113, 62, 72, 60}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 203, 93, 151, 171, 235}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 255}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 239, 41, 223}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 169, 63, 20}, 97}, {{247, 0, 0, 65, 230, 51, 249, 222, 153, 198, 49, 143, 227, 168, 54, 245}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{247, 0, 0, 230, 5, 218, 162, 144, 53, 112, 101, 36, 58, 11, 24, 168}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{247, 0, 0, 0, 0, 0, 0, 176, 0, 23, 255, 236, 148, 64, 93, 230}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 136}, 97}, {{247, 0, 195, 64, 44, 89, 14, 229, 213, 33, 77, 61, 183, 62, 110, 37}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 19, 1, 205, 150, 202, 155, 52, 110}, 97}, {{247, 0, 0, 159, 167, 18, 250, 25, 54, 147, 168, 161, 165, 226, 95, 135}, 97}, {{247, 0, 0, 0, 0, 0, 146, 105, 228, 98, 221, 181, 168, 51, 226, 102}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 29, 248, 152, 123, 50, 169, 109}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 79, 25, 252, 200, 186}, 97}, {{247, 0, 0, 221, 14, 191, 70, 151, 207, 97, 54, 125, 230, 217, 177, 43}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 32, 182, 208}, 97}, {{247, 0, 211, 68, 211, 53, 175, 168, 133, 60, 138, 138, 109, 244, 53, 188}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 190, 192, 39, 246, 13}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 174, 183, 155, 231, 33, 224, 90, 106}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 172}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 157, 110, 72, 103, 86, 46, 29, 169}, 97}, {{247, 0, 0, 0, 0, 0, 246, 29, 225, 212, 104, 16, 127, 164, 137, 233}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 211, 168, 239, 117, 51}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 183, 61, 17, 27}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 57, 172, 50}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 137, 239, 155}, 97}, {{247, 0, 0, 0, 123, 136, 141, 238, 171, 117, 215, 106, 40, 153, 9, 248}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 97}, {{247, 0, 0, 0, 0, 22, 166, 145, 72, 107, 161, 89, 153, 91, 124, 48}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 3, 120, 224, 76, 135}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 97}, {{247, 0, 0, 0, 0, 0, 121, 112, 97, 172, 75, 166, 0, 150, 183, 96}, 97}, {{247, 0, 0, 0, 0, 0, 195, 220, 125, 197, 222, 187, 82, 23, 189, 255}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 69, 73}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 81, 34, 120, 230}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 209, 180, 73, 106, 224, 40, 231, 64}, 97}, {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 97}, {{247, 0, 0, 21, 98, 42, 111, 122, 101, 53, 58, 182, 78, 90, 211, 104}, 97}, {{247, 0, 0, 0, 0, 90, 118, 180, 194, 132, 221, 212, 119, 253, 65, 120}, 97}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 114, 77, 210, 1, 122, 119, 207}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 193, 13, 88, 15, 230, 112, 28, 52, 181}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 16, 13, 103, 190, 9, 221, 2}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 245}, 146}, {{12, 128, 0, 0, 0, 0, 0, 49, 117, 63, 27, 94, 235, 79, 120, 211}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 237, 60, 53}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 7, 17, 178}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 152, 212, 34, 248, 49, 52, 127}, 146}, {{12, 128, 0, 0, 0, 0, 87, 35, 202, 28, 103, 182, 173, 216, 44, 236}, 146}, {{12, 128, 0, 202, 8, 222, 199, 68, 30, 214, 250, 190, 73, 86, 137, 58}, 146}, {{12, 128, 0, 0, 224, 1, 72, 109, 211, 212, 10, 77, 27, 48, 28, 91}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 214, 212, 71}, 146}, {{12, 128, 36, 205, 3, 18, 190, 123, 170, 240, 221, 223, 15, 26, 138, 31}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 114, 38, 77, 238, 18, 222, 124, 7}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 190, 226, 224, 192}, 146}, {{12, 128, 0, 0, 65, 165, 189, 119, 181, 36, 34, 174, 230, 10, 131, 215}, 146}, {{12, 128, 0, 93, 79, 24, 186, 252, 146, 6, 156, 186, 241, 233, 117, 156}, 146}, {{12, 128, 0, 0, 235, 13, 90, 96, 73, 192, 47, 95, 66, 79, 57, 34}, 146}, {{12, 128, 0, 0, 0, 55, 45, 224, 139, 220, 228, 132, 95, 6, 238, 170}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 56, 89, 136, 50, 133, 196, 220, 196}, 146}, {{12, 128, 0, 0, 0, 0, 100, 207, 206, 11, 51, 206, 144, 54, 12, 210}, 146}, {{12, 128, 0, 0, 0, 0, 133, 158, 183, 66, 42, 125, 60, 9, 77, 42}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 241}, 146}, {{12, 128, 0, 0, 0, 0, 124, 123, 138, 147, 167, 222, 215, 63, 5, 35}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31, 171, 253, 55, 220, 145}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 254, 91, 60, 223, 57, 163, 94, 38, 64, 22, 4, 149, 105}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 60, 216, 45, 224, 131, 187, 207}, 146}, {{12, 128, 0, 0, 184, 171, 23, 249, 86, 182, 136, 89, 44, 163, 167, 33}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 237, 81, 27, 30, 211, 145, 211, 27}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31, 151, 214, 93, 134, 94}, 146}, {{12, 128, 0, 0, 9, 70, 6, 148, 172, 85, 107, 254, 75, 180, 186, 107}, 146}, {{12, 128, 0, 0, 0, 151, 156, 203, 248, 59, 80, 147, 8, 17, 107, 53}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 62, 234}, 146}, {{12, 128, 41, 117, 158, 189, 86, 92, 230, 141, 208, 93, 80, 4, 33, 201}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 97, 170, 155, 19, 20, 47, 96, 33}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 1, 241, 14, 49, 182, 144, 141, 149}, 146}, {{12, 128, 0, 0, 0, 0, 0, 235, 116, 53, 67, 63, 160, 2, 96, 234}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 62, 173, 175, 177, 179, 154, 91}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 221, 21, 97, 230, 127, 187, 148, 118}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 77, 150, 8, 104, 46, 125}, 146}, {{12, 128, 0, 127, 192, 86, 63, 221, 63, 66, 149, 51, 248, 153, 71, 100}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 61}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 24, 84, 131, 17, 129, 213}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 194, 6, 25}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 162, 186, 122, 252}, 146}, {{12, 128, 0, 0, 44, 218, 198, 187, 57, 192, 70, 31, 71, 13, 158, 126}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 171, 41, 217}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 29, 36, 252, 102, 138, 47, 165, 44, 218, 232, 213, 229, 158}, 146}, {{12, 128, 0, 0, 0, 0, 0, 165, 47, 79, 211, 169, 184, 12, 88, 192}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 116, 78, 95, 193}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 209}, 146}, {{12, 128, 0, 0, 0, 0, 234, 77, 226, 255, 212, 22, 234, 219, 167, 240}, 146}, {{12, 128, 0, 0, 0, 0, 122, 129, 157, 104, 81, 31, 120, 213, 248, 118}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 24, 58}, 146}, {{12, 128, 0, 124, 131, 114, 245, 45, 220, 30, 83, 84, 149, 188, 178, 247}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 208, 75, 214, 186, 186, 74, 139}, 146}, {{12, 128, 0, 0, 0, 0, 0, 91, 155, 188, 237, 56, 196, 60, 211, 77}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 100, 2, 169, 238, 145, 112, 221, 13}, 146}, {{12, 128, 0, 248, 246, 62, 44, 87, 255, 187, 181, 89, 200, 95, 105, 21}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 91, 80, 100, 14, 26, 171}, 146}, {{12, 128, 0, 0, 0, 0, 0, 120, 93, 226, 189, 59, 59, 134, 214, 147}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 137}, 146}, {{12, 128, 0, 59, 93, 173, 9, 131, 37, 43, 30, 117, 159, 181, 227, 65}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 120, 67}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 187}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{12, 128, 0, 0, 26, 55, 121, 169, 193, 142, 92, 207, 212, 204, 136, 61}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 56, 132, 89, 222}, 146}, {{12, 128, 252, 155, 188, 6, 106, 157, 112, 31, 20, 201, 137, 235, 152, 68}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 115}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 212, 0}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 160, 82, 92, 134, 94, 209, 4, 41}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 210, 252}, 146}, {{12, 128, 9, 28, 199, 107, 27, 19, 59, 32, 113, 149, 52, 103, 71, 207}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 98, 126, 243, 109}, 146}, {{12, 128, 0, 0, 0, 72, 11, 234, 142, 13, 218, 223, 98, 89, 28, 251}, 146}, {{12, 128, 0, 0, 0, 0, 28, 166, 163, 173, 31, 234, 142, 71, 224, 111}, 146}, {{12, 128, 230, 232, 213, 21, 255, 92, 87, 232, 234, 43, 64, 118, 87, 121}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 149, 112, 39, 160, 24, 219, 80}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 52, 22, 175, 13, 209, 79}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 172, 184, 251, 172, 111, 34, 228}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 68, 114, 207, 236, 23, 101, 52}, 146}, {{12, 128, 0, 238, 61, 200, 237, 108, 152, 174, 119, 68, 206, 37, 154, 140}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 109, 51, 250, 171}, 146}, {{12, 128, 0, 0, 0, 0, 0, 214, 126, 71, 84, 240, 244, 188, 74, 55}, 146}, {{12, 128, 0, 0, 0, 0, 0, 58, 87, 185, 232, 60, 163, 175, 5, 29}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 141, 88}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 90, 57, 129}, 146}, {{12, 128, 0, 0, 24, 197, 182, 234, 187, 104, 195, 102, 158, 153, 115, 21}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 182}, 146}, {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 7, 125}, 146}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 249}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 18}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 117}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 144}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 174}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 116}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 142}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 137}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 14}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 128}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 253}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 101}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 231}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 183}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 57}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 142}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 52}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 218}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 182}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 9}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 153}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 249}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 93}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 52}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 5}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 194}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 29}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 19}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 136}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 7}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 17}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 99}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 231}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 3}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 195}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 148}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 53}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 46}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 70}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 242}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 75}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 66}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 142}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 134}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 204}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 133}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 35}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 87}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 196}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 239}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 33}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 229}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 84}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 166}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 1}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 74}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 87}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 196}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 60}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 84}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 177}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 249}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 33}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 154}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 126}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 184}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 83}, 129}, {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 76}, 129}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 179, 99, 251}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 102, 130, 229}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 66, 32}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 114, 211}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 215, 190, 205}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 31, 165, 86}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 96, 91}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 182}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 52, 91}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 238, 105}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 144, 85}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 227, 109}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 81, 132}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 207}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 182, 59, 65}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 198, 224, 87}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 31}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 162, 88}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 150, 245, 147}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 177}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 94}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 138, 162}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 2, 250}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 241, 87}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 138, 180}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 82, 133, 147}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 42}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 193, 24, 43}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 4, 93}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 121, 101}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 91, 176}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 206}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 161, 126}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 76, 131}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 21, 225}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 130, 207, 210}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 70}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 7}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 129}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 45}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 173, 251}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 215, 6, 203}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 112, 10}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 25}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 162, 131}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 252, 205}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 132, 53}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 12}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 235, 223, 30}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 116, 147, 76}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 189, 253, 107}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 29, 5}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 19, 216, 31}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 226, 217}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 92, 76}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 175, 128, 57}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 53, 66}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 160}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 135, 130}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 253, 13, 9}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 25, 31}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 206, 65, 211}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 56}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 119, 11, 206}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 134, 40, 125}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 16, 38}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 160, 56}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 192, 164}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 116}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 252}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 30}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 197, 207, 184}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 13, 190}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 168, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 23, 133}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 117, 20, 129}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 249}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 230}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 232, 207}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 116, 61}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 230, 69}, 159}, {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 252, 86}, 159}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 175}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 202}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 226}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 161}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 80}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 123}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 207}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 223}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 196}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 169}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 198}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 181}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 185}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 11}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 185}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 33}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 204}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 134}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 188}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 232}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 34}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 37}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 81}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 72}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 234}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 239}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 82}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 188}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 255}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 166}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 242}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 116, 8}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 40, 231}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 234, 213}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 75, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 179, 86}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 241, 144}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 16}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 159}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 14, 61}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 25, 238}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 126, 228}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 158}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 103}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 194, 162}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 200}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 184, 132}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 116, 110}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 193}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 144}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 68, 157}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 164, 13}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 165}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 207, 246}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 34}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 176}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 247, 155}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 132}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 11, 176}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 234, 234}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 82}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 236}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 8, 85}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 65}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 143}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 182, 156}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 117, 164}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 104}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 19, 128}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 20}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 217, 60}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 88}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 183}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 73, 187}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 62, 69}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 182}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 196, 186}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 106}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 203, 2}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 140}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 136, 87}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 28}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 154}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 132}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 186}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 179, 191}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 20, 72}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 93, 78}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 206, 88}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 101, 159}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 197}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 53}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 136}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 59, 57}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 233}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 162}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 207}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 2, 228}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 190, 14}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 76}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 64}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 166}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 36, 38}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 158}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 216}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 60, 85}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 141, 145}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 14, 97}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 119}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 13, 41}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 240, 72, 68}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 211, 75}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 28, 216}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 44}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 53, 139}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 108}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 186}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 231, 21, 49}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 92, 222}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 160, 46}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 174, 13}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 172}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 1}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 3}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 209}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 173, 8, 110}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 199, 68}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 227, 113, 183}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 216, 133}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 27}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 133}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 155}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 235}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 132}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 22, 184}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 189}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 188, 165, 104}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 23, 134}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 28, 138}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 56, 220}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 204, 96}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 183, 133}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 34, 94}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 171, 82}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 223}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 221}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 97, 225}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 116, 114}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 127, 12}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 153}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 23, 139}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 56}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 251, 240, 120}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 197}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 23}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 153, 102}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 88, 236, 3}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 29}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 188}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 61, 39}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 122, 64, 218}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 152, 207}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 1}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 215}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 140}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 100}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 128}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 232}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 78}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 186}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 199}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 208}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 180}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 210}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 150}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 200}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 107}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 236}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 54}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 1}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 137}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 175}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 89}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 118}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 27}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 148}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 161}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 62}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 234}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 153}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 184}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 225}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 20}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 25}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 146}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 14}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 224}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 43}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 140}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 255}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 18}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 26}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 236}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 147}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 148}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 239}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 77}, {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 177}, 77}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 99, 188, 217, 142, 90}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 212}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 18, 164, 148}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 18, 117, 244, 36, 69}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 134, 120, 47}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 125}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 24, 220}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 181, 167}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 48, 183}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 238}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 71, 253, 161}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 103, 26, 193, 26}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 119, 203, 215, 11, 1}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 82}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 113, 199}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 165, 67}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 160, 161, 88, 188, 244}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 201, 164, 62, 21}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 130, 249, 57}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 26, 136, 185, 81}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 247}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 31, 77}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 123}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 28, 154, 197, 215, 3}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 156, 244, 216, 131, 247}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 131, 147}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 25, 50, 127}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 21, 44, 134, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 201, 146, 77}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 49, 218, 136, 176, 30}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 26, 109, 253, 127, 222}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 169, 69, 254}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 109, 39, 9, 178}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 240, 73, 16, 129}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 113, 53, 56, 254}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 188, 214, 113}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 170, 142, 166, 13}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 175, 121, 231}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 37, 63, 91, 130}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 145, 194, 64, 178, 130}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 132, 175}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 62, 102, 203}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 64, 71, 223, 142}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 199, 58}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 160, 154, 176, 180, 167}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 94, 162, 212, 57, 54}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 94, 75}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 76, 22, 136, 163}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 153, 78, 199}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 79}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 24, 177, 233, 29, 172}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 39, 151, 91, 228}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 24, 42}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 143}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 14, 25, 86}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 235, 245, 31}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 50, 13}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 138, 128, 114, 204}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 181}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 191, 156, 155, 218}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 6, 173, 176}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 128, 204, 231, 138, 129}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 78, 239, 140, 179, 106}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 115, 24, 16}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 18}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 100, 73, 7, 135}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 51, 108, 218}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 253}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 174, 89}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 195, 2, 140, 92}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 182}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 117, 128, 205, 157}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 189, 162, 107, 133}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 136}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 33, 220, 55}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 230, 153, 247, 232, 166}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 209}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 64}, 121}, {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 121}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 221}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 241, 188, 162, 22}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 142}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 239, 159, 96, 139, 52, 250}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 38}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 217, 17, 45, 229, 40}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 194, 176, 74, 35, 244}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 12, 202, 239, 14, 96, 10}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 172, 101, 133, 255, 95, 68, 95}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 39, 55, 245, 212, 229, 47}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 201, 213}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 20, 85}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 166}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 8}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 14, 225, 61}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 77, 139, 196}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 132, 10}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 137}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 29, 225, 17, 127, 121, 12}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 20, 8, 80, 241}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 38, 50}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 164, 193, 111, 136, 232, 117}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 173, 56, 26, 143, 69}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 247, 240}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 151, 159, 45}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 194}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 187, 157, 83}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 206}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 56, 155}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 88}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 223, 160, 158}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 45, 145, 28}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 84, 3, 134, 63}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 29, 53, 64, 111, 206}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 227, 44}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 154, 112, 29, 38, 147}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 77, 50, 91, 2}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 37, 183, 67, 213, 240, 78}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 229, 230, 201}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 178, 151, 125}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 23, 197}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 99, 180, 229, 225}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 210}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 55, 32, 8, 177}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 238, 230, 160, 33, 22, 218}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 197, 119}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 84, 224, 181}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 26, 125, 189, 150}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 85, 230, 229, 8}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 27, 16}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 202, 188, 154, 154, 69, 109}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 131, 7, 136, 164, 225}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 72, 201}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 232}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 59, 198, 43}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 92, 102}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 133, 228, 50}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 103, 196, 21, 3, 104, 47, 80}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 42}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 48, 11, 124, 217}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 166, 47}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 233, 13}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 254, 248, 79, 214}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 228}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 61, 194, 133, 252}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 135}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 202, 137, 157, 179}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 86, 72, 191, 188, 82, 116}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 132, 177, 53, 120}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 219, 88, 127, 249, 21, 247}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 168}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 254, 63, 192, 216, 162}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 72, 171, 197, 125}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 231, 100}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 174, 244, 145}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 241}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 6, 63, 157}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 63, 189, 44}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 37, 125, 123, 142}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 188, 173}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 115, 208, 183, 55}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 115, 103, 135, 198, 33}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 190, 102}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 193, 57, 87, 248, 204, 218}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 138, 251, 119, 84, 209, 204}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 102}, {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 231, 29}, 102}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 133, 10, 116, 99, 253, 26}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 88, 215, 199, 64, 54, 218, 82}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 87, 76, 237}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 2, 47}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 122, 224, 153, 133, 20, 254, 131}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 65, 136, 97, 110, 139}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 68, 4, 46, 173, 110, 192, 255}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 54, 30}, 28}, {{28, 110, 164, 0, 0, 0, 0, 38, 7, 187, 7, 98, 247, 142, 32, 51}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 39, 63, 227, 52, 84, 111, 114, 214, 77, 178, 78, 165}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 209}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 138, 236, 30, 207, 151, 109}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 25, 190, 141}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 109, 129, 7}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 139, 155, 19, 16, 188, 248}, 28}, {{28, 110, 164, 0, 0, 0, 226, 134, 36, 49, 145, 252, 198, 133, 55, 62}, 28}, {{28, 110, 164, 0, 1, 102, 49, 43, 143, 126, 208, 23, 153, 110, 247, 136}, 28}, {{28, 110, 164, 0, 250, 122, 133, 65, 226, 193, 2, 46, 231, 91, 180, 166}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 252, 153, 210}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 168, 58, 95, 112, 121}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 28}, {{28, 110, 164, 0, 0, 109, 201, 164, 213, 9, 93, 246, 14, 107, 112, 252}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 5, 220, 73, 157, 32, 216, 132, 117}, 28}, {{28, 110, 164, 0, 0, 0, 0, 238, 212, 118, 139, 255, 170, 222, 207, 123}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 213}, 28}, {{28, 110, 164, 0, 0, 0, 0, 41, 151, 224, 123, 158, 182, 95, 85, 229}, 28}, {{28, 110, 164, 0, 0, 0, 123, 120, 45, 229, 21, 218, 6, 168, 111, 174}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 84, 183, 157, 127, 44, 254, 220}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 105, 10, 189, 121, 151, 228}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 118, 132, 176, 223, 87, 120}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 192, 130}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 35, 134, 249, 120, 183, 62}, 28}, {{28, 110, 164, 0, 168, 54, 195, 13, 211, 68, 241, 124, 226, 182, 88, 150}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 233, 227, 5, 10, 136}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 235, 251, 156, 47, 222, 103}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 108}, 28}, {{28, 110, 164, 0, 0, 0, 163, 26, 241, 46, 8, 209, 41, 251, 163, 107}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 180, 75}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 192, 245}, 28}, {{28, 110, 164, 0, 0, 0, 0, 116, 55, 172, 69, 156, 160, 245, 207, 77}, 28}, {{28, 110, 164, 0, 160, 252, 46, 237, 117, 38, 106, 184, 16, 121, 209, 64}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 241, 62, 40, 175, 139, 43, 98, 245}, 28}, {{28, 110, 164, 0, 0, 0, 0, 30, 98, 216, 174, 150, 89, 192, 76, 63}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 160, 9, 39}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 180, 144}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 225}, 28}, {{28, 110, 164, 0, 0, 0, 83, 32, 15, 141, 15, 136, 93, 15, 151, 27}, 28}, {{28, 110, 164, 0, 0, 207, 78, 43, 89, 150, 59, 2, 130, 152, 87, 22}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 191, 1, 68, 79, 165, 138}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 213, 228, 131, 240, 170}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 106, 192, 76, 103, 193}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 198, 52, 18, 186, 137}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 189, 254, 246, 65, 127}, 28}, {{28, 110, 164, 0, 0, 110, 43, 100, 6, 133, 20, 252, 75, 50, 189, 227}, 28}, {{28, 110, 164, 0, 0, 0, 0, 126, 164, 183, 218, 66, 190, 185, 206, 34}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 211, 168, 39, 254, 134, 210, 85}, 28}, {{28, 110, 164, 0, 0, 0, 0, 238, 88, 74, 35, 94, 172, 200, 243, 154}, 28}, {{28, 110, 164, 0, 0, 0, 139, 247, 118, 141, 171, 225, 41, 147, 203, 173}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 235, 85, 207, 172, 3, 89, 49}, 28}, {{28, 110, 164, 0, 0, 146, 130, 5, 149, 2, 10, 235, 111, 66, 76, 93}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 17, 175, 220, 30, 39, 63}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 105, 221, 50}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 54, 57, 201, 175, 77}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 121, 142, 249}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 65, 81, 26, 97, 150}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 7, 45, 23}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 243, 79, 166, 64, 91, 19}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 120, 133, 103, 165, 183, 76, 184}, 28}, {{28, 110, 164, 0, 108, 168, 159, 237, 225, 8, 196, 139, 193, 54, 74, 131}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 193, 149, 122, 251, 117, 168}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 62, 134, 27, 25, 163, 106, 214}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 16, 183}, 28}, {{28, 110, 164, 0, 0, 0, 191, 96, 54, 113, 61, 155, 212, 206, 124, 154}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 101, 54, 25}, 28}, {{28, 110, 164, 0, 0, 0, 135, 118, 200, 67, 46, 113, 117, 135, 111, 39}, 28}, {{28, 110, 164, 0, 85, 130, 30, 11, 152, 92, 203, 240, 49, 120, 144, 246}, 28}, {{28, 110, 164, 0, 0, 0, 0, 62, 234, 255, 68, 151, 120, 130, 205, 11}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 175, 244}, 28}, {{28, 110, 164, 0, 0, 0, 0, 236, 109, 182, 4, 182, 194, 223, 29, 154}, 28}, {{28, 110, 164, 0, 0, 0, 148, 133, 252, 165, 59, 140, 222, 188, 238, 69}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 143, 213, 15}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 114, 101, 11, 24, 37, 19, 235, 107}, 28}, {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 229, 0}, 28}, {{28, 110, 164, 0, 148, 66, 17, 159, 163, 79, 15, 17, 132, 235, 43, 87}, 28}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 7, 155, 115}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 140}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 162, 167, 43}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 173, 120, 243, 97}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 106, 146, 234, 151}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 82, 64}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 78, 160}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 188}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 67, 168, 117, 90}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 154, 137, 139, 63}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 171}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 133}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 68, 208, 130, 112}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 102, 240, 162}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 221, 61, 77, 7}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 219, 90}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 37}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 201, 164}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 195, 232, 211}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 49}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 211}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 25}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 206, 111}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 196, 237}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 31, 210, 208, 113}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 247, 14, 12}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 139, 153, 121, 121}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 42}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 178, 82, 243}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 231, 253}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 155, 131, 147, 215}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 74, 177}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 103, 223}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 157, 45}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 146, 132}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 47, 58}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 191, 66}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 240, 211, 253}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 132}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 147, 29, 56}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 47, 213, 191}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 191, 21, 184, 15}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 42}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 159}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 28, 205, 14}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 198}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 207, 40, 27}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 78, 87, 147, 128}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 222, 210}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 241, 19, 114, 54}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 150, 132}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 110}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 84, 87, 144}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 102, 71, 119}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 254, 43, 193}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 88, 115, 174}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 59, 54, 98}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 216}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 108, 182, 17, 48}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 85, 69, 213}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 186, 113, 83}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 153, 58, 50}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 57}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 254, 127, 46}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 3, 203, 182, 252}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 146, 116}, 154}, {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 15, 27}, 154}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 171, 213, 226}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 248, 228, 194, 7, 212}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 191}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 70, 77, 46, 114, 79, 224}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 19, 88, 133, 15, 145, 213}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 10}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 231, 97, 116}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 213, 204}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 120, 44, 18, 40}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 172, 132, 161, 93}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 68, 73}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 53, 210}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 134, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 107, 62, 175, 74, 3, 185}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 115, 144, 9, 152, 111}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 94, 2, 128}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 187}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 144}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 200, 79, 152, 47, 127}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 166, 170, 216, 137}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 230, 106, 183, 60, 48}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 25}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 154}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 47, 148}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 126, 156, 202}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 50, 121}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 208, 60, 106, 70, 123}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 73}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 115, 213}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 106, 105}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 7, 152, 170, 178}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 193, 249, 36}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 62, 91, 31, 27, 203, 37}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 176}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 123, 190, 111, 53, 157, 104}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 111, 6, 85, 52, 201}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 160, 44, 77, 12, 75, 104}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 106, 246, 72, 194, 222}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 136, 93}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 206, 149, 96}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 24, 36, 122, 19}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 191, 144, 136, 25}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 196}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 75, 203, 75, 25, 8, 75}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 225, 221, 72, 149}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 44, 117}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 202, 255, 73, 33}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 81, 38, 193, 205, 1}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 157, 210, 166, 105}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 176, 194, 33, 235, 59}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 62, 253, 50, 243, 74}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 109, 230, 34, 31, 226}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 31, 109}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 131, 180, 16, 100}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 217, 157, 38}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 255, 91}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 83}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 109, 149, 1, 251, 176, 167}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 154, 25, 29, 124, 150}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 163, 181, 63, 99}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 173}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 190}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 80, 52}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 119, 102, 197}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 107, 59, 130, 165, 120, 41}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 123, 96, 1}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 145}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 144, 103, 205, 102, 120, 186}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 29, 129, 158}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 231, 220, 247, 198}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 164, 79, 203}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 148, 192}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 4}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 38, 174}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 207, 76}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 153, 5, 185, 147}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 108, 110}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 101}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 43}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 138}, 39}, {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 71}, 39}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 32, 41, 75, 100, 140}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 28, 127, 76, 101, 26}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 2, 223, 58, 128, 94}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 206, 40, 93, 65, 173}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 121, 154, 42, 100}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 170}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 38, 223, 87, 88}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 124, 91, 223, 241, 18}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 138, 4, 115, 186, 162}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 129, 161}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 178, 21}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 126, 254, 55}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 160, 105, 240, 108, 145}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 51, 199, 101}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 135, 244, 218}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 12, 132, 42}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 21, 245, 26, 127}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 106}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 215}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 95, 155, 244, 102}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 243}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 89, 195, 8, 252, 48}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 253, 63, 4, 15, 95, 50}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 4, 101}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 229, 96}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 189, 204}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 102, 253, 213, 150, 94, 120}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 68}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 129, 143, 206, 15}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 231, 229, 160, 147}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 40, 0, 148}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 212, 106}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 218, 44, 5, 115, 154}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 10, 190, 149, 102}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 135, 192}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 76, 218}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 237, 23, 52, 69}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 211, 221, 32, 206, 48}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 70, 9, 120, 119, 169}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 195, 167}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 145}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 34, 115}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 250, 144, 140, 154}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 8}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 151}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 255, 218}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 53, 73}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 87, 76, 56, 235, 64}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 38, 131, 55, 216, 237}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 24, 100, 23, 230, 52, 74}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 109, 209}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 228, 89, 238}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 224}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 153, 183, 6, 114}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 227, 10}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 198, 196, 72, 5}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 76, 215}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 48}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 244, 83}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 94, 8, 173}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 234, 224}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 123, 245, 188}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 31, 20, 249, 97, 49}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 240, 103, 250, 238}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 196, 228, 49}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 222, 77, 217, 26}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 155, 109, 183, 58}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 160, 103, 105}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 236, 96, 171, 53, 181}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 180, 42, 253, 170}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 71}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 5}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 9, 93, 249, 28, 142}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 192, 254}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 198, 112, 165, 118, 255}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 138}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 75, 240, 109}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 190, 254, 119, 105}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 18, 208, 235, 117}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 218, 211, 10}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 79, 72, 91}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 92}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 36, 74}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 1, 129, 9}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 16, 211, 11, 62, 151, 98}, 163}, {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 19, 49}, 163}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 81}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 87}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 25, 89, 200, 188, 112, 245, 140}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 144, 115, 28, 226, 216, 216, 41}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 65, 11, 213, 5, 195, 105}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 149, 172, 96, 143, 20}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 163, 50, 65, 189, 207, 118, 228}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 132, 80, 200, 86, 101}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 250, 42, 98, 12, 26, 2}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 98, 248, 34, 199, 192}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 200, 25, 146, 138, 140, 217}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 57, 96, 19, 40}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 35, 103}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 195, 222, 16, 111, 20, 6, 138}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 169, 164, 225, 223}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 250, 52, 105, 240, 69, 247}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 43, 56, 126, 134, 159}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 183, 253, 172, 149}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 5}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 51, 110, 113, 222, 185, 105}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 169, 166, 212, 147, 122, 46}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 144, 58, 135, 153}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 99, 173}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 239, 242, 70, 165, 147}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 57}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 165, 219, 93, 57, 103}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 96, 250, 222}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 163, 74, 8, 107, 228, 56}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 40}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 72, 209, 43}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 105}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 22, 176, 100, 178, 34, 237}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 63, 175, 155, 8, 93, 187, 245}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 223, 149, 150, 158}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 199}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 61, 143, 163}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 163, 138, 19, 82, 159}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 55, 230, 54, 118}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 147, 63, 76}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 10, 104, 229, 11}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 189, 155, 15, 252}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 196, 134, 180, 115}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 103, 135, 159, 102, 5, 224, 194}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 210, 72, 121, 55, 58, 82}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 167}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 15, 199, 68, 236, 190, 143}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 129, 8, 253, 82}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 72, 58, 234, 43, 189}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 179, 93, 226, 143, 108}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 99, 146, 31, 28, 24, 207, 150}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 27, 84, 135, 0, 182, 138}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 97, 201, 16}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 12}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 230, 197, 54, 225}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 164, 63, 255, 127, 134}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 210, 77, 144, 97}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 189}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 147, 109, 39, 114}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 140, 16, 13, 112, 155, 83}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 206, 86, 165, 247, 23}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 172, 184, 42, 101, 164, 209, 111}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 142, 164, 22, 25, 74, 179}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 210, 203}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 118, 74, 160}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 138, 216, 118, 239}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 195, 120, 191}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 223, 112, 62, 52, 132}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 229, 140, 174, 222, 163, 111}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 167, 58, 86}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 42, 145, 14, 36, 205}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 201}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 126, 123, 69, 131}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 235, 117}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 6, 222, 143}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 222, 210}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 67, 125, 245}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 162, 154, 63, 3, 167}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 99, 243, 208, 107, 251}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 142, 101, 13, 201}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 177, 134, 174, 185, 13}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 62, 192, 42, 51}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 53, 112, 3}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 77, 217, 247, 29}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 125, 14, 38}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 220, 65, 92, 60, 86, 15, 14}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 101}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 93, 175, 200, 241}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 53, 54, 193, 200}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 174, 217, 127}, 42}, {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 32, 226, 127, 174, 122, 230}, 42}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 114, 148, 187, 172}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 37, 101, 239}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 147, 141, 121}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 114, 222}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 131, 227, 68}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 57, 103, 237}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 13, 58, 131}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 231, 200, 44}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 49}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 30, 179, 217}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 49, 189, 103}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 17, 164, 241}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 27, 203}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 18, 75, 5, 198}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 246, 10, 63}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 31}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 11}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 109}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 118}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 134, 74, 172}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 248}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 108, 132, 88}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 114}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 82, 213, 208}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 222}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 136, 72, 153}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 205}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 142}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 149}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 89, 248, 196}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 57}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 193, 177, 132, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 54, 101}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 227, 223, 82, 158}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 82}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 15, 210, 153}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 104, 206, 183, 188}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 125, 22, 135}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 233, 174, 40}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 48, 238, 131}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 198, 129}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 95, 243, 32}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 117}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 190, 190}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 179, 8}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 4, 222, 247, 146}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 203}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 190, 92, 172}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 87, 12, 17, 123}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 39}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 55}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 146, 159, 183}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 101, 242, 76}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 66, 229, 206, 160}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 76}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 204}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 194, 141}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 201, 113, 141}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 152, 153}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 220, 179}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 116, 42}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 124, 218, 146}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 166, 29}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 207, 148, 43, 164}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 157}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 166, 107}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 237}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 162}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 119, 120, 35, 191}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 16, 172, 71}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 41, 241, 143, 5}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 26, 94}, 207}, {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 185, 180, 213}, 207}, {{235, 0, 0, 82, 225, 179, 154, 162, 0, 223, 178, 246, 219, 74, 150, 216}, 25}, {{235, 0, 0, 0, 135, 33, 152, 139, 171, 36, 11, 89, 194, 150, 244, 241}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 134, 75, 45, 156, 2, 250, 28}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 172, 29, 92, 172, 5}, 25}, {{235, 0, 0, 0, 0, 0, 0, 1, 237, 199, 166, 74, 99, 186, 176, 89}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 104, 58, 98, 14, 81, 71, 114, 102}, 25}, {{235, 0, 92, 137, 81, 46, 230, 84, 170, 24, 83, 119, 232, 199, 149, 240}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 132, 178, 138, 134}, 25}, {{235, 0, 0, 0, 0, 0, 7, 241, 0, 156, 171, 177, 38, 237, 16, 252}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 106}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 14}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{235, 0, 0, 0, 0, 105, 223, 19, 136, 208, 152, 26, 253, 208, 119, 137}, 25}, {{235, 0, 0, 0, 0, 0, 0, 52, 136, 236, 53, 55, 173, 225, 208, 15}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 120, 66, 110}, 25}, {{235, 0, 0, 0, 0, 0, 155, 145, 211, 44, 130, 4, 142, 98, 7, 98}, 25}, {{235, 0, 0, 0, 0, 1, 171, 214, 16, 61, 108, 82, 66, 84, 139, 43}, 25}, {{235, 0, 0, 109, 96, 132, 28, 70, 185, 207, 41, 107, 88, 108, 11, 195}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 186, 92, 202, 206}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 126, 239, 179, 206, 60, 252, 73, 26}, 25}, {{235, 0, 0, 0, 0, 243, 143, 12, 95, 82, 14, 113, 125, 84, 173, 5}, 25}, {{235, 0, 185, 168, 181, 26, 123, 18, 194, 100, 200, 115, 97, 190, 4, 51}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 28, 40, 251}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 26, 44, 111, 100, 173, 171, 15}, 25}, {{235, 0, 0, 0, 0, 0, 0, 127, 126, 60, 165, 230, 175, 80, 220, 25}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 87}, 25}, {{235, 0, 0, 0, 219, 73, 131, 51, 142, 86, 11, 173, 149, 222, 234, 55}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 141, 211, 31, 31, 13}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 234, 85, 96, 208, 202, 237, 227}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 56, 67, 95, 152, 37, 115, 160}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 221, 65}, 25}, {{235, 0, 0, 127, 177, 209, 157, 21, 183, 129, 7, 137, 130, 172, 168, 214}, 25}, {{235, 0, 0, 0, 0, 0, 103, 20, 51, 248, 248, 228, 36, 75, 81, 191}, 25}, {{235, 0, 0, 0, 0, 0, 25, 227, 52, 5, 23, 71, 74, 127, 173, 114}, 25}, {{235, 0, 73, 187, 8, 176, 138, 116, 108, 89, 93, 30, 179, 62, 7, 174}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 85, 217, 109, 80, 28, 33, 209}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 95, 38, 236, 45}, 25}, {{235, 0, 0, 0, 0, 0, 0, 81, 24, 57, 191, 37, 63, 234, 6, 20}, 25}, {{235, 0, 0, 0, 214, 201, 120, 247, 104, 109, 170, 87, 205, 226, 174, 154}, 25}, {{235, 0, 0, 0, 68, 191, 231, 236, 241, 255, 109, 21, 163, 214, 176, 105}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 249, 61, 243, 55, 102, 188, 66}, 25}, {{235, 0, 0, 0, 0, 0, 70, 245, 213, 173, 30, 217, 23, 129, 100, 195}, 25}, {{235, 0, 0, 0, 0, 201, 173, 87, 16, 125, 229, 59, 110, 237, 51, 80}, 25}, {{235, 0, 0, 0, 0, 0, 102, 128, 0, 228, 124, 179, 193, 99, 178, 229}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 85, 190, 145, 60, 42}, 25}, {{235, 0, 222, 70, 219, 193, 238, 214, 237, 198, 139, 138, 42, 28, 56, 188}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 182, 228, 58, 202, 126}, 25}, {{235, 0, 0, 0, 183, 245, 2, 65, 225, 110, 117, 228, 140, 105, 69, 192}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 60}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 121, 107, 217}, 25}, {{235, 0, 0, 0, 0, 0, 0, 87, 164, 161, 191, 175, 197, 87, 230, 81}, 25}, {{235, 0, 0, 0, 0, 74, 65, 53, 186, 231, 41, 96, 163, 24, 253, 115}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 31, 51, 234}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 191, 106, 80, 46, 139, 54, 7}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 189, 132}, 25}, {{235, 0, 0, 0, 92, 212, 194, 204, 27, 234, 222, 221, 150, 45, 26, 248}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 164, 227, 189, 33, 133, 7, 199, 73}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 190, 132}, 25}, {{235, 0, 36, 196, 13, 244, 156, 140, 143, 55, 207, 120, 4, 109, 69, 145}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 239, 148, 130, 139, 220, 89, 79}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 196, 137}, 25}, {{235, 0, 0, 0, 0, 0, 0, 75, 64, 59, 225, 241, 77, 76, 252, 65}, 25}, {{235, 0, 0, 114, 39, 96, 58, 168, 123, 188, 55, 91, 185, 180, 128, 245}, 25}, {{235, 0, 0, 0, 0, 41, 183, 43, 80, 219, 247, 27, 184, 41, 71, 147}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 78, 97, 230, 56, 26, 172, 15}, 25}, {{235, 0, 0, 15, 209, 176, 145, 140, 39, 217, 194, 178, 77, 32, 8, 49}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 113, 51, 51, 233, 117, 16, 18}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 5}, 25}, {{235, 0, 0, 0, 114, 237, 92, 49, 3, 238, 100, 139, 58, 16, 114, 70}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 163, 158, 18, 52, 40}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 62, 188, 186, 181, 21}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 144, 204, 150, 194, 85}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 166, 114}, 25}, {{235, 0, 0, 136, 15, 191, 48, 168, 167, 4, 33, 41, 36, 135, 130, 3}, 25}, {{235, 0, 0, 0, 0, 0, 0, 32, 68, 149, 89, 88, 120, 91, 202, 120}, 25}, {{235, 0, 0, 0, 200, 199, 232, 177, 211, 133, 158, 16, 152, 192, 217, 18}, 25}, {{235, 0, 0, 102, 151, 172, 59, 128, 115, 173, 94, 252, 163, 182, 77, 221}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 218, 143, 46, 13, 70}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 146, 179, 248, 90}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 41, 137, 179, 174, 151, 182, 46}, 25}, {{235, 0, 146, 11, 228, 16, 149, 136, 225, 74, 180, 86, 179, 96, 243, 54}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 117}, 25}, {{235, 0, 0, 0, 0, 0, 234, 30, 125, 8, 46, 152, 119, 186, 106, 59}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 252, 98, 4, 72, 11, 121, 72, 199}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 93, 28, 154, 65, 221, 225, 88, 56}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 37, 144, 100, 156, 173}, 25}, {{235, 0, 0, 0, 0, 0, 171, 96, 122, 107, 65, 144, 153, 169, 190, 84}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 121, 127}, 25}, {{235, 0, 0, 0, 0, 0, 196, 136, 228, 18, 111, 225, 128, 195, 160, 113}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 105, 165, 7, 198, 4}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 25}, {{235, 0, 0, 165, 1, 189, 173, 61, 202, 56, 18, 12, 121, 141, 41, 238}, 25}, {{235, 0, 0, 0, 0, 0, 221, 17, 208, 239, 136, 115, 176, 231, 226, 40}, 25}, {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 13, 154, 85, 166, 191}, 25}, {{46, 72, 0, 0, 44, 142, 62, 57, 48, 116, 123, 24, 112, 147, 128, 83}, 150}, {{46, 72, 0, 0, 244, 31, 180, 223, 230, 225, 105, 241, 215, 145, 62, 160}, 150}, {{46, 72, 0, 0, 0, 0, 0, 109, 7, 225, 164, 142, 147, 64, 73, 88}, 150}, {{46, 72, 0, 169, 134, 194, 122, 171, 128, 63, 87, 206, 7, 79, 157, 8}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 176, 127, 99}, 150}, {{46, 72, 0, 0, 67, 221, 175, 130, 76, 10, 133, 59, 172, 69, 225, 240}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 151, 110, 122, 108}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 199, 23}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 115, 221, 13, 199, 58, 171, 11}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 11, 208}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 131, 190, 102, 186}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 28}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 43, 51, 86, 229, 64, 211, 159, 60}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 150}, {{46, 72, 0, 0, 0, 0, 0, 143, 150, 143, 93, 119, 241, 168, 122, 16}, 150}, {{46, 72, 0, 0, 127, 155, 210, 29, 189, 120, 54, 117, 102, 133, 206, 166}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 237, 225, 47, 35, 50, 215, 77}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 49, 190, 169, 72}, 150}, {{46, 72, 0, 0, 248, 152, 72, 200, 240, 121, 108, 89, 76, 152, 37, 24}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 85, 189, 102, 97, 181, 213, 102}, 150}, {{46, 72, 0, 0, 0, 51, 121, 243, 192, 248, 116, 119, 79, 244, 214, 22}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 161, 123, 88, 211, 29, 224, 98}, 150}, {{46, 72, 0, 0, 0, 174, 101, 105, 94, 234, 13, 239, 237, 255, 249, 244}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 53, 85, 123}, 150}, {{46, 72, 0, 64, 162, 228, 131, 153, 111, 47, 181, 20, 253, 245, 89, 131}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 107, 244, 108, 90}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 249, 77, 90, 220, 248, 75}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 116, 252, 226}, 150}, {{46, 72, 0, 0, 0, 0, 40, 138, 175, 110, 60, 144, 187, 145, 82, 60}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 34, 166, 130}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 23, 78, 82, 135}, 150}, {{46, 72, 0, 0, 0, 0, 0, 254, 156, 90, 185, 232, 133, 226, 44, 48}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 150}, {{46, 72, 0, 0, 22, 117, 50, 190, 57, 233, 126, 24, 36, 226, 147, 216}, 150}, {{46, 72, 0, 0, 0, 0, 209, 31, 34, 58, 253, 242, 123, 191, 158, 106}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 202, 243, 7, 107, 216, 206, 45, 146, 87, 237, 154}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 106, 149, 227}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 108}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 97, 68, 192, 56, 196, 111, 157, 57, 243, 24, 50, 230}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 137}, 150}, {{46, 72, 0, 0, 0, 0, 252, 13, 49, 121, 166, 247, 164, 232, 239, 96}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 150}, {{46, 72, 0, 0, 0, 0, 48, 13, 239, 168, 147, 193, 177, 244, 13, 130}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 4, 188, 48, 196, 145, 54, 22, 134}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 86, 237, 147, 111, 73, 236}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 76, 244}, 150}, {{46, 72, 0, 0, 115, 61, 206, 92, 227, 69, 245, 170, 42, 242, 60, 58}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 146, 230, 52, 20, 75, 11, 23, 136}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 16, 104, 220, 224, 40, 182, 195}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 172, 85}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 107, 228, 185, 28, 211, 147}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 172}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 230, 237, 208}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 103, 209, 10, 173}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 46, 232}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 68}, 150}, {{46, 72, 0, 18, 37, 180, 123, 214, 196, 82, 4, 219, 218, 214, 134, 186}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 92, 210, 162, 216, 192, 195}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 126, 80, 54, 104, 231, 21, 144}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 217, 99, 147, 45, 52, 237, 220}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 247}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 15, 87}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 116, 108, 13, 227, 72, 120, 248, 207, 180, 47, 36, 35}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 52, 141, 140, 144, 255, 32, 52, 84}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 150}, {{46, 72, 0, 0, 0, 0, 0, 236, 184, 237, 21, 164, 60, 159, 61, 174}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 204, 151, 4}, 150}, {{46, 72, 0, 0, 0, 65, 3, 122, 126, 197, 162, 24, 73, 61, 21, 169}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 178, 245, 76, 209, 120, 109, 52, 15, 75, 213, 43, 241, 174}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 66, 230, 25, 135, 191, 58, 51}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 39}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 2, 204, 147, 125, 68, 64, 76, 212, 31, 33, 131, 127, 217}, 150}, {{46, 72, 0, 0, 0, 0, 104, 47, 137, 160, 98, 9, 0, 172, 112, 13}, 150}, {{46, 72, 0, 0, 0, 0, 175, 172, 215, 37, 71, 185, 192, 194, 197, 207}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 171, 62}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 159, 64, 137, 151, 203, 136, 178}, 150}, {{46, 72, 0, 0, 0, 0, 190, 225, 17, 126, 243, 178, 251, 52, 255, 128}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 159, 82, 105, 201, 192, 48}, 150}, {{46, 72, 0, 0, 77, 117, 149, 158, 183, 147, 238, 153, 49, 145, 47, 61}, 150}, {{46, 72, 0, 0, 0, 0, 202, 239, 21, 235, 172, 57, 172, 95, 196, 120}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 117, 28, 122, 197, 62, 167}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 229, 192, 30, 5, 161, 100}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 211, 65}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 90, 151, 99, 139, 136, 0, 30, 154, 11, 179, 165, 226}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 150}, {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 150}, {{46, 72, 0, 0, 0, 0, 0, 121, 65, 156, 32, 86, 131, 184, 87, 61}, 150}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 29}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 225, 45}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 12, 197, 89}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 113, 72}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 199, 63, 184}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 180, 193}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 118, 20, 253, 231, 239, 106}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 144}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 160, 248, 130}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 115, 226, 44, 83}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 226, 114}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 90, 76, 99, 240, 103, 239}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 248, 149, 158}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 95}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 144, 170, 127}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 148, 151}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 79}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 110}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 219, 26}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 236}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 10, 83, 108, 54, 14}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 35}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 160, 30, 38, 131}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 137}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 154, 81, 12, 6}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 80, 104}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 158, 10, 205, 208, 134}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 181, 114, 49, 119}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 24}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 240, 184}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 161, 8, 173, 208, 236}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 24, 87, 229, 220, 197, 29}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 63, 68, 2, 179}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 243, 35, 211, 251}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 79, 177, 100}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 143, 130}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 151, 197}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 35, 58, 62, 33, 247}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 68, 84, 90, 134, 27, 92}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 79}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 50, 145, 3}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 167}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 18, 148}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 170, 50, 163, 71, 27}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 81}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 116, 159, 68, 212, 242, 137}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 177, 138, 94, 43, 152}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 174, 122, 65, 216}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 215, 162, 63, 163, 225, 140}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 240}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 122, 250, 20, 229, 204}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 1, 166}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 8, 119, 184, 180, 155}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 46}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 57}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 94, 226, 148, 108, 123, 74}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 169, 209, 191, 254, 170, 200}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 92, 125, 252, 123, 236}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 255, 184, 14, 15, 78, 195}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 234, 222, 153, 105, 70}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 12, 90}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 36, 205, 231}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 167, 55, 75, 106, 166}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 186, 76, 23, 149}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 35, 206, 54, 74, 5}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 197}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 134, 236, 151, 219}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 56, 39, 34, 163}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 33}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 220, 44, 242}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 191}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 254, 60, 118, 6, 49}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 110, 147, 7, 138}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 169, 19, 8, 111}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 64}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 18, 164, 127, 29}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 97, 133, 97, 160, 63}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 98}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 241, 122, 18, 141, 142}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 121, 64, 130}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 133, 236, 6, 185, 131, 45}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 173, 201}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 181, 45, 91, 117, 13, 100}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 55, 219}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 7, 61, 21, 92}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 229, 249, 66}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 95, 114, 8}, 103}, {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 132, 226, 57, 253, 40}, 103}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 102, 166, 203}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 41, 39}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 129, 176, 188, 207, 201, 154, 142}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 110, 186, 239, 231}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 45, 41, 29, 126, 255, 103}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 141, 15, 89, 122, 195, 119}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 171, 197, 49, 219}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 62, 230, 154, 200, 0, 194}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 82, 75, 200, 2, 253, 28}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 156, 129, 23, 68, 48}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 239, 6, 215, 50, 135, 197}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 112, 89, 56, 159}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 190, 11, 45, 194}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 148, 209, 136, 216}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 204, 149, 100, 69}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 43, 112, 122, 91, 28}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 161, 100, 240, 82, 101, 214}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 152, 73, 208, 85, 164}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 88, 52}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 126, 179, 127, 11, 50}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 187, 219, 218}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 188}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 97, 122, 110, 186, 104, 252}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 145, 24, 228}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 126, 210}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 25}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 211, 233}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 32, 15, 225}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 55, 248, 206, 204, 141, 119}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 52}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 56, 210, 149, 162, 39}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 59, 59}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 235, 125, 29, 100}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 18, 85, 94, 160}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 34, 203}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 127, 233, 167, 193, 62, 203}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 151, 9, 57, 73, 156, 204}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 238, 226, 52, 43}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 207}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 204, 155, 37, 118}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 159, 134, 18, 59, 242}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 72, 55, 88, 227, 142, 48}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 14, 162, 199, 117, 152, 173}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 9, 93, 131, 64, 190, 216}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 178, 133, 217}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 206, 185, 22, 113, 185, 240}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 23, 67, 186, 234}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 101, 0, 53, 96, 237, 119}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 168, 156, 79}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 138}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 209}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 136, 98, 151, 130, 135}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 44, 134, 223, 206, 147}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 107, 248, 87}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 79, 159, 30}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 38, 138}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 148, 243, 222}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 133, 44, 89, 129}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 218, 64, 6}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 207}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 86, 147, 105, 179, 6, 191}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 136, 225, 227}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 159}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 221, 144, 251}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 153, 52, 123, 179}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 237, 145, 170, 87, 235}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 245}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 133}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 61, 13, 130, 8, 74, 145}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 199, 159, 213}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 191, 116, 57, 140, 214}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 138, 77, 119, 110, 193, 80}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 64, 224}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 123, 66, 11}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 4, 32}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 170, 76, 53}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 53, 8, 143, 32, 98}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 11, 161, 8, 186, 83}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 149, 11, 200}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 15, 114, 252, 112, 175}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 69, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 179, 121, 242}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 184, 252, 228, 13}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 38}, 155}, {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 155}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 204}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 98, 191, 46}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 233}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 203, 93}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 163, 248, 118}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 215, 81, 169}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 48}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 6}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 17}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 4, 153, 146}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 122, 120}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 110}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 93}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 233, 66, 111}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 15, 106}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 192, 219}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 199, 31, 26}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 109, 110, 249}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 178}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 59, 158}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 63, 60}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 189, 122, 16}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 244, 48}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 81}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 176, 45}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 31, 73, 5}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 60}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 140, 49, 193}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 138, 106}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 189}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 186, 127}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 219}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 193}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 127, 133}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 221}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 123, 144, 205}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 33, 246, 43}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 242, 109}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 106}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 197, 53}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 84}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 212}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 255, 234}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 255}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 57, 134, 172}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 30}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 73, 40}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 132, 166, 221}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 164}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 6}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 17}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 173, 101, 100}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 160}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 230, 249, 25}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 99, 212, 118}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 131}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 5, 90}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 171, 47}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 26, 247}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 226, 172}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 60}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 65, 188}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 230, 227}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 236}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 176}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 218, 85, 62}, 142}, {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 142}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 169}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 76}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 52}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 3}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 9}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 221}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 214}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 236}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 64}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 119}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 13}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 178}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 83}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 157}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 175}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 128}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 249}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 228}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 2}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 94}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 31}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 90}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 229}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 113}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 229}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 80}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 1}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 97}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 25}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 123}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 143}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 198}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 222}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 128}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 186}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 30}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 226}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 4}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 220}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 34}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 2}, {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 36}, 2}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 154, 236, 87, 174}, 59}, {{25, 76, 0, 0, 0, 28, 134, 28, 125, 242, 152, 35, 220, 232, 236, 247}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 4, 183, 198}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 252, 194, 54, 92, 218, 223}, 59}, {{25, 76, 0, 0, 0, 0, 0, 140, 50, 178, 140, 27, 104, 149, 4, 145}, 59}, {{25, 76, 0, 0, 0, 0, 0, 88, 95, 90, 87, 226, 101, 148, 242, 92}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 89, 161, 103, 193, 170, 201}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 42, 98}, 59}, {{25, 76, 0, 0, 136, 220, 133, 121, 231, 240, 66, 170, 254, 143, 86, 233}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 78, 96, 154, 5, 6, 141, 0}, 59}, {{25, 76, 0, 0, 0, 0, 0, 77, 143, 165, 70, 65, 111, 9, 221, 183}, 59}, {{25, 76, 0, 0, 0, 0, 0, 8, 242, 107, 39, 115, 110, 116, 112, 19}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 244, 53, 15, 247}, 59}, {{25, 76, 0, 0, 147, 143, 89, 62, 57, 118, 8, 161, 145, 168, 96, 46}, 59}, {{25, 76, 0, 0, 168, 55, 88, 177, 107, 17, 32, 166, 209, 66, 159, 240}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 191, 49, 216, 13}, 59}, {{25, 76, 0, 0, 0, 0, 0, 131, 134, 43, 222, 249, 160, 163, 34, 17}, 59}, {{25, 76, 0, 0, 0, 0, 154, 249, 197, 221, 126, 123, 105, 160, 179, 235}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 57}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 111, 166, 36, 117, 160, 73, 150, 126, 174, 49}, 59}, {{25, 76, 0, 0, 0, 159, 77, 139, 139, 184, 165, 9, 208, 54, 188, 229}, 59}, {{25, 76, 0, 39, 109, 7, 113, 153, 88, 107, 161, 11, 130, 111, 79, 176}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 166, 255}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 208}, 59}, {{25, 76, 0, 0, 0, 0, 77, 242, 56, 99, 135, 28, 227, 219, 96, 180}, 59}, {{25, 76, 0, 180, 230, 92, 203, 121, 125, 205, 250, 90, 78, 35, 42, 244}, 59}, {{25, 76, 0, 0, 0, 0, 0, 146, 153, 169, 57, 110, 111, 156, 135, 247}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 207, 241, 49}, 59}, {{25, 76, 0, 186, 156, 211, 29, 235, 1, 174, 108, 75, 157, 168, 238, 55}, 59}, {{25, 76, 0, 0, 0, 0, 0, 113, 177, 159, 176, 128, 9, 161, 150, 219}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 209, 243, 209, 198, 166, 238, 129, 188, 75, 254, 70, 217}, 59}, {{25, 76, 0, 0, 0, 0, 0, 38, 82, 82, 76, 175, 162, 128, 21, 26}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 110, 108, 27, 155, 104, 182, 54, 252}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 21, 16, 192, 98, 148, 172, 97}, 59}, {{25, 76, 0, 0, 0, 0, 0, 165, 222, 46, 78, 8, 104, 33, 236, 12}, 59}, {{25, 76, 0, 0, 0, 0, 0, 241, 20, 219, 141, 134, 23, 53, 38, 234}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 147, 116, 52}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 48, 98, 5, 33, 249, 51, 38}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 136, 121}, 59}, {{25, 76, 0, 0, 0, 105, 12, 144, 151, 60, 220, 17, 205, 121, 29, 226}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 59}, {{25, 76, 0, 218, 152, 90, 44, 155, 143, 229, 120, 236, 81, 197, 146, 188}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 244, 73, 167, 234, 92, 65, 242, 213}, 59}, {{25, 76, 0, 0, 0, 0, 113, 12, 61, 158, 17, 251, 55, 50, 151, 195}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 106, 180, 146, 201, 130, 241}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 154, 170, 169, 74, 229, 105, 37, 152, 187, 237}, 59}, {{25, 76, 0, 0, 0, 0, 200, 57, 219, 43, 139, 143, 27, 154, 249, 141}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 143, 1, 13, 181, 160, 39}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 236, 253, 41, 14, 102, 72}, 59}, {{25, 76, 0, 0, 0, 0, 0, 177, 240, 5, 97, 114, 84, 127, 206, 208}, 59}, {{25, 76, 0, 0, 0, 230, 244, 23, 179, 8, 60, 173, 216, 148, 24, 179}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 17, 159, 143, 97}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 202, 142, 125, 177}, 59}, {{25, 76, 0, 0, 0, 169, 89, 233, 12, 120, 107, 95, 23, 106, 245, 55}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 24}, 59}, {{25, 76, 0, 0, 0, 26, 186, 87, 154, 120, 140, 172, 52, 188, 181, 229}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 131, 255, 255, 132, 86, 24, 215, 33}, 59}, {{25, 76, 0, 0, 0, 0, 0, 157, 139, 186, 50, 98, 57, 126, 160, 16}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 196, 130, 223, 139, 2, 140, 62, 151}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 238, 45}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 249, 82}, 59}, {{25, 76, 0, 0, 0, 0, 59, 245, 163, 226, 30, 213, 41, 255, 126, 240}, 59}, {{25, 76, 0, 244, 12, 180, 76, 32, 91, 174, 78, 87, 182, 240, 4, 5}, 59}, {{25, 76, 0, 0, 80, 218, 50, 0, 126, 89, 36, 146, 43, 146, 82, 168}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 0, 0, 119, 35, 170, 94, 0, 245, 80, 28, 214}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 152, 81, 184, 191, 184, 67, 129, 201}, 59}, {{25, 76, 0, 0, 235, 126, 249, 243, 235, 199, 123, 234, 109, 14, 29, 200}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 34, 174, 142, 12, 157, 41, 154, 227}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 57, 15, 107, 85, 75, 215, 183}, 59}, {{25, 76, 0, 0, 0, 0, 250, 9, 53, 143, 119, 157, 44, 21, 75, 2}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 23, 203}, 59}, {{25, 76, 0, 0, 21, 209, 188, 174, 69, 57, 4, 213, 171, 28, 74, 107}, 59}, {{25, 76, 0, 0, 0, 0, 0, 181, 63, 90, 231, 89, 240, 97, 222, 46}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 122, 84, 68, 194, 116, 207, 113, 239}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 160, 171, 78}, 59}, {{25, 76, 0, 0, 0, 0, 140, 195, 53, 159, 248, 225, 179, 199, 247, 4}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 250, 86}, 59}, {{25, 76, 0, 0, 0, 0, 0, 101, 241, 141, 180, 5, 210, 149, 147, 132}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 129, 242, 198, 80, 249, 135, 66}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 66, 190}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 221, 117}, 59}, {{25, 76, 0, 0, 0, 0, 0, 109, 82, 206, 177, 67, 90, 113, 195, 118}, 59}, {{25, 76, 0, 0, 0, 0, 41, 154, 180, 177, 177, 133, 166, 109, 61, 37}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 88, 87, 89, 121}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{25, 76, 0, 0, 0, 124, 173, 100, 38, 23, 7, 39, 25, 19, 199, 35}, 59}, {{25, 76, 0, 0, 0, 0, 98, 10, 89, 186, 4, 231, 155, 66, 194, 144}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 59}, {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 59}, 59}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 33}, 208}, {{160, 0, 0, 67, 245, 185, 38, 100, 142, 251, 21, 131, 149, 74, 142, 41}, 208}, {{160, 0, 0, 0, 165, 17, 250, 208, 118, 63, 43, 143, 6, 108, 51, 251}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 67, 66, 56, 164, 193, 82, 219}, 208}, {{160, 0, 0, 0, 0, 145, 207, 180, 228, 195, 66, 156, 20, 251, 159, 235}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 208, 85, 220, 174}, 208}, {{160, 0, 0, 180, 117, 7, 30, 218, 131, 210, 38, 152, 66, 216, 39, 223}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 230, 90, 40, 233}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 220, 190, 7, 75, 19}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 124, 137, 203, 23}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 134, 213, 220, 70, 10, 216, 126}, 208}, {{160, 0, 0, 22, 108, 139, 70, 1, 6, 67, 101, 88, 42, 148, 39, 231}, 208}, {{160, 0, 0, 0, 0, 0, 157, 217, 27, 115, 58, 45, 24, 125, 24, 189}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 216}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 236, 248, 38, 223}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 194}, 208}, {{160, 0, 160, 92, 53, 154, 160, 170, 200, 108, 205, 60, 217, 59, 70, 188}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 171, 6, 179, 228, 134, 153, 132, 142}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 31, 82, 233, 125, 60}, 208}, {{160, 0, 0, 0, 141, 139, 81, 181, 108, 49, 8, 73, 156, 77, 90, 58}, 208}, {{160, 0, 0, 0, 0, 0, 0, 96, 183, 206, 15, 242, 86, 122, 117, 119}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 224, 156}, 208}, {{160, 0, 0, 136, 41, 100, 166, 83, 70, 251, 250, 18, 113, 209, 50, 15}, 208}, {{160, 113, 143, 204, 43, 201, 141, 42, 172, 225, 36, 171, 130, 236, 114, 214}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 47, 201, 209, 37, 245, 211, 105, 101, 149, 44, 144, 185}, 208}, {{160, 0, 0, 166, 114, 159, 200, 198, 162, 170, 88, 30, 28, 111, 163, 60}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 208}, {{160, 0, 0, 111, 224, 185, 120, 159, 56, 86, 84, 198, 204, 172, 131, 169}, 208}, {{160, 0, 0, 0, 0, 0, 0, 205, 62, 159, 116, 200, 128, 100, 160, 208}, 208}, {{160, 0, 0, 0, 0, 0, 0, 254, 143, 245, 61, 14, 129, 118, 179, 228}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 106, 87}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 43, 125}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 113, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 247, 255}, 208}, {{160, 0, 0, 0, 0, 0, 0, 142, 240, 206, 135, 221, 118, 229, 215, 113}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 130, 136, 104, 88, 77, 224, 107}, 208}, {{160, 0, 123, 119, 253, 6, 153, 82, 129, 117, 7, 28, 38, 214, 108, 210}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 203, 250, 168, 7, 24}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 215, 29}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 93, 81, 39, 200}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 71, 26, 184, 105, 19, 239, 62, 75}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 137, 225, 249, 84, 178, 133, 35}, 208}, {{160, 0, 0, 0, 0, 0, 140, 28, 142, 214, 150, 137, 32, 48, 173, 31}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 93, 108, 55, 3}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 205, 182, 226, 187, 99, 113, 178, 243}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 128, 85, 18, 243, 138, 16, 9}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 30, 32, 168, 101, 17, 220, 69, 229, 83, 197, 237, 157, 146}, 208}, {{160, 244, 47, 196, 227, 91, 27, 130, 72, 2, 186, 213, 242, 187, 81, 187}, 208}, {{160, 0, 253, 125, 140, 59, 179, 116, 59, 203, 176, 197, 6, 134, 223, 1}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 98, 40, 93}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 196, 253, 49, 65, 105, 18, 1}, 208}, {{160, 0, 0, 112, 252, 76, 168, 183, 40, 41, 12, 42, 30, 82, 39, 185}, 208}, {{160, 21, 0, 140, 46, 194, 167, 128, 51, 179, 187, 210, 186, 32, 53, 124}, 208}, {{160, 0, 0, 128, 199, 149, 36, 28, 12, 102, 166, 211, 176, 1, 138, 154}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 149, 226, 205, 91, 235, 226, 93}, 208}, {{160, 0, 142, 132, 200, 8, 29, 7, 171, 142, 224, 235, 10, 97, 74, 219}, 208}, {{160, 0, 0, 0, 0, 108, 187, 204, 240, 201, 175, 140, 167, 105, 234, 221}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 106, 113}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 212, 148, 76, 144, 121, 158, 57}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 227, 41, 104, 236}, 208}, {{160, 0, 0, 0, 0, 0, 0, 223, 92, 159, 29, 251, 46, 52, 167, 245}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 210, 123, 38, 32, 175, 79, 19}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 12, 133, 39, 181, 217, 113, 29, 127, 66, 110, 90, 247, 198}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 73, 53, 58, 170}, 208}, {{160, 0, 194, 198, 36, 215, 135, 213, 174, 207, 240, 224, 156, 152, 238, 97}, 208}, {{160, 0, 0, 0, 0, 0, 109, 60, 189, 150, 129, 19, 220, 208, 32, 17}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 184, 118, 96, 92, 174}, 208}, {{160, 89, 70, 70, 122, 20, 161, 29, 152, 225, 91, 91, 56, 17, 72, 145}, 208}, {{160, 0, 0, 0, 0, 76, 97, 252, 34, 124, 99, 170, 30, 80, 96, 219}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 102, 236}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 73, 249}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 159, 167, 248, 235, 188}, 208}, {{160, 0, 0, 0, 167, 174, 247, 76, 165, 81, 193, 48, 157, 144, 81, 34}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 91}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 132, 23}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 129}, 208}, {{160, 0, 0, 0, 0, 227, 101, 27, 231, 8, 6, 12, 103, 157, 147, 243}, 208}, {{160, 0, 140, 136, 94, 198, 125, 153, 145, 7, 254, 101, 36, 252, 50, 216}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 119, 65, 206, 66}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 208}, {{160, 0, 0, 0, 211, 47, 83, 60, 221, 105, 4, 255, 86, 88, 145, 121}, 208}, {{160, 0, 0, 0, 0, 0, 203, 103, 179, 172, 157, 87, 25, 40, 149, 33}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 207, 191}, 208}, {{160, 0, 0, 0, 252, 157, 73, 25, 2, 152, 223, 6, 66, 180, 156, 34}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 208}, {{160, 0, 0, 0, 0, 0, 0, 128, 161, 220, 90, 54, 157, 75, 108, 141}, 208}, {{160, 0, 0, 0, 0, 192, 68, 185, 233, 9, 149, 251, 139, 126, 190, 44}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 208}, {{26, 203, 217, 152, 16, 187, 0, 166, 224, 181, 136, 14, 209, 202, 44, 124}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 187, 224, 239, 40}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 1, 41, 93, 11, 28, 231, 153}, 166}, {{26, 203, 217, 152, 16, 187, 0, 248, 85, 239, 137, 181, 154, 50, 234, 80}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 60, 149, 160, 198, 24, 39}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 172, 194, 42, 138, 93, 23, 23}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 34, 38}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 83, 151}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 245, 171, 251, 80, 211, 205, 84, 161}, 166}, {{26, 203, 217, 152, 16, 187, 0, 238, 141, 103, 221, 177, 137, 143, 249, 196}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 179, 9, 167, 77, 7, 163, 151}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 166}, {{26, 203, 217, 152, 16, 187, 0, 249, 214, 133, 175, 80, 38, 29, 122, 240}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 7, 73}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 220, 98}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 164, 12, 26, 47, 60, 167, 163}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 233, 187, 120, 21, 139}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 231, 169, 53, 176, 70}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 140, 30}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 124, 162}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 171, 30, 58, 229, 91, 179}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 186, 82, 171}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 54, 247, 40, 44, 141, 7, 213}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 163, 243, 179, 83, 62, 113, 252, 223}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 31, 50, 41, 74, 40, 6, 139}, 166}, {{26, 203, 217, 152, 16, 187, 0, 60, 149, 61, 181, 178, 87, 236, 11, 29}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 140, 95, 165, 127}, 166}, {{26, 203, 217, 152, 16, 187, 0, 118, 162, 55, 137, 84, 40, 203, 87, 205}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 191, 166, 147, 22, 22, 81, 254, 28, 14}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 254, 49, 27, 183}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 246, 212, 185, 72}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 55, 125, 60, 84, 119, 200}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 134, 227, 246, 228}, 166}, {{26, 203, 217, 152, 16, 187, 0, 82, 117, 14, 133, 200, 221, 93, 52, 253}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 217, 82, 135, 64, 201, 133, 55, 140}, 166}, {{26, 203, 217, 152, 16, 187, 0, 63, 135, 252, 30, 44, 186, 51, 148, 190}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 121, 177, 32, 11, 169, 0, 166, 124}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 140, 112, 79, 204, 242, 117, 208}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 4, 51, 253, 1, 85, 41, 114, 75}, 166}, {{26, 203, 217, 152, 16, 187, 0, 122, 180, 185, 47, 195, 198, 196, 251, 166}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 89, 100, 136}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 170, 70, 54, 11, 115, 108}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 225, 189, 144, 88, 198, 247, 18}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 169, 145, 44, 136}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 207, 92}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 54, 114, 190, 165, 166, 134}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 195, 8, 49, 16, 236, 245}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 103, 215, 249, 70, 218, 64}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 173, 80, 223, 147, 222, 7, 255}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 248, 97}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 189, 54, 199, 141, 216, 122, 189}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 142, 94, 219, 90, 238, 181}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 39, 8, 176, 100, 102}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 38, 45, 84}, 166}, {{26, 203, 217, 152, 16, 187, 0, 59, 139, 253, 160, 11, 183, 12, 176, 232}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 50, 236, 215, 206, 10, 158, 196, 88}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 245, 97, 99, 191, 57, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 156, 103, 178, 16, 41, 220}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 159, 238, 69, 77}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 86, 191, 81, 62, 162, 191, 170, 30}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 25, 37}, 166}, {{26, 203, 217, 152, 16, 187, 0, 141, 117, 182, 229, 78, 159, 166, 199, 116}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 139, 23, 154, 56, 80}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 222, 250, 107, 138}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 11, 121, 81, 202, 34, 197}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 58, 219, 26, 191, 171, 242, 225}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 114, 186, 152, 18, 134, 44, 21}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 166}, {{26, 203, 217, 152, 16, 187, 0, 117, 233, 250, 87, 120, 239, 239, 30, 85}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 107, 100}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 170, 137, 204, 138, 228, 7, 162, 223}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 20, 116, 28, 193, 130, 182}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 68, 199, 175}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 54, 232, 140, 150, 53, 218}, 166}, {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 166}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 145, 240, 202}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 203, 67, 121, 231}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 134, 188}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 40, 74, 109, 140, 47}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 194, 192}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 54, 103, 104, 121, 226, 177}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 155, 95, 88, 17, 94, 255}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 60, 241, 253, 74, 13}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 255}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 110, 40, 112, 158, 41}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 123, 109, 227, 222}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 119, 65, 31}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 10, 133, 165}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 85}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 33, 79, 240}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 196, 62, 14, 166, 224, 237}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 230, 131, 86, 17, 57}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 159, 9, 168, 205, 182}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 101, 223}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 193, 75, 120}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 36}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 112, 248}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 107, 143, 16}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 93, 75, 180, 45}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 19, 96, 197, 166, 76, 103}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 68, 65, 119, 144, 15}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 44}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 47, 106, 46, 159, 253, 209}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 101, 215}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 78, 199}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 96, 237}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 76, 43, 190, 33}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 146, 23, 114, 15}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 57, 171}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 173, 76, 207}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 16, 67, 98, 151, 184}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 227}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 71}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 161, 96, 229, 15, 129}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 19}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 75, 245, 206, 3, 166}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 42, 29, 202}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 106, 117, 250, 54, 195, 141}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 181, 195, 255, 113}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 16, 30}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 148, 108, 244, 71, 186}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 160}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 176, 45, 213, 25, 91}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 182, 129}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 227, 217, 173}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 233, 134, 75, 185}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 39}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 77, 231, 68}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 77, 57, 253, 207}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 116, 32, 50}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 253}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 227, 2, 152, 229, 99}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 34, 191, 43, 82, 216}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 148, 49, 57, 48}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 95, 91, 129, 66, 28}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 21}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 27, 178, 189, 154, 23, 236}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 117, 165, 208}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 185, 11, 180}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 147, 239}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 196, 187, 173, 226, 230}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 89, 36, 36, 74, 86, 185}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 59, 4, 186, 0, 170, 86}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 152}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 177, 33, 62, 182}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 234, 121, 52, 124}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 178, 97, 248, 218}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 56, 84, 63}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 23, 38}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 22, 5}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 66, 162, 65, 85}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 27, 147, 91, 111, 36}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 235, 56, 17, 215}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 82, 214, 47, 195, 62, 66}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 140, 151, 252, 239, 138}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 179, 171}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 134, 181, 9, 186, 243, 244}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 18}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 205}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 102}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 237, 82, 194, 173}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 47, 240, 235}, 62}, {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 62}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 88, 209, 151, 147, 234}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 147, 228}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 196, 100, 178}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 243, 10}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 165, 4, 34, 220, 122}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 53, 165, 227, 90, 101, 153, 69, 159}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 100, 203}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 10, 43, 179, 140}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 176}, {{175, 230, 160, 13, 187, 17, 0, 92, 189, 104, 43, 80, 240, 38, 63, 158}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 207, 78}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 9, 23, 94, 64, 73, 185, 160, 191}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 67, 117, 226, 132, 133, 224, 197, 148}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 30, 64, 13, 106, 146, 145, 158}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 247, 80}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 176, 57, 253}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 35, 229, 70, 203, 164, 106, 128, 87}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 109, 239, 21, 254, 119, 32, 135}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 45, 53, 65, 233, 1}, 176}, {{175, 230, 160, 13, 187, 17, 0, 26, 114, 156, 245, 211, 139, 220, 158, 108}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 36, 254, 250, 100, 48, 190, 9, 132}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 152, 219, 211, 204}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 212, 250, 58, 20, 75}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 234, 5, 179, 102, 191, 254, 245, 42}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 167, 2, 86, 219, 95, 209}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 230, 53, 163, 171, 239, 27, 200}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 209, 77, 220}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 136, 88, 148, 231, 39, 47, 193, 65}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 150, 184, 204, 111, 253, 252, 83, 114}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 142, 218, 147, 218, 176, 248}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 56, 117, 97, 50, 67}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 82, 243, 232, 44, 170}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 1, 137, 43, 202}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 227, 122, 51, 223}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 91, 57, 79, 117, 196, 136, 157}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 213, 49, 188, 121, 87, 141, 102, 204}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 203, 139, 189, 192, 107, 146, 207}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 172, 17}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 21, 8, 35, 10, 53}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 234, 180, 35, 74, 206, 223, 161, 207}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 175, 201, 154}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 176}, {{175, 230, 160, 13, 187, 17, 0, 154, 97, 151, 38, 173, 93, 171, 41, 45}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 16, 118, 32}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 229, 10, 190, 49, 43}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 186, 121}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 14, 199}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 244, 36, 110}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 79, 28}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 43, 59, 21, 58, 62}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 162, 171, 239, 204, 196, 97, 13, 11}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 21, 45, 203, 69, 81}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 207, 217, 66, 132, 117, 26}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 23, 224, 251, 194, 221, 207, 78}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 127, 132, 183}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 238, 132}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 141, 223}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 32, 192, 82, 18, 36, 191}, 176}, {{175, 230, 160, 13, 187, 17, 0, 230, 185, 51, 248, 153, 150, 52, 193, 240}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 125, 143, 245, 69, 23}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 37, 114, 192, 28, 133}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 249, 0, 254, 71, 247, 62}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 131, 28}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 13, 59, 171, 106, 81, 203, 76, 236}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 129, 67, 72, 32, 100, 48, 87, 251}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 132, 212, 14, 244, 63, 139}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 189, 131, 150, 224, 48, 128}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 61, 180, 150, 123, 115}, 176}, {{175, 230, 160, 13, 187, 17, 0, 179, 219, 209, 246, 191, 105, 36, 239, 191}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 176}, {{175, 230, 160, 13, 187, 17, 0, 15, 87, 162, 190, 172, 231, 30, 119, 175}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 110, 190, 136, 178}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 5, 201, 185, 207, 163}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 138, 243, 60}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 249, 133, 179, 155, 150, 203, 132, 184}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 181, 150, 212}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 55, 237}, 176}, {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 99, 60, 105, 200, 148, 24}, 176}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 141}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 3, 47, 130}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 228, 93}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 175, 49}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 147, 83}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 2}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 244, 243, 228}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 194}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 70}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 177, 2}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 181, 102}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 155, 89}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 81, 153}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 178, 7, 152}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 74, 11}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 32}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 66, 63}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 118}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 98, 47}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 96}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 213}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 169, 247}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 75, 200}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 102, 138}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 180, 45}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 18, 85}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 4, 89, 115}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 29}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 121, 24}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 198, 198}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 31}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 14, 139, 133}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 126}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 108}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 10, 77}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 131, 9, 53}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 80, 97}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 185}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 105, 234, 30}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 243}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 212, 201}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 251}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 7}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 53, 64}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 212, 167}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 119, 19, 17}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 19}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 69}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 161, 193}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 168}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 200, 174, 34}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 206}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 49, 222}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 167}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 150}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 124, 159}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 99}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 201}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 245}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 156}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 147, 37}, 6}, {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 252}, 6}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 79, 3, 70, 224}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 130, 14, 222, 140, 15, 252}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 3, 149, 135, 46, 181, 133, 134, 143}, 26}, {{45, 203, 3, 8, 0, 0, 0, 210, 163, 254, 225, 1, 181, 167, 124, 36}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 216, 213}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 116, 53, 119, 16, 49, 203, 38, 134}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 32, 204, 58, 250, 223, 83, 121}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 229, 12, 69, 147, 236}, 26}, {{45, 203, 3, 8, 5, 124, 133, 116, 254, 54, 40, 186, 240, 77, 143, 219}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 29, 193, 48, 220, 176, 177, 72, 53}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 19, 215, 66, 244}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 133, 56, 166, 208, 89}, 26}, {{45, 203, 3, 8, 0, 105, 96, 29, 33, 0, 202, 47, 49, 85, 252, 191}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 49, 32, 91, 140, 73, 54, 108}, 26}, {{45, 203, 3, 8, 0, 0, 0, 28, 125, 140, 255, 155, 195, 69, 113, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 30}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 91, 142, 172, 255}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 38, 82, 17, 61, 247, 182}, 26}, {{45, 203, 3, 8, 240, 43, 231, 34, 5, 69, 204, 114, 211, 39, 120, 136}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 83}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 171, 236, 193, 106, 116, 94, 80}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 211, 208, 236, 42, 205, 140, 39}, 26}, {{45, 203, 3, 8, 0, 30, 181, 10, 171, 8, 77, 133, 187, 202, 53, 84}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 35, 42, 12, 126, 171}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 238, 21, 187, 43}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 152, 141, 149, 141, 253, 70}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 27, 194, 180, 67, 99, 21, 132, 21, 162, 254}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 162, 88, 243, 246, 86, 188, 92}, 26}, {{45, 203, 3, 8, 0, 248, 233, 6, 92, 172, 183, 109, 230, 35, 145, 164}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 216, 91, 72, 129}, 26}, {{45, 203, 3, 8, 0, 54, 82, 197, 169, 229, 155, 31, 122, 69, 3, 237}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 22}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 190, 72, 76, 228, 207, 84, 87}, 26}, {{45, 203, 3, 8, 0, 0, 0, 116, 162, 242, 84, 13, 98, 63, 130, 10}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 26}, {{45, 203, 3, 8, 0, 0, 193, 247, 176, 74, 240, 1, 225, 90, 66, 91}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 89, 187, 25, 64, 28, 152, 159, 63}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 34, 156, 95, 212}, 26}, {{45, 203, 3, 8, 0, 0, 202, 152, 49, 200, 127, 131, 208, 85, 191, 126}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 84, 194, 39, 45, 226, 122}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 47}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 82, 195}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 153, 231, 167, 106, 35, 4, 209, 109}, 26}, {{45, 203, 3, 8, 0, 114, 104, 180, 22, 9, 137, 251, 44, 228, 152, 38}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 116, 179, 37, 59, 224, 194}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 225, 125, 130, 16, 142}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 198, 87, 28, 2, 156, 126}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 185, 63, 185, 158, 6}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 108, 77, 172, 106, 147}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 25, 69, 39, 199}, 26}, {{45, 203, 3, 8, 0, 0, 187, 17, 237, 254, 32, 199, 235, 72, 45, 61}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 243, 217, 70, 71}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 94}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 73, 119}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 157, 146, 118, 24, 102, 190, 101}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 77}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 131, 241, 81, 130, 16, 223, 106, 45, 198}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 164, 126, 188, 6, 71, 140, 85, 60}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 107}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 30, 217}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 234, 1}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 220, 135, 254, 106}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 66, 172, 112, 225, 154, 146, 81, 224}, 26}, {{45, 203, 3, 8, 0, 0, 183, 91, 82, 6, 14, 113, 239, 137, 231, 191}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 26}, {{45, 203, 3, 8, 0, 0, 171, 202, 18, 14, 234, 2, 149, 101, 111, 138}, 26}, {{45, 203, 3, 8, 0, 50, 236, 237, 96, 56, 250, 43, 37, 93, 23, 157}, 26}, {{45, 203, 3, 8, 0, 0, 241, 94, 157, 62, 42, 146, 19, 165, 175, 239}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 56}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 24}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 193, 94, 194, 13, 161, 92}, 26}, {{45, 203, 3, 8, 0, 0, 0, 213, 150, 189, 87, 171, 131, 254, 217, 208}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 207, 181, 129, 103, 236}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 75, 39, 60, 103, 172}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 174, 125, 175, 113, 116, 133, 213, 38}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{45, 203, 3, 8, 0, 77, 135, 96, 223, 116, 216, 250, 175, 200, 255, 225}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 202, 31, 15, 98}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 175, 164, 144, 219, 84, 218, 103}, 26}, {{45, 203, 3, 8, 0, 176, 76, 144, 23, 52, 0, 56, 203, 161, 160, 50}, 26}, {{45, 203, 3, 8, 0, 0, 0, 155, 6, 207, 91, 83, 50, 7, 91, 138}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 19, 103, 204, 215}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 26}, {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{120, 0, 0, 0, 14, 73, 125, 105, 13, 90, 88, 212, 53, 116, 255, 34}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 6}, {{120, 0, 0, 0, 84, 124, 179, 198, 48, 128, 104, 97, 221, 193, 132, 218}, 6}, {{120, 0, 0, 0, 0, 221, 156, 184, 215, 135, 62, 140, 17, 46, 114, 73}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 26, 36, 195, 236}, 6}, {{120, 0, 0, 0, 0, 151, 184, 161, 129, 85, 124, 213, 237, 97, 10, 246}, 6}, {{120, 0, 0, 0, 0, 148, 6, 240, 149, 175, 250, 103, 79, 104, 203, 5}, 6}, {{120, 153, 197, 231, 76, 163, 31, 193, 175, 93, 99, 233, 53, 82, 70, 179}, 6}, {{120, 0, 234, 195, 150, 13, 165, 135, 50, 66, 118, 208, 223, 73, 235, 138}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 186, 85}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 21, 130, 49, 106, 136}, 6}, {{120, 0, 58, 200, 240, 175, 66, 197, 73, 86, 201, 28, 218, 160, 76, 89}, 6}, {{120, 0, 0, 0, 0, 0, 32, 87, 230, 108, 101, 39, 102, 16, 49, 166}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 151, 7, 247, 254, 13}, 6}, {{120, 0, 0, 154, 83, 89, 139, 6, 242, 98, 197, 132, 169, 44, 235, 127}, 6}, {{120, 0, 0, 0, 0, 0, 0, 119, 61, 173, 69, 70, 169, 17, 59, 154}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 135, 197, 155, 50, 232, 27, 79}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 6}, {{120, 0, 0, 0, 0, 0, 0, 41, 163, 28, 93, 199, 246, 112, 152, 152}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 165, 201, 101, 75, 3, 18, 150, 130}, 6}, {{120, 0, 0, 0, 0, 0, 0, 83, 207, 211, 57, 160, 251, 4, 86, 151}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 54}, 6}, {{120, 0, 0, 0, 0, 0, 0, 239, 155, 8, 175, 92, 109, 5, 226, 209}, 6}, {{120, 0, 0, 169, 10, 214, 176, 175, 244, 166, 169, 64, 55, 35, 116, 225}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 28}, 6}, {{120, 0, 0, 186, 139, 10, 97, 122, 214, 212, 148, 123, 248, 45, 95, 103}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 225, 152, 220}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 119, 102, 165, 78, 42, 156, 58, 27}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 90}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 6}, {{120, 0, 0, 0, 220, 87, 109, 119, 146, 70, 2, 225, 97, 72, 117, 33}, 6}, {{120, 0, 0, 0, 0, 199, 27, 73, 236, 122, 208, 14, 103, 122, 156, 156}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 2}, 6}, {{120, 0, 0, 171, 162, 137, 2, 143, 30, 226, 231, 45, 230, 192, 136, 81}, 6}, {{120, 0, 0, 0, 0, 157, 136, 221, 25, 4, 77, 184, 132, 137, 207, 128}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 68, 253}, 6}, {{120, 0, 0, 0, 0, 48, 136, 139, 4, 17, 112, 100, 90, 38, 204, 125}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 81, 3, 210}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 20, 13, 192, 54, 39}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 20, 128, 21, 192, 1, 246, 223, 165}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 153, 203, 73, 216}, 6}, {{120, 0, 0, 0, 0, 0, 172, 110, 113, 62, 51, 140, 234, 249, 118, 234}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 8, 11, 18, 166, 70, 1, 18, 35}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{120, 0, 0, 0, 133, 9, 133, 251, 178, 27, 111, 27, 42, 45, 120, 48}, 6}, {{120, 0, 0, 0, 0, 0, 16, 15, 75, 180, 221, 144, 181, 183, 175, 111}, 6}, {{120, 0, 0, 100, 143, 245, 138, 252, 22, 46, 162, 61, 189, 224, 2, 182}, 6}, {{120, 0, 0, 0, 64, 14, 158, 180, 210, 157, 124, 226, 150, 161, 32, 99}, 6}, {{120, 0, 93, 3, 252, 28, 29, 155, 203, 227, 239, 166, 54, 88, 198, 39}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 214, 36, 225, 3, 166}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 6}, {{120, 0, 0, 0, 0, 0, 0, 202, 224, 151, 219, 79, 148, 12, 1, 166}, 6}, {{120, 0, 0, 0, 0, 0, 0, 152, 27, 133, 215, 204, 80, 24, 106, 115}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 52, 164, 213}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 6}, {{120, 96, 65, 167, 69, 25, 121, 42, 138, 98, 53, 80, 177, 122, 86, 169}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 6}, {{120, 0, 113, 32, 15, 161, 239, 81, 154, 31, 191, 95, 243, 162, 6, 230}, 6}, {{120, 0, 185, 122, 81, 249, 22, 197, 30, 75, 91, 129, 222, 19, 141, 248}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 141, 133, 49, 90, 35, 56, 62, 178}, 6}, {{120, 111, 179, 85, 248, 90, 124, 35, 153, 255, 179, 128, 151, 236, 47, 109}, 6}, {{120, 218, 7, 37, 233, 211, 106, 56, 188, 148, 96, 45, 208, 23, 160, 106}, 6}, {{120, 0, 0, 242, 90, 91, 40, 91, 81, 19, 245, 25, 236, 108, 6, 122}, 6}, {{120, 0, 0, 0, 0, 0, 81, 216, 176, 224, 183, 254, 124, 66, 24, 195}, 6}, {{120, 0, 0, 0, 192, 155, 25, 184, 252, 34, 119, 19, 174, 236, 246, 83}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 36, 93, 73, 59, 131, 243, 134}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 113, 65, 66, 100, 87, 157, 34, 181}, 6}, {{120, 0, 0, 0, 0, 57, 239, 92, 94, 11, 235, 48, 34, 66, 144, 70}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 35, 168, 31, 62, 195, 68, 77, 132}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 119, 112, 253, 194}, 6}, {{120, 0, 176, 223, 122, 77, 75, 192, 28, 196, 149, 51, 67, 58, 59, 252}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 168, 28, 252}, 6}, {{120, 199, 112, 6, 246, 77, 53, 237, 140, 180, 98, 134, 135, 143, 78, 49}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 211, 191, 108, 133, 176, 212, 173, 45}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 25}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 177, 248, 177, 179, 178}, 6}, {{120, 0, 0, 0, 0, 0, 0, 19, 157, 213, 255, 181, 57, 39, 138, 236}, 6}, {{120, 192, 63, 9, 6, 57, 227, 145, 107, 92, 198, 24, 13, 209, 30, 214}, 6}, {{120, 224, 214, 124, 65, 54, 4, 147, 81, 85, 214, 126, 44, 114, 7, 171}, 6}, {{120, 0, 0, 0, 0, 0, 0, 115, 187, 162, 180, 182, 148, 150, 204, 232}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 171, 202}, 6}, {{120, 0, 0, 0, 0, 0, 232, 191, 95, 197, 7, 215, 229, 26, 193, 231}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 113}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 171, 249, 246}, 6}, {{120, 0, 0, 0, 0, 0, 0, 11, 88, 106, 28, 227, 172, 222, 174, 156}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6}, {{120, 0, 0, 0, 0, 0, 0, 218, 158, 173, 65, 197, 248, 195, 199, 187}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 96, 194, 191, 140, 86}, 6}, {{120, 0, 0, 0, 0, 0, 90, 139, 154, 158, 173, 255, 81, 9, 179, 175}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 122, 196, 45, 249, 103, 23, 27, 154}, 6}, {{120, 0, 0, 0, 21, 231, 67, 100, 31, 105, 29, 153, 199, 160, 188, 103}, 6}, {{120, 0, 0, 227, 223, 208, 89, 52, 132, 145, 81, 29, 96, 75, 93, 199}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 255, 106, 79, 253, 199}, 6}, {{120, 0, 0, 0, 0, 0, 233, 178, 175, 120, 156, 230, 184, 78, 78, 176}, 6}, {{120, 0, 0, 0, 0, 0, 0, 0, 202, 5, 199, 60, 69, 11, 242, 151}, 6}, {{216, 0, 0, 0, 73, 191, 98, 134, 96, 202, 29, 96, 22, 86, 237, 192}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 25, 248}, 13}, {{216, 0, 0, 0, 60, 117, 224, 32, 104, 15, 65, 123, 181, 200, 230, 196}, 13}, {{216, 0, 0, 0, 0, 5, 222, 53, 94, 90, 178, 52, 36, 50, 88, 92}, 13}, {{216, 0, 0, 0, 0, 0, 125, 127, 69, 235, 188, 106, 125, 65, 113, 180}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 55, 162, 164}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 50}, 13}, {{216, 0, 0, 0, 49, 76, 241, 127, 57, 140, 155, 27, 92, 223, 126, 122}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 243}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 44, 76, 96}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 13}, {{216, 0, 0, 0, 0, 11, 179, 89, 96, 24, 238, 99, 72, 82, 86, 15}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 102, 250, 250, 219, 238, 209, 213, 229}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 238, 46, 168, 244, 59, 154, 79}, 13}, {{216, 0, 0, 0, 0, 0, 10, 11, 216, 229, 71, 236, 220, 238, 233, 65}, 13}, {{216, 0, 223, 232, 46, 195, 189, 179, 167, 9, 36, 110, 0, 1, 16, 173}, 13}, {{216, 0, 0, 0, 0, 0, 0, 151, 69, 26, 195, 46, 165, 15, 51, 174}, 13}, {{216, 0, 134, 52, 86, 235, 162, 169, 82, 0, 198, 92, 108, 28, 127, 248}, 13}, {{216, 0, 0, 209, 100, 98, 15, 195, 244, 216, 103, 135, 40, 221, 209, 131}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 8, 102, 127, 11}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 13}, {{216, 0, 0, 0, 0, 0, 0, 240, 103, 135, 57, 244, 39, 251, 129, 78}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 10, 27}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 98}, 13}, {{216, 0, 0, 0, 0, 0, 183, 166, 72, 103, 179, 199, 203, 112, 97, 159}, 13}, {{216, 0, 0, 154, 246, 193, 84, 219, 24, 109, 169, 149, 251, 222, 186, 133}, 13}, {{216, 0, 0, 0, 0, 221, 64, 158, 85, 150, 29, 249, 89, 222, 249, 209}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 94}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 221, 255, 141, 185, 19, 49, 167, 77, 31, 146}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 141}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 13}, {{216, 0, 0, 0, 209, 11, 1, 159, 159, 12, 202, 35, 158, 61, 160, 134}, 13}, {{216, 0, 81, 175, 124, 60, 216, 83, 244, 78, 37, 245, 85, 17, 140, 222}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 200, 51, 119, 124, 194, 255, 220, 24}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 128, 116, 130}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 170, 176, 121, 13, 213, 17, 182, 30, 134, 244}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 7, 200, 209, 235, 132}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 217, 227, 120, 39}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 170}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 70, 71, 187, 59, 235}, 13}, {{216, 0, 0, 0, 0, 78, 254, 194, 84, 251, 228, 134, 64, 179, 92, 98}, 13}, {{216, 0, 0, 0, 0, 0, 0, 152, 14, 250, 247, 169, 14, 121, 150, 106}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 174, 22, 62, 76}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 19, 206, 200, 213, 222, 12, 146, 99}, 13}, {{216, 0, 0, 0, 0, 249, 106, 135, 65, 81, 190, 227, 18, 133, 204, 4}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 201, 194, 213, 12}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 201, 222}, 13}, {{216, 0, 104, 180, 181, 227, 114, 137, 94, 220, 6, 216, 196, 216, 176, 166}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 69}, 13}, {{216, 0, 0, 0, 227, 226, 158, 96, 106, 135, 211, 10, 32, 21, 163, 40}, 13}, {{216, 0, 0, 0, 0, 0, 119, 222, 122, 186, 231, 195, 13, 76, 75, 138}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 94, 61, 235, 104, 205, 201, 93, 166}, 13}, {{216, 0, 0, 0, 198, 183, 145, 56, 61, 195, 252, 199, 63, 87, 102, 95}, 13}, {{216, 0, 0, 0, 0, 0, 90, 153, 222, 217, 255, 27, 120, 34, 79, 233}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 172, 253, 218}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 128, 5, 241}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 0, 251, 231, 70}, 13}, {{216, 0, 0, 0, 83, 27, 44, 56, 16, 101, 41, 34, 192, 152, 178, 237}, 13}, {{216, 0, 0, 0, 0, 0, 206, 31, 108, 182, 109, 128, 153, 99, 236, 184}, 13}, {{216, 0, 0, 0, 0, 13, 91, 199, 240, 99, 39, 24, 161, 71, 15, 93}, 13}, {{216, 0, 157, 94, 226, 165, 236, 110, 104, 119, 34, 76, 36, 47, 217, 48}, 13}, {{216, 0, 0, 0, 10, 242, 57, 13, 73, 25, 62, 33, 94, 241, 59, 127}, 13}, {{216, 0, 0, 0, 0, 0, 0, 221, 183, 34, 107, 106, 106, 41, 90, 24}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 145, 73}, 13}, {{216, 0, 0, 0, 0, 0, 166, 219, 112, 18, 160, 67, 12, 126, 38, 62}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 233, 231, 55, 193}, 13}, {{216, 0, 0, 0, 0, 158, 22, 234, 15, 28, 172, 15, 247, 188, 160, 45}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 189, 119, 162, 2, 250, 110, 152}, 13}, {{216, 0, 0, 0, 12, 52, 132, 14, 102, 243, 132, 214, 134, 61, 226, 58}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 160}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 165}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 209, 54}, 13}, {{216, 0, 0, 0, 0, 0, 74, 68, 216, 74, 129, 52, 47, 129, 153, 37}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 50, 87}, 13}, {{216, 40, 202, 97, 31, 148, 77, 90, 50, 219, 243, 153, 247, 221, 196, 46}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 0, 0, 182, 189, 66, 44, 67, 125, 193, 77, 180}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 37, 66, 172, 248, 198, 79, 230, 147, 66, 172, 43}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 68, 63, 173, 246, 206}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 158, 153, 106, 194, 66, 162, 169, 73}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 41, 89, 129, 163, 96, 219, 49, 133}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 131, 109, 244, 237, 181, 244, 14, 131}, 13}, {{216, 0, 0, 0, 20, 13, 187, 201, 123, 208, 234, 119, 193, 106, 160, 236}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 112, 233, 217, 67}, 13}, {{216, 0, 0, 0, 61, 156, 195, 9, 61, 186, 137, 165, 209, 178, 198, 251}, 13}, {{216, 0, 220, 88, 137, 68, 20, 16, 5, 37, 240, 99, 155, 217, 85, 104}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 37, 135, 73, 136, 212, 234, 180}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{216, 0, 0, 0, 0, 162, 252, 76, 52, 173, 201, 224, 84, 156, 165, 162}, 13}, {{216, 0, 0, 0, 0, 0, 0, 0, 0, 13, 32, 92, 197, 67, 166, 121}, 13}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 175, 151, 245, 177}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 62, 219, 119, 97, 152}, 41}, {{135, 215, 0, 71, 24, 153, 23, 125, 232, 179, 15, 219, 152, 85, 87, 212}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 253}, 41}, {{135, 215, 0, 71, 24, 0, 94, 51, 152, 1, 121, 14, 224, 42, 104, 251}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 12, 205, 140, 37, 251}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 247, 143, 157}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 242, 183, 166, 164, 161, 191, 240, 200}, 41}, {{135, 215, 0, 71, 24, 0, 108, 59, 52, 195, 116, 168, 6, 74, 133, 253}, 41}, {{135, 215, 0, 71, 24, 0, 0, 170, 223, 71, 129, 167, 90, 78, 16, 238}, 41}, {{135, 215, 0, 71, 24, 134, 94, 98, 68, 5, 165, 128, 22, 150, 136, 58}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 171, 135, 178, 104, 255, 16, 20}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 234, 200, 44, 162}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 16, 59, 133}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 41}, {{135, 215, 0, 71, 24, 0, 154, 244, 193, 101, 190, 159, 94, 148, 246, 142}, 41}, {{135, 215, 0, 71, 24, 0, 239, 214, 26, 80, 5, 242, 119, 95, 83, 234}, 41}, {{135, 215, 0, 71, 24, 0, 6, 145, 87, 168, 72, 3, 65, 63, 31, 18}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 98, 102, 202, 238, 99, 126, 186, 222}, 41}, {{135, 215, 0, 71, 24, 230, 120, 19, 162, 11, 194, 231, 234, 41, 3, 222}, 41}, {{135, 215, 0, 71, 24, 0, 0, 237, 53, 254, 22, 54, 46, 72, 76, 228}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 25}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 178, 141, 107}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 88, 185, 17, 25, 29}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 52, 204, 73, 172}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 248, 74, 230, 118, 28, 231}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 137, 128, 45, 223, 236, 119}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 175, 51, 225, 232, 80}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 44, 109, 80, 58, 174, 43, 249, 254}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 114, 235, 8, 101}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 158, 20, 176, 31, 252, 240, 175}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 42, 194, 61, 72}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 220, 94, 213, 106, 137, 117, 74, 156}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 57, 114, 131, 46}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 224, 169, 150, 86, 255, 41}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 132, 196, 141, 114, 195, 112, 138, 72}, 41}, {{135, 215, 0, 71, 24, 51, 75, 219, 141, 55, 155, 81, 211, 126, 162, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 254}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 229, 77, 202, 132, 70}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 41, 195, 79}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 63, 250, 241, 83}, 41}, {{135, 215, 0, 71, 24, 0, 0, 85, 57, 48, 235, 80, 83, 110, 20, 50}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 37, 196, 45, 15, 71, 154, 148}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 79, 100, 249}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 188, 20, 66, 31, 113, 5, 57, 238}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 248, 34, 120}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 94, 43, 116, 106, 33, 229, 175, 31, 216, 121}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 155, 240, 227, 203, 57, 246, 97, 123}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 246, 159, 207}, 41}, {{135, 215, 0, 71, 24, 5, 189, 112, 92, 218, 61, 192, 79, 206, 135, 221}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 182, 147, 149, 131, 79, 160}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 255}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 229, 127, 46, 152, 101, 50, 210}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 130, 217, 46}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 104, 35, 223, 225, 131, 245, 147}, 41}, {{135, 215, 0, 71, 24, 0, 156, 161, 93, 182, 64, 174, 103, 45, 177, 165}, 41}, {{135, 215, 0, 71, 24, 144, 124, 23, 13, 125, 38, 2, 43, 224, 116, 138}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 41}, {{135, 215, 0, 71, 24, 0, 122, 7, 200, 138, 229, 239, 169, 23, 232, 95}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 41}, {{135, 215, 0, 71, 24, 46, 220, 224, 238, 237, 248, 0, 119, 140, 139, 180}, 41}, {{135, 215, 0, 71, 24, 0, 225, 15, 36, 76, 121, 78, 123, 58, 87, 142}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 48, 8, 161, 74, 111}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 164, 158, 173, 135, 124, 222, 53, 237}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 154, 72, 199, 147, 218, 58, 211, 112}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 212, 231, 180}, 41}, {{135, 215, 0, 71, 24, 0, 49, 27, 91, 233, 217, 3, 15, 184, 172, 202}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 227, 20, 187, 161}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 11, 139, 80, 203, 110, 130, 162, 120, 135, 164}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 116, 92, 168}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 22, 49, 118, 1, 132, 189}, 41}, {{135, 215, 0, 71, 24, 0, 41, 178, 232, 72, 58, 48, 39, 9, 5, 199}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 83, 104, 204, 132}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 228, 217, 49, 113, 51, 239, 223}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 154, 79, 236, 108}, 41}, {{135, 215, 0, 71, 24, 0, 0, 115, 154, 97, 203, 231, 248, 231, 158, 31}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 204, 227, 240, 175, 204}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 88, 188, 127}, 41}, {{135, 215, 0, 71, 24, 231, 217, 57, 102, 146, 208, 237, 85, 165, 144, 99}, 41}, {{221, 149, 1, 40, 112, 0, 153, 248, 153, 114, 69, 87, 122, 218, 57, 202}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 99, 132, 243, 45, 80, 157}, 135}, {{221, 149, 1, 40, 112, 0, 0, 22, 169, 135, 93, 171, 223, 170, 32, 92}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 155, 235, 61, 193, 225}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 123, 16, 58, 109}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 113, 251, 192, 83, 27, 169, 246}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 5, 63, 181, 142}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 83, 108, 43, 168, 83, 113}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 5, 2, 17, 190, 106, 80}, 135}, {{221, 149, 1, 40, 112, 0, 0, 79, 79, 162, 20, 66, 188, 250, 117, 56}, 135}, {{221, 149, 1, 40, 112, 0, 0, 137, 164, 255, 17, 63, 103, 103, 122, 123}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 162, 246, 69, 108, 69}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 33, 46, 255, 33, 165}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 135}, {{221, 149, 1, 40, 112, 168, 148, 93, 114, 46, 163, 30, 73, 127, 105, 217}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 163, 158, 226, 145}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 66, 15, 73, 21, 29, 85, 188, 72, 252}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 196}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 136, 158, 185, 108, 96, 184, 41}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 249, 194, 29, 39, 218, 174}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 68, 107, 30, 28, 47, 104}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 177, 89, 195, 84, 102}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 96}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 209, 164, 25, 188}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 87, 229, 217}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 122, 75, 67, 3, 96, 50}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 20}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 134, 115, 190, 140, 34, 27, 153}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 249, 18, 44, 174}, 135}, {{221, 149, 1, 40, 112, 0, 0, 27, 200, 116, 135, 191, 24, 83, 15, 52}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 252, 78, 20, 159, 17, 70}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 117}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 82, 253, 182, 109, 195, 166}, 135}, {{221, 149, 1, 40, 112, 0, 210, 225, 8, 151, 100, 143, 2, 229, 158, 99}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 30, 51, 222, 170, 167, 207, 170, 118, 140, 60}, 135}, {{221, 149, 1, 40, 112, 0, 50, 100, 21, 63, 34, 149, 14, 121, 83, 93}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 73, 55, 76, 214}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 209, 102, 151, 153}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 113, 10, 51, 144, 38, 115, 96, 193, 101, 118}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 161, 99, 55, 19}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 214, 211, 222, 26, 183, 92}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 202, 122, 167, 23, 69}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 240, 83, 138, 249}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 134, 26, 236, 92, 78}, 135}, {{221, 149, 1, 40, 112, 0, 0, 58, 46, 51, 145, 245, 27, 6, 139, 89}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 25, 199, 34, 144, 210, 186}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 207, 238, 231, 209, 169, 53, 242, 229, 239}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 81, 16, 229, 33, 144, 10, 34}, 135}, {{221, 149, 1, 40, 112, 0, 0, 253, 91, 128, 61, 205, 209, 186, 177, 181}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 160}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 172, 170, 252, 150, 84, 178}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 95, 222, 230, 174, 204}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 135}, {{221, 149, 1, 40, 112, 0, 255, 89, 2, 44, 101, 137, 230, 179, 96, 144}, 135}, {{221, 149, 1, 40, 112, 0, 0, 165, 201, 118, 191, 29, 68, 91, 129, 55}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 47, 35, 90, 149}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 75, 47, 78}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 226, 155, 107, 191, 10, 21}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 50, 33, 200, 222, 80}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 11, 195, 160, 234, 103, 173}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 157, 159, 175, 91, 16, 92}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 177, 124, 169, 236}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 220, 197, 77}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 191, 249, 226, 117, 46, 142}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 59, 24, 140, 170, 196}, 135}, {{221, 149, 1, 40, 112, 0, 160, 38, 46, 140, 0, 186, 15, 53, 13, 83}, 135}, {{221, 149, 1, 40, 112, 0, 0, 243, 103, 213, 108, 2, 53, 185, 227, 153}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 6, 101, 31, 227, 97, 164}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 11, 74, 178, 119}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 39, 53, 102, 156, 32, 155, 61}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 48, 58, 9, 52, 147, 133, 85, 94}, 135}, {{221, 149, 1, 40, 112, 0, 0, 113, 51, 172, 198, 250, 38, 203, 80, 195}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 106, 54, 16, 212, 7, 11, 215, 244}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 45, 157, 66, 25, 61, 176, 66}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 183}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 77, 20, 109, 75, 219}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 125, 215, 141, 41, 57, 192, 218}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 200, 202, 137, 223, 245}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 232, 251, 237, 159}, 135}, {{221, 149, 1, 40, 112, 77, 199, 161, 4, 94, 231, 159, 216, 111, 44, 82}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 253, 148, 148, 83, 238, 194, 134}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 62, 230, 151, 113, 47, 130, 76, 155}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 204, 128, 189, 164, 38}, 135}, {{221, 149, 1, 40, 112, 0, 6, 195, 213, 75, 199, 115, 66, 254, 163, 255}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 75, 165, 199, 192, 91}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 27}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 143, 32, 120, 102, 150, 206, 24, 27}, 135}, {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 135}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 206, 21}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 240, 14}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 150, 240}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 31}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 246}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 97, 107, 98, 133}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 255}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 249}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 31}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 193, 107, 122}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 206, 107}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 17, 165, 218}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 46}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 182}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 183, 192, 1}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 134, 199, 11, 98}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 15, 214}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 134, 142}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 43}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 74, 78, 93}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 230, 148, 251}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 42}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 54}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 35}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 73}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 233, 216, 24}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 109}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 163}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 194, 114}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 163}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 127}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 176, 4}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 52, 92, 103}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 14}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 134}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 145, 22}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 200, 97, 244}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 217, 212}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 177, 143}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 119, 184, 139}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 244, 9}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 78, 60, 108}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 10, 187, 21}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 31, 148}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 12, 31}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 49, 168}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 183, 216}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 193}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 141}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 102, 114, 29, 91}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 224, 53}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 62}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 212, 76}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 76}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 167, 137, 213}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 90, 20, 137}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 72, 57}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 124, 179, 168}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 133, 172, 23}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 30, 243}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 164}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 106}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 216, 17, 30}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 184, 45, 33}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 156, 31, 51}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 175, 207}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 143, 234}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 203, 183, 244}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 167}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 149, 160}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 142, 139}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 204, 240, 21}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 64, 203}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 224}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 173}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 122, 156, 25, 94}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 82, 146, 117, 138}, 171}, {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 171}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 193}, 20}, {{202, 212, 96, 0, 0, 0, 0, 184, 56, 30, 43, 107, 5, 203, 118, 254}, 20}, {{202, 212, 96, 0, 0, 0, 0, 129, 45, 227, 48, 70, 138, 211, 229, 228}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 83, 64, 226, 26, 68, 191}, 20}, {{202, 212, 96, 127, 196, 154, 160, 103, 155, 5, 123, 207, 12, 96, 174, 52}, 20}, {{202, 212, 96, 0, 0, 88, 122, 165, 225, 149, 64, 135, 10, 20, 121, 146}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 158, 178, 139, 23, 240}, 20}, {{202, 212, 96, 0, 3, 60, 232, 9, 6, 79, 248, 249, 97, 143, 84, 111}, 20}, {{202, 212, 96, 0, 0, 0, 0, 27, 219, 185, 243, 88, 60, 212, 39, 108}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 131, 166, 111}, 20}, {{202, 212, 96, 0, 0, 0, 50, 131, 59, 179, 139, 96, 69, 238, 99, 122}, 20}, {{202, 212, 96, 0, 248, 38, 246, 79, 84, 30, 31, 79, 179, 192, 251, 99}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 185}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 77}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 35}, 20}, {{202, 212, 96, 0, 0, 0, 27, 65, 62, 70, 247, 212, 15, 174, 134, 68}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 91, 75, 240, 176, 225}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 0, 185, 27, 90, 179, 211, 74, 95, 55, 129, 88, 54}, 20}, {{202, 212, 96, 0, 0, 0, 0, 43, 209, 50, 195, 235, 76, 238, 198, 180}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 210, 74, 51, 69, 218, 93}, 20}, {{202, 212, 96, 0, 0, 0, 0, 18, 248, 107, 207, 61, 233, 4, 20, 179}, 20}, {{202, 212, 96, 0, 0, 0, 74, 159, 65, 107, 74, 144, 225, 204, 62, 219}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 217, 52, 232, 194, 98, 11, 232}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 35, 250}, 20}, {{202, 212, 96, 0, 0, 0, 96, 218, 78, 192, 167, 180, 106, 31, 69, 231}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 101, 46, 210, 119, 60, 26, 73, 43}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 169, 10, 164, 17, 217}, 20}, {{202, 212, 96, 0, 0, 0, 81, 103, 117, 181, 25, 222, 236, 94, 6, 255}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 36, 0, 43, 107, 172, 231, 186, 208}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 235, 95, 77}, 20}, {{202, 212, 96, 29, 155, 242, 162, 252, 232, 83, 38, 33, 174, 184, 254, 173}, 20}, {{202, 212, 96, 0, 0, 28, 244, 154, 251, 209, 37, 210, 85, 207, 87, 239}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 5, 85, 219}, 20}, {{202, 212, 96, 0, 0, 0, 0, 205, 16, 18, 93, 223, 169, 188, 111, 194}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 202, 49, 177, 39, 234, 228}, 20}, {{202, 212, 96, 187, 221, 158, 253, 110, 255, 165, 43, 138, 48, 146, 153, 141}, 20}, {{202, 212, 96, 0, 174, 203, 132, 224, 150, 225, 98, 215, 200, 1, 73, 17}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 38, 135, 202, 27, 165}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 26, 227, 52, 248, 81}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 231, 36}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 146}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 250, 114, 86}, 20}, {{202, 212, 96, 0, 0, 227, 106, 205, 80, 189, 175, 50, 104, 245, 85, 254}, 20}, {{202, 212, 96, 0, 6, 198, 155, 202, 181, 152, 0, 94, 85, 188, 26, 82}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 234, 55, 211, 252, 135, 6, 245, 186}, 20}, {{202, 212, 96, 0, 20, 157, 73, 59, 82, 94, 207, 156, 188, 254, 92, 254}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 120, 56, 191, 244, 125, 33, 230}, 20}, {{202, 212, 96, 0, 0, 0, 0, 203, 206, 151, 38, 2, 164, 177, 138, 219}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 127, 30, 95, 138, 126, 176, 64}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 166, 86}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 234, 38, 44, 215, 184, 28, 253, 1}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 221}, 20}, {{202, 212, 96, 0, 0, 0, 0, 176, 227, 159, 6, 188, 182, 191, 159, 250}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 60, 29, 44, 11, 250, 220, 115}, 20}, {{202, 212, 96, 83, 224, 110, 111, 245, 160, 80, 21, 169, 155, 246, 90, 10}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 22, 135}, 20}, {{202, 212, 96, 0, 0, 0, 19, 20, 62, 195, 115, 76, 29, 35, 166, 43}, 20}, {{202, 212, 96, 40, 27, 248, 37, 93, 246, 3, 160, 212, 67, 215, 212, 225}, 20}, {{202, 212, 96, 0, 0, 134, 34, 103, 9, 84, 201, 212, 86, 0, 167, 217}, 20}, {{202, 212, 96, 0, 0, 0, 100, 224, 83, 228, 226, 168, 97, 95, 67, 96}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 27, 123, 186, 190, 80, 196}, 20}, {{202, 212, 96, 0, 0, 0, 202, 240, 177, 23, 100, 8, 141, 187, 222, 36}, 20}, {{202, 212, 96, 0, 0, 225, 68, 2, 90, 71, 52, 48, 30, 213, 23, 9}, 20}, {{202, 212, 96, 0, 45, 48, 121, 209, 118, 183, 36, 114, 108, 23, 254, 93}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 253, 117}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 201, 108, 47, 141, 33, 221, 93, 98, 22, 29, 20, 120}, 20}, {{202, 212, 96, 0, 0, 0, 0, 211, 14, 228, 234, 90, 43, 146, 196, 193}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 85}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 39}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 41, 32}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 247, 131, 219, 48, 54, 216, 248}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 4, 151, 3, 108, 88, 110, 58}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 100, 120}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 20}, {{202, 212, 96, 0, 0, 25, 129, 167, 94, 67, 125, 160, 103, 7, 229, 231}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 171, 204, 146, 22, 31, 240, 151, 71}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 87, 100, 25}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 180, 129, 217, 61, 144, 202}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 132, 78}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 190, 144, 149, 29, 154, 147}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 90}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 97, 26, 105, 160, 216}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 112}, 20}, {{202, 212, 96, 0, 228, 222, 228, 77, 86, 26, 246, 152, 201, 245, 82, 195}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 20}, {{202, 212, 96, 0, 11, 255, 91, 176, 15, 56, 47, 177, 122, 254, 141, 9}, 20}, {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 130, 201, 189, 75, 181}, 20}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 226, 249, 186}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 46, 151}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 217, 244, 3}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 26, 124, 164, 243}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 106, 85, 49, 145}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 69, 116, 249}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 211, 234, 172, 165}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 3, 57}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 112, 124, 184}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 42}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 34, 226}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 96, 74, 180, 98}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 12, 111}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 9}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 56, 149}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 158, 123, 78, 106}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 221, 205, 190, 179}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 153, 35, 15}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 210, 58}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 98}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 34, 144, 49}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 160, 250, 51, 201}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 169}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 31, 215, 232, 21}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 93, 74, 30, 222}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 159, 55, 171, 138}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 71}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 191, 191, 146}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 114, 179, 194}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 62, 45, 85, 213}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 193, 129}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 198, 165}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 147, 189}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 232, 139, 6}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 131, 106, 139}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 65, 190}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 121, 149, 19}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 127}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 114, 16, 155}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 255, 63, 120, 136}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 9}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 86}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 108, 43}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 16, 63}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 142, 188, 255}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 195, 232, 212}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 211, 68, 63}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 231, 12, 181}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 5, 184}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 139, 234}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 106, 232}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 84, 2}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 117, 10, 196, 1}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 124, 201, 78, 58}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 150}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 143}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 104, 138}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 42, 234}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 102}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 100, 104, 195}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 122, 119, 35, 187}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 254}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 119, 120, 239}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 252, 41}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 170}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 6}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 16, 19, 76}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 215, 8, 77}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 203, 218}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 132, 183, 6, 77}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 134, 11}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 86, 95, 29, 45}, 119}, {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 13}, 119}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 61}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 60}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 194}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 230}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 56}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 88}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 14}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 16}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 16}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 78}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 252}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 219}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 122}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 31}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 6}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 22}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 143}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 69}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 122}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 4}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 222}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 20}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 32}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 93}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 200}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 120}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 251}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 90}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 34}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 220}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 143}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 163}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 57}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 59}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 237}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 248}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 20}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 191}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 41}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 68}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 153}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 173}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 84}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 194}, 49}, {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 49}, {{224, 0, 0, 29, 241, 150, 36, 254, 175, 131, 74, 77, 95, 128, 13, 116}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 41, 29}, 141}, {{224, 0, 195, 245, 162, 22, 234, 249, 66, 236, 130, 45, 103, 154, 21, 168}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 140, 22, 7}, 141}, {{224, 0, 0, 0, 0, 0, 0, 65, 51, 215, 61, 119, 14, 88, 92, 195}, 141}, {{224, 0, 0, 129, 134, 243, 107, 84, 69, 95, 72, 206, 41, 42, 83, 229}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 141}, {{224, 0, 0, 0, 0, 0, 62, 193, 174, 158, 45, 113, 147, 78, 82, 224}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 215, 77, 37, 235, 171, 165, 38, 131, 183, 207, 2}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 204, 162}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 252, 116}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 17, 225, 93}, 141}, {{224, 0, 0, 69, 133, 82, 85, 60, 200, 154, 78, 231, 87, 44, 65, 232}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 181, 23, 109, 143, 13, 191, 31, 172}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 111, 230, 136}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 141}, {{224, 0, 0, 212, 43, 219, 102, 109, 117, 59, 18, 142, 125, 48, 117, 184}, 141}, {{224, 0, 40, 192, 186, 59, 156, 201, 153, 225, 235, 55, 214, 243, 22, 51}, 141}, {{224, 0, 58, 184, 133, 36, 199, 192, 79, 64, 238, 79, 210, 1, 93, 116}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 141}, {{224, 0, 0, 0, 0, 0, 0, 114, 65, 168, 67, 202, 15, 64, 142, 19}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 179, 8, 67, 149, 113}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 22, 141, 215}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 110, 30, 90}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 225}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 156, 70, 228}, 141}, {{224, 0, 0, 0, 8, 48, 24, 172, 81, 225, 129, 132, 120, 237, 234, 135}, 141}, {{224, 0, 0, 18, 35, 13, 64, 248, 129, 166, 61, 120, 138, 29, 7, 16}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 223, 131, 231, 0, 158, 178, 125}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 186, 13, 153, 7, 48, 99, 69, 84}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 252, 132, 84}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 226, 58, 193, 105, 174}, 141}, {{224, 0, 0, 0, 81, 97, 177, 125, 206, 104, 228, 208, 255, 230, 43, 209}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 141}, {{224, 0, 0, 46, 106, 1, 134, 31, 88, 126, 143, 182, 211, 219, 62, 122}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 186}, 141}, {{224, 0, 0, 0, 0, 0, 0, 191, 138, 79, 172, 81, 62, 61, 8, 81}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 43, 68}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 70, 64, 150, 252}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 232, 179, 235}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 141, 190, 49, 30, 217, 133, 101}, 141}, {{224, 0, 0, 0, 0, 217, 114, 205, 127, 127, 224, 250, 2, 123, 84, 14}, 141}, {{224, 0, 0, 0, 0, 0, 150, 13, 62, 158, 174, 216, 183, 146, 210, 157}, 141}, {{224, 0, 0, 0, 0, 0, 0, 160, 10, 178, 215, 157, 210, 150, 187, 158}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 237, 139, 126, 197, 73, 121, 55, 136}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 118}, 141}, {{224, 0, 0, 129, 211, 67, 173, 130, 166, 40, 243, 46, 25, 189, 84, 85}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 91, 170, 201, 18, 24, 126, 13}, 141}, {{224, 0, 0, 156, 182, 237, 131, 97, 247, 52, 12, 173, 204, 38, 86, 180}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 63}, 141}, {{224, 0, 0, 0, 0, 0, 29, 243, 128, 1, 69, 135, 200, 31, 240, 4}, 141}, {{224, 0, 0, 0, 0, 103, 141, 173, 228, 146, 215, 237, 98, 17, 186, 209}, 141}, {{224, 0, 0, 0, 0, 0, 0, 205, 135, 218, 179, 74, 213, 159, 207, 204}, 141}, {{224, 0, 0, 218, 149, 111, 221, 79, 166, 217, 107, 165, 237, 229, 124, 171}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 97, 77}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 146, 61}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 114, 45}, 141}, {{224, 0, 0, 0, 0, 0, 0, 59, 66, 76, 150, 29, 64, 137, 61, 90}, 141}, {{224, 0, 0, 0, 0, 0, 31, 95, 61, 129, 68, 230, 72, 0, 91, 206}, 141}, {{224, 0, 0, 0, 0, 99, 37, 194, 9, 238, 152, 83, 188, 130, 181, 101}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 152, 12, 82, 196}, 141}, {{224, 0, 0, 0, 0, 105, 56, 190, 140, 77, 41, 58, 85, 102, 206, 218}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 175, 73}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 93, 207, 17, 59, 14}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 61, 77, 69, 10, 60, 143, 228}, 141}, {{224, 0, 0, 0, 0, 0, 171, 80, 72, 199, 57, 98, 23, 210, 6, 236}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 45, 102, 173, 35}, 141}, {{224, 0, 0, 0, 0, 253, 25, 33, 30, 176, 91, 100, 25, 180, 209, 212}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 234, 30, 188, 115, 205, 204, 170, 90, 127, 103, 20}, 141}, {{224, 0, 0, 0, 0, 112, 119, 230, 52, 202, 25, 144, 232, 106, 137, 248}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 186, 220, 54, 200}, 141}, {{224, 0, 0, 0, 0, 227, 10, 44, 206, 84, 220, 81, 50, 185, 127, 238}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 156}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 232, 226, 207}, 141}, {{224, 0, 0, 0, 170, 141, 252, 238, 10, 50, 94, 134, 242, 41, 205, 157}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 137, 94}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 56, 163, 80}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 180, 236, 162, 37}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 152, 162}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 158}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 163, 234, 147, 173, 111, 66, 160, 107}, 141}, {{224, 189, 104, 160, 178, 241, 25, 30, 59, 146, 31, 22, 225, 190, 3, 215}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 220, 41, 40, 95, 119, 240, 243}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 36, 103, 90, 35, 91}, 141}, {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 108, 209}, 141}, {{224, 0, 0, 0, 237, 0, 251, 205, 125, 10, 74, 107, 251, 132, 198, 219}, 141}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 249, 107, 8, 48, 37, 196}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 252, 206, 3, 57, 166, 107}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 134, 85, 67, 153}, 132}, {{250, 90, 241, 174, 163, 72, 0, 164, 189, 160, 226, 54, 86, 193, 100, 58}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 73, 90, 195, 76}, 132}, {{250, 90, 241, 174, 163, 72, 0, 161, 203, 241, 236, 36, 219, 207, 51, 14}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 189, 59, 26, 146, 139}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 122, 23, 148, 194, 124, 153, 134}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 162, 73, 164, 224}, 132}, {{250, 90, 241, 174, 163, 72, 38, 251, 63, 82, 63, 116, 238, 179, 3, 182}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 242, 3, 137, 67}, 132}, {{250, 90, 241, 174, 163, 72, 0, 34, 180, 198, 21, 182, 151, 20, 210, 87}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 29, 86, 111, 173, 66, 154, 212}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 103, 207, 142, 34}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 189, 201, 13, 115, 128, 56, 128, 182}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 203, 229, 131, 239, 50, 92, 200}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 135, 189}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 116, 64, 48, 168, 45, 202}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 24, 223, 174, 154, 109, 42}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 32, 154, 151}, 132}, {{250, 90, 241, 174, 163, 72, 130, 93, 208, 175, 146, 148, 119, 181, 230, 26}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 253, 193, 26, 91, 206, 85}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 117, 193, 176, 121, 27}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 37, 96, 113, 9}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 58, 216, 97, 132, 0, 224}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 49, 73, 70, 72, 1}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 68, 170, 188, 175, 203}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 201, 238}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 228, 226, 200, 112}, 132}, {{250, 90, 241, 174, 163, 72, 0, 122, 49, 251, 163, 5, 68, 40, 195, 250}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 24, 98, 241, 48, 111}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 110, 242, 67, 57, 121, 194, 19}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 12, 247, 233, 128, 199}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 44, 150, 39, 195, 94, 28, 65, 200}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 200, 71, 4}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 116, 173, 9, 181, 57, 176, 169, 15}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 14, 184, 194, 32}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 237, 33, 13, 37}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 205, 41, 95, 161, 219}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 205, 176, 106, 11, 91, 132, 25, 61}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 234, 239, 32, 16, 47, 182}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 240, 125, 246, 97, 47, 138}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 12, 87, 151, 228, 27, 127, 247}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 84, 27, 203, 250, 10, 0, 160, 60}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 68, 201, 113, 1, 185, 31, 64, 19, 4}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 151, 84}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 146, 186, 251}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 220, 218, 10, 201, 43}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 245, 142, 142, 185, 58, 215, 48, 114}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 229, 238, 254, 71, 213, 237, 85}, 132}, {{250, 90, 241, 174, 163, 72, 0, 75, 18, 206, 174, 245, 178, 36, 223, 3}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 186, 103, 111}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 171, 73, 87, 60, 244, 44, 109, 219, 10}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 239, 210, 6, 184, 229, 233, 61, 211, 108}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 201, 100, 51, 21, 90, 138, 79}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 80, 202, 159, 75, 76, 34, 230}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 33, 185, 195, 244, 2, 214, 87, 56}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 129, 66, 24, 204}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 198, 239, 8}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 18, 224, 153, 69, 83, 73}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 105, 83, 22}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 120, 209, 75, 4, 214, 118, 151}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 10, 2, 181, 147, 56}, 132}, {{250, 90, 241, 174, 163, 72, 0, 124, 148, 176, 21, 42, 230, 82, 221, 215}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 192, 156}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 215, 49, 32, 113, 126, 134, 148, 246}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 71, 176, 116, 169, 80}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 215, 32}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 74, 181, 141, 114, 92}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 124, 179, 141}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 143, 130, 220}, 132}, {{250, 90, 241, 174, 163, 72, 0, 24, 113, 103, 19, 247, 155, 148, 178, 100}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 61, 0, 152}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 106, 205, 220, 94, 141, 190}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 166, 233, 97, 161, 232}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 46, 117}, 132}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 27, 16}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 48}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 2}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 191}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 176, 188}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 21, 140}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 139}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 131, 207}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 72}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 151}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 116, 2}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 3}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 240, 86}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 44, 160}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 169, 50}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 4, 237}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 235, 30}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 67}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 53}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 61}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 104}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 83}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 167}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 252}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 50, 163}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 148}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 181, 154}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 159}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 62}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 40, 85}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 37, 141}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 74}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 43, 184}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 18}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 94, 201}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 62}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 27, 104}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 240}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 110, 208}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 123}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 89, 11}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 168}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 169, 36}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 74, 193}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 32, 139}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 150, 238}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 38, 238}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 201}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 198, 111}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 131}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 248}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 34, 150}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 46}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 27, 92}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 164, 210}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 21, 104}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 255}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 95, 151}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 110}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 218, 15}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 77, 99}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 229}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 214, 126}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 4}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 72}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 128}, 176}, {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 105, 165}, 176}, {{76, 64, 0, 0, 0, 0, 0, 0, 97, 175, 244, 244, 44, 194, 129, 116}, 186}, {{76, 64, 0, 0, 0, 112, 18, 158, 14, 64, 64, 193, 42, 252, 5, 143}, 186}, {{76, 64, 0, 0, 0, 27, 118, 98, 43, 18, 121, 10, 190, 224, 85, 85}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 29, 11, 156}, 186}, {{76, 64, 242, 156, 105, 227, 81, 55, 246, 165, 197, 250, 177, 212, 37, 43}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 118, 12, 227, 178}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 129, 186, 77, 166, 252, 22, 114}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 240, 209, 114, 26}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 53, 60, 88, 146}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 70}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 114, 118, 154}, 186}, {{76, 64, 0, 84, 229, 99, 87, 78, 229, 15, 198, 181, 105, 183, 0, 220}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 74, 28, 135, 127, 178, 8}, 186}, {{76, 64, 0, 0, 0, 0, 176, 197, 64, 111, 91, 144, 9, 23, 237, 27}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 193, 214, 12, 158, 80, 129}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 244, 22, 77, 39, 54, 94, 82}, 186}, {{76, 64, 0, 0, 0, 0, 122, 241, 106, 218, 33, 146, 117, 75, 42, 226}, 186}, {{76, 64, 0, 0, 0, 0, 201, 53, 60, 200, 187, 120, 138, 20, 130, 74}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 25, 178, 111, 97}, 186}, {{76, 64, 123, 138, 225, 215, 85, 190, 155, 156, 42, 51, 142, 58, 149, 186}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 0, 200, 90, 46, 139, 215, 88, 56, 69, 99, 197, 95, 234}, 186}, {{76, 64, 0, 0, 0, 0, 0, 80, 21, 102, 25, 236, 242, 205, 180, 31}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 34, 117, 210, 129, 213, 137, 51, 30}, 186}, {{76, 64, 0, 0, 0, 0, 120, 98, 34, 151, 35, 64, 202, 162, 220, 230}, 186}, {{76, 64, 0, 0, 249, 150, 73, 54, 54, 249, 114, 190, 67, 163, 132, 59}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 161, 11, 243, 177, 51, 141}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 199, 201, 39, 91, 114, 19, 236}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 186}, {{76, 64, 0, 0, 247, 197, 42, 177, 200, 26, 62, 117, 160, 42, 178, 193}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 209, 78, 70, 85, 20, 87, 26}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 56, 74, 223, 118, 233, 198}, 186}, {{76, 64, 0, 0, 0, 0, 0, 205, 125, 207, 85, 243, 82, 163, 215, 32}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 80, 194}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 63, 25, 254, 232}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 79, 155, 149, 90, 233, 17, 32}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 134, 204, 142, 227, 220, 238}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 186}, {{76, 64, 0, 0, 0, 0, 245, 248, 203, 66, 43, 210, 60, 126, 252, 227}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 0, 239, 156, 118, 186, 118, 198, 44, 141, 77, 214, 186, 87}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 213}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 175, 85, 244, 241}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 34, 39, 178, 62, 150, 163, 12, 197, 56, 16, 128, 165, 161}, 186}, {{76, 64, 0, 0, 0, 0, 0, 166, 88, 61, 143, 161, 203, 206, 233, 216}, 186}, {{76, 64, 0, 0, 0, 0, 0, 243, 12, 177, 55, 8, 172, 63, 218, 185}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 42, 7}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 0, 0, 0, 243, 23, 161, 143, 111, 107, 10, 39, 45, 123}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 15, 180, 157, 234, 173, 169}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 105, 215, 116, 188, 171, 75, 82}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 216, 255, 74, 46, 135, 9}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 186}, {{76, 64, 0, 0, 0, 0, 78, 100, 138, 99, 196, 21, 203, 179, 47, 137}, 186}, {{76, 64, 0, 0, 0, 0, 210, 148, 93, 130, 56, 159, 47, 147, 151, 53}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 207, 33, 112}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 208, 194, 248, 109, 240, 39, 188}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 195, 125, 177, 33, 174, 178}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 179, 16, 163}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 36, 161, 33}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 145, 138, 37, 76, 121, 181}, 186}, {{76, 64, 0, 27, 43, 188, 250, 176, 0, 21, 9, 208, 123, 122, 66, 91}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 63}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 94, 9, 107, 102}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 253, 209, 255, 71}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 186}, {{76, 64, 0, 0, 0, 0, 250, 170, 88, 38, 135, 150, 231, 144, 231, 50}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 41, 128, 132}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 11, 18, 232}, 186}, {{76, 64, 0, 243, 82, 88, 172, 120, 223, 70, 64, 25, 59, 17, 137, 30}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 189, 231, 130, 232}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 57, 225, 223}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 122, 128}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 171, 84, 58, 33, 153, 148}, 186}, {{76, 64, 0, 0, 0, 0, 133, 132, 161, 183, 159, 251, 114, 237, 242, 37}, 186}, {{76, 64, 0, 7, 250, 25, 228, 155, 242, 55, 66, 107, 14, 83, 44, 34}, 186}, {{76, 64, 0, 0, 241, 135, 245, 232, 189, 40, 81, 110, 53, 116, 5, 77}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 105, 244}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 186}, {{76, 64, 0, 0, 0, 0, 67, 64, 172, 52, 208, 100, 4, 135, 61, 165}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 56, 243, 167, 142, 213, 131}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 69, 222}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 0, 0, 0, 0, 102, 255, 233, 113, 86, 90, 250, 121, 19, 67}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 115, 28, 21}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 141}, 186}, {{76, 64, 0, 0, 0, 0, 0, 112, 195, 96, 213, 7, 188, 115, 131, 210}, 186}, {{76, 64, 0, 0, 0, 0, 0, 73, 245, 254, 18, 101, 207, 239, 35, 63}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 91, 174, 36, 211, 18, 119}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186}, {{76, 64, 222, 245, 184, 68, 235, 215, 112, 213, 238, 140, 102, 59, 251, 7}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 146, 30, 217, 196, 173, 230}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64, 144, 227, 150, 215, 241}, 186}, {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 186}, {{76, 64, 0, 0, 0, 0, 119, 150, 173, 173, 93, 52, 105, 64, 130, 217}, 186}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 123, 243, 45, 187, 248, 232, 43}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 223, 234, 61, 127, 20}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 203, 250, 215, 194}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 229}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 9, 24, 119, 134}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 96, 47, 156, 141}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 29, 77, 149, 129, 99, 159, 223}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 63, 163, 20, 139, 181, 4}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 19, 206, 114}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 124, 62, 139, 249}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 202}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 192, 204, 65, 50, 132, 215}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 100, 206, 227, 166, 70}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 16, 135, 167, 72}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 188, 65, 116}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 88, 124, 251, 5}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 122, 247, 96, 87, 211, 24}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 87, 159, 58, 163}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 35, 25, 139, 242, 255, 254}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 7, 93, 124, 86, 92, 189}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 125}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 110, 160, 108, 207, 75, 133}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 221, 17, 47, 40, 157, 74}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 170, 124, 7, 227, 194}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 211, 57, 233, 179}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 132, 235}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 212, 73, 162}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 31, 246, 171, 234, 96}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 94, 182, 44}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 28, 117, 83, 132, 186}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 103, 140, 6, 235, 250, 165, 57}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 60, 153}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 165, 59, 129, 137}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 215, 102, 92, 137, 57, 124}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 96, 89, 202, 88, 93}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 82}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 72}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 176, 56}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 176}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 136, 17, 221, 21, 179, 107, 161}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 167, 226, 233, 228, 95}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 182, 49, 217, 111}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 181, 154}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 186, 251}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 240, 146, 208, 65}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 51, 4, 212, 203}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 77, 216, 153, 169, 15, 224}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 109, 10, 68, 168, 166, 59, 131}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 217, 220, 70, 158, 19}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 22, 170, 123, 10, 117}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 27, 148, 17, 24, 128}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 93}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 12, 236, 102}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 177, 44, 34, 182, 149, 252}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 157, 218, 81, 81, 142}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 140, 134, 154, 51, 1}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 49, 155, 5}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 199, 147, 251}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 230, 108}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 5, 200, 62, 18, 115}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 181, 20}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 127, 115, 126, 153, 145, 87, 10}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 176, 128, 20, 169, 54, 44, 65}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 117, 57, 156, 135, 3, 75, 91}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 109, 142}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 160, 189, 160, 74}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 112, 56, 231, 109, 167}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 111, 235, 33, 183, 241, 191}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 75, 65, 28, 103, 150, 44}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 54, 94, 100}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 220, 117, 101, 151, 31, 6}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 170}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 11}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 116, 254, 16, 71, 151, 110, 31}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 178, 136, 37, 216, 131, 165}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 152, 226, 29}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 174}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 27, 235, 10, 233}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 161}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 39}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 185, 168}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 115, 167, 121, 223}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 195, 57, 219, 175, 188}, 93}, {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 178, 34, 24, 244, 35, 69}, 93}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 235}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 118}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 232}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 63}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 213}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 17}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 134}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 246}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 166, 113}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 251}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 253}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 29}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 84}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 237}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 187}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 89}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 134}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 203}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 180}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 78}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 7, 178}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 44}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 168}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 152}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 239}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 250}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 197}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 225}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 132}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 53}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 101}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 112}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 120}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 245}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 12, 192}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 142}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 201}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 55}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 180}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 158}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 31}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 116, 56}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 186}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 1}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 91}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 225}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 251}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 166}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 222}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 40, 60}, 242}, {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 242}, {{255, 133, 181, 0, 0, 0, 0, 52, 9, 193, 33, 163, 116, 190, 26, 24}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 252, 202, 174, 37, 69, 225, 247, 126}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 175, 98, 13}, 163}, {{255, 133, 181, 0, 0, 0, 0, 243, 32, 40, 210, 153, 103, 19, 159, 189}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 153, 81, 234, 100, 205, 244}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 10}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 17, 148, 162}, 163}, {{255, 133, 181, 0, 0, 0, 80, 182, 21, 113, 228, 251, 21, 103, 30, 242}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 155, 88, 136, 246, 5, 175, 202}, 163}, {{255, 133, 181, 0, 0, 0, 0, 191, 234, 31, 57, 114, 186, 152, 136, 92}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 92, 178, 121}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 39, 37, 124, 149, 14}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 96}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 80, 235, 221}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 223, 237, 56, 21, 71, 25, 108, 100}, 163}, {{255, 133, 181, 0, 0, 0, 0, 209, 98, 133, 93, 177, 251, 11, 122, 225}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 118, 223, 47, 209, 119}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 21, 205, 46, 3, 75, 250}, 163}, {{255, 133, 181, 0, 0, 88, 238, 159, 127, 131, 118, 171, 30, 21, 208, 226}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 210, 246, 26, 77, 117, 125, 33, 76}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 183, 88, 104, 126, 54, 228, 242}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 176, 249, 214, 191, 240, 238, 147, 20}, 163}, {{255, 133, 181, 0, 172, 143, 56, 134, 206, 156, 96, 217, 241, 128, 26, 217}, 163}, {{255, 133, 181, 0, 0, 121, 179, 190, 197, 149, 238, 135, 93, 141, 29, 195}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 73, 108, 62}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 150, 41, 250, 55, 159, 211}, 163}, {{255, 133, 181, 0, 0, 0, 156, 189, 219, 107, 216, 90, 209, 131, 86, 109}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 105, 139, 153, 156, 4, 80}, 163}, {{255, 133, 181, 0, 0, 0, 194, 84, 112, 185, 38, 233, 232, 239, 183, 205}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 235, 27, 208, 46, 31, 174, 156}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 66, 158}, 163}, {{255, 133, 181, 0, 0, 0, 0, 123, 161, 226, 50, 184, 195, 242, 218, 197}, 163}, {{255, 133, 181, 0, 12, 167, 253, 239, 107, 5, 3, 166, 85, 7, 62, 36}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 131}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 220, 178, 154, 191, 112}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 111, 111, 58, 252, 38}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 227, 150}, 163}, {{255, 133, 181, 0, 30, 74, 77, 132, 72, 75, 225, 77, 207, 172, 67, 221}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 10, 118, 144, 236, 41}, 163}, {{255, 133, 181, 0, 0, 209, 98, 35, 207, 25, 121, 106, 255, 98, 142, 47}, 163}, {{255, 133, 181, 0, 0, 0, 169, 121, 193, 18, 122, 217, 88, 143, 182, 250}, 163}, {{255, 133, 181, 0, 231, 10, 9, 121, 219, 117, 139, 172, 104, 196, 125, 136}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 118}, 163}, {{255, 133, 181, 0, 0, 0, 138, 123, 84, 40, 44, 155, 157, 101, 215, 69}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 110, 188, 58, 89, 94, 181, 96, 189}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 53, 166, 68, 38, 47, 145}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 29, 67, 37}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 10, 169, 71, 214, 44}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 93, 121, 32, 7, 114, 110, 206}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 251, 109, 78, 105, 90, 59, 69, 160}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 32, 72, 131}, 163}, {{255, 133, 181, 0, 87, 255, 223, 164, 55, 180, 231, 238, 211, 216, 80, 29}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 90, 178, 197}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 95, 56, 181, 235, 123, 252}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 35, 145, 68, 164, 164}, 163}, {{255, 133, 181, 0, 146, 5, 200, 12, 173, 45, 146, 215, 12, 69, 111, 214}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 184, 110, 33, 67, 58, 11, 249, 238, 22, 60, 214, 183}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 213, 89, 242, 139, 253, 162}, 163}, {{255, 133, 181, 0, 0, 93, 78, 45, 98, 162, 97, 77, 44, 176, 170, 31}, 163}, {{255, 133, 181, 0, 0, 0, 169, 225, 217, 82, 80, 83, 233, 181, 206, 70}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 113, 80, 51, 239, 5, 228, 92, 51, 107}, 163}, {{255, 133, 181, 0, 0, 254, 80, 143, 192, 220, 188, 124, 253, 72, 171, 99}, 163}, {{255, 133, 181, 0, 0, 0, 132, 87, 181, 250, 110, 244, 191, 95, 204, 141}, 163}, {{255, 133, 181, 0, 136, 86, 57, 126, 197, 35, 190, 87, 120, 188, 122, 85}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 126, 105, 171, 132, 130, 91, 230}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 34, 23, 156, 69, 38, 125, 181, 180}, 163}, {{255, 133, 181, 0, 180, 30, 67, 106, 74, 198, 228, 200, 209, 254, 100, 174}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 45, 55, 152, 205, 14, 50}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 255, 86, 163, 76, 135, 230, 179, 100, 162, 72, 41, 239}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 184, 106, 232, 96, 38, 125, 111, 126}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 147, 65, 159, 242, 187, 89, 251, 68}, 163}, {{255, 133, 181, 0, 0, 107, 26, 49, 48, 237, 197, 49, 143, 135, 170, 138}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 60, 175, 7}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 69, 78, 174, 142, 200, 149, 51, 171}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 197, 172, 44, 178, 207, 123, 10, 117}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 30, 167, 174, 152, 159}, 163}, {{255, 133, 181, 0, 0, 0, 0, 167, 14, 109, 101, 25, 61, 122, 40, 79}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 91, 255, 89, 123, 221, 110}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 114, 112, 163, 23, 8}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 197, 248, 11, 41, 30}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 56, 225, 164}, 163}, {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 218, 140}, 163}, {{255, 133, 181, 0, 0, 0, 62, 60, 139, 251, 123, 86, 152, 155, 83, 61}, 163}, {{128, 177, 92, 155, 91, 192, 0, 130, 90, 211, 180, 237, 5, 234, 218, 252}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 106, 123, 131, 219, 24, 44}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 119, 142, 206, 134}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 98, 194, 236, 14}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 78, 202, 251, 15, 6, 91, 60}, 184}, {{128, 177, 92, 155, 91, 192, 221, 217, 94, 83, 231, 235, 248, 228, 78, 105}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 64, 196, 86, 218}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 86, 241}, 184}, {{128, 177, 92, 155, 91, 192, 100, 36, 192, 106, 162, 48, 48, 169, 23, 147}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 32, 73, 151, 109, 113}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 224, 138, 168, 202, 132, 58, 208, 236}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 211, 65, 32, 146, 22, 65}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 127, 226, 121, 232, 77, 117, 156, 44}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 15, 73, 70, 185, 177, 45}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 184}, {{128, 177, 92, 155, 91, 192, 0, 188, 198, 58, 220, 205, 20, 118, 255, 219}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 91, 221}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 13, 132, 32, 85, 149, 153, 19, 217}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 210, 88, 223, 23, 207}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 127, 147, 123, 210, 159, 201, 47, 210, 251}, 184}, {{128, 177, 92, 155, 91, 192, 0, 95, 49, 52, 155, 28, 191, 182, 94, 149}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 184}, {{128, 177, 92, 155, 91, 192, 227, 67, 60, 213, 241, 54, 161, 104, 70, 126}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 184}, {{128, 177, 92, 155, 91, 192, 33, 108, 176, 128, 182, 151, 55, 231, 50, 123}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 246, 137, 255, 219, 178, 185, 252}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 16, 205, 45, 255, 69, 163, 226, 130}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 63, 21, 28, 148, 158, 10, 172, 75}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 215, 87, 226, 154, 125}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 214, 148, 118, 62, 156, 124}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 43, 122, 56, 34, 189, 254}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 92, 80, 151, 8, 209, 13}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 137, 104}, 184}, {{128, 177, 92, 155, 91, 192, 18, 177, 253, 46, 228, 59, 132, 74, 190, 154}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 125, 239, 54, 10, 175, 97, 134, 200}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 70, 123, 189, 153, 99, 132, 39, 30}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 126, 34, 204, 81, 11, 94, 197, 183}, 184}, {{128, 177, 92, 155, 91, 192, 0, 4, 108, 172, 103, 184, 160, 135, 127, 221}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 101, 43, 223, 250}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 161, 212, 2}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 251, 144, 153, 184, 91, 69}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 66, 143, 217, 201, 3, 6}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 123, 103, 217, 50, 220, 25, 35, 28}, 184}, {{128, 177, 92, 155, 91, 192, 177, 2, 212, 14, 226, 90, 100, 146, 41, 154}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 251, 219, 18, 16, 103}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 53, 210, 60, 247, 242, 44}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 252, 233}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 163, 29, 90, 31, 150, 249, 115, 90}, 184}, {{128, 177, 92, 155, 91, 192, 0, 221, 190, 118, 35, 91, 195, 191, 120, 181}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 4, 201, 137, 90}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 108, 7}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 232, 174, 215, 36, 191, 213}, 184}, {{128, 177, 92, 155, 91, 192, 194, 92, 30, 24, 91, 189, 0, 205, 26, 43}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 125, 231, 242, 127, 237, 58, 9, 144}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 187, 249, 163, 88, 53, 64, 122, 212, 191}, 184}, {{128, 177, 92, 155, 91, 192, 0, 154, 250, 171, 83, 89, 222, 35, 44, 102}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 57, 104, 15, 42, 121}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 198, 40, 223, 204, 238, 3}, 184}, {{128, 177, 92, 155, 91, 192, 0, 164, 217, 63, 189, 47, 49, 97, 231, 64}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 18, 50, 29, 145, 138, 144, 229, 74, 27}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 163, 43, 95, 64, 126, 187}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 174, 242, 150, 6, 75, 244}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 242, 205, 229, 148, 157, 169, 237}, 184}, {{128, 177, 92, 155, 91, 192, 0, 68, 217, 45, 251, 59, 246, 142, 121, 247}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 75, 118, 217, 119}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 181, 110, 15}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 21, 4, 212, 178}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 233, 96, 223, 185, 154}, 184}, {{128, 177, 92, 155, 91, 192, 190, 64, 13, 106, 28, 153, 110, 75, 151, 27}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 117, 65}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 43, 163, 42, 130, 144}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 100, 58, 159, 153}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 129, 153, 130, 26, 52, 39, 22, 77}, 184}, {{128, 177, 92, 155, 91, 192, 97, 27, 107, 70, 253, 127, 76, 116, 11, 119}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 1, 250, 103}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 183, 3, 108, 184}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 105, 86, 143, 193, 189}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 94, 86, 143, 19, 1}, 184}, {{128, 177, 92, 155, 91, 192, 0, 65, 118, 180, 47, 110, 136, 200, 123, 221}, 184}, {{128, 177, 92, 155, 91, 192, 0, 83, 48, 187, 134, 183, 57, 71, 73, 146}, 184}, {{128, 177, 92, 155, 91, 192, 0, 128, 35, 101, 100, 60, 54, 118, 228, 224}, 184}, {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 194, 245}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 219, 130, 130, 104, 226}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 102, 51}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 124, 155, 159, 192}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 47, 65}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 211}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 105, 118}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 47, 182, 199, 52, 162}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 192, 21, 33, 118, 62}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 143, 169, 89}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 139, 25}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 79}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 204, 120, 222, 107, 222, 219}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 30, 29, 253}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 46, 228, 61, 46, 207, 58}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 163, 24, 190}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 132, 127, 30, 86, 66, 115, 140}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 126, 74, 203, 186}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 56, 58}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 49, 71, 118}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 181, 30, 138, 240, 20, 63}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 107}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 47, 153, 36, 150, 5, 170, 79}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 189, 77, 227, 223, 216}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 195, 139, 29, 70, 38}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 88}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 91}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 237, 247, 185, 22, 197, 202, 18}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 163, 72, 101, 94, 96, 144}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 9, 140, 112, 74, 96, 11}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 131, 69, 241, 97, 47, 220}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 155, 43}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 46, 227, 71, 73, 135}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 179, 52, 237, 128, 101, 4}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 74, 198, 29}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 113, 220, 95, 246, 42}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 244, 167, 159, 11}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 255, 185}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 125, 22, 125, 1}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 26, 58, 2, 114}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 223, 96, 65, 77}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 86, 235, 113, 11, 171}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 20, 9}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 189, 24, 42, 126}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 56}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 233, 112, 185, 163, 1, 132, 183}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 255, 43}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 65, 81, 129, 132, 195}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 243, 190}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 27, 160, 105, 7, 133, 149}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 231, 104, 247, 155, 249, 142}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 122, 31}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 12, 242}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 202, 71, 48, 79, 70}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 245, 113, 127}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 244, 5, 82, 75, 227, 230, 142}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 75, 154}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 113}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 46}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 255, 220, 239, 212, 1, 146}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 150, 85, 22, 15, 118, 226}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 212, 89, 77, 76, 17, 76}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 22, 234}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 98}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 190}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 58, 36, 217, 225, 143, 201}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 196, 140, 124, 191, 118, 235}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 133, 135, 205}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 11, 164}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 93, 112, 81, 143, 255, 180}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 100, 243, 9}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 211, 178, 128, 102, 175, 24, 175}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 130, 38, 100, 15, 242, 65, 81}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 8, 105}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 85}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 231, 228, 28, 77, 55, 204}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 184, 119}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 90, 57, 97, 108}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 175, 114, 218, 75, 221}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 115}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 85, 108, 243, 26, 169, 1}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 83, 50}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 83, 45, 163, 118, 143, 241}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 202, 56, 200, 205, 37}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 174, 196, 38, 149}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 241, 167, 31, 215}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 158, 6}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 154, 121, 204, 179, 182}, 188}, {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 198, 139, 25, 62, 226, 154}, 188}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 193}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 35, 50, 81}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 50, 115}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 229, 27, 132, 149}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 107, 8, 107}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 104, 25, 99, 185, 119, 189}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 45, 24, 102}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 114, 160, 229, 63, 226}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 221, 52}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 218, 214, 80, 78, 66, 155}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 121, 4, 71, 210}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 157, 230, 31}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 24, 87, 13, 72, 216}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 140, 37, 35}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 94}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 106, 51}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 138, 87, 58}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 25, 230, 107, 59, 49}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 133, 169, 187, 93}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 84, 218, 188}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 226, 228, 36, 249}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 219}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 55, 154}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 84, 41}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 241}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 214, 32, 48}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 169, 149, 53, 212, 212}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 124, 140, 46, 149}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 185}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 184, 171, 12, 208, 97}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 118, 247, 88, 241, 78}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 62, 84, 11}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 253}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 203, 169, 81, 84, 211, 145}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 253, 4, 94}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 218}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 184, 116, 116}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 86}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 41, 212, 97, 35, 190, 43}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 237, 240, 177, 251, 128}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 57}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 201, 194, 112, 60, 198, 67}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 152, 28, 7, 170}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 27, 209}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 198, 224}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 61, 13}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 14, 33, 31}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 97, 30, 134}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 160, 247, 100, 6}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 30, 21}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 87, 85, 65, 129}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 22, 144}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 240, 61, 139, 204, 30}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 69, 118}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 226, 152, 254}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 96, 247, 93, 10, 76}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 247, 2, 51, 72, 245}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 223}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 28, 161, 9}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 14, 154, 129, 163, 128}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 82, 95, 82, 153}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 151, 127, 214, 81, 47}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 177, 130, 100, 249}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 233, 111}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 16}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 112, 43, 6, 198}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 75, 246, 126, 147, 74}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 122, 50, 199, 78, 255}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 177}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 254, 220, 140}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 176}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 33, 79}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 45, 66, 239}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 166, 241, 120, 184}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 93, 222, 87}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 244, 0, 96}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 15, 181, 236, 95, 209}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 61, 36, 200}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 251, 171, 191}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 246, 10}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 232, 84}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 102, 94}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 36, 25, 68}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 145, 218, 2, 29}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 12, 217}, 63}, {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 32, 116, 9, 176}, 63}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 200}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 12}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 95}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 48}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 30}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 1}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 17}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 249}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 113}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 201}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 110}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 207}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 138}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 187}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 209}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 60}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 132}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 214}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 32}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 103}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 42}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 252}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 144}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 95}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 116}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 221}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 101}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 49}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 31}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 100}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 84}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 16}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 163}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 77}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 232}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 160}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 233}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 153}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 26}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 237}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 197}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 92}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 186}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 172}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 248}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 8}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 150}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 80}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 119}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 177}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 60}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 243}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 237}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 92}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 113}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 219}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 202}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 239}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 76}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 70}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 72}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 242}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 69}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 175}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 240}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 57}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 39}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 251}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 164}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 90, 114, 115, 246}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 225, 177}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 253}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 183, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 153, 37}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 217, 6, 109}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 122, 203, 46, 16, 27, 156}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 173, 143}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 77, 200, 134, 152, 167}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 177, 216, 164}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 118, 127, 91}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 166, 246, 221, 26, 162}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 33, 42, 201, 84, 232}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 75, 209, 157}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 32, 127, 82, 56}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 242, 174, 102}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 64, 200, 44, 242, 143}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 127, 170, 18}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 251, 71, 13, 187}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 183}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 203, 154, 241}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 44, 82, 187, 252, 164}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 148, 83, 53, 139, 105, 155}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 42}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 213, 6, 34, 158, 86}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 54}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 128, 163, 232, 125}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 140, 249, 55, 193}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 74, 72, 30}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 255}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 28, 229}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 161, 35, 21, 122, 128, 4}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 222, 137, 51, 158}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 96, 92}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 229, 102, 220}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 147, 250, 34, 43}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 23, 52}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 38, 8, 143, 187, 115, 168}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 202, 29, 33}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 115}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 179, 174, 20, 103, 210, 53}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 116, 247, 41}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 62, 243, 199, 201}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 51, 89}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 165, 133, 42, 21, 255, 35}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 191}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 131, 177, 205, 105, 223, 125}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 190, 105}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 97, 217, 37}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 230, 81, 166}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 192, 254, 255, 165}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 74, 62, 222}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 2, 164, 28, 64}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 74, 23, 94, 171}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 81, 46, 154, 20}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 123, 15, 47, 242, 44, 77}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 72, 52, 116}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 55, 220, 193, 38, 203, 120}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 248, 177, 91, 164, 104, 251}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 114, 187}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 128, 47, 80, 168, 70, 167}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 175, 65, 113, 48, 122, 19}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 63, 90, 223, 50, 164, 17}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 212, 238, 8, 33, 27, 17}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 167, 19}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 203, 11, 87, 125, 54}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 204, 189, 54, 151, 232, 130}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 44, 72, 158, 236, 22, 18}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 227, 230, 68, 97, 24, 216}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 98}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 47, 146, 109}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 57, 95}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 67, 74, 175, 83}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 141, 189, 103, 126, 157}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 175}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 42}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 2, 113}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 89, 149, 190, 35, 223}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 92, 186, 202, 225}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 244, 57}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 146, 189, 4, 186}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 141, 194, 105, 36, 82}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 136, 127, 241, 253}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 149, 201}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 249, 245, 247, 214, 241, 152}, 228}, {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 157, 196}, 228}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 102, 25, 70, 201, 235, 183}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 228}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 114, 244, 140, 5}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 204, 82}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 133}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 77, 218, 231}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 43, 173, 198, 116, 229, 219}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 150, 170, 77, 46, 147, 165}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 245, 169, 242, 103}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 39, 149, 29}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 1, 137, 172, 250}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 221, 58, 12}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 2}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 128, 233, 206, 137}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 12, 32, 105, 185, 242, 199}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 3, 52, 247, 30, 196, 172}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 55, 91}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 191, 185, 118, 202, 112, 144}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 92, 16, 151}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 110}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 70, 154, 25, 211, 91}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 53, 230, 220, 177, 13}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 166, 77}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 91, 116, 73, 252, 73, 73}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 151, 17, 239}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 193, 146, 61, 192, 10}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 244, 30, 80}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 47, 243}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 11, 30, 214, 160, 189, 134}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 75}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 111, 118}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 136, 203, 57, 46}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 111, 90, 127, 115, 147}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 53}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 176}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 148, 190, 55}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 150, 119, 220, 166, 94, 12}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 41, 31, 69}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 53, 22, 84}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 73, 88, 183, 54, 201, 210}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 4, 138, 148}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 156, 5, 167, 27, 173, 90}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 113, 47, 76}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 5, 151, 244}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 135}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 46, 248}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 114, 107, 81, 26}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 85, 128, 112, 122, 71}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 236, 111, 182, 176, 211, 131}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 23, 132, 246}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 161, 141, 156, 76}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 215, 163, 80, 92, 84}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 222}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 174, 48, 63, 89, 34}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 181, 105, 54, 166, 108, 146}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 197, 15}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 148, 65, 38, 107, 188, 121}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 246, 102, 9, 55}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 190, 73, 247, 163, 148}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 152, 97, 250, 111, 202}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 149, 182, 52, 226}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 56, 54, 237, 226}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 239, 7, 71, 144}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 195, 101, 170, 81}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 125, 112, 130, 186, 56}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 248, 145}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 218, 115, 223, 47}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 141, 7, 47, 224}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 218}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 163}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 245, 34}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 224, 231, 247, 39}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 241, 192, 130}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 54, 107, 203, 103, 126, 102}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 178, 90, 72, 173}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 176, 163, 96, 14, 159}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 137, 118, 83}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 181, 141, 147, 184}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 155, 78, 172}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 180, 71, 125, 193, 28, 199}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 88, 205, 214, 70, 32}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 243, 102, 89, 153, 89, 241}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 78, 88, 163}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 205, 132, 53}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 228, 220, 251, 255}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 203, 7, 150, 19, 23, 244}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 197, 88, 7}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 118, 11, 9, 123, 17, 125}, 168}, {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 168}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 35}, 194}, {{97, 9, 64, 0, 0, 0, 192, 135, 50, 212, 49, 59, 146, 72, 224, 139}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 176, 227, 71, 28, 246, 156, 30}, 194}, {{97, 9, 64, 0, 0, 0, 252, 122, 57, 237, 97, 84, 114, 46, 244, 54}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 83, 213, 172, 36, 184, 192}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 166, 147, 109}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 163, 197, 121, 27, 6, 33, 227, 255}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 255}, 194}, {{97, 9, 64, 0, 0, 0, 0, 88, 112, 172, 14, 246, 82, 57, 105, 213}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 10, 213, 168, 125, 103, 152, 51, 194}, 194}, {{97, 9, 64, 187, 118, 236, 174, 172, 229, 23, 7, 20, 64, 115, 233, 255}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 132, 0, 253, 33, 42, 22, 89, 134, 242, 129, 106, 230}, 194}, {{97, 9, 64, 0, 0, 0, 0, 151, 214, 114, 1, 185, 165, 189, 93, 3}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 211, 2, 40, 105, 32, 99, 218, 220}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 194}, {{97, 9, 64, 0, 0, 0, 0, 209, 137, 69, 216, 84, 153, 210, 8, 62}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 144, 229, 90}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 101, 66, 17, 189, 94}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 115, 189, 77}, 194}, {{97, 9, 64, 0, 68, 24, 209, 79, 17, 171, 251, 19, 80, 141, 228, 126}, 194}, {{97, 9, 64, 0, 17, 120, 172, 226, 37, 60, 233, 193, 188, 230, 210, 112}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 210, 76}, 194}, {{97, 9, 64, 0, 0, 43, 177, 98, 143, 228, 64, 185, 211, 226, 35, 197}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 94, 189}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 171, 70, 243, 183, 89, 132, 10}, 194}, {{97, 9, 64, 0, 0, 0, 0, 144, 59, 148, 177, 220, 85, 235, 105, 122}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 13, 173, 226}, 194}, {{97, 9, 64, 35, 171, 157, 203, 218, 123, 13, 161, 71, 165, 171, 97, 60}, 194}, {{97, 9, 64, 126, 178, 80, 7, 2, 76, 212, 186, 211, 193, 78, 25, 23}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 44, 105, 136, 194, 99, 170}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 68, 197, 175, 85, 69, 137, 167, 25}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 236, 236, 237, 164, 229}, 194}, {{97, 9, 64, 82, 70, 83, 149, 51, 222, 33, 77, 50, 6, 51, 2, 54}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 131}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 215, 12, 132, 212, 66, 155, 182, 168}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 250, 197, 119}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 54, 83, 225, 249, 224, 145}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 142, 10, 90, 220, 193, 205, 45}, 194}, {{97, 9, 64, 0, 0, 0, 78, 74, 203, 0, 127, 215, 234, 77, 105, 149}, 194}, {{97, 9, 64, 144, 166, 163, 96, 73, 132, 209, 208, 194, 69, 31, 153, 141}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 115, 144, 116}, 194}, {{97, 9, 64, 0, 0, 0, 152, 55, 85, 252, 99, 187, 145, 48, 151, 204}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 59, 197, 202, 11, 80, 172, 117, 212}, 194}, {{97, 9, 64, 0, 0, 0, 191, 244, 125, 86, 112, 232, 141, 242, 160, 72}, 194}, {{97, 9, 64, 0, 0, 0, 0, 240, 117, 109, 44, 131, 254, 58, 139, 22}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 141, 172, 180, 233, 131, 238, 112, 192}, 194}, {{97, 9, 64, 0, 73, 210, 8, 209, 24, 130, 71, 55, 66, 76, 206, 145}, 194}, {{97, 9, 64, 0, 197, 62, 111, 189, 255, 142, 78, 181, 94, 182, 186, 73}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 26, 77, 35, 252, 196, 133, 186}, 194}, {{97, 9, 64, 0, 0, 68, 117, 205, 51, 247, 243, 242, 166, 218, 63, 111}, 194}, {{97, 9, 64, 0, 0, 0, 89, 237, 9, 186, 181, 126, 143, 33, 201, 255}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 191, 239, 65, 56, 143, 11, 59, 88}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 188, 254}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 114, 161}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 16, 164}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 67, 250, 111, 228, 80}, 194}, {{97, 9, 64, 0, 3, 6, 252, 174, 40, 168, 11, 192, 67, 29, 181, 94}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 226, 35, 7, 139, 95, 165}, 194}, {{97, 9, 64, 0, 0, 0, 0, 83, 76, 199, 200, 182, 133, 81, 170, 252}, 194}, {{97, 9, 64, 0, 0, 4, 217, 8, 100, 133, 249, 134, 247, 200, 209, 148}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 143}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 193, 70, 59}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 176}, 194}, {{97, 9, 64, 0, 115, 156, 188, 155, 165, 220, 70, 250, 93, 10, 22, 143}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 90}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 190, 153, 19, 159, 180, 213}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 153, 36, 110, 126, 25}, 194}, {{97, 9, 64, 50, 102, 204, 2, 232, 242, 228, 156, 219, 107, 226, 151, 249}, 194}, {{97, 9, 64, 0, 71, 166, 242, 140, 162, 14, 198, 198, 108, 83, 155, 240}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 55}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 211, 229, 92, 142, 254, 247, 105}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 200, 122}, 194}, {{97, 9, 64, 0, 0, 0, 214, 53, 217, 227, 103, 210, 78, 219, 13, 189}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 105, 140, 133, 199, 175, 193}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 24, 198, 17, 189, 115, 191, 84}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 102, 240, 230}, 194}, {{97, 9, 64, 0, 0, 0, 9, 122, 184, 81, 63, 39, 106, 113, 171, 234}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 223}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 50, 246, 221, 87, 229, 93, 16}, 194}, {{97, 9, 64, 0, 0, 0, 171, 227, 188, 13, 110, 32, 37, 149, 92, 234}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 81, 160, 156, 55, 44}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{97, 9, 64, 0, 2, 89, 63, 162, 183, 73, 170, 199, 211, 118, 230, 71}, 194}, {{97, 9, 64, 0, 0, 0, 59, 164, 29, 97, 192, 64, 159, 224, 80, 44}, 194}, {{97, 9, 64, 0, 92, 40, 216, 12, 85, 69, 127, 115, 72, 147, 181, 129}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 122, 65, 128, 166, 147}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 194}, {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 133, 247, 195, 248, 74}, 194}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 162, 51, 14, 198, 180}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 54, 13}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 236, 155, 227, 66, 79, 247, 123, 21}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 213, 218}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 106, 173, 54, 139, 85, 57}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 183, 127}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 92, 250, 108, 109}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 152, 35, 221}, 166}, {{213, 215, 45, 200, 170, 120, 0, 6, 102, 3, 176, 201, 39, 139, 85, 199}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 242, 248, 141}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 166}, {{213, 215, 45, 200, 170, 120, 0, 109, 217, 72, 228, 251, 182, 15, 131, 22}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 167, 195, 224, 181}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 79, 174, 59, 61}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 39, 103}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 162, 4}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 152, 210, 112, 68, 182, 218, 66, 204}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 160, 85, 153, 33, 35, 52, 87}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 20, 21, 123, 147, 61, 62, 17, 230}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 163, 248, 177}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 138, 3, 172, 251, 149}, 166}, {{213, 215, 45, 200, 170, 120, 37, 45, 190, 122, 134, 245, 96, 100, 53, 108}, 166}, {{213, 215, 45, 200, 170, 120, 0, 154, 39, 229, 22, 153, 126, 91, 43, 44}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 68, 202, 93, 59, 162, 235, 144, 128}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 31, 254, 99, 166, 77}, 166}, {{213, 215, 45, 200, 170, 120, 79, 200, 32, 24, 20, 16, 110, 30, 145, 168}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 175, 164, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 63, 5}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 74, 225, 16, 122, 183, 1, 17, 176}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 137, 49, 143, 179, 223}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 175, 231, 177, 161, 83, 131, 142}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 55, 76, 47, 127, 122, 180, 73, 62}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 228, 156, 95, 28, 80, 41, 193}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 107, 202, 27, 154, 163, 76, 6}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 242, 107, 148, 193, 76, 129, 145}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 140, 32, 135, 40, 59, 51, 225, 27}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 242, 206, 127, 222, 57, 123, 132, 192}, 166}, {{213, 215, 45, 200, 170, 120, 0, 80, 1, 239, 52, 157, 247, 48, 20, 93}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 157, 171, 27, 127, 101}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 151, 8, 98}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 68, 159, 199, 210, 59, 220, 160, 238}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 208, 213, 110, 230, 139}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 120, 223, 36, 216, 50, 166, 64, 137}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 80, 98, 204, 162, 59, 81}, 166}, {{213, 215, 45, 200, 170, 120, 0, 212, 186, 186, 30, 140, 38, 42, 36, 13}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 243, 211}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 119, 5, 249, 67, 241}, 166}, {{213, 215, 45, 200, 170, 120, 0, 91, 198, 169, 147, 103, 181, 224, 171, 21}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 87, 133, 117, 250, 136}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 181, 160, 55, 194, 12, 89, 158, 161}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 215, 58, 228}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 94, 136, 236, 107, 152, 19, 103, 35}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 76, 138, 113, 234, 67}, 166}, {{213, 215, 45, 200, 170, 120, 0, 168, 49, 136, 215, 205, 177, 111, 132, 43}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 153, 14, 86}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 166}, {{213, 215, 45, 200, 170, 120, 0, 224, 233, 17, 51, 137, 58, 210, 59, 233}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 194, 31, 105, 1, 71, 0, 12, 160}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 213, 141, 209}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 136, 140, 147, 247, 132, 66, 29}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 199, 49, 63, 198, 125}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 199, 211, 40, 11}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 85, 41}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 63, 28, 79}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 190, 27, 198, 233, 51, 134, 94, 90}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 241, 216, 105, 52, 254, 129, 68}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 210, 75, 213, 55}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 1, 236, 59, 7, 50, 105, 184, 138}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 82, 31, 16}, 166}, {{213, 215, 45, 200, 170, 120, 131, 216, 176, 80, 69, 181, 145, 142, 223, 36}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 254, 43, 241, 207}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 248, 215, 50, 215}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 95, 190, 126}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 246, 145}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 183, 169, 61, 230}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 213, 49, 54, 141, 95}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 34, 225, 207, 191, 18, 120, 78, 243}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 31, 61, 193}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 233, 97, 165, 139, 145}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 166}, {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 210}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 13}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 65}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 35, 119, 49}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 245, 213, 65, 141}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 160, 244}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 164, 16, 171, 46}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 191, 77}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 107, 91}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 6, 21, 205}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 25}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 235}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 168, 50, 111, 93}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 92, 243}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 61}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 208, 82, 4, 214}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 205, 119}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 199, 125, 91, 50}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 229, 98, 115, 102}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 63, 9}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 181}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 233, 50, 170}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 235, 16}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 126}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 75, 125, 214}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 185}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 129, 175, 118, 86}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 25}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 210}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 215}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 176, 7, 65}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 249, 168, 113, 133}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 82, 193}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 16, 30, 155}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 19, 43, 176}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 64}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 9, 61}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 235, 3, 238}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 228}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 112, 58}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 145, 252}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 42, 184}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 235, 182, 72}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 215, 4}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 153, 62, 243}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 14}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 77, 3, 7}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 37, 14, 98}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 7, 135, 53}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 149, 16}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 228, 157}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 189, 234, 188, 221}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 3, 204, 202}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 164}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 108, 69, 114}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 162, 47}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 127}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 137}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 238, 21}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 131, 79, 163}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 101, 49, 132}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 10, 26}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 132, 201}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 129}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 181, 94}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 38, 50, 123, 225}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 123, 201}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 33}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 147}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 96, 214, 60, 202}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 123}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 60}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 51, 165}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 141, 56, 31, 45}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 140, 101, 125, 253}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 254}, {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 159, 164, 134, 15}, 254}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 250, 55, 161, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 47, 63}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 138, 196, 76}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 172, 35, 221, 214, 141}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 36, 152}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 238}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 228, 185}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 150, 132, 42, 96, 191}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 168, 174, 134, 170}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 167, 226}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 229, 111}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 13}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 5}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 164}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 82, 251, 227, 199}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 229, 138}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 254, 195, 236, 188, 242}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 161}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 205, 22}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 167, 55}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 106, 228, 57, 124, 50}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 107, 35, 71, 124, 123}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 172, 189, 184}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 47, 105, 48, 172, 218}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 227, 206, 204, 251, 182, 23}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 201}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 28, 157, 72, 44}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 55, 237, 126, 166}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 74, 18, 144}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 15}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 102}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 27}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 131, 228}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 171}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 134, 110, 15, 94, 53, 107}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 152, 63, 132}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 212, 130, 186, 56}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 139, 249, 189, 226}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 51, 154, 75, 69, 238}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 96, 223, 255, 134, 75}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 76, 192}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 104, 27, 18}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 233, 209, 232, 86}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 181, 203, 11, 122}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 41, 184, 211, 79, 114}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 211, 12, 108}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 242, 65, 132}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 213, 118, 87, 19, 173}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 175, 181}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 244, 143, 174, 225, 238}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 14}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 75, 250, 6, 52, 201}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 175, 123}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 122, 156, 8, 168}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 19, 139, 192, 175}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 126, 59, 226, 14, 202}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 161, 13, 41, 8, 105, 25}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 96, 202, 17, 168, 159}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 192, 68, 180, 150}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 79, 143, 159, 94}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 168, 84, 118, 78}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 194}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 214}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 117, 195, 181, 130}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 27, 135}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 4, 83, 152, 186}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 91}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 212, 1, 106, 18, 135, 245}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 100, 170}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 149, 160}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 233, 227, 219, 25}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 205}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 75, 132, 130, 27}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 243}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 186}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 33, 96, 220, 180, 243}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 207}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 110}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 104, 251, 30, 245}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 250}, 49}, {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 16, 125}, 49}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 62, 109}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 254, 197, 188}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 15}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 195, 30, 175}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 138}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 186, 22}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 81, 70, 122}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 23, 125, 149}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 186}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 40, 159, 209}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 28, 12, 140}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 1}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 66, 49}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 238, 132}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 252, 202, 74}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 217, 196}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 209, 71}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 144}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 23, 180, 143}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 165, 14}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 225, 85, 141}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 125, 144}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 35, 81}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 26}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 95, 21}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 229, 184, 192}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 182, 98}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 143, 103, 226}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 131, 161, 79}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 52}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 148, 103}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 10}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 111}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 26, 56}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 253, 196}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 245, 117}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 66, 102}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 29, 255}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 215, 229}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 167, 20, 206}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 136, 150, 6}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 245}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 64, 193, 178}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 23}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 87, 20, 128}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 242, 195}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 228, 148}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 166, 112, 115}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 36, 31}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 105}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 142, 171, 81}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 94, 172, 227}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 164}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 78, 131}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 54, 180, 190}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 97}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 158}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 171, 10, 85}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 178}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 202, 72}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 167, 5, 54}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 54, 7, 61}, 95}, {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 245, 189, 33}, 95}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 106, 117, 64, 94, 230, 153, 109}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 58, 109, 224, 172, 12, 9, 155}, 193}, {{160, 91, 68, 81, 128, 68, 148, 184, 181, 236, 117, 175, 120, 172, 223, 77}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 83, 247, 75, 5}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 211, 8, 217, 235, 142}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 27, 109, 134, 116}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 180, 100, 226, 205, 75, 177}, 193}, {{160, 91, 68, 81, 128, 145, 30, 247, 69, 12, 71, 42, 41, 41, 44, 239}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 158, 240, 92, 2, 170, 37}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 154, 26, 47, 105}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 90, 124, 211, 141, 153, 203, 152}, 193}, {{160, 91, 68, 81, 128, 108, 94, 192, 170, 95, 186, 245, 146, 48, 93, 204}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 247, 179, 144}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 218, 198, 237, 238, 65, 144, 191, 82}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 37, 176, 189, 116}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 116}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 106, 249, 96, 213, 115}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 33, 84, 158, 94, 135}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 66, 202, 145, 193, 215, 215}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 174, 176, 206, 142}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 182, 22, 32, 62, 253, 110, 254, 12}, 193}, {{160, 91, 68, 81, 128, 0, 131, 111, 215, 91, 148, 174, 113, 149, 39, 56}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 158, 233, 184, 158, 119, 248}, 193}, {{160, 91, 68, 81, 128, 0, 57, 18, 241, 97, 239, 253, 72, 146, 61, 115}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 42, 226, 238, 38, 213}, 193}, {{160, 91, 68, 81, 128, 0, 0, 113, 17, 69, 39, 233, 246, 196, 64, 254}, 193}, {{160, 91, 68, 81, 128, 60, 96, 211, 79, 41, 99, 193, 247, 208, 13, 92}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 191, 156, 157, 182, 130, 8, 32, 147}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 176, 12, 103, 217}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 103, 73, 3, 166}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 207, 212, 108, 223, 126, 88, 105, 109}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 112, 48, 62, 209, 164, 163}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{160, 91, 68, 81, 128, 0, 47, 235, 194, 204, 225, 9, 170, 113, 160, 217}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 193, 50, 168, 88, 40, 93, 83}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 230, 62, 16, 151}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 54, 195, 138}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 129, 167, 99, 31, 94, 190, 206, 204}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 31, 209, 4, 134, 166}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 227, 156, 129}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 98, 56, 131, 202, 36}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 88, 22, 207, 59, 235, 3, 4}, 193}, {{160, 91, 68, 81, 128, 0, 128, 92, 107, 117, 238, 54, 244, 182, 131, 222}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 67, 191, 243, 58}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 223, 147, 241}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 84, 148, 150, 18, 117, 205}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 169, 15, 214, 202, 100, 14, 103, 182}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 157, 34, 56, 148}, 193}, {{160, 91, 68, 81, 128, 0, 195, 4, 35, 171, 18, 231, 247, 157, 241, 93}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 191, 40, 221, 227, 106, 7}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 160, 192, 134, 228}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 193}, {{160, 91, 68, 81, 128, 0, 0, 218, 248, 198, 172, 78, 103, 144, 41, 175}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 104, 165, 195}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 99, 59, 79, 95, 110, 21}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 33, 86, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 116, 83, 132, 210, 80, 3, 255, 161, 199}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 86, 221, 23, 118}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 130, 218, 238}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 243, 130, 92, 253, 142, 9, 211}, 193}, {{160, 91, 68, 81, 128, 9, 37, 28, 163, 105, 108, 16, 154, 185, 116, 240}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 229, 31, 119, 1, 55, 190, 128, 217}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 225, 244, 154}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 212, 48, 55, 24, 106}, 193}, {{160, 91, 68, 81, 128, 111, 9, 100, 86, 38, 205, 183, 234, 201, 15, 111}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 242, 80, 158, 53, 215, 238, 165, 11}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 67, 185, 5, 135, 135}, 193}, {{160, 91, 68, 81, 128, 245, 165, 116, 166, 57, 136, 117, 37, 98, 213, 250}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 41, 89, 152, 15, 66, 6, 205}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 236, 244, 164, 117, 29, 152, 168}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 236, 189, 111, 117}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 245, 232, 196}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 142, 66, 194, 81}, 193}, {{160, 91, 68, 81, 128, 0, 0, 90, 224, 82, 26, 35, 77, 210, 47, 90}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 202, 68, 80, 177, 94, 31, 46}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 127, 127, 166, 238, 15, 143}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 102, 73, 218, 30, 188, 41, 12, 121}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 73, 138, 142, 25, 111, 240, 49, 238}, 193}, {{160, 91, 68, 81, 128, 0, 35, 80, 171, 171, 11, 203, 253, 203, 255, 231}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 93}, 193}, {{160, 91, 68, 81, 128, 0, 0, 234, 80, 224, 226, 11, 77, 241, 144, 53}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 132, 0, 250, 33}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 227, 163, 207, 224, 52, 202, 12}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 142, 109, 58, 57, 82, 174, 117, 185}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 43, 252, 70, 31, 48, 194, 141}, 193}, {{160, 91, 68, 81, 128, 0, 121, 124, 43, 59, 47, 153, 154, 76, 168, 0}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 112, 51, 217, 85, 150, 12, 159, 36}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 161, 110, 179, 103, 123}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 136, 132, 106, 94, 164}, 193}, {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 214, 137, 244, 167, 12, 11}, 193}, {{160, 91, 68, 81, 128, 0, 0, 30, 255, 52, 255, 204, 221, 75, 206, 99}, 193}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 193, 123, 253}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 66, 244}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 112, 54}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 77, 225, 151}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 98, 234, 236, 187, 190}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 29, 37, 154, 253, 108}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 218, 167, 166, 113, 184, 127, 120}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 196, 170, 32}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 236}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 85, 36, 49}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 176, 91, 210, 98, 200, 210, 119}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 200, 123, 8, 202, 163, 177}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 72, 110, 220, 175, 115, 194, 177}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 224}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 105}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 149, 3}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 201, 11, 50, 73, 179}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 116, 228, 88}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 45, 108, 11, 61, 17}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 84, 22}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 166, 145, 22, 13, 37, 210}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 189, 96, 220, 193, 225}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 171, 123, 214, 47, 186}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 242, 243, 226, 233, 124}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 31, 204, 33, 36, 121, 27}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 231}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 67}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 101, 11, 38, 74, 141}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 54}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 108, 86, 139, 164, 194, 71, 61}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 222, 96, 31}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 195, 239, 79, 230, 35}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 154, 246, 163, 83, 210}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 123, 45, 219}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 101, 51, 64, 204, 159, 178}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 195, 139, 227, 125}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 134, 60, 103, 208}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 123, 99, 99}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 140, 84, 123, 192, 205}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 25, 7, 246, 196, 214, 129, 170, 1}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 43, 15}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 212, 155, 228, 127, 198, 176}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 159}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 235, 94, 13, 17, 164, 61, 142, 35}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 29}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 232, 171, 43, 114}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 19, 99, 71, 205, 110}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 160, 15, 55, 136, 113, 35, 118}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 38}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 197, 25, 186, 1, 60, 249, 90}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 186, 206, 180}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 107, 56, 29, 236}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 83, 151, 51}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 244, 8, 100, 251}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 81, 213, 99, 122, 98}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 240, 32, 121}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 132, 116, 147, 53, 51}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 132, 69, 50, 219}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 206, 148, 17, 114, 45, 241, 104, 187}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 16, 16, 229, 241, 188, 129, 90}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 167, 37, 243, 46, 25}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 77, 133, 149, 199, 241, 59, 129, 246}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 44, 76, 119, 237, 197, 171, 149}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 201, 229, 132, 63}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 185, 178, 95, 38, 239}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 226, 58, 237}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 225, 113, 8, 133, 125}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 114, 146, 234, 222, 242, 153, 179, 24}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 157, 183, 125, 215}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 71, 81, 223, 50, 72, 223, 65, 46}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 171, 181, 60, 33, 41, 35}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 17, 28}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 85, 148, 158, 180}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 130}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 97, 36, 35, 93, 69, 146}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 241}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 136, 110, 5}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 158}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 190, 91, 147, 92, 79, 187}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 102, 106, 151, 255, 49, 177, 198, 48}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 23, 19, 91, 199}, 155}, {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 155}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 206, 141, 10, 203, 217, 92, 254}, 133}, {{236, 194, 0, 0, 195, 151, 89, 221, 1, 236, 138, 215, 88, 5, 97, 193}, 133}, {{236, 194, 0, 0, 0, 101, 184, 161, 208, 199, 35, 33, 185, 75, 189, 190}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 194, 43}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 160, 53, 105, 195, 229, 236}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 123, 182, 99, 224, 137, 147}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 178}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 124}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 133}, {{236, 194, 0, 0, 19, 203, 207, 160, 70, 157, 169, 2, 83, 210, 76, 58}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 144, 228, 159, 140, 98, 255, 49}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 188, 12}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 224, 61, 204, 119, 253, 23, 212, 37}, 133}, {{236, 194, 0, 144, 130, 16, 27, 90, 118, 77, 128, 89, 67, 26, 4, 122}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 51, 251}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 147, 181, 79}, 133}, {{236, 194, 0, 0, 79, 57, 175, 126, 203, 215, 124, 188, 246, 55, 106, 191}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 78, 129, 137, 187}, 133}, {{236, 194, 0, 0, 0, 0, 0, 33, 201, 87, 140, 87, 61, 140, 188, 58}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 134}, 133}, {{236, 194, 0, 0, 28, 155, 60, 36, 55, 106, 21, 237, 18, 187, 238, 32}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 31, 134, 66, 130, 208, 117}, 133}, {{236, 194, 0, 0, 97, 33, 71, 189, 253, 128, 191, 126, 62, 63, 181, 50}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 73, 245, 145, 14}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 72, 154, 128, 196}, 133}, {{236, 194, 0, 0, 0, 112, 93, 36, 90, 213, 255, 166, 197, 62, 195, 80}, 133}, {{236, 194, 0, 0, 0, 0, 0, 162, 158, 12, 148, 251, 122, 101, 57, 245}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 30, 40, 213, 2, 50, 86}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 64, 72, 16, 76, 208, 83, 153}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 252, 78, 252}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 4, 167, 86, 148, 12, 128}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 117, 39, 178}, 133}, {{236, 194, 0, 0, 0, 137, 92, 193, 25, 23, 165, 195, 47, 45, 6, 238}, 133}, {{236, 194, 0, 0, 0, 32, 157, 52, 65, 159, 226, 111, 61, 11, 149, 242}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 142, 52, 17, 199, 143, 45, 151}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 159, 22, 16, 116}, 133}, {{236, 194, 0, 0, 0, 0, 0, 120, 68, 80, 108, 97, 58, 35, 65, 220}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 44, 6, 206, 131, 167, 154, 224}, 133}, {{236, 194, 0, 0, 0, 0, 38, 251, 222, 252, 25, 252, 107, 187, 94, 104}, 133}, {{236, 194, 0, 0, 145, 195, 112, 234, 105, 231, 123, 121, 125, 193, 10, 155}, 133}, {{236, 194, 0, 0, 0, 0, 101, 172, 244, 109, 147, 195, 110, 254, 75, 120}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 136, 102, 184, 54}, 133}, {{236, 194, 0, 0, 0, 0, 0, 194, 231, 163, 76, 239, 86, 126, 94, 119}, 133}, {{236, 194, 0, 0, 0, 0, 143, 131, 132, 188, 38, 141, 105, 138, 172, 47}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 2, 229, 74, 75, 62, 72, 145, 57}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 202, 160, 25}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 59, 222, 31, 20, 217, 167, 180, 227}, 133}, {{236, 194, 0, 0, 0, 23, 113, 27, 183, 25, 244, 101, 162, 92, 15, 154}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 254, 100, 11}, 133}, {{236, 194, 0, 228, 249, 224, 114, 4, 205, 139, 98, 218, 245, 160, 26, 70}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 180, 229, 232, 27, 60, 74, 209, 200}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 141, 200, 134, 52, 75, 37}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 185}, 133}, {{236, 194, 0, 0, 0, 0, 0, 89, 118, 42, 41, 250, 80, 4, 10, 126}, 133}, {{236, 194, 0, 149, 240, 122, 39, 86, 203, 200, 178, 223, 56, 19, 64, 230}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 149, 29, 58, 198, 24, 137}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 178, 202, 144}, 133}, {{236, 194, 0, 0, 0, 25, 249, 9, 153, 77, 159, 208, 193, 125, 23, 143}, 133}, {{236, 194, 0, 0, 0, 167, 83, 194, 118, 204, 252, 0, 97, 106, 143, 201}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 189, 108, 15, 155, 103, 131, 237}, 133}, {{236, 194, 0, 0, 0, 0, 0, 250, 119, 238, 107, 90, 255, 59, 116, 200}, 133}, {{236, 194, 0, 0, 0, 0, 0, 130, 10, 234, 112, 37, 246, 138, 226, 167}, 133}, {{236, 194, 0, 0, 0, 50, 96, 254, 163, 31, 68, 161, 169, 127, 84, 94}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 38, 204, 147, 174}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 210, 98, 116, 91, 137, 212, 115}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 118, 4, 157, 222, 19, 138, 110}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 56, 122}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 208, 90, 80, 244, 241, 139}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 196, 163, 211, 60, 153, 163}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 253, 175, 132, 103}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 237, 44, 7, 177, 30, 114, 76}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 148, 138, 151}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 16, 153}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 27, 137, 108, 168}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 160, 177, 214, 75, 127, 38, 25, 137}, 133}, {{236, 194, 0, 48, 149, 175, 225, 171, 252, 100, 27, 191, 42, 177, 74, 77}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 164, 110, 25, 34, 212, 90, 20}, 133}, {{236, 194, 0, 184, 34, 251, 182, 48, 62, 181, 218, 197, 48, 252, 179, 151}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 183, 50, 132, 128}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 255, 103, 40}, 133}, {{236, 194, 0, 0, 0, 0, 106, 228, 10, 13, 207, 36, 125, 172, 234, 218}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 15}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 125, 221, 61, 232, 154, 134, 211}, 133}, {{236, 194, 0, 0, 0, 0, 22, 77, 214, 50, 113, 25, 84, 127, 5, 113}, 133}, {{236, 194, 0, 0, 0, 0, 0, 254, 167, 1, 238, 111, 154, 47, 183, 138}, 133}, {{236, 194, 0, 0, 0, 123, 231, 207, 11, 49, 215, 64, 193, 199, 28, 226}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 199, 3, 220, 219}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 209, 45, 196, 37, 38, 31}, 133}, {{236, 194, 0, 0, 0, 0, 0, 0, 91, 99, 26, 74, 90, 238, 144, 115}, 133}, {{236, 194, 0, 237, 127, 86, 114, 135, 39, 175, 227, 178, 150, 3, 58, 174}, 133}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 125, 194, 232}, 10}, {{168, 243, 103, 221, 120, 106, 168, 35, 250, 13, 152, 109, 179, 164, 96, 248}, 10}, {{168, 243, 103, 221, 120, 0, 0, 5, 34, 227, 146, 113, 219, 171, 7, 252}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 251, 150, 218, 107}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 135, 83, 63, 251, 177}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 155, 93, 246, 221, 196, 168, 71}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 134, 6, 183, 17, 7, 73, 188, 61, 168}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 235, 201, 43, 157, 88}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 165, 95, 222, 159, 155, 88, 9, 94}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 216, 86, 68, 4}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 255, 241, 145, 240}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 143, 195, 217, 212}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 97, 217, 147, 101, 10, 253, 103, 148}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 149, 102, 79, 197, 74, 128, 215, 196}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 155, 203, 7, 4}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 45, 154, 208}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 255, 102, 77, 211, 30, 9, 217, 39}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 200, 20, 238, 143, 239, 123, 208, 161}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 79, 126, 148, 199, 34}, 10}, {{168, 243, 103, 221, 120, 0, 223, 8, 213, 214, 245, 103, 78, 15, 56, 244}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 99, 6, 181, 24, 190, 121, 47, 160}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 197, 114, 118, 253, 180}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 150, 103, 8, 130, 39, 116, 250}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 202, 19, 235, 202, 228, 31, 53, 131}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 10}, {{168, 243, 103, 221, 120, 0, 0, 78, 93, 18, 35, 177, 248, 218, 97, 238}, 10}, {{168, 243, 103, 221, 120, 223, 142, 172, 141, 213, 48, 112, 166, 228, 4, 26}, 10}, {{168, 243, 103, 221, 120, 0, 0, 213, 45, 140, 114, 229, 11, 42, 44, 106}, 10}, {{168, 243, 103, 221, 120, 0, 0, 1, 216, 108, 150, 178, 5, 208, 187, 112}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 121, 150, 18, 6, 31, 108, 51, 138, 47, 14}, 10}, {{168, 243, 103, 221, 120, 0, 0, 7, 116, 239, 124, 147, 180, 157, 157, 153}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 213}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 217, 184, 243}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 108, 72, 64, 235, 180, 219, 200}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 170, 10, 58, 197}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 10}, {{168, 243, 103, 221, 120, 225, 130, 32, 234, 213, 209, 39, 250, 82, 178, 165}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 145, 44, 234, 232}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 110, 174, 145, 112, 195, 81}, 10}, {{168, 243, 103, 221, 120, 0, 131, 53, 213, 249, 152, 229, 212, 8, 37, 22}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 106, 206, 195, 185, 197, 1}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 252, 59, 130, 7, 97, 152, 97, 4}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 10, 73, 93, 170, 252, 220}, 10}, {{168, 243, 103, 221, 120, 0, 236, 133, 106, 230, 3, 12, 219, 129, 174, 143}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 197}, 10}, {{168, 243, 103, 221, 120, 0, 0, 95, 136, 104, 79, 134, 243, 99, 195, 250}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 202, 203, 1, 84}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 197, 242, 184, 97, 231, 233}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 10}, {{168, 243, 103, 221, 120, 0, 0, 97, 60, 149, 217, 89, 225, 140, 170, 69}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 170, 250, 57, 147, 207, 154, 160, 233}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 241}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 200, 24, 106}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 235, 127, 24, 81, 45, 177, 67}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 123}, 10}, {{168, 243, 103, 221, 120, 0, 229, 197, 128, 86, 55, 158, 238, 207, 115, 48}, 10}, {{168, 243, 103, 221, 120, 0, 174, 49, 210, 206, 103, 54, 253, 173, 191, 149}, 10}, {{168, 243, 103, 221, 120, 0, 65, 208, 137, 193, 78, 218, 4, 162, 1, 36}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 46, 17, 138}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 216, 226, 55, 152, 113, 190, 39, 14}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 54, 43, 70, 74, 35, 127}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 50, 8, 126, 246}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 39, 215, 137, 158, 95}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 137, 189, 16, 154, 193, 69, 251}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 133, 122, 169, 159, 135, 234}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 198, 245, 95, 198, 175, 122, 167, 43}, 10}, {{168, 243, 103, 221, 120, 0, 0, 123, 198, 147, 142, 212, 176, 113, 224, 242}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 164, 48, 163}, 10}, {{168, 243, 103, 221, 120, 0, 78, 231, 61, 65, 129, 126, 3, 30, 49, 64}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 23}, 10}, {{168, 243, 103, 221, 120, 0, 0, 146, 186, 76, 64, 114, 3, 42, 112, 41}, 10}, {{168, 243, 103, 221, 120, 0, 82, 163, 96, 200, 166, 164, 255, 16, 88, 107}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 178}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 77, 110, 161, 140, 150}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 240, 168, 110, 219, 119, 228, 190, 50}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 102, 222, 65, 250, 108, 28, 63, 25}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 191, 84, 155, 176, 110, 85}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 186, 164, 107, 250}, 10}, {{168, 243, 103, 221, 120, 125, 194, 131, 18, 32, 199, 232, 169, 139, 52, 238}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 26, 15, 144}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 111, 236, 118, 80, 238, 76}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 141, 163, 197, 17, 22, 106, 48, 236}, 10}, {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 71, 77, 8}, 10}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 98, 182, 12}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 82}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 62, 178, 242, 138, 38, 119, 222}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 7, 242, 33, 42, 242, 181, 41}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 209, 100, 247, 102, 44, 187}, 31}, {{86, 194, 218, 188, 128, 0, 215, 77, 134, 68, 198, 68, 152, 15, 100, 113}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 61, 146, 156, 154, 8, 95, 242, 74}, 31}, {{86, 194, 218, 188, 128, 0, 138, 14, 157, 213, 64, 129, 192, 23, 64, 232}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 34, 188, 89}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 106, 215, 54, 186, 209, 220, 92}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 104, 18, 154}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 175, 64, 130, 52, 129, 173}, 31}, {{86, 194, 218, 188, 128, 0, 0, 254, 190, 48, 14, 125, 99, 25, 187, 236}, 31}, {{86, 194, 218, 188, 128, 0, 217, 142, 231, 129, 56, 232, 170, 103, 168, 227}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 75, 131, 25, 90, 211, 89, 75, 182}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 1, 207, 9}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 91, 99, 88, 242, 165, 8, 148}, 31}, {{86, 194, 218, 188, 128, 0, 35, 71, 117, 223, 212, 37, 128, 14, 161, 102}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 207, 74, 235, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 176, 241, 214, 67, 73, 251}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 249, 219, 84, 195, 213}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 35, 179, 107, 102}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 251, 173, 95, 54, 18, 76, 222}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 155}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 225, 130, 131, 136, 131, 89, 139, 73}, 31}, {{86, 194, 218, 188, 128, 0, 69, 199, 226, 138, 76, 81, 227, 126, 6, 179}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 32, 210, 106, 165}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 80, 175, 214, 144, 59}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 196, 158, 117}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 89, 112, 139}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 239}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 74, 252, 108, 223}, 31}, {{86, 194, 218, 188, 128, 0, 0, 115, 76, 115, 37, 49, 12, 207, 234, 226}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 198, 46, 58, 117, 37, 163, 119, 90}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 232}, 31}, {{86, 194, 218, 188, 128, 0, 236, 154, 179, 10, 171, 140, 13, 79, 166, 140}, 31}, {{86, 194, 218, 188, 128, 0, 0, 55, 145, 111, 125, 138, 71, 124, 33, 105}, 31}, {{86, 194, 218, 188, 128, 192, 122, 242, 163, 203, 54, 136, 36, 3, 249, 217}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 177}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 154, 30, 128}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 116, 20, 91, 189, 216}, 31}, {{86, 194, 218, 188, 128, 0, 0, 179, 96, 33, 36, 149, 14, 59, 86, 49}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 234, 159, 98, 112, 110, 166, 159}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 185, 113, 206, 135, 62, 63}, 31}, {{86, 194, 218, 188, 128, 0, 0, 243, 106, 6, 115, 21, 119, 1, 11, 88}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 90, 219, 42, 86}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 155, 159, 122, 5, 110, 30, 120, 109}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 8}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 69, 109, 140, 66, 49}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 113, 54, 250, 59, 11, 225, 26, 24}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 203, 71, 251, 52, 153}, 31}, {{86, 194, 218, 188, 128, 128, 43, 69, 68, 159, 185, 106, 140, 218, 24, 64}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 197}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 173, 17, 115, 76, 223, 236, 233}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 31}, {{86, 194, 218, 188, 128, 0, 0, 24, 93, 130, 143, 118, 92, 108, 15, 230}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 221, 199, 187, 114, 9, 40, 80}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 244, 83, 211, 203, 34, 108, 26, 14}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 164, 119, 101, 246, 215}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 16, 149, 149}, 31}, {{86, 194, 218, 188, 128, 171, 212, 79, 185, 117, 243, 107, 137, 237, 151, 7}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 210, 208, 139, 26, 3, 73}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 82, 148, 253, 26, 20, 205}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 100, 40, 243, 110, 24, 242, 177, 119}, 31}, {{86, 194, 218, 188, 128, 0, 0, 98, 142, 144, 185, 122, 181, 226, 188, 85}, 31}, {{86, 194, 218, 188, 128, 0, 184, 234, 44, 105, 124, 187, 98, 91, 80, 201}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 184, 34, 66, 63}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 202, 32, 240, 37}, 31}, {{86, 194, 218, 188, 128, 0, 193, 213, 117, 103, 63, 251, 116, 132, 73, 82}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 235, 203, 179, 156}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 195, 155, 228, 206, 44, 182}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 1, 205, 155, 213, 67, 136}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 51, 82, 133, 222}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 47, 168, 105, 24, 117, 247}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 160, 68, 56, 81, 168}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 62, 27, 124}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 206, 219, 171, 183, 232, 129, 87, 48}, 31}, {{86, 194, 218, 188, 128, 0, 133, 112, 205, 106, 6, 28, 93, 222, 22, 183}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 16}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 224, 199, 211}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 225, 82, 254, 67}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{86, 194, 218, 188, 128, 0, 135, 43, 202, 78, 248, 182, 151, 99, 221, 68}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 195, 121, 180, 136, 7, 27}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 38, 107, 10, 45, 190}, 31}, {{86, 194, 218, 188, 128, 0, 0, 136, 86, 135, 76, 11, 1, 131, 19, 6}, 31}, {{86, 194, 218, 188, 128, 0, 0, 237, 135, 248, 152, 141, 106, 164, 78, 239}, 31}, {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 98}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 138, 192}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 171, 129}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 113, 161}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 184, 36}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 154, 78}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 109}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 18, 11}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 61, 129}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 180, 209, 214}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 90}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 59}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 26, 96}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 83, 119}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 196, 213, 186}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 87}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 170}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 68, 54, 242}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 159, 107, 97}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 132}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 7, 161, 11}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 146, 65}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 208, 90}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 67, 63}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 16}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 23, 224}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 58, 197}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 154}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 200, 10, 90}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 88, 85}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 225, 176, 85}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 17}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 218}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 197, 85, 68}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 61}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 223, 207}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 246, 13}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 222, 185, 11}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 38, 202}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 170, 207, 165}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 250, 216, 65}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 172, 41}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 156, 12}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 148}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 70}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 118}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 42}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 115, 84, 138}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 55}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 231}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 10, 195, 12}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 113, 130}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 66, 96}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 71, 229, 220}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 60}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 177}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 157, 3, 142}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 52}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 143, 204, 15}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 152, 176}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 1}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 11}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 137, 40, 202}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 244, 154, 25}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 160}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 115, 189}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 233}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 107}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 130, 112, 87}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 63}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 22, 172, 206}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 53, 74, 75}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 90, 184, 123}, 22}, {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 22}, {{142, 34, 32, 0, 0, 0, 0, 0, 207, 168, 73, 46, 28, 38, 41, 207}, 214}, {{142, 34, 32, 73, 96, 60, 228, 215, 146, 243, 145, 173, 69, 70, 142, 96}, 214}, {{142, 34, 32, 0, 0, 0, 0, 103, 5, 147, 219, 215, 13, 254, 78, 79}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 200, 24, 117, 215, 203, 118, 203, 235}, 214}, {{142, 34, 32, 0, 0, 0, 0, 121, 110, 62, 68, 241, 60, 254, 99, 119}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 110, 26, 175, 121, 50, 123, 83}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 251, 241}, 214}, {{142, 34, 32, 0, 0, 0, 205, 46, 34, 184, 52, 12, 46, 246, 230, 238}, 214}, {{142, 34, 32, 249, 214, 73, 128, 236, 177, 79, 229, 224, 15, 124, 127, 6}, 214}, {{142, 34, 32, 0, 0, 0, 136, 244, 13, 162, 81, 38, 60, 152, 87, 170}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 8, 85, 108, 21, 16, 55}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 76}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 95, 173, 208, 47, 45}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 178, 53}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 127}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 214}, {{142, 34, 32, 0, 0, 0, 134, 36, 56, 200, 137, 177, 14, 107, 112, 179}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 76}, 214}, {{142, 34, 32, 0, 0, 0, 11, 111, 119, 181, 211, 18, 51, 140, 202, 101}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 175, 247, 50, 77, 188, 227, 22, 95}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 117, 64, 201, 155, 217, 111, 244, 250}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 110}, 214}, {{142, 34, 32, 0, 0, 233, 251, 156, 246, 145, 86, 205, 142, 2, 4, 37}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 8, 22, 67, 14, 18, 9}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 135, 222, 60, 150, 150, 183, 226, 142}, 214}, {{142, 34, 32, 124, 219, 241, 240, 201, 75, 8, 177, 65, 77, 124, 242, 157}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 212, 150, 66, 92, 57, 174}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 60, 248, 98, 177, 209, 207, 107, 138}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 214}, {{142, 34, 32, 0, 0, 204, 61, 194, 209, 34, 15, 197, 85, 236, 1, 169}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 183, 52, 214}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 77, 238, 188, 133, 254, 84, 150, 165}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 126, 15, 205}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 205, 54, 212, 4, 223, 167}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 65}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 182, 119, 155, 33, 117, 130, 196}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 0, 57, 36, 252, 23, 144, 211, 153, 44, 43, 180}, 214}, {{142, 34, 32, 0, 30, 204, 162, 168, 136, 122, 219, 56, 10, 46, 240, 43}, 214}, {{142, 34, 32, 0, 0, 19, 246, 203, 12, 14, 141, 210, 237, 183, 183, 178}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 177, 95, 192, 20, 107, 200}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 127, 156, 129, 56, 124, 145}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 52, 150}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 129, 44, 188, 251, 129}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 27, 6, 254}, 214}, {{142, 34, 32, 175, 118, 239, 180, 175, 149, 222, 167, 213, 211, 205, 114, 225}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 62, 13, 9, 164, 200, 144}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 9, 64, 73, 43, 182, 148}, 214}, {{142, 34, 32, 0, 0, 0, 17, 203, 51, 126, 174, 241, 97, 146, 167, 42}, 214}, {{142, 34, 32, 213, 213, 235, 92, 102, 212, 132, 181, 200, 34, 96, 253, 76}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 152, 140, 138, 213, 171, 79, 17, 123, 80, 239, 245, 86}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 93, 254, 81, 194, 194, 239, 195}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 137, 175, 231, 51, 129, 200}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 63, 209, 192, 227, 149, 239}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 84}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 26, 222, 19, 132, 153, 23, 163, 139}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 200, 225, 103, 51, 116, 32, 100}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 84, 151, 80}, 214}, {{142, 34, 32, 0, 0, 0, 0, 84, 198, 195, 63, 109, 254, 34, 197, 251}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 114, 29, 59, 93, 140}, 214}, {{142, 34, 32, 0, 0, 0, 0, 184, 39, 12, 71, 138, 53, 104, 13, 189}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 253, 214, 194, 178, 115, 118, 230}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 24, 133, 92, 93, 150, 39, 79}, 214}, {{142, 34, 32, 0, 238, 104, 82, 191, 57, 231, 129, 191, 219, 75, 96, 117}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 217, 154, 27, 223, 156}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 223}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 127, 152, 63, 168, 174, 7, 123, 233, 149, 238, 137, 231}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 63}, 214}, {{142, 34, 32, 0, 0, 126, 84, 149, 114, 229, 173, 169, 110, 169, 51, 148}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 164, 99, 73, 180, 248, 105, 151, 175}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 67, 171, 104, 144, 174, 99, 2}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 153, 51, 115, 44, 117}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 107, 111}, 214}, {{142, 34, 32, 0, 0, 63, 97, 64, 126, 142, 42, 79, 212, 224, 233, 156}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 254, 50, 79, 88, 84}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 188, 218}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 5, 168}, 214}, {{142, 34, 32, 0, 0, 0, 150, 105, 231, 130, 209, 213, 135, 169, 14, 188}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 13, 130, 193, 70, 175, 55, 140, 98}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 130, 65}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 70, 106, 198, 238, 177, 136}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 160}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 86, 225, 198, 81, 114, 28}, 214}, {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{142, 34, 32, 0, 0, 140, 12, 238, 153, 128, 111, 168, 161, 163, 62, 25}, 214}, {{142, 34, 32, 0, 11, 220, 213, 107, 215, 159, 250, 11, 138, 113, 189, 133}, 214}, {{142, 34, 32, 0, 241, 45, 14, 244, 57, 193, 228, 69, 26, 181, 220, 11}, 214}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 184, 35, 207}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 114, 218, 197, 22, 233, 50, 167}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 126, 90, 174, 27, 10, 145, 114}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 188, 126, 85, 86, 210, 68, 12}, 217}, {{213, 16, 208, 50, 100, 33, 192, 70, 23, 102, 174, 220, 155, 238, 131, 212}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 105, 83, 193, 226, 111, 168, 23}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 98, 243, 216, 201, 127}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 217}, {{213, 16, 208, 50, 100, 33, 192, 111, 228, 134, 90, 22, 158, 86, 183, 225}, 217}, {{213, 16, 208, 50, 100, 33, 192, 220, 190, 158, 162, 244, 121, 189, 140, 57}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 16, 26, 195, 237, 220, 191, 97}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 94, 43, 216, 201, 9, 241, 233}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 86, 38, 183, 19, 145}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 149, 85, 249, 122, 225}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 51, 99, 121}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 169, 68, 40, 54, 31, 132, 109, 25}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 104, 3, 22, 74, 228}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 166, 75, 108, 116, 39, 112, 44, 197}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 104, 103, 229, 135, 140, 44, 102, 118}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 103, 226, 74, 172, 180, 113, 95}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 53, 226, 250, 81, 30}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 54, 225, 148, 146}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 255, 80, 133, 134}, 217}, {{213, 16, 208, 50, 100, 33, 192, 91, 194, 175, 83, 19, 179, 15, 239, 124}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 45, 125, 144, 85, 212}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 235, 205}, 217}, {{213, 16, 208, 50, 100, 33, 192, 3, 119, 91, 39, 220, 205, 117, 165, 47}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 170, 47, 232, 11, 169, 106, 119}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 223, 197, 92, 20}, 217}, {{213, 16, 208, 50, 100, 33, 192, 29, 232, 77, 43, 137, 121, 44, 72, 132}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 145, 37}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 252, 18, 229, 130, 162, 218, 200, 145}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 194, 145, 106, 173, 79, 165, 150}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 100, 204}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 60, 62, 179}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 63, 175, 15, 142, 2, 238, 130}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 38, 146, 134}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 89, 130, 219, 110, 226}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 250, 156, 255, 29, 124, 100}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 56, 92}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 114, 8}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 13, 182, 218, 226}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 219, 240, 202, 35, 95}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 216, 49, 179, 63, 104, 201, 179, 98, 45}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 250, 231}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 7, 234, 223, 150, 171, 166, 57, 191}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 107, 151, 122, 189, 115}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 51, 222, 83, 246, 26}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 135, 55, 11}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 108, 104, 195, 6, 57}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 114, 27, 3}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 117, 234, 83}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 245, 32, 197, 184, 180, 189, 52}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 198, 231, 147}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 76, 62}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 205, 84, 160, 134}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 148, 61}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 196, 49, 13, 12, 107}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 204, 76, 194, 12}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 138, 193, 134}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 28, 185}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 212, 136, 67, 154, 162, 159}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 198, 195, 138}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 155, 221, 88, 234, 184, 216}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 106, 85, 139, 72, 16, 246, 138, 73}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 187, 184, 157, 153}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 35, 239, 185, 205}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 71, 144, 138, 251}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 187, 46}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 171, 155}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 128, 245, 46, 148, 209, 28, 244, 109}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 138, 254, 55, 188, 227, 39, 9}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 71, 93, 218, 74}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 131, 23, 92, 39}, 217}, {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 72, 75}, 217}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 244, 46}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 219, 113, 68}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 97, 164}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 202}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 136, 61}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 250, 99}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 202, 15}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 206}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 74, 203, 198}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 166}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 46, 30}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 2}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 164}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 106, 164}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 243}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 52}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 16}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 141, 137, 234}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 82, 32, 81}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 97}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 118, 16}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 198, 149, 163}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 36, 167, 103}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 253}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 164}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 140}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 103, 137}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 53}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 206, 242}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 190}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 190}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 149, 2}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 149}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 149, 56}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 141, 4}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 163, 37}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 146, 62, 54}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 73, 239, 88}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 45}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 100, 54}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 32}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 30, 165, 205}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 249, 156, 34}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 29, 180, 58}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 140, 72}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 12, 194}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 74, 62, 50}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 46}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 9, 42, 144}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 51}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 75, 101, 231}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 125, 13}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 159, 238}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 18, 114, 97}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 90, 62}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 77}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 34, 17}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 161}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 171, 212, 197}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 198, 255, 187}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 45}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 67, 59}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 93, 89, 242}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 58}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 201}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 66, 143}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 72, 164, 26}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 144, 11}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 211, 32, 199}, 102}, {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 102}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 79, 136}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 169, 106, 196}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 15, 235, 188}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 254, 172}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 120, 131, 157, 85}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 212, 110, 7}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 212, 118, 78, 134, 16}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 46, 184}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 180, 52, 98}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 220}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 143, 246, 58, 12, 145}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 135, 17, 39}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 109, 34, 99}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 9, 23, 99, 162, 29}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 78, 213, 213, 112}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 157, 128, 70}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 175}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 53, 144}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 154, 94, 114, 69}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 205, 115, 216, 81, 213}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 116, 213, 116, 14}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 249}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 230, 7, 242, 79}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 116, 60, 206, 169}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 82, 111, 42}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 45, 106, 100, 97}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 98, 75}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 192}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 197, 103}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 164, 155, 217, 213}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 87, 88, 69, 1, 75}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 80, 253}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 68, 208, 116, 176}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 225, 250, 111, 50, 193}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 34}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 16, 165, 155, 153}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 112, 7, 254, 1}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 17, 145, 192, 172, 126}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 36, 60}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 67, 238, 187, 133, 215}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 20}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 6, 185, 187, 176, 34}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 45, 250}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 148, 139}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 31, 250, 69, 235, 232}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 130}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 120, 225, 52, 76}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 42, 203}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 78, 12, 21, 90, 175}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 49, 11}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 92}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 119, 128}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 162}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 93, 30}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 153, 53, 89, 165}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 134, 95, 211, 111, 119}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 163, 1}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 69, 172}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 79, 204, 18, 160, 252}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 255, 118, 180}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 99, 163, 229, 233, 49}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 23, 128, 104, 160}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 134, 250, 16}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 99, 76, 101, 129, 142}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 1, 210}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 166}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 200, 12, 117}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 208, 107, 127, 30}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 152, 19}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 235, 127, 28, 165}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 182, 124, 51, 9, 229}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 166, 233}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 84, 247, 61, 212, 2}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 250, 29, 123}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 139}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 185, 22, 229, 177}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 160, 176, 31, 201}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 252, 95, 43, 89}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 111}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 134, 181}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 53}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 141}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 126, 194}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 52, 18, 16}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 152}, 169}, {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 243, 144, 145, 190, 217}, 169}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 209, 212, 240, 124, 177, 78, 209}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 139, 66, 11, 66}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 63, 52, 119, 255, 61, 124, 95, 122}, 152}, {{222, 46, 254, 64, 200, 97, 164, 132, 37, 97, 30, 215, 223, 21, 143, 3}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 37, 86, 251, 37, 128}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 114, 23, 242, 54, 135, 55, 182, 143, 177, 185, 96, 150}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 22, 205, 208, 76, 12, 210}, 152}, {{222, 46, 254, 64, 0, 0, 0, 216, 194, 107, 6, 184, 5, 249, 183, 54}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 240, 46, 194, 248}, 152}, {{222, 46, 254, 64, 210, 7, 71, 46, 39, 15, 249, 50, 4, 148, 70, 58}, 152}, {{222, 46, 254, 64, 0, 0, 139, 178, 206, 50, 124, 226, 189, 139, 71, 35}, 152}, {{222, 46, 254, 64, 0, 61, 131, 13, 121, 189, 1, 69, 48, 137, 24, 78}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 19}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 64, 47, 123, 216, 194, 14}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 139, 49, 130, 247, 137}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 28, 208, 197, 179, 58, 130}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 181, 179}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 135, 132, 254, 143}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 140, 217, 171, 14, 233, 149, 166}, 152}, {{222, 46, 254, 64, 0, 0, 207, 226, 57, 189, 218, 37, 75, 227, 145, 211}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 74, 32, 187, 255, 221, 124, 39}, 152}, {{222, 46, 254, 64, 0, 0, 0, 26, 224, 26, 140, 61, 245, 68, 117, 186}, 152}, {{222, 46, 254, 64, 0, 0, 148, 24, 112, 116, 40, 95, 97, 148, 77, 184}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 151, 50, 189, 183, 181, 142, 211, 7}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 184, 239, 203, 210}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 212, 152, 29, 27}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 150, 19, 250, 208, 150, 121, 238}, 152}, {{222, 46, 254, 64, 0, 0, 0, 112, 81, 105, 43, 37, 194, 246, 101, 93}, 152}, {{222, 46, 254, 64, 241, 57, 22, 127, 214, 149, 51, 150, 7, 57, 192, 44}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 206, 157, 129, 137}, 152}, {{222, 46, 254, 64, 0, 0, 252, 193, 44, 58, 41, 20, 174, 38, 2, 86}, 152}, {{222, 46, 254, 64, 0, 0, 0, 85, 113, 59, 37, 202, 104, 252, 174, 190}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 186, 235, 223, 245, 35, 251, 85, 94}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 10, 98, 169, 54, 53, 152, 191, 155}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 198, 144, 190, 87, 246, 68, 168, 176, 52, 1}, 152}, {{222, 46, 254, 64, 0, 0, 0, 69, 218, 171, 112, 141, 171, 122, 33, 255}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 65, 114, 54, 218, 167}, 152}, {{222, 46, 254, 64, 0, 0, 0, 218, 20, 167, 206, 44, 187, 16, 116, 63}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 202, 126, 244, 180, 188, 215}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 58, 28, 207, 246}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 244, 192, 167, 51, 12, 243, 161, 93, 235, 206}, 152}, {{222, 46, 254, 64, 0, 0, 18, 85, 157, 71, 152, 215, 212, 231, 212, 1}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 190, 126, 9, 62}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 223}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 44, 247, 173, 112, 130, 169, 200}, 152}, {{222, 46, 254, 64, 0, 27, 194, 24, 183, 123, 79, 228, 165, 151, 200, 229}, 152}, {{222, 46, 254, 64, 0, 0, 0, 125, 54, 213, 126, 67, 100, 59, 196, 108}, 152}, {{222, 46, 254, 64, 0, 0, 204, 117, 148, 217, 182, 224, 155, 72, 204, 188}, 152}, {{222, 46, 254, 64, 93, 30, 188, 242, 111, 55, 110, 175, 121, 153, 47, 145}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 135, 61}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 228, 204, 188, 190, 194, 6}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 59}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 49, 182, 108, 233, 2, 206}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 146, 176, 135, 1, 124, 21, 48, 34}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 233, 175, 64, 73, 161}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 146, 74}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 226, 201, 44, 49, 231}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 147, 150, 245, 216, 41}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 141}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 251, 4, 22, 200, 156, 91, 32}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 35, 239, 93, 7, 127, 143, 43, 149}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 49, 54, 185, 126, 212, 232, 70, 171}, 152}, {{222, 46, 254, 64, 210, 127, 78, 89, 198, 206, 69, 23, 114, 122, 143, 91}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 122, 56}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 198, 61, 201, 58, 223}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 214}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 61, 183, 230, 113, 35, 203, 112}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 219, 43, 36, 138, 198, 165}, 152}, {{222, 46, 254, 64, 0, 59, 185, 77, 141, 198, 53, 30, 200, 164, 79, 76}, 152}, {{222, 46, 254, 64, 0, 0, 0, 49, 165, 78, 208, 167, 92, 237, 74, 155}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 141}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 10, 186, 76, 139, 207, 223, 60, 120, 35, 206}, 152}, {{222, 46, 254, 64, 0, 0, 0, 163, 247, 128, 252, 49, 212, 139, 246, 187}, 152}, {{222, 46, 254, 64, 0, 0, 82, 205, 242, 8, 187, 41, 154, 68, 237, 47}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 152}, {{222, 46, 254, 64, 0, 0, 173, 66, 107, 169, 188, 94, 214, 208, 182, 64}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 36, 153, 231, 253}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 5, 210, 92, 121, 212, 153, 233, 124}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 116, 31, 33, 126, 62, 230, 76, 5}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 225, 215, 110, 32}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 203, 15, 62, 78, 236, 75, 174, 4}, 152}, {{222, 46, 254, 64, 0, 247, 102, 109, 175, 138, 228, 134, 65, 157, 151, 103}, 152}, {{222, 46, 254, 64, 46, 213, 65, 66, 149, 122, 250, 203, 197, 100, 179, 255}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 96, 239, 227, 57, 5, 89}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 61, 136, 132, 37}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 71, 30, 241, 229, 99, 122, 172}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 157, 67, 174, 0, 38, 130, 247, 94}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 166}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 152}, {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 242, 176, 154, 97}, 152}, {{222, 46, 254, 64, 0, 0, 122, 154, 222, 140, 197, 139, 33, 96, 67, 250}, 152}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 34, 246}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 155, 64}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 179}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 210, 194}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 1}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 237, 40}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 14, 219}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 4, 239}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 80}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 227, 227}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 53, 235}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 217, 120}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 9}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 123}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 32}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 21}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 148, 30}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 80, 22}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 119, 170}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 238}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 255}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 237, 239}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 149, 115}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 81}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 145, 56}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 167}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 58}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 212, 209}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 88}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 122, 144}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 116, 127}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 56, 199}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 61, 193}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 241}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 177}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 98}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 15, 227}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 112, 84}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 94}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 153}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 167, 181}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 187}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 232, 22}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 89}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 238, 39}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 39}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 39, 215, 42}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 153, 107}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 219, 112}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 166}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 206, 103}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 54, 26}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 137}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 24, 79}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 193, 75}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 111}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 57}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 132, 29}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 220, 94, 133}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 119, 252}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 18}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 50, 31}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 79}, 214}, {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 43, 30}, 214}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 33, 188}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 11, 147, 140}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 204, 20, 251}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 178, 191, 97}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 18}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 211, 177}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 173}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 27}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 152}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 181}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 79, 71}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 22}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 197, 197}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 12}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 173, 152}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 122, 239, 80}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 243, 80, 35}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 106}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 211, 122}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 174, 196}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 156}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 145}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 210}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 15}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 250, 11, 246}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 31, 64}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 106, 123}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 18, 164, 150}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 168}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 168, 216}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 209, 45, 112}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 31, 171}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 137, 173}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 107, 250, 184}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 142, 252, 102}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 68, 146}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 115}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 29}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 20}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 128}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 64}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 238, 77, 7}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 72, 43}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 83, 233, 145}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 103}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 56}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 27, 35, 86}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 72}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 47}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 150}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 249}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 52, 217}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 253, 82, 192}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 103}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 39}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 95, 110}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 76, 214}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 13, 16}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 134}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 205}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 115, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 58, 24}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 26}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 95}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 181}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 70, 238}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 64, 98, 254}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 227, 7}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 93, 52, 43}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 110, 92}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 223, 129, 80}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 180}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 77, 233}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 27, 182}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 242}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 59}, 178}, {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 44}, 178}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 67, 238, 159, 134, 155}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 164}, {{237, 229, 203, 8, 121, 176, 200, 148, 11, 242, 251, 175, 199, 82, 127, 212}, 164}, {{237, 229, 203, 8, 121, 176, 161, 193, 217, 194, 152, 57, 135, 21, 165, 166}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 88, 241, 192, 1, 191, 211, 22}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 255, 86, 141, 174, 6}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 10, 168, 83, 151, 44, 243, 238, 33}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 83, 69, 68}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 158, 170, 90}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 112, 51, 48, 118, 127, 88, 39, 116}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 27, 252, 158, 177, 204}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 22, 252, 84, 130, 48, 70, 7, 82}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 79, 141, 250, 106}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 188, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 226, 168, 134, 231, 6, 179, 95}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 164}, {{237, 229, 203, 8, 121, 176, 0, 168, 251, 67, 179, 193, 89, 59, 192, 44}, 164}, {{237, 229, 203, 8, 121, 176, 0, 39, 94, 139, 254, 1, 64, 90, 214, 144}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 144, 199, 125, 58, 203, 116}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 238, 190}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 203, 101, 169, 174, 138, 50, 26}, 164}, {{237, 229, 203, 8, 121, 176, 0, 154, 60, 66, 40, 187, 31, 0, 79, 85}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 132, 13, 189, 248, 194}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 53, 251, 238}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 60, 244, 84, 41, 165, 137}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 86, 221, 251, 213, 159, 202}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 127, 74, 211, 23, 135}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 75, 123, 154, 173, 19}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 204, 140, 57, 21, 113}, 164}, {{237, 229, 203, 8, 121, 176, 0, 36, 163, 121, 105, 254, 57, 70, 208, 92}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 191, 29, 87, 253, 208, 50, 237}, 164}, {{237, 229, 203, 8, 121, 176, 168, 126, 7, 48, 141, 217, 125, 165, 189, 142}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 13, 15}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 204, 125}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 34, 173, 30, 164, 110, 52, 247, 118}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 225, 224, 240}, 164}, {{237, 229, 203, 8, 121, 176, 0, 171, 245, 44, 151, 217, 253, 237, 157, 91}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 246, 151, 126, 20, 171, 83}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 16, 7, 251, 183, 28, 2, 63}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 127, 18, 209, 193, 188}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 187, 246, 27, 24, 114}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 245, 49, 91, 34, 9, 132, 17}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 15, 80, 9, 88, 187, 97, 125, 156}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 193, 131, 127, 231, 135}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 212, 105, 190}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 128, 206, 100, 84, 138, 219, 32, 104}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 54, 93, 171}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 50, 116, 26, 239, 163, 192, 198}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 67, 15, 123, 236, 48, 219}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 43, 14, 57, 153, 208}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 26, 178, 53, 63}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 81, 66, 34, 168, 182}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 232, 241, 187, 16}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 211, 138, 81, 138, 99, 52, 219, 207}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 38, 214, 47, 80, 133}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 165, 33, 49, 234}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 129, 68}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 204, 251}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 59, 179, 251, 184, 60, 95}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 225, 233, 238, 210, 183}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 1, 106, 7, 61, 27, 230, 67, 250}, 164}, {{237, 229, 203, 8, 121, 176, 93, 79, 192, 62, 82, 44, 129, 208, 126, 209}, 164}, {{237, 229, 203, 8, 121, 176, 0, 28, 160, 255, 97, 143, 82, 66, 109, 133}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 174, 172, 89, 137, 8, 161}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 60, 84}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 52, 204, 27, 193, 131, 76}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 87, 251, 94, 98, 78, 245}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 231, 35, 185, 43, 244, 186, 114, 53, 190}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 13, 69, 247, 172}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 190, 226, 55, 180, 204, 156}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 37, 68, 29, 130, 127, 242, 145}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 218, 189, 87, 48}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 138, 96, 231}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 24, 112, 44, 37}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 255, 83, 209, 48, 159, 31, 72, 140}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 160, 74, 254}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 153, 77, 247, 236, 133, 191}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 71, 202}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 117, 244, 205}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 138, 209}, 164}, {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 98, 251, 132, 67, 80, 255}, 164}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 158, 37}, 15}, {{6, 0, 0, 0, 118, 167, 78, 14, 135, 101, 167, 53, 222, 134, 171, 4}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 74, 24}, 15}, {{6, 0, 0, 0, 212, 221, 215, 109, 53, 178, 80, 166, 152, 137, 146, 37}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 145, 176}, 15}, {{6, 0, 207, 144, 236, 75, 134, 246, 210, 81, 41, 67, 110, 201, 153, 75}, 15}, {{6, 0, 0, 0, 94, 102, 103, 171, 114, 160, 214, 1, 74, 49, 154, 250}, 15}, {{6, 0, 0, 0, 177, 198, 162, 40, 91, 114, 130, 167, 75, 109, 107, 151}, 15}, {{6, 0, 0, 0, 0, 246, 68, 162, 94, 21, 113, 168, 62, 242, 44, 43}, 15}, {{6, 0, 0, 0, 0, 97, 68, 147, 2, 227, 93, 37, 48, 192, 132, 135}, 15}, {{6, 0, 0, 0, 0, 36, 1, 71, 6, 79, 133, 215, 158, 164, 169, 132}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 177, 243, 119, 214, 95, 146, 130, 220}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 5, 28, 11, 174, 147, 115, 186, 132}, 15}, {{6, 0, 0, 0, 0, 0, 98, 182, 50, 15, 16, 132, 32, 181, 177, 98}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 8, 170, 192, 38, 212, 56, 28, 253}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 216, 187, 138, 147, 100, 16, 22, 11}, 15}, {{6, 0, 0, 0, 231, 4, 69, 14, 130, 176, 163, 124, 72, 9, 75, 48}, 15}, {{6, 0, 0, 0, 0, 253, 169, 7, 4, 11, 204, 191, 147, 191, 233, 88}, 15}, {{6, 0, 196, 204, 165, 0, 215, 241, 154, 209, 214, 243, 14, 137, 122, 247}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 195, 32, 175, 68, 151, 129, 31, 13}, 15}, {{6, 0, 0, 141, 59, 133, 251, 120, 71, 61, 46, 133, 10, 212, 194, 77}, 15}, {{6, 0, 0, 0, 247, 1, 197, 69, 66, 151, 40, 195, 93, 209, 72, 94}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 245, 174}, 15}, {{6, 0, 0, 0, 0, 159, 160, 85, 140, 112, 107, 62, 102, 57, 245, 213}, 15}, {{6, 0, 0, 0, 0, 81, 235, 60, 75, 40, 108, 37, 7, 93, 32, 60}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 253}, 15}, {{6, 0, 0, 0, 0, 0, 0, 92, 188, 115, 101, 152, 135, 173, 240, 92}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 66, 94, 0, 39, 246, 90, 52, 130}, 15}, {{6, 0, 0, 0, 0, 124, 144, 168, 32, 23, 137, 44, 15, 137, 171, 194}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 176, 13, 153, 34, 50, 123, 13}, 15}, {{6, 0, 0, 0, 0, 0, 0, 156, 232, 194, 46, 127, 121, 14, 121, 11}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 110, 108}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 215, 119}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 10, 209, 129, 134, 209, 212, 122}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 190}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 203, 67, 86, 96, 229}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 214, 80, 127, 145, 163, 109, 70, 98}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 150, 42, 106, 79}, 15}, {{6, 249, 240, 72, 177, 60, 74, 188, 186, 66, 116, 183, 169, 197, 9, 124}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 237, 229, 210, 49, 37}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 64, 113, 95, 102, 216, 89, 216}, 15}, {{6, 0, 222, 144, 72, 64, 24, 219, 139, 76, 71, 106, 14, 181, 13, 80}, 15}, {{6, 0, 0, 0, 51, 168, 25, 255, 196, 217, 123, 66, 93, 92, 60, 193}, 15}, {{6, 0, 0, 0, 134, 44, 158, 67, 208, 125, 151, 228, 21, 66, 229, 97}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 184, 159, 255, 148}, 15}, {{6, 0, 36, 57, 106, 115, 209, 114, 43, 181, 0, 114, 192, 166, 175, 152}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 225, 194}, 15}, {{6, 0, 0, 181, 250, 210, 199, 42, 33, 53, 149, 217, 206, 8, 215, 45}, 15}, {{6, 0, 0, 0, 0, 0, 115, 168, 243, 119, 125, 111, 199, 177, 80, 13}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 77, 40, 40, 49}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 230}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 3, 3, 64, 87, 175}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 250, 40, 199, 46, 123, 122, 228}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 164, 127, 164, 247, 21, 178, 162, 233, 50, 150, 220, 49, 228}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 100}, 15}, {{6, 0, 0, 0, 0, 0, 86, 37, 131, 140, 219, 12, 195, 142, 224, 106}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 15}, {{6, 0, 208, 138, 255, 243, 30, 15, 33, 10, 119, 224, 3, 186, 144, 161}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 20, 150, 207, 152}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 48, 242, 163, 170, 209, 163, 161, 113}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 61}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 133, 233, 1, 252, 206}, 15}, {{6, 0, 0, 85, 121, 175, 59, 41, 51, 21, 206, 156, 18, 86, 174, 69}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 44}, 15}, {{6, 0, 0, 0, 0, 0, 0, 4, 81, 216, 11, 160, 144, 213, 182, 25}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 130}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 217}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 163, 125}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 53}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 226, 65, 115, 224, 158}, 15}, {{6, 0, 0, 0, 0, 0, 48, 251, 62, 82, 216, 0, 111, 244, 19, 68}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 191, 110, 36, 163}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 172}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 169}, 15}, {{6, 0, 0, 0, 242, 216, 54, 253, 66, 242, 236, 236, 104, 23, 246, 9}, 15}, {{6, 0, 0, 0, 0, 164, 220, 86, 39, 202, 223, 219, 90, 102, 185, 247}, 15}, {{6, 150, 171, 110, 109, 29, 120, 170, 168, 208, 98, 127, 177, 64, 38, 159}, 15}, {{6, 0, 0, 0, 0, 46, 105, 130, 13, 124, 105, 146, 172, 73, 112, 102}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 119, 12, 21, 254, 193}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 239, 97, 218, 113, 46, 111}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 191, 89, 124, 143, 5, 99, 36, 168}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 106, 92, 19, 48}, 15}, {{6, 0, 0, 0, 0, 0, 0, 100, 11, 179, 81, 50, 30, 168, 139, 183}, 15}, {{6, 0, 0, 0, 0, 0, 0, 236, 63, 109, 150, 197, 172, 186, 85, 49}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 177, 101, 132, 13, 34, 171, 105, 215}, 15}, {{6, 0, 0, 0, 0, 35, 232, 137, 254, 26, 82, 146, 101, 95, 98, 152}, 15}, {{6, 0, 0, 141, 11, 82, 167, 167, 24, 115, 137, 54, 128, 81, 190, 106}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 58, 182, 145, 216, 230, 62, 210}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 197}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 132}, 15}, {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 195}, 15}, {{6, 0, 0, 0, 0, 0, 88, 190, 219, 226, 52, 84, 244, 137, 104, 200}, 15}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 10, 21}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 205, 151, 218}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 220, 101}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 153, 108, 44, 80, 26, 205}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 182, 102, 87}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 240}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 199, 183, 98}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 69, 139, 203, 254, 19}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 122}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 198, 44, 135}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 207, 90, 146, 187, 234}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 121, 125, 112}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 128, 108, 210, 87}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 15, 190, 224, 64, 218, 5}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 35, 33, 148}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 61, 170, 115, 210}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 140, 83, 189, 84, 41, 114}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 192}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 114, 119}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 152, 251}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 29, 26, 189, 149}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 90, 230, 86, 188, 59, 244}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 223, 230, 93, 147}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 35, 183, 156}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 17, 13, 177}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 76}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 178, 167, 68, 183, 149}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 54, 237, 149, 137}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 19, 197, 233}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 94, 155}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 250, 97, 232, 103, 192}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 74, 199, 146, 18, 110}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 76, 228, 93, 213, 16}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 237, 136}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 223, 167, 195}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 41, 123}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 222}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 22}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 235, 236}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 150, 222, 70, 136}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 79}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 218, 226, 17, 29, 121}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 116, 251, 225, 44, 54, 205}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 46, 169, 92, 99}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 123}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 104, 34, 190, 221}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 201, 125}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 131, 194, 3, 21, 207}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 75, 232}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 69, 232, 228}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 102, 197}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 1, 26, 226, 80, 93, 138}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 144, 13, 12, 111, 89, 147}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 146, 163, 204}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 102, 236}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 119, 63}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 29, 235, 240, 136, 100, 29}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 73}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 219, 24, 124, 90}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 139, 90, 156, 170, 170, 51}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 58, 253, 146, 87, 85}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 226}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 166, 31, 216, 16, 227}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 137}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 43, 236, 249, 81}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 245, 214, 122, 57}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 181, 205, 36, 132, 148}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 82, 127, 177, 157}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 51}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 104, 123, 108, 122}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 89, 175, 109, 52, 123}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 82}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 228, 223, 71, 55, 149, 202}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 111, 132, 173}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 102, 141, 20, 8, 167, 96}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 51, 148, 80, 129}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 128, 161, 34, 237}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 23, 66}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 128, 5, 207, 254}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 138, 220}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 159, 86}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 246, 11, 195}, 94}, {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 245, 97, 203, 244}, 94}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 66, 16, 139}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 186, 57, 13, 50, 172, 151}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 182, 55, 94, 20}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 239, 173}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 13, 206, 213, 189}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 7, 37, 135, 174, 162}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 149, 226, 177, 164, 28}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 119, 107, 83, 117, 111, 234}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 12, 22, 95, 127}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 55, 62, 136, 116, 90, 114, 128}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 39, 119, 130, 5, 91}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 3, 93, 155, 205, 13, 100}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 77, 144, 214, 5, 81, 91}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 41}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 16, 143}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 233, 115, 65, 38}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 137, 141, 123, 233, 194}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 119, 215, 87}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 130, 41, 35, 101, 181, 78}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 235, 20, 104}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 41, 33, 57}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 20, 168}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 80}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 127, 190}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 142}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 180, 112}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 209, 164}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 178, 34, 169, 18, 38}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 157, 119, 176, 255, 0, 154}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 47, 160, 47, 217, 104, 201}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 200, 243}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 117, 254, 203, 200, 116, 44}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 84}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 172, 112, 16}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 44, 42, 73, 67}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 131, 2, 6, 68, 36}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 255, 30}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 236, 189}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 64, 172, 235}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 196, 26, 255, 246, 46, 22}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 189, 41, 202, 138}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 139, 14}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 161, 233}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 231, 252}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 31, 96, 237, 152, 67}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 195}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 9, 171, 181}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 111, 96, 168, 152}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 211, 71, 62, 123, 91, 76}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 97, 60, 169, 109, 4, 159}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 53, 68, 42}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 34, 236, 143, 199, 153}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 242, 208, 121, 218, 102}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 215, 54, 241, 7}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 110, 91, 172, 19, 24, 26, 254}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 165}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 56, 182, 15, 24}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 142, 144}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 127, 134, 71, 12, 133}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 68, 78, 108, 107, 180}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 90, 82, 115}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 21}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 125, 43}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 109, 200, 30, 10}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 52, 237}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 133, 62, 55, 135, 234, 208}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 76, 74, 82, 46, 13, 165, 255}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 196, 163, 98, 209}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 240, 102, 97, 129, 106, 228}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 122, 164, 101, 183, 94}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 173, 207}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 119, 163}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 162}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 72, 104, 192, 165, 96}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 219, 101, 222, 70, 213}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 24, 219}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 252, 64, 158, 59, 88}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 251, 75, 204, 234}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 192, 12, 223}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 157, 222, 45, 232}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 41, 126, 25}, 239}, {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 31, 10, 80, 196, 68, 103}, 239}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 231, 119, 69, 100, 96}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 63, 0, 66, 223, 68}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 223, 66, 3}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 149, 71, 43, 72}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 217, 206, 103}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 23, 172, 141}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 9}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 238, 111, 166, 60, 242}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 185, 149}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 40, 59, 71}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 243, 188, 185, 21}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 199}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 44}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 248, 113, 45, 83, 251}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 156, 118, 158, 251}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 175, 155, 248, 209}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 157, 89, 162, 198, 70}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 126, 84, 100, 134, 254}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 253, 94}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 135, 198, 179, 243}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 44}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 141, 174, 42, 113}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 250, 228, 120, 223, 153, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 153, 9, 30, 156, 21}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 191, 207, 4, 223, 253}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 1}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 243, 4, 153, 75, 250}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 245, 134, 166}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 149}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 237}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 54, 47, 221, 194, 114}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 115, 251, 172, 72}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 131}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 76, 104, 249, 87}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 11, 219, 85, 37}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 224, 85, 151}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 220, 104, 161}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 123, 10}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 31, 95}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 171, 147, 150, 244, 143, 13}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 103, 231, 223}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 193, 121, 120, 145, 81, 118}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 21, 210}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 113, 73, 70, 35}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 182, 75, 86}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 65, 32, 37, 152}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 127, 25, 132, 78, 247}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 161, 230, 31, 49, 153}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 141, 167, 207}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 131, 93}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 60, 250, 69}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 9, 163, 36}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 137}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 125, 14}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 26, 40, 234, 205, 215}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 202, 110}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 186, 144, 253, 191, 87}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 208}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 76, 233}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 27}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 226, 76, 146}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 6, 141, 207, 239, 81, 24}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 102, 110, 202, 94}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 12, 81, 206}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 22, 99, 176, 215}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 10}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 212, 103, 128, 94, 92, 196}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 118, 212, 250, 250, 140}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 33, 82}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 140, 196, 5, 185}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 203, 109, 226, 133, 53, 85}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 91, 51, 237, 29, 136}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 206, 202, 54, 144}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 167, 185, 92, 246}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 128, 114, 75}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 125, 68, 82, 46, 49}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 19, 47, 49, 39, 133, 110}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 136, 191, 59, 200}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 70, 94, 33, 25}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 98, 4, 196}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 195, 219}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 71, 28, 103, 12, 241}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 122}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 178, 28, 197, 38, 115}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 248, 205, 189, 182, 121}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 12, 85, 21, 100}, 82}, {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 11}, 82}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 79, 242}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 218, 152, 12, 12, 251, 5, 186}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 45, 90, 26, 111, 105, 109, 143, 27}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 70, 160, 32, 170}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 205, 75, 152, 208}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 58, 66, 142, 72, 129, 145}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 206, 70, 182, 69, 144, 147, 118, 7}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 69, 229, 99, 160}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 26, 136, 233}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 117, 28, 179, 162}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 48, 193, 183}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 172, 112, 160, 153, 100, 44}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 19, 226, 90, 170, 210, 156}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 170, 42, 200}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 155, 62, 240, 8}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 155, 215, 170, 113, 109, 236}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 202, 18, 248, 91, 53}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 179, 215, 100, 176, 10, 50}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 233, 58, 187, 48, 45, 50, 61}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 212, 162}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 121, 27}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 86, 27, 83}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 129, 213, 88}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 210, 32, 21, 50, 118, 62, 213}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 61, 85, 172, 193, 166, 236, 236}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 252, 114, 146}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 234, 21, 95}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 145, 242, 37, 230, 89, 98}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 42, 98, 238, 78, 253, 192}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 63, 78, 59, 104, 194, 234, 41, 14}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 72, 153}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 193, 162, 226, 81, 63, 94}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 71, 90, 66}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 229, 109}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 247, 6}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 3, 204, 85, 30, 168, 24, 190, 44}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 180, 158, 119, 25, 160, 211}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 181, 240, 85, 26, 123}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 174, 27, 231, 35, 253}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 119, 135, 66, 153, 125, 232, 158, 60}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 199, 12, 91}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 23, 89, 56, 47, 45, 125}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 251, 240, 83}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 232, 160, 124}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 94, 154}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 128, 8, 155, 66, 136}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 235, 33, 25, 102}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 97, 152, 4, 145, 216, 59, 196, 87}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 68, 229, 176, 153, 136, 243, 59, 242}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 127, 83, 5, 251, 139}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 69, 189, 26, 93, 206}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 21, 224, 164, 61, 107, 58}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 62, 14, 176, 97, 89, 174, 87}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 1, 41, 121, 207, 77, 92, 38}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 67, 16, 36, 104, 254, 181}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 192, 86}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 203, 245, 151}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 26, 111, 219, 48}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 156, 208, 46}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 60, 52, 82, 54, 32, 214}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 244, 55, 217}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 112, 127, 169, 17}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 196, 113, 8, 120, 106, 214, 209}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 20, 252, 156, 142, 214}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 175, 115, 102, 117, 168, 171}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 227, 9, 140}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 204, 173}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 206, 70}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 189, 4, 150, 190, 1, 215}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 19, 250, 58, 109, 50, 17}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 214, 13, 214}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 26, 140}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 48, 251, 151, 45}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 229, 146}, 54}, {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 125, 34, 166, 191, 145, 163}, 54}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 235, 182, 162}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 23}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 122, 33}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 65}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 85}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 156, 135, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 228}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 249}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 101, 136}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 231}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 220, 66, 203}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 64}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 229, 86}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 107}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 49, 228}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 134}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 81}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 197}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 24}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 225, 241}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 60, 136}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 137}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 92, 172}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 194, 58}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 149, 174}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 17, 141}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 11, 146}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 91}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 201, 231, 143}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 216, 106}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 18}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 113}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 19}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 218}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 138, 234}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 205, 196}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 6}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 219}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 191, 80}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 207}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 71, 148}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 11, 122}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 46, 172, 168}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 189}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 163, 9, 92}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 100, 223, 145}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 243}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 77}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 190, 207, 222}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 228, 49}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 186, 159, 247}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 249, 54, 85}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 130, 221, 98}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 221, 153, 250}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 199, 84}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 230, 72, 148}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 254, 238}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 187, 59}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 213, 153}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 48, 15, 155}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 52, 123}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 252, 39, 8}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 176, 18}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 230}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 140}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 197, 24}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 185, 69}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 233, 101, 38}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 169, 150, 233}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 97, 255}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 67, 67, 229}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 46, 108}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 31, 242}, 47}, {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 99, 136}, 47}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 133, 176}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 69, 243, 70}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 145, 52, 191, 240, 251}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 213, 183, 44, 240}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 245}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 159}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 191}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 116, 55, 2}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 156}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 83, 157}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 134, 195, 97, 255}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 100, 100, 214, 196, 47}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 240, 184, 250, 166, 43}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 90, 185, 65}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 97, 59, 193}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 226, 81, 205, 144}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 209, 136, 72}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 143, 91, 107, 186}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 89}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 226, 205, 224}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 164, 128}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 151}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 214, 123, 218, 15}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 117, 175}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 170, 113, 172, 11}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 216, 163}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 199, 196}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 110, 94, 230}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 14, 116, 58}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 142}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 229, 112, 166, 130}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 173, 68, 35, 127, 10}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 95, 213, 20}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 138, 22, 58}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 4, 178}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 136, 3, 128}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 6, 211}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 183}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 1, 24, 20}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 249, 15}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 26, 68, 114, 1, 4}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 15, 55}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 144}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 62, 46, 77}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 39}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 151, 202}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 78, 72}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 96}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 52, 160, 210, 90}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 65, 64}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 247, 143, 207}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 81, 131}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 1, 29, 146, 230}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 5, 43, 34, 173, 179}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 43, 110}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 154, 22, 152}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 65, 65}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 172, 246}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 205}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 20}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 116, 145, 173, 43}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 55, 148, 189}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 251, 102}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 83}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 141}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 158, 228, 65, 229}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 84, 62, 166, 88}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 58}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 169, 28, 185, 194, 195}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 61, 32, 113, 154, 99}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 60, 5, 26, 3}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 144, 198, 55, 45}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 180}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 185, 189, 190, 79}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 3, 255, 86}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 195, 60, 183, 222}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 45, 238, 230}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 214}, {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 247}, 214}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 41, 21, 116}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 154, 59, 63, 169, 85, 153}, 215}, {{64, 244, 193, 50, 48, 0, 0, 28, 211, 121, 2, 5, 112, 44, 175, 64}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 4, 60, 161, 3, 72, 151}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 193, 133, 56}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 120, 8, 21, 16, 5, 159, 238}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 204, 251, 17}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 119, 29, 50, 147, 248, 115, 196, 220}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 105, 41, 221, 102, 234, 100}, 215}, {{64, 244, 193, 50, 48, 84, 192, 86, 25, 142, 154, 248, 217, 83, 229, 166}, 215}, {{64, 244, 193, 50, 48, 0, 65, 128, 167, 156, 171, 201, 253, 63, 14, 105}, 215}, {{64, 244, 193, 50, 48, 0, 231, 234, 140, 186, 75, 40, 202, 94, 173, 32}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 186, 106, 131, 32}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 212, 248, 207, 110}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 76, 199, 30, 87, 118}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 233, 53, 36, 79, 212, 229, 52}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 228, 26, 90, 217, 215, 19}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 121, 171, 44, 187}, 215}, {{64, 244, 193, 50, 48, 0, 33, 106, 237, 218, 131, 84, 119, 19, 113, 53}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 128, 50, 94, 112, 224, 94, 65}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 197, 80, 148, 90, 237, 11, 40, 85}, 215}, {{64, 244, 193, 50, 48, 0, 237, 20, 97, 38, 248, 79, 232, 85, 96, 196}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 103}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 122}, 215}, {{64, 244, 193, 50, 48, 0, 189, 107, 10, 172, 24, 4, 124, 73, 246, 66}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 238, 231, 152, 122, 218, 24, 145, 152}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 44, 81, 246, 104, 2, 127, 255, 167, 46, 188, 163}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 168, 29, 62, 50, 222, 220, 29}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 43, 225, 183}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 28, 133, 79, 250}, 215}, {{64, 244, 193, 50, 48, 56, 238, 199, 173, 2, 7, 91, 133, 12, 157, 93}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 96, 116, 153, 68, 39, 84, 173}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 23, 113, 112, 215, 141}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 80, 120, 96}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 111, 29, 75, 25}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 215, 167, 100, 188, 179, 130}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 66, 222, 93, 34, 110, 194, 25, 16}, 215}, {{64, 244, 193, 50, 48, 0, 0, 100, 102, 81, 164, 245, 18, 132, 120, 29}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 168, 114, 48, 105, 41, 148, 246}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 209, 69, 206, 14, 105}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 106, 98, 43, 23, 156, 189, 188}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 161, 91, 83}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 229}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 54, 246, 176, 166, 254, 30, 227}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 229, 127, 10, 51}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 43, 212, 77, 143}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 174, 239, 235, 98, 31, 255, 223}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 24}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 96, 24, 94, 194, 114, 194, 147}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 3, 104, 56, 61, 88, 141}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 104, 117, 49}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 52, 87, 133}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 92, 141, 202, 111, 64}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 63, 141, 211, 148, 181, 109, 110}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 81, 9, 212, 180, 219}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 51, 116, 164}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 250, 202, 40, 150, 24, 54}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 123, 65, 63, 132}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 192, 117, 92, 227, 11, 232}, 215}, {{64, 244, 193, 50, 48, 0, 78, 132, 18, 34, 28, 140, 29, 10, 57, 232}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 143}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 82, 36, 35, 190, 97, 149}, 215}, {{64, 244, 193, 50, 48, 0, 0, 150, 68, 172, 0, 77, 25, 91, 14, 47}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 71, 228, 1, 107, 237, 240}, 215}, {{64, 244, 193, 50, 48, 0, 0, 187, 188, 49, 65, 40, 90, 31, 115, 30}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 83, 25, 2, 145, 192}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 220, 19, 220, 4, 222, 94}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 95, 146, 85, 156, 197, 139}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 16, 236, 5}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 164}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 191, 198, 189, 242, 145}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 104, 100, 233, 155, 36, 123, 182, 109}, 215}, {{64, 244, 193, 50, 48, 0, 0, 151, 180, 167, 41, 113, 99, 139, 77, 200}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 140}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 155, 172, 205, 103, 5}, 215}, {{64, 244, 193, 50, 48, 0, 82, 138, 205, 218, 113, 217, 11, 64, 131, 159}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 15, 78, 156, 35}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 117, 166, 23, 95, 6, 136}, 215}, {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 122, 91, 222, 9, 38}, 215}, {{64, 244, 193, 50, 48, 0, 0, 37, 100, 143, 35, 154, 49, 19, 166, 205}, 215}, {{64, 244, 193, 50, 48, 0, 103, 68, 191, 70, 53, 21, 253, 169, 144, 12}, 215}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 93, 229, 110, 101}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 126, 206, 45}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 45, 165}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 91, 204, 203, 232, 40}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 70, 234}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 109, 185}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 194, 41}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 134}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 169, 88, 75}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 233, 135}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 23, 82}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 57, 111, 242, 114}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 61, 16}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 48}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 12, 17, 123, 111}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 97, 39}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 237, 27}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 31}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 192}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 233, 217, 32, 160}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 158}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 24, 134, 0, 229}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 123, 91, 139}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 112, 221}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 17, 249, 207}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 232, 11, 243}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 174, 129, 130, 236, 64}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 205, 67}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 191}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 130, 228, 247}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 9}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 220, 222}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 62, 20, 190, 218}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 162, 24, 198, 117, 116}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 204}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 172, 88, 253, 166}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 9, 121, 157, 24}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 51, 49}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 148, 193, 82, 92}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 66, 139, 40, 124, 180}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 207, 148, 95, 208}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 58, 63}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 222, 210, 73, 103}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 170}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 67, 236}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 202}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 197}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 199, 31}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 41}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 37, 23}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 110, 86, 85, 53}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 183, 121, 205, 84, 173}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 95}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 192, 135}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 185, 33}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 214, 210, 206}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 154, 136, 222, 81}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 84, 186, 64}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 188, 37}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 89}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 64, 162, 145}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 238}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 93, 167}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 158, 88, 30}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 86, 77, 94, 115, 183}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 208}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 248, 200, 250}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 253, 70, 90, 222}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 203, 148, 245}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 63, 141}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 155, 124}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 20, 211, 126, 111}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 101, 108, 16, 103}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 83, 209}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 100, 112, 114}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 253, 2, 144, 234}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 231, 28}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 184, 96, 166}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 223, 104, 194, 18, 232}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 173, 229, 173}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 146, 45, 205, 240}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 163, 170}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 32, 63, 21, 81}, 153}, {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 219}, 153}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 245}, {{123, 0, 0, 175, 170, 33, 157, 187, 53, 230, 158, 98, 177, 174, 41, 184}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 46, 94}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 146, 70, 106, 155, 207}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 2, 236, 35, 14, 249, 38, 30}, 118}, {{123, 0, 0, 0, 0, 160, 42, 99, 143, 132, 230, 22, 187, 158, 130, 166}, 118}, {{123, 0, 183, 187, 50, 187, 168, 121, 170, 109, 211, 142, 36, 84, 203, 179}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 151}, 118}, {{123, 0, 0, 0, 0, 2, 252, 87, 101, 79, 63, 184, 76, 126, 239, 197}, 118}, {{123, 0, 65, 113, 88, 131, 93, 29, 82, 148, 238, 122, 240, 59, 77, 22}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 254, 210, 26, 188, 63, 67, 24}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 56, 154, 67, 141, 145, 130, 88, 45}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 31, 90, 30, 192, 142, 22, 64, 165, 185}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 129, 29, 48, 184, 103, 74, 230, 41, 32}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 118}, {{123, 0, 0, 0, 0, 0, 238, 239, 109, 204, 252, 167, 206, 16, 213, 95}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 118}, {{123, 0, 0, 0, 0, 159, 136, 251, 24, 240, 183, 80, 214, 80, 82, 180}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 145, 213}, 118}, {{123, 0, 0, 0, 0, 173, 211, 47, 13, 163, 113, 149, 82, 12, 10, 253}, 118}, {{123, 0, 0, 0, 40, 19, 119, 161, 229, 166, 241, 104, 109, 178, 56, 139}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 197, 22, 202, 83}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 51, 157, 94}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 103, 186, 30, 124, 148, 177, 73}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 14, 183, 236, 22, 45, 166, 40, 142}, 118}, {{123, 0, 0, 84, 86, 191, 75, 121, 179, 16, 164, 242, 27, 200, 71, 148}, 118}, {{123, 0, 0, 0, 0, 0, 0, 113, 43, 96, 185, 158, 145, 22, 89, 59}, 118}, {{123, 0, 0, 2, 59, 78, 81, 238, 213, 14, 71, 96, 30, 214, 166, 84}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 129, 10, 255, 59, 245, 147, 17}, 118}, {{123, 0, 0, 0, 0, 0, 0, 15, 42, 213, 131, 250, 5, 133, 19, 166}, 118}, {{123, 0, 0, 0, 0, 204, 7, 106, 35, 194, 44, 170, 130, 185, 71, 231}, 118}, {{123, 0, 0, 0, 0, 43, 243, 230, 234, 237, 150, 244, 31, 205, 243, 237}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 12, 123, 161, 234}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 150, 35, 79, 78, 80, 19, 20, 0}, 118}, {{123, 0, 0, 0, 0, 0, 93, 37, 24, 228, 11, 226, 101, 0, 84, 144}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 95, 247, 208}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 45, 30}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 62, 115, 175, 37, 41, 90, 197, 6}, 118}, {{123, 0, 0, 0, 0, 0, 61, 175, 129, 97, 131, 5, 186, 176, 3, 221}, 118}, {{123, 0, 0, 125, 33, 134, 21, 84, 7, 8, 133, 169, 189, 64, 121, 240}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 217, 144, 194, 179, 152, 162, 241, 27}, 118}, {{123, 0, 0, 0, 0, 0, 203, 161, 239, 53, 69, 29, 113, 24, 148, 98}, 118}, {{123, 0, 0, 0, 0, 140, 39, 208, 79, 237, 123, 37, 230, 201, 212, 190}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 142}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 116, 54, 250}, 118}, {{123, 0, 0, 0, 0, 0, 0, 203, 219, 131, 171, 177, 93, 44, 246, 181}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 16, 6}, 118}, {{123, 0, 0, 0, 0, 0, 0, 77, 88, 235, 31, 195, 243, 162, 118, 34}, 118}, {{123, 0, 0, 0, 0, 0, 0, 85, 83, 118, 254, 69, 15, 207, 14, 208}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 35, 204, 247, 33}, 118}, {{123, 0, 0, 0, 0, 0, 0, 238, 109, 241, 220, 11, 151, 154, 146, 34}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 27, 133, 164, 173, 229, 60, 169}, 118}, {{123, 0, 0, 114, 88, 86, 6, 158, 60, 34, 59, 77, 144, 222, 188, 84}, 118}, {{123, 0, 0, 0, 194, 152, 172, 23, 5, 211, 89, 156, 185, 158, 252, 167}, 118}, {{123, 0, 0, 0, 93, 49, 98, 106, 26, 233, 154, 78, 45, 104, 172, 126}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 97, 238, 251, 116, 81}, 118}, {{123, 0, 0, 0, 235, 238, 18, 38, 156, 245, 15, 68, 199, 205, 125, 230}, 118}, {{123, 0, 0, 0, 0, 0, 0, 216, 247, 233, 30, 240, 250, 222, 24, 135}, 118}, {{123, 0, 0, 151, 211, 254, 149, 209, 93, 142, 175, 190, 129, 251, 121, 11}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 148}, 118}, {{123, 0, 0, 0, 0, 0, 0, 218, 12, 76, 198, 89, 40, 48, 154, 19}, 118}, {{123, 0, 0, 0, 0, 165, 172, 122, 180, 137, 69, 137, 76, 65, 149, 187}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 118}, {{123, 0, 0, 0, 0, 191, 188, 93, 223, 91, 234, 23, 48, 6, 199, 220}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 47, 215, 194, 36, 213, 251, 57, 66, 81, 73, 185, 193, 120, 191}, 118}, {{123, 0, 0, 0, 0, 191, 45, 141, 7, 243, 213, 52, 199, 110, 122, 37}, 118}, {{123, 0, 0, 0, 0, 0, 0, 181, 228, 71, 48, 162, 106, 36, 106, 34}, 118}, {{123, 0, 0, 0, 0, 48, 79, 184, 183, 138, 230, 206, 187, 131, 32, 46}, 118}, {{123, 0, 0, 135, 178, 219, 149, 207, 235, 222, 159, 232, 36, 245, 197, 96}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 223, 99}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 246}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 122}, 118}, {{123, 0, 0, 0, 91, 117, 102, 126, 46, 199, 164, 67, 211, 130, 90, 29}, 118}, {{123, 0, 0, 0, 0, 0, 11, 61, 62, 199, 178, 233, 2, 153, 183, 79}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 160, 188, 136, 26}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 174, 110, 188}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 141, 31}, 118}, {{123, 0, 0, 0, 116, 168, 237, 10, 39, 77, 155, 202, 45, 149, 35, 142}, 118}, {{123, 0, 0, 0, 10, 30, 104, 64, 53, 213, 236, 91, 99, 170, 105, 220}, 118}, {{123, 0, 0, 0, 0, 0, 0, 126, 245, 128, 41, 181, 58, 90, 161, 136}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 227, 34, 196, 62, 78}, 118}, {{123, 0, 0, 200, 145, 201, 34, 126, 17, 148, 176, 121, 223, 45, 231, 55}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 74, 224, 18, 0, 126, 178, 219}, 118}, {{123, 0, 0, 0, 177, 39, 148, 195, 228, 248, 26, 205, 138, 204, 248, 106}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 220}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 215, 125}, 118}, {{123, 0, 0, 0, 245, 67, 13, 104, 163, 206, 79, 200, 161, 156, 114, 37}, 118}, {{123, 0, 0, 0, 150, 157, 223, 13, 251, 188, 108, 120, 113, 225, 109, 27}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 214, 211, 0}, 118}, {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 100, 97}, 118}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 128}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 2, 239}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 98, 185}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 107, 189, 230}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 175, 59, 71}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 22, 109, 9, 235}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 161, 143, 92, 142, 3, 192, 33}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 231}, 7}, {{103, 0, 0, 247, 82, 112, 88, 182, 107, 78, 254, 14, 155, 255, 133, 83}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 119, 134, 93}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 67, 229}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 62, 96, 3}, 7}, {{103, 0, 0, 0, 0, 25, 114, 85, 223, 140, 164, 239, 204, 230, 72, 29}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 150, 128, 114, 6, 53, 74, 70, 128}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 126, 240, 70, 195}, 7}, {{103, 0, 0, 0, 0, 0, 0, 252, 91, 165, 10, 88, 212, 3, 242, 104}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 1, 110, 107}, 7}, {{103, 0, 0, 0, 0, 198, 10, 139, 81, 170, 176, 106, 82, 101, 252, 147}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 159, 130, 88, 35, 153, 118, 4}, 7}, {{103, 0, 0, 179, 53, 214, 204, 179, 244, 143, 64, 242, 59, 121, 234, 2}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 108, 200, 212, 70, 140, 134, 227}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 20, 17}, 7}, {{103, 0, 0, 0, 0, 0, 138, 223, 59, 74, 72, 205, 250, 210, 120, 251}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 0, 0, 168, 38, 131, 177, 18, 112, 213, 169, 183, 116, 90}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 14, 254, 96, 148}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 84, 138}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 182, 232, 176, 210, 240, 7, 14}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 225, 112, 38, 244, 228, 113, 215}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 105, 165, 28}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 88, 202, 133, 253, 81, 53, 244}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 229, 172, 64, 75, 53, 113, 211}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 144, 35, 176, 237, 240, 174, 67, 154}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 159, 220, 141, 148, 73}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 171, 22, 43, 108}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 40, 154, 242, 19}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 44, 60, 249, 245, 28, 146, 181}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 11, 172, 156, 251, 45}, 7}, {{103, 0, 0, 0, 0, 0, 43, 4, 181, 62, 39, 116, 160, 134, 22, 123}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 220, 241, 95, 100, 119}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 75, 127, 251, 177, 97, 163, 142, 156}, 7}, {{103, 0, 0, 0, 0, 0, 0, 150, 138, 61, 4, 36, 219, 73, 194, 141}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 149}, 7}, {{103, 0, 0, 0, 0, 183, 90, 252, 118, 73, 170, 25, 243, 39, 157, 33}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 34}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 224, 15}, 7}, {{103, 0, 0, 0, 0, 0, 127, 147, 148, 98, 107, 106, 129, 209, 227, 80}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 72, 66, 114, 128, 73}, 7}, {{103, 0, 0, 196, 45, 113, 233, 7, 41, 199, 64, 85, 249, 157, 244, 192}, 7}, {{103, 0, 0, 100, 203, 64, 105, 247, 178, 200, 137, 162, 158, 189, 14, 220}, 7}, {{103, 0, 0, 0, 0, 0, 0, 27, 221, 129, 161, 187, 39, 48, 85, 97}, 7}, {{103, 0, 0, 0, 153, 58, 169, 5, 33, 227, 205, 128, 37, 240, 119, 17}, 7}, {{103, 0, 0, 0, 0, 0, 0, 194, 56, 251, 154, 172, 200, 249, 120, 51}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 91, 12, 236, 142, 197, 56, 124, 20, 20, 236, 8, 140, 87, 123}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 109, 168, 0, 161, 158, 227, 221, 225}, 7}, {{103, 0, 0, 207, 118, 122, 58, 101, 150, 86, 220, 77, 223, 32, 238, 51}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 23, 125, 170}, 7}, {{103, 0, 0, 0, 149, 218, 91, 195, 188, 57, 74, 98, 71, 31, 106, 195}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 171, 168, 31, 8}, 7}, {{103, 0, 17, 165, 87, 125, 69, 70, 72, 239, 59, 6, 55, 193, 66, 128}, 7}, {{103, 0, 0, 0, 199, 148, 67, 200, 151, 44, 128, 94, 107, 43, 48, 32}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 16, 4, 74, 243}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 244, 216, 35, 250, 156, 138, 215}, 7}, {{103, 0, 9, 94, 155, 46, 3, 240, 224, 186, 42, 167, 204, 27, 134, 1}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 116, 99, 24, 107, 207, 187, 26, 187}, 7}, {{103, 0, 61, 78, 26, 169, 209, 0, 48, 17, 2, 249, 65, 125, 26, 106}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 84, 163, 63}, 7}, {{103, 0, 0, 237, 11, 11, 168, 161, 179, 45, 92, 45, 167, 48, 1, 50}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 250, 111, 119, 86, 6, 187, 118}, 7}, {{103, 0, 0, 0, 141, 148, 239, 145, 6, 10, 131, 213, 69, 245, 31, 7}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 26}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 41, 93, 90, 4, 23, 208, 57, 19}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 185, 82, 205}, 7}, {{103, 0, 0, 0, 198, 235, 179, 60, 31, 117, 34, 68, 226, 63, 54, 247}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 67, 126, 177}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 191, 53, 69, 127, 28, 27, 39, 22, 194, 60, 80, 202, 45}, 7}, {{103, 0, 0, 0, 0, 0, 79, 0, 178, 243, 91, 103, 204, 255, 86, 188}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 204, 36, 14}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 45}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 152, 182, 86, 239}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 19, 91, 55, 69, 87, 234, 149}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 1, 197, 30, 147, 26, 178, 201, 89}, 7}, {{103, 0, 0, 0, 0, 65, 64, 81, 59, 20, 132, 173, 71, 113, 220, 29}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 109, 234, 92}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 185, 21}, 7}, {{103, 0, 0, 0, 0, 190, 43, 205, 170, 119, 249, 167, 122, 249, 150, 50}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 230, 100, 168, 196}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 24, 215, 53, 250, 114, 45, 108}, 7}, {{103, 0, 0, 200, 89, 253, 14, 224, 61, 105, 225, 228, 52, 68, 89, 164}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 111, 158, 21}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7}, {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 3, 102, 201}, 7}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 222, 109, 243, 172, 173}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 158, 11, 113}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 215, 150, 158, 195, 23}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 72, 166}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 48, 160, 98}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 8, 193, 113, 61, 178}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 224, 251, 12}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 37, 221, 33, 52}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 120, 62, 120}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 76, 196, 80, 255}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 29, 56, 220, 233}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 136}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 78, 36, 74}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 224, 192, 119}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 255, 116, 171, 36}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 189, 1}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 134, 82, 74}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 122, 96}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 152, 33, 149, 137, 235}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 11, 191}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 218, 68}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 43, 197}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 26, 75, 79, 163, 69}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 133, 61, 58, 116}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 176, 230}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 170}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 231, 208}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 222, 160, 251, 157}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 231}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 252, 74, 218, 164}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 19, 16, 107}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 52, 209, 188, 109, 134}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 78, 96}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 75, 47, 116, 240}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 5, 46, 123}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 79}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 235}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 95, 169}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 185, 247}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 215}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 250, 86, 200, 130, 7}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 149, 128, 54}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 206, 89, 218}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 135, 156, 210, 145, 253}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 168}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 71, 116, 92}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 116, 237, 48, 165, 203}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 213, 174, 26, 163, 115}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 21, 80, 1, 240}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 12, 71, 61}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 171, 85, 40}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 84, 161}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 152, 39, 208, 200}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 153}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 146, 198, 32, 248, 120}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 16, 35, 131, 107}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 65}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 200, 222, 26, 28}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 229}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 91, 114}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 238, 87, 144, 14}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 104, 59, 123, 185}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 228, 163, 147, 243, 38}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 21}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 200, 68, 188, 124}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 139, 107, 244, 55}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 87}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 121}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 195, 254, 76}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 117, 161, 115}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 66, 162, 55, 35, 157}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 215, 19, 230, 219, 237}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 78, 168, 180, 218}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 197, 113, 39, 130}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 237, 210, 82, 8, 159}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 1, 183}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 35, 194, 153, 146}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 202, 42, 173, 8, 151}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 178, 1, 100, 28, 232}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 35, 223, 211, 241}, 152}, {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 152}, 152}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 38}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 44}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 8}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 216}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 61}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 136}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 112}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 52}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 124}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 27}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 42}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 215}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 50}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 255}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 250}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 6}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 140}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 83}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 44}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 181}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 201}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 219}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 145}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 57}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 139}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 235}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 17}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 118}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 8}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 129}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 87}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 85}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 16}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 108}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 43}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 94}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 171}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 198}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 67}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 140}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 166}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 34}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 170}, 248}, {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 248}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 244, 156, 211, 116, 234}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 100}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 108, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 209, 134, 227}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 1, 31, 49, 135}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 165, 157, 211}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 11, 181, 238, 175}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 24, 173, 82, 20}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 228, 147, 160, 148}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 135, 35, 233, 79}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 166, 41, 182}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 246, 50}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 49, 166, 202, 133}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 161}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 147}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 236, 86, 162, 16}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 152, 106}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 211, 183, 163}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 84, 63, 255, 10}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 139, 196, 190}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 227, 86, 162}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 16, 154, 84}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 49}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 155}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 124}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 144}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 144}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 235, 37}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 117, 73, 43, 125}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 34}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 101, 191, 108, 159}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 239, 25}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 206, 83, 148, 38, 240}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 248}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 255}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 219, 90, 36}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 112, 136, 124, 141, 2}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 251, 23, 122, 249}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 226, 122, 212}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 62, 113}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 159}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 142, 246, 152, 105}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 210, 30, 31, 169}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 229}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 36}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 165}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 222, 228}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 187, 162}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 104, 229, 187}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 149, 69, 204}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 122, 69, 12, 252}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 5, 26, 103, 12}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 234}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 199, 233, 216, 20}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 152}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 106, 16, 244, 166}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 197, 90, 189}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 153, 24, 105}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 100, 169, 174}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 159, 15, 80, 243, 241}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 187}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 221}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 214, 89, 88, 202}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 120, 178, 71, 163}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 34}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 40, 201, 55, 169}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 173, 229}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 33}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 37, 230}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 248, 163, 74, 234}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 18}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 153, 79, 170}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 143}, {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 128, 119, 181, 120}, 143}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 27, 184, 104, 162, 218, 54, 20}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 233, 244}, 159}, {{250, 86, 233, 184, 0, 0, 88, 85, 45, 158, 227, 9, 134, 111, 137, 16}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 51, 157}, 159}, {{250, 86, 233, 184, 0, 0, 120, 93, 89, 98, 186, 171, 222, 199, 105, 154}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 18, 228}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 144, 121, 22, 135, 86}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 236, 71, 178, 206, 32}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 240, 69}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 159}, {{250, 86, 233, 184, 0, 0, 52, 54, 45, 76, 100, 152, 85, 139, 50, 212}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 205, 29, 99, 50, 225, 38, 245}, 159}, {{250, 86, 233, 184, 0, 0, 48, 63, 43, 203, 54, 150, 141, 59, 103, 23}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 129, 25, 172, 44, 236, 83}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 96, 171, 121, 122}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 119, 64, 6, 241, 78, 69}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 234, 33, 113, 227, 199}, 159}, {{250, 86, 233, 184, 0, 0, 153, 241, 89, 49, 189, 102, 110, 2, 48, 144}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 39, 99, 47, 189, 44, 153}, 159}, {{250, 86, 233, 184, 0, 0, 156, 28, 28, 84, 95, 23, 40, 244, 123, 171}, 159}, {{250, 86, 233, 184, 0, 0, 0, 199, 91, 97, 115, 245, 166, 188, 85, 122}, 159}, {{250, 86, 233, 184, 0, 0, 0, 228, 57, 6, 136, 248, 67, 167, 222, 19}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 223, 223, 91, 209, 212, 182}, 159}, {{250, 86, 233, 184, 0, 0, 46, 120, 194, 187, 200, 6, 250, 189, 202, 43}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 250}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 253, 4, 59, 0, 67, 248, 5, 146}, 159}, {{250, 86, 233, 184, 0, 0, 0, 47, 20, 52, 242, 246, 95, 204, 250, 173}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 198, 188}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 215, 217, 131, 24}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 104, 244, 11, 144}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 251, 57}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 94}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 254, 20}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 239, 197, 156, 185, 104, 209, 245}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 33, 45}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 198, 217, 237, 141, 105}, 159}, {{250, 86, 233, 184, 0, 0, 0, 194, 26, 48, 0, 159, 143, 6, 240, 92}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 156, 188, 104, 43, 163}, 159}, {{250, 86, 233, 184, 0, 99, 185, 127, 125, 192, 75, 87, 143, 228, 71, 92}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 96}, 159}, {{250, 86, 233, 184, 0, 0, 0, 191, 175, 111, 77, 161, 90, 146, 3, 141}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 19}, 159}, {{250, 86, 233, 184, 0, 167, 91, 252, 134, 239, 101, 128, 45, 216, 201, 68}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 235, 184, 107, 82, 192, 198}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 102, 130, 42, 4}, 159}, {{250, 86, 233, 184, 56, 94, 171, 115, 22, 135, 112, 194, 236, 98, 189, 163}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 71, 88, 192, 78, 182, 20, 17, 214}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 56, 172, 23, 128, 254, 14, 224}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 66}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 90, 135}, 159}, {{250, 86, 233, 184, 0, 0, 0, 119, 114, 29, 98, 222, 11, 122, 83, 230}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 222, 219, 0, 112, 243, 93}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 14, 74}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 62, 184, 137, 75, 151, 199, 51}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 152, 70, 26, 50, 182, 158, 252, 15}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 199}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 119, 199, 163, 26, 15, 99, 245, 189}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 34, 58, 170, 151, 230}, 159}, {{250, 86, 233, 184, 98, 129, 219, 240, 118, 22, 167, 154, 198, 104, 5, 86}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 244, 147, 207, 90, 61}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 221}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 163, 108, 65, 249}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 84, 86, 219, 15, 206, 120}, 159}, {{250, 86, 233, 184, 0, 0, 0, 97, 88, 24, 59, 37, 101, 109, 9, 52}, 159}, {{250, 86, 233, 184, 0, 0, 0, 72, 98, 220, 223, 226, 113, 134, 7, 220}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 150, 101, 44, 20, 205, 207}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 208, 156, 114, 52, 125, 195}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 23, 239, 200, 119}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 232, 79}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 114, 84}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 242, 38, 133, 64, 198}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 249, 187}, 159}, {{250, 86, 233, 184, 0, 0, 0, 29, 48, 210, 59, 94, 48, 196, 55, 103}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 232}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 139, 199, 161, 72, 147}, 159}, {{250, 86, 233, 184, 0, 85, 228, 170, 111, 1, 174, 57, 25, 0, 227, 145}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 73, 180, 176, 173}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 98}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 12, 230, 175, 11}, 159}, {{250, 86, 233, 184, 0, 140, 1, 75, 105, 23, 209, 5, 197, 19, 34, 239}, 159}, {{250, 86, 233, 184, 0, 0, 0, 57, 10, 243, 88, 140, 158, 67, 12, 125}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 32, 86, 25, 178}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 225, 205, 188, 242}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159}, {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 15, 255, 136, 197, 14}, 159}, {{122, 222, 2, 0, 0, 0, 251, 40, 77, 38, 137, 10, 190, 11, 211, 250}, 11}, {{122, 222, 2, 0, 0, 56, 59, 230, 5, 135, 216, 120, 19, 231, 69, 18}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 174, 25, 135, 155, 206, 13, 39, 248}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 66, 239, 29, 240, 15, 226, 138, 77}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 172, 228}, 11}, {{122, 222, 2, 0, 0, 0, 199, 57, 30, 217, 74, 128, 87, 237, 4, 139}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 104, 86}, 11}, {{122, 222, 2, 0, 125, 180, 128, 201, 193, 16, 44, 118, 34, 175, 151, 182}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 161, 155, 187, 43, 36, 170, 14, 8}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 48, 111, 210, 204, 168, 137}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 37, 96}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 213, 194, 110}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 73}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 235, 241, 16, 161, 92}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 11}, {{122, 222, 2, 0, 0, 149, 58, 148, 250, 242, 20, 105, 118, 160, 234, 26}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 11}, {{122, 222, 2, 0, 0, 0, 0, 181, 44, 5, 110, 211, 221, 250, 216, 99}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 58, 78, 11}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 80}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 237, 184, 216, 229, 129, 193}, 11}, {{122, 222, 2, 0, 197, 10, 167, 22, 111, 163, 163, 227, 185, 133, 145, 205}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 233, 87, 238, 214, 19, 150, 36, 182}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 40, 146, 145, 13, 7, 167}, 11}, {{122, 222, 2, 0, 15, 151, 197, 101, 108, 94, 173, 30, 244, 239, 195, 160}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 69, 27}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 166, 132}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 33, 132, 17, 58, 191, 251}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 106}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 147, 171, 225, 26, 38, 243, 243}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 237, 147}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 181, 95, 48, 161, 137, 99}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 181, 235, 242, 170, 211, 246}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 132, 86, 101, 195, 3, 187, 12}, 11}, {{122, 222, 2, 0, 0, 17, 3, 195, 126, 115, 112, 145, 102, 245, 144, 249}, 11}, {{122, 222, 2, 0, 0, 188, 115, 68, 114, 164, 76, 110, 153, 121, 249, 236}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 113, 167, 149, 82, 183, 0, 240, 182}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 229, 63, 85, 220, 211, 232, 116, 113}, 11}, {{122, 222, 2, 0, 0, 244, 173, 5, 152, 135, 194, 61, 32, 202, 122, 228}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 11}, {{122, 222, 2, 0, 0, 0, 0, 116, 93, 81, 207, 66, 113, 45, 7, 7}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 177, 224, 191, 142, 28, 242, 90}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 177, 109, 34, 12, 196, 126, 96, 204}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 193, 153, 171, 47, 239}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 180, 181, 23, 81, 226, 160}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 179, 206, 191}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 82, 71, 121}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 55, 125, 51, 226, 125, 168}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 122, 254, 50}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 107, 243, 149, 225, 215, 249}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 136, 232}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 179, 230, 124, 49, 33, 247}, 11}, {{122, 222, 2, 0, 221, 223, 254, 38, 185, 192, 168, 21, 59, 247, 50, 33}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 121}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 6, 158, 195, 207, 138, 187}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 189, 156, 6, 144, 214, 49, 56, 180}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 11}, {{122, 222, 2, 0, 0, 0, 59, 76, 82, 37, 61, 146, 119, 253, 233, 114}, 11}, {{122, 222, 2, 0, 0, 0, 99, 128, 211, 138, 35, 190, 229, 183, 79, 45}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 135}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 22, 211}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 39, 229, 11}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 58, 38}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 29, 148, 161, 128, 69, 203, 242, 178, 62, 117}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 64}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 214, 0, 177}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 110, 8, 234, 111, 172}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 16, 147, 215, 231, 131, 64, 234}, 11}, {{122, 222, 2, 0, 0, 133, 37, 19, 14, 140, 48, 179, 7, 161, 85, 101}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 216, 184, 135, 199, 88}, 11}, {{122, 222, 2, 0, 0, 0, 0, 148, 143, 116, 216, 167, 190, 204, 171, 25}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 219, 162, 31, 137, 151, 202, 0, 106}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 178, 206, 245, 38, 7, 72, 58, 227}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 55, 123, 4, 185, 79, 38, 237, 132}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 143, 93, 198, 238, 9, 167}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 182, 143}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 173, 94, 167, 154, 225, 249, 53, 20}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 192}, 11}, {{122, 222, 2, 0, 0, 109, 120, 24, 28, 154, 150, 189, 120, 246, 204, 251}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 196, 16, 94, 21, 245, 211}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 146}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 11}, {{122, 222, 2, 0, 158, 190, 137, 242, 12, 254, 56, 56, 147, 40, 223, 159}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 127, 207, 63}, 11}, {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 11}, {{122, 222, 2, 0, 0, 0, 0, 178, 21, 15, 17, 126, 206, 185, 6, 133}, 11}, {{122, 222, 2, 0, 0, 124, 192, 172, 86, 15, 184, 162, 92, 102, 4, 240}, 11}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 42, 27, 234, 162, 122}, 110}, {{27, 224, 235, 70, 0, 0, 0, 78, 226, 226, 164, 43, 206, 175, 65, 59}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 134, 147, 168, 187, 12, 28, 52, 22}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 144, 39, 203, 245, 19}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 164, 253, 47, 239, 29}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 73, 155}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 225}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 2, 33, 185, 235, 211}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 29, 133, 21, 91, 94, 82, 229}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 107, 240, 199, 239, 234}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 22, 237, 123, 133, 141}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 218, 152, 253, 249}, 110}, {{27, 224, 235, 70, 0, 0, 0, 88, 146, 198, 181, 244, 132, 97, 26, 237}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 136}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 97, 236, 174, 249}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 36, 117}, 110}, {{27, 224, 235, 70, 0, 0, 187, 214, 101, 229, 38, 72, 165, 144, 98, 185}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 117, 239}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 110}, {{27, 224, 235, 70, 0, 0, 202, 33, 169, 99, 40, 199, 242, 248, 194, 124}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 148, 100, 116, 233}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 68, 172, 135, 2, 218, 63}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 139, 187, 241, 58, 233, 92, 205}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 110, 47, 36, 134, 81}, 110}, {{27, 224, 235, 70, 0, 0, 210, 234, 66, 30, 111, 65, 3, 44, 11, 88}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 233, 157, 211, 113, 153, 56, 53, 93}, 110}, {{27, 224, 235, 70, 0, 0, 127, 93, 244, 194, 104, 63, 74, 27, 207, 237}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 192, 105, 144, 15, 8, 56, 43, 58}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 30, 121}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 202, 109}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 4, 156, 72, 74, 163, 67}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 111}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 213, 63, 74, 49, 128, 178, 86, 202}, 110}, {{27, 224, 235, 70, 0, 0, 0, 132, 33, 139, 83, 208, 176, 91, 121, 146}, 110}, {{27, 224, 235, 70, 0, 0, 246, 228, 43, 82, 52, 190, 245, 64, 194, 209}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 94, 27, 231, 62, 241, 198, 41, 199}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 89, 182}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 135, 230, 241, 143, 101, 65, 94}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 250, 245, 19, 40, 84, 8, 188, 64}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 221, 1, 40, 169, 0, 158, 220, 246}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 54, 30, 37, 138}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 126}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 251, 199, 156, 137, 34, 205, 238, 119, 27, 143, 110}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 205, 20, 189, 18, 223, 214, 255, 177}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 168}, 110}, {{27, 224, 235, 70, 92, 173, 226, 96, 62, 142, 129, 86, 10, 100, 46, 199}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 180, 97, 92, 79, 167, 226, 90, 205}, 110}, {{27, 224, 235, 70, 0, 0, 0, 96, 154, 28, 7, 30, 3, 35, 179, 255}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 80, 178, 161, 31, 136, 252, 46, 137}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 183, 97, 120, 253}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 222}, 110}, {{27, 224, 235, 70, 0, 0, 56, 50, 51, 73, 1, 238, 50, 87, 0, 245}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 16, 41}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 84, 227, 131, 87, 73, 26}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 27, 122, 197, 120, 42, 158, 108, 155}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 157, 172}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 19, 126, 175, 122, 145}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 15, 121, 195, 76, 179, 0}, 110}, {{27, 224, 235, 70, 0, 172, 177, 233, 39, 213, 78, 74, 189, 170, 201, 0}, 110}, {{27, 224, 235, 70, 0, 0, 225, 227, 104, 206, 34, 22, 183, 29, 200, 52}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 17, 51, 201, 138}, 110}, {{27, 224, 235, 70, 0, 0, 208, 66, 95, 243, 246, 215, 118, 203, 227, 58}, 110}, {{27, 224, 235, 70, 0, 0, 202, 226, 44, 234, 180, 254, 140, 160, 104, 240}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 110}, {{27, 224, 235, 70, 0, 0, 0, 97, 13, 207, 196, 40, 138, 209, 44, 194}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 56, 73, 81, 110, 60}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 25, 160, 214, 217, 219, 200, 75, 212}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 229, 20, 146, 23, 255}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 110}, {{27, 224, 235, 70, 0, 0, 225, 14, 18, 185, 114, 216, 143, 8, 131, 95}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 14}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 229, 105}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 4, 146, 86, 148, 239, 100, 28, 47}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 51, 78, 148, 3}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 215, 96, 67, 39, 57}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 126, 181, 189, 200, 226, 111}, 110}, {{27, 224, 235, 70, 0, 0, 0, 114, 198, 191, 214, 45, 197, 215, 9, 131}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 150, 190, 217, 250, 209, 216, 62}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 182, 179}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 99, 191, 235, 78}, 110}, {{27, 224, 235, 70, 0, 253, 7, 80, 142, 94, 96, 84, 244, 199, 243, 169}, 110}, {{27, 224, 235, 70, 0, 0, 0, 234, 29, 130, 65, 55, 96, 78, 201, 24}, 110}, {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 110}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 52, 39}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 99, 63}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 120}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 242, 127}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 218}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 132, 215}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 113, 111}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 66, 130, 241}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 54, 157}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 139, 90, 84}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 109, 8, 108}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 34}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 255, 188}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 122, 26}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 137, 99}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 28, 129, 112}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 9, 184, 243}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 33, 177, 180}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 156}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 94}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 32, 234, 249}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 210}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 161, 223}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 116, 4, 182}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 176}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 231, 90}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 21, 72, 91}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 61, 130, 206}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 12}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 43, 50, 158}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 153, 222, 209}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 141, 213, 206}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 236, 156}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 109}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 21, 196, 163}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 83, 145}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 98, 198}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 111}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 12}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 204, 161, 75}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 72, 103, 211}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 21, 149, 197}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 208}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 193, 43}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 217, 75}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 87, 175}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 141}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 245}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 51, 113, 66}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 1, 21}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 198, 72}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 240, 18}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 212, 37}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 176, 1}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 185, 194}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 207, 146}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 196, 79}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 23, 204, 127}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 28, 172}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 218, 49, 126}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 228}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 102}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 197, 7}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 151, 26, 184}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 156, 234, 19}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 80, 128}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 49, 204, 78}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 213, 37, 251}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 181}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 4}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 128, 100, 148, 44, 8, 10, 194}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 64, 163, 170, 53, 94, 88, 138}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 103, 10, 55, 190, 125, 7}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 12, 168}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 241, 142, 186, 108, 9}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 146, 97, 191, 203, 4, 98}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 8, 27, 13, 21, 108, 100, 129}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 95, 19, 152, 88, 69, 252, 195}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 15, 164}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 97, 171, 212, 148, 92}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 30, 25}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 124, 232}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 196}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 71, 182}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 67, 204, 211, 199, 62}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 60, 78, 244}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 179, 117, 98, 170, 233, 193, 145}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 216, 214}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 99}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 55, 133}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 141, 194, 113, 159, 157, 88, 178}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 243, 226}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 170, 201}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 166, 145}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 158, 183}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 230, 252, 229, 66, 21}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 178, 140}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 133, 12, 165, 238, 185, 158}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 202, 143, 94}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 22, 216, 57, 100, 186, 230, 175}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 178, 214, 119}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 191}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 23, 100}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 218, 92, 52}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 206, 153, 5}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 107, 67, 59}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 110, 86, 59, 167}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 46, 115, 111, 245, 49, 114}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 223, 53, 1, 67, 95}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 177}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 69, 220, 183, 206, 75}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 139, 121, 57, 17}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 244, 156}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 120}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 242, 226, 241, 101, 250, 229, 85}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 234, 55, 165, 24, 176, 134, 50}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 80, 8, 82, 231, 211, 202}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 152, 81, 150, 197, 140, 204}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 198, 131}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 142, 91, 98}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 72, 229}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 6, 100, 199, 246, 39, 218}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 38, 117}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 86, 4}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 24}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 12}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 178, 168, 140}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 66, 29, 201, 46, 186}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 27, 206, 225, 76, 91, 58}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 2, 44, 131}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 132, 81, 44, 94}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 39, 160, 166, 129, 235, 141}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 124, 184, 116, 132}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 57, 86}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 108, 247, 215, 222, 220, 68}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 34, 20, 35, 183}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 210, 235, 155, 135}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 190, 160, 106, 181, 19, 47}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 76, 73, 216, 15, 68, 166}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 234, 193, 190}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 103, 158, 171, 152}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 144, 178, 19, 169, 34}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 187, 247}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 11, 94, 209}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 46, 112, 165}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 249, 9, 115, 206, 66, 125}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 45}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 106, 154, 110, 62, 10}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 248, 58, 29, 199}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 92, 181, 147}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 236}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 59, 187, 72, 104}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 67}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 87, 179, 52, 9}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 86, 44, 134}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 50, 254, 133, 100}, 101}, {{73, 190, 57, 243, 49, 51, 15, 209, 0, 216, 127, 10, 55, 69, 110, 106}, 101}, {{18, 64, 0, 0, 0, 0, 0, 224, 138, 165, 73, 19, 105, 142, 156, 133}, 38}, {{18, 64, 0, 0, 19, 134, 130, 210, 1, 251, 21, 18, 217, 62, 235, 136}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 124, 253, 232, 10, 138, 205, 136}, 38}, {{18, 64, 0, 0, 0, 0, 113, 194, 173, 189, 96, 163, 44, 169, 139, 64}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 187, 197, 198}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 194, 150, 118, 37, 39, 117}, 38}, {{18, 64, 0, 0, 0, 0, 22, 135, 27, 32, 228, 214, 3, 163, 40, 231}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 186, 37, 222, 71}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 12}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 231, 161, 132, 55, 228, 35, 16}, 38}, {{18, 64, 212, 52, 25, 22, 224, 216, 27, 112, 254, 117, 201, 223, 140, 210}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 7, 48, 250, 155, 223, 216, 22, 129}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 74, 47}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 14, 139, 115, 243, 76, 58, 149}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 38}, {{18, 64, 144, 122, 41, 193, 154, 32, 165, 35, 10, 157, 108, 241, 56, 79}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 94, 151, 107, 252, 191, 245, 132}, 38}, {{18, 64, 0, 48, 195, 137, 24, 244, 26, 140, 23, 176, 199, 159, 54, 206}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 72}, 38}, {{18, 64, 0, 0, 0, 202, 211, 53, 43, 181, 80, 5, 6, 26, 169, 119}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 11, 187, 31, 38, 211, 26, 130, 159}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 169, 227, 229, 95, 125, 219, 22, 108}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 30, 58, 166, 76, 229, 232, 216, 30}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 102, 41, 33, 92, 236, 65}, 38}, {{18, 64, 0, 0, 156, 112, 42, 164, 137, 132, 177, 198, 206, 83, 44, 220}, 38}, {{18, 64, 0, 101, 45, 195, 51, 33, 184, 154, 196, 12, 138, 122, 103, 5}, 38}, {{18, 64, 0, 221, 179, 133, 211, 196, 179, 212, 4, 155, 179, 145, 102, 20}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 71, 89, 165, 240, 120, 231}, 38}, {{18, 64, 0, 0, 19, 230, 224, 94, 193, 203, 199, 46, 199, 251, 90, 197}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 43, 38, 102, 81, 19, 227}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 164, 107, 170, 41, 130, 47, 40}, 38}, {{18, 64, 0, 0, 0, 253, 105, 233, 222, 159, 188, 236, 63, 115, 183, 54}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 141, 181, 60}, 38}, {{18, 64, 0, 0, 0, 215, 197, 0, 90, 147, 178, 255, 119, 146, 124, 168}, 38}, {{18, 64, 94, 235, 165, 193, 253, 45, 173, 70, 125, 167, 115, 150, 228, 232}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 184, 190, 59, 122, 2, 111, 47, 91}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 125}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 70, 215, 119, 190, 182, 67, 128}, 38}, {{18, 64, 0, 0, 0, 0, 188, 111, 37, 56, 147, 180, 23, 52, 107, 62}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 200, 246, 32, 135, 150, 202, 71, 120}, 38}, {{18, 64, 0, 0, 231, 54, 143, 198, 187, 25, 215, 20, 188, 136, 147, 115}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 52, 32, 49, 255, 49, 236}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 254, 227}, 38}, {{18, 64, 0, 0, 0, 0, 0, 83, 255, 66, 148, 158, 223, 130, 246, 31}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 135, 103, 16, 177}, 38}, {{18, 64, 0, 0, 141, 254, 3, 50, 212, 184, 17, 79, 121, 6, 182, 0}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 107, 204, 192, 111, 201, 148}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{18, 64, 0, 0, 0, 0, 0, 229, 36, 165, 32, 113, 187, 53, 232, 35}, 38}, {{18, 64, 0, 54, 122, 26, 28, 41, 96, 5, 128, 13, 36, 119, 34, 48}, 38}, {{18, 64, 0, 0, 0, 0, 16, 100, 98, 222, 56, 251, 229, 17, 79, 217}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 149, 6, 160, 86, 203, 12, 44}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 149, 201, 121, 48}, 38}, {{18, 64, 140, 135, 167, 165, 191, 205, 192, 99, 11, 227, 251, 16, 81, 89}, 38}, {{18, 64, 61, 45, 75, 43, 19, 142, 127, 175, 30, 246, 21, 200, 175, 74}, 38}, {{18, 64, 0, 0, 0, 0, 0, 229, 105, 115, 196, 232, 142, 39, 126, 33}, 38}, {{18, 64, 0, 0, 0, 0, 202, 180, 99, 223, 224, 30, 9, 165, 103, 43}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 250, 103, 25, 238, 87, 170, 85}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 85, 154, 238}, 38}, {{18, 64, 0, 0, 0, 0, 0, 50, 161, 248, 105, 173, 245, 51, 243, 1}, 38}, {{18, 64, 213, 8, 1, 197, 54, 171, 117, 253, 197, 141, 180, 195, 241, 73}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 236}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 105, 106}, 38}, {{18, 64, 0, 0, 164, 44, 38, 104, 2, 204, 118, 248, 158, 104, 138, 97}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 67, 33, 99, 76}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 251, 190, 232, 132}, 38}, {{18, 64, 90, 218, 108, 3, 159, 186, 129, 33, 60, 62, 145, 80, 163, 208}, 38}, {{18, 64, 0, 0, 0, 189, 223, 31, 63, 33, 53, 128, 65, 235, 51, 33}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 147, 14, 79}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 3, 141}, 38}, {{18, 64, 0, 0, 0, 0, 0, 67, 239, 18, 68, 131, 199, 132, 142, 222}, 38}, {{18, 64, 0, 0, 0, 0, 0, 99, 133, 30, 163, 160, 199, 57, 17, 204}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 92, 57}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 120, 103, 38}, 38}, {{18, 64, 0, 11, 152, 164, 142, 124, 253, 69, 181, 253, 83, 222, 76, 225}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 54, 201, 241}, 38}, {{18, 64, 0, 12, 152, 249, 89, 120, 160, 104, 143, 164, 236, 12, 142, 186}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 74, 191, 100, 236, 119, 50, 90, 232}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 132, 111, 123, 10, 130, 225, 72, 220}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 38}, {{18, 64, 0, 0, 0, 207, 211, 225, 142, 24, 199, 93, 31, 108, 173, 152}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 187, 40}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 38}, {{18, 64, 0, 42, 76, 57, 237, 234, 84, 0, 80, 182, 195, 250, 227, 156}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 206, 229, 239}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 163, 214, 123, 188, 160, 243, 40}, 38}, {{18, 64, 0, 0, 0, 185, 131, 35, 96, 204, 174, 78, 231, 197, 94, 82}, 38}, {{18, 64, 0, 0, 0, 0, 19, 4, 12, 22, 26, 206, 237, 22, 97, 26}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 61}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 223, 246, 40, 158, 201, 180}, 38}, {{18, 64, 0, 0, 0, 0, 77, 21, 38, 68, 45, 81, 213, 20, 173, 186}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 79, 43, 177}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 15, 127, 59, 46, 182, 200, 10}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 162, 253, 23, 48, 124, 223, 248}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 40}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 213, 112}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 38}, {{18, 64, 0, 0, 0, 0, 0, 0, 160, 226, 160, 80, 46, 140, 169, 113}, 38}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 4, 234, 89}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 16, 76, 172}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 95, 221, 93}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 136, 168, 118, 23, 65}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 108, 27, 157, 235, 105}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 155, 116}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 77, 251, 99}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 242, 120, 134, 41}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 214, 18, 44, 70}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 242}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 223, 76, 22, 38}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 104, 136}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 46, 166, 43, 132}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 250, 160}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 116, 229, 220, 158, 44}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 225, 77}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 98}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 192, 38, 225, 160, 12}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 21}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 120, 130, 193}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 181}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 200}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 162, 111}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 10, 100}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 207}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 46, 214, 212, 149}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 177, 70, 205}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 188, 202, 69}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 16, 153, 185, 121, 61}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 160, 79, 52, 162, 208}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 1, 224, 149}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 139, 184, 180}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 94, 166, 19, 139, 52, 34}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 12, 135}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 24, 215, 184}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 121, 10, 98, 91, 57}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 72, 91, 181}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 44}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 205}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 170, 87, 208}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 181, 166, 153, 184}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 252, 190, 10, 217, 19}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 68, 83, 149, 71, 130, 91}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 196, 168}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 32, 140, 135, 99}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 54, 198, 4}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 234, 159, 77}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 160, 186}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 41}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 38, 42, 93, 207, 27}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 219, 69}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 17, 226, 150, 237, 84}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 105, 19}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 128, 253, 206, 188}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 139, 67, 37}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 172, 152, 195, 115, 225}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 91}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 239}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 134}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 81}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 175}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 98, 228, 224, 219}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 61, 195, 168}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 250, 14, 214}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 97, 27}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 37, 115, 74, 249}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 142, 219, 60, 34, 59}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 10, 240, 115}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 185, 86, 181, 165, 24, 218}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 245}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 57}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 88}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 37, 246}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 74, 226, 181}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 56}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 38, 87, 167, 121, 211}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 86, 14, 156, 161, 174}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 157, 49, 12, 9, 188}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 166, 142, 167, 107, 102, 205}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 57}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 177, 160, 101}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 76, 147}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 93, 47}, 142}, {{200, 48, 0, 215, 60, 135, 167, 30, 10, 245, 60, 223, 78, 32, 184, 210}, 142}, {{200, 48, 0, 0, 0, 0, 0, 239, 217, 164, 45, 164, 46, 131, 147, 150}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 220, 113, 160, 134, 164, 141}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 124, 207, 220, 195}, 142}, {{200, 48, 0, 0, 0, 0, 0, 255, 123, 73, 152, 36, 85, 206, 217, 188}, 142}, {{200, 48, 0, 0, 0, 0, 40, 134, 163, 196, 49, 217, 3, 121, 67, 189}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 154, 121, 109, 199, 58, 95}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 130, 107, 210, 100, 71, 149}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 240, 107, 226, 195}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 16}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 158, 26, 195, 175}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 130, 89, 57, 123, 18, 112}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 70, 53}, 142}, {{200, 48, 0, 0, 161, 167, 46, 154, 107, 14, 227, 85, 18, 8, 31, 31}, 142}, {{200, 48, 0, 80, 146, 39, 160, 176, 118, 98, 151, 88, 131, 108, 160, 91}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 167, 66, 2, 14, 154, 139, 92, 154, 254}, 142}, {{200, 48, 0, 33, 237, 138, 154, 26, 224, 198, 157, 101, 190, 17, 10, 72}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 82, 29, 239}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 229, 157, 175, 252}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 136, 18, 198, 8, 24, 94}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 77, 141, 87, 46, 213, 141}, 142}, {{200, 48, 0, 0, 0, 201, 78, 167, 126, 178, 71, 179, 75, 214, 44, 220}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 9, 37, 213, 28, 34, 54, 193, 114, 182, 57, 151}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 101, 175, 129, 196, 157, 81, 85}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 129, 71, 249, 115, 155, 194, 128}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 184, 90, 60, 92, 100, 109}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 122}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 239, 171, 193, 192, 97, 248}, 142}, {{200, 48, 0, 0, 0, 0, 153, 202, 174, 234, 21, 33, 95, 244, 100, 77}, 142}, {{200, 48, 0, 0, 0, 98, 252, 11, 243, 187, 11, 168, 87, 170, 185, 171}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 34, 146}, 142}, {{200, 48, 0, 0, 0, 0, 253, 145, 213, 9, 231, 103, 166, 70, 27, 110}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 86, 165, 204}, 142}, {{200, 48, 0, 0, 0, 0, 0, 175, 21, 139, 150, 66, 148, 167, 212, 25}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 150, 138, 7, 123}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 188}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 18, 103, 163, 127, 40, 169, 118, 116}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 77, 162, 78, 204, 53, 5, 50}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 147, 26, 77, 221, 124, 25}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 211, 8, 26, 209, 13, 114, 205}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 137, 156, 61, 157, 49, 102}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 165, 16, 30, 235, 158, 178, 45}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 107, 198, 111, 102, 137, 201}, 142}, {{200, 48, 0, 0, 210, 57, 143, 243, 17, 209, 101, 173, 248, 196, 47, 49}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 115, 254}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 75, 251, 70, 234, 92, 56, 132, 184, 131, 175}, 142}, {{200, 48, 0, 0, 0, 0, 0, 52, 221, 111, 12, 115, 22, 216, 7, 201}, 142}, {{200, 48, 0, 67, 222, 178, 22, 228, 100, 75, 234, 209, 130, 26, 253, 110}, 142}, {{200, 48, 0, 0, 0, 0, 0, 101, 218, 102, 180, 39, 139, 25, 122, 181}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 142}, {{200, 48, 0, 0, 0, 0, 0, 208, 59, 59, 59, 180, 116, 86, 100, 170}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 104, 221, 131, 81, 133, 77}, 142}, {{200, 48, 0, 0, 0, 0, 0, 193, 106, 99, 128, 94, 192, 234, 41, 35}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 47, 53}, 142}, {{200, 48, 0, 0, 0, 0, 0, 131, 7, 113, 80, 219, 122, 19, 231, 158}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 12, 191, 142, 2, 104, 138}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 142}, {{200, 48, 0, 0, 255, 169, 112, 122, 27, 152, 243, 63, 203, 213, 92, 249}, 142}, {{200, 48, 0, 0, 82, 89, 157, 167, 49, 170, 14, 243, 191, 191, 205, 190}, 142}, {{200, 48, 0, 160, 99, 62, 207, 123, 9, 248, 143, 239, 47, 188, 245, 25}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 24, 52, 36, 172, 25, 85, 164, 11, 184, 145, 88, 89}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 53, 16, 42, 63, 233, 223}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 58, 234, 20, 150, 115, 38, 116}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 9, 219}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 218, 26}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 26, 167, 205, 17, 225, 220, 7, 121}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 170, 41, 246, 207, 247, 36, 5, 62}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 99}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 66}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 28, 170, 12, 251, 52, 31, 66, 155}, 142}, {{200, 48, 0, 225, 241, 151, 213, 220, 113, 248, 197, 121, 145, 58, 0, 133}, 142}, {{200, 48, 0, 52, 251, 88, 88, 31, 167, 244, 208, 123, 173, 44, 39, 31}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{200, 48, 0, 0, 0, 118, 146, 139, 130, 240, 12, 253, 89, 105, 101, 192}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 142}, {{200, 48, 0, 0, 221, 117, 150, 221, 124, 157, 44, 87, 92, 213, 157, 101}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 218, 59, 149, 139, 150, 144, 127, 21}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 71, 144, 9, 243, 47, 195}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 131}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 89}, 142}, {{200, 48, 0, 0, 244, 182, 253, 102, 109, 245, 31, 19, 70, 104, 209, 246}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 226, 185}, 142}, {{200, 48, 0, 0, 20, 33, 159, 241, 109, 97, 230, 37, 23, 31, 123, 227}, 142}, {{200, 48, 0, 0, 0, 0, 0, 62, 203, 149, 99, 88, 167, 82, 177, 13}, 142}, {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 56}, 142}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 180, 194, 73, 99, 128, 235}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 63, 87, 53}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 111, 171, 157, 33, 35, 36, 39, 99}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 27, 183, 174}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 227, 129, 67}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 240, 154, 203, 225, 117, 100, 247, 142}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 53}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 225, 74, 6, 251, 39, 131}, 184}, {{181, 255, 153, 0, 0, 0, 0, 230, 38, 215, 5, 209, 226, 183, 141, 18}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 184}, {{181, 255, 153, 0, 0, 247, 172, 197, 129, 74, 205, 2, 111, 167, 119, 26}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 185, 254, 184, 131, 252, 159}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 192, 29}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 108, 195, 113, 155, 228}, 184}, {{181, 255, 153, 0, 0, 9, 153, 223, 173, 248, 168, 129, 44, 149, 250, 77}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 180, 7, 141, 77, 196, 24}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 219, 133, 167, 14, 139, 119, 30, 42}, 184}, {{181, 255, 153, 0, 0, 216, 135, 143, 191, 65, 182, 92, 185, 151, 135, 129}, 184}, {{181, 255, 153, 0, 0, 112, 38, 63, 151, 7, 176, 147, 65, 159, 154, 235}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 65, 224, 105, 200, 187, 31, 187, 99}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 205}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 101, 243}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 182, 112, 197, 20, 159, 144}, 184}, {{181, 255, 153, 0, 0, 0, 0, 65, 146, 2, 139, 53, 79, 69, 2, 102}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 171, 167, 203}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 8, 77}, 184}, {{181, 255, 153, 0, 0, 0, 0, 102, 150, 171, 148, 150, 238, 68, 58, 205}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 183}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 162, 120, 29, 216, 105}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{181, 255, 153, 0, 0, 0, 0, 148, 255, 198, 129, 182, 217, 154, 54, 126}, 184}, {{181, 255, 153, 0, 0, 0, 0, 29, 119, 116, 69, 210, 204, 58, 141, 133}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 110, 91, 210, 67, 88, 240, 67}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 184}, {{181, 255, 153, 0, 0, 0, 0, 162, 145, 55, 208, 30, 223, 12, 59, 173}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 110, 221}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 192}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 149, 12, 117, 28, 185, 207}, 184}, {{181, 255, 153, 0, 0, 154, 114, 110, 103, 43, 87, 166, 120, 161, 76, 184}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 1, 154, 161}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 163, 30}, 184}, {{181, 255, 153, 0, 0, 0, 45, 149, 184, 107, 104, 214, 62, 144, 118, 125}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{181, 255, 153, 0, 0, 0, 239, 43, 209, 189, 77, 160, 136, 141, 0, 198}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 158, 232, 111, 156, 112, 196, 8, 13}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 118, 136, 197}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 73, 179, 43}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 96, 63, 45, 66, 189}, 184}, {{181, 255, 153, 0, 0, 0, 0, 74, 201, 225, 162, 239, 68, 6, 177, 217}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 58, 204, 198, 43, 162, 186, 112}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 124, 208, 194}, 184}, {{181, 255, 153, 0, 60, 155, 171, 86, 157, 63, 209, 87, 227, 200, 180, 157}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 134, 100, 52, 229, 3, 4}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 186, 186, 203, 148, 15, 63, 214, 199}, 184}, {{181, 255, 153, 0, 0, 243, 74, 121, 223, 46, 92, 215, 125, 223, 164, 49}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 170, 149, 210, 80, 106, 5, 37, 62}, 184}, {{181, 255, 153, 0, 0, 168, 113, 119, 129, 75, 66, 187, 141, 188, 158, 250}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 118, 74, 128}, 184}, {{181, 255, 153, 0, 0, 0, 187, 96, 166, 108, 53, 155, 157, 139, 19, 243}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 184}, {{181, 255, 153, 0, 0, 16, 65, 189, 248, 154, 251, 101, 152, 19, 144, 39}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 243}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 39, 219, 74, 178, 11}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 241, 32, 22, 1, 177, 46, 96}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 199}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 38}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 243, 11, 224}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 212}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 165, 149}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 253}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 143}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 194, 129, 74, 255, 241, 60, 75}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 58, 22, 223, 167, 87}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 208}, 184}, {{181, 255, 153, 0, 247, 140, 121, 231, 16, 34, 255, 83, 223, 69, 156, 170}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 241, 175}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 184}, {{181, 255, 153, 0, 0, 71, 7, 201, 214, 102, 147, 66, 76, 12, 0, 134}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 147, 115, 249, 208, 164}, 184}, {{181, 255, 153, 0, 0, 222, 207, 39, 121, 66, 111, 5, 26, 236, 133, 14}, 184}, {{181, 255, 153, 0, 40, 50, 125, 219, 182, 245, 22, 119, 136, 39, 38, 172}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 95, 242}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 125, 144, 205}, 184}, {{181, 255, 153, 0, 0, 0, 0, 149, 203, 214, 255, 134, 148, 210, 218, 211}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 126, 56, 216, 56, 2}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 249, 106, 51, 218, 37, 3}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 168, 37, 61, 10, 110, 141}, 184}, {{181, 255, 153, 0, 0, 0, 0, 101, 136, 13, 52, 156, 63, 187, 218, 197}, 184}, {{181, 255, 153, 0, 0, 0, 240, 101, 151, 208, 128, 237, 30, 49, 250, 166}, 184}, {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 244, 74, 106, 137, 174, 196}, 184}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 25}, 91}, {{135, 168, 6, 128, 0, 0, 227, 63, 73, 238, 231, 79, 109, 139, 36, 134}, 91}, {{135, 168, 6, 128, 0, 213, 215, 254, 202, 4, 94, 82, 213, 156, 64, 199}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 227, 172}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 113, 17, 193, 60, 189, 141, 45}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 138, 248, 242, 147, 60}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 3, 103}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 155, 144, 35, 92}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 131, 83, 231, 86, 108, 48}, 91}, {{135, 168, 6, 128, 0, 3, 60, 5, 231, 43, 154, 74, 220, 93, 24, 177}, 91}, {{135, 168, 6, 128, 0, 99, 55, 101, 143, 41, 78, 152, 225, 226, 189, 44}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 202, 163, 67, 167, 201, 253}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 206, 41}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 47, 90, 89, 62, 83}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 196}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 100, 234, 28, 125, 29}, 91}, {{135, 168, 6, 128, 236, 176, 150, 185, 157, 145, 197, 127, 232, 176, 181, 162}, 91}, {{135, 168, 6, 128, 139, 67, 121, 129, 26, 221, 79, 220, 161, 115, 23, 253}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 91}, {{135, 168, 6, 128, 39, 228, 145, 123, 93, 181, 157, 190, 29, 122, 232, 14}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 33, 110, 84, 40, 52}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 241, 62, 129, 255, 47, 166, 250, 227}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 190, 235}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 87, 61, 247, 200, 4}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 196}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 140}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 62, 128}, 91}, {{135, 168, 6, 128, 24, 63, 83, 8, 22, 52, 223, 24, 1, 163, 211, 250}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 145}, 91}, {{135, 168, 6, 128, 0, 255, 29, 46, 150, 176, 172, 133, 187, 92, 8, 193}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 212}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 91}, {{135, 168, 6, 128, 0, 0, 171, 230, 186, 215, 87, 65, 138, 138, 245, 222}, 91}, {{135, 168, 6, 128, 155, 88, 184, 62, 152, 11, 58, 52, 160, 125, 188, 99}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 34}, 91}, {{135, 168, 6, 128, 0, 0, 0, 129, 55, 220, 241, 220, 61, 3, 41, 47}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 28, 230, 49, 25, 114}, 91}, {{135, 168, 6, 128, 0, 227, 182, 232, 28, 240, 194, 181, 51, 188, 36, 62}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 246, 200}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 109, 225, 63, 228, 169, 120, 158, 151, 189}, 91}, {{135, 168, 6, 128, 0, 0, 188, 37, 215, 170, 35, 198, 200, 113, 162, 175}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 207}, 91}, {{135, 168, 6, 128, 0, 0, 0, 253, 6, 97, 125, 82, 11, 239, 252, 8}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 160, 111, 103, 164, 226, 158, 7, 41, 226, 120}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 255, 244, 123, 20, 247, 65}, 91}, {{135, 168, 6, 128, 0, 0, 0, 46, 9, 229, 185, 48, 118, 45, 146, 167}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 14, 235, 168, 220, 152, 212, 124, 241}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 248, 221, 3, 56, 138, 116, 203}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 113, 25, 129, 53}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 93, 67, 48, 152}, 91}, {{135, 168, 6, 128, 0, 0, 254, 151, 176, 122, 246, 9, 163, 232, 9, 106}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 187, 2, 110, 227}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 173, 106, 254, 221, 198, 56, 102, 163}, 91}, {{135, 168, 6, 128, 0, 94, 154, 245, 38, 34, 172, 82, 41, 28, 59, 75}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 41, 68, 143, 219, 194}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 85, 119, 128, 141, 113, 118}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 208, 167, 120, 34, 195}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 68, 79, 104, 195, 103}, 91}, {{135, 168, 6, 128, 0, 78, 18, 68, 161, 141, 24, 123, 154, 93, 125, 149}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 209, 64, 15, 208, 81, 86, 236, 169}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 91}, {{135, 168, 6, 128, 0, 34, 18, 67, 14, 202, 46, 159, 156, 234, 42, 97}, 91}, {{135, 168, 6, 128, 68, 70, 208, 115, 52, 246, 252, 171, 241, 237, 52, 41}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 224}, 91}, {{135, 168, 6, 128, 0, 0, 0, 118, 26, 210, 62, 251, 7, 14, 114, 73}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 236, 132, 72, 204, 240, 85, 157, 49}, 91}, {{135, 168, 6, 128, 0, 0, 0, 134, 218, 97, 228, 143, 52, 199, 81, 149}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 171, 250, 137, 160, 8}, 91}, {{135, 168, 6, 128, 0, 0, 61, 152, 111, 193, 121, 0, 134, 114, 251, 49}, 91}, {{135, 168, 6, 128, 0, 0, 121, 134, 164, 155, 138, 250, 161, 184, 148, 237}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 84, 94, 144, 247, 75, 22}, 91}, {{135, 168, 6, 128, 0, 0, 0, 223, 26, 52, 23, 42, 80, 84, 6, 160}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 23}, 91}, {{135, 168, 6, 128, 0, 72, 25, 46, 135, 213, 227, 223, 186, 114, 162, 24}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 246}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 144, 125, 204, 92, 230, 226, 50, 169}, 91}, {{135, 168, 6, 128, 0, 0, 0, 66, 31, 107, 226, 52, 112, 206, 39, 133}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 50}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 154, 222, 26, 96, 237, 83, 144, 114}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 154}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 19, 158, 5, 246, 132}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 172, 113}, 91}, {{135, 168, 6, 128, 0, 0, 0, 94, 156, 34, 238, 139, 235, 237, 164, 242}, 91}, {{200, 224, 33, 245, 120, 0, 0, 103, 118, 21, 84, 233, 195, 1, 161, 148}, 224}, {{200, 224, 33, 245, 120, 0, 178, 0, 108, 241, 20, 97, 42, 48, 5, 83}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 250, 215, 5, 246, 239}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 152, 12, 202, 45, 211, 120, 66}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 29, 147, 47}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 177, 250, 132, 117, 10, 229}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 7, 125, 104, 162, 46}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 143, 63, 23, 162, 245, 57, 20, 65}, 224}, {{200, 224, 33, 245, 120, 0, 0, 231, 90, 131, 176, 232, 18, 28, 49, 8}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 90, 92, 214, 2, 233, 220, 196, 156}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 25, 40, 161, 93, 228}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 162, 26, 86, 243}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 152, 106, 182, 104, 43, 249, 198, 6}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 157, 11, 217, 40, 21, 119, 122}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 43, 49, 164, 157, 99, 241, 28, 105}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 59}, 224}, {{200, 224, 33, 245, 120, 0, 0, 8, 141, 118, 228, 49, 229, 31, 58, 148}, 224}, {{200, 224, 33, 245, 120, 0, 0, 98, 238, 4, 31, 243, 132, 10, 238, 95}, 224}, {{200, 224, 33, 245, 120, 0, 242, 95, 200, 112, 127, 112, 70, 186, 49, 88}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 184, 14, 222, 195, 76, 49, 29}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 76, 61, 174, 102}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 224}, {{200, 224, 33, 245, 120, 0, 0, 136, 240, 73, 65, 97, 211, 211, 69, 203}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 10, 116, 47, 16, 224, 127}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 15, 28, 74}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 224}, {{200, 224, 33, 245, 120, 0, 0, 117, 55, 162, 191, 198, 0, 207, 75, 239}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 209, 237, 214, 105}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 244, 35, 22, 12, 161}, 224}, {{200, 224, 33, 245, 120, 0, 0, 31, 210, 166, 11, 85, 236, 69, 114, 15}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 4, 114, 45, 79, 93, 208, 56}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 210, 199, 57, 192}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 197, 223, 153, 22, 246}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 179}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 40, 155, 82, 41}, 224}, {{200, 224, 33, 245, 120, 0, 33, 128, 133, 81, 66, 38, 193, 168, 26, 33}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 39}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 254, 32, 73, 31, 90, 9}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 174, 101, 227}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 215, 54, 9, 182, 102, 45}, 224}, {{200, 224, 33, 245, 120, 0, 0, 251, 190, 251, 176, 251, 79, 25, 60, 93}, 224}, {{200, 224, 33, 245, 120, 0, 239, 7, 155, 8, 43, 230, 225, 46, 139, 63}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 166, 202, 116, 84, 29, 52, 96}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 163, 158, 205, 93, 42}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 168, 166, 187, 75, 197, 29, 2}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 30, 119, 208, 128}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 50, 253, 138, 58, 219, 60, 75, 235}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 39, 154, 239, 250, 139, 219, 97, 244}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 176, 156, 121, 207, 84, 48, 0, 200}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 33, 183, 22}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 112, 139, 61, 24, 148, 30, 69, 144}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 66, 83, 197, 97, 161}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 143, 112, 68, 133, 154, 43}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 37}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 188, 5, 29, 226, 96, 232, 176}, 224}, {{200, 224, 33, 245, 120, 0, 0, 134, 93, 108, 187, 107, 84, 1, 6, 208}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 143, 129, 195}, 224}, {{200, 224, 33, 245, 120, 0, 233, 73, 51, 98, 173, 219, 178, 121, 52, 43}, 224}, {{200, 224, 33, 245, 120, 0, 219, 89, 130, 39, 154, 223, 132, 171, 236, 74}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 210, 166, 243}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 20, 214, 216, 234, 129, 158, 88}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 15, 109, 52, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 220, 244, 186}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 49, 68, 182, 193, 146, 197, 195, 51, 57, 42}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 17, 144, 177, 164}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 218}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 204, 249, 173, 175}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 36, 170, 132, 26}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 202, 235, 234, 28, 128, 52, 138, 105}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 153, 125, 228, 30, 7, 203}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 181, 183, 114, 113, 4}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 45, 30, 14}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 84, 1, 38, 143, 160}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 250, 141, 60, 6, 140, 111, 120, 7}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 109, 160, 164, 29, 204, 87, 53, 249}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 127, 87, 141, 236}, 224}, {{200, 224, 33, 245, 120, 0, 210, 90, 201, 58, 103, 108, 161, 169, 254, 0}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 225, 47, 30, 109}, 224}, {{200, 224, 33, 245, 120, 0, 0, 210, 121, 128, 75, 20, 129, 11, 210, 189}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 75, 21, 136}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 198, 223, 37, 168, 182, 201}, 224}, {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 166, 2, 201, 251}, 224}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 239, 137, 189, 245}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 22, 243, 126, 155, 221}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 190, 208}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 221}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 194, 87, 232, 214, 88}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 192, 14}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 49, 118, 43}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 107, 169, 154, 100, 169}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 188, 45, 235, 44, 5, 85}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 132, 38}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 110, 223, 63}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 196, 132, 235, 25, 242}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 129, 241}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 90, 248, 140, 237}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 46}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 247, 161, 199, 70}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 24, 86, 77}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 124, 143, 223, 21, 185, 186}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 100, 190, 232, 16, 128}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 168}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 59, 94, 227}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 77, 184, 45, 206}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 247, 81}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 252, 44, 56, 54, 208}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 243, 133, 214}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 243}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 17, 244, 96}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 79, 14, 132, 34, 72, 122}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 162, 46, 227, 181}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 193}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 252}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 213, 222, 193, 214, 47, 2}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 126, 93, 26, 157, 25}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 197, 157}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 85, 79, 57}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 147}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 138, 101}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 111, 227, 107}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 228}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 191, 210, 98, 173, 212}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 30, 230, 206, 71, 77}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 175, 167, 204}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 38}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 234, 119, 144, 240, 49}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 26, 242, 229}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 57}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 239}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 3, 58, 248, 52, 143}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 41, 99, 8, 227, 154}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 224, 40}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 126}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 132, 235, 6, 26, 94}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 198, 192}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 13, 65}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 102}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 34, 214, 49, 173, 54}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 160, 45, 49, 192, 96}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 222, 172, 197, 21, 219}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 182, 239, 227, 64}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 31, 199, 124}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 18}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 23}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 192, 91, 187}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 79, 137, 184, 119, 103}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 8, 136, 75, 60, 208}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 113, 154, 191, 208, 136}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 186, 72, 60, 37, 52}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 53, 80}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 153, 79, 187, 201, 254}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 32, 11, 235, 102}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 65}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 5, 71, 244, 113, 169}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 188, 216, 139}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 135}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 213, 60, 227, 227, 58}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 64, 102, 140, 111}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 17, 92, 209}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 208}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 201}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 249}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 107}, 114}, {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 114}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 98}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 94}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 153}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 89}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 183}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 115}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 125}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 248}, 184}, {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 184}, {{2, 23, 116, 48, 0, 0, 0, 55, 170, 112, 64, 191, 130, 249, 222, 155}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 97, 152, 35, 67, 92, 14}, 215}, {{2, 23, 116, 48, 0, 0, 191, 235, 175, 130, 135, 94, 111, 136, 206, 50}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 116, 15, 9, 8, 196}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 122}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 215}, {{2, 23, 116, 48, 0, 220, 241, 145, 140, 20, 243, 114, 165, 19, 141, 117}, 215}, {{2, 23, 116, 48, 0, 0, 0, 54, 133, 187, 24, 141, 181, 86, 52, 229}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 130, 171, 34, 51, 11, 56, 133, 9}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 126, 55, 216, 125, 100}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 50, 14, 134, 170, 171, 21}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 97, 114, 217, 238}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 180, 83, 101, 193}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 53, 221, 25, 219, 55}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 61, 95, 53, 105, 6, 119, 195}, 215}, {{2, 23, 116, 48, 0, 0, 198, 117, 218, 236, 24, 183, 15, 18, 166, 194}, 215}, {{2, 23, 116, 48, 0, 16, 63, 41, 94, 223, 216, 192, 205, 174, 205, 209}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 75, 71, 180, 222, 202, 164, 27, 253}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 85, 108}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 187, 41}, 215}, {{2, 23, 116, 48, 0, 47, 195, 242, 35, 137, 185, 203, 109, 229, 112, 105}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 176, 253, 150, 227, 151}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 14, 99, 0, 82, 28, 97}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 79, 149, 135, 98, 57, 129}, 215}, {{2, 23, 116, 48, 0, 0, 0, 181, 90, 253, 104, 116, 132, 155, 12, 147}, 215}, {{2, 23, 116, 48, 0, 0, 0, 71, 107, 78, 185, 61, 5, 124, 107, 166}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 147, 125, 62, 20, 226, 175}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 118, 207, 149, 177, 244, 195, 104}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 103, 239}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 17, 157, 194, 19}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 215}, {{2, 23, 116, 48, 0, 0, 29, 224, 116, 247, 141, 46, 199, 80, 205, 1}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 160, 255, 209, 98}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 15, 224, 213, 235, 1, 191, 208, 157}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 73, 202, 121, 174, 185, 6, 134, 100, 132, 188, 238}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 122, 238, 184, 2, 30, 4, 141}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 62}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 248, 14, 126, 234}, 215}, {{2, 23, 116, 48, 0, 180, 235, 0, 120, 167, 157, 8, 53, 149, 109, 12}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 66, 89, 197, 139, 178}, 215}, {{2, 23, 116, 48, 0, 77, 67, 244, 95, 198, 25, 82, 173, 215, 79, 230}, 215}, {{2, 23, 116, 48, 39, 209, 204, 231, 19, 207, 249, 16, 93, 13, 111, 12}, 215}, {{2, 23, 116, 48, 0, 0, 107, 19, 78, 65, 152, 55, 32, 97, 21, 233}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 97, 210, 171, 86}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 20, 28}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 146, 227, 63, 218, 202, 134}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 176, 19, 164, 201, 102, 156}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 225, 130, 45, 45}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 215}, {{2, 23, 116, 48, 0, 0, 143, 141, 182, 132, 228, 46, 187, 101, 203, 172}, 215}, {{2, 23, 116, 48, 0, 0, 178, 114, 128, 82, 181, 118, 147, 211, 225, 241}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 12, 148, 99, 29, 96, 37, 29}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 213, 250, 203, 104, 40, 168, 42, 135, 18, 43}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 215}, {{2, 23, 116, 48, 0, 0, 206, 251, 222, 135, 205, 165, 107, 113, 36, 52}, 215}, {{2, 23, 116, 48, 0, 0, 81, 236, 152, 198, 79, 164, 144, 135, 243, 106}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 215}, {{2, 23, 116, 48, 0, 8, 229, 237, 78, 6, 174, 147, 217, 17, 215, 115}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 157, 110, 245, 62, 16, 133}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 254, 202}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 243, 133}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 93}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 11, 224, 59, 153, 105, 124, 7}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 215}, {{2, 23, 116, 48, 0, 73, 97, 254, 222, 148, 110, 42, 49, 170, 172, 97}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 222, 189, 236, 27, 136, 237, 35}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 83, 105}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 236, 240, 187, 29, 1, 27, 151, 65}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 83, 240, 160, 181, 187}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 18, 101, 198, 220, 23, 21}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 197, 25}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 82}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 178, 155, 42, 186}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 206, 81, 24, 181}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 38, 24, 111, 230, 239, 31, 125}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 141, 207, 111, 161, 127, 122, 68, 33}, 215}, {{2, 23, 116, 48, 0, 0, 171, 219, 147, 45, 80, 73, 12, 117, 123, 184}, 215}, {{2, 23, 116, 48, 0, 0, 65, 36, 147, 128, 40, 35, 241, 54, 113, 146}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 250, 99, 151, 124, 88, 11, 10, 115}, 215}, {{2, 23, 116, 48, 103, 89, 173, 44, 204, 250, 6, 25, 225, 43, 73, 127}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 29}, 215}, {{2, 23, 116, 48, 0, 82, 248, 72, 147, 48, 187, 132, 53, 159, 204, 80}, 215}, {{2, 23, 116, 48, 0, 0, 109, 136, 147, 47, 45, 101, 17, 16, 244, 3}, 215}, {{2, 23, 116, 48, 0, 0, 74, 18, 100, 210, 149, 234, 200, 179, 29, 9}, 215}, {{2, 23, 116, 48, 0, 0, 0, 134, 162, 242, 248, 241, 188, 66, 35, 239}, 215}, {{2, 23, 116, 48, 0, 41, 148, 74, 110, 74, 22, 31, 18, 253, 176, 222}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 36}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 235, 187, 131, 15}, 215}, {{2, 23, 116, 48, 0, 0, 0, 0, 47, 242, 235, 174, 71, 167, 42, 241}, 215}, {{2, 23, 116, 48, 117, 3, 51, 252, 131, 8, 207, 145, 238, 242, 107, 121}, 215}, {{2, 23, 116, 48, 0, 0, 219, 121, 171, 122, 67, 123, 26, 160, 233, 65}, 215}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 167}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 74, 193, 218, 68}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 163, 194}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 43, 83, 127}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 105}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 231, 43}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 218, 131}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 56, 37, 62}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 27, 152, 112}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 154, 220, 18}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 33, 183, 104}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 196, 210, 17}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 43, 211}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 187, 30, 168}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 113, 77, 3}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 223, 63, 234, 73}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 179, 176, 166, 153}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 22}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 8, 108, 124, 163}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 205, 171, 244}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 34, 125, 80, 220}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 134, 73}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 207, 236, 2, 85}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 66, 95, 182}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 217, 253, 59, 200}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 4, 141, 13}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 200}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 42, 233}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 227}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 40}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 165, 61, 30, 241}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 72, 63}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 240, 49}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 112, 163, 166}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 141}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 44}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 201}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 102, 131}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 94}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 233, 247, 70, 211}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 228, 90, 62, 108}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 49, 98, 125}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 22, 144, 171, 152}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 228}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 177}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 98, 54, 224}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 247, 120, 75}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 5, 235, 4, 75}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 20, 194}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 108, 84, 52}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 34, 51}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 6, 238, 190}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 211, 69, 5}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 131, 222}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 201, 177}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 249, 230, 107}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 155, 139, 104}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 53, 191, 249, 31}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 154}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 180, 125, 151, 245}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 14, 144, 197, 253}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 245, 149}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 23, 161, 157}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 59}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 126, 38}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 8, 184, 116, 123}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 100, 168, 72}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 156, 245}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 59, 21, 164}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 75, 158, 161, 117}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 81, 105, 167}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 235}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 218, 161}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 23, 208}, 233}, {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 155, 125, 98, 228}, 233}, {{32, 141, 196, 0, 0, 0, 0, 0, 107, 237, 98, 205, 234, 133, 205, 102}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 101}, {{32, 141, 196, 0, 0, 0, 204, 106, 95, 54, 41, 13, 228, 108, 191, 233}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 119, 37, 6, 106, 28, 84}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 185, 203, 64, 220, 188, 80, 136}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 232}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 29, 199, 85, 110, 243, 79, 137}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 30, 50, 234, 53, 104, 137, 13}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 221, 192, 217, 87, 223, 79, 51, 253}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 184, 250, 79, 245, 183}, 101}, {{32, 141, 196, 0, 54, 35, 60, 152, 131, 208, 143, 120, 41, 0, 22, 44}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 91, 32}, 101}, {{32, 141, 196, 0, 0, 86, 247, 210, 230, 94, 77, 251, 188, 180, 129, 181}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 220, 152, 24, 192, 51, 204, 161, 58}, 101}, {{32, 141, 196, 0, 0, 0, 0, 240, 42, 32, 108, 165, 236, 253, 232, 199}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 135, 137, 16, 237, 176, 232, 181}, 101}, {{32, 141, 196, 0, 0, 164, 45, 127, 159, 4, 99, 223, 246, 199, 43, 208}, 101}, {{32, 141, 196, 0, 0, 0, 160, 102, 255, 30, 130, 15, 5, 177, 215, 141}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 47}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 88, 88, 43}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 229, 76}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 231, 254, 73, 89, 167}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 22, 16, 55, 111, 25}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 72, 10, 158, 240, 26, 96, 206}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 63, 149, 43, 33, 240, 154, 19, 232}, 101}, {{32, 141, 196, 0, 0, 35, 125, 106, 80, 102, 12, 18, 15, 221, 60, 79}, 101}, {{32, 141, 196, 0, 0, 0, 4, 104, 136, 156, 101, 250, 141, 231, 196, 185}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 222, 230, 175, 138, 202, 227, 117}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 157, 132, 58, 238, 241, 42}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 168}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 35, 15}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 227, 10, 161, 123, 227, 105, 178, 151}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 139, 11, 193, 34, 130, 92, 53}, 101}, {{32, 141, 196, 0, 0, 0, 0, 205, 214, 95, 172, 238, 79, 200, 179, 111}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 244}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 232, 91, 12, 61, 237, 244, 168, 146}, 101}, {{32, 141, 196, 0, 0, 0, 211, 196, 143, 233, 41, 19, 104, 20, 158, 4}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 121, 144, 94, 86, 167, 174}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 24, 200, 240, 202, 115, 95, 140, 142}, 101}, {{32, 141, 196, 0, 0, 0, 0, 222, 187, 234, 90, 137, 73, 91, 254, 48}, 101}, {{32, 141, 196, 0, 0, 0, 229, 199, 33, 12, 112, 232, 127, 224, 243, 38}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 190, 224, 227, 13, 206, 168, 5, 43, 132, 215}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 61, 243}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 98, 23, 236, 181, 49, 202, 212, 121}, 101}, {{32, 141, 196, 0, 0, 50, 221, 203, 148, 219, 21, 126, 170, 117, 107, 213}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 129, 220, 131, 39, 96, 79, 98}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 138}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 110, 217, 183}, 101}, {{32, 141, 196, 0, 0, 92, 150, 179, 213, 204, 206, 142, 65, 7, 19, 110}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 111, 125, 4, 222, 248, 113}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 38, 26, 48, 193, 67, 246, 51, 20}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 224, 60, 125, 39, 136, 122}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 76, 248}, 101}, {{32, 141, 196, 0, 0, 0, 0, 8, 219, 164, 223, 211, 176, 241, 0, 213}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 172, 222, 59, 125, 223, 2, 142, 104}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 9}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 250, 225, 72}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 168}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 194, 233, 79, 1, 83, 131, 5}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 15, 131, 205}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 195, 91, 247, 51, 32, 136}, 101}, {{32, 141, 196, 0, 0, 0, 0, 24, 53, 19, 216, 219, 29, 109, 25, 18}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 56, 159, 221, 162, 107, 66, 62, 91}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 175, 133, 190, 48, 148, 161, 239, 151}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 118, 8, 148, 38, 81, 123, 30}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 101}, {{32, 141, 196, 0, 180, 223, 63, 74, 164, 168, 198, 162, 122, 189, 207, 75}, 101}, {{32, 141, 196, 0, 0, 163, 58, 157, 82, 179, 141, 105, 191, 220, 76, 125}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 93, 4, 93, 19, 91}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 101}, {{32, 141, 196, 0, 0, 0, 100, 8, 55, 51, 247, 218, 243, 103, 204, 34}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 141, 154, 150, 195, 202, 192, 109, 63}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 1}, 101}, {{32, 141, 196, 0, 0, 0, 72, 224, 10, 193, 224, 198, 92, 32, 43, 116}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 165, 255, 120, 184, 89, 46, 249}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 101}, {{32, 141, 196, 0, 0, 0, 124, 162, 223, 48, 122, 68, 72, 73, 8, 144}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 68, 234}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 106, 199, 162, 101, 181}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 182, 88, 49, 211, 55, 92, 123}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 230}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 188, 36, 123, 61, 190, 248, 180}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 207, 228, 125, 46, 104}, 101}, {{32, 141, 196, 0, 0, 0, 94, 119, 47, 43, 225, 38, 186, 247, 92, 248}, 101}, {{32, 141, 196, 0, 0, 36, 40, 153, 10, 173, 68, 105, 201, 97, 198, 117}, 101}, {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 44}, 101}, {{32, 141, 196, 0, 0, 0, 0, 116, 5, 172, 93, 240, 116, 48, 70, 63}, 101}, {{32, 141, 196, 0, 0, 0, 0, 66, 140, 155, 230, 147, 240, 15, 196, 107}, 101}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 133, 31, 83, 132, 96}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 142, 63, 3, 227, 242, 238}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 46, 116}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 215}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 64, 15, 46}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 51, 120, 172}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 126, 108, 93, 55, 131, 250, 209}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 25, 133, 253, 59, 23, 210, 7}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 14, 38, 36, 197, 102}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 198, 171}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 6, 199, 48, 103, 211, 78}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 74, 152}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 165}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 17, 221, 205, 103, 204, 227}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 19, 29, 208, 6, 147, 145}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 132, 30, 222, 48}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 238, 33, 80, 106, 70}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 255, 119}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 174, 133, 143, 166, 152, 81}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 254, 75, 94, 17, 57, 52}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 85, 62, 186}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 125, 170, 162, 190, 166, 158, 224}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 151, 154, 199}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 34, 135, 76}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 215, 97, 156, 178}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 204, 7, 81, 226, 81}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 1, 196, 142, 36, 97, 58, 179}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 232}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 205, 81, 161, 160}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 148, 229, 157, 92, 24}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 225, 94, 60, 106, 99, 154}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 86, 159, 179, 189}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 16, 123, 232, 127, 249}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 129, 135, 226, 164, 151}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 128, 14, 113, 61, 134}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 237}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 194, 9, 111, 189, 247}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 53, 65}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 191, 124, 175, 149}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 235, 249, 138, 55, 30, 198}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 35}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 231, 28, 18, 198, 246, 131, 100}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 52}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 248, 99, 159, 4}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 223, 63}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 133, 207}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 43, 244}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 201}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 5, 102, 73, 118}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 160, 99, 157, 84}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 197, 158, 187, 119, 36}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 250, 52, 51, 73}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 108, 32, 187, 132, 9, 137}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 114, 207, 110, 56, 193}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 86}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 156, 239}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 109}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 216, 82, 138, 78, 47}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 210, 75, 59}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 65, 232, 88, 70}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 220, 57, 94, 142}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 206, 4, 111, 77, 145}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 130}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 111, 166, 77, 94, 58}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 215, 128}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 242, 253, 59, 28}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 14}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 201, 195, 47, 197, 235}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 176}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 217, 84}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 170, 20, 211, 230, 66, 200, 110}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 70, 200, 146, 198, 72}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 172, 185, 194}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 8, 203}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 129, 39, 78, 173}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 67, 177, 163}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 203, 85}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 60}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 156, 71, 4, 158}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 105, 171, 162, 179, 237}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 159, 43}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 216}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 54, 47, 228, 98, 241, 146, 227}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 161, 30, 100, 124}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 139}, {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 181, 104}, 139}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 4}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 192, 249, 239}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 226, 45}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 194}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 124}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 49, 137, 83, 165}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 76, 244, 39, 41}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 69}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 56, 30, 46}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 84}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 78, 76, 186}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 173}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 183, 10, 141, 172}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 250, 32, 231, 88}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 162, 78, 25}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 113}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 101}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 11, 112, 144, 107, 205}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 201}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 165}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 129, 13}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 48, 48, 235, 238}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 134, 149}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 121, 0, 255, 166}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 179, 147}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 227, 104, 23}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 220, 181, 82, 234}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 6, 177, 253, 174, 247}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 108}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 230, 197}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 250, 77}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 198, 245}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 220, 187, 7, 6}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 79}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 41, 56, 180}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 168, 187, 249, 254, 3}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 110, 109, 53, 239}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 230, 135, 248, 142, 38}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 98, 201, 228, 132}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 250, 43}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 155, 160, 24, 214, 146}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 135, 105}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 102, 201, 58, 1}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 100, 93, 37}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 30, 156, 130}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 236, 179, 20, 155}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 205, 21}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 224, 122, 153, 151}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 202}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 227}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 69, 244}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 106, 226, 254}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 101, 211}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 3, 184, 245, 223}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 252, 228, 48, 116}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 44, 71, 53, 39, 163, 92}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 222}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 248, 124, 208, 72}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 149}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 93, 23}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 110, 29, 60}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 108, 144, 215, 120}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 90, 133}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 111, 50, 52, 34, 15}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 14, 215, 194, 151, 157}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 41}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 245, 215, 185, 156, 216}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 185, 192, 1}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 11, 199}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 211, 78, 109}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 33, 235, 65, 122}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 238, 29}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 70, 87, 242, 96, 188}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 151, 133}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 73, 69, 80, 78}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 250, 34, 205, 74}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 220, 67, 220, 97, 225, 209}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 44, 54, 77, 216, 153}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 53, 216, 171, 177, 198}, 32}, {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 58, 38, 195, 44, 172}, 32}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 207, 163, 232, 144, 118}, 57}, {{95, 113, 12, 123, 0, 0, 219, 26, 214, 53, 168, 170, 157, 244, 24, 77}, 57}, {{95, 113, 12, 123, 0, 74, 177, 72, 87, 104, 179, 254, 242, 202, 102, 179}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 135, 192}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 57}, {{95, 113, 12, 123, 0, 0, 78, 146, 135, 234, 40, 183, 33, 158, 41, 139}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 58, 146}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 0, 0, 143, 41, 191, 189, 79, 98, 205, 38, 19}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 0, 0, 143, 0, 82, 187, 118, 135, 2, 3, 209}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 157, 204, 229, 239, 24}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 163, 152, 222, 20}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 48, 56, 11, 135, 200, 89, 81}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 255, 71, 254, 179}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 217, 152, 17, 23, 237}, 57}, {{95, 113, 12, 123, 0, 7, 83, 175, 78, 107, 183, 184, 128, 17, 25, 53}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 203, 88, 128, 110, 53}, 57}, {{95, 113, 12, 123, 0, 0, 4, 63, 248, 36, 138, 221, 179, 11, 189, 97}, 57}, {{95, 113, 12, 123, 0, 0, 0, 211, 212, 205, 110, 155, 248, 166, 157, 252}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 202, 35, 132, 192, 61}, 57}, {{95, 113, 12, 123, 0, 0, 0, 167, 9, 229, 56, 166, 70, 129, 253, 66}, 57}, {{95, 113, 12, 123, 0, 0, 0, 65, 150, 143, 149, 31, 208, 3, 236, 157}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 140, 91, 113, 167, 93, 159}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 215, 182, 195, 198, 58, 108, 181}, 57}, {{95, 113, 12, 123, 0, 0, 157, 87, 109, 240, 120, 221, 30, 134, 210, 44}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 11, 67, 126, 136, 206, 53, 199}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 46, 154, 38, 204, 131, 71, 215}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 55, 179, 110, 238, 228, 20, 97, 23}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 47, 187, 79, 49, 22, 42}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 34, 210, 239, 82, 217, 130, 91}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 167, 240, 59, 197, 166}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 66, 55, 96, 224, 190, 94, 165}, 57}, {{95, 113, 12, 123, 0, 0, 0, 205, 85, 244, 198, 192, 51, 68, 20, 232}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 202}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 3, 68, 3, 49, 151, 13, 165}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 190, 223, 147, 21, 255, 145, 149, 114}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 101, 20, 81, 192}, 57}, {{95, 113, 12, 123, 0, 0, 0, 71, 9, 16, 237, 31, 198, 168, 136, 216}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 222, 170, 123, 7, 64, 8, 43, 29}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 88, 45, 12, 193, 203, 54, 181}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 135, 33, 174, 192, 204, 103, 223}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 229}, 57}, {{95, 113, 12, 123, 0, 62, 157, 164, 234, 153, 90, 241, 131, 135, 29, 134}, 57}, {{95, 113, 12, 123, 0, 0, 0, 176, 60, 187, 122, 167, 91, 46, 242, 136}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 136, 92, 21, 176}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 202, 174, 43, 63, 14, 204}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 29}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 57}, {{95, 113, 12, 123, 0, 46, 33, 63, 64, 170, 68, 245, 104, 70, 163, 130}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 69, 134, 68, 191, 138}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 142, 221}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 83, 89}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 81, 222, 56, 37, 159, 156, 14, 3}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 210, 170}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 154, 249, 248, 50, 202}, 57}, {{95, 113, 12, 123, 0, 50, 198, 129, 238, 14, 61, 68, 98, 236, 38, 60}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 87, 182, 106, 98}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 79, 91}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 163}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 174, 9}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 61, 221, 248, 156, 60}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 252, 194, 235, 19, 240}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 235, 209, 6, 243, 251}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 159, 178, 181, 36, 172, 168}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 226, 131, 16, 124, 210}, 57}, {{95, 113, 12, 123, 0, 0, 0, 122, 104, 134, 98, 250, 193, 168, 193, 89}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 91, 110}, 57}, {{95, 113, 12, 123, 0, 187, 107, 237, 221, 172, 162, 55, 72, 253, 195, 38}, 57}, {{95, 113, 12, 123, 0, 0, 0, 140, 32, 2, 57, 90, 130, 170, 211, 36}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 79, 218}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 143, 67, 221, 122, 121, 233, 1, 25}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 96, 137, 93, 172, 124, 57, 176, 53}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 189, 97, 127, 129, 41, 102, 159}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 192, 137, 115, 158, 136, 30, 198, 156}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 255, 137, 84, 3}, 57}, {{95, 113, 12, 123, 0, 0, 228, 46, 208, 49, 120, 154, 132, 169, 82, 62}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 228, 64, 21, 62, 198}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 7, 243, 71, 4, 167, 104, 202}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 134, 53, 22, 221, 146, 2, 216, 72}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 91, 75, 215, 175, 169, 216, 160, 173}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 232}, 57}, {{95, 113, 12, 123, 0, 188, 91, 40, 233, 69, 207, 23, 152, 153, 68, 105}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 78, 51, 14, 204, 181, 42, 104, 136}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 127}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 187, 23, 154, 17, 246}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 112, 234, 200, 38, 29}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{95, 113, 12, 123, 0, 173, 86, 199, 175, 252, 89, 125, 142, 110, 238, 129}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 214, 74, 180, 166, 78}, 57}, {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 57}, {{95, 113, 12, 123, 0, 100, 244, 226, 212, 37, 110, 84, 240, 110, 59, 193}, 57}, {{95, 113, 12, 123, 0, 223, 243, 193, 254, 126, 255, 214, 49, 46, 145, 61}, 57}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 142}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 223, 135, 141}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 115}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 155, 24, 170, 14}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 26, 218, 148, 87}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 124, 73, 15}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 10, 0, 206}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 142, 232, 203}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 103}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 232}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 216}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 56, 251}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 227, 254}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 85, 244, 91}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 42}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 179, 240}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 125, 108}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 52, 44, 83}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 22, 66}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 80, 161, 49, 139}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 49}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 65, 137}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 244, 140, 34, 219}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 218, 43, 84}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 136, 168}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 27, 84}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 240, 237, 54, 151}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 3, 60, 175, 27}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 199, 208, 139, 202}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 163, 201}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 14, 112}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 23}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 65}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 13, 25}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 217, 69}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 127, 211, 245, 214}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 211, 220}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 200}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 44}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 24}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 195}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 84}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 202, 154, 53}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 209, 47}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 95, 113, 69}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 233, 5, 186}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 245, 171}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 230}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 230, 71, 218, 33}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 67}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 170, 43, 140, 139}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 196, 189, 60}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 212, 2, 48}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 192, 18}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 61, 118, 24, 87}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 248}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 177, 179, 153}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 107, 185}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 192}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 192}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 203, 20, 218}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 237, 28, 229, 216}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 214, 194, 226, 103}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 145, 144}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 114, 141, 35}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 35}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 22, 48, 239}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 129, 69, 34}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 197, 133, 94}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 116, 141}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 143, 115}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 72}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 195, 239, 106, 98}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 100}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 44, 158, 17, 175}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 188, 71, 132}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 26, 176}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 46}, 151}, {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 185, 51}, 151}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 179, 17, 210, 189, 192, 210, 197}, 0}, {{103, 226, 38, 123, 35, 199, 0, 176, 105, 246, 48, 92, 80, 53, 111, 233}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 46, 153, 34}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 208, 104}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 91, 15}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 191, 229}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 213, 102, 136, 124, 13, 232}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 169, 47, 147}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 235, 100, 31, 231, 84}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 222, 92, 35, 198, 131, 177, 166, 228}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 86, 88}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 24, 220, 24}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 55, 238, 113, 147, 80, 125}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 1, 80}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 149, 239, 20, 103, 168, 129, 153}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 83, 222, 6, 143, 252, 193, 111, 23}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 91, 135, 4, 165}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 164, 160, 210, 23, 184, 6, 138}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 73, 97, 140, 8, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 133, 51, 73, 98, 99, 57, 238}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 120, 141, 148}, 0}, {{103, 226, 38, 123, 35, 199, 0, 64, 36, 117, 182, 87, 119, 162, 56, 88}, 0}, {{103, 226, 38, 123, 35, 199, 0, 125, 70, 96, 150, 152, 129, 85, 201, 182}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 183, 179, 149, 211, 125, 5, 132, 36}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 244, 251, 197, 32, 239}, 0}, {{103, 226, 38, 123, 35, 199, 0, 206, 178, 47, 163, 99, 196, 126, 171, 114}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 162, 105, 177, 176, 69, 23, 127}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 244, 169, 158}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 77, 55, 8, 156, 216, 44, 48, 85}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 172, 46}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 216, 59, 18, 26, 138}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 228, 207, 90, 13, 220, 57, 7, 15}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 88, 54, 192, 85, 160, 92, 22, 235}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 94, 136, 43, 221, 233, 57}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 2, 69, 140, 191, 154, 3, 232}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 107, 120, 162, 130, 211, 85, 201, 199}, 0}, {{103, 226, 38, 123, 35, 199, 0, 249, 17, 215, 122, 85, 120, 34, 216, 136}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 172, 68, 224}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 199, 248}, 0}, {{103, 226, 38, 123, 35, 199, 0, 35, 207, 85, 5, 168, 62, 157, 65, 149}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 58, 132, 120, 145, 44, 8, 241}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 125, 208, 228}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 223, 74, 180, 144, 18, 173, 151}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 65, 206, 164, 0, 45}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 91, 193, 253, 98, 47, 247}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 12, 171, 92, 165, 239, 15, 51, 55}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 130, 145, 242, 190, 127, 72, 42, 85}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 103, 178, 77, 137, 167, 223, 136}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 45, 247, 231, 156, 153}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 175, 126, 179, 220, 190, 74, 76, 149}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 135, 77, 243, 150, 23, 144, 128, 194}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 122, 28, 51, 31, 4, 232, 97}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 110, 179, 109, 79, 224, 152}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 162, 188, 65, 244, 125, 24}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 6, 104, 226, 45, 108, 98, 89}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 27, 103}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 29, 160, 22}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 23, 23, 45, 210}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 170, 37, 193, 215}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 210, 198, 109, 23}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 243, 17, 133, 61, 5, 56, 162, 61}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 85, 150, 27}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 114, 83, 209, 142, 216}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 229, 12, 11, 126}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 101, 104}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 153, 123, 61, 74, 157, 155, 227, 167, 173}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 76, 184, 145}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 101, 144, 65, 47, 10, 124, 237}, 0}, {{103, 226, 38, 123, 35, 199, 0, 203, 149, 19, 244, 110, 61, 200, 116, 77}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 47, 190, 113, 238, 211}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 159, 28, 20, 145, 52, 135, 197, 32}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 158, 54, 63, 106}, 0}, {{103, 226, 38, 123, 35, 199, 0, 70, 25, 63, 29, 115, 206, 16, 77, 160}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 230, 188, 139, 80, 237, 224}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 83, 19, 33, 56, 233, 249, 22, 19}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 109, 73, 195, 105, 76, 186, 138}, 0}, {{103, 226, 38, 123, 35, 199, 0, 113, 188, 173, 192, 74, 146, 154, 138, 184}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 242, 184, 2}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 172, 28, 160}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 220, 99, 149, 22}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 51, 255}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}, {{103, 226, 38, 123, 35, 199, 0, 13, 2, 198, 178, 238, 137, 57, 171, 196}, 0}, {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 234, 38, 152, 166, 27}, 0}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 154, 165, 55, 120, 224}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 61, 212, 162, 20}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 43, 0, 41}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 38, 169, 24}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 129, 160, 111, 77, 255, 121}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 105, 77, 210, 206, 213, 180, 40}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 87, 18, 103, 115, 8, 67, 247}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 95, 171}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 86, 115, 41, 50, 201, 48, 190, 161}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 146, 231, 137, 103}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 130}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 223, 82}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 208, 171, 76, 175, 151, 80, 47}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 221, 79}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 76, 248, 152, 100}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 86}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 94, 235, 203, 5, 80, 4, 104}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 31, 160, 32, 21, 253, 176}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 35, 227, 240, 21}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 78, 239, 95, 179, 251, 197}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 248, 152, 200, 220, 182}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 158, 27, 79, 230, 204}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 252, 250, 42, 13}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 255, 67, 95}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 101, 231, 151, 51, 32}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 105, 184}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 247, 247, 252, 196, 73}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 238, 9, 225, 132}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 184, 251, 193, 70, 137}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 167, 111, 42, 123, 255, 151, 145}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 58, 140, 139}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 11, 88, 116, 46, 112, 105, 221}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 45, 68, 58, 88, 19, 171}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 16, 216, 154, 110, 46}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 207, 4, 86, 36}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 233, 242, 235, 52, 38, 145}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 124}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 100, 26, 17, 15}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 184, 99}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 245}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 67, 104, 50, 252}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 213, 131}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 6, 79, 93, 30, 27, 137}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 109, 123, 27, 204, 196, 241, 241}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 96, 49, 75, 147, 40, 207, 55}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 228}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 91, 148, 82}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 137}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 35, 166, 190}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 225, 71, 97, 154, 94}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 195, 227, 30, 224}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 27, 37, 14, 235, 9, 157}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 73, 96, 42}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 164}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 211}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 92, 108, 83, 220, 115, 148, 105}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 87, 131, 177, 234, 10}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 184, 243, 254, 50}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 18}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 184, 188, 217, 15}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 19}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 147, 102, 191, 57, 46}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 238, 206, 75, 121, 5}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 30, 77, 245, 197, 213, 203, 58}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 236}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 184, 78}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 4, 51}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 26}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 155, 123, 222, 182, 183, 199, 111}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 208, 187, 40, 36}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 159, 228}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 209, 123, 238, 59, 226}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 124}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 59, 220, 19, 48}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 42, 65, 152, 65, 242, 118}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 45, 238, 194, 55}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 120, 18, 207}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 114, 175}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 149, 130, 18, 130, 231}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 198, 250, 173, 205, 57, 125, 14}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 155, 135, 89}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 110, 140, 133, 79, 194}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 3, 86}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 16, 71}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 27, 1, 113, 144, 108, 211}, 227}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 113}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 51}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 52}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 166}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 9}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 59}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 124}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 55}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 187}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 8}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 241}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 103}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 114}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 200}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 175}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 204}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 118}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 124}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 20}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 169, 6}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 177}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 208, 201}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 73}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 23}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 48}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 255, 91}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 219}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 88}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 33}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 49, 66}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 95, 84}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 154, 11}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 88}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 176}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 74, 254}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 196}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 165}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 218}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 125, 132}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 60, 54}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 236}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 15, 153}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 215}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 216}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 84}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 231}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 52}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 138}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 140}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 75, 89}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 131, 232}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 103}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 168, 185}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 50}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 245, 212}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 144}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 227, 31}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 130}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 156, 91}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 159}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 173, 116}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 120}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 199}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 44, 252}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 213, 44}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 124}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 149, 39}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 56}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 159}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 235, 128}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 225, 2}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 158}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 140}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 178, 70}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 41, 113}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 214, 40}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 250, 146}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 140, 18}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 175, 26}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 228}, {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 72, 197}, 228}, {{158, 60, 111, 96, 0, 244, 121, 162, 211, 215, 70, 177, 197, 142, 187, 92}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 127, 156}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 69, 218, 14, 226, 60, 121}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 120, 125, 9, 134, 135, 76}, 64}, {{158, 60, 111, 96, 0, 0, 241, 238, 246, 97, 20, 57, 124, 6, 171, 7}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 55}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 228}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 171, 16, 228, 117, 113, 5}, 64}, {{158, 60, 111, 96, 0, 0, 0, 112, 17, 97, 181, 34, 18, 75, 30, 130}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 96}, 64}, {{158, 60, 111, 96, 0, 0, 216, 53, 176, 78, 208, 241, 55, 1, 227, 114}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 146}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 121, 215, 71, 168}, 64}, {{158, 60, 111, 96, 0, 0, 0, 235, 5, 67, 184, 195, 181, 182, 234, 0}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 206, 109, 64, 83}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 237}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 132, 173, 169, 134, 165}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 143, 58}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 93, 96}, 64}, {{158, 60, 111, 96, 0, 145, 157, 110, 64, 247, 220, 178, 93, 220, 126, 205}, 64}, {{158, 60, 111, 96, 0, 13, 62, 192, 165, 177, 9, 169, 151, 78, 187, 114}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 130, 81}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 186, 155, 167, 15, 189, 11, 117, 207}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 92}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 64}, {{158, 60, 111, 96, 0, 187, 127, 113, 227, 98, 95, 116, 11, 33, 207, 100}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 250, 70, 168, 203, 131, 77, 249, 131}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 184}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 40, 101, 100, 39, 210, 219, 15}, 64}, {{158, 60, 111, 96, 0, 0, 0, 115, 161, 73, 109, 170, 7, 55, 212, 231}, 64}, {{158, 60, 111, 96, 12, 173, 247, 119, 240, 106, 73, 1, 182, 83, 134, 192}, 64}, {{158, 60, 111, 96, 0, 0, 216, 7, 232, 239, 63, 32, 231, 135, 119, 131}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 36, 168, 248, 191, 11, 82}, 64}, {{158, 60, 111, 96, 158, 171, 78, 18, 199, 235, 206, 112, 221, 252, 120, 105}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 181, 121, 229, 102, 107, 252, 33, 180}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 211}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 154, 118}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 248, 199, 250, 236, 233, 110, 112, 76}, 64}, {{158, 60, 111, 96, 204, 217, 120, 192, 2, 24, 234, 194, 91, 244, 43, 162}, 64}, {{158, 60, 111, 96, 121, 207, 154, 219, 176, 110, 77, 33, 34, 250, 137, 155}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 163}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 199}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 144, 205, 32, 164, 219, 137, 239}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 62, 5, 213, 13, 96, 230, 251}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 240, 146, 110, 37, 249, 161, 134}, 64}, {{158, 60, 111, 96, 187, 188, 111, 17, 125, 52, 76, 167, 144, 124, 250, 114}, 64}, {{158, 60, 111, 96, 0, 54, 206, 201, 151, 212, 167, 33, 51, 32, 14, 227}, 64}, {{158, 60, 111, 96, 0, 0, 0, 183, 126, 151, 247, 35, 174, 81, 138, 176}, 64}, {{158, 60, 111, 96, 0, 0, 0, 228, 244, 139, 197, 47, 242, 119, 209, 220}, 64}, {{158, 60, 111, 96, 36, 253, 165, 22, 105, 41, 129, 219, 49, 72, 154, 175}, 64}, {{158, 60, 111, 96, 188, 98, 237, 194, 128, 207, 103, 59, 159, 65, 193, 54}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 203, 3, 193, 157, 48, 70, 48, 37}, 64}, {{158, 60, 111, 96, 128, 114, 224, 84, 230, 9, 25, 122, 119, 219, 200, 88}, 64}, {{158, 60, 111, 96, 0, 0, 113, 1, 137, 148, 174, 214, 25, 105, 35, 25}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 24, 76}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 5, 128}, 64}, {{158, 60, 111, 96, 0, 0, 230, 83, 238, 174, 223, 185, 71, 34, 73, 147}, 64}, {{158, 60, 111, 96, 0, 0, 241, 90, 104, 17, 156, 105, 22, 20, 42, 57}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 52, 12, 46, 119, 115}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 109, 166, 46, 144, 163, 12, 74}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 68}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 165, 122, 151, 207, 167, 212, 134}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 23, 51, 53, 230, 96, 24, 245, 49}, 64}, {{158, 60, 111, 96, 0, 0, 170, 170, 91, 73, 128, 234, 63, 150, 100, 170}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 191, 221}, 64}, {{158, 60, 111, 96, 0, 41, 79, 182, 187, 115, 85, 158, 121, 86, 90, 69}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 64}, {{158, 60, 111, 96, 0, 27, 136, 124, 220, 250, 36, 140, 0, 6, 111, 12}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 110, 163, 165, 57, 5}, 64}, {{158, 60, 111, 96, 0, 73, 114, 77, 214, 61, 106, 196, 78, 220, 139, 120}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 192, 201, 215, 186}, 64}, {{158, 60, 111, 96, 0, 0, 0, 234, 142, 124, 25, 217, 111, 202, 192, 75}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 186, 226, 164, 196, 71, 10}, 64}, {{158, 60, 111, 96, 0, 0, 142, 49, 47, 160, 188, 59, 158, 235, 163, 113}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 107}, 64}, {{158, 60, 111, 96, 0, 39, 37, 56, 158, 215, 43, 161, 216, 71, 127, 154}, 64}, {{158, 60, 111, 96, 104, 77, 77, 138, 210, 38, 108, 94, 27, 140, 253, 72}, 64}, {{158, 60, 111, 96, 0, 0, 173, 15, 56, 13, 107, 87, 131, 192, 245, 241}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 183, 92, 158, 213, 238, 176, 220, 131}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 180, 89, 194, 212}, 64}, {{158, 60, 111, 96, 0, 0, 0, 91, 246, 230, 235, 24, 218, 214, 64, 107}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 50, 23, 148, 122, 202}, 64}, {{158, 60, 111, 96, 18, 117, 198, 223, 52, 150, 68, 34, 157, 146, 133, 25}, 64}, {{158, 60, 111, 96, 0, 0, 86, 44, 150, 68, 4, 255, 86, 96, 247, 98}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 175, 6, 110, 146, 56, 132, 235}, 64}, {{158, 60, 111, 96, 0, 0, 0, 28, 213, 132, 162, 235, 133, 3, 241, 12}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 63, 94, 68, 187}, 64}, {{158, 60, 111, 96, 46, 212, 18, 33, 39, 152, 140, 79, 146, 197, 156, 195}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 129, 158, 178, 163, 20, 39, 144, 221}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 23, 108, 144, 208}, 64}, {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 220}, 64}, {{124, 108, 88, 0, 0, 245, 5, 216, 236, 63, 183, 102, 150, 188, 103, 162}, 179}, {{124, 108, 88, 0, 0, 0, 0, 89, 179, 160, 197, 253, 206, 186, 21, 242}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 115}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 243, 181, 240, 201, 186, 239, 19}, 179}, {{124, 108, 88, 0, 0, 0, 115, 27, 216, 27, 189, 147, 22, 67, 247, 121}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 74, 213, 91, 40, 88, 180}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 0, 0, 11, 126, 244, 231, 131, 143, 114, 83, 17, 33}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 236}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 133, 24, 48, 179, 15, 134, 161, 29}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 218, 41, 48}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 100, 229, 234, 72, 186, 79, 69, 225}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 171, 189, 195, 33, 1, 90, 82, 116}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 53, 178, 196, 180, 23, 165, 14, 116, 174, 142, 47, 108}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 40, 42, 244, 122, 17, 121}, 179}, {{124, 108, 88, 0, 0, 118, 89, 159, 218, 150, 141, 175, 147, 150, 238, 31}, 179}, {{124, 108, 88, 0, 0, 91, 38, 112, 83, 57, 38, 239, 35, 127, 199, 18}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 42, 176, 249, 25, 66, 218, 237, 153}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 47, 194, 181, 1, 166, 155, 65}, 179}, {{124, 108, 88, 0, 0, 38, 171, 46, 184, 34, 5, 80, 184, 107, 54, 88}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 124}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 14, 3, 242, 133, 225, 149, 211}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 98, 6}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 179}, {{124, 108, 88, 0, 0, 0, 57, 147, 239, 29, 104, 203, 212, 37, 70, 121}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 118, 64, 5}, 179}, {{124, 108, 88, 0, 0, 0, 223, 44, 247, 113, 175, 2, 187, 208, 12, 147}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 54, 203, 40}, 179}, {{124, 108, 88, 0, 0, 168, 203, 17, 242, 218, 130, 109, 244, 28, 105, 33}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 141}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 179}, {{124, 108, 88, 0, 23, 98, 117, 155, 22, 131, 153, 248, 161, 22, 14, 18}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 165, 159}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 179}, {{124, 108, 88, 0, 0, 59, 130, 161, 205, 206, 131, 67, 198, 57, 230, 248}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 79, 236, 185}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 143, 74, 242, 180, 120}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 6, 107, 152, 197, 0, 80, 120, 17}, 179}, {{124, 108, 88, 0, 0, 0, 89, 170, 190, 201, 253, 137, 194, 141, 242, 62}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 13, 241, 253, 109, 14, 34}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 122, 172, 117, 44, 72, 161}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 94}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 252, 176, 219, 41, 46}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 201, 31}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 209}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 226, 17, 195, 34, 5, 218, 77, 60}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 174, 24, 128, 226, 52, 57, 151, 108}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 83}, 179}, {{124, 108, 88, 0, 20, 135, 205, 22, 25, 241, 22, 158, 206, 3, 51, 175}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 223, 132, 79, 131, 209, 98, 207, 189}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 15, 182, 123, 159, 97, 132, 25}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 79, 247, 35, 188, 111, 195}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 150, 191, 69}, 179}, {{124, 108, 88, 0, 0, 0, 0, 190, 95, 68, 212, 138, 113, 214, 229, 40}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 119, 233, 209, 163, 169, 17}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 135, 6}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 179}, {{124, 108, 88, 0, 0, 0, 122, 218, 220, 209, 91, 221, 8, 42, 108, 234}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 0, 0, 21, 78, 145, 21, 207, 167, 190, 39, 89, 81}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 190, 62, 165, 95, 27, 164, 162, 214}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 85, 217}, 179}, {{124, 108, 88, 0, 0, 32, 80, 161, 87, 211, 75, 250, 64, 230, 136, 234}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 135, 195, 57, 95, 134}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 19, 177, 106, 7, 151}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 157, 104, 97, 108, 19}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 226, 189, 64, 153, 200, 40, 230}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 126}, 179}, {{124, 108, 88, 0, 0, 0, 0, 247, 20, 101, 214, 62, 198, 107, 164, 163}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 246, 129, 110, 175, 51}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 198, 30, 210, 156, 13, 61, 62, 190}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 176, 58, 1, 195, 11}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 172, 6, 69, 91, 145, 1, 72, 138}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 77, 24, 166, 212, 240, 58}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 44, 155, 201, 101, 22}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 213}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 179}, {{124, 108, 88, 0, 0, 0, 13, 31, 81, 250, 247, 252, 71, 89, 113, 23}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 135, 92, 175}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 4, 95, 82}, 179}, {{124, 108, 88, 0, 0, 131, 243, 91, 43, 153, 2, 252, 125, 16, 0, 168}, 179}, {{124, 108, 88, 0, 0, 0, 0, 97, 126, 170, 89, 5, 212, 40, 227, 27}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 14, 39}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 75, 160}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 179}, {{124, 108, 88, 0, 119, 125, 30, 71, 204, 255, 144, 216, 147, 101, 178, 198}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 26, 76, 178, 184, 192, 91, 117, 179}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 61, 96}, 179}, {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 72}, 179}, {{124, 108, 88, 0, 0, 0, 0, 137, 170, 66, 98, 124, 247, 251, 64, 113}, 179}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 91, 222, 111, 81, 6, 132}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 225, 124, 236}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 36, 113, 95, 178, 212, 20}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 69}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 30}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 170, 105}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 84, 215}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 101}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 241, 189, 144, 142, 181}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 220, 122, 57, 187, 139}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 3, 178, 98, 53, 69, 248}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 52, 28, 173}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 254, 154, 224, 247, 205, 110}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 86, 254, 31}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 245}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 117, 192, 150, 183, 247, 215}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 155, 233, 201, 47, 115, 175}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 208, 245, 149}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 140, 53, 214, 170, 37, 113}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 163, 2, 154}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 105, 36, 220, 239, 252}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 129, 110, 20, 24, 73, 240}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 44, 224, 213, 245, 186, 104}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 143}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 67, 193, 119, 40, 95}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 162, 17, 84, 203, 174}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 149}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 145, 240}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 208, 0, 93, 114, 201, 249}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 185, 11, 102}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 224, 75, 141, 19, 50}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 117, 187, 16, 1, 105, 227}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 242}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 100, 66, 16, 102, 222}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 204}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 227, 110}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 105, 100, 23, 132}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 91}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 85, 68, 221, 242, 84}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 24, 46, 114, 104, 54}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 124, 41, 59, 221, 250, 131}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 4, 90, 29, 219}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 169, 115, 3, 123}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 209, 237, 108, 99}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 140, 215, 146, 31}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 158}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 189, 194}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 59, 38}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 212}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 1, 3, 111}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 235}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 161, 12}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 7, 11, 232, 136, 245}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 6, 29, 201, 49, 15, 49}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 158, 60, 33, 151, 160}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 79, 171, 25, 183, 165, 245}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 20, 250, 166, 151, 5}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 126, 56}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 130, 20, 125, 234, 74}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 9, 61, 157, 126, 14}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 208, 177, 238, 121}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 193}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 142}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 52, 244, 238, 171, 176, 70}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 80}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 240, 230}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 55, 192, 105, 186, 90, 46, 167}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 36, 39, 174}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 221, 212, 37}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 141, 87}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 33, 11, 141, 51}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 121, 64, 211, 247, 107}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 237, 117, 73, 77, 222}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 80, 47, 153, 106}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 46}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 158, 236, 242, 179}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 38}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 18, 29, 82, 9}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 17, 77}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 229, 163}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 179, 43, 26, 90, 146}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 157, 212, 142, 75, 85, 106}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 39, 140, 85}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 115, 80, 207, 66, 83}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 83}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 67, 230, 112, 14}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 77, 90, 28, 20}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 228, 186, 47, 180, 100, 161}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 21, 106, 220}, 107}, {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 21, 26}, 107}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 119, 32}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 76}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 135}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 186, 98}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 223, 211}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 137}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 224, 80}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 148}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 16, 182}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 2}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 129}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 61}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 64, 252}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 43}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 50}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 129, 170}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 195}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 168}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 87}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 136}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 164}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 30, 243}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 79}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 84, 95}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 59}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 23}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 168, 144}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 74}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 236, 90}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 147}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 139}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 120}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 157}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 128}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 33, 196}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 62, 206}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 21}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 122, 10}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 158, 103}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 166, 176}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 149}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 214, 221}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 25}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 230, 54}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 38}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 184, 76}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 156, 73}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 166}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 145}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 64, 136}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 59}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 26, 134}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 66, 209}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 199, 95}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 15, 250}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 11}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 126}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 136, 194}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 225, 77}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 60, 137}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 89}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 129, 158}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 119, 112}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 165, 174}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 39}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 215}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 186, 120}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 160}, 206}, {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 93}, 206}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 88, 186, 54}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 34, 31, 230, 237, 165, 181}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 161}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 126, 200}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 144, 103, 250}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 65, 62, 125, 219, 159, 24}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 229, 81, 239, 113, 120, 148, 162}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 64, 132, 143}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 31, 70, 103, 248, 150}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 100}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 126, 12}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 193, 170, 19, 251, 82, 9}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 13, 250, 194}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 252, 173, 202, 143, 185, 198, 107}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 23, 11, 202, 68}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 184, 136, 241, 158}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 182, 102, 182, 25}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 99, 242, 85, 143}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 74, 124}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 231}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 149, 101, 38, 244, 32, 206}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 102, 235, 231, 33}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 255}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 212, 159, 152}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 45, 213, 133}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 228, 172}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 7}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 126, 177, 150}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 163, 14, 106}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 12, 124}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 87}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 93, 185, 224}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 201, 66, 186, 244, 125, 23}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 167, 117, 238, 164, 210}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 213, 6}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 131, 247, 79, 254, 138, 156}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 146, 17}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 149, 113, 146}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 216, 236, 55, 228, 221}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 239, 35, 31}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 17, 34, 124, 78, 206}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 5, 218, 192, 203, 134, 45, 54}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 162, 181, 229, 227, 111, 249}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 103, 250, 157, 112}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 115}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 251}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 189, 221, 34, 238, 194, 159}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 239}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 46, 178, 238, 231, 65, 151}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 31}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 131, 246}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 141, 161, 93, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 63, 155, 72}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 241, 48, 252, 163}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 93, 101, 237, 244}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 13}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 249, 112, 124, 196, 241, 194}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 232}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 104, 171, 55, 132}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 253, 101, 55, 58, 29}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 28, 0, 34}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 26}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 245, 228, 21}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 187, 130, 72, 204, 252, 5}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 90}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 219, 184, 144}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 40}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 150, 25, 94, 222}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 55, 123, 230}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 160, 245, 47}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 179}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 72, 210}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 199, 206, 177, 43}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 12, 241, 176, 240, 175}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 156, 115, 152, 126, 158}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 245}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 58, 167}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 134}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 228, 42}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 65, 59, 84}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 114, 5, 247, 139, 165, 96}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 237, 162, 103}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 20, 145, 115, 182, 46, 204, 160}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 11, 113, 255, 79}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 225, 160, 118, 3}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 112}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 166, 77, 124, 154, 94}, 95}, {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 182, 214, 231}, 95}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 80}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 132, 105}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 140, 243, 64}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 109}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 19, 65, 249}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 3}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 118, 220}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 203}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 120, 169}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 154}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 13, 203, 50}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 170, 166, 183}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 135, 70, 141}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 202, 229, 82}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 48}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 62, 134}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 222}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 91, 50}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 229, 90, 233}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 159}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 1, 243, 220}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 228, 5, 4}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 108}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 134, 116}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 5, 121}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 192, 55, 165}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 252}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 234, 12, 52}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 230, 8, 47}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 187}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 158}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 253, 1}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 25, 128, 68}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 131}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 220, 245}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 23, 67}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 216, 46}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 152, 148, 248}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 49, 158, 96}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 249, 161, 226}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 97, 162, 159}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 136}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 112, 68}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 85, 239}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 184, 240}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 197, 57, 171}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 63, 82}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 104, 179, 90}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 175, 252, 192}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 64, 74, 255}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 145}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 210}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 55, 7}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 192, 72}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 23, 223}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 78, 119}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 17, 175, 167}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 106}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 162, 190}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 181, 50}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 211, 73, 221}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 240, 120, 24}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 244}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 214, 4}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 15, 51, 142}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 229, 185, 43}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 157, 96, 172}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 246, 138}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 92, 211, 30}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 194, 53, 72}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 39}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 243, 53, 68}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 8}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 25}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 121}, 219}, {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 5, 98, 226}, 219}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 173}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 92}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 174}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 220}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 141}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 156}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 221}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 138}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 218, 56, 124, 227, 37, 171, 212}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 92, 150, 45, 49, 69, 164}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 72, 99}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 76, 117, 236, 56, 153, 150, 15, 136}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 242, 23, 46, 36, 225, 34}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 119, 71, 112, 218}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 60, 34, 186, 131}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 201, 110}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 59, 167}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 59, 4, 102, 64, 130, 111}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 109, 94, 133, 212, 62, 188, 179, 236}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 140, 210}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 213, 254, 104, 171, 245, 55, 11}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 107, 61, 66, 151, 145, 248}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 188, 167, 222, 252, 110}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 169, 10, 171, 166, 139, 89, 242}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 69, 166, 98, 85, 75, 85, 144}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 153, 26, 74, 153, 191, 227, 229}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 25, 123, 143, 194, 42, 47}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 39, 31, 144, 208, 153}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 82, 18, 146, 49, 161, 78, 55, 164}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 158, 128, 255}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 224, 112, 155, 172, 230, 233, 184}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 14, 44, 14}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 22, 168, 39, 195, 194, 28}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 237, 243, 201, 16, 88, 67}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 21, 73, 42, 138, 35, 173, 197}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 246, 87, 4, 161}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 220, 142, 147}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 160, 124, 177}, 84}, {{248, 122, 115, 81, 15, 158, 136, 20, 243, 105, 236, 23, 217, 82, 138, 19}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 129, 97}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 96, 186, 246, 182, 92, 77, 29, 242}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 15, 89, 209, 240}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 197, 215}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 255, 82}, 84}, {{248, 122, 115, 81, 15, 158, 136, 218, 115, 59, 250, 217, 84, 214, 181, 89}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 193, 229, 214, 170}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 128, 237, 96, 110, 132, 2, 203}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 57, 170}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 99, 5, 232, 196}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 124, 13, 228, 167, 170, 139, 134, 41}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 193, 178, 40}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 226, 20}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 46, 60, 203, 237, 91}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 157, 177, 205, 155, 75, 194, 7}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 73, 46, 219, 178, 142, 193, 66, 85}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 235, 196, 27, 166, 91, 61, 174, 69}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 149, 114, 126, 170, 93, 98, 10}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 130, 205, 182, 230, 93, 151, 69}, 84}, {{248, 122, 115, 81, 15, 158, 136, 172, 20, 12, 145, 31, 18, 66, 82, 214}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 185, 74}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 61, 7, 34}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 50, 183, 14, 45, 85, 201, 152}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 168, 147, 23, 60, 107, 108, 37, 185}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 41, 16, 218, 150, 108, 205}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 90, 208, 237, 63, 170, 182, 128, 159}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 40, 156, 198, 22}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 162, 110, 246, 185, 221, 16, 229}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 67, 26}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 190, 177, 114, 143, 25, 230, 158}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 86, 202, 36, 188, 160, 227}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 191, 167, 166, 132, 141, 9}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 252, 59, 151, 7, 154}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 53, 49}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 135, 136, 147, 50}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 41, 21, 127, 13, 132, 26}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 36, 226, 65, 172, 197, 129, 244}, 84}, {{248, 122, 115, 81, 15, 158, 136, 95, 169, 144, 59, 252, 217, 60, 130, 164}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 147, 47, 24, 19}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 211, 21, 15, 136, 53, 220}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 15, 23}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 130, 155, 107, 244}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 142, 254, 230}, 84}, {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 221, 169, 131, 222, 78, 190}, 84}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 15, 63}, 161}, {{8, 128, 0, 205, 84, 254, 26, 144, 226, 65, 116, 253, 7, 133, 127, 159}, 161}, {{8, 128, 0, 0, 0, 0, 96, 187, 2, 174, 249, 97, 194, 156, 133, 201}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 144, 25, 193, 172}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 5, 85, 32}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 230}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 183, 39, 49, 56, 203, 223, 71, 179}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 226, 153, 226, 121, 145, 90, 102, 134}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 71}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 173, 55, 86}, 161}, {{8, 128, 0, 46, 183, 105, 170, 33, 96, 194, 182, 131, 161, 117, 182, 25}, 161}, {{8, 128, 0, 0, 0, 0, 0, 252, 158, 114, 81, 209, 112, 57, 242, 64}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 17, 176, 79, 151, 76, 109, 255, 58}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 161}, {{8, 128, 0, 0, 0, 0, 0, 61, 161, 163, 110, 95, 167, 246, 95, 201}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 110, 243, 41, 190, 176, 213, 150}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 212, 41, 202}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 61, 188, 3, 82, 139, 130, 32}, 161}, {{8, 128, 0, 0, 18, 165, 116, 138, 118, 229, 215, 98, 197, 118, 105, 61}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 129, 55}, 161}, {{8, 128, 0, 0, 0, 0, 0, 117, 75, 69, 163, 13, 38, 156, 61, 70}, 161}, {{8, 128, 0, 0, 0, 0, 0, 149, 1, 24, 202, 71, 190, 181, 133, 45}, 161}, {{8, 128, 0, 5, 219, 117, 216, 166, 150, 124, 84, 199, 173, 61, 29, 2}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 42}, 161}, {{8, 128, 0, 0, 0, 0, 154, 174, 72, 246, 171, 99, 191, 132, 32, 53}, 161}, {{8, 128, 0, 0, 0, 32, 245, 84, 216, 63, 123, 58, 47, 98, 84, 166}, 161}, {{8, 128, 0, 0, 0, 0, 0, 6, 51, 174, 85, 78, 173, 160, 95, 24}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 61, 234, 144, 21}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 223, 49}, 161}, {{8, 128, 0, 22, 137, 252, 40, 102, 216, 88, 131, 65, 241, 240, 253, 252}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 236, 110, 239}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 129, 67, 60}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 206, 210, 187, 205}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 235, 102, 236}, 161}, {{8, 128, 0, 0, 0, 0, 140, 175, 0, 62, 46, 62, 8, 156, 66, 177}, 161}, {{8, 128, 0, 0, 111, 144, 249, 113, 33, 134, 104, 26, 10, 20, 44, 190}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 20, 151, 233, 232}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 244, 47}, 161}, {{8, 128, 0, 0, 71, 38, 5, 32, 138, 227, 167, 134, 193, 110, 61, 221}, 161}, {{8, 128, 179, 151, 187, 164, 88, 58, 79, 61, 109, 34, 102, 153, 151, 141}, 161}, {{8, 128, 0, 0, 0, 170, 219, 71, 109, 205, 213, 139, 144, 86, 113, 64}, 161}, {{8, 128, 0, 0, 0, 0, 0, 102, 202, 119, 18, 67, 87, 99, 224, 189}, 161}, {{8, 128, 0, 0, 0, 0, 0, 226, 102, 80, 41, 13, 244, 52, 249, 91}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 160, 240, 57, 99, 40, 4}, 161}, {{8, 128, 0, 0, 53, 223, 9, 163, 237, 196, 169, 122, 210, 244, 69, 186}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 19, 56, 201, 252, 234, 6, 254, 168}, 161}, {{8, 128, 0, 0, 0, 0, 159, 116, 174, 180, 3, 18, 235, 109, 13, 168}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 161}, {{8, 128, 0, 0, 0, 0, 0, 120, 104, 251, 179, 173, 20, 224, 48, 124}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 113, 241, 193, 102, 250, 166, 77, 94}, 161}, {{8, 128, 0, 0, 0, 194, 46, 10, 121, 57, 237, 2, 161, 38, 216, 40}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 40, 122}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 37, 169, 58, 254}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 161}, {{8, 128, 0, 118, 65, 223, 183, 195, 156, 105, 79, 195, 34, 148, 106, 115}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 33, 116, 39, 123}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 41}, 161}, {{8, 128, 0, 0, 78, 164, 0, 20, 60, 1, 0, 199, 45, 146, 65, 152}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 88}, 161}, {{8, 128, 0, 0, 0, 0, 0, 62, 195, 50, 62, 83, 79, 98, 102, 159}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 47, 125, 157, 44, 76, 80}, 161}, {{8, 128, 0, 0, 0, 0, 184, 173, 170, 24, 247, 62, 156, 132, 177, 83}, 161}, {{8, 128, 0, 0, 0, 0, 70, 183, 139, 156, 155, 196, 95, 127, 207, 27}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 167, 255, 227, 145, 219, 207}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 161}, {{8, 128, 0, 102, 63, 18, 119, 34, 76, 120, 2, 74, 93, 204, 228, 21}, 161}, {{8, 128, 0, 0, 0, 0, 246, 91, 240, 137, 36, 230, 182, 158, 67, 1}, 161}, {{8, 128, 0, 0, 0, 0, 0, 174, 214, 25, 160, 198, 60, 251, 213, 177}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 125, 203}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 92, 79, 97}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 173, 125, 123, 164, 115, 187, 240}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 94, 1, 196}, 161}, {{8, 128, 40, 183, 43, 84, 66, 199, 194, 195, 35, 253, 220, 232, 126, 78}, 161}, {{8, 128, 0, 151, 24, 253, 174, 2, 62, 26, 138, 20, 180, 80, 171, 236}, 161}, {{8, 128, 0, 0, 0, 0, 0, 87, 180, 48, 213, 168, 68, 93, 245, 58}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 160}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 252, 129, 168, 105, 225, 144, 123, 148}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 250, 143}, 161}, {{8, 128, 194, 36, 36, 27, 80, 175, 109, 165, 235, 247, 34, 110, 82, 66}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 161}, {{8, 128, 0, 0, 0, 221, 238, 149, 34, 109, 176, 119, 159, 215, 130, 18}, 161}, {{8, 128, 0, 0, 6, 194, 193, 236, 111, 7, 92, 135, 163, 206, 251, 64}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 191, 173, 109}, 161}, {{8, 128, 0, 0, 0, 40, 123, 63, 234, 123, 114, 176, 149, 5, 95, 49}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 182, 15, 38, 255, 95, 108}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 120, 130, 78, 145, 208, 120, 32}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 189, 118, 214, 226}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 197, 184, 39, 180, 90, 250, 88}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 156, 209}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 162, 86}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 47, 145, 2, 0, 111, 120, 160, 64}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 161}, {{8, 128, 13, 161, 40, 46, 38, 234, 80, 79, 178, 57, 170, 121, 100, 152}, 161}, {{8, 128, 0, 0, 0, 0, 0, 0, 0, 157, 188, 26, 201, 51, 243, 124}, 161}, {{8, 128, 221, 218, 245, 44, 125, 154, 153, 95, 147, 31, 91, 57, 67, 178}, 161}, {{8, 128, 0, 0, 0, 0, 253, 56, 206, 159, 15, 81, 39, 215, 32, 182}, 161}, {{8, 128, 0, 0, 84, 173, 185, 219, 75, 142, 50, 220, 82, 138, 151, 176}, 161}, {{142, 96, 105, 133, 251, 57, 128, 0, 102, 14, 52, 126, 153, 204, 39, 151}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 249, 153, 4, 252, 144}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 145, 75}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 197, 204, 48}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 181, 109, 21, 182}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 255, 104}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 198, 213, 79, 123, 215, 192, 145, 27}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 176, 115, 78, 69, 21}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 227, 74, 67, 231, 27, 90}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 79, 45, 238, 136, 207}, 25}, {{142, 96, 105, 133, 251, 57, 128, 29, 115, 86, 74, 171, 152, 183, 138, 91}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 38, 93, 141, 115}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 119, 246, 73, 68}, 25}, {{142, 96, 105, 133, 251, 57, 128, 3, 226, 34, 143, 156, 214, 206, 28, 183}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 76, 50, 129, 74, 150, 76}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 4, 236, 149, 254}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 61, 14, 125, 128, 37, 57, 239}, 25}, {{142, 96, 105, 133, 251, 57, 128, 54, 80, 22, 102, 35, 254, 164, 76, 49}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 129, 1}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 143, 252, 99, 190, 100, 42, 193, 237}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 196, 46, 36, 175, 171}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 133, 213, 138, 20, 64, 249, 136}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 247, 72, 202, 183, 31, 175}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 142, 62, 228}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 26, 35, 70, 14, 52}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 14, 65}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 232, 144, 186, 82, 134, 216}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 29, 24, 132}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 23, 183, 9, 228, 154, 79, 195, 177}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 229, 179, 165, 35, 78, 174, 44, 7}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 31, 50, 75, 237, 150, 137, 101, 110}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 173, 38, 62, 193, 168, 239, 93, 252}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 73, 223, 76, 99}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 174, 32, 228}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 61, 150, 143, 224}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 114, 153, 124, 29, 156, 163}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 168, 95, 152, 242, 223, 156, 227, 236}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 132, 130, 210, 74, 240, 247, 218}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 19, 252, 70, 106, 73, 55, 5}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 131, 225, 242, 251, 209, 108}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 136, 212, 30}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 55, 53, 182, 219, 124, 9}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 40, 240, 227}, 25}, {{142, 96, 105, 133, 251, 57, 128, 178, 193, 184, 173, 189, 82, 165, 222, 2}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 231, 148, 20, 139, 22, 213}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 39, 61, 232}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 47, 11, 220, 96, 232, 54, 15, 15}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 116, 39, 75, 214}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 86, 15, 4, 255, 112, 102, 136}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 246, 78, 118}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 227, 193, 154, 246, 200, 195, 7}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 160, 170, 8, 158}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 36, 183, 44, 81, 4, 184, 226}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 177, 141, 69, 102}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 187, 20}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 78, 247, 178, 100, 83, 195, 21}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 153, 181, 86, 208, 252, 183, 183}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 18, 12, 130, 160, 101, 19}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 43, 193, 200, 80, 188, 39, 97}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 143, 196, 32, 74, 38, 241, 172, 16}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 25, 205, 17, 6, 98, 176, 142, 157}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 37, 84}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 27, 138}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 185, 254}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 207, 150, 203, 149, 197}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 43, 100, 54, 37, 12, 113, 26, 49}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 79, 25, 243, 85}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 117, 60}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 104, 247, 71, 96}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 227, 241, 211, 82, 16, 196, 245}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 150, 237, 65, 207, 230, 177, 35}, 25}, {{142, 96, 105, 133, 251, 57, 128, 146, 74, 80, 172, 224, 93, 196, 119, 34}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 152, 29, 116, 170, 59}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 124, 64, 8}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 231, 26, 74, 115}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 75, 223, 4, 185, 220}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 208, 167, 213, 229, 176, 98}, 25}, {{142, 96, 105, 133, 251, 57, 128, 117, 14, 65, 36, 169, 154, 180, 88, 182}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 229, 14, 12, 173, 9, 15, 155, 30}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 138, 130, 229, 129, 163, 52}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 227, 52, 77, 3, 111, 173, 2}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 124, 144, 145, 180, 212, 70, 247}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 38, 250, 154}, 25}, {{142, 96, 105, 133, 251, 57, 128, 0, 0, 174, 212, 67, 45, 40, 189, 240}, 25}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 137}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 77}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 177, 99}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 208}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 2}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 161}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 182}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 146}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 72, 222}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 255}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 114}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 187}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 65}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 164, 71}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 48}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 45}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 42}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 228, 148}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 190}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 214, 244}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 71}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 84}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 133, 41}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 228}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 61}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 123}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 165, 31}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 71}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 158}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 188, 149}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 132}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 106}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 137}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 21}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 86, 51}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 217}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 72}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 240, 88}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 109, 142}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 192}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 41}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 69}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 176}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 184, 167}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 128}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 241}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 144, 155}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 92}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 55, 242}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 254}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 251, 108}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 149}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 47}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 149}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 216, 108}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 208, 130}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 172}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 150}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 243, 43}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 75, 55}, 113}, {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 105}, 113}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 27, 238}, 61}, {{0, 238, 80, 85, 166, 205, 68, 159, 171, 140, 224, 205, 30, 203, 85, 8}, 61}, {{0, 0, 0, 0, 200, 62, 231, 236, 148, 192, 221, 124, 138, 158, 159, 90}, 61}, {{0, 0, 218, 187, 192, 23, 152, 1, 51, 14, 153, 30, 134, 24, 46, 156}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 140, 205, 184, 193, 180, 4, 51, 45, 134, 65}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 61}, {{0, 0, 0, 0, 0, 0, 0, 3, 217, 205, 138, 181, 172, 191, 50, 112}, 61}, {{0, 0, 0, 192, 55, 26, 248, 134, 155, 210, 63, 104, 72, 159, 77, 232}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 231, 194, 101}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 175, 208, 47, 106}, 61}, {{0, 0, 0, 0, 0, 0, 114, 163, 245, 190, 30, 59, 228, 179, 215, 18}, 61}, {{0, 0, 0, 0, 0, 63, 80, 8, 241, 159, 105, 249, 9, 127, 215, 89}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 124, 233, 8}, 61}, {{0, 0, 0, 0, 0, 0, 0, 163, 83, 150, 115, 138, 88, 87, 106, 37}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 188, 113, 82, 235, 73, 138}, 61}, {{0, 0, 0, 161, 183, 103, 28, 194, 215, 78, 232, 71, 195, 90, 235, 247}, 61}, {{0, 0, 0, 0, 0, 122, 195, 161, 26, 22, 177, 174, 104, 78, 184, 141}, 61}, {{0, 0, 136, 93, 181, 244, 64, 6, 239, 238, 247, 147, 187, 149, 63, 80}, 61}, {{0, 0, 0, 0, 175, 91, 176, 31, 155, 239, 144, 240, 94, 213, 206, 155}, 61}, {{0, 0, 0, 157, 181, 8, 144, 79, 244, 153, 151, 86, 127, 87, 123, 254}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 57}, 61}, {{0, 0, 0, 0, 50, 185, 126, 15, 92, 116, 60, 172, 114, 253, 201, 145}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 169, 172, 142, 243, 156, 69, 238, 119}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 194, 168}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 119, 87, 152, 63, 18}, 61}, {{0, 0, 0, 0, 0, 60, 198, 22, 251, 217, 101, 182, 9, 38, 203, 143}, 61}, {{0, 0, 0, 0, 18, 35, 26, 251, 209, 38, 107, 241, 59, 253, 81, 134}, 61}, {{0, 6, 91, 242, 213, 218, 145, 137, 2, 44, 171, 45, 149, 212, 228, 214}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 106, 100, 187, 72, 82}, 61}, {{0, 0, 0, 0, 0, 0, 29, 249, 18, 141, 68, 170, 9, 93, 240, 53}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 174, 53, 31}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 61}, {{0, 245, 161, 116, 74, 213, 184, 79, 19, 141, 247, 178, 64, 83, 211, 43}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 234, 92, 224, 250, 28, 162, 99, 50}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 208, 166, 193, 104, 17, 31, 27, 16, 180, 39}, 61}, {{0, 0, 81, 83, 93, 180, 25, 1, 123, 220, 90, 238, 132, 235, 10, 214}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 142}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 208, 190, 58, 172, 7}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 8, 220}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 145, 42, 102, 36, 77, 107, 73, 163, 21, 126, 155, 226, 10, 147}, 61}, {{0, 0, 0, 0, 0, 0, 125, 170, 199, 139, 140, 105, 109, 198, 59, 252}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 37, 251, 159, 197}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 215}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 197, 19, 102, 56, 87, 160, 147, 53}, 61}, {{0, 0, 71, 129, 122, 15, 64, 156, 13, 146, 86, 147, 158, 186, 185, 151}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 144}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 48, 8}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 104, 141}, 61}, {{0, 0, 0, 0, 0, 0, 0, 171, 18, 237, 10, 241, 182, 199, 35, 103}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 15, 186, 56, 161}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 63, 35, 149, 153, 122, 26, 78, 87}, 61}, {{0, 0, 0, 30, 100, 217, 59, 27, 230, 160, 16, 6, 105, 183, 42, 10}, 61}, {{0, 0, 0, 0, 0, 48, 1, 230, 104, 27, 123, 128, 8, 211, 193, 133}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 110, 198, 144}, 61}, {{0, 0, 0, 0, 0, 145, 35, 208, 206, 51, 23, 83, 240, 147, 247, 196}, 61}, {{0, 0, 0, 44, 89, 134, 196, 25, 227, 187, 157, 104, 211, 231, 83, 193}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 164, 154, 159, 198, 37, 132, 32, 96}, 61}, {{0, 0, 0, 0, 0, 0, 205, 5, 238, 159, 65, 244, 168, 66, 137, 119}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 131, 69, 56, 192, 55, 96, 229, 134}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 173, 60, 135}, 61}, {{0, 0, 0, 222, 5, 95, 83, 54, 247, 113, 134, 187, 189, 57, 150, 220}, 61}, {{0, 0, 0, 0, 0, 0, 0, 240, 222, 204, 203, 104, 255, 232, 151, 169}, 61}, {{0, 0, 0, 0, 0, 0, 114, 64, 114, 2, 167, 193, 106, 119, 164, 223}, 61}, {{0, 0, 0, 0, 196, 88, 163, 253, 171, 82, 9, 156, 196, 105, 43, 248}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 75, 181}, 61}, {{0, 0, 0, 0, 0, 0, 98, 234, 225, 232, 129, 249, 67, 25, 86, 179}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 61}, {{0, 0, 245, 127, 197, 97, 126, 126, 73, 153, 205, 234, 169, 117, 180, 0}, 61}, {{0, 0, 0, 0, 0, 51, 104, 237, 140, 211, 129, 205, 248, 187, 191, 58}, 61}, {{0, 0, 0, 0, 0, 0, 0, 92, 69, 178, 142, 57, 101, 50, 177, 55}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 48}, 61}, {{0, 0, 0, 0, 0, 51, 169, 8, 252, 99, 52, 55, 34, 150, 30, 93}, 61}, {{0, 0, 0, 0, 1, 96, 167, 173, 192, 160, 106, 92, 5, 216, 162, 80}, 61}, {{0, 0, 0, 0, 238, 210, 65, 133, 254, 241, 247, 183, 131, 54, 20, 214}, 61}, {{0, 0, 0, 0, 0, 0, 48, 27, 88, 63, 127, 161, 159, 107, 160, 129}, 61}, {{0, 0, 0, 0, 251, 238, 72, 169, 168, 152, 228, 56, 55, 222, 132, 33}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 175, 82, 98, 255, 29, 194}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 66, 164}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 137, 12, 55, 155, 189, 16, 83, 180, 252, 131, 140, 20}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 95}, 61}, {{0, 0, 0, 0, 0, 0, 85, 38, 239, 63, 101, 17, 41, 5, 162, 44}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 46, 156, 186, 25, 187, 89}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 238}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 135}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 27, 203, 99, 13, 79, 211, 188, 237}, 61}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 29, 219, 31}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 233}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 38, 240, 217, 101, 189, 39}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 247, 197}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 152, 49}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 205, 208}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 222}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 202}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 217, 178, 54, 64, 47, 47, 62}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 217, 20, 134, 150}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 105, 117}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 29, 113, 105, 7, 85, 186, 26, 217}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 153, 72, 251, 193, 117}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 135, 203, 42}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 222, 50, 151, 237, 214, 48, 10}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 93}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 141, 204}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 11, 71, 111, 17, 105, 75}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 84}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 12, 86, 203, 76, 53}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 141, 160, 2}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 47, 4}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 178, 23, 150, 86, 178, 251}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 231}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 190, 178, 236, 40, 93, 250, 201}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 240, 158, 182, 222, 124, 196, 130}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 209, 40, 133, 251}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 255, 119, 199, 247}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 45, 90, 72, 52, 178, 196, 156}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 165, 9, 53, 182, 58, 214}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 224, 161, 149, 228, 34, 99, 52}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 7, 76, 240, 169, 231}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 22, 197, 135}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 98, 102, 77}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 184}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 237, 249}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 38, 239, 196, 211}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 194, 66, 20, 88, 1, 226}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 124}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 95, 213}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 33, 142, 53, 177}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 238, 147, 100, 198, 238}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 204, 28, 128}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 199, 117}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 59, 253, 133, 146, 164}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 70, 193, 66, 101, 171}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 84, 107, 59}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 46, 132, 105, 67}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 216, 132, 25, 180, 177}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 96, 50, 149, 165}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 222, 100, 132, 57}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 92, 101, 160, 180, 208, 96}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 151, 245, 69, 70}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 164, 52, 6, 166, 211}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 251}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 75, 181, 46, 133, 30}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 216, 227, 196, 138, 151, 26}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 230}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 158}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 193, 3, 6, 152, 154, 111}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 78, 128, 196, 50}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 160, 85}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 79, 198, 255, 194, 164, 48}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 25, 255, 94, 108}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 217, 251, 146, 167, 38, 25}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 119, 94, 156, 188, 39, 67, 140}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 138, 140, 214, 247, 80, 238, 232}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 134, 106, 80, 222, 120, 82, 57}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 110, 45, 107}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 139, 126, 148, 13, 40, 25}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 55}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 64, 227, 41, 44, 34, 251, 187}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 114, 81, 93, 94}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 19, 113, 82, 157, 125, 33, 252}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 79, 221, 120, 45, 253, 105, 32, 75}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 232, 28, 197, 242, 245, 30, 168, 96}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 109, 93, 219, 17, 101, 225}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 221, 212, 246, 40}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 226, 19, 94}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 51, 200, 52, 86}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 7, 159, 84, 170, 102, 117}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 250, 32}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 98, 204, 39}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 35, 234, 188, 235, 185, 102, 124}, 72}, {{175, 151, 75, 238, 26, 12, 100, 186, 0, 247, 168, 24, 204, 179, 199, 116}, 72}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 72, 34, 147}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 90, 242, 90}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 246, 237, 49, 179}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 126}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 194, 230}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 77}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 164, 53, 56}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 145}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 254, 78, 160}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 185}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 87, 84, 253}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 63, 41}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 63, 6, 220}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 31, 39}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 36, 95, 216}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 67, 122, 29}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 6, 241, 26}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 2, 182, 174}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 159}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 115, 254, 83}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 16, 255, 102}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 150, 78, 235}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 34}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 172}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 160}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 119, 111}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 137, 53}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 130, 169}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 205, 141}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 254, 250}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 162, 20}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 103}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 16, 53, 42}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 127, 63, 116}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 95}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 45, 109, 97}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 15, 70}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 207, 177, 62}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 179}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 213, 198, 172}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 200, 193, 168}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 14, 87, 79}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 160, 12, 77}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 235}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 143}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 187}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 251, 25}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 65}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 210, 89}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 229}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 16, 75}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 44, 106}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 218}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 91, 73}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 21, 216, 128}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 186}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 154, 19, 108, 26}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 119}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 80, 19}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 60, 47}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 144}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 222, 238, 224, 41}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 98, 143, 159, 56}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 45}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 138, 239, 109}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 206, 69, 47}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 164}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 199, 247}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 141}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 101}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 111, 250, 120}, 230}, {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 219, 125}, 230}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 102}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 213}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 75}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 146}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 16}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 231}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 237}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 153}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 32}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 174}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 127}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 120}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 105}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 154}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 139}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 34}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 31}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 124}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 231}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 231}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 75}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 49}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 142}, {{205, 196, 89, 90, 103, 128, 253, 173, 234, 100, 7, 30, 206, 199, 43, 82}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 164, 246, 205, 164, 200, 52}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 234, 11, 28, 48}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 238, 164, 76, 253}, 134}, {{205, 196, 89, 90, 103, 128, 0, 135, 249, 16, 215, 99, 197, 144, 77, 35}, 134}, {{205, 196, 89, 90, 103, 128, 0, 158, 84, 37, 15, 41, 158, 202, 109, 203}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 3, 207, 25, 117, 12, 1, 182}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 195, 161, 205, 109, 0, 2, 95}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 55, 80, 124, 44, 125, 18, 47, 118, 27, 194}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 223, 116, 222, 70, 42}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 86, 6, 96, 204, 134, 140, 183, 49}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 146, 130, 179, 142, 215}, 134}, {{205, 196, 89, 90, 103, 128, 0, 209, 110, 41, 222, 52, 55, 14, 112, 92}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 244, 22, 211}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 223, 236}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 116, 248, 207, 109, 82}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 73, 20, 28, 202, 40, 181}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 102, 234, 75, 143, 160, 37, 178, 93}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 243, 69, 35, 214, 216, 10, 84, 158, 21}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 13, 16, 103, 185, 90, 40, 67, 217}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 117, 89, 89, 189, 43, 13, 218, 255}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 57, 234, 108, 69}, 134}, {{205, 196, 89, 90, 103, 128, 140, 65, 56, 101, 146, 215, 202, 38, 151, 192}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 5, 11}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 132, 133, 152, 164, 153, 24, 6, 140}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 231, 203}, 134}, {{205, 196, 89, 90, 103, 128, 80, 31, 98, 14, 211, 5, 173, 217, 81, 43}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 127, 179}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 109, 218, 101, 26, 74, 219, 83, 227}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 3, 167, 0, 213, 161, 158, 51, 148, 226, 107}, 134}, {{205, 196, 89, 90, 103, 128, 0, 45, 33, 204, 180, 94, 80, 244, 81, 55}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 199, 6, 16, 47, 97, 39, 172, 67}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 230, 39, 39, 162, 253, 0, 48}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 217, 82, 4, 105, 152, 39}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 133, 166}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 215, 186, 37, 235}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 144, 109}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 43, 225}, 134}, {{205, 196, 89, 90, 103, 128, 0, 18, 88, 12, 43, 175, 180, 80, 132, 209}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 136, 195, 58}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 90, 172, 234, 157, 177, 128, 134}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 84, 65, 174}, 134}, {{205, 196, 89, 90, 103, 128, 0, 184, 145, 39, 215, 201, 167, 50, 117, 227}, 134}, {{205, 196, 89, 90, 103, 128, 0, 195, 180, 4, 190, 24, 159, 69, 238, 78}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 85, 26, 49, 157, 157, 195, 126}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 185, 189, 229, 215, 145, 221, 208}, 134}, {{205, 196, 89, 90, 103, 128, 0, 34, 141, 188, 246, 70, 4, 59, 254, 80}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 139, 32, 222, 209, 193, 38}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 133, 89, 254, 3, 110}, 134}, {{205, 196, 89, 90, 103, 128, 132, 123, 53, 233, 134, 81, 35, 234, 243, 239}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 201, 250, 25, 159, 160, 151, 33}, 134}, {{205, 196, 89, 90, 103, 128, 27, 228, 72, 52, 95, 165, 97, 22, 219, 210}, 134}, {{205, 196, 89, 90, 103, 128, 0, 141, 161, 13, 147, 70, 4, 23, 86, 235}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 255, 236, 45, 244, 44, 127, 163, 131}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 157, 129, 69, 247, 65, 199}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 90, 211, 146, 177, 221, 251, 94, 234}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 64, 16}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 219, 148, 63, 182, 51}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 25, 33, 44, 10}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 106, 11, 66}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 21, 110}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 18, 24, 62, 250, 166}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 139, 27}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 175, 83, 137}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 197, 81, 156, 19, 66, 219, 218, 249}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 248, 103, 135, 244, 218}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 122, 166, 91, 99, 138}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 187, 214, 36, 222, 14, 30, 83, 3}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 91, 207, 103, 170, 68, 158}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 179, 175, 172, 150}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 141, 217, 7, 179, 135, 161, 20}, 134}, {{205, 196, 89, 90, 103, 128, 0, 89, 25, 83, 226, 0, 80, 2, 182, 21}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 254, 142, 61, 164, 190}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 172, 31, 247, 240, 26, 190}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 85, 152, 20, 3, 214, 11}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 214, 75, 165, 45, 191, 241, 108}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 115, 81, 127, 239, 187, 94, 172}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 122, 223}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 243, 13, 157, 138, 28, 85, 109}, 134}, {{205, 196, 89, 90, 103, 128, 0, 9, 116, 244, 202, 90, 164, 22, 206, 10}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 41, 37, 254}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 118, 108, 60, 118, 56, 41, 158, 24}, 134}, {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 134}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 64}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 16}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 48}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 139}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 2}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 71}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 106}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 75}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 243}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 31}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 255}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 162}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 201}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 56}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 25}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 67}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 107}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 142}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 180}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 176}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 12}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 165}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 108}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 161}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 57}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 44}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 132}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 176}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 195}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 253}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 200}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 131}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 76}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 174}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 21}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 252}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 26}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 168}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 214}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 109}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 60}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 54}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 196}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 177}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 133}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 188}, 100}, {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 204}, 100}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 245}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 209}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 51}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 161}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 4, 237}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 87}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 77}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 195}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 123, 79}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 131}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 148}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 247, 220}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 107}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 96}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 110}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 75}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 124}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 252}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 111}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 249, 121}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 252, 115}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 137}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 122, 47}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 188, 103}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 84}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 123, 119}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 19}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 78}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 189}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 91, 206}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 64}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 109}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 114}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 121}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 10, 85}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 208, 50}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 84}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 28}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 86}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 172, 197}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 166}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 49}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 52, 73}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 189}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 213}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 219}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 247}, 45}, {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 45}, {{126, 148, 232, 152, 0, 0, 41, 126, 253, 112, 37, 146, 182, 49, 71, 146}, 219}, {{126, 148, 232, 152, 0, 0, 0, 26, 240, 101, 210, 252, 96, 0, 243, 236}, 219}, {{126, 148, 232, 152, 0, 0, 0, 74, 229, 61, 93, 228, 68, 166, 106, 146}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 174, 18, 83, 203, 102}, 219}, {{126, 148, 232, 152, 0, 117, 48, 190, 51, 148, 73, 216, 128, 204, 1, 13}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 190, 76, 249, 221, 60, 239}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 83, 232, 74, 251, 147, 108, 156, 17}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 145, 135, 130, 47, 206, 43, 112, 66}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 54, 41, 225, 124, 22, 70, 166}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 250, 113}, 219}, {{126, 148, 232, 152, 0, 0, 177, 34, 187, 118, 54, 107, 230, 184, 97, 230}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 40, 90, 23, 69, 30}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 191, 150, 80, 100, 115, 66, 229}, 219}, {{126, 148, 232, 152, 0, 94, 207, 180, 130, 103, 230, 46, 11, 115, 116, 229}, 219}, {{126, 148, 232, 152, 184, 161, 106, 148, 196, 168, 198, 153, 47, 106, 234, 198}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 38}, 219}, {{126, 148, 232, 152, 2, 223, 239, 164, 202, 164, 1, 250, 250, 158, 27, 36}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 98, 19, 152, 122}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 128, 123, 90, 56}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 197, 28, 45, 104}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 173, 181, 6, 171, 136, 169, 135, 178}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 137, 134, 190, 130, 193, 137, 111}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 67, 20, 90, 209, 249, 253, 85, 247}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 135, 38, 117, 167, 245, 128, 100}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 33, 229, 144, 101, 17}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 111, 142, 85, 181, 244}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 84, 173, 62, 205}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 248, 85, 159, 118, 28, 77, 148, 236}, 219}, {{126, 148, 232, 152, 0, 0, 111, 54, 202, 120, 162, 132, 108, 3, 166, 191}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 86, 255}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 23}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 1, 167}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 168, 82, 52, 74, 135, 190, 85}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 59, 8, 198, 177, 182, 227}, 219}, {{126, 148, 232, 152, 0, 0, 136, 87, 164, 183, 93, 155, 36, 158, 99, 77}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 214, 76, 147, 54}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 236, 70, 100, 54, 101, 7}, 219}, {{126, 148, 232, 152, 0, 0, 0, 61, 168, 202, 124, 100, 134, 120, 201, 5}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 253}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 87, 100, 4, 179}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 142, 66, 55, 112, 197, 83}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 150, 163}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 166, 239, 206, 155, 152, 224, 16}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 100, 74, 39, 116, 87, 203}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 71, 218, 21, 205, 147, 221, 171, 131, 152}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 25, 139, 81, 176, 218, 11, 244, 33, 194}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 62, 214, 172, 114, 156, 16}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 127, 25, 232, 93, 3}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 95, 175, 209, 207, 173, 46}, 219}, {{126, 148, 232, 152, 0, 0, 0, 182, 164, 195, 145, 160, 249, 137, 109, 222}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 30, 69, 119, 95, 27}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 127, 23, 250, 187, 225, 111, 203}, 219}, {{126, 148, 232, 152, 108, 251, 162, 76, 58, 181, 145, 159, 120, 43, 254, 250}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 219}, {{126, 148, 232, 152, 0, 0, 105, 149, 217, 206, 68, 25, 13, 225, 129, 196}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 102, 110, 156, 145, 125, 172, 199}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 115}, 219}, {{126, 148, 232, 152, 0, 0, 117, 152, 201, 208, 123, 217, 54, 15, 243, 238}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 193, 61, 107, 136}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 81}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 58, 100, 249, 241, 44, 60, 44}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 159, 139}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 81, 172, 51, 150, 240}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 1, 72, 136, 18}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 207, 86, 70, 156, 48, 69, 240}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 236, 43, 131, 116, 154}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 231, 210, 35, 37, 219, 151}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 32, 199, 43, 140, 244}, 219}, {{126, 148, 232, 152, 0, 0, 0, 224, 224, 65, 5, 75, 137, 123, 7, 92}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 200, 238, 179, 239, 80, 27, 250, 20}, 219}, {{126, 148, 232, 152, 0, 0, 0, 47, 222, 205, 206, 4, 188, 106, 111, 81}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 221, 244, 196, 109, 208, 148, 38, 137}, 219}, {{126, 148, 232, 152, 0, 0, 123, 135, 125, 217, 251, 205, 106, 33, 166, 171}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 207, 54, 180, 243, 113, 82, 149}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 98, 181, 107, 204}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 153, 8, 101, 91}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 251, 135, 235, 73, 217}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 56, 252, 192, 212, 235}, 219}, {{126, 148, 232, 152, 0, 0, 0, 208, 214, 229, 1, 100, 50, 161, 226, 188}, 219}, {{126, 148, 232, 152, 0, 177, 106, 213, 212, 17, 216, 61, 28, 15, 37, 220}, 219}, {{126, 148, 232, 152, 14, 116, 164, 26, 104, 253, 105, 184, 18, 224, 27, 209}, 219}, {{126, 148, 232, 152, 0, 0, 0, 0, 0, 21, 115, 235, 189, 85, 245, 49}, 219}, {{160, 72, 0, 0, 254, 47, 229, 43, 133, 153, 194, 146, 133, 187, 44, 226}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 56, 25, 77, 74}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 13, 82, 87, 120, 120, 61, 226, 54}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 43, 107, 169, 142, 177, 86}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 115, 114, 87}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 216, 59, 95, 131, 54, 33}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 232}, 52}, {{160, 72, 0, 0, 36, 183, 79, 237, 119, 39, 176, 161, 198, 15, 2, 51}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 48, 83, 186, 11, 16, 170, 96, 52}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 137, 239, 121, 243, 188, 89, 121}, 52}, {{160, 72, 0, 0, 0, 53, 63, 158, 148, 191, 150, 56, 239, 87, 239, 183}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 207, 66, 203, 186, 84, 197}, 52}, {{160, 72, 0, 8, 18, 165, 186, 70, 153, 85, 43, 192, 49, 155, 158, 226}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 206, 54, 45, 242, 205, 179, 219}, 52}, {{160, 72, 0, 0, 0, 0, 253, 36, 196, 248, 238, 160, 189, 14, 70, 190}, 52}, {{160, 72, 0, 0, 0, 0, 0, 145, 245, 98, 110, 50, 24, 91, 200, 247}, 52}, {{160, 72, 0, 0, 0, 226, 32, 116, 136, 141, 208, 67, 194, 60, 16, 29}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 52}, {{160, 72, 0, 0, 63, 168, 18, 73, 112, 12, 228, 180, 55, 197, 235, 95}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 136, 16, 120}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 235, 100}, 52}, {{160, 72, 0, 0, 0, 0, 214, 113, 30, 24, 93, 28, 216, 88, 206, 204}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 1}, 52}, {{160, 72, 0, 0, 0, 0, 250, 222, 15, 119, 24, 154, 123, 236, 109, 232}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 132, 128}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 189, 108, 39, 231, 245, 192, 129, 114}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 26, 39, 46, 142, 213, 8, 169, 83}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 129, 197, 254, 251, 93, 101}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 185, 107, 31}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 123, 68, 142, 199}, 52}, {{160, 72, 0, 0, 0, 0, 107, 245, 130, 138, 1, 66, 166, 37, 194, 168}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{160, 72, 0, 0, 74, 74, 40, 70, 74, 166, 23, 157, 3, 10, 173, 102}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 80, 165, 152, 172}, 52}, {{160, 72, 0, 0, 0, 124, 211, 160, 45, 124, 205, 140, 24, 23, 159, 239}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 165, 89, 56, 87}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 131, 186, 156, 30, 238, 120, 108, 46}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{160, 72, 0, 0, 80, 130, 162, 133, 225, 24, 127, 255, 195, 4, 1, 233}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 243, 53, 164, 102, 150, 74, 92}, 52}, {{160, 72, 0, 55, 53, 5, 205, 31, 10, 35, 115, 110, 95, 135, 34, 170}, 52}, {{160, 72, 0, 0, 0, 140, 85, 170, 71, 43, 125, 79, 112, 233, 224, 146}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 166, 143, 112, 12}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 143, 69, 11, 207, 58, 132, 92, 37}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 107, 103, 96, 41}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 134, 73, 89, 110, 137, 161}, 52}, {{160, 72, 0, 0, 26, 177, 16, 122, 119, 2, 144, 140, 183, 25, 196, 219}, 52}, {{160, 72, 0, 0, 34, 34, 75, 236, 26, 137, 126, 73, 93, 87, 204, 49}, 52}, {{160, 72, 0, 0, 0, 0, 0, 163, 205, 193, 124, 107, 131, 76, 97, 18}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 24, 158, 24, 109, 223, 24}, 52}, {{160, 72, 0, 0, 106, 181, 120, 45, 184, 203, 15, 212, 252, 90, 126, 226}, 52}, {{160, 72, 0, 0, 0, 122, 237, 146, 104, 13, 234, 54, 225, 185, 105, 217}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 212, 255}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 13, 149, 118, 230, 120, 203, 132}, 52}, {{160, 72, 0, 0, 230, 82, 85, 211, 50, 29, 109, 203, 96, 216, 173, 154}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 52}, {{160, 72, 0, 0, 0, 0, 64, 205, 46, 187, 161, 237, 229, 90, 252, 243}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 177, 240, 48, 30}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 184, 1, 4, 153, 27, 210, 168, 39}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 201, 162, 111, 50, 52, 67, 128, 59}, 52}, {{160, 72, 0, 240, 121, 218, 167, 10, 221, 219, 157, 173, 216, 36, 16, 250}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 198, 212, 112, 181}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 42, 61}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 128}, 52}, {{160, 72, 0, 0, 0, 57, 198, 211, 90, 183, 165, 118, 38, 152, 200, 88}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 199}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 37, 113, 255, 142, 201, 67, 12}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 20, 236, 45}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 239, 217, 34, 140, 174, 189, 165}, 52}, {{160, 72, 0, 0, 161, 205, 126, 61, 21, 171, 102, 66, 110, 141, 54, 10}, 52}, {{160, 72, 0, 0, 0, 0, 127, 133, 127, 45, 182, 198, 31, 125, 223, 18}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 229, 233, 216}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 129, 221, 41, 65, 130, 211, 53, 153}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 202, 128, 186}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 224, 48, 21, 75}, 52}, {{160, 72, 0, 0, 0, 0, 0, 203, 248, 12, 206, 3, 148, 233, 164, 97}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 45, 73, 191}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 158, 113, 231, 123, 203, 8, 174}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 49, 138}, 52}, {{160, 72, 0, 0, 0, 0, 127, 243, 199, 208, 33, 28, 190, 119, 68, 122}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 1, 215, 4, 239, 102, 126}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 137}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 147, 152, 163, 177, 209, 174, 239}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 136, 44, 89, 140, 112, 195}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 248, 230, 89, 167, 76, 66, 163, 114}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 174}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 78, 210}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 51, 167}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 8, 140, 157, 32, 15, 85, 42}, 52}, {{160, 72, 0, 0, 112, 115, 203, 117, 219, 37, 58, 179, 123, 170, 239, 224}, 52}, {{160, 72, 0, 0, 0, 0, 126, 77, 45, 160, 62, 157, 169, 202, 150, 217}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 38, 63, 127, 54, 25, 200, 32}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 78, 221, 250, 41, 79, 10, 4}, 52}, {{160, 72, 0, 0, 0, 68, 47, 165, 52, 252, 242, 120, 108, 54, 145, 154}, 52}, {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 27, 12}, 52}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 199, 9, 56}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 204}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 219}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 166, 16, 95, 15, 53}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 86, 236}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 194, 86, 106}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 202, 69, 213, 34, 188}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 94}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 125}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 152, 127, 226, 8, 22}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 33, 193, 165, 38, 130}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 120, 10, 84}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 235}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 66, 243, 245, 47}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 239, 63, 243}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 197, 96, 189}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 124}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 22, 188}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 143, 54, 208, 101}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 113, 125}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 83, 132}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 155}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 94, 118}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 254, 188, 245, 108}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 190, 211, 142, 123}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 157, 105, 197}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 240}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 203, 177, 93, 108}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 12, 243, 165, 153, 125}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 61, 164, 40, 97}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 49}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 105, 176, 216}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 74, 159, 129}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 112, 240, 189}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 209}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 219, 4}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 90, 162}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 36, 254, 56}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 107, 243, 97, 215}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 49, 50}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 166, 240, 233, 18}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 134, 94, 83, 34, 148}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 77}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 239, 5}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 86}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 199, 12, 167}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 51, 90, 244, 188}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 155, 63}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 66}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 156, 53, 2, 217, 204}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 67, 197, 137}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 108, 137, 193}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 153, 192, 98, 58, 118}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 174, 57, 203}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 243}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 67, 69, 230, 204}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 67, 142, 153}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 128, 98, 79, 85, 133}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 218, 42, 125}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 179, 73, 103}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 159, 213}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 205, 29, 96, 8}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 86}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 207, 10}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 177, 192, 157, 48, 22}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 175}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 100, 140, 187}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 254, 174}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 22, 8, 26}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 201, 51, 140, 212, 21}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 89, 17}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 119, 167, 41}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 241}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 19, 143, 158, 74}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 88}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 15}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 58, 154, 66, 203, 63}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 167, 62, 107, 148, 5}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 161}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 58}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 227, 214, 215}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 68, 243, 73, 74}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 46, 38, 95}, 240}, {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 100, 58}, 240}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 209, 239, 43}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 54, 76}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 249, 52, 111}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 174, 151, 205}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 100, 171, 169}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 217}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 76}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 88, 199}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 100, 203, 68, 146}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 143}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 63, 83, 74}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 249, 42, 136, 42}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 138, 62, 174}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 141, 75}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 129, 40, 249}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 17, 225, 118}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 204, 205, 197, 135}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 87, 40}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 7, 72, 86, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 209}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 200, 225, 37, 229}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 181, 129}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 221}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 105, 128}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 124, 123}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 131, 88, 19}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 34}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 144, 243, 208, 45}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 63, 228, 252, 68}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 178}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 29}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 91}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 40}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 37}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 131, 27, 80, 168}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 82}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 191}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 69}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 15}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 254, 70}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 22, 227, 170}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 143, 18}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 184, 123, 232, 112}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 27}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 111, 212, 120, 152}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 67, 137}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 168, 125, 10, 78}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 158}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 166, 69, 154, 215}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 151, 51, 186, 132}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 116, 176}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 60}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 162}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 19, 91, 236, 142}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 240, 110}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 104}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 118, 242}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 144, 188, 224}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 131}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 57, 25, 203}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 5, 115}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 74, 59}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 141, 223, 141}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 24}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 208}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 136, 99}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 102, 199, 166}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 183, 101, 58, 205}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 203}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 131, 245, 86, 12}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 42}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 34}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 189, 43, 135}, 13}, {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 62}, 13}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 217, 164, 18}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 204}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 57, 212}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 161, 43, 226, 199, 178}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 160, 234, 229, 168}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 168, 11, 189, 42}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 93}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 51, 225, 183, 207}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 185, 202}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 182, 251, 137}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 223, 70, 207, 93}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 131, 82}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 244, 236, 97}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 49}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 190, 181}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 201, 249, 101, 1}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 184, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 246, 129, 82, 230, 215}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 88, 241, 227}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 202, 239, 102}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 207, 188}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 229, 245}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 236, 75, 234}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 122}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 25, 177}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 153, 152, 150, 22, 109}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 3}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 126, 145}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 228, 220}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 120, 191, 78}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 45}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 250, 3, 182, 65}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 196, 123, 234}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 31}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 124, 212}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 250, 71, 243, 13, 99}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 78, 129, 193, 142}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 239, 58, 136, 245, 223}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 33}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 187}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 147, 232, 160, 20}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 255, 219}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 57}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 182, 137, 161, 190}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 181, 160}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 214}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 178, 65, 46}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 127, 17, 155, 200}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 103}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 70, 13, 71}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 157, 18, 252}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 86, 80, 184, 159}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 147}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 250, 175, 2, 54, 3}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 111}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 31, 48}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 49, 169}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 121, 108, 131}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 109, 127, 24}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 174, 211}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 225, 91, 148, 44}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 94}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 220}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 127}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 21, 108, 205}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 48, 8}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 251}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 163, 125, 7, 98}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 242}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 90, 23}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 67, 54, 50, 146}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 84, 247, 66}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 137, 147, 194, 137}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 20, 41}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 147, 229, 197, 47, 6}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 157, 203, 185, 107}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 27, 61, 91, 172}, 191}, {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 187}, 191}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 184}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 9}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 131, 241}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 213}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 255, 182}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 83}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 128, 25}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 51}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 194}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 20, 44}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 211}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 128, 113}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 211}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 221}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 82, 158}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 255}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 63, 15}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 85}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 136}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 219}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 107}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 97}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 201}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 52}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 255}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 245}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 192, 170}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 225}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 188}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 84}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 138, 69}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 227, 174}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 115, 98}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 52}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 194}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 60, 132}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 184}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 44, 42}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 131}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 181}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 184}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 17, 29}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 14}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 69, 214}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 195}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 155}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 159, 43}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 113}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 131, 203}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 40}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 127}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 178}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 82}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 48}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 252, 255}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 95}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 186}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 230}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 232}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 154, 12}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 11}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 95}, {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 193, 253}, 95}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 78, 72, 139, 48, 254}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 29}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 93, 221, 241, 10, 168, 159, 237}, 65}, {{91, 94, 36, 48, 0, 0, 97, 47, 110, 107, 39, 123, 166, 236, 165, 142}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 52, 177, 128, 209}, 65}, {{91, 94, 36, 48, 0, 0, 61, 1, 121, 245, 104, 161, 56, 219, 129, 162}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 186, 166, 194, 1}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 217, 59, 57, 74}, 65}, {{91, 94, 36, 48, 0, 173, 123, 155, 74, 182, 127, 155, 151, 112, 226, 66}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 209, 81}, 65}, {{91, 94, 36, 48, 0, 0, 116, 8, 15, 157, 220, 254, 4, 176, 82, 205}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 70}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 27, 237, 220, 236, 192}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 107, 70, 91, 229, 167, 236, 51, 190}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 104, 38}, 65}, {{91, 94, 36, 48, 0, 16, 193, 103, 66, 111, 157, 255, 13, 184, 138, 155}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 9, 161, 39, 70, 208, 129, 151, 130}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 31, 68, 39, 130}, 65}, {{91, 94, 36, 48, 0, 147, 53, 169, 187, 104, 121, 103, 112, 213, 211, 11}, 65}, {{91, 94, 36, 48, 0, 0, 141, 19, 90, 238, 136, 240, 58, 237, 94, 140}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 222, 175, 233, 67, 50, 74, 159, 197}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 196, 206, 225, 33, 180, 212, 159, 136}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 116, 47, 194, 5, 175, 202, 16}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 124, 12, 254, 48}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 96, 223}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 78, 106, 48, 205, 184, 75, 74, 70, 220, 65, 12}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 47, 95}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 165}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 162, 76, 246, 200}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 95, 228, 122, 63, 21, 104}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 157, 93, 70, 53, 90, 209}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 171, 132, 88, 104, 186, 45, 222}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 108, 140, 226, 91, 38}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 68, 110, 7, 87, 126}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 59}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 81, 146, 5, 194, 0, 205, 243}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 76, 83, 191, 250, 187, 23}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 48}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 247, 89}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 75, 73, 8, 52, 7, 18, 70}, 65}, {{91, 94, 36, 48, 0, 0, 140, 15, 121, 70, 99, 50, 121, 58, 44, 219}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 214, 164, 217, 47, 148, 14, 89}, 65}, {{91, 94, 36, 48, 0, 0, 0, 17, 133, 243, 160, 55, 98, 17, 124, 136}, 65}, {{91, 94, 36, 48, 0, 9, 44, 23, 190, 43, 43, 214, 133, 141, 220, 1}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 146, 189, 14, 196, 110, 166, 17, 138, 227}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 18, 26, 139, 141, 205, 30}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 211, 62}, 65}, {{91, 94, 36, 48, 0, 0, 0, 184, 170, 194, 78, 9, 210, 106, 219, 194}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 212, 167, 223, 185, 171, 37, 94}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 57, 126, 11, 117, 170, 185, 9, 154}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 202, 172, 80, 229, 42, 57, 151, 113}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 84, 195}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 204, 182, 29, 157, 253, 107, 49}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 3, 201, 148, 65, 99, 31, 246, 57}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 90, 187}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 244, 214, 10, 31, 46, 206}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 176, 143, 95, 115, 101, 168}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 186, 10}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 94, 30, 51, 220}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 11, 132, 177, 89, 126, 102}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 242, 81, 9, 125, 126, 103, 127, 228, 64, 59, 183, 216}, 65}, {{91, 94, 36, 48, 90, 116, 79, 9, 120, 134, 169, 174, 28, 176, 236, 249}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 245, 234, 10, 196, 37, 167, 150, 191}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 28, 233, 85, 42, 53, 175}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 166}, 65}, {{91, 94, 36, 48, 0, 0, 104, 6, 12, 30, 7, 35, 72, 14, 2, 11}, 65}, {{91, 94, 36, 48, 0, 0, 92, 87, 242, 132, 38, 55, 195, 183, 232, 121}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 252, 238, 9, 45}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 127, 87, 184, 252}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 106, 221, 245, 122}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 155, 190, 112, 25, 134}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 8, 42, 229, 54}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 254, 71, 50, 185, 63, 35, 222}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 211, 76}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 191, 66, 155, 100, 128, 73, 32}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 226, 35, 255, 171, 136, 170, 29}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 134, 177, 224, 229, 204}, 65}, {{91, 94, 36, 48, 0, 0, 0, 49, 43, 115, 209, 186, 176, 189, 38, 220}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 218, 178}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 29, 242, 241, 60, 241, 18, 220}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 57, 26}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 224, 33, 62, 220, 246}, 65}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 99, 190, 155, 109, 98, 146}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 138, 52, 79, 215, 231, 222, 80, 71}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 41, 252, 25, 46, 84, 102}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 101, 195, 186, 18, 207, 131, 47}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 202, 135, 247, 129, 202, 15}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 252, 247, 9, 41, 133, 40, 231}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 248, 158, 149, 94, 155, 5}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 120, 135, 167, 33}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 245, 173, 33, 74, 208, 142, 77, 236}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 119, 28, 147, 216}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 127, 43, 114, 182, 102}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 92, 32, 193, 42, 134, 227, 159, 35}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 164, 5}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 246, 156}, 195}, {{209, 238, 110, 0, 2, 152, 0, 214, 80, 143, 133, 128, 113, 125, 44, 207}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 211, 38}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 47, 125}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 114, 196, 62, 97, 218, 240, 146}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 160, 155, 206, 134, 222, 37}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 110, 21, 162}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 71, 109}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 75, 189, 41, 11}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 157, 167, 194, 206}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 87, 50, 167}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 180, 46, 23, 96, 148, 217, 144, 63}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 188, 41, 244, 128, 92, 242, 148, 195}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 210, 78, 136, 10, 130, 137}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 17, 110}, 195}, {{209, 238, 110, 0, 2, 152, 130, 165, 44, 100, 45, 3, 81, 34, 166, 184}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 45, 226, 37, 26, 123, 249, 241, 125}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 118, 220, 219}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 130, 90, 112, 218, 120, 44}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 199, 24, 142, 71}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 50, 106, 154, 190, 48, 220}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 196, 38}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 118, 146, 111, 189}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 140, 155, 188}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 50, 181, 156, 253, 75, 127}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 50, 117, 174, 51}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 140, 67, 226, 38, 205, 88, 56}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 184, 103, 211}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 218, 19, 68, 130, 82, 34, 215, 155}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 174, 44, 77, 215, 143}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 51, 77, 27}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 67, 18, 153}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 230, 157}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 66, 168, 227, 147, 134}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 209, 170, 206, 231}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 117, 220, 127, 79, 82, 206, 228}, 195}, {{209, 238, 110, 0, 2, 152, 0, 178, 142, 192, 153, 36, 131, 58, 254, 202}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 103, 106, 204, 56, 164}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 166, 189, 187, 88}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 10, 253, 245, 52, 42, 29}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 249, 65, 90, 169, 19, 147, 71, 12}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 124, 133, 137, 7, 143}, 195}, {{209, 238, 110, 0, 2, 152, 0, 161, 1, 18, 179, 178, 91, 90, 107, 61}, 195}, {{209, 238, 110, 0, 2, 152, 0, 91, 179, 231, 101, 204, 181, 195, 20, 202}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 160, 216, 13, 246, 132, 195, 168}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 146, 91, 209, 115, 199, 181, 23, 233}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 66, 133, 219, 78}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 217, 232, 244, 204, 243, 230, 6, 35}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 37, 199, 202, 111, 248, 170, 55, 36, 17}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 183, 26, 137}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 60, 169, 61, 194}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 57, 34, 165}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 70, 138, 80, 54, 9, 214}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 106, 246}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 166, 40, 140, 65, 14}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 122, 161, 11, 15, 158, 213}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 129, 53, 97}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 93, 209, 19, 138, 116, 115, 43}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 248, 171, 108, 3, 95}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 75, 228, 105, 61, 27}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 99, 37}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 20, 105}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 109, 131, 143}, 195}, {{209, 238, 110, 0, 2, 152, 0, 130, 182, 186, 43, 2, 131, 182, 45, 240}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 116, 84, 182, 107}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 201, 55, 9, 191}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 164, 9, 239, 106, 88, 220}, 195}, {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 22, 87, 53, 47}, 195}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 118, 77}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 98, 181}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 174}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 217}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 240, 78, 161}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 16, 129}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 252}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 247}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 145, 143}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 219, 188}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 86, 33}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 209}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 54, 212, 248}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 47}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 187}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 104, 253}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 24, 106}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 30, 174, 68}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 231}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 147}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 156}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 156, 32}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 160}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 72, 247, 35}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 141}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 192, 110}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 113, 226}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 45}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 112}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 17, 208}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 75, 19, 111}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 121, 177}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 34, 182}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 49}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 123, 134}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 177, 248}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 130}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 1, 247}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 77}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 146, 222}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 195}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 251, 176}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 123, 255}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 101, 129}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 1}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 179, 124}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 51, 218}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 136, 152}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 246, 195}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 192, 242}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 108, 220}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 57}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 234, 216}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 234, 124, 180}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 189}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 125}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 187, 27}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 155, 221}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 50, 121}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 235, 145}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 211}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 24}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 136, 241}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 64}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 23, 253}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 70, 139}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 151, 210, 172}, 21}, {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 181, 219}, 21}, {{112, 0, 0, 0, 0, 0, 190, 134, 227, 32, 46, 156, 96, 176, 252, 27}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 226}, 3}, {{112, 0, 0, 0, 0, 0, 0, 199, 203, 104, 84, 26, 43, 137, 163, 69}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 115, 193, 47, 150, 129}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 170, 152, 46}, 3}, {{112, 0, 0, 0, 0, 0, 12, 185, 94, 156, 183, 14, 43, 180, 65, 187}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 168, 164, 169, 244, 20, 137, 252, 152}, 3}, {{112, 0, 0, 0, 188, 130, 151, 92, 208, 13, 221, 100, 80, 39, 6, 223}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 163, 53}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 108, 132, 94}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 174, 93, 222, 30, 137, 176, 218}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 30, 156, 182}, 3}, {{112, 0, 0, 0, 16, 16, 134, 20, 4, 30, 0, 19, 73, 172, 207, 182}, 3}, {{112, 0, 117, 33, 27, 15, 14, 93, 82, 139, 26, 227, 162, 26, 107, 198}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 186, 49, 12, 243}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 3}, {{112, 0, 0, 0, 0, 0, 254, 96, 138, 194, 8, 96, 129, 45, 86, 121}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 26, 89, 99, 175, 6, 150, 188, 141}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 72, 198}, 3}, {{112, 0, 0, 0, 0, 32, 249, 207, 211, 39, 199, 58, 237, 255, 207, 199}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 230, 94, 113, 219}, 3}, {{112, 0, 0, 184, 60, 121, 20, 56, 109, 243, 22, 0, 192, 204, 220, 30}, 3}, {{112, 0, 0, 0, 0, 0, 189, 15, 102, 109, 212, 34, 97, 53, 92, 12}, 3}, {{112, 204, 148, 236, 106, 207, 1, 51, 18, 219, 201, 55, 53, 119, 116, 234}, 3}, {{112, 0, 0, 0, 0, 62, 93, 143, 136, 176, 164, 253, 88, 67, 171, 95}, 3}, {{112, 0, 0, 0, 169, 149, 19, 213, 100, 172, 147, 181, 139, 216, 158, 2}, 3}, {{112, 0, 0, 197, 212, 149, 209, 173, 147, 0, 157, 129, 38, 91, 212, 142}, 3}, {{112, 0, 0, 57, 173, 79, 161, 87, 58, 91, 29, 87, 27, 122, 194, 79}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 5, 73}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 139}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 55, 147, 51, 87}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 205, 148, 184, 18, 227}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 178}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 9}, 3}, {{112, 0, 9, 14, 217, 34, 212, 2, 46, 133, 86, 74, 195, 42, 69, 20}, 3}, {{112, 0, 0, 225, 40, 29, 103, 157, 240, 105, 91, 139, 250, 95, 153, 109}, 3}, {{112, 0, 0, 0, 0, 250, 182, 251, 21, 184, 94, 195, 247, 59, 190, 119}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 201, 99, 236, 28}, 3}, {{112, 0, 0, 0, 0, 0, 0, 248, 104, 159, 59, 159, 155, 215, 222, 199}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 62, 234, 245}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 124}, 3}, {{112, 0, 0, 0, 0, 0, 0, 224, 175, 228, 229, 172, 230, 134, 137, 114}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 109, 117, 71, 106, 225}, 3}, {{112, 0, 0, 0, 0, 0, 0, 244, 180, 239, 70, 120, 110, 186, 71, 45}, 3}, {{112, 0, 0, 100, 203, 250, 74, 171, 68, 123, 172, 116, 73, 8, 164, 103}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 197}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 65, 244, 7, 227, 236}, 3}, {{112, 0, 0, 0, 0, 0, 0, 84, 41, 118, 227, 160, 172, 249, 169, 188}, 3}, {{112, 0, 0, 27, 227, 130, 99, 235, 235, 71, 28, 112, 146, 178, 144, 93}, 3}, {{112, 0, 0, 0, 0, 29, 218, 157, 207, 27, 30, 78, 22, 7, 192, 144}, 3}, {{112, 0, 0, 0, 0, 0, 226, 202, 228, 73, 90, 60, 124, 180, 253, 155}, 3}, {{112, 0, 0, 0, 0, 0, 245, 183, 164, 112, 88, 251, 121, 137, 212, 157}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 90, 179, 49, 64, 5, 72, 128, 194, 26, 4, 96, 9}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 42, 200, 255}, 3}, {{112, 0, 0, 0, 0, 237, 224, 67, 28, 68, 122, 150, 142, 124, 47, 70}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 117, 4}, 3}, {{112, 0, 83, 126, 216, 152, 197, 7, 60, 79, 73, 157, 179, 49, 188, 107}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 168, 46, 72, 124, 161, 216, 34, 52, 48}, 3}, {{112, 0, 0, 0, 0, 0, 140, 21, 182, 253, 92, 2, 186, 27, 247, 233}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 190, 220, 117, 101, 240}, 3}, {{112, 0, 0, 8, 170, 101, 80, 47, 50, 22, 29, 152, 78, 105, 212, 197}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 147, 54, 150, 39}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 3}, {{112, 0, 0, 0, 0, 30, 185, 163, 41, 213, 25, 210, 241, 83, 241, 60}, 3}, {{112, 0, 0, 0, 0, 0, 216, 119, 79, 226, 111, 249, 123, 215, 185, 248}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 137, 72, 255, 178, 93, 37, 186, 161, 114, 55, 35, 190, 57, 160}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 238, 53, 206, 238, 23, 210, 190, 21}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 77, 25, 115, 127, 50, 97, 0, 222}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 141, 9, 236, 121}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 77, 204, 181, 228, 178}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 52, 84, 150, 201, 83, 210, 251, 66}, 3}, {{112, 0, 0, 0, 0, 0, 0, 68, 230, 59, 22, 68, 40, 172, 200, 54}, 3}, {{112, 0, 217, 110, 15, 243, 50, 13, 229, 207, 120, 221, 169, 210, 196, 28}, 3}, {{112, 0, 0, 0, 0, 0, 216, 194, 192, 67, 227, 14, 226, 166, 79, 7}, 3}, {{112, 0, 0, 0, 0, 0, 218, 237, 201, 157, 200, 112, 224, 51, 76, 115}, 3}, {{112, 0, 0, 124, 85, 150, 31, 195, 4, 9, 71, 52, 74, 50, 38, 243}, 3}, {{112, 0, 0, 145, 177, 175, 3, 35, 151, 249, 144, 101, 155, 224, 216, 175}, 3}, {{112, 0, 0, 52, 248, 181, 48, 88, 204, 209, 212, 165, 218, 148, 242, 123}, 3}, {{112, 0, 0, 214, 85, 120, 6, 67, 49, 12, 19, 4, 217, 101, 253, 125}, 3}, {{112, 0, 0, 0, 0, 0, 0, 134, 104, 124, 194, 76, 158, 50, 50, 153}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 226, 213, 149, 102, 99, 180, 15, 182}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 183, 217, 159, 48, 205, 255, 167, 139, 200, 53, 183, 175, 32}, 3}, {{112, 0, 0, 0, 0, 0, 0, 175, 39, 0, 66, 187, 255, 54, 33, 250}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 154, 31, 241, 8}, 3}, {{112, 0, 33, 104, 204, 67, 4, 250, 81, 90, 84, 185, 101, 73, 51, 253}, 3}, {{102, 96, 223, 28, 0, 0, 186, 40, 75, 221, 240, 73, 154, 223, 127, 45}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 106}, 92}, {{102, 96, 223, 28, 0, 0, 0, 120, 119, 141, 41, 166, 10, 201, 18, 123}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 84, 82, 165, 132, 184}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 92}, {{102, 96, 223, 28, 0, 0, 181, 179, 207, 149, 11, 174, 31, 149, 55, 194}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 101, 52}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 160, 198, 91, 217, 213}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 120}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 218, 217, 153, 106, 245, 112}, 92}, {{102, 96, 223, 28, 0, 38, 40, 121, 95, 80, 95, 110, 59, 226, 205, 236}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 43, 91}, 92}, {{102, 96, 223, 28, 0, 0, 0, 179, 9, 226, 26, 163, 167, 63, 82, 33}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 214, 197, 91, 21, 19, 255, 185, 92, 91, 28, 104}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 247, 46, 231, 21}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 60}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 26, 159, 207, 173, 152, 148}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 202}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 19, 120, 26, 137, 152, 41}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 37, 49}, 92}, {{102, 96, 223, 28, 0, 91, 84, 106, 187, 193, 122, 123, 60, 251, 117, 63}, 92}, {{102, 96, 223, 28, 0, 0, 0, 246, 198, 134, 116, 36, 143, 72, 153, 60}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 216, 152, 133, 152, 1, 81}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 180, 35, 213, 204, 219, 94, 248, 39}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 236, 244, 201, 183, 165, 184, 32, 143}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 132, 52, 46, 211, 107, 170, 49}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 190, 144}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 164, 182, 104, 149, 16, 150, 156, 227, 155}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 218, 206, 19, 139, 184, 126, 133, 39}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 91, 118, 10, 232, 106}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 176, 34, 193, 222, 233, 44}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 223, 165}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 60, 40}, 92}, {{102, 96, 223, 28, 0, 85, 236, 92, 214, 57, 51, 119, 173, 147, 105, 91}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 57, 197, 93, 122, 233, 30, 41, 61}, 92}, {{102, 96, 223, 28, 0, 99, 80, 243, 160, 114, 73, 207, 95, 161, 247, 61}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 165, 21, 44, 114, 155, 153, 224, 133}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 116, 212, 205, 238, 141}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 90}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 43, 3}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 129}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 92}, {{102, 96, 223, 28, 0, 0, 0, 230, 41, 14, 189, 36, 28, 170, 57, 27}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 108, 136, 10, 88, 203, 227, 94}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 190, 59, 208, 177, 202, 153}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 15, 61}, 92}, {{102, 96, 223, 28, 0, 0, 0, 122, 64, 4, 207, 58, 19, 1, 58, 57}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 80}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 234, 169, 133, 53, 138, 88, 25, 77}, 92}, {{102, 96, 223, 28, 202, 191, 68, 223, 75, 184, 238, 182, 119, 120, 144, 166}, 92}, {{102, 96, 223, 28, 0, 0, 211, 176, 238, 132, 170, 237, 23, 201, 46, 56}, 92}, {{102, 96, 223, 28, 0, 29, 139, 101, 156, 21, 197, 178, 25, 95, 18, 5}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 243}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 147, 242, 74, 34, 195, 12}, 92}, {{102, 96, 223, 28, 0, 0, 0, 218, 179, 143, 85, 237, 225, 136, 215, 159}, 92}, {{102, 96, 223, 28, 0, 0, 147, 7, 210, 42, 19, 240, 75, 243, 93, 91}, 92}, {{102, 96, 223, 28, 0, 0, 0, 105, 212, 88, 164, 171, 94, 176, 114, 130}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 178, 119}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 64}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 244, 98, 139, 213, 21, 64}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 125, 252, 108, 70}, 92}, {{102, 96, 223, 28, 0, 132, 228, 243, 188, 166, 216, 69, 13, 103, 70, 5}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 121, 83, 173, 239, 150, 177, 15, 94}, 92}, {{102, 96, 223, 28, 0, 55, 160, 76, 69, 145, 220, 90, 134, 127, 26, 79}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 116, 66, 210, 207, 222}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 48, 254}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 206, 40}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 170, 242, 136, 73, 12, 70, 190}, 92}, {{102, 96, 223, 28, 0, 0, 176, 161, 88, 178, 148, 158, 236, 236, 12, 108}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 224, 152, 103, 16, 199, 126, 149, 237}, 92}, {{102, 96, 223, 28, 0, 0, 176, 255, 249, 119, 196, 104, 90, 125, 164, 113}, 92}, {{102, 96, 223, 28, 0, 0, 0, 196, 255, 74, 12, 146, 90, 46, 122, 100}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 253, 107, 239, 201}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 190, 54}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 182, 194, 228, 76, 205, 8}, 92}, {{102, 96, 223, 28, 0, 0, 0, 224, 212, 116, 14, 15, 98, 177, 35, 154}, 92}, {{102, 96, 223, 28, 0, 202, 212, 175, 170, 52, 137, 126, 240, 220, 39, 172}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 118, 135, 10, 192, 44, 142, 94}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 60, 52}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 110, 11, 137, 81, 52, 62, 241, 122}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 43, 251, 110, 230}, 92}, {{102, 96, 223, 28, 0, 0, 0, 0, 58, 216, 39, 113, 31, 79, 94, 126}, 92}, {{137, 204, 150, 75, 193, 0, 0, 28, 28, 55, 90, 194, 118, 27, 215, 72}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 201, 69, 246}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 76, 60, 33, 109}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 53}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 123, 50, 224, 120, 211}, 237}, {{137, 204, 150, 75, 193, 0, 0, 72, 104, 42, 48, 0, 89, 246, 231, 15}, 237}, {{137, 204, 150, 75, 193, 0, 0, 114, 163, 107, 65, 201, 251, 244, 38, 7}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 56, 249, 187, 44, 157}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 221, 153, 26, 173, 127, 83}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 176, 156, 212, 250, 21, 163}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 207, 202, 186, 115, 251}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 135, 60, 55, 75, 127}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 37}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 219, 171, 135, 95, 82, 158}, 237}, {{137, 204, 150, 75, 193, 0, 0, 199, 194, 254, 220, 16, 56, 50, 56, 119}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 8, 198, 112, 98, 109, 249, 19}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 229, 135, 11, 28, 145}, 237}, {{137, 204, 150, 75, 193, 0, 142, 209, 168, 122, 168, 174, 170, 153, 254, 213}, 237}, {{137, 204, 150, 75, 193, 0, 0, 115, 233, 142, 97, 87, 41, 115, 165, 235}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 102, 7, 127, 182, 37, 155, 51}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 162, 140, 226, 160, 56, 37, 130, 124}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 161, 109, 51}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 237}, {{137, 204, 150, 75, 193, 0, 109, 247, 92, 55, 46, 210, 209, 202, 34, 58}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 53, 228, 46, 253, 44, 105, 131, 221}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 216, 99, 50}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 237}, {{137, 204, 150, 75, 193, 0, 0, 96, 38, 217, 116, 77, 118, 161, 171, 3}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 137, 252, 130, 204, 230, 170, 215, 222}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 237}, {{137, 204, 150, 75, 193, 0, 150, 152, 158, 77, 45, 119, 220, 4, 5, 62}, 237}, {{137, 204, 150, 75, 193, 0, 120, 185, 16, 221, 202, 127, 195, 87, 220, 147}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 254, 243, 167, 235, 50, 202, 56, 225}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 242, 233, 46, 93, 157, 39, 140, 98, 247, 172}, 237}, {{137, 204, 150, 75, 193, 0, 0, 105, 172, 143, 9, 22, 115, 20, 71, 151}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 156, 77, 218, 238, 44, 254}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 37, 177, 251}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 1, 252, 124, 61, 240, 159, 1, 199}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 206, 105, 178, 135, 247, 147}, 237}, {{137, 204, 150, 75, 193, 0, 33, 25, 74, 25, 194, 202, 52, 191, 102, 78}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 40, 15, 121, 203}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 153, 252, 139, 238, 29, 128, 82, 15}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 242, 154, 83}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 1, 39, 69, 7, 229, 156}, 237}, {{137, 204, 150, 75, 193, 0, 95, 29, 122, 180, 142, 105, 179, 120, 82, 200}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 148, 34, 174, 59}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 218}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 133}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 5, 108, 38, 42, 125, 233, 102}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 104, 204, 69, 176, 27, 128, 31, 187}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 228, 18, 86}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 43, 156, 178, 233}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 103, 102, 179, 150}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 113, 64, 226}, 237}, {{137, 204, 150, 75, 193, 0, 110, 57, 236, 63, 126, 141, 166, 104, 242, 105}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 235, 245, 33}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 27, 152, 151, 201, 191, 45, 129}, 237}, {{137, 204, 150, 75, 193, 0, 0, 158, 71, 27, 17, 108, 40, 242, 140, 173}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 175, 113, 26, 230, 62, 48, 78}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 248, 155, 145, 66, 153, 30, 84, 150}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 100, 232, 122, 205, 147, 184, 215, 142}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 135, 140, 73, 100, 175, 134, 68, 167, 194, 134}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 82, 106, 229, 106}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 166}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 100, 159, 163, 149, 74}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 24, 178, 77, 72, 72, 18, 208, 222, 209}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 52, 144, 192, 23, 237, 185}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 6, 176, 69, 131}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 35, 166, 200}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 89, 39, 109, 33, 105, 224, 183}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 210, 33, 135, 187, 96}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 162, 234, 116, 20, 227, 137}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{137, 204, 150, 75, 193, 0, 0, 141, 99, 27, 135, 82, 73, 240, 138, 232}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 107, 16, 34}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 151, 247, 137, 168, 210, 136}, 237}, {{137, 204, 150, 75, 193, 0, 173, 176, 128, 67, 191, 176, 196, 237, 31, 146}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 250, 15, 172, 137, 158}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 106, 164, 174, 94, 253}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 71, 68, 200, 84, 226, 138}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 163, 169, 217}, 237}, {{137, 204, 150, 75, 193, 0, 0, 0, 126, 104, 152, 255, 161, 187, 167, 45}, 237}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 172}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 72, 70}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 136, 29}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 171, 201, 3}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 94, 30}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 173, 93}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 192}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 73, 155}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 62, 201, 89}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 175, 17, 85}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 116}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 52, 202}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 49, 92}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 66}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 4, 210, 160}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 237}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 45, 229}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 223, 167}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 157, 73, 225}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 26, 138}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 71}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 170, 28, 18}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 43, 186, 200}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 80}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 86, 204}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 94, 120}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 100, 135}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 60}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 89, 45}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 196}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 251}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 93, 110, 103}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 96}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 37, 85, 228}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 77, 255}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 217, 77}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 76, 109}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 90, 91}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 55}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 7}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 24, 214, 108}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 96, 92}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 112, 159}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 189, 216}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 46, 17}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 217, 163, 215}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 98}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 118, 144, 247}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 177, 140}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 207}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 151, 255}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 175, 3}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 205, 200}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 244, 11}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 116}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 64, 22, 111}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 200}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 128}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 137, 197}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 80, 175}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 17}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 231, 250}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 229}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 51, 248, 6}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 178}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 237, 148}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 122}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 197, 119, 217}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 89, 73}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 111, 19, 104}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 60, 25}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 152}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 234}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 75, 219, 188}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 188}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 116}, {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 70, 169}, 116}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 232, 85, 133, 239}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 242, 248}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 19, 160, 20, 143, 254, 121, 225, 249}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 15, 146, 32, 243}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 116, 210, 50, 206, 1}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 246, 53}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 197, 6, 37, 9}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 97, 119, 243, 145}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 107, 136, 155, 244}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 217, 68, 119, 94, 4, 77}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 160, 101, 137, 83, 41, 186, 216, 245}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 232, 202, 101, 237, 67, 167, 219}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 172, 162, 168, 200}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 97, 63, 60, 132, 214, 255}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 222, 66, 233, 243}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 158, 224, 6, 161, 103}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 168, 96, 177, 217, 3, 8, 104, 15}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 219, 49, 36, 26, 250, 172, 199, 114}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 245, 113, 76, 114}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 248, 27, 29}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 231, 66, 159}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 4, 200, 250}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 74, 216, 11, 117, 69, 200}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 166, 170, 106, 231, 44, 234, 33}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 175, 69}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 149, 159, 188, 133}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 23, 41, 218, 218}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 154, 95, 60, 189}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 179, 219, 241, 216, 79, 8}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 145, 85, 120}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 251, 20}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 248, 236, 117, 239}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 243, 217, 91}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 2, 49, 103}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 233, 69}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 130, 246, 59, 242, 49, 48, 63, 172}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 172, 137}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 39, 219, 206, 65, 234, 231, 159}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 52, 144, 226, 214}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 26, 121}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 74, 205, 116, 254}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 83, 44, 17, 156, 70, 168, 8}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 125, 168, 137, 192}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 239, 35, 47, 158, 217}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 108, 244}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 238, 15}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 6, 202, 43, 161, 73, 231, 148}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 79, 73}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 39, 50, 21, 196, 169, 99, 206, 104}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 14, 148, 105, 210, 124, 66, 188}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 61, 115}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 37, 202, 46, 68, 248, 187, 55, 48}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 159, 237, 73, 57}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 89, 242, 137, 81, 0, 8, 83, 98}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 140, 153, 80}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 16, 77, 54, 172}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 199, 128, 42, 97, 200, 81}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 179, 134, 65}, 54}, {{55, 198, 139, 219, 161, 156, 140, 156, 16, 216, 7, 81, 130, 3, 80, 208}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 219, 108, 228, 195, 46}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 208, 158, 26, 186, 203}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 122, 218, 174, 125, 113}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 176, 143, 162, 151, 45, 237, 28}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 99, 88, 60}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 195, 150, 248}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 135, 36, 229, 63, 36}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 47, 206, 90, 192, 127}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 214, 78, 11, 163, 130, 80, 214, 9}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 118, 69, 49, 35, 128}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 226, 116, 139, 85, 129, 19, 201, 159}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54}, {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 167, 172, 6, 121, 160}, 54}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 82, 211, 166, 16, 37}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 161}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 176, 156, 127, 166, 162, 151, 210}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 50, 31, 39, 56}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 133, 21, 136, 102, 252, 217, 172}, 203}, {{44, 0, 0, 0, 0, 0, 0, 58, 79, 245, 164, 85, 30, 63, 26, 121}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 180, 163, 218, 213, 94, 9, 249}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 144, 5, 10, 35, 131, 231, 241, 46}, 203}, {{44, 0, 105, 161, 235, 41, 121, 117, 195, 90, 217, 110, 147, 13, 172, 59}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 69, 23, 5, 55, 221, 169, 199}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 203}, {{44, 0, 0, 0, 0, 0, 109, 255, 128, 122, 168, 248, 244, 77, 135, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 244, 139, 111}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 249, 162, 5, 221}, 203}, {{44, 0, 0, 243, 147, 130, 92, 201, 240, 184, 255, 3, 160, 7, 161, 87}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 203}, {{44, 0, 0, 0, 0, 0, 134, 15, 4, 153, 30, 13, 22, 105, 246, 151}, 203}, {{44, 0, 0, 0, 0, 200, 106, 211, 160, 148, 230, 244, 102, 77, 176, 120}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 252, 9, 103}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 222, 229, 48, 128}, 203}, {{44, 0, 0, 217, 73, 232, 82, 252, 244, 179, 218, 5, 215, 98, 225, 163}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 229, 219, 171, 102, 152}, 203}, {{44, 0, 0, 0, 0, 0, 152, 249, 95, 128, 214, 107, 238, 105, 180, 132}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 142, 119, 231, 107}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 3, 50, 130, 88, 172, 76, 147, 77, 95, 1, 97}, 203}, {{44, 0, 0, 71, 127, 143, 3, 0, 136, 164, 242, 168, 151, 129, 244, 248}, 203}, {{44, 0, 0, 0, 203, 18, 3, 96, 250, 83, 22, 27, 37, 183, 168, 7}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 209, 218}, 203}, {{44, 0, 0, 0, 0, 0, 0, 172, 219, 191, 45, 114, 220, 216, 155, 77}, 203}, {{44, 0, 0, 0, 0, 0, 0, 68, 150, 23, 33, 204, 135, 130, 103, 152}, 203}, {{44, 0, 22, 183, 168, 222, 23, 125, 235, 248, 101, 175, 30, 55, 30, 244}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 137}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 89, 32, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 142, 10, 231, 13, 175, 46, 122}, 203}, {{44, 0, 0, 0, 225, 184, 148, 130, 250, 189, 5, 48, 142, 248, 217, 29}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 148, 153, 133, 148, 196, 208, 65, 175}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 241, 47, 62, 206}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 231}, 203}, {{44, 0, 0, 0, 0, 0, 0, 121, 31, 49, 173, 59, 100, 0, 169, 136}, 203}, {{44, 0, 0, 0, 0, 0, 0, 93, 184, 142, 49, 71, 115, 93, 9, 158}, 203}, {{44, 0, 0, 0, 0, 34, 223, 30, 121, 187, 80, 55, 212, 254, 109, 235}, 203}, {{44, 0, 51, 15, 38, 245, 251, 202, 168, 122, 21, 94, 43, 239, 208, 152}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 235, 226, 190, 44}, 203}, {{44, 0, 0, 0, 0, 6, 61, 250, 26, 112, 232, 153, 209, 210, 253, 197}, 203}, {{44, 0, 0, 90, 204, 179, 45, 137, 205, 130, 109, 60, 210, 179, 166, 24}, 203}, {{44, 0, 0, 0, 0, 0, 0, 193, 139, 254, 76, 201, 76, 196, 20, 174}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 205, 58, 196, 20}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 35, 204, 120, 93}, 203}, {{44, 0, 0, 187, 97, 82, 114, 148, 247, 81, 137, 4, 23, 191, 10, 172}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 39, 71, 226, 22, 245, 104, 121, 48}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 89, 248, 193, 7}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 8, 242}, 203}, {{44, 0, 0, 0, 158, 37, 49, 84, 136, 126, 7, 162, 80, 12, 29, 178}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 27, 151, 85}, 203}, {{44, 0, 97, 8, 176, 127, 92, 124, 124, 58, 155, 89, 223, 221, 71, 204}, 203}, {{44, 0, 0, 239, 119, 158, 183, 107, 8, 155, 103, 235, 180, 29, 193, 34}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 173, 252, 23, 179}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 145, 151, 100, 113}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 178, 110}, 203}, {{44, 0, 0, 0, 0, 201, 151, 172, 75, 188, 131, 124, 124, 12, 179, 215}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 90}, 203}, {{44, 0, 0, 0, 0, 0, 230, 211, 16, 233, 29, 153, 237, 47, 53, 148}, 203}, {{44, 0, 0, 0, 0, 30, 179, 117, 94, 29, 79, 26, 151, 190, 232, 71}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 97, 94}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 207, 24, 236, 253, 87, 195, 112}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 89, 168, 127, 167, 78, 254, 18, 47, 174, 73, 43, 15, 160, 112}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 106, 172, 234, 74, 45, 240, 133, 221, 57, 67, 7}, 203}, {{44, 0, 0, 0, 0, 0, 122, 214, 247, 38, 48, 177, 202, 99, 87, 160}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 209, 226}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 157, 201, 135, 229, 194, 180, 228}, 203}, {{44, 0, 152, 55, 234, 249, 251, 106, 216, 184, 140, 130, 94, 238, 161, 101}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 8, 241, 9, 200, 15, 152, 198}, 203}, {{44, 0, 0, 0, 0, 0, 0, 107, 93, 154, 148, 122, 172, 100, 247, 136}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 91}, 203}, {{44, 0, 0, 117, 56, 20, 132, 216, 7, 9, 83, 226, 15, 74, 55, 190}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 155}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 169, 195, 84, 30}, 203}, {{44, 0, 0, 0, 117, 34, 7, 121, 187, 13, 132, 38, 155, 140, 91, 111}, 203}, {{44, 0, 0, 0, 0, 0, 88, 109, 21, 118, 195, 95, 199, 34, 54, 71}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 66, 133, 137, 228, 249}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 20}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 203}, {{44, 0, 0, 0, 0, 30, 26, 119, 49, 143, 66, 35, 148, 128, 189, 120}, 203}, {{44, 0, 0, 0, 0, 197, 175, 84, 205, 90, 90, 134, 69, 254, 23, 194}, 203}, {{44, 0, 0, 43, 122, 33, 215, 250, 80, 102, 178, 233, 73, 215, 25, 103}, 203}, {{44, 0, 0, 0, 0, 139, 137, 15, 137, 47, 162, 55, 210, 12, 175, 79}, 203}, {{44, 0, 227, 237, 188, 45, 192, 32, 39, 77, 31, 51, 179, 192, 58, 105}, 203}, {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 9, 207, 219, 192}, 203}, {{53, 38, 0, 0, 0, 0, 0, 0, 219, 57, 8, 157, 147, 15, 109, 227}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 194, 68, 56, 63, 144, 202, 182}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 231, 238, 72, 230, 198, 180, 167}, 74}, {{53, 38, 0, 0, 0, 0, 215, 211, 61, 181, 223, 107, 173, 177, 180, 154}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 74}, {{53, 38, 0, 0, 0, 31, 222, 246, 122, 200, 75, 46, 70, 29, 218, 138}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 37, 147, 55, 37, 33, 101, 69, 215}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 241, 221}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 74}, {{53, 38, 0, 0, 245, 235, 4, 35, 112, 140, 93, 153, 25, 0, 248, 179}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 240, 169, 95, 234, 39, 66}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 5, 41, 128}, 74}, {{53, 38, 0, 0, 0, 145, 145, 187, 221, 92, 254, 6, 183, 21, 185, 216}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 217, 86, 18, 63}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 19, 177, 175}, 74}, {{53, 38, 0, 170, 93, 241, 24, 229, 17, 249, 69, 31, 6, 29, 134, 125}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 24, 100, 37}, 74}, {{53, 38, 0, 226, 33, 135, 109, 154, 112, 110, 188, 207, 65, 68, 13, 141}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 129, 36, 111}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 153}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 135, 188, 107, 91, 235, 237, 155, 151, 180}, 74}, {{53, 38, 0, 0, 12, 223, 220, 113, 17, 1, 128, 100, 127, 198, 71, 161}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 165, 34, 88, 91}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 109, 94, 34, 89, 243, 154}, 74}, {{53, 38, 0, 139, 243, 248, 245, 97, 43, 225, 90, 233, 93, 25, 57, 20}, 74}, {{53, 38, 0, 0, 247, 92, 35, 180, 4, 198, 21, 107, 95, 63, 190, 108}, 74}, {{53, 38, 0, 0, 0, 0, 0, 76, 179, 199, 6, 96, 230, 136, 209, 246}, 74}, {{53, 38, 0, 0, 157, 11, 82, 137, 72, 210, 192, 222, 77, 150, 228, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 169, 122, 11, 99, 84, 212, 134, 75, 103}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 82, 76, 126, 237, 27, 50, 246}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 235, 240, 180, 23, 5, 49, 91, 53}, 74}, {{53, 38, 0, 0, 0, 0, 0, 52, 19, 219, 164, 176, 170, 248, 226, 15}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 175, 93, 77, 250, 111, 117, 13}, 74}, {{53, 38, 0, 0, 0, 0, 17, 72, 197, 0, 197, 44, 6, 145, 71, 254}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 197, 14, 35, 46, 172, 4, 155}, 74}, {{53, 38, 0, 0, 0, 88, 157, 108, 94, 39, 229, 81, 4, 95, 95, 175}, 74}, {{53, 38, 0, 0, 0, 0, 0, 155, 111, 65, 112, 227, 19, 195, 102, 82}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 67, 203, 100, 123, 79, 22, 95, 238}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 78, 202, 80, 74, 144, 249, 87, 137}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 190}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 254, 28, 155, 243}, 74}, {{53, 38, 0, 17, 137, 174, 223, 156, 15, 251, 40, 60, 29, 1, 166, 219}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 163, 144, 192, 238, 36, 76, 227, 179, 29, 183, 45, 112}, 74}, {{53, 38, 0, 0, 0, 0, 0, 174, 100, 43, 149, 205, 147, 28, 45, 191}, 74}, {{53, 38, 0, 0, 0, 4, 23, 21, 76, 162, 130, 244, 183, 124, 197, 235}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 80, 239, 249, 22, 63, 115, 183, 183}, 74}, {{53, 38, 0, 0, 151, 119, 28, 200, 140, 129, 247, 29, 35, 0, 195, 199}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 131, 205, 49}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 9, 236}, 74}, {{53, 38, 0, 0, 0, 0, 0, 166, 140, 214, 247, 223, 87, 19, 93, 42}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 237}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 97, 220}, 74}, {{53, 38, 0, 0, 121, 1, 80, 173, 32, 224, 86, 19, 211, 138, 4, 40}, 74}, {{53, 38, 0, 0, 0, 0, 0, 149, 222, 213, 221, 16, 100, 126, 251, 113}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 119, 180, 96, 89, 99, 85, 196}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 169, 229, 66, 131}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 111}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 222, 116, 156}, 74}, {{53, 38, 0, 38, 49, 121, 108, 95, 254, 114, 152, 101, 243, 82, 151, 34}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 48, 191, 20, 254, 120, 212, 50}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 116, 106, 239, 147, 5, 156, 9, 250}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 236, 228, 104, 220, 97, 103}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 11, 142, 71, 168, 109, 44, 64, 87}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{53, 38, 0, 0, 0, 87, 39, 54, 154, 6, 9, 248, 106, 149, 5, 201}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 144, 57, 146, 124, 151, 134}, 74}, {{53, 38, 0, 0, 0, 0, 56, 26, 30, 121, 144, 163, 212, 219, 181, 135}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 232, 198}, 74}, {{53, 38, 0, 0, 0, 0, 0, 172, 60, 212, 54, 12, 105, 71, 170, 159}, 74}, {{53, 38, 0, 0, 0, 0, 85, 235, 140, 89, 222, 172, 208, 89, 123, 74}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 31, 202, 45, 81, 168, 94}, 74}, {{53, 38, 0, 0, 0, 215, 122, 187, 190, 161, 99, 217, 213, 151, 56, 37}, 74}, {{53, 38, 0, 0, 0, 0, 19, 135, 199, 160, 71, 7, 44, 175, 79, 192}, 74}, {{53, 38, 0, 0, 0, 0, 0, 102, 204, 45, 77, 197, 147, 175, 172, 77}, 74}, {{53, 38, 0, 0, 0, 0, 6, 230, 240, 121, 217, 81, 223, 239, 222, 233}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 190, 161, 101, 245, 208, 57}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 74}, {{53, 38, 0, 41, 220, 38, 170, 82, 138, 17, 154, 18, 151, 96, 155, 184}, 74}, {{53, 38, 0, 0, 15, 188, 110, 113, 217, 252, 248, 107, 73, 41, 104, 183}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 173, 158, 215, 167}, 74}, {{53, 38, 0, 0, 177, 78, 199, 137, 164, 128, 16, 242, 78, 167, 42, 124}, 74}, {{53, 38, 0, 96, 102, 242, 145, 177, 246, 28, 118, 247, 159, 243, 201, 200}, 74}, {{53, 38, 0, 0, 0, 136, 229, 149, 93, 33, 183, 173, 99, 86, 48, 183}, 74}, {{53, 38, 0, 0, 0, 0, 109, 115, 219, 84, 126, 26, 3, 58, 157, 167}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 8, 192}, 74}, {{53, 38, 0, 0, 0, 0, 0, 233, 146, 82, 247, 96, 244, 8, 66, 97}, 74}, {{53, 38, 0, 0, 0, 0, 0, 0, 0, 254, 201, 132, 105, 7, 95, 148}, 74}, {{53, 38, 0, 0, 0, 164, 7, 254, 33, 80, 247, 3, 178, 174, 17, 13}, 74}, {{53, 38, 0, 0, 101, 213, 99, 19, 238, 128, 237, 43, 40, 239, 213, 72}, 74}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 97}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 45, 103, 106}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 91, 13, 131}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 87}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 70}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 94}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 40}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 182}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 229}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 40, 116}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 33, 51}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 167}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 204, 46, 62}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 205, 118}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 252}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 227, 57}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 222, 72, 228}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 95, 71}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 36}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 187, 215}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 71}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 37}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 186}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 242}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 225, 188, 241}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 27, 235, 219}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 204, 34, 2}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 200}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 166, 76, 119}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 164, 161}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 216}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 115, 153, 7}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 65}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 219}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 80, 245, 156}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 123}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 99, 132}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 205, 11, 9}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 180, 65}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 212}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 209, 170, 228}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 215}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 4}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 24}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 225, 86}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 28, 99, 108}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 94}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 182}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 34, 164, 125}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 126, 250, 196}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 110, 167}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 100}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 181, 239}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 89}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 132, 32}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 194, 178, 10}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 90}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 228}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 96, 45}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 180, 104, 79}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 59}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 75}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 117, 13, 236}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 240}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 175, 207, 44}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 15, 196}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 136, 149}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 190}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 108, 208, 6}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 210, 221}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 191, 9, 74}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 227, 15}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 185}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 160, 206, 6}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 175, 2, 194}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 92}, 220}, {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 82, 94}, 220}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 58, 165, 191, 166}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 52, 58, 139, 172, 210, 126, 58}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 157}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 134}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 145, 91, 77, 226}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 96, 70, 147}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 58, 97, 178, 186}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 112, 38, 176, 114, 141, 144}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 83}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 21, 170, 217, 105}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 220}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 1, 116, 68}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 82, 5, 135}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 178, 107, 206, 173, 142}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 3}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 231, 119, 218, 57, 77, 23, 168}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 11, 161, 242, 146}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 146, 128, 148}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 245, 37, 29, 78, 136, 255, 242}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 159, 184, 47}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 109, 25, 62, 26}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 43}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 224, 122}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 143, 185, 102, 214, 136, 36}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 13, 102, 180, 135, 115}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 78, 199, 200}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 10, 181}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 91, 163}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 241, 242, 204, 55}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 185, 128, 136, 45, 255}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 126, 52, 202, 107, 97, 120}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 254, 60, 162, 81, 3}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 165}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 212}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 168, 111, 143, 163}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 238}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 22}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 61, 150, 218, 91, 168, 76, 182}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 99, 96, 158, 126, 83}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 192, 117, 89, 21}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 160}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 12, 65, 39, 57, 143, 7, 8}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 17, 59, 182, 207}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 200, 127, 33, 162}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 21, 237, 231}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 30, 132, 95}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 106, 48}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 58, 241, 220}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 211, 89, 29}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 59, 215, 147}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 147, 224, 235, 188, 106, 44, 106}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 146, 186, 244, 79, 25, 1, 59}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 35, 235, 119, 233, 135, 154, 74}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 52, 165, 185, 185}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 80, 83, 29, 102}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 100, 179, 103, 210, 1, 89, 41}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 225, 106, 249}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 70}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 232, 193, 185}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 140}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 233, 236, 137, 245, 58, 233, 198}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 165}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 47, 217, 4, 156}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 98, 172}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 216}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 22, 248}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 111, 53}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 184, 199, 122, 149, 9, 69}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 144, 158}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 80, 21, 7, 140, 99}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 85}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 76, 1, 56, 41, 114, 171}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 42, 221}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 207, 41, 76, 214, 103, 182}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 182, 140, 30}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 82, 175, 112, 233}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 177, 88}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 210, 168, 215}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 243, 57, 223, 79, 208, 136}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 93, 113, 138}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 196, 11, 205, 244}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 33, 227, 151, 206, 253}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 145, 125, 242, 139}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 185, 86, 241, 230, 68, 14}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 166, 80, 156, 171, 8, 130}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 244, 19}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 53, 150, 131, 63}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 55, 180, 109, 4, 110, 61, 228}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 219, 234}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 194, 6, 109, 82}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 42, 97}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 23, 22, 13, 14, 183, 99}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 72}, 219}, {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 219}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 111, 91}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 200, 163, 78, 52}, 109}, {{96, 170, 52, 189, 221, 20, 161, 237, 97, 86, 82, 68, 251, 26, 166, 243}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 18, 221, 9, 173, 210, 220, 230, 171, 131, 226, 157, 41}, 109}, {{96, 0, 0, 0, 0, 0, 0, 151, 33, 15, 160, 193, 191, 122, 46, 161}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 42, 183, 67, 7, 227, 112, 222}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 159, 97, 171, 151, 110, 66, 33, 235}, 109}, {{96, 0, 0, 209, 32, 3, 192, 103, 196, 59, 85, 173, 121, 12, 15, 118}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 109}, {{96, 0, 250, 185, 47, 250, 33, 94, 100, 109, 11, 246, 135, 159, 228, 72}, 109}, {{96, 0, 0, 0, 0, 0, 90, 5, 162, 207, 125, 31, 203, 109, 139, 91}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 23, 22}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 14, 148, 187, 56, 188, 58, 85, 135, 42, 153, 169, 222, 183, 24, 29}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 208}, 109}, {{96, 182, 191, 192, 149, 16, 44, 139, 70, 80, 193, 8, 194, 24, 112, 107}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 174, 79, 67, 82, 88, 235, 226}, 109}, {{96, 0, 0, 0, 67, 141, 95, 237, 122, 128, 13, 114, 222, 173, 149, 144}, 109}, {{96, 0, 0, 0, 85, 159, 120, 167, 131, 72, 81, 233, 57, 33, 175, 179}, 109}, {{96, 177, 194, 76, 63, 57, 62, 126, 213, 240, 72, 229, 133, 46, 125, 76}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 253, 180, 11, 127, 238, 228, 187, 211}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 174, 10}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 235}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 25, 208, 221, 97, 70}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 239}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 44, 129, 18, 230}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 195, 59, 130, 36, 159, 47, 56}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 143, 80, 176}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 207}, 109}, {{96, 0, 0, 0, 0, 169, 208, 115, 118, 10, 108, 237, 183, 117, 202, 135}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 204, 37, 198}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 57, 68, 195, 250, 108, 39, 207, 21}, 109}, {{96, 0, 0, 0, 69, 207, 186, 36, 255, 137, 12, 87, 175, 177, 148, 158}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 108, 239}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 193, 80, 213, 106}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 217, 54}, 109}, {{96, 0, 0, 0, 0, 0, 243, 149, 107, 220, 132, 83, 134, 48, 168, 43}, 109}, {{96, 0, 0, 0, 0, 0, 67, 7, 156, 21, 215, 116, 152, 37, 238, 101}, 109}, {{96, 0, 50, 0, 154, 160, 44, 207, 107, 243, 189, 193, 10, 33, 133, 143}, 109}, {{96, 0, 0, 66, 241, 147, 114, 45, 7, 46, 85, 90, 50, 139, 12, 235}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 52, 164, 48, 175, 236, 113, 65}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 246}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 236, 211, 149, 230, 57, 29, 240, 124}, 109}, {{96, 0, 0, 0, 0, 142, 231, 119, 183, 211, 31, 58, 245, 135, 41, 5}, 109}, {{96, 0, 0, 0, 0, 55, 19, 249, 10, 82, 49, 212, 84, 81, 77, 223}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 161, 241, 215, 114, 246, 97, 183, 76}, 109}, {{96, 0, 0, 0, 96, 96, 169, 228, 70, 197, 42, 103, 37, 91, 161, 133}, 109}, {{96, 0, 0, 152, 160, 202, 246, 38, 25, 215, 255, 48, 197, 94, 12, 49}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 17}, 109}, {{96, 0, 174, 28, 169, 231, 82, 228, 127, 220, 116, 46, 147, 12, 65, 201}, 109}, {{96, 0, 0, 0, 0, 45, 12, 72, 227, 106, 47, 122, 39, 150, 44, 109}, 109}, {{96, 0, 0, 0, 174, 124, 202, 31, 171, 238, 56, 127, 254, 63, 33, 17}, 109}, {{96, 0, 0, 0, 0, 0, 0, 77, 231, 161, 32, 82, 78, 124, 178, 182}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 224, 150, 215, 246, 164}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 121, 174, 98, 154, 204, 170, 57}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 20}, 109}, {{96, 0, 0, 0, 219, 6, 142, 135, 36, 85, 42, 102, 49, 4, 240, 92}, 109}, {{96, 0, 0, 0, 0, 0, 71, 181, 76, 125, 199, 134, 88, 210, 90, 178}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 141, 139, 217, 234}, 109}, {{96, 0, 0, 188, 237, 176, 135, 9, 207, 64, 139, 235, 238, 20, 116, 17}, 109}, {{96, 0, 0, 236, 233, 115, 8, 40, 113, 67, 17, 246, 12, 116, 9, 164}, 109}, {{96, 0, 169, 251, 112, 35, 159, 18, 247, 13, 142, 232, 142, 158, 51, 162}, 109}, {{96, 0, 0, 0, 222, 158, 203, 114, 134, 221, 220, 7, 78, 64, 147, 156}, 109}, {{96, 0, 0, 64, 185, 142, 87, 98, 66, 25, 227, 94, 160, 180, 102, 201}, 109}, {{96, 0, 0, 0, 0, 0, 0, 19, 221, 225, 155, 129, 163, 144, 96, 95}, 109}, {{96, 0, 0, 0, 0, 165, 13, 239, 154, 55, 255, 170, 8, 84, 154, 168}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 79, 69, 56}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 109}, {{96, 157, 33, 239, 187, 236, 222, 229, 176, 199, 231, 122, 40, 33, 224, 47}, 109}, {{96, 0, 0, 0, 0, 0, 0, 46, 104, 245, 72, 2, 183, 152, 19, 189}, 109}, {{96, 0, 0, 0, 85, 217, 140, 143, 74, 164, 11, 229, 61, 64, 179, 137}, 109}, {{96, 0, 0, 0, 0, 0, 246, 25, 217, 228, 218, 192, 171, 35, 251, 235}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 107, 119, 29}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 226, 154, 209, 124, 128, 151, 94, 77}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 232, 237, 20, 177, 117, 182, 87, 66}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 97}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 31, 185, 90}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 187, 155, 167, 126, 70, 29, 150, 96, 97}, 109}, {{96, 0, 0, 0, 0, 0, 0, 205, 60, 152, 131, 215, 220, 14, 204, 112}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 109}, {{96, 0, 0, 0, 0, 0, 243, 183, 15, 83, 40, 156, 29, 186, 179, 137}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 168}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 78, 88, 152, 171, 176, 176, 155}, 109}, {{96, 0, 0, 0, 0, 49, 34, 211, 19, 242, 238, 191, 26, 168, 61, 235}, 109}, {{96, 0, 0, 0, 0, 0, 25, 1, 0, 99, 109, 130, 209, 230, 143, 61}, 109}, {{96, 0, 0, 0, 0, 46, 57, 46, 193, 156, 116, 255, 247, 64, 31, 195}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 218, 139, 144, 209}, 109}, {{96, 0, 0, 0, 0, 0, 0, 70, 134, 172, 22, 246, 254, 207, 107, 57}, 109}, {{96, 0, 199, 218, 133, 197, 202, 132, 241, 89, 80, 232, 122, 226, 250, 215}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 222, 227, 99, 101, 239, 169, 181}, 109}, {{96, 0, 28, 49, 152, 24, 226, 239, 229, 163, 214, 58, 230, 124, 129, 236}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 107}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 175, 65, 133, 224, 146}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 212, 1, 16, 240, 138}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 78, 219, 126, 124, 89, 136, 126, 49}, 109}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 212, 69, 242, 66, 239, 250, 195}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 22, 95, 60, 79, 18}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 11, 150, 201, 137}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 5}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 229, 110, 111}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 17, 244}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 122}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 15}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 64, 136, 10, 231, 201}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 36, 146, 162, 231, 42}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 175, 155, 59, 49, 76, 68, 85}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 90, 30}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 13, 0, 87, 173}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 195, 163, 177, 41, 5, 174}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 210, 191, 93}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 136, 121, 177}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 31, 119, 140, 97, 217}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 108, 159}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 132, 89, 192, 218, 166, 92, 163}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 82, 155, 193, 42, 113}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 46, 245}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 80, 99, 241, 143, 168}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 195, 159, 68, 68, 216, 78, 248}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 17, 217, 193, 129, 111, 97, 230, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 152, 161, 82, 196, 240, 52}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 48, 122}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 194, 68, 73, 174}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 155, 246}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 179, 104, 94, 166}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 134, 223}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 124, 204, 52}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 230, 191, 114, 42, 212, 213, 48, 28}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 63, 205}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 50, 135}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 109, 135, 48, 98, 200, 168, 142}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 133, 145, 149, 126}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 93, 184, 215, 207}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 201}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 187, 106, 84, 204, 133, 42, 207, 62}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 57, 220, 134}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 247, 14, 220}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 223, 198, 73, 99, 14, 62, 7}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 207}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 237, 66}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 181, 111, 154}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 220, 43, 1, 31, 17, 190}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 86, 194}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 143, 35}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 199, 25, 138, 180, 218, 129}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 29, 238}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 39, 166, 115, 20, 102, 83, 150}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 255, 196, 88, 117, 77, 142}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 248, 157, 9, 226}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 138, 171, 226, 162, 241, 43}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 100, 73, 193, 173, 59, 144, 95}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 76, 116, 96}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 147, 195}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 139, 3, 208}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 13}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 170, 203}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 193, 36}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 132, 28, 213}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 225, 170, 230}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 74, 135, 206, 227, 221, 207, 103}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 228, 70, 26, 255, 195, 20, 239}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 138, 36, 109, 53}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 67, 196, 195, 100, 73, 251, 155}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 99, 154, 182, 178, 59, 205, 69}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 197, 109, 48}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 109, 168, 7}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 220, 49, 128, 141, 83, 80, 160}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 238, 111, 187, 130, 11, 5, 145}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 107, 146, 101, 205}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 196}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 149, 199, 247, 248, 2, 101, 44}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 106, 166, 231, 113}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 201, 134, 6}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 52, 228, 32, 133, 79}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 78, 81, 162, 167, 40, 241}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 79, 153, 193}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 45}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 194, 67}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 34}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 33, 70, 62, 97}, 194}, {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 33, 178, 52, 96}, 194}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 225, 198, 224, 61, 43, 156}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 155}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 139, 148, 110, 139, 255}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 155, 45, 147, 248, 7, 195, 185}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 213, 98}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 242, 86, 202, 126, 60}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 196, 96, 116, 19}, 187}, {{101, 70, 196, 238, 0, 158, 21, 75, 64, 131, 47, 111, 61, 146, 88, 145}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 61, 36, 134, 228, 128}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 249}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 199, 130, 250, 149, 16, 59}, 187}, {{101, 70, 196, 238, 0, 6, 222, 220, 14, 95, 145, 73, 140, 194, 45, 211}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 107, 154, 195, 118, 207, 75, 205, 131}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 210, 106, 137, 11, 173, 10, 252, 155}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 169, 69, 177, 185, 110}, 187}, {{101, 70, 196, 238, 0, 0, 0, 49, 228, 247, 217, 167, 106, 218, 68, 96}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 74, 164, 83, 151, 211, 36, 153, 24}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 241}, 187}, {{101, 70, 196, 238, 0, 0, 0, 56, 225, 253, 15, 41, 180, 163, 247, 236}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 201, 201}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 52, 230, 105, 163, 248, 210, 236}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 161, 249, 220, 233, 55, 50}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 244, 255, 160, 133, 11, 126}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 230, 65}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 90, 185, 94, 27, 128, 2, 45, 190, 126}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 162, 97, 132, 33, 141, 237}, 187}, {{101, 70, 196, 238, 0, 0, 22, 22, 22, 150, 24, 41, 234, 130, 124, 23}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 175, 137, 71, 53}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 15, 220, 119, 226, 73, 169, 12}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 209, 38, 90, 158, 169}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 1, 185}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 196, 119, 235, 196, 177}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 62, 71, 14, 48}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 162, 220}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 192, 122, 47, 122}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 187}, {{101, 70, 196, 238, 0, 0, 134, 193, 245, 239, 58, 2, 107, 82, 244, 214}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 172, 40}, 187}, {{101, 70, 196, 238, 0, 0, 0, 153, 4, 68, 58, 254, 6, 56, 97, 27}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 153, 147, 223, 82, 179}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 91, 220, 212, 130, 56, 131, 54, 32}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 132, 57, 32, 142}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 194, 148}, 187}, {{101, 70, 196, 238, 0, 0, 82, 105, 64, 184, 10, 58, 210, 60, 206, 245}, 187}, {{101, 70, 196, 238, 0, 0, 65, 172, 100, 185, 34, 40, 83, 172, 41, 224}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 187, 217, 164, 235, 198, 225}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 188, 244, 222, 53, 167, 46, 38, 161}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 176}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 90, 2, 124, 114, 26, 246}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 47, 225, 28, 204, 75, 103, 140, 124, 196, 122}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 176, 218}, 187}, {{101, 70, 196, 238, 0, 0, 99, 26, 146, 89, 232, 183, 167, 182, 89, 159}, 187}, {{101, 70, 196, 238, 0, 0, 152, 245, 101, 182, 62, 46, 139, 29, 151, 31}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 32, 98}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 37, 209}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 195, 0, 40, 75, 75, 131}, 187}, {{101, 70, 196, 238, 0, 135, 178, 85, 13, 86, 190, 14, 33, 202, 241, 142}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 166, 13, 229, 71}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 60, 127, 239, 7}, 187}, {{101, 70, 196, 238, 0, 0, 143, 174, 45, 240, 125, 84, 152, 58, 188, 85}, 187}, {{101, 70, 196, 238, 0, 0, 80, 0, 68, 15, 249, 58, 52, 145, 99, 51}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 205, 34}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 252, 33, 2, 74, 73, 31}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 130, 5, 238, 12}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 23, 69, 109, 151, 104}, 187}, {{101, 70, 196, 238, 0, 0, 227, 232, 105, 175, 171, 197, 177, 76, 132, 191}, 187}, {{101, 70, 196, 238, 0, 145, 20, 66, 153, 147, 175, 65, 49, 124, 242, 50}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 168, 139, 202, 165}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 32, 145, 31, 100, 111, 95, 12, 151}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 182, 194, 189, 72}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 93, 222, 84, 200, 155, 179, 180}, 187}, {{101, 70, 196, 238, 0, 0, 0, 113, 227, 152, 103, 156, 141, 111, 98, 63}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 58, 196, 31, 38}, 187}, {{101, 70, 196, 238, 0, 0, 0, 10, 67, 57, 164, 239, 43, 174, 0, 167}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 1, 74, 244, 197, 177}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 117, 218, 231, 195, 131, 205, 155, 62}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 187}, {{101, 70, 196, 238, 0, 0, 120, 229, 235, 236, 39, 114, 119, 198, 122, 224}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 140, 249, 136, 0, 166}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 35, 201, 231, 238, 177, 194, 51}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 229}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 73, 119, 183, 71, 231, 245, 231}, 187}, {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{245, 173, 165, 177, 200, 161, 64, 0, 106, 48, 213, 192, 253, 238, 45, 166}, 79}, {{245, 173, 165, 177, 200, 161, 64, 66, 136, 233, 196, 6, 112, 135, 39, 64}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 59, 24, 8, 133, 37, 112}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 164, 205, 146, 168}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 254, 95, 196, 23, 214}, 79}, {{245, 173, 165, 177, 200, 161, 64, 43, 149, 82, 204, 40, 70, 94, 153, 170}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 196, 75, 124}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 191, 42, 213, 53, 23}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 191, 38, 177, 112, 114, 171}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 218, 105, 178, 200, 4, 160, 228, 12, 209}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 130, 2, 169}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 119, 115, 239, 86, 192, 193, 152}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 212, 187, 244, 150}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 134, 7, 155, 97, 12, 42, 23, 1}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 253, 250, 28}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 23, 171, 139, 234, 17, 5, 251, 25}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 177, 57, 7, 131}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 158, 9, 253}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 15, 194}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 207, 131, 157, 219, 125, 107}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 59, 27, 218, 164, 164, 196, 177}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 60, 24, 231, 236, 169, 174}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 67, 149, 163, 5, 1, 58, 131}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 209, 29, 180, 31}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 176, 26, 231, 235, 163, 169}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 171, 84, 79}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 206, 16}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 5, 23, 148, 122, 146}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 190, 98, 91, 0, 217, 188, 60}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 53, 131, 66, 28, 192, 43, 17}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 18, 55, 69, 89, 159, 157, 125}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 46, 1, 60}, 79}, {{245, 173, 165, 177, 200, 161, 64, 37, 237, 183, 33, 1, 203, 43, 44, 117}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 113, 103, 162, 143, 97, 23, 78}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 193, 127, 204, 11}, 79}, {{245, 173, 165, 177, 200, 161, 64, 6, 139, 9, 255, 19, 171, 72, 211, 155}, 79}, {{245, 173, 165, 177, 200, 161, 64, 219, 229, 35, 133, 9, 37, 47, 102, 139}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 47, 63, 83, 174, 81, 224, 155, 181, 125}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 162, 185, 149, 193, 110}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 160, 5}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 205, 190, 42, 105, 52}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 100, 218, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 196, 207, 149, 178, 91, 123, 7, 206}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 121, 137, 90, 90}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 111, 112}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 228, 105}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 112, 68, 112, 238, 20}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 131, 223, 251, 191, 229, 240, 214, 28}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 78, 246, 81, 89, 15, 174}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 15, 191, 81, 239, 205}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 248, 74, 100}, 79}, {{245, 173, 165, 177, 200, 161, 64, 172, 104, 222, 104, 130, 192, 34, 108, 52}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 84, 147, 229, 251, 180}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 20, 160, 15}, 79}, {{245, 173, 165, 177, 200, 161, 64, 23, 131, 151, 144, 149, 105, 225, 194, 46}, 79}, {{245, 173, 165, 177, 200, 161, 64, 151, 8, 148, 183, 228, 180, 93, 221, 66}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 206, 187, 213, 219}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 73, 61, 151, 131, 108}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 25, 56, 24, 135}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 53, 214, 75, 89}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 56, 197, 85, 225, 144, 215}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 79}, {{245, 173, 165, 177, 200, 161, 64, 140, 136, 6, 150, 113, 69, 31, 231, 127}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 46, 240, 82, 224, 238, 119}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 42, 68}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 171, 52, 98, 147, 183}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 184, 80}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 27, 2, 194, 92, 160}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 216, 210, 52, 21, 94, 226}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 108, 12, 6, 101, 203, 236}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 145, 88, 230, 173, 82, 138}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 56, 133, 29, 111, 226, 106, 77}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 105, 140, 174, 216, 81, 2, 132}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 80, 58, 34, 77, 80}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 253, 123, 220}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 224, 61, 62, 99, 239, 143}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 159, 59, 92}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 7, 67, 158, 114, 93, 201, 253, 45}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 156, 177, 147, 194, 5, 145}, 79}, {{245, 173, 165, 177, 200, 161, 64, 0, 165, 187, 118, 109, 53, 16, 129, 238}, 79}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 80}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 75, 251, 112, 210}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 243}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 29, 57, 124, 209, 30, 234, 184, 235}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 112, 205}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 127, 244, 118, 36}, 87}, {{0, 198, 0, 0, 0, 0, 122, 201, 87, 8, 250, 100, 204, 25, 8, 36}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 135, 116, 241, 1, 230, 155, 23}, 87}, {{0, 198, 0, 0, 17, 58, 156, 194, 0, 99, 135, 241, 109, 240, 121, 96}, 87}, {{0, 198, 0, 0, 39, 19, 6, 250, 75, 216, 169, 7, 15, 62, 80, 117}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 254, 226, 161, 132, 239, 156}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 173, 192}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 32, 81}, 87}, {{0, 198, 0, 226, 172, 9, 225, 156, 116, 70, 242, 65, 13, 168, 184, 231}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 185, 81, 58, 3, 45, 80}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 140}, 87}, {{0, 198, 0, 0, 13, 94, 80, 73, 242, 119, 99, 23, 111, 59, 231, 60}, 87}, {{0, 198, 0, 0, 0, 0, 4, 43, 109, 29, 37, 164, 219, 0, 65, 148}, 87}, {{0, 198, 0, 0, 0, 0, 0, 253, 232, 233, 240, 52, 239, 0, 175, 224}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 192, 218, 185, 124, 104, 203, 151}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 130, 108, 237, 81, 9, 192, 63}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 176, 9}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 36, 35, 250, 42, 162, 35, 18, 211}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 254, 123, 54}, 87}, {{0, 198, 0, 0, 0, 0, 0, 88, 73, 57, 230, 77, 91, 225, 178, 213}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 136, 31, 140, 197, 152, 233}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 148, 116, 177, 11, 9, 176}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 210, 22, 243, 201, 176, 120, 247}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 136, 6}, 87}, {{0, 198, 0, 0, 0, 140, 21, 180, 82, 243, 86, 149, 3, 109, 41, 129}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 45, 20, 144, 53, 72, 92, 24, 200}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 177, 173, 116, 10, 195, 238, 123}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 165, 198}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 230, 165, 196}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 61, 67, 219, 125, 59, 49, 125}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 224, 251, 243, 119, 241, 159, 246}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 174, 63, 175, 24, 223, 2, 162, 44}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 54, 178, 65}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 190, 72, 246, 43, 220, 60, 190}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 87}, {{0, 198, 0, 0, 0, 0, 154, 58, 20, 99, 78, 139, 140, 59, 111, 166}, 87}, {{0, 198, 0, 0, 0, 0, 8, 18, 164, 121, 205, 215, 235, 121, 70, 245}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 156, 204, 92, 83}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 218, 242, 188, 182}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 185, 123, 37, 116, 98, 132, 243, 246}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 34, 231}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 178, 230, 76, 204, 44, 144, 2, 177}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 5, 220, 188, 41, 116, 183}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 29, 235, 124, 16, 128, 182}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 191, 169, 155, 57}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 176}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 4, 118}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 161, 152, 122, 189, 12, 21, 166}, 87}, {{0, 198, 0, 0, 0, 0, 0, 111, 33, 112, 123, 57, 113, 214, 0, 39}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 243, 138, 172, 18, 176, 232, 106}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 112, 200, 128, 221, 143, 107, 12, 103}, 87}, {{0, 198, 0, 0, 0, 0, 222, 15, 142, 248, 44, 147, 252, 106, 72, 119}, 87}, {{0, 198, 0, 0, 0, 0, 80, 201, 81, 154, 83, 106, 174, 147, 30, 76}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 5, 182}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 93, 158, 85, 152, 159, 135, 248}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 195, 100, 250, 33, 135, 95}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 216, 3, 46, 229, 182, 251}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 74, 208, 198, 144, 35, 23}, 87}, {{0, 198, 0, 204, 217, 173, 159, 183, 172, 219, 202, 72, 251, 85, 75, 208}, 87}, {{0, 198, 0, 0, 0, 0, 196, 219, 103, 88, 102, 239, 114, 30, 64, 151}, 87}, {{0, 198, 0, 0, 0, 221, 41, 253, 133, 61, 40, 118, 169, 135, 165, 135}, 87}, {{0, 198, 0, 0, 0, 0, 0, 1, 162, 162, 127, 71, 75, 162, 191, 165}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 29, 12, 221, 112, 94, 249}, 87}, {{0, 198, 0, 80, 41, 112, 212, 11, 88, 250, 254, 152, 16, 177, 163, 156}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 84, 99, 102, 214, 88, 53}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 244, 197, 222, 178, 234, 39, 187, 179}, 87}, {{0, 198, 0, 0, 0, 0, 101, 255, 93, 223, 137, 102, 147, 224, 66, 39}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 190, 46, 92, 199, 139, 122, 131}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 156, 248, 233, 43, 238, 130, 151, 208}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 179}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 193}, 87}, {{0, 198, 0, 90, 152, 166, 250, 131, 249, 220, 81, 102, 100, 227, 102, 187}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 197, 168, 140, 25}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 63, 45}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 176, 185, 211, 84, 135, 196, 190, 157, 247}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 12, 207, 60}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 137, 19, 35}, 87}, {{0, 198, 0, 221, 129, 30, 143, 192, 73, 225, 228, 160, 222, 152, 200, 255}, 87}, {{0, 198, 0, 0, 0, 0, 0, 201, 188, 221, 135, 214, 198, 172, 131, 55}, 87}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 129, 238, 196, 150, 133, 138, 0, 39, 18, 211, 246, 20, 221, 42}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 244}, 126}, {{92, 0, 56, 250, 51, 88, 152, 218, 172, 33, 36, 233, 84, 202, 127, 69}, 126}, {{92, 0, 0, 0, 0, 0, 64, 243, 104, 202, 26, 181, 52, 168, 75, 253}, 126}, {{92, 0, 0, 0, 0, 52, 137, 76, 128, 95, 25, 96, 102, 243, 9, 15}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 92, 232, 85, 113, 42, 118, 90}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 188, 192, 244}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 126}, {{92, 0, 0, 0, 107, 173, 232, 94, 196, 195, 105, 187, 43, 119, 151, 133}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 217, 127}, 126}, {{92, 0, 0, 0, 0, 0, 125, 30, 242, 76, 29, 146, 100, 173, 125, 234}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 107, 78, 156, 15}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 42, 156, 211}, 126}, {{92, 0, 0, 0, 0, 92, 210, 11, 44, 166, 133, 192, 64, 4, 118, 205}, 126}, {{92, 0, 0, 0, 0, 0, 186, 154, 64, 145, 76, 173, 126, 13, 203, 151}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 184, 5, 187, 91, 15, 156, 120, 174}, 126}, {{92, 0, 0, 0, 192, 16, 142, 114, 230, 212, 95, 193, 142, 23, 99, 116}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 39, 229, 59, 85, 27, 107, 254, 23}, 126}, {{92, 0, 0, 0, 0, 0, 0, 26, 72, 110, 32, 242, 212, 57, 47, 80}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 118}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 135, 40, 239, 52, 61}, 126}, {{92, 0, 0, 0, 36, 73, 252, 117, 121, 86, 1, 194, 105, 64, 56, 114}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 66, 16, 79}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 0, 0, 0, 0, 206, 83, 84, 204, 27, 161, 142, 180, 138}, 126}, {{92, 0, 217, 87, 210, 75, 146, 141, 140, 99, 52, 141, 56, 89, 129, 186}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 35, 189, 98, 104}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 175, 106, 246}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 180, 92, 133, 102, 225}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 4, 17, 149, 230, 205, 249, 155, 191}, 126}, {{92, 0, 0, 85, 215, 27, 228, 23, 188, 187, 251, 177, 248, 49, 51, 171}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 160, 5, 16, 209}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 127, 90, 167}, 126}, {{92, 0, 0, 0, 0, 0, 20, 30, 41, 16, 191, 71, 117, 78, 30, 29}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 185, 176}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 89}, 126}, {{92, 0, 0, 0, 20, 88, 181, 13, 103, 131, 134, 167, 180, 190, 103, 236}, 126}, {{92, 0, 0, 0, 0, 0, 0, 34, 48, 89, 180, 204, 96, 28, 224, 193}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 20, 98, 109, 33, 129, 49, 179, 47}, 126}, {{92, 0, 0, 0, 0, 0, 0, 253, 182, 80, 159, 153, 211, 37, 68, 20}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 183, 112, 81}, 126}, {{92, 0, 44, 255, 229, 160, 1, 163, 159, 144, 169, 75, 31, 66, 254, 47}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 56, 1, 200, 173, 57, 67, 20}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 126}, {{92, 0, 123, 67, 132, 31, 243, 153, 153, 38, 94, 28, 236, 1, 73, 199}, 126}, {{92, 0, 0, 19, 17, 165, 45, 226, 106, 167, 15, 41, 112, 216, 149, 151}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 60, 113, 6, 181, 231, 17, 101}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 93, 142, 224}, 126}, {{92, 0, 0, 0, 165, 227, 248, 43, 229, 83, 53, 145, 114, 204, 95, 215}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 115, 15}, 126}, {{92, 0, 86, 176, 154, 0, 207, 190, 209, 132, 156, 246, 182, 165, 36, 95}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 41, 35, 180, 52, 158, 129, 137, 255, 60, 154, 12, 56, 138}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 184, 61, 55, 107, 218, 239, 205, 23}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 145, 220, 173, 181, 25, 107, 186, 130}, 126}, {{92, 0, 0, 0, 0, 52, 82, 145, 252, 103, 199, 220, 88, 154, 206, 189}, 126}, {{92, 0, 0, 186, 131, 76, 81, 207, 252, 187, 172, 67, 150, 124, 114, 143}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 61}, 126}, {{92, 0, 0, 0, 196, 249, 231, 8, 36, 207, 161, 54, 115, 177, 87, 226}, 126}, {{92, 0, 0, 0, 0, 58, 250, 224, 231, 186, 153, 160, 213, 73, 182, 85}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 39, 221, 6, 147, 121, 26, 223, 81, 16, 214, 215, 175, 111}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 136, 14, 126, 10, 83, 114, 75}, 126}, {{92, 0, 0, 0, 21, 234, 18, 146, 180, 143, 57, 114, 87, 179, 56, 214}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 126}, {{92, 0, 123, 17, 3, 225, 6, 41, 26, 231, 5, 104, 202, 96, 211, 210}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 157, 44, 254, 130, 216, 122, 106}, 126}, {{92, 0, 0, 0, 226, 184, 182, 42, 221, 208, 227, 239, 225, 151, 171, 92}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 220, 143, 127, 208, 242, 30, 181}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 204, 223, 39}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 168, 34}, 126}, {{92, 0, 0, 0, 0, 0, 148, 19, 62, 185, 36, 5, 144, 156, 17, 88}, 126}, {{92, 0, 0, 245, 101, 169, 181, 79, 183, 170, 13, 74, 12, 53, 84, 249}, 126}, {{92, 0, 0, 35, 92, 161, 89, 143, 36, 164, 145, 125, 8, 54, 46, 8}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 126}, {{92, 0, 0, 0, 220, 102, 140, 99, 123, 127, 224, 70, 119, 47, 78, 119}, 126}, {{92, 0, 0, 0, 0, 173, 48, 30, 162, 118, 68, 51, 121, 222, 110, 22}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 169, 149}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 168, 62, 133, 63, 50}, 126}, {{92, 0, 217, 160, 137, 249, 155, 11, 186, 17, 146, 253, 254, 88, 178, 255}, 126}, {{92, 0, 0, 239, 46, 108, 141, 100, 235, 125, 250, 177, 127, 173, 180, 49}, 126}, {{92, 0, 0, 0, 161, 128, 137, 239, 135, 103, 51, 131, 95, 1, 162, 174}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 135, 149, 22, 135, 137, 65, 61}, 126}, {{92, 0, 170, 165, 221, 19, 44, 255, 75, 185, 181, 149, 91, 153, 133, 67}, 126}, {{92, 0, 178, 222, 60, 208, 229, 134, 114, 96, 171, 145, 221, 57, 176, 1}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 219, 75, 192, 181, 132, 72, 190, 174}, 126}, {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 123}, 126}, {{92, 0, 0, 232, 124, 180, 72, 96, 82, 193, 241, 143, 144, 36, 53, 53}, 126}, {{92, 0, 235, 102, 113, 197, 60, 95, 198, 162, 39, 82, 82, 171, 202, 198}, 126}, {{92, 0, 0, 0, 213, 87, 118, 205, 232, 147, 231, 52, 192, 96, 97, 5}, 126}, {{92, 0, 0, 0, 0, 0, 193, 13, 227, 8, 218, 195, 130, 0, 104, 39}, 126}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 56, 38}, 106}, {{125, 0, 0, 0, 196, 145, 30, 87, 132, 146, 109, 223, 52, 69, 162, 102}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 146, 25}, 106}, {{125, 0, 0, 0, 0, 0, 189, 31, 13, 253, 137, 17, 211, 3, 134, 121}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 150, 61, 60, 209, 105, 189, 201}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 132, 85, 72, 162, 123, 193, 6}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 193}, 106}, {{125, 0, 0, 0, 0, 0, 147, 168, 52, 59, 230, 59, 164, 33, 69, 175}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 43, 241, 76, 144, 213, 99, 161, 168, 34, 130, 10, 1}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 216, 28, 56, 204, 7}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 11, 55, 116, 147, 193, 135, 255}, 106}, {{125, 0, 0, 0, 231, 31, 115, 68, 125, 151, 252, 95, 51, 239, 89, 247}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 24, 58}, 106}, {{125, 0, 0, 37, 225, 134, 240, 151, 152, 17, 193, 172, 106, 53, 51, 114}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 139, 219, 253, 194, 251, 109, 38, 53}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 231, 98, 18, 78, 77, 188, 126, 200}, 106}, {{125, 0, 0, 0, 0, 0, 221, 30, 63, 151, 191, 18, 119, 203, 115, 181}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 172, 63, 239, 154}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 232, 65, 13, 248, 52, 179, 30, 122, 125, 11, 48}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 122, 253, 116, 98, 162}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 41, 116}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 78, 20, 61}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 47, 160}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 163, 222, 46, 190}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 170, 247, 90, 233, 171, 98, 196, 24}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 106}, {{125, 0, 0, 0, 0, 0, 0, 177, 201, 203, 197, 89, 4, 216, 186, 165}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 166, 204}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 72, 112, 184, 20, 166, 142, 75, 55, 147, 77, 66, 29, 254}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 56, 16, 191, 216, 177}, 106}, {{125, 0, 0, 0, 0, 0, 0, 202, 198, 180, 35, 30, 160, 252, 155, 110}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 183, 61, 49, 161, 142, 16, 174, 44}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 174, 17, 175, 72, 47, 85, 222}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 106}, {{125, 0, 0, 1, 186, 73, 169, 171, 96, 41, 203, 132, 52, 243, 82, 249}, 106}, {{125, 0, 0, 34, 131, 252, 214, 237, 129, 57, 167, 229, 154, 200, 238, 146}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 245, 134, 12, 92, 96, 234, 20}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 255, 1, 170, 134, 76, 43, 112, 158}, 106}, {{125, 0, 0, 0, 0, 0, 0, 39, 114, 117, 154, 100, 218, 32, 204, 36}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 255, 252, 170}, 106}, {{125, 0, 0, 0, 0, 241, 133, 239, 233, 75, 66, 42, 10, 130, 128, 11}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 86, 139, 56, 216, 83}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 62, 17, 43, 243}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 196}, 106}, {{125, 0, 0, 95, 30, 93, 5, 242, 152, 79, 238, 179, 209, 99, 155, 165}, 106}, {{125, 0, 0, 0, 0, 0, 19, 48, 70, 15, 110, 238, 94, 132, 244, 158}, 106}, {{125, 0, 0, 0, 0, 206, 171, 241, 131, 245, 168, 234, 144, 35, 12, 215}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 18}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 220}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 233}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 185, 86, 227, 232, 129, 33, 62, 146}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 46}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 123, 161, 94, 53, 154}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 255}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 168, 139, 20, 113, 192, 57, 93}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 106}, {{125, 0, 0, 0, 0, 0, 90, 2, 190, 172, 157, 187, 160, 204, 106, 167}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 79, 246, 98, 227, 247, 77, 175, 16, 37, 206, 251, 159}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 93}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 65, 86, 112, 73, 163, 76, 81, 56}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 87, 130, 255, 24, 219, 84, 166}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 128, 133, 162, 127, 44, 223, 73}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 106}, {{125, 0, 0, 0, 0, 0, 89, 146, 199, 234, 171, 125, 53, 229, 219, 196}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 166, 240, 165, 16, 118, 82, 40}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 93, 54, 40, 202, 213}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 57, 132, 58, 97, 182, 196, 156, 111}, 106}, {{125, 0, 0, 0, 26, 161, 59, 157, 149, 196, 144, 171, 24, 63, 68, 26}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 225, 52, 20, 245, 66, 177, 144, 187}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 216, 42, 166, 180, 84, 79, 93, 124}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 132, 108, 63, 159}, 106}, {{125, 0, 0, 0, 0, 0, 0, 201, 171, 188, 255, 21, 135, 238, 152, 39}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 216, 127}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 221}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 34, 76, 218, 40, 162, 61, 17, 92}, 106}, {{125, 0, 0, 125, 225, 250, 188, 70, 8, 181, 11, 171, 209, 174, 196, 81}, 106}, {{125, 0, 0, 0, 0, 34, 22, 152, 207, 15, 71, 195, 60, 203, 82, 156}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 51, 187, 54}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 179, 37, 197, 171, 156}, 106}, {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 177, 103, 58, 112, 253}, 106}, {{125, 0, 0, 0, 0, 36, 18, 72, 216, 128, 73, 244, 11, 223, 89, 163}, 106}, {{56, 59, 35, 82, 101, 72, 0, 0, 17, 211, 116, 102, 8, 135, 202, 241}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 35, 117, 229, 112, 149, 176}, 96}, {{56, 59, 35, 82, 101, 72, 0, 31, 115, 167, 26, 244, 57, 117, 159, 197}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 29, 90, 94, 170}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 20, 56, 207, 69, 168, 247, 164}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 148, 41, 102, 77, 66}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 131, 25, 64, 87, 104, 127, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 29, 247, 104, 2, 111, 193}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 246, 80, 227, 251, 49, 114, 210}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 134, 119, 188}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 68, 142}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 126, 121, 144}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 123, 137, 90}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 222, 72, 93}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 199, 127, 87, 39, 133}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 154, 84, 190, 171, 161, 226, 131, 238}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 80, 2}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 135, 118}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 80, 59, 110, 0, 30, 234, 142, 3}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 153, 5, 63, 244, 231}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 68, 76, 74, 234}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 57, 81, 220, 176, 168, 63, 44}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 181, 78, 81, 177, 36}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 146, 242, 24, 60, 50, 124, 23}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 206, 12, 19, 46}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 210, 95}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 37, 26}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 213, 94}, 96}, {{56, 59, 35, 82, 101, 72, 0, 52, 127, 108, 249, 137, 104, 103, 19, 33}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 184, 90, 54, 5, 239, 7}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 41, 66, 117}, 96}, {{56, 59, 35, 82, 101, 72, 0, 41, 26, 202, 25, 65, 68, 185, 193, 117}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 120, 225, 128}, 96}, {{56, 59, 35, 82, 101, 72, 0, 152, 79, 25, 53, 31, 183, 178, 249, 33}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 149, 95, 21, 202, 185, 175, 251, 116}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 90, 51, 130, 170, 231, 235}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 228, 6, 178, 206, 114, 166}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 53, 0, 173, 187, 233, 242}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 253, 224, 140, 89, 187, 216}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 75, 32, 199, 222, 45, 101}, 96}, {{56, 59, 35, 82, 101, 72, 0, 9, 12, 15, 7, 159, 221, 63, 196, 45}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 35, 180}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 140, 62, 161, 122, 18, 191, 163}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 217, 130, 255, 126, 137, 226}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 248, 42, 132, 94, 8}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 28, 9, 88, 147, 75, 51, 75}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 143, 118, 204, 227, 96, 176, 204, 165}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 14, 239, 254, 48}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 196, 26}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 118, 4, 1, 39}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 4, 25, 132, 11}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 199, 19, 243, 203, 230}, 96}, {{56, 59, 35, 82, 101, 72, 0, 137, 56, 250, 19, 5, 50, 21, 25, 51}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 220, 186, 69, 209, 59}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 144, 189, 198, 1}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 197, 190, 29, 97, 250, 141}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 41, 69, 86, 27, 82, 48}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 165, 58, 110, 173, 132, 30, 223, 15}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 72, 14}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 113, 74, 39, 206, 37, 63, 87, 111}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 124, 132, 106}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 66, 175, 137, 242, 45}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 118, 124, 213, 84, 135, 61, 186, 94}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 12, 15}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 35, 79, 66, 155, 88, 220, 41}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 170, 49, 137, 182, 238, 12, 130}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 225, 225, 104}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 21, 205, 185, 42, 47, 12, 242, 50}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 175, 136, 122, 56, 72, 176, 48, 151}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 13, 102}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 163, 49, 151, 18, 1, 60}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 109, 94, 251, 99, 157}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 16, 76, 233, 249, 61, 34, 45}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 174, 139, 65, 254, 145, 218, 87, 200}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 76, 73}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 119, 113}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 78, 57, 86, 5, 154, 126, 203, 212}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 195, 88, 2, 9, 202, 59, 10, 46}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 237, 181, 142, 203, 45, 191}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{184, 72, 77, 251, 8, 166, 0, 0, 69, 107, 0, 36, 130, 40, 222, 54}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 37, 110, 133, 25, 148, 221, 24}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 210, 11, 175, 222, 254, 113, 244}, 45}, {{184, 72, 77, 251, 8, 166, 0, 203, 196, 198, 213, 147, 110, 158, 75, 41}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 67, 199, 38, 220, 201, 229, 7, 228}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 191, 200, 56, 176, 241, 201, 95}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 175, 64, 64, 80}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 130, 77, 27, 163}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 200, 205, 179, 81, 96, 106, 86, 9}, 45}, {{184, 72, 77, 251, 8, 166, 0, 79, 141, 166, 186, 190, 188, 242, 70, 142}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 189, 32, 66}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 145, 128, 167, 183}, 45}, {{184, 72, 77, 251, 8, 166, 0, 170, 50, 23, 217, 3, 137, 253, 207, 171}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 73, 208, 8, 17, 219, 35, 249, 218}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 232, 45, 55, 169, 99, 177, 241}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 157, 126, 1, 250, 166, 59, 247, 162}, 45}, {{184, 72, 77, 251, 8, 166, 0, 54, 36, 245, 128, 153, 62, 155, 56, 137}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 25, 150, 227, 97, 191, 227}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 104, 25, 7, 66, 10, 144}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 197, 134, 218, 90, 48, 40, 207}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 91, 180, 88}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 201, 243, 74, 8, 170}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 90, 240, 213}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 86, 49, 110, 29}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 143, 94, 134, 116, 9, 48, 11, 200}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 46, 142, 122, 41}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 33, 226, 124, 50, 238}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 198, 206, 83}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 238, 20, 79, 214, 183}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 208, 91, 51, 139, 91}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 210, 214, 232, 87, 186}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 154, 92, 23, 115, 134, 99}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 132, 73, 196, 253, 218, 207, 194, 5}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 35, 61, 113, 66}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 196, 81, 184, 76, 187, 82, 6}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 171, 17, 26, 56, 184, 9, 215, 21, 203}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 136, 59, 115, 153, 71}, 45}, {{184, 72, 77, 251, 8, 166, 18, 174, 66, 93, 113, 43, 140, 176, 57, 108}, 45}, {{184, 72, 77, 251, 8, 166, 0, 216, 119, 237, 107, 188, 104, 14, 199, 19}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 129, 195, 28, 80, 248, 49, 113, 159}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 8, 33, 188, 198, 72}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 95, 8}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 249, 210, 252, 74}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 216, 182}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 71, 232, 42, 13, 55}, 45}, {{184, 72, 77, 251, 8, 166, 0, 119, 142, 2, 143, 239, 211, 67, 52, 38}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 124, 9, 87, 82, 254}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 107, 188, 242, 103, 38, 0, 138}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 56, 207, 232, 56}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 131, 219, 20, 91, 100}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 86, 119}, 45}, {{184, 72, 77, 251, 8, 166, 0, 93, 232, 20, 125, 229, 114, 91, 138, 133}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 94, 29, 233, 67, 51, 63}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 142, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 129, 73}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 101, 31}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 204, 200, 122, 191}, 45}, {{184, 72, 77, 251, 8, 166, 0, 57, 107, 240, 148, 130, 185, 5, 62, 216}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 185, 236}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 219, 252, 78, 179, 89, 219}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 216, 15, 225, 102, 177}, 45}, {{184, 72, 77, 251, 8, 166, 0, 253, 3, 125, 175, 95, 214, 217, 121, 66}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 224, 45, 36, 39}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 44, 26, 199, 102, 46, 126}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 63, 201}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 187, 72, 77, 225}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 162, 209, 205, 100, 150, 111, 215, 145}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 128, 67, 243, 40, 162, 203, 140, 71}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 106, 55, 13, 107, 86, 254, 137}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 167, 252, 141, 180, 93, 56, 42}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 17, 210, 18}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 42, 91, 85, 214, 210, 55, 229}, 45}, {{184, 72, 77, 251, 8, 166, 0, 91, 54, 94, 128, 251, 9, 60, 248, 106}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 177, 87, 131}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 123, 113, 204, 172, 59}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 236, 207, 221, 154, 37, 67}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 167, 166, 125}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 45, 14, 213, 15}, 45}, {{184, 72, 77, 251, 8, 166, 0, 131, 49, 224, 215, 59, 47, 18, 249, 238}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 31, 36, 7, 163, 68, 119}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 201, 78, 44, 75, 82, 215, 89}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 45}, {{184, 72, 77, 251, 8, 166, 127, 125, 180, 66, 196, 230, 32, 205, 214, 214}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 172, 141}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 87, 149, 106}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 33, 3, 95, 50, 174}, 45}, {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 24, 185, 79, 211, 182}, 45}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 184}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 235}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 67}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 125}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 199}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 219, 31}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 189}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 110, 32}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 194, 190}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 177}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 200}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 64}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 71}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 122}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 127}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 229}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 161}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 252}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 119}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 47, 103}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 157}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 68}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 150}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 74}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 174}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 154}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 50}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 207}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 169}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 31}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 124}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 214}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 25}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 152, 106}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 11}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 79}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 148}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 129}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 130}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 39}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 48, 211}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 202}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 254}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 70}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 55}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 192}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 154}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 209}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 214}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 219, 248}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 103}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 224}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 52}, 8}, {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 147}, 8}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 64, 249}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 41, 136}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 62, 84}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 159, 149, 168, 69, 62, 43, 124}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 12, 96, 214}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 6, 176, 30, 10, 30, 203, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 108, 155, 218}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 52}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 126, 62, 251, 8, 35, 149}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 84, 104}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 153, 144, 33, 193, 125, 158, 233}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 104, 111, 4, 131, 246}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 252, 209, 250}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 92, 116, 74}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 111}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 72, 81, 9, 119, 133, 173, 147}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 148, 239}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 32, 208, 139, 43, 179}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 49, 23, 64, 255, 166, 157}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 252, 65, 164, 70, 104}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 114, 20}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 35, 122, 216, 123, 134, 87}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 125, 238, 118}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 135, 235, 167, 53, 238, 146, 19}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 212, 217}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 67, 135, 135, 35, 121, 3, 68}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 190, 122, 227, 196, 225}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 88, 48, 22, 211, 244, 224, 47}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 148, 47, 75, 126, 81, 236, 192}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 143, 1, 84, 181, 73, 38, 49}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 91, 66, 44, 106, 143}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 135, 56}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 156, 226, 124, 101, 149}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 186, 85, 243, 150, 36, 234}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 124, 238, 13, 60, 123, 97, 157, 53}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 114, 98, 150, 156}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 127, 169, 42, 45}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 179}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 207, 6, 127, 126, 33, 21, 66}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 154, 30, 239, 159}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 37}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 127, 143, 25, 220, 176}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 128, 174, 66, 45, 231}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 1, 94, 63, 87}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 226, 124, 136, 113, 120, 37}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 93, 150, 227, 61, 11, 83, 41}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 32}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 104, 1, 95, 198, 35, 1, 70}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 221, 110, 111, 35, 25, 202, 69}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 76, 238, 226, 101}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 188, 153, 149, 39}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 117, 98, 61, 182, 140, 66}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 224, 161, 44, 54, 197, 70, 159}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 199, 148, 187, 35}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 17, 75, 145, 161, 49, 48}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 17, 254, 119, 129, 232, 222}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 201, 143, 94}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 50, 190}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 78, 41, 5, 59, 253}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 184, 98, 191}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 180, 253, 170, 121}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 247, 124}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 190, 45, 248, 186, 65}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 129, 240, 154, 191}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 10, 170, 160}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 187, 134, 52, 79, 18}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 169, 249, 173, 167, 227}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 154, 94, 15, 135, 23, 46, 254}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 220, 20, 145, 92, 54, 10, 75}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 16, 148}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 105, 203, 139, 169, 248, 156}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 244, 145, 129, 26}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 202, 5, 217, 217, 146, 45, 170}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 131, 96, 145, 153, 123}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 204, 147, 189, 179}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 228, 54, 92, 159, 10, 51, 101}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 176, 1, 246, 102, 184}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 123, 152, 128}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 53, 217, 76}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 21}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 233, 138, 87, 216, 216, 198}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 91, 130, 3}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 174, 81, 212, 74, 35, 210}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 170, 190}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 16, 91, 166, 138, 120, 60, 121}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 202, 147, 219}, 226}, {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 231}, 226}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 125}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 202, 101, 68, 255, 220, 130}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 56, 152, 173, 136, 207}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 207, 4, 46, 81, 89, 170, 201, 84}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 69, 42, 161, 78, 169, 3, 140}, 222}, {{224, 48, 154, 231, 32, 0, 129, 3, 202, 180, 82, 205, 117, 77, 166, 53}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 156}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 93, 209, 127, 174, 133, 138, 174, 120}, 222}, {{224, 48, 154, 231, 32, 0, 159, 14, 171, 222, 140, 205, 76, 109, 34, 34}, 222}, {{224, 48, 154, 231, 32, 196, 51, 188, 95, 221, 167, 22, 69, 60, 214, 249}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 251, 175, 68, 101, 229, 230, 114, 140}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 31, 164, 16, 157}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 142, 113, 104}, 222}, {{224, 48, 154, 231, 32, 0, 0, 79, 91, 185, 134, 148, 10, 97, 157, 242}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 97, 26, 148, 33, 98, 145, 67}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 167, 20, 243, 200}, 222}, {{224, 48, 154, 231, 32, 0, 0, 169, 95, 16, 164, 103, 115, 94, 68, 153}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 20}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 102, 140, 102, 95, 217, 200}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 157, 72, 115, 97, 161}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 250, 71, 166, 45, 26, 247, 128, 49}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 245, 51, 222, 214, 30, 127}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 8, 84, 190}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 227, 197, 216, 138, 7, 141, 5, 153}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 222}, {{224, 48, 154, 231, 32, 0, 206, 203, 37, 210, 198, 26, 93, 117, 58, 46}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 152, 64, 21, 147}, 222}, {{224, 48, 154, 231, 32, 0, 0, 209, 35, 115, 80, 178, 229, 6, 6, 116}, 222}, {{224, 48, 154, 231, 32, 0, 0, 205, 209, 122, 201, 192, 115, 114, 230, 81}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 59, 18, 187, 218, 215, 42}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 176, 171, 224, 94, 34}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 133, 219, 141, 57, 241, 190, 104, 153, 188, 122}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 158}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 5, 3, 199, 113, 194, 191, 151, 34, 108, 209}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 222}, {{224, 48, 154, 231, 32, 0, 216, 176, 138, 77, 16, 62, 169, 103, 84, 8}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 4, 121, 100}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 174, 189, 139, 5, 20}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 222}, {{224, 48, 154, 231, 32, 0, 221, 108, 186, 15, 246, 65, 123, 38, 114, 195}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 240, 36, 86, 241}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 22, 2, 73, 50, 189, 42, 20, 245}, 222}, {{224, 48, 154, 231, 32, 148, 29, 128, 51, 227, 192, 166, 148, 222, 253, 177}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 37, 32, 75, 175, 58, 177, 147, 139}, 222}, {{224, 48, 154, 231, 32, 0, 181, 157, 221, 35, 209, 187, 94, 220, 26, 37}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 223, 55, 24, 27, 2, 202, 111}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 237, 85, 194, 154, 81, 30}, 222}, {{224, 48, 154, 231, 32, 0, 0, 149, 203, 172, 18, 189, 174, 115, 111, 25}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 53, 47, 222}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 205, 60, 78, 93, 37, 2}, 222}, {{224, 48, 154, 231, 32, 0, 235, 206, 229, 60, 106, 226, 210, 166, 73, 57}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 222}, {{224, 48, 154, 231, 32, 249, 236, 169, 28, 11, 174, 104, 120, 147, 249, 6}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 28, 0, 45, 225}, 222}, {{224, 48, 154, 231, 32, 0, 0, 157, 154, 136, 241, 131, 187, 57, 215, 218}, 222}, {{224, 48, 154, 231, 32, 0, 184, 56, 93, 230, 249, 156, 178, 188, 36, 244}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 162, 229, 112, 41, 11, 109, 37, 105}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 29}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 10, 163, 205, 192, 112}, 222}, {{224, 48, 154, 231, 32, 0, 0, 1, 27, 130, 27, 150, 222, 228, 15, 202}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 22, 233, 135, 243, 15, 178}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 154}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 189, 49, 209}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 140, 152, 245, 70, 35, 1}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 190, 231, 50, 38, 68, 39, 153, 20}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 222}, {{224, 48, 154, 231, 32, 0, 0, 90, 250, 169, 252, 92, 55, 27, 51, 248}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 230, 157, 58, 73}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 217, 64, 224, 190, 218, 27, 183, 86}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 177, 228, 235, 70}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 152, 149, 154}, 222}, {{224, 48, 154, 231, 32, 0, 0, 82, 61, 176, 82, 122, 108, 168, 8, 195}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 222}, {{224, 48, 154, 231, 32, 0, 0, 180, 25, 53, 124, 212, 134, 229, 144, 137}, 222}, {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 29, 43, 43, 110, 56, 210}, 222}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 247, 217, 204, 233}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 139, 10, 22, 5}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 165, 11}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 185, 248}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 234, 224, 241, 66, 24}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 207, 173}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 24, 45, 156, 85, 86}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 226, 216, 168, 244}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 70, 205, 85, 38}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 207, 88, 157}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 201, 69, 127, 2, 146, 228}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 127, 236}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 83, 21, 201, 90, 41, 56}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 158, 149, 32, 229, 46}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 20, 173, 5}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 90}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 153, 157, 131, 57, 140}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 129, 1, 175, 63, 139}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 114, 126, 217}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 220, 225, 74, 104, 104}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 247, 182, 29}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 223, 120, 229, 7, 108}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 102}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 89}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 177, 214, 33, 159, 119, 63, 41}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 192, 94, 16, 38, 223}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 62, 87, 255}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 27, 216, 118, 3, 43}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 6, 191, 66}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 190, 81, 112}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 206, 37, 125}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 226, 19, 91, 122, 230}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 170, 63}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 135, 249}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 150, 117, 217, 124}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 163}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 204, 52, 135, 241}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 189, 111, 162}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 87}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 245, 72}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 19, 214, 124, 23, 191, 1}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 171, 248, 54, 69, 131}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 140, 246}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 21, 179}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 206, 0, 247}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 103, 218}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 33, 31, 111, 120}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 156}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 181, 153, 183, 66}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 192, 148, 153}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 233, 32, 234, 115}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 26}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 17, 41}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 244, 126}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 64}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 132, 249}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 233, 213, 73, 145}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 114, 89, 95}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 100, 49, 177, 76}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 136}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 170, 37, 84, 148, 99}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 152}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 133}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 16, 67}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 235, 175, 73, 137, 131}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 119, 151, 148, 213, 199}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 251, 84, 165}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 239, 200, 177, 62}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 39, 201, 212, 97, 164}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 161, 76, 74}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 67, 238}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 138}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 248, 125}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 100, 11, 23}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 102, 11, 247, 43, 209}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 24, 111}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 66}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 216, 196, 51}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 30, 222, 183, 37, 162, 117}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 163}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 23, 205}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 165, 236, 137, 2, 217, 40}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 80, 154, 67, 57, 54, 154}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 7, 96, 102}, 218}, {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 132}, 218}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 45}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 17}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 237}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 80}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 114}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 96}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 27}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 187}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 56}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 157}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 52}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 46}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 217}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 216}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 97}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 158}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 236}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 157}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 186}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 132}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 51}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 135}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 219}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 251}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 233}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 91}, 59}, {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 59}, {{75, 0, 0, 251, 39, 219, 167, 71, 92, 231, 250, 83, 252, 31, 23, 19}, 80}, {{75, 0, 0, 0, 0, 17, 133, 240, 145, 47, 202, 1, 154, 124, 91, 251}, 80}, {{75, 0, 0, 0, 0, 0, 18, 197, 182, 109, 176, 20, 115, 147, 195, 59}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 215, 110, 232, 184, 236}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 128}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 170, 72, 1, 250, 69, 16, 136, 216}, 80}, {{75, 0, 0, 0, 0, 0, 0, 3, 237, 30, 154, 58, 190, 203, 255, 140}, 80}, {{75, 0, 0, 0, 135, 245, 201, 1, 92, 203, 120, 132, 99, 7, 10, 21}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 182, 66, 97}, 80}, {{75, 0, 0, 0, 0, 26, 164, 5, 87, 74, 235, 121, 71, 197, 20, 129}, 80}, {{75, 0, 0, 0, 0, 0, 195, 124, 168, 221, 33, 152, 252, 212, 228, 134}, 80}, {{75, 0, 0, 240, 255, 31, 123, 31, 119, 89, 3, 165, 102, 98, 19, 27}, 80}, {{75, 0, 0, 0, 0, 0, 58, 118, 178, 81, 5, 199, 249, 228, 116, 48}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 173, 136, 34, 12}, 80}, {{75, 0, 0, 20, 196, 194, 211, 53, 146, 253, 37, 137, 135, 11, 238, 165}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 113, 74, 22}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 143, 62}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 221, 237, 183, 252, 119}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 141, 204}, 80}, {{75, 0, 0, 0, 0, 0, 198, 127, 14, 225, 184, 246, 61, 204, 24, 157}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 198, 217}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 167, 55, 38, 185, 36, 221, 216}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 80}, {{75, 0, 0, 232, 3, 242, 165, 132, 241, 57, 69, 95, 248, 213, 231, 219}, 80}, {{75, 0, 0, 0, 0, 0, 20, 215, 94, 100, 69, 126, 51, 109, 169, 236}, 80}, {{75, 0, 0, 56, 7, 5, 10, 228, 128, 103, 23, 120, 253, 135, 215, 184}, 80}, {{75, 0, 0, 0, 0, 0, 16, 40, 165, 230, 68, 109, 56, 157, 88, 113}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 27, 132, 58, 102, 22, 238, 220, 148}, 80}, {{75, 0, 0, 0, 75, 239, 219, 244, 35, 235, 133, 84, 18, 197, 135, 179}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 157, 130, 109, 14}, 80}, {{75, 0, 0, 0, 5, 120, 203, 90, 62, 66, 127, 133, 105, 165, 75, 36}, 80}, {{75, 0, 0, 0, 108, 227, 156, 203, 157, 141, 41, 68, 174, 48, 1, 186}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 143, 23, 32, 198, 9, 61, 188, 29}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 174, 72, 67, 93, 101, 217, 40}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 59, 4}, 80}, {{75, 0, 0, 0, 0, 186, 81, 134, 254, 0, 255, 138, 202, 216, 151, 236}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 80, 196, 160, 24, 162, 72, 109}, 80}, {{75, 0, 0, 0, 0, 0, 0, 113, 129, 152, 36, 152, 82, 208, 142, 93}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, 65, 197}, 80}, {{75, 0, 106, 57, 54, 168, 107, 122, 126, 50, 58, 133, 104, 250, 54, 171}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 99, 135, 198, 152, 28, 255, 67}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 136}, 80}, {{75, 0, 0, 0, 0, 94, 177, 121, 88, 169, 129, 143, 131, 152, 188, 124}, 80}, {{75, 0, 0, 0, 0, 0, 157, 118, 36, 31, 90, 30, 0, 193, 175, 106}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 16, 123, 167, 170, 133}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 162, 91, 155, 139, 127}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 123, 240, 253, 66, 99, 204, 111, 200}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 16, 248, 27, 248, 59}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{75, 0, 0, 0, 0, 0, 0, 222, 70, 110, 27, 36, 130, 82, 19, 184}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 68, 142}, 80}, {{75, 0, 0, 212, 101, 31, 132, 4, 170, 188, 229, 240, 14, 68, 104, 200}, 80}, {{75, 0, 0, 0, 0, 81, 150, 90, 17, 18, 116, 149, 152, 55, 199, 235}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 236, 39, 192, 166, 89}, 80}, {{75, 0, 0, 0, 0, 218, 71, 59, 11, 183, 127, 219, 194, 74, 215, 187}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 93, 152}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 155, 219, 161, 149, 8, 94, 5}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 76, 227, 64, 74}, 80}, {{75, 0, 0, 0, 66, 166, 189, 125, 122, 58, 37, 28, 29, 31, 60, 195}, 80}, {{75, 0, 0, 0, 143, 0, 52, 174, 247, 24, 36, 98, 235, 86, 239, 79}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 199, 183, 13, 108, 109}, 80}, {{75, 0, 0, 0, 0, 0, 89, 197, 51, 117, 156, 140, 46, 147, 240, 70}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 209, 30}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 176, 174, 207, 221, 82, 31, 159}, 80}, {{75, 0, 0, 0, 0, 0, 0, 56, 185, 160, 68, 231, 208, 249, 109, 9}, 80}, {{75, 0, 0, 0, 0, 137, 13, 101, 85, 108, 226, 87, 26, 228, 218, 144}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 137, 53, 176, 161, 182, 186, 56}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 245, 123, 46, 86, 176, 192, 139}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 9, 249, 6, 151, 210, 20, 233, 67}, 80}, {{75, 0, 146, 250, 215, 207, 137, 19, 226, 124, 78, 90, 39, 208, 212, 94}, 80}, {{75, 0, 0, 69, 62, 85, 224, 183, 202, 248, 61, 152, 205, 162, 124, 108}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 104, 42, 164, 233, 144}, 80}, {{75, 0, 0, 0, 0, 185, 156, 8, 245, 199, 186, 206, 239, 29, 50, 119}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 61, 166, 159, 30, 30}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 44, 101, 254, 26}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 69, 36, 106, 165, 60, 207, 238, 168}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 32}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 164}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 81, 217}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 237, 83, 27, 66}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 135}, 80}, {{75, 0, 0, 0, 0, 0, 146, 174, 192, 65, 71, 219, 199, 39, 86, 132}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 252, 48, 145, 114, 157, 120, 106}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 118}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 123, 206, 207, 165}, 80}, {{75, 0, 0, 0, 0, 0, 0, 215, 45, 41, 191, 134, 83, 14, 70, 127}, 80}, {{75, 0, 0, 0, 123, 92, 6, 207, 4, 43, 190, 62, 76, 109, 251, 105}, 80}, {{75, 0, 11, 166, 5, 71, 100, 99, 160, 202, 179, 125, 191, 18, 75, 177}, 80}, {{75, 0, 0, 0, 0, 142, 85, 100, 211, 213, 27, 60, 102, 136, 14, 157}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{75, 0, 0, 0, 157, 143, 66, 190, 5, 58, 222, 28, 137, 142, 21, 188}, 80}, {{75, 0, 0, 0, 0, 0, 201, 218, 43, 186, 160, 244, 158, 72, 69, 225}, 80}, {{75, 0, 0, 0, 190, 101, 70, 127, 93, 69, 190, 246, 59, 83, 184, 214}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 210, 65, 184}, 80}, {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 15}, 80}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 181, 97, 12, 195, 209, 64, 44}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 176, 91, 75, 142, 157, 224}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 53, 13, 214, 236, 159, 167, 227, 82}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 97, 46, 22, 163, 79}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 96, 216, 242}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 18, 24, 166, 181, 143, 101, 243, 118}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 167, 230, 84}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 177, 99, 173, 108, 32, 116, 42}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 130, 177, 24, 119, 16, 214, 217}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 113}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 77, 160, 84, 75, 59}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 28, 206}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 47, 67, 123}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 64, 128, 105, 48, 86, 106, 18}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 64, 145, 247, 240, 139, 3, 26, 132}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 109, 190, 83, 179}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 113, 246, 248, 252, 198, 39, 167, 141}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 23}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 227, 30, 132, 49, 254}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 207, 199, 78, 83, 206, 128, 94}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 113, 65, 62}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 224, 204, 30, 120}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 55, 46, 218, 161, 60, 209, 255}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 135, 56, 163, 61}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 244, 230, 48, 136, 125, 16}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 69, 17, 2}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 93, 101, 77, 135, 80}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 83, 222, 112, 200, 218, 174}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 91, 0, 243, 4, 190, 225}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 54, 32, 236, 134, 218, 98, 246}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 211}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 188, 44, 225, 181, 165, 225}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 15, 94, 246, 40}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 89, 180, 29}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 226, 203, 124}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 201, 156, 38, 104, 2, 232}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 195}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 10, 141, 236, 91, 5, 238, 128, 218}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 77, 119, 191, 123, 241, 176}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 104, 16, 190, 112, 27, 249, 142, 173}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 226}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 39, 171, 227, 28, 172}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 61, 188, 108, 240, 144, 186, 236, 4}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 4, 177, 19, 43, 208, 19, 38}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 1, 1, 153, 161, 177, 114, 62, 102}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 53, 84, 203, 233}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 36, 71, 32}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 13, 52, 74, 188, 68, 108}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 161, 204, 82, 30, 88, 216, 245}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 21, 225, 166, 37, 90}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 149, 104}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 73, 37, 25}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 59, 21, 80, 255, 154, 59, 61}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 110, 254, 63}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 99, 60}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 234, 172, 195, 51}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 164, 109, 242, 125, 177, 79, 222, 130}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 125, 26, 87, 171, 21}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 80, 120, 46, 153, 243, 177, 130, 135}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 139, 36, 108, 12, 48, 55, 49, 229}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 241, 178, 173, 56, 131, 205, 216}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 241, 61, 144, 25, 50, 173, 155, 170}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 205}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 40, 113}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 62}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 199, 161, 66, 139, 172, 210, 56}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 150, 116, 134}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 107, 49, 184, 174, 40}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 251}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 78, 193, 249, 186, 52}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 141, 113, 111, 173, 223, 234, 25, 11}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 189, 184}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 23, 209, 84}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 23, 38, 136, 130, 70, 231, 6, 216}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 200, 231, 183, 236, 154}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 125, 95, 46}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 140, 135, 6, 118, 230, 94, 195}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 118, 131, 133, 186, 134, 221, 95}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 183}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 254, 221, 240, 154, 140}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 102, 253, 4, 159, 70}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 59, 30, 111, 85, 180}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 203, 182, 130, 194, 155, 151, 204}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 101, 75, 248, 106}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 200, 26, 34}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 191, 222, 230, 1, 247, 158}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 131, 14, 162, 117, 65, 193, 204}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 177}, {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 194, 211}, 177}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 27, 240}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 63, 40, 105}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 63, 207, 26}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 114, 106}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 109, 170, 18}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 75}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 145, 126}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 125, 252}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 240, 255}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 230, 251, 172}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 67, 19, 189}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 34, 187}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 88}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 141}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 234, 171}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 104, 73}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 3, 98}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 46}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 176, 157}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 101, 202}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 48}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 103, 190, 48}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 169}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 139}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 21}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 239, 230, 239}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 171, 142}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 155}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 160, 225}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 149}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 89}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 80, 235, 33}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 129, 74}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 205}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 45}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 87}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 197}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 216}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 52, 190}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 26}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 76, 109}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 98, 78}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 160}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 103, 31}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 204}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 203, 161}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 157, 251}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 215, 157, 101}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 56}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 154, 41, 158}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 141, 230, 86}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 182, 131}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 145}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 254, 68}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 238, 49, 33}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 89, 219, 143}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 230, 73, 112}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 181, 193, 41}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 130, 27, 227}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 242, 147}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 94, 242}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 235, 251, 131}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 43}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 42}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 125, 101}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 93, 84}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 134, 109, 124}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 106, 151}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 207}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 197, 173}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 209}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 199, 165}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 249, 140, 60}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 90, 42, 29}, 44}, {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 199, 156}, 44}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 5, 225}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 4}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 191, 23}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 61}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 68}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 45, 167, 238}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 52, 200, 252, 21}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 26, 33, 117}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 155}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 133}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 206, 251, 91}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 22, 22, 3, 221}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 190, 181, 140}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 108, 24, 189}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 28}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 101, 194, 90}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 51, 95}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 19, 241, 173, 160}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 108, 249, 8}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 135}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 101, 253, 168, 116}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 198, 175}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 106, 16, 47}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 16}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 67, 227, 58}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 244}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 69}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 175}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 114, 205}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 143, 190}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 176}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 181, 3, 240}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 131, 255, 94}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 104, 60}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 100, 153}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 212, 182}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 122, 59, 181}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 190}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 206, 127, 70}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 227, 247, 248}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 63}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 4, 119}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 252, 106}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 30, 189}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 217}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 218, 171, 192, 190}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 193, 45, 165}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 148, 15}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 127, 179}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 234}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 156, 181, 251}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 168, 13}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 40, 113, 71}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 222, 33, 98, 232}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 33}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 119}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 152, 233, 70, 67}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 228, 114}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 179, 217, 17}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 17, 238, 150}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 236}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 230, 106}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 187, 251, 219}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 234}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 120, 204, 255}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 63, 18}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 63, 187, 254, 105}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 151, 254, 91}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 15, 18}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 214, 28, 131, 145}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 149}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 83, 19, 164}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 206}, {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 234, 138, 105}, 206}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 213, 62, 184, 187, 254, 122}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 223, 65, 124, 96, 88}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 17, 166}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 152, 191, 75, 168}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 221, 242, 44, 105, 239, 134, 9}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 22, 194, 159, 112, 237}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 64}, {{123, 153, 102, 192, 0, 224, 170, 2, 155, 68, 93, 48, 237, 199, 223, 92}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 40, 176}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 117, 215, 21, 184, 77}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 19, 44, 80, 181, 144, 206, 82}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 233}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 59, 248}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 100, 129, 107, 191, 181, 185, 130}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 193, 164, 131, 48, 114}, 64}, {{123, 153, 102, 192, 0, 148, 9, 173, 215, 157, 165, 120, 211, 206, 114, 105}, 64}, {{123, 153, 102, 192, 0, 0, 37, 71, 88, 184, 122, 49, 136, 198, 20, 146}, 64}, {{123, 153, 102, 192, 0, 201, 113, 138, 148, 80, 26, 103, 246, 137, 222, 128}, 64}, {{123, 153, 102, 192, 0, 0, 103, 7, 35, 107, 80, 19, 40, 140, 122, 199}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 175, 55, 52, 95, 63}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 136}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 134, 243, 174, 128, 135, 190}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 4, 97, 200, 169, 169, 224, 194, 12}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 66}, 64}, {{123, 153, 102, 192, 0, 0, 250, 126, 118, 34, 255, 237, 107, 231, 119, 189}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 82, 12, 73, 105, 173, 100, 40, 253}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 64}, {{123, 153, 102, 192, 0, 0, 255, 135, 148, 133, 209, 132, 216, 208, 81, 3}, 64}, {{123, 153, 102, 192, 0, 0, 205, 185, 121, 11, 204, 91, 142, 81, 3, 6}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 90, 109, 177, 207, 34, 242}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 143, 241}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 40, 253, 236, 232, 222, 236, 45}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 186, 149}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 103, 99, 123, 255, 130}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 250, 107, 237, 247, 198}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 80}, 64}, {{123, 153, 102, 192, 0, 0, 0, 236, 136, 48, 8, 137, 229, 159, 82, 18}, 64}, {{123, 153, 102, 192, 0, 89, 150, 116, 184, 84, 44, 111, 172, 188, 239, 111}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 77}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 81, 126, 37, 146}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 207, 54, 62, 255, 10, 116, 32, 233}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 45, 95, 22, 86, 165, 12}, 64}, {{123, 153, 102, 192, 0, 0, 2, 82, 14, 79, 169, 150, 180, 89, 89, 171}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 124, 112}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 10, 249, 81, 18, 238, 110, 165}, 64}, {{123, 153, 102, 192, 0, 34, 72, 125, 178, 199, 199, 65, 165, 112, 106, 99}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 196, 170}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 156, 54, 16, 48, 150, 115, 62, 78}, 64}, {{123, 153, 102, 192, 0, 0, 4, 252, 161, 103, 123, 241, 204, 68, 182, 147}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 73, 195, 206, 69, 235, 41, 175}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 50}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 191, 132, 245, 118, 155, 158, 112, 142}, 64}, {{123, 153, 102, 192, 0, 33, 252, 84, 55, 183, 193, 63, 18, 178, 152, 86}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 237, 161, 70, 195, 65, 10}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 241, 43, 29, 14, 218, 165, 246, 111}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 239}, 64}, {{123, 153, 102, 192, 92, 97, 246, 5, 116, 155, 151, 163, 46, 188, 97, 81}, 64}, {{123, 153, 102, 192, 0, 0, 198, 229, 119, 2, 115, 124, 218, 88, 16, 126}, 64}, {{123, 153, 102, 192, 0, 0, 127, 186, 160, 128, 231, 30, 16, 19, 227, 190}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 216, 95, 38, 158, 196, 146, 63}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 85, 207, 20, 213}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 0, 0, 145, 39, 44, 195, 50, 99, 184, 219, 196}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 166, 106, 158, 4, 6, 74}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 155}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 188, 211, 77, 49, 195}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 152, 83, 214, 47}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 12, 252, 105, 120, 42, 78, 127}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 150, 49, 116, 99, 7, 155}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 79, 69, 87, 198, 114, 4, 250, 107}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 17, 218, 95, 218, 141, 8, 35}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 227, 62, 247, 209, 250}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{123, 153, 102, 192, 0, 238, 230, 4, 93, 121, 245, 216, 58, 41, 224, 123}, 64}, {{123, 153, 102, 192, 0, 0, 0, 78, 62, 98, 146, 47, 142, 2, 52, 122}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 249, 221}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 74, 150, 7, 4, 78, 116, 141}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 215, 104}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 145}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 97, 97, 56, 113, 120, 199}, 64}, {{123, 153, 102, 192, 0, 0, 168, 141, 223, 213, 168, 42, 90, 201, 226, 41}, 64}, {{123, 153, 102, 192, 0, 248, 164, 125, 228, 99, 100, 166, 79, 37, 236, 225}, 64}, {{123, 153, 102, 192, 0, 0, 0, 255, 139, 54, 107, 179, 233, 243, 205, 51}, 64}, {{123, 153, 102, 192, 0, 0, 66, 160, 213, 99, 208, 107, 65, 72, 89, 254}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 167, 158, 17, 107, 225, 92}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 134, 223, 150, 252}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 148, 156, 11, 42, 194, 59, 107}, 64}, {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 49, 88}, 64}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 217, 36, 46}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 239, 100}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 61}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 29, 32, 90}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 17}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 214, 139}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 162, 47}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 131, 120, 105}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 96}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 43}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 91}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 152}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 164, 100, 55}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 56}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 78, 56}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 23}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 25}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 187, 164, 77}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 77, 30, 188}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 249, 224}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 86, 82, 159}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 127}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 26, 184, 28}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 161, 32, 124}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 20, 10}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 111, 212}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 235}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 206}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 212}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 241}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 230, 76}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 135, 38, 22}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 252, 231, 90}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 6, 253, 92}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 63}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 216, 78, 249}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 146, 108, 109}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 27, 126}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 73}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 127}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 12, 249, 176}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 157}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 93}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 161}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 176, 229}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 48, 11, 194}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 100, 173, 93}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 137, 107, 118}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 194, 71, 147}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 1}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 96, 179, 88}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 224}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 90, 53, 17}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 39, 146, 144}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 35, 229, 146}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 213}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 173, 195}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 31, 117}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 18, 8, 163}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 4, 195, 192}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 249, 29, 165}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 106}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 231}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 223}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 109}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 166, 155, 222}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 184}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 90}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 57, 195}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 163, 108, 139}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 52}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 22, 105, 61}, 236}, {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 185, 194}, 236}, {{159, 235, 60, 0, 0, 0, 194, 179, 49, 185, 29, 220, 139, 63, 234, 220}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 250, 11, 10}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 87, 15, 213, 144, 243, 48, 216, 208, 217, 182}, 101}, {{159, 235, 60, 0, 0, 0, 0, 234, 135, 119, 79, 99, 116, 10, 92, 70}, 101}, {{159, 235, 60, 0, 0, 0, 0, 128, 99, 20, 166, 118, 197, 251, 185, 96}, 101}, {{159, 235, 60, 0, 4, 194, 101, 91, 155, 148, 253, 243, 103, 179, 45, 149}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 159, 180}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 240, 88, 118, 102, 188, 77}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 85, 209, 102}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 164, 218, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 76, 15, 117, 154, 248, 249, 36, 192, 15, 88}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 195}, 101}, {{159, 235, 60, 0, 0, 0, 0, 191, 119, 42, 179, 221, 142, 178, 50, 173}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 99, 142}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 228, 237, 200}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 91, 148, 148, 14, 180}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 238, 188, 157, 109, 198, 37, 196, 245}, 101}, {{159, 235, 60, 0, 0, 251, 152, 18, 233, 164, 236, 174, 177, 180, 52, 160}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 117, 81, 111, 200, 92, 164, 224, 214}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 198, 10, 249, 241, 164, 6}, 101}, {{159, 235, 60, 236, 2, 83, 99, 73, 234, 78, 210, 198, 214, 46, 85, 120}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 197, 131, 59, 91, 208, 102, 210, 96}, 101}, {{159, 235, 60, 0, 0, 0, 0, 227, 193, 113, 153, 94, 90, 202, 190, 50}, 101}, {{159, 235, 60, 0, 0, 0, 0, 208, 35, 77, 186, 45, 25, 153, 151, 6}, 101}, {{159, 235, 60, 0, 66, 97, 167, 164, 239, 224, 227, 118, 140, 167, 69, 52}, 101}, {{159, 235, 60, 0, 0, 0, 0, 107, 45, 163, 142, 106, 106, 87, 106, 222}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 89, 132, 255, 29, 103, 12, 86, 228}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 77, 195}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 176, 170, 30}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 42, 207, 223, 136, 53, 179, 84}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 22, 19, 1, 74, 55, 241}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 58, 137, 218, 94, 61, 229, 222}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 48, 171, 162, 191, 134, 114, 157}, 101}, {{159, 235, 60, 0, 0, 0, 128, 91, 45, 40, 115, 29, 78, 89, 123, 158}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 85, 51, 178, 189, 247}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 29, 53, 134, 73, 60, 237, 251, 44}, 101}, {{159, 235, 60, 0, 0, 0, 0, 139, 98, 242, 40, 197, 98, 62, 109, 213}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 171, 122, 150, 57, 167, 183}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 180, 4, 207, 184, 79}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 80, 88, 58, 128, 181, 82, 57, 11}, 101}, {{159, 235, 60, 0, 0, 2, 191, 82, 105, 98, 95, 230, 232, 131, 183, 104}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 93, 64, 228, 57, 239, 43, 122}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 145, 81}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 237, 56}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 242, 110, 125, 227, 221, 119}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 131, 103, 252, 62, 244}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 172, 113}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 63, 59, 140, 135, 154, 95, 44, 167, 172}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 181, 52}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 65, 180, 4, 168, 88}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 238, 68, 249}, 101}, {{159, 235, 60, 0, 96, 76, 229, 200, 156, 28, 148, 50, 104, 103, 45, 155}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 102, 14, 55, 135, 219, 189, 34}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 24, 53, 13, 174, 75, 192}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 184, 68, 114, 75, 119, 107, 230, 247, 244, 117}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 249, 60}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 229, 142, 203}, 101}, {{159, 235, 60, 0, 0, 34, 216, 58, 107, 230, 205, 185, 83, 19, 180, 112}, 101}, {{159, 235, 60, 0, 0, 0, 0, 51, 223, 247, 128, 140, 74, 130, 2, 39}, 101}, {{159, 235, 60, 0, 0, 27, 230, 25, 147, 172, 36, 56, 218, 83, 15, 174}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 183}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 79, 233, 18}, 101}, {{159, 235, 60, 0, 0, 244, 246, 247, 67, 184, 0, 222, 237, 190, 214, 254}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 84, 46, 177, 45, 28, 101, 7}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 42, 41, 58}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 143, 85, 108, 239, 138, 135, 88}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 107, 111, 53, 109, 32}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 230, 95, 211, 199, 191}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 50, 188}, 101}, {{159, 235, 60, 0, 0, 0, 87, 39, 103, 10, 239, 194, 246, 175, 238, 37}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 178, 139, 146, 151, 115, 58, 25, 96}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 63, 18, 151, 15, 196, 95, 155}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 237, 53, 114, 121, 207, 130}, 101}, {{159, 235, 60, 0, 198, 151, 36, 254, 177, 60, 42, 93, 44, 19, 89, 231}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 226}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 112, 224, 242, 122, 94, 98}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 12, 113, 44, 60, 168, 103}, 101}, {{159, 235, 60, 0, 0, 0, 0, 55, 98, 100, 239, 201, 221, 50, 28, 178}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 29, 48, 70, 137, 185, 199}, 101}, {{159, 235, 60, 0, 0, 0, 0, 149, 13, 0, 37, 65, 104, 138, 183, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 99}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 149, 16, 13, 200, 123, 252}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 101}, {{159, 235, 60, 0, 0, 0, 99, 19, 161, 190, 138, 60, 178, 153, 73, 57}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 41, 152, 146, 180, 144}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 137, 216, 248}, 101}, {{159, 235, 60, 0, 0, 76, 94, 3, 45, 217, 61, 102, 68, 177, 107, 168}, 101}, {{159, 235, 60, 0, 0, 51, 89, 73, 119, 66, 164, 145, 31, 201, 57, 190}, 101}, {{159, 235, 60, 0, 0, 0, 0, 0, 19, 5, 156, 250, 47, 243, 227, 194}, 101}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 52}, 49}, {{42, 194, 150, 0, 0, 0, 0, 120, 153, 35, 74, 33, 60, 188, 232, 184}, 49}, {{42, 194, 150, 0, 0, 0, 0, 22, 208, 6, 62, 128, 60, 165, 157, 247}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{42, 194, 150, 0, 0, 0, 0, 90, 192, 250, 60, 49, 248, 85, 37, 120}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 237, 23, 144, 192, 2, 84, 154, 182}, 49}, {{42, 194, 150, 0, 0, 57, 230, 216, 12, 105, 222, 59, 45, 25, 2, 130}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 49}, {{42, 194, 150, 0, 0, 22, 146, 143, 214, 39, 220, 140, 253, 13, 228, 119}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 222}, 49}, {{42, 194, 150, 0, 0, 139, 189, 55, 247, 206, 199, 33, 122, 254, 90, 245}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 160, 201, 181, 187, 164, 147, 73, 221}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 225, 30, 152, 251, 159}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 121, 75}, 49}, {{42, 194, 150, 0, 0, 0, 161, 94, 161, 248, 250, 28, 13, 83, 52, 182}, 49}, {{42, 194, 150, 0, 0, 0, 0, 91, 8, 73, 255, 147, 23, 164, 58, 175}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 98, 146, 142, 242, 49}, 49}, {{42, 194, 150, 0, 0, 0, 0, 2, 143, 0, 91, 124, 152, 15, 140, 1}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 69, 41, 225, 183, 52, 4, 209, 208}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 229, 124, 123, 85, 122, 126, 183}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 117, 60, 6, 24, 132, 228}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 116, 82, 233, 109, 26}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 156}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{42, 194, 150, 0, 0, 75, 201, 39, 138, 92, 245, 133, 180, 221, 179, 41}, 49}, {{42, 194, 150, 0, 0, 79, 244, 137, 183, 206, 211, 7, 59, 73, 26, 229}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 73}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 175, 57, 96}, 49}, {{42, 194, 150, 0, 0, 0, 77, 154, 179, 228, 107, 1, 194, 190, 31, 195}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 170, 32, 119, 177, 53, 209, 123, 255}, 49}, {{42, 194, 150, 0, 0, 0, 108, 242, 206, 211, 63, 141, 24, 103, 44, 106}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 16, 145, 252}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 91, 106, 62, 100, 147}, 49}, {{42, 194, 150, 0, 0, 0, 21, 201, 211, 53, 201, 244, 15, 149, 121, 241}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 231, 245, 208, 171, 124}, 49}, {{42, 194, 150, 0, 0, 0, 222, 245, 223, 28, 28, 131, 32, 9, 102, 181}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 215, 126, 29, 26, 45, 77, 240, 194}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 49}, {{42, 194, 150, 0, 0, 0, 90, 170, 250, 198, 220, 116, 206, 56, 35, 225}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 83, 124}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 209, 16}, 49}, {{42, 194, 150, 0, 0, 0, 178, 50, 175, 41, 121, 64, 28, 212, 93, 230}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 210, 30, 141, 238, 196, 57}, 49}, {{42, 194, 150, 0, 0, 0, 176, 51, 118, 230, 37, 198, 6, 71, 171, 254}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 58, 65, 169, 207, 210, 11}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{42, 194, 150, 0, 0, 0, 0, 254, 182, 254, 194, 36, 120, 199, 116, 25}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{42, 194, 150, 0, 0, 206, 89, 213, 154, 125, 113, 156, 131, 135, 221, 187}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 49}, {{42, 194, 150, 0, 0, 128, 44, 249, 112, 3, 74, 178, 31, 93, 69, 154}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 219, 228, 244, 149, 43, 81, 234, 155}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 110}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 193, 152, 101, 119, 87, 217, 197, 26}, 49}, {{42, 194, 150, 0, 0, 137, 99, 164, 25, 224, 79, 213, 185, 18, 250, 227}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 51, 38, 66, 152, 221}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 83}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 75, 216, 176, 52, 198, 229}, 49}, {{42, 194, 150, 0, 170, 202, 146, 88, 8, 23, 20, 82, 66, 108, 225, 52}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 174, 138, 111, 24, 207, 207, 25, 37}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 99, 59, 200, 251, 87, 92, 1, 191}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 175, 31}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 41, 104}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 87, 108, 156, 23, 131, 174}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 185, 6, 180, 174, 75, 169, 48, 165}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 236, 221, 134}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 59, 211, 26, 221, 162}, 49}, {{42, 194, 150, 0, 0, 255, 196, 183, 119, 88, 113, 8, 76, 168, 41, 254}, 49}, {{42, 194, 150, 0, 0, 214, 36, 239, 126, 132, 36, 223, 34, 48, 15, 118}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 87, 143, 197, 167, 11, 110, 25}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 29, 144, 230, 101, 43}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 66, 118, 50, 28, 201}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 64, 169}, 49}, {{42, 194, 150, 0, 57, 123, 21, 240, 7, 180, 248, 233, 119, 55, 103, 56}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 134, 129, 24, 133, 165, 171}, 49}, {{42, 194, 150, 0, 0, 0, 0, 58, 90, 70, 2, 248, 191, 92, 139, 157}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 71, 208, 55, 7, 107, 73, 154}, 49}, {{42, 194, 150, 0, 0, 99, 98, 111, 160, 203, 112, 147, 225, 203, 26, 205}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 108, 130, 248, 221, 155, 83}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{42, 194, 150, 0, 225, 203, 251, 115, 45, 170, 143, 74, 32, 156, 185, 120}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 100, 206, 7, 61, 41, 235}, 49}, {{42, 194, 150, 0, 0, 0, 155, 33, 203, 231, 22, 2, 114, 154, 220, 6}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 161}, 49}, {{42, 194, 150, 0, 0, 0, 130, 224, 230, 208, 198, 183, 226, 167, 206, 150}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 49}, {{42, 194, 150, 0, 255, 213, 117, 72, 23, 116, 220, 142, 167, 163, 11, 159}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 2, 164, 50, 131, 147, 243, 205, 202}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 85, 255}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 214, 176, 233, 168, 121, 31}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 203, 97, 67, 58, 25, 61}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 45, 109, 106, 160, 111}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 38, 145, 20, 63, 231, 80, 140, 194}, 49}, {{42, 194, 150, 0, 0, 0, 4, 57, 107, 138, 253, 95, 7, 105, 190, 235}, 49}, {{42, 194, 150, 0, 0, 0, 72, 63, 94, 100, 22, 138, 41, 102, 101, 9}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 198, 91, 200, 86, 146, 188, 62}, 49}, {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 49}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 124, 22, 42, 90, 160, 97}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 182}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 184, 56, 24, 141, 240, 38, 60, 6}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 138, 23, 104, 39, 57, 97}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 100, 208}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 97}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 201, 84, 139, 96, 136, 232, 247}, 179}, {{205, 96, 0, 0, 0, 0, 0, 54, 239, 255, 10, 120, 190, 26, 120, 121}, 179}, {{205, 96, 0, 0, 0, 142, 191, 156, 47, 61, 78, 195, 55, 158, 119, 162}, 179}, {{205, 96, 0, 0, 0, 223, 18, 100, 172, 137, 202, 77, 65, 36, 151, 211}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 155, 75, 48, 23, 212, 113}, 179}, {{205, 96, 0, 0, 0, 0, 158, 154, 61, 179, 79, 69, 132, 0, 146, 167}, 179}, {{205, 96, 0, 0, 0, 0, 125, 6, 237, 207, 136, 0, 137, 113, 229, 250}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 48, 235, 11}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 179}, {{205, 96, 0, 190, 240, 177, 238, 94, 119, 76, 13, 172, 16, 53, 92, 243}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 218}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 230, 54}, 179}, {{205, 96, 0, 0, 0, 253, 68, 173, 119, 64, 39, 183, 57, 172, 132, 224}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 84, 113, 65, 86, 44, 144}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 29, 107}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 176, 248, 242, 46, 52, 209, 23}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 27, 62, 76, 34, 62, 46}, 179}, {{205, 96, 0, 0, 95, 182, 87, 13, 30, 252, 242, 56, 186, 154, 30, 69}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 105, 124, 122, 167, 69, 143}, 179}, {{205, 96, 0, 0, 0, 0, 0, 169, 175, 234, 86, 62, 56, 205, 154, 134}, 179}, {{205, 96, 184, 183, 178, 88, 37, 22, 198, 230, 249, 15, 142, 227, 99, 238}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 56, 233, 68, 243, 225, 195, 86}, 179}, {{205, 96, 76, 254, 157, 6, 192, 117, 36, 34, 102, 6, 97, 116, 142, 97}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 81}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 171}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 76, 207}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 226, 49, 240, 125, 255, 40, 20}, 179}, {{205, 96, 0, 0, 0, 134, 244, 227, 166, 101, 8, 64, 89, 200, 165, 65}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 232, 15, 81}, 179}, {{205, 96, 0, 0, 0, 138, 215, 174, 100, 107, 19, 239, 139, 6, 208, 12}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 230, 100}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 187, 39, 246, 100, 191, 207, 206}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 134, 226, 110, 17, 196, 80}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 47, 78}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 135, 209, 251, 17, 90, 166, 167}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 166, 1}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 245}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 137, 112, 218, 90, 245, 34}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 64, 156, 119, 124, 60, 155, 25}, 179}, {{205, 96, 0, 77, 167, 197, 1, 139, 190, 194, 197, 145, 154, 216, 148, 67}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 99, 140, 67, 150, 4, 85, 234, 61}, 179}, {{205, 96, 0, 0, 0, 0, 0, 165, 20, 140, 101, 184, 163, 15, 242, 7}, 179}, {{205, 96, 0, 235, 107, 35, 85, 119, 6, 116, 51, 40, 165, 170, 62, 22}, 179}, {{205, 96, 37, 83, 170, 36, 148, 95, 110, 210, 10, 217, 38, 160, 93, 149}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 32, 238, 15, 129, 156, 151, 158, 23, 182, 197, 109, 216, 66}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 24, 162, 72, 243, 241, 48, 214}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 199, 17, 236, 88}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 161, 146}, 179}, {{205, 96, 0, 0, 0, 20, 54, 211, 93, 237, 56, 45, 190, 112, 40, 193}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 146, 122, 184, 78, 186, 129, 152, 24}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 192, 51, 212, 165, 74, 229, 54, 251}, 179}, {{205, 96, 0, 157, 235, 149, 77, 177, 130, 166, 150, 20, 51, 82, 163, 76}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 204, 75, 107}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 31, 84, 247, 36, 106, 232}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 2, 52, 218, 190, 243, 80}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 36, 83, 247, 31, 202, 248, 185, 121}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 121, 59, 215, 186, 36, 177, 139}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 92, 57, 37, 165, 205, 64, 157, 19}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 190, 255, 202, 145}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 230, 133}, 179}, {{205, 96, 0, 0, 0, 0, 0, 227, 136, 225, 97, 163, 174, 253, 66, 192}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 64, 23, 78}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 229, 113, 63, 186, 14, 197, 243}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 71, 127, 22, 71, 200, 3, 83}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 114, 193, 91, 186, 229, 124}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 136, 88, 0}, 179}, {{205, 96, 0, 0, 172, 48, 98, 75, 212, 229, 46, 97, 139, 42, 100, 22}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 172, 44, 121, 9}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 108}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 48, 166, 83, 183, 61, 162, 96, 177}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 191}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{205, 96, 155, 175, 183, 50, 174, 102, 61, 110, 73, 92, 195, 135, 112, 115}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 161}, 179}, {{205, 96, 0, 22, 110, 98, 221, 237, 248, 106, 15, 114, 89, 219, 141, 13}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 208, 35, 238, 37, 174, 236}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 159, 176, 31, 39, 17, 18, 162}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 91, 246, 155, 180, 131, 87, 152, 22}, 179}, {{205, 96, 0, 0, 0, 78, 85, 94, 67, 10, 23, 205, 122, 11, 224, 229}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 57, 124}, 179}, {{205, 96, 0, 0, 0, 238, 191, 105, 154, 225, 42, 37, 172, 167, 80, 32}, 179}, {{205, 96, 0, 0, 0, 0, 151, 59, 194, 103, 175, 159, 65, 46, 75, 240}, 179}, {{205, 96, 0, 0, 0, 0, 0, 0, 0, 86, 59, 86, 12, 100, 117, 184}, 179}, {{205, 96, 0, 0, 0, 65, 89, 225, 221, 242, 122, 32, 213, 185, 128, 51}, 179}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 76}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 226}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 184}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 75, 229}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 125}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 70, 118}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 188}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 74}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 111}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 4, 243}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 254, 216}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 163, 225}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 115}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 163}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 14, 46}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 96}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 88}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 48}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 191}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 21, 78}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 242, 49}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 44}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 222}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 45}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 220}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 133}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 69}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 160, 95}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 118}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 198, 149}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 211}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 174}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 199}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 67}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 3, 61}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 103}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 73, 189}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 28}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 119, 43}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 135}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 119}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 116}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 166}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 115, 63}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 108, 96}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 6}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 5}, 112}, {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 112}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 122, 62}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 153, 231, 168}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 43, 179, 118}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 203, 166}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 168, 195}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 65, 74, 174}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 173, 226, 9}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 4}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 192, 196, 35}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 82, 45}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 127, 224}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 174}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 68, 131}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 136}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 215, 208, 230}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 54, 105, 126}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 202, 58, 234}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 185, 177}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 184, 228, 238}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 183, 90, 82}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 63}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 187, 51, 207}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 187, 99, 235}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 8, 82, 46}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 32}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 219, 193}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 33}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 146, 40, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 80}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 90}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 250, 69, 196}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 177}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 171, 215, 138}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 73, 110, 178}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 170}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 142, 222, 247}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 5, 148}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 92, 224, 71}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 242, 1, 162}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 190, 58, 89}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 203, 151}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 223, 132}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 6, 236, 129}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 22, 57}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 104, 15, 149}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 111, 230}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 15, 255}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 191}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 172, 179, 126}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 167, 66, 241}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 76, 193, 66}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 204, 186}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 37, 86, 223}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 255, 242, 228}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 121, 232, 221}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 84}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 112, 31}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 148, 183}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 119, 132, 246}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 12, 199}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 122, 95, 212}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 241}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 14, 68, 140}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 161, 248}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 167}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 193}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 1}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 82, 142, 221}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 241, 81, 184}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 117, 58, 8}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 71}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 25}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 149, 210}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 169}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 93}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 232, 140}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 32}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 47, 237}, 31}, {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 217, 27}, 31}, {{120, 4, 235, 112, 34, 128, 0, 227, 179, 152, 240, 152, 197, 92, 129, 160}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 205, 247, 196}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 42, 170, 106}, 111}, {{120, 4, 235, 112, 34, 128, 0, 77, 188, 147, 102, 119, 114, 28, 170, 167}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 131, 65, 221, 72, 158, 226, 200, 215}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 47, 190, 101, 159, 90, 214}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 181, 69, 17, 49, 21, 3, 249, 113}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 217, 31, 195, 205, 28, 180, 10, 152}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 145, 24, 247}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 85, 203, 220, 188, 244, 42, 102}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 148, 238, 233, 187, 38, 54}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 191, 1, 215}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 238, 209, 89, 144, 135, 166, 164}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 118, 51, 109, 171, 129, 213, 97, 37, 79}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 111}, {{120, 4, 235, 112, 34, 128, 0, 144, 100, 167, 173, 133, 10, 102, 72, 154}, 111}, {{120, 4, 235, 112, 34, 128, 110, 221, 66, 96, 42, 165, 13, 147, 126, 214}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 21, 40, 33, 26, 199}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 254, 49, 239, 21, 52}, 111}, {{120, 4, 235, 112, 34, 128, 240, 15, 129, 54, 117, 154, 68, 60, 161, 183}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 232, 165, 248, 194, 247, 21, 248, 68}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 52, 43, 126, 107, 117, 236, 94, 10, 244}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 78, 172, 33}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 245, 130, 162, 238, 88}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 111, 16, 123, 85, 92, 185}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 103, 7, 224}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 57, 100, 51, 188, 13}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 234, 101, 131, 81}, 111}, {{120, 4, 235, 112, 34, 128, 223, 214, 82, 107, 255, 215, 129, 11, 152, 50}, 111}, {{120, 4, 235, 112, 34, 128, 164, 53, 164, 176, 4, 83, 144, 130, 119, 7}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 253, 251, 198}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 72, 51}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 127, 246, 247, 117, 121, 137, 219, 174}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 59, 103, 121, 130, 211}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 232, 54, 55, 42, 79, 254, 25}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 248, 185, 206}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 153, 49, 52, 40}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 4, 184, 241, 27, 26}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 50, 138, 209, 68, 233}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 151, 95, 52}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 211, 221, 28, 128, 152, 254, 26}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 1, 120, 177, 56, 238, 239, 78}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 224, 236, 55, 31, 160, 211}, 111}, {{120, 4, 235, 112, 34, 128, 210, 136, 24, 155, 240, 187, 121, 179, 171, 137}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 136, 194, 42, 53}, 111}, {{120, 4, 235, 112, 34, 128, 0, 240, 34, 213, 55, 83, 168, 165, 96, 174}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 89, 185}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 35, 175}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 165, 111, 29, 150, 64, 178}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 77, 5, 243, 15, 53, 185, 84}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 111, 224, 58, 212, 228, 98, 159}, 111}, {{120, 4, 235, 112, 34, 128, 110, 251, 160, 6, 190, 4, 239, 76, 26, 35}, 111}, {{120, 4, 235, 112, 34, 128, 204, 138, 114, 144, 10, 185, 1, 86, 232, 229}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 209, 245, 148, 127}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 205, 46, 64, 251}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 147, 219, 27}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 238, 100, 183}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 117, 6, 38, 64, 189, 234, 7}, 111}, {{120, 4, 235, 112, 34, 128, 19, 99, 189, 138, 60, 159, 86, 178, 122, 46}, 111}, {{120, 4, 235, 112, 34, 128, 0, 51, 142, 107, 234, 195, 105, 178, 156, 153}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 31, 71, 33, 57, 38, 248, 148, 218}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 19, 60, 243, 23, 97}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 132, 44, 8, 226, 163, 142, 91}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 110, 31, 67, 9, 253, 67, 119}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 195, 43, 133, 159}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 162, 120}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 111}, {{120, 4, 235, 112, 34, 128, 174, 170, 251, 74, 236, 136, 194, 23, 97, 40}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 230, 119, 131, 241, 8, 251, 191}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 19, 151, 39, 16, 226}, 111}, {{120, 4, 235, 112, 34, 128, 0, 33, 247, 149, 84, 221, 250, 34, 95, 205}, 111}, {{120, 4, 235, 112, 34, 128, 188, 195, 27, 116, 250, 158, 213, 124, 209, 168}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 229, 124, 177, 2, 58, 86}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{120, 4, 235, 112, 34, 128, 0, 107, 186, 84, 161, 180, 20, 181, 252, 201}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 31, 251, 177}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 183, 211}, 111}, {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 111}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 98, 26}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 237, 206, 89}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 40, 189, 40}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 177}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 24, 23, 20}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 192}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 110, 117, 133, 242, 25}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 239, 229, 93}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 4, 173, 136}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 68, 232, 100, 187}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 117}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 42, 225, 122, 169}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 223, 185, 18, 219}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 105, 90, 212, 75}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 86, 85, 108, 26}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 103, 192}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 251, 33, 22, 63}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 166, 120}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 71, 181, 192}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 218, 252, 56, 242}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 1, 184}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 135}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 66, 101}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 49, 203, 47, 79}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 142, 72, 92}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 43}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 239, 201, 86, 146}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 8, 255, 110, 103}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 52, 99}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 226, 109}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 76, 212}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 96, 7, 133}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 169, 243, 167, 229}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 42, 17, 251, 219}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 83}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 164, 186, 8, 149}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 96}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 129, 220}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 45, 205, 77}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 70}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 171}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 151, 221, 71, 84}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 239, 150}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 104, 88, 184}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 81}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 160, 121}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 125, 55, 222}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 92, 28}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 127, 49, 135}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 56, 167}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 19, 209, 119, 215, 143}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 66, 219, 140, 133}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 114, 58}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 175, 140}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 239, 212, 60}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 7, 15, 38}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 174}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 98, 133, 190}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 14, 29, 71, 65}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 99, 228, 243}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 68}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 77, 179, 94, 255, 95}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 248}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 29}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 72, 233}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 22, 21, 8}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 148, 26}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 197, 201, 245, 2}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 56}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 113}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 205}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 92}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 177, 23, 36, 236}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 195, 226}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 72, 11, 196}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 131, 18, 33}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 141, 217, 250, 202, 36}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 223}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 50, 62, 90, 181}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 54, 37}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 102}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 198, 60, 237, 167}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 231, 155, 112, 239}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 182}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 19, 39}, 65}, {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 113, 111}, 65}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 2, 232, 229, 20}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 227, 223, 194, 249}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 125}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 218, 187, 159, 225}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 192, 171}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 82, 214, 146, 221, 245}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 249, 113, 228, 24}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 2, 24, 154}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 84, 255, 139, 1, 200}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 84, 180}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 166, 194, 153, 253}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 80, 80, 142, 70}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 101, 146, 36, 136}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 31, 69, 80, 87, 27}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 122, 162, 6, 3}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 130, 154, 102}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 175}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 36, 101, 11}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 146}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 125, 196, 155}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 158}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 55}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 255, 213, 226}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 22, 42, 62, 7}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 230, 193, 31}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 234, 60, 121, 0, 150}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 111, 165, 16, 85, 36, 148}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 254, 151, 156, 195, 246}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 126, 234, 116, 243}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 181, 34, 26, 32}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 156, 200}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 186, 60, 119, 120, 192}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 9, 224, 20}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 183}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 196, 239, 157, 12, 139}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 87, 13}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 37, 26, 96, 188}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 159, 56, 117, 103, 84}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 180, 175}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 59}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 173, 35, 227, 236}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 240, 195}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 33, 244}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 74}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 46, 78, 227}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 12, 194, 243, 33}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 250, 73, 20}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 3, 216, 145, 147, 211}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 52}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 100, 122, 9, 155, 14}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 188, 41, 43, 142, 129, 7}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 173, 34}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 80, 237}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 4, 164}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 248, 220, 76, 19}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 88, 6, 233, 157}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 43, 74, 160}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 253, 252}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 52, 79, 161, 250}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 212, 96}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 176, 103}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 85, 190, 90, 144, 175}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 143}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 52, 161}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 66}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 152, 152, 191, 176}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 37}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 36}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 120, 124}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 54}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 144, 122}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 254, 76, 136, 29, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 85, 15, 90}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 17, 44, 128, 8, 160}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 205}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 12, 9}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 222}, {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 143, 169, 39, 89, 118}, 222}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 190, 58, 235, 167, 215, 191}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 167, 37, 14, 59, 183, 193, 125}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 156, 77}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 191, 178, 164}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 249}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 47, 98, 71}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 185, 133, 158, 172}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 137, 187, 52, 247, 104, 129, 154, 131}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 74, 176, 16, 150, 59, 225}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 230}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 37, 121}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 222, 141}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 94}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 103, 116, 176}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 6, 168, 160, 192, 48, 31, 81}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 217, 194, 245, 141, 129, 96}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 89, 175}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 88, 100, 253, 156, 27, 198, 218}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 81, 224, 100}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 63, 246, 73, 215, 108, 62, 6}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 40, 185}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 52, 68, 83, 79, 78, 82, 235}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 31, 189, 18, 183, 158, 61}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 133, 20}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 132, 127, 58, 123, 20}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 144, 79, 91, 56, 217}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 200, 1, 24, 225}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 217, 92, 222}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 115, 165, 181, 169}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 92, 72, 142, 5}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 49, 23, 234, 235, 186, 100, 202}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 121, 204, 7}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 83, 231, 82, 6, 183, 85, 195}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 147, 43, 156}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 151, 211, 209}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 39, 174, 94, 176}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 156}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 74, 11, 186, 114}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 6, 74, 166, 206, 62, 24, 77}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 143, 124, 90, 179}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 83, 8, 155, 98, 88}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 128, 131, 9}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 44, 118, 104, 135, 154, 142, 205, 228}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 162, 9}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 76, 23, 130, 185, 248, 7, 54, 65}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 235, 192, 49, 100, 188, 218, 22, 164}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 59, 69, 209, 16, 9}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 62, 163, 171, 75, 232, 186, 113, 245}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 7, 42}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 26, 207, 73}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 130, 159, 213, 12, 178, 180, 183}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 160}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 205, 104, 252, 212, 238}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 136, 189, 115, 159, 149, 42, 27, 38}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 94}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 163, 244}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 111, 205, 110}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 132, 90, 108}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 185, 202, 143, 19, 6, 122}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 1, 165, 193, 187}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 95, 172, 5, 193, 51, 39}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 136}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 115, 171, 174, 138, 78, 98}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 102, 76, 206, 153, 241, 173, 251, 246}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 9, 248, 254, 120, 27, 159}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 159, 194, 71, 162, 178, 193}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 230, 198}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 221, 118, 146, 202}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 203, 219, 81, 62}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 220, 28, 176, 176, 157, 158, 191}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 217, 26, 38, 30}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 120, 251, 76, 87, 243, 202, 66}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 41, 81}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 141, 106, 168, 58, 209, 177}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 46, 227, 213, 218, 85, 246, 187, 126}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 81, 42, 205}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 193, 128, 29, 189, 128, 197, 253, 124}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 221, 118, 26, 10, 117, 34, 81, 164}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 64, 120, 141, 126, 236, 106}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 87, 83, 100, 222}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 166, 169, 201, 116, 60, 168, 205, 58}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 218, 46, 86, 44, 85, 152, 13, 149}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 123, 175, 229, 85}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 228, 108, 40}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 196, 157, 24, 71, 123, 240, 96, 192}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 98, 146, 94}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 223, 186, 126, 200, 198, 36, 158}, 4}, {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 191, 145, 106, 110, 6, 102}, 4}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 22, 97, 199, 105}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 9, 22}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 180}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 43, 206, 219, 13, 189}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 196, 152, 134, 84, 246}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 225}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 196, 52, 72, 13, 198}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 99, 147, 74, 98, 111}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 75, 192, 212, 39, 116, 140, 47}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 88, 122, 243, 96, 22, 195}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 219}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 225, 59}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 136, 28, 250, 253, 51, 171}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 118, 35, 225, 152, 184}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 198, 224, 203}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 182, 50, 106, 31, 117, 157}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 109}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 216, 75, 246}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 30, 244, 49, 136, 227, 155, 188}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 100, 148}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 224, 158}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 167, 75, 23, 31}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 226, 201, 229}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 93, 23, 32, 213, 52, 74, 26}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 11, 224, 249, 195, 115, 20}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 168, 253, 32, 165}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 180}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 7}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 206, 224, 145, 219}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 154, 157, 52}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 18, 79, 168}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 188, 96, 165, 128, 224}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 76}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 27, 184}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 230, 42, 213, 169, 199, 209}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 3, 181}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 123}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 84, 166, 246, 107}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 151, 28}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 153, 29, 67, 112}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 236, 15}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 106, 141, 202, 22, 197, 219}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 137, 120, 9}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 147, 232, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 130, 77, 191}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 226}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 23, 15, 209, 234}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 133, 98, 198, 225, 175, 22}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 191, 148, 224, 120, 53, 126}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 201, 183, 147, 130, 204, 95, 123}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 63, 108, 177, 143}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 2, 11, 104, 47, 83, 26, 12}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 103, 42, 187, 175, 190}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 93, 153, 65, 218}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 159, 14, 116}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 27, 188, 201, 15}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 189, 81, 192, 156}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 94, 191, 33, 164, 63}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 31, 26, 70, 64}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 92, 182, 135, 123, 129, 84}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 233, 135}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 175, 219, 1, 203}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 211, 224, 39, 42, 110, 29}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 209, 87, 208, 190, 8}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 18, 101, 75}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 36, 106, 8, 202, 158, 82, 128}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 63, 177, 5}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 237, 214}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 254, 38, 101}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 32, 88, 46, 40, 190, 162}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 16, 57, 154, 26, 22}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 43, 68, 12}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 30, 128, 61, 205, 220, 96}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 166, 102, 96}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 246, 149, 249, 22, 216}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 141, 222}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 88, 27, 147, 17, 111, 114}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 175, 73, 140}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 18, 102, 24, 41, 18}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 246, 201}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 244, 125}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 48, 112, 131, 227}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 255, 178, 205, 182, 248}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 36, 181}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 36, 182, 124}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 76, 19, 35, 200}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 206, 197}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 122}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 231, 176}, 67}, {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 236, 103, 111}, 67}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 12}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 22}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 224}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 46}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 217}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 201}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 16}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 153}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 222}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 103}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 50}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 212, 129}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 136}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 238}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 51}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 95}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 25, 64}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 116}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 238}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 8}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 73, 232}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 184}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 140}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 122}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 86, 165}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 142}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 104}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 114}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 60}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 75, 30}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 198}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 35}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 218, 164}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 39}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 8}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 5}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 22}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 64}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 51}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 71, 178}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 106, 156}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 98}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 172}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 117, 223}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 110, 61}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 31}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 131}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 26}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 104, 132}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 47}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 189, 163}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 56}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 210, 230}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 34, 211}, 197}, {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 197}, {{63, 235, 20, 0, 0, 0, 138, 151, 158, 131, 233, 159, 10, 248, 169, 43}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 18}, 121}, {{63, 235, 20, 0, 98, 72, 213, 72, 228, 129, 22, 26, 203, 128, 183, 254}, 121}, {{63, 235, 20, 0, 136, 241, 198, 249, 158, 109, 102, 91, 153, 118, 2, 112}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 82, 156, 225, 5, 222, 95}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 148, 111, 112, 88, 113, 135, 74, 100}, 121}, {{63, 235, 20, 0, 0, 0, 171, 14, 21, 201, 10, 108, 241, 51, 61, 178}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 138}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 233, 9, 137, 70, 206}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 49, 212, 180, 30, 207, 219, 149}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 4, 76, 54, 36, 244, 205, 35, 41}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 81, 220, 73, 118, 227, 71}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 48, 140, 115, 221, 222, 58, 62}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 197}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 11, 156, 93, 81, 57, 15}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 92, 79, 60}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 195, 97, 43, 89, 54, 181, 202, 82}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 228, 64, 39, 111, 236, 126, 33}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 90, 129, 47, 226, 194, 87}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 133, 41, 115, 176, 31, 224, 18, 237}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 40}, 121}, {{63, 235, 20, 0, 0, 34, 181, 141, 20, 228, 188, 132, 0, 217, 98, 84}, 121}, {{63, 235, 20, 0, 163, 30, 39, 231, 35, 183, 179, 65, 9, 218, 156, 184}, 121}, {{63, 235, 20, 0, 0, 0, 239, 157, 34, 237, 211, 137, 175, 233, 185, 53}, 121}, {{63, 235, 20, 0, 0, 0, 52, 2, 0, 73, 67, 56, 202, 147, 90, 120}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 19, 108, 123, 88, 194, 164, 72}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 39, 16, 77, 125, 1, 9}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 233, 73, 241, 245, 129}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 64, 87, 15}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 204, 31}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 187, 162, 107, 241, 127, 68, 119}, 121}, {{63, 235, 20, 0, 77, 32, 119, 251, 217, 82, 243, 49, 4, 56, 246, 16}, 121}, {{63, 235, 20, 0, 0, 0, 0, 130, 188, 198, 113, 140, 191, 173, 134, 143}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 121}, {{63, 235, 20, 0, 0, 0, 0, 110, 66, 119, 248, 56, 71, 43, 23, 105}, 121}, {{63, 235, 20, 0, 0, 0, 33, 238, 177, 32, 248, 18, 75, 144, 74, 87}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 9, 41}, 121}, {{63, 235, 20, 0, 0, 113, 77, 238, 28, 187, 61, 235, 219, 237, 71, 164}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 186, 215, 206, 221, 115, 170, 85, 201, 170, 44, 251, 82}, 121}, {{63, 235, 20, 0, 0, 6, 236, 151, 0, 68, 56, 220, 111, 135, 134, 57}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 121, 96, 94, 14, 18, 74, 249, 127}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 212, 114, 10, 135, 143, 155, 215}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 163, 144, 119, 69, 196, 207}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 194, 32}, 121}, {{63, 235, 20, 0, 0, 52, 107, 195, 84, 126, 116, 232, 15, 7, 157, 144}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 195, 20, 15, 239, 98, 108, 24, 124, 11}, 121}, {{63, 235, 20, 0, 146, 186, 190, 112, 36, 195, 200, 90, 12, 154, 138, 5}, 121}, {{63, 235, 20, 0, 0, 0, 0, 108, 40, 122, 19, 101, 50, 158, 20, 203}, 121}, {{63, 235, 20, 0, 0, 167, 170, 127, 38, 167, 250, 211, 6, 123, 148, 107}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 19, 129, 8, 114, 150, 233, 113}, 121}, {{63, 235, 20, 0, 0, 0, 0, 152, 38, 65, 166, 75, 250, 252, 115, 16}, 121}, {{63, 235, 20, 0, 0, 0, 90, 100, 254, 45, 207, 119, 242, 35, 161, 24}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 59, 170, 166, 130, 71, 238, 254, 219}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 7, 233, 32, 67, 14, 196, 146, 194}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 235, 34}, 121}, {{63, 235, 20, 0, 13, 113, 254, 49, 4, 55, 113, 21, 60, 248, 133, 61}, 121}, {{63, 235, 20, 0, 212, 167, 150, 240, 253, 22, 6, 72, 110, 75, 89, 237}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 43, 44}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 230, 197, 52, 66, 122, 120}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 230, 42, 136, 42, 215, 65, 254, 186}, 121}, {{63, 235, 20, 0, 0, 252, 20, 235, 64, 84, 133, 88, 51, 178, 167, 144}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 236, 159, 65, 222, 245, 163}, 121}, {{63, 235, 20, 0, 0, 0, 200, 128, 179, 104, 106, 128, 89, 59, 149, 52}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 53, 215, 84, 77, 134}, 121}, {{63, 235, 20, 0, 189, 98, 40, 240, 18, 131, 13, 224, 228, 108, 106, 67}, 121}, {{63, 235, 20, 26, 79, 246, 34, 186, 163, 160, 244, 255, 93, 241, 100, 140}, 121}, {{63, 235, 20, 0, 0, 0, 211, 178, 135, 106, 58, 235, 254, 152, 32, 17}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 111, 139, 204, 0, 95, 89}, 121}, {{63, 235, 20, 0, 0, 0, 0, 229, 234, 119, 253, 60, 59, 100, 20, 36}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 190, 170, 46, 164, 143, 49}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 145, 197, 127, 138, 47, 191, 48, 159}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{63, 235, 20, 0, 236, 148, 0, 167, 80, 86, 12, 43, 105, 75, 218, 122}, 121}, {{63, 235, 20, 0, 0, 0, 240, 163, 91, 59, 90, 216, 70, 145, 65, 90}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 187, 21, 168, 158, 152, 3, 41}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 93, 122, 52, 243, 54, 91, 90, 200}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 12, 139, 75, 113, 110, 88, 120, 238}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 225, 248, 142}, 121}, {{63, 235, 20, 0, 0, 0, 152, 163, 46, 203, 182, 37, 108, 23, 201, 53}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 85, 215, 74}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 121}, {{63, 235, 20, 0, 0, 0, 131, 122, 193, 231, 234, 97, 36, 85, 38, 95}, 121}, {{63, 235, 20, 0, 37, 92, 34, 136, 146, 170, 152, 105, 87, 201, 213, 44}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 205, 214, 181}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 93, 149, 94, 85, 143, 24, 41}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 190}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 73, 179, 255, 62, 70}, 121}, {{63, 235, 20, 0, 0, 101, 249, 79, 41, 26, 220, 60, 46, 101, 176, 54}, 121}, {{63, 235, 20, 0, 0, 0, 0, 0, 0, 149, 144, 176, 28, 3, 55, 143}, 121}, {{128, 0, 0, 0, 64, 247, 91, 122, 178, 14, 147, 254, 76, 182, 78, 229}, 218}, {{128, 0, 0, 0, 168, 167, 181, 99, 55, 242, 182, 83, 247, 96, 140, 212}, 218}, {{128, 0, 0, 0, 168, 235, 255, 78, 12, 174, 152, 33, 123, 75, 110, 152}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 116, 31, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 170, 57, 253, 17, 29, 46, 219, 156, 149}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 97, 64, 190, 153, 40, 10, 113, 243}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 196, 15, 164, 160}, 218}, {{128, 0, 0, 0, 0, 26, 216, 166, 245, 64, 156, 130, 219, 80, 5, 135}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 166, 20, 180, 112, 120}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 64, 167, 42, 254, 244, 167, 74, 244}, 218}, {{128, 145, 64, 195, 55, 137, 74, 120, 252, 150, 199, 239, 163, 16, 206, 19}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 139}, 218}, {{128, 0, 38, 69, 162, 6, 78, 147, 83, 75, 18, 17, 218, 109, 239, 160}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 120, 160, 231, 123}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 236}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 126, 139, 164}, 218}, {{128, 0, 0, 192, 183, 201, 66, 169, 0, 154, 95, 90, 33, 84, 62, 255}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 74, 237, 42, 206, 2, 62, 26}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 121, 141, 104, 121}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 245, 6, 204}, 218}, {{128, 0, 0, 0, 0, 156, 129, 221, 145, 168, 65, 244, 203, 150, 217, 247}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 151}, 218}, {{128, 0, 0, 0, 84, 201, 192, 19, 221, 208, 235, 14, 48, 130, 29, 173}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 84, 160, 18, 174}, 218}, {{128, 0, 0, 0, 0, 191, 250, 56, 231, 251, 235, 170, 85, 92, 220, 179}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 155, 202, 216}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 19, 201, 84, 34, 16, 198, 92}, 218}, {{128, 0, 0, 0, 0, 0, 26, 60, 239, 105, 126, 48, 229, 39, 161, 159}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 50, 49, 106, 250, 20, 2, 239}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 122, 154, 200, 38}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 46, 110, 71, 96, 2, 214, 185, 61, 26, 206}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 138}, 218}, {{128, 0, 0, 16, 61, 147, 236, 12, 161, 28, 231, 139, 113, 126, 235, 146}, 218}, {{128, 0, 246, 97, 30, 14, 106, 172, 194, 222, 102, 251, 6, 73, 85, 79}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 15, 230}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 226, 14, 247, 180, 202, 223, 88, 50, 34, 199, 187, 233}, 218}, {{128, 0, 0, 174, 147, 154, 102, 193, 210, 243, 23, 242, 210, 213, 170, 226}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 42, 250, 16, 100, 159, 30, 76}, 218}, {{128, 0, 0, 0, 0, 239, 197, 142, 18, 124, 194, 32, 108, 190, 137, 213}, 218}, {{128, 0, 0, 0, 0, 20, 255, 46, 43, 83, 116, 195, 118, 238, 222, 183}, 218}, {{128, 0, 0, 0, 197, 171, 143, 223, 40, 66, 234, 22, 237, 225, 245, 50}, 218}, {{128, 0, 210, 240, 154, 107, 179, 149, 18, 115, 72, 47, 127, 121, 156, 7}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 69, 139, 205}, 218}, {{128, 0, 0, 0, 145, 26, 151, 222, 63, 95, 67, 116, 198, 216, 240, 193}, 218}, {{128, 0, 0, 0, 0, 0, 0, 137, 179, 232, 6, 11, 27, 50, 245, 230}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 203, 105}, 218}, {{128, 198, 55, 92, 45, 108, 56, 6, 243, 87, 96, 52, 117, 147, 177, 254}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 93, 172}, 218}, {{128, 0, 0, 0, 0, 80, 5, 208, 110, 136, 246, 70, 130, 227, 204, 68}, 218}, {{128, 0, 0, 0, 139, 189, 9, 107, 111, 77, 210, 6, 86, 17, 55, 2}, 218}, {{128, 0, 0, 0, 0, 82, 169, 98, 243, 41, 73, 23, 138, 138, 57, 243}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 96}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 76, 83}, 218}, {{128, 0, 0, 158, 245, 161, 116, 193, 109, 210, 233, 207, 204, 63, 89, 28}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 208, 179, 79}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 231, 0, 224, 219}, 218}, {{128, 0, 0, 0, 34, 251, 243, 199, 86, 226, 22, 170, 198, 179, 132, 240}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 33, 116}, 218}, {{128, 0, 0, 0, 0, 0, 87, 127, 74, 43, 122, 142, 157, 236, 128, 186}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 195, 163, 165}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 236, 253, 7, 252, 95, 156, 95}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 70, 104, 173, 192, 13, 79, 94, 171, 243}, 218}, {{128, 0, 0, 0, 0, 173, 18, 1, 71, 233, 223, 135, 189, 89, 2, 114}, 218}, {{128, 0, 0, 159, 211, 64, 82, 253, 234, 130, 238, 108, 59, 154, 153, 118}, 218}, {{128, 0, 0, 0, 0, 0, 0, 54, 75, 36, 180, 138, 103, 74, 20, 220}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 102}, 218}, {{128, 0, 0, 0, 245, 255, 56, 162, 189, 56, 32, 31, 121, 218, 95, 131}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 255, 93, 188, 116, 1, 89, 35}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 51}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 44, 240, 185, 97, 230}, 218}, {{128, 0, 0, 0, 0, 106, 202, 213, 159, 100, 202, 78, 185, 97, 28, 128}, 218}, {{128, 63, 144, 191, 143, 190, 164, 129, 240, 81, 145, 143, 61, 148, 32, 104}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 209, 14, 24, 119, 250, 211, 242, 135, 201, 91}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 247, 110, 211, 15, 154}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 248, 205, 222, 86}, 218}, {{128, 0, 0, 0, 90, 104, 126, 198, 113, 255, 56, 27, 34, 75, 45, 93}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 45, 123, 2, 47, 137, 71, 50}, 218}, {{128, 0, 0, 0, 0, 20, 13, 60, 55, 102, 47, 115, 215, 170, 71, 1}, 218}, {{128, 0, 0, 0, 0, 0, 0, 197, 254, 124, 252, 11, 233, 142, 242, 73}, 218}, {{128, 0, 0, 0, 23, 190, 125, 92, 194, 68, 48, 240, 52, 119, 62, 126}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 147, 236, 176, 28}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 109, 186, 169}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 30, 89, 252, 226, 45, 79, 240}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 72, 239, 1, 46, 177, 119, 12, 129}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 247, 12, 46, 128, 29, 91, 33, 49}, 218}, {{128, 247, 4, 188, 200, 68, 249, 253, 9, 175, 247, 220, 105, 179, 136, 48}, 218}, {{128, 0, 235, 104, 234, 29, 49, 128, 221, 222, 197, 121, 35, 47, 88, 19}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 133, 76, 248, 191, 198, 96, 76, 216}, 218}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 61, 130, 120, 76, 223, 204, 188, 187}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 23, 241, 184, 203}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 180}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 142, 114, 116, 234}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 78, 148, 74, 156, 19, 146, 124}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 46, 65, 28}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 115, 237, 0, 18}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 111, 160, 168, 49, 51, 104, 14}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 70, 124, 69, 65}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 171, 223, 44}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 16, 108, 165, 41, 117, 89, 112, 102, 178, 79}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 136, 83, 75, 121, 85, 56, 27, 52}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 138, 75, 219, 238}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 12, 62, 158, 97}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 114, 9, 43}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 6, 63, 143, 241}, 140}, {{15, 159, 42, 167, 76, 0, 70, 79, 194, 218, 222, 27, 90, 229, 202, 6}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 253, 1, 7, 75, 96, 66}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 29, 132, 190, 153, 129, 245}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 77, 126, 76}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 192}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 136}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 94, 148, 96, 43, 8}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 96, 16, 176, 187, 214, 19}, 140}, {{15, 159, 42, 167, 76, 0, 183, 9, 9, 176, 154, 1, 131, 55, 199, 104}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 233, 145, 216, 241, 61, 132}, 140}, {{15, 159, 42, 167, 76, 0, 0, 203, 96, 154, 64, 80, 65, 61, 20, 156}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 252, 63, 131, 45, 99, 113}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 228, 247, 218, 195, 195}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 11, 220, 100}, 140}, {{15, 159, 42, 167, 76, 0, 29, 5, 66, 137, 139, 196, 7, 248, 78, 53}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 133, 115, 186, 213, 52}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 48, 2, 13, 140, 50}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 62, 198, 72}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 244, 71, 123, 43, 158, 51}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 187}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 163, 90, 58, 8}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 114, 170, 75}, 140}, {{15, 159, 42, 167, 76, 0, 0, 189, 77, 151, 108, 200, 173, 184, 169, 135}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 221, 229, 137, 22, 101, 199, 190}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 209, 252, 108, 236, 168, 140}, 140}, {{15, 159, 42, 167, 76, 0, 0, 34, 209, 246, 254, 82, 10, 113, 231, 19}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 45, 132, 183, 98}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 126, 53, 212, 157, 90}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 212, 166, 50, 25, 94, 78, 87, 88, 92, 74}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 112}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 111, 51, 79, 41, 162, 100, 27, 3}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 185, 200, 39, 87, 128, 83, 198}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 248, 183, 145, 120, 52, 200, 24}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 140}, {{15, 159, 42, 167, 76, 0, 140, 192, 223, 9, 134, 28, 65, 140, 131, 6}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 53, 6, 203, 173, 67}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 7, 241, 132, 111, 147, 202, 98, 68}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 246, 125, 15}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 62}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 213, 74, 172, 129, 90, 48, 136, 150}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 227, 110, 140, 77, 229, 12, 64}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 189, 236, 114, 161, 111}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 25, 217, 229, 127, 29, 89, 70, 189}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 48}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 152, 5, 120}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 237}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 241, 158, 195, 210, 215}, 140}, {{15, 159, 42, 167, 76, 0, 134, 178, 231, 61, 188, 81, 138, 94, 177, 55}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 126, 125, 80, 145, 202, 116, 74, 78}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 125, 72, 202, 129, 100}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 229, 217, 48}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 197, 252, 66, 80, 183, 127, 123, 126}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 106, 94, 168, 130}, 140}, {{15, 159, 42, 167, 76, 0, 239, 23, 40, 102, 17, 240, 103, 161, 120, 147}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 7, 128, 63, 246, 190, 23, 157}, 140}, {{15, 159, 42, 167, 76, 0, 0, 227, 193, 201, 120, 99, 151, 18, 185, 129}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 41}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 86, 195, 115}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 140}, {{15, 159, 42, 167, 76, 0, 0, 148, 147, 227, 115, 18, 118, 182, 40, 48}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 195}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{15, 159, 42, 167, 76, 0, 0, 0, 183, 56, 112, 65, 128, 205, 83, 105}, 140}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 92}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 143, 67}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 173}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 97}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 5}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 155, 67}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 178, 114}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 181}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 253}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 207}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 253, 204}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 66}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 40, 212}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 201}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 106}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 165}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 17}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 155}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 145}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 195, 151}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 79}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 220, 8}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 47}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 55, 83}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 110, 30}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 173, 54}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 252, 175}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 127, 65}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 34}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 11, 108}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 100}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 68}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 45, 241}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 192}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 230, 119}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 199}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 168}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 99}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 7}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 231}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 3, 9}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 170, 110}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 27}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 8}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 182, 249}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 199}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 226, 21}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 98, 226}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 162}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 210, 232}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 160}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 95}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 192, 180}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 44}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 77, 68}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 35}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 148}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 215}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 146}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 32, 139}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 128, 176}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 164, 143}, 193}, {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 57, 95}, 193}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 47, 135}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 126, 228}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 22}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 2, 135, 4}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 201, 121, 147}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 12}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 233, 107, 161}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 66}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 64}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 134, 72, 249}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 187}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 246}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 236, 28}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 206, 124, 219}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 60, 74, 4, 171}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 236, 165, 239}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 130, 74, 6}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 230}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 250, 218, 166}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 210}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 142, 27, 210, 25}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 155, 45}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 36, 162, 221}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 134, 6, 147, 127}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 87}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 165}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 203}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 5, 54, 153, 20}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 90, 237, 32, 200}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 151, 183}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 4, 57}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 19, 7, 16, 42}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 55, 161}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 140, 158, 166}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 178}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 179}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 164, 144, 209}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 77}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 180, 238}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 75, 31}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 9, 155}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 130, 158}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 194, 174}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 238}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 3}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 136, 116, 255}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 94, 155, 126, 132}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 161, 85, 254}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 49, 247}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 62, 218, 244, 229}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 76, 137, 59, 121}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 170, 116, 14}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 59, 28}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 79, 136, 176}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 142, 215}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 52, 252}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 61, 84, 238, 213}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 53, 63, 173}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 35, 20, 150, 2}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 104, 87, 241}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 63, 61, 130, 238}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 76, 121, 39, 210}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 201, 193, 119}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 224, 81, 126, 228}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 203, 217, 182, 206}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 103}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 173, 223}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 201}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 71, 61}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 154, 118, 204, 101}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 224, 48, 65}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 238, 232}, 47}, {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 47}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 61, 13, 183, 120, 26}, 187}, {{238, 238, 96, 0, 0, 203, 67, 48, 85, 109, 196, 35, 156, 0, 172, 232}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 54, 210, 221, 108, 119}, 187}, {{238, 238, 96, 0, 0, 0, 0, 85, 136, 227, 197, 92, 198, 98, 41, 90}, 187}, {{238, 238, 96, 0, 0, 0, 0, 21, 156, 146, 21, 241, 138, 207, 100, 180}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 187}, {{238, 238, 96, 0, 2, 82, 24, 255, 236, 0, 213, 186, 179, 220, 183, 181}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 25, 171, 180, 215, 191, 16, 223}, 187}, {{238, 238, 96, 0, 0, 0, 164, 3, 40, 28, 161, 106, 101, 72, 9, 89}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 183, 103, 163, 88, 64, 165, 126, 147}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 216}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 46, 78, 193, 142, 74}, 187}, {{238, 238, 96, 0, 0, 94, 30, 156, 213, 220, 142, 216, 192, 140, 128, 77}, 187}, {{238, 238, 96, 0, 180, 67, 17, 15, 166, 200, 17, 3, 58, 182, 74, 36}, 187}, {{238, 238, 96, 0, 0, 0, 76, 186, 35, 47, 60, 71, 81, 154, 169, 224}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 187}, {{238, 238, 96, 0, 0, 0, 0, 180, 215, 127, 76, 80, 40, 176, 35, 185}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 158, 121, 122, 233, 31, 20, 242}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 44, 169, 36, 112, 169, 132, 186}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 101, 177, 134, 239, 145, 17}, 187}, {{238, 238, 96, 0, 0, 0, 0, 69, 240, 81, 49, 73, 38, 221, 33, 143}, 187}, {{238, 238, 96, 0, 0, 0, 0, 161, 236, 204, 6, 220, 243, 132, 38, 132}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 180, 164}, 187}, {{238, 238, 96, 0, 0, 0, 0, 186, 237, 66, 161, 188, 4, 193, 134, 138}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 221}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 218}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 169, 126, 74, 54, 14, 215, 173}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 66, 190, 220}, 187}, {{238, 238, 96, 0, 0, 0, 0, 84, 119, 144, 198, 210, 13, 39, 163, 3}, 187}, {{238, 238, 96, 0, 0, 86, 49, 34, 21, 75, 15, 146, 49, 18, 58, 112}, 187}, {{238, 238, 96, 0, 0, 116, 242, 135, 237, 204, 55, 102, 220, 113, 156, 37}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 70, 196, 3, 70, 249, 144, 245, 89, 67, 109, 110, 153}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 197, 172}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 172, 193, 80}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 191, 101, 166}, 187}, {{238, 238, 96, 0, 0, 0, 177, 159, 143, 54, 253, 145, 134, 37, 0, 139}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 202, 25, 190, 150, 162, 200}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 101}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 14, 80, 207, 47, 141, 41, 43}, 187}, {{238, 238, 96, 0, 0, 0, 172, 36, 12, 19, 175, 100, 216, 50, 197, 147}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 130, 116, 56, 241, 25}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 94, 147, 122, 166, 195}, 187}, {{238, 238, 96, 0, 0, 0, 42, 39, 48, 134, 61, 159, 46, 226, 116, 228}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 168, 174, 178, 78, 68}, 187}, {{238, 238, 96, 0, 157, 177, 105, 27, 11, 210, 253, 95, 23, 26, 235, 120}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 187}, {{238, 238, 96, 0, 0, 236, 68, 59, 125, 162, 35, 85, 130, 203, 127, 170}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 204, 28}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 66, 84, 182}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 93, 113, 242}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 111, 210, 103, 137, 255, 210, 195}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 219, 18, 76, 223, 173, 181, 88, 27}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 161, 65, 58, 28, 198, 130, 151, 74}, 187}, {{238, 238, 96, 0, 136, 10, 56, 215, 30, 75, 98, 93, 68, 125, 85, 84}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 138, 115, 129, 25, 132, 146, 242, 253}, 187}, {{238, 238, 96, 195, 69, 41, 40, 209, 36, 8, 58, 243, 180, 101, 253, 18}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 199, 29, 8, 197, 140, 173}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 252, 245}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 87, 236, 137}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 103}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 17, 142, 104, 142, 120}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 213, 120, 235, 195, 178, 99, 208}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 22, 232, 179, 51, 114, 84, 190, 30}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 140, 85, 29, 21, 181, 152}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 52, 129, 160, 211, 227, 127, 216, 138}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 141, 210, 2, 154, 133, 22}, 187}, {{238, 238, 96, 0, 0, 0, 71, 199, 77, 210, 15, 34, 221, 173, 240, 253}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 89}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 235, 103, 240}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 6, 234, 190, 191, 132}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 88, 63, 247}, 187}, {{238, 238, 96, 0, 0, 0, 78, 92, 122, 180, 221, 156, 50, 197, 114, 72}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 35, 86, 155}, 187}, {{238, 238, 96, 0, 0, 0, 247, 183, 160, 213, 205, 102, 38, 232, 201, 236}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 237, 119, 51, 233, 157}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 153, 245, 37, 79, 238, 240, 204, 76, 209, 102, 69, 64}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 142, 54, 174, 176, 129, 99}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 155, 251}, 187}, {{238, 238, 96, 0, 0, 0, 0, 241, 255, 234, 190, 84, 133, 136, 81, 253}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 109, 55}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 183, 26, 126, 235, 236}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 227, 124, 83, 209, 191, 136, 166, 19}, 187}, {{238, 238, 96, 0, 102, 212, 69, 14, 149, 110, 93, 20, 238, 182, 122, 251}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 147, 251, 128, 97, 96, 194, 94}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 34, 71, 21, 132, 252, 243, 2, 91}, 187}, {{238, 238, 96, 0, 0, 0, 0, 0, 0, 28, 50, 75, 69, 112, 217, 184}, 187}, {{238, 238, 96, 0, 0, 0, 0, 92, 99, 93, 187, 229, 116, 147, 180, 227}, 187}, {{238, 238, 96, 0, 0, 0, 0, 33, 134, 213, 58, 91, 93, 19, 138, 168}, 187}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 83, 126, 67, 227, 76}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 47, 134, 255, 80, 92, 110}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 231, 224, 45, 201}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 99, 14, 92, 116, 103}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 178, 149}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 5, 170, 130, 166, 189}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 124, 33, 40, 223, 233, 225}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 12, 214, 25, 149, 140, 21}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 199, 199, 7, 111, 88}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 63, 1, 114}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 41, 72, 180, 100}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 49, 233}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 73, 81, 210, 201, 24, 136, 97, 244}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 36, 152, 211, 30, 232, 234, 77}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 80, 200, 228, 149, 125, 165}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 169, 232, 30, 202}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 133, 22, 44, 211}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 162, 112, 157, 178, 181, 159}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 240, 114, 29, 36, 5}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 196, 190, 173, 58}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 217, 15, 112, 225, 191, 130, 187}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 208, 68, 239}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 187, 31, 241, 55}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 66, 152, 201, 201, 215, 178, 128, 145}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 221, 129, 167, 204, 229, 5, 50}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 245, 244, 236, 212, 111}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 117, 162, 98, 47, 249}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 133, 39, 107}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 155, 25, 161, 219, 200, 112, 204}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 114, 127, 120, 182, 134, 148, 23, 36}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 49, 81, 165, 85, 8}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 239, 87, 41, 84, 102}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 170, 51, 197, 153}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 29, 73, 172, 45, 93}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 254, 107, 211, 63}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 250, 179, 63, 70, 235, 121, 94, 32}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 174, 120, 36, 43, 96, 52}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 226, 68, 164, 48, 59, 183}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 170, 108, 240, 66, 148}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 58, 154, 222, 140, 223, 35, 195}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 62, 251, 193, 15}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 68, 68, 198}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 115, 128, 27, 44, 160, 55, 230}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 24, 4, 201}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 103, 96}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 5, 19, 98, 218, 18, 94, 160}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 110, 9, 246}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 59, 20, 186, 7, 65}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 54, 218, 153, 36, 6, 254, 193, 225}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 203, 115, 40}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 226, 123, 98, 149}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 45, 113, 5}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 255, 110, 83, 129, 181}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 31, 155, 73, 7}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 165, 187, 233}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 116, 82}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 30, 121, 84, 189, 218}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 110, 82, 216, 3, 66, 30, 253, 178}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 42, 116, 20, 230, 234, 108}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 238, 149, 254, 49, 32, 163, 54, 41}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 61, 36, 238, 182}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 58, 22, 1, 156, 53}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 80, 56, 36, 146, 153, 117, 200}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 125, 190}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 173, 44, 228, 160, 118}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 246, 161, 50, 247, 200, 223, 104, 25}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 130, 165, 253, 108, 240, 127, 167}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 194, 102, 234, 133}, 102}, {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 24, 174, 207, 134, 129}, 102}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 23, 55}, 237}, {{59, 40, 252, 185, 187, 216, 168, 234, 69, 204, 65, 47, 70, 14, 250, 30}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 190, 58, 62}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 245, 88, 202, 49, 47, 13, 120, 151}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 136, 187, 26, 9, 171, 85, 5, 41}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 80, 86, 74, 145, 228, 141, 55, 163}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 80, 1, 230, 91, 37, 118}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 116, 158}, 237}, {{59, 40, 252, 185, 187, 216, 0, 76, 54, 172, 96, 79, 138, 163, 104, 112}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 19, 214, 131}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 156, 174, 93, 5}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 50, 102}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 38, 194, 120}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 237, 204, 178}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 75, 100, 28}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 194, 30, 188, 214, 231, 251, 139}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 135, 66, 28, 127, 252, 37, 222, 75}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 127, 65, 46, 92}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 94, 159, 149, 210, 86}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 237}, {{59, 40, 252, 185, 187, 216, 0, 153, 42, 158, 160, 25, 111, 88, 176, 118}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 99, 72, 221, 138, 139}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 143, 186, 211, 110, 44, 97, 11, 169}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 78, 220, 23, 179, 32}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 183, 193, 87}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 107, 10}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 129, 188, 36}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 45, 95, 230, 108, 38}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 103, 27, 1, 255, 153, 77}, 237}, {{59, 40, 252, 185, 187, 216, 160, 164, 45, 201, 232, 209, 44, 161, 231, 198}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 167, 240, 69, 54, 158, 38}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 248, 99, 0, 40, 231}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 112, 24, 102}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 161, 242}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 57, 99, 217, 248, 178, 160, 165, 170}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 146, 42, 59, 33}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 30, 212, 10, 175, 138, 150, 153, 47}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 87, 39, 26, 164, 142, 142, 233, 95}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 103, 67, 110, 100, 53, 147, 204}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 30, 26, 198}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 183, 67}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 254, 130, 110}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 126, 182, 14, 25, 198, 199, 102, 207}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 255, 95, 75, 169}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 254, 222, 203, 104, 153, 242, 93}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 169, 20, 94, 9, 189, 250, 192}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 171, 20, 171}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 210, 127, 219, 82, 45, 9, 203, 14, 28}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 178, 188, 142, 156, 77, 103, 171}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 225, 120}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 114, 128, 241, 168}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 38, 211, 221, 177, 225}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 50, 240, 179, 176}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 14, 32, 40, 131, 246, 234}, 237}, {{59, 40, 252, 185, 187, 216, 0, 111, 45, 227, 161, 255, 133, 122, 56, 130}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 214, 250, 25, 93, 180, 220, 7}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 232, 122, 16}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 184, 87, 24, 142}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 71, 128, 63, 138}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 237}, {{59, 40, 252, 185, 187, 216, 0, 14, 194, 194, 108, 238, 57, 243, 119, 15}, 237}, {{59, 40, 252, 185, 187, 216, 133, 96, 167, 158, 72, 96, 41, 47, 43, 187}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 223, 227, 30, 68, 243, 22}, 237}, {{59, 40, 252, 185, 187, 216, 0, 51, 249, 83, 227, 33, 117, 220, 235, 249}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 126, 173, 241, 173, 122}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 175, 71}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 41, 159, 125, 49, 159, 1, 202}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 121, 117, 130, 20}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 77, 176, 231, 181}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 162, 241, 227}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 96, 30, 248, 59}, 237}, {{59, 40, 252, 185, 187, 216, 238, 164, 15, 156, 136, 219, 6, 149, 17, 113}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 91, 20, 163, 236, 24, 55}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 25, 163}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 190, 215, 113, 105, 127}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 235, 139, 251, 223, 75}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 81, 174, 79, 184, 248, 205}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 73, 15, 242, 229, 184, 177, 108, 194}, 237}, {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 33, 240}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 116}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 188, 173}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 83, 110}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 139, 70}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 35}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 150, 203}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 33, 105}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 18, 138}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 218}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 2, 82}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 199}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 231, 77}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 71, 210}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 83}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 99, 220}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 41}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 163, 222, 48}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 195}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 124}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 227}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 61}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 46, 75}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 131}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 171}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 39, 43}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 22, 129}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 47, 224}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 175}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 167}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 202}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 38}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 53, 43}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 26, 166}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 145}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 79}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 142}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 230}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 75}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 139}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 228}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 97}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 192, 93}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 154, 29}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 21, 4}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 100, 114, 147}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 39}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 9, 175}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 11, 6}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 3, 81}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 207}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 117, 245}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 107}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 237}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 127}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 163}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 179, 138}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 64, 42}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 245}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 28, 217, 250}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 191, 213}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 73, 52}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 138}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 222, 17}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 221}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 25}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 108}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 210}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 194}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 159}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 142}, 237}, {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 222}, 237}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 83}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 25}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 89}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 238}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 200}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 136}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 169, 244}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 111, 184}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 85}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 238}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 126}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 220}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 235}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 113, 163}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 215, 251}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 146}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 27}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 196}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 65}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 59}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 128}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 40}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 153}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 122}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 124, 138}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 187}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 13, 87}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 167, 154}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 196}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 168}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 214}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 45}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 206, 204}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 60}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 204}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 226}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 176, 47}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 176, 177}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 210, 183}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 18, 151}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 139}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 83, 29}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 62}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 236}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 152}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 237}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 151, 30}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 137}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 166}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 179}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 205, 100}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 17}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 146}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 214}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 124, 239}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 249}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 193, 63}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 10}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 233, 235}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 198, 136}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 164}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 153}, 115}, {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 115}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 36, 17, 187, 129}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 252, 36, 177, 30, 112}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 234}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 220, 219, 184}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 129, 56, 8}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 171, 51, 27}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 136, 44, 176}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 201, 215, 221, 70}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 118, 88, 5, 151}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 89}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 117}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 208, 137, 238, 238, 131}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 164}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 128, 100, 70}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 234}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 20, 181, 216}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 250, 66, 21}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 255}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 12, 205, 12}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 176, 79, 163, 100, 19}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 190, 194, 78, 110, 179}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 42}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 73, 134, 198, 81}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 169, 156}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 69, 190}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 153, 75, 226, 209}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 102, 173, 178}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 150, 51}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 167, 225, 255, 207, 178}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 138, 222, 11, 50}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 16, 223}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 8, 167}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 67, 133, 159, 255}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 13, 44, 1, 107}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 196, 128, 125}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 224, 160}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 194, 85, 80, 252}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 224, 69}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 181, 145, 205}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 95, 215, 154, 233, 142}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 255}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 119, 84, 241, 157, 53}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 125, 39}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 207}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 67, 79, 32}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 156, 76, 26, 83}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 115}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 42, 45, 37, 179, 137}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 186}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 241}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 232, 66, 15, 30, 14}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 125, 4, 50, 81}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 62, 177, 229}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 203, 172}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 221, 35, 252, 25, 154}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 53, 240, 123}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 42}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 31, 96, 74, 207}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 178}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 193, 76, 188}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 117, 229, 32}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 40, 221, 150}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 137, 211, 117, 235}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 9, 254, 3, 235, 234}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 205, 254}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 162}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 240}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 189, 73, 75}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 10, 54, 173}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 196, 234}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 90, 83}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 184, 81, 241, 58}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 9, 138}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 22, 60, 91, 220}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 17, 154}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 147, 152, 88, 229, 133}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 183, 9, 157}, 217}, {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 92}, 217}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 157, 168, 230, 16}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 116, 73}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 92, 206, 41, 109}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 201, 142, 105}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 4, 250, 36}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 88, 229, 27, 49}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 24, 122, 130}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 195, 84, 97, 172}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 191, 148}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 156, 128, 56}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 195, 53}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 9}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 176}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 208, 48}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 236, 167, 170}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 133, 53, 229, 244}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 136}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 5}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 11}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 56, 176, 249, 30, 174}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 26, 58, 38, 230, 252}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 116, 246, 3}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 14, 239, 20, 144}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 75, 51}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 21, 239, 109}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 242}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 61, 209}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 240}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 210, 168, 165, 55}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 79, 178, 129, 169, 2}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 95, 92, 232, 155}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 22, 160, 130}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 235, 39, 214}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 149, 18, 105}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 27, 148, 44}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 25, 200}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 238, 203}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 172}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 87, 21, 59, 11, 90}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 97, 27, 190, 168, 129}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 220, 7, 213, 9, 58}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 231, 151, 140}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 14, 182, 150, 122, 110}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 166}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 114, 206, 134, 51, 127}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 168, 79, 126, 70, 148}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 211, 173}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 154}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 238, 157, 80, 98}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 125, 184, 221, 15, 227}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 98, 247, 99}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 114, 58, 53, 76, 58}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 14, 223, 90, 96, 200}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 253, 95, 121, 244}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 121, 205, 123, 152}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 193, 157, 34, 112, 95}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 129, 176, 93, 30, 209}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 86, 19, 5, 218, 74}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 37, 46, 203, 0, 204}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 42, 87, 5}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 92, 224, 151, 104}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 55, 177}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 123, 87, 26}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 245, 181}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 43, 226, 227, 129, 154, 147}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 151, 144, 228, 195}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 199, 65, 12}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 193}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 255, 246, 199, 100}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 157, 174, 162}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 100, 70}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 26, 222, 189}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 202, 203, 199, 156}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 1, 21, 10, 85}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 230, 231, 152, 146, 24}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 216, 89}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 176, 116, 236, 223, 103}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 104}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 123, 9}, 21}, {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 252}, 21}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 182}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 175}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 166}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 120}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 117}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 183}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 194}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 174}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 252}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 201}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 86}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 57}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 153}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 68}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 110}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 13}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 79}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 68}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 25}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 22}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 180}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 8}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 73}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 199}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 231}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 248}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 98}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 199}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 72}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 172}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 164}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 117}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 10}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 170}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 233}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 10}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 147}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 143}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 56}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 223}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 81}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 2}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 63}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 67}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 127}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 233}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 3}, {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 252}, 3}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 67, 203, 77, 205}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 110, 73, 21, 170, 182, 22, 21, 122}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 51, 0, 13, 238, 207, 173, 155, 89}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 179, 196, 169, 13, 186, 252, 180, 59}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 249, 98, 223, 173, 89, 63, 88, 164}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 65, 150}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 85, 158, 39, 128, 68}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 79, 236, 130}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 112, 45, 17, 49, 78, 9, 2}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 245, 61, 24}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 62}, {{97, 141, 171, 175, 22, 233, 0, 100, 194, 56, 169, 167, 123, 30, 144, 170}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 252, 85, 69, 166, 203}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 111, 42, 77, 225}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 29, 83, 24, 128, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 177, 210, 107, 181, 204, 71, 21}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 66, 14, 243, 39, 179, 16, 143, 82}, 62}, {{97, 141, 171, 175, 22, 233, 0, 120, 56, 159, 126, 104, 16, 7, 13, 15}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 97, 182, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 241, 202, 98, 1, 48, 135, 84, 94}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 92, 206, 138, 161, 50, 83, 97}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 238, 38}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 32, 68, 196, 255, 35, 212}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 59, 76, 192, 238, 227}, 62}, {{97, 141, 171, 175, 22, 233, 0, 39, 23, 227, 89, 238, 114, 154, 67, 94}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 95, 122, 104, 204, 207, 64, 177, 5}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 186, 180, 187, 220, 41, 161}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 62, 12}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 246, 117}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 248, 252, 144, 234, 153, 95}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 243, 166, 189}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 220, 157, 224, 124}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 83, 97, 0, 137, 242, 208}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 33, 27, 213, 154, 88}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 29, 245, 158}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 176, 89, 200, 20, 65, 150, 199, 99}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 6, 233, 64, 215, 142}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 80, 204, 78, 52, 160, 158, 206, 33, 146}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 48, 38, 146, 225, 90, 171, 148}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 124, 129, 162, 77}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 97, 160, 12, 238, 143, 149, 145}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 141, 25}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 121, 144, 218}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 94, 253, 233, 66, 173, 246, 107}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 12, 80, 236}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 168, 147, 43}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 98, 44, 139}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 154, 156}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 240, 186, 143}, 62}, {{97, 141, 171, 175, 22, 233, 0, 150, 22, 9, 34, 88, 7, 23, 129, 205}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 55, 126, 254, 236, 112, 0, 133}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 220, 150, 200, 216, 215, 131, 208, 96}, 62}, {{97, 141, 171, 175, 22, 233, 0, 206, 197, 157, 160, 110, 205, 214, 27, 189}, 62}, {{97, 141, 171, 175, 22, 233, 0, 80, 104, 28, 235, 64, 220, 40, 79, 40}, 62}, {{97, 141, 171, 175, 22, 233, 0, 70, 142, 19, 67, 207, 100, 21, 0, 131}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 68, 12, 231}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 242, 25, 197, 253, 32}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 46, 144, 152, 104}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 18, 44, 32, 29, 143}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 83, 40, 155, 253, 166}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 196, 82, 199, 229, 23}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 195, 146, 38, 173, 149, 72, 165}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 76, 62, 36, 16, 67, 13}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 24, 32, 140, 10, 170, 77, 156, 21}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 181, 3}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 53, 152, 122, 147, 199}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 183, 176, 58, 68, 232}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 162, 123, 134, 25}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 60, 42}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 172, 2, 217, 120, 252, 228}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 161, 203, 13, 108, 11, 22, 92}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 124, 217, 203, 181, 81, 20, 190}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 152, 132, 202, 117, 207, 44, 135}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 49, 46, 208}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 71, 204, 183, 187}, 62}, {{97, 141, 171, 175, 22, 233, 0, 36, 178, 176, 93, 57, 58, 115, 245, 144}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 97, 230, 241, 240}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 171, 196, 195}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 84, 112}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 176, 182, 210}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 23, 122}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 112, 82, 190, 163, 251, 8, 181}, 62}, {{97, 141, 171, 175, 22, 233, 0, 230, 73, 153, 25, 134, 199, 233, 220, 237}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 62}, {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 33, 41, 240, 125, 179, 213}, 62}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 45, 244, 117, 182, 56, 15}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 186, 205, 242, 191}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 121, 135, 226, 230, 150, 6, 161, 43, 214, 228}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 33, 237, 200, 134, 94, 250, 163, 114}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 96, 90, 180, 162, 79, 146}, 80}, {{32, 204, 102, 191, 164, 242, 0, 198, 118, 148, 162, 26, 145, 76, 7, 175}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 55, 120}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 213, 121, 245, 229}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 60, 242, 7, 184, 237, 209, 25}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 19, 228, 93, 64, 182}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 95, 153, 170}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 57, 82, 79, 203, 6, 63}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 30, 113, 56, 74, 225, 172, 202, 160}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 72, 161, 169}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 148, 102, 235, 139, 148, 40, 219, 171}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 30, 42, 126, 132, 150, 13}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 5, 150}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 67, 67, 134, 66, 75, 253, 123}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 194, 67, 14, 167, 151, 44, 161}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 15, 201, 113, 82, 179, 171, 167, 112}, 80}, {{32, 204, 102, 191, 164, 242, 0, 139, 20, 57, 4, 168, 22, 154, 60, 192}, 80}, {{32, 204, 102, 191, 164, 242, 0, 78, 224, 73, 201, 116, 23, 204, 7, 230}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 81, 188, 191, 19, 150, 153, 130}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 177, 176, 17, 141, 216, 23, 125, 111, 192}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 79, 169, 20, 209, 93, 53, 157, 246}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 209, 166, 124, 63, 206, 254, 36}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 51, 169}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 166, 66}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 56, 46, 10, 171}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 63, 44}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 207, 17}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 136, 184, 223}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 248, 47, 0, 31}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 51, 223, 170}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 102, 62, 110, 188, 217}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 119, 37, 249}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 190, 210, 205, 113, 105, 110}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 102, 190, 177, 153, 245}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 163, 230, 69, 27, 142}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 142, 76, 215, 137, 19, 132, 104}, 80}, {{32, 204, 102, 191, 164, 242, 0, 35, 237, 93, 188, 143, 24, 97, 96, 124}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 7, 231}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 110, 22, 127, 196, 77, 18, 47, 47}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 13, 150}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 96, 28, 242, 64, 154, 233, 203, 193, 254}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 46, 177}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 61, 15, 166, 214, 107, 42, 48}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 156, 216, 18, 206}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 191, 184, 80, 156, 252, 197}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 63, 129, 66, 9, 142, 219}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 103, 51, 242}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 120, 111, 16, 39, 196, 51, 56, 176, 238}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 232, 188, 87, 103, 176, 53}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 31, 156, 176, 164, 107, 10, 202, 32}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 119, 12, 143}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 171, 237, 202, 226, 102, 114, 19, 192}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 106, 204, 83, 50, 168, 65}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 138, 41, 59, 45, 55, 170, 84, 97}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 198, 100, 241, 187, 122, 145, 254, 17}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 202, 156, 181, 82}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 106, 84}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 2, 108, 151, 94, 107}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 93, 180, 226, 163, 80, 32, 171}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 214, 193, 238, 215, 30, 146}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 211, 150, 75}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 81, 193, 128, 49, 221, 156}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 108, 230, 155, 172, 226}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 211, 91, 242, 179, 83, 111}, 80}, {{32, 204, 102, 191, 164, 242, 0, 118, 140, 24, 134, 126, 152, 126, 231, 220}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 227, 75, 68, 166, 236, 157}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 239, 159}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 51, 217, 60}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 74, 230, 78, 26, 195, 255, 153, 37}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 42, 67, 146, 104, 179}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 31, 10, 179}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 55, 39}, 80}, {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 179, 14, 244, 165, 190}, 80}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 175, 246, 90, 70, 93, 166, 197, 36}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 194, 201}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 12, 1, 51, 80, 27, 179, 178}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 89, 197}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 246, 183}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 104, 87}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 95, 18, 172, 180, 20, 30}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 155, 1, 199, 108, 130, 32, 191, 43}, 184}, {{29, 133, 210, 252, 124, 66, 160, 101, 112, 32, 100, 191, 77, 30, 51, 198}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 177, 9, 116, 73, 46, 115}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 61, 77, 203, 94, 197, 177, 173}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 201, 42, 13, 139, 78, 224}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 172, 136, 174, 244, 140, 249}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 238, 57, 27, 160}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 158, 128, 89, 182}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 150, 56, 38}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 25, 230, 122, 175, 200, 141, 61}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 180, 154, 71, 97, 20}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 26, 89, 241, 100, 253, 139}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 169, 21, 158, 233}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 223, 94, 122, 63, 169, 148, 82, 167}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 178, 253, 20, 59, 83}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 47, 218, 223, 153, 77, 143}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 127, 51, 221, 46, 216, 30}, 184}, {{29, 133, 210, 252, 124, 66, 160, 245, 56, 224, 240, 160, 65, 90, 49, 27}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 217, 0, 137}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 106, 103, 18, 238, 95, 240}, 184}, {{29, 133, 210, 252, 124, 66, 160, 22, 98, 144, 196, 195, 236, 71, 77, 216}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 253, 204, 19, 140, 166}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 171, 183, 104, 213, 224, 158, 189}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 201, 190}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 146, 139, 63, 154}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 57, 126, 39, 75, 212, 246}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 149, 9, 186, 177, 198, 229}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 224, 106}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 129, 90}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 53, 231, 72, 49, 247, 241}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 221, 81, 231, 254, 65, 198, 30}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 209, 28, 20, 217, 17, 49, 117}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 203, 54, 71, 11, 140}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 195, 103, 60, 189}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 212, 166, 49, 195, 50, 24, 92, 44}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 56, 109, 116, 82}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 220, 114, 203, 33, 126, 32}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 49, 148, 168, 80, 196, 144, 104}, 184}, {{29, 133, 210, 252, 124, 66, 160, 188, 0, 90, 202, 39, 14, 182, 10, 254}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 82, 137, 188, 150, 149, 143, 204}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 16, 210, 108, 92, 214, 115}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 107, 142, 226, 129, 131, 203}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 130, 119, 66}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 255, 233, 138, 0, 18}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 120, 238, 190}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 30, 60, 37, 181, 60, 227, 56, 135}, 184}, {{29, 133, 210, 252, 124, 66, 160, 203, 189, 111, 224, 95, 29, 83, 144, 71}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 155, 11, 169, 191, 101}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 10, 84}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 109, 145, 240, 45, 158}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 219, 63, 27, 70}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 249, 137, 14, 229, 209, 125, 195}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 81, 224, 114, 67, 83, 117, 151, 149}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 41, 15, 120, 14, 147, 167, 170}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 15, 100, 108, 172, 106}, 184}, {{29, 133, 210, 252, 124, 66, 160, 165, 169, 132, 161, 213, 51, 88, 25, 142}, 184}, {{29, 133, 210, 252, 124, 66, 160, 13, 208, 160, 22, 88, 165, 239, 179, 84}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 235, 216, 11}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 50, 243, 182, 180, 219, 43}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 125, 30}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 162, 231, 173, 236}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 193, 53}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 26, 45, 116, 69}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 90, 129, 205, 36, 94}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 156, 123, 134, 183, 71, 9, 27}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 232, 166, 74, 188, 242, 4, 40, 188}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 184}, {{29, 133, 210, 252, 124, 66, 160, 216, 65, 97, 191, 237, 148, 131, 78, 208}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 255, 242, 141, 163, 74, 2}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 107, 200}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 242, 230, 215, 132, 187}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 73, 247, 212, 163, 110}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 154, 209, 14, 208, 137, 137, 118}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 6, 105, 99, 42}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 31, 29, 234, 162, 136, 173, 248, 162}, 184}, {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 146, 89, 241, 222, 44, 63}, 184}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 229}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 182, 71, 221, 144}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 225}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 171, 134, 160, 19, 96}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 252, 26}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 130, 183}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 68, 114, 117, 249, 116}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 124, 24}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 39, 79}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 136}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 7, 16}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 127}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 128, 24, 54, 171}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 109}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 230, 165, 80}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 48, 198, 47, 137}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 133, 44}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 89}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 214, 40}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 144, 203, 140}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 220, 120, 162, 225}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 178, 23, 61, 58, 249}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 113, 251}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 59}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 182, 172, 254}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 212, 123, 147, 169, 36}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 215}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 209, 165, 115}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 183, 179}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 223, 180, 185}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 61, 112}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 8, 189}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 99}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 212, 180}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 252, 135}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 115, 17, 93, 174, 95}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 94, 167, 246}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 98, 147, 119, 176}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 216, 28, 69}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 250, 54, 253}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 32, 8, 242}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 15, 132, 74, 159, 138}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 103, 224, 45}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 140}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 83, 126, 142}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 191, 53, 44}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 241, 89, 98}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 31, 52, 13, 117, 105}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 29, 106}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 175, 160}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 70, 113}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 55, 112, 74, 151, 63}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 145}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 147, 136, 199}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 133, 214}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 89}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 82, 238, 98, 172}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 123, 253, 53}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 139, 193, 74, 90}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 252, 137, 228, 15, 40}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 132}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 78}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 136, 245, 185}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 122, 228}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 4, 55, 108, 162}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 140, 160, 45}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 158, 55, 12, 229}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 223, 95, 9}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 147, 189, 86, 154}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 250, 249, 229, 238, 236}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 31, 20, 140}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 53, 5, 176, 72}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 35, 4}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 45, 230, 229, 66, 59}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 130, 119, 143, 23}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 117, 128}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 27, 38, 45}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 164, 208, 107, 17}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 214}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 21, 86, 12, 164, 59}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 176, 134, 25, 189, 32}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 24, 242, 148, 48, 224}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 212}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 42, 139, 94}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 170, 102, 117, 214}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 243, 209}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 81, 9, 255, 47}, 197}, {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 16, 121, 4}, 197}, {{129, 216, 0, 0, 0, 228, 255, 185, 203, 71, 170, 124, 128, 94, 153, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 252, 179, 255, 2, 24, 111, 134, 143, 99}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 40, 182, 132, 77, 107, 84, 147}, 63}, {{129, 216, 0, 210, 172, 229, 141, 24, 101, 196, 231, 223, 105, 4, 201, 131}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 113}, 63}, {{129, 216, 0, 0, 0, 0, 0, 180, 148, 58, 104, 104, 20, 136, 0, 211}, 63}, {{129, 216, 0, 0, 0, 0, 77, 5, 76, 125, 184, 103, 236, 164, 73, 47}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 153, 8, 234, 213}, 63}, {{129, 216, 0, 0, 0, 61, 161, 175, 205, 44, 119, 199, 11, 212, 110, 196}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 6, 1}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 157, 173, 108, 3, 89, 251, 220}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 218}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 73, 229, 109, 187, 201, 246, 187, 149}, 63}, {{129, 216, 0, 0, 0, 0, 78, 43, 248, 160, 246, 53, 204, 238, 59, 75}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 250, 199, 218, 131, 24, 239}, 63}, {{129, 216, 0, 129, 137, 21, 186, 241, 31, 234, 44, 121, 53, 40, 182, 194}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 14}, 63}, {{129, 216, 190, 165, 2, 91, 78, 250, 78, 251, 154, 155, 192, 185, 138, 160}, 63}, {{129, 216, 0, 0, 0, 0, 101, 33, 141, 22, 124, 183, 63, 35, 126, 134}, 63}, {{129, 216, 0, 0, 0, 0, 127, 53, 172, 161, 194, 72, 252, 70, 36, 103}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 163, 217, 217, 215, 241, 61}, 63}, {{129, 216, 0, 0, 245, 252, 237, 173, 123, 107, 175, 5, 187, 217, 207, 228}, 63}, {{129, 216, 23, 182, 63, 83, 11, 89, 221, 118, 105, 54, 103, 204, 37, 127}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 63}, {{129, 216, 234, 241, 78, 45, 216, 50, 235, 233, 41, 106, 31, 32, 181, 246}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 224, 83, 159}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 184, 29, 64, 176, 114, 32, 14}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 137, 123, 205, 58, 203, 67, 92, 185, 83}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 204, 73, 78, 134, 150, 178, 235, 87, 77}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 53, 51, 38, 106}, 63}, {{129, 216, 0, 0, 0, 0, 3, 56, 45, 7, 8, 55, 191, 149, 11, 90}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 93, 38, 58, 221, 73, 142, 134, 236}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 47, 215}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 88, 122, 1, 241, 5, 201, 212}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 176, 33}, 63}, {{129, 216, 0, 191, 248, 66, 248, 79, 218, 185, 130, 150, 70, 210, 213, 115}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 52, 248, 51, 217, 146, 23}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 193, 78, 97}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 63}, {{129, 216, 0, 0, 109, 2, 143, 44, 7, 237, 60, 249, 227, 69, 20, 170}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 249}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 253, 47, 250, 28, 113, 123}, 63}, {{129, 216, 0, 0, 0, 0, 0, 122, 87, 103, 155, 187, 161, 108, 54, 21}, 63}, {{129, 216, 0, 0, 0, 0, 0, 226, 137, 243, 81, 45, 18, 104, 80, 173}, 63}, {{129, 216, 0, 0, 0, 44, 126, 14, 220, 35, 248, 223, 17, 8, 204, 228}, 63}, {{129, 216, 0, 187, 178, 161, 87, 183, 30, 62, 126, 6, 237, 90, 70, 14}, 63}, {{129, 216, 0, 0, 0, 144, 155, 106, 67, 237, 170, 211, 222, 107, 222, 128}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 23, 22}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 177, 207, 175, 232, 29, 98, 169, 184}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 17, 103, 255, 217}, 63}, {{129, 216, 0, 0, 99, 210, 192, 149, 96, 48, 98, 202, 69, 50, 89, 169}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 247, 27, 0}, 63}, {{129, 216, 0, 0, 0, 43, 91, 229, 0, 180, 94, 96, 101, 186, 70, 129}, 63}, {{129, 216, 0, 0, 37, 113, 16, 151, 5, 112, 108, 160, 224, 63, 221, 81}, 63}, {{129, 216, 0, 0, 0, 201, 60, 251, 72, 251, 238, 6, 18, 56, 57, 47}, 63}, {{129, 216, 0, 0, 0, 0, 167, 205, 102, 145, 104, 15, 116, 7, 157, 95}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 184, 152}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 218, 124, 253, 69, 40, 255}, 63}, {{129, 216, 0, 18, 130, 133, 159, 127, 57, 167, 235, 196, 228, 43, 3, 249}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 111, 68, 204, 248, 254, 38, 48}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 63}, {{129, 216, 0, 0, 0, 11, 126, 29, 50, 109, 46, 89, 135, 114, 237, 85}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 199, 181, 128, 186, 58, 142}, 63}, {{129, 216, 0, 0, 0, 0, 0, 127, 185, 180, 40, 202, 123, 235, 65, 43}, 63}, {{129, 216, 0, 0, 0, 227, 99, 213, 244, 27, 165, 226, 99, 156, 8, 5}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 253}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 70, 138, 169}, 63}, {{129, 216, 0, 0, 0, 0, 0, 1, 71, 105, 223, 221, 38, 194, 170, 108}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 155, 95, 101, 186}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 18, 107}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 106, 140, 89, 193, 235, 206, 51, 186}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 187, 94, 184, 140, 118, 238, 67, 18}, 63}, {{129, 216, 0, 0, 0, 0, 0, 127, 124, 7, 194, 59, 168, 8, 188, 104}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 193, 143, 14, 207, 243, 15, 134, 116}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 220}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 228, 144, 239, 102, 171, 90, 67}, 63}, {{129, 216, 0, 0, 0, 211, 25, 254, 156, 203, 84, 84, 202, 29, 35, 79}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 216, 246, 147, 120, 224, 66, 49}, 63}, {{129, 216, 0, 0, 99, 12, 33, 45, 5, 116, 20, 86, 208, 108, 205, 249}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 197, 28, 57, 123, 63, 219}, 63}, {{129, 216, 0, 0, 0, 153, 199, 180, 37, 2, 228, 102, 156, 116, 253, 152}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 199}, 63}, {{129, 216, 0, 0, 0, 185, 63, 61, 251, 248, 58, 154, 124, 223, 107, 245}, 63}, {{129, 216, 0, 58, 190, 206, 254, 189, 16, 188, 38, 120, 69, 1, 202, 121}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 91, 238, 248, 26, 123, 237, 163, 178}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 239, 201, 123, 232, 63, 0, 35, 222}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 66, 14, 157, 6, 188, 49, 29, 32}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 215, 170, 66, 215, 237, 73}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 33, 214, 166, 203, 132, 236, 126}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 63}, {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 219, 213, 118}, 63}, {{129, 216, 0, 83, 57, 89, 27, 198, 91, 151, 212, 23, 201, 6, 165, 2}, 63}, {{129, 216, 0, 0, 0, 0, 42, 94, 31, 13, 101, 108, 3, 68, 60, 213}, 63}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 186, 40}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 34, 73}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 108, 19, 141}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 44, 103}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 160, 222, 119}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 103, 124, 174}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 57, 227, 125}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 175, 15}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 86, 170, 101}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 157, 99}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 15}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 206, 146, 135}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 155, 242}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 99, 155}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 233}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 73, 81}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 59}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 108, 96}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 75}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 24, 99, 110}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 179, 2}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 169, 127, 40}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 97}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 151, 217}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 63}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 6, 31}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 8, 192, 48}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 24, 34}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 213}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 173}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 50}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 156, 108}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 127, 187, 108}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 64}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 44, 182}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 39}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 135, 24, 205}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 132, 23}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 201, 94}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 163, 67, 32}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 53}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 85, 32, 222}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 150, 10}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 196}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 139}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 78, 96}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 133}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 226}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 26, 53}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 147, 115}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 24, 134, 238}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 135, 16}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 95, 177, 211}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 12, 134}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 210}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 7, 194}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 171}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 17, 64}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 100}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 50, 58}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 52, 116, 236}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 224}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 239}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 83, 119}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 212, 175}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 100, 251}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 74, 169}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 146, 178, 94}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 172}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 37}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 96, 104, 193}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 146, 110}, 62}, {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 62}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 138}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 254}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 151}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 103}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 214}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 221}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 172}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 117}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 195}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 25}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 90}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 158}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 48}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 99}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 64}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 104}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 238}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 161}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 66}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 240}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 63}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 236}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 124}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 185}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 121}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 79}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 77}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 89}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 147}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 215}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 166}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 33}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 183}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 160}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 147}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 26}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 136}, 231}, {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 225}, 231}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 69}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 15, 118, 196}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 13, 162, 155, 77}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 81, 30, 65, 29, 255}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 6, 238, 192, 57, 131, 97, 197}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 129}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 159}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 232, 220, 147, 93, 129, 220}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 139}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 133, 143, 222, 176}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 17, 82, 60}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 208, 138, 174, 91, 93}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 2, 167, 7, 204, 181, 207}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 143, 45, 162, 121, 104}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 238, 64, 33, 98, 221}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 55}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 37, 0, 8, 55, 12, 27, 191}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 121}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 226, 232, 141}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 149, 148, 236, 245, 250, 168}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 251}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 152, 95, 103}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 1, 18, 249, 19, 98, 18}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 46, 5, 94, 80, 189, 7, 215}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 76, 210}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 213, 99, 245}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 155, 33, 211, 35, 56, 27}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 27, 220, 87, 199, 113, 212, 231}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 223}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 91, 216, 204}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 22, 204, 72, 226}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 250, 20, 72, 90}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 220, 14, 247, 221, 204}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 218, 118, 161}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 234, 23, 228, 232}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 16, 119, 251, 123, 2, 180, 199}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 69, 170, 220, 239, 66}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 185, 219, 229}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 7, 50, 97, 35}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 233, 16, 146, 251}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 37, 85, 236, 148}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 43, 248, 94}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 158, 5, 0, 215, 83, 51, 185}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 253, 35, 109}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 32, 46, 104, 152, 94}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 102}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 137}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 86, 230, 25, 205}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 27}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 212, 4, 141, 137, 213, 222}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 119, 116, 233, 89, 39, 241, 115}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 161, 67, 16, 103, 132, 89}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 219, 157}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 24}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 132, 225}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 181, 116, 172}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 78, 142, 118, 206, 84, 196}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 117, 8, 103, 94, 15, 235}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 99, 170}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 94, 203}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 185, 4, 30, 102, 111}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 39, 244, 235}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 211, 170}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 37, 240, 186}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 19, 212}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 2, 72, 74, 201, 104, 19, 244}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 124, 94, 102}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 243, 174, 187, 235, 176, 219}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 233, 141, 195, 187, 213, 98}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 123, 221, 184, 207, 39}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 244, 199, 61, 247, 127}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 76, 226, 254}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 250, 246, 78, 17, 224, 142}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 166, 215, 235, 226, 206, 164, 182}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 158}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 204, 158}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 92}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 54}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 208, 177}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 162, 152}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 47, 191, 93, 117, 77, 144, 186}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 156}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 47, 34, 200, 45, 163, 55, 152}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 226}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 150, 243, 133, 4, 128, 250}, 158}, {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 163, 216, 3, 0, 5}, 158}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 68, 175}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 243}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 243, 188}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 72, 198}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 138, 121}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 133}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 107, 106}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 155}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 93}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 194, 29}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 164}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 58}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 244}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 92}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 235, 205, 51}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 26}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 50}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 208}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 54}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 97}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 233}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 44, 159}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 48, 22, 167}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 188}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 44}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 75, 121, 17}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 82}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 217}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 250, 91}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 210}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 229, 138}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 141, 143}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 68, 41}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 142, 119, 200}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 118}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 184, 131}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 163, 107, 22}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 51, 179}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 66, 179}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 138, 193, 127}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 143, 108}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 191, 129}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 108, 207, 62}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 184, 180}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 244, 111, 243}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 53, 101}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 237, 71}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 91, 189}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 8}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 69, 4}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 16}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 167}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 212}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 80, 22}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 152}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 25}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 213, 14}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 30, 100}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 51, 86}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 99, 230}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 51, 199}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 179}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 80, 24, 132}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 10, 254}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 228}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 118}, {{14, 229, 193, 248, 0, 0, 0, 71, 180, 92, 3, 88, 140, 197, 237, 160}, 237}, {{14, 229, 193, 248, 0, 0, 0, 232, 127, 43, 110, 151, 77, 114, 214, 218}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 119, 246, 247, 101, 153, 17, 128}, 237}, {{14, 229, 193, 248, 0, 0, 91, 67, 196, 25, 129, 31, 144, 172, 12, 15}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 222, 102, 126, 129, 160, 161}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 44, 36, 78, 85, 190, 130, 126}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 6, 154, 165, 98, 245, 53, 76, 58}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 84, 6, 83, 134, 124}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 172, 132, 138, 180, 203, 120}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 138, 18, 254, 228}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 103, 76, 149, 15, 98}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 109, 22}, 237}, {{14, 229, 193, 248, 0, 0, 0, 19, 9, 196, 241, 117, 97, 117, 229, 143}, 237}, {{14, 229, 193, 248, 0, 32, 209, 53, 70, 4, 77, 119, 195, 29, 168, 229}, 237}, {{14, 229, 193, 248, 0, 0, 0, 207, 139, 141, 33, 71, 85, 119, 207, 205}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 19}, 237}, {{14, 229, 193, 248, 0, 0, 0, 185, 55, 120, 75, 222, 87, 201, 226, 177}, 237}, {{14, 229, 193, 248, 0, 0, 0, 43, 23, 2, 20, 4, 78, 78, 6, 166}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 210, 23, 245, 234, 154, 237}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 216}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 194, 189, 227, 67}, 237}, {{14, 229, 193, 248, 0, 0, 160, 161, 46, 14, 184, 48, 225, 168, 228, 128}, 237}, {{14, 229, 193, 248, 0, 0, 0, 71, 158, 25, 105, 55, 241, 121, 136, 171}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 62, 255, 194, 221}, 237}, {{14, 229, 193, 248, 0, 0, 0, 61, 187, 24, 248, 84, 5, 141, 249, 233}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 201}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 227, 4, 196, 37}, 237}, {{14, 229, 193, 248, 0, 0, 80, 242, 196, 116, 110, 123, 35, 203, 191, 9}, 237}, {{14, 229, 193, 248, 0, 74, 52, 101, 183, 12, 197, 181, 241, 99, 3, 132}, 237}, {{14, 229, 193, 248, 0, 0, 123, 47, 14, 226, 32, 155, 154, 77, 40, 235}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 249}, 237}, {{14, 229, 193, 248, 0, 0, 234, 83, 137, 201, 93, 46, 254, 50, 54, 35}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 76, 127, 106, 83, 63, 114, 254, 240, 98, 242}, 237}, {{14, 229, 193, 248, 0, 0, 0, 206, 213, 121, 245, 239, 138, 178, 234, 115}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 53, 41, 104, 203, 5, 70, 219, 3}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 237}, {{14, 229, 193, 248, 0, 212, 219, 253, 29, 133, 52, 187, 171, 163, 117, 19}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 90, 148, 68, 195}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 49, 204, 217, 136, 3, 134}, 237}, {{14, 229, 193, 248, 0, 0, 60, 44, 122, 126, 192, 171, 185, 8, 139, 161}, 237}, {{14, 229, 193, 248, 0, 248, 210, 222, 117, 53, 55, 51, 54, 69, 187, 126}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 66, 107, 218, 56, 34, 235, 210}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 101, 54, 66, 100}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 81, 117, 48, 171, 192, 72, 109, 6}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 233, 61, 83, 44, 113, 9}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 179, 211, 12, 88, 227}, 237}, {{14, 229, 193, 248, 0, 0, 0, 175, 167, 134, 59, 255, 179, 60, 126, 147}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 247}, 237}, {{14, 229, 193, 248, 0, 127, 128, 0, 160, 57, 145, 8, 32, 35, 255, 134}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 130, 16, 125, 231, 187, 85}, 237}, {{14, 229, 193, 248, 0, 227, 250, 157, 20, 240, 202, 118, 61, 33, 26, 11}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 128, 10}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 41}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 106, 149, 55, 166, 131, 21, 168, 187}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 237}, {{14, 229, 193, 248, 0, 0, 62, 179, 16, 130, 29, 49, 180, 155, 97, 2}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 79, 164, 32, 229, 242}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 163, 48, 98, 235, 177, 145, 94}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 217, 148, 250, 55, 103, 229, 16, 225}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 88, 59, 61, 21, 171}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 2, 208, 247, 113, 216, 138}, 237}, {{14, 229, 193, 248, 0, 0, 0, 104, 12, 214, 164, 45, 248, 233, 68, 14}, 237}, {{14, 229, 193, 248, 0, 235, 212, 176, 187, 172, 38, 125, 242, 194, 254, 99}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 188}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 59, 11, 178, 40, 168, 129, 139}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 180, 184, 9, 23}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 253}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 33, 111}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 24}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 211, 231, 22, 33, 89, 10, 154, 168}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 45, 181, 145, 217, 55, 147}, 237}, {{14, 229, 193, 248, 0, 0, 0, 183, 156, 197, 188, 4, 231, 106, 152, 24}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 237}, {{14, 229, 193, 248, 0, 0, 110, 134, 235, 197, 41, 103, 226, 78, 43, 117}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 206}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 226}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 101, 101}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 93, 161, 96, 212}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{14, 229, 193, 248, 0, 0, 96, 62, 34, 209, 49, 123, 14, 39, 236, 174}, 237}, {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 237}, 237}, {{14, 229, 193, 248, 154, 85, 101, 21, 7, 153, 94, 56, 57, 177, 184, 228}, 237}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 95, 70, 247}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 217, 228, 245, 39}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 25, 84, 55}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 234}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 94, 122, 62, 64, 234}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 29, 124, 148, 210, 205}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 58, 186, 217, 42, 77}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 3, 251, 230}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 159, 162}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 253, 210, 231}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 75, 70, 170, 212, 107}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 15, 189, 241, 130, 125}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 89, 39, 31, 10, 247}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 236, 85, 148, 242, 40}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 10}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 65, 140, 222, 110}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 235, 21, 118, 254}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 114, 46, 32, 7, 57}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 42, 219, 237, 236, 184}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 177, 100, 38, 217}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 118, 223, 57, 113}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 187, 162, 19, 118}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 41, 150, 189}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 70, 251, 45, 105, 57}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 214}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 254, 117, 200, 137, 97}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 1, 230, 144, 225, 59}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 209, 170, 22}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 3, 206}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 78}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 118, 140, 214, 65}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 65, 49, 36}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 146, 60, 55, 148}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 230, 12, 212, 19, 154}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 105, 91, 43, 152, 231}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 196, 75, 191, 177}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 168, 70, 76, 35}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 53, 110, 144, 186}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 192, 14}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 204, 185}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 13, 100}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 173, 87, 31, 174, 201}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 150}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 222, 210, 75, 177, 95}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 249, 87}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 10, 92, 6, 89}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 127, 224, 53}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 161, 34, 228, 156, 145}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 125}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 125, 73, 112}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 82, 159, 161, 125}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 57}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 182, 210, 53}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 221}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 210, 235, 160, 112, 187}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 133, 204}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 222, 84, 230, 170, 214}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 31, 247}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 100, 141, 58, 1, 12}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 75, 34}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 151, 49, 103, 62, 61}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 95, 31, 70}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 231}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 236}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 119, 12, 113}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 6}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 200, 120}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 159}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 247, 215, 251, 164}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 57, 207, 167, 117, 196}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 59, 181, 85, 150}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 24, 47, 42}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 45}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 243, 240}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 229, 69, 246, 160, 236}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 28, 31}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 191, 243, 91, 197}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 43, 207, 219, 173}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 31, 75, 31, 20}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 245, 188, 198, 84, 227}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 55, 117, 131}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 184, 44, 66, 209}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 11, 85, 193}, 15}, {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 97, 239, 154}, 15}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 84}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 239}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 79}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 96}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 65}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 122}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 104}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 201}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 216}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 68}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 205}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 168, 147}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 21, 221, 221, 50}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 45, 5, 43}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 66, 233, 254}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 72, 217, 172, 62, 187}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 189}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 144, 124, 83, 80, 17}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 89, 29, 155, 27, 166}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 28, 157}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 166, 87, 208}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 50}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 133, 139, 17, 131, 66}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 239}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 54, 171, 242, 225, 176}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 148, 137}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 218, 94}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 144, 92}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 118, 26, 76, 72, 132}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 251, 96, 160, 44}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 228, 237, 191, 1}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 146, 133, 232, 6}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 154, 123, 174, 38}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 188, 37}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 34, 1}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 80}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 219, 37, 134, 205}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 157, 117, 145, 150, 226}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 78, 179, 162, 69}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 216, 70, 103, 195, 177}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 143, 129, 241, 222}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 236, 93}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 176, 234, 184}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 169, 121}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 216, 129, 114, 24}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 61, 126, 236, 154}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 254, 155, 231, 195, 196}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 178, 15, 146, 156}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 97, 147, 73}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 130}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 159, 190, 139, 166, 166}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 114, 40}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 173, 136, 52}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 226, 18, 186}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 9, 175}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 109, 48, 11, 65}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 130, 190, 110, 174}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 177, 249}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 110, 242, 235, 117, 128}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 72, 21}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 165}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 113, 61}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 76}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 89, 221, 236, 18}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 205, 225, 147, 193}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 243, 117}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 237, 125, 73}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 16, 248, 240, 51}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 195}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 15}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 42, 78, 138, 205}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 135, 133}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 29}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 52, 38}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 57, 222, 44}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 167, 141, 164}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 73, 215, 146, 71, 204}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 187, 44, 161, 238}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 60, 178}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 65, 248, 128, 7, 79}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 198, 55, 41}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 108, 249}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 193}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 221, 19, 216, 102}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 219}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 210, 51, 196, 27}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 40}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 76}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 128}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 132, 230, 126}, 220}, {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 21, 9, 126, 150, 196}, 220}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 9, 203, 66}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 58, 132, 230}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 245, 100, 251, 55, 126, 215, 129, 237, 230, 107}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 187, 59, 185, 156, 89}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 201, 10, 204, 71, 188}, 42}, {{44, 26, 254, 11, 181, 0, 0, 156, 23, 120, 141, 186, 105, 18, 199, 185}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 188, 181, 34, 253, 20, 195, 228, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 72, 241, 130, 106, 11, 250, 250}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 208, 36, 157, 166, 12, 9}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 68, 69, 11, 82, 212}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 42}, {{44, 26, 254, 11, 181, 0, 0, 141, 249, 54, 121, 176, 148, 140, 182, 112}, 42}, {{44, 26, 254, 11, 181, 0, 0, 162, 54, 177, 38, 75, 203, 197, 255, 179}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 79, 64, 96, 223, 20}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 180, 199, 222, 111}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 95, 55, 215, 2, 76, 59, 37}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 96, 147, 221, 106, 20, 208, 83, 253, 147, 72}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 79, 223, 84, 3, 133, 95}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 165, 136, 164, 167, 209, 192, 130, 25}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 244, 91, 216, 155, 148, 234, 165, 207, 51}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 169, 11, 167, 113}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 164, 251, 3, 15}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 71, 30, 1}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 132, 14, 21, 169, 239, 239, 99}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 76, 0, 82, 149, 178, 255}, 42}, {{44, 26, 254, 11, 181, 0, 0, 92, 237, 220, 154, 229, 26, 205, 229, 127}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 11, 104, 221, 20, 150, 222, 97}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 137}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 34, 245, 36}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 250, 71, 8, 103, 43, 192, 49}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 146, 9, 228, 103, 39, 24}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 136, 219, 68, 32, 30, 172, 163}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 107, 185, 35, 20, 66, 199, 25}, 42}, {{44, 26, 254, 11, 181, 0, 163, 65, 123, 117, 48, 57, 22, 211, 13, 150}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 49, 159, 57, 186}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 57, 105, 0, 0, 9, 120, 42}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 177, 203, 118, 97, 119, 218, 179, 200}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 113, 43, 125, 175, 48, 234, 93, 152}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 27, 229, 101, 139, 241, 210, 77, 25}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 144, 176, 250, 155}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 124}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 57, 238, 124, 73, 50, 102, 204, 184}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 53}, 42}, {{44, 26, 254, 11, 181, 0, 0, 212, 152, 88, 83, 62, 194, 177, 174, 50}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 86, 113, 163, 70, 227, 63, 67, 130, 147, 225}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 193, 251, 69, 183, 160, 215}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 207, 162, 28, 110}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 166, 226, 93}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 126, 45, 240, 121, 149, 132, 238}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 84}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 13, 245, 225, 209, 148, 169, 161}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 179, 134, 164, 40, 126}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 7, 44, 158, 14, 63}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 197, 22, 85, 249, 244}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 134, 30, 164}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 64, 213, 97, 16}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 198, 182, 13}, 42}, {{44, 26, 254, 11, 181, 0, 0, 186, 120, 120, 53, 31, 226, 17, 199, 151}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 116, 84, 126, 1}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 107, 184, 125, 160, 2, 76}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 215, 39, 62, 237, 65}, 42}, {{44, 26, 254, 11, 181, 0, 0, 109, 127, 79, 97, 58, 91, 98, 33, 18}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 107, 75, 223, 5, 80, 227}, 42}, {{44, 26, 254, 11, 181, 0, 0, 120, 173, 212, 106, 218, 168, 41, 128, 199}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 109, 170, 21, 16, 189, 136, 54}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 50}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 71, 112, 99, 79, 227}, 42}, {{44, 26, 254, 11, 181, 0, 74, 20, 117, 242, 118, 221, 184, 182, 57, 141}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 250, 146, 131, 40, 176}, 42}, {{44, 26, 254, 11, 181, 0, 0, 114, 110, 198, 248, 5, 139, 39, 78, 222}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 245, 198, 199, 235, 224, 8, 115, 155, 179}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 229, 189, 199, 160, 83, 14, 242, 226}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 5, 55, 65, 238}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 69, 201, 12, 48, 165, 112, 33}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 208}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 83, 226, 77, 215, 194, 5}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 126, 28, 153, 180, 143}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 249, 197, 156, 145, 72, 236, 74}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 103, 173, 210, 245, 142, 235, 78}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 21, 14, 133}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 95, 193, 204, 124, 159, 82, 191, 189}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 196}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 228, 173, 19, 234, 87, 50, 41}, 42}, {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 31}, 42}, {{209, 114, 97, 249, 227, 159, 224, 0, 191, 73, 73, 231, 244, 27, 202, 126}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 70, 164, 126, 68, 159}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 23, 152, 125, 140, 78}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 79, 112, 51, 16, 158, 97, 84, 121}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 129, 195, 20, 71, 254}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 177, 192, 25, 191, 99, 21}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 115, 3, 155, 212, 239, 252, 132, 50}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 93, 115, 160, 54, 36, 171, 216}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 251, 168}, 144}, {{209, 114, 97, 249, 227, 159, 224, 176, 157, 1, 203, 178, 157, 33, 224, 89}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 144}, {{209, 114, 97, 249, 227, 159, 224, 52, 178, 140, 220, 71, 254, 247, 109, 160}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 118, 183}, 144}, {{209, 114, 97, 249, 227, 159, 224, 10, 221, 251, 80, 230, 161, 128, 16, 137}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 57, 175, 225, 119}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 190, 57}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 25, 248, 13, 143, 205, 96, 45}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 87, 192}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 106, 124, 162, 25}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 201, 91, 150, 225, 236, 179, 81}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 68, 109, 221, 255}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 49, 122, 120, 55, 230, 74, 236}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 248, 76, 16, 193, 95, 25}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 46, 44, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 4, 254, 99, 204}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 226, 45, 152, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 135, 45}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 106, 176, 184, 193, 63, 29, 168, 196}, 144}, {{209, 114, 97, 249, 227, 159, 224, 101, 172, 11, 229, 237, 121, 177, 178, 161}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 223, 10, 88, 76}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 229, 219, 232, 194, 64, 209}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 186, 115, 253, 165, 34}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 186, 39, 233, 148}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 69, 224}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 20, 197, 190}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 136, 124, 182, 4, 202}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 17, 110, 143, 82, 68, 215, 255}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 104, 124, 14, 237}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 251, 213, 92, 177, 165}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 176, 32}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 212, 136, 139, 35, 203, 22, 241, 73}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 4, 109}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 38, 0, 34}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 71, 4, 104, 194}, 144}, {{209, 114, 97, 249, 227, 159, 224, 43, 155, 231, 35, 136, 217, 5, 108, 161}, 144}, {{209, 114, 97, 249, 227, 159, 224, 54, 51, 8, 223, 94, 196, 1, 21, 111}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 24, 3, 231}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 10, 210, 48, 86, 174, 177, 134}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 51, 23, 251, 141, 5, 211}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 226, 246, 168, 238, 167, 183}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 184, 14, 45, 83, 105, 50, 114}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 81, 130, 91, 26}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 62, 75, 4, 127, 25, 27}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 79, 68, 122, 69, 120, 169, 94, 112}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 176, 239, 62, 169}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 196, 223, 81}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 26, 220, 151, 90, 38, 4}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 130, 233}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 103, 206, 225}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 140, 147, 240}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 91, 12, 225, 65}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 196, 97, 252, 107, 197, 13, 22, 166}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 107, 0, 70, 101, 91, 60, 230}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 106, 26, 37}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 90, 4, 185, 192, 7}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 160, 126, 204, 192, 135}, 144}, {{209, 114, 97, 249, 227, 159, 224, 7, 22, 116, 61, 61, 195, 251, 60, 133}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 34, 183, 61, 83, 150}, 144}, {{209, 114, 97, 249, 227, 159, 224, 204, 170, 250, 116, 51, 13, 245, 36, 57}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 75, 222, 128, 164, 153}, 144}, {{209, 114, 97, 249, 227, 159, 224, 110, 97, 228, 101, 196, 245, 4, 99, 243}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 173, 98, 59, 102, 154, 234}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 72, 3}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 175, 143, 13, 103, 245}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 109, 65}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 5, 34, 124, 221, 78}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 163, 179}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 40, 132}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 205, 209, 125, 43, 251, 178}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 207, 201, 79, 94, 63, 100, 179}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 162, 90}, 144}, {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 144}, {{184, 244, 43, 117, 56, 0, 0, 191, 87, 113, 169, 247, 20, 203, 105, 49}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 55, 82, 246}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 229, 37, 8, 79}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 203, 17, 130, 249, 19, 146, 125, 4}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 81, 211, 2, 49, 207}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 199, 240, 87, 224, 151, 31}, 74}, {{184, 244, 43, 117, 56, 0, 201, 228, 246, 15, 139, 59, 149, 134, 79, 191}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 92, 124, 254, 17, 23, 80, 183, 86}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 52, 187, 156, 115, 229, 201, 41}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 72, 189, 56, 215, 170, 122, 34, 52}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 100, 217, 32, 30, 150}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 38}, 74}, {{184, 244, 43, 117, 56, 0, 0, 197, 67, 132, 139, 122, 251, 180, 4, 243}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 37, 17, 162, 225, 148, 117, 62}, 74}, {{184, 244, 43, 117, 56, 0, 0, 72, 132, 86, 120, 7, 128, 27, 179, 225}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 101, 158, 16, 182, 53, 173, 130}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 69}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 253, 224, 8, 224, 223}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 241, 16, 46, 68, 203, 170}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 185}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 198, 68, 136, 55, 245, 1, 252, 98}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 97, 147, 157, 79, 43, 159}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 149}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 55}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 28, 174, 70, 195, 9}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 43, 160, 166, 218, 122, 188, 25}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 110, 40, 26, 62, 223}, 74}, {{184, 244, 43, 117, 56, 0, 124, 25, 71, 202, 57, 235, 54, 144, 125, 191}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 130, 142, 91, 235, 193, 233, 33}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 69, 18, 7, 70, 209, 235}, 74}, {{184, 244, 43, 117, 56, 0, 0, 83, 9, 223, 39, 0, 34, 245, 78, 45}, 74}, {{184, 244, 43, 117, 56, 0, 0, 41, 249, 128, 149, 80, 240, 105, 44, 96}, 74}, {{184, 244, 43, 117, 56, 0, 125, 200, 18, 17, 246, 91, 190, 153, 68, 127}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 78, 51, 160}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 117, 82, 129}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 198, 187, 166, 38}, 74}, {{184, 244, 43, 117, 56, 252, 97, 53, 143, 123, 185, 254, 163, 213, 92, 155}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 109, 59, 0, 171, 238, 68, 207, 163}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 180, 213, 50, 234, 58, 171}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 144, 228, 189, 172, 233, 211, 43, 57}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 142, 194, 27, 58}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 43, 99, 37, 21, 63}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 64}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 229, 75, 174, 112}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 84, 56, 162, 6, 225}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 156, 31, 133, 135, 253, 168}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 107, 146, 173, 40, 171}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 67, 5, 90}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 49, 234, 108}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 107, 25, 199, 180, 7, 51}, 74}, {{184, 244, 43, 117, 56, 0, 250, 135, 144, 126, 113, 174, 15, 187, 223, 81}, 74}, {{184, 244, 43, 117, 56, 0, 0, 90, 98, 59, 180, 55, 207, 3, 196, 1}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 192, 66, 173, 158, 74, 231, 169, 70}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 50, 35, 70, 231, 237}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 29, 117, 174, 63}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 143, 193, 95, 71}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 144}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 72, 138, 219, 219}, 74}, {{184, 244, 43, 117, 56, 0, 45, 168, 67, 30, 159, 200, 76, 121, 105, 130}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 56, 137, 150, 245, 73}, 74}, {{184, 244, 43, 117, 56, 0, 144, 121, 253, 38, 245, 14, 23, 236, 167, 15}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 122, 192, 223, 189, 78, 188, 133}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 80, 202, 117, 126, 147}, 74}, {{184, 244, 43, 117, 56, 0, 125, 182, 253, 178, 208, 189, 102, 39, 61, 100}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 93, 9, 90, 222, 230}, 74}, {{184, 244, 43, 117, 56, 0, 69, 221, 167, 149, 242, 92, 184, 233, 23, 57}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 100, 77, 226, 150, 192, 194}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 90, 246, 233}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 107}, 74}, {{184, 244, 43, 117, 56, 0, 0, 95, 126, 20, 254, 165, 87, 65, 35, 26}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 78, 194, 162}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 246, 74, 245, 136, 122, 225, 118, 156}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 38}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 231, 171, 189}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 138, 168, 178, 149, 88}, 74}, {{184, 244, 43, 117, 56, 0, 44, 126, 185, 77, 21, 187, 57, 230, 70, 48}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 66, 12, 85, 36}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 120, 69, 139, 15}, 74}, {{184, 244, 43, 117, 56, 103, 153, 41, 254, 223, 223, 126, 232, 125, 137, 157}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 213, 188, 25, 28, 115, 13, 169}, 74}, {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 74}, {{60, 81, 128, 0, 0, 188, 160, 4, 117, 240, 20, 24, 151, 183, 211, 175}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 219, 112}, 89}, {{60, 81, 128, 0, 145, 106, 155, 194, 30, 177, 105, 15, 89, 51, 95, 235}, 89}, {{60, 81, 128, 0, 8, 107, 121, 22, 108, 94, 121, 109, 84, 116, 204, 204}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 73, 0, 152, 129, 91, 167, 40}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 68, 82, 115, 116, 18, 101, 150}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 43, 66, 109, 65, 130}, 89}, {{60, 81, 128, 0, 80, 229, 177, 102, 182, 172, 78, 227, 245, 57, 90, 154}, 89}, {{60, 81, 128, 0, 0, 0, 140, 206, 44, 197, 238, 8, 196, 117, 255, 217}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 127, 238, 110, 136, 144, 102, 110}, 89}, {{60, 81, 128, 0, 0, 26, 191, 184, 115, 61, 97, 213, 84, 251, 194, 56}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 211, 54}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 152}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 130, 150}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 144, 196, 254, 178, 251}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 81, 135, 231, 48, 190, 109, 121, 192}, 89}, {{60, 81, 128, 133, 219, 23, 149, 51, 40, 154, 211, 77, 49, 126, 191, 66}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 84, 224}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 43, 221, 68}, 89}, {{60, 81, 128, 0, 110, 164, 136, 180, 131, 231, 148, 226, 165, 121, 245, 172}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 115, 53, 94, 178, 90}, 89}, {{60, 81, 128, 0, 131, 27, 99, 33, 216, 165, 38, 14, 167, 3, 118, 154}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 204, 249, 169, 233, 110, 28}, 89}, {{60, 81, 128, 0, 0, 61, 213, 96, 214, 201, 128, 53, 246, 249, 35, 49}, 89}, {{60, 81, 128, 0, 0, 198, 203, 101, 126, 76, 77, 31, 150, 173, 25, 65}, 89}, {{60, 81, 128, 0, 19, 162, 15, 163, 222, 157, 240, 54, 89, 248, 31, 231}, 89}, {{60, 81, 128, 0, 0, 217, 193, 54, 176, 1, 8, 75, 248, 39, 68, 81}, 89}, {{60, 81, 128, 0, 25, 153, 80, 26, 162, 71, 6, 110, 234, 194, 59, 157}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 39, 174, 49, 77, 219, 176, 76, 217}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 69, 208, 49, 224, 211}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 246, 215}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 229, 228, 47, 247, 16, 117, 39}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 239}, 89}, {{60, 81, 128, 0, 199, 69, 175, 113, 0, 194, 124, 3, 177, 174, 180, 27}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 121, 13, 178, 162, 34, 21, 135, 100}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 89}, {{60, 81, 128, 0, 0, 151, 213, 89, 170, 227, 42, 148, 226, 93, 62, 245}, 89}, {{60, 81, 128, 71, 236, 226, 155, 102, 252, 195, 226, 119, 165, 181, 158, 54}, 89}, {{60, 81, 128, 0, 0, 0, 0, 155, 201, 75, 164, 187, 245, 211, 204, 2}, 89}, {{60, 81, 128, 0, 94, 176, 105, 212, 27, 70, 75, 164, 228, 128, 199, 189}, 89}, {{60, 81, 128, 0, 0, 11, 73, 37, 59, 209, 130, 160, 90, 162, 232, 37}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 89}, {{60, 81, 128, 0, 0, 0, 12, 250, 18, 170, 208, 114, 196, 96, 128, 43}, 89}, {{60, 81, 128, 16, 219, 144, 223, 153, 151, 88, 72, 146, 205, 251, 117, 131}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 190, 108}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 32, 28}, 89}, {{60, 81, 128, 0, 0, 25, 69, 207, 51, 6, 181, 189, 133, 58, 176, 91}, 89}, {{60, 81, 128, 0, 0, 0, 148, 186, 23, 85, 170, 82, 12, 8, 142, 68}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 125, 193, 171, 115, 236}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 209}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 124, 53, 140, 104, 199}, 89}, {{60, 81, 128, 0, 0, 235, 67, 53, 79, 56, 58, 63, 121, 112, 86, 122}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 138}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 206, 88, 152}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 167}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 173}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 177}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 143, 253}, 89}, {{60, 81, 128, 0, 0, 0, 0, 245, 102, 213, 248, 233, 240, 8, 186, 136}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 229, 27, 36, 199, 110, 40}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 60}, 89}, {{60, 81, 128, 0, 0, 0, 0, 45, 79, 175, 144, 19, 98, 71, 70, 41}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 27, 55, 10, 136, 126}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 123, 192, 71, 238, 201, 245}, 89}, {{60, 81, 128, 0, 26, 51, 17, 231, 43, 226, 58, 70, 50, 121, 105, 29}, 89}, {{60, 81, 128, 246, 51, 237, 121, 180, 146, 83, 145, 85, 230, 99, 145, 121}, 89}, {{60, 81, 128, 0, 0, 0, 242, 248, 194, 26, 158, 81, 12, 45, 179, 244}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 18}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 89}, {{60, 81, 128, 0, 89, 129, 3, 198, 86, 209, 232, 18, 64, 80, 235, 179}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 58}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 229, 35}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 198}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 14, 124, 39, 46, 86, 131, 137, 26}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 148, 191}, 89}, {{60, 81, 128, 0, 0, 0, 180, 217, 134, 23, 238, 58, 73, 188, 196, 16}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 134, 238, 45, 8, 148, 131, 41, 155}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 30, 229, 85}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 108, 182}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 254, 6}, 89}, {{60, 81, 128, 0, 0, 0, 0, 68, 200, 131, 76, 227, 61, 76, 241, 28}, 89}, {{60, 81, 128, 0, 0, 127, 157, 190, 187, 113, 28, 47, 140, 215, 31, 28}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 89}, {{60, 81, 128, 0, 0, 0, 0, 150, 34, 72, 96, 99, 202, 175, 99, 234}, 89}, {{60, 81, 128, 0, 0, 183, 5, 148, 12, 193, 156, 101, 130, 233, 177, 19}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 16}, 89}, {{60, 81, 128, 0, 221, 162, 61, 61, 153, 172, 228, 166, 149, 205, 0, 108}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 125, 214, 209, 106, 127, 137, 108, 80}, 89}, {{60, 81, 128, 0, 0, 0, 0, 33, 229, 104, 127, 208, 209, 115, 93, 2}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 89}, {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 226, 101}, 89}, {{60, 81, 128, 0, 0, 231, 61, 247, 2, 174, 61, 227, 178, 131, 237, 155}, 89}, {{60, 81, 128, 0, 0, 0, 20, 214, 128, 45, 124, 154, 138, 139, 53, 33}, 89}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 171, 36}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 132}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 193, 206, 156}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 76, 19}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 199}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 233, 66, 14, 176}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 231, 198}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 149, 194, 209, 17}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 240, 66, 158}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 78}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 31, 20, 103, 159}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 87, 223}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 126, 226}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 95, 55, 151}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 92, 86, 51}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 118}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 132, 85}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 154, 213, 104, 169}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 93, 192}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 6}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 185}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 248, 126, 82}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 193, 235, 181, 176}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 250, 166, 246}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 236, 254, 153, 140}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 255, 180, 81}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 132, 249, 96}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 117, 148, 247, 137}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 233, 19, 179}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 208, 172, 167}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 179, 197, 193, 21}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 249}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 117}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 101, 247}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 122}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 245}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 246}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 157, 162}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 199}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 3, 199, 238, 206}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 183, 66, 227}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 123, 101, 101, 11}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 250, 23, 252}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 174, 196, 250, 237}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 133, 86}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 253, 180}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 16, 125, 112, 11}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 249, 235, 96, 47}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 88, 239}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 2, 220, 149, 238}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 35, 1, 132}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 22, 161, 91}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 170, 63, 1, 231}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 164, 66}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 109, 152}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 232, 148, 85}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 135, 153}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 19, 168, 147}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 61, 182, 160, 106}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 82, 43}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 151, 154}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 188, 138, 84, 92}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 72}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 180, 47}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 231}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 222, 133, 160}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 173}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 129, 212, 136}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 249}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 150, 101, 49, 145}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 67}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 117, 148}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 7, 155}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 120}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 62, 17, 104}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 137, 236}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 228, 10, 183, 70}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 168, 221, 231, 139}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 220, 123}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 55, 86, 246}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 248, 72, 247}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 22, 169, 132, 55}, 77}, {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 235}, 77}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 61}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 214, 228, 177}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 21}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 87, 9, 114}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 21, 230}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 110, 56}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 210}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 14}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 148}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 141, 192, 112}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 178, 128}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 247}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 156, 148, 48}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 227, 185}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 227, 220, 53, 140}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 125, 91, 87}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 147, 19}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 175}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 131, 168}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 42, 164}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 22, 177}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 107, 2, 92}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 199, 79}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 3, 198, 3}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 165, 118, 232}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 144, 253}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 114}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 112, 3, 72, 184}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 127, 62, 206}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 46, 94}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 128, 167, 189, 228}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 134}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 123, 204}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 52, 110}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 17, 147, 176, 96}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 139, 133, 144}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 176}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 94, 145, 55}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 100, 216, 199}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 196}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 55, 173}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 55, 249, 54}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 233}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 81, 81}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 141}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 170, 130}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 28, 245}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 13}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 216, 247, 232}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 200, 17, 39}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 116, 9, 170}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 247, 2, 40}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 97, 188, 77}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 35, 248}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 214, 172}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 74, 63, 145}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 80, 171}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 87}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 242, 239}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 123}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 123, 141, 96}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 226}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 201, 128}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 139, 64, 115, 167}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 34}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 2}, {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 139}, 2}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 83, 150, 244, 190, 43, 65}, 75}, {{168, 252, 0, 0, 0, 46, 247, 233, 32, 224, 124, 0, 250, 138, 7, 31}, 75}, {{168, 252, 0, 0, 0, 0, 46, 232, 152, 58, 54, 16, 138, 43, 106, 105}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 122}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 234, 50}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 70, 131}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 194}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 191, 139, 56, 151, 93, 80, 224}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 220}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 238}, 75}, {{168, 252, 0, 0, 0, 183, 226, 74, 109, 13, 131, 180, 151, 69, 164, 51}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 120, 5, 75, 198, 26, 211, 73, 24}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 203, 133}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 149, 147, 28, 227}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 49, 99, 92, 231, 160, 52, 15}, 75}, {{168, 252, 0, 0, 0, 0, 0, 154, 81, 207, 203, 140, 216, 72, 28, 157}, 75}, {{168, 252, 0, 0, 0, 0, 194, 30, 94, 52, 78, 4, 128, 245, 239, 31}, 75}, {{168, 252, 0, 0, 154, 126, 232, 145, 155, 6, 10, 185, 101, 233, 209, 252}, 75}, {{168, 252, 0, 0, 0, 8, 6, 13, 3, 59, 230, 140, 73, 65, 240, 196}, 75}, {{168, 252, 22, 193, 157, 101, 109, 140, 92, 4, 66, 129, 132, 134, 15, 53}, 75}, {{168, 252, 0, 0, 223, 42, 229, 158, 1, 170, 82, 235, 174, 30, 200, 71}, 75}, {{168, 252, 0, 0, 0, 0, 0, 74, 105, 239, 81, 134, 6, 213, 72, 147}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 130}, 75}, {{168, 252, 0, 219, 146, 40, 69, 227, 136, 73, 140, 104, 230, 65, 60, 46}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 243, 134}, 75}, {{168, 252, 0, 0, 0, 0, 0, 231, 30, 216, 92, 129, 122, 219, 135, 134}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 30, 41, 135, 92, 156, 92, 69, 71}, 75}, {{168, 252, 0, 0, 0, 241, 60, 125, 167, 173, 142, 142, 193, 193, 62, 201}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 124, 28, 39}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 203, 15, 201, 137, 149, 240, 179, 98}, 75}, {{168, 252, 0, 0, 0, 0, 0, 37, 18, 139, 160, 133, 5, 183, 35, 39}, 75}, {{168, 252, 0, 250, 79, 119, 64, 108, 164, 159, 102, 6, 77, 219, 126, 128}, 75}, {{168, 252, 0, 0, 0, 0, 0, 194, 20, 156, 192, 161, 85, 91, 102, 90}, 75}, {{168, 252, 0, 0, 0, 0, 40, 1, 191, 21, 241, 117, 48, 212, 253, 190}, 75}, {{168, 252, 0, 92, 248, 220, 83, 93, 66, 14, 94, 69, 207, 10, 146, 24}, 75}, {{168, 252, 0, 0, 0, 0, 0, 132, 57, 109, 13, 8, 101, 20, 139, 41}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 126, 41, 162}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 168, 150, 96}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 82, 102, 19, 234}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 6, 218, 23}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 19, 196, 182, 152, 169, 236, 136, 43}, 75}, {{168, 252, 0, 0, 0, 0, 138, 170, 88, 41, 237, 203, 43, 148, 220, 215}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 150, 104, 134}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 186, 227, 109, 10, 254, 205, 85, 252}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 25, 152, 197, 199, 243, 52, 206}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 201, 156, 106}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 76}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 192, 101, 164, 12}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 61, 115, 194, 127, 115, 188, 139}, 75}, {{168, 252, 0, 0, 0, 0, 0, 124, 126, 91, 57, 62, 177, 245, 103, 207}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 84}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 94, 148, 211}, 75}, {{168, 252, 0, 0, 0, 0, 129, 44, 54, 125, 245, 71, 122, 33, 112, 8}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 145}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 21, 211, 142, 189, 1, 175, 181}, 75}, {{168, 252, 0, 0, 253, 33, 164, 54, 40, 227, 41, 63, 38, 122, 80, 190}, 75}, {{168, 252, 0, 0, 0, 0, 26, 249, 216, 63, 229, 231, 143, 231, 104, 187}, 75}, {{168, 252, 0, 0, 0, 0, 0, 159, 83, 144, 27, 72, 141, 113, 59, 19}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 118, 130, 80}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 193, 85, 220, 94, 176, 86, 40, 184}, 75}, {{168, 252, 0, 0, 45, 221, 116, 170, 5, 146, 34, 170, 145, 49, 183, 23}, 75}, {{168, 252, 0, 0, 0, 0, 90, 183, 171, 182, 175, 221, 154, 82, 115, 21}, 75}, {{168, 252, 0, 0, 0, 72, 97, 84, 1, 41, 245, 117, 222, 179, 179, 11}, 75}, {{168, 252, 0, 0, 0, 49, 41, 227, 248, 25, 160, 91, 225, 114, 30, 163}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 105, 34, 40, 103, 150, 173}, 75}, {{168, 252, 4, 230, 19, 14, 206, 182, 243, 3, 110, 217, 235, 10, 152, 84}, 75}, {{168, 252, 0, 0, 0, 246, 49, 143, 103, 108, 90, 12, 38, 224, 40, 164}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 75}, {{168, 252, 0, 0, 0, 0, 0, 45, 130, 248, 122, 129, 145, 194, 91, 23}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 184, 118, 201, 36, 248, 194, 208}, 75}, {{168, 252, 0, 0, 183, 1, 122, 220, 175, 187, 141, 196, 95, 1, 83, 50}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 152, 234, 16, 188, 1, 156, 60}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 95, 130, 140, 34, 211, 12, 142, 121}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 204, 125, 231, 227, 24, 76}, 75}, {{168, 252, 0, 0, 0, 0, 0, 90, 11, 172, 65, 243, 95, 43, 62, 221}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 138, 128, 26, 147, 253, 17, 115}, 75}, {{168, 252, 0, 0, 0, 0, 152, 30, 232, 204, 112, 123, 46, 156, 230, 77}, 75}, {{168, 252, 0, 0, 64, 249, 147, 161, 49, 176, 215, 134, 176, 50, 141, 147}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 179, 235}, 75}, {{168, 252, 0, 0, 0, 0, 57, 90, 22, 187, 194, 87, 133, 233, 127, 105}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 109, 64}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 75}, {{168, 252, 0, 227, 15, 43, 59, 193, 137, 217, 39, 189, 96, 151, 177, 157}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 12, 80, 108}, 75}, {{168, 252, 0, 0, 0, 175, 63, 169, 241, 160, 220, 219, 96, 140, 167, 87}, 75}, {{168, 252, 0, 0, 170, 107, 255, 204, 219, 79, 120, 189, 237, 18, 63, 96}, 75}, {{168, 252, 0, 0, 0, 101, 227, 149, 232, 69, 189, 137, 106, 182, 252, 63}, 75}, {{168, 252, 0, 0, 0, 0, 229, 174, 231, 107, 177, 165, 129, 129, 58, 53}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 54, 150, 23, 137, 143, 26}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 58, 115, 240, 12, 110, 179, 39, 160}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 88, 249}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 41, 209}, 75}, {{168, 252, 0, 0, 44, 111, 186, 89, 255, 165, 161, 197, 11, 145, 34, 1}, 75}, {{168, 252, 0, 0, 0, 0, 0, 0, 0, 197, 45, 196, 9, 223, 175, 96}, 75}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 58, 182, 90, 229, 173, 203}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 188}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 185, 123, 163, 219, 195}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 103, 167, 104, 203, 254}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 8}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 120, 160}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 103, 48, 42, 94}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 189, 78, 33, 103, 107}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 183, 226}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 48, 93}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 38, 105, 24, 241}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 124, 41, 246, 204, 104, 199, 80}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 237, 178, 31, 123}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 41, 15, 247, 126, 160, 20, 204}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 150, 166, 156}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 47, 193, 33, 167, 254, 233, 152}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 94, 3, 70}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 111}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 118}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 156, 100, 164}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 70, 182, 166, 98, 251, 63, 40}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 174, 112, 57, 127, 144}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 198, 250, 41, 95}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 209, 181, 205, 245, 213, 166}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 72, 82, 241, 132, 109, 83, 17}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 137, 213, 172, 142}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 244, 225, 95}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 183}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 203}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 132, 171, 94, 179, 69}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 224, 52, 101}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 16, 151, 121}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 58, 103, 129, 250, 43, 74, 91}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 153}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 232, 54, 208, 226, 167, 208, 88}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 44, 46, 186}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 125, 175, 154, 166, 110, 28, 229}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 12, 7}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 153, 203, 76, 112, 252, 11}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 37, 153, 6}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 124, 205, 81, 197, 128, 91, 249}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 101, 18, 5}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 46, 214}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 115, 153, 159, 199, 111, 28}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 22, 73, 68, 18, 196}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 114}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 242, 59, 163, 229}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 190, 150, 13}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 219}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 51, 198, 116}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 106}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 131, 67, 99, 182, 218, 119, 124}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 41, 147, 164, 98, 60, 13}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 176, 198, 141, 162, 191, 63, 87}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 76, 197, 18, 151, 57, 25}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 46, 228, 72, 86, 71}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 212, 85, 214, 161, 103, 226}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 70, 244, 243, 25, 218, 123, 22}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 129, 124, 213}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 123, 2, 43}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 181, 99, 166, 214}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 46}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 208, 177, 123, 115}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 115, 168}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 196, 100}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 97, 100, 234, 120, 24, 122, 194}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 178}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 216}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 66, 92, 210, 208, 116, 137}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 238}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 11}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 75, 51, 11, 19, 104}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 77, 166, 165, 173, 198, 136}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 62, 20, 69, 145, 145}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 39, 156, 94, 251, 46, 33}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 189, 197}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 64, 99, 58, 146, 91, 139}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 3, 194, 176, 238, 209}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 180}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 244, 69, 107, 30, 45}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 238}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 126, 66, 32, 22, 98, 99, 234}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 34, 87, 136, 235}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 181, 233, 86, 23, 187, 251}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 162, 199}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 84, 190, 115, 173, 23}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 60, 186}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 90, 170, 183, 128, 204}, 18}, {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 35, 221, 178, 68}, 18}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 110, 60, 22, 234}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 136, 25, 79, 133}, 246}, {{212, 48, 214, 127, 78, 176, 142, 89, 144, 214, 230, 121, 146, 223, 59, 14}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 251, 162, 238, 192, 236, 200, 59}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 246}, {{212, 48, 214, 127, 78, 176, 0, 186, 40, 68, 212, 27, 231, 217, 171, 27}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 114, 93, 98, 244, 249}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 162, 165, 144}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 166, 52, 3}, 246}, {{212, 48, 214, 127, 78, 176, 0, 137, 64, 21, 145, 155, 199, 67, 214, 92}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 246}, {{212, 48, 214, 127, 78, 176, 29, 0, 29, 31, 228, 13, 5, 238, 194, 251}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 6, 142, 13, 167, 121, 151, 126}, 246}, {{212, 48, 214, 127, 78, 176, 0, 12, 171, 206, 243, 239, 16, 53, 79, 28}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 153, 46}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 194, 217, 172}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 110, 18, 3, 67, 47, 36}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 99, 175, 84}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 85, 54, 67, 98, 209}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 110, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 170, 225}, 246}, {{212, 48, 214, 127, 78, 176, 0, 6, 208, 176, 146, 44, 117, 101, 6, 118}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 30, 233, 95}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 133, 216, 254, 107, 244}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 222, 45, 41, 170, 10}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 203, 86, 122, 150, 192}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 127, 25, 43}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 176, 8, 56}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 209, 45, 122, 160, 250, 110}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 15, 86, 55}, 246}, {{212, 48, 214, 127, 78, 176, 14, 107, 125, 101, 233, 83, 249, 137, 196, 183}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 30, 76}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 14, 175, 31, 207, 250, 114, 167}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 232, 180, 141, 158, 127, 196}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 216, 106, 32, 172, 173, 41, 106, 156}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 194, 22, 250}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 43, 72, 55, 174, 144, 93, 74, 230}, 246}, {{212, 48, 214, 127, 78, 176, 0, 23, 10, 210, 46, 172, 248, 121, 56, 78}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 225, 22, 43, 115, 68, 239, 235}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 186, 150, 100, 85, 246}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 40, 75, 61, 27, 242, 202}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 162, 48, 190, 34}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 217, 29, 176, 176, 36, 160}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 194, 167, 99, 158, 127}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 36, 212, 18, 219, 127, 254, 251}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 246}, {{212, 48, 214, 127, 78, 176, 0, 50, 190, 183, 65, 141, 48, 200, 242, 68}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 1, 202, 211, 246, 191, 162}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 240, 81, 30, 32, 39}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 233, 224}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 195, 45, 217}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 35, 218}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 41, 79, 224, 242, 127}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 31, 72, 255, 45, 78}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 2, 53, 43, 13, 196, 1}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 232, 96}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 54, 137, 167}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 93, 95}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 89, 178, 228, 3}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 141, 173, 84}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 179, 128}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 112, 169, 144, 128, 230, 186, 71, 22}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 183, 255, 132, 99}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 38, 6, 54}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 146, 82, 0, 75, 203}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 99, 187, 59, 11, 139, 148, 245, 38, 59}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 138, 189}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 68, 137, 78, 227, 45}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 99, 211, 183, 67}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 206, 196, 169, 132, 85, 179}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 24, 253}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 193, 95, 80, 131, 255, 62, 185, 93}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 169, 251, 191, 226, 99, 154}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 157, 184, 167}, 246}, {{212, 48, 214, 127, 78, 176, 0, 188, 209, 161, 250, 81, 28, 54, 240, 81}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 100, 118}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 226, 186, 181, 17, 38}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 246}, {{212, 48, 214, 127, 78, 176, 0, 77, 8, 52, 229, 28, 176, 160, 211, 119}, 246}, {{212, 48, 214, 127, 78, 176, 0, 120, 63, 203, 101, 186, 4, 107, 63, 93}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 142, 116}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 65, 222, 120}, 246}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 213}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 11}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 160}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 134}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 242}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 164}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 109}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 3}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 119}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 230}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 31}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 14}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 185}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 51}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 108}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 111}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 197}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 175}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 75}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 102}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 62}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 101}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 3}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 47}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 69}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 57}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 184}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 116}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 117}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 93}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 170}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 10}, {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 112}, 10}, {{94, 200, 0, 0, 0, 0, 0, 214, 146, 92, 71, 1, 57, 211, 189, 39}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 98, 130, 92, 5}, 207}, {{94, 200, 0, 0, 0, 0, 209, 46, 69, 227, 136, 179, 120, 96, 179, 66}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 130, 4, 129, 36, 152, 219, 93}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 201, 52, 135, 186, 76, 59, 14, 122, 248, 21, 83}, 207}, {{94, 200, 0, 0, 61, 223, 131, 56, 242, 111, 159, 167, 235, 210, 146, 137}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 121, 9, 37, 102, 133, 137, 36, 113}, 207}, {{94, 200, 0, 0, 0, 223, 150, 227, 157, 247, 193, 119, 44, 12, 133, 181}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 213, 85, 64, 63}, 207}, {{94, 200, 78, 181, 60, 41, 84, 212, 218, 62, 112, 61, 247, 100, 194, 227}, 207}, {{94, 200, 0, 0, 0, 64, 78, 115, 244, 179, 144, 201, 15, 32, 44, 124}, 207}, {{94, 200, 0, 0, 168, 239, 126, 205, 135, 40, 11, 22, 89, 29, 194, 184}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 22, 252, 184}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 207}, {{94, 200, 0, 0, 0, 0, 106, 223, 121, 134, 49, 245, 8, 119, 2, 55}, 207}, {{94, 200, 251, 157, 94, 191, 57, 2, 8, 145, 78, 6, 158, 233, 153, 126}, 207}, {{94, 200, 0, 0, 211, 220, 223, 10, 138, 154, 195, 124, 79, 79, 110, 155}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 197, 182, 79, 199, 74, 214, 165}, 207}, {{94, 200, 0, 0, 0, 0, 12, 156, 137, 6, 96, 47, 213, 121, 111, 235}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 231, 141, 104, 225}, 207}, {{94, 200, 0, 89, 7, 103, 240, 237, 118, 190, 170, 41, 31, 233, 236, 100}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 192, 4}, 207}, {{94, 200, 0, 0, 66, 31, 187, 191, 118, 137, 171, 213, 152, 98, 213, 248}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 195}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 138, 187, 38, 198, 73, 163, 85, 28}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 115, 6}, 207}, {{94, 200, 0, 0, 0, 0, 0, 166, 204, 19, 1, 180, 178, 142, 100, 61}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 186, 91, 180, 195, 20, 101, 100}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 238, 52, 210, 83, 154, 151}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 112, 5, 175}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 136, 220, 135, 235, 8, 4}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 222, 23, 44, 177}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 17, 119, 17, 58, 1, 28, 146, 155}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 22, 218}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 135, 215, 156, 87, 126, 25, 181, 136}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 0, 25}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 82, 197, 237, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 245, 153, 48, 5, 94, 61}, 207}, {{94, 200, 0, 184, 172, 89, 52, 150, 167, 177, 138, 81, 82, 189, 210, 57}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 126}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 152, 135, 133, 14, 214, 40, 85}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 231, 21, 25, 155, 44, 9, 172, 206}, 207}, {{94, 200, 0, 0, 0, 0, 253, 209, 53, 81, 47, 183, 142, 207, 199, 248}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 102, 240, 86}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 196, 83, 236}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 62, 5, 47, 14, 184, 103, 35, 24}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 94, 107, 218, 150, 120, 109, 47}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 64, 226, 205, 204, 73, 202, 63}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 52, 9, 211, 30, 37, 74, 122, 76}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 75, 192, 130, 57}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 191, 108, 40, 92, 161, 24}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 125, 119, 71, 236, 54, 117}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 15, 119, 36, 244}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 162}, 207}, {{94, 200, 0, 0, 82, 43, 30, 104, 134, 247, 4, 248, 162, 174, 203, 43}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 47, 84, 86, 88, 100, 243, 11}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 70, 41, 14, 118}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 110, 56, 149, 162, 112, 129}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 123, 39}, 207}, {{94, 200, 0, 0, 0, 0, 0, 242, 248, 43, 248, 190, 227, 21, 240, 198}, 207}, {{94, 200, 0, 0, 179, 122, 203, 4, 10, 18, 61, 182, 42, 15, 234, 54}, 207}, {{94, 200, 0, 0, 0, 164, 210, 117, 90, 37, 237, 131, 222, 145, 132, 218}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 121, 63, 60, 98, 160, 94, 153, 162}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 204, 112, 194, 190}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 211, 250, 17, 188, 205, 234, 153, 63}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 105, 123, 246}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 18, 115, 109, 23, 166, 31, 58, 22}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 67, 70, 149}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 155, 232, 59, 199, 145, 44}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 58, 124, 88, 1, 169, 166}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 82, 194, 58, 161, 162, 150, 37, 164}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 231, 56, 47, 250, 186, 240}, 207}, {{94, 200, 0, 0, 0, 0, 0, 121, 121, 30, 90, 31, 188, 20, 129, 12}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 128}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 194}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 183, 103, 168, 8, 90, 32, 204}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 69, 60, 21}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 216, 250}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 78, 118, 9, 35}, 207}, {{94, 200, 226, 227, 223, 54, 65, 41, 177, 136, 149, 173, 97, 160, 226, 201}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 250}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 215, 162, 210, 207, 53, 148}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 6, 221, 55}, 207}, {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 40, 200, 69, 185, 133, 145}, 207}, {{94, 200, 0, 0, 0, 75, 110, 73, 200, 35, 50, 170, 161, 190, 218, 108}, 207}, {{94, 200, 0, 0, 0, 0, 148, 114, 247, 113, 119, 20, 198, 219, 108, 126}, 207}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 213}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 77, 204, 213, 128}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 79}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 14, 36}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 187, 119, 155, 110, 95}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 237, 121, 13, 84, 145}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 116, 76, 164}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 218, 104, 190, 71, 219}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 25, 185, 66, 126}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 180}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 144, 117, 3}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 196, 109, 54, 176}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 50, 135, 132, 127, 150, 70}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 146, 26, 143, 137}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 155, 190, 78, 197, 20}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 70, 24, 71, 213, 240, 69, 191}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 112, 242}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 50, 162, 188, 131}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 90, 194, 126, 183, 108, 152}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 45, 184, 151, 110, 218, 177, 19}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 106, 5}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 57, 82}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 44, 141, 98, 230, 98, 56}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 125}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 88, 16, 2, 196, 60, 131}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 23, 191, 247, 98, 169, 214}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 102}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 46, 35, 173, 91, 111, 122}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 50, 55, 201}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 106, 42, 113, 139}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 26, 226, 120, 24, 179}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 250, 43, 223, 218}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 214, 207, 208}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 149, 151, 25, 176}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 45, 163, 54, 23, 219, 226}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 52, 182, 112}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 82, 215, 77}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 165}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 191, 89}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 247, 128, 238, 240, 123}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 145, 239, 140, 187, 40}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 254, 186, 127, 6, 225}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 176, 168, 142, 239}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 90, 101, 236}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 90, 226, 32}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 247}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 27}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 50, 214}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 139, 119}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 173, 223, 158, 224, 106, 117}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 233}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 165, 187}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 243, 111, 134, 173, 4, 58}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 48, 37}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 90}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 194, 60}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 37, 85, 244}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 178, 175, 115, 28, 174}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 152, 233, 255, 130, 195}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 16, 69, 45, 87}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 219, 245, 231, 227, 250}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 94}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 181, 7, 246}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 12, 207, 239, 77, 70, 38}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 221, 200}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 197, 10, 220, 10, 253, 207}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 122, 123, 162, 129}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 121, 211}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 44, 157, 173, 166, 46}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 14, 216, 251, 102}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 61, 231, 97, 54, 45}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 135, 141, 42, 90, 250, 118}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 163, 20, 214, 115}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 99, 95, 51, 51, 20, 17}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 108, 154}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 141, 193, 194}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 142, 185, 78, 218, 178}, 41}, {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 174}, 41}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 250, 209}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 52, 199, 207, 95}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 43, 97, 19, 229}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 60, 198, 205, 41}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 222, 134, 14}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 19, 254, 143, 46}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 199, 50}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 207, 37, 113, 142}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 55, 56}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 62, 38}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 72, 174}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 85}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 200, 159}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 219, 218, 139, 12}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 93, 40, 253}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 165}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 220, 46, 141}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 200, 140}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 28, 57, 239, 13}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 213, 230, 181}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 211}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 71, 195}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 86, 225}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 198, 189}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 177}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 237, 192, 135, 229}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 241}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 245}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 6, 189}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 68}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 197, 113, 76}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 102}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 92, 153, 177, 114}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 162, 84}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 249}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 222, 95, 76, 92}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 93, 6}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 234, 158}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 39, 181}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 130, 10}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 98}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 105}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 229}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 255}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 129, 23}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 219, 20}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 125}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 102, 165, 200, 107}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 231}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 226, 26}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 40, 112, 2}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 156, 223, 159}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 217}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 234, 7, 219, 19}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 176, 38}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 203, 177}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 60, 5}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 232, 76}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 32, 191, 97}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 142, 96, 202, 86}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 184, 108, 204, 62}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 33, 92}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 165, 65, 204, 195}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 122, 236}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 247, 161}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 187}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 222, 21, 231, 32}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 193, 113, 59, 233}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 86, 142, 160, 154}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 210, 83}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 177, 110, 240}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 235, 199, 13}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 202, 193}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 117}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 132, 44, 207, 35}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 255, 241}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 39, 136, 80}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 52, 124, 152, 252}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 88, 110, 24}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 31}, 102}, {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 199}, 102}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 204}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 154}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 171}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 94}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 238}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 1}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 222}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 129}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 77}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 77}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118}, {{250, 128, 0, 0, 0, 0, 0, 131, 131, 146, 230, 141, 29, 232, 106, 32}, 146}, {{250, 128, 0, 0, 0, 0, 58, 5, 222, 97, 74, 196, 5, 132, 15, 82}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 246, 93, 98, 90}, 146}, {{250, 128, 170, 218, 217, 243, 215, 48, 149, 56, 192, 139, 195, 80, 235, 137}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 146}, {{250, 128, 185, 223, 12, 112, 172, 92, 188, 207, 36, 12, 230, 32, 208, 113}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 231, 28, 40, 200, 18, 248}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 226}, 146}, {{250, 128, 0, 0, 0, 0, 0, 193, 97, 188, 240, 213, 41, 50, 130, 55}, 146}, {{250, 128, 0, 0, 0, 0, 0, 203, 56, 221, 98, 145, 230, 128, 23, 125}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 69, 183, 111, 92, 174, 252, 143}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 64, 87, 212, 223, 19, 126, 76}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 123, 124, 103, 20, 83, 25, 102}, 146}, {{250, 128, 0, 0, 0, 0, 83, 195, 41, 254, 246, 183, 126, 201, 101, 7}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 203, 212, 144, 54, 12, 12, 12, 187}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 250, 114, 120, 60, 84, 226, 181}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 173, 215, 28, 102}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 119, 40, 207, 80, 59, 98}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 3, 54, 135, 110, 1, 237, 211, 138}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 241, 181, 197, 41, 132, 48}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 53}, 146}, {{250, 128, 0, 0, 0, 0, 0, 64, 131, 147, 0, 144, 140, 46, 141, 98}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 52, 78, 54, 248, 231, 34, 82}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 164, 41, 46, 253}, 146}, {{250, 128, 0, 0, 0, 0, 0, 247, 146, 197, 32, 135, 243, 133, 30, 107}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 62, 101, 235, 141, 113, 183, 210, 75}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 92, 8}, 146}, {{250, 128, 0, 0, 0, 0, 202, 149, 249, 204, 46, 132, 241, 142, 237, 6}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 105, 139, 10, 94, 24, 39}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 36, 5, 143, 126, 116, 178, 127, 152, 217, 144, 20, 40}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 158, 129, 169, 92}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 227, 243, 60, 244, 87, 55, 218}, 146}, {{250, 128, 0, 0, 0, 0, 0, 36, 220, 187, 93, 98, 191, 146, 77, 94}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 125, 168, 121, 205, 101, 170, 172, 72}, 146}, {{250, 128, 200, 61, 149, 102, 232, 174, 108, 157, 220, 9, 165, 154, 81, 19}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 194}, 146}, {{250, 128, 0, 143, 55, 121, 195, 118, 36, 223, 231, 233, 237, 7, 48, 67}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 77, 139, 38, 37, 33, 74, 99, 217}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 172, 208, 25, 28, 248, 254, 248, 92}, 146}, {{250, 128, 0, 0, 0, 248, 152, 55, 162, 3, 178, 124, 217, 81, 166, 126}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 250, 220, 149}, 146}, {{250, 128, 123, 185, 26, 168, 75, 199, 210, 130, 131, 166, 121, 230, 90, 46}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 146}, {{250, 128, 0, 0, 0, 0, 0, 215, 129, 162, 172, 141, 163, 148, 34, 159}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 15, 9}, 146}, {{250, 128, 0, 0, 0, 0, 0, 14, 207, 233, 167, 101, 73, 137, 126, 253}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 20, 246, 219, 124, 49, 78}, 146}, {{250, 128, 0, 0, 0, 0, 79, 7, 165, 213, 81, 167, 9, 142, 24, 227}, 146}, {{250, 128, 0, 0, 0, 58, 160, 20, 149, 73, 131, 167, 191, 255, 19, 48}, 146}, {{250, 128, 0, 232, 185, 37, 244, 132, 122, 115, 85, 80, 124, 24, 157, 250}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 215, 178, 155, 255, 17, 224, 169}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 245, 82, 236, 63, 107, 98}, 146}, {{250, 128, 0, 199, 92, 88, 38, 192, 62, 41, 142, 132, 21, 63, 54, 4}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 218, 173, 65, 235, 186, 179}, 146}, {{250, 128, 0, 0, 233, 249, 217, 103, 145, 134, 38, 130, 104, 183, 216, 78}, 146}, {{250, 128, 0, 0, 0, 250, 155, 133, 127, 189, 99, 6, 120, 133, 170, 54}, 146}, {{250, 128, 0, 0, 194, 179, 55, 130, 247, 77, 132, 236, 81, 101, 94, 151}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 139, 136, 69}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 105, 203, 171, 97, 26, 44, 101}, 146}, {{250, 128, 0, 0, 0, 119, 50, 27, 139, 154, 97, 95, 18, 12, 190, 190}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 209, 0, 190, 162, 237, 202, 175, 11}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 211, 251, 142, 160, 209, 20, 39}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 38, 191}, 146}, {{250, 128, 0, 0, 210, 245, 108, 55, 70, 250, 184, 86, 133, 122, 246, 99}, 146}, {{250, 128, 0, 78, 69, 33, 66, 104, 91, 118, 36, 45, 115, 8, 142, 87}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 88, 67, 239, 35}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 118, 199, 34, 189, 13, 154, 157}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 10, 58, 46, 133, 120, 200, 39, 3}, 146}, {{250, 128, 198, 91, 152, 86, 153, 102, 54, 111, 163, 3, 140, 31, 221, 230}, 146}, {{250, 128, 0, 0, 199, 82, 251, 83, 55, 56, 112, 221, 18, 69, 124, 75}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 126, 145}, 146}, {{250, 128, 0, 0, 0, 194, 22, 27, 184, 229, 70, 5, 19, 134, 118, 219}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 6, 61, 16, 33, 220, 128}, 146}, {{250, 128, 0, 92, 203, 93, 187, 148, 116, 1, 147, 81, 52, 114, 165, 61}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 39, 14, 138, 233}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 16, 164, 254, 163}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 139, 25, 212}, 146}, {{250, 128, 0, 69, 52, 155, 33, 67, 235, 95, 101, 191, 83, 188, 237, 140}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 197, 136, 21, 11, 9, 49, 253}, 146}, {{250, 128, 0, 0, 239, 230, 34, 83, 241, 39, 195, 72, 201, 195, 195, 106}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 62, 151, 198, 103}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 13, 170, 115, 80}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 212, 11, 46}, 146}, {{250, 128, 0, 0, 0, 0, 13, 124, 133, 145, 211, 163, 40, 186, 192, 217}, 146}, {{250, 128, 0, 0, 0, 149, 205, 227, 55, 130, 174, 103, 166, 39, 191, 31}, 146}, {{250, 128, 138, 153, 179, 210, 102, 1, 205, 208, 86, 226, 87, 45, 91, 78}, 146}, {{250, 128, 0, 246, 90, 82, 55, 137, 191, 116, 215, 4, 70, 190, 8, 195}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 235}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 251, 120}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 156, 118, 228, 66, 240, 199}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 12, 34, 246, 209}, 146}, {{250, 128, 0, 120, 54, 124, 183, 22, 77, 194, 140, 187, 223, 2, 185, 137}, 146}, {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 19, 57, 224, 30, 208, 114}, 146}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 50, 12}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 239, 236}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 190}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 195, 111}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 40}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 68, 61}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 162, 147}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 27}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 130, 32}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 233}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 60, 104}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 155}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 29, 102}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 42}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 47}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 81, 4}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 29, 175}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 253}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 213}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 212}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 218, 89}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 64, 239}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 13}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 36}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 222}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 117, 35}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 213, 84}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 52}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 196}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 191}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 121, 2}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 183}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 123}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 63, 198}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 248}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 72}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 6}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 184}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 147, 141}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 104, 92}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 119, 231}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 208}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 206}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 141}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 239}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 223, 67}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 203, 22}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 75, 232}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 20, 221}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 73, 243}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 42, 194}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 46}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 155}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 26, 166}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 191}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 200}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 155, 236}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 38}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 122}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 66, 224}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 135, 11}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 161}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 145}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 79, 242}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 50}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 182}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 169}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 234}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 41, 68}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 213, 99}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 85, 250}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 19, 30}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 244}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 16}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 129}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 13}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 118}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 126, 58}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 189}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 74}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 26, 229}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 20}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 141, 45}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 110, 40}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 218, 171}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 184, 19}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 204}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 31}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 118, 192}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 27}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 165}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 54, 145}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 156}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 20}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 174}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 169, 141}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 169}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 192}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 13}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 142, 21}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 5}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 191}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 237}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 174}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 152}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 243, 97}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 11}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 159, 106}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 133}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 71, 128}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 185}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 181}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 56, 222}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 185}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 231}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 5}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 96}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 82}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 6}, {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 31, 22}, 6}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 214}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 189, 9, 168, 108, 145, 117, 79, 25}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 146, 85, 110, 107, 118, 211, 242}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 128, 29, 97, 200, 36, 207, 167, 177}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 106, 82, 2, 224, 118, 7}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 115, 222, 108, 91}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 6, 37, 237, 202, 20, 9}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 129, 240}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 174}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 154, 121, 94, 106, 95}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 203, 105, 14, 20, 112, 79}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 184, 10, 96, 83, 254}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 45, 86, 151, 118, 230, 124}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 243, 130, 239, 147, 7, 158}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 19, 227, 176, 195, 101}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 254, 211}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 123, 1, 102, 45, 189, 105, 1}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 5, 59}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 22, 33}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 194, 104, 67}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 231, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 180, 207, 128, 242, 132}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 146, 233, 147, 185, 86, 82, 67, 76}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 15, 76, 176, 12, 94, 178}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 229, 132}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 106, 37, 156, 145, 110}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 74, 94, 134}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 109, 1, 13, 246, 91, 181}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 194}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 78}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 41}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 128, 208, 102, 216, 168}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 139, 213, 98, 170, 2}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 195, 236, 119, 8}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 163, 143, 183, 54, 173}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 127}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 132}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 220}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 106, 8, 228, 176, 118}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 215}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 151, 152, 241, 57, 20, 229}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 218, 63}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 120, 58, 37, 21, 154, 111}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 197, 83, 16}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 18, 112, 92, 46, 243, 103, 147}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 59, 179, 19}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 197, 92, 21}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 32, 221, 241, 97, 67, 9}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 216, 2, 65, 101, 49, 154, 6, 74}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 198, 154, 14, 136, 57}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 133, 130, 202, 104}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 195, 168, 252, 87, 91, 167, 204, 53}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 84, 168, 12, 130, 252, 74, 61, 242}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 2, 121, 203, 170}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 227, 51, 154, 93, 101, 69, 201, 112}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 121, 111}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 159, 127, 61, 17, 131}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 65, 187, 116, 73}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 59, 214, 6, 152, 212, 254, 196}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 183, 60}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 69}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 89, 209, 147, 232, 23, 254, 153}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 1, 162, 137}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 99, 108, 175, 170, 138}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 75, 216, 27, 1, 112}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 113, 253, 90, 181, 227, 53, 152, 156}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 242}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 67, 128}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 53}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 20, 72, 183, 35, 16, 43, 15}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 12, 160, 216}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 242, 75, 200, 58, 143, 255}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 175, 254, 140, 131, 148, 188, 188}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 217, 117, 220, 126, 231, 70}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 199, 244, 55, 170}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 135, 60, 4, 245, 206, 27}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 203, 195, 134, 21, 242, 148}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 246}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 95, 12}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 59, 215, 21, 197, 253, 225}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 58, 241, 143, 213, 108, 29, 141}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 24, 38, 239, 100, 41, 156, 175}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 74, 227, 42, 13}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 55, 244, 116, 33, 78, 150, 66}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 158}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 231, 152, 120, 221, 109}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 35, 189}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 133}, 18}, {{137, 131, 191, 40, 72, 209, 74, 64, 34, 239, 8, 97, 72, 62, 214, 107}, 18}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 31, 46, 166}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 55, 192, 9}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 46, 120, 232, 112, 226, 181}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 2}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 37, 81, 235, 30, 106}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 91, 32, 190}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 117, 8, 24}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 52, 212, 62, 72, 163, 249, 148}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 64, 137, 28, 233, 122, 88, 224}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 197, 73, 22, 239}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 235, 105, 161, 169, 84}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 193, 213, 50, 36}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 63, 124}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 226, 176}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 66, 41}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 114, 16, 210, 224, 79}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 57, 241, 182, 85, 73}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 204}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 254, 246}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 186, 54, 227}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 55}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 149, 179, 68, 182, 222, 214, 36}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 6, 236}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 249, 235, 6}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 58, 75, 0, 193}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 68, 163, 234}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 209, 43, 72, 102, 247, 237}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 164, 104, 198, 18, 8, 66}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 62, 33, 251, 78}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 148, 118, 147}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 188, 67}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 229, 46}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 173, 161, 0, 140, 197}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 65, 52, 108, 179}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 38, 106, 123, 170}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 98, 109}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 169}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 236}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 21, 184, 114}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 37, 131, 222, 58, 27, 198, 159}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 23, 75, 224, 225, 204, 6, 72}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 111, 7, 215}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 222}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 242}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 41, 251, 73, 114}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 55, 6, 104, 172, 69}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 227, 171, 51}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 4, 33, 61}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 119, 24, 147, 50}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 2, 158, 154, 152, 93, 51, 123}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 91, 175, 159}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 195, 64}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 117, 223, 37}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 157, 6, 132, 116, 46}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 191, 201, 73, 226, 97}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 148, 145, 221, 242, 20}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 147}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 158, 97, 95, 77, 39}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 178, 54}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 73, 174}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 201, 210, 121}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 174, 24}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 144}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 202, 144}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 59, 104, 236, 199}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 228}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 184, 137, 62, 59, 162, 143}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 67, 116, 160, 83, 170}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 218, 229, 5}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 141}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 18}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 147, 184, 68, 19, 174}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 163, 136, 15}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 12, 196, 192, 77, 157, 92}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 241, 190, 186, 232, 85}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 73}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 146, 98, 74}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 188, 159, 127, 134, 88, 73, 187}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 151}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 112}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 188, 48, 130, 232}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 37, 101, 67, 24, 143}, 83}, {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 187, 16, 25, 88, 224, 110}, 83}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 52, 166, 212}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 159}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 253, 234, 109}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 37, 67}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 20}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 205}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 173, 86, 232}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 221}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 121}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 43, 69}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 112, 73}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 135}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 86, 216, 93}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 141, 71, 171}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 150, 23}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 66, 90, 199}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 197}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 3}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 181}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 182, 191}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 68, 238, 155}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 208, 79}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 59, 111}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 11, 45}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 67}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 79, 54, 92}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 30}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 19, 60, 226}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 168}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 78, 219, 90}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 91, 161, 189}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 136}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 174, 32, 212}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 175, 153}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 248}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 20, 223}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 21, 94, 232}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 26, 172, 39}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 237, 115, 9}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 201, 29, 236}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 171, 3}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 172, 123, 6}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 245}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 161}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 73, 203}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 4}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 123, 174}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 173, 206, 195}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 251, 13}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 119, 168}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 208}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 163}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 218, 156}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 235, 210}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 208, 248, 152}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 246, 37}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 13}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 106}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 214, 244, 74}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 254}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 107, 26}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 124, 234}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 145, 239}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 117}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 234}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 178, 209}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 17, 92}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 196, 133}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 135, 38}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 129}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 177}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 31}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 105, 67, 190}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 146, 22, 119}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 128, 144}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 177}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 56, 244, 253}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 165, 149}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 90}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 103}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 28, 248, 28, 145, 196}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 207, 201, 128, 138, 247, 76, 16}, 140}, {{7, 31, 148, 19, 0, 0, 0, 81, 160, 93, 122, 138, 213, 182, 249, 107}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 231, 58, 123, 141}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 172}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 150, 26}, 140}, {{7, 31, 148, 19, 0, 0, 0, 196, 93, 243, 50, 76, 146, 57, 0, 33}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 145, 9, 149, 195, 110, 26, 210, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 229, 235, 195, 146, 107, 117, 175}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 76, 190, 220, 85}, 140}, {{7, 31, 148, 19, 0, 131, 25, 103, 13, 232, 25, 204, 14, 236, 241, 67}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 213, 75, 78, 136}, 140}, {{7, 31, 148, 19, 0, 0, 204, 32, 220, 84, 255, 12, 237, 66, 188, 40}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 139, 201}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 108, 58, 3, 87, 64, 78, 92}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 112, 248, 100, 223, 144, 63}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 36, 48, 228, 26, 70, 64, 45, 61, 144}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 85}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 225, 222}, 140}, {{7, 31, 148, 19, 0, 14, 233, 247, 0, 105, 153, 238, 174, 28, 53, 11}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 235, 24, 182, 78, 140, 4, 112, 152}, 140}, {{7, 31, 148, 19, 0, 14, 21, 150, 91, 205, 205, 205, 92, 167, 144, 197}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 87, 186, 20, 167, 255, 163, 243}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 186, 128, 66, 50, 191, 164}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 210, 19, 71, 87}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 101, 48, 14, 139}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 84, 194, 42, 142, 8, 235}, 140}, {{7, 31, 148, 19, 0, 0, 168, 182, 139, 24, 231, 102, 217, 51, 175, 177}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 42, 241}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 77, 169, 27, 172, 22, 133}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 167, 2, 212, 169, 87, 217}, 140}, {{7, 31, 148, 19, 0, 0, 0, 210, 110, 87, 14, 232, 56, 23, 169, 196}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 29, 86}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 35, 92, 54, 141, 166}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 220, 30, 46, 233, 126, 210, 72, 238}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 33, 139, 141, 47, 8, 35, 203}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 101, 104, 86, 242, 57, 155}, 140}, {{7, 31, 148, 19, 0, 120, 253, 187, 47, 23, 100, 29, 28, 201, 191, 26}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 252}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 92, 187}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 222, 92, 135, 89, 246, 55}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 46, 227, 132, 219, 205}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 166, 3, 131, 128, 168}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 115, 231, 86, 170, 5, 23, 193, 246}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 4, 242}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 114, 173}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 74, 220, 93, 177}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 47, 231, 105, 155}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 185, 4, 173, 105}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 112, 34, 97, 8}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 223, 253, 131, 25, 180}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 207, 36, 140, 114, 67}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 13, 239, 7, 49, 218, 150, 4}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 210, 232}, 140}, {{7, 31, 148, 19, 0, 0, 115, 80, 102, 91, 188, 141, 182, 229, 8, 63}, 140}, {{7, 31, 148, 19, 0, 156, 131, 71, 164, 52, 111, 26, 165, 162, 93, 34}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 69, 189}, 140}, {{7, 31, 148, 19, 0, 0, 0, 175, 226, 252, 122, 177, 45, 66, 105, 217}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 7}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 162, 207}, 140}, {{7, 31, 148, 19, 0, 149, 193, 134, 14, 76, 3, 189, 66, 35, 241, 148}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 105}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 140}, {{7, 31, 148, 19, 0, 1, 115, 70, 193, 231, 239, 191, 255, 246, 184, 88}, 140}, {{7, 31, 148, 19, 0, 0, 0, 13, 204, 150, 251, 98, 101, 203, 12, 85}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 192, 104, 184, 93, 212}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 151}, 140}, {{7, 31, 148, 19, 0, 0, 203, 23, 44, 233, 25, 34, 127, 210, 213, 249}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 111}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 77, 82}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 15, 61, 166, 190, 123, 238}, 140}, {{7, 31, 148, 19, 0, 0, 0, 89, 62, 85, 188, 161, 48, 217, 98, 118}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 65, 157, 72, 49, 85, 60, 44, 82}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 183, 220, 30, 90, 108, 130, 178}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 184, 13, 32, 231, 100}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 94, 81, 254, 66, 143, 209, 104, 130, 0}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 29, 228}, 140}, {{7, 31, 148, 19, 0, 22, 67, 204, 167, 226, 229, 214, 219, 4, 92, 130}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 174}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 13, 226, 219, 102, 190, 103}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 234, 200, 188, 199, 135}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 208, 104, 244, 253}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 249, 169}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 164, 191, 230, 189, 144}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 178, 252, 151, 164, 78}, 140}, {{7, 31, 148, 19, 0, 0, 0, 127, 160, 218, 90, 220, 8, 66, 162, 186}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 129, 228, 173, 73, 140, 126}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 160, 149}, 140}, {{7, 31, 148, 19, 0, 0, 156, 111, 45, 4, 134, 243, 67, 178, 2, 116}, 140}, {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 189}, 140}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 139, 38, 230, 242, 227, 140, 228, 158, 186, 71, 102}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 138, 84, 82, 37, 195, 177, 90}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 73}, 3}, {{112, 0, 0, 123, 227, 90, 245, 151, 250, 43, 21, 91, 163, 56, 163, 57}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 160, 133, 78, 136, 253}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 215, 204}, 3}, {{112, 0, 57, 202, 145, 87, 209, 163, 93, 11, 82, 59, 95, 101, 1, 90}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 183, 63, 218, 68}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 210, 49, 106, 68, 194, 250, 178, 216, 48, 240, 208}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 187}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 38, 209}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 36, 114, 225, 197, 220, 78, 140, 231}, 3}, {{112, 0, 163, 116, 104, 86, 121, 184, 154, 13, 249, 225, 163, 89, 133, 10}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 3}, {{112, 0, 0, 0, 0, 0, 0, 28, 200, 123, 230, 114, 144, 141, 218, 226}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 30}, 3}, {{112, 0, 0, 165, 221, 91, 110, 197, 105, 50, 7, 165, 56, 138, 235, 98}, 3}, {{112, 0, 37, 6, 122, 62, 179, 111, 29, 248, 223, 62, 101, 165, 154, 55}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 213, 168}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 87, 66, 169}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 142, 19, 179}, 3}, {{112, 123, 147, 4, 110, 231, 73, 55, 124, 159, 120, 148, 23, 110, 188, 117}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 225, 21, 213, 68, 74, 198, 135, 41}, 3}, {{112, 0, 0, 0, 0, 250, 189, 45, 216, 237, 244, 187, 145, 28, 16, 27}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 235, 137, 136}, 3}, {{112, 0, 0, 24, 141, 105, 167, 47, 117, 234, 150, 46, 99, 91, 184, 226}, 3}, {{112, 0, 0, 0, 0, 0, 52, 66, 4, 142, 55, 250, 69, 88, 177, 202}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 48, 102, 198, 139, 127, 86, 105}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 205, 104, 9, 116, 133}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 88, 28, 57, 209}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 131, 165, 10, 98}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 194}, 3}, {{112, 0, 0, 0, 192, 171, 40, 106, 35, 68, 116, 201, 128, 8, 139, 126}, 3}, {{112, 0, 213, 220, 27, 138, 186, 97, 34, 86, 166, 26, 62, 32, 24, 149}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 245, 106, 101, 254}, 3}, {{112, 0, 0, 194, 150, 118, 78, 75, 233, 107, 246, 198, 59, 205, 147, 167}, 3}, {{112, 0, 0, 112, 20, 95, 205, 186, 182, 217, 171, 26, 201, 73, 105, 35}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 196, 151, 226, 87, 217, 77, 34, 84}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 141, 169, 219, 250}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 203, 28, 103, 7, 210}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 88}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 139, 233, 212, 63}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 48, 84, 126, 248, 73, 211, 77}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 90, 1}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 1, 86, 231, 27}, 3}, {{112, 0, 0, 0, 0, 134, 28, 162, 125, 24, 13, 247, 155, 171, 5, 244}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 3}, {{112, 0, 0, 0, 0, 0, 81, 91, 108, 252, 156, 176, 227, 18, 27, 253}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 220, 68, 217, 107, 31, 89, 18, 83, 17, 26, 89, 5, 78, 223}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 252}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 98, 141, 162, 233, 218, 115, 135, 211, 136, 30}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 78, 169, 59, 141, 42, 30, 189, 97}, 3}, {{112, 0, 0, 0, 0, 0, 0, 42, 238, 123, 177, 81, 96, 10, 202, 178}, 3}, {{112, 27, 153, 64, 81, 250, 240, 230, 93, 187, 33, 35, 249, 206, 220, 207}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 111, 32, 127, 203, 136}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 73, 195, 190, 139}, 3}, {{112, 0, 97, 99, 112, 163, 6, 157, 181, 54, 109, 78, 45, 18, 49, 4}, 3}, {{112, 0, 0, 0, 135, 130, 248, 235, 231, 51, 122, 100, 145, 62, 95, 22}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 140, 197, 101, 178, 137, 161, 69, 224}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 135, 118, 134, 217, 231, 2, 61}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 127, 228, 241, 1}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 172, 72, 69, 40, 64}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 107, 110, 69}, 3}, {{112, 0, 114, 36, 251, 224, 173, 236, 134, 187, 72, 137, 251, 157, 103, 70}, 3}, {{112, 0, 232, 202, 160, 153, 192, 33, 172, 195, 196, 79, 63, 80, 128, 167}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 195, 194, 211, 166, 96, 103, 64, 241}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 67, 146, 85, 90, 20, 202, 143}, 3}, {{112, 0, 56, 95, 57, 212, 181, 7, 87, 92, 31, 130, 219, 57, 116, 86}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 18, 189, 119, 91}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 73, 142, 74, 25, 55, 87, 70}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 161, 110, 188}, 3}, {{112, 0, 0, 0, 0, 0, 0, 138, 37, 102, 142, 213, 46, 175, 107, 231}, 3}, {{112, 0, 0, 0, 0, 0, 228, 114, 216, 163, 61, 67, 69, 62, 57, 164}, 3}, {{112, 0, 0, 0, 0, 0, 130, 201, 215, 133, 186, 48, 151, 71, 159, 72}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 47}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 26, 187, 176}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 103, 241}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 89, 55, 217}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 141, 184}, 3}, {{112, 0, 0, 133, 201, 150, 142, 106, 180, 227, 29, 169, 164, 12, 11, 115}, 3}, {{112, 0, 221, 34, 87, 158, 34, 161, 58, 151, 106, 167, 187, 16, 60, 214}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 156}, 3}, {{112, 0, 210, 87, 187, 131, 53, 47, 126, 124, 211, 129, 172, 28, 252, 255}, 3}, {{112, 0, 0, 104, 179, 16, 72, 119, 244, 116, 192, 227, 82, 214, 14, 61}, 3}, {{112, 0, 0, 0, 0, 0, 0, 70, 138, 84, 34, 60, 247, 89, 153, 96}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 24, 176, 15, 47}, 3}, {{112, 0, 0, 0, 0, 0, 0, 183, 149, 35, 217, 195, 60, 175, 39, 162}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 233}, 3}, {{112, 0, 0, 69, 140, 243, 126, 100, 3, 40, 30, 9, 7, 127, 31, 163}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 66, 76, 243}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 26, 115, 124, 18, 111, 225, 159, 189}, 3}, {{112, 0, 0, 0, 0, 0, 0, 224, 169, 27, 44, 117, 149, 98, 96, 80}, 3}, {{112, 0, 0, 100, 30, 171, 113, 32, 68, 93, 244, 169, 63, 164, 150, 121}, 3}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 181, 38, 243, 217}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 28, 90, 101, 89}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 179, 191, 198, 90}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 137, 48, 137, 218}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 148, 238, 245, 95, 163, 149}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 26, 68, 236}, 31}, {{167, 50, 202, 179, 74, 146, 192, 72, 122, 46, 255, 252, 161, 219, 213, 21}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 95, 166, 21}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 60, 194, 185, 209, 162}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 90, 160, 216, 32, 162, 0, 40, 245}, 31}, {{167, 50, 202, 179, 74, 146, 192, 181, 252, 27, 101, 145, 171, 240, 84, 52}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 96, 201, 183, 10, 40, 14}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 43, 100, 174, 164, 250, 39, 209}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 195, 56, 232}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 87, 17, 87, 100, 125, 3, 121, 83, 152}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 255, 17}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 145, 172, 198, 118, 134, 120, 63, 128}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 193, 54, 220, 0, 79}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 48, 244, 157, 212, 38, 29}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 48, 248, 230, 196, 199}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 146, 103, 64, 18, 157, 130, 111}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 2, 144, 163, 208}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 123, 138, 18}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 180, 138}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 73, 173, 76, 31, 22, 186}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 71, 1}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 34, 107, 77, 212, 77, 171}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 152, 212, 200, 101, 184, 68, 107, 124}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 11, 234, 20}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 64, 40, 252, 194, 62, 100, 208, 243}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 158, 54}, 31}, {{167, 50, 202, 179, 74, 146, 192, 140, 177, 54, 97, 220, 64, 34, 0, 130}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 145, 116, 149, 210, 231, 129, 78}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 223, 113, 145}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 11, 225, 181, 253, 127, 178, 242, 72}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 173, 176, 50, 227, 205, 250}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 15, 138, 199}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 147, 132}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 75, 130, 71, 246, 173, 119}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 243, 118, 173, 217, 157, 81, 8, 144}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 185, 82, 61, 165, 189, 183, 207}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 125, 134, 2, 206, 58, 238, 70, 190}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 43, 78, 56}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 55, 170, 245, 128}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 225, 23, 144, 78}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 52, 173, 128, 193}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 143, 52, 11, 169, 72, 125}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 95, 132, 161, 104, 123, 124, 93, 29}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 117, 137, 255}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 129, 122, 101, 126, 78}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 191, 49, 16, 81}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 116, 6}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 156, 113, 29, 23, 144, 181, 143}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 142, 90, 117, 122}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 210, 188, 191, 46, 173, 161}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 202, 121, 79, 43, 143, 198, 170}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 75, 176, 57, 152, 15, 220, 92}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 225, 153, 244, 214, 105, 249, 161, 246}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 68, 158, 143, 220, 63, 141}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 22, 73}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 201, 43, 164}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 152, 246, 23, 201, 0, 213, 41}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 101, 113, 46, 114, 95, 233, 53, 82}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 104, 24}, 31}, {{167, 50, 202, 179, 74, 146, 192, 83, 17, 78, 78, 21, 152, 70, 199, 171}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 61, 103, 224, 203, 24, 190, 59, 93}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 137, 100, 125, 191, 65}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 84, 168, 167, 75, 206, 186}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 255, 239, 138}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 232, 221, 105, 243, 51, 76}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 31, 235, 102, 230, 0, 195}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 81, 33, 48, 192}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 187, 222, 173, 102, 223, 219}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 124, 66, 177, 234, 187, 239}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 18, 233, 157, 76, 117, 8}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 96, 68, 192}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 15, 214, 240, 66, 169}, 31}, {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 240, 44, 9, 63, 16}, 31}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 184}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 13}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 163}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 46}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 83}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 106}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 252}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 98}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 155}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 164}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 28}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 131}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 98}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 154}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 194}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 7}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 189}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 141}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 231}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 124}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 94}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 238}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 109}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 58}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 105}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 113}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 244}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 189}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 156}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 118, 114}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 102}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 77}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 242}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 34}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 83}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 3}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 251}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 101}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 184}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 221}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 204, 105}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 240}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 150}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 125}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 9}, {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 45}, 9}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 194, 97, 51, 51, 137, 145, 37, 57, 128, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 218}, {{128, 84, 145, 148, 213, 4, 38, 228, 7, 192, 158, 50, 42, 66, 61, 153}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 63, 40, 187, 145, 105}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 226, 159, 129}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 45, 1, 252, 97}, 218}, {{128, 0, 0, 144, 248, 68, 87, 196, 44, 3, 220, 183, 46, 199, 152, 77}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 56}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 112, 2}, 218}, {{128, 13, 144, 103, 103, 112, 96, 11, 72, 17, 83, 114, 192, 240, 152, 222}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 218}, {{128, 0, 0, 0, 194, 170, 23, 25, 178, 154, 163, 165, 24, 178, 156, 3}, 218}, {{128, 0, 0, 251, 38, 222, 228, 131, 201, 175, 25, 23, 2, 9, 116, 108}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 58, 226, 169}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 229}, 218}, {{128, 177, 41, 202, 55, 158, 47, 76, 194, 207, 73, 38, 27, 55, 33, 55}, 218}, {{128, 0, 0, 0, 0, 0, 87, 246, 212, 226, 116, 14, 221, 12, 238, 124}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 88, 69, 100, 133}, 218}, {{128, 0, 0, 195, 108, 92, 36, 51, 172, 1, 78, 101, 3, 27, 152, 241}, 218}, {{128, 129, 22, 104, 25, 221, 157, 41, 238, 244, 1, 108, 116, 106, 137, 188}, 218}, {{128, 0, 0, 0, 0, 94, 201, 18, 212, 242, 118, 97, 71, 213, 192, 19}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 60, 196, 84, 193}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 196, 23}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 167, 151, 38, 72}, 218}, {{128, 0, 0, 0, 0, 33, 209, 36, 62, 19, 199, 70, 77, 45, 57, 215}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 224, 56, 226, 145, 164}, 218}, {{128, 0, 0, 0, 156, 251, 233, 167, 4, 202, 204, 169, 212, 90, 131, 187}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 31, 90, 240, 45, 147, 246, 196, 241}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 44, 217}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 202, 39, 245, 1}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 91, 82, 109, 223, 180}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 8, 197, 186, 227, 64, 241, 122, 168}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 112, 154, 165, 60, 174, 142, 144, 119}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 107, 20, 44, 67, 37, 37, 1}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 41, 85, 17}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 59}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 228, 134, 79, 211, 255, 41, 229, 157, 202, 69, 59, 231, 28, 59, 41}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 158, 50, 56, 10, 14, 73, 48, 135}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 223}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 194, 77, 216}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 218}, {{128, 0, 0, 0, 0, 80, 199, 111, 201, 91, 31, 204, 206, 68, 185, 65}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 227, 20, 147, 74, 198, 236, 248, 147}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 93, 132, 159, 152}, 218}, {{128, 0, 0, 123, 228, 163, 28, 190, 99, 212, 103, 127, 43, 130, 220, 92}, 218}, {{128, 0, 0, 0, 0, 37, 246, 219, 191, 73, 125, 212, 128, 253, 172, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 218}, {{128, 0, 0, 0, 0, 0, 0, 92, 166, 158, 100, 23, 105, 169, 62, 14}, 218}, {{128, 0, 0, 0, 0, 164, 145, 147, 188, 21, 78, 149, 35, 65, 130, 201}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 23, 198, 33, 200, 115, 48, 207, 54}, 218}, {{128, 0, 0, 0, 0, 78, 208, 171, 80, 180, 248, 154, 57, 40, 48, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 60, 126, 249, 126, 164, 187, 98, 240, 228}, 218}, {{128, 0, 69, 209, 89, 63, 145, 88, 58, 1, 218, 184, 38, 189, 207, 130}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 26, 252, 60, 57, 174, 167, 71}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 35, 181}, 218}, {{128, 0, 0, 0, 0, 0, 0, 146, 35, 71, 243, 10, 204, 120, 83, 238}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 23, 0, 73}, 218}, {{128, 111, 39, 225, 71, 11, 243, 226, 116, 230, 60, 36, 244, 91, 126, 187}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 172, 112, 14, 10, 196, 181, 96, 113, 167, 23, 41, 249, 219, 194}, 218}, {{128, 0, 82, 159, 61, 4, 145, 62, 175, 148, 83, 137, 157, 177, 1, 161}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 103, 25, 104, 222}, 218}, {{128, 0, 36, 131, 44, 69, 142, 20, 104, 152, 152, 255, 203, 125, 188, 78}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 147}, 218}, {{128, 0, 0, 157, 12, 79, 104, 199, 68, 160, 96, 216, 242, 43, 41, 154}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 181, 214, 115, 18}, 218}, {{128, 241, 148, 101, 65, 143, 108, 60, 229, 16, 225, 53, 223, 251, 252, 110}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 77}, 218}, {{128, 0, 0, 0, 0, 0, 0, 122, 249, 150, 37, 152, 154, 165, 94, 229}, 218}, {{128, 0, 96, 68, 41, 84, 95, 34, 228, 208, 108, 191, 87, 82, 197, 35}, 218}, {{128, 0, 0, 0, 0, 212, 174, 195, 105, 250, 212, 97, 185, 129, 94, 40}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 32, 246, 169, 145, 224}, 218}, {{128, 0, 0, 146, 114, 9, 184, 127, 121, 50, 45, 243, 136, 221, 232, 228}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 92, 196, 34, 209, 10, 112, 106}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 113}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 114, 20, 85, 161, 120, 137, 253, 158, 217, 98, 84, 116, 208}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 240, 186, 162, 80, 30}, 218}, {{128, 93, 213, 130, 252, 201, 32, 172, 245, 150, 172, 168, 32, 16, 26, 153}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 236, 160, 214, 84, 106, 55, 230, 75}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 152, 21, 23, 76, 0, 24, 162, 43}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 93, 116, 212, 28, 231, 79, 27, 218}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 217, 51}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 75, 107, 238, 168, 180, 39, 16, 245}, 218}, {{128, 0, 0, 0, 0, 0, 224, 199, 5, 170, 233, 92, 228, 13, 242, 141}, 218}, {{128, 0, 0, 216, 68, 210, 100, 119, 249, 11, 188, 138, 68, 175, 3, 192}, 218}, {{128, 208, 80, 68, 16, 28, 115, 64, 193, 164, 225, 186, 78, 234, 63, 24}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 84, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 105, 85}, 218}, {{128, 0, 0, 0, 0, 0, 26, 128, 76, 19, 165, 143, 170, 195, 79, 123}, 218}, {{128, 0, 0, 0, 0, 0, 184, 246, 32, 247, 23, 1, 181, 93, 138, 10}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 109, 166, 189, 127}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 230, 90, 26, 188, 255, 180}, 50}, {{156, 163, 215, 175, 71, 80, 0, 82, 228, 165, 147, 104, 254, 252, 240, 130}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 148, 215, 219}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 118, 127, 203, 251, 241, 185, 228, 9}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 166, 174, 88, 56}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 91, 156, 21, 155, 120, 227, 89}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 156, 67}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 198, 57, 152}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 144, 215, 100, 75, 69, 179}, 50}, {{156, 163, 215, 175, 71, 80, 0, 216, 117, 29, 186, 5, 77, 5, 196, 84}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 9, 118, 143}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 85, 9, 237, 109, 111}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 118, 13, 189, 152, 109, 83, 18}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 137, 200, 220, 240, 242, 72, 47, 119}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 20, 169, 159}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 173, 46, 116}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 120, 5, 153, 194, 44, 74}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 36, 197, 232, 24, 32, 191, 81, 176}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 79, 194, 66, 156, 252, 87, 20, 161, 6}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 238, 117}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 99, 86, 77, 88, 144, 80, 191, 226, 93}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 180, 115, 241, 23, 196, 68, 252}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 131, 171, 69, 141}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 147, 250, 34}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 73, 124}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 177, 30, 182, 10, 194, 41, 70, 29}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 62, 14, 168, 154, 254}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 113, 74, 21, 126, 24}, 50}, {{156, 163, 215, 175, 71, 80, 0, 5, 222, 89, 251, 17, 90, 234, 201, 19}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 118, 254, 230, 179, 91, 251, 181}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 191, 104, 152, 3}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 2, 61, 237, 11, 184}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 227, 176, 252, 178, 147, 194, 136, 86, 217}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 126, 235}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 92, 113, 233}, 50}, {{156, 163, 215, 175, 71, 80, 0, 224, 95, 187, 40, 241, 209, 155, 196, 30}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 144, 236, 230, 9, 61, 45, 108}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 17, 16, 53, 73, 233, 59, 52}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 16, 90, 185, 81}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 197, 157, 52, 234, 126}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 142, 238}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 117, 25, 105, 209, 34}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 97, 76, 143, 77, 203, 93, 7, 193}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 140, 134, 90, 101, 193, 9, 203, 30}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 235, 245, 185}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 169, 39, 20, 183, 246}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 39, 117, 118, 137, 231}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 178, 114, 233, 190, 157, 150, 232}, 50}, {{156, 163, 215, 175, 71, 80, 0, 210, 159, 63, 65, 65, 125, 99, 7, 139}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 77, 252, 250, 91, 47, 85}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 56, 12, 159}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 219, 16, 30}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 38, 136, 179, 49, 203, 238}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 105, 243, 181, 71, 155, 59, 255, 32}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 66, 168, 187, 196, 25}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 74, 183}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 205, 52, 33, 169, 23, 132}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 234, 149, 86}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 203, 79, 94}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 152, 5, 184, 28, 3}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 33, 45}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 86, 113, 171, 57, 227, 26, 71, 226}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 69, 199, 108, 93, 194, 242}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 152, 136, 225}, 50}, {{156, 163, 215, 175, 71, 80, 156, 203, 141, 3, 212, 143, 39, 101, 139, 243}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 28, 218, 133, 246}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 26, 77, 9}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 163, 119, 89, 13, 231}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 54, 249, 135, 133, 65, 132}, 50}, {{156, 163, 215, 175, 71, 80, 0, 18, 117, 95, 84, 194, 214, 78, 169, 122}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 204, 233, 182, 39, 94, 83, 60, 92}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 111, 123, 51}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 235, 144}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 115, 239, 135, 12, 56, 174, 52}, 50}, {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 76, 226}, 50}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 81, 241}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 129, 109, 174, 255, 19, 60, 48}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 209, 165, 243, 90, 76, 149, 231}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 7, 128, 173, 8}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 76, 3, 156, 78, 179}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 130, 167, 84, 200, 72}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 136, 209, 127, 169, 146, 1, 161}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 223, 47, 88, 240, 149, 215, 178}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 58, 52, 254, 39}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 39, 244}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 106, 95, 92, 133, 79, 64, 156}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 93, 108}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 4, 118, 207, 235, 214, 235}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 200, 55, 18, 13, 104, 94}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 212, 13, 192, 238, 115, 53, 148, 161}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 49, 30}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 224, 81}, 34}, {{67, 24, 151, 198, 242, 128, 0, 70, 40, 222, 91, 237, 194, 126, 11, 243}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 37, 83, 171, 112, 58}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 60, 115, 132, 240}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 158, 236, 211, 246, 144}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 141, 233, 143}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 44, 117, 55, 172}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 41, 70, 7, 156, 21, 170, 90, 107}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 158, 151, 175}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 153, 35, 117, 88, 140, 59, 197}, 34}, {{67, 24, 151, 198, 242, 128, 0, 226, 235, 235, 201, 191, 31, 214, 124, 224}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 112, 63, 60, 185, 128, 151, 222}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 27, 6, 222, 131, 40}, 34}, {{67, 24, 151, 198, 242, 128, 166, 166, 231, 126, 29, 102, 0, 52, 107, 93}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 196, 50}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 67, 47}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 66, 180, 87, 24}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 9, 122, 9, 0, 52, 116}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 100, 82, 36, 114}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 221, 206}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 120, 43, 242, 145}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 19, 247, 160, 241, 98}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 202, 135, 25, 9}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 170, 75, 182}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 65, 239, 237, 163}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 246, 34, 115}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 97, 128}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 17, 182, 31, 45, 3, 102, 117, 187}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 12, 166, 225, 64, 13, 42, 2}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 23, 251, 96, 4, 124, 240, 212, 70}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 4, 228, 89}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 99, 86, 20, 235, 45}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 154, 220, 14, 43, 188, 149, 121}, 34}, {{67, 24, 151, 198, 242, 128, 0, 134, 136, 190, 226, 143, 135, 108, 7, 113}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 151, 45, 101, 106}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 195, 54}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 110, 218, 186}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 191, 30}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 74, 240, 183}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 190, 48, 198, 13, 125, 202, 30, 28}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 185, 24, 106, 57, 42}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 24, 83, 82, 138, 221}, 34}, {{67, 24, 151, 198, 242, 128, 34, 116, 19, 4, 63, 207, 41, 181, 251, 17}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 202, 206, 5, 166, 201}, 34}, {{67, 24, 151, 198, 242, 128, 0, 105, 117, 158, 137, 140, 34, 45, 238, 143}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 79, 14, 20, 238, 246, 4, 45, 36}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 34}, {{67, 24, 151, 198, 242, 128, 0, 244, 149, 51, 207, 187, 86, 223, 137, 161}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 37, 194, 252, 119, 197, 24, 52, 150, 235}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 58, 183, 163, 92, 67, 246}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 253, 148, 185}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 18, 9, 83, 247}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 46, 143, 237, 218, 122}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 221, 217, 232, 112, 191, 61}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 171, 203, 208, 66, 216, 48, 213, 121}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 107, 114, 72, 28, 210, 110, 103, 221}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 138, 8, 192, 237}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 155, 38, 94, 122, 244, 86}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 63, 86, 93, 236, 137, 224, 157, 191}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 190, 137, 127, 56}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 59, 76, 19, 23, 34, 8}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 59, 165, 222}, 34}, {{67, 24, 151, 198, 242, 128, 0, 140, 158, 76, 168, 75, 247, 112, 86, 150}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 85, 74, 70, 65}, 34}, {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 15, 238, 136, 8}, 34}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 214, 18, 208}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 74}, 11}, {{134, 107, 128, 123, 127, 2, 151, 90, 250, 39, 185, 9, 195, 111, 244, 139}, 11}, {{134, 107, 128, 0, 0, 0, 212, 106, 26, 21, 19, 242, 235, 95, 120, 141}, 11}, {{134, 107, 128, 0, 0, 0, 0, 11, 237, 174, 32, 185, 1, 66, 197, 135}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 99, 172, 36, 96, 224}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 207, 218, 179, 113, 122, 104, 123, 77}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 242, 133, 249, 37, 74, 158, 111, 199}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 13, 176, 155, 138, 52}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 45}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 4, 57, 108}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 224, 219, 85, 240, 71}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 255, 86, 183}, 11}, {{134, 107, 128, 0, 0, 0, 0, 240, 156, 62, 132, 177, 238, 34, 129, 116}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 210, 229, 12}, 11}, {{134, 107, 128, 0, 0, 0, 0, 212, 125, 1, 139, 137, 138, 209, 36, 222}, 11}, {{134, 107, 128, 0, 0, 100, 26, 50, 220, 193, 109, 87, 241, 33, 251, 2}, 11}, {{134, 107, 128, 0, 0, 0, 0, 179, 225, 106, 239, 32, 163, 177, 177, 221}, 11}, {{134, 107, 128, 0, 0, 0, 0, 63, 46, 114, 84, 127, 200, 250, 149, 133}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 219, 113, 66}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 29, 47}, 11}, {{134, 107, 128, 0, 0, 117, 192, 161, 225, 231, 205, 78, 248, 182, 193, 206}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 14, 112, 121, 21, 191, 108}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 244, 62, 54, 65, 160, 11, 204}, 11}, {{134, 107, 128, 0, 22, 236, 20, 214, 48, 250, 249, 15, 13, 170, 202, 185}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 8, 151, 144, 154, 195}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 213, 244, 42, 42, 4, 47, 187}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 234, 208, 173, 35, 245}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 177, 185, 5, 10, 82, 6, 33, 156}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 11}, {{134, 107, 128, 0, 0, 0, 0, 241, 6, 0, 57, 230, 13, 142, 110, 207}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 113, 81}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 84, 143, 161, 149, 215, 236, 255}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 205, 57, 174, 71, 119, 21}, 11}, {{134, 107, 128, 0, 0, 0, 10, 152, 254, 59, 221, 128, 77, 193, 7, 50}, 11}, {{134, 107, 128, 0, 0, 0, 86, 229, 193, 95, 139, 147, 110, 140, 23, 24}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 224, 214, 160}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 87, 222}, 11}, {{134, 107, 128, 87, 183, 213, 31, 131, 156, 241, 101, 126, 146, 129, 140, 241}, 11}, {{134, 107, 128, 0, 118, 61, 199, 254, 94, 38, 95, 114, 240, 171, 182, 57}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 113, 127, 2, 231, 242, 127, 135, 45}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 28, 59}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 144, 199, 154}, 11}, {{134, 107, 128, 74, 190, 135, 202, 41, 13, 44, 16, 105, 41, 131, 102, 203}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 11}, {{134, 107, 128, 0, 0, 0, 0, 227, 237, 185, 181, 234, 84, 223, 29, 124}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 241, 228, 240, 187, 144, 254, 138}, 11}, {{134, 107, 128, 0, 0, 0, 0, 103, 246, 173, 24, 184, 182, 53, 5, 121}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 27, 40, 156, 206, 112}, 11}, {{134, 107, 128, 0, 0, 0, 0, 33, 116, 254, 108, 217, 120, 158, 233, 158}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 86, 186, 150, 54, 203, 91, 211}, 11}, {{134, 107, 128, 57, 129, 45, 122, 219, 76, 55, 112, 142, 134, 33, 128, 36}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 161, 176, 77, 198, 70, 42, 114, 150}, 11}, {{134, 107, 128, 0, 0, 80, 251, 132, 1, 217, 64, 181, 191, 55, 245, 183}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 253, 16, 30, 46, 64, 164, 186}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 43, 223}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 139}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 243, 76, 245, 89, 233}, 11}, {{134, 107, 128, 205, 210, 192, 172, 151, 170, 44, 225, 217, 5, 73, 127, 198}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 161, 5, 158}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 243, 30, 43, 218, 247}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 76, 202, 102}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 68, 52}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 34, 238, 169, 205, 161, 129}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 163, 84}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 246, 152, 85, 39, 236, 208, 47, 92}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 194, 238}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 237, 202, 236, 244, 103, 136}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 154, 76}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 33, 139, 97}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 112, 94}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 34, 215, 36, 251, 31}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 212, 153, 149, 72, 135, 197, 230, 240}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 152, 38, 196, 219, 86, 255}, 11}, {{134, 107, 128, 0, 0, 182, 96, 74, 255, 133, 221, 211, 89, 52, 245, 155}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 11}, {{134, 107, 128, 0, 207, 18, 229, 118, 78, 3, 170, 170, 186, 131, 132, 101}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 48, 119, 243, 83, 232, 38, 237, 92}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 36, 253, 99}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 51, 233}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{134, 107, 128, 0, 0, 0, 0, 58, 216, 176, 246, 151, 11, 99, 89, 225}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 18, 24, 17, 246, 229, 248, 236, 109}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 158, 58, 71, 119, 143}, 11}, {{134, 107, 128, 0, 0, 250, 126, 48, 120, 200, 78, 216, 169, 17, 54, 96}, 11}, {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 47, 157, 177, 82, 166}, 11}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 178, 45, 24}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 201, 97, 13, 66, 166, 1, 30}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 205, 213}, 71}, {{35, 0, 0, 0, 244, 103, 0, 185, 89, 138, 103, 236, 205, 72, 4, 90}, 71}, {{35, 0, 150, 51, 29, 242, 78, 27, 32, 161, 151, 51, 113, 157, 178, 28}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 238, 173, 53, 116, 245, 37, 105, 95}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 189, 219, 154, 20, 13, 53, 164, 48}, 71}, {{35, 0, 0, 0, 0, 113, 37, 92, 60, 123, 209, 255, 218, 140, 33, 140}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 119, 149, 39, 249, 218, 91, 138}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 14}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 13, 91}, 71}, {{35, 0, 0, 0, 0, 0, 246, 123, 132, 121, 155, 91, 30, 239, 179, 247}, 71}, {{35, 0, 0, 158, 241, 64, 247, 204, 123, 18, 227, 200, 34, 219, 101, 53}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 40, 85}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 6, 16, 60, 43, 60}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 240, 81, 47}, 71}, {{35, 0, 0, 0, 210, 109, 65, 149, 101, 74, 30, 245, 131, 35, 181, 50}, 71}, {{35, 0, 0, 0, 41, 207, 108, 230, 168, 45, 42, 220, 115, 237, 33, 179}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 126, 216, 203, 157}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 53, 208, 103, 4, 221, 66, 35, 152, 51, 100, 74, 70, 48, 213}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 59, 194, 19}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 34, 241}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 247, 37}, 71}, {{35, 0, 0, 0, 0, 0, 0, 150, 68, 81, 118, 229, 73, 4, 50, 88}, 71}, {{35, 0, 0, 78, 164, 119, 57, 87, 243, 43, 246, 37, 161, 38, 191, 205}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 12, 33, 186, 39, 234, 113, 31}, 71}, {{35, 0, 0, 0, 0, 0, 0, 28, 148, 7, 86, 4, 90, 236, 40, 39}, 71}, {{35, 0, 0, 242, 110, 186, 64, 21, 156, 110, 162, 121, 151, 161, 3, 200}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 168, 157, 223, 198}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 210, 142, 137, 80, 170, 199, 189, 70, 217, 225, 54, 88}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 141}, 71}, {{35, 0, 0, 0, 0, 0, 140, 104, 107, 18, 95, 184, 161, 88, 213, 225}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 102, 235, 98, 157, 115, 119, 180, 64, 187, 246, 53, 47, 20}, 71}, {{35, 0, 144, 213, 126, 72, 132, 167, 167, 13, 98, 18, 99, 144, 76, 148}, 71}, {{35, 0, 0, 0, 0, 0, 0, 94, 184, 165, 146, 49, 63, 142, 1, 219}, 71}, {{35, 0, 0, 0, 150, 194, 171, 15, 196, 68, 247, 164, 229, 49, 7, 241}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 158}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 94, 181, 168, 2, 126}, 71}, {{35, 0, 0, 0, 0, 0, 137, 222, 202, 133, 160, 197, 4, 110, 90, 80}, 71}, {{35, 0, 0, 0, 0, 0, 0, 114, 204, 132, 22, 119, 56, 80, 164, 156}, 71}, {{35, 0, 14, 108, 17, 139, 10, 59, 196, 102, 229, 134, 68, 113, 123, 169}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 172, 171, 26, 119, 135, 55, 197, 103, 126, 235, 169, 201}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 151, 30, 173, 172}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 65, 25, 32, 169, 217}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 225, 251, 72, 16, 34}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 13, 107}, 71}, {{35, 0, 0, 0, 0, 0, 224, 37, 133, 101, 121, 86, 239, 76, 113, 100}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 55, 117, 186}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 36}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 140, 215}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 194}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 0, 0, 0, 118, 66, 177, 66, 154, 119, 54, 78, 117}, 71}, {{35, 0, 0, 0, 0, 0, 117, 78, 184, 54, 183, 224, 9, 63, 21, 76}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 89, 212, 160, 47, 246}, 71}, {{35, 0, 0, 156, 83, 106, 129, 186, 65, 115, 84, 106, 1, 21, 68, 169}, 71}, {{35, 0, 117, 75, 77, 252, 114, 207, 92, 255, 36, 14, 58, 218, 90, 215}, 71}, {{35, 0, 109, 151, 234, 21, 100, 23, 136, 26, 107, 106, 164, 232, 162, 25}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 54}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 203, 84, 226, 67, 65}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 214, 90, 59, 174}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 213, 20, 86, 148, 220, 22, 139, 18}, 71}, {{35, 0, 0, 0, 0, 0, 157, 228, 230, 60, 8, 105, 201, 178, 174, 50}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 173, 223, 177, 198, 242}, 71}, {{35, 0, 0, 0, 250, 222, 49, 118, 188, 69, 250, 229, 244, 120, 103, 65}, 71}, {{35, 0, 0, 232, 149, 239, 53, 162, 2, 163, 139, 123, 229, 19, 49, 129}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 133}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 71}, {{35, 0, 0, 0, 0, 183, 8, 27, 42, 230, 30, 155, 34, 83, 25, 193}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 107, 41, 253, 11, 142, 183, 131, 212}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 107, 144, 240}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 81, 22, 180, 61}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 59, 118, 153, 96, 178}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 32, 108, 16}, 71}, {{35, 0, 0, 0, 0, 211, 214, 100, 197, 196, 161, 202, 82, 54, 169, 188}, 71}, {{35, 0, 0, 0, 111, 184, 200, 81, 151, 84, 218, 116, 111, 126, 6, 33}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 224}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 36, 189, 163, 185}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 39, 157}, 71}, {{35, 0, 0, 0, 0, 0, 135, 88, 129, 134, 224, 205, 149, 204, 123, 240}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 39, 222, 70, 24, 39, 141, 202}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 24, 114, 244, 96, 122, 1, 76, 198}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 181, 229, 161, 161, 254, 49, 74}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 17, 218, 177, 46, 207}, 71}, {{35, 0, 0, 0, 0, 0, 132, 113, 45, 227, 69, 79, 205, 46, 149, 78}, 71}, {{35, 0, 0, 0, 0, 0, 109, 4, 8, 180, 61, 6, 210, 189, 149, 84}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 192, 68, 230}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 35, 249, 175, 120, 255, 161, 181, 215}, 71}, {{35, 0, 0, 0, 0, 0, 0, 153, 57, 81, 172, 219, 121, 16, 223, 204}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 242, 126}, 71}, {{35, 0, 0, 0, 0, 0, 0, 0, 0, 218, 87, 62, 69, 44, 221, 183}, 71}, {{46, 196, 84, 0, 135, 159, 223, 247, 215, 193, 99, 69, 227, 94, 228, 227}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 27, 154}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 104, 53, 44, 198, 180, 185, 211, 158}, 146}, {{46, 196, 84, 0, 0, 0, 251, 247, 203, 216, 247, 74, 225, 43, 132, 66}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 244, 180, 43, 160, 39, 147, 164, 12}, 146}, {{46, 196, 84, 0, 0, 167, 240, 140, 111, 118, 226, 90, 192, 246, 139, 190}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 35, 108, 177, 9, 187, 2}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 151, 236}, 146}, {{46, 196, 84, 0, 0, 0, 0, 75, 168, 166, 15, 235, 175, 186, 89, 218}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 46, 53, 224, 52, 145, 6, 180, 143}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 99, 67, 15, 159, 55, 109}, 146}, {{46, 196, 84, 0, 0, 218, 252, 148, 56, 64, 155, 144, 216, 161, 10, 55}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 206, 76, 121, 89, 118, 164, 47, 224}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 237, 244, 114, 104, 171, 204}, 146}, {{46, 196, 84, 0, 0, 0, 211, 37, 253, 174, 82, 153, 46, 16, 28, 96}, 146}, {{46, 196, 84, 0, 0, 10, 219, 191, 119, 94, 206, 143, 130, 245, 21, 149}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 205, 36, 206, 180, 144, 85}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 87}, 146}, {{46, 196, 84, 0, 0, 0, 0, 92, 96, 92, 80, 210, 109, 180, 243, 120}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 155}, 146}, {{46, 196, 84, 0, 0, 0, 81, 253, 85, 196, 11, 158, 71, 190, 150, 81}, 146}, {{46, 196, 84, 0, 7, 246, 72, 251, 107, 13, 212, 226, 248, 134, 85, 88}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 7}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 146}, {{46, 196, 84, 0, 0, 0, 0, 27, 193, 175, 63, 37, 29, 69, 154, 210}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 21, 71, 113}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 51}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 181, 113, 185, 225, 57}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 106, 190, 100, 210, 170, 181}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 51}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 227, 94, 198, 221, 227, 177, 221, 74}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{46, 196, 84, 0, 44, 78, 131, 156, 190, 214, 180, 251, 116, 126, 101, 1}, 146}, {{46, 196, 84, 0, 92, 35, 105, 212, 233, 145, 202, 124, 140, 9, 54, 211}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 105, 179}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 48, 128, 178, 216, 190, 5, 220}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 236, 6, 140, 205, 92, 108, 87}, 146}, {{46, 196, 84, 0, 0, 0, 192, 146, 111, 108, 101, 63, 95, 103, 122, 54}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 103, 48, 236, 28, 110, 161}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 113, 149, 100, 162, 10, 200}, 146}, {{46, 196, 84, 0, 245, 132, 158, 133, 22, 241, 11, 24, 252, 194, 84, 149}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 113, 212, 84}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 20}, 146}, {{46, 196, 84, 0, 0, 0, 0, 131, 119, 166, 31, 65, 107, 157, 32, 9}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{46, 196, 84, 0, 0, 34, 87, 195, 224, 232, 212, 255, 173, 13, 180, 169}, 146}, {{46, 196, 84, 0, 0, 0, 206, 170, 200, 52, 143, 114, 63, 57, 58, 73}, 146}, {{46, 196, 84, 0, 0, 0, 61, 174, 206, 141, 206, 11, 55, 116, 137, 40}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 207, 90, 127, 157, 98, 130}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 219, 60}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 35, 60}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 140, 133, 145, 237, 230, 151, 87, 237}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 67, 77, 109, 241, 26, 1}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 251, 75, 238, 3, 152, 17, 4, 132}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 92, 149, 252, 6, 154, 225, 167, 68}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 22, 9, 49}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 242, 209, 71, 206, 161, 26, 193, 59}, 146}, {{46, 196, 84, 0, 0, 0, 228, 37, 2, 196, 115, 254, 92, 231, 157, 200}, 146}, {{46, 196, 84, 0, 0, 0, 0, 167, 88, 0, 92, 127, 175, 65, 86, 68}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 146}, {{46, 196, 84, 0, 0, 173, 11, 3, 102, 209, 119, 38, 65, 13, 60, 5}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 251, 169, 157, 222, 31, 215, 226}, 146}, {{46, 196, 84, 0, 0, 111, 160, 149, 232, 3, 218, 254, 67, 186, 161, 179}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 6, 201, 157, 15, 183, 20}, 146}, {{46, 196, 84, 0, 0, 0, 70, 230, 211, 147, 252, 201, 52, 118, 113, 201}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 248, 75, 5}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 219, 244, 81}, 146}, {{46, 196, 84, 0, 0, 0, 0, 218, 181, 50, 105, 153, 187, 255, 200, 156}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 228, 50, 59, 208, 98}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 57, 169, 143, 148, 21}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 98, 156, 235, 56, 214, 178, 127}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 214, 166, 230, 225, 10, 5}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 73, 68, 160, 246, 135, 108}, 146}, {{46, 196, 84, 0, 0, 0, 0, 143, 29, 81, 213, 255, 127, 254, 108, 154}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 53, 206, 48, 228, 192, 6, 192}, 146}, {{46, 196, 84, 0, 0, 0, 233, 113, 70, 50, 224, 55, 244, 13, 152, 144}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 6, 195, 41, 190, 27}, 146}, {{46, 196, 84, 0, 0, 0, 0, 237, 81, 184, 15, 194, 155, 161, 208, 8}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{46, 196, 84, 0, 0, 0, 106, 225, 38, 203, 17, 128, 103, 248, 219, 45}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 142, 226, 222, 34, 121}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 146}, {{46, 196, 84, 0, 0, 8, 76, 112, 87, 249, 43, 61, 242, 60, 199, 190}, 146}, {{46, 196, 84, 0, 0, 0, 7, 130, 21, 159, 238, 144, 253, 77, 233, 0}, 146}, {{46, 196, 84, 0, 0, 0, 251, 154, 172, 235, 213, 255, 213, 203, 0, 52}, 146}, {{46, 196, 84, 0, 0, 0, 182, 227, 53, 140, 100, 76, 62, 116, 177, 27}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 219, 132, 42}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 41, 83, 232, 169, 185, 12, 156}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 146}, {{46, 196, 84, 0, 0, 248, 194, 156, 239, 21, 143, 129, 109, 189, 211, 25}, 146}, {{46, 196, 84, 0, 176, 42, 171, 189, 31, 121, 61, 253, 46, 225, 121, 145}, 146}, {{46, 196, 84, 0, 164, 223, 239, 10, 25, 160, 154, 99, 180, 215, 187, 208}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 149, 63, 152, 47, 82, 174, 80, 9}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 228, 55}, 146}, {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 13, 2}, 146}, {{46, 196, 84, 0, 22, 84, 193, 180, 170, 32, 77, 238, 161, 24, 182, 115}, 146}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 249}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 123, 202, 210, 32, 208, 47, 17}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 217, 162, 238, 98, 81, 222, 30}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 114, 167, 16, 196}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 89}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 253, 246, 249}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 184, 230, 137, 121, 184}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 87}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 98}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 230, 121, 82, 238, 32, 83, 144}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 124, 104, 123, 96, 15}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 242, 194, 30, 96}, 143}, {{78, 157, 79, 70, 252, 0, 242, 140, 241, 200, 132, 136, 133, 16, 122, 234}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 197}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 101}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 10}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 150}, 143}, {{78, 157, 79, 70, 252, 0, 226, 242, 197, 114, 196, 22, 150, 26, 250, 104}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 195}, 143}, {{78, 157, 79, 70, 252, 0, 0, 204, 58, 140, 61, 28, 116, 40, 222, 253}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 229, 82, 72, 146, 133, 126, 89, 29}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 4, 79, 247, 229, 94, 242, 2, 191}, 143}, {{78, 157, 79, 70, 252, 0, 0, 199, 80, 215, 159, 45, 151, 74, 126, 17}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 245}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 167, 247, 122, 113, 132, 84, 123, 56, 73, 111}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 197, 177, 62, 108, 189, 215, 247}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 104, 20, 78}, 143}, {{78, 157, 79, 70, 252, 0, 0, 43, 163, 175, 109, 189, 14, 202, 184, 18}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 40, 176, 63, 158, 50, 234, 150}, 143}, {{78, 157, 79, 70, 252, 0, 226, 39, 25, 7, 9, 67, 220, 10, 46, 133}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 85, 232, 92, 222, 235}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 88, 212, 244, 122, 133}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 26, 228, 252, 187}, 143}, {{78, 157, 79, 70, 252, 0, 0, 91, 242, 27, 53, 244, 127, 226, 76, 227}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 137, 80, 40, 87, 197}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 139, 119, 141, 241}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 85, 63, 134}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 153, 32, 116, 61, 246, 225}, 143}, {{78, 157, 79, 70, 252, 168, 169, 49, 6, 87, 62, 84, 112, 17, 60, 65}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 135, 75, 25, 199, 110, 35}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 41, 190, 248, 54, 122}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 245, 224, 211, 25, 135, 24, 2}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 167}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 133, 108, 41, 227, 96}, 143}, {{78, 157, 79, 70, 252, 0, 185, 108, 31, 133, 240, 142, 68, 128, 178, 236}, 143}, {{78, 157, 79, 70, 252, 0, 149, 80, 70, 122, 158, 132, 153, 74, 32, 127}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 14, 93, 168, 137, 62, 206}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 151, 248, 217, 138, 20, 116, 114, 246}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 65, 217, 227, 164}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 244}, 143}, {{78, 157, 79, 70, 252, 0, 127, 55, 128, 215, 38, 79, 220, 5, 183, 106}, 143}, {{78, 157, 79, 70, 252, 0, 0, 95, 80, 112, 98, 222, 137, 229, 139, 138}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 105, 74, 81, 177, 49, 191, 156}, 143}, {{78, 157, 79, 70, 252, 0, 231, 51, 84, 212, 229, 219, 84, 11, 140, 183}, 143}, {{78, 157, 79, 70, 252, 0, 0, 69, 2, 95, 235, 12, 250, 149, 38, 183}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 104, 176, 164, 198}, 143}, {{78, 157, 79, 70, 252, 0, 20, 31, 162, 172, 98, 222, 110, 198, 59, 198}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 190, 116, 26, 57}, 143}, {{78, 157, 79, 70, 252, 0, 243, 240, 5, 71, 129, 203, 47, 94, 163, 218}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 148, 163, 158}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 242}, 143}, {{78, 157, 79, 70, 252, 0, 81, 47, 248, 163, 201, 242, 214, 22, 37, 123}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 136, 107, 72, 106, 76, 206, 3}, 143}, {{78, 157, 79, 70, 252, 0, 0, 191, 14, 247, 122, 179, 113, 141, 228, 5}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 93, 155, 241, 227, 197, 226, 17}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 158, 111, 234, 4, 218}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 89}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 209}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 64}, 143}, {{78, 157, 79, 70, 252, 0, 5, 184, 76, 250, 88, 172, 250, 77, 71, 161}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 51, 133, 181, 119, 124, 206, 112, 60}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 80, 113, 91, 244, 17, 52}, 143}, {{78, 157, 79, 70, 252, 0, 0, 119, 116, 78, 228, 6, 38, 106, 250, 149}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 60}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 184, 217, 93, 230}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 217}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 40, 242, 90, 117, 21, 206, 89, 188}, 143}, {{78, 157, 79, 70, 252, 0, 199, 136, 170, 71, 232, 180, 112, 158, 194, 167}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 148, 189, 161, 149}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 151}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 220, 139, 97, 218, 73, 135, 52}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{78, 157, 79, 70, 252, 0, 206, 177, 222, 214, 122, 180, 72, 40, 177, 229}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 165, 88, 28, 190, 141, 103, 170, 241}, 143}, {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 12}, 143}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 12}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 42, 73}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 198, 51}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 156}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 29}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 87, 202}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 133}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 205}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 11}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 194}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 201}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 22}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 93, 70}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 56, 184}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 184}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 118}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 225}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 51}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 144}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 131}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 185}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 39}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 58}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 34}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 55}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 154}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 43}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 174}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 44}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 94}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 224}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 6}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 25, 99}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 85, 230}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 73}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 39}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 157, 108}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 50}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 227}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 219}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 209}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 173}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 153}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 67}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 30, 83}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 2, 144}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 39}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 196}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 128}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 105}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 182, 113}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 228}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 47}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 250}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 236}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 135}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 151}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 179}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 116}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 100}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 104, 92}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 195}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 17}, {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 127}, 17}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 177}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 75}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 138}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 4}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 110}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 185}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 32}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 60}, {{128, 0, 0, 0, 0, 0, 119, 110, 98, 15, 242, 73, 95, 233, 118, 119}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 43, 172, 6}, 218}, {{128, 0, 0, 0, 0, 0, 37, 206, 21, 69, 22, 216, 123, 30, 126, 72}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 168, 184, 143, 31, 89}, 218}, {{128, 0, 0, 128, 199, 98, 2, 171, 87, 227, 116, 67, 187, 49, 192, 169}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 53, 155, 234, 227, 79}, 218}, {{128, 0, 63, 74, 0, 202, 41, 166, 81, 73, 178, 220, 189, 47, 131, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 201, 140, 247, 103, 84, 116, 9, 143, 51, 146, 14, 107, 2, 121, 205}, 218}, {{128, 0, 0, 0, 0, 0, 61, 193, 251, 24, 172, 144, 64, 26, 245, 169}, 218}, {{128, 148, 189, 154, 65, 75, 180, 107, 160, 121, 157, 144, 94, 210, 82, 251}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 234, 121, 57, 116}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 6, 34, 82, 39, 247}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 47, 182, 20, 84, 237, 50, 16, 79}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 218}, {{128, 0, 0, 0, 242, 43, 76, 11, 1, 172, 168, 27, 188, 10, 118, 32}, 218}, {{128, 0, 0, 0, 31, 80, 154, 4, 27, 26, 43, 192, 235, 164, 210, 214}, 218}, {{128, 0, 0, 159, 138, 137, 168, 90, 20, 150, 3, 238, 140, 236, 139, 65}, 218}, {{128, 204, 49, 77, 185, 229, 182, 74, 161, 92, 250, 143, 163, 86, 173, 165}, 218}, {{128, 0, 0, 0, 0, 189, 40, 41, 13, 236, 127, 115, 31, 163, 32, 187}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 93, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 196, 83, 186, 92}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 252}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 184, 93, 178, 0, 20}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 223, 158, 101, 162}, 218}, {{128, 0, 0, 145, 38, 179, 227, 114, 239, 72, 126, 184, 17, 57, 83, 221}, 218}, {{128, 0, 0, 0, 0, 0, 248, 134, 83, 199, 37, 124, 178, 242, 204, 30}, 218}, {{128, 0, 0, 0, 252, 11, 218, 106, 235, 44, 148, 85, 34, 232, 49, 232}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 84, 114, 94, 79, 12, 93, 153}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 85, 190, 65, 128, 237, 241, 199, 62, 227}, 218}, {{128, 0, 0, 139, 250, 76, 64, 143, 251, 219, 80, 15, 252, 245, 134, 193}, 218}, {{128, 0, 0, 0, 0, 0, 46, 234, 219, 146, 254, 229, 113, 251, 40, 35}, 218}, {{128, 0, 0, 0, 0, 191, 92, 137, 242, 10, 26, 69, 63, 169, 6, 236}, 218}, {{128, 0, 0, 0, 0, 0, 253, 203, 132, 241, 192, 85, 20, 35, 232, 208}, 218}, {{128, 0, 0, 0, 0, 0, 0, 35, 146, 73, 114, 52, 25, 93, 118, 94}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 44, 68, 56, 69, 57}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 201, 8, 48, 187, 19, 72, 151, 68}, 218}, {{128, 0, 0, 0, 216, 153, 59, 141, 231, 19, 158, 224, 109, 31, 240, 62}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 37, 46, 194, 167}, 218}, {{128, 0, 0, 0, 226, 250, 98, 212, 176, 17, 31, 91, 101, 15, 12, 200}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 163, 221, 175, 60, 34}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 20, 29}, 218}, {{128, 49, 211, 244, 71, 23, 129, 72, 4, 252, 72, 222, 230, 96, 201, 50}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 15, 103, 1, 214}, 218}, {{128, 0, 0, 31, 199, 54, 184, 45, 236, 238, 196, 57, 186, 212, 176, 85}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 195, 107, 19}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 98, 214}, 218}, {{128, 112, 236, 182, 112, 50, 221, 82, 242, 69, 227, 86, 109, 220, 255, 128}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 83, 66, 39, 225, 143, 100, 210}, 218}, {{128, 0, 90, 234, 231, 17, 111, 3, 236, 182, 252, 233, 131, 189, 199, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 207, 223, 11, 33, 167, 12, 71, 119, 174, 18, 206, 186}, 218}, {{128, 0, 0, 195, 83, 233, 53, 224, 219, 14, 225, 61, 17, 49, 61, 234}, 218}, {{128, 0, 0, 74, 91, 38, 189, 113, 106, 216, 198, 29, 144, 110, 106, 78}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 249, 149, 207}, 218}, {{128, 0, 229, 221, 202, 121, 95, 83, 27, 94, 151, 31, 129, 250, 227, 61}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 150, 77, 5, 228, 27, 243, 105}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 223, 93, 52, 61}, 218}, {{128, 0, 0, 0, 214, 42, 103, 40, 199, 216, 167, 44, 200, 168, 72, 98}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 79, 105, 71, 222, 86}, 218}, {{128, 0, 0, 0, 0, 0, 91, 5, 176, 234, 244, 48, 122, 23, 66, 104}, 218}, {{128, 0, 115, 198, 250, 40, 65, 7, 39, 52, 29, 85, 172, 240, 32, 25}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 115, 220, 84}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 85, 141}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 133, 26, 41}, 218}, {{128, 0, 0, 0, 0, 177, 159, 33, 1, 8, 94, 65, 98, 48, 125, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 190}, 218}, {{128, 0, 0, 0, 13, 27, 66, 158, 174, 21, 225, 13, 102, 251, 226, 54}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 229, 191, 206, 184, 199, 20, 156}, 218}, {{128, 0, 0, 0, 28, 121, 165, 34, 91, 146, 26, 187, 36, 29, 77, 251}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 180, 201}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 41, 254, 57, 67, 198, 60, 254, 200, 174, 36}, 218}, {{128, 0, 0, 0, 0, 192, 233, 84, 156, 29, 6, 129, 209, 133, 118, 40}, 218}, {{128, 0, 91, 77, 125, 140, 178, 177, 22, 77, 255, 94, 62, 144, 124, 75}, 218}, {{128, 86, 97, 250, 168, 244, 117, 193, 223, 127, 228, 53, 13, 219, 20, 35}, 218}, {{128, 0, 0, 0, 0, 0, 0, 18, 32, 3, 8, 60, 146, 54, 233, 186}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 30}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 82, 121, 216}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 173, 30, 230, 220, 30, 179, 182, 229}, 218}, {{128, 0, 0, 0, 0, 0, 238, 218, 154, 181, 108, 83, 61, 208, 27, 12}, 218}, {{128, 0, 62, 63, 92, 244, 237, 212, 45, 5, 56, 81, 38, 171, 78, 170}, 218}, {{128, 0, 0, 120, 28, 48, 88, 250, 114, 153, 166, 61, 34, 127, 87, 193}, 218}, {{128, 0, 0, 0, 151, 173, 246, 28, 19, 178, 203, 126, 224, 168, 50, 133}, 218}, {{128, 0, 0, 0, 0, 0, 77, 42, 9, 48, 101, 24, 78, 142, 25, 60}, 218}, {{128, 0, 0, 0, 41, 43, 104, 103, 7, 24, 11, 173, 154, 193, 215, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 247, 130, 114, 209, 154, 52, 107}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 177, 52, 119, 9, 79, 126, 214, 129, 216, 0, 16, 118}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 76}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 245, 33}, 218}, {{128, 126, 151, 203, 125, 219, 223, 118, 119, 174, 124, 30, 10, 70, 167, 217}, 218}, {{128, 111, 220, 48, 100, 70, 164, 209, 29, 157, 100, 214, 191, 127, 130, 150}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 84, 40, 42, 69}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 69, 250, 242, 115, 14}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 218}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 46}, 5}, {{95, 240, 0, 0, 0, 0, 242, 136, 48, 193, 233, 131, 166, 175, 17, 147}, 5}, {{95, 240, 0, 0, 0, 0, 0, 78, 214, 128, 124, 87, 166, 149, 140, 170}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 255, 16, 238, 54, 143, 196, 118, 78, 178, 156, 234}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 237, 103, 126, 130}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 105, 36, 57, 177, 71, 141}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 197, 223, 27, 213, 232, 101, 123, 21, 76, 11, 206, 46}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 178, 0, 100}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 90, 55, 214}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 174, 55, 53, 134, 202, 219}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 145}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 160, 106}, 5}, {{95, 240, 0, 0, 0, 10, 170, 100, 79, 91, 93, 73, 155, 117, 22, 36}, 5}, {{95, 240, 0, 0, 166, 75, 155, 205, 250, 185, 32, 184, 84, 52, 201, 60}, 5}, {{95, 240, 0, 0, 0, 0, 0, 41, 4, 58, 198, 7, 79, 241, 65, 138}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 15, 36, 64, 238, 236, 139}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 200, 184, 31, 255, 211, 109, 247}, 5}, {{95, 240, 0, 0, 0, 0, 7, 225, 200, 59, 195, 60, 153, 38, 91, 214}, 5}, {{95, 240, 0, 0, 0, 0, 194, 89, 225, 124, 40, 43, 23, 225, 210, 213}, 5}, {{95, 240, 0, 0, 0, 0, 0, 154, 108, 114, 51, 105, 222, 167, 153, 232}, 5}, {{95, 240, 0, 0, 0, 0, 0, 150, 81, 218, 221, 167, 121, 233, 249, 140}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 89, 13}, 5}, {{95, 240, 0, 200, 210, 153, 56, 102, 228, 76, 246, 200, 173, 106, 5, 201}, 5}, {{95, 240, 70, 99, 86, 248, 233, 162, 97, 14, 130, 115, 90, 14, 149, 170}, 5}, {{95, 240, 63, 109, 29, 198, 162, 17, 188, 1, 140, 44, 138, 183, 25, 176}, 5}, {{95, 240, 0, 0, 0, 0, 0, 183, 20, 12, 112, 194, 39, 184, 237, 153}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 5}, {{95, 240, 0, 0, 0, 0, 0, 166, 107, 67, 164, 150, 245, 137, 230, 226}, 5}, {{95, 240, 0, 37, 237, 130, 150, 104, 43, 221, 247, 129, 176, 102, 27, 177}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 54, 160, 153, 32, 223, 74, 187, 97}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 175, 58, 249, 152, 117, 4, 61}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 168, 238, 115, 204}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 68, 181, 215}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 75, 25, 45, 75, 84, 238, 236, 52}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 164, 25, 209, 122, 129, 39, 36}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 29, 201, 158}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 155, 170, 153, 68, 109, 105}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 208, 186, 140}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 224, 150, 222, 37, 50, 101, 78, 145, 233, 97, 190}, 5}, {{95, 240, 0, 0, 0, 0, 159, 187, 231, 8, 200, 172, 53, 101, 148, 150}, 5}, {{95, 240, 49, 70, 199, 87, 182, 35, 21, 37, 189, 155, 200, 56, 93, 26}, 5}, {{95, 240, 8, 68, 146, 150, 129, 161, 226, 67, 24, 34, 234, 35, 200, 12}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 162, 147, 238, 92, 78, 254, 37}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 5, 17, 90, 186}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 197}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 120}, 5}, {{95, 240, 0, 0, 0, 0, 84, 89, 87, 79, 123, 136, 49, 127, 31, 86}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 130, 138, 71}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 151, 174}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 111, 189}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 8, 207, 255, 87}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 204, 69}, 5}, {{95, 240, 0, 0, 158, 234, 53, 5, 214, 165, 44, 79, 185, 60, 50, 254}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 79, 107, 51}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 248, 7, 133}, 5}, {{95, 240, 92, 122, 69, 224, 219, 124, 23, 28, 45, 151, 118, 37, 152, 28}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 22, 39, 61, 110, 70, 166, 231, 150}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 45, 50, 122, 148, 114, 191}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 254, 228, 175, 100, 44, 219, 174}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 25, 143, 52, 249, 205, 196, 248, 213}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 16, 230, 31, 34}, 5}, {{95, 240, 0, 226, 166, 146, 252, 12, 239, 220, 117, 95, 93, 34, 201, 209}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 198, 12, 202, 92, 0, 86, 76}, 5}, {{95, 240, 0, 0, 0, 240, 97, 98, 100, 141, 147, 192, 112, 61, 97, 145}, 5}, {{95, 240, 249, 89, 166, 120, 51, 229, 115, 87, 55, 179, 229, 2, 41, 74}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 35, 92, 176, 218, 245, 35}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 0, 0, 243, 174, 213, 236, 36, 93, 123, 234, 135}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 5}, {{95, 240, 0, 0, 0, 0, 0, 121, 224, 161, 102, 224, 132, 144, 173, 252}, 5}, {{95, 240, 0, 120, 53, 41, 116, 12, 150, 90, 139, 119, 207, 49, 18, 18}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 53, 188, 233, 52, 191, 83, 163}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 158, 96, 21, 72, 134, 125}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 116, 77, 177, 141}, 5}, {{95, 240, 0, 0, 0, 69, 95, 92, 146, 63, 160, 27, 252, 179, 90, 209}, 5}, {{95, 240, 0, 0, 0, 0, 123, 173, 198, 174, 161, 79, 190, 137, 123, 157}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 57, 132}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 211, 49}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 153, 55, 250, 243, 12, 210}, 5}, {{95, 240, 0, 0, 0, 0, 63, 66, 218, 59, 124, 226, 104, 183, 39, 189}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 14, 123, 11, 229, 104, 233}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 171, 39, 207, 221, 120, 119, 13, 165}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 240, 25, 224}, 5}, {{95, 240, 0, 0, 0, 0, 245, 142, 144, 180, 237, 145, 4, 113, 165, 63}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 5}, {{95, 240, 0, 0, 230, 176, 204, 163, 202, 58, 70, 204, 238, 57, 176, 234}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 13, 30}, 5}, {{95, 240, 0, 0, 171, 197, 96, 134, 86, 108, 22, 84, 118, 30, 183, 135}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 157, 94, 147, 3, 196, 234}, 5}, {{95, 240, 0, 0, 0, 0, 0, 0, 159, 56, 31, 159, 113, 175, 225, 82}, 5}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 12, 195, 217, 60, 126, 169}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 38, 171, 83}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 135, 79, 243, 189, 223}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 76, 189, 183, 192, 220, 133, 76, 236}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 228, 53, 22, 159}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 216, 246, 188, 59, 105, 63}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 21, 23, 26, 13, 74, 79, 145}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 242, 132, 220, 102, 19, 144, 103, 87}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 166, 218, 188, 223}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 222}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 162, 130, 152, 119, 89, 36}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 146, 194, 194, 29, 3, 35}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 249, 52, 43, 67, 61, 129}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 44, 58, 124}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 93, 90, 121, 158}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 110, 76}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 140, 86, 147, 17, 13, 31, 200, 119}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 98, 45, 55}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 52, 74, 214, 67, 189, 4, 211}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 46, 141, 96}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 54, 233}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 225, 245, 248, 180, 213, 105}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 192, 37}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 95, 231, 214, 160, 151, 141}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 148, 238, 179, 20}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 45, 172, 168, 162, 71, 167}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 220, 243}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 107}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 162, 112, 204, 170}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 166, 152}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 113, 172}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 198, 252, 47, 152}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 214}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 1, 3, 64, 161, 172, 54, 224}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 240, 248, 88}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 24, 119, 33}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 233, 5, 15, 203}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 51, 189}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 205, 19, 180, 30, 172, 251}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 72, 57, 198}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 189, 89, 230}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 91, 126, 192}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 174, 105, 205, 101, 234}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 203, 23, 60, 187}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 111, 132, 30, 160, 225, 96, 197}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 174, 243}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 222}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 47, 118, 93, 204, 206, 17}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 243}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 230, 54, 160, 46, 59, 160, 156, 220}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 112, 82, 105, 22}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 162, 129, 241, 142, 237, 155}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 161, 108}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 39, 41, 117, 35, 86, 235, 47}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 112, 159, 17, 175, 50, 211, 33}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 92, 252, 77, 59, 255}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 169, 15, 11, 61, 94, 183, 237}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 168, 1, 223, 21, 124, 145, 147}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 147, 199, 137, 130, 136, 219}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 68, 84, 227, 207, 99, 41}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 11, 43, 66, 116, 120, 127}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 178, 132}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 96, 219}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 252, 193, 198, 18, 230, 135, 139}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 102, 103, 233, 10, 139, 113}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 152, 20, 168, 235}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 28, 186, 20, 155, 240}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 36}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 13, 138, 199, 167, 86, 139, 22}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 97, 84, 192, 142, 243, 186, 115}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 113, 15, 174, 252, 90, 155, 123, 236}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 78, 213}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 105, 112}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 165}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 88, 74, 212}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 27, 63, 16, 108}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 245, 118, 94, 62, 227, 11}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 218, 17}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 176, 173, 123, 225, 52, 174, 159}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 152}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 154, 103, 26, 2, 148, 45, 186, 19}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 59, 3}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 94, 165, 39, 61}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 155, 157, 67, 61, 146, 110, 0, 174}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 114, 227, 97, 47, 52, 113}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 13, 152, 198, 144, 16}, 139}, {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 139}, {{18, 102, 62, 251, 44, 0, 0, 77, 251, 247, 238, 176, 224, 139, 225, 202}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 231, 142, 254, 207, 174, 90, 92}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 214, 54, 61, 126, 112, 35, 165, 153}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 216, 106, 57, 17, 95, 100, 55, 150}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 91, 203, 198, 183, 121}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 164, 253, 80, 241, 241, 32, 141, 235}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 167}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 252, 251, 142, 201}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 55, 162, 168, 244}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 56, 78, 189, 16}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 85, 40, 62, 167, 184, 9}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 10, 241, 235, 115}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 42, 240, 129}, 8}, {{18, 102, 62, 251, 44, 0, 0, 135, 132, 233, 242, 105, 206, 41, 232, 210}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 191, 143, 168, 166}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 78, 181, 188, 2, 58, 61}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 246, 235, 121}, 8}, {{18, 102, 62, 251, 44, 0, 60, 86, 237, 244, 206, 175, 43, 171, 213, 54}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 252, 172, 116}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 191, 44, 97, 50, 57, 65, 74, 146}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 149, 196, 49, 21, 60, 240}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 254, 52, 8, 201, 193, 90}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 170, 166, 227, 197, 25, 118, 223}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 21, 14, 242, 61, 127, 101, 37, 165, 12, 22}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 53, 13, 227, 154, 177, 209, 89, 81}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 223}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 190, 149, 235, 155, 169, 16}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 57, 14, 45, 72}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 168, 235, 73, 124}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 60, 65, 208, 189}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 40, 206, 99, 203, 136, 200, 244}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 109, 64, 25, 127, 43, 84, 2}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 49, 47, 114, 146, 49, 120, 10, 54}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 251, 221, 173}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 137, 22, 196, 164, 244, 70, 222}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 127, 96, 23, 135}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 48, 207, 142, 193, 176, 140, 70, 250}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 253, 246, 9, 108, 119, 18}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 207, 172, 74, 14}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 146, 172, 99, 79, 51, 230}, 8}, {{18, 102, 62, 251, 44, 0, 0, 245, 202, 227, 94, 111, 233, 77, 110, 183}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 226, 149, 125, 56}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 160, 247, 50, 157, 86, 112}, 8}, {{18, 102, 62, 251, 44, 0, 207, 195, 127, 149, 83, 185, 11, 81, 235, 16}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 85}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 166, 25, 88, 195, 81, 52, 162, 69}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 233, 172, 86, 44, 90, 89, 228}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 22, 139, 246, 215, 117, 98, 108}, 8}, {{18, 102, 62, 251, 44, 0, 88, 81, 193, 98, 159, 166, 44, 177, 38, 211}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 200}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 118, 104, 155, 113, 55, 63, 177}, 8}, {{18, 102, 62, 251, 44, 0, 183, 77, 196, 167, 5, 100, 226, 71, 87, 81}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 246}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 133, 73, 15}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 107, 34, 3, 32}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 35, 168, 73, 127, 96, 133, 27, 135}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 227, 38, 71, 225, 5, 245, 207, 30}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 131, 154, 65, 200, 170, 126, 223}, 8}, {{18, 102, 62, 251, 44, 0, 121, 29, 129, 45, 251, 30, 19, 221, 229, 27}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 43, 215, 44}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 106, 186, 106, 95, 54, 101, 131}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 153, 156, 4, 88, 116, 142, 44, 166, 85}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 124, 192, 247, 34}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 22, 231, 205, 125, 93}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 222, 41, 129}, 8}, {{18, 102, 62, 251, 44, 0, 0, 153, 253, 114, 7, 153, 49, 186, 200, 132}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 108, 102, 67, 10, 211}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 82, 185, 40, 168, 149, 20}, 8}, {{18, 102, 62, 251, 44, 0, 128, 133, 169, 73, 133, 14, 147, 25, 218, 157}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 51, 73, 186, 121, 92, 197}, 8}, {{18, 102, 62, 251, 44, 0, 0, 2, 231, 175, 7, 205, 51, 129, 167, 237}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 167, 51, 215, 235, 26, 36}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 46, 157, 152, 10}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 165, 7, 80}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 157, 154, 20, 142, 233, 241, 230}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 38, 224, 141, 27, 39, 223}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 252, 215, 165, 119, 97, 108, 12, 70}, 8}, {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 126, 226, 17, 37}, 8}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 47}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 91}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 46}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 247}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 126}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 245}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 85}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 106}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 209}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 45}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 136}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 124}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 97}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 199}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 180}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 27}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 134}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 239}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 51}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 27}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 43}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 159}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 51}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 198}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 245}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 61}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 74}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 194}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 171}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 113}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 209}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 67}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 83}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 52}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 229}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 142}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 162}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 255}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 254}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 206}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 124}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 246}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 250, 226, 209, 27, 177, 36, 168}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 91, 167}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 249, 20, 186, 94}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 166, 230}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 93, 103, 19, 241, 132, 86}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 40, 189, 173, 229, 215, 161}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 94, 49, 244, 48, 7}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 241, 188, 37, 124}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 139, 204, 248, 227, 72, 91, 249, 46}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 254, 27, 113, 7}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 249, 79, 125, 20, 114, 207, 205}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 208, 214, 140, 184}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 171}, {{18, 3, 207, 64, 25, 128, 11, 173, 146, 157, 208, 72, 60, 45, 209, 166}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 250, 62, 196, 129, 234, 134, 20}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 10, 6, 191, 72, 42, 94}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 12, 23, 35, 196, 204}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 148, 198, 135}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 146, 131, 38, 100, 90, 146, 74}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 76, 229, 146, 131, 189, 72}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 92, 149, 122, 165}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 85, 16}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 241, 160, 241, 50, 179, 131, 156, 31}, 171}, {{18, 3, 207, 64, 25, 128, 0, 64, 171, 219, 153, 36, 12, 49, 27, 215}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 241, 142, 11, 62, 92}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 206, 243, 154, 8, 20, 46, 51}, 171}, {{18, 3, 207, 64, 25, 128, 0, 106, 207, 34, 207, 57, 198, 215, 255, 138}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 251, 39, 27, 237, 113, 194, 233, 160}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 73, 138, 241, 245, 225, 55, 161}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 69, 14}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 95, 56, 156, 105, 16}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 99, 222, 92, 249}, 171}, {{18, 3, 207, 64, 25, 128, 0, 109, 214, 200, 95, 207, 157, 185, 108, 254}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 186, 121, 189, 10, 221}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 97, 250, 0, 250, 20, 41}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 5, 121, 120, 16, 250, 179}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 127, 239, 225}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 244, 227}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 170, 66, 119, 6, 248, 38, 241, 195}, 171}, {{18, 3, 207, 64, 25, 128, 15, 151, 84, 109, 251, 154, 162, 6, 186, 77}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 10, 8, 54, 139, 125, 45}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 3, 189, 42, 33, 216, 152, 50, 100}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 90, 221, 253, 88, 125, 50, 69, 130}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 217, 113, 237, 226}, 171}, {{18, 3, 207, 64, 25, 128, 0, 165, 57, 45, 156, 129, 149, 253, 125, 237}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 8, 204, 66}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 226, 183, 31, 202, 223}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 141, 170, 167, 205, 81, 187}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 199, 250, 168, 129, 114, 225, 51}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 215, 36, 27}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 159, 253, 38, 66, 223}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 222, 219, 69, 47}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 115, 54, 206, 245, 216}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 84, 189, 52, 90, 109, 183, 83}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 224, 45, 39, 64, 59, 148, 60}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 45, 210, 174, 142, 53, 103, 210}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 129, 138, 235}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 166, 220, 212}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 18, 217, 146, 178, 107, 221, 100, 35}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 128, 55, 75, 169}, 171}, {{18, 3, 207, 64, 25, 128, 0, 34, 116, 129, 58, 39, 165, 148, 84, 52}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 229, 119, 74, 98, 79, 148, 124}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 89, 168, 94}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 202, 150, 136, 76, 220, 36}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 139, 152, 106, 195, 215, 89, 119, 234}, 171}, {{18, 3, 207, 64, 25, 128, 252, 157, 99, 207, 209, 248, 81, 222, 176, 4}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 246, 207}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 101, 55}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 58, 248}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 138, 192, 205, 50, 69, 91}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 1, 9, 138}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 47, 175}, 171}, {{18, 3, 207, 64, 25, 128, 254, 41, 112, 32, 180, 199, 157, 85, 176, 124}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 233, 185, 72, 67, 228, 241, 176, 93}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 26, 54, 13, 255, 252}, 171}, {{18, 3, 207, 64, 25, 128, 155, 228, 253, 255, 241, 174, 197, 156, 247, 124}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 128, 66}, 171}, {{18, 3, 207, 64, 25, 128, 0, 146, 211, 234, 252, 171, 190, 4, 148, 193}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 235, 170, 217, 16, 6, 161}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 61, 140, 182}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 215, 58, 233, 193, 130, 249, 13, 109}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 173, 21, 4, 220, 14, 57, 234}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 157, 232, 94, 95, 195}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 175, 193}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 38, 206}, 171}, {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 101}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 17, 21}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 58, 198}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 231, 233, 140, 17}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 207, 186}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 106, 67}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 230}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 241, 228, 85, 66}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 75, 18}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 126, 29, 225, 165}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 114, 31, 148, 218}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 120}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 171}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 142, 217, 41, 238}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 122}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 15, 64, 195, 228}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 64, 190}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 103}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 8, 237, 172}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 108, 93, 125, 252}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 183, 161, 198, 31}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 233, 135, 185}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 120}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 79, 192}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 233, 125}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 65, 39, 9}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 255}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 155, 206, 128}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 73, 35}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 162, 3}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 32, 57, 123, 151}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 18, 229}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 123, 243, 253, 233}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 206, 176, 145}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 237, 197, 244}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 142, 171}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 100, 233}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 204}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 228, 149, 224, 154}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 18, 160, 11, 37}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 213, 226}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 221}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 101, 219, 68}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 157}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 69, 70, 170, 109}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 75}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 9, 100}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 68, 155}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 150, 167, 92}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 89}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 82, 255}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 142, 30, 182}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 78, 95, 68, 164}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 178, 22}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 20, 56}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 109}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 31, 46, 226}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 106, 237, 112, 45}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 81}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 67, 9}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 139}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 14, 101, 23}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 91, 226, 199, 135}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 158, 7, 186, 234}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 36, 227}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 89, 148}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 172, 47, 249}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 94, 239, 204, 12}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 192, 179, 37}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 96, 140, 2, 144}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 189, 109}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 31, 190}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 223}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 215, 207, 156, 234}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 243, 142}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 29, 105, 183, 133}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 210, 45, 107, 223}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 31}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 169, 72, 226, 190}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 13, 99, 165}, 206}, {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 12, 7}, 206}, {{166, 175, 186, 208, 0, 147, 114, 76, 34, 133, 113, 85, 94, 139, 85, 127}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 41, 200, 165, 164, 91, 22}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 117, 19, 205, 85, 19, 132, 96, 181, 215, 205, 252, 87}, 163}, {{166, 175, 186, 208, 0, 186, 94, 164, 53, 252, 214, 142, 35, 227, 88, 72}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 128, 154, 154, 46, 217}, 163}, {{166, 175, 186, 208, 0, 0, 21, 30, 177, 238, 8, 169, 144, 232, 136, 172}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 122, 38, 103, 3}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 34, 6}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 135, 215, 74, 126, 162, 14, 145, 168, 190, 79, 88}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 115, 131, 113, 144, 22}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 228, 159, 194, 100, 236, 181, 60, 218}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 29, 10, 66, 164, 9, 187, 124, 109}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 183, 211, 56, 70, 243, 115, 7, 252}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 197, 30, 19, 138, 128}, 163}, {{166, 175, 186, 208, 170, 242, 26, 239, 172, 246, 241, 20, 63, 55, 194, 179}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 159, 133, 23, 210, 143, 98, 195}, 163}, {{166, 175, 186, 208, 0, 183, 84, 179, 81, 224, 202, 31, 173, 146, 255, 41}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 107, 221, 223, 42}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 136, 184, 68, 6, 14, 3}, 163}, {{166, 175, 186, 208, 0, 0, 115, 111, 86, 98, 5, 180, 67, 97, 150, 216}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 65, 201, 90, 221, 42, 156, 109}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 155, 48, 40, 94, 154, 44}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 253, 122}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 216, 129, 146, 145, 153, 215, 167, 111}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 24}, 163}, {{166, 175, 186, 208, 0, 0, 0, 131, 53, 147, 173, 86, 226, 210, 39, 65}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 189, 152, 103, 191, 230, 178, 239, 162}, 163}, {{166, 175, 186, 208, 0, 0, 83, 218, 97, 239, 8, 99, 251, 167, 96, 176}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 62, 147, 248, 239, 159, 105, 75, 242}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 225, 104, 2, 248}, 163}, {{166, 175, 186, 208, 0, 102, 101, 194, 235, 2, 200, 221, 9, 195, 1, 25}, 163}, {{166, 175, 186, 208, 0, 0, 249, 124, 90, 105, 129, 3, 189, 160, 52, 128}, 163}, {{166, 175, 186, 208, 0, 0, 0, 216, 80, 82, 36, 111, 211, 124, 249, 101}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 236, 9, 134, 102}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 94, 231, 40, 39, 41, 124, 79, 199}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 59, 121, 137, 8, 138, 60, 212, 226}, 163}, {{166, 175, 186, 208, 146, 130, 41, 245, 86, 107, 63, 192, 148, 168, 228, 220}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 127, 59, 99, 229, 88, 111, 71}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 254}, 163}, {{166, 175, 186, 208, 0, 187, 91, 200, 161, 128, 9, 86, 44, 120, 191, 173}, 163}, {{166, 175, 186, 208, 0, 34, 84, 22, 147, 6, 63, 186, 74, 221, 40, 214}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 129, 182, 253, 17, 175, 188, 154}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 123, 147, 154, 0, 133, 57}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 169, 248}, 163}, {{166, 175, 186, 208, 0, 0, 0, 35, 207, 119, 165, 234, 254, 165, 108, 20}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 14, 53, 131, 199}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 237, 247, 1, 57, 246}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 98, 150, 114, 254}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 255, 168, 148, 47, 48, 116, 1}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 116, 130, 15, 50, 196, 116, 16, 195}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 187, 222}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 221, 240, 208, 5, 248}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 238, 188}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 35, 26, 60, 131, 27, 213, 202, 98}, 163}, {{166, 175, 186, 208, 0, 0, 118, 213, 192, 76, 136, 13, 11, 166, 240, 131}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 161}, 163}, {{166, 175, 186, 208, 0, 153, 31, 198, 94, 208, 109, 220, 221, 86, 150, 212}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 38, 18, 204, 121}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 154, 67, 197, 199, 28, 21, 162, 225}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 126, 9, 217, 106}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 162, 75, 110, 170, 47}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 138, 128, 132, 83, 233, 132, 28}, 163}, {{166, 175, 186, 208, 24, 46, 242, 236, 102, 0, 3, 193, 17, 70, 254, 222}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 226}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 145, 140}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 163}, {{166, 175, 186, 208, 0, 0, 180, 98, 92, 255, 222, 27, 16, 164, 69, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 163}, {{166, 175, 186, 208, 0, 15, 203, 107, 13, 204, 87, 207, 49, 156, 87, 255}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 255, 140, 251, 64, 136, 159, 177}, 163}, {{166, 175, 186, 208, 199, 183, 193, 85, 185, 226, 196, 6, 230, 20, 97, 211}, 163}, {{166, 175, 186, 208, 213, 34, 203, 11, 111, 148, 244, 162, 171, 203, 98, 249}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 18, 232}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 197}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 250, 64, 182, 236, 226}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 141, 224, 178, 50, 239, 104, 240}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 193, 241, 113, 87, 208, 252}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 22, 176, 158, 204, 88, 100}, 163}, {{166, 175, 186, 208, 10, 230, 122, 34, 250, 231, 64, 123, 196, 41, 6, 180}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 129, 98, 26, 78, 111, 150, 56, 99}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 172, 120}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 247, 253, 28, 24}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 111, 149}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 248, 73}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 66, 183, 177, 252}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 40, 125, 39, 251, 150, 8, 169}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 99, 72, 242, 18}, 163}, {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 53, 11, 0, 208}, 163}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 196, 86, 64, 45, 240, 74, 31}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 247, 132, 6, 84, 176}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 229, 160, 58, 31, 83, 83}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 35, 113, 214, 68}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 207, 249}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 128, 179, 59, 161, 232, 172}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 209, 210}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 128, 73}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 204}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 74, 135, 28, 108, 33, 255, 6}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 32, 75, 35, 85, 15, 162, 230, 230}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 55, 11, 99, 162, 202, 84}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 135, 106, 117}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 165, 122, 95, 76, 239, 68, 149}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 220}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 148, 149, 216, 156}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 173, 31, 221}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 45, 245, 97, 1, 156}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 74, 173, 162, 167, 98, 121, 99, 226}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 5}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 128, 207, 205, 129}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 156, 169, 138}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 120, 200, 126, 122, 50, 98}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 97, 32, 158}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 219, 102, 239, 156}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 203, 237}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 8, 52}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 71}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 222, 147, 249, 49, 213, 173, 29}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 40, 114}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 38, 137, 185}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 230}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 165, 73, 209, 70, 232}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 46, 113, 221, 12, 157, 2, 57}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 238, 78, 156, 243}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 209, 130, 158}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 189, 193, 204}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 25, 237, 109, 65, 15, 221, 174, 222}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 35, 88, 147, 132, 26, 90, 245}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 65}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 253}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 220}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 4, 3, 114, 180, 183, 81, 64}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 180, 243, 235}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 201, 38, 141, 25}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 229, 86}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 135, 6, 145}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 156, 188}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 7, 8, 71, 27}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 68, 89, 81, 199, 243}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 183, 114, 27}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 69, 53}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 22, 228, 161, 55, 197, 221}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 32}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 146, 18, 36, 232, 68, 227}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 151}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 173, 20, 95, 172, 173}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 208, 140, 31, 100, 19, 164, 60}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 88, 208, 86}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 250, 152, 201, 137}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 112, 237, 99}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 132, 191, 219}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 228, 222}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 145, 82, 151}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 74, 5, 208, 165, 166, 84, 141}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 195}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 194}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 80, 16, 180, 202}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 51, 83, 217, 99, 93}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 253, 221, 106, 237}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 118, 183, 213, 33, 154}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 56, 182, 27, 164, 39, 99, 139}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 19, 97, 214, 248}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 89, 239}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 112, 201, 212, 185, 172, 230, 139, 230}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 102, 210, 211, 4}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 184, 6, 240, 10, 29, 141, 90}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 209, 158}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 229, 94}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 199, 83, 82, 45, 93, 182, 76}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 135, 181, 0}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 218, 180, 181, 78, 137, 179, 104, 79}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 238, 78, 148, 227, 169, 118, 34}, 166}, {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 52}, 166}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 220, 177}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 185, 171, 33, 121, 32, 220, 217, 43}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 106, 45, 141, 69, 103, 107, 155}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 238, 137}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 109, 209, 155, 184, 159, 177}, 128}, {{94, 84, 182, 120, 204, 232, 64, 248, 70, 76, 229, 146, 6, 189, 0, 181}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 221, 22, 87, 76, 119}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 32, 43, 22}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 183, 162, 63, 128}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 247, 5, 152, 76}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 254, 186, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 91, 87, 150, 193, 100}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 238, 133}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 252, 197}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 172, 50, 6, 136, 191}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 240, 6, 60}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 134, 92, 187, 144, 75}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 106, 158, 51, 44, 209, 246}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 56, 141, 15, 147, 58, 3, 43, 116}, 128}, {{94, 84, 182, 120, 204, 232, 64, 127, 219, 66, 190, 192, 185, 11, 84, 243}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 203, 200, 123, 246, 125}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 179, 194, 78, 179, 91}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 129, 15}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 112, 209, 82}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 50, 36, 132, 180, 221, 54, 173}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 254, 186, 25}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 167, 159, 225}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 164, 26, 137, 4, 122, 121, 137}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 179, 34}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 69, 5, 25, 234}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 128}, {{94, 84, 182, 120, 204, 232, 64, 157, 46, 116, 171, 71, 141, 174, 0, 243}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 61, 205}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 236, 210, 96, 42, 6, 170, 173, 122}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 155, 225}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 13, 92, 108}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 217, 210}, 128}, {{94, 84, 182, 120, 204, 232, 64, 173, 48, 123, 52, 55, 74, 233, 221, 139}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 47, 122, 47, 198, 21, 62, 109, 56}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 104, 221, 33, 137, 130, 93, 16}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 224, 252, 103, 197, 168}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 31, 240}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 188, 131, 16, 100, 216, 215}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 39, 230, 28, 199, 182, 229}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 124, 106, 12, 165}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 152, 37, 6, 156, 170, 88, 83, 1}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 206, 212, 236, 13, 157, 116, 249, 208}, 128}, {{94, 84, 182, 120, 204, 232, 64, 46, 141, 215, 116, 156, 37, 6, 222, 207}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 117, 18}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 122, 91, 60, 178, 82, 161}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 146, 102, 113, 181}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 28, 198, 17, 31}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 244, 82, 225, 34, 159}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 11, 217, 235, 175, 110, 112}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 30, 8, 60, 129, 9}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 54, 87, 85, 41}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 60, 168, 163, 0, 149, 52, 187}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 178, 163, 129, 52}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 46, 230, 24, 135}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 90, 253, 66, 122}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 95, 168, 237}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 48, 98, 254, 0, 235, 147, 103}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 218, 132, 30, 88}, 128}, {{94, 84, 182, 120, 204, 232, 64, 195, 94, 196, 53, 175, 114, 82, 96, 171}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 77, 26, 237, 110, 136, 87, 32}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 63, 52, 228, 213, 37, 7, 213, 244, 12}, 128}, {{94, 84, 182, 120, 204, 232, 64, 168, 139, 140, 137, 161, 104, 110, 221, 81}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 237, 203, 62, 143, 227, 212}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 27, 55, 146}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 40, 247, 75, 57, 160, 247, 189, 80, 80}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 217, 180, 174, 156, 104}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 115, 57, 195, 225, 226, 137}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 40, 204, 42, 19, 235, 249, 17, 125}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 179, 241, 113}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 218, 62, 76, 95, 117, 208, 152, 36}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 141, 13, 70, 30}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 49, 46, 97, 154, 132, 202, 194}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 137, 240, 178}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 157, 202, 179, 228, 109}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 252, 230, 29, 249}, 128}, {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 128}, {{27, 174, 227, 228, 0, 0, 0, 0, 240, 214, 186, 154, 22, 101, 132, 132}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 167, 65, 117, 140, 253, 31}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 248, 205, 249, 94, 146, 133, 176}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 114, 105}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 53, 244, 82, 245, 157, 10}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 187, 45, 80, 226, 225, 222, 11, 176, 187, 140}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 95, 3, 111, 157, 96, 120, 138}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 59}, {{27, 174, 227, 228, 0, 0, 0, 65, 82, 47, 143, 70, 192, 79, 36, 106}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 78, 37, 192, 72}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 6, 119}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 6, 36, 90, 11, 159, 236, 5}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 183, 91, 100, 178}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 160, 35, 72, 134, 8, 92, 155, 115}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 87, 193, 97, 117}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 205, 224, 228, 230, 107, 201, 101, 25}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 20, 93, 140, 125}, 59}, {{27, 174, 227, 228, 0, 0, 0, 214, 87, 122, 185, 47, 181, 235, 153, 22}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 144, 125, 203, 247}, 59}, {{27, 174, 227, 228, 0, 0, 91, 129, 183, 40, 3, 24, 185, 186, 217, 75}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 143, 116, 111, 63, 228, 64, 92}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 93, 153, 160, 6, 160, 140}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 236, 229}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 236, 83, 189, 190, 9, 137, 148}, 59}, {{27, 174, 227, 228, 0, 0, 196, 87, 24, 51, 195, 135, 138, 177, 66, 226}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 75, 120, 197, 215}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 136}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 30, 198, 172, 96, 76}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 254, 211, 8, 203, 181, 72}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 4, 160}, 59}, {{27, 174, 227, 228, 0, 0, 97, 64, 248, 13, 203, 83, 112, 12, 238, 28}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 171, 152, 174, 207, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 134, 183}, 59}, {{27, 174, 227, 228, 0, 207, 109, 169, 246, 190, 135, 132, 221, 135, 220, 207}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 11, 8, 50, 250, 182}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 239}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 236, 156, 184, 170, 99}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 215, 3, 150, 220, 86, 43, 190, 225, 198, 126}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 197, 227}, 59}, {{27, 174, 227, 228, 0, 190, 41, 174, 55, 114, 127, 126, 48, 52, 28, 233}, 59}, {{27, 174, 227, 228, 0, 0, 240, 171, 243, 35, 177, 149, 25, 116, 97, 134}, 59}, {{27, 174, 227, 228, 0, 0, 158, 210, 87, 55, 60, 230, 225, 23, 246, 116}, 59}, {{27, 174, 227, 228, 0, 0, 0, 91, 173, 92, 141, 134, 34, 192, 253, 32}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 232, 216, 54, 247, 42, 99, 229, 22}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 179, 244}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 224, 224, 185, 11}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 167, 168, 62, 24, 144}, 59}, {{27, 174, 227, 228, 0, 0, 205, 121, 26, 104, 97, 2, 133, 51, 192, 71}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 102, 235, 237, 185}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 163, 36, 77, 214}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 40}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 117}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 237, 56, 106, 9, 134, 159}, 59}, {{27, 174, 227, 228, 0, 0, 250, 109, 63, 90, 57, 34, 38, 166, 86, 166}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 246, 109, 216, 177, 227}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 6, 81}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 216, 133, 225, 237}, 59}, {{27, 174, 227, 228, 0, 226, 226, 184, 208, 57, 41, 146, 253, 25, 158, 241}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 17, 138, 2, 198, 75}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 197, 162, 17, 47, 238}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 253}, 59}, {{27, 174, 227, 228, 0, 0, 0, 142, 233, 137, 133, 35, 146, 24, 84, 52}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 84, 185, 147, 220, 187, 104, 96}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 201, 164, 130, 233, 73, 204}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 221}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 81, 237, 114, 74, 251, 122, 11, 87}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 165, 73}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 255, 183, 196, 36}, 59}, {{27, 174, 227, 228, 0, 0, 197, 237, 29, 212, 195, 218, 0, 181, 36, 91}, 59}, {{27, 174, 227, 228, 0, 0, 0, 121, 131, 9, 123, 97, 124, 131, 78, 121}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 124}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 54, 198, 39, 225}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 120, 154, 213, 76, 22, 158, 105}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 155, 191, 62, 1, 222, 27, 237}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 236, 192, 251, 74, 117, 74, 229, 80}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 252, 171, 72, 225, 56}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 214}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 25, 190, 220, 243}, 59}, {{27, 174, 227, 228, 0, 125, 153, 78, 52, 163, 89, 204, 104, 140, 142, 203}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 118, 13, 69, 131, 43}, 59}, {{27, 174, 227, 228, 0, 0, 85, 137, 144, 25, 61, 167, 149, 194, 87, 135}, 59}, {{27, 174, 227, 228, 0, 0, 0, 228, 173, 226, 21, 244, 134, 18, 72, 94}, 59}, {{27, 174, 227, 228, 0, 168, 189, 97, 26, 128, 246, 227, 55, 98, 126, 150}, 59}, {{27, 174, 227, 228, 0, 0, 187, 165, 19, 199, 119, 18, 71, 66, 158, 158}, 59}, {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 231, 188}, 59}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 17, 225, 233, 180, 148, 183, 73}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 149, 201, 55, 119}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 161}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 159}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 130}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 22, 105, 33, 179, 110, 152, 93, 65}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 152}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 240, 201, 19, 45, 97}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 88, 127, 238, 117}, 179}, {{218, 12, 4, 156, 0, 0, 0, 45, 90, 59, 141, 199, 101, 228, 221, 172}, 179}, {{218, 12, 4, 156, 0, 0, 82, 157, 165, 2, 28, 142, 229, 6, 112, 149}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 143, 65, 196, 34}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 92, 161, 140, 34, 55, 195}, 179}, {{218, 12, 4, 156, 0, 97, 127, 80, 56, 18, 246, 218, 184, 249, 180, 39}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 212, 72, 130, 74}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 255, 54}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 223, 3, 145, 31, 231, 163}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 29, 191, 86, 77, 252}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 155, 118, 167, 169, 43, 8}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 233}, 179}, {{218, 12, 4, 156, 0, 0, 0, 124, 94, 174, 107, 44, 30, 254, 17, 178}, 179}, {{218, 12, 4, 156, 0, 6, 61, 56, 197, 143, 147, 240, 229, 198, 166, 116}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 139, 70}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 252, 2, 194, 230, 185, 99, 185, 151}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 221, 95, 133, 187, 196, 4, 108}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 161, 65, 67, 199, 134, 112, 253}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 169, 182, 64, 186}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 245, 156, 76, 172, 189, 229, 243, 32}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 74, 106, 73, 62, 83, 219, 172, 116}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 168, 205, 160, 36, 12, 73}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 83, 224, 58, 103, 1, 49}, 179}, {{218, 12, 4, 156, 0, 0, 47, 23, 109, 28, 148, 111, 34, 129, 98, 25}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 30, 118, 184, 25}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 70}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 82, 43}, 179}, {{218, 12, 4, 156, 0, 134, 129, 23, 184, 237, 116, 102, 174, 77, 13, 14}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 208, 209, 34, 146, 73, 179}, 179}, {{218, 12, 4, 156, 0, 0, 0, 44, 6, 66, 50, 63, 121, 224, 137, 222}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 241, 54, 203, 45, 176}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 85, 201, 137, 233, 213, 55, 103}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 198, 217, 249, 210}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 218, 84, 249, 154, 21}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 77, 107, 209, 242, 225}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 70, 166, 26, 162, 182}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 143, 228, 157, 73, 168, 91}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 248, 29, 23, 198, 251, 62}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 26, 210, 105, 132, 217, 78, 122, 202}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 240, 250, 128, 195, 59, 148}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 58}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 201, 224}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 73, 181, 103, 55, 217, 248, 206, 252}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 218, 111, 158, 45}, 179}, {{218, 12, 4, 156, 0, 229, 223, 139, 58, 166, 30, 87, 15, 220, 141, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 234}, 179}, {{218, 12, 4, 156, 0, 0, 0, 88, 103, 100, 27, 214, 10, 147, 146, 224}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 148, 126, 108, 71, 232, 240, 192, 215, 175, 181}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 206, 149, 12, 54, 134, 60, 55, 212}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 127, 214, 138, 56, 244, 121}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 121}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 22, 76}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 212, 153}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 245, 89, 33, 228, 6}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 235, 36, 146, 135, 158, 138, 217, 17}, 179}, {{218, 12, 4, 156, 0, 70, 47, 6, 75, 103, 15, 222, 90, 39, 170, 233}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 132, 146}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 229, 87, 192, 77}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 61, 113, 35, 34, 212}, 179}, {{218, 12, 4, 156, 0, 3, 42, 129, 116, 78, 122, 140, 111, 217, 116, 14}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 26, 31}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 157, 163, 217, 55, 106, 93}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 3}, 179}, {{218, 12, 4, 156, 0, 0, 227, 145, 150, 215, 214, 25, 108, 94, 109, 120}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 111, 19, 251, 65, 179, 60, 146, 203}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 184, 242, 121, 187, 146, 23, 25, 17}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 200, 44, 227, 36, 23, 175, 20}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 4}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 26, 228, 27, 98, 191, 210}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 249, 35}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 179}, {{218, 12, 4, 156, 0, 0, 0, 148, 10, 200, 185, 192, 133, 104, 204, 29}, 179}, {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 13, 137}, 179}, {{218, 12, 4, 156, 0, 140, 162, 27, 204, 107, 180, 31, 188, 219, 142, 0}, 179}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 87}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 98}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 36}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 160}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 198}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 230}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 38}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 243}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 222}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 176}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 26}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 238}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 125}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 28}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 180}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 223}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 254}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 147}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 198}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 94}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 146}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 100}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 99}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 122}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 212}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 106}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 208}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 88}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 42}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 2}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 96}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 22}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 180}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 156}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 29}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 10, 162, 93, 96}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 131, 14, 103, 120}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 238}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 98, 147, 194, 79}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 180, 0, 120}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 190, 116, 251}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 13, 113}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 94, 217}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 105, 202, 157, 50}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 206, 169}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 227}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 221, 121, 88}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 251, 244}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 124}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 18, 34}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 91, 186, 79, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 99, 171}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 40}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 4}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 188, 124, 130}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 225, 17}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 195, 254, 110, 24}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 57, 192}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 249, 103}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 149, 48, 234}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 140, 184}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 72, 237}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 236}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 186}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 16, 192}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 255, 105}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 139, 208, 140, 26}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 77}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 141, 246}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 154, 226, 240}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 75, 91, 44, 195}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 183}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 47, 45, 132, 109}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 79, 144}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 207}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 100, 3}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 1, 236}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 88, 254}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 187, 155, 127}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 199}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 205, 18, 201}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 180, 9}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 105}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 165, 201}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 242}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 105, 242, 19, 88}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 242, 178, 129}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 48}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 31, 156, 91, 76}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 25, 25}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 104}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 63, 52, 111, 107}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 156, 61, 92, 39}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 175}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 139}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 68, 132}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 71}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 166, 139}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 60, 251, 198, 235}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 162, 149, 61}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 73, 193}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 45, 175, 89}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 40}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 33}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 123, 139}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 61, 54, 106}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 159}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 199}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 13, 98, 247}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 67}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 150, 84, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 106, 166}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 118, 195}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 14, 247}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 124, 69}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 57}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 232}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 139, 100, 80}, 184}, {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 172}, 184}, {{51, 168, 0, 0, 0, 129, 179, 12, 49, 199, 23, 118, 34, 147, 225, 73}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 25, 231, 239, 29, 230, 77, 138, 80}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 73, 226, 179}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 219, 205, 235, 134, 181, 78, 173, 136, 220}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 84, 48, 31, 103, 67, 212, 226}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 83}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 86, 36, 166, 15, 29, 53, 151}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 123, 176, 225, 104, 27, 127}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 32}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 156, 197, 112, 58, 217, 21, 179, 53}, 45}, {{51, 168, 0, 0, 0, 3, 185, 41, 235, 225, 182, 70, 16, 241, 230, 36}, 45}, {{51, 168, 0, 0, 0, 228, 170, 2, 102, 57, 198, 52, 59, 214, 34, 84}, 45}, {{51, 168, 0, 0, 0, 0, 161, 173, 196, 224, 136, 28, 53, 179, 130, 53}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 148, 135, 245, 200, 91, 180}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 7, 132, 226, 173, 111, 39, 218, 38, 231, 114, 218, 29, 136}, 45}, {{51, 168, 0, 0, 0, 0, 0, 58, 179, 112, 22, 181, 114, 169, 151, 114}, 45}, {{51, 168, 0, 153, 28, 159, 42, 153, 116, 156, 214, 66, 182, 234, 160, 55}, 45}, {{51, 168, 0, 222, 238, 217, 148, 31, 118, 178, 39, 245, 168, 8, 82, 117}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 3, 185, 66}, 45}, {{51, 168, 152, 48, 137, 101, 148, 19, 104, 97, 116, 233, 153, 61, 79, 60}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 129}, 45}, {{51, 168, 0, 212, 43, 237, 112, 241, 94, 64, 244, 230, 7, 169, 176, 223}, 45}, {{51, 168, 0, 0, 0, 0, 0, 126, 218, 30, 77, 76, 145, 137, 240, 47}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 34}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 7}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 232, 244, 250, 171, 72, 96, 187}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 107}, 45}, {{51, 168, 0, 0, 0, 0, 0, 212, 23, 89, 160, 114, 88, 192, 243, 155}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 42, 113}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 55, 125, 138, 41}, 45}, {{51, 168, 0, 43, 14, 144, 79, 32, 194, 221, 98, 90, 239, 211, 255, 117}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 106, 142, 188, 150, 245, 9, 207, 76}, 45}, {{51, 168, 0, 0, 0, 0, 0, 152, 238, 201, 250, 21, 132, 55, 119, 64}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 208, 185}, 45}, {{51, 168, 0, 0, 182, 62, 105, 50, 13, 103, 83, 88, 178, 155, 161, 250}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 68}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 22, 187, 250}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 214, 222, 58, 81, 35, 131, 4}, 45}, {{51, 168, 0, 0, 0, 0, 209, 114, 21, 128, 203, 201, 28, 164, 152, 253}, 45}, {{51, 168, 0, 0, 201, 210, 219, 57, 231, 239, 134, 236, 152, 190, 88, 89}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 224, 111, 234, 45, 213, 54, 93}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 46, 94, 91, 83, 92, 254, 73, 183}, 45}, {{51, 168, 3, 193, 133, 98, 69, 255, 139, 237, 120, 116, 2, 125, 138, 230}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 27, 78, 47}, 45}, {{51, 168, 0, 0, 0, 0, 0, 140, 51, 196, 184, 212, 218, 19, 19, 165}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 147, 72, 242, 12, 9, 233}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 209, 131, 163, 108, 87, 101, 46, 2}, 45}, {{51, 168, 0, 0, 0, 132, 188, 131, 199, 91, 96, 31, 44, 52, 39, 2}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 150, 201, 219, 165, 141, 122, 204, 108}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 215, 14}, 45}, {{51, 168, 0, 187, 41, 102, 20, 13, 71, 224, 64, 133, 56, 112, 190, 71}, 45}, {{51, 168, 0, 0, 0, 0, 13, 242, 83, 134, 87, 126, 222, 62, 102, 29}, 45}, {{51, 168, 0, 0, 0, 0, 237, 232, 70, 8, 86, 67, 208, 118, 250, 249}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 121}, 45}, {{51, 168, 0, 0, 0, 0, 0, 6, 212, 131, 88, 199, 198, 228, 47, 95}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 45}, {{51, 168, 0, 0, 0, 0, 138, 164, 217, 243, 60, 69, 170, 80, 144, 74}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 22, 162, 161, 225}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 235, 124, 211, 165, 134, 170, 184, 178}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 186}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 206, 78, 59}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 202, 134, 225}, 45}, {{51, 168, 0, 117, 141, 236, 235, 83, 95, 208, 153, 27, 237, 157, 214, 5}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 51, 176}, 45}, {{51, 168, 0, 0, 0, 16, 197, 206, 62, 111, 4, 216, 83, 76, 128, 39}, 45}, {{51, 168, 0, 0, 115, 106, 196, 186, 147, 129, 231, 223, 90, 40, 234, 13}, 45}, {{51, 168, 0, 0, 0, 206, 164, 216, 204, 130, 152, 49, 19, 226, 118, 13}, 45}, {{51, 168, 0, 247, 98, 87, 154, 2, 204, 160, 7, 25, 99, 80, 26, 82}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 166, 73, 18, 88, 204, 42}, 45}, {{51, 168, 0, 0, 45, 44, 170, 137, 131, 115, 176, 139, 181, 183, 81, 234}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 16, 253}, 45}, {{51, 168, 0, 0, 0, 0, 0, 47, 66, 213, 141, 119, 111, 74, 38, 59}, 45}, {{51, 168, 0, 216, 17, 201, 159, 0, 93, 237, 98, 158, 238, 68, 162, 111}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 189, 238, 125, 212, 251, 131, 94, 14}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 124, 24, 234, 56, 188, 181, 203}, 45}, {{51, 168, 0, 0, 23, 15, 64, 56, 21, 67, 207, 113, 166, 73, 94, 126}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 98, 223, 198, 164, 189, 73, 183}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 4, 121, 79}, 45}, {{51, 168, 0, 0, 241, 22, 185, 224, 91, 216, 158, 36, 126, 67, 89, 160}, 45}, {{51, 168, 0, 233, 240, 186, 144, 37, 112, 172, 68, 220, 228, 219, 234, 17}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 21, 57}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 216, 217, 7, 100}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{51, 168, 0, 0, 108, 62, 161, 11, 71, 107, 84, 6, 77, 92, 226, 7}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 96, 254, 26, 109, 230, 26, 141, 68}, 45}, {{51, 168, 0, 0, 0, 0, 0, 0, 0, 79, 197, 195, 30, 7, 95, 244}, 45}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 209, 76, 64, 77, 208, 228, 163}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 138, 204, 175, 215, 41, 134, 138}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 221, 211, 23}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 200, 61, 130, 161, 35, 167, 208, 144}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 80, 87, 36, 133, 88}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 44, 51, 214, 188, 173, 58, 159, 192}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 5, 179, 150, 184, 74, 181, 164}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 21, 232, 201}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 8, 185, 12, 131}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 173, 231, 103, 33, 144, 213}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 188, 125, 161, 135}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 240, 97, 17, 112}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 196, 221, 39, 36, 74, 37}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 169, 217, 179}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 189, 116, 161, 69, 158, 149, 133}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 246, 114, 237, 195, 24, 144}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 214, 51, 249, 98, 199, 10}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 49, 134, 32, 142}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 68, 186, 220, 193, 35}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 92, 176, 128, 184, 238, 118}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 202, 125}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 117, 229, 70}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 218, 214}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 222, 171, 192, 30, 193, 92, 175, 153}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 131, 78, 28, 75, 51, 80, 159}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 46, 143, 174, 17, 124, 2, 160}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 8, 251, 35, 171, 32}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 73, 119}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 159, 219, 130, 185, 109, 97, 189, 122}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 19, 143, 159, 153, 234, 115, 46}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 116, 162, 146, 19, 140, 68, 37, 176}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 234, 27, 101}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 138, 212, 83, 153, 155, 65, 242, 231}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 159, 112, 56}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 227, 236, 210, 210, 179, 193, 99}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 160, 127, 33, 243, 220}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 188, 25, 181}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 6, 166, 174}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 105, 23, 114, 72, 1, 184, 247}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 1, 77, 86, 8, 115, 57}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 69, 39, 80, 36, 49}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 245, 60, 147, 114, 183, 138, 139, 59}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 13, 202, 241, 107, 240}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 208, 48, 144, 122, 99, 75, 12}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 154, 101}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 212, 164, 151, 91, 101, 11}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 47, 120, 107, 22, 174, 115, 73}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 237, 10, 78, 20, 73, 29, 105, 131}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 31, 219}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 116, 38, 27}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 252, 71, 77, 66, 246, 164, 236, 136}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 21, 80, 46, 177, 50, 131, 184, 228}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 151, 86, 6, 86, 124, 97, 178, 116}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 142, 170, 111, 148, 30}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 222, 11, 142, 238, 120, 209, 92}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 157, 172, 111, 240, 154, 179}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 14, 164, 38, 4, 166, 41}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 129, 115, 153, 73, 60, 56, 151, 99}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 143, 132, 141, 254, 174, 161, 127, 57}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 133, 170, 238, 32, 219}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 184, 101, 69, 4, 107, 60, 53}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 1, 111, 52, 79, 71}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 25, 217, 45, 43, 181, 164, 27}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 229, 191, 55, 18, 105, 249, 39}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 120, 241, 124, 59, 118, 201, 147}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 254, 136, 66, 235, 193, 77}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 99, 78, 211}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 130, 141, 27, 160}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 34, 146, 152}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 169, 28, 65}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 20, 153, 166}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 188, 219, 222, 251, 249, 173}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 7, 33, 154, 178, 141, 173, 36, 51}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 144, 200, 24, 76, 162, 204, 211}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 59, 220, 253, 181}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 217, 196, 136, 34}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 119, 141}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 223, 124, 28, 85, 29, 72, 179}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 22, 89, 224, 36, 75}, 144}, {{28, 182, 167, 124, 28, 22, 80, 227, 226, 210, 188, 2, 9, 232, 202, 143}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 215, 211, 147, 111, 76}, 144}, {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 20, 185, 82}, 144}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 172}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 236}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 185}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 161}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 177}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 96}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 99}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 175}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 103}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 33}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 144}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 108}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 36}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 18}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 110}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 152}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 178}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 18}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 228}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 21}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 129}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 233}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 183}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 136}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 29}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 225}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 226}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 185}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 95}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 42}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 216}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 44}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 220}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 113}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 53}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 199}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 121}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 151}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 78}, 119}, {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 111}, 119}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 78, 125, 37, 85, 193, 5}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 103, 119, 236, 54, 169, 118, 58}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 7, 43}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 62, 43}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 203}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 158, 174}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 89, 141, 34, 140, 128, 225}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 92, 95}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 26, 5, 204, 209, 4}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 172, 129, 108, 226, 149, 75, 138}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 229, 175, 40, 41, 19}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 112, 160, 101, 171, 54}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 244, 183}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 81, 123, 114, 223, 81, 135, 23}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 98, 26}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 58, 207, 26, 101}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 62, 29, 142, 213, 210}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 129, 167, 57, 152, 50}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 31, 182, 141, 159}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 51, 66}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 122, 70, 215, 49, 189, 220, 126}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 1, 189, 245, 237, 241, 120}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 53, 16, 23}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 104, 61}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 186, 2, 168, 146, 115, 26}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 208, 226, 86, 96, 170}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 71, 188}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 68, 218, 209, 250}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 119, 148, 142, 183}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 242, 77, 191, 112, 253}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 14, 134, 131, 210, 44}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 238, 152}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 179, 104, 16}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 16, 79, 5, 5}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 40, 87, 47, 9, 146, 96}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 212, 155, 245, 113, 180}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 106, 9, 84}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 88, 109, 186}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 57, 152, 200, 146, 129, 85}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 116, 48, 124, 248, 179}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 100, 82}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 173, 95, 92, 28}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 206, 197, 255, 102}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 159, 147, 243, 69, 92}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 125}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 240}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 60, 237, 8, 22, 200, 177, 117}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 136, 75, 78, 35, 144}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 252, 77}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 91, 16, 11, 127, 240}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 160}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 31}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 224, 197, 82, 75, 127}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 204}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 114, 236, 79, 55, 231, 41, 94}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 17, 103, 188}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 127, 122, 82, 4, 184}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 175, 106, 53}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 225}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 121, 233}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 240, 216, 176, 99, 150}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 14, 138, 44, 113, 123, 241, 254}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 189}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 156}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 113, 20, 170, 45, 207, 28}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 63, 107, 56, 243, 49, 134, 153}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 24, 106, 240, 160, 86, 107}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 53, 33, 152, 197, 97, 13}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 138}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 175, 71, 188}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 82}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 64, 67}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 117, 234, 66, 108}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 69, 15, 124, 20}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 162, 166, 181, 117, 95, 99}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 42}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 58, 188}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 41, 186, 14, 177, 247, 229}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 159, 193, 59, 37}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 25, 173}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 58, 150, 145, 67, 42}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 13, 254, 255}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 170}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 12, 127, 2}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 9, 44}, 113}, {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 33, 158, 255, 150}, 113}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 27, 4, 175}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 64}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 129, 255, 175}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 218, 250}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 99, 236}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 115, 95}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 196, 20, 89, 230}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 32, 24, 247, 31}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 155, 119, 179, 19, 209}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 185, 161, 33, 219}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 55, 161}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 189, 122, 183}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 157, 5}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 128, 85, 163}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 105, 70, 143, 238, 50}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 252}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 65, 89}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 244, 205, 34}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 249, 139, 150}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 45, 248, 156, 205}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 20, 8}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 244, 171}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 199}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 162, 225, 214, 237}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 92, 28, 37}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 229, 255, 83, 48}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 126, 149, 71, 213, 171}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 20, 131, 176}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 191, 38}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 52, 252, 207, 164}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 107, 85}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 204, 163, 229}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 6, 132, 68}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 167, 1, 177, 126}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 177, 157, 223}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 150}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 18}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 85, 127}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 138, 65}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 159, 20, 15, 145}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 81, 43, 102, 29}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 126, 131}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 152, 155, 203}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 15, 114, 170, 171, 57}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 85, 22}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 171, 240, 199}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 123, 154, 240, 89}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 5, 104}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 252, 100}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 20, 196, 230, 85}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 94, 242}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 34, 181, 141, 66}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 242, 214, 27}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 109, 234, 215, 112}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 7, 223, 8, 105, 29}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 109, 39, 106, 8, 81}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 230, 5, 60}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 182, 197, 81, 85}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 148, 229}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 66, 224, 73}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 140, 250}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 20, 181}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 137, 141, 82, 212, 242}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 176, 115}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 223, 131}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 64, 35}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 21, 211, 84}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 2, 65, 209, 183}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 95, 201, 45}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 19, 169, 153, 235}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 3, 137, 19}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 145, 72, 141, 77, 130}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 28}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 126, 11, 163, 170, 209}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 188}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 34, 22, 113, 20, 14}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 22, 24, 236}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 37, 112, 84}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 84, 53}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 52, 119, 223, 4}, 50}, {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 50}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 158, 81, 186}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 113, 216, 57, 43}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 105, 254, 201}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 120, 109, 210, 113, 174, 131}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 100, 188, 35, 210, 106}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 195, 178, 156, 234}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 50, 116, 68, 62}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 28, 62, 35, 178}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 101, 208, 240, 134}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 245, 161}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 9, 161, 193, 213, 246, 244}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 136, 12, 38, 104, 42, 33}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 148, 244, 188, 167, 18}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 199, 240, 163, 198, 159, 178, 220}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 13, 60, 3, 80}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 121, 11, 213, 230, 92, 27}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 16, 205, 171, 199, 75}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 42, 38, 220, 74, 25}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 42, 19, 122, 244, 115, 101}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 174, 121, 232, 159, 12, 178, 27, 47}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 149, 202, 88, 103, 44, 145, 214, 3}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 184, 15, 142, 88, 136, 134}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 204, 158, 250, 95, 68}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 178, 152, 1, 200, 213, 149, 183}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 82, 213, 149, 40}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 113, 58}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 218, 140, 108, 230, 140}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 151, 37}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 69, 171, 112, 67}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 36, 165, 160, 92, 158, 33, 180}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 48, 172, 165, 38, 84, 239, 134, 77}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 177, 178, 100, 72, 94, 5, 21}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 242, 70, 153, 28}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 36, 126, 74}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 244, 165, 217, 45, 202, 89}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 66, 220, 209, 91}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 218, 236}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 113, 197, 220, 30}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 34, 255, 185}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 124, 137, 134, 240, 36, 177, 44, 81}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 196, 172, 199}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 249, 206, 233}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 172, 29, 127, 72, 36, 147}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 89, 166, 209, 196, 238}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 216, 9, 189, 68, 225, 66}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 249, 83, 198, 174, 14, 152}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 222, 131}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 86, 205, 230, 197, 159}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 128, 32, 154, 25, 82, 4, 5}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 181, 220, 118, 216, 49, 211, 80}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 171, 230, 241, 198}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 129, 50}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 19, 75, 178, 254, 185, 235, 5}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 138, 43, 15}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 252, 147, 196}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 219, 29}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 181, 138, 198, 216, 120, 49}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 184, 133, 140, 141, 67, 94, 44, 244}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 152, 171, 243, 177, 125, 252, 82, 193}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 45, 11}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 103, 117, 90, 126}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 111, 187, 144, 208, 125, 213}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 33, 245, 18, 46}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 77, 122, 94, 109, 251, 141}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 51, 117, 116, 60, 49, 115, 70}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 48, 226}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 1, 227, 173, 236, 74, 166}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 107, 110, 221}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 178, 219, 119, 192}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 207}, {{170, 145, 230, 123, 215, 189, 73, 0, 0, 227, 116, 157, 205, 149, 227, 206}, 207}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 200}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 148, 13, 199, 189, 165}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 210, 44, 224, 111, 198, 68, 45, 248, 32}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 189, 154}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 230, 197, 40, 89, 4}, 3}, {{151, 166, 32, 0, 0, 159, 90, 175, 72, 61, 146, 102, 226, 253, 232, 222}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 32, 74, 5, 167, 216}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 149, 249, 53, 170, 63, 204}, 3}, {{151, 166, 32, 0, 95, 196, 149, 213, 28, 76, 207, 19, 106, 146, 71, 120}, 3}, {{151, 166, 32, 0, 0, 0, 0, 165, 209, 122, 57, 134, 205, 158, 14, 112}, 3}, {{151, 166, 32, 0, 245, 39, 188, 240, 42, 188, 71, 190, 181, 218, 144, 125}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 150}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 44, 133, 147}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 219, 132, 125, 69, 53, 92, 81}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 168, 143, 129, 81, 38, 241}, 3}, {{151, 166, 32, 0, 0, 121, 185, 209, 129, 33, 166, 95, 56, 112, 210, 120}, 3}, {{151, 166, 32, 0, 201, 84, 253, 83, 40, 223, 18, 172, 121, 240, 59, 163}, 3}, {{151, 166, 32, 0, 0, 0, 30, 126, 163, 90, 209, 161, 216, 103, 201, 187}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 18, 8, 221}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 237, 194, 255, 178, 208, 115, 134, 18}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 253, 121, 210, 209, 113, 149, 43}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 26, 121, 175, 149, 179, 174, 179, 218}, 3}, {{151, 166, 32, 0, 0, 0, 0, 156, 192, 61, 6, 177, 107, 97, 33, 213}, 3}, {{151, 166, 32, 0, 0, 205, 201, 242, 208, 153, 47, 8, 197, 232, 96, 172}, 3}, {{151, 166, 32, 0, 0, 29, 113, 104, 51, 202, 9, 128, 79, 43, 59, 13}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 199, 250, 107, 62, 169, 130, 115, 3}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 238, 183, 254, 2, 182}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 112, 211, 31, 125, 22}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 140, 195, 94, 176, 210, 164, 205, 136}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 244, 182, 71}, 3}, {{151, 166, 32, 8, 222, 188, 234, 48, 82, 21, 233, 44, 209, 209, 66, 233}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 200}, 3}, {{151, 166, 32, 0, 175, 92, 138, 237, 12, 80, 143, 153, 153, 226, 35, 17}, 3}, {{151, 166, 32, 0, 0, 0, 0, 41, 57, 112, 182, 238, 243, 123, 133, 39}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 35, 48, 238}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 229, 80, 128, 132, 183}, 3}, {{151, 166, 32, 0, 133, 246, 240, 101, 146, 129, 152, 237, 171, 113, 137, 149}, 3}, {{151, 166, 32, 0, 0, 0, 88, 232, 153, 168, 238, 7, 152, 19, 255, 235}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 249, 208, 231, 206, 229, 167, 255, 59}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 34, 165, 211, 107, 209, 15, 125}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 161, 74}, 3}, {{151, 166, 32, 0, 0, 118, 222, 237, 142, 152, 194, 209, 244, 46, 176, 128}, 3}, {{151, 166, 32, 0, 0, 156, 82, 122, 209, 139, 48, 160, 51, 21, 71, 157}, 3}, {{151, 166, 32, 0, 0, 22, 225, 114, 158, 149, 192, 146, 60, 40, 37, 131}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 35, 204, 165, 248, 51, 208, 7, 223}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 26, 66, 152}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 117, 210}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 106, 4, 168, 16, 114, 159, 124, 214}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 28, 45, 5, 178, 244, 71, 124, 14}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 137, 27, 97, 48, 128, 246, 91}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 137, 91, 50, 157, 47, 2, 21, 180}, 3}, {{151, 166, 32, 0, 205, 3, 158, 45, 131, 210, 91, 32, 165, 188, 66, 115}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 59}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 220, 149, 95, 249, 201}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 159, 179, 216, 217, 10, 84}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 218, 252, 235, 43, 214, 8, 248, 180}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 185, 205, 7, 46, 69, 222, 109, 66}, 3}, {{151, 166, 32, 0, 183, 125, 178, 118, 214, 62, 147, 238, 254, 214, 107, 248}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 114, 16}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 3}, {{151, 166, 32, 0, 0, 0, 0, 212, 108, 134, 152, 216, 177, 240, 42, 26}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 227, 76, 210}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 250, 54, 45, 78, 222}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 76, 119, 26, 113, 142, 74, 217, 120}, 3}, {{151, 166, 32, 0, 66, 39, 86, 111, 241, 15, 123, 89, 184, 227, 50, 33}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 127, 103}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 249}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 186, 254, 30, 202, 128, 103, 192, 237}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 187, 135}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 213, 0, 224, 215, 87, 217, 241}, 3}, {{151, 166, 32, 0, 0, 96, 148, 164, 90, 180, 250, 96, 233, 29, 221, 145}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 234, 31, 62, 230, 9, 7, 2, 161}, 3}, {{151, 166, 32, 0, 0, 0, 0, 255, 126, 108, 192, 189, 13, 164, 188, 202}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 138, 56, 201, 30, 196, 163}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 22, 187, 95, 17, 196, 3}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 14, 72, 109, 183, 31, 26, 43}, 3}, {{151, 166, 32, 0, 0, 24, 67, 235, 47, 13, 42, 93, 27, 140, 218, 50}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 20, 174, 253, 212, 99, 165, 181, 5}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 201, 10, 66}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 94, 210, 105, 254, 225, 172}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 202, 109, 222, 44, 50, 80, 203, 30}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 253, 198, 40, 243, 107, 156, 182}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 143, 140}, 3}, {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 126, 233, 148, 122, 60, 24}, 3}, {{151, 166, 32, 0, 0, 0, 179, 140, 80, 31, 221, 211, 232, 55, 221, 152}, 3}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 119, 32}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 40, 139, 202, 217, 170, 129}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 195, 162}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 208, 220, 111, 188}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 46, 220, 61, 22, 233, 100, 107}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 44, 235, 155, 245}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 221, 240, 219}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 68, 161, 171, 37}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 130, 190, 171, 96, 113, 69, 20, 238}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 25, 216, 230, 143, 1}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 159, 251, 253, 139, 210, 245}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 126, 103}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 22, 189, 79}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 235, 227}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 128, 194, 123, 138, 118, 113, 16, 54}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 79, 35, 34, 149, 16}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 112, 251, 4}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 242, 85}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 158, 118, 59}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 151, 46, 85}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 118, 227, 59, 152, 188, 194}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 178, 199}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 210, 10, 108}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 218, 144, 233, 9}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 252, 56, 243, 227, 252, 193}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 77, 199, 86, 196, 147}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 36, 29, 70, 199}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 248, 80, 159, 170, 20, 25, 180}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 140, 40, 195, 178, 57, 36, 41}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 215, 187}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 20, 172, 45, 180, 15}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 30, 98, 59, 163, 129, 33}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 126, 78, 165, 129}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 160, 54, 108, 95}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 143, 242}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 166, 134, 22, 219, 18, 33, 121, 3}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 232, 177, 196, 161, 192, 119}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 77, 175, 98, 239, 28, 113, 248, 32}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 45, 14, 87, 46}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 100, 14, 188, 213, 160}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 98, 124, 76, 199, 185}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 202, 74}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 115, 158, 197, 44, 153}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 11, 204}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 125, 169, 193}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 4, 9, 208, 163, 185, 41, 207}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 118, 190, 229, 102, 87, 189}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 128, 229, 5, 147, 52, 152}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 17, 225, 216}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 35, 117}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 15, 45}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 235, 125, 192, 60, 48, 218, 80, 125}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 251, 103}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 213, 29, 136, 4, 195, 64, 51, 221}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 93, 181, 196}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 166, 100}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 72, 230, 97, 247, 194, 143}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 143, 206}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 171, 207, 206, 120}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 75, 158, 86, 41, 202, 60, 126, 216}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 174, 167, 196, 23, 61, 192, 101}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 132, 26, 47, 174, 152, 85, 21, 193}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 136, 173, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 51, 206}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 203, 151, 193, 128, 45, 147}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 133, 20, 213, 44, 87, 178, 89}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 138, 63, 13}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 180, 149}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 167, 225, 181, 224}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 217, 60, 145, 64, 241, 69, 155, 185}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 23, 11, 162, 242, 221, 98, 76}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 138, 166, 120, 212, 106, 222, 100}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 153, 42, 182, 190, 55, 166}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 140, 30, 90, 243, 188, 200}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 123, 119, 141, 18, 93}, 13}, {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 154, 79}, 13}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 20, 10, 245, 92}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 99, 233, 236, 92, 224, 82, 23}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 30, 152, 162}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 166, 221, 78, 32, 160}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 211, 148, 184, 92, 87, 22, 166}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 167, 239, 125, 63, 127, 57, 58}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 150, 53, 147, 6}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 204, 104, 86, 157}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 97, 193, 170}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 24, 96, 8, 19, 97, 38, 92}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 236, 125, 130, 204, 88, 110}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 226, 248, 94, 152, 114, 137}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 81, 215, 142, 9, 155}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 141, 108, 67, 24, 207}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 209, 36, 47, 189, 7, 195, 143}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 176, 9}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 190, 212}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 39, 177, 107, 246, 71, 113, 138}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 82, 54}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 46}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 186, 196, 54, 243, 152, 226, 20, 228}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 114, 68, 224, 102, 26, 217, 19, 42}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 52, 214, 41, 157}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 95, 98, 16, 115, 149, 27, 204}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 217, 156, 27, 29}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 42, 122, 73, 237, 179, 230, 24}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 159, 111}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 118, 114, 168}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 175, 11, 42, 252, 138}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 21, 74, 54, 109}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 239}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 14, 253, 6, 50, 230, 147, 140, 143}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 236, 233, 199, 197, 108, 80, 202, 159}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 143, 104, 100, 19}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 210, 224, 80}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 94, 201, 14, 143, 57, 20}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 85, 64, 116, 1, 253, 205, 244}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 149, 244, 246, 61}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 117}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 220, 185, 8, 44, 197}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 214}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 254, 131, 93, 234, 211}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 146, 17, 74, 186, 171, 9}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 18, 4, 68, 117, 234, 28, 20, 185}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 239, 128, 246}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 235, 168, 94, 175, 202}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 65, 208, 37, 198, 105, 190, 193}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 109, 156, 21}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 73, 238, 18, 247, 60, 163, 91}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 78, 241, 233, 184, 97, 173, 213}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 244}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 35, 90, 250}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 233, 166, 84, 77, 93}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 102, 204, 112, 134, 82, 51, 238}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 96, 95, 143, 93, 178, 112, 93}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 202, 72, 166}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 102, 21, 202, 11}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 186, 47, 182, 108, 242, 174, 230}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 197, 84, 42}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 134, 110, 186, 93, 109}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 104, 19, 3, 144}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 124}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 179, 195}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 204, 76, 177}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 160, 86, 106, 149, 191, 106}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 163, 179, 242, 1, 45, 28, 111}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 52, 80, 105, 150, 57, 179, 89}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 178, 25, 94}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 46, 144}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 233, 62, 12, 65}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 180, 146, 248, 8, 63, 150, 133}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 201, 171, 7, 162, 18, 226, 219, 199}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 157, 1, 29, 93}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 117, 178, 24}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 87, 80, 81}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 234}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 127, 127, 33}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 94, 225, 176, 186, 20, 189}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 176, 233}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 79, 0, 245}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 130, 30, 125, 140, 177, 179, 250}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 140, 116, 56, 143, 171, 13}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 61}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 183, 61, 113, 133, 47, 184, 247}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 92, 27, 124, 186, 85, 227, 47}, 42}, {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 64, 252, 214, 11, 251, 174}, 42}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 188, 48, 108, 63, 93, 226}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 201, 145, 152, 232}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 100, 241, 173, 170, 78, 129, 172}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 240, 149, 17, 197}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 173, 65, 219, 193, 79, 116, 232, 26}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 6, 47, 107}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 8, 222, 122, 9}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 127, 67}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 137, 147, 249, 116}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 234, 178}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 11, 87, 10, 216, 73, 37, 61, 37}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 156, 70}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 129, 46, 166, 101}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 81, 167, 254, 69, 12}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 1, 83, 215, 236}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 192, 197, 125, 44, 54, 35}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 13, 2, 137, 0, 18, 88, 157}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 120, 123}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 59, 215, 71, 168, 133, 214}, 31}, {{48, 114, 33, 103, 247, 255, 64, 146, 153, 125, 228, 40, 148, 54, 4, 57}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 36, 145, 63, 230, 197}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 153, 70, 194, 70, 203}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 60, 112, 129}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 28, 119, 168, 178}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 202, 13, 127}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 194, 238, 232, 230, 68}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 82, 195, 95, 50, 133}, 31}, {{48, 114, 33, 103, 247, 255, 64, 189, 62, 209, 212, 64, 38, 235, 42, 94}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 243, 5, 177, 16}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 140, 48, 54, 249, 12, 205, 71}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 72, 15, 230, 111, 210}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 30, 105, 68, 94, 247, 28, 124, 23, 92}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 202, 106, 188, 47, 252, 243}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 199, 2, 85}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 106, 23}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 40, 146, 49, 187, 236}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 171, 27, 214, 66, 174, 182, 113}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 168, 83}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 250, 207, 254, 211, 229, 114, 24, 187}, 31}, {{48, 114, 33, 103, 247, 255, 64, 155, 70, 91, 92, 29, 176, 83, 117, 125}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 97, 43, 151, 234, 162, 25, 249}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 85, 197}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 246, 75, 237, 59, 42, 95, 114, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 225, 154, 137, 38, 215, 141, 59, 185, 226}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 65, 194, 210, 103, 192, 213, 222}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 232, 231, 38, 124, 64}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 130, 30, 19, 42, 220, 104, 209}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 201, 91, 73, 95, 81, 120, 146, 84}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 86, 118, 78, 193}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 202, 47, 172, 81}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 141, 221}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 125, 216, 1, 167, 45, 80}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 133, 210, 197, 202}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 105, 84, 177, 231, 101}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 121, 88, 192}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 244, 245, 21, 109, 45, 182}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 210, 125, 66, 232, 169, 249}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 129, 112, 239, 65, 155, 240, 95}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 165, 81, 22, 129}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 253, 247, 24, 186, 190, 106, 28}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 70, 53, 42, 72, 41, 167, 197}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 87, 45, 135, 229, 140, 141, 126}, 31}, {{48, 114, 33, 103, 247, 255, 64, 28, 68, 216, 124, 108, 169, 10, 3, 81}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 18}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 187, 179, 24}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 85, 118, 52}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 148, 87, 3, 110}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 129, 83, 212, 219, 191, 46, 108, 213}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 12, 183}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 64, 224, 136, 21, 7, 112, 149, 199}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 70, 100, 10, 46, 84, 180}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 212, 222, 18, 48, 247}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31}, {{48, 114, 33, 103, 247, 255, 64, 0, 76, 33, 225, 141, 55, 90, 135, 204}, 31}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 219, 137, 120}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 31, 254, 76}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 19}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 71, 34}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 39, 24}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 222, 209}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 134, 206, 159, 191}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 246, 60}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 133}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 146}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 141, 238, 74}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 90}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 72, 25}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 237, 186, 99}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 195, 78}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 220, 106}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 120, 249, 107}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 3}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 167, 165, 175, 171}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 208}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 16}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 75, 13}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 210}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 164, 123, 251}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 21, 204, 133}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 107, 119, 181}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 95, 163}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 179, 40}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 65, 56, 40}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 56, 222, 216}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 242, 15, 104}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 46, 109}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 1, 56}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 91, 244}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 105}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 219}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 66, 221}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 168, 79, 108}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 18, 17, 193, 10}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 13}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 127}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 216, 118}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 231, 129}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 8, 199, 3, 85}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 53, 255}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 152, 136}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 146}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 195, 120}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 48, 196, 139}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 105, 53, 13}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 175, 156}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 103}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 232}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 7, 197, 155}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 121, 170}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 53, 27}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 181, 238}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 82, 219}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 115, 34, 222, 55}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 27}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 152, 195, 28, 76}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 19, 188}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 252, 247}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 12, 253, 173}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 235, 26}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 217, 234, 241}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 13, 61}, 30}, {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 6, 84, 4}, 30}, {{179, 129, 186, 144, 0, 0, 117, 204, 186, 157, 238, 62, 163, 36, 22, 148}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 178}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 151}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 178}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 90}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 239, 173, 202, 47, 38}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 253, 126, 174, 185, 95, 89, 145, 41, 208, 100, 18}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 195, 245, 82, 186}, 94}, {{179, 129, 186, 144, 0, 4, 95, 149, 48, 168, 247, 184, 34, 59, 189, 186}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 121, 99, 221, 249, 52, 87}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 207, 51, 238, 27, 94, 81}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 220, 132, 43, 78, 167, 22}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 119, 196, 69, 76, 167, 211, 184}, 94}, {{179, 129, 186, 144, 214, 252, 186, 13, 253, 164, 40, 253, 88, 127, 153, 215}, 94}, {{179, 129, 186, 144, 0, 0, 80, 186, 68, 185, 212, 216, 0, 182, 62, 107}, 94}, {{179, 129, 186, 144, 0, 230, 84, 11, 194, 225, 30, 218, 84, 89, 11, 253}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 126, 127, 254, 244, 229, 84, 43}, 94}, {{179, 129, 186, 144, 0, 0, 200, 248, 10, 34, 35, 214, 235, 228, 89, 149}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 109, 23, 166, 145, 187, 245}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 184, 178, 243, 116, 252, 203, 41, 92}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 47, 32, 214, 214, 128, 160, 81, 169, 236, 39, 148}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 80, 45, 227, 201, 60, 75, 30, 134}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 198, 72}, 94}, {{179, 129, 186, 144, 0, 0, 166, 227, 163, 169, 44, 70, 65, 228, 253, 184}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 13, 45, 28, 118, 174, 6, 221}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 83, 5}, 94}, {{179, 129, 186, 144, 0, 232, 69, 85, 174, 118, 88, 135, 21, 81, 136, 138}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 206, 118, 65, 252, 145, 8, 54}, 94}, {{179, 129, 186, 144, 0, 101, 152, 199, 101, 11, 208, 193, 58, 6, 42, 172}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 121, 198, 195, 222, 216, 67, 216, 54}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 101, 39}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 7, 235, 98, 128}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 221, 129, 115, 33}, 94}, {{179, 129, 186, 144, 0, 0, 0, 243, 54, 173, 87, 183, 251, 255, 144, 92}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 86, 218, 193, 41, 65, 196}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 243, 30, 33, 10}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 187}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 81, 7, 7, 4, 149}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 81, 247, 87, 61, 159}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 221, 27, 240, 201}, 94}, {{179, 129, 186, 144, 153, 87, 228, 209, 130, 134, 240, 69, 189, 253, 110, 74}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 218, 220, 163, 80}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 183, 245}, 94}, {{179, 129, 186, 144, 0, 61, 227, 73, 12, 210, 155, 150, 48, 117, 83, 58}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 98, 24, 147, 95}, 94}, {{179, 129, 186, 144, 0, 0, 0, 175, 82, 162, 207, 43, 191, 43, 106, 68}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 239, 184, 40, 218, 13}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 220, 114}, 94}, {{179, 129, 186, 144, 0, 0, 0, 87, 13, 164, 123, 77, 53, 183, 13, 78}, 94}, {{179, 129, 186, 144, 0, 163, 45, 211, 139, 54, 121, 153, 66, 171, 22, 34}, 94}, {{179, 129, 186, 144, 0, 0, 154, 25, 24, 148, 155, 38, 112, 175, 83, 158}, 94}, {{179, 129, 186, 144, 0, 0, 166, 213, 156, 28, 161, 214, 71, 41, 14, 96}, 94}, {{179, 129, 186, 144, 0, 251, 89, 79, 29, 126, 90, 184, 94, 184, 75, 12}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 134, 3, 2, 21, 158, 103}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 103, 197, 22, 30, 16, 252, 46, 128, 112}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 209, 219, 96, 8}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 43, 241, 239, 35, 11, 172, 192, 226}, 94}, {{179, 129, 186, 144, 0, 0, 0, 104, 250, 66, 34, 210, 144, 47, 185, 192}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 94}, {{179, 129, 186, 144, 0, 101, 194, 117, 68, 128, 84, 183, 182, 218, 175, 107}, 94}, {{179, 129, 186, 144, 0, 251, 137, 44, 125, 147, 61, 32, 60, 60, 162, 158}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 254, 52, 149, 108, 189, 247, 137, 254}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 63, 59, 65, 86, 153, 169, 139, 7}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 202, 195, 242, 18, 236, 51}, 94}, {{179, 129, 186, 144, 0, 0, 0, 219, 238, 211, 235, 152, 135, 248, 247, 126}, 94}, {{179, 129, 186, 144, 0, 0, 87, 29, 108, 139, 180, 1, 0, 181, 56, 14}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 223, 27, 170, 34, 51, 160, 103, 226}, 94}, {{179, 129, 186, 144, 0, 0, 0, 35, 105, 211, 120, 13, 236, 6, 142, 143}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 124}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 226, 60, 167, 23, 139, 34}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 85}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 231, 199, 67, 54}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 152, 124}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 39, 191, 254, 15, 115}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 105}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 98, 183, 128, 183, 142, 23, 165}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 102, 189, 115, 246, 114, 1}, 94}, {{179, 129, 186, 144, 0, 99, 18, 135, 254, 214, 63, 219, 178, 164, 157, 222}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 57, 32, 69, 167, 28, 254}, 94}, {{179, 129, 186, 144, 0, 0, 185, 232, 171, 174, 80, 18, 53, 81, 214, 236}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 248, 247, 245, 212}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 254, 16, 125, 226, 206}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 63, 75}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 108, 38, 2, 103, 245, 127, 47, 47}, 94}, {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 143, 209}, 94}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 217, 114, 148, 136}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 54, 82, 196, 144, 229, 161}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 242}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 52}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 78, 86, 225, 133}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 69, 93, 51}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 56, 139, 170, 195, 169}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 219, 98}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 57, 80}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 169, 194, 13, 121, 172}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 1, 54}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 93, 202, 178, 174}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 18, 112, 93, 60}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 211, 199, 151, 124, 187, 183}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 99, 109, 0, 73, 213, 222}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 34, 223}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 220, 186, 219, 180, 3}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 24, 152, 172, 6, 55}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 227, 117}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 185, 24, 56}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 250, 73, 186, 231}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 184}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 80, 166, 196, 100, 87, 84}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 117, 183, 163, 7, 188, 90}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 20, 251, 68, 140}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 100, 10}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 66, 38, 201, 207, 48, 143}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 234, 7, 230, 219, 155, 117}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 168}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 108, 114, 151, 57, 98}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 20, 122, 46}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 82, 207}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 62, 132}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 19, 247}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 213, 7, 217, 8, 212, 5}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 39, 224, 212, 24, 116}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 178, 215, 195, 205, 136}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 83, 211, 101}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 139, 198, 83, 208, 113, 24}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 122, 186, 137, 161}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 189, 112, 140, 85, 246}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 110, 54, 163, 24, 60, 66}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 231, 86}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 7}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 201, 180, 239, 38, 186}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 107, 185, 124, 165, 210, 87}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 251}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 18, 242, 147, 232, 231}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 11, 62, 143, 14, 109}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 212, 41, 94}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 95}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 54, 101, 231, 34}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 94, 107}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 237, 74, 177, 27, 87, 70}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 19}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 18}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 43, 75, 61, 100, 6}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 175, 220}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 153, 87, 23, 58}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 160, 138}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 251, 5, 150}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 224, 225, 30, 126, 230}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 143, 170, 215, 83, 107, 92, 104}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 78, 48, 16, 220, 253, 193}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 123}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 196, 49, 136}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 22, 16}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 123, 234, 39, 228, 170}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 248, 43, 148, 246, 129}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 204, 46, 176, 82}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 244, 59, 115, 195, 25}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 242, 179, 129, 31}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 152, 4, 55, 11, 115}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 22, 177}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 195, 156, 243}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 47, 195, 86}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 6, 209, 190, 156}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 251, 234, 229, 171, 133, 43}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 13, 221, 177, 249, 39}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 97, 28, 34, 149, 10, 236}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 151, 32}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 7, 249, 165, 238, 7}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 186, 145, 58}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 170, 169}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 14, 253, 100, 141, 129}, 190}, {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 108, 209, 127, 142}, 190}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 90, 51, 212, 109, 52, 205, 77}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 254, 253, 140, 94}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 222, 206, 46, 43, 10}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 93}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 48, 6, 151, 70}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 233, 232, 248, 237, 153, 45, 92}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 174, 156, 239, 77, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 244, 178, 149, 85, 89, 34}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 109, 159, 42, 88, 98, 5, 80}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 194, 95, 127, 243, 230, 53}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 177, 189}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 155, 238, 173, 239, 143, 245}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 76, 88, 74, 135, 109, 108, 158, 70}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 18, 49, 158, 24, 230}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 239, 72, 245, 175, 182, 208, 73}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 22}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 78, 24, 8, 5, 90}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 16, 233, 205}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 44, 167, 231, 147, 83}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 8, 17}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 200}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 79, 60, 202, 247, 65, 16, 109, 253}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 213, 124, 10}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 100, 100, 26}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 113, 39, 209, 161, 58}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 150, 3, 209, 85}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 83, 49, 54, 85}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 87, 205, 144, 167, 254}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 89}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 59, 132, 150, 247}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 28, 199, 5}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 185, 233, 2, 173}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 73, 99, 44, 169, 129, 255}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 35, 220, 194, 16}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 219, 168, 113}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 249, 97}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 51, 7, 60, 203}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 175, 49}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 198}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 68, 234, 156, 201, 8, 184, 241}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 1, 14, 193, 241, 224, 157, 213}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 80, 18, 254}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 81, 79, 129}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 229}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 37, 23, 233, 45}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 185, 125, 160, 20, 63}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 168, 51, 133, 241, 195, 151}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 27, 187, 193, 2}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 223, 220, 64, 145, 168, 121}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 165, 184, 7, 178, 210, 44}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 193, 108, 113, 98, 15, 162, 127}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 90, 243, 102, 37, 23, 161}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 18, 163, 82, 38, 116, 5, 72}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 120, 225, 80, 121, 39, 56, 238, 254}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 162, 197, 168, 187, 177, 244, 245, 150}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 133, 39, 224, 70}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 193, 170, 201, 227, 192, 73}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 2, 172, 203, 244, 172, 48}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 6, 115, 76, 68, 248, 230, 177}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 28, 119, 106}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 244}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 169, 228, 239, 15, 233}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 226, 92, 80, 99, 241, 68}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 193}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 227, 106, 96}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 229, 152, 125, 65, 37, 193}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 153, 107}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 168, 158, 133, 237}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 95, 118, 116, 157, 23}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 116, 166, 54, 214, 114, 22}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 236}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 236, 29, 238, 241, 92, 85}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 85, 246, 251, 126, 197, 191, 196}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 92, 233, 51, 213}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 129, 24, 252, 127}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 129}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 16, 41, 254}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 49, 215, 178}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 229}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 88, 27, 150, 148, 148, 180, 97}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 241, 106, 6, 7, 71}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 72, 248}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 254, 164, 31, 134}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 150, 30, 111, 232}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 223, 217}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 69, 204, 49, 152, 110, 16, 87}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 135, 111, 37, 4}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 150, 128, 208, 33}, 238}, {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 65, 16, 19, 39}, 238}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 108, 244}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 20}, {{16, 50, 248, 88, 0, 0, 0, 44, 19, 49, 124, 28, 6, 181, 52, 124}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 48, 206, 194, 21, 181}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 237}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 122, 47, 196, 22, 133, 93, 120, 71}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 118, 149, 241, 145, 52}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 71, 124, 173, 151}, 20}, {{16, 50, 248, 88, 0, 0, 0, 156, 212, 85, 201, 54, 157, 208, 207, 72}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 227, 199}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 135, 240, 24, 154, 249, 251, 49, 123}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 79, 199, 63, 16, 226}, 20}, {{16, 50, 248, 88, 0, 102, 65, 55, 183, 56, 110, 197, 113, 74, 200, 59}, 20}, {{16, 50, 248, 88, 0, 0, 70, 130, 240, 94, 104, 211, 138, 103, 190, 85}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 254, 113, 144, 106, 74, 222, 155, 62}, 20}, {{16, 50, 248, 88, 0, 0, 0, 94, 191, 83, 131, 83, 246, 122, 254, 57}, 20}, {{16, 50, 248, 88, 0, 0, 103, 114, 16, 29, 131, 21, 253, 251, 118, 33}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 206, 11, 31, 79, 174, 235, 137}, 20}, {{16, 50, 248, 88, 0, 0, 249, 241, 106, 166, 200, 107, 208, 246, 222, 73}, 20}, {{16, 50, 248, 88, 0, 0, 86, 99, 251, 194, 83, 106, 154, 192, 186, 53}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 8, 226, 70, 74, 114}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 42, 129}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 204, 169}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 112, 119, 85, 223}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 95, 34}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 235, 160}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 162, 67, 67, 74, 129}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 25, 197, 69, 96}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 68}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 20}, {{16, 50, 248, 88, 61, 0, 161, 204, 96, 231, 190, 28, 35, 58, 56, 12}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 130, 1}, 20}, {{16, 50, 248, 88, 0, 0, 0, 164, 119, 86, 188, 236, 249, 14, 207, 90}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 115, 72, 63, 58, 2, 185, 247}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 253, 53, 1, 96, 63, 169, 87}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 109, 212, 168, 46, 75}, 20}, {{16, 50, 248, 88, 0, 154, 60, 36, 6, 16, 31, 194, 173, 101, 63, 73}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 129, 197, 245, 163}, 20}, {{16, 50, 248, 88, 0, 62, 58, 113, 217, 59, 126, 160, 154, 226, 110, 239}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 127, 95, 81, 147, 22, 212}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 75, 30, 170, 156, 222, 118, 81, 238}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 20}, {{16, 50, 248, 88, 0, 38, 99, 165, 61, 251, 236, 19, 189, 9, 186, 52}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 51, 107}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 240, 189, 184, 188, 209, 204}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 232, 27, 61, 64, 6, 255, 186}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 35, 58, 133, 87, 15, 200, 122, 49}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 157, 223, 221, 210, 206, 112, 84}, 20}, {{16, 50, 248, 88, 0, 0, 0, 107, 186, 40, 79, 26, 37, 74, 107, 180}, 20}, {{16, 50, 248, 88, 0, 225, 128, 134, 118, 76, 2, 42, 53, 132, 6, 165}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 205, 78, 18, 116, 127, 112, 228}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 254, 232, 55, 146, 31, 170}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 221, 5, 233, 194, 109, 147, 159}, 20}, {{16, 50, 248, 88, 0, 0, 36, 107, 45, 164, 166, 175, 85, 179, 232, 108}, 20}, {{16, 50, 248, 88, 0, 0, 24, 159, 221, 235, 35, 179, 179, 53, 65, 31}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 45, 237, 108, 221, 217, 149}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 180, 137, 118, 205}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 30, 58, 108, 72}, 20}, {{16, 50, 248, 88, 0, 0, 87, 252, 208, 207, 165, 249, 27, 246, 78, 122}, 20}, {{16, 50, 248, 88, 0, 123, 46, 157, 32, 255, 89, 91, 19, 39, 23, 57}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 115, 42, 56, 240}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 66, 125, 181, 160, 155}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 77, 154, 223, 93}, 20}, {{16, 50, 248, 88, 0, 0, 0, 135, 234, 16, 135, 229, 145, 247, 113, 207}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 124, 47, 119, 137, 2, 24, 119, 77}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 125, 31, 134, 68, 22}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 165, 14}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 101}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 148, 67, 190, 133}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 134, 6, 227, 147, 243}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 211, 127, 209, 247, 22, 51, 103}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 136, 171, 80, 180, 12}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 20}, {{16, 50, 248, 88, 0, 0, 138, 64, 98, 121, 53, 74, 184, 20, 240, 191}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 32, 101, 245, 88, 42, 120}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 125, 162, 236, 183}, 20}, {{16, 50, 248, 88, 0, 0, 0, 200, 78, 252, 20, 15, 203, 88, 251, 101}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 3, 101, 222, 148, 154, 147}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 137, 229}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 247, 5, 163, 154, 168}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 94, 170, 245, 147, 245, 74, 163}, 20}, {{16, 50, 248, 88, 0, 0, 132, 157, 195, 221, 193, 138, 28, 201, 88, 48}, 20}, {{16, 50, 248, 88, 0, 185, 110, 185, 174, 204, 240, 12, 174, 7, 12, 102}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 46, 44, 213, 97, 60}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 47, 171}, 20}, {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 189, 221, 43, 121, 174}, 20}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 205, 167}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 39, 25, 82, 224}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 227, 224}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 166, 0, 242, 143, 242, 241}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 45, 118, 227, 129, 30, 82}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 181, 115, 119}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 228, 88, 85}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 67, 98, 196, 129}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 98, 77, 152}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 110, 25, 98, 15, 45, 7, 214, 200}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 53, 195, 206}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 208, 116, 64, 233, 61, 162}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 210, 91}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 148, 111, 101, 2, 41, 1, 67, 255}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 87, 227}, 84}, {{189, 96, 58, 53, 191, 235, 64, 170, 144, 217, 73, 140, 33, 238, 151, 83}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 237, 239, 230, 179}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 111, 108, 135}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 122, 2, 160, 83}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 12, 254, 211, 57, 189, 90}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 180, 72, 213}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 75, 191, 183, 102, 33, 47, 235}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 38, 132, 71, 188}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 129, 239, 157, 125, 93, 207, 208}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 202, 249}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 61, 239}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 20, 2, 107, 58, 70, 189, 225, 139}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 84, 49, 94, 109, 87, 141, 54, 23}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 60, 68, 131, 225}, 84}, {{189, 96, 58, 53, 191, 235, 64, 143, 253, 248, 104, 183, 23, 159, 210, 86}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 226, 153, 211, 67}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 186, 141, 58, 197, 106, 96}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 240, 122, 33, 144, 94, 124}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 132, 220}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 207, 2, 174, 180}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 58, 249}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 240, 199, 51, 53, 217, 242, 121}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 20, 48, 143, 181, 65, 43}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 135, 100, 134, 158, 219}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 187, 127, 144, 59, 196}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 98, 250, 237}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 218, 231}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 253, 204, 103, 157, 24, 224, 152, 142}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 191, 5}, 84}, {{189, 96, 58, 53, 191, 235, 64, 56, 27, 241, 167, 171, 205, 106, 227, 29}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 83, 182, 70, 166, 46}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 145, 9, 192}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 84, 207, 154}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 211, 158, 51, 16, 7, 185}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 42, 60, 247}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 92, 106, 76}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 27, 149, 125}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 52, 109}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 225, 86}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 205, 191, 137, 181, 208, 94, 117}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 200, 232}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 225, 215, 38}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 38, 231, 57, 39, 212, 40, 189, 26}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 129, 116, 192, 110, 91, 10, 82}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 53, 119, 203}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 218, 6}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 141, 116, 123, 242, 229}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 98, 82, 195}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 17, 166, 85, 235, 171, 178}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 127, 137, 212}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 149, 126, 14}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 96, 177, 136, 160, 135}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 219, 8, 153}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 101, 67, 208}, 84}, {{189, 96, 58, 53, 191, 235, 64, 36, 167, 11, 88, 28, 182, 127, 249, 149}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 22, 35, 189, 143, 227, 229}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 199, 80, 215, 246}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 15, 244}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 83, 127, 105, 9}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 45, 244, 160}, 84}, {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 216, 70, 85}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 56, 131, 201, 68, 77}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 45, 101, 92, 224, 46, 40, 176, 110}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 180, 148, 51, 1, 53, 56, 84, 139}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 38, 252, 232, 112, 76, 50, 160, 236}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 138, 241, 71, 205, 173, 233, 64}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 120, 165}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 132, 100, 236, 72}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 55, 119, 3, 12, 3, 212, 93, 200}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 51, 104, 110, 82, 115, 112}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 49, 180, 121, 185, 67, 21, 97, 225, 82}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 242, 84, 122, 38, 90}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 134, 98, 113, 177, 21, 96, 45}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 78, 5, 148, 178, 57}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 29, 232}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 57, 3, 117, 105, 87}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 166, 120, 41}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 226, 168, 167}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 225, 92, 93, 238, 198}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 115, 232, 179, 127, 157, 40, 111}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 6, 47, 9, 83, 168}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 119, 238, 157, 15, 137, 91}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 101, 218}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 28, 215}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 187, 127, 197, 230, 167, 100, 213, 162, 17}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 1, 52}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 250, 150, 194, 194, 191, 76, 139}, 108}, {{111, 98, 6, 65, 35, 192, 0, 158, 98, 40, 9, 56, 254, 104, 221, 131}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 110, 210, 90, 211, 35, 227, 243, 145}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 16, 246, 22, 179, 129}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 103, 132, 45, 155, 245}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 235, 23, 19, 188, 171, 14, 142}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 67, 16}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 169, 15, 222}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 103, 37, 231, 232, 70, 255, 140, 234}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 44, 125, 139, 198}, 108}, {{111, 98, 6, 65, 35, 192, 0, 127, 113, 9, 7, 41, 200, 59, 177, 155}, 108}, {{111, 98, 6, 65, 35, 192, 0, 144, 215, 17, 238, 239, 10, 220, 131, 79}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 231, 108, 14}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 74, 108, 32, 82, 30}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 206, 20}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 236, 186, 216, 5, 174}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 241, 205, 34}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 177, 153, 93, 136, 144, 4, 66, 22}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 215, 217, 242, 32}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 212, 129, 76, 70, 170}, 108}, {{111, 98, 6, 65, 35, 192, 120, 167, 94, 39, 119, 85, 7, 105, 87, 75}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 91, 33, 121, 226, 14}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 30, 51, 246}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 163, 233, 138, 55}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 123, 46}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 135, 171, 164, 50, 182, 254, 86}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 198, 175, 138, 162, 180, 147, 151, 72}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 88, 212}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 93, 63, 165, 240, 143}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 222, 58, 81}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 85, 9, 45, 132, 58}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 188, 134}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 109, 55, 31}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 226, 5, 201, 111, 118, 22, 9, 76}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 84, 65, 233}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 3, 36, 1, 176}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 108, 50}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 20, 85, 4, 39}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 209, 50, 225, 198}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 237, 16}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 227, 33}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 141, 155, 129, 10, 11, 49, 95}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 45, 197}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 90, 142, 12, 71, 220, 152}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 194, 87, 111, 21, 110, 241}, 108}, {{111, 98, 6, 65, 35, 192, 146, 82, 110, 163, 221, 103, 73, 130, 245, 241}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 203, 237}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 158, 118}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 17, 251, 83, 73}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 195, 10, 102, 27, 230, 217}, 108}, {{111, 98, 6, 65, 35, 192, 0, 13, 225, 63, 130, 130, 174, 69, 86, 228}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 69, 18}, 108}, {{111, 98, 6, 65, 35, 192, 0, 72, 15, 210, 73, 175, 240, 25, 47, 237}, 108}, {{111, 98, 6, 65, 35, 192, 89, 49, 220, 236, 72, 3, 167, 83, 137, 101}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 48, 198, 12}, 108}, {{111, 98, 6, 65, 35, 192, 199, 31, 92, 231, 35, 204, 58, 53, 190, 219}, 108}, {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 98, 170, 100, 84}, 108}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 87, 120, 48}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 197, 217}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 98}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 127, 130, 95}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 224, 69, 26, 136}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 13, 63, 37}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 82}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 18, 123}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 159, 46}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 253}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 5, 154, 89}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 25, 198, 242}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 19, 9, 67, 223}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 97, 2}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 220, 246, 228, 78}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 186, 24}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 106}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 248}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 181, 171}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 79, 68}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 80, 246}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 64, 221, 174, 183}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 193}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 133, 19}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 161, 82}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 172}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 146, 177, 81, 116}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 35, 3, 40}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 200, 27}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 105, 192, 241}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 236, 251}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 95, 150, 117}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 233, 219, 52, 160}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 154, 55}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 153, 78, 143, 207}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 2, 59, 160}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 12, 129, 53, 87}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 193, 54, 220}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 189, 187, 233, 92}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 153}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 99}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 113}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 11, 183, 145, 210}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 115, 23}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 74, 210, 70, 193}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 89, 42, 62}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 138, 167, 175}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 141}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 109}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 163}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 202}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 65, 49}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 101, 147, 254}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 146}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 94, 92}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 243}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 237, 147, 53}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 198, 227, 197, 208}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 176, 206, 18, 244}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 143, 39, 137}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 141}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 107, 228}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 107, 29, 231, 57}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 50, 175}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 134}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 123, 26}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 149, 157, 18, 46}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 187, 41, 36}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 166}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 108}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 12, 109}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 136}, {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 30, 240, 167, 56}, 136}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 217}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 223, 113, 237}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 67, 96, 73, 52}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 245, 194}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 255, 99, 110, 102}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 18}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 41, 5, 192}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 214, 45, 18}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 130, 186, 216}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 55}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 186, 213}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 95}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 64, 226, 251}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 110, 128}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 223, 106}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 161, 203, 234}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 107}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 182, 118, 162}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 203, 236, 8, 108}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 13}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 142}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 137}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 165, 179, 151}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 119, 22, 193}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 74, 9, 54}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 129, 247, 215}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 101, 106}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 203}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 149, 150}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 148}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 173, 8}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 30, 24, 102}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 227, 5, 37}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 141}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 179, 165}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 125}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 245, 66, 231}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 31, 30, 167, 88}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 46, 197}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 94}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 209}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 190}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 11, 255, 7, 105}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 244}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 242, 159, 59}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 55, 224, 91, 106}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 220, 242, 77}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 74}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 13, 167, 72, 254}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 202, 145, 79}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 119}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 129, 185}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 228, 202, 128}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 106, 123, 231, 4}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 10, 143}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 207}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 93, 59}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 99, 41, 121}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 30}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 122, 157}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 177, 54, 161, 190}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 223}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 135, 45, 90, 158}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 167}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 49}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 13}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 212, 129}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 101, 236, 57}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 7, 32, 242}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 86, 9, 105, 138}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 173}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 44}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 26, 13}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 55, 143}, 196}, {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 77, 240}, 196}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 237, 255, 159, 117}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 252, 72, 216, 65, 15, 33, 49}, 67}, {{26, 76, 129, 48, 0, 0, 0, 139, 238, 78, 246, 6, 80, 15, 68, 189}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 175, 219, 235, 159, 60, 217, 65, 252}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 32, 60}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 67}, {{26, 76, 129, 48, 0, 0, 244, 21, 214, 149, 207, 197, 65, 19, 143, 184}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 198, 20}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 225}, 67}, {{26, 76, 129, 48, 0, 0, 92, 134, 99, 254, 25, 171, 125, 3, 143, 133}, 67}, {{26, 76, 129, 48, 0, 0, 109, 176, 33, 95, 138, 168, 88, 144, 150, 22}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 190, 173}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 181, 123, 213, 221, 39}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 49}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 201, 62, 193, 155, 162, 95, 252, 248}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 253, 93, 213, 122, 29, 203, 158, 229}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 214, 12}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 30, 166}, 67}, {{26, 76, 129, 48, 0, 0, 110, 225, 2, 210, 50, 72, 212, 225, 48, 155}, 67}, {{26, 76, 129, 48, 0, 0, 0, 154, 96, 124, 138, 47, 55, 153, 191, 122}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 187, 175}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 143}, 67}, {{26, 76, 129, 48, 0, 132, 130, 147, 50, 33, 76, 103, 10, 133, 60, 15}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 132, 50}, 67}, {{26, 76, 129, 48, 0, 27, 180, 5, 95, 37, 88, 1, 66, 50, 30, 74}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 88, 98, 183, 179}, 67}, {{26, 76, 129, 48, 0, 221, 158, 150, 146, 138, 216, 193, 230, 250, 80, 114}, 67}, {{26, 76, 129, 48, 0, 95, 139, 33, 247, 104, 248, 124, 217, 210, 14, 81}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 11, 135, 103, 145, 31}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 102, 139}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 145, 17, 226, 106, 0, 190, 19, 181}, 67}, {{26, 76, 129, 48, 0, 123, 122, 51, 131, 226, 139, 122, 142, 82, 122, 41}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 163, 121, 171, 126, 101, 157, 192}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 36, 58, 223, 141}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 84, 101, 254, 136, 105}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 11, 142, 137, 107, 48, 116}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 4, 53}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 196, 244, 90, 147, 48, 217, 11}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 73, 35, 59, 132, 253, 35, 56}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 232, 220, 189, 160, 137, 127, 182, 105}, 67}, {{26, 76, 129, 48, 71, 223, 232, 25, 245, 209, 156, 170, 248, 230, 135, 9}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 126, 32, 63, 175}, 67}, {{26, 76, 129, 48, 0, 0, 0, 199, 68, 125, 204, 101, 43, 186, 142, 6}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 237, 246, 164, 224, 141, 94, 46}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 100}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 101, 195, 198, 160, 181, 163, 250, 100}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 220, 35}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 67}, {{26, 76, 129, 48, 0, 77, 234, 134, 176, 134, 66, 12, 172, 116, 138, 134}, 67}, {{26, 76, 129, 48, 0, 0, 239, 76, 88, 241, 135, 36, 48, 131, 144, 251}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 167}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 23, 100, 11, 234, 41, 129}, 67}, {{26, 76, 129, 48, 0, 4, 58, 155, 26, 75, 32, 56, 110, 169, 157, 242}, 67}, {{26, 76, 129, 48, 0, 0, 251, 90, 161, 168, 39, 63, 247, 229, 236, 12}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 123, 85, 19, 176, 89, 253, 244}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 120, 122, 66, 219, 228, 212, 201, 84}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 24, 83, 158, 138, 156, 26, 225}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 122, 191, 169, 55, 46}, 67}, {{26, 76, 129, 48, 0, 0, 0, 199, 171, 134, 10, 104, 228, 197, 137, 155}, 67}, {{26, 76, 129, 48, 0, 0, 202, 129, 1, 138, 192, 248, 251, 114, 138, 1}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 204}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 168, 162}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 75, 247, 75, 211, 210, 150, 137, 181}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 64, 126, 205, 153, 249, 141, 205, 100}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 67}, {{26, 76, 129, 48, 68, 52, 12, 9, 73, 252, 237, 79, 191, 232, 233, 134}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 176, 98, 145, 129, 53, 34, 192}, 67}, {{26, 76, 129, 48, 0, 0, 0, 12, 138, 181, 244, 142, 24, 127, 150, 137}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 82, 241}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 141, 183, 185, 13}, 67}, {{26, 76, 129, 48, 0, 0, 0, 52, 214, 129, 130, 169, 16, 223, 44, 80}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 71, 2, 14, 247}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 63}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 181, 171, 72, 129, 198, 102, 56}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 79, 143, 213, 47, 1, 5, 187}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 207, 153}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 53, 167}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 186}, 67}, {{26, 76, 129, 48, 0, 0, 109, 184, 68, 108, 227, 48, 55, 152, 30, 152}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 127, 139}, 67}, {{26, 76, 129, 48, 180, 253, 179, 231, 157, 223, 80, 128, 20, 158, 47, 72}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 30, 109, 26, 5, 3, 193, 86}, 67}, {{26, 76, 129, 48, 0, 0, 0, 77, 95, 161, 235, 105, 192, 219, 147, 95}, 67}, {{26, 76, 129, 48, 124, 206, 202, 183, 160, 230, 148, 229, 64, 178, 62, 202}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 220, 99}, 67}, {{26, 76, 129, 48, 0, 0, 15, 122, 18, 51, 61, 14, 193, 160, 12, 227}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 192}, 67}, {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 198, 38}, 67}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 146, 146, 56, 2, 54, 13, 25}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 47, 58, 83, 63, 24, 224}, 104}, {{231, 96, 0, 0, 0, 37, 68, 129, 10, 206, 22, 213, 57, 207, 62, 195}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 104}, {{231, 96, 0, 0, 0, 0, 10, 240, 176, 45, 69, 52, 213, 162, 129, 154}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 124, 19, 159}, 104}, {{231, 96, 0, 0, 170, 106, 13, 237, 156, 240, 54, 235, 14, 22, 172, 244}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 52, 157, 212, 210}, 104}, {{231, 96, 0, 68, 19, 117, 190, 31, 157, 106, 86, 47, 143, 187, 143, 237}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 29}, 104}, {{231, 96, 0, 0, 0, 0, 0, 244, 199, 86, 153, 190, 144, 122, 161, 116}, 104}, {{231, 96, 0, 68, 14, 223, 56, 77, 189, 52, 225, 108, 113, 55, 116, 53}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 246, 19, 236, 75, 126, 218, 254, 30}, 104}, {{231, 96, 0, 82, 62, 217, 47, 93, 40, 46, 45, 110, 164, 209, 32, 167}, 104}, {{231, 96, 144, 84, 202, 100, 223, 216, 8, 157, 151, 142, 195, 157, 44, 248}, 104}, {{231, 96, 0, 127, 67, 228, 105, 190, 30, 106, 136, 19, 164, 3, 56, 48}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 66, 37, 80, 76}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 98, 250, 160, 153, 95, 178, 192, 215, 107, 233, 14, 197}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 188, 72, 253, 53}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 136, 177, 89, 140}, 104}, {{231, 96, 0, 0, 0, 164, 205, 46, 127, 203, 36, 240, 104, 90, 33, 240}, 104}, {{231, 96, 0, 0, 136, 129, 149, 116, 182, 156, 218, 187, 49, 253, 15, 97}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 142, 152, 38}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 150, 137, 177}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 104, 82, 33, 13, 111, 147, 219, 4}, 104}, {{231, 96, 0, 0, 0, 0, 0, 66, 77, 219, 239, 191, 105, 18, 173, 204}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 216, 57, 181, 151, 96, 180, 246}, 104}, {{231, 96, 0, 0, 0, 0, 157, 75, 142, 6, 21, 51, 25, 211, 163, 93}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 56, 73, 49, 35, 57, 182}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 151, 31, 75, 57, 220, 252, 202, 230}, 104}, {{231, 96, 0, 0, 0, 0, 0, 90, 127, 81, 65, 243, 126, 233, 162, 123}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 175, 207}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 161, 165, 10, 42, 6, 180, 55}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 125, 64, 233, 86, 168, 138, 152, 24}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 249, 113, 137, 241, 230, 244, 49, 55}, 104}, {{231, 96, 0, 0, 180, 63, 97, 118, 120, 80, 191, 67, 227, 173, 8, 23}, 104}, {{231, 96, 0, 0, 0, 0, 121, 110, 137, 125, 42, 45, 71, 236, 195, 118}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 176}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 201}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 193}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 210, 156, 97}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 251, 243}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 232, 111}, 104}, {{231, 96, 0, 0, 110, 46, 87, 178, 58, 113, 14, 190, 209, 65, 17, 199}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 50, 148, 173, 41}, 104}, {{231, 96, 0, 0, 78, 80, 35, 107, 65, 182, 83, 120, 54, 162, 37, 121}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 76, 239, 197, 112, 118, 111}, 104}, {{231, 96, 0, 0, 0, 0, 0, 41, 71, 157, 134, 2, 226, 101, 2, 9}, 104}, {{231, 96, 0, 0, 17, 153, 237, 129, 67, 33, 136, 155, 47, 128, 188, 139}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 89, 50}, 104}, {{231, 96, 0, 0, 0, 213, 229, 211, 199, 173, 60, 218, 178, 65, 65, 251}, 104}, {{231, 96, 35, 145, 215, 24, 205, 24, 197, 156, 112, 187, 171, 204, 49, 213}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 210, 69, 165, 249, 204, 221}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 5, 94, 24, 140, 61, 142, 79, 229}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 250, 154, 146, 169, 111, 223, 198}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 252, 62, 41, 17, 230, 67, 125, 49}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 168, 236, 141, 182, 11, 181, 88}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 68, 186, 156, 244}, 104}, {{231, 96, 0, 0, 0, 0, 0, 171, 196, 49, 225, 171, 90, 229, 57, 229}, 104}, {{231, 96, 0, 0, 0, 0, 0, 56, 49, 214, 156, 147, 192, 80, 171, 194}, 104}, {{231, 96, 0, 0, 221, 49, 117, 212, 243, 156, 86, 3, 17, 248, 117, 249}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 239, 15, 223, 22}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 107, 83, 46, 216, 157, 255, 80, 119, 25, 175}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 8, 214, 7, 41, 34, 254}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 16, 210, 173, 131, 106, 5, 247, 124}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 49, 155, 84}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 16, 86, 255}, 104}, {{231, 96, 0, 0, 189, 26, 108, 107, 208, 152, 113, 11, 5, 68, 158, 98}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 250, 95, 83, 166, 119, 221}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 164, 53}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 50, 128}, 104}, {{231, 96, 0, 0, 0, 227, 115, 182, 254, 204, 64, 143, 146, 216, 43, 129}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 5, 121, 246, 88, 24, 92}, 104}, {{231, 96, 0, 0, 0, 0, 0, 178, 39, 244, 120, 91, 50, 28, 15, 202}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 125, 4, 170, 156}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 187}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 75}, 104}, {{231, 96, 0, 0, 0, 0, 0, 107, 102, 188, 221, 128, 111, 236, 202, 7}, 104}, {{231, 96, 0, 0, 0, 0, 61, 195, 150, 236, 204, 104, 46, 126, 144, 52}, 104}, {{231, 96, 0, 254, 150, 207, 225, 16, 186, 55, 48, 209, 175, 193, 135, 140}, 104}, {{231, 96, 0, 0, 0, 0, 0, 91, 225, 186, 242, 231, 82, 140, 72, 34}, 104}, {{231, 96, 0, 0, 0, 0, 246, 20, 222, 237, 101, 233, 125, 156, 33, 130}, 104}, {{231, 96, 0, 0, 198, 185, 116, 207, 160, 152, 105, 94, 221, 9, 213, 197}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 12, 167, 83, 193, 153, 59, 20}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104}, {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 254, 22, 95, 127, 116, 187}, 104}, {{93, 172, 223, 252, 203, 0, 206, 0, 243, 148, 90, 38, 30, 244, 110, 162}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 92, 6, 189, 251, 230, 42, 194}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 219, 177, 218, 169, 66, 227, 240, 39}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 177, 68}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 193, 204, 234, 77}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 249, 174, 122, 18, 142, 120, 155}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 116, 145, 135, 53, 79}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 183, 55, 113, 191, 116, 111, 129}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 53, 136, 208}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 149, 165, 177, 39, 51, 106, 67, 220}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 150, 103, 114, 113, 54, 136}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 101, 140, 65, 47, 164}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 149, 156}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 76, 9, 28, 43, 80, 129}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 168, 187, 45, 219, 169, 247}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 140, 215, 181, 185, 206, 80, 191, 15}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 18, 162, 246, 60, 128, 146, 146, 2}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 143, 204}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 65, 227, 83}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 117, 216, 233}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 12, 135, 67, 195, 113}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 124, 74, 60, 60}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 189, 87, 70, 32, 42}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 104, 37, 20, 189, 12, 27, 255}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 213, 57, 87, 86, 173, 93, 108, 94}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 104, 236, 9, 127, 243, 222, 201}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 183, 181, 158, 172}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 80, 11, 138}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 254, 111, 26}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 80, 223, 113}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 211, 170, 228, 180, 209}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 191, 214, 178, 97, 129}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 16, 104, 205, 59, 23, 178}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 150, 67, 156, 3}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 147, 0, 244, 22}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 53, 188, 212, 122}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 188, 108}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 186, 226}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 218, 24, 232, 180, 97}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 124, 232, 62, 139, 245, 229, 28}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 35, 148, 152, 192, 154}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 76, 245, 98, 234, 242, 16}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 133, 49, 223, 150, 44, 113, 51}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 223, 17, 67}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 70, 72, 225, 76, 240, 191, 41}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 77, 176}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 3, 85, 128, 176, 137, 0, 203, 67}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 205, 52}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 61, 64, 41, 202, 228, 198}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 253, 138, 29, 103, 76, 11}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 167, 218, 181, 195, 44, 33}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 154, 1, 209, 96, 244, 54}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 64, 30, 102, 142, 148, 73}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 199, 163, 187, 144}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 240, 172}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 187, 115}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 36, 118, 193, 222, 157, 32}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 44, 131, 45, 191, 114}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 93, 130, 16}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 104, 95, 175, 246, 74, 25}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 147, 243, 145, 253, 232, 174}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 169, 242, 11, 32, 252, 94, 227}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 202, 141, 156}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{93, 172, 223, 252, 203, 0, 206, 70, 166, 67, 11, 150, 44, 61, 45, 164}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 255, 73, 83, 170, 4}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 150, 139, 176, 220, 81, 249, 75}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 128, 142, 14, 0, 37, 181}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 118, 249, 195, 225, 94, 243, 225, 232}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 111, 81, 20, 170, 57}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 135, 231, 53, 64}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 136, 191, 254, 147}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 100, 44}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 27, 232, 108, 50, 161, 101, 14}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 17, 117, 118}, 15}, {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 173, 97}, 15}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 237}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 140}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 143}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 109}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 246}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 241}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 238}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 8}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 79}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 130}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 221}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 106}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 129}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 168}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 31}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 122}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 43}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 226}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 16}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 110}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 165}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 157}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 218}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 104}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 73}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 223}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 183}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 66}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 1}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 224}, {{99, 161, 189, 88, 48, 0, 0, 242, 49, 217, 144, 171, 81, 51, 214, 247}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 238, 74, 64, 167, 133, 177, 66, 229}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 160, 231, 245, 84, 187, 147, 118, 106}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 39, 206, 9, 114, 192, 101, 82, 46, 204, 232}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 79, 146, 209, 32}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 231, 113, 155, 120, 42, 130, 222}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 167, 94, 204}, 179}, {{99, 161, 189, 88, 48, 39, 104, 159, 15, 152, 244, 86, 239, 237, 6, 242}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 223, 186, 66, 18, 117, 225}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 142, 203, 190, 102, 86, 209}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 215, 69, 79, 56, 111}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 141}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 245, 127, 255, 248, 4}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 177, 70, 186, 87}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 187, 167, 145, 234, 38, 85, 180, 27}, 179}, {{99, 161, 189, 88, 48, 0, 214, 71, 118, 29, 38, 197, 138, 12, 50, 242}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 113, 191, 153, 2, 54, 221, 127, 174}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 90, 88, 33, 113, 57, 65, 79, 23}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 69}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 132, 186, 242, 11, 229}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 102, 171, 127, 161, 226, 136}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 51, 62, 252, 13}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 235, 88, 94, 235, 131, 149, 16, 73}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 108, 235, 93, 152, 61, 170, 125, 168, 179, 126}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 242, 17, 240, 167, 242, 102, 141}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 203, 28, 53, 196, 182}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 71, 16, 136, 233, 83, 243, 211, 194, 128}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 117, 117, 58, 193, 39, 184, 114, 216}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 132, 81, 122, 237}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 3, 177, 55, 121, 28, 104, 191, 156, 72}, 179}, {{99, 161, 189, 88, 48, 0, 165, 234, 55, 44, 148, 58, 3, 68, 167, 49}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 123, 69, 75, 164, 174, 49, 161, 220}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 8, 40, 253, 102, 224, 170, 97, 44}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 43, 204, 151, 4, 1, 106}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 234}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 127, 82, 231}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 28}, 179}, {{99, 161, 189, 88, 48, 0, 0, 20, 252, 137, 253, 2, 146, 193, 63, 175}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 92, 215, 95, 255}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 207, 54, 192, 193, 178}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 195, 172, 113, 154}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 38, 54, 105, 47}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 55}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 64, 47, 104, 67, 31}, 179}, {{99, 161, 189, 88, 48, 25, 38, 85, 134, 43, 108, 207, 80, 186, 197, 110}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 107, 56, 137, 236}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 219, 21, 238, 225, 174, 105}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 243, 233, 195, 175}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 13, 38, 74, 231, 219, 74, 232, 151, 156, 52, 100}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 24, 235, 50, 202, 146, 16, 163, 1, 107, 37, 192}, 179}, {{99, 161, 189, 88, 48, 0, 116, 107, 115, 58, 238, 26, 229, 33, 101, 54}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 96}, 179}, {{99, 161, 189, 88, 48, 0, 0, 62, 29, 115, 61, 171, 121, 135, 58, 3}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 178, 209, 105, 176, 194, 159, 170, 221}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 221}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 179}, {{99, 161, 189, 88, 48, 0, 0, 149, 65, 172, 153, 132, 169, 200, 38, 255}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 203, 103, 92}, 179}, {{99, 161, 189, 88, 48, 0, 250, 212, 143, 253, 25, 129, 181, 63, 31, 245}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 147, 161, 248, 239}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 245}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 142, 193, 150, 145, 182}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 113, 212, 81, 98, 207}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 98, 152, 115, 0, 117, 52, 86, 48}, 179}, {{99, 161, 189, 88, 48, 193, 1, 122, 86, 68, 67, 109, 84, 151, 71, 142}, 179}, {{99, 161, 189, 88, 48, 62, 186, 221, 224, 71, 23, 135, 216, 239, 234, 146}, 179}, {{99, 161, 189, 88, 48, 0, 0, 230, 133, 58, 255, 60, 97, 64, 132, 78}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 229, 250, 2, 87, 246, 228, 50, 68}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 120, 129, 234, 10, 28, 220}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 126, 122, 139, 71, 109, 111}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 167, 245, 174, 109, 28}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 202, 245, 61}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 35, 66, 237, 76, 11}, 179}, {{99, 161, 189, 88, 48, 0, 0, 64, 207, 0, 66, 226, 119, 231, 19, 56}, 179}, {{99, 161, 189, 88, 48, 0, 0, 117, 239, 65, 214, 113, 172, 210, 208, 15}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 65, 96, 104}, 179}, {{99, 161, 189, 88, 48, 0, 133, 7, 101, 27, 12, 181, 57, 18, 110, 156}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 60}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 50}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 185, 196, 189, 76, 216, 144}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 242, 204, 16, 158, 92}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 25, 155, 0, 28, 58, 198, 69}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 141, 60, 42}, 179}, {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 179}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 229, 123, 252, 187, 33, 163}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 132}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 83}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 187, 229}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 115, 147, 42, 133, 174, 222}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 172, 150}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 175}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 94, 165}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 231, 161, 197, 45, 130}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 18, 191, 161, 3, 17, 109, 224}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 202, 229, 21, 54, 177}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 212, 136, 13}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 111, 42, 148, 34, 74}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 197, 183, 165, 189, 74}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 92, 233, 212, 196, 214, 225}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 196, 83, 140}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 53, 224, 25}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 59, 228}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 10, 97, 152, 129, 42}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 238, 123, 99, 156, 80}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 205, 65, 209, 190}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 254, 37, 4}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 128, 150, 137, 40}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 123, 234, 7}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 89, 6}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 118, 73}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 49, 252, 167}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 195, 55, 14, 234, 143, 55}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 87}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 94, 175, 235, 101, 186}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 113, 27, 75, 190}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 30, 39, 25, 163, 197, 255, 117}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 45, 22, 229, 244, 18, 69}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 254, 162, 217}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 30, 216, 11}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 7, 132, 142, 177, 158, 165}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 117}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 149, 235, 67}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 17, 141, 48, 184, 220, 154}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 212, 173}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 255, 71, 46, 234, 63, 185}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 247, 192, 229}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 252}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 76, 165, 13, 65, 45}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 148, 88, 112, 162, 216, 252}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 110}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 36, 22, 82, 34, 128}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 175}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 35, 251, 172, 109, 69, 3}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 22, 84, 148, 161, 248, 126}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 220, 172, 135}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 251, 105}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 84}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 68, 71}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 105, 82, 197, 239, 102, 88}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 169, 109, 129}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 230, 63, 26, 182}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 159, 58, 151, 69}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 165, 144, 117, 104, 141}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 225, 153, 198}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 26, 47, 137}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 197, 182, 166, 141, 236}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 93}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 172, 92, 94}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 66, 34, 216, 224, 94, 170, 203}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 129, 68, 134}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 223, 11, 87, 144}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 100, 179, 187, 211, 99}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 195, 216, 103}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 226, 37, 73}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 221, 135}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 185, 24, 226}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 78, 112, 102, 161}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 252, 111, 246, 204}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 90, 238, 239}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 182, 250}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 107, 66}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 163, 242, 8, 75, 107, 229}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 158, 21, 180}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 161}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 124}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 176, 109}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 41, 236, 215, 84}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 135, 53}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 193, 155}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 136, 224, 61, 78, 116, 152, 181}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 201}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 206, 112, 210, 61, 46}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 237}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 79, 151, 2}, 84}, {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 11, 92, 136, 160}, 84}, {{169, 53, 32, 0, 109, 56, 125, 26, 38, 72, 195, 158, 220, 255, 197, 179}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 96}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 110, 11, 73, 171, 16}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 236, 241, 146, 254, 25, 132, 126, 42}, 65}, {{169, 53, 32, 123, 55, 223, 140, 205, 106, 24, 74, 42, 255, 117, 206, 11}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 216}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 92}, 65}, {{169, 53, 32, 0, 0, 0, 134, 144, 59, 127, 70, 105, 37, 89, 105, 131}, 65}, {{169, 53, 32, 0, 183, 172, 113, 249, 246, 124, 10, 232, 145, 94, 155, 79}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 1, 91, 224, 36, 180, 75, 200}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 193, 102, 105}, 65}, {{169, 53, 32, 0, 0, 0, 219, 108, 99, 59, 25, 228, 209, 205, 58, 213}, 65}, {{169, 53, 32, 0, 0, 145, 67, 78, 238, 47, 61, 185, 156, 11, 195, 215}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 94, 90, 155, 98, 146, 87, 231, 1}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 250, 155, 147, 90, 206, 200, 241, 217}, 65}, {{169, 53, 32, 0, 0, 0, 124, 148, 74, 162, 65, 183, 57, 129, 255, 161}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 50, 247, 135, 49, 92}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 78, 147}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 51, 115, 69, 24, 246, 245, 214, 235, 59, 67, 232, 96}, 65}, {{169, 53, 32, 0, 0, 16, 143, 207, 87, 23, 115, 236, 175, 180, 237, 248}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 196, 224, 217, 47, 80, 48, 180, 188}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 9, 65, 206}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 41, 252, 78, 211, 11, 153}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 9, 20, 76, 98, 254, 203, 202}, 65}, {{169, 53, 32, 0, 0, 0, 0, 128, 132, 160, 95, 50, 157, 168, 120, 219}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 89, 38, 80, 199, 223}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 4, 91, 49, 67, 199, 113, 229, 118}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 62, 224, 216, 60, 155, 35}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 19, 16, 204, 120, 42, 249, 126}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 65}, {{169, 53, 32, 0, 0, 167, 146, 121, 173, 220, 108, 153, 41, 253, 196, 29}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 70, 118, 44, 168, 32, 210}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 171, 247, 139, 20, 52}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 81, 68, 108, 227, 236, 129, 184, 104}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 93, 255, 97, 100, 239, 244, 89}, 65}, {{169, 53, 32, 0, 0, 208, 15, 248, 147, 222, 33, 123, 74, 123, 175, 57}, 65}, {{169, 53, 32, 0, 0, 0, 0, 42, 225, 172, 83, 75, 180, 229, 84, 59}, 65}, {{169, 53, 32, 0, 52, 117, 127, 243, 92, 106, 163, 6, 73, 165, 231, 120}, 65}, {{169, 53, 32, 0, 0, 0, 174, 167, 112, 62, 229, 243, 82, 65, 72, 45}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 223, 54, 93, 137, 251, 186, 235, 18, 217, 166, 159, 235}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 73, 165, 88, 69, 65}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 144, 197}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 42, 247, 135, 17, 60}, 65}, {{169, 53, 32, 0, 0, 0, 0, 159, 29, 212, 204, 165, 185, 21, 190, 155}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 39, 8}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 156, 16, 64}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 134, 136, 78, 173, 144, 246, 15}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 181, 139, 57, 96, 122, 253}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 212, 29, 20, 203, 72, 253, 107}, 65}, {{169, 53, 32, 0, 119, 124, 100, 130, 192, 116, 96, 72, 52, 59, 88, 135}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 191, 109, 146}, 65}, {{169, 53, 32, 0, 0, 0, 0, 132, 53, 96, 191, 124, 132, 109, 186, 35}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 19, 85, 14, 37, 78, 253, 23}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 54, 117, 203}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 122, 83, 29, 33, 154, 89}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 3, 119, 82, 239, 92, 5, 89}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 224, 91, 22}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 89, 198, 143, 226, 198}, 65}, {{169, 53, 32, 0, 0, 0, 232, 54, 26, 55, 233, 177, 69, 9, 221, 86}, 65}, {{169, 53, 32, 0, 254, 144, 250, 238, 27, 199, 188, 47, 18, 16, 111, 41}, 65}, {{169, 53, 32, 85, 126, 8, 198, 119, 195, 55, 239, 31, 91, 79, 114, 168}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 44, 162}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 202, 44}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 65, 173, 141, 4, 53, 169, 15, 236}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 122, 248, 43, 149, 33, 31}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 168, 36}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 68, 106, 58, 63, 55}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{169, 53, 32, 0, 0, 0, 0, 121, 33, 254, 157, 189, 12, 200, 27, 31}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 83, 213, 36, 212, 255}, 65}, {{169, 53, 32, 0, 0, 0, 158, 88, 146, 110, 165, 144, 234, 146, 4, 113}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 11, 85, 84, 88, 22, 244, 27, 46}, 65}, {{169, 53, 32, 0, 57, 121, 102, 156, 106, 113, 182, 155, 143, 175, 120, 237}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 83, 134, 6, 42, 71, 163, 61, 161}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 134, 137, 33, 84, 174, 162, 196}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 185, 249, 135, 56, 98, 42, 125, 36}, 65}, {{169, 53, 32, 0, 0, 0, 247, 54, 64, 250, 173, 91, 102, 23, 87, 115}, 65}, {{169, 53, 32, 0, 0, 0, 34, 100, 13, 147, 138, 105, 108, 219, 151, 57}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 232, 38, 93}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 25, 113, 78, 210, 225, 235, 213, 104}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 124, 255, 185, 186, 30, 247, 136}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 252, 164, 54, 182, 29, 142, 19}, 65}, {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 226}, 65}, {{169, 53, 32, 0, 0, 0, 0, 199, 35, 181, 141, 2, 116, 41, 190, 79}, 65}, {{169, 53, 32, 0, 117, 37, 127, 201, 116, 133, 175, 138, 222, 98, 213, 40}, 65}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 224}, {{136, 0, 0, 0, 203, 122, 57, 113, 105, 31, 220, 236, 7, 36, 93, 96}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 76, 133, 219, 205, 46, 167, 25}, 224}, {{136, 0, 53, 15, 24, 85, 63, 180, 187, 94, 228, 34, 106, 220, 61, 30}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 48, 59}, 224}, {{136, 0, 0, 0, 0, 0, 0, 250, 163, 158, 203, 95, 136, 52, 111, 235}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 55, 207, 138}, 224}, {{136, 0, 18, 187, 215, 16, 72, 232, 141, 212, 214, 76, 192, 93, 119, 51}, 224}, {{136, 0, 0, 0, 109, 149, 196, 43, 53, 62, 37, 209, 103, 236, 58, 214}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 116}, 224}, {{136, 0, 0, 150, 183, 50, 99, 178, 70, 205, 74, 97, 185, 174, 150, 64}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 146, 93, 229, 246}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 31, 93, 139, 160}, 224}, {{136, 0, 0, 0, 127, 192, 240, 228, 153, 210, 236, 220, 126, 52, 138, 24}, 224}, {{136, 0, 0, 0, 0, 224, 60, 153, 96, 111, 7, 253, 134, 186, 75, 63}, 224}, {{136, 0, 0, 0, 0, 0, 0, 213, 92, 98, 55, 214, 98, 150, 147, 239}, 224}, {{136, 37, 100, 4, 190, 227, 50, 210, 127, 118, 60, 203, 118, 81, 32, 203}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 135, 49}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 127, 171}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 73, 172, 237, 30}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 143}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 83, 177, 59}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 170, 109, 142, 38}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 59, 88, 57, 160, 193}, 224}, {{136, 0, 0, 0, 0, 54, 76, 230, 147, 37, 81, 114, 249, 212, 51, 16}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 28}, 224}, {{136, 0, 171, 11, 158, 142, 245, 138, 234, 117, 4, 244, 203, 177, 107, 109}, 224}, {{136, 0, 31, 132, 61, 49, 87, 106, 243, 16, 219, 70, 89, 137, 119, 112}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 79, 92}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 244, 244, 19, 248}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 135}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 247, 14, 192, 156, 80, 157, 219, 64}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 152, 254}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 185, 55, 7, 249, 202, 251, 179, 105}, 224}, {{136, 0, 30, 9, 198, 66, 129, 172, 63, 233, 181, 160, 45, 132, 24, 92}, 224}, {{136, 0, 0, 158, 17, 224, 67, 105, 122, 155, 117, 89, 77, 209, 230, 177}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 126}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 122, 185, 92, 84, 62, 1, 234, 175}, 224}, {{136, 0, 0, 146, 189, 147, 15, 86, 183, 146, 50, 117, 130, 7, 194, 254}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 255, 60, 72}, 224}, {{136, 0, 0, 0, 0, 0, 0, 104, 107, 244, 138, 12, 78, 42, 103, 160}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 126, 215, 139}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 57, 51}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 243, 80}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 186}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 1, 233, 242, 71, 100, 0, 189, 208}, 224}, {{136, 0, 0, 0, 0, 0, 158, 251, 176, 90, 144, 89, 112, 196, 49, 174}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 224}, {{136, 0, 0, 132, 20, 10, 163, 177, 67, 218, 61, 203, 96, 180, 58, 148}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 154, 227, 242, 77, 63, 40, 165}, 224}, {{136, 0, 0, 213, 55, 3, 148, 114, 76, 27, 115, 0, 85, 21, 19, 115}, 224}, {{136, 0, 0, 0, 195, 111, 234, 2, 67, 118, 30, 140, 234, 182, 250, 196}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 22, 109}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 173, 225, 183, 180, 230, 141, 34, 158, 59, 255}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 0, 189, 227, 211, 177, 129, 142, 214, 208, 222}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 105, 41}, 224}, {{136, 0, 161, 223, 255, 249, 149, 113, 33, 193, 62, 68, 10, 66, 22, 122}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 217, 183, 36, 188}, 224}, {{136, 0, 0, 45, 81, 224, 75, 83, 136, 138, 218, 35, 8, 244, 133, 21}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 35, 255, 215, 4, 201, 67, 133, 252}, 224}, {{136, 0, 0, 0, 0, 0, 0, 83, 57, 176, 185, 206, 214, 137, 166, 72}, 224}, {{136, 0, 0, 203, 248, 99, 10, 185, 227, 25, 49, 165, 123, 231, 157, 7}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{136, 0, 0, 0, 0, 0, 26, 235, 44, 1, 226, 165, 95, 132, 82, 225}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 202}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 185, 90, 136, 206}, 224}, {{136, 0, 9, 144, 138, 31, 210, 1, 228, 218, 121, 20, 206, 5, 214, 46}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 28, 24}, 224}, {{136, 0, 0, 0, 0, 15, 208, 92, 197, 224, 111, 254, 197, 215, 213, 25}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 249, 134, 118}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 224}, {{136, 0, 0, 191, 116, 213, 199, 168, 209, 141, 22, 98, 9, 189, 133, 133}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 15, 205}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 182, 244, 65, 49}, 224}, {{136, 0, 0, 0, 0, 0, 64, 120, 242, 50, 60, 185, 219, 55, 253, 213}, 224}, {{136, 175, 7, 82, 254, 231, 5, 88, 36, 226, 188, 132, 141, 76, 190, 8}, 224}, {{136, 0, 0, 0, 0, 0, 0, 40, 5, 106, 115, 17, 177, 22, 36, 181}, 224}, {{136, 0, 0, 144, 134, 184, 190, 195, 178, 23, 198, 88, 55, 251, 93, 112}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 31, 224, 221, 129, 241, 13, 245}, 224}, {{136, 0, 0, 0, 0, 0, 4, 76, 6, 101, 206, 106, 215, 119, 100, 79}, 224}, {{136, 0, 0, 0, 125, 247, 42, 234, 217, 37, 211, 67, 161, 38, 207, 223}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 81, 179, 116}, 224}, {{136, 0, 0, 0, 0, 0, 111, 8, 47, 217, 160, 253, 32, 188, 242, 60}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 250}, 224}, {{136, 0, 0, 0, 0, 0, 0, 24, 16, 103, 174, 154, 226, 21, 126, 195}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 178, 245}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 176, 128, 197, 69, 229, 218, 149, 64}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 217, 221, 205}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 91, 128, 70}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 54}, 224}, {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 73, 211, 247, 165, 233}, 224}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 225, 244, 17, 248, 77, 51, 221}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 202, 133, 209, 72, 65, 202}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 20, 200, 221, 37, 208}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 100, 111, 92, 1, 74, 10}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 243, 160, 59, 192, 4}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 255, 168, 177, 109, 18, 107, 228, 245}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 229, 180, 111, 150, 168, 223}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 28, 45}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 242, 113, 192, 179}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 244, 158}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 12, 114, 43, 225}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 250, 131, 229, 60, 122, 147, 21, 157}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 121, 182, 56, 180}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 79, 40}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 244, 111}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 87, 187}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 146, 194, 151, 102, 171, 28, 183}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 168, 26, 15, 81}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 244, 80, 80}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 218, 79, 47, 240, 31, 55}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 59, 182, 53, 81, 135, 242, 136, 69}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 111, 241, 106, 185, 14, 192}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 85, 142, 122, 202, 115, 53, 94}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 188, 2, 224, 38, 234, 224}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 86, 213, 53, 36, 2, 116}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 57, 79, 91}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 189, 24, 133, 204, 195}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 77, 220, 136, 252, 96}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 198, 151, 92, 191, 245}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 205, 176, 247, 170, 65, 29}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 37, 184, 15, 159, 130}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 124, 102, 229, 245}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 9, 218, 95, 200, 158}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 30, 112, 42, 76, 20, 55, 52}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 20, 0, 102, 217, 23, 89}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 51, 253}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 234, 46, 241, 10, 216}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 22, 200, 177, 126, 36}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 33, 132, 63, 204}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 42, 199, 238, 78, 221, 56, 47}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 253, 66, 127, 135, 237}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 138, 210, 203, 129}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 163, 154, 11}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 216, 83, 102, 212, 219, 111, 110, 185}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 191, 18, 91, 237, 88, 230, 41, 187}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 228, 38, 127, 178, 145, 102, 223, 173}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 66, 124, 161, 7, 82, 1, 63}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 175, 192, 227, 102, 30, 147, 107, 170}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 81, 206, 148}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 22, 237, 69, 228, 170, 95, 15, 65}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 54, 89, 149, 172, 162, 35, 185}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 71, 211, 23, 63}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 63, 9, 35, 111}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 110, 227}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 79, 220, 67, 255, 243, 69, 50}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 240, 112, 3, 205, 98, 179}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 40, 199, 144, 189, 2, 67, 171, 132}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 177, 172, 209, 13, 163, 233, 76}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 9, 64, 2}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 142, 250, 100}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 89, 208, 62, 59, 38, 169, 224, 119}, 154}, {{131, 162, 144, 124, 12, 98, 242, 252, 124, 32, 0, 154, 109, 205, 214, 91}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 110, 17, 205, 141}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 138, 115, 28, 99, 230, 240, 42, 82}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 123, 178, 33, 220}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 141, 146, 243}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 158, 43}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 137, 167, 34, 76}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 8, 10, 255, 47, 153, 147, 205}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 154}, {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 16, 178, 226}, 154}, {{75, 50, 129, 192, 0, 0, 0, 0, 60, 111, 72, 104, 158, 231, 67, 86}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 70, 4, 254, 46, 205, 29, 0, 14}, 106}, {{75, 50, 129, 192, 250, 246, 85, 132, 202, 236, 56, 101, 192, 179, 166, 84}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 147, 8}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 75, 54, 146, 51, 56}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 246, 37, 6, 214, 17, 139}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 123}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 160}, 106}, {{75, 50, 129, 192, 0, 0, 165, 55, 47, 126, 48, 136, 155, 183, 49, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 195, 140}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 250, 95}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 87, 36, 44, 251, 145, 5}, 106}, {{75, 50, 129, 192, 0, 73, 146, 71, 200, 176, 196, 229, 95, 100, 180, 18}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 129, 64, 183, 69, 107, 159}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 178, 179, 73, 59, 43, 76, 187}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 238, 123}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 53, 119, 152, 223, 196, 170, 215, 99}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 23, 33}, 106}, {{75, 50, 129, 192, 0, 214, 21, 190, 7, 143, 114, 223, 56, 206, 237, 146}, 106}, {{75, 50, 129, 192, 0, 0, 51, 74, 222, 136, 213, 137, 192, 18, 126, 55}, 106}, {{75, 50, 129, 192, 0, 171, 230, 189, 43, 221, 142, 204, 46, 56, 239, 216}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 254, 159, 170, 102, 208, 185, 32, 224}, 106}, {{75, 50, 129, 192, 0, 126, 48, 69, 189, 135, 18, 177, 216, 185, 93, 76}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 93, 152, 244, 179, 167, 189, 193}, 106}, {{75, 50, 129, 192, 18, 178, 124, 5, 173, 144, 106, 30, 160, 231, 214, 191}, 106}, {{75, 50, 129, 192, 0, 0, 17, 116, 22, 233, 198, 244, 63, 204, 78, 23}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 239, 242, 145, 237, 83, 101, 105}, 106}, {{75, 50, 129, 192, 0, 0, 0, 198, 51, 68, 2, 52, 120, 3, 27, 38}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 106}, {{75, 50, 129, 192, 0, 0, 23, 104, 126, 253, 119, 246, 29, 94, 147, 93}, 106}, {{75, 50, 129, 192, 0, 0, 0, 73, 233, 175, 17, 64, 219, 249, 14, 59}, 106}, {{75, 50, 129, 192, 0, 212, 142, 38, 93, 194, 1, 56, 176, 203, 222, 198}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 88}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 21, 105, 68, 36, 89, 229, 171}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 186, 140, 88, 221}, 106}, {{75, 50, 129, 192, 0, 0, 77, 198, 104, 207, 10, 25, 123, 223, 79, 22}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 208, 23}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 168, 125, 115, 77, 86}, 106}, {{75, 50, 129, 192, 0, 0, 28, 214, 231, 249, 40, 252, 77, 251, 61, 237}, 106}, {{75, 50, 129, 192, 0, 0, 84, 48, 81, 36, 82, 140, 127, 172, 72, 121}, 106}, {{75, 50, 129, 192, 0, 95, 66, 206, 106, 118, 199, 73, 69, 194, 199, 97}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 241, 52, 88, 166, 255}, 106}, {{75, 50, 129, 192, 0, 0, 214, 103, 130, 237, 241, 147, 180, 237, 134, 67}, 106}, {{75, 50, 129, 192, 0, 0, 125, 87, 112, 246, 249, 184, 220, 167, 98, 112}, 106}, {{75, 50, 129, 192, 0, 107, 181, 106, 34, 21, 3, 129, 22, 180, 27, 180}, 106}, {{75, 50, 129, 192, 171, 246, 35, 109, 79, 217, 113, 2, 251, 50, 77, 43}, 106}, {{75, 50, 129, 192, 61, 48, 207, 134, 77, 197, 254, 206, 171, 174, 93, 52}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 197, 167, 56, 179, 240, 62, 63, 231}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 217, 209}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 140, 49, 3, 98, 113, 4, 56, 111}, 106}, {{75, 50, 129, 192, 0, 0, 0, 166, 207, 159, 133, 44, 108, 121, 132, 106}, 106}, {{75, 50, 129, 192, 51, 96, 218, 55, 164, 124, 235, 157, 186, 98, 222, 247}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 179, 63, 199, 4, 162}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 50, 78, 117, 12}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 63, 50, 119, 13, 115}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 183, 209, 222, 162, 125, 138}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 202, 37, 172, 209, 8, 1, 107, 148}, 106}, {{75, 50, 129, 192, 0, 0, 193, 78, 167, 247, 175, 211, 41, 84, 82, 22}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 155, 93}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 209, 253, 100, 23, 169}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 61, 78, 142, 82, 185}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 246, 41, 138, 249, 140, 27}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 172, 244, 0, 206, 244, 84, 178}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 110, 82, 197, 147}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 132, 74, 211, 228, 155}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 29, 224, 246, 213, 138}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 138, 196, 89, 93, 55, 210}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 106}, {{75, 50, 129, 192, 155, 181, 127, 96, 85, 191, 95, 57, 71, 75, 30, 205}, 106}, {{75, 50, 129, 192, 0, 0, 0, 37, 90, 236, 2, 190, 253, 89, 34, 65}, 106}, {{75, 50, 129, 192, 0, 0, 0, 23, 45, 187, 239, 181, 98, 255, 48, 7}, 106}, {{75, 50, 129, 192, 0, 0, 20, 144, 21, 191, 193, 178, 44, 49, 166, 4}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 240, 242, 208, 25, 188, 134}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 3, 158, 129, 98, 153, 35, 160, 44}, 106}, {{75, 50, 129, 192, 0, 35, 181, 202, 126, 48, 42, 90, 22, 133, 239, 86}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 50, 88, 45, 70}, 106}, {{75, 50, 129, 192, 0, 0, 153, 187, 201, 29, 5, 90, 6, 208, 203, 183}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 49, 175, 245, 179, 160}, 106}, {{75, 50, 129, 192, 0, 0, 202, 43, 133, 174, 206, 86, 235, 153, 218, 125}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 215, 107, 234, 94}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 192, 21, 84, 242, 252}, 106}, {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 32, 238, 62, 85, 173, 53}, 106}, {{75, 50, 129, 192, 0, 0, 215, 28, 167, 62, 24, 11, 164, 4, 101, 7}, 106}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 53, 127, 36, 137}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 111, 221, 159, 16, 38}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 250, 217, 65, 43, 162, 174}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 21, 227}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 108}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 161}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 77, 25, 48, 61, 159, 136}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 168, 66, 134, 245}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 218, 181}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 125, 43, 229, 40, 99, 35}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 108, 235, 85, 73}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 52, 105, 214, 2, 21}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 114, 168, 175, 87}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 217, 176, 195, 170, 29, 115}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 43, 91, 34, 83, 31, 247}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 2, 22, 38, 160, 153, 243}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 67, 100}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 183, 55}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 119, 152, 146, 210, 11, 110}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 81, 200, 29, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 65, 175, 81, 28, 37, 192, 254}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 223, 227, 217, 192, 167, 211}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 173, 66, 168}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 87, 149, 156, 119, 103}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 253, 109, 198, 142}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 253, 29, 248, 230, 46, 235, 78}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 70, 216, 143, 100, 153}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 218, 111, 49, 34, 16, 132}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 116, 25, 18, 201, 165, 157}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 101, 101, 165, 22}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 212, 141, 105, 30}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 39, 45, 157, 235, 151, 136, 116}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 200, 120, 183, 232, 214}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 162}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 171, 250, 202, 204, 179}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 62, 237, 162, 18, 156}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 236, 120, 165}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 57, 187, 220, 182}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 107, 64, 102, 251, 92, 206, 190}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 154, 228, 126, 93, 140, 196}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 191, 88, 63, 230, 52}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 72, 251, 225, 49, 242, 12, 146}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 189, 140, 151, 76, 193, 217, 68}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 92, 55, 97, 9, 88}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 148, 116, 71, 244}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 228, 193, 16}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 162, 179, 73, 181}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 65, 232, 251, 71, 228, 164}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 124, 46, 126}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 65, 210}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 8, 130, 78, 165, 141, 253, 150}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 95}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 53, 138, 215, 180, 219}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 245, 136, 226, 39, 5, 60}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 234, 23, 91, 69, 3, 106, 18}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 2}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 106, 166, 84, 45, 47}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 32, 198}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 85, 52, 246, 38, 249}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 123, 154, 217, 38, 174, 157}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 35, 14, 48, 141, 146}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 10, 36, 127, 92, 12}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 152, 156}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 140, 70, 245, 83, 85}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 39, 19, 77, 192, 90, 196, 205}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 52, 112}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 60, 241, 145, 177}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 179, 133}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 190, 21}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 86, 188, 156, 201, 28, 159}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 25, 15, 80, 93}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 119, 12, 218, 105, 102, 79}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 33}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 109}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 5, 84, 184, 46, 129, 20}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 118, 142, 172, 30, 152, 22, 94}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 155, 197}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 235, 150, 142, 203}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 203}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 247, 35, 33, 73}, 125}, {{158, 0, 65, 251, 100, 131, 56, 18, 203, 97, 25, 188, 124, 31, 215, 207}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 19, 238, 180, 144, 1}, 118}, {{158, 0, 0, 0, 40, 37, 112, 118, 133, 114, 244, 178, 227, 202, 188, 253}, 118}, {{158, 0, 0, 0, 0, 0, 216, 36, 59, 214, 46, 168, 145, 46, 61, 43}, 118}, {{158, 0, 0, 0, 0, 0, 184, 245, 73, 188, 16, 169, 99, 226, 179, 169}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 63, 245, 207, 149, 2}, 118}, {{158, 0, 0, 25, 85, 59, 201, 185, 0, 54, 232, 55, 77, 33, 240, 2}, 118}, {{158, 0, 0, 0, 196, 169, 100, 134, 146, 187, 142, 146, 179, 13, 186, 184}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 205, 53, 22, 200}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 251, 36, 52, 20, 253, 153, 161, 28, 154, 56}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 196, 84, 82, 237, 77, 209, 168, 127}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 176, 171, 249, 53}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 33, 25, 196, 98, 70, 241, 245, 90, 169}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 1, 190, 160, 220}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 114, 74, 171, 213, 113, 249, 109, 139}, 118}, {{158, 0, 8, 200, 19, 72, 82, 44, 245, 222, 24, 211, 161, 92, 177, 45}, 118}, {{158, 0, 0, 0, 163, 153, 97, 211, 115, 182, 110, 170, 85, 192, 44, 214}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 118}, {{158, 0, 0, 94, 51, 169, 251, 125, 185, 152, 123, 80, 238, 32, 30, 165}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 250, 40}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 212, 53, 55, 199, 153}, 118}, {{158, 0, 0, 0, 0, 0, 0, 34, 175, 200, 125, 241, 68, 105, 49, 123}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 172, 236, 220, 160, 212, 132, 229, 172}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 177, 135, 248, 196, 77, 57, 248, 110}, 118}, {{158, 0, 0, 0, 20, 235, 187, 36, 175, 5, 152, 106, 221, 197, 136, 188}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 71}, 118}, {{158, 0, 0, 0, 0, 0, 59, 238, 4, 183, 11, 185, 48, 144, 235, 63}, 118}, {{158, 0, 0, 250, 2, 15, 150, 253, 164, 149, 253, 99, 177, 70, 29, 73}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 192, 139}, 118}, {{158, 0, 0, 0, 232, 165, 35, 225, 236, 107, 98, 175, 102, 199, 147, 40}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 48, 153, 50, 202, 72, 47, 142}, 118}, {{158, 0, 0, 0, 129, 158, 185, 217, 216, 150, 6, 249, 179, 171, 235, 138}, 118}, {{158, 0, 0, 0, 0, 197, 94, 43, 94, 132, 201, 107, 161, 54, 236, 11}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 93, 144, 159}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 223, 167, 42, 251, 79, 79, 115, 223, 192}, 118}, {{158, 0, 0, 0, 95, 153, 215, 25, 26, 255, 227, 136, 136, 55, 125, 163}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 214, 88, 129, 28, 85, 227, 30, 139, 117, 84, 11, 118}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 135, 234, 36, 254, 248}, 118}, {{158, 0, 0, 0, 0, 143, 80, 164, 226, 74, 24, 72, 23, 240, 21, 134}, 118}, {{158, 0, 80, 194, 195, 26, 4, 117, 68, 229, 19, 34, 181, 202, 198, 85}, 118}, {{158, 0, 163, 166, 130, 164, 204, 86, 242, 195, 235, 214, 154, 150, 200, 140}, 118}, {{158, 0, 0, 0, 57, 117, 219, 253, 138, 177, 207, 61, 193, 105, 93, 145}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 248, 30, 217, 142}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 0, 0, 127, 96, 195, 43, 17, 60, 38, 146, 112, 249}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 159, 78}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 225, 147, 134, 74, 76, 225, 165, 135}, 118}, {{158, 0, 0, 0, 0, 77, 114, 155, 56, 155, 142, 164, 118, 67, 114, 29}, 118}, {{158, 0, 0, 0, 0, 22, 55, 132, 246, 229, 63, 61, 20, 241, 80, 216}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 170, 27}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 209, 241, 154}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 0, 50, 122, 169, 181, 146, 205, 153, 116, 201, 188, 199, 178}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 96, 254, 27}, 118}, {{158, 0, 0, 0, 229, 113, 231, 41, 198, 150, 59, 209, 60, 40, 81, 12}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 173, 2}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 79, 28, 172}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 51, 93, 236}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 229, 178, 109, 219}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 38, 231, 67, 3, 201, 242, 98, 12}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 240, 118, 62, 118}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 215, 204, 19, 165, 155, 238, 101, 176}, 118}, {{158, 0, 0, 0, 0, 180, 226, 31, 147, 97, 104, 243, 164, 253, 241, 45}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 103}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 147, 89}, 118}, {{158, 0, 0, 0, 0, 0, 231, 244, 212, 150, 239, 247, 166, 144, 5, 252}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 115, 171, 82, 64, 6, 210, 137}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 225, 222, 75, 224, 10}, 118}, {{158, 0, 0, 53, 182, 227, 230, 0, 105, 84, 96, 54, 44, 192, 138, 218}, 118}, {{158, 0, 140, 181, 55, 216, 245, 209, 47, 121, 54, 58, 48, 97, 245, 166}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 144}, 118}, {{158, 0, 0, 0, 0, 0, 0, 191, 140, 62, 2, 165, 73, 36, 119, 44}, 118}, {{158, 0, 30, 169, 84, 84, 115, 248, 58, 71, 230, 27, 134, 192, 185, 134}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 165, 162, 231, 209, 158}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 175, 180, 94, 175}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 118}, {{158, 0, 0, 181, 63, 110, 198, 98, 225, 97, 170, 192, 211, 207, 225, 78}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 173, 88, 232, 217, 73, 237, 94, 104}, 118}, {{158, 0, 0, 219, 172, 155, 139, 172, 92, 115, 164, 214, 248, 212, 80, 93}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 206}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 68, 2, 22, 196, 159, 104, 154}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{158, 0, 0, 145, 5, 80, 139, 177, 13, 58, 137, 169, 144, 107, 8, 63}, 118}, {{158, 0, 0, 0, 0, 0, 0, 115, 162, 23, 25, 90, 51, 156, 76, 115}, 118}, {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 110, 75, 46}, 118}, {{158, 0, 236, 238, 49, 89, 65, 163, 161, 25, 218, 239, 70, 197, 139, 72}, 118}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 113, 100, 145, 215}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 64, 207, 46, 120}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 40, 226, 89, 179, 65}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 30, 195, 83, 175}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 143, 183, 46, 246, 65}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 106, 100, 230, 188, 213, 241}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 6, 217, 207}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 108, 73, 30, 232}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 141, 69, 146, 204, 185}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 7}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 209, 110, 2}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 22, 218, 198, 194, 217, 35}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 137, 228, 242, 120, 88}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 187}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 128}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 95}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 113, 113, 23, 129, 121}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 117}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 41, 134}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 224}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 69}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 72, 200, 85}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 222, 241, 60, 122}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 78, 22, 255, 41, 121, 141}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 50, 26, 34, 189, 189}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 234, 5, 136, 211, 8}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 59}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 236, 90, 88, 150, 38, 108}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 187, 216, 0, 106, 158, 199}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 241}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 10, 217}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 39}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 224, 143}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 156, 237, 16, 138, 199}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 220, 100, 58, 179, 192}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 113, 186, 118}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 98, 33, 75, 73, 191, 213}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 17, 33}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 98, 16, 237, 156}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 133}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 247}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 47, 255}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 244, 62, 163, 167, 144}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 26, 198, 216, 223, 60}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 202, 47, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 160, 146, 40, 162, 85}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 101, 170}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 156, 124, 39, 186, 18}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 220, 121}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 150, 192}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 151, 56, 65, 212, 132, 53}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 79, 190, 197, 71, 70}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 195, 66}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 227}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 56, 175, 89, 15, 56}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 237, 60, 153, 108, 165}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 243}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 66}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 127, 23}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 138}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 88, 65, 3}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 23, 95, 35, 91, 102}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 169, 114, 70, 238, 25, 210}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 44, 77, 93, 131}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 36, 155, 182}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 51}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 88, 44, 123, 81, 242}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 24, 136, 11, 154, 80, 86}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 78, 92}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 27, 243, 202, 216, 235}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 110, 142, 5, 186, 233}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 125}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 43, 13, 196}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 159, 196, 235, 122}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 98, 184, 98}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 252, 15, 101, 226, 134, 198}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 8, 116, 198, 204, 16, 155}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 92, 7, 213, 98}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 21, 194, 239, 169, 214}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 75, 210, 11, 66}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 210, 89, 247, 10}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 110}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 185, 238, 188}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 94, 161}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 19, 32, 54, 87, 246, 156}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 182}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 204, 30, 235, 133, 225}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 255, 55, 165}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 33, 11, 251, 24, 186}, 52}, {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 191, 38, 214}, 52}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 124, 185}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 1, 80, 181, 211, 151}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 194, 238, 28, 174}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 99, 206, 195}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 210}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 55, 197}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 214, 209, 85, 69, 20, 92, 208, 160}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 230, 165, 138, 33, 78, 159, 43, 223}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 177, 175, 221, 208, 86, 157, 190}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 169, 9, 151, 247, 194, 236, 110}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 142, 164, 36, 137, 224, 51}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 88, 168, 62, 21, 156, 242}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 170, 136}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 75, 109, 205, 165, 25, 121, 9}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 61}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 217, 35, 155, 158, 155, 73}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 24}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 46, 72}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 116, 77, 187}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 112, 6, 36}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 239, 213, 178, 60, 161, 180}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 15, 64, 60, 151, 24}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 242, 247, 157, 149}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 65}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 243, 92, 210, 217, 46, 200}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 155}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 226, 1, 195, 195, 11, 86, 112}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 214, 44, 41, 55, 121}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 21}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 13, 106, 14}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 19, 69, 156, 23, 184}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 94, 7, 33, 160, 188, 195, 121}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 214, 234, 135, 193}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 53, 255, 7, 139, 214, 96}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 111, 255}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 251, 237, 201, 46}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 204}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 30, 97, 13}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 27, 54, 64, 23, 8, 187}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 209, 22, 170}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 6, 149}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 144, 172, 170, 23, 157, 224, 58}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 40, 83}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 112, 89, 229, 151, 206, 127, 92}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 155, 78, 190, 157, 140}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 239, 88, 190, 23, 82, 203, 120}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 195, 12, 117, 228, 30, 104}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 129, 208, 24}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 87, 79, 190, 108}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 236, 180, 87}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 36, 85}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 222, 155, 72, 227, 196, 43, 86}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 169, 57, 21, 152, 112, 250}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 79, 57, 210, 246, 135}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 34, 230, 3, 241, 136}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 87, 93, 200, 194}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 46, 144, 15}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 168, 58, 88, 164, 162, 240, 175}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 105, 185, 90, 150, 174, 220, 83}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 88, 207, 198, 93}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 116, 125, 122, 101, 108}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 58, 246, 84}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 29, 223, 13, 64, 224}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 166, 100, 171}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 247, 59, 84, 148, 32, 98}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 204, 206, 252, 183, 234}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 224, 25, 66, 11, 67}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 92, 4, 118}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 21, 60, 110, 111, 45, 220}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 74, 139, 100}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 4, 124, 44, 46, 167, 200}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 67, 13}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 129, 251, 167, 109, 2, 46}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 66, 31, 165, 77, 126, 111, 17, 207}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 112, 107, 85, 64}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 36, 207, 24, 235, 103, 64, 21, 235}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 183, 195, 177, 179}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 85, 220}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 189, 152, 171, 182}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 127, 59, 145, 216, 169, 174}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 232, 245, 80, 149, 103}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 46, 203}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 253, 223, 218, 253, 165, 203}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 184, 49, 149, 214, 6, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 205}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 189, 80}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 133, 41}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 28, 165, 214, 160}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 164, 255}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 187, 216, 182}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 45, 116, 250, 180, 235, 143, 158}, 173}, {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 209, 165, 84, 116, 51}, 173}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 7}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 94}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 5}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 201}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 58}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 86}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 59}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 228}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 31}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 130}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 175}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 5}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 92}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 196}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 165}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 212}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 149}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 138}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 178}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 152}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 70}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 216}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 132}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 99}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 177}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 143}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 133}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 29}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 106}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 120}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 78}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 88}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 48}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 55}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 247}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 130}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 178}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 11}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 238}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 89}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 105}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 195}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 49}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 231}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 132}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 196}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 201}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 42}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 199}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 248}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 114}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 101}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 196}, 8}, {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 8}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 26, 3, 134, 104, 190}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 100, 97, 194, 4, 140}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 80}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 155, 71, 128, 183, 229, 84}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 183}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 77, 161, 2, 135, 5}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 94, 233}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 253, 6}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 50, 234, 175, 121, 208, 55}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 64, 9}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 236}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 14, 209, 62, 86}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 76, 197, 232, 206}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 50, 128, 178, 36, 228}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 8, 191, 46, 73}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 243, 134}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 102, 174, 199, 78}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 231, 243, 231, 199, 130}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 17, 251, 143, 5, 165}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 180, 78}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 215, 167, 41}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 228, 239, 219, 180, 50, 223}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 111, 41, 37}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 161}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 231, 7, 211}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 56, 125, 252, 10}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 37}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 18, 115}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 207, 229, 236}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 229, 178}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 241}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 34, 141}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 175, 94}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 207, 20, 219, 139}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 141, 4}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 108, 175, 171, 196}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 87, 45}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 245}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 1, 188, 158, 165}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 166, 29, 98, 139, 127}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 102, 155, 66}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 190}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 180, 73}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 250, 105, 201, 141}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 33}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 34, 176}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 145, 224, 211, 176, 188}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 144, 74, 36, 233, 133}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 33, 75, 47, 128, 58}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 208, 130, 224}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 151, 12, 253}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 194, 211}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 44, 69, 17, 193, 110}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 124, 230, 170, 126, 161}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 23, 199}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 188, 150, 172, 196, 139, 33}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 146, 243, 37}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 250, 185, 154}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 138, 169, 93, 214, 134}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 116, 136}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 114}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 199, 196, 99, 114}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 24, 40}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 73, 80}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 21, 171, 161, 126, 94}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 198, 153, 128, 93, 233, 216}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 127, 219, 168, 254, 206}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 135, 236, 220, 63}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 70, 58}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 94, 42}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 91, 18, 16, 195, 25, 149}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 5, 155, 112}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 6, 64, 117, 164, 53}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 100, 187}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 8, 99, 206}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 223, 62}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 141, 107, 121, 120, 0}, 211}, {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 211}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 203, 254, 167, 115, 233, 92}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 220, 48, 109, 136, 158}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 62, 95, 201, 253, 178, 191, 26}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 232, 116, 142, 111, 40, 212, 99}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 218}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 250, 228, 163, 9, 47}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 201, 90, 201, 83, 185}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 240, 215, 244, 9, 10, 32}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 116, 120, 218, 240, 172}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 188, 203, 183, 101, 128, 227, 216}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 4, 138, 27, 67, 162, 206}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 160, 115, 221, 127, 216, 149}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 221, 106, 35}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 224, 97, 46, 4, 241, 12}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 225, 138, 30, 199, 217, 220}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 247}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 214, 180, 170, 187, 105, 217, 68, 200}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 153, 227}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 117, 163, 180, 59, 216, 119, 162}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 44, 90, 81, 231, 149, 100, 17}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 148, 237, 159, 76, 67}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 249, 123, 212, 249, 139, 147, 13}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 145}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 103}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 89, 210, 143, 82}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 38, 3}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 176, 39, 232, 121, 23, 235, 103}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 217, 154, 93, 72, 42, 8}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 102, 116, 184}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 216, 142, 60}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 150, 25, 168, 175}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 239, 237, 17, 231, 33, 153}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 194, 136, 26, 111, 245, 75, 204, 19}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 114}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 126, 113, 131, 141}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 110, 233, 167}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 127, 44, 210, 227, 224, 80}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 196}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 255, 107}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 50, 28, 89, 218, 168, 74, 142, 212}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 100, 98, 202, 126, 62, 59, 52}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 181, 74, 118, 98, 207, 76}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 194}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 75}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 146, 76, 194, 213, 29}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 18, 59, 1, 53}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 228, 86, 29}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 108, 8, 63}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 41, 167, 56}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 93, 149, 158, 216, 200}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 215, 159, 110, 141, 106}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 244, 35, 127, 85}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 66, 139}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 228, 251}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 59}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 49}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 132, 176}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 188}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 65, 184, 159, 239, 199}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 163, 248, 245, 115}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 199, 81}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 252, 124, 142, 58, 235}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 112, 57, 196, 132, 151, 51}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 30, 17, 117, 150, 121, 77, 174}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 90, 217, 156, 12, 199}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 188, 102, 244, 236, 142}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 213, 65, 224}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 97, 79, 220, 174}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 63, 214, 180, 170}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 116}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 225, 68}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 7, 44, 118, 201, 48, 224, 4}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 60, 86, 241}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 114, 213, 173, 7, 115, 80, 1}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 104}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 253, 190, 231, 108}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 102, 66, 223, 116, 121, 210}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 133, 12, 67, 246, 174, 161}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 99, 210, 133, 4}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 138, 20, 233, 56, 237, 64, 62, 172}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 109, 253, 255, 55, 74}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 112, 214}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 97, 177, 11, 22, 69, 110, 82}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 40, 179, 21, 248, 180, 90, 28, 60}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 249, 225, 246}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 176, 105, 161, 37, 243, 215, 148, 187}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 253}, {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 154}, 253}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 64, 18, 249, 104, 188}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 214}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 50, 38, 111, 26}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 239, 152}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 157, 215, 106}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 79, 58, 76, 145}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 245, 32, 122, 2, 167, 96, 50, 239}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 162, 30, 84}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 224, 193, 227, 203, 200}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 201, 202, 82, 137}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 126, 182, 15}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 101, 96, 23, 20}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 66, 191, 87, 19, 85, 255, 25}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 241, 103, 162}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 141, 138, 13, 60, 243, 146, 152, 177}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 65, 221, 142, 226, 217, 191, 190}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 214, 195}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 63}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 49, 33, 180, 26, 219, 124, 115}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 86}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 176}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 77, 33, 98, 244, 242, 67}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 81, 103}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 161, 125, 19, 72}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 37, 154, 22}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 170, 242, 137, 240, 144, 28, 124}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 134, 100, 200, 242, 136, 44, 202}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 60, 108}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 197, 95, 59}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 84, 78, 186, 195, 185}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 194, 246, 7, 109, 142, 67, 189}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 244}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 65}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 111, 156}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 218, 249, 209}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 172, 138, 43, 80, 122}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 38}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 74, 181, 237, 158, 119, 220, 132}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 108, 221, 100, 54}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 248, 84}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 199, 245, 5, 69}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 236, 43, 183, 56, 13, 211}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 251, 92, 29}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 195, 227, 125, 216, 132, 134}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 120, 9, 170}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 161, 154}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 66, 99, 177, 166, 67, 118}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 96, 216, 96, 163, 170}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 17, 64, 241}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 253, 33, 191}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 219, 208, 154, 49, 130, 196, 121}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 1, 95, 217, 77, 28, 56, 254}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 164, 174, 190, 73, 197, 135, 39}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 31, 191, 81, 209, 152, 229}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 71, 166, 54, 84}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 191, 117, 209, 156, 148, 72, 24}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 81, 184, 81, 222}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 138, 3, 219, 50, 201, 147}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 34, 48, 192, 152, 92, 165}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 241, 183, 2, 187, 83, 2, 229}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 248, 142, 108, 159, 192}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 20, 16, 36, 66, 226, 100}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 164, 225, 81}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 79, 35}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 48}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 109, 80, 20, 91, 103}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 230, 149, 139}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 155, 213, 233, 83, 101, 239}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 75, 8, 6}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 160, 203}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 122, 151, 164, 212, 247, 152, 110, 152}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 173, 76, 160, 198, 174}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 115, 124, 214, 21, 132}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 237, 221, 114}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 179, 190, 175}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 153, 14}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 175, 204, 101}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 6, 47, 122, 178}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 228, 229}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 59, 152, 150}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 254, 114, 127, 235, 146, 255, 49, 83}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 186, 117, 53, 134}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 141}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 234, 171, 53}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 190, 166}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 91, 255, 56, 31, 208, 166, 137}, 47}, {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 215, 201}, 47}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 25}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 242}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 210}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 133}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 176}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 20}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 17}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 119}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 245}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 50}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 97}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 249}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 140}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 20}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 140}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 163}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 56}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 177}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 215}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 129}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 79}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 162}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 85}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 132}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 191}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 202}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 114}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 130}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 11}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 121}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 74}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 157}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 78}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 211}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 144}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 208}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 21}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 218}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 57}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 46}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 176}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 227}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 201}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 214}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 79}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 165}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 44}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 101}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 12}, 73}, {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 73}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 5, 248, 114}, 192}, {{6, 108, 0, 0, 90, 88, 87, 37, 56, 207, 95, 246, 41, 183, 22, 106}, 192}, {{6, 108, 0, 0, 0, 0, 0, 47, 11, 23, 26, 208, 219, 34, 107, 124}, 192}, {{6, 108, 0, 0, 0, 0, 41, 178, 214, 194, 167, 95, 78, 180, 127, 129}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 14, 156, 182, 59, 39, 42, 4, 105, 167, 108, 223}, 192}, {{6, 108, 0, 0, 0, 173, 126, 178, 216, 108, 215, 237, 144, 151, 36, 69}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 21, 164}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 64, 132, 133, 147, 87, 60, 200, 132, 254, 164}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 195, 114, 160, 215, 123, 222}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 117, 205, 163, 41}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 73, 134, 127}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 24, 30, 217, 253, 189, 153, 34}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 6, 119, 223}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 186}, 192}, {{6, 108, 0, 0, 0, 0, 0, 13, 154, 186, 140, 78, 217, 242, 62, 199}, 192}, {{6, 108, 0, 181, 60, 188, 130, 80, 197, 234, 104, 28, 202, 56, 158, 78}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 54, 216}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 76, 8, 239, 73, 218, 76}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 87, 122, 220}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 102, 99, 52, 78, 114, 10}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 192}, {{6, 108, 0, 0, 27, 243, 57, 134, 139, 23, 29, 155, 20, 230, 140, 44}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 208, 146, 69}, 192}, {{6, 108, 0, 0, 0, 0, 0, 232, 140, 249, 192, 135, 68, 167, 127, 51}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 112, 218, 86, 122}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 6, 136}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 74, 225, 69, 207, 250, 230, 71}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 51, 72, 12, 165, 104, 217, 95}, 192}, {{6, 108, 0, 0, 246, 35, 7, 46, 20, 134, 56, 81, 119, 202, 43, 199}, 192}, {{6, 108, 0, 0, 0, 0, 0, 245, 70, 5, 45, 148, 216, 48, 231, 121}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 85, 92, 235, 189, 164, 16, 129, 56}, 192}, {{6, 108, 0, 0, 0, 134, 189, 90, 142, 203, 73, 130, 193, 211, 205, 62}, 192}, {{6, 108, 0, 0, 0, 85, 47, 179, 32, 254, 98, 176, 202, 68, 252, 235}, 192}, {{6, 108, 0, 0, 0, 0, 7, 159, 167, 132, 73, 211, 247, 132, 123, 122}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 243, 141, 15, 94, 46, 196, 200}, 192}, {{6, 108, 0, 0, 0, 197, 213, 8, 104, 76, 247, 6, 131, 242, 31, 177}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 228, 253, 133, 82, 95, 32}, 192}, {{6, 108, 0, 0, 0, 0, 0, 163, 139, 233, 45, 90, 74, 228, 152, 182}, 192}, {{6, 108, 0, 0, 0, 203, 237, 163, 115, 247, 15, 235, 174, 185, 14, 107}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 49}, 192}, {{6, 108, 0, 18, 177, 105, 38, 25, 62, 121, 38, 71, 139, 39, 120, 159}, 192}, {{6, 108, 0, 178, 49, 65, 126, 230, 69, 203, 43, 40, 143, 9, 25, 53}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 171, 224, 191, 28, 193, 34, 230}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 34, 185, 249, 19}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 115, 138, 58, 154, 37, 171, 23, 244}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 163, 85, 200, 237, 176, 10}, 192}, {{6, 108, 0, 6, 185, 229, 23, 119, 186, 254, 129, 179, 222, 27, 255, 88}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 91}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 189, 32, 103, 64, 81, 251}, 192}, {{6, 108, 0, 0, 95, 29, 186, 114, 153, 207, 0, 129, 44, 110, 109, 45}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 241, 201, 221, 21, 201, 214}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 185, 102, 2, 158, 174, 29}, 192}, {{6, 108, 0, 0, 0, 113, 200, 67, 132, 46, 158, 241, 118, 43, 200, 31}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 22, 115, 141, 62, 223, 220, 207, 91}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 31, 149, 90, 164, 184, 33, 181, 217}, 192}, {{6, 108, 0, 0, 123, 124, 83, 148, 139, 49, 255, 109, 171, 204, 86, 225}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 42, 239, 127, 84, 48, 106, 202, 32}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 65, 178, 198, 183}, 192}, {{6, 108, 0, 0, 0, 0, 242, 118, 215, 100, 166, 96, 99, 234, 21, 137}, 192}, {{6, 108, 0, 18, 217, 50, 97, 184, 17, 184, 167, 161, 89, 40, 203, 202}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 79}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 123, 35, 37, 153, 152, 50}, 192}, {{6, 108, 0, 0, 0, 0, 135, 147, 161, 141, 44, 111, 202, 175, 132, 63}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 128}, 192}, {{6, 108, 0, 0, 0, 36, 196, 45, 207, 37, 3, 32, 239, 126, 148, 80}, 192}, {{6, 108, 0, 0, 0, 211, 74, 105, 123, 41, 204, 36, 147, 173, 141, 198}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 146, 164}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 142, 139, 164, 92, 98, 113, 146, 93}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 202, 94}, 192}, {{6, 108, 0, 186, 185, 251, 24, 88, 200, 228, 152, 89, 98, 203, 6, 56}, 192}, {{6, 108, 0, 0, 0, 0, 96, 167, 16, 7, 68, 204, 45, 154, 22, 25}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 174, 131, 104, 154}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 157, 80, 195, 36}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 25, 88, 181, 208, 89, 24}, 192}, {{6, 108, 0, 0, 0, 0, 224, 186, 93, 241, 76, 78, 183, 27, 56, 102}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 240, 207, 125}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 233, 155, 151}, 192}, {{6, 108, 0, 0, 0, 0, 94, 224, 249, 8, 23, 89, 89, 107, 117, 90}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 162, 172, 123, 25}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 135, 201, 246, 55, 77, 55, 19, 213}, 192}, {{6, 108, 0, 126, 49, 185, 98, 243, 246, 117, 26, 161, 177, 26, 208, 102}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 167, 21, 39, 227, 249, 244, 114, 124}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 204, 254, 110, 204, 90, 165}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 192, 110, 6, 176, 48, 190, 210}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 244, 250, 33}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 134}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 105}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 169}, 192}, {{6, 108, 0, 0, 0, 144, 231, 247, 29, 129, 132, 114, 142, 118, 243, 218}, 192}, {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 74, 246, 35, 90}, 192}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 55}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 198}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 74}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 234, 114}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 244, 143, 219}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 35, 163}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 206}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 151, 247, 110}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 179, 4, 88}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 104, 40}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 13}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 56, 227, 223}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 42}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 113}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 225, 233}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 233, 242, 135, 151}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 208, 85}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 76, 138}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 111}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 74, 81}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 220, 54}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 200}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 69, 19, 210}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 100, 227}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 194}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 140, 112, 137}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 64, 91, 27, 16}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 83, 142}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 115}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 186, 179}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 181}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 52}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 193, 1}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 74, 114, 181}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 156, 20}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 72, 242}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 119, 200, 87}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 245}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 187, 162, 70, 89}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 125, 159, 161}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 138}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 150, 100}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 66, 207, 110}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 23, 47}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 206}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 127, 218}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 100, 207}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 213, 87, 97}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 208}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 187, 146, 76, 3}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 17, 41}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 119, 204, 63}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 85, 207, 183}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 193, 20, 51}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 110}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 108, 71}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 214, 193, 12, 115}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 67}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 105, 66, 75}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 69, 10, 88, 150}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 235}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 9}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 16}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 119, 154, 18, 92}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 39, 224, 219, 96}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 110, 144}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 22, 217}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 159}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 30, 220}, 147}, {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 89, 72, 159}, 147}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 86}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 77, 224, 248, 253, 192}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 22, 57, 4, 198}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 219, 247, 240}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 151}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 18, 182, 193, 31}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 29, 215, 9, 232, 93}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 201}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 103, 46, 17, 76}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 44, 127, 224, 128}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 2, 60, 75, 85, 184}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 32, 17, 190}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 154, 6, 103, 220}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 2, 171}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 141, 57}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 254}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 171}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 226, 24}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 45}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 149, 20}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 80, 201}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 99, 229, 202}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 223, 145}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 50, 88}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 145, 115}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 195, 170, 160, 153, 24}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 133, 82, 87, 61, 199}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 151, 176, 95, 124}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 161, 210, 155}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 26, 222, 142}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 156, 224, 187, 88, 218}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 165, 175, 69, 121}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 221, 223}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 140, 143, 232}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 218, 31}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 31}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 90, 146, 154}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 134}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 238, 7, 163, 153, 214}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 47, 12, 162, 155, 219}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 121, 55}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 30, 151, 249, 186}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 203}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 59, 172, 175}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 100, 181}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 243, 174}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 41, 194, 226}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 110, 94, 59}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 187, 160, 156, 146}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 53, 178}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 241, 78, 166}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 69, 147, 1, 55, 190}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 5, 242}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 65, 18}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 232, 184, 6, 66}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 131, 160, 247, 47}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 225, 177, 52}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 92, 255}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 60, 22}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 121, 45, 34}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 248, 241, 16, 29, 34}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 46, 177, 221, 2}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 147, 150}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 209}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 11, 84, 132, 22, 173}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 158, 180}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 169, 171, 254, 244}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 90, 144}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 76, 208, 177, 174, 240}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 138}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 121}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 22, 69, 139, 185}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 229}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 73, 66, 195, 126}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 106, 213, 199}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 130}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 7, 122}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 70}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 89}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 95}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 129, 55, 82, 179, 110}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 190}, 16}, {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 16}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 27}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 35}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 83}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 149}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 26}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 118}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 4}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 180, 32}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 117}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 122}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 214, 195}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 69}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 47}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 132}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 182}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 162}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 45}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 211}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 17}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 124}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 35}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 168}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 71}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 5, 39}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 144}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 105, 121}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 111}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 199}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 156}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 142}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 126}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 200}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 156}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 112}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 162}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 216}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 247}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 2}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 83}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 170}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 23}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 231, 150}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 52}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 187}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 197}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 15}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 179}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 75}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 99}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 109}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 172}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 247}, 167}, {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 185}, 167}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 154, 85, 221, 28, 120, 143, 55}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 90, 40, 123, 95, 133}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 154, 107, 188, 99, 38, 60}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 236, 252}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 155, 34, 21, 4, 166}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 213, 14}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 164}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 229, 91, 123, 101, 177, 119, 121}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 218, 50, 150, 152, 3, 235}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 250, 177, 192, 195, 156, 144}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 138, 152, 116}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 245, 79, 188}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 46, 75}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 96, 188, 123, 6}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 189, 242, 186, 212, 160, 44}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 52}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 44, 255, 149}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 9, 49, 207, 122, 73, 29, 196}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 91, 107, 33, 136, 215, 13}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 95}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 238, 114, 122, 167, 29}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 147, 33, 43}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 2, 177, 16, 95, 7}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 142, 22, 88}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 82, 74, 10, 113}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 215, 218, 16, 155}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 88, 252, 163, 125, 102, 44}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 126}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 117}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 35, 12, 227}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 171, 82, 123, 51, 155, 203}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 122, 212}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 86}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 188, 90, 180, 17}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 103}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 81, 225, 252, 116, 87}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 254, 53, 234, 183, 213, 83}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 207, 58, 159, 142, 62, 43, 225}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 104, 186}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 106, 55, 122, 137, 72, 187, 179}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 162, 91, 118, 216, 137, 145, 132}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 97, 195, 206, 66, 46, 114}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 222, 13, 226, 45, 246}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 127, 170, 41}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 244, 76, 201, 10, 200, 86}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 222, 225, 109, 35, 2}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 197, 29, 234}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 10, 186, 76, 238, 48}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 89}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 130, 0, 5, 122}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 248, 126, 14, 104}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 234, 165}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 181, 82, 186}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 50, 110}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 179, 250, 238, 253}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 78, 46, 171, 104, 249, 143}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 175, 209, 80}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 42, 164, 149}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 38, 69, 106}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 225, 208, 248, 244}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 62, 203, 15, 184}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 179, 68, 84, 112}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 198, 81, 215, 243, 33, 122}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 247, 25}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 198, 142, 75, 137, 3}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 205, 17, 106, 33}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 185, 217}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 41, 79}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 219, 222, 63, 229, 50, 23, 231}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 36, 201, 242, 231, 80, 12}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 137, 116}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 235, 132, 94}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 116, 62, 92}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 203, 92, 84, 225}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 99, 122, 40, 122, 38, 20}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 253, 63}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 163, 74, 91, 102}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 171, 110, 2, 32, 155, 86, 71}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 137, 107, 139, 99, 102, 220}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 71, 242, 190, 242, 149, 163}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 68, 107, 129, 128}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 115, 114, 210, 117, 228, 82}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 190, 169, 102, 72}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 33, 82, 129}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 192}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 124, 95}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 139, 188, 120, 11, 161}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 91, 103, 18}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 247, 30, 66, 115}, 148}, {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 148}, {{169, 108, 190, 162, 23, 39, 140, 0, 15, 226, 229, 13, 173, 237, 137, 52}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 102, 208}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 126, 137, 58, 86, 80, 117, 196, 227}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 131, 189}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 146, 203}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 228, 78, 150}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 119, 221, 180, 203, 179, 49}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 64, 88, 21, 148, 201}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 35, 177, 142, 140, 196, 81, 13, 237}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 201, 27}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 103, 192, 13, 155, 67, 10, 55}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 68, 165, 143, 248}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 51, 150, 81, 105}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 26, 66, 52, 75, 110, 73, 152}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 100, 240, 195, 230}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 44, 231, 109, 85, 234, 125}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 223, 105, 21, 170}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 208, 74, 191, 107, 116, 149, 52, 232}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 102, 241, 223, 72, 85, 98, 18, 194}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 119, 219, 235, 99, 253}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 85, 39, 73, 50, 136, 23, 84}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 91, 163, 81, 172, 28, 111}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 37, 168, 155, 210, 70, 254, 42}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 142, 40, 126, 140, 217, 139}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 10, 125, 215, 67, 200}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 86, 99, 106, 162, 182}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 10, 190, 50, 60, 245}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 236, 14}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 8, 161}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 219, 236, 127, 22, 157, 143, 219}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 252, 247, 13, 74, 48}, 66}, {{169, 108, 190, 162, 23, 39, 140, 43, 61, 43, 127, 88, 227, 4, 34, 202}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 219, 114}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 97, 182, 56, 87, 84}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 20, 199, 101, 78, 230, 129, 154}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 13, 89, 162, 177, 175, 92, 197, 14}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 249, 13, 63, 90, 221}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 225, 187}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 210, 93, 243, 76, 228, 186, 193}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 36, 175, 13, 221, 5, 68, 92}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 125, 211, 62, 132, 210, 88, 140, 125}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 81, 107, 112, 111, 242, 47, 147}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 65, 119, 202, 211}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 139, 65, 232, 61, 210, 246, 41, 27}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 243, 203}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 210, 184, 117, 156, 18}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 246, 10, 81, 19, 221, 28}, 66}, {{169, 108, 190, 162, 23, 39, 140, 207, 100, 9, 131, 206, 85, 135, 246, 7}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 90, 39, 227, 239}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 125, 2, 248, 113, 149, 196}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 154, 185, 221, 173, 247}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 208, 54, 189, 235}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 63, 108, 55, 70, 93, 138, 194, 235}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 1, 53, 8, 239, 179}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 3, 128, 201}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 133, 232, 108, 27, 171}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 140, 173}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 55, 82, 112, 47, 99, 145, 175}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 66, 80, 26, 219, 37, 219, 15, 205}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 155, 73, 93}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 80, 159, 154, 159}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 14, 97, 134, 235}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 186, 111, 155, 56, 235, 111, 194, 10}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 245, 89, 35, 88}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 20, 147}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 221, 18, 238}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 60, 117, 216, 109, 62}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 203, 34, 48, 104, 223}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 75, 39, 55, 233, 164}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 214, 94, 2, 57, 11}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 159, 223, 77}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 73, 23, 236, 176, 147}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 233, 145}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 106, 235, 162}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 52, 198, 101, 39, 249, 245, 39}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 145, 196, 141}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 237, 235, 42, 171, 190, 90}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 9, 14, 175, 67, 91}, 66}, {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 161, 59, 37, 87, 106}, 66}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 81}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 51}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 176}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 228, 196}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 111}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 140, 140}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 130}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 84}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 128, 212}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 10}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 252, 233}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 76, 104}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 209}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 197}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 204, 92}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 116}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 109}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 76}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 42}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 70}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 63}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 248, 54}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 41, 204}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 97, 250}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 4, 191}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 227}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 46, 249}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 32}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 180}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 249, 80}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 126}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 97, 82}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 203, 149}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 39}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 78, 131}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 165}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 68}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 68, 45}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 23, 5}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 138, 72}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 230, 108}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 145}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 49, 129}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 109}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 189}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 54, 72}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 38, 146}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 74}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 49, 80}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 245, 160}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 19}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 239}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 89, 95}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 89, 183}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 68, 126}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 216, 72}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 32, 213}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 169}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 243, 202}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 145}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 57, 120}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 114, 177}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 187, 202}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 235}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 244}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 250}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 193}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 164, 87}, 70}, {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 70}, {{71, 191, 0, 0, 0, 0, 0, 20, 45, 115, 229, 107, 54, 22, 139, 140}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 57, 230, 44, 198, 62, 8}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{71, 191, 0, 0, 140, 136, 4, 228, 22, 207, 248, 21, 68, 96, 66, 196}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 33, 180, 166, 72}, 166}, {{71, 191, 0, 11, 123, 197, 97, 182, 125, 179, 20, 223, 223, 170, 219, 105}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 51, 131, 148}, 166}, {{71, 191, 0, 185, 193, 33, 75, 168, 121, 123, 112, 60, 144, 236, 143, 190}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 150, 122, 192}, 166}, {{71, 191, 0, 0, 0, 0, 0, 102, 149, 233, 170, 225, 166, 161, 31, 6}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 106, 227, 184, 14, 131, 46, 57, 19}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 161, 4}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 213, 227, 45, 55, 55, 30}, 166}, {{71, 191, 0, 0, 0, 0, 168, 212, 122, 93, 6, 152, 236, 238, 11, 193}, 166}, {{71, 191, 0, 0, 0, 22, 41, 38, 168, 151, 160, 18, 49, 169, 184, 189}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 197, 6, 87, 253, 2, 85}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 3, 61, 156, 84, 5, 51, 60}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 20, 91, 166, 95}, 166}, {{71, 191, 0, 0, 0, 0, 64, 51, 213, 170, 122, 92, 158, 133, 73, 7}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{71, 191, 0, 0, 0, 28, 149, 20, 167, 9, 12, 22, 113, 50, 218, 153}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 177, 137, 150, 241, 240, 153}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 166}, {{71, 191, 0, 0, 0, 0, 213, 215, 173, 149, 23, 93, 9, 243, 186, 98}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 247}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 176, 179, 9}, 166}, {{71, 191, 0, 0, 0, 0, 0, 53, 162, 204, 59, 53, 61, 216, 39, 225}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 69, 187, 144, 199, 230, 82}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 175, 25, 246, 134, 116, 206}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 11, 199}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 84, 27, 32, 79, 171, 99}, 166}, {{71, 191, 0, 130, 72, 183, 3, 26, 67, 244, 115, 40, 6, 173, 142, 145}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 253, 236, 162, 41}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 90, 84, 12, 1, 170, 47, 215}, 166}, {{71, 191, 0, 227, 139, 29, 2, 44, 233, 150, 72, 247, 27, 121, 57, 96}, 166}, {{71, 191, 0, 188, 97, 149, 63, 162, 145, 242, 173, 173, 55, 148, 30, 101}, 166}, {{71, 191, 0, 0, 62, 246, 183, 31, 106, 7, 227, 89, 39, 107, 218, 129}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 107, 216}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 43, 182}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 236, 125, 136, 53, 49, 24, 108}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 118, 209, 114, 119}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{71, 191, 0, 0, 0, 0, 0, 190, 132, 76, 108, 112, 136, 7, 170, 15}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 247, 61, 40, 151, 82, 20}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 252, 228, 124, 80, 209, 54}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 228, 34}, 166}, {{71, 191, 0, 0, 41, 111, 81, 1, 191, 81, 174, 209, 213, 79, 188, 205}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 79, 226, 113, 6}, 166}, {{71, 191, 0, 195, 153, 178, 208, 209, 208, 127, 222, 76, 33, 149, 155, 117}, 166}, {{71, 191, 0, 0, 0, 27, 99, 114, 42, 119, 152, 168, 120, 102, 28, 31}, 166}, {{71, 191, 0, 210, 201, 210, 204, 59, 238, 181, 142, 238, 110, 158, 175, 200}, 166}, {{71, 191, 0, 0, 0, 0, 0, 231, 77, 161, 120, 198, 92, 159, 135, 58}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 133, 76, 36, 233, 101, 227}, 166}, {{71, 191, 0, 0, 0, 0, 155, 139, 129, 142, 61, 27, 27, 204, 215, 223}, 166}, {{71, 191, 0, 0, 192, 16, 233, 176, 65, 197, 232, 46, 46, 237, 138, 144}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 5, 93, 91, 43, 235, 66, 49}, 166}, {{71, 191, 0, 115, 56, 42, 183, 79, 105, 225, 177, 229, 206, 154, 137, 53}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 198, 144, 151, 106, 153, 0, 192}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 88, 4}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 105}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 26, 91, 119, 150, 104, 199, 220, 175}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 203, 162}, 166}, {{71, 191, 0, 0, 0, 21, 209, 23, 115, 141, 159, 57, 48, 254, 148, 13}, 166}, {{71, 191, 0, 0, 0, 104, 229, 215, 25, 110, 103, 149, 76, 101, 216, 231}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 149, 27}, 166}, {{71, 191, 0, 0, 0, 0, 247, 50, 30, 33, 28, 53, 233, 53, 37, 87}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 178, 36, 239, 31}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 118, 83, 207, 158}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 13, 171, 255, 68}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 21, 241, 134, 145}, 166}, {{71, 191, 0, 48, 249, 252, 152, 78, 59, 255, 123, 168, 179, 108, 172, 79}, 166}, {{71, 191, 0, 0, 203, 229, 130, 93, 22, 214, 237, 110, 42, 61, 110, 12}, 166}, {{71, 191, 0, 0, 0, 220, 251, 232, 162, 56, 36, 51, 64, 69, 192, 183}, 166}, {{71, 191, 0, 0, 0, 0, 0, 142, 125, 203, 22, 78, 46, 245, 118, 68}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 137, 137, 209, 179, 69, 96, 76, 53}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 166}, {{71, 191, 0, 0, 0, 0, 0, 212, 202, 66, 131, 83, 35, 127, 33, 154}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 175}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 34, 148, 228}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 49, 94, 103, 167, 235, 64}, 166}, {{71, 191, 0, 0, 0, 86, 153, 210, 61, 9, 112, 124, 40, 119, 22, 218}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 111, 155}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 134, 82}, 166}, {{71, 191, 0, 176, 212, 100, 225, 118, 155, 171, 66, 111, 235, 145, 166, 71}, 166}, {{71, 191, 0, 0, 0, 22, 44, 228, 45, 40, 48, 44, 85, 60, 232, 53}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 8}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 108, 163, 42, 122, 34, 36, 2}, 166}, {{71, 191, 0, 0, 0, 0, 0, 30, 190, 163, 81, 178, 245, 204, 161, 16}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 49, 139}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 37, 146, 14, 154, 129, 22, 100, 153}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 115}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 240, 191}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 26}, 166}, {{71, 191, 0, 0, 0, 0, 0, 197, 26, 229, 12, 245, 178, 137, 23, 155}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 166}, {{71, 191, 0, 0, 0, 0, 0, 191, 11, 197, 51, 226, 54, 162, 78, 63}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 34, 158, 136, 220}, 166}, {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 177}, 166}, {{48, 136, 194, 145, 57, 96, 80, 19, 231, 36, 35, 106, 118, 10, 202, 104}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 159, 27, 201, 183, 66, 143, 98}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 212, 155, 214, 237, 49, 226, 83}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 191, 27, 138, 201, 239}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 129, 225, 143, 240, 64, 144, 50, 243}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 207, 7, 254, 155, 110, 46}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 111, 53, 58}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 87, 116, 140, 79, 93, 196, 88, 111}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 5, 32, 153}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 75, 150, 204, 195, 224, 223, 20}, 109}, {{48, 136, 194, 145, 57, 96, 0, 99, 232, 122, 126, 34, 190, 217, 24, 206}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 109}, {{48, 136, 194, 145, 57, 96, 0, 124, 171, 74, 127, 77, 210, 181, 16, 153}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 40, 32, 49, 26, 27, 81}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 99, 100, 154, 85}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 68, 148, 3, 84}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 224, 141, 21, 82}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 107, 84, 85, 27, 155, 48, 196}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 177, 25, 249, 134, 99}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 42, 87, 21, 244, 166, 242, 116, 10}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 239, 121, 230, 166, 226, 7, 199, 63}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 151, 18, 239, 46, 32, 145, 197}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 43, 95, 45, 227}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 177, 178, 118, 236}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 149, 22, 101, 147, 206, 43, 140, 13, 189}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 40, 161}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 86, 193}, 109}, {{48, 136, 194, 145, 57, 96, 0, 202, 227, 2, 10, 70, 62, 154, 212, 106}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 207, 7, 162}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 250, 161, 92, 89, 80, 35, 82}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 194, 237, 72, 31, 234, 0, 211, 213}, 109}, {{48, 136, 194, 145, 57, 96, 0, 163, 4, 152, 0, 99, 204, 14, 183, 191}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 159, 124, 239, 153, 109, 214}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 135, 143, 232}, 109}, {{48, 136, 194, 145, 57, 96, 0, 178, 177, 213, 1, 203, 113, 90, 250, 109}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 138, 205, 250, 243, 245}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 205, 25, 71}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 163, 222, 123, 255, 36, 44, 111}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 147, 158, 183, 220, 2, 114}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 1, 225, 15, 42, 196, 57, 175}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 94, 183}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 46, 158, 53, 66, 160, 253, 135}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 170, 16, 98, 184, 183, 187, 112}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 226, 56, 255, 108, 159, 225}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 99, 63, 117, 251, 204, 254, 251}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 189, 14, 133, 72, 173, 156, 26, 171}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 214, 197}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 236, 174}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 12, 227, 191, 131, 120, 67}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 218, 6, 176, 166, 59, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 50, 67, 35, 253, 41, 215, 114, 239}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 199, 143, 116}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 209, 140, 32, 192, 12}, 109}, {{48, 136, 194, 145, 57, 96, 131, 29, 225, 88, 220, 83, 241, 38, 135, 15}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 75, 157, 201, 113, 63, 236, 43, 143}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 169, 116, 213, 180, 65}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 57, 239, 164, 127, 122, 109, 196, 166, 147}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 243, 102, 195, 1, 2, 149, 167}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 72, 10, 235, 153, 129}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 210, 90}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 99, 75, 6, 134, 8, 67}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 236, 231, 203}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 41, 53, 179, 141, 90, 163, 223}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 154, 114, 74, 106, 89, 90}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 21, 2}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 169, 210, 247, 21, 110, 2}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 132, 87}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 154, 124, 132, 74, 204, 192}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 2, 48, 168, 7, 145}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 82, 105}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 38, 30, 157}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 124, 148, 77}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 124, 143, 46, 34, 241, 153, 133}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 108, 241}, 109}, {{48, 136, 194, 145, 57, 96, 0, 175, 181, 16, 27, 44, 194, 150, 252, 167}, 109}, {{48, 136, 194, 145, 57, 96, 161, 167, 101, 29, 184, 69, 31, 90, 243, 84}, 109}, {{48, 136, 194, 145, 57, 96, 69, 235, 255, 186, 86, 54, 175, 187, 119, 191}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 160, 116, 214, 222, 143}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 199, 41, 201, 32, 5, 254}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 153, 33, 153}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 29, 73}, 109}, {{48, 136, 194, 145, 57, 96, 194, 214, 187, 191, 81, 106, 166, 148, 159, 179}, 109}, {{144, 0, 0, 0, 0, 0, 0, 0, 9, 28, 221, 7, 65, 147, 59, 215}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 40, 75, 178}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 226}, {{144, 243, 39, 36, 13, 248, 104, 36, 190, 176, 9, 44, 53, 242, 88, 177}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 142, 54, 3, 254, 29}, 226}, {{144, 0, 0, 54, 117, 170, 217, 171, 252, 59, 133, 105, 217, 122, 54, 52}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 13, 85, 27}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 0, 92, 175, 41, 45, 136, 61, 239, 41, 113}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 199, 44, 234}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 43, 142}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 197, 21, 172, 50, 30, 237, 79}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 197, 137, 125, 240}, 226}, {{144, 0, 0, 0, 0, 0, 0, 165, 74, 235, 71, 244, 45, 202, 197, 189}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 181}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 87, 191, 51, 226, 237, 89, 13}, 226}, {{144, 0, 0, 0, 0, 112, 93, 153, 246, 255, 163, 4, 37, 118, 237, 21}, 226}, {{144, 0, 0, 166, 237, 67, 93, 64, 186, 1, 196, 170, 253, 144, 175, 48}, 226}, {{144, 0, 0, 0, 0, 0, 0, 68, 236, 248, 152, 251, 139, 63, 134, 27}, 226}, {{144, 0, 0, 0, 21, 217, 220, 179, 173, 234, 141, 92, 248, 55, 250, 198}, 226}, {{144, 0, 0, 0, 0, 0, 0, 197, 154, 246, 182, 11, 50, 87, 211, 170}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 112, 212, 97, 16, 146}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 230, 44, 218, 87}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 218, 8, 179, 188, 57, 77, 214}, 226}, {{144, 16, 176, 102, 189, 18, 112, 0, 37, 231, 59, 93, 96, 128, 49, 45}, 226}, {{144, 0, 0, 0, 0, 151, 254, 198, 89, 222, 24, 132, 108, 131, 138, 1}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 54, 86, 30}, 226}, {{144, 0, 0, 93, 181, 152, 191, 133, 120, 137, 183, 166, 19, 225, 132, 89}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 47, 84, 124, 30}, 226}, {{144, 213, 73, 22, 137, 91, 78, 5, 53, 35, 77, 122, 41, 91, 254, 228}, 226}, {{144, 0, 0, 0, 0, 0, 253, 203, 110, 65, 167, 161, 23, 40, 181, 120}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 232, 77}, 226}, {{144, 0, 0, 0, 212, 67, 138, 142, 52, 68, 14, 32, 81, 71, 20, 86}, 226}, {{144, 0, 0, 0, 44, 36, 248, 50, 68, 38, 243, 152, 84, 197, 136, 106}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 156, 237, 53, 159}, 226}, {{144, 0, 0, 0, 0, 66, 239, 66, 41, 232, 1, 229, 95, 105, 207, 218}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 214, 229}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 27, 143}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 177}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 170}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 151}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 238, 87, 106, 40, 182, 61, 150, 140}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 200}, 226}, {{144, 0, 0, 0, 184, 142, 54, 107, 194, 29, 206, 96, 214, 14, 67, 74}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 114, 230, 95, 35, 142, 93, 54}, 226}, {{144, 0, 0, 0, 20, 135, 17, 118, 18, 8, 40, 242, 169, 80, 220, 16}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 188, 156, 210, 253, 165, 30, 113, 49, 146, 138, 189, 247, 9}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 213}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 171, 131}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 191}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 167}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 230, 181}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 49, 254, 234, 100, 150}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 40, 49, 97, 157, 160, 244, 67, 255}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 122, 72, 21, 196}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 24, 39, 206, 89, 212, 219, 214, 211}, 226}, {{144, 0, 0, 0, 164, 167, 32, 15, 82, 131, 54, 66, 241, 95, 22, 19}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 157}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 12, 192, 136, 150, 128, 253, 12, 236, 209, 217, 12, 4}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 146, 161, 106, 37}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 242, 224, 21}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 255, 132}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 184, 154, 232, 227}, 226}, {{144, 0, 0, 0, 0, 0, 45, 187, 97, 46, 161, 80, 166, 212, 10, 145}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 11, 244, 188, 176, 222}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 247, 82, 113, 150, 63, 123, 164}, 226}, {{144, 0, 0, 0, 0, 191, 246, 161, 81, 166, 87, 160, 137, 149, 214, 111}, 226}, {{144, 0, 0, 0, 60, 80, 21, 82, 223, 6, 241, 194, 93, 156, 194, 183}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 236, 70, 190, 11, 52}, 226}, {{144, 212, 49, 208, 189, 121, 131, 232, 35, 77, 161, 213, 81, 247, 17, 112}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 159, 80, 43, 115, 39, 225, 213, 233, 162, 115}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 128, 83, 176, 62, 234}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 17, 87}, 226}, {{144, 0, 0, 0, 0, 202, 132, 248, 237, 149, 181, 204, 80, 138, 151, 105}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 226}, {{144, 0, 0, 0, 0, 0, 0, 67, 96, 42, 53, 157, 63, 183, 203, 109}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 223}, 226}, {{144, 0, 0, 241, 35, 160, 119, 11, 163, 189, 111, 2, 5, 113, 187, 179}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 198, 216, 65, 123, 121}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 252, 244, 157, 244, 164}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 118, 137}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 210, 0, 37, 105, 5}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 213, 230}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 54, 143, 43, 0, 148, 53, 215, 124}, 226}, {{144, 0, 19, 185, 7, 1, 95, 237, 60, 187, 13, 178, 150, 147, 228, 61}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 244, 39, 122, 39, 134, 227, 113}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 107, 119}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 120, 205}, 226}, {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 226, 72, 81, 51}, 226}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 255, 154, 172, 151}, 8}, {{223, 209, 10, 57, 0, 0, 59, 245, 4, 99, 191, 121, 108, 184, 222, 175}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 120, 9, 86, 90, 93, 198, 150}, 8}, {{223, 209, 10, 57, 0, 0, 223, 46, 81, 158, 53, 242, 142, 105, 31, 16}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 33, 124, 93, 198, 125, 72}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 16, 187, 159, 197, 219, 231, 214}, 8}, {{223, 209, 10, 57, 0, 0, 0, 32, 117, 174, 0, 137, 188, 186, 122, 15}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 165, 151, 204, 207, 29, 86, 117, 122}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 158, 92, 100, 162, 81, 227}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 239, 167, 158, 6, 128}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 64, 15, 132, 220, 159, 255, 219, 22}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 194, 194}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 237, 231, 168, 199, 216, 160, 229, 149, 9, 199, 128}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 47, 252, 64, 112, 255, 92, 38}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 5, 83}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 22, 20, 8, 87}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 126, 101, 63, 40, 200, 203, 232, 122}, 8}, {{223, 209, 10, 57, 0, 0, 111, 209, 66, 216, 217, 221, 225, 123, 202, 58}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 140, 212}, 8}, {{223, 209, 10, 57, 0, 101, 3, 189, 241, 59, 249, 140, 67, 123, 108, 247}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 100, 234, 188, 23, 234, 104}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 16, 62}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 56, 125, 208, 67, 130, 148}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 62, 231, 7, 58}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 71, 252}, 8}, {{223, 209, 10, 57, 0, 19, 110, 27, 74, 236, 95, 46, 38, 97, 11, 43}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 8}, {{223, 209, 10, 57, 0, 0, 74, 26, 205, 137, 215, 177, 109, 103, 145, 34}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 8}, {{223, 209, 10, 57, 0, 119, 134, 45, 150, 122, 219, 32, 135, 28, 63, 51}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 8}, {{223, 209, 10, 57, 0, 0, 37, 247, 139, 87, 126, 131, 33, 240, 230, 170}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 200, 125, 183, 222, 48}, 8}, {{223, 209, 10, 57, 0, 24, 43, 171, 85, 158, 240, 213, 150, 92, 206, 123}, 8}, {{223, 209, 10, 57, 0, 0, 0, 85, 137, 112, 159, 31, 132, 233, 13, 194}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 194, 218, 68, 124}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 92, 101, 218, 107, 38, 8, 224, 54}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 50, 4}, 8}, {{223, 209, 10, 57, 0, 34, 125, 199, 102, 161, 190, 186, 14, 52, 70, 180}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 152, 200, 69, 0, 107, 166}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 58, 133, 138, 29, 160, 2, 57, 131, 88, 192, 105}, 8}, {{223, 209, 10, 57, 0, 0, 0, 146, 254, 94, 42, 87, 54, 175, 4, 125}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 14, 20, 206, 3, 210, 111}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 131, 154, 195, 60, 249, 124, 254}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 8}, {{223, 209, 10, 57, 0, 0, 227, 41, 114, 126, 46, 86, 178, 218, 161, 37}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 160, 164, 200, 13, 206, 21, 139}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 32, 183, 20, 150, 78}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 108, 132, 48, 161, 245}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 131, 111}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 157, 102, 106, 196}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 205, 174, 92, 249, 204, 48}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 94, 198, 83, 219, 164, 52}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 84, 234, 129, 233, 194, 93}, 8}, {{223, 209, 10, 57, 0, 0, 142, 172, 57, 66, 81, 147, 41, 53, 163, 179}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 110, 68, 173, 254, 199, 102, 111}, 8}, {{223, 209, 10, 57, 0, 0, 0, 254, 168, 129, 50, 11, 118, 79, 191, 73}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 248, 190, 149, 237, 76, 195, 171}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 196}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 118, 146}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 236, 116, 38, 71, 204}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 219, 46, 8, 25, 242, 64, 43, 211, 141, 101}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 118, 172, 72, 49, 2}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 49, 157, 221, 207}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 94, 100, 228, 202, 97, 70, 229, 216, 193}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 36, 125, 235, 199, 184, 66}, 8}, {{223, 209, 10, 57, 0, 139, 14, 208, 115, 221, 252, 64, 55, 107, 221, 176}, 8}, {{223, 209, 10, 57, 0, 0, 0, 242, 244, 235, 218, 109, 175, 96, 19, 72}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 195}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 210, 14, 62, 71, 237}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 151, 8, 105, 204, 115, 202}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 240, 250}, 8}, {{223, 209, 10, 57, 0, 113, 10, 217, 0, 91, 18, 82, 139, 47, 246, 225}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 237, 127, 204, 228}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 220, 203, 175, 25}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 48, 216, 11, 132, 254, 108, 70, 171}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 50, 118, 226, 144, 231}, 8}, {{223, 209, 10, 57, 0, 0, 149, 17, 57, 50, 24, 87, 40, 139, 110, 105}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 187, 103, 115, 127, 231, 236, 48, 225}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 63, 139, 217, 201}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 115}, 8}, {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 3, 99, 141, 125, 182}, 8}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 39, 120, 138}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 251, 82}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 47, 230}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 134, 98, 207, 73}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 228, 7}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 83}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 81, 41, 43, 96}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 217, 227, 70, 201}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 113, 191, 102}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 45, 221, 212}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 157, 167, 41}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 47, 235, 207, 27}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 123}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 166}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 130, 96, 104}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 105, 161, 47}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 72, 155, 11}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 109, 84}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 175, 71}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 136, 86, 30}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 126, 78, 74, 73, 174}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 11, 10, 65}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 89, 115, 90, 38}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 170}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 169, 119}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 177, 23, 53, 96}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 14, 31, 6}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 142, 142, 168, 124}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 53, 141, 232}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 2, 137}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 74, 165, 195}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 35, 207, 153}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 185, 98, 17}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 152, 79, 180}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 14, 238, 6, 224}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 167, 123}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 109, 82}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 159, 100, 126}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 83, 6, 118, 37}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 149, 210, 55, 52}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 24}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 58}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 246, 245, 50}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 23, 60}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 232}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 60, 123, 175, 203, 254}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 175, 100, 101}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 138, 229, 166}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 62}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 159, 102}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 227, 102, 22, 147}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 23, 90}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 111, 20, 67, 3, 57}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 140, 104, 85, 245}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 161, 68}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 12, 62, 164, 148, 16}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 102, 14, 91, 119}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 189, 228, 229}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 8, 8, 95}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 148, 219}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 116, 22}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 15, 68}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 196, 195}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 187}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 200, 10}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 110, 4, 16, 64, 51}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 130}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 71, 6, 83}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 170, 114, 29, 152}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 136, 223}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 205, 242, 39, 149}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 96, 192, 194, 167}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 173, 128, 95, 216}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 97, 244, 73, 210}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 116}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 1, 51, 30, 70}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 82}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 167, 17, 96}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 22}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 212}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 180, 124, 232}, 218}, {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 40}, 218}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 195}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 100, 211}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 236, 109, 40, 70, 152}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 58, 114}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 103, 76, 116, 76, 41}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 86, 146}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 54, 181}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 148, 40, 40, 235, 154}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 62, 255, 255, 39, 26}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 177, 162, 17}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 54, 56}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 223, 86}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 234, 86, 190, 104}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 191, 23, 181, 54}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 104, 167, 220, 88}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 161, 17, 123, 170}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 1, 131}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 244, 89}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 123, 55, 205, 105}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 132, 138, 220, 41}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 216, 18}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 168, 114}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 187, 190, 7, 97, 174}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 35}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 19, 84, 199}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 107, 132, 142, 203, 136}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 199, 148, 121}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 222, 125}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 154, 141}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 230, 211, 180, 144}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 211, 46, 229, 57, 13, 250}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 196, 129}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 174, 76}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 154, 219, 70}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 1}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 19}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 36, 185, 230, 28}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 132, 95, 109}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 214, 229, 192, 120, 37, 216}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 234}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 37, 77, 225, 207}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 99, 11, 135}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 119, 53, 192, 175, 153}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 40, 26, 118, 45}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 75, 18, 29, 135}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 85, 160, 121, 242}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 180}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 240, 117, 20}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 243}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 77, 133, 98, 46}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 83, 47, 253}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 70, 59, 191}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 72, 94}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 81, 155, 219, 144}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 177, 199, 201, 137, 156}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 78, 4, 91}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 166, 151, 214}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 208, 130, 230, 188}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 226, 209}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 140, 248, 227}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 199, 130, 139, 121, 80}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 230, 183, 151}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 191, 93, 129}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 163, 218, 173, 243, 216}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 42, 155}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 163, 188}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 140, 111, 187, 236, 149}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 222, 30, 123}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 145, 83}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 35, 169}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 128}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 157, 124}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 47, 170, 249, 188}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 4, 245, 239, 177, 24, 201}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 167, 48}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 146, 210, 58, 55, 224}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 158}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 122, 132, 137, 39, 19}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 84}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 224, 27, 37, 1, 26}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 12, 73}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 103, 241, 87, 214, 172}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 126, 41, 214}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 203}, 54}, {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 86, 68, 178, 166, 13}, 54}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 33, 126, 190}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 137, 78, 4, 164, 17}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 21, 27, 106}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 106, 217}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 97, 42, 225}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 30, 89, 131, 80, 52, 225, 57}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 178}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 214, 104, 1, 254, 194}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 66, 203}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 216, 79}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 152, 178}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 178, 173, 94, 34, 77, 74}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 114, 9, 178, 64, 190, 202}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 222, 129, 47, 52}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 2, 217, 65, 113, 219, 185, 126}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 151, 164, 212, 249, 127, 126}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 216}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 30, 167, 216, 200}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 63, 58}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 237, 178, 159, 38, 3, 44}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 163, 177, 162, 62}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 168, 91, 197, 71, 249}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 223, 135, 143, 89, 87, 168, 143}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 86, 197, 42, 194}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 241, 187, 56}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 48, 229, 78, 87, 67, 219}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 79, 214, 118, 210, 149, 136}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 245, 73, 166, 151, 171, 31}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 147, 155, 118, 185, 13}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 142, 104, 70, 109}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 151, 211, 240}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 202, 182, 50, 60}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 177, 211, 197, 145, 65, 204}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 116, 233, 10, 97}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 16, 98, 180}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 220, 228, 182, 125, 244, 176}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 188}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 99, 122, 47, 31, 68, 5, 136}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 50, 74, 73, 61, 81, 96, 208}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 8, 86, 114}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 102, 223, 135}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 146, 201, 191}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 149, 106, 223, 40, 62}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 149, 51, 57, 124, 26}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 95, 56, 255}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 200, 83, 225, 245, 138, 231}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 152}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 29}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 240}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 138, 105, 57, 105}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 213, 154, 152, 251, 129, 91}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 142, 250, 236, 177, 133}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 144, 23, 3, 139, 113, 149, 56}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 145}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 166, 227, 95, 242, 208}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 134}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 20, 57, 134, 112, 211, 76}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 57, 244, 255, 15, 223}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 16, 52, 85}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 187}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 40}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 94, 207, 106}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 196}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 237, 162, 125, 8}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 21, 18, 120, 11, 169}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 71, 211, 45}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 161, 212}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 124, 205, 132, 185, 234, 237, 234}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 148, 231, 204, 27, 170, 33, 161}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 114, 57, 146, 39, 16, 70}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 147, 101, 149, 169}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 181, 158, 19, 2, 171, 245, 94}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 140, 162, 199}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 162, 70, 239, 14, 245}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 241, 205}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 161, 240, 49, 142, 7}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 235, 195, 3}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 243, 156, 251, 199, 187, 24}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 120, 217, 0, 51}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 70, 114, 88, 176, 135}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 196, 167, 144}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 175, 229, 121, 81, 212}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 10}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 250}, 48}, {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 51}, 48}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 128, 190, 47, 239}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 199, 222, 23, 216, 10, 34}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 53, 208, 239, 65, 22}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 120, 254, 194, 92}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 133, 76}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 25, 60, 32}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 254, 5, 26, 27, 145, 119, 191, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 53, 80, 71, 211, 48, 96, 131}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 236, 210, 97, 60, 56, 237, 21}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 205, 196, 147, 101, 5, 28, 2, 149}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 142, 146, 232, 218, 152, 222, 56, 67}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 230, 166, 96}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 59, 129, 158, 204, 142, 121, 221}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 177, 220, 24, 100, 31, 99}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 52, 85, 68}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 45, 211, 9}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 248, 55, 131, 59, 24, 152, 45}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 17, 254, 90, 225, 46}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 186, 215, 236}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 77, 181, 217, 218, 159}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 41, 97}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 226, 251, 74, 37, 91, 171, 3}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 244, 173, 51, 116, 190, 40, 197}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 191, 177, 223, 134}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 132, 166, 95, 74}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 127, 115, 249, 8, 193, 128, 10}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 65, 26}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 145, 156}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 88, 2}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 118, 89, 14}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 207, 112, 82, 79, 221, 123, 2}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 255, 231, 220, 44}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 26, 31, 3, 232, 89, 30, 21, 242}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 239, 72, 49}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 200, 73, 245, 25, 240, 76}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 242, 124, 250}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 105, 169, 23}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 159, 105, 253, 127, 248, 21, 198}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 213, 186, 100}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 110, 141, 2, 75, 81, 140, 79, 149}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 224, 150, 19, 221, 135, 119, 121}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 199, 145, 98, 75, 158, 193, 111, 13}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 155, 128, 166, 198, 29, 136}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 113, 9, 18}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 234, 213, 240, 110, 64}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 77, 42}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 87, 244, 204, 50, 91}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 73, 21, 223, 154, 56, 81, 142, 223}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 45, 99, 198, 128, 214, 145, 90}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 65, 18, 233, 170, 239, 207, 162, 157}, 244}, {{14, 73, 54, 76, 232, 35, 32, 181, 176, 179, 82, 181, 174, 7, 121, 131}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 25, 167, 151}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 73, 181, 23, 206, 83}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 198, 199, 199, 119, 37, 155, 16, 80}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 238, 100, 60, 28, 122}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 64, 9, 132, 203, 22, 105, 241, 185, 212}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 78, 189}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 172, 0, 119, 219, 22, 110}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 215, 178}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 210, 150, 131, 189, 167, 64, 168}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 183, 209, 213}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 167, 189}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 167, 206, 43}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 22, 28, 72, 70, 150, 170}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 105, 109, 3}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 148, 203, 223, 99, 191, 220}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 30, 241, 188, 143, 185, 213, 124, 69}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 124, 225, 207}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 105, 15, 246, 149, 253}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 111, 121}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 62, 129, 220, 61, 188}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 110, 43, 197}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 226, 87, 78, 126, 64, 197, 13, 44}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 167, 234}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 116, 133}, 244}, {{14, 73, 54, 76, 232, 35, 32, 166, 184, 126, 164, 96, 11, 169, 150, 0}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 192, 200, 126, 132, 48}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 11, 37, 51}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 243, 190, 5}, 244}, {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 103, 168, 149, 126, 121, 170}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 241}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 62, 12, 231}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 63, 39, 163, 123, 10, 142}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 66, 86, 127}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 113, 75, 28, 170, 128, 234}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 235, 241, 85, 122, 19}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 8, 61, 252, 64}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 74, 109, 127}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 35, 100, 52, 240}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 47, 85, 44, 112}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 142, 21, 252, 175, 242}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 60}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 25}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 38, 73, 222, 167}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 92, 129}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 75, 248, 199, 198, 113}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 18, 64}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 104}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 69, 135, 146, 180, 212, 24}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 148, 75, 114, 52, 206}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 117}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 219, 244, 7}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 106, 143}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 132, 80, 39}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 55, 184, 236, 173, 176}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 248, 110}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 150, 91, 104}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 10, 226, 101, 132, 115}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 42, 65, 133, 216, 181, 140}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 52, 242, 111}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 167, 93, 203, 140, 242, 180}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 132, 137}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 169, 150, 25}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 72, 225, 42, 167}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 222, 154, 123}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 46, 100}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 169, 164, 233, 204, 84}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 37, 227, 171}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 168, 142, 40, 236, 56, 241}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 60, 229, 152, 151, 216, 211}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 176, 17, 217, 180, 124}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 150}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 26, 196, 69, 44}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 142, 55, 2, 144, 113}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 137, 2, 50}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 181, 42}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 115, 50, 122, 213, 197, 152}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 253, 163}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 182, 80, 227, 251, 215, 250}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 24}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 6, 210, 87, 101, 142}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 108, 227}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 195, 253, 84}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 1, 76, 65, 98, 222}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 105, 185, 43}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 210, 154, 229, 215}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 93, 222, 172}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 28, 17, 187}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 173, 230, 180, 3}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 23, 69}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 35, 140}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 122, 34, 61, 125, 55}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 88}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 78, 239, 182, 14}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 126}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 134, 27, 225, 13}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 113, 192, 56, 26}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 232, 251, 8, 64}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 107, 20, 127}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 80, 89, 197, 173, 243}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 244, 131, 10}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 140, 248}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 82}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 31, 184}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 190, 98, 86, 129, 231, 121}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 114, 128, 229, 147, 126, 172}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 93, 167}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 107, 141, 13}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 26, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 204}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 95, 108, 182}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 161, 182}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 191, 191, 183, 43, 180, 130}, 50}, {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 50}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 27, 9, 221, 203, 82, 45}, 173}, {{122, 170, 9, 134, 124, 91, 24, 209, 123, 117, 144, 31, 182, 111, 236, 228}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 59, 183, 23}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 118, 49, 86, 27, 39}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 121, 71, 121, 61}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 221, 80, 28, 183, 196}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 189, 179, 165, 171, 215, 99, 222}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 43, 203, 224, 27, 78}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 52, 69, 90, 250, 116, 73, 164, 227}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 150, 215, 162}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 205, 255, 142, 69, 255, 126}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 126, 214, 29, 255, 154, 160, 248, 214}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 122, 87, 96, 130, 206, 141, 199, 202}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 119, 185, 97, 35, 90, 252, 16, 7}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 242, 12, 14, 94, 191, 156, 166, 10}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 136, 95, 187, 164}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 26, 253, 251, 249}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 246, 121, 244, 78, 211, 131, 98}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 226, 205, 137, 210, 184, 9}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 57, 151, 221, 15, 43, 78, 17}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 51, 166, 212}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 145, 109, 4}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 196, 192, 81, 177, 66}, 173}, {{122, 170, 9, 134, 124, 91, 24, 222, 106, 12, 235, 161, 122, 109, 192, 187}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 88, 26}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 102, 28, 249, 63}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 251, 159, 228, 145, 10, 152, 218}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 67, 110}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 155, 243, 73, 99, 110}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 57, 6, 99, 30}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 132, 30, 137, 134, 99, 204}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 20, 232, 91}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 107, 107, 253, 141}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 175, 41, 168, 226, 45, 119, 193}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 71, 236, 54, 162}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 168, 127}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 166, 192}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 100, 229, 158, 146, 211, 9}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 253, 44, 140, 36, 139, 174, 238, 8}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 238, 75, 128, 90, 192, 68, 192}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 93, 40, 194, 140, 152, 213}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 169, 89}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 205, 154, 121, 152}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 37, 127, 33, 175}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 168, 139, 255, 67, 7, 58, 11}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 115, 61, 128, 105, 42, 230, 75, 80}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 238, 51, 172, 129, 211, 225, 55}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 178, 133, 182, 80, 72, 233, 25}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 161, 114, 225, 116, 120, 170}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 71, 181, 86, 238, 165, 222, 130}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 50, 75, 95, 22}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 58, 254, 85, 213, 136, 1, 57, 199}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 59, 149, 125, 220, 138, 225, 21}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 59, 60, 3, 177, 187, 141, 203, 68}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 169, 8, 234}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 144, 104, 97, 63, 207}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 109, 167, 32, 94, 208, 1}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 36, 148, 32, 30, 155, 230, 101}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 38, 52, 158, 180}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 182, 157, 228, 190, 211, 217, 97}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 123, 93, 206, 79}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 252, 228}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 173, 59, 131, 92, 203, 166}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 26, 130, 44}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 182, 71, 253, 149, 166}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 111, 184}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 244, 72, 68, 47, 38, 110, 77, 228}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 90, 214, 61}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 49, 166, 223, 92, 54, 228, 122}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 203, 3, 202}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 126, 161, 209, 250, 80}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 46, 217, 171, 155, 148, 147, 165, 218}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 231, 226, 138, 57, 97, 152, 39}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 63, 18}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 126, 196, 162, 83}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 189, 177, 191, 156, 170, 152, 131}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 212, 179, 209, 80}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 100, 62, 78, 86}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 46, 21}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 158, 190, 174, 178}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 55, 221, 67, 130, 197, 35}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 162, 107, 58, 132, 253, 126, 36, 244}, 173}, {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 173}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 44}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 111, 22}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 216, 26}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 194, 106}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 18, 115, 119}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 230}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 29}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 125, 35}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 129, 132, 129}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 86, 58}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 244, 85, 63}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 158}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 151}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 124}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 174, 203}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 29, 2, 9, 184}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 41}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 240}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 161}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 29, 100}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 113, 12, 253, 75}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 233}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 12, 5, 225, 12, 45}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 63, 60, 142, 242}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 157, 148, 146}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 58, 173}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 247, 166, 97}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 164, 236, 254}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 205, 227, 71}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 82, 170, 18}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 111, 116, 112}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 56, 18, 24, 185}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 97, 95, 64}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 242, 203, 147, 145}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 60}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 4, 206, 218, 180}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 239, 229, 143, 11}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 46}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 78, 228, 36}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 90, 165}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 241, 227, 160, 254}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 189, 124}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 27}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 143, 81, 18, 238}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 219, 0, 186, 76, 208}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 115, 127}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 66, 229, 213, 186, 10}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 139}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 125, 94, 147, 162, 173}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 30, 170, 87, 183}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 6, 152}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 174, 160, 204, 211, 51}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 190, 121, 122}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 148, 100, 10, 39}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 109, 67}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 254, 176}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 179, 163, 84}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 142}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 115, 32, 135}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 212}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 156, 247}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 228, 248}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 197, 92, 92}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 180, 174, 94, 161}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 55, 244, 228}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 67}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 152}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 158, 45, 121}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 27}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 185, 133}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 130}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 141, 192}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 70}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 192, 159, 228, 220}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 90, 201, 126, 121}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 67, 150}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 155, 236}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 94, 87, 140}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 220, 20, 91}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 247, 119}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 212}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 246, 214}, 245}, {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 112, 174, 231}, 245}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 54}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 204}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 76}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 25}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 193}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 132}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 16}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 6}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 27}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 181}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 147}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 26}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 12}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 96}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 153}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 214}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 140}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 140}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 78}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 29}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 39}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 77}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 71}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 189}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 25}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 161}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 149}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 215}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 168}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 136}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 110}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 226}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 129}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 99}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 32}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 236}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 228}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 48}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 17}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 135}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 45}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 43}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 101}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 26}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 229}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 131}, 86}, {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 86}, {{128, 0, 0, 0, 239, 161, 128, 123, 93, 240, 48, 188, 107, 60, 208, 212}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 85, 20}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 84, 3, 131, 155, 89, 48, 130, 104, 185, 209, 129}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 147, 203, 31, 58, 25}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 188, 120, 20, 215, 141, 21, 187}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 252, 108, 2, 193}, 218}, {{128, 0, 0, 0, 0, 0, 0, 138, 255, 88, 150, 251, 209, 37, 77, 39}, 218}, {{128, 0, 231, 154, 212, 207, 68, 85, 53, 36, 197, 6, 196, 195, 103, 49}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 72, 88, 90}, 218}, {{128, 0, 0, 0, 0, 40, 115, 142, 194, 69, 110, 206, 175, 114, 155, 253}, 218}, {{128, 0, 0, 0, 0, 0, 0, 68, 157, 78, 40, 8, 57, 167, 140, 190}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 218}, {{128, 0, 0, 0, 0, 0, 85, 238, 248, 106, 130, 47, 202, 145, 145, 98}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 143, 247, 186, 217, 113}, 218}, {{128, 0, 0, 50, 178, 135, 103, 3, 221, 247, 198, 13, 29, 78, 84, 246}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 145, 80, 10}, 218}, {{128, 0, 0, 0, 0, 0, 32, 171, 101, 111, 0, 88, 192, 177, 42, 160}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 187, 77, 229, 2, 202, 190, 77, 106}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 250, 189, 236}, 218}, {{128, 0, 0, 0, 171, 104, 251, 57, 50, 61, 160, 190, 158, 142, 136, 190}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 99}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 218, 90, 211, 63, 65, 248, 183}, 218}, {{128, 0, 155, 8, 127, 58, 133, 5, 230, 56, 175, 204, 168, 162, 173, 28}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 220, 132, 93, 82}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 185, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 1, 82, 15, 3, 4, 27, 191, 230, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 26}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 161, 131, 58, 77, 233, 202, 168, 144, 2, 250, 157, 251, 95}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 118}, 218}, {{128, 0, 0, 0, 0, 0, 0, 86, 187, 27, 145, 100, 176, 35, 93, 166}, 218}, {{128, 0, 0, 0, 0, 0, 0, 59, 71, 70, 114, 218, 152, 145, 239, 54}, 218}, {{128, 0, 0, 0, 91, 179, 170, 79, 103, 75, 49, 41, 125, 225, 170, 232}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 219, 190, 180, 82, 162, 32, 173, 99, 230, 222, 113, 43, 77, 84, 123}, 218}, {{128, 0, 0, 0, 0, 0, 40, 253, 98, 34, 235, 152, 72, 30, 112, 239}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 22, 23, 161, 107}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 253, 151, 147, 116, 32, 30, 243}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 135, 176, 43, 14, 72}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 190, 192, 196, 157, 223, 181, 215}, 218}, {{128, 0, 61, 140, 86, 48, 90, 174, 6, 123, 250, 225, 46, 13, 166, 99}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 21}, 218}, {{128, 0, 0, 0, 0, 0, 0, 245, 25, 238, 88, 134, 202, 137, 76, 126}, 218}, {{128, 0, 0, 0, 0, 0, 0, 249, 150, 16, 80, 110, 201, 34, 170, 255}, 218}, {{128, 0, 0, 0, 98, 221, 39, 218, 250, 83, 177, 78, 124, 250, 146, 25}, 218}, {{128, 0, 0, 0, 0, 28, 94, 155, 99, 220, 88, 106, 54, 188, 39, 157}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 81, 62}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 59, 50, 158, 13, 195, 175, 218}, 218}, {{128, 0, 0, 0, 0, 0, 195, 163, 63, 208, 56, 136, 223, 157, 2, 74}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 157}, 218}, {{128, 0, 167, 134, 176, 67, 72, 111, 140, 19, 87, 210, 95, 117, 49, 197}, 218}, {{128, 0, 0, 245, 43, 227, 192, 208, 233, 223, 142, 56, 65, 249, 204, 11}, 218}, {{128, 0, 0, 0, 0, 0, 24, 125, 242, 36, 39, 12, 33, 161, 189, 154}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 156, 228, 189, 133, 32}, 218}, {{128, 0, 0, 170, 140, 43, 73, 240, 179, 236, 56, 25, 125, 95, 34, 29}, 218}, {{128, 0, 0, 0, 0, 180, 128, 89, 230, 241, 156, 51, 214, 232, 160, 52}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 170, 149, 193, 152, 202}, 218}, {{128, 0, 74, 131, 160, 141, 245, 247, 219, 228, 81, 164, 45, 163, 118, 71}, 218}, {{128, 0, 0, 27, 88, 118, 3, 241, 174, 242, 81, 34, 209, 210, 244, 100}, 218}, {{128, 0, 0, 113, 38, 180, 88, 79, 246, 45, 121, 254, 240, 223, 119, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 38, 191, 80}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 7, 182, 196, 242, 186, 252, 148}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 119, 96, 2, 83, 69, 96, 43}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 145, 24, 237, 181, 54, 162, 217, 62}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 177, 41, 104, 63, 18, 83, 65, 42}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 169, 181, 44, 9}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 70, 169}, 218}, {{128, 0, 4, 123, 218, 148, 53, 183, 143, 48, 160, 238, 133, 198, 55, 225}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 218}, {{128, 0, 0, 0, 0, 65, 33, 97, 58, 61, 100, 18, 55, 91, 107, 93}, 218}, {{128, 88, 22, 112, 150, 32, 115, 251, 60, 236, 198, 231, 110, 29, 3, 217}, 218}, {{128, 0, 251, 238, 160, 35, 73, 100, 129, 186, 233, 222, 186, 15, 235, 239}, 218}, {{128, 0, 0, 74, 2, 171, 230, 38, 16, 51, 162, 117, 69, 217, 150, 125}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 131, 18, 40, 12, 48, 232, 105, 207}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 115, 71, 66}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 149}, 218}, {{128, 0, 37, 67, 149, 176, 111, 172, 201, 62, 185, 211, 4, 33, 66, 70}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 24}, 218}, {{128, 0, 0, 0, 0, 135, 172, 232, 204, 234, 171, 145, 213, 15, 17, 221}, 218}, {{128, 0, 0, 0, 0, 0, 113, 94, 1, 89, 102, 28, 189, 160, 168, 100}, 218}, {{128, 0, 0, 0, 198, 95, 32, 26, 154, 20, 213, 201, 37, 40, 132, 2}, 218}, {{128, 0, 0, 0, 0, 0, 118, 58, 225, 127, 72, 85, 109, 44, 254, 109}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 232, 240, 6, 46, 210, 51, 240, 37}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 180, 113, 186}, 218}, {{128, 34, 148, 28, 127, 57, 217, 168, 243, 70, 127, 91, 124, 91, 168, 178}, 218}, {{128, 0, 17, 6, 63, 110, 255, 16, 200, 107, 9, 118, 200, 232, 130, 127}, 218}, {{128, 0, 0, 91, 47, 124, 25, 175, 79, 41, 253, 254, 134, 26, 76, 200}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 43, 242}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 55, 92}, 218}, {{128, 0, 0, 0, 0, 0, 0, 248, 251, 1, 31, 113, 177, 30, 216, 185}, 218}, {{128, 0, 0, 0, 0, 0, 255, 246, 67, 236, 254, 13, 2, 244, 85, 76}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 51, 194}, 218}, {{128, 253, 190, 35, 108, 62, 135, 124, 177, 238, 85, 80, 255, 235, 11, 247}, 218}, {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 218}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 233, 188}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 101, 231, 72, 228, 230, 92, 174, 111, 237}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 184, 141, 35, 151, 117, 29, 155}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 25, 166, 138, 231, 125}, 144}, {{12, 35, 50, 0, 0, 0, 78, 183, 122, 246, 51, 111, 2, 215, 177, 215}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 23, 223}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 249, 94}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 133, 17, 92}, 144}, {{12, 35, 50, 0, 0, 0, 0, 254, 97, 114, 97, 216, 190, 79, 145, 190}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 144}, {{12, 35, 50, 0, 0, 0, 240, 171, 114, 80, 143, 20, 27, 147, 222, 65}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 205, 203, 7, 228, 133, 116, 202, 247}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 33, 254, 124}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 13, 164, 118, 17, 165}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 34, 154, 12, 28, 219, 255, 155, 62, 63, 116, 80}, 144}, {{12, 35, 50, 0, 0, 0, 201, 244, 116, 12, 211, 77, 196, 70, 194, 14}, 144}, {{12, 35, 50, 0, 67, 64, 233, 26, 63, 103, 71, 43, 168, 62, 184, 102}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 145, 84, 128, 212, 106, 95, 144}, 144}, {{12, 35, 50, 0, 0, 160, 99, 166, 78, 148, 239, 122, 42, 136, 3, 10}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 27, 90, 227, 242, 18, 165, 11}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 234, 238, 58, 114, 218, 174, 167}, 144}, {{12, 35, 50, 0, 0, 241, 47, 233, 25, 205, 200, 202, 212, 10, 37, 35}, 144}, {{12, 35, 50, 0, 0, 5, 117, 106, 126, 187, 101, 112, 91, 83, 5, 247}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 144}, {{12, 35, 50, 0, 0, 0, 120, 247, 34, 207, 8, 10, 77, 228, 77, 132}, 144}, {{12, 35, 50, 0, 0, 103, 199, 67, 5, 142, 195, 154, 228, 39, 105, 38}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 164, 117, 21}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 2, 43, 44, 221, 117, 104}, 144}, {{12, 35, 50, 0, 0, 117, 43, 71, 186, 38, 220, 1, 32, 239, 171, 207}, 144}, {{12, 35, 50, 0, 0, 0, 172, 77, 22, 210, 141, 140, 55, 155, 94, 175}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 86}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 114, 248, 40, 107, 53, 28}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 195, 153, 98, 225, 34, 144, 188, 190}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 200, 224, 166}, 144}, {{12, 35, 50, 0, 48, 167, 122, 68, 20, 71, 17, 113, 181, 177, 221, 204}, 144}, {{12, 35, 50, 0, 0, 182, 181, 26, 145, 169, 22, 39, 212, 228, 151, 167}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 161, 52, 72, 113, 207}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 84}, 144}, {{12, 35, 50, 0, 0, 0, 0, 88, 165, 51, 21, 235, 167, 215, 233, 31}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 223}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 188, 33, 85, 219, 36, 233, 146, 118, 63}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 195, 63, 217, 47, 20, 135, 53}, 144}, {{12, 35, 50, 0, 0, 235, 6, 122, 88, 146, 138, 237, 151, 194, 173, 250}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 169, 53, 168}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 174}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 69, 1, 123}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 154, 88, 138, 66, 167, 102, 23, 124}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 60}, 144}, {{12, 35, 50, 0, 0, 0, 34, 153, 39, 239, 226, 189, 90, 52, 53, 88}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 45}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 77, 173, 158, 76, 228, 59, 159, 141, 6}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 40, 152, 187, 133, 204, 157}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 51, 100, 94, 241, 251, 36, 149, 179}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 178, 36}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 34, 138, 227, 115, 227, 248, 226, 167}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 38}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 1, 110, 15, 38, 130, 66}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 165}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 163, 135}, 144}, {{12, 35, 50, 0, 0, 0, 0, 180, 6, 255, 230, 148, 39, 247, 107, 167}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 207, 32, 115, 244, 248, 185, 48, 7}, 144}, {{12, 35, 50, 0, 0, 0, 255, 255, 126, 252, 141, 80, 51, 250, 248, 141}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 104}, 144}, {{12, 35, 50, 0, 0, 0, 0, 85, 154, 217, 189, 173, 225, 189, 204, 254}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 41, 50, 166}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 82, 65, 190, 207, 76}, 144}, {{12, 35, 50, 0, 0, 0, 0, 64, 149, 185, 170, 46, 70, 218, 193, 46}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 114, 106, 138, 138, 39, 118, 230}, 144}, {{12, 35, 50, 0, 0, 0, 12, 39, 224, 141, 177, 104, 94, 152, 183, 133}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 61, 238}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 55}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 138, 62}, 144}, {{12, 35, 50, 0, 0, 96, 246, 32, 41, 30, 199, 254, 93, 127, 11, 237}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 103, 94, 42, 241, 184, 217, 145}, 144}, {{12, 35, 50, 0, 0, 74, 138, 183, 204, 140, 22, 68, 246, 83, 52, 23}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 178, 89, 41, 94, 74, 132, 74}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 244, 172}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 129, 124}, 144}, {{12, 35, 50, 0, 0, 0, 12, 34, 250, 242, 104, 55, 115, 37, 77, 193}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 171, 161, 90}, 144}, {{12, 35, 50, 0, 0, 0, 196, 203, 44, 156, 255, 92, 17, 11, 38, 249}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 169, 122, 138, 196, 221, 217, 253, 228}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 7, 131, 30, 238, 188}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 48, 146, 255}, 144}, {{12, 35, 50, 0, 0, 111, 107, 43, 217, 49, 207, 1, 43, 55, 51, 84}, 144}, {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{12, 35, 50, 0, 5, 141, 17, 224, 65, 0, 218, 89, 194, 156, 144, 70}, 144}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 238}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 186, 29}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 228, 217, 172, 138}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 98}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 134}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 239, 29, 89, 219}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 205}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 86, 246, 44}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 51, 162}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 229, 69, 92, 166}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 97, 45, 216}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 238, 115, 235, 127}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 168, 24}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 247, 13, 34, 175}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 197}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 13}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 3, 10}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 255, 247, 221}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 128, 74, 145}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 249, 208, 167}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 153}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 81, 195}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 227}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 226, 99, 27, 4}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 63, 43, 190, 123}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 99}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 150, 207, 237, 33}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 62, 210, 163, 76}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 238, 68, 254}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 90, 184}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 230, 36}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 38, 177, 140, 29}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 246, 41}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 249, 53}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 220, 49, 249, 98}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 157, 142}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 124}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 10, 101}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 162}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 163, 132}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 31}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 70, 1, 50}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 53, 21, 207}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 30}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 200, 29, 70, 37}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 49, 86, 84}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 124, 214, 28}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 59}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 239, 17, 112, 139}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 146, 128, 160, 104}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 81, 235, 227}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 239, 67, 212, 131}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 21, 64}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 199, 28}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 229, 44, 78}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 44, 92, 131}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 120}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 95, 255}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 202, 132, 103}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 60, 85, 245}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 158, 130, 33, 66}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 242, 97, 51}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 54}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 235}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 220, 203, 37, 162}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 159}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 204, 156, 239, 103}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 80, 218}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 98, 109, 117}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 22, 27, 15}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 244}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 137, 49}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 167, 96, 5}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 191, 137, 137}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 53}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 147, 248, 253}, 171}, {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 188, 228}, 171}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 144, 127, 152, 35}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 231, 201}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 67, 2, 8}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 156, 41, 252}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 11, 211, 254, 34}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 189, 252, 123, 6}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 240}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 111, 3, 66}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 65, 144}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 12, 241}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 211}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 62, 28, 33}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 147}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 240}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 146, 31}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 234, 23, 175}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 5, 130, 112, 50}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 83, 82}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 121, 57, 188}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 202, 29}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 140}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 150, 199, 131}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 9, 23, 189}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 177, 190, 191}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 93, 110, 212}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 236, 63}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 53, 165, 197}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 192, 66}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 4, 14, 232}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 12}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 51, 43, 79}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 242, 122, 228}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 33, 136, 76}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 52}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 100}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 114, 25, 155}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 154, 108}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 229, 191}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 15, 232}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 149, 90, 242}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 76, 40, 54}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 217, 128, 251}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 111, 84}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 56, 224, 187}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 248, 65, 175}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 78}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 117}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 162, 243}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 200, 29, 27}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 208, 95, 245}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 67}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 254, 162}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 22}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 37, 160}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 214}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 78, 44}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 129, 164, 190}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 186}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 64, 247, 138}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 211}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 251, 105}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 249, 120, 78}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 164, 223}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 215, 99}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 157, 118, 171}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 144, 9}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 242, 185, 229}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 32}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 13}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 175, 180}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 225, 220, 4}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 72, 219}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 34, 17, 251}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 211}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 68}, 231}, {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 231}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 145, 108, 91}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 242, 107}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 200}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 234, 95, 196}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 211}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 72, 137, 176}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 208, 34, 25}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 226, 43, 142}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 180, 75, 74, 194}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 127, 211, 144, 99}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 20, 222, 165}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 120, 10, 231, 70}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 189, 10, 129, 68}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 6, 54, 80, 8}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 179}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 220, 111}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 104, 202, 103, 83}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 158, 104, 195}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 100}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 41, 46, 144}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 59, 174, 83, 201}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 90, 113}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 32, 100, 145, 65}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 86, 218}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 83, 41}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 9, 105, 215}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 137}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 87, 24}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 181, 215}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 110, 181, 134}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 54}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 19, 89, 162, 117}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 8, 165, 90}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 94, 121, 48, 245}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 161, 74, 143}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 22}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 55, 64, 86, 119}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 162}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 41, 160, 90, 11}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 35, 173}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 185, 91}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 67, 210, 204}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 167, 10, 19, 76}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 155, 88, 27}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 184, 255, 118, 14}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 255, 85, 181, 14}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 234}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 176, 36, 218}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 230, 36}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 131, 66, 222, 197}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 42, 61, 201}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 22}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 73, 166, 4}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 183, 215, 121, 20}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 186, 153}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 175, 219, 31}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 90, 149}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 149, 103, 30, 67}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 160}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 45, 138, 7}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 31, 215}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 108, 62}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 122}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 71}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 20, 236, 15}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 246, 125, 131, 21}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 135}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 46, 206, 213, 62}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 163, 97, 182}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 45}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 246, 11, 8, 245}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 223, 244, 39}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 187}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 216}, 34}, {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 181, 183}, 34}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 74, 87, 104, 42}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 56, 57, 66}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 207, 199, 18, 51, 93, 22}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 82, 144, 100}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 147, 72, 11, 28, 139, 23, 250}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 51, 163, 132, 222, 71, 189, 128, 175}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 192, 135, 22}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 193, 103, 48, 118, 238, 8}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 150, 191, 166, 215, 16, 122, 239, 146}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 252, 165, 128, 211, 196, 218, 32, 104}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 149, 64, 144, 15, 44, 81, 79, 193}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 176, 142, 179, 212, 121, 219}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 167, 58, 200, 134, 242, 27, 75, 147}, 225}, {{216, 69, 47, 53, 117, 24, 56, 132, 163, 64, 144, 118, 116, 236, 24, 106}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 66, 154, 90, 120, 130}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 32, 26, 102, 216, 150, 235, 20, 229}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 156, 154, 106, 80, 235, 32, 26}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 58, 118, 197, 234, 126, 193, 8, 205}, 225}, {{216, 69, 47, 53, 117, 24, 56, 198, 35, 66, 160, 255, 199, 119, 47, 112}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 14, 165}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 190, 253, 80, 6, 63, 105, 225, 179}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 181, 208, 194, 34, 120, 151}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 232, 171}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 144, 48, 239, 232, 175, 181}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 121, 2, 126, 4, 31, 122, 176}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 253, 230, 253, 247}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 94, 2, 41, 211, 82, 158}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 161, 192}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 107, 149}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 38, 106, 43, 65, 113}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 64, 36, 26, 23, 149, 252}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 159, 76, 200, 245, 179, 150}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 107, 27}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 153, 64, 164, 129, 159, 182}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 44, 63}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 51, 136, 97, 9, 62, 18, 52}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 19, 99, 116, 131, 34}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 84, 138, 114}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 1, 157, 188, 165, 150, 72, 174}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 220, 148, 174, 207, 204, 18, 11}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 201, 236, 138}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 177, 82, 82, 77}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 194, 180, 241, 73, 158, 99}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 97, 123, 230, 55, 42}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 87, 68, 112, 42}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 206, 242, 249}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 46, 28, 65, 121, 148, 72}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 7, 104, 220}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 199, 158, 83}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 174, 166, 174, 237, 206, 123, 77}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 48, 63, 49, 107, 88}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 60, 106, 67, 109, 242, 161}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 181, 220, 115, 119, 202, 38, 68}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 130, 98, 207, 29, 161, 200, 228}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 97, 200, 212, 134, 175}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 180, 137}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 208, 246, 41, 21, 230, 174, 0, 139}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 41, 191, 242, 225, 20, 159, 69, 175}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 132, 225, 154, 111, 196, 238, 173}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 202, 147, 130}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 239, 228, 80, 13, 189, 92, 127}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 185, 127}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 171, 179, 39, 170, 95, 8, 114, 111}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 193, 115, 67, 210, 53, 199}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 243, 8}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 96, 214, 227, 6, 81, 77, 242}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 121, 7, 206, 71, 79, 113}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 161, 173}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 233, 84}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 217, 8, 215, 221, 147, 138}, 225}, {{216, 69, 47, 53, 117, 24, 56, 146, 198, 7, 44, 131, 228, 149, 209, 120}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 30, 133, 150, 112, 87, 213}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 26, 218, 246, 46, 246, 84, 183}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 236, 145, 90}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 33, 121, 215}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 125, 23, 125, 153, 37, 1}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 36, 226}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 99, 213}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 123, 105, 109, 174, 165, 182}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 53, 175, 127, 10, 151}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 225}, {{216, 69, 47, 53, 117, 24, 56, 59, 161, 88, 12, 206, 244, 49, 138, 148}, 225}, {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 179}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 102, 96, 212, 59, 219, 212}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 217, 56, 251}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 207, 156, 228, 99}, 174}, {{180, 87, 25, 236, 56, 0, 18, 115, 125, 237, 78, 194, 235, 179, 214, 216}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 66, 18, 74, 131, 71}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 213, 105, 152}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 42, 33, 67}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 61, 180, 49}, 174}, {{180, 87, 25, 236, 56, 0, 47, 114, 234, 13, 165, 99, 9, 221, 167, 217}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 126, 99, 14, 226, 191, 185}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 143, 17, 204, 30, 68, 245, 109}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 19, 156, 239, 194, 6}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 75, 174, 171}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 142, 201, 55, 5, 69, 236, 251}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 53}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 174}, {{180, 87, 25, 236, 56, 0, 0, 90, 192, 86, 73, 85, 216, 15, 235, 142}, 174}, {{180, 87, 25, 236, 56, 0, 144, 204, 40, 157, 36, 192, 246, 91, 20, 63}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 12, 81, 42, 7}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 210}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 217, 228, 230, 248, 184, 196}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 38, 254, 204, 3, 41, 13}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 246, 56, 20, 28, 225}, 174}, {{180, 87, 25, 236, 56, 0, 0, 79, 62, 60, 210, 196, 195, 246, 198, 165}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 247, 43, 153, 86, 47, 33, 63, 76}, 174}, {{180, 87, 25, 236, 56, 0, 169, 253, 162, 215, 242, 131, 40, 231, 226, 190}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 27, 195, 142, 172, 196, 149, 26, 30}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 103}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 246, 165, 15, 95, 156, 41, 33}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 117, 178, 84, 48, 141, 110, 247}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 43}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 174}, {{180, 87, 25, 236, 56, 0, 226, 25, 87, 251, 101, 231, 226, 201, 189, 148}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 98, 112, 189, 200, 162, 96, 78, 153}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 112, 175, 191, 193}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 174}, {{180, 87, 25, 236, 56, 0, 103, 118, 132, 246, 121, 238, 243, 231, 147, 51}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 55}, 174}, {{180, 87, 25, 236, 56, 0, 0, 108, 113, 12, 36, 12, 208, 62, 191, 85}, 174}, {{180, 87, 25, 236, 56, 0, 0, 55, 241, 2, 210, 60, 131, 2, 218, 26}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 151, 254, 60, 46, 89, 23}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 188, 134, 109, 11, 155, 227, 115}, 174}, {{180, 87, 25, 236, 56, 0, 0, 61, 0, 57, 113, 247, 117, 221, 16, 248}, 174}, {{180, 87, 25, 236, 56, 0, 137, 41, 41, 22, 213, 105, 97, 46, 133, 254}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 168, 227, 104}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 174}, {{180, 87, 25, 236, 56, 0, 0, 81, 6, 208, 132, 248, 37, 147, 150, 97}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 148, 116, 16, 235, 209, 9, 89, 247}, 174}, {{180, 87, 25, 236, 56, 0, 115, 83, 87, 220, 138, 173, 88, 122, 224, 45}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 252, 59, 2, 241, 162}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 63, 169, 151, 132, 137, 123, 94}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 201}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 103, 107, 144, 203, 121, 135, 69}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 10, 148, 167, 40, 226, 14}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 176, 120, 116}, 174}, {{180, 87, 25, 236, 56, 0, 0, 21, 70, 241, 139, 18, 246, 161, 34, 16}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 34}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 231, 170, 202, 232, 27, 81}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 248}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 169, 248, 175, 236, 97, 24, 137}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 202}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 174, 220, 76, 2, 82, 100, 165, 121}, 174}, {{180, 87, 25, 236, 56, 0, 255, 95, 149, 19, 206, 184, 200, 159, 13, 132}, 174}, {{180, 87, 25, 236, 56, 0, 120, 30, 11, 94, 248, 135, 250, 253, 190, 167}, 174}, {{180, 87, 25, 236, 56, 0, 0, 95, 7, 157, 188, 172, 58, 144, 214, 219}, 174}, {{180, 87, 25, 236, 56, 0, 22, 117, 204, 61, 130, 43, 47, 87, 59, 210}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 101, 248, 248, 132, 4, 232, 192, 216}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 111, 78, 35, 165}, 174}, {{180, 87, 25, 236, 56, 219, 110, 147, 171, 134, 33, 61, 45, 68, 189, 105}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 97, 208, 147, 7, 153, 40, 50, 202}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 56, 3, 172, 255, 30, 210, 6}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 78, 2, 53, 162, 253, 75, 95}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 88}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 61, 228, 3, 194, 33, 214, 137}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 250, 158, 130}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 54}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 211, 242, 253, 107, 182, 179}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 168, 140, 196, 205}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 63, 235, 225, 72, 162, 102, 111, 63}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 214, 111, 7, 36, 228, 193, 179}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 70, 56, 200, 87, 60, 119, 198, 63}, 174}, {{180, 87, 25, 236, 56, 0, 99, 76, 38, 21, 76, 187, 15, 39, 231, 48}, 174}, {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 124, 187, 201}, 174}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 233}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 205}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 111}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 119}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 206}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 21}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 84}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 12}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 92}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 219}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 44}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 166}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 183}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 76}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 69}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 93}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 213}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 77}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 2}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 66}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 181}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 149}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 129}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 184}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 157}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 22}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 71}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 79}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 205}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 251}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 76}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 121}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 36}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 92}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 64}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 83}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 55}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 123}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 196}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 13}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 104}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 210}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 46}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 112}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 37}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 39}, {{186, 117, 252, 0, 11, 243, 204, 70, 166, 125, 173, 167, 183, 26, 71, 116}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 206, 65, 147}, 59}, {{186, 117, 252, 0, 0, 0, 0, 53, 145, 184, 155, 104, 247, 40, 115, 221}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 5, 204, 40, 58, 254, 194, 185}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 193, 19, 167, 84, 214}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 63, 179, 183, 206, 253}, 59}, {{186, 117, 252, 0, 0, 0, 0, 162, 109, 174, 217, 54, 58, 124, 99, 94}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 59}, {{186, 117, 252, 0, 0, 0, 56, 205, 146, 20, 190, 38, 41, 57, 22, 46}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 246, 223, 94, 17, 186, 106}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 59}, {{186, 117, 252, 0, 5, 7, 6, 80, 35, 60, 160, 8, 223, 173, 157, 201}, 59}, {{186, 117, 252, 0, 0, 141, 39, 237, 53, 135, 158, 5, 246, 248, 49, 36}, 59}, {{186, 117, 252, 0, 0, 0, 212, 158, 165, 52, 232, 56, 168, 31, 22, 103}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 179, 98, 70}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 59}, {{186, 117, 252, 0, 0, 68, 89, 4, 246, 31, 136, 137, 250, 186, 182, 99}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 239, 39, 240, 187, 238, 172}, 59}, {{186, 117, 252, 0, 0, 0, 151, 33, 116, 98, 173, 248, 170, 177, 208, 126}, 59}, {{186, 117, 252, 0, 0, 118, 148, 168, 208, 5, 106, 16, 32, 148, 96, 158}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 97, 114, 58}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 100, 117, 102}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 118, 125, 14, 119, 0, 218}, 59}, {{186, 117, 252, 0, 0, 0, 0, 179, 225, 180, 131, 213, 151, 6, 153, 125}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 47, 129, 63, 71, 248, 34, 77, 30}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 53, 176, 187, 4, 89, 168}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 177, 213, 19, 97, 123, 179, 242}, 59}, {{186, 117, 252, 0, 0, 0, 0, 112, 109, 237, 225, 66, 229, 12, 248, 108}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 62, 71, 249}, 59}, {{186, 117, 252, 0, 0, 0, 0, 21, 36, 55, 73, 141, 129, 209, 199, 158}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 85, 244, 103, 201, 50}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 212, 155}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 105, 43, 150, 69, 254, 132}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 154, 165}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 97, 83, 127, 255, 104}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 71, 112, 218}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 29}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 78, 64, 187, 68, 211}, 59}, {{186, 117, 252, 0, 0, 0, 0, 210, 155, 176, 24, 126, 124, 151, 227, 122}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 231, 183, 80, 192, 208, 155, 168}, 59}, {{186, 117, 252, 0, 0, 0, 0, 220, 79, 142, 10, 197, 35, 226, 229, 104}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 182, 170, 157, 177, 60, 60, 104}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 210, 88, 149, 152, 195, 16, 206, 185}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 100, 187}, 59}, {{186, 117, 252, 0, 0, 0, 0, 78, 232, 49, 20, 0, 236, 100, 52, 111}, 59}, {{186, 117, 252, 0, 0, 0, 238, 226, 165, 250, 46, 159, 20, 189, 95, 7}, 59}, {{186, 117, 252, 0, 0, 10, 222, 190, 231, 45, 242, 97, 10, 130, 224, 13}, 59}, {{186, 117, 252, 0, 0, 89, 247, 38, 245, 211, 26, 180, 201, 253, 199, 209}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 31}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 54}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 186, 208, 225}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 34, 96, 49, 62, 133, 248}, 59}, {{186, 117, 252, 0, 0, 0, 0, 241, 252, 13, 142, 63, 16, 55, 168, 32}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 59}, {{186, 117, 252, 0, 0, 0, 26, 161, 73, 75, 128, 236, 89, 219, 236, 236}, 59}, {{186, 117, 252, 0, 0, 0, 94, 222, 78, 85, 99, 94, 121, 57, 116, 128}, 59}, {{186, 117, 252, 0, 0, 0, 0, 126, 254, 227, 38, 14, 35, 109, 255, 66}, 59}, {{186, 117, 252, 104, 139, 40, 86, 65, 28, 147, 177, 195, 240, 1, 231, 162}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 61, 223, 254, 119, 75}, 59}, {{186, 117, 252, 0, 138, 124, 42, 11, 92, 216, 230, 234, 88, 105, 168, 179}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 236, 117, 239}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 204, 131, 76, 181, 111, 2}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 77, 47}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 200, 62, 116, 179, 241, 84, 118, 9}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 168, 191, 159}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 19, 204}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 0, 214, 208, 6, 116, 60, 255, 94, 120, 255, 95, 150, 20}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 94, 182, 213, 29, 45, 45, 46}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 42, 113}, 59}, {{186, 117, 252, 0, 185, 152, 29, 172, 173, 82, 249, 122, 139, 229, 222, 252}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 4, 129, 29, 215, 146, 103, 100, 177}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 98, 49}, 59}, {{186, 117, 252, 0, 0, 0, 0, 83, 190, 188, 236, 73, 174, 180, 40, 18}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 62, 200, 95, 187, 102, 20, 122, 243, 53, 206, 141, 153, 76}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 120, 37, 228, 154, 234, 128}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 245, 171, 170, 195, 7, 29, 161, 142}, 59}, {{186, 117, 252, 0, 222, 50, 211, 171, 44, 217, 145, 181, 189, 243, 242, 65}, 59}, {{186, 117, 252, 0, 0, 131, 161, 158, 47, 253, 108, 231, 7, 1, 225, 251}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 213, 181, 67}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 137, 213}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 205, 172, 56, 92, 244}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 58, 186}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 58, 201, 104, 191, 136, 65, 124, 188}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 236, 141, 109, 146, 95, 4, 73, 253}, 59}, {{186, 117, 252, 0, 0, 120, 245, 52, 188, 75, 145, 156, 223, 154, 165, 175}, 59}, {{186, 117, 252, 0, 149, 52, 175, 43, 55, 97, 34, 126, 46, 238, 199, 230}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 198, 233}, 59}, {{186, 117, 252, 0, 0, 0, 0, 0, 216, 180, 141, 13, 128, 70, 3, 196}, 59}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 15, 210, 150, 85}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 70, 189, 50, 237, 0, 250}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 146, 133, 232}, 96}, {{243, 119, 54, 16, 128, 0, 180, 164, 131, 31, 32, 7, 124, 108, 225, 201}, 96}, {{243, 119, 54, 16, 128, 0, 0, 98, 143, 211, 87, 203, 213, 237, 118, 57}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 253, 18, 235, 58, 93}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 248, 197, 191, 60, 6}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 247, 211, 247, 231, 138}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 162, 42, 202}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 75, 62, 109, 228, 194, 56, 15, 233, 242, 118}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 75}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 24, 117, 238, 115, 186, 58, 8}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 234}, 96}, {{243, 119, 54, 16, 128, 18, 238, 60, 166, 229, 162, 45, 184, 75, 98, 21}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 217, 155, 163, 46, 23}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 213, 216, 87, 142, 239, 254}, 96}, {{243, 119, 54, 16, 128, 235, 184, 189, 251, 117, 165, 160, 243, 142, 253, 25}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 86}, 96}, {{243, 119, 54, 16, 128, 0, 30, 4, 17, 39, 169, 142, 134, 138, 105, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 163, 184, 117, 34, 137}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 7, 173, 76, 109, 23, 192, 83}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 101}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 162}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 254, 26, 119, 23, 189, 79}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 188, 56, 229, 190, 32}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 237, 231, 145, 14, 248, 223, 91}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 117, 182, 163}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 231, 37, 182, 97, 145, 232, 2}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 148}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 185, 209, 217, 2}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 85, 61, 222}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 1, 58, 195, 107, 78}, 96}, {{243, 119, 54, 16, 128, 87, 173, 42, 183, 119, 51, 41, 167, 231, 151, 192}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 52, 11, 117}, 96}, {{243, 119, 54, 16, 128, 0, 0, 29, 242, 65, 174, 208, 165, 204, 156, 47}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 144, 69, 1}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 65, 192, 40, 120, 194, 126, 86, 138, 133}, 96}, {{243, 119, 54, 16, 128, 0, 229, 228, 73, 191, 147, 235, 222, 212, 187, 24}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 227, 214, 78, 119, 30, 126, 213}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 159, 100, 64, 199, 151, 167, 122, 235}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 5, 188, 218, 30}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 32, 152, 75, 95, 150, 98, 118}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 137, 38, 206, 126, 238, 115}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 176, 45, 51, 216, 211}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 206, 195, 139, 196, 119, 73, 152, 244}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 25, 138, 232, 21, 214, 186, 194}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 179, 16, 236, 51, 17}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 173, 214, 99, 162, 58, 168}, 96}, {{243, 119, 54, 16, 128, 0, 0, 199, 206, 250, 179, 183, 104, 1, 75, 8}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 198, 125, 168}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 49, 75, 133, 68, 237}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 150, 172, 119, 158, 41}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 108}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 180, 92, 26, 134}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 130, 219, 155, 176, 76, 203}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 101, 206, 148, 150}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 240, 59, 73, 190, 188, 228}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 131, 60, 155, 254, 105}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 115, 137, 178, 101, 114, 191, 128, 151}, 96}, {{243, 119, 54, 16, 128, 0, 0, 31, 228, 56, 237, 153, 9, 37, 48, 209}, 96}, {{243, 119, 54, 16, 128, 0, 16, 112, 14, 83, 106, 221, 244, 101, 201, 10}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 227, 203, 128, 103, 139, 60}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 233, 126, 86}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 120, 213, 208}, 96}, {{243, 119, 54, 16, 128, 0, 0, 236, 211, 94, 1, 20, 0, 225, 40, 227}, 96}, {{243, 119, 54, 16, 128, 244, 21, 185, 213, 113, 30, 10, 69, 140, 214, 253}, 96}, {{243, 119, 54, 16, 128, 0, 146, 58, 244, 220, 9, 29, 189, 64, 83, 160}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 16}, 96}, {{243, 119, 54, 16, 128, 0, 0, 168, 9, 164, 152, 234, 204, 94, 60, 69}, 96}, {{243, 119, 54, 16, 128, 0, 0, 249, 183, 76, 55, 222, 176, 76, 75, 95}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 166, 87, 31, 188}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 127, 178, 213, 3, 182}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 151, 61, 238, 206}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 135, 240, 157, 44, 141, 233}, 96}, {{243, 119, 54, 16, 128, 0, 0, 203, 209, 255, 99, 107, 173, 195, 110, 223}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 255, 42, 217, 117, 112, 97, 113, 78}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 223, 13, 255, 27, 52}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 151, 81, 223, 99, 159, 120, 118, 198}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 151, 232, 213, 66, 51}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 158, 21, 64}, 96}, {{243, 119, 54, 16, 128, 0, 0, 183, 25, 80, 13, 71, 82, 214, 157, 171}, 96}, {{243, 119, 54, 16, 128, 0, 0, 171, 169, 32, 77, 48, 132, 119, 75, 111}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 133, 188, 80}, 96}, {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 96}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 40, 189, 197}, 208}, {{160, 0, 0, 146, 167, 224, 164, 218, 36, 84, 87, 132, 67, 117, 208, 71}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 230, 39, 21, 15, 10, 109, 239}, 208}, {{160, 0, 0, 0, 0, 0, 108, 20, 239, 212, 207, 157, 229, 34, 181, 112}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 2, 83, 189, 59, 140}, 208}, {{160, 0, 0, 12, 11, 113, 74, 81, 132, 36, 193, 165, 193, 51, 19, 150}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 70, 110, 196, 166, 234}, 208}, {{160, 0, 252, 140, 210, 46, 14, 140, 184, 97, 238, 48, 66, 11, 70, 111}, 208}, {{160, 0, 0, 0, 0, 8, 124, 142, 238, 26, 141, 200, 222, 175, 100, 226}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 2}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 85, 48, 216, 25, 55, 206, 62, 243, 85, 123, 50, 148}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 112, 96}, 208}, {{160, 0, 79, 252, 45, 203, 188, 249, 56, 165, 218, 41, 43, 12, 233, 223}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 78}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 38, 103}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 171, 222}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 203}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 137}, 208}, {{160, 0, 150, 214, 39, 86, 145, 128, 6, 175, 94, 143, 6, 129, 122, 180}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 137, 5, 120}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 208}, {{160, 0, 0, 0, 98, 10, 205, 207, 86, 209, 85, 61, 17, 216, 228, 189}, 208}, {{160, 0, 0, 0, 0, 0, 82, 179, 34, 161, 103, 250, 229, 13, 160, 11}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 98, 196, 181, 87, 1}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 170, 109, 182, 21}, 208}, {{160, 0, 41, 10, 58, 242, 99, 193, 158, 216, 23, 152, 243, 64, 24, 172}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 226, 246, 233, 68, 3}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 215, 36}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 117, 63, 170}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 252, 243, 116, 162}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 51, 101, 34, 227, 248, 203, 115, 162}, 208}, {{160, 0, 0, 140, 235, 68, 134, 105, 53, 88, 120, 158, 171, 148, 43, 109}, 208}, {{160, 0, 0, 0, 0, 0, 0, 87, 196, 250, 157, 153, 216, 155, 109, 176}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 171, 184, 240, 70}, 208}, {{160, 0, 0, 97, 130, 0, 0, 198, 66, 63, 23, 18, 99, 69, 36, 102}, 208}, {{160, 0, 0, 0, 222, 71, 64, 92, 62, 217, 161, 86, 121, 151, 169, 179}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 208}, {{160, 121, 80, 190, 218, 105, 88, 65, 211, 1, 136, 74, 83, 89, 52, 209}, 208}, {{160, 0, 0, 144, 179, 125, 231, 55, 102, 177, 35, 201, 211, 186, 23, 138}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 111, 51, 75, 123}, 208}, {{160, 0, 0, 0, 202, 63, 84, 158, 112, 135, 5, 119, 213, 188, 157, 117}, 208}, {{160, 0, 0, 0, 0, 0, 177, 129, 76, 144, 25, 164, 226, 120, 159, 233}, 208}, {{160, 0, 0, 172, 0, 181, 166, 38, 96, 252, 53, 145, 102, 213, 226, 174}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 28, 169, 50, 248, 54, 162, 81, 125, 36, 52}, 208}, {{160, 0, 0, 222, 160, 207, 163, 193, 83, 153, 149, 230, 83, 64, 110, 231}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 9}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 28, 142, 160, 153, 224, 67, 215}, 208}, {{160, 0, 0, 0, 210, 237, 74, 239, 223, 192, 253, 60, 40, 14, 76, 88}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 83, 114, 105, 55, 74, 47, 236, 6}, 208}, {{160, 0, 0, 0, 0, 0, 0, 98, 119, 236, 18, 199, 168, 179, 147, 209}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 7}, 208}, {{160, 0, 0, 0, 0, 0, 93, 71, 43, 190, 111, 2, 111, 113, 150, 105}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 148}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 214, 182, 232, 195, 158, 87, 203}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 123, 163, 251, 1, 9}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 50, 86}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 62, 4, 165, 113, 205, 117, 187}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 99, 222, 105, 32, 57, 5, 203}, 208}, {{160, 0, 0, 0, 0, 0, 76, 135, 231, 149, 42, 28, 69, 192, 200, 14}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 189, 133, 165, 88, 41, 207, 226}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 248, 122, 249, 70, 42, 246, 255, 43, 87, 89, 154, 7}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 33, 83, 143, 170}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 61, 124, 222, 28, 159, 107, 246, 217}, 208}, {{160, 0, 0, 0, 0, 0, 253, 1, 189, 63, 249, 51, 197, 209, 98, 202}, 208}, {{160, 0, 0, 203, 45, 178, 47, 45, 205, 109, 165, 24, 113, 117, 152, 13}, 208}, {{160, 0, 0, 255, 129, 161, 103, 36, 186, 71, 211, 251, 7, 118, 78, 147}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 164, 117}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 218, 227}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 118, 47, 223, 197}, 208}, {{160, 0, 0, 0, 182, 36, 36, 92, 131, 129, 92, 65, 84, 188, 229, 213}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 184, 168, 199, 195, 58, 215, 144, 70}, 208}, {{160, 0, 0, 0, 0, 247, 94, 197, 47, 221, 74, 181, 64, 196, 184, 49}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 18, 196}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 9}, 208}, {{160, 0, 0, 0, 0, 0, 0, 76, 161, 144, 127, 160, 193, 203, 28, 142}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 140, 181, 214, 242, 68}, 208}, {{160, 0, 18, 27, 142, 162, 159, 202, 176, 79, 44, 228, 37, 101, 78, 128}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 38, 32}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 79, 31}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 208}, {{160, 0, 0, 0, 191, 133, 43, 188, 193, 255, 192, 156, 195, 61, 132, 163}, 208}, {{160, 0, 0, 0, 0, 0, 41, 167, 45, 179, 105, 137, 158, 16, 188, 2}, 208}, {{160, 0, 0, 72, 120, 26, 39, 77, 60, 206, 109, 150, 4, 222, 163, 52}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 109}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 237, 97, 14, 121, 60}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 59, 1, 128}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 87, 33, 144, 131, 95}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 157}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 44}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 119}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 51}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 122}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 225}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 131}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 67}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 43, 108}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 117, 41}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 237}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 4, 142}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 223}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 71}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 225}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 241}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 76}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 53}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 133}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 18}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 67}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 244}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 200}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 135}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 216}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 237, 246}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 113}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 44}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 154}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 181}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 40}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 200}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 34}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 173}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 68, 109}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 250}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 2}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 43}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 226}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 245}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 46}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 192}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 35}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 174, 57}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 160}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 243, 116}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 207}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 147}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 57, 235}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 197}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 194}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 137}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 56}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 116}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 218}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 66, 90}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 112}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 19}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 160}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 226}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 97}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 168}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 92}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 226}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 104}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 122}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 30}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 140}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 126}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 178}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 35}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 176}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 6}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 165}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 79}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 16}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 58}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 44, 126}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 200}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 230}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 34}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 185}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 68}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 104}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 33}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 162, 1}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 6}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 83, 55}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 135}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 144}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 27}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 21, 1}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 121}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 119, 148}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 19}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 108}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 118}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 139, 132}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 138}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 146}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 213}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 218}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 245}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 98}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 148}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 214}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 234}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 180, 64, 162}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 145, 78, 255, 180}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 248, 223, 82}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 75, 161, 84}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 29, 190, 210, 44, 91}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 147, 134, 169, 119, 195, 134, 97}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 107, 149, 86, 65, 237, 243}, 199}, {{41, 215, 84, 136, 234, 0, 229, 3, 208, 15, 166, 31, 66, 130, 188, 115}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 217, 1, 75, 22}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 114, 97, 244, 171, 183, 137, 199, 195}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 77, 201, 24, 3, 132, 148, 227}, 199}, {{41, 215, 84, 136, 234, 0, 0, 87, 91, 167, 242, 51, 175, 254, 245, 134}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 233, 216, 229, 107, 137, 114, 72}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 109, 124, 214, 237, 4, 191}, 199}, {{41, 215, 84, 136, 234, 0, 11, 38, 255, 197, 252, 92, 251, 44, 142, 32}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 168, 1, 137, 174, 67, 125, 15, 156, 224}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 166, 174, 207, 238}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 116, 184, 32, 226, 90, 118}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 208}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 64, 157, 57, 3, 103, 164, 236, 118}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 52, 37, 67, 8}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 207, 211, 47, 177, 209, 56, 69, 154}, 199}, {{41, 215, 84, 136, 234, 0, 0, 126, 77, 93, 152, 168, 196, 17, 13, 214}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 10, 35, 235, 152, 126, 73, 33, 186}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 182, 139, 208, 240, 162, 21, 230, 235}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 142}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 69, 90, 161, 112, 135, 247, 8}, 199}, {{41, 215, 84, 136, 234, 0, 0, 124, 217, 99, 246, 58, 169, 116, 152, 112}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 220, 115, 30, 64, 19, 104, 10}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 199}, {{41, 215, 84, 136, 234, 0, 0, 157, 9, 127, 167, 238, 37, 244, 51, 99}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 37, 48, 215}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 100, 188, 129, 157, 226, 168, 173}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 48, 171, 251, 57, 164}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 94, 138, 170, 205, 131}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 104, 171, 165, 160, 211}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 103, 26, 112, 65, 54}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 2, 48, 220, 51, 169, 40, 89}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 30, 11, 10, 170, 110, 42, 195}, 199}, {{41, 215, 84, 136, 234, 0, 0, 241, 140, 140, 9, 160, 45, 236, 236, 53}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 189, 108, 53, 69, 245}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 234, 121, 160, 132, 26, 243, 192}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 253, 168, 109, 129, 215, 44, 65, 244}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 254, 199, 72, 236, 103, 85, 161}, 199}, {{41, 215, 84, 136, 234, 0, 0, 130, 138, 158, 7, 187, 194, 125, 204, 224}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 171}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 119, 133, 3}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 164, 185, 142, 139, 14}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 249}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 89, 29, 31}, 199}, {{41, 215, 84, 136, 234, 0, 27, 178, 159, 137, 29, 24, 88, 153, 117, 67}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 158, 50, 166, 185, 64}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 83, 103, 186, 229, 189}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 101}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 109, 152, 152, 131, 109, 231}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 191, 199, 29, 101, 162, 106, 144}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 160, 233, 47, 71, 135, 24, 77}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 240}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 3, 2, 234, 189, 122, 246, 154, 38}, 199}, {{41, 215, 84, 136, 234, 0, 4, 235, 162, 94, 172, 172, 67, 111, 181, 112}, 199}, {{41, 215, 84, 136, 234, 0, 0, 100, 203, 109, 67, 31, 172, 157, 197, 43}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 226, 12, 15, 172, 218, 155}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 55, 90, 117, 155, 245, 75, 22}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 93, 126, 108, 198, 208}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 239, 38, 28, 97, 227, 238}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 242, 227, 181, 130, 215, 20, 132}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 74, 166, 173, 56, 102, 231}, 199}, {{41, 215, 84, 136, 234, 0, 0, 249, 203, 167, 82, 100, 8, 15, 121, 126}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 199}, {{41, 215, 84, 136, 234, 0, 71, 84, 103, 227, 17, 124, 23, 220, 238, 117}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 109, 22, 168}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 221, 23, 43, 127, 90, 202}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 203, 110, 154, 218, 118, 139, 34, 68}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 22, 14, 58, 215, 218, 173, 65}, 199}, {{41, 215, 84, 136, 234, 0, 0, 9, 217, 150, 206, 172, 139, 121, 60, 8}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 123, 36, 149, 104, 205, 64, 19}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 3, 188, 24}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 197}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 99, 33, 193, 2}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 49}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 88, 66, 144, 23, 30, 30, 80, 58}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 243}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 9}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 174, 62, 208, 92, 219}, 199}, {{41, 215, 84, 136, 234, 0, 0, 0, 144, 200, 169, 20, 111, 63, 154, 28}, 199}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 195, 189}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 219, 6, 110, 119}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 62, 235, 142, 32, 221}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 34, 146, 146, 159}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 81, 25}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 8}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 183, 130, 200, 10}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 131, 232, 71, 55, 189, 109, 235}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 60, 154, 220, 233, 150, 127, 171}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 193, 214, 152, 241, 239}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 43, 186, 127, 165, 160}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 112, 111}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 77, 197, 17, 2, 226}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 115, 1, 105, 140, 53, 177}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 188, 94, 160, 224, 69, 84}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 162}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 127, 243, 194, 31, 205}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 197}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 199}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 141, 198, 146, 86}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 253, 80, 232, 14}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 213, 14}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 39, 242}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 77, 233, 3, 30}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 247, 229, 24, 239}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 166, 2}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 104, 117, 32}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 219, 10, 10}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 200, 187, 224, 99, 145}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 21, 69, 124, 17}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 91, 128, 165, 88}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 39, 155}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 154}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 98, 93, 4, 52, 160}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 211, 181, 219}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 84, 159, 67, 68, 210, 142}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 48, 177, 216, 245}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 186, 24, 185, 120}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 138, 10, 214, 131, 73, 247, 88}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 250, 142, 210, 220}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 121}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 188, 135}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 70, 203, 87, 33}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 128, 86, 175, 153}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 154, 7, 173, 74, 136, 139}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 167, 151, 18, 175, 17}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 90, 112, 227, 201, 12}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 6, 110, 98, 166, 3, 95}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 53, 244, 127, 88}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 98, 76, 190, 143, 160, 63}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 238, 128, 145, 142, 71, 148}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 219, 39, 199}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 226, 138, 211}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 222, 229, 58, 247}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 245, 190, 186, 77}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 17, 208, 163, 198, 182, 242, 22}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 43, 181, 212, 11}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 46}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 174}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 249, 0, 234}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 142, 248}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 126, 45}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 243, 30, 102, 248, 130, 46}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 200, 23, 14, 17}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 34, 111, 101, 117, 168, 252, 207}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 224, 171, 250, 118}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 218, 110}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 41}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 62, 34, 40, 82, 175}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 47, 70, 22, 13, 9}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 187, 88, 208, 29, 165}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 240, 51, 67, 170}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 65}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 125, 21, 206, 84}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 136, 7, 89}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 253, 129, 111, 98, 223, 180}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 249, 146}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 198, 53, 62, 21, 31}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 23}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 247, 119, 189, 155, 219}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 252, 102, 156, 118, 162}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 192, 66}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 246, 222, 168, 227, 26, 99}, 191}, {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 241}, 191}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 115, 65, 180, 0, 142}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 212, 82, 133}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 57}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 89, 13, 230}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 39, 31, 174, 61, 25}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 81, 74, 221}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 116, 72, 13}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 12, 97, 17, 196, 29, 53}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 232}, 235}, {{113, 31, 181, 245, 21, 0, 0, 223, 114, 193, 33, 100, 25, 152, 194, 157}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 216, 23, 164, 110}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 196, 100, 4, 179, 57, 192}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 61, 149, 247, 165, 220, 242, 186}, 235}, {{113, 31, 181, 245, 21, 0, 0, 15, 135, 232, 200, 161, 119, 48, 51, 59}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 94, 56, 9, 106}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 238, 4, 117, 178, 99}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 85, 222, 198, 231, 122, 227, 39, 44}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 49, 51, 233, 224, 54}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 133, 190, 118, 96}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 108, 186, 2, 40, 71, 33, 146, 80, 147}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 135, 42, 37, 142, 207, 191, 16, 25}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 109, 21, 30, 23, 119, 205, 131}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 122, 56, 187, 215, 10, 5, 108, 181, 12, 133}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 183, 43, 100, 107}, 235}, {{113, 31, 181, 245, 21, 0, 0, 93, 222, 122, 77, 167, 11, 22, 71, 84}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 238, 217, 90, 130, 193, 37, 15, 52}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 233, 195, 235, 42, 206}, 235}, {{113, 31, 181, 245, 21, 0, 0, 4, 100, 115, 242, 242, 108, 134, 53, 142}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 94, 147, 103, 112}, 235}, {{113, 31, 181, 245, 21, 0, 1, 128, 100, 29, 130, 62, 156, 18, 19, 91}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 76, 43, 244}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 192, 144, 175, 97, 124}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 151}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 10, 91, 248, 238, 190, 12, 43, 132}, 235}, {{113, 31, 181, 245, 21, 0, 1, 227, 214, 13, 60, 144, 115, 179, 25, 114}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 63, 209, 230, 88, 128, 189}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 67, 194, 43, 27, 12, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 141, 75, 67, 213, 143, 230}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 51, 118, 146, 12}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 88}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 219, 255, 85, 237, 49, 209, 37, 150}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 117, 10, 70, 234, 33}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 8, 82, 161, 248}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 217, 245, 61, 65, 49}, 235}, {{113, 31, 181, 245, 21, 0, 99, 132, 151, 248, 47, 157, 230, 182, 65, 26}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 29, 142, 133, 168, 22, 146, 150, 92}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 163, 40, 250}, 235}, {{113, 31, 181, 245, 21, 0, 217, 19, 203, 59, 129, 106, 196, 209, 230, 42}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 214, 161, 173, 119, 163, 137, 244}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 154, 18, 85, 46, 92, 132}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 173, 244, 236}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 175, 24, 225, 49, 146}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 157, 121, 192}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 121, 185, 200, 131, 249, 208, 48, 56}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 19, 3, 213, 108, 32, 202, 118}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 30}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 107, 186, 213, 164, 6, 235}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 244}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 187, 210, 213, 72, 49, 237, 228, 32}, 235}, {{113, 31, 181, 245, 21, 0, 195, 215, 243, 202, 211, 224, 35, 95, 69, 79}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 186, 26, 100, 69}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 58, 157, 64, 199, 88, 76, 229}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 106, 70, 241, 57}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 216, 201, 31, 86, 26, 75, 97}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 216, 214, 179}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 208, 154, 60, 68, 251, 251, 51, 228, 181}, 235}, {{113, 31, 181, 245, 21, 0, 11, 112, 181, 201, 198, 142, 139, 159, 56, 38}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 172, 23, 194, 143, 124, 48, 243, 87}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 39, 142, 216, 33, 39}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 37, 121, 161}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 127, 48, 254, 61, 99}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 42, 56, 0, 112, 34, 216}, 235}, {{113, 31, 181, 245, 21, 0, 163, 254, 178, 120, 92, 87, 204, 96, 74, 84}, 235}, {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 68, 4, 230}, 235}, {{113, 31, 181, 245, 21, 0, 0, 9, 233, 233, 55, 132, 104, 8, 110, 238}, 235}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 164, 150, 224}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 15}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 103, 74, 141, 110, 166, 212, 147, 9}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 45}, {{181, 216, 192, 248, 184, 220, 230, 6, 134, 208, 169, 127, 80, 209, 54, 138}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 156, 153, 161}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 162, 225, 70}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 54, 215, 226, 45, 200, 140, 252}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 242, 20, 53, 219, 45}, 45}, {{181, 216, 192, 0, 0, 211, 100, 54, 208, 223, 212, 220, 111, 198, 55, 207}, 45}, {{181, 216, 192, 0, 0, 0, 122, 44, 210, 225, 37, 55, 75, 62, 145, 200}, 45}, {{181, 216, 192, 0, 0, 0, 0, 53, 137, 203, 40, 200, 98, 191, 140, 70}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 205, 3, 46, 207, 51, 74}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 172, 128, 64}, 45}, {{181, 216, 192, 88, 94, 243, 239, 15, 134, 84, 66, 93, 162, 237, 183, 105}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 162, 234, 249, 210, 133}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 200}, 45}, {{181, 216, 192, 0, 0, 240, 166, 0, 152, 178, 16, 99, 219, 235, 251, 240}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 223, 252, 226, 114, 82, 237}, 45}, {{181, 216, 192, 0, 125, 33, 100, 164, 218, 120, 186, 219, 64, 206, 209, 211}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 227, 149, 179}, 45}, {{181, 216, 192, 0, 0, 4, 222, 29, 203, 189, 174, 55, 162, 27, 97, 34}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 9, 42, 77, 119, 202, 76}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 132, 102, 5, 37, 23, 150, 151}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 151, 22, 36, 126, 4, 102}, 45}, {{181, 216, 192, 198, 81, 30, 90, 85, 22, 58, 211, 139, 95, 198, 103, 195}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 66, 230, 115, 6, 51, 48, 45, 123, 110, 12}, 45}, {{181, 216, 192, 0, 0, 0, 144, 46, 79, 157, 131, 60, 252, 18, 41, 185}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 75, 104, 82}, 45}, {{181, 216, 192, 0, 0, 0, 72, 161, 87, 115, 127, 27, 206, 12, 13, 56}, 45}, {{181, 216, 192, 0, 183, 1, 100, 20, 144, 246, 161, 141, 121, 51, 148, 240}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 45}, {{181, 216, 192, 0, 23, 253, 129, 91, 73, 210, 223, 167, 30, 227, 184, 193}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 17, 10, 13, 243, 156, 242}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 127, 52, 240, 35, 20, 238}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 153, 40, 241, 70, 136, 195, 144, 30}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 159, 172, 188, 48, 144}, 45}, {{181, 216, 192, 0, 0, 0, 0, 147, 36, 200, 29, 106, 53, 93, 218, 202}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 94, 161, 248, 111, 145}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 192, 139, 238, 103, 240, 164}, 45}, {{181, 216, 192, 0, 0, 153, 15, 5, 221, 208, 85, 83, 66, 200, 159, 118}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 77, 18}, 45}, {{181, 216, 192, 0, 0, 22, 141, 193, 84, 177, 145, 98, 131, 101, 82, 56}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 47, 209, 28, 220, 128, 223}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 164, 196, 22, 252, 146, 14, 82, 195}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 253, 183, 56, 98, 98, 167, 102}, 45}, {{181, 216, 192, 0, 0, 0, 138, 72, 242, 24, 68, 34, 31, 202, 233, 53}, 45}, {{181, 216, 192, 0, 0, 0, 0, 110, 228, 108, 62, 6, 236, 130, 5, 243}, 45}, {{181, 216, 192, 0, 0, 34, 232, 69, 123, 153, 241, 73, 238, 87, 112, 57}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 95, 226, 75, 238, 199, 200}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 245, 212, 115, 17, 139, 245}, 45}, {{181, 216, 192, 0, 0, 0, 147, 191, 185, 70, 148, 63, 206, 25, 55, 14}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 181}, 45}, {{181, 216, 192, 0, 29, 30, 130, 204, 228, 129, 46, 142, 189, 199, 176, 233}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 35, 234, 48, 228, 94, 14}, 45}, {{181, 216, 192, 0, 12, 137, 71, 98, 232, 237, 190, 123, 157, 130, 58, 175}, 45}, {{181, 216, 192, 139, 138, 238, 128, 190, 27, 153, 36, 198, 206, 104, 183, 65}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 203, 242, 150, 192, 72, 109, 228}, 45}, {{181, 216, 192, 0, 0, 128, 55, 181, 243, 253, 175, 32, 37, 152, 209, 151}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 88, 49, 9, 213, 67, 192, 69, 35}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 45}, {{181, 216, 192, 0, 0, 0, 0, 141, 224, 10, 128, 49, 113, 236, 58, 237}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 184, 149, 230}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 58}, 45}, {{181, 216, 192, 0, 0, 63, 3, 128, 91, 107, 4, 212, 198, 19, 142, 224}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 245}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 30, 74}, 45}, {{181, 216, 192, 0, 78, 204, 95, 31, 52, 222, 98, 30, 173, 177, 201, 208}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 253, 165, 60, 17, 255}, 45}, {{181, 216, 192, 0, 0, 0, 118, 150, 229, 27, 17, 203, 39, 42, 221, 76}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 242, 84, 39, 67, 50, 201, 205}, 45}, {{181, 216, 192, 0, 244, 96, 146, 111, 26, 19, 201, 79, 183, 243, 40, 179}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 135, 255}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 224, 36, 84, 52, 255}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 27, 38, 117, 108, 57, 133}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 237, 42, 225}, 45}, {{181, 216, 192, 113, 213, 207, 3, 115, 234, 41, 97, 215, 144, 219, 49, 168}, 45}, {{181, 216, 192, 0, 0, 20, 189, 34, 252, 108, 195, 106, 35, 145, 52, 150}, 45}, {{181, 216, 192, 0, 210, 228, 192, 61, 237, 45, 38, 174, 38, 206, 176, 18}, 45}, {{181, 216, 192, 0, 0, 0, 33, 1, 141, 90, 255, 222, 55, 122, 90, 151}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 199, 97, 125, 26, 193, 220, 79}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 55, 97}, 45}, {{181, 216, 192, 0, 0, 0, 0, 117, 2, 119, 143, 189, 163, 24, 104, 143}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 180, 43, 38, 76, 116, 133, 198}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 77, 102, 118, 214, 228, 113}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 148, 175}, 45}, {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 254, 36, 212, 80, 202, 163}, 45}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 255, 81, 222, 74, 93}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 89, 240, 139}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 152}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 151, 191}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 208, 32, 238, 244, 8, 194, 53}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 202, 155, 164, 70, 221}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 197, 47}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 231, 234, 232, 207, 86}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 40, 62, 235}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 237, 252, 107, 32}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 10, 54, 138, 236, 249, 42, 190}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 127, 177, 148, 180, 181}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 46}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 64, 54, 46, 166}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 8, 118, 63}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 28, 156, 99, 168, 5, 200, 172}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 52, 238}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 232, 136, 245, 76}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 210, 95, 94, 49, 4, 231}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 181, 224, 160, 182, 172}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 239, 52, 237, 46}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 208, 45, 236, 54, 209, 31}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 33, 63, 210}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 255, 137, 211}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 250}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 99, 24, 217, 5}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 184, 119, 226, 122}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 237, 24, 44, 36, 88}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 20, 181, 160, 147, 119, 249}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 99, 210, 205, 133, 54, 76, 225}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 194, 188, 42, 218, 94, 238, 246}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 70, 198, 51, 26, 237, 220}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 213, 127}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 116, 209, 255}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 204, 24, 87}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 181, 28, 247, 215, 101, 102, 243}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 181}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 247, 253, 70, 152}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 253}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 45, 228, 154, 48, 83, 172}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 88, 61, 15, 56, 241, 215}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 89}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 18, 83, 45}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 60}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 180, 56, 30, 183}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 37, 2, 140, 145, 240, 86}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 241, 144, 249}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 70, 95}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 238, 50, 5, 207, 215, 201, 128}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 138, 73, 223, 63, 241, 172, 221}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 33, 93, 207, 40, 87, 228}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 116, 115, 180, 172, 57, 40}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 57, 16, 75, 100, 120, 164}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 243, 108}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 50, 195, 118}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 192, 244, 1, 74}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 90, 180, 188, 225, 184, 233, 8}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 62, 99, 2}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 150, 234, 45, 89, 200, 124}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 156, 107, 84, 5, 192, 162}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 174, 43, 79, 211, 231, 170}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 61, 141, 78, 103, 1}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 21, 92, 86, 191, 58, 218}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 106}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 203, 152, 160}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 43, 105, 119, 203}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 159, 122, 225, 114, 5, 168}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 139, 45, 170, 110, 147, 16, 194}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 146, 247, 182}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 52}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 220, 188, 139, 231, 104}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 75, 132, 106, 60}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 13, 51, 210}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 107, 125}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 26, 220, 212, 137, 118, 24, 18}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 150, 104}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 53, 30, 74, 121, 240}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 244, 12, 217}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 15, 201, 138, 222, 180}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 129, 222}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 235, 107, 66, 0, 246, 177}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 39, 77}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 144, 102, 47, 155, 196}, 164}, {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 21, 94, 23}, 164}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 130}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 246}, 166}, {{136, 27, 192, 176, 53, 221, 221, 78, 179, 64, 73, 154, 146, 187, 238, 139}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 110, 132, 201, 54, 105, 159, 13, 51}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 249, 222, 13, 24, 165, 208, 237}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 166}, {{136, 27, 192, 85, 244, 100, 57, 83, 237, 237, 7, 75, 170, 124, 189, 130}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 74, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 170}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 237, 29, 223, 228, 0, 57, 8, 23}, 166}, {{136, 27, 192, 0, 0, 88, 41, 6, 142, 178, 137, 45, 82, 131, 89, 50}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 213, 255, 139, 155, 253}, 166}, {{136, 27, 192, 0, 0, 0, 141, 205, 8, 56, 20, 220, 132, 32, 247, 164}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 162, 151, 194, 216, 54, 228, 245, 43}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 218}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 83, 27, 35, 13, 215, 83, 45, 143, 183, 96, 173, 158}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 114, 83, 110, 177, 1}, 166}, {{136, 27, 192, 179, 197, 130, 166, 40, 43, 58, 204, 25, 228, 10, 175, 103}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 31, 24, 169, 119, 87}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 42, 41, 221, 236, 31, 135, 90, 54}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 117, 176}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 44}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 161, 96}, 166}, {{136, 27, 192, 0, 0, 139, 195, 177, 152, 219, 167, 145, 3, 114, 156, 65}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 177, 122}, 166}, {{136, 27, 192, 2, 162, 238, 180, 85, 236, 236, 150, 253, 159, 245, 29, 222}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 166}, {{136, 27, 192, 0, 0, 0, 131, 239, 38, 26, 134, 65, 36, 56, 208, 200}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 64, 154, 38, 63, 66}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 78, 188, 65, 7, 136, 254, 180, 224}, 166}, {{136, 27, 192, 0, 0, 0, 0, 192, 23, 177, 250, 158, 246, 152, 119, 121}, 166}, {{136, 27, 192, 0, 0, 201, 137, 154, 220, 196, 178, 188, 211, 185, 223, 55}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 180, 26}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 112, 22, 45, 116, 106, 45, 215, 172}, 166}, {{136, 27, 192, 0, 0, 0, 0, 41, 225, 116, 44, 255, 80, 5, 236, 32}, 166}, {{136, 27, 192, 0, 250, 117, 55, 6, 239, 78, 181, 110, 93, 52, 189, 247}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 85, 76, 54, 139, 25, 123, 163, 70}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 58, 27, 195}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 135, 131, 233, 223, 25, 254, 166, 248}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 137, 10, 83, 66, 35, 179}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 27, 177, 32, 254, 231, 79, 209}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 195, 80, 229, 249, 253, 19, 20, 154, 183, 124, 176}, 166}, {{136, 27, 192, 0, 0, 55, 173, 107, 15, 42, 238, 171, 192, 158, 34, 202}, 166}, {{136, 27, 192, 0, 0, 0, 0, 86, 153, 56, 137, 190, 45, 200, 55, 225}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 159}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 19, 127, 254, 24, 111, 222, 198, 58}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 108}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 56, 77, 213, 169, 12, 62, 29}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 56}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 206, 137}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 14, 57, 163, 49, 88}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 166}, {{136, 27, 192, 0, 0, 0, 0, 28, 110, 99, 159, 186, 149, 137, 119, 251}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 182, 169, 97, 88, 196}, 166}, {{136, 27, 192, 44, 208, 52, 32, 169, 137, 244, 174, 37, 115, 164, 139, 15}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 37, 196}, 166}, {{136, 27, 192, 190, 56, 244, 49, 64, 152, 105, 84, 29, 198, 32, 229, 36}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 18, 140}, 166}, {{136, 27, 192, 0, 163, 9, 162, 21, 166, 180, 97, 111, 102, 192, 207, 155}, 166}, {{136, 27, 192, 87, 0, 42, 6, 240, 185, 16, 54, 24, 201, 217, 62, 230}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 214, 196}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 200, 236, 25, 126, 243, 60}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 70}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 169, 246, 124, 151, 229, 23}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 190}, 166}, {{136, 27, 192, 0, 171, 234, 36, 187, 94, 57, 191, 98, 200, 26, 149, 34}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 198, 3, 68, 110, 114, 252, 99, 69}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 166}, {{136, 27, 192, 0, 0, 0, 0, 147, 48, 10, 41, 243, 163, 122, 62, 217}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 31}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 134, 98, 196}, 166}, {{136, 27, 192, 0, 0, 31, 220, 27, 216, 42, 66, 110, 230, 10, 246, 60}, 166}, {{136, 27, 192, 122, 247, 112, 36, 111, 207, 197, 53, 235, 28, 144, 17, 120}, 166}, {{136, 27, 192, 150, 118, 68, 186, 163, 208, 139, 173, 35, 153, 78, 56, 87}, 166}, {{136, 27, 192, 41, 218, 84, 37, 139, 88, 190, 104, 89, 12, 141, 248, 243}, 166}, {{136, 27, 192, 0, 0, 0, 0, 88, 215, 123, 33, 97, 154, 145, 190, 204}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 31, 153, 87, 168, 38, 42, 251, 237}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 146, 197, 62, 172, 189, 183, 241}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 166}, {{136, 27, 192, 0, 0, 156, 88, 177, 133, 49, 248, 189, 30, 61, 197, 81}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 108}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 166}, {{136, 27, 192, 0, 252, 26, 187, 232, 239, 246, 184, 166, 242, 37, 100, 48}, 166}, {{136, 27, 192, 0, 0, 0, 0, 189, 241, 147, 223, 34, 1, 212, 243, 254}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 44}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 210, 28}, 166}, {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 30, 29, 168, 97, 40}, 166}, {{136, 27, 192, 0, 0, 111, 199, 25, 52, 55, 82, 158, 138, 135, 122, 74}, 166}, {{136, 27, 192, 0, 0, 3, 139, 118, 163, 185, 22, 39, 14, 49, 7, 223}, 166}, {{136, 27, 192, 0, 0, 0, 225, 222, 153, 12, 45, 113, 4, 94, 8, 122}, 166}, {{2, 175, 111, 0, 147, 46, 33, 213, 255, 124, 54, 70, 248, 243, 187, 127}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 172, 195}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 45, 51}, 140}, {{2, 175, 111, 0, 0, 142, 209, 248, 150, 156, 128, 180, 0, 54, 43, 50}, 140}, {{2, 175, 111, 0, 0, 0, 194, 161, 162, 17, 66, 153, 156, 254, 75, 148}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 255}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 172, 36, 114, 173, 141, 230, 128, 50}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 218, 199, 129}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 140}, {{2, 175, 111, 0, 0, 0, 0, 176, 108, 203, 51, 25, 181, 249, 100, 135}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 125}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 88, 68, 192, 84, 185}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 227, 52, 9}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 171}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 203, 157, 211, 122, 208, 5, 76, 216}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 221, 208, 176, 229, 49, 89, 7}, 140}, {{2, 175, 111, 0, 0, 84, 25, 156, 163, 208, 51, 177, 166, 122, 227, 102}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 217}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 51, 237}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 216, 244, 124, 7, 19, 92, 209, 62}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 169}, 140}, {{2, 175, 111, 0, 0, 0, 0, 174, 91, 228, 45, 205, 127, 45, 170, 247}, 140}, {{2, 175, 111, 0, 15, 6, 20, 223, 24, 122, 100, 127, 228, 95, 104, 199}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 103, 162, 236}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 103, 179, 12, 109, 122, 4, 13, 106}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 135, 174, 119, 33, 187, 138, 175, 233, 166, 22, 197, 130}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 23, 147, 8, 162, 131}, 140}, {{2, 175, 111, 0, 59, 126, 55, 40, 180, 24, 159, 181, 235, 84, 91, 146}, 140}, {{2, 175, 111, 0, 0, 0, 0, 2, 93, 245, 197, 173, 70, 85, 107, 44}, 140}, {{2, 175, 111, 0, 174, 242, 169, 145, 201, 41, 41, 193, 212, 74, 57, 44}, 140}, {{2, 175, 111, 0, 0, 232, 101, 138, 176, 125, 156, 16, 63, 221, 179, 102}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 252, 255, 25, 12, 52, 196, 219, 65}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 99, 80, 66}, 140}, {{2, 175, 111, 0, 229, 114, 186, 227, 191, 119, 141, 244, 153, 162, 205, 89}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 149, 143, 7}, 140}, {{2, 175, 111, 0, 0, 0, 0, 160, 80, 119, 3, 161, 146, 121, 22, 84}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 72, 237, 238, 222, 226, 233, 153}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 182, 82, 138}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 45}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 232, 33, 165}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 218, 197}, 140}, {{2, 175, 111, 0, 0, 110, 154, 170, 9, 227, 166, 242, 147, 144, 185, 102}, 140}, {{2, 175, 111, 0, 182, 96, 86, 117, 81, 223, 67, 67, 163, 195, 156, 4}, 140}, {{2, 175, 111, 0, 0, 243, 19, 87, 160, 85, 226, 117, 135, 30, 200, 230}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 71}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 177, 153, 151, 92, 171}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 85}, 140}, {{2, 175, 111, 0, 0, 0, 0, 216, 128, 243, 129, 32, 97, 5, 23, 232}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 38, 47, 48, 88, 117, 108}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 202, 206, 226, 8, 43, 97, 215, 253, 5, 10, 154}, 140}, {{2, 175, 111, 0, 224, 41, 33, 223, 28, 177, 12, 114, 187, 131, 148, 169}, 140}, {{2, 175, 111, 0, 0, 0, 0, 233, 183, 50, 235, 80, 88, 227, 130, 133}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 154, 97}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 111}, 140}, {{2, 175, 111, 0, 0, 0, 225, 239, 112, 237, 92, 196, 205, 175, 60, 130}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 211}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 68, 150}, 140}, {{2, 175, 111, 0, 131, 18, 169, 12, 188, 226, 234, 202, 163, 183, 63, 160}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 31, 217, 153, 20, 160, 16, 27, 56}, 140}, {{2, 175, 111, 0, 0, 0, 32, 74, 15, 194, 98, 61, 199, 112, 208, 69}, 140}, {{2, 175, 111, 0, 0, 108, 9, 124, 109, 80, 204, 5, 222, 219, 170, 57}, 140}, {{2, 175, 111, 0, 0, 0, 0, 73, 114, 143, 100, 177, 196, 103, 46, 158}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 247, 199, 72, 49, 167, 136, 101, 122}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 213, 1, 86, 48, 24, 185, 129}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 100, 3, 136, 90, 12, 128}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 56, 125, 168, 60, 130, 35, 85, 153}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 236, 186, 73, 154, 69, 28, 253, 145}, 140}, {{2, 175, 111, 0, 56, 51, 65, 207, 140, 15, 27, 150, 216, 4, 141, 83}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 121, 207, 15, 223, 148, 221, 4, 242}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 128, 195, 24, 130, 209}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 14, 127, 94, 57, 67, 35}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 29, 3, 233}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 71, 85, 79, 185, 224, 101, 58, 242}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 182, 16, 150, 131, 119, 73}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 15, 34, 88, 117, 66, 182, 52, 198}, 140}, {{2, 175, 111, 0, 131, 227, 181, 187, 44, 40, 104, 229, 245, 17, 231, 147}, 140}, {{2, 175, 111, 0, 0, 214, 78, 197, 61, 68, 67, 241, 202, 103, 241, 152}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 248, 6, 153, 155, 230}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 180}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 59, 194, 113}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 252, 167, 48, 58, 142, 162, 234}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 159, 131, 102, 79, 227, 115, 147}, 140}, {{2, 175, 111, 0, 53, 145, 162, 83, 126, 21, 5, 221, 190, 68, 221, 140}, 140}, {{2, 175, 111, 0, 0, 0, 0, 2, 132, 37, 229, 77, 246, 100, 234, 8}, 140}, {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 207, 181, 20, 55, 96, 210}, 140}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 125}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 189}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 71}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 164}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 126}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 233}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 190}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 180}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 100}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 84}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 7}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 113}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 175}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 95}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 104}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 62}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 151}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 118}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 57}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 47}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 152}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 211}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 24}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 215}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 187}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 33}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 48}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 96}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 214, 74}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 220}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 111}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 89}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 211}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 246}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 225}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 219}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 177}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 17}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 133}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 147}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 63}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 179}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 138}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 173}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 197, 20}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 66}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 210}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 154}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 148}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 66}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 112}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 2}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 242}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 46}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 18}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 210}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 42}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 217}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 160}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 65}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 170}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 7}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 166}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 108, 63}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 148}, {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 181, 83}, 148}, {{96, 0, 0, 0, 0, 0, 209, 235, 108, 138, 14, 97, 150, 139, 48, 252}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 109}, {{96, 0, 230, 156, 18, 32, 218, 157, 116, 214, 33, 188, 227, 172, 73, 131}, 109}, {{96, 0, 0, 0, 0, 0, 0, 250, 183, 32, 152, 105, 147, 204, 18, 190}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 181, 172, 15}, 109}, {{96, 0, 0, 8, 177, 147, 63, 58, 87, 216, 253, 7, 232, 58, 12, 114}, 109}, {{96, 0, 0, 0, 0, 0, 211, 194, 238, 6, 0, 250, 102, 1, 193, 239}, 109}, {{96, 0, 0, 0, 0, 173, 145, 26, 173, 222, 131, 138, 248, 82, 123, 9}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 189, 230, 30, 208, 84, 228, 31, 39}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 99, 149}, 109}, {{96, 225, 244, 121, 150, 207, 40, 110, 236, 99, 136, 150, 241, 170, 26, 103}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 64, 255, 217}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 35, 162, 235, 234, 192, 110, 190, 27}, 109}, {{96, 0, 0, 0, 0, 0, 172, 208, 61, 91, 35, 116, 16, 92, 211, 90}, 109}, {{96, 0, 0, 26, 25, 100, 219, 46, 76, 2, 234, 250, 68, 101, 69, 102}, 109}, {{96, 0, 0, 0, 0, 0, 135, 135, 164, 216, 250, 138, 167, 84, 82, 30}, 109}, {{96, 0, 0, 0, 0, 0, 0, 35, 60, 25, 17, 251, 157, 112, 233, 86}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 13, 216}, 109}, {{96, 85, 229, 145, 53, 174, 6, 59, 251, 66, 116, 192, 77, 130, 213, 153}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 173, 195, 218, 207, 120, 144, 5}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 29}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 46, 74, 103, 68, 31}, 109}, {{96, 0, 0, 0, 0, 2, 195, 138, 161, 27, 250, 143, 9, 153, 63, 233}, 109}, {{96, 0, 0, 0, 0, 0, 0, 207, 1, 81, 230, 246, 85, 24, 104, 185}, 109}, {{96, 0, 18, 6, 0, 186, 78, 165, 131, 137, 21, 246, 45, 61, 174, 213}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 143, 36}, 109}, {{96, 0, 0, 0, 0, 0, 0, 50, 89, 39, 235, 175, 228, 139, 227, 246}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 25, 245, 121, 52, 53, 92, 186, 232, 246, 92}, 109}, {{96, 0, 0, 0, 0, 185, 72, 136, 145, 22, 92, 99, 252, 32, 148, 60}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 27, 190, 232, 156, 8, 182, 157, 181}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 127, 133, 19, 187, 87, 231, 152}, 109}, {{96, 0, 0, 0, 0, 0, 0, 53, 58, 156, 99, 197, 173, 23, 109, 100}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 103, 175, 199, 252, 2, 219, 109, 225}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 109}, {{96, 0, 0, 0, 0, 0, 90, 85, 157, 34, 177, 152, 75, 149, 33, 110}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 144, 185}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 50, 15, 128, 92, 222}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 103, 157, 157, 144}, 109}, {{96, 0, 0, 0, 0, 0, 0, 12, 43, 249, 238, 56, 193, 193, 115, 206}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 252, 87, 19, 234}, 109}, {{96, 0, 0, 0, 0, 0, 37, 11, 110, 128, 37, 66, 184, 9, 179, 160}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 36, 215, 126, 164, 179, 196, 61, 196, 242, 27, 248}, 109}, {{96, 0, 0, 0, 0, 189, 245, 110, 123, 84, 137, 133, 163, 195, 165, 165}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 9, 201, 121, 158}, 109}, {{96, 0, 0, 0, 0, 64, 205, 30, 50, 134, 101, 140, 2, 37, 76, 130}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 235, 46, 93, 211, 222, 41, 188}, 109}, {{96, 0, 0, 138, 87, 183, 246, 87, 181, 147, 221, 136, 255, 41, 143, 120}, 109}, {{96, 0, 0, 250, 13, 35, 255, 175, 116, 229, 219, 130, 186, 17, 225, 9}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 116, 118}, 109}, {{96, 0, 0, 87, 41, 40, 97, 122, 5, 105, 3, 105, 12, 21, 41, 207}, 109}, {{96, 0, 68, 153, 152, 55, 94, 169, 95, 231, 103, 245, 216, 105, 201, 190}, 109}, {{96, 0, 0, 0, 147, 198, 198, 176, 180, 121, 236, 163, 233, 72, 254, 213}, 109}, {{96, 0, 0, 0, 128, 160, 94, 205, 212, 1, 169, 225, 91, 52, 24, 146}, 109}, {{96, 0, 0, 0, 0, 0, 208, 4, 7, 97, 29, 111, 140, 181, 75, 221}, 109}, {{96, 0, 0, 0, 0, 0, 0, 211, 223, 147, 136, 7, 47, 38, 103, 85}, 109}, {{96, 242, 0, 74, 222, 44, 101, 219, 135, 191, 175, 226, 76, 64, 177, 127}, 109}, {{96, 0, 0, 0, 0, 0, 99, 173, 205, 85, 226, 100, 130, 180, 115, 192}, 109}, {{96, 0, 39, 254, 173, 216, 172, 220, 174, 128, 80, 83, 43, 48, 85, 27}, 109}, {{96, 0, 61, 94, 242, 244, 116, 48, 32, 177, 221, 167, 163, 68, 149, 5}, 109}, {{96, 0, 0, 0, 52, 131, 172, 68, 55, 28, 250, 74, 205, 231, 245, 148}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 203, 182, 33}, 109}, {{96, 0, 0, 0, 0, 0, 74, 121, 146, 13, 94, 40, 40, 144, 106, 220}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 35}, 109}, {{96, 0, 0, 51, 201, 90, 53, 237, 251, 208, 121, 120, 58, 64, 130, 43}, 109}, {{96, 209, 173, 252, 138, 149, 241, 137, 161, 105, 116, 28, 155, 142, 3, 157}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 153, 127, 37, 157, 31, 18, 4}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 119, 250, 168, 120}, 109}, {{96, 0, 64, 122, 177, 49, 76, 190, 197, 220, 220, 166, 142, 2, 167, 16}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 225, 75, 36, 210, 113, 76, 47}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 109}, {{96, 0, 161, 226, 13, 58, 32, 110, 222, 99, 31, 53, 172, 139, 170, 44}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 219, 211, 40}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 85, 57, 144}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 109}, {{96, 0, 0, 0, 0, 0, 138, 10, 209, 54, 19, 177, 24, 112, 203, 99}, 109}, {{96, 0, 62, 242, 23, 63, 129, 58, 140, 211, 200, 165, 2, 148, 33, 123}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 55, 229, 108, 210, 192, 244, 62}, 109}, {{96, 0, 0, 0, 0, 59, 62, 199, 237, 74, 195, 249, 102, 23, 189, 177}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 65, 236, 14, 246, 229, 237, 240, 201}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 159, 23, 84}, 109}, {{96, 0, 0, 0, 0, 0, 0, 203, 218, 33, 154, 20, 127, 45, 126, 56}, 109}, {{96, 0, 23, 120, 189, 36, 106, 39, 107, 218, 183, 214, 143, 160, 18, 68}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 236, 32, 166}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 109}, {{96, 0, 148, 207, 197, 91, 125, 222, 214, 217, 214, 78, 120, 191, 243, 243}, 109}, {{96, 190, 137, 85, 42, 60, 10, 65, 123, 66, 168, 128, 154, 113, 86, 188}, 109}, {{96, 0, 0, 214, 213, 153, 14, 211, 92, 4, 78, 82, 8, 177, 116, 211}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 11, 82, 243, 196, 65}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 101, 116}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 109}, {{96, 0, 0, 0, 93, 127, 157, 184, 97, 85, 134, 154, 85, 192, 187, 133}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 216, 166, 131}, 109}, {{96, 0, 0, 0, 0, 232, 145, 167, 246, 212, 131, 178, 50, 91, 188, 145}, 109}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 19}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 231}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 233}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 146}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 99}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 91}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 85}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 166}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 67}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 242}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 72}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 104}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 163}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 59}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 102}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 220}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 6}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 110}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 13}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 199}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 137}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 198}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 188}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 160}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 139}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 1}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 254}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 97}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 213}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 27}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 145}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 227}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 94}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 79, 11, 95, 184, 83, 111}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 216}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 38, 245, 198}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 95, 2, 136, 203, 102}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 251, 143, 213, 229, 142, 13}, 85}, {{111, 11, 96, 0, 0, 0, 203, 249, 70, 129, 43, 2, 248, 175, 60, 77}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 85}, {{111, 11, 96, 0, 0, 0, 0, 186, 173, 232, 217, 163, 117, 222, 252, 135}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 180, 245, 129}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 84, 174, 107}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 122, 228, 125, 204, 229, 177, 62}, 85}, {{111, 11, 96, 0, 0, 78, 64, 139, 238, 196, 178, 56, 8, 87, 173, 37}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 206, 157}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 0, 138, 5}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 196, 196, 233, 148, 122, 67, 169}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 103}, 85}, {{111, 11, 96, 0, 0, 0, 0, 253, 147, 209, 25, 110, 169, 228, 122, 32}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 100, 27, 186, 61, 237, 187}, 85}, {{111, 11, 96, 0, 0, 0, 0, 132, 6, 141, 75, 178, 162, 53, 101, 158}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 181, 83, 52}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 85}, {{111, 11, 96, 199, 41, 45, 223, 226, 198, 202, 127, 163, 24, 206, 132, 95}, 85}, {{111, 11, 96, 0, 0, 0, 1, 78, 229, 197, 20, 102, 22, 221, 71, 228}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 246, 60, 153, 114, 59, 242}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 251, 77, 226, 238, 128, 7, 81}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 12, 68, 3}, 85}, {{111, 11, 96, 0, 0, 0, 93, 169, 239, 50, 50, 134, 110, 248, 193, 122}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 179, 61}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 234, 98, 214, 233, 108, 101, 61}, 85}, {{111, 11, 96, 0, 0, 0, 227, 206, 18, 244, 152, 199, 66, 238, 111, 238}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 85}, {{111, 11, 96, 0, 0, 0, 175, 132, 222, 37, 34, 172, 242, 15, 252, 61}, 85}, {{111, 11, 96, 0, 3, 166, 153, 20, 40, 178, 176, 54, 193, 15, 51, 56}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 85}, {{111, 11, 96, 0, 232, 41, 73, 0, 104, 222, 229, 28, 65, 33, 0, 2}, 85}, {{111, 11, 96, 186, 45, 198, 164, 36, 246, 81, 121, 251, 123, 23, 117, 27}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 126, 180, 36, 72, 9, 250}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 23, 136, 17, 155, 141, 14, 114}, 85}, {{111, 11, 96, 0, 122, 57, 184, 180, 35, 67, 63, 80, 185, 227, 12, 228}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 9, 15, 201, 129, 34, 31, 23, 3}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 182, 63, 224, 127, 195, 162, 234, 28}, 85}, {{111, 11, 96, 0, 105, 204, 243, 82, 57, 124, 23, 223, 167, 231, 106, 4}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 85}, {{111, 11, 96, 0, 0, 0, 242, 110, 253, 15, 221, 55, 108, 209, 93, 40}, 85}, {{111, 11, 96, 0, 0, 0, 60, 84, 27, 225, 96, 19, 61, 158, 31, 139}, 85}, {{111, 11, 96, 0, 24, 90, 39, 222, 195, 247, 39, 122, 184, 43, 114, 29}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 178, 10, 82, 124, 82, 18}, 85}, {{111, 11, 96, 0, 0, 111, 118, 195, 185, 44, 219, 252, 203, 129, 117, 120}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 120, 167, 157, 172, 187, 232, 28}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 166, 5}, 85}, {{111, 11, 96, 0, 0, 23, 101, 178, 87, 26, 218, 146, 122, 113, 186, 125}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 94, 53, 180}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 20, 153, 250, 200, 23, 132, 28, 75}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 188, 54, 113, 199, 110}, 85}, {{111, 11, 96, 0, 53, 11, 46, 210, 221, 83, 186, 42, 196, 247, 52, 137}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 58, 167, 0, 141, 138, 150, 220}, 85}, {{111, 11, 96, 52, 117, 233, 250, 60, 128, 106, 235, 114, 27, 84, 253, 242}, 85}, {{111, 11, 96, 0, 0, 0, 55, 39, 14, 115, 84, 33, 233, 9, 93, 178}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 32, 161}, 85}, {{111, 11, 96, 0, 31, 181, 65, 162, 62, 96, 139, 34, 203, 0, 231, 199}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 135, 233, 242}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 229, 189, 65, 36, 253}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 90, 168, 8}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 68}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 2, 5, 21, 198, 1, 46}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 149, 12, 17, 209, 197, 18}, 85}, {{111, 11, 96, 255, 23, 69, 103, 181, 160, 145, 237, 101, 32, 218, 241, 151}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 250}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 176, 53, 34, 158, 105}, 85}, {{111, 11, 96, 0, 0, 0, 38, 147, 169, 137, 165, 176, 176, 15, 238, 71}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 85}, {{111, 11, 96, 0, 0, 0, 246, 94, 53, 5, 113, 72, 10, 71, 242, 182}, 85}, {{111, 11, 96, 0, 242, 252, 146, 158, 144, 56, 59, 78, 130, 252, 69, 119}, 85}, {{111, 11, 96, 0, 0, 0, 0, 15, 74, 204, 69, 219, 168, 156, 246, 27}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 14}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 66, 74, 59, 95, 43, 62}, 85}, {{111, 11, 96, 0, 0, 0, 182, 182, 124, 218, 253, 149, 247, 56, 162, 135}, 85}, {{111, 11, 96, 0, 0, 82, 114, 201, 154, 240, 50, 11, 16, 90, 32, 100}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 53, 35, 153, 20, 3}, 85}, {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 85}, {{111, 11, 96, 0, 0, 0, 0, 155, 247, 226, 126, 80, 7, 52, 92, 4}, 85}, {{111, 11, 96, 0, 0, 0, 0, 92, 208, 160, 231, 57, 114, 50, 31, 38}, 85}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 199, 86}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 72}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 190}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 25}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 24}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 197}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 197}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 214}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 99}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 55}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 142}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 105, 66}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 93}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 237, 72}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 130}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 223}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 178, 117}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 151}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 182, 175}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 164}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 185}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 100, 11}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 25, 119}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 40, 210}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 63}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 40, 246}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 95}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 254}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 148, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 25}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 129, 191}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 14, 73}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 222}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 137}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 221, 1}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 108}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 222}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 174, 175}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 155, 74}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 60}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 176}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 44}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 11}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 68}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 16, 218}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 173}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 19, 138}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 77, 137}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 104, 234}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 48}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 94}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 173}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 161}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 250}, {{141, 52, 0, 0, 130, 56, 229, 100, 36, 139, 152, 135, 49, 170, 173, 209}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 255, 91}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 172, 72, 230, 253, 65, 226}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 80, 41, 131, 56, 60, 43, 4, 223}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 87, 169}, 153}, {{141, 52, 0, 0, 0, 0, 0, 8, 28, 98, 248, 93, 158, 127, 235, 234}, 153}, {{141, 52, 0, 0, 0, 0, 0, 232, 97, 53, 115, 191, 4, 133, 36, 118}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 22}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 94, 93, 131, 238, 186, 80}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 248, 11, 60, 117, 64, 216, 30}, 153}, {{141, 52, 0, 0, 0, 0, 174, 38, 14, 116, 123, 96, 44, 103, 228, 230}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 146, 150, 158, 233, 220, 76, 14, 158}, 153}, {{141, 52, 0, 0, 0, 0, 121, 164, 54, 176, 88, 131, 132, 205, 61, 41}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 182, 232, 106, 176, 132, 117, 84}, 153}, {{141, 52, 0, 0, 0, 0, 70, 126, 31, 79, 192, 209, 0, 217, 196, 55}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 143, 10, 235, 128, 202, 105, 248}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 70, 32, 59, 15, 176, 139, 89, 207, 81, 148, 213, 78, 107}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 0, 0, 0, 0, 195, 86, 169, 56, 46, 184, 180, 137, 126}, 153}, {{141, 52, 0, 0, 186, 72, 222, 151, 14, 211, 63, 170, 148, 6, 162, 11}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 58, 225, 8}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 193, 121}, 153}, {{141, 52, 0, 0, 132, 33, 135, 13, 104, 222, 58, 88, 95, 149, 67, 133}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 217, 5}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 205, 233, 194, 93, 35, 47}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 153}, {{141, 52, 0, 0, 0, 0, 0, 137, 144, 116, 11, 28, 83, 124, 88, 238}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 64, 130, 232, 48, 221, 81, 61, 220, 255, 120, 44, 164, 133}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 130, 161, 162, 83}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 227, 103, 61, 108, 190, 215, 7, 213}, 153}, {{141, 52, 0, 0, 0, 0, 0, 24, 65, 156, 9, 229, 18, 125, 204, 139}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 29, 255, 195}, 153}, {{141, 52, 0, 0, 0, 143, 215, 56, 61, 155, 39, 27, 216, 226, 2, 135}, 153}, {{141, 52, 0, 246, 27, 15, 205, 229, 172, 158, 187, 27, 232, 77, 154, 140}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 246}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 107, 34, 12, 116, 163, 85, 158}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 90, 99, 18, 137, 61, 182, 205}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 16, 2, 186}, 153}, {{141, 52, 0, 0, 193, 136, 68, 198, 126, 63, 197, 77, 105, 102, 123, 233}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 186, 18, 32, 162, 88, 251, 172}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 232, 186, 73, 26, 111, 54, 30}, 153}, {{141, 52, 0, 0, 158, 109, 3, 203, 49, 69, 0, 149, 240, 168, 222, 33}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 134, 248, 182, 20, 225, 34}, 153}, {{141, 52, 0, 0, 34, 96, 105, 85, 54, 112, 139, 208, 166, 105, 97, 95}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 22, 126, 207}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 41, 62, 215, 188, 172, 216, 46, 194}, 153}, {{141, 52, 0, 0, 85, 185, 120, 135, 225, 13, 74, 36, 42, 76, 212, 232}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 81, 212, 253, 80}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 177, 234, 83, 75}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 197, 137, 143}, 153}, {{141, 52, 0, 146, 65, 197, 239, 62, 132, 210, 26, 193, 203, 42, 206, 153}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 153}, {{141, 52, 0, 0, 0, 0, 136, 238, 70, 93, 127, 1, 7, 232, 133, 149}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 245, 15, 65, 119}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 57, 126, 109, 157, 24, 74}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 214, 232}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 94, 127, 19, 161, 12, 117, 188, 109}, 153}, {{141, 52, 0, 0, 0, 0, 0, 179, 161, 239, 98, 195, 190, 40, 17, 67}, 153}, {{141, 52, 0, 0, 0, 54, 138, 156, 70, 94, 10, 58, 127, 36, 125, 200}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 60}, 153}, {{141, 52, 0, 0, 0, 148, 188, 254, 13, 64, 96, 155, 210, 144, 21, 43}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 29, 219, 69, 35}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 3}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 40, 109, 28, 117}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 157, 210, 90, 233, 134, 72, 136}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 201, 92, 6, 213, 166, 14, 24}, 153}, {{141, 52, 0, 127, 137, 41, 52, 91, 4, 29, 166, 8, 207, 179, 247, 12}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 11, 101, 174, 195, 54, 123, 177, 56}, 153}, {{141, 52, 0, 0, 0, 0, 137, 90, 240, 107, 254, 112, 183, 52, 19, 20}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 29, 1, 91, 80, 114, 30}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 208, 121, 176, 216, 236, 22, 174}, 153}, {{141, 52, 0, 0, 0, 0, 106, 16, 93, 60, 84, 153, 31, 148, 13, 228}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 12, 164, 57}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 176}, 153}, {{141, 52, 0, 0, 0, 0, 0, 13, 124, 16, 170, 85, 103, 237, 222, 96}, 153}, {{141, 52, 0, 129, 157, 3, 73, 160, 230, 66, 126, 119, 100, 98, 19, 137}, 153}, {{141, 52, 0, 0, 239, 60, 93, 176, 187, 210, 90, 3, 219, 98, 67, 161}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 233, 7, 14, 55, 227, 157, 51, 76}, 153}, {{141, 52, 0, 0, 0, 65, 19, 217, 72, 254, 250, 153, 17, 70, 20, 212}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 175, 163, 67, 115}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 80, 192, 1, 234, 230, 165, 120, 237}, 153}, {{141, 52, 0, 42, 225, 125, 100, 177, 254, 225, 48, 56, 202, 193, 35, 121}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 212, 180, 202, 94, 119, 87, 41}, 153}, {{141, 52, 0, 0, 0, 0, 0, 32, 230, 119, 246, 150, 18, 245, 225, 77}, 153}, {{141, 52, 0, 0, 0, 196, 244, 130, 177, 104, 5, 44, 52, 83, 29, 225}, 153}, {{141, 52, 0, 99, 76, 98, 233, 218, 134, 110, 211, 236, 209, 233, 189, 71}, 153}, {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 153}, {{141, 52, 0, 0, 0, 0, 236, 152, 249, 0, 9, 177, 30, 30, 241, 10}, 153}, {{141, 52, 0, 0, 0, 0, 128, 230, 184, 109, 152, 203, 19, 90, 154, 132}, 153}, {{141, 52, 0, 0, 108, 212, 228, 34, 237, 248, 180, 142, 134, 0, 217, 59}, 153}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 182}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 19, 156, 140}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 111}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 55}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 226, 125}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 156, 180, 101}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 232, 224}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 222, 56, 177}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 100, 165}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 126, 192}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 54, 30, 121}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 203, 172}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 235, 90, 203}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 63}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 219, 48}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 173, 125}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 168, 22}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 101, 244, 249}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 161}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 199, 59}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 120}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 8, 255}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 237}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 20, 117, 142}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 35, 9, 49, 189}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 140}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 69}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 119}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 99}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 38, 10}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 234}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 42, 95}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 58, 143}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 204}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 7, 30, 119}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 117, 29}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 49, 160, 95}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 247, 107, 164, 13}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 157, 144, 243, 241}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 62, 236, 27}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 100, 167}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 151, 62}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 53}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 253, 89, 224}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 78}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 136, 54}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 154, 154, 62}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 234, 194, 62, 188}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 105, 252, 176}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 235}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 121, 250}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 143, 118}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 76}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 60, 40, 194}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 70, 229}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 50}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 164, 188, 79}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 150, 235, 159}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 187, 251, 239, 113}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 64}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 113}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 66, 147, 47}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 245, 135, 214}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 78, 76, 243}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 204}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 14}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 227}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 2}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 57, 196, 74}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 197}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 98}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 253, 47, 85}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 25, 23, 183}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 160, 238}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 252, 25, 113}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 47, 146}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 71, 140, 205, 141}, 23}, {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 25, 164, 141}, 23}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 129, 244}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 240, 183}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 209}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 123, 128}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 203, 208}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 5}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 130, 128}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 179}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 159}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 239}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 21, 142}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 47, 33}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 110, 93}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 255}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 36}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 185, 30}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 255, 14}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 138}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 120, 128}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 153, 55}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 234}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 235, 130}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 215}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 185, 224}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 119}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 66, 8}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 220}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 37, 94}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 234}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 61, 194}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 92}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 238, 241}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 202}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 177}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 155, 181}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 84, 130}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 62}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 153}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 153}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 86}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 235, 62}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 10, 40}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 174}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 95, 224}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 222, 153}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 75}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 143}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 187}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 238, 140}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 201, 58}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 19}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 119}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 143}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 169, 230}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 165}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 226}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 47, 151}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 120}, 38}, {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 38}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 46, 69}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 249}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 249}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 136, 151}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 59}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 18}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 101}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 135, 150}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 115}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 213}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 30}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 45}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 217}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 159}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 98}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 33}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 130}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 120}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 143}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 151}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 206, 97}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 32}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 52}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 245}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 207}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 211}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 98}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 53}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 97}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 17}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 64, 163}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 177}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 223}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 241}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 203}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 168, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 78, 66}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 128}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 232}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 10}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 145}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 124, 207}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 166}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 217}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 104}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 14}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 158}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 129, 41}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 255}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 128}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 158, 95}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 121}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 193}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 79}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 121}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 118, 165, 231, 105}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 40, 104, 109, 2}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 53, 213}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 124, 101, 105, 19}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 176, 124}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 106, 249, 162}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 181, 102, 83, 37}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 214}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 253, 121, 72, 25}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 76, 49, 75}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 222, 164}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 101}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 226}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 50, 2}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 250}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 197, 54, 250, 86}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 32, 4}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 107, 100}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 211, 195, 164, 3}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 71, 210, 44, 123}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 166}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 134, 87, 221}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 232}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 157, 167, 63, 141}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 171, 58}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 234}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 19, 160}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 185}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 231, 93}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 190}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 29}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 180, 188, 56, 76}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 84, 9}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 82, 161, 137}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 141, 108}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 168, 39}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 22, 132, 84}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 248, 105}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 250, 203}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 61, 227, 225, 67}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 66, 230, 4, 168}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 244, 164, 252, 150}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 18, 156, 241, 85}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 231, 240}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 169}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 198, 8}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 235, 85, 74, 105}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 48, 184, 188, 46}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 5, 63}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 14}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 215, 220, 205}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 193, 96}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 109, 118, 226}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 41}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 224, 81, 82, 115}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 157, 20, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 30, 165, 228}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 192}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 79}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 211, 93, 218, 82}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 31}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 109, 0, 216}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 138, 197}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 152, 135, 92}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 12}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 64, 204}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 159, 110, 171}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 85, 175, 176}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 6}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 228, 88, 88}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 181, 182, 151, 40, 37}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 4, 17, 25}, 146}, {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 172}, 146}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 240, 11, 103, 69, 74, 155, 201, 2, 105, 215, 199, 113, 210}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 32, 159, 16, 8}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 165, 19, 207}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 116, 72, 96, 246, 3, 75, 10}, 138}, {{210, 99, 0, 0, 0, 164, 116, 233, 188, 37, 58, 240, 40, 185, 53, 151}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 121, 49, 241, 175, 108, 133, 135, 201, 47, 219, 196, 154}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 57}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 22}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 235, 164, 103, 90, 6, 232, 235}, 138}, {{210, 99, 0, 29, 119, 210, 103, 66, 202, 246, 145, 26, 238, 208, 35, 113}, 138}, {{210, 99, 0, 0, 0, 0, 17, 145, 225, 4, 245, 53, 234, 119, 219, 226}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 61, 140, 72}, 138}, {{210, 99, 0, 0, 249, 219, 202, 223, 130, 176, 177, 210, 57, 10, 184, 89}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 216, 146, 165, 206, 84, 65, 210, 226}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 171, 80, 220, 56, 200, 203}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 154}, 138}, {{210, 99, 0, 0, 0, 172, 130, 62, 77, 10, 175, 95, 51, 21, 218, 219}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 138}, {{210, 99, 0, 0, 0, 121, 229, 139, 176, 226, 126, 34, 79, 216, 227, 225}, 138}, {{210, 99, 0, 0, 0, 16, 66, 3, 221, 100, 36, 129, 128, 168, 177, 150}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 215, 79, 150, 183, 56, 219, 11, 212, 166}, 138}, {{210, 99, 0, 0, 0, 141, 233, 92, 56, 25, 56, 132, 144, 165, 173, 203}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 184, 203, 112, 1, 162, 233}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 218, 194, 187, 197, 120, 221}, 138}, {{210, 99, 0, 0, 0, 57, 194, 119, 53, 250, 55, 32, 97, 31, 50, 3}, 138}, {{210, 99, 0, 0, 0, 130, 52, 103, 171, 50, 223, 49, 20, 45, 214, 38}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 93, 94, 119, 178, 179, 2}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 40, 81, 186}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 25, 168}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 254}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 195, 192, 152, 200}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 89, 49, 148, 230}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 189, 151, 204, 108}, 138}, {{210, 99, 0, 0, 0, 0, 0, 226, 0, 25, 53, 20, 64, 119, 55, 2}, 138}, {{210, 99, 0, 0, 102, 44, 14, 196, 104, 167, 162, 167, 62, 181, 170, 137}, 138}, {{210, 99, 0, 143, 87, 40, 212, 31, 176, 210, 21, 9, 20, 74, 228, 105}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 138}, {{210, 99, 0, 133, 252, 161, 106, 148, 63, 45, 109, 135, 187, 178, 34, 207}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 143}, 138}, {{210, 99, 0, 61, 139, 180, 179, 196, 28, 145, 161, 18, 72, 41, 135, 215}, 138}, {{210, 99, 0, 0, 0, 116, 51, 5, 189, 148, 179, 228, 212, 157, 64, 123}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 58, 163, 152, 132, 203, 35, 46}, 138}, {{210, 99, 0, 0, 0, 0, 128, 78, 196, 144, 67, 14, 224, 255, 209, 50}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 171, 217, 244, 84, 184, 62, 113}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 224, 190}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 79, 243}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 131, 153, 123, 152, 40, 137, 0, 157, 214, 177, 42, 74, 85}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 97}, 138}, {{210, 99, 0, 0, 180, 171, 144, 32, 139, 190, 32, 73, 217, 214, 250, 153}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 169}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 139, 14, 232, 109, 141, 6, 59, 220, 210}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 184, 131, 71, 139, 59, 154}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 138}, {{210, 99, 0, 0, 0, 0, 227, 107, 82, 182, 87, 231, 173, 127, 44, 39}, 138}, {{210, 99, 0, 0, 0, 1, 24, 164, 47, 45, 219, 145, 229, 227, 211, 118}, 138}, {{210, 99, 0, 0, 0, 0, 0, 90, 4, 148, 180, 30, 199, 239, 85, 16}, 138}, {{210, 99, 0, 0, 0, 0, 217, 206, 137, 102, 24, 213, 240, 210, 117, 125}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 60, 47, 253}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 167, 177, 170, 227, 10, 40, 113}, 138}, {{210, 99, 0, 0, 0, 0, 192, 59, 152, 119, 76, 216, 230, 221, 202, 127}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 102, 22, 39}, 138}, {{210, 99, 0, 0, 0, 198, 103, 207, 96, 248, 75, 135, 191, 186, 63, 14}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 125, 139, 39, 152, 72, 4, 114, 253}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 206, 26, 45}, 138}, {{210, 99, 0, 0, 0, 0, 0, 236, 202, 30, 159, 23, 156, 29, 228, 36}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 123, 175, 245, 67, 110, 72, 41}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 248, 73, 231, 96, 136, 148, 120, 46, 120, 13, 171, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 129, 233, 192, 245}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 25}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 95}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 250, 52, 161, 159, 178, 194, 230}, 138}, {{210, 99, 0, 0, 0, 0, 252, 185, 104, 205, 176, 49, 176, 30, 108, 134}, 138}, {{210, 99, 0, 0, 0, 0, 0, 76, 159, 104, 151, 220, 216, 41, 16, 128}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 211, 205, 230, 24, 227, 97, 13}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 178, 249, 155, 145, 92, 216, 200}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 138}, {{210, 99, 0, 0, 44, 4, 32, 114, 7, 73, 199, 94, 27, 3, 81, 207}, 138}, {{210, 99, 0, 0, 0, 190, 219, 210, 64, 197, 104, 173, 60, 133, 116, 151}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 198}, 138}, {{210, 99, 0, 0, 166, 142, 54, 21, 150, 219, 148, 154, 14, 178, 172, 255}, 138}, {{210, 99, 0, 201, 112, 5, 115, 115, 4, 191, 116, 76, 174, 144, 180, 53}, 138}, {{210, 99, 0, 0, 0, 48, 237, 253, 109, 110, 212, 237, 104, 241, 174, 245}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 168, 84}, 138}, {{210, 99, 0, 0, 0, 0, 115, 18, 212, 131, 46, 109, 232, 179, 33, 63}, 138}, {{210, 99, 0, 0, 0, 0, 0, 252, 77, 241, 213, 111, 138, 168, 138, 143}, 138}, {{210, 99, 0, 0, 0, 0, 7, 58, 107, 103, 4, 139, 206, 181, 148, 161}, 138}, {{210, 99, 0, 0, 65, 62, 209, 62, 74, 217, 57, 188, 121, 77, 26, 130}, 138}, {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 154, 0, 28, 120}, 138}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 29}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 186, 80}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 137, 34, 242}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 182}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 135, 210, 83}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 252, 76, 190}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 202}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 152, 35}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 205, 65}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 182}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 145}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 53, 229, 216, 206}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 40}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 254, 39}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 206, 4, 36}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 44, 96, 88}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 3, 155}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 200, 165}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 239, 125, 100}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 148, 143}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 49, 26}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 73, 16, 201, 177}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 120}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 138, 34, 95}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 220}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 210, 223}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 16, 23, 67}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 159, 186, 160}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 161, 59}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 153, 5, 255, 156}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 39}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 131, 176, 251}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 108, 153, 45}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 208, 77, 219, 158}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 5, 80}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 159, 116, 116}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 173, 180}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 232}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 88}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 72, 236}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 192, 32}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 133, 127, 232}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 200, 116}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 185, 110, 0, 30}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 143, 175, 125}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 129, 241}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 44}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 242, 1, 233, 201}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 247}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 202}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 161, 36, 233}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 25, 229, 189}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 228, 140}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 221, 29, 198}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 217, 106}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 189, 125}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 95}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 41, 34, 41}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 130, 190}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 79}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 29, 169, 50}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 42}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 5, 235, 148, 11}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 23, 57}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 229, 228}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 145, 111}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 109}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 54, 114, 248, 65}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 85, 81, 79}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 100, 102}, 149}, {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 247, 137}, 149}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 86, 28, 76, 81}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 50, 217, 183, 64}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 35, 150}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 212, 83, 109}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 200, 254}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 178, 124}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 40}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 117, 165, 96}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 139}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 47, 60}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 83, 161, 63, 81}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 248, 92, 88, 64}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 153, 170, 246, 159}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 44}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 128, 182, 156}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 131}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 57, 187, 99, 173}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 119, 192, 163}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 94}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 134, 219, 145, 245}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 136, 67, 152}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 201}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 252, 120, 32}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 235}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 114}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 101, 51, 2}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 182, 46, 73}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 108}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 118}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 58, 78}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 10, 121}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 191}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 212}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 105, 172, 246, 51}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 255, 80}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 174, 165}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 43, 218}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 31}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 101, 17}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 98}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 91, 113, 11}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 52, 119, 71}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 154, 110, 99, 33}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 54, 51, 91}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 166, 236, 59, 161}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 247, 227, 91, 110}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 46, 225, 102, 188}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 205, 150}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 231, 238, 230}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 129, 142}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 153, 253}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 134}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 141, 100}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 251, 99, 235}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 194, 56, 87}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 242}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 125}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 22, 187, 212}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 235, 14, 144}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 79, 60, 123, 147}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 29, 61, 169}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 232}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 46, 55, 241}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 29, 94, 124, 166}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 41}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 187, 9, 53}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 62, 189, 182}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 171, 183, 44, 101}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 202, 245, 196}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 42, 71}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 31}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 93, 130, 72, 35}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 59}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 178, 228}, 232}, {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 190, 36, 229, 235}, 232}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 99, 35, 166, 63, 207}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 98, 152, 184, 240, 79, 242}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 191, 47, 113, 34, 215, 159}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 79, 189, 213, 146, 86}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 185, 102, 23}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 133, 215}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 197, 10}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 6, 255, 57, 208, 248}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 33, 79}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 168, 145, 253, 118}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 110, 157, 70, 192, 17}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 58, 65, 56}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 95, 127, 21, 126, 229, 25}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 60, 196}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 14, 5}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 65, 27, 54, 124, 201, 82, 20, 249}, 255}, {{75, 58, 170, 52, 146, 80, 146, 200, 137, 151, 79, 185, 143, 203, 17, 168}, 255}, {{75, 58, 170, 52, 146, 80, 0, 4, 110, 215, 34, 0, 44, 186, 66, 234}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 43, 248}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 81, 109, 18, 89, 192, 34, 147}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 253, 225, 175, 146}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 161, 96, 231, 83, 46, 66, 47}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 129, 81, 10}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 255, 205, 68}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 112, 247, 75, 219, 66}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 243, 21, 55, 201}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 98, 244, 193, 69, 54, 40, 145, 175}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 44, 30, 240}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 105, 201, 134, 176}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 196, 104, 47, 74, 90, 89, 3}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 213, 187, 233, 217}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 200, 144, 201, 203, 91, 27}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 220, 28, 195, 120, 192, 80, 170, 242}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 136, 176, 61, 177, 198, 42}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 67, 161, 239}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 207, 16, 45, 179, 123, 155}, 255}, {{75, 58, 170, 52, 146, 80, 8, 175, 197, 32, 253, 35, 115, 84, 82, 151}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 238, 200}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 103, 10, 37, 55, 93}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 218, 70, 131, 206, 68}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 152, 25, 166, 205, 190, 12, 221}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 133, 175, 38, 123, 147, 28}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 20, 146, 112, 72, 140, 154, 215, 66}, 255}, {{75, 58, 170, 52, 146, 80, 0, 85, 101, 84, 0, 53, 242, 28, 7, 82}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 69, 13, 238}, 255}, {{75, 58, 170, 52, 146, 80, 0, 31, 233, 245, 202, 222, 159, 242, 154, 22}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 117, 195, 58, 153, 141, 3}, 255}, {{75, 58, 170, 52, 146, 80, 0, 32, 122, 217, 129, 176, 118, 245, 21, 92}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 197, 252, 236, 183}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 102, 201, 241, 230, 54, 34}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 29, 20, 199, 139, 158, 137, 56, 67}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 240, 10, 229, 36, 255, 227, 137, 24}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 229, 164, 0, 12, 93, 99, 169}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 100, 9}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 198, 151, 160, 31, 67, 112, 142}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 215, 22, 6, 83, 19, 66, 42, 27}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 121, 93, 91, 104, 101}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 252, 186, 135, 74, 38, 210, 194, 36}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 132, 234, 167, 72, 110, 144, 74, 7}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 45, 255, 187, 19, 10, 72, 240}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 77, 168, 15}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 35, 194, 244}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 37, 110, 199}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 82, 140, 251}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 28, 20, 152, 229}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 195, 130, 69, 172, 230, 14}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 175, 124, 89}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 20, 194, 208, 117, 49, 115, 222, 12, 205}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 37, 135, 133}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 220, 241, 36, 226, 37, 222, 71}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 223, 35, 46}, 255}, {{75, 58, 170, 52, 146, 80, 0, 163, 180, 102, 103, 194, 58, 212, 199, 163}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 45, 255, 133, 219, 102, 141, 29, 138}, 255}, {{75, 58, 170, 52, 146, 80, 0, 77, 229, 68, 170, 182, 163, 51, 107, 84}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 228, 35, 95, 6, 191, 247, 62}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 124, 175}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 145, 255, 179, 229, 26, 43, 144}, 255}, {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 203, 25}, 255}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 123, 67, 247, 237}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 191, 101, 163, 191, 250}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 131, 173, 35, 175, 186}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 218, 21, 81, 245}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 168, 36, 139, 231, 226, 150, 152}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 62, 7}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 70, 84, 2, 80, 253, 238}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 22, 60}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 127, 29, 26, 109, 22, 214}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 230, 25, 75, 149, 202}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 26, 122}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 240, 240, 34}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 127, 74, 207, 212, 117}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 175, 7, 101, 62}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 48, 102, 62, 160, 172}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 208, 15, 196, 209, 171}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 198, 2, 183, 162, 222, 204, 183, 211}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 93, 229, 143, 222, 191, 170, 166, 109}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 101, 39, 1, 224, 207}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 97, 102, 78}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 95, 34, 129, 37, 98, 171, 2, 202}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 241, 32, 249, 194, 142}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 233, 73}, 148}, {{92, 21, 1, 113, 185, 88, 160, 227, 208, 231, 130, 39, 186, 222, 107, 138}, 148}, {{92, 21, 1, 113, 185, 88, 160, 68, 16, 237, 22, 221, 185, 154, 255, 49}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 203, 112, 17, 84, 157, 230, 56, 159}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 228, 176, 228, 230, 222}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 213, 143, 180, 197, 22, 54, 240}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 149, 47}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 69, 222, 69, 38, 131, 115, 99}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 96, 164, 134, 109, 76, 119}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 224, 39, 229, 202}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 198, 108, 79, 20, 185, 217, 98}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 220, 136, 185, 212, 13, 152, 132, 53}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 212, 75, 241}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 140, 22, 163, 197, 192, 253, 178, 239}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 161, 169, 232}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 239, 193}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 191, 211, 155, 50, 85}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 78, 88, 222, 139, 224, 183, 181, 69}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 125, 105, 185, 113, 8, 99}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 40, 169, 251, 120, 207, 126, 212, 212}, 148}, {{92, 21, 1, 113, 185, 88, 160, 19, 29, 134, 179, 69, 112, 73, 78, 160}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 223, 255, 145, 111, 89, 142, 154}, 148}, {{92, 21, 1, 113, 185, 88, 160, 138, 89, 25, 229, 214, 90, 84, 10, 178}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 45, 164, 127, 111, 143, 63, 93, 169}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 50, 105, 185, 137, 28, 212}, 148}, {{92, 21, 1, 113, 185, 88, 160, 3, 143, 220, 7, 224, 84, 169, 218, 94}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 121, 89}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 21, 47, 141}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 174, 2, 33}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 99, 86, 63}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 114, 115, 155, 203}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 85, 214, 6, 10}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 72, 231, 253, 81, 156, 82, 106}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 5, 55, 72, 112, 69, 68, 185}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 15, 41, 226, 60}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 138, 154, 101, 2, 190, 231, 226}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 139, 55}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 87, 249, 78, 244, 164, 187, 113}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 130, 151, 24, 57, 58, 39, 56}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 128, 150, 105, 191}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 64, 62, 27, 190, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 106, 108, 191, 84, 138, 101}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 239, 74}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 212, 58}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 244, 120, 216, 177, 148, 47, 140}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 240, 61, 64, 226, 64, 76, 73, 180}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 5, 105, 137}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 224, 105}, 148}, {{92, 21, 1, 113, 185, 88, 160, 35, 205, 167, 217, 28, 220, 72, 107, 18}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 29, 34, 43, 16, 166, 220, 24, 1}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 142, 22, 60, 84, 222, 97}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 160, 47}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 199, 202}, 148}, {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 72, 203}, 148}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 44, 53}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 41, 151, 225, 105}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 135, 132, 124}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 191, 223, 45, 252, 19}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 108, 234, 138, 195, 33, 161}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 118, 129, 116}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 84, 14, 158, 148, 2}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 215, 136, 133, 235, 62}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 115, 49, 110, 197, 196, 130}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 217, 149}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 63, 77, 123, 57, 93, 207, 87, 119}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 38, 126, 178, 114, 5}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 247, 166, 213, 102, 84, 63, 148, 175, 130}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 22, 252, 169, 90, 11, 55, 202, 22}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 94, 142, 172, 23, 176, 3, 191}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 123, 34, 144}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 47, 98, 157, 195, 218}, 117}, {{103, 180, 222, 187, 129, 117, 0, 20, 132, 24, 93, 73, 149, 80, 49, 211}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 130, 124, 231, 194}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 37, 4, 2, 175, 110, 216}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 66, 164}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 215, 50, 183, 143, 106, 191, 31, 210}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 194, 86, 188, 202, 77, 145, 56}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 48, 12, 16, 90, 182, 238, 100}, 117}, {{103, 180, 222, 187, 129, 117, 0, 42, 172, 64, 193, 235, 21, 108, 122, 129}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 228, 99, 57, 25}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 143, 64, 211, 27, 254}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 219, 164, 132, 80, 157, 154, 161}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 138, 31, 253, 24, 53, 39, 75, 164}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 225, 24, 210, 16, 24, 209, 139}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 238, 113, 196, 119}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 73, 59}, 117}, {{103, 180, 222, 187, 129, 117, 0, 143, 32, 10, 41, 220, 92, 161, 229, 135}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 22, 177, 203}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 39, 167, 233, 145, 250, 150, 53, 163}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 129, 156, 242, 219, 130, 191, 110, 71}, 117}, {{103, 180, 222, 187, 129, 117, 0, 203, 88, 122, 139, 236, 152, 11, 178, 118}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 81, 253, 66, 107}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 110, 221, 247, 206}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 147, 26}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 158, 21}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 84, 68, 71, 235}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 65, 130, 161, 109}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 105, 90, 31, 235, 57, 161}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 203, 174, 113}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 138, 157}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 8, 179, 181, 95}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 17, 113, 165}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 119, 164, 182}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 33, 197, 58, 199, 239}, 117}, {{103, 180, 222, 187, 129, 117, 0, 153, 50, 161, 124, 73, 27, 200, 9, 43}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 72, 213, 155}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 82, 33, 215, 227, 53, 81}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 165, 218, 15}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 93, 167, 162, 241, 219}, 117}, {{103, 180, 222, 187, 129, 117, 0, 252, 25, 59, 123, 46, 206, 205, 146, 233}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 14, 110, 56, 202, 60, 116}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 180, 30, 226, 156, 22, 60, 123, 67}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 155, 141, 65}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 78, 254, 55, 176, 32, 116, 46, 47}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 250, 15}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 191, 74, 64, 202, 73, 234}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 36, 96, 123, 128}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 44, 171, 86, 221, 76, 67, 60, 67}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 130, 160}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 147, 122, 246, 144, 19, 104, 208, 125, 23}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 203, 233, 243, 81}, 117}, {{103, 180, 222, 187, 129, 117, 0, 59, 19, 230, 92, 41, 19, 130, 142, 244}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 209, 207, 251, 12, 10, 211}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 142, 100, 167, 99, 179, 191}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 100, 24, 253, 15, 129}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 44, 85, 121, 86, 141}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 144, 78, 103, 154}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 195, 36, 91, 75, 114, 11}, 117}, {{103, 180, 222, 187, 129, 117, 0, 227, 245, 2, 127, 189, 71, 41, 185, 231}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 117}, {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 145, 240, 122, 107, 251, 115}, 117}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 70, 168, 175, 176}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 68, 240, 55, 103, 57, 83, 58}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 155, 19, 233, 3}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 48, 105, 23, 195, 33, 181, 98}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 248, 208, 156, 69}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 170, 217, 118, 110, 214, 188, 240, 195}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 96, 154, 96, 40, 105, 53, 133, 91}, 237}, {{32, 76, 0, 132, 3, 103, 164, 147, 189, 89, 24, 246, 105, 186, 169, 35}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 45, 80, 114, 93}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 244, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 210, 96, 171, 74, 203, 26, 162, 107, 200, 253, 185, 225, 19}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 108}, 237}, {{32, 76, 0, 0, 85, 70, 0, 175, 213, 224, 248, 227, 16, 49, 61, 178}, 237}, {{32, 76, 0, 213, 122, 137, 1, 33, 199, 158, 9, 32, 29, 58, 199, 20}, 237}, {{32, 76, 0, 0, 0, 225, 16, 117, 153, 240, 32, 78, 133, 201, 71, 110}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 234, 48, 44, 30, 161, 226, 38, 218}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 171, 218, 53, 32, 136, 147, 86}, 237}, {{32, 76, 0, 0, 0, 0, 0, 56, 44, 88, 115, 199, 187, 246, 160, 192}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 237}, {{32, 76, 0, 0, 0, 0, 0, 71, 245, 187, 29, 104, 255, 123, 144, 21}, 237}, {{32, 76, 0, 78, 250, 165, 92, 34, 110, 121, 158, 90, 177, 224, 218, 217}, 237}, {{32, 76, 0, 0, 0, 221, 248, 135, 172, 73, 107, 11, 25, 184, 128, 248}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 31, 9, 147, 240}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 225, 64}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 230, 235, 124, 17, 2, 116, 1}, 237}, {{32, 76, 105, 147, 208, 129, 158, 152, 152, 8, 123, 21, 193, 198, 146, 248}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 235, 206, 156, 1, 141, 30, 139}, 237}, {{32, 76, 0, 0, 189, 96, 237, 238, 143, 177, 187, 153, 252, 221, 71, 213}, 237}, {{32, 76, 0, 84, 57, 120, 75, 225, 148, 223, 117, 8, 53, 31, 23, 45}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 228, 154}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 98, 175}, 237}, {{32, 76, 0, 0, 0, 0, 21, 90, 152, 111, 75, 133, 87, 157, 176, 236}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 88, 194, 18, 192}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 131, 100}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 240, 130, 147, 142, 100, 84, 92, 127}, 237}, {{32, 76, 0, 0, 83, 216, 87, 20, 71, 209, 81, 78, 55, 33, 78, 132}, 237}, {{32, 76, 0, 96, 167, 183, 234, 9, 251, 190, 58, 24, 214, 209, 144, 143}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 209, 65, 211, 205}, 237}, {{32, 76, 0, 0, 88, 105, 38, 25, 63, 10, 52, 114, 150, 145, 168, 27}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 101, 12, 126}, 237}, {{32, 76, 0, 78, 194, 189, 169, 123, 218, 121, 220, 93, 254, 180, 162, 176}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 139, 30, 177}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 170, 254, 111, 255, 31, 34}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 207, 232, 107, 254, 220, 222, 0, 69}, 237}, {{32, 76, 0, 0, 0, 0, 29, 108, 81, 79, 161, 18, 226, 160, 94, 23}, 237}, {{32, 76, 163, 43, 148, 35, 207, 234, 95, 223, 51, 188, 139, 39, 6, 199}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 114, 183, 211, 102, 9, 89, 114, 229, 203}, 237}, {{32, 76, 0, 0, 0, 0, 113, 134, 238, 235, 44, 153, 199, 55, 234, 244}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 220, 137, 166, 57, 102, 162}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 6, 91, 209}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 173}, 237}, {{32, 76, 0, 0, 0, 0, 49, 44, 177, 124, 123, 97, 225, 180, 13, 3}, 237}, {{32, 76, 0, 0, 0, 0, 0, 116, 31, 211, 14, 39, 147, 69, 212, 141}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 82, 82, 253, 222}, 237}, {{32, 76, 0, 0, 3, 88, 202, 89, 213, 100, 120, 202, 58, 255, 227, 136}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 42, 199, 7, 0, 4, 125}, 237}, {{32, 76, 0, 17, 1, 61, 23, 75, 54, 113, 204, 72, 22, 186, 172, 154}, 237}, {{32, 76, 0, 0, 0, 220, 231, 184, 91, 181, 88, 103, 190, 208, 182, 152}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 251, 235, 4, 81}, 237}, {{32, 76, 0, 0, 0, 0, 48, 43, 52, 153, 82, 253, 140, 90, 77, 37}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 41, 247, 143, 7}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 41, 250, 128, 221, 56, 196}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 109, 20, 57}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 184, 203, 164, 174, 196, 8}, 237}, {{32, 76, 0, 0, 0, 236, 179, 66, 38, 7, 155, 249, 56, 189, 32, 57}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 36, 84, 241, 206}, 237}, {{32, 76, 98, 76, 24, 220, 152, 14, 95, 39, 42, 4, 35, 95, 210, 165}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 253, 86, 174}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 85}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 61, 127, 25}, 237}, {{32, 76, 0, 49, 78, 211, 229, 74, 13, 123, 146, 105, 166, 214, 193, 127}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 186, 36, 87, 99, 187, 190, 65, 51, 248}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 141, 20, 54}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 72, 78, 30, 1, 194, 192, 4, 24}, 237}, {{32, 76, 0, 0, 0, 0, 0, 173, 136, 82, 3, 162, 134, 147, 29, 171}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 15, 194, 209}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 84, 191, 197, 239}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 200, 116, 213}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 10, 206, 36, 169, 13, 194}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 171}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 22, 244, 132, 173, 63, 170, 227}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 174, 234, 77}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 117, 252, 205, 45, 83, 85}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 131, 20}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 235, 208, 250}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 237}, {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 146}, 237}, {{32, 76, 0, 0, 0, 0, 126, 79, 27, 190, 111, 8, 59, 117, 236, 24}, 237}, {{7, 60, 96, 0, 0, 255, 177, 114, 9, 109, 98, 166, 63, 4, 28, 173}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 253, 66, 193, 213, 249, 173, 184, 151}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 73, 78}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 48, 252, 53, 153, 6}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 141, 95, 165, 139, 170, 142}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 135, 143, 135, 128, 68}, 113}, {{7, 60, 96, 0, 140, 180, 196, 185, 30, 71, 18, 44, 198, 170, 68, 252}, 113}, {{7, 60, 96, 85, 66, 194, 245, 37, 188, 229, 63, 211, 139, 51, 215, 38}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 202, 99, 234, 123, 6, 69}, 113}, {{7, 60, 96, 0, 0, 210, 219, 18, 13, 119, 166, 51, 238, 118, 191, 11}, 113}, {{7, 60, 96, 0, 0, 0, 148, 26, 66, 94, 231, 147, 69, 218, 208, 9}, 113}, {{7, 60, 96, 140, 77, 141, 48, 72, 104, 136, 129, 83, 94, 131, 101, 236}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 123, 55, 146, 217, 99}, 113}, {{7, 60, 96, 0, 0, 112, 101, 27, 94, 154, 225, 179, 216, 207, 135, 87}, 113}, {{7, 60, 96, 0, 0, 38, 57, 204, 19, 236, 251, 89, 192, 196, 78, 130}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 233, 247, 212}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 196, 2, 135, 87, 182}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 102, 102}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 235}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 4, 38}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 107, 33}, 113}, {{7, 60, 96, 0, 0, 0, 39, 101, 245, 197, 239, 202, 169, 54, 44, 51}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 175, 136, 88, 85, 38, 105, 1, 128}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 229, 150, 143, 88, 34}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 200, 17, 43, 202, 62, 112}, 113}, {{7, 60, 96, 0, 0, 140, 90, 222, 0, 136, 88, 246, 112, 31, 14, 143}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 58}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 252, 75, 121, 175, 222, 11, 124, 227}, 113}, {{7, 60, 96, 0, 0, 107, 182, 136, 211, 217, 6, 26, 85, 215, 241, 238}, 113}, {{7, 60, 96, 122, 127, 25, 5, 131, 135, 115, 8, 88, 170, 49, 34, 192}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 98, 196, 4, 88, 236, 16, 221, 18}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 141, 247, 88}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 225, 110, 50, 95, 31, 160, 219, 25, 44, 144}, 113}, {{7, 60, 96, 0, 0, 0, 0, 204, 10, 19, 194, 142, 151, 178, 235, 69}, 113}, {{7, 60, 96, 0, 2, 2, 166, 150, 5, 118, 65, 167, 93, 116, 146, 189}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 50, 13, 51}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 190, 252}, 113}, {{7, 60, 96, 0, 0, 109, 53, 145, 30, 144, 127, 31, 189, 45, 6, 182}, 113}, {{7, 60, 96, 0, 68, 106, 69, 206, 239, 17, 74, 229, 52, 188, 178, 59}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 173}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 243, 134}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 235, 246}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 240, 10, 62}, 113}, {{7, 60, 96, 25, 189, 73, 148, 187, 135, 233, 47, 194, 42, 63, 93, 108}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 113}, {{7, 60, 96, 0, 178, 8, 168, 254, 43, 93, 231, 210, 76, 241, 108, 206}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 104, 230, 209, 38, 86, 180, 114, 52}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 195}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 94, 5, 65, 33, 82, 219}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 73, 138, 48, 232, 211, 199, 78, 50, 69}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 51, 199, 254, 75, 248, 218, 64}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 45, 15, 185, 135, 199}, 113}, {{7, 60, 96, 0, 0, 0, 35, 146, 189, 138, 69, 198, 242, 112, 32, 71}, 113}, {{7, 60, 96, 0, 0, 6, 193, 135, 80, 232, 224, 6, 89, 71, 238, 22}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 195, 147, 80, 53, 220, 15, 150, 182}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 134, 32, 181, 236, 224, 30, 113}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 88, 45}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 1}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 17, 240, 187, 210, 149, 4, 11}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 218}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 232, 49, 213, 44, 240}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 205, 161, 205}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 252, 222, 3, 78, 2}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 14, 52, 37, 2, 231}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 68, 125, 247, 0, 79, 248}, 113}, {{7, 60, 96, 0, 0, 0, 243, 81, 81, 139, 238, 56, 62, 5, 0, 48}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 28, 32, 107, 53, 52, 217}, 113}, {{7, 60, 96, 0, 0, 0, 0, 214, 253, 6, 214, 106, 167, 213, 15, 146}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 4, 151, 103, 247, 198, 169, 103}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 132, 194, 196, 127, 88}, 113}, {{7, 60, 96, 0, 0, 221, 120, 106, 217, 221, 152, 11, 147, 10, 244, 109}, 113}, {{7, 60, 96, 0, 0, 0, 0, 214, 238, 203, 44, 9, 59, 103, 147, 229}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 198, 53, 41, 188, 246}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 159, 6}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 16, 180, 181, 99, 248, 21, 183, 20, 0}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 7, 234, 96, 251, 47, 154, 58}, 113}, {{7, 60, 96, 228, 87, 70, 62, 111, 39, 125, 213, 207, 90, 162, 45, 176}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 116, 20, 214, 159, 106, 163, 101}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 4, 116, 11}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 75, 0, 8, 155, 111, 53, 61, 242}, 113}, {{7, 60, 96, 0, 207, 180, 230, 62, 154, 5, 156, 99, 65, 27, 100, 145}, 113}, {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 169}, 113}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 25, 197}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 25, 93}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 116, 117, 114, 139, 44, 231}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 204, 24, 64, 58, 53, 209, 175}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 101, 25, 159, 124, 111, 112, 118}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 185, 119, 19, 59, 159, 104}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 242, 146, 54, 202, 241, 21, 47, 151}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 206, 179, 10}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 111, 211, 116, 114, 155, 97}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 73, 55, 89, 76, 192, 150, 41}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 18, 91, 120}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 73, 144, 248, 134, 10, 201}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 30, 34, 24}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 218, 107, 98, 250, 160}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 203, 6, 133, 108, 182, 137, 234, 35}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 175, 74, 86}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 219, 248}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 107, 4}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 174, 95, 255, 144, 167, 73, 94}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 245, 146, 19, 37, 24, 86}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 58, 211, 51, 249}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 159, 77, 113, 20}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 174, 158}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 139, 182, 143, 215}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 71, 192, 133}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 26, 130, 186, 86, 237, 55, 153, 143}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 19, 243, 224, 225, 51}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 129, 52}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 232, 104}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 89, 217, 121, 37, 33, 96, 178, 66}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 248, 103, 194, 189, 72, 212, 140, 202}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 70, 41, 250, 153, 215, 75, 114, 103}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 100, 179, 154, 134}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 160, 110}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 90, 100, 192}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 100, 223, 39}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 210, 121, 134, 50, 118, 8}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 245, 69, 18, 200, 145}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 28, 250, 252, 120, 192, 215}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 242, 61, 186, 43, 131, 117, 153}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 3, 233, 53, 191}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 63, 65, 127, 218, 114, 183, 47, 144}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 102, 46, 57}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 122, 134, 39}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 25, 172, 184, 91}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 64, 127, 231, 207, 152}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 252, 3, 248, 163, 170, 84, 2}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 155, 170, 31, 44, 246, 177}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 193, 201, 92, 254, 91, 94, 179, 212}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 192, 189, 235, 68, 197, 105}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 62, 101, 10}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 253, 61, 12, 135, 188, 126, 58, 147}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 189, 238, 63, 75, 91, 76}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 23, 165, 135, 209, 27, 47, 145, 122}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 37, 108, 158, 189}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 251, 112, 240, 24}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 245, 126, 90, 32, 137, 108, 246}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 171, 128, 249, 158, 67}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 113, 212, 250, 35, 82, 110, 247, 108}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 88, 237, 231}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 183, 36, 40}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 70, 141, 21, 153, 240}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 56, 125}, 162}, {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 162}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 132}, 225}, {{21, 78, 0, 210, 215, 27, 160, 64, 126, 246, 189, 149, 102, 88, 74, 61}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 166}, 225}, {{21, 78, 0, 245, 15, 76, 71, 44, 94, 34, 48, 128, 119, 21, 171, 88}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 172, 22}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 210, 212, 95, 139}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 239, 195, 217}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 92, 80, 44, 105, 66, 173}, 225}, {{21, 78, 0, 0, 0, 169, 206, 185, 237, 100, 37, 56, 2, 8, 137, 252}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 15, 203, 52, 202}, 225}, {{21, 78, 0, 0, 0, 0, 126, 232, 187, 13, 34, 219, 163, 104, 13, 97}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 225}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 107, 150, 245}, 225}, {{21, 78, 0, 0, 180, 9, 127, 222, 46, 77, 69, 212, 164, 7, 126, 17}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 234}, 225}, {{21, 78, 0, 0, 0, 72, 14, 59, 210, 220, 64, 138, 83, 31, 188, 19}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 125, 149, 75}, 225}, {{21, 78, 0, 0, 0, 0, 151, 230, 214, 145, 180, 12, 38, 212, 148, 32}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 199, 117, 236}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 211, 251, 110}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 202, 194}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 39}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 209, 238, 80, 218}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 90}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 225}, {{21, 78, 0, 0, 0, 0, 146, 48, 53, 91, 9, 69, 239, 93, 107, 255}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 228, 51, 225, 208, 155, 28, 88, 139}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 35, 121, 5, 237, 112, 189, 26, 193}, 225}, {{21, 78, 0, 0, 0, 47, 38, 140, 9, 82, 215, 150, 66, 164, 168, 104}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 248}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 170, 107, 118}, 225}, {{21, 78, 0, 0, 0, 0, 0, 124, 6, 227, 2, 250, 179, 190, 79, 29}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 100, 180, 13, 177, 24, 214, 181}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 159, 118, 175, 222}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 170, 219}, 225}, {{21, 78, 0, 0, 0, 0, 0, 75, 173, 116, 134, 104, 105, 7, 244, 251}, 225}, {{21, 78, 0, 0, 0, 247, 19, 31, 13, 111, 246, 173, 96, 134, 99, 197}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 164, 50, 162, 238, 163, 142}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 223, 128, 131, 1}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 35, 30, 155, 156, 4, 204, 81, 172}, 225}, {{21, 78, 0, 0, 0, 218, 27, 233, 83, 68, 28, 175, 57, 60, 13, 115}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 188, 166, 5, 236, 2, 123, 50}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 4}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 46, 80, 188, 237, 198, 245, 116, 143}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 225}, {{21, 78, 0, 0, 0, 104, 45, 2, 214, 66, 71, 115, 155, 64, 32, 2}, 225}, {{21, 78, 0, 0, 0, 182, 103, 141, 62, 109, 247, 150, 59, 232, 57, 174}, 225}, {{21, 78, 0, 0, 54, 30, 119, 5, 200, 241, 1, 81, 220, 123, 60, 20}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 200, 152, 149}, 225}, {{21, 78, 0, 0, 0, 0, 0, 85, 61, 4, 239, 99, 26, 32, 52, 55}, 225}, {{21, 78, 0, 0, 0, 255, 31, 98, 100, 39, 207, 69, 216, 83, 76, 55}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 171, 44, 92, 245, 12, 213, 71}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 168, 62}, 225}, {{21, 78, 0, 0, 3, 176, 202, 225, 53, 185, 142, 230, 94, 189, 162, 76}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 128, 103, 9}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 171, 253}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 63}, 225}, {{21, 78, 0, 0, 0, 0, 0, 132, 58, 241, 30, 114, 53, 122, 7, 255}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 1, 104, 24, 39, 75, 202, 145, 137, 152, 66}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 86, 6}, 225}, {{21, 78, 0, 0, 0, 0, 0, 255, 151, 140, 151, 53, 172, 1, 59, 230}, 225}, {{21, 78, 0, 0, 56, 15, 65, 112, 112, 194, 16, 218, 170, 117, 149, 99}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 89, 31}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 230}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 219, 225, 219, 202, 49, 203, 194}, 225}, {{21, 78, 0, 0, 0, 0, 0, 21, 32, 3, 78, 207, 145, 180, 163, 24}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 20, 128}, 225}, {{21, 78, 0, 0, 0, 0, 0, 161, 58, 243, 75, 215, 27, 132, 245, 229}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 138, 249, 5, 84, 187, 68, 148, 76}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 127, 251, 40}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 219, 101, 173, 1, 178, 125, 171, 131}, 225}, {{21, 78, 0, 0, 0, 156, 101, 87, 131, 27, 227, 154, 89, 158, 251, 112}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 59, 31, 94, 226}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 30}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 225}, {{21, 78, 0, 0, 0, 0, 5, 158, 222, 23, 74, 150, 230, 87, 89, 208}, 225}, {{21, 78, 0, 0, 0, 98, 89, 140, 121, 171, 114, 91, 134, 13, 67, 183}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 217, 189, 21, 109, 139, 104}, 225}, {{21, 78, 0, 0, 35, 243, 232, 205, 166, 141, 137, 198, 213, 100, 114, 193}, 225}, {{21, 78, 0, 0, 0, 0, 142, 236, 39, 159, 157, 233, 121, 110, 66, 223}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 98, 112}, 225}, {{21, 78, 0, 0, 0, 0, 0, 12, 21, 5, 70, 129, 128, 167, 119, 207}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 14, 134, 140, 15, 8, 253}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 16, 159}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 68, 23, 72, 221, 36, 2, 27, 95}, 225}, {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 53}, 225}, {{21, 78, 0, 110, 12, 172, 13, 160, 208, 168, 44, 80, 111, 153, 10, 168}, 225}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 90, 166, 208, 127}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 228}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 210, 32, 144}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 61}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 220, 215, 129}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 86}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 160}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 202}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 105, 169}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 194, 236}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 242, 12, 96}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 157}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 116, 199}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 109, 64}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 149}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 6, 79, 69, 59}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 118, 205}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 120}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 105, 25}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 10}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 33}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 240, 35}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 224, 153, 105}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 211, 106, 19}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 6, 252, 159, 61}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 45, 231, 77}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 113}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 196}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 200, 191, 235, 142}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 46, 120}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 11, 108, 201}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 161, 18, 126}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 52, 106}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 219}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 121, 187, 38}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 26, 100}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 34, 168, 223}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 254, 168}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 228}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 161, 126, 83}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 44}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 106, 185, 223}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 79, 193}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 238, 227}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 244}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 243, 99, 73}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 170, 163, 15, 30}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 93}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 230}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 65, 214, 90, 70}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 125}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 186, 136, 64, 119}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 135}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 35}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 161, 125, 222, 71}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 76}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 255, 115, 52}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 170, 167, 201}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 14}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 73}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 229, 33, 90}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 17}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 118, 163}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 132, 144}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 176, 7}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 32, 97}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 155}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 104, 112}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 217, 77}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 8, 196}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 121}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 197}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 121}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 166, 166, 235}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 213, 76, 40}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 22, 72, 72}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 210}, {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 23, 234}, 210}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 233, 51, 61}, 34}, {{84, 120, 160, 0, 222, 176, 188, 166, 39, 62, 16, 17, 232, 64, 21, 221}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 33, 58, 139}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 83, 100, 167, 200, 245, 120}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 154}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 245, 127, 61, 109, 243, 17, 168}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 146}, 34}, {{84, 120, 160, 0, 0, 0, 0, 222, 152, 139, 160, 254, 231, 216, 140, 156}, 34}, {{84, 120, 160, 0, 223, 116, 216, 122, 47, 1, 16, 246, 182, 230, 94, 73}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 143, 83, 154, 90, 136, 127}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 200, 44}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 238, 154, 156, 114, 106, 29}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 33, 145, 209}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 65, 100, 144}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 27}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 163, 84, 67, 57, 211, 186, 160, 127}, 34}, {{84, 120, 160, 0, 0, 0, 0, 192, 98, 226, 2, 71, 22, 162, 214, 2}, 34}, {{84, 120, 160, 0, 0, 217, 255, 45, 80, 175, 25, 226, 79, 144, 112, 209}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 199, 26}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 73, 121, 45}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 168, 119, 193, 215, 94, 214, 216}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 21, 28}, 34}, {{84, 120, 160, 0, 186, 171, 97, 125, 243, 209, 3, 50, 224, 37, 156, 4}, 34}, {{84, 120, 160, 0, 0, 0, 247, 34, 242, 133, 196, 83, 123, 66, 158, 28}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 4, 157}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 156, 207, 3, 255, 16, 169, 19}, 34}, {{84, 120, 160, 0, 0, 185, 211, 167, 26, 195, 30, 174, 8, 0, 46, 59}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 74}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 102, 100, 1, 212, 90, 152, 107, 167, 132, 115}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 236, 85, 184, 165, 38, 243}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 158, 142, 174, 54, 14, 200, 142, 171}, 34}, {{84, 120, 160, 0, 0, 0, 15, 191, 228, 64, 197, 186, 116, 162, 174, 59}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 225, 143, 44}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 204, 90}, 34}, {{84, 120, 160, 0, 0, 100, 203, 205, 51, 62, 63, 94, 227, 151, 224, 236}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 95, 213, 127, 174, 232, 227, 25, 42}, 34}, {{84, 120, 160, 0, 0, 0, 197, 91, 114, 21, 184, 240, 22, 82, 154, 120}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 25, 49, 36, 197, 160}, 34}, {{84, 120, 160, 0, 241, 96, 133, 69, 222, 216, 6, 249, 69, 239, 238, 254}, 34}, {{84, 120, 160, 0, 0, 0, 98, 247, 159, 148, 16, 92, 164, 215, 186, 150}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 122, 146, 60}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 146}, 34}, {{84, 120, 160, 0, 0, 99, 213, 59, 217, 75, 239, 23, 167, 186, 109, 147}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 167, 190, 46}, 34}, {{84, 120, 160, 0, 0, 0, 116, 39, 192, 234, 126, 58, 188, 132, 150, 29}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 161, 123, 56, 241, 72, 53}, 34}, {{84, 120, 160, 0, 0, 59, 41, 28, 143, 228, 98, 105, 26, 195, 231, 204}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 194, 229, 179}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 34}, {{84, 120, 160, 0, 0, 0, 174, 129, 83, 107, 202, 65, 235, 83, 177, 210}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 214}, 34}, {{84, 120, 160, 0, 73, 56, 229, 242, 164, 35, 160, 95, 165, 159, 8, 94}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 225, 125, 227, 165, 111}, 34}, {{84, 120, 160, 0, 188, 91, 184, 148, 135, 151, 128, 186, 212, 236, 108, 62}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 68, 207, 197}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 236, 211, 207, 220, 179, 232, 195}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 4, 64, 179, 62, 139, 146, 106}, 34}, {{84, 120, 160, 0, 25, 154, 153, 226, 11, 135, 191, 237, 244, 95, 5, 134}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 106, 172, 123, 25, 28}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 75, 13, 212, 73, 204, 43, 243, 74}, 34}, {{84, 120, 160, 0, 0, 0, 0, 216, 86, 21, 87, 117, 232, 166, 26, 157}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 99}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 97, 45, 242, 216, 194}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 218, 131, 223}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 94}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 234, 188, 234, 154, 80, 8, 0}, 34}, {{84, 120, 160, 0, 0, 0, 0, 248, 5, 221, 19, 131, 227, 11, 54, 160}, 34}, {{84, 120, 160, 0, 0, 0, 0, 67, 199, 66, 53, 149, 23, 46, 253, 92}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 121}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 248, 107, 101, 119, 227}, 34}, {{84, 120, 160, 0, 247, 91, 33, 153, 153, 103, 182, 60, 74, 71, 253, 85}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 253, 129, 93}, 34}, {{84, 120, 160, 0, 0, 0, 0, 174, 253, 49, 190, 78, 230, 129, 159, 46}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{84, 120, 160, 121, 71, 42, 200, 20, 206, 51, 242, 165, 100, 246, 83, 83}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 182, 115, 85, 200, 124, 30, 0}, 34}, {{84, 120, 160, 0, 188, 60, 118, 190, 198, 31, 3, 97, 206, 2, 161, 47}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 204, 86}, 34}, {{84, 120, 160, 0, 0, 0, 249, 131, 199, 133, 44, 69, 242, 14, 4, 207}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 194, 22, 243}, 34}, {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 159, 224, 1, 180, 74, 187}, 34}, {{126, 5, 126, 176, 0, 0, 0, 142, 165, 218, 100, 57, 83, 124, 84, 102}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 130, 212}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 110, 35, 62, 210, 98, 245, 216}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 253, 86, 104, 117, 49, 118, 126, 32, 53}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 249, 25, 69, 145, 151, 234, 116, 5}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 12, 185, 108, 239, 122, 147, 234, 85, 172}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 167, 111, 77, 81, 204}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 163, 253, 239, 251, 34}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 34, 172, 199, 242, 245, 99, 69, 190, 177}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 66, 10}, 224}, {{126, 5, 126, 176, 0, 225, 79, 100, 175, 249, 100, 225, 173, 119, 172, 149}, 224}, {{126, 5, 126, 176, 103, 214, 77, 186, 242, 65, 169, 100, 180, 18, 245, 7}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 179, 210, 4, 156}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 124, 229, 84, 25, 37, 44, 167, 53}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 157, 141, 68, 148, 225, 64, 143}, 224}, {{126, 5, 126, 176, 0, 0, 127, 255, 21, 149, 61, 134, 215, 214, 233, 102}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 156}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 169, 234, 154, 117, 177}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 71, 55, 60, 52, 205, 132, 102, 111}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 202, 86, 98, 52, 143, 237}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 105, 229}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 244, 223}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 190, 126}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 233, 91, 51, 137}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 133, 31, 2, 16}, 224}, {{126, 5, 126, 176, 0, 138, 157, 160, 123, 223, 72, 58, 115, 62, 216, 227}, 224}, {{126, 5, 126, 176, 0, 0, 0, 131, 93, 147, 203, 188, 171, 72, 243, 86}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 92, 142, 44, 128, 45, 119, 222}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 80, 4, 72, 19}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 100, 182, 127, 105}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 226, 201, 61, 195, 15, 234, 126}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 218, 145, 61, 41, 145}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 137, 27, 17, 99, 143, 81}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 184, 180, 244, 20}, 224}, {{126, 5, 126, 176, 0, 221, 66, 184, 66, 211, 135, 16, 90, 94, 20, 116}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 168}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 36, 183, 206, 197, 214, 88}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 102, 97, 223, 157, 157}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 224}, {{126, 5, 126, 176, 0, 0, 142, 239, 237, 183, 203, 139, 87, 203, 71, 189}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 197, 232}, 224}, {{126, 5, 126, 176, 0, 0, 94, 64, 156, 6, 117, 201, 224, 146, 165, 147}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 36, 205, 194, 71, 71, 169, 60}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 209, 201}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 88, 141, 1, 29}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 215, 165, 243, 1, 200, 146, 132}, 224}, {{126, 5, 126, 176, 0, 0, 242, 230, 252, 105, 119, 136, 139, 136, 74, 206}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 224}, {{126, 5, 126, 176, 0, 231, 14, 54, 39, 177, 30, 17, 226, 29, 79, 243}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 172, 103, 112, 177}, 224}, {{126, 5, 126, 176, 0, 0, 113, 122, 180, 104, 87, 156, 174, 56, 37, 95}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 23, 233, 210, 142, 188}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 210, 137, 193, 182, 189}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 195}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 58, 117, 195, 132}, 224}, {{126, 5, 126, 176, 0, 0, 186, 167, 86, 191, 112, 92, 231, 123, 107, 243}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 3}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 245, 46, 10, 254, 143}, 224}, {{126, 5, 126, 176, 1, 1, 89, 73, 245, 75, 147, 205, 166, 229, 74, 48}, 224}, {{126, 5, 126, 176, 0, 0, 0, 88, 9, 225, 176, 105, 199, 80, 190, 64}, 224}, {{126, 5, 126, 176, 0, 0, 29, 128, 178, 196, 122, 242, 18, 66, 26, 21}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 107, 175}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 224}, {{126, 5, 126, 176, 0, 249, 110, 160, 127, 65, 74, 196, 178, 49, 24, 240}, 224}, {{126, 5, 126, 176, 0, 0, 203, 85, 162, 168, 211, 227, 107, 225, 202, 128}, 224}, {{126, 5, 126, 176, 0, 0, 249, 21, 18, 88, 21, 102, 145, 219, 32, 197}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 240, 242, 125, 165}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 236, 191}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 221, 8, 242, 236, 18, 39, 128, 170}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 58}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 45, 60, 132, 66, 171, 104, 116, 133}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 103, 159, 8, 171, 71}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 70, 201, 212, 191, 200, 236, 109}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 192, 226, 24, 225, 122, 111}, 224}, {{126, 5, 126, 176, 0, 151, 245, 171, 17, 75, 136, 111, 187, 211, 170, 28}, 224}, {{126, 5, 126, 176, 0, 0, 64, 34, 8, 111, 28, 201, 29, 147, 185, 131}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 213, 2, 140, 40, 129, 162}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 50, 89, 188, 181, 148, 126, 227, 81}, 224}, {{126, 5, 126, 176, 0, 0, 0, 230, 90, 46, 17, 101, 166, 62, 104, 151}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 31}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 167, 140}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 97, 152, 216, 43, 38, 227, 84}, 224}, {{126, 5, 126, 176, 0, 0, 92, 103, 54, 12, 241, 104, 217, 46, 120, 179}, 224}, {{126, 5, 126, 176, 0, 198, 16, 61, 115, 41, 48, 53, 241, 60, 201, 193}, 224}, {{126, 5, 126, 176, 0, 0, 0, 0, 0, 212, 166, 138, 237, 54, 163, 155}, 224}, {{126, 5, 126, 176, 0, 0, 252, 109, 89, 136, 218, 34, 142, 187, 236, 12}, 224}, {{126, 5, 126, 176, 0, 201, 51, 204, 152, 42, 17, 193, 20, 157, 161, 108}, 224}, {{4, 58, 0, 0, 0, 0, 0, 99, 146, 249, 94, 217, 146, 74, 127, 222}, 143}, {{4, 58, 0, 68, 95, 63, 240, 164, 207, 138, 183, 172, 236, 229, 250, 9}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 61, 215, 106, 137, 201, 27, 11}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 247, 118, 198, 189, 21, 89, 200, 209}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 101, 189, 220, 149, 227, 90}, 143}, {{4, 58, 0, 0, 0, 124, 102, 222, 37, 44, 63, 239, 75, 244, 74, 119}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 47}, 143}, {{4, 58, 0, 0, 47, 99, 169, 245, 253, 208, 223, 171, 147, 94, 150, 234}, 143}, {{4, 58, 0, 0, 0, 34, 43, 227, 170, 6, 206, 227, 46, 155, 96, 67}, 143}, {{4, 58, 0, 224, 97, 23, 234, 52, 98, 6, 27, 181, 67, 96, 138, 228}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 158, 245, 166}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 41, 254, 168}, 143}, {{4, 58, 0, 0, 0, 0, 30, 34, 176, 28, 195, 9, 247, 215, 252, 170}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 119, 19, 52}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 100, 204}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 153, 172, 156, 45, 199, 86}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 247, 142, 192, 131, 137, 69, 205, 249}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 127, 54, 161, 169, 223, 46, 191, 166}, 143}, {{4, 58, 0, 0, 0, 0, 0, 211, 8, 112, 190, 91, 15, 29, 90, 32}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 137, 83, 149, 152, 243, 247}, 143}, {{4, 58, 0, 0, 0, 0, 230, 123, 183, 177, 139, 195, 203, 163, 201, 76}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 189, 203, 209, 202, 91, 244, 102, 169}, 143}, {{4, 58, 0, 166, 119, 59, 141, 157, 86, 133, 254, 201, 2, 144, 179, 243}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 78, 247, 90}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{4, 58, 0, 0, 0, 0, 118, 203, 108, 217, 98, 186, 11, 147, 6, 100}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 104, 115}, 143}, {{4, 58, 0, 0, 149, 119, 21, 135, 141, 221, 69, 104, 108, 131, 220, 103}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 235, 103, 103}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 255, 143, 59, 195, 8, 184, 67}, 143}, {{4, 58, 0, 0, 0, 0, 0, 234, 219, 50, 138, 97, 220, 206, 187, 24}, 143}, {{4, 58, 0, 0, 0, 0, 0, 222, 211, 222, 217, 251, 66, 47, 239, 128}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 118, 40, 189, 4, 45, 176}, 143}, {{4, 58, 0, 0, 0, 0, 0, 146, 133, 44, 103, 109, 213, 153, 68, 80}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 241, 186, 118, 82}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 25, 144, 87, 139}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 242, 85, 177, 227, 148, 242, 135, 197}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 184, 172, 164, 226, 199, 237}, 143}, {{4, 58, 0, 0, 0, 59, 57, 116, 11, 188, 89, 95, 126, 209, 47, 44}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 73, 236, 44, 124}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 208, 68, 43, 37, 72, 209, 82, 164}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 205, 83, 223, 23, 127, 61, 45}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 133, 198, 140, 121, 15, 80, 47}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 189, 183, 114, 253}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 17, 23}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 181, 50, 232, 236, 82, 218, 216, 160}, 143}, {{4, 58, 0, 0, 211, 48, 182, 132, 121, 232, 125, 211, 201, 116, 46, 149}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 166}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 88, 146, 37, 28}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 226, 229, 40, 150}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{4, 58, 0, 0, 0, 0, 156, 254, 25, 64, 148, 134, 172, 179, 243, 212}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 179, 55, 206, 154, 8, 38, 132, 50}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 9, 225}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 165, 86}, 143}, {{4, 58, 0, 0, 0, 198, 31, 24, 123, 97, 232, 179, 83, 126, 32, 187}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 171, 171, 147, 72, 59, 67, 46, 82}, 143}, {{4, 58, 0, 0, 10, 52, 50, 224, 162, 57, 17, 233, 156, 211, 227, 156}, 143}, {{4, 58, 0, 0, 49, 104, 207, 255, 251, 23, 60, 235, 167, 207, 121, 142}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 160, 94}, 143}, {{4, 58, 0, 0, 239, 242, 45, 174, 41, 178, 62, 172, 189, 67, 67, 239}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 96, 17, 120, 131, 165, 123}, 143}, {{4, 58, 0, 0, 0, 99, 38, 9, 160, 144, 129, 161, 5, 241, 126, 196}, 143}, {{4, 58, 0, 0, 0, 0, 0, 25, 147, 205, 96, 163, 138, 233, 43, 130}, 143}, {{4, 58, 0, 169, 231, 62, 114, 198, 111, 228, 74, 106, 23, 239, 128, 169}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 82, 11}, 143}, {{4, 58, 0, 0, 0, 0, 120, 74, 162, 25, 211, 80, 175, 129, 52, 83}, 143}, {{4, 58, 0, 227, 215, 179, 209, 11, 217, 141, 171, 207, 82, 67, 221, 98}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 46, 241, 46, 149}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 33, 236, 180}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 22, 15, 77, 69, 238, 0, 90, 126}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 186, 82, 23}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 6, 66, 32, 39, 66, 156, 51, 113}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 143}, {{4, 58, 0, 0, 8, 116, 197, 251, 151, 240, 75, 246, 0, 187, 92, 242}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 71, 203}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 12, 31, 228, 116, 90, 225}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 205}, 143}, {{4, 58, 0, 23, 212, 142, 82, 235, 165, 209, 143, 168, 4, 48, 45, 46}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 76, 253, 203, 236, 32, 209}, 143}, {{4, 58, 0, 0, 0, 0, 55, 222, 16, 66, 5, 7, 74, 250, 129, 245}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 143}, {{4, 58, 0, 0, 0, 0, 93, 149, 30, 119, 187, 222, 42, 165, 146, 94}, 143}, {{4, 58, 0, 0, 0, 191, 59, 88, 243, 161, 135, 146, 84, 198, 37, 154}, 143}, {{4, 58, 0, 0, 8, 241, 233, 178, 226, 158, 248, 54, 61, 43, 157, 153}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 26, 15, 66, 93, 253, 243}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 29}, 143}, {{4, 58, 0, 96, 41, 129, 99, 252, 210, 22, 167, 110, 130, 144, 113, 229}, 143}, {{4, 58, 0, 248, 204, 103, 111, 142, 32, 190, 243, 231, 123, 30, 151, 46}, 143}, {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 184, 88, 50, 22, 216, 187}, 143}, {{4, 58, 0, 0, 0, 0, 0, 55, 227, 229, 165, 32, 170, 187, 122, 177}, 143}, {{4, 58, 0, 0, 0, 0, 143, 160, 182, 115, 43, 85, 128, 169, 253, 239}, 143}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 176, 129, 10, 64}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 18, 182, 3}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 99, 202, 246, 145}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 91, 92, 205, 6, 21, 173}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 115, 177, 47, 250}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 65, 179, 234, 19, 127, 215}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 250, 221}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 180, 171, 40, 4}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 145, 197}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 79, 81, 64}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 8, 129, 152}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 198, 120, 171, 234, 32}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 96, 208, 86, 250, 64, 15, 188}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 92, 88, 145}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 235, 146, 45, 211}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 110, 146, 136, 153, 222, 185}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 55, 241, 217}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 170, 224}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 57, 118, 155, 25, 156, 250}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 114, 156, 39}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 244, 105}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 101, 0, 254}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 157}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 108, 208, 202}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 11, 246, 29, 242}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 224, 97, 39}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 153, 205, 101, 213, 177, 229}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 175, 18, 215}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 60, 180, 117, 191, 240}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 124, 13, 134}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 153, 156, 173, 234}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 25, 32, 111, 99, 30, 246}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 151, 234, 3, 42, 33, 173, 76}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 6}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 174, 121, 161, 100}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 178}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 16, 143}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 52, 25, 198, 1, 201}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 238}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 220, 52, 147, 79, 62, 116, 42}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 244, 11, 176, 47}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 40, 222, 106, 32, 99}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 37, 209, 181}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 190, 16, 86, 104}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 145, 9, 125}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 164, 69, 154, 229}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 74, 220, 230, 242, 77}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 109, 17}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 76, 241, 159, 230, 10}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 79, 69, 4, 109, 206, 9}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 195, 202, 47, 20}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 113}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 176, 77, 203, 210, 146}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 93, 71, 200, 209}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 116, 106, 23, 192, 91}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 1, 5, 177, 205, 29}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 22, 45, 15}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 212, 185, 63, 19}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 89, 208, 10, 159}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 49}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 71, 173, 12, 32, 123, 74}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 255, 60, 214, 32, 174, 49, 82}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 214, 55, 209}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 209, 173}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 25, 161, 227, 193, 166}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 157, 93, 211}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 81, 106, 62, 50, 245, 225}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 242, 208, 68, 181, 191, 247, 223}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 103, 78, 198}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 35}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 29, 180, 9, 152, 241, 120}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 207, 116, 217, 126}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 179}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 129}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 243, 76, 181, 168, 59, 4}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 30, 130, 128, 75, 246, 149}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 160, 194, 152, 12, 17, 24}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 7, 12}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 186, 205, 11}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 163, 152, 133, 219}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 215, 30}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 130}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 139}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 55, 100, 127, 116}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 196}, 216}, {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 156, 79, 54, 53}, 216}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 239}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 251}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 147}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 219}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 90}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 112}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 11}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 71}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 214}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 145}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 97}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 194, 116}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 162}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 28, 178}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 114}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 80}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 149}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 210}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 93}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 93}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 244}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 169}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 70}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 41}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 49}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 217}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 90}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 254}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 155}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 33}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 251, 135}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 84}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 103}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 7}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 35, 90}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 102, 79}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 58}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 116}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 178}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 119}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 165}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 112}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 86}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 206}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 51}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 220}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 126}, 54}, {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 157}, 54}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 89, 153, 230}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 23, 170}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 223, 187, 10}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 177, 154, 135, 238, 109, 241, 88}, 35}, {{223, 0, 0, 0, 0, 139, 207, 127, 12, 230, 155, 192, 108, 77, 232, 74}, 35}, {{223, 0, 0, 0, 0, 0, 173, 206, 148, 12, 127, 244, 14, 198, 64, 188}, 35}, {{223, 0, 0, 0, 0, 32, 145, 60, 230, 177, 191, 249, 42, 147, 207, 149}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 106, 132}, 35}, {{223, 0, 0, 0, 136, 243, 66, 252, 36, 29, 85, 154, 164, 136, 249, 41}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 144}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 182}, 35}, {{223, 0, 151, 27, 224, 23, 197, 224, 97, 7, 185, 82, 159, 204, 80, 7}, 35}, {{223, 0, 148, 57, 106, 254, 53, 149, 40, 230, 28, 194, 219, 4, 99, 111}, 35}, {{223, 0, 0, 0, 0, 0, 61, 126, 130, 230, 179, 155, 173, 171, 158, 83}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 34, 231, 36, 92, 111, 116, 46}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 181, 178, 6, 195, 244, 95, 22, 74}, 35}, {{223, 0, 0, 0, 0, 0, 165, 216, 165, 207, 108, 4, 11, 237, 97, 7}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 35}, {{223, 0, 0, 0, 0, 0, 0, 44, 168, 218, 114, 115, 167, 69, 184, 25}, 35}, {{223, 0, 0, 0, 0, 0, 228, 196, 150, 16, 96, 55, 116, 127, 174, 103}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 162, 219, 80}, 35}, {{223, 0, 67, 21, 181, 147, 133, 46, 171, 23, 87, 140, 174, 89, 162, 77}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 248, 95, 208, 137}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 207, 200, 58, 154, 212, 207, 59, 69}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 212, 89, 125, 47, 111, 21, 89, 135}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 47, 179, 175}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 19, 158, 97, 152}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 41, 99, 15, 238, 93, 66, 41, 75}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 44, 27, 95}, 35}, {{223, 0, 0, 64, 171, 114, 13, 101, 178, 187, 76, 25, 81, 219, 36, 49}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 82, 212, 207, 255}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 80, 60}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 226, 219, 148, 82, 125, 220, 16, 223}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 66}, 35}, {{223, 0, 92, 175, 102, 196, 241, 12, 103, 88, 179, 138, 84, 128, 22, 198}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 230, 219, 139}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 244, 58, 212, 239, 130, 17, 245, 175}, 35}, {{223, 0, 0, 177, 175, 104, 69, 39, 155, 235, 2, 73, 168, 221, 213, 4}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 203, 58, 46, 198, 153, 255, 183, 93}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 10, 163, 24, 69, 99}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 142, 140, 129, 234, 70, 36, 128, 135}, 35}, {{223, 0, 0, 0, 0, 0, 120, 106, 137, 119, 161, 82, 113, 180, 79, 55}, 35}, {{223, 0, 0, 0, 0, 0, 0, 135, 249, 88, 48, 26, 139, 45, 166, 174}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 16, 245, 195}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 177, 193, 222}, 35}, {{223, 0, 0, 28, 238, 81, 118, 69, 119, 73, 219, 1, 118, 209, 223, 238}, 35}, {{223, 0, 0, 0, 0, 88, 124, 187, 118, 99, 110, 65, 85, 201, 89, 129}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 157, 180, 6, 134}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 24, 8}, 35}, {{223, 0, 0, 0, 224, 109, 137, 82, 162, 94, 114, 108, 242, 201, 104, 6}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 1, 6, 179, 225, 110}, 35}, {{223, 0, 0, 0, 25, 98, 123, 34, 208, 103, 23, 5, 58, 74, 61, 191}, 35}, {{223, 0, 0, 0, 236, 157, 134, 202, 119, 115, 215, 23, 146, 14, 85, 240}, 35}, {{223, 0, 0, 0, 0, 0, 0, 97, 83, 49, 124, 80, 222, 137, 65, 89}, 35}, {{223, 0, 0, 0, 0, 0, 0, 252, 21, 85, 158, 117, 30, 127, 36, 172}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 124, 50, 120, 95, 94}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 35}, {{223, 0, 0, 49, 48, 140, 131, 9, 34, 200, 60, 212, 0, 67, 185, 92}, 35}, {{223, 0, 0, 0, 93, 189, 128, 20, 53, 163, 149, 6, 131, 49, 0, 51}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 204, 11, 139, 14, 108, 90, 160}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 228, 40, 175}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 248, 49, 221, 236, 79}, 35}, {{223, 0, 239, 255, 187, 241, 27, 155, 14, 222, 229, 63, 114, 6, 127, 6}, 35}, {{223, 0, 0, 0, 0, 0, 165, 81, 48, 112, 116, 124, 91, 252, 250, 133}, 35}, {{223, 0, 0, 115, 129, 183, 221, 219, 216, 145, 237, 77, 94, 94, 195, 17}, 35}, {{223, 0, 0, 0, 105, 218, 82, 154, 60, 85, 1, 144, 253, 19, 174, 86}, 35}, {{223, 0, 0, 0, 0, 0, 100, 220, 244, 111, 142, 196, 13, 157, 120, 227}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 34, 1, 221, 73, 47, 228, 5, 177}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 252, 229, 252}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 224, 223, 77, 217}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 205, 178}, 35}, {{223, 0, 0, 144, 64, 234, 219, 141, 216, 4, 228, 147, 168, 235, 30, 187}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 63, 178, 46}, 35}, {{223, 0, 0, 0, 0, 0, 0, 73, 174, 133, 162, 47, 78, 134, 172, 160}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 20, 95, 60, 7}, 35}, {{223, 0, 201, 70, 157, 38, 48, 100, 176, 124, 105, 97, 52, 125, 18, 91}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 131, 247, 174, 110, 97, 182, 188, 28}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 64, 153}, 35}, {{223, 0, 0, 229, 231, 97, 222, 44, 60, 38, 4, 21, 199, 48, 34, 120}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 213}, 35}, {{223, 0, 0, 101, 35, 182, 62, 68, 93, 244, 203, 211, 47, 167, 34, 95}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 38, 22, 172, 58, 246, 77, 227}, 35}, {{223, 0, 0, 0, 0, 0, 0, 102, 123, 105, 170, 208, 97, 218, 208, 133}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 174, 200}, 35}, {{223, 0, 138, 13, 166, 190, 160, 83, 217, 90, 197, 196, 154, 1, 110, 12}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 7}, 35}, {{223, 0, 241, 108, 116, 250, 112, 19, 145, 252, 250, 144, 192, 91, 168, 32}, 35}, {{223, 0, 0, 0, 179, 136, 223, 119, 215, 199, 76, 21, 177, 11, 254, 81}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 242, 219, 96, 225, 224}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 126}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 177}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 90, 222, 176, 201, 6}, 35}, {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 151}, 35}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 211}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 83}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 194}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 199}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 144}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 138}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 79}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 79}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 54}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 230}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 70, 100, 146, 61, 146, 46}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 212, 169}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 47, 213, 1}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 255, 121, 241, 116, 74, 38, 104, 138}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 234}, {{1, 137, 53, 36, 210, 184, 0, 178, 206, 135, 177, 100, 236, 60, 90, 171}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 13, 170, 43, 27, 13, 202}, 234}, {{1, 137, 53, 36, 210, 184, 0, 13, 43, 169, 109, 95, 217, 219, 149, 33}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 252, 39}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 144, 255}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 130, 163, 146, 223}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 148, 161, 0, 184, 120, 212, 226, 248}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 99, 252, 250, 134, 2, 181, 153}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 51, 91, 38, 79}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 219, 151, 157}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 66, 21, 69}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 196, 230, 79, 17}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 27, 77, 61, 230}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 82, 78, 69, 239, 54, 234, 179}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 57, 112, 251, 29, 247, 36, 38, 108, 8}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 255, 33, 33, 64, 255}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 158, 130, 193, 231, 18, 177}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 35, 228, 115, 118, 200, 144, 74, 22}, 234}, {{1, 137, 53, 36, 210, 184, 0, 82, 187, 55, 249, 154, 192, 118, 54, 172}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 234}, {{1, 137, 53, 36, 210, 184, 22, 196, 109, 59, 71, 164, 100, 43, 126, 228}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 161, 154}, 234}, {{1, 137, 53, 36, 210, 184, 0, 236, 147, 128, 188, 206, 58, 231, 247, 22}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 119, 165, 180, 53, 57, 236}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 23, 11, 162, 112, 120, 58}, 234}, {{1, 137, 53, 36, 210, 184, 0, 45, 66, 50, 42, 203, 96, 203, 208, 78}, 234}, {{1, 137, 53, 36, 210, 184, 0, 95, 150, 50, 83, 89, 99, 198, 75, 61}, 234}, {{1, 137, 53, 36, 210, 184, 0, 170, 25, 149, 180, 62, 247, 158, 54, 90}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 210, 150, 44, 81, 38, 102, 61}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 209, 205, 215}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 200, 17, 131, 99}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 193, 201, 24, 94, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 162, 150, 249, 8}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 97, 41, 67, 76, 145, 201, 144, 55}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 201, 7, 33, 199, 199, 110}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 192, 120, 190, 45, 143, 90, 229, 31}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 88, 20, 142, 247, 132}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 5, 40}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 10, 46, 118, 221, 217, 215}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 201, 124, 187, 23}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 148, 173}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 6, 18, 58, 243, 166}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 71, 238, 99, 241}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 101, 98, 70, 89, 48}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 80, 163, 24, 70, 166}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 69, 147, 34, 91, 217, 237, 104, 196}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 234}, {{1, 137, 53, 36, 210, 184, 0, 92, 81, 28, 140, 118, 124, 97, 55, 36}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 95, 186, 24}, 234}, {{1, 137, 53, 36, 210, 184, 0, 12, 172, 178, 129, 234, 50, 123, 216, 236}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 234}, {{1, 137, 53, 36, 210, 184, 0, 164, 248, 224, 210, 233, 248, 175, 39, 95}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 28, 237}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 20, 82, 157, 190, 113, 237}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 190, 223, 72, 0, 50, 65}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 125, 157, 51, 240}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 10, 140, 230, 240, 237}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 35, 34, 201, 154, 66, 249, 242}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 120, 127, 70, 116, 71, 46, 110}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 167, 89, 250, 109, 198, 227, 193, 77, 250, 202}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 82, 251, 132, 187, 20}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 225, 34, 131, 134}, 234}, {{1, 137, 53, 36, 210, 184, 219, 217, 108, 133, 227, 32, 40, 192, 173, 252}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 24, 114, 134, 116, 16}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 135, 226, 93, 115, 244, 15, 130, 11}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 241, 178, 176, 144, 78}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 179, 97}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 255, 16, 89, 87, 100, 64, 151, 178}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 176, 250, 69, 107, 59}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 255, 23}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 79, 39, 175, 196, 238, 67, 30, 95}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 143, 244, 8, 144, 157, 0, 191, 247}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 117, 243, 3, 166, 74, 220, 63, 83}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 216, 28, 159, 48, 208, 121}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 234}, {{1, 137, 53, 36, 210, 184, 0, 195, 99, 253, 175, 63, 132, 109, 164, 7}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 1, 42, 35, 54, 212}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 187, 211, 188, 59, 144, 156}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 51, 0, 102}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 203, 66, 162, 0}, 234}, {{1, 137, 53, 36, 210, 184, 0, 0, 196, 216, 136, 141, 33, 130, 230, 184}, 234}, {{1, 137, 53, 36, 210, 184, 0, 153, 94, 70, 149, 97, 179, 240, 107, 252}, 234}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 160}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 22}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 168}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 152}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 204}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 70}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 71}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 32}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 154}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 62}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 124}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 153}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 184}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 143}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 199}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 163}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 47}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 232}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 160}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 89}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 4}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 144}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 238}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 110}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 19}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 243}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 237}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 225}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 144}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 198}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 30}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 223}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 27}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 5}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 165}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 33}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 212}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 180}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 197}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 70}, {{105, 73, 57, 108, 0, 86, 189, 37, 59, 121, 81, 225, 119, 248, 197, 15}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 243, 117, 191, 113, 159, 108}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 106}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 160, 122, 163, 38, 58, 69, 188, 198}, 246}, {{105, 73, 57, 108, 0, 0, 0, 36, 207, 231, 151, 171, 87, 227, 165, 41}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 140, 151, 244, 67}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 228}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 26, 240, 37, 3, 253, 228}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 144, 46, 10, 248, 71, 237, 122}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 33}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 97, 138, 199, 153, 172, 4, 218}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 81, 90, 223, 251}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 128, 1, 9, 121, 150}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 189, 120, 244, 36, 189, 218, 63, 122}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 222, 199, 205, 246, 10}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 108, 92, 159, 4, 230, 76}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 190, 178, 77, 191, 67, 36, 128}, 246}, {{105, 73, 57, 108, 0, 0, 164, 172, 159, 232, 188, 238, 236, 135, 253, 124}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 232, 247, 37, 156, 201, 85}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 230, 170, 125, 179, 32, 140, 107, 106, 148, 24, 103}, 246}, {{105, 73, 57, 108, 0, 0, 0, 212, 122, 222, 20, 31, 216, 156, 0, 89}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 94, 19, 73, 193, 153}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 64, 185, 62, 23, 110, 36, 217, 141}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 104, 126, 179, 142, 248, 35}, 246}, {{105, 73, 57, 108, 0, 0, 238, 248, 62, 156, 198, 193, 199, 84, 246, 12}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 191, 35, 67, 199, 196, 95, 151, 146}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 147, 220, 236, 163, 207}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 248, 247}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 232, 161}, 246}, {{105, 73, 57, 108, 0, 104, 84, 65, 190, 62, 137, 161, 213, 171, 173, 233}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 108, 74, 31, 40, 52}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 127}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 248, 170, 68, 218, 128}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 213, 107, 212, 24, 46}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 95, 106, 196, 76, 175}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 6, 197, 84, 22}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 59, 9}, 246}, {{105, 73, 57, 108, 0, 0, 0, 113, 184, 199, 54, 234, 89, 253, 167, 166}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 58, 1, 149, 125, 94, 92, 38, 94}, 246}, {{105, 73, 57, 108, 0, 0, 0, 17, 162, 95, 194, 38, 161, 43, 143, 3}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 165, 119, 67, 50, 218, 160, 170}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 157, 33}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 211, 33, 237, 220, 30, 242, 199}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 248, 215, 148, 110}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 246}, {{105, 73, 57, 108, 0, 0, 0, 193, 66, 237, 251, 151, 131, 125, 204, 164}, 246}, {{105, 73, 57, 108, 0, 0, 75, 83, 51, 136, 248, 46, 67, 201, 166, 153}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 38, 222, 213, 30}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 44, 28}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 137}, 246}, {{105, 73, 57, 108, 0, 0, 0, 63, 161, 213, 72, 100, 68, 50, 188, 100}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 125, 144, 195, 25, 134, 16, 116, 21}, 246}, {{105, 73, 57, 108, 0, 0, 235, 167, 70, 222, 71, 187, 241, 126, 66, 24}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 181, 2, 112, 54, 94, 130, 151}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 171, 26, 192, 88}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 218, 82, 202, 13, 5}, 246}, {{105, 73, 57, 108, 0, 0, 114, 180, 67, 105, 25, 209, 149, 159, 89, 139}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 83, 31, 9, 197, 39, 141, 250}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 11, 100}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 200, 33, 18, 169, 85, 96}, 246}, {{105, 73, 57, 108, 0, 0, 192, 189, 210, 223, 183, 177, 191, 58, 84, 64}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 232, 186, 103, 103, 221, 153, 157, 147}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 164, 82, 248, 56, 217}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 104, 173, 229, 59, 234, 117, 121}, 246}, {{105, 73, 57, 108, 0, 0, 76, 214, 103, 138, 89, 139, 195, 90, 40, 197}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 246}, {{105, 73, 57, 108, 0, 0, 0, 142, 239, 4, 135, 219, 28, 25, 56, 137}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 70, 128}, 246}, {{105, 73, 57, 108, 0, 0, 0, 54, 138, 20, 12, 98, 252, 235, 8, 255}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 19, 70, 233, 62, 222, 38, 4, 226}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 254, 146, 92, 57, 235, 21, 90, 86}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 2}, 246}, {{105, 73, 57, 108, 0, 85, 78, 151, 178, 97, 233, 138, 188, 166, 212, 109}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 202, 63, 114, 162}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 239, 103}, 246}, {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 246}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 217}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 201}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 49}, {{110, 77, 0, 0, 0, 0, 0, 56, 169, 140, 174, 82, 161, 141, 9, 155}, 49}, {{110, 77, 0, 0, 0, 0, 0, 250, 184, 160, 179, 5, 223, 231, 185, 241}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 49}, {{110, 77, 0, 0, 0, 0, 0, 163, 132, 19, 175, 251, 255, 249, 137, 126}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 240, 110}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 229, 185}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 48, 144, 112, 50, 17, 144, 166}, 49}, {{110, 77, 0, 0, 0, 0, 0, 22, 188, 202, 109, 69, 72, 242, 121, 212}, 49}, {{110, 77, 0, 0, 0, 159, 45, 40, 37, 242, 122, 125, 162, 229, 207, 152}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 36}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 54, 184, 194, 89, 132, 55}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 137, 79, 194, 145, 36, 202}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 73, 109, 236}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 173, 254, 137, 54, 63, 164, 151, 13}, 49}, {{110, 77, 0, 0, 5, 114, 131, 136, 33, 110, 111, 54, 35, 81, 230, 52}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 30, 133, 152, 226, 77, 244, 198, 107}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 185, 145, 20}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 53}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 147, 212, 195, 184, 129, 187}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 75, 183, 209, 32, 192, 198, 58}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 229, 191, 83, 176}, 49}, {{110, 77, 0, 0, 0, 126, 7, 163, 179, 116, 166, 23, 228, 123, 207, 39}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 51, 126, 42, 99, 20, 227, 176, 193}, 49}, {{110, 77, 0, 0, 0, 0, 0, 206, 222, 10, 166, 177, 129, 161, 215, 93}, 49}, {{110, 77, 0, 0, 0, 38, 49, 70, 90, 27, 120, 6, 150, 88, 3, 244}, 49}, {{110, 77, 0, 0, 54, 166, 205, 20, 199, 62, 130, 68, 177, 19, 70, 3}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 57}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 23, 88}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 230, 75}, 49}, {{110, 77, 0, 0, 0, 0, 0, 253, 1, 82, 1, 179, 159, 49, 113, 169}, 49}, {{110, 77, 0, 0, 0, 175, 39, 118, 217, 182, 80, 159, 43, 244, 104, 162}, 49}, {{110, 77, 0, 0, 0, 0, 183, 152, 177, 184, 92, 171, 233, 94, 29, 96}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 185}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 49}, {{110, 77, 0, 0, 0, 0, 0, 140, 226, 206, 67, 106, 96, 151, 106, 106}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 49}, {{110, 77, 0, 0, 0, 0, 0, 201, 33, 135, 207, 202, 252, 216, 204, 233}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 48, 50}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 108, 226, 21, 91, 219, 127, 243}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 12}, 49}, {{110, 77, 0, 160, 200, 101, 175, 139, 19, 68, 174, 125, 33, 220, 130, 89}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 9, 226, 191}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 68, 226}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 93, 250, 95}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 204, 20, 166}, 49}, {{110, 77, 0, 9, 43, 250, 226, 44, 152, 132, 114, 230, 209, 220, 37, 236}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 217}, 49}, {{110, 77, 0, 0, 0, 227, 85, 144, 20, 72, 66, 29, 50, 221, 194, 35}, 49}, {{110, 77, 0, 0, 0, 0, 0, 138, 15, 16, 22, 231, 98, 119, 86, 42}, 49}, {{110, 77, 0, 0, 0, 13, 189, 11, 135, 238, 45, 225, 128, 15, 137, 164}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 196, 73, 222, 48, 120, 208}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 0, 0, 0, 0, 131, 181, 143, 237, 59, 229, 177, 166, 189}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 246, 128, 155}, 49}, {{110, 77, 0, 0, 0, 0, 0, 66, 242, 219, 21, 213, 218, 200, 238, 65}, 49}, {{110, 77, 0, 0, 0, 0, 224, 234, 146, 149, 127, 185, 247, 109, 249, 6}, 49}, {{110, 77, 0, 0, 0, 0, 0, 178, 253, 19, 77, 243, 136, 139, 213, 212}, 49}, {{110, 77, 0, 0, 0, 0, 156, 164, 114, 29, 234, 122, 194, 160, 247, 196}, 49}, {{110, 77, 0, 11, 45, 142, 230, 246, 45, 228, 22, 148, 248, 245, 110, 80}, 49}, {{110, 77, 0, 9, 227, 36, 239, 64, 155, 202, 2, 194, 10, 91, 155, 150}, 49}, {{110, 77, 0, 7, 147, 22, 111, 176, 96, 221, 27, 128, 37, 206, 194, 234}, 49}, {{110, 77, 0, 0, 0, 0, 0, 208, 240, 76, 20, 25, 70, 245, 4, 196}, 49}, {{110, 77, 0, 0, 0, 0, 34, 216, 84, 131, 243, 6, 143, 44, 23, 213}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 95, 222, 196}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 112}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 182, 159, 244, 216, 211, 145, 198, 203, 179, 174, 194, 154, 146}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 51, 207, 121, 47, 250, 200, 17}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 190, 137, 10}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 103, 13, 37, 37, 29, 170, 163}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 94, 118, 114, 169, 70, 143, 34}, 49}, {{110, 77, 0, 0, 0, 0, 241, 97, 70, 128, 27, 10, 171, 140, 204, 236}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 59, 248}, 49}, {{110, 77, 0, 0, 122, 123, 27, 225, 90, 189, 230, 246, 154, 158, 224, 178}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 2}, 49}, {{110, 77, 0, 0, 0, 0, 0, 156, 121, 44, 236, 152, 155, 242, 244, 12}, 49}, {{110, 77, 0, 0, 0, 70, 89, 191, 69, 116, 225, 168, 220, 204, 70, 194}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 58, 180, 48}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 0, 0, 0, 0, 235, 61, 130, 96, 183, 20, 197, 181, 202}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 136, 189, 223}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 174, 5, 43}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 81}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 101, 114, 134, 246, 129, 183, 28, 67, 116, 10, 246, 163, 246}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 127, 238, 133, 98, 111, 71, 51, 183}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 55, 85, 13, 112}, 49}, {{110, 77, 0, 174, 150, 162, 217, 20, 102, 40, 90, 130, 133, 30, 74, 90}, 49}, {{110, 77, 0, 0, 0, 0, 40, 177, 27, 194, 57, 192, 24, 163, 106, 120}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 172, 15, 188}, 49}, {{110, 77, 0, 74, 127, 85, 229, 89, 128, 218, 70, 81, 189, 53, 187, 164}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 93, 57, 159, 241, 239, 232, 79, 163}, 49}, {{110, 77, 0, 0, 252, 121, 254, 40, 227, 111, 156, 27, 17, 237, 178, 109}, 49}, {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 151, 39, 200, 113}, 49}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 22, 208, 181, 253, 62, 1, 217, 140}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 222, 158}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 83, 70, 245, 135}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 24, 62}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 88, 92, 179}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 76, 106, 217, 206}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 249, 249, 48, 33, 35, 251}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 205, 130, 89, 40, 89, 188, 75}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 136, 203, 119, 207}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 200, 13, 145, 183, 166, 105}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 186, 251}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 165, 90, 124, 76, 40}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 123, 129, 182, 232, 88}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 217, 209, 224, 57, 238, 72, 90}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 27, 185, 54, 229, 204}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 196, 154, 45, 83}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 129, 220, 206, 113, 117, 143, 101}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 255, 112}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 244, 149, 129, 227}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 143, 209, 8, 87, 161, 226, 229}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 115, 76, 46, 94, 182, 134}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 131, 232, 1, 133, 11, 52, 175, 98}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 164, 148, 12, 118, 155}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 4, 131, 75, 46, 71, 25, 191}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 114, 201, 193, 72, 63, 177, 184, 7}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 38, 180, 67, 49, 208, 188}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 208, 149, 172, 199, 242, 38, 18}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 70, 112}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 218, 142, 180, 144}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 70, 168, 235, 187, 159, 2, 22, 147}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 155, 175}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 215, 74}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 106, 246, 181, 247, 120}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 230, 17, 95, 203, 200, 247, 40}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 198, 160, 94, 154, 128, 222, 251}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 196, 168, 169, 79, 45, 150, 7, 242}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 163, 109, 148}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 234, 254, 41}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 101, 186, 157, 226, 155}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 47, 135, 66, 239, 133, 62}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 160, 129}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 179, 148, 244, 178, 162, 38, 238}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 131, 197, 165, 30, 179, 78}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 126, 44, 78, 229}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 77}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 2, 30, 170, 136}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 188, 57, 37, 186}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 50, 0, 85}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 204, 28, 136, 198}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 40, 127, 228}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 2, 72, 181, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 41, 160, 144, 60, 214}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 99, 43, 209, 163, 237, 232, 68}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 114, 187, 188, 197}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 94, 36, 150}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 61, 86, 215, 109, 71}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 138, 132, 95, 251}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 150, 239, 101, 182}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 192, 9, 45}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 72, 83, 119}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 63, 108, 39, 162, 141, 129, 53, 77}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 79, 25, 159, 248, 121, 28}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 171, 98}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 176, 86, 212, 228, 216, 140, 114, 101}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 185, 241, 52, 175}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 91, 37, 56}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 245, 81, 16, 23, 186, 30, 250, 116}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 77, 9, 228, 232, 250}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 71, 106}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 20, 186, 178, 44, 185}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 219, 192, 162}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 74, 209, 123, 40, 252, 107, 246, 233}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 194, 138, 235, 100, 117, 170}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 245, 14, 190, 178, 114, 248, 70, 74}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 111, 176, 48, 155, 243, 212}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 84, 147, 171, 121, 42, 214, 15, 41}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 144, 181, 136, 200, 93}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 206, 189, 25}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 187, 102}, 2}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 26, 204, 96, 207, 129, 200, 101}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 66, 151, 48, 139}, 64}, {{81, 189, 220, 168, 192, 0, 247, 58, 49, 34, 85, 100, 169, 81, 96, 83}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 64}, {{81, 189, 220, 168, 192, 254, 236, 18, 182, 5, 191, 173, 2, 125, 200, 214}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 148, 217, 163, 229, 153, 81, 252}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 245, 247, 195, 218, 154}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 47, 163, 155, 83, 194, 130, 136, 17}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 36, 203, 178, 147, 146, 249}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 69, 197, 20}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 222, 241, 153, 38, 245, 208, 184}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 64}, {{81, 189, 220, 168, 192, 0, 0, 5, 209, 209, 44, 216, 9, 29, 93, 138}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 162}, 64}, {{81, 189, 220, 168, 192, 0, 0, 50, 86, 125, 118, 107, 198, 244, 89, 163}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 64}, {{81, 189, 220, 168, 192, 0, 0, 138, 236, 65, 168, 187, 254, 173, 125, 107}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 43, 17, 111, 135, 58, 137}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 53, 203, 32, 181, 29, 220, 131, 110}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 7, 179, 90, 235, 8, 79}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 120, 137, 78, 181}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 154, 205, 17, 79, 80, 81, 165, 94}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 184, 81, 2}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 119, 83, 43, 202, 231, 191}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 51, 163, 103, 154, 60, 252, 39, 17}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 135, 201, 41, 143, 187}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 180, 138, 89, 48, 78, 218, 239, 134}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 224, 181, 242, 141, 85, 65, 18}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 1, 196, 145}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 103, 182, 180, 235, 75}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 104, 174, 116, 31, 138, 218, 176}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 160, 214, 69, 93, 226, 151, 249}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 9}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 217, 52, 4, 148, 2, 217}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 160}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 223, 66, 105, 110}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 138, 134, 134, 50, 203}, 64}, {{81, 189, 220, 168, 192, 0, 0, 32, 161, 48, 87, 118, 221, 203, 6, 245}, 64}, {{81, 189, 220, 168, 192, 0, 0, 183, 167, 208, 21, 155, 190, 91, 207, 179}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 134, 205, 92, 242}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 242}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 216, 210, 22, 195, 26, 78, 128}, 64}, {{81, 189, 220, 168, 192, 0, 33, 15, 66, 249, 18, 90, 148, 68, 85, 181}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 19, 15, 59, 24, 247}, 64}, {{81, 189, 220, 168, 192, 0, 27, 2, 92, 181, 5, 9, 148, 240, 4, 28}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 198, 132, 255, 100}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 44, 232, 186, 69, 139}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 64, 90, 51, 210, 152, 207, 180, 165}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 38, 78, 73, 248, 237, 250, 154}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 60, 25, 172}, 64}, {{81, 189, 220, 168, 192, 0, 102, 160, 137, 55, 155, 216, 100, 7, 25, 104}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 26, 190, 162, 184, 162, 32, 127, 154}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 148, 103, 70, 85, 253, 7, 198, 244}, 64}, {{81, 189, 220, 168, 192, 0, 133, 35, 17, 52, 210, 203, 205, 201, 216, 168}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 85, 92, 246, 10, 32, 156, 5}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 182, 140, 225, 85, 3, 18, 222, 23}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 178, 110, 230, 20, 64, 25}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 88, 138, 177, 233, 240, 152}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 217, 72, 158, 50, 27, 243, 152, 174}, 64}, {{81, 189, 220, 168, 192, 0, 0, 252, 216, 54, 122, 212, 228, 172, 61, 108}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 119, 82, 29, 75, 136, 58, 252}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 181, 83, 107}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 249, 248, 42}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 99, 122, 134, 216, 183, 249, 172}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 19, 40, 101, 154, 237, 65, 137, 251}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 249, 152, 65, 170, 84, 76, 53, 198}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 68}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 220, 255, 206}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 218, 32, 253, 209, 93}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 190, 242, 210, 43, 123, 6, 210, 76}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 183, 161, 88, 38, 162, 130}, 64}, {{81, 189, 220, 168, 192, 0, 111, 231, 113, 250, 149, 178, 233, 52, 59, 156}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 9, 210, 83, 13, 79}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 82, 181, 65}, 64}, {{81, 189, 220, 168, 192, 0, 0, 13, 223, 199, 217, 176, 5, 82, 89, 249}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 53}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 156, 205, 61}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 248, 138, 221, 111}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 75, 24, 116, 144, 115, 95}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 92, 16, 32, 200, 39, 28}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 64}, {{81, 189, 220, 168, 192, 99, 143, 85, 226, 36, 210, 173, 21, 209, 114, 17}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 223, 114, 74, 229, 86}, 64}, {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 117}, 64}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 44, 238, 61, 88, 209, 167}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 82, 70}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 150, 59, 10, 185, 98, 78, 191}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 30, 39}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 48, 60, 234, 217, 138, 113}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 77, 189, 244, 19, 148, 61, 115}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 119, 45, 149, 2}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 117, 121}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 239, 219, 31, 183, 67, 128}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 114, 148, 111}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 145, 166, 56, 149, 122}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 126, 191, 219, 164, 95, 114, 249}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 196, 67, 46, 211, 9, 95, 45}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 101, 50, 222}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 23, 163, 175, 130, 26, 204, 79, 205}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 19, 4}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 206}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 3, 92, 83, 27, 38, 14, 101, 253}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 255, 208}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 230, 146, 0, 16, 26, 40, 239}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 84, 111, 126, 6, 222, 88, 6}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 125}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 153, 112, 53, 195, 239}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 90, 164, 238, 27, 191, 22}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 63, 23}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 58, 140, 140, 183, 183, 106}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 98, 147, 20, 55, 148, 222}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 146, 176, 98, 4, 198, 187}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 79, 184, 44}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 128, 5, 206, 188, 153, 128}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 194, 247}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 225, 105, 230, 227, 146, 229, 239, 2}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 47, 213, 22, 228, 120, 41, 136}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 125}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 222, 37, 168, 245, 105}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 227}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 181, 40, 189, 201, 255, 60, 217}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 23}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 234, 148}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 210}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 227, 0, 38}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 49, 23, 56, 28}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 186, 110, 71}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 249}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 160, 32, 12, 226}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 164, 49, 181, 78}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 150, 115}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 100}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 165, 79, 42, 244, 61}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 238, 234, 118, 50, 228, 94, 11}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 93, 163, 223, 231, 22, 125}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 209, 56, 4, 165, 66, 180, 92}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 231}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 159, 85, 27}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 61, 181, 254, 61, 10}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 50, 15, 132}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 11, 168, 190, 149, 182, 208, 13}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 80, 209, 224, 44, 199}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 59, 105}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 89}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 45, 230, 241, 214, 161, 224, 176}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 15}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 126, 204, 230, 180}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 171, 147, 174}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 131, 46, 50, 163, 156, 31}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 86}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 98}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 164, 112, 231, 189, 91, 209, 102}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 240}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 69, 72, 42}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 55, 26, 16}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 30, 195, 73, 17, 114, 123, 206, 90}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 215, 9, 1}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 85, 198}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 44, 36, 117, 203, 189, 73, 27}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 151, 131, 97, 204}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 126, 178, 173}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 100, 212, 249, 198, 164, 153, 140}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 212, 207, 9, 190, 52, 63, 52, 143}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 44, 95, 75, 63, 189, 49}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 123, 101, 127}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 226, 191, 117, 120}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 156, 75, 145, 157, 11, 211}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 135, 123, 213, 191, 238, 131}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 118, 254}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 86, 180, 224, 152}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 183, 136, 17}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 239}, {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 141, 165, 52, 79, 236}, 239}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 245}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 117}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 114}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 176}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 163}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 194}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 51}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 131}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 243}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 57}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 181}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 98}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 233}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 130}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 19}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 37}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 125}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 129}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 176}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 185}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 240}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 49}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 151}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 6}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 48}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 47}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 79}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 42, 93, 183}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 164}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 158, 231}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 183}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 184, 174, 211, 135, 59}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 202, 63, 29}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 224}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 110, 236}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 109, 107}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 129, 69, 22, 189}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 154, 132}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 94}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 225}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 62, 139, 198, 235, 174}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 9, 123, 213}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 110, 169, 207}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 107, 223}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 32, 82, 130}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 108}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 159, 238}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 58, 39, 224, 139, 138}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 158, 168}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 67, 108, 244}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 60, 133, 10}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 37, 194, 81, 61, 199}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 55, 187}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 172, 81, 232, 246}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 125, 70, 2, 45}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 79, 222}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 162, 40}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 67, 108, 216, 1}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 140, 186, 104, 122}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 24, 128}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 69, 13, 195}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 153, 216, 12}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 64, 210, 234, 250}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 84, 175, 152}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 218, 93, 50, 169, 135}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 84}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 117, 67, 0, 252}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 16, 154, 194}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 149, 142, 129, 231, 211}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 92, 55, 208, 137}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 53, 223, 232, 225, 147}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 129, 40, 206, 107}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 77, 98, 249}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 158, 22, 77, 172}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 48, 84}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 238, 185, 99}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 180, 141, 193}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 238}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 235, 64, 85, 168}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 136}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 144, 124, 206, 32, 143}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 104, 104, 200, 61}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 138, 153, 59}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 52, 165}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 165}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 153, 237, 244}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 90, 253}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 225, 40, 126, 102}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 135, 116, 188, 201, 250}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 26, 57, 249, 197, 255}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 189, 182, 137, 91, 189}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 208, 16, 213}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 32}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 128}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 222}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 214, 168, 119}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 243, 98, 45}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 148, 138, 44, 138, 22}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 75, 42, 37}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 115, 162}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 146, 193, 87, 188, 27}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 132, 183}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 192, 227}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 104}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 211, 138, 21}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 196, 203, 132, 113, 2}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 15, 50, 54, 240}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 11, 103, 125, 194}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 15, 115, 207, 211}, 43}, {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 150, 111, 27, 58, 46}, 43}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 17, 242}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 64, 245}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 137, 52}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 113, 186, 129}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 32, 191}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 213}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 17, 222, 215, 185}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 35, 254}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 199}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 16, 109}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 2}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 110}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 242}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 245, 64}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 86}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 145}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 154, 242, 45}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 191}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 240, 16, 84}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 86, 225}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 26}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 3, 0, 132}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 197, 57}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 186}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 128, 114, 96, 146}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 71, 157, 250}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 178, 28}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 246, 32}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 242, 212}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 185, 168, 254}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 104, 23, 126}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 220}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 98, 219, 160}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 130, 157, 214}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 110, 232}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 177, 124}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 119, 44, 100}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 148, 232, 233}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 83, 179, 201}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 162, 252, 237}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 44, 231, 207}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 129, 239, 41}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 187, 194, 240}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 222, 162}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 220}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 193, 23, 220}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 66, 53}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 241, 146}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 206, 252, 29}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 255, 221, 226}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 245, 162, 228}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 79, 16, 85}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 26}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 236, 97, 57}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 72, 42}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 230, 157, 214}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 7, 207, 213, 217}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 89, 248}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 230, 186, 125}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 221}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 104, 67, 205, 221}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 140, 51, 249}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 1, 89, 112}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 195}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 65, 226, 214, 177}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 216, 216, 245, 228}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 27}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 19, 197}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 160, 248, 120}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 163, 144, 116, 146}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 73, 59, 71}, 17}, {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 40, 39}, 17}, {{109, 74, 145, 192, 0, 0, 0, 0, 130, 174, 250, 240, 53, 136, 59, 233}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 170, 236, 152, 82}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 71, 44, 117, 1, 67, 17, 244}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 232, 121, 72, 215, 137}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 171, 88, 111, 89, 41}, 5}, {{109, 74, 145, 192, 0, 63, 238, 23, 120, 222, 119, 92, 143, 209, 76, 136}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 229, 104, 243, 184, 255, 213, 41}, 5}, {{109, 74, 145, 192, 0, 0, 24, 178, 136, 61, 250, 203, 128, 163, 252, 71}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 78, 83, 137, 19, 85, 89, 25, 208}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 44, 32, 221, 82, 56, 36, 124, 233}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 5}, {{109, 74, 145, 192, 0, 0, 0, 29, 87, 48, 194, 217, 59, 192, 110, 54}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 169, 228, 115, 151, 55, 238, 176, 141, 114, 125}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 23, 205, 213, 188, 159, 110}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 117, 157, 3, 140, 51, 217, 208, 148}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 168, 211, 38, 79}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 51, 155, 200, 59, 236, 44, 28}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 168, 165, 96, 242, 119, 28, 191, 81}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 233, 79, 43, 62, 52}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 52, 178, 216, 206, 43}, 5}, {{109, 74, 145, 192, 0, 216, 155, 153, 38, 204, 101, 39, 245, 245, 111, 211}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 72, 37, 176, 79, 136, 131, 199, 226}, 5}, {{109, 74, 145, 192, 0, 0, 136, 203, 109, 198, 162, 98, 97, 102, 36, 3}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 204, 169, 40, 210, 45, 212, 53, 126, 92}, 5}, {{109, 74, 145, 192, 0, 0, 79, 241, 52, 49, 198, 158, 205, 14, 56, 119}, 5}, {{109, 74, 145, 192, 1, 157, 74, 144, 88, 187, 115, 245, 94, 172, 72, 101}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 251, 42, 135, 219}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 169, 240, 99, 131, 89, 157}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 241, 103, 8, 29, 149, 9}, 5}, {{109, 74, 145, 192, 0, 0, 0, 69, 189, 169, 187, 249, 83, 44, 40, 135}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 234, 195, 82, 245, 183, 253}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 13, 223, 53, 53, 229}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 151, 182, 46, 160}, 5}, {{109, 74, 145, 192, 0, 0, 0, 163, 180, 197, 145, 216, 12, 54, 253, 220}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 32, 96}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 112, 22, 248, 228, 255, 193, 46}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 83, 142, 156, 238}, 5}, {{109, 74, 145, 192, 0, 0, 97, 219, 54, 17, 104, 165, 224, 111, 105, 193}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 180, 252, 51, 103, 150, 248, 186, 40}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 179, 91, 114, 220}, 5}, {{109, 74, 145, 192, 0, 67, 91, 179, 179, 171, 166, 112, 251, 91, 239, 184}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 198, 195, 249, 233, 46, 72}, 5}, {{109, 74, 145, 192, 235, 148, 185, 239, 37, 149, 239, 110, 218, 152, 64, 83}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 206, 27}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 222, 111}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 158, 33, 226, 60, 123}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 64, 31, 74, 104, 17, 174, 222}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 8, 168, 207, 249, 11, 246, 149}, 5}, {{109, 74, 145, 192, 0, 0, 0, 123, 163, 137, 80, 164, 52, 77, 18, 1}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 226, 188}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 17, 42, 218, 124, 69, 176, 71, 124}, 5}, {{109, 74, 145, 192, 0, 0, 0, 6, 43, 75, 139, 135, 91, 202, 101, 196}, 5}, {{109, 74, 145, 192, 0, 0, 86, 12, 113, 85, 7, 3, 253, 81, 213, 52}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 38, 36, 236, 72, 11, 41, 152}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 191, 46, 74, 11, 53, 222, 208}, 5}, {{109, 74, 145, 192, 0, 213, 59, 61, 57, 195, 209, 36, 75, 71, 210, 33}, 5}, {{109, 74, 145, 192, 131, 90, 138, 228, 128, 229, 91, 38, 104, 109, 124, 74}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 161, 229, 248, 122, 101, 59}, 5}, {{109, 74, 145, 192, 0, 0, 147, 87, 77, 221, 200, 232, 187, 223, 102, 121}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 199}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 182, 40, 88, 162}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 157, 243}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 51, 146}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 225, 81, 148, 29}, 5}, {{109, 74, 145, 192, 0, 0, 81, 158, 113, 81, 70, 16, 9, 76, 143, 230}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 4, 190}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 42, 48}, 5}, {{109, 74, 145, 192, 0, 0, 200, 154, 175, 140, 201, 12, 105, 60, 87, 179}, 5}, {{109, 74, 145, 192, 0, 165, 76, 6, 123, 43, 123, 115, 83, 133, 238, 140}, 5}, {{109, 74, 145, 192, 0, 0, 0, 102, 205, 111, 248, 242, 20, 244, 148, 202}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 190, 154, 232, 106, 156}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 173, 25, 125, 88, 28}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 5}, {{109, 74, 145, 192, 0, 169, 139, 155, 191, 139, 209, 81, 169, 111, 160, 236}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 146, 12, 81, 69, 29, 167, 193, 102, 178, 111, 15}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 134, 21, 25, 159, 223, 10}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 102, 163}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 152, 190, 15, 41, 34, 122}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5}, {{109, 74, 145, 192, 0, 56, 159, 89, 252, 50, 28, 213, 51, 127, 77, 251}, 5}, {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 97, 56}, 5}, {{109, 74, 145, 192, 179, 198, 161, 15, 103, 19, 19, 197, 29, 31, 19, 73}, 5}, {{109, 74, 145, 192, 0, 0, 0, 59, 51, 43, 210, 40, 208, 254, 54, 100}, 5}, {{109, 74, 145, 192, 0, 0, 174, 155, 137, 227, 127, 118, 240, 157, 229, 34}, 5}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 175, 14}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 26, 123}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 82}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 254, 93, 147, 180, 96}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 156, 206, 144}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 143, 3, 166}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 132, 166, 4, 23}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 142}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 162, 36, 76}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 143}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 211, 60}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 41, 152, 167, 89}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 36, 50}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 125, 131, 174, 33}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 39, 27}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 239}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 91, 46, 38, 27, 67}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 115, 206, 135}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 165, 154, 12, 2}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 177, 236, 186, 155}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 185, 251, 9, 233}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 107, 211, 192, 25, 249}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 220}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 47, 216, 55, 224, 207}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 3, 213}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 89, 169, 111}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 14, 83, 181, 105}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 166, 249, 163}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 9, 244}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 13, 234, 54, 5, 38}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 121}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 160}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 65, 86}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 249, 242, 170}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 132, 254, 37}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 139, 129, 74, 247}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 215, 23, 195, 207}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 50, 128}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 246, 126}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 242, 186, 11, 64}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 3, 91}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 134}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 221, 245}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 65}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 4, 42, 28, 231, 34}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 67, 41, 72}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 208}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 131, 237, 25, 227}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 10}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 10, 135, 103, 22, 124}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 78, 77, 76}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 219, 93, 157}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 180}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 15, 132, 221, 251}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 80, 50}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 247}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 102}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 211, 3}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 252, 64}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 109, 242}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 117, 127}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 89, 159, 106, 251, 201}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 47, 252}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 100, 33, 214}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 168, 25}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 120, 77, 6, 238}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 48, 79, 78, 170, 219}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 196, 58, 98}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 80}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 68, 74}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 169, 129, 100, 30, 107}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 167, 22, 10}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 191}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 225}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 170}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 16, 91, 96, 37}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 181, 88, 131}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 240}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 134, 66, 14, 193}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 114, 129, 26, 215, 78, 61, 38, 67}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 175, 176, 254, 138, 170, 245}, 197}, {{153, 251, 115, 65, 104, 179, 0, 111, 100, 213, 32, 203, 152, 104, 45, 212}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 233, 155, 84, 72, 73}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 143, 26, 188, 177, 200, 149, 227}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 87, 192, 249, 170, 55, 9, 21, 24}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 122, 216, 84, 206, 7, 176}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 190, 118}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 27, 254, 226, 241, 245}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 110, 85, 159, 136}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 111, 230, 9, 190, 45, 230}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 76, 195, 172, 60, 254, 230}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 96, 235, 229, 64, 47, 132, 89, 196, 249}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 49, 217, 131, 92, 81, 41, 102, 179}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 143, 249, 2, 66, 180, 40, 210, 162}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 67, 86, 185, 250, 149, 126, 144, 68, 37}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 248, 47}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 235, 228, 6, 179}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 102, 155, 88, 214}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 61, 90, 126, 44}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 245, 218, 205}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 186, 180, 45, 167, 33, 147}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 249, 150, 11, 248, 111, 24, 221, 217}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 184, 173, 242, 18, 95, 113, 250}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 182, 221, 194, 104, 122, 185, 21}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 101, 164, 108, 51, 154, 88, 144, 188}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 236, 109, 235, 229, 203}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 88, 200, 236}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 141, 23, 203, 147, 35, 219, 23, 36}, 197}, {{153, 251, 115, 65, 104, 179, 0, 252, 196, 71, 183, 177, 250, 116, 184, 124}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 21, 71}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 188, 50}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 100, 131, 104, 28, 137, 182, 94}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 192, 85, 121, 114}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 65, 214, 32, 176, 169, 159}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 162, 207, 23, 250, 20, 132}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 12, 248, 232, 187, 197}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 34, 172, 27, 27, 189, 134}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 131, 185, 205, 145, 41, 107, 47, 7}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 83, 213, 193, 199, 255, 158}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 199, 70}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 108, 35, 178, 234, 183, 130, 152}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 55, 146, 138, 111, 248, 168, 176, 17}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 60, 5, 251, 44, 46, 210, 246}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 183, 27, 164}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 144, 211, 97, 71}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 59, 208, 101, 7, 116, 91, 233}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 164, 128, 252, 110}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 152, 165, 135, 235, 118, 2, 172, 216}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 55, 112, 191}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 171, 167, 44, 73, 185, 238, 195}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 110, 47, 15, 253, 80, 79, 103, 208}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 37, 192, 225, 40, 86}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 67, 66, 26, 251}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 48, 250, 82}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 240, 223}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 219, 190, 100, 76}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 152, 155, 132, 28, 186, 160}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 149, 50, 225, 221, 117, 103}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 221, 28, 240, 150, 189}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 38, 83, 82, 240, 181, 19, 33, 19}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 204, 201}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 86, 69, 250}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 1, 103, 65, 24, 102, 172}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 53, 64, 178, 5, 33, 93, 239, 95}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 51, 253}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 198, 225, 123, 29}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 123, 42, 118, 135, 176}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 17, 79, 39, 70, 222, 156, 103}, 197}, {{153, 251, 115, 65, 104, 179, 0, 181, 132, 172, 53, 66, 57, 123, 231, 79}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 60, 249, 107, 15, 105, 208, 208, 40}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 65, 13, 45, 34}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 174, 147, 126}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 93, 8, 148, 67, 134}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 10, 28, 72, 173}, 197}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 31, 119, 203, 127, 63}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 88, 64, 13, 165}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 200, 214}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 255, 247, 184, 11, 244}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 135}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 87, 207, 90}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 241}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 205, 217, 42, 45}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 50, 167, 119}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 212}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 142, 65, 248, 80}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 148}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 113, 113, 237}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 116, 74, 11, 43}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 50, 64, 188}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 206, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 243, 111, 203, 104}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 26, 85, 131, 220}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 150, 193, 53, 64}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 216}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 31, 8, 146, 40}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 132, 253, 181, 71, 217}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 230, 118, 252}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 23, 113, 92, 50, 223}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 205, 185, 110}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 47, 253, 172, 71}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 159, 224}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 153, 199, 176, 198}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 131, 239, 150, 66}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 61, 226, 176}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 216, 130, 113}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 103}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 161, 89, 36, 28}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 228, 57, 24, 169}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 207, 103, 100}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 222, 231, 21, 52}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 226}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 209}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 110, 230, 47, 226, 55}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 178, 21, 107}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 197, 158, 132, 55}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 166, 164, 153, 69}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 192}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 109, 213}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 18}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 78, 136, 65}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 179, 222}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 121, 66, 116, 238}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 145, 218}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 37}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 184, 65, 164}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 173, 156}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 117, 137, 203, 11}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 125, 252, 138}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 178, 181, 248}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 59, 124, 239}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 254}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 68, 158}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 152}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 111, 205}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 252, 217, 91, 54}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 13, 51, 114}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 198, 158, 251, 109}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 136, 207, 198, 97}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 195, 158, 141, 145, 52}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 29}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 194, 104, 222, 45}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 193, 105, 123, 245}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 119, 237, 91}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 22, 100, 101}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 115}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 23, 13, 242, 19}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 187}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 131, 33, 80}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 94, 187}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 3, 132, 165, 115, 155}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 13, 225, 146}, 192}, {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 115, 94, 7, 82, 55}, 192}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 14, 75, 117, 213}, 160}, {{61, 77, 121, 176, 138, 152, 0, 221, 95, 66, 26, 233, 4, 29, 225, 104}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 207, 168, 200, 149, 10, 38, 142, 66}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 7, 210, 105, 190, 67, 41, 110}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 96, 40, 239, 75, 222, 98, 213, 62}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 181, 237, 5, 179, 12, 203, 35, 236}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 17, 119, 253, 16, 104}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 227, 212, 43, 0, 2}, 160}, {{61, 77, 121, 176, 138, 152, 215, 19, 75, 50, 55, 137, 249, 250, 207, 68}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 32, 88, 255, 79, 67, 149, 241}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 152, 180}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 92, 125, 73, 82}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 3, 58, 79, 172, 203, 21, 103, 250, 148}, 160}, {{61, 77, 121, 176, 138, 152, 0, 151, 75, 126, 109, 134, 12, 228, 35, 147}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 93, 133, 146, 222, 194, 225, 107}, 160}, {{61, 77, 121, 176, 138, 152, 123, 212, 158, 114, 161, 200, 163, 95, 195, 112}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 179, 47, 29, 89}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 95, 92}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 51, 205}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 117, 15}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 215, 117, 100, 252, 38, 55, 14, 150}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 219, 229}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 25, 227, 235, 46, 42, 192, 95, 182}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 135, 115, 164, 39, 198}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 102, 72, 12, 3, 194, 6, 217}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 164, 117, 222, 235, 2, 159}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 160}, {{61, 77, 121, 176, 138, 152, 0, 186, 229, 185, 85, 202, 208, 136, 64, 135}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 45, 125, 80, 153, 94}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 170, 216, 8, 94}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 160}, {{61, 77, 121, 176, 138, 152, 0, 239, 208, 246, 84, 1, 157, 57, 66, 220}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 50, 254, 254, 196, 124, 75}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 46, 41, 95, 195, 253, 174, 231, 243}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 140, 12, 16, 75, 82}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 147, 76}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 239, 165, 152, 31}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 213, 241, 204}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 35, 191, 80, 237, 233, 248}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 12, 92, 11}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 215, 15, 164, 206, 150}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 138, 90, 188, 132, 251, 13}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 104, 56, 58}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 71, 81, 195, 179, 99}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 193, 222, 21}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 160}, {{61, 77, 121, 176, 138, 152, 0, 239, 176, 108, 198, 64, 100, 10, 150, 188}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 89, 105, 250, 75, 109}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 187, 171}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 50, 33, 233, 255, 82, 3, 114}, 160}, {{61, 77, 121, 176, 138, 152, 0, 8, 240, 88, 177, 26, 206, 130, 51, 197}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 83, 252, 95, 61, 5, 171, 34}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 133, 19, 19}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 252, 222}, 160}, {{61, 77, 121, 176, 138, 152, 0, 50, 45, 156, 233, 10, 91, 164, 144, 185}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 100, 6, 211, 123, 118, 112, 166}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 110, 12, 58, 2}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 147, 123, 162, 68, 114, 106}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 195, 165}, 160}, {{61, 77, 121, 176, 138, 152, 0, 31, 118, 82, 249, 234, 59, 57, 237, 155}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 242, 73, 162, 9}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 231, 65, 74, 57, 131, 39, 56, 69}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 26, 97, 195, 251}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 132, 162, 98, 233, 81, 129, 21, 197}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 5, 83, 61, 47, 97}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 56, 183, 224, 114, 166, 209, 203, 245}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 133, 28, 116, 124, 33, 31, 95, 206}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 160, 39, 213, 255}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 147, 148, 224, 29, 175, 21, 212, 75}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 161, 186, 208, 251, 171, 225, 8, 39}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 7, 180, 216, 200, 103, 16, 54}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 73, 137, 40}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 68, 52, 134, 189}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 24, 60, 122, 5, 218}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 157, 218, 10, 142, 123}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 187, 125, 195, 103}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 101, 228, 66}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 136, 131}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 207, 102, 169}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 160}, {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 41, 65, 105}, 160}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 67}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 3, 111, 254}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 165, 79, 222, 105, 84}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 212, 214, 20, 111, 247}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 101}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 204, 77, 164}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 182, 199, 79, 123}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 18, 51, 249, 200}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 254, 44, 125}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 82}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 104, 49, 106, 248, 155}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 191, 151}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 146, 108, 75}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 165, 29}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 109, 36, 62}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 126, 247}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 225, 210, 95, 154}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 130, 152}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 124, 140, 129, 185, 224}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 160, 123, 150}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 159}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 42}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 187, 158, 164, 16}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 139, 186, 244, 253, 5}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 40, 161}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 11, 103, 133, 156, 138}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 195, 239, 80, 55, 249}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 220, 19, 20, 156, 42}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 211, 238, 135, 184, 250}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 108}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 88, 67, 208, 215}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 148}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 65, 56}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 119, 8, 193}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 178, 167, 221}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 139, 250}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 207, 168, 35}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 36, 252, 16}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 44, 212, 24, 226}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 167}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 196}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 197, 116}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 161, 173, 21, 98}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 14, 123, 254}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 231}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 137}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 239, 165, 252, 183, 107}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 150, 132, 68, 69}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 10, 1, 208}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 134, 179}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 143, 57, 181, 70}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 214, 130, 185}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 146, 242, 237, 82}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 99, 135}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 219}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 6, 154}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 77}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 63, 122, 10}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 237, 245, 240, 8, 141}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 122, 254, 251}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 54, 39}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 217, 82, 214, 145}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 221, 231, 90}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 198, 108, 148, 30, 101}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 42, 101, 25}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 22, 60, 64, 137}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 100, 39, 60, 239}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 214, 80, 250, 119}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 85, 195, 76, 81}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 125, 68, 253, 81}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 5, 213}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 99, 86, 209}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 177, 44, 22}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 78, 180}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 243, 249, 87, 131, 26}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 86}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 164}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 25}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 249}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 241, 228, 20}, 199}, {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 183, 106, 78, 232}, 199}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 217}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 72}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 216, 234, 253, 218}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 167, 135}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 126, 252}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 167, 162, 249, 249}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 18}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 228}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 164}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 165, 2, 113, 34}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 131}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 145, 167, 46}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 220, 148, 18}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 46, 235, 169}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 57, 82}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 29, 15, 228}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 130, 66, 243}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 205, 150}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 224, 71}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 105}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 208}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 40}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 95, 30}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 204, 179}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 169, 49, 48, 79, 196}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 185, 20, 66, 83}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 204, 14, 236, 57}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 221, 78}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 6, 154, 120}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 27, 249, 78}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 98}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 79, 140, 123}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 157, 136, 228}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 253}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 94}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 125, 97, 20, 17}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 244, 184, 52}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 222, 234, 151}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 214}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 72, 133, 183, 109, 157}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 94, 22, 210, 111, 170}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 225, 111, 33, 16}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 27, 133}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 96, 17}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 158, 16, 213}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 78, 20, 138, 2}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 64, 23, 190, 235}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 35}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 189}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 130, 41, 31}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 19, 90}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 130, 2}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 152, 222, 110}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 98}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 220, 46}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 220, 91, 41}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 65, 28, 19, 194}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 78, 216, 178, 94, 248}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 117}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 62, 12, 37}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 76, 66, 75, 68, 5}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 199, 219, 210, 58, 136}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 73}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 13, 223}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 37, 86, 127, 64, 106}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 42}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 221, 35}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 88, 207}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 74, 91, 139, 41}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 36, 199, 169, 46}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 34, 89, 133, 87, 3}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 251}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 119, 63, 1, 177}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 108, 62, 181}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 134, 189, 145, 206, 231}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 141, 120}, 75}, {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 126}, 75}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 232}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 206}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 5, 129}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 237, 88}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 26, 26}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 228, 101}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 68, 193}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 12, 43}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 180, 146}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 244, 165}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 7}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 235}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 133}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 36}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 194}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 198}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 119, 203}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 68, 176}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 255}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 194, 6}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 206}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 188, 64}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 134}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 127}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 224, 110}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 45, 33}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 250}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 85, 209}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 138, 165}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 178, 198}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 140}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 66, 253}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 200}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 80}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 15, 252}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 130}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 21}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 225}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 91}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 223}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 167}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 205}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 187}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 91, 38}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 229}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 174}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 5, 194}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 220, 1}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 123, 168}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 180}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 52}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 127}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 189}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 185, 198}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 82, 149}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 212}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 138}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 252}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 93, 186}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 114, 9}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 159, 221}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 22}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 34, 191}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 155}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 139, 81}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 101}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 192, 220}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 113}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 43, 56}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 132}, 222}, {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 72, 243}, 222}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 23}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 62, 98, 145, 125, 112}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 127, 250, 138, 175}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 68, 8, 149}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 151, 154, 98, 96}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 75, 252}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 229, 230, 126}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 180}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 16, 108}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 254}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 245, 171, 193}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 113, 151}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 133, 168, 249, 160}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 231, 156}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 156, 54, 70}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 115, 117}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 31, 166}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 145}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 4, 139, 22}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 40, 195, 22}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 65, 163}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 159, 101, 23, 224}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 223, 228, 44, 70}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 215, 32, 78, 210, 103}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 128}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 228, 241, 114, 193, 223}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 65}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 134, 101, 135}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 59, 81}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 203, 99, 247, 215, 3}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 88}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 130, 100, 169, 73}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 128, 177, 53, 251}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 172, 107, 22}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 102, 37}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 105, 78, 187, 100}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 244, 147, 219, 145}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 169, 223}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 83, 53}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 1}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 219, 172, 62}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 4, 211}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 79}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 48, 163}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 39, 211}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 151, 216, 98}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 251, 154}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 198, 201}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 251}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 52, 123, 40}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 241, 219}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 127}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 53, 111}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 132, 35, 95}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 5, 50, 5, 97, 187}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 39, 44}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 108, 72, 199}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 162, 127, 26, 82, 114}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 54, 59, 128, 187, 86}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 132, 195}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 80, 238}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 91}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 174, 144, 115}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 131}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 194, 58, 163, 65}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 224}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 233, 121, 15, 175, 32}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 208, 12, 25, 131}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 48, 206, 222}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 74, 217, 164, 101}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 183, 51}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 110, 49, 235, 57}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 20}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 252, 66, 186}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 100, 220, 249, 206, 192}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 83, 159}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 112, 140, 125, 184}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 26, 74, 201}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 189, 184}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 20, 233}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 226, 17, 175, 97}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 173, 48}, 39}, {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 39}, {{124, 170, 35, 47, 152, 224, 0, 112, 9, 92, 46, 66, 226, 177, 17, 128}, 9}, {{124, 170, 35, 47, 152, 224, 0, 144, 87, 100, 89, 121, 142, 86, 191, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 199, 194, 79, 112, 149, 108, 57, 91}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 194, 26}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 253, 129, 144, 109}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 216, 168, 36, 98, 199, 20}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 243, 229, 228, 250, 172, 240}, 9}, {{124, 170, 35, 47, 152, 224, 0, 138, 218, 219, 179, 65, 75, 45, 217, 140}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 161, 39, 38, 205, 176, 215}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 164, 5, 206}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 65, 165, 45, 99, 227, 100}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 240, 218, 89, 170}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 198, 105, 68, 23, 192, 105}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 225, 53, 52, 104}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 247, 24, 40, 164, 174}, 9}, {{124, 170, 35, 47, 152, 224, 0, 177, 180, 172, 162, 118, 140, 54, 171, 200}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 186, 100, 101, 215, 77}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 91, 146, 1, 190, 102}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 32, 163, 109, 141}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 16, 132}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 108, 152, 93, 61, 158, 183}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 88, 151, 207, 187}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 58, 184, 56}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 15, 52}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 21, 234}, 9}, {{124, 170, 35, 47, 152, 224, 0, 121, 3, 223, 249, 9, 63, 75, 195, 114}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 20, 107}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 252, 162, 150, 155, 5, 159, 10, 201}, 9}, {{124, 170, 35, 47, 152, 224, 0, 200, 187, 246, 241, 36, 108, 86, 66, 140}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 36, 128, 50}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 111, 215}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 27, 147, 195}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 88, 86, 91, 125, 25, 117, 33}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 108, 62, 83, 179, 244, 181, 182, 26}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 47, 137, 160}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 80, 183, 127, 214, 10, 75, 157, 53}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 84, 124, 20, 236, 93, 235, 176}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 91, 50, 129, 190, 132, 81, 20, 191}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 196, 173, 147, 216}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 62, 197, 47, 88, 188, 242}, 9}, {{124, 170, 35, 47, 152, 224, 0, 202, 171, 236, 240, 118, 2, 40, 148, 161}, 9}, {{124, 170, 35, 47, 152, 224, 0, 16, 138, 158, 139, 127, 38, 15, 255, 19}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 208, 4, 125, 107, 171, 0, 202, 126}, 9}, {{124, 170, 35, 47, 152, 224, 0, 185, 44, 56, 201, 126, 44, 176, 17, 99}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 169, 40, 199}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 117, 66, 22, 204, 238}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 9}, {{124, 170, 35, 47, 152, 224, 0, 106, 131, 120, 23, 153, 112, 163, 98, 39}, 9}, {{124, 170, 35, 47, 152, 224, 0, 27, 147, 106, 3, 11, 155, 192, 52, 228}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 203, 135, 111, 213, 245, 227}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 99, 40, 83, 132}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 239, 168, 38, 1}, 9}, {{124, 170, 35, 47, 152, 224, 0, 56, 15, 227, 244, 59, 23, 142, 19, 160}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 32, 246, 2, 38, 125, 75, 30, 58}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 166, 71, 1, 22, 156}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 240, 110, 131, 83, 87, 83, 86, 207}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 131, 5, 82, 180, 5, 145, 95}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 99, 173, 215, 119}, 9}, {{124, 170, 35, 47, 152, 224, 117, 161, 58, 89, 39, 235, 85, 52, 152, 45}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 152, 82, 153, 247, 24, 44}, 9}, {{124, 170, 35, 47, 152, 224, 0, 167, 217, 115, 177, 84, 11, 249, 167, 180}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 199, 134, 47}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 205, 178, 232, 153}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 225, 234, 63, 152, 243, 77, 166, 65}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 59, 214, 38, 7, 220, 100}, 9}, {{124, 170, 35, 47, 152, 224, 9, 7, 225, 250, 143, 83, 183, 232, 106, 130}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 22, 154, 213}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 81, 26, 181, 151, 122, 50, 30}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 18, 84, 114}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 119, 249, 145, 133, 23, 248, 115}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 231, 130, 244, 200, 159}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 108, 89, 241, 50, 129, 244, 94, 62}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 15, 28}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 108, 18, 134, 109, 53}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 12, 9}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 94, 233, 139, 241, 49}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 106, 138, 165, 5, 226}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 1, 52, 217, 4, 147, 0, 27, 110}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 233, 79, 199}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 229, 183, 26, 67, 111, 127}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 141, 97, 215, 175, 60, 102}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 63, 4, 76, 114, 49, 180, 88}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 194, 196}, 9}, {{124, 170, 35, 47, 152, 224, 0, 249, 251, 78, 189, 135, 179, 1, 203, 1}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9}, {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 222, 148}, 9}, {{192, 221, 20, 228, 0, 0, 0, 0, 152, 92, 12, 1, 247, 192, 216, 148}, 217}, {{192, 221, 20, 228, 0, 0, 0, 23, 173, 90, 246, 122, 248, 242, 214, 207}, 217}, {{192, 221, 20, 228, 0, 0, 69, 239, 171, 145, 10, 85, 31, 112, 105, 184}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 154, 158, 121, 238, 209, 198}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 53, 139, 55, 26, 228, 11, 15, 91}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 99, 61}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 233}, 217}, {{192, 221, 20, 228, 0, 0, 203, 112, 178, 97, 46, 61, 171, 32, 214, 22}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 22, 124, 36, 78, 203, 131}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 45, 21, 165, 205, 24, 2, 166, 72}, 217}, {{192, 221, 20, 228, 0, 0, 0, 39, 85, 240, 235, 50, 35, 208, 168, 140}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 109, 225}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 39, 42}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 163, 157, 115, 64, 79, 44, 249}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 59, 226, 45, 193, 167, 184, 162}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 184, 166, 207, 4, 207, 36, 201, 75}, 217}, {{192, 221, 20, 228, 0, 176, 251, 32, 203, 209, 140, 254, 160, 221, 197, 134}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 101}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 85, 196, 116, 2, 248, 240, 209}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 158, 8, 119, 48, 77, 177, 152}, 217}, {{192, 221, 20, 228, 0, 0, 0, 9, 15, 120, 86, 56, 234, 11, 188, 172}, 217}, {{192, 221, 20, 228, 0, 233, 113, 34, 66, 249, 154, 67, 109, 156, 161, 29}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 148, 219, 175, 225, 38, 249}, 217}, {{192, 221, 20, 228, 0, 0, 254, 229, 251, 67, 204, 61, 226, 125, 244, 182}, 217}, {{192, 221, 20, 228, 0, 0, 207, 55, 214, 245, 145, 242, 226, 246, 209, 183}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 66, 49, 26, 97, 120, 195}, 217}, {{192, 221, 20, 228, 0, 86, 81, 56, 145, 190, 184, 8, 210, 212, 242, 54}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 197, 96, 115, 0, 176}, 217}, {{192, 221, 20, 228, 0, 0, 62, 175, 207, 94, 116, 167, 95, 203, 243, 71}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 77, 165}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 210, 248, 34, 19, 126, 149, 201}, 217}, {{192, 221, 20, 228, 0, 0, 250, 228, 178, 54, 137, 39, 199, 90, 253, 127}, 217}, {{192, 221, 20, 228, 0, 97, 14, 127, 155, 216, 252, 71, 184, 59, 12, 96}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 29, 85, 48, 225, 244, 108, 69}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 26}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 210}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 45}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 85, 60}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 196, 244, 223, 171, 173, 120, 206, 212}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 202, 227}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 47, 134}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 177, 131, 199, 222, 212, 110, 49, 173}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 157}, 217}, {{192, 221, 20, 228, 0, 0, 81, 13, 79, 170, 150, 64, 8, 160, 37, 151}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 226, 156, 127, 50, 73, 243}, 217}, {{192, 221, 20, 228, 0, 0, 0, 223, 250, 189, 228, 1, 219, 178, 82, 16}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 6, 60, 209, 167, 174, 26}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 4, 251}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 92, 209, 178, 243, 200}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 185, 78}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 227, 166, 57, 172, 198}, 217}, {{192, 221, 20, 228, 0, 187, 237, 148, 112, 221, 79, 62, 91, 9, 174, 251}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 67, 163, 218, 127, 176, 91, 109, 165}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 131, 147, 62, 81, 147, 91, 103, 60}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 186, 28, 18, 177}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 89, 52}, 217}, {{192, 221, 20, 228, 0, 114, 70, 76, 126, 225, 157, 68, 232, 79, 166, 27}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 44, 23, 6, 90}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 124, 191, 33, 188, 107, 236}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 108, 235, 28, 84, 21}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 104, 159, 247, 251, 10, 35, 238}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 133, 239, 25, 109}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 217}, {{192, 221, 20, 228, 0, 0, 0, 155, 208, 40, 178, 143, 6, 150, 141, 252}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 85, 215, 55, 119, 114, 73, 159, 57, 39, 189}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 231, 31, 162, 1, 231, 237}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 67}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 246, 75}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 52, 73, 134, 220, 31, 169, 220, 108}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 92, 69, 118, 230}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 217}, {{192, 221, 20, 228, 0, 0, 121, 218, 218, 195, 86, 113, 244, 89, 53, 155}, 217}, {{192, 221, 20, 228, 0, 0, 0, 90, 67, 206, 8, 181, 198, 6, 18, 186}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 108, 40, 130, 78, 103}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 217}, {{192, 221, 20, 228, 0, 129, 242, 0, 150, 236, 88, 181, 199, 147, 169, 168}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 62}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 222}, 217}, {{192, 221, 20, 228, 0, 0, 16, 178, 117, 28, 52, 229, 196, 103, 130, 156}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 20, 105}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 29, 140, 54, 111, 98}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 172, 128}, 217}, {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 94}, 217}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 62, 165, 92}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 144, 215, 11, 111, 49, 30}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 79, 90, 183, 102, 5, 142, 41, 13}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 236, 162, 198, 201, 209}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 234, 241, 81, 77, 139, 156}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 22, 11, 60}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 82, 105, 35}, 142}, {{208, 178, 136, 0, 0, 95, 185, 184, 166, 197, 215, 225, 152, 26, 110, 254}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 202}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 41, 212, 127, 207, 137}, 142}, {{208, 178, 136, 0, 0, 0, 94, 19, 253, 51, 167, 83, 100, 195, 250, 169}, 142}, {{208, 178, 136, 0, 0, 0, 65, 185, 158, 110, 146, 164, 123, 34, 135, 164}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 75}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 142, 239, 99, 160, 86, 80, 226, 126}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 97, 215}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 37, 38}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 23, 75, 228}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 97, 18, 195}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 76, 244, 126, 230, 100, 28}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 127, 58, 252, 14, 221, 111}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 159, 227, 62, 54, 45, 46}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 183, 210}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 34, 148, 252, 135, 135, 186}, 142}, {{208, 178, 136, 0, 0, 0, 139, 156, 48, 49, 58, 81, 216, 141, 10, 154}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 229, 188}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 128, 211, 216, 204, 35, 79, 149}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 10, 37}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 161, 207, 236, 83, 140, 115, 204, 39}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 145, 52, 114}, 142}, {{208, 178, 136, 0, 177, 223, 150, 2, 16, 198, 244, 157, 62, 234, 140, 62}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 247, 110, 113, 16, 3, 91, 56}, 142}, {{208, 178, 136, 0, 0, 0, 43, 89, 4, 37, 209, 219, 225, 140, 221, 230}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 142}, {{208, 178, 136, 0, 0, 0, 190, 149, 215, 168, 233, 181, 130, 59, 146, 30}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 139, 107, 211, 131, 106, 36, 11, 221}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 152, 235, 180, 34, 103, 148}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 229, 80, 243, 2, 67, 54, 243, 9}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 212, 93, 73, 172, 196, 23}, 142}, {{208, 178, 136, 0, 0, 233, 9, 123, 208, 216, 224, 200, 16, 46, 143, 25}, 142}, {{208, 178, 136, 0, 0, 0, 0, 63, 172, 10, 168, 120, 131, 71, 12, 65}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 133, 27, 14, 223, 196, 152}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 209}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 214, 183, 88, 17, 219, 81, 58}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 140}, 142}, {{208, 178, 136, 0, 0, 232, 87, 247, 182, 109, 44, 228, 201, 163, 88, 235}, 142}, {{208, 178, 136, 0, 17, 104, 131, 144, 214, 107, 66, 102, 218, 79, 212, 155}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 74, 14}, 142}, {{208, 178, 136, 0, 0, 0, 234, 203, 22, 183, 192, 205, 132, 97, 138, 204}, 142}, {{208, 178, 136, 0, 90, 183, 97, 77, 69, 124, 6, 167, 242, 101, 107, 157}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 72, 190, 227, 240, 234}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 97, 99, 105, 131, 234, 108, 66}, 142}, {{208, 178, 136, 0, 0, 0, 201, 115, 197, 164, 159, 36, 160, 192, 111, 162}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 26, 244, 88, 251, 63, 16, 180, 19}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 214, 130, 148, 108, 115, 63, 82, 37}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 88, 187}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 184}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 82, 218, 234, 210, 155, 232}, 142}, {{208, 178, 136, 0, 0, 199, 90, 218, 220, 229, 82, 231, 213, 48, 108, 234}, 142}, {{208, 178, 136, 0, 67, 32, 214, 158, 237, 66, 134, 141, 42, 15, 138, 204}, 142}, {{208, 178, 136, 0, 175, 125, 167, 215, 7, 101, 133, 174, 108, 14, 50, 224}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 237}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 121, 150}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 195, 237, 212, 30, 189}, 142}, {{208, 178, 136, 0, 0, 0, 177, 162, 10, 239, 247, 72, 230, 128, 218, 148}, 142}, {{208, 178, 136, 0, 0, 0, 38, 135, 11, 26, 232, 125, 155, 5, 140, 210}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{208, 178, 136, 0, 0, 0, 0, 87, 139, 129, 31, 181, 232, 172, 142, 6}, 142}, {{208, 178, 136, 0, 0, 0, 76, 218, 238, 143, 184, 221, 153, 80, 62, 242}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 186}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 179, 138, 26, 169, 171, 189, 208}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 119, 184, 123, 215, 241}, 142}, {{208, 178, 136, 0, 0, 0, 155, 121, 86, 238, 126, 201, 78, 183, 99, 63}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 85}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 176, 86, 208, 63, 12, 4, 42, 79}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 156, 18, 211, 126, 39}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 160, 214, 215, 70, 245}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 163, 46}, 142}, {{208, 178, 136, 0, 163, 151, 183, 237, 246, 115, 41, 122, 82, 162, 58, 88}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 118, 132, 26, 22, 252, 227, 215, 37}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39}, 142}, {{208, 178, 136, 0, 0, 0, 0, 100, 195, 205, 230, 177, 111, 155, 151, 224}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 103, 255, 64, 20, 206, 218, 150}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 20, 71, 220, 254, 192, 2, 72}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 63, 207, 210, 151, 154, 44, 162}, 142}, {{208, 178, 136, 0, 0, 0, 179, 217, 6, 177, 85, 65, 117, 7, 135, 64}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 78, 92, 16, 140, 160, 12, 176, 202}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 253, 139}, 142}, {{208, 178, 136, 0, 0, 0, 0, 31, 35, 124, 174, 205, 174, 105, 118, 186}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 56, 85, 62, 24, 137, 100, 237}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 237, 2, 23, 47, 145, 110}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 99, 241, 30, 133, 155, 120, 247, 74}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 16, 16, 107, 206, 251, 150}, 142}, {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 67, 89}, 142}, {{208, 178, 136, 0, 0, 0, 78, 211, 160, 194, 161, 22, 10, 108, 58, 142}, 142}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 27, 68}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 203, 135, 255, 92, 228, 143}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 224, 58, 245, 129, 129, 20, 213}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 129, 26}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 141, 133, 222, 72, 113, 124, 171, 147}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 146, 89, 155, 178, 55}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 113, 17, 61, 28}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 192}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 109, 67, 131, 167, 9, 46, 219}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 212, 134, 9, 52, 98}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 45, 156, 108, 110, 102}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 28}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 176}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 108, 64, 18, 40, 112, 119, 204, 51}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 180, 16, 122}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 206, 187, 233, 95}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 88, 227, 79, 158, 134}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 5, 100, 240, 214, 167, 161}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 214, 77, 146}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 7, 2, 218, 1}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 171, 177, 228}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 152, 0, 132, 111, 163}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 79, 5}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 21, 200, 112, 176}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 17, 67, 137, 95, 142}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 171, 202, 68, 211}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 128, 149, 31, 130, 229}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 29, 115}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 155, 96, 9}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 16, 157, 207, 255, 31}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 216, 217, 158}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 97, 233, 166}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 56, 253, 172, 24}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 179, 82, 95}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 20, 208, 232, 175}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 29}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 222, 184, 74, 65, 4, 158}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 86, 250, 251, 52, 77}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 46, 216, 92}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 241, 19, 8, 179, 27}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 6, 158, 72, 154}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 5, 184}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 86, 185, 48, 133, 36, 24}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 71, 220, 243}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 245, 222, 85, 237, 92}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 178, 12}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 7}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 59, 130, 163, 103, 222, 17, 125}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 67, 56}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 223}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 222, 194}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 40, 41, 212, 127, 42, 51}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 43, 206, 172, 247, 198, 184}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 249}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 185, 244, 101, 197, 198}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 57, 77, 159, 13, 83, 69}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 150, 195, 58, 117, 108}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 169, 87, 18, 217}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 151, 226, 170, 209}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 225, 51, 236, 84}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 173, 214, 12, 37, 34}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 254, 93, 25}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 157, 255, 123, 28, 58, 165, 169}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 203}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 76}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 98, 43}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 191, 64}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 157, 166}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 59, 59, 60, 1, 104}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 248, 161, 149, 215, 82, 180}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 132, 214, 96, 107, 58}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 185}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 44}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 30, 143}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 119}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 154, 57, 131, 82, 6}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 206, 15, 147, 246, 165}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 231, 163, 161, 165, 37, 9}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 228, 206, 136, 168, 207, 200}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 169, 235, 255, 92, 86, 86}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 202, 110, 104, 116, 49, 179, 160}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 10, 64, 29, 124, 209, 243}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 131, 87, 63, 47}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 41, 246, 159, 82, 110, 195}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 19, 61}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 42, 137, 30, 174, 237, 9, 117}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 127, 120, 202}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 139, 73, 71, 210}, 18}, {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 92, 11}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 74, 163}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 63}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 33, 160}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 221, 39}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 236, 104}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 39, 110}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 83}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 86, 34}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 40}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 194, 94}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 117, 191}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 162, 147}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 216}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 110, 64}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 89, 96}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 91}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 184, 103}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 201}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 16, 23}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 170, 197}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 4}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 196}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 176, 187}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 224, 56}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 82, 47}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 195, 203}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 130}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 114, 160}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 195, 93}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 146}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 149, 21}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 86, 247}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 106}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 170, 173}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 34}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 8}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 239}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 36, 153}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 119, 253}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 194, 112}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 232, 41}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 107, 112}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 201}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 94, 220}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 255, 30}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 15}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 233, 219}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 84}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 71}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 118}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 231}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 7}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 199}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 92, 233}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 19, 243}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 11}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 173}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 180}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 175, 184, 84}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 122, 97, 47, 111, 222, 145, 50, 3}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 58, 213, 117}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 42, 78, 225, 154, 226, 31, 73, 155}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 112, 155, 100, 94, 132, 55, 162}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 246, 210, 144, 133, 173, 80}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 237, 51, 106}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 164, 159, 212, 43, 192, 63, 195, 125}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 95, 164, 181, 91, 101}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 83, 10, 35, 214, 92, 78}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 119, 205, 12, 170, 186}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 82, 170}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 207, 179, 69, 100}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 186, 78, 82, 157, 233, 92, 217, 27}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 139, 7, 44}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 85, 9, 100, 201, 235, 11, 137}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 18, 29, 88, 220, 84, 185}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 157, 9, 129, 161, 195, 140}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 254, 30, 77, 48}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 128, 9}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 103, 192, 90}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 158, 210, 193, 150}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 43, 131, 74}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 135, 175, 20, 209, 145, 69}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 15, 35, 69, 29, 45, 214, 4, 119}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 48, 16, 36, 64, 201}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 215, 170, 114}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 168, 138, 119, 155, 114, 64, 155, 21}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 252, 36, 34}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 152, 204, 54}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 80, 8, 176, 23, 150, 28, 245, 181}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 238, 95, 208, 152, 177}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 7, 71, 32, 46, 212, 178}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 57, 9}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 85, 114, 153}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 151, 107}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 151, 194, 113, 204}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 82, 159, 127, 179}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 243, 145, 250, 21, 210, 188, 177, 146}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 44, 37, 72, 90}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 159, 176, 72, 220, 125, 160, 101, 197}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 120, 59, 58, 154, 151}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 192, 54, 215}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 88, 119, 111, 237, 72, 250}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 31, 176, 116}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 47, 182}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 84, 215, 130, 221, 93, 237, 144, 39}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 143, 239, 124, 208, 129, 20, 124}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 191, 155, 150}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 62, 20, 89, 2, 156, 10, 136}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 130, 117, 23, 0, 92, 239}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 151, 249, 240, 111, 164, 191, 117, 76}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 166, 2, 89, 248, 139, 93, 2}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 131, 100, 9, 122, 224, 24, 86}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 57, 236, 210, 7, 8}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 103, 183, 189, 136}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 24, 212, 70, 94, 46, 70, 73}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 20, 69, 161, 71, 110, 190, 154}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 142, 91, 80, 137, 208}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 73, 141, 96, 239, 181}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 219, 172}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 24, 44, 106, 233, 57, 0, 205, 96}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 230, 176, 144, 180, 90}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 233, 41}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 241, 228, 20, 170, 96}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 86, 204, 184}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 81, 118, 20, 90, 5, 36}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 82, 10, 84, 174, 69, 68, 59}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 120, 251, 103, 202}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 202, 138, 122, 66}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 129, 20}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 248, 223, 15, 157, 98, 102, 78, 73}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 64, 183, 135, 2}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 111, 49, 81, 159, 110, 137, 71}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 205}, {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 180, 168, 146, 25, 70, 8}, 205}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 89, 202, 241, 169, 247, 23}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 218, 238, 94, 196, 120, 241, 98}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 209, 170, 241, 72}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 99, 6, 222, 114, 240, 129, 35}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 116, 156, 164, 149, 245}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 51, 177, 191, 196, 175, 228, 55, 46}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 13, 99, 181, 110, 77, 129, 7, 45}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 20, 100, 119, 72, 55}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 132, 107, 159, 73, 80, 229}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 156, 219, 48, 117, 252, 105}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 169, 219, 64, 206}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 236, 194, 117, 248, 40}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 29, 6}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 60, 70, 189, 240}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 220, 108}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 161, 114}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 69, 243, 90, 103, 75, 12}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 19, 230, 239, 43, 41, 195, 232}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 21, 0, 10, 173}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 132, 164}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 45, 223, 186, 13, 60, 146}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 134, 180}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 194, 192, 37, 3, 64, 146, 168}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 225, 58, 37, 21, 105, 196, 154}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 116, 175, 204}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 240, 233, 242, 120, 236, 59}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 109, 139}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 70, 11, 238, 195, 118, 46}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 64, 220}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 169, 232, 42, 240, 168, 138, 104}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 133, 115, 35, 98, 47, 8}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 56, 250, 114, 236, 252, 200, 61}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 32, 217, 254, 155, 16, 91, 227}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 23, 67, 213, 122, 173, 203, 37}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 131, 233, 202, 76, 24, 121, 5, 24}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 214}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 147, 78}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 86, 197, 162, 218, 1, 78, 252}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 109, 99}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 67}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 221, 133, 98, 50, 127}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 124, 228}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 34, 133, 232, 168, 206, 209, 24, 34}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 210, 202, 79, 248}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 61, 171}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 48, 62, 84, 244, 143, 221, 100}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 250, 9, 97, 227}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 138, 151, 135, 210, 150, 18}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 203, 156, 56}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 186, 246, 184, 218}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 110, 238, 239, 250, 15, 220}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 253, 51, 61, 160, 73}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 42, 49, 159, 29}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 24, 104, 54, 19, 173, 230, 37}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 156, 102, 88, 121, 110}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 137, 204, 97, 117, 198, 216}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 164, 242}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 180, 99, 201, 34, 99, 177, 13}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 250, 141, 248, 110}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 33, 25, 190, 20, 19}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 167}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 202, 92, 15, 255}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 15, 111}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 155, 28, 4, 236, 146}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 54, 10, 232}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 207, 233, 138, 35, 34, 248, 172, 223}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 102}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 32, 246, 170}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 244, 23}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 243, 165, 17, 172, 66}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 112, 9, 132, 194, 221, 60}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 78}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 51, 213}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 124, 56, 140, 230, 136, 210, 93, 173}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 76, 83, 207, 143, 3, 14}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 27}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 235, 66, 91, 73, 16, 135}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 212, 39, 210, 30}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 105, 204, 243, 185, 232, 153}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 144, 85, 59, 77, 218, 241}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 231, 180}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 132}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 96}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 198, 56, 43, 218, 191, 13, 108, 42}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 94}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 202}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 70}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 69, 255}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 171, 72, 58}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 148, 44, 254, 91}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 143, 178, 165, 60, 20, 24, 89}, 251}, {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 183, 73, 248, 62, 211, 84, 59, 155}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 124, 222, 107, 121, 192, 255}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 68, 118, 39, 83, 184, 214}, 178}, {{185, 202, 148, 0, 0, 154, 124, 84, 243, 212, 250, 142, 103, 122, 29, 192}, 178}, {{185, 202, 148, 0, 0, 0, 129, 223, 151, 221, 99, 220, 206, 172, 121, 211}, 178}, {{185, 202, 148, 0, 114, 195, 137, 26, 212, 221, 130, 154, 165, 105, 208, 151}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 59, 136, 211, 151, 95, 249, 62, 209}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 182, 64}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 50, 159, 122, 225, 148, 195, 52, 62}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 89}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 80, 69, 14, 164, 223, 77}, 178}, {{185, 202, 148, 0, 0, 0, 0, 206, 32, 32, 122, 45, 130, 36, 24, 244}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 39, 83, 1, 44, 1, 209, 254}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 84, 31, 164, 189, 141}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 9}, 178}, {{185, 202, 148, 0, 0, 0, 0, 69, 206, 10, 184, 208, 144, 200, 7, 206}, 178}, {{185, 202, 148, 0, 0, 165, 69, 75, 81, 141, 83, 195, 243, 50, 153, 240}, 178}, {{185, 202, 148, 0, 0, 0, 151, 66, 205, 207, 254, 91, 221, 95, 26, 235}, 178}, {{185, 202, 148, 0, 0, 0, 0, 121, 193, 16, 135, 74, 49, 96, 73, 174}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 137, 179}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 147, 209, 28, 73, 180, 10}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 194, 125, 107, 185, 164}, 178}, {{185, 202, 148, 227, 6, 237, 35, 218, 141, 164, 227, 254, 204, 255, 146, 224}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 239, 91}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 46, 183, 178, 55, 208, 153, 24, 116, 51, 199, 1}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 26, 166, 202, 42, 114}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 194, 176, 51, 79, 117, 236, 125}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 93, 33, 69, 227, 187, 24}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 176, 108}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 205, 239, 58, 147, 150, 175}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 179, 97, 133, 147, 247, 249, 138, 46, 169, 160}, 178}, {{185, 202, 148, 0, 0, 6, 159, 37, 214, 169, 95, 27, 103, 19, 251, 221}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 31, 237, 147}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 75, 2}, 178}, {{185, 202, 148, 0, 0, 63, 206, 117, 216, 228, 91, 194, 175, 36, 141, 199}, 178}, {{185, 202, 148, 0, 0, 75, 29, 7, 6, 178, 177, 122, 81, 243, 94, 3}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 117}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 238, 189, 195, 211, 126, 71}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 87, 194, 14}, 178}, {{185, 202, 148, 0, 0, 233, 84, 23, 18, 7, 229, 190, 184, 113, 36, 70}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 74, 164, 30, 66, 54, 185}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 143, 47, 61, 94, 94}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 91, 152, 245, 157, 255, 36}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 178}, {{185, 202, 148, 0, 118, 90, 22, 107, 88, 231, 74, 46, 142, 138, 49, 217}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 252, 170, 16, 90, 62, 111, 220}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 143, 227, 68, 110, 226, 204}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 202, 131, 211}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 45, 146, 51, 0, 241, 234, 211, 65}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 151, 147, 190, 211, 252, 102, 197}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 187, 188, 119, 44, 83, 0, 140, 203}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 51, 226}, 178}, {{185, 202, 148, 0, 0, 0, 0, 6, 240, 89, 152, 226, 92, 208, 201, 19}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 83, 232, 62, 73, 29, 204, 141, 152}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 209, 195, 99}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 178}, {{185, 202, 148, 0, 0, 168, 0, 154, 72, 122, 184, 106, 221, 154, 66, 241}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 121, 230, 121, 63, 26, 244, 77, 64}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 77, 170, 125, 178, 61}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 73, 142, 208, 9, 226, 46, 221, 197}, 178}, {{185, 202, 148, 0, 60, 123, 115, 83, 177, 26, 217, 150, 115, 163, 240, 11}, 178}, {{185, 202, 148, 0, 0, 0, 28, 233, 169, 253, 171, 152, 77, 37, 238, 232}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 144}, 178}, {{185, 202, 148, 0, 205, 221, 71, 98, 242, 124, 82, 1, 119, 136, 248, 96}, 178}, {{185, 202, 148, 0, 0, 0, 0, 156, 77, 35, 252, 69, 70, 58, 3, 120}, 178}, {{185, 202, 148, 0, 0, 0, 134, 175, 41, 51, 252, 79, 33, 246, 137, 171}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 17, 240, 76, 25, 232, 237, 84, 86, 225}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 75, 151, 157, 205, 94, 28, 230}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 250, 242, 136, 15, 227}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 60, 13, 184, 171, 99, 162, 208, 229}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 238, 242, 222}, 178}, {{185, 202, 148, 0, 0, 112, 149, 168, 252, 129, 38, 8, 0, 126, 177, 31}, 178}, {{185, 202, 148, 0, 0, 0, 0, 98, 2, 53, 30, 114, 112, 165, 167, 234}, 178}, {{185, 202, 148, 0, 0, 0, 0, 202, 136, 236, 29, 248, 50, 116, 146, 54}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 223}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 63, 169, 156, 73, 255}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 32, 174, 80, 166, 245, 190, 76}, 178}, {{185, 202, 148, 0, 97, 125, 10, 116, 101, 6, 239, 21, 177, 73, 217, 43}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 116, 1, 64, 79, 255, 133, 32}, 178}, {{185, 202, 148, 0, 0, 0, 109, 118, 117, 178, 30, 99, 99, 214, 246, 202}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 39, 121, 60, 16, 22, 227, 42}, 178}, {{185, 202, 148, 0, 0, 0, 0, 107, 49, 127, 113, 153, 255, 63, 222, 128}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 178}, {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 178}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 65, 215}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 137, 66, 172, 155, 231, 218, 128}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 87, 191, 226, 64, 186, 5, 113, 196}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 78, 184, 8, 126, 189, 207}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 177}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 34, 52, 133, 217, 249, 109, 203}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 197, 61, 218}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 69, 22, 168}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 195, 200, 160, 95, 135, 9}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 123, 62}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 79, 196}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 134, 72}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 159}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 162, 80, 26, 129, 99, 180, 62}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 222, 139, 236, 213}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 81, 26, 36, 194, 251, 235}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 235, 47, 146, 183, 157, 145}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 185, 188, 186, 38, 155, 114, 190, 242}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 235, 123, 220, 179, 171}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 15, 129, 39, 242}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 75, 151, 67, 114, 6, 150, 120, 111}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 43}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 234, 71, 236, 74, 20, 125, 51}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 5, 89, 105}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 26, 173, 191, 23, 44, 50, 108}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 165, 42}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 48, 235}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 41}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 37, 218, 225, 61, 233, 81, 64}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 76, 63, 101}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 5, 130, 252, 179, 1, 24}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 171, 58, 1}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 76, 155, 239, 239, 192, 85, 73, 209}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 128, 60, 235, 145, 247, 94}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 206, 11}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 250, 115, 56, 175, 99, 153}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 147}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 38}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 44, 198, 182, 236, 71}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 152, 124, 198}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 203, 226, 99, 45, 221, 255}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 239, 171, 91, 207}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 82, 92, 66, 46}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 58, 154, 128, 130}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 60, 193, 72, 77}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 155, 174, 43, 31}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 97}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 18, 61}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 77}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 220, 71, 224, 83, 205}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 5, 73, 109}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 74, 170}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 82}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 169, 202, 90}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 65, 124, 182}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 27, 117}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 1, 229, 189, 19, 160}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 29, 141, 243, 142, 84}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 70, 89, 234, 123}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 39}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 244, 196}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 23, 155, 32, 74}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 72, 116, 40}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 141, 244, 42}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 233, 35, 230, 247, 66, 32}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 39, 149, 72, 26, 16}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 137}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 221}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 138, 152, 185, 91}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 51, 11, 170, 214, 49, 172, 111, 12}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 99, 129, 156, 8, 186, 61}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 143, 188, 110, 185, 131, 202, 233}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 87}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 75, 152, 186, 68, 62, 173, 194, 243}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 193, 69, 159, 246}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 178, 17, 167}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 220, 251, 145, 182, 38, 253}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 164}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 89, 254, 16, 203}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 84, 120, 167}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 109, 126}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 162, 206}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 147, 219, 198, 144, 172, 167, 151}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 122, 21, 255, 73, 35}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 28}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 37, 150, 46, 35}, 198}, {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 190, 24, 5, 244, 245}, 198}, {{69, 181, 5, 227, 64, 0, 84, 18, 169, 215, 176, 29, 238, 109, 76, 141}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 76, 161, 239, 2, 145, 75, 48}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 215, 207, 99, 108, 84}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 140}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 73, 138, 88, 73, 9, 67}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 28, 171, 45, 14, 77, 161}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 129, 204, 33, 198, 107, 105, 240, 44}, 84}, {{69, 181, 5, 227, 64, 0, 50, 76, 145, 124, 122, 241, 239, 120, 40, 12}, 84}, {{69, 181, 5, 227, 64, 0, 7, 231, 190, 8, 124, 27, 24, 15, 33, 66}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 238, 99, 171, 54, 225, 204}, 84}, {{69, 181, 5, 227, 64, 67, 212, 69, 210, 18, 158, 229, 141, 112, 136, 215}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 150, 139, 25, 141}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 48, 70, 165, 6, 7, 239}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 129, 190, 45, 169, 39, 168, 235}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 166, 68, 28}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 216, 88, 212, 225, 108, 75, 217, 241}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 129, 235, 239, 227}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 228, 230, 108, 196, 120, 80, 121, 14}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 154, 91, 64, 246, 0, 59, 173, 80}, 84}, {{69, 181, 5, 227, 64, 0, 152, 26, 83, 123, 68, 110, 25, 219, 155, 29}, 84}, {{69, 181, 5, 227, 64, 0, 217, 240, 146, 188, 31, 74, 175, 214, 184, 201}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 42, 100, 220}, 84}, {{69, 181, 5, 227, 64, 0, 0, 225, 176, 33, 67, 168, 152, 79, 94, 243}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 48, 62, 15, 241}, 84}, {{69, 181, 5, 227, 64, 0, 149, 0, 67, 20, 19, 29, 215, 222, 106, 64}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 84}, {{69, 181, 5, 227, 64, 0, 102, 158, 215, 247, 246, 204, 25, 210, 190, 227}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 11, 62, 203}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 75}, 84}, {{69, 181, 5, 227, 64, 0, 93, 91, 151, 52, 59, 215, 141, 214, 236, 86}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 219, 167, 11, 55, 154, 105}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 198, 107, 129, 13, 175, 66}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 206, 144, 170, 111, 149, 113, 96, 58, 193, 24}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 77, 83, 77, 117, 75, 70}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 148, 226, 151}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 178, 96, 171}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 239, 63, 179}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 20}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 153, 206, 116, 67, 175, 169, 241}, 84}, {{69, 181, 5, 227, 64, 0, 0, 111, 235, 201, 147, 251, 141, 132, 17, 170}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 115, 156, 98}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 236, 229, 84, 61}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 147}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 160}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 114}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 175, 208, 88, 110, 167}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 161, 89, 99, 214, 164, 87, 9}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 32, 200, 117}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 53, 10, 10, 7, 58, 197, 142, 28}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 152, 26, 176, 170, 223, 114, 136, 45}, 84}, {{69, 181, 5, 227, 64, 0, 106, 191, 114, 48, 71, 247, 77, 226, 13, 148}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 93, 236, 182, 84, 11, 205, 248}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 4, 172, 105, 160, 110, 9, 96, 62}, 84}, {{69, 181, 5, 227, 64, 0, 0, 250, 25, 250, 0, 250, 103, 68, 146, 180}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 205}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 55}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 1, 146, 242, 5, 227, 146}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 200, 48, 83, 33, 18, 138, 178, 103}, 84}, {{69, 181, 5, 227, 64, 199, 158, 55, 153, 59, 186, 214, 185, 66, 118, 99}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 132, 161, 115, 233, 168, 114, 102}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 31, 186, 140, 195, 94, 12, 163, 220}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 230, 70, 230, 119, 66}, 84}, {{69, 181, 5, 227, 64, 0, 0, 18, 56, 2, 102, 159, 215, 235, 191, 47}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 223}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 231, 90, 155, 199, 48, 58, 139}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 82, 205, 233, 86, 111, 94}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 253, 91, 44, 208}, 84}, {{69, 181, 5, 227, 64, 0, 0, 154, 134, 43, 146, 70, 31, 228, 88, 122}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 203}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 229, 55, 174}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 196}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 24, 151, 227, 26, 116, 177, 186, 143}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 185, 231, 232, 26}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 204, 77, 218, 124, 26, 99}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 21, 58, 112, 184, 85}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 47, 4, 118, 57, 246}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 84}, {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 106, 112, 196, 144, 11, 68}, 84}, {{69, 181, 5, 227, 64, 0, 161, 202, 130, 130, 94, 184, 44, 162, 177, 62}, 84}, {{69, 181, 5, 227, 64, 250, 236, 97, 21, 190, 201, 0, 196, 147, 100, 78}, 84}, {{69, 181, 5, 227, 64, 73, 157, 130, 109, 97, 111, 171, 50, 197, 73, 187}, 84}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 245, 211, 3, 94}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 217}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 152, 54, 56, 132}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 37, 209, 115, 250}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 199, 75, 8, 43, 165, 189, 81}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 23, 175, 7}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 177, 1, 130, 235, 95, 154}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 131, 50, 43, 19, 248}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 54, 197, 129, 73, 223}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 223, 219, 11, 163, 32}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 226, 19, 144, 111, 149, 249, 241}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 28, 210, 208, 87, 243}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 168, 253, 55}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 156, 241, 93, 201}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 193, 196, 82}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 114, 99, 74, 3, 224, 175}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 15, 205, 231, 64, 153}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 130}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 209, 166, 139, 21, 239, 161}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 119, 130, 62, 242, 129}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 239, 65, 244, 196}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 7, 196, 83, 163, 241, 194}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 160, 248, 15, 242, 24, 106}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 65}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 111, 17}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 114, 45, 221, 16, 198, 192, 11}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 252, 121, 223, 85, 115, 159, 43}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 27, 237, 131}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 223, 168, 219, 129}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 41, 135, 46, 28, 130, 187, 166}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 79, 148}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 121, 110, 56, 246, 167}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 193, 84, 86, 73, 170, 105, 58}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 253, 229, 137, 238, 22}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 158, 120, 114}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 107, 127, 172, 251, 248}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 160, 73, 170, 135, 217}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 7, 251, 191}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 61, 197, 186}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 194, 119, 250, 65, 115, 155}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 130}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 106, 162, 206, 213, 11, 62, 22}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 252, 14, 239, 244, 10}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 27, 45, 179}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 60, 207, 255}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 58, 232}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 43, 47, 206, 156, 229}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 107, 52}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 136}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 226, 33, 99, 16, 47, 13}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 121, 155, 182}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 225, 207, 175, 192}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 78, 205, 36, 43, 25}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 113, 141, 120, 218, 131}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 4}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 229}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 56, 188, 249, 255, 42, 17}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 238, 143, 107, 183, 85, 185, 5}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 206, 155, 86}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 91, 228, 85, 164}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 188, 124, 154, 121, 40}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 50}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 8, 183, 214, 5, 137}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 171}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 83, 81, 212, 165, 196, 139, 185}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 33, 1, 28, 42, 73, 158, 103}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 88}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 237, 126, 229, 88}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 193, 73, 230}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 207, 151, 52, 205}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 160, 248, 107, 109, 94}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 14, 156, 44, 173, 212, 73, 23}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 195, 164, 226}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 25, 66, 153, 99, 189, 88, 196}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 18, 195, 123, 94, 222, 207}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 93, 193, 217, 87, 108}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 36, 12, 40, 129, 187}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 60, 3, 108, 86, 125}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 82, 54, 23}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 227, 153, 243, 70, 147, 230}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 46, 237, 236, 86, 19, 205}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 207, 82, 174, 140, 118}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 153, 217, 146, 186, 157, 243, 225}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 103, 172, 156, 8, 96, 134}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 75, 36, 95, 176, 233, 159}, 128}, {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 128}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 148, 128}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 158}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 187, 223}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 72, 112, 12}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 184}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 138}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 134, 86, 97}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 81, 243}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 139, 112}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 102}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 87, 51}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 87}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 216, 150}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 43}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 136}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 232}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 78, 184}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 192, 92, 91}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 249}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 123, 136, 204}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 92, 110}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 153, 237}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 166}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 2, 9}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 18, 204, 27}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 151, 203}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 52, 117, 175}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 15, 22}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 23}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 77, 235}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 104, 241}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 27}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 142}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 137}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 168, 194, 74}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 63, 215, 249}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 109, 213, 192}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 197}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 113, 164}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 100}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 120}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 177, 251, 254}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 94, 188}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 185, 188}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 94, 190}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 189, 121}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 209, 57, 238}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 243, 116, 39}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 172}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 253, 161}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 134}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 51, 182}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 120, 8, 21}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 21, 29, 85}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 54}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 34, 207, 125}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 57, 181}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 249, 40}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 164, 236, 195}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 168}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 52, 70}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 178, 146}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 2, 61}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 176}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 42, 51}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 209, 242}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 199, 27}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 17}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 167, 198, 42}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 75}, {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 97}, 75}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 43, 178}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 18, 8}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 165, 67}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 167}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 104, 66}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 237, 50, 84}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 233, 34}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 235}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 226, 84}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 57, 10}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 98}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 44, 156}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 140}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 97, 13, 25}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 254, 173, 200}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 145, 90, 205}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 237, 202}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 84}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 184, 168}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 82, 68}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 2, 250}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 46}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 30}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 192, 254}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 109, 141}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 177, 53}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 129}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 184, 172, 36}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 168}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 93, 35}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 65, 109}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 199}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 235}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 145}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 156, 4}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 82}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 243}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 87}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 210}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 230, 166, 188}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 95, 60}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 242, 44, 207}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 87, 193, 51}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 31}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 84}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 13, 35}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 223, 89}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 184, 227}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 58, 115}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 153, 190}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 116, 180}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 37, 23, 110}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 223}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 99, 68}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 196, 210}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 172}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 71, 251}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 239}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 143}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 2, 136}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 97}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 118, 28}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 29, 82, 189}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 196}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 114, 21}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 222, 160}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 140, 157, 239}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 43, 50, 88}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 122, 232}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 4}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 192}, {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 246}, 192}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 240}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 237}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 54}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 77}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 44}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 63}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 203}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 169}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 55}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 132}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 155}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 61}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 136}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 39}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 47}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 118}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 158}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 128}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 190}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 220}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 252}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 111}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 2}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 71}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 74}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 234}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 108}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 199}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 13}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 220}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 43}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 166}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 94}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 204}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 132}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 88}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 195}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 89}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 171}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 181}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 170}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 41}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 40}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 26}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 196}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 157}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 60}, {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 39}, 60}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 200, 184}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 215, 128, 142, 248, 114, 151, 64}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 4, 104, 91, 77, 238, 114}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 87, 85, 60}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 59}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 144, 115, 131, 55}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 109, 20, 128, 84, 164, 163, 136}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 106, 193, 86, 10, 245, 154}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 49, 65, 150}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 29, 1, 33, 211, 52, 193}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 234, 205, 61, 195, 22}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 120, 157}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 10, 0, 102, 191, 136, 79, 43}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 24, 185, 114, 237, 196, 7, 164}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 63, 6, 152, 58, 172}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 19, 93, 204}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 211, 38, 211, 62, 231}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 118, 204, 55, 221, 161}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 176, 212, 61, 188, 185, 6, 47, 238}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 192, 50}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 172, 248, 106, 44, 47}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 178, 61, 51}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 26, 84, 47, 172, 201, 240, 64}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 156}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 158, 66, 179, 220}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 83, 59, 130}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 89, 22, 127, 98, 193}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 202, 92, 221}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 126, 58, 136, 61, 247, 217}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 137, 20, 251, 107, 104}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 159, 187, 186, 215, 23, 206}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 235, 91, 2, 34, 202, 88, 129}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 105}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 225, 44, 56, 198}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 243}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 194, 216, 101, 157}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 215, 209, 213, 228, 7, 207, 91, 137}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 221}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 230, 56, 105, 222, 63, 175}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 123, 74, 150, 106}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 80, 27, 143}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 38, 57, 39, 91, 223}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 27, 145, 221, 252, 11}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 46}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 80, 113, 240, 125, 79}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 155}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 222, 24}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 54, 229, 126, 186}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 185, 78, 188}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 249, 38, 166, 60}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 72, 163, 57, 249, 20, 63}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 98, 48, 70}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 208, 230}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 159, 18, 191, 75, 254, 86}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 61, 84}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 168, 195, 199, 47, 167, 87}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 76, 102, 10}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 8, 48}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 24, 117, 165}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 47, 116}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 78, 230, 193}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 159, 32, 127, 49, 54, 133}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 34, 141, 22, 8, 32}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 100, 160, 244, 158, 16, 73}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 40, 107, 110}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 88, 49, 11, 106, 231, 162, 171}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 20, 228}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 239, 181}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 222, 131, 212, 208, 224, 10}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 11, 232}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 18, 78, 24, 181, 48, 234, 14, 32}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 25, 222, 44, 74, 74, 204, 150, 224}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 27, 218, 16, 63, 226}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 139, 110, 243, 9, 175, 26, 19}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 54, 49, 211, 141, 34, 240, 25}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 242, 107, 136, 217, 62, 242}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 239}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 209, 102, 246}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 73, 34}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 253, 230, 107, 177, 194}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 173, 149}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 195, 232, 193, 77}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 251, 178}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 76, 53, 54, 211, 126}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 93}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 33, 19, 138, 29, 55}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 53, 186, 35}, 169}, {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 71, 133, 222, 142, 232, 9}, 169}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 101, 103}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 250, 137, 94, 71, 115, 155}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 175, 151}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 115, 231, 211, 121}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 149, 8}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 230, 162, 164}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 88, 109, 241, 116, 155, 59, 57}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 128, 205, 150, 39, 41}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 75, 52, 195, 162, 70, 139, 232}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 116, 246, 250, 240, 151}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 251}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 38, 219, 207, 159, 173, 235, 158}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 122, 243, 53, 157, 67, 15}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 174, 53}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 166}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 135, 243, 55}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 124}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 148, 79, 29}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 253, 228, 94}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 30, 148, 190}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 45, 175, 215, 71, 250, 209}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 184, 196, 163, 23}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 150, 246, 130, 104, 208, 3}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 29, 133}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 48, 219, 154, 205}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 164}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 166, 20, 237, 159, 114}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 203, 94, 141, 150, 16}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 209, 95, 74, 253, 212, 115}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 27, 247, 123, 35, 70, 3, 149}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 56, 231, 210, 253, 224, 182}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 132, 113, 181, 101, 46, 150, 241}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 91}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 182, 145, 184}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 50, 198, 237, 124, 106, 117, 107}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 150, 116, 42, 222, 186}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 80, 47, 2}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 177, 38, 2, 56, 177, 83, 156}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 129, 251, 196, 66, 58}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 91, 246}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 10, 184, 238, 235, 253, 214, 78, 103}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 177, 48, 237, 109, 175}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 22, 81, 132}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 84, 109, 89, 134, 249, 33}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 202, 218, 104}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 164, 50, 181, 56}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 121, 8, 174, 120}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 166, 71, 246, 52, 207, 200}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 104}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 3, 6, 74, 10, 83, 244, 32, 94}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 252, 51}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 48, 144, 88, 193}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 241, 173, 168}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 108, 232, 91}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 165}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 216}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 16, 172}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 128, 207, 170, 15}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 57, 101, 101}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 26, 202}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 53, 84, 201, 100, 250}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 178, 155, 138, 14, 232}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 155, 218, 144, 54, 155, 247, 9}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 105}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 236, 217, 28, 171, 127, 233, 147}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 107, 58, 160, 27, 64, 109, 107}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 156, 248, 198, 178}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 200, 161, 109}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 148, 124}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 52, 106, 127, 52, 33, 5}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 100, 198, 197, 171, 163, 59}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 146, 147}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 23}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 80, 131, 205, 153, 229, 132}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 80, 67, 143, 93}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 133, 12, 242, 118}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 9, 38, 222, 180, 51, 137, 146}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 235, 241, 111, 192, 118, 133, 201}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 70, 197, 19, 143, 58, 195, 245}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 42, 123, 202, 107, 32, 103}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 164, 83, 17, 223, 231, 253, 37}, 10}, {{104, 202, 127, 109, 73, 16, 17, 12, 0, 1, 55, 132, 197, 65, 237, 151}, 10}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 174}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 21}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 222}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 211}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 252}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 28}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 16}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 71}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 233}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 21}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 172}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 69}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 165}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 255}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 80}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 173}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 75}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 64}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 182}, {{119, 208, 0, 0, 0, 0, 0, 158, 105, 122, 160, 140, 166, 229, 40, 225}, 29}, {{119, 208, 0, 0, 0, 143, 220, 41, 199, 243, 86, 223, 156, 147, 192, 176}, 29}, {{119, 208, 0, 0, 0, 59, 183, 81, 89, 133, 95, 254, 43, 112, 162, 104}, 29}, {{119, 208, 121, 112, 157, 133, 186, 141, 214, 221, 24, 221, 164, 226, 164, 161}, 29}, {{119, 208, 0, 114, 68, 248, 168, 38, 255, 219, 224, 9, 72, 153, 155, 150}, 29}, {{119, 208, 0, 0, 0, 0, 0, 13, 166, 17, 94, 210, 96, 169, 16, 23}, 29}, {{119, 208, 0, 86, 98, 82, 55, 65, 157, 201, 195, 60, 195, 107, 155, 219}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 48, 194, 116, 201, 100, 237, 132}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 203}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 8, 120, 89, 53}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 128, 145, 5, 224, 106, 156}, 29}, {{119, 208, 0, 212, 233, 196, 179, 201, 61, 43, 89, 216, 188, 38, 89, 40}, 29}, {{119, 208, 0, 0, 227, 73, 128, 153, 131, 144, 77, 199, 228, 92, 89, 122}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 170, 145, 35}, 29}, {{119, 208, 0, 0, 0, 19, 33, 175, 147, 114, 215, 141, 174, 168, 248, 198}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 140, 35}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 129, 175, 113, 252}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 123}, 29}, {{119, 208, 0, 0, 0, 0, 0, 116, 86, 52, 244, 238, 217, 252, 177, 180}, 29}, {{119, 208, 0, 0, 0, 2, 224, 130, 9, 18, 237, 73, 251, 103, 103, 221}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 73, 115, 56}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 55}, 29}, {{119, 208, 0, 0, 0, 0, 66, 209, 201, 97, 84, 220, 49, 78, 95, 39}, 29}, {{119, 208, 0, 0, 0, 124, 105, 83, 140, 179, 16, 189, 152, 248, 162, 43}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 88, 118}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 29}, {{119, 208, 0, 0, 0, 205, 158, 214, 196, 21, 246, 192, 69, 4, 122, 31}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 48, 9, 216, 76, 131, 216}, 29}, {{119, 208, 0, 0, 0, 0, 0, 22, 242, 208, 11, 53, 247, 13, 200, 198}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 233, 37, 187, 253, 244, 237, 175, 73}, 29}, {{119, 208, 0, 254, 188, 6, 102, 134, 119, 158, 117, 23, 82, 5, 233, 212}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 5, 246, 231, 142}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 125, 186, 33, 145, 228, 87}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 29}, {{119, 208, 0, 0, 0, 0, 0, 68, 61, 99, 2, 48, 57, 7, 79, 31}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 238}, 29}, {{119, 208, 0, 0, 0, 0, 112, 168, 102, 167, 134, 5, 40, 219, 216, 226}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 90, 29, 83}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 29}, {{119, 208, 0, 0, 0, 0, 0, 146, 10, 21, 93, 105, 153, 245, 94, 99}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 243, 123, 252, 245, 167, 100, 75, 233, 126, 10, 34, 150, 94, 97}, 29}, {{119, 208, 0, 0, 0, 0, 0, 166, 121, 135, 22, 233, 219, 29, 68, 63}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 82, 34}, 29}, {{119, 208, 0, 0, 0, 0, 0, 146, 40, 40, 44, 245, 29, 130, 120, 23}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 126, 51}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 45, 119, 16, 181}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 97}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 72, 8, 118}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 218, 119, 103, 35}, 29}, {{119, 208, 0, 108, 213, 89, 12, 167, 44, 120, 45, 16, 56, 225, 202, 147}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 120, 180, 138, 206, 143, 246, 37, 1}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 221, 198, 48, 161, 65, 33}, 29}, {{119, 208, 0, 22, 47, 164, 217, 206, 140, 76, 50, 157, 195, 66, 52, 48}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 20, 239, 99, 14, 195, 161, 66, 40}, 29}, {{119, 208, 0, 0, 196, 90, 178, 9, 235, 179, 66, 195, 238, 54, 72, 225}, 29}, {{119, 208, 0, 0, 0, 187, 204, 110, 206, 231, 27, 83, 122, 119, 152, 238}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 130, 46, 177, 183, 230, 159}, 29}, {{119, 208, 0, 0, 0, 72, 155, 226, 141, 98, 112, 37, 253, 208, 20, 49}, 29}, {{119, 208, 0, 0, 0, 0, 45, 30, 145, 39, 189, 246, 207, 118, 5, 110}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 197, 87, 212, 193, 126, 185, 210, 2}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 66, 9, 100, 183}, 29}, {{119, 208, 0, 157, 134, 24, 153, 138, 174, 231, 202, 58, 52, 179, 54, 39}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 178, 152, 152}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 192, 45, 175, 106, 114, 230}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 249}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 240, 226, 204, 117}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 104, 154, 23, 195, 110, 49}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 0, 0, 0, 0, 221, 96, 50, 12, 83, 55, 80, 189, 96}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 237, 113}, 29}, {{119, 208, 0, 0, 0, 0, 115, 114, 99, 53, 237, 205, 8, 198, 245, 128}, 29}, {{119, 208, 0, 0, 0, 0, 111, 5, 5, 27, 21, 58, 187, 118, 96, 166}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 31, 183, 219, 199, 108, 242, 65, 252}, 29}, {{119, 208, 0, 0, 0, 0, 209, 140, 138, 63, 199, 198, 83, 185, 2, 215}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 125, 210, 224, 77}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 151, 240, 2}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 137, 202, 87, 60, 207, 68}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 214, 109, 78}, 29}, {{119, 208, 0, 0, 0, 0, 0, 28, 19, 196, 171, 26, 199, 32, 150, 115}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 99, 144, 196}, 29}, {{119, 208, 0, 0, 134, 45, 196, 41, 64, 143, 9, 54, 21, 76, 9, 194}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 38, 158, 132, 86, 68, 77, 226}, 29}, {{119, 208, 0, 0, 0, 0, 30, 123, 25, 55, 248, 192, 222, 88, 206, 246}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 29}, {{119, 208, 0, 0, 0, 0, 0, 152, 127, 34, 143, 215, 126, 163, 63, 65}, 29}, {{119, 208, 0, 0, 0, 122, 237, 197, 148, 178, 166, 252, 94, 123, 224, 217}, 29}, {{119, 208, 0, 124, 126, 33, 252, 183, 141, 97, 222, 69, 88, 68, 15, 109}, 29}, {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29}, {{119, 208, 0, 200, 106, 178, 47, 2, 87, 118, 10, 17, 215, 106, 174, 18}, 29}, {{119, 208, 0, 0, 0, 0, 194, 84, 13, 201, 89, 42, 118, 3, 78, 22}, 29}, {{119, 208, 0, 0, 0, 0, 51, 252, 130, 198, 220, 137, 43, 58, 93, 73}, 29}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 92, 43}, 208}, {{160, 0, 0, 0, 0, 130, 169, 84, 68, 180, 90, 102, 25, 81, 137, 1}, 208}, {{160, 79, 126, 50, 129, 117, 160, 142, 47, 161, 230, 109, 12, 176, 79, 247}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 249, 193, 88, 73, 198, 132, 155, 27, 236, 74, 101, 153}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 120, 208, 196}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 223, 134, 113, 93, 82, 222, 161, 232}, 208}, {{160, 0, 0, 0, 0, 0, 232, 17, 4, 93, 27, 236, 102, 150, 109, 177}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 16, 39}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 11, 217}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 40}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 57, 18, 41, 165}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 27, 232, 146, 63, 205, 53, 137}, 208}, {{160, 0, 0, 0, 0, 0, 202, 157, 37, 34, 187, 97, 4, 95, 72, 112}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 243, 6, 72, 192, 159, 164, 47}, 208}, {{160, 0, 0, 0, 184, 157, 112, 149, 120, 116, 143, 251, 58, 17, 220, 147}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 254}, 208}, {{160, 0, 0, 0, 210, 31, 188, 151, 98, 248, 241, 213, 2, 167, 48, 136}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 150, 1, 118, 183, 154, 86, 13}, 208}, {{160, 0, 199, 84, 187, 58, 165, 41, 127, 254, 235, 165, 89, 125, 168, 65}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 208, 152, 59, 46, 232, 69, 95}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 68, 124, 60, 89, 14, 127, 31}, 208}, {{160, 0, 0, 0, 0, 0, 107, 53, 29, 139, 126, 64, 209, 202, 21, 2}, 208}, {{160, 0, 0, 0, 0, 0, 0, 166, 23, 103, 188, 155, 154, 114, 24, 255}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 76, 214}, 208}, {{160, 0, 0, 0, 0, 0, 25, 74, 29, 173, 219, 18, 80, 60, 15, 227}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 27, 58}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 115, 156, 57, 29, 124, 239, 85, 160}, 208}, {{160, 0, 0, 0, 152, 10, 147, 71, 245, 58, 161, 15, 22, 195, 144, 50}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 213, 211, 14, 181}, 208}, {{160, 0, 0, 0, 245, 91, 29, 136, 174, 196, 16, 172, 78, 15, 229, 23}, 208}, {{160, 0, 0, 0, 0, 101, 145, 9, 3, 46, 100, 177, 182, 122, 45, 180}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 88, 228, 178, 212, 115}, 208}, {{160, 201, 123, 135, 142, 102, 69, 59, 176, 158, 237, 17, 188, 174, 54, 147}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 161, 254, 247, 69, 131}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 162, 43, 199, 221, 96, 110, 86, 113}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 232, 42, 225, 254, 143, 116, 126, 31}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 208}, {{160, 0, 0, 45, 11, 243, 208, 128, 180, 12, 5, 202, 14, 74, 161, 125}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 98, 30, 111, 183, 100, 39, 182}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 41}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 59, 164, 42, 2, 147, 11, 92, 176}, 208}, {{160, 0, 0, 0, 0, 0, 2, 155, 244, 160, 147, 44, 249, 93, 150, 141}, 208}, {{160, 83, 20, 184, 116, 105, 36, 14, 113, 15, 22, 226, 174, 144, 24, 2}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 14, 50, 222, 54, 202}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 227, 24, 137}, 208}, {{160, 0, 0, 0, 0, 0, 132, 192, 244, 71, 26, 65, 208, 244, 97, 104}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 208}, {{160, 0, 0, 0, 0, 0, 248, 233, 152, 29, 179, 96, 79, 36, 121, 173}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 50, 79, 199}, 208}, {{160, 0, 0, 0, 0, 0, 225, 4, 147, 129, 149, 30, 67, 233, 24, 65}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 244, 246}, 208}, {{160, 0, 144, 202, 187, 183, 165, 232, 244, 7, 235, 127, 168, 13, 68, 209}, 208}, {{160, 0, 9, 153, 217, 240, 133, 226, 208, 1, 31, 78, 139, 95, 9, 67}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 54}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 185, 42, 229, 129}, 208}, {{160, 0, 114, 226, 127, 60, 127, 52, 24, 201, 180, 107, 34, 198, 92, 79}, 208}, {{160, 0, 0, 0, 47, 246, 179, 120, 192, 58, 146, 52, 243, 174, 184, 22}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 23, 232, 63, 2, 162, 18, 77, 106, 247, 24}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 62, 151}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 206, 230}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 155, 204, 3, 44}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 75, 238, 116, 231, 208, 197, 250}, 208}, {{160, 216, 191, 31, 31, 144, 175, 19, 183, 32, 159, 90, 186, 77, 115, 180}, 208}, {{160, 0, 0, 0, 0, 0, 0, 39, 208, 72, 51, 159, 62, 203, 208, 232}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 25, 230, 157, 79, 91, 173, 162}, 208}, {{160, 0, 0, 0, 0, 47, 4, 113, 4, 226, 135, 162, 0, 195, 251, 154}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 6, 252, 217, 243, 65, 179, 226}, 208}, {{160, 0, 0, 0, 0, 0, 0, 20, 151, 76, 177, 55, 117, 177, 41, 252}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 183, 184, 59, 41, 235, 111, 187}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 132, 227}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 124, 65, 254, 120, 57, 252, 192, 92}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 56}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 109}, 208}, {{160, 0, 0, 0, 0, 0, 0, 53, 236, 100, 239, 157, 0, 255, 248, 185}, 208}, {{160, 0, 201, 32, 78, 23, 76, 139, 35, 134, 220, 152, 148, 121, 14, 118}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 16, 98}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 15, 121, 98, 36, 115, 249, 52}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 235}, 208}, {{160, 0, 0, 0, 0, 0, 34, 67, 15, 56, 88, 166, 182, 97, 124, 87}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 59, 202}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 168, 45, 81, 0, 219, 112, 148, 45}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 82, 153, 155, 124, 133, 1, 87, 197}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 151, 84, 125, 111, 217, 146, 200}, 208}, {{160, 0, 0, 0, 130, 7, 138, 84, 250, 132, 250, 139, 107, 122, 168, 121}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 195, 90, 91}, 208}, {{160, 0, 43, 0, 10, 214, 146, 229, 239, 235, 13, 214, 82, 193, 137, 241}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 87, 29, 64}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 107, 51, 184, 121, 119, 39, 57}, 208}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 124, 241, 106, 89, 190}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 151, 90, 119, 233, 118, 94, 234, 71}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 148, 208, 50, 67, 203}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 226, 202, 115, 84, 53, 9, 97}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 37, 228, 67, 129, 0, 179}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 103, 149, 210, 233, 24, 68, 185, 2}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 38, 43, 108, 249}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 79, 49, 43, 223, 101, 171, 188}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 128, 120}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 70, 87, 202, 121, 150, 186}, 93}, {{170, 144, 64, 2, 107, 166, 128, 16, 1, 77, 88, 162, 248, 228, 33, 114}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 223, 140, 1, 93, 150, 29}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 134, 125, 128, 62, 162, 178}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 90, 110}, 93}, {{170, 144, 64, 2, 107, 166, 128, 111, 52, 133, 6, 111, 68, 0, 145, 34}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 39, 40, 208, 121, 41}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 218, 191, 96, 41, 139, 147, 158}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 166, 245}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 108, 13, 155, 123, 89, 92}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 39, 68, 123, 131, 15}, 93}, {{170, 144, 64, 2, 107, 166, 128, 108, 142, 13, 178, 127, 39, 122, 7, 242}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 120, 174, 52}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 224, 155, 226, 81, 221, 191, 153}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 159, 30, 129, 195}, 93}, {{170, 144, 64, 2, 107, 166, 128, 89, 19, 69, 203, 24, 51, 253, 50, 61}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 205, 132, 8, 250, 86, 217, 253, 213}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 187, 157}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 199, 207, 153, 252, 150, 179, 116}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 12, 11, 198, 30, 243}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 63, 204, 145, 123, 82, 83, 222, 112}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 44, 0, 21, 201}, 93}, {{170, 144, 64, 2, 107, 166, 128, 160, 252, 121, 221, 79, 58, 92, 223, 11}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 32, 88, 1}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 68, 68, 114, 245, 236, 88}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 101, 251, 224, 90, 136, 39, 109}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 69, 51, 6, 66, 206, 49, 82}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 131, 15, 87}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 164, 53, 56, 142, 253}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 246, 213}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 126, 245, 79, 57, 82, 78, 42}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 167, 23, 51, 128, 176, 149}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 71, 217, 73, 243}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 185, 42, 18, 27, 38, 76, 6, 49}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 225, 166}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 203, 81, 10}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 97, 204, 17, 2, 229, 244, 20, 107}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 119, 114, 48, 75}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 47, 174}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 71, 59, 82, 29, 204}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 16, 145, 61, 242, 114, 22}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 215, 34, 56, 24, 166, 60}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 185, 68, 196, 239}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 160, 148, 207, 64, 230, 15, 22, 106}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 33, 218, 231, 57, 39, 183, 221}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 234, 127, 227, 168, 35}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 76, 247, 5}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 17, 36, 50, 238, 143}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 176, 38}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 241, 78, 111, 117, 71, 5}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 2, 42, 178, 58, 191}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 51, 31, 46, 55, 223, 72, 28, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 65, 176, 240}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 63, 155, 243, 199}, 93}, {{170, 144, 64, 2, 107, 166, 128, 187, 28, 18, 41, 170, 75, 21, 199, 77}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 145, 242, 15, 11, 159, 178, 95}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 31, 12, 233, 31, 144}, 93}, {{170, 144, 64, 2, 107, 166, 128, 148, 92, 122, 218, 180, 138, 117, 107, 159}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 46, 14, 13}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 125, 143, 156, 108, 1}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 178, 113}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 231, 75, 142}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 126, 90, 78, 76}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 132, 182, 164, 176, 128, 124, 224, 30}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 77, 78, 1, 229, 186, 242, 158, 92}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 153, 143, 144}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 177, 43, 100, 2, 246}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 205, 70, 54}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 202, 86, 201, 16, 124, 217, 224, 243}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 232, 49, 127}, 93}, {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 93}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 121, 209, 66, 83, 240}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 110, 192, 203, 220, 238}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 128, 188, 126, 25, 70, 156}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 233, 167, 200, 142}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 177, 125, 140, 63, 47}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 135, 205, 185, 102}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 241, 122, 18, 252, 56}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 167}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 61, 60, 22, 212}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 50, 182, 1, 163, 101, 214}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 56, 146, 228, 140}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 41, 68, 111}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 42, 155, 212, 39, 169, 195}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 91}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 14, 170, 15}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 124, 44}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 204, 100, 82, 34, 130, 121}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 146, 160, 240}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 171}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 98, 82, 213, 50, 246}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 80, 97, 255, 149, 130}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 68, 81, 216, 110}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 249, 191}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 35, 128, 189}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 187, 216, 126, 40, 27}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 226, 94, 23, 29, 161}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 248, 241, 72}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 113, 250, 248, 228, 65}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 83, 143, 79, 41}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 75, 49, 91, 216}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 242, 189, 175}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 159, 65, 18}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 230}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 125, 125, 244, 139, 98}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 222, 201}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 26, 73, 165, 67, 183}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 241, 135, 22, 172}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 168, 112, 175, 181}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 224, 111, 68}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 10, 29, 134, 15}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 126, 73, 204, 40}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 85, 55, 220, 248, 248, 249}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 11, 133, 3, 216, 41, 133}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 253}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 246, 59}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 65, 87}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 127, 129, 80, 242, 37}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 162, 117, 22, 4}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 41}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 1, 47, 141, 212, 98, 139}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 174, 246, 44, 248, 52}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 226}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 164}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 3, 78}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 3}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 231, 107, 67, 128, 202}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 12}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 1, 225, 246}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 83, 217}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 228, 137, 174, 128}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 99, 40, 177, 171, 155}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 210, 153, 147, 80, 163}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 154, 205, 129, 72, 214}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 189, 77, 164, 152}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 186, 179, 110, 73, 170}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 241, 112, 96}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 203, 142}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 198, 55, 186, 229, 114}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 39}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 117, 126, 13, 22}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 119, 80, 33}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 189}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 24, 145}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 178, 170, 92}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 244, 60, 72, 174, 28, 231}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 176, 188, 156, 232, 161}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 49, 102}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 89, 190}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 201, 141}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 75}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 51}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 219, 213, 105, 48}, 228}, {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 161, 56}, 228}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 137, 58, 7, 95, 53, 65, 171}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 123, 208, 14, 151, 10, 128}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 165}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 197, 14, 48, 190, 11, 231}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 252, 197, 165, 174}, 236}, {{147, 237, 16, 120, 192, 0, 0, 187, 43, 76, 237, 167, 208, 97, 163, 197}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 47, 124, 167, 173, 122}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 211, 144, 183, 203, 240}, 236}, {{147, 237, 16, 120, 192, 83, 8, 213, 183, 115, 58, 188, 208, 89, 29, 74}, 236}, {{147, 237, 16, 120, 192, 0, 161, 82, 50, 122, 13, 231, 236, 66, 165, 134}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 236}, {{147, 237, 16, 120, 192, 0, 0, 125, 24, 134, 24, 210, 172, 110, 63, 53}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 250, 89, 34, 1, 210, 42, 138, 229}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 75, 190, 40}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 225, 233, 109, 118, 133}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 219}, 236}, {{147, 237, 16, 120, 192, 0, 240, 151, 205, 226, 249, 243, 84, 20, 192, 90}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 45, 71, 52, 225}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 235, 223, 144, 240, 143, 89, 34, 228}, 236}, {{147, 237, 16, 120, 192, 0, 0, 254, 13, 31, 144, 37, 238, 222, 68, 85}, 236}, {{147, 237, 16, 120, 192, 0, 95, 128, 92, 78, 238, 97, 123, 14, 182, 18}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 56, 252, 161, 245}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 216, 90, 124}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 36, 158, 43, 160, 0, 132, 119}, 236}, {{147, 237, 16, 120, 192, 0, 164, 199, 194, 159, 163, 75, 176, 193, 47, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 139, 164, 191}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 222}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 105, 125, 203, 33, 244, 146, 250, 72, 255, 35}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 105, 114, 120, 107, 75}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 147, 50, 142, 209, 34, 56, 34, 216, 195, 84}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 208, 13, 138, 111, 88, 95, 47, 132}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 65, 212, 150, 140, 130, 100, 110, 254}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 236}, {{147, 237, 16, 120, 192, 0, 74, 127, 195, 4, 64, 192, 76, 14, 116, 71}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 176, 240, 119}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 20, 142, 54, 54, 24, 99, 12, 233}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 12, 173, 40, 201, 74, 106}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 163, 199, 2, 236, 194, 179}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 178}, 236}, {{147, 237, 16, 120, 192, 0, 27, 12, 26, 132, 160, 45, 97, 88, 227, 26}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 245, 218, 37}, 236}, {{147, 237, 16, 120, 192, 0, 199, 233, 73, 203, 20, 173, 195, 52, 243, 65}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 116}, 236}, {{147, 237, 16, 120, 192, 0, 138, 70, 49, 241, 184, 65, 174, 87, 217, 47}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 236}, {{147, 237, 16, 120, 192, 0, 154, 225, 103, 53, 21, 24, 186, 36, 93, 218}, 236}, {{147, 237, 16, 120, 192, 0, 22, 73, 202, 216, 47, 240, 125, 55, 233, 77}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 162, 34, 95, 126, 213}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 73}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 85, 11, 135, 70, 184, 39}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 17, 9, 157, 106, 5, 239}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 238}, 236}, {{147, 237, 16, 120, 192, 0, 0, 150, 41, 154, 156, 155, 185, 174, 87, 18}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 174, 53, 55, 86, 207}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 86}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 188, 141, 158, 117, 110, 202, 83}, 236}, {{147, 237, 16, 120, 192, 0, 194, 120, 66, 58, 230, 37, 214, 171, 152, 128}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 240, 110, 136, 214, 121, 225}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 133, 27, 64, 172, 176, 110}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 54}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 187}, 236}, {{147, 237, 16, 120, 192, 0, 208, 120, 102, 215, 127, 21, 255, 196, 240, 113}, 236}, {{147, 237, 16, 120, 192, 0, 0, 108, 253, 248, 4, 207, 178, 127, 233, 214}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 84, 247, 44, 108, 75}, 236}, {{147, 237, 16, 120, 192, 0, 0, 129, 174, 129, 219, 0, 65, 249, 53, 52}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 123}, 236}, {{147, 237, 16, 120, 192, 0, 158, 165, 190, 238, 50, 3, 12, 14, 38, 17}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 110, 182, 112, 237, 47, 141, 125, 180}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 244, 132, 68, 154, 219, 252, 58, 49}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 36, 105, 121, 12, 101, 214}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 30, 125, 248, 214, 88, 147}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 169, 176, 191, 208, 89}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 236}, {{147, 237, 16, 120, 192, 21, 223, 85, 223, 47, 94, 24, 130, 245, 196, 140}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 9, 152, 219, 245}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 6, 243, 202, 225, 41, 54, 24, 148}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 162, 152, 226, 8, 55, 175}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 136, 205, 28, 202, 18}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 253, 39, 209, 20, 177, 253}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 248, 162, 244, 66, 57, 211, 198, 230}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 0, 198, 36, 5, 210, 168, 73, 248}, 236}, {{147, 237, 16, 120, 192, 0, 0, 0, 128, 3, 98, 90, 247, 164, 144, 220}, 236}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 48, 215, 239, 34, 200}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 60, 211, 86, 104, 130, 166, 171, 156}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 134, 252, 243, 111}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 165, 132, 74, 87, 218, 180}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 187, 92, 54, 13, 141, 43}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 45, 155, 49, 116}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 201, 172, 251, 203, 245, 212, 247}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 26, 72, 102, 115, 243}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 152, 234, 196, 155, 228, 53, 227}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 53, 236, 65}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 201, 121, 195, 78}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 40, 51}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 163, 51}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 108, 100, 239}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 89, 53, 46, 253, 105, 254, 214, 238}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 192, 158, 79, 185, 207}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 249, 235, 221, 20}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 230, 94, 142}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 132, 158, 210, 231, 10}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 255, 235, 175}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 120, 158, 188, 136, 228, 207}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 85, 54, 100, 199}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 54}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 250, 131, 5, 120, 167, 94}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 139, 226, 42}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 223, 77, 61, 174, 71, 111, 32}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 235, 141, 209, 102}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 19, 50}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 246, 19, 199, 236}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 190, 31, 122, 132, 129, 209}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 159, 167, 33, 200, 129}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 215, 176, 35, 28, 196, 38}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 222, 95, 127, 62, 143, 37}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 68, 28, 22}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 252, 130, 239, 130, 74, 135}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 190, 32}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 117, 179, 208}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 174, 135, 99, 192, 78}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 229, 136, 99, 217, 137}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 246, 125, 238, 112, 143, 145, 226, 222}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 215, 46, 176}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 145, 203, 113, 168, 121, 178, 113, 228}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 72, 128}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 233, 70}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 198, 152}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 198, 141, 141, 69}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 35, 70, 45, 168, 244}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 95, 251, 116, 247, 135, 200, 226}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 164, 62}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 247, 56, 11, 106}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 10, 88, 115, 76, 212}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 120, 206, 44, 97}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 61, 74, 149, 9, 212, 146}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 41, 144, 106}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 114, 204, 144, 122, 181}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 18, 73, 83, 212, 101, 72}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 216, 217, 90, 76, 115, 68, 255}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 122, 111, 224, 133, 76, 127}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 104, 92, 207, 52, 169, 103}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 181, 46, 238, 26}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 240, 102, 47, 66, 79, 167, 111}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 100, 83, 155, 234}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 119, 173, 239, 252}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 139, 175, 101, 170, 115}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 108, 246, 170, 97}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 111, 131, 114, 87, 21}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 46, 127}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 119, 130, 134, 223, 18}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 57, 37, 132, 189, 135, 248, 200}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 49, 190, 110, 239}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 2, 29}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 83, 44, 253, 151, 30, 139, 108, 60}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 159, 81, 251, 165, 74, 134}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 81, 169, 110, 36, 245, 67, 43, 34}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 50, 7, 165, 205}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 183, 226, 47, 105, 171, 140, 250}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 18, 33, 103, 63}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 28, 65}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 206, 134, 177, 250, 11, 151}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 99, 254, 63}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 157, 39, 93, 252, 174, 87, 130}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 190}, {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 190}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 254, 88, 211, 176, 81, 216, 132}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 139, 180, 65, 182, 56}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 232, 63}, 217}, {{116, 148, 142, 240, 10, 253, 128, 249, 77, 255, 182, 227, 243, 10, 41, 32}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 178, 204, 178}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 173, 108, 43, 209, 160}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 11, 66, 194, 245, 177}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 170, 116, 79, 53, 239}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 99, 204, 206, 10, 235, 104, 71, 168}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 44, 98, 47, 230}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 36, 28, 137, 176, 225, 201}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 249, 127, 126, 183}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 54, 189, 2, 77, 172, 139, 135}, 217}, {{116, 148, 142, 240, 10, 253, 128, 71, 51, 225, 94, 67, 235, 177, 69, 15}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 255, 233, 221, 34, 235}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 130, 40, 240, 158, 227, 162, 45}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 183, 216, 85, 94, 93, 86, 173}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 199, 252, 130, 196, 124, 27, 227, 186}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 71, 145, 156, 187, 121}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 123, 151, 200, 2, 48, 203}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 201, 192, 49}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 140, 125, 101, 80}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 195, 162, 60, 64}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 169, 118, 167, 114, 176, 0, 20, 87, 251}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 118, 243, 23, 211, 251}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 35, 242, 191, 123, 109, 206, 113, 172}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 13, 168, 171}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 37, 186}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 190, 131, 87, 229, 97, 47, 45, 181}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 79, 63, 34, 25, 167, 203}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 243, 238, 211, 94, 128, 18, 140}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 175, 228}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 149, 156, 24, 135, 71, 100, 238, 19}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 233, 172, 175}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 84, 232, 145, 248, 158}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 62, 83, 234}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 199, 170, 76, 117, 70, 93, 231}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 247, 203, 76}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 202, 23, 85}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 76, 206, 232, 30, 136, 37, 189, 236}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 193, 146}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 212, 172, 5, 165, 177, 185, 182}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 139, 147, 12}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 154, 63, 86, 59}, 217}, {{116, 148, 142, 240, 10, 253, 128, 222, 10, 150, 147, 73, 189, 113, 230, 130}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 207, 220, 7, 90, 98, 38, 86, 148}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 145, 64, 252, 25}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 142, 242, 53, 90, 189, 126}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 44, 152, 79}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 108, 72}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 49, 102, 199, 192, 25, 111, 122, 97}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 75, 107, 249, 159, 108, 125, 225}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 44, 153, 26, 203, 128, 40, 184}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 102, 226, 239, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 182, 157, 41, 70}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 128, 208, 10}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 26, 200, 43, 215, 19}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 119, 192, 212, 99, 225}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 34, 26, 97, 193, 146, 221}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 52, 34, 170, 45, 175, 43, 6}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 116, 80, 18, 28}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 202, 230, 126, 201}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 39, 121, 192, 54, 120, 248, 66}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 139, 17, 102, 243, 236, 49}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 99, 155, 141, 70, 217, 255}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 77, 49, 246, 83, 32, 243, 234}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 111, 108}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 25, 76, 183, 82, 36, 228, 5, 137}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 52, 240, 168, 174}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 39, 50, 193, 214}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 193, 82, 144, 106, 123, 244, 4}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 60, 17}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 242, 193, 29, 250, 202}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 11, 161, 196, 123, 28, 133, 85}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 84, 24, 54, 126, 101, 131, 3, 243}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 84, 79, 190, 178}, 217}, {{116, 148, 142, 240, 10, 253, 128, 112, 87, 143, 93, 151, 57, 143, 22, 250}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 137, 129, 128, 61, 73, 4, 82, 208}, 217}, {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 172, 65, 238}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 120, 56, 10}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 112}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 135, 236, 254}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 240, 66, 119}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 231, 128, 220}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 90, 132, 57}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 90, 207}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 12}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 19}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 96, 41}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 15, 49, 137, 141}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 179, 103, 207, 16}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 244, 83}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 235, 56, 64}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 210}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 226}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 226, 221}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 208, 97, 186, 98}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 230, 144}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 105, 226}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 41, 181, 80, 10}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 160, 189, 26}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 70, 132}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 137, 12}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 246, 158, 89, 178}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 236, 157}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 129}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 97, 143, 121}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 80, 50}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 185, 89, 47, 112}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 78, 127, 103}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 121, 182, 148, 159}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 169}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 88, 90, 233}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 91, 124, 27}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 254}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 240, 13}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 24, 53}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 140, 218, 58}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 107}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 164}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 56, 50, 229}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 81, 184, 225}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 94, 50}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 246, 41, 227}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 142}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 220, 62, 156}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 225, 133}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 174}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 70}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 89}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 73, 64, 98}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 172, 71, 54}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 87, 209, 63}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 232, 141, 1, 32}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 172, 107, 216}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 18}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 22}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 47, 203}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 75, 182}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 232, 64, 146}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 112}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 75}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 46, 204, 32}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 149, 175}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 183}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 160, 147}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 191, 52}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 80, 22}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 214, 59, 145}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 131, 103, 141}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 63}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 23, 251}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 242}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 167, 9}, 74}, {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 136, 226, 195}, 74}, {{148, 61, 120, 49, 220, 65, 150, 0, 179, 103, 94, 84, 242, 232, 115, 152}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 185, 119, 169, 120, 155, 158}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 39, 213}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 27, 236, 229, 84, 209, 188}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 197, 211, 222, 218, 27, 221}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 214, 231, 60, 9, 149}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 17, 138, 50, 148, 138}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 179, 84, 212, 2}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 137, 160, 229, 247, 165}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 28, 222, 186, 201}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 39, 196, 92, 139, 90}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 215, 82, 31, 121}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 95, 84}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 124, 0, 200, 92, 177, 129, 92}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 225, 47}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 103, 19, 194, 211, 48, 137, 11, 223}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 75, 143, 147, 28, 87, 200}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 207, 22, 67, 46}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 17, 244, 170, 71, 31, 127, 227}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 164, 3, 104}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 139, 41, 123, 124}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 234, 165, 235}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 245, 123, 159, 205, 150, 123, 111, 170}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 188, 112, 148, 123, 253}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 86, 205, 158, 135}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 23, 94, 27}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 187, 247, 50, 162, 175, 48}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 105, 93, 144}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 5, 134, 87, 79, 112}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 231, 22, 196, 4, 86, 173}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 97, 168, 89, 42}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 242, 55, 222}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 108, 250, 158, 200, 178}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 218, 224, 8}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 9, 247}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 24, 65, 172, 49, 52, 127, 35}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 183, 240, 145, 228, 56}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 233, 224}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 20, 164, 153, 72, 45}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 156, 226, 131}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 38, 58, 220, 182}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 79, 253}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 198, 55}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 158, 166, 147, 153}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 50, 96, 228, 38, 97}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 207, 91, 189, 178, 39, 2, 63}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 8, 142, 205, 195, 49}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 128, 29, 132, 68, 155, 71}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 215, 26, 147}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 211, 228, 119}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 47, 135}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 92, 124, 68, 135, 47}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 121, 0, 191, 43}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 42, 117}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 209, 173, 225, 80}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 131, 101, 189, 79}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 196, 236, 106, 200, 195, 232, 169, 95}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 197, 85, 97, 2, 124}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 26, 112, 88, 202, 181, 235, 6}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 197, 103, 125, 61, 162, 3}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 152, 131, 106, 135, 154, 241, 28}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 5, 70}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 18, 254, 0, 73, 122, 141, 20}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 127, 238, 55}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 168, 200, 249, 71, 10}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 90, 176, 223, 198, 183, 172, 203}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 182, 78, 144, 40, 45}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 96, 143, 71, 14, 233}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 123, 69, 17}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 231, 247, 156}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 222, 203, 120, 205}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 9, 94, 220, 23, 114, 214, 37}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 162, 5, 226}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 1, 33, 144, 34, 169, 44, 42}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 157, 77, 67, 116}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 94, 84, 43, 128, 55}, 180}, {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 155, 11, 80, 121, 204}, 180}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 58, 182, 192, 245, 38, 226, 93, 65}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 189, 202, 250}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 20, 229, 125, 168}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 24, 203, 219, 175, 170, 4}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 174, 93, 246, 164, 47, 40, 199, 210}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 147, 5, 237, 132, 44, 251}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 23, 42, 240, 135, 8, 159}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 103, 232, 238, 29, 213}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 79, 251}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 4, 192, 102, 121, 13, 23, 167, 142}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 221, 127, 73, 97, 122, 250}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 39, 10, 250, 246, 197, 24}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 132, 151, 181, 234, 53, 60, 206, 161}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 102, 247, 31, 60, 237}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 186, 157, 149, 50, 42, 89}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 50, 82, 101, 1, 254}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 213, 37, 120, 154, 134, 129, 179, 122}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 183, 42, 72, 210, 121, 102}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 97, 175, 64, 203, 218}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 111, 47, 145, 103, 42, 100}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 195, 41, 10}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 244, 162, 48}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 218, 44, 202, 148, 139, 212}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 121, 12, 223, 229, 214, 238}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 116, 113, 122}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 119, 85, 1, 183}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 238, 61, 96}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 139, 132, 239, 122, 114, 52, 85, 94}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 125, 194, 67, 172, 66, 246}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 23, 13, 143}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 149, 20, 68}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 194, 41, 229, 46}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 67, 216, 66, 64}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 232, 66, 15, 152, 201, 139}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 123, 228, 36, 182, 26, 152}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 78, 43, 174, 252, 135, 244, 70, 86}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 176, 68}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 74, 148, 160, 236, 230}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 60, 244, 28, 67, 138, 169, 30, 210}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 194, 69, 158}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 41, 194, 189, 19, 65, 236}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 223, 153, 190, 222, 15, 10, 157, 56}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 193, 47, 58, 100, 5, 86}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 86, 228, 70}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 208, 11, 238, 50, 134}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 197, 193, 89}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 98, 46, 99, 192, 253, 185}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 98, 95, 124, 222, 227, 145, 92, 190}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 115, 44, 147, 152}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 82, 208, 99, 229, 66, 249, 220}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 58, 57}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 50, 68}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 189, 64, 95, 147, 177, 70, 18, 100}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 104, 133, 172, 129, 53, 242, 230, 33}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 116, 245, 145}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 234, 90, 241, 211, 16, 48, 84}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 88, 199}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 166, 148, 147, 18}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 204, 34, 223, 5}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 193, 195}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 46, 27, 156, 183, 42, 185, 100, 135}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 169, 50}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 30, 2, 100, 100, 83, 91, 227}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 255, 151, 122, 69, 34}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 190, 30, 198, 217, 222}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 254, 60, 55}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 204, 223, 140, 36, 219, 252}, 91}, {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 91}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 92, 96, 184, 60, 103, 21, 130}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 75, 12, 172, 236, 87, 242}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 61, 134, 230}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 17, 141, 27}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 115, 5, 13, 31, 147, 158, 124, 158}, 230}, {{215, 109, 147, 157, 32, 28, 52, 158, 245, 98, 97, 198, 41, 53, 135, 70}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 161, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 7, 193, 112, 187, 123}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 96, 37, 157, 36, 242, 25, 82}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 121, 97}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 124, 228, 117, 90, 83, 134, 35, 44}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 232, 166, 19}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 197, 140, 50}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 14, 176, 252, 70}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 103, 186, 232}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 10, 98, 5, 87}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 94, 50}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 130, 5, 236, 254}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 75, 62, 173, 46, 234, 50, 144, 14}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 111, 164, 218, 61, 96, 128, 87, 147, 130}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 141, 79, 59, 243, 3, 55, 201}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 212, 194}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 239, 210}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 231, 233, 115, 144, 160, 182}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 240, 205, 165, 144, 235, 187}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 129, 227, 17, 159, 27}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 27, 111}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 125, 178, 26, 12, 160}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 176, 227, 210}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 176, 189}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 190, 248, 55, 146, 145, 39, 118}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 69, 50}, 230}, {{215, 109, 147, 157, 32, 28, 52, 164, 219, 47, 147, 114, 16, 162, 81, 2}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 204, 201, 252, 221, 174, 110, 162, 214}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 115, 24, 209, 22, 23, 165, 246}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 73, 193, 37, 243, 46}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 195, 150, 15, 137, 27, 10, 171}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 184, 218, 24}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 73, 158, 81}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 227, 252}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 97, 133, 54, 72, 241, 132, 60, 239}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 131, 131, 124, 242, 175, 55, 149}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 244, 49, 59, 54, 2, 241}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 86, 54, 31, 69, 134, 188, 154, 143}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 218, 99, 144, 211, 182, 253, 121, 21}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 222, 96, 139, 232, 67, 33, 137, 206}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 4, 129, 226, 243, 13, 165, 138}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 194, 125}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 49, 12, 59, 10, 6, 107, 165, 88}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 217, 51, 43, 235, 196}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 71, 34, 48, 253, 61}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 60, 193}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 191, 167, 130, 136, 191, 207}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 5, 54, 176, 213, 175}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 182, 117}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 132, 158, 149, 167, 35}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 149, 244, 78, 163, 239, 232, 11}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 227, 145, 186, 198, 175, 68, 184, 171, 101}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 39, 48}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 154, 119, 125, 200, 63, 250}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 237, 18, 251, 101}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 102, 131, 2, 180, 104, 31, 190}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 176, 31, 236}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 177, 128, 11, 238}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 54, 133, 136, 12}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 227, 221, 248, 209, 74, 90, 17, 224}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 167, 236, 233, 93, 166, 190}, 230}, {{215, 109, 147, 157, 32, 28, 52, 231, 106, 212, 61, 238, 239, 130, 20, 253}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 45, 176}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 27, 201, 228, 84, 25, 143, 162}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 37, 110, 253, 79, 229}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 214, 96, 248, 11}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 198, 106, 240, 24, 185, 150}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 39, 79, 29, 133}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 169, 66, 35, 36, 127, 73, 5}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 254, 227, 179, 158, 134, 156, 200, 164}, 230}, {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 109, 23, 56, 65, 7}, 230}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 92, 221, 48}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 172, 95, 211, 139, 133, 223, 213, 27}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 189, 192, 244}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 181, 72, 125, 69, 245}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 192, 80, 129, 109}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 134, 109, 220, 63, 238, 168, 214}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 86, 9, 157, 46, 251, 208, 118, 133}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 205, 169, 42, 61, 24, 55, 133, 60, 8}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 88, 215, 201, 167, 15, 36, 196}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 123, 150, 46, 205, 42, 20, 49, 230, 86}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 88, 48, 165, 79, 62}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 207, 168, 177, 246, 203, 55, 215, 244, 64}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 138, 217, 99, 246, 211, 45}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 125, 244, 166, 226}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 73, 163, 47}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 233, 21, 13, 228, 17, 23, 21}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 233, 16, 26, 2, 133, 104}, 175}, {{151, 26, 182, 112, 205, 220, 160, 208, 22, 19, 242, 37, 57, 21, 35, 147}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 118, 162}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 45, 115, 41, 142}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 51, 198, 157, 126}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 80, 126, 33}, 175}, {{151, 26, 182, 112, 205, 220, 160, 62, 94, 54, 56, 194, 117, 103, 102, 1}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 234, 87, 206, 192, 41}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 122, 20, 195, 94, 132, 59, 61, 105}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 8, 155}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 238, 68}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 218, 167, 96, 30, 179}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 162, 83, 131}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 23, 217, 6, 214}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 149, 11, 253, 244, 26, 88, 24}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 201, 85, 51}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 239, 116, 242}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 158, 39, 229, 136, 196, 252, 99}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 98, 213, 137}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 252, 93, 218, 141, 41, 26, 118}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 212, 100, 194, 182, 112, 167, 243, 176}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 50, 195, 46, 60, 19}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 175}, {{151, 26, 182, 112, 205, 220, 160, 243, 135, 103, 25, 119, 199, 22, 16, 5}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 77, 71, 66, 35, 71, 29, 55}, 175}, {{151, 26, 182, 112, 205, 220, 160, 9, 182, 142, 137, 17, 234, 40, 63, 171}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 162, 58, 220}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 145, 188}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 222, 156, 55, 101, 239, 173}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 92, 153}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 241, 196, 125, 202, 237, 133}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 254, 101, 176}, 175}, {{151, 26, 182, 112, 205, 220, 160, 140, 37, 36, 25, 67, 75, 213, 130, 184}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 187, 241, 252}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 178, 141, 209}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 22, 155}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 149, 109, 125, 22, 195, 36, 128, 138}, 175}, {{151, 26, 182, 112, 205, 220, 160, 222, 224, 120, 15, 201, 247, 113, 190, 5}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 216, 190, 36, 217, 136, 209, 67, 149}, 175}, {{151, 26, 182, 112, 205, 220, 160, 33, 233, 172, 206, 6, 129, 46, 40, 159}, 175}, {{151, 26, 182, 112, 205, 220, 160, 82, 168, 4, 241, 225, 125, 59, 71, 247}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 158, 201, 112, 178, 174, 65}, 175}, {{151, 26, 182, 112, 205, 220, 160, 204, 209, 202, 113, 84, 34, 177, 87, 68}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 143, 100, 255, 54}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 10, 144}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 225, 126, 134, 237}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 158, 48, 207, 214, 45}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 131, 211, 31, 159, 60, 197, 194, 94}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 42, 200, 37}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 239, 129, 168, 42}, 175}, {{151, 26, 182, 112, 205, 220, 160, 187, 246, 90, 140, 225, 163, 137, 213, 165}, 175}, {{151, 26, 182, 112, 205, 220, 160, 88, 122, 252, 245, 186, 79, 194, 159, 42}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 104, 182, 110, 132, 183, 21, 212, 178}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 172, 173, 129, 62}, 175}, {{151, 26, 182, 112, 205, 220, 160, 88, 128, 36, 188, 131, 8, 137, 185, 173}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 224, 214, 126, 14, 3, 24}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 224, 228, 131}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 214, 44, 195, 196, 155, 108, 164}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 73, 82, 234, 76, 119}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 15, 55, 200, 3, 175, 79, 13, 13}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 1, 63, 173, 127, 99}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 193, 100, 173, 235}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 168, 50, 59, 51, 92, 35, 252}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 99, 97, 121, 88, 146, 96}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 124, 226, 185, 23, 119, 54, 55, 160}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 28, 239, 166, 33}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 234, 251, 20, 74, 136, 46, 81, 220}, 175}, {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 175}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 153, 207, 12, 146}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 18, 104}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 235, 102, 129, 137, 17}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 212, 124}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 125, 160, 2}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 94, 89, 18, 41, 89}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 98, 67}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 82, 26}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 240, 14, 92, 182}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 207, 57, 79}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 94, 202, 189, 33, 49, 190}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 115, 227, 163, 203, 83, 160}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 116, 60, 6}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 153, 160, 109}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 247, 114, 92, 119, 226}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 65, 64, 7, 138, 180}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 201}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 186}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 190, 116}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 213}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 50, 32, 39, 107, 135}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 166, 43, 190, 83, 49, 126}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 140, 134, 247, 12, 156, 201}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 2, 45}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 21, 39, 180, 64, 33}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 173}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 144}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 61, 187, 186, 136}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 203, 99, 48}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 102}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 153}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 7, 52, 160, 49, 67}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 124, 138, 8, 197}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 16}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 47, 13, 171, 33, 144, 86}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 117, 226, 130, 105, 193, 155}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 19, 142, 41, 143, 209}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 15}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 217, 156, 143}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 135}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 228, 5, 167}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 115, 103, 230, 239}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 79, 79}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 232, 205, 239, 243, 186}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 109, 130, 125, 176}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 231, 243, 151}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 50}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 238, 150, 146, 178, 109}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 34, 178, 212, 79, 238, 74}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 244, 228, 247, 190}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 124}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 45, 211}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 15}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 219, 181}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 223, 51, 179, 77, 19}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 172}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 170, 8, 77}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 172, 122}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 124}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 244, 72, 136}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 45, 177}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 196, 58, 246, 104, 62, 90}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 237, 188, 77}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 33, 197, 130, 225, 77, 238}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 25, 141, 102}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 172, 222, 92}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 187, 136, 148, 68, 115}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 243, 4}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 80, 114}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 147}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 103, 122, 66, 49}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 254, 102, 113}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 42, 111, 14, 80}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 120, 24, 67, 139}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 8, 7, 225, 154, 134}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 222, 53, 241}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 223}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 3, 64, 64, 162, 73, 130}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 33, 143, 65, 239}, 171}, {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 171}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 202}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 58, 113, 235, 3, 1, 20}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 230, 66, 58, 72, 117, 133}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 38, 231, 38}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 208, 61, 120, 9, 20, 149, 214, 143}, 113}, {{251, 50, 228, 178, 202, 195, 0, 245, 51, 4, 92, 117, 11, 21, 189, 219}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 173, 6, 141, 222, 77, 188}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 8, 162, 52, 197, 9, 174, 70, 195, 126}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 152, 116, 69, 162, 113, 54, 129, 85}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 180, 180, 25, 99}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 150, 105, 249, 237}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 115, 213, 17, 46, 77}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 136, 97, 162, 196, 96}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 141, 17, 201, 175, 55}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 134, 69, 198, 191, 188, 90, 96, 208}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 41, 52, 198, 188}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 207, 65, 73, 191, 117, 160, 221, 45}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 254, 75}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 72, 124, 170, 203, 114}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 33, 192, 76, 64, 83, 170, 52, 13}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 113}, {{251, 50, 228, 178, 202, 195, 0, 171, 127, 127, 177, 32, 107, 153, 97, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 48, 124, 244, 87, 27, 169}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 175, 38, 248}, 113}, {{251, 50, 228, 178, 202, 195, 0, 27, 207, 229, 165, 28, 100, 75, 181, 253}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 91, 93, 215, 160, 42, 190, 131, 161, 144}, 113}, {{251, 50, 228, 178, 202, 195, 0, 65, 71, 120, 215, 160, 71, 116, 163, 246}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 136, 195, 87, 51}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 189, 8}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 104, 169, 196, 33, 94}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 26, 158, 21}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 169, 60, 68}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 103, 123, 90}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 113, 115}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 223, 29, 163, 177, 32}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 29, 217, 185, 148, 105, 156, 81, 48}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 100, 82, 68, 138, 112, 102}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 226, 147, 71, 191, 199, 189, 224, 97}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 92, 31, 139, 146, 7, 255}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 74, 123, 58}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 254, 119, 102, 213, 65, 71}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 166, 7, 211}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 97, 170, 178}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 95, 43, 198, 146}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 174, 99, 189, 20, 68, 134, 203}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 88, 178, 190}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 72, 0, 172, 143}, 113}, {{251, 50, 228, 178, 202, 195, 0, 192, 245, 12, 19, 119, 91, 14, 112, 167}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 250, 195, 209, 230, 71, 116, 76, 89}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 47, 186, 88, 33, 105, 102}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 154, 53}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 26, 177, 233, 191, 56}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 17, 13, 173, 36, 61}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 29, 94}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 243, 9, 111, 6, 20, 115, 146, 112}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 37, 47, 206}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 199, 204, 218, 119, 51}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 77, 4}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 211, 134, 13, 107, 126, 242, 82}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 153, 95, 187, 173, 210}, 113}, {{251, 50, 228, 178, 202, 195, 0, 57, 48, 7, 185, 49, 199, 225, 21, 223}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 120, 6, 12, 213, 7, 67, 12, 32}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 238, 24, 55, 220, 6, 122, 239, 200}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 16, 111}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 189, 137, 252, 71, 35, 50}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 23, 209, 59, 38, 143, 201}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 175, 252, 17, 14, 27, 100}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 72, 211}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 65, 108, 214, 205, 206}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 150, 191, 9, 50, 124, 5, 251, 175}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 49, 164, 99, 111, 18}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 113, 40, 76, 212, 195}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 169, 249, 114}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 180, 247, 82, 233, 184, 200}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 113}, {{251, 50, 228, 178, 202, 195, 0, 177, 105, 93, 36, 29, 166, 4, 138, 224}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 130, 86, 140, 20, 53}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 148, 172, 165, 93, 159, 205}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 253, 239, 196, 248}, 113}, {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 165, 182, 77, 135, 135, 192}, 113}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 252}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 184}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 36, 153}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 242, 60}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 133}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 153, 245}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 159, 47, 191}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 74, 173}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 242, 238, 60}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 222, 221}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 211, 161, 8}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 255}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 224}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 203, 164, 149}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 223, 214, 47}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 132, 111}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 40, 232, 198}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 183, 4, 116}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 107}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 79, 175}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 25, 12}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 129, 24}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 118, 68}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 94, 81}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 178}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 149, 99}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 229}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 231, 156, 156}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 67, 100, 197}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 116, 108, 105}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 29}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 6, 182}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 168, 229, 41}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 220, 239, 138}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 154, 161}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 255}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 28, 187}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 154}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 97, 38}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 124, 222}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 138}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 58, 12, 111}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 109}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 114}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 147, 72, 191}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 29, 17, 166}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 179, 129}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 133}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 182}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 191, 203, 83}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 169, 25, 226}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 120, 156}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 14}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 200, 148, 187}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 237, 29, 135}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 236, 44}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 210, 201, 213}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 154, 189}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 2, 21, 38}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 3, 28}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 59, 159, 7}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 47, 211, 166}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 12, 239, 88}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 176, 231, 41}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 70}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 117, 250, 85}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 130}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 85, 11}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 13}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 248, 45}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 157, 219}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 109}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 154}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 234, 77}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 39, 2, 144}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 68, 16}, 187}, {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 109, 162}, 187}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 38}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 109, 163, 201, 201, 254, 49, 195}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 10, 161, 69, 69, 211, 221, 226, 84, 169, 46}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 65, 209, 160, 193, 85}, 35}, {{111, 52, 10, 0, 0, 0, 175, 242, 112, 17, 36, 151, 0, 95, 212, 22}, 35}, {{111, 52, 10, 0, 0, 0, 0, 251, 106, 142, 5, 5, 123, 110, 229, 50}, 35}, {{111, 52, 10, 0, 0, 255, 125, 225, 46, 225, 28, 230, 84, 93, 126, 157}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 166, 13, 6, 128, 213, 160}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 29, 123, 237}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 197, 221, 76, 41, 241}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 226, 28, 104, 222, 236, 102, 185}, 35}, {{111, 52, 10, 0, 0, 0, 26, 116, 237, 88, 150, 45, 102, 74, 97, 14}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 87, 115, 140, 35, 213, 192, 255}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 65, 94, 195}, 35}, {{111, 52, 10, 0, 89, 13, 80, 222, 206, 209, 135, 3, 172, 229, 248, 33}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 150}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 79, 55, 121, 21, 81, 92, 201}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 67, 183, 52, 142, 5, 75}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 56, 86, 58, 118, 57, 98, 238, 205}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 139}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 173, 108, 255, 164, 174}, 35}, {{111, 52, 10, 0, 0, 0, 0, 79, 150, 43, 133, 199, 146, 191, 251, 164}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 157, 102, 169, 3, 79, 26, 118, 195}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 13, 184, 107, 199, 143}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 220, 110, 244, 132, 65, 122, 249}, 35}, {{111, 52, 10, 0, 0, 55, 226, 101, 59, 183, 190, 191, 163, 19, 70, 250}, 35}, {{111, 52, 10, 0, 0, 0, 0, 166, 194, 66, 66, 141, 158, 66, 125, 134}, 35}, {{111, 52, 10, 0, 0, 126, 223, 105, 140, 237, 221, 205, 60, 105, 143, 44}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 152, 81, 65, 3, 219, 114, 97, 88}, 35}, {{111, 52, 10, 0, 0, 132, 123, 140, 243, 27, 247, 73, 152, 64, 73, 208}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 134}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 94, 203, 157, 114, 67, 54}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 61, 109, 69, 93, 130, 2, 183}, 35}, {{111, 52, 10, 0, 0, 0, 0, 133, 236, 49, 172, 144, 64, 103, 160, 57}, 35}, {{111, 52, 10, 0, 0, 0, 71, 132, 126, 84, 1, 57, 233, 180, 79, 10}, 35}, {{111, 52, 10, 0, 0, 0, 155, 214, 25, 219, 76, 242, 129, 53, 124, 214}, 35}, {{111, 52, 10, 0, 0, 0, 0, 45, 51, 26, 20, 88, 188, 198, 107, 196}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 191, 246, 71, 230, 100}, 35}, {{111, 52, 10, 0, 0, 5, 50, 228, 65, 131, 5, 112, 155, 66, 32, 52}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 124, 62}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 90, 46, 7, 93, 76, 125}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 133, 96, 117, 250, 27, 68}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 18, 245, 85}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 153, 205, 122}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 46, 44, 6, 20, 115, 231, 92, 189}, 35}, {{111, 52, 10, 0, 0, 0, 131, 92, 4, 196, 234, 78, 52, 127, 248, 39}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 156, 47, 201, 176, 217}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 194, 72}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 12, 24, 207, 33, 174, 118, 233}, 35}, {{111, 52, 10, 0, 58, 161, 201, 156, 164, 35, 156, 78, 97, 73, 153, 147}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 68, 44, 124, 239, 180, 254, 26, 109}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 148}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 186, 41, 18}, 35}, {{111, 52, 10, 0, 0, 0, 222, 127, 121, 57, 121, 156, 88, 77, 223, 185}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 53, 56}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 19, 231, 253}, 35}, {{111, 52, 10, 0, 0, 139, 19, 85, 91, 154, 107, 239, 29, 68, 90, 74}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 39, 101, 82, 191, 170, 133, 11, 230}, 35}, {{111, 52, 10, 0, 0, 0, 0, 214, 180, 55, 33, 238, 158, 181, 136, 143}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 186}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 57}, 35}, {{111, 52, 10, 0, 0, 0, 85, 192, 25, 168, 114, 158, 43, 78, 152, 219}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 254, 111, 161, 231, 101, 201, 134}, 35}, {{111, 52, 10, 0, 0, 0, 167, 204, 162, 110, 99, 111, 82, 231, 207, 109}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 13, 212, 146, 36, 213, 158, 121, 47}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 170, 77, 218, 12, 87, 194, 129}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 108, 219, 152, 124, 159, 233}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 136, 175}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 226, 86}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 34, 126}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 178, 45, 224, 129, 101, 156, 2, 155}, 35}, {{111, 52, 10, 0, 0, 117, 64, 57, 36, 145, 172, 30, 245, 22, 1, 245}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 251}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 182, 115, 211, 176, 20, 170}, 35}, {{111, 52, 10, 0, 0, 9, 142, 136, 220, 84, 51, 140, 204, 1, 86, 191}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 171, 115, 44, 125, 161, 41, 47}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 196, 51, 59, 164, 9, 140, 137, 169}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 71, 245, 63, 3, 209, 173, 65}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 9, 210, 166, 138, 254, 138, 161, 220}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 255, 18, 230, 103, 212}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 24, 170, 169, 229, 16, 144, 146}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 211, 240, 235, 190, 34, 53, 205}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 147, 163, 17, 152, 101}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 33}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 72, 149, 118, 104, 204, 215}, 35}, {{111, 52, 10, 0, 0, 0, 0, 142, 19, 127, 97, 61, 241, 50, 29, 160}, 35}, {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 168, 49, 184, 185, 220, 22}, 35}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 145, 210, 12, 134}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 85}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 96, 179, 204, 99, 74, 9}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 115}, {{69, 12, 116, 151, 32, 0, 83, 158, 254, 149, 244, 231, 21, 230, 172, 45}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 31, 52, 44, 233}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 102, 119, 9, 157}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 252, 121, 114, 125, 78}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 187}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 152}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 243, 84, 157, 124, 144, 103}, 115}, {{69, 12, 116, 151, 32, 0, 197, 50, 112, 131, 174, 125, 52, 232, 206, 198}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 79, 252, 130, 254, 60, 21, 65}, 115}, {{69, 12, 116, 151, 32, 0, 0, 89, 132, 162, 169, 211, 224, 170, 166, 24}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 34, 131, 43, 140, 33, 91, 167, 58}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 182}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 90, 63, 108, 51, 224, 153, 177, 188, 85, 147}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 27, 197, 144, 226}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 108, 216, 26, 173, 193, 223}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 185, 35, 43, 68, 49, 136, 128}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 243, 9, 113, 111, 32, 244, 8, 208}, 115}, {{69, 12, 116, 151, 32, 0, 0, 18, 55, 196, 196, 192, 77, 126, 235, 157}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 204, 220, 49, 36, 200, 255, 34, 17}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 148, 133, 100, 40, 244, 147, 206, 26}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 151, 216, 21, 139, 179, 90}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 169, 92, 132, 169}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 133}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 243, 57, 255, 162}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 66, 127, 251, 178, 224, 14, 80, 57}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 209}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 190, 221, 231, 87, 89, 188, 146}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 78, 45, 106}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 163, 132, 51}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 75, 21, 61, 210}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 70, 57, 158, 222, 157}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 142, 244, 194, 120, 221, 31}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 38, 123, 235, 181}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 33, 4, 137, 206, 162}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 213}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 220, 2, 111, 208, 235}, 115}, {{69, 12, 116, 151, 32, 0, 0, 31, 210, 44, 25, 135, 166, 193, 65, 170}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 95, 131, 135, 247}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 248, 92, 148}, 115}, {{69, 12, 116, 151, 32, 0, 41, 59, 203, 197, 0, 160, 22, 54, 153, 85}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 12, 101, 204, 72, 116}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 208, 235, 226, 101, 47, 132, 46, 156}, 115}, {{69, 12, 116, 151, 32, 0, 0, 220, 210, 231, 122, 169, 132, 91, 235, 123}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 178, 59, 49, 87, 95, 242}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 93, 146, 18, 66}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 67, 244, 43, 174, 49, 196, 142}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 90, 219, 189, 241, 153, 236}, 115}, {{69, 12, 116, 151, 32, 0, 0, 188, 219, 35, 181, 124, 90, 110, 85, 227}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 67, 154, 107, 69, 201}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 248, 223, 122, 13, 18, 144, 84, 162}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 143, 25, 241, 23, 19, 8, 206}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 206, 160, 214, 143}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 249, 156, 244, 220, 155}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 206, 50, 158, 227}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 124, 54, 63, 119, 82, 239}, 115}, {{69, 12, 116, 151, 32, 0, 0, 113, 75, 79, 0, 108, 190, 174, 248, 145}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 60}, 115}, {{69, 12, 116, 151, 32, 0, 0, 136, 5, 112, 197, 198, 158, 29, 54, 208}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 54, 39, 176, 106}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 113, 201, 159, 150, 233, 152}, 115}, {{69, 12, 116, 151, 32, 0, 0, 34, 90, 246, 21, 3, 124, 239, 135, 207}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 130, 126, 21, 19, 45, 242}, 115}, {{69, 12, 116, 151, 32, 0, 0, 223, 1, 113, 148, 105, 222, 93, 131, 190}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 164, 133, 108, 14, 226, 164}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 40, 64, 19, 90, 106, 199, 3, 246}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 234, 117, 23, 100, 171, 98, 129, 61}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 223, 162, 31, 126, 43, 168}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 115}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 165}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 238, 202, 130, 157, 137, 8, 9, 12}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 241, 215, 71, 74, 182, 46, 111}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 165, 23, 104, 245, 213}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 201, 228, 129, 119, 223, 143, 250}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{69, 12, 116, 151, 32, 0, 0, 238, 241, 107, 17, 20, 42, 109, 84, 139}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 64, 62, 203, 243, 66, 175, 172}, 115}, {{69, 12, 116, 151, 32, 0, 0, 13, 72, 52, 46, 111, 84, 159, 214, 245}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 115}, {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 115}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 167, 44, 85, 121, 4, 249}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 145, 169, 172}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 41, 197, 139}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 90, 182, 180, 114, 144}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 146, 34, 113, 43, 93}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 94, 92, 167, 236}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 60, 83, 79, 53, 15, 75, 40}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 204, 201, 91, 78, 201, 33, 166}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 86, 245, 210}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 236, 240}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 67, 113, 84, 49, 156, 135, 41, 231}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 195, 190, 49, 145, 20, 140}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 184, 72, 209, 13, 219}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 57, 2, 246, 48, 172, 83, 130}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 112, 92, 130, 56, 251, 183, 209, 7}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 251, 199, 13, 136, 223, 193, 171, 140}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 112, 187, 8, 122, 215, 93, 118}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 82, 124, 11, 123, 21}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 13, 147, 210, 113}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 88, 177, 161}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 35, 111, 179}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 94, 6, 240, 18, 15, 224, 43, 167}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 22, 32, 84, 87}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 51, 90, 251, 218}, 18}, {{187, 60, 97, 40, 112, 101, 96, 151, 135, 156, 155, 56, 132, 9, 128, 96}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 91, 53}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 112, 55, 131}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 65, 132}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 198, 105, 27, 177, 63, 28, 27, 24}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 105, 193, 134, 56, 15}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 146, 128, 106, 115, 69, 154}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 18, 211, 12, 118, 37}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 225, 140}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 102, 7, 160, 130}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 23, 221, 163}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 235, 105, 203, 7}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 153, 21, 87, 126, 56}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 39, 235, 203, 16}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 16, 82, 163}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 77, 28, 47, 199, 246, 174, 24}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 133, 76, 28, 79, 54}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 212, 161, 228, 229, 47, 254, 0, 94}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 144, 155, 109, 5, 167, 240}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 130, 67, 51, 112, 175}, 18}, {{187, 60, 97, 40, 112, 101, 96, 113, 202, 100, 242, 53, 101, 36, 97, 141}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 184, 201, 200, 168, 18, 231, 178, 193}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 238, 211, 14}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 11, 130, 87, 202, 141, 226}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 181, 180, 8, 91}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 167, 140, 234, 100, 110}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 33, 251, 234, 90, 229, 141}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 96, 194, 244, 96, 3, 101, 111, 59}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 242, 227, 208, 182, 187, 138, 12, 72}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 248, 108, 186, 108}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 126, 184, 48, 52, 237, 8, 163}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 225, 64, 223}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 112, 58, 175, 14, 121, 100, 247, 126}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 162, 153, 36, 151, 114, 89, 231}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 155, 183}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 184, 101}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 223, 35, 239, 124, 52}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 176, 112, 18, 124, 199, 83, 76}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 125, 5, 85, 100}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 18}, {{187, 60, 97, 40, 112, 101, 96, 217, 49, 203, 29, 214, 81, 167, 53, 116}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 102, 215, 246}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 243, 58, 46, 174, 200}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 118, 47, 70, 169, 194, 0, 133, 144}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 229, 117}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 188, 76, 20}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 172, 177, 139, 236, 141, 171}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 137, 18}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 94, 15, 156, 133, 59, 245}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 47, 93, 17, 201}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 32, 127, 92, 244, 130, 69, 209}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 207, 104, 74, 106}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 18}, {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 171, 218, 178, 157}, 18}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 251, 96, 150}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 47, 106, 100, 125, 170, 144, 109}, 34}, {{230, 194, 136, 255, 206, 0, 0, 236, 3, 221, 42, 74, 84, 12, 45, 142}, 34}, {{230, 194, 136, 255, 206, 0, 247, 221, 181, 226, 26, 169, 242, 194, 31, 224}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 20, 24, 227, 107, 146, 96}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 52, 93, 79, 70, 30, 48, 187, 193, 14}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 170, 12, 130, 12, 214, 187}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 99}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 119, 58, 154, 111, 164}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 255, 205, 162, 232, 229, 156, 210, 175}, 34}, {{230, 194, 136, 255, 206, 0, 107, 124, 74, 152, 70, 51, 221, 184, 160, 123}, 34}, {{230, 194, 136, 255, 206, 0, 0, 2, 34, 89, 54, 160, 30, 42, 201, 127}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 173, 238, 55, 17, 47, 168}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 92, 70, 228, 175, 42, 57}, 34}, {{230, 194, 136, 255, 206, 0, 62, 78, 84, 219, 28, 120, 209, 125, 150, 255}, 34}, {{230, 194, 136, 255, 206, 0, 0, 234, 41, 78, 186, 107, 38, 168, 56, 25}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 34, 54, 130, 34}, 34}, {{230, 194, 136, 255, 206, 0, 141, 212, 29, 236, 2, 38, 30, 164, 41, 106}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 206, 60, 154, 180, 91, 107, 58}, 34}, {{230, 194, 136, 255, 206, 0, 250, 171, 12, 32, 169, 147, 32, 199, 192, 161}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 53}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 192}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 176, 16, 208}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 241}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 13, 20, 106, 216}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 140, 50, 87, 130, 9, 155, 198}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 22, 219, 129, 94, 169, 38, 182}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 60}, 34}, {{230, 194, 136, 255, 206, 0, 0, 16, 17, 254, 132, 194, 70, 37, 35, 44}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 134, 195, 125, 253, 60, 18, 117, 190}, 34}, {{230, 194, 136, 255, 206, 0, 177, 91, 230, 117, 213, 194, 25, 30, 103, 32}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 223, 96, 203, 231}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 171, 164, 146, 137, 113, 220, 240, 138}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 187, 2, 130}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 30, 112, 180, 254, 120, 24, 116}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 57, 190, 133, 20, 127, 130}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 99, 199, 107, 64}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 127, 67, 151, 155, 110, 232, 153, 3}, 34}, {{230, 194, 136, 255, 206, 0, 0, 128, 15, 209, 132, 8, 23, 103, 19, 66}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 103}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 239, 131, 50, 51, 230, 51, 50, 142}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 18, 246, 255}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 127, 42, 193, 10, 26, 55, 35}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 11, 175, 26, 81}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 182, 184, 166, 250, 160, 92, 211, 168}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 200, 228, 207, 231, 221}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 195, 246, 10, 240, 39, 105}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 150, 125, 4, 213, 157, 201, 146}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 27, 65, 16, 27, 91}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 34, 33, 186, 209, 253, 17, 221, 60}, 34}, {{230, 194, 136, 255, 206, 236, 115, 229, 2, 46, 94, 73, 223, 46, 135, 230}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 246, 0, 244, 19, 207, 123, 211, 83}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 220, 127, 252, 233, 6, 86}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 42, 250, 134, 226, 195, 137, 182}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 23}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 227, 148, 155, 75, 78, 95}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 190, 25, 114}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 134, 212, 69, 116, 252}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 177, 89, 114, 58, 180, 19, 123, 82}, 34}, {{230, 194, 136, 255, 206, 0, 88, 254, 158, 145, 94, 82, 91, 160, 214, 198}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 209, 192, 102, 24, 128}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 35, 210, 155}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 96, 228, 180, 212}, 34}, {{230, 194, 136, 255, 206, 0, 81, 67, 207, 134, 251, 179, 216, 47, 247, 17}, 34}, {{230, 194, 136, 255, 206, 0, 206, 79, 98, 188, 224, 155, 8, 204, 146, 188}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 120, 136, 46, 251, 246}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 104, 211, 77, 142, 6}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 108, 54, 158, 54, 11}, 34}, {{230, 194, 136, 255, 206, 0, 48, 175, 60, 205, 123, 31, 137, 78, 201, 247}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 145, 250, 11, 250, 178}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 48, 28, 221, 149, 201, 62}, 34}, {{230, 194, 136, 255, 206, 0, 28, 93, 91, 192, 234, 12, 155, 68, 239, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 54, 60, 153, 7, 241, 164, 146, 197, 239}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 14, 188, 191, 163, 49, 15}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 203, 106, 236, 66, 5, 84, 112}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 165, 91, 213, 103, 168, 80, 137, 175}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 228, 45, 158, 19, 91, 189}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 34}, {{230, 194, 136, 255, 206, 0, 0, 199, 255, 30, 105, 210, 52, 184, 77, 33}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 214, 187, 36}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{230, 194, 136, 255, 206, 0, 58, 220, 249, 209, 134, 5, 115, 9, 167, 180}, 34}, {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 169, 125, 82}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 163, 128}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 141, 122, 114}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 89, 39, 170}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 15, 41}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 37, 3, 148, 94}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 211, 209, 139, 170}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 107, 21, 46, 154}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 54, 1, 61, 109}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 123, 182}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 246, 116, 97}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 142, 1, 71}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 38}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 223, 244}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 237}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 1, 213, 141}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 182, 68}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 20}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 126, 107}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 190, 210, 111, 190}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 106, 147, 13, 133}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 166, 18, 79}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 145, 126}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 36, 9, 116, 87}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 134, 87}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 171}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 111, 212}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 252, 63, 184}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 27, 129}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 87, 37, 226}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 165, 55}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 220, 77}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 238, 192, 232, 186}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 77, 25, 229, 94}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 80, 33, 145}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 4, 250, 25, 194}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 13}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 42, 21}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 5}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 17, 84, 188}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 235, 150, 26, 215}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 80}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 41}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 230}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 128}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 195, 87}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 91, 244, 236, 49}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 127, 95, 188, 129}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 61, 89, 145, 240}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 53, 109, 116}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 177}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 227, 154, 190, 98}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 1, 65, 55, 121, 162}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 72, 164, 102, 228, 17}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 224, 209, 253, 235}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 64, 158, 233}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 142, 112}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 151}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 18}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 192, 248}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 74, 132}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 55}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 216, 112, 29, 56}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 25}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 204, 54, 247, 135}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 35}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 186, 122, 72, 117}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 180, 34, 64, 98}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 23}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 182, 228}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 47, 242}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 191, 62, 13}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 115, 45, 139, 214}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 149, 223}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 241, 238}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 91, 194}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 251, 162, 240}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 53, 132, 153}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 74, 2, 59, 7, 247}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 243, 34, 176, 78}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 93, 142, 135}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 171, 177}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 75}, {{11, 58, 130, 89, 128, 0, 243, 76, 121, 62, 105, 232, 7, 175, 220, 198}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 56, 10, 125, 109, 40}, 232}, {{11, 58, 130, 89, 128, 0, 0, 20, 133, 158, 90, 25, 200, 95, 105, 21}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 51, 229, 30, 202, 249, 161, 236}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 41, 129, 241, 37, 96, 79}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 180, 98, 5, 148, 4, 20, 151}, 232}, {{11, 58, 130, 89, 128, 0, 0, 90, 193, 17, 251, 192, 150, 142, 218, 230}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 141, 240, 35}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 34, 59, 219, 224, 198, 46, 229, 247}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 137, 3, 35, 56, 41}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 118, 62, 31, 189, 132}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 171, 118, 2, 88, 208}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 77, 145, 152, 120, 172, 206, 151}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 60, 69, 114, 127, 106, 253, 72}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 0, 177, 100, 151, 135, 89, 30, 166, 154, 179}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 200}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 232}, {{11, 58, 130, 89, 128, 0, 22, 228, 192, 159, 252, 102, 5, 122, 157, 141}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 177, 146, 2, 150, 27, 207}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 77, 180, 210}, 232}, {{11, 58, 130, 89, 128, 0, 0, 122, 21, 6, 242, 5, 212, 111, 25, 115}, 232}, {{11, 58, 130, 89, 128, 166, 43, 219, 11, 173, 155, 142, 203, 114, 250, 238}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 203, 40, 153, 186, 74}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 26, 79, 197, 242, 121, 194}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 238, 109, 59, 88, 108, 100, 83}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 203, 91, 152}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 64, 127, 41, 205, 13}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 16, 228, 87, 21, 9, 190}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 58, 245, 102}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 144, 224, 42, 172, 27, 108, 115, 39}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 76, 248, 65, 10, 101, 27, 112, 17}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 163, 83, 137, 78}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 247, 242, 212, 52, 190, 182, 203}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 31, 194, 26, 141, 199, 186, 192, 52}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 95, 114, 84, 128, 42, 172}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 162}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 124, 234, 253, 62, 7, 145}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 26, 150, 179, 10, 190}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 251, 165, 160, 145, 100, 6}, 232}, {{11, 58, 130, 89, 128, 0, 0, 76, 195, 166, 180, 87, 52, 235, 136, 51}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 73}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 225, 85, 69, 232, 212, 252}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 232}, {{11, 58, 130, 89, 128, 0, 0, 249, 46, 150, 65, 173, 243, 210, 249, 176}, 232}, {{11, 58, 130, 89, 128, 0, 0, 63, 204, 130, 141, 82, 174, 71, 172, 86}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 41, 125, 112, 53, 182, 96, 247}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 238, 126, 102}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 37, 76, 119, 149, 158, 152}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 104, 225, 204, 97, 239, 234, 196, 243}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 80}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 44, 133, 183, 84}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 24, 246, 9, 242, 66, 65, 66}, 232}, {{11, 58, 130, 89, 128, 0, 0, 155, 117, 249, 3, 12, 123, 81, 219, 176}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 68, 80, 245, 83, 134, 154, 201, 181}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 180, 195, 107, 141, 34, 147, 54}, 232}, {{11, 58, 130, 89, 128, 0, 0, 240, 254, 93, 8, 59, 31, 15, 193, 193}, 232}, {{11, 58, 130, 89, 128, 0, 0, 216, 53, 92, 126, 248, 146, 37, 181, 196}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 235, 133, 155, 7, 206, 234, 243, 251, 183, 50}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 232}, {{11, 58, 130, 89, 128, 0, 0, 29, 182, 102, 69, 109, 74, 26, 233, 105}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 60, 59, 61}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 118, 227, 86, 236, 118, 171, 156}, 232}, {{11, 58, 130, 89, 128, 96, 183, 186, 33, 54, 20, 94, 55, 19, 41, 72}, 232}, {{11, 58, 130, 89, 128, 0, 0, 80, 84, 163, 143, 108, 235, 83, 179, 235}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 151, 189, 10, 74}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 140}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 179, 82, 30, 72, 183, 21, 80}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 127, 6, 182, 212, 64, 90}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 185}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 102, 211, 233}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 223, 213, 209, 111, 248, 80, 253, 25}, 232}, {{11, 58, 130, 89, 128, 100, 55, 217, 113, 42, 89, 245, 9, 65, 93, 120}, 232}, {{11, 58, 130, 89, 128, 130, 30, 3, 129, 113, 229, 170, 41, 146, 255, 231}, 232}, {{11, 58, 130, 89, 128, 0, 0, 49, 172, 125, 237, 218, 44, 117, 133, 26}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 45}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 179, 220, 167, 137, 206}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 5}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 228, 68, 23}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 224, 47, 197, 19, 8, 223}, 232}, {{11, 58, 130, 89, 128, 90, 131, 203, 210, 117, 227, 37, 186, 251, 78, 174}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 38, 49, 157, 168, 61, 118, 197, 62}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 82}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 232}, {{11, 58, 130, 89, 128, 0, 73, 121, 184, 111, 130, 99, 235, 177, 24, 144}, 232}, {{11, 58, 130, 89, 128, 0, 0, 224, 205, 78, 48, 91, 115, 57, 54, 250}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 214, 200, 110, 33, 145, 210}, 232}, {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 242, 219, 185, 223}, 232}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 191, 45}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 101}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 118, 129, 28, 1}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 214, 228}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 129, 96, 2, 16}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 72, 251, 91}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 44, 103, 61, 224}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 89, 110}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 14}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 56, 64, 227}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 171, 249}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 229, 175}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 235, 113}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 105, 138, 207, 154}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 205, 67, 1}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 156}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 86, 114, 87, 130}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 34, 37, 217, 249}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 199, 238, 146, 5}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 137, 42}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 150, 233, 237, 123}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 102}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 216, 37, 223, 208}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 142, 106, 5, 117}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 240}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 183, 92, 86, 198}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 42}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 149}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 95}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 147}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 159}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 103, 132, 252, 15}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 230, 126, 219}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 67}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 133}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 36, 132, 46}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 192, 107, 56, 40}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 61, 118, 148}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 55, 211}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 138}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 188}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 180, 135}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 133, 80, 13, 68}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 74, 138, 44}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 35, 10}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 92, 232}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 10}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 114}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 206, 162, 64, 87}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 180, 144, 213}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 3, 112, 72, 171}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 81, 127, 45}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 124, 85, 209}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 178, 147, 68, 88}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 69}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 50, 215}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 46, 39, 161}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 82, 61}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 78, 104}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 241, 108}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 150}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 235, 21, 104}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 210, 40, 118, 191}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 175, 181}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 204, 200, 122}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 122}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 139, 26, 32, 43}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 137, 196, 210}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 96, 252, 153, 25}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 177}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 25}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 163}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 50, 177, 63}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 39, 166}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 14}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 49, 139, 160}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 142, 211}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 230, 138}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 10, 38}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 29, 180, 191, 18}, 154}, {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 154}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 176, 99}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 185, 131, 201}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 198, 216, 51, 144, 161, 252, 205, 115}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 141}, 195}, {{6, 180, 224, 182, 154, 253, 106, 117, 190, 3, 194, 26, 55, 222, 246, 48}, 195}, {{6, 180, 224, 0, 0, 0, 0, 196, 86, 254, 243, 53, 168, 216, 93, 159}, 195}, {{6, 180, 224, 24, 50, 73, 143, 0, 221, 254, 50, 192, 248, 38, 221, 216}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 84, 71, 101, 105, 235, 31, 233, 111}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 94, 109, 175, 59, 85, 67, 92}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 93, 151, 153, 173, 114, 104, 203, 155}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 91, 96, 235}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 81, 148}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 49, 60, 42}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 64, 177, 87, 101, 4, 244, 212, 74}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 244, 247, 122, 5, 75}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 217, 206, 247, 37, 235}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 213, 2, 232, 245, 73, 243}, 195}, {{6, 180, 224, 0, 0, 0, 201, 39, 17, 134, 194, 195, 169, 130, 84, 140}, 195}, {{6, 180, 224, 0, 0, 0, 0, 84, 51, 36, 44, 246, 215, 201, 191, 144}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 81, 21, 208, 137, 222}, 195}, {{6, 180, 224, 0, 0, 0, 213, 127, 21, 252, 30, 112, 14, 193, 38, 185}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 212, 37, 203, 18, 207, 100, 202}, 195}, {{6, 180, 224, 0, 0, 0, 0, 145, 206, 147, 195, 8, 215, 160, 163, 208}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 46, 208, 37, 233, 39}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 83, 172, 142}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 217, 102, 102, 196, 230, 127, 255, 190}, 195}, {{6, 180, 224, 173, 24, 108, 60, 149, 49, 204, 62, 189, 28, 79, 78, 164}, 195}, {{6, 180, 224, 0, 87, 6, 209, 16, 193, 10, 194, 242, 123, 255, 228, 53}, 195}, {{6, 180, 224, 0, 0, 0, 0, 123, 148, 87, 35, 253, 146, 166, 163, 134}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 188, 221}, 195}, {{6, 180, 224, 0, 0, 0, 0, 198, 27, 23, 205, 54, 150, 255, 215, 128}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 174, 173, 221, 247, 40, 245}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 254, 246, 37, 221, 203, 246}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 195}, {{6, 180, 224, 188, 85, 34, 14, 50, 156, 181, 193, 95, 181, 17, 65, 164}, 195}, {{6, 180, 224, 0, 0, 253, 92, 167, 135, 253, 87, 59, 41, 141, 174, 150}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 169, 1}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 195}, {{6, 180, 224, 0, 0, 0, 0, 224, 23, 236, 178, 237, 241, 152, 28, 66}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 163, 20}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 80, 140, 163}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 73, 227, 151, 130, 153, 83}, 195}, {{6, 180, 224, 0, 0, 0, 136, 27, 14, 177, 128, 135, 232, 251, 152, 32}, 195}, {{6, 180, 224, 0, 41, 133, 2, 35, 159, 167, 80, 135, 160, 148, 87, 13}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 93, 73, 163}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 33, 234, 70, 118, 65, 0, 252}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 129, 222, 224, 234, 249, 160}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 149, 101, 10, 220, 157}, 195}, {{6, 180, 224, 0, 92, 33, 77, 58, 251, 138, 42, 180, 195, 46, 55, 218}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{6, 180, 224, 0, 0, 0, 0, 26, 231, 58, 70, 177, 222, 21, 7, 49}, 195}, {{6, 180, 224, 0, 0, 0, 0, 247, 99, 50, 40, 62, 225, 156, 74, 0}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 48, 198, 18, 78, 114, 99}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 159, 56, 133, 218, 28}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 26}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 141, 185, 63, 144, 213, 164, 88}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 235, 199, 111, 85, 46}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 60, 75, 193, 216, 245, 188}, 195}, {{6, 180, 224, 0, 0, 14, 126, 14, 227, 77, 202, 8, 19, 208, 41, 41}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 177, 63, 165, 238, 38, 223, 36}, 195}, {{6, 180, 224, 62, 18, 169, 230, 119, 231, 189, 4, 210, 214, 136, 75, 217}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 143, 231, 107, 3, 59, 255, 7}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 137}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 69, 86}, 195}, {{6, 180, 224, 0, 0, 0, 250, 50, 28, 235, 44, 45, 110, 106, 165, 141}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 221, 99}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 222, 36, 218, 157, 64, 44, 117, 127}, 195}, {{6, 180, 224, 0, 0, 0, 210, 204, 70, 199, 139, 45, 148, 126, 226, 7}, 195}, {{6, 180, 224, 0, 201, 195, 124, 217, 197, 113, 50, 184, 178, 197, 197, 183}, 195}, {{6, 180, 224, 0, 0, 194, 204, 41, 254, 153, 28, 89, 231, 50, 8, 33}, 195}, {{6, 180, 224, 0, 29, 104, 91, 11, 9, 98, 115, 19, 74, 120, 107, 252}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{6, 180, 224, 68, 200, 115, 243, 152, 102, 112, 92, 161, 91, 252, 98, 174}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 163, 144, 227, 101, 247, 59}, 195}, {{6, 180, 224, 0, 0, 0, 0, 13, 167, 139, 182, 239, 52, 96, 228, 106}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 185, 204}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 34}, 195}, {{6, 180, 224, 0, 0, 207, 195, 213, 207, 231, 207, 127, 204, 106, 41, 48}, 195}, {{6, 180, 224, 0, 0, 0, 157, 29, 133, 76, 24, 85, 132, 169, 253, 187}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 19, 172, 83, 46, 48, 225}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 148, 158, 237, 224, 240, 45, 187, 146}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 241}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 113, 65, 200, 8, 237, 7, 247, 146}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 163, 184, 24, 216, 203, 64, 145}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 236, 187, 173, 18, 223, 70}, 195}, {{6, 180, 224, 0, 77, 45, 115, 191, 43, 208, 83, 68, 16, 196, 80, 157}, 195}, {{6, 180, 224, 0, 0, 81, 209, 245, 100, 204, 214, 94, 229, 221, 29, 96}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 208}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 18, 255, 12, 75, 202, 3, 57, 185}, 195}, {{6, 180, 224, 0, 0, 3, 213, 248, 84, 193, 168, 21, 112, 108, 43, 226}, 195}, {{6, 180, 224, 0, 252, 25, 201, 229, 85, 250, 86, 255, 35, 60, 239, 88}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 175, 174}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 135, 53, 248, 73, 25, 22}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 195}, {{6, 180, 224, 0, 0, 0, 0, 40, 109, 59, 122, 169, 110, 65, 244, 0}, 195}, {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 220, 46}, 195}, {{6, 180, 224, 0, 130, 252, 147, 7, 231, 153, 36, 233, 47, 224, 246, 212}, 195}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 40, 150, 247, 63, 238, 108}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 43, 97, 4}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 230, 47}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 130, 233, 54, 192}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 145, 208, 19}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 133, 65, 191, 123, 251, 249}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 12, 230, 193, 197}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 136, 4}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 164, 20, 29}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 34, 188}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 100, 211, 157, 33, 211, 72}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 3, 80, 14}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 36, 27}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 12, 59, 52}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 12, 74, 163, 251, 35, 252}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 202}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 17, 236}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 234, 111}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 171, 166, 105, 184, 122, 43, 184}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 98, 57, 190, 146, 220, 49}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 176, 187, 243, 197, 47}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 148, 241, 123}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 251, 122, 48, 175, 122}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 31, 148, 159, 193, 40, 92}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 19, 168}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 187, 64, 41}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 131, 84, 56, 169, 182, 138}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 124, 77, 179, 89}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 244, 78, 80, 82, 179, 180}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 234, 127, 55}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 125, 3, 38, 9, 8, 108}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 3, 148, 203, 35, 124, 139}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 76, 55, 233}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 123, 248, 44, 131, 2, 232, 110}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 229, 205, 225, 21}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 37, 74, 227, 43, 202}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 94}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 157, 134, 235, 24, 198}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 153, 193, 136, 85, 63, 155}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 122, 143, 75, 30, 27}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 29, 63, 188, 44, 167}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 140, 25, 95, 142, 155}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 64}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 18, 170}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 219, 126, 127, 64, 202, 28}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 202}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 135, 77, 57, 240}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 105, 193, 53, 155, 157, 72}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 238, 195}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 174, 116, 31, 239}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 240, 79}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 201, 151, 91, 96}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 101, 8, 217, 39, 235, 4, 11}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 122, 243, 225, 248, 229, 177}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 60, 191, 91, 153, 101, 133}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 243, 24, 27, 142}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 175, 204, 102, 98, 6, 122}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 58, 49, 218, 160, 147}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 93, 161, 26, 232, 77}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 197, 209, 140, 132}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 53, 61, 6, 12, 199}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 233, 21, 15, 24}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 49, 233, 106, 161, 177}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 251, 173, 71, 78, 131}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 130, 238, 137, 16, 10}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 71, 210, 189}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 151, 151, 208, 236}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 236, 245}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 115}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 221, 94, 63, 202, 181}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 221, 216, 162, 123}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 144, 248}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 181, 215}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 147, 223, 123, 156, 118, 128, 61}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 101}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 26, 137, 191, 192, 159}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 123, 131, 204, 154, 199, 22}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 144, 241, 79, 113, 73, 225, 211}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 46, 173, 15}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 79, 214, 112, 148, 242, 20, 236}, 122}, {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 122}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 40}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 96, 98, 48}, 97}, {{225, 10, 131, 0, 0, 0, 0, 235, 155, 107, 94, 94, 43, 88, 117, 192}, 97}, {{225, 10, 131, 0, 0, 0, 0, 167, 4, 203, 164, 225, 174, 234, 141, 137}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 88, 159, 216, 183, 186, 170}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 235}, 97}, {{225, 10, 131, 0, 0, 0, 186, 14, 124, 120, 209, 86, 161, 18, 191, 251}, 97}, {{225, 10, 131, 0, 0, 0, 48, 139, 81, 100, 119, 73, 53, 172, 6, 222}, 97}, {{225, 10, 131, 0, 0, 0, 0, 10, 87, 124, 172, 58, 67, 238, 226, 93}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 11, 124, 198, 175, 156}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 220, 51, 73, 20, 17}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 243, 198, 209}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 49}, 97}, {{225, 10, 131, 0, 0, 152, 146, 206, 211, 219, 120, 160, 185, 79, 249, 6}, 97}, {{225, 10, 131, 0, 203, 187, 232, 63, 134, 113, 222, 122, 137, 52, 78, 155}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 135, 29, 86, 69, 202, 253, 105, 117}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 97}, {{225, 10, 131, 0, 0, 0, 0, 112, 231, 116, 160, 150, 9, 140, 42, 173}, 97}, {{225, 10, 131, 0, 0, 0, 0, 243, 195, 245, 190, 52, 171, 84, 238, 43}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 98, 72, 133}, 97}, {{225, 10, 131, 0, 0, 0, 253, 253, 47, 122, 132, 86, 250, 120, 69, 19}, 97}, {{225, 10, 131, 0, 0, 0, 49, 154, 151, 135, 102, 11, 136, 148, 212, 147}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 253, 86, 43, 36, 204, 176, 162}, 97}, {{225, 10, 131, 0, 0, 54, 123, 221, 147, 246, 167, 104, 200, 185, 5, 232}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 24, 203, 111, 93, 179, 219, 12}, 97}, {{225, 10, 131, 0, 0, 0, 0, 118, 47, 135, 40, 87, 40, 251, 57, 251}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 19}, 97}, {{225, 10, 131, 0, 0, 0, 0, 207, 219, 244, 49, 147, 254, 212, 210, 64}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 10, 60}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 99}, 97}, {{225, 10, 131, 0, 10, 55, 254, 112, 254, 247, 107, 2, 29, 61, 143, 100}, 97}, {{225, 10, 131, 0, 0, 102, 77, 255, 116, 233, 20, 108, 50, 145, 108, 47}, 97}, {{225, 10, 131, 0, 0, 69, 152, 53, 93, 227, 0, 103, 255, 119, 7, 44}, 97}, {{225, 10, 131, 0, 0, 0, 0, 119, 6, 197, 128, 172, 184, 195, 102, 176}, 97}, {{225, 10, 131, 0, 246, 133, 63, 128, 227, 43, 142, 48, 15, 236, 61, 130}, 97}, {{225, 10, 131, 0, 0, 0, 102, 93, 4, 115, 135, 9, 129, 147, 171, 174}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 58, 57, 255, 187, 217, 147}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 97}, {{225, 10, 131, 0, 0, 0, 79, 218, 51, 74, 52, 149, 30, 104, 254, 122}, 97}, {{225, 10, 131, 0, 0, 0, 0, 210, 139, 42, 180, 242, 41, 103, 120, 51}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 31, 178, 240}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 99, 143, 115, 198, 163, 105, 216, 70}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 105}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 244, 142}, 97}, {{225, 10, 131, 0, 0, 0, 118, 224, 175, 23, 110, 231, 132, 168, 103, 158}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 78, 143, 72, 31, 244, 185, 124, 102}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 48, 77}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 239, 126, 181}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 104, 102, 21, 156, 26, 147, 126, 89}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 236, 120, 109, 17, 171, 234, 86}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 200, 28, 203, 144, 44, 21}, 97}, {{225, 10, 131, 0, 0, 133, 191, 180, 233, 205, 196, 148, 200, 223, 174, 171}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 100, 226, 134, 84, 11, 125}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 152, 213, 23, 155, 175}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 36, 59, 234, 24, 238}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 132, 141}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 141, 14, 190, 131, 50, 18}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 57, 42, 145, 30, 238, 39}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 0, 0, 82, 2, 188, 3, 241, 18, 183, 97, 106, 52}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 166, 187, 151, 34, 45, 164}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 27, 162, 160, 56, 245, 78, 19, 236}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 218, 39, 224, 198, 141, 223, 117, 62}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 60, 182, 216}, 97}, {{225, 10, 131, 0, 164, 7, 226, 124, 49, 176, 89, 168, 241, 51, 238, 76}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 145, 124, 145, 51, 164, 19, 43, 199}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 42, 68}, 97}, {{225, 10, 131, 0, 253, 87, 95, 56, 19, 64, 239, 240, 43, 148, 44, 95}, 97}, {{225, 10, 131, 0, 34, 146, 81, 147, 120, 130, 62, 37, 124, 209, 43, 216}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 242, 145}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 68, 126, 40, 21, 190, 39, 160, 132, 204, 180, 225, 60}, 97}, {{225, 10, 131, 0, 187, 199, 184, 129, 41, 250, 155, 144, 209, 192, 165, 91}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 167, 151, 19}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 97}, {{225, 10, 131, 0, 0, 0, 0, 83, 170, 97, 174, 88, 223, 204, 204, 124}, 97}, {{225, 10, 131, 0, 118, 13, 190, 123, 89, 196, 1, 21, 133, 160, 222, 194}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 241, 110, 146, 235, 120}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 10, 32}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 254, 216, 160, 29, 125}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 191, 210, 36}, 97}, {{225, 10, 131, 0, 0, 97, 74, 179, 9, 34, 205, 219, 11, 120, 221, 193}, 97}, {{225, 10, 131, 0, 0, 0, 123, 195, 30, 144, 174, 137, 161, 136, 68, 34}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 74, 51, 166, 71, 241, 92}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 243, 60, 48, 43, 67, 233}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 149, 173, 92, 220, 136}, 97}, {{225, 10, 131, 0, 0, 0, 0, 31, 222, 157, 126, 152, 183, 164, 62, 203}, 97}, {{225, 10, 131, 0, 0, 110, 130, 248, 128, 204, 229, 206, 62, 191, 53, 66}, 97}, {{225, 10, 131, 0, 0, 0, 0, 0, 0, 152, 5, 41, 180, 247, 202, 71}, 97}, {{16, 0, 0, 0, 0, 46, 194, 222, 161, 95, 197, 19, 42, 104, 195, 136}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 202}, 220}, {{16, 0, 0, 0, 0, 17, 51, 190, 208, 163, 208, 215, 243, 70, 29, 235}, 220}, {{16, 0, 0, 0, 0, 8, 152, 157, 185, 100, 57, 124, 96, 57, 163, 55}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 196, 238, 0, 167, 92, 70, 131}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 90, 116, 110}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 80, 58, 234, 219, 11}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 203}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 178, 177, 199, 180}, 220}, {{16, 0, 0, 0, 0, 0, 0, 119, 75, 7, 16, 200, 213, 119, 68, 36}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 29, 45, 83, 92}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 0, 0, 0, 4, 129, 207, 194, 57, 118, 7, 76, 111, 93, 150}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 199, 164}, 220}, {{16, 0, 209, 172, 12, 22, 244, 213, 211, 105, 100, 102, 112, 50, 112, 196}, 220}, {{16, 0, 0, 37, 99, 159, 56, 42, 184, 132, 163, 205, 40, 63, 229, 188}, 220}, {{16, 0, 0, 0, 0, 0, 0, 142, 180, 226, 139, 145, 249, 134, 131, 166}, 220}, {{16, 0, 0, 217, 221, 90, 113, 117, 212, 34, 51, 33, 21, 108, 85, 25}, 220}, {{16, 0, 0, 0, 0, 0, 126, 146, 139, 235, 209, 242, 135, 227, 223, 95}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 159, 185}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 49, 246, 226, 232}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 113}, 220}, {{16, 0, 0, 0, 62, 164, 184, 38, 117, 242, 72, 218, 50, 240, 15, 194}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 6, 99, 240, 61, 101}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 204, 33, 77}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 186}, 220}, {{16, 46, 232, 238, 212, 158, 224, 119, 24, 24, 139, 127, 61, 239, 68, 215}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 3, 44, 29, 187, 190, 48, 106}, 220}, {{16, 0, 0, 0, 245, 133, 127, 89, 176, 41, 111, 248, 255, 170, 97, 244}, 220}, {{16, 0, 0, 0, 0, 4, 29, 56, 129, 59, 108, 59, 93, 14, 153, 6}, 220}, {{16, 0, 0, 0, 0, 0, 69, 149, 3, 141, 69, 220, 205, 4, 133, 207}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 195, 174, 37, 96, 170, 14, 12}, 220}, {{16, 0, 0, 0, 0, 0, 0, 127, 124, 153, 183, 87, 5, 162, 144, 138}, 220}, {{16, 0, 0, 0, 0, 113, 205, 89, 82, 190, 211, 109, 152, 64, 132, 176}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 189, 154, 135, 30, 173}, 220}, {{16, 0, 0, 0, 0, 120, 175, 74, 5, 184, 186, 126, 46, 212, 210, 38}, 220}, {{16, 137, 221, 200, 17, 68, 20, 211, 55, 83, 63, 11, 204, 219, 198, 98}, 220}, {{16, 0, 0, 0, 0, 101, 17, 158, 199, 141, 21, 62, 35, 173, 137, 205}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 211, 88, 162, 247, 3, 22, 122, 96, 198, 6, 18, 218, 87, 104, 53}, 220}, {{16, 0, 0, 0, 0, 0, 223, 79, 131, 120, 102, 100, 156, 131, 71, 166}, 220}, {{16, 0, 0, 136, 97, 149, 228, 16, 224, 24, 163, 8, 33, 60, 251, 219}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 163, 66}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 140}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 162, 196}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 28, 27, 29, 170, 179}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 154, 117, 14, 15, 240, 216, 223, 110}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 57, 230, 167, 238}, 220}, {{16, 0, 0, 0, 0, 4, 178, 235, 5, 192, 101, 118, 170, 79, 232, 151}, 220}, {{16, 0, 0, 0, 0, 0, 0, 154, 147, 185, 25, 166, 224, 229, 122, 143}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 171, 126, 94, 72, 29, 26, 175}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 227, 247, 43, 20, 86}, 220}, {{16, 184, 245, 188, 161, 135, 17, 93, 218, 213, 135, 235, 138, 204, 156, 57}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 154, 183, 137, 116, 76, 179, 44, 252, 255, 21, 181, 80, 24, 151}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 105, 72, 119, 161, 15, 174, 182, 108}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 34}, 220}, {{16, 0, 69, 234, 70, 81, 114, 235, 83, 108, 151, 242, 96, 92, 132, 223}, 220}, {{16, 0, 0, 0, 0, 0, 70, 235, 118, 156, 254, 197, 29, 50, 206, 122}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 156, 11, 160, 16, 6, 126, 20}, 220}, {{16, 0, 0, 0, 0, 0, 74, 7, 197, 230, 217, 1, 109, 39, 157, 238}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 123, 50, 14, 148, 239}, 220}, {{16, 0, 0, 0, 236, 165, 255, 103, 253, 152, 246, 31, 119, 225, 232, 176}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 243, 16, 83, 81, 84, 115, 211}, 220}, {{16, 0, 0, 209, 184, 117, 34, 191, 7, 43, 17, 64, 217, 2, 217, 163}, 220}, {{16, 0, 0, 0, 236, 212, 247, 127, 60, 124, 164, 193, 95, 61, 148, 191}, 220}, {{16, 0, 0, 0, 0, 175, 204, 184, 2, 56, 154, 132, 38, 238, 234, 124}, 220}, {{16, 0, 0, 0, 0, 66, 145, 120, 192, 143, 18, 241, 249, 216, 108, 35}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 225, 111}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 178}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 236, 126, 100, 137, 236, 215, 83, 62, 2, 23, 239, 49, 208, 169}, 220}, {{16, 0, 0, 0, 0, 0, 0, 49, 68, 252, 188, 51, 175, 133, 33, 62}, 220}, {{16, 0, 0, 170, 131, 7, 109, 109, 75, 193, 81, 204, 31, 129, 90, 152}, 220}, {{16, 0, 80, 33, 214, 43, 167, 89, 82, 179, 68, 63, 38, 60, 14, 79}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 0, 248, 144, 135, 168, 243, 35, 96, 108, 152, 118, 175, 28, 233}, 220}, {{16, 0, 0, 57, 155, 0, 49, 34, 4, 114, 125, 220, 130, 190, 67, 150}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 187, 187, 23}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 29, 255, 224, 12, 66, 114, 179, 195}, 220}, {{16, 0, 208, 228, 13, 24, 69, 0, 52, 38, 31, 4, 60, 216, 160, 126}, 220}, {{16, 0, 0, 0, 0, 0, 0, 24, 114, 142, 211, 236, 93, 206, 107, 152}, 220}, {{16, 0, 0, 32, 78, 38, 159, 50, 32, 190, 3, 142, 152, 189, 56, 237}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 246, 94, 182, 121}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 38, 225, 130, 120, 41}, 220}, {{16, 0, 0, 0, 0, 0, 236, 77, 248, 128, 70, 161, 54, 125, 177, 9}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 108, 235, 196, 96, 150}, 220}, {{16, 0, 0, 0, 124, 73, 220, 124, 4, 23, 52, 39, 64, 65, 146, 121}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 193, 19, 22}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 255}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 147, 255, 43}, 220}, {{16, 0, 0, 0, 0, 86, 69, 128, 79, 203, 170, 252, 40, 20, 227, 15}, 220}, {{16, 0, 0, 23, 143, 97, 146, 193, 253, 1, 71, 8, 8, 140, 5, 113}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220}, {{16, 0, 0, 104, 72, 213, 236, 90, 103, 216, 186, 112, 219, 17, 61, 31}, 220}, {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 142, 193, 120, 140, 81}, 220}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 80}, {{166, 0, 0, 161, 96, 63, 242, 107, 212, 66, 228, 186, 174, 1, 77, 138}, 80}, {{166, 0, 0, 0, 170, 156, 35, 132, 19, 92, 169, 161, 173, 207, 66, 203}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 59, 240}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 88}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 242}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 102, 223, 171, 56, 241, 236, 195, 36}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 63}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 55, 189, 103, 145, 232, 124, 219, 235, 82, 121, 60, 22}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 51, 8, 32, 49, 126}, 80}, {{166, 0, 0, 0, 0, 0, 0, 255, 167, 165, 114, 144, 211, 142, 31, 63}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 85, 16, 61, 196}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 255, 127}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 81, 24, 84}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 62, 22, 105, 245}, 80}, {{166, 227, 1, 128, 131, 214, 93, 149, 133, 51, 14, 95, 130, 176, 147, 223}, 80}, {{166, 0, 0, 0, 180, 218, 155, 86, 194, 60, 34, 21, 247, 116, 243, 241}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 119, 202, 28, 170, 210, 201, 218}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 228, 168}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 32, 225, 78, 105, 81}, 80}, {{166, 0, 0, 125, 35, 245, 120, 223, 66, 129, 141, 248, 197, 108, 188, 171}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 177, 122, 196}, 80}, {{166, 0, 158, 6, 40, 21, 171, 74, 146, 243, 20, 2, 228, 48, 107, 96}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 254, 135, 108, 180}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 195, 125, 30, 221, 118, 161, 172, 232}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 194, 225, 131, 93}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 42, 232}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 46, 232, 214, 10, 190}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 197, 101, 200, 13}, 80}, {{166, 0, 0, 0, 0, 95, 219, 42, 6, 179, 175, 106, 90, 102, 126, 11}, 80}, {{166, 102, 71, 106, 138, 226, 27, 186, 176, 174, 185, 137, 65, 97, 227, 100}, 80}, {{166, 0, 145, 205, 138, 253, 184, 30, 64, 92, 159, 49, 81, 151, 123, 1}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 156, 1, 132, 93, 14}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 70, 195, 41, 121}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 31, 31, 220, 251, 152, 81, 203, 201}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 46, 9, 98}, 80}, {{166, 0, 153, 190, 201, 100, 161, 17, 104, 172, 5, 196, 248, 230, 201, 167}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 240, 152, 241, 42, 26, 31, 237, 204}, 80}, {{166, 0, 0, 100, 49, 233, 66, 71, 232, 219, 237, 110, 123, 233, 117, 239}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 59, 15}, 80}, {{166, 0, 0, 0, 0, 0, 0, 200, 140, 184, 74, 1, 59, 151, 3, 167}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 176, 55, 79, 84, 15}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 124, 145, 250, 15, 195}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 24, 82}, 80}, {{166, 0, 0, 0, 147, 167, 171, 57, 240, 38, 120, 80, 176, 50, 7, 160}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 168, 184, 134}, 80}, {{166, 0, 0, 0, 0, 0, 11, 192, 106, 219, 25, 20, 44, 48, 117, 156}, 80}, {{166, 0, 76, 26, 173, 105, 199, 8, 88, 114, 19, 139, 191, 171, 185, 235}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 53, 204, 193, 144, 131, 223, 198}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 141, 72, 166, 53, 186}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 123, 110, 63, 242, 146, 92, 122, 103}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 80}, {{166, 0, 0, 0, 0, 0, 0, 110, 183, 169, 62, 1, 255, 158, 56, 67}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 2, 63}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 75}, 80}, {{166, 0, 0, 0, 0, 0, 0, 22, 149, 92, 35, 216, 149, 207, 12, 7}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 243, 176, 82}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 73, 159, 43}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 216, 73, 102, 127}, 80}, {{166, 0, 0, 68, 0, 222, 131, 238, 240, 188, 38, 109, 215, 206, 166, 203}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 80}, {{166, 0, 0, 16, 90, 237, 13, 229, 62, 251, 191, 180, 141, 151, 214, 123}, 80}, {{166, 0, 0, 0, 0, 0, 182, 157, 166, 79, 38, 169, 193, 152, 24, 57}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 92, 84, 4}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 167, 118, 122, 115, 235, 45, 112, 25}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 64, 111}, 80}, {{166, 0, 0, 0, 0, 0, 0, 100, 204, 53, 43, 63, 191, 211, 54, 249}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 145, 78, 91, 207, 95, 186, 114, 154, 127, 247, 213, 16, 8, 244}, 80}, {{166, 0, 0, 217, 28, 23, 80, 204, 155, 18, 14, 36, 237, 91, 42, 156}, 80}, {{166, 0, 200, 161, 91, 28, 135, 193, 201, 45, 239, 72, 213, 41, 143, 82}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 231, 89, 228, 140, 121, 219, 199}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 241}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 183, 159, 214, 194, 153, 20, 9}, 80}, {{166, 0, 0, 0, 0, 211, 44, 116, 189, 7, 145, 136, 195, 157, 208, 69}, 80}, {{166, 0, 0, 0, 0, 0, 0, 20, 136, 104, 59, 255, 80, 221, 232, 173}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 164, 229, 99, 64, 145, 222, 167, 43}, 80}, {{166, 0, 172, 110, 120, 141, 210, 228, 130, 211, 181, 170, 38, 208, 225, 120}, 80}, {{166, 0, 0, 0, 0, 0, 67, 172, 14, 65, 142, 203, 187, 29, 71, 243}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 84, 196, 26, 142, 19}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 196, 133, 19, 205, 84}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 80, 204, 95, 208, 66, 105, 254, 132}, 80}, {{166, 0, 0, 0, 0, 0, 0, 176, 3, 90, 246, 169, 78, 37, 151, 85}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 184, 69, 136, 66, 124, 245, 244, 74}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 134, 245, 12}, 80}, {{166, 0, 0, 0, 0, 91, 131, 224, 222, 87, 56, 198, 100, 200, 77, 244}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 47}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 48, 63, 143}, 80}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 131, 164}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 80, 237, 242, 181}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 54, 207, 60, 14, 110}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 233, 154, 232, 55, 54, 3}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 101, 206, 98}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 203, 226, 241, 22}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 19, 117, 136, 137, 52}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 79}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 46, 169, 209, 215, 162, 98}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 224, 119, 207, 227, 167}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 228, 29, 70}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 163, 52, 40}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 40, 7, 62}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 143, 100, 92, 121, 62}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 255, 27, 241, 14}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 23, 116, 144, 89}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 231, 211, 230}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 46}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 153, 28, 18}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 121, 128, 195, 169, 17}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 30, 251, 244}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 110}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 231, 57, 151, 216, 226}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 248, 216, 253, 156}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 66, 243}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 191, 0, 121, 241, 47}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 67, 246, 92}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 16, 6, 18}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 60, 17, 29, 102}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 37}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 33}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 235, 144, 148, 166, 129}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 135, 195, 108, 107, 188}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 196, 51}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 254, 240, 113, 172, 107, 209}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 126}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 84, 176, 210, 181, 32, 10}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 154, 88, 135, 84, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 201, 199}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 154}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 188, 1}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 136, 108}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 101, 117, 199, 195}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 45}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 36, 191, 211, 198}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 208, 8, 134, 83, 229}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 75, 244, 187}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 92, 236, 156}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 74, 228}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 86, 234}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 255, 161}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 196, 191, 85, 226}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 17, 246, 143}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 140, 184, 87}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 81, 81}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 10, 155, 139, 143}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 149, 89, 235, 161}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 151, 137, 21, 17, 31}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 10}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 227, 68, 202}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 162, 19, 253, 50}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 117, 233, 12, 154, 59}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 243, 60, 156}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 175, 7, 96, 221}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 203, 208, 145}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 212, 44, 59}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 62, 224, 170, 144}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 89, 198}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 188, 155, 199}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 17, 76, 167}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 164, 140, 116, 27, 178}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 213, 32, 139}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 85, 16, 255, 228}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 80, 251, 12, 30, 219}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 180, 87, 28, 39}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 68, 84, 227, 86, 239}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 4, 88, 15, 228}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 4, 79, 148, 41}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 3}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 44, 201}, 133}, {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 4, 151, 150, 255}, 133}, {{138, 74, 163, 93, 12, 0, 0, 218, 131, 58, 115, 80, 247, 174, 85, 250}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 176, 163, 187, 62, 120, 240, 220}, 93}, {{138, 74, 163, 93, 12, 0, 0, 199, 183, 41, 240, 6, 166, 68, 175, 197}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 240, 119, 35, 230, 166, 112}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 45, 165, 97, 140, 144}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 237}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 162, 148, 235, 110, 171}, 93}, {{138, 74, 163, 93, 12, 0, 0, 81, 180, 240, 149, 21, 15, 206, 207, 142}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 20, 190, 254, 181, 126, 21, 225, 142}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 176, 82, 73, 10, 23, 103}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 57, 219, 118, 172}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 146, 168, 201, 55, 75, 241, 220, 138}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 168, 231, 116, 13}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 68, 216, 111}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 236, 60, 117, 246, 190, 66, 201}, 93}, {{138, 74, 163, 93, 12, 0, 226, 98, 70, 136, 226, 99, 156, 94, 23, 161}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 199, 144, 59}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 77, 170, 93, 17, 137, 133, 85}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 22, 83, 24, 22}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 5, 83, 219, 44, 101, 164}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 216, 193, 81, 5, 70}, 93}, {{138, 74, 163, 93, 12, 0, 77, 14, 245, 82, 194, 72, 117, 86, 145, 3}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 232, 15, 220, 67, 245}, 93}, {{138, 74, 163, 93, 12, 0, 0, 21, 78, 203, 220, 104, 87, 145, 145, 243}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 93}, {{138, 74, 163, 93, 12, 0, 0, 183, 107, 117, 140, 135, 140, 84, 181, 207}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 43, 15, 248, 110, 12, 216}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 58, 54, 162, 106, 60, 57, 26, 121}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 96}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 125, 33, 53, 159}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 13, 10, 213, 211, 9, 35, 181}, 93}, {{138, 74, 163, 93, 12, 0, 115, 159, 120, 145, 224, 50, 242, 16, 122, 54}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 82, 22, 188, 99, 60, 73, 161}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 102}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 67, 15, 190, 183}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 226, 239, 89, 215, 13, 65, 181}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 168, 95, 82, 199}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 75, 110, 5, 134}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 65, 118, 178, 45, 255, 77}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 239, 210, 128, 228, 112, 144, 92, 241}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 93}, {{138, 74, 163, 93, 12, 0, 0, 57, 53, 97, 107, 72, 217, 155, 30, 243}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 251, 191, 88, 78, 214}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 240, 252, 94}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 162, 89, 184, 214}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 235, 12, 224, 167, 50}, 93}, {{138, 74, 163, 93, 12, 247, 90, 129, 138, 219, 24, 197, 12, 54, 244, 203}, 93}, {{138, 74, 163, 93, 12, 0, 0, 94, 246, 144, 121, 218, 160, 203, 1, 192}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 103, 208, 18, 80, 136, 221, 92, 51, 153, 69}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 221, 0, 9, 238, 149}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 244, 236, 237, 220, 22}, 93}, {{138, 74, 163, 93, 12, 0, 0, 229, 176, 190, 127, 87, 5, 4, 247, 17}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 190, 241, 129, 148, 45, 146}, 93}, {{138, 74, 163, 93, 12, 0, 123, 16, 0, 166, 104, 207, 138, 12, 118, 51}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 146, 93, 104, 47, 218, 10}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 93}, {{138, 74, 163, 93, 12, 0, 184, 207, 118, 11, 151, 100, 213, 199, 239, 210}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 81, 88, 213, 87}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 189, 41, 249, 79, 165, 116, 174, 63}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 143, 50, 161, 73}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 161, 69, 159, 31, 86, 6, 242, 33}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 103, 85, 122, 233, 122}, 93}, {{138, 74, 163, 93, 12, 0, 156, 246, 167, 201, 22, 57, 156, 83, 129, 148}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 94, 133, 44, 155, 24, 97, 18}, 93}, {{138, 74, 163, 93, 12, 0, 170, 241, 40, 164, 249, 168, 227, 109, 218, 217}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 155, 5, 9, 40, 214, 97, 28, 153}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 185, 242, 125, 82, 8, 194, 204, 213}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 108, 162, 136, 26, 132, 64, 46}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 95, 23, 75, 237}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 149, 113, 223, 26, 75, 57, 63}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 162, 88, 235, 77}, 93}, {{138, 74, 163, 93, 12, 0, 252, 122, 58, 98, 219, 63, 130, 94, 154, 103}, 93}, {{138, 74, 163, 93, 12, 0, 217, 74, 104, 173, 143, 7, 153, 54, 232, 171}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 58, 251, 222}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 195, 179, 209, 68}, 93}, {{138, 74, 163, 93, 12, 0, 0, 255, 188, 85, 69, 92, 175, 168, 41, 212}, 93}, {{138, 74, 163, 93, 12, 0, 91, 66, 75, 149, 159, 237, 112, 134, 0, 5}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 164, 115, 192, 121, 167}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 73, 188, 38, 247}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 221, 223, 245, 244, 157, 225, 245, 56}, 93}, {{138, 74, 163, 93, 12, 0, 0, 231, 188, 236, 47, 142, 120, 136, 77, 74}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 41, 181, 115, 14, 186, 67, 13, 35}, 93}, {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 216, 212, 150, 137, 137}, 93}, {{138, 74, 163, 93, 12, 0, 0, 65, 142, 203, 78, 76, 131, 226, 187, 25}, 93}, {{138, 74, 163, 93, 12, 0, 0, 181, 180, 83, 22, 187, 254, 238, 161, 27}, 93}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 116}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 88}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 228, 222}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 165}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 226}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 192}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 63}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 221}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 1}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 63}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 133, 96}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 14}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 65}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 141}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 243}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 15, 52}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 129}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 230}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 205}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 251}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 14}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 140}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 252}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 87}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 85, 43}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 236}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 82, 9}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 250}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 49}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 238, 55}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 141}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 183, 138}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 56}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 141, 23}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 52}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 137}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 41}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 48}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 162, 71}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 173}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 63}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 228}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 18, 49}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 124}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 163}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 6, 48}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 10}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 10}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 74}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 235}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 246}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 133}, 176}, {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 168}, 176}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 58, 42}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 63, 53}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 204}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 242, 46, 203}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 225}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 180}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 158, 97, 100}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 222, 231, 78}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 247}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 121, 172, 199}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 11}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 254}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 120}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 243, 96, 191}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 111}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 217, 252, 57}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 252}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 59}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 166, 79, 53}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 247}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 138, 170, 201}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 19}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 208, 179, 53}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 182, 230, 32}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 104, 209, 53}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 64, 216}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 76, 153}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 156}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 194, 103, 25}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 251, 44, 136}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 97}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 254, 133, 243}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 245}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 66, 145, 211}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 230}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 238, 92, 142}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 21, 54}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 147}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 8}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 111, 216}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 64, 221, 249}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 201, 150}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 101, 175}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 34}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 6, 247}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 205, 43}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 36}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 234, 111, 192}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 119, 216, 226}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 138, 114}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 118}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 191}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 147, 222, 90}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 222}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 135}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 71, 110}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 54}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 1, 185, 193}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 123, 181, 16}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 49, 81}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 151, 55, 135}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 133}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 205, 243, 186}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 107}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 63, 95}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 205, 90, 193}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 178, 207, 205}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 209, 120, 51, 50}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 226, 96}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 201, 131}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 130, 83}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 89}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 71}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 52, 193, 203}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 65, 169, 236}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 155, 7, 221, 122}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 252, 19, 182}, 68}, {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 39, 78, 215}, 68}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 202, 165}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 45, 190}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 105, 83}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 226}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 168, 90}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 133, 248}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 40}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 162}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 53}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 162, 221}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 107}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 204, 233}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 53, 206}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 209}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 170, 67, 240}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 142, 71}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 57, 184}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 142, 110}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 227}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 69, 224}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 21, 169}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 11}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 77, 59}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 114, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 164}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 171}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 67}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 102, 90}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 27, 101}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 211}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 47}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 3, 172}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 36, 113}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 199, 231}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 249}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 124, 236}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 200}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 68, 153}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 246, 147}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 60}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 191}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 203}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 225, 144}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 148, 71}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 209, 39}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 63}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 15, 3}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 40, 191}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 83}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 41}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 84, 255, 44}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 231}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 254, 248}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 136, 12, 200}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 94, 208}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 81, 182}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 28, 197}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 81}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 106}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 122, 105}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 100}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 155}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 246, 212}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 178}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 154}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 166, 59}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 181}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 229}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 68, 95}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 117}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 201, 154}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 48, 60}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 202, 230}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 247}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 240}, {{2, 205, 40, 24, 0, 0, 0, 65, 150, 104, 171, 54, 64, 184, 125, 172}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 249, 6, 222, 246, 68, 52}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 219}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 136}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 109, 93, 7, 72, 110, 81, 9}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 207, 86, 75, 18, 248}, 240}, {{2, 205, 40, 24, 0, 0, 0, 207, 255, 210, 94, 148, 13, 98, 158, 81}, 240}, {{2, 205, 40, 24, 0, 0, 0, 86, 61, 154, 11, 179, 28, 15, 250, 98}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 135}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 219, 28, 45, 221, 10, 44, 56, 196}, 240}, {{2, 205, 40, 24, 0, 0, 0, 16, 125, 154, 55, 42, 14, 22, 155, 37}, 240}, {{2, 205, 40, 24, 0, 0, 0, 86, 106, 105, 210, 76, 137, 69, 51, 229}, 240}, {{2, 205, 40, 24, 0, 103, 160, 82, 33, 103, 244, 27, 233, 244, 101, 114}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 184, 69, 42, 118, 65, 193}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 92, 146, 126, 193, 253}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 210, 57, 91, 19, 76, 246, 122}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 1}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 227, 182, 209, 161, 153, 46, 21, 2}, 240}, {{2, 205, 40, 24, 0, 0, 126, 143, 55, 196, 27, 237, 234, 148, 12, 53}, 240}, {{2, 205, 40, 24, 0, 61, 136, 17, 128, 26, 154, 126, 143, 38, 48, 165}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 104, 227, 198, 84, 67, 69}, 240}, {{2, 205, 40, 24, 0, 0, 221, 181, 75, 214, 71, 205, 62, 112, 151, 158}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 46, 35, 28, 239, 204, 41, 178, 190}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 217, 127}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 164}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 84, 201, 0, 201, 142, 137, 176, 7, 162, 175}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 55, 12, 240, 48}, 240}, {{2, 205, 40, 24, 0, 0, 0, 222, 253, 66, 212, 96, 244, 249, 62, 166}, 240}, {{2, 205, 40, 24, 0, 0, 0, 79, 29, 146, 173, 226, 102, 77, 3, 228}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 201, 103, 175, 201}, 240}, {{2, 205, 40, 24, 0, 238, 149, 224, 151, 251, 170, 2, 51, 192, 192, 70}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 227, 63}, 240}, {{2, 205, 40, 24, 0, 0, 98, 241, 1, 24, 35, 83, 152, 148, 142, 106}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 94, 22}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 64, 141, 69, 26, 104, 47, 103}, 240}, {{2, 205, 40, 24, 0, 104, 22, 74, 153, 197, 237, 51, 9, 134, 232, 181}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 120, 204, 82, 15}, 240}, {{2, 205, 40, 24, 0, 222, 1, 51, 171, 118, 175, 43, 164, 108, 23, 187}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 190, 39, 238, 206, 116, 56, 96}, 240}, {{2, 205, 40, 24, 0, 0, 38, 184, 172, 82, 106, 119, 39, 77, 83, 61}, 240}, {{2, 205, 40, 24, 0, 0, 101, 185, 222, 19, 19, 70, 151, 116, 181, 252}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 161, 93, 227, 161, 15, 74}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 188, 10, 160, 189, 57}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 178, 94, 170, 238, 33, 90, 184}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 211, 177, 22, 182, 240, 130, 9, 99}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 231}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 184, 199, 234, 215, 16, 177}, 240}, {{2, 205, 40, 24, 0, 0, 0, 110, 145, 35, 55, 46, 58, 1, 57, 30}, 240}, {{2, 205, 40, 24, 0, 73, 102, 13, 248, 148, 42, 94, 76, 182, 233, 249}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 136}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 60}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 138, 25, 208, 17, 144, 35}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 139}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 57, 146, 112, 23, 145, 16, 242}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 158, 85, 189, 108, 121}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 3, 166, 152, 213, 157, 161, 227}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 30, 254, 30, 126, 146}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 219}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 178, 160, 33, 136, 134, 105}, 240}, {{2, 205, 40, 24, 0, 0, 0, 36, 181, 191, 105, 160, 92, 42, 52, 133}, 240}, {{2, 205, 40, 24, 0, 0, 0, 85, 14, 109, 167, 172, 119, 201, 53, 42}, 240}, {{2, 205, 40, 24, 0, 0, 194, 152, 63, 255, 53, 159, 37, 63, 76, 156}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 27}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 126, 188, 98, 216, 109, 211}, 240}, {{2, 205, 40, 24, 0, 36, 239, 254, 195, 195, 203, 93, 175, 254, 86, 11}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 114, 156, 18, 187, 168, 62, 134}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 181, 23, 66, 37, 43, 223, 44, 139}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 58, 69, 24, 120, 182, 36, 76}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 250, 9, 188, 181}, 240}, {{2, 205, 40, 24, 0, 203, 25, 173, 116, 89, 207, 51, 115, 227, 236, 76}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 32}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 76, 189, 109, 235, 144}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 69, 157, 190, 214, 191, 49, 59, 111}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 146, 120, 54, 145, 3}, 240}, {{2, 205, 40, 24, 0, 224, 86, 255, 133, 229, 152, 16, 169, 151, 199, 237}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 51, 114, 10, 120}, 240}, {{2, 205, 40, 24, 0, 0, 80, 193, 22, 202, 28, 134, 173, 109, 58, 199}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 52, 159, 27, 157, 123, 108, 184}, 240}, {{2, 205, 40, 24, 0, 65, 178, 63, 90, 198, 244, 239, 52, 23, 70, 138}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 85, 15, 210, 176, 43, 54, 125}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 31}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 130}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 18}, 240}, {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 26, 89, 183, 72, 166}, 240}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 58, 96, 63}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 29}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 114, 196, 160, 156, 150, 237}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 249, 100}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 19, 255, 238}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 181, 17, 192, 104}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 151, 117, 249, 114, 126}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 161, 24, 50, 27, 54}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 88, 232, 24, 142}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 183}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 179, 170}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 143, 168, 192, 146, 192, 248}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 91, 121, 61, 72}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 101}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 154}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 199, 15}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 136, 168, 166, 227, 1, 217}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 94, 144, 85, 11, 235, 75}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 203}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 145, 96, 18, 84, 21, 63}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 117, 35, 195, 17, 216}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 148, 123, 174, 83, 73, 82}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 235, 204}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 114, 210, 122, 74}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 4, 205, 57, 127, 91, 248}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 102, 237}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 92, 247, 26}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 170}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 178, 71, 59, 241, 65, 183}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 144, 25, 179}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 218}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 124, 88, 66, 212}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 12, 157, 169}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 163, 196, 171, 253, 142}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 244, 32, 229}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 180, 196, 200}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 250, 211, 8, 122}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 228, 221, 58, 161, 2}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 121, 170, 31, 186}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 80, 94}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 71, 224}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 92, 101, 222, 61, 3, 170}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 11, 104, 207, 217, 70}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 210, 120, 5, 107, 159, 153}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 51, 124, 249}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 2, 208, 85, 88}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 130, 77, 69, 205, 244}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 161, 219}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 54, 233, 193, 4, 59, 9}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 234}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 85, 118}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 82, 216, 231, 96}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 244, 120, 189, 185}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 210, 152, 220, 149}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 206, 209, 154, 236}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 65, 203, 172, 5}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 34, 146}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 159, 253}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 202, 91, 66}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 193, 118, 184, 4, 143}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 176, 173, 158, 93}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 193, 156, 19, 130}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 175}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 132}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 139, 6}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 74, 255}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 246}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 142, 77, 179, 240, 194}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 243, 232, 3, 25, 210, 86}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 118, 72, 216, 236, 29}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 51, 116, 93, 184, 42}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 53, 138, 177, 90}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 1, 94, 21}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 161, 250, 206}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 33}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 100, 69, 6, 63, 130, 59}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 249, 192, 199, 193}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 82}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 199}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 227, 31, 202, 254, 242, 158}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 121, 148, 150, 198}, 83}, {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 90, 165, 70, 198, 96}, 83}, {{5, 117, 182, 141, 166, 249, 196, 0, 31, 223, 183, 92, 76, 48, 191, 23}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 236, 57, 22, 183, 2, 64, 135, 134}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 219, 166}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 140, 4, 200, 46}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 90, 250, 52, 217, 163, 188}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 242, 154, 239, 180}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 111, 94, 14, 120, 35}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 80, 74, 38, 74, 37}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 204, 178, 152, 218, 98}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 61, 118, 106, 184, 136, 20}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 39, 148, 149, 61, 219, 66, 168, 228}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 214, 223, 93, 168, 123, 122, 34, 92}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 173, 122, 186, 43, 143}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 26, 70, 13, 174, 31, 61, 236}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 121, 235}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 177, 255, 239}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 242, 50, 127, 184, 132}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 194, 97, 128, 220}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 172, 103}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 251, 132, 163, 197}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 63, 198, 203}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 238, 59, 160, 241, 60}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 201, 197, 196, 38, 235}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 14, 156, 152}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 82}, 132}, {{5, 117, 182, 141, 166, 249, 196, 33, 208, 238, 25, 95, 244, 234, 253, 192}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 79, 6, 222}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 19, 115, 160}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 126, 218, 123, 227, 226, 169, 70, 164}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 158, 69, 27, 254, 98, 156}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 156, 168, 61, 3, 214, 160}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 218, 150, 89}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 211, 94, 149, 248, 186, 49}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 112, 102, 51}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 236, 38, 202, 47, 115, 93, 141, 235}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 19, 29, 57, 178, 220, 27}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 108, 98, 72, 57}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 233, 129, 65}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 116, 247, 33, 0, 17, 207, 13, 244}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 89, 74, 35}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 178, 243, 69, 199, 100}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 92, 169, 163, 74, 237, 220, 146}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 190, 89, 178, 193, 76, 203, 37, 94}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 103, 90, 101, 99, 40, 61, 8}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 75, 6}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 145, 35}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 139, 250, 226, 217, 54, 93, 184}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 151, 193, 182, 194, 115}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 92, 89, 178, 110, 38, 80, 241}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 234, 253, 170, 209}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 228, 64, 250, 189, 208, 132}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 52, 20, 161, 72, 222, 208, 51, 90}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 17, 154, 39, 88, 210}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 180, 195, 79}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 104, 170, 86}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 148, 13, 39, 136, 161, 22}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 26, 43, 251, 204}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 250, 188, 66, 69, 31, 201, 114}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 234, 207, 51, 52}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 24, 107, 247, 109, 71, 25}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 44, 44, 250, 126, 26, 76, 68, 104}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 186, 10}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 157, 254, 195}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 116, 73, 214, 91, 72, 0, 84, 164}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 113, 251, 140, 91, 46, 7, 17}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 220, 229, 208, 38, 250, 167}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 73, 20}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 165, 230, 49, 9, 3, 233, 89}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 142, 224, 177, 239, 219, 29}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 81, 187, 107, 240, 197, 192, 18, 139}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 234, 127, 35, 216, 55}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 113, 59, 181, 31, 31}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 156, 155, 18, 84, 59, 124, 149, 133}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 132}, {{5, 117, 182, 141, 166, 249, 196, 0, 137, 43, 222, 31, 202, 101, 48, 192}, 132}, {{46, 152, 169, 0, 0, 0, 214, 135, 124, 184, 187, 199, 54, 77, 189, 232}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 201, 104, 173, 25, 97, 172, 164}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 158, 171, 43, 49, 242, 173}, 217}, {{46, 152, 169, 0, 0, 1, 241, 15, 7, 41, 4, 62, 112, 66, 121, 41}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 246}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 148, 55, 23}, 217}, {{46, 152, 169, 0, 188, 144, 203, 120, 99, 159, 121, 214, 202, 79, 83, 128}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 107, 167, 80, 175, 149, 194, 113}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 47, 166, 111, 236, 104, 147}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 204, 10}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 110, 51, 251}, 217}, {{46, 152, 169, 0, 0, 24, 208, 96, 240, 77, 12, 46, 205, 57, 92, 9}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 12, 171, 188, 207, 188, 236}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 14, 87, 73}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 187}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 70, 94, 25, 51, 188, 177, 49}, 217}, {{46, 152, 169, 0, 0, 0, 173, 246, 139, 143, 133, 106, 172, 55, 191, 93}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 213, 45, 93, 8, 248, 63, 233, 133, 113}, 217}, {{46, 152, 169, 0, 0, 226, 66, 88, 97, 18, 70, 112, 8, 159, 54, 239}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 242, 96, 244, 9, 183, 105, 240, 12}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 15, 126, 236}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 188, 33, 24}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 204, 82, 228, 179, 39}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 128, 106, 29, 123, 226, 95}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 183, 247, 85, 151, 53, 173}, 217}, {{46, 152, 169, 0, 0, 0, 0, 81, 40, 10, 145, 92, 147, 109, 37, 246}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 70, 214, 243, 53, 9, 83, 143, 190}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 82, 32}, 217}, {{46, 152, 169, 0, 16, 56, 98, 111, 171, 252, 47, 243, 85, 145, 72, 207}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 68, 246}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 83, 145, 186, 105, 249, 122, 238, 159}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 109, 40, 251, 234, 252}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 247, 49, 252}, 217}, {{46, 152, 169, 0, 0, 0, 0, 46, 35, 236, 14, 3, 124, 51, 131, 254}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 42, 41, 157, 190, 170, 103, 108, 104}, 217}, {{46, 152, 169, 0, 0, 0, 0, 196, 252, 249, 153, 255, 142, 96, 138, 167}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 83, 65, 193, 57, 178}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 94, 57, 121, 0, 190, 52, 159}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 115, 6, 141, 201, 107}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 130, 192}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 24, 210, 116, 88, 44}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 133, 132, 17, 20, 77, 120, 155}, 217}, {{46, 152, 169, 0, 0, 0, 0, 222, 81, 50, 125, 189, 87, 189, 111, 1}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 61, 117, 196}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 153, 240, 125, 89, 78, 156, 219}, 217}, {{46, 152, 169, 0, 135, 103, 153, 167, 27, 167, 247, 163, 4, 159, 71, 46}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 128, 149, 13, 159, 158, 160, 34}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 61, 108, 159, 191, 69, 150, 69, 72, 196, 5}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 3, 90, 252, 20, 153, 146}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 83, 225, 116, 255, 98}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 177, 74, 211}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 51, 7, 3}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 168, 23, 16, 181, 150}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 219, 69, 126, 20, 29, 36, 171, 152, 82, 71, 11, 148}, 217}, {{46, 152, 169, 0, 0, 0, 0, 110, 156, 46, 114, 214, 163, 203, 6, 44}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 16, 235, 241, 151, 185, 36, 171, 129}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 144, 165, 179, 106, 153}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 142, 82}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 29, 127, 144}, 217}, {{46, 152, 169, 0, 0, 0, 0, 48, 109, 167, 97, 93, 74, 187, 153, 169}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 137, 168, 235, 22, 124, 127, 164, 96}, 217}, {{46, 152, 169, 0, 0, 196, 235, 223, 103, 188, 61, 50, 229, 166, 119, 86}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 19, 163, 33}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 35, 86, 149, 186, 76, 250, 88}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 6, 179}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 176}, 217}, {{46, 152, 169, 0, 0, 106, 75, 248, 133, 111, 114, 234, 2, 29, 255, 139}, 217}, {{46, 152, 169, 0, 0, 4, 153, 132, 51, 236, 19, 133, 223, 155, 207, 94}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 184, 240, 119, 182, 180}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 207, 148, 204, 108, 50, 213, 130}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 13, 117, 233, 26, 136, 28, 125}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 7, 200, 73, 113, 74, 151, 205, 140}, 217}, {{46, 152, 169, 0, 0, 185, 65, 62, 222, 39, 26, 209, 223, 61, 9, 214}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 215, 163, 158, 202, 159, 53, 129}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 217}, {{46, 152, 169, 0, 0, 0, 0, 12, 55, 158, 92, 9, 134, 45, 7, 34}, 217}, {{46, 152, 169, 0, 0, 0, 209, 223, 212, 204, 78, 168, 186, 216, 86, 151}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 1, 27, 42, 57, 90, 182, 247}, 217}, {{46, 152, 169, 0, 0, 0, 71, 171, 241, 72, 206, 3, 78, 50, 87, 198}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 217}, {{46, 152, 169, 0, 0, 39, 13, 93, 175, 181, 44, 225, 125, 27, 122, 116}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 231, 126, 29, 114, 240, 230, 113}, 217}, {{46, 152, 169, 0, 0, 1, 226, 83, 219, 205, 42, 80, 146, 64, 53, 48}, 217}, {{46, 152, 169, 0, 0, 0, 0, 170, 103, 202, 147, 231, 87, 5, 94, 139}, 217}, {{46, 152, 169, 0, 0, 0, 247, 208, 167, 208, 107, 41, 90, 242, 170, 118}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 225, 19, 88, 143, 190, 88, 153, 101}, 217}, {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 98}, 217}, {{46, 152, 169, 0, 88, 62, 14, 230, 14, 217, 255, 30, 10, 213, 130, 157}, 217}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 24}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 205, 107, 157, 198}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 215}, 61}, {{0, 0, 0, 0, 250, 233, 114, 182, 238, 224, 246, 248, 106, 211, 94, 142}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 30}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 123, 167, 7, 13, 75, 43, 112, 165}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 249, 219, 169}, 61}, {{0, 0, 0, 137, 19, 7, 12, 97, 224, 10, 22, 50, 253, 55, 213, 136}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 183, 140, 98, 98, 210, 184, 2, 198}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 222}, 61}, {{0, 0, 10, 103, 98, 113, 170, 243, 106, 6, 99, 207, 49, 34, 139, 16}, 61}, {{0, 0, 99, 116, 196, 153, 6, 25, 150, 118, 54, 58, 110, 41, 26, 36}, 61}, {{0, 0, 0, 0, 0, 167, 250, 15, 92, 243, 248, 241, 64, 206, 237, 255}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 220, 89, 244, 155}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 228, 171, 87, 192}, 61}, {{0, 0, 0, 0, 0, 0, 236, 28, 111, 95, 77, 136, 129, 3, 1, 216}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 249}, 61}, {{0, 237, 199, 237, 214, 56, 44, 163, 196, 122, 160, 51, 60, 37, 37, 23}, 61}, {{0, 0, 0, 0, 0, 182, 7, 147, 39, 118, 184, 243, 22, 240, 118, 152}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 27, 81, 72, 159, 212, 18, 24, 196, 3, 25, 94, 177, 149, 76}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 172, 184, 21, 95, 160, 32}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 218}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 229, 54, 1, 93, 81, 255}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 76, 151, 34, 107}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 8, 160, 222, 150}, 61}, {{0, 0, 0, 19, 87, 104, 5, 140, 180, 124, 238, 228, 101, 148, 90, 225}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 23}, 61}, {{0, 0, 170, 174, 173, 49, 109, 61, 141, 118, 16, 0, 198, 139, 144, 255}, 61}, {{0, 144, 49, 240, 149, 73, 65, 240, 98, 128, 136, 182, 252, 76, 145, 185}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 61}, {{0, 0, 0, 0, 0, 0, 247, 120, 223, 56, 76, 213, 198, 217, 12, 88}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 5, 126, 85, 90, 20}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 16, 79, 35, 149}, 61}, {{0, 0, 38, 48, 226, 45, 143, 30, 95, 40, 44, 86, 37, 148, 26, 125}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 199, 226}, 61}, {{0, 52, 93, 199, 208, 170, 160, 158, 62, 187, 64, 153, 80, 128, 15, 6}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 61, 136, 84, 224, 36}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 204, 176}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 61}, {{0, 0, 0, 0, 0, 0, 118, 234, 215, 171, 14, 242, 170, 74, 119, 101}, 61}, {{0, 0, 0, 0, 0, 0, 44, 75, 75, 176, 23, 209, 24, 106, 47, 138}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 137, 98}, 61}, {{0, 0, 0, 0, 0, 90, 219, 188, 87, 233, 113, 175, 205, 181, 184, 20}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 227, 92, 97, 115}, 61}, {{0, 0, 0, 0, 0, 0, 102, 235, 214, 161, 143, 146, 41, 0, 173, 112}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 83, 244, 185}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 219, 231, 188}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 213, 231, 98, 176, 80, 112, 7, 141}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 106, 155, 190}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 20, 14, 189, 142, 90, 195}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 169}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 230, 183}, 61}, {{0, 0, 0, 0, 0, 0, 0, 25, 129, 65, 77, 216, 163, 18, 125, 95}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 128}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 52, 196}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 152, 72, 14}, 61}, {{0, 0, 62, 228, 215, 77, 202, 134, 22, 2, 240, 54, 26, 246, 89, 62}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 190, 204, 103, 64, 126, 212}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 201, 122}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 79, 89, 93}, 61}, {{0, 0, 0, 0, 0, 0, 183, 157, 153, 0, 49, 40, 12, 84, 59, 224}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 42}, 61}, {{0, 0, 0, 0, 34, 107, 146, 31, 121, 127, 208, 77, 217, 10, 207, 128}, 61}, {{0, 0, 0, 105, 198, 119, 50, 24, 61, 0, 92, 5, 205, 114, 177, 32}, 61}, {{0, 0, 0, 0, 0, 133, 169, 114, 29, 80, 52, 203, 246, 21, 183, 159}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 190, 96, 130, 80, 140, 91}, 61}, {{0, 0, 0, 0, 38, 239, 149, 241, 240, 64, 64, 190, 32, 106, 65, 251}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 220}, 61}, {{0, 0, 0, 0, 0, 0, 0, 147, 137, 195, 191, 16, 220, 245, 103, 53}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 239}, 61}, {{0, 0, 0, 180, 229, 0, 85, 126, 212, 110, 17, 176, 250, 246, 77, 33}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 128, 173, 236, 151, 70}, 61}, {{0, 0, 0, 0, 0, 0, 73, 21, 201, 56, 93, 13, 121, 129, 16, 61}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 135, 32, 129, 132}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 124, 116}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 233, 168, 0, 229}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 29, 255, 40}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 209, 212, 218, 17, 200}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 111, 50}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 239, 17, 5}, 61}, {{0, 0, 0, 0, 0, 0, 150, 37, 67, 44, 134, 40, 213, 194, 72, 231}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 226}, 61}, {{0, 0, 0, 0, 0, 179, 215, 48, 24, 70, 198, 10, 166, 141, 148, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 150, 227, 163, 155}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 78, 176, 241, 240, 18, 172, 156, 62}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 249, 104, 231, 227, 15, 209}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 158, 86, 69, 125, 153}, 61}, {{0, 0, 0, 16, 207, 141, 210, 103, 224, 121, 175, 5, 112, 155, 126, 115}, 61}, {{0, 0, 0, 0, 244, 149, 194, 121, 80, 39, 19, 23, 120, 206, 195, 120}, 61}, {{0, 0, 0, 0, 0, 139, 54, 239, 86, 182, 139, 86, 204, 132, 15, 154}, 61}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 28}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 110, 231}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 147, 167, 142, 1, 219, 164}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 7}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 112, 200, 78, 199, 90}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 165, 47, 64, 9}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 115, 48, 64, 190, 40, 62}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 6, 240, 121, 247}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 90, 57, 224, 71, 126, 226, 167}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 163, 132, 8, 70, 126, 52}, 193}, {{233, 202, 159, 219, 0, 0, 110, 174, 243, 90, 74, 170, 86, 96, 181, 124}, 193}, {{233, 202, 159, 219, 0, 0, 162, 137, 75, 225, 38, 149, 184, 166, 107, 9}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 102, 76, 184, 102, 207, 57, 153}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 68, 148, 93, 30}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 241}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 235, 27, 244, 192, 224, 45, 71}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 45, 160, 104, 93, 246, 37}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 80, 122}, 193}, {{233, 202, 159, 219, 0, 0, 0, 221, 149, 160, 84, 154, 86, 206, 106, 211}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 31}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 34}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 139, 179, 237, 218, 192, 103, 120}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 188, 92, 221, 119, 70, 48, 109, 193, 181, 135}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 231}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 122, 146, 246, 161, 7, 178}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 123, 175, 233, 59, 232, 186, 90}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 120, 209, 19, 194, 36, 117}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 159, 243, 8, 114, 219, 155}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 106, 6}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 114}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 246, 122, 37, 233, 250, 45, 128}, 193}, {{233, 202, 159, 219, 0, 0, 0, 155, 20, 35, 254, 238, 228, 179, 85, 78}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 111, 188, 15, 243, 82, 243, 224, 65}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 27, 95, 4, 8, 227}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 77, 15, 161, 143, 235, 111, 245}, 193}, {{233, 202, 159, 219, 0, 0, 195, 227, 43, 178, 150, 124, 137, 251, 137, 27}, 193}, {{233, 202, 159, 219, 0, 0, 0, 23, 100, 194, 117, 189, 241, 122, 38, 182}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 103}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 67, 88}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 126, 23, 224, 44, 126, 76, 136, 48}, 193}, {{233, 202, 159, 219, 0, 34, 185, 3, 96, 201, 71, 253, 89, 121, 74, 28}, 193}, {{233, 202, 159, 219, 0, 167, 173, 213, 234, 99, 57, 88, 15, 124, 50, 113}, 193}, {{233, 202, 159, 219, 0, 118, 91, 168, 156, 209, 253, 191, 90, 154, 116, 115}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 139, 19, 90, 73, 249}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 147, 238, 27, 42}, 193}, {{233, 202, 159, 219, 0, 0, 0, 26, 58, 48, 230, 105, 16, 15, 56, 24}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 217}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 197}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 239, 145, 14, 89, 238, 110}, 193}, {{233, 202, 159, 219, 0, 0, 0, 38, 27, 190, 229, 135, 61, 66, 137, 94}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 83, 93, 127, 244, 133, 52, 185, 57}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 235}, 193}, {{233, 202, 159, 219, 0, 109, 254, 71, 101, 245, 185, 11, 98, 155, 222, 96}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 31, 170, 167, 190, 58}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 177, 151, 183, 160}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 183, 76}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 109, 204}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 115, 212, 200, 146, 156, 65}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 209, 152, 32, 7, 146}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 133, 236, 97, 3, 148}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 182, 62, 173, 230, 156, 238}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 171, 104, 137, 158}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 96}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 152, 197, 222, 7, 176, 104, 177}, 193}, {{233, 202, 159, 219, 0, 100, 210, 121, 81, 173, 178, 170, 147, 14, 92, 195}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 156, 152, 16, 146, 198, 186, 142}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 42, 234, 33, 47, 138, 180, 253}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 90, 79, 114, 203}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 8}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 99, 143, 149, 193, 51}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 35, 84}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 173, 98, 47, 117}, 193}, {{233, 202, 159, 219, 0, 0, 144, 254, 140, 115, 56, 8, 213, 231, 203, 120}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 210, 23}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 22, 20, 172, 216}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 223}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{233, 202, 159, 219, 0, 0, 0, 248, 49, 180, 182, 87, 80, 102, 148, 62}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 92, 31}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 227, 145, 238, 92}, 193}, {{233, 202, 159, 219, 0, 0, 215, 12, 109, 162, 111, 250, 120, 248, 202, 37}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 213, 164, 59, 194, 14, 255}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 117, 112, 182, 132, 42, 253, 65, 19}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 252, 32, 212, 16, 225, 222, 84}, 193}, {{233, 202, 159, 219, 0, 0, 80, 59, 53, 212, 45, 237, 209, 250, 40, 193}, 193}, {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 193}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 254, 59}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 68, 245, 75, 39, 252, 7}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 250, 53, 247, 152, 46}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 34}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 147, 162}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 25, 207, 61, 20, 237, 175}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 160, 185}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 248, 195, 108, 143, 219, 221}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 249, 238, 174, 213, 97}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 93, 137, 17, 70, 165}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 207, 17, 211, 224}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 23, 198, 212, 32, 87}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 121, 245, 127, 245, 11}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 168, 145, 103}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 131, 34, 39, 113, 212, 28}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 200, 49, 192, 103, 60, 134}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 214, 252, 44}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 253, 36, 40, 53, 204, 43, 54}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 84, 47, 127}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 150, 200, 84, 110}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 15, 254, 223, 167, 12}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 3, 94}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 138}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 167, 194}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 160, 215, 166, 175}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 61, 150}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 35, 70}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 146}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 69, 219}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 47, 48, 101, 62, 37, 27}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 63, 181}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 111}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 63, 201, 243, 121}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 196}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 159, 253, 5, 24, 28}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 121}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 152}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 11, 210, 86}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 121, 57, 185, 145}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 218, 31, 236, 242}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 16, 251}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 31}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 29, 13, 166, 106, 132}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 152}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 210, 19, 231}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 14, 196}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 75, 252, 29, 129}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 213, 40}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 201}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 212, 43, 252}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 65, 213, 43, 103, 79, 98}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 223, 146, 142, 20, 251}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 79, 247, 184, 139, 30, 140}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 217, 131, 92, 129, 39}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 120, 26, 248}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 79}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 94, 39, 2, 13}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 219, 139, 130}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 81, 38, 3, 211}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 246}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 42, 12}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 174, 117, 84}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 128, 242, 126, 213, 129, 191}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 231}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 156, 156, 240, 4, 25, 194}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 110}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 206, 177, 252, 146}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 74, 146, 8}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 97}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 45, 240, 34, 33, 38, 27}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 90, 229}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 121, 109, 114, 138}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 15, 36, 110}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 174, 46, 99, 151, 24}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 245, 112}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 105, 60, 26, 130}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 103, 159, 117, 193, 195}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 104, 208, 208}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 195, 170, 165, 149}, 61}, {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 61}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 162}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 108}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 192, 19, 178, 91}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 100, 130, 14, 89, 236}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 240, 103, 117}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 33, 13, 168, 155}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 21, 231, 180, 233}, 65}, {{241, 222, 251, 114, 200, 0, 120, 145, 67, 43, 124, 132, 59, 105, 171, 226}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 66, 157, 232, 60}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 92, 109, 219, 209}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 43, 20, 245, 71, 7, 218}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 71, 45, 70, 18, 50, 145, 126}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 224}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 205, 5, 83}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 2, 194, 176, 213, 242, 241, 170}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 135, 228, 125, 145, 144, 27, 100, 45, 231, 51}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 145}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 60}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 171, 122, 142, 43, 160, 22, 201, 80}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 208}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 18, 109, 124, 81, 231, 104}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 197, 117, 10}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 166, 185, 85, 112}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 199, 11, 208, 157, 44}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 26, 236, 187, 131}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 196, 239, 31, 203, 108, 85}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 211, 207, 63, 49, 245, 216, 86, 1}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 78, 104, 184}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 5, 244, 149, 119, 72}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 241}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 40, 139, 128, 117, 107, 163}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 55}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 109, 22, 38, 163, 169, 179, 235, 101}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 143}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 202, 110, 28, 2, 194, 40, 17}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 158, 242, 175}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 120, 182, 103, 170}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 159, 105, 192, 77, 241, 168, 17, 125}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 19}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 70, 231, 222, 158, 107, 65, 205, 9}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 60, 241, 247, 139, 58, 217}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 115, 70, 243, 13, 92, 221, 255}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 139}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 160, 165, 178, 235, 128, 250}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 230, 229, 98, 151, 45, 231, 144}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 199}, 65}, {{241, 222, 251, 114, 200, 0, 182, 50, 83, 2, 189, 5, 239, 35, 253, 121}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 127, 55, 170, 72}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 65}, {{241, 222, 251, 114, 200, 0, 163, 80, 166, 219, 207, 207, 101, 2, 44, 96}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 101, 219, 93, 254, 88, 38}, 65}, {{241, 222, 251, 114, 200, 0, 57, 165, 186, 208, 13, 200, 210, 198, 123, 36}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 189, 246, 122, 0, 128}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 51, 6, 196}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 247, 206, 255, 79}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 126, 137, 203, 63}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 49, 124, 55}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 65}, {{241, 222, 251, 114, 200, 0, 165, 157, 138, 113, 190, 142, 186, 180, 22, 114}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 189, 193, 213}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 70, 140, 89, 118, 18, 113, 82, 190}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 225, 44, 106, 12, 99, 19}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 139}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 185}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 27, 119, 38, 109, 143, 143, 91, 103}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 12, 167, 215, 181}, 65}, {{241, 222, 251, 114, 200, 0, 0, 193, 59, 199, 166, 103, 86, 53, 89, 79}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 212, 130, 29, 133, 34, 208, 204, 62}, 65}, {{241, 222, 251, 114, 200, 0, 63, 216, 162, 197, 220, 48, 66, 46, 170, 246}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 11, 223, 22, 74, 227, 171, 171, 69}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 120, 238, 52, 223, 25}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 188, 82, 69, 223}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 79, 154, 82, 119, 7, 18, 165}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 39, 171, 111, 37, 215}, 65}, {{241, 222, 251, 114, 200, 0, 0, 148, 85, 145, 219, 141, 214, 203, 174, 109}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 201, 113, 212, 120, 204, 89, 50}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 137, 54, 251, 96, 57, 42}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 204, 173, 157, 95, 40, 58, 159, 171}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 65}, {{241, 222, 251, 114, 200, 0, 111, 179, 138, 11, 118, 177, 34, 40, 136, 125}, 65}, {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 35, 184, 27}, 65}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 201, 117, 175}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 22, 238, 132}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 202, 31, 95}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 83}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 98, 212, 125}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 70, 246, 99, 226}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 236, 123, 140, 215}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 50, 147}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 95, 127, 49, 230}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 234, 148, 70}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 68, 79, 47}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 76}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 166, 32, 60}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 60}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 15, 116, 169}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 36, 66}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 26, 199}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 176, 86}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 34, 54, 128}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 108, 156}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 120, 58, 5, 192}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 171}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 57, 106}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 93, 104, 65}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 95}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 32}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 45, 55, 95}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 141, 51, 222}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 6}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 180, 206}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 94}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 52, 63}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 7, 120}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 124, 72}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 235, 42, 98, 230}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 183, 186, 106}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 234}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 200, 137}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 154}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 58}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 13}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 139, 36, 42}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 129, 26, 81, 124}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 69, 231}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 153, 212, 51, 211}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 190, 33}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 240, 213}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 137, 52, 93, 26}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 30, 102, 235}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 148, 202, 222, 239}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 251}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 64, 103, 152, 67}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 204, 99, 146}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 96, 125}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 149, 166, 103}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 164, 91}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 197}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 224}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 183}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 247, 236}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 246}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 103, 101, 112, 135}, 108}, {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 56}, 108}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 158, 160, 77, 116, 89, 167}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 142, 198}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 179, 21, 211, 68}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 207, 203}, 244}, {{201, 35, 222, 208, 0, 0, 0, 252, 187, 153, 91, 114, 153, 116, 165, 208}, 244}, {{201, 35, 222, 208, 0, 0, 206, 28, 6, 163, 227, 196, 158, 113, 136, 28}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 206, 130, 227, 207, 250}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 199, 156, 72, 177, 81, 186, 92, 157}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 78, 93}, 244}, {{201, 35, 222, 208, 0, 0, 158, 174, 42, 154, 22, 63, 215, 4, 109, 207}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 85, 181, 87, 233}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 151, 114, 195, 174, 125}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 172, 110, 240, 103, 158, 197}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 113, 68, 12, 10, 133, 208, 154, 44}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 24, 174, 180, 161}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 130, 219, 7, 75, 126}, 244}, {{201, 35, 222, 208, 0, 0, 213, 121, 15, 42, 231, 31, 121, 136, 232, 52}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 220, 28}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 154, 241, 244, 219}, 244}, {{201, 35, 222, 208, 197, 151, 156, 84, 52, 94, 249, 237, 1, 221, 70, 14}, 244}, {{201, 35, 222, 208, 0, 0, 0, 232, 234, 197, 77, 46, 217, 122, 216, 187}, 244}, {{201, 35, 222, 208, 0, 211, 79, 255, 184, 173, 205, 157, 160, 230, 183, 178}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 118, 14, 167, 28, 62, 143, 78, 197}, 244}, {{201, 35, 222, 208, 0, 0, 5, 134, 129, 33, 70, 188, 119, 96, 189, 210}, 244}, {{201, 35, 222, 208, 94, 129, 138, 176, 230, 194, 52, 150, 71, 234, 236, 241}, 244}, {{201, 35, 222, 208, 0, 0, 0, 118, 237, 93, 30, 160, 163, 164, 169, 194}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 60, 25, 87, 241, 16, 50, 39, 181}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 239, 84, 75, 145, 132, 226}, 244}, {{201, 35, 222, 208, 0, 0, 0, 89, 85, 105, 223, 122, 106, 5, 21, 106}, 244}, {{201, 35, 222, 208, 0, 0, 0, 159, 37, 137, 88, 115, 230, 128, 130, 37}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 89, 208, 24, 53, 117, 62}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 155, 97, 173, 83, 163, 144, 244}, 244}, {{201, 35, 222, 208, 0, 171, 176, 224, 196, 184, 127, 163, 79, 42, 67, 228}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 19, 193, 200, 218, 152, 211}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 92, 20, 94, 235, 237}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 60, 38, 191, 14, 147, 188}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 214, 89, 53, 182}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 255, 235, 61, 85, 133, 94, 165}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 16, 203, 129, 251, 192, 159, 69, 155}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 110, 198, 204, 132, 199, 80}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 38, 248, 77, 11, 47}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 206, 79, 55, 53, 155}, 244}, {{201, 35, 222, 208, 0, 0, 0, 64, 232, 224, 218, 78, 167, 64, 202, 164}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 211}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{201, 35, 222, 208, 0, 0, 0, 10, 194, 168, 220, 144, 68, 11, 230, 9}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 5, 62, 108, 222, 130, 216, 62}, 244}, {{201, 35, 222, 208, 201, 254, 72, 27, 196, 118, 61, 60, 203, 94, 204, 224}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 129, 93, 119, 95, 110, 121}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 54, 13, 63, 3, 218, 26, 39, 248}, 244}, {{201, 35, 222, 208, 0, 0, 0, 172, 203, 219, 186, 198, 1, 239, 241, 5}, 244}, {{201, 35, 222, 208, 0, 0, 168, 230, 148, 102, 247, 24, 11, 149, 113, 104}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{201, 35, 222, 208, 0, 197, 161, 186, 185, 231, 11, 64, 246, 47, 171, 96}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 166, 226, 80, 152, 120, 150, 166, 5}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 202, 53, 85, 147, 113, 71}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 40, 143, 26, 69}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 155, 13, 36, 116, 32, 110, 197}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 87, 197, 193, 154}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 42, 159, 240, 61, 232, 18, 253, 125}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 161, 110}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 34, 133, 130, 193}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 21, 41, 165, 23, 48, 199}, 244}, {{201, 35, 222, 208, 0, 251, 176, 69, 37, 105, 153, 197, 97, 21, 132, 94}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 232, 76, 69, 75, 236, 69, 253, 100}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 197, 137, 179, 157, 119, 1, 31}, 244}, {{201, 35, 222, 208, 0, 0, 78, 149, 143, 84, 2, 232, 219, 201, 252, 230}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 221, 81, 15, 62, 176}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 15, 187, 209, 221, 94, 146}, 244}, {{201, 35, 222, 208, 0, 237, 36, 89, 9, 37, 87, 1, 140, 132, 130, 94}, 244}, {{201, 35, 222, 208, 32, 238, 61, 119, 196, 239, 118, 136, 33, 102, 221, 105}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 72, 9, 122, 197}, 244}, {{201, 35, 222, 208, 0, 0, 0, 43, 103, 33, 141, 203, 9, 170, 44, 232}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 23, 113, 99, 127}, 244}, {{201, 35, 222, 208, 0, 99, 17, 246, 39, 248, 176, 208, 137, 97, 57, 47}, 244}, {{201, 35, 222, 208, 0, 224, 100, 229, 7, 191, 111, 200, 95, 215, 116, 165}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 104, 17, 183, 151, 99}, 244}, {{201, 35, 222, 208, 0, 0, 0, 91, 40, 50, 230, 205, 29, 17, 21, 133}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 148, 7, 42, 1, 75}, 244}, {{201, 35, 222, 208, 0, 0, 0, 120, 212, 18, 15, 118, 180, 246, 58, 77}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 210, 245, 106, 185, 155, 119, 123, 46}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 156, 27, 136, 72}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 162, 165}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 245, 69, 160, 55, 24, 196}, 244}, {{201, 35, 222, 208, 0, 0, 25, 82, 66, 7, 143, 68, 130, 100, 145, 117}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 139, 109, 32, 6, 37, 48, 158, 107}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 61, 238, 68, 218, 193, 68, 156}, 244}, {{201, 35, 222, 208, 0, 0, 0, 54, 219, 228, 140, 159, 241, 37, 222, 89}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 7, 118, 2, 234, 59, 196, 223}, 244}, {{201, 35, 222, 208, 0, 0, 203, 54, 167, 12, 148, 209, 187, 123, 90, 159}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 224}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 38, 27, 146, 216}, 244}, {{201, 35, 222, 208, 0, 0, 0, 0, 0, 65, 191, 243, 255, 199, 162, 48}, 244}, {{201, 35, 222, 208, 0, 0, 0, 81, 230, 236, 113, 201, 235, 162, 131, 81}, 244}, {{201, 35, 222, 208, 0, 240, 177, 31, 36, 208, 213, 142, 34, 41, 62, 203}, 244}, {{201, 35, 222, 208, 0, 0, 192, 12, 177, 252, 119, 22, 129, 121, 217, 58}, 244}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 179}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 89, 93, 17, 11}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 158}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 50}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 35}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 219, 155}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 12}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 16}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 254}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 214, 61, 36}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 100, 35}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 131, 248}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 60, 115, 247}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 184}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 186, 230}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 124, 25}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 240}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 25, 19, 68}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 73, 97, 251}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 142, 118}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 140}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 246, 10, 32}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 191, 129, 20}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 209}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 100}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 194, 216}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 121, 199}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 107, 10, 193, 128}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 213, 162}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 31}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 42, 41}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 5, 235, 165}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 56}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 92, 241}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 113, 40}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 40, 60, 101, 99}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 98, 188, 165}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 180, 97}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 78, 209, 114}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 69}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 115, 219}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 217, 26, 3}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 255, 209}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 242}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 125, 247, 233, 72}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 85}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 40}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 8, 230}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 236}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 231}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 36, 229, 69}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 13, 99, 233}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 231, 81, 97}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 46}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 88, 66, 70}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 112}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 13, 221, 185}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 94}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 9, 152, 163}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 25, 198}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 39, 110}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 136, 133, 188}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 74, 16}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 126, 56, 156}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 218, 44}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 153, 236}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 103, 207}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 129, 203}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 10}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 22, 62, 185}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 168, 237}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 175, 138, 151}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 85, 27, 235}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 194}, {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 113}, 194}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 82}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 162}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 240}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 164}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 193}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 190}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 28}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 88}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 60}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 140}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 146}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 235}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 11}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 50}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 178}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 202}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 170}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 238}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 54}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 174}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 233}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 69}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 117}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 101}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 146}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 176}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 102}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 73}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 234}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 101}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 205}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 75}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 187}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 7}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 218}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 169}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 68}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 124}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 45}, {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 79}, 45}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 127, 132, 192}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 212, 97, 164, 142, 223}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 224, 77}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 41, 146, 253, 68}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 142, 100}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 6, 71, 77, 68}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 224, 246, 5, 199}, 224}, {{209, 17, 111, 41, 154, 94, 0, 191, 98, 196, 241, 148, 91, 149, 84, 27}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 148, 162, 44, 39}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 52, 224, 78, 105, 238, 40, 48, 101}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 64, 243, 120}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 63, 246, 65, 250, 171, 34}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 104, 79, 254, 67, 40, 46, 75}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 138, 73, 38, 47, 55, 42, 37, 168}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 68, 116, 178}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 30, 37, 17, 50}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 135, 56, 23, 200}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 253, 4}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 125, 45, 243, 53, 48, 178, 144}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 197, 183, 100, 91, 148, 255, 185}, 224}, {{209, 17, 111, 41, 154, 94, 0, 88, 192, 183, 184, 209, 25, 168, 220, 57}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 208, 99, 172, 50, 139, 203}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 135, 246, 92, 34, 89, 189, 189}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 133, 82, 6}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 20, 238, 20, 245, 72, 162}, 224}, {{209, 17, 111, 41, 154, 94, 0, 221, 165, 98, 253, 201, 75, 132, 127, 45}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 132, 77, 145, 117}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 34, 30, 104, 193, 140, 102}, 224}, {{209, 17, 111, 41, 154, 94, 0, 88, 185, 163, 165, 147, 143, 218, 141, 5}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 88, 70, 59, 230, 201, 104, 43, 12}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 52, 84, 74, 220, 187, 8}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 207, 30, 116, 141, 205}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 102, 120, 55, 185, 96, 148, 250, 80}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 209, 17}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 52, 225, 138, 242, 30}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 21, 35, 241, 99, 145}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 120, 163, 11, 116}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 190, 25, 157, 3, 112, 46, 204, 207}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 14, 254, 10, 252, 89}, 224}, {{209, 17, 111, 41, 154, 94, 0, 114, 71, 22, 207, 41, 147, 115, 118, 210}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 124, 58, 141}, 224}, {{209, 17, 111, 41, 154, 94, 0, 239, 180, 125, 122, 209, 148, 178, 47, 78}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 78, 75, 156}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 185, 60, 54, 92, 194, 113, 40}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 183, 148, 254}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 207, 253, 134, 128, 15, 125}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 58, 184, 74, 107, 160, 169, 3}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 191, 101, 130, 184, 152, 43}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 6, 166, 170, 117}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 235, 196, 253, 165, 136, 76, 139}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 217, 232, 246, 249}, 224}, {{209, 17, 111, 41, 154, 94, 0, 209, 106, 230, 109, 181, 165, 237, 169, 122}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 242, 243, 240, 206}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 126, 213, 180, 202, 34, 196, 192, 6}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 156, 119, 136, 105, 169, 147, 167}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 43, 57, 202, 6, 2, 67, 152, 43, 26}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 197, 210, 228, 8, 217}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 226, 128, 160, 19}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 182, 123, 17, 121, 66}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 92, 10, 139, 1, 143, 235, 50, 94}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 109, 218, 139, 79, 156}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 14, 160}, 224}, {{209, 17, 111, 41, 154, 94, 0, 186, 4, 75, 82, 225, 212, 34, 241, 221}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 178, 18, 8, 183, 183, 117, 186, 225, 141}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 238, 119, 76, 160, 230, 127, 7, 27}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 226, 112, 228, 87}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 116, 196, 96, 235, 143, 45, 250}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 185, 127}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 104, 208, 148, 26}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 36, 72, 26, 16, 150}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 122, 40, 216}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 228, 141, 70, 84, 27, 132, 158, 41}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 207, 12, 136, 254, 100, 220, 77, 38}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 166, 106, 168, 211, 9, 233, 103}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 72, 134, 151, 192, 103, 5, 11, 171}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 61, 147, 31, 234}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 205, 253, 4, 99, 105, 118, 196, 186}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 50, 185, 123, 194, 58}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 72, 161, 143, 255, 4, 21, 149}, 224}, {{209, 17, 111, 41, 154, 94, 0, 95, 252, 194, 252, 214, 86, 19, 235, 14}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 49, 5, 36, 46, 68, 90, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 99, 117, 122, 229, 183}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 221, 151}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 40, 115, 147, 129, 128, 13, 196}, 224}, {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 246, 137}, 224}, {{40, 245, 128, 0, 0, 0, 120, 203, 170, 185, 249, 22, 82, 188, 38, 168}, 17}, {{40, 245, 128, 0, 0, 155, 157, 85, 27, 145, 175, 69, 205, 87, 158, 162}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 96, 136, 221}, 17}, {{40, 245, 128, 193, 184, 166, 187, 99, 127, 167, 172, 81, 240, 135, 234, 95}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 99}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 176, 83}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 79, 150, 151, 203, 239}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 11, 184}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 125, 87}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 172, 239, 87, 233, 224}, 17}, {{40, 245, 128, 0, 0, 0, 47, 2, 53, 109, 64, 19, 202, 12, 142, 13}, 17}, {{40, 245, 128, 230, 32, 42, 85, 203, 241, 253, 167, 74, 138, 45, 182, 111}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 143}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 131, 198}, 17}, {{40, 245, 128, 0, 64, 173, 200, 124, 183, 168, 212, 148, 35, 170, 209, 98}, 17}, {{40, 245, 128, 245, 139, 27, 10, 2, 76, 116, 158, 222, 165, 173, 250, 248}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 60}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 251, 157, 100, 15, 185, 49}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 221, 86, 248, 154, 35, 19, 57}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31, 24, 216, 14, 176}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 39, 99}, 17}, {{40, 245, 128, 0, 0, 0, 0, 23, 20, 216, 5, 102, 17, 194, 174, 166}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 154, 176}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 114, 214, 147, 23, 128, 240, 196}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 48, 0, 240}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 78, 207, 48}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 234}, 17}, {{40, 245, 128, 0, 0, 238, 158, 16, 4, 139, 69, 108, 111, 167, 185, 88}, 17}, {{40, 245, 128, 0, 0, 0, 0, 87, 231, 141, 169, 6, 107, 35, 33, 236}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 214, 221, 253, 58, 45, 53, 8, 113}, 17}, {{40, 245, 128, 0, 0, 3, 126, 223, 1, 151, 187, 251, 179, 211, 169, 154}, 17}, {{40, 245, 128, 0, 112, 179, 56, 23, 40, 100, 173, 233, 25, 181, 95, 146}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 38, 149, 209}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 58, 143, 113, 22, 57, 129, 198}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 23, 177, 83, 170, 90}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 126, 22, 12, 12, 81, 115}, 17}, {{40, 245, 128, 0, 0, 0, 0, 46, 35, 221, 242, 212, 84, 200, 132, 164}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17}, {{40, 245, 128, 0, 156, 22, 184, 39, 9, 3, 222, 171, 78, 195, 245, 0}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 227, 120, 159, 234, 73, 80, 205, 138}, 17}, {{40, 245, 128, 0, 163, 149, 34, 16, 254, 75, 130, 119, 158, 93, 132, 242}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 240, 173, 92}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 228, 168, 181, 210, 198, 158, 93, 106}, 17}, {{40, 245, 128, 0, 0, 0, 0, 70, 167, 237, 175, 13, 139, 15, 233, 204}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 96, 81, 19, 233, 235, 157}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 250, 88}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 189, 97, 178, 197, 58, 49, 249}, 17}, {{40, 245, 128, 0, 99, 148, 128, 34, 184, 2, 113, 203, 32, 164, 138, 180}, 17}, {{40, 245, 128, 0, 0, 0, 0, 238, 66, 73, 9, 159, 84, 7, 191, 59}, 17}, {{40, 245, 128, 0, 125, 185, 172, 234, 23, 72, 82, 2, 42, 137, 3, 58}, 17}, {{40, 245, 128, 0, 0, 0, 0, 252, 80, 123, 211, 184, 54, 195, 246, 145}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 234, 202, 69, 191, 64, 154, 66, 151}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 17}, {{40, 245, 128, 0, 0, 0, 0, 156, 129, 2, 10, 0, 143, 220, 247, 116}, 17}, {{40, 245, 128, 0, 0, 36, 130, 180, 209, 27, 224, 114, 229, 149, 203, 24}, 17}, {{40, 245, 128, 0, 0, 133, 8, 216, 84, 247, 193, 213, 37, 197, 60, 247}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 194, 22, 180, 33, 15, 80}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 20, 165, 101, 125, 157}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 155, 224, 33}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 50}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 182, 111, 246, 177, 64}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 174, 197, 130, 220, 133, 123, 255}, 17}, {{40, 245, 128, 0, 0, 207, 79, 212, 118, 196, 204, 48, 112, 115, 59, 245}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 252, 199, 115, 111, 216, 213, 65, 73}, 17}, {{40, 245, 128, 0, 0, 0, 0, 89, 234, 254, 133, 136, 200, 115, 139, 179}, 17}, {{40, 245, 128, 0, 0, 0, 0, 243, 167, 5, 137, 202, 250, 189, 31, 31}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 216, 31}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 152, 174, 10}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 69, 252, 42, 249, 181}, 17}, {{40, 245, 128, 0, 204, 57, 58, 106, 147, 167, 55, 141, 188, 143, 73, 64}, 17}, {{40, 245, 128, 0, 0, 0, 230, 22, 142, 113, 111, 178, 96, 84, 245, 203}, 17}, {{40, 245, 128, 0, 0, 0, 0, 168, 17, 101, 12, 84, 44, 198, 39, 75}, 17}, {{40, 245, 128, 0, 255, 111, 23, 24, 74, 107, 87, 84, 59, 22, 144, 201}, 17}, {{40, 245, 128, 0, 0, 67, 195, 39, 135, 189, 27, 134, 184, 168, 108, 206}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 120}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 136, 45, 233, 173, 72}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 218, 155, 188, 148, 21, 103}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 133, 76, 131, 84, 75, 223}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 220, 80}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 67, 67, 212, 77, 64, 114}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 157}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 65, 254, 53}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 86, 163, 83, 65, 85, 37}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 157, 31, 183, 121, 228}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 70, 167, 75, 248, 168, 47}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 240, 26, 228, 161, 36, 250}, 17}, {{40, 245, 128, 0, 135, 227, 39, 58, 223, 135, 86, 249, 72, 120, 80, 146}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 44, 215, 170, 217, 145}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 122, 125, 116, 177, 164, 184, 208}, 17}, {{40, 245, 128, 0, 222, 29, 191, 179, 59, 195, 214, 101, 82, 36, 232, 69}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 106, 231, 127}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17}, {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 17}, {{40, 245, 128, 0, 0, 0, 0, 183, 166, 106, 45, 172, 109, 157, 135, 18}, 17}, {{40, 245, 128, 0, 0, 134, 65, 241, 113, 138, 98, 219, 242, 198, 182, 6}, 17}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 118, 33, 187, 68, 196, 231}, 133}, {{72, 121, 151, 83, 170, 80, 0, 158, 55, 239, 22, 111, 34, 32, 243, 77}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 131, 225, 192, 80, 85}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 194, 157, 2, 232, 167, 242, 46, 59}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 95, 172, 229, 112}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 68, 100, 103, 65, 100, 113, 17, 232}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 144, 251, 222, 142, 77}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 211, 41}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 129, 204, 64, 205, 143, 146, 13}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 66, 53, 210, 88, 152, 4, 66}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 252, 121, 52, 50, 160, 41, 55}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 103, 56, 138, 145, 202, 104, 179}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 26, 39, 49, 25}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 149, 0, 159, 87, 229, 248, 217}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 227, 63, 236}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 148, 31, 0, 163, 194, 253, 89}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 217, 227, 120, 176, 52}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 227, 233, 45, 186, 109}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 145, 161, 191, 220, 5, 223}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 170, 189, 47, 206}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 133}, {{72, 121, 151, 83, 170, 80, 0, 221, 107, 195, 202, 82, 51, 86, 123, 185}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 174, 71, 243, 13}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 1, 127, 185, 10}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 171, 72, 128, 34, 211}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 193, 208, 49, 37, 251}, 133}, {{72, 121, 151, 83, 170, 80, 252, 250, 194, 131, 123, 228, 213, 164, 130, 255}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 111, 230, 121, 150, 228, 41}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 133}, {{72, 121, 151, 83, 170, 80, 0, 65, 186, 48, 82, 101, 193, 35, 44, 11}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 11, 124, 237, 4}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 211, 198}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 50, 78, 165, 173}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 146, 81}, 133}, {{72, 121, 151, 83, 170, 80, 0, 44, 144, 122, 50, 1, 93, 235, 90, 29}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 248, 165, 131, 111, 160}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 4, 180, 234, 174, 195, 63}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 156, 181, 166, 240, 148, 173, 227}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 133}, {{72, 121, 151, 83, 170, 80, 0, 235, 159, 211, 86, 27, 51, 224, 111, 71}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 142, 215}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 58, 171, 68, 16, 60, 163, 183, 125}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 229, 99, 160, 127, 201}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 180, 47, 68}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 194, 66, 6}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 45, 197, 147, 31, 13, 60, 121, 209}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 60, 249, 55, 24, 166, 209}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 219, 86, 3, 188, 1}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 121, 107, 37, 126, 49, 9, 82, 85}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 36, 51, 236, 177, 151, 105, 65}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 47, 76, 87, 42}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 70, 164, 231, 94, 119, 64}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 174, 11, 129}, 133}, {{72, 121, 151, 83, 170, 80, 122, 189, 190, 25, 196, 230, 29, 34, 128, 142}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 87, 47, 53, 174, 211, 137}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 125, 82, 59, 17, 197, 209}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 62, 235, 133, 15}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 46, 83, 50}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 222, 222, 73, 141, 8, 207, 43, 77}, 133}, {{72, 121, 151, 83, 170, 80, 92, 181, 148, 174, 162, 2, 249, 186, 5, 94}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 124, 197, 14}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 11, 189}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 233, 89, 202, 77}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 208, 220, 146}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 244, 90}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 228, 90, 160, 155, 192}, 133}, {{72, 121, 151, 83, 170, 80, 0, 77, 29, 249, 234, 79, 70, 201, 85, 86}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 63, 16, 38, 245, 185, 109, 172, 70}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 59, 86, 47, 188, 114}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 50, 24, 95, 115, 117, 237}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 206, 239}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 60, 52, 233, 236, 245, 112, 188, 152}, 133}, {{72, 121, 151, 83, 170, 80, 0, 49, 98, 5, 108, 245, 164, 144, 179, 217}, 133}, {{72, 121, 151, 83, 170, 80, 0, 174, 166, 105, 242, 23, 199, 89, 214, 116}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 208, 210, 199, 119, 141}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 139, 115, 160, 217, 97}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 188, 221, 11, 251}, 133}, {{72, 121, 151, 83, 170, 80, 147, 29, 149, 9, 124, 172, 0, 216, 138, 184}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 116, 216, 207, 239, 35, 170, 90, 66, 15}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 247, 228, 201, 135, 136, 96, 221, 153}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 207, 193}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 138, 131, 254, 194, 47}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 206, 191, 153}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 133}, {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 133}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 29, 88}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 177, 215}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 117}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 62, 224, 214, 21}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 97, 116}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 234, 223, 165}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 57, 23, 85}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 210}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 67, 102, 125}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 206}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 151, 214, 121, 171}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 150, 211}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 49, 144, 188}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 194, 17, 56}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 32, 78}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 46, 119, 158}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 126, 39, 21, 105, 149}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 60, 178}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 157, 76}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 14, 250}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 240, 117, 113}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 85, 228, 171, 247}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 161, 161, 114}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 64}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 91, 159}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 47, 227, 72, 108}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 180, 15, 32}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 69, 220, 65, 104, 239}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 35}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 166, 89, 94, 169}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 74, 3}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 86, 229}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 125, 15, 17, 251, 35}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 3, 36, 34}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 163, 15}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 128, 76}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 162, 245, 255}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 241}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 218, 177, 157, 172}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 136, 50}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 214, 86, 88, 179}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 82, 38, 65, 199}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 150, 197, 214}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 87, 0, 113, 222, 61}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 84, 194, 192}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 168}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 221, 104}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 245, 99}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 188}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 203, 200, 72}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 39, 113}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 194, 14, 165, 13}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 15, 167, 173}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 111, 230, 24, 54}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 153}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 37}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 14, 26}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 242}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 251, 170, 37}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 215, 132, 26}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 55, 6, 181}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 192}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 34, 130, 14}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 221, 207}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 50, 21, 197}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 56, 86}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 18, 148, 132, 255}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 218, 54, 91}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 188, 142, 43, 181}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 200}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 219, 226, 99}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 246, 74}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 182, 189, 173}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 208}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 248, 135, 21}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 10, 208, 168}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 241, 46, 226, 1}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 6, 137, 249, 97, 141}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 98, 166, 199, 62}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 151, 105, 19}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 203, 113, 62}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 116, 97}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 217, 64}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 87, 18, 35, 217}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 60, 240, 31, 39, 190}, 125}, {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 53, 86, 167}, 125}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 61}, {{0, 0, 0, 0, 0, 48, 154, 134, 55, 146, 130, 190, 155, 183, 237, 164}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 62, 9}, 61}, {{0, 0, 0, 73, 77, 75, 5, 129, 84, 193, 84, 160, 235, 78, 164, 162}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 184, 144, 219, 168}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 144, 74, 54, 55, 5, 29, 25, 59}, 61}, {{0, 199, 138, 82, 74, 114, 232, 31, 64, 133, 32, 37, 39, 18, 102, 6}, 61}, {{0, 0, 0, 0, 0, 86, 27, 61, 87, 103, 219, 109, 167, 51, 17, 5}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 226, 46, 117}, 61}, {{0, 0, 231, 189, 147, 181, 212, 63, 109, 32, 145, 236, 10, 100, 211, 165}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 172, 139, 42}, 61}, {{0, 0, 0, 138, 52, 252, 105, 185, 209, 201, 54, 230, 252, 20, 241, 129}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 237, 118, 241, 36, 244}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 1, 21}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 117, 149}, 61}, {{0, 0, 121, 168, 34, 152, 120, 84, 186, 115, 234, 76, 166, 254, 254, 227}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 157, 160, 97, 50}, 61}, {{0, 0, 0, 0, 0, 0, 0, 235, 222, 91, 32, 241, 7, 166, 40, 103}, 61}, {{0, 91, 167, 227, 26, 140, 35, 131, 161, 187, 63, 232, 129, 237, 123, 120}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 183, 149, 93, 189, 168}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 227, 24, 222, 111, 160, 220, 17, 70, 108, 70, 125, 57}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 179, 1, 220, 85, 50, 172}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 61}, {{0, 0, 0, 0, 0, 0, 182, 145, 112, 177, 207, 254, 103, 126, 11, 142}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 125, 160, 191, 239}, 61}, {{0, 0, 0, 0, 248, 31, 119, 75, 31, 28, 26, 143, 44, 235, 46, 204}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 12, 119}, 61}, {{0, 0, 0, 0, 0, 204, 82, 87, 26, 215, 203, 177, 97, 10, 206, 220}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 50, 148, 15, 29, 12}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 67, 163, 239, 55, 215, 61, 160, 202}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 119, 231, 70, 143, 35, 99}, 61}, {{0, 0, 0, 0, 0, 231, 226, 127, 133, 143, 132, 163, 80, 216, 86, 186}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 145, 44, 103, 179}, 61}, {{0, 0, 0, 0, 0, 0, 50, 53, 111, 97, 80, 226, 208, 95, 30, 125}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 187, 45, 35, 22, 85, 96, 84, 97, 57, 174}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 87}, 61}, {{0, 0, 0, 0, 0, 0, 158, 47, 156, 188, 154, 52, 103, 69, 145, 109}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 58, 148, 213}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 183, 35, 123, 76, 127, 247}, 61}, {{0, 0, 0, 0, 94, 82, 80, 227, 8, 192, 116, 186, 37, 76, 133, 61}, 61}, {{0, 84, 216, 126, 35, 115, 249, 32, 172, 98, 5, 41, 151, 2, 235, 203}, 61}, {{0, 0, 0, 234, 196, 80, 154, 98, 234, 236, 13, 169, 221, 166, 87, 220}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 61}, {{0, 0, 182, 53, 4, 220, 24, 247, 10, 215, 31, 161, 55, 193, 180, 122}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 44, 126}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 175, 79, 61}, 61}, {{0, 0, 125, 53, 196, 196, 228, 238, 147, 199, 233, 208, 73, 86, 169, 38}, 61}, {{0, 0, 0, 0, 0, 0, 120, 141, 0, 189, 195, 56, 229, 191, 17, 74}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 205, 214, 43, 213, 65, 255}, 61}, {{0, 0, 0, 0, 41, 118, 129, 94, 87, 119, 72, 221, 57, 135, 237, 78}, 61}, {{0, 0, 0, 93, 109, 66, 156, 41, 181, 158, 140, 144, 95, 131, 20, 229}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 166, 17, 253, 92, 46}, 61}, {{0, 0, 0, 0, 0, 0, 188, 175, 114, 27, 15, 16, 105, 176, 192, 115}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 80}, 61}, {{0, 0, 0, 0, 0, 222, 228, 49, 109, 74, 244, 71, 90, 121, 239, 252}, 61}, {{0, 0, 0, 0, 0, 0, 0, 179, 251, 183, 53, 79, 66, 46, 72, 197}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 61}, {{0, 98, 240, 85, 137, 191, 159, 80, 171, 180, 213, 51, 55, 223, 8, 161}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 124}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 162, 84, 184}, 61}, {{0, 0, 0, 0, 0, 32, 217, 158, 238, 183, 172, 130, 83, 219, 137, 211}, 61}, {{0, 0, 0, 0, 0, 0, 0, 17, 192, 84, 213, 92, 22, 207, 215, 61}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 136, 76}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 41, 81, 224, 250, 132, 181}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 222, 252, 30, 233, 206, 75, 142, 211, 133, 98, 125, 227, 178, 203}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 119, 121, 213, 153, 154, 72, 76, 245}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 250}, 61}, {{0, 0, 0, 0, 230, 115, 165, 62, 82, 65, 212, 53, 226, 199, 58, 145}, 61}, {{0, 0, 0, 0, 101, 62, 83, 116, 84, 215, 178, 163, 173, 115, 142, 16}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 178, 111, 124, 21, 29, 46}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 76}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 230}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 150}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 87, 195, 163, 34, 4, 91, 51, 121, 140}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 70}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 67, 158, 234, 52, 241}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 227}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 51}, 61}, {{0, 0, 0, 0, 0, 150, 249, 165, 241, 236, 2, 157, 16, 152, 84, 234}, 61}, {{0, 0, 0, 107, 154, 126, 82, 104, 113, 186, 3, 32, 37, 155, 50, 148}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 208}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 155}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 229, 180}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 206, 71}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 145, 146, 225}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 191, 143}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 216, 130, 222}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 93, 136, 144}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 41}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 211}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 164, 55}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 206}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 195, 166}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 238}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 192, 42}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 143, 175}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 216}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 71, 183}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 34}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 194, 254}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 115, 5, 35}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 170, 243}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 157, 62}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 70, 219}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 205, 220, 230}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 245}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 58, 23, 166}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 38, 166, 64}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 39, 68}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 255}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 82, 60, 17}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 48, 59}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 58, 219}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 80, 152}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 219, 17, 34}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 169}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 251}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 149, 48, 187}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 185, 152}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 150}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 75, 5}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 164, 16, 90}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 201, 84, 47}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 44, 76, 138}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 131, 159}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 147, 148, 150}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 51, 63}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 143, 16}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 104}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 105, 97, 108}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 90, 159, 240}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 209, 57}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 109}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 3, 81, 84}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 143, 125, 141}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 214}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 179, 66, 180}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 161}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 65, 93}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 89, 145}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 202}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 167, 191}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 61}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 25}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 73, 139}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 251, 189, 70}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 40, 13}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 30, 255}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 1, 72}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 29, 198}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 104, 143, 208}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 151, 14, 94}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 245}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 208, 35, 231}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 184, 197}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 220}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 243}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 179}, 140}, {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 214, 68, 61}, 140}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 19, 179, 4, 36}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 58, 162, 243, 108, 134, 31, 54, 169}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 30, 202, 26, 224}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 229, 9, 54, 88}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 49, 212, 129, 246, 26, 178}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 45, 56, 100, 13, 99, 134, 135}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 232, 183}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 157, 46, 146, 61}, 91}, {{243, 122, 30, 80, 0, 0, 0, 218, 179, 74, 226, 43, 196, 226, 183, 11}, 91}, {{243, 122, 30, 80, 146, 158, 175, 239, 119, 5, 131, 191, 64, 167, 217, 195}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 120, 42, 220, 253}, 91}, {{243, 122, 30, 80, 105, 199, 180, 14, 40, 137, 115, 152, 21, 93, 221, 5}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 141, 1, 208, 203, 0, 149}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 58, 130, 151, 171, 19, 155}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 167, 189}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 239, 67}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 127, 203, 19, 165, 71, 55}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 139, 194, 94, 169, 54}, 91}, {{243, 122, 30, 80, 0, 193, 148, 164, 130, 178, 63, 86, 34, 195, 25, 193}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 19, 27, 179, 40, 140}, 91}, {{243, 122, 30, 80, 105, 21, 109, 70, 243, 235, 248, 78, 89, 219, 229, 25}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 76, 89, 163, 220, 129, 208, 164, 33}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 172, 97, 141, 191, 86, 251}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 17}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 196, 79, 107, 143, 130, 40}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 247, 67, 203, 67}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 128, 111, 216, 46, 82, 31}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 202, 245, 30, 152, 211, 138, 226, 22, 250, 58, 95}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 221, 45, 90, 135}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 96, 72, 70, 220, 12, 44, 11, 155}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 224, 180, 181, 130}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 65, 206, 80, 148, 75, 136, 217, 83}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 130, 187, 203, 218, 29, 4}, 91}, {{243, 122, 30, 80, 0, 0, 50, 186, 247, 214, 24, 240, 25, 152, 204, 50}, 91}, {{243, 122, 30, 80, 69, 90, 240, 97, 63, 231, 241, 156, 19, 59, 202, 251}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 75, 47, 246, 77, 69, 67}, 91}, {{243, 122, 30, 80, 0, 0, 0, 96, 121, 24, 154, 40, 46, 60, 27, 107}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 140, 71, 9, 63, 231, 25}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 113, 233, 159, 17, 52}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 195, 105, 204, 67, 118, 19, 125}, 91}, {{243, 122, 30, 80, 0, 128, 189, 84, 186, 147, 177, 47, 122, 46, 197, 33}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 49, 180, 11, 244, 80, 199, 9}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 229, 200, 95, 245, 163, 245, 247, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 180, 151, 177, 116, 193, 219, 60, 63}, 91}, {{243, 122, 30, 80, 96, 181, 251, 70, 112, 120, 231, 4, 190, 92, 242, 185}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 104, 118, 146, 238, 64, 161, 142, 55}, 91}, {{243, 122, 30, 80, 0, 0, 81, 128, 110, 235, 220, 236, 67, 149, 216, 46}, 91}, {{243, 122, 30, 80, 0, 2, 47, 153, 27, 13, 101, 221, 137, 54, 102, 18}, 91}, {{243, 122, 30, 80, 0, 146, 94, 86, 74, 122, 135, 204, 74, 231, 40, 178}, 91}, {{243, 122, 30, 80, 90, 226, 149, 156, 229, 240, 106, 237, 117, 35, 77, 190}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 187, 117, 9, 188}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 91, 73, 236, 26, 237, 9, 74, 240}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 1, 200, 99, 60, 168}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 128, 38, 95, 59}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 30, 218, 69, 217}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 43, 215, 179, 215, 101}, 91}, {{243, 122, 30, 80, 171, 19, 227, 170, 208, 107, 254, 159, 89, 146, 19, 9}, 91}, {{243, 122, 30, 80, 0, 0, 192, 230, 41, 163, 120, 22, 105, 52, 198, 15}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 110, 10}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 45, 213, 15, 126, 187}, 91}, {{243, 122, 30, 80, 0, 0, 0, 127, 72, 128, 205, 194, 201, 216, 68, 88}, 91}, {{243, 122, 30, 80, 0, 0, 0, 181, 205, 215, 154, 184, 236, 9, 115, 243}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 124, 31, 89, 226, 238}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 149, 23, 165, 65, 157, 1, 184, 140}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 77, 48, 175, 199, 51, 234}, 91}, {{243, 122, 30, 80, 0, 0, 0, 12, 167, 15, 52, 36, 180, 41, 229, 14}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 30, 60}, 91}, {{243, 122, 30, 80, 0, 52, 48, 233, 129, 157, 119, 31, 189, 34, 130, 33}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 16, 187, 55, 63, 149}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 125, 129, 80, 198, 73, 20, 69, 75, 94, 217}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 52, 29, 69, 210, 140, 101, 112, 250}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 91}, {{243, 122, 30, 80, 0, 196, 54, 165, 15, 125, 64, 126, 199, 211, 148, 193}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 245, 46, 241, 209, 32, 11, 47, 127, 7, 148, 32}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 224, 206, 140, 184, 230}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 107, 123, 166, 57, 100}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 98, 66, 108, 130, 124, 234, 153}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 146, 101}, 91}, {{243, 122, 30, 80, 0, 0, 67, 100, 130, 27, 249, 182, 203, 244, 179, 74}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 91}, {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 85}, 91}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 241, 196}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 238, 240, 81}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 92, 239, 33, 59}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 52, 178, 125, 143, 34, 232, 250, 82}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 169, 107, 69, 83, 198, 59}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 90, 62, 91, 86, 10, 0, 29}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 66, 157, 215}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 47, 184, 251, 33, 209, 64, 32, 98}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 4, 252, 19}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 73, 161, 32, 165}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 167, 51, 126, 156, 42, 131, 102}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 235, 218}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 203, 85, 35, 142, 171, 61}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 92}, {{89, 250, 80, 72, 148, 4, 0, 38, 98, 206, 76, 60, 42, 42, 177, 25}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 216, 93}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 54, 191, 208, 160, 62, 96}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 92}, {{89, 250, 80, 72, 148, 4, 0, 6, 211, 14, 101, 35, 91, 7, 217, 218}, 92}, {{89, 250, 80, 72, 148, 4, 0, 189, 86, 168, 53, 131, 109, 56, 59, 222}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 244, 55}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 103, 204, 40, 226, 99, 246}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 178, 166, 210, 71, 214}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 251, 53, 228, 231}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 138, 176, 2, 45}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 105, 55, 142, 107, 156, 6}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 112, 45, 77}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 162, 223, 111, 36, 103, 188}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 17, 121, 29, 96, 18, 205}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 91, 77}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 79, 192, 26, 139, 58}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 214, 17}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 139, 201, 75, 183, 230, 214}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 239, 120}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 91, 238, 176, 122, 158, 175, 104}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 82, 168, 71}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 95, 223, 236, 22}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 33, 106}, 92}, {{89, 250, 80, 72, 148, 4, 0, 212, 179, 119, 10, 205, 56, 126, 176, 40}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 217, 217, 5, 246, 40, 160, 162, 16}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 132, 197}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 38, 79, 221, 248, 159, 172}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 26, 190, 121}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 186, 130, 183}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 27, 65, 210, 230}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 170, 157, 156, 43, 243, 144, 100, 248}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 218, 157, 123, 212, 29, 143, 151, 207}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 231, 84, 46}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 161, 218, 48, 218, 178, 81, 134, 45}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 122, 55, 148, 47, 204}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 140, 223, 73, 208}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 23, 137, 14, 183, 162, 131}, 92}, {{89, 250, 80, 72, 148, 4, 0, 138, 129, 49, 32, 246, 91, 90, 255, 5}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 49, 94, 208, 239}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 71, 103}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 238, 152}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 31, 77, 110}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 216, 2}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 2, 247, 173, 235, 67, 137, 21, 89}, 92}, {{89, 250, 80, 72, 148, 4, 0, 210, 18, 253, 165, 103, 67, 35, 150, 99}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 30, 15, 19, 16, 87, 199}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 87, 142, 161, 201, 162, 47, 239}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 243, 53, 54, 211}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 93, 219, 56, 22, 189, 201, 71}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 44, 80}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 49, 253, 177, 131, 204, 49, 148}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 245, 219, 26, 122, 66, 79, 13, 238}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 207, 241, 59}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 78, 239, 237, 99, 181, 159, 187}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 25, 21, 85, 47}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 57, 233, 168, 56, 198, 224, 113, 17}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 104, 254}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 75, 180, 152}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 196, 205, 107, 196}, 92}, {{89, 250, 80, 72, 148, 4, 0, 45, 81, 144, 231, 213, 188, 142, 168, 163}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 135, 55, 19}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 126, 110, 73}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 54, 220, 123, 98, 177, 76}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 154, 33, 20, 240, 116, 229, 152, 162}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 131, 29}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 20, 242, 183, 15, 160, 16}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 132, 8, 219}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 250, 108, 31, 124, 191, 192}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 105, 158, 145}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 238, 153, 134, 101, 151, 17, 157}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 226, 60, 127, 36}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 48, 23, 111, 119, 164, 183, 33}, 92}, {{89, 250, 80, 72, 148, 4, 0, 0, 0, 41, 243, 168, 19, 150, 192, 79}, 92}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 164, 244, 97, 174, 55, 48}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 189}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 148, 97, 148, 156, 194, 156}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 39, 42, 161}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 249, 193, 126, 102}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 119, 84, 85}, 125}, {{187, 152, 0, 0, 0, 0, 253, 110, 52, 161, 46, 161, 61, 209, 245, 186}, 125}, {{187, 152, 0, 0, 0, 0, 0, 153, 119, 191, 31, 130, 171, 5, 215, 149}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 64, 153, 18, 8, 138, 225, 243, 18, 215, 198, 6, 23}, 125}, {{187, 152, 0, 0, 167, 248, 132, 117, 26, 146, 162, 24, 185, 72, 172, 216}, 125}, {{187, 152, 0, 0, 0, 0, 0, 14, 174, 87, 176, 140, 109, 210, 140, 218}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 33, 15, 254}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 239, 172, 250, 165, 255, 132}, 125}, {{187, 152, 0, 0, 0, 137, 220, 8, 79, 157, 209, 148, 85, 144, 10, 41}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 128, 62, 183, 135}, 125}, {{187, 152, 0, 0, 0, 28, 106, 58, 53, 8, 80, 227, 188, 166, 12, 31}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 170, 54}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 84, 140, 73, 243, 181, 181, 180, 119}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 140, 178, 119, 123}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 12, 70, 178, 68}, 125}, {{187, 152, 0, 0, 0, 0, 53, 42, 127, 64, 200, 89, 254, 39, 10, 237}, 125}, {{187, 152, 0, 0, 0, 74, 175, 19, 183, 170, 59, 225, 60, 156, 202, 65}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 107, 68, 10, 62, 124, 161, 255}, 125}, {{187, 152, 0, 0, 0, 240, 167, 57, 172, 180, 8, 88, 251, 11, 29, 14}, 125}, {{187, 152, 0, 0, 211, 62, 209, 131, 61, 21, 35, 27, 169, 7, 81, 235}, 125}, {{187, 152, 0, 0, 0, 0, 0, 180, 220, 13, 233, 135, 194, 250, 208, 122}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 62, 192, 189}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 198}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 243, 155, 225}, 125}, {{187, 152, 0, 0, 0, 0, 160, 160, 141, 137, 37, 92, 233, 93, 17, 24}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 113, 236, 105, 39, 175, 175, 163, 176}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 227, 239}, 125}, {{187, 152, 0, 0, 0, 0, 0, 210, 160, 48, 125, 61, 235, 131, 121, 68}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 65, 179}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 240, 135, 238, 103, 89, 41, 75, 226}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 125}, {{187, 152, 0, 0, 106, 157, 158, 184, 8, 89, 111, 38, 83, 63, 155, 3}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 75, 1, 101, 224, 138, 121, 110, 142}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 125}, {{187, 152, 0, 140, 65, 12, 179, 197, 130, 233, 212, 176, 103, 208, 127, 172}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 125, 181}, 125}, {{187, 152, 0, 0, 0, 0, 0, 140, 72, 77, 255, 177, 80, 51, 23, 56}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 231, 31, 210, 44}, 125}, {{187, 152, 0, 0, 0, 0, 0, 244, 157, 163, 187, 190, 234, 247, 56, 120}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 59, 236, 23, 249, 93, 16, 229, 13}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 80, 194}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 79, 73, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 76, 8, 168}, 125}, {{187, 152, 158, 1, 199, 220, 56, 166, 217, 136, 45, 125, 233, 27, 171, 41}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 112, 40, 37, 172, 136, 168, 107, 59}, 125}, {{187, 152, 0, 0, 0, 162, 140, 7, 61, 95, 77, 216, 140, 99, 0, 93}, 125}, {{187, 152, 0, 168, 130, 89, 66, 94, 14, 74, 232, 114, 7, 85, 38, 31}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 209}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 65, 227, 39, 246, 13, 169, 232}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 125}, {{187, 152, 0, 0, 0, 195, 253, 93, 200, 89, 185, 57, 222, 134, 215, 195}, 125}, {{187, 152, 0, 0, 163, 15, 230, 18, 40, 158, 143, 0, 173, 233, 251, 122}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 174, 90}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 18, 39, 244, 107, 211, 20, 16, 198}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 199, 147, 54, 242}, 125}, {{187, 152, 0, 0, 0, 0, 109, 211, 152, 183, 221, 18, 230, 4, 123, 10}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 34, 240, 86, 45}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 224, 23, 218}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 80, 208, 51, 187}, 125}, {{187, 152, 0, 0, 0, 0, 0, 2, 42, 208, 129, 31, 209, 218, 201, 17}, 125}, {{187, 152, 0, 0, 246, 5, 180, 161, 205, 50, 204, 85, 197, 223, 164, 179}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 199, 18, 29, 1}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 242, 57, 24, 110, 26, 74}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 253}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 131, 173}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 70, 80, 96, 113}, 125}, {{187, 152, 0, 0, 0, 0, 171, 125, 167, 26, 175, 47, 205, 122, 163, 187}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 125}, {{187, 152, 0, 154, 246, 182, 227, 98, 161, 78, 69, 189, 231, 41, 57, 29}, 125}, {{187, 152, 0, 198, 52, 37, 67, 154, 90, 68, 36, 155, 59, 66, 35, 25}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 60, 152, 76, 251}, 125}, {{187, 152, 0, 246, 227, 3, 27, 203, 93, 223, 130, 141, 203, 45, 45, 135}, 125}, {{187, 152, 0, 0, 158, 7, 0, 48, 222, 94, 118, 219, 207, 203, 21, 75}, 125}, {{187, 152, 162, 85, 68, 113, 126, 172, 61, 232, 119, 162, 76, 27, 154, 42}, 125}, {{187, 152, 0, 0, 0, 0, 0, 76, 103, 7, 61, 156, 142, 77, 61, 67}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 91, 126, 220, 177, 5, 61}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 224}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 183, 54, 22, 1, 91, 88, 101, 46}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 197, 56, 206, 62, 142, 209, 139, 121}, 125}, {{187, 152, 0, 0, 0, 0, 0, 183, 143, 94, 160, 94, 181, 183, 156, 173}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 195, 189, 234, 33, 100, 23, 194, 50}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 18}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 53, 157, 68, 44, 83, 188, 54, 3}, 125}, {{187, 152, 0, 0, 0, 0, 0, 0, 0, 43, 121, 214, 104, 229, 157, 210}, 125}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 231}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 112}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 86}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 146, 46}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 61}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 175}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 196}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 98, 13}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 212}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 17}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 147, 252}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 254, 223}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 191}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 241, 21}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 210, 145}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 194, 170}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 194}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 22}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 178, 32}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 107, 158}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 206}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 182}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 31}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 115}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 45, 83}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 254}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 184, 118}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 93, 184}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 118, 242}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 12}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 73}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 84}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 57, 57}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 77, 231}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 123}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 57}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 9, 41}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 77}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 63}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 161}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 253}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 5}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 21}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 52, 160}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 59, 37}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 7}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 80, 220}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 67, 22}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 145}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 97}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 183, 30}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 116, 238}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 85}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 249, 101}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 82, 68}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 151}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 134}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 119}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 115}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 244, 12}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 70}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 45, 96}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 217}, 249}, {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 249}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 202, 190, 22, 39, 168, 105}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 191, 240, 45, 188}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 12, 51, 103}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 238, 160, 53, 49, 0, 120, 17}, 202}, {{254, 202, 113, 112, 173, 0, 0, 118, 45, 130, 85, 116, 93, 241, 99, 163}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 248, 111, 211, 81, 125, 62}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 111, 240, 139}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 154, 45, 231, 171, 217}, 202}, {{254, 202, 113, 112, 173, 0, 0, 65, 75, 195, 215, 213, 132, 199, 237, 130}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 24, 47, 55, 126, 166}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 3, 87, 234}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 152, 114, 40, 210, 191}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 51, 207, 13, 3, 103, 90}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 81, 238, 66, 100, 118, 171}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 254}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 90, 92, 87, 27, 101, 225, 245}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 166, 158, 223, 254}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 52, 255, 120, 192, 203}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 155, 94, 229, 118, 201, 188, 50, 235}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 217}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 66, 84, 241, 107, 53, 214, 241, 152}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 27, 147, 21, 113, 202, 210, 101, 156}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 162}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 156, 105, 43, 167, 147, 129}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 67}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 205, 8, 112, 242, 20, 27, 43}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 232, 194, 8, 222}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 171, 196, 53, 50, 108, 108}, 202}, {{254, 202, 113, 112, 173, 0, 0, 65, 196, 177, 97, 123, 231, 216, 186, 232}, 202}, {{254, 202, 113, 112, 173, 0, 99, 113, 107, 218, 146, 79, 141, 29, 47, 85}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 141, 240, 71}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 180, 190, 35, 93, 185, 158, 193, 163}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 38, 69, 146}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 146, 253, 134, 69, 53, 106}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 241, 87, 238, 186, 208}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 202}, {{254, 202, 113, 112, 173, 0, 246, 18, 146, 238, 30, 192, 132, 233, 222, 56}, 202}, {{254, 202, 113, 112, 173, 0, 190, 11, 96, 2, 182, 40, 56, 188, 76, 208}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 41, 84, 139, 123, 31, 72, 140, 8}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 207, 145, 35, 141, 152, 165, 137, 96}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 112, 223, 105}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 29, 165, 207, 56, 255, 4, 187}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 159, 60, 88, 239, 28, 113, 84}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 182, 31, 111}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 191}, 202}, {{254, 202, 113, 112, 173, 0, 233, 225, 129, 79, 136, 47, 43, 84, 32, 197}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 164, 47, 246, 33, 40, 43, 254}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 189}, 202}, {{254, 202, 113, 112, 173, 0, 61, 117, 122, 233, 21, 167, 203, 223, 30, 167}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 85}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 71, 91, 114, 134, 118, 213, 52}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 100, 173, 224, 192}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 15, 211, 219}, 202}, {{254, 202, 113, 112, 173, 0, 0, 12, 202, 247, 111, 251, 69, 47, 56, 132}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 251}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 53}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 36, 114, 49, 59, 3, 219}, 202}, {{254, 202, 113, 112, 173, 0, 0, 124, 243, 39, 15, 74, 164, 46, 192, 140}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 36, 196, 120, 32, 140}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 251}, 202}, {{254, 202, 113, 112, 173, 0, 136, 99, 112, 168, 233, 102, 74, 245, 88, 224}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 164, 172, 69, 213, 196, 124, 225, 250}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 65, 78, 178, 240, 122, 57, 250}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 178, 102, 222, 52, 0, 118, 163, 80}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 36, 159, 27, 38, 72}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 25, 21, 164, 170, 18, 127, 32}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 118, 82, 217}, 202}, {{254, 202, 113, 112, 173, 0, 0, 71, 254, 110, 94, 217, 134, 253, 42, 196}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 240, 66, 27, 228, 47, 181, 182, 172, 66, 54}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 226, 42, 7, 45, 161, 65, 188, 210}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 247, 29, 134, 178, 68, 120}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 233, 75, 86, 232}, 202}, {{254, 202, 113, 112, 173, 0, 0, 115, 82, 61, 124, 65, 98, 34, 64, 186}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 150, 192, 21, 42, 251, 21, 214}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 26, 65, 155, 142, 176, 36}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 249, 47, 184}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 16, 216, 150, 9}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 42, 84, 16}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 107, 57, 217}, 202}, {{254, 202, 113, 112, 173, 0, 0, 0, 0, 179, 187, 17, 131, 217, 221, 58}, 202}, {{254, 202, 113, 112, 173, 0, 79, 207, 185, 232, 76, 92, 161, 59, 248, 149}, 202}, {{254, 202, 113, 112, 173, 0, 80, 159, 88, 145, 208, 177, 14, 167, 253, 99}, 202}, {{80, 152, 0, 0, 0, 0, 0, 43, 57, 87, 157, 155, 227, 156, 173, 168}, 107}, {{80, 152, 0, 0, 0, 0, 249, 255, 230, 41, 174, 73, 108, 162, 143, 35}, 107}, {{80, 152, 0, 0, 0, 0, 104, 5, 179, 93, 201, 60, 113, 129, 178, 246}, 107}, {{80, 152, 95, 109, 235, 84, 48, 68, 196, 119, 97, 208, 245, 68, 210, 229}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 51}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 107}, {{80, 152, 43, 94, 146, 234, 180, 183, 37, 1, 157, 236, 43, 130, 16, 201}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 239, 247, 123, 86, 196, 85, 163}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 233}, 107}, {{80, 152, 0, 0, 164, 210, 137, 135, 76, 221, 138, 72, 217, 207, 122, 26}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 120}, 107}, {{80, 152, 0, 0, 0, 242, 57, 47, 111, 8, 115, 214, 147, 248, 95, 59}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 107}, {{80, 152, 0, 0, 80, 122, 155, 247, 32, 147, 92, 233, 169, 118, 163, 148}, 107}, {{80, 152, 0, 0, 121, 69, 53, 26, 205, 26, 133, 84, 109, 1, 145, 193}, 107}, {{80, 152, 0, 0, 106, 141, 49, 180, 148, 251, 62, 16, 99, 76, 197, 218}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 88, 202, 28, 57, 151, 202, 210, 82}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{80, 152, 0, 0, 0, 0, 38, 34, 248, 146, 83, 106, 161, 250, 222, 101}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 123, 239, 224, 62, 195, 88}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 32, 206, 144, 93, 114, 11}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 232, 180, 41, 80, 132, 150, 111}, 107}, {{80, 152, 0, 0, 0, 55, 148, 119, 30, 234, 185, 146, 62, 201, 6, 51}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 162, 31, 73, 195, 41, 220, 106}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 109, 8, 44, 167, 195, 212}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 195, 1, 200, 67, 134, 246, 214, 45}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 54, 43, 46, 98, 21, 178, 143, 233}, 107}, {{80, 152, 0, 237, 228, 0, 168, 26, 50, 11, 116, 134, 122, 237, 187, 87}, 107}, {{80, 152, 0, 0, 0, 69, 0, 93, 26, 31, 33, 198, 163, 24, 12, 50}, 107}, {{80, 152, 251, 206, 33, 49, 86, 149, 208, 167, 114, 137, 15, 163, 246, 212}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 77, 251, 136, 86, 48, 173, 89, 67}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 158, 139, 227, 2, 107, 250}, 107}, {{80, 152, 0, 0, 0, 16, 73, 29, 130, 234, 86, 249, 229, 207, 167, 50}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 91, 2, 168, 32, 219, 246, 5}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 65, 248, 61, 248}, 107}, {{80, 152, 194, 40, 18, 99, 177, 154, 166, 211, 153, 150, 39, 160, 251, 63}, 107}, {{80, 152, 0, 0, 236, 147, 88, 0, 92, 71, 165, 2, 215, 36, 106, 12}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 214, 31, 29, 42, 111, 163, 125, 176}, 107}, {{80, 152, 0, 0, 0, 0, 0, 237, 8, 19, 93, 71, 165, 60, 87, 112}, 107}, {{80, 152, 0, 0, 0, 35, 89, 203, 247, 190, 61, 193, 173, 139, 176, 182}, 107}, {{80, 152, 0, 0, 26, 143, 65, 200, 221, 48, 52, 157, 58, 52, 162, 95}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 207}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 47, 163, 83}, 107}, {{80, 152, 0, 0, 0, 0, 29, 232, 57, 101, 177, 9, 184, 167, 98, 143}, 107}, {{80, 152, 97, 204, 48, 190, 81, 89, 240, 171, 11, 171, 119, 18, 174, 8}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 165}, 107}, {{80, 152, 0, 245, 134, 1, 237, 74, 148, 85, 231, 189, 161, 51, 31, 82}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 153}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 117, 212}, 107}, {{80, 152, 0, 197, 161, 156, 136, 96, 107, 41, 182, 203, 26, 58, 136, 175}, 107}, {{80, 152, 0, 0, 0, 237, 191, 68, 4, 51, 60, 169, 27, 77, 232, 181}, 107}, {{80, 152, 0, 88, 150, 152, 85, 14, 243, 230, 177, 202, 89, 207, 79, 198}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 162, 36, 130, 63, 215, 57, 0}, 107}, {{80, 152, 0, 117, 175, 198, 161, 33, 92, 174, 246, 29, 104, 169, 19, 175}, 107}, {{80, 152, 253, 24, 86, 148, 46, 47, 142, 88, 65, 227, 163, 172, 123, 19}, 107}, {{80, 152, 0, 0, 0, 170, 69, 222, 60, 207, 28, 122, 6, 158, 117, 47}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{80, 152, 207, 92, 8, 167, 187, 252, 3, 250, 86, 97, 138, 194, 162, 197}, 107}, {{80, 152, 0, 0, 0, 0, 0, 67, 107, 202, 227, 63, 125, 61, 230, 45}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 37, 26, 28}, 107}, {{80, 152, 0, 0, 190, 87, 65, 177, 7, 193, 78, 136, 64, 124, 105, 139}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 242, 131, 2, 215, 224, 25, 145, 35}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 75, 51}, 107}, {{80, 152, 0, 0, 0, 0, 0, 141, 17, 234, 199, 159, 104, 20, 67, 208}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 107}, {{80, 152, 0, 0, 0, 36, 112, 115, 37, 192, 2, 23, 193, 230, 190, 93}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 33, 53, 214, 130, 221, 136}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 234}, 107}, {{80, 152, 0, 189, 231, 181, 151, 82, 38, 25, 228, 18, 146, 58, 220, 127}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 85, 248, 202, 132, 214, 2, 231}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 137, 199, 152}, 107}, {{80, 152, 0, 0, 0, 194, 205, 253, 165, 205, 167, 99, 77, 55, 106, 117}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 234, 142, 63, 97, 128, 227, 157, 98}, 107}, {{80, 152, 0, 0, 0, 0, 113, 64, 173, 190, 30, 143, 46, 46, 112, 122}, 107}, {{80, 152, 0, 0, 0, 211, 33, 203, 112, 231, 249, 95, 195, 175, 166, 166}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 156, 116, 115, 235, 23, 109, 212}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 2, 4, 198, 149}, 107}, {{80, 152, 0, 0, 0, 117, 8, 70, 166, 181, 205, 189, 64, 180, 41, 181}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 136, 172, 111, 60, 88, 59, 93, 97}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 132}, 107}, {{80, 152, 0, 0, 0, 0, 48, 190, 86, 252, 99, 166, 169, 10, 161, 27}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 218, 161}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 254, 213, 155, 95, 77, 112}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 95, 56, 189}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 4, 61, 57, 164, 229, 147}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 255, 54, 3, 6, 71, 63, 61, 175}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 226, 119, 60, 198, 7, 35, 84}, 107}, {{80, 152, 0, 0, 0, 17, 188, 35, 68, 129, 178, 54, 137, 227, 184, 211}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 230, 199}, 107}, {{80, 152, 0, 0, 38, 123, 200, 6, 125, 31, 78, 123, 113, 20, 193, 232}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 219, 96, 156, 113}, 107}, {{80, 152, 0, 0, 0, 0, 0, 233, 192, 244, 246, 213, 162, 56, 246, 172}, 107}, {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 56, 88, 42, 103, 196, 190, 5}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 32, 183, 89, 70}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 172, 28, 32, 6, 178, 48, 3, 19}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 15, 185, 29}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 250, 113}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{222, 216, 0, 0, 0, 0, 128, 32, 41, 84, 206, 38, 1, 56, 252, 158}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 195, 125, 155, 205, 73, 46, 38}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 71, 158, 113, 109, 24, 244, 217}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 124}, {{222, 216, 0, 0, 0, 0, 102, 236, 219, 60, 147, 51, 45, 71, 104, 87}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 118, 36, 85, 60, 129, 224, 214, 83}, 124}, {{222, 216, 0, 0, 70, 202, 95, 99, 201, 74, 11, 235, 19, 79, 105, 175}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 177}, 124}, {{222, 216, 0, 0, 0, 0, 3, 205, 72, 185, 228, 134, 94, 112, 206, 151}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 114, 120}, 124}, {{222, 216, 0, 0, 34, 165, 194, 205, 53, 219, 158, 164, 20, 17, 140, 88}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{222, 216, 0, 119, 104, 156, 123, 248, 217, 253, 213, 193, 72, 18, 196, 203}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 39, 233, 196, 193, 238, 97, 182, 149}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 180, 1, 110, 246, 138, 127, 247}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 136, 188, 120, 60}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 221, 146, 19, 202}, 124}, {{222, 216, 0, 0, 0, 0, 17, 174, 252, 139, 86, 53, 42, 96, 133, 241}, 124}, {{222, 216, 0, 0, 0, 0, 89, 189, 183, 214, 201, 44, 183, 175, 37, 115}, 124}, {{222, 216, 0, 116, 197, 192, 144, 214, 208, 80, 50, 118, 159, 12, 141, 34}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 112, 21, 198, 211}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 61, 57}, 124}, {{222, 216, 0, 0, 0, 96, 4, 127, 251, 154, 68, 139, 126, 49, 235, 200}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 239, 115, 194, 2}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 169, 73, 197}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 38, 204, 62, 169}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 162, 228, 181, 163, 184, 218, 240, 220}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 54, 64, 50, 209}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 16}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 231, 238, 54}, 124}, {{222, 216, 0, 0, 0, 176, 195, 190, 124, 138, 209, 64, 218, 91, 223, 15}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 36, 191, 240}, 124}, {{222, 216, 0, 0, 0, 0, 0, 216, 165, 138, 157, 184, 137, 192, 79, 1}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 252, 241}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 124}, {{222, 216, 0, 0, 137, 231, 38, 242, 207, 47, 183, 223, 71, 51, 7, 22}, 124}, {{222, 216, 0, 0, 240, 59, 111, 131, 230, 102, 82, 79, 241, 234, 211, 0}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 23, 224, 42, 189, 67, 218, 240}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 230, 56, 117, 92, 12, 185, 185}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 12, 152, 202}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 172, 156, 72, 193, 213, 99, 206, 219}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 79, 101, 215, 206, 177, 152}, 124}, {{222, 216, 0, 0, 87, 85, 78, 40, 0, 51, 116, 111, 209, 204, 207, 98}, 124}, {{222, 216, 0, 0, 0, 0, 105, 255, 118, 75, 224, 140, 244, 224, 167, 226}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 35, 174, 118, 178, 71, 3, 0, 18}, 124}, {{222, 216, 0, 0, 251, 88, 215, 236, 250, 44, 117, 127, 5, 189, 248, 127}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 248, 111, 68}, 124}, {{222, 216, 74, 39, 77, 201, 23, 6, 50, 183, 108, 133, 195, 175, 188, 89}, 124}, {{222, 216, 0, 0, 0, 166, 146, 47, 211, 182, 27, 86, 12, 166, 186, 196}, 124}, {{222, 216, 0, 0, 0, 105, 241, 15, 162, 31, 61, 89, 165, 172, 143, 4}, 124}, {{222, 216, 0, 0, 0, 0, 0, 12, 143, 235, 25, 105, 138, 3, 123, 143}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 204, 45}, 124}, {{222, 216, 0, 0, 0, 0, 0, 195, 179, 5, 34, 76, 76, 204, 47, 100}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 217}, 124}, {{222, 216, 0, 0, 0, 0, 0, 137, 186, 155, 153, 193, 211, 254, 173, 106}, 124}, {{222, 216, 0, 0, 0, 0, 226, 134, 185, 16, 185, 4, 183, 18, 161, 62}, 124}, {{222, 216, 0, 0, 0, 0, 0, 244, 38, 243, 29, 232, 18, 154, 250, 171}, 124}, {{222, 216, 0, 0, 0, 0, 0, 26, 35, 92, 7, 78, 46, 74, 139, 147}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 236, 219, 81, 98}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 147}, 124}, {{222, 216, 0, 0, 103, 22, 66, 212, 174, 122, 114, 200, 113, 49, 182, 38}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 141, 6, 138, 247}, 124}, {{222, 216, 0, 0, 0, 0, 0, 249, 222, 84, 196, 191, 94, 235, 145, 170}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 113, 168, 231, 15}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 51}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 91, 27, 141, 226, 182, 127, 174, 170}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 135, 103, 151, 197, 138, 201, 225}, 124}, {{222, 216, 24, 121, 31, 200, 75, 77, 153, 35, 6, 58, 95, 194, 156, 166}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 75, 145, 216}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 195, 33, 37, 249, 23, 55, 239, 202}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{222, 216, 0, 0, 0, 0, 243, 88, 45, 35, 32, 46, 184, 51, 203, 57}, 124}, {{222, 216, 0, 0, 0, 97, 146, 32, 245, 150, 123, 202, 93, 108, 222, 230}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 105, 138, 81, 8}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 240}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 76, 56, 194, 180}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 58, 52, 187, 89, 118, 41, 200}, 124}, {{222, 216, 0, 0, 0, 0, 0, 101, 58, 2, 53, 39, 84, 99, 210, 49}, 124}, {{222, 216, 0, 0, 0, 230, 218, 251, 134, 185, 57, 18, 32, 126, 2, 225}, 124}, {{222, 216, 0, 0, 14, 56, 160, 62, 177, 207, 241, 170, 236, 92, 235, 4}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 207, 140, 217, 190, 14, 66}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 163, 193}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 20, 64, 255, 60, 60, 42}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 86, 191, 151, 223}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 139, 153}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 152}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 92, 115}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 148, 232, 115, 254}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 102, 188, 57, 183, 166, 67, 93}, 124}, {{222, 216, 0, 0, 0, 0, 0, 0, 0, 192, 192, 230, 4, 244, 116, 251}, 124}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 148, 125, 14, 253, 234, 92, 98}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 177, 47}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 60, 136, 246}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 77, 176, 17, 157, 172, 186, 253, 190}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 202, 190, 237}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 117, 87, 25, 59}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 227, 237, 229}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 181, 219}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 27, 196}, 57}, {{219, 138, 253, 12, 188, 197, 48, 145, 238, 136, 163, 26, 70, 222, 155, 33}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 143, 222, 36, 109, 36, 0, 118}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 237, 43, 131, 163, 116}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 200, 99, 55, 178}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 200, 28, 211, 64}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 10, 33, 90, 30, 41}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 194, 87, 250, 207, 31, 11, 79, 33}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 98, 52, 121, 90, 244, 171, 192}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 238, 238}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 168, 56, 95, 144, 132, 179}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 75, 221, 143, 36, 32, 42}, 57}, {{219, 138, 253, 12, 188, 197, 48, 255, 67, 201, 6, 130, 244, 252, 101, 185}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 112, 134, 210, 195, 96, 97, 227, 164}, 57}, {{219, 138, 253, 12, 188, 197, 48, 234, 103, 40, 82, 80, 197, 192, 253, 228}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 117, 172, 132, 66, 195, 212}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 134, 174, 253, 176, 28, 169, 181}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 172, 26, 226, 95, 208, 162}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 202, 66, 159, 106, 173}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 19, 85, 105, 96, 43, 251}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 21, 31}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 186, 249, 137, 119, 102, 27}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 33, 137}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 111, 173, 144, 93, 226, 49, 172, 34}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 20, 222, 171, 147, 29}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 29, 217, 139, 1, 202, 176, 190, 194}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 90, 29, 246, 138, 71, 178, 254, 153}, 57}, {{219, 138, 253, 12, 188, 197, 48, 232, 242, 128, 80, 115, 101, 47, 135, 227}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 63, 246, 127, 48, 190}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 209, 10, 167, 136, 119, 225}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 199, 53}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 99, 172, 153, 98, 32, 105}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 178, 238, 242}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 133, 18, 197, 64}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 134, 104, 98, 28, 41, 131, 105}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 42, 76, 68, 12, 129, 38, 100, 251}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 172, 67, 173, 243, 156}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 232, 181, 218, 210, 234, 69, 168, 66}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 22, 16, 0, 99, 253, 59, 121}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 187, 203, 192, 114, 78, 143}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 11, 143, 250, 223, 214, 70, 34, 3}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 253, 29, 34, 197, 253, 253, 115}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 101, 83, 112, 255, 22, 49, 243, 49}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 22, 199, 252, 213, 158}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 88, 141, 108, 81, 211}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 246, 38, 173, 100, 217, 196, 8, 180}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 1, 70, 74, 178}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 36, 62, 156, 89}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 246, 252, 4, 143, 169, 1, 14, 153}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 10, 148, 171, 71}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 241, 22}, 57}, {{219, 138, 253, 12, 188, 197, 48, 61, 43, 223, 164, 170, 138, 170, 15, 158}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 236, 15, 78, 117, 228, 102, 195}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 22, 247, 109}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 63, 255, 83, 12, 142, 98}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 116, 71, 196, 252}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 156, 225}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 112, 177, 142, 8, 53, 111, 112, 163}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 186, 216, 81, 6, 55}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 245, 130, 248, 183, 128, 195, 107}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 210, 247, 45, 108}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 21, 3, 62, 32, 143, 145, 209}, 57}, {{219, 138, 253, 12, 188, 197, 48, 4, 138, 102, 144, 195, 128, 241, 181, 136}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 215, 62, 200, 244, 164, 51}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 156, 34, 180, 209}, 57}, {{219, 138, 253, 12, 188, 197, 48, 223, 168, 117, 182, 134, 157, 83, 155, 108}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 254, 81, 20, 113, 8, 185, 231, 96}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 45, 128}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 88, 245, 82, 149, 96, 239, 216}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 32, 122, 10, 15}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 227, 253, 165}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 167, 76, 219, 236}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 100, 41, 1, 152, 98}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 206, 90, 83, 174, 149}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 3, 38, 66, 86, 105, 238}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 70, 73}, 57}, {{219, 138, 253, 12, 188, 197, 48, 212, 215, 8, 252, 102, 234, 51, 191, 89}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 206, 203, 115, 25, 183, 246, 49, 210}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 95, 203}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 8, 238, 67, 234, 96, 215}, 57}, {{219, 138, 253, 12, 188, 197, 48, 0, 211, 75, 171, 30, 126, 187, 47, 23}, 57}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 25}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 238, 175, 195}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 162}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 200, 16, 96, 129}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 105, 12}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 196, 89}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 49, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 137}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 252, 246, 211}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 242}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 96}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 184, 184}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 238}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 114}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 8, 22, 203}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 96, 127}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 214, 126, 95}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 215}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 65}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 45, 19, 148}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 30}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 239}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 227, 101, 131, 1}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 49, 159, 128, 178}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 6, 164}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 226, 245, 167}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 181, 214, 55}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 183, 30}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 199}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 86, 240, 139}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 2, 146, 24}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 210, 94, 242, 51}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 45, 209, 141}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 25, 56, 104, 8}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 162, 243, 63, 232}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 59, 25}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 171, 130, 18}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 98, 69}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 11, 22, 106}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 143, 8}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 77, 242}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 220}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 179, 179}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 225, 240, 178}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 14, 165}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 215, 52, 128}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 177, 193, 84, 114}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 37, 1}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 81, 138}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 239}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 190, 184, 29}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 231, 20, 244}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 253, 234, 26}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 167, 182, 46}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 241, 88, 137}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 238, 31}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 12}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 18, 164, 25, 157}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 95, 49}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 156, 252, 79, 90}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 232}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 38, 77}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 96, 78, 4}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 80}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 219, 192, 23, 164}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 9, 129}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 217, 68}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 18, 49, 19, 153}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 120}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 167, 90, 189, 73}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 142, 150, 84, 183}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 197}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 200}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 181}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 90}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 237, 81}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 199, 133, 111, 153, 28}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 158, 187, 202, 82, 129}, 107}, {{195, 236, 245, 0, 117, 124, 248, 192, 199, 77, 83, 223, 172, 204, 243, 149}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 86, 103, 18, 38, 199, 249, 234, 59}, 107}, {{195, 236, 245, 0, 0, 0, 0, 71, 121, 111, 46, 138, 192, 195, 36, 223}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 133, 192, 201}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 124, 69}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 200, 124}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 113, 81, 3, 197, 52, 45}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 4, 164}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 243, 119, 30, 164, 181}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 2, 58}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 192, 53, 108, 15, 181, 88, 129}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 248}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 67, 118, 223, 58, 243, 16}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 107, 195}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 87, 155, 246}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 90, 203, 48, 224, 153, 39, 162}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 206, 175, 160, 157, 100}, 107}, {{195, 236, 245, 0, 0, 0, 0, 162, 205, 232, 148, 140, 247, 108, 186, 234}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 64, 139, 160, 110, 153, 73, 180}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 249, 192, 86, 72, 60, 141, 163, 239}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 106, 169, 7, 97, 98, 194, 66, 188, 185}, 107}, {{195, 236, 245, 0, 0, 0, 0, 29, 219, 219, 234, 134, 84, 240, 191, 248}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 238, 243, 138, 224, 235, 151}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 113}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 24, 38, 76, 16, 49, 68, 31}, 107}, {{195, 236, 245, 0, 0, 44, 42, 156, 81, 34, 55, 201, 98, 1, 23, 90}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 135, 87, 126, 52, 249, 197, 40}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 121, 16, 182, 102, 86, 202}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 210, 143, 199, 105, 219, 221}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 107}, {{195, 236, 245, 0, 0, 0, 252, 69, 82, 6, 5, 251, 217, 255, 209, 61}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 103, 110, 236, 218, 222, 19}, 107}, {{195, 236, 245, 0, 0, 128, 2, 145, 79, 8, 11, 116, 103, 197, 225, 44}, 107}, {{195, 236, 245, 0, 0, 0, 244, 196, 84, 214, 68, 232, 158, 244, 231, 73}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 115, 41, 206, 213, 126, 12}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 202, 9, 217, 18, 207, 105, 211}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 15, 22, 174, 150, 131}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 85, 4, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 131, 192, 103}, 107}, {{195, 236, 245, 0, 0, 0, 0, 214, 152, 24, 156, 104, 17, 93, 29, 219}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 237, 227}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 47, 215, 8, 118, 237, 123}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 1, 117, 215, 54, 170, 48, 7}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 194, 86, 175, 200, 64, 80, 75, 220, 205}, 107}, {{195, 236, 245, 0, 0, 0, 0, 215, 217, 64, 159, 17, 181, 3, 163, 240}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 5}, 107}, {{195, 236, 245, 0, 0, 0, 0, 96, 155, 227, 129, 75, 126, 0, 27, 106}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 27, 13, 238}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 137}, 107}, {{195, 236, 245, 0, 0, 158, 61, 101, 50, 220, 61, 196, 147, 164, 203, 118}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 252, 62, 242, 117, 140, 19}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 14, 217, 52, 33, 61, 77}, 107}, {{195, 236, 245, 0, 0, 0, 72, 246, 83, 60, 108, 146, 225, 71, 179, 3}, 107}, {{195, 236, 245, 0, 125, 96, 156, 187, 181, 222, 92, 99, 231, 240, 43, 110}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 100, 130, 252, 184, 204, 44}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 157, 207, 27}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 90, 108, 27}, 107}, {{195, 236, 245, 0, 200, 105, 239, 226, 15, 138, 118, 114, 62, 195, 5, 39}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 153, 7, 54}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 94, 2, 200}, 107}, {{195, 236, 245, 0, 0, 8, 244, 116, 142, 141, 211, 34, 21, 59, 83, 242}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 94, 171, 127, 22, 196, 225, 80, 168}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 188, 57, 105, 243, 119}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 229}, 107}, {{195, 236, 245, 0, 0, 0, 0, 105, 216, 70, 79, 170, 60, 51, 40, 45}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 143, 251, 73}, 107}, {{195, 236, 245, 0, 0, 182, 45, 218, 213, 158, 187, 132, 57, 251, 207, 85}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 171, 191, 212, 215, 108, 238}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 2, 39, 218, 240, 53, 58, 147}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 88, 204}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 18, 246, 215, 123, 44, 72, 156, 212}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 137}, 107}, {{195, 236, 245, 0, 44, 120, 195, 141, 49, 99, 51, 106, 56, 241, 177, 109}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 112, 123, 84, 169, 96}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 98, 242, 108, 35, 68, 115, 217, 222}, 107}, {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 186, 181, 15, 35, 215}, 107}, {{195, 236, 245, 0, 0, 104, 80, 1, 11, 16, 3, 0, 233, 175, 69, 210}, 107}, {{195, 236, 245, 0, 0, 0, 0, 72, 177, 100, 71, 208, 197, 104, 4, 247}, 107}, {{195, 236, 245, 0, 0, 0, 15, 81, 20, 199, 127, 62, 81, 235, 88, 222}, 107}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 101}, {{112, 0, 0, 0, 0, 113, 62, 76, 208, 238, 78, 119, 64, 237, 250, 192}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 5, 30, 114, 30, 160, 172, 122}, 3}, {{112, 0, 241, 242, 250, 196, 95, 151, 142, 168, 251, 115, 150, 94, 190, 92}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 146, 81, 156, 144}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 87, 33, 172, 169, 192, 96, 182}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 3}, {{112, 0, 0, 0, 0, 0, 0, 252, 84, 182, 196, 68, 179, 44, 210, 164}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 49}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 40, 48, 151, 178}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 5, 11, 93, 208}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 146, 111, 128, 204}, 3}, {{112, 0, 0, 0, 0, 0, 225, 163, 37, 10, 36, 184, 2, 140, 33, 102}, 3}, {{112, 236, 246, 109, 235, 17, 243, 108, 16, 33, 202, 155, 252, 55, 240, 250}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 60, 203, 78, 40, 16}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 85, 132, 20, 124, 17, 77, 214, 56}, 3}, {{112, 0, 248, 95, 145, 238, 76, 237, 172, 56, 156, 222, 170, 50, 167, 97}, 3}, {{112, 0, 0, 0, 123, 167, 15, 39, 152, 185, 125, 249, 213, 16, 195, 189}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 20, 121, 11, 253, 144, 56, 242, 25}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 35, 109}, 3}, {{112, 0, 0, 0, 87, 39, 134, 120, 97, 99, 172, 65, 105, 185, 53, 193}, 3}, {{112, 0, 182, 24, 227, 42, 125, 228, 81, 14, 74, 155, 105, 9, 108, 53}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 50, 115}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 98, 241, 17, 30, 14, 177, 114, 160, 181}, 3}, {{112, 0, 34, 16, 48, 5, 84, 248, 134, 250, 67, 47, 31, 78, 37, 86}, 3}, {{112, 0, 0, 0, 0, 0, 197, 161, 97, 249, 105, 123, 19, 193, 163, 25}, 3}, {{112, 0, 89, 254, 86, 126, 119, 218, 176, 248, 57, 182, 55, 61, 38, 226}, 3}, {{112, 0, 0, 38, 97, 17, 196, 232, 31, 190, 172, 81, 109, 104, 228, 29}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 64, 217, 148, 201, 189, 175, 64, 128, 176, 116, 61}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 254, 148}, 3}, {{112, 0, 0, 0, 81, 59, 143, 148, 167, 176, 14, 25, 186, 195, 73, 42}, 3}, {{112, 0, 0, 0, 0, 244, 91, 204, 152, 61, 120, 47, 136, 156, 206, 161}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 45, 84, 106}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 75, 2, 241, 39, 74}, 3}, {{112, 110, 160, 203, 226, 168, 223, 208, 73, 170, 166, 211, 126, 147, 25, 2}, 3}, {{112, 0, 0, 0, 0, 154, 152, 166, 42, 39, 88, 149, 48, 205, 207, 98}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 211, 152, 46, 218}, 3}, {{112, 0, 0, 168, 8, 9, 24, 103, 114, 69, 119, 79, 255, 36, 164, 70}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 146, 187, 218, 106}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 54, 154}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 31, 153}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 165, 238, 62, 210, 248, 26, 19, 114, 173, 223, 233, 138, 183, 176, 29}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 6, 197, 203, 175, 25, 207, 137}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 231, 115, 3, 250}, 3}, {{112, 0, 0, 25, 152, 208, 59, 207, 120, 52, 86, 90, 56, 250, 254, 187}, 3}, {{112, 0, 0, 0, 0, 0, 0, 12, 162, 27, 92, 156, 141, 13, 161, 53}, 3}, {{112, 0, 0, 235, 205, 229, 7, 166, 90, 15, 15, 222, 87, 228, 93, 99}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 88, 175, 173, 16, 104, 127, 133, 158}, 3}, {{112, 0, 0, 150, 90, 238, 45, 183, 117, 211, 99, 21, 254, 166, 228, 35}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 192, 40, 89, 247, 136, 165, 246}, 3}, {{112, 219, 191, 74, 215, 205, 0, 104, 104, 57, 96, 252, 174, 34, 23, 24}, 3}, {{112, 0, 235, 51, 83, 35, 218, 244, 77, 104, 226, 56, 129, 190, 124, 81}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 1, 160, 97}, 3}, {{112, 0, 0, 29, 10, 167, 212, 122, 107, 166, 240, 222, 171, 37, 249, 94}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 45, 179}, 3}, {{112, 0, 0, 0, 0, 0, 0, 41, 91, 211, 174, 189, 145, 204, 246, 59}, 3}, {{112, 0, 0, 0, 0, 111, 120, 197, 182, 48, 247, 110, 255, 161, 12, 225}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 205, 184, 83}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 230, 58, 26}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 144}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 253, 145, 91, 142, 4, 138, 122, 243}, 3}, {{112, 0, 0, 0, 0, 0, 126, 26, 153, 208, 130, 145, 151, 148, 207, 192}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 233, 129, 79}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 62, 44, 210, 137, 170, 16, 216}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 49, 18, 45, 68, 166, 186, 32, 136}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 184, 167, 3, 67}, 3}, {{112, 0, 0, 0, 0, 0, 241, 196, 19, 94, 203, 192, 189, 168, 244, 81}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 61, 193, 54, 143, 111, 150, 171, 224}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 85, 224, 129, 126}, 3}, {{112, 0, 0, 0, 0, 0, 0, 141, 229, 203, 39, 194, 179, 218, 246, 13}, 3}, {{112, 0, 0, 112, 77, 244, 228, 188, 222, 5, 169, 40, 164, 57, 9, 42}, 3}, {{112, 0, 0, 0, 0, 77, 138, 184, 107, 133, 65, 204, 124, 5, 104, 248}, 3}, {{112, 0, 255, 149, 93, 199, 179, 130, 198, 91, 179, 152, 159, 192, 177, 209}, 3}, {{112, 14, 104, 219, 180, 128, 153, 128, 180, 36, 118, 152, 161, 10, 131, 234}, 3}, {{112, 0, 0, 0, 0, 233, 223, 8, 13, 122, 165, 243, 148, 157, 241, 233}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 226, 23, 153, 243, 73, 77, 182, 117, 80, 140, 187, 184, 34, 82}, 3}, {{112, 0, 0, 132, 231, 39, 40, 97, 79, 77, 119, 195, 42, 218, 187, 224}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 175, 203}, 3}, {{112, 0, 0, 0, 0, 0, 0, 42, 123, 142, 136, 177, 6, 71, 49, 39}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 11, 167}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 142, 218, 177, 171}, 3}, {{112, 0, 0, 140, 192, 218, 20, 238, 203, 197, 54, 146, 199, 13, 85, 36}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 219, 57, 28, 84}, 3}, {{112, 0, 0, 0, 0, 255, 44, 56, 54, 76, 198, 59, 169, 249, 80, 105}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 229, 15, 26, 151}, 3}, {{112, 0, 35, 246, 165, 152, 83, 39, 212, 186, 237, 191, 32, 98, 15, 68}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 33, 54, 199, 109, 230, 31, 73, 31}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 234, 90, 202, 194, 147, 26, 163, 59}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 52}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 137, 28, 211, 160, 187, 47, 135}, 3}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 175, 197}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 22}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 190, 239, 89, 26}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 139, 28, 200, 5}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 105, 73, 22, 63, 200, 16, 111}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 27, 214, 241, 157, 49}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 155}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 75}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 123, 130, 110, 239}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 142, 253}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 134, 89, 232, 121}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 32}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 201}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 71}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 57, 255, 13, 39, 67, 178}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 230, 19, 98, 244, 142, 59, 235}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 35, 107, 243, 253, 183}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 90, 242, 185, 76, 92, 1}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 225, 125, 143, 195, 97, 227, 138, 61}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 182, 75, 9, 15, 200}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 136, 81, 188, 118, 205, 219}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 197}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 192, 231, 69, 98, 30, 60}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 157, 220, 54, 26, 185, 182}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 23, 133, 49, 60, 161}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 154, 132, 146, 205}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 2, 112, 137, 233, 184, 139, 19}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 75}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 118, 91, 125, 192}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 160, 40, 123, 2}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 75, 23}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 212, 166, 160, 211, 139, 248}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 157, 41, 20, 66, 159, 213, 38}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 246, 133}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 239, 102}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 240}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 52}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 96, 40, 116, 234, 142, 39}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 62, 125}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 197, 192, 222, 219, 232}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 52, 206, 29, 98, 38}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 81, 173, 11, 104, 116, 20, 198, 196}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 129, 30, 7, 84, 140, 151, 158}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 239}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 58}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 198, 160, 188}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 249, 235}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 245, 81, 156, 24}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 216}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 13, 210, 239, 127, 105, 59, 217}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 18, 132, 235, 6, 85, 87, 109, 109}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 116, 205, 200, 5, 31, 13, 180}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 96}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 194, 115, 75, 34}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 246, 70, 184, 124, 205, 113, 139}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 170, 100, 76, 134, 149}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 114, 189, 145, 67, 143}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 103, 180, 152, 193}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 163, 198, 31, 6, 90, 13, 179}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 41, 188, 68, 17, 44, 196}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 47, 10, 26}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 149, 43}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 127, 116, 16, 202, 173}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 136, 77, 82}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 131, 150, 144}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 58, 67, 196, 238, 171, 145}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 126, 68, 113}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 158, 39, 214, 171}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 252, 252}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 97, 13, 156, 254, 44, 84}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 208, 46, 184, 225, 159, 54, 251}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 225, 18, 82, 16, 193, 147}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 30, 161, 204, 3, 121, 136}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 12, 30, 175, 85, 224, 166, 103}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 64, 75, 128, 15, 120, 126, 150}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 219, 13, 188}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 162, 20}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 166, 142, 122}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 56, 225, 111, 163, 105, 31, 55}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 76, 151, 205}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 51, 178, 240, 245, 70, 104}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 181, 171, 76, 252, 64, 136, 203}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 70, 109, 191, 246}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 165, 168, 118}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 246, 254, 171, 217, 92}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 200, 42, 176}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 16}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 143, 134, 95, 134, 194}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 86, 221, 169, 162}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 201}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 130, 76, 210, 52, 7, 175, 40}, 136}, {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 155}, 136}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 59, 105, 79, 154, 0, 116}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 69, 21, 65, 224, 185}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 161, 172, 113, 224, 244, 192, 211, 45}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 246, 47, 47, 12}, 114}, {{41, 171, 206, 178, 195, 80, 210, 56, 66, 163, 108, 69, 225, 34, 187, 61}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 10, 212, 2, 46}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 50, 9, 84}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 145, 180, 19, 237, 176}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 17, 86, 147, 52, 10, 232, 180, 167}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 27, 249, 3, 130, 93, 162, 28, 82, 65}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 133, 128, 47, 71, 116, 230, 229}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 178, 148, 170, 175}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 128, 160, 103, 10, 58, 24, 203}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 204, 100, 1}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 124, 157, 237, 70, 142}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 205, 12, 100}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 197, 209, 120, 140, 143, 247}, 114}, {{41, 171, 206, 178, 195, 80, 0, 103, 41, 244, 157, 24, 45, 32, 223, 7}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 34, 171}, 114}, {{41, 171, 206, 178, 195, 80, 172, 201, 67, 61, 194, 241, 70, 240, 63, 73}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 107, 2}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 6, 52, 76, 155, 34}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 109, 81, 228}, 114}, {{41, 171, 206, 178, 195, 80, 0, 137, 185, 250, 103, 247, 174, 123, 146, 226}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 242, 97, 54}, 114}, {{41, 171, 206, 178, 195, 80, 0, 85, 127, 51, 152, 97, 231, 206, 70, 198}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 74, 245, 64, 105}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 114}, {{41, 171, 206, 178, 195, 80, 0, 30, 209, 18, 26, 46, 255, 23, 109, 231}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 120, 7, 7, 242, 123}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 43, 55, 58, 99, 253, 69}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 195, 187, 26, 219}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 54, 90, 111, 135, 180, 196, 183}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 238, 62, 180}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 32, 204, 146}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 27, 76, 77}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 30, 95, 253, 172, 71, 14, 218}, 114}, {{41, 171, 206, 178, 195, 80, 228, 23, 142, 243, 17, 191, 123, 68, 169, 118}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 66, 238, 250, 221, 245, 176, 230}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 188, 103, 33}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 50, 178, 73, 35}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 80, 205, 231}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 157, 113, 9, 44, 188, 102, 153, 184}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 154, 201, 178, 234}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 63, 53, 87, 214}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 105, 204, 130, 8, 200, 66, 25, 123}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 25, 133, 36, 174, 9}, 114}, {{41, 171, 206, 178, 195, 80, 0, 45, 149, 225, 66, 133, 14, 90, 208, 86}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 81, 237}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 28, 75, 51, 102, 108}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 155, 54}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 77, 94, 242, 138}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 81, 47, 130, 42, 90, 170, 31, 218, 86, 60}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 41, 218, 107, 219, 129, 167}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 201, 16, 48, 3, 194}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 209, 6, 240, 177, 53, 126, 48}, 114}, {{41, 171, 206, 178, 195, 80, 0, 249, 117, 129, 110, 34, 55, 141, 89, 140}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 114}, {{41, 171, 206, 178, 195, 80, 0, 64, 217, 97, 237, 142, 176, 115, 254, 221}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 146, 88, 0, 229, 73, 244}, 114}, {{41, 171, 206, 178, 195, 80, 139, 207, 155, 158, 106, 57, 142, 166, 210, 27}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 52, 183, 208, 92, 234, 87, 229, 46, 69, 173}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 244, 138, 6, 4, 211, 214, 111, 14}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 95, 143, 102, 50, 104}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 16, 148, 171, 125}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 188, 5, 100, 47, 35}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 54, 145, 251, 42}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 191, 163}, 114}, {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 114}, {{159, 15, 180, 0, 0, 0, 62, 146, 221, 34, 103, 137, 46, 225, 240, 28}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 242, 187, 104, 242, 146, 2, 28}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 110}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 215}, {{159, 15, 180, 130, 162, 20, 171, 120, 131, 185, 17, 185, 36, 171, 49, 109}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 215}, {{159, 15, 180, 0, 0, 0, 25, 194, 5, 231, 33, 51, 58, 209, 102, 59}, 215}, {{159, 15, 180, 0, 0, 36, 154, 210, 84, 155, 255, 69, 89, 220, 64, 2}, 215}, {{159, 15, 180, 0, 0, 0, 51, 154, 0, 25, 230, 9, 204, 6, 220, 25}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 178, 206, 126}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 16, 114, 161, 164, 126}, 215}, {{159, 15, 180, 0, 99, 191, 189, 215, 61, 111, 87, 84, 48, 153, 233, 27}, 215}, {{159, 15, 180, 0, 1, 249, 147, 148, 155, 21, 205, 94, 100, 43, 129, 132}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 104, 237, 64, 207, 55, 164}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 200, 159}, 215}, {{159, 15, 180, 0, 106, 148, 86, 116, 184, 231, 157, 32, 51, 194, 68, 82}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 215}, {{159, 15, 180, 0, 0, 15, 156, 101, 235, 134, 219, 134, 166, 224, 191, 84}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 54, 114, 118, 222, 129, 155, 127, 212}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 46, 101}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 97, 95, 168, 157, 154, 221, 162, 81}, 215}, {{159, 15, 180, 0, 23, 9, 212, 184, 148, 95, 93, 2, 229, 61, 125, 107}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 49, 176, 43, 89, 95, 196, 134}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 88, 251, 5}, 215}, {{159, 15, 180, 0, 0, 0, 0, 39, 34, 130, 187, 188, 97, 227, 242, 55}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 254}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 124}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 119, 138, 73, 138, 97}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 176, 48, 179, 18, 250}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 215}, {{159, 15, 180, 0, 0, 0, 0, 178, 63, 200, 66, 220, 73, 34, 27, 133}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 109, 55, 181, 118, 250, 248}, 215}, {{159, 15, 180, 0, 0, 0, 102, 226, 251, 27, 232, 165, 156, 7, 0, 180}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 25, 140, 107, 22, 153, 182, 85, 46}, 215}, {{159, 15, 180, 73, 19, 76, 60, 204, 48, 122, 65, 187, 39, 229, 81, 73}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 47, 217, 232, 74, 129, 233, 89}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 232, 211, 19, 160, 128}, 215}, {{159, 15, 180, 120, 157, 147, 186, 227, 229, 194, 105, 125, 16, 81, 201, 157}, 215}, {{159, 15, 180, 0, 0, 0, 83, 46, 101, 59, 75, 184, 133, 200, 171, 245}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 215}, {{159, 15, 180, 0, 0, 0, 0, 22, 19, 6, 47, 125, 129, 181, 239, 198}, 215}, {{159, 15, 180, 0, 0, 0, 122, 187, 197, 215, 236, 246, 209, 110, 204, 234}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 166, 205}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 123, 89, 77, 116, 8, 44, 93, 117, 65, 101}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 131, 174, 160}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 255, 242, 135, 248, 46}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 69, 151, 21}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 48, 162, 11, 254, 2, 43, 150}, 215}, {{159, 15, 180, 0, 0, 0, 0, 22, 206, 75, 245, 117, 18, 46, 61, 92}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 54, 218, 201}, 215}, {{159, 15, 180, 0, 0, 0, 1, 235, 92, 230, 237, 56, 122, 57, 190, 190}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 10, 32, 216, 126, 49, 134, 185, 224, 110, 57}, 215}, {{159, 15, 180, 0, 0, 0, 0, 167, 178, 213, 169, 171, 187, 196, 213, 85}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 9, 81}, 215}, {{159, 15, 180, 0, 0, 0, 222, 78, 187, 38, 21, 244, 172, 80, 81, 20}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 159, 234, 130, 175, 246}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 95, 88, 182, 23, 192}, 215}, {{159, 15, 180, 0, 236, 83, 2, 191, 200, 36, 110, 69, 124, 244, 35, 40}, 215}, {{159, 15, 180, 0, 0, 231, 117, 196, 149, 246, 7, 19, 69, 156, 29, 86}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 215}, {{159, 15, 180, 0, 137, 65, 57, 61, 63, 150, 27, 15, 131, 125, 139, 36}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 19}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 254, 9, 137, 146, 78}, 215}, {{159, 15, 180, 0, 0, 75, 110, 157, 171, 224, 211, 253, 160, 189, 131, 6}, 215}, {{159, 15, 180, 0, 0, 103, 165, 60, 89, 45, 142, 205, 47, 208, 39, 34}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 7, 83}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 249, 210, 109, 37, 180}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 30, 5}, 215}, {{159, 15, 180, 0, 0, 0, 0, 29, 225, 166, 95, 155, 166, 189, 35, 70}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 105, 4, 13, 50, 25, 207}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 19, 70, 41}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 187, 203, 232, 160, 79, 151}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 249, 24, 159, 80, 210, 164, 40, 24}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 83, 27, 195, 57, 191}, 215}, {{159, 15, 180, 0, 87, 172, 154, 248, 126, 51, 193, 208, 89, 179, 224, 235}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 234, 108, 226, 112, 115, 51, 127, 5}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 244, 75, 46}, 215}, {{159, 15, 180, 0, 58, 240, 129, 126, 1, 213, 13, 216, 90, 29, 88, 106}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 75, 79, 239, 58, 29, 137, 166}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 180, 102, 76, 126, 8, 14, 139}, 215}, {{159, 15, 180, 0, 0, 218, 245, 95, 176, 83, 100, 112, 251, 191, 29, 58}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 147, 214, 175}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 231, 160, 181, 3, 216, 173, 98, 255}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 215}, {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 218, 139, 173, 11, 110}, 215}, {{159, 15, 180, 0, 0, 193, 206, 89, 176, 2, 223, 142, 167, 36, 88, 62}, 215}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 3, 18, 246}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 166, 245, 26, 214, 3}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 118, 47}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 57, 153, 59, 225}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 2}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 19, 59}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 53, 197, 244, 251, 201}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 241, 177, 107, 143, 241}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 193, 57, 49}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 48, 229, 36}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 87, 155, 59, 195, 14}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 170, 240}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 235}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 201, 21}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 81, 192}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 252, 252, 118}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 202, 14}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 224, 76, 168}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 100, 65, 168, 111, 56, 74}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 112, 249, 44, 205, 202}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 22, 166, 42}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 235}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 196, 72, 85, 120, 114}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 75, 76}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 154}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 138}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 66, 205, 36}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 38, 103, 74, 39, 156}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 90, 214, 161, 137}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 117, 48, 187, 104, 7}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 240, 183, 99, 185, 124, 217}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 202, 2, 155}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 208, 221, 217}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 130, 222, 202, 199, 134}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 230, 139}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 131, 98, 121}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 184, 102, 70, 143}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 95, 255, 181, 44}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 175, 173, 213}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 28, 112, 239}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 21, 222, 153, 205}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 134, 31, 159}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 117, 96, 156}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 54, 170, 177}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 112}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 176}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 106}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 212, 33, 112, 7}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 169, 134}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 244}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 221, 147}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 95, 163, 169, 13, 79}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 248}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 78, 68, 233}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 206}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 86, 237, 48, 230}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 73, 88, 138, 158, 138}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 107, 9, 44, 217}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 61, 235, 130}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 52, 61}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 7, 106}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 94}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 80, 170, 119}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 201}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 176, 236, 139, 58}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 216, 131}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 176, 48, 178, 7}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 78, 231, 91}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 101, 217, 30, 132, 186}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 13, 137, 105, 184}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 136}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 66, 46, 207}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 65, 218, 82}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 84, 245, 133, 188, 154}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 151, 131, 165, 40}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 113, 206, 222, 82, 76}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 243, 185, 236}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 234}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 198, 244, 167, 32, 170}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 42, 200, 68}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 88, 156, 76, 25, 211, 214}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 255, 191}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 42, 224}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 193, 212, 192, 198, 197}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 221, 205}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 135, 110}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 189, 226}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 191, 143}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 200}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 40, 91, 11, 5}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 234, 178, 117, 21}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 151, 254}, 249}, {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 73}, 249}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 149}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 152, 21, 254, 17}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 214, 164, 112}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 233, 45, 15}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 183, 63}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 76, 38, 210}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 11, 94, 17}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 102, 179, 220}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 74}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 24, 16, 165, 203}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 70}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 87, 159}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 160, 243, 85, 151}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 148, 174, 87}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 120}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 189, 186, 199, 56}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 64, 48, 106}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 110}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 227}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 252, 130, 96}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 136, 22, 192}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 192, 199, 133, 235}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 41, 171, 36, 106}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 158, 159}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 127, 28, 101}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 215, 145}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 64, 195, 210}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 17, 142, 53, 229}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 124, 227}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 86, 187}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 55, 97, 126}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 101, 206}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 52}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 119}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 88}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 93, 51, 101, 214}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 36, 220}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 66}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 211, 111, 238}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 82, 120}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 63}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 103, 226, 82, 188}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 87, 121, 242, 129}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 229, 73, 40, 85}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 229}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 116, 82, 179}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 127}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 76, 107}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 39, 229, 95, 99}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 164, 4, 196}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 196, 116}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 154}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 205, 6}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 158, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 152, 88, 157}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 201, 196, 125}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 191, 12}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 131, 35, 55, 88}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 207, 74, 143, 174}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 64}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 211}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 243, 9, 255}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 143}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 253, 100, 230}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 67, 178, 147, 38}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 18, 107}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 202, 246}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 253, 102, 112}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 22}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 52, 22, 170}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 156}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 1}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 155}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 199, 193, 148}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 148, 55, 67}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 36, 28, 202, 220}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 164, 23, 111}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 188, 43}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 250, 41, 204, 63}, 29}, {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 233, 130, 31, 145}, 29}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 65, 0, 123, 122, 69}, 71}, {{22, 185, 238, 100, 25, 16, 0, 83, 218, 101, 87, 193, 165, 43, 132, 249}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 197, 137, 239, 64, 159, 156, 34}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 203, 198, 107}, 71}, {{22, 185, 238, 100, 25, 16, 0, 91, 44, 190, 123, 64, 4, 151, 159, 242}, 71}, {{22, 185, 238, 100, 25, 16, 0, 152, 206, 204, 102, 178, 138, 9, 233, 95}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 218, 129, 23, 26}, 71}, {{22, 185, 238, 100, 25, 16, 0, 3, 65, 57, 110, 230, 122, 22, 233, 121}, 71}, {{22, 185, 238, 100, 25, 16, 0, 50, 187, 106, 107, 254, 126, 78, 238, 169}, 71}, {{22, 185, 238, 100, 25, 16, 0, 72, 127, 62, 135, 131, 251, 144, 126, 241}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 71}, {{22, 185, 238, 100, 25, 16, 193, 177, 108, 77, 164, 109, 226, 22, 68, 169}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 228, 221, 5, 4, 238, 28, 26}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 123, 73, 215, 183, 196, 249, 171}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 209, 92, 27, 246, 92, 62, 253}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 163, 205, 17, 249, 138}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 177, 188, 112, 149, 31}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 21, 1, 231}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 142, 143}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 71}, {{22, 185, 238, 100, 25, 16, 0, 6, 44, 209, 152, 86, 183, 38, 202, 244}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 18, 55, 58, 64, 137}, 71}, {{22, 185, 238, 100, 25, 16, 0, 102, 69, 247, 135, 96, 180, 200, 190, 217}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 84, 140, 10, 224, 9, 160}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 181, 17, 86, 46}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 102, 40, 182}, 71}, {{22, 185, 238, 100, 25, 16, 0, 81, 190, 79, 60, 196, 49, 94, 80, 181}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 154, 228, 224, 217, 201, 83}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 193, 36, 181, 163, 16, 88, 224}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 137, 159, 213, 164, 243, 191, 183}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 209, 100, 125, 36, 130, 93, 22}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 208, 219, 135, 53, 159, 138}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 133, 178, 89}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 85, 13, 62, 11, 195, 76, 149, 187}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 214, 82, 32}, 71}, {{22, 185, 238, 100, 25, 16, 143, 144, 83, 134, 226, 249, 52, 63, 99, 150}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 182, 47, 169, 116}, 71}, {{22, 185, 238, 100, 25, 16, 0, 207, 105, 29, 3, 107, 157, 110, 237, 183}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 46, 31, 113, 128, 169, 247}, 71}, {{22, 185, 238, 100, 25, 16, 0, 144, 173, 70, 81, 157, 151, 50, 166, 219}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 231, 202, 23, 28, 15, 42, 76, 206}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 26, 130, 118, 80, 211, 180, 18, 210}, 71}, {{22, 185, 238, 100, 25, 16, 0, 184, 134, 165, 104, 187, 45, 125, 169, 159}, 71}, {{22, 185, 238, 100, 25, 16, 0, 52, 196, 132, 153, 186, 11, 36, 75, 58}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 23, 170, 242, 231, 236, 11, 43, 28}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 219, 93}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 142, 102, 10, 254, 132, 101, 20, 230}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 112, 207, 79, 179, 225, 129, 100}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 223, 10, 39, 85, 116, 51, 249, 160}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 17, 214, 185, 48}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 92, 35, 202}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 197, 197, 140, 30, 218, 234}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 125, 239, 4, 67, 58, 73}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 104, 190, 136, 61, 199, 141, 161}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 158, 52, 35, 76, 124, 29, 179}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 37, 247, 199, 253}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 40, 157}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 156, 208, 77}, 71}, {{22, 185, 238, 100, 25, 16, 68, 169, 233, 237, 104, 106, 220, 195, 108, 128}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 32, 35, 194, 68, 224}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 62, 70, 192, 254, 128, 93, 104, 48}, 71}, {{22, 185, 238, 100, 25, 16, 203, 33, 224, 222, 204, 63, 184, 253, 146, 154}, 71}, {{22, 185, 238, 100, 25, 16, 0, 188, 182, 181, 254, 77, 103, 58, 112, 76}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 20, 53, 88}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 152, 178, 232, 3, 200}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 160, 93, 221, 133, 205, 11, 104, 163}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 82, 188, 36, 236, 12}, 71}, {{22, 185, 238, 100, 25, 16, 0, 55, 72, 143, 238, 102, 86, 36, 53, 68}, 71}, {{22, 185, 238, 100, 25, 16, 0, 246, 244, 43, 226, 190, 69, 129, 205, 178}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 136, 109, 29}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 14, 22}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 33, 9}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 175, 111}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 121, 84}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 69, 237, 2, 18, 16}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 168, 199, 35, 28, 115}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 71}, {{22, 185, 238, 100, 25, 16, 0, 104, 39, 169, 250, 154, 186, 238, 163, 84}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 69, 149, 144, 246, 43, 223}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 199, 21, 67, 221, 76}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 24, 152, 19, 41, 28}, 71}, {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 10, 83, 70, 116, 59, 212}, 71}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 112}, {{93, 152, 229, 140, 0, 0, 0, 56, 235, 123, 219, 81, 158, 255, 32, 19}, 72}, {{93, 152, 229, 140, 0, 0, 0, 102, 58, 254, 62, 9, 205, 242, 117, 12}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 163, 189}, 72}, {{93, 152, 229, 140, 0, 44, 129, 51, 220, 233, 234, 110, 68, 34, 61, 201}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 249, 218}, 72}, {{93, 152, 229, 140, 0, 76, 244, 254, 9, 169, 137, 135, 154, 248, 172, 63}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 104, 44, 139, 120, 140, 125, 50, 28}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 168, 91, 239, 255, 132, 33, 171, 43}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 224}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 112}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 47, 237, 71, 139, 14, 162}, 72}, {{93, 152, 229, 140, 0, 0, 0, 235, 93, 85, 83, 154, 214, 98, 222, 8}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 102, 5, 161, 149, 165, 27, 82, 55}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 81, 230, 204, 247, 237, 158, 196}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 72}, {{93, 152, 229, 140, 0, 0, 0, 168, 64, 153, 56, 230, 66, 222, 218, 224}, 72}, {{93, 152, 229, 140, 0, 0, 0, 18, 206, 140, 201, 171, 205, 33, 12, 201}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 107, 9, 94, 134, 117, 181}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 179, 129, 195, 140, 139, 3}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 77, 163, 26, 190, 95, 154, 7, 56}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 73}, 72}, {{93, 152, 229, 140, 0, 0, 0, 218, 135, 214, 112, 6, 204, 146, 51, 23}, 72}, {{93, 152, 229, 140, 0, 0, 195, 253, 219, 90, 31, 147, 140, 239, 151, 93}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 30, 176, 211, 254, 146}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 198, 15, 157, 164, 175, 215, 84}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 234, 107, 62, 30, 45, 153, 89, 150}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 170, 162}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 1, 206, 162, 206, 185}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 191, 158}, 72}, {{93, 152, 229, 140, 0, 0, 0, 147, 63, 99, 93, 68, 208, 45, 223, 167}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 188, 73, 205, 103, 18, 59, 45}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 2, 184, 190, 127, 244, 169, 68, 19}, 72}, {{93, 152, 229, 140, 0, 0, 0, 43, 236, 183, 223, 207, 174, 137, 165, 224}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 221, 238, 131, 103, 70}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 131, 250, 29, 128, 54, 135}, 72}, {{93, 152, 229, 140, 0, 180, 129, 152, 106, 71, 38, 187, 89, 209, 193, 47}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 4}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 4}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 239, 25, 41, 130, 56}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 193, 29, 211, 195, 221, 241, 18, 126}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 218, 172, 218, 179, 55, 44, 171}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 191, 152, 18, 135, 18}, 72}, {{93, 152, 229, 140, 0, 0, 206, 69, 78, 79, 178, 74, 53, 194, 104, 244}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 15, 254, 23, 58}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 72}, {{93, 152, 229, 140, 0, 0, 0, 215, 179, 91, 67, 106, 77, 5, 120, 115}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 188, 186, 43, 28, 48, 182, 175, 163}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 73, 48, 1, 225, 86}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 19, 73, 104, 212, 110}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 72}, {{93, 152, 229, 140, 0, 0, 243, 73, 101, 97, 226, 37, 133, 241, 254, 154}, 72}, {{93, 152, 229, 140, 0, 66, 188, 103, 25, 163, 94, 139, 225, 176, 188, 178}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 10, 23, 135, 144, 80, 209, 229, 233}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 118}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 148, 171}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 9, 63, 5, 241, 212}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 139, 113, 20, 184, 57, 135, 155}, 72}, {{93, 152, 229, 140, 0, 0, 177, 71, 171, 145, 52, 81, 161, 122, 246, 21}, 72}, {{93, 152, 229, 140, 0, 0, 229, 44, 56, 252, 9, 207, 241, 112, 248, 24}, 72}, {{93, 152, 229, 140, 0, 0, 0, 51, 176, 165, 110, 52, 212, 206, 124, 106}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 210, 52, 136, 202, 70}, 72}, {{93, 152, 229, 140, 0, 171, 34, 94, 3, 195, 68, 236, 58, 85, 181, 38}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 91, 151, 248, 50, 61, 247, 69}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 73}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 112}, 72}, {{93, 152, 229, 140, 0, 0, 43, 58, 111, 14, 126, 8, 59, 183, 167, 159}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 201, 12, 50, 173, 16, 5}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 84, 130, 71, 200, 57, 194, 69, 173}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 60, 155, 207, 93}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 36, 250, 209, 108, 73, 143, 138, 209}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 134, 125}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 71}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 246, 4, 68, 152, 173, 218}, 72}, {{93, 152, 229, 140, 0, 127, 235, 208, 178, 172, 209, 131, 198, 134, 191, 228}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 224, 36, 68, 230, 249, 189}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 72}, {{93, 152, 229, 140, 0, 0, 0, 190, 195, 137, 217, 143, 31, 3, 254, 92}, 72}, {{93, 152, 229, 140, 0, 0, 96, 3, 250, 3, 244, 221, 44, 17, 98, 156}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 159, 183, 45, 90, 174, 236}, 72}, {{93, 152, 229, 140, 0, 127, 176, 57, 175, 81, 1, 18, 196, 131, 6, 86}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 198}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 158, 33, 247, 127, 103}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 158, 248, 19, 215, 167, 65}, 72}, {{93, 152, 229, 140, 0, 0, 0, 0, 0, 39, 188, 114, 53, 77, 119, 13}, 72}, {{93, 152, 229, 140, 0, 0, 122, 32, 80, 115, 170, 220, 158, 105, 142, 217}, 72}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 137, 67, 59, 235, 209}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 139, 141, 203}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 114, 244}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 3, 6}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 14}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 82, 123, 77, 122, 226}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 195, 10, 173, 175}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 59}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 61, 93, 246, 241, 65}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 174, 17, 186}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 135, 130, 138, 229}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 79, 133, 120, 45}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 117, 154}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 193, 117, 199}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 102, 214, 227, 41}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 57, 41, 153, 155}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 21, 169}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 34, 142, 54, 249, 202}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 148, 218, 104, 78}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 137, 234, 46}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 128, 223, 245, 63, 135, 11}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 11, 130, 18, 132, 72}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 234, 195}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 51, 202, 87, 191, 63}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 83, 103, 119, 115}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 181}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 135, 131, 253, 230, 74, 240}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 155, 223, 59}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 43, 197, 72, 253}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 29, 250, 220, 145}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 1}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 155, 242, 2}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 195}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 243, 249, 226}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 213, 195}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 246, 245}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 227, 151, 68, 223, 2}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 244, 165}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 133, 55}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 9, 216, 135, 75, 65, 171}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 75}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 111}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 112, 85}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 52}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 100}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 49}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 76, 178, 100, 167}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 205, 22, 154, 232, 136}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 50}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 148, 75, 43, 172, 254, 18}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 118, 153, 196, 207}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 41, 181}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 37, 50, 18}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 254, 38}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 183, 126}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 215, 75, 130, 128}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 254, 208, 238, 193, 238, 159}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 1}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 179, 155}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 231, 46, 117, 34}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 158, 185, 241}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 15, 62, 52, 143}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 78, 140}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 139, 182, 255, 18}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 239}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 163, 233}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 26, 194}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 8}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 25, 125, 96, 66}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 240, 62, 0, 16, 166, 238}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 227, 144, 66, 115}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 174, 86, 148, 128, 25}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 40, 59}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 175, 175, 200, 211}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 37, 170, 225, 30, 121, 152}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 105, 143, 4, 180}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 137, 200, 240, 194, 195, 135}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 147, 197, 11, 229}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 245}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 74}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 1}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 135}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 112}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 34, 143}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 132, 78, 66}, 155}, {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 155}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 143, 175}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 68, 208}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 3}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 232, 145, 180}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 152, 135, 251}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 212, 129, 206, 194, 168, 106, 204}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 117, 95, 202, 75, 92, 184}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 93, 199, 72, 178}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 79, 229, 235}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 182, 118, 149, 72}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 29, 224, 101, 174}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 249, 40, 72, 148, 54, 131, 76}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 32, 181, 60, 222}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 79, 251}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 182, 233, 250}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 243, 181, 134, 135, 74, 243}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 251}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 214, 68, 44, 71, 154}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 65, 125, 24, 12, 27, 5}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 152}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 57, 73, 24, 140, 239, 24, 102}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 126, 158, 144, 198}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 236, 166, 35}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 192, 157, 234, 244, 214}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 241, 223, 252, 91}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 128, 79, 135, 86, 21}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 32, 74, 208, 252, 129, 114}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 143, 234, 113, 195, 192, 183, 219}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 253}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 3, 94, 60, 215, 224, 197, 60, 89}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 62, 147, 164, 252}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 220, 12, 241, 19, 155}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 44, 208, 107, 117}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 44, 39, 131}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 69, 106}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 175, 208, 136}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 9}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 162, 32, 174, 121, 129, 73}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 222, 143, 24}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 155}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 186}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 24, 154, 195, 144}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 174, 204, 45}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 37, 191, 37, 94}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 88, 200, 107, 62, 63}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 49, 23, 39, 17, 121, 39, 164}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 97, 24}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 133, 214, 175, 141, 161, 244}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 134, 151, 254, 222, 236, 208, 176}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 109, 63, 33, 7}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 184, 43}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 67}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 170, 203, 181, 254, 198, 173}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 91}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 80, 86, 252}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 230, 13, 79}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 21, 102, 68, 136, 161, 158}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 215, 151, 169, 4}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 85}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 188, 218, 16}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 76, 6, 73, 177, 164, 94}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 237, 7, 182, 107, 137, 84}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 89, 3, 119, 87}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 14, 175}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 224, 103, 94, 28, 19}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 213, 132, 98, 207}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 99}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 206, 203, 60, 20}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 173}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 38, 42, 22, 148, 164, 112, 156}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 112, 123, 37, 209, 204, 120, 75, 133}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 67, 10, 196, 184}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 131, 176, 222, 44}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 64, 41, 252, 166, 86, 12}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 74}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 161}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 28, 177, 139, 3, 121, 140}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 190, 164, 241, 169, 47, 159}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 20, 167, 61, 42, 56, 88, 82}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 142, 64, 13, 245}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 229, 145, 129, 128, 228}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 55, 89, 175, 28}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 204, 117, 90, 59}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 222, 11, 209}, 66}, {{30, 202, 177, 3, 253, 202, 164, 248, 190, 1, 58, 99, 37, 27, 62, 56}, 66}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 105, 33, 107, 18}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 110, 181, 62, 241}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 59}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 199, 155, 211}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 69, 48}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 116, 232, 68}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 48, 210, 173}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 173, 55}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 9, 71}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 197, 202}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 140}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 188, 249, 157, 243}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 130, 88, 181}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 182}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 38, 233, 172}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 22}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 78}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 69, 157, 217}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 218, 107, 154}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 8, 145}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 220, 13, 247}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 126}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 73}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 2, 140, 24, 17}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 7, 42, 58}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 53}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 34, 198}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 30, 85}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 38, 69}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 49, 17, 100}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 73, 175}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 178, 6, 139}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 180}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 145}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 235, 184, 143}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 136, 217}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 236}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 217, 128, 54}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 77, 51}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 191}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 71}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 67, 197, 54, 169}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 10, 30}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 40, 184, 158, 7}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 53, 191, 106}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 123, 211, 40}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 235}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 183}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 81}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 233, 95}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 64, 227}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 93, 154, 144}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 32}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 143, 79, 66}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 112}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 193, 202}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 240}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 111, 38, 250}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 242, 67}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 26}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 187}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 34}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 228, 149}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 22, 1, 132, 154}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 54, 62, 200}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 133, 117, 73}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 172, 70}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 212, 47}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 86, 111, 194, 92}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 232, 171, 101}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 141, 123, 164}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 106, 228, 9, 6}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 230, 93}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 188, 203, 138, 211}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 217, 66}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 170, 231, 197}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 98, 200, 182}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 77}, {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 234, 136, 2, 118}, 77}, {{96, 0, 0, 0, 0, 59, 75, 191, 198, 130, 30, 46, 171, 113, 205, 54}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 198, 6, 148, 97}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 119, 141}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 109}, {{96, 0, 0, 0, 0, 0, 76, 195, 207, 117, 177, 64, 218, 40, 18, 116}, 109}, {{96, 0, 0, 0, 0, 149, 56, 79, 86, 166, 231, 22, 103, 107, 210, 70}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 90, 43, 217, 250, 239, 38, 81}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 104, 176, 171}, 109}, {{96, 0, 0, 0, 208, 189, 137, 31, 91, 181, 232, 98, 80, 105, 208, 112}, 109}, {{96, 0, 0, 0, 0, 0, 59, 233, 247, 159, 187, 21, 245, 65, 58, 227}, 109}, {{96, 0, 0, 120, 249, 158, 86, 40, 153, 200, 172, 230, 52, 20, 253, 226}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 57, 226, 113}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 64, 115}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 253, 202, 241}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 50, 88, 193, 152, 194}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 89, 170, 104, 46, 176}, 109}, {{96, 0, 0, 0, 0, 0, 132, 26, 242, 106, 43, 140, 5, 177, 85, 252}, 109}, {{96, 0, 0, 0, 0, 45, 109, 96, 117, 238, 95, 142, 234, 5, 154, 12}, 109}, {{96, 0, 0, 169, 101, 41, 68, 19, 175, 58, 206, 47, 74, 151, 38, 205}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 19, 179, 181, 51, 26}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 187, 228, 152, 205, 163, 191, 122, 86}, 109}, {{96, 0, 0, 0, 0, 0, 18, 35, 22, 139, 126, 59, 97, 173, 178, 51}, 109}, {{96, 0, 0, 230, 199, 254, 185, 16, 68, 161, 105, 24, 146, 197, 89, 247}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 217}, 109}, {{96, 0, 0, 0, 0, 135, 63, 152, 172, 66, 192, 96, 167, 122, 215, 199}, 109}, {{96, 0, 133, 56, 80, 82, 32, 3, 216, 92, 186, 186, 155, 79, 45, 159}, 109}, {{96, 0, 0, 0, 0, 1, 56, 64, 48, 44, 34, 227, 66, 180, 97, 198}, 109}, {{96, 0, 0, 0, 7, 192, 255, 192, 32, 0, 220, 135, 167, 74, 27, 61}, 109}, {{96, 0, 0, 0, 25, 41, 93, 246, 6, 158, 188, 249, 62, 215, 172, 15}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 95, 237, 203}, 109}, {{96, 0, 0, 0, 0, 245, 38, 66, 135, 26, 121, 245, 5, 143, 162, 23}, 109}, {{96, 0, 0, 0, 0, 0, 0, 75, 86, 8, 242, 210, 68, 124, 199, 27}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 250, 247, 194, 200, 246, 33, 191, 53, 202, 152, 102}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 50, 48, 117}, 109}, {{96, 0, 135, 228, 40, 144, 105, 45, 68, 99, 168, 248, 237, 139, 101, 38}, 109}, {{96, 0, 0, 0, 0, 0, 0, 227, 29, 158, 27, 192, 134, 187, 211, 176}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 197, 107, 27}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 63, 205, 118, 68, 99, 241, 129, 107, 101}, 109}, {{96, 0, 0, 0, 0, 0, 198, 216, 170, 43, 26, 77, 187, 53, 209, 167}, 109}, {{96, 0, 0, 182, 229, 136, 32, 160, 138, 214, 189, 174, 240, 207, 242, 155}, 109}, {{96, 0, 32, 251, 66, 137, 16, 25, 153, 234, 115, 65, 135, 215, 44, 45}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 150, 51, 224, 30, 213, 166, 218, 236}, 109}, {{96, 0, 0, 0, 136, 94, 89, 57, 234, 117, 162, 25, 173, 29, 235, 222}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 109}, {{96, 0, 224, 250, 141, 4, 238, 226, 191, 141, 101, 98, 100, 97, 4, 40}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 220, 113, 196, 11}, 109}, {{96, 0, 0, 0, 0, 57, 246, 239, 32, 136, 177, 103, 120, 112, 255, 60}, 109}, {{96, 0, 0, 0, 0, 0, 0, 107, 111, 105, 20, 179, 108, 47, 27, 186}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 80, 54, 225, 18, 145, 69, 36}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 245, 156, 183, 80, 135, 243, 72, 102}, 109}, {{96, 0, 0, 0, 0, 0, 33, 244, 129, 154, 134, 185, 229, 40, 161, 202}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 11, 9, 156}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 211, 183, 196, 181}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 21, 106, 201}, 109}, {{96, 0, 0, 0, 0, 0, 70, 72, 145, 228, 20, 224, 185, 233, 54, 40}, 109}, {{96, 247, 57, 226, 91, 0, 142, 232, 108, 13, 155, 176, 81, 61, 243, 118}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 194, 28, 130, 103, 245, 104, 117, 183}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 232, 12, 58}, 109}, {{96, 0, 175, 128, 254, 156, 21, 128, 172, 110, 205, 138, 147, 73, 70, 86}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 43, 173, 163, 225, 193, 242, 28, 11}, 109}, {{96, 0, 0, 0, 0, 0, 0, 67, 232, 235, 203, 216, 68, 129, 223, 71}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 204, 207, 143}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 201, 168, 136, 114, 193, 84, 236}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 245}, 109}, {{96, 0, 0, 0, 0, 249, 250, 162, 198, 217, 87, 173, 34, 66, 98, 188}, 109}, {{96, 0, 0, 0, 122, 117, 225, 44, 238, 223, 113, 48, 146, 227, 186, 198}, 109}, {{96, 0, 0, 0, 0, 110, 6, 6, 112, 33, 19, 77, 101, 66, 101, 75}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 83, 149, 104}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 165, 93, 53, 188}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 58, 162, 98, 228, 57}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 226, 18, 162, 37, 50, 203, 133}, 109}, {{96, 0, 0, 0, 0, 0, 180, 172, 136, 3, 151, 205, 231, 5, 7, 15}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 27, 135, 85, 5, 236, 7, 119}, 109}, {{96, 0, 106, 80, 135, 138, 93, 217, 203, 143, 249, 183, 163, 171, 33, 127}, 109}, {{96, 0, 0, 0, 0, 236, 117, 94, 204, 223, 4, 71, 205, 221, 48, 189}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 191, 100, 148, 9, 210}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 43, 67, 240, 120}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 106, 77}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 20, 240, 131, 180, 147}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 4, 122, 67, 129, 188, 167, 39, 40}, 109}, {{96, 181, 223, 177, 190, 59, 143, 141, 132, 218, 154, 5, 22, 141, 223, 35}, 109}, {{96, 0, 0, 203, 43, 46, 106, 138, 253, 244, 13, 196, 65, 175, 100, 142}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 216, 51}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 124, 159, 155}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 163, 204}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 20, 232, 185}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 126, 55, 4, 9, 119}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 109}, {{96, 0, 0, 190, 128, 81, 10, 220, 56, 237, 86, 211, 149, 79, 99, 212}, 109}, {{96, 0, 0, 0, 0, 0, 189, 105, 154, 5, 234, 170, 203, 211, 250, 192}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 212, 28, 7, 39}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 119, 175, 208, 170, 16}, 109}, {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 35}, 109}, {{96, 74, 211, 141, 155, 7, 185, 214, 27, 100, 97, 7, 43, 41, 14, 48}, 109}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 191, 213}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 76, 203, 190, 239, 10}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 33, 97, 97, 246}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 31, 209, 62, 70, 5}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 109, 225, 71, 252}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 13, 52, 214, 78, 180}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 212, 142, 91, 99}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 61, 74}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 249, 216, 42, 102, 198}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 32, 239, 210, 249, 96}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 209, 71, 158, 5}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 113, 135, 48, 138, 23, 112}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 53, 42}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 46, 162, 249, 185, 169}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 97}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 117, 37}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 107, 34}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 142}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 168, 100}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 228, 169}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 62, 169, 10, 178, 143}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 217, 78, 136, 15}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 156, 142, 138, 18}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 81, 131, 223, 77, 102, 234}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 252, 117, 152, 162}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 164, 227, 130, 203}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 248, 171}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 176, 195, 203, 2, 20}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 152, 196, 126, 102, 190, 252}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 161}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 113, 61, 199, 4, 127, 124}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 211, 100}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 43, 234, 169, 217, 252, 31}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 75, 57, 240, 10, 131, 135}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 149, 124, 248}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 139, 18, 39, 149, 226, 160}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 33, 105, 255}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 239, 235, 165, 246, 84, 253}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 174, 221, 29, 40}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 47, 90, 52, 48, 25}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 192, 199, 254, 9}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 229, 215, 68, 208, 43}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 181, 75, 251, 164, 153}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 92}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 107}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 220}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 185, 237, 216, 29}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 200, 14, 128}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 42, 140, 44}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 72, 203, 252, 181}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 208}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 84, 15, 88, 210}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 18, 185, 12, 62, 131, 210}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 164, 219, 32, 81, 89}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 155, 168, 224, 242}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 44, 9, 151}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 233}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 14, 233, 187}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 74, 1, 79, 92, 74, 202}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 216, 159, 142}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 89, 61, 226, 226}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 62, 116, 126, 207, 54}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 51, 123, 183}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 221, 141, 116, 232, 101, 54}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 39, 66, 222, 118, 184, 180}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 211, 213, 24, 209}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 144, 236}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 190, 255}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 94}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 50, 161, 60, 195, 212, 91}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 211, 69, 19}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 229, 66}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 70, 14, 253, 237, 243, 69}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 57}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 2, 142}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 110, 79, 132, 130}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 235}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 174, 10}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 75, 48}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 129, 245}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 185, 243}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 165, 233, 4}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 251, 109, 146, 131, 198, 150}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 115}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 51, 174, 209, 168}, 37}, {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 163, 62}, 37}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 184, 114, 47, 161}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 146, 182, 188, 222}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 87, 170}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 122, 247, 79}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 126, 45}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 182, 27, 75, 176}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 252, 95, 74}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 235, 242}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 132}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 92, 12, 73, 122}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 102, 248, 137}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 206, 123, 19}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 172, 162, 134}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 255}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 167, 13, 146, 122}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 207, 238}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 100, 162, 93}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 100, 154, 129}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 136, 232}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 82, 91}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 232, 100, 47}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 248, 79, 183, 2}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 230}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 76, 134, 204, 223}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 61}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 230}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 194, 130, 202, 244}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 65, 96, 79, 196}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 254, 31, 226}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 86}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 125, 165, 104, 126}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 247}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 120}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 211}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 117, 144, 185}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 123}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 113, 255}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 218, 172, 223, 60}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 64, 206, 211, 187}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 236, 135, 84}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 157, 128, 50, 62}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 83, 108}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 230}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 31, 146}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 103, 191}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 76}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 241, 52}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 174, 151, 26, 21}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 48}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 100, 213, 59, 129}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 176, 87}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 212, 177}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 25, 249}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 27, 181}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 232}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 52}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 136, 204, 179}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 247}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 240, 234}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 232, 47, 4, 170}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 81}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 120}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 142, 12, 125}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 101}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 172}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 39, 93, 217, 17}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 172, 222, 155}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 252}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 249}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 94, 85}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 122, 109}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 33, 116, 127}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 214}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 9, 3}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 192, 100}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 231, 41, 185}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 49, 164}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 2}, 56}, {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 32, 154}, 56}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 84}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 242}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 176}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 122}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 138, 228}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 62}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 162, 150}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 144}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 68}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 73}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 64}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 235}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 92, 2}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 149}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 60, 134}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 107}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 220}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 126, 116}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 152, 253}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 95}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 64}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 200, 158}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 252}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 89}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 91}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 151}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 208, 118}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 241}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 196}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 147, 144}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 131, 48}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 218}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 115}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 44}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 44}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 30, 72}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 37}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 123, 100, 175}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 183}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 70, 62}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 59}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 121, 41}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 190}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 18}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 92, 72}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 174, 17}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 8}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 30, 113}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 36, 234}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 22, 118, 32}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 2}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 122, 102}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 34}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 197, 219}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 207, 35}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 32, 139}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 13}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 5}, {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 10}, 5}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 213, 186, 60, 154, 148}, 15}, {{62, 128, 139, 128, 71, 22, 241, 219, 143, 63, 67, 37, 226, 105, 157, 233}, 15}, {{62, 128, 139, 128, 191, 101, 145, 14, 92, 10, 128, 233, 153, 133, 62, 243}, 15}, {{62, 128, 139, 128, 0, 0, 0, 21, 173, 249, 81, 144, 172, 35, 71, 117}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 225, 139, 255, 58, 118, 9}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 172, 76, 213, 170, 68, 151}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 38, 40, 3, 213, 80, 41}, 15}, {{62, 128, 139, 128, 137, 19, 205, 102, 71, 159, 144, 90, 9, 42, 57, 246}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 86, 80, 47, 9, 187, 68, 196, 194}, 15}, {{62, 128, 139, 128, 0, 99, 202, 219, 3, 6, 221, 72, 132, 20, 247, 235}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 67, 222, 234, 233, 165, 252, 233, 128, 233}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 56}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 102, 85, 63, 10, 127, 21}, 15}, {{62, 128, 139, 128, 74, 142, 35, 92, 240, 189, 85, 86, 225, 247, 242, 193}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 152, 25, 173, 154, 17, 225, 106}, 15}, {{62, 128, 139, 128, 0, 179, 185, 51, 251, 212, 149, 133, 170, 78, 187, 200}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 122, 108, 147, 121, 62, 9, 7}, 15}, {{62, 128, 139, 128, 0, 0, 0, 100, 134, 46, 38, 9, 172, 23, 126, 69}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 102}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 52, 171, 51, 127, 47, 111, 249}, 15}, {{62, 128, 139, 128, 0, 0, 0, 197, 52, 90, 96, 9, 10, 51, 172, 20}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 82}, 15}, {{62, 128, 139, 128, 0, 0, 17, 41, 178, 195, 126, 234, 134, 249, 56, 149}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 182, 65}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 225, 29, 123, 60, 217, 9, 23}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 53}, 15}, {{62, 128, 139, 128, 0, 0, 0, 195, 193, 132, 232, 218, 126, 70, 33, 126}, 15}, {{62, 128, 139, 128, 170, 186, 64, 40, 166, 205, 92, 5, 140, 125, 150, 98}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 175, 20, 202, 23, 171, 166, 234}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 15}, {{62, 128, 139, 128, 66, 197, 64, 40, 213, 36, 214, 233, 188, 68, 130, 154}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 48, 34, 62, 211, 80}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 93, 24, 234, 27, 119, 203, 129}, 15}, {{62, 128, 139, 128, 175, 233, 115, 196, 97, 105, 80, 208, 204, 152, 130, 42}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 119}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 252, 239, 41, 26}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 186, 228, 185, 162, 162, 167, 136}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 19, 188, 56, 201, 239, 164, 212, 138}, 15}, {{62, 128, 139, 128, 0, 0, 149, 57, 18, 249, 200, 8, 54, 233, 99, 43}, 15}, {{62, 128, 139, 128, 0, 0, 60, 104, 97, 80, 249, 122, 80, 122, 154, 71}, 15}, {{62, 128, 139, 128, 0, 0, 167, 185, 207, 88, 219, 127, 233, 162, 56, 252}, 15}, {{62, 128, 139, 128, 205, 108, 224, 35, 112, 80, 85, 120, 24, 14, 210, 204}, 15}, {{62, 128, 139, 128, 0, 38, 26, 21, 204, 163, 247, 70, 114, 71, 65, 89}, 15}, {{62, 128, 139, 128, 0, 0, 86, 171, 44, 12, 150, 113, 63, 228, 23, 80}, 15}, {{62, 128, 139, 128, 0, 0, 85, 188, 142, 196, 220, 66, 154, 189, 36, 199}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 69, 29, 248, 178, 84, 180, 11, 86}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 37, 225, 225, 133, 45, 141, 9, 43}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 193, 150, 235, 210, 181, 247}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 171}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 79, 198, 86, 222, 120, 198, 164, 183}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 39, 11, 17, 87, 214}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 206, 136, 82, 19, 147, 195, 96, 91}, 15}, {{62, 128, 139, 128, 0, 21, 137, 251, 49, 190, 242, 206, 161, 181, 108, 66}, 15}, {{62, 128, 139, 128, 0, 0, 141, 163, 83, 125, 211, 241, 57, 151, 135, 255}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 193, 196, 225, 126, 99}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 234, 12, 55, 3, 100, 29}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 6, 96, 217, 224, 156, 23, 155, 91}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 84, 11}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 222, 33, 48, 127, 58, 60, 219, 134}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 203, 214, 96, 5, 100, 140}, 15}, {{62, 128, 139, 128, 0, 21, 100, 16, 228, 141, 68, 34, 231, 244, 161, 16}, 15}, {{62, 128, 139, 128, 0, 0, 151, 243, 60, 28, 223, 170, 204, 138, 97, 23}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 11, 209}, 15}, {{62, 128, 139, 128, 0, 36, 236, 77, 202, 154, 247, 82, 218, 245, 45, 120}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 85, 205, 222, 141}, 15}, {{62, 128, 139, 128, 0, 0, 159, 174, 9, 224, 58, 30, 174, 215, 99, 162}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 148, 209, 120, 162, 114}, 15}, {{62, 128, 139, 128, 0, 0, 21, 213, 89, 130, 126, 72, 60, 234, 27, 161}, 15}, {{62, 128, 139, 128, 245, 233, 49, 22, 14, 205, 177, 244, 80, 84, 246, 38}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 160, 150, 219, 140, 202, 99, 221, 190, 178, 64, 0, 245}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 46, 188}, 15}, {{62, 128, 139, 128, 0, 0, 0, 31, 57, 253, 140, 218, 162, 120, 187, 181}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 190, 183, 39, 156, 213}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 76}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 92, 93, 10, 157, 186}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 150, 210}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 66, 138, 34, 76, 167, 221}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 215, 39, 134, 52, 68}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 95, 233, 81, 183, 29, 223}, 15}, {{62, 128, 139, 128, 0, 3, 84, 62, 120, 229, 93, 132, 122, 172, 140, 91}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{62, 128, 139, 128, 0, 78, 88, 181, 178, 148, 6, 47, 194, 46, 67, 194}, 15}, {{62, 128, 139, 128, 0, 0, 0, 0, 0, 182, 97, 228, 51, 50, 7, 108}, 15}, {{214, 1, 84, 232, 0, 0, 0, 0, 79, 194, 184, 245, 164, 243, 225, 88}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 220, 145}, 183}, {{214, 1, 84, 232, 0, 0, 229, 15, 18, 95, 195, 179, 246, 77, 59, 66}, 183}, {{214, 1, 84, 232, 0, 0, 20, 224, 79, 209, 229, 139, 188, 40, 59, 238}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 129, 53, 65, 205, 69, 58}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 208, 117, 129, 91, 149, 144}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 57, 125, 78, 85, 16, 118}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 187}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 177, 53, 80, 178, 139, 133, 131, 55}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 186, 179, 253, 178, 125, 124}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 96, 93, 72, 240}, 183}, {{214, 1, 84, 232, 0, 114, 200, 167, 221, 179, 230, 224, 79, 22, 77, 141}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 118, 138, 174, 209, 253, 117, 30, 83, 115, 180}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 121}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 241, 177, 1, 122, 74, 13, 52, 21}, 183}, {{214, 1, 84, 232, 69, 241, 70, 43, 107, 204, 103, 176, 112, 176, 239, 41}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 229, 117}, 183}, {{214, 1, 84, 232, 0, 0, 0, 2, 145, 148, 41, 153, 183, 231, 74, 162}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 254}, 183}, {{214, 1, 84, 232, 229, 228, 224, 117, 44, 200, 92, 122, 48, 205, 125, 200}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 124, 100, 84, 121, 134, 57}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 255, 251}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 164, 168, 244, 186, 123, 57, 196}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 114, 137, 145, 28, 1}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 128, 172, 47, 136, 127, 104, 59, 42, 62, 55}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 103}, 183}, {{214, 1, 84, 232, 0, 110, 14, 180, 46, 86, 70, 108, 233, 219, 58, 181}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 237, 29, 9, 140}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 46, 127, 66, 119, 10, 137, 254, 242}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 221, 62, 200, 38, 23, 26}, 183}, {{214, 1, 84, 232, 0, 0, 152, 112, 138, 53, 41, 166, 20, 245, 0, 65}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 187, 162, 12, 43, 20, 21, 30}, 183}, {{214, 1, 84, 232, 0, 0, 226, 239, 17, 234, 54, 234, 165, 219, 223, 80}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 251, 182, 193, 68, 237, 201}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 183, 205, 138, 119, 27, 14, 22, 66}, 183}, {{214, 1, 84, 232, 0, 134, 176, 15, 179, 28, 199, 247, 245, 49, 18, 89}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 164, 14, 210, 43, 240, 159, 239, 207}, 183}, {{214, 1, 84, 232, 0, 0, 0, 110, 147, 19, 53, 120, 194, 244, 88, 39}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 114, 132, 195, 235, 161, 211, 215, 71}, 183}, {{214, 1, 84, 232, 0, 0, 16, 204, 62, 14, 252, 52, 244, 34, 80, 164}, 183}, {{214, 1, 84, 232, 0, 105, 89, 232, 131, 220, 217, 6, 198, 144, 160, 214}, 183}, {{214, 1, 84, 232, 0, 0, 238, 146, 102, 25, 65, 43, 126, 202, 225, 37}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 183}, {{214, 1, 84, 232, 0, 32, 51, 29, 206, 5, 90, 3, 172, 211, 149, 244}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 244, 239, 104, 167, 24}, 183}, {{214, 1, 84, 232, 0, 65, 211, 73, 118, 199, 10, 112, 77, 158, 71, 170}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 119, 88, 248, 18, 155, 241, 49, 211}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 61}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 38, 166, 218, 110, 79, 237, 158, 175}, 183}, {{214, 1, 84, 232, 0, 0, 227, 31, 254, 83, 123, 121, 165, 5, 78, 114}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 45, 118, 62, 50, 195, 63, 219}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 58, 137, 127, 224, 173}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 183}, {{214, 1, 84, 232, 0, 0, 0, 200, 31, 243, 53, 247, 45, 142, 172, 158}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 183}, {{214, 1, 84, 232, 0, 0, 82, 220, 132, 105, 116, 129, 202, 8, 222, 175}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 183}, {{214, 1, 84, 232, 0, 0, 0, 197, 187, 183, 248, 47, 112, 190, 91, 229}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 22, 105, 65, 107, 161, 215, 91, 84, 247, 128, 218}, 183}, {{214, 1, 84, 232, 0, 35, 77, 224, 241, 48, 9, 64, 152, 13, 82, 149}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 62, 208}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 196, 18, 233, 63}, 183}, {{214, 1, 84, 232, 232, 90, 236, 204, 94, 163, 164, 231, 208, 153, 244, 173}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 108}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 58, 248, 192, 12, 11, 45, 133}, 183}, {{214, 1, 84, 232, 251, 225, 173, 163, 61, 27, 145, 232, 139, 198, 165, 112}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 29, 62, 225, 238, 153, 207, 203, 231, 10, 26, 160, 122}, 183}, {{214, 1, 84, 232, 0, 144, 250, 150, 49, 70, 105, 48, 58, 85, 77, 89}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 10, 160, 74, 230, 153}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 206}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 242, 5}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 255, 216, 140, 63}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 138, 160, 77, 147, 212, 248, 135, 230}, 183}, {{214, 1, 84, 232, 0, 0, 0, 119, 8, 245, 123, 30, 51, 119, 209, 86}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 4, 194}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 183}, {{214, 1, 84, 232, 0, 0, 21, 32, 9, 177, 124, 146, 45, 89, 246, 252}, 183}, {{214, 1, 84, 232, 0, 0, 8, 232, 67, 130, 126, 8, 231, 217, 208, 129}, 183}, {{214, 1, 84, 232, 0, 0, 0, 57, 220, 89, 113, 115, 83, 170, 225, 154}, 183}, {{214, 1, 84, 232, 0, 0, 0, 8, 235, 120, 57, 114, 154, 92, 115, 229}, 183}, {{214, 1, 84, 232, 0, 0, 0, 192, 225, 151, 135, 88, 70, 213, 50, 180}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 161, 159}, 183}, {{214, 1, 84, 232, 0, 0, 0, 0, 253, 193, 143, 193, 175, 17, 137, 226}, 183}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 227, 93}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 160}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 171, 40}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 68, 110}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 43, 127}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 219}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 33, 40}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 212}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 212}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 233}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 26, 153}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 97, 235}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 103}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 114}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 3, 24}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 169, 75}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 89}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 46, 61}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 197}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 169, 34}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 17, 138}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 202, 63}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 254}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 160, 107}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 76, 180}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 200, 120}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 255}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 248, 172}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 190, 215}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 35}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 19, 250}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 218, 181}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 211, 26}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 228}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 120}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 113}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 232, 128}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 215, 99}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 189, 48}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 121, 254}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 63}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 199}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 97, 250}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 51}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 149, 81}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 132, 148}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 213, 1}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 171}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 50, 250}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 162, 230}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 230}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 5}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 225}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 74, 27}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 148}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 216, 36}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 190, 24}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 105, 146}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 34, 142}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 216, 111}, 171}, {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 232, 35}, 171}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 2}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 37}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 147}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 77}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 253}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 235}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 253}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 255}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 152}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 182}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 155}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 153}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 160}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 208}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 113}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 248}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 132}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 117}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 15}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 248}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 43}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 192}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 183}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 11}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 18}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 14}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 41}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 95}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 51}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 201}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 69}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 69}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 43}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 123}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 35}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 246}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 162}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 1}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 129}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 162}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 208}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 238}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 186}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 75}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 113}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 198}, 202}, {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 225}, 202}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 99, 136, 104}, 136}, {{152, 0, 0, 0, 0, 38, 250, 240, 127, 110, 39, 173, 28, 2, 222, 114}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 21, 165, 117, 26, 34, 118, 84}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 7}, 136}, {{152, 0, 0, 0, 0, 0, 0, 143, 101, 178, 24, 197, 220, 205, 49, 184}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 219, 180, 151, 34}, 136}, {{152, 0, 0, 0, 0, 67, 163, 29, 94, 6, 233, 134, 235, 45, 115, 160}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 232, 164, 109}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 133, 250, 92, 91}, 136}, {{152, 0, 0, 0, 0, 0, 0, 120, 210, 42, 87, 29, 81, 39, 141, 172}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 196, 99, 47, 110, 245, 133, 232, 221}, 136}, {{152, 0, 0, 45, 127, 16, 168, 28, 245, 197, 206, 176, 88, 243, 215, 119}, 136}, {{152, 0, 0, 0, 0, 0, 0, 240, 17, 174, 80, 123, 170, 195, 23, 242}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 6, 71, 171, 236, 138, 133, 12}, 136}, {{152, 0, 32, 151, 250, 164, 124, 142, 181, 68, 29, 146, 165, 77, 171, 214}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 233, 116, 41, 68, 65, 2, 177}, 136}, {{152, 0, 0, 0, 0, 0, 0, 79, 5, 93, 220, 135, 216, 142, 54, 153}, 136}, {{152, 0, 21, 214, 12, 20, 158, 249, 6, 182, 163, 232, 166, 36, 118, 50}, 136}, {{152, 0, 0, 0, 0, 212, 167, 8, 120, 96, 23, 183, 102, 14, 156, 217}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 67}, 136}, {{152, 0, 0, 39, 120, 104, 110, 198, 179, 31, 224, 144, 222, 210, 72, 88}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 101}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 68}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 63, 245, 94, 250}, 136}, {{152, 0, 0, 0, 237, 198, 239, 203, 145, 129, 7, 255, 196, 35, 221, 240}, 136}, {{152, 186, 30, 230, 97, 248, 86, 20, 35, 14, 71, 88, 99, 138, 76, 227}, 136}, {{152, 0, 50, 198, 72, 53, 34, 30, 160, 163, 53, 240, 101, 145, 146, 73}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 205}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 203, 106}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 150, 176, 32, 12, 51}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 226, 31, 118}, 136}, {{152, 160, 159, 145, 87, 11, 60, 255, 162, 36, 79, 59, 125, 1, 243, 206}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 138, 246, 105, 182}, 136}, {{152, 0, 83, 54, 89, 144, 101, 201, 51, 142, 184, 116, 95, 110, 10, 178}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 132, 221, 241, 214}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 230, 122, 19, 216, 17, 128, 198, 53}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 86, 250, 139, 6, 168, 49, 242, 146, 185}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 233, 42, 240, 27, 52}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 180, 248, 133, 146, 216, 207, 36, 236}, 136}, {{152, 0, 0, 0, 0, 65, 239, 21, 230, 133, 141, 252, 60, 194, 70, 86}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 112, 196, 198, 69, 55, 0, 204, 223}, 136}, {{152, 0, 0, 0, 0, 0, 0, 231, 49, 115, 99, 246, 82, 113, 117, 158}, 136}, {{152, 0, 0, 0, 99, 168, 48, 32, 26, 144, 29, 203, 9, 25, 57, 252}, 136}, {{152, 0, 0, 0, 0, 0, 248, 105, 57, 98, 36, 170, 32, 88, 40, 163}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 235, 106, 28, 10, 234, 31, 11}, 136}, {{152, 218, 191, 234, 39, 18, 141, 190, 16, 112, 31, 14, 16, 63, 104, 9}, 136}, {{152, 0, 0, 0, 0, 0, 0, 147, 83, 186, 234, 58, 224, 142, 94, 160}, 136}, {{152, 0, 0, 0, 0, 128, 222, 200, 44, 82, 33, 93, 130, 67, 69, 242}, 136}, {{152, 0, 132, 1, 177, 232, 47, 170, 156, 190, 66, 217, 158, 133, 227, 72}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 214, 13, 195, 76, 188, 194, 186}, 136}, {{152, 0, 0, 6, 238, 192, 236, 155, 126, 62, 152, 84, 148, 49, 156, 28}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 7}, 136}, {{152, 0, 0, 0, 0, 0, 242, 36, 28, 159, 226, 189, 38, 84, 122, 50}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 172, 5, 104, 126, 94, 11, 162, 175}, 136}, {{152, 0, 0, 188, 95, 112, 248, 125, 73, 94, 201, 116, 104, 236, 106, 14}, 136}, {{152, 0, 0, 0, 0, 82, 94, 89, 90, 189, 206, 145, 208, 152, 231, 165}, 136}, {{152, 0, 0, 0, 0, 0, 176, 17, 175, 21, 34, 36, 139, 115, 107, 52}, 136}, {{152, 0, 0, 0, 0, 0, 0, 8, 220, 31, 86, 245, 88, 18, 132, 141}, 136}, {{152, 124, 96, 81, 182, 82, 119, 233, 236, 17, 40, 190, 181, 145, 52, 237}, 136}, {{152, 0, 0, 0, 0, 0, 36, 223, 234, 235, 89, 226, 111, 233, 120, 82}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 12, 241}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 57, 57, 86, 38}, 136}, {{152, 0, 215, 199, 181, 162, 222, 227, 32, 0, 184, 52, 19, 38, 125, 239}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 11, 247, 224, 82, 150}, 136}, {{152, 0, 0, 169, 21, 118, 64, 83, 88, 120, 224, 160, 219, 178, 49, 113}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 254, 230, 66, 235, 130, 123, 241, 58}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 93, 137, 31}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 41, 237, 31}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 164, 167}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 144, 101, 137, 44, 104, 26, 158, 123, 227, 62, 177, 70}, 136}, {{152, 0, 0, 87, 238, 185, 38, 185, 72, 55, 157, 180, 21, 157, 194, 197}, 136}, {{152, 20, 251, 235, 191, 176, 235, 252, 193, 152, 79, 37, 209, 109, 252, 105}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 233}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 75, 18, 161, 225}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 251, 219, 65, 58}, 136}, {{152, 0, 0, 0, 143, 250, 10, 18, 71, 83, 55, 61, 101, 114, 11, 93}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 49, 251, 8, 244, 79}, 136}, {{152, 0, 0, 0, 0, 0, 0, 4, 176, 183, 206, 168, 195, 186, 127, 13}, 136}, {{152, 0, 0, 232, 244, 227, 255, 19, 230, 184, 163, 192, 173, 38, 40, 231}, 136}, {{152, 0, 0, 0, 0, 207, 142, 140, 4, 34, 229, 173, 212, 96, 190, 144}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 241}, 136}, {{152, 0, 0, 0, 102, 73, 34, 193, 182, 16, 211, 204, 16, 122, 153, 235}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 199, 77, 89}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 82, 205, 79}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 68}, 136}, {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 4, 151, 169}, 136}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 208}, 107}, {{9, 174, 211, 200, 120, 0, 0, 73, 31, 145, 158, 45, 54, 205, 38, 156}, 107}, {{9, 174, 211, 200, 120, 172, 164, 20, 56, 123, 166, 160, 119, 144, 111, 238}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 119, 227, 77, 159, 107, 195, 173, 133}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 24, 40, 51, 107, 140, 149, 98}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 104, 228, 152, 190, 220, 230, 3}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 62, 86, 112, 46}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 107}, {{9, 174, 211, 200, 120, 0, 0, 67, 18, 152, 161, 24, 22, 48, 196, 209}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 7, 105, 200, 11, 251, 1, 90, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 123, 175, 194, 97}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 141}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 2, 13, 91, 78, 111, 33, 16}, 107}, {{9, 174, 211, 200, 120, 0, 195, 29, 23, 35, 153, 228, 146, 91, 8, 232}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 88, 219, 188, 176}, 107}, {{9, 174, 211, 200, 120, 0, 0, 58, 163, 195, 83, 74, 227, 227, 198, 106}, 107}, {{9, 174, 211, 200, 120, 0, 53, 95, 233, 248, 152, 217, 53, 72, 190, 163}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 209}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 141, 81, 95, 174}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 120, 8, 163, 162, 216, 7, 31, 153}, 107}, {{9, 174, 211, 200, 120, 0, 0, 160, 76, 232, 115, 172, 232, 13, 225, 55}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 170, 46, 182, 253, 234, 5}, 107}, {{9, 174, 211, 200, 120, 0, 0, 120, 103, 88, 19, 76, 85, 68, 227, 247}, 107}, {{9, 174, 211, 200, 120, 121, 64, 129, 162, 50, 45, 167, 24, 42, 228, 146}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 228, 210, 125, 19, 225, 105, 19}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 187, 212, 180}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 55, 96, 182, 94, 73, 79, 146, 153}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 53, 138, 34, 81}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 6, 128, 3, 226, 42, 136}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 148, 176, 90, 123, 238, 49, 171, 144, 48}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 158, 144, 41, 97, 185, 61}, 107}, {{9, 174, 211, 200, 120, 0, 0, 39, 81, 246, 157, 196, 17, 235, 196, 164}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 231, 165, 51}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 77, 141, 110, 132, 238}, 107}, {{9, 174, 211, 200, 120, 0, 0, 154, 33, 16, 162, 40, 9, 246, 252, 150}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 163, 209, 188, 196, 134, 65}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 252, 119, 10, 230, 234}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 19, 52, 94, 71, 95}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 3, 93, 18, 159, 148, 104, 40}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 114, 1, 65, 63, 144, 108}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 118, 191, 248, 187}, 107}, {{9, 174, 211, 200, 120, 0, 0, 73, 196, 14, 47, 8, 195, 101, 199, 11}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 17}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 190, 151, 253, 145, 102, 107, 116, 17, 253, 56}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 250, 185, 163, 1, 167, 191}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 145, 23, 134, 207, 108}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 48, 97, 65, 156, 25, 122, 165, 7, 38, 153}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 220, 97, 200, 76, 35, 246}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 61}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 211, 84, 240, 231, 254, 110, 133}, 107}, {{9, 174, 211, 200, 120, 0, 42, 146, 116, 107, 40, 149, 190, 65, 159, 133}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 92, 116, 22, 55, 41, 16}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 181, 40, 145, 162, 180, 189, 159, 123}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 151, 199, 17, 125, 77, 127}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 57}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 37, 144, 206, 201, 107, 16, 157, 235}, 107}, {{9, 174, 211, 200, 120, 0, 0, 130, 166, 146, 9, 215, 71, 173, 19, 81}, 107}, {{9, 174, 211, 200, 120, 0, 0, 2, 238, 28, 134, 115, 71, 113, 94, 220}, 107}, {{9, 174, 211, 200, 120, 0, 0, 15, 104, 125, 247, 190, 84, 244, 37, 112}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 241, 229, 122, 75}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 217, 228, 47, 187, 71}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 160, 41, 5, 187, 237, 255}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 83, 222, 181}, 107}, {{9, 174, 211, 200, 120, 99, 242, 112, 9, 143, 13, 194, 16, 190, 97, 112}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 141, 188, 202, 116, 56}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 208, 200, 227, 81, 166}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 172, 77, 255, 46, 152, 123, 106}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 5, 39, 164, 39, 174, 225, 97}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 52, 255, 24, 224, 7, 162, 139, 21}, 107}, {{9, 174, 211, 200, 120, 0, 51, 226, 137, 86, 223, 191, 80, 188, 181, 169}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 107}, {{9, 174, 211, 200, 120, 0, 84, 235, 14, 224, 85, 166, 153, 148, 221, 174}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 216, 255, 96, 162, 98, 148, 164}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 222, 110, 177, 150}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 220}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 131, 88, 38, 214, 188, 20, 50}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 159, 151, 246}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 153, 19, 229, 158, 151, 121, 31}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 221, 54, 161, 49, 236}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 211, 172, 150, 94, 170, 139}, 107}, {{9, 174, 211, 200, 120, 0, 0, 0, 249, 52, 208, 184, 243, 90, 22, 24}, 107}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 146, 221, 189, 221}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 39}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 205}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 70}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 162, 86}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 137}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 47, 51, 43, 151}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 249, 52, 21, 199}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 159}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 153, 149, 53, 10, 80}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 184, 24, 119, 17}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 211, 79}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 207}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 255, 220, 4}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 250, 97, 192}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 164, 89, 233, 63}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 225, 227, 200, 200}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 115, 219}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 215}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 138, 16}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 10, 82, 44}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 159, 97, 211, 4, 204}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 225, 228}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 3, 90, 145}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 165, 64, 109, 242}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 155}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 18}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 138}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 98, 86}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 139, 10}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 49}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 9, 164, 58, 252}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 126}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 1, 130, 193, 86}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 62, 207, 33, 192}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 153, 119, 0, 81}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 68, 184}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 59, 243}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 174, 126, 201}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 139, 18, 30, 111, 170}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 156}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 187, 202}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 174}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 213, 66, 211, 245}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 132, 121, 30}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 112, 92, 143, 175}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 12, 66}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 124, 168, 176, 78}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 183, 153, 162, 19}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 23}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 66, 118, 120, 226}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 128}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 252}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 113, 153}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 108, 102}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 47}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 36, 44}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 100, 86, 61}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 175}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 10}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 74, 72}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 40}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 1}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 13, 197}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 3, 127, 167, 116}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 178}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 186}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 209, 139, 33, 242}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 192, 101, 37, 106}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 125}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 71, 143, 93}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 30}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 18, 213, 77, 66}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 149, 74, 225, 195}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 39, 211, 157, 146}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 173, 135}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 163, 115}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 205, 238, 60}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 193}, {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 57, 217, 238, 141}, 193}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 127, 96, 99, 50, 166}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 158, 104, 80}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 44, 245, 99, 254, 185, 248, 231, 66}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 132, 170, 162, 170, 39, 103}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 42, 220}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 167, 60, 110, 237, 40}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 122, 247}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 119, 94, 144, 17, 130, 4, 219, 173}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 108, 5, 83, 78, 76, 223}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 111, 26, 72, 27, 129, 132}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 70, 81, 109, 38}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 194, 220, 229, 186, 233, 207, 35}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 240, 204, 81}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 99, 247, 126, 50, 146, 1}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 43, 171, 177, 1, 40, 208, 36}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 227, 196, 169, 3, 186, 129}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 196, 45, 119, 101, 216}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 68, 105, 190, 83, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 125, 18, 57, 252, 112, 200, 135, 63, 81}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 71, 120, 239, 199}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 200, 137}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 1, 89}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 15, 67, 95, 235}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 203, 191, 239, 56, 143, 179}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 68, 157}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 176, 149, 202, 90, 184, 125}, 4}, {{23, 28, 202, 10, 90, 158, 64, 1, 21, 3, 90, 107, 219, 74, 100, 123}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 242, 153, 203, 130, 243, 154, 7}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 10, 209}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 225, 255, 183, 74, 237}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 49, 41, 249, 46, 161, 201}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 197, 86, 65, 72, 240, 124, 2, 91}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 48, 133, 226}, 4}, {{23, 28, 202, 10, 90, 158, 64, 71, 201, 38, 239, 150, 208, 107, 15, 38}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 168, 16, 113, 38, 26, 44, 22, 110}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 48, 143, 79, 45, 220}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 160, 112, 119, 107, 2}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 130, 78, 151, 44, 187, 198}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 54, 233}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 76, 86, 244}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 60, 85, 181, 30, 91}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 235, 40, 178, 173}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 92, 172, 144, 75}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 63, 66, 104, 46}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 186, 52, 143, 54}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 212, 175, 101}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 13, 181, 80, 220}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 151}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 196, 62, 221, 254}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 165, 232, 145, 20, 10, 34}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 202, 222, 210, 92, 61, 94}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 102, 103, 211, 233}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 34, 222, 155, 166, 210}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 99, 14, 154, 245, 155, 126, 229, 198}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 137, 197, 243, 58, 102, 212}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 110, 113}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 123, 114, 127, 250, 231, 26, 183, 140}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 240, 164, 31}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 120, 124, 43}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 121, 242, 127}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 94, 136, 122, 143, 152}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 199, 145, 39, 3, 173, 167, 240}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 238, 190}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 180, 164, 181, 168}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 102, 88, 58, 63, 27}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 148, 14, 96}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 135, 146, 1, 241, 146, 92}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 59, 136, 2, 199, 234, 182}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 145, 80}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 118, 220, 67, 143, 206}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 90, 108, 253, 86, 114, 66}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 185, 42, 137, 86}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 79, 23}, 4}, {{23, 28, 202, 10, 90, 158, 64, 207, 164, 23, 138, 183, 95, 82, 66, 216}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 229, 142, 182, 64, 179, 15, 14}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 4}, {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 4}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 239, 18}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 25, 128}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 126, 26}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 111, 40, 185}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 89, 87}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 116, 34}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 13}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 187, 61, 167}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 36, 22, 156}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 162, 24}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 39, 147}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 218}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 73}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 197, 131}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 103, 82}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 39, 108, 243}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 67, 77, 157}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 87, 52}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 186, 169, 200}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 31, 79, 121}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 245, 227, 79}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 235, 51, 70}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 238, 70}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 45, 192, 55}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 209, 124, 154}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 62}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 228, 83, 238}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 208, 122, 19}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 251, 83, 223}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 101}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 170, 218, 249}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 97, 52}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 135}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 24, 65}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 139, 127, 90}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 183}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 86}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 244}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 201, 176, 83}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 3}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 71, 96, 155}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 88, 39}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 107, 57, 121}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 225, 213}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 117}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 107, 98, 139}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 132, 14}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 146, 96, 87}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 53}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 202}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 139}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 61, 242}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 188}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 72, 177}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 133}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 22, 135}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 235}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 205, 16, 51}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 210}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 86}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 248, 80}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 103, 37}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 158}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 84, 202}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 136, 10, 94}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 43}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 70, 93}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 68}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 218, 3, 245}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 68, 8, 113}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 81}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 14, 95}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 131}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 18}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 15, 170}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 214, 243}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 157}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 218, 148}, 68}, {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 102, 236, 105}, 68}, {{252, 0, 0, 0, 0, 0, 0, 0, 21, 111, 167, 28, 196, 178, 228, 10}, 40}, {{252, 0, 0, 190, 175, 230, 24, 47, 163, 98, 114, 24, 163, 161, 174, 153}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 55, 8}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 40}, {{252, 0, 0, 0, 174, 190, 67, 179, 117, 201, 33, 254, 43, 216, 200, 90}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 159, 247, 72, 72, 223, 77, 180}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 0, 181, 217, 105, 116, 115, 216, 161, 92, 100}, 40}, {{252, 0, 0, 0, 53, 170, 213, 49, 0, 244, 146, 161, 51, 72, 244, 69}, 40}, {{252, 0, 0, 0, 0, 0, 0, 108, 107, 155, 105, 123, 77, 144, 34, 27}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 97, 52, 52, 224, 111, 213, 97}, 40}, {{252, 0, 0, 0, 0, 0, 0, 58, 225, 163, 116, 16, 132, 169, 92, 127}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 232, 253, 98, 106, 227, 63, 37}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 202, 50, 88}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 208}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 65, 158}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 125, 43, 255, 203, 101, 95, 26}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 244, 123}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 214, 124, 72}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 158, 195, 85, 167}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 235, 49, 36, 135, 250, 36, 132, 218}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 207, 91, 68}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 126, 12}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 29, 52, 190, 109, 89, 228, 62, 176}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 51, 132, 165, 41, 5, 145, 186}, 40}, {{252, 0, 0, 0, 119, 175, 217, 16, 168, 247, 149, 248, 35, 232, 56, 160}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 151, 117, 59, 0}, 40}, {{252, 0, 0, 148, 228, 43, 67, 149, 121, 239, 207, 68, 17, 17, 212, 110}, 40}, {{252, 0, 0, 0, 74, 74, 231, 28, 94, 163, 219, 2, 241, 82, 197, 8}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 40}, {{252, 0, 0, 0, 0, 0, 0, 232, 25, 194, 184, 103, 75, 159, 181, 250}, 40}, {{252, 0, 0, 0, 0, 0, 0, 3, 241, 74, 138, 49, 157, 99, 202, 85}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 37}, 40}, {{252, 0, 0, 0, 0, 0, 0, 156, 149, 216, 205, 173, 134, 1, 179, 173}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 245, 200, 126, 132, 94}, 40}, {{252, 0, 196, 99, 45, 189, 2, 95, 102, 249, 156, 51, 187, 57, 66, 7}, 40}, {{252, 0, 0, 0, 0, 27, 251, 148, 146, 220, 182, 242, 27, 4, 119, 199}, 40}, {{252, 0, 0, 139, 10, 105, 73, 83, 232, 114, 50, 243, 140, 202, 7, 238}, 40}, {{252, 0, 0, 130, 252, 193, 179, 25, 170, 153, 178, 78, 16, 205, 22, 158}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 187}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 64, 243, 60, 11, 43, 153, 150}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 254, 207, 160, 207, 32}, 40}, {{252, 0, 0, 0, 0, 0, 0, 57, 64, 72, 66, 24, 41, 159, 8, 211}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 94, 9}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 70}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 232, 6, 202, 33, 202, 140, 130}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 45, 97}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 216, 176, 171, 11, 25}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 33, 164, 109, 77}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 50}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 85, 235, 199, 27}, 40}, {{252, 0, 0, 178, 236, 155, 169, 182, 254, 100, 236, 222, 249, 164, 66, 73}, 40}, {{252, 0, 0, 0, 0, 159, 172, 180, 181, 5, 6, 252, 114, 185, 211, 228}, 40}, {{252, 0, 0, 0, 0, 0, 14, 104, 167, 233, 169, 130, 40, 231, 107, 193}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 37}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 130, 255}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 60, 86}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 183, 1, 55, 95}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 40}, {{252, 0, 45, 63, 229, 24, 78, 37, 254, 157, 32, 110, 233, 77, 85, 128}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 217, 255, 20, 227, 30}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 30, 105, 207}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 76, 126}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 214, 116, 212, 181, 26, 208, 177, 208}, 40}, {{252, 0, 0, 0, 195, 190, 142, 10, 129, 21, 119, 179, 38, 7, 176, 79}, 40}, {{252, 0, 0, 0, 0, 125, 197, 37, 170, 58, 2, 95, 170, 6, 228, 94}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 55, 194, 99, 147, 194}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 165, 183, 208, 13, 157, 172, 92, 235, 137, 173}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 233}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 232, 114, 190, 218}, 40}, {{252, 0, 83, 249, 16, 205, 190, 223, 144, 175, 130, 195, 175, 94, 226, 43}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 61, 9, 186, 39, 141, 75, 82, 23}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 5}, 40}, {{252, 0, 0, 48, 220, 139, 174, 86, 223, 103, 7, 120, 55, 227, 240, 231}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 196, 194, 28, 156, 90}, 40}, {{252, 0, 118, 222, 9, 205, 160, 246, 4, 156, 226, 50, 131, 190, 19, 137}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 224, 180, 61, 152, 172, 33, 87}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 66, 124, 218, 83}, 40}, {{252, 0, 154, 49, 137, 62, 213, 254, 67, 117, 246, 178, 107, 200, 125, 127}, 40}, {{252, 0, 0, 0, 0, 0, 0, 185, 175, 112, 202, 167, 50, 95, 128, 166}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 115, 0, 19, 243, 192}, 40}, {{252, 0, 54, 20, 29, 15, 72, 83, 168, 101, 252, 36, 6, 205, 82, 33}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 6, 70, 79, 231, 245, 208, 135}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 141}, 40}, {{252, 0, 0, 0, 0, 0, 127, 120, 158, 73, 152, 185, 22, 74, 119, 158}, 40}, {{252, 0, 110, 62, 115, 101, 221, 28, 111, 146, 225, 184, 30, 186, 192, 20}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 79}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 65, 253, 63}, 40}, {{252, 0, 0, 0, 138, 131, 201, 147, 155, 111, 136, 97, 166, 148, 44, 180}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 184, 64, 201, 69, 171, 94, 204}, 40}, {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 39, 55}, 40}, {{252, 0, 0, 50, 106, 47, 24, 196, 216, 44, 102, 130, 12, 120, 54, 154}, 40}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 15, 165, 222, 176, 197, 18, 198}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 72, 48, 110, 133}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 103, 100, 3, 158}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 133, 236, 6, 108}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 39}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 201, 100, 81, 132, 236, 180, 240}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 64, 71, 120, 40}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 173, 118, 230, 44, 151, 67, 46}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 181, 65, 251, 9, 162, 7}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 77, 172, 34, 66, 43, 101}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 139, 142, 55, 190, 249, 79, 101}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 21, 254, 213, 128, 104, 173, 69}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 171, 178, 109, 31}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 215, 9, 36, 21, 52, 245, 73, 40}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 141, 74, 242, 92, 213}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 219, 172, 228, 209, 40}, 255}, {{20, 165, 57, 130, 164, 0, 0, 35, 75, 184, 206, 45, 27, 201, 142, 219}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 147, 175, 36, 239, 145, 185, 181, 123}, 255}, {{20, 165, 57, 130, 164, 0, 91, 160, 51, 152, 168, 130, 106, 67, 27, 2}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 67, 106, 35, 229, 79, 41, 236, 23}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 123, 78, 187, 82}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 22, 135, 192, 104}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 242, 1, 96, 247, 196, 8, 234}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 255}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 3}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 23, 65, 231, 107, 138}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 184, 101, 188, 55, 68, 169}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 215, 168, 129}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 182, 182, 9, 5, 132}, 255}, {{20, 165, 57, 130, 164, 0, 137, 145, 35, 86, 177, 158, 213, 174, 205, 224}, 255}, {{20, 165, 57, 130, 164, 0, 96, 237, 105, 65, 105, 131, 53, 224, 119, 136}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 2, 107, 236, 253, 221, 165}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 129, 142, 17, 52}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 104, 5, 242, 96, 133, 45, 143}, 255}, {{20, 165, 57, 130, 164, 0, 137, 18, 122, 193, 152, 209, 14, 182, 86, 100}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 131, 76, 92, 44, 204, 145}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 102, 142, 169, 191, 16, 5}, 255}, {{20, 165, 57, 130, 164, 0, 30, 92, 72, 169, 105, 67, 230, 226, 7, 197}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 38, 192, 127, 110, 230, 189}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 161, 123, 11}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 116, 233, 94, 110, 200}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 237, 237, 163, 152}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 254}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 55, 207, 106, 50}, 255}, {{20, 165, 57, 130, 164, 0, 0, 169, 209, 24, 177, 191, 95, 225, 156, 61}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 180, 250, 211}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 70, 201, 0, 229, 79, 142, 42, 46}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 52}, 255}, {{20, 165, 57, 130, 164, 0, 0, 181, 234, 254, 39, 9, 209, 0, 138, 182}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 100, 96, 7, 16, 110, 11, 212}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 179, 31, 39, 222, 43, 108, 243, 55, 246}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 17, 42, 74, 77, 160, 184, 52, 165}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 37}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 120, 38, 56}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91}, 255}, {{20, 165, 57, 130, 164, 0, 0, 57, 115, 129, 175, 215, 200, 87, 229, 208}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 109, 176, 88}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 99}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 255}, {{20, 165, 57, 130, 164, 0, 0, 164, 214, 40, 65, 239, 153, 132, 152, 87}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 138, 34, 132, 2}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 192, 180, 137, 238, 11}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 192, 205, 242}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 219, 248, 225, 11, 221, 179}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 239}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 58, 0, 172, 232, 185, 0, 67}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 255}, {{20, 165, 57, 130, 164, 0, 99, 8, 250, 216, 69, 86, 83, 149, 160, 28}, 255}, {{20, 165, 57, 130, 164, 0, 0, 191, 40, 67, 221, 133, 221, 157, 202, 92}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 241, 181, 125, 254, 34}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 62, 191, 140, 124, 17, 55, 170}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 47, 203, 111}, 255}, {{20, 165, 57, 130, 164, 0, 0, 105, 246, 186, 57, 12, 194, 61, 47, 150}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 170, 67, 60, 214, 232, 171}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 176, 39, 251, 121, 30, 228, 64, 53}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 69, 63, 97, 255, 32, 18}, 255}, {{20, 165, 57, 130, 164, 0, 27, 90, 249, 79, 40, 201, 64, 68, 112, 148}, 255}, {{20, 165, 57, 130, 164, 0, 249, 181, 221, 29, 126, 53, 216, 120, 180, 226}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 91, 164, 101, 116, 107, 230, 205, 143, 101, 161, 53}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{20, 165, 57, 130, 164, 0, 0, 80, 120, 84, 244, 153, 114, 153, 253, 204}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 171, 100, 196, 199, 244, 103, 194, 142}, 255}, {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 52, 218, 236}, 255}, {{167, 56, 128, 0, 0, 0, 35, 158, 199, 47, 65, 118, 121, 111, 14, 14}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 68, 125, 216, 239, 87, 95, 65}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 140}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 55}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 127}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 124, 239, 144, 234, 124, 203, 148, 80}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 105, 207, 217, 213, 209}, 108}, {{167, 56, 128, 0, 0, 0, 0, 140, 69, 65, 178, 72, 103, 255, 40, 176}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 108}, {{167, 56, 128, 0, 0, 0, 241, 220, 90, 205, 63, 205, 201, 12, 52, 144}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 176, 62, 5, 7, 102, 30, 36}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 26, 15, 58}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 216}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 213, 90, 231}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 75, 215, 28, 245, 92}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 226}, 108}, {{167, 56, 128, 0, 0, 0, 230, 119, 96, 89, 29, 145, 167, 194, 82, 159}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 110, 146, 187, 73, 90, 19, 94}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 173, 209}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 186, 151, 162, 131, 12, 29}, 108}, {{167, 56, 128, 0, 0, 0, 246, 222, 215, 39, 255, 145, 41, 146, 95, 221}, 108}, {{167, 56, 128, 120, 46, 10, 208, 26, 202, 182, 6, 123, 3, 55, 110, 251}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 144}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 72, 204, 124, 240, 83, 107, 68, 136}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 204, 147}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 63, 35, 127, 103, 254, 163, 111}, 108}, {{167, 56, 128, 0, 0, 0, 12, 61, 219, 28, 219, 229, 125, 155, 203, 209}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 145, 38, 221}, 108}, {{167, 56, 128, 0, 0, 0, 0, 169, 137, 216, 148, 231, 171, 112, 219, 30}, 108}, {{167, 56, 128, 0, 0, 0, 44, 127, 121, 15, 62, 134, 27, 89, 68, 104}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 102}, 108}, {{167, 56, 128, 0, 0, 0, 70, 145, 40, 160, 21, 205, 116, 8, 148, 154}, 108}, {{167, 56, 128, 0, 0, 0, 233, 37, 53, 181, 34, 142, 186, 189, 138, 81}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 126, 255, 15, 98, 63, 48, 166, 5}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 205, 243, 9, 15, 166}, 108}, {{167, 56, 128, 0, 0, 0, 0, 211, 151, 221, 40, 138, 36, 188, 6, 48}, 108}, {{167, 56, 128, 0, 0, 0, 242, 126, 232, 44, 31, 99, 200, 131, 255, 191}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 5, 190, 55, 59, 162}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 102, 101, 128, 234, 171}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 170, 20, 86, 212, 124, 88, 159}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 239, 63, 123, 165, 123, 150, 121, 18}, 108}, {{167, 56, 128, 0, 4, 166, 95, 75, 234, 191, 72, 162, 234, 61, 18, 48}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 101, 251, 197}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 132, 29, 92, 242, 58, 141, 81}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 36, 175}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 69, 0, 31}, 108}, {{167, 56, 128, 176, 22, 31, 113, 72, 63, 5, 224, 33, 209, 174, 219, 42}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 198, 252, 197, 145, 126, 153, 221, 209}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 206, 255, 79}, 108}, {{167, 56, 128, 0, 44, 191, 13, 122, 85, 70, 236, 166, 195, 153, 60, 101}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 215, 217, 34, 201, 47}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 58, 194, 255}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 165, 237, 29, 89, 132, 226, 229}, 108}, {{167, 56, 128, 0, 158, 164, 178, 238, 29, 150, 81, 88, 155, 112, 187, 175}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 35, 41, 25, 154, 23, 229, 158, 162}, 108}, {{167, 56, 128, 0, 0, 0, 173, 39, 237, 173, 122, 14, 42, 108, 230, 31}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 152, 163, 65, 176, 85, 156, 49}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 96, 108, 60, 21, 212, 2, 222, 57}, 108}, {{167, 56, 128, 113, 212, 182, 110, 251, 134, 229, 0, 18, 95, 238, 150, 251}, 108}, {{167, 56, 128, 0, 0, 0, 0, 74, 150, 57, 17, 83, 166, 63, 71, 26}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 108}, {{167, 56, 128, 0, 233, 96, 173, 108, 30, 104, 118, 143, 248, 43, 114, 29}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 144, 229, 35, 55, 233}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 4, 226}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 196, 113, 77}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 35, 167}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 57, 117, 191, 79, 242}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 72, 157, 7}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 98, 200, 198, 148, 59, 168, 159, 192}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 137}, 108}, {{167, 56, 128, 194, 242, 30, 228, 9, 216, 30, 177, 226, 229, 247, 231, 52}, 108}, {{167, 56, 128, 0, 47, 34, 132, 206, 61, 169, 197, 40, 208, 159, 198, 150}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 45}, 108}, {{167, 56, 128, 0, 0, 0, 228, 146, 75, 187, 105, 48, 236, 29, 122, 240}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 57, 165, 77, 18, 71, 167, 145}, 108}, {{167, 56, 128, 10, 204, 20, 255, 47, 169, 62, 222, 177, 123, 70, 64, 185}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 9, 107, 171, 88, 255, 187, 194, 64}, 108}, {{167, 56, 128, 0, 0, 0, 97, 220, 245, 205, 135, 77, 65, 182, 212, 43}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 136, 99, 192, 158, 142, 85}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 123, 249}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 108, 4}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 231, 11, 29, 253, 117, 119, 176}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 219}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 165, 219}, 108}, {{167, 56, 128, 0, 85, 145, 105, 99, 190, 20, 217, 126, 100, 81, 137, 77}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 108, 3}, 108}, {{167, 56, 128, 0, 0, 87, 41, 228, 84, 49, 207, 182, 25, 218, 46, 78}, 108}, {{167, 56, 128, 0, 0, 104, 116, 137, 110, 16, 20, 64, 131, 113, 251, 220}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 130, 58}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 105, 1}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 84}, 108}, {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 108}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 42, 178}, 219}, {{91, 204, 0, 0, 39, 241, 21, 59, 160, 111, 24, 53, 197, 81, 239, 137}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 255, 35, 128, 61, 30, 39}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 188, 106, 146, 42, 14, 185}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 245, 130, 141, 187, 254, 48, 47, 69}, 219}, {{91, 204, 0, 145, 67, 227, 35, 72, 152, 109, 75, 213, 134, 26, 102, 149}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 51, 190, 105, 148, 52, 39, 223}, 219}, {{91, 204, 0, 75, 1, 250, 242, 129, 188, 199, 123, 190, 23, 161, 183, 92}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 11, 89, 194, 71, 49, 13, 175, 139}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 199, 217, 12, 141, 178, 43, 93, 31}, 219}, {{91, 204, 0, 0, 0, 0, 0, 86, 113, 165, 23, 202, 132, 160, 175, 88}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 96, 11, 228, 9}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 107, 166}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 55, 188, 155, 51, 22, 251}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 106, 177, 64, 81, 213, 51, 161}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 148, 187, 169}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 123, 229, 26, 66}, 219}, {{91, 204, 0, 0, 0, 0, 0, 147, 183, 69, 250, 117, 65, 56, 144, 36}, 219}, {{91, 204, 0, 0, 0, 0, 73, 12, 241, 161, 71, 194, 136, 125, 211, 91}, 219}, {{91, 204, 0, 0, 0, 0, 164, 31, 15, 253, 216, 69, 254, 9, 86, 240}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 19, 238, 97, 44, 114, 86, 77, 19, 125, 127, 179, 120, 131}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 35, 221, 24, 89}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 147, 200, 238, 58, 174, 19, 221}, 219}, {{91, 204, 0, 222, 175, 0, 213, 218, 199, 20, 162, 216, 148, 58, 80, 90}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 49, 50, 116, 188, 131, 7, 130, 221, 133, 122, 30, 10, 42}, 219}, {{91, 204, 0, 0, 174, 246, 207, 91, 244, 129, 131, 179, 245, 4, 216, 30}, 219}, {{91, 204, 0, 0, 0, 0, 0, 184, 196, 210, 252, 242, 15, 151, 55, 134}, 219}, {{91, 204, 0, 0, 0, 0, 0, 117, 46, 69, 91, 47, 32, 130, 56, 239}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 19}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 247, 187, 201, 0, 176, 3, 5}, 219}, {{91, 204, 0, 0, 0, 0, 75, 198, 203, 235, 20, 69, 180, 163, 116, 59}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 214, 2, 213, 66, 216, 143}, 219}, {{91, 204, 0, 0, 0, 0, 78, 0, 71, 143, 198, 137, 87, 7, 0, 173}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 241, 104, 126, 196, 142, 73, 105, 203}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 142, 12, 180, 196, 164, 54, 201, 7, 7, 243, 35, 13}, 219}, {{91, 204, 0, 113, 13, 19, 58, 139, 148, 172, 243, 246, 195, 157, 12, 157}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 231, 210}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 187, 209}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 157, 23, 183, 13, 101, 226}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 67, 115, 233, 3}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 99, 249, 54, 58, 207, 89, 208, 56}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 219}, {{91, 204, 0, 0, 0, 172, 164, 86, 99, 194, 183, 92, 121, 49, 177, 238}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 40, 192, 189, 107, 44, 26, 253}, 219}, {{91, 204, 0, 0, 0, 0, 0, 184, 237, 232, 9, 223, 105, 72, 57, 28}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 198, 229}, 219}, {{91, 204, 0, 0, 0, 115, 97, 150, 175, 195, 164, 153, 207, 23, 173, 25}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 175}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 124, 215, 34, 59, 200, 11}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 219}, {{91, 204, 0, 0, 0, 0, 0, 121, 162, 182, 21, 228, 235, 245, 44, 84}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 55, 240, 140, 1}, 219}, {{91, 204, 0, 152, 29, 233, 123, 218, 108, 193, 84, 66, 180, 170, 59, 31}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 14, 242, 109}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 15, 249, 65, 212, 38, 170, 17}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 116, 87, 47, 77, 69, 154, 95, 182, 68, 136}, 219}, {{91, 204, 0, 0, 0, 186, 198, 68, 99, 153, 232, 199, 229, 171, 172, 187}, 219}, {{91, 204, 0, 0, 112, 171, 222, 181, 206, 185, 86, 155, 82, 178, 212, 78}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 154}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 238}, 219}, {{91, 204, 0, 0, 0, 0, 222, 28, 204, 84, 247, 248, 179, 203, 124, 11}, 219}, {{91, 204, 0, 0, 0, 0, 254, 54, 69, 12, 30, 235, 140, 134, 242, 218}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 197, 0, 73}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 15, 18, 20, 30, 232, 136, 207}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 96, 73, 115, 247, 198, 242, 230}, 219}, {{91, 204, 77, 245, 25, 213, 205, 128, 79, 126, 25, 143, 39, 222, 37, 41}, 219}, {{91, 204, 0, 63, 247, 172, 221, 99, 117, 100, 56, 48, 228, 121, 35, 175}, 219}, {{91, 204, 0, 0, 234, 213, 197, 32, 219, 96, 136, 58, 223, 16, 124, 39}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 64, 118}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 24, 143, 84, 199}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 106, 132}, 219}, {{91, 204, 0, 0, 0, 0, 0, 164, 46, 254, 11, 4, 41, 19, 155, 255}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 163}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 231, 61, 180}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{91, 204, 0, 0, 0, 92, 185, 255, 170, 210, 253, 73, 88, 97, 11, 72}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 237, 137, 246, 123, 170, 1, 188}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 108, 196, 10, 137, 221, 116}, 219}, {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 165, 196, 252, 71, 14, 239}, 219}, {{91, 204, 0, 0, 0, 0, 178, 74, 43, 95, 55, 175, 139, 144, 36, 138}, 219}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 98}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 241}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 20, 60}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 254}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 145}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 79}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 29}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 29, 90}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 168}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 73, 34}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 176}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 237, 96}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 77}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 229, 21}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 197}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 129}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 126}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 143, 101}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 96}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 96}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 130, 189}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 209}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 110, 7}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 23, 26}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 191, 172}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 109}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 213}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 47}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 174, 3}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 207, 150}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 171}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 213, 204}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 90}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 72}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 146}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 195, 123}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 239}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 123, 254}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 241}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 35, 83}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 35}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 101}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 36, 12}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 65, 89}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 165, 216}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 230, 239}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 179}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 246}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 162, 9}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 45}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 105}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 95}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 32}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 11}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 126}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 101}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 12}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 59, 234, 86, 111, 92}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 84}, {{156, 60, 245, 247, 189, 0, 28, 245, 133, 48, 94, 146, 3, 86, 23, 152}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 88, 247, 53}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 25, 228, 113, 93, 10}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 80, 124, 129, 234, 158, 215, 45, 30}, 84}, {{156, 60, 245, 247, 189, 0, 0, 48, 109, 28, 135, 219, 252, 9, 75, 1}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 35}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 86, 242, 9, 80, 129, 66, 33, 150}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 239}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 180, 249, 136}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 35, 34, 91, 23, 89, 69, 212}, 84}, {{156, 60, 245, 247, 189, 0, 132, 83, 201, 175, 181, 70, 106, 229, 217, 229}, 84}, {{156, 60, 245, 247, 189, 0, 49, 121, 83, 192, 64, 181, 18, 187, 126, 210}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 128, 21, 124, 97, 205}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 69, 130, 118}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 239, 64, 7, 119, 155, 30}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 245, 1, 194, 143, 189, 132, 151, 37}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 76, 48, 238, 117, 181, 131}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 50}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 123, 23, 123}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 29, 149, 127, 0, 185, 202}, 84}, {{156, 60, 245, 247, 189, 0, 5, 173, 55, 173, 184, 209, 84, 88, 8, 144}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 252, 133, 68, 208}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 178, 123, 48, 67, 165, 21, 28}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 8, 120, 95, 124}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 185, 104, 239, 57, 217}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 112, 182, 186, 118, 16, 157, 114, 251}, 84}, {{156, 60, 245, 247, 189, 0, 229, 7, 107, 224, 240, 170, 192, 98, 187, 188}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 60, 74, 173, 112}, 84}, {{156, 60, 245, 247, 189, 0, 0, 54, 80, 101, 139, 67, 110, 117, 14, 31}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 48}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 208}, 84}, {{156, 60, 245, 247, 189, 0, 0, 38, 76, 157, 158, 169, 158, 203, 102, 120}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 117, 182, 34, 249, 228}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 84}, {{156, 60, 245, 247, 189, 0, 242, 166, 157, 80, 144, 11, 80, 136, 63, 131}, 84}, {{156, 60, 245, 247, 189, 0, 0, 190, 78, 90, 43, 137, 193, 5, 63, 249}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 158, 208, 94}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 141, 168, 63, 102, 215}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 143, 244, 72}, 84}, {{156, 60, 245, 247, 189, 0, 81, 129, 152, 133, 230, 141, 30, 83, 175, 172}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 5}, 84}, {{156, 60, 245, 247, 189, 0, 0, 24, 5, 151, 79, 73, 150, 67, 110, 164}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 161, 128, 63, 243}, 84}, {{156, 60, 245, 247, 189, 0, 252, 123, 232, 176, 146, 201, 105, 238, 88, 67}, 84}, {{156, 60, 245, 247, 189, 0, 0, 81, 201, 55, 101, 181, 12, 167, 200, 29}, 84}, {{156, 60, 245, 247, 189, 0, 0, 112, 249, 172, 144, 51, 80, 55, 127, 222}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 102, 147, 171, 115}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 236, 184, 141, 28, 36}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 187, 188, 226, 51}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 71, 56, 203}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 178, 55, 69, 229}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 77, 48, 88, 147, 53, 223}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 78}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 33, 234, 31, 43, 75, 115, 5}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 2, 81, 182, 10, 88, 27}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 47, 26, 201, 96, 81, 204, 129, 230}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 206, 182, 201, 50, 124}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 188, 236, 46, 44, 33, 18, 119, 119}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 175, 62, 141, 189, 29, 93, 30}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 48, 237, 25, 114, 52, 70, 27}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 43, 26, 55, 156, 255, 118, 167, 201}, 84}, {{156, 60, 245, 247, 189, 0, 130, 170, 58, 237, 7, 145, 133, 193, 32, 203}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 3, 43, 84, 236}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 229}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 251, 145, 63}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 119, 106, 144, 170}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 194, 142, 243, 21, 210, 11, 154, 226}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 25, 169, 66}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 162, 243, 33, 156}, 84}, {{156, 60, 245, 247, 189, 0, 0, 152, 107, 124, 63, 24, 129, 139, 175, 83}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 84}, {{156, 60, 245, 247, 189, 0, 0, 106, 230, 243, 77, 101, 80, 152, 94, 191}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 85, 64, 86}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 84}, {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 92, 198}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 222}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 55, 6}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 50, 47, 136}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 116}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 104}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 120, 165}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 26, 179}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 201}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 38, 129, 173}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 232, 173, 169}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 99, 213, 245}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 192, 195}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 89, 59, 69}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 252, 47}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 189, 60, 16}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 43, 215, 212}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 36}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 34, 194}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 198}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 47}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 75, 68}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 47, 129}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 222, 105, 202}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 71, 54}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 33}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 221}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 193, 39, 193}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 196}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 157}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 217, 16, 200}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 231, 64, 142}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 192, 42, 239}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 209, 133}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 56, 59, 74}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 226, 254}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 79, 125, 67}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 85, 42, 67}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 180, 89}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 206, 246, 151}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 217, 34, 26}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 124, 62, 105}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 9, 85, 101}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 70, 231, 75}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 77, 228}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 29, 229, 64}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 83, 179}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 7, 156, 74}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 152, 132, 240}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 248, 172, 192}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 91, 127}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 105, 34, 69}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 151, 238}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 65}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 82}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 77, 229}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 182, 175, 148}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 230, 19}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 55}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 34, 91}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 104}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 51}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 175, 240}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 250, 45}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 54, 33, 206}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 155, 146}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 25}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 206}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 183, 35}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 88, 196}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 13, 6}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 25}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 178}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 40}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 84}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 96, 232, 227}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 184, 244, 193}, 33}, {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 66, 216}, 33}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 106, 164}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 38}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 104, 155}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 218, 201}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 104}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 255}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 207}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 78, 225}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 150, 221, 211, 237}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 19}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 251, 132, 245}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 46}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 129}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 25}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 10, 224, 5}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 122, 27, 184}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 75, 6}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 38, 30, 127}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 101}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 39, 45}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 69, 27, 81}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 201, 235}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 255, 111, 35}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 116, 32, 139}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 156, 174, 105, 6}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 114}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 1, 175}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 173, 21}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 167, 80, 140}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 48, 18, 108}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 239, 179}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 76, 194, 227}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 58, 171}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 114, 49}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 218, 150, 247}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 76}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 42, 224}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 220, 104}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 250, 196, 240}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 213}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 97, 162}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 68, 84}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 23}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 96, 184, 189, 190}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 203, 205, 147, 33}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 216, 137}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 98, 247, 112}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 230, 199}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 254, 247}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 10, 68}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 166}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 155, 102, 161}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 62}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 150, 56}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 143}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 132, 245, 78, 93}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 69}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 26, 49, 198, 129}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 165}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 53, 147}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 172, 31, 216}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 183, 217, 29}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 66, 27, 18, 161}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 160, 163}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 162, 157, 29}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 212, 128, 57}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 239}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 39, 218}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 220}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 135, 166, 175}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 127}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 7, 222, 109}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 137}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 223, 45}, 199}, {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 179, 19, 52}, 199}, {{156, 77, 105, 235, 145, 216, 0, 0, 49, 131, 87, 48, 73, 167, 80, 250}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 121, 166, 240, 190, 77, 3, 228}, 52}, {{156, 77, 105, 235, 145, 216, 0, 91, 205, 40, 0, 73, 60, 211, 93, 124}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 222, 167, 185, 30}, 52}, {{156, 77, 105, 235, 145, 216, 252, 125, 18, 190, 155, 22, 131, 173, 0, 119}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 111, 231, 31, 201, 15, 207, 71}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 52}, {{156, 77, 105, 235, 145, 216, 0, 250, 114, 123, 105, 134, 71, 113, 60, 4}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 189, 212, 242}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 216, 62, 94, 199, 21, 41}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 196, 48, 253, 115, 126, 48, 217}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 254, 244, 158}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 209, 68}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 214, 124, 34, 53, 239, 10}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 54, 208, 84, 33}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 90, 176}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 214, 248, 96, 109}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 182, 210, 95}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 215, 72, 209, 142, 240}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 255, 85}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 211, 230, 178}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 52}, {{156, 77, 105, 235, 145, 216, 233, 131, 251, 153, 140, 93, 173, 248, 218, 156}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 117, 91, 16, 200, 36, 114, 123}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 169, 233}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 76, 159, 250, 155, 254, 87, 97}, 52}, {{156, 77, 105, 235, 145, 216, 0, 73, 196, 196, 61, 11, 46, 153, 4, 201}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 109, 69, 196}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 74, 157, 200, 219}, 52}, {{156, 77, 105, 235, 145, 216, 0, 241, 23, 98, 216, 21, 127, 169, 247, 137}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 216, 117, 47, 244, 228, 94, 99}, 52}, {{156, 77, 105, 235, 145, 216, 0, 147, 95, 58, 5, 251, 15, 131, 140, 245}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 179, 212, 171, 52}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 55, 159, 25, 22, 31, 2}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 241, 227, 109, 186}, 52}, {{156, 77, 105, 235, 145, 216, 0, 204, 18, 229, 94, 113, 249, 129, 41, 206}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 237, 73, 145, 59, 13, 34, 18, 46}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 202, 209, 189, 143, 237, 38, 143}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 206, 180, 144, 226, 154, 58, 173, 150}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 132, 173, 201, 146, 189, 26, 100}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 122, 248, 111, 201, 214, 223, 151, 195}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 85, 81}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 162, 198, 138}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 60, 118, 146, 221, 38, 82, 21, 151}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 178, 94, 152, 170, 13, 5}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 52, 245, 9, 249, 191, 200, 23, 97}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 180, 141, 92, 92, 243, 58, 29, 158}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 69, 97, 158, 209, 195, 176, 169, 58}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 91, 142, 102, 253, 223, 171, 175, 255}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 69, 54, 131, 134, 73, 106}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 5, 218}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 8, 197}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 82, 78, 33, 187, 206, 125, 5, 57, 115}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 65, 94, 233}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 128, 197, 34, 126, 41}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 58, 63, 221, 172, 94, 141, 30}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 129, 72, 210}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 232, 94, 25, 11, 242}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 60, 253, 188, 65, 31, 181, 35, 211}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 12, 173, 27, 185, 18, 156}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 40, 217, 145}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 126, 219, 120, 247, 187}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 140, 49, 157, 255, 130, 79, 78}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 108, 59, 47, 111, 135, 69, 116, 76, 102}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 80, 87, 51}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 104, 122, 46}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 232, 180}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 187, 81, 101}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 177, 233, 241}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 177, 147, 106, 165, 254, 188, 194}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 81, 132, 107, 254, 50, 137, 75, 57}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 90, 206, 153, 195, 167, 14, 187, 178}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 123, 149, 119, 78, 239}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 213, 181, 53, 184, 53, 66, 126}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 136, 67, 215, 216, 76}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 193, 141, 163}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 63, 25, 64, 37, 157, 156}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 199, 76, 31, 227, 47}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 44, 124, 156, 183, 185, 247}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 239, 49, 21, 89, 110}, 52}, {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 249, 40, 109, 227}, 52}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 221}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 110}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 31}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 52}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 34}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 159}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 207}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 23}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 190}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 25}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 150}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 176}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 183}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 61}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 39}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 198}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 192}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 238}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 81}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 143}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 13}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 13}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 40}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 121}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 111}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 4}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 116}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 48}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 210}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 135}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 161}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 41}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 163}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 131}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 243}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 247}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 33}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 86}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 5}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 238}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 214}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 109}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 107}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 183}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 63}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 184}, {{13, 30, 0, 0, 0, 0, 0, 0, 177, 207, 35, 173, 188, 108, 116, 243}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 125, 220, 252, 184, 65, 240, 1, 97}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 129}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 216, 157}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 227, 103, 123}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 29, 166, 219, 22, 146, 122, 239}, 124}, {{13, 30, 0, 0, 0, 75, 227, 253, 123, 8, 69, 159, 103, 150, 127, 74}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 132, 138, 170, 163, 18, 132, 173}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 56, 49, 35, 39, 107, 231, 192, 160, 144, 243, 155, 34}, 124}, {{13, 30, 0, 0, 0, 0, 181, 141, 211, 91, 216, 247, 137, 107, 103, 127}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 249, 208, 112, 194, 98, 13, 46, 96}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 185, 240, 235, 28}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 47, 136, 103, 249}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 10, 105}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 124}, {{13, 30, 0, 0, 0, 58, 147, 118, 66, 161, 44, 82, 67, 12, 35, 88}, 124}, {{13, 30, 0, 0, 0, 119, 51, 245, 217, 182, 62, 178, 43, 89, 227, 20}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 176}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 2}, 124}, {{13, 30, 0, 0, 0, 0, 0, 90, 103, 91, 200, 96, 230, 8, 102, 39}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 172, 56, 192, 206, 144, 179, 105}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 182, 182, 152, 87, 217, 51, 216, 99}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 78, 167, 7}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 54, 58, 30, 2, 169, 62, 10, 54}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 124}, {{13, 30, 0, 0, 0, 0, 0, 6, 203, 210, 36, 157, 139, 130, 157, 170}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 252, 20, 200, 238, 201, 73, 214, 113}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 142, 243, 79, 187, 39, 16}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 165}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 245}, 124}, {{13, 30, 0, 248, 190, 136, 227, 151, 148, 170, 74, 119, 164, 168, 104, 143}, 124}, {{13, 30, 0, 0, 0, 0, 212, 122, 44, 205, 65, 248, 187, 109, 183, 17}, 124}, {{13, 30, 0, 0, 234, 3, 118, 33, 215, 11, 175, 172, 111, 169, 93, 223}, 124}, {{13, 30, 0, 0, 120, 204, 77, 206, 49, 88, 234, 231, 115, 36, 224, 18}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 157}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 208, 28, 131, 167, 32, 66, 157, 5}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 174, 214, 56, 33, 165, 47}, 124}, {{13, 30, 0, 0, 0, 0, 144, 248, 179, 170, 178, 216, 146, 47, 244, 50}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 190}, 124}, {{13, 30, 0, 0, 25, 66, 77, 234, 160, 162, 197, 215, 69, 104, 33, 245}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 130, 32, 15}, 124}, {{13, 30, 0, 0, 0, 0, 110, 207, 186, 110, 177, 181, 44, 224, 196, 109}, 124}, {{13, 30, 0, 0, 0, 228, 79, 221, 169, 251, 13, 95, 104, 5, 131, 178}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 70, 159, 49, 92}, 124}, {{13, 30, 0, 0, 0, 0, 0, 97, 219, 234, 47, 163, 8, 114, 193, 93}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 202}, 124}, {{13, 30, 0, 0, 0, 0, 124, 196, 37, 10, 139, 237, 245, 160, 9, 165}, 124}, {{13, 30, 0, 0, 7, 85, 140, 2, 194, 6, 167, 79, 147, 113, 166, 1}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 77, 192, 237, 139, 158, 142, 25}, 124}, {{13, 30, 0, 0, 241, 29, 229, 222, 239, 165, 127, 79, 10, 113, 255, 112}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 47, 252, 106, 119, 164, 163, 6, 29}, 124}, {{13, 30, 0, 0, 219, 110, 29, 130, 67, 129, 156, 70, 213, 121, 149, 84}, 124}, {{13, 30, 0, 0, 0, 130, 99, 227, 140, 10, 80, 103, 6, 43, 140, 237}, 124}, {{13, 30, 0, 183, 26, 234, 198, 244, 222, 166, 5, 219, 158, 107, 33, 254}, 124}, {{13, 30, 0, 0, 0, 77, 45, 182, 246, 216, 58, 255, 6, 122, 169, 81}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 69, 137, 200, 234, 42, 80, 207, 44}, 124}, {{13, 30, 0, 0, 0, 0, 0, 169, 7, 95, 145, 128, 237, 234, 92, 98}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 217, 157, 115, 165, 131, 96}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 103}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 59, 15, 88}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 93, 11, 165, 147, 151, 70, 67, 18, 229, 242, 195}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 165, 110}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 32}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 168, 233}, 124}, {{13, 30, 0, 0, 0, 0, 0, 44, 150, 53, 133, 171, 58, 197, 134, 35}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 124}, {{13, 30, 0, 0, 0, 0, 0, 20, 195, 87, 133, 122, 55, 165, 210, 103}, 124}, {{13, 30, 0, 223, 88, 253, 231, 115, 102, 124, 246, 145, 116, 85, 185, 15}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 205}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 41, 255, 148}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 34, 37, 62, 196, 38, 89, 169, 67}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 164, 239, 214, 82, 154, 65}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 124}, {{13, 30, 0, 0, 0, 123, 144, 24, 242, 221, 255, 230, 21, 208, 179, 42}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 145, 65, 209, 103, 185, 146, 202}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 136, 7, 201, 186, 215, 119, 87, 58}, 124}, {{13, 30, 0, 0, 117, 29, 187, 192, 177, 16, 235, 44, 225, 102, 251, 86}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 226}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 69, 229, 245, 130}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 90, 21, 44, 209, 250, 79, 162, 47}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 249, 3, 235, 254, 96, 140, 73, 14}, 124}, {{13, 30, 0, 5, 97, 180, 239, 167, 163, 123, 164, 54, 68, 35, 104, 149}, 124}, {{13, 30, 0, 0, 0, 0, 56, 185, 66, 212, 19, 45, 75, 157, 107, 72}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 170, 178, 139}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 122}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 245, 194, 206, 255, 243, 73, 193}, 124}, {{13, 30, 0, 68, 123, 164, 71, 132, 211, 186, 52, 40, 254, 242, 11, 161}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 110, 115, 61}, 124}, {{13, 30, 0, 0, 0, 118, 170, 235, 113, 86, 252, 26, 201, 62, 63, 70}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 197}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 124}, {{13, 30, 0, 79, 50, 213, 174, 21, 197, 157, 214, 183, 101, 11, 145, 142}, 124}, {{13, 30, 0, 0, 0, 0, 205, 132, 160, 209, 22, 252, 151, 165, 43, 48}, 124}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 183, 170}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 95}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 81, 113}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 224, 49}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 28}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 57}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 253, 49}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 182, 65}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 129, 29}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 211, 77}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 73}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 201, 131}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 89}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 50}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 11}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 193}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 55}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 229}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 15, 43}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 46, 137}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 137, 208}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 89}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 154}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 55, 37}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 222}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 87}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 5, 69}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 197, 154}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 69}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 213, 152}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 173}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 10}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 98, 186}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 207, 133}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 251}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 65}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 242, 76}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 65}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 232}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 140}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 133, 165}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 172, 40}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 125, 31}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 100}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 147}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 219, 90}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 29}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 26}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 133}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 114, 189}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 238}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 255}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 136, 73}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 189}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 88}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 128}, {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 156}, 128}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 161, 11, 239, 218, 128, 113, 227, 158, 29}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 55, 126, 78}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 129, 50, 181, 249, 168, 4, 126}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 216, 68, 171, 30, 163, 116}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 1, 220, 185, 239, 152, 139, 96}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 160, 199, 122, 156, 237}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 51, 100, 40, 222, 211, 181}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 86, 26}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 13, 35, 38}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 217, 99, 217, 48, 168, 64, 154, 76}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 194, 9}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 94, 12, 91, 78, 243, 52, 185, 199}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 240, 235, 162, 36, 235, 141}, 255}, {{15, 192, 109, 31, 149, 221, 0, 131, 139, 125, 9, 145, 158, 182, 248, 169}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 93, 161, 230}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 15, 250, 6, 120, 242, 1, 157}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 35, 187, 131, 90, 51, 82, 19}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 53, 65, 81, 106, 82, 228, 76, 107}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 19, 135, 41, 43, 8}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 243, 183}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 11, 123, 201}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 177, 38, 21, 114, 33, 114, 125}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 101, 227, 249, 187, 55}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 3, 209, 55, 24}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 44, 63, 35}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 207, 192, 199, 216, 43, 98}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 237, 97, 86, 24, 112, 246, 72, 201}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 181, 41, 124, 201, 229, 39, 146, 6}, 255}, {{15, 192, 109, 31, 149, 221, 0, 149, 195, 168, 168, 226, 140, 150, 135, 34}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 39, 71, 118}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 28, 133, 221, 89, 243}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 2, 154, 107}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 94, 195, 134}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 138, 219, 176, 101, 101, 57, 137}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 159, 132, 248, 255, 190}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 66, 145}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 226, 24}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 120, 185}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 122, 31, 9}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 182, 244}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 133, 80, 215, 78, 32, 45, 9}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 36, 151, 72, 168}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 181, 16, 90, 229, 227, 142, 137, 197}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 49, 149, 241, 176}, 255}, {{15, 192, 109, 31, 149, 221, 0, 68, 71, 233, 117, 249, 68, 243, 182, 162}, 255}, {{15, 192, 109, 31, 149, 221, 0, 93, 15, 163, 254, 205, 184, 36, 115, 77}, 255}, {{15, 192, 109, 31, 149, 221, 0, 137, 48, 102, 80, 3, 214, 233, 16, 2}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 227, 43, 125, 10, 133, 255, 111}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 78, 123, 82, 171, 177, 105}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 66, 176, 87, 202, 9, 175, 17}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 5, 231, 245, 13, 24, 136, 164}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 43, 192, 222}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 62, 213, 231, 64, 255, 63, 216, 159, 11}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 125, 30, 152, 142, 129, 249}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 163, 133, 137, 149}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 255, 110, 110}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 204, 124, 166, 169, 3, 45, 33}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 102, 113, 145}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 14, 184, 15}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 64, 63, 2, 97, 23, 36, 232, 102}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 185, 192, 203, 36, 148, 129, 234}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 59, 152, 29, 251}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 171, 180}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 143, 213, 218, 53, 13, 127, 25}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 100, 218, 135}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 170, 26, 11, 78, 106, 127}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 51, 41, 245, 221, 24, 162, 223}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 215, 199, 132, 153}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 29, 38, 58, 153, 215}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 141, 248, 167, 143, 132, 210, 87}, 255}, {{15, 192, 109, 31, 149, 221, 0, 126, 179, 231, 36, 141, 60, 230, 110, 35}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 92, 151, 119, 49, 51}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 253, 95}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 55, 49, 82, 32}, 255}, {{15, 192, 109, 31, 149, 221, 0, 21, 214, 204, 178, 139, 25, 89, 58, 170}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 81, 81, 251, 204}, 255}, {{15, 192, 109, 31, 149, 221, 0, 253, 178, 50, 85, 78, 156, 24, 189, 39}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 85, 237, 136, 204, 21}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 21, 196}, 255}, {{15, 192, 109, 31, 149, 221, 0, 0, 0, 128, 104, 251, 187, 181, 214, 181}, 255}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 21}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 131, 126}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 121, 236}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 3, 190}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 77}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 114}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 138, 118}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 7, 140}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 155, 32}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 11}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 81}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 131}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 41}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 79, 79}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 85, 28}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 18}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 61, 99}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 78}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 22}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 196, 90}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 71}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 163, 33}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 22, 203}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 229, 154}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 126, 119}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 13, 124}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 129, 49}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 243}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 255, 252}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 118}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 171}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 100}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 199}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 161}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 30, 204}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 183, 91}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 124}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 172, 60}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 121, 178}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 87}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 226, 53}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 132}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 58}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 248}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 233, 167}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 168}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 230, 163}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 141, 197}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 36, 135}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 130, 114}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 199}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 20}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 235}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 157}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 89, 51}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 146}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 132, 120}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 58, 148}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 39}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 41, 36}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 23, 208}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 124}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 124, 225}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 146}, {{16, 229, 224, 0, 0, 39, 201, 227, 80, 231, 159, 111, 140, 75, 73, 113}, 172}, {{16, 229, 224, 0, 0, 0, 0, 109, 32, 0, 97, 180, 58, 254, 50, 107}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 91, 136, 141, 56, 107, 81, 228}, 172}, {{16, 229, 224, 0, 0, 229, 171, 151, 98, 176, 195, 210, 223, 4, 233, 75}, 172}, {{16, 229, 224, 0, 0, 0, 60, 65, 31, 226, 219, 149, 202, 20, 118, 119}, 172}, {{16, 229, 224, 0, 20, 99, 192, 31, 246, 215, 24, 152, 60, 74, 6, 19}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 38, 62, 149, 134, 52, 158, 179, 82}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 97, 111, 216}, 172}, {{16, 229, 224, 0, 0, 0, 60, 21, 47, 31, 169, 188, 78, 66, 105, 176}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 213, 186, 121, 125, 106, 127, 129, 65}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 172}, {{16, 229, 224, 0, 0, 190, 235, 215, 205, 183, 173, 80, 11, 131, 157, 222}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 129, 181, 66, 44, 92, 233, 194, 200}, 172}, {{16, 229, 224, 0, 0, 0, 0, 22, 100, 78, 140, 43, 242, 225, 52, 83}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 23, 147, 117, 84, 36, 42}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 172, 218, 122, 21, 134, 86, 102}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 241}, 172}, {{16, 229, 224, 0, 0, 0, 0, 165, 113, 150, 139, 189, 34, 55, 91, 222}, 172}, {{16, 229, 224, 0, 0, 0, 0, 136, 78, 14, 200, 143, 75, 114, 146, 56}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 213, 112, 11, 187, 139, 185}, 172}, {{16, 229, 224, 0, 0, 49, 83, 205, 7, 142, 130, 111, 111, 151, 250, 231}, 172}, {{16, 229, 224, 0, 0, 0, 0, 65, 57, 14, 29, 159, 9, 165, 85, 180}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 24, 129, 205, 166, 121, 44, 228}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 32, 7, 255}, 172}, {{16, 229, 224, 0, 0, 0, 0, 236, 215, 182, 196, 251, 161, 213, 162, 79}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 176, 226, 57, 236, 84, 107, 154}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 172}, {{16, 229, 224, 0, 0, 0, 0, 82, 200, 148, 128, 203, 116, 139, 36, 111}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 14, 156, 1, 79, 240, 159, 71, 122, 10}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 115, 205}, 172}, {{16, 229, 224, 0, 132, 91, 107, 195, 239, 119, 100, 79, 160, 89, 69, 44}, 172}, {{16, 229, 224, 0, 0, 106, 46, 139, 58, 226, 128, 102, 162, 130, 28, 60}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 204, 237, 131}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 189}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 136}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 126, 240, 242, 229, 174}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 72, 245}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 79, 48, 85, 76, 192}, 172}, {{16, 229, 224, 0, 0, 0, 0, 251, 95, 42, 124, 253, 86, 76, 240, 77}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 188, 102, 12, 232, 24}, 172}, {{16, 229, 224, 0, 0, 245, 104, 149, 107, 198, 181, 12, 95, 77, 53, 160}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 79, 125, 28, 242, 67}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 11, 211, 64}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 125, 55}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 137, 213, 215, 194, 48, 111, 14}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 121, 160, 229}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 133, 141}, 172}, {{16, 229, 224, 0, 239, 151, 123, 197, 39, 125, 201, 84, 221, 130, 17, 228}, 172}, {{16, 229, 224, 0, 172, 29, 191, 77, 128, 254, 90, 163, 12, 16, 159, 173}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 54, 153, 169, 192, 190, 60, 98, 166}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 240, 203, 109, 29, 245, 114, 61}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 53, 104, 159, 151, 39}, 172}, {{16, 229, 224, 0, 0, 138, 157, 172, 251, 209, 69, 27, 199, 106, 57, 235}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 235, 120, 210, 202, 165, 93, 233}, 172}, {{16, 229, 224, 0, 0, 0, 0, 99, 224, 236, 141, 206, 255, 110, 175, 37}, 172}, {{16, 229, 224, 0, 0, 244, 18, 218, 158, 155, 47, 204, 19, 110, 101, 96}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 204, 18}, 172}, {{16, 229, 224, 0, 0, 222, 35, 189, 175, 37, 44, 66, 197, 93, 38, 188}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 112, 78, 107, 129, 173, 236, 21, 35}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 47, 33, 37}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 170, 23, 41, 164, 119}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 145, 68, 132}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 119, 173, 117}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 49}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 251, 200, 213, 144, 137}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 4, 172, 188, 87, 151, 64}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 25}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 39, 156, 243, 132, 1, 53}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 113}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 229, 201, 100, 163, 3, 114, 208, 18}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 164, 36, 154, 3, 173}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 142}, 172}, {{16, 229, 224, 0, 184, 34, 200, 187, 195, 62, 250, 134, 91, 245, 154, 198}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 2, 251, 54, 122, 12, 110, 160, 226}, 172}, {{16, 229, 224, 0, 0, 0, 0, 27, 203, 175, 82, 238, 7, 1, 196, 114}, 172}, {{16, 229, 224, 0, 0, 0, 9, 152, 226, 200, 210, 14, 223, 36, 117, 209}, 172}, {{16, 229, 224, 0, 0, 0, 0, 165, 155, 239, 244, 89, 193, 105, 54, 164}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 236, 215, 76, 220, 183, 103}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 201, 239, 33, 242, 59, 192, 106, 248}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 170, 71, 116, 15, 229, 172, 214}, 172}, {{16, 229, 224, 0, 0, 0, 184, 117, 173, 86, 210, 180, 111, 205, 220, 36}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 8}, 172}, {{16, 229, 224, 0, 110, 0, 54, 22, 69, 161, 136, 104, 209, 234, 118, 248}, 172}, {{16, 229, 224, 0, 0, 165, 253, 178, 145, 124, 6, 175, 88, 245, 189, 164}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 172}, {{16, 229, 224, 0, 0, 237, 45, 36, 7, 151, 15, 170, 69, 160, 103, 15}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 229, 105, 62, 215, 93}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 91, 150, 192, 217, 10, 48}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 172, 45, 59, 47, 41, 236, 179, 246}, 172}, {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 86, 238, 253, 148, 174}, 172}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 78, 159}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 96}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 143, 101, 221}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 108, 215, 157, 219}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 24, 193, 21, 235, 157}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 241}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 71, 80, 81, 73, 2, 86}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 66, 16, 134}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 137, 121}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 54, 21, 174}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 16, 122, 155, 62}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 186, 202, 135, 109}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 59, 34, 127}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 89}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 87, 39, 79, 252}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 113, 131, 143, 161}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 45, 255, 90, 251, 12}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 41, 237, 151, 67, 47}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 208}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 47, 135, 140, 129, 1}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 98, 125, 248, 226}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 255}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 168, 199}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 35, 37, 61, 178}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 218}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 119, 184}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 34}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 200, 61, 159, 139, 169, 141}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 149, 87}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 142, 228, 89}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 115, 135, 145}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 121, 146}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 101, 128, 240}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 4, 111, 34, 238, 180, 18}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 216, 123, 95, 119, 247, 185, 100}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 126}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 62}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 189, 166, 156, 171, 123}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 55, 134, 110}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 3, 127, 155, 194, 238}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 240}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 214, 29, 52}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 48, 146, 54, 62, 3, 168}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 12, 44, 236, 39, 151}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 140, 201, 116, 186, 109, 161}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 64, 146, 78, 37, 76}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 147, 1, 243, 173, 187, 40}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 5, 130}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 211, 136, 47, 45, 176, 202, 74}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 253, 118, 118, 74, 185, 98}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 238, 175, 34, 132, 42, 47}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 227, 163, 210, 12, 131}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 144}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 186, 140}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 89, 45, 235, 138, 187}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 203}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 139, 0, 58, 170, 248, 95}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 172, 226, 211, 185}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 122, 70}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 58, 111, 100, 118, 139}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 174, 28, 153}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 234, 77, 176}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 69, 3, 227, 68}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 105, 124, 78, 133, 62}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 146}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 169, 97}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 117, 133}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 146, 41}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 196, 122}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 157, 199, 161, 53, 25, 137}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 168, 135, 211}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 50, 59}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 15}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 160}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 181, 87, 201, 241, 163}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 182, 61, 185, 205, 133, 67}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 33, 130, 77, 77, 10}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 228}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 122, 118, 95, 66, 180}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 229, 172, 106, 107, 247, 82}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 5, 239, 189, 98}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 161, 189, 75, 247}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 131, 39, 1, 77}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 192, 75, 226}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 116}, {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 141, 77, 40}, 116}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 126, 151, 166, 98, 84}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 81}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 122, 251, 223, 151, 184}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 182, 178, 254, 83, 217, 16}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 95, 210}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 23, 93, 95}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 167, 62, 205, 211}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 100, 180, 53, 219, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 23, 178, 98, 137, 25, 79}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 125, 57, 87, 31, 75, 202}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 201, 188, 138}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 109, 147, 105, 232, 151}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 223, 5, 19, 89, 6, 249, 240}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 100, 31, 30, 180, 250, 22}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 49}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 41, 132, 223, 165, 244, 29}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 146, 14, 195, 115, 7, 203}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 20}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 107}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 133}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 56, 62, 255, 82, 11, 187}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 157, 7, 108, 101, 3, 181}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 209}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 241, 79}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 168, 86, 24, 21}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 107, 178, 221, 33, 48, 159}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 116}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 182, 213, 94, 52, 6, 112}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 79, 15, 3}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 184, 210, 168}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 175}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 134, 2, 138, 222}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 158, 173, 38}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 77}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 236, 25, 11, 101, 43, 236}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 8}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 8, 160, 140, 171}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 249, 29, 44, 15}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 99, 229, 173}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 199, 168}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 216}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 69, 160, 220, 120, 14, 250, 203}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 37, 215, 185, 79, 62, 132}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 3, 203, 20, 159, 91, 6}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 183, 98, 183}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 174, 136, 137}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 127, 28, 102}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 248}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 86, 76, 93, 181, 104}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 188, 70, 195, 28, 15, 126, 252}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 113, 115, 192, 198, 219, 207}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 163, 24, 247, 181, 9, 72}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 15, 156}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 239, 65, 170, 181, 213, 79, 78}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 112, 154, 254, 233}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 154, 54, 18, 127, 185, 86, 11}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 245, 1}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 219}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 119, 85, 200, 65, 0, 107, 151}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 157, 232, 13, 163, 168, 212, 234}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 41, 185, 118}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 191, 237, 145}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 178, 136}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 25, 169}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 177, 113, 196}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 92}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 34, 81, 86, 46, 233}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 154, 54, 206, 210, 159}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 54, 254, 183}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 246, 46, 252, 242, 80}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 211, 96, 141, 59}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 22, 216, 229, 96, 204, 35, 34}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 134, 172, 162, 141, 8}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 253, 71, 53, 181, 9, 185, 197}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 117, 48}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 11, 134, 108}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 53}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 237, 52, 233, 233, 48}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 114}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 76, 123, 89, 11, 172}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 230, 230, 205, 158, 98, 34, 84}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 103, 119, 198, 246}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 190}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 91, 132, 250, 244, 213}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 194, 106, 254, 204, 207}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 151, 21}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 48}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 132}, 189}, {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 78, 151, 129, 145, 211, 248}, 189}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 191, 49, 13}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 80}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 67, 2, 103, 162, 157, 37}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 96, 56}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 209, 143, 251, 19, 164, 186}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 155}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 152, 230, 223}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 228, 26, 184, 65, 133}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 222, 244, 61}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 254, 199, 223, 127, 244, 159}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 29, 133}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 219, 227}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 169, 208, 8, 102}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 9, 170, 43, 21, 46, 95}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 126, 135}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 228, 31, 137, 96, 154}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 234, 108, 135, 13, 216}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 88, 222, 132, 164, 160}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 178, 17, 81, 43}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 211, 229, 232, 57}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 203, 23, 112}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 213, 135, 71, 132}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 47, 66, 146}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 166, 12, 60}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 200, 210, 186, 121, 69, 89}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 177, 82, 238}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 196, 226, 104, 79, 30}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 130, 103, 229}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 165}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 101, 113, 137}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 24}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 28, 157, 239, 119, 79, 128}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 7}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 184, 106, 10}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 248, 8, 30}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 61, 65, 29, 88}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 25, 75, 3, 36, 137}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 241, 160, 226, 134, 68}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 92, 90, 240, 185, 56, 206, 200}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 196, 237, 82, 105, 147}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 91, 111, 83}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 17, 201, 223}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 118}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 59, 7, 84}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 54}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 215, 13}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 134, 53, 181, 237, 166}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 200, 4, 125, 69, 220, 75}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 191, 86, 118, 220, 255}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 18, 40, 128, 36}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 111, 133, 203}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 232, 142, 117, 18, 176, 230}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 132, 109}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 16, 162, 48, 78, 96}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 146, 197, 223, 237}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 151, 34, 178}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 45}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 109, 251, 180, 127, 240, 223}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 27}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 92, 246}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 207, 13, 46, 77, 81, 146}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 110, 19, 29, 240, 184, 32}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 135, 43}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 95, 240, 144, 103}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 64, 130, 137, 116}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 19, 2, 51, 157, 168, 37}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 169, 27, 176, 231, 199}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 28, 183, 195, 93, 103}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 210}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 45, 57, 169, 136, 32, 80}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 63}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 193, 101, 71}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 223, 139}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 176, 109}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 251, 95, 172, 49, 115, 15}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 65, 150, 65}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 235, 165}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 197}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 108, 95}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 150, 35, 204, 216, 45, 243, 212}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 35}, 10}, {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 129, 13}, 10}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 96, 41}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 97, 187, 78}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 9}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 145}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 17}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 204, 93, 43}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 87}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 103}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 201}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 114, 122}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 63, 6}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 170, 136}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 10}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 138, 195}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 177, 205, 104}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 34}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 7}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 155}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 240}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 135}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 139, 72, 165}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 206}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 225, 20}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 169, 114, 29}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 134, 3}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 240, 45, 140}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 88}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 68, 94}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 45}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 142, 143, 158}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 13, 80}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 249, 238}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 96, 90}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 133, 112}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 153, 99, 141}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 63, 223}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 33}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 161, 237}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 111}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 38, 60}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 132}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 133, 70}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 255, 17}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 29, 173, 210}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 84}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 67, 34}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 215, 98, 120}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 163, 13, 110}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 67, 69}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 220, 97}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 235}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 75, 226}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 156, 20}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 80, 152}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 250}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 3, 45, 220}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 205}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 212}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 210, 146, 84}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 252, 203}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 37, 5}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 50}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 228}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 102, 210}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 132, 117}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 29, 75}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 73, 138}, 184}, {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 103, 22}, 184}, {{170, 82, 72, 53, 128, 0, 0, 0, 45, 80, 100, 94, 160, 188, 120, 119}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 98}, {{170, 82, 72, 53, 128, 0, 0, 118, 22, 190, 45, 123, 118, 42, 24, 110}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 1, 173, 222, 59, 113, 208}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 225, 42, 207, 173, 38, 12, 242, 233}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 146}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 219, 137, 41, 108, 157, 195, 35}, 98}, {{170, 82, 72, 53, 128, 0, 103, 59, 105, 121, 121, 159, 196, 94, 69, 210}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 81, 183, 120, 76, 226, 162, 193}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 82, 151, 204, 147, 192, 166, 10, 52}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 98, 212, 204, 92, 93, 112, 126, 42}, 98}, {{170, 82, 72, 53, 128, 0, 0, 119, 180, 178, 125, 200, 1, 235, 96, 169}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 33, 218, 97, 17, 192, 173, 252}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 69}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 92, 135, 169, 233, 32, 80, 170, 57}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 81, 113, 233, 142, 236, 205, 144}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 8, 218, 200, 229, 205, 191}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 174, 38, 80, 35, 54, 185}, 98}, {{170, 82, 72, 53, 128, 0, 0, 124, 68, 211, 56, 231, 222, 71, 237, 99}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 158, 28, 77, 122, 181}, 98}, {{170, 82, 72, 53, 128, 64, 209, 32, 123, 212, 148, 249, 113, 180, 63, 102}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 116, 70, 229, 189, 3, 19, 1}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 144, 98, 58, 3, 142, 187, 100}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 101, 154, 85, 87, 131, 135}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 46, 127, 181, 17, 128}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 134, 28, 236, 202, 215, 151, 3, 188, 82, 70, 38}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 130, 180, 175, 244, 77, 122, 164}, 98}, {{170, 82, 72, 53, 128, 0, 0, 245, 202, 39, 244, 124, 179, 143, 44, 217}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 174, 255, 199}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 105, 180, 229, 20, 232, 121, 226, 115, 46}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 107, 9, 207, 212}, 98}, {{170, 82, 72, 53, 128, 0, 0, 155, 131, 197, 175, 27, 159, 139, 22, 150}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 21, 140, 15, 200, 230, 40}, 98}, {{170, 82, 72, 53, 128, 30, 140, 114, 40, 65, 172, 145, 122, 44, 104, 12}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 57, 100, 40, 86, 163, 226, 35}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 215, 190, 159, 96, 54, 129, 79}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 11, 197, 197, 150, 28, 134}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 98, 72, 150}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 164, 145, 59}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 43, 60, 78, 9, 3, 238, 56, 57}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 126, 0, 254, 25, 45}, 98}, {{170, 82, 72, 53, 128, 73, 192, 239, 58, 74, 156, 212, 173, 115, 229, 184}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 115}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 80, 112, 137, 152, 91, 188, 59, 172}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 213, 156, 168}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 242, 44, 183, 254, 106, 157}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 98}, {{170, 82, 72, 53, 128, 0, 136, 171, 71, 24, 118, 49, 188, 63, 60, 207}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 253, 82, 227, 22, 117, 136, 241, 142}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 98, 211, 159}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 10}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 116, 35, 67, 4, 112, 61, 245}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 143, 121, 100, 246, 106}, 98}, {{170, 82, 72, 53, 128, 123, 146, 16, 80, 185, 252, 86, 35, 170, 173, 205}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 68, 254, 168, 107, 191, 17}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 207, 61, 138}, 98}, {{170, 82, 72, 53, 128, 239, 125, 102, 231, 143, 49, 70, 205, 84, 100, 111}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 174, 96, 198, 55}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 180, 240, 99, 111}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 207, 104, 212, 250, 6, 20, 238}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 194}, 98}, {{170, 82, 72, 53, 128, 29, 5, 68, 89, 146, 78, 244, 45, 113, 118, 110}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 169}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 217, 212, 165}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 160}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 36, 239, 0, 66, 14, 244, 137, 203}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 48, 245, 99, 51, 110, 87, 99}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 5, 78, 66, 19}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 115, 186, 5, 212, 120, 10, 142}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 96}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 16, 219, 52, 189, 95}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 39}, 98}, {{170, 82, 72, 53, 128, 0, 50, 193, 13, 178, 254, 134, 96, 215, 209, 225}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 160, 135, 24, 179, 244, 94}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 160, 249, 207, 175}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 115, 132, 85, 2, 70, 148, 101, 141}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 214, 193, 63}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 216, 158, 139}, 98}, {{170, 82, 72, 53, 128, 0, 155, 27, 137, 169, 81, 0, 91, 109, 181, 107}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 117, 176, 230}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 112, 35, 203, 144, 57, 86, 58, 118}, 98}, {{170, 82, 72, 53, 128, 0, 0, 0, 0, 215, 26, 33, 61, 147, 235, 195}, 98}, {{170, 82, 72, 53, 128, 19, 249, 232, 159, 179, 48, 237, 49, 188, 51, 36}, 98}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 182, 158, 99, 143, 183}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 133, 183, 11, 1}, 37}, {{152, 100, 37, 122, 242, 64, 0, 118, 67, 8, 129, 108, 108, 41, 97, 155}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 36, 181, 241, 118}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 25, 131, 61}, 37}, {{152, 100, 37, 122, 242, 64, 0, 58, 230, 150, 26, 44, 196, 70, 167, 13}, 37}, {{152, 100, 37, 122, 242, 64, 228, 99, 197, 73, 135, 169, 69, 27, 130, 70}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 233, 134, 48, 190, 95, 76, 175, 69}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 133, 204, 209, 90, 219, 245, 55, 161}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 231, 23, 156, 173, 141}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 166, 210, 70, 213, 155, 39, 113}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 185, 210, 45, 196, 251, 255}, 37}, {{152, 100, 37, 122, 242, 64, 14, 44, 102, 19, 26, 13, 182, 165, 25, 201}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 7, 66, 192}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 89, 243, 78, 34}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 119, 28, 39, 113, 73}, 37}, {{152, 100, 37, 122, 242, 64, 0, 204, 154, 172, 221, 151, 237, 186, 76, 183}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 29, 118}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 53, 26, 107, 129}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 55, 119, 82, 209, 9, 233}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 189, 29, 145, 150, 243}, 37}, {{152, 100, 37, 122, 242, 64, 0, 226, 64, 202, 246, 185, 9, 50, 86, 63}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 184, 247, 251, 176, 30, 80, 236}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 91, 133, 0, 203, 62, 115, 66}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 122, 73, 26, 134, 143, 222}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 156, 131, 70, 224, 145, 59}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 146, 176, 31, 2, 7, 30}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 48, 119, 35}, 37}, {{152, 100, 37, 122, 242, 64, 54, 19, 196, 66, 132, 171, 229, 103, 53, 218}, 37}, {{152, 100, 37, 122, 242, 64, 0, 31, 240, 75, 224, 33, 69, 47, 209, 28}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 182, 104, 254, 93, 102, 238, 201}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 125, 20, 114, 106, 233, 203, 227, 216}, 37}, {{152, 100, 37, 122, 242, 64, 0, 16, 102, 233, 235, 199, 167, 73, 4, 106}, 37}, {{152, 100, 37, 122, 242, 64, 0, 86, 151, 36, 127, 150, 184, 163, 205, 8}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 35, 152, 175, 169, 230, 252}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 161, 107}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 197, 180, 11, 174, 252, 103, 93}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 168, 117, 27}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 11, 24, 118, 28}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 231, 65}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 198, 182}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 29, 31, 228, 193}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 227, 98, 226, 96, 110, 89}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 115, 217, 2, 50, 175, 178, 235, 63}, 37}, {{152, 100, 37, 122, 242, 64, 0, 125, 169, 166, 249, 164, 158, 118, 119, 218}, 37}, {{152, 100, 37, 122, 242, 64, 214, 129, 60, 27, 138, 202, 116, 1, 72, 161}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 205, 216, 173, 237, 24, 9}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 139, 194, 84}, 37}, {{152, 100, 37, 122, 242, 64, 40, 59, 243, 190, 67, 239, 178, 92, 98, 111}, 37}, {{152, 100, 37, 122, 242, 64, 197, 214, 194, 210, 1, 63, 210, 2, 48, 102}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 141, 190, 248, 184, 161, 241, 210, 88}, 37}, {{152, 100, 37, 122, 242, 64, 0, 136, 44, 108, 34, 230, 26, 254, 228, 157}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 33, 142, 167, 165, 157}, 37}, {{152, 100, 37, 122, 242, 64, 0, 105, 244, 255, 9, 29, 152, 45, 49, 156}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 242, 90}, 37}, {{152, 100, 37, 122, 242, 64, 0, 33, 88, 99, 167, 133, 28, 180, 34, 122}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 73, 253, 16, 239, 48, 241, 65, 196, 242}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 18, 126, 10, 237, 22, 29}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 123, 8, 21, 207, 89, 14, 56}, 37}, {{152, 100, 37, 122, 242, 64, 0, 204, 47, 34, 21, 127, 238, 74, 238, 59}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 23, 207, 63, 48, 35, 147, 112}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 148, 127, 75, 229, 199, 4, 59}, 37}, {{152, 100, 37, 122, 242, 64, 24, 244, 4, 236, 10, 47, 48, 81, 179, 160}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 252, 254, 55, 13, 178, 63}, 37}, {{152, 100, 37, 122, 242, 64, 0, 246, 209, 234, 104, 103, 100, 109, 150, 177}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 82, 111, 123, 85}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 166, 109, 49}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 46, 54}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 63, 163, 252, 10, 80, 206, 13}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 124, 29, 18, 217, 48, 61, 154, 20}, 37}, {{152, 100, 37, 122, 242, 64, 0, 44, 50, 45, 110, 40, 222, 180, 6, 165}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 109, 58, 249, 218}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 196, 203, 234, 60}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 1, 44, 16}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{152, 100, 37, 122, 242, 64, 0, 215, 53, 93, 45, 181, 123, 107, 82, 88}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 138, 159, 52}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 182, 242, 33, 90, 169, 17, 4, 151}, 37}, {{152, 100, 37, 122, 242, 64, 0, 196, 37, 116, 92, 6, 102, 92, 162, 176}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 173, 8, 211}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 200, 182, 27, 167, 212}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 109, 42, 3, 93, 46, 56, 98, 232}, 37}, {{152, 100, 37, 122, 242, 64, 0, 229, 194, 251, 52, 233, 175, 79, 155, 116}, 37}, {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 165, 70}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 131, 86, 2, 218, 138, 78, 32, 152}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 204, 192, 159}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 116, 208}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 146, 134, 202, 238, 12, 139, 119}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 94, 116, 215, 176, 219, 241, 219, 243}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 157, 242, 182, 190, 82, 116}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135}, 174}, {{174, 231, 230, 33, 71, 224, 0, 227, 207, 186, 227, 79, 212, 122, 10, 108}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 118, 79}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 85, 89, 90, 58, 253, 240, 213}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 220, 224, 130, 5, 141, 37}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 48, 60, 91, 2}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 245, 95, 39, 16, 87}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 15, 232, 58, 128, 58, 127, 4}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 85, 159, 250, 210}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 139, 230, 222, 114}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 138, 179, 232, 211, 35}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 75, 57, 106, 92, 243, 242}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 234, 160, 97, 184, 15, 126, 202}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 13, 190, 14}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 180, 77, 197, 141, 0, 54, 136}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 238, 198, 130, 99, 73}, 174}, {{174, 231, 230, 33, 71, 224, 0, 59, 141, 125, 48, 107, 180, 220, 169, 123}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 148, 189, 35, 210, 218, 169}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 23, 139, 241, 27, 69, 226}, 174}, {{174, 231, 230, 33, 71, 224, 0, 74, 97, 153, 56, 64, 172, 142, 197, 188}, 174}, {{174, 231, 230, 33, 71, 224, 0, 212, 29, 33, 102, 174, 56, 132, 83, 107}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 186, 235, 203, 214}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 178, 68, 44, 167}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 61, 213, 123, 143, 22, 178}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 151, 59, 186, 199}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 22, 67, 195, 54, 211, 31, 171, 84, 133}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 210, 176, 208}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 159, 146, 116, 224, 118}, 174}, {{174, 231, 230, 33, 71, 224, 0, 105, 192, 230, 158, 60, 4, 134, 119, 214}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 174}, {{174, 231, 230, 33, 71, 224, 99, 140, 216, 82, 150, 99, 111, 69, 87, 159}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 26, 192}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 248, 172, 151, 4, 223}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 221, 233}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 89, 51, 242}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 245, 193, 213, 248, 191, 84, 45}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 174, 18, 25, 4}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 11, 13, 45, 10}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 122, 149, 144, 169}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 196, 224, 63}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 15, 247, 247, 220, 229, 150, 102, 139}, 174}, {{174, 231, 230, 33, 71, 224, 0, 173, 227, 219, 148, 2, 204, 141, 160, 122}, 174}, {{174, 231, 230, 33, 71, 224, 148, 78, 136, 122, 217, 147, 193, 201, 156, 212}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 13, 41}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 125, 175, 12, 172}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 24, 96, 7, 230, 55, 245, 69}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 14, 181, 125}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 101, 107, 184, 155, 156, 152}, 174}, {{174, 231, 230, 33, 71, 224, 82, 155, 229, 223, 252, 55, 2, 208, 106, 45}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 83, 53, 68}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 120, 35, 223, 240}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 25, 75}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 174}, {{174, 231, 230, 33, 71, 224, 0, 145, 199, 20, 159, 96, 202, 242, 18, 81}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 241, 124, 215, 149}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 207, 222, 52, 135, 62, 87, 159, 120}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 97, 173, 244, 121, 49, 131, 185}, 174}, {{174, 231, 230, 33, 71, 224, 240, 90, 124, 27, 215, 225, 114, 227, 104, 171}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 138, 4, 44, 135, 137}, 174}, {{174, 231, 230, 33, 71, 224, 230, 86, 190, 60, 191, 79, 130, 188, 238, 168}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 174, 160}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 215, 9, 5, 178, 44, 114, 208}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 139, 161}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 240, 161, 131, 113, 175}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 4, 108, 8}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 240, 184, 8, 8, 50, 78}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 235, 109, 165, 48, 232, 37}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 90, 4, 234, 169, 78, 110, 58}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 104, 126, 87, 151, 233, 80, 71, 13}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 246, 75, 17, 110, 19, 69, 3}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 105, 223, 12, 83, 24, 107}, 174}, {{174, 231, 230, 33, 71, 224, 0, 0, 0, 12, 207, 59, 155, 213, 56, 112}, 174}, {{174, 231, 230, 33, 71, 224, 0, 130, 89, 158, 158, 81, 237, 222, 61, 67}, 174}, {{174, 231, 230, 33, 71, 224, 0, 234, 130, 158, 35, 232, 6, 90, 170, 167}, 174}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 187, 3, 41, 46}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 255, 238, 254}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 173, 159, 193, 132, 67}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 112, 150, 226, 14, 83}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 21, 93, 57, 185, 60, 158}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 101, 1, 151, 250}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 187, 244, 25, 130, 157}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 36}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 172, 134, 29, 128}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 61, 171, 155, 117, 40, 218}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 191, 31}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 195, 175, 62, 133}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 63, 203, 160, 112, 172, 175}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 44}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 124, 105}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 90, 70, 229, 207, 4, 30, 181}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 140, 179}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 141, 171, 163, 12, 232}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 6, 168, 99, 92}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 144, 146, 1, 205, 88, 173}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 129, 85, 102, 68}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 52}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 29, 221, 135}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 208, 18, 182, 254, 99, 79, 101}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 34, 145, 36, 173, 248, 143, 80}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 14, 233, 10, 88, 187}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 226, 3, 27, 46, 101}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 130, 209}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 82, 21}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 234, 153}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 94, 188, 192, 142, 251}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 152, 178, 4, 32, 41}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 132, 149, 216, 247}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 89, 212}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 228, 176, 76, 238, 250, 83}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 122, 220, 65, 253}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 77}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 7, 57, 52, 136, 107, 36}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 45}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 251, 169, 107}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 251, 168, 206, 174}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 193, 102, 98, 191}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 63, 214, 179, 209, 255}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 156, 53, 213, 13, 192, 177, 204}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 208, 246, 236, 127, 137, 206, 14}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 99, 192, 224, 135, 5, 161, 152}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 120, 174, 227}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 33, 13, 159}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 127}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 56}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 188}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 58, 45, 160, 96, 116}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 233, 196, 36, 111, 107, 105}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 216, 255, 224, 245, 161, 210}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 155, 210}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 231}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 112, 75, 17, 244, 171}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 3}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 73, 131}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 142, 144, 185, 225, 220, 103}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 106, 213, 255}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 31, 132, 23, 3}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 129, 66, 130, 97}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 241, 165, 7}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 247}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 109, 232, 150, 51}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 87}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 184, 94, 106, 208}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 158, 64, 180, 84, 62, 247}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 248, 69, 35}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 136, 121, 26, 246, 246, 190}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 11, 51, 171, 196, 246, 153}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 247}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 107, 126, 196, 110, 63, 194, 191}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 65, 148, 138, 12}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 236, 227, 195, 82}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 123, 229, 65, 124, 207, 37}, 251}, {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 206, 101, 175, 199, 112}, 251}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 136, 218, 209, 90, 159}, 115}, {{167, 186, 101, 187, 122, 0, 0, 191, 75, 151, 179, 104, 133, 80, 0, 146}, 115}, {{167, 186, 101, 187, 122, 0, 164, 141, 30, 251, 140, 161, 26, 215, 70, 194}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 129, 40, 86}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 32, 17, 233, 17}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 127, 40, 96, 72, 184, 121, 129, 108}, 115}, {{167, 186, 101, 187, 122, 0, 0, 46, 195, 33, 160, 180, 234, 145, 167, 151}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 27, 42, 243, 20}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 229, 111, 222}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 190, 38, 112, 98, 162, 220}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 52}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 169, 89, 49, 159, 31}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 128, 193, 140, 238, 182, 70, 222}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 105, 121, 133, 171, 74, 219, 123}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 124, 11, 19, 118, 200}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 197, 160, 211, 43}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 37, 179, 166}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 10, 148, 222, 223, 138, 151}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 75, 157, 120, 124}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 238, 202, 86, 191, 173, 109, 93}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 26, 198, 128}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 3, 104, 77, 163}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 236, 162, 248, 201, 198, 12}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 138, 35, 51, 57, 63, 85}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 101, 33, 100, 43, 120, 251}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 223, 251, 13, 164, 29, 64, 192, 87}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 94, 182, 202}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 20, 149, 216, 195, 53}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 208, 7, 211, 110}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 45, 181, 241}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 86, 75, 182, 36, 67, 204, 223, 88}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 138, 225, 117, 188, 135, 42}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 194}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 115, 215, 197, 74}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 249, 244, 59, 194, 52, 94, 253, 19}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 92}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 138, 192, 131, 18}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 227, 165, 135, 3, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 32}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 175, 89, 210, 48, 190}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 23}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 26, 201, 0, 10}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 219}, 115}, {{167, 186, 101, 187, 122, 0, 0, 96, 168, 240, 184, 237, 97, 196, 41, 4}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 124, 217, 211, 201, 13, 138, 193}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 210, 47, 44, 239}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 42, 239, 204, 90, 32, 81}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 73, 117, 24, 212, 120, 97}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 239, 27, 95, 45}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 203, 200, 226, 38, 103, 222, 204}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 222}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 88, 237, 50, 172, 11, 129, 156, 146, 223}, 115}, {{167, 186, 101, 187, 122, 0, 0, 249, 98, 188, 173, 231, 188, 29, 167, 113}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 157, 148, 50}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 194}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 27, 100, 15}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 235, 3, 186, 217}, 115}, {{167, 186, 101, 187, 122, 0, 87, 225, 104, 30, 165, 133, 19, 173, 62, 68}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 2, 251, 255, 232, 48, 248, 128}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 197, 23, 232, 19}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 163, 168, 145}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 219, 237, 213, 187, 201, 249, 34, 215}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 214, 54, 16}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 154, 69, 114, 24, 117, 26}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 30}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 164, 241, 12}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 78, 254, 153, 80}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 167, 212, 77, 187, 160, 159, 114, 152}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 111, 49, 120, 94, 31, 232}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 224, 41, 21, 179}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 201, 25, 139, 214, 136, 248, 236, 127}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 1}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 40}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 54, 93, 167, 79, 22, 65, 249, 239}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 204, 52, 117, 165, 110}, 115}, {{167, 186, 101, 187, 122, 0, 195, 49, 139, 50, 177, 104, 224, 92, 48, 150}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 79, 58, 244, 76, 31, 6, 57, 25}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 250, 9, 82, 38, 115}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 233, 57, 55, 73, 245, 178, 153, 248}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 214, 176, 136, 3, 228, 4, 63, 107}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 134, 6, 26, 231, 92, 107}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 144, 233, 59, 151, 221}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 82, 79, 42, 100}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 91}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 207, 146, 125, 43, 53, 105, 242}, 115}, {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 243, 178, 203}, 115}, {{167, 186, 101, 187, 122, 0, 0, 232, 165, 247, 108, 97, 241, 216, 217, 24}, 115}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 100}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 124}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 233}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 20, 65}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 151}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 49, 93}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 113}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 41}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 39}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 226}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 182}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 178, 228}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 139, 76}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 136}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 15, 211}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 150}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 191}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 192}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 167}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 227, 137}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 247}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 38, 31}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 30, 204}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 61}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 177}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 79}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 90}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 91, 89}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 172}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 151}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 161}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 174}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 69}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 185}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 106, 72}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 38, 245}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 112}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 175}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 172, 213}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 155, 42}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 76}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 118}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 201, 25}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 13, 227}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 95, 130}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 84}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 196}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 231, 249}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 74, 219}, 252}, {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 83}, 252}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 251, 219, 251, 105}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 237, 54, 3, 120, 19}, 176}, {{83, 132, 219, 86, 86, 0, 0, 48, 38, 138, 41, 116, 104, 120, 204, 127}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 24, 91, 241, 246, 5, 72, 84, 219}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 120, 157, 9, 244, 195, 198}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 105, 136, 62, 255, 82, 33, 109, 26, 191}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 147, 9, 10}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 242}, 176}, {{83, 132, 219, 86, 86, 0, 139, 218, 245, 124, 24, 115, 237, 246, 236, 116}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 208, 16, 193}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 80, 62, 54, 248, 248, 165, 145, 72}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 229}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 163, 29, 199}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 204, 247, 203, 77, 30}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 234, 104, 82, 174, 116, 106, 202, 211}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 21}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 28, 52, 126}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 231, 32, 151, 0, 90, 55, 132, 28}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 103, 90, 13, 148, 166}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 164, 59, 72, 40, 181, 38}, 176}, {{83, 132, 219, 86, 86, 0, 161, 240, 1, 122, 45, 174, 70, 193, 191, 237}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 85}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 139, 116, 129}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 41, 223, 74, 188}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 10, 71, 157, 117, 214, 19, 15, 89, 90, 183}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 51, 240, 242, 203, 3, 253, 186, 146}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 148, 158, 114, 59, 66}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 219, 63, 151, 216, 102}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 255, 226, 208, 134, 17, 193, 102}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 123, 60, 101, 212, 81, 120, 78, 174}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 209, 93, 106, 127, 31, 119, 217}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 193, 161, 249, 166, 183}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 96, 122, 31, 154, 240, 114, 148, 183}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 115, 191, 176}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 112, 208, 147, 161, 76, 12}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 180, 164, 117, 75, 245, 89}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 193, 38, 195, 229, 93, 110, 208, 171}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 97, 0, 25, 42, 147, 60, 136, 234}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 237, 35, 236, 165, 230, 10, 207, 29}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 87, 66, 234, 107, 5, 156, 46, 133, 248}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 46, 121, 126}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 158, 127, 177, 117, 197}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 75, 68, 89, 162, 64, 228, 162, 123}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 110, 217, 233, 208, 208, 235, 231}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 41, 0, 91, 99, 24, 111, 57, 230}, 176}, {{83, 132, 219, 86, 86, 0, 187, 57, 244, 255, 22, 63, 195, 219, 186, 223}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 240, 140, 159, 208, 254}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 121, 103, 46, 219, 212, 125, 226, 188, 28}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 95, 123, 191, 52, 250, 187}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 153, 200, 30, 154, 31, 48}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 109}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 179, 114, 248, 36, 172, 71}, 176}, {{83, 132, 219, 86, 86, 0, 0, 35, 149, 72, 125, 108, 78, 20, 212, 189}, 176}, {{83, 132, 219, 86, 86, 0, 65, 208, 146, 166, 40, 80, 194, 11, 247, 197}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 8}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 11, 156, 172, 131, 8, 50}, 176}, {{83, 132, 219, 86, 86, 0, 0, 200, 159, 130, 253, 111, 30, 104, 234, 127}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 230, 212, 69, 42, 199, 211}, 176}, {{83, 132, 219, 86, 86, 0, 100, 69, 175, 226, 82, 215, 183, 18, 24, 223}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 230, 16, 126, 158, 240}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 187, 125, 254, 174, 136, 111, 193, 78}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 22, 19, 210}, 176}, {{83, 132, 219, 86, 86, 0, 0, 88, 116, 178, 1, 99, 219, 68, 231, 205}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 36, 160, 150, 176, 225, 105, 138, 54}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 35, 178, 100, 119, 66, 30, 109, 56}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 6, 178, 10, 206}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 84, 178, 30, 59, 251}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 6, 101, 112, 151, 138, 125}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 165, 251, 20, 186}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 74}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 210, 136, 1, 87}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 242, 192, 166, 14, 31}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 229, 81, 137, 162, 181}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 193, 156, 122, 135, 253, 29, 188, 11}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 176}, {{83, 132, 219, 86, 86, 0, 143, 84, 86, 119, 190, 6, 249, 118, 27, 201}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 176}, {{83, 132, 219, 86, 86, 0, 0, 216, 233, 69, 82, 171, 15, 119, 243, 81}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 87}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 217, 16, 216, 238, 117, 88}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 199, 131, 192}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 237, 56, 6, 72, 123, 29, 214, 63}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 176}, {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 59, 43, 59, 48, 75, 20}, 176}, {{83, 132, 219, 86, 86, 0, 58, 2, 110, 176, 251, 131, 49, 202, 245, 235}, 176}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 51, 231}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 237, 154, 241, 57}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 101, 37, 13}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 198}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 57, 50, 211}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 182, 77, 103}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 235, 70, 139}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 188, 238, 191}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 111, 221, 98}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 107, 160, 35}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 253}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 64}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 162, 246}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 225, 235, 16}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 189, 17}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 33}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 138, 96, 85}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 41}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 116}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 253, 15}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 149}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 78, 149, 138, 193}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 94, 172, 41, 199}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 160, 80, 201}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 213}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 248, 120, 76}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 227, 22, 45, 134}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 218}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 63, 40, 230, 165}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 56, 49, 137, 148}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 190, 80, 231}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 167, 128, 111, 117}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 131, 187, 23, 140}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 237, 232}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 114, 189}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 27, 154}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 116}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 154, 255, 211}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 127, 81}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 56, 154}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 109, 156}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 32, 208, 251, 221}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 122, 62, 134}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 28, 32}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 210}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 31, 221, 123}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 76, 228, 86}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 206}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 124, 214, 5}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 181, 44, 70}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 195, 77, 143}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 92}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 244}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 213}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 92, 140}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 153}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 190, 10, 70, 230}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 232, 151}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 143, 103}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 106, 219, 195, 104}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 209}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 171}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 193, 37, 62, 49}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 11, 248}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 13, 83}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 44, 174, 224, 57}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 12, 158, 102}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 155}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 79, 181, 170, 208}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 155, 246}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 117}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 197}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 229, 85}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 155}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 36}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 33, 15}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 127, 110, 187}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 75, 35, 1, 97}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 244, 111, 48}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 21, 0, 25, 46}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 220, 73}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 123, 61}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 248, 12, 145}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 131}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 95, 228}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 27, 21, 213}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 154, 227}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 249, 125}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 123, 204, 43}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 186}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 193, 117}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 180, 180, 83, 46}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 177, 14, 134}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 19}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 246}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 13}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 40}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 221, 228, 59}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 113, 119}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 219, 199, 197, 249}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 2, 231, 165, 135}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 193, 141, 8, 112}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 54}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 161, 70, 35}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 60, 117, 56, 205}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 129}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 62}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 84, 27, 189, 183}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 247}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 116}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 110}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 1}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 121, 119}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 53, 222, 39}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 171}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 121, 143, 246, 159}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 132, 132, 56}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 254, 165, 51}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 170, 130, 225, 103}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 105, 127, 121}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 4, 170}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 141}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 201, 208, 163, 128}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 68, 78, 88}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 237, 33, 222, 179}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 194, 225, 40}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 111}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 218, 251, 144}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 254, 170, 6}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 180}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 113, 4}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 95, 124}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 234, 142, 108, 236}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 225, 170, 175, 197}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 148, 193}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 196}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 224, 84, 222, 128}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 246}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 217}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 28, 129, 182}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 148, 221}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 198, 219, 60, 152}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 172, 106}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 74, 134, 180}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 163}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 201, 30, 232, 173}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 97}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 122}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 252, 196, 194}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 86, 107, 247}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 202}, {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 232}, 202}, {{160, 0, 0, 0, 6, 76, 64, 56, 25, 49, 182, 166, 114, 130, 34, 73}, 208}, {{160, 0, 0, 0, 0, 1, 121, 240, 63, 124, 55, 131, 201, 204, 91, 244}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 147, 40, 252, 108, 109, 105, 179}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 30, 64, 16, 124, 194, 62, 51}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 208}, {{160, 220, 175, 102, 229, 73, 47, 159, 44, 200, 39, 238, 255, 66, 145, 181}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 245, 3, 193}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 208}, {{160, 0, 48, 207, 183, 23, 85, 79, 255, 39, 65, 175, 75, 184, 95, 168}, 208}, {{160, 0, 0, 0, 0, 185, 158, 129, 60, 248, 126, 22, 136, 19, 116, 70}, 208}, {{160, 0, 0, 0, 0, 103, 206, 43, 100, 130, 210, 90, 94, 13, 248, 97}, 208}, {{160, 0, 0, 0, 148, 85, 44, 138, 166, 16, 122, 104, 117, 82, 97, 79}, 208}, {{160, 0, 34, 21, 133, 221, 133, 111, 90, 45, 254, 238, 171, 52, 219, 219}, 208}, {{160, 0, 0, 191, 118, 75, 238, 135, 106, 36, 105, 19, 206, 242, 222, 33}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 144, 74, 14, 52}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 52, 175, 201, 37, 14, 64, 148, 215}, 208}, {{160, 0, 0, 10, 140, 133, 230, 61, 210, 127, 165, 92, 90, 50, 166, 248}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 16}, 208}, {{160, 0, 0, 0, 0, 0, 244, 179, 63, 100, 131, 19, 122, 127, 150, 146}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 29, 204, 124, 142}, 208}, {{160, 0, 0, 0, 81, 236, 217, 230, 247, 20, 32, 121, 252, 155, 192, 233}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 127, 147, 110, 230}, 208}, {{160, 0, 0, 0, 0, 0, 0, 235, 217, 47, 165, 143, 144, 14, 72, 129}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 240, 200}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 244, 121, 143, 63, 16, 19, 252}, 208}, {{160, 0, 0, 0, 0, 0, 85, 68, 187, 159, 202, 149, 224, 10, 243, 24}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 159}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 127, 59, 45, 230}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 103, 240, 42, 68}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 7, 86, 251, 1}, 208}, {{160, 212, 13, 63, 61, 250, 94, 118, 174, 226, 179, 213, 255, 122, 248, 215}, 208}, {{160, 0, 0, 20, 195, 57, 171, 243, 103, 191, 36, 7, 75, 240, 175, 135}, 208}, {{160, 18, 205, 37, 123, 195, 43, 245, 66, 160, 105, 73, 94, 81, 135, 2}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 29}, 208}, {{160, 0, 41, 203, 172, 157, 152, 127, 233, 57, 106, 196, 103, 203, 193, 129}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 106, 107, 176}, 208}, {{160, 0, 0, 0, 32, 51, 111, 206, 15, 128, 64, 78, 60, 95, 253, 233}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 175}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 20}, 208}, {{160, 0, 0, 0, 0, 0, 0, 134, 46, 127, 93, 100, 223, 94, 240, 110}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 71, 200, 64}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 208}, {{160, 0, 0, 0, 0, 0, 123, 146, 163, 43, 95, 58, 252, 173, 81, 241}, 208}, {{160, 0, 0, 21, 46, 135, 18, 155, 210, 142, 62, 90, 199, 163, 165, 28}, 208}, {{160, 0, 0, 0, 0, 0, 175, 66, 161, 57, 165, 108, 108, 200, 165, 48}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 153, 186, 13, 243, 219, 114, 86}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 220, 102, 91, 11}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 99, 4, 227}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 214, 39, 113, 222}, 208}, {{160, 0, 0, 0, 0, 0, 190, 120, 188, 223, 62, 68, 37, 244, 164, 240}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 235, 160, 115, 119, 221}, 208}, {{160, 0, 121, 9, 37, 76, 33, 29, 96, 78, 78, 252, 172, 191, 219, 143}, 208}, {{160, 0, 0, 0, 0, 0, 159, 230, 93, 211, 202, 142, 224, 65, 103, 9}, 208}, {{160, 0, 0, 0, 15, 81, 104, 120, 172, 236, 85, 151, 160, 172, 133, 251}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 190, 78, 235, 75, 168, 208, 102, 130, 178, 123, 106, 25, 136, 250, 46}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 161, 192}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 43}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 208}, {{160, 0, 10, 181, 219, 127, 152, 153, 220, 50, 137, 128, 109, 26, 192, 159}, 208}, {{160, 0, 0, 0, 34, 87, 233, 239, 239, 176, 185, 34, 201, 161, 161, 73}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 55, 143, 15, 28, 4}, 208}, {{160, 237, 32, 214, 201, 20, 58, 85, 168, 20, 154, 9, 237, 57, 102, 70}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 117, 164, 190, 15, 147}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 64, 218, 125, 41, 161, 50, 241}, 208}, {{160, 0, 204, 110, 156, 31, 97, 82, 153, 72, 226, 32, 248, 93, 60, 239}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 3, 182, 111, 129, 203, 135, 28, 115}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 242, 235, 119, 206, 198, 105, 125}, 208}, {{160, 0, 0, 0, 52, 209, 194, 64, 96, 22, 129, 247, 5, 140, 34, 153}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 59, 178, 209, 68}, 208}, {{160, 0, 0, 204, 44, 74, 72, 221, 96, 166, 234, 97, 109, 225, 192, 103}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 56, 241, 247, 16, 97, 141, 239, 150}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 237, 254, 39, 74, 36, 161, 122, 22, 181, 228, 252, 252, 24, 199, 115}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 161, 253, 82}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 240, 178, 210}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 157, 227, 8}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 9, 254, 133}, 208}, {{160, 0, 0, 0, 207, 125, 45, 43, 30, 61, 30, 82, 19, 7, 165, 167}, 208}, {{160, 0, 202, 162, 186, 24, 81, 58, 81, 122, 8, 92, 156, 128, 150, 129}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 207, 243, 158, 94, 181, 190, 235, 222}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 111, 71, 125, 239, 65}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 225, 61, 150, 80}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 154, 71, 1, 196, 104}, 208}, {{160, 0, 0, 0, 60, 143, 48, 197, 221, 208, 207, 95, 218, 16, 67, 77}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 208}, {{160, 0, 0, 0, 0, 0, 70, 245, 19, 60, 76, 90, 50, 9, 112, 240}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 155, 108}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 208}, {{160, 0, 0, 68, 102, 83, 137, 184, 53, 237, 60, 110, 165, 10, 143, 253}, 208}, {{160, 0, 0, 0, 76, 112, 100, 110, 171, 9, 20, 178, 114, 78, 131, 220}, 208}, {{160, 0, 0, 0, 0, 0, 153, 129, 62, 236, 127, 212, 171, 233, 126, 175}, 208}, {{160, 0, 0, 0, 201, 76, 120, 139, 215, 135, 76, 252, 42, 87, 187, 11}, 208}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 62, 160, 39, 176, 128}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 112, 202}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 97, 148, 49, 112, 174}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 120, 133, 110, 156, 135}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 200, 185}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 61, 159, 103, 117, 14}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 30, 55, 249}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 185, 212, 246}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 182}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 214}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 12}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 148, 151, 22}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 242, 83}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 106, 87, 233}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 95, 65, 86, 231}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 143, 159}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 44, 226, 95, 40, 103}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 93, 125}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 40, 88}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 77, 61, 30}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 205, 185}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 50, 102}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 25, 160, 41, 238}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 148, 245}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 15, 120, 254, 114, 32}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 69, 178, 47, 91}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 74, 50, 201, 111, 28, 234}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 66, 45}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 218, 116, 122, 97, 35}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 217, 61, 137, 182}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 40}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 153, 243, 161}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 22, 96, 160}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 96, 246}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 115, 237, 85, 141, 153, 229}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 237, 74, 58, 70}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 241, 140, 116, 233}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 142, 87, 187, 127}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 78, 46, 70, 185, 62}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 227, 83, 170}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 97}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 172, 120, 168, 176}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 117, 234, 125, 4}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 216, 194, 4, 153}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 51, 56, 157}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 208, 7}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 127}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 61, 40, 160, 80}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 236, 25, 109, 159, 196, 196}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 228, 134, 130, 12}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 72, 107, 228}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 246, 216}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 198}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 254, 77, 51, 253}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 187, 20, 11, 69, 84, 96}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 250}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 240, 129}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 187, 188, 147, 175, 103, 182}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 216}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 12}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 50, 38}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 159}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 34, 110}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 107, 75, 67}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 230, 208, 3, 104, 213}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 228, 102}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 158}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 252}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 221, 45, 146}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 71, 95, 248}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 117}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 147, 148}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 221}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 137, 178, 87}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 110, 38, 47}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 116, 194, 21, 153}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 162, 212, 133}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 55, 67, 127}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 20, 20, 103, 55}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 69, 149}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 76, 157}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 50}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 179, 46, 164, 181, 237}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 132, 94, 185, 152}, 158}, {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 16, 227}, 158}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 206, 225, 39, 126, 143, 187}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 251, 225, 67, 242, 167, 148}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 5, 16, 251}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 146}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 105, 144, 115, 86, 173, 135}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 215}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 94, 128, 106, 4, 59}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 225, 209, 160, 178, 116}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 79, 190, 241}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 186, 44}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 160, 172, 230, 198, 138}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 114, 15, 123}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 108, 222, 99, 1, 36}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 88}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 251, 185, 94, 77, 39, 13}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 106, 54, 133, 110}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 213, 29, 120, 48}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 149, 47, 7, 23, 86}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 116}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 124}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 205}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 134}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 235, 138, 32, 235}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 118, 176, 141, 156}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 222}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 39, 149}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 114, 209, 121}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 119, 133, 154, 191, 149, 151}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 151, 143, 45}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 210, 39, 174, 195, 37, 127}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 112, 106, 51, 192, 220, 58}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 182}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 202, 72}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 22, 239, 140, 183}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 254}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 222, 255, 142}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 61, 80, 207}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 90, 113, 200, 29, 182, 18}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 117}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 224, 195, 205, 81, 191, 14}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 166}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 255, 176}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 243}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 2}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 205}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 84, 27, 18, 251, 110, 164}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 16, 165, 16}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 70}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 44}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 211, 125, 178, 133, 81}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 6}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 129, 171, 86, 62, 85, 51}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 43, 200, 18}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 134, 16, 81, 87}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 61, 42, 179, 8, 147}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 164, 235, 153, 133}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 55, 79, 25, 237}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 123, 128, 56}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 187, 150, 192, 31}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 249, 182, 191, 130, 0, 189}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 47, 146, 41, 231}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 197, 205}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 69, 217}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 224, 73, 100}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 176, 36}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 26, 50, 50, 129}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 228}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 157}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 199, 238, 148, 250}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 31, 64, 53, 242}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 251}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 231, 59}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 16, 100, 160, 151, 164}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 144, 93, 114, 8}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 240, 65, 27}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 79, 201}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 103, 47}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 232, 243, 248}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 102, 170, 50, 85, 207, 226}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 164, 69}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 104}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 87, 57, 241}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 217, 121, 212, 231}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 94}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 143, 136}, 136}, {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 241, 250}, 136}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 237, 144}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 232, 122, 113, 11, 69, 227}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 1, 135, 248, 148, 206, 70, 238, 4}, 191}, {{105, 197, 26, 80, 0, 0, 0, 177, 101, 183, 99, 186, 188, 132, 232, 194}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 227}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133}, 191}, {{105, 197, 26, 80, 210, 87, 113, 6, 41, 227, 120, 19, 26, 3, 14, 24}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 24, 248, 174, 185, 252, 209, 60}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 93, 138, 76, 190, 117}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 193}, 191}, {{105, 197, 26, 80, 0, 0, 0, 124, 234, 155, 185, 98, 157, 175, 110, 131}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 193, 21, 228, 133, 22, 123, 115, 82}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 197, 206, 103, 2, 84, 200, 203}, 191}, {{105, 197, 26, 80, 0, 164, 193, 119, 206, 198, 219, 166, 248, 177, 52, 163}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 190, 236, 183, 64}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 186, 112, 92, 140}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 191}, {{105, 197, 26, 80, 0, 0, 0, 131, 138, 170, 218, 100, 94, 20, 58, 8}, 191}, {{105, 197, 26, 80, 0, 83, 31, 52, 116, 230, 103, 167, 158, 34, 156, 54}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 134, 80, 40, 114, 246}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 111, 82, 206, 7, 64}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 18, 140, 33, 144, 105, 200}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 203, 188, 139, 182, 240, 168, 204}, 191}, {{105, 197, 26, 80, 0, 0, 234, 115, 86, 36, 144, 45, 233, 67, 55, 250}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 143, 152}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 56, 33, 115, 63, 125}, 191}, {{105, 197, 26, 80, 0, 0, 0, 225, 101, 241, 16, 185, 110, 238, 48, 140}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 106}, 191}, {{105, 197, 26, 80, 208, 241, 60, 138, 238, 125, 208, 147, 39, 239, 43, 182}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 208}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 43, 122, 25, 213, 78}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 124, 10, 81, 104, 239, 57, 242, 221, 72, 97, 28, 244}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 116, 145, 237, 99, 243, 171}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 94, 122, 170, 246, 44, 152}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 136, 133, 73, 78, 103, 79, 71}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 34, 172, 32, 69, 23}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 121, 176, 79, 43}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 55, 133, 162, 162, 73, 47}, 191}, {{105, 197, 26, 80, 0, 0, 0, 196, 179, 77, 175, 10, 38, 98, 80, 185}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 44, 48}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 191}, {{105, 197, 26, 80, 0, 0, 0, 229, 78, 45, 202, 245, 105, 97, 227, 163}, 191}, {{105, 197, 26, 80, 0, 221, 54, 101, 246, 153, 128, 171, 166, 182, 23, 106}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 34, 56, 76, 171}, 191}, {{105, 197, 26, 80, 0, 0, 0, 18, 173, 153, 135, 113, 214, 115, 21, 162}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 160, 7, 42, 15, 196, 107}, 191}, {{105, 197, 26, 80, 0, 0, 41, 111, 79, 190, 8, 121, 46, 169, 164, 168}, 191}, {{105, 197, 26, 80, 0, 0, 77, 221, 151, 245, 239, 219, 245, 154, 253, 85}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 68, 43}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 158, 208, 31, 85, 100, 148, 208, 228}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 198, 144, 48, 106, 104, 43}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 88, 5, 39, 12, 224, 200}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 170, 19, 19, 123, 222}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 86, 180, 187, 27, 181, 178, 239, 159}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 235, 65, 40, 88, 190, 229, 180, 126}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 232, 59, 97, 16, 236, 127}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 210, 56, 42, 157, 96}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 169, 168, 185, 214, 118, 230}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 72, 255, 103, 19, 18, 254, 235}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 74, 239, 242, 8}, 191}, {{105, 197, 26, 80, 0, 0, 123, 131, 110, 93, 9, 110, 155, 99, 139, 176}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 191}, {{105, 197, 26, 80, 0, 0, 26, 175, 43, 41, 76, 69, 218, 211, 50, 104}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 244, 74, 185, 50, 126}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 165, 110, 96, 84, 136}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, 246, 152}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 42}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 33, 105, 187, 80}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 236, 27, 78, 19, 73, 138}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 53, 216, 69, 159, 83, 239, 22, 128}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 95, 198, 126, 13, 194}, 191}, {{105, 197, 26, 80, 0, 90, 166, 228, 71, 221, 126, 72, 235, 168, 146, 144}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 108}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 31}, 191}, {{105, 197, 26, 80, 0, 241, 49, 39, 78, 113, 88, 253, 217, 172, 22, 167}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 248, 190, 84, 53, 105, 28}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 235, 88, 125, 50, 192, 133}, 191}, {{105, 197, 26, 80, 0, 0, 0, 152, 23, 59, 20, 162, 82, 154, 3, 235}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 208, 52, 112, 77, 147, 196, 9, 211}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 184, 168, 94, 254, 192, 220, 29}, 191}, {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 162}, 191}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 126}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 139}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 216}, {{136, 32, 240, 0, 0, 0, 226, 67, 154, 155, 224, 14, 91, 36, 221, 143}, 216}, {{136, 32, 240, 0, 0, 0, 80, 107, 75, 101, 31, 166, 205, 0, 83, 97}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 253}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 107, 47, 161, 199, 77}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 250}, 216}, {{136, 32, 240, 0, 0, 14, 21, 90, 74, 71, 245, 66, 152, 22, 49, 183}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 8, 213}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 37, 244, 218, 77, 113}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 106}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 116, 87, 20, 217, 193, 228}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 136, 129, 14, 171, 180, 148, 201, 225}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 84}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 149}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 229, 158, 76}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 202}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 131}, 216}, {{136, 32, 240, 0, 0, 157, 84, 230, 194, 216, 10, 208, 196, 99, 219, 166}, 216}, {{136, 32, 240, 0, 15, 28, 61, 104, 239, 193, 101, 7, 26, 0, 236, 71}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 88, 58, 59, 196, 34, 32}, 216}, {{136, 32, 240, 0, 0, 0, 0, 48, 150, 91, 184, 66, 35, 165, 170, 157}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 129, 169, 103, 102, 197, 28, 226, 102, 182}, 216}, {{136, 32, 240, 0, 0, 0, 80, 190, 59, 60, 17, 88, 137, 128, 150, 242}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 79, 60}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 3, 233, 67}, 216}, {{136, 32, 240, 0, 0, 0, 8, 170, 8, 88, 92, 4, 165, 168, 212, 17}, 216}, {{136, 32, 240, 0, 0, 0, 249, 97, 129, 255, 23, 123, 51, 28, 70, 237}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 125, 133, 101, 121, 134, 249, 239}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 227, 190, 209, 145, 51, 83, 207}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 163, 6, 99}, 216}, {{136, 32, 240, 0, 0, 63, 110, 18, 39, 243, 110, 12, 139, 186, 230, 127}, 216}, {{136, 32, 240, 0, 246, 249, 250, 199, 11, 146, 221, 160, 151, 36, 205, 95}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 24, 112}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 214, 96, 17, 8, 9}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 139}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 236}, 216}, {{136, 32, 240, 0, 239, 120, 139, 47, 25, 118, 46, 216, 196, 220, 8, 223}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 229}, 216}, {{136, 32, 240, 0, 0, 0, 0, 170, 157, 247, 46, 156, 7, 19, 232, 68}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 145, 108, 227, 127, 21, 128, 43, 165}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 130, 244, 14, 7, 195}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 95, 167, 37, 115, 100}, 216}, {{136, 32, 240, 0, 234, 162, 10, 67, 205, 233, 251, 164, 213, 69, 44, 210}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 211, 239, 33}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 15, 7, 218, 233, 36, 229}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 96, 166, 3, 178, 156, 164}, 216}, {{136, 32, 240, 0, 45, 204, 136, 16, 9, 85, 249, 215, 42, 170, 90, 8}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 43}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 5, 11, 135, 179, 176, 43, 34, 115, 33}, 216}, {{136, 32, 240, 0, 0, 0, 0, 130, 163, 23, 60, 156, 37, 224, 16, 85}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 214, 208, 248, 56, 90}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 77, 120, 92, 34, 116, 201}, 216}, {{136, 32, 240, 0, 0, 225, 255, 190, 50, 133, 218, 48, 39, 119, 229, 151}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 249, 141, 76, 139, 20, 59, 180, 42}, 216}, {{136, 32, 240, 0, 168, 75, 161, 58, 71, 205, 23, 16, 175, 72, 107, 155}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 52}, 216}, {{136, 32, 240, 0, 24, 147, 184, 178, 37, 240, 0, 101, 18, 50, 111, 17}, 216}, {{136, 32, 240, 0, 0, 0, 0, 9, 117, 125, 253, 52, 1, 152, 134, 155}, 216}, {{136, 32, 240, 0, 0, 0, 129, 149, 24, 91, 222, 107, 27, 224, 68, 147}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 118, 157, 193}, 216}, {{136, 32, 240, 0, 200, 198, 196, 64, 136, 88, 247, 216, 29, 214, 178, 105}, 216}, {{136, 32, 240, 0, 0, 188, 128, 230, 147, 20, 149, 11, 219, 75, 169, 248}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 243, 231, 113, 83, 29, 141, 137, 97}, 216}, {{136, 32, 240, 0, 0, 0, 0, 50, 149, 241, 5, 241, 38, 17, 56, 175}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 84, 72, 22, 166, 107, 132, 64, 191}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 30, 126}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 46, 162, 229, 239, 200}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 86, 184, 172, 80, 249, 213}, 216}, {{136, 32, 240, 0, 0, 0, 0, 242, 237, 163, 180, 170, 219, 179, 162, 121}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 84, 31, 107, 245, 1, 74, 94, 85}, 216}, {{136, 32, 240, 0, 0, 0, 0, 229, 85, 30, 208, 183, 119, 191, 62, 191}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 216}, {{136, 32, 240, 0, 0, 0, 0, 187, 116, 152, 62, 46, 146, 134, 160, 38}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 174, 87, 199, 156, 202, 180, 142, 165}, 216}, {{136, 32, 240, 0, 0, 170, 241, 22, 84, 29, 205, 234, 79, 207, 72, 7}, 216}, {{136, 32, 240, 0, 0, 0, 8, 9, 105, 224, 63, 10, 148, 224, 239, 194}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 123}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 135}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 57, 110}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 66, 5, 165, 137, 31}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 99, 181, 155, 6, 157, 180}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 163, 215, 236, 129, 215, 166, 16}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 188}, 216}, {{136, 32, 240, 0, 0, 0, 0, 200, 30, 215, 247, 188, 92, 51, 165, 42}, 216}, {{136, 32, 240, 0, 195, 154, 249, 60, 38, 50, 64, 79, 20, 123, 230, 173}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 99, 126, 120, 202, 217, 128, 23}, 216}, {{136, 32, 240, 0, 0, 0, 100, 171, 33, 146, 127, 25, 255, 26, 192, 162}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 134, 192, 16}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 107, 188, 251, 29, 201, 152, 201, 110}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 140, 69}, 216}, {{136, 32, 240, 0, 0, 0, 0, 132, 68, 106, 229, 66, 153, 251, 239, 68}, 216}, {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 247, 236, 228, 110, 83}, 216}, {{136, 32, 240, 0, 161, 251, 175, 79, 126, 117, 177, 171, 100, 17, 138, 48}, 216}, {{100, 238, 112, 40, 0, 0, 0, 0, 252, 12, 85, 204, 56, 128, 152, 10}, 93}, {{100, 238, 112, 40, 0, 53, 149, 75, 42, 142, 113, 45, 60, 92, 199, 29}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 13, 159, 233, 214, 86, 202, 112}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 94, 167, 198, 44, 28, 91, 125, 171}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 143, 13}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 218, 92, 194, 209, 187, 59, 16}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 51, 137, 212, 248, 222, 107, 45, 179}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 126, 36, 207, 44, 50, 186, 8, 74, 13, 90, 232}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 35, 187, 125, 204, 51, 58}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 141, 30, 121, 14, 103, 156}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 182, 48}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 236, 122, 154, 187, 161, 52, 74, 47}, 93}, {{100, 238, 112, 40, 96, 232, 64, 74, 190, 181, 76, 172, 193, 237, 167, 109}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 52, 200, 103, 155}, 93}, {{100, 238, 112, 40, 0, 220, 160, 63, 145, 168, 148, 7, 43, 234, 9, 61}, 93}, {{100, 238, 112, 40, 0, 0, 0, 20, 217, 85, 84, 31, 234, 111, 237, 136}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 245, 122, 238, 172, 16, 51, 215}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 140, 157, 220, 0, 200, 199, 12}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 206, 235, 150, 5, 1}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 106}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 91, 46, 229, 35, 35, 128}, 93}, {{100, 238, 112, 40, 0, 0, 65, 242, 188, 116, 56, 201, 248, 10, 80, 56}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 163, 34, 206, 1, 37, 174}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 26, 14, 84, 38, 253}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 195, 25, 254, 219, 95, 190, 40, 177}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 64, 242, 110, 183, 107, 150}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 76, 177, 160, 179, 136, 73, 153, 34}, 93}, {{100, 238, 112, 40, 0, 0, 192, 16, 214, 4, 232, 235, 243, 50, 25, 56}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 102}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 21}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 60, 86, 230, 160, 33, 220, 3, 214}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 179, 134, 119, 31, 93, 70, 2}, 93}, {{100, 238, 112, 40, 0, 0, 0, 78, 179, 55, 86, 159, 162, 208, 131, 225}, 93}, {{100, 238, 112, 40, 0, 0, 248, 24, 15, 61, 154, 171, 99, 83, 176, 64}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 82, 131, 213, 167, 97, 15, 83, 20}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 16, 74, 240, 25, 32, 232}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 152, 82}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 129, 151}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 28, 156, 67, 214, 165, 169, 142}, 93}, {{100, 238, 112, 40, 0, 155, 71, 246, 213, 60, 238, 51, 11, 158, 239, 134}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 30, 41, 223, 13, 13, 206, 137, 218}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 104, 100, 47, 168, 145}, 93}, {{100, 238, 112, 40, 0, 129, 98, 128, 217, 45, 179, 159, 212, 165, 92, 30}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 171}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 116, 25, 161, 238, 191, 126, 169}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 41, 201, 112, 99, 35, 28, 171, 202}, 93}, {{100, 238, 112, 40, 0, 8, 112, 120, 203, 206, 176, 235, 187, 255, 247, 38}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 26, 38, 9, 88, 228}, 93}, {{100, 238, 112, 40, 0, 0, 193, 31, 44, 106, 205, 174, 174, 113, 49, 244}, 93}, {{100, 238, 112, 40, 0, 0, 11, 240, 32, 41, 43, 101, 89, 126, 78, 68}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 217, 229, 70, 99, 67, 25, 154, 43, 37, 144, 238, 88}, 93}, {{100, 238, 112, 40, 0, 101, 189, 138, 73, 155, 124, 7, 177, 120, 204, 148}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 226, 234, 249, 19}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 235, 208}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 49, 89, 213, 60}, 93}, {{100, 238, 112, 40, 0, 0, 47, 227, 115, 47, 170, 6, 151, 141, 144, 171}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 13, 140, 21, 172, 25, 81, 126}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 167, 241, 140, 49}, 93}, {{100, 238, 112, 40, 0, 0, 0, 178, 68, 8, 111, 97, 128, 49, 247, 242}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 180, 253, 225, 136, 185, 128}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 49, 194, 81, 106, 153, 200}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 93, 136, 30, 117, 39}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 140, 112, 212, 253, 169, 95}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 205, 158, 12, 193, 71}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 151, 48, 135, 238, 74, 148}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 38, 9, 104, 126, 196, 175, 201}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 119, 131, 80, 235, 227}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 98, 162, 66, 15, 114, 242}, 93}, {{100, 238, 112, 40, 0, 0, 165, 143, 204, 172, 66, 80, 114, 78, 92, 45}, 93}, {{100, 238, 112, 40, 0, 0, 0, 71, 45, 226, 133, 8, 81, 122, 246, 144}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 71, 97, 221, 145, 172}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 42, 36}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 120, 135, 151, 138, 186, 49, 92, 226}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 189, 2, 65, 217}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 94, 88, 160, 109}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 73, 128, 217, 200, 25, 206, 135, 208}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 234, 119, 48, 0, 185, 200}, 93}, {{100, 238, 112, 40, 0, 0, 0, 234, 189, 116, 195, 14, 162, 201, 218, 217}, 93}, {{100, 238, 112, 40, 0, 2, 126, 157, 24, 33, 1, 149, 86, 128, 66, 184}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 119, 40, 195, 103, 68, 40, 188}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 8, 218}, 93}, {{100, 238, 112, 40, 0, 0, 228, 218, 80, 101, 200, 92, 235, 28, 81, 110}, 93}, {{100, 238, 112, 40, 0, 0, 224, 112, 40, 0, 240, 95, 178, 133, 96, 242}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 241, 143, 121, 141, 122}, 93}, {{100, 238, 112, 40, 0, 0, 51, 146, 182, 23, 144, 41, 143, 37, 251, 148}, 93}, {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 93}, {{100, 238, 112, 40, 0, 0, 176, 226, 194, 114, 209, 112, 49, 156, 3, 157}, 93}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 196}, {{80, 0, 0, 0, 0, 0, 0, 118, 119, 197, 227, 206, 226, 97, 251, 249}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 26, 5, 83}, 196}, {{80, 0, 0, 0, 0, 0, 0, 146, 71, 117, 204, 109, 173, 9, 44, 193}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 196}, {{80, 0, 213, 55, 128, 4, 184, 228, 212, 135, 45, 168, 85, 76, 159, 110}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 68, 162, 82}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 220, 96, 233, 90, 133, 56, 237, 110}, 196}, {{80, 0, 0, 0, 162, 51, 187, 51, 13, 16, 127, 226, 6, 102, 3, 23}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 23, 16, 37, 14}, 196}, {{80, 0, 168, 232, 39, 21, 200, 66, 87, 54, 241, 109, 134, 177, 218, 93}, 196}, {{80, 0, 0, 0, 0, 249, 196, 239, 217, 159, 101, 45, 166, 249, 124, 238}, 196}, {{80, 0, 0, 0, 155, 65, 6, 238, 133, 56, 230, 177, 56, 109, 53, 141}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 72, 5}, 196}, {{80, 0, 0, 0, 195, 172, 49, 240, 72, 101, 10, 134, 3, 211, 27, 27}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 196}, {{80, 205, 113, 96, 0, 169, 224, 95, 118, 62, 95, 212, 241, 156, 234, 203}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 211, 228}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67}, 196}, {{80, 0, 0, 0, 0, 0, 167, 52, 183, 28, 125, 69, 240, 224, 120, 218}, 196}, {{80, 0, 119, 5, 128, 238, 136, 179, 187, 161, 55, 186, 33, 109, 34, 87}, 196}, {{80, 0, 0, 0, 0, 0, 0, 210, 227, 160, 157, 91, 118, 91, 130, 73}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 77, 68, 15, 47, 196, 19, 52, 91}, 196}, {{80, 0, 0, 0, 83, 242, 37, 132, 164, 90, 160, 42, 52, 85, 170, 72}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 169, 123, 26}, 196}, {{80, 0, 0, 0, 65, 123, 44, 0, 52, 43, 33, 140, 139, 224, 86, 203}, 196}, {{80, 0, 0, 0, 195, 34, 107, 100, 176, 19, 94, 183, 158, 35, 50, 146}, 196}, {{80, 0, 84, 239, 99, 204, 14, 199, 201, 8, 229, 138, 246, 160, 233, 64}, 196}, {{80, 0, 0, 0, 93, 230, 190, 55, 1, 171, 190, 213, 161, 83, 95, 214}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 159, 93, 154, 233, 32, 246, 115, 220}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107}, 196}, {{80, 0, 0, 0, 86, 224, 225, 65, 136, 109, 226, 140, 72, 92, 202, 71}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 117, 62, 113, 15}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 196}, {{80, 0, 0, 0, 0, 66, 121, 44, 219, 1, 107, 1, 138, 23, 187, 19}, 196}, {{80, 0, 0, 0, 0, 0, 5, 239, 109, 38, 253, 79, 138, 218, 153, 194}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 6, 87, 166, 133, 142}, 196}, {{80, 0, 0, 0, 0, 0, 0, 115, 72, 61, 201, 172, 81, 23, 227, 219}, 196}, {{80, 167, 231, 123, 222, 17, 202, 36, 42, 162, 131, 108, 101, 105, 229, 133}, 196}, {{80, 0, 0, 0, 0, 0, 0, 183, 239, 174, 118, 235, 69, 188, 82, 128}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 196}, {{80, 0, 0, 200, 235, 127, 183, 72, 192, 122, 218, 125, 41, 237, 232, 36}, 196}, {{80, 0, 0, 0, 202, 61, 226, 68, 0, 111, 239, 197, 64, 222, 253, 5}, 196}, {{80, 0, 0, 91, 99, 87, 226, 85, 149, 194, 21, 29, 217, 5, 72, 4}, 196}, {{80, 0, 0, 0, 0, 0, 84, 236, 14, 101, 18, 251, 193, 239, 87, 186}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 71, 95, 184}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 241, 74, 111, 218}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 175}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 76}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 13, 151, 251, 214}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 46, 169, 111, 190}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 99, 212, 31}, 196}, {{80, 0, 0, 0, 117, 40, 53, 60, 129, 83, 238, 36, 210, 14, 79, 64}, 196}, {{80, 0, 0, 5, 185, 231, 95, 43, 230, 44, 117, 222, 52, 177, 179, 58}, 196}, {{80, 0, 0, 18, 230, 245, 76, 104, 203, 205, 4, 88, 27, 150, 241, 109}, 196}, {{80, 0, 0, 82, 177, 160, 36, 125, 142, 13, 65, 181, 164, 44, 243, 212}, 196}, {{80, 0, 0, 107, 13, 220, 131, 140, 239, 92, 220, 111, 100, 22, 121, 174}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 41, 250}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 112, 65}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 238, 167, 253, 229, 235, 216, 145}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 4, 74}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 167, 184, 168, 214, 122, 69, 199}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 196}, {{80, 0, 0, 62, 126, 233, 76, 73, 243, 84, 20, 28, 96, 200, 1, 189}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 196}, {{80, 0, 0, 197, 201, 102, 12, 126, 56, 95, 193, 87, 66, 253, 132, 220}, 196}, {{80, 0, 0, 192, 62, 23, 130, 167, 29, 6, 38, 15, 88, 1, 20, 210}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 181, 92, 248, 11}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 76, 221, 102, 212}, 196}, {{80, 0, 0, 0, 0, 0, 0, 90, 228, 127, 148, 180, 184, 153, 97, 6}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 99, 228}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 238}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 106, 116}, 196}, {{80, 0, 231, 84, 147, 254, 156, 151, 106, 180, 132, 184, 116, 129, 150, 236}, 196}, {{80, 0, 0, 146, 245, 116, 202, 176, 107, 70, 133, 183, 230, 127, 31, 139}, 196}, {{80, 0, 0, 146, 219, 186, 206, 167, 71, 182, 240, 55, 208, 233, 118, 247}, 196}, {{80, 0, 0, 0, 0, 0, 0, 163, 78, 241, 248, 169, 222, 104, 198, 250}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 196}, {{80, 0, 0, 0, 187, 254, 86, 251, 57, 115, 255, 41, 63, 58, 81, 199}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 215}, 196}, {{80, 0, 0, 0, 0, 69, 247, 122, 173, 50, 72, 113, 207, 132, 168, 40}, 196}, {{80, 0, 0, 0, 0, 222, 255, 36, 10, 51, 43, 115, 117, 24, 25, 110}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 39, 255}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 46, 240, 30, 15}, 196}, {{80, 0, 219, 218, 234, 163, 114, 135, 162, 203, 21, 3, 19, 135, 85, 189}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 74, 149}, 196}, {{80, 107, 203, 226, 63, 107, 238, 18, 3, 144, 58, 127, 144, 231, 146, 114}, 196}, {{80, 78, 203, 29, 92, 179, 202, 163, 176, 49, 191, 154, 135, 6, 232, 178}, 196}, {{80, 0, 0, 0, 44, 49, 6, 33, 239, 22, 180, 48, 175, 8, 19, 150}, 196}, {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 220}, 196}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 155, 131, 41}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 33, 121, 29}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 123, 10, 86, 40}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 14}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 93, 162, 177}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 30, 247}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 5}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 35}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 24, 62}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 207}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 213, 44, 31}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 75, 159, 0, 226, 56}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 62, 189}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 19, 41, 157, 90, 59}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 6}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 20, 98, 198, 110, 154}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 117, 89, 32}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 207, 30}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 115}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 58, 188, 212}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 194, 16, 145, 102}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 91}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 62, 27, 98, 181}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 18, 138, 6, 21}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 56, 27, 109, 202}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 50, 215}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 122, 88, 35, 121}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 11, 48, 17}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 11, 52, 21}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 24, 68, 130, 44, 17}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 127, 211, 35, 244}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 180, 163}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 35, 60, 59, 251}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 217, 32}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 124}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 43, 146, 74, 251}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 88, 108}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 150, 146, 42, 158}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 195, 186, 224}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 252, 122, 24}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 68}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 158, 89}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 221, 178, 22, 204}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 24, 52}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 191, 187}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 214, 92, 105, 172}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 202}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 38, 52, 147, 176}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 248, 26, 110}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 113, 208, 90, 226, 134}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 76}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 33, 48}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 7, 8, 249}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 82, 167, 109, 232}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 145, 159, 230, 225, 51}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 48, 212, 79, 131, 144}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 234}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 241, 132, 221}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 44}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 162, 32, 123, 243}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 235, 198, 224, 75, 141}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 231}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 238}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 247}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 173, 201, 236}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 135, 26, 142}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 185, 219, 208}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 47, 146, 51}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 8, 116}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 166, 97, 59}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 155, 89, 142}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 123, 198, 239, 9}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 93, 158}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 87, 93, 171, 227}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 119}, {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 84, 10, 229, 45}, 119}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 219, 151}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 44}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 142, 115}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 205}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 248, 117}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 154, 206}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 204, 8}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 217}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 219}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 125}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 77}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 54, 220}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 10, 143}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 1, 147}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 150}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 135}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 132}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 97}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 119, 109}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 170, 40}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 196}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 214}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 146}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 170, 63}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 177, 125}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 69, 88}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 240}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 105}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 200}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 8, 117}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 19, 210}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 29, 103}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 165}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 163}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 188, 207}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 69, 242}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 19}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 225, 183}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 34, 93}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 99, 206}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 6}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 36}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 200, 239}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 19, 162}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 31, 95}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 122, 33}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 144, 159}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 204}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 207}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 135}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 244}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 87, 56}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 92}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 52}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 49}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 36, 82}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 49, 220}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 152, 131}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 230}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 29}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 196, 157}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 38, 180}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 93}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 213, 46, 223}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 203}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 200, 33}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 228, 39}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 84, 245}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 36, 221}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 103}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 226, 190, 67}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 247, 68}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 129, 23}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 175}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 5, 170, 20}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 140, 104}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 153, 14}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 127, 201}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 142}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 34, 205, 90}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 70, 5, 98}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 197}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 204, 210}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 42, 31}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 228, 43}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 148, 227}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 7, 103}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 46, 153, 249}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 94, 93, 21}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 138, 16}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 42}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 225, 183, 249}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 239, 118}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 190, 252}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 173, 55, 65}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 242, 239, 69}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 121, 1, 252}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 231, 188}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 71, 30}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 132, 176}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 172}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 251, 183, 134}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 76, 35}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 102}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 12}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 180, 85, 6}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 252, 73, 204}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 195, 255}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 93}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 160, 60, 238}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 192}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 238, 216, 181}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 86, 147}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 172}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 181, 99, 211}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 20, 132}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 251}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 53}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 223, 198}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 91}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 75, 248}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 71, 146, 4}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 211, 184}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 158}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 77, 173, 104}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 52}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 3, 100, 5}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 193, 26}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 54}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 216, 250, 207}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 176, 68}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 68}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 222, 223}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 134, 202, 25}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 26, 31}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 183}, {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 212, 16}, 183}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 5, 126, 138, 138, 133}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 152, 77, 220, 132, 106, 82, 255, 188}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 212, 154, 181}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 174, 177, 74, 16, 60}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 146, 188, 37, 22, 117, 118, 181, 94}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 89, 64, 89, 146, 161, 49}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 95, 63, 189, 30, 58, 34, 36, 192}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 65, 202, 253, 189, 83}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 42, 6, 219, 109, 201, 42, 219, 57, 2}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 123, 44, 232, 91, 247, 51, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 182, 117, 247}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 199, 174, 174, 6, 195}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 47, 108, 63, 183}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 124, 79, 139, 242}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 78, 101, 0, 219, 9, 211}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 3, 19, 91, 153, 159}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 163, 248, 75, 211, 194, 15, 135}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 23, 233, 161, 43, 210, 135, 9}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 44, 187, 172, 204, 146, 253, 14}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 123, 182, 127, 97, 31, 152, 166}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 114, 9, 86, 212, 228, 163, 181}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 47, 55, 199, 62, 176}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 230, 183, 37, 149}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 222, 217, 183, 138, 176}, 207}, {{10, 61, 43, 101, 64, 102, 208, 226, 79, 67, 235, 135, 59, 73, 229, 70}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 49}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 231, 174}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 227, 76, 54, 204, 253, 143, 197}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 18, 169, 241}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 174, 141, 211}, 207}, {{10, 61, 43, 101, 64, 102, 208, 210, 0, 138, 89, 125, 255, 161, 180, 140}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 64, 243, 218, 134, 145, 83, 76}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 171, 40, 107, 220, 46, 58, 25}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 167, 93, 175, 233, 197, 108, 229}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 161, 119, 103, 206, 205, 167}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 213, 28, 115, 98, 65}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 81, 76, 202, 137}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 80, 107, 246, 153, 203, 233}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 98, 27, 47, 213, 240, 115}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 112, 19}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 102, 242, 11, 174}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 205, 174, 136, 215, 237, 83, 36, 252}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 34, 95, 111, 9, 133, 162, 227}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 163, 210, 21}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 201, 27, 205, 86, 31, 247, 7}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 250, 38, 41, 20, 54}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 191, 57, 73, 207, 101}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 34, 0, 70, 164, 98, 234, 5, 196}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 130, 36, 95, 123, 89, 195, 168}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 35, 66, 216, 237, 197, 249}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 6, 104}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 224, 79, 88, 24, 65, 192}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 228, 16, 72, 58, 5, 2, 228, 92}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 8, 3, 187, 238}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 191, 178}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 233, 38}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 59, 173, 33}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 97, 254, 96, 221, 165, 169}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 231, 113, 64, 0, 253, 36, 242, 42}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 43, 56, 237, 66}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 33, 151, 209}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 62, 66, 242, 246, 202, 231, 50}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 126, 19, 169}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 83, 171, 135, 235, 104, 152}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 151, 43}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 237, 131, 51, 56}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 131, 63, 229, 76, 153, 145, 164}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 59, 141, 122, 54, 184, 117, 113, 211}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 33, 44, 0, 103, 23}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 78, 252, 137, 120, 198}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 125, 167, 157, 163, 112, 137, 51}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 231, 89}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 125, 249, 153, 78, 49, 36, 199, 177}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 236, 119, 176, 45, 150}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 113, 104, 157, 18, 193, 244}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 188, 123, 254, 92, 128, 162}, 207}, {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 207}, {{151, 128, 0, 8, 3, 179, 204, 15, 228, 38, 65, 66, 77, 42, 206, 128}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 91, 107, 56, 24, 9, 216, 21, 21}, 102}, {{151, 128, 0, 0, 0, 0, 147, 240, 170, 121, 76, 192, 207, 213, 200, 175}, 102}, {{151, 128, 0, 97, 34, 181, 193, 124, 20, 79, 91, 110, 177, 207, 4, 166}, 102}, {{151, 128, 0, 0, 0, 0, 214, 80, 227, 143, 1, 102, 219, 23, 76, 148}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 214, 89}, 102}, {{151, 128, 0, 220, 240, 56, 206, 153, 162, 99, 24, 15, 238, 253, 254, 120}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 82, 42, 197, 26, 103, 194, 253, 118, 253}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 106, 105, 158, 162, 152, 17, 141, 191}, 102}, {{151, 128, 0, 0, 0, 0, 248, 136, 120, 95, 168, 56, 246, 95, 254, 174}, 102}, {{151, 128, 0, 0, 0, 0, 155, 10, 182, 223, 144, 100, 86, 100, 81, 70}, 102}, {{151, 128, 0, 0, 0, 0, 0, 238, 92, 211, 48, 241, 25, 250, 241, 125}, 102}, {{151, 128, 0, 0, 0, 0, 139, 181, 139, 110, 90, 220, 222, 184, 193, 53}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 84}, 102}, {{151, 128, 0, 0, 40, 110, 100, 240, 240, 164, 129, 188, 109, 63, 138, 121}, 102}, {{151, 128, 0, 0, 0, 0, 80, 210, 122, 95, 38, 150, 244, 99, 158, 13}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 241, 92, 166, 75}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 119, 105, 215, 118, 127, 186}, 102}, {{151, 128, 0, 0, 0, 11, 227, 190, 209, 226, 151, 15, 3, 87, 65, 208}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 20, 91, 130, 245, 86, 133, 229}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 218, 217, 225, 75}, 102}, {{151, 128, 0, 0, 16, 109, 24, 197, 242, 15, 79, 107, 109, 247, 239, 214}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 240, 15, 242, 133, 192, 245, 236, 159, 232, 1, 147, 101, 140, 102}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 135}, 102}, {{151, 128, 0, 0, 0, 0, 222, 102, 157, 184, 41, 173, 74, 232, 69, 59}, 102}, {{151, 128, 0, 96, 64, 112, 55, 24, 190, 82, 64, 6, 57, 179, 41, 249}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 245, 152, 31, 155, 67, 89}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 155, 9, 147, 210, 160, 135, 167}, 102}, {{151, 128, 51, 50, 48, 253, 126, 203, 81, 137, 193, 149, 224, 23, 204, 209}, 102}, {{151, 128, 97, 26, 225, 232, 179, 91, 99, 66, 44, 138, 28, 34, 17, 44}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 95, 51, 236, 235, 66, 53}, 102}, {{151, 128, 0, 0, 0, 0, 0, 129, 94, 162, 20, 2, 112, 245, 189, 177}, 102}, {{151, 128, 174, 230, 148, 137, 171, 49, 126, 17, 185, 189, 224, 76, 198, 169}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 32, 179, 173, 253, 174, 244, 66, 224, 180, 217}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 227, 122}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 62, 215, 46}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 186, 117, 132, 11, 89, 125, 8, 145}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 80, 185, 117, 74}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 43, 129, 24, 203, 7, 3, 246, 16}, 102}, {{151, 128, 0, 0, 0, 9, 221, 252, 90, 244, 44, 2, 221, 188, 240, 178}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 114}, 102}, {{151, 128, 0, 44, 193, 114, 255, 195, 130, 214, 72, 85, 55, 143, 170, 193}, 102}, {{151, 128, 0, 0, 159, 34, 215, 71, 207, 117, 202, 194, 180, 52, 146, 24}, 102}, {{151, 128, 0, 211, 195, 104, 254, 201, 50, 35, 67, 70, 94, 66, 41, 218}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 153, 112, 183, 149, 100, 58, 170}, 102}, {{151, 128, 109, 20, 20, 92, 4, 246, 156, 24, 27, 102, 162, 129, 243, 14}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 147, 11, 154}, 102}, {{151, 128, 0, 107, 211, 60, 14, 66, 99, 52, 120, 137, 49, 96, 187, 163}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 223, 204, 67, 203}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 203, 159, 32}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222}, 102}, {{151, 128, 39, 10, 26, 202, 209, 102, 22, 229, 75, 82, 212, 7, 22, 142}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 79, 63, 128, 57, 98, 31, 42, 11}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 167, 233, 152, 183, 97, 120, 43}, 102}, {{151, 128, 0, 203, 157, 210, 103, 13, 107, 22, 231, 137, 87, 10, 141, 108}, 102}, {{151, 128, 0, 0, 110, 84, 210, 49, 232, 14, 120, 175, 69, 99, 70, 244}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 176, 132, 111, 198, 115, 71, 154, 51, 162}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 8, 87, 163, 162, 44, 176}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 105, 43, 56, 45, 175, 218}, 102}, {{151, 128, 0, 0, 0, 0, 0, 4, 84, 9, 155, 236, 195, 82, 231, 211}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 57, 204, 103, 97, 174, 50, 117, 55}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 97, 69, 220, 228}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 71, 204, 167, 31, 254, 204, 234}, 102}, {{151, 128, 0, 0, 0, 0, 81, 90, 203, 79, 6, 196, 75, 68, 206, 207}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 155, 51, 83, 72}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 56, 214, 208, 98, 110, 28}, 102}, {{151, 128, 63, 222, 252, 162, 126, 30, 154, 165, 201, 131, 63, 159, 110, 52}, 102}, {{151, 128, 0, 0, 0, 73, 48, 254, 244, 74, 194, 30, 16, 187, 225, 219}, 102}, {{151, 128, 0, 0, 0, 0, 53, 38, 177, 121, 49, 144, 43, 145, 43, 252}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 137, 86}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 163}, 102}, {{151, 128, 0, 0, 0, 140, 129, 186, 109, 119, 226, 97, 36, 194, 88, 207}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0}, 102}, {{151, 128, 132, 241, 8, 91, 24, 236, 100, 75, 94, 9, 247, 157, 25, 177}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 201, 241, 188, 109}, 102}, {{151, 128, 0, 1, 116, 84, 95, 86, 243, 179, 202, 34, 46, 77, 75, 10}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 94, 226, 92, 41}, 102}, {{151, 128, 0, 0, 0, 0, 3, 190, 8, 127, 225, 17, 213, 5, 157, 41}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 229}, 102}, {{151, 128, 0, 0, 0, 109, 161, 163, 18, 113, 216, 180, 132, 64, 143, 240}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 214, 203, 210, 209, 123, 134, 235}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 196, 84, 70, 147}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 121, 49, 196}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 4, 234, 224, 147, 8, 127, 217, 94}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 193}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 191, 7, 65, 56, 78, 24, 81, 49}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 120, 102, 233, 228, 23, 41}, 102}, {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 213, 79, 243, 73}, 102}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 95, 130, 238, 52, 248, 84}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 81, 248, 87, 19, 49, 144, 163, 203}, 36}, {{210, 241, 0, 0, 0, 0, 0, 125, 49, 94, 194, 238, 49, 191, 60, 35}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 93, 205, 72, 247, 62, 163, 252}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 149, 183, 203, 19, 151, 111, 173, 164}, 36}, {{210, 241, 0, 0, 0, 0, 92, 35, 254, 104, 27, 242, 194, 0, 153, 11}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 133, 161, 43, 237, 148, 69}, 36}, {{210, 241, 0, 0, 0, 0, 0, 188, 142, 91, 126, 223, 15, 58, 63, 194}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 223, 132, 5, 233}, 36}, {{210, 241, 0, 103, 36, 146, 34, 248, 235, 254, 166, 116, 206, 175, 59, 241}, 36}, {{210, 241, 0, 0, 0, 0, 0, 171, 42, 155, 235, 63, 107, 236, 139, 122}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 184, 94, 227}, 36}, {{210, 241, 0, 0, 0, 0, 163, 1, 9, 93, 129, 200, 91, 87, 208, 128}, 36}, {{210, 241, 0, 0, 0, 0, 22, 206, 138, 41, 154, 88, 120, 198, 132, 229}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 92, 241, 137, 81}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 28, 218, 189, 63, 227, 225, 200}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 133, 117, 118, 141, 110, 38, 38, 109, 178, 174}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 238, 143, 93, 130, 243, 205, 221, 147}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 61, 173, 30, 0, 92, 187, 234}, 36}, {{210, 241, 0, 41, 161, 90, 79, 33, 158, 114, 170, 111, 118, 161, 179, 10}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 35}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 174, 137, 158, 122, 181, 114, 74}, 36}, {{210, 241, 0, 0, 0, 120, 84, 53, 148, 236, 167, 185, 91, 19, 113, 95}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 149, 232, 82, 193, 221, 26, 54, 85, 73, 205, 61, 233, 147}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 177, 34, 66, 192, 51, 33, 62}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 32}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 127, 60}, 36}, {{210, 241, 0, 0, 13, 207, 192, 226, 196, 198, 4, 117, 180, 73, 119, 38}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 192, 141, 95, 129, 148, 19}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 132, 194, 71, 51, 21, 110, 78}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 73}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 4}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 187, 99, 138, 210, 203, 133}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 40, 8, 177, 112}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 229, 244, 151}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 121}, 36}, {{210, 241, 0, 0, 0, 212, 211, 43, 186, 140, 114, 194, 167, 174, 80, 205}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 36}, {{210, 241, 0, 0, 0, 0, 0, 144, 97, 228, 138, 198, 87, 158, 163, 123}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 52, 192, 64, 254, 128, 75, 123, 51}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 63, 128}, 36}, {{210, 241, 0, 0, 53, 42, 9, 74, 210, 73, 240, 36, 7, 75, 54, 76}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 150, 27, 83, 35, 120, 46, 2, 29}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 152, 126}, 36}, {{210, 241, 0, 0, 0, 0, 129, 77, 197, 223, 41, 163, 230, 173, 3, 149}, 36}, {{210, 241, 0, 0, 0, 85, 78, 90, 50, 29, 27, 19, 70, 75, 69, 67}, 36}, {{210, 241, 0, 26, 27, 236, 219, 247, 102, 161, 239, 29, 3, 220, 73, 142}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 35, 73, 220, 154, 204, 111, 2}, 36}, {{210, 241, 0, 0, 86, 114, 117, 254, 220, 8, 186, 228, 136, 240, 91, 83}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 55, 99, 7}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 208, 48, 128, 85, 138, 8, 126, 164}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 227, 58}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 208}, 36}, {{210, 241, 0, 0, 0, 0, 0, 10, 200, 46, 192, 179, 75, 66, 228, 184}, 36}, {{210, 241, 0, 0, 0, 18, 24, 193, 73, 5, 22, 228, 78, 32, 74, 62}, 36}, {{210, 241, 0, 0, 0, 0, 0, 196, 241, 243, 42, 4, 132, 30, 82, 84}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 36}, {{210, 241, 0, 0, 0, 0, 0, 103, 126, 54, 246, 63, 21, 131, 165, 105}, 36}, {{210, 241, 0, 134, 114, 198, 37, 133, 92, 169, 96, 226, 176, 202, 166, 245}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 205, 235, 202, 149, 177, 144, 111}, 36}, {{210, 241, 0, 0, 0, 0, 0, 179, 12, 81, 205, 113, 8, 112, 51, 142}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 201, 76, 180, 45, 122, 13, 19, 13}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 191, 144}, 36}, {{210, 241, 0, 0, 0, 5, 88, 109, 102, 84, 231, 201, 1, 212, 50, 233}, 36}, {{210, 241, 0, 0, 0, 30, 29, 13, 227, 209, 122, 225, 6, 113, 79, 229}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 142, 14}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 88, 82, 38, 46, 47, 172, 91}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 75, 12, 134, 195, 229, 76, 205, 105}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 39, 124, 76}, 36}, {{210, 241, 0, 0, 0, 0, 0, 22, 249, 232, 160, 27, 48, 195, 226, 225}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 195, 104, 56}, 36}, {{210, 241, 0, 0, 0, 91, 210, 82, 94, 199, 134, 253, 101, 95, 72, 17}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 174, 207, 48, 60}, 36}, {{210, 241, 0, 41, 228, 111, 179, 97, 239, 252, 220, 223, 75, 125, 162, 3}, 36}, {{210, 241, 0, 0, 0, 7, 81, 168, 183, 24, 215, 142, 20, 8, 60, 161}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 3}, 36}, {{210, 241, 0, 0, 55, 191, 125, 253, 223, 63, 247, 70, 131, 162, 44, 246}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 141, 114}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 173, 48, 250, 21, 46, 219, 238, 231}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 161}, 36}, {{210, 241, 0, 0, 0, 0, 0, 199, 68, 130, 155, 253, 233, 24, 13, 109}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 150, 119, 133, 146, 0, 35}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 132, 208, 216, 198}, 36}, {{210, 241, 0, 0, 0, 0, 37, 28, 132, 186, 158, 33, 127, 222, 212, 139}, 36}, {{210, 241, 0, 0, 97, 200, 140, 40, 232, 1, 115, 12, 175, 86, 18, 19}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 81, 8, 246, 143, 43, 7, 117}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 7, 35, 48, 44, 151, 73, 207, 46}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36}, {{210, 241, 0, 0, 0, 0, 0, 168, 14, 154, 138, 48, 252, 120, 51, 162}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 114, 249}, 36}, {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 113, 150, 9, 71, 138, 22}, 36}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 1}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 250, 153, 37}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 20, 24, 219, 149}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 165, 47, 225, 134}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 151}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 56}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 210}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 7}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 234, 233, 242}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 58, 239, 233}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 244, 198, 174, 107}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 191}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 115, 212}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 212, 145, 62}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 154}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 135, 249, 16, 222}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 171, 24, 199}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 155, 220}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 83, 102, 120}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 151, 115, 236}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 225, 170, 16}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 115, 149}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 97}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 95, 40, 150}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 53, 122, 103}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 75}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 95}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 122, 96}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 166, 224, 132, 137}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 163}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 40, 239}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 162}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 203}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 49, 63}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 77, 246, 125}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 58, 181}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 119}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 87, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 195, 208, 78}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 222, 93}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 13, 224, 38}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 53, 150}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 88}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 211}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 33, 144, 134}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 229, 181, 34, 9}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 88}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 241, 81, 178}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 228, 200}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 23, 53, 137, 99}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 183}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 116, 74, 250}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 18, 137, 255}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 36, 56}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 231, 183, 34}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 113, 126, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 204}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 140, 74}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 146, 41}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 201}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 224, 20, 250}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 90, 122}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 84, 219, 5}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 26, 228, 117}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 155, 230, 107}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 241}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 130}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 84, 148, 69, 54}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 150, 103, 26}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 77, 103, 188}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 213, 27}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 50, 201, 30}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 209, 194}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 120, 202, 192}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 57, 117}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 67, 118}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 127, 61}, 41}, {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 84, 108, 168}, 41}, {{123, 111, 88, 192, 69, 70, 0, 227, 195, 110, 175, 184, 162, 126, 92, 126}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 130, 193, 230, 161, 184, 27, 81}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 187, 198, 82, 165, 18, 239}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 77, 132, 117, 187, 213, 191, 25, 38}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 8, 119, 2}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 110, 17, 98, 126, 179}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 164, 238, 43, 45, 151, 236, 27}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 136, 226, 246, 39, 15}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 242, 131, 163}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 196, 221, 123, 46, 134}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 155, 164, 63, 52, 135}, 70}, {{123, 111, 88, 192, 69, 70, 0, 196, 182, 79, 215, 108, 158, 178, 131, 12}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 254, 46, 126}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 98, 152, 172, 30, 31}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 176, 1, 11, 7}, 70}, {{123, 111, 88, 192, 69, 70, 0, 141, 196, 28, 205, 9, 198, 167, 105, 15}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 116, 143, 146, 244, 226, 175, 163, 82}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 204, 199, 59, 133, 54, 173, 131, 234}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 105, 82, 167, 179}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 19, 134}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 81, 104, 132, 148, 172, 198, 189, 169}, 70}, {{123, 111, 88, 192, 69, 70, 0, 46, 145, 44, 36, 161, 199, 83, 79, 217}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 168, 120, 139, 105, 47, 105, 146}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 111, 114, 247, 254, 201, 209}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 222, 233, 109, 206, 108, 206, 10, 207}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 238, 176, 161, 68, 182, 254, 41, 245}, 70}, {{123, 111, 88, 192, 69, 70, 0, 121, 47, 129, 230, 38, 72, 79, 26, 134}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 235, 122, 140, 189}, 70}, {{123, 111, 88, 192, 69, 70, 0, 176, 63, 57, 21, 164, 167, 80, 94, 193}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 169, 215, 249, 195, 32}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 34, 17, 24, 2, 21, 190, 128}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 126, 66, 218, 158, 150, 106}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 27, 88, 58, 118, 177, 231}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 167, 159, 242, 75, 65, 56, 78}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 39, 126}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 225, 164, 170, 71}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 228, 11, 119, 140, 115, 37, 142, 112}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 107, 70, 66, 62}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 170, 161}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 161, 12, 84}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 49, 55, 81, 175}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 40, 95, 45, 204, 252, 251, 189, 142}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 112, 237, 130, 209, 141, 37, 21}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 226, 3, 5, 168, 150}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 178, 152, 79, 105, 6, 230, 238}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 202, 185, 235, 87, 57, 243}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 200, 50}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 154, 17, 161, 219, 108, 37}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 248, 138, 195, 72, 191, 150, 40}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 37, 119, 23, 86, 75, 39, 18, 179}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 188, 230, 156}, 70}, {{123, 111, 88, 192, 69, 70, 0, 45, 129, 81, 196, 222, 58, 187, 188, 139}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 111, 68, 29, 194, 23, 90, 33, 224}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 70}, {{123, 111, 88, 192, 69, 70, 0, 24, 221, 21, 16, 104, 180, 182, 121, 19}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 216, 148}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 18, 211, 237, 187, 221, 189, 231}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 220, 78, 37, 160, 204, 236}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 185, 202}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 162, 212, 156, 239, 19, 214}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 25, 219}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 226, 83, 161, 207, 214, 13, 130, 37}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 253, 81, 134, 181, 218, 130, 120}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 158, 179, 242, 132, 27, 193, 189}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 63, 12, 28, 221, 151}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 139, 118, 79}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 231, 199, 28, 203, 139, 137, 59}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 182, 237}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 234, 236, 33}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 68, 169, 120, 115, 241, 171}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 154, 122, 245, 251, 236, 178, 63, 207}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 100, 176, 150, 219, 86, 179}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 69, 210, 32, 247, 161, 8, 209}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 172, 17, 81, 0}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 56, 133}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 6, 208, 62, 221, 4, 158, 57}, 70}, {{123, 111, 88, 192, 69, 70, 0, 74, 120, 192, 110, 181, 84, 55, 14, 112}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 242, 105, 98, 181, 119}, 70}, {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 58, 39, 53, 89, 6}, 70}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 197, 156, 167}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 128, 52, 132, 204, 19}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 73}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 14, 231}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 25, 252}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 62, 170, 78}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 142}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 246, 252, 29, 122, 138, 210, 121}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 224, 244, 28, 131, 194, 15}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 98, 152, 132, 170, 216, 89, 124}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 145, 249, 73, 39, 121, 22}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 9, 23, 213, 168, 114, 11, 169}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 208}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 46, 142}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 118, 123, 182, 255, 202}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 204, 91}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 43, 168, 10, 21}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 122, 184, 96, 25, 9, 139, 73}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 212, 97, 192}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 168, 19, 238, 69, 98, 153}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 186, 138, 9, 153}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 92, 20, 4, 111, 75, 113}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 42, 239, 77, 200}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 191, 124, 33, 68}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 4, 143, 17}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 237}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 133, 151, 252, 140}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 89, 138, 34, 174, 154}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 77, 58, 169, 125, 185, 42}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 56, 182, 208, 149, 200}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 178}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 75, 86, 216}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 190, 117, 231, 208, 47}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 11, 232, 219, 148}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 98, 89, 42, 142}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 140, 102}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 54, 164, 192}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 59, 132, 241}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 139, 93, 228}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 37, 167, 64, 62, 95, 98}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 84}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 212, 2}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 244, 81, 127, 148, 127, 61}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 226, 185}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 161}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 99}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 140, 92}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 107, 197, 185, 220, 26, 54}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 22}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 188, 181, 196, 86}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 157, 151, 129, 29, 136, 115, 22}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 210, 182, 33, 77, 62, 202}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 248, 223, 49, 240, 249, 200}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 9, 231, 162, 104, 157}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 107, 61, 12, 134, 110}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 60, 36, 117, 114, 166}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 209, 245, 213, 113}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 10, 115, 121, 193, 59}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 114}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 90, 110, 232, 255}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 128, 71, 65, 88, 0, 220, 238}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 180, 42, 116, 154}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 132, 156, 131, 188, 230, 108}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 12, 224, 17}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 104, 108, 240, 227, 26}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 119}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 14, 63, 216, 105, 78}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 224}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 177, 120, 141}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 157, 38, 36, 152, 16, 240}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 213, 16, 236, 78, 174, 135, 115}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 184, 238, 27, 179}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 102, 95, 155, 93, 204, 177}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 236, 114, 69, 148, 244, 249, 24}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 132, 191, 133, 75, 81, 110}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 74, 252, 134, 7}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 96, 10, 55, 1, 105, 194}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 159, 58}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 42, 236, 53, 61, 179, 252}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 220, 180}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 132, 60, 128, 233, 232}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 250, 149, 163, 247}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 83, 218, 12, 217, 150}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 160}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 132}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 203, 0, 190, 195, 10}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 205, 12, 246, 40, 218, 96, 117, 217}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 137}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 94, 114, 123, 30, 198}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 124, 19, 7, 240, 103, 36}, 218}, {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 119, 134}, 218}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 226}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 57}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 98}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 215}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 188}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 154}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 208}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 184}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 40}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 123}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 204}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 242}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 72}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 65}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 11}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 95}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 246}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 207}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 209}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 127}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 230}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 139}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 42}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 49}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 212}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 127}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 88}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 113}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 54}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 31}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 45}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 254}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 50}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 4}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 127}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 158}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 216}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 113}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 26}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 25}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 65, 217, 96}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 96, 199, 88}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 42}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 236}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 120}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 133, 95}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 207, 226}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 33, 82, 174}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 65, 3}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 74, 127, 25}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 242, 245, 46}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 14}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 163, 41, 85}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 169, 30}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 41, 238}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 141}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 238, 32}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 142, 138}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 92, 6}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 43, 133, 212}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 219}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 103, 110, 244}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 93}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 73, 163, 118}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 193}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 178, 105}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 194}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 130, 50}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 87, 61}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 108}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 193, 68}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 29, 18}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 61}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 140, 166}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 169}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 226, 36, 76}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 63}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 122, 23}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 181}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 30}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 184}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 111}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 22, 233, 97}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 244, 69}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 24, 174}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 14}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 35, 73, 248}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 30, 131}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 38, 235, 63}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 204, 161}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 75}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 224, 228}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 127}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 21, 133}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 174, 250, 222}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 15, 87, 42}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 99, 8}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 55, 138}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 41, 124}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 231, 145}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 93, 237, 104}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 148}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 84}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 187, 214}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 162}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 123}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 191, 1}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 42, 31, 241}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 105, 166}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 120}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 191}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 221, 19}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 32, 74, 32}, 6}, {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 29, 103}, 6}, {{35, 32, 0, 0, 0, 0, 100, 32, 206, 154, 164, 220, 235, 241, 8, 199}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 91, 151, 67, 56, 244, 213}, 26}, {{35, 32, 0, 0, 0, 214, 101, 42, 251, 22, 161, 202, 71, 208, 147, 241}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 187, 139, 44, 195, 181, 239}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 117, 182, 186, 64, 248, 185}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 120}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 34, 106, 252, 55, 153, 155, 108}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 141}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 133, 9, 171, 220, 84, 129, 73}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 33, 136}, 26}, {{35, 32, 0, 0, 133, 225, 177, 195, 206, 239, 66, 110, 160, 201, 137, 106}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 140, 132, 144, 226, 229, 92}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 181, 104, 193, 134, 241, 204, 141, 161}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 19, 120, 5}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 149, 241, 29, 107, 164, 229, 198}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 134, 128, 146, 86, 235, 254, 190, 76}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 212, 106, 2, 238, 80, 184, 135, 236}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 173, 223, 215}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 71, 194, 98, 236}, 26}, {{35, 32, 0, 0, 91, 0, 122, 82, 82, 14, 191, 28, 207, 109, 248, 254}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 206}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 159, 189, 145, 121}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 170, 234, 18, 163, 212, 193, 74}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 161, 175}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 241, 201, 123, 129}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 107, 75}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 26}, {{35, 32, 0, 0, 128, 130, 215, 152, 20, 193, 48, 220, 74, 216, 110, 21}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 145, 133, 43, 192, 184, 5, 101}, 26}, {{35, 32, 0, 155, 227, 84, 195, 220, 147, 54, 211, 199, 128, 28, 41, 160}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 61, 77, 228, 3, 169, 89, 191, 73}, 26}, {{35, 32, 0, 0, 18, 10, 207, 5, 59, 47, 155, 32, 30, 134, 180, 158}, 26}, {{35, 32, 0, 0, 0, 130, 167, 95, 97, 14, 155, 69, 205, 177, 188, 45}, 26}, {{35, 32, 0, 0, 61, 136, 157, 160, 222, 125, 228, 160, 253, 108, 172, 220}, 26}, {{35, 32, 128, 125, 246, 104, 190, 226, 27, 245, 111, 83, 83, 154, 168, 183}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 100, 10, 142, 56, 193, 33, 226, 244}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 77, 158, 52, 205, 233, 102}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 211, 82}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 106, 133, 91, 68, 43, 239, 125, 13, 20, 247, 223, 43, 59}, 26}, {{35, 32, 0, 0, 168, 101, 9, 173, 163, 255, 44, 77, 167, 31, 158, 31}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 27, 214, 178, 126, 40, 96, 115, 2}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 254, 224, 33, 71, 64, 223, 245}, 26}, {{35, 32, 0, 0, 0, 0, 5, 210, 37, 57, 194, 172, 215, 35, 148, 201}, 26}, {{35, 32, 0, 0, 0, 0, 0, 58, 4, 248, 140, 161, 106, 171, 161, 239}, 26}, {{35, 32, 0, 0, 0, 0, 78, 87, 230, 32, 210, 239, 225, 149, 176, 132}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 52, 50, 66, 217, 125, 234}, 26}, {{35, 32, 0, 0, 0, 0, 0, 186, 127, 87, 72, 81, 74, 77, 189, 23}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 82, 251, 148, 133, 218, 194}, 26}, {{35, 32, 0, 0, 0, 239, 87, 136, 40, 67, 194, 62, 120, 190, 84, 142}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 26}, {{35, 32, 0, 0, 0, 100, 189, 139, 36, 46, 173, 41, 236, 57, 22, 111}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 83, 173, 63}, 26}, {{35, 32, 0, 0, 0, 0, 0, 49, 236, 12, 189, 30, 119, 221, 180, 40}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 180, 74, 58, 17, 78, 133}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 229, 188, 10, 215}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 73, 70, 29, 199, 12, 238}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 112, 106}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 43}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 26}, {{35, 32, 42, 136, 160, 3, 124, 132, 192, 97, 144, 82, 184, 9, 196, 137}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 100, 72, 58}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 156, 200, 231, 166, 149, 31, 78, 216, 193, 134, 31}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 11, 178}, 26}, {{35, 32, 0, 0, 0, 0, 0, 233, 248, 2, 49, 130, 234, 255, 222, 139}, 26}, {{35, 32, 0, 0, 109, 214, 10, 129, 163, 28, 70, 182, 148, 8, 231, 225}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 194, 49, 254, 216, 155, 217}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 142, 143, 170, 135, 162, 72}, 26}, {{35, 32, 0, 0, 0, 0, 14, 83, 198, 49, 116, 220, 62, 220, 211, 38}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 160, 123, 127, 20, 154, 118, 61, 88}, 26}, {{35, 32, 0, 0, 0, 0, 0, 108, 102, 85, 30, 80, 194, 169, 241, 117}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 149, 48, 241, 88, 214, 192}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 26}, {{35, 32, 0, 0, 0, 0, 0, 13, 100, 97, 118, 5, 29, 214, 167, 12}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 236, 122, 87, 217}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 107, 193}, 26}, {{35, 32, 0, 0, 0, 0, 0, 188, 237, 144, 167, 47, 82, 245, 135, 100}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 43, 86, 134, 41, 214, 207}, 26}, {{35, 32, 0, 0, 0, 0, 0, 64, 65, 231, 66, 9, 74, 236, 11, 33}, 26}, {{35, 32, 0, 0, 0, 0, 16, 110, 76, 227, 171, 53, 99, 46, 216, 244}, 26}, {{35, 32, 0, 0, 65, 19, 89, 234, 41, 78, 3, 238, 72, 106, 120, 150}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 198, 65, 157}, 26}, {{35, 32, 0, 0, 0, 0, 44, 150, 196, 4, 42, 220, 105, 102, 66, 99}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 55, 99, 242, 38, 13, 14}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 129, 114, 90, 176, 54, 52}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 141, 222, 12, 252}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 197, 48, 92, 34, 240, 241}, 26}, {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 54, 210, 208, 29}, 26}, {{35, 32, 0, 0, 0, 60, 113, 135, 75, 112, 169, 254, 7, 198, 166, 108}, 26}, {{103, 123, 49, 209, 228, 229, 144, 0, 201, 41, 134, 229, 228, 239, 24, 162}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 95, 51}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 170, 142, 21, 109, 245, 55, 166, 248}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 33, 210, 147, 84, 207}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 250, 32, 89}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 68, 89, 181, 38, 31, 69, 212}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 113}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 46, 210, 48, 70, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 26, 36, 15, 51, 66, 151}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 159, 105, 27}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 196, 88, 107, 64, 70, 31, 127}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 89, 244, 187, 12, 140, 174, 246}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 71, 172, 184, 99, 34, 170}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 227, 86, 130, 51, 220, 41, 60}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 88, 167, 78, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 203, 150, 142}, 149}, {{103, 123, 49, 209, 228, 229, 144, 185, 111, 50, 100, 213, 138, 78, 29, 30}, 149}, {{103, 123, 49, 209, 228, 229, 144, 151, 170, 198, 132, 11, 67, 227, 122, 148}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 27, 159, 61, 215}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 120, 251, 24, 248}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 126, 2, 46, 189}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 135, 2, 73}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 187, 181, 155, 146, 74}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 176, 76, 167}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 221, 204, 39, 94, 192}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 12, 20, 85, 159, 148, 106, 170}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 95, 245}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 26, 148, 93}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 238, 212, 217, 14, 101}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 209, 238, 246, 206}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 182, 92, 52}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 211, 75, 80}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 66, 162}, 149}, {{103, 123, 49, 209, 228, 229, 144, 79, 162, 120, 98, 248, 27, 187, 6, 32}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 223, 90, 61, 111, 133, 195, 16}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 218, 155, 212, 88, 122}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 250, 228, 238, 196}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 181, 68, 79, 173, 249, 128, 77}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 91, 33, 186, 151, 113}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 91, 2, 232}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 22, 43, 88, 68}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 58, 52, 55, 238, 52, 78}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 120, 24, 213, 37, 187}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 181, 136, 87, 225, 198, 145, 31, 180}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 120, 7, 97, 64, 218, 167, 225, 86}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 10, 184, 251, 86, 196, 126}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 117, 219}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 112, 16, 235}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 59, 245, 172, 166, 109, 138, 183}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 48, 92, 89}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 255, 233, 117}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 12, 45, 198, 62}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 200, 119, 28, 101, 189, 23, 135, 115}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 12, 253}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 107, 117, 221, 119}, 149}, {{103, 123, 49, 209, 228, 229, 144, 230, 34, 132, 51, 87, 230, 207, 187, 141}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 238, 101}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 238, 222}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 195, 66, 97}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 49, 92, 17, 226, 10}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 160, 149, 127, 199, 239}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 226, 75, 98, 237}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 130, 36, 176, 104, 54, 27}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 143, 168, 44, 172, 18, 251, 164, 69}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 226}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 176, 146, 96, 223, 131}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 183, 138, 16, 220, 50, 198}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 35, 165, 181, 27}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 242, 25, 111, 138}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 215, 169, 9, 196}, 149}, {{103, 123, 49, 209, 228, 229, 144, 196, 121, 167, 210, 70, 194, 126, 198, 234}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 172, 152, 252, 78, 18, 193}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 111, 49}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 52, 52, 57, 103, 185, 209, 173}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 133, 234, 111, 124, 140, 112}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 82, 21}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 109, 250, 222, 243}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 174, 177}, 149}, {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 149}, {{50, 244, 58, 191, 95, 156, 0, 227, 150, 151, 92, 212, 102, 38, 142, 157}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 83, 76, 97, 60, 105, 121, 169}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 166, 53, 4, 192}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 91, 202, 184, 97, 78, 1}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 49, 156, 249, 20, 60, 2}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 92, 21, 10, 99, 49}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 78, 17, 189, 58}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 168, 241, 213, 190, 173, 75, 212}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 156, 118, 166, 128, 188, 208, 16}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 217, 13, 77, 176, 204}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 161, 137, 106, 7, 26, 179, 67}, 127}, {{50, 244, 58, 191, 95, 156, 0, 32, 165, 249, 47, 81, 129, 66, 150, 158}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 232, 133, 16, 143, 221, 67}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 83, 144, 151, 8}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 10, 194, 178, 32, 220, 47, 219, 110}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 145, 88, 211}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 123, 218, 106}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 224, 30, 176, 248, 142}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 31, 95, 221, 160, 69}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 97, 234, 247, 33, 94, 40, 215}, 127}, {{50, 244, 58, 191, 95, 156, 0, 169, 18, 37, 231, 27, 179, 252, 188, 221}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 104, 181, 23}, 127}, {{50, 244, 58, 191, 95, 156, 0, 199, 216, 146, 83, 53, 54, 124, 30, 174}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 123, 182, 64}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 238, 192}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 183, 131}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 212, 34, 226, 235}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 26, 171, 235}, 127}, {{50, 244, 58, 191, 95, 156, 0, 238, 179, 190, 128, 10, 108, 181, 202, 78}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 54, 35, 102, 147, 78, 89, 99}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 64, 164}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 44, 93, 141, 126, 247, 163}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 52, 166, 175, 193, 48, 46}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 66, 46, 172, 187, 206, 59, 104, 209}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 163, 69}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 230, 200, 148}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 167, 198, 90, 207}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 198, 43, 107, 82, 99}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 166, 104, 142, 233, 21, 72, 63}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 110, 105, 8, 7, 220, 180}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 124, 165, 125, 165, 21, 208, 43}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 177, 88, 147, 91, 226, 153, 125, 144}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 10, 163}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 140, 14}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 249, 8, 38, 110, 53}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 204, 161, 225}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 167, 17, 90, 170}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 207, 143, 190, 156, 221}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 58, 203, 198, 67, 48}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 154, 159, 162, 182, 175, 158, 104, 109, 251}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 192, 32, 190, 1}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 189, 226, 215, 188}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 73, 29, 35, 136, 154, 117, 171}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 132, 198, 21, 145, 204, 239, 70}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 8, 232, 98, 237, 18, 196}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 66, 198, 193, 146, 192, 137}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 40, 55, 163, 243, 30, 207, 28, 7}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 88, 124, 139, 124, 248, 186, 120, 11}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 108, 133}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 122, 177, 132}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 217, 199, 184}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 213, 230, 152}, 127}, {{50, 244, 58, 191, 95, 156, 0, 249, 119, 93, 217, 98, 147, 143, 102, 144}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 169, 111}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 216, 182, 139, 9, 31, 78, 251}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 13, 4, 214, 104, 117, 32}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 236, 15, 227, 139, 57, 138, 146}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 138, 95, 210, 92, 195, 118}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 12, 197, 130, 192, 6, 91, 222}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 98, 125, 213}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 169, 132, 116, 50, 20}, 127}, {{50, 244, 58, 191, 95, 156, 0, 162, 192, 197, 223, 82, 249, 189, 232, 6}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 235, 28, 178, 197, 224}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 180, 97, 175, 3, 3, 196}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 153, 30, 57, 89}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 6, 112, 208, 151, 181}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 181, 50, 119}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 205, 166, 211, 180}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 152, 251, 80}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 113, 177, 243, 62}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 170, 104, 55, 123, 153, 32}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 238, 135, 216, 120, 19, 188, 22}, 127}, {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 127}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 38, 230, 166}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 125, 81}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 95, 132}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 159, 53, 142, 40, 29, 81}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 177, 197, 219}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 224, 252, 124, 101, 156, 77, 53, 112}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 61, 48, 241}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 114, 195, 224, 153, 2, 35, 251}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 20, 180}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 67, 66, 124, 110, 227, 67}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 43}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 7, 48, 166, 217, 104, 203, 210}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 226, 92, 84, 206, 99}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 169}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 50, 145, 69, 115, 81}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 242, 188, 73}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 61, 169, 58, 22, 99, 196}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 210, 75, 198, 211, 186, 255, 62}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 21, 158, 206, 59, 131, 162}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 97, 183}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 23}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 212, 196, 127, 169, 250, 132}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 112, 212, 79, 55, 231}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 251, 33, 206, 179, 158, 157, 93, 26}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 59}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 134, 187, 51, 72, 172}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 103}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 193, 7, 232, 251, 142}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 136, 120, 43}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 176, 22, 105, 250, 135, 213, 209}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 172, 161, 239, 237, 55, 6}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 53, 197, 174, 33, 159}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 186, 222, 205, 231, 183, 133, 91}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 245, 254, 172, 109, 224}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 143, 236}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 157, 183, 74, 16, 4}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 178}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 115}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 69, 249, 152, 70, 92, 234, 42}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 93, 10, 215, 53, 202}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 220, 238, 72}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 36, 249, 112, 174, 203, 54}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 230, 128, 75, 53, 75, 85, 167}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 88, 21, 199, 67, 206, 109}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 165}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 220, 68, 200, 165, 26, 186}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 152, 11, 234, 123, 89}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 217, 1}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 79, 37, 241, 190, 40, 73, 72, 2}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 242, 71, 150, 160, 115, 198, 182}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 98, 8, 229, 169, 144}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 248, 197, 87, 156}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 90, 163}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 194}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 201}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 24, 193, 236}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 64, 54, 217, 154, 63}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 174, 41}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 180, 87}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 219, 225, 80, 20, 119, 251, 246}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 58, 21}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 131, 210, 151, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 89, 238, 246, 123, 52, 7}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 31, 136, 81, 0, 189, 161, 53}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 121, 19, 176, 221, 115, 74, 245, 172}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 9, 83, 197, 5, 150, 183}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 204, 197}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 48, 238, 185, 52, 50, 68}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 92, 6, 97, 38, 66}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 149}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 1, 154, 186}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 142, 74, 23}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 63, 212, 44, 218, 127}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 209, 187, 147}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 166, 255, 0, 200, 77}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 79, 76, 250, 214, 173, 148}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 53, 36, 5, 229, 24, 48, 109}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 197}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 60, 195, 26}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 159, 130, 14, 85, 73, 89}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 163, 141, 253, 76, 39}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 127, 31, 80, 204, 230, 47, 221}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 174, 133, 245}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 181, 136, 4}, 144}, {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 241, 4, 114, 27, 24, 77}, 144}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 196, 82, 127, 42, 97, 28}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 201, 12}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 175, 121, 188, 34}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 223, 179, 33, 141, 151, 155, 111}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 209, 222, 231, 210}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 1, 126, 122, 36, 106, 110, 236, 103}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 10, 148, 110, 254, 92}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 72, 186, 217}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 201, 165, 46, 17, 39, 200, 156, 141}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 64, 65, 34, 209, 26, 83, 51}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 167, 93, 11}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 14, 197, 181, 189, 8, 124, 246}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 216, 106, 64, 69, 207, 253, 147}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 184, 111, 121, 233, 221, 255}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 137}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 82, 198, 199, 185}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 107, 86, 141, 121, 180, 150, 118}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 212, 106, 187, 66, 151}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 142, 175, 95}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 207, 110, 194, 39, 18, 60, 122, 254}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 211, 27, 144, 193}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 153, 107, 8, 41, 216, 255}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 19, 233, 52}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 118, 60, 159, 6, 99, 106}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 197, 228, 252, 24, 19}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 247, 184, 133, 107, 81}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 12, 168, 249}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 227, 105, 75, 149}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 129, 96, 37, 46}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 104, 158}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 209, 221, 213}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 60, 82, 94, 26, 66, 151}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 105, 144}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 238, 186, 203, 10, 168, 29, 218, 142}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 242, 116, 124, 227}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 244, 111, 28}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 50, 178, 217, 234, 159, 41, 189, 136}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 89, 135, 134, 70, 118, 227}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 134, 204, 20, 73, 234, 122, 7, 34}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 9, 153, 216, 1, 20, 105, 3}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 160, 6, 200, 89}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 82, 44, 181}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 151, 128}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 144, 55, 63, 38, 67, 33}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 131, 188, 66, 194, 136}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 236, 253}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 146, 34, 247, 62, 227}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 152, 80, 97, 169, 44, 24, 124, 227}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 65, 121, 94, 92, 42, 219, 22, 68}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 11, 84}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 126, 71, 135, 213, 118}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 18, 203}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 243, 126, 218, 82, 122, 8}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 201, 180, 0, 102, 127, 180, 56, 117}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 109, 133}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 185, 217, 35, 39}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 196, 240, 116, 48, 218, 162, 216, 101}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 45, 172, 69, 45, 102, 213, 50, 45}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 98, 246, 86}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 175, 29, 7, 197, 76, 30, 134}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 111, 4, 143, 40, 208}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 96, 124, 82, 155, 0, 229, 220}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 76, 164, 95, 163}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 144, 137, 140, 12, 169}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 25, 45, 94, 97}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 7, 56, 37, 135}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 212, 17, 68, 74, 145, 54, 191}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 22, 58, 218, 135, 68, 186, 87, 211}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 1, 252}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 108, 50, 112, 255, 114, 122, 69}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 177, 69, 35, 75, 145, 25, 95}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 38, 156, 50, 23, 126, 124}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 27, 252}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 63, 132, 117, 242, 94, 3, 211, 123}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 106, 205, 114, 44, 76, 191}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 35, 6, 252, 105}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 202, 107, 91, 87}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 3, 37, 218, 101, 254, 30}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 14, 44, 111, 88, 245, 90}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 234, 215, 130}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 240, 68, 98, 4, 173}, 213}, {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 100, 73, 48, 225}, 213}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 41, 126, 110, 68, 146, 198}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 40, 103, 93}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 212, 31, 148, 193, 141}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 19, 3, 190, 85, 150}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 61, 31, 165, 59, 12}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 150, 100}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 9, 214}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 8, 238, 40, 245}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 110, 184, 246, 222, 254}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 14, 15, 184}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 40, 224, 41}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 155, 106, 183, 61, 130, 92, 198}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 184, 33, 22}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 130, 174, 254, 149, 38, 203}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 114, 57}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 24, 212, 118, 125, 171, 186}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 93, 77, 78, 136, 127, 166, 147}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 35, 106, 131, 161, 232}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 15, 111}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 151, 44}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 251, 12}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 93, 77, 118, 244, 23, 24, 215}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 135, 251, 254, 157, 173, 148, 82}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 191, 152, 96, 213, 238, 169}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 115, 146, 151, 223}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 238, 182, 37, 115}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 88, 255, 56}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 42, 37, 142, 154}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 80, 227, 68}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 46, 49, 239}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 177, 55, 254, 129}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 16, 111, 150, 3}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 230, 84, 190, 93}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 179, 77, 124, 31, 253, 239}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 173, 116, 113}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 78, 22, 113, 177, 34, 150, 4}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 237, 251, 144, 230, 55, 254, 94, 186}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 184, 168, 254, 246, 122, 142}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 161, 72, 23, 86, 27, 128, 243, 226}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 190, 16, 229, 85, 154, 152}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 41, 58, 75}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 216, 88, 60, 152, 129, 115, 185}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 140, 87, 7, 196, 215, 216, 99}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 111, 157}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 71, 193, 132, 143, 1}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 244, 198, 131, 102, 223, 190, 215}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 184, 55, 211, 191}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 90, 248, 159, 75, 15}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 91, 123, 249, 123, 211}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 233, 9, 196, 203, 162, 153, 175}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 28, 161, 231}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 65}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 38, 31, 223, 150}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 237, 155, 7}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 48}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 120, 29, 213}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 65, 135}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 116, 137, 210, 45, 118}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 139, 183, 92, 163, 230}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 1, 93, 221, 172, 138}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 22, 120, 112, 245, 47}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 186, 109, 128, 60, 91, 103}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 70, 217, 198, 212, 71, 193}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 217, 130, 210, 129, 3, 164, 42, 117}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 176, 54, 219, 58, 55, 235, 204, 220}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 172}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 63, 10, 77, 135, 87}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 180, 225}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 125}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 221, 19, 160, 252, 69, 6, 99}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 243, 220}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 153, 98, 22, 203, 33, 72}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 149}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 161}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 61, 212, 96, 214, 66}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 60}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 26, 32, 30, 185, 204, 71}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 248, 99, 107, 112, 92, 49, 99}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 7}, 115}, {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 81, 121, 5, 85, 6, 254}, 115}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 118, 44, 190, 248}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 10, 83}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 75, 65}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 215, 195, 187}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 245, 72}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 89, 165, 181, 97, 164}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 215, 172, 221}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 68}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 38}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 79, 136, 122, 58}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 219, 217, 176, 149, 133}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 170, 139}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 2, 191, 135, 156, 174}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 189, 34, 5, 236}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 184, 191, 117}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 134, 142}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 165, 55}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 186, 64}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 163, 151, 158, 221}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 83, 29, 49}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 128, 153, 9, 9}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 68}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 85, 152, 181, 37}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 122, 45, 61, 229}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 214, 178}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 235, 30, 91, 180, 192}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 129, 113, 28}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 182, 25, 6}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 232}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 84}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 190, 19, 187}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 251, 4, 32}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 142, 214}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 40, 167, 7, 115}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 68, 206, 22, 17}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 205, 122}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 11, 210, 153, 232}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 173}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 29, 16, 148, 159, 95}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 111, 29}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 32, 178}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 189, 187, 224}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 44, 16, 148}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 189, 133, 26}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 182, 48, 149, 52, 120}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 249, 215}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 168}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 77, 171, 136, 123, 10}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 68, 245, 241}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 13, 111, 220, 176}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 253, 52, 118, 221, 104}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 1, 192}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 8, 32, 172, 134, 246}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 103, 167}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 97, 40, 196, 85, 181}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 95, 91, 228, 59}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 105, 250}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 129, 223, 102, 246}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 170, 89}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 193, 184, 15, 56, 121}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 196, 1, 168}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 161, 23}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 154, 182}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 166, 225}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 123, 86}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 28, 127}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 180, 45}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 79, 61, 63, 83}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 16, 2, 73, 180}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 189, 214}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 225, 45}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 254, 151, 254, 136}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 25}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 7}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 215, 48, 142}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 174}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 98, 207, 62, 232, 75}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 63, 231}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 107, 152, 181, 152}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 207}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 229, 120, 161}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 155, 178, 232}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 13}, 146}, {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 146}, {{160, 180, 220, 128, 0, 0, 0, 107, 211, 242, 150, 80, 1, 6, 54, 177}, 58}, {{160, 180, 220, 128, 0, 0, 0, 26, 122, 143, 105, 131, 211, 249, 203, 117}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 92, 191, 194, 54, 149, 138, 37, 145}, 58}, {{160, 180, 220, 128, 0, 0, 0, 142, 141, 238, 163, 189, 22, 232, 166, 111}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 31, 145, 55, 122, 198}, 58}, {{160, 180, 220, 128, 0, 202, 188, 159, 203, 167, 27, 2, 240, 116, 157, 168}, 58}, {{160, 180, 220, 128, 0, 0, 0, 132, 37, 70, 137, 31, 84, 243, 12, 13}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 165, 253, 198, 54, 125, 169, 156}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 34}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 139}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 41, 127, 88, 57, 24}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 152, 188, 162, 163, 191}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 58}, {{160, 180, 220, 128, 138, 171, 171, 167, 28, 62, 80, 38, 38, 90, 18, 52}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 247, 221, 166, 73, 217, 222, 202, 62}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 114, 81, 217, 160, 236}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 97, 85, 217, 237, 94, 180, 7}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 79, 54, 119, 15, 19, 126, 194, 182}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 194, 3, 138, 228, 85, 9, 186, 31}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 34, 240, 250, 214}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 200, 7}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 177, 120, 129, 53, 61}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 152, 140, 125, 77}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 249, 105, 161, 236, 254, 202, 239}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 112, 222, 143, 176, 75, 58, 18, 28}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 177, 110, 217, 134, 233, 234, 70}, 58}, {{160, 180, 220, 128, 0, 42, 217, 181, 186, 177, 7, 90, 122, 246, 56, 101}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 182, 100, 226, 130, 202}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 188, 141}, 58}, {{160, 180, 220, 128, 0, 0, 0, 213, 251, 212, 173, 197, 236, 31, 132, 221}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 137, 130, 73, 253, 220, 29}, 58}, {{160, 180, 220, 128, 0, 25, 88, 46, 73, 7, 155, 231, 60, 12, 218, 123}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 12, 79, 33, 158, 213, 85, 137, 162}, 58}, {{160, 180, 220, 128, 0, 0, 38, 193, 169, 119, 166, 240, 218, 188, 45, 79}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 230, 92, 79, 102, 240, 240}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 13, 119, 23, 222, 101, 27, 140, 160}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 152, 98, 94, 159, 59, 156, 227, 92}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 69, 243}, 58}, {{160, 180, 220, 128, 0, 0, 74, 176, 31, 204, 219, 67, 68, 213, 221, 51}, 58}, {{160, 180, 220, 128, 0, 151, 86, 217, 203, 35, 151, 56, 159, 48, 182, 252}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 98, 189, 160, 219, 32}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 159, 84, 112, 87}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 171}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 53, 223, 146, 181}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 45, 25, 51, 164, 185, 238, 48, 249}, 58}, {{160, 180, 220, 128, 0, 0, 97, 101, 231, 34, 85, 186, 216, 148, 54, 158}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 68}, 58}, {{160, 180, 220, 128, 0, 0, 140, 185, 239, 149, 242, 76, 234, 51, 198, 52}, 58}, {{160, 180, 220, 128, 0, 92, 120, 145, 50, 92, 250, 235, 254, 183, 11, 168}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 58}, {{160, 180, 220, 128, 0, 0, 157, 105, 83, 76, 250, 56, 89, 133, 247, 142}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 141, 93, 245, 54, 34}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 22, 110, 78, 255}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 101}, 58}, {{160, 180, 220, 128, 0, 0, 0, 88, 240, 116, 78, 88, 41, 65, 59, 201}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 157, 139, 226, 131, 197, 233, 93}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 178, 43, 116, 182, 252, 200, 208, 173}, 58}, {{160, 180, 220, 128, 0, 119, 30, 246, 107, 11, 170, 207, 147, 5, 0, 20}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 244, 134, 18, 205, 208, 181, 85, 250}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 118, 240}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 126, 98, 68, 131}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 142, 1, 183, 187, 37, 62}, 58}, {{160, 180, 220, 128, 0, 219, 161, 53, 49, 4, 95, 58, 227, 83, 187, 41}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 84, 228}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 159}, 58}, {{160, 180, 220, 128, 0, 0, 0, 193, 169, 75, 4, 159, 157, 25, 234, 63}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 165}, 58}, {{160, 180, 220, 128, 0, 0, 0, 184, 31, 145, 22, 220, 243, 119, 18, 4}, 58}, {{160, 180, 220, 128, 0, 0, 102, 198, 161, 214, 131, 213, 95, 132, 104, 244}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 217, 165, 128, 9}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 76, 55, 46, 207, 110, 50, 98, 126}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 156, 239, 154, 237, 227, 174, 169}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 154, 230, 243, 60, 95, 157}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 234, 22, 69, 113, 158, 240}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 108, 100, 200, 118, 149, 141, 133, 212}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 244, 153, 16, 193, 227, 141, 47, 247}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 102, 242}, 58}, {{160, 180, 220, 128, 0, 0, 153, 18, 153, 225, 201, 98, 216, 89, 81, 134}, 58}, {{160, 180, 220, 128, 0, 0, 0, 144, 97, 197, 247, 79, 31, 235, 15, 203}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 211}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 171, 10, 217, 119, 84, 183, 126}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 234, 11, 200, 0, 142}, 58}, {{160, 180, 220, 128, 250, 9, 141, 50, 69, 115, 190, 88, 190, 215, 135, 230}, 58}, {{160, 180, 220, 128, 0, 53, 234, 161, 30, 155, 138, 230, 41, 23, 176, 52}, 58}, {{160, 180, 220, 128, 0, 0, 54, 108, 21, 154, 148, 225, 62, 7, 21, 83}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 216}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 164, 190}, 58}, {{160, 180, 220, 128, 0, 0, 102, 225, 36, 208, 124, 24, 157, 54, 33, 109}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 48}, 58}, {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 54, 113, 27, 145, 184}, 58}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 186, 14, 148}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 144, 75, 153, 45, 173, 206, 147}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 108, 178, 176, 143, 207, 77}, 222}, {{234, 6, 112, 19, 61, 74, 0, 29, 211, 165, 226, 58, 243, 120, 64, 194}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 185, 32, 153, 13}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 171, 80, 1, 87, 223, 190}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 146, 236, 165, 192, 73, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 9, 223, 121, 249, 67, 148}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 246, 205, 73}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 159, 132, 182}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 28, 182}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 30, 48}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 42, 120, 21, 173, 28, 114, 239}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 208, 109, 149, 0, 189, 29, 125, 144}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 68, 81, 84, 239, 170, 92, 231}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 190, 241, 6, 200}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 84, 141, 220}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 251, 148, 222, 190, 117, 133, 21, 32}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 168, 125, 15, 34, 157, 41}, 222}, {{234, 6, 112, 19, 61, 74, 0, 218, 171, 22, 185, 141, 198, 240, 138, 35}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 206, 148, 43, 151, 96, 131, 145, 125}, 222}, {{234, 6, 112, 19, 61, 74, 0, 169, 218, 19, 64, 70, 219, 47, 42, 210}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 77, 39, 254, 12, 175, 220, 0, 227}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 214, 84, 159, 132}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 249, 78, 136, 77, 45}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 174, 97, 12, 197, 16, 129}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 162, 198, 57, 84}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 57, 240}, 222}, {{234, 6, 112, 19, 61, 74, 0, 108, 49, 85, 80, 163, 185, 151, 65, 193}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 98, 251}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 34, 34, 117}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 222}, {{234, 6, 112, 19, 61, 74, 0, 191, 97, 19, 224, 202, 136, 143, 0, 39}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 131, 3, 31, 48, 164}, 222}, {{234, 6, 112, 19, 61, 74, 0, 47, 30, 88, 47, 215, 102, 173, 171, 172}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 222}, {{234, 6, 112, 19, 61, 74, 0, 133, 186, 185, 90, 187, 142, 127, 158, 251}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 8, 92, 115, 101, 199, 224, 226}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 50, 213, 50, 246, 133, 12, 54, 42}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 57, 251, 225, 99, 69, 251, 126, 213}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 238, 192, 77, 172}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 115, 140, 158, 74, 238}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 6, 1, 125, 202, 28, 250, 40}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 131, 201, 104, 31, 104, 45, 69, 197}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 42, 202, 234, 90, 174, 98, 80}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 100, 112, 156, 179, 230, 175, 186, 73}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 4, 102}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 115, 230}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 48, 152, 47, 54, 112}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 129, 2, 22, 201, 126, 124}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 230, 5, 132, 166, 177, 114}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 39, 218}, 222}, {{234, 6, 112, 19, 61, 74, 0, 108, 133, 42, 157, 163, 36, 205, 255, 110}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 35, 110, 243, 111, 34, 136}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 70, 97, 115, 134, 116, 188, 98, 47}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 130, 97, 209}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 243, 171, 153, 135, 217, 245}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 134, 2, 34, 250}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 20, 203}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 170, 148, 169, 154}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 34, 114, 215, 177}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 180, 86, 124, 101, 246, 79}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 170, 31, 14, 107, 48, 195, 26}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 211, 83, 13, 158, 157}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 109, 59, 173, 148, 1}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 150, 91, 100}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 33, 97, 255, 18}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 1, 139, 157, 84, 80, 194, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 124, 33, 115, 119, 26, 237, 163, 68, 193}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 249, 5, 69, 49}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 72, 96, 56, 61, 55}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 53, 226, 41, 13, 135}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 45, 104, 233, 42, 205, 16}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 177, 236, 98, 33, 29, 43}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 6, 70, 74, 234}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 143, 91, 242, 151, 226, 59, 47, 85}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 211, 97}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 98, 82, 9, 144, 4, 25, 210}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 100, 116, 98, 71, 144, 112, 141}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 15, 202, 214}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 139, 132, 44, 120}, 222}, {{234, 6, 112, 19, 61, 74, 0, 62, 213, 59, 166, 159, 3, 241, 174, 163}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206}, 222}, {{234, 6, 112, 19, 61, 74, 0, 115, 60, 94, 53, 129, 177, 249, 67, 107}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 235, 206, 178, 206, 203, 38, 167, 161}, 222}, {{234, 6, 112, 19, 61, 74, 0, 193, 67, 45, 63, 112, 41, 63, 10, 79}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 222}, {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 222}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 49, 80}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 222, 111, 234, 223, 226}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 176, 174, 213}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 212, 29, 227, 117}, 16}, {{97, 110, 34, 117, 149, 148, 0, 48, 190, 30, 248, 145, 56, 144, 9, 89}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 218, 117, 127, 200}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 174, 43, 146, 57, 12, 82, 201}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 227, 20, 204}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 107, 128, 114, 181}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 125, 228, 181, 245, 22}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 109, 233, 230, 230, 85}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 16}, {{97, 110, 34, 117, 149, 148, 0, 104, 194, 86, 250, 61, 36, 216, 3, 165}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 11, 162, 187, 252}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 210, 238}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 172, 56, 193}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 214, 129}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 17, 238}, 16}, {{97, 110, 34, 117, 149, 148, 0, 62, 83, 127, 147, 229, 25, 215, 7, 124}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 16}, {{97, 110, 34, 117, 149, 148, 0, 78, 152, 22, 56, 1, 66, 173, 96, 152}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83}, 16}, {{97, 110, 34, 117, 149, 148, 0, 74, 22, 212, 254, 223, 178, 228, 205, 249}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 45, 231}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 80, 219, 147}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 115, 16}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 16, 102, 175, 67}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 147, 253, 150}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 134, 113, 189, 184}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 90, 245, 126, 215, 73}, 16}, {{97, 110, 34, 117, 149, 148, 0, 115, 44, 241, 76, 219, 103, 155, 124, 177}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 207, 123}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 86, 0, 49}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 122, 218, 68, 64, 197, 110, 253}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 182, 73, 36, 163, 117}, 16}, {{97, 110, 34, 117, 149, 148, 0, 62, 116, 216, 117, 26, 244, 151, 19, 89}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 93, 175, 101, 246, 153, 68, 196, 48}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 233, 111, 225}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 190, 248, 2}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 231, 64}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 231, 162, 229, 95, 164}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 97, 179}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 187, 227, 53, 56, 104, 236, 193}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 9, 5, 31}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 178, 111, 97, 63, 208, 139, 38}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 86, 174, 21, 38, 7, 77, 58, 195}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 186, 166}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 159, 103, 234, 139, 18, 75, 73}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 167, 145, 86, 132, 221, 148}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 239, 105, 41, 141, 137, 232, 27}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 16, 217}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 1, 3, 39, 180, 238}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 122, 181}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 104, 158, 49, 104}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 25, 186, 153, 184, 123, 64, 202, 45}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 248, 78, 98, 49, 15, 219, 75}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 140, 231}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 132, 28, 231, 192, 245}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 91, 133, 185, 123, 196, 86}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 158, 184, 138}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 44, 206, 138, 73, 119, 255, 84, 111}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 184, 244, 244, 4}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 4, 174, 24, 36, 231}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 226, 127, 100, 68, 17}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 91, 74, 162, 149, 79, 72, 128, 70}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 55, 179}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 54, 249, 93, 143, 197}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 167, 197, 92, 132}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 61, 126, 60, 124, 202, 235, 77, 11}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 207, 102, 165, 176, 151, 206}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 129, 39, 234, 172, 137, 111, 5, 37}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 148, 233, 22, 51}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16}, {{97, 110, 34, 117, 149, 148, 0, 108, 5, 236, 166, 208, 20, 93, 56, 218}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 110, 86, 150, 211, 161, 214, 31}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 29, 71, 23}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 81, 46, 7, 129, 147}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 62, 110, 42, 90, 117, 143}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 82, 142, 244, 135, 44, 101, 122}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 140, 131, 149, 48, 43}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 167, 24, 222, 231, 236, 140, 7, 228}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 217, 113, 49, 98, 180, 236}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 15, 54, 54, 56, 213}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 236, 141, 208, 34, 211}, 16}, {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 216, 184, 16}, 16}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 111, 92, 170, 88, 181, 249}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 80, 80, 11}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 221, 200, 46, 91}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 22, 10, 207, 192, 87, 61, 130}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 85, 214, 171, 209, 197, 138, 202}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 143, 19, 207, 54, 40, 169}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 146, 113, 49}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 197}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 20, 179}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 72, 165, 156, 38, 171, 55}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 61}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 227, 120}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 29, 236, 157, 108, 15}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 67, 175, 112, 215, 244, 143}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 163, 175, 2, 94, 229, 191}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 248, 69}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 4, 114, 180, 189, 192, 35}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 168, 232, 155, 169, 141}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 72, 221}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 89}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 152, 126, 113, 108, 128}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 24, 110}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 60, 252, 47, 252}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 106}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 230, 173, 248}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 63, 242, 201, 68, 11}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 111}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 38, 184, 110}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 52, 179}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 136, 208, 163, 103, 213}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 190, 242, 134}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 49, 140, 150, 66, 155}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 219}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 89, 82, 136, 201, 101}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 106}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 226, 14, 246}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 2, 219, 87, 139, 197, 127, 138}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 232, 83, 191, 144, 82}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 126, 129, 14, 66, 1, 35}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 91, 166}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 93}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 10, 181, 217}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 183, 237, 98, 197, 159, 161, 175}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 106, 174, 48, 122}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 133, 71}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 108, 63}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 50, 25, 37, 200}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 159}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 25, 162, 135}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 116, 98, 141, 213, 48, 26, 97}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 78, 199, 96, 180, 2}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 176}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 80, 122, 0, 78, 90}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 196, 50, 71, 178, 147, 116, 181}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 126, 70, 61, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 179}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 190, 28}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 90, 218, 32, 106, 22, 123}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 215, 46, 50, 37, 58, 113, 44}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 11, 151}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 176, 187, 176}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 112, 74, 54, 176, 109}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 146, 161, 232}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 134, 132, 158, 202}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 147, 202, 200}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 179, 219, 183, 66, 13, 24}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 196, 172, 221}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 2}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 230, 53, 139, 131, 188, 17, 157}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 32, 176, 198, 193, 178, 96, 170}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 88, 250, 88, 204}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 155, 188}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 254, 121, 41, 215}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 57, 17, 144, 75, 102}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 236, 86, 255, 246, 150, 159}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 190}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 100, 37, 179, 252, 42, 99}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 178, 28}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 234}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 239, 36}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 110, 183, 215}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 233, 185, 32}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 230, 11, 247, 231, 108, 208}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 215, 235, 222, 168, 102}, 169}, {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 235}, 169}, {{169, 134, 111, 89, 9, 0, 61, 62, 186, 173, 79, 60, 171, 130, 96, 153}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 96, 138, 54}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 85, 219, 234, 1}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 48, 35, 5, 46}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 233, 230, 115}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 229, 242, 35, 155}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 28}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 23, 170, 122, 247}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 92, 32, 241, 232}, 175}, {{169, 134, 111, 89, 9, 0, 249, 123, 106, 186, 223, 229, 172, 4, 122, 106}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 206}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 97}, 175}, {{169, 134, 111, 89, 9, 0, 0, 54, 18, 116, 194, 241, 154, 70, 179, 162}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 143, 182, 33, 230, 148, 253}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 129, 201, 237, 155, 120, 139, 226, 224}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 250, 105, 25}, 175}, {{169, 134, 111, 89, 9, 0, 202, 250, 98, 228, 10, 146, 97, 187, 241, 211}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 137, 62, 144, 21, 161}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 164, 56, 232, 215, 153}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 184, 97, 115, 92, 17, 238, 39}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 6, 91, 77, 157, 239, 163, 233}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 178, 150, 239}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 211}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 99, 74, 122, 110, 87, 17, 221}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 93, 203, 221, 178}, 175}, {{169, 134, 111, 89, 9, 0, 169, 192, 129, 73, 9, 24, 220, 127, 223, 72}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 218, 10, 88, 193, 86, 213}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 72, 155, 55, 51, 5, 40}, 175}, {{169, 134, 111, 89, 9, 0, 182, 187, 181, 101, 108, 148, 58, 240, 74, 17}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 88, 193, 230, 186, 55, 52, 165, 252}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 69}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 204, 173, 72, 97, 71}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 125, 175, 59, 115, 159, 94, 156, 234, 119}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 49}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 155, 205, 160}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 23, 56, 43, 198, 247, 169}, 175}, {{169, 134, 111, 89, 9, 0, 241, 237, 44, 245, 127, 36, 67, 138, 245, 54}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 114, 102, 208, 230, 181, 138, 248, 20}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 182, 17, 26, 91, 207, 245, 254, 20}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 196, 155, 50}, 175}, {{169, 134, 111, 89, 9, 0, 14, 50, 173, 163, 120, 92, 54, 133, 216, 19}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 117, 175, 81, 192, 48}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 81, 226, 125, 127, 109, 101, 137}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 25, 159, 110, 232, 5}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 209, 233, 86}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 57, 238, 41, 108, 104, 106}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 60, 185, 187, 58, 237, 131}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 143, 15, 191, 123, 12, 240, 131, 117}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 156, 209, 195, 58, 184, 22, 68, 68}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 178, 158, 162, 244}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 81, 233, 197, 164, 16, 99, 149}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 182, 155, 82}, 175}, {{169, 134, 111, 89, 9, 0, 8, 44, 49, 109, 85, 74, 214, 73, 232, 85}, 175}, {{169, 134, 111, 89, 9, 0, 0, 173, 128, 182, 192, 203, 251, 187, 48, 109}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 121, 164, 152, 192, 103, 166, 74}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 59, 98, 100, 66, 67, 122, 152}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 33, 224, 149}, 175}, {{169, 134, 111, 89, 9, 0, 0, 190, 180, 25, 231, 103, 18, 202, 116, 14}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 250, 186, 39, 194, 119, 54, 228}, 175}, {{169, 134, 111, 89, 9, 0, 0, 24, 53, 105, 151, 81, 176, 86, 143, 152}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 99}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 120, 174, 94, 182, 127, 137, 36}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 76, 181, 126, 181, 203, 177, 249, 180}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 239}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 50, 245, 151}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 214, 219, 237, 209, 112, 109}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 84, 63, 5, 12, 94, 144}, 175}, {{169, 134, 111, 89, 9, 0, 71, 159, 204, 245, 152, 52, 50, 82, 254, 250}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 100}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 251}, 175}, {{169, 134, 111, 89, 9, 0, 0, 57, 73, 66, 34, 16, 140, 53, 74, 174}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 53, 190, 213, 239, 228, 127, 216, 130}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 181, 125, 193, 57}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 44, 2, 239, 65, 75}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 114}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 174, 240, 178, 181, 97, 14}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 169, 89, 63, 176, 251, 221}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 196, 95, 184}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 73, 38}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 135}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 165, 162, 161, 233, 27, 164}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 96}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 137, 190, 221, 173, 103, 31}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 111, 160, 22, 34}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 16, 38, 134, 43, 64, 200}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 70, 172, 225, 152, 188, 60, 173}, 175}, {{169, 134, 111, 89, 9, 0, 0, 0, 0, 178, 79, 8, 247, 17, 248, 106}, 175}, {{134, 80, 227, 43, 0, 33, 217, 198, 132, 55, 149, 9, 123, 26, 90, 218}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 26, 104, 153, 180, 134}, 3}, {{134, 80, 227, 43, 0, 13, 19, 48, 186, 202, 140, 115, 201, 55, 105, 3}, 3}, {{134, 80, 227, 43, 0, 14, 150, 21, 61, 182, 53, 76, 111, 207, 154, 251}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 75, 175, 125, 50}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 48, 31, 82, 55}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 43, 233, 45, 66, 246}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 5, 101, 20, 45, 211}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 101, 238, 189, 69, 19, 105, 180, 108, 40, 104, 171}, 3}, {{134, 80, 227, 43, 0, 0, 165, 234, 153, 226, 108, 139, 125, 13, 238, 69}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 3}, {{134, 80, 227, 43, 0, 0, 0, 41, 247, 88, 38, 9, 225, 142, 156, 80}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 220, 125, 135, 151}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 47, 83, 210, 41}, 3}, {{134, 80, 227, 43, 0, 0, 137, 42, 103, 115, 36, 155, 218, 80, 86, 125}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 130, 144, 137, 94, 49, 7}, 3}, {{134, 80, 227, 43, 0, 0, 0, 177, 110, 24, 103, 40, 213, 232, 254, 184}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 137, 129, 50, 97, 50, 33}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 172, 166, 175, 229, 131, 255}, 3}, {{134, 80, 227, 43, 0, 0, 0, 211, 3, 29, 194, 162, 0, 199, 205, 24}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 255, 21}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 243, 252, 9, 240, 83, 168, 50}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 250, 147, 179, 251, 248, 236, 206, 74, 23, 138, 45}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 248}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 83, 227, 192, 211, 220, 58, 146}, 3}, {{134, 80, 227, 43, 0, 0, 0, 106, 149, 134, 228, 214, 157, 145, 87, 174}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 180, 48, 198, 252, 20, 134, 148}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 14, 168, 247, 248}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 6, 219, 247, 174, 101}, 3}, {{134, 80, 227, 43, 0, 0, 217, 191, 21, 37, 176, 95, 238, 245, 145, 234}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 225, 201, 113, 20, 103, 110, 22, 37}, 3}, {{134, 80, 227, 43, 0, 0, 0, 67, 152, 88, 41, 217, 246, 207, 173, 103}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 3}, {{134, 80, 227, 43, 0, 0, 4, 19, 145, 253, 1, 5, 64, 234, 101, 169}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 4, 227, 27, 46, 27, 201, 121, 229, 219, 18}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 245, 254, 110, 159, 148, 109}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 161, 120, 212, 169}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 3}, {{134, 80, 227, 43, 0, 249, 29, 228, 80, 219, 142, 224, 196, 170, 167, 58}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 71, 13, 123, 61, 150, 71, 71, 34}, 3}, {{134, 80, 227, 43, 0, 0, 56, 214, 203, 178, 186, 92, 61, 85, 138, 191}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 154, 230, 23, 2}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 134, 67, 241, 153}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 5}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 13, 178, 21, 244}, 3}, {{134, 80, 227, 43, 0, 0, 153, 220, 197, 25, 171, 12, 149, 72, 141, 105}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 171, 206, 24, 130, 207, 74}, 3}, {{134, 80, 227, 43, 0, 0, 0, 35, 98, 201, 60, 105, 9, 121, 194, 48}, 3}, {{134, 80, 227, 43, 0, 23, 116, 157, 178, 100, 144, 46, 28, 102, 105, 29}, 3}, {{134, 80, 227, 43, 0, 0, 221, 35, 119, 253, 152, 102, 167, 31, 98, 116}, 3}, {{134, 80, 227, 43, 0, 28, 233, 25, 210, 248, 215, 133, 144, 35, 53, 17}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 231}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 84, 57, 127, 43, 149, 238}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 157, 252}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 84, 154, 94, 143, 209, 57, 241, 164}, 3}, {{134, 80, 227, 43, 0, 93, 76, 28, 63, 250, 219, 141, 24, 172, 250, 118}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 74, 145}, 3}, {{134, 80, 227, 43, 0, 0, 101, 150, 163, 70, 127, 16, 176, 183, 219, 105}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 47, 52}, 3}, {{134, 80, 227, 43, 0, 0, 0, 153, 142, 86, 24, 58, 8, 178, 175, 122}, 3}, {{134, 80, 227, 43, 0, 119, 208, 189, 193, 242, 54, 92, 206, 87, 247, 122}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 61, 219, 153, 252, 130, 202, 211, 5}, 3}, {{134, 80, 227, 43, 0, 61, 8, 247, 47, 50, 194, 187, 253, 4, 1, 207}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 126}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 26, 68, 99, 52, 166, 236}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 142, 33, 206, 110, 133}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 118}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 35}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 164, 41, 18, 101, 144}, 3}, {{134, 80, 227, 43, 0, 0, 55, 129, 166, 153, 172, 0, 63, 63, 144, 26}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 254, 207, 224, 121, 115}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 66, 104, 155, 184}, 3}, {{134, 80, 227, 43, 0, 0, 19, 198, 55, 150, 142, 90, 140, 105, 201, 119}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 206, 112, 98, 137, 178, 216}, 3}, {{134, 80, 227, 43, 0, 0, 182, 153, 45, 174, 60, 109, 185, 227, 232, 140}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 112}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 60, 115, 225, 233}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 38, 187, 236, 193, 215, 145}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 179, 72, 92, 92}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 114}, 3}, {{134, 80, 227, 43, 0, 0, 206, 193, 252, 76, 55, 150, 131, 155, 215, 67}, 3}, {{134, 80, 227, 43, 0, 28, 243, 77, 168, 125, 28, 166, 115, 190, 40, 121}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 211}, 3}, {{134, 80, 227, 43, 0, 0, 0, 187, 3, 154, 115, 148, 96, 206, 109, 75}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 253, 32, 162, 126}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162}, 3}, {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 60, 179}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 251, 56, 186}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 244}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 142, 62}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 51, 85}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 179}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 67}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 68, 198}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 247, 251}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 174}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 110, 195}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 45, 62, 180}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 73, 255}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 98, 191, 171}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 62}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 188, 46, 79}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 105}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 239, 159}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 53, 138, 56}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 129, 218, 189}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 72}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 28, 247}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 101, 137}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 205}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 146, 193}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 156}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 93, 17, 44}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 152, 215, 30}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 23, 9}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 161, 62, 208}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 42, 232}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 6, 97, 188}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 246, 181, 17}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 20, 151}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 243, 173}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 190, 62, 39}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 180, 78, 227}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 48, 107}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 100, 30, 231}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 24, 84}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 81, 208}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 224}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 140, 226, 15}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 56, 152, 126}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 9, 61, 175}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 204}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 71}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 17, 173}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 215}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 227, 52, 4}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 234, 198}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 84}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 105, 131, 24}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 26, 120, 52}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 224, 130, 174}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 144}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 227}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 212}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 244}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 254, 147, 161}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 158}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 68, 122}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 230, 10, 183}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 8, 127}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 193, 63}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 184, 195, 15}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 50}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 1, 170}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 214, 133, 141}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 66, 244, 17}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 97, 132}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 80, 216}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 27}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 93, 202}, 2}, {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 99, 39}, 2}, {{189, 190, 121, 135, 160, 0, 35, 62, 72, 36, 79, 168, 228, 74, 74, 167}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 246}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 146, 36, 10, 240, 137, 133, 102, 198, 45, 216}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 44, 132, 130, 54, 123, 221}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 190, 22, 76, 2, 146, 190, 169, 16}, 193}, {{189, 190, 121, 135, 160, 0, 0, 94, 54, 56, 117, 42, 17, 247, 73, 1}, 193}, {{189, 190, 121, 135, 160, 0, 149, 59, 91, 26, 123, 38, 60, 191, 208, 140}, 193}, {{189, 190, 121, 135, 160, 0, 241, 69, 43, 254, 56, 38, 5, 245, 107, 232}, 193}, {{189, 190, 121, 135, 160, 0, 0, 167, 5, 223, 38, 109, 201, 89, 112, 169}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 115, 80, 11, 101, 146, 51, 170, 232}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 174}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 59, 16, 196, 191, 96, 20, 205, 42}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 253, 103, 113, 208}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 178, 150, 87, 112, 173, 74}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 247, 159, 241, 175}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 102}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 89, 156, 40, 208, 121}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 217, 99, 223, 180}, 193}, {{189, 190, 121, 135, 160, 0, 244, 11, 220, 216, 124, 212, 7, 157, 73, 193}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 90, 110, 90, 58, 119, 119}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 211, 81, 182, 244, 59, 131, 113}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 38}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 93, 108, 98, 229, 236, 22, 194, 210, 17, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 143, 184, 162, 46, 232, 216, 217, 5}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 100, 97, 185, 38, 234, 16, 82, 150, 100}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 138, 178, 146, 146, 29, 102, 7, 190}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 78}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 164, 6, 249}, 193}, {{189, 190, 121, 135, 160, 0, 0, 140, 70, 219, 211, 235, 94, 157, 192, 20}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 2}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 129, 75, 25, 254, 111, 118, 30}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 165, 249, 184, 224}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 117, 122, 87, 46, 29, 221}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 8, 94, 112, 222}, 193}, {{189, 190, 121, 135, 160, 0, 0, 254, 150, 88, 197, 5, 124, 35, 116, 73}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 138, 131, 9, 57, 187, 201, 222, 156}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 12, 189, 107}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 209, 80, 11, 116, 123}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 231, 129, 46, 165, 52}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 84}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 40, 134, 140, 185, 237, 67, 11, 156}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 30, 219, 229, 83, 194}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 176, 57, 77}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 114, 139, 126}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 141, 95, 78, 180, 243}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 154, 187, 207, 11}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 217}, 193}, {{189, 190, 121, 135, 160, 0, 32, 33, 180, 155, 101, 254, 94, 113, 222, 126}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 37, 206, 178, 183, 151, 66, 38, 48}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 191, 51, 128, 118, 203, 153}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 136, 196, 119, 147, 165, 156, 122, 149}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 55, 235, 141, 152}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 2, 182, 177, 194}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 210, 131, 205, 33, 218, 88, 82, 226}, 193}, {{189, 190, 121, 135, 160, 0, 138, 5, 181, 179, 217, 24, 247, 175, 237, 15}, 193}, {{189, 190, 121, 135, 160, 0, 136, 166, 22, 38, 72, 220, 81, 94, 90, 112}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 35}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 86, 227, 64, 57, 218}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 50, 132, 165}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 8, 0, 33, 211, 167, 186, 226}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 154, 73, 111, 96, 34, 148, 137, 209, 151, 196, 228}, 193}, {{189, 190, 121, 135, 160, 0, 0, 113, 172, 226, 91, 224, 187, 231, 93, 32}, 193}, {{189, 190, 121, 135, 160, 214, 140, 233, 230, 33, 25, 62, 17, 249, 191, 80}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 222, 132, 68, 240}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 150, 190, 79, 250, 33, 39}, 193}, {{189, 190, 121, 135, 160, 0, 25, 159, 86, 185, 146, 21, 56, 31, 168, 193}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 249, 237, 171, 251, 35}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 11, 231, 53, 102, 127, 17, 218, 136}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 179, 145, 212, 99}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 82, 168, 46, 140, 78, 252, 92, 215}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 16}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 71, 120, 21, 45, 138}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 134, 234, 246, 33, 34, 110}, 193}, {{189, 190, 121, 135, 160, 0, 0, 11, 123, 201, 171, 142, 96, 164, 173, 23}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 68, 214, 234, 136, 92, 22}, 193}, {{189, 190, 121, 135, 160, 0, 3, 183, 63, 222, 226, 48, 53, 20, 166, 184}, 193}, {{189, 190, 121, 135, 160, 111, 16, 229, 53, 48, 12, 38, 19, 41, 170, 134}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 250, 28, 75, 13, 154}, 193}, {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 57, 211, 33, 41}, 193}, {{189, 190, 121, 135, 160, 0, 0, 213, 174, 221, 208, 4, 36, 176, 237, 220}, 193}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 93}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 255}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 116}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 91}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 170}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 140}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 211}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 76}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 123}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 86}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 2}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 140}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 44}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 165}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 125}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 107}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 208}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 151}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 93, 37, 242, 207, 151, 21, 91}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 252, 230, 132}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 153, 144, 110, 111}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 80, 236, 163}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 227, 67, 96, 8, 117, 15, 209}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 27, 139, 151}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 66, 51, 175, 98, 244, 92, 173}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 2, 205}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 108, 2, 116, 94}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 91, 34}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 78, 221}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 7, 183, 172, 218}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 22, 118, 37, 213, 153, 194, 151, 11}, 182}, {{32, 1, 115, 244, 33, 219, 96, 83, 194, 96, 190, 7, 96, 23, 113, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 224, 253, 168, 80, 70, 107, 61}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 109, 38, 32, 248, 76}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 6, 134}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 217, 253, 181, 62, 102}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 3, 195, 162, 205, 25, 243}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 239, 210, 216, 30}, 182}, {{32, 1, 115, 244, 33, 219, 96, 226, 116, 4, 195, 61, 48, 31, 58, 137}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 37, 224, 48, 155}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 114, 123, 118, 227}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 10, 229, 185, 243, 122, 154, 232}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 202, 89, 25}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 31, 56}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 206, 44, 152, 139, 177, 166}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 75, 152}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 83, 82, 249, 93, 4, 81, 230, 225}, 182}, {{32, 1, 115, 244, 33, 219, 96, 164, 238, 115, 99, 237, 115, 78, 76, 2}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 53, 32, 224, 103}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 229, 137, 41, 121}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 143, 122, 54, 16, 235, 196, 104, 213}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 25, 49, 125, 74, 61, 100, 58, 135}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 180, 83, 254, 54, 124, 233, 60, 75, 87}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 160, 61, 138}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 205, 54, 73}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 193, 77, 133, 53, 69, 38}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 59, 69, 137, 173, 83, 63}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 173, 203, 238, 238, 122, 117, 240, 171}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 66, 91}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 59, 102, 222, 113, 147, 231}, 182}, {{32, 1, 115, 244, 33, 219, 96, 205, 54, 32, 138, 57, 151, 251, 111, 45}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 71, 152, 81, 244, 233}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 231, 254, 15, 94}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 166, 55, 179, 154, 124, 49, 119, 88}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 6, 0, 143, 39, 59}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 39, 88, 164, 35, 61, 233}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 29, 160}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 57, 147, 162, 133, 118, 141, 62}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 196, 141, 228, 11, 135, 97}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 223, 232, 1, 165, 229}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 165, 69, 131, 22, 252, 86}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 168, 252}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 207, 130, 10, 118, 164}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 134, 15, 92, 24, 108, 95, 28, 103}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 18, 234, 76, 87, 6, 115}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 70, 240}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 212, 124, 243, 201, 200, 31}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 188, 40, 224, 3, 214, 125, 182, 117}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 197, 67, 207, 20}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 211, 188, 93, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 244, 29, 183}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 182, 32}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 162, 105, 161, 244}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 141, 244}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 92, 220, 39, 228}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 27, 137, 143, 120, 146, 226, 141}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 1, 245, 84, 87, 73}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 204, 117}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 132, 0, 192, 17, 174}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 38, 143}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 81, 118, 192, 160, 162, 211, 254, 192}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 101, 253}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 236, 48, 3, 244, 129, 156, 52, 157}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 138, 35, 30, 196, 59, 153, 134, 170}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 140, 138, 15, 47, 15, 240, 43, 116}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 211, 9}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 207, 48, 75, 194, 97, 231}, 182}, {{32, 1, 115, 244, 33, 219, 96, 57, 248, 23, 232, 213, 180, 5, 138, 127}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 196}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 31, 18, 108, 168, 63, 231}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 216, 255, 178, 92, 26, 191, 166, 152}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 180, 87, 181}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 154, 153, 191, 184}, 182}, {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 182}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 18, 243, 124, 250, 122, 84}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 232, 226}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 148}, {{220, 128, 0, 0, 198, 142, 2, 133, 65, 142, 129, 243, 177, 228, 89, 89}, 148}, {{220, 128, 0, 0, 0, 236, 99, 209, 97, 172, 179, 242, 88, 200, 200, 167}, 148}, {{220, 128, 0, 218, 117, 150, 38, 172, 134, 156, 151, 120, 157, 42, 92, 81}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 129, 149, 52}, 148}, {{220, 128, 0, 0, 30, 137, 246, 247, 212, 244, 180, 134, 38, 175, 3, 70}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 199, 204}, 148}, {{220, 128, 0, 156, 139, 88, 163, 120, 78, 170, 71, 103, 236, 87, 231, 102}, 148}, {{220, 128, 0, 0, 0, 0, 177, 255, 185, 220, 224, 249, 242, 228, 55, 242}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 138, 163, 153, 1, 221, 22, 143}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 35, 102}, 148}, {{220, 128, 0, 0, 0, 61, 99, 134, 153, 216, 236, 252, 127, 83, 125, 29}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 12, 133, 53}, 148}, {{220, 128, 0, 0, 0, 0, 76, 31, 182, 177, 57, 8, 140, 189, 151, 245}, 148}, {{220, 128, 0, 0, 0, 213, 122, 75, 0, 42, 22, 19, 30, 31, 158, 151}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 130, 27, 97}, 148}, {{220, 128, 124, 181, 14, 222, 202, 235, 131, 99, 75, 116, 42, 84, 225, 208}, 148}, {{220, 128, 0, 0, 0, 0, 0, 122, 141, 10, 116, 11, 170, 23, 194, 225}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 149}, 148}, {{220, 128, 0, 87, 111, 63, 231, 212, 12, 95, 226, 67, 154, 18, 166, 195}, 148}, {{220, 128, 0, 0, 0, 0, 158, 123, 21, 204, 171, 184, 55, 98, 100, 228}, 148}, {{220, 128, 0, 0, 0, 0, 192, 198, 198, 252, 122, 154, 80, 148, 69, 86}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 22, 17, 128}, 148}, {{220, 128, 0, 0, 0, 0, 0, 197, 65, 71, 27, 90, 104, 173, 133, 246}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 221, 152, 104}, 148}, {{220, 128, 0, 0, 0, 31, 82, 62, 154, 165, 75, 108, 78, 64, 22, 216}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 201, 211, 83, 82, 237, 165}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 131, 153, 38, 106, 163, 9, 85, 31}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 160}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 11, 170, 9}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 96, 248}, 148}, {{220, 128, 0, 0, 0, 0, 148, 203, 60, 236, 207, 220, 52, 238, 152, 187}, 148}, {{220, 128, 0, 0, 0, 77, 51, 98, 94, 208, 26, 241, 53, 0, 26, 114}, 148}, {{220, 128, 0, 0, 94, 215, 184, 197, 96, 236, 48, 235, 182, 232, 38, 129}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 67}, 148}, {{220, 128, 0, 41, 15, 41, 139, 72, 188, 254, 126, 203, 179, 5, 71, 249}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 40, 196, 195, 100, 112, 240, 101}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 148}, {{220, 128, 0, 0, 0, 157, 226, 203, 111, 185, 38, 205, 213, 89, 173, 74}, 148}, {{220, 128, 0, 0, 103, 121, 196, 125, 189, 246, 68, 151, 36, 142, 247, 166}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 169}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99}, 148}, {{220, 128, 102, 67, 247, 94, 10, 128, 107, 138, 42, 17, 222, 138, 110, 237}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 173, 18, 44, 55, 51, 232, 90}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 148}, {{220, 128, 0, 0, 0, 0, 76, 197, 6, 43, 59, 228, 9, 105, 116, 154}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 81, 141, 166, 51, 119, 214, 254}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 24, 81}, 148}, {{220, 128, 0, 0, 0, 0, 63, 177, 55, 7, 37, 191, 59, 224, 225, 80}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 164, 245, 174}, 148}, {{220, 128, 0, 0, 0, 0, 138, 202, 115, 246, 53, 41, 215, 140, 152, 201}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{220, 128, 0, 0, 116, 179, 146, 38, 58, 141, 152, 233, 50, 141, 54, 169}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 7, 198, 228, 179, 63, 220, 216}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 148}, {{220, 128, 0, 0, 0, 162, 207, 22, 190, 205, 6, 213, 180, 155, 157, 247}, 148}, {{220, 128, 0, 0, 0, 0, 0, 234, 184, 85, 118, 132, 243, 244, 79, 153}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 123, 246, 34, 85, 46, 80}, 148}, {{220, 128, 0, 239, 166, 99, 215, 158, 184, 17, 193, 153, 160, 78, 0, 65}, 148}, {{220, 128, 0, 0, 0, 198, 216, 100, 254, 98, 71, 83, 56, 186, 66, 28}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 150, 96, 216, 202, 73, 211, 110}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 87, 130}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 46, 38, 58, 128}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 189, 185, 27, 72, 229, 206, 198, 91}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 161, 35, 252, 91}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 126, 24}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 190}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 151, 162}, 148}, {{220, 128, 0, 0, 0, 192, 34, 229, 94, 233, 218, 89, 198, 192, 190, 29}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 33, 92, 224, 24, 141, 90, 153}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 47}, 148}, {{220, 128, 0, 0, 0, 0, 83, 255, 199, 236, 58, 127, 14, 72, 244, 6}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 184, 71, 163, 98, 243, 136, 187}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 216, 12, 245, 208, 181, 147}, 148}, {{220, 128, 0, 0, 0, 0, 0, 15, 247, 44, 16, 93, 128, 128, 247, 139}, 148}, {{220, 128, 0, 0, 0, 0, 0, 67, 105, 59, 76, 31, 90, 11, 71, 69}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 228, 244, 44, 110, 189, 122}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 33, 61, 76, 249}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 139, 168, 16, 161, 39, 89, 83}, 148}, {{220, 128, 0, 0, 0, 0, 73, 67, 177, 66, 105, 73, 203, 174, 129, 32}, 148}, {{220, 128, 0, 0, 0, 69, 34, 147, 150, 60, 65, 91, 137, 8, 135, 26}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 127}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 23, 36}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 116, 161, 42}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 145, 87, 10}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 68, 239}, 148}, {{220, 128, 0, 0, 0, 0, 252, 222, 72, 172, 58, 113, 142, 10, 140, 82}, 148}, {{220, 128, 0, 0, 0, 82, 165, 188, 90, 187, 19, 182, 220, 226, 83, 255}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 36, 84, 118, 145, 110, 177, 14, 212}, 148}, {{220, 128, 0, 33, 26, 48, 216, 58, 38, 155, 172, 141, 20, 16, 184, 0}, 148}, {{220, 128, 0, 0, 0, 0, 0, 7, 179, 137, 249, 1, 104, 4, 200, 248}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 201, 47, 65}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 182, 0, 254, 53, 7, 9}, 148}, {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 63, 95, 149, 5}, 148}, {{206, 87, 135, 235, 116, 128, 152, 71, 153, 196, 236, 95, 120, 215, 235, 36}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 221, 52, 48, 26, 252, 222}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 131, 38, 80}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 177, 35, 134, 79, 90}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 206, 132, 164, 124, 245, 32, 9}, 53}, {{206, 87, 135, 235, 116, 128, 0, 46, 248, 197, 50, 199, 138, 16, 238, 30}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 124, 89, 43, 148, 188}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 190, 89, 57, 43}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 49, 67, 121, 125, 120, 7}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 103, 37, 235, 153, 155, 36, 103, 75}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 230, 100, 59, 56, 60, 118, 132}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 236, 154}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 120, 20, 171}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 45, 234, 106, 15, 148, 157, 223, 185}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 173, 176, 74, 56, 204, 173, 147}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 164, 126, 189, 122}, 53}, {{206, 87, 135, 235, 116, 128, 0, 56, 11, 174, 53, 119, 65, 178, 11, 101}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 150, 101, 34, 190, 227, 81, 43, 148}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 143, 63, 194}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 190, 123, 255}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 140, 89, 139, 5, 17, 177, 224}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 206, 97, 178, 184, 37}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 230, 182, 209, 22}, 53}, {{206, 87, 135, 235, 116, 128, 243, 173, 83, 34, 83, 111, 162, 104, 69, 83}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 40, 70, 107, 117, 239}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 184, 30}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 118, 78, 177, 123, 223, 179, 123}, 53}, {{206, 87, 135, 235, 116, 128, 0, 34, 126, 135, 214, 240, 0, 54, 239, 233}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 189, 185, 195}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 245, 120, 171, 170, 74, 172, 244, 147}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 18, 221}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 127, 159, 48, 246, 186, 43, 106, 1}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 145, 96, 210, 112}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 200, 87, 82}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 67, 172, 94}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 221, 139, 122, 104, 112, 186, 58}, 53}, {{206, 87, 135, 235, 116, 128, 0, 82, 115, 204, 16, 147, 252, 148, 118, 204}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 115, 201, 169, 194, 171, 75, 15}, 53}, {{206, 87, 135, 235, 116, 128, 87, 130, 54, 189, 193, 61, 83, 72, 36, 45}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 62, 65}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 215, 143, 128, 155, 64, 157, 143}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 215, 54, 144}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 110, 113, 110, 69, 30, 255, 20, 175, 130}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 207, 66}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 82, 31, 50, 198}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 178, 27}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 48, 151, 30, 172, 4}, 53}, {{206, 87, 135, 235, 116, 128, 43, 147, 26, 148, 93, 91, 33, 205, 105, 235}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 53}, {{206, 87, 135, 235, 116, 128, 179, 246, 67, 249, 166, 203, 223, 175, 27, 25}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 83, 115, 170, 108, 58}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 33, 164, 83, 50}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 7, 89, 218, 105, 35, 244, 15, 165}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 58, 227, 160}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 111, 60}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 27, 242, 16, 246, 105, 42, 202, 28}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 102, 147, 101, 170, 158, 80}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 167, 100, 231, 15, 170, 84, 144, 13}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 142, 79, 84, 139, 95, 124}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 80, 98, 154, 69, 57}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 225, 194, 93, 141, 135, 195, 170}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 15, 104, 162, 39}, 53}, {{206, 87, 135, 235, 116, 128, 55, 163, 30, 55, 68, 220, 220, 252, 109, 74}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 79, 1, 198, 110, 115, 89, 220, 109}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 16, 168, 21, 153, 116}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 154, 49, 125, 44, 157, 58}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 229, 138, 214}, 53}, {{206, 87, 135, 235, 116, 128, 109, 149, 188, 245, 249, 198, 63, 42, 148, 8}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118}, 53}, {{206, 87, 135, 235, 116, 128, 0, 152, 138, 128, 18, 169, 171, 205, 60, 208}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 72, 66}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 208, 180, 67, 173, 204, 161}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 72, 46, 121}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 158, 147, 46, 25, 5, 147}, 53}, {{206, 87, 135, 235, 116, 128, 0, 18, 45, 55, 16, 140, 136, 143, 31, 202}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 107, 186, 90, 153}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 30, 100, 21, 22}, 53}, {{206, 87, 135, 235, 116, 128, 0, 199, 64, 141, 125, 122, 16, 234, 4, 116}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 236, 185}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53}, {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 194, 179, 12}, 53}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 164, 123, 188, 69, 226, 83, 100, 173, 131, 242, 31, 122, 11}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 65, 31, 64, 231, 25, 10, 0, 82}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 87}, {{152, 128, 0, 86, 139, 105, 72, 187, 158, 90, 105, 83, 148, 124, 96, 25}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 250, 91, 92, 199, 15, 202, 193, 57, 150, 203}, 87}, {{152, 128, 0, 0, 0, 0, 0, 108, 102, 138, 253, 66, 50, 40, 20, 202}, 87}, {{152, 128, 158, 216, 178, 211, 226, 138, 135, 75, 140, 118, 144, 90, 96, 135}, 87}, {{152, 128, 0, 0, 0, 0, 0, 117, 128, 180, 38, 249, 163, 117, 16, 23}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 90}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 115}, 87}, {{152, 128, 167, 57, 160, 234, 42, 41, 97, 51, 107, 228, 209, 50, 49, 175}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 13}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 177, 180, 208, 154, 206, 32, 254}, 87}, {{152, 128, 0, 0, 6, 234, 86, 81, 40, 170, 202, 23, 178, 166, 113, 218}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 87}, {{152, 128, 0, 0, 109, 241, 137, 64, 48, 2, 6, 67, 231, 3, 110, 131}, 87}, {{152, 128, 0, 151, 133, 175, 60, 70, 128, 180, 100, 83, 39, 102, 168, 239}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 171, 64}, 87}, {{152, 128, 0, 0, 0, 0, 11, 135, 137, 190, 157, 166, 65, 6, 91, 13}, 87}, {{152, 128, 0, 245, 86, 106, 11, 111, 124, 38, 111, 217, 52, 205, 206, 129}, 87}, {{152, 128, 0, 0, 170, 6, 171, 14, 161, 87, 194, 181, 120, 135, 205, 212}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 87}, {{152, 128, 77, 129, 8, 221, 204, 231, 60, 187, 49, 74, 113, 193, 70, 246}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180}, 87}, {{152, 128, 0, 0, 0, 0, 0, 3, 221, 238, 151, 41, 33, 190, 28, 84}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 74}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 35, 224, 216, 64, 25, 100}, 87}, {{152, 128, 0, 0, 0, 0, 0, 23, 156, 164, 61, 191, 172, 169, 233, 113}, 87}, {{152, 128, 0, 0, 0, 0, 0, 144, 42, 231, 173, 74, 210, 204, 95, 238}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 125, 103, 48}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 103, 198, 85, 60}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 50, 140, 66, 103, 137, 220, 215}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 43}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 183}, 87}, {{152, 128, 0, 0, 59, 190, 55, 148, 211, 31, 121, 128, 139, 134, 228, 120}, 87}, {{152, 128, 0, 0, 164, 73, 75, 174, 238, 255, 233, 178, 15, 71, 187, 190}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 70, 50}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 141, 31, 87, 40}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 225, 7, 196, 81, 51, 61, 52}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 244, 193, 62, 223}, 87}, {{152, 128, 0, 0, 0, 0, 0, 142, 65, 131, 17, 82, 210, 97, 137, 254}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 165, 127, 21, 38, 115, 196, 6}, 87}, {{152, 128, 0, 0, 0, 237, 136, 247, 219, 155, 170, 229, 18, 17, 185, 206}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 96, 113, 181, 218, 226, 187}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 7, 160}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 98}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 213, 58, 44, 168}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 100, 143}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 63}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 186, 212, 218}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 60, 194, 130, 91, 13, 100, 242}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 168, 225, 145, 63, 89, 41, 224, 37, 25, 0, 164, 81}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 20, 15, 163, 55, 4, 219}, 87}, {{152, 128, 0, 73, 147, 24, 175, 74, 64, 219, 75, 239, 51, 21, 202, 199}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 118, 155}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 124, 198, 21, 79, 82, 116, 135}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 80}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 109, 215, 28, 200, 45, 30}, 87}, {{152, 128, 0, 0, 0, 0, 0, 102, 27, 247, 49, 11, 161, 166, 105, 71}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 76}, 87}, {{152, 128, 0, 173, 124, 54, 108, 199, 126, 42, 141, 228, 40, 135, 165, 75}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 111, 148, 122, 51}, 87}, {{152, 128, 0, 0, 0, 210, 73, 94, 142, 29, 91, 219, 166, 102, 179, 135}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 236, 164, 23, 36, 19, 150, 22}, 87}, {{152, 128, 22, 90, 188, 86, 104, 89, 80, 4, 125, 253, 181, 69, 45, 217}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 10, 117, 197, 136}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 225, 122, 13, 169, 191, 165}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 154, 136, 179}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 43, 194, 222, 147}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 191}, 87}, {{152, 128, 0, 0, 55, 164, 115, 77, 1, 41, 54, 189, 2, 179, 11, 120}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 220}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 150}, 87}, {{152, 128, 0, 0, 0, 68, 139, 173, 135, 218, 169, 237, 1, 82, 118, 96}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 236, 20, 92, 23, 15, 249, 5}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 38, 82, 82}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 138, 111, 218}, 87}, {{152, 128, 0, 0, 136, 11, 107, 50, 58, 88, 70, 33, 149, 230, 193, 148}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 60, 93, 105, 147, 8, 170, 47, 126}, 87}, {{152, 128, 0, 0, 24, 146, 6, 53, 156, 111, 195, 5, 240, 29, 193, 213}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 176}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 113, 21, 229, 186, 93, 9, 27}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 141}, 87}, {{152, 128, 0, 3, 6, 69, 8, 214, 50, 31, 39, 229, 227, 90, 176, 128}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 127, 254, 132, 141, 24, 66, 72, 228}, 87}, {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 2, 17}, 87}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 66}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 8, 107, 113}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 119, 248, 255, 173}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 127, 233, 248}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 114, 12, 162, 81, 206, 252}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 42, 214, 154, 186}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 24, 72, 26}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 121, 216, 164, 139}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 146, 119, 11, 43, 100}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 137, 133}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 21, 232, 152, 48}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 223, 60, 235, 187, 84, 51}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 222, 215, 55}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 175, 103, 48, 33, 123}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 252, 148, 119, 255, 35, 126}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 216, 43, 229, 216, 20}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 165, 128, 222}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 234, 201, 148, 122, 166}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 101}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 88, 10, 223, 58}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 153, 255, 110}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 192}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 86}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 102, 109, 103, 31, 180}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 72, 14, 222, 104, 20, 241}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 191}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 83, 96, 27}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 8, 169}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 45, 18, 88, 89, 104, 224}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 109, 185, 61}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 220, 185, 255, 41, 178}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 54, 68}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 113, 251, 23, 48, 116, 139}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 59, 130}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 93, 80, 249}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 61, 64, 238, 38, 230}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 68, 136}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 161}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 71}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 231, 181, 180, 159}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 143, 250, 10}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 201, 48}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 161, 100}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 11, 241, 51, 201, 136, 122}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 158, 108, 161, 44, 17}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 160, 222, 236, 123}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 146, 118, 4, 105, 43, 89}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 151, 218}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 110, 77, 239, 37}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 108, 75, 229}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 243, 235, 150}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 242, 152}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 95, 205, 173, 2}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 234, 55, 63, 79}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 112, 169, 23, 162}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 151, 67, 6, 130, 190}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 173, 27, 172}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 180}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 43, 85}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 85, 222}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 63, 211}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 165, 35, 163, 252}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 169}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 115}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 137, 249, 75, 220}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 170, 39, 41, 138}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 250}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 239, 65, 193, 4, 79, 27}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 139}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 197, 177, 150, 18, 58}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 132}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 52}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 53, 215}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 145, 120, 204, 33, 20}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 225, 117, 62, 129, 57}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 150, 156, 40, 253}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 192, 19, 3, 187, 150}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 65, 208, 23, 70, 159, 6}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 234, 194, 66, 43}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 45, 30, 64, 26}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 237, 249, 53}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 236}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 126, 118}, 235}, {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 62, 46}, 235}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 150, 184, 213, 167, 0, 10, 18}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 42, 31, 255, 119, 39, 40, 42}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 78, 217}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 1}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 217, 250, 21, 241, 22, 74, 137, 232}, 51}, {{84, 220, 82, 0, 116, 100, 106, 101, 193, 1, 156, 227, 137, 163, 222, 199}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 153, 141, 51, 167, 54, 251, 217}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 254}, 51}, {{84, 220, 82, 0, 0, 0, 0, 196, 81, 173, 24, 94, 144, 40, 60, 62}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 213, 81, 75, 32, 62, 68}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, 171, 108}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 151}, 51}, {{84, 220, 82, 0, 221, 237, 36, 159, 164, 140, 38, 157, 112, 135, 187, 127}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 89, 221, 30}, 51}, {{84, 220, 82, 0, 0, 49, 89, 163, 149, 162, 25, 24, 182, 28, 120, 124}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 196, 229, 142}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 241, 87, 58}, 51}, {{84, 220, 82, 0, 0, 0, 53, 123, 61, 20, 100, 45, 140, 83, 18, 71}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 197, 88, 11, 133, 114}, 51}, {{84, 220, 82, 0, 0, 99, 134, 248, 42, 176, 105, 203, 41, 188, 27, 110}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 218, 82}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 50, 86}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 26, 143, 155, 131, 62, 16}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 159, 173, 208, 41, 140, 58, 248, 36}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 87, 146, 253, 221, 119, 21}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 41, 127}, 51}, {{84, 220, 82, 0, 0, 0, 162, 142, 142, 26, 125, 75, 128, 135, 73, 167}, 51}, {{84, 220, 82, 0, 0, 146, 9, 107, 203, 98, 212, 219, 176, 64, 207, 105}, 51}, {{84, 220, 82, 0, 127, 1, 76, 197, 220, 150, 95, 80, 54, 241, 80, 80}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 232, 26, 175, 39, 110, 0, 153}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 242, 217, 95, 189, 243, 133, 91}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 191, 91, 50, 155, 10, 115, 250}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 140, 111}, 51}, {{84, 220, 82, 0, 248, 159, 25, 178, 163, 187, 16, 226, 220, 188, 7, 226}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 178, 116, 246, 117, 150}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 143, 88, 16, 227, 33}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 161, 63, 93, 80, 116, 44, 109, 109}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 232, 160, 22, 255, 168, 45}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 173, 187, 106}, 51}, {{84, 220, 82, 0, 0, 0, 3, 221, 242, 61, 176, 23, 129, 5, 92, 1}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 136, 104, 52, 213, 20, 66, 84}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 200, 210, 207, 65, 232, 10, 5, 10}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 174, 29, 102}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 9}, 51}, {{84, 220, 82, 0, 0, 0, 222, 250, 102, 220, 165, 51, 124, 28, 70, 97}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 247, 14, 124, 41, 155}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 247}, 51}, {{84, 220, 82, 0, 0, 0, 0, 125, 68, 27, 216, 173, 210, 184, 204, 190}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 66, 65, 202, 160, 227, 71, 8}, 51}, {{84, 220, 82, 0, 0, 0, 0, 31, 223, 16, 224, 125, 167, 239, 190, 53}, 51}, {{84, 220, 82, 0, 0, 173, 122, 181, 66, 180, 115, 125, 79, 172, 183, 26}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 79, 119}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 95, 91, 88}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 210, 158, 179}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 179, 74, 171, 120, 40, 155}, 51}, {{84, 220, 82, 145, 35, 247, 57, 71, 148, 185, 63, 1, 95, 106, 92, 13}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 60, 209, 61}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 71}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 8, 38, 182}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 46, 227, 241, 157, 173}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 115}, 51}, {{84, 220, 82, 0, 192, 36, 175, 14, 101, 43, 230, 210, 138, 213, 70, 98}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 15, 34, 233}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 51}, {{84, 220, 82, 0, 0, 0, 229, 81, 85, 6, 202, 87, 150, 66, 221, 115}, 51}, {{84, 220, 82, 0, 0, 174, 177, 46, 149, 98, 94, 66, 176, 171, 214, 7}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 58}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 168, 227, 151}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 51}, {{84, 220, 82, 0, 0, 52, 74, 203, 2, 124, 191, 87, 234, 77, 186, 214}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 107}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 136, 243, 151}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 109, 149, 130}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 214, 48}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 22, 143}, 51}, {{84, 220, 82, 0, 0, 90, 79, 19, 76, 92, 252, 53, 147, 122, 173, 112}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 155, 80, 129, 31, 15, 108, 130, 52}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 118, 95, 128}, 51}, {{84, 220, 82, 0, 62, 253, 191, 84, 98, 171, 29, 143, 7, 240, 148, 91}, 51}, {{84, 220, 82, 0, 0, 0, 0, 179, 221, 41, 99, 242, 40, 168, 213, 239}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 196, 47, 230, 133, 148, 164, 63, 146}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219}, 51}, {{84, 220, 82, 0, 86, 55, 236, 67, 64, 2, 158, 228, 209, 233, 183, 199}, 51}, {{84, 220, 82, 0, 0, 5, 181, 255, 5, 26, 19, 186, 184, 201, 4, 34}, 51}, {{84, 220, 82, 0, 0, 0, 0, 85, 109, 188, 19, 81, 119, 233, 93, 4}, 51}, {{84, 220, 82, 0, 113, 70, 169, 33, 192, 90, 87, 43, 66, 154, 61, 84}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 67, 143, 107, 194, 53, 137}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 163, 4}, 51}, {{84, 220, 82, 0, 0, 0, 0, 0, 205, 235, 104, 253, 233, 242, 64, 199}, 51}, {{84, 220, 82, 0, 0, 0, 116, 41, 89, 137, 65, 77, 100, 54, 197, 118}, 51}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 135}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 78}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 116}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 74}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 125}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 114}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 254}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 231}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 23}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 251}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 240}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 236}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 163}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 51}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 9}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 174}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 67}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 99}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 165}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 190}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 134}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 178}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 75}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 171}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 206}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 146}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 181}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 74}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 116}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 158}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 34}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 11}, {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 48}, 11}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 216}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 63, 19, 240, 34}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 191, 55, 130, 140, 77, 98}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 143, 247, 182, 37}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 190, 69, 251, 115, 93}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 138, 40}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 207, 86}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 246, 253, 44, 113}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 12, 100, 205, 149}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 221, 87, 70, 185, 179, 101}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 103, 118}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 202, 123, 151}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 239, 137, 186, 249, 44, 40}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 245, 27, 50}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 36, 163, 104}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 184, 170, 190, 133}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 160, 211, 52, 17, 142}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 115, 52, 171, 239, 252, 192}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 228, 187, 73, 46, 204, 122}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 221, 161}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 186, 48, 137, 24, 143}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 208, 246, 153, 62, 131, 73}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 244, 86, 149}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 92}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 254, 215, 108, 177, 219}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 9}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 138}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 224}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 146, 200}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 170, 36, 206, 132}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 239}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 38, 118, 133, 157}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 177, 1}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 177, 84, 228, 92, 113}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 47, 209, 150, 196, 8, 20}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 101, 158, 119, 165}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 161, 88, 51, 152}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 32}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 129, 45, 2, 138, 228, 35}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 40, 103, 131, 95, 183}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 188, 230, 20, 183, 182, 173}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 230, 91, 131, 8}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 152, 188, 4, 205, 215, 219}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 215, 1}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 41, 147, 150, 255}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 116, 15}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 59, 179}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 180, 61, 199, 248}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 110, 228, 172, 175, 61}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 33, 220, 198}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 10, 146, 63, 240, 10, 185}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 102, 131, 218, 132, 69, 29, 120}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 218, 72, 116, 144}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 171, 92, 31}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 163, 68, 174, 16}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 56, 228, 249}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 237, 247, 151}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 153, 23, 79, 251, 135, 169, 144}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 218, 239, 59, 162, 217, 183}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 232, 212, 242, 195, 137, 219}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 47}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 64, 195, 107, 147, 184}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 119}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 94, 18, 54}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 1, 165, 208, 236, 65}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 112}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 149, 242, 20, 241}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 97, 174, 212, 197, 30}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 181}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 52, 119, 36, 129, 61, 228}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 224, 211, 102, 16}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 137, 50, 227, 78, 163}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 223, 250, 224, 37, 158}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 235}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 18, 63, 66, 74, 210}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 252}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 98, 83, 199, 141, 75}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 151, 43, 29, 17}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 73, 68, 249, 18}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 73, 118, 84, 133, 95, 30}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 49}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 237, 236}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 37, 228, 245}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 160, 36, 28, 135}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 8}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 85, 146, 240, 219, 19, 184, 115}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 197, 92}, 28}, {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 132}, 28}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 69}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 177, 238}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 86, 121}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 38, 49, 115}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 168, 12}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 13, 226}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 15}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 79}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 43, 41}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 154}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 39, 130, 47}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 97}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 126, 145}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 186, 235, 74}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 220, 109, 54}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 160, 40, 144}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 97, 74}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 4}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 154, 146, 74}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 137, 36}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 28, 14}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 241}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 186, 177, 236}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 138, 241}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 89}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 199}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 126, 72}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 222, 110, 150}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 159, 185}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 85}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 174}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 189, 210, 226}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 227, 212, 209}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 123}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 60, 96, 203}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 58}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 153}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 50, 37}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 235}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 162, 118, 53}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 244, 81, 39}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 9, 184, 219}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 163, 163}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 180, 34, 118}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 202, 77}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 105}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 186}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 83, 56, 136}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 152}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 31, 171}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 53}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 173}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 180, 20, 67}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 35, 125}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 39}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 34}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 7}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 44}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 201}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 244, 176, 248}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 187, 72, 34}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 133}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 60, 126, 174}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 20}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 134}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 96, 205}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 154, 227, 101}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 36, 17, 10}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 215, 197, 119}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 169, 66, 133}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 163, 153}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 248}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 167, 238, 132}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 45, 236, 61}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 179, 118, 255}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 135, 113, 114}, 73}, {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 189}, 73}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 99, 237, 199, 80}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 52, 18, 173, 206, 80, 214, 248, 201}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 176, 74, 219, 254, 68, 39, 40}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 48, 193, 126, 60, 121}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 109, 183}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 47, 154, 195, 122}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 159, 86, 251, 35, 118, 213}, 216}, {{234, 197, 12, 160, 0, 0, 229, 217, 156, 230, 125, 38, 229, 72, 234, 154}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 134, 61, 155, 107, 183, 121}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 78, 155}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 245, 168, 136, 141, 33, 151, 32}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 70}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 32, 19, 230, 199, 181, 200, 40, 51}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 4, 66, 78, 8, 61, 243, 24}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 27}, 216}, {{234, 197, 12, 160, 0, 0, 56, 98, 227, 126, 92, 219, 99, 28, 178, 234}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 216}, {{234, 197, 12, 160, 0, 0, 175, 155, 183, 4, 243, 37, 140, 193, 26, 6}, 216}, {{234, 197, 12, 160, 151, 182, 119, 205, 26, 63, 100, 72, 56, 218, 227, 185}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 48, 215, 187, 81, 1, 26}, 216}, {{234, 197, 12, 160, 165, 181, 25, 55, 30, 46, 104, 15, 154, 207, 216, 231}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 43, 250, 16, 81, 101}, 216}, {{234, 197, 12, 160, 0, 0, 0, 217, 220, 9, 140, 118, 169, 226, 179, 2}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 32, 36, 120, 221, 9, 105, 209}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 171}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 200, 106, 166, 126, 42, 204}, 216}, {{234, 197, 12, 160, 0, 0, 56, 240, 77, 190, 11, 29, 65, 246, 29, 160}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 124, 162}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 213, 235, 125, 67, 66, 41}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 38, 11, 114, 129, 204, 176, 163, 59}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 44, 38}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 155, 70, 128, 29, 100, 48, 118, 126, 6}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 31, 187}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 66, 218, 176, 38, 157, 194, 210}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 224, 20, 92, 14, 87, 112, 74}, 216}, {{234, 197, 12, 160, 0, 0, 0, 60, 123, 36, 155, 199, 81, 40, 208, 133}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 82, 166, 208, 160, 71, 99, 149, 191}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 164, 205, 172, 37, 16, 237}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 170, 155, 141, 244, 242, 119, 177}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 46, 36, 129, 243, 52, 123, 42, 214}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 16, 120, 150, 161, 172, 42, 44}, 216}, {{234, 197, 12, 160, 0, 0, 166, 125, 80, 130, 4, 50, 183, 216, 92, 26}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 169, 95}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 161, 36}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 92, 151, 65, 200, 155, 138}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 91, 117, 78, 15}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 229, 25}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 231, 9, 255, 232, 219}, 216}, {{234, 197, 12, 160, 0, 0, 7, 186, 2, 166, 107, 132, 37, 247, 35, 80}, 216}, {{234, 197, 12, 160, 0, 32, 21, 161, 147, 16, 221, 136, 104, 84, 2, 61}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 57, 116, 55, 33, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 200, 214, 157, 235, 218, 195, 15, 132}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 137, 188, 10, 141, 199, 182}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 52}, 216}, {{234, 197, 12, 160, 0, 0, 114, 99, 90, 233, 187, 6, 254, 134, 150, 166}, 216}, {{234, 197, 12, 160, 81, 172, 88, 211, 141, 112, 102, 242, 131, 174, 147, 183}, 216}, {{234, 197, 12, 160, 0, 0, 65, 226, 62, 155, 16, 254, 149, 234, 57, 55}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 86, 143, 46, 145}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 201, 133, 23, 187, 11, 185, 36}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 180, 229, 62, 184, 154}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 120, 219, 205, 240, 9, 239, 42}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 46, 233, 74, 237, 148, 80, 219, 12}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 177, 159, 70, 68, 118, 211}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 95, 51, 9, 2, 91, 24, 145}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 124, 241, 238, 212, 197, 250, 154, 233}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 110, 134, 43, 200, 223}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 229, 48, 152, 84}, 216}, {{234, 197, 12, 160, 0, 215, 237, 142, 138, 172, 110, 145, 125, 255, 171, 204}, 216}, {{234, 197, 12, 160, 0, 214, 48, 77, 60, 44, 217, 225, 152, 247, 192, 192}, 216}, {{234, 197, 12, 160, 110, 3, 229, 94, 237, 175, 113, 60, 182, 68, 156, 168}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 116, 199, 76, 176, 130, 170, 230, 96}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 91}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 235, 63}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 91, 199, 146, 154}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 187, 49, 123, 59, 234}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 182, 23, 91, 91, 136}, 216}, {{234, 197, 12, 160, 0, 46, 34, 63, 209, 116, 142, 140, 177, 15, 190, 144}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 131, 87, 173, 145, 188, 126, 65}, 216}, {{234, 197, 12, 160, 0, 0, 245, 54, 46, 139, 159, 17, 165, 112, 213, 30}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 69, 31, 75, 31, 90, 131, 251}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 91, 46, 79, 103, 19, 58, 60, 26}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 249, 118, 93, 167}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 253, 161}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 127}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 180, 28, 29, 198, 213}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 209, 238, 95, 26, 215}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 151, 75, 252, 24, 173, 80, 106, 57}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 189, 156, 241, 226}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 83, 91, 40, 251, 52, 124}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 216}, {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 216}, {{234, 197, 12, 160, 0, 40, 12, 217, 144, 194, 192, 74, 28, 2, 66, 103}, 216}, {{191, 94, 0, 0, 0, 0, 0, 207, 71, 28, 201, 114, 223, 124, 245, 4}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 205, 99, 159, 117, 172, 48, 113}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 99}, {{191, 94, 0, 177, 35, 22, 27, 191, 247, 153, 130, 138, 249, 30, 69, 22}, 99}, {{191, 94, 0, 3, 51, 166, 25, 139, 194, 231, 193, 101, 152, 208, 125, 197}, 99}, {{191, 94, 0, 0, 49, 22, 66, 146, 64, 239, 107, 154, 9, 127, 22, 218}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 71}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 43, 133, 225, 25, 120, 61, 247}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 75}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 149, 117}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 21, 169, 17, 213, 194, 149, 194}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 165, 195}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 134, 90, 243, 20, 82, 222}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 34, 30, 201}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 184, 123, 252, 177}, 99}, {{191, 94, 0, 0, 0, 0, 252, 37, 124, 80, 9, 52, 47, 17, 214, 78}, 99}, {{191, 94, 0, 0, 0, 0, 0, 174, 61, 129, 252, 39, 8, 228, 91, 72}, 99}, {{191, 94, 0, 74, 34, 243, 162, 22, 238, 28, 131, 46, 196, 96, 209, 121}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 141, 89, 87, 39}, 99}, {{191, 94, 0, 0, 246, 158, 218, 227, 230, 188, 135, 162, 61, 143, 113, 33}, 99}, {{191, 94, 0, 0, 0, 75, 85, 106, 36, 178, 169, 140, 175, 172, 93, 7}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 3}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 50, 145, 90, 112, 188, 212, 241, 100}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 202, 148, 249, 34, 125, 189, 183}, 99}, {{191, 94, 0, 0, 0, 212, 105, 46, 98, 159, 103, 140, 170, 28, 62, 10}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 245, 97, 83, 74}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 139, 187}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 75, 142, 1, 143}, 99}, {{191, 94, 0, 0, 0, 0, 152, 156, 1, 2, 110, 71, 62, 199, 221, 224}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 172, 124, 178, 84}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 96, 160, 165, 187, 70, 66}, 99}, {{191, 94, 0, 0, 184, 184, 19, 72, 213, 250, 110, 1, 110, 9, 152, 247}, 99}, {{191, 94, 0, 185, 28, 229, 19, 222, 185, 91, 224, 128, 152, 147, 24, 207}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 241, 200, 74, 45}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 183}, 99}, {{191, 94, 0, 0, 0, 243, 30, 91, 108, 141, 13, 177, 251, 80, 233, 28}, 99}, {{191, 94, 0, 0, 0, 35, 205, 136, 52, 249, 31, 227, 222, 102, 237, 143}, 99}, {{191, 94, 0, 0, 254, 248, 244, 40, 72, 3, 199, 250, 85, 34, 37, 48}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 89, 45, 236, 203, 255, 24, 38, 65}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 99}, {{191, 94, 0, 0, 0, 0, 0, 145, 57, 57, 148, 184, 64, 8, 132, 101}, 99}, {{191, 94, 0, 0, 212, 153, 132, 189, 208, 11, 128, 17, 213, 140, 209, 127}, 99}, {{191, 94, 0, 0, 0, 18, 73, 190, 135, 61, 233, 99, 0, 95, 179, 11}, 99}, {{191, 94, 0, 0, 0, 0, 34, 108, 14, 200, 200, 210, 195, 152, 29, 51}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 93, 45, 132}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 252, 43, 185, 13, 122, 41}, 99}, {{191, 94, 0, 121, 93, 185, 25, 35, 156, 224, 29, 63, 108, 246, 218, 144}, 99}, {{191, 94, 0, 0, 0, 176, 243, 121, 109, 246, 120, 158, 186, 49, 163, 74}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 130}, 99}, {{191, 94, 0, 0, 0, 89, 175, 23, 216, 153, 21, 216, 78, 211, 187, 240}, 99}, {{191, 94, 0, 0, 0, 120, 124, 235, 79, 50, 200, 209, 96, 200, 60, 33}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 241, 183, 107, 183, 31, 41}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 26, 157}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 82, 204, 222}, 99}, {{191, 94, 0, 180, 154, 226, 201, 55, 157, 21, 51, 185, 239, 253, 64, 186}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 178, 247, 169, 252, 99, 240, 187}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 10, 241, 60, 58, 160, 208, 123, 226}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 244, 172, 132, 14, 76, 135}, 99}, {{191, 94, 0, 0, 0, 43, 180, 59, 52, 157, 133, 105, 191, 22, 170, 240}, 99}, {{191, 94, 0, 0, 203, 82, 98, 60, 236, 61, 128, 167, 230, 71, 213, 113}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 250}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 110, 240, 2}, 99}, {{191, 94, 0, 0, 0, 252, 85, 188, 2, 109, 105, 100, 96, 180, 75, 117}, 99}, {{191, 94, 0, 124, 195, 4, 75, 132, 53, 68, 23, 228, 105, 193, 228, 111}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 152, 195, 1, 173, 36, 146, 21}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 189, 209, 252, 140, 46, 181, 242, 127}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 46, 130, 44, 71, 27, 240}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 30, 180, 106, 67}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 118, 164, 21}, 99}, {{191, 94, 0, 0, 168, 37, 34, 114, 139, 71, 96, 102, 187, 199, 27, 190}, 99}, {{191, 94, 0, 165, 182, 39, 6, 87, 112, 5, 119, 192, 24, 20, 65, 42}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 52, 205, 2, 166, 102, 86, 79}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 184, 249, 90}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 81, 37, 219, 191, 95, 165}, 99}, {{191, 94, 0, 0, 0, 0, 0, 88, 227, 122, 2, 54, 226, 146, 237, 137}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 99}, {{191, 94, 0, 236, 60, 60, 209, 86, 249, 137, 142, 101, 169, 79, 61, 121}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 99}, {{191, 94, 0, 176, 72, 13, 12, 216, 91, 100, 83, 234, 243, 194, 41, 140}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 241, 208, 230, 188}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152}, 99}, {{191, 94, 0, 0, 0, 0, 67, 199, 214, 194, 21, 255, 201, 50, 206, 237}, 99}, {{191, 94, 0, 170, 58, 150, 150, 205, 143, 139, 83, 188, 26, 99, 125, 205}, 99}, {{191, 94, 0, 250, 119, 60, 97, 187, 61, 106, 230, 14, 91, 178, 77, 128}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 166, 224, 0, 142, 153, 252, 164, 50}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 20, 104}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 49, 24}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 36, 143, 169, 19, 64, 250, 109, 87}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221}, 99}, {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 38}, 99}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 232, 240, 238, 90, 160, 105}, 35}, {{200, 8, 0, 0, 230, 47, 77, 202, 229, 132, 57, 128, 8, 220, 118, 252}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 5, 16, 253, 219}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 154, 232, 217, 37, 248, 25}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 80, 96, 88, 92, 152, 126, 36}, 35}, {{200, 8, 0, 0, 0, 150, 162, 146, 39, 120, 67, 18, 229, 71, 34, 72}, 35}, {{200, 8, 0, 243, 147, 215, 191, 156, 128, 86, 132, 82, 11, 186, 52, 172}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 158, 87, 46, 39, 136, 91}, 35}, {{200, 8, 0, 56, 209, 242, 220, 57, 239, 19, 9, 10, 199, 56, 124, 21}, 35}, {{200, 8, 0, 0, 0, 0, 91, 138, 140, 80, 128, 100, 189, 74, 15, 229}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 140, 124}, 35}, {{200, 8, 0, 0, 72, 233, 64, 21, 210, 116, 18, 4, 232, 212, 95, 31}, 35}, {{200, 8, 0, 0, 0, 0, 181, 235, 4, 164, 2, 237, 169, 19, 52, 106}, 35}, {{200, 8, 0, 0, 0, 184, 234, 233, 224, 246, 137, 10, 138, 180, 254, 198}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 214}, 35}, {{200, 8, 0, 0, 60, 180, 58, 255, 210, 64, 155, 216, 82, 242, 157, 134}, 35}, {{200, 8, 0, 0, 0, 0, 159, 197, 159, 190, 244, 212, 250, 53, 251, 225}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 18, 30, 240, 11, 94, 8, 143}, 35}, {{200, 8, 0, 0, 0, 212, 20, 128, 251, 78, 38, 11, 58, 80, 187, 21}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 8}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 164, 28, 107}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 99, 11, 209, 58, 95, 35}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 79, 48, 111, 67, 110, 193}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{200, 8, 0, 0, 144, 105, 128, 119, 192, 100, 246, 226, 142, 15, 159, 166}, 35}, {{200, 8, 0, 0, 0, 0, 0, 21, 34, 127, 254, 88, 54, 125, 244, 241}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192}, 35}, {{200, 8, 0, 146, 42, 183, 180, 207, 45, 15, 16, 196, 91, 134, 199, 227}, 35}, {{200, 8, 0, 0, 0, 55, 228, 244, 226, 232, 205, 222, 167, 99, 75, 198}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{200, 8, 0, 0, 0, 0, 0, 147, 195, 171, 125, 190, 167, 255, 97, 101}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 1, 130, 146, 213, 3, 42, 23}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 175, 215, 35, 206, 49, 255, 94, 97}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 16, 225, 185, 18}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 41}, 35}, {{200, 8, 0, 0, 0, 0, 0, 10, 31, 177, 196, 160, 112, 160, 1, 219}, 35}, {{200, 8, 0, 229, 108, 236, 152, 179, 142, 171, 81, 75, 48, 5, 207, 73}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 228, 217, 244, 37, 103, 11, 242, 32}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 146}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 254, 115}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 249, 93, 78, 236, 31, 6}, 35}, {{200, 8, 0, 0, 0, 0, 0, 180, 109, 56, 92, 229, 99, 50, 247, 222}, 35}, {{200, 8, 0, 0, 154, 218, 186, 186, 129, 112, 88, 19, 168, 244, 117, 43}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 140}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 171, 196, 153, 7, 253, 44, 87, 152}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 185, 209, 218, 68, 87, 127, 145}, 35}, {{200, 8, 0, 0, 150, 183, 34, 187, 31, 53, 189, 94, 27, 70, 12, 28}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 21, 17, 60}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 38, 13, 30, 216, 25, 221}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 24, 125, 55, 195, 27, 176, 36, 247}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 35}, {{200, 8, 0, 0, 0, 0, 0, 146, 109, 130, 242, 231, 165, 209, 93, 75}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 93, 82, 243}, 35}, {{200, 8, 0, 0, 123, 144, 107, 104, 246, 180, 220, 224, 119, 41, 163, 26}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 208, 201}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{200, 8, 0, 0, 0, 37, 144, 67, 227, 7, 124, 249, 65, 75, 61, 56}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 255, 226}, 35}, {{200, 8, 0, 0, 0, 133, 168, 207, 104, 57, 146, 93, 161, 235, 96, 101}, 35}, {{200, 8, 0, 231, 150, 231, 177, 211, 190, 195, 178, 206, 249, 142, 219, 203}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 222, 78, 8, 8, 1, 169, 90, 101}, 35}, {{200, 8, 0, 0, 169, 184, 156, 220, 248, 82, 41, 215, 233, 186, 133, 154}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 47, 16, 25, 125}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 69}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 111, 152}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 196, 14}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 53}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 89, 221, 225, 254}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 220, 22, 53, 76, 66, 167}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 157, 4, 96, 94, 142, 166, 62}, 35}, {{200, 8, 0, 0, 0, 0, 72, 168, 8, 135, 58, 181, 167, 72, 17, 40}, 35}, {{200, 8, 0, 0, 0, 75, 11, 206, 217, 162, 113, 166, 2, 5, 18, 130}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244}, 35}, {{200, 8, 0, 0, 0, 0, 58, 237, 151, 14, 41, 239, 107, 86, 42, 91}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 148, 231, 104, 240}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 28, 174}, 35}, {{200, 8, 0, 0, 185, 139, 50, 33, 15, 140, 13, 245, 214, 127, 23, 89}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 192, 162, 184, 74, 126, 66, 89}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 208, 93, 20, 78, 210, 115, 82, 177}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 80, 55}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 67, 89, 217}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 220, 195}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, 31}, 35}, {{200, 8, 0, 0, 0, 0, 0, 248, 53, 66, 252, 227, 62, 3, 254, 96}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 102, 19, 177, 189, 178, 141, 146, 63}, 35}, {{200, 8, 0, 0, 0, 0, 46, 249, 205, 235, 237, 60, 165, 224, 61, 119}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 15}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 112, 246, 196, 141, 9, 86, 116, 235}, 35}, {{200, 8, 0, 0, 0, 0, 0, 4, 21, 24, 107, 237, 254, 114, 90, 142}, 35}, {{200, 8, 0, 0, 0, 25, 169, 4, 121, 65, 165, 245, 168, 23, 124, 131}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 53, 89, 155, 236, 133, 241}, 35}, {{200, 8, 0, 0, 0, 0, 182, 10, 57, 199, 196, 194, 54, 173, 225, 113}, 35}, {{200, 8, 0, 0, 0, 0, 13, 218, 226, 219, 201, 34, 14, 167, 10, 132}, 35}, {{200, 8, 0, 0, 0, 0, 0, 73, 33, 172, 95, 113, 242, 215, 95, 235}, 35}, {{200, 8, 0, 0, 0, 0, 0, 0, 0, 34, 234, 33, 235, 105, 77, 79}, 35}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 195}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 201}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 34}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 9}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 231}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 138}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 229}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 254}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 234}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 43, 115}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 50, 242}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 34, 97}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 250}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 235, 60}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 189}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 198}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 217, 163}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 150, 16}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 77, 93}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 103}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 97}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 34}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 199, 30}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 25}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 96, 184}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 168}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 98}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 90, 232}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 197, 67}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 78}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 3}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 218}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 117}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 44, 195}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 25}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 100}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 75, 65}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 247}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 235}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 78, 4}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 234}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 122, 251}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 174}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 5}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 97, 59}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 202}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 203, 22}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 161}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 40}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 4}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 157}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 224}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 176}, {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 254}, 176}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 99, 33}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 174}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 132, 154}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 196, 106, 104}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 16, 239, 232}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 158, 37, 154, 82}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 63, 174}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 92, 24}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 103, 64, 124}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 188, 103, 137, 227, 250}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 246, 176, 42, 24}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 188}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 228, 122, 65, 196}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 156, 132, 197, 71}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 205, 196}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 212, 153, 230}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 173}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 25}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 93, 239, 140, 198}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 161, 252, 106}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 193, 164, 254}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 137, 242, 45}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 29, 89}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 170}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 225}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 45, 142, 32}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 167, 40, 247, 12}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 115, 223, 50, 159}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 237, 78, 101}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 28, 37, 213}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 199, 173, 206}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 14, 135, 141, 103}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 30, 78, 10, 28}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 36, 184, 20, 124}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 102, 24, 155, 34}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 68}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 67, 43, 239}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 231, 102, 152}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 145, 136, 85}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 51}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 24}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 10}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 51, 114, 94}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 135}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 145, 160}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 81, 147, 102}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 14, 31, 57, 199, 169}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 55}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 215, 224}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 242, 5}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 168, 29}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 198, 186, 32}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 224}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 225}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 37, 98, 45}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 130}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 61}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 20, 162, 38, 166}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 185}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 222}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 101}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 25, 93, 127}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 251, 48, 61, 78}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 77, 30, 79}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 162, 84, 11}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 171}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 173, 246, 232, 230}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 112, 4, 225, 20}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 2, 162, 45}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 70}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 214, 175, 49, 169}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 208, 163}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 109}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 184}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 97}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 163, 238, 172}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 141, 202, 173, 145}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 232, 101}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 226}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 234, 40}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 158, 250}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 205}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 125}, 217}, {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 217}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 244}, {{160, 0, 0, 0, 0, 156, 206, 34, 63, 20, 13, 218, 149, 242, 247, 167}, 208}, {{160, 0, 0, 0, 190, 76, 21, 102, 16, 26, 219, 213, 24, 133, 252, 207}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 251, 188, 197, 215, 32, 2, 151, 117}, 208}, {{160, 0, 0, 0, 0, 203, 222, 142, 65, 120, 186, 58, 205, 205, 50, 159}, 208}, {{160, 0, 215, 182, 176, 190, 251, 128, 197, 153, 162, 47, 221, 237, 68, 46}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 193, 228, 66, 206}, 208}, {{160, 0, 0, 0, 0, 0, 118, 57, 156, 198, 17, 36, 217, 119, 104, 77}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 37, 130, 16}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 184, 129, 71}, 208}, {{160, 0, 0, 0, 0, 0, 0, 61, 53, 210, 146, 105, 7, 197, 175, 199}, 208}, {{160, 0, 0, 0, 114, 88, 206, 148, 226, 2, 54, 186, 151, 184, 97, 86}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 123, 22, 132, 88, 136, 212, 93, 149}, 208}, {{160, 233, 151, 72, 179, 155, 77, 37, 240, 133, 86, 205, 210, 106, 91, 100}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 25, 4}, 208}, {{160, 0, 0, 0, 0, 112, 152, 214, 157, 67, 197, 111, 56, 220, 94, 75}, 208}, {{160, 0, 0, 0, 0, 0, 0, 156, 152, 194, 88, 162, 155, 230, 21, 45}, 208}, {{160, 0, 206, 228, 127, 0, 204, 97, 17, 32, 23, 149, 181, 35, 230, 206}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 202, 60, 120, 56, 254, 48, 67}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 235, 136, 93}, 208}, {{160, 0, 0, 0, 0, 122, 110, 10, 183, 26, 224, 72, 71, 224, 161, 50}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 205, 29, 13, 235, 68, 26, 80}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 115, 4, 68, 224, 92, 119, 78}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 190, 207, 224}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 34, 156}, 208}, {{160, 0, 0, 184, 234, 202, 82, 252, 211, 250, 247, 14, 191, 218, 1, 149}, 208}, {{160, 120, 179, 20, 180, 220, 104, 135, 109, 117, 36, 12, 137, 149, 160, 41}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 44, 69, 84, 109, 19, 120, 30, 147}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 62}, 208}, {{160, 0, 23, 190, 24, 165, 204, 194, 238, 78, 128, 35, 177, 161, 151, 149}, 208}, {{160, 0, 166, 7, 205, 106, 198, 159, 215, 215, 190, 197, 198, 7, 187, 174}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 103, 165}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 179, 76}, 208}, {{160, 0, 51, 115, 164, 178, 163, 91, 118, 88, 54, 124, 30, 59, 127, 136}, 208}, {{160, 0, 0, 0, 161, 125, 182, 203, 186, 85, 63, 62, 74, 84, 202, 36}, 208}, {{160, 0, 0, 0, 0, 0, 224, 8, 193, 233, 220, 83, 222, 96, 216, 186}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 89, 9, 204}, 208}, {{160, 0, 95, 52, 225, 1, 129, 106, 163, 161, 165, 229, 147, 66, 69, 51}, 208}, {{160, 0, 0, 0, 0, 0, 0, 114, 157, 17, 26, 82, 248, 166, 46, 92}, 208}, {{160, 0, 0, 0, 0, 0, 81, 103, 136, 184, 167, 195, 19, 52, 154, 142}, 208}, {{160, 0, 0, 0, 0, 0, 0, 12, 224, 72, 160, 73, 21, 126, 196, 113}, 208}, {{160, 0, 117, 59, 34, 128, 58, 144, 161, 50, 22, 224, 199, 17, 13, 92}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 19, 156, 173, 251, 74, 56, 121, 176}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 81, 163, 131, 1, 183}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 188, 15, 226, 107, 142}, 208}, {{160, 120, 107, 254, 255, 212, 210, 151, 197, 43, 232, 118, 202, 211, 10, 57}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 106, 47, 109, 86, 37}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 130, 193, 248, 168, 177}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 86, 41, 166, 54, 72}, 208}, {{160, 0, 0, 0, 0, 0, 96, 28, 238, 37, 185, 10, 176, 73, 90, 133}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 216, 36, 247, 119, 219, 149, 143}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 25, 103, 56, 247}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 63}, 208}, {{160, 142, 160, 34, 127, 90, 162, 34, 125, 204, 60, 217, 106, 133, 148, 28}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 166, 187, 223, 101}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 161, 100, 122}, 208}, {{160, 0, 0, 0, 0, 0, 0, 149, 187, 242, 105, 78, 147, 171, 100, 203}, 208}, {{160, 0, 154, 183, 121, 107, 224, 195, 205, 6, 110, 65, 32, 36, 217, 186}, 208}, {{160, 0, 0, 0, 0, 0, 0, 41, 200, 74, 163, 79, 144, 158, 247, 11}, 208}, {{160, 0, 0, 0, 0, 0, 0, 186, 58, 43, 191, 12, 26, 69, 203, 72}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 224, 59}, 208}, {{160, 0, 0, 0, 0, 0, 11, 51, 235, 239, 17, 237, 127, 238, 10, 96}, 208}, {{160, 0, 0, 0, 0, 0, 66, 108, 33, 121, 107, 115, 233, 146, 135, 254}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 82, 187, 112, 2, 152, 234, 164, 0, 131}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 182, 143, 168, 32, 52, 218, 117}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 77, 117, 103, 28, 231, 87, 138, 86}, 208}, {{160, 0, 0, 0, 0, 0, 178, 83, 84, 101, 147, 252, 219, 159, 251, 239}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 183, 137, 126}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 94, 91, 204}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 199, 249, 7, 254, 124, 71, 33, 157, 151, 93, 147, 85, 24, 230}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 125}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 21, 58, 214, 159, 236}, 208}, {{160, 0, 0, 0, 119, 225, 65, 156, 61, 99, 70, 89, 106, 33, 141, 181}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 77, 57, 149, 71, 185, 155, 42, 61, 88, 30}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 40, 164, 195, 235, 150, 209, 113, 27}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 174, 4, 253, 125, 14, 43, 47, 41}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 94, 56, 167, 191, 251}, 208}, {{160, 0, 0, 0, 0, 0, 0, 240, 33, 113, 75, 233, 178, 149, 193, 225}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 48, 90}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 45, 20}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 83, 57, 208, 231}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 132, 52, 213, 70, 135, 79, 51}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 132, 86}, 208}, {{160, 0, 0, 0, 150, 164, 230, 213, 12, 228, 81, 1, 249, 113, 28, 245}, 208}, {{160, 0, 0, 0, 60, 121, 172, 14, 248, 77, 40, 225, 147, 196, 54, 206}, 208}, {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 208}, {{160, 0, 0, 0, 0, 0, 0, 140, 79, 155, 47, 70, 91, 129, 93, 180}, 208}, {{41, 85, 143, 128, 91, 137, 192, 0, 27, 104, 141, 212, 36, 90, 89, 139}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 88, 92, 178, 6, 152, 9, 26}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 123, 25, 125, 90, 61, 169, 192, 128}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 129}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 216, 83, 148}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 82, 203, 139, 121}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 178, 218, 143, 175, 60}, 219}, {{41, 85, 143, 128, 91, 137, 192, 254, 102, 202, 114, 174, 103, 91, 124, 68}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 47, 207, 64, 190}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 127, 230, 128, 214}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 74, 102, 192, 113, 211, 53, 85, 205}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 137, 58, 14}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 135, 1, 201, 190}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 126, 242, 13, 196, 15}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 238, 22, 45, 214}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 28, 251, 178}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 168, 149}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 89, 53, 182}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 97, 114}, 219}, {{41, 85, 143, 128, 91, 137, 192, 167, 130, 231, 220, 85, 133, 167, 161, 78}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 255, 138, 180, 206, 246, 133, 170, 206}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 129, 195, 205}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 167, 131, 212, 251}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 203, 65, 7, 76, 104, 105}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 39, 156, 188}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 94, 86, 134, 147}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 189, 15, 159, 161, 133, 21, 187, 113}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 118, 69, 28, 160, 247, 78, 23}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 172, 25, 252, 33, 41}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 47, 153, 54, 209, 224, 31}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 9, 127, 82, 215, 98}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 29, 251, 206, 232, 94, 133}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 143, 168, 225, 252, 71, 207}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 219}, {{41, 85, 143, 128, 91, 137, 192, 174, 91, 144, 125, 135, 26, 30, 7, 116}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 79, 225, 228, 153}, 219}, {{41, 85, 143, 128, 91, 137, 192, 75, 191, 191, 169, 159, 207, 89, 228, 49}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 162, 83, 241, 115}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 126, 76, 159, 230, 23, 157}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 123, 116, 227, 192, 47, 52, 164, 231}, 219}, {{41, 85, 143, 128, 91, 137, 192, 99, 248, 37, 242, 74, 192, 128, 240, 171}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 45, 5, 249, 45}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 159, 77, 166, 220, 127, 122}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 46, 199}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 35, 202}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 75, 125}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 16, 10, 8, 172, 163, 120}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 160, 87, 83, 211, 195, 121, 20, 222}, 219}, {{41, 85, 143, 128, 91, 137, 192, 91, 91, 88, 151, 122, 176, 82, 2, 149}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 91, 125, 33}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 57, 116, 140, 204, 73}, 219}, {{41, 85, 143, 128, 91, 137, 192, 235, 8, 89, 134, 236, 131, 9, 31, 239}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 111, 67}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 203, 168, 12, 207, 42}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 199, 6, 212, 133, 33, 151, 82, 126}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 206, 125, 100, 206, 78, 135}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 215, 103, 247, 69}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 63, 249, 214}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 59, 173}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 116, 92, 159, 103, 95, 224, 242}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 181, 106, 38}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 115, 125, 129, 174, 143, 4}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 117, 78, 61, 27, 164, 98, 122}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 85, 118, 124, 237, 76, 92}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 166, 67, 223, 125, 102, 122, 240}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 4, 24, 57, 140}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 187}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 10, 51, 27, 213, 27, 214, 37, 46}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 48, 7, 86, 100, 210, 27, 52, 157}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 166, 124, 219, 168, 20, 133, 175, 196}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 121, 22}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 176, 63, 40, 92}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 248, 10, 233, 246, 117, 232, 81}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 201, 225}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 16, 129}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 28, 76}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 71, 66, 242, 71, 107, 174}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 48, 243, 114}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 223, 228, 98, 244, 56}, 219}, {{41, 85, 143, 128, 91, 137, 192, 56, 19, 140, 193, 24, 216, 233, 71, 40}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 130, 168, 209}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 219}, {{41, 85, 143, 128, 91, 137, 192, 0, 110, 154, 225, 82, 250, 159, 138, 192}, 219}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 44, 213, 182, 244, 6}, 165}, {{116, 110, 192, 0, 0, 227, 199, 111, 7, 52, 90, 110, 80, 101, 43, 163}, 165}, {{116, 110, 192, 0, 0, 87, 247, 56, 156, 174, 209, 143, 214, 190, 152, 106}, 165}, {{116, 110, 192, 158, 17, 247, 145, 202, 86, 112, 202, 55, 46, 11, 40, 137}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 83, 210, 216, 148, 205}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 51, 162, 73}, 165}, {{116, 110, 192, 0, 0, 0, 139, 8, 34, 97, 216, 208, 121, 11, 82, 237}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 2, 167, 176, 19, 225, 204, 137, 86, 66, 163}, 165}, {{116, 110, 192, 43, 0, 157, 196, 146, 224, 168, 196, 118, 69, 20, 156, 132}, 165}, {{116, 110, 192, 0, 33, 118, 191, 235, 27, 109, 229, 131, 22, 139, 142, 39}, 165}, {{116, 110, 192, 0, 240, 108, 247, 173, 176, 227, 204, 212, 200, 146, 176, 135}, 165}, {{116, 110, 192, 28, 122, 13, 33, 139, 229, 80, 47, 0, 255, 193, 185, 251}, 165}, {{116, 110, 192, 0, 0, 93, 220, 77, 235, 185, 168, 115, 242, 92, 50, 86}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 26, 37, 32, 61, 28, 255, 228, 35}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 96, 101, 161, 197, 18, 228}, 165}, {{116, 110, 192, 0, 0, 226, 130, 154, 150, 109, 148, 204, 111, 164, 38, 80}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 33, 15, 42, 243, 165, 47}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 47, 106, 117}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 134, 191, 102, 193, 15, 112, 156}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 95, 155}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 203, 240, 185}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 195}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 28, 216, 236, 84, 67, 99, 160, 161, 86, 200, 89, 117, 127}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 165}, {{116, 110, 192, 0, 0, 0, 0, 58, 204, 43, 51, 87, 24, 1, 236, 19}, 165}, {{116, 110, 192, 0, 0, 0, 0, 159, 13, 43, 96, 161, 237, 126, 182, 79}, 165}, {{116, 110, 192, 0, 0, 139, 36, 179, 253, 56, 101, 91, 226, 184, 15, 110}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 79, 221, 175, 251, 13, 250, 80, 60}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 150, 152, 2, 203, 159, 51, 116, 104}, 165}, {{116, 110, 192, 0, 0, 219, 202, 222, 56, 217, 14, 15, 127, 39, 235, 234}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 182, 237, 141, 63, 170, 79, 251, 103, 86, 21, 118, 48}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 223}, 165}, {{116, 110, 192, 0, 0, 0, 0, 34, 241, 206, 50, 241, 248, 33, 108, 174}, 165}, {{116, 110, 192, 0, 0, 0, 0, 169, 12, 154, 227, 210, 253, 85, 34, 115}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 211}, 165}, {{116, 110, 192, 0, 0, 192, 15, 147, 131, 233, 137, 207, 234, 189, 218, 57}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 76, 30, 215, 143, 178, 64, 160, 210}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 150, 136}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 208, 171, 218, 52, 244}, 165}, {{116, 110, 192, 0, 194, 123, 155, 77, 28, 89, 136, 99, 0, 36, 213, 46}, 165}, {{116, 110, 192, 0, 0, 177, 62, 25, 221, 104, 53, 75, 44, 235, 224, 18}, 165}, {{116, 110, 192, 0, 218, 54, 183, 182, 27, 143, 18, 74, 59, 112, 31, 71}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 154, 95, 132, 84, 64, 194}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 165}, {{116, 110, 192, 0, 0, 0, 0, 210, 118, 192, 74, 42, 71, 206, 155, 15}, 165}, {{116, 110, 192, 0, 21, 120, 31, 255, 142, 93, 52, 78, 82, 47, 224, 3}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 87, 240, 36, 194, 12, 4, 149}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 181, 127, 32, 231, 139, 234, 43}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 165}, {{116, 110, 192, 226, 42, 0, 62, 160, 80, 4, 140, 167, 230, 142, 171, 134}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 190, 93, 83, 185, 64, 246, 78, 20}, 165}, {{116, 110, 192, 0, 0, 0, 88, 12, 185, 131, 123, 190, 81, 89, 188, 31}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 167, 187}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 165}, {{116, 110, 192, 0, 169, 224, 141, 232, 102, 141, 147, 148, 214, 202, 250, 204}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 5, 174, 174, 215, 154, 176, 191, 67, 47, 117, 167, 77, 16}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 152, 161, 203, 70, 159}, 165}, {{116, 110, 192, 0, 0, 30, 195, 85, 102, 236, 166, 184, 41, 76, 90, 118}, 165}, {{116, 110, 192, 0, 5, 70, 246, 80, 56, 212, 179, 167, 102, 183, 17, 0}, 165}, {{116, 110, 192, 0, 0, 50, 223, 243, 89, 254, 143, 243, 188, 127, 126, 26}, 165}, {{116, 110, 192, 0, 0, 0, 0, 212, 215, 167, 185, 222, 232, 92, 89, 18}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 183, 195, 79, 251, 63, 33, 90, 136}, 165}, {{116, 110, 192, 0, 0, 106, 254, 101, 110, 128, 15, 227, 36, 170, 113, 136}, 165}, {{116, 110, 192, 0, 0, 0, 0, 80, 91, 231, 40, 96, 199, 254, 157, 22}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 133, 226}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 247, 234, 218, 140, 204, 101}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 4}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 152}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 85, 133, 131, 187, 8}, 165}, {{116, 110, 192, 0, 0, 0, 89, 214, 130, 235, 23, 129, 114, 84, 172, 134}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 133, 221, 177, 18, 11, 205, 89, 59}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 132, 136, 64}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 250}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 175}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 206, 178, 0}, 165}, {{116, 110, 192, 0, 110, 181, 109, 66, 139, 85, 141, 106, 80, 5, 229, 43}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 222, 124, 186, 228, 21, 53}, 165}, {{116, 110, 192, 0, 0, 229, 29, 128, 195, 150, 81, 230, 15, 68, 244, 45}, 165}, {{116, 110, 192, 0, 88, 18, 80, 223, 244, 52, 146, 192, 90, 191, 11, 74}, 165}, {{116, 110, 192, 0, 0, 0, 0, 68, 20, 172, 231, 246, 175, 127, 67, 113}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 254, 27}, 165}, {{116, 110, 192, 0, 225, 14, 84, 225, 41, 180, 9, 116, 20, 69, 28, 143}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 225, 229, 8, 255, 229, 18, 76}, 165}, {{116, 110, 192, 17, 169, 146, 206, 34, 242, 196, 126, 42, 65, 179, 175, 188}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 141, 192, 5}, 165}, {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 99}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 28}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 134}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 56}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 137}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 58}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 189}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 226}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 254}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 130}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 209}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 209}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 141}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 64}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 122}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 142}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 169}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 153}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 234}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 245}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 160}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 240}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 247}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 233}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 219}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 218}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 1}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 6}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 72, 185, 108}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 239, 38}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 230, 122, 56, 168, 92}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 74, 34, 24}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 78, 5, 126, 79, 92, 76}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 17, 141, 194}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 10, 179, 100, 68, 52, 62, 219, 67}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 203, 172, 173, 237}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 215, 54, 49, 230}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 35, 172, 166}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 118, 153, 156, 96, 69}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 69, 0, 183, 133, 86, 134}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 215, 65, 93, 77, 189, 45, 141}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 172, 63, 111, 3, 131}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 46, 226, 16}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 99, 8, 91}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 142, 200, 222, 193, 228, 2, 68}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 111, 59, 69}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 206, 172, 65, 49, 167, 52}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 102, 110, 49, 163, 33, 248}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 9, 155, 214, 183, 46, 143, 168, 35}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 227}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 222, 152, 14}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 95, 196}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 90, 184, 28}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 218, 207, 34}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 220, 109, 8, 196, 164, 97}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 40, 132, 221, 195}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 187, 173, 83, 5, 23, 37, 122, 15}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 53, 51, 93, 6, 250, 31}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 89, 70}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 119, 76, 226}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 222, 212, 167, 139}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 130, 185, 237, 129, 140, 72, 50, 153}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 50, 73}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 169, 82, 87, 122, 113}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 15, 205, 15, 207, 252, 105}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 212, 225, 242}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 88, 205, 224, 234, 91}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 120, 11}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 226, 107, 134, 164}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 5, 231, 49, 214, 36, 236, 132}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 106, 142, 215, 10, 109}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 236, 38, 157, 93, 230, 17, 59}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 51, 0, 92, 48, 66, 183, 199}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 97, 146, 112}, 47}, {{229, 23, 116, 61, 80, 139, 200, 115, 108, 170, 144, 167, 198, 232, 70, 65}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 20, 0, 44, 75, 4, 128}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 185, 64, 41, 121, 153}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 47}, {{229, 23, 116, 61, 80, 139, 200, 109, 96, 13, 226, 65, 0, 126, 151, 233}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 203, 18, 77, 76, 80, 179}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 73, 218, 129}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 9, 201, 26, 182, 150, 124}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 20, 105, 255, 128, 65, 242, 164}, 47}, {{229, 23, 116, 61, 80, 139, 200, 110, 207, 106, 64, 220, 90, 102, 185, 222}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 90, 25, 8}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 113, 145, 92}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 37, 15}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 108, 61, 189, 3, 41, 100, 255}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 237, 110, 42, 6, 132}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 26, 177, 103}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 144, 241}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 120, 234, 160, 6, 181}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 208, 215, 193, 192, 195, 82}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 187, 213, 75, 7, 156, 80}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 128, 204, 193, 227, 125}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 90, 110, 99, 40, 110, 249}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 111, 254, 123, 167, 230}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 198, 210, 82, 182, 85, 13}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 72, 37, 64, 121, 3, 53}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 104, 84, 219, 224, 43, 214}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 129, 53, 220, 43, 113, 64, 200, 168}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 143, 241, 103, 83, 255, 204, 93}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 81, 90, 122, 85, 5, 196, 5}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 216, 252, 23, 58}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 225, 114, 179}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 104, 58, 81, 112}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 175, 52, 107, 191, 46, 106, 35}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 57}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 113, 97}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 141, 240, 153, 43, 7}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 200, 228, 1, 98, 133, 66, 147, 72}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 44, 138, 94, 246}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 195, 55, 167, 139, 157, 230}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 13, 166, 40, 111, 2, 19}, 47}, {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 47}, {{83, 123, 74, 0, 0, 0, 193, 71, 104, 8, 208, 232, 230, 26, 179, 91}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 74, 84, 39, 255, 245}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 212, 149, 237, 145, 60, 32, 231, 82}, 73}, {{83, 123, 74, 0, 0, 0, 0, 212, 114, 67, 219, 50, 202, 140, 204, 95}, 73}, {{83, 123, 74, 0, 46, 148, 95, 99, 194, 241, 80, 154, 100, 242, 226, 12}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 73}, {{83, 123, 74, 0, 201, 220, 208, 94, 8, 189, 220, 113, 229, 115, 58, 3}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 73, 28, 56, 211, 127, 150, 86}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 107, 105, 158, 83, 31, 89, 105}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 33, 170, 59, 118, 21}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 109, 169, 62}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 211, 125, 212, 177, 61, 226, 195}, 73}, {{83, 123, 74, 0, 148, 254, 190, 21, 24, 194, 23, 122, 26, 245, 208, 119}, 73}, {{83, 123, 74, 0, 0, 0, 242, 199, 20, 68, 78, 22, 127, 252, 16, 193}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 86, 166, 121, 68, 167, 207, 251, 214}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 236, 243, 235}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 32, 148, 184}, 73}, {{83, 123, 74, 225, 165, 79, 64, 68, 20, 85, 201, 31, 254, 244, 126, 37}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 184, 70, 156, 53, 145, 49}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66}, 73}, {{83, 123, 74, 0, 34, 142, 221, 18, 5, 5, 54, 144, 71, 194, 131, 180}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 196, 230, 193}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 186, 207}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 235, 218}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 39, 202, 248, 106, 87}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 94, 118, 154}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 214, 222, 55, 157, 173, 28, 192, 141}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 211, 117}, 73}, {{83, 123, 74, 0, 0, 0, 0, 197, 185, 200, 7, 32, 52, 116, 106, 166}, 73}, {{83, 123, 74, 0, 217, 220, 167, 233, 59, 64, 245, 119, 158, 136, 90, 165}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 73}, {{83, 123, 74, 48, 51, 65, 226, 113, 118, 2, 86, 77, 120, 189, 14, 115}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 159, 216}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 105, 117, 64, 136, 95, 224, 205, 66, 101, 168, 87}, 73}, {{83, 123, 74, 0, 109, 148, 17, 31, 14, 229, 154, 242, 78, 207, 233, 188}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 108}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 156, 86, 183, 156, 154, 71, 148}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 125, 184, 155, 252, 193}, 73}, {{83, 123, 74, 0, 164, 39, 73, 204, 203, 237, 246, 35, 182, 51, 45, 33}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 73}, {{83, 123, 74, 0, 0, 111, 58, 5, 27, 216, 219, 135, 57, 114, 228, 95}, 73}, {{83, 123, 74, 0, 129, 32, 227, 137, 115, 223, 103, 248, 103, 158, 41, 250}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 209}, 73}, {{83, 123, 74, 0, 0, 69, 188, 99, 197, 31, 255, 190, 123, 169, 245, 21}, 73}, {{83, 123, 74, 0, 0, 0, 0, 11, 154, 85, 50, 28, 105, 164, 32, 203}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 136, 127, 61, 120, 67, 255}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 59, 78, 79, 179, 197, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 190}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 250, 138}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 165, 57, 81, 194, 90, 50}, 73}, {{83, 123, 74, 0, 84, 28, 201, 25, 186, 254, 235, 101, 77, 222, 115, 113}, 73}, {{83, 123, 74, 0, 226, 209, 220, 164, 189, 213, 50, 167, 229, 148, 89, 4}, 73}, {{83, 123, 74, 0, 0, 0, 195, 122, 197, 4, 107, 246, 70, 126, 168, 194}, 73}, {{83, 123, 74, 0, 24, 91, 27, 12, 238, 102, 177, 44, 206, 73, 84, 80}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 166, 132, 53, 132, 61, 78, 202, 147}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 249, 87}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 169, 212}, 73}, {{83, 123, 74, 0, 0, 59, 221, 69, 67, 157, 78, 13, 254, 175, 32, 97}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 214, 254, 9, 123, 76, 108}, 73}, {{83, 123, 74, 43, 67, 243, 2, 211, 111, 31, 133, 146, 108, 222, 212, 236}, 73}, {{83, 123, 74, 0, 204, 149, 97, 111, 31, 142, 100, 114, 106, 227, 92, 224}, 73}, {{83, 123, 74, 0, 152, 239, 12, 210, 165, 134, 253, 32, 98, 108, 190, 159}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 238, 140, 137, 154, 181}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 80}, 73}, {{83, 123, 74, 0, 0, 0, 0, 43, 179, 240, 97, 121, 48, 78, 179, 251}, 73}, {{83, 123, 74, 0, 0, 48, 61, 91, 76, 35, 145, 70, 47, 215, 206, 193}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 119, 253, 189, 27, 205}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 42, 90, 136}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 158, 77, 63, 188, 39, 86, 149}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 67, 114, 221, 8, 188, 187}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 27, 28, 161, 216, 41, 97, 242}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 85, 127, 184, 111, 221}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 62, 98}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 139, 151, 181, 80, 22, 33, 26, 250}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 129, 167, 40, 170, 136, 174, 27, 184, 19, 175, 227, 150}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 224, 220, 86, 135, 150, 241}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 73}, {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 38, 199}, 73}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 130, 116}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 223, 183}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 46, 185, 68, 31}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 196, 134, 72}, 98}, {{151, 243, 45, 217, 216, 158, 0, 79, 214, 62, 162, 204, 173, 84, 171, 3}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 195, 131, 39, 107, 94, 128, 107, 98, 236, 156}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 231, 82, 147, 24, 213, 80, 8, 189}, 98}, {{151, 243, 45, 217, 216, 158, 0, 241, 83, 18, 253, 88, 62, 133, 123, 99}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 96, 34, 24}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 63, 49, 98, 12, 185, 218, 101, 209, 72}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 49, 108, 66, 90}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 165, 105, 190, 65, 202, 7, 244, 48}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 176, 190, 125, 197, 148}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 154, 118, 193}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 129, 58, 152, 228}, 98}, {{151, 243, 45, 217, 216, 158, 0, 44, 192, 197, 105, 81, 189, 77, 7, 95}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 177, 12, 250, 104, 195}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 155, 57, 113, 99, 229, 181, 62}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 150, 39, 233}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 32, 177, 20, 135, 8}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 175, 215, 46}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 190, 97, 3, 205, 54, 70, 170, 85}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 233, 228, 39, 232, 186, 178, 25}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 89, 212, 203, 34, 96}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 107, 241, 26, 58}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 13, 38, 120, 211, 38, 47, 96}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 114, 123, 231, 39, 240, 71, 35, 233}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 65, 208}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 16, 56, 119, 192}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 83, 22}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 197, 63}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 9, 40, 199, 117, 113, 254, 121, 60}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 24, 23, 22, 173, 46, 38, 30}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 166, 171}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 140, 109, 164, 44}, 98}, {{151, 243, 45, 217, 216, 158, 0, 48, 223, 238, 126, 216, 28, 128, 3, 72}, 98}, {{151, 243, 45, 217, 216, 158, 0, 78, 146, 10, 144, 99, 182, 240, 183, 2}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 152, 216, 211, 146, 103, 140, 55}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 75, 168, 54, 119}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 57, 40, 140, 195, 107}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 129, 215, 232, 235, 75}, 98}, {{151, 243, 45, 217, 216, 158, 0, 32, 122, 210, 48, 87, 70, 246, 194, 158}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 32, 144, 244, 253, 122, 249}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 83, 122, 18, 127, 120, 178, 143, 204}, 98}, {{151, 243, 45, 217, 216, 158, 0, 25, 63, 129, 211, 125, 207, 226, 189, 198}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 255, 117}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 74, 28}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 254, 83, 54, 203, 13}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 112, 224}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 37, 34, 162, 78}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 54, 81}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 132, 184}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 184, 24, 39, 215, 91, 90}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 65, 145, 18, 151, 249, 192, 197, 57}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 79, 60, 63}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 171, 67, 246, 23, 64, 20, 206, 6}, 98}, {{151, 243, 45, 217, 216, 158, 0, 246, 221, 143, 72, 188, 78, 76, 243, 68}, 98}, {{151, 243, 45, 217, 216, 158, 0, 89, 44, 72, 8, 159, 84, 138, 35, 69}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 27, 168, 151}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 98}, {{151, 243, 45, 217, 216, 158, 0, 47, 23, 54, 169, 17, 17, 131, 157, 57}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 67, 186, 164, 80}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 232, 205, 112}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 208, 95, 233, 11, 207, 23}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 236, 223, 115}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 50, 45, 45, 115}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 3, 224, 73, 148}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 85, 18, 15, 205, 207}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 151, 101, 184}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 103, 191, 209}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 44, 64, 120, 214, 168}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 239, 6, 242}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 152, 89, 250, 84, 220, 145, 55}, 98}, {{151, 243, 45, 217, 216, 158, 0, 172, 94, 231, 119, 34, 230, 247, 88, 147}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 190, 164, 249}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 17, 150, 82, 108, 29}, 98}, {{151, 243, 45, 217, 216, 158, 0, 0, 0, 151, 49, 16, 202, 110, 181, 44}, 98}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 9, 56, 76, 134}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 175, 219, 143, 38, 51, 90, 105, 5}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 147, 221, 167}, 21}, {{171, 184, 110, 211, 237, 114, 144, 69, 226, 195, 122, 197, 59, 136, 120, 241}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 7, 223, 83, 230, 62}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 97, 177, 111}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 25, 148, 85, 161, 2, 88}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 178, 104, 120, 90, 147}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 254, 225, 216, 18, 66, 127, 255, 72}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 115, 26}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 161, 40, 90, 250, 15, 160, 76}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 248, 222, 229, 40, 225, 131, 248, 173}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 213, 196, 146, 199, 80, 10, 246, 60}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 44, 169, 69, 231}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 22, 1, 70, 194, 177, 192, 95}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 193, 251, 30, 210, 159}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 116, 59}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 153, 97, 177}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 25, 51, 82, 102, 70, 29}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 168, 37}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 84, 49, 196, 72, 194, 201}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 209, 24, 164, 227, 190}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 17, 79}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 4, 201, 201}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 200, 131, 140, 28}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 250, 240, 115, 161, 101, 119}, 21}, {{171, 184, 110, 211, 237, 114, 144, 208, 145, 163, 136, 188, 236, 186, 118, 112}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 10}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 150, 14}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 173}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 102, 36, 42, 139, 29}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 93, 53, 222, 72, 132, 146, 165, 115}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 109, 63, 121, 217, 54, 236, 96, 116}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 35, 253, 206, 190}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 143, 39, 76, 84, 127, 30, 109, 231}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 35, 229, 63, 193, 167}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 105, 145}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 63, 151, 87, 24, 58, 243, 154, 183}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 235, 65, 30, 227, 193, 140}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 111, 58, 108, 163, 116, 51, 140}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 155, 65, 188, 76, 127, 248, 178}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 78, 37, 166}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 41, 156, 93, 26, 23, 98, 211, 44}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 56, 46, 15, 42}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 241, 228, 192, 124, 167}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 55, 204}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 228, 14, 148, 52, 194}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 199, 73, 137, 179, 94}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 203, 129, 185, 4, 32, 159, 173, 93}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 243, 81}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 168, 40, 231, 93, 55}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 117, 137, 220, 83, 174}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 219, 121, 171, 166}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 124, 105, 66}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 199, 203, 64, 14, 41}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 52, 135, 27, 130, 103, 5, 45, 26}, 21}, {{171, 184, 110, 211, 237, 114, 144, 248, 233, 129, 74, 251, 156, 247, 195, 95}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 193, 144, 138, 213, 116, 211}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 180, 155, 236, 208, 74, 193, 69}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 75, 151, 199}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 117, 73, 158, 124, 161, 6}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 1, 244, 4, 196, 23, 248}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 22, 116, 107, 184, 111, 125, 123, 246}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 145, 49, 240, 224, 35, 22, 218}, 21}, {{171, 184, 110, 211, 237, 114, 144, 144, 46, 246, 42, 10, 248, 227, 127, 193}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 35, 225, 220}, 21}, {{171, 184, 110, 211, 237, 114, 144, 41, 66, 101, 180, 222, 125, 13, 101, 20}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 184, 231, 20}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 184, 32, 28, 185, 183}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 51, 240, 28, 96, 75, 252, 137}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 54, 45}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 59, 234, 103}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 239, 120, 99, 153, 177, 86, 86, 70}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 15, 87, 36}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 199, 149, 194, 84, 229, 202, 246}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 28, 83, 79}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 70, 186, 123, 38, 211, 176, 186}, 21}, {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 215}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 84, 43, 6, 68, 62, 131, 125}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 147}, 142}, {{7, 246, 199, 119, 0, 0, 0, 134, 35, 35, 248, 16, 176, 53, 254, 106}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 104, 223, 181, 6}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 108, 143, 138, 102, 61, 208}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 142}, {{7, 246, 199, 119, 0, 0, 0, 133, 2, 28, 76, 162, 216, 206, 113, 184}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 121}, 142}, {{7, 246, 199, 119, 0, 0, 209, 60, 110, 16, 70, 38, 6, 171, 211, 13}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 125, 74, 194, 89, 114, 100}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 172}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 199, 125}, 142}, {{7, 246, 199, 119, 0, 68, 122, 241, 219, 139, 38, 54, 89, 20, 165, 56}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 89, 128, 7, 239, 106, 118, 62, 31}, 142}, {{7, 246, 199, 119, 0, 10, 128, 171, 157, 162, 168, 64, 242, 106, 21, 138}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 142, 140}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 161, 147, 135, 251, 22, 230, 18, 110}, 142}, {{7, 246, 199, 119, 0, 0, 143, 70, 8, 247, 46, 164, 48, 113, 89, 226}, 142}, {{7, 246, 199, 119, 0, 0, 133, 238, 117, 37, 163, 92, 12, 247, 80, 111}, 142}, {{7, 246, 199, 119, 0, 0, 20, 165, 125, 61, 35, 67, 198, 242, 214, 140}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 249}, 142}, {{7, 246, 199, 119, 0, 148, 194, 185, 147, 78, 161, 62, 4, 156, 105, 126}, 142}, {{7, 246, 199, 119, 0, 0, 218, 49, 97, 127, 153, 140, 54, 112, 147, 71}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 194, 235, 83, 182, 123, 116, 47}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 176, 90, 161, 181, 155, 101, 197, 6}, 142}, {{7, 246, 199, 119, 0, 0, 54, 228, 197, 135, 173, 188, 103, 164, 50, 125}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 76, 211, 1, 164, 69, 107, 104, 24, 77}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 252, 34, 232, 124, 151, 173, 109}, 142}, {{7, 246, 199, 119, 0, 0, 0, 77, 110, 145, 128, 20, 253, 231, 112, 89}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 142, 189}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 243, 45, 24, 104, 47, 236, 88, 151}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 218, 2, 166, 182, 185, 241}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 5, 59, 100, 46, 2, 58, 12, 205, 129}, 142}, {{7, 246, 199, 119, 0, 110, 77, 192, 5, 17, 70, 116, 198, 148, 241, 29}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 206, 177, 56, 181, 4, 76, 207, 186}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 253, 168}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 46, 159, 50, 185, 135, 126, 247, 41}, 142}, {{7, 246, 199, 119, 0, 110, 77, 180, 193, 187, 116, 255, 247, 158, 22, 67}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73}, 142}, {{7, 246, 199, 119, 0, 0, 6, 112, 105, 161, 137, 172, 8, 114, 201, 92}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 45, 28, 93, 113, 70, 13, 204, 39}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 52}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 167, 208, 254, 11, 90}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 111, 133, 116, 243, 94, 85, 12}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 33, 75, 172, 70, 17}, 142}, {{7, 246, 199, 119, 0, 0, 199, 186, 1, 179, 53, 143, 142, 203, 124, 109}, 142}, {{7, 246, 199, 119, 0, 138, 60, 175, 6, 4, 229, 0, 182, 166, 165, 105}, 142}, {{7, 246, 199, 119, 0, 72, 25, 103, 192, 119, 147, 254, 213, 24, 130, 79}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 60, 231}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 102, 21, 103, 111, 53, 146, 70}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 109, 13, 82, 19, 97, 226, 37, 2}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 163, 131}, 142}, {{7, 246, 199, 119, 0, 0, 0, 101, 129, 113, 29, 76, 16, 144, 180, 88}, 142}, {{7, 246, 199, 119, 0, 23, 58, 187, 185, 126, 193, 135, 234, 44, 213, 63}, 142}, {{7, 246, 199, 119, 0, 0, 148, 92, 249, 119, 156, 173, 84, 11, 124, 49}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 36, 231, 138, 101, 11}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 228, 121, 36, 127, 199, 13}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 213}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 84, 226, 67, 253}, 142}, {{7, 246, 199, 119, 0, 0, 36, 161, 95, 17, 174, 164, 188, 112, 37, 182}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 132, 90, 253, 110, 53, 185}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 201, 104, 137, 15, 226, 12, 162, 82}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 159, 219, 188, 54, 65}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 142}, {{7, 246, 199, 119, 0, 0, 0, 210, 214, 194, 184, 9, 62, 0, 89, 51}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 135}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 216}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 199, 135, 206, 214, 190}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 181, 175, 252, 122, 43, 121, 253}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 41, 54}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 123, 248, 226, 117, 127, 6, 169, 187}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 55, 48, 14, 81, 204, 57, 90}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 9}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 66, 114, 110, 77}, 142}, {{7, 246, 199, 119, 0, 0, 37, 184, 81, 160, 223, 241, 136, 129, 226, 251}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 196, 73, 198, 144, 82, 69, 206, 9}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 168, 254, 116, 119, 218, 20}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 18}, 142}, {{7, 246, 199, 119, 0, 0, 0, 126, 214, 70, 195, 174, 237, 11, 251, 194}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 24, 15, 134, 135}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 201, 213, 15, 126, 53, 40, 0, 163}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 133, 200}, 142}, {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 224, 238}, 142}, {{7, 246, 199, 119, 0, 165, 242, 101, 243, 13, 177, 58, 52, 93, 57, 157}, 142}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 103}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 156, 198}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 144, 19, 62}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 50, 19}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 75}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 152, 244, 50, 136}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 69, 127, 13}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 176, 127, 207, 88}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 219, 6}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 210, 174, 73, 147}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 217, 129, 135}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 203, 144, 176}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 48, 246, 249}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 38, 114, 87, 213}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 177, 129}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 64, 188, 94}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 69, 181}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 207}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 71, 198, 150}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 254, 232}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 175, 84, 95}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 175}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 113, 40}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 104, 196, 233}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 134, 242, 118}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 211, 119, 33}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 40, 106, 193}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 214}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 36}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 119, 105, 70}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 12, 220, 64}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 86, 105, 252}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 212, 56}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 218, 201, 26}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 120, 229}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 213, 27}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 254}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 68, 120, 163}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 246, 172}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 226}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 106, 17, 140, 227}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 58, 58}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 185, 222, 244}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 107, 217, 248}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 15}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 28}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 251}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 66, 125, 250, 53}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 97, 51}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 221, 184, 154}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 189}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 70, 239, 120, 157}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 255, 61, 200, 144}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 68, 205}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 157, 94}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 203}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 95, 193}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 82, 96}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 10, 212}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 1, 28}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 69, 218}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 67}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 78, 140, 87}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 116, 248}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 103, 229, 131}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 48, 161, 198}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 210}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 168, 135}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 145, 4}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 85, 20, 204}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 47}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 155}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 34}, {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 134, 63, 151, 21}, 34}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 17}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 225, 243, 76}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 86, 214, 154, 179}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 63}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 182, 246, 104, 55, 250}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 133, 6, 31}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 220, 102}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 79, 98}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 2, 134, 37, 94, 80}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 205, 37, 147, 217, 164, 177}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 81, 12}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 81, 102}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 107, 222, 1, 45, 247}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 243, 165}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 223, 98, 194}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 49, 206, 74}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 190, 190, 166}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 4, 83, 240, 213, 91}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 224, 232, 0, 147}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 134, 170}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 26, 210, 55, 208}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 58, 181, 123, 27}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 190, 42, 148, 229, 106}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 124, 131, 140, 111}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 247, 20, 43, 174, 135, 195}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 60, 227, 103, 51}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 246, 180, 214, 233, 8}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 165, 113, 30, 173}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 159, 74, 107, 40}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 175}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 180, 71, 181, 71, 121}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 22}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 63, 169, 240, 174, 78}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 152, 126, 214, 50}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 83, 11, 180, 197}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 41, 46, 230, 53, 8}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 250, 58, 24, 196}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 235, 19}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 11}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 250, 122, 219}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 161, 186, 26, 45, 162, 254}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 23, 11, 255, 97, 246}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 41}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 177, 241, 94}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 201, 159, 159, 136, 66, 89}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 114, 221}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 216, 6, 119, 154, 218}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 160, 183}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 218, 87, 31}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 98, 124, 44}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 184, 164, 204, 144, 47, 87}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 81}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 185, 154, 134, 106, 126}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 75}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 197}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 23, 141}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 68, 28}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 123, 205}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 166}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 129, 186, 157, 168}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 4, 18, 63, 92, 88, 83}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 42, 61, 178, 175}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 38, 106}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 128, 233, 118}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 28}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 122}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 142, 197, 188, 168, 229, 238}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 123, 226, 15, 178}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 66, 182}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 250, 71, 233}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 172, 242, 224, 62}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 201, 81, 249}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 99, 186, 242, 246, 20, 163}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 173, 120, 184, 252, 173}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 74, 26, 19, 110, 193}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 38, 176, 145}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 210, 113, 166, 106}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 108, 80, 58, 206}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 20, 38, 43, 116, 174}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 110}, 41}, {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 41}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 122, 200, 233, 172, 99}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 18, 42, 219, 126, 60}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 42, 91, 97}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 253, 188, 71, 68, 120}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 77, 0, 187, 200, 139, 33, 90}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 101, 169, 241}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 46, 36, 182, 36}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 75, 17, 4, 227, 181, 188, 212, 205}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 199, 113}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 162, 61, 198, 209, 10, 115, 131}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 92, 51, 83, 39}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 148, 188, 33, 229, 223, 68, 38, 134}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 90, 137, 62, 32, 105, 76}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 34, 196, 215, 90, 94, 141}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 54, 154, 126, 64, 58, 168}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 57, 235, 238}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 190, 195, 88}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 99, 126, 198}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 242, 181, 56, 185, 166, 221, 231, 12}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 198, 109, 75, 67, 92, 45, 54}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 145, 83, 53, 96, 20}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 11, 219, 178, 240}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 91, 223, 1, 96, 45, 141, 70}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 218, 246, 14, 143, 205}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 62, 44, 60, 35, 128, 171, 199}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 15, 141, 34, 38, 54, 89}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 45, 102, 99, 242, 6, 31, 4}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 230, 18, 112, 27}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 211, 158, 14}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 29, 217, 107, 60, 12, 101}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 8, 64, 173, 112, 232}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 29, 74}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 85, 73, 178}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 220, 255, 64, 92, 46, 234, 198, 110}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 168, 40, 122, 52, 145, 77}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 96, 62, 19, 179, 210}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 212, 210, 103, 164, 166}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 84, 8, 104, 116, 3}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 91, 246, 44, 3, 58, 14, 207, 54}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 86, 212, 50}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 60, 117, 19, 169, 45, 132}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 197, 184, 156, 147}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 49, 179, 203, 0, 237, 61, 62, 52}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 160, 61}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 23, 61, 180, 92, 136}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 252}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 149, 244, 63, 237, 49, 148, 124, 230}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 17, 237, 100, 39, 165, 22, 168, 170}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 247, 47, 52, 81, 3, 128, 221}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 224, 97}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 214, 52, 117, 66, 209}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 167, 103, 111, 91, 215, 87, 130, 247}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 175, 103, 133}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 192, 56, 126}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 11, 80, 97}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 93, 255, 192, 182, 11, 162}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 88, 86, 108, 37, 123, 35, 85, 167}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 123, 46, 209, 34, 234, 237, 150, 89}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 180, 220, 39, 38, 223, 216, 204}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 16, 191}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 140, 118, 224, 238}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 22, 31, 170, 57}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 220, 143, 180, 236, 162, 199, 113}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 229, 151, 69, 27, 145, 72, 10}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 144, 195, 2, 105, 22, 40, 53}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 76, 121, 246, 115, 244, 161, 219}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 129, 33, 63, 112, 181, 224}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 202, 89, 224, 43, 48, 213}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 59, 165, 214, 28}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 55, 123}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 175, 51, 63}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 59, 51, 48, 233, 188}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 51, 250, 210, 130, 54, 6, 127, 8}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 58, 214, 45, 112, 30}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 195, 239, 60, 132, 146, 3, 67}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 65, 83, 46, 244}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 145, 7, 250}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 55, 110, 173}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 155, 159, 82, 66, 162}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 50, 196, 46, 49, 222, 110, 248, 1}, 80}, {{235, 6, 229, 248, 151, 137, 36, 0, 0, 139, 249, 98, 18, 218, 139, 118}, 80}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 187, 247, 3, 223, 165, 129}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 91}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 189, 243}, 11}, {{156, 39, 96, 0, 0, 0, 0, 81, 246, 195, 218, 238, 99, 42, 196, 175}, 11}, {{156, 39, 96, 0, 92, 34, 43, 28, 176, 78, 242, 9, 163, 10, 50, 228}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 52}, 11}, {{156, 39, 96, 0, 159, 202, 235, 115, 147, 178, 168, 70, 220, 77, 202, 40}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 16, 31}, 11}, {{156, 39, 96, 0, 0, 0, 102, 65, 94, 247, 154, 247, 85, 145, 247, 19}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 0, 0, 0, 225, 136, 218, 28, 57, 61, 81, 178, 153}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 165, 102}, 11}, {{156, 39, 96, 0, 0, 0, 218, 195, 231, 237, 31, 65, 42, 151, 209, 151}, 11}, {{156, 39, 96, 0, 0, 68, 14, 221, 121, 33, 209, 13, 27, 113, 238, 238}, 11}, {{156, 39, 96, 0, 0, 0, 17, 93, 164, 88, 53, 90, 78, 61, 146, 144}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 105, 142, 70, 91, 217, 199, 1}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 95, 219, 192, 203, 57, 248, 210}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 249, 116, 152, 195, 108, 246}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 110, 66, 16}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 62}, 11}, {{156, 39, 96, 0, 0, 51, 168, 38, 160, 123, 100, 123, 44, 66, 161, 224}, 11}, {{156, 39, 96, 0, 0, 0, 240, 246, 153, 113, 169, 236, 42, 195, 213, 25}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 195, 153, 31, 143, 242, 103, 31, 138}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 1, 185, 7, 74, 46}, 11}, {{156, 39, 96, 0, 0, 87, 14, 123, 145, 18, 21, 4, 123, 247, 62, 242}, 11}, {{156, 39, 96, 0, 0, 0, 90, 1, 51, 135, 134, 17, 69, 2, 92, 225}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 44, 79, 135, 46, 193, 117}, 11}, {{156, 39, 96, 0, 27, 123, 82, 192, 152, 22, 111, 185, 160, 81, 172, 108}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 134, 71, 156, 41, 129, 77, 21}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 231}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 3, 228, 74}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 75, 89, 181, 113, 250}, 11}, {{156, 39, 96, 0, 0, 0, 0, 199, 113, 178, 220, 121, 102, 37, 247, 33}, 11}, {{156, 39, 96, 234, 12, 231, 104, 59, 87, 70, 48, 225, 116, 254, 214, 157}, 11}, {{156, 39, 96, 0, 0, 250, 95, 9, 39, 118, 187, 71, 31, 197, 221, 157}, 11}, {{156, 39, 96, 74, 112, 75, 169, 2, 18, 210, 247, 75, 79, 20, 24, 203}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 146, 113, 40, 166, 239}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 186}, 11}, {{156, 39, 96, 0, 0, 0, 0, 103, 255, 44, 192, 149, 200, 172, 110, 48}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 53, 68}, 11}, {{156, 39, 96, 0, 0, 0, 0, 214, 238, 218, 32, 175, 3, 167, 169, 105}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 8, 84}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 211}, 11}, {{156, 39, 96, 0, 0, 152, 95, 144, 251, 161, 219, 226, 224, 244, 15, 240}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 0, 2, 24, 86, 69, 26, 182, 227, 109, 126, 80, 13}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 122, 54, 218, 128, 45, 123}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 122}, 11}, {{156, 39, 96, 0, 0, 169, 213, 241, 235, 179, 80, 253, 237, 195, 28, 176}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 73, 68, 61, 188, 198, 237}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 224, 92, 218, 112, 96, 38, 101}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 50, 25, 113, 11, 151}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 214, 53, 21, 101, 112, 95, 197, 16, 229, 254, 57, 64, 201}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 244, 189, 52, 161, 125, 20, 255, 80}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 192, 158, 196}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 94, 31, 244}, 11}, {{156, 39, 96, 0, 0, 0, 70, 40, 32, 35, 149, 78, 88, 165, 15, 186}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 158, 44}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 240, 211, 126, 3, 131, 41, 9, 175}, 11}, {{156, 39, 96, 37, 22, 200, 78, 144, 11, 201, 16, 179, 209, 14, 205, 254}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 175, 14, 155}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 147, 29, 53, 50, 80, 133, 243}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 189, 129, 22, 138, 129, 203, 243, 78, 254, 251, 134, 0}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 253, 103, 254, 236, 200, 54, 161, 93}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153, 197, 78, 5}, 11}, {{156, 39, 96, 0, 193, 42, 134, 210, 134, 126, 44, 152, 77, 164, 53, 170}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 224}, 11}, {{156, 39, 96, 0, 155, 239, 44, 89, 38, 202, 96, 49, 72, 159, 90, 89}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 11}, {{156, 39, 96, 180, 45, 184, 124, 200, 191, 177, 155, 216, 64, 52, 102, 26}, 11}, {{156, 39, 96, 0, 0, 0, 0, 197, 227, 16, 34, 110, 64, 211, 241, 213}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 68}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 248, 68, 231}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 11}, {{156, 39, 96, 0, 74, 236, 201, 152, 213, 68, 171, 229, 98, 188, 132, 107}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 183, 167, 228, 63, 48, 62, 221, 77}, 11}, {{156, 39, 96, 0, 0, 0, 0, 29, 132, 8, 130, 102, 83, 97, 98, 29}, 11}, {{156, 39, 96, 0, 0, 0, 197, 130, 24, 102, 167, 155, 166, 243, 177, 93}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 82, 178, 200, 172, 195, 239, 225, 172}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 4, 225, 46, 67, 62}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11}, {{156, 39, 96, 183, 118, 149, 156, 166, 108, 174, 126, 232, 248, 111, 137, 76}, 11}, {{156, 39, 96, 0, 0, 177, 46, 169, 236, 246, 233, 122, 120, 58, 159, 232}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 174, 114, 66, 189, 69, 21, 95}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 7, 121, 21, 144, 153, 175}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 33, 156, 164, 235, 217, 113, 40}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 108, 14, 75, 236, 38}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 83, 176, 237, 118, 65, 211}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 106, 24}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 221, 132}, 11}, {{156, 39, 96, 0, 0, 0, 0, 62, 229, 182, 37, 30, 205, 207, 123, 150}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 0, 206, 240, 125, 223, 87, 3, 47}, 11}, {{156, 39, 96, 0, 0, 0, 0, 0, 29, 37, 135, 122, 66, 147, 239, 212}, 11}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 76}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 3, 35, 180, 12, 130, 212, 125}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 164, 210, 205}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 194}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 56, 175, 181, 201, 97, 189, 138, 195}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 36, 15, 223, 35}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 18}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 145, 196, 52, 81, 118}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 196, 159, 69, 104, 90, 102}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 236, 68, 145, 99, 118}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 223, 118, 145}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 123, 11}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 12, 83, 49, 103, 25, 209, 212}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 54, 109}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 197, 218, 99, 90, 69, 136}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 162, 162, 77, 115, 253, 97, 145, 64}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 50, 191, 23, 32, 99, 180}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 237, 77, 30, 177, 177, 218}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 252, 96, 244, 226}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 100, 83, 190}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 53, 62, 146, 12, 147, 93, 189, 204}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 8, 171, 204, 95}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 216, 200}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 172, 141, 255, 246, 247, 36, 15}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 230, 115, 212}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 100, 25, 136}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 63, 125}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 206}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 161, 248, 177, 84}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 158}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 218, 175, 205}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 156, 31, 110, 189}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 89, 246, 252}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 189, 198, 85, 65, 97, 154, 174}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 6}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 5, 65}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 186, 208, 155, 76, 33, 98, 248, 166}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 110, 236, 45, 90, 124, 250, 144}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 149, 52, 123, 126}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 206, 1, 10, 64, 20}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 142, 157, 45, 119}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 49, 111, 15, 235, 183}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 246, 1, 3, 60, 206, 171, 162}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 208, 245, 217, 208, 78}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 197, 162, 93, 230}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 215, 14}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 131, 36, 27, 126, 63, 165}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 4, 79}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 153}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 78, 252, 135, 138, 127, 234, 102}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 161, 5, 45, 179, 45, 51}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 48, 252, 104}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 210, 99}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 212, 48, 151}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 156, 137, 206, 236, 36}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 207, 253, 167, 208, 180, 32, 120}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 120, 20, 18, 15, 91, 65}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 53, 238, 213, 199}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 184, 206, 237, 202, 107}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 22, 178, 134, 188}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 231, 184, 137, 205, 192}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 252, 200, 157, 166, 43, 217, 190, 3}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 162, 249, 65}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 54, 208, 121}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 157, 47}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 19, 174, 190, 244}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 255, 35, 97, 135}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 165, 13, 34, 13, 163, 170, 224}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 144, 159, 177, 30, 247}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 26, 54, 26, 37, 108}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 49, 37}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 88, 100, 120}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 198, 38}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 144, 115}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 99, 49}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 121, 104, 221}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 20, 222, 89}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 163, 47}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 102, 244}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 119, 216, 231, 254, 108, 7, 8, 251}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 234, 47, 22, 183, 57, 188, 101, 92}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 97, 144, 57, 233, 186}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 81, 35}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 194, 224, 10, 65}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 5, 121, 48, 211, 230, 99, 66}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 71, 99, 32, 250, 60, 63}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 255, 76, 77, 54, 122}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 229, 211, 113, 73, 90, 248}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 83, 183, 155, 50, 136}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 186, 107, 28, 241, 169}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 125, 182, 28, 21, 131, 229, 25}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 70, 230, 155, 70, 9}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 254}, {{92, 188, 82, 192, 142, 249, 190, 128, 216, 36, 37, 56, 178, 93, 82, 193}, 254}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 131, 82}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 111, 82, 127, 226}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 146, 240, 169}, 95}, {{253, 218, 181, 46, 134, 144, 0, 113, 92, 225, 254, 41, 77, 153, 118, 232}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 63, 53, 19, 67, 54, 197, 10}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 95}, {{253, 218, 181, 46, 134, 144, 0, 199, 112, 188, 5, 7, 216, 24, 9, 133}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 94, 2}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 118, 249}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 212, 239, 128, 123, 21, 202}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 143, 191}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 156, 103, 18, 166, 19, 9, 47}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 117, 143, 217, 128, 69}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 143, 20, 149, 105}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 152, 198, 67, 162}, 95}, {{253, 218, 181, 46, 134, 144, 0, 46, 30, 63, 180, 95, 199, 187, 220, 10}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 197, 106, 83}, 95}, {{253, 218, 181, 46, 134, 144, 0, 238, 10, 35, 89, 165, 165, 241, 2, 169}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 61, 163, 211}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 131, 231, 216, 237, 30, 21, 244, 225}, 95}, {{253, 218, 181, 46, 134, 144, 42, 233, 136, 2, 74, 176, 225, 83, 47, 79}, 95}, {{253, 218, 181, 46, 134, 144, 0, 84, 13, 222, 45, 35, 39, 3, 103, 95}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 26, 90, 39, 65, 41, 228, 8}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 197, 33, 68, 154, 171, 184, 67}, 95}, {{253, 218, 181, 46, 134, 144, 0, 25, 182, 7, 117, 27, 132, 155, 191, 47}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 61, 194, 243, 71}, 95}, {{253, 218, 181, 46, 134, 144, 0, 107, 89, 192, 36, 134, 24, 115, 69, 6}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 10, 128, 148, 210, 111}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 31, 242, 19, 99}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 220, 239, 69, 188, 254, 226, 154, 188}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 239, 70, 47, 48, 119, 8}, 95}, {{253, 218, 181, 46, 134, 144, 0, 109, 35, 36, 224, 97, 212, 161, 199, 26}, 95}, {{253, 218, 181, 46, 134, 144, 27, 224, 128, 225, 239, 175, 109, 218, 225, 151}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 37, 167, 94}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 181, 237}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 64, 167}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 224, 16, 0, 181, 52, 229, 244}, 95}, {{253, 218, 181, 46, 134, 144, 205, 80, 88, 120, 253, 183, 17, 136, 18, 183}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 37, 242}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 245, 1, 103, 242, 130, 163, 250, 208}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 255, 0, 58, 124, 116, 218}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 24, 197}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 38, 34, 241, 48}, 95}, {{253, 218, 181, 46, 134, 144, 0, 246, 210, 50, 150, 231, 167, 78, 250, 11}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 199, 210, 250, 201, 181, 242}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 215, 136, 193, 12, 149, 137, 25, 158, 102}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 145, 26, 194}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 23, 186, 216, 147, 32, 24}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 209, 138, 180}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 246, 62, 140, 216, 209, 218, 45}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 221, 218, 62}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 36, 119}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 27, 211, 202}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 221, 37, 4, 42, 177}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 209, 122, 100, 165, 190, 4, 213, 223}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 93, 70, 42, 80}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 181, 96, 85, 32}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 22, 128, 218, 63, 168, 163}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 121, 222, 93, 183, 113, 174, 168, 142}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 146, 93, 3}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 212, 109, 213, 26, 143}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 209, 245, 141}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 12, 81}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 154, 171, 217, 82, 8}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 5, 198, 227, 207, 173, 129, 144, 172}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 242, 37, 74, 80, 68, 27, 222, 255}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 69, 161}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 33, 222, 79}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 212, 179, 224, 139, 78, 62}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 96, 180, 137, 140, 185, 147, 167}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 48, 129, 188, 220, 184, 124, 35}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 219, 229, 186, 188, 137}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 143, 166, 11, 175, 209, 21, 73, 2}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 255, 21, 110, 117, 189, 32, 196}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 62, 219, 105}, 95}, {{253, 218, 181, 46, 134, 144, 0, 206, 5, 239, 136, 147, 173, 131, 214, 102}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 147, 254, 90, 234, 227, 55}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 142, 154}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 83, 110, 14, 42, 108, 37, 150}, 95}, {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 236, 33, 4, 3, 230}, 95}, {{189, 19, 31, 244, 80, 0, 230, 11, 177, 190, 152, 150, 24, 222, 41, 122}, 8}, {{189, 19, 31, 244, 80, 0, 0, 253, 163, 102, 21, 228, 147, 187, 186, 163}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 181, 223, 181, 124, 249, 173, 194, 210}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 146, 236, 77, 66}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 94, 36, 108, 9, 218, 118, 190, 99}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 161, 114, 40, 4, 15, 8, 0, 104, 203}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 78, 80, 168}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 227, 15, 124, 160}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 13}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 80, 144, 95, 211, 10, 137}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 118, 133, 4, 140, 110, 63, 203, 170}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 198, 202, 87, 98}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 176, 206, 122, 142, 5, 127, 107, 226}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 118, 70, 247}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 105, 104, 176, 173, 139, 200, 94}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 96}, 8}, {{189, 19, 31, 244, 80, 0, 120, 248, 36, 169, 174, 84, 79, 196, 212, 87}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 38, 100, 106}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 36, 23, 250, 204, 239, 187, 242}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 156, 127, 121, 126}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 206}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 157, 78, 98, 81, 216, 101, 242, 113}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 61}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 176}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 6, 179, 168, 223, 130}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 246, 119, 172, 147, 89, 88}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 74, 91, 248, 187}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 36, 102, 92, 189, 255, 73, 109}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 131, 138, 104, 20}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 232}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 229, 52, 43, 187, 29, 109}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 123, 168, 167, 154, 239, 234, 122, 31}, 8}, {{189, 19, 31, 244, 80, 0, 0, 12, 232, 75, 144, 99, 61, 164, 137, 176}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 117, 39, 48, 51, 21}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 33, 70, 167, 252}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 48, 40, 68}, 8}, {{189, 19, 31, 244, 80, 0, 0, 13, 71, 78, 92, 181, 33, 46, 165, 213}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 2, 232, 64, 42, 41, 12}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 245, 124, 135, 4, 183, 154}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 155, 53, 186, 251, 74, 2}, 8}, {{189, 19, 31, 244, 80, 0, 193, 5, 48, 26, 41, 152, 226, 115, 241, 189}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 218, 1, 123, 43, 84, 204, 91, 240}, 8}, {{189, 19, 31, 244, 80, 0, 0, 241, 238, 114, 169, 9, 171, 153, 93, 135}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 167, 105, 128, 235, 28, 216, 7}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 63, 133, 247, 195, 174, 128, 193}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 215, 212, 247, 141, 67, 74, 2}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 78, 54, 231, 218, 186, 114, 188}, 8}, {{189, 19, 31, 244, 80, 0, 107, 71, 255, 111, 223, 46, 149, 48, 35, 147}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 138}, 8}, {{189, 19, 31, 244, 80, 0, 224, 240, 250, 203, 52, 172, 165, 187, 140, 117}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 20, 244, 182, 16}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 145, 100, 250, 169, 233}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 227}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 115}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 149, 124, 182, 114, 103, 198}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 70, 245, 119, 16, 59}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 143, 247, 215, 152}, 8}, {{189, 19, 31, 244, 80, 0, 15, 51, 160, 108, 107, 13, 35, 20, 62, 127}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 27, 235, 248}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 132, 45, 224, 244, 124}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 193, 224, 189, 155, 149, 104, 165, 218}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 229, 206, 217, 1}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 231, 91, 233, 182, 67, 190, 49, 81, 172}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 53, 59, 100, 46, 192, 63, 137}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 10}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 170, 65, 161, 251, 148}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 207, 138, 24, 184}, 8}, {{189, 19, 31, 244, 80, 0, 0, 234, 182, 250, 199, 126, 77, 254, 18, 133}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 45}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 167, 15, 83, 13, 250, 229}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 72, 212, 175, 235, 113, 182}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 137, 242, 139, 100, 25}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 215, 126, 118, 56, 57, 24}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 62}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 32}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 10, 232, 125, 239, 52}, 8}, {{189, 19, 31, 244, 80, 0, 0, 15, 26, 60, 138, 133, 243, 132, 110, 75}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 146, 10, 88}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 146, 139, 59, 1, 117, 121, 219, 248}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 26, 111, 254}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 223, 85, 81, 116, 108, 129, 87}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 0}, 8}, {{189, 19, 31, 244, 80, 0, 0, 56, 31, 7, 129, 167, 21, 165, 134, 251}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 121, 75, 170, 82, 32, 49, 231, 216}, 8}, {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 177, 83, 32, 38}, 8}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 27, 227, 46, 252, 42, 132}, 212}, {{30, 116, 0, 0, 0, 0, 43, 166, 0, 98, 46, 246, 162, 108, 46, 16}, 212}, {{30, 116, 0, 0, 0, 172, 152, 250, 54, 196, 225, 183, 101, 102, 69, 143}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 212}, {{30, 116, 0, 0, 106, 30, 46, 210, 206, 148, 176, 58, 208, 181, 177, 223}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 222, 134, 32, 25}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 48, 115, 89, 242, 142, 164}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 206}, 212}, {{30, 116, 0, 0, 84, 164, 249, 140, 134, 184, 78, 234, 54, 65, 158, 134}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 166, 22, 38, 148}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 122, 123}, 212}, {{30, 116, 0, 0, 0, 0, 0, 111, 77, 97, 50, 2, 65, 230, 91, 223}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 68, 227, 78, 108, 219, 231, 121, 93}, 212}, {{30, 116, 0, 0, 109, 253, 240, 199, 157, 42, 118, 160, 115, 119, 186, 36}, 212}, {{30, 116, 0, 0, 0, 0, 139, 82, 38, 204, 139, 53, 178, 138, 75, 232}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 199, 7, 97, 180, 21, 97, 115}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 112}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 170, 60, 226, 42}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 89, 49, 250, 210, 180, 109}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 212, 74, 130, 149, 187, 246, 210}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 95, 183, 52}, 212}, {{30, 116, 0, 0, 164, 160, 141, 196, 4, 160, 148, 224, 202, 165, 156, 170}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 66, 195, 90, 70, 188, 117, 152, 203, 165, 46, 213, 138, 255, 166}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 80, 248, 23, 174}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 212}, {{30, 116, 0, 0, 0, 0, 161, 114, 119, 65, 30, 47, 54, 97, 239, 117}, 212}, {{30, 116, 0, 0, 0, 0, 0, 135, 135, 216, 106, 62, 248, 202, 164, 161}, 212}, {{30, 116, 0, 0, 171, 18, 184, 199, 185, 254, 37, 114, 129, 233, 207, 198}, 212}, {{30, 116, 0, 0, 0, 131, 40, 126, 110, 148, 137, 216, 251, 130, 117, 93}, 212}, {{30, 116, 0, 0, 0, 0, 15, 39, 223, 2, 57, 67, 209, 166, 90, 142}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 0, 0, 0, 0, 0, 25, 198, 174, 249, 236, 230, 124, 109, 160}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 0, 0, 0, 174, 248, 210, 121, 101, 86, 89, 107, 93, 93, 4}, 212}, {{30, 116, 0, 0, 0, 0, 57, 108, 239, 194, 103, 59, 33, 196, 251, 145}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 122, 14, 30, 57}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 116, 199}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 14, 34, 238, 108, 134, 1, 172}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 252}, 212}, {{30, 116, 0, 11, 46, 25, 52, 108, 71, 32, 97, 19, 142, 70, 222, 100}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 34}, 212}, {{30, 116, 0, 0, 223, 239, 16, 219, 222, 242, 194, 97, 48, 213, 26, 168}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 240, 105, 14, 48, 225, 30}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 79, 216, 212, 71}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 75, 114}, 212}, {{30, 116, 0, 51, 41, 189, 207, 5, 44, 116, 205, 119, 47, 215, 166, 38}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 2, 176, 211, 176, 217, 90, 248, 199, 121, 159, 193, 14, 185, 57}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 9, 77, 202, 52, 127, 147, 161, 128}, 212}, {{30, 116, 0, 0, 0, 0, 102, 218, 189, 206, 114, 176, 192, 151, 239, 138}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 50, 196, 249, 51, 234, 229, 113, 216}, 212}, {{30, 116, 0, 0, 124, 26, 78, 192, 109, 146, 161, 204, 124, 20, 44, 89}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 98, 75, 88, 245, 36, 30, 215, 24}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 150, 31, 210, 35, 100, 171, 117}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 244, 8}, 212}, {{30, 116, 0, 0, 0, 0, 0, 38, 47, 114, 45, 51, 235, 145, 170, 254}, 212}, {{30, 116, 0, 55, 65, 29, 233, 113, 80, 215, 190, 114, 232, 238, 163, 107}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 150, 129, 134, 31, 212, 174, 67}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 83, 224, 177}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 38, 153, 132, 73, 230, 145, 8, 113}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 217, 184}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 84, 0, 36, 6, 121, 129, 32, 166}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 167, 38, 243, 164}, 212}, {{30, 116, 0, 240, 89, 40, 190, 38, 225, 102, 121, 207, 102, 23, 75, 217}, 212}, {{30, 116, 0, 0, 0, 0, 0, 20, 55, 249, 37, 61, 230, 247, 181, 81}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 39, 234, 13, 36, 102, 201}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 194, 236}, 212}, {{30, 116, 0, 0, 0, 0, 0, 174, 242, 121, 241, 6, 17, 239, 147, 90}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43}, 212}, {{30, 116, 0, 0, 113, 244, 65, 170, 89, 129, 155, 149, 58, 175, 8, 72}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 62, 145, 192, 239, 117, 183}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 107}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 22, 181, 104, 225}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 201, 99}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 3}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 143, 37, 155, 31, 160, 203}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 161}, 212}, {{30, 116, 0, 123, 50, 97, 13, 25, 210, 245, 221, 232, 205, 148, 95, 32}, 212}, {{30, 116, 0, 0, 0, 0, 183, 211, 71, 193, 76, 252, 125, 94, 115, 233}, 212}, {{30, 116, 0, 238, 31, 116, 67, 101, 242, 90, 246, 150, 214, 197, 48, 221}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158, 199}, 212}, {{30, 116, 0, 0, 27, 254, 35, 114, 66, 85, 173, 215, 5, 250, 28, 11}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 187, 113, 52, 156}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 0, 0, 0, 0, 0, 185, 86, 122, 207, 25, 82, 35, 98, 209}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 212}, {{30, 116, 0, 64, 81, 242, 114, 181, 115, 50, 140, 48, 98, 193, 82, 58}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 25, 109, 88, 129}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 189}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 233}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 98, 138, 246}, 212}, {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 247, 156}, 212}, {{30, 116, 0, 0, 242, 7, 185, 224, 78, 77, 61, 133, 39, 194, 3, 168}, 212}, {{30, 116, 0, 0, 40, 252, 9, 46, 145, 111, 81, 124, 10, 126, 20, 13}, 212}, {{30, 116, 0, 0, 0, 208, 43, 147, 134, 158, 107, 30, 150, 140, 65, 179}, 212}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 185, 118, 95}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 150}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 178, 113}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 68, 74, 198}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 33, 59}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 119, 232, 143}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 165, 179}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 233, 76, 51}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 181, 85, 72}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 199}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 154, 197}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 69, 207}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 59, 57}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 188, 97, 50}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 38, 97}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 158, 219}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 87, 197}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 168, 10}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 213, 87, 202}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 123}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 207}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 74, 27, 77, 154}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 56, 162}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 200}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 246, 219, 131, 95}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 9, 5, 204}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 21, 1}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 255}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 113}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 100, 27, 123}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 147, 89}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 3, 57, 235}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 83}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 92, 136}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 40, 182, 69}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 163}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 75}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 106}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 137, 87, 213}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 252}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 41, 206, 189}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 22, 211}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 220, 2, 173}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 27}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 103, 97, 55}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 93, 96, 92}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 150}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 56}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 187, 146}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 236, 168}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 148, 91}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 227, 51, 62}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 4}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 213, 33, 102}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 173}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 247}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 174, 64, 32}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 184, 185, 231}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 114}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 98, 14, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 153}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 226, 66}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 115, 185}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 144, 225, 166}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 244, 106, 7}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 192, 218, 83}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 176, 242, 244}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 72, 127, 79}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 177, 168}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 175}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 77, 21}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 208}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 142}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 202, 54, 68}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 40, 200, 94}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 222}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 68, 119, 205}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 230, 164, 56}, 217}, {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 38, 52}, 217}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 35, 59, 228, 21, 203, 1}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 240, 3, 178, 192, 64}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 253, 179, 26, 203, 2, 73, 122}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 246, 251, 91, 98}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 81, 223, 92, 0, 67, 221}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 168, 191, 189, 99}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 164, 166, 60, 178}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 32, 43}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 141, 2, 119, 22}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 55, 66, 219, 161, 149, 58, 116, 133}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 87, 245}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 86, 101, 159, 184, 66, 159, 213}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 251, 180, 236, 194, 164}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 251, 168, 228}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 215, 149, 203, 72, 154}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 240, 85, 244, 123, 25, 246, 63, 102}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 91, 248, 3, 178, 21, 213, 215, 69}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 111, 199, 53, 218, 13}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 83, 132, 53, 226, 197}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 42, 107, 210, 135, 10}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 70}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 206, 17, 113, 139, 31, 178, 160}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 122}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 23, 46, 59, 227, 137, 74, 144}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 73, 126, 211, 218, 47, 85}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 99, 223, 38, 4, 243, 90, 19, 13}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 11, 18, 152, 90, 245, 214}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 242, 32, 224, 55}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 156, 100, 250, 151, 2, 253, 10, 207}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 65, 182, 124, 88, 95, 42}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 13, 202, 237, 198, 110, 188, 205, 147}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 200, 250, 206, 226, 143}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 177, 205, 233}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 184, 57, 37, 109, 85, 222, 38}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 118, 94, 7, 232, 46}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 211}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 203, 231, 76, 73, 175}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 135, 176, 90}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 84, 8, 186, 148, 227}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 252, 166}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 77, 136}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 150}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 115, 59, 87, 190, 241, 123, 33}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 4, 170, 196}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 16, 255}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 237, 146, 21, 209, 132, 127, 201}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 118, 165, 175, 255}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 27, 183, 64}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 48, 143, 12}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 129, 13, 107, 25, 188, 44}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 177, 154, 128, 30, 76}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 134, 145, 193, 129, 23, 31}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 17, 81}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 225, 215, 123, 171, 9}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 94, 144, 160, 234, 37, 225}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 223, 138, 134, 82, 92, 199}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 186, 152, 128, 226, 214, 118, 112}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 2, 31, 172, 39, 11}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 34, 47, 179}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 215, 208, 251, 199, 160, 15, 68, 214}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 186, 149, 180, 189, 23, 222, 174, 152}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 146, 106, 99}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 96, 145, 160, 72, 244, 72}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 225, 215, 147, 104, 75, 81, 229}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 27, 31, 244, 125, 194, 80}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 183, 91, 34, 243, 99, 163, 140, 159}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 234, 45, 23, 217, 72, 194}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 214, 135, 70, 150, 47}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 9, 162, 253, 5}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 189, 158, 73}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 105, 247, 253, 217, 84, 237, 128, 209}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 177, 254, 162, 111, 118, 218, 221}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 169, 207, 25, 166, 165}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 164, 41, 164, 91, 72}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 194, 89, 130, 127}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 15, 6, 201, 148, 114, 27, 180}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 182, 123, 87, 185}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 21, 186, 177, 97, 106}, 15}, {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 228, 185, 137, 147, 90}, 15}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 145, 187}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 90, 92}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 250, 235, 24, 237}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 188}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 155, 34, 220}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 127, 3, 3}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 109, 53, 238, 198, 181}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 97}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 36, 48}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 14}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 167}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 65, 55, 245}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 181}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 39, 74}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 87}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 211}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 246, 252, 104, 76, 140}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 15, 238}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 123, 96, 176, 225}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 15}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 38, 103, 56, 38}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 152, 77}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 42, 107, 241}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 123, 16}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 23, 111, 121, 181}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 30, 73, 63, 219, 191}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 1, 61, 147, 142}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 224, 21, 91, 224}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 231}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 36}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 192, 31, 58}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 153}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 48}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 6, 101, 41, 36}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 147, 33}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 32, 159}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 170, 107, 97, 27, 190}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 211}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 156}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 168, 197, 73}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 109, 122}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 246, 251}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 182}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 119, 220, 249}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 159}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 26, 174}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 59, 222, 209, 148}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 74}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 234}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 237, 248}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 6, 28}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 63, 242}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 215, 165, 160}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 29, 207}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 18}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 63, 216, 88}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 183, 243, 224, 84}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 128, 160}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 84, 226, 201, 242}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 97, 57}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 214, 114}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 184, 253}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 15, 149}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 246, 113, 92, 66, 11}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 149, 62, 168}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 185, 81, 169, 155, 147}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 5, 166, 234, 103, 35}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 49, 150}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 121, 5, 85}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 29}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 141, 69, 233}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 89, 113, 57, 18}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 183}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 120}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 83, 76, 251, 178}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 118, 82, 12, 166, 41}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 209, 77, 157, 37}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 243, 81, 1, 180}, 66}, {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 184, 63}, 66}, {{68, 210, 158, 64, 18, 188, 221, 219, 215, 32, 123, 255, 248, 119, 163, 212}, 122}, {{68, 210, 158, 64, 0, 0, 0, 245, 245, 76, 46, 244, 239, 29, 83, 10}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 78, 224, 183, 16, 68, 140, 111, 44}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 203}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 208, 15}, 122}, {{68, 210, 158, 64, 0, 3, 0, 183, 230, 164, 73, 27, 16, 122, 59, 104}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 191, 175}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247}, 122}, {{68, 210, 158, 64, 0, 0, 218, 142, 53, 146, 147, 115, 34, 209, 154, 232}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 192, 135, 226, 35, 251, 69, 177, 61}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 251}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 42, 202}, 122}, {{68, 210, 158, 64, 181, 212, 204, 70, 173, 155, 47, 114, 16, 249, 176, 154}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 103, 243, 81, 17, 60}, 122}, {{68, 210, 158, 64, 0, 65, 31, 136, 1, 187, 137, 148, 88, 23, 153, 64}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 11}, 122}, {{68, 210, 158, 64, 0, 149, 144, 53, 96, 17, 77, 39, 175, 75, 192, 50}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 235}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 128, 238, 230, 126, 180, 42, 250, 136}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 136, 195, 3, 108, 141}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 67}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 163, 119, 144, 182, 72, 211, 75, 28}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 174, 211}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 237, 183, 64, 101, 152, 44, 165}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 139}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 113, 137}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 122}, {{68, 210, 158, 64, 0, 0, 0, 179, 32, 74, 88, 92, 122, 33, 254, 135}, 122}, {{68, 210, 158, 64, 0, 115, 30, 85, 235, 242, 27, 247, 186, 70, 233, 153}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 124, 209, 156, 121, 239}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 202, 219}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 236, 126, 243, 182, 50}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 94, 250, 7, 84, 199}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 83, 186, 44, 52, 234, 1, 91, 225}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 134}, 122}, {{68, 210, 158, 64, 0, 0, 0, 1, 173, 104, 65, 25, 36, 46, 248, 136}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 111, 178, 67, 55, 116, 108, 157, 235, 58, 73}, 122}, {{68, 210, 158, 64, 0, 0, 0, 20, 132, 17, 8, 166, 190, 26, 128, 253}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 90, 148, 80, 248, 216}, 122}, {{68, 210, 158, 64, 0, 0, 0, 112, 20, 65, 226, 248, 170, 186, 197, 19}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 136, 64, 121, 136, 210, 73, 177}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 82, 250, 176, 131, 196, 3}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 122}, {{68, 210, 158, 64, 0, 23, 233, 3, 144, 23, 18, 92, 148, 41, 157, 141}, 122}, {{68, 210, 158, 64, 0, 227, 84, 21, 65, 140, 246, 50, 242, 106, 213, 51}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 231, 34, 153, 209}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 218, 112, 3, 9, 155, 92, 34}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 231, 126, 193, 11, 237, 119, 226, 24}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 15, 131, 1, 235, 211, 238, 138, 133}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 194, 248, 66, 25, 232}, 122}, {{68, 210, 158, 64, 0, 0, 0, 217, 12, 216, 205, 84, 178, 222, 243, 1}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 183, 155, 191, 211}, 122}, {{68, 210, 158, 64, 0, 179, 48, 240, 72, 247, 148, 69, 47, 74, 185, 241}, 122}, {{68, 210, 158, 64, 0, 0, 0, 50, 21, 196, 67, 247, 118, 245, 34, 200}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 119, 172, 93, 254, 175, 26, 181, 76}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 252, 123, 151, 220, 233}, 122}, {{68, 210, 158, 64, 0, 0, 0, 133, 137, 10, 136, 169, 149, 10, 108, 112}, 122}, {{68, 210, 158, 64, 0, 0, 0, 80, 81, 114, 110, 34, 119, 153, 87, 99}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 8, 65, 68, 146, 17}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 250}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 97, 164, 162, 172, 186, 168}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 171, 134, 19, 52, 255, 87, 154}, 122}, {{68, 210, 158, 64, 0, 0, 0, 9, 29, 168, 204, 116, 13, 23, 60, 199}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 201, 227, 161, 40, 83, 157, 11}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 81, 40, 229, 227}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 226, 245, 135, 23, 110, 188, 126}, 122}, {{68, 210, 158, 64, 0, 121, 238, 156, 47, 20, 141, 96, 45, 108, 28, 164}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 31, 160}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 169, 245, 121, 56, 207, 236, 45}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 120}, 122}, {{68, 210, 158, 64, 0, 0, 76, 204, 171, 192, 244, 30, 130, 236, 101, 230}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 88, 73, 86, 232, 136, 143, 8, 71}, 122}, {{68, 210, 158, 64, 0, 154, 131, 233, 46, 232, 68, 29, 192, 29, 60, 31}, 122}, {{68, 210, 158, 64, 0, 0, 0, 211, 160, 154, 225, 137, 194, 25, 86, 130}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 34, 112, 111, 45, 127, 122, 170}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 204, 68, 198, 56, 107, 129, 46, 8}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 59, 84}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 68, 48, 212, 214, 2}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 200, 221}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 254, 240, 165, 4, 137, 82, 108}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 16, 81, 181, 6, 152, 139}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 122}, {{68, 210, 158, 64, 0, 0, 214, 102, 49, 229, 59, 119, 35, 88, 237, 20}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 236, 119, 206, 229}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 196, 105, 116, 165, 177}, 122}, {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 191}, 122}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 192}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 38}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 88, 136, 213}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 158, 48, 204}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 220, 11}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 161}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 60, 23}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 105, 234, 78}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 155, 220}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 248, 7, 67}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 60, 191}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 241, 55}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 53, 86}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 100, 122}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 221}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 160, 196, 98}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 229, 183}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 173, 213}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 166, 203}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 170, 217, 238}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 8}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 58, 137}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 5, 53, 22}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 172, 82, 169}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 235, 12}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 186}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 25, 104, 158}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 51}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 78, 153, 180}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 95, 211}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 58, 177, 52}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 13}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 107, 54}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 144, 184}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 69, 77, 141}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 17, 154}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 171, 156}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 126, 246}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 97, 229, 57}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 201, 24}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 201, 76, 157}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 91, 144}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 118, 121}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 170, 74}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 224, 230, 191}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 5, 226, 251}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 6}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 84}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 248, 124, 215}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 238}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 201, 192, 176}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 89}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 212}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 43}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 171}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 139}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 146, 61, 65}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 147, 53}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 22, 95}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 137, 122, 81}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 226, 210}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 50, 61, 230}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 221, 86}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 182, 108, 204}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 210}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 23, 145, 176}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 11, 175}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 85, 250, 119}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 183}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 206, 26, 12}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 202}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 112, 18, 192}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 113, 202}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 98, 43, 94}, 12}, {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 12}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 187, 135, 184, 175}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 10, 128, 105, 174, 56, 62}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 155}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 91, 60, 89}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 87, 4, 88, 111, 5}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 123, 125}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 117}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 252, 254, 18}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 58, 189}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 149, 151, 127}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 88, 197}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 225, 104, 86, 174}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 133, 177, 95, 52, 9, 8, 181}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 204, 71, 241, 200, 238}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 79, 197, 227, 140}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 150, 89, 217, 69}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 47, 151}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 2, 208, 97, 237, 25, 157}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 139, 212, 154, 113, 102, 50, 77}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 198}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 211, 173}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 182, 168, 198, 26, 78}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 12, 155, 37, 75}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 64, 50, 91, 151}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 80, 110, 79, 144, 121, 27}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 102, 202, 121, 58, 224, 230}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 239, 94, 83, 75, 213}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 54, 223}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 11, 212, 6, 102, 131}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 126, 16, 228, 114}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 125, 101, 58, 246, 209}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 252, 240, 57}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 94, 200, 51, 106, 97, 146}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 110, 28, 37}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 11, 229, 15}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 78, 190, 50}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 209, 250, 214, 203, 181}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 242, 130, 81}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 253, 135}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 57, 195, 233, 75}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 172}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 171, 5}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 127}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 252, 54, 90, 237, 110}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 238}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 136}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 42}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 248, 94, 151, 130}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 243}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 136, 101, 134, 173, 95, 162}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 125, 114, 57}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 231, 68, 77, 69, 140}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 107, 34, 45}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 90, 174, 126, 201}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 189, 96, 250, 68}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 228, 48, 37}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 228, 254, 121}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 177, 253, 163, 255}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 72, 69}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 20, 22, 231}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 50, 131, 66, 191, 255, 123}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 105, 65}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 170, 85, 181, 230, 179}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 250, 191, 246, 19, 47}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 10}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 21, 136, 92, 76}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 64, 97, 244, 241, 154}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 168}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 60, 103, 109, 22, 168, 212}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 169, 67, 132}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 4, 100, 71, 204}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 77, 201, 12, 155, 171}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 91, 146}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 32, 82}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 224, 164}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 38, 39, 59, 120, 82}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 250, 193, 34, 224}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 32, 165, 124, 7, 13, 159}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 140, 232, 161, 65}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 106, 151, 210, 183, 170}, 171}, {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 39, 126, 107, 44}, 171}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 250, 188}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 241, 58}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 167}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 48, 6}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 254, 232}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 32}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 2, 176}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 165}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 175}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 29, 124}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 205, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 121, 125}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 83}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 84}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 120, 198}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 116, 107}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 207, 76}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 50}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 153}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 91}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 2}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 229}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 21}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 46}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 144}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 166, 169}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 26, 58}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 252}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 204}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 234}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 11, 181}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 120}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 242}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 154}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 210, 159}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 140}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 107, 107}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 80, 81}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 115, 205}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 2}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 72}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 183, 113}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 17}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 33, 140}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 180}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 156}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 27}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 159}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 5}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 40, 164}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 120, 47}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 108}, 42}, {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 42}, {{179, 10, 70, 80, 0, 0, 171, 102, 251, 70, 135, 10, 204, 11, 245, 1}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 135}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 104, 15, 202, 22, 147, 129, 197, 56}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 173, 84, 27, 171, 137, 63}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 49, 0, 59, 58, 146, 207}, 194}, {{179, 10, 70, 80, 0, 0, 203, 189, 238, 16, 194, 125, 19, 84, 75, 181}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 144, 8, 108, 220, 188, 80, 140}, 194}, {{179, 10, 70, 80, 0, 0, 0, 110, 189, 67, 18, 70, 172, 111, 250, 83}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 117, 48, 113, 93, 84, 243, 44, 131, 157, 155}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 141, 180, 120, 74, 31, 196}, 194}, {{179, 10, 70, 80, 0, 0, 33, 45, 168, 241, 5, 135, 91, 160, 62, 49}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 39, 20, 138, 162}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 38, 174, 42, 191, 217, 90, 165}, 194}, {{179, 10, 70, 80, 0, 25, 108, 241, 165, 139, 55, 236, 88, 245, 117, 254}, 194}, {{179, 10, 70, 80, 0, 0, 0, 213, 44, 154, 42, 60, 22, 108, 79, 165}, 194}, {{179, 10, 70, 80, 0, 177, 43, 53, 167, 42, 36, 217, 242, 23, 191, 40}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 38, 177, 13, 179, 52, 48}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 140, 221}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 60, 230, 254, 157, 237, 74}, 194}, {{179, 10, 70, 80, 0, 0, 205, 139, 86, 227, 81, 39, 62, 83, 203, 3}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 199}, 194}, {{179, 10, 70, 80, 0, 0, 226, 140, 145, 191, 117, 149, 70, 27, 160, 84}, 194}, {{179, 10, 70, 80, 97, 175, 43, 210, 101, 169, 231, 119, 100, 93, 138, 163}, 194}, {{179, 10, 70, 80, 102, 140, 62, 222, 242, 52, 101, 52, 146, 217, 107, 81}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 133, 67, 87, 243, 197, 206, 211}, 194}, {{179, 10, 70, 80, 0, 204, 208, 181, 151, 118, 155, 88, 73, 82, 236, 2}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 100, 60, 37, 130}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 193, 240, 77, 224, 173, 195, 97, 180}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174}, 194}, {{179, 10, 70, 80, 0, 114, 92, 213, 118, 94, 29, 133, 18, 96, 213, 247}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 19, 194, 73, 147, 201, 98, 128}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 25, 94}, 194}, {{179, 10, 70, 80, 0, 4, 120, 99, 167, 22, 179, 219, 47, 151, 249, 192}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 6, 175, 211, 115, 107}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 14}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 200, 58, 105, 188}, 194}, {{179, 10, 70, 80, 0, 183, 49, 210, 168, 137, 86, 37, 175, 95, 208, 55}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 143}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 169, 22, 75, 218}, 194}, {{179, 10, 70, 80, 0, 0, 36, 173, 147, 46, 148, 98, 82, 158, 169, 30}, 194}, {{179, 10, 70, 80, 0, 0, 0, 51, 144, 242, 186, 9, 237, 114, 199, 4}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 150, 225}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 50, 4, 189, 80, 47, 162}, 194}, {{179, 10, 70, 80, 0, 0, 36, 227, 63, 242, 212, 95, 83, 231, 66, 224}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 102}, 194}, {{179, 10, 70, 80, 0, 0, 155, 181, 189, 197, 229, 22, 183, 45, 147, 57}, 194}, {{179, 10, 70, 80, 0, 251, 252, 209, 94, 29, 112, 168, 179, 43, 62, 14}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 113}, 194}, {{179, 10, 70, 80, 0, 0, 0, 63, 231, 88, 58, 218, 34, 158, 140, 116}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 50, 41, 219, 44}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 32, 251, 228, 120, 237, 188, 61}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 104, 175, 126, 121}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 94}, 194}, {{179, 10, 70, 80, 0, 0, 255, 79, 139, 50, 17, 5, 98, 90, 58, 186}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 225, 10, 49, 249, 123}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 166, 53, 58, 220, 37, 67, 52, 83, 154, 28}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 245, 140, 59, 225, 169, 184, 161, 96}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 196, 178, 47, 161, 81, 42, 150}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 21, 37}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 123, 163}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 158, 99, 56, 120, 215, 228}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 233, 253, 49, 152, 178}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 194}, {{179, 10, 70, 80, 38, 63, 3, 223, 254, 200, 37, 1, 8, 58, 65, 239}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 176, 141, 4, 220, 98}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 117}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 124, 167, 35, 164, 123, 234, 65}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 201}, 194}, {{179, 10, 70, 80, 0, 0, 242, 113, 148, 147, 104, 233, 154, 53, 44, 162}, 194}, {{179, 10, 70, 80, 0, 184, 192, 104, 68, 65, 66, 204, 98, 62, 70, 38}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 176, 77, 206, 14}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 61, 14, 33, 31}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 152, 204, 89, 114, 15}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 205, 160, 66, 193, 208, 208, 34}, 194}, {{179, 10, 70, 80, 0, 0, 8, 152, 109, 198, 187, 15, 3, 235, 106, 69}, 194}, {{179, 10, 70, 80, 0, 0, 0, 69, 196, 204, 137, 41, 115, 89, 135, 246}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 245}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 160, 27, 45, 228, 46, 31, 58}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 77, 80, 151, 74, 215, 246}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 242, 140, 176, 137, 140}, 194}, {{179, 10, 70, 80, 0, 0, 0, 58, 22, 209, 127, 104, 12, 148, 132, 55}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 32, 184, 49, 145, 231, 193, 105, 152, 211}, 194}, {{179, 10, 70, 80, 0, 150, 0, 225, 128, 149, 229, 102, 241, 153, 179, 35}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 143, 79, 55, 246, 128, 155}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 194}, {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 239}, 194}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 188, 255}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 239, 219}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 100, 200}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 117}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 61}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 112}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 185, 254}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 192}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 167, 215}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 249}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 175}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 95}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 229}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 37, 103}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 223}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 110, 10}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 157}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 78}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 246, 195}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 197}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 168, 120}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 246}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 34, 220}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 165, 1}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 112, 205}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 151}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 49}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 16, 39}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 188}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 192, 123}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 39, 119}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 7, 101}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 57}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 42}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 96}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 72, 120}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 162}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 25}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 88, 44}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 180}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 157}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 192}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 67}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 171}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 122, 225}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 213, 163}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 86}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 17, 60}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 240}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 33, 196}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 169}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 77}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 237}, {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 29}, 237}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 93, 51}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 84, 214, 62}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 65, 246, 90, 153}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 204}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 249, 250, 96}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 78, 235}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 57}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 54, 58, 114}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 155}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 182, 3, 111}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 139}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 179, 165, 156}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 208, 67, 200}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 252, 113, 147}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 236, 252, 65}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 149, 111}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 96, 98, 248}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 6}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 208, 213, 121, 117}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 206, 70, 133}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 145, 205}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 16}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 159, 55, 13}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 157, 141, 143}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 77, 245}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 165}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 62, 14, 6}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 120}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 156, 52}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 57}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 209}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 183, 121}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 203, 147, 98}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 202, 249, 15, 93}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 204}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 54}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 206, 168, 80, 45}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 55, 100, 85}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 237, 250, 140}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 204, 83, 141}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 176, 89, 155}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 167, 142}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 80}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 186, 209}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 81, 253, 201}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 181, 156, 116}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 80, 94, 199}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 25, 126, 161}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 138}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 160}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 168, 164}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 199, 6, 143}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 61, 48}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 149, 118}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 224, 66, 184}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 149, 202}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 227, 86, 117}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 190, 84, 140}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 192, 192, 134}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 77}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 35, 187}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 163, 66, 40, 92}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 206}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 149, 18}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 89, 157, 69}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 103, 232}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 110, 121, 92}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 55, 91}, 151}, {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 248, 173, 101, 22}, 151}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 3}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 199}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 43}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 52}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 228}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 160}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 49}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 107}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 24}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 177, 42}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 201, 191}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 162}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 178}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 127}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 136}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 193}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 165}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 184}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 247}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 50}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 218}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 22}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 223}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 123}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 50}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 76, 34}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 121}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 55}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 191, 75}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 140}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 227}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 250}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 197}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 57}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 142}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 111, 75}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 99}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 193}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 124}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 53}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 201}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 237}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 154}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 228}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 225, 141}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 234}, 238}, {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 238}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 204, 160, 54, 71, 68, 68}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 53}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 89, 81, 29, 196, 241}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 103}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 249, 199}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 233, 50, 99, 20, 83, 234}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 180, 105, 72, 19, 208, 134, 24, 107}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 15, 138, 82, 75, 160, 175, 57}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 3, 166, 135, 26, 85, 192, 72}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 153, 133, 196, 251, 53, 138, 102}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 33, 13, 191, 69, 39, 10}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 151}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 157, 159, 168}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 67, 236, 216, 171, 23, 44, 235}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 167}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 118, 39, 76, 21, 142, 97}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 167, 179}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 101}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 79, 86, 64, 112, 35, 186, 59}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 176, 120, 244, 214, 71, 160, 64}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 241, 42, 47}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 123, 216, 113, 117}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 102, 161, 114, 4, 71, 129, 49}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 52, 31, 15, 252, 62}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 51}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 155, 97, 168, 125, 217}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 68, 178, 216, 3, 115, 27, 2}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 182, 234, 190, 152, 202}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 61, 91}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 189, 22, 206, 182, 9}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 243, 86}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 132, 51, 65, 34, 38}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 150, 167, 106, 72, 155, 124, 176}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 191, 253}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 205, 195, 39, 221, 108, 38, 16, 89}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 176, 73, 53, 24}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 188, 4, 54, 4, 161, 173, 45}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 229}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 213, 240}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 26, 202, 128}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 77, 253, 8, 217, 142, 2, 71, 155}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 47, 168, 61, 30, 75}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 127, 36, 55, 174, 183}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 147, 102}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 109, 15}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 222, 234, 190, 119}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 183}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 209, 93, 48, 103}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 80}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 230, 58, 97, 211}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 86, 116, 107, 203}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 186, 242}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 106}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 98, 101}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 108, 81, 17, 241, 132}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 153, 158, 161, 153, 44, 245, 76}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 241, 217, 197, 91, 149}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 181, 189, 217, 15, 145, 160, 94}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 163, 101, 186, 205, 231, 208}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 173, 73, 53, 189, 248, 22, 190, 5}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 146, 144, 61, 253, 147, 214}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 133, 254, 91, 136, 213, 147, 25}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 32, 4, 214, 101, 75, 44, 1, 197}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 27, 62, 85}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 141, 22}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 198, 164, 59, 232, 245}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 81, 252, 149, 183, 89, 137}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 143, 105, 191}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 64, 26, 151, 161, 82, 11, 117, 44}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 58, 132, 166, 228, 40, 64}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 53, 37}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 133}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 135, 205, 188}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 22, 71, 31, 15}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 18, 222, 175, 78, 146, 86, 111}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 62, 14, 136, 232, 147, 80}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 167, 154}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 120, 253, 190, 133, 205, 71, 120}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 12, 73, 163, 168, 210, 186, 11}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 108, 202, 140, 89}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 49, 5, 239}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 230, 36, 237, 254, 240, 200}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 189, 195, 135}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 24}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 2, 254, 21, 22, 204}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 126, 167, 135, 164, 11, 204, 2, 88}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 119}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 102, 80, 149, 2, 108}, 128}, {{4, 26, 181, 37, 206, 129, 233, 32, 0, 111, 154, 71, 12, 239, 214, 104}, 128}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 107, 255, 190, 44, 196, 60, 145}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 212}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 27, 100, 69}, 227}, {{81, 58, 248, 0, 0, 0, 0, 26, 156, 175, 98, 84, 239, 57, 0, 44}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 131}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 81, 156, 61, 197, 125, 135, 157}, 227}, {{81, 58, 248, 0, 0, 167, 170, 116, 25, 227, 1, 245, 125, 154, 145, 97}, 227}, {{81, 58, 248, 0, 0, 25, 61, 224, 136, 147, 68, 188, 181, 218, 190, 78}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 161, 19, 238, 130, 107, 224, 235}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 50, 92}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 201, 15, 143, 35, 42}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 31, 243}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 68, 53, 228, 225, 43, 191, 173, 34}, 227}, {{81, 58, 248, 0, 0, 186, 131, 241, 8, 197, 246, 200, 88, 167, 165, 244}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 180}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 249, 137, 137, 46, 189}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 227}, {{81, 58, 248, 0, 32, 102, 204, 201, 17, 55, 43, 81, 142, 219, 194, 248}, 227}, {{81, 58, 248, 0, 0, 50, 51, 154, 83, 126, 174, 15, 220, 163, 116, 232}, 227}, {{81, 58, 248, 0, 0, 0, 0, 26, 123, 93, 85, 30, 164, 87, 126, 47}, 227}, {{81, 58, 248, 0, 0, 0, 0, 21, 196, 34, 74, 206, 89, 75, 214, 64}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 231, 43, 131}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 218, 217, 240, 209, 168, 224, 113, 177}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 108, 229, 141, 238, 96, 244, 130, 218}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 173}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 215, 50, 253}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 43}, 227}, {{81, 58, 248, 0, 0, 0, 33, 82, 164, 100, 92, 221, 58, 214, 239, 4}, 227}, {{81, 58, 248, 0, 0, 0, 0, 221, 250, 107, 228, 159, 65, 233, 110, 241}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 69}, 227}, {{81, 58, 248, 0, 0, 0, 0, 189, 5, 198, 104, 190, 68, 69, 167, 114}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121, 115, 208, 53}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{81, 58, 248, 0, 0, 0, 0, 23, 201, 141, 154, 37, 29, 84, 113, 199}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 58, 188, 217, 218, 110}, 227}, {{81, 58, 248, 0, 0, 241, 193, 5, 147, 131, 145, 254, 3, 143, 95, 54}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 49, 235, 44, 35, 143, 154, 189}, 227}, {{81, 58, 248, 0, 0, 0, 0, 158, 138, 155, 224, 172, 129, 88, 197, 3}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 158}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 103, 144, 68}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 226, 16, 111, 82, 181, 133, 143}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 86}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 191, 222, 76, 155, 138}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 81, 206, 68, 101, 196, 35}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 68, 116, 120, 217, 217, 240, 21}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 139}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, 227}, {{81, 58, 248, 0, 0, 0, 78, 27, 118, 165, 97, 151, 133, 85, 185, 93}, 227}, {{81, 58, 248, 0, 0, 0, 192, 35, 15, 147, 78, 88, 233, 166, 110, 29}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 14, 245, 21, 71, 133, 156, 53, 200}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{81, 58, 248, 0, 246, 12, 191, 131, 72, 37, 238, 234, 235, 229, 238, 110}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 227}, {{81, 58, 248, 0, 0, 0, 0, 172, 138, 64, 209, 240, 39, 113, 198, 105}, 227}, {{81, 58, 248, 0, 249, 103, 168, 65, 141, 59, 60, 152, 128, 98, 44, 141}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 95, 94, 83, 24, 201, 139}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 66}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 107}, 227}, {{81, 58, 248, 0, 81, 50, 238, 164, 74, 187, 191, 109, 181, 30, 126, 125}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 233, 30, 250, 119, 57, 136}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 143, 0, 145, 195, 228, 25}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 174, 157, 85, 238, 11, 240, 162, 203}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 7}, 227}, {{81, 58, 248, 0, 0, 4, 99, 207, 196, 183, 169, 57, 45, 200, 230, 58}, 227}, {{81, 58, 248, 0, 0, 0, 0, 31, 23, 91, 201, 201, 65, 36, 38, 90}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 32}, 227}, {{81, 58, 248, 0, 31, 173, 211, 56, 114, 24, 96, 38, 149, 57, 248, 209}, 227}, {{81, 58, 248, 0, 0, 0, 0, 53, 141, 178, 75, 186, 98, 158, 52, 196}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 185}, 227}, {{81, 58, 248, 0, 242, 253, 37, 75, 245, 129, 117, 36, 171, 59, 169, 127}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 107, 163}, 227}, {{81, 58, 248, 0, 0, 0, 250, 34, 206, 180, 238, 100, 130, 7, 126, 18}, 227}, {{81, 58, 248, 0, 247, 213, 203, 168, 42, 51, 86, 107, 53, 153, 42, 8}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 51, 8, 114, 121, 168, 234, 216, 52}, 227}, {{81, 58, 248, 0, 65, 201, 134, 108, 98, 24, 10, 202, 206, 169, 47, 253}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 69, 11}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 161, 97, 186, 255, 125}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207, 24}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 32}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 227}, {{81, 58, 248, 0, 0, 0, 0, 111, 128, 90, 44, 144, 218, 100, 193, 182}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 179, 147, 75, 124, 18}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 220, 228, 146, 223, 170, 31, 79, 165}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 31, 153, 229, 100, 185, 89, 199, 166}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 217}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 236, 3, 51, 41, 40, 96, 79, 74}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 70, 9, 112}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 132, 191, 67, 40, 106}, 227}, {{81, 58, 248, 0, 0, 0, 0, 219, 226, 152, 233, 44, 127, 70, 23, 30}, 227}, {{81, 58, 248, 0, 0, 0, 0, 53, 152, 130, 155, 198, 109, 188, 215, 172}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 227}, {{81, 58, 248, 0, 0, 0, 0, 0, 156, 192, 239, 165, 121, 74, 198, 159}, 227}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 138}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 67, 213, 146, 65, 233, 217, 24, 178, 49, 12, 168, 136}, 60}, {{31, 128, 0, 100, 78, 172, 166, 170, 65, 44, 190, 236, 3, 44, 157, 107}, 60}, {{31, 128, 252, 110, 81, 96, 145, 129, 112, 193, 18, 222, 21, 167, 208, 221}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 214, 23}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 21}, 60}, {{31, 128, 0, 0, 0, 0, 246, 33, 201, 245, 150, 124, 58, 89, 91, 85}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 208, 109}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 127, 41, 184, 112, 72, 119}, 60}, {{31, 128, 0, 0, 233, 136, 168, 163, 46, 229, 90, 255, 51, 218, 139, 197}, 60}, {{31, 128, 0, 0, 0, 154, 25, 104, 169, 167, 1, 201, 174, 61, 181, 137}, 60}, {{31, 128, 0, 0, 0, 140, 57, 167, 209, 12, 190, 119, 61, 18, 216, 98}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 81, 232, 230, 206, 106, 49}, 60}, {{31, 128, 0, 0, 0, 131, 51, 185, 56, 172, 250, 194, 140, 180, 228, 113}, 60}, {{31, 128, 0, 0, 0, 0, 60, 121, 243, 39, 167, 252, 241, 49, 127, 193}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 118, 38, 173, 203, 1, 10, 118}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 158, 40, 12, 39, 199, 59, 141}, 60}, {{31, 128, 0, 0, 191, 70, 117, 116, 65, 21, 67, 153, 239, 136, 91, 155}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 153, 150, 95, 128, 83, 102, 1}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 246, 199}, 60}, {{31, 128, 0, 0, 190, 13, 223, 43, 181, 173, 68, 1, 152, 195, 229, 119}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79}, 60}, {{31, 128, 10, 127, 81, 11, 234, 191, 78, 125, 45, 206, 196, 35, 229, 107}, 60}, {{31, 128, 0, 0, 0, 0, 223, 150, 43, 231, 132, 118, 164, 105, 24, 255}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, 190, 28}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 48, 240, 167, 33, 204, 155, 87}, 60}, {{31, 128, 0, 0, 0, 0, 18, 131, 214, 114, 75, 109, 251, 207, 228, 152}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 51}, 60}, {{31, 128, 0, 0, 0, 93, 251, 125, 134, 144, 78, 96, 18, 42, 159, 144}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 159, 44, 58, 179, 245, 184, 125, 40}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 240, 246, 174, 167, 120, 183, 170, 109, 234, 226, 252, 127, 58}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 97, 102}, 60}, {{31, 128, 0, 0, 0, 0, 0, 21, 49, 137, 199, 223, 248, 42, 181, 66}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181, 60}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 50, 101, 9}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 38, 199, 192, 201, 75, 120}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 104, 236, 229, 6, 98, 186}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 36, 199, 206, 129, 179, 67}, 60}, {{31, 128, 0, 0, 126, 193, 250, 214, 60, 151, 51, 63, 82, 56, 12, 116}, 60}, {{31, 128, 0, 0, 0, 182, 189, 97, 206, 150, 176, 32, 158, 216, 34, 240}, 60}, {{31, 128, 0, 59, 27, 176, 219, 107, 187, 34, 151, 143, 19, 97, 134, 26}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 173, 24, 23, 176, 239, 9, 244, 217}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 78, 49, 124, 246, 4, 108, 53, 216}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 56, 140}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 30, 114}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 215}, 60}, {{31, 128, 0, 145, 94, 90, 148, 245, 62, 222, 177, 221, 214, 36, 144, 207}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 80, 144, 208}, 60}, {{31, 128, 135, 56, 72, 253, 49, 34, 171, 115, 166, 53, 46, 35, 90, 106}, 60}, {{31, 128, 0, 0, 222, 33, 107, 10, 99, 158, 3, 9, 74, 49, 94, 239}, 60}, {{31, 128, 0, 0, 0, 0, 0, 77, 249, 125, 33, 169, 75, 251, 141, 217}, 60}, {{31, 128, 152, 34, 255, 222, 42, 78, 167, 16, 156, 6, 140, 194, 137, 102}, 60}, {{31, 128, 0, 0, 0, 0, 92, 98, 132, 194, 191, 111, 62, 193, 245, 197}, 60}, {{31, 128, 208, 158, 56, 49, 54, 168, 237, 21, 80, 88, 58, 61, 169, 49}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230}, 60}, {{31, 128, 0, 0, 84, 180, 212, 195, 66, 227, 95, 40, 66, 222, 218, 82}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 64, 68, 99, 136, 140, 82}, 60}, {{31, 128, 0, 0, 0, 0, 252, 65, 76, 76, 131, 143, 230, 191, 248, 147}, 60}, {{31, 128, 0, 0, 162, 194, 227, 13, 26, 19, 139, 143, 243, 162, 90, 215}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 182, 197, 215}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 239, 137, 221, 183}, 60}, {{31, 128, 0, 0, 219, 23, 190, 171, 79, 61, 46, 68, 200, 203, 252, 39}, 60}, {{31, 128, 0, 0, 35, 239, 142, 215, 66, 120, 168, 163, 147, 250, 16, 135}, 60}, {{31, 128, 0, 0, 0, 0, 82, 157, 135, 82, 13, 16, 148, 57, 239, 205}, 60}, {{31, 128, 0, 0, 0, 0, 172, 171, 109, 96, 139, 249, 173, 69, 226, 2}, 60}, {{31, 128, 0, 0, 126, 91, 63, 93, 69, 54, 184, 86, 138, 20, 209, 245}, 60}, {{31, 128, 0, 9, 94, 97, 134, 24, 181, 118, 228, 54, 180, 55, 13, 102}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 150, 101, 173, 231, 137, 101}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 58}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 14, 113, 237}, 60}, {{31, 128, 0, 0, 47, 36, 211, 137, 156, 217, 165, 85, 249, 209, 42, 37}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 31, 110, 239, 54, 49, 148, 135, 7}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 124}, 60}, {{31, 128, 0, 0, 0, 134, 5, 227, 161, 14, 28, 159, 203, 97, 168, 103}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 254, 242, 240, 58, 68, 203, 31}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 220}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 32, 130}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 84, 0, 196, 23, 105, 208, 239}, 60}, {{31, 128, 0, 34, 75, 69, 5, 93, 71, 88, 117, 62, 180, 168, 46, 110}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 41, 81}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 67, 199}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 54, 83, 49, 163, 251, 24, 21}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 190, 237, 200, 32, 105, 207, 193, 152, 199, 141, 149, 186}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 5, 7, 216, 86, 29, 253, 105}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 26, 176, 111, 209}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 19, 26, 142}, 60}, {{31, 128, 0, 17, 215, 181, 254, 209, 118, 50, 44, 116, 107, 237, 143, 97}, 60}, {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 218}, 60}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 50, 201, 43}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200}, 148}, {{115, 195, 64, 0, 232, 202, 143, 226, 227, 190, 93, 97, 187, 82, 223, 201}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 108}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 212, 141}, 148}, {{115, 195, 64, 0, 0, 0, 23, 230, 143, 19, 62, 72, 44, 177, 216, 76}, 148}, {{115, 195, 64, 0, 213, 38, 186, 254, 45, 50, 228, 26, 37, 28, 105, 55}, 148}, {{115, 195, 64, 187, 186, 175, 207, 37, 156, 9, 70, 216, 192, 100, 18, 172}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 132, 149, 176}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40}, 148}, {{115, 195, 64, 0, 0, 0, 134, 187, 177, 252, 36, 16, 139, 209, 221, 100}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 148}, {{115, 195, 64, 0, 0, 0, 0, 116, 66, 215, 223, 59, 10, 23, 92, 29}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 194, 204, 130, 136, 102}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 110, 113, 252, 238, 136, 119, 31}, 148}, {{115, 195, 64, 0, 0, 54, 220, 18, 49, 96, 115, 147, 57, 162, 61, 241}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 226, 29, 75, 174, 66, 99}, 148}, {{115, 195, 64, 0, 0, 183, 112, 47, 189, 167, 15, 33, 137, 77, 233, 31}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 75, 69}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 217}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 77, 19, 233, 111, 148, 242, 150}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20}, 148}, {{115, 195, 64, 140, 135, 159, 119, 253, 180, 49, 173, 105, 182, 31, 183, 17}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 222, 226}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 169, 90, 177, 85, 94, 177, 77}, 148}, {{115, 195, 64, 0, 0, 0, 152, 233, 23, 2, 15, 12, 35, 51, 136, 240}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 189}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 128, 41}, 148}, {{115, 195, 64, 0, 108, 151, 22, 76, 238, 139, 138, 190, 62, 102, 129, 212}, 148}, {{115, 195, 64, 0, 170, 11, 110, 74, 135, 163, 250, 119, 206, 95, 88, 55}, 148}, {{115, 195, 64, 0, 121, 4, 96, 69, 35, 22, 234, 5, 229, 57, 135, 48}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 64, 255, 121, 131, 151, 84, 29, 247}, 148}, {{115, 195, 64, 0, 0, 40, 221, 224, 118, 77, 233, 155, 93, 248, 100, 213}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 150, 5, 88}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 214, 170, 84, 170, 138}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 246, 184, 140, 189, 96, 48, 254, 64}, 148}, {{115, 195, 64, 0, 172, 189, 208, 63, 40, 98, 49, 15, 93, 56, 147, 253}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 45, 213}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 231, 255, 154}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 117, 196, 126}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 48, 151, 210, 142, 69}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 81, 101, 209}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 157}, 148}, {{115, 195, 64, 0, 101, 195, 67, 62, 147, 85, 108, 105, 230, 46, 92, 190}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 71}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 61, 231, 251, 77, 15, 85, 19}, 148}, {{115, 195, 64, 0, 0, 0, 40, 172, 204, 69, 111, 214, 27, 148, 62, 138}, 148}, {{115, 195, 64, 230, 80, 224, 229, 116, 251, 167, 26, 205, 195, 253, 98, 236}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 37}, 148}, {{115, 195, 64, 119, 164, 145, 5, 55, 79, 126, 81, 225, 128, 97, 59, 50}, 148}, {{115, 195, 64, 0, 0, 0, 0, 154, 170, 6, 187, 248, 117, 52, 148, 68}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 11, 207, 207, 48, 230, 96, 222, 27}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 163, 129, 167}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 27, 165, 118, 7, 255}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 140}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 112, 8, 242}, 148}, {{115, 195, 64, 0, 0, 0, 173, 249, 247, 219, 98, 78, 107, 224, 191, 52}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 63, 82, 15, 188, 215, 116}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 14, 132, 33, 127, 12}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 161, 52, 93, 254, 112, 64, 18}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 30, 90, 193, 3, 79, 190, 219, 145}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 245, 216}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 121}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 3, 106, 126, 207, 32, 86, 44, 142, 4, 167}, 148}, {{115, 195, 64, 0, 0, 0, 183, 173, 181, 93, 56, 150, 224, 123, 167, 13}, 148}, {{115, 195, 64, 0, 0, 228, 149, 139, 206, 49, 25, 251, 179, 155, 92, 169}, 148}, {{115, 195, 64, 130, 163, 141, 190, 41, 125, 41, 76, 12, 21, 85, 164, 117}, 148}, {{115, 195, 64, 0, 0, 0, 0, 112, 37, 46, 56, 3, 88, 219, 43, 83}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 90, 153, 34, 184, 179, 27, 22}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 85, 9, 75, 94, 85}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 67, 105, 112, 187, 45, 88, 179}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 78, 204, 122}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 96, 135}, 148}, {{115, 195, 64, 0, 0, 141, 155, 154, 135, 141, 42, 78, 248, 169, 253, 50}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 26, 183, 90, 118, 91, 105, 37}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 151, 135, 44, 167, 162, 52}, 148}, {{115, 195, 64, 0, 0, 0, 0, 114, 224, 248, 166, 203, 133, 68, 121, 165}, 148}, {{115, 195, 64, 189, 218, 90, 87, 127, 64, 118, 211, 44, 151, 215, 190, 65}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 148}, {{115, 195, 64, 97, 22, 33, 248, 193, 191, 58, 239, 168, 58, 84, 226, 86}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 26, 98, 149}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 89, 156, 93, 22, 128}, 148}, {{115, 195, 64, 0, 42, 95, 12, 130, 207, 203, 13, 100, 167, 6, 136, 251}, 148}, {{115, 195, 64, 0, 0, 0, 0, 121, 103, 217, 79, 196, 69, 116, 200, 182}, 148}, {{115, 195, 64, 0, 0, 0, 0, 0, 40, 2, 62, 70, 171, 34, 173, 131}, 148}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 129}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 195, 26, 237}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 37, 122, 249, 217}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 95, 61, 94, 103}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 47, 72, 243, 8, 45, 26}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 136, 218, 252, 7, 75, 85}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 201, 104, 161, 190, 103}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 222, 241, 236, 15, 158, 176}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 16, 225, 237, 88, 170, 144, 51, 250}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 179, 27, 170, 246, 136, 102, 1}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 17, 148, 91, 1, 188, 188}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 177, 31, 102, 72, 201, 68}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 127, 45}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 2, 101, 5}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 76, 64, 99, 62, 82, 28, 164, 215}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 180, 23, 227, 87, 162, 75}, 202}, {{117, 214, 20, 80, 83, 51, 128, 64, 191, 122, 56, 11, 178, 217, 215, 13}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 242, 180, 99, 124}, 202}, {{117, 214, 20, 80, 83, 51, 128, 190, 30, 220, 28, 44, 208, 138, 2, 186}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 239, 112, 202}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 87, 222, 128, 61, 71, 219, 90}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 251, 46, 67}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 37, 46, 64, 27}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 19, 178, 85, 185, 58, 78, 85, 180}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 214}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 131, 195, 68, 180}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 167, 115, 168, 91, 87, 52, 219}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 131, 18, 176, 47, 152, 52}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 98, 250, 101, 4, 165, 236, 185, 233}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 110, 212, 160, 172, 217, 4, 25}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 118, 6, 254, 114, 116, 123}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 184, 103, 18, 181, 85, 94, 191}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 154, 116, 235, 97}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 11, 64, 42, 148, 244, 152, 236}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 235, 158, 46, 42, 121, 97}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 184, 185, 192, 109, 123, 136, 253}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 76, 172}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 134, 155, 142}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 185, 180}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 184, 94, 214, 219}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 55, 126, 84, 114, 239, 90, 87, 128}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 8, 212, 34}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 143, 228, 91, 9, 10, 228}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 156, 39, 151, 71, 23, 88, 252, 60}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 94, 29, 163, 251, 131}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 242, 91, 37, 62}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 80, 2, 23, 252, 18, 217, 250, 20}, 202}, {{117, 214, 20, 80, 83, 51, 128, 142, 137, 125, 72, 172, 112, 131, 78, 162}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 250, 200, 97, 159, 201, 215}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 72}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 214, 5, 32, 34, 146}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 214, 13, 103, 140}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 71}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 203, 23, 72}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 21}, 202}, {{117, 214, 20, 80, 83, 51, 128, 59, 208, 81, 130, 161, 18, 17, 162, 45}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 88, 132, 228}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 187, 189, 9, 139, 159, 199, 237}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 210, 178, 185, 155, 96, 25}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 50, 243, 5, 210, 71, 186}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 84, 4, 162, 58, 40, 252, 102}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 69, 191, 21, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 163, 53, 61, 111, 128, 130}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 75, 149, 108, 196, 255, 58, 202}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 169, 45}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 188, 120, 70, 241, 61}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 26, 181, 245, 28, 123, 132, 83, 46}, 202}, {{117, 214, 20, 80, 83, 51, 128, 211, 110, 243, 134, 192, 132, 62, 189, 82}, 202}, {{117, 214, 20, 80, 83, 51, 128, 237, 67, 85, 194, 32, 150, 243, 5, 59}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 104, 102, 41, 80, 1, 243}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 195, 224, 137, 116, 30, 166, 58, 108}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 180, 207, 64, 0, 176, 156}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 84, 134, 213, 157, 242}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 170, 125, 131, 61, 0, 147}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 67, 113, 38, 24, 120}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 121, 114, 230, 183, 63, 117}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 245, 1, 197, 197, 43, 8}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 104, 166, 75, 229, 204, 135}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 231, 219}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 98, 151, 122, 41, 77}, 202}, {{117, 214, 20, 80, 83, 51, 128, 0, 0, 32, 136, 144, 80, 95, 55, 88}, 202}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 195, 181}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 164, 51, 130, 165}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 236}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 125, 102}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 174, 13, 134}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 119, 23, 55}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 225, 71, 93, 10, 234}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 167, 255, 190, 104}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 195, 219, 57}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 77}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 46, 163, 158, 84}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 48, 210}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 137, 121, 58, 65, 9}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 191, 92, 215}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 132, 73, 209}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 255, 56, 108}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 73, 164, 250, 114, 192}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 144, 22, 239, 229, 244}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 135}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 41, 65}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 117, 69, 46}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 248, 195, 170, 128}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 213, 121, 75, 179, 177}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 18, 132, 210, 120}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 206}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 48, 207, 64, 219, 163}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 140, 19, 113, 139}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 105, 31, 213}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 13, 227, 252}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 137, 15, 159}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 188, 140, 4}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 2}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 53, 117, 113, 206}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 237, 157, 193, 95, 201}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 94, 192, 88, 85}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 171, 195, 187, 9}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 70, 123}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 251, 2, 40, 190}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 85}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 195, 240, 73, 139, 208}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 78, 87, 181, 183, 236}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 195}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 64, 240, 222, 243}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 34}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 60, 6, 146, 246, 173}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 111}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 170, 205, 122, 38}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 182, 229, 65, 250}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 227}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 26, 188, 202, 92}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 106, 66, 94, 133, 51}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 210, 32}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 254, 168, 124, 241, 171}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 211}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 71, 22, 103, 157, 85}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 48}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 93}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 152}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 10, 205, 244, 94}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 73, 54}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 251, 182}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 61, 127, 153, 109, 60}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 207, 51, 172, 45}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 207}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 216, 187}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 175, 199, 249, 196, 225}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 68, 119}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 126, 31, 161}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 108, 59, 8, 85}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 123, 118}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 211, 10, 123, 252}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 73, 176}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 151}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 220, 115}, 88}, {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 88}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 45}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 12, 115, 135}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 8, 11, 153, 13}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 199, 147}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 50, 111, 137, 6}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 247, 83, 9}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 127}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 9}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 166}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 176}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 212}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 243, 70, 173}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 167}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 195}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 99, 140, 134, 50}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 237, 39, 82}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 105}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 126, 222, 26}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 146, 35, 142}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 19, 38}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 99, 134}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 52, 160, 171}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 227}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 3}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 26, 181, 70, 156}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 83}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 198, 134, 90, 143}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 72, 208}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 173, 133, 249}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 94, 226, 157}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 83}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 143}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 37}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 80, 124}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 233}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 190, 47}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 226}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 160, 50}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 8, 252}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 53, 85, 183, 138}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 72}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 176, 118}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 193, 117, 133}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 69, 33}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 248, 57}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 90, 229}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 180}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 108, 182, 219}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 171, 200}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 150}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 112, 8, 36}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 9}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 92, 160, 140}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 99, 139, 114}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 71, 233}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 110, 121}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 137, 115}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 228, 46, 100, 128}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 179}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 250, 79}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 53, 94}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 146, 130, 244, 212}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 88}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 149, 42, 150}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 132, 241, 11}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 191, 32}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 223}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 55, 42, 188}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 207, 8, 75, 84}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 212, 126}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 43, 123, 242, 62}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 45, 160, 156, 20}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 164}, 3}, {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 65, 148}, 3}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 110, 37}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 15}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 54, 212}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 50}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 111}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 212}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 84}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 173}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 50, 16}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 102}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 250}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 29}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 85, 144}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 103}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 238}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 46, 70}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 64, 64}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 176}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 167}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 28}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 174}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 114}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 124}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 21}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 192}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 249, 89}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 255}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 74}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 200}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 134, 160}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 146, 24}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 235, 16}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 57}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 217}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 168}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 78}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 110}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 33, 139}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 145}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 141}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 229}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 62, 16}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 145, 218}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 218}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 63}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 30}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 145}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 165}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 255}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 67}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 22}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 83}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 84}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 146}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 243}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 116, 8, 225, 211}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 62, 49, 21, 126}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 135, 92, 232, 217, 3}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 12, 224, 126, 145, 140}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 110}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 164, 227, 243, 33, 28}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 22, 179, 36}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 26}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 144, 236, 249, 5, 18}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 189, 240, 39, 163}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 15}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 147, 251, 214, 243, 72}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 129, 116}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 69, 249, 42}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 11, 9, 190}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 112, 149, 96, 82, 2}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 95}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 17, 211, 254, 67, 31}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 1}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 213}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 35}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 90, 118, 131, 56, 70}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 146, 51, 84, 94, 52}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 25}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 223, 70, 98, 222, 121}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 151, 94, 176, 154, 133}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 78, 2, 158, 223, 208}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 231}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 72, 158, 242, 164, 61}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 213, 14, 39}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 65, 159, 13, 19, 222}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 32}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 91, 1}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 15, 204, 22, 83}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 30, 242}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 59, 18, 148}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 103, 97, 181, 220, 160}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 68}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 113, 13, 140, 196}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 79, 107}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 151, 58, 11, 35}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 79, 237}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 101, 29, 199, 46, 30}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 82, 209}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 253, 187}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 100, 83, 110}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 214, 101}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 88}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 150}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 242, 169, 59, 6}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 143, 51, 91}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 210, 237, 145}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 74}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 95, 221, 101, 206}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 73, 36, 67, 231, 61}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 193, 216, 168}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 77}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 54, 162, 216, 49}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 194, 163, 49}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 112}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 32, 17, 19, 231}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 138, 164, 172}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 252, 217, 169}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 60, 97, 13, 232, 148}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 216}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 233, 199}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 9}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 174, 179, 22}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 10}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 69, 20, 141, 147}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 189, 150, 127}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 15, 157}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 104, 236, 96, 245}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 237, 89, 84}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 85, 109}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 76, 95, 68}, 95}, {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 9, 174}, 95}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 13, 252}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 238, 232, 244, 11}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 15, 127, 180}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 156, 16, 99, 166}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 54, 247}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 182, 93, 245}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 202, 95, 120, 132}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 26, 119}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 230, 33, 169, 25}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 202}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 90, 198}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 70, 247, 193, 255}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 31, 49, 237, 153}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 129, 168, 152}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 231, 205}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 69, 179, 50, 145}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 251, 5, 118, 124}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 229, 229, 164, 178}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 125}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 234, 133, 204}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 193, 244}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 84}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 87, 192}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 58, 255, 237, 106}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 130, 121}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 98, 76, 236}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 34}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 14, 2}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 152, 161, 5, 19, 146}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 184, 168}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 83, 181}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 170, 140, 128}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 121, 188, 57, 131}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 242, 227, 183}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 251, 162, 44, 18}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 88}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 146, 120}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 75, 207}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 182, 174, 240}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 9, 146, 70}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 93, 194}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 30}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 28, 41, 175, 204}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 57, 196, 7, 22}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 169, 82, 4}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 32, 123}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 52, 141}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 32}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 126, 192}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 139}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 240, 130, 195}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 9, 29, 90}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 45, 196}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 252, 31}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 120}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 251, 162, 164, 162}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 206, 42, 166}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 161}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 38, 16, 103}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 83, 215, 81}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 122, 101, 184}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 250}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 1, 163}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 21, 21, 134, 2, 113}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 138, 140, 128, 249}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 27}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 31, 220}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 38, 133, 67, 188}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 255}, {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 127, 26, 215, 79}, 255}, {{0, 97, 220, 64, 0, 0, 58, 248, 15, 217, 179, 218, 152, 223, 226, 206}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 15, 227, 247, 168, 63, 48, 77, 72}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 157, 78, 239, 246, 236, 85, 208}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 117, 161, 210, 129, 160, 196}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 55, 71, 180, 243, 138, 51, 245, 225}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 146, 244, 154, 36}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 119, 144, 75, 131, 238}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 95, 47, 127, 76, 24}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 163, 42, 7, 143, 118, 204}, 48}, {{0, 97, 220, 64, 237, 135, 209, 99, 86, 217, 161, 88, 251, 12, 197, 26}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 189, 154}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 59, 73, 179, 151}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 68, 239, 143, 121, 22}, 48}, {{0, 97, 220, 64, 74, 83, 13, 39, 73, 63, 63, 23, 44, 230, 41, 52}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 126, 8, 76, 130, 177, 63, 185, 194}, 48}, {{0, 97, 220, 64, 0, 0, 0, 126, 136, 74, 92, 114, 166, 190, 128, 143}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 253, 190, 106, 107, 169, 132, 38}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 147, 46, 152, 191, 53}, 48}, {{0, 97, 220, 64, 0, 73, 105, 117, 144, 182, 53, 199, 216, 203, 213, 80}, 48}, {{0, 97, 220, 64, 0, 0, 81, 115, 116, 133, 40, 194, 218, 112, 142, 222}, 48}, {{0, 97, 220, 64, 0, 0, 105, 151, 18, 104, 225, 247, 150, 133, 155, 137}, 48}, {{0, 97, 220, 64, 111, 47, 17, 98, 19, 93, 219, 95, 197, 233, 115, 52}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 53, 105, 121, 156}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 158, 124, 197, 3, 70, 201}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 188, 139}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 9, 73, 195, 75, 180, 254, 153, 90}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 214, 186, 115, 129, 185, 233}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 74, 72, 166, 67, 10, 215}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 161, 198, 15, 81, 208, 43, 251}, 48}, {{0, 97, 220, 64, 0, 0, 0, 95, 163, 10, 187, 214, 238, 253, 161, 208}, 48}, {{0, 97, 220, 64, 0, 0, 0, 233, 182, 224, 151, 209, 103, 67, 137, 185}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 11, 206}, 48}, {{0, 97, 220, 64, 48, 61, 246, 163, 51, 99, 141, 55, 243, 53, 127, 155}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 60, 95}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 4, 129, 181, 61, 88, 214, 51}, 48}, {{0, 97, 220, 64, 0, 0, 37, 86, 162, 172, 247, 151, 197, 229, 197, 71}, 48}, {{0, 97, 220, 64, 0, 0, 252, 114, 233, 46, 227, 157, 189, 191, 233, 81}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 114, 158}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 134, 18, 226, 99, 15, 225, 246}, 48}, {{0, 97, 220, 64, 0, 0, 93, 74, 172, 57, 242, 0, 68, 158, 18, 72}, 48}, {{0, 97, 220, 64, 0, 0, 226, 56, 170, 116, 52, 179, 2, 16, 44, 40}, 48}, {{0, 97, 220, 64, 0, 0, 58, 199, 115, 138, 211, 210, 82, 175, 3, 229}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 39, 132, 200, 213, 59}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 210, 229, 111, 57}, 48}, {{0, 97, 220, 64, 30, 251, 154, 236, 185, 168, 244, 100, 203, 153, 204, 2}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 100, 88, 44, 132, 232, 68, 58}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 46, 60}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 111, 116, 32, 178, 177, 200, 189, 24}, 48}, {{0, 97, 220, 64, 0, 0, 0, 197, 1, 211, 109, 231, 235, 122, 155, 177}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 57, 185, 56, 145, 152, 160, 174, 81}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 213, 253}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 176, 43, 71, 237, 72, 238, 200, 126}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 69, 42, 140, 165, 250, 22, 93}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 224, 69, 29, 109}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243, 115, 37}, 48}, {{0, 97, 220, 64, 0, 125, 238, 160, 174, 108, 164, 177, 47, 40, 6, 129}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 30, 168, 112, 12, 118, 126, 89, 72, 229, 133}, 48}, {{0, 97, 220, 64, 0, 0, 130, 72, 160, 137, 34, 208, 170, 80, 248, 44}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 61, 148, 16, 102, 140, 200, 242, 25}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 48}, {{0, 97, 220, 64, 0, 0, 100, 241, 234, 47, 92, 238, 26, 83, 62, 168}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 70, 228, 123, 182, 223, 71, 181, 194}, 48}, {{0, 97, 220, 64, 0, 0, 246, 61, 187, 244, 181, 45, 137, 239, 171, 25}, 48}, {{0, 97, 220, 64, 0, 0, 0, 119, 218, 102, 254, 30, 95, 52, 90, 146}, 48}, {{0, 97, 220, 64, 0, 0, 0, 53, 211, 26, 37, 76, 56, 131, 224, 209}, 48}, {{0, 97, 220, 64, 0, 54, 159, 57, 77, 23, 29, 202, 203, 188, 99, 196}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 244, 131, 66, 139}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 139, 39, 15, 99, 60, 221, 103, 92, 174}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 63, 253}, 48}, {{0, 97, 220, 64, 121, 233, 212, 127, 134, 84, 177, 108, 171, 82, 107, 241}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 194, 106}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 137, 48, 240, 75, 169, 159, 5}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 252, 160, 12, 53}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 178, 35, 89, 208, 142, 197, 200}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 216}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 124, 252}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 203, 98}, 48}, {{0, 97, 220, 64, 0, 133, 92, 116, 4, 151, 41, 9, 78, 139, 81, 209}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 126, 221, 215, 191}, 48}, {{0, 97, 220, 64, 0, 45, 105, 27, 248, 117, 114, 207, 107, 45, 83, 36}, 48}, {{0, 97, 220, 64, 0, 0, 129, 172, 195, 145, 114, 65, 206, 89, 129, 129}, 48}, {{0, 97, 220, 64, 172, 28, 123, 73, 68, 4, 6, 171, 192, 186, 118, 168}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 224, 157}, 48}, {{0, 97, 220, 64, 0, 0, 177, 200, 90, 176, 87, 37, 52, 197, 248, 47}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 226, 241, 144, 49}, 48}, {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 48}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 48, 227, 80, 154}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 29, 84, 30, 89}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 143}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 50, 79, 224, 202, 194}, 38}, {{227, 206, 189, 31, 222, 8, 192, 65, 2, 5, 195, 97, 87, 124, 145, 22}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 39, 72, 4, 191}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 80, 33, 37, 180, 216, 67, 168, 98}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 137, 128}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 31, 121, 14, 34, 246, 117}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 8, 167, 37, 27, 211}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 65, 237, 222, 141, 225, 3, 23, 152}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 211, 91, 21, 6, 152, 232, 69, 91}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 190, 30, 210, 113, 104}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 68, 101, 210, 0, 14, 99}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 149, 126, 105, 61}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 23, 104}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 159, 217, 151, 188, 76, 45, 47}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 105, 59, 86, 173, 98}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 48, 113, 47, 226}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 33, 225, 248, 120, 83, 117, 158}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 23, 221, 45, 4, 12, 127}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 183, 59, 180}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 221, 172, 173, 206, 203, 169}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 191, 12, 77}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 168, 136, 135, 192, 3, 171, 253}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 201, 123, 155, 145, 15, 76, 144}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 244, 92, 152}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 31}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 56, 239, 34, 71, 38, 143, 110}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 226, 167, 192, 122, 59, 103, 205, 103}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 37, 228, 246}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 225, 106, 196, 86}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 78, 90, 166}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 130, 52, 10, 144, 124, 21, 69, 30}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 108, 144, 147, 170, 53, 142}, 38}, {{227, 206, 189, 31, 222, 8, 192, 121, 217, 146, 216, 218, 57, 16, 36, 10}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 42, 100, 191, 189, 219, 165}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 237, 199}, 38}, {{227, 206, 189, 31, 222, 8, 192, 211, 30, 157, 15, 5, 23, 72, 224, 170}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 40, 161, 105, 65, 125, 56, 139, 200}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 36, 7, 105, 166, 54, 192, 3, 236}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 234, 132, 49, 24}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 159, 212, 122, 39, 128, 11, 183}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 49, 98, 12, 92, 56}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 48, 252, 72}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 18, 113, 248, 21, 211, 129}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 174, 94, 48, 141}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 56}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 251, 136, 209, 198, 101, 165, 92}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 5, 252, 210, 178}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 82, 94, 51}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 180, 5, 224, 169}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 7, 219, 18, 41, 239, 189, 203, 98}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 191, 228}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 74, 252, 12, 34, 191, 175}, 38}, {{227, 206, 189, 31, 222, 8, 192, 136, 3, 220, 143, 89, 154, 175, 181, 183}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 128, 175, 62, 203, 72, 66, 128, 157}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 133, 237, 210}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 109, 99, 69, 223, 226, 193}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 169, 189, 170, 170, 84}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 84, 184, 192}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 68, 112, 170, 238}, 38}, {{227, 206, 189, 31, 222, 8, 192, 116, 100, 139, 184, 218, 74, 228, 115, 92}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 195, 65, 58}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 96, 45}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 179, 250, 70, 26, 146, 151}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 29, 114, 140, 201, 134, 125}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 58, 53, 117}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 24, 209, 202, 31, 9, 127, 105, 148}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 4, 43, 181, 130}, 38}, {{227, 206, 189, 31, 222, 8, 192, 42, 234, 246, 119, 103, 228, 132, 87, 121}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 104, 34, 49, 86, 94, 151, 255}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 56, 198, 203, 193, 212, 97}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 116, 33, 135, 223, 194}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 131, 134, 202, 53, 45, 54, 24}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 21, 237, 163, 246, 245, 199, 171, 77}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 232, 96, 113, 226, 240, 62}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 163, 246, 158, 63, 143, 3}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 156, 32, 211, 86}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 56, 114, 217, 250, 67, 190}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 78, 34, 135, 89, 62, 194, 136}, 38}, {{227, 206, 189, 31, 222, 8, 192, 232, 37, 116, 122, 244, 77, 54, 178, 231}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 87, 183, 124, 140, 24}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 235, 228, 225, 204}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 130, 142, 183}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 115, 96}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 231, 73, 55}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 63, 138, 106}, 38}, {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 227, 194, 232, 106}, 38}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 173}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 189}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 220}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 41}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 81}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 98}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 74}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 197}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 114}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 60}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 247}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 220}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 14}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 165}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 53}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 143}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 36}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 13}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 229}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 105}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 119}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 134}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 141}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 30}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 39}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 248}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 114}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 211}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 181}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 212}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 26}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 9}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 14}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 139}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 213}, 20}, {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 20}, {{39, 20, 125, 69, 252, 64, 0, 99, 43, 176, 167, 154, 58, 148, 168, 125}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 169, 216, 180}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 68, 34, 25, 185, 172, 76, 89, 82}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 90, 213, 47, 39, 113, 0, 112, 43, 228}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 169, 129, 169, 37, 229}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 140, 56, 3, 75, 46, 60}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 6, 70, 98, 29}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 103, 211, 63, 147, 21, 134, 21, 74}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 186, 153, 107, 216, 160, 2, 182}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 78, 183, 5, 135, 63, 194, 136}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 44, 84}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 143, 72, 7, 13, 153}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 68, 118, 30, 12}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 190, 24, 153, 139}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 74, 91}, 41}, {{39, 20, 125, 69, 252, 64, 0, 60, 152, 38, 145, 176, 169, 246, 51, 171}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 75, 88, 10, 63, 60, 241, 187}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 210, 214, 223, 42, 238, 208}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 84, 114, 107, 145}, 41}, {{39, 20, 125, 69, 252, 64, 0, 78, 136, 3, 134, 144, 157, 135, 87, 216}, 41}, {{39, 20, 125, 69, 252, 64, 121, 65, 155, 209, 249, 48, 77, 238, 246, 171}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 112, 145}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 237, 11, 94, 79, 173}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 19, 129, 94, 146, 90, 170, 48}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 196, 137, 74, 152, 37, 134, 157, 89}, 41}, {{39, 20, 125, 69, 252, 64, 248, 105, 20, 28, 181, 71, 16, 215, 21, 132}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 248, 193, 43, 77, 8, 54, 223}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 126, 71, 154, 214}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 68, 236, 84, 190, 213, 96, 222}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 13, 97, 36, 24, 196, 131}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 76, 31, 77, 144, 7}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 228, 135, 218}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 225, 73}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 232, 93, 189, 49}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 169, 60, 175, 240, 137, 150, 92}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 74, 69, 85, 125, 47, 163}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 16, 82, 162, 29, 120, 198, 113}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 126, 229, 105, 100, 136, 169}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 172, 153, 214, 114, 1, 38, 31}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 123, 173, 245, 69, 74, 75}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 222, 102, 178, 34, 210, 65}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 82, 163, 0, 42, 201, 169}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 173, 127, 153, 69, 99, 87, 191}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 217, 113, 206, 247}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 161, 191, 14, 57, 194}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 176, 192, 36, 172, 116, 109}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 100, 161}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 75, 164, 116, 194, 26, 214}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 37, 55, 26, 171, 125, 4, 75}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 69, 130, 125, 95, 42, 95, 89}, 41}, {{39, 20, 125, 69, 252, 64, 74, 223, 92, 8, 232, 212, 28, 221, 168, 164}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 55, 169, 174, 199, 229, 133, 72}, 41}, {{39, 20, 125, 69, 252, 64, 0, 9, 226, 171, 235, 221, 243, 176, 12, 97}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 171, 6, 148, 88, 95, 94}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 226, 165, 146, 9}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 204, 158}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 252, 139, 43, 247, 25, 219}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 54, 5, 148, 123, 150, 62}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 83, 34, 70, 113}, 41}, {{39, 20, 125, 69, 252, 64, 36, 159, 234, 27, 175, 111, 112, 91, 174, 186}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 130, 214}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 84, 246, 176}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 172, 59, 195, 19, 31, 37}, 41}, {{39, 20, 125, 69, 252, 64, 0, 27, 19, 253, 158, 125, 187, 159, 204, 218}, 41}, {{39, 20, 125, 69, 252, 64, 54, 39, 190, 39, 231, 206, 184, 184, 93, 21}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 27, 215, 215, 202}, 41}, {{39, 20, 125, 69, 252, 64, 213, 61, 19, 190, 120, 210, 68, 141, 92, 62}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 2, 100, 246}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 252, 253}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 124, 60, 44, 206, 219, 98}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 179, 108, 202, 198, 196, 167, 246}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 64, 73, 25, 191, 223, 155}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69}, 41}, {{39, 20, 125, 69, 252, 64, 0, 132, 200, 20, 134, 85, 190, 117, 140, 54}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 117, 253, 236}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 82, 197}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 168, 163, 193}, 41}, {{39, 20, 125, 69, 252, 64, 243, 136, 1, 51, 219, 112, 7, 122, 135, 60}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 119, 224, 59, 48, 146, 227, 108}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 3, 5, 188, 143, 6}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 10, 197, 109, 244, 99, 15, 146}, 41}, {{39, 20, 125, 69, 252, 64, 141, 180, 113, 125, 136, 66, 245, 181, 89, 192}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 181, 118, 88, 209, 224}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 240, 73, 230, 52, 45, 28}, 41}, {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41}, {{39, 20, 125, 69, 252, 64, 0, 82, 51, 160, 82, 145, 67, 51, 65, 116}, 41}, {{39, 20, 125, 69, 252, 64, 46, 39, 30, 158, 163, 205, 170, 44, 213, 133}, 41}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 105, 17}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 33, 105, 184}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 205, 106, 182}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 20}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 186, 1}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 162, 136, 106}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 245}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 30, 233, 74, 180}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 68, 232, 57, 201}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 195, 208}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 130, 111}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 99}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 146, 147, 249}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 251, 171, 173, 96}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 231}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 119, 162, 156}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 84, 237}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 139}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 229, 88, 22, 148}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 172, 224, 251}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 197, 16, 51}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 56, 247, 77, 161}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 124, 92, 171}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 195}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 122, 225, 170, 198}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 161, 232, 214}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 107, 92, 26, 240}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 120, 234}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 231, 249, 16}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 129, 193}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 201, 153, 25}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 154, 139, 52}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 88}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 195}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 129, 195}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 10}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 129}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 1}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 158, 26, 128, 42}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 224}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 80, 45}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 236}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 220}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 186, 186}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 193, 87, 55}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 174, 207}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 121, 8}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 250, 39, 56}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 247}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 189, 95, 203, 33}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 232}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 56, 147, 134, 33}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 230, 229}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 235, 188, 105}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 109}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 119, 24, 154}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 19, 143}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 118, 72}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 178, 214}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 168, 91}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 144, 67, 29}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 58}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 203, 171, 169}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 105, 136, 36}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 133}, {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 82, 162, 201, 57}, 133}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 214, 50, 210}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 173, 93}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 152, 62, 10}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 173, 241}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 153}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 217, 72, 254}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 185, 113, 233}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 222, 51, 59}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 236, 244, 21}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 124, 206, 176}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 209}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 207, 205}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 201, 52, 38}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 143}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 152, 124}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 70, 223}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 94, 211}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 157, 10}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 127, 208}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 41}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 49}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 117, 145}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 137}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 201}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 128, 117}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 23, 236, 184}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 106}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 51, 6, 121}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 212}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 32}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 25}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 238, 112, 183}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 194}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 54}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 141, 206}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 121, 52, 110}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 117, 145, 124}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 54, 123, 95}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 92, 27, 30}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 238, 37}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 130}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 103, 106, 91}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 152}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 122, 46, 222}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 2}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 175}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 205, 56}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 46, 110, 220}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 70, 215}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 94, 64, 238}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 49, 127}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 66}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 195, 87, 14}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 113, 49}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 2, 143}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 167, 81, 134}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 162, 143}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 214, 188}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 103}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 229, 220}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 66}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 20, 250, 216}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 145, 192, 163}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 152, 19}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 1, 105, 254}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 112, 196, 168}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 130}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 214}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 69}, 189}, {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 189}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 230, 52}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 129}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 27, 219, 192}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 135}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 248}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 5}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 193, 179}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 36}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 182, 64}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 106, 80}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 236, 155, 53}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 220, 34, 59}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 182}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 64, 186, 63}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 254, 186, 131}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 160, 31}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 236, 9}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 247, 142, 36}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 155, 38}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 78, 146}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 132}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 71, 212, 45}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 13, 199, 212}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 3, 198}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 4, 243, 232}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 73}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 49, 158, 140}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 218, 248, 149}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 132, 195, 12}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 115, 240}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 171}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 141, 17, 180}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 240, 50}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 140, 165}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 79}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 102, 14}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 185}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 23, 125}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 151}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 85, 124}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 164}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 206, 205, 175}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 154, 178, 128}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 37, 106, 55}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 62, 77, 188}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 155, 163}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 199}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 232}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 247, 132, 27}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 157, 35}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 127}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 175}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 43}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 196, 21, 141, 255}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 72}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 68, 29, 70}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 90}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 127, 177, 119}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 41, 93, 41}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 132, 42, 86}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 253}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 139, 170}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 113}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 72, 230}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 73}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 67, 61, 186, 67}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 115, 53}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 226}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 185, 173, 114}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 158}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 184, 48}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 151}, {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 110, 40}, 151}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 26, 189, 162, 89, 61, 244, 175}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 221, 3}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 60, 24}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 73}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 197, 46, 101}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 191, 213}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 3, 3, 7, 56, 49, 3, 59}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 161}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 221, 92, 57, 214}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 149, 85, 133, 76, 126, 24}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 121, 111, 16}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 73}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 17, 7, 27, 221, 152}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 153, 73, 24}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 245, 242, 105}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 228, 102, 65, 195, 42, 201}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 111, 2, 88, 190, 158}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 34}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 46}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 87}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 23, 208, 216, 36}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 51, 212, 29, 121}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 81, 96, 101, 245, 85, 133}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 186, 129}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 174, 25, 2}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 108, 102, 101}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 127}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 92, 214, 80, 173}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 176, 245, 37, 214, 208, 223}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 63}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 180, 190, 50, 194}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 215, 26, 254, 149, 34}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 217, 173, 15, 85}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 82, 222, 36, 101, 98, 42}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 253}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 6, 113}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 255, 10, 98, 190, 5}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 10}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 108, 191, 200, 185, 208}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 32}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 198}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 198, 62, 184}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 80, 230, 110, 186, 9}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 163, 243, 138, 77, 63}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 237, 216, 73, 118, 26}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 188, 16, 5, 246, 108, 193}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 250, 121}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 108}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 194}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 166, 105, 96, 166, 94, 60}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 109}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 215}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 16, 155, 130, 124, 48, 103}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 59, 119}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 72, 167}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 210, 99, 169}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 75}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 42, 96}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 99, 145, 189}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 101}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 191, 116, 77, 104}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 39, 173, 150, 64, 183, 251, 93}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 195, 188, 208, 151}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 35, 134, 248, 174, 20}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 1, 177, 158, 55, 249, 246}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 51, 143, 105}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 78, 68, 95, 178, 176, 118}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 68, 1}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 231, 124, 92, 139, 161}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 129}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 168, 253, 252, 231, 164, 113}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 142, 170, 254, 16}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 252, 188, 109, 192, 225, 231, 108}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 34, 51, 89, 213, 34, 163}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 104}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 43, 40, 58, 58, 71}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 39, 185, 108, 187, 1, 157, 100}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 45, 195, 226, 7}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 238, 59, 147, 98}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 166, 127, 185, 155, 51}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 99, 118, 15, 179}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 250, 49, 212}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 11, 155, 244, 96, 180}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 188, 106, 233, 155, 96, 18, 167}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 120, 111, 54, 81, 112, 22}, 100}, {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 15, 130}, 100}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 207, 212, 3, 145, 107, 31, 182}, 118}, {{25, 86, 139, 116, 190, 88, 0, 130, 210, 240, 215, 218, 8, 73, 32, 107}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 85, 185, 118, 88, 104, 105, 97, 140}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 237, 6, 218}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 234, 107}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 65, 84, 36, 36}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 41, 159, 85, 88, 77}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 197, 63, 36}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 53, 211, 17, 87, 100, 244, 39, 154}, 118}, {{25, 86, 139, 116, 190, 88, 0, 193, 141, 57, 52, 87, 70, 33, 5, 181}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 111, 63, 167, 183}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 231, 236, 220, 190}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 156, 128, 153, 219, 90, 26, 22, 71}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 44, 79, 19, 177}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104}, 118}, {{25, 86, 139, 116, 190, 88, 0, 131, 76, 1, 101, 232, 102, 80, 224, 189}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 164, 24, 213}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 121, 167, 173, 12, 208, 179}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 15, 92}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 233, 132, 198, 15, 56, 82, 105}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 225, 124, 162, 42, 247, 113, 253, 72}, 118}, {{25, 86, 139, 116, 190, 88, 0, 80, 44, 237, 70, 16, 137, 203, 217, 12}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 85, 138, 205, 137}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 142, 28, 24, 170, 63, 199}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 220, 162, 85, 214, 100, 102}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 47, 51}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 67, 221, 243, 54, 145, 134, 101}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 40, 146, 118, 6}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 228, 127, 179, 47, 224, 245, 75, 130}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 197, 164}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 33, 124, 118, 77}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 105, 34}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 196, 205, 108, 85, 148, 2, 255}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 131, 107, 133, 104}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 62, 109, 140, 156, 11}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 212, 77}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 2, 58, 113, 5, 57, 233, 126, 193}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 44, 64, 6, 208}, 118}, {{25, 86, 139, 116, 190, 88, 0, 171, 27, 231, 237, 228, 150, 44, 35, 61}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 178, 14, 4, 20, 108, 213, 230}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 47, 227, 64, 178}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 39, 173, 109, 233, 99, 143, 71, 88}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 142, 211, 159}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 198, 220, 124, 60}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 53, 20, 30, 113}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 151, 42, 37, 101, 124, 208, 40, 7, 66}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 122, 163, 100, 83, 44, 211, 41}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 241, 56, 11, 229}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 239, 243, 201, 243, 110}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 43, 73}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 93, 42, 116, 226, 76, 172, 95}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 190, 217, 227, 183, 180, 169}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 57, 120}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 45, 67, 48, 1}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 187, 83, 19, 116, 95, 79, 6, 186}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 238, 114, 11, 224, 137, 78, 52, 177}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 174, 50, 58, 108, 166, 147, 166, 198}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 230, 179, 0, 162, 171, 116}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 53, 182}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 116, 178, 128}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 21, 34, 199}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 119, 188}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 176, 209, 220, 235, 103, 215, 72}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 185, 183}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 196, 234, 142, 29, 140}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 118, 192}, 118}, {{25, 86, 139, 116, 190, 88, 0, 6, 195, 105, 124, 44, 160, 166, 209, 169}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 203, 248, 80, 26, 178, 76, 16, 230}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 81, 89, 19, 138, 72, 85}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 104, 102, 73, 4, 203}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 191, 55, 210, 10, 193, 12}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 30, 123, 65, 5, 151, 38}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 234, 247, 26, 139, 5, 150, 135}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 42, 249, 87}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 83, 144, 41, 189, 0, 42}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 2, 35, 12, 160, 18, 7, 195}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 164, 98, 95, 100, 32, 195, 2, 97}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 50, 67, 181, 130, 224, 87, 124}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 234, 82}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 169, 36, 174}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 230, 117, 41, 83, 223, 115, 211, 232}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 128, 177, 201, 29, 253, 255}, 118}, {{25, 86, 139, 116, 190, 88, 0, 130, 109, 188, 231, 209, 75, 142, 53, 189}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 143, 229, 107, 232, 48, 54, 54, 28}, 118}, {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 189, 85, 125, 211}, 118}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 160, 146, 205, 240, 19, 214, 210}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 191, 239, 232, 216, 176}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 70, 223, 19, 106, 103}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 239, 155, 98, 191}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 84}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 105, 236, 27, 58}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 60, 101, 154, 77, 23, 70, 236, 8}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 67, 131, 150, 51}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 158, 54, 190, 50, 19, 183}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 131, 251, 155, 248}, 164}, {{113, 40, 65, 141, 64, 0, 0, 126, 56, 39, 186, 168, 21, 241, 184, 34}, 164}, {{113, 40, 65, 141, 64, 224, 5, 187, 119, 253, 250, 187, 108, 152, 139, 207}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 245, 120, 55, 109, 118, 107, 65, 31}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 94, 77, 239, 85, 50, 229, 143, 106}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 88, 60, 90, 128, 237}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 57, 230, 97, 142}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 130, 120, 192, 159, 162}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 221, 141, 169, 148}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 210, 31, 115, 192, 197, 2, 232}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 153}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 60, 32, 57, 15, 231, 190}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 209}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 32, 172, 221, 100}, 164}, {{113, 40, 65, 141, 64, 0, 0, 81, 46, 1, 230, 178, 145, 248, 61, 101}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 43, 250, 124}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 20, 176, 247, 186, 5, 248, 206, 246}, 164}, {{113, 40, 65, 141, 64, 186, 94, 1, 8, 221, 246, 9, 116, 181, 75, 240}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 212, 235, 11, 174}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 53, 121, 202, 124, 248}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 179, 145, 189, 181, 195, 246, 44}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 252, 203, 38, 176, 116}, 164}, {{113, 40, 65, 141, 64, 0, 0, 20, 214, 221, 31, 192, 105, 220, 161, 19}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 230, 129, 15, 113}, 164}, {{113, 40, 65, 141, 64, 0, 0, 255, 155, 89, 173, 158, 224, 72, 181, 193}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 176, 41, 174, 75, 17, 132, 229, 107}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 252, 195, 22, 226, 210}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 140, 97, 146, 147, 140, 223}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 107, 91, 246, 22, 144, 139}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 8, 189, 233, 248, 130, 10, 250, 8}, 164}, {{113, 40, 65, 141, 64, 116, 111, 67, 20, 224, 197, 78, 227, 247, 87, 89}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 38, 83, 120, 69, 117, 234, 160, 246}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 134}, 164}, {{113, 40, 65, 141, 64, 249, 119, 18, 25, 72, 243, 120, 242, 200, 223, 23}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 220, 213, 142, 254, 141, 98, 152, 210}, 164}, {{113, 40, 65, 141, 64, 0, 192, 41, 102, 217, 86, 100, 113, 123, 170, 23}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 169, 78, 99, 138, 147, 169, 123, 15}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 200, 19, 47, 16}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 149, 105, 190, 255}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 90}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 224}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 194}, 164}, {{113, 40, 65, 141, 64, 0, 58, 165, 202, 204, 174, 149, 141, 170, 142, 200}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248}, 164}, {{113, 40, 65, 141, 64, 185, 254, 87, 104, 105, 170, 233, 105, 12, 217, 223}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 94, 134, 177, 53, 31, 238}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 45}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 2, 235, 123, 81, 23, 206, 198, 192}, 164}, {{113, 40, 65, 141, 64, 0, 47, 191, 138, 250, 231, 197, 189, 57, 144, 236}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 164}, {{113, 40, 65, 141, 64, 30, 135, 177, 236, 50, 175, 46, 181, 137, 243, 99}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 160, 158, 99, 254}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 132, 36, 102, 76, 18, 182, 243}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 225, 221, 77, 107, 70}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 124, 199, 121, 139, 183, 114}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 49, 26, 63, 232, 221, 246, 155, 68}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 196, 224, 166, 174, 242, 191, 69}, 164}, {{113, 40, 65, 141, 64, 0, 5, 9, 214, 151, 179, 68, 91, 253, 135, 99}, 164}, {{113, 40, 65, 141, 64, 0, 0, 5, 0, 171, 239, 96, 34, 154, 0, 93}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 188, 28, 56, 111, 152}, 164}, {{113, 40, 65, 141, 64, 51, 96, 155, 66, 167, 40, 67, 103, 48, 23, 91}, 164}, {{113, 40, 65, 141, 64, 151, 47, 59, 118, 60, 109, 42, 122, 163, 84, 156}, 164}, {{113, 40, 65, 141, 64, 0, 0, 215, 128, 3, 156, 47, 47, 61, 249, 216}, 164}, {{113, 40, 65, 141, 64, 0, 215, 139, 46, 52, 147, 73, 205, 88, 22, 137}, 164}, {{113, 40, 65, 141, 64, 0, 144, 206, 90, 130, 187, 195, 32, 111, 205, 126}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 212, 144, 130, 93}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 36, 18, 64, 99, 149, 136, 1, 56}, 164}, {{113, 40, 65, 141, 64, 0, 21, 166, 214, 252, 13, 107, 112, 182, 5, 186}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 192, 177, 89, 118, 91, 7}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 205, 60, 28, 161, 194}, 164}, {{113, 40, 65, 141, 64, 0, 30, 48, 254, 194, 219, 142, 61, 4, 172, 13}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 15, 140, 11, 63}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 193, 238, 13}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 40, 243, 170, 166}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 184, 119, 153, 223, 225, 191, 212}, 164}, {{113, 40, 65, 141, 64, 0, 0, 199, 68, 40, 214, 135, 28, 12, 100, 226}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 52}, 164}, {{113, 40, 65, 141, 64, 0, 0, 0, 250, 43, 173, 14, 145, 12, 89, 84}, 164}, {{113, 40, 65, 141, 64, 0, 135, 61, 75, 92, 168, 87, 180, 17, 201, 208}, 164}, {{113, 40, 65, 141, 64, 0, 0, 76, 240, 48, 90, 72, 242, 123, 219, 40}, 164}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 100, 197, 22}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 87, 106}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 208}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 199, 63}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 100, 10}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 147, 117}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 205, 133, 133}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 75}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 102, 116}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 146, 180}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 48, 130}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 181, 58}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 146, 147, 213}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 247, 253}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 14, 120, 111}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 130, 226, 209}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 120, 47}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 122}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 165}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 57}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 26, 176}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 91, 176, 43}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 7, 21}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 20, 16, 61}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 138, 3}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 19, 61}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 236, 57, 2}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 63, 187}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 111, 71, 64}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 213}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 54, 18, 242}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 36, 254}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 160}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 78, 143, 82}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 161, 86, 40}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 53}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 184, 229, 133}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 117, 187, 4}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 195, 222}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 53}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 43, 219}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 131}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 15}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 242, 29, 99}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 108, 1, 21}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 246}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 72, 2}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 14}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 95, 216}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 43, 88}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 6, 1}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 192}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 92}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 237, 200, 220}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 124, 50}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 125, 146, 210}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 158}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 162, 26, 107}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 129, 177}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 138, 254}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 146, 54}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 15, 151, 46}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 63, 223}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 123}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 71}, {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 78, 193}, 71}, {{39, 0, 0, 183, 241, 137, 43, 36, 171, 17, 232, 124, 22, 153, 194, 124}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 69, 62, 180, 64, 71, 237, 29}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 133, 220, 177, 124}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 139, 208, 207, 42, 40, 144, 234, 31}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 0, 0, 0, 14, 83, 223, 138, 68, 235, 82, 17, 27, 94}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 16, 156, 176, 134, 123, 80, 150, 83, 183, 238, 150, 160, 168}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 9, 136, 159, 232, 183}, 251}, {{39, 0, 0, 0, 0, 82, 239, 178, 132, 221, 78, 243, 126, 84, 130, 228}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 160}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 92, 85, 167, 138, 124, 4, 97, 235}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 145, 183, 151, 59, 14}, 251}, {{39, 0, 0, 0, 0, 79, 39, 246, 200, 62, 177, 244, 139, 107, 125, 107}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 178, 168, 237, 247, 127}, 251}, {{39, 0, 0, 0, 0, 0, 113, 149, 120, 88, 59, 215, 197, 235, 156, 5}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 64, 184, 74, 98, 3}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 54, 108}, 251}, {{39, 0, 226, 202, 123, 33, 218, 235, 223, 15, 180, 173, 118, 239, 68, 0}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 176, 225, 152, 120, 254}, 251}, {{39, 0, 0, 0, 0, 0, 65, 178, 133, 80, 169, 201, 159, 150, 59, 95}, 251}, {{39, 0, 0, 160, 232, 14, 165, 214, 198, 249, 216, 208, 154, 250, 148, 112}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 87, 86}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 107}, 251}, {{39, 0, 0, 0, 0, 0, 0, 193, 99, 7, 105, 82, 126, 222, 130, 172}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 199, 124, 52, 165, 82, 145, 21}, 251}, {{39, 0, 0, 0, 0, 87, 70, 191, 184, 12, 89, 11, 148, 132, 36, 162}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 64, 114}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 92, 108, 225, 189, 163, 245, 127, 101}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 134, 193}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 191, 238, 255}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 208}, 251}, {{39, 0, 0, 177, 17, 195, 58, 67, 87, 221, 192, 32, 251, 94, 15, 40}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 179, 200, 186, 181, 227, 154, 199, 85, 70, 117, 214, 44, 219}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 169, 251, 230, 101, 121, 238, 246, 116}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 34, 98, 159, 0, 160, 170, 48, 118}, 251}, {{39, 0, 0, 0, 0, 203, 211, 2, 115, 19, 107, 147, 86, 51, 191, 91}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 143, 254}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 189, 60, 224, 239, 108, 118, 112}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 122, 130, 77, 186, 198, 140, 200}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 110, 118, 84, 248, 153, 215, 217, 184}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 128, 147, 226, 86}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 64, 163, 0, 143, 48, 239, 14, 96}, 251}, {{39, 0, 0, 0, 0, 0, 240, 39, 203, 71, 165, 93, 87, 234, 62, 153}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 170, 166, 198, 199, 105, 242, 152, 49}, 251}, {{39, 0, 76, 106, 21, 16, 206, 252, 128, 250, 58, 241, 186, 19, 1, 180}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 241, 198, 221, 115, 104}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 87}, 251}, {{39, 0, 0, 0, 0, 0, 83, 49, 134, 86, 228, 165, 158, 248, 176, 239}, 251}, {{39, 0, 0, 0, 0, 0, 0, 213, 112, 124, 197, 47, 142, 231, 63, 225}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 150, 81, 117}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 93, 225}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 0, 113, 171, 145, 230, 200, 247, 121, 53, 24, 171, 38, 150}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 251}, {{39, 0, 0, 0, 8, 252, 181, 184, 206, 119, 245, 52, 241, 99, 35, 112}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 69, 146, 166, 94, 13, 31, 192}, 251}, {{39, 0, 0, 0, 0, 156, 11, 238, 93, 251, 190, 141, 187, 254, 98, 127}, 251}, {{39, 0, 0, 0, 0, 0, 178, 224, 198, 250, 79, 15, 134, 11, 232, 116}, 251}, {{39, 0, 70, 79, 102, 7, 99, 233, 113, 51, 143, 0, 203, 212, 153, 166}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 126, 41, 226, 196, 68}, 251}, {{39, 0, 105, 95, 205, 198, 69, 110, 146, 201, 39, 7, 222, 176, 23, 68}, 251}, {{39, 0, 0, 0, 0, 232, 248, 91, 248, 217, 137, 50, 55, 195, 255, 235}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 25, 63, 243, 1, 238, 135, 88, 183}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 103, 19}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13}, 251}, {{39, 0, 167, 207, 33, 247, 54, 39, 31, 114, 80, 123, 169, 220, 145, 166}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 230, 230, 159, 0}, 251}, {{39, 0, 71, 232, 252, 97, 25, 205, 176, 49, 187, 135, 233, 35, 33, 247}, 251}, {{39, 0, 0, 10, 173, 135, 240, 187, 166, 210, 17, 142, 32, 24, 94, 10}, 251}, {{39, 0, 0, 0, 0, 0, 214, 179, 184, 143, 121, 133, 46, 65, 251, 186}, 251}, {{39, 0, 0, 0, 0, 163, 16, 188, 106, 247, 46, 125, 23, 172, 159, 175}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 116}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 98, 50}, 251}, {{39, 0, 0, 0, 0, 0, 12, 174, 157, 41, 181, 166, 189, 40, 134, 132}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 175, 120, 9, 19}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 151, 152, 222, 3, 76, 199, 101, 216}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 1, 7, 194, 157, 42, 220, 197, 222}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 9, 95, 119}, 251}, {{39, 0, 122, 32, 134, 235, 234, 106, 108, 85, 40, 61, 182, 160, 186, 18}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 138, 166, 199, 146, 26, 157, 183}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 99}, 251}, {{39, 0, 0, 0, 0, 253, 250, 214, 107, 121, 245, 225, 8, 138, 139, 252}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 152, 174, 163, 241}, 251}, {{39, 0, 0, 0, 11, 80, 193, 136, 224, 63, 202, 145, 168, 26, 139, 194}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 103, 88, 160, 68, 136, 22, 199, 233}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 67, 187, 64, 89}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 199, 29, 111, 217, 24}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 122, 246, 245, 151, 177, 201, 36, 48}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 106, 247, 211, 99, 253}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 17, 32, 205}, 251}, {{39, 0, 0, 96, 112, 175, 43, 56, 231, 173, 191, 13, 207, 249, 131, 126}, 251}, {{39, 0, 0, 0, 0, 0, 0, 0, 164, 91, 10, 51, 167, 246, 102, 43}, 251}, {{39, 0, 0, 0, 0, 0, 0, 144, 27, 96, 108, 159, 157, 97, 27, 181}, 251}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 175, 225, 101, 169, 119, 64, 236}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 194, 129, 64, 130, 254, 207}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 230, 57, 40, 16}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 48, 253, 2, 25, 111}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 216, 192, 38, 159, 77, 13, 33}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 90, 221, 96, 174, 128, 7, 40}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 122, 117}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 37, 11, 178, 242, 199, 91}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 156, 98, 139, 224}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 23, 92, 96, 250, 178}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 77, 205, 12, 82, 209, 119, 105, 48}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 178, 183}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 20, 185, 161, 163, 141, 223, 3, 145}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 172, 87, 190}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 177, 24, 15}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 126, 116, 220, 175}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 109, 55}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 183, 79, 6, 119, 7, 127, 111}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 15, 4, 54}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 32, 178, 151, 210, 107, 230, 192, 186}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 176, 167, 13, 165}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 57, 222, 170, 48, 7, 217, 192, 29}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 141, 189}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 167, 60, 88, 36}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 146, 58, 110, 61, 221, 29}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 90, 156, 23, 102, 86}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 111, 54, 204, 68, 165, 253, 146}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 181, 226}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 2, 27, 115, 187, 64}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 184, 60, 44, 98}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 232, 40, 178}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 71, 108, 163, 117}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 20, 241, 6, 121, 59, 6, 94, 39}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 208, 30, 162, 40, 157}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 47, 139, 103}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 123}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 243, 226, 205, 74}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 219, 23, 245, 200}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 137, 18, 156, 254, 219}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 224, 163, 234, 180, 156, 203, 86, 228}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 191, 70, 56, 9}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 4}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 27, 250}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 33, 190, 104, 140, 163, 144, 100, 161}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 185}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 234, 9, 105, 67}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 68, 253, 226, 122, 249, 134, 21, 151}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 184, 224, 113}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 7, 171, 59, 10, 125, 147, 65, 93}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 208, 235, 110, 104, 72, 159, 254}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 179, 82, 221, 113, 110, 91}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 30, 145, 78, 108}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 7, 152}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 92, 209, 158, 39, 29, 98}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 50, 222, 169, 155, 100, 126, 12}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 127}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 169, 251, 191, 13, 139, 83, 215}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 163, 63, 161, 47, 70, 25, 200, 194}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 188, 41, 192, 128}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 150, 77, 59, 230, 165}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 116, 166, 79, 40, 77}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 71, 22, 23, 3, 78, 214}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 210, 167, 226, 253, 168, 60}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 6, 109, 153}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 48, 174, 242, 118, 203}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 20, 63, 212, 84, 163, 181}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 86}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 37, 246, 190, 112, 31}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 25, 0, 179, 181, 164, 49}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 207, 97, 140, 170}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 61, 19, 48, 40, 151, 17, 74}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 49, 216, 78, 200, 115, 149}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 49, 206, 175, 132, 140, 214}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 88, 93, 86}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 170, 225, 195}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 221, 252, 240, 10, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 209}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 156, 193, 85, 75, 253, 56, 159}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 196, 159, 105}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 113, 30, 181, 97, 190, 65, 86, 106}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 131, 102, 116, 232, 15, 159}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 228, 217, 26, 12, 141, 55}, 51}, {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 151, 14, 243}, 51}, {{0, 0, 0, 0, 0, 0, 0, 0, 8, 124, 193, 240, 71, 174, 112, 75}, 61}, {{0, 0, 0, 0, 0, 0, 142, 8, 29, 45, 213, 128, 178, 156, 28, 162}, 61}, {{0, 0, 0, 1, 130, 73, 119, 98, 68, 137, 219, 147, 12, 96, 190, 25}, 61}, {{0, 0, 0, 26, 100, 18, 61, 172, 136, 210, 212, 82, 90, 122, 112, 246}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 129, 109, 126}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 206, 21, 250, 204, 32, 92, 20, 75, 64, 241, 191, 53, 108}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 15, 107, 70}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 14, 7}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 131, 243, 36}, 61}, {{0, 0, 83, 27, 1, 120, 174, 98, 177, 43, 181, 173, 44, 223, 155, 60}, 61}, {{0, 158, 205, 104, 239, 133, 64, 123, 66, 110, 62, 156, 147, 19, 220, 85}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89}, 61}, {{0, 0, 0, 0, 200, 58, 181, 41, 210, 243, 109, 251, 198, 105, 105, 249}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 169, 34, 126, 210, 58, 77}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14}, 61}, {{0, 0, 0, 153, 173, 148, 70, 12, 225, 28, 10, 76, 242, 203, 105, 21}, 61}, {{0, 0, 0, 0, 96, 212, 102, 38, 177, 142, 218, 192, 129, 12, 21, 88}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 150, 63, 26, 207, 31, 173}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 247, 163}, 61}, {{0, 0, 0, 0, 0, 0, 0, 184, 13, 131, 250, 165, 137, 28, 15, 172}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 52, 60, 106, 88}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199}, 61}, {{0, 0, 171, 39, 120, 231, 26, 66, 62, 69, 144, 101, 110, 112, 206, 66}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 129, 28, 93}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 143, 59, 198}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 115, 165, 140, 252, 100}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 199, 220, 101, 14, 45, 250, 122}, 61}, {{0, 128, 178, 188, 97, 72, 192, 224, 92, 7, 73, 84, 57, 197, 190, 7}, 61}, {{0, 0, 0, 0, 180, 143, 32, 235, 15, 213, 153, 226, 83, 185, 169, 151}, 61}, {{0, 0, 0, 0, 0, 0, 0, 61, 197, 105, 154, 20, 119, 179, 215, 234}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 118, 142, 66, 54, 191, 42, 156, 215}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 181, 193, 129}, 61}, {{0, 0, 232, 151, 67, 53, 172, 64, 154, 175, 75, 161, 124, 254, 158, 128}, 61}, {{0, 0, 0, 0, 0, 250, 95, 252, 51, 209, 0, 160, 38, 64, 208, 240}, 61}, {{0, 0, 98, 6, 32, 82, 50, 141, 102, 135, 3, 81, 39, 202, 45, 29}, 61}, {{0, 0, 0, 0, 227, 73, 119, 152, 98, 57, 61, 66, 40, 38, 38, 22}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 223, 44, 242, 19, 33, 188, 73, 60, 242, 102, 87, 255, 1}, 61}, {{0, 0, 0, 0, 0, 0, 0, 102, 147, 246, 228, 89, 23, 178, 64, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 77, 122, 97}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 89, 83, 198}, 61}, {{0, 0, 0, 0, 68, 99, 12, 14, 19, 200, 90, 118, 184, 156, 189, 39}, 61}, {{0, 0, 0, 0, 0, 149, 199, 73, 57, 66, 212, 29, 142, 50, 122, 213}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 77, 32, 200, 93, 172, 232, 98, 186}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 204}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 250, 232, 92, 73, 20}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 76, 236, 158, 228, 33}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 93, 150}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 147, 104, 142, 78}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 116, 2}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177}, 61}, {{0, 0, 0, 0, 0, 67, 49, 254, 253, 0, 231, 37, 126, 55, 31, 170}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 103, 217}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 235}, 61}, {{0, 0, 0, 0, 0, 0, 0, 108, 139, 244, 163, 223, 167, 229, 252, 205}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 222, 78, 158, 28, 236}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 155, 172, 198, 36, 253, 232}, 61}, {{0, 0, 0, 0, 0, 0, 0, 36, 141, 73, 252, 121, 168, 76, 74, 159}, 61}, {{0, 0, 0, 0, 0, 0, 0, 174, 13, 247, 33, 11, 59, 181, 151, 100}, 61}, {{0, 0, 0, 0, 0, 33, 189, 141, 237, 246, 13, 251, 213, 103, 107, 211}, 61}, {{0, 0, 0, 0, 182, 162, 167, 0, 155, 44, 94, 10, 163, 49, 226, 161}, 61}, {{0, 41, 236, 218, 204, 190, 193, 201, 207, 29, 93, 49, 87, 63, 227, 168}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 193, 36}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 7}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 81, 219, 88, 17, 89, 39, 61, 210}, 61}, {{0, 0, 0, 0, 0, 0, 48, 249, 126, 50, 107, 167, 133, 95, 120, 100}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 179}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 93}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 60, 124, 169}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 64, 236, 203}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 115, 153, 238, 54}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115}, 61}, {{0, 0, 0, 158, 217, 255, 130, 7, 64, 37, 102, 150, 229, 159, 15, 182}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 181, 255, 200, 242, 53, 100, 201, 145, 143, 197}, 61}, {{0, 0, 0, 0, 0, 0, 0, 132, 11, 184, 159, 178, 185, 194, 198, 245}, 61}, {{0, 0, 0, 76, 5, 219, 81, 234, 28, 94, 188, 39, 94, 234, 219, 28}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 177, 145, 172, 216, 172, 22, 98, 252}, 61}, {{0, 0, 158, 73, 45, 112, 201, 189, 65, 183, 217, 36, 185, 237, 133, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 202, 90, 191}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 88, 43, 117, 217, 120}, 61}, {{0, 0, 0, 0, 0, 0, 84, 220, 205, 45, 92, 179, 173, 34, 247, 245}, 61}, {{0, 0, 0, 0, 0, 59, 241, 142, 20, 53, 150, 172, 94, 33, 203, 158}, 61}, {{0, 0, 0, 0, 0, 0, 74, 162, 9, 173, 60, 156, 44, 173, 24, 222}, 61}, {{0, 0, 0, 0, 183, 233, 34, 219, 28, 60, 126, 195, 158, 193, 39, 225}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 235, 252, 1}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 159, 67, 2}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 215, 218, 142}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 55, 234, 75, 121, 228, 194}, 61}, {{0, 0, 0, 122, 243, 212, 83, 191, 40, 20, 2, 27, 37, 33, 164, 63}, 61}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 226, 195, 165}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 168, 85}, 144}, {{140, 128, 0, 0, 0, 0, 61, 237, 219, 161, 212, 140, 91, 243, 188, 41}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 132, 1, 184, 58, 27, 240}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 100}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 31, 108, 78, 232, 165, 99}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 145, 101, 178, 94, 225, 102, 237, 218, 151, 29, 175, 121}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 144, 154, 77, 140, 205, 43, 13, 55}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 175, 53, 118, 62, 142, 145, 167, 191, 252, 40, 133, 51}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 34, 142, 187, 9, 167, 8, 143, 58, 223, 242, 186, 183, 226, 89}, 144}, {{140, 128, 0, 0, 0, 0, 0, 31, 251, 179, 50, 165, 195, 223, 52, 114}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 191, 18, 170, 174}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 179, 125, 7, 7, 232, 94, 29}, 144}, {{140, 128, 0, 0, 0, 0, 185, 255, 128, 19, 231, 140, 195, 190, 103, 172}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 100}, 144}, {{140, 128, 0, 0, 0, 0, 0, 85, 188, 170, 237, 86, 195, 83, 96, 22}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 169}, 144}, {{140, 128, 0, 62, 152, 77, 133, 17, 233, 205, 37, 236, 15, 211, 89, 62}, 144}, {{140, 128, 144, 45, 118, 134, 207, 50, 105, 64, 255, 59, 89, 203, 223, 146}, 144}, {{140, 128, 0, 0, 0, 0, 237, 5, 96, 193, 10, 190, 196, 134, 243, 9}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 216, 18, 195, 162}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 95, 207, 164}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 149, 126}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 0, 0, 0, 63, 3, 72, 164, 9, 117, 250, 0, 213}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 1, 115, 135, 238, 14, 116, 84}, 144}, {{140, 128, 0, 190, 199, 85, 203, 16, 32, 162, 89, 104, 168, 128, 170, 116}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 4, 36}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 168, 176, 150, 199, 78, 187, 237, 198}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 234, 134, 84, 50, 217, 96, 244, 191, 121, 107, 202, 40, 50}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 180, 177, 130, 38}, 144}, {{140, 128, 0, 0, 176, 155, 200, 249, 182, 247, 128, 75, 100, 43, 65, 212}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 58, 141, 79, 234, 13, 219, 16, 100}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 68, 215, 136, 244, 220, 86}, 144}, {{140, 128, 0, 0, 0, 0, 202, 215, 18, 198, 253, 76, 33, 65, 54, 186}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 89, 24, 186}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 11, 81, 160}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 67, 4, 17}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 220, 86}, 144}, {{140, 128, 0, 78, 9, 51, 90, 156, 140, 156, 206, 156, 91, 242, 152, 172}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 34, 180, 11, 138, 180, 21, 48}, 144}, {{140, 128, 0, 0, 0, 121, 207, 207, 92, 144, 242, 65, 85, 160, 233, 184}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 81, 93, 2, 139, 210, 54, 209, 190}, 144}, {{140, 128, 0, 0, 198, 24, 14, 189, 146, 106, 25, 77, 144, 56, 40, 247}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 70, 189, 48}, 144}, {{140, 128, 0, 0, 85, 169, 9, 248, 146, 1, 103, 48, 121, 110, 191, 237}, 144}, {{140, 128, 249, 200, 131, 77, 2, 78, 145, 27, 120, 45, 21, 96, 238, 1}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 103}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 69, 122, 176, 188, 68, 111, 93}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 232, 108, 56, 19}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 19, 105, 94, 100}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 210, 58}, 144}, {{140, 128, 0, 22, 29, 104, 119, 248, 28, 169, 77, 87, 216, 227, 188, 205}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 80, 108, 4, 22, 102, 69, 65}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 144}, {{140, 128, 0, 0, 73, 144, 209, 152, 76, 3, 120, 14, 192, 171, 158, 37}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 183, 0}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 33, 20}, 144}, {{140, 128, 0, 0, 0, 0, 30, 242, 106, 195, 140, 16, 75, 161, 9, 230}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 106, 155, 102}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 16, 127, 161, 20}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 3, 249, 222, 132, 100, 29, 168, 25}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 41, 101, 231, 27}, 144}, {{140, 128, 0, 0, 0, 0, 163, 171, 145, 29, 60, 217, 131, 220, 46, 231}, 144}, {{140, 128, 0, 16, 101, 255, 248, 85, 191, 157, 70, 168, 218, 194, 185, 114}, 144}, {{140, 128, 0, 0, 0, 0, 0, 77, 249, 129, 74, 69, 159, 121, 78, 175}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 170, 92, 181, 1, 42, 204, 178}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 65, 61, 79, 77, 237, 136, 199, 152}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 22, 56, 95, 14, 179, 213}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 88, 169}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 225, 211, 102, 191, 226, 118}, 144}, {{140, 128, 63, 204, 160, 47, 152, 175, 30, 83, 49, 78, 242, 13, 222, 91}, 144}, {{140, 128, 0, 0, 0, 201, 160, 208, 5, 216, 74, 204, 176, 113, 217, 135}, 144}, {{140, 128, 0, 0, 222, 161, 199, 124, 255, 164, 110, 56, 213, 176, 78, 156}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 185, 247, 215, 183, 10, 80, 93, 82}, 144}, {{140, 128, 0, 0, 60, 93, 5, 99, 175, 194, 65, 149, 199, 246, 39, 239}, 144}, {{140, 128, 114, 150, 20, 229, 159, 107, 117, 153, 137, 162, 43, 26, 95, 131}, 144}, {{140, 128, 34, 189, 236, 90, 163, 234, 146, 100, 219, 237, 120, 193, 55, 69}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 86, 237, 173, 183, 207, 107, 185, 213}, 144}, {{140, 128, 0, 0, 0, 0, 0, 110, 72, 126, 38, 48, 57, 159, 208, 105}, 144}, {{140, 128, 0, 130, 241, 189, 204, 79, 105, 93, 95, 203, 249, 220, 73, 26}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 24, 110, 170, 255, 94, 180, 15, 155}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 119, 145}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 77, 0, 25, 79}, 144}, {{140, 128, 0, 245, 165, 207, 160, 12, 14, 76, 181, 102, 27, 223, 167, 72}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 189, 222, 7}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 79, 3, 198, 220, 139, 59, 55, 175}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 41}, 144}, {{140, 128, 0, 0, 0, 130, 109, 235, 192, 103, 20, 209, 24, 137, 227, 121}, 144}, {{140, 128, 0, 0, 0, 0, 0, 0, 0, 241, 23, 139, 63, 137, 77, 200}, 144}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 4}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 85, 100, 242, 177, 163}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 155, 108, 164}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 148, 115, 114}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 149, 20, 234, 49}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 76, 185, 151}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 217, 190, 130, 69}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 126}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 44}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 104, 159, 191}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 36, 42, 45, 229}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 219}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 24}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 32, 90, 72, 30}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 68, 59, 161}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 141, 33, 62}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 190, 162, 61}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 216, 41, 6}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 13, 153}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 107, 140, 120, 161}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 95}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 48}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 25, 241, 66}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 196, 69, 29, 49}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 106, 204, 98, 13}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 109}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 86, 136, 25}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 94}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 162, 214, 183}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 106, 128, 224}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 184, 43}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 86, 27, 107, 215}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 166}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 91, 48, 121, 175}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 158, 211}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 85, 41}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 239, 7, 151, 146, 137}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 231, 129, 16, 84, 173}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 156}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 84, 67, 185}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 5, 123, 47}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 110, 123, 79}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 124}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 234, 144}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 131}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 176, 176, 241, 223, 166}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 204, 159, 24, 151, 134}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 181, 86}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 218, 242, 14}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 229}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 27}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 135, 198, 35}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 86, 244, 219, 225, 147}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 89, 139, 218, 129}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 233, 82, 48}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 115, 147}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 200, 7, 227, 127}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 231, 167}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 14}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 208, 6}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 36, 81}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 27, 177, 152}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 141}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 211, 9, 161, 91, 65}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 181, 144, 91}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 54, 195, 158}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 229, 184, 54}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 6}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 116}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 126, 134, 202, 94}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 206, 155, 94, 229}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 49, 26, 39, 229}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 4}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 74, 87, 187}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 92, 95, 210}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 222, 15, 122}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 9, 189, 85, 120, 10}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 69, 177, 55, 173}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 103, 41}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 218, 205, 177, 204}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 27}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 180, 248, 151, 119}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 187, 251, 155, 169}, 51}, {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 206, 29, 71, 19}, 51}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 216}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 149, 64, 140}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 31, 19, 233, 74}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 241, 44, 45, 253}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 60}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 90, 101, 170}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 20, 38}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 130, 220, 215, 200}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 211, 65, 75, 223}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 198}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 46, 243}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 107, 115, 214}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 181, 143}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 124, 22, 180}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 188, 187, 42, 192}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 239, 206, 120, 148}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 243}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 9}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 21}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 9, 145}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 48, 34, 188}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 132, 128, 140, 117}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 99, 113, 60, 172}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 65, 155, 224}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 88, 81}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 201, 184}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 145, 243, 181, 91}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 123, 148, 16}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 174}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 225, 144, 12}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 66}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 229}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 100, 71, 113}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 222, 121, 58}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 124, 173}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 182, 56}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 48}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 230}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 173}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 199, 73, 207, 4}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 96, 20}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 223}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 163, 171, 68, 229}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 175, 122}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 99, 23, 239, 145}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 74}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 193, 164, 219}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 164, 52}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 150}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 198}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 105, 14, 146, 234}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 130}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 138}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 15, 176, 164}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 61, 65, 73, 218}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 93, 161, 125, 94}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 237, 84, 127, 137}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 207, 31, 182}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 165, 59}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 166, 227}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 244, 41, 191, 114}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 246, 190}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 65, 101, 117, 47}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 99, 248, 29, 239}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 72, 63, 205}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 40, 132}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 118, 46, 73}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 254, 171}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 28, 39, 211}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 160, 213, 157, 251}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 142, 224, 60}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 115, 117}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 202}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 77, 226, 212, 210}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 213, 174}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 10, 40}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 89}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 178}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 180, 134}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 248, 253, 238, 122}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 41}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 98, 54}, 32}, {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 63, 2, 112, 56}, 32}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 137, 240, 74, 22, 140, 91, 13}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 4, 22, 132, 50, 235, 86}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 56, 193, 138, 223, 192, 116, 37}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 164, 59}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 34, 235, 41}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 220, 143, 101, 140, 191, 146, 98}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 250, 15, 79, 172}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 222, 241, 48, 208, 230}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 193, 142, 255, 235, 201, 48}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 9}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 20, 170, 5, 127}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 29, 241, 154}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 221, 250, 61, 104, 133, 14}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 71, 125, 15}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 161, 78}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 150, 79, 228, 111}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 140, 5, 154, 184}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 11, 158, 92, 113, 43, 3}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 191, 224, 27, 29, 85, 37}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 110}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 61, 210, 12, 205, 46, 187}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 125, 72, 170}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 119}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 100, 45}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 143}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 106, 230}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 175, 144, 228}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 201}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 84, 48, 63}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 230, 141}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 62}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 152, 175}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 141, 251, 33, 65}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 132, 46, 225, 103}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 39, 42, 167}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 169, 239, 180, 146, 233, 67}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 242, 151, 35, 171, 135}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 175, 129}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 160, 48, 189, 251}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 227, 180}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 205, 179, 105}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 195, 209, 114}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 163, 134, 40}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 37, 15, 22}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 175, 177, 154, 69}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 101, 83, 6}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 219, 123, 218, 111}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 164, 137, 238, 213, 60, 61}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 44, 208}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 120, 183, 133, 74, 90}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 43}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 121}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 146}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 157}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 161, 117, 142, 118, 213, 221}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 114}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 63, 15}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 93}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 148, 169, 64, 24, 4}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 99}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 249, 16, 94, 23, 99}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 145, 252, 222, 207, 119}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 198, 96, 180, 176}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 22, 82, 27, 119, 218}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 165, 169, 229, 220}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 168}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 27, 161}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 132, 18, 192, 26, 37, 92}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 218}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 181, 8, 42, 40, 150, 129}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 102, 174, 145}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 250, 41, 24}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 106, 96, 96, 145, 175, 114}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 223, 250, 178, 142, 249, 80, 74}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 106, 139, 40, 9, 225, 153}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 55, 21, 215, 0}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 90, 14}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 217, 194, 2, 205, 10, 41}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 172, 133, 75, 67}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 117}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 71, 213, 158}, 137}, {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 89, 187, 178}, 137}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 191, 132, 192, 120, 156, 230, 142}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 241, 107, 81, 155, 92, 13}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 194, 157, 163, 25, 95, 111, 188, 200}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 36, 13, 70, 199, 127}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 90, 187, 0, 180, 60, 91, 19, 50}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 55, 131}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 206, 122, 203, 71, 66, 42, 183, 33}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 159, 192, 38, 112}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 14, 197, 26, 173, 29, 64}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 170, 224}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 207, 22, 154, 148, 96}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 93, 217, 110}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 47, 64, 127, 29, 172, 90, 30, 176}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 48, 150}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 54, 55, 85, 200, 28, 170, 182}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 207}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 57, 59}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 104, 121}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 17, 213, 40, 130, 31, 182, 181, 89}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 153, 78, 134, 193, 245, 180}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 152, 4, 77, 74, 78, 143}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 189, 232, 195}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 132}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 186, 107, 254, 24}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 4, 222, 63, 213}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 11, 14, 129, 194, 95, 159, 234}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 231, 30, 238, 136, 26, 122, 61}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 60, 119, 85}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 91, 159, 152, 216, 173, 244}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 153, 105, 217, 236, 225, 230}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 123, 153, 133, 209, 174}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 140}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 175, 199, 163, 177, 122}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 231, 22, 103, 85, 196, 171}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 103, 147, 224, 15, 25, 151, 239}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 8, 77, 7}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 157, 109, 180}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 158, 204, 247}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 129, 71, 134, 57, 79}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 255, 174, 109}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 11, 105, 158, 211, 131}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 1, 179, 94, 30, 40, 249, 162, 175}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 50, 127}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 172, 58, 159, 24, 1}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 73, 127, 182, 20, 165, 215, 174, 84}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 152}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 184, 62, 87, 114, 83, 142, 36, 223}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 136, 20, 136, 58}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 208, 62, 149, 137, 239, 217, 176}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 176, 22, 193, 199, 50, 163, 246}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 179, 218, 110, 201, 19, 69}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 76, 239, 109, 170, 13, 19}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 117, 83, 172, 192}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 130, 182, 69, 188, 148, 165, 149, 90}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 39, 204, 37, 108, 250, 9}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 43, 196}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 101, 78, 149}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 151, 163, 81, 35, 217}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 228}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 7, 169, 207, 192}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 165, 33}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 110, 117, 166, 13, 242, 42}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 249, 230, 63, 249, 105}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 23, 209, 43, 156, 192, 23}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 178, 136, 205}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 137, 136, 209, 189, 11, 51}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 111, 98}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 117, 144, 119}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 94, 196}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 50}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 69, 232, 196, 64, 95, 124, 15}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 249, 162, 80, 84}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 59, 221, 127, 136, 94, 65, 47}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 8, 137}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 220, 158, 88, 241}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 88, 91, 249}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 80, 231, 48, 243, 122, 119, 50, 178}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 177, 21, 9, 56, 109, 139}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 111, 52, 241, 161, 225, 72}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 163, 0, 240, 11}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 220, 29, 206}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 222, 27, 140}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 231, 91, 191}, 2}, {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 189, 30, 14}, 2}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 236, 134, 144}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 38, 118}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 30, 133, 184, 210, 216, 99, 113}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 177, 36, 127, 231, 48, 101, 60}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 220, 176, 111, 246, 233}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 157, 190, 200}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 160, 173}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 165, 92, 204, 71, 143}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 240, 215, 10, 189, 233}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 60, 2, 7, 242, 33, 239, 156}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 2, 136, 253, 136, 41, 78}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 73, 107, 247, 47, 166, 177}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 131, 51, 145, 207, 150, 17}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 128, 214, 108, 182, 40, 148, 39}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 180, 164, 31, 121, 192, 139, 247}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 14}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 145, 82, 146, 36}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 167, 54, 87}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 65, 207, 148, 56, 225, 238}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 95, 231}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 3, 135, 223, 1, 140}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 131, 162, 156, 197, 178, 155}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 192, 253, 83, 77, 49, 195, 31, 254}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 57, 21, 159, 182, 230, 23}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 87, 124, 141, 99, 113, 88}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 116, 70, 228, 171, 174, 211, 253}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 193, 93, 167, 22}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 123, 185, 163, 252}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 243, 208, 80, 50, 251, 25, 121}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 228, 182}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 152, 78, 44}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 90, 150, 211, 54, 74}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 91, 210, 75, 85, 123, 70, 59}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 43, 204, 142, 151, 165, 33}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 20, 240, 253, 10, 33}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 216, 116, 121, 176, 222}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 68, 168, 84, 244, 221, 118, 95}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 73, 102, 92, 231, 74, 153, 15}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 94, 71}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 34, 58, 164, 246, 196, 111}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 103, 223, 147, 210, 7, 70}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 232, 76, 232}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 123, 203}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 52, 53, 198, 75}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 248, 3, 33, 183, 178, 210, 1}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 94, 86, 162, 245}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 183, 116, 179, 46, 83, 173, 7}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 2}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 219, 107, 164}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 80, 9, 112, 216, 41, 115}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 16, 171, 129, 91, 127}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 9, 208, 237, 35, 55}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 65, 81, 177, 137, 10, 87, 64, 249}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 102}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 191, 134, 151, 82, 80}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 6}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 90, 54, 225, 193, 232}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 218}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 255, 254, 149, 76, 159, 173, 80}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 187, 10, 102, 177, 34, 34}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 147, 181, 112, 116, 46, 143}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 70, 238, 61, 23, 55, 93}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 72, 231, 111, 108, 186, 252, 94}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 120, 18, 131, 19, 98, 7, 204}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 25, 177, 140}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 231, 50, 160, 242, 84, 247, 162}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 43, 87, 83, 115}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 184, 7, 82, 25}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 226, 228, 226, 233, 199, 14}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 7, 251, 128, 19, 143}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 190, 161}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 185, 73, 121, 238, 39, 236}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 51}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 146, 25}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 151, 83, 216, 100, 50, 30, 207}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 6, 117, 249, 190, 31}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 64, 253, 210, 162, 27, 98, 238}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 245}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 194, 17, 244, 124}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 91, 126, 24, 145, 226}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 21, 144, 10}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 22, 177, 28, 253, 142, 130}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 78, 17, 98, 214, 186, 21}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 194, 17, 223}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 250, 5}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 129, 79, 245, 224, 208, 83, 253}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 115, 9}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 245, 52, 221, 123, 51}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 143, 3}, 163}, {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 123}, 163}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 108, 136}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 106, 5}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 222, 255}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 13}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 15}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 50, 169}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 2, 220}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 154, 90, 153}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 254, 168, 83}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 18, 156}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 8, 160}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 163}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 112, 166}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 68}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 215}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 12, 43, 95}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 31, 251, 223}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 32, 185, 21}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 99, 160, 81}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 20}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 13, 55}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 220, 152}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 226, 45}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 244}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 64, 140}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 94, 194}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 100, 6}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 143, 27}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 160}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 184}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 208, 79}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 92}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 140}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 59, 27}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 105, 197}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 202, 89}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 164, 19}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 252}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 156, 232}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 245}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 238, 143}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 229, 59}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 201, 93}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 164, 176}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 154, 125}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 95}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 64}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 184, 57, 47}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 219}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 69}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 168}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 217}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 42}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 121, 94}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 28}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 83, 139, 114}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 234, 219}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 49, 219, 3}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 84, 165}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 162, 180}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 63, 247, 174}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 176, 205}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 183, 23}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 164}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 6, 210, 232}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 118}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 62}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 243}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 206, 100}, 162}, {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 91, 23, 147}, 162}, {{161, 64, 0, 0, 0, 0, 128, 101, 47, 2, 74, 86, 38, 169, 181, 58}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 91, 151, 146, 111, 137, 241, 184}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 196, 1, 93, 94, 145, 230, 225, 82}, 192}, {{161, 64, 0, 0, 0, 0, 59, 93, 255, 171, 165, 60, 71, 219, 249, 30}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 192}, {{161, 64, 19, 159, 199, 89, 51, 72, 82, 248, 175, 171, 225, 219, 94, 253}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 189, 153, 200}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 6, 196, 255, 169, 49, 227}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 253, 5, 179, 20, 213, 138, 107, 122}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 126, 254, 23, 115, 158, 29, 175, 124}, 192}, {{161, 64, 0, 0, 208, 22, 97, 180, 165, 34, 6, 146, 90, 28, 56, 76}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 57, 141, 197, 76, 188, 106, 232, 19, 225, 31, 236, 240, 147, 171}, 192}, {{161, 64, 0, 0, 0, 0, 70, 171, 78, 237, 49, 145, 83, 162, 6, 145}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 76, 166, 173, 183, 205, 79, 169}, 192}, {{161, 64, 0, 0, 0, 0, 0, 207, 236, 49, 139, 204, 5, 72, 208, 160}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 37, 144, 179, 175, 91, 11, 219, 46}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 214, 180, 117, 62}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 214, 223}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 243, 25, 148, 110, 202, 130}, 192}, {{161, 64, 152, 107, 165, 87, 89, 92, 82, 218, 181, 148, 214, 184, 96, 39}, 192}, {{161, 64, 0, 0, 0, 221, 203, 216, 61, 144, 105, 248, 190, 251, 76, 30}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 172, 174, 192, 152, 127, 155, 18, 249}, 192}, {{161, 64, 0, 0, 0, 0, 0, 121, 1, 79, 7, 160, 132, 94, 62, 86}, 192}, {{161, 64, 0, 0, 0, 0, 2, 10, 149, 63, 194, 108, 15, 56, 164, 186}, 192}, {{161, 64, 0, 17, 206, 140, 160, 184, 2, 134, 181, 126, 218, 208, 81, 54}, 192}, {{161, 64, 0, 0, 0, 0, 0, 128, 220, 233, 46, 179, 249, 125, 7, 61}, 192}, {{161, 64, 0, 185, 12, 186, 190, 18, 230, 93, 84, 184, 195, 113, 32, 197}, 192}, {{161, 64, 0, 7, 65, 100, 155, 38, 220, 34, 118, 139, 46, 103, 192, 30}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 153, 40, 201, 135}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 194}, 192}, {{161, 64, 0, 0, 0, 0, 122, 163, 150, 106, 120, 109, 62, 103, 202, 230}, 192}, {{161, 64, 199, 130, 48, 70, 233, 92, 106, 65, 66, 203, 17, 172, 20, 69}, 192}, {{161, 64, 91, 119, 36, 135, 1, 193, 95, 144, 179, 88, 96, 62, 204, 247}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 116, 224, 18, 104, 0, 209}, 192}, {{161, 64, 0, 0, 0, 0, 0, 240, 104, 224, 107, 188, 82, 184, 231, 158}, 192}, {{161, 64, 0, 0, 0, 149, 60, 42, 13, 171, 107, 77, 235, 6, 52, 119}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 48, 110, 122, 183, 71, 179, 6}, 192}, {{161, 64, 0, 0, 0, 214, 235, 35, 21, 171, 117, 47, 197, 224, 127, 27}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 150, 248, 173, 195, 88, 107, 176, 60}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 172}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 196, 67, 39, 146, 131, 52}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 123, 107, 79}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 63}, 192}, {{161, 64, 0, 0, 0, 0, 0, 192, 39, 101, 173, 146, 146, 144, 84, 197}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 112, 46, 229, 75, 15, 158}, 192}, {{161, 64, 0, 0, 0, 0, 0, 46, 131, 222, 173, 22, 229, 96, 82, 216}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 147, 232, 110, 4, 126, 113, 135, 137}, 192}, {{161, 64, 0, 0, 0, 0, 0, 93, 227, 99, 39, 19, 118, 23, 244, 36}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 95, 209, 63, 210, 195, 82, 16, 142}, 192}, {{161, 64, 0, 0, 0, 0, 226, 22, 131, 197, 136, 62, 64, 140, 99, 167}, 192}, {{161, 64, 0, 0, 0, 0, 0, 185, 215, 157, 223, 212, 225, 37, 216, 13}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 26, 189, 85, 178, 134, 90, 182, 45, 81, 135}, 192}, {{161, 64, 0, 0, 0, 0, 0, 185, 245, 188, 102, 207, 160, 42, 137, 40}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 51, 168, 203, 48, 82, 34, 3, 53}, 192}, {{161, 64, 0, 0, 0, 0, 0, 205, 199, 173, 83, 8, 150, 99, 151, 76}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 252, 63, 159, 134, 155, 77}, 192}, {{161, 64, 0, 0, 106, 255, 227, 103, 32, 86, 183, 148, 219, 40, 67, 231}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 134, 192, 15, 39, 1, 218, 86, 27, 110, 202}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 169, 23, 102, 107, 51, 80, 115, 101, 181}, 192}, {{161, 64, 0, 0, 196, 213, 19, 117, 58, 193, 5, 76, 121, 218, 183, 29}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 166}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 73, 51, 16, 44, 141, 55}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 156, 95, 206, 2, 241, 117, 195, 157}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 232, 15, 206, 203, 220, 28, 153, 155}, 192}, {{161, 64, 0, 0, 135, 192, 225, 81, 141, 195, 39, 169, 135, 158, 239, 166}, 192}, {{161, 64, 65, 241, 45, 65, 17, 43, 183, 25, 180, 50, 31, 5, 9, 157}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 223, 109}, 192}, {{161, 64, 130, 174, 108, 176, 186, 212, 126, 177, 62, 189, 32, 210, 20, 128}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 220, 7, 50, 76, 3, 5, 199}, 192}, {{161, 64, 0, 0, 48, 58, 25, 47, 49, 200, 68, 242, 141, 147, 176, 251}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 37, 230, 70, 162, 214, 20, 245, 114}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 132, 242, 67, 65, 94, 21}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 88, 233, 23}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 209, 100, 65, 86, 123, 35, 100, 91}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 155, 181, 108, 186}, 192}, {{161, 64, 0, 0, 0, 209, 228, 115, 163, 106, 247, 69, 168, 5, 229, 117}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 56, 145, 10, 205}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90}, 192}, {{161, 64, 0, 0, 0, 0, 0, 235, 17, 153, 1, 208, 252, 243, 176, 27}, 192}, {{161, 64, 0, 0, 80, 215, 226, 117, 245, 95, 31, 86, 40, 227, 251, 46}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 52, 174, 50, 114, 232, 158}, 192}, {{161, 64, 0, 0, 0, 0, 0, 192, 164, 27, 117, 17, 145, 250, 116, 164}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 54, 254, 127, 70, 188, 89, 222, 246}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 124, 187, 245}, 192}, {{161, 64, 0, 0, 0, 0, 0, 79, 144, 6, 82, 216, 225, 30, 217, 201}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 103, 244, 31, 53, 229, 252, 208, 52}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 192}, {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 150, 101, 134, 54}, 192}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 186, 180, 109, 253, 0, 175}, 185}, {{233, 70, 240, 45, 240, 0, 171, 165, 209, 153, 249, 75, 218, 42, 159, 172}, 185}, {{233, 70, 240, 45, 240, 90, 177, 199, 128, 30, 55, 223, 68, 175, 118, 26}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 185, 99, 22, 50, 106, 204, 51, 124}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 158}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 62, 151, 162, 52}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 204, 198, 116, 22, 210, 182}, 185}, {{233, 70, 240, 45, 240, 0, 0, 184, 234, 131, 189, 6, 199, 125, 52, 147}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 238, 230, 67}, 185}, {{233, 70, 240, 45, 240, 0, 246, 27, 109, 225, 36, 83, 195, 12, 217, 165}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 122, 182, 29}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 88, 23, 15, 185, 162, 210}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 9, 227, 181, 60, 73, 234, 150}, 185}, {{233, 70, 240, 45, 240, 0, 163, 100, 134, 236, 171, 227, 2, 18, 66, 212}, 185}, {{233, 70, 240, 45, 240, 0, 0, 236, 182, 160, 20, 25, 239, 92, 217, 132}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 37, 68, 209, 162, 246, 154}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 27, 227, 22, 253}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 23}, 185}, {{233, 70, 240, 45, 240, 0, 133, 145, 24, 20, 188, 104, 174, 77, 69, 152}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 48, 248, 180}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182}, 185}, {{233, 70, 240, 45, 240, 0, 34, 24, 174, 52, 25, 53, 144, 210, 233, 184}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 78, 246, 12, 147, 200, 219, 56, 52}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 160, 85, 80, 141, 127, 168, 111, 65}, 185}, {{233, 70, 240, 45, 240, 49, 7, 159, 71, 4, 71, 33, 105, 71, 169, 3}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 40}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 178, 212, 249, 123, 148, 251, 152}, 185}, {{233, 70, 240, 45, 240, 165, 121, 37, 69, 119, 87, 47, 164, 118, 169, 125}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 97, 191, 148, 99, 186, 124, 70, 75}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 64, 165, 69}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 125, 219, 45, 83}, 185}, {{233, 70, 240, 45, 240, 0, 74, 5, 171, 101, 64, 168, 44, 235, 115, 42}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 89}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 184, 54, 130, 72, 199, 223, 57, 95}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 149, 150, 255, 103}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 5, 219, 22, 162, 236, 112, 185}, 185}, {{233, 70, 240, 45, 240, 0, 43, 37, 149, 153, 223, 151, 159, 20, 229, 201}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 135, 148, 202, 56, 191}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 197, 46, 75, 254, 141, 181, 36, 48}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 126, 37, 253, 36, 80}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 208}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 11, 64, 37, 64, 34, 0, 20}, 185}, {{233, 70, 240, 45, 240, 0, 0, 247, 61, 101, 71, 37, 10, 146, 127, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 218}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 7, 122, 253, 174, 119}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 100, 172, 197, 107, 249, 190, 194, 127}, 185}, {{233, 70, 240, 45, 240, 0, 0, 190, 226, 57, 164, 109, 158, 7, 197, 217}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 235, 67, 77, 92, 200}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231}, 185}, {{233, 70, 240, 45, 240, 0, 63, 123, 60, 86, 40, 101, 52, 22, 33, 247}, 185}, {{233, 70, 240, 45, 240, 0, 24, 134, 255, 9, 133, 181, 77, 144, 80, 5}, 185}, {{233, 70, 240, 45, 240, 0, 108, 56, 188, 179, 185, 189, 85, 20, 194, 67}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 42, 83, 137, 11, 255, 192, 80, 145}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 101, 149, 8, 193, 14, 189, 157}, 185}, {{233, 70, 240, 45, 240, 0, 0, 95, 218, 29, 122, 95, 194, 197, 9, 224}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 197, 117, 184, 138}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 131, 124, 154, 195, 23}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 188}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 143, 145, 237, 197, 179, 84, 16}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 12, 42, 255, 235, 20, 254}, 185}, {{233, 70, 240, 45, 240, 0, 255, 121, 185, 66, 31, 34, 47, 232, 136, 75}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 217, 248, 3, 35, 136, 180, 120}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 109, 202, 246}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 8}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 28}, 185}, {{233, 70, 240, 45, 240, 0, 133, 175, 104, 44, 199, 53, 230, 6, 167, 228}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 129, 170, 84, 100, 177, 250, 164}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 176, 139, 202, 115, 144, 157, 190, 248}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 13, 189, 213, 130, 175, 59, 198}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 160, 56, 244, 230, 138}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 153, 214, 223, 188, 253, 50, 42, 118, 1}, 185}, {{233, 70, 240, 45, 240, 185, 180, 230, 26, 188, 195, 73, 215, 203, 197, 251}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 65, 131, 80, 32, 96, 210, 8, 206, 198, 190}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 108, 67, 188, 229, 127, 64, 42}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 211, 227, 82, 133, 134}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 34, 164, 156, 0, 19, 135, 163}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 244, 236, 28, 130, 25, 189, 36, 6}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 184, 28, 55, 244, 196, 236}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 228, 118, 61, 115, 230, 52}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 203, 193, 241, 224, 28, 47, 244}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 105, 209, 165, 163}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 59, 185, 144, 251, 244, 204, 228}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 39, 228, 31, 193, 179, 224, 148, 169}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 56}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 171, 25, 157}, 185}, {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 81, 50, 144, 159, 51, 63}, 185}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 204, 247, 138}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 45, 98, 24, 52, 43, 50, 216, 70}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 160}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 19, 176}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 170, 27, 158, 32, 63, 2, 73}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 134, 72, 165, 17, 137, 36, 108}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 243, 228, 196, 249}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 113, 182, 58}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 60, 86, 128, 29, 252}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 32, 26, 68, 137}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 121, 66, 5}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 43, 112}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 85, 90, 70, 53, 197}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 231, 51, 119, 32, 175}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 150}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 67, 37, 78, 71}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 109, 8, 113, 171, 147, 47, 192, 122}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 4, 29, 209}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 121, 26, 49, 237, 52, 176, 19, 22}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 115, 43, 105}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 201, 181, 232, 171, 188, 40, 105, 2}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 139, 43, 3, 112, 57}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 238, 21, 34, 75, 117}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 205, 13, 119}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 158, 177, 97, 114, 217, 34}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 88}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 115, 20}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 157}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 239}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 142, 178, 60, 144, 43, 153, 248, 225}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 21, 244, 48, 76, 114}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 139, 198, 212}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 78, 128}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 160, 238}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 187, 152, 10, 113, 120, 63, 88, 78}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 175, 115, 65, 85, 242, 50, 80, 81}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 166, 159, 13, 145, 124, 212}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 233, 131, 252, 151, 129, 11}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 90, 127, 161, 37}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 220, 16, 46, 5, 194, 223}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 210, 51, 79, 21, 90, 217, 142}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 71}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 197, 191, 61, 226}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 124, 158, 85, 199, 214, 49, 29, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 237, 147, 204, 149, 152}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 40, 149, 105, 246, 133, 65, 33}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 153, 101, 122, 146, 198, 65}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 168, 59, 193, 125}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 23, 40}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 176}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 188, 208, 252}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 16}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 247, 93}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 167, 53, 94, 52, 28, 226, 207}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 102, 76, 204, 79, 54, 199, 107, 226}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 164}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 201, 145, 32, 40}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 219, 125, 251, 255}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 225, 6, 208, 158, 248, 196, 39}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 10, 104, 241, 180, 136, 154, 56, 169}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 149}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 77, 6, 202, 38}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 253, 162, 91, 86, 144}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 218, 148, 106}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 198, 171, 70, 210, 135, 210, 245}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 7, 72, 177, 249, 145, 139}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 181, 103, 35}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 190, 254, 143}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 20, 95, 253, 89, 75, 207}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 208, 144, 79, 7}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 164, 235, 173, 8, 7}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 55, 206, 230, 196}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 23}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 27}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 111, 215, 189}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 217, 72, 3, 191, 172, 31, 73}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 104, 202, 66, 180, 13}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 153, 190, 195, 70, 162, 159}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 207, 237, 215, 32, 89, 69}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 154, 89, 150}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 84, 36, 130, 193, 45, 168}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 21}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 86, 153, 69, 23, 123, 204, 82}, 51}, {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 169, 45, 236, 42, 50, 187}, 51}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 63, 118, 46, 92, 95, 223}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 89, 38, 88, 33, 153, 183, 219, 203}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 158, 55}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 25, 10, 135, 21, 210, 65, 15}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 83, 124, 228, 4}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 101, 10, 200, 58, 5, 232, 103}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 143, 130, 246, 12, 202, 41, 15, 173}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 230, 171, 219, 231, 16}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 36, 13, 120, 235, 153, 185, 42, 98}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 132}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 166, 13, 119}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 210, 17, 197, 215, 172, 252, 219, 84}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 148, 216, 14, 129, 122, 229, 245, 249}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 213, 199, 81, 207, 106, 89, 59, 97}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 13, 152, 255}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 116, 255, 80, 123, 190, 233}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 39, 190, 103}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 89, 94, 178, 169, 16, 69, 200, 78, 84}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 92, 189, 107, 106, 142, 198, 112}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 101}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 160, 43, 102}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 132, 44, 204, 152, 12, 180}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 32}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 68, 99, 127}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 40, 29, 75, 194, 7, 188, 231}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 133}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 156, 154, 149}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 65, 182}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 74, 26, 175}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 92}, 93}, {{146, 197, 243, 235, 243, 56, 140, 244, 151, 77, 10, 135, 88, 154, 117, 209}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 129, 174, 155, 76, 243, 186, 182, 120}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 81, 26}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 45, 131, 55, 115, 163, 185, 204}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 69, 28, 251, 133, 120}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 3, 213, 145, 181, 188, 238, 30}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 203, 84, 156, 234, 30, 48, 132, 189}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 233, 81, 0, 234, 221}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 222, 9, 25, 177, 143, 5}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 146, 126, 110, 164, 53, 30, 86, 230}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 248, 177, 139, 204, 155, 243, 122}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 1, 73, 204, 118, 254, 73, 226}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 171, 164}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 101, 103, 144}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 199, 182, 71, 131, 40, 172, 197, 247}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 153, 157, 48, 201, 147, 130}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 163, 46}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 96, 35, 124, 76, 183, 216, 199, 192}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 203, 152, 175, 230, 54, 251, 127, 139}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 161, 222, 130, 208, 73, 115, 238, 40}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 215, 221, 14, 57}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 174, 4, 45, 133, 150, 113}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 75, 49}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 215}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 221, 123}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 161, 107}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 164, 71, 220, 111, 150}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 182, 64, 44, 102, 43, 224, 79}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 186, 33, 36, 152}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 208, 93, 20, 143, 221}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 169}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 189, 217, 229, 62, 111}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 231, 68, 197, 63, 38, 228, 85}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 74, 36, 104, 80, 223, 151, 55}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 242}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 140}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 56, 167}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 61, 138, 107, 198, 30, 147, 3}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 44, 245, 224, 73, 156, 40, 189, 180}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 97}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 150, 146, 106, 123, 67, 38, 169, 117}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 74, 152, 107, 155, 173, 236}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 241, 199, 70, 38}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 222, 40, 123, 253}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 85, 207}, 93}, {{146, 197, 243, 235, 243, 56, 140, 146, 62, 167, 50, 116, 99, 184, 46, 222}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 141, 226, 99, 77, 219, 16, 118, 185}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 175, 200, 70, 217, 155}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 136, 169, 180, 23}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 243}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 59, 56, 49, 230, 176, 192, 2}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 36}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 239, 244, 185, 211, 164, 143, 16}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 114, 159, 103, 28, 75}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 83, 178, 136}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 88}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 93}, {{146, 197, 243, 235, 243, 56, 140, 0, 0, 223, 72, 39, 167, 29, 7, 56}, 93}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 249, 214, 246, 97, 116, 193}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 80, 189, 18, 98, 134}, 61}, {{0, 0, 0, 0, 127, 61, 140, 86, 77, 116, 180, 161, 17, 200, 185, 121}, 61}, {{0, 0, 0, 68, 56, 51, 110, 19, 147, 155, 98, 247, 247, 190, 91, 150}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 80, 87, 234}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 7}, 61}, {{0, 0, 0, 0, 0, 0, 143, 169, 140, 106, 85, 182, 86, 99, 242, 30}, 61}, {{0, 0, 0, 0, 56, 100, 212, 144, 149, 230, 252, 46, 249, 229, 194, 106}, 61}, {{0, 0, 65, 185, 248, 229, 119, 62, 208, 72, 18, 202, 127, 92, 4, 217}, 61}, {{0, 0, 0, 0, 0, 0, 255, 142, 105, 12, 154, 105, 234, 61, 53, 223}, 61}, {{0, 0, 0, 0, 76, 148, 115, 229, 118, 108, 58, 44, 74, 34, 211, 237}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 221, 204}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 216, 146, 92}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132, 147, 5}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 233, 74, 250, 149, 15}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 124, 152, 131, 65}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 6, 100, 60, 75, 139, 88, 183, 194, 43, 101, 110, 140}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 211, 34, 10, 17, 140, 179}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 57, 72, 19, 162}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 60, 210}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 83, 11, 225, 93, 187, 112, 133, 31}, 61}, {{0, 0, 0, 0, 0, 0, 198, 248, 211, 253, 255, 33, 170, 145, 28, 23}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 250, 120, 7, 115, 193}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189}, 61}, {{0, 0, 123, 27, 198, 2, 180, 222, 173, 234, 15, 67, 163, 152, 88, 41}, 61}, {{0, 20, 219, 171, 21, 217, 145, 214, 88, 189, 4, 67, 26, 193, 78, 68}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 112, 3, 50, 144}, 61}, {{0, 0, 0, 0, 0, 0, 0, 40, 224, 130, 246, 20, 41, 97, 28, 113}, 61}, {{0, 0, 0, 0, 0, 0, 185, 225, 120, 86, 62, 239, 114, 204, 12, 94}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 187, 150, 58, 86, 122, 223, 119, 56, 181, 62, 82, 53}, 61}, {{0, 0, 0, 0, 0, 221, 137, 181, 159, 125, 220, 202, 175, 211, 135, 28}, 61}, {{0, 0, 0, 0, 0, 149, 232, 17, 81, 245, 86, 159, 167, 64, 111, 79}, 61}, {{0, 0, 0, 38, 111, 234, 117, 17, 91, 252, 185, 88, 185, 166, 187, 3}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 120, 186, 79, 240, 151, 1, 181, 140, 18}, 61}, {{0, 0, 0, 33, 236, 44, 246, 33, 124, 147, 187, 84, 88, 226, 87, 128}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194}, 61}, {{0, 0, 0, 0, 45, 61, 209, 64, 110, 238, 178, 252, 186, 139, 216, 118}, 61}, {{0, 0, 0, 191, 225, 124, 185, 175, 22, 54, 26, 221, 245, 80, 112, 120}, 61}, {{0, 0, 0, 0, 202, 93, 221, 81, 53, 16, 104, 226, 26, 247, 215, 139}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 95, 208, 130, 38, 198, 72, 194, 44}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102}, 61}, {{0, 228, 44, 63, 196, 51, 97, 70, 20, 177, 54, 82, 163, 130, 73, 185}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 251, 4, 223, 5, 10}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 101, 4, 62, 234, 86, 7}, 61}, {{0, 0, 0, 0, 191, 79, 85, 57, 188, 171, 227, 116, 3, 45, 46, 104}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 8, 160, 46, 204, 199, 104}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 194, 110, 223, 63}, 61}, {{0, 80, 148, 166, 30, 230, 205, 38, 29, 118, 70, 199, 28, 165, 8, 5}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 236, 166, 94, 249, 107, 64}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 203, 172, 63}, 61}, {{0, 0, 0, 0, 0, 0, 0, 155, 134, 245, 247, 91, 16, 101, 108, 206}, 61}, {{0, 0, 0, 0, 0, 238, 243, 55, 2, 240, 22, 38, 34, 2, 3, 180}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 168, 87, 237}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 19}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 128, 78, 205, 42, 128, 89}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 16, 193}, 61}, {{0, 0, 0, 0, 0, 0, 65, 51, 251, 54, 74, 130, 101, 130, 210, 209}, 61}, {{0, 0, 0, 0, 0, 0, 0, 87, 138, 146, 63, 227, 230, 107, 23, 15}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 194, 132, 107, 53, 177, 249}, 61}, {{0, 0, 196, 97, 3, 83, 16, 122, 155, 136, 68, 140, 86, 26, 178, 244}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 70, 224, 119, 127, 186}, 61}, {{0, 0, 0, 0, 0, 0, 27, 25, 73, 174, 102, 232, 49, 222, 144, 188}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 9, 74, 50, 194, 26}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 61}, {{0, 3, 89, 198, 185, 155, 183, 216, 131, 160, 27, 69, 75, 58, 220, 144}, 61}, {{0, 0, 0, 0, 0, 0, 0, 66, 146, 149, 71, 194, 226, 242, 41, 178}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 22, 33, 109}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 181, 170, 61, 86, 138, 90}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27}, 61}, {{0, 0, 0, 0, 14, 84, 249, 156, 104, 198, 242, 153, 240, 94, 196, 174}, 61}, {{0, 0, 0, 0, 172, 84, 217, 244, 166, 42, 101, 254, 32, 35, 117, 131}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 212, 41}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 91, 111, 179, 6, 79, 110}, 61}, {{0, 0, 0, 147, 150, 139, 72, 137, 227, 96, 140, 229, 104, 83, 111, 145}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 216, 154}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 24}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 117, 69, 82, 111, 53, 201, 8, 129}, 61}, {{0, 0, 0, 0, 0, 71, 77, 199, 55, 50, 36, 40, 221, 31, 139, 174}, 61}, {{0, 0, 60, 2, 118, 83, 202, 232, 196, 110, 153, 26, 147, 209, 60, 139}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 133, 69, 113, 10, 105, 252}, 61}, {{0, 0, 0, 0, 103, 221, 104, 20, 142, 15, 112, 40, 235, 83, 19, 189}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 0, 145, 37, 33, 51, 25, 47, 0, 205, 155, 124}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 65, 114, 123, 231, 136, 216, 36, 3}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 134, 158, 247, 241, 244, 237, 47, 112}, 61}, {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61}, {{0, 0, 0, 0, 0, 59, 77, 85, 181, 121, 29, 16, 71, 31, 70, 155}, 61}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 231, 220}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 134, 219}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 185}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 130, 15, 46, 153, 202, 118}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 133, 90, 231, 204, 198}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 134, 48, 24}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 71, 172, 170}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 217}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 88}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 188, 71, 187, 122, 199}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 247, 70, 240, 91, 81}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 134, 163, 26, 8, 73}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 97, 183, 44}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 175, 164, 103}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 34, 9, 98, 108}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 221, 88, 192, 240, 84, 50}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 189, 13}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 126, 34, 47}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 44, 148, 111, 64, 166, 239}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 93, 212, 111}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 180, 186, 167, 173, 229, 156}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 112, 192, 7, 212, 95}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 195, 27}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 132, 12}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 187, 94, 250, 141, 211}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 166, 14, 94, 56, 83, 111}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 95, 4, 120, 245, 93, 81}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 248, 78, 107, 245, 18}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 185, 109, 62, 167, 38}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 183}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 210, 94}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 251, 101, 27, 161}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 33, 49}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 175, 195, 203}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 171, 147, 205}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 140}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 115, 207, 203, 38, 201, 193}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 155, 242, 107}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 159, 4, 241, 204, 22, 218}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 2, 219, 126, 147, 105}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 119, 214, 116, 185}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 148, 238, 20, 63, 3}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 4, 66, 101, 21, 103, 10}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 98, 107, 16, 226, 231}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 24}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 107, 81, 81, 107}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 181, 179, 203, 72, 138}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 42}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 59, 101, 173, 58}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 98, 193, 242}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 114, 72}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 61, 61, 48}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 102, 91, 248, 131, 19, 96}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 132, 165, 194, 148, 18}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 83, 139, 201, 115, 130}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 25, 91, 131, 168}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 3}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 24, 16, 143, 100, 18, 172}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 151, 2, 145, 149}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 227, 23}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 76}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 99, 129, 18}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 12}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 191, 92, 162, 150}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 21, 141, 52, 48}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 176, 162, 188, 226, 204}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 56, 116, 182, 69, 58}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 254, 61, 212, 0, 146}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 122, 87, 252, 140, 49, 6}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 11, 200, 203, 99, 29, 12}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 138, 127, 34}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 215, 30}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 59, 167, 181}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 162}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 73, 3, 1}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 223}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 199}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 168, 10, 219, 1, 30}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 156}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 57}, 189}, {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 82, 134, 105}, 189}, {{164, 151, 192, 0, 218, 0, 146, 211, 35, 160, 218, 204, 62, 131, 38, 104}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 95, 165, 208, 211, 187, 169}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 49, 155, 185, 13, 174, 17, 251}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 140, 227}, 248}, {{164, 151, 192, 0, 0, 0, 201, 246, 180, 254, 207, 158, 132, 105, 99, 123}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 43, 67, 85, 17, 223, 11, 26}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 138, 121, 33}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 232, 198, 101, 198, 232}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 160, 184, 232, 0, 187}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 193, 237, 4, 35, 138, 183, 42}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 221}, 248}, {{164, 151, 192, 0, 0, 0, 0, 135, 82, 151, 88, 69, 23, 239, 6, 19}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 101, 217, 215, 4, 16, 42, 143, 198}, 248}, {{164, 151, 192, 214, 234, 48, 52, 118, 245, 88, 46, 91, 151, 155, 54, 82}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 49, 195}, 248}, {{164, 151, 192, 0, 0, 0, 21, 42, 119, 85, 43, 220, 83, 62, 117, 73}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 240, 147, 48}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 53}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 33, 240, 168, 239, 140, 231, 180}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 179, 42, 136, 166, 32}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 171, 41, 54, 171, 218}, 248}, {{164, 151, 192, 0, 48, 107, 30, 89, 42, 155, 246, 67, 177, 2, 89, 123}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 203, 120, 231, 153, 33, 60, 66, 137}, 248}, {{164, 151, 192, 0, 0, 0, 0, 89, 10, 135, 202, 84, 27, 232, 212, 221}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 235, 74, 41, 227, 188}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 205, 17, 117, 23, 140, 87, 40, 75}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 108, 38, 116, 225, 105, 134, 139, 221}, 248}, {{164, 151, 192, 0, 0, 0, 194, 98, 214, 65, 218, 130, 205, 246, 53, 133}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 235, 140, 69, 35, 82, 122, 6, 246}, 248}, {{164, 151, 192, 0, 0, 0, 11, 229, 222, 133, 4, 121, 63, 156, 218, 101}, 248}, {{164, 151, 192, 0, 0, 0, 0, 17, 130, 125, 145, 253, 29, 36, 100, 87}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 215, 230}, 248}, {{164, 151, 192, 0, 0, 0, 0, 189, 35, 236, 15, 85, 155, 122, 8, 121}, 248}, {{164, 151, 192, 0, 0, 0, 85, 37, 71, 197, 211, 216, 251, 254, 89, 191}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 233, 174, 116, 168, 168, 206, 198}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 29, 192, 67, 225, 248, 72}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 140, 207, 253, 66, 48, 157, 129, 14}, 248}, {{164, 151, 192, 0, 118, 30, 100, 208, 254, 29, 182, 110, 147, 163, 176, 248}, 248}, {{164, 151, 192, 97, 111, 181, 250, 237, 254, 251, 193, 0, 160, 28, 82, 190}, 248}, {{164, 151, 192, 0, 0, 87, 164, 122, 143, 172, 206, 48, 24, 253, 105, 178}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 249}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 47, 237, 15}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 182, 101, 45, 224, 113, 51, 54, 31, 26, 43, 186}, 248}, {{164, 151, 192, 0, 0, 0, 160, 72, 48, 79, 212, 212, 37, 145, 164, 235}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 228, 254, 190, 220, 199, 78, 200, 130}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 153, 64, 74}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 8, 22, 183, 182, 244}, 248}, {{164, 151, 192, 0, 0, 0, 0, 96, 157, 244, 46, 104, 141, 169, 157, 178}, 248}, {{164, 151, 192, 0, 0, 186, 98, 199, 69, 167, 136, 209, 105, 68, 185, 221}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 106, 219, 30, 95, 229, 54}, 248}, {{164, 151, 192, 0, 0, 0, 92, 188, 62, 187, 229, 234, 39, 73, 229, 33}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 31, 100, 246, 176, 81, 180}, 248}, {{164, 151, 192, 194, 238, 109, 121, 129, 92, 131, 139, 238, 145, 6, 171, 98}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 78, 49, 65, 97, 92, 19}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 224, 217, 205, 155, 175, 45, 230, 105}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 168, 168}, 248}, {{164, 151, 192, 0, 0, 176, 115, 215, 77, 91, 24, 28, 51, 195, 219, 242}, 248}, {{164, 151, 192, 0, 0, 91, 215, 207, 224, 83, 53, 20, 169, 214, 251, 39}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 133, 212, 66, 53, 63}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 96, 140, 70, 197, 51, 215, 73}, 248}, {{164, 151, 192, 0, 0, 0, 242, 81, 233, 123, 49, 77, 129, 9, 226, 179}, 248}, {{164, 151, 192, 0, 0, 0, 0, 184, 42, 133, 207, 72, 48, 150, 63, 36}, 248}, {{164, 151, 192, 0, 0, 244, 71, 0, 101, 42, 142, 127, 190, 125, 104, 105}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 40}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 43, 87, 48, 62, 159, 28, 170}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 72, 153, 92, 3, 229}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 192, 189, 21, 167, 209, 34}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 162, 198, 182, 210, 236, 22}, 248}, {{164, 151, 192, 0, 209, 158, 8, 163, 27, 19, 192, 234, 182, 122, 153, 146}, 248}, {{164, 151, 192, 0, 0, 0, 237, 237, 171, 215, 5, 142, 99, 163, 36, 155}, 248}, {{164, 151, 192, 0, 0, 0, 247, 171, 58, 75, 1, 105, 73, 168, 245, 239}, 248}, {{164, 151, 192, 0, 205, 190, 9, 121, 109, 181, 213, 241, 83, 56, 209, 48}, 248}, {{164, 151, 192, 0, 0, 0, 0, 23, 233, 244, 0, 28, 164, 212, 16, 130}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 86, 13, 202, 5, 137, 91, 54}, 248}, {{164, 151, 192, 0, 0, 0, 0, 205, 217, 244, 128, 109, 196, 249, 1, 202}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 0, 0, 35, 98, 212, 97, 81, 179, 158, 153, 199, 220, 97}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 130, 177, 136, 175, 224}, 248}, {{164, 151, 192, 0, 0, 0, 0, 5, 176, 63, 154, 21, 235, 171, 138, 223}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 244, 134, 12, 251, 235}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 176, 220}, 248}, {{164, 151, 192, 0, 165, 220, 175, 1, 82, 4, 103, 232, 233, 62, 24, 221}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 42, 200}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 195, 101, 107, 76, 152, 40}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 3, 9, 73, 67, 247, 79, 230}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 164, 57, 128}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 186, 208, 189, 6, 169, 71, 84, 244}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 149, 53, 146, 108, 85, 7}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 109, 58, 228, 51, 103, 45, 219}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 248}, {{164, 151, 192, 21, 40, 243, 32, 4, 180, 231, 195, 173, 9, 71, 101, 157}, 248}, {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 84, 62, 16, 12, 210, 40}, 248}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 38}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 124, 87}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 94, 87, 164, 65}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 31, 226, 70, 119, 100}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 223, 122, 34, 30}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 31, 79, 20}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 59, 122, 35}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 22}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 99, 101, 80}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 96}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 107, 119, 62}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 81, 138, 8, 22, 35}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 148, 62, 194, 91}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 146, 30, 33, 136, 167, 183}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 11, 175, 75, 87, 27}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 191, 38, 217}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 172}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 179, 18, 79, 113, 122}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 99, 30, 16, 81}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 245, 71, 155, 86}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 40, 38, 131, 126, 55}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 23, 21}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 255}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 203, 103}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 55, 123, 219, 164}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 194, 144, 51, 89}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 112, 228, 114}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 47, 113, 82}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 157, 29, 116}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 223, 244, 235}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 252, 228}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 24}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 15, 128, 205, 183}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 152}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 5, 40, 168, 170}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 208, 167, 146, 187}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 226, 154, 174, 195, 55}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 102, 128, 203, 210, 75, 225}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 4, 248}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 64, 104, 205}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 241, 11, 253}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 42, 66, 111, 174, 210, 143}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 59, 125}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 38, 183, 76, 252, 197}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 226, 195, 88, 146, 241}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 59, 245}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 113, 216, 80, 205, 228}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 172, 125, 211, 45}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 198, 102}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 94}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 94, 90, 46, 159, 36}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 72, 10, 153, 99}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 182, 6}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 223, 206, 185}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 246, 39}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 254}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 62, 247, 80}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 29, 88}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 51, 114}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 60, 128, 136, 42}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 5, 180}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 179, 67, 114, 112}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 96, 10}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 208, 24, 151, 141, 181, 155}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 4, 15, 199, 234, 97}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 248, 242}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 12, 220}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 35, 22, 238}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 188, 244, 189, 172, 232, 57}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 27}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 102, 149, 161, 206}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 180, 84}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 64, 104, 239}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 235, 175, 60}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 50}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 110, 192, 119, 58, 224}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 106, 189, 75}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 163}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 172, 176, 255}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 8, 74, 216, 130}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 50, 142, 38, 96, 248, 85}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 161, 229, 73, 107}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 216, 217, 238, 35}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 166, 33}, 167}, {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 197, 237}, 167}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 6, 30, 182}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 69, 49, 185, 199, 148, 46, 161, 66}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 97, 114, 153, 193, 6, 191, 112, 181}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 183, 12, 29, 86, 207, 26, 154}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 34, 174, 55, 125}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 116, 140, 99, 211, 7, 228, 143}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 198, 250, 3, 120, 88}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 81, 25, 255, 172, 108, 15}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 139, 92, 252, 131, 155, 251, 80}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 240, 68, 133, 9, 158, 177}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 254, 74, 77, 169, 24, 86, 106}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 135, 33, 67, 32, 210, 82}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 191, 241, 201, 99, 208, 111}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 223, 240, 228, 14, 127, 91}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 89, 28, 247, 36, 32, 100, 58}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 68, 105, 177, 208, 214, 147, 16, 101}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 70, 139, 202, 235, 34}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 220, 62, 86, 223, 145, 14, 174, 38}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 51, 128, 196, 5, 9, 40}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 104, 62}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 166, 174, 234, 55, 199, 189, 39, 201}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 170, 85, 66, 104, 103, 83, 89, 152}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 10, 122, 18, 125, 135, 144, 118, 11}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 96, 115, 108, 160, 107, 137}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 43, 131, 249, 197, 40, 23, 236, 123}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 181, 124, 212, 167, 20, 233, 204, 233}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 29, 105, 48}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 26, 141, 50, 84, 206, 203}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 86, 228, 44, 244}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 19, 53, 227, 95, 119, 227, 147, 51}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 138, 98, 107}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 242, 15, 81, 160, 122, 251, 202, 142}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 149, 169, 142, 149, 210, 140, 147, 235}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 123, 210, 118, 181, 72, 173, 84, 54, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 168, 172, 182, 247, 219}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 56, 162, 208, 19, 45, 98, 217, 178}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 34, 15, 104, 190, 219}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 155, 126}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 236, 159, 137}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 131, 21, 53, 164, 137, 248, 14}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 186, 199, 150}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 219, 36}, 28}, {{109, 229, 118, 155, 43, 154, 0, 25, 52, 94, 68, 37, 223, 255, 165, 99}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93}, 28}, {{109, 229, 118, 155, 43, 154, 0, 90, 129, 244, 101, 142, 221, 169, 28, 242}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 180, 26, 141, 157, 151, 69, 15, 154}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 79, 32, 247, 219, 175}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 238, 213, 76, 88, 161, 66, 66, 174}, 28}, {{109, 229, 118, 155, 43, 154, 0, 110, 11, 12, 187, 80, 130, 98, 42, 131}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 118, 254}, 28}, {{109, 229, 118, 155, 43, 154, 0, 51, 123, 29, 85, 70, 207, 31, 127, 185}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 53, 239, 229, 233}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 177, 14}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 78, 17, 3, 230, 244}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 35, 193, 247, 205, 51, 107, 254, 88}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 111, 63, 92, 76, 9}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 28, 75, 59, 221, 15}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 101, 81}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 10, 100, 179, 55, 32, 159, 233, 193}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 98, 196, 185, 198, 185}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 117, 111, 195, 200, 198, 124}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 19, 38, 16}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 35, 89, 92, 116, 63, 105, 89, 221}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 222, 92, 81, 229}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 247, 19, 85, 0, 225, 169, 8, 26}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 183, 27, 230}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 34, 246, 181, 204, 39, 65, 22, 104}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 19, 135}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 243, 103, 201, 96, 89, 109, 69}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 40, 94, 109, 218, 96, 6, 253}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 67, 121, 30, 151, 34, 133, 49}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 68, 190}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 171, 166, 167, 97, 99}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 18, 93, 242, 56, 236}, 28}, {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 241, 41, 160}, 28}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 37}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 109}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 78}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 246}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 106}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 6, 95}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 214, 59}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 131}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 76, 108}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 84, 163}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 231}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 176}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 201, 140}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 238}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 13, 36}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 168}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 234, 69}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 181}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 188}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 228}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 206, 29}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 200, 70}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 252, 147}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 244, 29}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 137}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 69}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 93}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 199}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 71}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 182, 8}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 195}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 63, 106}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 219, 243}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 38}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 133}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 133, 189}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 103, 11}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 18}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 130, 5}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 125, 9}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 201, 98}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 101, 61}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 6}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 46, 217}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 169}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 250, 42}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 129, 22}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 56}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 190}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 22, 173}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 255, 179}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 34, 47}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 40, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 201}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 212}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 134}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 203}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 251, 154}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 134}, 234}, {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 234}, {{228, 128, 0, 0, 0, 0, 101, 17, 13, 15, 158, 73, 127, 81, 182, 253}, 70}, {{228, 128, 0, 0, 44, 125, 69, 18, 108, 193, 115, 149, 117, 203, 133, 119}, 70}, {{228, 128, 0, 77, 53, 132, 37, 50, 252, 156, 222, 88, 168, 211, 50, 87}, 70}, {{228, 128, 0, 159, 189, 211, 251, 84, 62, 68, 95, 133, 83, 33, 228, 250}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 120, 141, 27}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 111, 140}, 70}, {{228, 128, 0, 0, 0, 0, 0, 57, 168, 54, 28, 68, 113, 120, 26, 63}, 70}, {{228, 128, 0, 0, 0, 0, 43, 97, 6, 102, 248, 69, 112, 64, 13, 104}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 145, 244, 42, 65}, 70}, {{228, 128, 0, 40, 219, 132, 22, 190, 43, 136, 211, 103, 243, 213, 25, 87}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 234, 86, 25, 196, 106, 107}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 192, 172, 17, 171}, 70}, {{228, 128, 0, 0, 123, 5, 211, 243, 112, 162, 191, 105, 32, 111, 99, 210}, 70}, {{228, 128, 0, 0, 0, 0, 0, 210, 25, 243, 103, 23, 89, 153, 216, 179}, 70}, {{228, 128, 0, 0, 125, 201, 209, 42, 6, 141, 15, 70, 177, 32, 194, 229}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, 90}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 207, 218, 131, 146, 12, 10, 97, 26, 37, 207, 250, 105, 203, 32}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 152, 60, 66, 41, 183, 143, 198, 179, 227, 147, 184, 43, 216}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 62}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 31, 178, 107, 25}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 14, 72}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 217}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 248, 59, 173, 30, 133, 108, 187, 4}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 3}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 62, 215, 0, 247, 217, 158, 32, 108}, 70}, {{228, 128, 0, 0, 90, 36, 63, 139, 123, 255, 255, 122, 49, 14, 219, 212}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 204, 2, 243, 187, 152, 170, 180}, 70}, {{228, 128, 0, 0, 0, 27, 203, 151, 231, 50, 254, 112, 4, 118, 216, 233}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 254, 198}, 70}, {{228, 128, 0, 0, 0, 0, 123, 87, 117, 162, 171, 29, 130, 163, 106, 140}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 167, 69, 93, 91, 245}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 78, 153, 249, 229}, 70}, {{228, 128, 225, 97, 174, 52, 16, 35, 68, 225, 32, 123, 142, 15, 130, 87}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 54, 34, 185, 90}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 246}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 254}, 70}, {{228, 128, 0, 253, 203, 191, 4, 112, 187, 224, 100, 76, 3, 197, 236, 53}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 93}, 70}, {{228, 128, 0, 0, 0, 0, 0, 64, 192, 141, 126, 148, 142, 106, 4, 230}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 157, 72}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 194}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 39, 164, 173, 23, 33, 182, 98}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 223, 242}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 244, 124}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 73, 44, 249}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 0, 0, 0, 0, 98, 70, 229, 60, 66, 205, 47, 56, 241}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 124, 232, 11, 70, 78, 122, 151, 184}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 49, 208, 11, 49, 142, 59, 130, 77}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 204}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 96, 81, 155, 49, 29, 114, 219, 246}, 70}, {{228, 128, 0, 0, 181, 203, 255, 186, 206, 220, 58, 100, 136, 76, 135, 67}, 70}, {{228, 128, 0, 0, 0, 104, 145, 111, 41, 151, 10, 228, 52, 50, 221, 220}, 70}, {{228, 128, 242, 140, 85, 45, 117, 179, 126, 82, 58, 140, 167, 8, 209, 222}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 116, 87, 73, 166, 254, 125}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 63, 197, 103, 193}, 70}, {{228, 128, 0, 0, 0, 105, 40, 244, 94, 112, 209, 239, 30, 107, 90, 12}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 195, 79, 120}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 165, 2, 182}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 70}, {{228, 128, 0, 0, 0, 0, 233, 158, 140, 80, 10, 185, 146, 118, 228, 182}, 70}, {{228, 128, 0, 0, 0, 77, 35, 221, 181, 99, 112, 76, 151, 28, 221, 143}, 70}, {{228, 128, 217, 138, 226, 99, 22, 249, 34, 139, 220, 61, 229, 68, 30, 45}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245}, 70}, {{228, 128, 0, 0, 52, 199, 145, 196, 41, 29, 133, 188, 150, 28, 51, 45}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 171, 36, 228, 209, 26, 251}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 23, 197, 40, 40}, 70}, {{228, 128, 103, 75, 50, 10, 227, 45, 148, 155, 0, 251, 135, 152, 217, 132}, 70}, {{228, 128, 0, 0, 0, 42, 170, 255, 158, 229, 8, 66, 134, 41, 197, 238}, 70}, {{228, 128, 33, 138, 209, 228, 131, 30, 50, 246, 113, 9, 161, 117, 168, 131}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 136, 131, 13, 58, 214, 93, 206, 176}, 70}, {{228, 128, 0, 0, 0, 13, 193, 0, 183, 40, 235, 91, 38, 189, 67, 147}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 70, 147, 142, 169, 34, 128, 79, 163}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 182, 67}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 9, 226, 81}, 70}, {{228, 128, 0, 0, 0, 0, 107, 56, 126, 203, 130, 212, 141, 94, 223, 11}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 238}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 12, 199, 240}, 70}, {{228, 128, 0, 0, 133, 121, 235, 9, 232, 67, 166, 11, 129, 233, 26, 56}, 70}, {{228, 128, 0, 0, 0, 0, 0, 95, 54, 43, 104, 107, 71, 198, 162, 73}, 70}, {{228, 128, 0, 0, 0, 15, 2, 130, 174, 11, 57, 161, 184, 72, 249, 6}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 119, 5, 10}, 70}, {{228, 128, 0, 0, 0, 0, 0, 84, 233, 12, 202, 208, 244, 193, 227, 247}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 172, 41, 16}, 70}, {{228, 128, 0, 81, 112, 68, 55, 158, 51, 1, 82, 49, 91, 85, 232, 144}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 32, 84, 222, 31, 233, 238}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 192, 82, 206}, 70}, {{228, 128, 0, 0, 115, 222, 172, 24, 137, 203, 239, 157, 130, 210, 18, 135}, 70}, {{228, 128, 215, 177, 101, 54, 191, 1, 115, 13, 87, 229, 162, 249, 89, 76}, 70}, {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46}, 70}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 242, 135}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 67}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 23}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 79}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 201}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 54, 72}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 123, 43}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 203}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 231}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 14}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 62}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 41}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 210}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 106, 222}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 43}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 162, 48}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 156}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 158}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 168}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 237}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 112, 3}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 44}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 5}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 169}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 250}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 239}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 255}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 175}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 110, 122}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 67, 141}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 13}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 44}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 97}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 64, 226}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 95}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 204}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 196, 47}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 142}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 65}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 139}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 184}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 148}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 155, 214}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 246}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 135, 152}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 214, 67}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 151}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 242, 145}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 81}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 34, 54}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 186, 214}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 212}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 79}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 162}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 39}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 38}, 50}, {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 52}, 50}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 80}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 98, 75}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 220, 119}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 214, 242, 151, 99, 40}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 225, 239}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 11, 240}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 171}, {{41, 100, 27, 84, 106, 112, 96, 33, 74, 250, 31, 237, 191, 140, 38, 72}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 188, 83, 98}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 85}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 110, 21, 157}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 214, 202, 146, 191, 65}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 110, 122, 191, 208}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 131, 228, 84}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 82, 100, 162, 95}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 3, 181}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 247, 254, 20, 250, 120, 207, 44}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 24, 205, 127, 84, 165, 68, 96, 5}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 25, 195, 30, 203, 187}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 177, 82, 24}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 65, 226, 45, 53, 227, 252, 253, 136}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 39, 254, 206}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 54, 20, 186, 67, 188, 8}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 37, 5, 151, 93, 78, 60, 51}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 241, 14, 180, 86}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 86, 58}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 30, 90, 125, 124, 93}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 158, 79}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 225, 172, 78, 111, 177, 133, 195, 221}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 195, 117, 36, 44, 84, 45, 250, 193}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 222, 185, 148, 141, 189}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 58, 176, 249, 107, 37}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 208, 173, 213, 123, 70, 75, 168, 67}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 67, 241, 153}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 119, 211}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 23}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 233, 133, 56, 240, 117, 39, 39}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 186, 75, 231, 51, 135, 202, 85, 253}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 63, 13}, 171}, {{41, 100, 27, 84, 106, 112, 96, 243, 207, 77, 128, 224, 112, 147, 169, 3}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 112, 173, 119}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 222, 102, 10, 224}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 211, 183}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 143, 94, 77}, 171}, {{41, 100, 27, 84, 106, 112, 96, 155, 88, 244, 102, 183, 99, 130, 236, 102}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 154}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 91, 210, 95, 133, 84, 216, 10}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 103, 98}, 171}, {{41, 100, 27, 84, 106, 112, 96, 162, 195, 154, 57, 171, 180, 175, 96, 111}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 228, 216, 94, 3, 71}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 232, 166, 199, 34, 17, 58, 188}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 195}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 166, 130, 151, 243, 40}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 225, 17, 122, 72, 113, 45}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 36, 144, 24, 156, 7}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 227, 85, 109, 128, 136, 210}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 61, 199, 110, 20, 212, 156, 204}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 234}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 204}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 7, 92, 222, 0, 237, 67}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 242, 67, 76, 63}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 50, 59}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 162, 134}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 190, 133, 211, 220, 226}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 247, 7, 186, 53}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 194, 193, 116, 84, 230, 199, 102}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 255, 236}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 65, 48, 209, 205, 251, 70}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 82, 94, 134, 253, 107, 240}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 231, 78, 77}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 182, 156, 26}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 43, 125}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 1, 117, 91, 89}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 135, 218, 24}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 147, 40, 12, 189}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 244, 92, 175}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 19, 237, 230, 177, 44}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 28, 150, 130, 109, 78}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 78}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 110}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 174, 252, 143, 44, 127, 21, 134, 240}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 201, 127, 16, 214, 162, 218}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 137, 193, 169, 80, 39, 78, 100, 185}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 40, 111, 93, 255, 198, 2, 242, 233}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 64, 76, 118, 136, 77, 132}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 37, 173, 65, 246, 43, 126, 38, 73}, 171}, {{41, 100, 27, 84, 106, 112, 96, 110, 101, 90, 238, 56, 244, 48, 22, 164}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 70, 62, 19, 33}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 174, 47, 72, 102, 100, 104, 247, 251}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 125}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 236, 233, 31, 75}, 171}, {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 23, 170}, 171}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 41}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 53}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 54}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 236}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 231}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 50}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 248}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 250}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 254}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 53}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 66}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 61}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 18}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 172}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 43}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 89}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 190}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 29}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 175}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 130}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 175}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 106}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 10}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 117}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 215}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 234}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 231}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 244}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 162}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 94}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 228}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 138}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 125}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 130}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 144}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 232}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 215}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 8}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 144}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 231}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 122}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 197}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 122}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 249}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 62}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 213}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 137}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 236}, {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 254}, 236}, {{112, 0, 0, 0, 0, 0, 0, 0, 159, 223, 148, 164, 106, 163, 39, 232}, 3}, {{112, 35, 163, 101, 15, 51, 236, 88, 74, 47, 22, 153, 33, 28, 67, 234}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 64}, 3}, {{112, 0, 0, 141, 153, 9, 25, 190, 124, 196, 185, 236, 106, 88, 133, 122}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 122}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 39, 248, 166, 107, 148, 184, 196}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223}, 3}, {{112, 0, 0, 0, 138, 95, 11, 129, 31, 238, 230, 124, 108, 57, 160, 137}, 3}, {{112, 0, 0, 38, 154, 25, 175, 183, 221, 212, 1, 89, 76, 245, 99, 239}, 3}, {{112, 0, 0, 0, 0, 65, 17, 226, 161, 251, 227, 144, 234, 20, 42, 192}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 70, 81, 86, 210}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38}, 3}, {{112, 0, 0, 0, 251, 87, 163, 125, 237, 43, 117, 144, 161, 0, 240, 111}, 3}, {{112, 0, 0, 0, 0, 137, 152, 231, 120, 173, 119, 145, 221, 83, 27, 103}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 39, 32, 178}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 23, 148, 31, 164, 114, 35, 227, 134}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75}, 3}, {{112, 0, 0, 0, 0, 0, 0, 5, 201, 247, 194, 223, 202, 144, 246, 218}, 3}, {{112, 0, 0, 0, 0, 0, 170, 177, 141, 245, 123, 210, 225, 227, 235, 108}, 3}, {{112, 0, 0, 52, 166, 57, 47, 50, 14, 171, 199, 49, 18, 231, 94, 2}, 3}, {{112, 9, 166, 37, 84, 231, 24, 19, 144, 26, 142, 158, 26, 105, 32, 167}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 205, 20, 213, 33, 67, 128, 251}, 3}, {{112, 0, 0, 0, 0, 0, 223, 217, 108, 145, 222, 86, 255, 193, 182, 88}, 3}, {{112, 0, 0, 0, 0, 0, 72, 23, 202, 219, 29, 222, 73, 12, 2, 52}, 3}, {{112, 0, 0, 0, 0, 0, 0, 244, 5, 24, 147, 124, 18, 187, 232, 110}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 124, 214, 91, 85, 133, 160, 72, 70}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 85, 231}, 3}, {{112, 0, 0, 0, 64, 169, 229, 122, 9, 62, 97, 157, 70, 240, 130, 153}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 162, 150, 103}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 180, 223, 134}, 3}, {{112, 0, 0, 0, 206, 36, 183, 224, 108, 25, 184, 122, 186, 89, 98, 55}, 3}, {{112, 0, 0, 0, 0, 49, 168, 208, 135, 91, 213, 244, 142, 151, 153, 239}, 3}, {{112, 0, 0, 201, 177, 184, 129, 87, 106, 46, 44, 141, 101, 211, 239, 107}, 3}, {{112, 0, 165, 68, 37, 3, 73, 93, 235, 194, 185, 238, 19, 221, 164, 8}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 126, 102}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 150, 55, 105, 97, 245}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 102, 56, 193, 218, 67, 24, 38}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 99, 103, 246}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 162, 72, 117, 45, 238, 19, 122}, 3}, {{112, 0, 0, 0, 0, 0, 0, 93, 27, 90, 27, 152, 207, 14, 14, 44}, 3}, {{112, 0, 0, 252, 216, 244, 88, 92, 181, 198, 96, 141, 6, 161, 3, 159}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 250, 30, 171}, 3}, {{112, 0, 0, 0, 0, 17, 127, 179, 211, 62, 168, 249, 170, 68, 72, 28}, 3}, {{112, 0, 0, 0, 0, 0, 159, 42, 130, 92, 36, 115, 47, 198, 232, 42}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 237, 169}, 3}, {{112, 0, 0, 0, 160, 120, 196, 63, 124, 147, 103, 46, 215, 171, 167, 245}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 161, 228, 125, 213}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 152}, 3}, {{112, 0, 0, 0, 36, 237, 56, 188, 249, 236, 164, 118, 143, 133, 232, 191}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 62, 49, 67, 137, 51, 159, 159}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 199}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 221, 89, 27}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 111, 117, 70}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 156, 108, 80, 68, 99, 132, 44, 218}, 3}, {{112, 0, 0, 0, 102, 242, 1, 150, 30, 97, 42, 222, 34, 56, 157, 53}, 3}, {{112, 0, 0, 0, 0, 150, 232, 30, 131, 253, 14, 145, 27, 29, 178, 28}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 211, 61}, 3}, {{112, 0, 0, 0, 0, 0, 0, 53, 158, 244, 141, 224, 72, 97, 144, 108}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 199, 104, 146, 123}, 3}, {{112, 0, 0, 0, 0, 0, 239, 112, 160, 166, 243, 9, 81, 178, 111, 140}, 3}, {{112, 0, 0, 0, 0, 168, 206, 188, 70, 26, 152, 93, 159, 177, 220, 142}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 109, 66, 215, 40}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 28, 36, 240, 230}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 218, 169, 46, 188}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 95, 42, 127}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156}, 3}, {{112, 0, 48, 80, 2, 103, 159, 139, 190, 32, 21, 118, 7, 12, 17, 182}, 3}, {{112, 0, 0, 188, 105, 151, 96, 211, 22, 139, 72, 81, 49, 219, 40, 180}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 63}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 141, 26, 129, 21}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3}, {{112, 0, 0, 0, 0, 0, 26, 35, 23, 218, 171, 155, 83, 213, 155, 177}, 3}, {{112, 0, 0, 50, 162, 203, 25, 139, 161, 11, 127, 151, 22, 49, 215, 41}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 31, 187}, 3}, {{112, 0, 0, 0, 36, 93, 167, 245, 65, 241, 249, 104, 126, 195, 52, 92}, 3}, {{112, 0, 156, 94, 146, 48, 82, 95, 22, 144, 0, 154, 99, 111, 58, 203}, 3}, {{112, 0, 0, 0, 0, 0, 170, 224, 185, 221, 195, 59, 96, 85, 242, 12}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 154, 246}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 53, 105, 98, 154, 47, 41, 153}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 235, 82, 46}, 3}, {{112, 0, 0, 0, 0, 0, 0, 120, 232, 59, 163, 160, 164, 116, 113, 90}, 3}, {{112, 0, 0, 0, 0, 0, 0, 36, 222, 15, 226, 149, 218, 36, 101, 212}, 3}, {{112, 0, 0, 0, 0, 0, 0, 242, 6, 250, 184, 197, 60, 34, 7, 233}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 171, 89, 154, 200}, 3}, {{112, 0, 0, 0, 0, 0, 108, 161, 150, 185, 36, 108, 252, 183, 1, 170}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 3}, {{112, 0, 0, 203, 132, 179, 111, 217, 200, 26, 129, 90, 184, 189, 44, 8}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 3}, {{112, 0, 0, 0, 0, 204, 213, 61, 178, 222, 189, 37, 15, 201, 82, 52}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 134, 200, 139, 34, 84, 18, 243}, 3}, {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 28, 61, 83, 61, 5}, 3}, {{112, 0, 0, 0, 243, 10, 142, 240, 110, 16, 205, 220, 54, 240, 188, 174}, 3}, {{112, 0, 0, 0, 0, 0, 0, 154, 124, 131, 71, 30, 220, 17, 179, 236}, 3}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 71, 40}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 85, 135, 212, 231}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 99, 76, 180, 98, 61}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 175, 19}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 249}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 98}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 249, 140, 131}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 138, 226}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 145, 28, 146}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 153}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 78, 213, 149, 137, 28}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 226}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 54, 132}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 209, 35, 147}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 63}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 78, 78, 179}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 192, 157}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 61, 186, 82}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 95}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 90, 127, 134}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 205}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 192, 76, 58, 140}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 164, 47, 12}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 111, 205}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 126}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 215, 160, 57}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 248, 98}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 222, 228}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 9, 164}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 14, 206, 236, 240}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 18}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 13, 48}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 65}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 154}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 7, 176, 38}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 222, 42, 42, 255, 28}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 251, 42, 80, 197, 80}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 129, 96}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 131, 48, 93}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 41, 10, 137, 129}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 57, 17, 179, 4}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 204, 191}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 46, 64, 31, 67, 113}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 137, 223}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 190, 26, 179, 131}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 60, 196, 246, 101}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 106, 23, 55}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 70, 63, 89, 106, 18}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 176, 141, 95, 212}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 77, 114}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 125, 202, 37, 143, 11}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 79, 114}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 2}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 244, 164, 199}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 90, 207}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 192, 12}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 73, 147, 255}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 235, 22}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 14, 70, 98, 41}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 205}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 104, 49, 90}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 28, 251}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 138, 16}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 131, 148, 107, 58}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 131, 253, 154, 83}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 157, 75, 79, 103}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 91, 187}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 63, 14, 103}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 5, 74}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 140, 233, 134, 79}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 76}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 10, 25}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 249, 96, 225}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 184, 163}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 150, 107, 160}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 150, 121, 254, 87}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 217}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 179}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 103, 23, 28, 95}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 171, 205}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 240}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 100, 155}, 64}, {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 131, 79}, 64}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 180, 233}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 2}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 216}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 167}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 155}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 146}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 114}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 212, 1}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 106, 140}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 183, 225}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 227}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 223}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 24, 169}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 95, 167}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 130, 16}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 14, 41}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 54}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 151}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 138, 209}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 39, 104}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 250}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 38}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 246, 165}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 152}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 56}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 1, 191}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 59}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 189}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 147}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 162}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 191}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 151}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 251}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 254}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 181}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 143, 54}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 47}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 4, 32}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 105}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 46, 22}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 10}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 22, 175}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 177}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 237}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 32}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 22}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 198, 72}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 236}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 130, 28}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 211, 69}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 105}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 213}, {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 29, 8}, 213}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 251}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 39, 72, 217, 153}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 200, 177, 231, 245, 203, 14}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 167, 56, 240, 228}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 86, 107}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 37, 238, 67, 162, 208, 191, 109, 108}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 156, 74, 232}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 154, 91, 186, 95, 238, 86, 153}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 48, 41, 213, 75}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 59, 27, 96}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 197}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 92, 127, 158, 206, 216}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 37, 196, 185}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 53, 174, 170, 176}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 65}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 20, 189, 15, 205, 38, 191, 247, 80}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 112, 0, 131, 96}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 11}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 47}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 117, 130, 90, 253, 101, 151}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 23, 138}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 152, 196, 208, 48, 73, 118}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 253, 203, 222, 69}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 12, 55}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 147, 252, 218, 231, 123, 192}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 161, 62, 195, 111, 44, 111}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 29, 28, 197, 222}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 87}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 236}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 6, 133, 27, 37, 57, 114, 77}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 208, 103, 119}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 147, 209, 247, 129, 198, 224}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 130, 213, 215, 22, 227, 250, 153, 78}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 171, 41, 190, 36, 101, 206}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 231, 74, 39, 61, 242, 208, 92, 91}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 194, 238, 229, 159}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 119, 32, 182, 250, 106, 127, 200, 45}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 73, 106, 198, 174, 102, 232, 46, 45}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 92, 65, 91}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 72, 145}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 70, 25, 187, 244, 116, 11, 254}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 77, 149, 74, 71, 147}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 18, 9, 181, 29, 138, 193}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 81}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 37, 67, 223, 28, 247, 218, 73, 222}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 48}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 117, 88, 58, 178}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 212, 49, 27, 31, 74}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 55}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 162, 86, 215}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 180, 232, 122, 141, 125, 126, 79}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 121, 14, 180, 215}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 158, 248, 72, 2, 165, 238}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 128, 200}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 69, 178, 22, 100, 33}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 36, 152, 106, 91, 82, 61, 16}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 165, 173, 230, 126, 98}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 118, 21, 239, 100}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 86, 6, 190}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 190}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 254, 15, 129, 164}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 46, 2}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 229}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 10, 133, 202, 32, 42, 189, 7, 114}, 15}, {{209, 89, 168, 236, 146, 169, 100, 32, 14, 21, 236, 108, 83, 162, 22, 127}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 250, 244, 170, 143, 172, 178}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 207, 163, 77, 21, 61, 3, 139, 3}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 174, 202, 119, 96, 208, 186, 204, 172}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 83, 104, 194, 191, 33, 60}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 213, 68, 34, 14, 11}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 13, 25, 116, 104, 167, 243}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 245, 39}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 25, 215, 167, 150}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 31, 62, 215, 0, 133, 72, 217, 47}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 247, 178, 198, 81, 99, 228}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 125, 204, 186, 254, 152, 58, 178, 6}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 177, 139, 17, 75, 77, 202, 249}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 229, 220, 109, 242, 41, 169, 226, 19}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 168, 12, 109}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 134}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 79, 205, 248, 114, 124, 213}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 136, 43, 198, 102}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 114, 145, 131, 202, 16, 79, 201}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 3, 138, 143, 110, 114, 176}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 169, 46, 86}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 76, 111, 46, 152, 0, 255, 26}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 238, 235, 68, 138, 234}, 15}, {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 140, 122, 243, 177}, 15}, {{131, 210, 208, 130, 83, 88, 132, 172, 174, 146, 179, 49, 231, 39, 95, 221}, 145}, {{131, 210, 208, 0, 0, 0, 0, 250, 198, 64, 136, 137, 161, 175, 46, 128}, 145}, {{131, 210, 208, 0, 0, 0, 78, 132, 229, 201, 63, 240, 202, 116, 72, 214}, 145}, {{131, 210, 208, 0, 0, 0, 77, 35, 229, 223, 140, 154, 125, 159, 212, 31}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 238, 61}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 58, 253, 40, 249, 169}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 120, 115, 107}, 145}, {{131, 210, 208, 0, 0, 0, 0, 122, 139, 143, 51, 13, 207, 231, 18, 238}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 177, 141, 11, 147, 113}, 145}, {{131, 210, 208, 0, 0, 47, 2, 56, 116, 15, 204, 221, 145, 196, 175, 115}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 215, 188, 68, 20, 104, 167, 189}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 181, 51, 104, 55, 168, 45}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 125, 151, 0}, 145}, {{131, 210, 208, 0, 0, 0, 152, 11, 159, 10, 174, 88, 16, 82, 16, 186}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 25, 70, 226, 47, 214, 203, 170, 141, 98, 64}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 25}, 145}, {{131, 210, 208, 0, 0, 185, 204, 145, 0, 194, 34, 120, 42, 79, 6, 71}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 92, 220, 38, 189, 175, 170, 45}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 55, 89, 241, 156, 18}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 231, 199}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 151, 248, 79}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 91}, 145}, {{131, 210, 208, 13, 93, 27, 186, 19, 185, 81, 14, 214, 35, 201, 84, 129}, 145}, {{131, 210, 208, 0, 0, 229, 103, 184, 43, 67, 194, 43, 199, 1, 100, 169}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 109, 156, 29, 56, 70, 73}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 146, 223}, 145}, {{131, 210, 208, 0, 0, 0, 0, 173, 187, 45, 250, 230, 231, 3, 82, 93}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 227, 1, 192, 54}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 52, 155, 39}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 113, 117, 246}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 203, 18, 121}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 220, 94, 84}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 193, 198}, 145}, {{131, 210, 208, 0, 232, 209, 94, 132, 236, 65, 122, 55, 175, 228, 252, 88}, 145}, {{131, 210, 208, 0, 179, 26, 55, 53, 62, 226, 157, 204, 53, 231, 128, 169}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 228, 98, 5, 44, 190, 98, 4}, 145}, {{131, 210, 208, 0, 22, 115, 177, 64, 110, 82, 198, 224, 241, 93, 6, 6}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 232, 191}, 145}, {{131, 210, 208, 57, 234, 151, 208, 41, 197, 124, 119, 68, 92, 27, 23, 99}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 85, 230, 117, 16, 62, 113}, 145}, {{131, 210, 208, 0, 55, 172, 36, 79, 68, 160, 149, 141, 228, 158, 189, 140}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 86, 139}, 145}, {{131, 210, 208, 24, 226, 130, 197, 91, 199, 151, 77, 18, 115, 8, 167, 234}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 34, 204, 226, 168, 216, 211}, 145}, {{131, 210, 208, 166, 124, 76, 68, 183, 228, 208, 137, 48, 184, 167, 213, 133}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 25, 12, 111, 49, 161}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 14, 7, 40}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 179, 17, 20, 192, 183, 18, 232}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 182, 250, 83, 136, 159, 52}, 145}, {{131, 210, 208, 0, 0, 0, 55, 161, 136, 51, 94, 62, 194, 64, 124, 50}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 56}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 156, 69, 203, 198, 195, 92, 78}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 132, 33, 41, 38, 192}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 25, 135, 170, 39, 194, 182, 63}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 220, 210, 236, 79, 66, 246}, 145}, {{131, 210, 208, 0, 129, 194, 240, 220, 151, 215, 46, 186, 214, 171, 217, 42}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 68}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 154, 122, 209, 137, 150}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 241, 161}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 120, 173, 2, 79, 81, 79, 229}, 145}, {{131, 210, 208, 0, 0, 0, 0, 239, 64, 175, 202, 119, 229, 106, 117, 127}, 145}, {{131, 210, 208, 0, 0, 0, 0, 231, 75, 178, 202, 237, 243, 170, 92, 194}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 143, 46, 158, 74, 87}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 101, 191, 110, 176, 233, 136, 112}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 24, 41, 29, 255, 105, 142}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 254, 43, 85, 45, 219, 110, 199, 195}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 214, 94, 163, 8, 162, 61, 82, 23, 234, 166}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198}, 145}, {{131, 210, 208, 0, 214, 190, 60, 74, 108, 252, 173, 107, 105, 254, 93, 230}, 145}, {{131, 210, 208, 0, 0, 0, 0, 51, 137, 216, 43, 139, 180, 126, 54, 4}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 18, 111}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170}, 145}, {{131, 210, 208, 0, 0, 65, 221, 199, 24, 8, 220, 54, 185, 115, 160, 176}, 145}, {{131, 210, 208, 164, 15, 78, 181, 21, 240, 159, 128, 10, 245, 42, 135, 189}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 55, 236, 105, 252, 226, 237, 250, 126}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 110, 249, 210}, 145}, {{131, 210, 208, 0, 0, 0, 0, 13, 231, 219, 98, 250, 30, 208, 94, 62}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 189, 254, 220, 34, 202, 162, 156}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 158}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 30, 116, 2, 32, 66, 11}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 170, 88, 243, 45, 169, 94}, 145}, {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 12, 173, 36}, 145}, {{131, 210, 208, 0, 56, 25, 167, 108, 197, 33, 157, 5, 110, 237, 25, 15}, 145}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 215, 193, 29, 61, 5, 241}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 212, 236, 57, 103}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 227, 119, 51, 172, 13}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 11, 207, 31, 186, 211, 164, 91, 112}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 112, 47}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 46, 114}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 226, 208, 74, 0, 5, 12, 82, 190}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 229, 206, 137, 105, 58, 191, 17, 163}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 230, 172, 182, 234, 136, 43, 221}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 212, 177, 128, 157, 71, 68, 16}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 92, 147}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 150, 56, 22, 58, 9, 114}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 74, 87, 175, 121, 169, 254, 29}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 163, 46, 13, 119, 192, 110}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 35, 196, 154, 122, 92, 224, 246}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 128, 231, 42, 19, 157, 165, 6, 243}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 36, 168, 177, 169, 26}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 148}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 33, 181, 25, 113}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 115, 231, 135, 190, 211, 16, 97}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 27, 99, 100}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 138, 99, 87, 56, 128, 175}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 135, 11, 216}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 192, 30, 99, 206, 225}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 97, 151, 188, 171, 227, 60}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 220, 211, 249, 119, 112, 192}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 245, 138, 56, 15, 70, 191, 49, 150}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 221, 229, 17, 244, 161, 25, 76}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 24, 165, 21}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 99, 58, 10, 254, 238}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 102, 121, 111}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 49, 132, 222, 210, 5, 137, 112}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 49, 48}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 131, 179, 148, 139, 239, 120}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 42, 30, 174}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 50, 162, 95, 30, 53, 219, 254, 154}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 175}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 73, 128, 232, 227, 251}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 122, 161, 223, 171, 99, 205}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 10, 215, 252, 86, 120, 99}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 107, 232, 181, 126, 2, 247}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 19, 135, 96, 22, 243, 5, 187}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 172, 107, 113, 53, 23}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 40, 182, 187, 206, 246, 33, 81, 231}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 116, 139, 119, 75, 8, 161, 149}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 117}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 47, 82, 186, 199, 97, 31, 77}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 12, 79, 87}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 141, 156, 163, 32, 222, 109, 31}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 205, 185, 51}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 119, 31, 138, 201, 251, 105}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 18, 160, 146, 160, 219, 226}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 239, 31}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 207, 94, 253}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 144, 82, 63, 149, 254}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 197, 248, 10, 171}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 15, 101, 6, 192, 47, 78, 201}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 74, 33, 81, 198, 194, 103}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 115, 80, 142, 41, 139, 227}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 196, 239, 70}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 232, 138, 69, 127, 57}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 143, 63, 236, 165, 121, 190, 78, 103}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 37, 211, 46, 248, 12, 155, 118}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 112, 245, 0, 185, 101}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 59, 179, 138, 249, 223, 183}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 255, 247}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 218, 159, 189, 57, 78, 59, 132, 244}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 67, 0, 65, 141}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 235, 33, 130, 123, 129, 8, 207}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 61}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 164, 254, 200, 77, 25, 240, 91, 115}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 212, 143, 154, 85}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 224, 152, 209, 171, 217, 243}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 158, 155, 27, 227, 80}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 186, 238}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 169, 248}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 185, 38, 210, 118, 110, 240, 247, 131}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 109, 37, 240, 40, 142, 227, 171, 224}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 108}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 156, 234, 80}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 12, 24, 211, 183, 35, 208}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 91, 211, 159}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 57, 92, 182, 19, 212}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 87, 48, 31, 90, 13, 49, 134, 145}, 27}, {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 131, 17}, 27}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 75}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 76}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 210}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 48}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 140}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 85}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 117}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 221}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 71}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 12}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 11}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 137}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 139}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 15}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 55}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 28}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 222}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 224}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 177}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 12}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 207}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 236}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 102}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 69}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 253}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 54}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 174}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 163}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 151}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 43}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 56}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 50}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 180}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 207}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 65}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 138}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 241}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 109}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 247}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 172}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 58}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 218}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 39}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 48}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 150}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 28}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 28}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 112}, 247}, {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 100}, 247}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 9, 48, 191}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 202, 4, 240, 49, 91}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 240, 49, 144}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 195, 205, 227, 73, 75, 126, 178}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 107}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 119, 4, 135}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 161, 53, 131, 246, 145}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 221, 233, 225, 243}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, 66}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 54, 135, 199, 210, 250, 16, 184}, 121}, {{143, 46, 30, 175, 224, 0, 0, 88, 150, 130, 25, 94, 80, 9, 238, 64}, 121}, {{143, 46, 30, 175, 224, 0, 249, 237, 99, 227, 161, 32, 178, 125, 76, 147}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109}, 121}, {{143, 46, 30, 175, 224, 0, 0, 46, 188, 242, 10, 68, 187, 218, 170, 166}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 62, 85, 4, 145, 123, 63, 231}, 121}, {{143, 46, 30, 175, 224, 0, 113, 22, 135, 183, 84, 108, 186, 242, 96, 89}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 72, 6, 169, 43}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 52, 209, 168, 50, 223, 143, 56, 244}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 229, 22, 85, 114, 49, 114}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 208}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 108, 210, 208, 63}, 121}, {{143, 46, 30, 175, 224, 0, 164, 184, 178, 166, 90, 244, 71, 58, 26, 69}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 148, 63, 163, 222, 137, 95, 9}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 247, 241, 19, 131, 53, 176, 184, 53}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 227, 234, 191, 209, 44, 191, 114, 198}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 153}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 122, 232, 50, 109, 38, 242, 169, 195}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 157, 99, 243, 91, 159, 15, 61, 231}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 52}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 128, 179, 194, 207, 146, 33, 232}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 153, 21, 219, 44, 102, 228, 234, 149, 192}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 246, 43, 233, 195}, 121}, {{143, 46, 30, 175, 224, 0, 0, 237, 26, 80, 104, 55, 44, 31, 4, 226}, 121}, {{143, 46, 30, 175, 224, 0, 188, 255, 116, 127, 139, 219, 187, 53, 116, 143}, 121}, {{143, 46, 30, 175, 224, 0, 0, 76, 104, 104, 232, 148, 223, 143, 77, 198}, 121}, {{143, 46, 30, 175, 224, 0, 205, 165, 250, 70, 117, 187, 73, 178, 164, 195}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 13, 27, 207, 99, 170, 60}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 180, 90, 122, 212, 56, 63, 57}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 71, 116, 194, 181}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 20, 64, 21}, 121}, {{143, 46, 30, 175, 224, 0, 11, 223, 38, 208, 176, 68, 238, 210, 134, 9}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 223, 254, 104, 171, 240, 22, 59, 89}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 250, 223, 32, 13, 144, 139, 62, 24}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 170, 44, 194, 146, 36, 222, 216}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232}, 121}, {{143, 46, 30, 175, 224, 0, 0, 186, 205, 2, 239, 99, 150, 193, 175, 149}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 11, 148, 166}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 64, 156, 233, 228, 211, 164}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 248, 58, 170, 117, 213, 228, 152}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 93, 192, 230, 9, 52}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 145, 225, 200}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 194, 101, 171, 234, 140}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 227, 106, 86}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 171, 35, 58, 130, 23, 11, 1}, 121}, {{143, 46, 30, 175, 224, 0, 179, 161, 229, 205, 242, 52, 203, 74, 222, 181}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 108, 164, 217, 183, 33, 238, 209, 54}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 118, 238, 194, 3, 173}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 177, 255, 20, 39, 186, 32, 20}, 121}, {{143, 46, 30, 175, 224, 0, 0, 24, 91, 24, 91, 97, 90, 179, 121, 97}, 121}, {{143, 46, 30, 175, 224, 0, 0, 14, 178, 90, 126, 227, 126, 146, 250, 13}, 121}, {{143, 46, 30, 175, 224, 0, 0, 79, 58, 14, 214, 199, 245, 97, 127, 48}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 119, 193, 188, 69}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 245, 233, 72, 149, 31, 221, 128}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 130, 212, 140, 177}, 121}, {{143, 46, 30, 175, 224, 0, 0, 10, 59, 13, 206, 218, 183, 130, 119, 76}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 113, 240, 63, 219}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 89, 61, 39, 71, 215, 89}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 175, 209, 235, 125, 232}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 11, 208, 210, 250, 69, 121, 225, 78}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 215, 183, 168, 213, 94, 49, 209}, 121}, {{143, 46, 30, 175, 224, 0, 0, 164, 110, 132, 153, 65, 97, 82, 164, 232}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 45, 142, 57, 20, 6}, 121}, {{143, 46, 30, 175, 224, 0, 0, 139, 79, 192, 236, 8, 145, 160, 63, 179}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 95, 196, 135, 89, 166, 124, 160}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 221, 147, 26, 72}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 135, 38, 181, 233}, 121}, {{143, 46, 30, 175, 224, 0, 0, 132, 180, 98, 140, 165, 41, 202, 93, 110}, 121}, {{143, 46, 30, 175, 224, 0, 0, 223, 231, 83, 45, 154, 224, 59, 136, 236}, 121}, {{143, 46, 30, 175, 224, 0, 0, 215, 163, 251, 43, 157, 65, 94, 217, 8}, 121}, {{143, 46, 30, 175, 224, 0, 64, 37, 143, 250, 10, 105, 9, 6, 153, 170}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 132, 3, 219, 231, 224, 89}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 201, 57, 244}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 175, 171, 36, 255, 212, 158}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 38, 211, 242, 225, 75, 187}, 121}, {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 88, 203, 220, 216, 123, 106}, 121}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 163, 212, 184, 134, 56}, 214}, {{155, 85, 217, 180, 32, 235, 48, 45, 11, 236, 248, 176, 77, 7, 2, 34}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 179, 85, 238, 234, 252, 180, 84}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 81, 214, 68, 97, 205}, 214}, {{155, 85, 217, 180, 0, 11, 200, 255, 0, 164, 200, 168, 211, 23, 48, 168}, 214}, {{155, 85, 217, 180, 0, 0, 250, 29, 158, 73, 88, 167, 170, 100, 146, 19}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 25}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 192, 106, 224, 221, 61, 39}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 149, 20, 172, 108, 4, 110, 67}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 132, 115, 179, 185, 147}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 125, 254, 104, 245, 74, 172, 121}, 214}, {{155, 85, 217, 180, 0, 0, 253, 26, 214, 139, 146, 27, 73, 7, 158, 188}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 65, 11, 120, 209, 220, 194, 12}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 17, 129, 155, 145, 100}, 214}, {{155, 85, 217, 180, 0, 0, 0, 37, 220, 64, 152, 5, 124, 17, 175, 86}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 126, 229, 65, 116, 133, 75}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 190, 197}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 121, 52, 36, 144, 79, 70}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 59, 18, 76, 96, 87, 69, 131, 152, 161, 107, 204}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 75}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 170, 18}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210}, 214}, {{155, 85, 217, 180, 0, 0, 0, 106, 221, 90, 42, 13, 219, 139, 102, 49}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 180, 103, 30, 134, 109, 79, 13, 7}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 87, 243, 135, 174, 96}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 14, 14, 98, 78, 185, 126, 41}, 214}, {{155, 85, 217, 180, 0, 0, 164, 149, 121, 27, 23, 253, 244, 59, 196, 220}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 139, 58, 240, 86, 234, 93, 236, 135}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 154, 197, 42, 38}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 160, 239, 59, 254, 190}, 214}, {{155, 85, 217, 180, 201, 60, 89, 13, 240, 123, 171, 148, 128, 49, 42, 104}, 214}, {{155, 85, 217, 180, 0, 98, 23, 20, 209, 144, 218, 240, 152, 106, 191, 205}, 214}, {{155, 85, 217, 180, 0, 0, 0, 142, 65, 146, 198, 167, 4, 103, 184, 11}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 143, 121, 207, 175, 129}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 35, 117}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 30, 139, 65, 226, 7}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 72, 13, 100, 243, 58, 83, 226, 223}, 214}, {{155, 85, 217, 180, 0, 0, 247, 32, 22, 209, 212, 112, 164, 183, 31, 186}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 113, 6, 169, 90, 240, 98, 210, 91, 127}, 214}, {{155, 85, 217, 180, 0, 0, 0, 252, 213, 52, 170, 46, 18, 169, 130, 109}, 214}, {{155, 85, 217, 180, 0, 0, 0, 220, 160, 116, 60, 102, 124, 115, 141, 251}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 74, 140}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 37, 84, 102, 9, 5, 62, 158, 106}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 191, 25, 116, 93}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 70, 77, 73, 152, 56, 103, 205}, 214}, {{155, 85, 217, 180, 0, 0, 96, 192, 153, 39, 55, 11, 192, 116, 119, 165}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205, 160, 92}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 26, 75, 24, 195, 108, 233, 17, 5}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 204, 5, 186, 165, 123, 54, 142}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 181, 133, 253, 30, 208, 48, 102}, 214}, {{155, 85, 217, 180, 0, 0, 0, 17, 122, 172, 155, 150, 192, 31, 90, 124}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 182, 203, 212, 227, 240, 142, 223}, 214}, {{155, 85, 217, 180, 0, 0, 229, 128, 22, 130, 35, 237, 48, 6, 246, 1}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 88, 121, 179, 243, 168, 74, 73}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68}, 214}, {{155, 85, 217, 180, 0, 0, 60, 21, 114, 32, 144, 177, 111, 55, 196, 234}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 21, 173, 36, 43, 250, 51, 111, 234, 77, 65}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 246, 241, 73, 27}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 137, 9}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 240, 55, 44, 208}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 180, 47, 207, 36, 13, 4, 120}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 236, 150, 58, 122, 18}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 39}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 107, 252, 149, 177}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 72}, 214}, {{155, 85, 217, 180, 0, 0, 89, 75, 143, 171, 203, 246, 101, 4, 134, 209}, 214}, {{155, 85, 217, 180, 0, 0, 0, 44, 194, 136, 81, 202, 160, 218, 131, 57}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 69, 16, 83, 215}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 188}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 61}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 93, 197}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 53, 237, 101, 254}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 52, 210, 97, 62, 177, 155, 167}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 100, 170, 236, 91, 136, 190}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 40, 9, 37, 75, 37, 88}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 73, 202, 176, 56, 63, 203}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 215, 249}, 214}, {{155, 85, 217, 180, 0, 0, 56, 246, 188, 200, 0, 90, 108, 96, 59, 28}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 27, 218, 118, 78, 109}, 214}, {{155, 85, 217, 180, 8, 216, 51, 214, 60, 116, 59, 169, 210, 239, 185, 5}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 160, 138}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 148, 255, 89, 71, 48, 241, 138}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 214}, {{155, 85, 217, 180, 0, 0, 0, 0, 7, 4, 235, 172, 45, 77, 225, 232}, 214}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 44, 105, 40, 57, 58, 36}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 167, 138, 145, 18, 212, 102, 104}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203}, 221}, {{58, 62, 156, 0, 0, 0, 249, 81, 150, 209, 236, 216, 219, 225, 81, 145}, 221}, {{58, 62, 156, 0, 0, 0, 0, 212, 119, 153, 101, 245, 117, 87, 227, 44}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 30, 112}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 29, 8, 244, 149, 3, 203}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 127, 242}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 111, 243}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 147, 188}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 63, 15, 174, 100, 62, 220, 172, 35}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 5, 198}, 221}, {{58, 62, 156, 0, 0, 0, 0, 109, 18, 183, 145, 207, 63, 191, 75, 91}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 38, 89, 215, 27, 52, 224, 40, 151, 147, 54, 54, 109}, 221}, {{58, 62, 156, 0, 0, 121, 6, 69, 79, 77, 126, 90, 244, 201, 182, 19}, 221}, {{58, 62, 156, 0, 0, 73, 170, 207, 156, 158, 87, 14, 206, 134, 167, 43}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 133, 33, 212, 38, 125, 58}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 178, 120, 197, 24, 208, 159, 228, 241}, 221}, {{58, 62, 156, 0, 0, 0, 123, 53, 122, 56, 94, 13, 165, 139, 117, 170}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 65, 210, 98, 43, 32}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 201, 7, 124, 103, 253, 53, 241, 184}, 221}, {{58, 62, 156, 0, 0, 46, 27, 153, 245, 79, 210, 109, 122, 64, 144, 85}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 196, 51, 116, 232, 156}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 143}, 221}, {{58, 62, 156, 0, 0, 0, 163, 131, 3, 248, 39, 112, 160, 66, 186, 212}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 131}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 63, 197, 173, 215, 153}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 200, 195, 105, 186, 180}, 221}, {{58, 62, 156, 0, 0, 195, 126, 85, 202, 13, 124, 50, 106, 238, 79, 232}, 221}, {{58, 62, 156, 0, 0, 0, 130, 117, 113, 135, 200, 238, 223, 241, 4, 222}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 102, 12, 36}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 197, 13, 191, 15, 36, 252}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 90, 162, 205, 158, 74}, 221}, {{58, 62, 156, 0, 0, 221, 199, 63, 134, 52, 238, 163, 236, 211, 105, 17}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 115, 200, 30, 212, 109, 171}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 231, 217, 249, 199, 205, 69, 206, 75}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 216, 15, 65, 195, 98, 8}, 221}, {{58, 62, 156, 0, 0, 39, 108, 179, 5, 93, 203, 253, 225, 120, 143, 221}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 174, 169, 90, 229, 24, 53, 219, 189, 96, 19, 140}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 114, 12, 176, 40, 198}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 99, 156, 60, 161, 0, 24}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 251, 22, 105, 166, 152, 40}, 221}, {{58, 62, 156, 0, 0, 178, 98, 238, 160, 20, 197, 140, 113, 117, 162, 187}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 79, 253, 174, 95, 220, 233}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 136, 137, 79, 1, 52}, 221}, {{58, 62, 156, 0, 67, 225, 218, 199, 147, 59, 247, 140, 197, 184, 161, 125}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 97, 62}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 117}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 21, 94, 178, 157, 146, 162, 25}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 0, 213, 94, 39, 55, 35, 246, 8, 32, 186}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 173, 47, 119, 92, 221, 48, 84, 196, 130, 42, 108}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 248}, 221}, {{58, 62, 156, 0, 0, 3, 214, 159, 241, 102, 118, 160, 147, 140, 90, 149}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 13, 209, 59, 3, 236, 211, 209}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 0, 200, 77, 157, 236, 192, 134, 115, 78, 131}, 221}, {{58, 62, 156, 0, 0, 147, 210, 13, 30, 0, 38, 143, 138, 56, 222, 224}, 221}, {{58, 62, 156, 0, 46, 116, 170, 179, 50, 214, 42, 229, 33, 190, 72, 117}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 98, 189}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 62}, 221}, {{58, 62, 156, 0, 0, 0, 110, 58, 97, 74, 4, 190, 211, 123, 80, 74}, 221}, {{58, 62, 156, 0, 0, 0, 0, 167, 104, 84, 69, 129, 103, 29, 162, 241}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 2, 112, 223, 88, 237, 7, 213}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 132, 203, 243}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 48, 59, 4, 162, 14}, 221}, {{58, 62, 156, 0, 0, 0, 0, 16, 42, 108, 32, 38, 95, 238, 77, 39}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 165, 36, 32, 229, 243, 83, 133}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 221, 239, 172, 250, 241, 157, 62, 203, 44, 33}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 34, 47, 28, 164, 37, 205, 184}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 241, 77}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 240}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 43, 178, 252}, 221}, {{58, 62, 156, 0, 0, 0, 130, 235, 109, 110, 63, 79, 93, 77, 76, 174}, 221}, {{58, 62, 156, 0, 0, 0, 0, 188, 49, 2, 26, 234, 195, 93, 217, 2}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 31, 75}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 26, 123, 86, 197, 227, 8, 109}, 221}, {{58, 62, 156, 0, 0, 0, 232, 46, 233, 54, 122, 117, 189, 43, 249, 2}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 214, 176, 144, 137, 25, 242, 223, 16}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 141, 43, 117, 127, 231, 34}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 225, 233, 72, 202, 211}, 221}, {{58, 62, 156, 0, 0, 0, 132, 221, 109, 176, 61, 139, 101, 139, 62, 26}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 219, 121, 147, 206, 127, 91}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 147, 249, 168, 222, 109}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 28, 136, 159, 253, 241, 202}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 221}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 23, 118, 150, 203, 99, 199, 65, 221}, 221}, {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 221}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 32, 45, 77, 26, 41, 143, 188}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 67, 115}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 202, 150, 179, 168, 94, 10}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 57, 47, 101, 48, 208, 17}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 186, 214, 207}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 172, 91, 125, 145}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 23, 177, 156, 148, 146, 107, 38, 154}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 125, 144}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 210, 87}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 48, 33, 132, 139, 140, 208, 63}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 187, 113, 112, 136, 243, 100}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 64, 82, 110, 85, 60, 159, 155}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 249, 120, 148, 106, 125}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 230, 31}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 244, 109, 19, 136, 211, 135}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 16, 1, 187, 30}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 150, 90, 98, 178, 17, 185, 133}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 245}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 146, 162, 142, 72, 10, 74, 167}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 234, 29, 101, 122, 128, 180}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 68, 134}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 255}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 183, 167, 40}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 236, 15, 127}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 163, 106, 84, 177, 78}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 130, 131, 149, 91, 45, 245}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 151, 206}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 198, 208}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 10, 131, 63, 30, 206, 101}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 135}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 17, 171}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 212, 116, 126}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 117, 134, 225, 13, 92, 26}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 168, 55, 70, 138}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 166, 206, 171, 7, 151, 96}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 232, 133, 216, 23, 242, 210, 223}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 86, 152, 189, 128, 17, 132}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 12, 84}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 20, 236, 128, 124, 72, 116, 149}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 215, 198, 106, 218, 65, 89}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 99, 14, 98, 37, 126, 6, 67}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 149, 149, 190, 71, 51, 1}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 41, 55, 162, 99}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 198, 28, 152, 84}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 151, 209, 153, 238}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 122, 74, 87, 109, 149, 41, 184}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 22, 213, 21, 204, 93, 204, 239}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 165, 111, 212, 193, 190}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 89, 194}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 215, 99, 135, 233, 111, 187, 83}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 17, 31}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 80, 119, 150, 123, 230, 172}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 31, 74}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 191, 161, 3, 187, 225, 150}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 196, 23, 86, 231}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 247, 169, 194, 141, 141, 32}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 225}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 19, 33, 237}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 145, 77, 14, 229, 122, 181}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 35}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 225, 109, 172, 133, 206, 216, 206}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 27, 94}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 23, 128, 34, 95}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 79, 137, 43, 8, 2, 46, 232}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 94}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 168, 213, 180}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 98, 71, 199, 100, 106, 146, 55}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 83, 107, 70, 177, 10, 131, 7}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 36}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 11, 59, 187, 202, 41, 235, 94}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 1, 62, 115}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 65, 170, 62, 202, 215}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 123, 203, 75, 32, 145, 45, 179, 98}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 2, 154}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 228}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 19, 21, 27, 17, 48, 118, 125}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 86, 161, 19, 108, 175, 15}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 129, 37, 27, 126, 123}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 74, 244}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 168, 147, 189, 143, 8, 211, 220}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 91, 3, 183, 17}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 147, 154, 159, 43, 63, 37, 136}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 42}, 102}, {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 4, 103}, 102}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 131, 233, 156, 142, 158, 15, 1, 146}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 242, 126, 172, 224, 147, 14, 144, 186, 160, 182, 57}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 183, 104}, 84}, {{64, 108, 54, 140, 176, 2, 225, 175, 194, 15, 239, 115, 189, 12, 238, 220}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 5, 25, 247, 67, 232}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 210}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62}, 84}, {{64, 0, 191, 51, 99, 149, 109, 165, 216, 41, 43, 50, 170, 238, 150, 251}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 238, 147, 88, 121}, 84}, {{64, 0, 0, 0, 0, 0, 94, 229, 41, 137, 202, 209, 1, 119, 187, 238}, 84}, {{64, 0, 0, 0, 0, 0, 92, 47, 247, 10, 133, 205, 178, 129, 103, 75}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 38, 242, 142, 235}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 194}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 87, 6, 87, 43, 99}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 63}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 105, 19}, 84}, {{64, 0, 0, 0, 0, 0, 134, 133, 2, 165, 25, 25, 196, 136, 47, 199}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 202, 246, 70, 98, 41, 174, 151, 203, 98, 199, 240, 198, 17, 108}, 84}, {{64, 0, 239, 186, 29, 228, 209, 245, 53, 135, 99, 195, 25, 145, 98, 116}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 82}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 121, 218, 253, 24}, 84}, {{64, 0, 0, 0, 0, 0, 0, 228, 195, 201, 248, 61, 177, 12, 6, 208}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 75, 117, 143, 42, 39, 162, 66, 219}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201, 9}, 84}, {{64, 0, 23, 195, 152, 245, 35, 181, 184, 48, 141, 130, 185, 27, 38, 1}, 84}, {{64, 0, 0, 0, 0, 0, 29, 109, 27, 232, 132, 135, 1, 134, 44, 56}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 219, 140, 196, 86, 177}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 98}, 84}, {{64, 0, 0, 0, 0, 0, 181, 48, 198, 12, 51, 200, 116, 187, 240, 150}, 84}, {{64, 0, 0, 0, 178, 201, 145, 213, 210, 60, 114, 1, 124, 97, 52, 44}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 109, 157, 103}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 126, 50}, 84}, {{64, 0, 0, 0, 0, 0, 0, 138, 29, 44, 115, 217, 122, 85, 202, 24}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 47, 48, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 147, 115}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149}, 84}, {{64, 0, 0, 0, 162, 246, 210, 42, 82, 4, 237, 166, 26, 85, 166, 92}, 84}, {{64, 0, 0, 0, 0, 0, 0, 227, 98, 117, 13, 69, 236, 247, 133, 224}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 118, 57, 134, 57, 164, 218, 20, 73}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 164, 227, 130, 123}, 84}, {{64, 0, 0, 0, 228, 240, 33, 21, 221, 154, 211, 172, 106, 3, 247, 180}, 84}, {{64, 0, 0, 0, 200, 23, 78, 55, 170, 186, 69, 155, 38, 176, 26, 120}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 8, 255, 53, 164, 241}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 165, 238, 170, 177, 21, 55, 7, 107}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 251, 20, 227, 30, 76, 253, 244, 22, 53, 184}, 84}, {{64, 0, 0, 0, 28, 218, 79, 99, 186, 94, 78, 183, 77, 228, 138, 43}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 101, 248}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 169, 164, 45, 88, 189, 228, 97}, 84}, {{64, 0, 0, 0, 0, 197, 213, 151, 15, 226, 22, 202, 58, 210, 230, 162}, 84}, {{64, 0, 0, 0, 20, 46, 155, 234, 10, 12, 168, 111, 184, 87, 71, 3}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 89, 235, 44, 211, 150, 1, 65, 172, 81, 48, 160}, 84}, {{64, 0, 0, 0, 0, 133, 161, 84, 23, 233, 121, 126, 222, 202, 123, 66}, 84}, {{64, 187, 239, 42, 94, 235, 130, 19, 103, 53, 20, 68, 30, 99, 44, 177}, 84}, {{64, 0, 0, 0, 45, 2, 185, 147, 138, 130, 157, 196, 13, 191, 15, 96}, 84}, {{64, 0, 0, 45, 40, 111, 46, 224, 147, 17, 39, 116, 147, 89, 209, 3}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 211, 39, 156, 17}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 99, 22, 21, 200}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 232, 110, 81, 174, 25, 169, 249}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 35, 114}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 197, 17, 237, 19, 64}, 84}, {{64, 0, 0, 0, 134, 204, 145, 119, 117, 58, 168, 134, 0, 97, 21, 9}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 169}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 123, 164, 30, 197, 93, 203, 233, 64, 201, 98, 224, 93}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 78, 52}, 84}, {{64, 0, 0, 0, 0, 168, 172, 119, 114, 92, 126, 142, 201, 45, 69, 158}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160}, 84}, {{64, 0, 75, 62, 138, 170, 117, 11, 61, 224, 69, 185, 177, 213, 84, 193}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 83, 50, 192, 143, 21, 218, 127}, 84}, {{64, 0, 0, 148, 137, 249, 79, 222, 122, 214, 46, 199, 25, 148, 147, 138}, 84}, {{64, 0, 0, 0, 0, 30, 18, 7, 185, 160, 80, 32, 244, 253, 172, 70}, 84}, {{64, 0, 249, 87, 18, 112, 198, 109, 22, 130, 196, 5, 109, 117, 239, 122}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 98, 135, 49}, 84}, {{64, 0, 0, 0, 0, 99, 118, 76, 162, 119, 11, 100, 116, 28, 232, 244}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 11, 217, 106, 92}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 51, 207, 216, 79, 67, 235, 19}, 84}, {{64, 0, 0, 0, 182, 122, 39, 253, 153, 237, 225, 166, 70, 248, 10, 14}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 197, 5, 212, 101}, 84}, {{64, 0, 0, 0, 87, 205, 213, 150, 38, 128, 229, 145, 103, 203, 119, 218}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 163, 131, 148, 15, 67, 58, 35, 49}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 245, 188, 111, 176, 31, 188, 29, 15}, 84}, {{64, 0, 0, 250, 80, 136, 131, 92, 250, 161, 37, 161, 60, 96, 102, 180}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 72, 141, 81, 90, 155}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 63, 131, 30, 162, 215}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 80, 76, 174}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 182, 40, 87, 16, 97, 59}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 84}, {{64, 0, 0, 0, 0, 0, 0, 242, 225, 72, 4, 247, 71, 8, 112, 29}, 84}, {{64, 186, 145, 1, 94, 157, 186, 176, 142, 229, 61, 235, 78, 196, 196, 65}, 84}, {{64, 0, 0, 0, 223, 211, 46, 181, 154, 203, 252, 148, 88, 154, 11, 233}, 84}, {{64, 0, 0, 180, 166, 78, 234, 45, 62, 216, 136, 104, 236, 59, 170, 45}, 84}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 185, 157, 218, 54, 110}, 197}, {{63, 134, 251, 59, 192, 0, 233, 95, 69, 50, 240, 108, 240, 248, 241, 92}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 92, 129, 245, 133, 95}, 197}, {{63, 134, 251, 59, 192, 0, 0, 125, 109, 66, 92, 113, 131, 140, 70, 145}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 186, 175, 229, 112, 226, 108, 242}, 197}, {{63, 134, 251, 59, 192, 0, 24, 69, 196, 24, 220, 191, 86, 27, 121, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 104, 91, 249, 198}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 246, 45, 228, 52, 254}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 83, 231, 114, 201, 214, 65, 238, 65}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 51, 213, 99, 137, 226}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 251, 115, 43, 204}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 201}, 197}, {{63, 134, 251, 59, 192, 0, 193, 21, 203, 161, 155, 170, 152, 153, 189, 25}, 197}, {{63, 134, 251, 59, 192, 0, 0, 16, 84, 37, 163, 78, 23, 235, 234, 116}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 247, 34, 118, 112, 36}, 197}, {{63, 134, 251, 59, 192, 0, 0, 216, 0, 153, 33, 199, 78, 168, 5, 209}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 50, 149, 120, 226}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 121}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 82, 58, 93, 110, 70}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 196}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 148, 244, 45, 67, 145, 77}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 99, 242, 155}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 139, 141, 5, 234}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 8, 252, 237, 43, 27, 203, 54}, 197}, {{63, 134, 251, 59, 192, 0, 236, 70, 231, 67, 93, 18, 86, 168, 101, 54}, 197}, {{63, 134, 251, 59, 192, 0, 140, 160, 186, 221, 221, 10, 35, 159, 65, 228}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 16, 222, 158, 39}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 247, 4, 220, 83, 54}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 104, 114, 167, 207, 167, 214, 251, 96}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 39, 190, 222, 119, 248, 102, 240}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 201, 128, 158, 192}, 197}, {{63, 134, 251, 59, 192, 0, 0, 224, 86, 254, 222, 238, 154, 144, 224, 245}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 10}, 197}, {{63, 134, 251, 59, 192, 0, 56, 101, 73, 127, 89, 202, 217, 24, 87, 7}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 169, 205, 219}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 52, 67, 20, 243, 255, 81}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 126, 41, 237, 77, 233, 212, 5}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 208, 195, 65, 86, 88}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 222, 246, 205, 166, 80, 55, 224, 82}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 228, 17, 208, 212, 125}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 35}, 197}, {{63, 134, 251, 59, 192, 0, 165, 239, 210, 187, 240, 86, 168, 17, 99, 107}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 254, 211, 40}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 98}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 184, 105, 191}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 46, 224, 113, 211, 204}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 178, 26, 4, 93, 177, 143}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 151}, 197}, {{63, 134, 251, 59, 192, 0, 0, 177, 126, 254, 231, 95, 42, 44, 239, 57}, 197}, {{63, 134, 251, 59, 192, 0, 0, 207, 243, 169, 151, 205, 44, 206, 64, 120}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 184, 214, 170, 21, 66, 144, 92, 26, 69}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 243, 101, 134, 6, 134}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 175, 158, 193}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 88, 87, 73, 117, 28, 250, 254, 233}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 26, 78, 54, 192, 66, 116, 229, 34}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 202}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 159, 25, 147}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 149, 41, 132, 180, 35}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 215, 30, 166, 128}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 132, 221, 143, 95}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 108, 227, 185, 6, 23, 226, 157}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 64, 77, 121, 228, 228, 179, 21, 4}, 197}, {{63, 134, 251, 59, 192, 0, 0, 191, 56, 248, 25, 253, 211, 103, 88, 170}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 94, 147, 114, 206, 28, 150}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 234, 62, 170, 77, 41, 61, 243, 196}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 104, 125, 85, 28, 62, 34, 78, 237}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 117, 222, 66}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 84, 58, 128, 152, 126, 126, 217}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 36, 129, 188, 90, 107, 70}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 155, 84, 247}, 197}, {{63, 134, 251, 59, 192, 0, 0, 32, 99, 143, 39, 85, 93, 244, 24, 29}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 67, 187, 159, 128}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 191, 77, 116}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 186, 254, 247}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 148, 252, 37, 39, 121, 213, 107, 56}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 14}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 36, 64, 160, 91, 25, 89}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 121, 86, 42, 100, 68, 46, 105}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 247, 23, 77}, 197}, {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 98, 38, 76, 171}, 197}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 51}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 155, 179, 111, 96, 154}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 202}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 242, 251}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 36, 187, 75, 205}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 125, 115, 194}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 115, 155}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 197, 5, 83}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 174, 54}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 204}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 249}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 37, 192, 68, 19, 123}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 87, 194, 29, 200, 80}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 40, 172, 160, 87}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 150, 142, 124, 203}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 181, 132}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 239, 173, 81}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 219, 20}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 162, 107, 141, 163}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 196, 118, 101}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 60, 95, 22, 150, 23}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 120, 138, 174, 18, 9}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 148}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 115, 134, 121}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 51, 187, 230, 172, 206, 250}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 218, 229}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 102, 212, 38, 181}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 36}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 234, 76, 154, 56}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 128, 251, 236, 164}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 7, 48, 49}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 174, 53}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 41, 24}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 235, 90}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 133}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 182, 239, 200, 64}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 94, 213, 91, 211, 29}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 29, 133, 10, 19, 23}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 74, 27}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 59}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 6, 61, 51}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 64, 196, 243}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 246}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 241, 253}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 145, 248}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 16, 242, 166, 72, 55}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 23, 178, 196}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 145, 226, 171, 219}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 45, 128, 229}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 169, 117, 60, 67, 173}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 234, 203}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 99}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 113, 85, 171}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 197, 34, 254, 77, 70}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 77}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 177, 172, 23, 205, 62}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 67, 44, 60, 81}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 150}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 44, 29, 226, 4, 201}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 213, 190}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 24}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 229, 206}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 184}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 43, 29, 11}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 9, 97, 201, 254, 254}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 74}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 104, 138}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 174, 210, 47, 153, 105}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 125, 139, 43}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 84, 70, 193, 222, 160}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 50, 166, 16, 118, 249}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 13, 245}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 91}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 169, 25, 35, 19, 91}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 36, 38, 50}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 246, 178, 214}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 99}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 243, 231}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 192, 255, 23, 61, 18}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 181}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 66, 235}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 7, 158, 192}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 218, 13}, 106}, {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 61, 44, 226, 224, 132}, 106}, }; #define NUM_ROUTE_ENTRIES (sizeof(large_route_table) / sizeof(large_route_table[0])) #define NUM_IPS_ENTRIES (sizeof(large_ips_table) / sizeof(large_ips_table[0])) #endif /* _TEST_LPM_ROUTES_H_ */ ================================================ FILE: app/test/test_lpm_routes.h ================================================ [File too large to display: 20.5 MB] ================================================ FILE: app/test/test_malloc.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #define N 10000 /* * Malloc * ====== * * Allocate some dynamic memory from heap (3 areas). Check that areas * don't overlap and that alignment constraints match. This test is * done many times on different lcores simultaneously. */ /* Test if memory overlaps: return 1 if true, or 0 if false. */ static int is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2) { unsigned long ptr1 = (unsigned long)p1; unsigned long ptr2 = (unsigned long)p2; if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1) return 1; else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2) return 1; return 0; } static int is_aligned(void *p, int align) { unsigned long addr = (unsigned long)p; unsigned mask = align - 1; if (addr & mask) return 0; return 1; } static int test_align_overlap_per_lcore(__attribute__((unused)) void *arg) { const unsigned align1 = 8, align2 = 64, align3 = 2048; unsigned i,j; void *p1 = NULL, *p2 = NULL, *p3 = NULL; int ret = 0; for (i = 0; i < N; i++) { p1 = rte_zmalloc("dummy", 1000, align1); if (!p1){ printf("rte_zmalloc returned NULL (i=%u)\n", i); ret = -1; break; } for(j = 0; j < 1000 ; j++) { if( *(char *)p1 != 0) { printf("rte_zmalloc didn't zero" "the allocated memory\n"); ret = -1; } } p2 = rte_malloc("dummy", 1000, align2); if (!p2){ printf("rte_malloc returned NULL (i=%u)\n", i); ret = -1; rte_free(p1); break; } p3 = rte_malloc("dummy", 1000, align3); if (!p3){ printf("rte_malloc returned NULL (i=%u)\n", i); ret = -1; rte_free(p1); rte_free(p2); break; } if (is_memory_overlap(p1, 1000, p2, 1000)) { printf("p1 and p2 overlaps\n"); ret = -1; } if (is_memory_overlap(p2, 1000, p3, 1000)) { printf("p2 and p3 overlaps\n"); ret = -1; } if (is_memory_overlap(p1, 1000, p3, 1000)) { printf("p1 and p3 overlaps\n"); ret = -1; } if (!is_aligned(p1, align1)) { printf("p1 is not aligned\n"); ret = -1; } if (!is_aligned(p2, align2)) { printf("p2 is not aligned\n"); ret = -1; } if (!is_aligned(p3, align3)) { printf("p3 is not aligned\n"); ret = -1; } rte_free(p1); rte_free(p2); rte_free(p3); } rte_malloc_dump_stats(stdout, "dummy"); return ret; } static int test_reordered_free_per_lcore(__attribute__((unused)) void *arg) { const unsigned align1 = 8, align2 = 64, align3 = 2048; unsigned i,j; void *p1, *p2, *p3; int ret = 0; for (i = 0; i < 30; i++) { p1 = rte_zmalloc("dummy", 1000, align1); if (!p1){ printf("rte_zmalloc returned NULL (i=%u)\n", i); ret = -1; break; } for(j = 0; j < 1000 ; j++) { if( *(char *)p1 != 0) { printf("rte_zmalloc didn't zero" "the allocated memory\n"); ret = -1; } } /* use calloc to allocate 1000 16-byte items this time */ p2 = rte_calloc("dummy", 1000, 16, align2); /* for third request use regular malloc again */ p3 = rte_malloc("dummy", 1000, align3); if (!p2 || !p3){ printf("rte_malloc returned NULL (i=%u)\n", i); ret = -1; break; } if (is_memory_overlap(p1, 1000, p2, 1000)) { printf("p1 and p2 overlaps\n"); ret = -1; } if (is_memory_overlap(p2, 1000, p3, 1000)) { printf("p2 and p3 overlaps\n"); ret = -1; } if (is_memory_overlap(p1, 1000, p3, 1000)) { printf("p1 and p3 overlaps\n"); ret = -1; } if (!is_aligned(p1, align1)) { printf("p1 is not aligned\n"); ret = -1; } if (!is_aligned(p2, align2)) { printf("p2 is not aligned\n"); ret = -1; } if (!is_aligned(p3, align3)) { printf("p3 is not aligned\n"); ret = -1; } /* try freeing in every possible order */ switch (i%6){ case 0: rte_free(p1); rte_free(p2); rte_free(p3); break; case 1: rte_free(p1); rte_free(p3); rte_free(p2); break; case 2: rte_free(p2); rte_free(p1); rte_free(p3); break; case 3: rte_free(p2); rte_free(p3); rte_free(p1); break; case 4: rte_free(p3); rte_free(p1); rte_free(p2); break; case 5: rte_free(p3); rte_free(p2); rte_free(p1); break; } } rte_malloc_dump_stats(stdout, "dummy"); return ret; } /* test function inside the malloc lib*/ static int test_str_to_size(void) { struct { const char *str; uint64_t value; } test_values[] = {{ "5G", (uint64_t)5 * 1024 * 1024 *1024 }, {"0x20g", (uint64_t)0x20 * 1024 * 1024 *1024}, {"10M", 10 * 1024 * 1024}, {"050m", 050 * 1024 * 1024}, {"8K", 8 * 1024}, {"15k", 15 * 1024}, {"0200", 0200}, {"0x103", 0x103}, {"432", 432}, {"-1", 0}, /* negative values return 0 */ {" -2", 0}, {" -3MB", 0}, {"18446744073709551616", 0} /* ULLONG_MAX + 1 == out of range*/ }; unsigned i; for (i = 0; i < sizeof(test_values)/sizeof(test_values[0]); i++) if (rte_str_to_size(test_values[i].str) != test_values[i].value) return -1; return 0; } static int test_multi_alloc_statistics(void) { int socket = 0; struct rte_malloc_socket_stats pre_stats, post_stats ,first_stats, second_stats; size_t size = 2048; int align = 1024; #ifndef RTE_LIBRTE_MALLOC_DEBUG int trailer_size = 0; #else int trailer_size = RTE_CACHE_LINE_SIZE; #endif int overhead = RTE_CACHE_LINE_SIZE + trailer_size; rte_malloc_get_socket_stats(socket, &pre_stats); void *p1 = rte_malloc_socket("stats", size , align, socket); if (!p1) return -1; rte_free(p1); rte_malloc_dump_stats(stdout, "stats"); rte_malloc_get_socket_stats(socket,&post_stats); /* Check statistics reported are correct */ /* All post stats should be equal to pre stats after alloc freed */ if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) && (post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) && (post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&& (post_stats.alloc_count!=pre_stats.alloc_count)&& (post_stats.free_count!=pre_stats.free_count)) { printf("Malloc statistics are incorrect - freed alloc\n"); return -1; } /* Check two consecutive allocations */ size = 1024; align = 0; rte_malloc_get_socket_stats(socket,&pre_stats); void *p2 = rte_malloc_socket("add", size ,align, socket); if (!p2) return -1; rte_malloc_get_socket_stats(socket,&first_stats); void *p3 = rte_malloc_socket("add2", size,align, socket); if (!p3) return -1; rte_malloc_get_socket_stats(socket,&second_stats); rte_free(p2); rte_free(p3); /* After freeing both allocations check stats return to original */ rte_malloc_get_socket_stats(socket, &post_stats); if(second_stats.heap_totalsz_bytes != first_stats.heap_totalsz_bytes) { printf("Incorrect heap statistics: Total size \n"); return -1; } /* Check allocated size is equal to two additions plus overhead */ if(second_stats.heap_allocsz_bytes != size + overhead + first_stats.heap_allocsz_bytes) { printf("Incorrect heap statistics: Allocated size \n"); return -1; } /* Check that allocation count increments correctly i.e. +1 */ if (second_stats.alloc_count != first_stats.alloc_count + 1) { printf("Incorrect heap statistics: Allocated count \n"); return -1; } if (second_stats.free_count != first_stats.free_count){ printf("Incorrect heap statistics: Free count \n"); return -1; } /* Make sure that we didn't touch our greatest chunk: 2 * 11M) */ if (post_stats.greatest_free_size != pre_stats.greatest_free_size) { printf("Incorrect heap statistics: Greatest free size \n"); return -1; } /* Free size must equal the original free size minus the new allocation*/ if (first_stats.heap_freesz_bytes <= second_stats.heap_freesz_bytes) { printf("Incorrect heap statistics: Free size \n"); return -1; } if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) && (post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) && (post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&& (post_stats.alloc_count!=pre_stats.alloc_count)&& (post_stats.free_count!=pre_stats.free_count)) { printf("Malloc statistics are incorrect - freed alloc\n"); return -1; } return 0; } static int test_rte_malloc_type_limits(void) { /* The type-limits functionality is not yet implemented, * so always return 0 no matter what the retval. */ const char *typename = "limit_test"; rte_malloc_set_limit(typename, 64 * 1024); rte_malloc_dump_stats(stdout, typename); return 0; } static int test_realloc(void) { const char hello_str[] = "Hello, world!"; const unsigned size1 = 1024; const unsigned size2 = size1 + 1024; const unsigned size3 = size2; const unsigned size4 = size3 + 1024; /* test data is the same even if element is moved*/ char *ptr1 = rte_zmalloc(NULL, size1, RTE_CACHE_LINE_SIZE); if (!ptr1){ printf("NULL pointer returned from rte_zmalloc\n"); return -1; } snprintf(ptr1, size1, "%s" ,hello_str); char *ptr2 = rte_realloc(ptr1, size2, RTE_CACHE_LINE_SIZE); if (!ptr2){ rte_free(ptr1); printf("NULL pointer returned from rte_realloc\n"); return -1; } if (ptr1 == ptr2){ printf("unexpected - ptr1 == ptr2\n"); } if (strcmp(ptr2, hello_str) != 0){ printf("Error - lost data from pointed area\n"); rte_free(ptr2); return -1; } unsigned i; for (i = strnlen(hello_str, sizeof(hello_str)); i < size1; i++) if (ptr2[i] != 0){ printf("Bad data in realloc\n"); rte_free(ptr2); return -1; } /* now allocate third element, free the second * and resize third. It should not move. (ptr1 is now invalid) */ char *ptr3 = rte_zmalloc(NULL, size3, RTE_CACHE_LINE_SIZE); if (!ptr3){ printf("NULL pointer returned from rte_zmalloc\n"); rte_free(ptr2); return -1; } for (i = 0; i < size3; i++) if (ptr3[i] != 0){ printf("Bad data in zmalloc\n"); rte_free(ptr3); rte_free(ptr2); return -1; } rte_free(ptr2); /* first resize to half the size of the freed block */ char *ptr4 = rte_realloc(ptr3, size4, RTE_CACHE_LINE_SIZE); if (!ptr4){ printf("NULL pointer returned from rte_realloc\n"); rte_free(ptr3); return -1; } if (ptr3 != ptr4){ printf("Unexpected - ptr4 != ptr3\n"); rte_free(ptr4); return -1; } /* now resize again to the full size of the freed block */ ptr4 = rte_realloc(ptr3, size3 + size2 + size1, RTE_CACHE_LINE_SIZE); if (ptr3 != ptr4){ printf("Unexpected - ptr4 != ptr3 on second resize\n"); rte_free(ptr4); return -1; } rte_free(ptr4); /* now try a resize to a smaller size, see if it works */ const unsigned size5 = 1024; const unsigned size6 = size5 / 2; char *ptr5 = rte_malloc(NULL, size5, RTE_CACHE_LINE_SIZE); if (!ptr5){ printf("NULL pointer returned from rte_malloc\n"); return -1; } char *ptr6 = rte_realloc(ptr5, size6, RTE_CACHE_LINE_SIZE); if (!ptr6){ printf("NULL pointer returned from rte_realloc\n"); rte_free(ptr5); return -1; } if (ptr5 != ptr6){ printf("Error, resizing to a smaller size moved data\n"); rte_free(ptr6); return -1; } rte_free(ptr6); /* check for behaviour changing alignment */ const unsigned size7 = 1024; const unsigned orig_align = RTE_CACHE_LINE_SIZE; unsigned new_align = RTE_CACHE_LINE_SIZE * 2; char *ptr7 = rte_malloc(NULL, size7, orig_align); if (!ptr7){ printf("NULL pointer returned from rte_malloc\n"); return -1; } /* calc an alignment we don't already have */ while(RTE_PTR_ALIGN(ptr7, new_align) == ptr7) new_align *= 2; char *ptr8 = rte_realloc(ptr7, size7, new_align); if (!ptr8){ printf("NULL pointer returned from rte_realloc\n"); rte_free(ptr7); return -1; } if (RTE_PTR_ALIGN(ptr8, new_align) != ptr8){ printf("Failure to re-align data\n"); rte_free(ptr8); return -1; } rte_free(ptr8); /* test behaviour when there is a free block after current one, * but its not big enough */ unsigned size9 = 1024, size10 = 1024; unsigned size11 = size9 + size10 + 256; char *ptr9 = rte_malloc(NULL, size9, RTE_CACHE_LINE_SIZE); if (!ptr9){ printf("NULL pointer returned from rte_malloc\n"); return -1; } char *ptr10 = rte_malloc(NULL, size10, RTE_CACHE_LINE_SIZE); if (!ptr10){ printf("NULL pointer returned from rte_malloc\n"); return -1; } rte_free(ptr9); char *ptr11 = rte_realloc(ptr10, size11, RTE_CACHE_LINE_SIZE); if (!ptr11){ printf("NULL pointer returned from rte_realloc\n"); rte_free(ptr10); return -1; } if (ptr11 == ptr10){ printf("Error, unexpected that realloc has not created new buffer\n"); rte_free(ptr11); return -1; } rte_free(ptr11); /* check we don't crash if we pass null to realloc * We should get a malloc of the size requested*/ const size_t size12 = 1024; size_t size12_check; char *ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE); if (!ptr12){ printf("NULL pointer returned from rte_realloc\n"); return -1; } if (rte_malloc_validate(ptr12, &size12_check) < 0 || size12_check != size12){ rte_free(ptr12); return -1; } rte_free(ptr12); return 0; } static int test_random_alloc_free(void *_ __attribute__((unused))) { struct mem_list { struct mem_list *next; char data[0]; } *list_head = NULL; unsigned i; unsigned count = 0; rte_srand((unsigned)rte_rdtsc()); for (i = 0; i < N; i++){ unsigned free_mem = 0; size_t allocated_size; while (!free_mem){ const unsigned mem_size = sizeof(struct mem_list) + \ rte_rand() % (64 * 1024); const unsigned align = 1 << (rte_rand() % 12); /* up to 4k alignment */ struct mem_list *entry = rte_malloc(NULL, mem_size, align); if (entry == NULL) return -1; if (RTE_PTR_ALIGN(entry, align)!= entry) return -1; if (rte_malloc_validate(entry, &allocated_size) == -1 || allocated_size < mem_size) return -1; memset(entry->data, rte_lcore_id(), mem_size - sizeof(*entry)); entry->next = list_head; if (rte_malloc_validate(entry, NULL) == -1) return -1; list_head = entry; count++; /* switch to freeing the memory with a 20% probability */ free_mem = ((rte_rand() % 10) >= 8); } while (list_head){ struct mem_list *entry = list_head; list_head = list_head->next; rte_free(entry); } } printf("Lcore %u allocated/freed %u blocks\n", rte_lcore_id(), count); return 0; } #define err_return() do { \ printf("%s: %d - Error\n", __func__, __LINE__); \ goto err_return; \ } while (0) static int test_rte_malloc_validate(void) { const size_t request_size = 1024; size_t allocated_size; char *data_ptr = rte_malloc(NULL, request_size, RTE_CACHE_LINE_SIZE); #ifdef RTE_LIBRTE_MALLOC_DEBUG int retval; char *over_write_vals = NULL; #endif if (data_ptr == NULL) { printf("%s: %d - Allocation error\n", __func__, __LINE__); return -1; } /* check that a null input returns -1 */ if (rte_malloc_validate(NULL, NULL) != -1) err_return(); /* check that we get ok on a valid pointer */ if (rte_malloc_validate(data_ptr, &allocated_size) < 0) err_return(); /* check that the returned size is ok */ if (allocated_size < request_size) err_return(); #ifdef RTE_LIBRTE_MALLOC_DEBUG /****** change the header to be bad */ char save_buf[64]; over_write_vals = (char *)((uintptr_t)data_ptr - sizeof(save_buf)); /* first save the data as a backup before overwriting it */ memcpy(save_buf, over_write_vals, sizeof(save_buf)); memset(over_write_vals, 1, sizeof(save_buf)); /* then run validate */ retval = rte_malloc_validate(data_ptr, NULL); /* finally restore the data again */ memcpy(over_write_vals, save_buf, sizeof(save_buf)); /* check we previously had an error */ if (retval != -1) err_return(); /* check all ok again */ if (rte_malloc_validate(data_ptr, &allocated_size) < 0) err_return(); /**** change the trailer to be bad */ over_write_vals = (char *)((uintptr_t)data_ptr + allocated_size); /* first save the data as a backup before overwriting it */ memcpy(save_buf, over_write_vals, sizeof(save_buf)); memset(over_write_vals, 1, sizeof(save_buf)); /* then run validate */ retval = rte_malloc_validate(data_ptr, NULL); /* finally restore the data again */ memcpy(over_write_vals, save_buf, sizeof(save_buf)); if (retval != -1) err_return(); /* check all ok again */ if (rte_malloc_validate(data_ptr, &allocated_size) < 0) err_return(); #endif rte_free(data_ptr); return 0; err_return: /*clean up */ rte_free(data_ptr); return -1; } static int test_zero_aligned_alloc(void) { char *p1 = rte_malloc(NULL,1024, 0); if (!p1) goto err_return; if (!rte_is_aligned(p1, RTE_CACHE_LINE_SIZE)) goto err_return; rte_free(p1); return 0; err_return: /*clean up */ if (p1) rte_free(p1); return -1; } static int test_malloc_bad_params(void) { const char *type = NULL; size_t size = 0; unsigned align = RTE_CACHE_LINE_SIZE; /* rte_malloc expected to return null with inappropriate size */ char *bad_ptr = rte_malloc(type, size, align); if (bad_ptr != NULL) goto err_return; /* rte_malloc expected to return null with inappropriate alignment */ align = 17; size = 1024; bad_ptr = rte_malloc(type, size, align); if (bad_ptr != NULL) goto err_return; return 0; err_return: /* clean up pointer */ if (bad_ptr) rte_free(bad_ptr); return -1; } /* Check if memory is avilable on a specific socket */ static int is_mem_on_socket(int32_t socket) { const struct rte_memseg *ms = rte_eal_get_physmem_layout(); unsigned i; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (socket == ms[i].socket_id) return 1; } return 0; } /* * Find what socket a memory address is on. Only works for addresses within * memsegs, not heap or stack... */ static int32_t addr_to_socket(void * addr) { const struct rte_memseg *ms = rte_eal_get_physmem_layout(); unsigned i; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if ((ms[i].addr <= addr) && ((uintptr_t)addr < ((uintptr_t)ms[i].addr + (uintptr_t)ms[i].len))) return ms[i].socket_id; } return -1; } /* Test using rte_[c|m|zm]alloc_socket() on a specific socket */ static int test_alloc_single_socket(int32_t socket) { const char *type = NULL; const size_t size = 10; const unsigned align = 0; char *mem = NULL; int32_t desired_socket = (socket == SOCKET_ID_ANY) ? (int32_t)rte_socket_id() : socket; /* Test rte_calloc_socket() */ mem = rte_calloc_socket(type, size, sizeof(char), align, socket); if (mem == NULL) return -1; if (addr_to_socket(mem) != desired_socket) { rte_free(mem); return -1; } rte_free(mem); /* Test rte_malloc_socket() */ mem = rte_malloc_socket(type, size, align, socket); if (mem == NULL) return -1; if (addr_to_socket(mem) != desired_socket) { return -1; } rte_free(mem); /* Test rte_zmalloc_socket() */ mem = rte_zmalloc_socket(type, size, align, socket); if (mem == NULL) return -1; if (addr_to_socket(mem) != desired_socket) { rte_free(mem); return -1; } rte_free(mem); return 0; } static int test_alloc_socket(void) { unsigned socket_count = 0; unsigned i; if (test_alloc_single_socket(SOCKET_ID_ANY) < 0) return -1; for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { if (is_mem_on_socket(i)) { socket_count++; if (test_alloc_single_socket(i) < 0) { printf("Fail: rte_malloc_socket(..., %u) did not succeed\n", i); return -1; } } else { if (test_alloc_single_socket(i) == 0) { printf("Fail: rte_malloc_socket(..., %u) succeeded\n", i); return -1; } } } /* Print warnign if only a single socket, but don't fail the test */ if (socket_count < 2) { printf("WARNING: alloc_socket test needs memory on multiple sockets!\n"); } return 0; } static int test_malloc(void) { unsigned lcore_id; int ret = 0; if (test_str_to_size() < 0){ printf("test_str_to_size() failed\n"); return -1; } else printf("test_str_to_size() passed\n"); if (test_zero_aligned_alloc() < 0){ printf("test_zero_aligned_alloc() failed\n"); return -1; } else printf("test_zero_aligned_alloc() passed\n"); if (test_malloc_bad_params() < 0){ printf("test_malloc_bad_params() failed\n"); return -1; } else printf("test_malloc_bad_params() passed\n"); if (test_realloc() < 0){ printf("test_realloc() failed\n"); return -1; } else printf("test_realloc() passed\n"); /*----------------------------*/ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id); } RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) ret = -1; } if (ret < 0){ printf("test_align_overlap_per_lcore() failed\n"); return ret; } else printf("test_align_overlap_per_lcore() passed\n"); /*----------------------------*/ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id); } RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) ret = -1; } if (ret < 0){ printf("test_reordered_free_per_lcore() failed\n"); return ret; } else printf("test_reordered_free_per_lcore() passed\n"); /*----------------------------*/ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id); } RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) ret = -1; } if (ret < 0){ printf("test_random_alloc_free() failed\n"); return ret; } else printf("test_random_alloc_free() passed\n"); /*----------------------------*/ ret = test_rte_malloc_type_limits(); if (ret < 0){ printf("test_rte_malloc_type_limits() failed\n"); return ret; } /* TODO: uncomment following line once type limits are valid */ /*else printf("test_rte_malloc_type_limits() passed\n");*/ /*----------------------------*/ ret = test_rte_malloc_validate(); if (ret < 0){ printf("test_rte_malloc_validate() failed\n"); return ret; } else printf("test_rte_malloc_validate() passed\n"); ret = test_alloc_socket(); if (ret < 0){ printf("test_alloc_socket() failed\n"); return ret; } else printf("test_alloc_socket() passed\n"); ret = test_multi_alloc_statistics(); if (ret < 0) { printf("test_multi_alloc_statistics() failed\n"); return ret; } else printf("test_multi_alloc_statistics() passed\n"); return 0; } static struct test_command malloc_cmd = { .command = "malloc_autotest", .callback = test_malloc, }; REGISTER_TEST_COMMAND(malloc_cmd); ================================================ FILE: app/test/test_mbuf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #define MBUF_DATA_SIZE 2048 #define NB_MBUF 128 #define MBUF_TEST_DATA_LEN 1464 #define MBUF_TEST_DATA_LEN2 50 #define MBUF_TEST_HDR1_LEN 20 #define MBUF_TEST_HDR2_LEN 30 #define MBUF_TEST_ALL_HDRS_LEN (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN) /* size of private data for mbuf in pktmbuf_pool2 */ #define MBUF2_PRIV_SIZE 128 #define REFCNT_MAX_ITER 64 #define REFCNT_MAX_TIMEOUT 10 #define REFCNT_MAX_REF (RTE_MAX_LCORE) #define REFCNT_MBUF_NUM 64 #define REFCNT_RING_SIZE (REFCNT_MBUF_NUM * REFCNT_MAX_REF) #define MAGIC_DATA 0x42424242 #define MAKE_STRING(x) # x static struct rte_mempool *pktmbuf_pool = NULL; static struct rte_mempool *pktmbuf_pool2 = NULL; #ifdef RTE_MBUF_REFCNT_ATOMIC static struct rte_mempool *refcnt_pool = NULL; static struct rte_ring *refcnt_mbuf_ring = NULL; static volatile uint32_t refcnt_stop_slaves; static unsigned refcnt_lcore[RTE_MAX_LCORE]; #endif /* * MBUF * ==== * * #. Allocate a mbuf pool. * * - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE * bytes long. * * #. Test multiple allocations of mbufs from this pool. * * - Allocate NB_MBUF and store pointers in a table. * - If an allocation fails, return an error. * - Free all these mbufs. * - Repeat the same test to check that mbufs were freed correctly. * * #. Test data manipulation in pktmbuf. * * - Alloc an mbuf. * - Append data using rte_pktmbuf_append(). * - Test for error in rte_pktmbuf_append() when len is too large. * - Trim data at the end of mbuf using rte_pktmbuf_trim(). * - Test for error in rte_pktmbuf_trim() when len is too large. * - Prepend a header using rte_pktmbuf_prepend(). * - Test for error in rte_pktmbuf_prepend() when len is too large. * - Remove data at the beginning of mbuf using rte_pktmbuf_adj(). * - Test for error in rte_pktmbuf_adj() when len is too large. * - Check that appended data is not corrupt. * - Free the mbuf. * - Between all these tests, check data_len and pkt_len, and * that the mbuf is contiguous. * - Repeat the test to check that allocation operations * reinitialize the mbuf correctly. * * #. Test packet cloning * - Clone a mbuf and verify the data * - Clone the cloned mbuf and verify the data * - Attach a mbuf to another that does not have the same priv_size. */ #define GOTO_FAIL(str, ...) do { \ printf("mbuf test FAILED (l.%d): <" str ">\n", \ __LINE__, ##__VA_ARGS__); \ goto fail; \ } while(0) /* * test data manipulation in mbuf with non-ascii data */ static int test_pktmbuf_with_non_ascii_data(void) { struct rte_mbuf *m = NULL; char *data; m = rte_pktmbuf_alloc(pktmbuf_pool); if (m == NULL) GOTO_FAIL("Cannot allocate mbuf"); if (rte_pktmbuf_pkt_len(m) != 0) GOTO_FAIL("Bad length"); data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN); if (data == NULL) GOTO_FAIL("Cannot append data"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad data length"); memset(data, 0xff, rte_pktmbuf_pkt_len(m)); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN); rte_pktmbuf_free(m); return 0; fail: if(m) { rte_pktmbuf_free(m); } return -1; } /* * test data manipulation in mbuf */ static int test_one_pktmbuf(void) { struct rte_mbuf *m = NULL; char *data, *data2, *hdr; unsigned i; printf("Test pktmbuf API\n"); /* alloc a mbuf */ m = rte_pktmbuf_alloc(pktmbuf_pool); if (m == NULL) GOTO_FAIL("Cannot allocate mbuf"); if (rte_pktmbuf_pkt_len(m) != 0) GOTO_FAIL("Bad length"); rte_pktmbuf_dump(stdout, m, 0); /* append data */ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN); if (data == NULL) GOTO_FAIL("Cannot append data"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad data length"); memset(data, 0x66, rte_pktmbuf_pkt_len(m)); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN); rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN); /* this append should fail */ data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1)); if (data2 != NULL) GOTO_FAIL("Append should not succeed"); /* append some more data */ data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2); if (data2 == NULL) GOTO_FAIL("Cannot append data"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2) GOTO_FAIL("Bad data length"); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); /* trim data at the end of mbuf */ if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0) GOTO_FAIL("Cannot trim data"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad data length"); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); /* this trim should fail */ if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0) GOTO_FAIL("trim should not succeed"); /* prepend one header */ hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN); if (hdr == NULL) GOTO_FAIL("Cannot prepend"); if (data - hdr != MBUF_TEST_HDR1_LEN) GOTO_FAIL("Prepend failed"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN) GOTO_FAIL("Bad data length"); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); memset(hdr, 0x55, MBUF_TEST_HDR1_LEN); /* prepend another header */ hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN); if (hdr == NULL) GOTO_FAIL("Cannot prepend"); if (data - hdr != MBUF_TEST_ALL_HDRS_LEN) GOTO_FAIL("Prepend failed"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN) GOTO_FAIL("Bad data length"); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); memset(hdr, 0x55, MBUF_TEST_HDR2_LEN); rte_mbuf_sanity_check(m, 1); rte_mbuf_sanity_check(m, 0); rte_pktmbuf_dump(stdout, m, 0); /* this prepend should fail */ hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1)); if (hdr != NULL) GOTO_FAIL("prepend should not succeed"); /* remove data at beginning of mbuf (adj) */ if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN)) GOTO_FAIL("rte_pktmbuf_adj failed"); if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad pkt length"); if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN) GOTO_FAIL("Bad data length"); if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); /* this adj should fail */ if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL) GOTO_FAIL("rte_pktmbuf_adj should not succeed"); /* check data */ if (!rte_pktmbuf_is_contiguous(m)) GOTO_FAIL("Buffer should be continuous"); for (i=0; inext = rte_pktmbuf_alloc(pktmbuf_pool); if (m->next == NULL) GOTO_FAIL("Next Pkt Null\n"); rte_pktmbuf_append(m->next, sizeof(uint32_t)); data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *); *data = MAGIC_DATA; clone = rte_pktmbuf_clone(m, pktmbuf_pool); if (clone == NULL) GOTO_FAIL("cannot clone data\n"); data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *); if (*data != MAGIC_DATA) GOTO_FAIL("invalid data in clone\n"); data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *); if (*data != MAGIC_DATA) GOTO_FAIL("invalid data in clone->next\n"); if (rte_mbuf_refcnt_read(m) != 2) GOTO_FAIL("invalid refcnt in m\n"); if (rte_mbuf_refcnt_read(m->next) != 2) GOTO_FAIL("invalid refcnt in m->next\n"); /* try to clone the clone */ clone2 = rte_pktmbuf_clone(clone, pktmbuf_pool); if (clone2 == NULL) GOTO_FAIL("cannot clone the clone\n"); data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *); if (*data != MAGIC_DATA) GOTO_FAIL("invalid data in clone2\n"); data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *); if (*data != MAGIC_DATA) GOTO_FAIL("invalid data in clone2->next\n"); if (rte_mbuf_refcnt_read(m) != 3) GOTO_FAIL("invalid refcnt in m\n"); if (rte_mbuf_refcnt_read(m->next) != 3) GOTO_FAIL("invalid refcnt in m->next\n"); /* free mbuf */ rte_pktmbuf_free(m); rte_pktmbuf_free(clone); rte_pktmbuf_free(clone2); m = NULL; clone = NULL; clone2 = NULL; printf("%s ok\n", __func__); return 0; fail: if (m) rte_pktmbuf_free(m); if (clone) rte_pktmbuf_free(clone); if (clone2) rte_pktmbuf_free(clone2); return -1; } static int test_attach_from_different_pool(void) { struct rte_mbuf *m = NULL; struct rte_mbuf *clone = NULL; struct rte_mbuf *clone2 = NULL; char *data, *c_data, *c_data2; /* alloc a mbuf */ m = rte_pktmbuf_alloc(pktmbuf_pool); if (m == NULL) GOTO_FAIL("cannot allocate mbuf"); if (rte_pktmbuf_pkt_len(m) != 0) GOTO_FAIL("Bad length"); data = rte_pktmbuf_mtod(m, char *); /* allocate a new mbuf from the second pool, and attach it to the first * mbuf */ clone = rte_pktmbuf_alloc(pktmbuf_pool2); if (clone == NULL) GOTO_FAIL("cannot allocate mbuf from second pool\n"); /* check data room size and priv size, and erase priv */ if (rte_pktmbuf_data_room_size(clone->pool) != 0) GOTO_FAIL("data room size should be 0\n"); if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE) GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE); memset(clone + 1, 0, MBUF2_PRIV_SIZE); /* save data pointer to compare it after detach() */ c_data = rte_pktmbuf_mtod(clone, char *); if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE) GOTO_FAIL("bad data pointer in clone"); if (rte_pktmbuf_headroom(clone) != 0) GOTO_FAIL("bad headroom in clone"); rte_pktmbuf_attach(clone, m); if (rte_pktmbuf_mtod(clone, char *) != data) GOTO_FAIL("clone was not attached properly\n"); if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM) GOTO_FAIL("bad headroom in clone after attach"); if (rte_mbuf_refcnt_read(m) != 2) GOTO_FAIL("invalid refcnt in m\n"); /* allocate a new mbuf from the second pool, and attach it to the first * cloned mbuf */ clone2 = rte_pktmbuf_alloc(pktmbuf_pool2); if (clone2 == NULL) GOTO_FAIL("cannot allocate clone2 from second pool\n"); /* check data room size and priv size, and erase priv */ if (rte_pktmbuf_data_room_size(clone2->pool) != 0) GOTO_FAIL("data room size should be 0\n"); if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE) GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE); memset(clone2 + 1, 0, MBUF2_PRIV_SIZE); /* save data pointer to compare it after detach() */ c_data2 = rte_pktmbuf_mtod(clone2, char *); if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE) GOTO_FAIL("bad data pointer in clone2"); if (rte_pktmbuf_headroom(clone2) != 0) GOTO_FAIL("bad headroom in clone2"); rte_pktmbuf_attach(clone2, clone); if (rte_pktmbuf_mtod(clone2, char *) != data) GOTO_FAIL("clone2 was not attached properly\n"); if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM) GOTO_FAIL("bad headroom in clone2 after attach"); if (rte_mbuf_refcnt_read(m) != 3) GOTO_FAIL("invalid refcnt in m\n"); /* detach the clones */ rte_pktmbuf_detach(clone); if (c_data != rte_pktmbuf_mtod(clone, char *)) GOTO_FAIL("clone was not detached properly\n"); rte_pktmbuf_detach(clone2); if (c_data2 != rte_pktmbuf_mtod(clone2, char *)) GOTO_FAIL("clone2 was not detached properly\n"); /* free the clones and the initial mbuf */ rte_pktmbuf_free(clone2); rte_pktmbuf_free(clone); rte_pktmbuf_free(m); printf("%s ok\n", __func__); return 0; fail: if (m) rte_pktmbuf_free(m); if (clone) rte_pktmbuf_free(clone); if (clone2) rte_pktmbuf_free(clone2); return -1; } #undef GOTO_FAIL /* * test allocation and free of mbufs */ static int test_pktmbuf_pool(void) { unsigned i; struct rte_mbuf *m[NB_MBUF]; int ret = 0; for (i=0; idata_off += 64; } /* free them */ for (i=0; idata_off != RTE_PKTMBUF_HEADROOM) { printf("invalid data_off\n"); ret = -1; } } /* free them */ for (i=0; inext; rte_pktmbuf_free_seg(mt); } } } return ret; } /* * Stress test for rte_mbuf atomic refcnt. * Implies that RTE_MBUF_REFCNT_ATOMIC is defined. * For more efficency, recomended to run with RTE_LIBRTE_MBUF_DEBUG defined. */ #ifdef RTE_MBUF_REFCNT_ATOMIC static int test_refcnt_slave(__attribute__((unused)) void *arg) { unsigned lcore, free; void *mp = 0; lcore = rte_lcore_id(); printf("%s started at lcore %u\n", __func__, lcore); free = 0; while (refcnt_stop_slaves == 0) { if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) { free++; rte_pktmbuf_free((struct rte_mbuf *)mp); } } refcnt_lcore[lcore] += free; printf("%s finished at lcore %u, " "number of freed mbufs: %u\n", __func__, lcore, free); return (0); } static void test_refcnt_iter(unsigned lcore, unsigned iter) { uint16_t ref; unsigned i, n, tref, wn; struct rte_mbuf *m; tref = 0; /* For each mbuf in the pool: * - allocate mbuf, * - increment it's reference up to N+1, * - enqueue it N times into the ring for slave cores to free. */ for (i = 0, n = rte_mempool_count(refcnt_pool); i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL; i++) { ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL); tref += ref; if ((ref & 1) != 0) { rte_pktmbuf_refcnt_update(m, ref); while (ref-- != 0) rte_ring_enqueue(refcnt_mbuf_ring, m); } else { while (ref-- != 0) { rte_pktmbuf_refcnt_update(m, 1); rte_ring_enqueue(refcnt_mbuf_ring, m); } } rte_pktmbuf_free(m); } if (i != n) rte_panic("(lcore=%u, iter=%u): was able to allocate only " "%u from %u mbufs\n", lcore, iter, i, n); /* wait till slave lcores will consume all mbufs */ while (!rte_ring_empty(refcnt_mbuf_ring)) ; /* check that all mbufs are back into mempool by now */ for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) { if ((i = rte_mempool_count(refcnt_pool)) == n) { refcnt_lcore[lcore] += tref; printf("%s(lcore=%u, iter=%u) completed, " "%u references processed\n", __func__, lcore, iter, tref); return; } rte_delay_ms(1000); } rte_panic("(lcore=%u, iter=%u): after %us only " "%u of %u mbufs left free\n", lcore, iter, wn, i, n); } static int test_refcnt_master(void) { unsigned i, lcore; lcore = rte_lcore_id(); printf("%s started at lcore %u\n", __func__, lcore); for (i = 0; i != REFCNT_MAX_ITER; i++) test_refcnt_iter(lcore, i); refcnt_stop_slaves = 1; rte_wmb(); printf("%s finished at lcore %u\n", __func__, lcore); return (0); } #endif static int test_refcnt_mbuf(void) { #ifdef RTE_MBUF_REFCNT_ATOMIC unsigned lnum, master, slave, tref; if ((lnum = rte_lcore_count()) == 1) { printf("skipping %s, number of lcores: %u is not enough\n", __func__, lnum); return (0); } printf("starting %s, at %u lcores\n", __func__, lnum); /* create refcnt pool & ring if they don't exist */ if (refcnt_pool == NULL && (refcnt_pool = rte_pktmbuf_pool_create( MAKE_STRING(refcnt_pool), REFCNT_MBUF_NUM, 0, 0, 0, SOCKET_ID_ANY)) == NULL) { printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n", __func__); return (-1); } if (refcnt_mbuf_ring == NULL && (refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring", REFCNT_RING_SIZE, SOCKET_ID_ANY, RING_F_SP_ENQ)) == NULL) { printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring) "\n", __func__); return (-1); } refcnt_stop_slaves = 0; memset(refcnt_lcore, 0, sizeof (refcnt_lcore)); rte_eal_mp_remote_launch(test_refcnt_slave, NULL, SKIP_MASTER); test_refcnt_master(); rte_eal_mp_wait_lcore(); /* check that we porcessed all references */ tref = 0; master = rte_get_master_lcore(); RTE_LCORE_FOREACH_SLAVE(slave) tref += refcnt_lcore[slave]; if (tref != refcnt_lcore[master]) rte_panic("refernced mbufs: %u, freed mbufs: %u\n", tref, refcnt_lcore[master]); rte_mempool_dump(stdout, refcnt_pool); rte_ring_dump(stdout, refcnt_mbuf_ring); #endif return (0); } #include #include /* use fork() to test mbuf errors panic */ static int verify_mbuf_check_panics(struct rte_mbuf *buf) { int pid; int status; pid = fork(); if (pid == 0) { rte_mbuf_sanity_check(buf, 1); /* should panic */ exit(0); /* return normally if it doesn't panic */ } else if (pid < 0){ printf("Fork Failed\n"); return -1; } wait(&status); if(status == 0) return -1; return 0; } static int test_failing_mbuf_sanity_check(void) { struct rte_mbuf *buf; struct rte_mbuf badbuf; printf("Checking rte_mbuf_sanity_check for failure conditions\n"); /* get a good mbuf to use to make copies */ buf = rte_pktmbuf_alloc(pktmbuf_pool); if (buf == NULL) return -1; printf("Checking good mbuf initially\n"); if (verify_mbuf_check_panics(buf) != -1) return -1; printf("Now checking for error conditions\n"); if (verify_mbuf_check_panics(NULL)) { printf("Error with NULL mbuf test\n"); return -1; } badbuf = *buf; badbuf.pool = NULL; if (verify_mbuf_check_panics(&badbuf)) { printf("Error with bad-pool mbuf test\n"); return -1; } badbuf = *buf; badbuf.buf_physaddr = 0; if (verify_mbuf_check_panics(&badbuf)) { printf("Error with bad-physaddr mbuf test\n"); return -1; } badbuf = *buf; badbuf.buf_addr = NULL; if (verify_mbuf_check_panics(&badbuf)) { printf("Error with bad-addr mbuf test\n"); return -1; } badbuf = *buf; badbuf.refcnt = 0; if (verify_mbuf_check_panics(&badbuf)) { printf("Error with bad-refcnt(0) mbuf test\n"); return -1; } badbuf = *buf; badbuf.refcnt = UINT16_MAX; if (verify_mbuf_check_panics(&badbuf)) { printf("Error with bad-refcnt(MAX) mbuf test\n"); return -1; } return 0; } static int test_mbuf(void) { RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_SIZE * 2); /* create pktmbuf pool if it does not exist */ if (pktmbuf_pool == NULL) { pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool", NB_MBUF, 32, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY); } if (pktmbuf_pool == NULL) { printf("cannot allocate mbuf pool\n"); return -1; } /* create a specific pktmbuf pool with a priv_size != 0 and no data * room size */ if (pktmbuf_pool2 == NULL) { pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2", NB_MBUF, 32, MBUF2_PRIV_SIZE, 0, SOCKET_ID_ANY); } if (pktmbuf_pool2 == NULL) { printf("cannot allocate mbuf pool\n"); return -1; } /* test multiple mbuf alloc */ if (test_pktmbuf_pool() < 0) { printf("test_mbuf_pool() failed\n"); return -1; } /* do it another time to check that all mbufs were freed */ if (test_pktmbuf_pool() < 0) { printf("test_mbuf_pool() failed (2)\n"); return -1; } /* test that the pointer to the data on a packet mbuf is set properly */ if (test_pktmbuf_pool_ptr() < 0) { printf("test_pktmbuf_pool_ptr() failed\n"); return -1; } /* test data manipulation in mbuf */ if (test_one_pktmbuf() < 0) { printf("test_one_mbuf() failed\n"); return -1; } /* * do it another time, to check that allocation reinitialize * the mbuf correctly */ if (test_one_pktmbuf() < 0) { printf("test_one_mbuf() failed (2)\n"); return -1; } if (test_pktmbuf_with_non_ascii_data() < 0) { printf("test_pktmbuf_with_non_ascii_data() failed\n"); return -1; } /* test free pktmbuf segment one by one */ if (test_pktmbuf_free_segment() < 0) { printf("test_pktmbuf_free_segment() failed.\n"); return -1; } if (testclone_testupdate_testdetach()<0){ printf("testclone_and_testupdate() failed \n"); return -1; } if (test_attach_from_different_pool() < 0) { printf("test_attach_from_different_pool() failed\n"); return -1; } if (test_refcnt_mbuf()<0){ printf("test_refcnt_mbuf() failed \n"); return -1; } if (test_failing_mbuf_sanity_check() < 0) { printf("test_failing_mbuf_sanity_check() failed\n"); return -1; } return 0; } static struct test_command mbuf_cmd = { .command = "mbuf_autotest", .callback = test_mbuf, }; REGISTER_TEST_COMMAND(mbuf_cmd); ================================================ FILE: app/test/test_memcpy.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "test.h" /* * Set this to the maximum buffer size you want to test. If it is 0, then the * values in the buf_sizes[] array below will be used. */ #define TEST_VALUE_RANGE 0 /* List of buffer sizes to test */ #if TEST_VALUE_RANGE == 0 static size_t buf_sizes[] = { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257, 320, 384, 511, 512, 513, 1023, 1024, 1025, 1518, 1522, 1600, 2048, 3072, 4096, 5120, 6144, 7168, 8192 }; /* MUST be as large as largest packet size above */ #define SMALL_BUFFER_SIZE 8192 #else /* TEST_VALUE_RANGE != 0 */ static size_t buf_sizes[TEST_VALUE_RANGE]; #define SMALL_BUFFER_SIZE TEST_VALUE_RANGE #endif /* TEST_VALUE_RANGE == 0 */ /* * Arrays of this size are used for measuring uncached memory accesses by * picking a random location within the buffer. Make this smaller if there are * memory allocation errors. */ #define LARGE_BUFFER_SIZE (100 * 1024 * 1024) /* How many times to run timing loop for performance tests */ #define TEST_ITERATIONS 1000000 #define TEST_BATCH_SIZE 100 /* Data is aligned on this many bytes (power of 2) */ #define ALIGNMENT_UNIT 32 /* * Create two buffers, and initialise one with random values. These are copied * to the second buffer and then compared to see if the copy was successful. * The bytes outside the copied area are also checked to make sure they were not * changed. */ static int test_single_memcpy(unsigned int off_src, unsigned int off_dst, size_t size) { unsigned int i; uint8_t dest[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT]; uint8_t src[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT]; void * ret; /* Setup buffers */ for (i = 0; i < SMALL_BUFFER_SIZE + ALIGNMENT_UNIT; i++) { dest[i] = 0; src[i] = (uint8_t) rte_rand(); } /* Do the copy */ ret = rte_memcpy(dest + off_dst, src + off_src, size); if (ret != (dest + off_dst)) { printf("rte_memcpy() returned %p, not %p\n", ret, dest + off_dst); } /* Check nothing before offset is affected */ for (i = 0; i < off_dst; i++) { if (dest[i] != 0) { printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): " "[modified before start of dst].\n", (unsigned)size, off_src, off_dst); return -1; } } /* Check everything was copied */ for (i = 0; i < size; i++) { if (dest[i + off_dst] != src[i + off_src]) { printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): " "[didn't copy byte %u].\n", (unsigned)size, off_src, off_dst, i); return -1; } } /* Check nothing after copy was affected */ for (i = size; i < SMALL_BUFFER_SIZE; i++) { if (dest[i + off_dst] != 0) { printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): " "[copied too many].\n", (unsigned)size, off_src, off_dst); return -1; } } return 0; } /* * Check functionality for various buffer sizes and data offsets/alignments. */ static int func_test(void) { unsigned int off_src, off_dst, i; unsigned int num_buf_sizes = sizeof(buf_sizes) / sizeof(buf_sizes[0]); int ret; for (off_src = 0; off_src < ALIGNMENT_UNIT; off_src++) { for (off_dst = 0; off_dst < ALIGNMENT_UNIT; off_dst++) { for (i = 0; i < num_buf_sizes; i++) { ret = test_single_memcpy(off_src, off_dst, buf_sizes[i]); if (ret != 0) return -1; } } } return 0; } static int test_memcpy(void) { int ret; ret = func_test(); if (ret != 0) return -1; return 0; } static struct test_command memcpy_cmd = { .command = "memcpy_autotest", .callback = test_memcpy, }; REGISTER_TEST_COMMAND(memcpy_cmd); ================================================ FILE: app/test/test_memcpy_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "test.h" /* * Set this to the maximum buffer size you want to test. If it is 0, then the * values in the buf_sizes[] array below will be used. */ #define TEST_VALUE_RANGE 0 /* List of buffer sizes to test */ #if TEST_VALUE_RANGE == 0 static size_t buf_sizes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 191, 192, 193, 255, 256, 257, 319, 320, 321, 383, 384, 385, 447, 448, 449, 511, 512, 513, 767, 768, 769, 1023, 1024, 1025, 1518, 1522, 1536, 1600, 2048, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192 }; /* MUST be as large as largest packet size above */ #define SMALL_BUFFER_SIZE 8192 #else /* TEST_VALUE_RANGE != 0 */ static size_t buf_sizes[TEST_VALUE_RANGE]; #define SMALL_BUFFER_SIZE TEST_VALUE_RANGE #endif /* TEST_VALUE_RANGE == 0 */ /* * Arrays of this size are used for measuring uncached memory accesses by * picking a random location within the buffer. Make this smaller if there are * memory allocation errors. */ #define LARGE_BUFFER_SIZE (100 * 1024 * 1024) /* How many times to run timing loop for performance tests */ #define TEST_ITERATIONS 1000000 #define TEST_BATCH_SIZE 100 /* Data is aligned on this many bytes (power of 2) */ #define ALIGNMENT_UNIT 32 /* * Pointers used in performance tests. The two large buffers are for uncached * access where random addresses within the buffer are used for each * memcpy. The two small buffers are for cached access. */ static uint8_t *large_buf_read, *large_buf_write; static uint8_t *small_buf_read, *small_buf_write; /* Initialise data buffers. */ static int init_buffers(void) { unsigned i; large_buf_read = rte_malloc("memcpy", LARGE_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT); if (large_buf_read == NULL) goto error_large_buf_read; large_buf_write = rte_malloc("memcpy", LARGE_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT); if (large_buf_write == NULL) goto error_large_buf_write; small_buf_read = rte_malloc("memcpy", SMALL_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT); if (small_buf_read == NULL) goto error_small_buf_read; small_buf_write = rte_malloc("memcpy", SMALL_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT); if (small_buf_write == NULL) goto error_small_buf_write; for (i = 0; i < LARGE_BUFFER_SIZE; i++) large_buf_read[i] = rte_rand(); for (i = 0; i < SMALL_BUFFER_SIZE; i++) small_buf_read[i] = rte_rand(); return 0; error_small_buf_write: rte_free(small_buf_read); error_small_buf_read: rte_free(large_buf_write); error_large_buf_write: rte_free(large_buf_read); error_large_buf_read: printf("ERROR: not enough memory\n"); return -1; } /* Cleanup data buffers */ static void free_buffers(void) { rte_free(large_buf_read); rte_free(large_buf_write); rte_free(small_buf_read); rte_free(small_buf_write); } /* * Get a random offset into large array, with enough space needed to perform * max copy size. Offset is aligned, uoffset is used for unalignment setting. */ static inline size_t get_rand_offset(size_t uoffset) { return (((rte_rand() % (LARGE_BUFFER_SIZE - SMALL_BUFFER_SIZE)) & ~(ALIGNMENT_UNIT - 1)) + uoffset); } /* Fill in source and destination addresses. */ static inline void fill_addr_arrays(size_t *dst_addr, int is_dst_cached, size_t dst_uoffset, size_t *src_addr, int is_src_cached, size_t src_uoffset) { unsigned int i; for (i = 0; i < TEST_BATCH_SIZE; i++) { dst_addr[i] = (is_dst_cached) ? dst_uoffset : get_rand_offset(dst_uoffset); src_addr[i] = (is_src_cached) ? src_uoffset : get_rand_offset(src_uoffset); } } /* * WORKAROUND: For some reason the first test doing an uncached write * takes a very long time (~25 times longer than is expected). So we do * it once without timing. */ static void do_uncached_write(uint8_t *dst, int is_dst_cached, const uint8_t *src, int is_src_cached, size_t size) { unsigned i, j; size_t dst_addrs[TEST_BATCH_SIZE], src_addrs[TEST_BATCH_SIZE]; for (i = 0; i < (TEST_ITERATIONS / TEST_BATCH_SIZE); i++) { fill_addr_arrays(dst_addrs, is_dst_cached, 0, src_addrs, is_src_cached, 0); for (j = 0; j < TEST_BATCH_SIZE; j++) { rte_memcpy(dst+dst_addrs[j], src+src_addrs[j], size); } } } /* * Run a single memcpy performance test. This is a macro to ensure that if * the "size" parameter is a constant it won't be converted to a variable. */ #define SINGLE_PERF_TEST(dst, is_dst_cached, dst_uoffset, \ src, is_src_cached, src_uoffset, size) \ do { \ unsigned int iter, t; \ size_t dst_addrs[TEST_BATCH_SIZE], src_addrs[TEST_BATCH_SIZE]; \ uint64_t start_time, total_time = 0; \ uint64_t total_time2 = 0; \ for (iter = 0; iter < (TEST_ITERATIONS / TEST_BATCH_SIZE); iter++) { \ fill_addr_arrays(dst_addrs, is_dst_cached, dst_uoffset, \ src_addrs, is_src_cached, src_uoffset); \ start_time = rte_rdtsc(); \ for (t = 0; t < TEST_BATCH_SIZE; t++) \ rte_memcpy(dst+dst_addrs[t], src+src_addrs[t], size); \ total_time += rte_rdtsc() - start_time; \ } \ for (iter = 0; iter < (TEST_ITERATIONS / TEST_BATCH_SIZE); iter++) { \ fill_addr_arrays(dst_addrs, is_dst_cached, dst_uoffset, \ src_addrs, is_src_cached, src_uoffset); \ start_time = rte_rdtsc(); \ for (t = 0; t < TEST_BATCH_SIZE; t++) \ memcpy(dst+dst_addrs[t], src+src_addrs[t], size); \ total_time2 += rte_rdtsc() - start_time; \ } \ printf("%8.0f -", (double)total_time /TEST_ITERATIONS); \ printf("%5.0f", (double)total_time2 / TEST_ITERATIONS); \ } while (0) /* Run aligned memcpy tests for each cached/uncached permutation */ #define ALL_PERF_TESTS_FOR_SIZE(n) \ do { \ if (__builtin_constant_p(n)) \ printf("\nC%6u", (unsigned)n); \ else \ printf("\n%7u", (unsigned)n); \ SINGLE_PERF_TEST(small_buf_write, 1, 0, small_buf_read, 1, 0, n); \ SINGLE_PERF_TEST(large_buf_write, 0, 0, small_buf_read, 1, 0, n); \ SINGLE_PERF_TEST(small_buf_write, 1, 0, large_buf_read, 0, 0, n); \ SINGLE_PERF_TEST(large_buf_write, 0, 0, large_buf_read, 0, 0, n); \ } while (0) /* Run unaligned memcpy tests for each cached/uncached permutation */ #define ALL_PERF_TESTS_FOR_SIZE_UNALIGNED(n) \ do { \ if (__builtin_constant_p(n)) \ printf("\nC%6u", (unsigned)n); \ else \ printf("\n%7u", (unsigned)n); \ SINGLE_PERF_TEST(small_buf_write, 1, 1, small_buf_read, 1, 5, n); \ SINGLE_PERF_TEST(large_buf_write, 0, 1, small_buf_read, 1, 5, n); \ SINGLE_PERF_TEST(small_buf_write, 1, 1, large_buf_read, 0, 5, n); \ SINGLE_PERF_TEST(large_buf_write, 0, 1, large_buf_read, 0, 5, n); \ } while (0) /* Run memcpy tests for constant length */ #define ALL_PERF_TEST_FOR_CONSTANT \ do { \ TEST_CONSTANT(6U); TEST_CONSTANT(64U); TEST_CONSTANT(128U); \ TEST_CONSTANT(192U); TEST_CONSTANT(256U); TEST_CONSTANT(512U); \ TEST_CONSTANT(768U); TEST_CONSTANT(1024U); TEST_CONSTANT(1536U); \ } while (0) /* Run all memcpy tests for aligned constant cases */ static inline void perf_test_constant_aligned(void) { #define TEST_CONSTANT ALL_PERF_TESTS_FOR_SIZE ALL_PERF_TEST_FOR_CONSTANT; #undef TEST_CONSTANT } /* Run all memcpy tests for unaligned constant cases */ static inline void perf_test_constant_unaligned(void) { #define TEST_CONSTANT ALL_PERF_TESTS_FOR_SIZE_UNALIGNED ALL_PERF_TEST_FOR_CONSTANT; #undef TEST_CONSTANT } /* Run all memcpy tests for aligned variable cases */ static inline void perf_test_variable_aligned(void) { unsigned n = sizeof(buf_sizes) / sizeof(buf_sizes[0]); unsigned i; for (i = 0; i < n; i++) { ALL_PERF_TESTS_FOR_SIZE((size_t)buf_sizes[i]); } } /* Run all memcpy tests for unaligned variable cases */ static inline void perf_test_variable_unaligned(void) { unsigned n = sizeof(buf_sizes) / sizeof(buf_sizes[0]); unsigned i; for (i = 0; i < n; i++) { ALL_PERF_TESTS_FOR_SIZE_UNALIGNED((size_t)buf_sizes[i]); } } /* Run all memcpy tests */ static int perf_test(void) { int ret; ret = init_buffers(); if (ret != 0) return ret; #if TEST_VALUE_RANGE != 0 /* Set up buf_sizes array, if required */ unsigned i; for (i = 0; i < TEST_VALUE_RANGE; i++) buf_sizes[i] = i; #endif /* See function comment */ do_uncached_write(large_buf_write, 0, small_buf_read, 1, SMALL_BUFFER_SIZE); printf("\n** rte_memcpy() - memcpy perf. tests (C = compile-time constant) **\n" "======= ============== ============== ============== ==============\n" " Size Cache to cache Cache to mem Mem to cache Mem to mem\n" "(bytes) (ticks) (ticks) (ticks) (ticks)\n" "------- -------------- -------------- -------------- --------------"); printf("\n========================== %2dB aligned ============================", ALIGNMENT_UNIT); /* Do aligned tests where size is a variable */ perf_test_variable_aligned(); printf("\n------- -------------- -------------- -------------- --------------"); /* Do aligned tests where size is a compile-time constant */ perf_test_constant_aligned(); printf("\n=========================== Unaligned ============================="); /* Do unaligned tests where size is a variable */ perf_test_variable_unaligned(); printf("\n------- -------------- -------------- -------------- --------------"); /* Do unaligned tests where size is a compile-time constant */ perf_test_constant_unaligned(); printf("\n======= ============== ============== ============== ==============\n\n"); free_buffers(); return 0; } static int test_memcpy_perf(void) { int ret; ret = perf_test(); if (ret != 0) return -1; return 0; } static struct test_command memcpy_perf_cmd = { .command = "memcpy_perf_autotest", .callback = test_memcpy_perf, }; REGISTER_TEST_COMMAND(memcpy_perf_cmd); ================================================ FILE: app/test/test_memory.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "test.h" /* * Memory * ====== * * - Dump the mapped memory. The python-expect script checks that at * least one line is dumped. * * - Check that memory size is different than 0. * * - Try to read all memory; it should not segfault. */ static int test_memory(void) { uint64_t s; unsigned i, j; const struct rte_memseg *mem; /* * dump the mapped memory: the python-expect script checks * that at least one line is dumped */ printf("Dump memory layout\n"); rte_dump_physmem_layout(stdout); /* check that memory size is != 0 */ s = rte_eal_get_physmem_size(); if (s == 0) { printf("No memory detected\n"); return -1; } /* try to read memory (should not segfault) */ mem = rte_eal_get_physmem_layout(); for (i = 0; i < RTE_MAX_MEMSEG && mem[i].addr != NULL ; i++) { /* check memory */ for (j = 0; j #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Mempool * ======= * * Basic tests: done on one core with and without cache: * * - Get one object, put one object * - Get two objects, put two objects * - Get all objects, test that their content is not modified and * put them back in the pool. */ #define N 65536 #define TIME_S 5 #define MEMPOOL_ELT_SIZE 2048 #define MAX_KEEP 128 #define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE))-1) static struct rte_mempool *mp; static struct rte_mempool *mp_cache, *mp_nocache; static rte_atomic32_t synchro; /* * save the object number in the first 4 bytes of object data. All * other bytes are set to 0. */ static void my_obj_init(struct rte_mempool *mp, __attribute__((unused)) void *arg, void *obj, unsigned i) { uint32_t *objnum = obj; memset(obj, 0, mp->elt_size); *objnum = i; } /* basic tests (done on one core) */ static int test_mempool_basic(void) { uint32_t *objnum; void **objtable; void *obj, *obj2; char *obj_data; int ret = 0; unsigned i, j; /* dump the mempool status */ rte_mempool_dump(stdout, mp); printf("get an object\n"); if (rte_mempool_get(mp, &obj) < 0) return -1; rte_mempool_dump(stdout, mp); /* tests that improve coverage */ printf("get object count\n"); if (rte_mempool_count(mp) != MEMPOOL_SIZE - 1) return -1; printf("get private data\n"); if (rte_mempool_get_priv(mp) != (char*) mp + MEMPOOL_HEADER_SIZE(mp, mp->pg_num)) return -1; printf("get physical address of an object\n"); if (MEMPOOL_IS_CONTIG(mp) && rte_mempool_virt2phy(mp, obj) != (phys_addr_t) (mp->phys_addr + (phys_addr_t) ((char*) obj - (char*) mp))) return -1; printf("put the object back\n"); rte_mempool_put(mp, obj); rte_mempool_dump(stdout, mp); printf("get 2 objects\n"); if (rte_mempool_get(mp, &obj) < 0) return -1; if (rte_mempool_get(mp, &obj2) < 0) { rte_mempool_put(mp, obj); return -1; } rte_mempool_dump(stdout, mp); printf("put the objects back\n"); rte_mempool_put(mp, obj); rte_mempool_put(mp, obj2); rte_mempool_dump(stdout, mp); /* * get many objects: we cannot get them all because the cache * on other cores may not be empty. */ objtable = malloc(MEMPOOL_SIZE * sizeof(void *)); if (objtable == NULL) { return -1; } for (i=0; i MEMPOOL_SIZE) { printf("bad object number\n"); ret = -1; break; } for (j=sizeof(*objnum); jelt_size; j++) { if (obj_data[j] != 0) ret = -1; } rte_mempool_put(mp, objtable[i]); } free(objtable); if (ret == -1) printf("objects were modified!\n"); return ret; } static int test_mempool_creation_with_exceeded_cache_size(void) { struct rte_mempool *mp_cov; mp_cov = rte_mempool_create("test_mempool_creation_with_exceeded_cache_size", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, RTE_MEMPOOL_CACHE_MAX_SIZE + 32, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if(NULL != mp_cov) { return -1; } return 0; } static struct rte_mempool *mp_spsc; static rte_spinlock_t scsp_spinlock; static void *scsp_obj_table[MAX_KEEP]; /* * single producer function */ static int test_mempool_single_producer(void) { unsigned int i; void *obj = NULL; uint64_t start_cycles, end_cycles; uint64_t duration = rte_get_timer_hz() * 8; start_cycles = rte_get_timer_cycles(); while (1) { end_cycles = rte_get_timer_cycles(); /* duration uses up, stop producing */ if (start_cycles + duration < end_cycles) break; rte_spinlock_lock(&scsp_spinlock); for (i = 0; i < MAX_KEEP; i ++) { if (NULL != scsp_obj_table[i]) { obj = scsp_obj_table[i]; break; } } rte_spinlock_unlock(&scsp_spinlock); if (i >= MAX_KEEP) { continue; } if (rte_mempool_from_obj(obj) != mp_spsc) { printf("test_mempool_single_producer there is an obj not owned by this mempool\n"); return -1; } rte_mempool_sp_put(mp_spsc, obj); rte_spinlock_lock(&scsp_spinlock); scsp_obj_table[i] = NULL; rte_spinlock_unlock(&scsp_spinlock); } return 0; } /* * single consumer function */ static int test_mempool_single_consumer(void) { unsigned int i; void * obj; uint64_t start_cycles, end_cycles; uint64_t duration = rte_get_timer_hz() * 5; start_cycles = rte_get_timer_cycles(); while (1) { end_cycles = rte_get_timer_cycles(); /* duration uses up, stop consuming */ if (start_cycles + duration < end_cycles) break; rte_spinlock_lock(&scsp_spinlock); for (i = 0; i < MAX_KEEP; i ++) { if (NULL == scsp_obj_table[i]) break; } rte_spinlock_unlock(&scsp_spinlock); if (i >= MAX_KEEP) continue; if (rte_mempool_sc_get(mp_spsc, &obj) < 0) break; rte_spinlock_lock(&scsp_spinlock); scsp_obj_table[i] = obj; rte_spinlock_unlock(&scsp_spinlock); } return 0; } /* * test function for mempool test based on singple consumer and single producer, can run on one lcore only */ static int test_mempool_launch_single_consumer(__attribute__((unused)) void *arg) { return test_mempool_single_consumer(); } static void my_mp_init(struct rte_mempool * mp, __attribute__((unused)) void * arg) { printf("mempool name is %s\n", mp->name); /* nothing to be implemented here*/ return ; } /* * it tests the mempool operations based on singple producer and single consumer */ static int test_mempool_sp_sc(void) { int ret = 0; unsigned lcore_id = rte_lcore_id(); unsigned lcore_next; /* create a mempool with single producer/consumer ring */ if (NULL == mp_spsc) { mp_spsc = rte_mempool_create("test_mempool_sp_sc", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, my_mp_init, NULL, my_obj_init, NULL, SOCKET_ID_ANY, MEMPOOL_F_NO_CACHE_ALIGN | MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET); if (NULL == mp_spsc) { return -1; } } if (rte_mempool_lookup("test_mempool_sp_sc") != mp_spsc) { printf("Cannot lookup mempool from its name\n"); return -1; } lcore_next = rte_get_next_lcore(lcore_id, 0, 1); if (RTE_MAX_LCORE <= lcore_next) return -1; if (rte_eal_lcore_role(lcore_next) != ROLE_RTE) return -1; rte_spinlock_init(&scsp_spinlock); memset(scsp_obj_table, 0, sizeof(scsp_obj_table)); rte_eal_remote_launch(test_mempool_launch_single_consumer, NULL, lcore_next); if(test_mempool_single_producer() < 0) ret = -1; if(rte_eal_wait_lcore(lcore_next) < 0) ret = -1; return ret; } /* * it tests some more basic of mempool */ static int test_mempool_basic_ex(struct rte_mempool * mp) { unsigned i; void **obj; void *err_obj; int ret = -1; if (mp == NULL) return ret; obj = rte_calloc("test_mempool_basic_ex", MEMPOOL_SIZE , sizeof(void *), 0); if (obj == NULL) { printf("test_mempool_basic_ex fail to rte_malloc\n"); return ret; } printf("test_mempool_basic_ex now mempool (%s) has %u free entries\n", mp->name, rte_mempool_free_count(mp)); if (rte_mempool_full(mp) != 1) { printf("test_mempool_basic_ex the mempool is not full but it should be\n"); goto fail_mp_basic_ex; } for (i = 0; i < MEMPOOL_SIZE; i ++) { if (rte_mempool_mc_get(mp, &obj[i]) < 0) { printf("fail_mp_basic_ex fail to get mempool object for [%u]\n", i); goto fail_mp_basic_ex; } } if (rte_mempool_mc_get(mp, &err_obj) == 0) { printf("test_mempool_basic_ex get an impossible obj from mempool\n"); goto fail_mp_basic_ex; } printf("number: %u\n", i); if (rte_mempool_empty(mp) != 1) { printf("test_mempool_basic_ex the mempool is not empty but it should be\n"); goto fail_mp_basic_ex; } for (i = 0; i < MEMPOOL_SIZE; i ++) { rte_mempool_mp_put(mp, obj[i]); } if (rte_mempool_full(mp) != 1) { printf("test_mempool_basic_ex the mempool is not full but it should be\n"); goto fail_mp_basic_ex; } ret = 0; fail_mp_basic_ex: if (obj != NULL) rte_free((void *)obj); return ret; } static int test_mempool_same_name_twice_creation(void) { struct rte_mempool *mp_tc; mp_tc = rte_mempool_create("test_mempool_same_name_twice_creation", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); if (NULL == mp_tc) return -1; mp_tc = rte_mempool_create("test_mempool_same_name_twice_creation", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); if (NULL != mp_tc) return -1; return 0; } /* * BAsic test for mempool_xmem functions. */ static int test_mempool_xmem_misc(void) { uint32_t elt_num, total_size; size_t sz; ssize_t usz; elt_num = MAX_KEEP; total_size = rte_mempool_calc_obj_size(MEMPOOL_ELT_SIZE, 0, NULL); sz = rte_mempool_xmem_size(elt_num, total_size, MEMPOOL_PG_SHIFT_MAX); usz = rte_mempool_xmem_usage(NULL, elt_num, total_size, 0, 1, MEMPOOL_PG_SHIFT_MAX); if(sz != (size_t)usz) { printf("failure @ %s: rte_mempool_xmem_usage(%u, %u) " "returns: %#zx, while expected: %#zx;\n", __func__, elt_num, total_size, sz, (size_t)usz); return (-1); } return (0); } static int test_mempool(void) { rte_atomic32_init(&synchro); /* create a mempool (without cache) */ if (mp_nocache == NULL) mp_nocache = rte_mempool_create("test_nocache", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if (mp_nocache == NULL) return -1; /* create a mempool (with cache) */ if (mp_cache == NULL) mp_cache = rte_mempool_create("test_cache", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, RTE_MEMPOOL_CACHE_MAX_SIZE, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if (mp_cache == NULL) return -1; /* retrieve the mempool from its name */ if (rte_mempool_lookup("test_nocache") != mp_nocache) { printf("Cannot lookup mempool from its name\n"); return -1; } rte_mempool_list_dump(stdout); /* basic tests without cache */ mp = mp_nocache; if (test_mempool_basic() < 0) return -1; /* basic tests with cache */ mp = mp_cache; if (test_mempool_basic() < 0) return -1; /* more basic tests without cache */ if (test_mempool_basic_ex(mp_nocache) < 0) return -1; /* mempool operation test based on single producer and single comsumer */ if (test_mempool_sp_sc() < 0) return -1; if (test_mempool_creation_with_exceeded_cache_size() < 0) return -1; if (test_mempool_same_name_twice_creation() < 0) return -1; if (test_mempool_xmem_misc() < 0) return -1; rte_mempool_list_dump(stdout); return 0; } static struct test_command mempool_cmd = { .command = "mempool_autotest", .callback = test_mempool, }; REGISTER_TEST_COMMAND(mempool_cmd); ================================================ FILE: app/test/test_mempool_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Mempool performance * ======= * * Each core get *n_keep* objects per bulk of *n_get_bulk*. Then, * objects are put back in the pool per bulk of *n_put_bulk*. * * This sequence is done during TIME_S seconds. * * This test is done on the following configurations: * * - Cores configuration (*cores*) * * - One core with cache * - Two cores with cache * - Max. cores with cache * - One core without cache * - Two cores without cache * - Max. cores without cache * * - Bulk size (*n_get_bulk*, *n_put_bulk*) * * - Bulk get from 1 to 32 * - Bulk put from 1 to 32 * * - Number of kept objects (*n_keep*) * * - 32 * - 128 */ #define N 65536 #define TIME_S 5 #define MEMPOOL_ELT_SIZE 2048 #define MAX_KEEP 128 #define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE))-1) static struct rte_mempool *mp; static struct rte_mempool *mp_cache, *mp_nocache; static rte_atomic32_t synchro; /* number of objects in one bulk operation (get or put) */ static unsigned n_get_bulk; static unsigned n_put_bulk; /* number of objects retrived from mempool before putting them back */ static unsigned n_keep; /* number of enqueues / dequeues */ struct mempool_test_stats { unsigned enq_count; } __rte_cache_aligned; static struct mempool_test_stats stats[RTE_MAX_LCORE]; /* * save the object number in the first 4 bytes of object data. All * other bytes are set to 0. */ static void my_obj_init(struct rte_mempool *mp, __attribute__((unused)) void *arg, void *obj, unsigned i) { uint32_t *objnum = obj; memset(obj, 0, mp->elt_size); *objnum = i; } static int per_lcore_mempool_test(__attribute__((unused)) void *arg) { void *obj_table[MAX_KEEP]; unsigned i, idx; unsigned lcore_id = rte_lcore_id(); int ret; uint64_t start_cycles, end_cycles; uint64_t time_diff = 0, hz = rte_get_timer_hz(); /* n_get_bulk and n_put_bulk must be divisors of n_keep */ if (((n_keep / n_get_bulk) * n_get_bulk) != n_keep) return -1; if (((n_keep / n_put_bulk) * n_put_bulk) != n_keep) return -1; stats[lcore_id].enq_count = 0; /* wait synchro for slaves */ if (lcore_id != rte_get_master_lcore()) while (rte_atomic32_read(&synchro) == 0); start_cycles = rte_get_timer_cycles(); while (time_diff/hz < TIME_S) { for (i = 0; likely(i < (N/n_keep)); i++) { /* get n_keep objects by bulk of n_bulk */ idx = 0; while (idx < n_keep) { ret = rte_mempool_get_bulk(mp, &obj_table[idx], n_get_bulk); if (unlikely(ret < 0)) { rte_mempool_dump(stdout, mp); rte_ring_dump(stdout, mp->ring); /* in this case, objects are lost... */ return -1; } idx += n_get_bulk; } /* put the objects back */ idx = 0; while (idx < n_keep) { rte_mempool_put_bulk(mp, &obj_table[idx], n_put_bulk); idx += n_put_bulk; } } end_cycles = rte_get_timer_cycles(); time_diff = end_cycles - start_cycles; stats[lcore_id].enq_count += N; } return 0; } /* launch all the per-lcore test, and display the result */ static int launch_cores(unsigned cores) { unsigned lcore_id; unsigned rate; int ret; unsigned cores_save = cores; rte_atomic32_set(&synchro, 0); /* reset stats */ memset(stats, 0, sizeof(stats)); printf("mempool_autotest cache=%u cores=%u n_get_bulk=%u " "n_put_bulk=%u n_keep=%u ", (unsigned) mp->cache_size, cores, n_get_bulk, n_put_bulk, n_keep); if (rte_mempool_count(mp) != MEMPOOL_SIZE) { printf("mempool is not full\n"); return -1; } RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (cores == 1) break; cores--; rte_eal_remote_launch(per_lcore_mempool_test, NULL, lcore_id); } /* start synchro and launch test on master */ rte_atomic32_set(&synchro, 1); ret = per_lcore_mempool_test(NULL); cores = cores_save; RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (cores == 1) break; cores--; if (rte_eal_wait_lcore(lcore_id) < 0) ret = -1; } if (ret < 0) { printf("per-lcore test returned -1\n"); return -1; } rate = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) rate += (stats[lcore_id].enq_count / TIME_S); printf("rate_persec=%u\n", rate); return 0; } /* for a given number of core, launch all test cases */ static int do_one_mempool_test(unsigned cores) { unsigned bulk_tab_get[] = { 1, 4, 32, 0 }; unsigned bulk_tab_put[] = { 1, 4, 32, 0 }; unsigned keep_tab[] = { 32, 128, 0 }; unsigned *get_bulk_ptr; unsigned *put_bulk_ptr; unsigned *keep_ptr; int ret; for (get_bulk_ptr = bulk_tab_get; *get_bulk_ptr; get_bulk_ptr++) { for (put_bulk_ptr = bulk_tab_put; *put_bulk_ptr; put_bulk_ptr++) { for (keep_ptr = keep_tab; *keep_ptr; keep_ptr++) { n_get_bulk = *get_bulk_ptr; n_put_bulk = *put_bulk_ptr; n_keep = *keep_ptr; ret = launch_cores(cores); if (ret < 0) return -1; } } } return 0; } static int test_mempool_perf(void) { rte_atomic32_init(&synchro); /* create a mempool (without cache) */ if (mp_nocache == NULL) mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, 0, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if (mp_nocache == NULL) return -1; /* create a mempool (with cache) */ if (mp_cache == NULL) mp_cache = rte_mempool_create("perf_test_cache", MEMPOOL_SIZE, MEMPOOL_ELT_SIZE, RTE_MEMPOOL_CACHE_MAX_SIZE, 0, NULL, NULL, my_obj_init, NULL, SOCKET_ID_ANY, 0); if (mp_cache == NULL) return -1; /* performance test with 1, 2 and max cores */ printf("start performance test (without cache)\n"); mp = mp_nocache; if (do_one_mempool_test(1) < 0) return -1; if (do_one_mempool_test(2) < 0) return -1; if (do_one_mempool_test(rte_lcore_count()) < 0) return -1; /* performance test with 1, 2 and max cores */ printf("start performance test (with cache)\n"); mp = mp_cache; if (do_one_mempool_test(1) < 0) return -1; if (do_one_mempool_test(2) < 0) return -1; if (do_one_mempool_test(rte_lcore_count()) < 0) return -1; rte_mempool_list_dump(stdout); return 0; } static struct test_command mempool_perf_cmd = { .command = "mempool_perf_autotest", .callback = test_mempool_perf, }; REGISTER_TEST_COMMAND(mempool_perf_cmd); ================================================ FILE: app/test/test_memzone.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../lib/librte_eal/common/malloc_elem.h" #include "test.h" /* * Memzone * ======= * * - Search for three reserved zones or reserve them if they do not exist: * * - One is on any socket id. * - The second is on socket 0. * - The last one is on socket 1 (if socket 1 exists). * * - Check that the zones exist. * * - Check that the zones are cache-aligned. * * - Check that zones do not overlap. * * - Check that the zones are on the correct socket id. * * - Check that a lookup of the first zone returns the same pointer. * * - Check that it is not possible to create another zone with the * same name as an existing zone. * * - Check flags for specific huge page size reservation */ /* Test if memory overlaps: return 1 if true, or 0 if false. */ static int is_memory_overlap(phys_addr_t ptr1, size_t len1, phys_addr_t ptr2, size_t len2) { if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1) return 1; else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2) return 1; return 0; } static int test_memzone_invalid_alignment(void) { const struct rte_memzone * mz; mz = rte_memzone_lookup("invalid_alignment"); if (mz != NULL) { printf("Zone with invalid alignment has been reserved\n"); return -1; } mz = rte_memzone_reserve_aligned("invalid_alignment", 100, SOCKET_ID_ANY, 0, 100); if (mz != NULL) { printf("Zone with invalid alignment has been reserved\n"); return -1; } return 0; } static int test_memzone_reserving_zone_size_bigger_than_the_maximum(void) { const struct rte_memzone * mz; mz = rte_memzone_lookup("zone_size_bigger_than_the_maximum"); if (mz != NULL) { printf("zone_size_bigger_than_the_maximum has been reserved\n"); return -1; } mz = rte_memzone_reserve("zone_size_bigger_than_the_maximum", (size_t)-1, SOCKET_ID_ANY, 0); if (mz != NULL) { printf("It is impossible to reserve such big a memzone\n"); return -1; } return 0; } static int test_memzone_reserve_flags(void) { const struct rte_memzone *mz; const struct rte_memseg *ms; int hugepage_2MB_avail = 0; int hugepage_1GB_avail = 0; int hugepage_16MB_avail = 0; int hugepage_16GB_avail = 0; const size_t size = 100; int i = 0; ms = rte_eal_get_physmem_layout(); for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (ms[i].hugepage_sz == RTE_PGSIZE_2M) hugepage_2MB_avail = 1; if (ms[i].hugepage_sz == RTE_PGSIZE_1G) hugepage_1GB_avail = 1; if (ms[i].hugepage_sz == RTE_PGSIZE_16M) hugepage_16MB_avail = 1; if (ms[i].hugepage_sz == RTE_PGSIZE_16G) hugepage_16GB_avail = 1; } /* Display the availability of 2MB ,1GB, 16MB, 16GB pages */ if (hugepage_2MB_avail) printf("2MB Huge pages available\n"); if (hugepage_1GB_avail) printf("1GB Huge pages available\n"); if (hugepage_16MB_avail) printf("16MB Huge pages available\n"); if (hugepage_16GB_avail) printf("16GB Huge pages available\n"); /* * If 2MB pages available, check that a small memzone is correctly * reserved from 2MB huge pages when requested by the RTE_MEMZONE_2MB flag. * Also check that RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an * available page size (i.e 1GB ) when 2MB pages are unavailable. */ if (hugepage_2MB_avail) { mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, RTE_MEMZONE_2MB); if (mz == NULL) { printf("MEMZONE FLAG 2MB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_2M) { printf("hugepage_sz not equal 2M\n"); return -1; } mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 2MB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_2M) { printf("hugepage_sz not equal 2M\n"); return -1; } /* Check if 1GB huge pages are unavailable, that function fails unless * HINT flag is indicated */ if (!hugepage_1GB_avail) { mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 1GB & HINT\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_2M) { printf("hugepage_sz not equal 2M\n"); return -1; } mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, RTE_MEMZONE_1GB); if (mz != NULL) { printf("MEMZONE FLAG 1GB\n"); return -1; } } } /*As with 2MB tests above for 1GB huge page requests*/ if (hugepage_1GB_avail) { mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, RTE_MEMZONE_1GB); if (mz == NULL) { printf("MEMZONE FLAG 1GB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_1G) { printf("hugepage_sz not equal 1G\n"); return -1; } mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 1GB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_1G) { printf("hugepage_sz not equal 1G\n"); return -1; } /* Check if 1GB huge pages are unavailable, that function fails unless * HINT flag is indicated */ if (!hugepage_2MB_avail) { mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL){ printf("MEMZONE FLAG 2MB & HINT\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_1G) { printf("hugepage_sz not equal 1G\n"); return -1; } mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, RTE_MEMZONE_2MB); if (mz != NULL) { printf("MEMZONE FLAG 2MB\n"); return -1; } } if (hugepage_2MB_avail && hugepage_1GB_avail) { mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_2MB|RTE_MEMZONE_1GB); if (mz != NULL) { printf("BOTH SIZES SET\n"); return -1; } } } /* * This option is for IBM Power. If 16MB pages available, check * that a small memzone is correctly reserved from 16MB huge pages * when requested by the RTE_MEMZONE_16MB flag. Also check that * RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an available * page size (i.e 16GB ) when 16MB pages are unavailable. */ if (hugepage_16MB_avail) { mz = rte_memzone_reserve("flag_zone_16M", size, SOCKET_ID_ANY, RTE_MEMZONE_16MB); if (mz == NULL) { printf("MEMZONE FLAG 16MB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16M) { printf("hugepage_sz not equal 16M\n"); return -1; } mz = rte_memzone_reserve("flag_zone_16M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 2MB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16M) { printf("hugepage_sz not equal 16M\n"); return -1; } /* Check if 1GB huge pages are unavailable, that function fails * unless HINT flag is indicated */ if (!hugepage_16GB_avail) { mz = rte_memzone_reserve("flag_zone_16G_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 16GB & HINT\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16M) { printf("hugepage_sz not equal 16M\n"); return -1; } mz = rte_memzone_reserve("flag_zone_16G", size, SOCKET_ID_ANY, RTE_MEMZONE_16GB); if (mz != NULL) { printf("MEMZONE FLAG 16GB\n"); return -1; } } } /*As with 16MB tests above for 16GB huge page requests*/ if (hugepage_16GB_avail) { mz = rte_memzone_reserve("flag_zone_16G", size, SOCKET_ID_ANY, RTE_MEMZONE_16GB); if (mz == NULL) { printf("MEMZONE FLAG 16GB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16G) { printf("hugepage_sz not equal 16G\n"); return -1; } mz = rte_memzone_reserve("flag_zone_16G_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 16GB\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16G) { printf("hugepage_sz not equal 16G\n"); return -1; } /* Check if 1GB huge pages are unavailable, that function fails * unless HINT flag is indicated */ if (!hugepage_16MB_avail) { mz = rte_memzone_reserve("flag_zone_16M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); if (mz == NULL) { printf("MEMZONE FLAG 16MB & HINT\n"); return -1; } if (mz->hugepage_sz != RTE_PGSIZE_16G) { printf("hugepage_sz not equal 16G\n"); return -1; } mz = rte_memzone_reserve("flag_zone_16M", size, SOCKET_ID_ANY, RTE_MEMZONE_16MB); if (mz != NULL) { printf("MEMZONE FLAG 16MB\n"); return -1; } } if (hugepage_16MB_avail && hugepage_16GB_avail) { mz = rte_memzone_reserve("flag_zone_16M_HINT", size, SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_16GB); if (mz != NULL) { printf("BOTH SIZES SET\n"); return -1; } } } return 0; } /* Find the heap with the greatest free block size */ static size_t find_max_block_free_size(const unsigned _align) { struct rte_malloc_socket_stats stats; unsigned i, align = _align; size_t len = 0; for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { rte_malloc_get_socket_stats(i, &stats); if (stats.greatest_free_size > len) len = stats.greatest_free_size; } if (align < RTE_CACHE_LINE_SIZE) align = RTE_CACHE_LINE_ROUNDUP(align+1); if (len <= MALLOC_ELEM_OVERHEAD + align) return 0; return len - MALLOC_ELEM_OVERHEAD - align; } static int test_memzone_reserve_max(void) { const struct rte_memzone *mz; size_t maxlen; maxlen = find_max_block_free_size(0); if (maxlen == 0) { printf("There is no space left!\n"); return 0; } mz = rte_memzone_reserve("max_zone", 0, SOCKET_ID_ANY, 0); if (mz == NULL){ printf("Failed to reserve a big chunk of memory - %s\n", rte_strerror(rte_errno)); rte_dump_physmem_layout(stdout); rte_memzone_dump(stdout); return -1; } if (mz->len != maxlen) { printf("Memzone reserve with 0 size did not return bigest block\n"); printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len); rte_dump_physmem_layout(stdout); rte_memzone_dump(stdout); return -1; } return 0; } static int test_memzone_reserve_max_aligned(void) { const struct rte_memzone *mz; size_t maxlen = 0; /* random alignment */ rte_srand((unsigned)rte_rdtsc()); const unsigned align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */ maxlen = find_max_block_free_size(align); if (maxlen == 0) { printf("There is no space left for biggest %u-aligned memzone!\n", align); return 0; } mz = rte_memzone_reserve_aligned("max_zone_aligned", 0, SOCKET_ID_ANY, 0, align); if (mz == NULL){ printf("Failed to reserve a big chunk of memory - %s\n", rte_strerror(rte_errno)); rte_dump_physmem_layout(stdout); rte_memzone_dump(stdout); return -1; } if (mz->len != maxlen) { printf("Memzone reserve with 0 size and alignment %u did not return" " bigest block\n", align); printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len); rte_dump_physmem_layout(stdout); rte_memzone_dump(stdout); return -1; } return 0; } static int test_memzone_aligned(void) { const struct rte_memzone *memzone_aligned_32; const struct rte_memzone *memzone_aligned_128; const struct rte_memzone *memzone_aligned_256; const struct rte_memzone *memzone_aligned_512; const struct rte_memzone *memzone_aligned_1024; /* memzone that should automatically be adjusted to align on 64 bytes */ memzone_aligned_32 = rte_memzone_reserve_aligned("aligned_32", 100, SOCKET_ID_ANY, 0, 32); /* memzone that is supposed to be aligned on a 128 byte boundary */ memzone_aligned_128 = rte_memzone_reserve_aligned("aligned_128", 100, SOCKET_ID_ANY, 0, 128); /* memzone that is supposed to be aligned on a 256 byte boundary */ memzone_aligned_256 = rte_memzone_reserve_aligned("aligned_256", 100, SOCKET_ID_ANY, 0, 256); /* memzone that is supposed to be aligned on a 512 byte boundary */ memzone_aligned_512 = rte_memzone_reserve_aligned("aligned_512", 100, SOCKET_ID_ANY, 0, 512); /* memzone that is supposed to be aligned on a 1024 byte boundary */ memzone_aligned_1024 = rte_memzone_reserve_aligned("aligned_1024", 100, SOCKET_ID_ANY, 0, 1024); printf("check alignments and lengths\n"); if (memzone_aligned_32 == NULL) { printf("Unable to reserve 64-byte aligned memzone!\n"); return -1; } if ((memzone_aligned_32->phys_addr & RTE_CACHE_LINE_MASK) != 0) return -1; if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0) return -1; if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0) return -1; if (memzone_aligned_128 == NULL) { printf("Unable to reserve 128-byte aligned memzone!\n"); return -1; } if ((memzone_aligned_128->phys_addr & 127) != 0) return -1; if (((uintptr_t) memzone_aligned_128->addr & 127) != 0) return -1; if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0) return -1; if (memzone_aligned_256 == NULL) { printf("Unable to reserve 256-byte aligned memzone!\n"); return -1; } if ((memzone_aligned_256->phys_addr & 255) != 0) return -1; if (((uintptr_t) memzone_aligned_256->addr & 255) != 0) return -1; if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0) return -1; if (memzone_aligned_512 == NULL) { printf("Unable to reserve 512-byte aligned memzone!\n"); return -1; } if ((memzone_aligned_512->phys_addr & 511) != 0) return -1; if (((uintptr_t) memzone_aligned_512->addr & 511) != 0) return -1; if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0) return -1; if (memzone_aligned_1024 == NULL) { printf("Unable to reserve 1024-byte aligned memzone!\n"); return -1; } if ((memzone_aligned_1024->phys_addr & 1023) != 0) return -1; if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0) return -1; if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0) return -1; /* check that zones don't overlap */ printf("check overlapping\n"); if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, memzone_aligned_128->phys_addr, memzone_aligned_128->len)) return -1; if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, memzone_aligned_256->phys_addr, memzone_aligned_256->len)) return -1; if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, memzone_aligned_512->phys_addr, memzone_aligned_512->len)) return -1; if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) return -1; if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, memzone_aligned_256->phys_addr, memzone_aligned_256->len)) return -1; if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, memzone_aligned_512->phys_addr, memzone_aligned_512->len)) return -1; if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) return -1; if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, memzone_aligned_512->phys_addr, memzone_aligned_512->len)) return -1; if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) return -1; if (is_memory_overlap(memzone_aligned_512->phys_addr, memzone_aligned_512->len, memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) return -1; return 0; } static int check_memzone_bounded(const char *name, uint32_t len, uint32_t align, uint32_t bound) { const struct rte_memzone *mz; phys_addr_t bmask; bmask = ~((phys_addr_t)bound - 1); if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0, align, bound)) == NULL) { printf("%s(%s): memzone creation failed\n", __func__, name); return (-1); } if ((mz->phys_addr & ((phys_addr_t)align - 1)) != 0) { printf("%s(%s): invalid phys addr alignment\n", __func__, mz->name); return (-1); } if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) { printf("%s(%s): invalid virtual addr alignment\n", __func__, mz->name); return (-1); } if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len || mz->len < RTE_CACHE_LINE_SIZE) { printf("%s(%s): invalid length\n", __func__, mz->name); return (-1); } if ((mz->phys_addr & bmask) != ((mz->phys_addr + mz->len - 1) & bmask)) { printf("%s(%s): invalid memzone boundary %u crossed\n", __func__, mz->name, bound); return (-1); } return (0); } static int test_memzone_bounded(void) { const struct rte_memzone *memzone_err; const char *name; int rc; /* should fail as boundary is not power of two */ name = "bounded_error_31"; if ((memzone_err = rte_memzone_reserve_bounded(name, 100, SOCKET_ID_ANY, 0, 32, UINT32_MAX)) != NULL) { printf("%s(%s)created a memzone with invalid boundary " "conditions\n", __func__, memzone_err->name); return (-1); } /* should fail as len is greater then boundary */ name = "bounded_error_32"; if ((memzone_err = rte_memzone_reserve_bounded(name, 100, SOCKET_ID_ANY, 0, 32, 32)) != NULL) { printf("%s(%s)created a memzone with invalid boundary " "conditions\n", __func__, memzone_err->name); return (-1); } if ((rc = check_memzone_bounded("bounded_128", 100, 128, 128)) != 0) return (rc); if ((rc = check_memzone_bounded("bounded_256", 100, 256, 128)) != 0) return (rc); if ((rc = check_memzone_bounded("bounded_1K", 100, 64, 1024)) != 0) return (rc); if ((rc = check_memzone_bounded("bounded_1K_MAX", 0, 64, 1024)) != 0) return (rc); return 0; } static int test_memzone_free(void) { const struct rte_memzone *mz[RTE_MAX_MEMZONE]; int i; char name[20]; mz[0] = rte_memzone_reserve("tempzone0", 2000, SOCKET_ID_ANY, 0); mz[1] = rte_memzone_reserve("tempzone1", 4000, SOCKET_ID_ANY, 0); if (mz[0] > mz[1]) return -1; if (!rte_memzone_lookup("tempzone0")) return -1; if (!rte_memzone_lookup("tempzone1")) return -1; if (rte_memzone_free(mz[0])) { printf("Fail memzone free - tempzone0\n"); return -1; } if (rte_memzone_lookup("tempzone0")) { printf("Found previously free memzone - tempzone0\n"); return -1; } mz[2] = rte_memzone_reserve("tempzone2", 2000, SOCKET_ID_ANY, 0); if (mz[2] > mz[1]) { printf("tempzone2 should have gotten the free entry from tempzone0\n"); return -1; } if (rte_memzone_free(mz[2])) { printf("Fail memzone free - tempzone2\n"); return -1; } if (rte_memzone_lookup("tempzone2")) { printf("Found previously free memzone - tempzone2\n"); return -1; } if (rte_memzone_free(mz[1])) { printf("Fail memzone free - tempzone1\n"); return -1; } if (rte_memzone_lookup("tempzone1")) { printf("Found previously free memzone - tempzone1\n"); return -1; } i = 0; do { snprintf(name, sizeof(name), "tempzone%u", i); mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0); } while (mz[i++] != NULL); if (rte_memzone_free(mz[0])) { printf("Fail memzone free - tempzone0\n"); return -1; } mz[0] = rte_memzone_reserve("tempzone0new", 0, SOCKET_ID_ANY, 0); if (mz[0] == NULL) { printf("Fail to create memzone - tempzone0new - when MAX memzones were " "created and one was free\n"); return -1; } for (i = i - 2; i >= 0; i--) { if (rte_memzone_free(mz[i])) { printf("Fail memzone free - tempzone%d\n", i); return -1; } } return 0; } static int test_memzone(void) { const struct rte_memzone *memzone1; const struct rte_memzone *memzone2; const struct rte_memzone *memzone3; const struct rte_memzone *memzone4; const struct rte_memzone *mz; memzone1 = rte_memzone_reserve("testzone1", 100, SOCKET_ID_ANY, 0); memzone2 = rte_memzone_reserve("testzone2", 1000, 0, 0); memzone3 = rte_memzone_reserve("testzone3", 1000, 1, 0); memzone4 = rte_memzone_reserve("testzone4", 1024, SOCKET_ID_ANY, 0); /* memzone3 may be NULL if we don't have NUMA */ if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL) return -1; rte_memzone_dump(stdout); /* check cache-line alignments */ printf("check alignments and lengths\n"); if ((memzone1->phys_addr & RTE_CACHE_LINE_MASK) != 0) return -1; if ((memzone2->phys_addr & RTE_CACHE_LINE_MASK) != 0) return -1; if (memzone3 != NULL && (memzone3->phys_addr & RTE_CACHE_LINE_MASK) != 0) return -1; if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0) return -1; if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0) return -1; if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 || memzone3->len == 0)) return -1; if (memzone4->len != 1024) return -1; /* check that zones don't overlap */ printf("check overlapping\n"); if (is_memory_overlap(memzone1->phys_addr, memzone1->len, memzone2->phys_addr, memzone2->len)) return -1; if (memzone3 != NULL && is_memory_overlap(memzone1->phys_addr, memzone1->len, memzone3->phys_addr, memzone3->len)) return -1; if (memzone3 != NULL && is_memory_overlap(memzone2->phys_addr, memzone2->len, memzone3->phys_addr, memzone3->len)) return -1; printf("check socket ID\n"); /* memzone2 must be on socket id 0 and memzone3 on socket 1 */ if (memzone2->socket_id != 0) return -1; if (memzone3 != NULL && memzone3->socket_id != 1) return -1; printf("test zone lookup\n"); mz = rte_memzone_lookup("testzone1"); if (mz != memzone1) return -1; printf("test duplcate zone name\n"); mz = rte_memzone_reserve("testzone1", 100, SOCKET_ID_ANY, 0); if (mz != NULL) return -1; printf("test free memzone\n"); if (test_memzone_free() < 0) return -1; printf("test reserving memzone with bigger size than the maximum\n"); if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0) return -1; printf("test memzone_reserve flags\n"); if (test_memzone_reserve_flags() < 0) return -1; printf("test alignment for memzone_reserve\n"); if (test_memzone_aligned() < 0) return -1; printf("test boundary alignment for memzone_reserve\n"); if (test_memzone_bounded() < 0) return -1; printf("test invalid alignment for memzone_reserve\n"); if (test_memzone_invalid_alignment() < 0) return -1; printf("test reserving the largest size memzone possible\n"); if (test_memzone_reserve_max() < 0) return -1; printf("test reserving the largest size aligned memzone possible\n"); if (test_memzone_reserve_max_aligned() < 0) return -1; return 0; } static struct test_command memzone_cmd = { .command = "memzone_autotest", .callback = test_memzone, }; REGISTER_TEST_COMMAND(memzone_cmd); ================================================ FILE: app/test/test_meter.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" #include #include #define mlog(format, ...) do{\ printf("Line %d:",__LINE__);\ printf(format, ##__VA_ARGS__);\ printf("\n");\ }while(0); #define melog(format, ...) do{\ printf("Line %d:",__LINE__);\ printf(format, ##__VA_ARGS__);\ printf(" failed!\n");\ return -1;\ }while(0); #define TM_TEST_SRTCM_CIR_DF 46000000 #define TM_TEST_SRTCM_CBS_DF 2048 #define TM_TEST_SRTCM_EBS_DF 4096 #define TM_TEST_TRTCM_CIR_DF 46000000 #define TM_TEST_TRTCM_PIR_DF 69000000 #define TM_TEST_TRTCM_CBS_DF 2048 #define TM_TEST_TRTCM_PBS_DF 4096 static struct rte_meter_srtcm_params sparams = {.cir = TM_TEST_SRTCM_CIR_DF, .cbs = TM_TEST_SRTCM_CBS_DF, .ebs = TM_TEST_SRTCM_EBS_DF,}; static struct rte_meter_trtcm_params tparams= {.cir = TM_TEST_TRTCM_CIR_DF, .pir = TM_TEST_TRTCM_PIR_DF, .cbs = TM_TEST_TRTCM_CBS_DF, .pbs = TM_TEST_TRTCM_PBS_DF,}; /** * functional test for rte_meter_srtcm_config */ static inline int tm_test_srtcm_config(void) { #define SRTCM_CFG_MSG "srtcm_config" struct rte_meter_srtcm sm; struct rte_meter_srtcm_params sparams1; /* invalid parameter test */ if(rte_meter_srtcm_config(NULL, NULL) == 0) melog(SRTCM_CFG_MSG); if(rte_meter_srtcm_config(&sm, NULL) == 0) melog(SRTCM_CFG_MSG); if(rte_meter_srtcm_config(NULL, &sparams) == 0) melog(SRTCM_CFG_MSG); /* cbs and ebs can't both be zero */ sparams1 = sparams; sparams1.cbs = 0; sparams1.ebs = 0; if(rte_meter_srtcm_config(&sm, &sparams1) == 0) melog(SRTCM_CFG_MSG); /* cir should never be 0 */ sparams1 = sparams; sparams1.cir = 0; if(rte_meter_srtcm_config(&sm, &sparams1) == 0) melog(SRTCM_CFG_MSG); /* one of ebs and cbs can be zero, should be successful */ sparams1 = sparams; sparams1.ebs = 0; if(rte_meter_srtcm_config(&sm, &sparams1) != 0) melog(SRTCM_CFG_MSG); sparams1 = sparams; sparams1.cbs = 0; if(rte_meter_srtcm_config(&sm, &sparams1) != 0) melog(SRTCM_CFG_MSG); /* usual parameter, should be successful */ if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_CFG_MSG); return 0; } /** * functional test for rte_meter_trtcm_config */ static inline int tm_test_trtcm_config(void) { struct rte_meter_trtcm tm; struct rte_meter_trtcm_params tparams1; #define TRTCM_CFG_MSG "trtcm_config" /* invalid parameter test */ if(rte_meter_trtcm_config(NULL, NULL) == 0) melog(TRTCM_CFG_MSG); if(rte_meter_trtcm_config(&tm, NULL) == 0) melog(TRTCM_CFG_MSG); if(rte_meter_trtcm_config(NULL, &tparams) == 0) melog(TRTCM_CFG_MSG); /* cir, cbs, pir and pbs never be zero */ tparams1 = tparams; tparams1.cir = 0; if(rte_meter_trtcm_config(&tm, &tparams1) == 0) melog(TRTCM_CFG_MSG); tparams1 = tparams; tparams1.cbs = 0; if(rte_meter_trtcm_config(&tm, &tparams1) == 0) melog(TRTCM_CFG_MSG); tparams1 = tparams; tparams1.pbs = 0; if(rte_meter_trtcm_config(&tm, &tparams1) == 0) melog(TRTCM_CFG_MSG); tparams1 = tparams; tparams1.pir = 0; if(rte_meter_trtcm_config(&tm, &tparams1) == 0) melog(TRTCM_CFG_MSG); /* pir should be greater or equal to cir */ tparams1 = tparams; tparams1.pir = tparams1.cir - 1; if(rte_meter_trtcm_config(&tm, &tparams1) == 0) melog(TRTCM_CFG_MSG" pir < cir test"); /* usual parameter, should be successful */ if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_CFG_MSG); return 0; } /** * functional test for rte_meter_srtcm_color_blind_check */ static inline int tm_test_srtcm_color_blind_check(void) { #define SRTCM_BLIND_CHECK_MSG "srtcm_blind_check" struct rte_meter_srtcm sm; uint64_t time; uint64_t hz = rte_get_tsc_hz(); /* Test green */ if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_blind_check( &sm, time, TM_TEST_SRTCM_CBS_DF - 1) != e_RTE_METER_GREEN) melog(SRTCM_BLIND_CHECK_MSG" GREEN"); /* Test yellow */ if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_blind_check( &sm, time, TM_TEST_SRTCM_CBS_DF + 1) != e_RTE_METER_YELLOW) melog(SRTCM_BLIND_CHECK_MSG" YELLOW"); if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_blind_check( &sm, time, (uint32_t)sm.ebs - 1) != e_RTE_METER_YELLOW) melog(SRTCM_BLIND_CHECK_MSG" YELLOW"); /* Test red */ if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_blind_check( &sm, time, TM_TEST_SRTCM_EBS_DF + 1) != e_RTE_METER_RED) melog(SRTCM_BLIND_CHECK_MSG" RED"); return 0; } /** * functional test for rte_meter_trtcm_color_blind_check */ static inline int tm_test_trtcm_color_blind_check(void) { #define TRTCM_BLIND_CHECK_MSG "trtcm_blind_check" uint64_t time; struct rte_meter_trtcm tm; uint64_t hz = rte_get_tsc_hz(); /* Test green */ if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_blind_check( &tm, time, TM_TEST_TRTCM_CBS_DF - 1) != e_RTE_METER_GREEN) melog(TRTCM_BLIND_CHECK_MSG" GREEN"); /* Test yellow */ if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_blind_check( &tm, time, TM_TEST_TRTCM_CBS_DF + 1) != e_RTE_METER_YELLOW) melog(TRTCM_BLIND_CHECK_MSG" YELLOW"); if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_blind_check( &tm, time, TM_TEST_TRTCM_PBS_DF - 1) != e_RTE_METER_YELLOW) melog(TRTCM_BLIND_CHECK_MSG" YELLOW"); /* Test red */ if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_BLIND_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_blind_check( &tm, time, TM_TEST_TRTCM_PBS_DF + 1) != e_RTE_METER_RED) melog(TRTCM_BLIND_CHECK_MSG" RED"); return 0; } /** * @in[4] : the flags packets carries. * @in[4] : the flags function expect to return. * It will do blind check at the time of 1 second from beginning. * At the time, it will use packets length of cbs -1, cbs + 1, * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do * aware check, expect flag out[0], out[1], out[2] and out[3] */ static inline int tm_test_srtcm_aware_check (enum rte_meter_color in[4], enum rte_meter_color out[4]) { #define SRTCM_AWARE_CHECK_MSG "srtcm_aware_check" struct rte_meter_srtcm sm; uint64_t time; uint64_t hz = rte_get_tsc_hz(); if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_aware_check( &sm, time, TM_TEST_SRTCM_CBS_DF - 1, in[0]) != out[0]) melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]); if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_aware_check( &sm, time, TM_TEST_SRTCM_CBS_DF + 1, in[1]) != out[1]) melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]); if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_aware_check( &sm, time, TM_TEST_SRTCM_EBS_DF - 1, in[2]) != out[2]) melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]); if(rte_meter_srtcm_config(&sm, &sparams) != 0) melog(SRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_srtcm_color_aware_check( &sm, time, TM_TEST_SRTCM_EBS_DF + 1, in[3]) != out[3]) melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]); return 0; } /** * functional test for rte_meter_srtcm_color_aware_check */ static inline int tm_test_srtcm_color_aware_check(void) { enum rte_meter_color in[4], out[4]; /** * test 4 points that will produce green, yellow, yellow, red flag * if using blind check */ /* previouly have a green, test points should keep unchanged */ in[0] = in[1] = in[2] = in[3] = e_RTE_METER_GREEN; out[0] = e_RTE_METER_GREEN; out[1] = e_RTE_METER_YELLOW; out[2] = e_RTE_METER_YELLOW; out[3] = e_RTE_METER_RED; if(tm_test_srtcm_aware_check(in, out) != 0) return -1; /** * previously have a yellow, green & yellow = yellow * yellow & red = red */ in[0] = in[1] = in[2] = in[3] = e_RTE_METER_YELLOW; out[0] = e_RTE_METER_YELLOW; out[1] = e_RTE_METER_YELLOW; out[2] = e_RTE_METER_YELLOW; out[3] = e_RTE_METER_RED; if(tm_test_srtcm_aware_check(in, out) != 0) return -1; /** * previously have a red, red & green = red * red & yellow = red */ in[0] = in[1] = in[2] = in[3] = e_RTE_METER_RED; out[0] = e_RTE_METER_RED; out[1] = e_RTE_METER_RED; out[2] = e_RTE_METER_RED; out[3] = e_RTE_METER_RED; if(tm_test_srtcm_aware_check(in, out) != 0) return -1; return 0; } /** * @in[4] : the flags packets carries. * @in[4] : the flags function expect to return. * It will do blind check at the time of 1 second from beginning. * At the time, it will use packets length of cbs -1, cbs + 1, * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do * aware check, expect flag out[0], out[1], out[2] and out[3] */ static inline int tm_test_trtcm_aware_check (enum rte_meter_color in[4], enum rte_meter_color out[4]) { #define TRTCM_AWARE_CHECK_MSG "trtcm_aware_check" struct rte_meter_trtcm tm; uint64_t time; uint64_t hz = rte_get_tsc_hz(); if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_aware_check( &tm, time, TM_TEST_TRTCM_CBS_DF - 1, in[0]) != out[0]) melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]); if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_aware_check( &tm, time, TM_TEST_TRTCM_CBS_DF + 1, in[1]) != out[1]) melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]); if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_aware_check( &tm, time, TM_TEST_TRTCM_PBS_DF - 1, in[2]) != out[2]) melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]); if(rte_meter_trtcm_config(&tm, &tparams) != 0) melog(TRTCM_AWARE_CHECK_MSG); time = rte_get_tsc_cycles() + hz; if(rte_meter_trtcm_color_aware_check( &tm, time, TM_TEST_TRTCM_PBS_DF + 1, in[3]) != out[3]) melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]); return 0; } /** * functional test for rte_meter_trtcm_color_aware_check */ static inline int tm_test_trtcm_color_aware_check(void) { enum rte_meter_color in[4], out[4]; /** * test 4 points that will produce green, yellow, yellow, red flag * if using blind check */ /* previouly have a green, test points should keep unchanged */ in[0] = in[1] = in[2] = in[3] = e_RTE_METER_GREEN; out[0] = e_RTE_METER_GREEN; out[1] = e_RTE_METER_YELLOW; out[2] = e_RTE_METER_YELLOW; out[3] = e_RTE_METER_RED; if(tm_test_trtcm_aware_check(in, out) != 0) return -1; in[0] = in[1] = in[2] = in[3] = e_RTE_METER_YELLOW; out[0] = e_RTE_METER_YELLOW; out[1] = e_RTE_METER_YELLOW; out[2] = e_RTE_METER_YELLOW; out[3] = e_RTE_METER_RED; if(tm_test_trtcm_aware_check(in, out) != 0) return -1; in[0] = in[1] = in[2] = in[3] = e_RTE_METER_RED; out[0] = e_RTE_METER_RED; out[1] = e_RTE_METER_RED; out[2] = e_RTE_METER_RED; out[3] = e_RTE_METER_RED; if(tm_test_trtcm_aware_check(in, out) != 0) return -1; return 0; } /** * test main entrance for library meter */ static int test_meter(void) { if(tm_test_srtcm_config() != 0 ) return -1; if(tm_test_trtcm_config() != 0 ) return -1; if(tm_test_srtcm_color_blind_check() != 0) return -1; if(tm_test_trtcm_color_blind_check()!= 0) return -1; if(tm_test_srtcm_color_aware_check()!= 0) return -1; if(tm_test_trtcm_color_aware_check()!= 0) return -1; return 0; } static struct test_command meter_cmd = { .command = "meter_autotest", .callback = test_meter, }; REGISTER_TEST_COMMAND(meter_cmd); ================================================ FILE: app/test/test_mp_secondary.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "test.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_HASH #include #include #endif /* RTE_LIBRTE_HASH */ #ifdef RTE_LIBRTE_LPM #include #endif /* RTE_LIBRTE_LPM */ #include #include "process.h" #define launch_proc(ARGV) process_dup(ARGV, \ sizeof(ARGV)/(sizeof(ARGV[0])), __func__) #ifdef RTE_EXEC_ENV_LINUXAPP static char* get_current_prefix(char * prefix, int size) { char path[PATH_MAX] = {0}; char buf[PATH_MAX] = {0}; /* get file for config (fd is always 3) */ snprintf(path, sizeof(path), "/proc/self/fd/%d", 3); /* return NULL on error */ if (readlink(path, buf, sizeof(buf)) == -1) return NULL; /* get the basename */ snprintf(buf, sizeof(buf), "%s", basename(buf)); /* copy string all the way from second char up to start of _config */ snprintf(prefix, size, "%.*s", (int)(strnlen(buf, sizeof(buf)) - sizeof("_config")), &buf[1]); return prefix; } #endif /* * This function is called in the primary i.e. main test, to spawn off secondary * processes to run actual mp tests. Uses fork() and exec pair */ static int run_secondary_instances(void) { int ret = 0; char coremask[10]; #ifdef RTE_EXEC_ENV_LINUXAPP char tmp[PATH_MAX] = {0}; char prefix[PATH_MAX] = {0}; get_current_prefix(tmp, sizeof(tmp)); snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp); #else const char *prefix = ""; #endif /* good case, using secondary */ const char *argv1[] = { prgname, "-c", coremask, "--proc-type=secondary", prefix }; /* good case, using auto */ const char *argv2[] = { prgname, "-c", coremask, "--proc-type=auto", prefix }; /* bad case, using invalid type */ const char *argv3[] = { prgname, "-c", coremask, "--proc-type=ERROR", prefix }; #ifdef RTE_EXEC_ENV_LINUXAPP /* bad case, using invalid file prefix */ const char *argv4[] = { prgname, "-c", coremask, "--proc-type=secondary", "--file-prefix=ERROR" }; #endif snprintf(coremask, sizeof(coremask), "%x", \ (1 << rte_get_master_lcore())); ret |= launch_proc(argv1); ret |= launch_proc(argv2); ret |= !(launch_proc(argv3)); #ifdef RTE_EXEC_ENV_LINUXAPP ret |= !(launch_proc(argv4)); #endif return ret; } /* * This function is run in the secondary instance to test that creation of * objects fails in a secondary */ static int run_object_creation_tests(void) { const unsigned flags = 0; const unsigned size = 1024; const unsigned elt_size = 64; const unsigned cache_size = 64; const unsigned priv_data_size = 32; printf("### Testing object creation - expect lots of mz reserve errors!\n"); rte_errno = 0; if ((rte_memzone_reserve("test_mz", size, rte_socket_id(), flags) == NULL) && (rte_memzone_lookup("test_mz") == NULL)) { printf("Error: unexpected return value from rte_memzone_reserve\n"); return -1; } printf("# Checked rte_memzone_reserve() OK\n"); rte_errno = 0; if ((rte_ring_create( "test_ring", size, rte_socket_id(), flags) == NULL) && (rte_ring_lookup("test_ring") == NULL)){ printf("Error: unexpected return value from rte_ring_create()\n"); return -1; } printf("# Checked rte_ring_create() OK\n"); rte_errno = 0; if ((rte_mempool_create("test_mp", size, elt_size, cache_size, priv_data_size, NULL, NULL, NULL, NULL, rte_socket_id(), flags) == NULL) && (rte_mempool_lookup("test_mp") == NULL)){ printf("Error: unexpected return value from rte_mempool_create()\n"); return -1; } printf("# Checked rte_mempool_create() OK\n"); #ifdef RTE_LIBRTE_HASH const struct rte_hash_parameters hash_params = { .name = "test_mp_hash" }; rte_errno=0; if ((rte_hash_create(&hash_params) != NULL) && (rte_hash_find_existing(hash_params.name) == NULL)){ printf("Error: unexpected return value from rte_hash_create()\n"); return -1; } printf("# Checked rte_hash_create() OK\n"); const struct rte_fbk_hash_params fbk_params = { .name = "test_fbk_mp_hash" }; rte_errno=0; if ((rte_fbk_hash_create(&fbk_params) != NULL) && (rte_fbk_hash_find_existing(fbk_params.name) == NULL)){ printf("Error: unexpected return value from rte_fbk_hash_create()\n"); return -1; } printf("# Checked rte_fbk_hash_create() OK\n"); #endif #ifdef RTE_LIBRTE_LPM rte_errno=0; if ((rte_lpm_create("test_lpm", size, rte_socket_id(), 0) != NULL) && (rte_lpm_find_existing("test_lpm") == NULL)){ printf("Error: unexpected return value from rte_lpm_create()\n"); return -1; } printf("# Checked rte_lpm_create() OK\n"); #endif /* Run a test_pci call */ if (test_pci() != 0) { printf("PCI scan failed in secondary\n"); if (getuid() == 0) /* pci scans can fail as non-root */ return -1; } else printf("PCI scan succeeded in secondary\n"); return 0; } /* if called in a primary process, just spawns off a secondary process to * run validation tests - which brings us right back here again... * if called in a secondary process, this runs a series of API tests to check * how things run in a secondary instance. */ int test_mp_secondary(void) { if (rte_eal_process_type() == RTE_PROC_PRIMARY) { if (!test_pci_run) { printf("=== Running pre-requisite test of test_pci\n"); test_pci(); printf("=== Requisite test done\n"); } return run_secondary_instances(); } printf("IN SECONDARY PROCESS\n"); return run_object_creation_tests(); } static struct test_command multiprocess_cmd = { .command = "multiprocess_autotest", .callback = test_mp_secondary, }; REGISTER_TEST_COMMAND(multiprocess_cmd); ================================================ FILE: app/test/test_pci.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "test.h" /* Generic maximum number of drivers to have room to allocate all drivers */ #define NUM_MAX_DRIVERS 256 /* * PCI test * ======== * * - Register a driver with a ``devinit()`` function. * * - Dump all PCI devices. * * - Check that the ``devinit()`` function is called at least once. */ int test_pci_run = 0; /* value checked by the multiprocess test */ static unsigned pci_dev_count; static int my_driver_init(struct rte_pci_driver *dr, struct rte_pci_device *dev); /* IXGBE NICS */ struct rte_pci_id my_driver_id[] = { #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include { .vendor_id = 0, /* sentinel */ }, }; struct rte_pci_id my_driver_id2[] = { /* IGB & EM NICS */ #define RTE_PCI_DEV_ID_DECL_EM(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include { .vendor_id = 0, /* sentinel */ }, }; struct rte_pci_driver my_driver = { .name = "test_driver", .devinit = my_driver_init, .id_table = my_driver_id, .drv_flags = 0, }; struct rte_pci_driver my_driver2 = { .name = "test_driver2", .devinit = my_driver_init, .id_table = my_driver_id2, .drv_flags = 0, }; static int my_driver_init(__attribute__((unused)) struct rte_pci_driver *dr, struct rte_pci_device *dev) { printf("My driver init called in %s\n", dr->name); printf("%x:%x:%x.%d", dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); printf(" - vendor:%x device:%x\n", dev->id.vendor_id, dev->id.device_id); pci_dev_count ++; return 0; } static void blacklist_all_devices(void) { struct rte_pci_device *dev = NULL; unsigned i = 0; char pci_addr_str[16]; TAILQ_FOREACH(dev, &pci_device_list, next) { snprintf(pci_addr_str, sizeof(pci_addr_str), PCI_PRI_FMT, dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, pci_addr_str) < 0) { printf("Error: cannot blacklist <%s>", pci_addr_str); break; } i++; } printf("%u devices blacklisted\n", i); } /* clear devargs list that was modified by the test */ static void free_devargs_list(void) { struct rte_devargs *devargs; while (!TAILQ_EMPTY(&devargs_list)) { devargs = TAILQ_FIRST(&devargs_list); TAILQ_REMOVE(&devargs_list, devargs, next); if (devargs->args) free(devargs->args); free(devargs); } } int test_pci(void) { struct rte_devargs_list save_devargs_list; struct rte_pci_driver *dr = NULL; struct rte_pci_driver *save_pci_driver_list[NUM_MAX_DRIVERS]; unsigned i, num_drivers = 0; printf("Dump all devices\n"); rte_eal_pci_dump(stdout); /* Unregister all previous drivers */ TAILQ_FOREACH(dr, &pci_driver_list, next) { rte_eal_pci_unregister(dr); save_pci_driver_list[num_drivers++] = dr; } rte_eal_pci_register(&my_driver); rte_eal_pci_register(&my_driver2); pci_dev_count = 0; printf("Scan bus\n"); rte_eal_pci_probe(); if (pci_dev_count == 0) { printf("no device detected\n"); return -1; } /* save the real devargs_list */ save_devargs_list = devargs_list; TAILQ_INIT(&devargs_list); blacklist_all_devices(); pci_dev_count = 0; printf("Scan bus with all devices blacklisted\n"); rte_eal_pci_probe(); free_devargs_list(); devargs_list = save_devargs_list; if (pci_dev_count != 0) { printf("not all devices are blacklisted\n"); return -1; } test_pci_run = 1; rte_eal_pci_unregister(&my_driver); rte_eal_pci_unregister(&my_driver2); /* Restore original driver list */ for (i = 0; i < num_drivers; i++) rte_eal_pci_register(save_pci_driver_list[i]); return 0; } static struct test_command pci_cmd = { .command = "pci_autotest", .callback = test_pci, }; REGISTER_TEST_COMMAND(pci_cmd); ================================================ FILE: app/test/test_per_lcore.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Per-lcore variables and lcore launch * ==================================== * * - Use ``rte_eal_mp_remote_launch()`` to call ``assign_vars()`` on * every available lcore. In this function, a per-lcore variable is * assigned to the lcore_id. * * - Use ``rte_eal_mp_remote_launch()`` to call ``display_vars()`` on * every available lcore. The function checks that the variable is * correctly set, or returns -1. * * - If at least one per-core variable was not correct, the test function * returns -1. */ static RTE_DEFINE_PER_LCORE(unsigned, test) = 0x12345678; static int assign_vars(__attribute__((unused)) void *arg) { if (RTE_PER_LCORE(test) != 0x12345678) return -1; RTE_PER_LCORE(test) = rte_lcore_id(); return 0; } static int display_vars(__attribute__((unused)) void *arg) { unsigned lcore_id = rte_lcore_id(); unsigned var = RTE_PER_LCORE(test); unsigned socket_id = rte_lcore_to_socket_id(lcore_id); printf("on socket %u, on core %u, variable is %u\n", socket_id, lcore_id, var); if (lcore_id != var) return -1; RTE_PER_LCORE(test) = 0x12345678; return 0; } static int test_per_lcore_delay(__attribute__((unused)) void *arg) { rte_delay_ms(5000); printf("wait 5000ms on lcore %u\n", rte_lcore_id()); return 0; } static int test_per_lcore(void) { unsigned lcore_id; int ret; rte_eal_mp_remote_launch(assign_vars, NULL, SKIP_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } rte_eal_mp_remote_launch(display_vars, NULL, SKIP_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } /* test if it could do remote launch twice at the same time or not */ ret = rte_eal_mp_remote_launch(test_per_lcore_delay, NULL, SKIP_MASTER); if (ret < 0) { printf("It fails to do remote launch but it should able to do\n"); return -1; } /* it should not be able to launch a lcore which is running */ ret = rte_eal_mp_remote_launch(test_per_lcore_delay, NULL, SKIP_MASTER); if (ret == 0) { printf("It does remote launch successfully but it should not at this time\n"); return -1; } RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } static struct test_command per_lcore_cmd = { .command = "per_lcore_autotest", .callback = test_per_lcore, }; REGISTER_TEST_COMMAND(per_lcore_cmd); ================================================ FILE: app/test/test_pmd_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "packet_burst_generator.h" #include "test.h" #define NB_ETHPORTS_USED (1) #define NB_SOCKETS (2) #define MEMPOOL_CACHE_SIZE 250 #define MAX_PKT_BURST (32) #define RTE_TEST_RX_DESC_DEFAULT (128) #define RTE_TEST_TX_DESC_DEFAULT (512) #define RTE_PORT_ALL (~(uint8_t)0x0) /* how long test would take at full line rate */ #define RTE_TEST_DURATION (2) /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ #define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */ /* * These default values are optimized for use with the Intel(R) 82599 10 GbE * Controller and the DPDK ixgbe PMD. Consider using other values for other * network controllers and/or network drivers. */ #define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */ #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ #define MAX_TRAFFIC_BURST 2048 #define NB_MBUF RTE_MAX( \ (unsigned)(nb_ports*nb_rx_queue*nb_rxd + \ nb_ports*nb_lcores*MAX_PKT_BURST + \ nb_ports*nb_tx_queue*nb_txd + \ nb_lcores*MEMPOOL_CACHE_SIZE + \ nb_ports*MAX_TRAFFIC_BURST), \ (unsigned)8192) static struct rte_mempool *mbufpool[NB_SOCKETS]; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .hw_vlan_strip = 0, /**< VLAN strip enabled. */ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ .enable_scatter = 0, /**< scatter rx disabled */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .lpbk_mode = 1, /* enable loopback */ }; static struct rte_eth_rxconf rx_conf = { .rx_thresh = { .pthresh = RX_PTHRESH, .hthresh = RX_HTHRESH, .wthresh = RX_WTHRESH, }, .rx_free_thresh = 32, }; static struct rte_eth_txconf tx_conf = { .tx_thresh = { .pthresh = TX_PTHRESH, .hthresh = TX_HTHRESH, .wthresh = TX_WTHRESH, }, .tx_free_thresh = 32, /* Use PMD default values */ .tx_rs_thresh = 32, /* Use PMD default values */ .txq_flags = (ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) }; enum { LCORE_INVALID = 0, LCORE_AVAIL, LCORE_USED, }; struct lcore_conf { uint8_t status; uint8_t socketid; uint16_t nb_ports; uint8_t portlist[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct lcore_conf lcore_conf[RTE_MAX_LCORE]; static uint64_t link_mbps; enum { SC_CONTINUOUS = 0, SC_BURST_POLL_FIRST, SC_BURST_XMIT_FIRST, }; static uint32_t sc_flag; /* Check the link status of all ports in up to 3s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("Checking link statuses...\n"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) { printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); if (link_mbps == 0) link_mbps = link.link_speed; } else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) print_flag = 1; } } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } static int init_traffic(struct rte_mempool *mp, struct rte_mbuf **pkts_burst, uint32_t burst_size) { struct ether_hdr pkt_eth_hdr; struct ipv4_hdr pkt_ipv4_hdr; struct udp_hdr pkt_udp_hdr; uint32_t pktlen; static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; initialize_eth_header(&pkt_eth_hdr, (struct ether_addr *)src_mac, (struct ether_addr *)dst_mac, ETHER_TYPE_IPv4, 0, 0); pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, IPV4_ADDR(10, 0, 0, 1), IPV4_ADDR(10, 0, 0, 2), 26); printf("IPv4 pktlen %u\n", pktlen); pktlen = initialize_udp_header(&pkt_udp_hdr, 0, 0, 18); printf("UDP pktlen %u\n", pktlen); return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr, 0, &pkt_ipv4_hdr, 1, &pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1); } static int init_lcores(void) { unsigned lcore_id; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { lcore_conf[lcore_id].socketid = rte_lcore_to_socket_id(lcore_id); if (rte_lcore_is_enabled(lcore_id) == 0) { lcore_conf[lcore_id].status = LCORE_INVALID; continue; } else lcore_conf[lcore_id].status = LCORE_AVAIL; } return 0; } static int init_mbufpool(unsigned nb_mbuf) { int socketid; unsigned lcore_id; char s[64]; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socketid = rte_lcore_to_socket_id(lcore_id); if (socketid >= NB_SOCKETS) { rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", socketid, lcore_id, NB_SOCKETS); } if (mbufpool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); mbufpool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (mbufpool[socketid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); else printf("Allocated mbuf pool on socket %d\n", socketid); } } return 0; } static uint16_t alloc_lcore(uint16_t socketid) { unsigned lcore_id; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (LCORE_AVAIL != lcore_conf[lcore_id].status || lcore_conf[lcore_id].socketid != socketid || lcore_id == rte_get_master_lcore()) continue; lcore_conf[lcore_id].status = LCORE_USED; lcore_conf[lcore_id].nb_ports = 0; return lcore_id; } return (uint16_t)-1; } volatile uint64_t stop; uint64_t count; uint64_t drop; uint64_t idle; static void reset_count(void) { count = 0; drop = 0; idle = 0; } static void stats_display(uint8_t port_id) { struct rte_eth_stats stats; rte_eth_stats_get(port_id, &stats); printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " "%-"PRIu64"\n", stats.ipackets, stats.imissed, stats.ibytes); printf(" RX-badcrc: %-10"PRIu64" RX-badlen: %-10"PRIu64" RX-errors: " "%-"PRIu64"\n", stats.ibadcrc, stats.ibadlen, stats.ierrors); printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf); printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " "%-"PRIu64"\n", stats.opackets, stats.oerrors, stats.obytes); } static void signal_handler(int signum) { /* USR1 signal, stop testing */ if (signum == SIGUSR1) { printf("Force Stop!\n"); stop = 1; } /* USR2 signal, print stats */ if (signum == SIGUSR2) stats_display(0); } struct rte_mbuf **tx_burst; uint64_t (*do_measure)(struct lcore_conf *conf, struct rte_mbuf *pkts_burst[], uint64_t total_pkts); static uint64_t measure_rxtx(struct lcore_conf *conf, struct rte_mbuf *pkts_burst[], uint64_t total_pkts) { unsigned i, portid, nb_rx, nb_tx; uint64_t prev_tsc, cur_tsc; prev_tsc = rte_rdtsc(); while (likely(!stop)) { for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); if (unlikely(nb_rx == 0)) { idle++; continue; } count += nb_rx; nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); if (unlikely(nb_tx < nb_rx)) { drop += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } } if (unlikely(count >= total_pkts)) break; } cur_tsc = rte_rdtsc(); return cur_tsc - prev_tsc; } static uint64_t measure_rxonly(struct lcore_conf *conf, struct rte_mbuf *pkts_burst[], uint64_t total_pkts) { unsigned i, portid, nb_rx, nb_tx; uint64_t diff_tsc, cur_tsc; diff_tsc = 0; while (likely(!stop)) { for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; cur_tsc = rte_rdtsc(); nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); if (unlikely(nb_rx == 0)) { idle++; continue; } diff_tsc += rte_rdtsc() - cur_tsc; count += nb_rx; nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); if (unlikely(nb_tx < nb_rx)) { drop += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } } if (unlikely(count >= total_pkts)) break; } return diff_tsc; } static uint64_t measure_txonly(struct lcore_conf *conf, struct rte_mbuf *pkts_burst[], uint64_t total_pkts) { unsigned i, portid, nb_rx, nb_tx; uint64_t diff_tsc, cur_tsc; printf("do tx measure\n"); diff_tsc = 0; while (likely(!stop)) { for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); if (unlikely(nb_rx == 0)) { idle++; continue; } count += nb_rx; cur_tsc = rte_rdtsc(); nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); if (unlikely(nb_tx < nb_rx)) { drop += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } diff_tsc += rte_rdtsc() - cur_tsc; } if (unlikely(count >= total_pkts)) break; } return diff_tsc; } /* main processing loop */ static int main_loop(__rte_unused void *args) { #define PACKET_SIZE 64 #define FRAME_GAP 12 #define MAC_PREAMBLE 8 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; unsigned i, portid, nb_rx = 0, nb_tx = 0; struct lcore_conf *conf; int pkt_per_port; uint64_t diff_tsc; uint64_t packets_per_second, total_packets; lcore_id = rte_lcore_id(); conf = &lcore_conf[lcore_id]; if (conf->status != LCORE_USED) return 0; pkt_per_port = MAX_TRAFFIC_BURST; int idx = 0; for (i = 0; i < conf->nb_ports; i++) { int num = pkt_per_port; portid = conf->portlist[i]; printf("inject %d packet to port %d\n", num, portid); while (num) { nb_tx = RTE_MIN(MAX_PKT_BURST, num); nb_tx = rte_eth_tx_burst(portid, 0, &tx_burst[idx], nb_tx); num -= nb_tx; idx += nb_tx; } } printf("Total packets inject to prime ports = %u\n", idx); packets_per_second = (link_mbps * 1000 * 1000) / ((PACKET_SIZE + FRAME_GAP + MAC_PREAMBLE) * CHAR_BIT); printf("Each port will do %"PRIu64" packets per second\n", packets_per_second); total_packets = RTE_TEST_DURATION * conf->nb_ports * packets_per_second; printf("Test will stop after at least %"PRIu64" packets received\n", + total_packets); diff_tsc = do_measure(conf, pkts_burst, total_packets); for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; int nb_free = pkt_per_port; do { /* dry out */ nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); nb_tx = 0; while (nb_tx < nb_rx) rte_pktmbuf_free(pkts_burst[nb_tx++]); nb_free -= nb_rx; } while (nb_free != 0); printf("free %d mbuf left in port %u\n", pkt_per_port, portid); } if (count == 0) return -1; printf("%"PRIu64" packet, %"PRIu64" drop, %"PRIu64" idle\n", count, drop, idle); printf("Result: %"PRIu64" cycles per packet\n", diff_tsc / count); return 0; } rte_atomic64_t start; static inline int poll_burst(void *args) { #define MAX_IDLE (10000) unsigned lcore_id; struct rte_mbuf **pkts_burst; uint64_t diff_tsc, cur_tsc; uint16_t next[RTE_MAX_ETHPORTS]; struct lcore_conf *conf; uint32_t pkt_per_port = *((uint32_t *)args); unsigned i, portid, nb_rx = 0; uint64_t total; uint64_t timeout = MAX_IDLE; lcore_id = rte_lcore_id(); conf = &lcore_conf[lcore_id]; if (conf->status != LCORE_USED) return 0; total = pkt_per_port * conf->nb_ports; printf("start to receive total expect %"PRIu64"\n", total); pkts_burst = (struct rte_mbuf **) rte_calloc_socket("poll_burst", total, sizeof(void *), RTE_CACHE_LINE_SIZE, conf->socketid); if (!pkts_burst) return -1; for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; next[portid] = i * pkt_per_port; } while (!rte_atomic64_read(&start)) ; cur_tsc = rte_rdtsc(); while (total) { for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, &pkts_burst[next[portid]], MAX_PKT_BURST); if (unlikely(nb_rx == 0)) { timeout--; if (unlikely(timeout == 0)) goto timeout; continue; } next[portid] += nb_rx; total -= nb_rx; } } timeout: diff_tsc = rte_rdtsc() - cur_tsc; printf("%"PRIu64" packets lost, IDLE %"PRIu64" times\n", total, MAX_IDLE - timeout); /* clean up */ total = pkt_per_port * conf->nb_ports - total; for (i = 0; i < total; i++) rte_pktmbuf_free(pkts_burst[i]); rte_free(pkts_burst); return diff_tsc / total; } static int exec_burst(uint32_t flags, int lcore) { unsigned i, portid, nb_tx = 0; struct lcore_conf *conf; uint32_t pkt_per_port; int num, idx = 0; int diff_tsc; conf = &lcore_conf[lcore]; pkt_per_port = MAX_TRAFFIC_BURST; num = pkt_per_port; rte_atomic64_init(&start); /* start polling thread, but not actually poll yet */ rte_eal_remote_launch(poll_burst, (void *)&pkt_per_port, lcore); /* Only when polling first */ if (flags == SC_BURST_POLL_FIRST) rte_atomic64_set(&start, 1); /* start xmit */ while (num) { nb_tx = RTE_MIN(MAX_PKT_BURST, num); for (i = 0; i < conf->nb_ports; i++) { portid = conf->portlist[i]; rte_eth_tx_burst(portid, 0, &tx_burst[idx], nb_tx); idx += nb_tx; } num -= nb_tx; } sleep(5); /* only when polling second */ if (flags == SC_BURST_XMIT_FIRST) rte_atomic64_set(&start, 1); /* wait for polling finished */ diff_tsc = rte_eal_wait_lcore(lcore); if (diff_tsc < 0) return -1; printf("Result: %d cycles per packet\n", diff_tsc); return 0; } static int test_pmd_perf(void) { uint16_t nb_ports, num, nb_lcores, slave_id = (uint16_t)-1; uint16_t nb_rxd = MAX_TRAFFIC_BURST; uint16_t nb_txd = MAX_TRAFFIC_BURST; uint16_t portid; uint16_t nb_rx_queue = 1, nb_tx_queue = 1; int socketid = -1; int ret; printf("Start PMD RXTX cycles cost test.\n"); signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); nb_ports = rte_eth_dev_count(); if (nb_ports < NB_ETHPORTS_USED) { printf("At least %u port(s) used for perf. test\n", NB_ETHPORTS_USED); return -1; } if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; nb_lcores = rte_lcore_count(); memset(lcore_conf, 0, sizeof(lcore_conf)); init_lcores(); init_mbufpool(NB_MBUF); if (sc_flag == SC_CONTINUOUS) { nb_rxd = RTE_TEST_RX_DESC_DEFAULT; nb_txd = RTE_TEST_TX_DESC_DEFAULT; } printf("CONFIG RXD=%d TXD=%d\n", nb_rxd, nb_txd); reset_count(); num = 0; for (portid = 0; portid < nb_ports; portid++) { if (socketid == -1) { socketid = rte_eth_dev_socket_id(portid); slave_id = alloc_lcore(socketid); if (slave_id == (uint16_t)-1) { printf("No avail lcore to run test\n"); return -1; } printf("Performance test runs on lcore %u socket %u\n", slave_id, socketid); } if (socketid != rte_eth_dev_socket_id(portid)) { printf("Skip port %d\n", portid); continue; } /* port configure */ ret = rte_eth_dev_configure(portid, nb_rx_queue, nb_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); printf("Port %u ", portid); print_ethaddr("Address:", &ports_eth_addr[portid]); printf("\n"); /* tx queue setup */ ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, socketid, &tx_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); /* rx queue steup */ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, socketid, &rx_conf, mbufpool[socketid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," "port=%d\n", ret, portid); /* Start device */ stop = 0; ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); /* always eanble promiscuous */ rte_eth_promiscuous_enable(portid); lcore_conf[slave_id].portlist[num++] = portid; lcore_conf[slave_id].nb_ports++; } check_all_ports_link_status(nb_ports, RTE_PORT_ALL); if (tx_burst == NULL) { tx_burst = (struct rte_mbuf **) rte_calloc_socket("tx_buff", MAX_TRAFFIC_BURST * nb_ports, sizeof(void *), RTE_CACHE_LINE_SIZE, socketid); if (!tx_burst) return -1; } init_traffic(mbufpool[socketid], tx_burst, MAX_TRAFFIC_BURST * nb_ports); printf("Generate %d packets @socket %d\n", MAX_TRAFFIC_BURST * nb_ports, socketid); if (sc_flag == SC_CONTINUOUS) { /* do both rxtx by default */ if (NULL == do_measure) do_measure = measure_rxtx; rte_eal_remote_launch(main_loop, NULL, slave_id); if (rte_eal_wait_lcore(slave_id) < 0) return -1; } else if (sc_flag == SC_BURST_POLL_FIRST || sc_flag == SC_BURST_XMIT_FIRST) exec_burst(sc_flag, slave_id); /* port tear down */ for (portid = 0; portid < nb_ports; portid++) { if (socketid != rte_eth_dev_socket_id(portid)) continue; rte_eth_dev_stop(portid); } return 0; } int test_set_rxtx_conf(cmdline_fixed_string_t mode) { printf("mode switch to %s\n", mode); if (!strcmp(mode, "vector")) { /* vector rx, tx */ tx_conf.txq_flags = 0xf01; tx_conf.tx_rs_thresh = 32; tx_conf.tx_free_thresh = 32; port_conf.rxmode.hw_ip_checksum = 0; port_conf.rxmode.enable_scatter = 0; return 0; } else if (!strcmp(mode, "scalar")) { /* bulk alloc rx, simple tx */ tx_conf.txq_flags = 0xf01; tx_conf.tx_rs_thresh = 128; tx_conf.tx_free_thresh = 128; port_conf.rxmode.hw_ip_checksum = 1; port_conf.rxmode.enable_scatter = 0; return 0; } else if (!strcmp(mode, "hybrid")) { /* bulk alloc rx, vector tx * when vec macro not define, * using the same rx/tx as scalar */ tx_conf.txq_flags = 0xf01; tx_conf.tx_rs_thresh = 32; tx_conf.tx_free_thresh = 32; port_conf.rxmode.hw_ip_checksum = 1; port_conf.rxmode.enable_scatter = 0; return 0; } else if (!strcmp(mode, "full")) { /* full feature rx,tx pair */ tx_conf.txq_flags = 0x0; /* must condition */ tx_conf.tx_rs_thresh = 32; tx_conf.tx_free_thresh = 32; port_conf.rxmode.hw_ip_checksum = 0; port_conf.rxmode.enable_scatter = 1; /* must condition */ return 0; } return -1; } int test_set_rxtx_anchor(cmdline_fixed_string_t type) { printf("type switch to %s\n", type); if (!strcmp(type, "rxtx")) { do_measure = measure_rxtx; return 0; } else if (!strcmp(type, "rxonly")) { do_measure = measure_rxonly; return 0; } else if (!strcmp(type, "txonly")) { do_measure = measure_txonly; return 0; } return -1; } int test_set_rxtx_sc(cmdline_fixed_string_t type) { printf("stream control switch to %s\n", type); if (!strcmp(type, "continuous")) { sc_flag = SC_CONTINUOUS; return 0; } else if (!strcmp(type, "poll_before_xmit")) { sc_flag = SC_BURST_POLL_FIRST; return 0; } else if (!strcmp(type, "poll_after_xmit")) { sc_flag = SC_BURST_XMIT_FIRST; return 0; } return -1; } static struct test_command pmd_perf_cmd = { .command = "pmd_perf_autotest", .callback = test_pmd_perf, }; REGISTER_TEST_COMMAND(pmd_perf_cmd); ================================================ FILE: app/test/test_pmd_ring.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include #include #include static struct rte_mempool *mp; #define TX_PORT 0 #define RX_PORT 1 #define RXTX_PORT 2 #define RXTX_PORT2 3 #define RXTX_PORT3 4 #define SOCKET0 0 #define RING_SIZE 256 #define NB_MBUF 512 static int test_ethdev_configure(void) { struct rte_eth_conf null_conf; struct rte_eth_link link; memset(&null_conf, 0, sizeof(struct rte_eth_conf)); if ((TX_PORT >= RTE_MAX_ETHPORTS) || (RX_PORT >= RTE_MAX_ETHPORTS)\ || (RXTX_PORT >= RTE_MAX_ETHPORTS)) { printf(" TX/RX port exceed max eth ports\n"); return -1; } if (rte_eth_dev_configure(TX_PORT, 1, 2, &null_conf) < 0) { printf("Configure failed for TX port\n"); return -1; } /* Test queue release */ if (rte_eth_dev_configure(TX_PORT, 1, 1, &null_conf) < 0) { printf("Configure failed for TX port\n"); return -1; } if (rte_eth_dev_configure(RX_PORT, 1, 1, &null_conf) < 0) { printf("Configure failed for RX port\n"); return -1; } if (rte_eth_dev_configure(RXTX_PORT, 1, 1, &null_conf) < 0) { printf("Configure failed for RXTX port\n"); return -1; } if (rte_eth_tx_queue_setup(TX_PORT, 0, RING_SIZE, SOCKET0, NULL) < 0) { printf("TX queue setup failed\n"); return -1; } if (rte_eth_rx_queue_setup(RX_PORT, 0, RING_SIZE, SOCKET0, NULL, mp) < 0) { printf("RX queue setup failed\n"); return -1; } if (rte_eth_tx_queue_setup(RXTX_PORT, 0, RING_SIZE, SOCKET0, NULL) < 0) { printf("TX queue setup failed\n"); return -1; } if (rte_eth_rx_queue_setup(RXTX_PORT, 0, RING_SIZE, SOCKET0, NULL, mp) < 0) { printf("RX queue setup failed\n"); return -1; } if (rte_eth_dev_start(TX_PORT) < 0) { printf("Error starting TX port\n"); return -1; } if (rte_eth_dev_start(RX_PORT) < 0) { printf("Error starting RX port\n"); return -1; } if (rte_eth_dev_start(RXTX_PORT) < 0) { printf("Error starting RX port\n"); return -1; } rte_eth_link_get(TX_PORT, &link); rte_eth_link_get(RX_PORT, &link); rte_eth_link_get(RXTX_PORT, &link); return 0; } static int test_send_basic_packets(void) { struct rte_mbuf bufs[RING_SIZE]; struct rte_mbuf *pbufs[RING_SIZE]; int i; printf("Testing ring pmd RX/TX\n"); for (i = 0; i < RING_SIZE/2; i++) pbufs[i] = &bufs[i]; if (rte_eth_tx_burst(TX_PORT, 0, pbufs, RING_SIZE/2) < RING_SIZE/2) { printf("Failed to transmit packet burst\n"); return -1; } if (rte_eth_rx_burst(RX_PORT, 0, pbufs, RING_SIZE) != RING_SIZE/2) { printf("Failed to receive packet burst\n"); return -1; } for (i = 0; i < RING_SIZE/2; i++) if (pbufs[i] != &bufs[i]) { printf("Error: received data does not match that transmitted\n"); return -1; } return 0; } static int test_get_stats(void) { struct rte_eth_stats stats; struct rte_mbuf buf, *pbuf = &buf; printf("Testing ring PMD stats\n"); /* check stats of RXTX port, should all be zero */ rte_eth_stats_get(RXTX_PORT, &stats); if (stats.ipackets != 0 || stats.opackets != 0 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not zero\n"); return -1; } /* send and receive 1 packet and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT, &stats); if (stats.ipackets != 1 || stats.opackets != 1 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } return 0; } static int test_stats_reset(void) { struct rte_eth_stats stats; struct rte_mbuf buf, *pbuf = &buf; printf("Testing ring PMD stats reset\n"); rte_eth_stats_reset(RXTX_PORT); /* check stats of RXTX port, should all be zero */ rte_eth_stats_get(RXTX_PORT, &stats); if (stats.ipackets != 0 || stats.opackets != 0 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not zero\n"); return -1; } /* send and receive 1 packet and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT, &stats); if (stats.ipackets != 1 || stats.opackets != 1 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } rte_eth_stats_reset(RXTX_PORT); /* check stats of RXTX port, should all be zero */ rte_eth_stats_get(RXTX_PORT, &stats); if (stats.ipackets != 0 || stats.opackets != 0 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not zero\n"); return -1; } return 0; } static int test_pmd_ring_pair_create_attach(void) { struct rte_eth_stats stats, stats2; struct rte_mbuf buf, *pbuf = &buf; struct rte_eth_conf null_conf; if ((RXTX_PORT2 >= RTE_MAX_ETHPORTS) || (RXTX_PORT3 >= RTE_MAX_ETHPORTS)) { printf(" TX/RX port exceed max eth ports\n"); return -1; } if ((rte_eth_dev_configure(RXTX_PORT2, 1, 1, &null_conf) < 0) || (rte_eth_dev_configure(RXTX_PORT3, 1, 1, &null_conf) < 0)) { printf("Configure failed for RXTX port\n"); return -1; } if ((rte_eth_tx_queue_setup(RXTX_PORT2, 0, RING_SIZE, SOCKET0, NULL) < 0) || (rte_eth_tx_queue_setup(RXTX_PORT3, 0, RING_SIZE, SOCKET0, NULL) < 0)) { printf("TX queue setup failed\n"); return -1; } if ((rte_eth_rx_queue_setup(RXTX_PORT2, 0, RING_SIZE, SOCKET0, NULL, mp) < 0) || (rte_eth_rx_queue_setup(RXTX_PORT3, 0, RING_SIZE, SOCKET0, NULL, mp) < 0)) { printf("RX queue setup failed\n"); return -1; } if ((rte_eth_dev_start(RXTX_PORT2) < 0) || (rte_eth_dev_start(RXTX_PORT3) < 0)) { printf("Error starting RXTX port\n"); return -1; } /* * send and receive 1 packet (RXTX_PORT2 -> RXTX_PORT3) * and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT2, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT3, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT2, &stats); rte_eth_stats_get(RXTX_PORT3, &stats2); if (stats.ipackets != 0 || stats.opackets != 1 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } if (stats2.ipackets != 1 || stats2.opackets != 0 || stats2.ibytes != 0 || stats2.obytes != 0 || stats2.ierrors != 0 || stats2.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } /* * send and receive 1 packet (RXTX_PORT3 -> RXTX_PORT2) * and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT3, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT2, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT2, &stats); rte_eth_stats_get(RXTX_PORT3, &stats2); if (stats.ipackets != 1 || stats.opackets != 1 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } if (stats2.ipackets != 1 || stats2.opackets != 1 || stats2.ibytes != 0 || stats2.obytes != 0 || stats2.ierrors != 0 || stats2.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } /* * send and receive 1 packet (RXTX_PORT2 -> RXTX_PORT2) * and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT2, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT2, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT2, &stats); rte_eth_stats_get(RXTX_PORT3, &stats2); if (stats.ipackets != 2 || stats.opackets != 2 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } if (stats2.ipackets != 1 || stats2.opackets != 1 || stats2.ibytes != 0 || stats2.obytes != 0 || stats2.ierrors != 0 || stats2.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } /* * send and receive 1 packet (RXTX_PORT3 -> RXTX_PORT3) * and check for stats update */ if (rte_eth_tx_burst(RXTX_PORT3, 0, &pbuf, 1) != 1) { printf("Error sending packet to RXTX port\n"); return -1; } if (rte_eth_rx_burst(RXTX_PORT3, 0, &pbuf, 1) != 1) { printf("Error receiving packet from RXTX port\n"); return -1; } rte_eth_stats_get(RXTX_PORT2, &stats); rte_eth_stats_get(RXTX_PORT3, &stats2); if (stats.ipackets != 2 || stats.opackets != 2 || stats.ibytes != 0 || stats.obytes != 0 || stats.ierrors != 0 || stats.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } if (stats2.ipackets != 2 || stats2.opackets != 2 || stats2.ibytes != 0 || stats2.obytes != 0 || stats2.ierrors != 0 || stats2.oerrors != 0) { printf("Error: RXTX port stats are not as expected\n"); return -1; } rte_eth_dev_stop(RXTX_PORT2); rte_eth_dev_stop(RXTX_PORT3); return 0; } static int test_pmd_ring(void) { mp = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mp == NULL) return -1; if ((TX_PORT >= RTE_MAX_ETHPORTS) || (RX_PORT >= RTE_MAX_ETHPORTS)\ || (RXTX_PORT >= RTE_MAX_ETHPORTS)) { printf(" TX/RX port exceed max eth ports\n"); return -1; } if (test_ethdev_configure() < 0) return -1; if (test_send_basic_packets() < 0) return -1; if (test_get_stats() < 0) return -1; if (test_stats_reset() < 0) return -1; rte_eth_dev_stop(RX_PORT); rte_eth_dev_stop(TX_PORT); rte_eth_dev_stop(RXTX_PORT); if (test_pmd_ring_pair_create_attach() < 0) return -1; return 0; } static struct test_command ring_pmd_cmd = { .command = "ring_pmd_autotest", .callback = test_pmd_ring, }; REGISTER_TEST_COMMAND(ring_pmd_cmd); ================================================ FILE: app/test/test_power.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" #include static int test_power(void) { int ret = -1; enum power_management_env env; /* Test setting an invalid environment */ ret = rte_power_set_env(PM_ENV_NOT_SET); if (ret == 0) { printf("Unexpectedly succeeded on setting an invalid environment\n"); return -1; } /* Test that the environment has not been set */ env = rte_power_get_env(); if (env != PM_ENV_NOT_SET) { printf("Unexpectedly got a valid environment configuration\n"); return -1; } /* verify that function pointers are NULL */ if (rte_power_freqs != NULL) { printf("rte_power_freqs should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_get_freq != NULL) { printf("rte_power_get_freq should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_set_freq != NULL) { printf("rte_power_set_freq should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_freq_up != NULL) { printf("rte_power_freq_up should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_freq_down != NULL) { printf("rte_power_freq_down should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_freq_max != NULL) { printf("rte_power_freq_max should be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_freq_min != NULL) { printf("rte_power_freq_min should be NULL, environment has not been " "initialised\n"); goto fail_all; } rte_power_unset_env(); return 0; fail_all: rte_power_unset_env(); return -1; } static struct test_command power_cmd = { .command = "power_autotest", .callback = test_power, }; REGISTER_TEST_COMMAND(power_cmd); ================================================ FILE: app/test/test_power_acpi_cpufreq.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" #include #define TEST_POWER_LCORE_ID 2U #define TEST_POWER_LCORE_INVALID ((unsigned)RTE_MAX_LCORE) #define TEST_POWER_FREQS_NUM_MAX ((unsigned)RTE_MAX_LCORE_FREQS) #define TEST_POWER_SYSFILE_CUR_FREQ \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq" static uint32_t total_freq_num; static uint32_t freqs[TEST_POWER_FREQS_NUM_MAX]; static int check_cur_freq(unsigned lcore_id, uint32_t idx) { #define TEST_POWER_CONVERT_TO_DECIMAL 10 FILE *f; char fullpath[PATH_MAX]; char buf[BUFSIZ]; uint32_t cur_freq; int ret = -1; if (snprintf(fullpath, sizeof(fullpath), TEST_POWER_SYSFILE_CUR_FREQ, lcore_id) < 0) { return 0; } f = fopen(fullpath, "r"); if (f == NULL) { return 0; } if (fgets(buf, sizeof(buf), f) == NULL) { goto fail_get_cur_freq; } cur_freq = strtoul(buf, NULL, TEST_POWER_CONVERT_TO_DECIMAL); ret = (freqs[idx] == cur_freq ? 0 : -1); fail_get_cur_freq: fclose(f); return ret; } /* Check rte_power_freqs() */ static int check_power_freqs(void) { uint32_t ret; total_freq_num = 0; memset(freqs, 0, sizeof(freqs)); /* test with an invalid lcore id */ ret = rte_power_freqs(TEST_POWER_LCORE_INVALID, freqs, TEST_POWER_FREQS_NUM_MAX); if (ret > 0) { printf("Unexpectedly get available freqs successfully on " "lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } /* test with NULL buffer to save available freqs */ ret = rte_power_freqs(TEST_POWER_LCORE_ID, NULL, TEST_POWER_FREQS_NUM_MAX); if (ret > 0) { printf("Unexpectedly get available freqs successfully with " "NULL buffer on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* test of getting zero number of freqs */ ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs, 0); if (ret > 0) { printf("Unexpectedly get available freqs successfully with " "zero buffer size on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* test with all valid input parameters */ ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs, TEST_POWER_FREQS_NUM_MAX); if (ret == 0 || ret > TEST_POWER_FREQS_NUM_MAX) { printf("Fail to get available freqs on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Save the total number of available freqs */ total_freq_num = ret; return 0; } /* Check rte_power_get_freq() */ static int check_power_get_freq(void) { int ret; uint32_t count; /* test with an invalid lcore id */ count = rte_power_get_freq(TEST_POWER_LCORE_INVALID); if (count < TEST_POWER_FREQS_NUM_MAX) { printf("Unexpectedly get freq index successfully on " "lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } count = rte_power_get_freq(TEST_POWER_LCORE_ID); if (count >= TEST_POWER_FREQS_NUM_MAX) { printf("Fail to get the freq index on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, count); if (ret < 0) return -1; return 0; } /* Check rte_power_set_freq() */ static int check_power_set_freq(void) { int ret; /* test with an invalid lcore id */ ret = rte_power_set_freq(TEST_POWER_LCORE_INVALID, 0); if (ret >= 0) { printf("Unexpectedly set freq index successfully on " "lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } /* test with an invalid freq index */ ret = rte_power_set_freq(TEST_POWER_LCORE_ID, TEST_POWER_FREQS_NUM_MAX); if (ret >= 0) { printf("Unexpectedly set an invalid freq index (%u)" "successfully on lcore %u\n", TEST_POWER_FREQS_NUM_MAX, TEST_POWER_LCORE_ID); return -1; } /** * test with an invalid freq index which is right one bigger than * total number of freqs */ ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num); if (ret >= 0) { printf("Unexpectedly set an invalid freq index (%u)" "successfully on lcore %u\n", total_freq_num, TEST_POWER_LCORE_ID); return -1; } ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num - 1); if (ret < 0) { printf("Fail to set freq index on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1); if (ret < 0) return -1; return 0; } /* Check rte_power_freq_down() */ static int check_power_freq_down(void) { int ret; /* test with an invalid lcore id */ ret = rte_power_freq_down(TEST_POWER_LCORE_INVALID); if (ret >= 0) { printf("Unexpectedly scale down successfully the freq on " "lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } /* Scale down to min and then scale down one step */ ret = rte_power_freq_min(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale down the freq to min on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } ret = rte_power_freq_down(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale down the freq on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1); if (ret < 0) return -1; /* Scale up to max and then scale down one step */ ret = rte_power_freq_max(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale up the freq to max on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } ret = rte_power_freq_down(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale down the freq on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, 1); if (ret < 0) return -1; return 0; } /* Check rte_power_freq_up() */ static int check_power_freq_up(void) { int ret; /* test with an invalid lcore id */ ret = rte_power_freq_up(TEST_POWER_LCORE_INVALID); if (ret >= 0) { printf("Unexpectedly scale up successfully the freq on %u\n", TEST_POWER_LCORE_INVALID); return -1; } /* Scale down to min and then scale up one step */ ret = rte_power_freq_min(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale down the freq to min on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } ret = rte_power_freq_up(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale up the freq on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 2); if (ret < 0) return -1; /* Scale up to max and then scale up one step */ ret = rte_power_freq_max(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale up the freq to max on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } ret = rte_power_freq_up(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale up the freq on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, 0); if (ret < 0) return -1; return 0; } /* Check rte_power_freq_max() */ static int check_power_freq_max(void) { int ret; /* test with an invalid lcore id */ ret = rte_power_freq_max(TEST_POWER_LCORE_INVALID); if (ret >= 0) { printf("Unexpectedly scale up successfully the freq to max on " "lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } ret = rte_power_freq_max(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale up the freq to max on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, 0); if (ret < 0) return -1; return 0; } /* Check rte_power_freq_min() */ static int check_power_freq_min(void) { int ret; /* test with an invalid lcore id */ ret = rte_power_freq_min(TEST_POWER_LCORE_INVALID); if (ret >= 0) { printf("Unexpectedly scale down successfully the freq to min " "on lcore %u\n", TEST_POWER_LCORE_INVALID); return -1; } ret = rte_power_freq_min(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Fail to scale down the freq to min on lcore %u\n", TEST_POWER_LCORE_ID); return -1; } /* Check the current frequency */ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1); if (ret < 0) return -1; return 0; } static int test_power_acpi_cpufreq(void) { int ret = -1; enum power_management_env env; ret = rte_power_set_env(PM_ENV_ACPI_CPUFREQ); if (ret != 0) { printf("Failed on setting environment to PM_ENV_ACPI_CPUFREQ, this " "may occur if environment is not configured correctly or " " operating in another valid Power management environment\n"); return -1; } /* Test environment configuration */ env = rte_power_get_env(); if (env != PM_ENV_ACPI_CPUFREQ) { printf("Unexpectedly got an environment other than ACPI cpufreq\n"); goto fail_all; } /* verify that function pointers are not NULL */ if (rte_power_freqs == NULL) { printf("rte_power_freqs should not be NULL, environment has not been " "initialised\n"); goto fail_all; } if (rte_power_get_freq == NULL) { printf("rte_power_get_freq should not be NULL, environment has not " "been initialised\n"); goto fail_all; } if (rte_power_set_freq == NULL) { printf("rte_power_set_freq should not be NULL, environment has not " "been initialised\n"); goto fail_all; } if (rte_power_freq_up == NULL) { printf("rte_power_freq_up should not be NULL, environment has not " "been initialised\n"); goto fail_all; } if (rte_power_freq_down == NULL) { printf("rte_power_freq_down should not be NULL, environment has not " "been initialised\n"); goto fail_all; } if (rte_power_freq_max == NULL) { printf("rte_power_freq_max should not be NULL, environment has not " "been initialised\n"); goto fail_all; } if (rte_power_freq_min == NULL) { printf("rte_power_freq_min should not be NULL, environment has not " "been initialised\n"); goto fail_all; } /* test of init power management for an invalid lcore */ ret = rte_power_init(TEST_POWER_LCORE_INVALID); if (ret == 0) { printf("Unexpectedly initialise power management successfully " "for lcore %u\n", TEST_POWER_LCORE_INVALID); rte_power_unset_env(); return -1; } /* Test initialisation of a valid lcore */ ret = rte_power_init(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Cannot initialise power management for lcore %u, this " "may occur if environment is not configured " "correctly(APCI cpufreq) or operating in another valid " "Power management environment\n", TEST_POWER_LCORE_ID); rte_power_unset_env(); return -1; } /** * test of initialising power management for the lcore which has * been initialised */ ret = rte_power_init(TEST_POWER_LCORE_ID); if (ret == 0) { printf("Unexpectedly init successfully power twice on " "lcore %u\n", TEST_POWER_LCORE_ID); goto fail_all; } ret = check_power_freqs(); if (ret < 0) goto fail_all; if (total_freq_num < 2) { rte_power_exit(TEST_POWER_LCORE_ID); printf("Frequency can not be changed due to CPU itself\n"); rte_power_unset_env(); return 0; } ret = check_power_get_freq(); if (ret < 0) goto fail_all; ret = check_power_set_freq(); if (ret < 0) goto fail_all; ret = check_power_freq_down(); if (ret < 0) goto fail_all; ret = check_power_freq_up(); if (ret < 0) goto fail_all; ret = check_power_freq_max(); if (ret < 0) goto fail_all; ret = check_power_freq_min(); if (ret < 0) goto fail_all; ret = rte_power_exit(TEST_POWER_LCORE_ID); if (ret < 0) { printf("Cannot exit power management for lcore %u\n", TEST_POWER_LCORE_ID); rte_power_unset_env(); return -1; } /** * test of exiting power management for the lcore which has been exited */ ret = rte_power_exit(TEST_POWER_LCORE_ID); if (ret == 0) { printf("Unexpectedly exit successfully power management twice " "on lcore %u\n", TEST_POWER_LCORE_ID); rte_power_unset_env(); return -1; } /* test of exit power management for an invalid lcore */ ret = rte_power_exit(TEST_POWER_LCORE_INVALID); if (ret == 0) { printf("Unpectedly exit power management successfully for " "lcore %u\n", TEST_POWER_LCORE_INVALID); rte_power_unset_env(); return -1; } rte_power_unset_env(); return 0; fail_all: rte_power_exit(TEST_POWER_LCORE_ID); rte_power_unset_env(); return -1; } static struct test_command power_acpi_cpufreq_cmd = { .command = "power_acpi_cpufreq_autotest", .callback = test_power_acpi_cpufreq, }; REGISTER_TEST_COMMAND(power_acpi_cpufreq_cmd); ================================================ FILE: app/test/test_power_kvm_vm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" #include #include #define TEST_POWER_VM_LCORE_ID 0U #define TEST_POWER_VM_LCORE_OUT_OF_BOUNDS (RTE_MAX_LCORE+1) #define TEST_POWER_VM_LCORE_INVALID 1U static int test_power_kvm_vm(void) { int ret; enum power_management_env env; ret = rte_power_set_env(PM_ENV_KVM_VM); if (ret != 0) { printf("Failed on setting environment to PM_ENV_KVM_VM\n"); return -1; } /* Test environment configuration */ env = rte_power_get_env(); if (env != PM_ENV_KVM_VM) { printf("Unexpectedly got a Power Management environment other than " "KVM VM\n"); rte_power_unset_env(); return -1; } /* verify that function pointers are not NULL */ if (rte_power_freqs == NULL) { printf("rte_power_freqs should not be NULL, environment has not been " "initialised\n"); return -1; } if (rte_power_get_freq == NULL) { printf("rte_power_get_freq should not be NULL, environment has not " "been initialised\n"); return -1; } if (rte_power_set_freq == NULL) { printf("rte_power_set_freq should not be NULL, environment has not " "been initialised\n"); return -1; } if (rte_power_freq_up == NULL) { printf("rte_power_freq_up should not be NULL, environment has not " "been initialised\n"); return -1; } if (rte_power_freq_down == NULL) { printf("rte_power_freq_down should not be NULL, environment has not " "been initialised\n"); return -1; } if (rte_power_freq_max == NULL) { printf("rte_power_freq_max should not be NULL, environment has not " "been initialised\n"); return -1; } if (rte_power_freq_min == NULL) { printf("rte_power_freq_min should not be NULL, environment has not " "been initialised\n"); return -1; } /* Test initialisation of an out of bounds lcore */ ret = rte_power_init(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); if (ret != -1) { printf("rte_power_init unexpectedly succeeded on an invalid lcore %u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); rte_power_unset_env(); return -1; } /* Test initialisation of a valid lcore */ ret = rte_power_init(TEST_POWER_VM_LCORE_ID); if (ret < 0) { printf("Cannot initialise power management for lcore %u, this " "may occur if environment is not configured " "correctly(KVM VM) or operating in another valid " "Power management environment\n", TEST_POWER_VM_LCORE_ID); rte_power_unset_env(); return -1; } /* Test initialisation of previously initialised lcore */ ret = rte_power_init(TEST_POWER_VM_LCORE_ID); if (ret == 0) { printf("rte_power_init unexpectedly succeeded on calling init twice on" " lcore %u\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test frequency up of invalid lcore */ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); if (ret == 1) { printf("rte_power_freq_up unexpectedly succeeded on invalid lcore %u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); goto fail_all; } /* Test frequency down of invalid lcore */ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); if (ret == 1) { printf("rte_power_freq_down unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); goto fail_all; } /* Test frequency min of invalid lcore */ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); if (ret == 1) { printf("rte_power_freq_min unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); goto fail_all; } /* Test frequency max of invalid lcore */ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); if (ret == 1) { printf("rte_power_freq_max unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS); goto fail_all; } /* Test frequency up of valid but uninitialised lcore */ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_INVALID); if (ret == 1) { printf("rte_power_freq_up unexpectedly succeeded on invalid lcore %u\n", TEST_POWER_VM_LCORE_INVALID); goto fail_all; } /* Test frequency down of valid but uninitialised lcore */ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_INVALID); if (ret == 1) { printf("rte_power_freq_down unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_INVALID); goto fail_all; } /* Test frequency min of valid but uninitialised lcore */ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_INVALID); if (ret == 1) { printf("rte_power_freq_min unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_INVALID); goto fail_all; } /* Test frequency max of valid but uninitialised lcore */ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_INVALID); if (ret == 1) { printf("rte_power_freq_max unexpectedly succeeded on invalid lcore " "%u\n", TEST_POWER_VM_LCORE_INVALID); goto fail_all; } /* Test frequency up of valid lcore */ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_ID); if (ret != 1) { printf("rte_power_freq_up unexpectedly failed on valid lcore %u\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test frequency down of valid lcore */ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_ID); if (ret != 1) { printf("rte_power_freq_down unexpectedly failed on valid lcore " "%u\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test frequency min of valid lcore */ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_ID); if (ret != 1) { printf("rte_power_freq_min unexpectedly failed on valid lcore " "%u\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test frequency max of valid lcore */ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_ID); if (ret != 1) { printf("rte_power_freq_max unexpectedly failed on valid lcore " "%u\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test unsupported rte_power_freqs */ ret = rte_power_freqs(TEST_POWER_VM_LCORE_ID, NULL, 0); if (ret != -ENOTSUP) { printf("rte_power_freqs did not return the expected -ENOTSUP(%d) but " "returned %d\n", -ENOTSUP, ret); goto fail_all; } /* Test unsupported rte_power_get_freq */ ret = rte_power_get_freq(TEST_POWER_VM_LCORE_ID); if (ret != -ENOTSUP) { printf("rte_power_get_freq did not return the expected -ENOTSUP(%d) but" " returned %d for lcore %u\n", -ENOTSUP, ret, TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test unsupported rte_power_set_freq */ ret = rte_power_set_freq(TEST_POWER_VM_LCORE_ID, 0); if (ret != -ENOTSUP) { printf("rte_power_set_freq did not return the expected -ENOTSUP(%d) but" " returned %d for lcore %u\n", -ENOTSUP, ret, TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test removing of an lcore */ ret = rte_power_exit(TEST_POWER_VM_LCORE_ID); if (ret != 0) { printf("rte_power_exit unexpectedly failed on valid lcore %u," "please ensure that the environment has been configured " "correctly\n", TEST_POWER_VM_LCORE_ID); goto fail_all; } /* Test frequency up of previously removed lcore */ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_ID); if (ret == 0) { printf("rte_power_freq_up unexpectedly succeeded on a removed " "lcore %u\n", TEST_POWER_VM_LCORE_ID); return -1; } /* Test frequency down of previously removed lcore */ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_ID); if (ret == 0) { printf("rte_power_freq_down unexpectedly succeeded on a removed " "lcore %u\n", TEST_POWER_VM_LCORE_ID); return -1; } /* Test frequency min of previously removed lcore */ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_ID); if (ret == 0) { printf("rte_power_freq_min unexpectedly succeeded on a removed " "lcore %u\n", TEST_POWER_VM_LCORE_ID); return -1; } /* Test frequency max of previously removed lcore */ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_ID); if (ret == 0) { printf("rte_power_freq_max unexpectedly succeeded on a removed " "lcore %u\n", TEST_POWER_VM_LCORE_ID); return -1; } rte_power_unset_env(); return 0; fail_all: rte_power_exit(TEST_POWER_VM_LCORE_ID); rte_power_unset_env(); return -1; } static struct test_command power_kvm_vm_cmd = { .command = "power_kvm_vm_autotest", .callback = test_power_kvm_vm, }; REGISTER_TEST_COMMAND(power_kvm_vm_cmd); ================================================ FILE: app/test/test_prefetch.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "test.h" /* * Prefetch test * ============= * * - Just test that the macro can be called and validate the compilation. * The test always return success. */ static int test_prefetch(void) { int a; rte_prefetch0(&a); rte_prefetch1(&a); rte_prefetch2(&a); return 0; } static struct test_command prefetch_cmd = { .command = "prefetch_autotest", .callback = test_prefetch, }; REGISTER_TEST_COMMAND(prefetch_cmd); ================================================ FILE: app/test/test_red.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "test.h" #include #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* conversion may lose significant bits */ #pragma warning(disable:181) /* Arg incompatible with format string */ #endif #define TEST_HZ_PER_KHZ 1000 #define TEST_NSEC_MARGIN 500 /**< nanosecond margin when calculating clk freq */ #define MAX_QEMPTY_TIME_MSEC 50000 #define MSEC_PER_SEC 1000 /**< Milli-seconds per second */ #define USEC_PER_MSEC 1000 /**< Micro-seconds per milli-second */ #define USEC_PER_SEC 1000000 /**< Micro-seconds per second */ /**< structures for testing rte_red performance and function */ struct test_rte_red_config { /**< Test structure for RTE_RED config */ struct rte_red_config *rconfig; /**< RTE_RED configuration parameters */ uint8_t num_cfg; /**< Number of RTE_RED configs to test */ uint8_t *wq_log2; /**< Test wq_log2 value to use */ uint32_t min_th; /**< Queue minimum threshold */ uint32_t max_th; /**< Queue maximum threshold */ uint8_t *maxp_inv; /**< Inverse mark probability */ }; struct test_queue { /**< Test structure for RTE_RED Queues */ struct rte_red *rdata; /**< RTE_RED runtime data */ uint32_t num_queues; /**< Number of RTE_RED queues to test */ uint32_t *qconfig; /**< Configuration of RTE_RED queues for test */ uint32_t *q; /**< Queue size */ uint32_t q_ramp_up; /**< Num of enqueues to ramp up the queue */ uint32_t avg_ramp_up; /**< Average num of enqueues to ramp up the queue */ uint32_t avg_tolerance; /**< Tolerance in queue average */ double drop_tolerance; /**< Drop tolerance of packets not enqueued */ }; struct test_var { /**< Test variables used for testing RTE_RED */ uint32_t wait_usec; /**< Micro second wait interval */ uint32_t num_iterations; /**< Number of test iterations */ uint32_t num_ops; /**< Number of test operations */ uint64_t clk_freq; /**< CPU clock frequency */ uint32_t sleep_sec; /**< Seconds to sleep */ uint32_t *dropped; /**< Test operations dropped */ uint32_t *enqueued; /**< Test operations enqueued */ }; struct test_config { /**< Master test structure for RTE_RED */ const char *ifname; /**< Interface name */ const char *msg; /**< Test message for display */ const char *htxt; /**< Header txt display for result output */ struct test_rte_red_config *tconfig; /**< Test structure for RTE_RED config */ struct test_queue *tqueue; /**< Test structure for RTE_RED Queues */ struct test_var *tvar; /**< Test variables used for testing RTE_RED */ uint32_t *tlevel; /**< Queue levels */ }; enum test_result { FAIL = 0, PASS }; /**< Test structure to define tests to run */ struct tests { struct test_config *testcfg; enum test_result (*testfn)(struct test_config *); }; struct rdtsc_prof { uint64_t clk_start; uint64_t clk_min; /**< min clocks */ uint64_t clk_max; /**< max clocks */ uint64_t clk_avgc; /**< count to calc average */ double clk_avg; /**< cumulative sum to calc average */ const char *name; }; static const uint64_t port_speed_bytes = (10ULL*1000ULL*1000ULL*1000ULL)/8ULL; static double inv_cycles_per_byte = 0; static double pkt_time_usec = 0; static void init_port_ts(uint64_t cpu_clock) { double cycles_per_byte = (double)(cpu_clock) / (double)(port_speed_bytes); inv_cycles_per_byte = 1.0 / cycles_per_byte; pkt_time_usec = 1000000.0 / ((double)port_speed_bytes / (double)RTE_RED_S); } static uint64_t get_port_ts(void) { return (uint64_t)((double)rte_rdtsc() * inv_cycles_per_byte); } static void rdtsc_prof_init(struct rdtsc_prof *p, const char *name) { p->clk_min = (uint64_t)(-1LL); p->clk_max = 0; p->clk_avg = 0; p->clk_avgc = 0; p->name = name; } static inline void rdtsc_prof_start(struct rdtsc_prof *p) { #ifdef __PIC__ asm volatile ( "mov %%ebx, %%edi\n" "cpuid\n" "xchgl %%ebx, %%edi;\n" : : : "%eax", "%edi", "%ecx", "%edx" ); #else asm( "cpuid" : : : "%eax", "%ebx", "%ecx", "%edx" ); #endif p->clk_start = rte_rdtsc(); } static inline void rdtsc_prof_end(struct rdtsc_prof *p) { uint64_t clk_start = rte_rdtsc() - p->clk_start; p->clk_avgc++; p->clk_avg += (double) clk_start; if (clk_start > p->clk_max) p->clk_max = clk_start; if (clk_start < p->clk_min) p->clk_min = clk_start; } static void rdtsc_prof_print(struct rdtsc_prof *p) { if (p->clk_avgc>0) { printf("RDTSC stats for %s: n=%" PRIu64 ", min=%" PRIu64 ", max=%" PRIu64 ", avg=%.1f\n", p->name, p->clk_avgc, p->clk_min, p->clk_max, (p->clk_avg / ((double) p->clk_avgc))); } } static uint32_t rte_red_get_avg_int(const struct rte_red_config *red_cfg, struct rte_red *red) { /** * scale by 1/n and convert from fixed-point to integer */ return red->avg >> (RTE_RED_SCALING + red_cfg->wq_log2); } static double rte_red_get_avg_float(const struct rte_red_config *red_cfg, struct rte_red *red) { /** * scale by 1/n and convert from fixed-point to floating-point */ return ldexp((double)red->avg, -(RTE_RED_SCALING + red_cfg->wq_log2)); } static void rte_red_set_avg_int(const struct rte_red_config *red_cfg, struct rte_red *red, uint32_t avg) { /** * scale by n and convert from integer to fixed-point */ red->avg = avg << (RTE_RED_SCALING + red_cfg->wq_log2); } static double calc_exp_avg_on_empty(double avg, uint32_t n, uint32_t time_diff) { return avg * pow((1.0 - 1.0 / (double)n), (double)time_diff / pkt_time_usec); } static double calc_drop_rate(uint32_t enqueued, uint32_t dropped) { return (double)dropped / ((double)enqueued + (double)dropped); } /** * calculate the drop probability */ static double calc_drop_prob(uint32_t min_th, uint32_t max_th, uint32_t maxp_inv, uint32_t avg) { double drop_prob = 0.0; if (avg < min_th) { drop_prob = 0.0; } else if (avg < max_th) { drop_prob = (1.0 / (double)maxp_inv) * ((double)(avg - min_th) / (double)(max_th - min_th)); } else { drop_prob = 1.0; } return (drop_prob); } /** * check if drop rate matches drop probability within tolerance */ static int check_drop_rate(double *diff, double drop_rate, double drop_prob, double tolerance) { double abs_diff = 0.0; int ret = 1; abs_diff = fabs(drop_rate - drop_prob); if ((int)abs_diff == 0) { *diff = 0.0; } else { *diff = (abs_diff / drop_prob) * 100.0; if (*diff > tolerance) { ret = 0; } } return (ret); } /** * check if average queue size is within tolerance */ static int check_avg(double *diff, double avg, double exp_avg, double tolerance) { double abs_diff = 0.0; int ret = 1; abs_diff = fabs(avg - exp_avg); if ((int)abs_diff == 0) { *diff = 0.0; } else { *diff = (abs_diff / exp_avg) * 100.0; if (*diff > tolerance) { ret = 0; } } return (ret); } /** * get the clk frequency in Hz */ static uint64_t get_machclk_freq(void) { uint64_t start = 0; uint64_t end = 0; uint64_t diff = 0; uint64_t clk_freq_hz = 0; struct timespec tv_start = {0, 0}, tv_end = {0, 0}; struct timespec req = {0, 0}; req.tv_sec = 1; req.tv_nsec = 0; clock_gettime(CLOCK_REALTIME, &tv_start); start = rte_rdtsc(); if (nanosleep(&req, NULL) != 0) { perror("get_machclk_freq()"); exit(EXIT_FAILURE); } clock_gettime(CLOCK_REALTIME, &tv_end); end = rte_rdtsc(); diff = (uint64_t)(tv_end.tv_sec - tv_start.tv_sec) * USEC_PER_SEC + ((tv_end.tv_nsec - tv_start.tv_nsec + TEST_NSEC_MARGIN) / USEC_PER_MSEC); /**< diff is in micro secs */ if (diff == 0) return(0); clk_freq_hz = ((end - start) * USEC_PER_SEC / diff); return (clk_freq_hz); } /** * initialize the test rte_red config */ static enum test_result test_rte_red_init(struct test_config *tcfg) { unsigned i = 0; tcfg->tvar->clk_freq = get_machclk_freq(); init_port_ts( tcfg->tvar->clk_freq ); for (i = 0; i < tcfg->tconfig->num_cfg; i++) { if (rte_red_config_init(&tcfg->tconfig->rconfig[i], (uint16_t)tcfg->tconfig->wq_log2[i], (uint16_t)tcfg->tconfig->min_th, (uint16_t)tcfg->tconfig->max_th, (uint16_t)tcfg->tconfig->maxp_inv[i]) != 0) { return(FAIL); } } *tcfg->tqueue->q = 0; *tcfg->tvar->dropped = 0; *tcfg->tvar->enqueued = 0; return(PASS); } /** * enqueue until actual queue size reaches target level */ static int increase_actual_qsize(struct rte_red_config *red_cfg, struct rte_red *red, uint32_t *q, uint32_t level, uint32_t attempts) { uint32_t i = 0; for (i = 0; i < attempts; i++) { int ret = 0; /** * enqueue */ ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts() ); if (ret == 0) { if (++(*q) >= level) break; } } /** * check if target actual queue size has been reached */ if (*q != level) return (-1); /** * success */ return (0); } /** * enqueue until average queue size reaches target level */ static int increase_average_qsize(struct rte_red_config *red_cfg, struct rte_red *red, uint32_t *q, uint32_t level, uint32_t num_ops) { uint32_t avg = 0; uint32_t i = 0; for (i = 0; i < num_ops; i++) { /** * enqueue */ rte_red_enqueue(red_cfg, red, *q, get_port_ts()); } /** * check if target average queue size has been reached */ avg = rte_red_get_avg_int(red_cfg, red); if (avg != level) return (-1); /** * success */ return (0); } /** * setup default values for the functional test structures */ static struct rte_red_config ft_wrconfig[1]; static struct rte_red ft_rtdata[1]; static uint8_t ft_wq_log2[] = {9}; static uint8_t ft_maxp_inv[] = {10}; static uint32_t ft_qconfig[] = {0, 0, 1, 1}; static uint32_t ft_q[] ={0}; static uint32_t ft_dropped[] ={0}; static uint32_t ft_enqueued[] ={0}; static struct test_rte_red_config ft_tconfig = { .rconfig = ft_wrconfig, .num_cfg = RTE_DIM(ft_wrconfig), .wq_log2 = ft_wq_log2, .min_th = 32, .max_th = 128, .maxp_inv = ft_maxp_inv, }; static struct test_queue ft_tqueue = { .rdata = ft_rtdata, .num_queues = RTE_DIM(ft_rtdata), .qconfig = ft_qconfig, .q = ft_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 5, /* 5 percent */ .drop_tolerance = 50, /* 50 percent */ }; static struct test_var ft_tvar = { .wait_usec = 250000, .num_iterations = 20, .num_ops = 10000, .clk_freq = 0, .dropped = ft_dropped, .enqueued = ft_enqueued, .sleep_sec = (MAX_QEMPTY_TIME_MSEC / MSEC_PER_SEC) + 2, }; /** * functional test enqueue/dequeue packets */ static void enqueue_dequeue_func(struct rte_red_config *red_cfg, struct rte_red *red, uint32_t *q, uint32_t num_ops, uint32_t *enqueued, uint32_t *dropped) { uint32_t i = 0; for (i = 0; i < num_ops; i++) { int ret = 0; /** * enqueue */ ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts()); if (ret == 0) (*enqueued)++; else (*dropped)++; } } /** * Test F1: functional test 1 */ static uint32_t ft1_tlevels[] = {6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144}; static struct test_config func_test1_config = { .ifname = "functional test 1 interface", .msg = "functional test 1 : use one rte_red configuration,\n" " increase average queue size to various levels,\n" " compare drop rate to drop probability\n\n", .htxt = " " "avg queue size " "enqueued " "dropped " "drop prob % " "drop rate % " "diff % " "tolerance % " "\n", .tconfig = &ft_tconfig, .tqueue = &ft_tqueue, .tvar = &ft_tvar, .tlevel = ft1_tlevels, }; static enum test_result func_test1(struct test_config *tcfg) { enum test_result result = PASS; uint32_t i = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (i = 0; i < RTE_DIM(ft1_tlevels); i++) { const char *label = NULL; uint32_t avg = 0; double drop_rate = 0.0; double drop_prob = 0.0; double diff = 0.0; /** * reset rte_red run-time data */ rte_red_rt_data_init(tcfg->tqueue->rdata); *tcfg->tvar->enqueued = 0; *tcfg->tvar->dropped = 0; if (increase_actual_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, tcfg->tlevel[i], tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, tcfg->tlevel[i], tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } enqueue_dequeue_func(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, tcfg->tvar->num_ops, tcfg->tvar->enqueued, tcfg->tvar->dropped); avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if (avg != tcfg->tlevel[i]) { fprintf(stderr, "Fail: avg != level\n"); result = FAIL; } drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, *tcfg->tconfig->maxp_inv, tcfg->tlevel[i]); if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) result = FAIL; if (tcfg->tlevel[i] == tcfg->tconfig->min_th) label = "min thresh: "; else if (tcfg->tlevel[i] == tcfg->tconfig->max_th) label = "max thresh: "; else label = " "; printf("%s%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", label, avg, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, drop_prob * 100.0, drop_rate * 100.0, diff, (double)tcfg->tqueue->drop_tolerance); } out: return (result); } /** * Test F2: functional test 2 */ static uint32_t ft2_tlevel[] = {127}; static uint8_t ft2_wq_log2[] = {9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; static uint8_t ft2_maxp_inv[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; static struct rte_red_config ft2_rconfig[10]; static struct test_rte_red_config ft2_tconfig = { .rconfig = ft2_rconfig, .num_cfg = RTE_DIM(ft2_rconfig), .wq_log2 = ft2_wq_log2, .min_th = 32, .max_th = 128, .maxp_inv = ft2_maxp_inv, }; static struct test_config func_test2_config = { .ifname = "functional test 2 interface", .msg = "functional test 2 : use several RED configurations,\n" " increase average queue size to just below maximum threshold,\n" " compare drop rate to drop probability\n\n", .htxt = "RED config " "avg queue size " "min threshold " "max threshold " "drop prob % " "drop rate % " "diff % " "tolerance % " "\n", .tconfig = &ft2_tconfig, .tqueue = &ft_tqueue, .tvar = &ft_tvar, .tlevel = ft2_tlevel, }; static enum test_result func_test2(struct test_config *tcfg) { enum test_result result = PASS; double prev_drop_rate = 1.0; uint32_t i = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } rte_red_rt_data_init(tcfg->tqueue->rdata); if (increase_actual_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (i = 0; i < tcfg->tconfig->num_cfg; i++) { uint32_t avg = 0; double drop_rate = 0.0; double drop_prob = 0.0; double diff = 0.0; *tcfg->tvar->dropped = 0; *tcfg->tvar->enqueued = 0; enqueue_dequeue_func(&tcfg->tconfig->rconfig[i], tcfg->tqueue->rdata, tcfg->tqueue->q, tcfg->tvar->num_ops, tcfg->tvar->enqueued, tcfg->tvar->dropped); avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[i], tcfg->tqueue->rdata); if (avg != *tcfg->tlevel) result = FAIL; drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, tcfg->tconfig->maxp_inv[i], *tcfg->tlevel); if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) result = FAIL; /** * drop rate should decrease as maxp_inv increases */ if (drop_rate > prev_drop_rate) result = FAIL; prev_drop_rate = drop_rate; printf("%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", i, avg, tcfg->tconfig->min_th, tcfg->tconfig->max_th, drop_prob * 100.0, drop_rate * 100.0, diff, (double)tcfg->tqueue->drop_tolerance); } out: return (result); } /** * Test F3: functional test 3 */ static uint32_t ft3_tlevel[] = {1022}; static struct test_rte_red_config ft3_tconfig = { .rconfig = ft_wrconfig, .num_cfg = RTE_DIM(ft_wrconfig), .wq_log2 = ft_wq_log2, .min_th = 32, .max_th = 1023, .maxp_inv = ft_maxp_inv, }; static struct test_config func_test3_config = { .ifname = "functional test 3 interface", .msg = "functional test 3 : use one RED configuration,\n" " increase average queue size to target level,\n" " dequeue all packets until queue is empty,\n" " confirm that average queue size is computed correctly while queue is empty\n\n", .htxt = "q avg before " "q avg after " "expected " "difference % " "tolerance % " "result " "\n", .tconfig = &ft3_tconfig, .tqueue = &ft_tqueue, .tvar = &ft_tvar, .tlevel = ft3_tlevel, }; static enum test_result func_test3(struct test_config *tcfg) { enum test_result result = PASS; uint32_t i = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } rte_red_rt_data_init(tcfg->tqueue->rdata); if (increase_actual_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (i = 0; i < tcfg->tvar->num_iterations; i++) { double avg_before = 0; double avg_after = 0; double exp_avg = 0; double diff = 0.0; avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); /** * empty the queue */ *tcfg->tqueue->q = 0; rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); rte_delay_us(tcfg->tvar->wait_usec); /** * enqueue one packet to recalculate average queue size */ if (rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tqueue->q, get_port_ts()) == 0) { (*tcfg->tqueue->q)++; } else { printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__); result = FAIL; } exp_avg = calc_exp_avg_on_empty(avg_before, (1 << *tcfg->tconfig->wq_log2), tcfg->tvar->wait_usec); avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) result = FAIL; printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", avg_before, avg_after, exp_avg, diff, (double)tcfg->tqueue->avg_tolerance, diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail"); } out: return (result); } /** * Test F4: functional test 4 */ static uint32_t ft4_tlevel[] = {1022}; static uint8_t ft4_wq_log2[] = {11}; static struct test_rte_red_config ft4_tconfig = { .rconfig = ft_wrconfig, .num_cfg = RTE_DIM(ft_wrconfig), .min_th = 32, .max_th = 1023, .wq_log2 = ft4_wq_log2, .maxp_inv = ft_maxp_inv, }; static struct test_queue ft4_tqueue = { .rdata = ft_rtdata, .num_queues = RTE_DIM(ft_rtdata), .qconfig = ft_qconfig, .q = ft_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 0, /* 0 percent */ .drop_tolerance = 50, /* 50 percent */ }; static struct test_config func_test4_config = { .ifname = "functional test 4 interface", .msg = "functional test 4 : use one RED configuration,\n" " increase average queue size to target level,\n" " dequeue all packets until queue is empty,\n" " confirm that average queue size is computed correctly while\n" " queue is empty for more than 50 sec,\n" " (this test takes 52 sec to run)\n\n", .htxt = "q avg before " "q avg after " "expected " "difference % " "tolerance % " "result " "\n", .tconfig = &ft4_tconfig, .tqueue = &ft4_tqueue, .tvar = &ft_tvar, .tlevel = ft4_tlevel, }; static enum test_result func_test4(struct test_config *tcfg) { enum test_result result = PASS; uint64_t time_diff = 0; uint64_t start = 0; double avg_before = 0.0; double avg_after = 0.0; double exp_avg = 0.0; double diff = 0.0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } rte_red_rt_data_init(tcfg->tqueue->rdata); if (increase_actual_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, *tcfg->tlevel, tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } printf("%s", tcfg->htxt); avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); /** * empty the queue */ *tcfg->tqueue->q = 0; rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); /** * record empty time locally */ start = rte_rdtsc(); sleep(tcfg->tvar->sleep_sec); /** * enqueue one packet to recalculate average queue size */ if (rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tqueue->q, get_port_ts()) != 0) { result = FAIL; goto out; } (*tcfg->tqueue->q)++; /** * calculate how long queue has been empty */ time_diff = ((rte_rdtsc() - start) / tcfg->tvar->clk_freq) * MSEC_PER_SEC; if (time_diff < MAX_QEMPTY_TIME_MSEC) { /** * this could happen if sleep was interrupted for some reason */ result = FAIL; goto out; } /** * confirm that average queue size is now at expected level */ exp_avg = 0.0; avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) result = FAIL; printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", avg_before, avg_after, exp_avg, diff, (double)tcfg->tqueue->avg_tolerance, diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail"); out: return (result); } /** * Test F5: functional test 5 */ static uint32_t ft5_tlevel[] = {127}; static uint8_t ft5_wq_log2[] = {9, 8}; static uint8_t ft5_maxp_inv[] = {10, 20}; static struct rte_red_config ft5_config[2]; static struct rte_red ft5_data[4]; static uint32_t ft5_q[4]; static uint32_t ft5_dropped[] = {0, 0, 0, 0}; static uint32_t ft5_enqueued[] = {0, 0, 0, 0}; static struct test_rte_red_config ft5_tconfig = { .rconfig = ft5_config, .num_cfg = RTE_DIM(ft5_config), .min_th = 32, .max_th = 128, .wq_log2 = ft5_wq_log2, .maxp_inv = ft5_maxp_inv, }; static struct test_queue ft5_tqueue = { .rdata = ft5_data, .num_queues = RTE_DIM(ft5_data), .qconfig = ft_qconfig, .q = ft5_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 5, /* 10 percent */ .drop_tolerance = 50, /* 50 percent */ }; struct test_var ft5_tvar = { .wait_usec = 0, .num_iterations = 15, .num_ops = 10000, .clk_freq = 0, .dropped = ft5_dropped, .enqueued = ft5_enqueued, .sleep_sec = 0, }; static struct test_config func_test5_config = { .ifname = "functional test 5 interface", .msg = "functional test 5 : use several queues (each with its own run-time data),\n" " use several RED configurations (such that each configuration is shared by multiple queues),\n" " increase average queue size to just below maximum threshold,\n" " compare drop rate to drop probability,\n" " (this is a larger scale version of functional test 2)\n\n", .htxt = "queue " "config " "avg queue size " "min threshold " "max threshold " "drop prob % " "drop rate % " "diff % " "tolerance % " "\n", .tconfig = &ft5_tconfig, .tqueue = &ft5_tqueue, .tvar = &ft5_tvar, .tlevel = ft5_tlevel, }; static enum test_result func_test5(struct test_config *tcfg) { enum test_result result = PASS; uint32_t j = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (j = 0; j < tcfg->tqueue->num_queues; j++) { rte_red_rt_data_init(&tcfg->tqueue->rdata[j]); tcfg->tqueue->q[j] = 0; if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], &tcfg->tqueue->q[j], *tcfg->tlevel, tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], &tcfg->tqueue->q[j], *tcfg->tlevel, tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } } for (j = 0; j < tcfg->tqueue->num_queues; j++) { uint32_t avg = 0; double drop_rate = 0.0; double drop_prob = 0.0; double diff = 0.0; tcfg->tvar->dropped[j] = 0; tcfg->tvar->enqueued[j] = 0; enqueue_dequeue_func(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], &tcfg->tqueue->q[j], tcfg->tvar->num_ops, &tcfg->tvar->enqueued[j], &tcfg->tvar->dropped[j]); avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j]); if (avg != *tcfg->tlevel) result = FAIL; drop_rate = calc_drop_rate(tcfg->tvar->enqueued[j],tcfg->tvar->dropped[j]); drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, tcfg->tconfig->maxp_inv[tcfg->tqueue->qconfig[j]], *tcfg->tlevel); if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) result = FAIL; printf("%-15u%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n", j, tcfg->tqueue->qconfig[j], avg, tcfg->tconfig->min_th, tcfg->tconfig->max_th, drop_prob * 100.0, drop_rate * 100.0, diff, (double)tcfg->tqueue->drop_tolerance); } out: return (result); } /** * Test F6: functional test 6 */ static uint32_t ft6_tlevel[] = {1022}; static uint8_t ft6_wq_log2[] = {9, 8}; static uint8_t ft6_maxp_inv[] = {10, 20}; static struct rte_red_config ft6_config[2]; static struct rte_red ft6_data[4]; static uint32_t ft6_q[4]; static struct test_rte_red_config ft6_tconfig = { .rconfig = ft6_config, .num_cfg = RTE_DIM(ft6_config), .min_th = 32, .max_th = 1023, .wq_log2 = ft6_wq_log2, .maxp_inv = ft6_maxp_inv, }; static struct test_queue ft6_tqueue = { .rdata = ft6_data, .num_queues = RTE_DIM(ft6_data), .qconfig = ft_qconfig, .q = ft6_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 5, /* 10 percent */ .drop_tolerance = 50, /* 50 percent */ }; static struct test_config func_test6_config = { .ifname = "functional test 6 interface", .msg = "functional test 6 : use several queues (each with its own run-time data),\n" " use several RED configurations (such that each configuration is sharte_red by multiple queues),\n" " increase average queue size to target level,\n" " dequeue all packets until queue is empty,\n" " confirm that average queue size is computed correctly while queue is empty\n" " (this is a larger scale version of functional test 3)\n\n", .htxt = "queue " "config " "q avg before " "q avg after " "expected " "difference % " "tolerance % " "result ""\n", .tconfig = &ft6_tconfig, .tqueue = &ft6_tqueue, .tvar = &ft_tvar, .tlevel = ft6_tlevel, }; static enum test_result func_test6(struct test_config *tcfg) { enum test_result result = PASS; uint32_t j = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (j = 0; j < tcfg->tqueue->num_queues; j++) { rte_red_rt_data_init(&tcfg->tqueue->rdata[j]); tcfg->tqueue->q[j] = 0; if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], &tcfg->tqueue->q[j], *tcfg->tlevel, tcfg->tqueue->q_ramp_up) != 0) { result = FAIL; goto out; } if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], &tcfg->tqueue->q[j], *tcfg->tlevel, tcfg->tqueue->avg_ramp_up) != 0) { result = FAIL; goto out; } } for (j = 0; j < tcfg->tqueue->num_queues; j++) { double avg_before = 0; double avg_after = 0; double exp_avg = 0; double diff = 0.0; avg_before = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j]); /** * empty the queue */ tcfg->tqueue->q[j] = 0; rte_red_mark_queue_empty(&tcfg->tqueue->rdata[j], get_port_ts()); rte_delay_us(tcfg->tvar->wait_usec); /** * enqueue one packet to recalculate average queue size */ if (rte_red_enqueue(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j], tcfg->tqueue->q[j], get_port_ts()) == 0) { tcfg->tqueue->q[j]++; } else { printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__); result = FAIL; } exp_avg = calc_exp_avg_on_empty(avg_before, (1 << tcfg->tconfig->wq_log2[tcfg->tqueue->qconfig[j]]), tcfg->tvar->wait_usec); avg_after = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]], &tcfg->tqueue->rdata[j]); if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) result = FAIL; printf("%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", j, tcfg->tqueue->qconfig[j], avg_before, avg_after, exp_avg, diff, (double)tcfg->tqueue->avg_tolerance, diff <= tcfg->tqueue->avg_tolerance ? "pass" : "fail"); } out: return (result); } /** * setup default values for the performance test structures */ static struct rte_red_config pt_wrconfig[1]; static struct rte_red pt_rtdata[1]; static uint8_t pt_wq_log2[] = {9}; static uint8_t pt_maxp_inv[] = {10}; static uint32_t pt_qconfig[] = {0}; static uint32_t pt_q[] = {0}; static uint32_t pt_dropped[] = {0}; static uint32_t pt_enqueued[] = {0}; static struct test_rte_red_config pt_tconfig = { .rconfig = pt_wrconfig, .num_cfg = RTE_DIM(pt_wrconfig), .wq_log2 = pt_wq_log2, .min_th = 32, .max_th = 128, .maxp_inv = pt_maxp_inv, }; static struct test_queue pt_tqueue = { .rdata = pt_rtdata, .num_queues = RTE_DIM(pt_rtdata), .qconfig = pt_qconfig, .q = pt_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 5, /* 10 percent */ .drop_tolerance = 50, /* 50 percent */ }; /** * enqueue/dequeue packets */ static void enqueue_dequeue_perf(struct rte_red_config *red_cfg, struct rte_red *red, uint32_t *q, uint32_t num_ops, uint32_t *enqueued, uint32_t *dropped, struct rdtsc_prof *prof) { uint32_t i = 0; for (i = 0; i < num_ops; i++) { uint64_t ts = 0; int ret = 0; /** * enqueue */ ts = get_port_ts(); rdtsc_prof_start(prof); ret = rte_red_enqueue(red_cfg, red, *q, ts ); rdtsc_prof_end(prof); if (ret == 0) (*enqueued)++; else (*dropped)++; } } /** * Setup test structures for tests P1, P2, P3 * performance tests 1, 2 and 3 */ static uint32_t pt1_tlevel[] = {16}; static uint32_t pt2_tlevel[] = {80}; static uint32_t pt3_tlevel[] = {144}; static struct test_var perf1_tvar = { .wait_usec = 0, .num_iterations = 15, .num_ops = 50000000, .clk_freq = 0, .dropped = pt_dropped, .enqueued = pt_enqueued, .sleep_sec = 0 }; static struct test_config perf1_test1_config = { .ifname = "performance test 1 interface", .msg = "performance test 1 : use one RED configuration,\n" " set actual and average queue sizes to level below min threshold,\n" " measure enqueue performance\n\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf1_tvar, .tlevel = pt1_tlevel, }; static struct test_config perf1_test2_config = { .ifname = "performance test 2 interface", .msg = "performance test 2 : use one RED configuration,\n" " set actual and average queue sizes to level in between min and max thresholds,\n" " measure enqueue performance\n\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf1_tvar, .tlevel = pt2_tlevel, }; static struct test_config perf1_test3_config = { .ifname = "performance test 3 interface", .msg = "performance test 3 : use one RED configuration,\n" " set actual and average queue sizes to level above max threshold,\n" " measure enqueue performance\n\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf1_tvar, .tlevel = pt3_tlevel, }; /** * Performance test function to measure enqueue performance. * This runs performance tests 1, 2 and 3 */ static enum test_result perf1_test(struct test_config *tcfg) { enum test_result result = PASS; struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; uint32_t total = 0; printf("%s", tcfg->msg); rdtsc_prof_init(&prof, "enqueue"); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } /** * set average queue size to target level */ *tcfg->tqueue->q = *tcfg->tlevel; /** * initialize the rte_red run time data structure */ rte_red_rt_data_init(tcfg->tqueue->rdata); /** * set the queue average */ rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel); if (rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata) != *tcfg->tlevel) { result = FAIL; goto out; } enqueue_dequeue_perf(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, tcfg->tqueue->q, tcfg->tvar->num_ops, tcfg->tvar->enqueued, tcfg->tvar->dropped, &prof); total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total, *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0, *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); rdtsc_prof_print(&prof); out: return (result); } /** * Setup test structures for tests P4, P5, P6 * performance tests 4, 5 and 6 */ static uint32_t pt4_tlevel[] = {16}; static uint32_t pt5_tlevel[] = {80}; static uint32_t pt6_tlevel[] = {144}; static struct test_var perf2_tvar = { .wait_usec = 500, .num_iterations = 10000, .num_ops = 10000, .dropped = pt_dropped, .enqueued = pt_enqueued, .sleep_sec = 0 }; static struct test_config perf2_test4_config = { .ifname = "performance test 4 interface", .msg = "performance test 4 : use one RED configuration,\n" " set actual and average queue sizes to level below min threshold,\n" " dequeue all packets until queue is empty,\n" " measure enqueue performance when queue is empty\n\n", .htxt = "iteration " "q avg before " "q avg after " "expected " "difference % " "tolerance % " "result ""\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf2_tvar, .tlevel = pt4_tlevel, }; static struct test_config perf2_test5_config = { .ifname = "performance test 5 interface", .msg = "performance test 5 : use one RED configuration,\n" " set actual and average queue sizes to level in between min and max thresholds,\n" " dequeue all packets until queue is empty,\n" " measure enqueue performance when queue is empty\n\n", .htxt = "iteration " "q avg before " "q avg after " "expected " "difference " "tolerance " "result ""\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf2_tvar, .tlevel = pt5_tlevel, }; static struct test_config perf2_test6_config = { .ifname = "performance test 6 interface", .msg = "performance test 6 : use one RED configuration,\n" " set actual and average queue sizes to level above max threshold,\n" " dequeue all packets until queue is empty,\n" " measure enqueue performance when queue is empty\n\n", .htxt = "iteration " "q avg before " "q avg after " "expected " "difference % " "tolerance % " "result ""\n", .tconfig = &pt_tconfig, .tqueue = &pt_tqueue, .tvar = &perf2_tvar, .tlevel = pt6_tlevel, }; /** * Performance test function to measure enqueue performance when the * queue is empty. This runs performance tests 4, 5 and 6 */ static enum test_result perf2_test(struct test_config *tcfg) { enum test_result result = PASS; struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL}; uint32_t total = 0; uint32_t i = 0; printf("%s", tcfg->msg); rdtsc_prof_init(&prof, "enqueue"); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } printf("%s", tcfg->htxt); for (i = 0; i < tcfg->tvar->num_iterations; i++) { uint32_t count = 0; uint64_t ts = 0; double avg_before = 0; int ret = 0; /** * set average queue size to target level */ *tcfg->tqueue->q = *tcfg->tlevel; count = (*tcfg->tqueue->rdata).count; /** * initialize the rte_red run time data structure */ rte_red_rt_data_init(tcfg->tqueue->rdata); (*tcfg->tqueue->rdata).count = count; /** * set the queue average */ rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel); avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if ((avg_before < *tcfg->tlevel) || (avg_before > *tcfg->tlevel)) { result = FAIL; goto out; } /** * empty the queue */ *tcfg->tqueue->q = 0; rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts()); /** * wait for specified period of time */ rte_delay_us(tcfg->tvar->wait_usec); /** * measure performance of enqueue operation while queue is empty */ ts = get_port_ts(); rdtsc_prof_start(&prof); ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tqueue->q, ts ); rdtsc_prof_end(&prof); /** * gather enqueued/dropped statistics */ if (ret == 0) (*tcfg->tvar->enqueued)++; else (*tcfg->tvar->dropped)++; /** * on first and last iteration, confirm that * average queue size was computed correctly */ if ((i == 0) || (i == tcfg->tvar->num_iterations - 1)) { double avg_after = 0; double exp_avg = 0; double diff = 0.0; int ok = 0; avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); exp_avg = calc_exp_avg_on_empty(avg_before, (1 << *tcfg->tconfig->wq_log2), tcfg->tvar->wait_usec); if (check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance)) ok = 1; printf("%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n", i, avg_before, avg_after, exp_avg, diff, (double)tcfg->tqueue->avg_tolerance, ok ? "pass" : "fail"); if (!ok) { result = FAIL; goto out; } } } total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped; printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total, *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0, *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0); rdtsc_prof_print(&prof); out: return (result); } /** * setup default values for overflow test structures */ static uint32_t avg_max = 0; static uint32_t avg_max_bits = 0; static struct rte_red_config ovfl_wrconfig[1]; static struct rte_red ovfl_rtdata[1]; static uint8_t ovfl_maxp_inv[] = {10}; static uint32_t ovfl_qconfig[] = {0, 0, 1, 1}; static uint32_t ovfl_q[] ={0}; static uint32_t ovfl_dropped[] ={0}; static uint32_t ovfl_enqueued[] ={0}; static uint32_t ovfl_tlevel[] = {1023}; static uint8_t ovfl_wq_log2[] = {12}; static struct test_rte_red_config ovfl_tconfig = { .rconfig = ovfl_wrconfig, .num_cfg = RTE_DIM(ovfl_wrconfig), .wq_log2 = ovfl_wq_log2, .min_th = 32, .max_th = 1023, .maxp_inv = ovfl_maxp_inv, }; static struct test_queue ovfl_tqueue = { .rdata = ovfl_rtdata, .num_queues = RTE_DIM(ovfl_rtdata), .qconfig = ovfl_qconfig, .q = ovfl_q, .q_ramp_up = 1000000, .avg_ramp_up = 1000000, .avg_tolerance = 5, /* 10 percent */ .drop_tolerance = 50, /* 50 percent */ }; static struct test_var ovfl_tvar = { .wait_usec = 10000, .num_iterations = 1, .num_ops = 10000, .clk_freq = 0, .dropped = ovfl_dropped, .enqueued = ovfl_enqueued, .sleep_sec = 0 }; static void ovfl_check_avg(uint32_t avg) { if (avg > avg_max) { double avg_log = 0; uint32_t bits = 0; avg_max = avg; avg_log = log(((double)avg_max)); avg_log = avg_log / log(2.0); bits = (uint32_t)ceil(avg_log); if (bits > avg_max_bits) avg_max_bits = bits; } } static struct test_config ovfl_test1_config = { .ifname = "queue avergage overflow test interface", .msg = "overflow test 1 : use one RED configuration,\n" " increase average queue size to target level,\n" " check maximum number of bits requirte_red to represent avg_s\n\n", .htxt = "avg queue size " "wq_log2 " "fraction bits " "max queue avg " "num bits " "enqueued " "dropped " "drop prob % " "drop rate % " "\n", .tconfig = &ovfl_tconfig, .tqueue = &ovfl_tqueue, .tvar = &ovfl_tvar, .tlevel = ovfl_tlevel, }; static enum test_result ovfl_test1(struct test_config *tcfg) { enum test_result result = PASS; uint32_t avg = 0; uint32_t i = 0; double drop_rate = 0.0; double drop_prob = 0.0; double diff = 0.0; int ret = 0; printf("%s", tcfg->msg); if (test_rte_red_init(tcfg) != PASS) { result = FAIL; goto out; } /** * reset rte_red run-time data */ rte_red_rt_data_init(tcfg->tqueue->rdata); /** * increase actual queue size */ for (i = 0; i < tcfg->tqueue->q_ramp_up; i++) { ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tqueue->q, get_port_ts()); if (ret == 0) { if (++(*tcfg->tqueue->q) >= *tcfg->tlevel) break; } } /** * enqueue */ for (i = 0; i < tcfg->tqueue->avg_ramp_up; i++) { ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tqueue->q, get_port_ts()); ovfl_check_avg((*tcfg->tqueue->rdata).avg); avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if (avg == *tcfg->tlevel) { if (ret == 0) (*tcfg->tvar->enqueued)++; else (*tcfg->tvar->dropped)++; } } /** * check if target average queue size has been reached */ avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata); if (avg != *tcfg->tlevel) { result = FAIL; goto out; } /** * check drop rate against drop probability */ drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped); drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th, *tcfg->tconfig->maxp_inv, *tcfg->tlevel); if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance)) result = FAIL; printf("%s", tcfg->htxt); printf("%-16u%-9u%-15u0x%08x %-10u%-10u%-10u%-13.2lf%-13.2lf\n", avg, *tcfg->tconfig->wq_log2, RTE_RED_SCALING, avg_max, avg_max_bits, *tcfg->tvar->enqueued, *tcfg->tvar->dropped, drop_prob * 100.0, drop_rate * 100.0); out: return (result); } /** * define the functional and performance tests to be executed */ struct tests func_tests[] = { { &func_test1_config, func_test1 }, { &func_test2_config, func_test2 }, { &func_test3_config, func_test3 }, { &func_test4_config, func_test4 }, { &func_test5_config, func_test5 }, { &func_test6_config, func_test6 }, { &ovfl_test1_config, ovfl_test1 }, }; struct tests perf_tests[] = { { &perf1_test1_config, perf1_test }, { &perf1_test2_config, perf1_test }, { &perf1_test3_config, perf1_test }, { &perf2_test4_config, perf2_test }, { &perf2_test5_config, perf2_test }, { &perf2_test6_config, perf2_test }, }; /** * function to execute the required_red tests */ static void run_tests(struct tests *test_type, uint32_t test_count, uint32_t *num_tests, uint32_t *num_pass) { enum test_result result = PASS; uint32_t i = 0; for (i = 0; i < test_count; i++) { printf("\n--------------------------------------------------------------------------------\n"); result = test_type[i].testfn(test_type[i].testcfg); (*num_tests)++; if (result == PASS) { (*num_pass)++; printf("--------------------------------------------------------------------------\n"); } else { printf("--------------------------------------------------------------------------\n"); } } return; } /** * check if functions accept invalid parameters * * First, all functions will be called without initialized RED * Then, all of them will be called with NULL/invalid parameters * * Some functions are not tested as they are performance-critical and thus * don't do any parameter checking. */ static int test_invalid_parameters(void) { struct rte_red_config config; if (rte_red_rt_data_init(NULL) == 0) { printf("rte_red_rt_data_init should have failed!\n"); return -1; } if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) { printf("rte_red_config_init should have failed!\n"); return -1; } if (rte_red_rt_data_init(NULL) == 0) { printf("rte_red_rt_data_init should have failed!\n"); return -1; } /* NULL config */ if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* min_treshold == max_treshold */ if (rte_red_config_init(&config, 0, 1, 1, 0) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* min_treshold > max_treshold */ if (rte_red_config_init(&config, 0, 2, 1, 0) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* wq_log2 > RTE_RED_WQ_LOG2_MAX */ if (rte_red_config_init(&config, RTE_RED_WQ_LOG2_MAX + 1, 1, 2, 0) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* wq_log2 < RTE_RED_WQ_LOG2_MIN */ if (rte_red_config_init(&config, RTE_RED_WQ_LOG2_MIN - 1, 1, 2, 0) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* maxp_inv > RTE_RED_MAXP_INV_MAX */ if (rte_red_config_init(&config, RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MAX + 1) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } /* maxp_inv < RTE_RED_MAXP_INV_MIN */ if (rte_red_config_init(&config, RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MIN - 1) == 0) { printf("%i: rte_red_config_init should have failed!\n", __LINE__); return -1; } return 0; } static int test_red(void) { uint32_t num_tests = 0; uint32_t num_pass = 0; int ret = 0; if (test_invalid_parameters() < 0) return -1; run_tests(func_tests, RTE_DIM(func_tests), &num_tests, &num_pass); run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass); if (num_pass == num_tests) { printf("[total: %u, pass: %u]\n", num_tests, num_pass); ret = 0; } else { printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass, num_tests - num_pass); ret = -1; } return (ret); } static struct test_command red_cmd = { .command = "red_autotest", .callback = test_red, }; REGISTER_TEST_COMMAND(red_cmd); ================================================ FILE: app/test/test_reorder.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include "stdio.h" #include #include #include #include #include #include #include #include #include "test.h" #define BURST 32 #define REORDER_BUFFER_SIZE 16384 #define NUM_MBUFS (2*REORDER_BUFFER_SIZE) #define REORDER_BUFFER_SIZE_INVALID 2049 struct reorder_unittest_params { struct rte_mempool *p; struct rte_reorder_buffer *b; }; static struct reorder_unittest_params default_params = { .p = NULL, .b = NULL }; static struct reorder_unittest_params *test_params = &default_params; static int test_reorder_create(void) { struct rte_reorder_buffer *b = NULL; b = rte_reorder_create(NULL, rte_socket_id(), REORDER_BUFFER_SIZE); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on create() with NULL name"); b = rte_reorder_create("PKT", rte_socket_id(), REORDER_BUFFER_SIZE_INVALID); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on create() with invalid buffer size param."); b = rte_reorder_create("PKT_RO1", rte_socket_id(), REORDER_BUFFER_SIZE); printf("DEBUG: b= %p, orig_b= %p\n", b, test_params->b); TEST_ASSERT_EQUAL(b, test_params->b, "New reorder instance created with already existing name"); return 0; } static int test_reorder_init(void) { struct rte_reorder_buffer *b = NULL; unsigned int size; /* * The minimum memory area size that should be passed to library is, * sizeof(struct rte_reorder_buffer) + (2 * size * sizeof(struct rte_mbuf *)); * Otherwise error will be thrown */ size = 100; b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on init with NULL buffer."); b = rte_malloc(NULL, size, 0); b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on init with invalid mem zone size."); rte_free(b); size = 262336; b = rte_malloc(NULL, size, 0); b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE_INVALID); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on init with invalid buffer size param."); b = rte_reorder_init(b, size, NULL, REORDER_BUFFER_SIZE); TEST_ASSERT((b == NULL) && (rte_errno == EINVAL), "No error on init with invalid name."); rte_free(b); return 0; } static int test_reorder_find_existing(void) { struct rte_reorder_buffer *b = NULL; /* Try to find existing reorder buffer instance */ b = rte_reorder_find_existing("PKT_RO1"); TEST_ASSERT_EQUAL(b, test_params->b, "existing reorder buffer instance not found"); /* Try to find non existing reorder buffer instance */ b = rte_reorder_find_existing("ro_find_non_existing"); TEST_ASSERT((b == NULL) && (rte_errno == ENOENT), "non existing reorder buffer instance found"); return 0; } static int test_reorder_free(void) { struct rte_reorder_buffer *b1 = NULL, *b2 = NULL; const char *name = "test_free"; b1 = rte_reorder_create(name, rte_socket_id(), 8); TEST_ASSERT_NOT_NULL(b1, "Failed to create reorder buffer."); b2 = rte_reorder_find_existing(name); TEST_ASSERT_EQUAL(b1, b2, "Failed to find existing reorder buffer"); rte_reorder_free(b1); b2 = rte_reorder_find_existing(name); TEST_ASSERT((b2 == NULL) && (rte_errno == ENOENT), "Found previously freed reorder buffer"); return 0; } static int test_reorder_insert(void) { struct rte_reorder_buffer *b = NULL; struct rte_mempool *p = test_params->p; const unsigned int size = 4; const unsigned int num_bufs = 6; struct rte_mbuf *bufs[num_bufs]; int ret = 0; unsigned i; /* This would create a reorder buffer instance consisting of: * reorder_seq = 0 * ready_buf: RB[size] = {NULL, NULL, NULL, NULL} * order_buf: OB[size] = {NULL, NULL, NULL, NULL} */ b = rte_reorder_create("test_insert", rte_socket_id(), size); TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer"); ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs); TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool"); /* late packet */ bufs[0]->seqn = 3 * size; ret = rte_reorder_insert(b, bufs[0]); if (!((ret == -1) && (rte_errno == ERANGE))) { printf("%s:%d: No error inserting late packet with seqn:" " 3 * size\n", __func__, __LINE__); ret = -1; goto exit; } for (i = 0; i < num_bufs; i++) bufs[i]->seqn = i; /* This should fill up order buffer: * reorder_seq = 0 * RB[] = {NULL, NULL, NULL, NULL} * OB[] = {0, 1, 2, 3} */ for (i = 0; i < size; i++) { ret = rte_reorder_insert(b, bufs[i]); if (ret != 0) { printf("%s:%d: Error inserting packet with seqn less than size\n", __func__, __LINE__); ret = -1; goto exit; } } /* early packet - should move mbufs to ready buf and move sequence window * reorder_seq = 4 * RB[] = {0, 1, 2, 3} * OB[] = {4, NULL, NULL, NULL} */ ret = rte_reorder_insert(b, bufs[4]); if (ret != 0) { printf("%s:%d: Error inserting early packet with seqn: size\n", __func__, __LINE__); ret = -1; goto exit; } /* early packet from current sequence window - full ready buffer */ bufs[5]->seqn = 2 * size; ret = rte_reorder_insert(b, bufs[5]); if (!((ret == -1) && (rte_errno == ENOSPC))) { printf("%s:%d: No error inserting early packet with full ready buffer\n", __func__, __LINE__); ret = -1; goto exit; } ret = 0; exit: rte_mempool_put_bulk(p, (void *)bufs, num_bufs); rte_reorder_free(b); return ret; } static int test_reorder_drain(void) { struct rte_reorder_buffer *b = NULL; struct rte_mempool *p = test_params->p; const unsigned int size = 4; const unsigned int num_bufs = 10; struct rte_mbuf *bufs[num_bufs]; int ret = 0; unsigned i, cnt; /* This would create a reorder buffer instance consisting of: * reorder_seq = 0 * ready_buf: RB[size] = {NULL, NULL, NULL, NULL} * order_buf: OB[size] = {NULL, NULL, NULL, NULL} */ b = rte_reorder_create("test_insert", rte_socket_id(), size); TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer"); ret = rte_mempool_get_bulk(p, (void *)bufs, num_bufs); TEST_ASSERT_SUCCESS(ret, "Error getting mbuf from pool"); /* Check no drained packets if reorder is empty */ cnt = rte_reorder_drain(b, bufs, 1); if (cnt != 0) { printf("%s:%d: drained packets from empty reorder buffer\n", __func__, __LINE__); ret = -1; goto exit; } for (i = 0; i < num_bufs; i++) bufs[i]->seqn = i; /* Insert packet with seqn 1: * reorder_seq = 0 * RB[] = {NULL, NULL, NULL, NULL} * OB[] = {NULL, 1, NULL, NULL} */ rte_reorder_insert(b, bufs[1]); /* Check no drained packets if no ready/order packets */ cnt = rte_reorder_drain(b, bufs, 1); if (cnt != 0) { printf("%s:%d: drained packets from empty reorder buffer\n", __func__, __LINE__); ret = -1; goto exit; } /* Insert more packets * RB[] = {NULL, NULL, NULL, NULL} * OB[] = {0, 1, NULL, 3} */ rte_reorder_insert(b, bufs[0]); rte_reorder_insert(b, bufs[3]); /* drained expected packets */ cnt = rte_reorder_drain(b, bufs, 4); if (cnt != 2) { printf("%s:%d:%d: number of expected packets not drained\n", __func__, __LINE__, cnt); ret = -1; goto exit; } /* * RB[] = {NULL, NULL, NULL, NULL} * OB[] = {NULL, 3, NULL, NULL} */ rte_reorder_insert(b, bufs[4]); rte_reorder_insert(b, bufs[7]); /* * RB[] = {3, 4, NULL, NULL} * OB[] = {NULL, NULL, 7, NULL} */ cnt = rte_reorder_drain(b, bufs, 4); if (cnt != 2) { printf("%s:%d:%d: number of expected packets not drained\n", __func__, __LINE__, cnt); ret = -1; goto exit; } ret = 0; exit: rte_mempool_put_bulk(p, (void *)bufs, num_bufs); rte_reorder_free(b); return ret; } static int test_setup(void) { /* reorder buffer instance creation */ if (test_params->b == NULL) { test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(), REORDER_BUFFER_SIZE); if (test_params->b == NULL) { printf("%s: Error creating reorder buffer instance b\n", __func__); return -1; } } else rte_reorder_reset(test_params->b); /* mempool creation */ if (test_params->p == NULL) { test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL", NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (test_params->p == NULL) { printf("%s: Error creating mempool\n", __func__); return -1; } } return 0; } static struct unit_test_suite reorder_test_suite = { .setup = test_setup, .suite_name = "Reorder Unit Test Suite", .unit_test_cases = { TEST_CASE(test_reorder_create), TEST_CASE(test_reorder_init), TEST_CASE(test_reorder_find_existing), TEST_CASE(test_reorder_free), TEST_CASE(test_reorder_insert), TEST_CASE(test_reorder_drain), TEST_CASES_END() } }; static int test_reorder(void) { return unit_test_suite_runner(&reorder_test_suite); } static struct test_command reorder_cmd = { .command = "reorder_autotest", .callback = test_reorder, }; REGISTER_TEST_COMMAND(reorder_cmd); ================================================ FILE: app/test/test_ring.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Ring * ==== * * #. Basic tests: done on one core: * * - Using single producer/single consumer functions: * * - Enqueue one object, two objects, MAX_BULK objects * - Dequeue one object, two objects, MAX_BULK objects * - Check that dequeued pointers are correct * * - Using multi producers/multi consumers functions: * * - Enqueue one object, two objects, MAX_BULK objects * - Dequeue one object, two objects, MAX_BULK objects * - Check that dequeued pointers are correct * * - Test watermark and default bulk enqueue/dequeue: * * - Set watermark * - Set default bulk value * - Enqueue objects, check that -EDQUOT is returned when * watermark is exceeded * - Check that dequeued pointers are correct * * #. Check live watermark change * * - Start a loop on another lcore that will enqueue and dequeue * objects in a ring. It will monitor the value of watermark. * - At the same time, change the watermark on the master lcore. * - The slave lcore will check that watermark changes from 16 to 32. * * #. Performance tests. * * Tests done in test_ring_perf.c */ #define RING_SIZE 4096 #define MAX_BULK 32 #define N 65536 #define TIME_S 5 static rte_atomic32_t synchro; static struct rte_ring *r; #define TEST_RING_VERIFY(exp) \ if (!(exp)) { \ printf("error at %s:%d\tcondition " #exp " failed\n", \ __func__, __LINE__); \ rte_ring_dump(stdout, r); \ return (-1); \ } #define TEST_RING_FULL_EMTPY_ITER 8 static int check_live_watermark_change(__attribute__((unused)) void *dummy) { uint64_t hz = rte_get_timer_hz(); void *obj_table[MAX_BULK]; unsigned watermark, watermark_old = 16; uint64_t cur_time, end_time; int64_t diff = 0; int i, ret; unsigned count = 4; /* init the object table */ memset(obj_table, 0, sizeof(obj_table)); end_time = rte_get_timer_cycles() + (hz * 2); /* check that bulk and watermark are 4 and 32 (respectively) */ while (diff >= 0) { /* add in ring until we reach watermark */ ret = 0; for (i = 0; i < 16; i ++) { if (ret != 0) break; ret = rte_ring_enqueue_bulk(r, obj_table, count); } if (ret != -EDQUOT) { printf("Cannot enqueue objects, or watermark not " "reached (ret=%d)\n", ret); return -1; } /* read watermark, the only change allowed is from 16 to 32 */ watermark = r->prod.watermark; if (watermark != watermark_old && (watermark_old != 16 || watermark != 32)) { printf("Bad watermark change %u -> %u\n", watermark_old, watermark); return -1; } watermark_old = watermark; /* dequeue objects from ring */ while (i--) { ret = rte_ring_dequeue_bulk(r, obj_table, count); if (ret != 0) { printf("Cannot dequeue (ret=%d)\n", ret); return -1; } } cur_time = rte_get_timer_cycles(); diff = end_time - cur_time; } if (watermark_old != 32 ) { printf(" watermark was not updated (wm=%u)\n", watermark_old); return -1; } return 0; } static int test_live_watermark_change(void) { unsigned lcore_id = rte_lcore_id(); unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1); printf("Test watermark live modification\n"); rte_ring_set_water_mark(r, 16); /* launch a thread that will enqueue and dequeue, checking * watermark and quota */ rte_eal_remote_launch(check_live_watermark_change, NULL, lcore_id2); rte_delay_ms(1000); rte_ring_set_water_mark(r, 32); rte_delay_ms(1000); if (rte_eal_wait_lcore(lcore_id2) < 0) return -1; return 0; } /* Test for catch on invalid watermark values */ static int test_set_watermark( void ){ unsigned count; int setwm; struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex"); if(r == NULL){ printf( " ring lookup failed\n" ); goto error; } count = r->prod.size*2; setwm = rte_ring_set_water_mark(r, count); if (setwm != -EINVAL){ printf("Test failed to detect invalid watermark count value\n"); goto error; } count = 0; rte_ring_set_water_mark(r, count); if (r->prod.watermark != r->prod.size) { printf("Test failed to detect invalid watermark count value\n"); goto error; } return 0; error: return -1; } /* * helper routine for test_ring_basic */ static int test_ring_basic_full_empty(void * const src[], void *dst[]) { unsigned i, rand; const unsigned rsz = RING_SIZE - 1; printf("Basic full/empty test\n"); for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) { /* random shift in the ring */ rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL); printf("%s: iteration %u, random shift: %u;\n", __func__, i, rand); TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, rand)); TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rand)); /* fill the ring */ TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, rsz)); TEST_RING_VERIFY(0 == rte_ring_free_count(r)); TEST_RING_VERIFY(rsz == rte_ring_count(r)); TEST_RING_VERIFY(rte_ring_full(r)); TEST_RING_VERIFY(0 == rte_ring_empty(r)); /* empty the ring */ TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rsz)); TEST_RING_VERIFY(rsz == rte_ring_free_count(r)); TEST_RING_VERIFY(0 == rte_ring_count(r)); TEST_RING_VERIFY(0 == rte_ring_full(r)); TEST_RING_VERIFY(rte_ring_empty(r)); /* check data */ TEST_RING_VERIFY(0 == memcmp(src, dst, rsz)); rte_ring_dump(stdout, r); } return (0); } static int test_ring_basic(void) { void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; int ret; unsigned i, num_elems; /* alloc dummy object pointers */ src = malloc(RING_SIZE*2*sizeof(void *)); if (src == NULL) goto fail; for (i = 0; i < RING_SIZE*2 ; i++) { src[i] = (void *)(unsigned long)i; } cur_src = src; /* alloc some room for copied objects */ dst = malloc(RING_SIZE*2*sizeof(void *)); if (dst == NULL) goto fail; memset(dst, 0, RING_SIZE*2*sizeof(void *)); cur_dst = dst; printf("enqueue 1 obj\n"); ret = rte_ring_sp_enqueue_bulk(r, cur_src, 1); cur_src += 1; if (ret != 0) goto fail; printf("enqueue 2 objs\n"); ret = rte_ring_sp_enqueue_bulk(r, cur_src, 2); cur_src += 2; if (ret != 0) goto fail; printf("enqueue MAX_BULK objs\n"); ret = rte_ring_sp_enqueue_bulk(r, cur_src, MAX_BULK); cur_src += MAX_BULK; if (ret != 0) goto fail; printf("dequeue 1 obj\n"); ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 1); cur_dst += 1; if (ret != 0) goto fail; printf("dequeue 2 objs\n"); ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 2); cur_dst += 2; if (ret != 0) goto fail; printf("dequeue MAX_BULK objs\n"); ret = rte_ring_sc_dequeue_bulk(r, cur_dst, MAX_BULK); cur_dst += MAX_BULK; if (ret != 0) goto fail; /* check data */ if (memcmp(src, dst, cur_dst - dst)) { rte_hexdump(stdout, "src", src, cur_src - src); rte_hexdump(stdout, "dst", dst, cur_dst - dst); printf("data after dequeue is not the same\n"); goto fail; } cur_src = src; cur_dst = dst; printf("enqueue 1 obj\n"); ret = rte_ring_mp_enqueue_bulk(r, cur_src, 1); cur_src += 1; if (ret != 0) goto fail; printf("enqueue 2 objs\n"); ret = rte_ring_mp_enqueue_bulk(r, cur_src, 2); cur_src += 2; if (ret != 0) goto fail; printf("enqueue MAX_BULK objs\n"); ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK); cur_src += MAX_BULK; if (ret != 0) goto fail; printf("dequeue 1 obj\n"); ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 1); cur_dst += 1; if (ret != 0) goto fail; printf("dequeue 2 objs\n"); ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 2); cur_dst += 2; if (ret != 0) goto fail; printf("dequeue MAX_BULK objs\n"); ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK); cur_dst += MAX_BULK; if (ret != 0) goto fail; /* check data */ if (memcmp(src, dst, cur_dst - dst)) { rte_hexdump(stdout, "src", src, cur_src - src); rte_hexdump(stdout, "dst", dst, cur_dst - dst); printf("data after dequeue is not the same\n"); goto fail; } cur_src = src; cur_dst = dst; printf("fill and empty the ring\n"); for (i = 0; istats[lcore_id]; printf("Test the ring stats.\n"); /* Reset the watermark in case it was set in another test. */ rte_ring_set_water_mark(r, 0); /* Reset the ring stats. */ memset(&r->stats[lcore_id], 0, sizeof(r->stats[lcore_id])); /* Allocate some dummy object pointers. */ src = malloc(RING_SIZE*2*sizeof(void *)); if (src == NULL) goto fail; for (i = 0; i < RING_SIZE*2 ; i++) { src[i] = (void *)(unsigned long)i; } /* Allocate some memory for copied objects. */ dst = malloc(RING_SIZE*2*sizeof(void *)); if (dst == NULL) goto fail; memset(dst, 0, RING_SIZE*2*sizeof(void *)); /* Set the head and tail pointers. */ cur_src = src; cur_dst = dst; /* Do Enqueue tests. */ printf("Test the dequeue stats.\n"); /* Fill the ring up to RING_SIZE -1. */ printf("Fill the ring.\n"); for (i = 0; i< (RING_SIZE/MAX_BULK); i++) { rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); cur_src += MAX_BULK; } /* Adjust for final enqueue = MAX_BULK -1. */ cur_src--; printf("Verify that the ring is full.\n"); if (rte_ring_full(r) != 1) goto fail; printf("Verify the enqueue success stats.\n"); /* Stats should match above enqueue operations to fill the ring. */ if (ring_stats->enq_success_bulk != (RING_SIZE/MAX_BULK)) goto fail; /* Current max objects is RING_SIZE -1. */ if (ring_stats->enq_success_objs != RING_SIZE -1) goto fail; /* Shouldn't have any failures yet. */ if (ring_stats->enq_fail_bulk != 0) goto fail; if (ring_stats->enq_fail_objs != 0) goto fail; printf("Test stats for SP burst enqueue to a full ring.\n"); num_items = 2; ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != 0) goto fail; failed_enqueue_ops += 1; failed_enqueue_items += num_items; /* The enqueue should have failed. */ if (ring_stats->enq_fail_bulk != failed_enqueue_ops) goto fail; if (ring_stats->enq_fail_objs != failed_enqueue_items) goto fail; printf("Test stats for SP bulk enqueue to a full ring.\n"); num_items = 4; ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); if (ret != -ENOBUFS) goto fail; failed_enqueue_ops += 1; failed_enqueue_items += num_items; /* The enqueue should have failed. */ if (ring_stats->enq_fail_bulk != failed_enqueue_ops) goto fail; if (ring_stats->enq_fail_objs != failed_enqueue_items) goto fail; printf("Test stats for MP burst enqueue to a full ring.\n"); num_items = 8; ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != 0) goto fail; failed_enqueue_ops += 1; failed_enqueue_items += num_items; /* The enqueue should have failed. */ if (ring_stats->enq_fail_bulk != failed_enqueue_ops) goto fail; if (ring_stats->enq_fail_objs != failed_enqueue_items) goto fail; printf("Test stats for MP bulk enqueue to a full ring.\n"); num_items = 16; ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); if (ret != -ENOBUFS) goto fail; failed_enqueue_ops += 1; failed_enqueue_items += num_items; /* The enqueue should have failed. */ if (ring_stats->enq_fail_bulk != failed_enqueue_ops) goto fail; if (ring_stats->enq_fail_objs != failed_enqueue_items) goto fail; /* Do Dequeue tests. */ printf("Test the dequeue stats.\n"); printf("Empty the ring.\n"); for (i = 0; ideq_success_bulk != (RING_SIZE/MAX_BULK)) goto fail; /* Objects dequeued is RING_SIZE -1. */ if (ring_stats->deq_success_objs != RING_SIZE -1) goto fail; /* Shouldn't have any dequeue failure stats yet. */ if (ring_stats->deq_fail_bulk != 0) goto fail; printf("Test stats for SC burst dequeue with an empty ring.\n"); num_items = 2; ret = rte_ring_sc_dequeue_burst(r, cur_dst, num_items); if ((ret & RTE_RING_SZ_MASK) != 0) goto fail; failed_dequeue_ops += 1; failed_dequeue_items += num_items; /* The dequeue should have failed. */ if (ring_stats->deq_fail_bulk != failed_dequeue_ops) goto fail; if (ring_stats->deq_fail_objs != failed_dequeue_items) goto fail; printf("Test stats for SC bulk dequeue with an empty ring.\n"); num_items = 4; ret = rte_ring_sc_dequeue_bulk(r, cur_dst, num_items); if (ret != -ENOENT) goto fail; failed_dequeue_ops += 1; failed_dequeue_items += num_items; /* The dequeue should have failed. */ if (ring_stats->deq_fail_bulk != failed_dequeue_ops) goto fail; if (ring_stats->deq_fail_objs != failed_dequeue_items) goto fail; printf("Test stats for MC burst dequeue with an empty ring.\n"); num_items = 8; ret = rte_ring_mc_dequeue_burst(r, cur_dst, num_items); if ((ret & RTE_RING_SZ_MASK) != 0) goto fail; failed_dequeue_ops += 1; failed_dequeue_items += num_items; /* The dequeue should have failed. */ if (ring_stats->deq_fail_bulk != failed_dequeue_ops) goto fail; if (ring_stats->deq_fail_objs != failed_dequeue_items) goto fail; printf("Test stats for MC bulk dequeue with an empty ring.\n"); num_items = 16; ret = rte_ring_mc_dequeue_bulk(r, cur_dst, num_items); if (ret != -ENOENT) goto fail; failed_dequeue_ops += 1; failed_dequeue_items += num_items; /* The dequeue should have failed. */ if (ring_stats->deq_fail_bulk != failed_dequeue_ops) goto fail; if (ring_stats->deq_fail_objs != failed_dequeue_items) goto fail; printf("Test total enqueue/dequeue stats.\n"); /* At this point the enqueue and dequeue stats should be the same. */ if (ring_stats->enq_success_bulk != ring_stats->deq_success_bulk) goto fail; if (ring_stats->enq_success_objs != ring_stats->deq_success_objs) goto fail; if (ring_stats->enq_fail_bulk != ring_stats->deq_fail_bulk) goto fail; if (ring_stats->enq_fail_objs != ring_stats->deq_fail_objs) goto fail; /* Watermark Tests. */ printf("Test the watermark/quota stats.\n"); printf("Verify the initial watermark stats.\n"); /* Watermark stats should be 0 since there is no watermark. */ if (ring_stats->enq_quota_bulk != 0) goto fail; if (ring_stats->enq_quota_objs != 0) goto fail; /* Set a watermark. */ rte_ring_set_water_mark(r, 16); /* Reset pointers. */ cur_src = src; cur_dst = dst; last_enqueue_ops = ring_stats->enq_success_bulk; last_enqueue_items = ring_stats->enq_success_objs; printf("Test stats for SP burst enqueue below watermark.\n"); num_items = 8; ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != num_items) goto fail; /* Watermark stats should still be 0. */ if (ring_stats->enq_quota_bulk != 0) goto fail; if (ring_stats->enq_quota_objs != 0) goto fail; /* Success stats should have increased. */ if (ring_stats->enq_success_bulk != last_enqueue_ops + 1) goto fail; if (ring_stats->enq_success_objs != last_enqueue_items + num_items) goto fail; last_enqueue_ops = ring_stats->enq_success_bulk; last_enqueue_items = ring_stats->enq_success_objs; printf("Test stats for SP burst enqueue at watermark.\n"); num_items = 8; ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != num_items) goto fail; /* Watermark stats should have changed. */ if (ring_stats->enq_quota_bulk != 1) goto fail; if (ring_stats->enq_quota_objs != num_items) goto fail; last_quota_ops = ring_stats->enq_quota_bulk; last_quota_items = ring_stats->enq_quota_objs; printf("Test stats for SP burst enqueue above watermark.\n"); num_items = 1; ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != num_items) goto fail; /* Watermark stats should have changed. */ if (ring_stats->enq_quota_bulk != last_quota_ops +1) goto fail; if (ring_stats->enq_quota_objs != last_quota_items + num_items) goto fail; last_quota_ops = ring_stats->enq_quota_bulk; last_quota_items = ring_stats->enq_quota_objs; printf("Test stats for MP burst enqueue above watermark.\n"); num_items = 2; ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); if ((ret & RTE_RING_SZ_MASK) != num_items) goto fail; /* Watermark stats should have changed. */ if (ring_stats->enq_quota_bulk != last_quota_ops +1) goto fail; if (ring_stats->enq_quota_objs != last_quota_items + num_items) goto fail; last_quota_ops = ring_stats->enq_quota_bulk; last_quota_items = ring_stats->enq_quota_objs; printf("Test stats for SP bulk enqueue above watermark.\n"); num_items = 4; ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); if (ret != -EDQUOT) goto fail; /* Watermark stats should have changed. */ if (ring_stats->enq_quota_bulk != last_quota_ops +1) goto fail; if (ring_stats->enq_quota_objs != last_quota_items + num_items) goto fail; last_quota_ops = ring_stats->enq_quota_bulk; last_quota_items = ring_stats->enq_quota_objs; printf("Test stats for MP bulk enqueue above watermark.\n"); num_items = 8; ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); if (ret != -EDQUOT) goto fail; /* Watermark stats should have changed. */ if (ring_stats->enq_quota_bulk != last_quota_ops +1) goto fail; if (ring_stats->enq_quota_objs != last_quota_items + num_items) goto fail; printf("Test watermark success stats.\n"); /* Success stats should be same as last non-watermarked enqueue. */ if (ring_stats->enq_success_bulk != last_enqueue_ops) goto fail; if (ring_stats->enq_success_objs != last_enqueue_items) goto fail; /* Cleanup. */ /* Empty the ring. */ for (i = 0; istats[lcore_id], 0, sizeof(r->stats[lcore_id])); /* Free memory before test completed */ if (src) free(src); if (dst) free(dst); return 0; fail: if (src) free(src); if (dst) free(dst); return -1; #endif } /* * it will always fail to create ring with a wrong ring size number in this function */ static int test_ring_creation_with_wrong_size(void) { struct rte_ring * rp = NULL; /* Test if ring size is not power of 2 */ rp = rte_ring_create("test_bad_ring_size", RING_SIZE + 1, SOCKET_ID_ANY, 0); if (NULL != rp) { return -1; } /* Test if ring size is exceeding the limit */ rp = rte_ring_create("test_bad_ring_size", (RTE_RING_SZ_MASK + 1), SOCKET_ID_ANY, 0); if (NULL != rp) { return -1; } return 0; } /* * it tests if it would always fail to create ring with an used ring name */ static int test_ring_creation_with_an_used_name(void) { struct rte_ring * rp; rp = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); if (NULL != rp) return -1; return 0; } /* * Test to if a non-power of 2 count causes the create * function to fail correctly */ static int test_create_count_odd(void) { struct rte_ring *r = rte_ring_create("test_ring_count", 4097, SOCKET_ID_ANY, 0 ); if(r != NULL){ return -1; } return 0; } static int test_lookup_null(void) { struct rte_ring *rlp = rte_ring_lookup("ring_not_found"); if (rlp ==NULL) if (rte_errno != ENOENT){ printf( "test failed to returnn error on null pointer\n"); return -1; } return 0; } /* * it tests some more basic ring operations */ static int test_ring_basic_ex(void) { int ret = -1; unsigned i; struct rte_ring * rp; void **obj = NULL; obj = rte_calloc("test_ring_basic_ex_malloc", RING_SIZE, sizeof(void *), 0); if (obj == NULL) { printf("test_ring_basic_ex fail to rte_malloc\n"); goto fail_test; } rp = rte_ring_create("test_ring_basic_ex", RING_SIZE, SOCKET_ID_ANY, RING_F_SP_ENQ | RING_F_SC_DEQ); if (rp == NULL) { printf("test_ring_basic_ex fail to create ring\n"); goto fail_test; } if (rte_ring_lookup("test_ring_basic_ex") != rp) { goto fail_test; } if (rte_ring_empty(rp) != 1) { printf("test_ring_basic_ex ring is not empty but it should be\n"); goto fail_test; } printf("%u ring entries are now free\n", rte_ring_free_count(rp)); for (i = 0; i < RING_SIZE; i ++) { rte_ring_enqueue(rp, obj[i]); } if (rte_ring_full(rp) != 1) { printf("test_ring_basic_ex ring is not full but it should be\n"); goto fail_test; } for (i = 0; i < RING_SIZE; i ++) { rte_ring_dequeue(rp, &obj[i]); } if (rte_ring_empty(rp) != 1) { printf("test_ring_basic_ex ring is not empty but it should be\n"); goto fail_test; } /* Covering the ring burst operation */ ret = rte_ring_enqueue_burst(rp, obj, 2); if ((ret & RTE_RING_SZ_MASK) != 2) { printf("test_ring_basic_ex: rte_ring_enqueue_burst fails \n"); goto fail_test; } ret = rte_ring_dequeue_burst(rp, obj, 2); if (ret != 2) { printf("test_ring_basic_ex: rte_ring_dequeue_burst fails \n"); goto fail_test; } ret = 0; fail_test: if (obj != NULL) rte_free(obj); return ret; } static int test_ring(void) { /* some more basic operations */ if (test_ring_basic_ex() < 0) return -1; rte_atomic32_init(&synchro); if (r == NULL) r = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); if (r == NULL) return -1; /* retrieve the ring from its name */ if (rte_ring_lookup("test") != r) { printf("Cannot lookup ring from its name\n"); return -1; } /* burst operations */ if (test_ring_burst_basic() < 0) return -1; /* basic operations */ if (test_ring_basic() < 0) return -1; /* ring stats */ if (test_ring_stats() < 0) return -1; /* basic operations */ if (test_live_watermark_change() < 0) return -1; if ( test_set_watermark() < 0){ printf ("Test failed to detect invalid parameter\n"); return -1; } else printf ( "Test detected forced bad watermark values\n"); if ( test_create_count_odd() < 0){ printf ("Test failed to detect odd count\n"); return -1; } else printf ( "Test detected odd count\n"); if ( test_lookup_null() < 0){ printf ("Test failed to detect NULL ring lookup\n"); return -1; } else printf ( "Test detected NULL ring lookup \n"); /* test of creating ring with wrong size */ if (test_ring_creation_with_wrong_size() < 0) return -1; /* test of creation ring with an used name */ if (test_ring_creation_with_an_used_name() < 0) return -1; /* dump the ring status */ rte_ring_list_dump(stdout); return 0; } static struct test_command ring_cmd = { .command = "ring_autotest", .callback = test_ring, }; REGISTER_TEST_COMMAND(ring_cmd); ================================================ FILE: app/test/test_ring_perf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" /* * Ring * ==== * * Measures performance of various operations using rdtsc * * Empty ring dequeue * * Enqueue/dequeue of bursts in 1 threads * * Enqueue/dequeue of bursts in 2 threads */ #define RING_NAME "RING_PERF" #define RING_SIZE 4096 #define MAX_BURST 32 /* * the sizes to enqueue and dequeue in testing * (marked volatile so they won't be seen as compile-time constants) */ static const volatile unsigned bulk_sizes[] = { 8, 32 }; /* The ring structure used for tests */ static struct rte_ring *r; struct lcore_pair { unsigned c1, c2; }; static volatile unsigned lcore_count = 0; /**** Functions to analyse our core mask to get cores for different tests ***/ static int get_two_hyperthreads(struct lcore_pair *lcp) { unsigned id1, id2; unsigned c1, c2, s1, s2; RTE_LCORE_FOREACH(id1) { /* inner loop just re-reads all id's. We could skip the first few * elements, but since number of cores is small there is little point */ RTE_LCORE_FOREACH(id2) { if (id1 == id2) continue; c1 = lcore_config[id1].core_id; c2 = lcore_config[id2].core_id; s1 = lcore_config[id1].socket_id; s2 = lcore_config[id2].socket_id; if ((c1 == c2) && (s1 == s2)){ lcp->c1 = id1; lcp->c2 = id2; return 0; } } } return 1; } static int get_two_cores(struct lcore_pair *lcp) { unsigned id1, id2; unsigned c1, c2, s1, s2; RTE_LCORE_FOREACH(id1) { RTE_LCORE_FOREACH(id2) { if (id1 == id2) continue; c1 = lcore_config[id1].core_id; c2 = lcore_config[id2].core_id; s1 = lcore_config[id1].socket_id; s2 = lcore_config[id2].socket_id; if ((c1 != c2) && (s1 == s2)){ lcp->c1 = id1; lcp->c2 = id2; return 0; } } } return 1; } static int get_two_sockets(struct lcore_pair *lcp) { unsigned id1, id2; unsigned s1, s2; RTE_LCORE_FOREACH(id1) { RTE_LCORE_FOREACH(id2) { if (id1 == id2) continue; s1 = lcore_config[id1].socket_id; s2 = lcore_config[id2].socket_id; if (s1 != s2){ lcp->c1 = id1; lcp->c2 = id2; return 0; } } } return 1; } /* Get cycle counts for dequeuing from an empty ring. Should be 2 or 3 cycles */ static void test_empty_dequeue(void) { const unsigned iter_shift = 26; const unsigned iterations = 1<size; unsigned i; void *burst[MAX_BURST] = {0}; if ( __sync_add_and_fetch(&lcore_count, 1) != 2 ) while(lcore_count != 2) rte_pause(); const uint64_t sp_start = rte_rdtsc(); for (i = 0; i < iterations; i++) while (rte_ring_sp_enqueue_bulk(r, burst, size) != 0) rte_pause(); const uint64_t sp_end = rte_rdtsc(); const uint64_t mp_start = rte_rdtsc(); for (i = 0; i < iterations; i++) while (rte_ring_mp_enqueue_bulk(r, burst, size) != 0) rte_pause(); const uint64_t mp_end = rte_rdtsc(); params->spsc = ((double)(sp_end - sp_start))/(iterations*size); params->mpmc = ((double)(mp_end - mp_start))/(iterations*size); return 0; } /* * Function that uses rdtsc to measure timing for ring dequeue. Needs pair * thread running enqueue_bulk function */ static int dequeue_bulk(void *p) { const unsigned iter_shift = 23; const unsigned iterations = 1<size; unsigned i; void *burst[MAX_BURST] = {0}; if ( __sync_add_and_fetch(&lcore_count, 1) != 2 ) while(lcore_count != 2) rte_pause(); const uint64_t sc_start = rte_rdtsc(); for (i = 0; i < iterations; i++) while (rte_ring_sc_dequeue_bulk(r, burst, size) != 0) rte_pause(); const uint64_t sc_end = rte_rdtsc(); const uint64_t mc_start = rte_rdtsc(); for (i = 0; i < iterations; i++) while (rte_ring_mc_dequeue_bulk(r, burst, size) != 0) rte_pause(); const uint64_t mc_end = rte_rdtsc(); params->spsc = ((double)(sc_end - sc_start))/(iterations*size); params->mpmc = ((double)(mc_end - mc_start))/(iterations*size); return 0; } /* * Function that calls the enqueue and dequeue bulk functions on pairs of cores. * used to measure ring perf between hyperthreads, cores and sockets. */ static void run_on_core_pair(struct lcore_pair *cores, lcore_function_t f1, lcore_function_t f2) { struct thread_params param1 = {0}, param2 = {0}; unsigned i; for (i = 0; i < sizeof(bulk_sizes)/sizeof(bulk_sizes[0]); i++) { lcore_count = 0; param1.size = param2.size = bulk_sizes[i]; if (cores->c1 == rte_get_master_lcore()) { rte_eal_remote_launch(f2, ¶m2, cores->c2); f1(¶m1); rte_eal_wait_lcore(cores->c2); } else { rte_eal_remote_launch(f1, ¶m1, cores->c1); rte_eal_remote_launch(f2, ¶m2, cores->c2); rte_eal_wait_lcore(cores->c1); rte_eal_wait_lcore(cores->c2); } printf("SP/SC bulk enq/dequeue (size: %u): %.2F\n", bulk_sizes[i], param1.spsc + param2.spsc); printf("MP/MC bulk enq/dequeue (size: %u): %.2F\n", bulk_sizes[i], param1.mpmc + param2.mpmc); } } /* * Test function that determines how long an enqueue + dequeue of a single item * takes on a single lcore. Result is for comparison with the bulk enq+deq. */ static void test_single_enqueue_dequeue(void) { const unsigned iter_shift = 24; const unsigned iterations = 1<> iter_shift); printf("MP/MC single enq/dequeue: %"PRIu64"\n", (mc_end-mc_start) >> iter_shift); } /* * Test that does both enqueue and dequeue on a core using the burst() API calls * instead of the bulk() calls used in other tests. Results should be the same * as for the bulk function called on a single lcore. */ static void test_burst_enqueue_dequeue(void) { const unsigned iter_shift = 23; const unsigned iterations = 1<> iter_shift) / bulk_sizes[sz]; uint64_t sc_avg = ((sc_end-sc_start) >> iter_shift) / bulk_sizes[sz]; printf("SP/SC burst enq/dequeue (size: %u): %"PRIu64"\n", bulk_sizes[sz], sc_avg); printf("MP/MC burst enq/dequeue (size: %u): %"PRIu64"\n", bulk_sizes[sz], mc_avg); } } /* Times enqueue and dequeue on a single lcore */ static void test_bulk_enqueue_dequeue(void) { const unsigned iter_shift = 23; const unsigned iterations = 1< #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * rwlock test * =========== * * - There is a global rwlock and a table of rwlocks (one per lcore). * * - The test function takes all of these locks and launches the * ``test_rwlock_per_core()`` function on each core (except the master). * * - The function takes the global write lock, display something, * then releases the global lock. * - Then, it takes the per-lcore write lock, display something, and * releases the per-core lock. * - Finally, a read lock is taken during 100 ms, then released. * * - The main function unlocks the per-lcore locks sequentially and * waits between each lock. This triggers the display of a message * for each core, in the correct order. * * Then, it tries to take the global write lock and display the last * message. The autotest script checks that the message order is correct. */ static rte_rwlock_t sl; static rte_rwlock_t sl_tab[RTE_MAX_LCORE]; static int test_rwlock_per_core(__attribute__((unused)) void *arg) { rte_rwlock_write_lock(&sl); printf("Global write lock taken on core %u\n", rte_lcore_id()); rte_rwlock_write_unlock(&sl); rte_rwlock_write_lock(&sl_tab[rte_lcore_id()]); printf("Hello from core %u !\n", rte_lcore_id()); rte_rwlock_write_unlock(&sl_tab[rte_lcore_id()]); rte_rwlock_read_lock(&sl); printf("Global read lock taken on core %u\n", rte_lcore_id()); rte_delay_ms(100); printf("Release global read lock on core %u\n", rte_lcore_id()); rte_rwlock_read_unlock(&sl); return 0; } static int test_rwlock(void) { int i; rte_rwlock_init(&sl); for (i=0; i #include #include #include #include #include "test.h" #include #include #include #include #include #define SUBPORT 0 #define PIPE 1 #define TC 2 #define QUEUE 3 static struct rte_sched_subport_params subport_param[] = { { .tb_rate = 1250000000, .tb_size = 1000000, .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000}, .tc_period = 10, }, }; static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, .tb_size = 1000000, .tc_rate = {305175, 305175, 305175, 305175}, .tc_period = 40, .wrr_weights = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, }, }; static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ .mtu = 1522, .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 4096, .qsize = {64, 64, 64, 64}, .pipe_profiles = pipe_profile, .n_pipe_profiles = 1, }; #define NB_MBUF 32 #define MBUF_DATA_SZ (2048 + RTE_PKTMBUF_HEADROOM) #define MEMPOOL_CACHE_SZ 0 #define SOCKET 0 static struct rte_mempool * create_mempool(void) { struct rte_mempool * mp; mp = rte_mempool_lookup("test_sched"); if (!mp) mp = rte_pktmbuf_pool_create("test_sched", NB_MBUF, MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, SOCKET); return mp; } static void prepare_pkt(struct rte_mbuf *mbuf) { struct ether_hdr *eth_hdr; struct vlan_hdr *vlan1, *vlan2; struct ipv4_hdr *ip_hdr; /* Simulate a classifier */ eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *); vlan1 = (struct vlan_hdr *)(ð_hdr->ether_type ); vlan2 = (struct vlan_hdr *)((uintptr_t)ð_hdr->ether_type + sizeof(struct vlan_hdr)); eth_hdr = (struct ether_hdr *)((uintptr_t)ð_hdr->ether_type + 2 *sizeof(struct vlan_hdr)); ip_hdr = (struct ipv4_hdr *)((uintptr_t)eth_hdr + sizeof(eth_hdr->ether_type)); vlan1->vlan_tci = rte_cpu_to_be_16(SUBPORT); vlan2->vlan_tci = rte_cpu_to_be_16(PIPE); eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); ip_hdr->dst_addr = IPv4(0,0,TC,QUEUE); rte_sched_port_pkt_write(mbuf, SUBPORT, PIPE, TC, QUEUE, e_RTE_METER_YELLOW); /* 64 byte packet */ mbuf->pkt_len = 60; mbuf->data_len = 60; } /** * test main entrance for library sched */ static int test_sched(void) { struct rte_mempool *mp = NULL; struct rte_sched_port *port = NULL; uint32_t pipe; struct rte_mbuf *in_mbufs[10]; struct rte_mbuf *out_mbufs[10]; int i; int err; mp = create_mempool(); TEST_ASSERT_NOT_NULL(mp, "Error creating mempool\n"); port_param.socket = 0; port_param.rate = (uint64_t) 10000 * 1000 * 1000 / 8; port = rte_sched_port_config(&port_param); TEST_ASSERT_NOT_NULL(port, "Error config sched port\n"); err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } for (i = 0; i < 10; i++) { in_mbufs[i] = rte_pktmbuf_alloc(mp); TEST_ASSERT_NOT_NULL(in_mbufs[i], "Packet allocation failed\n"); prepare_pkt(in_mbufs[i]); } err = rte_sched_port_enqueue(port, in_mbufs, 10); TEST_ASSERT_EQUAL(err, 10, "Wrong enqueue, err=%d\n", err); err = rte_sched_port_dequeue(port, out_mbufs, 10); TEST_ASSERT_EQUAL(err, 10, "Wrong dequeue, err=%d\n", err); for (i = 0; i < 10; i++) { enum rte_meter_color color; uint32_t subport, traffic_class, queue; color = rte_sched_port_pkt_read_color(out_mbufs[i]); TEST_ASSERT_EQUAL(color, e_RTE_METER_YELLOW, "Wrong color\n"); rte_sched_port_pkt_read_tree_path(out_mbufs[i], &subport, &pipe, &traffic_class, &queue); TEST_ASSERT_EQUAL(subport, SUBPORT, "Wrong subport\n"); TEST_ASSERT_EQUAL(pipe, PIPE, "Wrong pipe\n"); TEST_ASSERT_EQUAL(traffic_class, TC, "Wrong traffic_class\n"); TEST_ASSERT_EQUAL(queue, QUEUE, "Wrong queue\n"); } struct rte_sched_subport_stats subport_stats; uint32_t tc_ov; rte_sched_subport_read_stats(port, SUBPORT, &subport_stats, &tc_ov); #if 0 TEST_ASSERT_EQUAL(subport_stats.n_pkts_tc[TC-1], 10, "Wrong subport stats\n"); #endif struct rte_sched_queue_stats queue_stats; uint16_t qlen; rte_sched_queue_read_stats(port, QUEUE, &queue_stats, &qlen); #if 0 TEST_ASSERT_EQUAL(queue_stats.n_pkts, 10, "Wrong queue stats\n"); #endif rte_sched_port_free(port); return 0; } static struct test_command sched_cmd = { .command = "sched_autotest", .callback = test_sched, }; REGISTER_TEST_COMMAND(sched_cmd); ================================================ FILE: app/test/test_spinlock.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" /* * Spinlock test * ============= * * - There is a global spinlock and a table of spinlocks (one per lcore). * * - The test function takes all of these locks and launches the * ``test_spinlock_per_core()`` function on each core (except the master). * * - The function takes the global lock, display something, then releases * the global lock. * - The function takes the per-lcore lock, display something, then releases * the per-core lock. * * - The main function unlocks the per-lcore locks sequentially and * waits between each lock. This triggers the display of a message * for each core, in the correct order. The autotest script checks that * this order is correct. * * - A load test is carried out, with all cores attempting to lock a single lock * multiple times */ static rte_spinlock_t sl, sl_try; static rte_spinlock_t sl_tab[RTE_MAX_LCORE]; static rte_spinlock_recursive_t slr; static unsigned count = 0; static rte_atomic32_t synchro; static int test_spinlock_per_core(__attribute__((unused)) void *arg) { rte_spinlock_lock(&sl); printf("Global lock taken on core %u\n", rte_lcore_id()); rte_spinlock_unlock(&sl); rte_spinlock_lock(&sl_tab[rte_lcore_id()]); printf("Hello from core %u !\n", rte_lcore_id()); rte_spinlock_unlock(&sl_tab[rte_lcore_id()]); return 0; } static int test_spinlock_recursive_per_core(__attribute__((unused)) void *arg) { unsigned id = rte_lcore_id(); rte_spinlock_recursive_lock(&slr); printf("Global recursive lock taken on core %u - count = %d\n", id, slr.count); rte_spinlock_recursive_lock(&slr); printf("Global recursive lock taken on core %u - count = %d\n", id, slr.count); rte_spinlock_recursive_lock(&slr); printf("Global recursive lock taken on core %u - count = %d\n", id, slr.count); printf("Hello from within recursive locks from core %u !\n", id); rte_spinlock_recursive_unlock(&slr); printf("Global recursive lock released on core %u - count = %d\n", id, slr.count); rte_spinlock_recursive_unlock(&slr); printf("Global recursive lock released on core %u - count = %d\n", id, slr.count); rte_spinlock_recursive_unlock(&slr); printf("Global recursive lock released on core %u - count = %d\n", id, slr.count); return 0; } static rte_spinlock_t lk = RTE_SPINLOCK_INITIALIZER; static uint64_t lock_count[RTE_MAX_LCORE] = {0}; #define TIME_S 5 static int load_loop_fn(void *func_param) { uint64_t time_diff = 0, begin; uint64_t hz = rte_get_timer_hz(); uint64_t lcount = 0; const int use_lock = *(int*)func_param; const unsigned lcore = rte_lcore_id(); /* wait synchro for slaves */ if (lcore != rte_get_master_lcore()) while (rte_atomic32_read(&synchro) == 0); begin = rte_get_timer_cycles(); while (time_diff / hz < TIME_S) { if (use_lock) rte_spinlock_lock(&lk); lcount++; if (use_lock) rte_spinlock_unlock(&lk); /* delay to make lock duty cycle slighlty realistic */ rte_delay_us(1); time_diff = rte_get_timer_cycles() - begin; } lock_count[lcore] = lcount; return 0; } static int test_spinlock_perf(void) { unsigned int i; uint64_t total = 0; int lock = 0; const unsigned lcore = rte_lcore_id(); printf("\nTest with no lock on single core...\n"); load_loop_fn(&lock); printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]); memset(lock_count, 0, sizeof(lock_count)); printf("\nTest with lock on single core...\n"); lock = 1; load_loop_fn(&lock); printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]); memset(lock_count, 0, sizeof(lock_count)); printf("\nTest with lock on %u cores...\n", rte_lcore_count()); /* Clear synchro and start slaves */ rte_atomic32_set(&synchro, 0); rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER); /* start synchro and launch test on master */ rte_atomic32_set(&synchro, 1); load_loop_fn(&lock); rte_eal_mp_wait_lcore(); RTE_LCORE_FOREACH(i) { printf("Core [%u] count = %"PRIu64"\n", i, lock_count[i]); total += lock_count[i]; } printf("Total count = %"PRIu64"\n", total); return 0; } /* * Use rte_spinlock_trylock() to trylock a spinlock object, * If it could not lock the object sucessfully, it would * return immediately and the variable of "count" would be * increased by one per times. the value of "count" could be * checked as the result later. */ static int test_spinlock_try(__attribute__((unused)) void *arg) { if (rte_spinlock_trylock(&sl_try) == 0) { rte_spinlock_lock(&sl); count ++; rte_spinlock_unlock(&sl); } return 0; } /* * Test rte_eal_get_lcore_state() in addition to spinlocks * as we have "waiting" then "running" lcores. */ static int test_spinlock(void) { int ret = 0; int i; /* slave cores should be waiting: print it */ RTE_LCORE_FOREACH_SLAVE(i) { printf("lcore %d state: %d\n", i, (int) rte_eal_get_lcore_state(i)); } rte_spinlock_init(&sl); rte_spinlock_init(&sl_try); rte_spinlock_recursive_init(&slr); for (i=0; i #include #include #include #include #include #include "test.h" #define LOG(...) do {\ fprintf(stderr, "%s() ln %d: ", __func__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ } while(0) #define DATA_BYTE 'a' static int test_rte_strsplit(void) { int i; do { /* ======================================================= * split a mac address correct number of splits requested * =======================================================*/ char test_string[] = "54:65:76:87:98:90"; char *splits[6]; LOG("Source string: '%s', to split on ':'\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ':') != 6) { LOG("Error splitting mac address\n"); return -1; } for (i = 0; i < 6; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while (0); do { /* ======================================================= * split on spaces smaller number of splits requested * =======================================================*/ char test_string[] = "54 65 76 87 98 90"; char *splits[6]; LOG("Source string: '%s', to split on ' '\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 3, ' ') != 3) { LOG("Error splitting mac address for max 2 splits\n"); return -1; } for (i = 0; i < 3; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while (0); do { /* ======================================================= * split on commas - more splits than commas requested * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; LOG("Source string: '%s', to split on ','\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ',') != 4) { LOG("Error splitting %s on ','\n", test_string); return -1; } for (i = 0; i < 4; i++) LOG("Token %d = %s\n", i + 1, splits[i]); } while(0); do { /* ======================================================= * Try splitting on non-existent character. * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; LOG("Source string: '%s', to split on ' '\n", test_string); if (rte_strsplit(test_string, sizeof(test_string), splits, 6, ' ') != 1) { LOG("Error splitting %s on ' '\n", test_string); return -1; } LOG("String not split\n"); } while(0); do { /* ======================================================= * Invalid / edge case parameter checks * =======================================================*/ char test_string[] = "a,b,c,d"; char *splits[6]; if (rte_strsplit(NULL, 0, splits, 6, ',') >= 0 || errno != EINVAL){ LOG("Error: rte_strsplit accepted NULL string parameter\n"); return -1; } if (rte_strsplit(test_string, sizeof(test_string), NULL, 0, ',') >= 0 || errno != EINVAL){ LOG("Error: rte_strsplit accepted NULL array parameter\n"); return -1; } errno = 0; if (rte_strsplit(test_string, 0, splits, 6, ',') != 0 || errno != 0) { LOG("Error: rte_strsplit did not accept 0 length string\n"); return -1; } if (rte_strsplit(test_string, sizeof(test_string), splits, 0, ',') != 0 || errno != 0) { LOG("Error: rte_strsplit did not accept 0 length array\n"); return -1; } LOG("Parameter test cases passed\n"); } while(0); LOG("%s - PASSED\n", __func__); return 0; } static int test_string_fns(void) { if (test_rte_strsplit() < 0) return -1; return 0; } static struct test_command string_cmd = { .command = "string_autotest", .callback = test_string_fns, }; REGISTER_TEST_COMMAND(string_cmd); ================================================ FILE: app/test/test_table.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "test.h" #include "test_table.h" #include "test_table_pipeline.h" #include "test_table_ports.h" #include "test_table_tables.h" #include "test_table_combined.h" #include "test_table_acl.h" /* Global variables */ struct rte_pipeline *p; struct rte_ring *rings_rx[N_PORTS]; struct rte_ring *rings_tx[N_PORTS]; struct rte_mempool *pool = NULL; uint32_t port_in_id[N_PORTS]; uint32_t port_out_id[N_PORTS]; uint32_t port_out_id_type[3]; uint32_t table_id[N_PORTS*2]; uint64_t override_hit_mask = 0xFFFFFFFF; uint64_t override_miss_mask = 0xFFFFFFFF; uint64_t non_reserved_actions_hit = 0; uint64_t non_reserved_actions_miss = 0; uint8_t connect_miss_action_to_port_out = 0; uint8_t connect_miss_action_to_table = 0; uint32_t table_entry_default_action = RTE_PIPELINE_ACTION_DROP; uint32_t table_entry_hit_action = RTE_PIPELINE_ACTION_PORT; uint32_t table_entry_miss_action = RTE_PIPELINE_ACTION_DROP; rte_pipeline_port_in_action_handler port_in_action = NULL; rte_pipeline_port_out_action_handler port_out_action = NULL; rte_pipeline_table_action_handler_hit action_handler_hit = NULL; rte_pipeline_table_action_handler_miss action_handler_miss = NULL; /* Function prototypes */ static void app_init_rings(void); static void app_init_mbuf_pools(void); uint64_t pipeline_test_hash(void *key, __attribute__((unused)) uint32_t key_size, __attribute__((unused)) uint64_t seed) { uint32_t *k32 = (uint32_t *) key; uint32_t ip_dst = rte_be_to_cpu_32(k32[0]); uint64_t signature = ip_dst; return signature; } static void app_init_mbuf_pools(void) { /* Init the buffer pool */ printf("Getting/Creating the mempool ...\n"); pool = rte_mempool_lookup("mempool"); if (!pool) { pool = rte_pktmbuf_pool_create( "mempool", POOL_SIZE, POOL_CACHE_SIZE, 0, POOL_BUFFER_SIZE, 0); if (pool == NULL) rte_panic("Cannot create mbuf pool\n"); } } static void app_init_rings(void) { uint32_t i; for (i = 0; i < N_PORTS; i++) { char name[32]; snprintf(name, sizeof(name), "app_ring_rx_%u", i); rings_rx[i] = rte_ring_lookup(name); if (rings_rx[i] == NULL) { rings_rx[i] = rte_ring_create( name, RING_RX_SIZE, 0, RING_F_SP_ENQ | RING_F_SC_DEQ); } if (rings_rx[i] == NULL) rte_panic("Cannot create RX ring %u\n", i); } for (i = 0; i < N_PORTS; i++) { char name[32]; snprintf(name, sizeof(name), "app_ring_tx_%u", i); rings_tx[i] = rte_ring_lookup(name); if (rings_tx[i] == NULL) { rings_tx[i] = rte_ring_create( name, RING_TX_SIZE, 0, RING_F_SP_ENQ | RING_F_SC_DEQ); } if (rings_tx[i] == NULL) rte_panic("Cannot create TX ring %u\n", i); } } static int test_table(void) { int status, failures; unsigned i; failures = 0; app_init_rings(); app_init_mbuf_pools(); printf("\n\n\n\n************Pipeline tests************\n"); if (test_table_pipeline() < 0) return -1; printf("\n\n\n\n************Port tests************\n"); for (i = 0; i < n_port_tests; i++) { status = port_tests[i](); if (status < 0) { printf("\nPort test number %d failed (%d).\n", i, status); failures++; return -1; } } printf("\n\n\n\n************Table tests************\n"); for (i = 0; i < n_table_tests; i++) { status = table_tests[i](); if (status < 0) { printf("\nTable test number %d failed (%d).\n", i, status); failures++; return -1; } } printf("\n\n\n\n************Table tests************\n"); for (i = 0; i < n_table_tests_combined; i++) { status = table_tests_combined[i](); if (status < 0) { printf("\nCombined table test number %d failed with " "reason number %d.\n", i, status); failures++; return -1; } } if (failures) return -1; #ifdef RTE_LIBRTE_ACL printf("\n\n\n\n************ACL tests************\n"); if (test_table_ACL() < 0) return -1; #endif return 0; } static struct test_command table_cmd = { .command = "table_autotest", .callback = test_table, }; REGISTER_TEST_COMMAND(table_cmd); ================================================ FILE: app/test/test_table.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #ifdef RTE_LIBRTE_ACL #include #endif #include #include #include #ifndef TEST_TABLE_H_ #define TEST_TABLE_H_ #define RING_SIZE 4096 #define MAX_BULK 32 #define N 65536 #define TIME_S 5 #define TEST_RING_FULL_EMTPY_ITER 8 #define N_PORTS 2 #define N_PKTS 2 #define N_PKTS_EXT 6 #define RING_RX rings_rx[0] #define RING_RX_2 rings_rx[1] #define RING_TX rings_tx[0] #define RING_TX_2 rings_tx[1] #define PORT_RX_RING_SIZE 128 #define PORT_TX_RING_SIZE 512 #define RING_RX_SIZE 128 #define RING_TX_SIZE 128 #define POOL_BUFFER_SIZE RTE_MBUF_DEFAULT_BUF_SIZE #define POOL_SIZE (32 * 1024) #define POOL_CACHE_SIZE 256 #define BURST_SIZE 8 #define WORKER_TYPE 1 #define MAX_DUMMY_PORTS 2 #define MP_NAME "dummy_port_mempool" #define MBUF_COUNT (8000 * MAX_DUMMY_PORTS) #define MP_CACHE_SZ 256 #define MP_SOCKET 0 #define MP_FLAGS 0 /* Macros */ #define RING_ENQUEUE(ring, value) do { \ struct rte_mbuf *m; \ uint32_t *k32, *signature; \ uint8_t *key; \ \ m = rte_pktmbuf_alloc(pool); \ if (m == NULL) \ return -1; \ signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0); \ key = RTE_MBUF_METADATA_UINT8_PTR(m, 32); \ k32 = (uint32_t *) key; \ k32[0] = (value); \ *signature = pipeline_test_hash(key, 0, 0); \ rte_ring_enqueue((ring), m); \ } while (0) #define RUN_PIPELINE(pipeline) do { \ rte_pipeline_run((pipeline)); \ rte_pipeline_flush((pipeline)); \ } while (0) #define VERIFY(var, value) do { \ if ((var) != -(value)) \ return var; \ } while (0) #define VERIFY_TRAFFIC(ring, sent, expected) do { \ unsigned i, n = 0; \ void *mbuf = NULL; \ \ for (i = 0; i < (sent); i++) { \ if (!rte_ring_dequeue((ring), &mbuf)) { \ if (mbuf == NULL) \ continue; \ n++; \ rte_pktmbuf_free((struct rte_mbuf *)mbuf); \ } \ else \ break; \ } \ printf("Expected %d, got %d\n", expected, n); \ if (n != (expected)) { \ return -21; \ } \ } while (0) /* Function definitions */ uint64_t pipeline_test_hash( void *key, __attribute__((unused)) uint32_t key_size, __attribute__((unused)) uint64_t seed); /* Extern variables */ extern struct rte_pipeline *p; extern struct rte_ring *rings_rx[N_PORTS]; extern struct rte_ring *rings_tx[N_PORTS]; extern struct rte_mempool *pool; extern uint32_t port_in_id[N_PORTS]; extern uint32_t port_out_id[N_PORTS]; extern uint32_t port_out_id_type[3]; extern uint32_t table_id[N_PORTS*2]; extern uint64_t override_hit_mask; extern uint64_t override_miss_mask; extern uint64_t non_reserved_actions_hit; extern uint64_t non_reserved_actions_miss; extern uint8_t connect_miss_action_to_port_out; extern uint8_t connect_miss_action_to_table; extern uint32_t table_entry_default_action; extern uint32_t table_entry_hit_action; extern uint32_t table_entry_miss_action; extern rte_pipeline_port_in_action_handler port_in_action; extern rte_pipeline_port_out_action_handler port_out_action; extern rte_pipeline_table_action_handler_hit action_handler_hit; extern rte_pipeline_table_action_handler_miss action_handler_miss; /* Global data types */ struct manage_ops { uint32_t op_id; void *op_data; int expected_result; }; /* Internal pipeline structures */ struct rte_port_in { struct rte_port_in_ops ops; uint32_t burst_size; uint32_t table_id; void *h_port; }; struct rte_port_out { struct rte_port_out_ops ops; void *h_port; }; struct rte_table { struct rte_table_ops ops; rte_pipeline_table_action_handler_hit f_action; uint32_t table_next_id; uint32_t table_next_id_valid; uint8_t actions_lookup_miss[RTE_CACHE_LINE_SIZE]; uint32_t action_data_size; void *h_table; }; #define RTE_PIPELINE_MAX_NAME_SZ 124 struct rte_pipeline { char name[RTE_PIPELINE_MAX_NAME_SZ]; uint32_t socket_id; struct rte_port_in ports_in[16]; struct rte_port_out ports_out[16]; struct rte_table tables[64]; uint32_t num_ports_in; uint32_t num_ports_out; uint32_t num_tables; struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_table_entry *actions[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t mask_action[64]; uint32_t mask_actions; }; #endif ================================================ FILE: app/test/test_table_acl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "test_table.h" #include "test_table_acl.h" #define IPv4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \ (((b) & 0xff) << 16) | \ (((c) & 0xff) << 8) | \ ((d) & 0xff)) /* * Rule and trace formats definitions. **/ struct ipv4_5tuple { uint8_t proto; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; }; enum { PROTO_FIELD_IPV4, SRC_FIELD_IPV4, DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, NUM_FIELDS_IPV4 }; struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV4, .input_index = PROTO_FIELD_IPV4, .offset = offsetof(struct ipv4_5tuple, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC_FIELD_IPV4, .input_index = SRC_FIELD_IPV4, .offset = offsetof(struct ipv4_5tuple, ip_src), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST_FIELD_IPV4, .input_index = DST_FIELD_IPV4, .offset = offsetof(struct ipv4_5tuple, ip_dst), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV4, .input_index = SRCP_FIELD_IPV4, .offset = offsetof(struct ipv4_5tuple, port_src), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV4, .input_index = SRCP_FIELD_IPV4, .offset = offsetof(struct ipv4_5tuple, port_dst), }, }; struct rte_table_acl_rule_add_params table_acl_IPv4_rule; typedef int (*parse_5tuple)(char *text, struct rte_table_acl_rule_add_params *rule); /* * The order of the fields in the rule string after the initial '@' */ enum { CB_FLD_SRC_ADDR, CB_FLD_DST_ADDR, CB_FLD_SRC_PORT_RANGE, CB_FLD_DST_PORT_RANGE, CB_FLD_PROTO, CB_FLD_NUM, }; #define GET_CB_FIELD(in, fd, base, lim, dlm) \ do { \ unsigned long val; \ char *end; \ \ errno = 0; \ val = strtoul((in), &end, (base)); \ if (errno != 0 || end[0] != (dlm) || val > (lim)) \ return -EINVAL; \ (fd) = (typeof(fd)) val; \ (in) = end + 1; \ } while (0) static int parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) { uint8_t a, b, c, d, m; GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); addr[0] = IPv4(a, b, c, d); mask_len[0] = m; return 0; } static int parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high) { uint16_t a, b; GET_CB_FIELD(in, a, 0, UINT16_MAX, ':'); GET_CB_FIELD(in, b, 0, UINT16_MAX, 0); port_low[0] = a; port_high[0] = b; return 0; } static int parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v) { int i, rc; char *s, *sp, *in[CB_FLD_NUM]; static const char *dlm = " \t\n"; /* ** Skip leading '@' */ if (strchr(str, '@') != str) return -EINVAL; s = str + 1; /* * Populate the 'in' array with the location of each * field in the string we're parsing */ for (i = 0; i != DIM(in); i++) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; s = NULL; } /* Parse x.x.x.x/x */ rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], &v->field_value[SRC_FIELD_IPV4].value.u32, &v->field_value[SRC_FIELD_IPV4].mask_range.u32); if (rc != 0) { RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n", in[CB_FLD_SRC_ADDR]); return rc; } printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32, v->field_value[SRC_FIELD_IPV4].mask_range.u32); /* Parse x.x.x.x/x */ rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], &v->field_value[DST_FIELD_IPV4].value.u32, &v->field_value[DST_FIELD_IPV4].mask_range.u32); if (rc != 0) { RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n", in[CB_FLD_DST_ADDR]); return rc; } printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32, v->field_value[DST_FIELD_IPV4].mask_range.u32); /* Parse n:n */ rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE], &v->field_value[SRCP_FIELD_IPV4].value.u16, &v->field_value[SRCP_FIELD_IPV4].mask_range.u16); if (rc != 0) { RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n", in[CB_FLD_SRC_PORT_RANGE]); return rc; } printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16, v->field_value[SRCP_FIELD_IPV4].mask_range.u16); /* Parse n:n */ rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE], &v->field_value[DSTP_FIELD_IPV4].value.u16, &v->field_value[DSTP_FIELD_IPV4].mask_range.u16); if (rc != 0) { RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n", in[CB_FLD_DST_PORT_RANGE]); return rc; } printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16, v->field_value[DSTP_FIELD_IPV4].mask_range.u16); /* parse 0/0xnn */ GET_CB_FIELD(in[CB_FLD_PROTO], v->field_value[PROTO_FIELD_IPV4].value.u8, 0, UINT8_MAX, '/'); GET_CB_FIELD(in[CB_FLD_PROTO], v->field_value[PROTO_FIELD_IPV4].mask_range.u8, 0, UINT8_MAX, 0); printf("V=%u, mask=%u\n", (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8, v->field_value[PROTO_FIELD_IPV4].mask_range.u8); return 0; } /* * The format for these rules DO NOT need the port ranges to be * separated by ' : ', just ':'. It's a lot more readable and * cleaner, IMO. */ char lines[][128] = { "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */ "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */ "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */ "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */ "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */ }; char line[128]; static int setup_acl_pipeline(void) { int ret; int i; struct rte_pipeline_params pipeline_params = { .name = "PIPELINE", .socket_id = 0, }; uint32_t n; struct rte_table_acl_rule_add_params rule_params; struct rte_pipeline_table_acl_rule_delete_params *delete_params; parse_5tuple parser; char acl_name[64]; /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) { RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n", __func__); goto fail; } /* Input port configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .burst_size = BURST_SIZE, }; /* Put in action for some ports */ if (i) port_params.f_action = port_in_action; ret = rte_pipeline_port_in_create(p, &port_params, &port_in_id[i]); if (ret) { rte_panic("Unable to configure input port %d, ret:%d\n", i, ret); goto fail; } } /* output Port configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = rings_tx[i], .tx_burst_sz = BURST_SIZE, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) { rte_panic("Unable to configure output port %d\n", i); goto fail; } } /* Table configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_pipeline_table_params table_params; /* Set up defaults for stub */ table_params.ops = &rte_table_stub_ops; table_params.arg_create = NULL; table_params.f_action_hit = action_handler_hit; table_params.f_action_miss = NULL; table_params.action_data_size = 0; RTE_LOG(INFO, PIPELINE, "miss_action=%x\n", table_entry_miss_action); printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs), RTE_ACL_RULE_SZ(DIM(ipv4_defs))); struct rte_table_acl_params acl_params; acl_params.n_rules = 1 << 5; acl_params.n_rule_fields = DIM(ipv4_defs); snprintf(acl_name, sizeof(acl_name), "ACL%d", i); acl_params.name = acl_name; memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs)); table_params.ops = &rte_table_acl_ops; table_params.arg_create = &acl_params; if (rte_pipeline_table_create(p, &table_params, &table_id[i])) { rte_panic("Unable to configure table %u\n", i); goto fail; } if (connect_miss_action_to_table) { if (rte_pipeline_table_create(p, &table_params, &table_id[i+2])) { rte_panic("Unable to configure table %u\n", i); goto fail; } } } for (i = 0; i < N_PORTS; i++) { if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id[i])) { rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id[i]); goto fail; } } /* Add entries to tables */ for (i = 0; i < N_PORTS; i++) { struct rte_pipeline_table_entry table_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i^1]}, }; int key_found; struct rte_pipeline_table_entry *entry_ptr; memset(&rule_params, 0, sizeof(rule_params)); parser = parse_cb_ipv4_rule; for (n = 1; n <= 5; n++) { snprintf(line, sizeof(line), "%s", lines[n-1]); printf("PARSING [%s]\n", line); ret = parser(line, &rule_params); if (ret != 0) { RTE_LOG(ERR, PIPELINE, "line %u: parse_cb_ipv4vlan_rule" " failed, error code: %d (%s)\n", n, ret, strerror(-ret)); return ret; } rule_params.priority = RTE_ACL_MAX_PRIORITY - n; ret = rte_pipeline_table_entry_add(p, table_id[i], &rule_params, &table_entry, &key_found, &entry_ptr); if (ret < 0) { rte_panic("Add entry to table %u failed (%d)\n", table_id[i], ret); goto fail; } } /* delete a few rules */ for (n = 2; n <= 3; n++) { snprintf(line, sizeof(line), "%s", lines[n-1]); printf("PARSING [%s]\n", line); ret = parser(line, &rule_params); if (ret != 0) { RTE_LOG(ERR, PIPELINE, "line %u: parse rule " " failed, error code: %d (%s)\n", n, ret, strerror(-ret)); return ret; } delete_params = (struct rte_pipeline_table_acl_rule_delete_params *) &(rule_params.field_value[0]); ret = rte_pipeline_table_entry_delete(p, table_id[i], delete_params, &key_found, NULL); if (ret < 0) { rte_panic("Add entry to table %u failed (%d)\n", table_id[i], ret); goto fail; } else printf("Deleted Rule.\n"); } /* Try to add duplicates */ for (n = 1; n <= 5; n++) { snprintf(line, sizeof(line), "%s", lines[n-1]); printf("PARSING [%s]\n", line); ret = parser(line, &rule_params); if (ret != 0) { RTE_LOG(ERR, PIPELINE, "line %u: parse rule" " failed, error code: %d (%s)\n", n, ret, strerror(-ret)); return ret; } rule_params.priority = RTE_ACL_MAX_PRIORITY - n; ret = rte_pipeline_table_entry_add(p, table_id[i], &rule_params, &table_entry, &key_found, &entry_ptr); if (ret < 0) { rte_panic("Add entry to table %u failed (%d)\n", table_id[i], ret); goto fail; } } } /* Enable input ports */ for (i = 0; i < N_PORTS ; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) { rte_panic("Pipeline consistency check failed\n"); goto fail; } return 0; fail: return -1; } static int test_pipeline_single_filter(int expected_count) { int i, j, ret, tx_count; struct ipv4_5tuple five_tuple; /* Allocate a few mbufs and manually insert into the rings. */ for (i = 0; i < N_PORTS; i++) { for (j = 0; j < 8; j++) { struct rte_mbuf *mbuf; mbuf = rte_pktmbuf_alloc(pool); if (mbuf == NULL) /* this will cause test failure after cleanup * of already enqueued mbufs, as the mbuf * counts won't match */ break; memset(rte_pktmbuf_mtod(mbuf, char *), 0x00, sizeof(struct ipv4_5tuple)); five_tuple.proto = j; five_tuple.ip_src = rte_bswap32(IPv4(192, 168, j, 1)); five_tuple.ip_dst = rte_bswap32(IPv4(10, 4, j, 1)); five_tuple.port_src = rte_bswap16(100 + j); five_tuple.port_dst = rte_bswap16(200 + j); memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple, sizeof(struct ipv4_5tuple)); RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n", __func__, i); rte_ring_enqueue(rings_rx[i], mbuf); } } /* Run pipeline once */ rte_pipeline_run(p); rte_pipeline_flush(p); tx_count = 0; for (i = 0; i < N_PORTS; i++) { void *objs[RING_TX_SIZE]; struct rte_mbuf *mbuf; ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10); if (ret <= 0) { printf("Got no objects from ring %d - error code %d\n", i, ret); } else { printf("Got %d object(s) from ring %d!\n", ret, i); for (j = 0; j < ret; j++) { mbuf = (struct rte_mbuf *)objs[j]; rte_hexdump(stdout, "mbuf", rte_pktmbuf_mtod(mbuf, char *), 64); rte_pktmbuf_free(mbuf); } tx_count += ret; } } if (tx_count != expected_count) { RTE_LOG(INFO, PIPELINE, "%s: Unexpected packets for ACL test, " "expected %d, got %d\n", __func__, expected_count, tx_count); goto fail; } rte_pipeline_free(p); return 0; fail: return -1; } int test_table_ACL(void) { override_hit_mask = 0xFF; /* All packets are a hit */ setup_acl_pipeline(); if (test_pipeline_single_filter(10) < 0) return -1; return 0; } ================================================ FILE: app/test/test_table_acl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test prototypes */ int test_table_ACL(void); ================================================ FILE: app/test/test_table_combined.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "test_table_combined.h" #include "test_table.h" #include #define MAX_TEST_KEYS 128 #define N_PACKETS 50 enum check_table_result { CHECK_TABLE_OK, CHECK_TABLE_PORT_CONFIG, CHECK_TABLE_PORT_ENABLE, CHECK_TABLE_TABLE_CONFIG, CHECK_TABLE_ENTRY_ADD, CHECK_TABLE_DEFAULT_ENTRY_ADD, CHECK_TABLE_CONNECT, CHECK_TABLE_MANAGE_ERROR, CHECK_TABLE_CONSISTENCY, CHECK_TABLE_NO_TRAFFIC, CHECK_TABLE_INVALID_PARAMETER, }; struct table_packets { uint32_t hit_packet[MAX_TEST_KEYS]; uint32_t miss_packet[MAX_TEST_KEYS]; uint32_t n_hit_packets; uint32_t n_miss_packets; }; combined_table_test table_tests_combined[] = { test_table_lpm_combined, test_table_lpm_ipv6_combined, test_table_hash8lru, test_table_hash8ext, test_table_hash16lru, test_table_hash16ext, test_table_hash32lru, test_table_hash32ext, }; unsigned n_table_tests_combined = RTE_DIM(table_tests_combined); /* Generic port tester function */ static int test_table_type(struct rte_table_ops *table_ops, void *table_args, void *key, struct table_packets *table_packets, struct manage_ops *manage_ops, unsigned n_ops) { uint32_t ring_in_id, table_id, ring_out_id, ring_out_2_id; unsigned i; RTE_SET_USED(manage_ops); RTE_SET_USED(n_ops); /* Create pipeline */ struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = 0, }; struct rte_pipeline *pipeline = rte_pipeline_create(&pipeline_params); /* Create input ring */ struct rte_port_ring_reader_params ring_params_rx = { .ring = RING_RX, }; struct rte_port_ring_writer_params ring_params_tx = { .ring = RING_RX, .tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX, }; struct rte_pipeline_port_in_params ring_in_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *)&ring_params_rx, .f_action = NULL, .burst_size = RTE_PORT_IN_BURST_SIZE_MAX, }; if (rte_pipeline_port_in_create(pipeline, &ring_in_params, &ring_in_id) != 0) return -CHECK_TABLE_PORT_CONFIG; /* Create table */ struct rte_pipeline_table_params table_params = { .ops = table_ops, .arg_create = table_args, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(pipeline, &table_params, &table_id) != 0) return -CHECK_TABLE_TABLE_CONFIG; /* Create output ports */ ring_params_tx.ring = RING_TX; struct rte_pipeline_port_out_params ring_out_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *)&ring_params_tx, .f_action = NULL, }; if (rte_pipeline_port_out_create(pipeline, &ring_out_params, &ring_out_id) != 0) return -CHECK_TABLE_PORT_CONFIG; ring_params_tx.ring = RING_TX_2; if (rte_pipeline_port_out_create(pipeline, &ring_out_params, &ring_out_2_id) != 0) return -CHECK_TABLE_PORT_CONFIG; /* Add entry to the table */ struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_DROP, {.table_id = ring_out_id}, }; struct rte_pipeline_table_entry table_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.table_id = ring_out_id}, }; struct rte_pipeline_table_entry *default_entry_ptr, *entry_ptr; int key_found; if (rte_pipeline_table_default_entry_add(pipeline, table_id, &default_entry, &default_entry_ptr) != 0) return -CHECK_TABLE_DEFAULT_ENTRY_ADD; if (rte_pipeline_table_entry_add(pipeline, table_id, key ? key : &table_entry, &table_entry, &key_found, &entry_ptr) != 0) return -CHECK_TABLE_ENTRY_ADD; /* Create connections and check consistency */ if (rte_pipeline_port_in_connect_to_table(pipeline, ring_in_id, table_id) != 0) return -CHECK_TABLE_CONNECT; if (rte_pipeline_port_in_enable(pipeline, ring_in_id) != 0) return -CHECK_TABLE_PORT_ENABLE; if (rte_pipeline_check(pipeline) != 0) return -CHECK_TABLE_CONSISTENCY; /* Flow test - All hits */ if (table_packets->n_hit_packets) { for (i = 0; i < table_packets->n_hit_packets; i++) RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, table_packets->n_hit_packets); } /* Flow test - All misses */ if (table_packets->n_miss_packets) { for (i = 0; i < table_packets->n_miss_packets; i++) RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0); } /* Flow test - Half hits, half misses */ if (table_packets->n_hit_packets && table_packets->n_miss_packets) { for (i = 0; i < (table_packets->n_hit_packets) / 2; i++) RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]); for (i = 0; i < (table_packets->n_miss_packets) / 2; i++) RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, table_packets->n_hit_packets / 2); } /* Flow test - Single packet */ if (table_packets->n_hit_packets) { RING_ENQUEUE(RING_RX, table_packets->hit_packet[0]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 1); } if (table_packets->n_miss_packets) { RING_ENQUEUE(RING_RX, table_packets->miss_packet[0]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0); } /* Change table entry action */ printf("Change entry action\n"); table_entry.table_id = ring_out_2_id; if (rte_pipeline_table_default_entry_add(pipeline, table_id, &default_entry, &default_entry_ptr) != 0) return -CHECK_TABLE_ENTRY_ADD; if (rte_pipeline_table_entry_add(pipeline, table_id, key ? key : &table_entry, &table_entry, &key_found, &entry_ptr) != 0) return -CHECK_TABLE_ENTRY_ADD; /* Check that traffic destination has changed */ if (table_packets->n_hit_packets) { for (i = 0; i < table_packets->n_hit_packets; i++) RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]); RUN_PIPELINE(pipeline); VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 0); VERIFY_TRAFFIC(RING_TX_2, table_packets->n_hit_packets, table_packets->n_hit_packets); } printf("delete entry\n"); /* Delete table entry */ rte_pipeline_table_entry_delete(pipeline, table_id, key ? key : &table_entry, &key_found, NULL); rte_pipeline_free(pipeline); return 0; } /* Table tests */ int test_table_stub_combined(void) { int status, i; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < N_PACKETS; i++) table_packets.hit_packet[i] = i; table_packets.n_hit_packets = N_PACKETS; table_packets.n_miss_packets = 0; status = test_table_type(&rte_table_stub_ops, NULL, NULL, &table_packets, NULL, 1); VERIFY(status, CHECK_TABLE_OK); return 0; } int test_table_lpm_combined(void) { int status, i; /* Traffic flow */ struct rte_table_lpm_params lpm_params = { .n_rules = 1 << 16, .entry_unique_size = 8, .offset = 0, }; struct rte_table_lpm_key lpm_key = { .ip = 0xadadadad, .depth = 16, }; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < N_PACKETS; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < N_PACKETS; i++) table_packets.miss_packet[i] = 0xfefefefe; table_packets.n_hit_packets = N_PACKETS; table_packets.n_miss_packets = N_PACKETS; status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params, (void *)&lpm_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ lpm_params.n_rules = 0; status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params, (void *)&lpm_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); lpm_params.n_rules = 1 << 24; lpm_key.depth = 0; status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params, (void *)&lpm_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_ENTRY_ADD); lpm_key.depth = 33; status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params, (void *)&lpm_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_ENTRY_ADD); return 0; } int test_table_lpm_ipv6_combined(void) { int status, i; /* Traffic flow */ struct rte_table_lpm_ipv6_params lpm_ipv6_params = { .n_rules = 1 << 16, .number_tbl8s = 1 << 13, .entry_unique_size = 8, .offset = 32, }; struct rte_table_lpm_ipv6_key lpm_ipv6_key = { .depth = 16, }; memset(lpm_ipv6_key.ip, 0xad, 16); struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < N_PACKETS; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < N_PACKETS; i++) table_packets.miss_packet[i] = 0xadadadab; table_packets.n_hit_packets = N_PACKETS; table_packets.n_miss_packets = N_PACKETS; status = test_table_type(&rte_table_lpm_ipv6_ops, (void *)&lpm_ipv6_params, (void *)&lpm_ipv6_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ lpm_ipv6_params.n_rules = 0; status = test_table_type(&rte_table_lpm_ipv6_ops, (void *)&lpm_ipv6_params, (void *)&lpm_ipv6_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); lpm_ipv6_params.n_rules = 1 << 24; lpm_ipv6_key.depth = 0; status = test_table_type(&rte_table_lpm_ipv6_ops, (void *)&lpm_ipv6_params, (void *)&lpm_ipv6_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_ENTRY_ADD); lpm_ipv6_key.depth = 129; status = test_table_type(&rte_table_lpm_ipv6_ops, (void *)&lpm_ipv6_params, (void *)&lpm_ipv6_key, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_ENTRY_ADD); return 0; } int test_table_hash8lru(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key8_lru_params key8lru_params = { .n_entries = 1<<24, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key8lru[8]; uint32_t *k8lru = (uint32_t *) key8lru; memset(key8lru, 0, sizeof(key8lru)); k8lru[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xfefefefe; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key8_lru_ops, (void *)&key8lru_params, (void *)key8lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key8lru_params.n_entries = 0; status = test_table_type(&rte_table_hash_key8_lru_ops, (void *)&key8lru_params, (void *)key8lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key8lru_params.n_entries = 1<<16; key8lru_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key8_lru_ops, (void *)&key8lru_params, (void *)key8lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } int test_table_hash16lru(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key16_lru_params key16lru_params = { .n_entries = 1<<16, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key16lru[16]; uint32_t *k16lru = (uint32_t *) key16lru; memset(key16lru, 0, sizeof(key16lru)); k16lru[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xfefefefe; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key16_lru_ops, (void *)&key16lru_params, (void *)key16lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key16lru_params.n_entries = 0; status = test_table_type(&rte_table_hash_key16_lru_ops, (void *)&key16lru_params, (void *)key16lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key16lru_params.n_entries = 1<<16; key16lru_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key16_lru_ops, (void *)&key16lru_params, (void *)key16lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } int test_table_hash32lru(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key32_lru_params key32lru_params = { .n_entries = 1<<16, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key32lru[32]; uint32_t *k32lru = (uint32_t *) key32lru; memset(key32lru, 0, sizeof(key32lru)); k32lru[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xbdadadad; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key32_lru_ops, (void *)&key32lru_params, (void *)key32lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key32lru_params.n_entries = 0; status = test_table_type(&rte_table_hash_key32_lru_ops, (void *)&key32lru_params, (void *)key32lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key32lru_params.n_entries = 1<<16; key32lru_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key32_lru_ops, (void *)&key32lru_params, (void *)key32lru, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } int test_table_hash8ext(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key8_ext_params key8ext_params = { .n_entries = 1<<16, .n_entries_ext = 1<<15, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key8ext[8]; uint32_t *k8ext = (uint32_t *) key8ext; memset(key8ext, 0, sizeof(key8ext)); k8ext[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xbdadadad; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key8_ext_ops, (void *)&key8ext_params, (void *)key8ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key8ext_params.n_entries = 0; status = test_table_type(&rte_table_hash_key8_ext_ops, (void *)&key8ext_params, (void *)key8ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key8ext_params.n_entries = 1<<16; key8ext_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key8_ext_ops, (void *)&key8ext_params, (void *)key8ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key8ext_params.f_hash = pipeline_test_hash; key8ext_params.n_entries_ext = 0; status = test_table_type(&rte_table_hash_key8_ext_ops, (void *)&key8ext_params, (void *)key8ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } int test_table_hash16ext(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key16_ext_params key16ext_params = { .n_entries = 1<<16, .n_entries_ext = 1<<15, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key16ext[16]; uint32_t *k16ext = (uint32_t *) key16ext; memset(key16ext, 0, sizeof(key16ext)); k16ext[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xbdadadad; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key16_ext_ops, (void *)&key16ext_params, (void *)key16ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key16ext_params.n_entries = 0; status = test_table_type(&rte_table_hash_key16_ext_ops, (void *)&key16ext_params, (void *)key16ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key16ext_params.n_entries = 1<<16; key16ext_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key16_ext_ops, (void *)&key16ext_params, (void *)key16ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key16ext_params.f_hash = pipeline_test_hash; key16ext_params.n_entries_ext = 0; status = test_table_type(&rte_table_hash_key16_ext_ops, (void *)&key16ext_params, (void *)key16ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } int test_table_hash32ext(void) { int status, i; /* Traffic flow */ struct rte_table_hash_key32_ext_params key32ext_params = { .n_entries = 1<<16, .n_entries_ext = 1<<15, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; uint8_t key32ext[32]; uint32_t *k32ext = (uint32_t *) key32ext; memset(key32ext, 0, sizeof(key32ext)); k32ext[0] = 0xadadadad; struct table_packets table_packets; printf("--------------\n"); printf("RUNNING TEST - %s\n", __func__); printf("--------------\n"); for (i = 0; i < 50; i++) table_packets.hit_packet[i] = 0xadadadad; for (i = 0; i < 50; i++) table_packets.miss_packet[i] = 0xbdadadad; table_packets.n_hit_packets = 50; table_packets.n_miss_packets = 50; status = test_table_type(&rte_table_hash_key32_ext_ops, (void *)&key32ext_params, (void *)key32ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_OK); /* Invalid parameters */ key32ext_params.n_entries = 0; status = test_table_type(&rte_table_hash_key32_ext_ops, (void *)&key32ext_params, (void *)key32ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key32ext_params.n_entries = 1<<16; key32ext_params.f_hash = NULL; status = test_table_type(&rte_table_hash_key32_ext_ops, (void *)&key32ext_params, (void *)key32ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); key32ext_params.f_hash = pipeline_test_hash; key32ext_params.n_entries_ext = 0; status = test_table_type(&rte_table_hash_key32_ext_ops, (void *)&key32ext_params, (void *)key32ext, &table_packets, NULL, 0); VERIFY(status, CHECK_TABLE_TABLE_CONFIG); return 0; } ================================================ FILE: app/test/test_table_combined.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test prototypes */ int test_table_stub_combined(void); int test_table_lpm_combined(void); int test_table_lpm_ipv6_combined(void); #ifdef RTE_LIBRTE_ACL int test_table_acl(void); #endif int test_table_hash8unoptimized(void); int test_table_hash8lru(void); int test_table_hash8ext(void); int test_table_hash16unoptimized(void); int test_table_hash16lru(void); int test_table_hash16ext(void); int test_table_hash32unoptimized(void); int test_table_hash32lru(void); int test_table_hash32ext(void); /* Extern variables */ typedef int (*combined_table_test)(void); extern combined_table_test table_tests_combined[]; extern unsigned n_table_tests_combined; ================================================ FILE: app/test/test_table_pipeline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test_table.h" #include "test_table_pipeline.h" #if 0 static rte_pipeline_port_out_action_handler port_action_0x00 (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg); static rte_pipeline_port_out_action_handler port_action_0xFF (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg); static rte_pipeline_port_out_action_handler port_action_stub (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg); rte_pipeline_port_out_action_handler port_action_0x00(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg) { RTE_SET_USED(pkts); RTE_SET_USED(n); RTE_SET_USED(arg); printf("Port Action 0x00\n"); *pkts_mask = 0x00; return 0; } rte_pipeline_port_out_action_handler port_action_0xFF(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg) { RTE_SET_USED(pkts); RTE_SET_USED(n); RTE_SET_USED(arg); printf("Port Action 0xFF\n"); *pkts_mask = 0xFF; return 0; } rte_pipeline_port_out_action_handler port_action_stub(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg) { RTE_SET_USED(pkts); RTE_SET_USED(n); RTE_SET_USED(pkts_mask); RTE_SET_USED(arg); printf("Port Action stub\n"); return 0; } #endif rte_pipeline_table_action_handler_hit table_action_0x00(struct rte_mbuf **pkts, uint64_t *pkts_mask, struct rte_pipeline_table_entry **actions, uint32_t action_mask); rte_pipeline_table_action_handler_hit table_action_stub_hit(struct rte_mbuf **pkts, uint64_t *pkts_mask, struct rte_pipeline_table_entry **actions, uint32_t action_mask); rte_pipeline_table_action_handler_miss table_action_stub_miss(struct rte_mbuf **pkts, uint64_t *pkts_mask, struct rte_pipeline_table_entry *action, uint32_t action_mask); rte_pipeline_table_action_handler_hit table_action_0x00(__attribute__((unused)) struct rte_mbuf **pkts, uint64_t *pkts_mask, __attribute__((unused)) struct rte_pipeline_table_entry **actions, __attribute__((unused)) uint32_t action_mask) { printf("Table Action, setting pkts_mask to 0x00\n"); *pkts_mask = 0x00; return 0; } rte_pipeline_table_action_handler_hit table_action_stub_hit(__attribute__((unused)) struct rte_mbuf **pkts, uint64_t *pkts_mask, __attribute__((unused)) struct rte_pipeline_table_entry **actions, __attribute__((unused)) uint32_t action_mask) { printf("STUB Table Action Hit - doing nothing\n"); printf("STUB Table Action Hit - setting mask to 0x%"PRIx64"\n", override_hit_mask); *pkts_mask = override_hit_mask; return 0; } rte_pipeline_table_action_handler_miss table_action_stub_miss(__attribute__((unused)) struct rte_mbuf **pkts, uint64_t *pkts_mask, __attribute__((unused)) struct rte_pipeline_table_entry *action, __attribute__((unused)) uint32_t action_mask) { printf("STUB Table Action Miss - setting mask to 0x%"PRIx64"\n", override_miss_mask); *pkts_mask = override_miss_mask; return 0; } enum e_test_type { e_TEST_STUB = 0, e_TEST_LPM, e_TEST_LPM6, e_TEST_HASH_LRU_8, e_TEST_HASH_LRU_16, e_TEST_HASH_LRU_32, e_TEST_HASH_EXT_8, e_TEST_HASH_EXT_16, e_TEST_HASH_EXT_32 }; char pipeline_test_names[][64] = { "Stub", "LPM", "LPMv6", "8-bit LRU Hash", "16-bit LRU Hash", "32-bit LRU Hash", "16-bit Ext Hash", "8-bit Ext Hash", "32-bit Ext Hash", "" }; static int cleanup_pipeline(void) { rte_pipeline_free(p); return 0; } static int check_pipeline_invalid_params(void); static int check_pipeline_invalid_params(void) { struct rte_pipeline_params pipeline_params_1 = { .name = NULL, .socket_id = 0, }; struct rte_pipeline_params pipeline_params_2 = { .name = "PIPELINE", .socket_id = -1, }; struct rte_pipeline_params pipeline_params_3 = { .name = "PIPELINE", .socket_id = 127, }; p = rte_pipeline_create(NULL); if (p != NULL) { RTE_LOG(INFO, PIPELINE, "%s: configured pipeline with null params\n", __func__); goto fail; } p = rte_pipeline_create(&pipeline_params_1); if (p != NULL) { RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with NULL " "name\n", __func__); goto fail; } p = rte_pipeline_create(&pipeline_params_2); if (p != NULL) { RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid " "socket\n", __func__); goto fail; } p = rte_pipeline_create(&pipeline_params_3); if (p != NULL) { RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid " "socket\n", __func__); goto fail; } /* Check pipeline consistency */ if (!rte_pipeline_check(p)) { rte_panic("Pipeline consistency reported as OK\n"); goto fail; } return 0; fail: return -1; } static int setup_pipeline(int test_type) { int ret; int i; struct rte_pipeline_params pipeline_params = { .name = "PIPELINE", .socket_id = 0, }; RTE_LOG(INFO, PIPELINE, "%s: **** Setting up %s test\n", __func__, pipeline_test_names[test_type]); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) { RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n", __func__); goto fail; } ret = rte_pipeline_free(p); if (ret != 0) { RTE_LOG(INFO, PIPELINE, "%s: Failed to free pipeline\n", __func__); goto fail; } /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) { RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n", __func__); goto fail; } /* Input port configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .burst_size = BURST_SIZE, }; /* Put in action for some ports */ if (i) port_params.f_action = NULL; ret = rte_pipeline_port_in_create(p, &port_params, &port_in_id[i]); if (ret) { rte_panic("Unable to configure input port %d, ret:%d\n", i, ret); goto fail; } } /* output Port configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = rings_tx[i], .tx_burst_sz = BURST_SIZE, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, }; if (i) port_params.f_action = port_out_action; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) { rte_panic("Unable to configure output port %d\n", i); goto fail; } } /* Table configuration */ for (i = 0; i < N_PORTS; i++) { struct rte_pipeline_table_params table_params = { .ops = &rte_table_stub_ops, .arg_create = NULL, .f_action_hit = action_handler_hit, .f_action_miss = action_handler_miss, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id[i])) { rte_panic("Unable to configure table %u\n", i); goto fail; } if (connect_miss_action_to_table) if (rte_pipeline_table_create(p, &table_params, &table_id[i+2])) { rte_panic("Unable to configure table %u\n", i); goto fail; } } for (i = 0; i < N_PORTS; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id[i])) { rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id[i]); goto fail; } /* Add entries to tables */ for (i = 0; i < N_PORTS; i++) { struct rte_pipeline_table_entry default_entry = { .action = (enum rte_pipeline_action) table_entry_default_action, {.port_id = port_out_id[i^1]}, }; struct rte_pipeline_table_entry *default_entry_ptr; if (connect_miss_action_to_table) { printf("Setting first table to output to next table\n"); default_entry.action = RTE_PIPELINE_ACTION_TABLE; default_entry.table_id = table_id[i+2]; } /* Add the default action for the table. */ ret = rte_pipeline_table_default_entry_add(p, table_id[i], &default_entry, &default_entry_ptr); if (ret < 0) { rte_panic("Unable to add default entry to table %u " "code %d\n", table_id[i], ret); goto fail; } else printf("Added default entry to table id %d with " "action %x\n", table_id[i], default_entry.action); if (connect_miss_action_to_table) { /* We create a second table so the first can pass traffic into it */ struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i^1]}, }; printf("Setting secont table to output to port\n"); /* Add the default action for the table. */ ret = rte_pipeline_table_default_entry_add(p, table_id[i+2], &default_entry, &default_entry_ptr); if (ret < 0) { rte_panic("Unable to add default entry to " "table %u code %d\n", table_id[i], ret); goto fail; } else printf("Added default entry to table id %d " "with action %x\n", table_id[i], default_entry.action); } } /* Enable input ports */ for (i = 0; i < N_PORTS ; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) { rte_panic("Pipeline consistency check failed\n"); goto fail; } else printf("Pipeline Consistency OK!\n"); return 0; fail: return -1; } static int test_pipeline_single_filter(int test_type, int expected_count) { int i; int j; int ret; int tx_count; RTE_LOG(INFO, PIPELINE, "%s: **** Running %s test\n", __func__, pipeline_test_names[test_type]); /* Run pipeline once */ rte_pipeline_run(p); ret = rte_pipeline_flush(NULL); if (ret != -EINVAL) { RTE_LOG(INFO, PIPELINE, "%s: No pipeline flush error NULL pipeline (%d)\n", __func__, ret); goto fail; } /* * Allocate a few mbufs and manually insert into the rings. */ for (i = 0; i < N_PORTS; i++) for (j = 0; j < N_PORTS; j++) { struct rte_mbuf *m; uint8_t *key; uint32_t *k32; m = rte_pktmbuf_alloc(pool); if (m == NULL) { rte_panic("Failed to alloc mbuf from pool\n"); return -1; } key = RTE_MBUF_METADATA_UINT8_PTR(m, 32); k32 = (uint32_t *) key; k32[0] = 0xadadadad >> (j % 2); RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n", __func__, i); rte_ring_enqueue(rings_rx[i], m); } /* Run pipeline once */ rte_pipeline_run(p); /* * need to flush the pipeline, as there may be less hits than the burst size and they will not have been flushed to the tx rings. */ rte_pipeline_flush(p); /* * Now we'll see what we got back on the tx rings. We should see whatever * packets we had hits on that were destined for the output ports. */ tx_count = 0; for (i = 0; i < N_PORTS; i++) { void *objs[RING_TX_SIZE]; struct rte_mbuf *mbuf; ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10); if (ret <= 0) printf("Got no objects from ring %d - error code %d\n", i, ret); else { printf("Got %d object(s) from ring %d!\n", ret, i); for (j = 0; j < ret; j++) { mbuf = (struct rte_mbuf *)objs[j]; rte_hexdump(stdout, "Object:", rte_pktmbuf_mtod(mbuf, char *), mbuf->data_len); rte_pktmbuf_free(mbuf); } tx_count += ret; } } if (tx_count != expected_count) { RTE_LOG(INFO, PIPELINE, "%s: Unexpected packets out for %s test, expected %d, " "got %d\n", __func__, pipeline_test_names[test_type], expected_count, tx_count); goto fail; } cleanup_pipeline(); return 0; fail: return -1; } int test_table_pipeline(void) { /* TEST - All packets dropped */ action_handler_hit = NULL; action_handler_miss = NULL; table_entry_default_action = RTE_PIPELINE_ACTION_DROP; setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 0) < 0) return -1; /* TEST - All packets passed through */ table_entry_default_action = RTE_PIPELINE_ACTION_PORT; setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0) return -1; /* TEST - one packet per port */ action_handler_hit = NULL; action_handler_miss = (rte_pipeline_table_action_handler_miss) table_action_stub_miss; table_entry_default_action = RTE_PIPELINE_ACTION_PORT; override_miss_mask = 0x01; /* one packet per port */ setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0) return -1; /* TEST - one packet per port */ override_miss_mask = 0x02; /*all per port */ setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0) return -1; /* TEST - all packets per port */ override_miss_mask = 0x03; /*all per port */ setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0) return -1; /* * This test will set up two tables in the pipeline. the first table * will forward to another table on miss, and the second table will * forward to port. */ connect_miss_action_to_table = 1; table_entry_default_action = RTE_PIPELINE_ACTION_TABLE; action_handler_hit = NULL; /* not for stub, hitmask always zero */ action_handler_miss = NULL; setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0) return -1; connect_miss_action_to_table = 0; printf("TEST - two tables, hitmask override to 0x01\n"); connect_miss_action_to_table = 1; action_handler_miss = (rte_pipeline_table_action_handler_miss)table_action_stub_miss; override_miss_mask = 0x01; setup_pipeline(e_TEST_STUB); if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0) return -1; connect_miss_action_to_table = 0; if (check_pipeline_invalid_params()) { RTE_LOG(INFO, PIPELINE, "%s: Check pipeline invalid params " "failed.\n", __func__); return -1; } return 0; } ================================================ FILE: app/test/test_table_pipeline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test prototypes */ int test_table_pipeline(void); ================================================ FILE: app/test/test_table_ports.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_table_ports.h" #include "test_table.h" port_test port_tests[] = { test_port_ring_reader, test_port_ring_writer, }; unsigned n_port_tests = RTE_DIM(port_tests); /* Port tests */ int test_port_ring_reader(void) { int status, i; struct rte_port_ring_reader_params port_ring_reader_params; void *port; /* Invalid params */ port = rte_port_ring_reader_ops.f_create(NULL, 0); if (port != NULL) return -1; status = rte_port_ring_reader_ops.f_free(port); if (status >= 0) return -2; /* Create and free */ port_ring_reader_params.ring = RING_RX; port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0); if (port == NULL) return -3; status = rte_port_ring_reader_ops.f_free(port); if (status != 0) return -4; /* -- Traffic RX -- */ int expected_pkts, received_pkts; struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX]; void *mbuf[RTE_PORT_IN_BURST_SIZE_MAX]; port_ring_reader_params.ring = RING_RX; port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0); /* Single packet */ mbuf[0] = (void *)rte_pktmbuf_alloc(pool); expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring, mbuf, 1); received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf, 1); if (received_pkts < expected_pkts) return -5; rte_pktmbuf_free(res_mbuf[0]); /* Multiple packets */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) mbuf[i] = rte_pktmbuf_alloc(pool); expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring, (void * const *) mbuf, RTE_PORT_IN_BURST_SIZE_MAX); received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX); if (received_pkts < expected_pkts) return -6; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(res_mbuf[i]); return 0; } int test_port_ring_writer(void) { int status, i; struct rte_port_ring_writer_params port_ring_writer_params; void *port; /* Invalid params */ port = rte_port_ring_writer_ops.f_create(NULL, 0); if (port != NULL) return -1; status = rte_port_ring_writer_ops.f_free(port); if (status >= 0) return -2; port_ring_writer_params.ring = NULL; port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0); if (port != NULL) return -3; port_ring_writer_params.ring = RING_TX; port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX + 1; port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0); if (port != NULL) return -4; /* Create and free */ port_ring_writer_params.ring = RING_TX; port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX; port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0); if (port == NULL) return -5; status = rte_port_ring_writer_ops.f_free(port); if (status != 0) return -6; /* -- Traffic TX -- */ int expected_pkts, received_pkts; struct rte_mbuf *mbuf[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX]; port_ring_writer_params.ring = RING_TX; port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX; port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0); /* Single packet */ mbuf[0] = rte_pktmbuf_alloc(pool); rte_port_ring_writer_ops.f_tx(port, mbuf[0]); rte_port_ring_writer_ops.f_flush(port); expected_pkts = 1; received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring, (void **)res_mbuf, port_ring_writer_params.tx_burst_sz); if (received_pkts < expected_pkts) return -7; rte_pktmbuf_free(res_mbuf[0]); /* Multiple packets */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) { mbuf[i] = rte_pktmbuf_alloc(pool); rte_port_ring_writer_ops.f_tx(port, mbuf[i]); } expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX; received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring, (void **)res_mbuf, port_ring_writer_params.tx_burst_sz); if (received_pkts < expected_pkts) return -8; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(res_mbuf[i]); /* TX Bulk */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) mbuf[i] = rte_pktmbuf_alloc(pool); rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-1); expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX; received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring, (void **)res_mbuf, port_ring_writer_params.tx_burst_sz); if (received_pkts < expected_pkts) return -8; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(res_mbuf[i]); for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) mbuf[i] = rte_pktmbuf_alloc(pool); rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-3); rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)2); expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX; received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring, (void **)res_mbuf, port_ring_writer_params.tx_burst_sz); if (received_pkts < expected_pkts) return -9; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(res_mbuf[i]); return 0; } ================================================ FILE: app/test/test_table_ports.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test prototypes */ int test_port_ring_reader(void); int test_port_ring_writer(void); /* Extern variables */ typedef int (*port_test)(void); extern port_test port_tests[]; extern unsigned n_port_tests; ================================================ FILE: app/test/test_table_tables.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test_table_tables.h" #include "test_table.h" table_test table_tests[] = { test_table_stub, test_table_array, test_table_lpm, test_table_lpm_ipv6, test_table_hash_lru, test_table_hash_ext, }; #define PREPARE_PACKET(mbuf, value) do { \ uint32_t *k32, *signature; \ uint8_t *key; \ mbuf = rte_pktmbuf_alloc(pool); \ signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, 0); \ key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, 32); \ memset(key, 0, 32); \ k32 = (uint32_t *) key; \ k32[0] = (value); \ *signature = pipeline_test_hash(key, 0, 0); \ } while (0) unsigned n_table_tests = RTE_DIM(table_tests); /* Function prototypes */ static int test_table_hash_lru_generic(struct rte_table_ops *ops); static int test_table_hash_ext_generic(struct rte_table_ops *ops); struct rte_bucket_4_8 { /* Cache line 0 */ uint64_t signature; uint64_t lru_list; struct rte_bucket_4_8 *next; uint64_t next_valid; uint64_t key[4]; /* Cache line 1 */ uint8_t data[0]; }; #if RTE_TABLE_HASH_LRU_STRATEGY == 3 uint64_t shuffles = 0xfffffffdfffbfff9ULL; #else uint64_t shuffles = 0x0003000200010000ULL; #endif static int test_lru_update(void) { struct rte_bucket_4_8 b; struct rte_bucket_4_8 *bucket; uint32_t i; uint64_t pos; uint64_t iterations; uint64_t j; int poss; printf("---------------------------\n"); printf("Testing lru_update macro...\n"); printf("---------------------------\n"); bucket = &b; iterations = 10; #if RTE_TABLE_HASH_LRU_STRATEGY == 3 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL; #else bucket->lru_list = 0x0000000100020003ULL; #endif poss = 0; for (j = 0; j < iterations; j++) for (i = 0; i < 9; i++) { uint32_t idx = i >> 1; lru_update(bucket, idx); pos = lru_pos(bucket); poss += pos; printf("%s: %d lru_list=%016"PRIx64", upd=%d, " "pos=%"PRIx64"\n", __func__, i, bucket->lru_list, i>>1, pos); } if (bucket->lru_list != shuffles) { printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016" PRIx64"\n", __func__, i, bucket->lru_list, shuffles); return -1; } printf("%s: output checksum of results =%d\n", __func__, poss); #if 0 if (poss != 126) { printf("%s: ERROR output checksum of results =%d expected %d\n", __func__, poss, 126); return -1; } #endif fflush(stdout); uint64_t sc_start = rte_rdtsc(); iterations = 100000000; poss = 0; for (j = 0; j < iterations; j++) { for (i = 0; i < 4; i++) { lru_update(bucket, i); pos |= bucket->lru_list; } } uint64_t sc_end = rte_rdtsc(); printf("%s: output checksum of results =%llu\n", __func__, (long long unsigned int)pos); printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n", __func__, sc_start, sc_end); printf("\nlru_update: %lu cycles per loop iteration.\n\n", (long unsigned int)((sc_end-sc_start)/(iterations*4))); return 0; } /* Table tests */ int test_table_stub(void) { int i; uint64_t expected_mask = 0, result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; /* Create */ table = rte_table_stub_ops.f_create(NULL, 0, 1); if (table == NULL) return -1; /* Traffic flow */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) PREPARE_PACKET(mbufs[i], 0xadadadad); else PREPARE_PACKET(mbufs[i], 0xadadadab); expected_mask = 0; rte_table_stub_ops.f_lookup(table, mbufs, -1, &result_mask, (void **)entries); if (result_mask != expected_mask) return -2; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); return 0; } int test_table_array(void) { int status, i; uint64_t result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; char entry1, entry2; void *entry_ptr; int key_found; /* Initialize params and create tables */ struct rte_table_array_params array_params = { .n_entries = 7, .offset = 1 }; table = rte_table_array_ops.f_create(NULL, 0, 1); if (table != NULL) return -1; array_params.n_entries = 0; table = rte_table_array_ops.f_create(&array_params, 0, 1); if (table != NULL) return -2; array_params.n_entries = 7; table = rte_table_array_ops.f_create(&array_params, 0, 1); if (table != NULL) return -3; array_params.n_entries = 1 << 24; array_params.offset = 1; table = rte_table_array_ops.f_create(&array_params, 0, 1); if (table == NULL) return -4; array_params.offset = 32; table = rte_table_array_ops.f_create(&array_params, 0, 1); if (table == NULL) return -5; /* Free */ status = rte_table_array_ops.f_free(table); if (status < 0) return -6; status = rte_table_array_ops.f_free(NULL); if (status == 0) return -7; /* Add */ struct rte_table_array_key array_key_1 = { .pos = 10, }; struct rte_table_array_key array_key_2 = { .pos = 20, }; entry1 = 'A'; entry2 = 'B'; table = rte_table_array_ops.f_create(&array_params, 0, 1); if (table == NULL) return -8; status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1, &key_found, &entry_ptr); if (status == 0) return -9; status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL, &key_found, &entry_ptr); if (status == 0) return -10; status = rte_table_array_ops.f_add(table, (void *) &array_key_1, &entry1, &key_found, &entry_ptr); if (status != 0) return -11; /* Traffic flow */ status = rte_table_array_ops.f_add(table, (void *) &array_key_2, &entry2, &key_found, &entry_ptr); if (status != 0) return -12; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) PREPARE_PACKET(mbufs[i], 10); else PREPARE_PACKET(mbufs[i], 20); rte_table_array_ops.f_lookup(table, mbufs, -1, &result_mask, (void **)entries); for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0 && *entries[i] != 'A') return -13; else if (i % 2 == 1 && *entries[i] != 'B') return -13; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); status = rte_table_array_ops.f_free(table); return 0; } int test_table_lpm(void) { int status, i; uint64_t expected_mask = 0, result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; char entry; void *entry_ptr; int key_found; uint32_t entry_size = 1; /* Initialize params and create tables */ struct rte_table_lpm_params lpm_params = { .n_rules = 1 << 24, .entry_unique_size = entry_size, .offset = 1 }; table = rte_table_lpm_ops.f_create(NULL, 0, entry_size); if (table != NULL) return -1; lpm_params.n_rules = 0; table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -2; lpm_params.n_rules = 1 << 24; lpm_params.offset = 32; lpm_params.entry_unique_size = 0; table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -3; lpm_params.entry_unique_size = entry_size + 1; table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -4; lpm_params.entry_unique_size = entry_size; table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size); if (table == NULL) return -5; /* Free */ status = rte_table_lpm_ops.f_free(table); if (status < 0) return -6; status = rte_table_lpm_ops.f_free(NULL); if (status == 0) return -7; /* Add */ struct rte_table_lpm_key lpm_key; lpm_key.ip = 0xadadadad; table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1); if (table == NULL) return -8; status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -9; status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found, &entry_ptr); if (status == 0) return -10; status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found, &entry_ptr); if (status == 0) return -11; lpm_key.depth = 0; status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -12; lpm_key.depth = 33; status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -13; lpm_key.depth = 16; status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status != 0) return -14; /* Delete */ status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL); if (status == 0) return -15; status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL); if (status == 0) return -16; lpm_key.depth = 0; status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status == 0) return -17; lpm_key.depth = 33; status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status == 0) return -18; lpm_key.depth = 16; status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status != 0) return -19; status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status != 0) return -20; /* Traffic flow */ entry = 'A'; status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status < 0) return -21; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) { expected_mask |= (uint64_t)1 << i; PREPARE_PACKET(mbufs[i], 0xadadadad); } else PREPARE_PACKET(mbufs[i], 0xadadadab); rte_table_lpm_ops.f_lookup(table, mbufs, -1, &result_mask, (void **)entries); if (result_mask != expected_mask) return -22; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); status = rte_table_lpm_ops.f_free(table); return 0; } int test_table_lpm_ipv6(void) { int status, i; uint64_t expected_mask = 0, result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; char entry; void *entry_ptr; int key_found; uint32_t entry_size = 1; /* Initialize params and create tables */ struct rte_table_lpm_ipv6_params lpm_params = { .n_rules = 1 << 24, .number_tbl8s = 1 << 21, .entry_unique_size = entry_size, .offset = 32 }; table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size); if (table != NULL) return -1; lpm_params.n_rules = 0; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -2; lpm_params.n_rules = 1 << 24; lpm_params.number_tbl8s = 0; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -2; lpm_params.number_tbl8s = 1 << 21; lpm_params.entry_unique_size = 0; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -2; lpm_params.entry_unique_size = entry_size + 1; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table != NULL) return -2; lpm_params.entry_unique_size = entry_size; lpm_params.offset = 32; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table == NULL) return -3; /* Free */ status = rte_table_lpm_ipv6_ops.f_free(table); if (status < 0) return -4; status = rte_table_lpm_ipv6_ops.f_free(NULL); if (status == 0) return -5; /* Add */ struct rte_table_lpm_ipv6_key lpm_key; lpm_key.ip[0] = 0xad; lpm_key.ip[1] = 0xad; lpm_key.ip[2] = 0xad; lpm_key.ip[3] = 0xad; table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size); if (table == NULL) return -6; status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -7; status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found, &entry_ptr); if (status == 0) return -8; status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found, &entry_ptr); if (status == 0) return -9; lpm_key.depth = 0; status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -10; lpm_key.depth = 129; status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status == 0) return -11; lpm_key.depth = 16; status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status != 0) return -12; /* Delete */ status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found, NULL); if (status == 0) return -13; status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL); if (status == 0) return -14; lpm_key.depth = 0; status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status == 0) return -15; lpm_key.depth = 129; status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status == 0) return -16; lpm_key.depth = 16; status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status != 0) return -17; status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found, NULL); if (status != 0) return -18; /* Traffic flow */ entry = 'A'; status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry, &key_found, &entry_ptr); if (status < 0) return -19; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) { expected_mask |= (uint64_t)1 << i; PREPARE_PACKET(mbufs[i], 0xadadadad); } else PREPARE_PACKET(mbufs[i], 0xadadadab); rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1, &result_mask, (void **)entries); if (result_mask != expected_mask) return -20; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); status = rte_table_lpm_ipv6_ops.f_free(table); return 0; } static int test_table_hash_lru_generic(struct rte_table_ops *ops) { int status, i; uint64_t expected_mask = 0, result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; char entry; void *entry_ptr; int key_found; /* Initialize params and create tables */ struct rte_table_hash_key8_lru_params hash_params = { .n_entries = 1 << 10, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 1, .key_offset = 32 }; hash_params.n_entries = 0; table = ops->f_create(&hash_params, 0, 1); if (table != NULL) return -1; hash_params.n_entries = 1 << 10; hash_params.signature_offset = 1; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -2; hash_params.signature_offset = 0; hash_params.key_offset = 1; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -3; hash_params.key_offset = 32; hash_params.f_hash = NULL; table = ops->f_create(&hash_params, 0, 1); if (table != NULL) return -4; hash_params.f_hash = pipeline_test_hash; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -5; /* Free */ status = ops->f_free(table); if (status < 0) return -6; status = ops->f_free(NULL); if (status == 0) return -7; /* Add */ uint8_t key[32]; uint32_t *k32 = (uint32_t *) &key; memset(key, 0, 32); k32[0] = rte_be_to_cpu_32(0xadadadad); table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -8; entry = 'A'; status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); if (status != 0) return -9; /* Delete */ status = ops->f_delete(table, &key, &key_found, NULL); if (status != 0) return -10; status = ops->f_delete(table, &key, &key_found, NULL); if (status != 0) return -11; /* Traffic flow */ entry = 'A'; status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); if (status < 0) return -12; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) { expected_mask |= (uint64_t)1 << i; PREPARE_PACKET(mbufs[i], 0xadadadad); } else PREPARE_PACKET(mbufs[i], 0xadadadab); ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries); if (result_mask != expected_mask) return -13; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); status = ops->f_free(table); return 0; } static int test_table_hash_ext_generic(struct rte_table_ops *ops) { int status, i; uint64_t expected_mask = 0, result_mask; struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX]; void *table; char *entries[RTE_PORT_IN_BURST_SIZE_MAX]; char entry; int key_found; void *entry_ptr; /* Initialize params and create tables */ struct rte_table_hash_key8_ext_params hash_params = { .n_entries = 1 << 10, .n_entries_ext = 1 << 4, .f_hash = pipeline_test_hash, .seed = 0, .signature_offset = 1, .key_offset = 32 }; hash_params.n_entries = 0; table = ops->f_create(&hash_params, 0, 1); if (table != NULL) return -1; hash_params.n_entries = 1 << 10; hash_params.n_entries_ext = 0; table = ops->f_create(&hash_params, 0, 1); if (table != NULL) return -2; hash_params.n_entries_ext = 1 << 4; hash_params.signature_offset = 1; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -2; hash_params.signature_offset = 0; hash_params.key_offset = 1; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -3; hash_params.key_offset = 32; hash_params.f_hash = NULL; table = ops->f_create(&hash_params, 0, 1); if (table != NULL) return -4; hash_params.f_hash = pipeline_test_hash; table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -5; /* Free */ status = ops->f_free(table); if (status < 0) return -6; status = ops->f_free(NULL); if (status == 0) return -7; /* Add */ uint8_t key[32]; uint32_t *k32 = (uint32_t *) &key; memset(key, 0, 32); k32[0] = rte_be_to_cpu_32(0xadadadad); table = ops->f_create(&hash_params, 0, 1); if (table == NULL) return -8; entry = 'A'; status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); if (status != 0) return -9; /* Delete */ status = ops->f_delete(table, &key, &key_found, NULL); if (status != 0) return -10; status = ops->f_delete(table, &key, &key_found, NULL); if (status != 0) return -11; /* Traffic flow */ entry = 'A'; status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr); if (status < 0) return -12; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) if (i % 2 == 0) { expected_mask |= (uint64_t)1 << i; PREPARE_PACKET(mbufs[i], 0xadadadad); } else PREPARE_PACKET(mbufs[i], 0xadadadab); ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries); if (result_mask != expected_mask) return -13; /* Free resources */ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) rte_pktmbuf_free(mbufs[i]); status = ops->f_free(table); return 0; } int test_table_hash_lru(void) { int status; status = test_table_hash_lru_generic(&rte_table_hash_key8_lru_ops); if (status < 0) return status; status = test_table_hash_lru_generic( &rte_table_hash_key8_lru_dosig_ops); if (status < 0) return status; status = test_table_hash_lru_generic(&rte_table_hash_key16_lru_ops); if (status < 0) return status; status = test_table_hash_lru_generic(&rte_table_hash_key32_lru_ops); if (status < 0) return status; status = test_lru_update(); if (status < 0) return status; return 0; } int test_table_hash_ext(void) { int status; status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops); if (status < 0) return status; status = test_table_hash_ext_generic( &rte_table_hash_key8_ext_dosig_ops); if (status < 0) return status; status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops); if (status < 0) return status; status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops); if (status < 0) return status; return 0; } ================================================ FILE: app/test/test_table_tables.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Test prototypes */ int test_table_lpm(void); int test_table_lpm_ipv6(void); int test_table_array(void); #ifdef RTE_LIBRTE_ACL int test_table_acl(void); #endif int test_table_hash_unoptimized(void); int test_table_hash_lru(void); int test_table_hash_ext(void); int test_table_stub(void); /* Extern variables */ typedef int (*table_test)(void); extern table_test table_tests[]; extern unsigned n_table_tests; ================================================ FILE: app/test/test_tailq.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "test.h" #define do_return(...) do { \ printf("Error at %s, line %d: ", __func__, __LINE__); \ printf(__VA_ARGS__); \ return 1; \ } while (0) static struct rte_tailq_elem rte_dummy_tailq = { .name = "dummy", }; EAL_REGISTER_TAILQ(rte_dummy_tailq) static struct rte_tailq_elem rte_dummy_dyn_tailq = { .name = "dummy_dyn", }; static struct rte_tailq_elem rte_dummy_dyn2_tailq = { .name = "dummy_dyn", }; static struct rte_tailq_entry d_elem; static struct rte_tailq_entry d_dyn_elem; static int test_tailq_early(void) { struct rte_tailq_entry_head *d_head; d_head = RTE_TAILQ_CAST(rte_dummy_tailq.head, rte_tailq_entry_head); if (d_head == NULL) do_return("Error %s has not been initialised\n", rte_dummy_tailq.name); /* check we can add an item to it */ TAILQ_INSERT_TAIL(d_head, &d_elem, next); return 0; } static int test_tailq_create(void) { struct rte_tailq_entry_head *d_head; /* create a tailq and check its non-null (since we are post-eal init) */ if ((rte_eal_tailq_register(&rte_dummy_dyn_tailq) < 0) || (rte_dummy_dyn_tailq.head == NULL)) do_return("Error allocating %s\n", rte_dummy_dyn_tailq.name); d_head = RTE_TAILQ_CAST(rte_dummy_dyn_tailq.head, rte_tailq_entry_head); /* check we can add an item to it */ TAILQ_INSERT_TAIL(d_head, &d_dyn_elem, next); if (strcmp(rte_dummy_dyn2_tailq.name, rte_dummy_dyn_tailq.name)) do_return("Error, something is wrong in the tailq test\n"); /* try allocating again, and check for failure */ if (!rte_eal_tailq_register(&rte_dummy_dyn2_tailq)) do_return("Error, registering the same tailq %s did not fail\n", rte_dummy_dyn2_tailq.name); return 0; } static int test_tailq_lookup(void) { /* run successful test - check result is found */ struct rte_tailq_entry_head *d_head; struct rte_tailq_entry *d_ptr; d_head = RTE_TAILQ_LOOKUP(rte_dummy_tailq.name, rte_tailq_entry_head); /* rte_dummy_tailq has been registered by EAL_REGISTER_TAILQ */ if (d_head == NULL || d_head != RTE_TAILQ_CAST(rte_dummy_tailq.head, rte_tailq_entry_head)) do_return("Error with tailq lookup\n"); TAILQ_FOREACH(d_ptr, d_head, next) if (d_ptr != &d_elem) do_return("Error with tailq returned from lookup - " "expected element not found\n"); d_head = RTE_TAILQ_LOOKUP(rte_dummy_dyn_tailq.name, rte_tailq_entry_head); /* rte_dummy_dyn_tailq has been registered by test_tailq_create */ if (d_head == NULL || d_head != RTE_TAILQ_CAST(rte_dummy_dyn_tailq.head, rte_tailq_entry_head)) do_return("Error with tailq lookup\n"); TAILQ_FOREACH(d_ptr, d_head, next) if (d_ptr != &d_dyn_elem) do_return("Error with tailq returned from lookup - " "expected element not found\n"); /* now try a bad/error lookup */ d_head = RTE_TAILQ_LOOKUP("coucou", rte_tailq_entry_head); if (d_head != NULL) do_return("Error, lookup does not return NULL for bad tailq name\n"); return 0; } static int test_tailq(void) { int ret = 0; ret |= test_tailq_early(); ret |= test_tailq_create(); ret |= test_tailq_lookup(); return ret; } static struct test_command tailq_cmd = { .command = "tailq_autotest", .callback = test_tailq, }; REGISTER_TEST_COMMAND(tailq_cmd); ================================================ FILE: app/test/test_thash.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Vladimir Medvedkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "test.h" #include struct test_thash_v4 { uint32_t dst_ip; uint32_t src_ip; uint16_t dst_port; uint16_t src_port; uint32_t hash_l3; uint32_t hash_l3l4; }; struct test_thash_v6 { uint8_t dst_ip[16]; uint8_t src_ip[16]; uint16_t dst_port; uint16_t src_port; uint32_t hash_l3; uint32_t hash_l3l4; }; /*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/ struct test_thash_v4 v4_tbl[] = { {IPv4(161, 142, 100, 80), IPv4(66, 9, 149, 187), 1766, 2794, 0x323e8fc2, 0x51ccc178}, {IPv4(65, 69, 140, 83), IPv4(199, 92, 111, 2), 4739, 14230, 0xd718262a, 0xc626b0ea}, {IPv4(12, 22, 207, 184), IPv4(24, 19, 198, 95), 38024, 12898, 0xd2d0a5de, 0x5c2b394a}, {IPv4(209, 142, 163, 6), IPv4(38, 27, 205, 30), 2217, 48228, 0x82989176, 0xafc7327f}, {IPv4(202, 188, 127, 2), IPv4(153, 39, 163, 191), 1303, 44251, 0x5d1809c5, 0x10e828a2}, }; struct test_thash_v6 v6_tbl[] = { /*3ffe:2501:200:3::1*/ {{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,}, /*3ffe:2501:200:1fff::7*/ {0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,}, 1766, 2794, 0x2cc18cd5, 0x40207d3d}, /*ff02::1*/ {{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,}, /*3ffe:501:8::260:97ff:fe40:efab*/ {0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00, 0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,}, 4739, 14230, 0x0f0c461c, 0xdde51bbf}, /*fe80::200:f8ff:fe21:67cf*/ {{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,}, /*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/ {0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03, 0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,}, 38024, 44251, 0x4b61e985, 0x02d1feef}, }; uint8_t default_rss_key[] = { 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa, }; static int test_thash(void) { uint32_t i, j; union rte_thash_tuple tuple; uint32_t rss_l3, rss_l3l4; uint8_t rss_key_be[RTE_DIM(default_rss_key)]; struct ipv6_hdr ipv6_hdr; /* Convert RSS key*/ rte_convert_rss_key((uint32_t *)&default_rss_key, (uint32_t *)rss_key_be, RTE_DIM(default_rss_key)); for (i = 0; i < RTE_DIM(v4_tbl); i++) { tuple.v4.src_addr = v4_tbl[i].src_ip; tuple.v4.dst_addr = v4_tbl[i].dst_ip; tuple.v4.sport = v4_tbl[i].src_port; tuple.v4.dport = v4_tbl[i].dst_port; /*Calculate hash with original key*/ rss_l3 = rte_softrss((uint32_t *)&tuple, RTE_THASH_V4_L3_LEN, default_rss_key); rss_l3l4 = rte_softrss((uint32_t *)&tuple, RTE_THASH_V4_L4_LEN, default_rss_key); if ((rss_l3 != v4_tbl[i].hash_l3) || (rss_l3l4 != v4_tbl[i].hash_l3l4)) return -1; /*Calculate hash with converted key*/ rss_l3 = rte_softrss_be((uint32_t *)&tuple, RTE_THASH_V4_L3_LEN, rss_key_be); rss_l3l4 = rte_softrss_be((uint32_t *)&tuple, RTE_THASH_V4_L4_LEN, rss_key_be); if ((rss_l3 != v4_tbl[i].hash_l3) || (rss_l3l4 != v4_tbl[i].hash_l3l4)) return -1; } for (i = 0; i < RTE_DIM(v6_tbl); i++) { /*Fill ipv6 hdr*/ for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++) ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j]; for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++) ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j]; /*Load and convert ipv6 address into tuple*/ rte_thash_load_v6_addrs(&ipv6_hdr, &tuple); tuple.v6.sport = v6_tbl[i].src_port; tuple.v6.dport = v6_tbl[i].dst_port; /*Calculate hash with original key*/ rss_l3 = rte_softrss((uint32_t *)&tuple, RTE_THASH_V6_L3_LEN, default_rss_key); rss_l3l4 = rte_softrss((uint32_t *)&tuple, RTE_THASH_V6_L4_LEN, default_rss_key); if ((rss_l3 != v6_tbl[i].hash_l3) || (rss_l3l4 != v6_tbl[i].hash_l3l4)) return -1; /*Calculate hash with converted key*/ rss_l3 = rte_softrss_be((uint32_t *)&tuple, RTE_THASH_V6_L3_LEN, rss_key_be); rss_l3l4 = rte_softrss_be((uint32_t *)&tuple, RTE_THASH_V6_L4_LEN, rss_key_be); if ((rss_l3 != v6_tbl[i].hash_l3) || (rss_l3l4 != v6_tbl[i].hash_l3l4)) return -1; } return 0; } static struct test_command thash_cmd = { .command = "thash_autotest", .callback = test_thash, }; REGISTER_TEST_COMMAND(thash_cmd); ================================================ FILE: app/test/test_timer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" /* * Timer * ===== * * #. Stress test 1. * * The objective of the timer stress tests is to check that there are no * race conditions in list and status management. This test launches, * resets and stops the timer very often on many cores at the same * time. * * - Only one timer is used for this test. * - On each core, the rte_timer_manage() function is called from the main * loop every 3 microseconds. * - In the main loop, the timer may be reset (randomly, with a * probability of 0.5 %) 100 microseconds later on a random core, or * stopped (with a probability of 0.5 % also). * - In callback, the timer is can be reset (randomly, with a * probability of 0.5 %) 100 microseconds later on the same core or * on another core (same probability), or stopped (same * probability). * * # Stress test 2. * * The objective of this test is similar to the first in that it attempts * to find if there are any race conditions in the timer library. However, * it is less complex in terms of operations performed and duration, as it * is designed to have a predictable outcome that can be tested. * * - A set of timers is initialized for use by the test * - All cores then simultaneously are set to schedule all the timers at * the same time, so conflicts should occur. * - Then there is a delay while we wait for the timers to expire * - Then the master lcore calls timer_manage() and we check that all * timers have had their callbacks called exactly once - no more no less. * - Then we repeat the process, except after setting up the timers, we have * all cores randomly reschedule them. * - Again we check that the expected number of callbacks has occurred when * we call timer-manage. * * #. Basic test. * * This test performs basic functional checks of the timers. The test * uses four different timers that are loaded and stopped under * specific conditions in specific contexts. * * - Four timers are used for this test. * - On each core, the rte_timer_manage() function is called from main loop * every 3 microseconds. * * The autotest python script checks that the behavior is correct: * * - timer0 * * - At initialization, timer0 is loaded by the master core, on master core * in "single" mode (time = 1 second). * - In the first 19 callbacks, timer0 is reloaded on the same core, * then, it is explicitly stopped at the 20th call. * - At t=25s, timer0 is reloaded once by timer2. * * - timer1 * * - At initialization, timer1 is loaded by the master core, on the * master core in "single" mode (time = 2 seconds). * - In the first 9 callbacks, timer1 is reloaded on another * core. After the 10th callback, timer1 is not reloaded anymore. * * - timer2 * * - At initialization, timer2 is loaded by the master core, on the * master core in "periodical" mode (time = 1 second). * - In the callback, when t=25s, it stops timer3 and reloads timer0 * on the current core. * * - timer3 * * - At initialization, timer3 is loaded by the master core, on * another core in "periodical" mode (time = 1 second). * - It is stopped at t=25s by timer2. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TEST_DURATION_S 20 /* in seconds */ #define NB_TIMER 4 #define RTE_LOGTYPE_TESTTIMER RTE_LOGTYPE_USER3 static volatile uint64_t end_time; static volatile int test_failed; struct mytimerinfo { struct rte_timer tim; unsigned id; unsigned count; }; static struct mytimerinfo mytiminfo[NB_TIMER]; static void timer_basic_cb(struct rte_timer *tim, void *arg); static void mytimer_reset(struct mytimerinfo *timinfo, uint64_t ticks, enum rte_timer_type type, unsigned tim_lcore, rte_timer_cb_t fct) { rte_timer_reset_sync(&timinfo->tim, ticks, type, tim_lcore, fct, timinfo); } /* timer callback for stress tests */ static void timer_stress_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg) { long r; unsigned lcore_id = rte_lcore_id(); uint64_t hz = rte_get_timer_hz(); if (rte_timer_pending(tim)) return; r = rte_rand(); if ((r & 0xff) == 0) { mytimer_reset(&mytiminfo[0], hz, SINGLE, lcore_id, timer_stress_cb); } else if ((r & 0xff) == 1) { mytimer_reset(&mytiminfo[0], hz, SINGLE, rte_get_next_lcore(lcore_id, 0, 1), timer_stress_cb); } else if ((r & 0xff) == 2) { rte_timer_stop(&mytiminfo[0].tim); } } static int timer_stress_main_loop(__attribute__((unused)) void *arg) { uint64_t hz = rte_get_timer_hz(); unsigned lcore_id = rte_lcore_id(); uint64_t cur_time; int64_t diff = 0; long r; while (diff >= 0) { /* call the timer handler on each core */ rte_timer_manage(); /* simulate the processing of a packet * (1 us = 2000 cycles at 2 Ghz) */ rte_delay_us(1); /* randomly stop or reset timer */ r = rte_rand(); lcore_id = rte_get_next_lcore(lcore_id, 0, 1); if ((r & 0xff) == 0) { /* 100 us */ mytimer_reset(&mytiminfo[0], hz/10000, SINGLE, lcore_id, timer_stress_cb); } else if ((r & 0xff) == 1) { rte_timer_stop_sync(&mytiminfo[0].tim); } cur_time = rte_get_timer_cycles(); diff = end_time - cur_time; } lcore_id = rte_lcore_id(); RTE_LOG(INFO, TESTTIMER, "core %u finished\n", lcore_id); return 0; } /* Need to synchronize slave lcores through multiple steps. */ enum { SLAVE_WAITING = 1, SLAVE_RUN_SIGNAL, SLAVE_RUNNING, SLAVE_FINISHED }; static rte_atomic16_t slave_state[RTE_MAX_LCORE]; static void master_init_slaves(void) { unsigned i; RTE_LCORE_FOREACH_SLAVE(i) { rte_atomic16_set(&slave_state[i], SLAVE_WAITING); } } static void master_start_slaves(void) { unsigned i; RTE_LCORE_FOREACH_SLAVE(i) { rte_atomic16_set(&slave_state[i], SLAVE_RUN_SIGNAL); } RTE_LCORE_FOREACH_SLAVE(i) { while (rte_atomic16_read(&slave_state[i]) != SLAVE_RUNNING) rte_pause(); } } static void master_wait_for_slaves(void) { unsigned i; RTE_LCORE_FOREACH_SLAVE(i) { while (rte_atomic16_read(&slave_state[i]) != SLAVE_FINISHED) rte_pause(); } } static void slave_wait_to_start(void) { unsigned lcore_id = rte_lcore_id(); while (rte_atomic16_read(&slave_state[lcore_id]) != SLAVE_RUN_SIGNAL) rte_pause(); rte_atomic16_set(&slave_state[lcore_id], SLAVE_RUNNING); } static void slave_finish(void) { unsigned lcore_id = rte_lcore_id(); rte_atomic16_set(&slave_state[lcore_id], SLAVE_FINISHED); } static volatile int cb_count = 0; /* callback for second stress test. will only be called * on master lcore */ static void timer_stress2_cb(struct rte_timer *tim __rte_unused, void *arg __rte_unused) { cb_count++; } #define NB_STRESS2_TIMERS 8192 static int timer_stress2_main_loop(__attribute__((unused)) void *arg) { static struct rte_timer *timers; int i, ret; uint64_t delay = rte_get_timer_hz() / 4; unsigned lcore_id = rte_lcore_id(); unsigned master = rte_get_master_lcore(); int32_t my_collisions = 0; static rte_atomic32_t collisions; if (lcore_id == master) { cb_count = 0; test_failed = 0; rte_atomic32_set(&collisions, 0); master_init_slaves(); timers = rte_malloc(NULL, sizeof(*timers) * NB_STRESS2_TIMERS, 0); if (timers == NULL) { printf("Test Failed\n"); printf("- Cannot allocate memory for timers\n" ); test_failed = 1; master_start_slaves(); goto cleanup; } for (i = 0; i < NB_STRESS2_TIMERS; i++) rte_timer_init(&timers[i]); master_start_slaves(); } else { slave_wait_to_start(); if (test_failed) goto cleanup; } /* have all cores schedule all timers on master lcore */ for (i = 0; i < NB_STRESS2_TIMERS; i++) { ret = rte_timer_reset(&timers[i], delay, SINGLE, master, timer_stress2_cb, NULL); /* there will be collisions when multiple cores simultaneously * configure the same timers */ if (ret != 0) my_collisions++; } if (my_collisions != 0) rte_atomic32_add(&collisions, my_collisions); /* wait long enough for timers to expire */ rte_delay_ms(500); /* all cores rendezvous */ if (lcore_id == master) { master_wait_for_slaves(); } else { slave_finish(); } /* now check that we get the right number of callbacks */ if (lcore_id == master) { my_collisions = rte_atomic32_read(&collisions); if (my_collisions != 0) printf("- %d timer reset collisions (OK)\n", my_collisions); rte_timer_manage(); if (cb_count != NB_STRESS2_TIMERS) { printf("Test Failed\n"); printf("- Stress test 2, part 1 failed\n"); printf("- Expected %d callbacks, got %d\n", NB_STRESS2_TIMERS, cb_count); test_failed = 1; master_start_slaves(); goto cleanup; } cb_count = 0; /* proceed */ master_start_slaves(); } else { /* proceed */ slave_wait_to_start(); if (test_failed) goto cleanup; } /* now test again, just stop and restart timers at random after init*/ for (i = 0; i < NB_STRESS2_TIMERS; i++) rte_timer_reset(&timers[i], delay, SINGLE, master, timer_stress2_cb, NULL); /* pick random timer to reset, stopping them first half the time */ for (i = 0; i < 100000; i++) { int r = rand() % NB_STRESS2_TIMERS; if (i % 2) rte_timer_stop(&timers[r]); rte_timer_reset(&timers[r], delay, SINGLE, master, timer_stress2_cb, NULL); } /* wait long enough for timers to expire */ rte_delay_ms(500); /* now check that we get the right number of callbacks */ if (lcore_id == master) { master_wait_for_slaves(); rte_timer_manage(); if (cb_count != NB_STRESS2_TIMERS) { printf("Test Failed\n"); printf("- Stress test 2, part 2 failed\n"); printf("- Expected %d callbacks, got %d\n", NB_STRESS2_TIMERS, cb_count); test_failed = 1; } else { printf("Test OK\n"); } } cleanup: if (lcore_id == master) { master_wait_for_slaves(); if (timers != NULL) { rte_free(timers); timers = NULL; } } else { slave_finish(); } return 0; } /* timer callback for basic tests */ static void timer_basic_cb(struct rte_timer *tim, void *arg) { struct mytimerinfo *timinfo = arg; uint64_t hz = rte_get_timer_hz(); unsigned lcore_id = rte_lcore_id(); uint64_t cur_time = rte_get_timer_cycles(); if (rte_timer_pending(tim)) return; timinfo->count ++; RTE_LOG(INFO, TESTTIMER, "%"PRIu64": callback id=%u count=%u on core %u\n", cur_time, timinfo->id, timinfo->count, lcore_id); /* reload timer 0 on same core */ if (timinfo->id == 0 && timinfo->count < 20) { mytimer_reset(timinfo, hz, SINGLE, lcore_id, timer_basic_cb); return; } /* reload timer 1 on next core */ if (timinfo->id == 1 && timinfo->count < 10) { mytimer_reset(timinfo, hz*2, SINGLE, rte_get_next_lcore(lcore_id, 0, 1), timer_basic_cb); return; } /* Explicitelly stop timer 0. Once stop() called, we can even * erase the content of the structure: it is not referenced * anymore by any code (in case of dynamic structure, it can * be freed) */ if (timinfo->id == 0 && timinfo->count == 20) { /* stop_sync() is not needed, because we know that the * status of timer is only modified by this core */ rte_timer_stop(tim); memset(tim, 0xAA, sizeof(struct rte_timer)); return; } /* stop timer3, and restart a new timer0 (it was removed 5 * seconds ago) for a single shot */ if (timinfo->id == 2 && timinfo->count == 25) { rte_timer_stop_sync(&mytiminfo[3].tim); /* need to reinit because structure was erased with 0xAA */ rte_timer_init(&mytiminfo[0].tim); mytimer_reset(&mytiminfo[0], hz, SINGLE, lcore_id, timer_basic_cb); } } static int timer_basic_main_loop(__attribute__((unused)) void *arg) { uint64_t hz = rte_get_timer_hz(); unsigned lcore_id = rte_lcore_id(); uint64_t cur_time; int64_t diff = 0; /* launch all timers on core 0 */ if (lcore_id == rte_get_master_lcore()) { mytimer_reset(&mytiminfo[0], hz, SINGLE, lcore_id, timer_basic_cb); mytimer_reset(&mytiminfo[1], hz*2, SINGLE, lcore_id, timer_basic_cb); mytimer_reset(&mytiminfo[2], hz, PERIODICAL, lcore_id, timer_basic_cb); mytimer_reset(&mytiminfo[3], hz, PERIODICAL, rte_get_next_lcore(lcore_id, 0, 1), timer_basic_cb); } while (diff >= 0) { /* call the timer handler on each core */ rte_timer_manage(); /* simulate the processing of a packet * (3 us = 6000 cycles at 2 Ghz) */ rte_delay_us(3); cur_time = rte_get_timer_cycles(); diff = end_time - cur_time; } RTE_LOG(INFO, TESTTIMER, "core %u finished\n", lcore_id); return 0; } static int timer_sanity_check(void) { #ifdef RTE_LIBEAL_USE_HPET if (eal_timer_source != EAL_TIMER_HPET) { printf("Not using HPET, can't sanity check timer sources\n"); return 0; } const uint64_t t_hz = rte_get_tsc_hz(); const uint64_t h_hz = rte_get_hpet_hz(); printf("Hertz values: TSC = %"PRIu64", HPET = %"PRIu64"\n", t_hz, h_hz); const uint64_t tsc_start = rte_get_tsc_cycles(); const uint64_t hpet_start = rte_get_hpet_cycles(); rte_delay_ms(100); /* delay 1/10 second */ const uint64_t tsc_end = rte_get_tsc_cycles(); const uint64_t hpet_end = rte_get_hpet_cycles(); printf("Measured cycles: TSC = %"PRIu64", HPET = %"PRIu64"\n", tsc_end-tsc_start, hpet_end-hpet_start); const double tsc_time = (double)(tsc_end - tsc_start)/t_hz; const double hpet_time = (double)(hpet_end - hpet_start)/h_hz; /* get the percentage that the times differ by */ const double time_diff = fabs(tsc_time - hpet_time)*100/tsc_time; printf("Measured time: TSC = %.4f, HPET = %.4f\n", tsc_time, hpet_time); printf("Elapsed time measured by TSC and HPET differ by %f%%\n", time_diff); if (time_diff > 0.1) { printf("Error times differ by >0.1%%"); return -1; } #endif return 0; } static int test_timer(void) { unsigned i; uint64_t cur_time; uint64_t hz; /* sanity check our timer sources and timer config values */ if (timer_sanity_check() < 0) { printf("Timer sanity checks failed\n"); return TEST_FAILED; } if (rte_lcore_count() < 2) { printf("not enough lcores for this test\n"); return TEST_FAILED; } /* init timer */ for (i=0; i #include #include #include #include #include #include #include #include #define MAX_ITERATIONS 1000000 int outstanding_count = 0; static void timer_cb(struct rte_timer *t __rte_unused, void *param __rte_unused) { outstanding_count--; } #define DELAY_SECONDS 1 #ifdef RTE_EXEC_ENV_LINUXAPP #define do_delay() usleep(10) #else #define do_delay() rte_pause() #endif static int test_timer_perf(void) { unsigned iterations = 100; unsigned i; struct rte_timer *tms; uint64_t start_tsc, end_tsc, delay_start; unsigned lcore_id = rte_lcore_id(); tms = rte_malloc(NULL, sizeof(*tms) * MAX_ITERATIONS, 0); for (i = 0; i < MAX_ITERATIONS; i++) rte_timer_init(&tms[i]); const uint64_t ticks = rte_get_timer_hz() * DELAY_SECONDS; const uint64_t ticks_per_ms = rte_get_tsc_hz()/1000; const uint64_t ticks_per_us = ticks_per_ms/1000; while (iterations <= MAX_ITERATIONS) { printf("Appending %u timers\n", iterations); start_tsc = rte_rdtsc(); for (i = 0; i < iterations; i++) rte_timer_reset(&tms[i], ticks, SINGLE, lcore_id, timer_cb, NULL); end_tsc = rte_rdtsc(); printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", (end_tsc-start_tsc)/iterations, ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); outstanding_count = iterations; delay_start = rte_get_timer_cycles(); while (rte_get_timer_cycles() < delay_start + ticks) do_delay(); start_tsc = rte_rdtsc(); while (outstanding_count) rte_timer_manage(); end_tsc = rte_rdtsc(); printf("Time for %u callbacks: %"PRIu64" (%"PRIu64"ms), ", iterations, end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); printf("Time per callback: %"PRIu64" (%"PRIu64"us)\n", (end_tsc-start_tsc)/iterations, ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); printf("Resetting %u timers\n", iterations); start_tsc = rte_rdtsc(); for (i = 0; i < iterations; i++) rte_timer_reset(&tms[i], rte_rand() % ticks, SINGLE, lcore_id, timer_cb, NULL); end_tsc = rte_rdtsc(); printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations, end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms)); printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n", (end_tsc-start_tsc)/iterations, ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us)); outstanding_count = iterations; delay_start = rte_get_timer_cycles(); while (rte_get_timer_cycles() < delay_start + ticks) do_delay(); rte_timer_manage(); if (outstanding_count != 0) { printf("Error: outstanding callback count = %d\n", outstanding_count); return -1; } iterations *= 10; printf("\n"); } printf("All timers processed ok\n"); /* measure time to poll an empty timer list */ start_tsc = rte_rdtsc(); for (i = 0; i < iterations; i++) rte_timer_manage(); end_tsc = rte_rdtsc(); printf("\nTime per rte_timer_manage with zero timers: %"PRIu64" cycles\n", (end_tsc - start_tsc + iterations/2) / iterations); /* measure time to poll a timer list with timers, but without * calling any callbacks */ rte_timer_reset(&tms[0], ticks * 100, SINGLE, lcore_id, timer_cb, NULL); start_tsc = rte_rdtsc(); for (i = 0; i < iterations; i++) rte_timer_manage(); end_tsc = rte_rdtsc(); printf("Time per rte_timer_manage with zero callbacks: %"PRIu64" cycles\n", (end_tsc - start_tsc + iterations/2) / iterations); return 0; } static struct test_command timer_perf_cmd = { .command = "timer_perf_autotest", .callback = test_timer_perf, }; REGISTER_TEST_COMMAND(timer_perf_cmd); ================================================ FILE: app/test/test_timer_racecond.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Akamai Technologies. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include #include #include #include #include #include #include #include #include #undef TEST_TIMER_RACECOND_VERBOSE #ifdef RTE_EXEC_ENV_LINUXAPP #define usec_delay(us) usleep(us) #else #define usec_delay(us) rte_delay_us(us) #endif #define BILLION (1UL << 30) #define TEST_DURATION_S 20 /* in seconds */ #define N_TIMERS 50 static struct rte_timer timer[N_TIMERS]; static unsigned timer_lcore_id[N_TIMERS]; static unsigned master; static volatile unsigned stop_slaves; static int reload_timer(struct rte_timer *tim); static void timer_cb(struct rte_timer *tim, void *arg __rte_unused) { /* Simulate slow callback function, 100 us. */ rte_delay_us(100); #ifdef TEST_TIMER_RACECOND_VERBOSE if (tim == &timer[0]) printf("------------------------------------------------\n"); printf("timer_cb: core %u timer %lu\n", rte_lcore_id(), tim - timer); #endif (void)reload_timer(tim); } RTE_DEFINE_PER_LCORE(unsigned, n_reset_collisions); static int reload_timer(struct rte_timer *tim) { /* Make timer expire roughly when the TSC hits the next BILLION * multiple. Add in timer's index to make them expire in nearly * sorted order. This makes all timers somewhat synchronized, * firing ~2-3 times per second, assuming 2-3 GHz TSCs. */ uint64_t ticks = BILLION - (rte_get_timer_cycles() % BILLION) + (tim - timer); int ret; ret = rte_timer_reset(tim, ticks, PERIODICAL, master, timer_cb, NULL); if (ret != 0) { #ifdef TEST_TIMER_RACECOND_VERBOSE printf("- core %u failed to reset timer %lu (OK)\n", rte_lcore_id(), tim - timer); #endif RTE_PER_LCORE(n_reset_collisions) += 1; } return ret; } static int slave_main_loop(__attribute__((unused)) void *arg) { unsigned lcore_id = rte_lcore_id(); unsigned i; RTE_PER_LCORE(n_reset_collisions) = 0; printf("Starting main loop on core %u\n", lcore_id); while (!stop_slaves) { /* Wait until the timer manager is running. * We know it's running when we see timer[0] NOT pending. */ if (rte_timer_pending(&timer[0])) { rte_pause(); continue; } /* Now, go cause some havoc! * Reload our timers. */ for (i = 0; i < N_TIMERS; i++) { if (timer_lcore_id[i] == lcore_id) (void)reload_timer(&timer[i]); } usec_delay(100*1000); /* sleep 100 ms */ } if (RTE_PER_LCORE(n_reset_collisions) != 0) { printf("- core %u, %u reset collisions (OK)\n", lcore_id, RTE_PER_LCORE(n_reset_collisions)); } return 0; } static int test_timer_racecond(void) { int ret; uint64_t hz; uint64_t cur_time; uint64_t end_time; int64_t diff = 0; unsigned lcore_id; unsigned i; master = lcore_id = rte_lcore_id(); hz = rte_get_timer_hz(); /* init and start timers */ for (i = 0; i < N_TIMERS; i++) { rte_timer_init(&timer[i]); ret = reload_timer(&timer[i]); TEST_ASSERT(ret == 0, "reload_timer failed"); /* Distribute timers to slaves. * Note that we assign timer[0] to the master. */ timer_lcore_id[i] = lcore_id; lcore_id = rte_get_next_lcore(lcore_id, 1, 1); } /* calculate the "end of test" time */ cur_time = rte_get_timer_cycles(); end_time = cur_time + (hz * TEST_DURATION_S); /* start slave cores */ stop_slaves = 0; printf("Start timer manage race condition test (%u seconds)\n", TEST_DURATION_S); rte_eal_mp_remote_launch(slave_main_loop, NULL, SKIP_MASTER); while (diff >= 0) { /* run the timers */ rte_timer_manage(); /* wait 100 ms */ usec_delay(100*1000); cur_time = rte_get_timer_cycles(); diff = end_time - cur_time; } /* stop slave cores */ printf("Stopping timer manage race condition test\n"); stop_slaves = 1; rte_eal_mp_wait_lcore(); /* stop timers */ for (i = 0; i < N_TIMERS; i++) { ret = rte_timer_stop(&timer[i]); TEST_ASSERT(ret == 0, "rte_timer_stop failed"); } return TEST_SUCCESS; } static struct test_command timer_racecond_cmd = { .command = "timer_racecond_autotest", .callback = test_timer_racecond, }; REGISTER_TEST_COMMAND(timer_racecond_cmd); ================================================ FILE: app/test/test_version.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "test.h" static int test_version(void) { const char *version = rte_version(); if (version == NULL) return -1; printf("Version string: '%s'\n", version); if (*version == '\0' || strncmp(version, RTE_VER_PREFIX, sizeof(RTE_VER_PREFIX)-1) != 0) return -1; return 0; } static struct test_command version_cmd = { .command = "version_autotest", .callback = test_version, }; REGISTER_TEST_COMMAND(version_cmd); ================================================ FILE: app/test/virtual_pmd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "virtual_pmd.h" #define MAX_PKT_BURST 512 static const char *virtual_ethdev_driver_name = "Virtual PMD"; struct virtual_ethdev_private { struct eth_dev_ops dev_ops; struct rte_eth_stats eth_stats; struct rte_ring *rx_queue; struct rte_ring *tx_queue; int tx_burst_fail_count; }; struct virtual_ethdev_queue { int port_id; int queue_id; }; static int virtual_ethdev_start_success(struct rte_eth_dev *eth_dev __rte_unused) { eth_dev->data->dev_started = 1; return 0; } static int virtual_ethdev_start_fail(struct rte_eth_dev *eth_dev __rte_unused) { eth_dev->data->dev_started = 0; return -1; } static void virtual_ethdev_stop(struct rte_eth_dev *eth_dev __rte_unused) { void *pkt = NULL; struct virtual_ethdev_private *prv = eth_dev->data->dev_private; eth_dev->data->dev_link.link_status = 0; eth_dev->data->dev_started = 0; while (rte_ring_dequeue(prv->rx_queue, &pkt) != -ENOENT) rte_pktmbuf_free(pkt); while (rte_ring_dequeue(prv->tx_queue, &pkt) != -ENOENT) rte_pktmbuf_free(pkt); } static void virtual_ethdev_close(struct rte_eth_dev *dev __rte_unused) {} static int virtual_ethdev_configure_success(struct rte_eth_dev *dev __rte_unused) { return 0; } static int virtual_ethdev_configure_fail(struct rte_eth_dev *dev __rte_unused) { return -1; } static void virtual_ethdev_info_get(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info) { dev_info->driver_name = virtual_ethdev_driver_name; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)2048; dev_info->max_rx_queues = (uint16_t)128; dev_info->max_tx_queues = (uint16_t)512; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static int virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool __rte_unused) { struct virtual_ethdev_queue *rx_q; rx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL, sizeof(struct virtual_ethdev_queue), 0, socket_id); if (rx_q == NULL) return -1; rx_q->port_id = dev->data->port_id; rx_q->queue_id = rx_queue_id; dev->data->rx_queues[rx_queue_id] = rx_q; return 0; } static int virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused, uint16_t rx_queue_id __rte_unused, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool __rte_unused) { return -1; } static int virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id, const struct rte_eth_txconf *tx_conf __rte_unused) { struct virtual_ethdev_queue *tx_q; tx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL, sizeof(struct virtual_ethdev_queue), 0, socket_id); if (tx_q == NULL) return -1; tx_q->port_id = dev->data->port_id; tx_q->queue_id = tx_queue_id; dev->data->tx_queues[tx_queue_id] = tx_q; return 0; } static int virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused, uint16_t tx_queue_id __rte_unused, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { return -1; } static void virtual_ethdev_rx_queue_release(void *q __rte_unused) { } static void virtual_ethdev_tx_queue_release(void *q __rte_unused) { } static int virtual_ethdev_link_update_success(struct rte_eth_dev *bonded_eth_dev, int wait_to_complete __rte_unused) { if (!bonded_eth_dev->data->dev_started) bonded_eth_dev->data->dev_link.link_status = 0; return 0; } static int virtual_ethdev_link_update_fail(struct rte_eth_dev *bonded_eth_dev __rte_unused, int wait_to_complete __rte_unused) { return -1; } static void virtual_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct virtual_ethdev_private *dev_private = dev->data->dev_private; if (stats) rte_memcpy(stats, &dev_private->eth_stats, sizeof(*stats)); } static void virtual_ethdev_stats_reset(struct rte_eth_dev *dev) { struct virtual_ethdev_private *dev_private = dev->data->dev_private; void *pkt = NULL; while (rte_ring_dequeue(dev_private->tx_queue, &pkt) == -ENOBUFS) rte_pktmbuf_free(pkt); /* Reset internal statistics */ memset(&dev_private->eth_stats, 0, sizeof(dev_private->eth_stats)); } static void virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev *dev __rte_unused) {} static void virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused) {} static const struct eth_dev_ops virtual_ethdev_default_dev_ops = { .dev_configure = virtual_ethdev_configure_success, .dev_start = virtual_ethdev_start_success, .dev_stop = virtual_ethdev_stop, .dev_close = virtual_ethdev_close, .dev_infos_get = virtual_ethdev_info_get, .rx_queue_setup = virtual_ethdev_rx_queue_setup_success, .tx_queue_setup = virtual_ethdev_tx_queue_setup_success, .rx_queue_release = virtual_ethdev_rx_queue_release, .tx_queue_release = virtual_ethdev_tx_queue_release, .link_update = virtual_ethdev_link_update_success, .stats_get = virtual_ethdev_stats_get, .stats_reset = virtual_ethdev_stats_reset, .promiscuous_enable = virtual_ethdev_promiscuous_mode_enable, .promiscuous_disable = virtual_ethdev_promiscuous_mode_disable }; void virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = dev->data->dev_private; struct eth_dev_ops *dev_ops = &dev_private->dev_ops; if (success) dev_ops->dev_start = virtual_ethdev_start_success; else dev_ops->dev_start = virtual_ethdev_start_fail; } void virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = dev->data->dev_private; struct eth_dev_ops *dev_ops = &dev_private->dev_ops; if (success) dev_ops->dev_configure = virtual_ethdev_configure_success; else dev_ops->dev_configure = virtual_ethdev_configure_fail; } void virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = dev->data->dev_private; struct eth_dev_ops *dev_ops = &dev_private->dev_ops; if (success) dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_success; else dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_fail; } void virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = dev->data->dev_private; struct eth_dev_ops *dev_ops = &dev_private->dev_ops; if (success) dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_success; else dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_fail; } void virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = dev->data->dev_private; struct eth_dev_ops *dev_ops = &dev_private->dev_ops; if (success) dev_ops->link_update = virtual_ethdev_link_update_success; else dev_ops->link_update = virtual_ethdev_link_update_fail; } static uint16_t virtual_ethdev_rx_burst_success(void *queue __rte_unused, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct rte_eth_dev *vrtl_eth_dev; struct virtual_ethdev_queue *pq_map; struct virtual_ethdev_private *dev_private; int rx_count, i; pq_map = (struct virtual_ethdev_queue *)queue; vrtl_eth_dev = &rte_eth_devices[pq_map->port_id]; dev_private = vrtl_eth_dev->data->dev_private; rx_count = rte_ring_dequeue_burst(dev_private->rx_queue, (void **) bufs, nb_pkts); /* increments ipackets count */ dev_private->eth_stats.ipackets += rx_count; /* increments ibytes count */ for (i = 0; i < rx_count; i++) dev_private->eth_stats.ibytes += rte_pktmbuf_pkt_len(bufs[i]); return rx_count; } static uint16_t virtual_ethdev_rx_burst_fail(void *queue __rte_unused, struct rte_mbuf **bufs __rte_unused, uint16_t nb_pkts __rte_unused) { return 0; } static uint16_t virtual_ethdev_tx_burst_success(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct virtual_ethdev_queue *tx_q = (struct virtual_ethdev_queue *)queue; struct rte_eth_dev *vrtl_eth_dev; struct virtual_ethdev_private *dev_private; int i; vrtl_eth_dev = &rte_eth_devices[tx_q->port_id]; dev_private = vrtl_eth_dev->data->dev_private; if (!vrtl_eth_dev->data->dev_link.link_status) nb_pkts = 0; else nb_pkts = rte_ring_enqueue_burst(dev_private->tx_queue, (void **)bufs, nb_pkts); /* increment opacket count */ dev_private->eth_stats.opackets += nb_pkts; /* increment obytes count */ for (i = 0; i < nb_pkts; i++) dev_private->eth_stats.obytes += rte_pktmbuf_pkt_len(bufs[i]); return nb_pkts; } static uint16_t virtual_ethdev_tx_burst_fail(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct rte_eth_dev *vrtl_eth_dev = NULL; struct virtual_ethdev_queue *tx_q = NULL; struct virtual_ethdev_private *dev_private = NULL; int i; tx_q = (struct virtual_ethdev_queue *)queue; vrtl_eth_dev = &rte_eth_devices[tx_q->port_id]; dev_private = vrtl_eth_dev->data->dev_private; if (dev_private->tx_burst_fail_count < nb_pkts) { int successfully_txd = nb_pkts - dev_private->tx_burst_fail_count; /* increment opacket count */ dev_private->eth_stats.opackets += successfully_txd; /* free packets in burst */ for (i = 0; i < successfully_txd; i++) { /* free packets in burst */ if (bufs[i] != NULL) rte_pktmbuf_free(bufs[i]); bufs[i] = NULL; } return successfully_txd; } return 0; } void virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success) { struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; if (success) vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success; else vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_fail; } void virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success) { struct virtual_ethdev_private *dev_private = NULL; struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; dev_private = vrtl_eth_dev->data->dev_private; if (success) vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success; else vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail; dev_private->tx_burst_fail_count = 0; } void virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id, uint8_t packet_fail_count) { struct virtual_ethdev_private *dev_private = NULL; struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; dev_private = vrtl_eth_dev->data->dev_private; dev_private->tx_burst_fail_count = packet_fail_count; } void virtual_ethdev_set_link_status(uint8_t port_id, uint8_t link_status) { struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; vrtl_eth_dev->data->dev_link.link_status = link_status; } void virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status) { struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; vrtl_eth_dev->data->dev_link.link_status = link_status; _rte_eth_dev_callback_process(vrtl_eth_dev, RTE_ETH_EVENT_INTR_LSC); } int virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id, struct rte_mbuf **pkt_burst, int burst_length) { struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; struct virtual_ethdev_private *dev_private = vrtl_eth_dev->data->dev_private; return rte_ring_enqueue_burst(dev_private->rx_queue, (void **)pkt_burst, burst_length); } int virtual_ethdev_get_mbufs_from_tx_queue(uint8_t port_id, struct rte_mbuf **pkt_burst, int burst_length) { struct virtual_ethdev_private *dev_private; struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id]; dev_private = vrtl_eth_dev->data->dev_private; return rte_ring_dequeue_burst(dev_private->tx_queue, (void **)pkt_burst, burst_length); } static uint8_t get_number_of_sockets(void) { int sockets = 0; int i; const struct rte_memseg *ms = rte_eal_get_physmem_layout(); for (i = 0; i < RTE_MAX_MEMSEG && ms[i].addr != NULL; i++) { if (sockets < ms[i].socket_id) sockets = ms[i].socket_id; } /* Number of sockets = maximum socket_id + 1 */ return ++sockets; } int virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, uint8_t socket_id, uint8_t isr_support) { struct rte_pci_device *pci_dev = NULL; struct rte_eth_dev *eth_dev = NULL; struct eth_driver *eth_drv = NULL; struct rte_pci_driver *pci_drv = NULL; struct rte_pci_id *id_table = NULL; struct virtual_ethdev_private *dev_private = NULL; char name_buf[RTE_RING_NAMESIZE]; /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (dev_private) data */ if (socket_id >= get_number_of_sockets()) goto err; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id); if (pci_dev == NULL) goto err; eth_drv = rte_zmalloc_socket(name, sizeof(*eth_drv), 0, socket_id); if (eth_drv == NULL) goto err; pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id); if (pci_drv == NULL) goto err; id_table = rte_zmalloc_socket(name, sizeof(*id_table), 0, socket_id); if (id_table == NULL) goto err; id_table->device_id = 0xBEEF; dev_private = rte_zmalloc_socket(name, sizeof(*dev_private), 0, socket_id); if (dev_private == NULL) goto err; snprintf(name_buf, sizeof(name_buf), "%s_rxQ", name); dev_private->rx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id, 0); if (dev_private->rx_queue == NULL) goto err; snprintf(name_buf, sizeof(name_buf), "%s_txQ", name); dev_private->tx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id, 0); if (dev_private->tx_queue == NULL) goto err; /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PCI); if (eth_dev == NULL) goto err; pci_dev->numa_node = socket_id; pci_drv->name = virtual_ethdev_driver_name; pci_drv->id_table = id_table; if (isr_support) pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC; else pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; eth_drv->pci_drv = (struct rte_pci_driver)(*pci_drv); eth_dev->driver = eth_drv; eth_dev->data->nb_rx_queues = (uint16_t)1; eth_dev->data->nb_tx_queues = (uint16_t)1; TAILQ_INIT(&(eth_dev->link_intr_cbs)); eth_dev->data->dev_link.link_status = 0; eth_dev->data->dev_link.link_speed = ETH_LINK_SPEED_10000; eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; eth_dev->data->mac_addrs = rte_zmalloc(name, ETHER_ADDR_LEN, 0); if (eth_dev->data->mac_addrs == NULL) goto err; memcpy(eth_dev->data->mac_addrs, mac_addr, sizeof(*eth_dev->data->mac_addrs)); eth_dev->data->dev_started = 0; eth_dev->data->promiscuous = 0; eth_dev->data->scattered_rx = 0; eth_dev->data->all_multicast = 0; eth_dev->data->dev_private = dev_private; /* Copy default device operation functions */ dev_private->dev_ops = virtual_ethdev_default_dev_ops; eth_dev->dev_ops = &dev_private->dev_ops; eth_dev->pci_dev = pci_dev; eth_dev->pci_dev->driver = ð_drv->pci_drv; eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success; eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success; return eth_dev->data->port_id; err: rte_free(pci_dev); rte_free(pci_drv); rte_free(eth_drv); rte_free(id_table); rte_free(dev_private); return -1; } ================================================ FILE: app/test/virtual_pmd.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __VIRTUAL_ETHDEV_H_ #define __VIRTUAL_ETHDEV_H_ #ifdef __cplusplus extern "C" { #endif #include int virtual_ethdev_init(void); int virtual_ethdev_create(const char *name, struct ether_addr *mac_addr, uint8_t socket_id, uint8_t isr_support); void virtual_ethdev_set_link_status(uint8_t port_id, uint8_t link_status); void virtual_ethdev_simulate_link_status_interrupt(uint8_t port_id, uint8_t link_status); int virtual_ethdev_add_mbufs_to_rx_queue(uint8_t port_id, struct rte_mbuf **pkts_burst, int burst_length); int virtual_ethdev_get_mbufs_from_tx_queue(uint8_t port_id, struct rte_mbuf **pkt_burst, int burst_length); /** Control methods for the dev_ops functions pointer to control the behavior * of the Virtual PMD */ void virtual_ethdev_start_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_stop_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_configure_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_rx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_tx_queue_setup_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_link_update_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_rx_burst_fn_set_success(uint8_t port_id, uint8_t success); void virtual_ethdev_tx_burst_fn_set_success(uint8_t port_id, uint8_t success); /* if a value greater than zero is set for packet_fail_count then virtual * device tx burst function will fail that many packet from burst or all * packets if packet_fail_count is greater than the number of packets in the * burst */ void virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint8_t port_id, uint8_t packet_fail_count); #ifdef __cplusplus } #endif #endif /* __VIRTUAL_ETHDEV_H_ */ ================================================ FILE: app/test-acl/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_LIBRTE_ACL),y) APP = testacl CFLAGS += $(WERROR_FLAGS) # all source are stored in SRCS-y SRCS-y := main.c # this application needs libraries first DEPDIRS-y += lib include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: app/test-acl/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #define PRINT_USAGE_START "%s [EAL options]\n" #define RTE_LOGTYPE_TESTACL RTE_LOGTYPE_USER1 #define APP_NAME "TESTACL" #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ unsigned long val; \ char *end_fld; \ errno = 0; \ val = strtoul((in), &end_fld, (base)); \ if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ return -EINVAL; \ (fd) = (typeof(fd))val; \ (in) = end_fld + 1; \ } while (0) #define OPT_RULE_FILE "rulesf" #define OPT_TRACE_FILE "tracef" #define OPT_RULE_NUM "rulenum" #define OPT_TRACE_NUM "tracenum" #define OPT_TRACE_STEP "tracestep" #define OPT_SEARCH_ALG "alg" #define OPT_BLD_CATEGORIES "bldcat" #define OPT_RUN_CATEGORIES "runcat" #define OPT_MAX_SIZE "maxsize" #define OPT_ITER_NUM "iter" #define OPT_VERBOSE "verbose" #define OPT_IPV6 "ipv6" #define TRACE_DEFAULT_NUM 0x10000 #define TRACE_STEP_MAX 0x1000 #define TRACE_STEP_DEF 0x100 #define RULE_NUM 0x10000 enum { DUMP_NONE, DUMP_SEARCH, DUMP_PKT, DUMP_MAX }; struct acl_alg { const char *name; enum rte_acl_classify_alg alg; }; static const struct acl_alg acl_alg[] = { { .name = "scalar", .alg = RTE_ACL_CLASSIFY_SCALAR, }, { .name = "sse", .alg = RTE_ACL_CLASSIFY_SSE, }, { .name = "avx2", .alg = RTE_ACL_CLASSIFY_AVX2, }, }; static struct { const char *prgname; const char *rule_file; const char *trace_file; size_t max_size; uint32_t bld_categories; uint32_t run_categories; uint32_t nb_rules; uint32_t nb_traces; uint32_t trace_step; uint32_t trace_sz; uint32_t iter_num; uint32_t verbose; uint32_t ipv6; struct acl_alg alg; uint32_t used_traces; void *traces; struct rte_acl_ctx *acx; } config = { .bld_categories = 3, .run_categories = 1, .nb_rules = RULE_NUM, .nb_traces = TRACE_DEFAULT_NUM, .trace_step = TRACE_STEP_DEF, .iter_num = 1, .verbose = DUMP_MAX, .alg = { .name = "default", .alg = RTE_ACL_CLASSIFY_DEFAULT, }, .ipv6 = 0 }; static struct rte_acl_param prm = { .name = APP_NAME, .socket_id = SOCKET_ID_ANY, }; /* * Rule and trace formats definitions. */ struct ipv4_5tuple { uint8_t proto; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; }; enum { PROTO_FIELD_IPV4, SRC_FIELD_IPV4, DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, NUM_FIELDS_IPV4 }; struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PROTO, .offset = offsetof(struct ipv4_5tuple, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_SRC, .offset = offsetof(struct ipv4_5tuple, ip_src), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_DST, .offset = offsetof(struct ipv4_5tuple, ip_dst), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PORTS, .offset = offsetof(struct ipv4_5tuple, port_src), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PORTS, .offset = offsetof(struct ipv4_5tuple, port_dst), }, }; #define IPV6_ADDR_LEN 16 #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) #define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) struct ipv6_5tuple { uint8_t proto; uint32_t ip_src[IPV6_ADDR_U32]; uint32_t ip_dst[IPV6_ADDR_U32]; uint16_t port_src; uint16_t port_dst; }; enum { PROTO_FIELD_IPV6, SRC1_FIELD_IPV6, SRC2_FIELD_IPV6, SRC3_FIELD_IPV6, SRC4_FIELD_IPV6, DST1_FIELD_IPV6, DST2_FIELD_IPV6, DST3_FIELD_IPV6, DST4_FIELD_IPV6, SRCP_FIELD_IPV6, DSTP_FIELD_IPV6, NUM_FIELDS_IPV6 }; struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV6, .input_index = PROTO_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC1_FIELD_IPV6, .input_index = SRC1_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_src[0]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC2_FIELD_IPV6, .input_index = SRC2_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_src[1]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC3_FIELD_IPV6, .input_index = SRC3_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_src[2]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC4_FIELD_IPV6, .input_index = SRC4_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_src[3]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST1_FIELD_IPV6, .input_index = DST1_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_dst[0]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST2_FIELD_IPV6, .input_index = DST2_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_dst[1]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST3_FIELD_IPV6, .input_index = DST3_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_dst[2]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST4_FIELD_IPV6, .input_index = DST4_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, ip_dst[3]), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV6, .input_index = SRCP_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, port_src), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV6, .input_index = SRCP_FIELD_IPV6, .offset = offsetof(struct ipv6_5tuple, port_dst), }, }; enum { CB_FLD_SRC_ADDR, CB_FLD_DST_ADDR, CB_FLD_SRC_PORT_LOW, CB_FLD_SRC_PORT_DLM, CB_FLD_SRC_PORT_HIGH, CB_FLD_DST_PORT_LOW, CB_FLD_DST_PORT_DLM, CB_FLD_DST_PORT_HIGH, CB_FLD_PROTO, CB_FLD_NUM, }; enum { CB_TRC_SRC_ADDR, CB_TRC_DST_ADDR, CB_TRC_SRC_PORT, CB_TRC_DST_PORT, CB_TRC_PROTO, CB_TRC_NUM, }; RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS); static const char cb_port_delim[] = ":"; static char line[LINE_MAX]; #define dump_verbose(lvl, fh, fmt, args...) do { \ if ((lvl) <= (int32_t)config.verbose) \ fprintf(fh, fmt, ##args); \ } while (0) /* * Parse ClassBench input trace (test vectors and expected results) file. * Expected format: * \ * */ static int parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v) { int i; char *s, *sp, *in[CB_TRC_NUM]; static const char *dlm = " \t\n"; s = str; for (i = 0; i != RTE_DIM(in); i++) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; s = NULL; } GET_CB_FIELD(in[CB_TRC_SRC_ADDR], v->ip_src, 0, UINT32_MAX, 0); GET_CB_FIELD(in[CB_TRC_DST_ADDR], v->ip_dst, 0, UINT32_MAX, 0); GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); /* convert to network byte order. */ v->ip_src = rte_cpu_to_be_32(v->ip_src); v->ip_dst = rte_cpu_to_be_32(v->ip_dst); v->port_src = rte_cpu_to_be_16(v->port_src); v->port_dst = rte_cpu_to_be_16(v->port_dst); return 0; } /* * Parses IPV6 address, exepcts the following format: * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit). */ static int parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32], char dlm) { uint32_t addr[IPV6_ADDR_U16]; GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm); *end = in; v[0] = (addr[0] << 16) + addr[1]; v[1] = (addr[2] << 16) + addr[3]; v[2] = (addr[4] << 16) + addr[5]; v[3] = (addr[6] << 16) + addr[7]; return 0; } static int parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32]) { int32_t rc; const char *end; rc = parse_ipv6_addr(in, &end, v, 0); if (rc != 0) return rc; v[0] = rte_cpu_to_be_32(v[0]); v[1] = rte_cpu_to_be_32(v[1]); v[2] = rte_cpu_to_be_32(v[2]); v[3] = rte_cpu_to_be_32(v[3]); return 0; } /* * Parse ClassBench input trace (test vectors and expected results) file. * Expected format: * \ * */ static int parse_cb_ipv6_trace(char *str, struct ipv6_5tuple *v) { int32_t i, rc; char *s, *sp, *in[CB_TRC_NUM]; static const char *dlm = " \t\n"; s = str; for (i = 0; i != RTE_DIM(in); i++) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; s = NULL; } /* get ip6 src address. */ rc = parse_cb_ipv6_addr_trace(in[CB_TRC_SRC_ADDR], v->ip_src); if (rc != 0) return rc; /* get ip6 dst address. */ rc = parse_cb_ipv6_addr_trace(in[CB_TRC_DST_ADDR], v->ip_dst); if (rc != 0) return rc; GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); /* convert to network byte order. */ v->port_src = rte_cpu_to_be_16(v->port_src); v->port_dst = rte_cpu_to_be_16(v->port_dst); return 0; } static void tracef_init(void) { static const char name[] = APP_NAME; FILE *f; size_t sz; uint32_t n; struct ipv4_5tuple *v; struct ipv6_5tuple *w; sz = config.nb_traces * (config.ipv6 ? sizeof(*w) : sizeof(*v)); config.traces = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); if (config.traces == NULL) rte_exit(EXIT_FAILURE, "Cannot allocate %zu bytes for " "requested %u number of trace records\n", sz, config.nb_traces); f = fopen(config.trace_file, "r"); if (f == NULL) rte_exit(-EINVAL, "failed to open file: %s\n", config.trace_file); v = config.traces; w = config.traces; for (n = 0; n != config.nb_traces; n++) { if (fgets(line, sizeof(line), f) == NULL) break; if (config.ipv6) { if (parse_cb_ipv6_trace(line, w + n) != 0) rte_exit(EXIT_FAILURE, "%s: failed to parse ipv6 trace " "record at line %u\n", config.trace_file, n + 1); } else { if (parse_cb_ipv4_trace(line, v + n) != 0) rte_exit(EXIT_FAILURE, "%s: failed to parse ipv4 trace " "record at line %u\n", config.trace_file, n + 1); } } config.used_traces = n; fclose(f); } static int parse_ipv6_net(const char *in, struct rte_acl_field field[4]) { int32_t rc; const char *mp; uint32_t i, m, v[4]; const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; /* get address. */ rc = parse_ipv6_addr(in, &mp, v, '/'); if (rc != 0) return rc; /* get mask. */ GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); /* put all together. */ for (i = 0; i != RTE_DIM(v); i++) { if (m >= (i + 1) * nbu32) field[i].mask_range.u32 = nbu32; else field[i].mask_range.u32 = m > (i * nbu32) ? m - (i * 32) : 0; field[i].value.u32 = v[i]; } return 0; } static int parse_cb_ipv6_rule(char *str, struct acl_rule *v) { int i, rc; char *s, *sp, *in[CB_FLD_NUM]; static const char *dlm = " \t\n"; /* * Skip leading '@' */ if (strchr(str, '@') != str) return -EINVAL; s = str + 1; for (i = 0; i != RTE_DIM(in); i++) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; s = NULL; } rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); if (rc != 0) { RTE_LOG(ERR, TESTACL, "failed to read source address/mask: %s\n", in[CB_FLD_SRC_ADDR]); return rc; } rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); if (rc != 0) { RTE_LOG(ERR, TESTACL, "failed to read destination address/mask: %s\n", in[CB_FLD_DST_ADDR]); return rc; } /* source port. */ GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], v->field[SRCP_FIELD_IPV6].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], v->field[SRCP_FIELD_IPV6].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; /* destination port. */ GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], v->field[DSTP_FIELD_IPV6].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], v->field[DSTP_FIELD_IPV6].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8, 0, UINT8_MAX, '/'); GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8, 0, UINT8_MAX, 0); return 0; } static int parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) { uint8_t a, b, c, d, m; GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); addr[0] = IPv4(a, b, c, d); mask_len[0] = m; return 0; } /* * Parse ClassBench rules file. * Expected format: * '@''/' \ * '/' \ * ":" \ * ":" \ * '/' */ static int parse_cb_ipv4_rule(char *str, struct acl_rule *v) { int i, rc; char *s, *sp, *in[CB_FLD_NUM]; static const char *dlm = " \t\n"; /* * Skip leading '@' */ if (strchr(str, '@') != str) return -EINVAL; s = str + 1; for (i = 0; i != RTE_DIM(in); i++) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; s = NULL; } rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], &v->field[SRC_FIELD_IPV4].value.u32, &v->field[SRC_FIELD_IPV4].mask_range.u32); if (rc != 0) { RTE_LOG(ERR, TESTACL, "failed to read source address/mask: %s\n", in[CB_FLD_SRC_ADDR]); return rc; } rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], &v->field[DST_FIELD_IPV4].value.u32, &v->field[DST_FIELD_IPV4].mask_range.u32); if (rc != 0) { RTE_LOG(ERR, TESTACL, "failed to read destination address/mask: %s\n", in[CB_FLD_DST_ADDR]); return rc; } /* source port. */ GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], v->field[SRCP_FIELD_IPV4].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], v->field[SRCP_FIELD_IPV4].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; /* destination port. */ GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], v->field[DSTP_FIELD_IPV4].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], v->field[DSTP_FIELD_IPV4].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8, 0, UINT8_MAX, '/'); GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8, 0, UINT8_MAX, 0); return 0; } typedef int (*parse_5tuple)(char *text, struct acl_rule *rule); static int add_cb_rules(FILE *f, struct rte_acl_ctx *ctx) { int rc; uint32_t n; struct acl_rule v; parse_5tuple parser; memset(&v, 0, sizeof(v)); parser = (config.ipv6 != 0) ? parse_cb_ipv6_rule : parse_cb_ipv4_rule; for (n = 1; fgets(line, sizeof(line), f) != NULL; n++) { rc = parser(line, &v); if (rc != 0) { RTE_LOG(ERR, TESTACL, "line %u: parse_cb_ipv4vlan_rule" " failed, error code: %d (%s)\n", n, rc, strerror(-rc)); return rc; } v.data.category_mask = RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES, typeof(v.data.category_mask)); v.data.priority = RTE_ACL_MAX_PRIORITY - n; v.data.userdata = n; rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&v, 1); if (rc != 0) { RTE_LOG(ERR, TESTACL, "line %u: failed to add rules " "into ACL context, error code: %d (%s)\n", n, rc, strerror(-rc)); return rc; } } return 0; } static void acx_init(void) { int ret; FILE *f; struct rte_acl_config cfg; memset(&cfg, 0, sizeof(cfg)); /* setup ACL build config. */ if (config.ipv6) { cfg.num_fields = RTE_DIM(ipv6_defs); memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs)); } else { cfg.num_fields = RTE_DIM(ipv4_defs); memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs)); } cfg.num_categories = config.bld_categories; cfg.max_size = config.max_size; /* setup ACL creation parameters. */ prm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields); prm.max_rule_num = config.nb_rules; config.acx = rte_acl_create(&prm); if (config.acx == NULL) rte_exit(rte_errno, "failed to create ACL context\n"); /* set default classify method for this context. */ if (config.alg.alg != RTE_ACL_CLASSIFY_DEFAULT) { ret = rte_acl_set_ctx_classify(config.acx, config.alg.alg); if (ret != 0) rte_exit(ret, "failed to setup %s method " "for ACL context\n", config.alg.name); } /* add ACL rules. */ f = fopen(config.rule_file, "r"); if (f == NULL) rte_exit(-EINVAL, "failed to open file %s\n", config.rule_file); ret = add_cb_rules(f, config.acx); if (ret != 0) rte_exit(ret, "failed to add rules into ACL context\n"); fclose(f); /* perform build. */ ret = rte_acl_build(config.acx, &cfg); dump_verbose(DUMP_NONE, stdout, "rte_acl_build(%u) finished with %d\n", config.bld_categories, ret); rte_acl_dump(config.acx); if (ret != 0) rte_exit(ret, "failed to build search context\n"); } static uint32_t search_ip5tuples_once(uint32_t categories, uint32_t step, const char *alg) { int ret; uint32_t i, j, k, n, r; const uint8_t *data[step], *v; uint32_t results[step * categories]; v = config.traces; for (i = 0; i != config.used_traces; i += n) { n = RTE_MIN(step, config.used_traces - i); for (j = 0; j != n; j++) { data[j] = v; v += config.trace_sz; } ret = rte_acl_classify(config.acx, data, results, n, categories); if (ret != 0) rte_exit(ret, "classify for ipv%c_5tuples returns %d\n", config.ipv6 ? '6' : '4', ret); for (r = 0, j = 0; j != n; j++) { for (k = 0; k != categories; k++, r++) { dump_verbose(DUMP_PKT, stdout, "ipv%c_5tuple: %u, category: %u, " "result: %u\n", config.ipv6 ? '6' : '4', i + j + 1, k, results[r] - 1); } } } dump_verbose(DUMP_SEARCH, stdout, "%s(%u, %u, %s) returns %u\n", __func__, categories, step, alg, i); return i; } static int search_ip5tuples(__attribute__((unused)) void *arg) { uint64_t pkt, start, tm; uint32_t i, lcore; lcore = rte_lcore_id(); start = rte_rdtsc(); pkt = 0; for (i = 0; i != config.iter_num; i++) { pkt += search_ip5tuples_once(config.run_categories, config.trace_step, config.alg.name); } tm = rte_rdtsc() - start; dump_verbose(DUMP_NONE, stdout, "%s @lcore %u: %" PRIu32 " iterations, %" PRIu64 " pkts, %" PRIu32 " categories, %" PRIu64 " cycles, %#Lf cycles/pkt\n", __func__, lcore, i, pkt, config.run_categories, tm, (long double)tm / pkt); return 0; } static unsigned long get_ulong_opt(const char *opt, const char *name, size_t min, size_t max) { unsigned long val; char *end; errno = 0; val = strtoul(opt, &end, 0); if (errno != 0 || end[0] != 0 || val > max || val < min) rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", opt, name); return val; } static void get_alg_opt(const char *opt, const char *name) { uint32_t i; for (i = 0; i != RTE_DIM(acl_alg); i++) { if (strcmp(opt, acl_alg[i].name) == 0) { config.alg = acl_alg[i]; return; } } rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", opt, name); } static void print_usage(const char *prgname) { uint32_t i, n, rc; char buf[PATH_MAX]; n = 0; buf[0] = 0; for (i = 0; i < RTE_DIM(acl_alg) - 1; i++) { rc = snprintf(buf + n, sizeof(buf) - n, "%s|", acl_alg[i].name); if (rc > sizeof(buf) - n) break; n += rc; } snprintf(buf + n, sizeof(buf) - n, "%s", acl_alg[i].name); fprintf(stdout, PRINT_USAGE_START "--" OPT_RULE_FILE "=\n" "[--" OPT_TRACE_FILE "=]\n" "[--" OPT_RULE_NUM "=]\n" "[--" OPT_TRACE_NUM "=]\n" "[--" OPT_TRACE_STEP "=]\n" "[--" OPT_BLD_CATEGORIES "=]\n" "[--" OPT_RUN_CATEGORIES "= " "should be either 1 or multiple of %zu, " "but not greater then %u]\n" "[--" OPT_MAX_SIZE "= " "leave 0 for default behaviour]\n" "[--" OPT_ITER_NUM "=]\n" "[--" OPT_VERBOSE "=]\n" "[--" OPT_SEARCH_ALG "=%s]\n" "[--" OPT_IPV6 "=]\n", prgname, RTE_ACL_RESULTS_MULTIPLIER, (uint32_t)RTE_ACL_MAX_CATEGORIES, buf); } static void dump_config(FILE *f) { fprintf(f, "%s:\n", __func__); fprintf(f, "%s:%s\n", OPT_RULE_FILE, config.rule_file); fprintf(f, "%s:%s\n", OPT_TRACE_FILE, config.trace_file); fprintf(f, "%s:%u\n", OPT_RULE_NUM, config.nb_rules); fprintf(f, "%s:%u\n", OPT_TRACE_NUM, config.nb_traces); fprintf(f, "%s:%u\n", OPT_TRACE_STEP, config.trace_step); fprintf(f, "%s:%u\n", OPT_BLD_CATEGORIES, config.bld_categories); fprintf(f, "%s:%u\n", OPT_RUN_CATEGORIES, config.run_categories); fprintf(f, "%s:%zu\n", OPT_MAX_SIZE, config.max_size); fprintf(f, "%s:%u\n", OPT_ITER_NUM, config.iter_num); fprintf(f, "%s:%u\n", OPT_VERBOSE, config.verbose); fprintf(f, "%s:%u(%s)\n", OPT_SEARCH_ALG, config.alg.alg, config.alg.name); fprintf(f, "%s:%u\n", OPT_IPV6, config.ipv6); } static void check_config(void) { if (config.rule_file == NULL) { print_usage(config.prgname); rte_exit(-EINVAL, "mandatory option %s is not specified\n", OPT_RULE_FILE); } } static void get_input_opts(int argc, char **argv) { static struct option lgopts[] = { {OPT_RULE_FILE, 1, 0, 0}, {OPT_TRACE_FILE, 1, 0, 0}, {OPT_TRACE_NUM, 1, 0, 0}, {OPT_RULE_NUM, 1, 0, 0}, {OPT_MAX_SIZE, 1, 0, 0}, {OPT_TRACE_STEP, 1, 0, 0}, {OPT_BLD_CATEGORIES, 1, 0, 0}, {OPT_RUN_CATEGORIES, 1, 0, 0}, {OPT_ITER_NUM, 1, 0, 0}, {OPT_VERBOSE, 1, 0, 0}, {OPT_SEARCH_ALG, 1, 0, 0}, {OPT_IPV6, 0, 0, 0}, {NULL, 0, 0, 0} }; int opt, opt_idx; while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) { if (opt != 0) { print_usage(config.prgname); rte_exit(-EINVAL, "unknown option: %c", opt); } if (strcmp(lgopts[opt_idx].name, OPT_RULE_FILE) == 0) { config.rule_file = optarg; } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) { config.trace_file = optarg; } else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) { config.nb_rules = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, RTE_ACL_MAX_INDEX + 1); } else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) { config.max_size = get_ulong_opt(optarg, lgopts[opt_idx].name, 0, SIZE_MAX); } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) { config.nb_traces = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, UINT32_MAX); } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) { config.trace_step = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, TRACE_STEP_MAX); } else if (strcmp(lgopts[opt_idx].name, OPT_BLD_CATEGORIES) == 0) { config.bld_categories = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, RTE_ACL_MAX_CATEGORIES); } else if (strcmp(lgopts[opt_idx].name, OPT_RUN_CATEGORIES) == 0) { config.run_categories = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, RTE_ACL_MAX_CATEGORIES); } else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) { config.iter_num = get_ulong_opt(optarg, lgopts[opt_idx].name, 1, INT32_MAX); } else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) { config.verbose = get_ulong_opt(optarg, lgopts[opt_idx].name, DUMP_NONE, DUMP_MAX); } else if (strcmp(lgopts[opt_idx].name, OPT_SEARCH_ALG) == 0) { get_alg_opt(optarg, lgopts[opt_idx].name); } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) { config.ipv6 = 1; } } config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) : sizeof(struct ipv4_5tuple); } int main(int argc, char **argv) { int ret; uint32_t lcore; ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); argc -= ret; argv += ret; config.prgname = argv[0]; get_input_opts(argc, argv); dump_config(stdout); check_config(); acx_init(); if (config.trace_file != NULL) tracef_init(); RTE_LCORE_FOREACH_SLAVE(lcore) rte_eal_remote_launch(search_ip5tuples, NULL, lcore); search_ip5tuples(NULL); rte_eal_mp_wait_lcore(); rte_acl_free(config.acx); return 0; } ================================================ FILE: app/test-pipeline/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_LIBRTE_PIPELINE),y) # # library name # APP = testpipeline CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # # all source are stored in SRCS-y # SRCS-y := main.c SRCS-y += config.c SRCS-y += init.c SRCS-y += runtime.c SRCS-y += pipeline_stub.c SRCS-y += pipeline_hash.c SRCS-y += pipeline_lpm.c SRCS-y += pipeline_lpm_ipv6.c # include ACL lib if available SRCS-$(CONFIG_RTE_LIBRTE_ACL) += pipeline_acl.c # this application needs libraries first DEPDIRS-y += lib drivers include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: app/test-pipeline/config.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" struct app_params app; static const char usage[] = "\n"; void app_print_usage(void) { printf(usage); } static int app_parse_port_mask(const char *arg) { char *end = NULL; uint64_t port_mask; uint32_t i; if (arg[0] == '\0') return -1; port_mask = strtoul(arg, &end, 16); if ((end == NULL) || (*end != '\0')) return -2; if (port_mask == 0) return -3; app.n_ports = 0; for (i = 0; i < 64; i++) { if ((port_mask & (1LLU << i)) == 0) continue; if (app.n_ports >= APP_MAX_PORTS) return -4; app.ports[app.n_ports] = i; app.n_ports++; } if (!rte_is_power_of_2(app.n_ports)) return -5; return 0; } struct { const char *name; uint32_t value; } app_args_table[] = { {"none", e_APP_PIPELINE_NONE}, {"stub", e_APP_PIPELINE_STUB}, {"hash-8-ext", e_APP_PIPELINE_HASH_KEY8_EXT}, {"hash-8-lru", e_APP_PIPELINE_HASH_KEY8_LRU}, {"hash-16-ext", e_APP_PIPELINE_HASH_KEY16_EXT}, {"hash-16-lru", e_APP_PIPELINE_HASH_KEY16_LRU}, {"hash-32-ext", e_APP_PIPELINE_HASH_KEY32_EXT}, {"hash-32-lru", e_APP_PIPELINE_HASH_KEY32_LRU}, {"hash-spec-8-ext", e_APP_PIPELINE_HASH_SPEC_KEY8_EXT}, {"hash-spec-8-lru", e_APP_PIPELINE_HASH_SPEC_KEY8_LRU}, {"hash-spec-16-ext", e_APP_PIPELINE_HASH_SPEC_KEY16_EXT}, {"hash-spec-16-lru", e_APP_PIPELINE_HASH_SPEC_KEY16_LRU}, {"hash-spec-32-ext", e_APP_PIPELINE_HASH_SPEC_KEY32_EXT}, {"hash-spec-32-lru", e_APP_PIPELINE_HASH_SPEC_KEY32_LRU}, {"acl", e_APP_PIPELINE_ACL}, {"lpm", e_APP_PIPELINE_LPM}, {"lpm-ipv6", e_APP_PIPELINE_LPM_IPV6}, }; int app_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"none", 0, 0, 0}, {"stub", 0, 0, 0}, {"hash-8-ext", 0, 0, 0}, {"hash-8-lru", 0, 0, 0}, {"hash-16-ext", 0, 0, 0}, {"hash-16-lru", 0, 0, 0}, {"hash-32-ext", 0, 0, 0}, {"hash-32-lru", 0, 0, 0}, {"hash-spec-8-ext", 0, 0, 0}, {"hash-spec-8-lru", 0, 0, 0}, {"hash-spec-16-ext", 0, 0, 0}, {"hash-spec-16-lru", 0, 0, 0}, {"hash-spec-32-ext", 0, 0, 0}, {"hash-spec-32-lru", 0, 0, 0}, {"acl", 0, 0, 0}, {"lpm", 0, 0, 0}, {"lpm-ipv6", 0, 0, 0}, {NULL, 0, 0, 0} }; uint32_t lcores[3], n_lcores, lcore_id, pipeline_type_provided; /* EAL args */ n_lcores = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (n_lcores >= 3) { RTE_LOG(ERR, USER1, "Number of cores must be 3\n"); app_print_usage(); return -1; } lcores[n_lcores] = lcore_id; n_lcores++; } if (n_lcores != 3) { RTE_LOG(ERR, USER1, "Number of cores must be 3\n"); app_print_usage(); return -1; } app.core_rx = lcores[0]; app.core_worker = lcores[1]; app.core_tx = lcores[2]; /* Non-EAL args */ argvopt = argv; app.pipeline_type = e_APP_PIPELINE_HASH_KEY16_LRU; pipeline_type_provided = 0; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { case 'p': if (app_parse_port_mask(optarg) < 0) { app_print_usage(); return -1; } break; case 0: /* long options */ if (!pipeline_type_provided) { uint32_t i; for (i = 0; i < e_APP_PIPELINES; i++) { if (!strcmp(lgopts[option_index].name, app_args_table[i].name)) { app.pipeline_type = app_args_table[i].value; pipeline_type_provided = 1; break; } } break; } app_print_usage(); return -1; default: return -1; } } if (optind >= 0) argv[optind - 1] = prgname; ret = optind - 1; optind = 0; /* reset getopt lib */ return ret; } ================================================ FILE: app/test-pipeline/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" struct app_params app = { /* Ports*/ .n_ports = APP_MAX_PORTS, .port_rx_ring_size = 128, .port_tx_ring_size = 512, /* Rings */ .ring_rx_size = 128, .ring_tx_size = 128, /* Buffer pool */ .pool_buffer_size = 2048 + RTE_PKTMBUF_HEADROOM, .pool_size = 32 * 1024, .pool_cache_size = 256, /* Burst sizes */ .burst_size_rx_read = 64, .burst_size_rx_write = 64, .burst_size_worker_read = 64, .burst_size_worker_write = 64, .burst_size_tx_read = 64, .burst_size_tx_write = 64, }; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /* Header Split disabled */ .hw_ip_checksum = 1, /* IP checksum offload enabled */ .hw_vlan_filter = 0, /* VLAN filtering disabled */ .jumbo_frame = 0, /* Jumbo Frame Support disabled */ .hw_strip_crc = 0, /* CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_eth_rxconf rx_conf = { .rx_thresh = { .pthresh = 8, .hthresh = 8, .wthresh = 4, }, .rx_free_thresh = 64, .rx_drop_en = 0, }; static struct rte_eth_txconf tx_conf = { .tx_thresh = { .pthresh = 36, .hthresh = 0, .wthresh = 0, }, .tx_free_thresh = 0, .tx_rs_thresh = 0, }; static void app_init_mbuf_pools(void) { /* Init the buffer pool */ RTE_LOG(INFO, USER1, "Creating the mbuf pool ...\n"); app.pool = rte_pktmbuf_pool_create("mempool", app.pool_size, app.pool_cache_size, 0, app.pool_buffer_size, rte_socket_id()); if (app.pool == NULL) rte_panic("Cannot create mbuf pool\n"); } static void app_init_rings(void) { uint32_t i; for (i = 0; i < app.n_ports; i++) { char name[32]; snprintf(name, sizeof(name), "app_ring_rx_%u", i); app.rings_rx[i] = rte_ring_create( name, app.ring_rx_size, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); if (app.rings_rx[i] == NULL) rte_panic("Cannot create RX ring %u\n", i); } for (i = 0; i < app.n_ports; i++) { char name[32]; snprintf(name, sizeof(name), "app_ring_tx_%u", i); app.rings_tx[i] = rte_ring_create( name, app.ring_tx_size, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); if (app.rings_tx[i] == NULL) rte_panic("Cannot create TX ring %u\n", i); } } static void app_ports_check_link(void) { uint32_t all_ports_up, i; all_ports_up = 1; for (i = 0; i < app.n_ports; i++) { struct rte_eth_link link; uint8_t port; port = (uint8_t) app.ports[i]; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(port, &link); RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n", port, link.link_speed / 1000, link.link_status ? "UP" : "DOWN"); if (link.link_status == 0) all_ports_up = 0; } if (all_ports_up == 0) rte_panic("Some NIC ports are DOWN\n"); } static void app_init_ports(void) { uint32_t i; /* Init NIC ports, then start the ports */ for (i = 0; i < app.n_ports; i++) { uint8_t port; int ret; port = (uint8_t) app.ports[i]; RTE_LOG(INFO, USER1, "Initializing NIC port %u ...\n", port); /* Init port */ ret = rte_eth_dev_configure( port, 1, 1, &port_conf); if (ret < 0) rte_panic("Cannot init NIC port %u (%d)\n", port, ret); rte_eth_promiscuous_enable(port); /* Init RX queues */ ret = rte_eth_rx_queue_setup( port, 0, app.port_rx_ring_size, rte_eth_dev_socket_id(port), &rx_conf, app.pool); if (ret < 0) rte_panic("Cannot init RX for port %u (%d)\n", (uint32_t) port, ret); /* Init TX queues */ ret = rte_eth_tx_queue_setup( port, 0, app.port_tx_ring_size, rte_eth_dev_socket_id(port), &tx_conf); if (ret < 0) rte_panic("Cannot init TX for port %u (%d)\n", (uint32_t) port, ret); /* Start port */ ret = rte_eth_dev_start(port); if (ret < 0) rte_panic("Cannot start port %u (%d)\n", port, ret); } app_ports_check_link(); } void app_init(void) { app_init_mbuf_pools(); app_init_rings(); app_init_ports(); RTE_LOG(INFO, USER1, "Initialization completed\n"); } ================================================ FILE: app/test-pipeline/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" int main(int argc, char **argv) { uint32_t lcore; int ret; /* Init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) return -1; argc -= ret; argv += ret; /* Parse application arguments (after the EAL ones) */ ret = app_parse_args(argc, argv); if (ret < 0) { app_print_usage(); return -1; } /* Init */ app_init(); /* Launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore) { if (rte_eal_wait_lcore(lcore) < 0) return -1; } return 0; } int app_lcore_main_loop(__attribute__((unused)) void *arg) { unsigned lcore; lcore = rte_lcore_id(); if (lcore == app.core_rx) { switch (app.pipeline_type) { case e_APP_PIPELINE_ACL: app_main_loop_rx(); return 0; default: app_main_loop_rx_metadata(); return 0; } } if (lcore == app.core_worker) { switch (app.pipeline_type) { case e_APP_PIPELINE_STUB: app_main_loop_worker_pipeline_stub(); return 0; case e_APP_PIPELINE_HASH_KEY8_EXT: case e_APP_PIPELINE_HASH_KEY8_LRU: case e_APP_PIPELINE_HASH_KEY16_EXT: case e_APP_PIPELINE_HASH_KEY16_LRU: case e_APP_PIPELINE_HASH_KEY32_EXT: case e_APP_PIPELINE_HASH_KEY32_LRU: case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT: case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU: case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT: case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU: case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT: case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU: app_main_loop_worker_pipeline_hash(); return 0; case e_APP_PIPELINE_ACL: #ifndef RTE_LIBRTE_ACL rte_exit(EXIT_FAILURE, "ACL not present in build\n"); #else app_main_loop_worker_pipeline_acl(); return 0; #endif case e_APP_PIPELINE_LPM: app_main_loop_worker_pipeline_lpm(); return 0; case e_APP_PIPELINE_LPM_IPV6: app_main_loop_worker_pipeline_lpm_ipv6(); return 0; case e_APP_PIPELINE_NONE: default: app_main_loop_worker(); return 0; } } if (lcore == app.core_tx) { app_main_loop_tx(); return 0; } return 0; } ================================================ FILE: app/test-pipeline/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ #ifndef APP_MBUF_ARRAY_SIZE #define APP_MBUF_ARRAY_SIZE 256 #endif struct app_mbuf_array { struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE]; uint16_t n_mbufs; }; #ifndef APP_MAX_PORTS #define APP_MAX_PORTS 4 #endif struct app_params { /* CPU cores */ uint32_t core_rx; uint32_t core_worker; uint32_t core_tx; /* Ports*/ uint32_t ports[APP_MAX_PORTS]; uint32_t n_ports; uint32_t port_rx_ring_size; uint32_t port_tx_ring_size; /* Rings */ struct rte_ring *rings_rx[APP_MAX_PORTS]; struct rte_ring *rings_tx[APP_MAX_PORTS]; uint32_t ring_rx_size; uint32_t ring_tx_size; /* Internal buffers */ struct app_mbuf_array mbuf_rx; struct app_mbuf_array mbuf_tx[APP_MAX_PORTS]; /* Buffer pool */ struct rte_mempool *pool; uint32_t pool_buffer_size; uint32_t pool_size; uint32_t pool_cache_size; /* Burst sizes */ uint32_t burst_size_rx_read; uint32_t burst_size_rx_write; uint32_t burst_size_worker_read; uint32_t burst_size_worker_write; uint32_t burst_size_tx_read; uint32_t burst_size_tx_write; /* App behavior */ uint32_t pipeline_type; } __rte_cache_aligned; extern struct app_params app; int app_parse_args(int argc, char **argv); void app_print_usage(void); void app_init(void); int app_lcore_main_loop(void *arg); /* Pipeline */ enum { e_APP_PIPELINE_NONE = 0, e_APP_PIPELINE_STUB, e_APP_PIPELINE_HASH_KEY8_EXT, e_APP_PIPELINE_HASH_KEY8_LRU, e_APP_PIPELINE_HASH_KEY16_EXT, e_APP_PIPELINE_HASH_KEY16_LRU, e_APP_PIPELINE_HASH_KEY32_EXT, e_APP_PIPELINE_HASH_KEY32_LRU, e_APP_PIPELINE_HASH_SPEC_KEY8_EXT, e_APP_PIPELINE_HASH_SPEC_KEY8_LRU, e_APP_PIPELINE_HASH_SPEC_KEY16_EXT, e_APP_PIPELINE_HASH_SPEC_KEY16_LRU, e_APP_PIPELINE_HASH_SPEC_KEY32_EXT, e_APP_PIPELINE_HASH_SPEC_KEY32_LRU, e_APP_PIPELINE_ACL, e_APP_PIPELINE_LPM, e_APP_PIPELINE_LPM_IPV6, e_APP_PIPELINES }; void app_main_loop_rx(void); void app_main_loop_rx_metadata(void); uint64_t test_hash(void *key, uint32_t key_size, uint64_t seed); void app_main_loop_worker(void); void app_main_loop_worker_pipeline_stub(void); void app_main_loop_worker_pipeline_hash(void); void app_main_loop_worker_pipeline_acl(void); void app_main_loop_worker_pipeline_lpm(void); void app_main_loop_worker_pipeline_lpm_ipv6(void); void app_main_loop_tx(void); #define APP_FLUSH 0 #ifndef APP_FLUSH #define APP_FLUSH 0x3FF #endif #endif /* _MAIN_H_ */ ================================================ FILE: app/test-pipeline/pipeline_acl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" enum { PROTO_FIELD_IPV4, SRC_FIELD_IPV4, DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, NUM_FIELDS_IPV4 }; /* * Here we define the 'shape' of the data we're searching for, * by defining the meta-data of the ACL rules. * in this case, we're defining 5 tuples. IP addresses, ports, * and protocol. */ struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV4, .input_index = PROTO_FIELD_IPV4, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, next_proto_id), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC_FIELD_IPV4, .input_index = SRC_FIELD_IPV4, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, src_addr), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST_FIELD_IPV4, .input_index = DST_FIELD_IPV4, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, dst_addr), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV4, .input_index = SRCP_FIELD_IPV4, .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV4, .input_index = SRCP_FIELD_IPV4, .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(uint16_t), }, }; void app_main_loop_worker_pipeline_acl(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with ACL table)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ { struct rte_table_acl_params table_acl_params = { .name = "test", /* unique identifier for acl contexts */ .n_rules = 1 << 5, .n_rule_fields = DIM(ipv4_field_formats), }; /* Copy in the rule meta-data defined above into the params */ memcpy(table_acl_params.field_format, ipv4_field_formats, sizeof(ipv4_field_formats)); struct rte_pipeline_table_params table_params = { .ops = &rte_table_acl_ops, .arg_create = &table_acl_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the ACL table\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry table_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_table_acl_rule_add_params rule_params; struct rte_pipeline_table_entry *entry_ptr; int key_found, ret; memset(&rule_params, 0, sizeof(rule_params)); /* Set the rule values */ rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0; rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0; rule_params.field_value[DST_FIELD_IPV4].value.u32 = i << (24 - __builtin_popcount(app.n_ports - 1)); rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 = 8 + __builtin_popcount(app.n_ports - 1); rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0; rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 = UINT16_MAX; rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0; rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 = UINT16_MAX; rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0; rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0; rule_params.priority = 0; uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4]. value.u32; uint32_t dst_mask = rule_params.field_value[DST_FIELD_IPV4].mask_range.u32; printf("Adding rule to ACL table (IPv4 destination = " "%u.%u.%u.%u/%u => port out = %u)\n", (dst_addr & 0xFF000000) >> 24, (dst_addr & 0x00FF0000) >> 16, (dst_addr & 0x0000FF00) >> 8, dst_addr & 0x000000FF, dst_mask, table_entry.port_id); /* For ACL, add needs an rte_table_acl_rule_add_params struct */ ret = rte_pipeline_table_entry_add(p, table_id, &rule_params, &table_entry, &key_found, &entry_ptr); if (ret < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, ret); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif } ================================================ FILE: app/test-pipeline/pipeline_hash.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" static void translate_options(uint32_t *special, uint32_t *ext, uint32_t *key_size) { switch (app.pipeline_type) { case e_APP_PIPELINE_HASH_KEY8_EXT: *special = 0; *ext = 1; *key_size = 8; return; case e_APP_PIPELINE_HASH_KEY8_LRU: *special = 0; *ext = 0; *key_size = 8; return; case e_APP_PIPELINE_HASH_KEY16_EXT: *special = 0; *ext = 1; *key_size = 16; return; case e_APP_PIPELINE_HASH_KEY16_LRU: *special = 0; *ext = 0; *key_size = 16; return; case e_APP_PIPELINE_HASH_KEY32_EXT: *special = 0; *ext = 1; *key_size = 32; return; case e_APP_PIPELINE_HASH_KEY32_LRU: *special = 0; *ext = 0; *key_size = 32; return; case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT: *special = 1; *ext = 1; *key_size = 8; return; case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU: *special = 1; *ext = 0; *key_size = 8; return; case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT: *special = 1; *ext = 1; *key_size = 16; return; case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU: *special = 1; *ext = 0; *key_size = 16; return; case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT: *special = 1; *ext = 1; *key_size = 32; return; case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU: *special = 1; *ext = 0; *key_size = 32; return; default: rte_panic("Invalid hash table type or key size\n"); } } void app_main_loop_worker_pipeline_hash(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; uint32_t special, ext, key_size; translate_options(&special, &ext, &key_size); RTE_LOG(INFO, USER1, "Core %u is doing work " "(pipeline with hash table, %s, %s, %d-byte key)\n", rte_lcore_id(), special ? "specialized" : "non-specialized", ext ? "extendible bucket" : "LRU", key_size); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ switch (app.pipeline_type) { case e_APP_PIPELINE_HASH_KEY8_EXT: case e_APP_PIPELINE_HASH_KEY16_EXT: case e_APP_PIPELINE_HASH_KEY32_EXT: { struct rte_table_hash_ext_params table_hash_params = { .key_size = key_size, .n_keys = 1 << 24, .n_buckets = 1 << 22, .n_buckets_ext = 1 << 21, .f_hash = test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_ext_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_KEY8_LRU: case e_APP_PIPELINE_HASH_KEY16_LRU: case e_APP_PIPELINE_HASH_KEY32_LRU: { struct rte_table_hash_lru_params table_hash_params = { .key_size = key_size, .n_keys = 1 << 24, .n_buckets = 1 << 22, .f_hash = test_hash, .seed = 0, .signature_offset = 0, .key_offset = 32, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_lru_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT: { struct rte_table_hash_key8_ext_params table_hash_params = { .n_entries = 1 << 24, .n_entries_ext = 1 << 23, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key8_ext_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU: { struct rte_table_hash_key8_lru_params table_hash_params = { .n_entries = 1 << 24, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key8_lru_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT: { struct rte_table_hash_key16_ext_params table_hash_params = { .n_entries = 1 << 24, .n_entries_ext = 1 << 23, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key16_ext_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table)\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU: { struct rte_table_hash_key16_lru_params table_hash_params = { .n_entries = 1 << 24, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key16_lru_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT: { struct rte_table_hash_key32_ext_params table_hash_params = { .n_entries = 1 << 24, .n_entries_ext = 1 << 23, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key32_ext_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU: { struct rte_table_hash_key32_lru_params table_hash_params = { .n_entries = 1 << 24, .signature_offset = 0, .key_offset = 32, .f_hash = test_hash, .seed = 0, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key32_lru_ops, .arg_create = &table_hash_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the hash table\n"); } break; default: rte_panic("Invalid hash table type or key size\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < (1 << 24); i++) { struct rte_pipeline_table_entry entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_pipeline_table_entry *entry_ptr; uint8_t key[32]; uint32_t *k32 = (uint32_t *) key; int key_found, status; memset(key, 0, sizeof(key)); k32[0] = rte_be_to_cpu_32(i); status = rte_pipeline_table_entry_add(p, table_id, key, &entry, &key_found, &entry_ptr); if (status < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, status); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif } uint64_t test_hash( void *key, __attribute__((unused)) uint32_t key_size, __attribute__((unused)) uint64_t seed) { uint32_t *k32 = (uint32_t *) key; uint32_t ip_dst = rte_be_to_cpu_32(k32[0]); uint64_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30); return signature; } void app_main_loop_rx_metadata(void) { uint32_t i, j; int ret; RTE_LOG(INFO, USER1, "Core %u is doing RX (with meta-data)\n", rte_lcore_id()); for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { uint16_t n_mbufs; n_mbufs = rte_eth_rx_burst( app.ports[i], 0, app.mbuf_rx.array, app.burst_size_rx_read); if (n_mbufs == 0) continue; for (j = 0; j < n_mbufs; j++) { struct rte_mbuf *m; uint8_t *m_data, *key; struct ipv4_hdr *ip_hdr; struct ipv6_hdr *ipv6_hdr; uint32_t ip_dst; uint8_t *ipv6_dst; uint32_t *signature, *k32; m = app.mbuf_rx.array[j]; m_data = rte_pktmbuf_mtod(m, uint8_t *); signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0); key = RTE_MBUF_METADATA_UINT8_PTR(m, 32); #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { #else if (m->ol_flags & PKT_RX_IPV4_HDR) { #endif ip_hdr = (struct ipv4_hdr *) &m_data[sizeof(struct ether_hdr)]; ip_dst = ip_hdr->dst_addr; k32 = (uint32_t *) key; k32[0] = ip_dst & 0xFFFFFF00; #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { #else } else { #endif ipv6_hdr = (struct ipv6_hdr *) &m_data[sizeof(struct ether_hdr)]; ipv6_dst = ipv6_hdr->dst_addr; memcpy(key, ipv6_dst, 16); #ifdef RTE_NEXT_ABI } else continue; #else } #endif *signature = test_hash(key, 0, 0); } do { ret = rte_ring_sp_enqueue_bulk( app.rings_rx[i], (void **) app.mbuf_rx.array, n_mbufs); } while (ret < 0); } } ================================================ FILE: app/test-pipeline/pipeline_lpm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" void app_main_loop_worker_pipeline_lpm(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with " "LPM table)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ { struct rte_table_lpm_params table_lpm_params = { .n_rules = 1 << 24, .entry_unique_size = sizeof(struct rte_pipeline_table_entry), .offset = 32, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_lpm_ops, .arg_create = &table_lpm_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the LPM table\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_table_lpm_key key = { .ip = i << (24 - __builtin_popcount(app.n_ports - 1)), .depth = 8 + __builtin_popcount(app.n_ports - 1), }; struct rte_pipeline_table_entry *entry_ptr; int key_found, status; printf("Adding rule to LPM table (IPv4 destination = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu8 " => port out = %" PRIu32 ")\n", (key.ip & 0xFF000000) >> 24, (key.ip & 0x00FF0000) >> 16, (key.ip & 0x0000FF00) >> 8, key.ip & 0x000000FF, key.depth, i); status = rte_pipeline_table_entry_add(p, table_id, &key, &entry, &key_found, &entry_ptr); if (status < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, status); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif } ================================================ FILE: app/test-pipeline/pipeline_lpm_ipv6.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" void app_main_loop_worker_pipeline_lpm_ipv6(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with IPv6 LPM table)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ { struct rte_table_lpm_ipv6_params table_lpm_ipv6_params = { .n_rules = 1 << 24, .number_tbl8s = 1 << 21, .entry_unique_size = sizeof(struct rte_pipeline_table_entry), .offset = 32, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_lpm_ipv6_ops, .arg_create = &table_lpm_ipv6_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the IPv6 LPM table\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_table_lpm_ipv6_key key; struct rte_pipeline_table_entry *entry_ptr; uint32_t ip; int key_found, status; key.depth = 8 + __builtin_popcount(app.n_ports - 1); ip = rte_bswap32(i << (24 - __builtin_popcount(app.n_ports - 1))); memcpy(key.ip, &ip, sizeof(uint32_t)); printf("Adding rule to IPv6 LPM table (IPv6 destination = " "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:" "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%u => " "port out = %u)\n", key.ip[0], key.ip[1], key.ip[2], key.ip[3], key.ip[4], key.ip[5], key.ip[6], key.ip[7], key.ip[8], key.ip[9], key.ip[10], key.ip[11], key.ip[12], key.ip[13], key.ip[14], key.ip[15], key.depth, i); status = rte_pipeline_table_entry_add(p, table_id, &key, &entry, &key_found, &entry_ptr); if (status < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, status); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif } ================================================ FILE: app/test-pipeline/pipeline_stub.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "main.h" void app_main_loop_worker_pipeline_stub(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id[APP_MAX_PORTS]; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with stub " "tables)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_params table_params = { .ops = &rte_table_stub_ops, .arg_create = NULL, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id[i])) rte_panic("Unable to configure table %u\n", i); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id[i])) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id[i]); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i ^ 1]}, }; struct rte_pipeline_table_entry *default_entry_ptr; if (rte_pipeline_table_default_entry_add(p, table_id[i], &entry, &default_entry_ptr)) rte_panic("Unable to add default entry to table %u\n", table_id[i]); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif } ================================================ FILE: app/test-pipeline/runtime.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" void app_main_loop_rx(void) { uint32_t i; int ret; RTE_LOG(INFO, USER1, "Core %u is doing RX\n", rte_lcore_id()); for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { uint16_t n_mbufs; n_mbufs = rte_eth_rx_burst( app.ports[i], 0, app.mbuf_rx.array, app.burst_size_rx_read); if (n_mbufs == 0) continue; do { ret = rte_ring_sp_enqueue_bulk( app.rings_rx[i], (void **) app.mbuf_rx.array, n_mbufs); } while (ret < 0); } } void app_main_loop_worker(void) { struct app_mbuf_array *worker_mbuf; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (no pipeline)\n", rte_lcore_id()); worker_mbuf = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array), RTE_CACHE_LINE_SIZE, rte_socket_id()); if (worker_mbuf == NULL) rte_panic("Worker thread: cannot allocate buffer space\n"); for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { int ret; ret = rte_ring_sc_dequeue_bulk( app.rings_rx[i], (void **) worker_mbuf->array, app.burst_size_worker_read); if (ret == -ENOENT) continue; do { ret = rte_ring_sp_enqueue_bulk( app.rings_tx[i ^ 1], (void **) worker_mbuf->array, app.burst_size_worker_write); } while (ret < 0); } } void app_main_loop_tx(void) { uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing TX\n", rte_lcore_id()); for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { uint16_t n_mbufs, n_pkts; int ret; n_mbufs = app.mbuf_tx[i].n_mbufs; ret = rte_ring_sc_dequeue_bulk( app.rings_tx[i], (void **) &app.mbuf_tx[i].array[n_mbufs], app.burst_size_tx_read); if (ret == -ENOENT) continue; n_mbufs += app.burst_size_tx_read; if (n_mbufs < app.burst_size_tx_write) { app.mbuf_tx[i].n_mbufs = n_mbufs; continue; } n_pkts = rte_eth_tx_burst( app.ports[i], 0, app.mbuf_tx[i].array, n_mbufs); if (n_pkts < n_mbufs) { uint16_t k; for (k = n_pkts; k < n_mbufs; k++) { struct rte_mbuf *pkt_to_free; pkt_to_free = app.mbuf_tx[i].array[k]; rte_pktmbuf_free(pkt_to_free); } } app.mbuf_tx[i].n_mbufs = 0; } } ================================================ FILE: app/test-pmd/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_TEST_PMD),y) # # library name # APP = testpmd CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # # all source are stored in SRCS-y # SRCS-y := testpmd.c SRCS-y += parameters.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c SRCS-y += config.c SRCS-y += iofwd.c SRCS-y += macfwd.c SRCS-y += macfwd-retry.c SRCS-y += macswap.c SRCS-y += flowgen.c SRCS-y += rxonly.c SRCS-y += txonly.c SRCS-y += csumonly.c SRCS-y += icmpecho.c SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c SRCS-y += mempool_anon.c ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) CFLAGS_mempool_anon.o := -D_GNU_SOURCE endif CFLAGS_cmdline.o := -D_GNU_SOURCE # this application needs libraries first DEPDIRS-y += lib drivers include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: app/test-pmd/cmdline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #ifndef __linux__ #ifndef __FreeBSD__ #include #else #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_PMD_BOND #include #endif #include "testpmd.h" static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue); #ifdef RTE_NIC_BYPASS uint8_t bypass_is_supported(portid_t port_id); #endif /* *** Help command with introduction. *** */ struct cmd_help_brief_result { cmdline_fixed_string_t help; }; static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf( cl, "\n" "Help is available for the following sections:\n\n" " help control : Start and stop forwarding.\n" " help display : Displaying port, stats and config " "information.\n" " help config : Configuration information.\n" " help ports : Configuring ports.\n" " help registers : Reading and setting port registers.\n" " help filters : Filters configuration help.\n" " help all : All of the above sections.\n\n" ); } cmdline_parse_token_string_t cmd_help_brief_help = TOKEN_STRING_INITIALIZER(struct cmd_help_brief_result, help, "help"); cmdline_parse_inst_t cmd_help_brief = { .f = cmd_help_brief_parsed, .data = NULL, .help_str = "show help", .tokens = { (void *)&cmd_help_brief_help, NULL, }, }; /* *** Help command with help sections. *** */ struct cmd_help_long_result { cmdline_fixed_string_t help; cmdline_fixed_string_t section; }; static void cmd_help_long_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { int show_all = 0; struct cmd_help_long_result *res = parsed_result; if (!strcmp(res->section, "all")) show_all = 1; if (show_all || !strcmp(res->section, "control")) { cmdline_printf( cl, "\n" "Control forwarding:\n" "-------------------\n\n" "start\n" " Start packet forwarding with current configuration.\n\n" "start tx_first\n" " Start packet forwarding with current config" " after sending one burst of packets.\n\n" "stop\n" " Stop packet forwarding, and display accumulated" " statistics.\n\n" "quit\n" " Quit to prompt.\n\n" ); } if (show_all || !strcmp(res->section, "display")) { cmdline_printf( cl, "\n" "Display:\n" "--------\n\n" "show port (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n" " Display information for port_id, or all.\n\n" "show port X rss reta (size) (mask0,mask1,...)\n" " Display the rss redirection table entry indicated" " by masks on port X. size is used to indicate the" " hardware supported reta size\n\n" "show port rss-hash [key]\n" " Display the RSS hash functions and RSS hash key" " of port X\n\n" "clear port (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n" " Clear information for port_id, or all.\n\n" "show config (rxtx|cores|fwd)\n" " Display the given configuration.\n\n" "read rxd (port_id) (queue_id) (rxd_id)\n" " Display an RX descriptor of a port RX queue.\n\n" "read txd (port_id) (queue_id) (txd_id)\n" " Display a TX descriptor of a port TX queue.\n\n" ); } if (show_all || !strcmp(res->section, "config")) { cmdline_printf( cl, "\n" "Configuration:\n" "--------------\n" "Configuration changes only become active when" " forwarding is started/restarted.\n\n" "set default\n" " Reset forwarding to the default configuration.\n\n" "set verbose (level)\n" " Set the debug verbosity level X.\n\n" "set nbport (num)\n" " Set number of ports.\n\n" "set nbcore (num)\n" " Set number of cores.\n\n" "set coremask (mask)\n" " Set the forwarding cores hexadecimal mask.\n\n" "set portmask (mask)\n" " Set the forwarding ports hexadecimal mask.\n\n" "set burst (num)\n" " Set number of packets per burst.\n\n" "set burst tx delay (microseconds) retry (num)\n" " Set the transmit delay time and number of retries" " in mac_retry forwarding mode.\n\n" "set txpkts (x[,y]*)\n" " Set the length of each segment of TXONLY" " packets.\n\n" "set corelist (x[,y]*)\n" " Set the list of forwarding cores.\n\n" "set portlist (x[,y]*)\n" " Set the list of forwarding ports.\n\n" "vlan set strip (on|off) (port_id)\n" " Set the VLAN strip on a port.\n\n" "vlan set stripq (on|off) (port_id,queue_id)\n" " Set the VLAN strip for a queue on a port.\n\n" "vlan set filter (on|off) (port_id)\n" " Set the VLAN filter on a port.\n\n" "vlan set qinq (on|off) (port_id)\n" " Set the VLAN QinQ (extended queue in queue)" " on a port.\n\n" "vlan set tpid (value) (port_id)\n" " Set the outer VLAN TPID for Packet Filtering on" " a port\n\n" "rx_vlan add (vlan_id|all) (port_id)\n" " Add a vlan_id, or all identifiers, to the set" " of VLAN identifiers filtered by port_id.\n\n" "rx_vlan rm (vlan_id|all) (port_id)\n" " Remove a vlan_id, or all identifiers, from the set" " of VLAN identifiers filtered by port_id.\n\n" "rx_vlan add (vlan_id) port (port_id) vf (vf_mask)\n" " Add a vlan_id, to the set of VLAN identifiers" "filtered for VF(s) from port_id.\n\n" "rx_vlan rm (vlan_id) port (port_id) vf (vf_mask)\n" " Remove a vlan_id, to the set of VLAN identifiers" "filtered for VF(s) from port_id.\n\n" "rx_vlan set tpid (value) (port_id)\n" " Set the outer VLAN TPID for Packet Filtering on" " a port\n\n" "tunnel_filter add (port_id) (outer_mac) (inner_mac) (ip_addr) " "(inner_vlan) (vxlan|nvgre) (filter_type) (tenant_id) (queue_id)\n" " add a tunnel filter of a port.\n\n" "tunnel_filter rm (port_id) (outer_mac) (inner_mac) (ip_addr) " "(inner_vlan) (vxlan|nvgre) (filter_type) (tenant_id) (queue_id)\n" " remove a tunnel filter of a port.\n\n" "rx_vxlan_port add (udp_port) (port_id)\n" " Add an UDP port for VXLAN packet filter on a port\n\n" "rx_vxlan_port rm (udp_port) (port_id)\n" " Remove an UDP port for VXLAN packet filter on a port\n\n" "tx_vlan set (port_id) vlan_id[, vlan_id_outer]\n" " Set hardware insertion of VLAN IDs (single or double VLAN " "depends on the number of VLAN IDs) in packets sent on a port.\n\n" "tx_vlan set pvid port_id vlan_id (on|off)\n" " Set port based TX VLAN insertion.\n\n" "tx_vlan reset (port_id)\n" " Disable hardware insertion of a VLAN header in" " packets sent on a port.\n\n" "csum set (ip|udp|tcp|sctp|outer-ip) (hw|sw) (port_id)\n" " Select hardware or software calculation of the" " checksum when transmitting a packet using the" " csum forward engine.\n" " ip|udp|tcp|sctp always concern the inner layer.\n" " outer-ip concerns the outer IP layer in" " case the packet is recognized as a tunnel packet by" " the forward engine (vxlan, gre and ipip are supported)\n" " Please check the NIC datasheet for HW limits.\n\n" "csum parse-tunnel (on|off) (tx_port_id)\n" " If disabled, treat tunnel packets as non-tunneled" " packets (treat inner headers as payload). The port\n" " argument is the port used for TX in csum forward" " engine.\n\n" "csum show (port_id)\n" " Display tx checksum offload configuration\n\n" "tso set (segsize) (portid)\n" " Enable TCP Segmentation Offload in csum forward" " engine.\n" " Please check the NIC datasheet for HW limits.\n\n" "tso show (portid)" " Display the status of TCP Segmentation Offload.\n\n" "set fwd (%s)\n" " Set packet forwarding mode.\n\n" "mac_addr add (port_id) (XX:XX:XX:XX:XX:XX)\n" " Add a MAC address on port_id.\n\n" "mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)\n" " Remove a MAC address from port_id.\n\n" "mac_addr add port (port_id) vf (vf_id) (mac_address)\n" " Add a MAC address for a VF on the port.\n\n" "set port (port_id) uta (mac_address|all) (on|off)\n" " Add/Remove a or all unicast hash filter(s)" "from port X.\n\n" "set promisc (port_id|all) (on|off)\n" " Set the promiscuous mode on port_id, or all.\n\n" "set allmulti (port_id|all) (on|off)\n" " Set the allmulti mode on port_id, or all.\n\n" "set flow_ctrl rx (on|off) tx (on|off) (high_water)" " (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd" " (on|off) autoneg (on|off) (port_id)\n" "set flow_ctrl rx (on|off) (portid)\n" "set flow_ctrl tx (on|off) (portid)\n" "set flow_ctrl high_water (high_water) (portid)\n" "set flow_ctrl low_water (low_water) (portid)\n" "set flow_ctrl pause_time (pause_time) (portid)\n" "set flow_ctrl send_xon (send_xon) (portid)\n" "set flow_ctrl mac_ctrl_frame_fwd (on|off) (portid)\n" "set flow_ctrl autoneg (on|off) (port_id)\n" " Set the link flow control parameter on a port.\n\n" "set pfc_ctrl rx (on|off) tx (on|off) (high_water)" " (low_water) (pause_time) (priority) (port_id)\n" " Set the priority flow control parameter on a" " port.\n\n" "set stat_qmap (tx|rx) (port_id) (queue_id) (qmapping)\n" " Set statistics mapping (qmapping 0..15) for RX/TX" " queue on port.\n" " e.g., 'set stat_qmap rx 0 2 5' sets rx queue 2" " on port 0 to mapping 5.\n\n" "set port (port_id) vf (vf_id) rx|tx on|off\n" " Enable/Disable a VF receive/tranmit from a port\n\n" "set port (port_id) vf (vf_id) (mac_addr)" " (exact-mac#exact-mac-vlan#hashmac|hashmac-vlan) on|off\n" " Add/Remove unicast or multicast MAC addr filter" " for a VF.\n\n" "set port (port_id) vf (vf_id) rxmode (AUPE|ROPE|BAM" "|MPE) (on|off)\n" " AUPE:accepts untagged VLAN;" "ROPE:accept unicast hash\n\n" " BAM:accepts broadcast packets;" "MPE:accepts all multicast packets\n\n" " Enable/Disable a VF receive mode of a port\n\n" "set port (port_id) queue (queue_id) rate (rate_num)\n" " Set rate limit for a queue of a port\n\n" "set port (port_id) vf (vf_id) rate (rate_num) " "queue_mask (queue_mask_value)\n" " Set rate limit for queues in VF of a port\n\n" "set port (port_id) mirror-rule (rule_id)" " (pool-mirror-up|pool-mirror-down|vlan-mirror)" " (poolmask|vlanid[,vlanid]*) dst-pool (pool_id) (on|off)\n" " Set pool or vlan type mirror rule on a port.\n" " e.g., 'set port 0 mirror-rule 0 vlan-mirror 0,1" " dst-pool 0 on' enable mirror traffic with vlan 0,1" " to pool 0.\n\n" "set port (port_id) mirror-rule (rule_id)" " (uplink-mirror|downlink-mirror) dst-pool" " (pool_id) (on|off)\n" " Set uplink or downlink type mirror rule on a port.\n" " e.g., 'set port 0 mirror-rule 0 uplink-mirror dst-pool" " 0 on' enable mirror income traffic to pool 0.\n\n" "reset port (port_id) mirror-rule (rule_id)\n" " Reset a mirror rule.\n\n" "set flush_rx (on|off)\n" " Flush (default) or don't flush RX streams before" " forwarding. Mainly used with PCAP drivers.\n\n" #ifdef RTE_NIC_BYPASS "set bypass mode (normal|bypass|isolate) (port_id)\n" " Set the bypass mode for the lowest port on bypass enabled" " NIC.\n\n" "set bypass event (timeout|os_on|os_off|power_on|power_off) " "mode (normal|bypass|isolate) (port_id)\n" " Set the event required to initiate specified bypass mode for" " the lowest port on a bypass enabled NIC where:\n" " timeout = enable bypass after watchdog timeout.\n" " os_on = enable bypass when OS/board is powered on.\n" " os_off = enable bypass when OS/board is powered off.\n" " power_on = enable bypass when power supply is turned on.\n" " power_off = enable bypass when power supply is turned off." "\n\n" "set bypass timeout (0|1.5|2|3|4|8|16|32)\n" " Set the bypass watchdog timeout to 'n' seconds" " where 0 = instant.\n\n" "show bypass config (port_id)\n" " Show the bypass configuration for a bypass enabled NIC" " using the lowest port on the NIC.\n\n" #endif #ifdef RTE_LIBRTE_PMD_BOND "create bonded device (mode) (socket)\n" " Create a new bonded device with specific bonding mode and socket.\n\n" "add bonding slave (slave_id) (port_id)\n" " Add a slave device to a bonded device.\n\n" "remove bonding slave (slave_id) (port_id)\n" " Remove a slave device from a bonded device.\n\n" "set bonding mode (value) (port_id)\n" " Set the bonding mode on a bonded device.\n\n" "set bonding primary (slave_id) (port_id)\n" " Set the primary slave for a bonded device.\n\n" "show bonding config (port_id)\n" " Show the bonding config for port_id.\n\n" "set bonding mac_addr (port_id) (address)\n" " Set the MAC address of a bonded device.\n\n" "set bonding xmit_balance_policy (port_id) (l2|l23|l34)\n" " Set the transmit balance policy for bonded device running in balance mode.\n\n" "set bonding mon_period (port_id) (value)\n" " Set the bonding link status monitoring polling period in ms.\n\n" #endif "set link-up port (port_id)\n" " Set link up for a port.\n\n" "set link-down port (port_id)\n" " Set link down for a port.\n\n" , list_pkt_forwarding_modes() ); } if (show_all || !strcmp(res->section, "ports")) { cmdline_printf( cl, "\n" "Port Operations:\n" "----------------\n\n" "port start (port_id|all)\n" " Start all ports or port_id.\n\n" "port stop (port_id|all)\n" " Stop all ports or port_id.\n\n" "port close (port_id|all)\n" " Close all ports or port_id.\n\n" "port attach (ident)\n" " Attach physical or virtual dev by pci address or virtual device name\n\n" "port detach (port_id)\n" " Detach physical or virtual dev by port_id\n\n" "port config (port_id|all)" " speed (10|100|1000|10000|40000|auto)" " duplex (half|full|auto)\n" " Set speed and duplex for all ports or port_id\n\n" "port config all (rxq|txq|rxd|txd) (value)\n" " Set number for rxq/txq/rxd/txd.\n\n" "port config all max-pkt-len (value)\n" " Set the max packet length.\n\n" "port config all (crc-strip|rx-cksum|hw-vlan|hw-vlan-filter|" "hw-vlan-strip|hw-vlan-extend|drop-en)" " (on|off)\n" " Set crc-strip/rx-checksum/hardware-vlan/drop_en" " for ports.\n\n" "port config all rss (all|ip|tcp|udp|sctp|ether|none)\n" " Set the RSS mode.\n\n" "port config port-id rss reta (hash,queue)[,(hash,queue)]\n" " Set the RSS redirection table.\n\n" "port config (port_id) dcb vt (on|off) (traffic_class)" " pfc (on|off)\n" " Set the DCB mode.\n\n" "port config all burst (value)\n" " Set the number of packets per burst.\n\n" "port config all (txpt|txht|txwt|rxpt|rxht|rxwt)" " (value)\n" " Set the ring prefetch/host/writeback threshold" " for tx/rx queue.\n\n" "port config all (txfreet|txrst|rxfreet) (value)\n" " Set free threshold for rx/tx, or set" " tx rs bit threshold.\n\n" "port config mtu X value\n" " Set the MTU of port X to a given value\n\n" "port (port_id) (rxq|txq) (queue_id) (start|stop)\n" " Start/stop a rx/tx queue of port X. Only take effect" " when port X is started\n" ); } if (show_all || !strcmp(res->section, "registers")) { cmdline_printf( cl, "\n" "Registers:\n" "----------\n\n" "read reg (port_id) (address)\n" " Display value of a port register.\n\n" "read regfield (port_id) (address) (bit_x) (bit_y)\n" " Display a port register bit field.\n\n" "read regbit (port_id) (address) (bit_x)\n" " Display a single port register bit.\n\n" "write reg (port_id) (address) (value)\n" " Set value of a port register.\n\n" "write regfield (port_id) (address) (bit_x) (bit_y)" " (value)\n" " Set bit field of a port register.\n\n" "write regbit (port_id) (address) (bit_x) (value)\n" " Set single bit value of a port register.\n\n" ); } if (show_all || !strcmp(res->section, "filters")) { cmdline_printf( cl, "\n" "filters:\n" "--------\n\n" "ethertype_filter (port_id) (add|del)" " (mac_addr|mac_ignr) (mac_address) ethertype" " (ether_type) (drop|fwd) queue (queue_id)\n" " Add/Del an ethertype filter.\n\n" "2tuple_filter (port_id) (add|del)" " dst_port (dst_port_value) protocol (protocol_value)" " mask (mask_value) tcp_flags (tcp_flags_value)" " priority (prio_value) queue (queue_id)\n" " Add/Del a 2tuple filter.\n\n" "5tuple_filter (port_id) (add|del)" " dst_ip (dst_address) src_ip (src_address)" " dst_port (dst_port_value) src_port (src_port_value)" " protocol (protocol_value)" " mask (mask_value) tcp_flags (tcp_flags_value)" " priority (prio_value) queue (queue_id)\n" " Add/Del a 5tuple filter.\n\n" "syn_filter (port_id) (add|del) priority (high|low) queue (queue_id)" " Add/Del syn filter.\n\n" "flex_filter (port_id) (add|del) len (len_value)" " bytes (bytes_value) mask (mask_value)" " priority (prio_value) queue (queue_id)\n" " Add/Del a flex filter.\n\n" "flow_director_filter (port_id) (add|del|update)" " flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag)" " src (src_ip_address) dst (dst_ip_address)" " vlan (vlan_value) flexbytes (flexbytes_value)" " (drop|fwd) queue (queue_id) fd_id (fd_id_value)\n" " Add/Del an IP type flow director filter.\n\n" "flow_director_filter (port_id) (add|del|update)" " flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp)" " src (src_ip_address) (src_port)" " dst (dst_ip_address) (dst_port)" " vlan (vlan_value) flexbytes (flexbytes_value)" " (drop|fwd) queue (queue_id) fd_id (fd_id_value)\n" " Add/Del an UDP/TCP type flow director filter.\n\n" "flow_director_filter (port_id) (add|del|update)" " flow (ipv4-sctp|ipv6-sctp)" " src (src_ip_address) (src_port)" " dst (dst_ip_address) (dst_port)" " tag (verification_tag) vlan (vlan_value)" " flexbytes (flexbytes_value) (drop|fwd)" " queue (queue_id) fd_id (fd_id_value)\n" " Add/Del a SCTP type flow director filter.\n\n" "flow_director_filter (port_id) (add|del|update)" " flow l2_payload ether (ethertype)" " flexbytes (flexbytes_value) (drop|fwd)" " queue (queue_id) fd_id (fd_id_value)\n" " Add/Del a l2 payload type flow director filter.\n\n" "flush_flow_director (port_id)\n" " Flush all flow director entries of a device.\n\n" "flow_director_mask (port_id) vlan (vlan_value)" " src_mask (ipv4_src) (ipv6_src) (src_port)" " dst_mask (ipv4_dst) (ipv6_dst) (dst_port)\n" " Set flow director mask.\n\n" "flow_director_flex_mask (port_id)" " flow (none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|" "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload|all)" " (mask)\n" " Configure mask of flex payload.\n\n" "flow_director_flex_payload (port_id)" " (raw|l2|l3|l4) (config)\n" " Configure flex payload selection.\n\n" "get_sym_hash_ena_per_port (port_id)\n" " get symmetric hash enable configuration per port.\n\n" "set_sym_hash_ena_per_port (port_id) (enable|disable)\n" " set symmetric hash enable configuration per port" " to enable or disable.\n\n" "get_hash_global_config (port_id)\n" " Get the global configurations of hash filters.\n\n" "set_hash_global_config (port_id) (toeplitz|simple_xor|default)" " (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)" " (enable|disable)\n" " Set the global configurations of hash filters.\n\n" ); } } cmdline_parse_token_string_t cmd_help_long_help = TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, help, "help"); cmdline_parse_token_string_t cmd_help_long_section = TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section, "all#control#display#config#" "ports#registers#filters"); cmdline_parse_inst_t cmd_help_long = { .f = cmd_help_long_parsed, .data = NULL, .help_str = "show help", .tokens = { (void *)&cmd_help_long_help, (void *)&cmd_help_long_section, NULL, }, }; /* *** start/stop/close all ports *** */ struct cmd_operate_port_result { cmdline_fixed_string_t keyword; cmdline_fixed_string_t name; cmdline_fixed_string_t value; }; static void cmd_operate_port_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_operate_port_result *res = parsed_result; if (!strcmp(res->name, "start")) start_port(RTE_PORT_ALL); else if (!strcmp(res->name, "stop")) stop_port(RTE_PORT_ALL); else if (!strcmp(res->name, "close")) close_port(RTE_PORT_ALL); else printf("Unknown parameter\n"); } cmdline_parse_token_string_t cmd_operate_port_all_cmd = TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, keyword, "port"); cmdline_parse_token_string_t cmd_operate_port_all_port = TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name, "start#stop#close"); cmdline_parse_token_string_t cmd_operate_port_all_all = TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value, "all"); cmdline_parse_inst_t cmd_operate_port = { .f = cmd_operate_port_parsed, .data = NULL, .help_str = "port start|stop|close all: start/stop/close all ports", .tokens = { (void *)&cmd_operate_port_all_cmd, (void *)&cmd_operate_port_all_port, (void *)&cmd_operate_port_all_all, NULL, }, }; /* *** start/stop/close specific port *** */ struct cmd_operate_specific_port_result { cmdline_fixed_string_t keyword; cmdline_fixed_string_t name; uint8_t value; }; static void cmd_operate_specific_port_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_operate_specific_port_result *res = parsed_result; if (!strcmp(res->name, "start")) start_port(res->value); else if (!strcmp(res->name, "stop")) stop_port(res->value); else if (!strcmp(res->name, "close")) close_port(res->value); else printf("Unknown parameter\n"); } cmdline_parse_token_string_t cmd_operate_specific_port_cmd = TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result, keyword, "port"); cmdline_parse_token_string_t cmd_operate_specific_port_port = TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result, name, "start#stop#close"); cmdline_parse_token_num_t cmd_operate_specific_port_id = TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result, value, UINT8); cmdline_parse_inst_t cmd_operate_specific_port = { .f = cmd_operate_specific_port_parsed, .data = NULL, .help_str = "port start|stop|close X: start/stop/close port X", .tokens = { (void *)&cmd_operate_specific_port_cmd, (void *)&cmd_operate_specific_port_port, (void *)&cmd_operate_specific_port_id, NULL, }, }; /* *** attach a specified port *** */ struct cmd_operate_attach_port_result { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t identifier; }; static void cmd_operate_attach_port_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_operate_attach_port_result *res = parsed_result; if (!strcmp(res->keyword, "attach")) attach_port(res->identifier); else printf("Unknown parameter\n"); } cmdline_parse_token_string_t cmd_operate_attach_port_port = TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, port, "port"); cmdline_parse_token_string_t cmd_operate_attach_port_keyword = TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, keyword, "attach"); cmdline_parse_token_string_t cmd_operate_attach_port_identifier = TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result, identifier, NULL); cmdline_parse_inst_t cmd_operate_attach_port = { .f = cmd_operate_attach_port_parsed, .data = NULL, .help_str = "port attach identifier, " "identifier: pci address or virtual dev name", .tokens = { (void *)&cmd_operate_attach_port_port, (void *)&cmd_operate_attach_port_keyword, (void *)&cmd_operate_attach_port_identifier, NULL, }, }; /* *** detach a specified port *** */ struct cmd_operate_detach_port_result { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; uint8_t port_id; }; static void cmd_operate_detach_port_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_operate_detach_port_result *res = parsed_result; if (!strcmp(res->keyword, "detach")) detach_port(res->port_id); else printf("Unknown parameter\n"); } cmdline_parse_token_string_t cmd_operate_detach_port_port = TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, port, "port"); cmdline_parse_token_string_t cmd_operate_detach_port_keyword = TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result, keyword, "detach"); cmdline_parse_token_num_t cmd_operate_detach_port_port_id = TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result, port_id, UINT8); cmdline_parse_inst_t cmd_operate_detach_port = { .f = cmd_operate_detach_port_parsed, .data = NULL, .help_str = "port detach port_id", .tokens = { (void *)&cmd_operate_detach_port_port, (void *)&cmd_operate_detach_port_keyword, (void *)&cmd_operate_detach_port_port_id, NULL, }, }; /* *** configure speed for all ports *** */ struct cmd_config_speed_all { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t item1; cmdline_fixed_string_t item2; cmdline_fixed_string_t value1; cmdline_fixed_string_t value2; }; static void cmd_config_speed_all_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_speed_all *res = parsed_result; uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; uint16_t link_duplex = 0; portid_t pid; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->value1, "10")) link_speed = ETH_LINK_SPEED_10; else if (!strcmp(res->value1, "100")) link_speed = ETH_LINK_SPEED_100; else if (!strcmp(res->value1, "1000")) link_speed = ETH_LINK_SPEED_1000; else if (!strcmp(res->value1, "10000")) link_speed = ETH_LINK_SPEED_10G; else if (!strcmp(res->value1, "40000")) link_speed = ETH_LINK_SPEED_40G; else if (!strcmp(res->value1, "auto")) link_speed = ETH_LINK_SPEED_AUTONEG; else { printf("Unknown parameter\n"); return; } if (!strcmp(res->value2, "half")) link_duplex = ETH_LINK_HALF_DUPLEX; else if (!strcmp(res->value2, "full")) link_duplex = ETH_LINK_FULL_DUPLEX; else if (!strcmp(res->value2, "auto")) link_duplex = ETH_LINK_AUTONEG_DUPLEX; else { printf("Unknown parameter\n"); return; } FOREACH_PORT(pid, ports) { ports[pid].dev_conf.link_speed = link_speed; ports[pid].dev_conf.link_duplex = link_duplex; } cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_speed_all_port = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, port, "port"); cmdline_parse_token_string_t cmd_config_speed_all_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, keyword, "config"); cmdline_parse_token_string_t cmd_config_speed_all_all = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, all, "all"); cmdline_parse_token_string_t cmd_config_speed_all_item1 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed"); cmdline_parse_token_string_t cmd_config_speed_all_value1 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1, "10#100#1000#10000#40000#auto"); cmdline_parse_token_string_t cmd_config_speed_all_item2 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex"); cmdline_parse_token_string_t cmd_config_speed_all_value2 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2, "half#full#auto"); cmdline_parse_inst_t cmd_config_speed_all = { .f = cmd_config_speed_all_parsed, .data = NULL, .help_str = "port config all speed 10|100|1000|10000|40000|auto duplex " "half|full|auto", .tokens = { (void *)&cmd_config_speed_all_port, (void *)&cmd_config_speed_all_keyword, (void *)&cmd_config_speed_all_all, (void *)&cmd_config_speed_all_item1, (void *)&cmd_config_speed_all_value1, (void *)&cmd_config_speed_all_item2, (void *)&cmd_config_speed_all_value2, NULL, }, }; /* *** configure speed for specific port *** */ struct cmd_config_speed_specific { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; uint8_t id; cmdline_fixed_string_t item1; cmdline_fixed_string_t item2; cmdline_fixed_string_t value1; cmdline_fixed_string_t value2; }; static void cmd_config_speed_specific_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_speed_specific *res = parsed_result; uint16_t link_speed = ETH_LINK_SPEED_AUTONEG; uint16_t link_duplex = 0; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (port_id_is_invalid(res->id, ENABLED_WARN)) return; if (!strcmp(res->value1, "10")) link_speed = ETH_LINK_SPEED_10; else if (!strcmp(res->value1, "100")) link_speed = ETH_LINK_SPEED_100; else if (!strcmp(res->value1, "1000")) link_speed = ETH_LINK_SPEED_1000; else if (!strcmp(res->value1, "10000")) link_speed = ETH_LINK_SPEED_10000; else if (!strcmp(res->value1, "40000")) link_speed = ETH_LINK_SPEED_40G; else if (!strcmp(res->value1, "auto")) link_speed = ETH_LINK_SPEED_AUTONEG; else { printf("Unknown parameter\n"); return; } if (!strcmp(res->value2, "half")) link_duplex = ETH_LINK_HALF_DUPLEX; else if (!strcmp(res->value2, "full")) link_duplex = ETH_LINK_FULL_DUPLEX; else if (!strcmp(res->value2, "auto")) link_duplex = ETH_LINK_AUTONEG_DUPLEX; else { printf("Unknown parameter\n"); return; } ports[res->id].dev_conf.link_speed = link_speed; ports[res->id].dev_conf.link_duplex = link_duplex; cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_speed_specific_port = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, port, "port"); cmdline_parse_token_string_t cmd_config_speed_specific_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, keyword, "config"); cmdline_parse_token_num_t cmd_config_speed_specific_id = TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, id, UINT8); cmdline_parse_token_string_t cmd_config_speed_specific_item1 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item1, "speed"); cmdline_parse_token_string_t cmd_config_speed_specific_value1 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1, "10#100#1000#10000#40000#auto"); cmdline_parse_token_string_t cmd_config_speed_specific_item2 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2, "duplex"); cmdline_parse_token_string_t cmd_config_speed_specific_value2 = TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2, "half#full#auto"); cmdline_parse_inst_t cmd_config_speed_specific = { .f = cmd_config_speed_specific_parsed, .data = NULL, .help_str = "port config X speed 10|100|1000|10000|40000|auto duplex " "half|full|auto", .tokens = { (void *)&cmd_config_speed_specific_port, (void *)&cmd_config_speed_specific_keyword, (void *)&cmd_config_speed_specific_id, (void *)&cmd_config_speed_specific_item1, (void *)&cmd_config_speed_specific_value1, (void *)&cmd_config_speed_specific_item2, (void *)&cmd_config_speed_specific_value2, NULL, }, }; /* *** configure txq/rxq, txd/rxd *** */ struct cmd_config_rx_tx { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; uint16_t value; }; static void cmd_config_rx_tx_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_rx_tx *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "rxq")) { if (res->value <= 0) { printf("rxq %d invalid - must be > 0\n", res->value); return; } nb_rxq = res->value; } else if (!strcmp(res->name, "txq")) { if (res->value <= 0) { printf("txq %d invalid - must be > 0\n", res->value); return; } nb_txq = res->value; } else if (!strcmp(res->name, "rxd")) { if (res->value <= 0 || res->value > RTE_TEST_RX_DESC_MAX) { printf("rxd %d invalid - must be > 0 && <= %d\n", res->value, RTE_TEST_RX_DESC_MAX); return; } nb_rxd = res->value; } else if (!strcmp(res->name, "txd")) { if (res->value <= 0 || res->value > RTE_TEST_TX_DESC_MAX) { printf("txd %d invalid - must be > 0 && <= %d\n", res->value, RTE_TEST_TX_DESC_MAX); return; } nb_txd = res->value; } else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_rx_tx_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, port, "port"); cmdline_parse_token_string_t cmd_config_rx_tx_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, keyword, "config"); cmdline_parse_token_string_t cmd_config_rx_tx_all = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, all, "all"); cmdline_parse_token_string_t cmd_config_rx_tx_name = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, name, "rxq#txq#rxd#txd"); cmdline_parse_token_num_t cmd_config_rx_tx_value = TOKEN_NUM_INITIALIZER(struct cmd_config_rx_tx, value, UINT16); cmdline_parse_inst_t cmd_config_rx_tx = { .f = cmd_config_rx_tx_parsed, .data = NULL, .help_str = "port config all rxq|txq|rxd|txd value", .tokens = { (void *)&cmd_config_rx_tx_port, (void *)&cmd_config_rx_tx_keyword, (void *)&cmd_config_rx_tx_all, (void *)&cmd_config_rx_tx_name, (void *)&cmd_config_rx_tx_value, NULL, }, }; /* *** config max packet length *** */ struct cmd_config_max_pkt_len_result { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; uint32_t value; }; static void cmd_config_max_pkt_len_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_max_pkt_len_result *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "max-pkt-len")) { if (res->value < ETHER_MIN_LEN) { printf("max-pkt-len can not be less than %d\n", ETHER_MIN_LEN); return; } if (res->value == rx_mode.max_rx_pkt_len) return; rx_mode.max_rx_pkt_len = res->value; if (res->value > ETHER_MAX_LEN) rx_mode.jumbo_frame = 1; else rx_mode.jumbo_frame = 0; } else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_max_pkt_len_port = TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, port, "port"); cmdline_parse_token_string_t cmd_config_max_pkt_len_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, keyword, "config"); cmdline_parse_token_string_t cmd_config_max_pkt_len_all = TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, all, "all"); cmdline_parse_token_string_t cmd_config_max_pkt_len_name = TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, name, "max-pkt-len"); cmdline_parse_token_num_t cmd_config_max_pkt_len_value = TOKEN_NUM_INITIALIZER(struct cmd_config_max_pkt_len_result, value, UINT32); cmdline_parse_inst_t cmd_config_max_pkt_len = { .f = cmd_config_max_pkt_len_parsed, .data = NULL, .help_str = "port config all max-pkt-len value", .tokens = { (void *)&cmd_config_max_pkt_len_port, (void *)&cmd_config_max_pkt_len_keyword, (void *)&cmd_config_max_pkt_len_all, (void *)&cmd_config_max_pkt_len_name, (void *)&cmd_config_max_pkt_len_value, NULL, }, }; /* *** configure port MTU *** */ struct cmd_config_mtu_result { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t mtu; uint8_t port_id; uint16_t value; }; static void cmd_config_mtu_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_mtu_result *res = parsed_result; if (res->value < ETHER_MIN_LEN) { printf("mtu cannot be less than %d\n", ETHER_MIN_LEN); return; } port_mtu_set(res->port_id, res->value); } cmdline_parse_token_string_t cmd_config_mtu_port = TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, port, "port"); cmdline_parse_token_string_t cmd_config_mtu_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword, "config"); cmdline_parse_token_string_t cmd_config_mtu_mtu = TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword, "mtu"); cmdline_parse_token_num_t cmd_config_mtu_port_id = TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, port_id, UINT8); cmdline_parse_token_num_t cmd_config_mtu_value = TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, value, UINT16); cmdline_parse_inst_t cmd_config_mtu = { .f = cmd_config_mtu_parsed, .data = NULL, .help_str = "port config mtu value", .tokens = { (void *)&cmd_config_mtu_port, (void *)&cmd_config_mtu_keyword, (void *)&cmd_config_mtu_mtu, (void *)&cmd_config_mtu_port_id, (void *)&cmd_config_mtu_value, NULL, }, }; /* *** configure rx mode *** */ struct cmd_config_rx_mode_flag { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; cmdline_fixed_string_t value; }; static void cmd_config_rx_mode_flag_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_rx_mode_flag *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "crc-strip")) { if (!strcmp(res->value, "on")) rx_mode.hw_strip_crc = 1; else if (!strcmp(res->value, "off")) rx_mode.hw_strip_crc = 0; else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "rx-cksum")) { if (!strcmp(res->value, "on")) rx_mode.hw_ip_checksum = 1; else if (!strcmp(res->value, "off")) rx_mode.hw_ip_checksum = 0; else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "hw-vlan")) { if (!strcmp(res->value, "on")) { rx_mode.hw_vlan_filter = 1; rx_mode.hw_vlan_strip = 1; } else if (!strcmp(res->value, "off")) { rx_mode.hw_vlan_filter = 0; rx_mode.hw_vlan_strip = 0; } else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "hw-vlan-filter")) { if (!strcmp(res->value, "on")) rx_mode.hw_vlan_filter = 1; else if (!strcmp(res->value, "off")) rx_mode.hw_vlan_filter = 0; else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "hw-vlan-strip")) { if (!strcmp(res->value, "on")) rx_mode.hw_vlan_strip = 1; else if (!strcmp(res->value, "off")) rx_mode.hw_vlan_strip = 0; else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "hw-vlan-extend")) { if (!strcmp(res->value, "on")) rx_mode.hw_vlan_extend = 1; else if (!strcmp(res->value, "off")) rx_mode.hw_vlan_extend = 0; else { printf("Unknown parameter\n"); return; } } else if (!strcmp(res->name, "drop-en")) { if (!strcmp(res->value, "on")) rx_drop_en = 1; else if (!strcmp(res->value, "off")) rx_drop_en = 0; else { printf("Unknown parameter\n"); return; } } else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_rx_mode_flag_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, port, "port"); cmdline_parse_token_string_t cmd_config_rx_mode_flag_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, keyword, "config"); cmdline_parse_token_string_t cmd_config_rx_mode_flag_all = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, all, "all"); cmdline_parse_token_string_t cmd_config_rx_mode_flag_name = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, name, "crc-strip#rx-cksum#hw-vlan#" "hw-vlan-filter#hw-vlan-strip#hw-vlan-extend"); cmdline_parse_token_string_t cmd_config_rx_mode_flag_value = TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, value, "on#off"); cmdline_parse_inst_t cmd_config_rx_mode_flag = { .f = cmd_config_rx_mode_flag_parsed, .data = NULL, .help_str = "port config all crc-strip|rx-cksum|hw-vlan|" "hw-vlan-filter|hw-vlan-strip|hw-vlan-extend on|off", .tokens = { (void *)&cmd_config_rx_mode_flag_port, (void *)&cmd_config_rx_mode_flag_keyword, (void *)&cmd_config_rx_mode_flag_all, (void *)&cmd_config_rx_mode_flag_name, (void *)&cmd_config_rx_mode_flag_value, NULL, }, }; /* *** configure rss *** */ struct cmd_config_rss { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; cmdline_fixed_string_t value; }; static void cmd_config_rss_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_rss *res = parsed_result; struct rte_eth_rss_conf rss_conf; uint8_t i; if (!strcmp(res->value, "all")) rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP | ETH_RSS_SCTP | ETH_RSS_L2_PAYLOAD; else if (!strcmp(res->value, "ip")) rss_conf.rss_hf = ETH_RSS_IP; else if (!strcmp(res->value, "udp")) rss_conf.rss_hf = ETH_RSS_UDP; else if (!strcmp(res->value, "tcp")) rss_conf.rss_hf = ETH_RSS_TCP; else if (!strcmp(res->value, "sctp")) rss_conf.rss_hf = ETH_RSS_SCTP; else if (!strcmp(res->value, "ether")) rss_conf.rss_hf = ETH_RSS_L2_PAYLOAD; else if (!strcmp(res->value, "none")) rss_conf.rss_hf = 0; else { printf("Unknown parameter\n"); return; } rss_conf.rss_key = NULL; for (i = 0; i < rte_eth_dev_count(); i++) rte_eth_dev_rss_hash_update(i, &rss_conf); } cmdline_parse_token_string_t cmd_config_rss_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rss, port, "port"); cmdline_parse_token_string_t cmd_config_rss_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_rss, keyword, "config"); cmdline_parse_token_string_t cmd_config_rss_all = TOKEN_STRING_INITIALIZER(struct cmd_config_rss, all, "all"); cmdline_parse_token_string_t cmd_config_rss_name = TOKEN_STRING_INITIALIZER(struct cmd_config_rss, name, "rss"); cmdline_parse_token_string_t cmd_config_rss_value = TOKEN_STRING_INITIALIZER(struct cmd_config_rss, value, "all#ip#tcp#udp#sctp#ether#none"); cmdline_parse_inst_t cmd_config_rss = { .f = cmd_config_rss_parsed, .data = NULL, .help_str = "port config all rss all|ip|tcp|udp|sctp|ether|none", .tokens = { (void *)&cmd_config_rss_port, (void *)&cmd_config_rss_keyword, (void *)&cmd_config_rss_all, (void *)&cmd_config_rss_name, (void *)&cmd_config_rss_value, NULL, }, }; /* *** configure rss hash key *** */ struct cmd_config_rss_hash_key { cmdline_fixed_string_t port; cmdline_fixed_string_t config; uint8_t port_id; cmdline_fixed_string_t rss_hash_key; cmdline_fixed_string_t key; }; #define RSS_HASH_KEY_LENGTH 40 static uint8_t hexa_digit_to_value(char hexa_digit) { if ((hexa_digit >= '0') && (hexa_digit <= '9')) return (uint8_t) (hexa_digit - '0'); if ((hexa_digit >= 'a') && (hexa_digit <= 'f')) return (uint8_t) ((hexa_digit - 'a') + 10); if ((hexa_digit >= 'A') && (hexa_digit <= 'F')) return (uint8_t) ((hexa_digit - 'A') + 10); /* Invalid hexa digit */ return 0xFF; } static uint8_t parse_and_check_key_hexa_digit(char *key, int idx) { uint8_t hexa_v; hexa_v = hexa_digit_to_value(key[idx]); if (hexa_v == 0xFF) printf("invalid key: character %c at position %d is not a " "valid hexa digit\n", key[idx], idx); return hexa_v; } static void cmd_config_rss_hash_key_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_rss_hash_key *res = parsed_result; uint8_t hash_key[RSS_HASH_KEY_LENGTH]; uint8_t xdgt0; uint8_t xdgt1; int i; /* Check the length of the RSS hash key */ if (strlen(res->key) != (RSS_HASH_KEY_LENGTH * 2)) { printf("key length: %d invalid - key must be a string of %d" "hexa-decimal numbers\n", (int) strlen(res->key), RSS_HASH_KEY_LENGTH * 2); return; } /* Translate RSS hash key into binary representation */ for (i = 0; i < RSS_HASH_KEY_LENGTH; i++) { xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2)); if (xdgt0 == 0xFF) return; xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1); if (xdgt1 == 0xFF) return; hash_key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1); } port_rss_hash_key_update(res->port_id, hash_key); } cmdline_parse_token_string_t cmd_config_rss_hash_key_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, port, "port"); cmdline_parse_token_string_t cmd_config_rss_hash_key_config = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, config, "config"); cmdline_parse_token_num_t cmd_config_rss_hash_key_port_id = TOKEN_NUM_INITIALIZER(struct cmd_config_rss_hash_key, port_id, UINT8); cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_hash_key = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, rss_hash_key, "rss-hash-key"); cmdline_parse_token_string_t cmd_config_rss_hash_key_value = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, key, NULL); cmdline_parse_inst_t cmd_config_rss_hash_key = { .f = cmd_config_rss_hash_key_parsed, .data = NULL, .help_str = "port config X rss-hash-key 80 hexa digits", .tokens = { (void *)&cmd_config_rss_hash_key_port, (void *)&cmd_config_rss_hash_key_config, (void *)&cmd_config_rss_hash_key_port_id, (void *)&cmd_config_rss_hash_key_rss_hash_key, (void *)&cmd_config_rss_hash_key_value, NULL, }, }; /* *** configure port rxq/txq start/stop *** */ struct cmd_config_rxtx_queue { cmdline_fixed_string_t port; uint8_t portid; cmdline_fixed_string_t rxtxq; uint16_t qid; cmdline_fixed_string_t opname; }; static void cmd_config_rxtx_queue_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_rxtx_queue *res = parsed_result; uint8_t isrx; uint8_t isstart; int ret = 0; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } if (port_id_is_invalid(res->portid, ENABLED_WARN)) return; if (port_is_started(res->portid) != 1) { printf("Please start port %u first\n", res->portid); return; } if (!strcmp(res->rxtxq, "rxq")) isrx = 1; else if (!strcmp(res->rxtxq, "txq")) isrx = 0; else { printf("Unknown parameter\n"); return; } if (isrx && rx_queue_id_is_invalid(res->qid)) return; else if (!isrx && tx_queue_id_is_invalid(res->qid)) return; if (!strcmp(res->opname, "start")) isstart = 1; else if (!strcmp(res->opname, "stop")) isstart = 0; else { printf("Unknown parameter\n"); return; } if (isstart && isrx) ret = rte_eth_dev_rx_queue_start(res->portid, res->qid); else if (!isstart && isrx) ret = rte_eth_dev_rx_queue_stop(res->portid, res->qid); else if (isstart && !isrx) ret = rte_eth_dev_tx_queue_start(res->portid, res->qid); else ret = rte_eth_dev_tx_queue_stop(res->portid, res->qid); if (ret == -ENOTSUP) printf("Function not supported in PMD driver\n"); } cmdline_parse_token_string_t cmd_config_rxtx_queue_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, port, "port"); cmdline_parse_token_num_t cmd_config_rxtx_queue_portid = TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, portid, UINT8); cmdline_parse_token_string_t cmd_config_rxtx_queue_rxtxq = TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, rxtxq, "rxq#txq"); cmdline_parse_token_num_t cmd_config_rxtx_queue_qid = TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, qid, UINT16); cmdline_parse_token_string_t cmd_config_rxtx_queue_opname = TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, opname, "start#stop"); cmdline_parse_inst_t cmd_config_rxtx_queue = { .f = cmd_config_rxtx_queue_parsed, .data = NULL, .help_str = "port X rxq|txq ID start|stop", .tokens = { (void *)&cmd_config_speed_all_port, (void *)&cmd_config_rxtx_queue_portid, (void *)&cmd_config_rxtx_queue_rxtxq, (void *)&cmd_config_rxtx_queue_qid, (void *)&cmd_config_rxtx_queue_opname, NULL, }, }; /* *** Configure RSS RETA *** */ struct cmd_config_rss_reta { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; uint8_t port_id; cmdline_fixed_string_t name; cmdline_fixed_string_t list_name; cmdline_fixed_string_t list_of_items; }; static int parse_reta_config(const char *str, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t nb_entries) { int i; unsigned size; uint16_t hash_index, idx, shift; uint8_t nb_queue; char s[256]; const char *p, *p0 = str; char *end; enum fieldnames { FLD_HASH_INDEX = 0, FLD_QUEUE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 65535) return -1; } hash_index = (uint16_t)int_fld[FLD_HASH_INDEX]; nb_queue = (uint8_t)int_fld[FLD_QUEUE]; if (hash_index >= nb_entries) { printf("Invalid RETA hash index=%d\n", hash_index); return -1; } idx = hash_index / RTE_RETA_GROUP_SIZE; shift = hash_index % RTE_RETA_GROUP_SIZE; reta_conf[idx].mask |= (1ULL << shift); reta_conf[idx].reta[shift] = nb_queue; } return 0; } static void cmd_set_rss_reta_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret; struct rte_eth_dev_info dev_info; struct rte_eth_rss_reta_entry64 reta_conf[8]; struct cmd_config_rss_reta *res = parsed_result; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(res->port_id, &dev_info); if (dev_info.reta_size == 0) { printf("Redirection table size is 0 which is " "invalid for RSS\n"); return; } else printf("The reta size of port %d is %u\n", res->port_id, dev_info.reta_size); if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) { printf("Currently do not support more than %u entries of " "redirection table\n", ETH_RSS_RETA_SIZE_512); return; } memset(reta_conf, 0, sizeof(reta_conf)); if (!strcmp(res->list_name, "reta")) { if (parse_reta_config(res->list_of_items, reta_conf, dev_info.reta_size)) { printf("Invalid RSS Redirection Table " "config entered\n"); return; } ret = rte_eth_dev_rss_reta_update(res->port_id, reta_conf, dev_info.reta_size); if (ret != 0) printf("Bad redirection table parameter, " "return code = %d \n", ret); } } cmdline_parse_token_string_t cmd_config_rss_reta_port = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, port, "port"); cmdline_parse_token_string_t cmd_config_rss_reta_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, keyword, "config"); cmdline_parse_token_num_t cmd_config_rss_reta_port_id = TOKEN_NUM_INITIALIZER(struct cmd_config_rss_reta, port_id, UINT8); cmdline_parse_token_string_t cmd_config_rss_reta_name = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, name, "rss"); cmdline_parse_token_string_t cmd_config_rss_reta_list_name = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_name, "reta"); cmdline_parse_token_string_t cmd_config_rss_reta_list_of_items = TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_of_items, NULL); cmdline_parse_inst_t cmd_config_rss_reta = { .f = cmd_set_rss_reta_parsed, .data = NULL, .help_str = "port config X rss reta (hash,queue)[,(hash,queue)]", .tokens = { (void *)&cmd_config_rss_reta_port, (void *)&cmd_config_rss_reta_keyword, (void *)&cmd_config_rss_reta_port_id, (void *)&cmd_config_rss_reta_name, (void *)&cmd_config_rss_reta_list_name, (void *)&cmd_config_rss_reta_list_of_items, NULL, }, }; /* *** SHOW PORT RETA INFO *** */ struct cmd_showport_reta { cmdline_fixed_string_t show; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t rss; cmdline_fixed_string_t reta; uint16_t size; cmdline_fixed_string_t list_of_items; }; static int showport_parse_reta_config(struct rte_eth_rss_reta_entry64 *conf, uint16_t nb_entries, char *str) { uint32_t size; const char *p, *p0 = str; char s[256]; char *end; char *str_fld[8]; uint16_t i, num = nb_entries / RTE_RETA_GROUP_SIZE; int ret; p = strchr(p0, '('); if (p == NULL) return -1; p++; p0 = strchr(p, ')'); if (p0 == NULL) return -1; size = p0 - p; if (size >= sizeof(s)) { printf("The string size exceeds the internal buffer size\n"); return -1; } snprintf(s, sizeof(s), "%.*s", size, p); ret = rte_strsplit(s, sizeof(s), str_fld, num, ','); if (ret <= 0 || ret != num) { printf("The bits of masks do not match the number of " "reta entries: %u\n", num); return -1; } for (i = 0; i < ret; i++) conf[i].mask = (uint64_t)strtoul(str_fld[i], &end, 0); return 0; } static void cmd_showport_reta_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_showport_reta *res = parsed_result; struct rte_eth_rss_reta_entry64 reta_conf[8]; struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(res->port_id, &dev_info); if (dev_info.reta_size == 0 || res->size != dev_info.reta_size || res->size > ETH_RSS_RETA_SIZE_512) { printf("Invalid redirection table size: %u\n", res->size); return; } memset(reta_conf, 0, sizeof(reta_conf)); if (showport_parse_reta_config(reta_conf, res->size, res->list_of_items) < 0) { printf("Invalid string: %s for reta masks\n", res->list_of_items); return; } port_rss_reta_info(res->port_id, reta_conf, res->size); } cmdline_parse_token_string_t cmd_showport_reta_show = TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, show, "show"); cmdline_parse_token_string_t cmd_showport_reta_port = TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, port, "port"); cmdline_parse_token_num_t cmd_showport_reta_port_id = TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, port_id, UINT8); cmdline_parse_token_string_t cmd_showport_reta_rss = TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, rss, "rss"); cmdline_parse_token_string_t cmd_showport_reta_reta = TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, reta, "reta"); cmdline_parse_token_num_t cmd_showport_reta_size = TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, size, UINT16); cmdline_parse_token_string_t cmd_showport_reta_list_of_items = TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, list_of_items, NULL); cmdline_parse_inst_t cmd_showport_reta = { .f = cmd_showport_reta_parsed, .data = NULL, .help_str = "show port X rss reta (size) (mask0,mask1,...)", .tokens = { (void *)&cmd_showport_reta_show, (void *)&cmd_showport_reta_port, (void *)&cmd_showport_reta_port_id, (void *)&cmd_showport_reta_rss, (void *)&cmd_showport_reta_reta, (void *)&cmd_showport_reta_size, (void *)&cmd_showport_reta_list_of_items, NULL, }, }; /* *** Show RSS hash configuration *** */ struct cmd_showport_rss_hash { cmdline_fixed_string_t show; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t rss_hash; cmdline_fixed_string_t key; /* optional argument */ }; static void cmd_showport_rss_hash_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *show_rss_key) { struct cmd_showport_rss_hash *res = parsed_result; port_rss_hash_conf_show(res->port_id, show_rss_key != NULL); } cmdline_parse_token_string_t cmd_showport_rss_hash_show = TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, show, "show"); cmdline_parse_token_string_t cmd_showport_rss_hash_port = TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, port, "port"); cmdline_parse_token_num_t cmd_showport_rss_hash_port_id = TOKEN_NUM_INITIALIZER(struct cmd_showport_rss_hash, port_id, UINT8); cmdline_parse_token_string_t cmd_showport_rss_hash_rss_hash = TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, rss_hash, "rss-hash"); cmdline_parse_token_string_t cmd_showport_rss_hash_rss_key = TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, key, "key"); cmdline_parse_inst_t cmd_showport_rss_hash = { .f = cmd_showport_rss_hash_parsed, .data = NULL, .help_str = "show port X rss-hash (X = port number)\n", .tokens = { (void *)&cmd_showport_rss_hash_show, (void *)&cmd_showport_rss_hash_port, (void *)&cmd_showport_rss_hash_port_id, (void *)&cmd_showport_rss_hash_rss_hash, NULL, }, }; cmdline_parse_inst_t cmd_showport_rss_hash_key = { .f = cmd_showport_rss_hash_parsed, .data = (void *)1, .help_str = "show port X rss-hash key (X = port number)\n", .tokens = { (void *)&cmd_showport_rss_hash_show, (void *)&cmd_showport_rss_hash_port, (void *)&cmd_showport_rss_hash_port_id, (void *)&cmd_showport_rss_hash_rss_hash, (void *)&cmd_showport_rss_hash_rss_key, NULL, }, }; /* *** Configure DCB *** */ struct cmd_config_dcb { cmdline_fixed_string_t port; cmdline_fixed_string_t config; uint8_t port_id; cmdline_fixed_string_t dcb; cmdline_fixed_string_t vt; cmdline_fixed_string_t vt_en; uint8_t num_tcs; cmdline_fixed_string_t pfc; cmdline_fixed_string_t pfc_en; }; static void cmd_config_dcb_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_dcb *res = parsed_result; struct dcb_config dcb_conf; portid_t port_id = res->port_id; struct rte_port *port; port = &ports[port_id]; /** Check if the port is not started **/ if (port->port_status != RTE_PORT_STOPPED) { printf("Please stop port %d first\n",port_id); return; } dcb_conf.num_tcs = (enum rte_eth_nb_tcs) res->num_tcs; if ((dcb_conf.num_tcs != ETH_4_TCS) && (dcb_conf.num_tcs != ETH_8_TCS)){ printf("The invalid number of traffic class,only 4 or 8 allowed\n"); return; } /* DCB in VT mode */ if (!strncmp(res->vt_en, "on",2)) dcb_conf.dcb_mode = DCB_VT_ENABLED; else dcb_conf.dcb_mode = DCB_ENABLED; if (!strncmp(res->pfc_en, "on",2)) { dcb_conf.pfc_en = 1; } else dcb_conf.pfc_en = 0; if (init_port_dcb_config(port_id,&dcb_conf) != 0) { printf("Cannot initialize network ports\n"); return; } cmd_reconfig_device_queue(port_id, 1, 1); } cmdline_parse_token_string_t cmd_config_dcb_port = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, port, "port"); cmdline_parse_token_string_t cmd_config_dcb_config = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, config, "config"); cmdline_parse_token_num_t cmd_config_dcb_port_id = TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, port_id, UINT8); cmdline_parse_token_string_t cmd_config_dcb_dcb = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, dcb, "dcb"); cmdline_parse_token_string_t cmd_config_dcb_vt = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt, "vt"); cmdline_parse_token_string_t cmd_config_dcb_vt_en = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt_en, "on#off"); cmdline_parse_token_num_t cmd_config_dcb_num_tcs = TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, num_tcs, UINT8); cmdline_parse_token_string_t cmd_config_dcb_pfc= TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc, "pfc"); cmdline_parse_token_string_t cmd_config_dcb_pfc_en = TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc_en, "on#off"); cmdline_parse_inst_t cmd_config_dcb = { .f = cmd_config_dcb_parsed, .data = NULL, .help_str = "port config port-id dcb vt on|off nb-tcs pfc on|off", .tokens = { (void *)&cmd_config_dcb_port, (void *)&cmd_config_dcb_config, (void *)&cmd_config_dcb_port_id, (void *)&cmd_config_dcb_dcb, (void *)&cmd_config_dcb_vt, (void *)&cmd_config_dcb_vt_en, (void *)&cmd_config_dcb_num_tcs, (void *)&cmd_config_dcb_pfc, (void *)&cmd_config_dcb_pfc_en, NULL, }, }; /* *** configure number of packets per burst *** */ struct cmd_config_burst { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; uint16_t value; }; static void cmd_config_burst_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_burst *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "burst")) { if (res->value < 1 || res->value > MAX_PKT_BURST) { printf("burst must be >= 1 && <= %d\n", MAX_PKT_BURST); return; } nb_pkt_per_burst = res->value; } else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_burst_port = TOKEN_STRING_INITIALIZER(struct cmd_config_burst, port, "port"); cmdline_parse_token_string_t cmd_config_burst_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_burst, keyword, "config"); cmdline_parse_token_string_t cmd_config_burst_all = TOKEN_STRING_INITIALIZER(struct cmd_config_burst, all, "all"); cmdline_parse_token_string_t cmd_config_burst_name = TOKEN_STRING_INITIALIZER(struct cmd_config_burst, name, "burst"); cmdline_parse_token_num_t cmd_config_burst_value = TOKEN_NUM_INITIALIZER(struct cmd_config_burst, value, UINT16); cmdline_parse_inst_t cmd_config_burst = { .f = cmd_config_burst_parsed, .data = NULL, .help_str = "port config all burst value", .tokens = { (void *)&cmd_config_burst_port, (void *)&cmd_config_burst_keyword, (void *)&cmd_config_burst_all, (void *)&cmd_config_burst_name, (void *)&cmd_config_burst_value, NULL, }, }; /* *** configure rx/tx queues *** */ struct cmd_config_thresh { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; uint8_t value; }; static void cmd_config_thresh_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_thresh *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "txpt")) tx_pthresh = res->value; else if(!strcmp(res->name, "txht")) tx_hthresh = res->value; else if(!strcmp(res->name, "txwt")) tx_wthresh = res->value; else if(!strcmp(res->name, "rxpt")) rx_pthresh = res->value; else if(!strcmp(res->name, "rxht")) rx_hthresh = res->value; else if(!strcmp(res->name, "rxwt")) rx_wthresh = res->value; else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_thresh_port = TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, port, "port"); cmdline_parse_token_string_t cmd_config_thresh_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, keyword, "config"); cmdline_parse_token_string_t cmd_config_thresh_all = TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, all, "all"); cmdline_parse_token_string_t cmd_config_thresh_name = TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, name, "txpt#txht#txwt#rxpt#rxht#rxwt"); cmdline_parse_token_num_t cmd_config_thresh_value = TOKEN_NUM_INITIALIZER(struct cmd_config_thresh, value, UINT8); cmdline_parse_inst_t cmd_config_thresh = { .f = cmd_config_thresh_parsed, .data = NULL, .help_str = "port config all txpt|txht|txwt|rxpt|rxht|rxwt value", .tokens = { (void *)&cmd_config_thresh_port, (void *)&cmd_config_thresh_keyword, (void *)&cmd_config_thresh_all, (void *)&cmd_config_thresh_name, (void *)&cmd_config_thresh_value, NULL, }, }; /* *** configure free/rs threshold *** */ struct cmd_config_threshold { cmdline_fixed_string_t port; cmdline_fixed_string_t keyword; cmdline_fixed_string_t all; cmdline_fixed_string_t name; uint16_t value; }; static void cmd_config_threshold_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_config_threshold *res = parsed_result; if (!all_ports_stopped()) { printf("Please stop all ports first\n"); return; } if (!strcmp(res->name, "txfreet")) tx_free_thresh = res->value; else if (!strcmp(res->name, "txrst")) tx_rs_thresh = res->value; else if (!strcmp(res->name, "rxfreet")) rx_free_thresh = res->value; else { printf("Unknown parameter\n"); return; } init_port_config(); cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1); } cmdline_parse_token_string_t cmd_config_threshold_port = TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, port, "port"); cmdline_parse_token_string_t cmd_config_threshold_keyword = TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, keyword, "config"); cmdline_parse_token_string_t cmd_config_threshold_all = TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, all, "all"); cmdline_parse_token_string_t cmd_config_threshold_name = TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, name, "txfreet#txrst#rxfreet"); cmdline_parse_token_num_t cmd_config_threshold_value = TOKEN_NUM_INITIALIZER(struct cmd_config_threshold, value, UINT16); cmdline_parse_inst_t cmd_config_threshold = { .f = cmd_config_threshold_parsed, .data = NULL, .help_str = "port config all txfreet|txrst|rxfreet value", .tokens = { (void *)&cmd_config_threshold_port, (void *)&cmd_config_threshold_keyword, (void *)&cmd_config_threshold_all, (void *)&cmd_config_threshold_name, (void *)&cmd_config_threshold_value, NULL, }, }; /* *** stop *** */ struct cmd_stop_result { cmdline_fixed_string_t stop; }; static void cmd_stop_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { stop_packet_forwarding(); } cmdline_parse_token_string_t cmd_stop_stop = TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop"); cmdline_parse_inst_t cmd_stop = { .f = cmd_stop_parsed, .data = NULL, .help_str = "stop - stop packet forwarding", .tokens = { (void *)&cmd_stop_stop, NULL, }, }; /* *** SET CORELIST and PORTLIST CONFIGURATION *** */ unsigned int parse_item_list(char* str, const char* item_name, unsigned int max_items, unsigned int *parsed_items, int check_unique_values) { unsigned int nb_item; unsigned int value; unsigned int i; unsigned int j; int value_ok; char c; /* * First parse all items in the list and store their value. */ value = 0; nb_item = 0; value_ok = 0; for (i = 0; i < strnlen(str, STR_TOKEN_SIZE); i++) { c = str[i]; if ((c >= '0') && (c <= '9')) { value = (unsigned int) (value * 10 + (c - '0')); value_ok = 1; continue; } if (c != ',') { printf("character %c is not a decimal digit\n", c); return (0); } if (! value_ok) { printf("No valid value before comma\n"); return (0); } if (nb_item < max_items) { parsed_items[nb_item] = value; value_ok = 0; value = 0; } nb_item++; } if (nb_item >= max_items) { printf("Number of %s = %u > %u (maximum items)\n", item_name, nb_item + 1, max_items); return (0); } parsed_items[nb_item++] = value; if (! check_unique_values) return (nb_item); /* * Then, check that all values in the list are differents. * No optimization here... */ for (i = 0; i < nb_item; i++) { for (j = i + 1; j < nb_item; j++) { if (parsed_items[j] == parsed_items[i]) { printf("duplicated %s %u at index %u and %u\n", item_name, parsed_items[i], i, j); return (0); } } } return (nb_item); } struct cmd_set_list_result { cmdline_fixed_string_t cmd_keyword; cmdline_fixed_string_t list_name; cmdline_fixed_string_t list_of_items; }; static void cmd_set_list_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_list_result *res; union { unsigned int lcorelist[RTE_MAX_LCORE]; unsigned int portlist[RTE_MAX_ETHPORTS]; } parsed_items; unsigned int nb_item; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } res = parsed_result; if (!strcmp(res->list_name, "corelist")) { nb_item = parse_item_list(res->list_of_items, "core", RTE_MAX_LCORE, parsed_items.lcorelist, 1); if (nb_item > 0) set_fwd_lcores_list(parsed_items.lcorelist, nb_item); return; } if (!strcmp(res->list_name, "portlist")) { nb_item = parse_item_list(res->list_of_items, "port", RTE_MAX_ETHPORTS, parsed_items.portlist, 1); if (nb_item > 0) set_fwd_ports_list(parsed_items.portlist, nb_item); } } cmdline_parse_token_string_t cmd_set_list_keyword = TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, cmd_keyword, "set"); cmdline_parse_token_string_t cmd_set_list_name = TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_name, "corelist#portlist"); cmdline_parse_token_string_t cmd_set_list_of_items = TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_of_items, NULL); cmdline_parse_inst_t cmd_set_fwd_list = { .f = cmd_set_list_parsed, .data = NULL, .help_str = "set corelist|portlist x[,y]*", .tokens = { (void *)&cmd_set_list_keyword, (void *)&cmd_set_list_name, (void *)&cmd_set_list_of_items, NULL, }, }; /* *** SET COREMASK and PORTMASK CONFIGURATION *** */ struct cmd_setmask_result { cmdline_fixed_string_t set; cmdline_fixed_string_t mask; uint64_t hexavalue; }; static void cmd_set_mask_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_setmask_result *res = parsed_result; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } if (!strcmp(res->mask, "coremask")) set_fwd_lcores_mask(res->hexavalue); else if (!strcmp(res->mask, "portmask")) set_fwd_ports_mask(res->hexavalue); } cmdline_parse_token_string_t cmd_setmask_set = TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, set, "set"); cmdline_parse_token_string_t cmd_setmask_mask = TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, mask, "coremask#portmask"); cmdline_parse_token_num_t cmd_setmask_value = TOKEN_NUM_INITIALIZER(struct cmd_setmask_result, hexavalue, UINT64); cmdline_parse_inst_t cmd_set_fwd_mask = { .f = cmd_set_mask_parsed, .data = NULL, .help_str = "set coremask|portmask hexadecimal value", .tokens = { (void *)&cmd_setmask_set, (void *)&cmd_setmask_mask, (void *)&cmd_setmask_value, NULL, }, }; /* * SET NBPORT, NBCORE, PACKET BURST, and VERBOSE LEVEL CONFIGURATION */ struct cmd_set_result { cmdline_fixed_string_t set; cmdline_fixed_string_t what; uint16_t value; }; static void cmd_set_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_result *res = parsed_result; if (!strcmp(res->what, "nbport")) set_fwd_ports_number(res->value); else if (!strcmp(res->what, "nbcore")) set_fwd_lcores_number(res->value); else if (!strcmp(res->what, "burst")) set_nb_pkt_per_burst(res->value); else if (!strcmp(res->what, "verbose")) set_verbose_level(res->value); } cmdline_parse_token_string_t cmd_set_set = TOKEN_STRING_INITIALIZER(struct cmd_set_result, set, "set"); cmdline_parse_token_string_t cmd_set_what = TOKEN_STRING_INITIALIZER(struct cmd_set_result, what, "nbport#nbcore#burst#verbose"); cmdline_parse_token_num_t cmd_set_value = TOKEN_NUM_INITIALIZER(struct cmd_set_result, value, UINT16); cmdline_parse_inst_t cmd_set_numbers = { .f = cmd_set_parsed, .data = NULL, .help_str = "set nbport|nbcore|burst|verbose value", .tokens = { (void *)&cmd_set_set, (void *)&cmd_set_what, (void *)&cmd_set_value, NULL, }, }; /* *** SET SEGMENT LENGTHS OF TXONLY PACKETS *** */ struct cmd_set_txpkts_result { cmdline_fixed_string_t cmd_keyword; cmdline_fixed_string_t txpkts; cmdline_fixed_string_t seg_lengths; }; static void cmd_set_txpkts_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_txpkts_result *res; unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT]; unsigned int nb_segs; res = parsed_result; nb_segs = parse_item_list(res->seg_lengths, "segment lengths", RTE_MAX_SEGS_PER_PKT, seg_lengths, 0); if (nb_segs > 0) set_tx_pkt_segments(seg_lengths, nb_segs); } cmdline_parse_token_string_t cmd_set_txpkts_keyword = TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result, cmd_keyword, "set"); cmdline_parse_token_string_t cmd_set_txpkts_name = TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result, txpkts, "txpkts"); cmdline_parse_token_string_t cmd_set_txpkts_lengths = TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result, seg_lengths, NULL); cmdline_parse_inst_t cmd_set_txpkts = { .f = cmd_set_txpkts_parsed, .data = NULL, .help_str = "set txpkts x[,y]*", .tokens = { (void *)&cmd_set_txpkts_keyword, (void *)&cmd_set_txpkts_name, (void *)&cmd_set_txpkts_lengths, NULL, }, }; /* *** ADD/REMOVE ALL VLAN IDENTIFIERS TO/FROM A PORT VLAN RX FILTER *** */ struct cmd_rx_vlan_filter_all_result { cmdline_fixed_string_t rx_vlan; cmdline_fixed_string_t what; cmdline_fixed_string_t all; uint8_t port_id; }; static void cmd_rx_vlan_filter_all_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_rx_vlan_filter_all_result *res = parsed_result; if (!strcmp(res->what, "add")) rx_vlan_all_filter_set(res->port_id, 1); else rx_vlan_all_filter_set(res->port_id, 0); } cmdline_parse_token_string_t cmd_rx_vlan_filter_all_rx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result, rx_vlan, "rx_vlan"); cmdline_parse_token_string_t cmd_rx_vlan_filter_all_what = TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result, what, "add#rm"); cmdline_parse_token_string_t cmd_rx_vlan_filter_all_all = TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result, all, "all"); cmdline_parse_token_num_t cmd_rx_vlan_filter_all_portid = TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_all_result, port_id, UINT8); cmdline_parse_inst_t cmd_rx_vlan_filter_all = { .f = cmd_rx_vlan_filter_all_parsed, .data = NULL, .help_str = "add/remove all identifiers to/from the set of VLAN " "Identifiers filtered by a port", .tokens = { (void *)&cmd_rx_vlan_filter_all_rx_vlan, (void *)&cmd_rx_vlan_filter_all_what, (void *)&cmd_rx_vlan_filter_all_all, (void *)&cmd_rx_vlan_filter_all_portid, NULL, }, }; /* *** VLAN OFFLOAD SET ON A PORT *** */ struct cmd_vlan_offload_result { cmdline_fixed_string_t vlan; cmdline_fixed_string_t set; cmdline_fixed_string_t what; cmdline_fixed_string_t on; cmdline_fixed_string_t port_id; }; static void cmd_vlan_offload_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int on; struct cmd_vlan_offload_result *res = parsed_result; char *str; int i, len = 0; portid_t port_id = 0; unsigned int tmp; str = res->port_id; len = strnlen(str, STR_TOKEN_SIZE); i = 0; /* Get port_id first */ while(i < len){ if(str[i] == ',') break; i++; } str[i]='\0'; tmp = strtoul(str, NULL, 0); /* If port_id greater that what portid_t can represent, return */ if(tmp >= RTE_MAX_ETHPORTS) return; port_id = (portid_t)tmp; if (!strcmp(res->on, "on")) on = 1; else on = 0; if (!strcmp(res->what, "strip")) rx_vlan_strip_set(port_id, on); else if(!strcmp(res->what, "stripq")){ uint16_t queue_id = 0; /* No queue_id, return */ if(i + 1 >= len) { printf("must specify (port,queue_id)\n"); return; } tmp = strtoul(str + i + 1, NULL, 0); /* If queue_id greater that what 16-bits can represent, return */ if(tmp > 0xffff) return; queue_id = (uint16_t)tmp; rx_vlan_strip_set_on_queue(port_id, queue_id, on); } else if (!strcmp(res->what, "filter")) rx_vlan_filter_set(port_id, on); else vlan_extend_set(port_id, on); return; } cmdline_parse_token_string_t cmd_vlan_offload_vlan = TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, vlan, "vlan"); cmdline_parse_token_string_t cmd_vlan_offload_set = TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, set, "set"); cmdline_parse_token_string_t cmd_vlan_offload_what = TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, what, "strip#filter#qinq#stripq"); cmdline_parse_token_string_t cmd_vlan_offload_on = TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, on, "on#off"); cmdline_parse_token_string_t cmd_vlan_offload_portid = TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result, port_id, NULL); cmdline_parse_inst_t cmd_vlan_offload = { .f = cmd_vlan_offload_parsed, .data = NULL, .help_str = "set strip|filter|qinq|stripq on|off port_id[,queue_id], filter/strip for rx side" " qinq(extended) for both rx/tx sides ", .tokens = { (void *)&cmd_vlan_offload_vlan, (void *)&cmd_vlan_offload_set, (void *)&cmd_vlan_offload_what, (void *)&cmd_vlan_offload_on, (void *)&cmd_vlan_offload_portid, NULL, }, }; /* *** VLAN TPID SET ON A PORT *** */ struct cmd_vlan_tpid_result { cmdline_fixed_string_t vlan; cmdline_fixed_string_t set; cmdline_fixed_string_t what; uint16_t tp_id; uint8_t port_id; }; static void cmd_vlan_tpid_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_vlan_tpid_result *res = parsed_result; vlan_tpid_set(res->port_id, res->tp_id); return; } cmdline_parse_token_string_t cmd_vlan_tpid_vlan = TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, vlan, "vlan"); cmdline_parse_token_string_t cmd_vlan_tpid_set = TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, set, "set"); cmdline_parse_token_string_t cmd_vlan_tpid_what = TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result, what, "tpid"); cmdline_parse_token_num_t cmd_vlan_tpid_tpid = TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result, tp_id, UINT16); cmdline_parse_token_num_t cmd_vlan_tpid_portid = TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result, port_id, UINT8); cmdline_parse_inst_t cmd_vlan_tpid = { .f = cmd_vlan_tpid_parsed, .data = NULL, .help_str = "set tpid tp_id port_id, set the Outer VLAN Ether type", .tokens = { (void *)&cmd_vlan_tpid_vlan, (void *)&cmd_vlan_tpid_set, (void *)&cmd_vlan_tpid_what, (void *)&cmd_vlan_tpid_tpid, (void *)&cmd_vlan_tpid_portid, NULL, }, }; /* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */ struct cmd_rx_vlan_filter_result { cmdline_fixed_string_t rx_vlan; cmdline_fixed_string_t what; uint16_t vlan_id; uint8_t port_id; }; static void cmd_rx_vlan_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_rx_vlan_filter_result *res = parsed_result; if (!strcmp(res->what, "add")) rx_vft_set(res->port_id, res->vlan_id, 1); else rx_vft_set(res->port_id, res->vlan_id, 0); } cmdline_parse_token_string_t cmd_rx_vlan_filter_rx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result, rx_vlan, "rx_vlan"); cmdline_parse_token_string_t cmd_rx_vlan_filter_what = TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result, what, "add#rm"); cmdline_parse_token_num_t cmd_rx_vlan_filter_vlanid = TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result, vlan_id, UINT16); cmdline_parse_token_num_t cmd_rx_vlan_filter_portid = TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result, port_id, UINT8); cmdline_parse_inst_t cmd_rx_vlan_filter = { .f = cmd_rx_vlan_filter_parsed, .data = NULL, .help_str = "add/remove a VLAN identifier to/from the set of VLAN " "Identifiers filtered by a port", .tokens = { (void *)&cmd_rx_vlan_filter_rx_vlan, (void *)&cmd_rx_vlan_filter_what, (void *)&cmd_rx_vlan_filter_vlanid, (void *)&cmd_rx_vlan_filter_portid, NULL, }, }; /* *** ENABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */ struct cmd_tx_vlan_set_result { cmdline_fixed_string_t tx_vlan; cmdline_fixed_string_t set; uint8_t port_id; uint16_t vlan_id; }; static void cmd_tx_vlan_set_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tx_vlan_set_result *res = parsed_result; int vlan_offload = rte_eth_dev_get_vlan_offload(res->port_id); if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) { printf("Error, as QinQ has been enabled.\n"); return; } tx_vlan_set(res->port_id, res->vlan_id); } cmdline_parse_token_string_t cmd_tx_vlan_set_tx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result, tx_vlan, "tx_vlan"); cmdline_parse_token_string_t cmd_tx_vlan_set_set = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result, set, "set"); cmdline_parse_token_num_t cmd_tx_vlan_set_vlanid = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result, vlan_id, UINT16); cmdline_parse_token_num_t cmd_tx_vlan_set_portid = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result, port_id, UINT8); cmdline_parse_inst_t cmd_tx_vlan_set = { .f = cmd_tx_vlan_set_parsed, .data = NULL, .help_str = "enable hardware insertion of a single VLAN header " "with a given TAG Identifier in packets sent on a port", .tokens = { (void *)&cmd_tx_vlan_set_tx_vlan, (void *)&cmd_tx_vlan_set_set, (void *)&cmd_tx_vlan_set_portid, (void *)&cmd_tx_vlan_set_vlanid, NULL, }, }; /* *** ENABLE HARDWARE INSERTION OF Double VLAN HEADER IN TX PACKETS *** */ struct cmd_tx_vlan_set_qinq_result { cmdline_fixed_string_t tx_vlan; cmdline_fixed_string_t set; uint8_t port_id; uint16_t vlan_id; uint16_t vlan_id_outer; }; static void cmd_tx_vlan_set_qinq_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tx_vlan_set_qinq_result *res = parsed_result; int vlan_offload = rte_eth_dev_get_vlan_offload(res->port_id); if (!(vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)) { printf("Error, as QinQ hasn't been enabled.\n"); return; } tx_qinq_set(res->port_id, res->vlan_id, res->vlan_id_outer); } cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_tx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result, tx_vlan, "tx_vlan"); cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_set = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result, set, "set"); cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_portid = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result, port_id, UINT8); cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result, vlan_id, UINT16); cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid_outer = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result, vlan_id_outer, UINT16); cmdline_parse_inst_t cmd_tx_vlan_set_qinq = { .f = cmd_tx_vlan_set_qinq_parsed, .data = NULL, .help_str = "enable hardware insertion of double VLAN header " "with given TAG Identifiers in packets sent on a port", .tokens = { (void *)&cmd_tx_vlan_set_qinq_tx_vlan, (void *)&cmd_tx_vlan_set_qinq_set, (void *)&cmd_tx_vlan_set_qinq_portid, (void *)&cmd_tx_vlan_set_qinq_vlanid, (void *)&cmd_tx_vlan_set_qinq_vlanid_outer, NULL, }, }; /* *** ENABLE/DISABLE PORT BASED TX VLAN INSERTION *** */ struct cmd_tx_vlan_set_pvid_result { cmdline_fixed_string_t tx_vlan; cmdline_fixed_string_t set; cmdline_fixed_string_t pvid; uint8_t port_id; uint16_t vlan_id; cmdline_fixed_string_t mode; }; static void cmd_tx_vlan_set_pvid_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tx_vlan_set_pvid_result *res = parsed_result; if (strcmp(res->mode, "on") == 0) tx_vlan_pvid_set(res->port_id, res->vlan_id, 1); else tx_vlan_pvid_set(res->port_id, res->vlan_id, 0); } cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_tx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, tx_vlan, "tx_vlan"); cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_set = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, set, "set"); cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_pvid = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, pvid, "pvid"); cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_port_id = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, port_id, UINT8); cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_vlan_id = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, vlan_id, UINT16); cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_mode = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result, mode, "on#off"); cmdline_parse_inst_t cmd_tx_vlan_set_pvid = { .f = cmd_tx_vlan_set_pvid_parsed, .data = NULL, .help_str = "tx_vlan set pvid port_id vlan_id (on|off)", .tokens = { (void *)&cmd_tx_vlan_set_pvid_tx_vlan, (void *)&cmd_tx_vlan_set_pvid_set, (void *)&cmd_tx_vlan_set_pvid_pvid, (void *)&cmd_tx_vlan_set_pvid_port_id, (void *)&cmd_tx_vlan_set_pvid_vlan_id, (void *)&cmd_tx_vlan_set_pvid_mode, NULL, }, }; /* *** DISABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */ struct cmd_tx_vlan_reset_result { cmdline_fixed_string_t tx_vlan; cmdline_fixed_string_t reset; uint8_t port_id; }; static void cmd_tx_vlan_reset_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tx_vlan_reset_result *res = parsed_result; tx_vlan_reset(res->port_id); } cmdline_parse_token_string_t cmd_tx_vlan_reset_tx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result, tx_vlan, "tx_vlan"); cmdline_parse_token_string_t cmd_tx_vlan_reset_reset = TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result, reset, "reset"); cmdline_parse_token_num_t cmd_tx_vlan_reset_portid = TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_reset_result, port_id, UINT8); cmdline_parse_inst_t cmd_tx_vlan_reset = { .f = cmd_tx_vlan_reset_parsed, .data = NULL, .help_str = "disable hardware insertion of a VLAN header in packets " "sent on a port", .tokens = { (void *)&cmd_tx_vlan_reset_tx_vlan, (void *)&cmd_tx_vlan_reset_reset, (void *)&cmd_tx_vlan_reset_portid, NULL, }, }; /* *** ENABLE HARDWARE INSERTION OF CHECKSUM IN TX PACKETS *** */ struct cmd_csum_result { cmdline_fixed_string_t csum; cmdline_fixed_string_t mode; cmdline_fixed_string_t proto; cmdline_fixed_string_t hwsw; uint8_t port_id; }; static void csum_show(int port_id) { struct rte_eth_dev_info dev_info; uint16_t ol_flags; ol_flags = ports[port_id].tx_ol_flags; printf("Parse tunnel is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_PARSE_TUNNEL) ? "on" : "off"); printf("IP checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) ? "hw" : "sw"); printf("UDP checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) ? "hw" : "sw"); printf("TCP checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) ? "hw" : "sw"); printf("SCTP checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) ? "hw" : "sw"); printf("Outer-Ip checksum offload is %s\n", (ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ? "hw" : "sw"); /* display warnings if configuration is not supported by the NIC */ rte_eth_dev_info_get(port_id, &dev_info); if ((ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0) { printf("Warning: hardware IP checksum enabled but not " "supported by port %d\n", port_id); } if ((ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) { printf("Warning: hardware UDP checksum enabled but not " "supported by port %d\n", port_id); } if ((ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) { printf("Warning: hardware TCP checksum enabled but not " "supported by port %d\n", port_id); } if ((ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) == 0) { printf("Warning: hardware SCTP checksum enabled but not " "supported by port %d\n", port_id); } if ((ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) == 0) { printf("Warning: hardware outer IP checksum enabled but not " "supported by port %d\n", port_id); } } static void cmd_csum_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_csum_result *res = parsed_result; int hw = 0; uint16_t mask = 0; if (port_id_is_invalid(res->port_id, ENABLED_WARN)) { printf("invalid port %d\n", res->port_id); return; } if (!strcmp(res->mode, "set")) { if (!strcmp(res->hwsw, "hw")) hw = 1; if (!strcmp(res->proto, "ip")) { mask = TESTPMD_TX_OFFLOAD_IP_CKSUM; } else if (!strcmp(res->proto, "udp")) { mask = TESTPMD_TX_OFFLOAD_UDP_CKSUM; } else if (!strcmp(res->proto, "tcp")) { mask = TESTPMD_TX_OFFLOAD_TCP_CKSUM; } else if (!strcmp(res->proto, "sctp")) { mask = TESTPMD_TX_OFFLOAD_SCTP_CKSUM; } else if (!strcmp(res->proto, "outer-ip")) { mask = TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM; } if (hw) ports[res->port_id].tx_ol_flags |= mask; else ports[res->port_id].tx_ol_flags &= (~mask); } csum_show(res->port_id); } cmdline_parse_token_string_t cmd_csum_csum = TOKEN_STRING_INITIALIZER(struct cmd_csum_result, csum, "csum"); cmdline_parse_token_string_t cmd_csum_mode = TOKEN_STRING_INITIALIZER(struct cmd_csum_result, mode, "set"); cmdline_parse_token_string_t cmd_csum_proto = TOKEN_STRING_INITIALIZER(struct cmd_csum_result, proto, "ip#tcp#udp#sctp#outer-ip"); cmdline_parse_token_string_t cmd_csum_hwsw = TOKEN_STRING_INITIALIZER(struct cmd_csum_result, hwsw, "hw#sw"); cmdline_parse_token_num_t cmd_csum_portid = TOKEN_NUM_INITIALIZER(struct cmd_csum_result, port_id, UINT8); cmdline_parse_inst_t cmd_csum_set = { .f = cmd_csum_parsed, .data = NULL, .help_str = "enable/disable hardware calculation of L3/L4 checksum when " "using csum forward engine: csum set ip|tcp|udp|sctp|outer-ip hw|sw ", .tokens = { (void *)&cmd_csum_csum, (void *)&cmd_csum_mode, (void *)&cmd_csum_proto, (void *)&cmd_csum_hwsw, (void *)&cmd_csum_portid, NULL, }, }; cmdline_parse_token_string_t cmd_csum_mode_show = TOKEN_STRING_INITIALIZER(struct cmd_csum_result, mode, "show"); cmdline_parse_inst_t cmd_csum_show = { .f = cmd_csum_parsed, .data = NULL, .help_str = "show checksum offload configuration: csum show ", .tokens = { (void *)&cmd_csum_csum, (void *)&cmd_csum_mode_show, (void *)&cmd_csum_portid, NULL, }, }; /* Enable/disable tunnel parsing */ struct cmd_csum_tunnel_result { cmdline_fixed_string_t csum; cmdline_fixed_string_t parse; cmdline_fixed_string_t onoff; uint8_t port_id; }; static void cmd_csum_tunnel_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_csum_tunnel_result *res = parsed_result; if (port_id_is_invalid(res->port_id, ENABLED_WARN)) return; if (!strcmp(res->onoff, "on")) ports[res->port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_PARSE_TUNNEL; else ports[res->port_id].tx_ol_flags &= (~TESTPMD_TX_OFFLOAD_PARSE_TUNNEL); csum_show(res->port_id); } cmdline_parse_token_string_t cmd_csum_tunnel_csum = TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result, csum, "csum"); cmdline_parse_token_string_t cmd_csum_tunnel_parse = TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result, parse, "parse_tunnel"); cmdline_parse_token_string_t cmd_csum_tunnel_onoff = TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result, onoff, "on#off"); cmdline_parse_token_num_t cmd_csum_tunnel_portid = TOKEN_NUM_INITIALIZER(struct cmd_csum_tunnel_result, port_id, UINT8); cmdline_parse_inst_t cmd_csum_tunnel = { .f = cmd_csum_tunnel_parsed, .data = NULL, .help_str = "enable/disable parsing of tunnels for csum engine: " "csum parse_tunnel on|off ", .tokens = { (void *)&cmd_csum_tunnel_csum, (void *)&cmd_csum_tunnel_parse, (void *)&cmd_csum_tunnel_onoff, (void *)&cmd_csum_tunnel_portid, NULL, }, }; /* *** ENABLE HARDWARE SEGMENTATION IN TX PACKETS *** */ struct cmd_tso_set_result { cmdline_fixed_string_t tso; cmdline_fixed_string_t mode; uint16_t tso_segsz; uint8_t port_id; }; static void cmd_tso_set_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tso_set_result *res = parsed_result; struct rte_eth_dev_info dev_info; if (port_id_is_invalid(res->port_id, ENABLED_WARN)) return; if (!strcmp(res->mode, "set")) ports[res->port_id].tso_segsz = res->tso_segsz; if (ports[res->port_id].tso_segsz == 0) printf("TSO is disabled\n"); else printf("TSO segment size is %d\n", ports[res->port_id].tso_segsz); /* display warnings if configuration is not supported by the NIC */ rte_eth_dev_info_get(res->port_id, &dev_info); if ((ports[res->port_id].tso_segsz != 0) && (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) { printf("Warning: TSO enabled but not " "supported by port %d\n", res->port_id); } } cmdline_parse_token_string_t cmd_tso_set_tso = TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, tso, "tso"); cmdline_parse_token_string_t cmd_tso_set_mode = TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, mode, "set"); cmdline_parse_token_num_t cmd_tso_set_tso_segsz = TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result, tso_segsz, UINT16); cmdline_parse_token_num_t cmd_tso_set_portid = TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result, port_id, UINT8); cmdline_parse_inst_t cmd_tso_set = { .f = cmd_tso_set_parsed, .data = NULL, .help_str = "Set TSO segment size for csum engine (0 to disable): " "tso set ", .tokens = { (void *)&cmd_tso_set_tso, (void *)&cmd_tso_set_mode, (void *)&cmd_tso_set_tso_segsz, (void *)&cmd_tso_set_portid, NULL, }, }; cmdline_parse_token_string_t cmd_tso_show_mode = TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, mode, "show"); cmdline_parse_inst_t cmd_tso_show = { .f = cmd_tso_set_parsed, .data = NULL, .help_str = "Show TSO segment size for csum engine: " "tso show ", .tokens = { (void *)&cmd_tso_set_tso, (void *)&cmd_tso_show_mode, (void *)&cmd_tso_set_portid, NULL, }, }; /* *** ENABLE/DISABLE FLUSH ON RX STREAMS *** */ struct cmd_set_flush_rx { cmdline_fixed_string_t set; cmdline_fixed_string_t flush_rx; cmdline_fixed_string_t mode; }; static void cmd_set_flush_rx_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_flush_rx *res = parsed_result; no_flush_rx = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1); } cmdline_parse_token_string_t cmd_setflushrx_set = TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx, set, "set"); cmdline_parse_token_string_t cmd_setflushrx_flush_rx = TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx, flush_rx, "flush_rx"); cmdline_parse_token_string_t cmd_setflushrx_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx, mode, "on#off"); cmdline_parse_inst_t cmd_set_flush_rx = { .f = cmd_set_flush_rx_parsed, .help_str = "set flush_rx on|off: enable/disable flush on rx streams", .data = NULL, .tokens = { (void *)&cmd_setflushrx_set, (void *)&cmd_setflushrx_flush_rx, (void *)&cmd_setflushrx_mode, NULL, }, }; /* *** ENABLE/DISABLE LINK STATUS CHECK *** */ struct cmd_set_link_check { cmdline_fixed_string_t set; cmdline_fixed_string_t link_check; cmdline_fixed_string_t mode; }; static void cmd_set_link_check_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_link_check *res = parsed_result; no_link_check = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1); } cmdline_parse_token_string_t cmd_setlinkcheck_set = TOKEN_STRING_INITIALIZER(struct cmd_set_link_check, set, "set"); cmdline_parse_token_string_t cmd_setlinkcheck_link_check = TOKEN_STRING_INITIALIZER(struct cmd_set_link_check, link_check, "link_check"); cmdline_parse_token_string_t cmd_setlinkcheck_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_link_check, mode, "on#off"); cmdline_parse_inst_t cmd_set_link_check = { .f = cmd_set_link_check_parsed, .help_str = "set link_check on|off: enable/disable link status check " "when starting/stopping a port", .data = NULL, .tokens = { (void *)&cmd_setlinkcheck_set, (void *)&cmd_setlinkcheck_link_check, (void *)&cmd_setlinkcheck_mode, NULL, }, }; #ifdef RTE_NIC_BYPASS /* *** SET NIC BYPASS MODE *** */ struct cmd_set_bypass_mode_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bypass; cmdline_fixed_string_t mode; cmdline_fixed_string_t value; uint8_t port_id; }; static void cmd_set_bypass_mode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bypass_mode_result *res = parsed_result; portid_t port_id = res->port_id; uint32_t bypass_mode = RTE_BYPASS_MODE_NORMAL; if (!bypass_is_supported(port_id)) return; if (!strcmp(res->value, "bypass")) bypass_mode = RTE_BYPASS_MODE_BYPASS; else if (!strcmp(res->value, "isolate")) bypass_mode = RTE_BYPASS_MODE_ISOLATE; else bypass_mode = RTE_BYPASS_MODE_NORMAL; /* Set the bypass mode for the relevant port. */ if (0 != rte_eth_dev_bypass_state_set(port_id, &bypass_mode)) { printf("\t Failed to set bypass mode for port = %d.\n", port_id); } } cmdline_parse_token_string_t cmd_setbypass_mode_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result, set, "set"); cmdline_parse_token_string_t cmd_setbypass_mode_bypass = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result, bypass, "bypass"); cmdline_parse_token_string_t cmd_setbypass_mode_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result, mode, "mode"); cmdline_parse_token_string_t cmd_setbypass_mode_value = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result, value, "normal#bypass#isolate"); cmdline_parse_token_num_t cmd_setbypass_mode_port = TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_mode_result, port_id, UINT8); cmdline_parse_inst_t cmd_set_bypass_mode = { .f = cmd_set_bypass_mode_parsed, .help_str = "set bypass mode (normal|bypass|isolate) (port_id): " "Set the NIC bypass mode for port_id", .data = NULL, .tokens = { (void *)&cmd_setbypass_mode_set, (void *)&cmd_setbypass_mode_bypass, (void *)&cmd_setbypass_mode_mode, (void *)&cmd_setbypass_mode_value, (void *)&cmd_setbypass_mode_port, NULL, }, }; /* *** SET NIC BYPASS EVENT *** */ struct cmd_set_bypass_event_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bypass; cmdline_fixed_string_t event; cmdline_fixed_string_t event_value; cmdline_fixed_string_t mode; cmdline_fixed_string_t mode_value; uint8_t port_id; }; static void cmd_set_bypass_event_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int32_t rc; struct cmd_set_bypass_event_result *res = parsed_result; portid_t port_id = res->port_id; uint32_t bypass_event = RTE_BYPASS_EVENT_NONE; uint32_t bypass_mode = RTE_BYPASS_MODE_NORMAL; if (!bypass_is_supported(port_id)) return; if (!strcmp(res->event_value, "timeout")) bypass_event = RTE_BYPASS_EVENT_TIMEOUT; else if (!strcmp(res->event_value, "os_on")) bypass_event = RTE_BYPASS_EVENT_OS_ON; else if (!strcmp(res->event_value, "os_off")) bypass_event = RTE_BYPASS_EVENT_OS_OFF; else if (!strcmp(res->event_value, "power_on")) bypass_event = RTE_BYPASS_EVENT_POWER_ON; else if (!strcmp(res->event_value, "power_off")) bypass_event = RTE_BYPASS_EVENT_POWER_OFF; else bypass_event = RTE_BYPASS_EVENT_NONE; if (!strcmp(res->mode_value, "bypass")) bypass_mode = RTE_BYPASS_MODE_BYPASS; else if (!strcmp(res->mode_value, "isolate")) bypass_mode = RTE_BYPASS_MODE_ISOLATE; else bypass_mode = RTE_BYPASS_MODE_NORMAL; /* Set the watchdog timeout. */ if (bypass_event == RTE_BYPASS_EVENT_TIMEOUT) { rc = -EINVAL; if (!RTE_BYPASS_TMT_VALID(bypass_timeout) || (rc = rte_eth_dev_wd_timeout_store(port_id, bypass_timeout)) != 0) { printf("Failed to set timeout value %u " "for port %d, errto code: %d.\n", bypass_timeout, port_id, rc); } } /* Set the bypass event to transition to bypass mode. */ if (0 != rte_eth_dev_bypass_event_store(port_id, bypass_event, bypass_mode)) { printf("\t Failed to set bypass event for port = %d.\n", port_id); } } cmdline_parse_token_string_t cmd_setbypass_event_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, set, "set"); cmdline_parse_token_string_t cmd_setbypass_event_bypass = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, bypass, "bypass"); cmdline_parse_token_string_t cmd_setbypass_event_event = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, event, "event"); cmdline_parse_token_string_t cmd_setbypass_event_event_value = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, event_value, "none#timeout#os_off#os_on#power_on#power_off"); cmdline_parse_token_string_t cmd_setbypass_event_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, mode, "mode"); cmdline_parse_token_string_t cmd_setbypass_event_mode_value = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result, mode_value, "normal#bypass#isolate"); cmdline_parse_token_num_t cmd_setbypass_event_port = TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_event_result, port_id, UINT8); cmdline_parse_inst_t cmd_set_bypass_event = { .f = cmd_set_bypass_event_parsed, .help_str = "set bypass event (timeout|os_on|os_off|power_on|power_off) " "mode (normal|bypass|isolate) (port_id): " "Set the NIC bypass event mode for port_id", .data = NULL, .tokens = { (void *)&cmd_setbypass_event_set, (void *)&cmd_setbypass_event_bypass, (void *)&cmd_setbypass_event_event, (void *)&cmd_setbypass_event_event_value, (void *)&cmd_setbypass_event_mode, (void *)&cmd_setbypass_event_mode_value, (void *)&cmd_setbypass_event_port, NULL, }, }; /* *** SET NIC BYPASS TIMEOUT *** */ struct cmd_set_bypass_timeout_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bypass; cmdline_fixed_string_t timeout; cmdline_fixed_string_t value; }; static void cmd_set_bypass_timeout_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bypass_timeout_result *res = parsed_result; if (!strcmp(res->value, "1.5")) bypass_timeout = RTE_BYPASS_TMT_1_5_SEC; else if (!strcmp(res->value, "2")) bypass_timeout = RTE_BYPASS_TMT_2_SEC; else if (!strcmp(res->value, "3")) bypass_timeout = RTE_BYPASS_TMT_3_SEC; else if (!strcmp(res->value, "4")) bypass_timeout = RTE_BYPASS_TMT_4_SEC; else if (!strcmp(res->value, "8")) bypass_timeout = RTE_BYPASS_TMT_8_SEC; else if (!strcmp(res->value, "16")) bypass_timeout = RTE_BYPASS_TMT_16_SEC; else if (!strcmp(res->value, "32")) bypass_timeout = RTE_BYPASS_TMT_32_SEC; else bypass_timeout = RTE_BYPASS_TMT_OFF; } cmdline_parse_token_string_t cmd_setbypass_timeout_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result, set, "set"); cmdline_parse_token_string_t cmd_setbypass_timeout_bypass = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result, bypass, "bypass"); cmdline_parse_token_string_t cmd_setbypass_timeout_timeout = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result, timeout, "timeout"); cmdline_parse_token_string_t cmd_setbypass_timeout_value = TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result, value, "0#1.5#2#3#4#8#16#32"); cmdline_parse_inst_t cmd_set_bypass_timeout = { .f = cmd_set_bypass_timeout_parsed, .help_str = "set bypass timeout (0|1.5|2|3|4|8|16|32) seconds: " "Set the NIC bypass watchdog timeout", .data = NULL, .tokens = { (void *)&cmd_setbypass_timeout_set, (void *)&cmd_setbypass_timeout_bypass, (void *)&cmd_setbypass_timeout_timeout, (void *)&cmd_setbypass_timeout_value, NULL, }, }; /* *** SHOW NIC BYPASS MODE *** */ struct cmd_show_bypass_config_result { cmdline_fixed_string_t show; cmdline_fixed_string_t bypass; cmdline_fixed_string_t config; uint8_t port_id; }; static void cmd_show_bypass_config_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_bypass_config_result *res = parsed_result; uint32_t event_mode; uint32_t bypass_mode; portid_t port_id = res->port_id; uint32_t timeout = bypass_timeout; int i; static const char * const timeouts[RTE_BYPASS_TMT_NUM] = {"off", "1.5", "2", "3", "4", "8", "16", "32"}; static const char * const modes[RTE_BYPASS_MODE_NUM] = {"UNKNOWN", "normal", "bypass", "isolate"}; static const char * const events[RTE_BYPASS_EVENT_NUM] = { "NONE", "OS/board on", "power supply on", "OS/board off", "power supply off", "timeout"}; int num_events = (sizeof events) / (sizeof events[0]); if (!bypass_is_supported(port_id)) return; /* Display the bypass mode.*/ if (0 != rte_eth_dev_bypass_state_show(port_id, &bypass_mode)) { printf("\tFailed to get bypass mode for port = %d\n", port_id); return; } else { if (!RTE_BYPASS_MODE_VALID(bypass_mode)) bypass_mode = RTE_BYPASS_MODE_NONE; printf("\tbypass mode = %s\n", modes[bypass_mode]); } /* Display the bypass timeout.*/ if (!RTE_BYPASS_TMT_VALID(timeout)) timeout = RTE_BYPASS_TMT_OFF; printf("\tbypass timeout = %s\n", timeouts[timeout]); /* Display the bypass events and associated modes. */ for (i = RTE_BYPASS_EVENT_START; i < num_events; i++) { if (0 != rte_eth_dev_bypass_event_show(port_id, i, &event_mode)) { printf("\tFailed to get bypass mode for event = %s\n", events[i]); } else { if (!RTE_BYPASS_MODE_VALID(event_mode)) event_mode = RTE_BYPASS_MODE_NONE; printf("\tbypass event: %-16s = %s\n", events[i], modes[event_mode]); } } } cmdline_parse_token_string_t cmd_showbypass_config_show = TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result, show, "show"); cmdline_parse_token_string_t cmd_showbypass_config_bypass = TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result, bypass, "bypass"); cmdline_parse_token_string_t cmd_showbypass_config_config = TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result, config, "config"); cmdline_parse_token_num_t cmd_showbypass_config_port = TOKEN_NUM_INITIALIZER(struct cmd_show_bypass_config_result, port_id, UINT8); cmdline_parse_inst_t cmd_show_bypass_config = { .f = cmd_show_bypass_config_parsed, .help_str = "show bypass config (port_id): " "Show the NIC bypass config for port_id", .data = NULL, .tokens = { (void *)&cmd_showbypass_config_show, (void *)&cmd_showbypass_config_bypass, (void *)&cmd_showbypass_config_config, (void *)&cmd_showbypass_config_port, NULL, }, }; #endif #ifdef RTE_LIBRTE_PMD_BOND /* *** SET BONDING MODE *** */ struct cmd_set_bonding_mode_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bonding; cmdline_fixed_string_t mode; uint8_t value; uint8_t port_id; }; static void cmd_set_bonding_mode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bonding_mode_result *res = parsed_result; portid_t port_id = res->port_id; /* Set the bonding mode for the relevant port. */ if (0 != rte_eth_bond_mode_set(port_id, res->value)) printf("\t Failed to set bonding mode for port = %d.\n", port_id); } cmdline_parse_token_string_t cmd_setbonding_mode_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result, set, "set"); cmdline_parse_token_string_t cmd_setbonding_mode_bonding = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_setbonding_mode_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result, mode, "mode"); cmdline_parse_token_num_t cmd_setbonding_mode_value = TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result, value, UINT8); cmdline_parse_token_num_t cmd_setbonding_mode_port = TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result, port_id, UINT8); cmdline_parse_inst_t cmd_set_bonding_mode = { .f = cmd_set_bonding_mode_parsed, .help_str = "set bonding mode (mode_value) (port_id): Set the bonding mode for port_id", .data = NULL, .tokens = { (void *) &cmd_setbonding_mode_set, (void *) &cmd_setbonding_mode_bonding, (void *) &cmd_setbonding_mode_mode, (void *) &cmd_setbonding_mode_value, (void *) &cmd_setbonding_mode_port, NULL } }; /* *** SET BALANCE XMIT POLICY *** */ struct cmd_set_bonding_balance_xmit_policy_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bonding; cmdline_fixed_string_t balance_xmit_policy; uint8_t port_id; cmdline_fixed_string_t policy; }; static void cmd_set_bonding_balance_xmit_policy_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bonding_balance_xmit_policy_result *res = parsed_result; portid_t port_id = res->port_id; uint8_t policy; if (!strcmp(res->policy, "l2")) { policy = BALANCE_XMIT_POLICY_LAYER2; } else if (!strcmp(res->policy, "l23")) { policy = BALANCE_XMIT_POLICY_LAYER23; } else if (!strcmp(res->policy, "l34")) { policy = BALANCE_XMIT_POLICY_LAYER34; } else { printf("\t Invalid xmit policy selection"); return; } /* Set the bonding mode for the relevant port. */ if (0 != rte_eth_bond_xmit_policy_set(port_id, policy)) { printf("\t Failed to set bonding balance xmit policy for port = %d.\n", port_id); } } cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result, set, "set"); cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_bonding = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_balance_xmit_policy = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result, balance_xmit_policy, "balance_xmit_policy"); cmdline_parse_token_num_t cmd_setbonding_balance_xmit_policy_port = TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result, port_id, UINT8); cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_policy = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result, policy, "l2#l23#l34"); cmdline_parse_inst_t cmd_set_balance_xmit_policy = { .f = cmd_set_bonding_balance_xmit_policy_parsed, .help_str = "set bonding balance_xmit_policy (port_id) (policy_value): Set the bonding balance_xmit_policy for port_id", .data = NULL, .tokens = { (void *)&cmd_setbonding_balance_xmit_policy_set, (void *)&cmd_setbonding_balance_xmit_policy_bonding, (void *)&cmd_setbonding_balance_xmit_policy_balance_xmit_policy, (void *)&cmd_setbonding_balance_xmit_policy_port, (void *)&cmd_setbonding_balance_xmit_policy_policy, NULL } }; /* *** SHOW NIC BONDING CONFIGURATION *** */ struct cmd_show_bonding_config_result { cmdline_fixed_string_t show; cmdline_fixed_string_t bonding; cmdline_fixed_string_t config; uint8_t port_id; }; static void cmd_show_bonding_config_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_bonding_config_result *res = parsed_result; int bonding_mode; uint8_t slaves[RTE_MAX_ETHPORTS]; int num_slaves, num_active_slaves; int primary_id; int i; portid_t port_id = res->port_id; /* Display the bonding mode.*/ bonding_mode = rte_eth_bond_mode_get(port_id); if (bonding_mode < 0) { printf("\tFailed to get bonding mode for port = %d\n", port_id); return; } else printf("\tBonding mode: %d\n", bonding_mode); if (bonding_mode == BONDING_MODE_BALANCE) { int balance_xmit_policy; balance_xmit_policy = rte_eth_bond_xmit_policy_get(port_id); if (balance_xmit_policy < 0) { printf("\tFailed to get balance xmit policy for port = %d\n", port_id); return; } else { printf("\tBalance Xmit Policy: "); switch (balance_xmit_policy) { case BALANCE_XMIT_POLICY_LAYER2: printf("BALANCE_XMIT_POLICY_LAYER2"); break; case BALANCE_XMIT_POLICY_LAYER23: printf("BALANCE_XMIT_POLICY_LAYER23"); break; case BALANCE_XMIT_POLICY_LAYER34: printf("BALANCE_XMIT_POLICY_LAYER34"); break; } printf("\n"); } } num_slaves = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS); if (num_slaves < 0) { printf("\tFailed to get slave list for port = %d\n", port_id); return; } if (num_slaves > 0) { printf("\tSlaves (%d): [", num_slaves); for (i = 0; i < num_slaves - 1; i++) printf("%d ", slaves[i]); printf("%d]\n", slaves[num_slaves - 1]); } else { printf("\tSlaves: []\n"); } num_active_slaves = rte_eth_bond_active_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS); if (num_active_slaves < 0) { printf("\tFailed to get active slave list for port = %d\n", port_id); return; } if (num_active_slaves > 0) { printf("\tActive Slaves (%d): [", num_active_slaves); for (i = 0; i < num_active_slaves - 1; i++) printf("%d ", slaves[i]); printf("%d]\n", slaves[num_active_slaves - 1]); } else { printf("\tActive Slaves: []\n"); } primary_id = rte_eth_bond_primary_get(port_id); if (primary_id < 0) { printf("\tFailed to get primary slave for port = %d\n", port_id); return; } else printf("\tPrimary: [%d]\n", primary_id); } cmdline_parse_token_string_t cmd_showbonding_config_show = TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result, show, "show"); cmdline_parse_token_string_t cmd_showbonding_config_bonding = TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_showbonding_config_config = TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result, config, "config"); cmdline_parse_token_num_t cmd_showbonding_config_port = TOKEN_NUM_INITIALIZER(struct cmd_show_bonding_config_result, port_id, UINT8); cmdline_parse_inst_t cmd_show_bonding_config = { .f = cmd_show_bonding_config_parsed, .help_str = "show bonding config (port_id): Show the bonding config for port_id", .data = NULL, .tokens = { (void *)&cmd_showbonding_config_show, (void *)&cmd_showbonding_config_bonding, (void *)&cmd_showbonding_config_config, (void *)&cmd_showbonding_config_port, NULL } }; /* *** SET BONDING PRIMARY *** */ struct cmd_set_bonding_primary_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bonding; cmdline_fixed_string_t primary; uint8_t slave_id; uint8_t port_id; }; static void cmd_set_bonding_primary_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bonding_primary_result *res = parsed_result; portid_t master_port_id = res->port_id; portid_t slave_port_id = res->slave_id; /* Set the primary slave for a bonded device. */ if (0 != rte_eth_bond_primary_set(master_port_id, slave_port_id)) { printf("\t Failed to set primary slave for port = %d.\n", master_port_id); return; } init_port_config(); } cmdline_parse_token_string_t cmd_setbonding_primary_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result, set, "set"); cmdline_parse_token_string_t cmd_setbonding_primary_bonding = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_setbonding_primary_primary = TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result, primary, "primary"); cmdline_parse_token_num_t cmd_setbonding_primary_slave = TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result, slave_id, UINT8); cmdline_parse_token_num_t cmd_setbonding_primary_port = TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result, port_id, UINT8); cmdline_parse_inst_t cmd_set_bonding_primary = { .f = cmd_set_bonding_primary_parsed, .help_str = "set bonding primary (slave_id) (port_id): Set the primary slave for port_id", .data = NULL, .tokens = { (void *)&cmd_setbonding_primary_set, (void *)&cmd_setbonding_primary_bonding, (void *)&cmd_setbonding_primary_primary, (void *)&cmd_setbonding_primary_slave, (void *)&cmd_setbonding_primary_port, NULL } }; /* *** ADD SLAVE *** */ struct cmd_add_bonding_slave_result { cmdline_fixed_string_t add; cmdline_fixed_string_t bonding; cmdline_fixed_string_t slave; uint8_t slave_id; uint8_t port_id; }; static void cmd_add_bonding_slave_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_add_bonding_slave_result *res = parsed_result; portid_t master_port_id = res->port_id; portid_t slave_port_id = res->slave_id; /* Set the primary slave for a bonded device. */ if (0 != rte_eth_bond_slave_add(master_port_id, slave_port_id)) { printf("\t Failed to add slave %d to master port = %d.\n", slave_port_id, master_port_id); return; } init_port_config(); set_port_slave_flag(slave_port_id); } cmdline_parse_token_string_t cmd_addbonding_slave_add = TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result, add, "add"); cmdline_parse_token_string_t cmd_addbonding_slave_bonding = TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_addbonding_slave_slave = TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result, slave, "slave"); cmdline_parse_token_num_t cmd_addbonding_slave_slaveid = TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result, slave_id, UINT8); cmdline_parse_token_num_t cmd_addbonding_slave_port = TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result, port_id, UINT8); cmdline_parse_inst_t cmd_add_bonding_slave = { .f = cmd_add_bonding_slave_parsed, .help_str = "add bonding slave (slave_id) (port_id): Add a slave device to a bonded device", .data = NULL, .tokens = { (void *)&cmd_addbonding_slave_add, (void *)&cmd_addbonding_slave_bonding, (void *)&cmd_addbonding_slave_slave, (void *)&cmd_addbonding_slave_slaveid, (void *)&cmd_addbonding_slave_port, NULL } }; /* *** REMOVE SLAVE *** */ struct cmd_remove_bonding_slave_result { cmdline_fixed_string_t remove; cmdline_fixed_string_t bonding; cmdline_fixed_string_t slave; uint8_t slave_id; uint8_t port_id; }; static void cmd_remove_bonding_slave_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_remove_bonding_slave_result *res = parsed_result; portid_t master_port_id = res->port_id; portid_t slave_port_id = res->slave_id; /* Set the primary slave for a bonded device. */ if (0 != rte_eth_bond_slave_remove(master_port_id, slave_port_id)) { printf("\t Failed to remove slave %d from master port = %d.\n", slave_port_id, master_port_id); return; } init_port_config(); clear_port_slave_flag(slave_port_id); } cmdline_parse_token_string_t cmd_removebonding_slave_remove = TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result, remove, "remove"); cmdline_parse_token_string_t cmd_removebonding_slave_bonding = TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_removebonding_slave_slave = TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result, slave, "slave"); cmdline_parse_token_num_t cmd_removebonding_slave_slaveid = TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result, slave_id, UINT8); cmdline_parse_token_num_t cmd_removebonding_slave_port = TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result, port_id, UINT8); cmdline_parse_inst_t cmd_remove_bonding_slave = { .f = cmd_remove_bonding_slave_parsed, .help_str = "remove bonding slave (slave_id) (port_id): Remove a slave device from a bonded device", .data = NULL, .tokens = { (void *)&cmd_removebonding_slave_remove, (void *)&cmd_removebonding_slave_bonding, (void *)&cmd_removebonding_slave_slave, (void *)&cmd_removebonding_slave_slaveid, (void *)&cmd_removebonding_slave_port, NULL } }; /* *** CREATE BONDED DEVICE *** */ struct cmd_create_bonded_device_result { cmdline_fixed_string_t create; cmdline_fixed_string_t bonded; cmdline_fixed_string_t device; uint8_t mode; uint8_t socket; }; static int bond_dev_num = 0; static void cmd_create_bonded_device_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_create_bonded_device_result *res = parsed_result; char ethdev_name[RTE_ETH_NAME_MAX_LEN]; int port_id; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "eth_bond_testpmd_%d", bond_dev_num++); /* Create a new bonded device. */ port_id = rte_eth_bond_create(ethdev_name, res->mode, res->socket); if (port_id < 0) { printf("\t Failed to create bonded device.\n"); return; } else { printf("Created new bonded device %s on (port %d).\n", ethdev_name, port_id); /* Update number of ports */ nb_ports = rte_eth_dev_count(); reconfig(port_id, res->socket); rte_eth_promiscuous_enable(port_id); ports[port_id].enabled = 1; } } cmdline_parse_token_string_t cmd_createbonded_device_create = TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result, create, "create"); cmdline_parse_token_string_t cmd_createbonded_device_bonded = TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result, bonded, "bonded"); cmdline_parse_token_string_t cmd_createbonded_device_device = TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result, device, "device"); cmdline_parse_token_num_t cmd_createbonded_device_mode = TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result, mode, UINT8); cmdline_parse_token_num_t cmd_createbonded_device_socket = TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result, socket, UINT8); cmdline_parse_inst_t cmd_create_bonded_device = { .f = cmd_create_bonded_device_parsed, .help_str = "create bonded device (mode) (socket): Create a new bonded device with specific bonding mode and socket", .data = NULL, .tokens = { (void *)&cmd_createbonded_device_create, (void *)&cmd_createbonded_device_bonded, (void *)&cmd_createbonded_device_device, (void *)&cmd_createbonded_device_mode, (void *)&cmd_createbonded_device_socket, NULL } }; /* *** SET MAC ADDRESS IN BONDED DEVICE *** */ struct cmd_set_bond_mac_addr_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bonding; cmdline_fixed_string_t mac_addr; uint8_t port_num; struct ether_addr address; }; static void cmd_set_bond_mac_addr_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bond_mac_addr_result *res = parsed_result; int ret; if (port_id_is_invalid(res->port_num, ENABLED_WARN)) return; ret = rte_eth_bond_mac_address_set(res->port_num, &res->address); /* check the return value and print it if is < 0 */ if (ret < 0) printf("set_bond_mac_addr error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_set_bond_mac_addr_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, set, "set"); cmdline_parse_token_string_t cmd_set_bond_mac_addr_bonding = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_set_bond_mac_addr_mac = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, mac_addr, "mac_addr"); cmdline_parse_token_num_t cmd_set_bond_mac_addr_portnum = TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mac_addr_result, port_num, UINT8); cmdline_parse_token_etheraddr_t cmd_set_bond_mac_addr_addr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_bond_mac_addr_result, address); cmdline_parse_inst_t cmd_set_bond_mac_addr = { .f = cmd_set_bond_mac_addr_parsed, .data = (void *) 0, .help_str = "set bonding mac_addr (port_id) (address): ", .tokens = { (void *)&cmd_set_bond_mac_addr_set, (void *)&cmd_set_bond_mac_addr_bonding, (void *)&cmd_set_bond_mac_addr_mac, (void *)&cmd_set_bond_mac_addr_portnum, (void *)&cmd_set_bond_mac_addr_addr, NULL } }; /* *** SET LINK STATUS MONITORING POLLING PERIOD ON BONDED DEVICE *** */ struct cmd_set_bond_mon_period_result { cmdline_fixed_string_t set; cmdline_fixed_string_t bonding; cmdline_fixed_string_t mon_period; uint8_t port_num; uint32_t period_ms; }; static void cmd_set_bond_mon_period_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_bond_mon_period_result *res = parsed_result; int ret; if (res->port_num >= nb_ports) { printf("Port id %d must be less than %d\n", res->port_num, nb_ports); return; } ret = rte_eth_bond_link_monitoring_set(res->port_num, res->period_ms); /* check the return value and print it if is < 0 */ if (ret < 0) printf("set_bond_mac_addr error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_set_bond_mon_period_set = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result, set, "set"); cmdline_parse_token_string_t cmd_set_bond_mon_period_bonding = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result, bonding, "bonding"); cmdline_parse_token_string_t cmd_set_bond_mon_period_mon_period = TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result, mon_period, "mon_period"); cmdline_parse_token_num_t cmd_set_bond_mon_period_portnum = TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result, port_num, UINT8); cmdline_parse_token_num_t cmd_set_bond_mon_period_period_ms = TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result, period_ms, UINT32); cmdline_parse_inst_t cmd_set_bond_mon_period = { .f = cmd_set_bond_mon_period_parsed, .data = (void *) 0, .help_str = "set bonding mon_period (port_id) (period_ms): ", .tokens = { (void *)&cmd_set_bond_mon_period_set, (void *)&cmd_set_bond_mon_period_bonding, (void *)&cmd_set_bond_mon_period_mon_period, (void *)&cmd_set_bond_mon_period_portnum, (void *)&cmd_set_bond_mon_period_period_ms, NULL } }; #endif /* RTE_LIBRTE_PMD_BOND */ /* *** SET FORWARDING MODE *** */ struct cmd_set_fwd_mode_result { cmdline_fixed_string_t set; cmdline_fixed_string_t fwd; cmdline_fixed_string_t mode; }; static void cmd_set_fwd_mode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_fwd_mode_result *res = parsed_result; set_pkt_forwarding_mode(res->mode); } cmdline_parse_token_string_t cmd_setfwd_set = TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, set, "set"); cmdline_parse_token_string_t cmd_setfwd_fwd = TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, fwd, "fwd"); cmdline_parse_token_string_t cmd_setfwd_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, mode, "" /* defined at init */); cmdline_parse_inst_t cmd_set_fwd_mode = { .f = cmd_set_fwd_mode_parsed, .data = NULL, .help_str = NULL, /* defined at init */ .tokens = { (void *)&cmd_setfwd_set, (void *)&cmd_setfwd_fwd, (void *)&cmd_setfwd_mode, NULL, }, }; static void cmd_set_fwd_mode_init(void) { char *modes, *c; static char token[128]; static char help[256]; cmdline_parse_token_string_t *token_struct; modes = list_pkt_forwarding_modes(); snprintf(help, sizeof help, "set fwd %s - " "set packet forwarding mode", modes); cmd_set_fwd_mode.help_str = help; /* string token separator is # */ for (c = token; *modes != '\0'; modes++) if (*modes == '|') *c++ = '#'; else *c++ = *modes; token_struct = (cmdline_parse_token_string_t*)cmd_set_fwd_mode.tokens[2]; token_struct->string_data.str = token; } /* *** SET BURST TX DELAY TIME RETRY NUMBER *** */ struct cmd_set_burst_tx_retry_result { cmdline_fixed_string_t set; cmdline_fixed_string_t burst; cmdline_fixed_string_t tx; cmdline_fixed_string_t delay; uint32_t time; cmdline_fixed_string_t retry; uint32_t retry_num; }; static void cmd_set_burst_tx_retry_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_burst_tx_retry_result *res = parsed_result; if (!strcmp(res->set, "set") && !strcmp(res->burst, "burst") && !strcmp(res->tx, "tx")) { if (!strcmp(res->delay, "delay")) burst_tx_delay_time = res->time; if (!strcmp(res->retry, "retry")) burst_tx_retry_num = res->retry_num; } } cmdline_parse_token_string_t cmd_set_burst_tx_retry_set = TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, set, "set"); cmdline_parse_token_string_t cmd_set_burst_tx_retry_burst = TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, burst, "burst"); cmdline_parse_token_string_t cmd_set_burst_tx_retry_tx = TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, tx, "tx"); cmdline_parse_token_string_t cmd_set_burst_tx_retry_delay = TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, delay, "delay"); cmdline_parse_token_num_t cmd_set_burst_tx_retry_time = TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, time, UINT32); cmdline_parse_token_string_t cmd_set_burst_tx_retry_retry = TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry, "retry"); cmdline_parse_token_num_t cmd_set_burst_tx_retry_retry_num = TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry_num, UINT32); cmdline_parse_inst_t cmd_set_burst_tx_retry = { .f = cmd_set_burst_tx_retry_parsed, .help_str = "set burst tx delay (time_by_useconds) retry (retry_num)", .tokens = { (void *)&cmd_set_burst_tx_retry_set, (void *)&cmd_set_burst_tx_retry_burst, (void *)&cmd_set_burst_tx_retry_tx, (void *)&cmd_set_burst_tx_retry_delay, (void *)&cmd_set_burst_tx_retry_time, (void *)&cmd_set_burst_tx_retry_retry, (void *)&cmd_set_burst_tx_retry_retry_num, NULL, }, }; /* *** SET PROMISC MODE *** */ struct cmd_set_promisc_mode_result { cmdline_fixed_string_t set; cmdline_fixed_string_t promisc; cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */ uint8_t port_num; /* valid if "allports" argument == 0 */ cmdline_fixed_string_t mode; }; static void cmd_set_promisc_mode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *allports) { struct cmd_set_promisc_mode_result *res = parsed_result; int enable; portid_t i; if (!strcmp(res->mode, "on")) enable = 1; else enable = 0; /* all ports */ if (allports) { FOREACH_PORT(i, ports) { if (enable) rte_eth_promiscuous_enable(i); else rte_eth_promiscuous_disable(i); } } else { if (enable) rte_eth_promiscuous_enable(res->port_num); else rte_eth_promiscuous_disable(res->port_num); } } cmdline_parse_token_string_t cmd_setpromisc_set = TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, set, "set"); cmdline_parse_token_string_t cmd_setpromisc_promisc = TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, promisc, "promisc"); cmdline_parse_token_string_t cmd_setpromisc_portall = TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, port_all, "all"); cmdline_parse_token_num_t cmd_setpromisc_portnum = TOKEN_NUM_INITIALIZER(struct cmd_set_promisc_mode_result, port_num, UINT8); cmdline_parse_token_string_t cmd_setpromisc_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, mode, "on#off"); cmdline_parse_inst_t cmd_set_promisc_mode_all = { .f = cmd_set_promisc_mode_parsed, .data = (void *)1, .help_str = "set promisc all on|off: set promisc mode for all ports", .tokens = { (void *)&cmd_setpromisc_set, (void *)&cmd_setpromisc_promisc, (void *)&cmd_setpromisc_portall, (void *)&cmd_setpromisc_mode, NULL, }, }; cmdline_parse_inst_t cmd_set_promisc_mode_one = { .f = cmd_set_promisc_mode_parsed, .data = (void *)0, .help_str = "set promisc X on|off: set promisc mode on port X", .tokens = { (void *)&cmd_setpromisc_set, (void *)&cmd_setpromisc_promisc, (void *)&cmd_setpromisc_portnum, (void *)&cmd_setpromisc_mode, NULL, }, }; /* *** SET ALLMULTI MODE *** */ struct cmd_set_allmulti_mode_result { cmdline_fixed_string_t set; cmdline_fixed_string_t allmulti; cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */ uint8_t port_num; /* valid if "allports" argument == 0 */ cmdline_fixed_string_t mode; }; static void cmd_set_allmulti_mode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *allports) { struct cmd_set_allmulti_mode_result *res = parsed_result; int enable; portid_t i; if (!strcmp(res->mode, "on")) enable = 1; else enable = 0; /* all ports */ if (allports) { FOREACH_PORT(i, ports) { if (enable) rte_eth_allmulticast_enable(i); else rte_eth_allmulticast_disable(i); } } else { if (enable) rte_eth_allmulticast_enable(res->port_num); else rte_eth_allmulticast_disable(res->port_num); } } cmdline_parse_token_string_t cmd_setallmulti_set = TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, set, "set"); cmdline_parse_token_string_t cmd_setallmulti_allmulti = TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, allmulti, "allmulti"); cmdline_parse_token_string_t cmd_setallmulti_portall = TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, port_all, "all"); cmdline_parse_token_num_t cmd_setallmulti_portnum = TOKEN_NUM_INITIALIZER(struct cmd_set_allmulti_mode_result, port_num, UINT8); cmdline_parse_token_string_t cmd_setallmulti_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, mode, "on#off"); cmdline_parse_inst_t cmd_set_allmulti_mode_all = { .f = cmd_set_allmulti_mode_parsed, .data = (void *)1, .help_str = "set allmulti all on|off: set allmulti mode for all ports", .tokens = { (void *)&cmd_setallmulti_set, (void *)&cmd_setallmulti_allmulti, (void *)&cmd_setallmulti_portall, (void *)&cmd_setallmulti_mode, NULL, }, }; cmdline_parse_inst_t cmd_set_allmulti_mode_one = { .f = cmd_set_allmulti_mode_parsed, .data = (void *)0, .help_str = "set allmulti X on|off: set allmulti mode on port X", .tokens = { (void *)&cmd_setallmulti_set, (void *)&cmd_setallmulti_allmulti, (void *)&cmd_setallmulti_portnum, (void *)&cmd_setallmulti_mode, NULL, }, }; /* *** SETUP ETHERNET LINK FLOW CONTROL *** */ struct cmd_link_flow_ctrl_set_result { cmdline_fixed_string_t set; cmdline_fixed_string_t flow_ctrl; cmdline_fixed_string_t rx; cmdline_fixed_string_t rx_lfc_mode; cmdline_fixed_string_t tx; cmdline_fixed_string_t tx_lfc_mode; cmdline_fixed_string_t mac_ctrl_frame_fwd; cmdline_fixed_string_t mac_ctrl_frame_fwd_mode; cmdline_fixed_string_t autoneg_str; cmdline_fixed_string_t autoneg; cmdline_fixed_string_t hw_str; uint32_t high_water; cmdline_fixed_string_t lw_str; uint32_t low_water; cmdline_fixed_string_t pt_str; uint16_t pause_time; cmdline_fixed_string_t xon_str; uint16_t send_xon; uint8_t port_id; }; cmdline_parse_token_string_t cmd_lfc_set_set = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, set, "set"); cmdline_parse_token_string_t cmd_lfc_set_flow_ctrl = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, flow_ctrl, "flow_ctrl"); cmdline_parse_token_string_t cmd_lfc_set_rx = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, rx, "rx"); cmdline_parse_token_string_t cmd_lfc_set_rx_mode = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, rx_lfc_mode, "on#off"); cmdline_parse_token_string_t cmd_lfc_set_tx = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, tx, "tx"); cmdline_parse_token_string_t cmd_lfc_set_tx_mode = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, tx_lfc_mode, "on#off"); cmdline_parse_token_string_t cmd_lfc_set_high_water_str = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, hw_str, "high_water"); cmdline_parse_token_num_t cmd_lfc_set_high_water = TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result, high_water, UINT32); cmdline_parse_token_string_t cmd_lfc_set_low_water_str = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, lw_str, "low_water"); cmdline_parse_token_num_t cmd_lfc_set_low_water = TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result, low_water, UINT32); cmdline_parse_token_string_t cmd_lfc_set_pause_time_str = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, pt_str, "pause_time"); cmdline_parse_token_num_t cmd_lfc_set_pause_time = TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result, pause_time, UINT16); cmdline_parse_token_string_t cmd_lfc_set_send_xon_str = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, xon_str, "send_xon"); cmdline_parse_token_num_t cmd_lfc_set_send_xon = TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result, send_xon, UINT16); cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd_mode = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, mac_ctrl_frame_fwd, "mac_ctrl_frame_fwd"); cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, mac_ctrl_frame_fwd_mode, "on#off"); cmdline_parse_token_string_t cmd_lfc_set_autoneg_str = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, autoneg_str, "autoneg"); cmdline_parse_token_string_t cmd_lfc_set_autoneg = TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result, autoneg, "on#off"); cmdline_parse_token_num_t cmd_lfc_set_portid = TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result, port_id, UINT8); /* forward declaration */ static void cmd_link_flow_ctrl_set_parsed(void *parsed_result, struct cmdline *cl, void *data); cmdline_parse_inst_t cmd_link_flow_control_set = { .f = cmd_link_flow_ctrl_set_parsed, .data = NULL, .help_str = "Configure the Ethernet flow control: set flow_ctrl rx on|off \ tx on|off high_water low_water pause_time send_xon mac_ctrl_frame_fwd on|off \ autoneg on|off port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_rx, (void *)&cmd_lfc_set_rx_mode, (void *)&cmd_lfc_set_tx, (void *)&cmd_lfc_set_tx_mode, (void *)&cmd_lfc_set_high_water, (void *)&cmd_lfc_set_low_water, (void *)&cmd_lfc_set_pause_time, (void *)&cmd_lfc_set_send_xon, (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode, (void *)&cmd_lfc_set_mac_ctrl_frame_fwd, (void *)&cmd_lfc_set_autoneg_str, (void *)&cmd_lfc_set_autoneg, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_rx = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_rx, .help_str = "Change rx flow control parameter: set flow_ctrl " "rx on|off port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_rx, (void *)&cmd_lfc_set_rx_mode, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_tx = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_tx, .help_str = "Change tx flow control parameter: set flow_ctrl " "tx on|off port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_tx, (void *)&cmd_lfc_set_tx_mode, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_hw = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_hw, .help_str = "Change high water flow control parameter: set flow_ctrl " "high_water value port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_high_water_str, (void *)&cmd_lfc_set_high_water, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_lw = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_lw, .help_str = "Change low water flow control parameter: set flow_ctrl " "low_water value port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_low_water_str, (void *)&cmd_lfc_set_low_water, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_pt = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_pt, .help_str = "Change pause time flow control parameter: set flow_ctrl " "pause_time value port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_pause_time_str, (void *)&cmd_lfc_set_pause_time, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_xon = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_xon, .help_str = "Change send_xon flow control parameter: set flow_ctrl " "send_xon value port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_send_xon_str, (void *)&cmd_lfc_set_send_xon, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_macfwd = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_macfwd, .help_str = "Change mac ctrl fwd flow control parameter: set flow_ctrl " "mac_ctrl_frame_fwd on|off port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode, (void *)&cmd_lfc_set_mac_ctrl_frame_fwd, (void *)&cmd_lfc_set_portid, NULL, }, }; cmdline_parse_inst_t cmd_link_flow_control_set_autoneg = { .f = cmd_link_flow_ctrl_set_parsed, .data = (void *)&cmd_link_flow_control_set_autoneg, .help_str = "Change autoneg flow control parameter: set flow_ctrl " "autoneg on|off port_id", .tokens = { (void *)&cmd_lfc_set_set, (void *)&cmd_lfc_set_flow_ctrl, (void *)&cmd_lfc_set_autoneg_str, (void *)&cmd_lfc_set_autoneg, (void *)&cmd_lfc_set_portid, NULL, }, }; static void cmd_link_flow_ctrl_set_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_link_flow_ctrl_set_result *res = parsed_result; cmdline_parse_inst_t *cmd = data; struct rte_eth_fc_conf fc_conf; int rx_fc_en = 0; int tx_fc_en = 0; int ret; /* * Rx on/off, flow control is enabled/disabled on RX side. This can indicate * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side. * Tx on/off, flow control is enabled/disabled on TX side. This can indicate * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side. */ static enum rte_eth_fc_mode rx_tx_onoff_2_lfc_mode[2][2] = { {RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL} }; /* Partial command line, retrieve current configuration */ if (cmd) { ret = rte_eth_dev_flow_ctrl_get(res->port_id, &fc_conf); if (ret != 0) { printf("cannot get current flow ctrl parameters, return" "code = %d\n", ret); return; } if ((fc_conf.mode == RTE_FC_RX_PAUSE) || (fc_conf.mode == RTE_FC_FULL)) rx_fc_en = 1; if ((fc_conf.mode == RTE_FC_TX_PAUSE) || (fc_conf.mode == RTE_FC_FULL)) tx_fc_en = 1; } if (!cmd || cmd == &cmd_link_flow_control_set_rx) rx_fc_en = (!strcmp(res->rx_lfc_mode, "on")) ? 1 : 0; if (!cmd || cmd == &cmd_link_flow_control_set_tx) tx_fc_en = (!strcmp(res->tx_lfc_mode, "on")) ? 1 : 0; fc_conf.mode = rx_tx_onoff_2_lfc_mode[rx_fc_en][tx_fc_en]; if (!cmd || cmd == &cmd_link_flow_control_set_hw) fc_conf.high_water = res->high_water; if (!cmd || cmd == &cmd_link_flow_control_set_lw) fc_conf.low_water = res->low_water; if (!cmd || cmd == &cmd_link_flow_control_set_pt) fc_conf.pause_time = res->pause_time; if (!cmd || cmd == &cmd_link_flow_control_set_xon) fc_conf.send_xon = res->send_xon; if (!cmd || cmd == &cmd_link_flow_control_set_macfwd) { if (!strcmp(res->mac_ctrl_frame_fwd_mode, "on")) fc_conf.mac_ctrl_frame_fwd = 1; else fc_conf.mac_ctrl_frame_fwd = 0; } if (!cmd || cmd == &cmd_link_flow_control_set_autoneg) fc_conf.autoneg = (!strcmp(res->autoneg, "on")) ? 1 : 0; ret = rte_eth_dev_flow_ctrl_set(res->port_id, &fc_conf); if (ret != 0) printf("bad flow contrl parameter, return code = %d \n", ret); } /* *** SETUP ETHERNET PIRORITY FLOW CONTROL *** */ struct cmd_priority_flow_ctrl_set_result { cmdline_fixed_string_t set; cmdline_fixed_string_t pfc_ctrl; cmdline_fixed_string_t rx; cmdline_fixed_string_t rx_pfc_mode; cmdline_fixed_string_t tx; cmdline_fixed_string_t tx_pfc_mode; uint32_t high_water; uint32_t low_water; uint16_t pause_time; uint8_t priority; uint8_t port_id; }; static void cmd_priority_flow_ctrl_set_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_priority_flow_ctrl_set_result *res = parsed_result; struct rte_eth_pfc_conf pfc_conf; int rx_fc_enable, tx_fc_enable; int ret; /* * Rx on/off, flow control is enabled/disabled on RX side. This can indicate * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side. * Tx on/off, flow control is enabled/disabled on TX side. This can indicate * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side. */ static enum rte_eth_fc_mode rx_tx_onoff_2_pfc_mode[2][2] = { {RTE_FC_NONE, RTE_FC_RX_PAUSE}, {RTE_FC_TX_PAUSE, RTE_FC_FULL} }; rx_fc_enable = (!strncmp(res->rx_pfc_mode, "on",2)) ? 1 : 0; tx_fc_enable = (!strncmp(res->tx_pfc_mode, "on",2)) ? 1 : 0; pfc_conf.fc.mode = rx_tx_onoff_2_pfc_mode[rx_fc_enable][tx_fc_enable]; pfc_conf.fc.high_water = res->high_water; pfc_conf.fc.low_water = res->low_water; pfc_conf.fc.pause_time = res->pause_time; pfc_conf.priority = res->priority; ret = rte_eth_dev_priority_flow_ctrl_set(res->port_id, &pfc_conf); if (ret != 0) printf("bad priority flow contrl parameter, return code = %d \n", ret); } cmdline_parse_token_string_t cmd_pfc_set_set = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, set, "set"); cmdline_parse_token_string_t cmd_pfc_set_flow_ctrl = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, pfc_ctrl, "pfc_ctrl"); cmdline_parse_token_string_t cmd_pfc_set_rx = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, rx, "rx"); cmdline_parse_token_string_t cmd_pfc_set_rx_mode = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, rx_pfc_mode, "on#off"); cmdline_parse_token_string_t cmd_pfc_set_tx = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, tx, "tx"); cmdline_parse_token_string_t cmd_pfc_set_tx_mode = TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, tx_pfc_mode, "on#off"); cmdline_parse_token_num_t cmd_pfc_set_high_water = TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, high_water, UINT32); cmdline_parse_token_num_t cmd_pfc_set_low_water = TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, low_water, UINT32); cmdline_parse_token_num_t cmd_pfc_set_pause_time = TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, pause_time, UINT16); cmdline_parse_token_num_t cmd_pfc_set_priority = TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, priority, UINT8); cmdline_parse_token_num_t cmd_pfc_set_portid = TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result, port_id, UINT8); cmdline_parse_inst_t cmd_priority_flow_control_set = { .f = cmd_priority_flow_ctrl_set_parsed, .data = NULL, .help_str = "Configure the Ethernet priority flow control: set pfc_ctrl rx on|off\n\ tx on|off high_water low_water pause_time priority port_id", .tokens = { (void *)&cmd_pfc_set_set, (void *)&cmd_pfc_set_flow_ctrl, (void *)&cmd_pfc_set_rx, (void *)&cmd_pfc_set_rx_mode, (void *)&cmd_pfc_set_tx, (void *)&cmd_pfc_set_tx_mode, (void *)&cmd_pfc_set_high_water, (void *)&cmd_pfc_set_low_water, (void *)&cmd_pfc_set_pause_time, (void *)&cmd_pfc_set_priority, (void *)&cmd_pfc_set_portid, NULL, }, }; /* *** RESET CONFIGURATION *** */ struct cmd_reset_result { cmdline_fixed_string_t reset; cmdline_fixed_string_t def; }; static void cmd_reset_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Reset to default forwarding configuration...\n"); set_def_fwd_config(); } cmdline_parse_token_string_t cmd_reset_set = TOKEN_STRING_INITIALIZER(struct cmd_reset_result, reset, "set"); cmdline_parse_token_string_t cmd_reset_def = TOKEN_STRING_INITIALIZER(struct cmd_reset_result, def, "default"); cmdline_parse_inst_t cmd_reset = { .f = cmd_reset_parsed, .data = NULL, .help_str = "set default: reset default forwarding configuration", .tokens = { (void *)&cmd_reset_set, (void *)&cmd_reset_def, NULL, }, }; /* *** START FORWARDING *** */ struct cmd_start_result { cmdline_fixed_string_t start; }; cmdline_parse_token_string_t cmd_start_start = TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start"); static void cmd_start_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { start_packet_forwarding(0); } cmdline_parse_inst_t cmd_start = { .f = cmd_start_parsed, .data = NULL, .help_str = "start packet forwarding", .tokens = { (void *)&cmd_start_start, NULL, }, }; /* *** START FORWARDING WITH ONE TX BURST FIRST *** */ struct cmd_start_tx_first_result { cmdline_fixed_string_t start; cmdline_fixed_string_t tx_first; }; static void cmd_start_tx_first_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { start_packet_forwarding(1); } cmdline_parse_token_string_t cmd_start_tx_first_start = TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result, start, "start"); cmdline_parse_token_string_t cmd_start_tx_first_tx_first = TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result, tx_first, "tx_first"); cmdline_parse_inst_t cmd_start_tx_first = { .f = cmd_start_tx_first_parsed, .data = NULL, .help_str = "start packet forwarding, after sending 1 burst of packets", .tokens = { (void *)&cmd_start_tx_first_start, (void *)&cmd_start_tx_first_tx_first, NULL, }, }; /* *** SET LINK UP *** */ struct cmd_set_link_up_result { cmdline_fixed_string_t set; cmdline_fixed_string_t link_up; cmdline_fixed_string_t port; uint8_t port_id; }; cmdline_parse_token_string_t cmd_set_link_up_set = TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, set, "set"); cmdline_parse_token_string_t cmd_set_link_up_link_up = TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, link_up, "link-up"); cmdline_parse_token_string_t cmd_set_link_up_port = TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, port, "port"); cmdline_parse_token_num_t cmd_set_link_up_port_id = TOKEN_NUM_INITIALIZER(struct cmd_set_link_up_result, port_id, UINT8); static void cmd_set_link_up_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_link_up_result *res = parsed_result; dev_set_link_up(res->port_id); } cmdline_parse_inst_t cmd_set_link_up = { .f = cmd_set_link_up_parsed, .data = NULL, .help_str = "set link-up port (port id)", .tokens = { (void *)&cmd_set_link_up_set, (void *)&cmd_set_link_up_link_up, (void *)&cmd_set_link_up_port, (void *)&cmd_set_link_up_port_id, NULL, }, }; /* *** SET LINK DOWN *** */ struct cmd_set_link_down_result { cmdline_fixed_string_t set; cmdline_fixed_string_t link_down; cmdline_fixed_string_t port; uint8_t port_id; }; cmdline_parse_token_string_t cmd_set_link_down_set = TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, set, "set"); cmdline_parse_token_string_t cmd_set_link_down_link_down = TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, link_down, "link-down"); cmdline_parse_token_string_t cmd_set_link_down_port = TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, port, "port"); cmdline_parse_token_num_t cmd_set_link_down_port_id = TOKEN_NUM_INITIALIZER(struct cmd_set_link_down_result, port_id, UINT8); static void cmd_set_link_down_parsed( __attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_link_down_result *res = parsed_result; dev_set_link_down(res->port_id); } cmdline_parse_inst_t cmd_set_link_down = { .f = cmd_set_link_down_parsed, .data = NULL, .help_str = "set link-down port (port id)", .tokens = { (void *)&cmd_set_link_down_set, (void *)&cmd_set_link_down_link_down, (void *)&cmd_set_link_down_port, (void *)&cmd_set_link_down_port_id, NULL, }, }; /* *** SHOW CFG *** */ struct cmd_showcfg_result { cmdline_fixed_string_t show; cmdline_fixed_string_t cfg; cmdline_fixed_string_t what; }; static void cmd_showcfg_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_showcfg_result *res = parsed_result; if (!strcmp(res->what, "rxtx")) rxtx_config_display(); else if (!strcmp(res->what, "cores")) fwd_lcores_config_display(); else if (!strcmp(res->what, "fwd")) fwd_config_display(); } cmdline_parse_token_string_t cmd_showcfg_show = TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, show, "show"); cmdline_parse_token_string_t cmd_showcfg_port = TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, cfg, "config"); cmdline_parse_token_string_t cmd_showcfg_what = TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, what, "rxtx#cores#fwd"); cmdline_parse_inst_t cmd_showcfg = { .f = cmd_showcfg_parsed, .data = NULL, .help_str = "show config rxtx|cores|fwd", .tokens = { (void *)&cmd_showcfg_show, (void *)&cmd_showcfg_port, (void *)&cmd_showcfg_what, NULL, }, }; /* *** SHOW ALL PORT INFO *** */ struct cmd_showportall_result { cmdline_fixed_string_t show; cmdline_fixed_string_t port; cmdline_fixed_string_t what; cmdline_fixed_string_t all; }; static void cmd_showportall_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { portid_t i; struct cmd_showportall_result *res = parsed_result; if (!strcmp(res->show, "clear")) { if (!strcmp(res->what, "stats")) FOREACH_PORT(i, ports) nic_stats_clear(i); else if (!strcmp(res->what, "xstats")) FOREACH_PORT(i, ports) nic_xstats_clear(i); } else if (!strcmp(res->what, "info")) FOREACH_PORT(i, ports) port_infos_display(i); else if (!strcmp(res->what, "stats")) FOREACH_PORT(i, ports) nic_stats_display(i); else if (!strcmp(res->what, "xstats")) FOREACH_PORT(i, ports) nic_xstats_display(i); else if (!strcmp(res->what, "fdir")) FOREACH_PORT(i, ports) fdir_get_infos(i); else if (!strcmp(res->what, "stat_qmap")) FOREACH_PORT(i, ports) nic_stats_mapping_display(i); } cmdline_parse_token_string_t cmd_showportall_show = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, show, "show#clear"); cmdline_parse_token_string_t cmd_showportall_port = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, port, "port"); cmdline_parse_token_string_t cmd_showportall_what = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, what, "info#stats#xstats#fdir#stat_qmap"); cmdline_parse_token_string_t cmd_showportall_all = TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, all, "all"); cmdline_parse_inst_t cmd_showportall = { .f = cmd_showportall_parsed, .data = NULL, .help_str = "show|clear port info|stats|xstats|fdir|stat_qmap all", .tokens = { (void *)&cmd_showportall_show, (void *)&cmd_showportall_port, (void *)&cmd_showportall_what, (void *)&cmd_showportall_all, NULL, }, }; /* *** SHOW PORT INFO *** */ struct cmd_showport_result { cmdline_fixed_string_t show; cmdline_fixed_string_t port; cmdline_fixed_string_t what; uint8_t portnum; }; static void cmd_showport_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_showport_result *res = parsed_result; if (!strcmp(res->show, "clear")) { if (!strcmp(res->what, "stats")) nic_stats_clear(res->portnum); else if (!strcmp(res->what, "xstats")) nic_xstats_clear(res->portnum); } else if (!strcmp(res->what, "info")) port_infos_display(res->portnum); else if (!strcmp(res->what, "stats")) nic_stats_display(res->portnum); else if (!strcmp(res->what, "xstats")) nic_xstats_display(res->portnum); else if (!strcmp(res->what, "fdir")) fdir_get_infos(res->portnum); else if (!strcmp(res->what, "stat_qmap")) nic_stats_mapping_display(res->portnum); } cmdline_parse_token_string_t cmd_showport_show = TOKEN_STRING_INITIALIZER(struct cmd_showport_result, show, "show#clear"); cmdline_parse_token_string_t cmd_showport_port = TOKEN_STRING_INITIALIZER(struct cmd_showport_result, port, "port"); cmdline_parse_token_string_t cmd_showport_what = TOKEN_STRING_INITIALIZER(struct cmd_showport_result, what, "info#stats#xstats#fdir#stat_qmap"); cmdline_parse_token_num_t cmd_showport_portnum = TOKEN_NUM_INITIALIZER(struct cmd_showport_result, portnum, UINT8); cmdline_parse_inst_t cmd_showport = { .f = cmd_showport_parsed, .data = NULL, .help_str = "show|clear port info|stats|xstats|fdir|stat_qmap X (X = port number)", .tokens = { (void *)&cmd_showport_show, (void *)&cmd_showport_port, (void *)&cmd_showport_what, (void *)&cmd_showport_portnum, NULL, }, }; /* *** READ PORT REGISTER *** */ struct cmd_read_reg_result { cmdline_fixed_string_t read; cmdline_fixed_string_t reg; uint8_t port_id; uint32_t reg_off; }; static void cmd_read_reg_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_read_reg_result *res = parsed_result; port_reg_display(res->port_id, res->reg_off); } cmdline_parse_token_string_t cmd_read_reg_read = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, read, "read"); cmdline_parse_token_string_t cmd_read_reg_reg = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, reg, "reg"); cmdline_parse_token_num_t cmd_read_reg_port_id = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, port_id, UINT8); cmdline_parse_token_num_t cmd_read_reg_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, reg_off, UINT32); cmdline_parse_inst_t cmd_read_reg = { .f = cmd_read_reg_parsed, .data = NULL, .help_str = "read reg port_id reg_off", .tokens = { (void *)&cmd_read_reg_read, (void *)&cmd_read_reg_reg, (void *)&cmd_read_reg_port_id, (void *)&cmd_read_reg_reg_off, NULL, }, }; /* *** READ PORT REGISTER BIT FIELD *** */ struct cmd_read_reg_bit_field_result { cmdline_fixed_string_t read; cmdline_fixed_string_t regfield; uint8_t port_id; uint32_t reg_off; uint8_t bit1_pos; uint8_t bit2_pos; }; static void cmd_read_reg_bit_field_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_read_reg_bit_field_result *res = parsed_result; port_reg_bit_field_display(res->port_id, res->reg_off, res->bit1_pos, res->bit2_pos); } cmdline_parse_token_string_t cmd_read_reg_bit_field_read = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result, read, "read"); cmdline_parse_token_string_t cmd_read_reg_bit_field_regfield = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result, regfield, "regfield"); cmdline_parse_token_num_t cmd_read_reg_bit_field_port_id = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, port_id, UINT8); cmdline_parse_token_num_t cmd_read_reg_bit_field_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, reg_off, UINT32); cmdline_parse_token_num_t cmd_read_reg_bit_field_bit1_pos = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit1_pos, UINT8); cmdline_parse_token_num_t cmd_read_reg_bit_field_bit2_pos = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit2_pos, UINT8); cmdline_parse_inst_t cmd_read_reg_bit_field = { .f = cmd_read_reg_bit_field_parsed, .data = NULL, .help_str = "read regfield port_id reg_off bit_x bit_y " "(read register bit field between bit_x and bit_y included)", .tokens = { (void *)&cmd_read_reg_bit_field_read, (void *)&cmd_read_reg_bit_field_regfield, (void *)&cmd_read_reg_bit_field_port_id, (void *)&cmd_read_reg_bit_field_reg_off, (void *)&cmd_read_reg_bit_field_bit1_pos, (void *)&cmd_read_reg_bit_field_bit2_pos, NULL, }, }; /* *** READ PORT REGISTER BIT *** */ struct cmd_read_reg_bit_result { cmdline_fixed_string_t read; cmdline_fixed_string_t regbit; uint8_t port_id; uint32_t reg_off; uint8_t bit_pos; }; static void cmd_read_reg_bit_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_read_reg_bit_result *res = parsed_result; port_reg_bit_display(res->port_id, res->reg_off, res->bit_pos); } cmdline_parse_token_string_t cmd_read_reg_bit_read = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result, read, "read"); cmdline_parse_token_string_t cmd_read_reg_bit_regbit = TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result, regbit, "regbit"); cmdline_parse_token_num_t cmd_read_reg_bit_port_id = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, port_id, UINT8); cmdline_parse_token_num_t cmd_read_reg_bit_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, reg_off, UINT32); cmdline_parse_token_num_t cmd_read_reg_bit_bit_pos = TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, bit_pos, UINT8); cmdline_parse_inst_t cmd_read_reg_bit = { .f = cmd_read_reg_bit_parsed, .data = NULL, .help_str = "read regbit port_id reg_off bit_x (0 <= bit_x <= 31)", .tokens = { (void *)&cmd_read_reg_bit_read, (void *)&cmd_read_reg_bit_regbit, (void *)&cmd_read_reg_bit_port_id, (void *)&cmd_read_reg_bit_reg_off, (void *)&cmd_read_reg_bit_bit_pos, NULL, }, }; /* *** WRITE PORT REGISTER *** */ struct cmd_write_reg_result { cmdline_fixed_string_t write; cmdline_fixed_string_t reg; uint8_t port_id; uint32_t reg_off; uint32_t value; }; static void cmd_write_reg_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_write_reg_result *res = parsed_result; port_reg_set(res->port_id, res->reg_off, res->value); } cmdline_parse_token_string_t cmd_write_reg_write = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, write, "write"); cmdline_parse_token_string_t cmd_write_reg_reg = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, reg, "reg"); cmdline_parse_token_num_t cmd_write_reg_port_id = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, port_id, UINT8); cmdline_parse_token_num_t cmd_write_reg_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, reg_off, UINT32); cmdline_parse_token_num_t cmd_write_reg_value = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, value, UINT32); cmdline_parse_inst_t cmd_write_reg = { .f = cmd_write_reg_parsed, .data = NULL, .help_str = "write reg port_id reg_off reg_value", .tokens = { (void *)&cmd_write_reg_write, (void *)&cmd_write_reg_reg, (void *)&cmd_write_reg_port_id, (void *)&cmd_write_reg_reg_off, (void *)&cmd_write_reg_value, NULL, }, }; /* *** WRITE PORT REGISTER BIT FIELD *** */ struct cmd_write_reg_bit_field_result { cmdline_fixed_string_t write; cmdline_fixed_string_t regfield; uint8_t port_id; uint32_t reg_off; uint8_t bit1_pos; uint8_t bit2_pos; uint32_t value; }; static void cmd_write_reg_bit_field_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_write_reg_bit_field_result *res = parsed_result; port_reg_bit_field_set(res->port_id, res->reg_off, res->bit1_pos, res->bit2_pos, res->value); } cmdline_parse_token_string_t cmd_write_reg_bit_field_write = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result, write, "write"); cmdline_parse_token_string_t cmd_write_reg_bit_field_regfield = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result, regfield, "regfield"); cmdline_parse_token_num_t cmd_write_reg_bit_field_port_id = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, port_id, UINT8); cmdline_parse_token_num_t cmd_write_reg_bit_field_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, reg_off, UINT32); cmdline_parse_token_num_t cmd_write_reg_bit_field_bit1_pos = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit1_pos, UINT8); cmdline_parse_token_num_t cmd_write_reg_bit_field_bit2_pos = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit2_pos, UINT8); cmdline_parse_token_num_t cmd_write_reg_bit_field_value = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, value, UINT32); cmdline_parse_inst_t cmd_write_reg_bit_field = { .f = cmd_write_reg_bit_field_parsed, .data = NULL, .help_str = "write regfield port_id reg_off bit_x bit_y reg_value" "(set register bit field between bit_x and bit_y included)", .tokens = { (void *)&cmd_write_reg_bit_field_write, (void *)&cmd_write_reg_bit_field_regfield, (void *)&cmd_write_reg_bit_field_port_id, (void *)&cmd_write_reg_bit_field_reg_off, (void *)&cmd_write_reg_bit_field_bit1_pos, (void *)&cmd_write_reg_bit_field_bit2_pos, (void *)&cmd_write_reg_bit_field_value, NULL, }, }; /* *** WRITE PORT REGISTER BIT *** */ struct cmd_write_reg_bit_result { cmdline_fixed_string_t write; cmdline_fixed_string_t regbit; uint8_t port_id; uint32_t reg_off; uint8_t bit_pos; uint8_t value; }; static void cmd_write_reg_bit_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_write_reg_bit_result *res = parsed_result; port_reg_bit_set(res->port_id, res->reg_off, res->bit_pos, res->value); } cmdline_parse_token_string_t cmd_write_reg_bit_write = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result, write, "write"); cmdline_parse_token_string_t cmd_write_reg_bit_regbit = TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result, regbit, "regbit"); cmdline_parse_token_num_t cmd_write_reg_bit_port_id = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, port_id, UINT8); cmdline_parse_token_num_t cmd_write_reg_bit_reg_off = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, reg_off, UINT32); cmdline_parse_token_num_t cmd_write_reg_bit_bit_pos = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, bit_pos, UINT8); cmdline_parse_token_num_t cmd_write_reg_bit_value = TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, value, UINT8); cmdline_parse_inst_t cmd_write_reg_bit = { .f = cmd_write_reg_bit_parsed, .data = NULL, .help_str = "write regbit port_id reg_off bit_x 0/1 (0 <= bit_x <= 31)", .tokens = { (void *)&cmd_write_reg_bit_write, (void *)&cmd_write_reg_bit_regbit, (void *)&cmd_write_reg_bit_port_id, (void *)&cmd_write_reg_bit_reg_off, (void *)&cmd_write_reg_bit_bit_pos, (void *)&cmd_write_reg_bit_value, NULL, }, }; /* *** READ A RING DESCRIPTOR OF A PORT RX/TX QUEUE *** */ struct cmd_read_rxd_txd_result { cmdline_fixed_string_t read; cmdline_fixed_string_t rxd_txd; uint8_t port_id; uint16_t queue_id; uint16_t desc_id; }; static void cmd_read_rxd_txd_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_read_rxd_txd_result *res = parsed_result; if (!strcmp(res->rxd_txd, "rxd")) rx_ring_desc_display(res->port_id, res->queue_id, res->desc_id); else if (!strcmp(res->rxd_txd, "txd")) tx_ring_desc_display(res->port_id, res->queue_id, res->desc_id); } cmdline_parse_token_string_t cmd_read_rxd_txd_read = TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, read, "read"); cmdline_parse_token_string_t cmd_read_rxd_txd_rxd_txd = TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, rxd_txd, "rxd#txd"); cmdline_parse_token_num_t cmd_read_rxd_txd_port_id = TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, port_id, UINT8); cmdline_parse_token_num_t cmd_read_rxd_txd_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, queue_id, UINT16); cmdline_parse_token_num_t cmd_read_rxd_txd_desc_id = TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, desc_id, UINT16); cmdline_parse_inst_t cmd_read_rxd_txd = { .f = cmd_read_rxd_txd_parsed, .data = NULL, .help_str = "read rxd|txd port_id queue_id rxd_id", .tokens = { (void *)&cmd_read_rxd_txd_read, (void *)&cmd_read_rxd_txd_rxd_txd, (void *)&cmd_read_rxd_txd_port_id, (void *)&cmd_read_rxd_txd_queue_id, (void *)&cmd_read_rxd_txd_desc_id, NULL, }, }; /* *** QUIT *** */ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { pmd_test_exit(); cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, .data = NULL, .help_str = "exit application", .tokens = { (void *)&cmd_quit_quit, NULL, }, }; /* *** ADD/REMOVE MAC ADDRESS FROM A PORT *** */ struct cmd_mac_addr_result { cmdline_fixed_string_t mac_addr_cmd; cmdline_fixed_string_t what; uint8_t port_num; struct ether_addr address; }; static void cmd_mac_addr_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_mac_addr_result *res = parsed_result; int ret; if (strcmp(res->what, "add") == 0) ret = rte_eth_dev_mac_addr_add(res->port_num, &res->address, 0); else ret = rte_eth_dev_mac_addr_remove(res->port_num, &res->address); /* check the return value and print it if is < 0 */ if(ret < 0) printf("mac_addr_cmd error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_mac_addr_cmd = TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, mac_addr_cmd, "mac_addr"); cmdline_parse_token_string_t cmd_mac_addr_what = TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, what, "add#remove"); cmdline_parse_token_num_t cmd_mac_addr_portnum = TOKEN_NUM_INITIALIZER(struct cmd_mac_addr_result, port_num, UINT8); cmdline_parse_token_etheraddr_t cmd_mac_addr_addr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address); cmdline_parse_inst_t cmd_mac_addr = { .f = cmd_mac_addr_parsed, .data = (void *)0, .help_str = "mac_addr add|remove X
: " "add/remove MAC address on port X", .tokens = { (void *)&cmd_mac_addr_cmd, (void *)&cmd_mac_addr_what, (void *)&cmd_mac_addr_portnum, (void *)&cmd_mac_addr_addr, NULL, }, }; /* *** CONFIGURE QUEUE STATS COUNTER MAPPINGS *** */ struct cmd_set_qmap_result { cmdline_fixed_string_t set; cmdline_fixed_string_t qmap; cmdline_fixed_string_t what; uint8_t port_id; uint16_t queue_id; uint8_t map_value; }; static void cmd_set_qmap_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_qmap_result *res = parsed_result; int is_rx = (strcmp(res->what, "tx") == 0) ? 0 : 1; set_qmap(res->port_id, (uint8_t)is_rx, res->queue_id, res->map_value); } cmdline_parse_token_string_t cmd_setqmap_set = TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, set, "set"); cmdline_parse_token_string_t cmd_setqmap_qmap = TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, qmap, "stat_qmap"); cmdline_parse_token_string_t cmd_setqmap_what = TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result, what, "tx#rx"); cmdline_parse_token_num_t cmd_setqmap_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, port_id, UINT8); cmdline_parse_token_num_t cmd_setqmap_queueid = TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, queue_id, UINT16); cmdline_parse_token_num_t cmd_setqmap_mapvalue = TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result, map_value, UINT8); cmdline_parse_inst_t cmd_set_qmap = { .f = cmd_set_qmap_parsed, .data = NULL, .help_str = "Set statistics mapping value on tx|rx queue_id of port_id", .tokens = { (void *)&cmd_setqmap_set, (void *)&cmd_setqmap_qmap, (void *)&cmd_setqmap_what, (void *)&cmd_setqmap_portid, (void *)&cmd_setqmap_queueid, (void *)&cmd_setqmap_mapvalue, NULL, }, }; /* *** CONFIGURE UNICAST HASH TABLE *** */ struct cmd_set_uc_hash_table { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t what; struct ether_addr address; cmdline_fixed_string_t mode; }; static void cmd_set_uc_hash_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret=0; struct cmd_set_uc_hash_table *res = parsed_result; int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0; if (strcmp(res->what, "uta") == 0) ret = rte_eth_dev_uc_hash_table_set(res->port_id, &res->address,(uint8_t)is_on); if (ret < 0) printf("bad unicast hash table parameter, return code = %d \n", ret); } cmdline_parse_token_string_t cmd_set_uc_hash_set = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table, set, "set"); cmdline_parse_token_string_t cmd_set_uc_hash_port = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table, port, "port"); cmdline_parse_token_num_t cmd_set_uc_hash_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_uc_hash_table, port_id, UINT8); cmdline_parse_token_string_t cmd_set_uc_hash_what = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table, what, "uta"); cmdline_parse_token_etheraddr_t cmd_set_uc_hash_mac = TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_uc_hash_table, address); cmdline_parse_token_string_t cmd_set_uc_hash_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table, mode, "on#off"); cmdline_parse_inst_t cmd_set_uc_hash_filter = { .f = cmd_set_uc_hash_parsed, .data = NULL, .help_str = "set port X uta Y on|off(X = port number,Y = MAC address)", .tokens = { (void *)&cmd_set_uc_hash_set, (void *)&cmd_set_uc_hash_port, (void *)&cmd_set_uc_hash_portid, (void *)&cmd_set_uc_hash_what, (void *)&cmd_set_uc_hash_mac, (void *)&cmd_set_uc_hash_mode, NULL, }, }; struct cmd_set_uc_all_hash_table { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t what; cmdline_fixed_string_t value; cmdline_fixed_string_t mode; }; static void cmd_set_uc_all_hash_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret=0; struct cmd_set_uc_all_hash_table *res = parsed_result; int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0; if ((strcmp(res->what, "uta") == 0) && (strcmp(res->value, "all") == 0)) ret = rte_eth_dev_uc_all_hash_table_set(res->port_id,(uint8_t) is_on); if (ret < 0) printf("bad unicast hash table parameter," "return code = %d \n", ret); } cmdline_parse_token_string_t cmd_set_uc_all_hash_set = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table, set, "set"); cmdline_parse_token_string_t cmd_set_uc_all_hash_port = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table, port, "port"); cmdline_parse_token_num_t cmd_set_uc_all_hash_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_uc_all_hash_table, port_id, UINT8); cmdline_parse_token_string_t cmd_set_uc_all_hash_what = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table, what, "uta"); cmdline_parse_token_string_t cmd_set_uc_all_hash_value = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table, value,"all"); cmdline_parse_token_string_t cmd_set_uc_all_hash_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table, mode, "on#off"); cmdline_parse_inst_t cmd_set_uc_all_hash_filter = { .f = cmd_set_uc_all_hash_parsed, .data = NULL, .help_str = "set port X uta all on|off (X = port number)", .tokens = { (void *)&cmd_set_uc_all_hash_set, (void *)&cmd_set_uc_all_hash_port, (void *)&cmd_set_uc_all_hash_portid, (void *)&cmd_set_uc_all_hash_what, (void *)&cmd_set_uc_all_hash_value, (void *)&cmd_set_uc_all_hash_mode, NULL, }, }; /* *** CONFIGURE MACVLAN FILTER FOR VF(s) *** */ struct cmd_set_vf_macvlan_filter { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t vf; uint8_t vf_id; struct ether_addr address; cmdline_fixed_string_t filter_type; cmdline_fixed_string_t mode; }; static void cmd_set_vf_macvlan_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int is_on, ret = 0; struct cmd_set_vf_macvlan_filter *res = parsed_result; struct rte_eth_mac_filter filter; memset(&filter, 0, sizeof(struct rte_eth_mac_filter)); (void)rte_memcpy(&filter.mac_addr, &res->address, ETHER_ADDR_LEN); /* set VF MAC filter */ filter.is_vf = 1; /* set VF ID */ filter.dst_id = res->vf_id; if (!strcmp(res->filter_type, "exact-mac")) filter.filter_type = RTE_MAC_PERFECT_MATCH; else if (!strcmp(res->filter_type, "exact-mac-vlan")) filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; else if (!strcmp(res->filter_type, "hashmac")) filter.filter_type = RTE_MAC_HASH_MATCH; else if (!strcmp(res->filter_type, "hashmac-vlan")) filter.filter_type = RTE_MACVLAN_HASH_MATCH; is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0; if (is_on) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_MACVLAN, RTE_ETH_FILTER_ADD, &filter); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_MACVLAN, RTE_ETH_FILTER_DELETE, &filter); if (ret < 0) printf("bad set MAC hash parameter, return code = %d\n", ret); } cmdline_parse_token_string_t cmd_set_vf_macvlan_set = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter, set, "set"); cmdline_parse_token_string_t cmd_set_vf_macvlan_port = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter, port, "port"); cmdline_parse_token_num_t cmd_set_vf_macvlan_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter, port_id, UINT8); cmdline_parse_token_string_t cmd_set_vf_macvlan_vf = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter, vf, "vf"); cmdline_parse_token_num_t cmd_set_vf_macvlan_vf_id = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter, vf_id, UINT8); cmdline_parse_token_etheraddr_t cmd_set_vf_macvlan_mac = TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_macvlan_filter, address); cmdline_parse_token_string_t cmd_set_vf_macvlan_filter_type = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter, filter_type, "exact-mac#exact-mac-vlan" "#hashmac#hashmac-vlan"); cmdline_parse_token_string_t cmd_set_vf_macvlan_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter, mode, "on#off"); cmdline_parse_inst_t cmd_set_vf_macvlan_filter = { .f = cmd_set_vf_macvlan_parsed, .data = NULL, .help_str = "set port (portid) vf (vfid) (mac-addr) " "(exact-mac|exact-mac-vlan|hashmac|hashmac-vlan) " "on|off\n" "exact match rule:exact match of MAC or MAC and VLAN; " "hash match rule: hash match of MAC and exact match " "of VLAN", .tokens = { (void *)&cmd_set_vf_macvlan_set, (void *)&cmd_set_vf_macvlan_port, (void *)&cmd_set_vf_macvlan_portid, (void *)&cmd_set_vf_macvlan_vf, (void *)&cmd_set_vf_macvlan_vf_id, (void *)&cmd_set_vf_macvlan_mac, (void *)&cmd_set_vf_macvlan_filter_type, (void *)&cmd_set_vf_macvlan_mode, NULL, }, }; /* *** CONFIGURE VF TRAFFIC CONTROL *** */ struct cmd_set_vf_traffic { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t vf; uint8_t vf_id; cmdline_fixed_string_t what; cmdline_fixed_string_t mode; }; static void cmd_set_vf_traffic_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_vf_traffic *res = parsed_result; int is_rx = (strcmp(res->what, "rx") == 0) ? 1 : 0; int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0; set_vf_traffic(res->port_id, (uint8_t)is_rx, res->vf_id,(uint8_t) is_on); } cmdline_parse_token_string_t cmd_setvf_traffic_set = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic, set, "set"); cmdline_parse_token_string_t cmd_setvf_traffic_port = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic, port, "port"); cmdline_parse_token_num_t cmd_setvf_traffic_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic, port_id, UINT8); cmdline_parse_token_string_t cmd_setvf_traffic_vf = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic, vf, "vf"); cmdline_parse_token_num_t cmd_setvf_traffic_vfid = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic, vf_id, UINT8); cmdline_parse_token_string_t cmd_setvf_traffic_what = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic, what, "tx#rx"); cmdline_parse_token_string_t cmd_setvf_traffic_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic, mode, "on#off"); cmdline_parse_inst_t cmd_set_vf_traffic = { .f = cmd_set_vf_traffic_parsed, .data = NULL, .help_str = "set port X vf Y rx|tx on|off" "(X = port number,Y = vf id)", .tokens = { (void *)&cmd_setvf_traffic_set, (void *)&cmd_setvf_traffic_port, (void *)&cmd_setvf_traffic_portid, (void *)&cmd_setvf_traffic_vf, (void *)&cmd_setvf_traffic_vfid, (void *)&cmd_setvf_traffic_what, (void *)&cmd_setvf_traffic_mode, NULL, }, }; /* *** CONFIGURE VF RECEIVE MODE *** */ struct cmd_set_vf_rxmode { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t vf; uint8_t vf_id; cmdline_fixed_string_t what; cmdline_fixed_string_t mode; cmdline_fixed_string_t on; }; static void cmd_set_vf_rxmode_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret; uint16_t rx_mode = 0; struct cmd_set_vf_rxmode *res = parsed_result; int is_on = (strcmp(res->on, "on") == 0) ? 1 : 0; if (!strcmp(res->what,"rxmode")) { if (!strcmp(res->mode, "AUPE")) rx_mode |= ETH_VMDQ_ACCEPT_UNTAG; else if (!strcmp(res->mode, "ROPE")) rx_mode |= ETH_VMDQ_ACCEPT_HASH_UC; else if (!strcmp(res->mode, "BAM")) rx_mode |= ETH_VMDQ_ACCEPT_BROADCAST; else if (!strncmp(res->mode, "MPE",3)) rx_mode |= ETH_VMDQ_ACCEPT_MULTICAST; } ret = rte_eth_dev_set_vf_rxmode(res->port_id,res->vf_id,rx_mode,(uint8_t)is_on); if (ret < 0) printf("bad VF receive mode parameter, return code = %d \n", ret); } cmdline_parse_token_string_t cmd_set_vf_rxmode_set = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, set, "set"); cmdline_parse_token_string_t cmd_set_vf_rxmode_port = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, port, "port"); cmdline_parse_token_num_t cmd_set_vf_rxmode_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode, port_id, UINT8); cmdline_parse_token_string_t cmd_set_vf_rxmode_vf = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, vf, "vf"); cmdline_parse_token_num_t cmd_set_vf_rxmode_vfid = TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode, vf_id, UINT8); cmdline_parse_token_string_t cmd_set_vf_rxmode_what = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, what, "rxmode"); cmdline_parse_token_string_t cmd_set_vf_rxmode_mode = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, mode, "AUPE#ROPE#BAM#MPE"); cmdline_parse_token_string_t cmd_set_vf_rxmode_on = TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode, on, "on#off"); cmdline_parse_inst_t cmd_set_vf_rxmode = { .f = cmd_set_vf_rxmode_parsed, .data = NULL, .help_str = "set port X vf Y rxmode AUPE|ROPE|BAM|MPE on|off", .tokens = { (void *)&cmd_set_vf_rxmode_set, (void *)&cmd_set_vf_rxmode_port, (void *)&cmd_set_vf_rxmode_portid, (void *)&cmd_set_vf_rxmode_vf, (void *)&cmd_set_vf_rxmode_vfid, (void *)&cmd_set_vf_rxmode_what, (void *)&cmd_set_vf_rxmode_mode, (void *)&cmd_set_vf_rxmode_on, NULL, }, }; /* *** ADD MAC ADDRESS FILTER FOR A VF OF A PORT *** */ struct cmd_vf_mac_addr_result { cmdline_fixed_string_t mac_addr_cmd; cmdline_fixed_string_t what; cmdline_fixed_string_t port; uint8_t port_num; cmdline_fixed_string_t vf; uint8_t vf_num; struct ether_addr address; }; static void cmd_vf_mac_addr_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_vf_mac_addr_result *res = parsed_result; int ret = 0; if (strcmp(res->what, "add") == 0) ret = rte_eth_dev_mac_addr_add(res->port_num, &res->address, res->vf_num); if(ret < 0) printf("vf_mac_addr_cmd error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_vf_mac_addr_cmd = TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result, mac_addr_cmd,"mac_addr"); cmdline_parse_token_string_t cmd_vf_mac_addr_what = TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result, what,"add"); cmdline_parse_token_string_t cmd_vf_mac_addr_port = TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result, port,"port"); cmdline_parse_token_num_t cmd_vf_mac_addr_portnum = TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result, port_num, UINT8); cmdline_parse_token_string_t cmd_vf_mac_addr_vf = TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result, vf,"vf"); cmdline_parse_token_num_t cmd_vf_mac_addr_vfnum = TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result, vf_num, UINT8); cmdline_parse_token_etheraddr_t cmd_vf_mac_addr_addr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_vf_mac_addr_result, address); cmdline_parse_inst_t cmd_vf_mac_addr_filter = { .f = cmd_vf_mac_addr_parsed, .data = (void *)0, .help_str = "mac_addr add port X vf Y ethaddr:(X = port number," "Y = VF number)add MAC address filtering for a VF on port X", .tokens = { (void *)&cmd_vf_mac_addr_cmd, (void *)&cmd_vf_mac_addr_what, (void *)&cmd_vf_mac_addr_port, (void *)&cmd_vf_mac_addr_portnum, (void *)&cmd_vf_mac_addr_vf, (void *)&cmd_vf_mac_addr_vfnum, (void *)&cmd_vf_mac_addr_addr, NULL, }, }; /* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */ struct cmd_vf_rx_vlan_filter { cmdline_fixed_string_t rx_vlan; cmdline_fixed_string_t what; uint16_t vlan_id; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t vf; uint64_t vf_mask; }; static void cmd_vf_rx_vlan_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_vf_rx_vlan_filter *res = parsed_result; if (!strcmp(res->what, "add")) set_vf_rx_vlan(res->port_id, res->vlan_id,res->vf_mask, 1); else set_vf_rx_vlan(res->port_id, res->vlan_id,res->vf_mask, 0); } cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_rx_vlan = TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter, rx_vlan, "rx_vlan"); cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_what = TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter, what, "add#rm"); cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vlanid = TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter, vlan_id, UINT16); cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_port = TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter, port, "port"); cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_portid = TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter, port_id, UINT8); cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_vf = TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter, vf, "vf"); cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vf_mask = TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter, vf_mask, UINT64); cmdline_parse_inst_t cmd_vf_rxvlan_filter = { .f = cmd_vf_rx_vlan_filter_parsed, .data = NULL, .help_str = "rx_vlan add|rm X port Y vf Z (X = VLAN ID," "Y = port number,Z = hexadecimal VF mask)", .tokens = { (void *)&cmd_vf_rx_vlan_filter_rx_vlan, (void *)&cmd_vf_rx_vlan_filter_what, (void *)&cmd_vf_rx_vlan_filter_vlanid, (void *)&cmd_vf_rx_vlan_filter_port, (void *)&cmd_vf_rx_vlan_filter_portid, (void *)&cmd_vf_rx_vlan_filter_vf, (void *)&cmd_vf_rx_vlan_filter_vf_mask, NULL, }, }; /* *** SET RATE LIMIT FOR A QUEUE OF A PORT *** */ struct cmd_queue_rate_limit_result { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_num; cmdline_fixed_string_t queue; uint8_t queue_num; cmdline_fixed_string_t rate; uint16_t rate_num; }; static void cmd_queue_rate_limit_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_queue_rate_limit_result *res = parsed_result; int ret = 0; if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0) && (strcmp(res->queue, "queue") == 0) && (strcmp(res->rate, "rate") == 0)) ret = set_queue_rate_limit(res->port_num, res->queue_num, res->rate_num); if (ret < 0) printf("queue_rate_limit_cmd error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_queue_rate_limit_set = TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result, set, "set"); cmdline_parse_token_string_t cmd_queue_rate_limit_port = TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result, port, "port"); cmdline_parse_token_num_t cmd_queue_rate_limit_portnum = TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result, port_num, UINT8); cmdline_parse_token_string_t cmd_queue_rate_limit_queue = TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result, queue, "queue"); cmdline_parse_token_num_t cmd_queue_rate_limit_queuenum = TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result, queue_num, UINT8); cmdline_parse_token_string_t cmd_queue_rate_limit_rate = TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result, rate, "rate"); cmdline_parse_token_num_t cmd_queue_rate_limit_ratenum = TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result, rate_num, UINT16); cmdline_parse_inst_t cmd_queue_rate_limit = { .f = cmd_queue_rate_limit_parsed, .data = (void *)0, .help_str = "set port X queue Y rate Z:(X = port number," "Y = queue number,Z = rate number)set rate limit for a queue on port X", .tokens = { (void *)&cmd_queue_rate_limit_set, (void *)&cmd_queue_rate_limit_port, (void *)&cmd_queue_rate_limit_portnum, (void *)&cmd_queue_rate_limit_queue, (void *)&cmd_queue_rate_limit_queuenum, (void *)&cmd_queue_rate_limit_rate, (void *)&cmd_queue_rate_limit_ratenum, NULL, }, }; /* *** SET RATE LIMIT FOR A VF OF A PORT *** */ struct cmd_vf_rate_limit_result { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_num; cmdline_fixed_string_t vf; uint8_t vf_num; cmdline_fixed_string_t rate; uint16_t rate_num; cmdline_fixed_string_t q_msk; uint64_t q_msk_val; }; static void cmd_vf_rate_limit_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_vf_rate_limit_result *res = parsed_result; int ret = 0; if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0) && (strcmp(res->vf, "vf") == 0) && (strcmp(res->rate, "rate") == 0) && (strcmp(res->q_msk, "queue_mask") == 0)) ret = set_vf_rate_limit(res->port_num, res->vf_num, res->rate_num, res->q_msk_val); if (ret < 0) printf("vf_rate_limit_cmd error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_vf_rate_limit_set = TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result, set, "set"); cmdline_parse_token_string_t cmd_vf_rate_limit_port = TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result, port, "port"); cmdline_parse_token_num_t cmd_vf_rate_limit_portnum = TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result, port_num, UINT8); cmdline_parse_token_string_t cmd_vf_rate_limit_vf = TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result, vf, "vf"); cmdline_parse_token_num_t cmd_vf_rate_limit_vfnum = TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result, vf_num, UINT8); cmdline_parse_token_string_t cmd_vf_rate_limit_rate = TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result, rate, "rate"); cmdline_parse_token_num_t cmd_vf_rate_limit_ratenum = TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result, rate_num, UINT16); cmdline_parse_token_string_t cmd_vf_rate_limit_q_msk = TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result, q_msk, "queue_mask"); cmdline_parse_token_num_t cmd_vf_rate_limit_q_msk_val = TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result, q_msk_val, UINT64); cmdline_parse_inst_t cmd_vf_rate_limit = { .f = cmd_vf_rate_limit_parsed, .data = (void *)0, .help_str = "set port X vf Y rate Z queue_mask V:(X = port number," "Y = VF number,Z = rate number, V = queue mask value)set rate limit " "for queues of VF on port X", .tokens = { (void *)&cmd_vf_rate_limit_set, (void *)&cmd_vf_rate_limit_port, (void *)&cmd_vf_rate_limit_portnum, (void *)&cmd_vf_rate_limit_vf, (void *)&cmd_vf_rate_limit_vfnum, (void *)&cmd_vf_rate_limit_rate, (void *)&cmd_vf_rate_limit_ratenum, (void *)&cmd_vf_rate_limit_q_msk, (void *)&cmd_vf_rate_limit_q_msk_val, NULL, }, }; /* *** ADD TUNNEL FILTER OF A PORT *** */ struct cmd_tunnel_filter_result { cmdline_fixed_string_t cmd; cmdline_fixed_string_t what; uint8_t port_id; struct ether_addr outer_mac; struct ether_addr inner_mac; cmdline_ipaddr_t ip_value; uint16_t inner_vlan; cmdline_fixed_string_t tunnel_type; cmdline_fixed_string_t filter_type; uint32_t tenant_id; uint16_t queue_num; }; static void cmd_tunnel_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tunnel_filter_result *res = parsed_result; struct rte_eth_tunnel_filter_conf tunnel_filter_conf; int ret = 0; tunnel_filter_conf.outer_mac = &res->outer_mac; tunnel_filter_conf.inner_mac = &res->inner_mac; tunnel_filter_conf.inner_vlan = res->inner_vlan; if (res->ip_value.family == AF_INET) { tunnel_filter_conf.ip_addr.ipv4_addr = res->ip_value.addr.ipv4.s_addr; tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV4; } else { memcpy(&(tunnel_filter_conf.ip_addr.ipv6_addr), &(res->ip_value.addr.ipv6), sizeof(struct in6_addr)); tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV6; } if (!strcmp(res->filter_type, "imac-ivlan")) tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_IVLAN; else if (!strcmp(res->filter_type, "imac-ivlan-tenid")) tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID; else if (!strcmp(res->filter_type, "imac-tenid")) tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_TENID; else if (!strcmp(res->filter_type, "imac")) tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IMAC; else if (!strcmp(res->filter_type, "omac-imac-tenid")) tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_OMAC_TENID_IMAC; else { printf("The filter type is not supported"); return; } if (!strcmp(res->tunnel_type, "vxlan")) tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN; else if (!strcmp(res->tunnel_type, "nvgre")) tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_NVGRE; else { printf("The tunnel type %s not supported.\n", res->tunnel_type); return; } tunnel_filter_conf.tenant_id = res->tenant_id; tunnel_filter_conf.queue_id = res->queue_num; if (!strcmp(res->what, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_ADD, &tunnel_filter_conf); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_DELETE, &tunnel_filter_conf); if (ret < 0) printf("cmd_tunnel_filter_parsed error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_tunnel_filter_cmd = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result, cmd, "tunnel_filter"); cmdline_parse_token_string_t cmd_tunnel_filter_what = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result, what, "add#rm"); cmdline_parse_token_num_t cmd_tunnel_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result, port_id, UINT8); cmdline_parse_token_etheraddr_t cmd_tunnel_filter_outer_mac = TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result, outer_mac); cmdline_parse_token_etheraddr_t cmd_tunnel_filter_inner_mac = TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result, inner_mac); cmdline_parse_token_num_t cmd_tunnel_filter_innner_vlan = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result, inner_vlan, UINT16); cmdline_parse_token_ipaddr_t cmd_tunnel_filter_ip_value = TOKEN_IPADDR_INITIALIZER(struct cmd_tunnel_filter_result, ip_value); cmdline_parse_token_string_t cmd_tunnel_filter_tunnel_type = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result, tunnel_type, "vxlan#nvgre"); cmdline_parse_token_string_t cmd_tunnel_filter_filter_type = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result, filter_type, "imac-ivlan#imac-ivlan-tenid#imac-tenid#" "imac#omac-imac-tenid"); cmdline_parse_token_num_t cmd_tunnel_filter_tenant_id = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result, tenant_id, UINT32); cmdline_parse_token_num_t cmd_tunnel_filter_queue_num = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result, queue_num, UINT16); cmdline_parse_inst_t cmd_tunnel_filter = { .f = cmd_tunnel_filter_parsed, .data = (void *)0, .help_str = "add/rm tunnel filter of a port: " "tunnel_filter add port_id outer_mac inner_mac ip " "inner_vlan tunnel_type(vxlan|nvgre) filter_type " "(imac-ivlan|imac-ivlan-tenid|imac-tenid|" "imac|omac-imac-tenid) " "tenant_id queue_num", .tokens = { (void *)&cmd_tunnel_filter_cmd, (void *)&cmd_tunnel_filter_what, (void *)&cmd_tunnel_filter_port_id, (void *)&cmd_tunnel_filter_outer_mac, (void *)&cmd_tunnel_filter_inner_mac, (void *)&cmd_tunnel_filter_ip_value, (void *)&cmd_tunnel_filter_innner_vlan, (void *)&cmd_tunnel_filter_tunnel_type, (void *)&cmd_tunnel_filter_filter_type, (void *)&cmd_tunnel_filter_tenant_id, (void *)&cmd_tunnel_filter_queue_num, NULL, }, }; /* *** CONFIGURE TUNNEL UDP PORT *** */ struct cmd_tunnel_udp_config { cmdline_fixed_string_t cmd; cmdline_fixed_string_t what; uint16_t udp_port; uint8_t port_id; }; static void cmd_tunnel_udp_config_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_tunnel_udp_config *res = parsed_result; struct rte_eth_udp_tunnel tunnel_udp; int ret; tunnel_udp.udp_port = res->udp_port; if (!strcmp(res->cmd, "rx_vxlan_port")) tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN; if (!strcmp(res->what, "add")) ret = rte_eth_dev_udp_tunnel_add(res->port_id, &tunnel_udp); else ret = rte_eth_dev_udp_tunnel_delete(res->port_id, &tunnel_udp); if (ret < 0) printf("udp tunneling add error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_tunnel_udp_config_cmd = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config, cmd, "rx_vxlan_port"); cmdline_parse_token_string_t cmd_tunnel_udp_config_what = TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config, what, "add#rm"); cmdline_parse_token_num_t cmd_tunnel_udp_config_udp_port = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config, udp_port, UINT16); cmdline_parse_token_num_t cmd_tunnel_udp_config_port_id = TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config, port_id, UINT8); cmdline_parse_inst_t cmd_tunnel_udp_config = { .f = cmd_tunnel_udp_config_parsed, .data = (void *)0, .help_str = "add/rm an tunneling UDP port filter: " "rx_vxlan_port add udp_port port_id", .tokens = { (void *)&cmd_tunnel_udp_config_cmd, (void *)&cmd_tunnel_udp_config_what, (void *)&cmd_tunnel_udp_config_udp_port, (void *)&cmd_tunnel_udp_config_port_id, NULL, }, }; /* *** CONFIGURE VM MIRROR VLAN/POOL RULE *** */ struct cmd_set_mirror_mask_result { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t mirror; uint8_t rule_id; cmdline_fixed_string_t what; cmdline_fixed_string_t value; cmdline_fixed_string_t dstpool; uint8_t dstpool_id; cmdline_fixed_string_t on; }; cmdline_parse_token_string_t cmd_mirror_mask_set = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, set, "set"); cmdline_parse_token_string_t cmd_mirror_mask_port = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, port, "port"); cmdline_parse_token_num_t cmd_mirror_mask_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result, port_id, UINT8); cmdline_parse_token_string_t cmd_mirror_mask_mirror = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, mirror, "mirror-rule"); cmdline_parse_token_num_t cmd_mirror_mask_ruleid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result, rule_id, UINT8); cmdline_parse_token_string_t cmd_mirror_mask_what = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, what, "pool-mirror-up#pool-mirror-down" "#vlan-mirror"); cmdline_parse_token_string_t cmd_mirror_mask_value = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, value, NULL); cmdline_parse_token_string_t cmd_mirror_mask_dstpool = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, dstpool, "dst-pool"); cmdline_parse_token_num_t cmd_mirror_mask_poolid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result, dstpool_id, UINT8); cmdline_parse_token_string_t cmd_mirror_mask_on = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result, on, "on#off"); static void cmd_set_mirror_mask_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret,nb_item,i; struct cmd_set_mirror_mask_result *res = parsed_result; struct rte_eth_mirror_conf mr_conf; memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf)); unsigned int vlan_list[ETH_MIRROR_MAX_VLANS]; mr_conf.dst_pool = res->dstpool_id; if (!strcmp(res->what, "pool-mirror-up")) { mr_conf.pool_mask = strtoull(res->value, NULL, 16); mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_UP; } else if (!strcmp(res->what, "pool-mirror-down")) { mr_conf.pool_mask = strtoull(res->value, NULL, 16); mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_DOWN; } else if (!strcmp(res->what, "vlan-mirror")) { mr_conf.rule_type = ETH_MIRROR_VLAN; nb_item = parse_item_list(res->value, "vlan", ETH_MIRROR_MAX_VLANS, vlan_list, 1); if (nb_item <= 0) return; for (i = 0; i < nb_item; i++) { if (vlan_list[i] > ETHER_MAX_VLAN_ID) { printf("Invalid vlan_id: must be < 4096\n"); return; } mr_conf.vlan.vlan_id[i] = (uint16_t)vlan_list[i]; mr_conf.vlan.vlan_mask |= 1ULL << i; } } if (!strcmp(res->on, "on")) ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf, res->rule_id, 1); else ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf, res->rule_id, 0); if (ret < 0) printf("mirror rule add error: (%s)\n", strerror(-ret)); } cmdline_parse_inst_t cmd_set_mirror_mask = { .f = cmd_set_mirror_mask_parsed, .data = NULL, .help_str = "set port X mirror-rule Y pool-mirror-up|pool-mirror-down|vlan-mirror" " pool_mask|vlan_id[,vlan_id]* dst-pool Z on|off", .tokens = { (void *)&cmd_mirror_mask_set, (void *)&cmd_mirror_mask_port, (void *)&cmd_mirror_mask_portid, (void *)&cmd_mirror_mask_mirror, (void *)&cmd_mirror_mask_ruleid, (void *)&cmd_mirror_mask_what, (void *)&cmd_mirror_mask_value, (void *)&cmd_mirror_mask_dstpool, (void *)&cmd_mirror_mask_poolid, (void *)&cmd_mirror_mask_on, NULL, }, }; /* *** CONFIGURE VM MIRROR UDLINK/DOWNLINK RULE *** */ struct cmd_set_mirror_link_result { cmdline_fixed_string_t set; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t mirror; uint8_t rule_id; cmdline_fixed_string_t what; cmdline_fixed_string_t dstpool; uint8_t dstpool_id; cmdline_fixed_string_t on; }; cmdline_parse_token_string_t cmd_mirror_link_set = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, set, "set"); cmdline_parse_token_string_t cmd_mirror_link_port = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, port, "port"); cmdline_parse_token_num_t cmd_mirror_link_portid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result, port_id, UINT8); cmdline_parse_token_string_t cmd_mirror_link_mirror = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, mirror, "mirror-rule"); cmdline_parse_token_num_t cmd_mirror_link_ruleid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result, rule_id, UINT8); cmdline_parse_token_string_t cmd_mirror_link_what = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, what, "uplink-mirror#downlink-mirror"); cmdline_parse_token_string_t cmd_mirror_link_dstpool = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, dstpool, "dst-pool"); cmdline_parse_token_num_t cmd_mirror_link_poolid = TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result, dstpool_id, UINT8); cmdline_parse_token_string_t cmd_mirror_link_on = TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result, on, "on#off"); static void cmd_set_mirror_link_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret; struct cmd_set_mirror_link_result *res = parsed_result; struct rte_eth_mirror_conf mr_conf; memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf)); if (!strcmp(res->what, "uplink-mirror")) mr_conf.rule_type = ETH_MIRROR_UPLINK_PORT; else mr_conf.rule_type = ETH_MIRROR_DOWNLINK_PORT; mr_conf.dst_pool = res->dstpool_id; if (!strcmp(res->on, "on")) ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf, res->rule_id, 1); else ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf, res->rule_id, 0); /* check the return value and print it if is < 0 */ if (ret < 0) printf("mirror rule add error: (%s)\n", strerror(-ret)); } cmdline_parse_inst_t cmd_set_mirror_link = { .f = cmd_set_mirror_link_parsed, .data = NULL, .help_str = "set port X mirror-rule Y uplink-mirror|" "downlink-mirror dst-pool Z on|off", .tokens = { (void *)&cmd_mirror_link_set, (void *)&cmd_mirror_link_port, (void *)&cmd_mirror_link_portid, (void *)&cmd_mirror_link_mirror, (void *)&cmd_mirror_link_ruleid, (void *)&cmd_mirror_link_what, (void *)&cmd_mirror_link_dstpool, (void *)&cmd_mirror_link_poolid, (void *)&cmd_mirror_link_on, NULL, }, }; /* *** RESET VM MIRROR RULE *** */ struct cmd_rm_mirror_rule_result { cmdline_fixed_string_t reset; cmdline_fixed_string_t port; uint8_t port_id; cmdline_fixed_string_t mirror; uint8_t rule_id; }; cmdline_parse_token_string_t cmd_rm_mirror_rule_reset = TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result, reset, "reset"); cmdline_parse_token_string_t cmd_rm_mirror_rule_port = TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result, port, "port"); cmdline_parse_token_num_t cmd_rm_mirror_rule_portid = TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result, port_id, UINT8); cmdline_parse_token_string_t cmd_rm_mirror_rule_mirror = TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result, mirror, "mirror-rule"); cmdline_parse_token_num_t cmd_rm_mirror_rule_ruleid = TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result, rule_id, UINT8); static void cmd_reset_mirror_rule_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret; struct cmd_set_mirror_link_result *res = parsed_result; /* check rule_id */ ret = rte_eth_mirror_rule_reset(res->port_id,res->rule_id); if(ret < 0) printf("mirror rule remove error: (%s)\n", strerror(-ret)); } cmdline_parse_inst_t cmd_reset_mirror_rule = { .f = cmd_reset_mirror_rule_parsed, .data = NULL, .help_str = "reset port X mirror-rule Y", .tokens = { (void *)&cmd_rm_mirror_rule_reset, (void *)&cmd_rm_mirror_rule_port, (void *)&cmd_rm_mirror_rule_portid, (void *)&cmd_rm_mirror_rule_mirror, (void *)&cmd_rm_mirror_rule_ruleid, NULL, }, }; /* ******************************************************************************** */ struct cmd_dump_result { cmdline_fixed_string_t dump; }; static void dump_struct_sizes(void) { #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t)); DUMP_SIZE(struct rte_mbuf); DUMP_SIZE(struct rte_mempool); DUMP_SIZE(struct rte_ring); #undef DUMP_SIZE } static void cmd_dump_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_dump_result *res = parsed_result; if (!strcmp(res->dump, "dump_physmem")) rte_dump_physmem_layout(stdout); else if (!strcmp(res->dump, "dump_memzone")) rte_memzone_dump(stdout); else if (!strcmp(res->dump, "dump_log_history")) rte_log_dump_history(stdout); else if (!strcmp(res->dump, "dump_struct_sizes")) dump_struct_sizes(); else if (!strcmp(res->dump, "dump_ring")) rte_ring_list_dump(stdout); else if (!strcmp(res->dump, "dump_mempool")) rte_mempool_list_dump(stdout); else if (!strcmp(res->dump, "dump_devargs")) rte_eal_devargs_dump(stdout); } cmdline_parse_token_string_t cmd_dump_dump = TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, "dump_physmem#" "dump_memzone#" "dump_log_history#" "dump_struct_sizes#" "dump_ring#" "dump_mempool#" "dump_devargs"); cmdline_parse_inst_t cmd_dump = { .f = cmd_dump_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "dump status", .tokens = { /* token list, NULL terminated */ (void *)&cmd_dump_dump, NULL, }, }; /* ******************************************************************************** */ struct cmd_dump_one_result { cmdline_fixed_string_t dump; cmdline_fixed_string_t name; }; static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_dump_one_result *res = parsed_result; if (!strcmp(res->dump, "dump_ring")) { struct rte_ring *r; r = rte_ring_lookup(res->name); if (r == NULL) { cmdline_printf(cl, "Cannot find ring\n"); return; } rte_ring_dump(stdout, r); } else if (!strcmp(res->dump, "dump_mempool")) { struct rte_mempool *mp; mp = rte_mempool_lookup(res->name); if (mp == NULL) { cmdline_printf(cl, "Cannot find mempool\n"); return; } rte_mempool_dump(stdout, mp); } } cmdline_parse_token_string_t cmd_dump_one_dump = TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump, "dump_ring#dump_mempool"); cmdline_parse_token_string_t cmd_dump_one_name = TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL); cmdline_parse_inst_t cmd_dump_one = { .f = cmd_dump_one_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "dump one ring/mempool: dump_ring|dump_mempool ", .tokens = { /* token list, NULL terminated */ (void *)&cmd_dump_one_dump, (void *)&cmd_dump_one_name, NULL, }, }; /* *** Add/Del syn filter *** */ struct cmd_syn_filter_result { cmdline_fixed_string_t filter; uint8_t port_id; cmdline_fixed_string_t ops; cmdline_fixed_string_t priority; cmdline_fixed_string_t high; cmdline_fixed_string_t queue; uint16_t queue_id; }; static void cmd_syn_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_syn_filter_result *res = parsed_result; struct rte_eth_syn_filter syn_filter; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_SYN); if (ret < 0) { printf("syn filter is not supported on port %u.\n", res->port_id); return; } memset(&syn_filter, 0, sizeof(syn_filter)); if (!strcmp(res->ops, "add")) { if (!strcmp(res->high, "high")) syn_filter.hig_pri = 1; else syn_filter.hig_pri = 0; syn_filter.queue = res->queue_id; ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_SYN, RTE_ETH_FILTER_ADD, &syn_filter); } else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_SYN, RTE_ETH_FILTER_DELETE, &syn_filter); if (ret < 0) printf("syn filter programming error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_syn_filter_filter = TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result, filter, "syn_filter"); cmdline_parse_token_num_t cmd_syn_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result, port_id, UINT8); cmdline_parse_token_string_t cmd_syn_filter_ops = TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result, ops, "add#del"); cmdline_parse_token_string_t cmd_syn_filter_priority = TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result, priority, "priority"); cmdline_parse_token_string_t cmd_syn_filter_high = TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result, high, "high#low"); cmdline_parse_token_string_t cmd_syn_filter_queue = TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result, queue, "queue"); cmdline_parse_token_num_t cmd_syn_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result, queue_id, UINT16); cmdline_parse_inst_t cmd_syn_filter = { .f = cmd_syn_filter_parsed, .data = NULL, .help_str = "add/delete syn filter", .tokens = { (void *)&cmd_syn_filter_filter, (void *)&cmd_syn_filter_port_id, (void *)&cmd_syn_filter_ops, (void *)&cmd_syn_filter_priority, (void *)&cmd_syn_filter_high, (void *)&cmd_syn_filter_queue, (void *)&cmd_syn_filter_queue_id, NULL, }, }; /* *** ADD/REMOVE A 2tuple FILTER *** */ struct cmd_2tuple_filter_result { cmdline_fixed_string_t filter; uint8_t port_id; cmdline_fixed_string_t ops; cmdline_fixed_string_t dst_port; uint16_t dst_port_value; cmdline_fixed_string_t protocol; uint8_t protocol_value; cmdline_fixed_string_t mask; uint8_t mask_value; cmdline_fixed_string_t tcp_flags; uint8_t tcp_flags_value; cmdline_fixed_string_t priority; uint8_t priority_value; cmdline_fixed_string_t queue; uint16_t queue_id; }; static void cmd_2tuple_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct rte_eth_ntuple_filter filter; struct cmd_2tuple_filter_result *res = parsed_result; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE); if (ret < 0) { printf("ntuple filter is not supported on port %u.\n", res->port_id); return; } memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter)); filter.flags = RTE_2TUPLE_FLAGS; filter.dst_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0; filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0; filter.proto = res->protocol_value; filter.priority = res->priority_value; if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) { printf("nonzero tcp_flags is only meaningful" " when protocol is TCP.\n"); return; } if (res->tcp_flags_value > TCP_FLAG_ALL) { printf("invalid TCP flags.\n"); return; } if (res->tcp_flags_value != 0) { filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG; filter.tcp_flags = res->tcp_flags_value; } /* need convert to big endian. */ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value); filter.queue = res->queue_id; if (!strcmp(res->ops, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); if (ret < 0) printf("2tuple filter programming error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_2tuple_filter_filter = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, filter, "2tuple_filter"); cmdline_parse_token_num_t cmd_2tuple_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, port_id, UINT8); cmdline_parse_token_string_t cmd_2tuple_filter_ops = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, ops, "add#del"); cmdline_parse_token_string_t cmd_2tuple_filter_dst_port = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, dst_port, "dst_port"); cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, dst_port_value, UINT16); cmdline_parse_token_string_t cmd_2tuple_filter_protocol = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, protocol, "protocol"); cmdline_parse_token_num_t cmd_2tuple_filter_protocol_value = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, protocol_value, UINT8); cmdline_parse_token_string_t cmd_2tuple_filter_mask = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, mask, "mask"); cmdline_parse_token_num_t cmd_2tuple_filter_mask_value = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, mask_value, INT8); cmdline_parse_token_string_t cmd_2tuple_filter_tcp_flags = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, tcp_flags, "tcp_flags"); cmdline_parse_token_num_t cmd_2tuple_filter_tcp_flags_value = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, tcp_flags_value, UINT8); cmdline_parse_token_string_t cmd_2tuple_filter_priority = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, priority, "priority"); cmdline_parse_token_num_t cmd_2tuple_filter_priority_value = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, priority_value, UINT8); cmdline_parse_token_string_t cmd_2tuple_filter_queue = TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result, queue, "queue"); cmdline_parse_token_num_t cmd_2tuple_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result, queue_id, UINT16); cmdline_parse_inst_t cmd_2tuple_filter = { .f = cmd_2tuple_filter_parsed, .data = NULL, .help_str = "add a 2tuple filter", .tokens = { (void *)&cmd_2tuple_filter_filter, (void *)&cmd_2tuple_filter_port_id, (void *)&cmd_2tuple_filter_ops, (void *)&cmd_2tuple_filter_dst_port, (void *)&cmd_2tuple_filter_dst_port_value, (void *)&cmd_2tuple_filter_protocol, (void *)&cmd_2tuple_filter_protocol_value, (void *)&cmd_2tuple_filter_mask, (void *)&cmd_2tuple_filter_mask_value, (void *)&cmd_2tuple_filter_tcp_flags, (void *)&cmd_2tuple_filter_tcp_flags_value, (void *)&cmd_2tuple_filter_priority, (void *)&cmd_2tuple_filter_priority_value, (void *)&cmd_2tuple_filter_queue, (void *)&cmd_2tuple_filter_queue_id, NULL, }, }; /* *** ADD/REMOVE A 5tuple FILTER *** */ struct cmd_5tuple_filter_result { cmdline_fixed_string_t filter; uint8_t port_id; cmdline_fixed_string_t ops; cmdline_fixed_string_t dst_ip; cmdline_ipaddr_t dst_ip_value; cmdline_fixed_string_t src_ip; cmdline_ipaddr_t src_ip_value; cmdline_fixed_string_t dst_port; uint16_t dst_port_value; cmdline_fixed_string_t src_port; uint16_t src_port_value; cmdline_fixed_string_t protocol; uint8_t protocol_value; cmdline_fixed_string_t mask; uint8_t mask_value; cmdline_fixed_string_t tcp_flags; uint8_t tcp_flags_value; cmdline_fixed_string_t priority; uint8_t priority_value; cmdline_fixed_string_t queue; uint16_t queue_id; }; static void cmd_5tuple_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct rte_eth_ntuple_filter filter; struct cmd_5tuple_filter_result *res = parsed_result; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE); if (ret < 0) { printf("ntuple filter is not supported on port %u.\n", res->port_id); return; } memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter)); filter.flags = RTE_5TUPLE_FLAGS; filter.dst_ip_mask = (res->mask_value & 0x10) ? UINT32_MAX : 0; filter.src_ip_mask = (res->mask_value & 0x08) ? UINT32_MAX : 0; filter.dst_port_mask = (res->mask_value & 0x04) ? UINT16_MAX : 0; filter.src_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0; filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0; filter.proto = res->protocol_value; filter.priority = res->priority_value; if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) { printf("nonzero tcp_flags is only meaningful" " when protocol is TCP.\n"); return; } if (res->tcp_flags_value > TCP_FLAG_ALL) { printf("invalid TCP flags.\n"); return; } if (res->tcp_flags_value != 0) { filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG; filter.tcp_flags = res->tcp_flags_value; } if (res->dst_ip_value.family == AF_INET) /* no need to convert, already big endian. */ filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr; else { if (filter.dst_ip_mask == 0) { printf("can not support ipv6 involved compare.\n"); return; } filter.dst_ip = 0; } if (res->src_ip_value.family == AF_INET) /* no need to convert, already big endian. */ filter.src_ip = res->src_ip_value.addr.ipv4.s_addr; else { if (filter.src_ip_mask == 0) { printf("can not support ipv6 involved compare.\n"); return; } filter.src_ip = 0; } /* need convert to big endian. */ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value); filter.src_port = rte_cpu_to_be_16(res->src_port_value); filter.queue = res->queue_id; if (!strcmp(res->ops, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); if (ret < 0) printf("5tuple filter programming error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_5tuple_filter_filter = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, filter, "5tuple_filter"); cmdline_parse_token_num_t cmd_5tuple_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, port_id, UINT8); cmdline_parse_token_string_t cmd_5tuple_filter_ops = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, ops, "add#del"); cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, dst_ip, "dst_ip"); cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value = TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result, dst_ip_value); cmdline_parse_token_string_t cmd_5tuple_filter_src_ip = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, src_ip, "src_ip"); cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value = TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result, src_ip_value); cmdline_parse_token_string_t cmd_5tuple_filter_dst_port = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, dst_port, "dst_port"); cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, dst_port_value, UINT16); cmdline_parse_token_string_t cmd_5tuple_filter_src_port = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, src_port, "src_port"); cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, src_port_value, UINT16); cmdline_parse_token_string_t cmd_5tuple_filter_protocol = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, protocol, "protocol"); cmdline_parse_token_num_t cmd_5tuple_filter_protocol_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, protocol_value, UINT8); cmdline_parse_token_string_t cmd_5tuple_filter_mask = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, mask, "mask"); cmdline_parse_token_num_t cmd_5tuple_filter_mask_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, mask_value, INT8); cmdline_parse_token_string_t cmd_5tuple_filter_tcp_flags = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, tcp_flags, "tcp_flags"); cmdline_parse_token_num_t cmd_5tuple_filter_tcp_flags_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, tcp_flags_value, UINT8); cmdline_parse_token_string_t cmd_5tuple_filter_priority = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, priority, "priority"); cmdline_parse_token_num_t cmd_5tuple_filter_priority_value = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, priority_value, UINT8); cmdline_parse_token_string_t cmd_5tuple_filter_queue = TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result, queue, "queue"); cmdline_parse_token_num_t cmd_5tuple_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result, queue_id, UINT16); cmdline_parse_inst_t cmd_5tuple_filter = { .f = cmd_5tuple_filter_parsed, .data = NULL, .help_str = "add/del a 5tuple filter", .tokens = { (void *)&cmd_5tuple_filter_filter, (void *)&cmd_5tuple_filter_port_id, (void *)&cmd_5tuple_filter_ops, (void *)&cmd_5tuple_filter_dst_ip, (void *)&cmd_5tuple_filter_dst_ip_value, (void *)&cmd_5tuple_filter_src_ip, (void *)&cmd_5tuple_filter_src_ip_value, (void *)&cmd_5tuple_filter_dst_port, (void *)&cmd_5tuple_filter_dst_port_value, (void *)&cmd_5tuple_filter_src_port, (void *)&cmd_5tuple_filter_src_port_value, (void *)&cmd_5tuple_filter_protocol, (void *)&cmd_5tuple_filter_protocol_value, (void *)&cmd_5tuple_filter_mask, (void *)&cmd_5tuple_filter_mask_value, (void *)&cmd_5tuple_filter_tcp_flags, (void *)&cmd_5tuple_filter_tcp_flags_value, (void *)&cmd_5tuple_filter_priority, (void *)&cmd_5tuple_filter_priority_value, (void *)&cmd_5tuple_filter_queue, (void *)&cmd_5tuple_filter_queue_id, NULL, }, }; /* *** ADD/REMOVE A flex FILTER *** */ struct cmd_flex_filter_result { cmdline_fixed_string_t filter; cmdline_fixed_string_t ops; uint8_t port_id; cmdline_fixed_string_t len; uint8_t len_value; cmdline_fixed_string_t bytes; cmdline_fixed_string_t bytes_value; cmdline_fixed_string_t mask; cmdline_fixed_string_t mask_value; cmdline_fixed_string_t priority; uint8_t priority_value; cmdline_fixed_string_t queue; uint16_t queue_id; }; static int xdigit2val(unsigned char c) { int val; if (isdigit(c)) val = c - '0'; else if (isupper(c)) val = c - 'A' + 10; else val = c - 'a' + 10; return val; } static void cmd_flex_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { int ret = 0; struct rte_eth_flex_filter filter; struct cmd_flex_filter_result *res = parsed_result; char *bytes_ptr, *mask_ptr; uint16_t len, i, j = 0; char c; int val; uint8_t byte = 0; if (res->len_value > RTE_FLEX_FILTER_MAXLEN) { printf("the len exceed the max length 128\n"); return; } memset(&filter, 0, sizeof(struct rte_eth_flex_filter)); filter.len = res->len_value; filter.priority = res->priority_value; filter.queue = res->queue_id; bytes_ptr = res->bytes_value; mask_ptr = res->mask_value; /* translate bytes string to array. */ if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') || (bytes_ptr[1] == 'X'))) bytes_ptr += 2; len = strnlen(bytes_ptr, res->len_value * 2); if (len == 0 || (len % 8 != 0)) { printf("please check len and bytes input\n"); return; } for (i = 0; i < len; i++) { c = bytes_ptr[i]; if (isxdigit(c) == 0) { /* invalid characters. */ printf("invalid input\n"); return; } val = xdigit2val(c); if (i % 2) { byte |= val; filter.bytes[j] = byte; printf("bytes[%d]:%02x ", j, filter.bytes[j]); j++; byte = 0; } else byte |= val << 4; } printf("\n"); /* translate mask string to uint8_t array. */ if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') || (mask_ptr[1] == 'X'))) mask_ptr += 2; len = strnlen(mask_ptr, (res->len_value + 3) / 4); if (len == 0) { printf("invalid input\n"); return; } j = 0; byte = 0; for (i = 0; i < len; i++) { c = mask_ptr[i]; if (isxdigit(c) == 0) { /* invalid characters. */ printf("invalid input\n"); return; } val = xdigit2val(c); if (i % 2) { byte |= val; filter.mask[j] = byte; printf("mask[%d]:%02x ", j, filter.mask[j]); j++; byte = 0; } else byte |= val << 4; } printf("\n"); if (!strcmp(res->ops, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FLEXIBLE, RTE_ETH_FILTER_ADD, &filter); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FLEXIBLE, RTE_ETH_FILTER_DELETE, &filter); if (ret < 0) printf("flex filter setting error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_flex_filter_filter = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, filter, "flex_filter"); cmdline_parse_token_num_t cmd_flex_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, port_id, UINT8); cmdline_parse_token_string_t cmd_flex_filter_ops = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, ops, "add#del"); cmdline_parse_token_string_t cmd_flex_filter_len = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, len, "len"); cmdline_parse_token_num_t cmd_flex_filter_len_value = TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, len_value, UINT8); cmdline_parse_token_string_t cmd_flex_filter_bytes = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, bytes, "bytes"); cmdline_parse_token_string_t cmd_flex_filter_bytes_value = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, bytes_value, NULL); cmdline_parse_token_string_t cmd_flex_filter_mask = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, mask, "mask"); cmdline_parse_token_string_t cmd_flex_filter_mask_value = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, mask_value, NULL); cmdline_parse_token_string_t cmd_flex_filter_priority = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, priority, "priority"); cmdline_parse_token_num_t cmd_flex_filter_priority_value = TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, priority_value, UINT8); cmdline_parse_token_string_t cmd_flex_filter_queue = TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result, queue, "queue"); cmdline_parse_token_num_t cmd_flex_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result, queue_id, UINT16); cmdline_parse_inst_t cmd_flex_filter = { .f = cmd_flex_filter_parsed, .data = NULL, .help_str = "add/del a flex filter", .tokens = { (void *)&cmd_flex_filter_filter, (void *)&cmd_flex_filter_port_id, (void *)&cmd_flex_filter_ops, (void *)&cmd_flex_filter_len, (void *)&cmd_flex_filter_len_value, (void *)&cmd_flex_filter_bytes, (void *)&cmd_flex_filter_bytes_value, (void *)&cmd_flex_filter_mask, (void *)&cmd_flex_filter_mask_value, (void *)&cmd_flex_filter_priority, (void *)&cmd_flex_filter_priority_value, (void *)&cmd_flex_filter_queue, (void *)&cmd_flex_filter_queue_id, NULL, }, }; /* *** Filters Control *** */ /* *** deal with ethertype filter *** */ struct cmd_ethertype_filter_result { cmdline_fixed_string_t filter; uint8_t port_id; cmdline_fixed_string_t ops; cmdline_fixed_string_t mac; struct ether_addr mac_addr; cmdline_fixed_string_t ethertype; uint16_t ethertype_value; cmdline_fixed_string_t drop; cmdline_fixed_string_t queue; uint16_t queue_id; }; cmdline_parse_token_string_t cmd_ethertype_filter_filter = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, filter, "ethertype_filter"); cmdline_parse_token_num_t cmd_ethertype_filter_port_id = TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result, port_id, UINT8); cmdline_parse_token_string_t cmd_ethertype_filter_ops = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, ops, "add#del"); cmdline_parse_token_string_t cmd_ethertype_filter_mac = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, mac, "mac_addr#mac_ignr"); cmdline_parse_token_etheraddr_t cmd_ethertype_filter_mac_addr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_ethertype_filter_result, mac_addr); cmdline_parse_token_string_t cmd_ethertype_filter_ethertype = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, ethertype, "ethertype"); cmdline_parse_token_num_t cmd_ethertype_filter_ethertype_value = TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result, ethertype_value, UINT16); cmdline_parse_token_string_t cmd_ethertype_filter_drop = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, drop, "drop#fwd"); cmdline_parse_token_string_t cmd_ethertype_filter_queue = TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result, queue, "queue"); cmdline_parse_token_num_t cmd_ethertype_filter_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result, queue_id, UINT16); static void cmd_ethertype_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_ethertype_filter_result *res = parsed_result; struct rte_eth_ethertype_filter filter; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_ETHERTYPE); if (ret < 0) { printf("ethertype filter is not supported on port %u.\n", res->port_id); return; } memset(&filter, 0, sizeof(filter)); if (!strcmp(res->mac, "mac_addr")) { filter.flags |= RTE_ETHTYPE_FLAGS_MAC; (void)rte_memcpy(&filter.mac_addr, &res->mac_addr, sizeof(struct ether_addr)); } if (!strcmp(res->drop, "drop")) filter.flags |= RTE_ETHTYPE_FLAGS_DROP; filter.ether_type = res->ethertype_value; filter.queue = res->queue_id; if (!strcmp(res->ops, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_ETHERTYPE, RTE_ETH_FILTER_ADD, &filter); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_ETHERTYPE, RTE_ETH_FILTER_DELETE, &filter); if (ret < 0) printf("ethertype filter programming error: (%s)\n", strerror(-ret)); } cmdline_parse_inst_t cmd_ethertype_filter = { .f = cmd_ethertype_filter_parsed, .data = NULL, .help_str = "add or delete an ethertype filter entry", .tokens = { (void *)&cmd_ethertype_filter_filter, (void *)&cmd_ethertype_filter_port_id, (void *)&cmd_ethertype_filter_ops, (void *)&cmd_ethertype_filter_mac, (void *)&cmd_ethertype_filter_mac_addr, (void *)&cmd_ethertype_filter_ethertype, (void *)&cmd_ethertype_filter_ethertype_value, (void *)&cmd_ethertype_filter_drop, (void *)&cmd_ethertype_filter_queue, (void *)&cmd_ethertype_filter_queue_id, NULL, }, }; /* *** deal with flow director filter *** */ struct cmd_flow_director_result { cmdline_fixed_string_t flow_director_filter; uint8_t port_id; cmdline_fixed_string_t ops; cmdline_fixed_string_t flow; cmdline_fixed_string_t flow_type; cmdline_fixed_string_t ether; uint16_t ether_type; cmdline_fixed_string_t src; cmdline_ipaddr_t ip_src; uint16_t port_src; cmdline_fixed_string_t dst; cmdline_ipaddr_t ip_dst; uint16_t port_dst; cmdline_fixed_string_t verify_tag; uint32_t verify_tag_value; cmdline_fixed_string_t vlan; uint16_t vlan_value; cmdline_fixed_string_t flexbytes; cmdline_fixed_string_t flexbytes_value; cmdline_fixed_string_t drop; cmdline_fixed_string_t queue; uint16_t queue_id; cmdline_fixed_string_t fd_id; uint32_t fd_id_value; }; static inline int parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num) { char s[256]; const char *p, *p0 = q_arg; char *end; unsigned long int_fld; char *str_fld[max_num]; int i; unsigned size; int ret = -1; p = strchr(p0, '('); if (p == NULL) return -1; ++p; p0 = strchr(p, ')'); if (p0 == NULL) return -1; size = p0 - p; if (size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ','); if (ret < 0 || ret > max_num) return -1; for (i = 0; i < ret; i++) { errno = 0; int_fld = strtoul(str_fld[i], &end, 0); if (errno != 0 || *end != '\0' || int_fld > UINT8_MAX) return -1; flexbytes[i] = (uint8_t)int_fld; } return ret; } static uint16_t str2flowtype(char *string) { uint8_t i = 0; static const struct { char str[32]; uint16_t type; } flowtype_str[] = { {"raw", RTE_ETH_FLOW_RAW}, {"ipv4", RTE_ETH_FLOW_IPV4}, {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, {"ipv6", RTE_ETH_FLOW_IPV6}, {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, }; for (i = 0; i < RTE_DIM(flowtype_str); i++) { if (!strcmp(flowtype_str[i].str, string)) return flowtype_str[i].type; } return RTE_ETH_FLOW_UNKNOWN; } #define IPV4_ADDR_TO_UINT(ip_addr, ip) \ do { \ if ((ip_addr).family == AF_INET) \ (ip) = (ip_addr).addr.ipv4.s_addr; \ else { \ printf("invalid parameter.\n"); \ return; \ } \ } while (0) #define IPV6_ADDR_TO_ARRAY(ip_addr, ip) \ do { \ if ((ip_addr).family == AF_INET6) \ (void)rte_memcpy(&(ip), \ &((ip_addr).addr.ipv6), \ sizeof(struct in6_addr)); \ else { \ printf("invalid parameter.\n"); \ return; \ } \ } while (0) static void cmd_flow_director_filter_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_flow_director_result *res = parsed_result; struct rte_eth_fdir_filter entry; uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN]; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR); if (ret < 0) { printf("flow director is not supported on port %u.\n", res->port_id); return; } memset(flexbytes, 0, sizeof(flexbytes)); memset(&entry, 0, sizeof(struct rte_eth_fdir_filter)); ret = parse_flexbytes(res->flexbytes_value, flexbytes, RTE_ETH_FDIR_MAX_FLEXLEN); if (ret < 0) { printf("error: Cannot parse flexbytes input.\n"); return; } entry.input.flow_type = str2flowtype(res->flow_type); switch (entry.input.flow_type) { case RTE_ETH_FLOW_FRAG_IPV4: case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: IPV4_ADDR_TO_UINT(res->ip_dst, entry.input.flow.ip4_flow.dst_ip); IPV4_ADDR_TO_UINT(res->ip_src, entry.input.flow.ip4_flow.src_ip); /* need convert to big endian. */ entry.input.flow.udp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst); entry.input.flow.udp4_flow.src_port = rte_cpu_to_be_16(res->port_src); break; case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: IPV4_ADDR_TO_UINT(res->ip_dst, entry.input.flow.sctp4_flow.ip.dst_ip); IPV4_ADDR_TO_UINT(res->ip_src, entry.input.flow.sctp4_flow.ip.src_ip); /* need convert to big endian. */ #ifdef RTE_NEXT_ABI entry.input.flow.sctp4_flow.dst_port = rte_cpu_to_be_16(res->port_dst); entry.input.flow.sctp4_flow.src_port = rte_cpu_to_be_16(res->port_src); #endif entry.input.flow.sctp4_flow.verify_tag = rte_cpu_to_be_32(res->verify_tag_value); break; case RTE_ETH_FLOW_FRAG_IPV6: case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: IPV6_ADDR_TO_ARRAY(res->ip_dst, entry.input.flow.ipv6_flow.dst_ip); IPV6_ADDR_TO_ARRAY(res->ip_src, entry.input.flow.ipv6_flow.src_ip); /* need convert to big endian. */ entry.input.flow.udp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst); entry.input.flow.udp6_flow.src_port = rte_cpu_to_be_16(res->port_src); break; case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: IPV6_ADDR_TO_ARRAY(res->ip_dst, entry.input.flow.sctp6_flow.ip.dst_ip); IPV6_ADDR_TO_ARRAY(res->ip_src, entry.input.flow.sctp6_flow.ip.src_ip); /* need convert to big endian. */ #ifdef RTE_NEXT_ABI entry.input.flow.sctp6_flow.dst_port = rte_cpu_to_be_16(res->port_dst); entry.input.flow.sctp6_flow.src_port = rte_cpu_to_be_16(res->port_src); #endif entry.input.flow.sctp6_flow.verify_tag = rte_cpu_to_be_32(res->verify_tag_value); break; case RTE_ETH_FLOW_L2_PAYLOAD: entry.input.flow.l2_flow.ether_type = rte_cpu_to_be_16(res->ether_type); break; default: printf("invalid parameter.\n"); return; } (void)rte_memcpy(entry.input.flow_ext.flexbytes, flexbytes, RTE_ETH_FDIR_MAX_FLEXLEN); entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(res->vlan_value); entry.action.flex_off = 0; /*use 0 by default */ if (!strcmp(res->drop, "drop")) entry.action.behavior = RTE_ETH_FDIR_REJECT; else entry.action.behavior = RTE_ETH_FDIR_ACCEPT; /* set to report FD ID by default */ entry.action.report_status = RTE_ETH_FDIR_REPORT_ID; entry.action.rx_queue = res->queue_id; entry.soft_id = res->fd_id_value; if (!strcmp(res->ops, "add")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_ADD, &entry); else if (!strcmp(res->ops, "del")) ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_DELETE, &entry); else ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_UPDATE, &entry); if (ret < 0) printf("flow director programming error: (%s)\n", strerror(-ret)); } cmdline_parse_token_string_t cmd_flow_director_filter = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, flow_director_filter, "flow_director_filter"); cmdline_parse_token_num_t cmd_flow_director_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, port_id, UINT8); cmdline_parse_token_string_t cmd_flow_director_ops = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, ops, "add#del#update"); cmdline_parse_token_string_t cmd_flow_director_flow = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, flow, "flow"); cmdline_parse_token_string_t cmd_flow_director_flow_type = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, flow_type, "ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#" "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload"); cmdline_parse_token_string_t cmd_flow_director_ether = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, ether, "ether"); cmdline_parse_token_num_t cmd_flow_director_ether_type = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, ether_type, UINT16); cmdline_parse_token_string_t cmd_flow_director_src = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, src, "src"); cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result, ip_src); cmdline_parse_token_num_t cmd_flow_director_port_src = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, port_src, UINT16); cmdline_parse_token_string_t cmd_flow_director_dst = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, dst, "dst"); cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result, ip_dst); cmdline_parse_token_num_t cmd_flow_director_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, port_dst, UINT16); cmdline_parse_token_string_t cmd_flow_director_verify_tag = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, verify_tag, "verify_tag"); cmdline_parse_token_num_t cmd_flow_director_verify_tag_value = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, verify_tag_value, UINT32); cmdline_parse_token_string_t cmd_flow_director_vlan = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, vlan, "vlan"); cmdline_parse_token_num_t cmd_flow_director_vlan_value = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, vlan_value, UINT16); cmdline_parse_token_string_t cmd_flow_director_flexbytes = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, flexbytes, "flexbytes"); cmdline_parse_token_string_t cmd_flow_director_flexbytes_value = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, flexbytes_value, NULL); cmdline_parse_token_string_t cmd_flow_director_drop = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, drop, "drop#fwd"); cmdline_parse_token_string_t cmd_flow_director_queue = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, queue, "queue"); cmdline_parse_token_num_t cmd_flow_director_queue_id = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, queue_id, UINT16); cmdline_parse_token_string_t cmd_flow_director_fd_id = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result, fd_id, "fd_id"); cmdline_parse_token_num_t cmd_flow_director_fd_id_value = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result, fd_id_value, UINT32); cmdline_parse_inst_t cmd_add_del_ip_flow_director = { .f = cmd_flow_director_filter_parsed, .data = NULL, .help_str = "add or delete an ip flow director entry on NIC", .tokens = { (void *)&cmd_flow_director_filter, (void *)&cmd_flow_director_port_id, (void *)&cmd_flow_director_ops, (void *)&cmd_flow_director_flow, (void *)&cmd_flow_director_flow_type, (void *)&cmd_flow_director_src, (void *)&cmd_flow_director_ip_src, (void *)&cmd_flow_director_dst, (void *)&cmd_flow_director_ip_dst, (void *)&cmd_flow_director_vlan, (void *)&cmd_flow_director_vlan_value, (void *)&cmd_flow_director_flexbytes, (void *)&cmd_flow_director_flexbytes_value, (void *)&cmd_flow_director_drop, (void *)&cmd_flow_director_queue, (void *)&cmd_flow_director_queue_id, (void *)&cmd_flow_director_fd_id, (void *)&cmd_flow_director_fd_id_value, NULL, }, }; cmdline_parse_inst_t cmd_add_del_udp_flow_director = { .f = cmd_flow_director_filter_parsed, .data = NULL, .help_str = "add or delete an udp/tcp flow director entry on NIC", .tokens = { (void *)&cmd_flow_director_filter, (void *)&cmd_flow_director_port_id, (void *)&cmd_flow_director_ops, (void *)&cmd_flow_director_flow, (void *)&cmd_flow_director_flow_type, (void *)&cmd_flow_director_src, (void *)&cmd_flow_director_ip_src, (void *)&cmd_flow_director_port_src, (void *)&cmd_flow_director_dst, (void *)&cmd_flow_director_ip_dst, (void *)&cmd_flow_director_port_dst, (void *)&cmd_flow_director_vlan, (void *)&cmd_flow_director_vlan_value, (void *)&cmd_flow_director_flexbytes, (void *)&cmd_flow_director_flexbytes_value, (void *)&cmd_flow_director_drop, (void *)&cmd_flow_director_queue, (void *)&cmd_flow_director_queue_id, (void *)&cmd_flow_director_fd_id, (void *)&cmd_flow_director_fd_id_value, NULL, }, }; cmdline_parse_inst_t cmd_add_del_sctp_flow_director = { .f = cmd_flow_director_filter_parsed, .data = NULL, .help_str = "add or delete a sctp flow director entry on NIC", .tokens = { (void *)&cmd_flow_director_filter, (void *)&cmd_flow_director_port_id, (void *)&cmd_flow_director_ops, (void *)&cmd_flow_director_flow, (void *)&cmd_flow_director_flow_type, (void *)&cmd_flow_director_src, (void *)&cmd_flow_director_ip_src, (void *)&cmd_flow_director_port_dst, (void *)&cmd_flow_director_dst, (void *)&cmd_flow_director_ip_dst, (void *)&cmd_flow_director_port_dst, (void *)&cmd_flow_director_verify_tag, (void *)&cmd_flow_director_verify_tag_value, (void *)&cmd_flow_director_vlan, (void *)&cmd_flow_director_vlan_value, (void *)&cmd_flow_director_flexbytes, (void *)&cmd_flow_director_flexbytes_value, (void *)&cmd_flow_director_drop, (void *)&cmd_flow_director_queue, (void *)&cmd_flow_director_queue_id, (void *)&cmd_flow_director_fd_id, (void *)&cmd_flow_director_fd_id_value, NULL, }, }; cmdline_parse_inst_t cmd_add_del_l2_flow_director = { .f = cmd_flow_director_filter_parsed, .data = NULL, .help_str = "add or delete a L2 flow director entry on NIC", .tokens = { (void *)&cmd_flow_director_filter, (void *)&cmd_flow_director_port_id, (void *)&cmd_flow_director_ops, (void *)&cmd_flow_director_flow, (void *)&cmd_flow_director_flow_type, (void *)&cmd_flow_director_ether, (void *)&cmd_flow_director_ether_type, (void *)&cmd_flow_director_flexbytes, (void *)&cmd_flow_director_flexbytes_value, (void *)&cmd_flow_director_drop, (void *)&cmd_flow_director_queue, (void *)&cmd_flow_director_queue_id, (void *)&cmd_flow_director_fd_id, (void *)&cmd_flow_director_fd_id_value, NULL, }, }; struct cmd_flush_flow_director_result { cmdline_fixed_string_t flush_flow_director; uint8_t port_id; }; cmdline_parse_token_string_t cmd_flush_flow_director_flush = TOKEN_STRING_INITIALIZER(struct cmd_flush_flow_director_result, flush_flow_director, "flush_flow_director"); cmdline_parse_token_num_t cmd_flush_flow_director_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flush_flow_director_result, port_id, UINT8); static void cmd_flush_flow_director_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_flow_director_result *res = parsed_result; int ret = 0; ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR); if (ret < 0) { printf("flow director is not supported on port %u.\n", res->port_id); return; } ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_FLUSH, NULL); if (ret < 0) printf("flow director table flushing error: (%s)\n", strerror(-ret)); } cmdline_parse_inst_t cmd_flush_flow_director = { .f = cmd_flush_flow_director_parsed, .data = NULL, .help_str = "flush all flow director entries of a device on NIC", .tokens = { (void *)&cmd_flush_flow_director_flush, (void *)&cmd_flush_flow_director_port_id, NULL, }, }; /* *** deal with flow director mask *** */ struct cmd_flow_director_mask_result { cmdline_fixed_string_t flow_director_mask; uint8_t port_id; cmdline_fixed_string_t vlan; uint16_t vlan_value; cmdline_fixed_string_t src_mask; cmdline_ipaddr_t ipv4_src; cmdline_ipaddr_t ipv6_src; uint16_t port_src; cmdline_fixed_string_t dst_mask; cmdline_ipaddr_t ipv4_dst; cmdline_ipaddr_t ipv6_dst; uint16_t port_dst; }; static void cmd_flow_director_mask_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_flow_director_mask_result *res = parsed_result; struct rte_eth_fdir_masks *mask; struct rte_port *port; if (res->port_id > nb_ports) { printf("Invalid port, range is [0, %d]\n", nb_ports - 1); return; } port = &ports[res->port_id]; /** Check if the port is not started **/ if (port->port_status != RTE_PORT_STOPPED) { printf("Please stop port %d first\n", res->port_id); return; } mask = &port->dev_conf.fdir_conf.mask; mask->vlan_tci_mask = res->vlan_value; IPV4_ADDR_TO_UINT(res->ipv4_src, mask->ipv4_mask.src_ip); IPV4_ADDR_TO_UINT(res->ipv4_dst, mask->ipv4_mask.dst_ip); IPV6_ADDR_TO_ARRAY(res->ipv6_src, mask->ipv6_mask.src_ip); IPV6_ADDR_TO_ARRAY(res->ipv6_dst, mask->ipv6_mask.dst_ip); mask->src_port_mask = res->port_src; mask->dst_port_mask = res->port_dst; cmd_reconfig_device_queue(res->port_id, 1, 1); } cmdline_parse_token_string_t cmd_flow_director_mask = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result, flow_director_mask, "flow_director_mask"); cmdline_parse_token_num_t cmd_flow_director_mask_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result, port_id, UINT8); cmdline_parse_token_string_t cmd_flow_director_mask_vlan = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result, vlan, "vlan"); cmdline_parse_token_num_t cmd_flow_director_mask_vlan_value = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result, vlan_value, UINT16); cmdline_parse_token_string_t cmd_flow_director_mask_src = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result, src_mask, "src_mask"); cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_src = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result, ipv4_src); cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_src = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result, ipv6_src); cmdline_parse_token_num_t cmd_flow_director_mask_port_src = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result, port_src, UINT16); cmdline_parse_token_string_t cmd_flow_director_mask_dst = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result, dst_mask, "dst_mask"); cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_dst = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result, ipv4_dst); cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_dst = TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result, ipv6_dst); cmdline_parse_token_num_t cmd_flow_director_mask_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result, port_dst, UINT16); cmdline_parse_inst_t cmd_set_flow_director_mask = { .f = cmd_flow_director_mask_parsed, .data = NULL, .help_str = "set flow director's mask on NIC", .tokens = { (void *)&cmd_flow_director_mask, (void *)&cmd_flow_director_mask_port_id, (void *)&cmd_flow_director_mask_vlan, (void *)&cmd_flow_director_mask_vlan_value, (void *)&cmd_flow_director_mask_src, (void *)&cmd_flow_director_mask_ipv4_src, (void *)&cmd_flow_director_mask_ipv6_src, (void *)&cmd_flow_director_mask_port_src, (void *)&cmd_flow_director_mask_dst, (void *)&cmd_flow_director_mask_ipv4_dst, (void *)&cmd_flow_director_mask_ipv6_dst, (void *)&cmd_flow_director_mask_port_dst, NULL, }, }; /* *** deal with flow director mask on flexible payload *** */ struct cmd_flow_director_flex_mask_result { cmdline_fixed_string_t flow_director_flexmask; uint8_t port_id; cmdline_fixed_string_t flow; cmdline_fixed_string_t flow_type; cmdline_fixed_string_t mask; }; static void cmd_flow_director_flex_mask_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_flow_director_flex_mask_result *res = parsed_result; struct rte_eth_fdir_info fdir_info; struct rte_eth_fdir_flex_mask flex_mask; struct rte_port *port; uint32_t flow_type_mask; uint16_t i; int ret; if (res->port_id > nb_ports) { printf("Invalid port, range is [0, %d]\n", nb_ports - 1); return; } port = &ports[res->port_id]; /** Check if the port is not started **/ if (port->port_status != RTE_PORT_STOPPED) { printf("Please stop port %d first\n", res->port_id); return; } memset(&flex_mask, 0, sizeof(struct rte_eth_fdir_flex_mask)); ret = parse_flexbytes(res->mask, flex_mask.mask, RTE_ETH_FDIR_MAX_FLEXLEN); if (ret < 0) { printf("error: Cannot parse mask input.\n"); return; } memset(&fdir_info, 0, sizeof(fdir_info)); ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_INFO, &fdir_info); if (ret < 0) { printf("Cannot get FDir filter info\n"); return; } if (!strcmp(res->flow_type, "none")) { /* means don't specify the flow type */ flex_mask.flow_type = RTE_ETH_FLOW_UNKNOWN; for (i = 0; i < RTE_ETH_FLOW_MAX; i++) memset(&port->dev_conf.fdir_conf.flex_conf.flex_mask[i], 0, sizeof(struct rte_eth_fdir_flex_mask)); port->dev_conf.fdir_conf.flex_conf.nb_flexmasks = 1; (void)rte_memcpy(&port->dev_conf.fdir_conf.flex_conf.flex_mask[0], &flex_mask, sizeof(struct rte_eth_fdir_flex_mask)); cmd_reconfig_device_queue(res->port_id, 1, 1); return; } flow_type_mask = fdir_info.flow_types_mask[0]; if (!strcmp(res->flow_type, "all")) { if (!flow_type_mask) { printf("No flow type supported\n"); return; } for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) { if (flow_type_mask & (1 << i)) { flex_mask.flow_type = i; fdir_set_flex_mask(res->port_id, &flex_mask); } } cmd_reconfig_device_queue(res->port_id, 1, 1); return; } flex_mask.flow_type = str2flowtype(res->flow_type); if (!(flow_type_mask & (1 << flex_mask.flow_type))) { printf("Flow type %s not supported on port %d\n", res->flow_type, res->port_id); return; } fdir_set_flex_mask(res->port_id, &flex_mask); cmd_reconfig_device_queue(res->port_id, 1, 1); } cmdline_parse_token_string_t cmd_flow_director_flexmask = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result, flow_director_flexmask, "flow_director_flex_mask"); cmdline_parse_token_num_t cmd_flow_director_flexmask_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flex_mask_result, port_id, UINT8); cmdline_parse_token_string_t cmd_flow_director_flexmask_flow = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result, flow, "flow"); cmdline_parse_token_string_t cmd_flow_director_flexmask_flow_type = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result, flow_type, "none#ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#" "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload#all"); cmdline_parse_token_string_t cmd_flow_director_flexmask_mask = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result, mask, NULL); cmdline_parse_inst_t cmd_set_flow_director_flex_mask = { .f = cmd_flow_director_flex_mask_parsed, .data = NULL, .help_str = "set flow director's flex mask on NIC", .tokens = { (void *)&cmd_flow_director_flexmask, (void *)&cmd_flow_director_flexmask_port_id, (void *)&cmd_flow_director_flexmask_flow, (void *)&cmd_flow_director_flexmask_flow_type, (void *)&cmd_flow_director_flexmask_mask, NULL, }, }; /* *** deal with flow director flexible payload configuration *** */ struct cmd_flow_director_flexpayload_result { cmdline_fixed_string_t flow_director_flexpayload; uint8_t port_id; cmdline_fixed_string_t payload_layer; cmdline_fixed_string_t payload_cfg; }; static inline int parse_offsets(const char *q_arg, uint16_t *offsets, uint16_t max_num) { char s[256]; const char *p, *p0 = q_arg; char *end; unsigned long int_fld; char *str_fld[max_num]; int i; unsigned size; int ret = -1; p = strchr(p0, '('); if (p == NULL) return -1; ++p; p0 = strchr(p, ')'); if (p0 == NULL) return -1; size = p0 - p; if (size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ','); if (ret < 0 || ret > max_num) return -1; for (i = 0; i < ret; i++) { errno = 0; int_fld = strtoul(str_fld[i], &end, 0); if (errno != 0 || *end != '\0' || int_fld > UINT16_MAX) return -1; offsets[i] = (uint16_t)int_fld; } return ret; } static void cmd_flow_director_flxpld_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_flow_director_flexpayload_result *res = parsed_result; struct rte_eth_flex_payload_cfg flex_cfg; struct rte_port *port; int ret = 0; if (res->port_id > nb_ports) { printf("Invalid port, range is [0, %d]\n", nb_ports - 1); return; } port = &ports[res->port_id]; /** Check if the port is not started **/ if (port->port_status != RTE_PORT_STOPPED) { printf("Please stop port %d first\n", res->port_id); return; } memset(&flex_cfg, 0, sizeof(struct rte_eth_flex_payload_cfg)); if (!strcmp(res->payload_layer, "raw")) flex_cfg.type = RTE_ETH_RAW_PAYLOAD; else if (!strcmp(res->payload_layer, "l2")) flex_cfg.type = RTE_ETH_L2_PAYLOAD; else if (!strcmp(res->payload_layer, "l3")) flex_cfg.type = RTE_ETH_L3_PAYLOAD; else if (!strcmp(res->payload_layer, "l4")) flex_cfg.type = RTE_ETH_L4_PAYLOAD; ret = parse_offsets(res->payload_cfg, flex_cfg.src_offset, RTE_ETH_FDIR_MAX_FLEXLEN); if (ret < 0) { printf("error: Cannot parse flex payload input.\n"); return; } fdir_set_flex_payload(res->port_id, &flex_cfg); cmd_reconfig_device_queue(res->port_id, 1, 1); } cmdline_parse_token_string_t cmd_flow_director_flexpayload = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result, flow_director_flexpayload, "flow_director_flex_payload"); cmdline_parse_token_num_t cmd_flow_director_flexpayload_port_id = TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flexpayload_result, port_id, UINT8); cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_layer = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result, payload_layer, "raw#l2#l3#l4"); cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_cfg = TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result, payload_cfg, NULL); cmdline_parse_inst_t cmd_set_flow_director_flex_payload = { .f = cmd_flow_director_flxpld_parsed, .data = NULL, .help_str = "set flow director's flex payload on NIC", .tokens = { (void *)&cmd_flow_director_flexpayload, (void *)&cmd_flow_director_flexpayload_port_id, (void *)&cmd_flow_director_flexpayload_payload_layer, (void *)&cmd_flow_director_flexpayload_payload_cfg, NULL, }, }; /* *** Classification Filters Control *** */ /* *** Get symmetric hash enable per port *** */ struct cmd_get_sym_hash_ena_per_port_result { cmdline_fixed_string_t get_sym_hash_ena_per_port; uint8_t port_id; }; static void cmd_get_sym_hash_per_port_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { struct cmd_get_sym_hash_ena_per_port_result *res = parsed_result; struct rte_eth_hash_filter_info info; int ret; if (rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_HASH) < 0) { printf("RTE_ETH_FILTER_HASH not supported on port: %d\n", res->port_id); return; } memset(&info, 0, sizeof(info)); info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT; ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_GET, &info); if (ret < 0) { printf("Cannot get symmetric hash enable per port " "on port %u\n", res->port_id); return; } printf("Symmetric hash is %s on port %u\n", info.info.enable ? "enabled" : "disabled", res->port_id); } cmdline_parse_token_string_t cmd_get_sym_hash_ena_per_port_all = TOKEN_STRING_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result, get_sym_hash_ena_per_port, "get_sym_hash_ena_per_port"); cmdline_parse_token_num_t cmd_get_sym_hash_ena_per_port_port_id = TOKEN_NUM_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result, port_id, UINT8); cmdline_parse_inst_t cmd_get_sym_hash_ena_per_port = { .f = cmd_get_sym_hash_per_port_parsed, .data = NULL, .help_str = "get_sym_hash_ena_per_port port_id", .tokens = { (void *)&cmd_get_sym_hash_ena_per_port_all, (void *)&cmd_get_sym_hash_ena_per_port_port_id, NULL, }, }; /* *** Set symmetric hash enable per port *** */ struct cmd_set_sym_hash_ena_per_port_result { cmdline_fixed_string_t set_sym_hash_ena_per_port; cmdline_fixed_string_t enable; uint8_t port_id; }; static void cmd_set_sym_hash_per_port_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { struct cmd_set_sym_hash_ena_per_port_result *res = parsed_result; struct rte_eth_hash_filter_info info; int ret; if (rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_HASH) < 0) { printf("RTE_ETH_FILTER_HASH not supported on port: %d\n", res->port_id); return; } memset(&info, 0, sizeof(info)); info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT; if (!strcmp(res->enable, "enable")) info.info.enable = 1; ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_SET, &info); if (ret < 0) { printf("Cannot set symmetric hash enable per port on " "port %u\n", res->port_id); return; } printf("Symmetric hash has been set to %s on port %u\n", res->enable, res->port_id); } cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_all = TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result, set_sym_hash_ena_per_port, "set_sym_hash_ena_per_port"); cmdline_parse_token_num_t cmd_set_sym_hash_ena_per_port_port_id = TOKEN_NUM_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result, port_id, UINT8); cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_enable = TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result, enable, "enable#disable"); cmdline_parse_inst_t cmd_set_sym_hash_ena_per_port = { .f = cmd_set_sym_hash_per_port_parsed, .data = NULL, .help_str = "set_sym_hash_ena_per_port port_id enable|disable", .tokens = { (void *)&cmd_set_sym_hash_ena_per_port_all, (void *)&cmd_set_sym_hash_ena_per_port_port_id, (void *)&cmd_set_sym_hash_ena_per_port_enable, NULL, }, }; /* Get global config of hash function */ struct cmd_get_hash_global_config_result { cmdline_fixed_string_t get_hash_global_config; uint8_t port_id; }; static char * flowtype_to_str(uint16_t ftype) { uint16_t i; static struct { char str[16]; uint16_t ftype; } ftype_table[] = { {"ipv4", RTE_ETH_FLOW_IPV4}, {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, {"ipv6", RTE_ETH_FLOW_IPV6}, {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, }; for (i = 0; i < RTE_DIM(ftype_table); i++) { if (ftype_table[i].ftype == ftype) return ftype_table[i].str; } return NULL; } static void cmd_get_hash_global_config_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { struct cmd_get_hash_global_config_result *res = parsed_result; struct rte_eth_hash_filter_info info; uint32_t idx, offset; uint16_t i; char *str; int ret; if (rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_HASH) < 0) { printf("RTE_ETH_FILTER_HASH not supported on port %d\n", res->port_id); return; } memset(&info, 0, sizeof(info)); info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG; ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_GET, &info); if (ret < 0) { printf("Cannot get hash global configurations by port %d\n", res->port_id); return; } switch (info.info.global_conf.hash_func) { case RTE_ETH_HASH_FUNCTION_TOEPLITZ: printf("Hash function is Toeplitz\n"); break; case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR: printf("Hash function is Simple XOR\n"); break; default: printf("Unknown hash function\n"); break; } for (i = 0; i < RTE_ETH_FLOW_MAX; i++) { idx = i / UINT32_BIT; offset = i % UINT32_BIT; if (!(info.info.global_conf.valid_bit_mask[idx] & (1UL << offset))) continue; str = flowtype_to_str(i); if (!str) continue; printf("Symmetric hash is %s globally for flow type %s " "by port %d\n", ((info.info.global_conf.sym_hash_enable_mask[idx] & (1UL << offset)) ? "enabled" : "disabled"), str, res->port_id); } } cmdline_parse_token_string_t cmd_get_hash_global_config_all = TOKEN_STRING_INITIALIZER(struct cmd_get_hash_global_config_result, get_hash_global_config, "get_hash_global_config"); cmdline_parse_token_num_t cmd_get_hash_global_config_port_id = TOKEN_NUM_INITIALIZER(struct cmd_get_hash_global_config_result, port_id, UINT8); cmdline_parse_inst_t cmd_get_hash_global_config = { .f = cmd_get_hash_global_config_parsed, .data = NULL, .help_str = "get_hash_global_config port_id", .tokens = { (void *)&cmd_get_hash_global_config_all, (void *)&cmd_get_hash_global_config_port_id, NULL, }, }; /* Set global config of hash function */ struct cmd_set_hash_global_config_result { cmdline_fixed_string_t set_hash_global_config; uint8_t port_id; cmdline_fixed_string_t hash_func; cmdline_fixed_string_t flow_type; cmdline_fixed_string_t enable; }; static void cmd_set_hash_global_config_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { struct cmd_set_hash_global_config_result *res = parsed_result; struct rte_eth_hash_filter_info info; uint32_t ftype, idx, offset; int ret; if (rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_HASH) < 0) { printf("RTE_ETH_FILTER_HASH not supported on port %d\n", res->port_id); return; } memset(&info, 0, sizeof(info)); info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG; if (!strcmp(res->hash_func, "toeplitz")) info.info.global_conf.hash_func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; else if (!strcmp(res->hash_func, "simple_xor")) info.info.global_conf.hash_func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; else if (!strcmp(res->hash_func, "default")) info.info.global_conf.hash_func = RTE_ETH_HASH_FUNCTION_DEFAULT; ftype = str2flowtype(res->flow_type); idx = ftype / (CHAR_BIT * sizeof(uint32_t)); offset = ftype % (CHAR_BIT * sizeof(uint32_t)); info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset); if (!strcmp(res->enable, "enable")) info.info.global_conf.sym_hash_enable_mask[idx] |= (1UL << offset); ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_SET, &info); if (ret < 0) printf("Cannot set global hash configurations by port %d\n", res->port_id); else printf("Global hash configurations have been set " "succcessfully by port %d\n", res->port_id); } cmdline_parse_token_string_t cmd_set_hash_global_config_all = TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result, set_hash_global_config, "set_hash_global_config"); cmdline_parse_token_num_t cmd_set_hash_global_config_port_id = TOKEN_NUM_INITIALIZER(struct cmd_set_hash_global_config_result, port_id, UINT8); cmdline_parse_token_string_t cmd_set_hash_global_config_hash_func = TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result, hash_func, "toeplitz#simple_xor#default"); cmdline_parse_token_string_t cmd_set_hash_global_config_flow_type = TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result, flow_type, "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); cmdline_parse_token_string_t cmd_set_hash_global_config_enable = TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result, enable, "enable#disable"); cmdline_parse_inst_t cmd_set_hash_global_config = { .f = cmd_set_hash_global_config_parsed, .data = NULL, .help_str = "set_hash_global_config port_id " "toeplitz|simple_xor|default " "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " "enable|disable", .tokens = { (void *)&cmd_set_hash_global_config_all, (void *)&cmd_set_hash_global_config_port_id, (void *)&cmd_set_hash_global_config_hash_func, (void *)&cmd_set_hash_global_config_flow_type, (void *)&cmd_set_hash_global_config_enable, NULL, }, }; /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; cmdline_fixed_string_t what; uint8_t port_num; struct ether_addr mc_addr; }; static void cmd_mcast_addr_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_mcast_addr_result *res = parsed_result; if (!is_multicast_ether_addr(&res->mc_addr)) { printf("Invalid multicast addr %02X:%02X:%02X:%02X:%02X:%02X\n", res->mc_addr.addr_bytes[0], res->mc_addr.addr_bytes[1], res->mc_addr.addr_bytes[2], res->mc_addr.addr_bytes[3], res->mc_addr.addr_bytes[4], res->mc_addr.addr_bytes[5]); return; } if (strcmp(res->what, "add") == 0) mcast_addr_add(res->port_num, &res->mc_addr); else mcast_addr_remove(res->port_num, &res->mc_addr); } cmdline_parse_token_string_t cmd_mcast_addr_cmd = TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, mcast_addr_cmd, "mcast_addr"); cmdline_parse_token_string_t cmd_mcast_addr_what = TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, what, "add#remove"); cmdline_parse_token_num_t cmd_mcast_addr_portnum = TOKEN_NUM_INITIALIZER(struct cmd_mcast_addr_result, port_num, UINT8); cmdline_parse_token_etheraddr_t cmd_mcast_addr_addr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address); cmdline_parse_inst_t cmd_mcast_addr = { .f = cmd_mcast_addr_parsed, .data = (void *)0, .help_str = "mcast_addr add|remove X : add/remove multicast MAC address on port X", .tokens = { (void *)&cmd_mcast_addr_cmd, (void *)&cmd_mcast_addr_what, (void *)&cmd_mcast_addr_portnum, (void *)&cmd_mcast_addr_addr, NULL, }, }; /* ******************************************************************************** */ /* list of instructions */ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_brief, (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_showport, (cmdline_parse_inst_t *)&cmd_showportall, (cmdline_parse_inst_t *)&cmd_showcfg, (cmdline_parse_inst_t *)&cmd_start, (cmdline_parse_inst_t *)&cmd_start_tx_first, (cmdline_parse_inst_t *)&cmd_set_link_up, (cmdline_parse_inst_t *)&cmd_set_link_down, (cmdline_parse_inst_t *)&cmd_reset, (cmdline_parse_inst_t *)&cmd_set_numbers, (cmdline_parse_inst_t *)&cmd_set_txpkts, (cmdline_parse_inst_t *)&cmd_set_fwd_list, (cmdline_parse_inst_t *)&cmd_set_fwd_mask, (cmdline_parse_inst_t *)&cmd_set_fwd_mode, (cmdline_parse_inst_t *)&cmd_set_burst_tx_retry, (cmdline_parse_inst_t *)&cmd_set_promisc_mode_one, (cmdline_parse_inst_t *)&cmd_set_promisc_mode_all, (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_one, (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_all, (cmdline_parse_inst_t *)&cmd_set_flush_rx, (cmdline_parse_inst_t *)&cmd_set_link_check, #ifdef RTE_NIC_BYPASS (cmdline_parse_inst_t *)&cmd_set_bypass_mode, (cmdline_parse_inst_t *)&cmd_set_bypass_event, (cmdline_parse_inst_t *)&cmd_set_bypass_timeout, (cmdline_parse_inst_t *)&cmd_show_bypass_config, #endif #ifdef RTE_LIBRTE_PMD_BOND (cmdline_parse_inst_t *) &cmd_set_bonding_mode, (cmdline_parse_inst_t *) &cmd_show_bonding_config, (cmdline_parse_inst_t *) &cmd_set_bonding_primary, (cmdline_parse_inst_t *) &cmd_add_bonding_slave, (cmdline_parse_inst_t *) &cmd_remove_bonding_slave, (cmdline_parse_inst_t *) &cmd_create_bonded_device, (cmdline_parse_inst_t *) &cmd_set_bond_mac_addr, (cmdline_parse_inst_t *) &cmd_set_balance_xmit_policy, (cmdline_parse_inst_t *) &cmd_set_bond_mon_period, #endif (cmdline_parse_inst_t *)&cmd_vlan_offload, (cmdline_parse_inst_t *)&cmd_vlan_tpid, (cmdline_parse_inst_t *)&cmd_rx_vlan_filter_all, (cmdline_parse_inst_t *)&cmd_rx_vlan_filter, (cmdline_parse_inst_t *)&cmd_tx_vlan_set, (cmdline_parse_inst_t *)&cmd_tx_vlan_set_qinq, (cmdline_parse_inst_t *)&cmd_tx_vlan_reset, (cmdline_parse_inst_t *)&cmd_tx_vlan_set_pvid, (cmdline_parse_inst_t *)&cmd_csum_set, (cmdline_parse_inst_t *)&cmd_csum_show, (cmdline_parse_inst_t *)&cmd_csum_tunnel, (cmdline_parse_inst_t *)&cmd_tso_set, (cmdline_parse_inst_t *)&cmd_tso_show, (cmdline_parse_inst_t *)&cmd_link_flow_control_set, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_rx, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_tx, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_hw, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_lw, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_pt, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_xon, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_macfwd, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_autoneg, (cmdline_parse_inst_t *)&cmd_priority_flow_control_set, (cmdline_parse_inst_t *)&cmd_config_dcb, (cmdline_parse_inst_t *)&cmd_read_reg, (cmdline_parse_inst_t *)&cmd_read_reg_bit_field, (cmdline_parse_inst_t *)&cmd_read_reg_bit, (cmdline_parse_inst_t *)&cmd_write_reg, (cmdline_parse_inst_t *)&cmd_write_reg_bit_field, (cmdline_parse_inst_t *)&cmd_write_reg_bit, (cmdline_parse_inst_t *)&cmd_read_rxd_txd, (cmdline_parse_inst_t *)&cmd_stop, (cmdline_parse_inst_t *)&cmd_mac_addr, (cmdline_parse_inst_t *)&cmd_set_qmap, (cmdline_parse_inst_t *)&cmd_operate_port, (cmdline_parse_inst_t *)&cmd_operate_specific_port, (cmdline_parse_inst_t *)&cmd_operate_attach_port, (cmdline_parse_inst_t *)&cmd_operate_detach_port, (cmdline_parse_inst_t *)&cmd_config_speed_all, (cmdline_parse_inst_t *)&cmd_config_speed_specific, (cmdline_parse_inst_t *)&cmd_config_rx_tx, (cmdline_parse_inst_t *)&cmd_config_mtu, (cmdline_parse_inst_t *)&cmd_config_max_pkt_len, (cmdline_parse_inst_t *)&cmd_config_rx_mode_flag, (cmdline_parse_inst_t *)&cmd_config_rss, (cmdline_parse_inst_t *)&cmd_config_rxtx_queue, (cmdline_parse_inst_t *)&cmd_config_rss_reta, (cmdline_parse_inst_t *)&cmd_showport_reta, (cmdline_parse_inst_t *)&cmd_config_burst, (cmdline_parse_inst_t *)&cmd_config_thresh, (cmdline_parse_inst_t *)&cmd_config_threshold, (cmdline_parse_inst_t *)&cmd_set_vf_rxmode, (cmdline_parse_inst_t *)&cmd_set_uc_hash_filter, (cmdline_parse_inst_t *)&cmd_set_uc_all_hash_filter, (cmdline_parse_inst_t *)&cmd_vf_mac_addr_filter, (cmdline_parse_inst_t *)&cmd_set_vf_macvlan_filter, (cmdline_parse_inst_t *)&cmd_set_vf_traffic, (cmdline_parse_inst_t *)&cmd_vf_rxvlan_filter, (cmdline_parse_inst_t *)&cmd_queue_rate_limit, (cmdline_parse_inst_t *)&cmd_vf_rate_limit, (cmdline_parse_inst_t *)&cmd_tunnel_filter, (cmdline_parse_inst_t *)&cmd_tunnel_udp_config, (cmdline_parse_inst_t *)&cmd_set_mirror_mask, (cmdline_parse_inst_t *)&cmd_set_mirror_link, (cmdline_parse_inst_t *)&cmd_reset_mirror_rule, (cmdline_parse_inst_t *)&cmd_showport_rss_hash, (cmdline_parse_inst_t *)&cmd_showport_rss_hash_key, (cmdline_parse_inst_t *)&cmd_config_rss_hash_key, (cmdline_parse_inst_t *)&cmd_dump, (cmdline_parse_inst_t *)&cmd_dump_one, (cmdline_parse_inst_t *)&cmd_ethertype_filter, (cmdline_parse_inst_t *)&cmd_syn_filter, (cmdline_parse_inst_t *)&cmd_2tuple_filter, (cmdline_parse_inst_t *)&cmd_5tuple_filter, (cmdline_parse_inst_t *)&cmd_flex_filter, (cmdline_parse_inst_t *)&cmd_add_del_ip_flow_director, (cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director, (cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director, (cmdline_parse_inst_t *)&cmd_add_del_l2_flow_director, (cmdline_parse_inst_t *)&cmd_flush_flow_director, (cmdline_parse_inst_t *)&cmd_set_flow_director_mask, (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_mask, (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload, (cmdline_parse_inst_t *)&cmd_get_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; /* prompt function, called from main on MASTER lcore */ void prompt(void) { struct cmdline *cl; /* initialize non-constant commands */ cmd_set_fwd_mode_init(); cl = cmdline_stdin_new(main_ctx, "testpmd> "); if (cl == NULL) { return; } cmdline_interact(cl); cmdline_stdin_exit(cl); } static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue) { if (id == (portid_t)RTE_PORT_ALL) { portid_t pid; FOREACH_PORT(pid, ports) { /* check if need_reconfig has been set to 1 */ if (ports[pid].need_reconfig == 0) ports[pid].need_reconfig = dev; /* check if need_reconfig_queues has been set to 1 */ if (ports[pid].need_reconfig_queues == 0) ports[pid].need_reconfig_queues = queue; } } else if (!port_id_is_invalid(id, DISABLED_WARN)) { /* check if need_reconfig has been set to 1 */ if (ports[id].need_reconfig == 0) ports[id].need_reconfig = dev; /* check if need_reconfig_queues has been set to 1 */ if (ports[id].need_reconfig_queues == 0) ports[id].need_reconfig_queues = queue; } } #ifdef RTE_NIC_BYPASS #include uint8_t bypass_is_supported(portid_t port_id) { struct rte_port *port; struct rte_pci_id *pci_id; if (port_id_is_invalid(port_id, ENABLED_WARN)) return 0; /* Get the device id. */ port = &ports[port_id]; pci_id = &port->dev_info.pci_dev->id; /* Check if NIC supports bypass. */ if (pci_id->device_id == IXGBE_DEV_ID_82599_BYPASS) { return 1; } else { printf("\tBypass not supported for port_id = %d.\n", port_id); return 0; } } #endif ================================================ FILE: app/test-pmd/config.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* BSD LICENSE * * Copyright 2013-2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" static char *flowtype_to_str(uint16_t flow_type); static void print_ethaddr(const char *name, struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } void nic_stats_display(portid_t port_id) { struct rte_eth_stats stats; struct rte_port *port = &ports[port_id]; uint8_t i; portid_t pid; static const char *nic_stats_border = "########################"; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return; } rte_eth_stats_get(port_id, &stats); printf("\n %s NIC statistics for port %-2d %s\n", nic_stats_border, port_id, nic_stats_border); if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " "%-"PRIu64"\n", stats.ipackets, stats.imissed, stats.ibytes); printf(" RX-badcrc: %-10"PRIu64" RX-badlen: %-10"PRIu64" RX-errors: " "%-"PRIu64"\n", stats.ibadcrc, stats.ibadlen, stats.ierrors); printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf); printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " "%-"PRIu64"\n", stats.opackets, stats.oerrors, stats.obytes); } else { printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64 " RX-bytes: %10"PRIu64"\n", stats.ipackets, stats.ierrors, stats.ibytes); printf(" RX-badcrc: %10"PRIu64" RX-badlen: %10"PRIu64 " RX-errors: %10"PRIu64"\n", stats.ibadcrc, stats.ibadlen, stats.ierrors); printf(" RX-nombuf: %10"PRIu64"\n", stats.rx_nombuf); printf(" TX-packets: %10"PRIu64" TX-errors: %10"PRIu64 " TX-bytes: %10"PRIu64"\n", stats.opackets, stats.oerrors, stats.obytes); } /* stats fdir */ if (fdir_conf.mode != RTE_FDIR_MODE_NONE) printf(" Fdirmiss: %-10"PRIu64" Fdirmatch: %-10"PRIu64"\n", stats.fdirmiss, stats.fdirmatch); if (port->rx_queue_stats_mapping_enabled) { printf("\n"); for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d RX-packets: %10"PRIu64 " RX-errors: %10"PRIu64 " RX-bytes: %10"PRIu64"\n", i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]); } } if (port->tx_queue_stats_mapping_enabled) { printf("\n"); for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d TX-packets: %10"PRIu64 " TX-bytes: %10"PRIu64"\n", i, stats.q_opackets[i], stats.q_obytes[i]); } } /* Display statistics of XON/XOFF pause frames, if any. */ if ((stats.tx_pause_xon | stats.rx_pause_xon | stats.tx_pause_xoff | stats.rx_pause_xoff) > 0) { printf(" RX-XOFF: %-10"PRIu64" RX-XON: %-10"PRIu64"\n", stats.rx_pause_xoff, stats.rx_pause_xon); printf(" TX-XOFF: %-10"PRIu64" TX-XON: %-10"PRIu64"\n", stats.tx_pause_xoff, stats.tx_pause_xon); } printf(" %s############################%s\n", nic_stats_border, nic_stats_border); } void nic_stats_clear(portid_t port_id) { portid_t pid; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return; } rte_eth_stats_reset(port_id); printf("\n NIC statistics for port %d cleared\n", port_id); } void nic_xstats_display(portid_t port_id) { struct rte_eth_xstats *xstats; int len, ret, i; printf("###### NIC extended statistics for port %-2d\n", port_id); len = rte_eth_xstats_get(port_id, NULL, 0); if (len < 0) { printf("Cannot get xstats count\n"); return; } xstats = malloc(sizeof(xstats[0]) * len); if (xstats == NULL) { printf("Cannot allocate memory for xstats\n"); return; } ret = rte_eth_xstats_get(port_id, xstats, len); if (ret < 0 || ret > len) { printf("Cannot get xstats\n"); free(xstats); return; } for (i = 0; i < len; i++) printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value); free(xstats); } void nic_xstats_clear(portid_t port_id) { rte_eth_xstats_reset(port_id); } void nic_stats_mapping_display(portid_t port_id) { struct rte_port *port = &ports[port_id]; uint16_t i; portid_t pid; static const char *nic_stats_mapping_border = "########################"; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return; } if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { printf("Port id %d - either does not support queue statistic mapping or" " no queue statistic mapping set\n", port_id); return; } printf("\n %s NIC statistics mapping for port %-2d %s\n", nic_stats_mapping_border, port_id, nic_stats_mapping_border); if (port->rx_queue_stats_mapping_enabled) { for (i = 0; i < nb_rx_queue_stats_mappings; i++) { if (rx_queue_stats_mappings[i].port_id == port_id) { printf(" RX-queue %2d mapped to Stats Reg %2d\n", rx_queue_stats_mappings[i].queue_id, rx_queue_stats_mappings[i].stats_counter_id); } } printf("\n"); } if (port->tx_queue_stats_mapping_enabled) { for (i = 0; i < nb_tx_queue_stats_mappings; i++) { if (tx_queue_stats_mappings[i].port_id == port_id) { printf(" TX-queue %2d mapped to Stats Reg %2d\n", tx_queue_stats_mappings[i].queue_id, tx_queue_stats_mappings[i].stats_counter_id); } } } printf(" %s####################################%s\n", nic_stats_mapping_border, nic_stats_mapping_border); } void port_infos_display(portid_t port_id) { struct rte_port *port; struct ether_addr mac_addr; struct rte_eth_link link; struct rte_eth_dev_info dev_info; int vlan_offload; struct rte_mempool * mp; static const char *info_border = "*********************"; portid_t pid; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return; } port = &ports[port_id]; rte_eth_link_get_nowait(port_id, &link); printf("\n%s Infos for port %-2d %s\n", info_border, port_id, info_border); rte_eth_macaddr_get(port_id, &mac_addr); print_ethaddr("MAC address: ", &mac_addr); printf("\nConnect to socket: %u", port->socket_id); if (port_numa[port_id] != NUMA_NO_CONFIG) { mp = mbuf_pool_find(port_numa[port_id]); if (mp) printf("\nmemory allocation on the socket: %d", port_numa[port_id]); } else printf("\nmemory allocation on the socket: %u",port->socket_id); printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); printf("Link speed: %u Mbps\n", (unsigned) link.link_speed); printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); printf("Promiscuous mode: %s\n", rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled"); printf("Allmulticast mode: %s\n", rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled"); printf("Maximum number of MAC addresses: %u\n", (unsigned int)(port->dev_info.max_mac_addrs)); printf("Maximum number of MAC addresses of hash filtering: %u\n", (unsigned int)(port->dev_info.max_hash_mac_addrs)); vlan_offload = rte_eth_dev_get_vlan_offload(port_id); if (vlan_offload >= 0){ printf("VLAN offload: \n"); if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD) printf(" strip on \n"); else printf(" strip off \n"); if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD) printf(" filter on \n"); else printf(" filter off \n"); if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) printf(" qinq(extend) on \n"); else printf(" qinq(extend) off \n"); } memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); if (dev_info.hash_key_size > 0) printf("Hash key size in bytes: %u\n", dev_info.hash_key_size); if (dev_info.reta_size > 0) printf("Redirection table size: %u\n", dev_info.reta_size); if (!dev_info.flow_type_rss_offloads) printf("No flow type is supported.\n"); else { uint16_t i; char *p; printf("Supported flow types:\n"); for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX; i++) { if (!(dev_info.flow_type_rss_offloads & (1ULL << i))) continue; p = flowtype_to_str(i); printf(" %s\n", (p ? p : "unknown")); } } } int port_id_is_invalid(portid_t port_id, enum print_warning warning) { if (port_id == (portid_t)RTE_PORT_ALL) return 0; if (port_id < RTE_MAX_ETHPORTS && ports[port_id].enabled) return 0; if (warning == ENABLED_WARN) printf("Invalid port %d\n", port_id); return 1; } static int vlan_id_is_invalid(uint16_t vlan_id) { if (vlan_id < 4096) return 0; printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id); return 1; } static int port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off) { uint64_t pci_len; if (reg_off & 0x3) { printf("Port register offset 0x%X not aligned on a 4-byte " "boundary\n", (unsigned)reg_off); return 1; } pci_len = ports[port_id].dev_info.pci_dev->mem_resource[0].len; if (reg_off >= pci_len) { printf("Port %d: register offset %u (0x%X) out of port PCI " "resource (length=%"PRIu64")\n", port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len); return 1; } return 0; } static int reg_bit_pos_is_invalid(uint8_t bit_pos) { if (bit_pos <= 31) return 0; printf("Invalid bit position %d (must be <= 31)\n", bit_pos); return 1; } #define display_port_and_reg_off(port_id, reg_off) \ printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off)) static inline void display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v) { display_port_and_reg_off(port_id, (unsigned)reg_off); printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v); } void port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) { uint32_t reg_v; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; if (reg_bit_pos_is_invalid(bit_x)) return; reg_v = port_id_pci_reg_read(port_id, reg_off); display_port_and_reg_off(port_id, (unsigned)reg_off); printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x)); } void port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, uint8_t bit1_pos, uint8_t bit2_pos) { uint32_t reg_v; uint8_t l_bit; uint8_t h_bit; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; if (reg_bit_pos_is_invalid(bit1_pos)) return; if (reg_bit_pos_is_invalid(bit2_pos)) return; if (bit1_pos > bit2_pos) l_bit = bit2_pos, h_bit = bit1_pos; else l_bit = bit1_pos, h_bit = bit2_pos; reg_v = port_id_pci_reg_read(port_id, reg_off); reg_v >>= l_bit; if (h_bit < 31) reg_v &= ((1 << (h_bit - l_bit + 1)) - 1); display_port_and_reg_off(port_id, (unsigned)reg_off); printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit, ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v); } void port_reg_display(portid_t port_id, uint32_t reg_off) { uint32_t reg_v; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; reg_v = port_id_pci_reg_read(port_id, reg_off); display_port_reg_value(port_id, reg_off, reg_v); } void port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, uint8_t bit_v) { uint32_t reg_v; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; if (reg_bit_pos_is_invalid(bit_pos)) return; if (bit_v > 1) { printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v); return; } reg_v = port_id_pci_reg_read(port_id, reg_off); if (bit_v == 0) reg_v &= ~(1 << bit_pos); else reg_v |= (1 << bit_pos); port_id_pci_reg_write(port_id, reg_off, reg_v); display_port_reg_value(port_id, reg_off, reg_v); } void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value) { uint32_t max_v; uint32_t reg_v; uint8_t l_bit; uint8_t h_bit; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; if (reg_bit_pos_is_invalid(bit1_pos)) return; if (reg_bit_pos_is_invalid(bit2_pos)) return; if (bit1_pos > bit2_pos) l_bit = bit2_pos, h_bit = bit1_pos; else l_bit = bit1_pos, h_bit = bit2_pos; if ((h_bit - l_bit) < 31) max_v = (1 << (h_bit - l_bit + 1)) - 1; else max_v = 0xFFFFFFFF; if (value > max_v) { printf("Invalid value %u (0x%x) must be < %u (0x%x)\n", (unsigned)value, (unsigned)value, (unsigned)max_v, (unsigned)max_v); return; } reg_v = port_id_pci_reg_read(port_id, reg_off); reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */ reg_v |= (value << l_bit); /* Set changed bits */ port_id_pci_reg_write(port_id, reg_off, reg_v); display_port_reg_value(port_id, reg_off, reg_v); } void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (port_reg_off_is_invalid(port_id, reg_off)) return; port_id_pci_reg_write(port_id, reg_off, reg_v); display_port_reg_value(port_id, reg_off, reg_v); } void port_mtu_set(portid_t port_id, uint16_t mtu) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_mtu(port_id, mtu); if (diag == 0) return; printf("Set MTU failed. diag=%d\n", diag); } /* * RX/TX ring descriptors display functions. */ int rx_queue_id_is_invalid(queueid_t rxq_id) { if (rxq_id < nb_rxq) return 0; printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq); return 1; } int tx_queue_id_is_invalid(queueid_t txq_id) { if (txq_id < nb_txq) return 0; printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq); return 1; } static int rx_desc_id_is_invalid(uint16_t rxdesc_id) { if (rxdesc_id < nb_rxd) return 0; printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n", rxdesc_id, nb_rxd); return 1; } static int tx_desc_id_is_invalid(uint16_t txdesc_id) { if (txdesc_id < nb_txd) return 0; printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n", txdesc_id, nb_txd); return 1; } static const struct rte_memzone * ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id) { char mz_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(mz_name, sizeof(mz_name), "%s_%s_%d_%d", ports[port_id].dev_info.driver_name, ring_name, port_id, q_id); mz = rte_memzone_lookup(mz_name); if (mz == NULL) printf("%s ring memory zoneof (port %d, queue %d) not" "found (zone name = %s\n", ring_name, port_id, q_id, mz_name); return (mz); } union igb_ring_dword { uint64_t dword; struct { #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN uint32_t lo; uint32_t hi; #else uint32_t hi; uint32_t lo; #endif } words; }; struct igb_ring_desc_32_bytes { union igb_ring_dword lo_dword; union igb_ring_dword hi_dword; union igb_ring_dword resv1; union igb_ring_dword resv2; }; struct igb_ring_desc_16_bytes { union igb_ring_dword lo_dword; union igb_ring_dword hi_dword; }; static void ring_rxd_display_dword(union igb_ring_dword dword) { printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo, (unsigned)dword.words.hi); } static void ring_rx_descriptor_display(const struct rte_memzone *ring_mz, #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC uint8_t port_id, #else __rte_unused uint8_t port_id, #endif uint16_t desc_id) { struct igb_ring_desc_16_bytes *ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); if (strstr(dev_info.driver_name, "i40e") != NULL) { /* 32 bytes RX descriptor, i40e only */ struct igb_ring_desc_32_bytes *ring = (struct igb_ring_desc_32_bytes *)ring_mz->addr; ring[desc_id].lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); ring_rxd_display_dword(ring[desc_id].lo_dword); ring[desc_id].hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); ring_rxd_display_dword(ring[desc_id].hi_dword); ring[desc_id].resv1.dword = rte_le_to_cpu_64(ring[desc_id].resv1.dword); ring_rxd_display_dword(ring[desc_id].resv1); ring[desc_id].resv2.dword = rte_le_to_cpu_64(ring[desc_id].resv2.dword); ring_rxd_display_dword(ring[desc_id].resv2); return; } #endif /* 16 bytes RX descriptor */ ring[desc_id].lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); ring_rxd_display_dword(ring[desc_id].lo_dword); ring[desc_id].hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); ring_rxd_display_dword(ring[desc_id].hi_dword); } static void ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id) { struct igb_ring_desc_16_bytes *ring; struct igb_ring_desc_16_bytes txd; ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr; txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword); txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword); printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n", (unsigned)txd.lo_dword.words.lo, (unsigned)txd.lo_dword.words.hi, (unsigned)txd.hi_dword.words.lo, (unsigned)txd.hi_dword.words.hi); } void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) { const struct rte_memzone *rx_mz; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (rx_queue_id_is_invalid(rxq_id)) return; if (rx_desc_id_is_invalid(rxd_id)) return; rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id); if (rx_mz == NULL) return; ring_rx_descriptor_display(rx_mz, port_id, rxd_id); } void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) { const struct rte_memzone *tx_mz; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (tx_queue_id_is_invalid(txq_id)) return; if (tx_desc_id_is_invalid(txd_id)) return; tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id); if (tx_mz == NULL) return; ring_tx_descriptor_display(tx_mz, txd_id); } void fwd_lcores_config_display(void) { lcoreid_t lc_id; printf("List of forwarding lcores:"); for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++) printf(" %2u", fwd_lcores_cpuids[lc_id]); printf("\n"); } void rxtx_config_display(void) { printf(" %s packet forwarding - CRC stripping %s - " "packets/burst=%d\n", cur_fwd_eng->fwd_mode_name, rx_mode.hw_strip_crc ? "enabled" : "disabled", nb_pkt_per_burst); if (cur_fwd_eng == &tx_only_engine) printf(" packet len=%u - nb packet segments=%d\n", (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs); struct rte_eth_rxconf *rx_conf = &ports[0].rx_conf; struct rte_eth_txconf *tx_conf = &ports[0].tx_conf; printf(" nb forwarding cores=%d - nb forwarding ports=%d\n", nb_fwd_lcores, nb_fwd_ports); printf(" RX queues=%d - RX desc=%d - RX free threshold=%d\n", nb_rxq, nb_rxd, rx_conf->rx_free_thresh); printf(" RX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", rx_conf->rx_thresh.pthresh, rx_conf->rx_thresh.hthresh, rx_conf->rx_thresh.wthresh); printf(" TX queues=%d - TX desc=%d - TX free threshold=%d\n", nb_txq, nb_txd, tx_conf->tx_free_thresh); printf(" TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n", tx_conf->tx_thresh.pthresh, tx_conf->tx_thresh.hthresh, tx_conf->tx_thresh.wthresh); printf(" TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n", tx_conf->tx_rs_thresh, tx_conf->txq_flags); } void port_rss_reta_info(portid_t port_id, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t nb_entries) { uint16_t i, idx, shift; int ret; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries); if (ret != 0) { printf("Failed to get RSS RETA info, return code = %d\n", ret); return; } for (i = 0; i < nb_entries; i++) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; if (!(reta_conf[idx].mask & (1ULL << shift))) continue; printf("RSS RETA configuration: hash index=%u, queue=%u\n", i, reta_conf[idx].reta[shift]); } } /* * Displays the RSS hash functions of a port, and, optionaly, the RSS hash * key of the port. */ void port_rss_hash_conf_show(portid_t port_id, int show_rss_key) { struct rss_type_info { char str[32]; uint64_t rss_type; }; static const struct rss_type_info rss_type_table[] = { {"ipv4", ETH_RSS_IPV4}, {"ipv4-frag", ETH_RSS_FRAG_IPV4}, {"ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP}, {"ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP}, {"ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP}, {"ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER}, {"ipv6", ETH_RSS_IPV6}, {"ipv6-frag", ETH_RSS_FRAG_IPV6}, {"ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP}, {"ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP}, {"ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP}, {"ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER}, {"l2-payload", ETH_RSS_L2_PAYLOAD}, {"ipv6-ex", ETH_RSS_IPV6_EX}, {"ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX}, {"ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX}, }; struct rte_eth_rss_conf rss_conf; uint8_t rss_key[10 * 4]; uint64_t rss_hf; uint8_t i; int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; /* Get RSS hash key if asked to display it */ rss_conf.rss_key = (show_rss_key) ? rss_key : NULL; diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); if (diag != 0) { switch (diag) { case -ENODEV: printf("port index %d invalid\n", port_id); break; case -ENOTSUP: printf("operation not supported by device\n"); break; default: printf("operation failed - diag=%d\n", diag); break; } return; } rss_hf = rss_conf.rss_hf; if (rss_hf == 0) { printf("RSS disabled\n"); return; } printf("RSS functions:\n "); for (i = 0; i < RTE_DIM(rss_type_table); i++) { if (rss_hf & rss_type_table[i].rss_type) printf("%s ", rss_type_table[i].str); } printf("\n"); if (!show_rss_key) return; printf("RSS key:\n"); for (i = 0; i < sizeof(rss_key); i++) printf("%02X", rss_key[i]); printf("\n"); } void port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key) { struct rte_eth_rss_conf rss_conf; int diag; rss_conf.rss_key = NULL; diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf); if (diag == 0) { rss_conf.rss_key = hash_key; diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf); } if (diag == 0) return; switch (diag) { case -ENODEV: printf("port index %d invalid\n", port_id); break; case -ENOTSUP: printf("operation not supported by device\n"); break; default: printf("operation failed - diag=%d\n", diag); break; } } /* * Setup forwarding configuration for each logical core. */ static void setup_fwd_config_of_each_lcore(struct fwd_config *cfg) { streamid_t nb_fs_per_lcore; streamid_t nb_fs; streamid_t sm_id; lcoreid_t nb_extra; lcoreid_t nb_fc; lcoreid_t nb_lc; lcoreid_t lc_id; nb_fs = cfg->nb_fwd_streams; nb_fc = cfg->nb_fwd_lcores; if (nb_fs <= nb_fc) { nb_fs_per_lcore = 1; nb_extra = 0; } else { nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc); nb_extra = (lcoreid_t) (nb_fs % nb_fc); } nb_lc = (lcoreid_t) (nb_fc - nb_extra); sm_id = 0; for (lc_id = 0; lc_id < nb_lc; lc_id++) { fwd_lcores[lc_id]->stream_idx = sm_id; fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore; sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); } /* * Assign extra remaining streams, if any. */ nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1); for (lc_id = 0; lc_id < nb_extra; lc_id++) { fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id; fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore; sm_id = (streamid_t) (sm_id + nb_fs_per_lcore); } } static void simple_fwd_config_setup(void) { portid_t i; portid_t j; portid_t inc = 2; if (port_topology == PORT_TOPOLOGY_CHAINED || port_topology == PORT_TOPOLOGY_LOOP) { inc = 1; } else if (nb_fwd_ports % 2) { printf("\nWarning! Cannot handle an odd number of ports " "with the current port topology. Configuration " "must be changed to have an even number of ports, " "or relaunch application with " "--port-topology=chained\n\n"); } cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports; cur_fwd_config.nb_fwd_streams = (streamid_t) cur_fwd_config.nb_fwd_ports; /* reinitialize forwarding streams */ init_fwd_streams(); /* * In the simple forwarding test, the number of forwarding cores * must be lower or equal to the number of forwarding ports. */ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports) cur_fwd_config.nb_fwd_lcores = (lcoreid_t) cur_fwd_config.nb_fwd_ports; setup_fwd_config_of_each_lcore(&cur_fwd_config); for (i = 0; i < cur_fwd_config.nb_fwd_ports; i = (portid_t) (i + inc)) { if (port_topology != PORT_TOPOLOGY_LOOP) j = (portid_t) ((i + 1) % cur_fwd_config.nb_fwd_ports); else j = i; fwd_streams[i]->rx_port = fwd_ports_ids[i]; fwd_streams[i]->rx_queue = 0; fwd_streams[i]->tx_port = fwd_ports_ids[j]; fwd_streams[i]->tx_queue = 0; fwd_streams[i]->peer_addr = j; if (port_topology == PORT_TOPOLOGY_PAIRED) { fwd_streams[j]->rx_port = fwd_ports_ids[j]; fwd_streams[j]->rx_queue = 0; fwd_streams[j]->tx_port = fwd_ports_ids[i]; fwd_streams[j]->tx_queue = 0; fwd_streams[j]->peer_addr = i; } } } /** * For the RSS forwarding test, each core is assigned on every port a transmit * queue whose index is the index of the core itself. This approach limits the * maximumm number of processing cores of the RSS test to the maximum number of * TX queues supported by the devices. * * Each core is assigned a single stream, each stream being composed of * a RX queue to poll on a RX port for input messages, associated with * a TX queue of a TX port where to send forwarded packets. * All packets received on the RX queue of index "RxQj" of the RX port "RxPi" * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two * following rules: * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd * - TxQl = RxQj */ static void rss_fwd_config_setup(void) { portid_t rxp; portid_t txp; queueid_t rxq; queueid_t nb_q; lcoreid_t lc_id; nb_q = nb_rxq; if (nb_q > nb_txq) nb_q = nb_txq; cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; cur_fwd_config.nb_fwd_ports = nb_fwd_ports; cur_fwd_config.nb_fwd_streams = (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); if (cur_fwd_config.nb_fwd_streams > cur_fwd_config.nb_fwd_lcores) cur_fwd_config.nb_fwd_streams = (streamid_t)cur_fwd_config.nb_fwd_lcores; else cur_fwd_config.nb_fwd_lcores = (lcoreid_t)cur_fwd_config.nb_fwd_streams; /* reinitialize forwarding streams */ init_fwd_streams(); setup_fwd_config_of_each_lcore(&cur_fwd_config); rxp = 0; rxq = 0; for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { struct fwd_stream *fs; fs = fwd_streams[lc_id]; if ((rxp & 0x1) == 0) txp = (portid_t) (rxp + 1); else txp = (portid_t) (rxp - 1); /* * if we are in loopback, simply send stuff out through the * ingress port */ if (port_topology == PORT_TOPOLOGY_LOOP) txp = rxp; fs->rx_port = fwd_ports_ids[rxp]; fs->rx_queue = rxq; fs->tx_port = fwd_ports_ids[txp]; fs->tx_queue = rxq; fs->peer_addr = fs->tx_port; rxq = (queueid_t) (rxq + 1); if (rxq < nb_q) continue; /* * rxq == nb_q * Restart from RX queue 0 on next RX port */ rxq = 0; if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) rxp = (portid_t) (rxp + ((nb_ports >> 1) / nb_fwd_ports)); else rxp = (portid_t) (rxp + 1); } } /* * In DCB and VT on,the mapping of 128 receive queues to 128 transmit queues. */ static void dcb_rxq_2_txq_mapping(queueid_t rxq, queueid_t *txq) { if(dcb_q_mapping == DCB_4_TCS_Q_MAPPING) { if (rxq < 32) /* tc0: 0-31 */ *txq = rxq; else if (rxq < 64) { /* tc1: 64-95 */ *txq = (uint16_t)(rxq + 32); } else { /* tc2: 96-111;tc3:112-127 */ *txq = (uint16_t)(rxq/2 + 64); } } else { if (rxq < 16) /* tc0 mapping*/ *txq = rxq; else if (rxq < 32) { /* tc1 mapping*/ *txq = (uint16_t)(rxq + 16); } else if (rxq < 64) { /*tc2,tc3 mapping */ *txq = (uint16_t)(rxq + 32); } else { /* tc4,tc5,tc6 and tc7 mapping */ *txq = (uint16_t)(rxq/2 + 64); } } } /** * For the DCB forwarding test, each core is assigned on every port multi-transmit * queue. * * Each core is assigned a multi-stream, each stream being composed of * a RX queue to poll on a RX port for input messages, associated with * a TX queue of a TX port where to send forwarded packets. * All packets received on the RX queue of index "RxQj" of the RX port "RxPi" * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two * following rules: * In VT mode, * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd * - TxQl = RxQj * In non-VT mode, * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd * There is a mapping of RxQj to TxQl to be required,and the mapping was implemented * in dcb_rxq_2_txq_mapping function. */ static void dcb_fwd_config_setup(void) { portid_t rxp; portid_t txp; queueid_t rxq; queueid_t nb_q; lcoreid_t lc_id; uint16_t sm_id; nb_q = nb_rxq; cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; cur_fwd_config.nb_fwd_ports = nb_fwd_ports; cur_fwd_config.nb_fwd_streams = (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports); /* reinitialize forwarding streams */ init_fwd_streams(); setup_fwd_config_of_each_lcore(&cur_fwd_config); rxp = 0; rxq = 0; for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { /* a fwd core can run multi-streams */ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { struct fwd_stream *fs; fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; if ((rxp & 0x1) == 0) txp = (portid_t) (rxp + 1); else txp = (portid_t) (rxp - 1); fs->rx_port = fwd_ports_ids[rxp]; fs->rx_queue = rxq; fs->tx_port = fwd_ports_ids[txp]; if (dcb_q_mapping == DCB_VT_Q_MAPPING) fs->tx_queue = rxq; else dcb_rxq_2_txq_mapping(rxq, &fs->tx_queue); fs->peer_addr = fs->tx_port; rxq = (queueid_t) (rxq + 1); if (rxq < nb_q) continue; rxq = 0; if (numa_support && (nb_fwd_ports <= (nb_ports >> 1))) rxp = (portid_t) (rxp + ((nb_ports >> 1) / nb_fwd_ports)); else rxp = (portid_t) (rxp + 1); } } } static void icmp_echo_config_setup(void) { portid_t rxp; queueid_t rxq; lcoreid_t lc_id; uint16_t sm_id; if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores) cur_fwd_config.nb_fwd_lcores = (lcoreid_t) (nb_txq * nb_fwd_ports); else cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores; cur_fwd_config.nb_fwd_ports = nb_fwd_ports; cur_fwd_config.nb_fwd_streams = (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports); if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores) cur_fwd_config.nb_fwd_lcores = (lcoreid_t)cur_fwd_config.nb_fwd_streams; if (verbose_level > 0) { printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n", __FUNCTION__, cur_fwd_config.nb_fwd_lcores, cur_fwd_config.nb_fwd_ports, cur_fwd_config.nb_fwd_streams); } /* reinitialize forwarding streams */ init_fwd_streams(); setup_fwd_config_of_each_lcore(&cur_fwd_config); rxp = 0; rxq = 0; for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) { if (verbose_level > 0) printf(" core=%d: \n", lc_id); for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { struct fwd_stream *fs; fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; fs->rx_port = fwd_ports_ids[rxp]; fs->rx_queue = rxq; fs->tx_port = fs->rx_port; fs->tx_queue = lc_id; fs->peer_addr = fs->tx_port; if (verbose_level > 0) printf(" stream=%d port=%d rxq=%d txq=%d\n", sm_id, fs->rx_port, fs->rx_queue, fs->tx_queue); rxq = (queueid_t) (rxq + 1); if (rxq == nb_rxq) { rxq = 0; rxp = (portid_t) (rxp + 1); } } } } void fwd_config_setup(void) { cur_fwd_config.fwd_eng = cur_fwd_eng; if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) { icmp_echo_config_setup(); return; } if ((nb_rxq > 1) && (nb_txq > 1)){ if (dcb_config) dcb_fwd_config_setup(); else rss_fwd_config_setup(); } else simple_fwd_config_setup(); } static void pkt_fwd_config_display(struct fwd_config *cfg) { struct fwd_stream *fs; lcoreid_t lc_id; streamid_t sm_id; printf("%s packet forwarding - ports=%d - cores=%d - streams=%d - " "NUMA support %s, MP over anonymous pages %s\n", cfg->fwd_eng->fwd_mode_name, cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams, numa_support == 1 ? "enabled" : "disabled", mp_anon != 0 ? "enabled" : "disabled"); if (strcmp(cfg->fwd_eng->fwd_mode_name, "mac_retry") == 0) printf("TX retry num: %u, delay between TX retries: %uus\n", burst_tx_retry_num, burst_tx_delay_time); for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) { printf("Logical Core %u (socket %u) forwards packets on " "%d streams:", fwd_lcores_cpuids[lc_id], rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]), fwd_lcores[lc_id]->stream_nb); for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) { fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id]; printf("\n RX P=%d/Q=%d (socket %u) -> TX " "P=%d/Q=%d (socket %u) ", fs->rx_port, fs->rx_queue, ports[fs->rx_port].socket_id, fs->tx_port, fs->tx_queue, ports[fs->tx_port].socket_id); print_ethaddr("peer=", &peer_eth_addrs[fs->peer_addr]); } printf("\n"); } printf("\n"); } void fwd_config_display(void) { if((dcb_config) && (nb_fwd_lcores == 1)) { printf("In DCB mode,the nb forwarding cores should be larger than 1\n"); return; } fwd_config_setup(); pkt_fwd_config_display(&cur_fwd_config); } int set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc) { unsigned int i; unsigned int lcore_cpuid; int record_now; record_now = 0; again: for (i = 0; i < nb_lc; i++) { lcore_cpuid = lcorelist[i]; if (! rte_lcore_is_enabled(lcore_cpuid)) { printf("lcore %u not enabled\n", lcore_cpuid); return -1; } if (lcore_cpuid == rte_get_master_lcore()) { printf("lcore %u cannot be masked on for running " "packet forwarding, which is the master lcore " "and reserved for command line parsing only\n", lcore_cpuid); return -1; } if (record_now) fwd_lcores_cpuids[i] = lcore_cpuid; } if (record_now == 0) { record_now = 1; goto again; } nb_cfg_lcores = (lcoreid_t) nb_lc; if (nb_fwd_lcores != (lcoreid_t) nb_lc) { printf("previous number of forwarding cores %u - changed to " "number of configured cores %u\n", (unsigned int) nb_fwd_lcores, nb_lc); nb_fwd_lcores = (lcoreid_t) nb_lc; } return 0; } int set_fwd_lcores_mask(uint64_t lcoremask) { unsigned int lcorelist[64]; unsigned int nb_lc; unsigned int i; if (lcoremask == 0) { printf("Invalid NULL mask of cores\n"); return -1; } nb_lc = 0; for (i = 0; i < 64; i++) { if (! ((uint64_t)(1ULL << i) & lcoremask)) continue; lcorelist[nb_lc++] = i; } return set_fwd_lcores_list(lcorelist, nb_lc); } void set_fwd_lcores_number(uint16_t nb_lc) { if (nb_lc > nb_cfg_lcores) { printf("nb fwd cores %u > %u (max. number of configured " "lcores) - ignored\n", (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores); return; } nb_fwd_lcores = (lcoreid_t) nb_lc; printf("Number of forwarding cores set to %u\n", (unsigned int) nb_fwd_lcores); } void set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) { unsigned int i; portid_t port_id; int record_now; record_now = 0; again: for (i = 0; i < nb_pt; i++) { port_id = (portid_t) portlist[i]; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (record_now) fwd_ports_ids[i] = port_id; } if (record_now == 0) { record_now = 1; goto again; } nb_cfg_ports = (portid_t) nb_pt; if (nb_fwd_ports != (portid_t) nb_pt) { printf("previous number of forwarding ports %u - changed to " "number of configured ports %u\n", (unsigned int) nb_fwd_ports, nb_pt); nb_fwd_ports = (portid_t) nb_pt; } } void set_fwd_ports_mask(uint64_t portmask) { unsigned int portlist[64]; unsigned int nb_pt; unsigned int i; if (portmask == 0) { printf("Invalid NULL mask of ports\n"); return; } nb_pt = 0; for (i = 0; i < (unsigned)RTE_MIN(64, RTE_MAX_ETHPORTS); i++) { if (! ((uint64_t)(1ULL << i) & portmask)) continue; portlist[nb_pt++] = i; } set_fwd_ports_list(portlist, nb_pt); } void set_fwd_ports_number(uint16_t nb_pt) { if (nb_pt > nb_cfg_ports) { printf("nb fwd ports %u > %u (number of configured " "ports) - ignored\n", (unsigned int) nb_pt, (unsigned int) nb_cfg_ports); return; } nb_fwd_ports = (portid_t) nb_pt; printf("Number of forwarding ports set to %u\n", (unsigned int) nb_fwd_ports); } void set_nb_pkt_per_burst(uint16_t nb) { if (nb > MAX_PKT_BURST) { printf("nb pkt per burst: %u > %u (maximum packet per burst) " " ignored\n", (unsigned int) nb, (unsigned int) MAX_PKT_BURST); return; } nb_pkt_per_burst = nb; printf("Number of packets per burst set to %u\n", (unsigned int) nb_pkt_per_burst); } void set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs) { uint16_t tx_pkt_len; unsigned i; if (nb_segs >= (unsigned) nb_txd) { printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n", nb_segs, (unsigned int) nb_txd); return; } /* * Check that each segment length is greater or equal than * the mbuf data sise. * Check also that the total packet length is greater or equal than the * size of an empty UDP/IP packet (sizeof(struct ether_hdr) + 20 + 8). */ tx_pkt_len = 0; for (i = 0; i < nb_segs; i++) { if (seg_lengths[i] > (unsigned) mbuf_data_size) { printf("length[%u]=%u > mbuf_data_size=%u - give up\n", i, seg_lengths[i], (unsigned) mbuf_data_size); return; } tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]); } if (tx_pkt_len < (sizeof(struct ether_hdr) + 20 + 8)) { printf("total packet length=%u < %d - give up\n", (unsigned) tx_pkt_len, (int)(sizeof(struct ether_hdr) + 20 + 8)); return; } for (i = 0; i < nb_segs; i++) tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i]; tx_pkt_length = tx_pkt_len; tx_pkt_nb_segs = (uint8_t) nb_segs; } char* list_pkt_forwarding_modes(void) { static char fwd_modes[128] = ""; const char *separator = "|"; struct fwd_engine *fwd_eng; unsigned i = 0; if (strlen (fwd_modes) == 0) { while ((fwd_eng = fwd_engines[i++]) != NULL) { strcat(fwd_modes, fwd_eng->fwd_mode_name); strcat(fwd_modes, separator); } fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0'; } return fwd_modes; } void set_pkt_forwarding_mode(const char *fwd_mode_name) { struct fwd_engine *fwd_eng; unsigned i; i = 0; while ((fwd_eng = fwd_engines[i]) != NULL) { if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) { printf("Set %s packet forwarding mode\n", fwd_mode_name); cur_fwd_eng = fwd_eng; return; } i++; } printf("Invalid %s packet forwarding mode\n", fwd_mode_name); } void set_verbose_level(uint16_t vb_level) { printf("Change verbose level from %u to %u\n", (unsigned int) verbose_level, (unsigned int) vb_level); verbose_level = vb_level; } void vlan_extend_set(portid_t port_id, int on) { int diag; int vlan_offload; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); if (on) vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD; else vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD; diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); if (diag < 0) printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); } void rx_vlan_strip_set(portid_t port_id, int on) { int diag; int vlan_offload; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); if (on) vlan_offload |= ETH_VLAN_STRIP_OFFLOAD; else vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD; diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); if (diag < 0) printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); } void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on); if (diag < 0) printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed " "diag=%d\n", port_id, queue_id, on, diag); } void rx_vlan_filter_set(portid_t port_id, int on) { int diag; int vlan_offload; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; vlan_offload = rte_eth_dev_get_vlan_offload(port_id); if (on) vlan_offload |= ETH_VLAN_FILTER_OFFLOAD; else vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD; diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload); if (diag < 0) printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed " "diag=%d\n", port_id, on, diag); } int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return 1; if (vlan_id_is_invalid(vlan_id)) return 1; diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on); if (diag == 0) return 0; printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed " "diag=%d\n", port_id, vlan_id, on, diag); return -1; } void rx_vlan_all_filter_set(portid_t port_id, int on) { uint16_t vlan_id; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; for (vlan_id = 0; vlan_id < 4096; vlan_id++) { if (rx_vft_set(port_id, vlan_id, on)) break; } } void vlan_tpid_set(portid_t port_id, uint16_t tp_id) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id); if (diag == 0) return; printf("tx_vlan_tpid_set(port_pi=%d, tpid=%d) failed " "diag=%d\n", port_id, tp_id, diag); } void tx_vlan_set(portid_t port_id, uint16_t vlan_id) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; tx_vlan_reset(port_id); ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN; ports[port_id].tx_vlan_id = vlan_id; } void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; if (vlan_id_is_invalid(vlan_id_outer)) return; tx_vlan_reset(port_id); ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ; ports[port_id].tx_vlan_id = vlan_id; ports[port_id].tx_vlan_id_outer = vlan_id_outer; } void tx_vlan_reset(portid_t port_id) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN | TESTPMD_TX_OFFLOAD_INSERT_QINQ); ports[port_id].tx_vlan_id = 0; ports[port_id].tx_vlan_id_outer = 0; } void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return; rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on); } void set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) { uint16_t i; uint8_t existing_mapping_found = 0; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id))) return; if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { printf("map_value not in required range 0..%d\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); return; } if (!is_rx) { /*then tx*/ for (i = 0; i < nb_tx_queue_stats_mappings; i++) { if ((tx_queue_stats_mappings[i].port_id == port_id) && (tx_queue_stats_mappings[i].queue_id == queue_id)) { tx_queue_stats_mappings[i].stats_counter_id = map_value; existing_mapping_found = 1; break; } } if (!existing_mapping_found) { /* A new additional mapping... */ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id; tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id; tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value; nb_tx_queue_stats_mappings++; } } else { /*rx*/ for (i = 0; i < nb_rx_queue_stats_mappings; i++) { if ((rx_queue_stats_mappings[i].port_id == port_id) && (rx_queue_stats_mappings[i].queue_id == queue_id)) { rx_queue_stats_mappings[i].stats_counter_id = map_value; existing_mapping_found = 1; break; } } if (!existing_mapping_found) { /* A new additional mapping... */ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id; rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id; rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value; nb_rx_queue_stats_mappings++; } } } static inline void print_fdir_mask(struct rte_eth_fdir_masks *mask) { printf("\n vlan_tci: 0x%04x, src_ipv4: 0x%08x, dst_ipv4: 0x%08x," " src_port: 0x%04x, dst_port: 0x%04x", mask->vlan_tci_mask, mask->ipv4_mask.src_ip, mask->ipv4_mask.dst_ip, mask->src_port_mask, mask->dst_port_mask); printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x," " dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1], mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3], mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1], mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]); printf("\n"); } static inline void print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) { struct rte_eth_flex_payload_cfg *cfg; uint32_t i, j; for (i = 0; i < flex_conf->nb_payloads; i++) { cfg = &flex_conf->flex_set[i]; if (cfg->type == RTE_ETH_RAW_PAYLOAD) printf("\n RAW: "); else if (cfg->type == RTE_ETH_L2_PAYLOAD) printf("\n L2_PAYLOAD: "); else if (cfg->type == RTE_ETH_L3_PAYLOAD) printf("\n L3_PAYLOAD: "); else if (cfg->type == RTE_ETH_L4_PAYLOAD) printf("\n L4_PAYLOAD: "); else printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type); for (j = 0; j < num; j++) printf(" %-5u", cfg->src_offset[j]); } printf("\n"); } static char * flowtype_to_str(uint16_t flow_type) { struct flow_type_info { char str[32]; uint16_t ftype; }; uint8_t i; static struct flow_type_info flowtype_str_table[] = { {"raw", RTE_ETH_FLOW_RAW}, {"ipv4", RTE_ETH_FLOW_IPV4}, {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4}, {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP}, {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP}, {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP}, {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER}, {"ipv6", RTE_ETH_FLOW_IPV6}, {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6}, {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP}, {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP}, {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP}, {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER}, {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD}, }; for (i = 0; i < RTE_DIM(flowtype_str_table); i++) { if (flowtype_str_table[i].ftype == flow_type) return flowtype_str_table[i].str; } return NULL; } static inline void print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) { struct rte_eth_fdir_flex_mask *mask; uint32_t i, j; char *p; for (i = 0; i < flex_conf->nb_flexmasks; i++) { mask = &flex_conf->flex_mask[i]; p = flowtype_to_str(mask->flow_type); printf("\n %s:\t", p ? p : "unknown"); for (j = 0; j < num; j++) printf(" %02x", mask->mask[j]); } printf("\n"); } static inline void print_fdir_flow_type(uint32_t flow_types_mask) { int i; char *p; for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) { if (!(flow_types_mask & (1 << i))) continue; p = flowtype_to_str(i); if (p) printf(" %s", p); else printf(" unknown"); } printf("\n"); } void fdir_get_infos(portid_t port_id) { struct rte_eth_fdir_stats fdir_stat; struct rte_eth_fdir_info fdir_info; int ret; static const char *fdir_stats_border = "########################"; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); if (ret < 0) { printf("\n FDIR is not supported on port %-2d\n", port_id); return; } memset(&fdir_info, 0, sizeof(fdir_info)); rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_INFO, &fdir_info); memset(&fdir_stat, 0, sizeof(fdir_stat)); rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_STATS, &fdir_stat); printf("\n %s FDIR infos for port %-2d %s\n", fdir_stats_border, port_id, fdir_stats_border); printf(" MODE: "); if (fdir_info.mode == RTE_FDIR_MODE_PERFECT) printf(" PERFECT\n"); else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE) printf(" SIGNATURE\n"); else printf(" DISABLE\n"); printf(" SUPPORTED FLOW TYPE: "); print_fdir_flow_type(fdir_info.flow_types_mask[0]); printf(" FLEX PAYLOAD INFO:\n"); printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n" " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n" " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n", fdir_info.max_flexpayload, fdir_info.flex_payload_limit, fdir_info.flex_payload_unit, fdir_info.max_flex_payload_segment_num, fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num); printf(" MASK: "); print_fdir_mask(&fdir_info.mask); if (fdir_info.flex_conf.nb_payloads > 0) { printf(" FLEX PAYLOAD SRC OFFSET:"); print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload); } if (fdir_info.flex_conf.nb_flexmasks > 0) { printf(" FLEX MASK CFG:"); print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload); } printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n", fdir_stat.guarant_cnt, fdir_stat.best_cnt); printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n", fdir_info.guarant_spc, fdir_info.best_spc); printf(" collision: %-10"PRIu32" free: %"PRIu32"\n" " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n" " add: %-10"PRIu64" remove: %"PRIu64"\n" " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n", fdir_stat.collision, fdir_stat.free, fdir_stat.maxhash, fdir_stat.maxlen, fdir_stat.add, fdir_stat.remove, fdir_stat.f_add, fdir_stat.f_remove); printf(" %s############################%s\n", fdir_stats_border, fdir_stats_border); } void fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg) { struct rte_port *port; struct rte_eth_fdir_flex_conf *flex_conf; int i, idx = 0; port = &ports[port_id]; flex_conf = &port->dev_conf.fdir_conf.flex_conf; for (i = 0; i < RTE_ETH_FLOW_MAX; i++) { if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) { idx = i; break; } } if (i >= RTE_ETH_FLOW_MAX) { if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) { idx = flex_conf->nb_flexmasks; flex_conf->nb_flexmasks++; } else { printf("The flex mask table is full. Can not set flex" " mask for flow_type(%u).", cfg->flow_type); return; } } (void)rte_memcpy(&flex_conf->flex_mask[idx], cfg, sizeof(struct rte_eth_fdir_flex_mask)); } void fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg) { struct rte_port *port; struct rte_eth_fdir_flex_conf *flex_conf; int i, idx = 0; port = &ports[port_id]; flex_conf = &port->dev_conf.fdir_conf.flex_conf; for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) { if (cfg->type == flex_conf->flex_set[i].type) { idx = i; break; } } if (i >= RTE_ETH_PAYLOAD_MAX) { if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) { idx = flex_conf->nb_payloads; flex_conf->nb_payloads++; } else { printf("The flex payload table is full. Can not set" " flex payload for type(%u).", cfg->type); return; } } (void)rte_memcpy(&flex_conf->flex_set[idx], cfg, sizeof(struct rte_eth_flex_payload_cfg)); } void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (is_rx) diag = rte_eth_dev_set_vf_rx(port_id,vf,on); else diag = rte_eth_dev_set_vf_tx(port_id,vf,on); if (diag == 0) return; if(is_rx) printf("rte_eth_dev_set_vf_rx for port_id=%d failed " "diag=%d\n", port_id, diag); else printf("rte_eth_dev_set_vf_tx for port_id=%d failed " "diag=%d\n", port_id, diag); } void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on) { int diag; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; if (vlan_id_is_invalid(vlan_id)) return; diag = rte_eth_dev_set_vf_vlan_filter(port_id, vlan_id, vf_mask, on); if (diag == 0) return; printf("rte_eth_dev_set_vf_vlan_filter for port_id=%d failed " "diag=%d\n", port_id, diag); } int set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) { int diag; struct rte_eth_link link; if (port_id_is_invalid(port_id, ENABLED_WARN)) return 1; rte_eth_link_get_nowait(port_id, &link); if (rate > link.link_speed) { printf("Invalid rate value:%u bigger than link speed: %u\n", rate, link.link_speed); return 1; } diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate); if (diag == 0) return diag; printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n", port_id, diag); return diag; } int set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) { int diag; struct rte_eth_link link; if (q_msk == 0) return 0; if (port_id_is_invalid(port_id, ENABLED_WARN)) return 1; rte_eth_link_get_nowait(port_id, &link); if (rate > link.link_speed) { printf("Invalid rate value:%u bigger than link speed: %u\n", rate, link.link_speed); return 1; } diag = rte_eth_set_vf_rate_limit(port_id, vf, rate, q_msk); if (diag == 0) return diag; printf("rte_eth_set_vf_rate_limit for port_id=%d failed diag=%d\n", port_id, diag); return diag; } /* * Functions to manage the set of filtered Multicast MAC addresses. * * A pool of filtered multicast MAC addresses is associated with each port. * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses. * The address of the pool and the number of valid multicast MAC addresses * recorded in the pool are stored in the fields "mc_addr_pool" and * "mc_addr_nb" of the "rte_port" data structure. * * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes * to be supplied a contiguous array of multicast MAC addresses. * To comply with this constraint, the set of multicast addresses recorded * into the pool are systematically compacted at the beginning of the pool. * Hence, when a multicast address is removed from the pool, all following * addresses, if any, are copied back to keep the set contiguous. */ #define MCAST_POOL_INC 32 static int mcast_addr_pool_extend(struct rte_port *port) { struct ether_addr *mc_pool; size_t mc_pool_size; /* * If a free entry is available at the end of the pool, just * increment the number of recorded multicast addresses. */ if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) { port->mc_addr_nb++; return 0; } /* * [re]allocate a pool with MCAST_POOL_INC more entries. * The previous test guarantees that port->mc_addr_nb is a multiple * of MCAST_POOL_INC. */ mc_pool_size = sizeof(struct ether_addr) * (port->mc_addr_nb + MCAST_POOL_INC); mc_pool = (struct ether_addr *) realloc(port->mc_addr_pool, mc_pool_size); if (mc_pool == NULL) { printf("allocation of pool of %u multicast addresses failed\n", port->mc_addr_nb + MCAST_POOL_INC); return -ENOMEM; } port->mc_addr_pool = mc_pool; port->mc_addr_nb++; return 0; } static void mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx) { port->mc_addr_nb--; if (addr_idx == port->mc_addr_nb) { /* No need to recompact the set of multicast addressses. */ if (port->mc_addr_nb == 0) { /* free the pool of multicast addresses. */ free(port->mc_addr_pool); port->mc_addr_pool = NULL; } return; } memmove(&port->mc_addr_pool[addr_idx], &port->mc_addr_pool[addr_idx + 1], sizeof(struct ether_addr) * (port->mc_addr_nb - addr_idx)); } static void eth_port_multicast_addr_list_set(uint8_t port_id) { struct rte_port *port; int diag; port = &ports[port_id]; diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool, port->mc_addr_nb); if (diag == 0) return; printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n", port->mc_addr_nb, port_id, -diag); } void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr) { struct rte_port *port; uint32_t i; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; port = &ports[port_id]; /* * Check that the added multicast MAC address is not already recorded * in the pool of multicast addresses. */ for (i = 0; i < port->mc_addr_nb; i++) { if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) { printf("multicast address already filtered by port\n"); return; } } if (mcast_addr_pool_extend(port) != 0) return; ether_addr_copy(mc_addr, &port->mc_addr_pool[i]); eth_port_multicast_addr_list_set(port_id); } void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr) { struct rte_port *port; uint32_t i; if (port_id_is_invalid(port_id, ENABLED_WARN)) return; port = &ports[port_id]; /* * Search the pool of multicast MAC addresses for the removed address. */ for (i = 0; i < port->mc_addr_nb; i++) { if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) break; } if (i == port->mc_addr_nb) { printf("multicast address not filtered by port %d\n", port_id); return; } mcast_addr_pool_remove(port, i); eth_port_multicast_addr_list_set(port_id); } ================================================ FILE: app/test-pmd/csumonly.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" #define IP_DEFTTL 64 /* from RFC 1340. */ #define IP_VERSION 0x40 #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) #define GRE_KEY_PRESENT 0x2000 #define GRE_KEY_LEN 4 #define GRE_SUPPORTED_FIELDS GRE_KEY_PRESENT /* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */ #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8))) #else #define _htons(x) (x) #endif /* structure that caches offload info for the current packet */ struct testpmd_offload_info { uint16_t ethertype; uint16_t l2_len; uint16_t l3_len; uint16_t l4_len; uint8_t l4_proto; uint8_t is_tunnel; uint16_t outer_ethertype; uint16_t outer_l2_len; uint16_t outer_l3_len; uint8_t outer_l4_proto; uint16_t tso_segsz; }; /* simplified GRE header */ struct simple_gre_hdr { uint16_t flags; uint16_t proto; } __attribute__((__packed__)); static uint16_t get_psd_sum(void *l3_hdr, uint16_t ethertype, uint64_t ol_flags) { if (ethertype == _htons(ETHER_TYPE_IPv4)) return rte_ipv4_phdr_cksum(l3_hdr, ol_flags); else /* assume ethertype == ETHER_TYPE_IPv6 */ return rte_ipv6_phdr_cksum(l3_hdr, ol_flags); } static uint16_t get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype) { if (ethertype == _htons(ETHER_TYPE_IPv4)) return rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr); else /* assume ethertype == ETHER_TYPE_IPv6 */ return rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr); } /* Parse an IPv4 header to fill l3_len, l4_len, and l4_proto */ static void parse_ipv4(struct ipv4_hdr *ipv4_hdr, struct testpmd_offload_info *info) { struct tcp_hdr *tcp_hdr; info->l3_len = (ipv4_hdr->version_ihl & 0x0f) * 4; info->l4_proto = ipv4_hdr->next_proto_id; /* only fill l4_len for TCP, it's useful for TSO */ if (info->l4_proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + info->l3_len); info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2; } else info->l4_len = 0; } /* Parse an IPv6 header to fill l3_len, l4_len, and l4_proto */ static void parse_ipv6(struct ipv6_hdr *ipv6_hdr, struct testpmd_offload_info *info) { struct tcp_hdr *tcp_hdr; info->l3_len = sizeof(struct ipv6_hdr); info->l4_proto = ipv6_hdr->proto; /* only fill l4_len for TCP, it's useful for TSO */ if (info->l4_proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)ipv6_hdr + info->l3_len); info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2; } else info->l4_len = 0; } /* * Parse an ethernet header to fill the ethertype, l2_len, l3_len and * ipproto. This function is able to recognize IPv4/IPv6 with one optional vlan * header. The l4_len argument is only set in case of TCP (useful for TSO). */ static void parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info) { struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; info->l2_len = sizeof(struct ether_hdr); info->ethertype = eth_hdr->ether_type; if (info->ethertype == _htons(ETHER_TYPE_VLAN)) { struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); info->l2_len += sizeof(struct vlan_hdr); info->ethertype = vlan_hdr->eth_proto; } switch (info->ethertype) { case _htons(ETHER_TYPE_IPv4): ipv4_hdr = (struct ipv4_hdr *) ((char *)eth_hdr + info->l2_len); parse_ipv4(ipv4_hdr, info); break; case _htons(ETHER_TYPE_IPv6): ipv6_hdr = (struct ipv6_hdr *) ((char *)eth_hdr + info->l2_len); parse_ipv6(ipv6_hdr, info); break; default: info->l4_len = 0; info->l3_len = 0; info->l4_proto = 0; break; } } /* Parse a vxlan header */ static void #ifdef RTE_NEXT_ABI parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info, uint32_t pkt_type) #else parse_vxlan(struct udp_hdr *udp_hdr, struct testpmd_offload_info *info, uint64_t mbuf_olflags) #endif { struct ether_hdr *eth_hdr; /* check udp destination port, 4789 is the default vxlan port * (rfc7348) or that the rx offload flag is set (i40e only * currently) */ if (udp_hdr->dst_port != _htons(4789) && #ifdef RTE_NEXT_ABI RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0) #else (mbuf_olflags & (PKT_RX_TUNNEL_IPV4_HDR | PKT_RX_TUNNEL_IPV6_HDR)) == 0) #endif return; info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; eth_hdr = (struct ether_hdr *)((char *)udp_hdr + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)); parse_ethernet(eth_hdr, info); info->l2_len += ETHER_VXLAN_HLEN; /* add udp + vxlan */ } /* Parse a gre header */ static void parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info) { struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; uint8_t gre_len = 0; /* check which fields are supported */ if ((gre_hdr->flags & _htons(~GRE_SUPPORTED_FIELDS)) != 0) return; gre_len += sizeof(struct simple_gre_hdr); if (gre_hdr->flags & _htons(GRE_KEY_PRESENT)) gre_len += GRE_KEY_LEN; if (gre_hdr->proto == _htons(ETHER_TYPE_IPv4)) { info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; ipv4_hdr = (struct ipv4_hdr *)((char *)gre_hdr + gre_len); parse_ipv4(ipv4_hdr, info); info->ethertype = _htons(ETHER_TYPE_IPv4); info->l2_len = 0; } else if (gre_hdr->proto == _htons(ETHER_TYPE_IPv6)) { info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; ipv6_hdr = (struct ipv6_hdr *)((char *)gre_hdr + gre_len); info->ethertype = _htons(ETHER_TYPE_IPv6); parse_ipv6(ipv6_hdr, info); info->l2_len = 0; } else if (gre_hdr->proto == _htons(ETHER_TYPE_TEB)) { info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; info->outer_l4_proto = info->l4_proto; eth_hdr = (struct ether_hdr *)((char *)gre_hdr + gre_len); parse_ethernet(eth_hdr, info); } else return; info->l2_len += gre_len; } /* Parse an encapsulated ip or ipv6 header */ static void parse_encap_ip(void *encap_ip, struct testpmd_offload_info *info) { struct ipv4_hdr *ipv4_hdr = encap_ip; struct ipv6_hdr *ipv6_hdr = encap_ip; uint8_t ip_version; ip_version = (ipv4_hdr->version_ihl & 0xf0) >> 4; if (ip_version != 4 && ip_version != 6) return; info->is_tunnel = 1; info->outer_ethertype = info->ethertype; info->outer_l2_len = info->l2_len; info->outer_l3_len = info->l3_len; if (ip_version == 4) { parse_ipv4(ipv4_hdr, info); info->ethertype = _htons(ETHER_TYPE_IPv4); } else { parse_ipv6(ipv6_hdr, info); info->ethertype = _htons(ETHER_TYPE_IPv6); } info->l2_len = 0; } /* modify the IPv4 or IPv4 source address of a packet */ static void change_ip_addresses(void *l3_hdr, uint16_t ethertype) { struct ipv4_hdr *ipv4_hdr = l3_hdr; struct ipv6_hdr *ipv6_hdr = l3_hdr; if (ethertype == _htons(ETHER_TYPE_IPv4)) { ipv4_hdr->src_addr = rte_cpu_to_be_32(rte_be_to_cpu_32(ipv4_hdr->src_addr) + 1); } else if (ethertype == _htons(ETHER_TYPE_IPv6)) { ipv6_hdr->src_addr[15] = ipv6_hdr->src_addr[15] + 1; } } /* if possible, calculate the checksum of a packet in hw or sw, * depending on the testpmd command line configuration */ static uint64_t process_inner_cksums(void *l3_hdr, const struct testpmd_offload_info *info, uint16_t testpmd_ol_flags) { struct ipv4_hdr *ipv4_hdr = l3_hdr; struct udp_hdr *udp_hdr; struct tcp_hdr *tcp_hdr; struct sctp_hdr *sctp_hdr; uint64_t ol_flags = 0; if (info->ethertype == _htons(ETHER_TYPE_IPv4)) { ipv4_hdr = l3_hdr; ipv4_hdr->hdr_checksum = 0; ol_flags |= PKT_TX_IPV4; if (info->tso_segsz != 0 && info->l4_proto == IPPROTO_TCP) { ol_flags |= PKT_TX_IP_CKSUM; } else { if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) ol_flags |= PKT_TX_IP_CKSUM; else ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr); } } else if (info->ethertype == _htons(ETHER_TYPE_IPv6)) ol_flags |= PKT_TX_IPV6; else return 0; /* packet type not supported, nothing to do */ if (info->l4_proto == IPPROTO_UDP) { udp_hdr = (struct udp_hdr *)((char *)l3_hdr + info->l3_len); /* do not recalculate udp cksum if it was 0 */ if (udp_hdr->dgram_cksum != 0) { udp_hdr->dgram_cksum = 0; if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) { ol_flags |= PKT_TX_UDP_CKSUM; udp_hdr->dgram_cksum = get_psd_sum(l3_hdr, info->ethertype, ol_flags); } else { udp_hdr->dgram_cksum = get_udptcp_checksum(l3_hdr, udp_hdr, info->ethertype); } } } else if (info->l4_proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + info->l3_len); tcp_hdr->cksum = 0; if (info->tso_segsz != 0) { ol_flags |= PKT_TX_TCP_SEG; tcp_hdr->cksum = get_psd_sum(l3_hdr, info->ethertype, ol_flags); } else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) { ol_flags |= PKT_TX_TCP_CKSUM; tcp_hdr->cksum = get_psd_sum(l3_hdr, info->ethertype, ol_flags); } else { tcp_hdr->cksum = get_udptcp_checksum(l3_hdr, tcp_hdr, info->ethertype); } } else if (info->l4_proto == IPPROTO_SCTP) { sctp_hdr = (struct sctp_hdr *)((char *)l3_hdr + info->l3_len); sctp_hdr->cksum = 0; /* sctp payload must be a multiple of 4 to be * offloaded */ if ((testpmd_ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) && ((ipv4_hdr->total_length & 0x3) == 0)) { ol_flags |= PKT_TX_SCTP_CKSUM; } else { /* XXX implement CRC32c, example available in * RFC3309 */ } } return ol_flags; } /* Calculate the checksum of outer header (only vxlan is supported, * meaning IP + UDP). The caller already checked that it's a vxlan * packet */ static uint64_t process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info, uint16_t testpmd_ol_flags) { struct ipv4_hdr *ipv4_hdr = outer_l3_hdr; struct ipv6_hdr *ipv6_hdr = outer_l3_hdr; struct udp_hdr *udp_hdr; uint64_t ol_flags = 0; if (info->outer_ethertype == _htons(ETHER_TYPE_IPv4)) { ipv4_hdr->hdr_checksum = 0; ol_flags |= PKT_TX_OUTER_IPV4; if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ol_flags |= PKT_TX_OUTER_IP_CKSUM; else ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr); } else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ol_flags |= PKT_TX_OUTER_IPV6; if (info->outer_l4_proto != IPPROTO_UDP) return ol_flags; /* outer UDP checksum is always done in software as we have no * hardware supporting it today, and no API for it. */ udp_hdr = (struct udp_hdr *)((char *)outer_l3_hdr + info->outer_l3_len); /* do not recalculate udp cksum if it was 0 */ if (udp_hdr->dgram_cksum != 0) { udp_hdr->dgram_cksum = 0; if (info->outer_ethertype == _htons(ETHER_TYPE_IPv4)) udp_hdr->dgram_cksum = rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr); else udp_hdr->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr); } return ol_flags; } /* * Receive a burst of packets, and for each packet: * - parse packet, and try to recognize a supported packet type (1) * - if it's not a supported packet type, don't touch the packet, else: * - modify the IPs in inner headers and in outer headers if any * - reprocess the checksum of all supported layers. This is done in SW * or HW, depending on testpmd command line configuration * - if TSO is enabled in testpmd command line, also flag the mbuf for TCP * segmentation offload (this implies HW TCP checksum) * Then transmit packets on the output port. * * (1) Supported packets are: * Ether / (vlan) / IP|IP6 / UDP|TCP|SCTP . * Ether / (vlan) / outer IP|IP6 / outer UDP / VxLAN / Ether / IP|IP6 / * UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / GRE / Ether / IP|IP6 / UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / GRE / IP|IP6 / UDP|TCP|SCTP * Ether / (vlan) / outer IP|IP6 / IP|IP6 / UDP|TCP|SCTP * * The testpmd command line for this forward engine sets the flags * TESTPMD_TX_OFFLOAD_* in ports[tx_port].tx_ol_flags. They control * wether a checksum must be calculated in software or in hardware. The * IP, UDP, TCP and SCTP flags always concern the inner layer. The * OUTER_IP is only useful for tunnel packets. */ static void pkt_burst_checksum_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_port *txp; struct rte_mbuf *m; struct ether_hdr *eth_hdr; void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */ uint16_t nb_rx; uint16_t nb_tx; uint16_t i; uint64_t ol_flags; uint16_t testpmd_ol_flags; uint32_t rx_bad_ip_csum; uint32_t rx_bad_l4_csum; struct testpmd_offload_info info; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* receive a burst of packet */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; rx_bad_ip_csum = 0; rx_bad_l4_csum = 0; txp = &ports[fs->tx_port]; testpmd_ol_flags = txp->tx_ol_flags; memset(&info, 0, sizeof(info)); info.tso_segsz = txp->tso_segsz; for (i = 0; i < nb_rx; i++) { ol_flags = 0; info.is_tunnel = 0; m = pkts_burst[i]; /* Update the L3/L4 checksum error packet statistics */ rx_bad_ip_csum += ((m->ol_flags & PKT_RX_IP_CKSUM_BAD) != 0); rx_bad_l4_csum += ((m->ol_flags & PKT_RX_L4_CKSUM_BAD) != 0); /* step 1: dissect packet, parsing optional vlan, ip4/ip6, vxlan * and inner headers */ eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); parse_ethernet(eth_hdr, &info); l3_hdr = (char *)eth_hdr + info.l2_len; /* check if it's a supported tunnel */ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_PARSE_TUNNEL) { if (info.l4_proto == IPPROTO_UDP) { struct udp_hdr *udp_hdr; udp_hdr = (struct udp_hdr *)((char *)l3_hdr + info.l3_len); #ifdef RTE_NEXT_ABI parse_vxlan(udp_hdr, &info, m->packet_type); #else parse_vxlan(udp_hdr, &info, m->ol_flags); #endif } else if (info.l4_proto == IPPROTO_GRE) { struct simple_gre_hdr *gre_hdr; gre_hdr = (struct simple_gre_hdr *) ((char *)l3_hdr + info.l3_len); parse_gre(gre_hdr, &info); } else if (info.l4_proto == IPPROTO_IPIP) { void *encap_ip_hdr; encap_ip_hdr = (char *)l3_hdr + info.l3_len; parse_encap_ip(encap_ip_hdr, &info); } } /* update l3_hdr and outer_l3_hdr if a tunnel was parsed */ if (info.is_tunnel) { outer_l3_hdr = l3_hdr; l3_hdr = (char *)l3_hdr + info.outer_l3_len + info.l2_len; } /* step 2: change all source IPs (v4 or v6) so we need * to recompute the chksums even if they were correct */ change_ip_addresses(l3_hdr, info.ethertype); if (info.is_tunnel == 1) change_ip_addresses(outer_l3_hdr, info.outer_ethertype); /* step 3: depending on user command line configuration, * recompute checksum either in software or flag the * mbuf to offload the calculation to the NIC. If TSO * is configured, prepare the mbuf for TCP segmentation. */ /* process checksums of inner headers first */ ol_flags |= process_inner_cksums(l3_hdr, &info, testpmd_ol_flags); /* Then process outer headers if any. Note that the software * checksum will be wrong if one of the inner checksums is * processed in hardware. */ if (info.is_tunnel == 1) { ol_flags |= process_outer_cksums(outer_l3_hdr, &info, testpmd_ol_flags); } /* step 4: fill the mbuf meta data (flags and header lengths) */ if (info.is_tunnel == 1) { if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) { m->outer_l2_len = info.outer_l2_len; m->outer_l3_len = info.outer_l3_len; m->l2_len = info.l2_len; m->l3_len = info.l3_len; m->l4_len = info.l4_len; } else { /* if there is a outer UDP cksum processed in sw and the inner in hw, the outer checksum will be wrong as the payload will be modified by the hardware */ m->l2_len = info.outer_l2_len + info.outer_l3_len + info.l2_len; m->l3_len = info.l3_len; m->l4_len = info.l4_len; } } else { /* this is only useful if an offload flag is * set, but it does not hurt to fill it in any * case */ m->l2_len = info.l2_len; m->l3_len = info.l3_len; m->l4_len = info.l4_len; } m->tso_segsz = info.tso_segsz; m->ol_flags = ol_flags; /* if verbose mode is enabled, dump debug info */ if (verbose_level > 0) { struct { uint64_t flag; uint64_t mask; } tx_flags[] = { { PKT_TX_IP_CKSUM, PKT_TX_IP_CKSUM }, { PKT_TX_UDP_CKSUM, PKT_TX_L4_MASK }, { PKT_TX_TCP_CKSUM, PKT_TX_L4_MASK }, { PKT_TX_SCTP_CKSUM, PKT_TX_L4_MASK }, { PKT_TX_IPV4, PKT_TX_IPV4 }, { PKT_TX_IPV6, PKT_TX_IPV6 }, { PKT_TX_OUTER_IP_CKSUM, PKT_TX_OUTER_IP_CKSUM }, { PKT_TX_OUTER_IPV4, PKT_TX_OUTER_IPV4 }, { PKT_TX_OUTER_IPV6, PKT_TX_OUTER_IPV6 }, { PKT_TX_TCP_SEG, PKT_TX_TCP_SEG }, }; unsigned j; const char *name; printf("-----------------\n"); /* dump rx parsed packet info */ printf("rx: l2_len=%d ethertype=%x l3_len=%d " "l4_proto=%d l4_len=%d\n", info.l2_len, rte_be_to_cpu_16(info.ethertype), info.l3_len, info.l4_proto, info.l4_len); if (info.is_tunnel == 1) printf("rx: outer_l2_len=%d outer_ethertype=%x " "outer_l3_len=%d\n", info.outer_l2_len, rte_be_to_cpu_16(info.outer_ethertype), info.outer_l3_len); /* dump tx packet info */ if ((testpmd_ol_flags & (TESTPMD_TX_OFFLOAD_IP_CKSUM | TESTPMD_TX_OFFLOAD_UDP_CKSUM | TESTPMD_TX_OFFLOAD_TCP_CKSUM | TESTPMD_TX_OFFLOAD_SCTP_CKSUM)) || info.tso_segsz != 0) printf("tx: m->l2_len=%d m->l3_len=%d " "m->l4_len=%d\n", m->l2_len, m->l3_len, m->l4_len); if ((info.is_tunnel == 1) && (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM)) printf("tx: m->outer_l2_len=%d m->outer_l3_len=%d\n", m->outer_l2_len, m->outer_l3_len); if (info.tso_segsz != 0) printf("tx: m->tso_segsz=%d\n", m->tso_segsz); printf("tx: flags="); for (j = 0; j < sizeof(tx_flags)/sizeof(*tx_flags); j++) { name = rte_get_tx_ol_flag_name(tx_flags[j].flag); if ((m->ol_flags & tx_flags[j].mask) == tx_flags[j].flag) printf("%s ", name); } printf("\n"); } } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); fs->tx_packets += nb_tx; fs->rx_bad_ip_csum += rx_bad_ip_csum; fs->rx_bad_l4_csum += rx_bad_l4_csum; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_rx)) { fs->fwd_dropped += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine csum_fwd_engine = { .fwd_mode_name = "csum", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_checksum_forward, }; ================================================ FILE: app/test-pmd/flowgen.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2013 Tilera Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Tilera Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" /* hardcoded configuration (for now) */ static unsigned cfg_n_flows = 1024; static unsigned cfg_pkt_size = 300; static uint32_t cfg_ip_src = IPv4(10, 254, 0, 0); static uint32_t cfg_ip_dst = IPv4(10, 253, 0, 0); static uint16_t cfg_udp_src = 1000; static uint16_t cfg_udp_dst = 1001; static struct ether_addr cfg_ether_src = {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x00 }}; static struct ether_addr cfg_ether_dst = {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x01 }}; #define IP_DEFTTL 64 /* from RFC 1340. */ #define IP_VERSION 0x40 #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) static inline struct rte_mbuf * tx_mbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return (m); } static inline uint16_t ip_sum(const unaligned_uint16_t *hdr, int hdr_len) { uint32_t sum = 0; while (hdr_len > 1) { sum += *hdr++; if (sum & 0x80000000) sum = (sum & 0xFFFF) + (sum >> 16); hdr_len -= 2; } while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); return ~sum; } /* * Multi-flow generation mode. * * We originate a bunch of flows (varying destination IP addresses), and * terminate receive traffic. Received traffic is simply discarded, but we * still do so in order to maintain traffic statistics. */ static void pkt_burst_flow_gen(struct fwd_stream *fs) { unsigned pkt_size = cfg_pkt_size - 4; /* Adjust FCS */ struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mempool *mbp; struct rte_mbuf *pkt; struct ether_hdr *eth_hdr; struct ipv4_hdr *ip_hdr; struct udp_hdr *udp_hdr; uint16_t vlan_tci, vlan_tci_outer; uint16_t ol_flags; uint16_t nb_rx; uint16_t nb_tx; uint16_t nb_pkt; uint16_t i; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif static int next_flow = 0; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* Receive a burst of packets and discard them. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); fs->rx_packets += nb_rx; for (i = 0; i < nb_rx; i++) rte_pktmbuf_free(pkts_burst[i]); mbp = current_fwd_lcore()->mbp; vlan_tci = ports[fs->tx_port].tx_vlan_id; vlan_tci_outer = ports[fs->tx_port].tx_vlan_id_outer; ol_flags = ports[fs->tx_port].tx_ol_flags; for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) { pkt = tx_mbuf_alloc(mbp); if (!pkt) break; pkt->data_len = pkt_size; pkt->next = NULL; /* Initialize Ethernet header. */ eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); ether_addr_copy(&cfg_ether_dst, ð_hdr->d_addr); ether_addr_copy(&cfg_ether_src, ð_hdr->s_addr); eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); /* Initialize IP header. */ ip_hdr = (struct ipv4_hdr *)(eth_hdr + 1); memset(ip_hdr, 0, sizeof(*ip_hdr)); ip_hdr->version_ihl = IP_VHL_DEF; ip_hdr->type_of_service = 0; ip_hdr->fragment_offset = 0; ip_hdr->time_to_live = IP_DEFTTL; ip_hdr->next_proto_id = IPPROTO_UDP; ip_hdr->packet_id = 0; ip_hdr->src_addr = rte_cpu_to_be_32(cfg_ip_src); ip_hdr->dst_addr = rte_cpu_to_be_32(cfg_ip_dst + next_flow); ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_size - sizeof(*eth_hdr)); ip_hdr->hdr_checksum = ip_sum((unaligned_uint16_t *)ip_hdr, sizeof(*ip_hdr)); /* Initialize UDP header. */ udp_hdr = (struct udp_hdr *)(ip_hdr + 1); udp_hdr->src_port = rte_cpu_to_be_16(cfg_udp_src); udp_hdr->dst_port = rte_cpu_to_be_16(cfg_udp_dst); udp_hdr->dgram_cksum = 0; /* No UDP checksum. */ udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_size - sizeof(*eth_hdr) - sizeof(*ip_hdr)); pkt->nb_segs = 1; pkt->pkt_len = pkt_size; pkt->ol_flags = ol_flags; pkt->vlan_tci = vlan_tci; pkt->vlan_tci_outer = vlan_tci_outer; pkt->l2_len = sizeof(struct ether_hdr); pkt->l3_len = sizeof(struct ipv4_hdr); pkts_burst[nb_pkt] = pkt; next_flow = (next_flow + 1) % cfg_n_flows; } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_pkt)) { /* Back out the flow counter. */ next_flow -= (nb_pkt - nb_tx); while (next_flow < 0) next_flow += cfg_n_flows; do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_pkt); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine flow_gen_engine = { .fwd_mode_name = "flowgen", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_flow_gen, }; ================================================ FILE: app/test-pmd/icmpecho.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2013 6WIND * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" static const char * arp_op_name(uint16_t arp_op) { switch (arp_op ) { case ARP_OP_REQUEST: return "ARP Request"; case ARP_OP_REPLY: return "ARP Reply"; case ARP_OP_REVREQUEST: return "Reverse ARP Request"; case ARP_OP_REVREPLY: return "Reverse ARP Reply"; case ARP_OP_INVREQUEST: return "Peer Identify Request"; case ARP_OP_INVREPLY: return "Peer Identify Reply"; default: break; } return "Unkwown ARP op"; } static const char * ip_proto_name(uint16_t ip_proto) { static const char * ip_proto_names[] = { "IP6HOPOPTS", /**< IP6 hop-by-hop options */ "ICMP", /**< control message protocol */ "IGMP", /**< group mgmt protocol */ "GGP", /**< gateway^2 (deprecated) */ "IPv4", /**< IPv4 encapsulation */ "UNASSIGNED", "TCP", /**< transport control protocol */ "ST", /**< Stream protocol II */ "EGP", /**< exterior gateway protocol */ "PIGP", /**< private interior gateway */ "RCC_MON", /**< BBN RCC Monitoring */ "NVPII", /**< network voice protocol*/ "PUP", /**< pup */ "ARGUS", /**< Argus */ "EMCON", /**< EMCON */ "XNET", /**< Cross Net Debugger */ "CHAOS", /**< Chaos*/ "UDP", /**< user datagram protocol */ "MUX", /**< Multiplexing */ "DCN_MEAS", /**< DCN Measurement Subsystems */ "HMP", /**< Host Monitoring */ "PRM", /**< Packet Radio Measurement */ "XNS_IDP", /**< xns idp */ "TRUNK1", /**< Trunk-1 */ "TRUNK2", /**< Trunk-2 */ "LEAF1", /**< Leaf-1 */ "LEAF2", /**< Leaf-2 */ "RDP", /**< Reliable Data */ "IRTP", /**< Reliable Transaction */ "TP4", /**< tp-4 w/ class negotiation */ "BLT", /**< Bulk Data Transfer */ "NSP", /**< Network Services */ "INP", /**< Merit Internodal */ "SEP", /**< Sequential Exchange */ "3PC", /**< Third Party Connect */ "IDPR", /**< InterDomain Policy Routing */ "XTP", /**< XTP */ "DDP", /**< Datagram Delivery */ "CMTP", /**< Control Message Transport */ "TPXX", /**< TP++ Transport */ "ILTP", /**< IL transport protocol */ "IPv6_HDR", /**< IP6 header */ "SDRP", /**< Source Demand Routing */ "IPv6_RTG", /**< IP6 routing header */ "IPv6_FRAG", /**< IP6 fragmentation header */ "IDRP", /**< InterDomain Routing*/ "RSVP", /**< resource reservation */ "GRE", /**< General Routing Encap. */ "MHRP", /**< Mobile Host Routing */ "BHA", /**< BHA */ "ESP", /**< IP6 Encap Sec. Payload */ "AH", /**< IP6 Auth Header */ "INLSP", /**< Integ. Net Layer Security */ "SWIPE", /**< IP with encryption */ "NHRP", /**< Next Hop Resolution */ "UNASSIGNED", "UNASSIGNED", "UNASSIGNED", "ICMPv6", /**< ICMP6 */ "IPv6NONEXT", /**< IP6 no next header */ "Ipv6DSTOPTS",/**< IP6 destination option */ "AHIP", /**< any host internal protocol */ "CFTP", /**< CFTP */ "HELLO", /**< "hello" routing protocol */ "SATEXPAK", /**< SATNET/Backroom EXPAK */ "KRYPTOLAN", /**< Kryptolan */ "RVD", /**< Remote Virtual Disk */ "IPPC", /**< Pluribus Packet Core */ "ADFS", /**< Any distributed FS */ "SATMON", /**< Satnet Monitoring */ "VISA", /**< VISA Protocol */ "IPCV", /**< Packet Core Utility */ "CPNX", /**< Comp. Prot. Net. Executive */ "CPHB", /**< Comp. Prot. HeartBeat */ "WSN", /**< Wang Span Network */ "PVP", /**< Packet Video Protocol */ "BRSATMON", /**< BackRoom SATNET Monitoring */ "ND", /**< Sun net disk proto (temp.) */ "WBMON", /**< WIDEBAND Monitoring */ "WBEXPAK", /**< WIDEBAND EXPAK */ "EON", /**< ISO cnlp */ "VMTP", /**< VMTP */ "SVMTP", /**< Secure VMTP */ "VINES", /**< Banyon VINES */ "TTP", /**< TTP */ "IGP", /**< NSFNET-IGP */ "DGP", /**< dissimilar gateway prot. */ "TCF", /**< TCF */ "IGRP", /**< Cisco/GXS IGRP */ "OSPFIGP", /**< OSPFIGP */ "SRPC", /**< Strite RPC protocol */ "LARP", /**< Locus Address Resoloution */ "MTP", /**< Multicast Transport */ "AX25", /**< AX.25 Frames */ "4IN4", /**< IP encapsulated in IP */ "MICP", /**< Mobile Int.ing control */ "SCCSP", /**< Semaphore Comm. security */ "ETHERIP", /**< Ethernet IP encapsulation */ "ENCAP", /**< encapsulation header */ "AES", /**< any private encr. scheme */ "GMTP", /**< GMTP */ "IPCOMP", /**< payload compression (IPComp) */ "UNASSIGNED", "UNASSIGNED", "PIM", /**< Protocol Independent Mcast */ }; if (ip_proto < sizeof(ip_proto_names) / sizeof(ip_proto_names[0])) return ip_proto_names[ip_proto]; switch (ip_proto) { #ifdef IPPROTO_PGM case IPPROTO_PGM: /**< PGM */ return "PGM"; #endif case IPPROTO_SCTP: /**< Stream Control Transport Protocol */ return "SCTP"; #ifdef IPPROTO_DIVERT case IPPROTO_DIVERT: /**< divert pseudo-protocol */ return "DIVERT"; #endif case IPPROTO_RAW: /**< raw IP packet */ return "RAW"; default: break; } return "UNASSIGNED"; } static void ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf) { uint32_t ipv4_addr; ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr); sprintf(buf, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF, (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF, ipv4_addr & 0xFF); } static void ether_addr_dump(const char *what, const struct ether_addr *ea) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, ea); if (what) printf("%s", what); printf("%s", buf); } static void ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr) { char buf[16]; ipv4_addr_to_dot(be_ipv4_addr, buf); if (what) printf("%s", what); printf("%s", buf); } static uint16_t ipv4_hdr_cksum(struct ipv4_hdr *ip_h) { uint16_t *v16_h; uint32_t ip_cksum; /* * Compute the sum of successive 16-bit words of the IPv4 header, * skipping the checksum field of the header. */ v16_h = (unaligned_uint16_t *) ip_h; ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] + v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9]; /* reduce 32 bit checksum to 16 bits and complement it */ ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16); ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16); ip_cksum = (~ip_cksum) & 0x0000FFFF; return (ip_cksum == 0) ? 0xFFFF : (uint16_t) ip_cksum; } #define is_multicast_ipv4_addr(ipv4_addr) \ (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0) /* * Receive a burst of packets, lookup for ICMP echo requets, and, if any, * send back ICMP echo replies. */ static void reply_to_icmp_echo_rqsts(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *pkt; struct ether_hdr *eth_h; struct vlan_hdr *vlan_h; struct arp_hdr *arp_h; struct ipv4_hdr *ip_h; struct icmp_hdr *icmp_h; struct ether_addr eth_addr; uint32_t ip_addr; uint16_t nb_rx; uint16_t nb_tx; uint16_t nb_replies; uint16_t eth_type; uint16_t vlan_id; uint16_t arp_op; uint16_t arp_pro; uint32_t cksum; uint8_t i; int l2_len; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * First, receive a burst of packets. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; nb_replies = 0; for (i = 0; i < nb_rx; i++) { pkt = pkts_burst[i]; eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type); l2_len = sizeof(struct ether_hdr); if (verbose_level > 0) { printf("\nPort %d pkt-len=%u nb-segs=%u\n", fs->rx_port, pkt->pkt_len, pkt->nb_segs); ether_addr_dump(" ETH: src=", ð_h->s_addr); ether_addr_dump(" dst=", ð_h->d_addr); } if (eth_type == ETHER_TYPE_VLAN) { vlan_h = (struct vlan_hdr *) ((char *)eth_h + sizeof(struct ether_hdr)); l2_len += sizeof(struct vlan_hdr); eth_type = rte_be_to_cpu_16(vlan_h->eth_proto); if (verbose_level > 0) { vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci) & 0xFFF; printf(" [vlan id=%u]", vlan_id); } } if (verbose_level > 0) { printf(" type=0x%04x\n", eth_type); } /* Reply to ARP requests */ if (eth_type == ETHER_TYPE_ARP) { arp_h = (struct arp_hdr *) ((char *)eth_h + l2_len); arp_op = RTE_BE_TO_CPU_16(arp_h->arp_op); arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_pro); if (verbose_level > 0) { printf(" ARP: hrd=%d proto=0x%04x hln=%d " "pln=%d op=%u (%s)\n", RTE_BE_TO_CPU_16(arp_h->arp_hrd), arp_pro, arp_h->arp_hln, arp_h->arp_pln, arp_op, arp_op_name(arp_op)); } if ((RTE_BE_TO_CPU_16(arp_h->arp_hrd) != ARP_HRD_ETHER) || (arp_pro != ETHER_TYPE_IPv4) || (arp_h->arp_hln != 6) || (arp_h->arp_pln != 4) ) { rte_pktmbuf_free(pkt); if (verbose_level > 0) printf("\n"); continue; } if (verbose_level > 0) { ether_addr_copy(&arp_h->arp_data.arp_sha, ð_addr); ether_addr_dump(" sha=", ð_addr); ip_addr = arp_h->arp_data.arp_sip; ipv4_addr_dump(" sip=", ip_addr); printf("\n"); ether_addr_copy(&arp_h->arp_data.arp_tha, ð_addr); ether_addr_dump(" tha=", ð_addr); ip_addr = arp_h->arp_data.arp_tip; ipv4_addr_dump(" tip=", ip_addr); printf("\n"); } if (arp_op != ARP_OP_REQUEST) { rte_pktmbuf_free(pkt); continue; } /* * Build ARP reply. */ /* Use source MAC address as destination MAC address. */ ether_addr_copy(ð_h->s_addr, ð_h->d_addr); /* Set source MAC address with MAC address of TX port */ ether_addr_copy(&ports[fs->tx_port].eth_addr, ð_h->s_addr); arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); ether_addr_copy(&arp_h->arp_data.arp_tha, ð_addr); ether_addr_copy(&arp_h->arp_data.arp_sha, &arp_h->arp_data.arp_tha); ether_addr_copy(ð_h->s_addr, &arp_h->arp_data.arp_sha); /* Swap IP addresses in ARP payload */ ip_addr = arp_h->arp_data.arp_sip; arp_h->arp_data.arp_sip = arp_h->arp_data.arp_tip; arp_h->arp_data.arp_tip = ip_addr; pkts_burst[nb_replies++] = pkt; continue; } if (eth_type != ETHER_TYPE_IPv4) { rte_pktmbuf_free(pkt); continue; } ip_h = (struct ipv4_hdr *) ((char *)eth_h + l2_len); if (verbose_level > 0) { ipv4_addr_dump(" IPV4: src=", ip_h->src_addr); ipv4_addr_dump(" dst=", ip_h->dst_addr); printf(" proto=%d (%s)\n", ip_h->next_proto_id, ip_proto_name(ip_h->next_proto_id)); } /* * Check if packet is a ICMP echo request. */ icmp_h = (struct icmp_hdr *) ((char *)ip_h + sizeof(struct ipv4_hdr)); if (! ((ip_h->next_proto_id == IPPROTO_ICMP) && (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST) && (icmp_h->icmp_code == 0))) { rte_pktmbuf_free(pkt); continue; } if (verbose_level > 0) printf(" ICMP: echo request seq id=%d\n", rte_be_to_cpu_16(icmp_h->icmp_seq_nb)); /* * Prepare ICMP echo reply to be sent back. * - switch ethernet source and destinations addresses, * - use the request IP source address as the reply IP * destination address, * - if the request IP destination address is a multicast * address: * - choose a reply IP source address different from the * request IP source address, * - re-compute the IP header checksum. * Otherwise: * - switch the request IP source and destination * addresses in the reply IP header, * - keep the IP header checksum unchanged. * - set IP_ICMP_ECHO_REPLY in ICMP header. * ICMP checksum is computed by assuming it is valid in the * echo request and not verified. */ ether_addr_copy(ð_h->s_addr, ð_addr); ether_addr_copy(ð_h->d_addr, ð_h->s_addr); ether_addr_copy(ð_addr, ð_h->d_addr); ip_addr = ip_h->src_addr; if (is_multicast_ipv4_addr(ip_h->dst_addr)) { uint32_t ip_src; ip_src = rte_be_to_cpu_32(ip_addr); if ((ip_src & 0x00000003) == 1) ip_src = (ip_src & 0xFFFFFFFC) | 0x00000002; else ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001; ip_h->src_addr = rte_cpu_to_be_32(ip_src); ip_h->dst_addr = ip_addr; ip_h->hdr_checksum = ipv4_hdr_cksum(ip_h); } else { ip_h->src_addr = ip_h->dst_addr; ip_h->dst_addr = ip_addr; } icmp_h->icmp_type = IP_ICMP_ECHO_REPLY; cksum = ~icmp_h->icmp_cksum & 0xffff; cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff; cksum += htons(IP_ICMP_ECHO_REPLY << 8); cksum = (cksum & 0xffff) + (cksum >> 16); cksum = (cksum & 0xffff) + (cksum >> 16); icmp_h->icmp_cksum = ~cksum; pkts_burst[nb_replies++] = pkt; } /* Send back ICMP echo replies, if any. */ if (nb_replies > 0) { nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_replies); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_replies)) { fs->fwd_dropped += (nb_replies - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_replies); } } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine icmp_echo_engine = { .fwd_mode_name = "icmpecho", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = reply_to_icmp_echo_rqsts, }; ================================================ FILE: app/test-pmd/ieee1588fwd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "testpmd.h" /** * The structure of a PTP V2 packet. * * Only the minimum fields used by the ieee1588 test are represented. */ struct ptpv2_msg { uint8_t msg_id; uint8_t version; /**< must be 0x02 */ uint8_t unused[34]; }; #define PTP_SYNC_MESSAGE 0x0 #define PTP_DELAY_REQ_MESSAGE 0x1 #define PTP_PATH_DELAY_REQ_MESSAGE 0x2 #define PTP_PATH_DELAY_RESP_MESSAGE 0x3 #define PTP_FOLLOWUP_MESSAGE 0x8 #define PTP_DELAY_RESP_MESSAGE 0x9 #define PTP_PATH_DELAY_FOLLOWUP_MESSAGE 0xA #define PTP_ANNOUNCE_MESSAGE 0xB #define PTP_SIGNALLING_MESSAGE 0xC #define PTP_MANAGEMENT_MESSAGE 0xD /* * Forwarding of IEEE1588 Precise Time Protocol (PTP) packets. * * In this mode, packets are received one by one and are expected to be * PTP V2 L2 Ethernet frames (with the specific Ethernet type "0x88F7") * containing PTP "sync" messages (version 2 at offset 1, and message ID * 0 at offset 0). * * Check that each received packet is a IEEE1588 PTP V2 packet of type * PTP_SYNC_MESSAGE, and that it has been identified and timestamped * by the hardware. * Check that the value of the last RX timestamp recorded by the controller * is greater than the previous one. * * If everything is OK, send the received packet back on the same port, * requesting for it to be timestamped by the hardware. * Check that the value of the last TX timestamp recorded by the controller * is greater than the previous one. */ static void port_ieee1588_rx_timestamp_check(portid_t pi, uint32_t index) { struct timespec timestamp = {0, 0}; if (rte_eth_timesync_read_rx_timestamp(pi, ×tamp, index) < 0) { printf("Port %u RX timestamp registers not valid\n", (unsigned) pi); return; } printf("Port %u RX timestamp value %lu\n", (unsigned) pi, timestamp.tv_sec); } #define MAX_TX_TMST_WAIT_MICROSECS 1000 /**< 1 milli-second */ static void port_ieee1588_tx_timestamp_check(portid_t pi) { struct timespec timestamp = {0, 0}; unsigned wait_us = 0; while ((rte_eth_timesync_read_tx_timestamp(pi, ×tamp) < 0) && (wait_us < MAX_TX_TMST_WAIT_MICROSECS)) { rte_delay_us(1); wait_us++; } if (wait_us >= MAX_TX_TMST_WAIT_MICROSECS) { printf("Port %u TX timestamp registers not valid after " "%u micro-seconds\n", (unsigned) pi, (unsigned) MAX_TX_TMST_WAIT_MICROSECS); return; } printf("Port %u TX timestamp value %lu validated after " "%u micro-second%s\n", (unsigned) pi, timestamp.tv_sec, wait_us, (wait_us == 1) ? "" : "s"); } static void ieee1588_packet_fwd(struct fwd_stream *fs) { struct rte_mbuf *mb; struct ether_hdr *eth_hdr; struct ptpv2_msg *ptp_hdr; uint16_t eth_type; uint32_t timesync_index; /* * Receive 1 packet at a time. */ if (rte_eth_rx_burst(fs->rx_port, fs->rx_queue, &mb, 1) == 0) return; fs->rx_packets += 1; /* * Check that the received packet is a PTP packet that was detected * by the hardware. */ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); eth_type = rte_be_to_cpu_16(eth_hdr->ether_type); if (! (mb->ol_flags & PKT_RX_IEEE1588_PTP)) { if (eth_type == ETHER_TYPE_1588) { printf("Port %u Received PTP packet not filtered" " by hardware\n", (unsigned) fs->rx_port); } else { printf("Port %u Received non PTP packet type=0x%4x " "len=%u\n", (unsigned) fs->rx_port, eth_type, (unsigned) mb->pkt_len); } rte_pktmbuf_free(mb); return; } if (eth_type != ETHER_TYPE_1588) { printf("Port %u Received NON PTP packet incorrectly" " detected by hardware\n", (unsigned) fs->rx_port); rte_pktmbuf_free(mb); return; } /* * Check that the received PTP packet is a PTP V2 packet of type * PTP_SYNC_MESSAGE. */ ptp_hdr = (struct ptpv2_msg *) (rte_pktmbuf_mtod(mb, char *) + sizeof(struct ether_hdr)); if (ptp_hdr->version != 0x02) { printf("Port %u Received PTP V2 Ethernet frame with wrong PTP" " protocol version 0x%x (should be 0x02)\n", (unsigned) fs->rx_port, ptp_hdr->version); rte_pktmbuf_free(mb); return; } if (ptp_hdr->msg_id != PTP_SYNC_MESSAGE) { printf("Port %u Received PTP V2 Ethernet frame with unexpected" " message ID 0x%x (expected 0x0 - PTP_SYNC_MESSAGE)\n", (unsigned) fs->rx_port, ptp_hdr->msg_id); rte_pktmbuf_free(mb); return; } printf("Port %u IEEE1588 PTP V2 SYNC Message filtered by hardware\n", (unsigned) fs->rx_port); /* * Check that the received PTP packet has been timestamped by the * hardware. */ if (! (mb->ol_flags & PKT_RX_IEEE1588_TMST)) { printf("Port %u Received PTP packet not timestamped" " by hardware\n", (unsigned) fs->rx_port); rte_pktmbuf_free(mb); return; } /* For i40e we need the timesync register index. It is ignored for the * other PMDs. */ timesync_index = mb->timesync & 0x3; /* Read and check the RX timestamp. */ port_ieee1588_rx_timestamp_check(fs->rx_port, timesync_index); /* Forward PTP packet with hardware TX timestamp */ mb->ol_flags |= PKT_TX_IEEE1588_TMST; fs->tx_packets += 1; if (rte_eth_tx_burst(fs->rx_port, fs->tx_queue, &mb, 1) == 0) { printf("Port %u sent PTP packet dropped\n", (unsigned) fs->rx_port); fs->fwd_dropped += 1; rte_pktmbuf_free(mb); return; } /* * Check the TX timestamp. */ port_ieee1588_tx_timestamp_check(fs->rx_port); } static void port_ieee1588_fwd_begin(portid_t pi) { rte_eth_timesync_enable(pi); } static void port_ieee1588_fwd_end(portid_t pi) { rte_eth_timesync_disable(pi); } struct fwd_engine ieee1588_fwd_engine = { .fwd_mode_name = "ieee1588", .port_fwd_begin = port_ieee1588_fwd_begin, .port_fwd_end = port_ieee1588_fwd_end, .packet_fwd = ieee1588_packet_fwd, }; ================================================ FILE: app/test-pmd/iofwd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" /* * Forwarding of packets in I/O mode. * Forward packets "as-is". * This is the fastest possible forwarding operation, as it does not access * to packets data. */ static void pkt_burst_io_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; uint16_t nb_rx; uint16_t nb_tx; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * Receive a burst of packets and forward them. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_rx)) { fs->fwd_dropped += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine io_fwd_engine = { .fwd_mode_name = "io", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_io_forward, }; ================================================ FILE: app/test-pmd/macfwd-retry.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" #define BURST_TX_WAIT_US 10 #define BURST_TX_RETRIES 5 /* * Global variables that control number of retires and * timeout (in us) between retires. */ uint32_t burst_tx_delay_time = BURST_TX_WAIT_US; uint32_t burst_tx_retry_num = BURST_TX_RETRIES; /* * Forwarding of packets in MAC mode with a wait and retry on TX to reduce packet loss. * Change the source and the destination Ethernet addressed of packets * before forwarding them. */ static void pkt_burst_mac_retry_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *mb; struct ether_hdr *eth_hdr; uint32_t retry; uint16_t nb_rx; uint16_t nb_tx; uint16_t i; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * Receive a burst of packets and forward them. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; for (i = 0; i < nb_rx; i++) { mb = pkts_burst[i]; eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); ether_addr_copy(&peer_eth_addrs[fs->peer_addr], ð_hdr->d_addr); ether_addr_copy(&ports[fs->tx_port].eth_addr, ð_hdr->s_addr); } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); /* * If not all packets have been TX'd then wait and retry. */ if (unlikely(nb_tx < nb_rx)) { for (retry = 0; retry < burst_tx_retry_num; retry++) { rte_delay_us(burst_tx_delay_time); nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue, &pkts_burst[nb_tx], nb_rx - nb_tx); if (nb_tx == nb_rx) break; } } fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_rx)) { fs->fwd_dropped += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine mac_retry_fwd_engine = { .fwd_mode_name = "mac_retry", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_mac_retry_forward, }; ================================================ FILE: app/test-pmd/macfwd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" /* * Forwarding of packets in MAC mode. * Change the source and the destination Ethernet addressed of packets * before forwarding them. */ static void pkt_burst_mac_forward(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_port *txp; struct rte_mbuf *mb; struct ether_hdr *eth_hdr; uint16_t nb_rx; uint16_t nb_tx; uint16_t i; uint64_t ol_flags = 0; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * Receive a burst of packets and forward them. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; txp = &ports[fs->tx_port]; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN) ol_flags = PKT_TX_VLAN_PKT; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ) ol_flags |= PKT_TX_QINQ_PKT; for (i = 0; i < nb_rx; i++) { mb = pkts_burst[i]; eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); ether_addr_copy(&peer_eth_addrs[fs->peer_addr], ð_hdr->d_addr); ether_addr_copy(&ports[fs->tx_port].eth_addr, ð_hdr->s_addr); mb->ol_flags = ol_flags; mb->l2_len = sizeof(struct ether_hdr); mb->l3_len = sizeof(struct ipv4_hdr); mb->vlan_tci = txp->tx_vlan_id; mb->vlan_tci_outer = txp->tx_vlan_id_outer; } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_rx)) { fs->fwd_dropped += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine mac_fwd_engine = { .fwd_mode_name = "mac", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_mac_forward, }; ================================================ FILE: app/test-pmd/macswap.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014 Tilera Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Tilera Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" /* * MAC swap forwarding mode: Swap the source and the destination Ethernet * addresses of packets before forwarding them. */ static void pkt_burst_mac_swap(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_port *txp; struct rte_mbuf *mb; struct ether_hdr *eth_hdr; struct ether_addr addr; uint16_t nb_rx; uint16_t nb_tx; uint16_t i; uint64_t ol_flags = 0; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * Receive a burst of packets and forward them. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; txp = &ports[fs->tx_port]; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN) ol_flags = PKT_TX_VLAN_PKT; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ) ol_flags |= PKT_TX_QINQ_PKT; for (i = 0; i < nb_rx; i++) { mb = pkts_burst[i]; eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); /* Swap dest and src mac addresses. */ ether_addr_copy(ð_hdr->d_addr, &addr); ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); ether_addr_copy(&addr, ð_hdr->s_addr); mb->ol_flags = ol_flags; mb->l2_len = sizeof(struct ether_hdr); mb->l3_len = sizeof(struct ipv4_hdr); mb->vlan_tci = txp->tx_vlan_id; mb->vlan_tci_outer = txp->tx_vlan_id_outer; } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_rx)) { fs->fwd_dropped += (nb_rx - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_rx); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine mac_swap_engine = { .fwd_mode_name = "macswap", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_mac_swap, }; ================================================ FILE: app/test-pmd/mempool_anon.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "mempool_osdep.h" #include #ifdef RTE_EXEC_ENV_LINUXAPP #include #include #include #define PAGEMAP_FNAME "/proc/self/pagemap" /* * the pfn (page frame number) are bits 0-54 (see pagemap.txt in linux * Documentation). */ #define PAGEMAP_PFN_BITS 54 #define PAGEMAP_PFN_MASK RTE_LEN2MASK(PAGEMAP_PFN_BITS, phys_addr_t) static int get_phys_map(void *va, phys_addr_t pa[], uint32_t pg_num, uint32_t pg_sz) { int32_t fd, rc; uint32_t i, nb; off_t ofs; ofs = (uintptr_t)va / pg_sz * sizeof(*pa); nb = pg_num * sizeof(*pa); if ((fd = open(PAGEMAP_FNAME, O_RDONLY)) < 0) return (ENOENT); if ((rc = pread(fd, pa, nb, ofs)) < 0 || (rc -= nb) != 0) { RTE_LOG(ERR, USER1, "failed read of %u bytes from \'%s\' " "at offset %zu, error code: %d\n", nb, PAGEMAP_FNAME, (size_t)ofs, errno); rc = ENOENT; } close(fd); for (i = 0; i != pg_num; i++) pa[i] = (pa[i] & PAGEMAP_PFN_MASK) * pg_sz; return (rc); } struct rte_mempool * mempool_anon_create(const char *name, unsigned elt_num, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags) { struct rte_mempool *mp; phys_addr_t *pa; char *va, *uv; uint32_t n, pg_num, pg_shift, pg_sz, total_size; size_t sz; ssize_t usz; int32_t rc; rc = ENOMEM; mp = NULL; pg_sz = getpagesize(); if (rte_is_power_of_2(pg_sz) == 0) { rte_errno = EINVAL; return (mp); } pg_shift = rte_bsf32(pg_sz); total_size = rte_mempool_calc_obj_size(elt_size, flags, NULL); /* calc max memory size and max number of pages needed. */ sz = rte_mempool_xmem_size(elt_num, total_size, pg_shift); pg_num = sz >> pg_shift; /* get chunk of virtually continuos memory.*/ if ((va = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_LOCKED, -1, 0)) == MAP_FAILED) { RTE_LOG(ERR, USER1, "%s(%s) failed mmap of %zu bytes, " "error code: %d\n", __func__, name, sz, errno); rte_errno = rc; return (mp); } /* extract physical mappings of the allocated memory. */ if ((pa = calloc(pg_num, sizeof (*pa))) != NULL && (rc = get_phys_map(va, pa, pg_num, pg_sz)) == 0) { /* * Check that allocated size is big enough to hold elt_num * objects and a calcualte how many bytes are actually required. */ if ((usz = rte_mempool_xmem_usage(va, elt_num, total_size, pa, pg_num, pg_shift)) < 0) { n = -usz; rc = ENOENT; RTE_LOG(ERR, USER1, "%s(%s) only %u objects from %u " "requested can be created over " "mmaped region %p of %zu bytes\n", __func__, name, n, elt_num, va, sz); } else { /* unmap unused pages if any */ if ((size_t)usz < sz) { uv = va + usz; usz = sz - usz; RTE_LOG(INFO, USER1, "%s(%s): unmap unused %zu of %zu " "mmaped bytes @%p\n", __func__, name, (size_t)usz, sz, uv); munmap(uv, usz); sz -= usz; pg_num = sz >> pg_shift; } if ((mp = rte_mempool_xmem_create(name, elt_num, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags, va, pa, pg_num, pg_shift)) != NULL) RTE_VERIFY(elt_num == mp->size); } } if (mp == NULL) { munmap(va, sz); rte_errno = rc; } free(pa); return (mp); } #else /* RTE_EXEC_ENV_LINUXAPP */ struct rte_mempool * mempool_anon_create(__rte_unused const char *name, __rte_unused unsigned elt_num, __rte_unused unsigned elt_size, __rte_unused unsigned cache_size, __rte_unused unsigned private_data_size, __rte_unused rte_mempool_ctor_t *mp_init, __rte_unused void *mp_init_arg, __rte_unused rte_mempool_obj_ctor_t *obj_init, __rte_unused void *obj_init_arg, __rte_unused int socket_id, __rte_unused unsigned flags) { rte_errno = ENOTSUP; return (NULL); } #endif /* RTE_EXEC_ENV_LINUXAPP */ ================================================ FILE: app/test-pmd/mempool_osdep.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MEMPOOL_OSDEP_H_ #define _MEMPOOL_OSDEP_H_ #include /** * @file * mempool OS specific header. */ /* * Create mempool over objects from mmap(..., MAP_ANONYMOUS, ...). */ struct rte_mempool * mempool_anon_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); #endif /*_RTE_MEMPOOL_OSDEP_H_ */ ================================================ FILE: app/test-pmd/parameters.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_CMDLINE #include #include #endif #ifdef RTE_LIBRTE_PMD_BOND #include #endif #include "testpmd.h" static void usage(char* progname) { printf("usage: %s " #ifdef RTE_LIBRTE_CMDLINE "[--interactive|-i] " #endif "[--help|-h] | [--auto-start|-a] | [" "--coremask=COREMASK --portmask=PORTMASK --numa " "--mbuf-size= | --total-num-mbufs= | " "--nb-cores= | --nb-ports= | " #ifdef RTE_LIBRTE_CMDLINE "--eth-peers-configfile= | " "--eth-peer=X,M:M:M:M:M:M | " #endif "--pkt-filter-mode= |" "--rss-ip | --rss-udp | " "--rxpt= | --rxht= | --rxwt= | --rxfreet= | " "--txpt= | --txht= | --txwt= | --txfreet= | " "--txrst= | --txqflags= ]\n", progname); #ifdef RTE_LIBRTE_CMDLINE printf(" --interactive: run in interactive mode.\n"); #endif printf(" --auto-start: start forwarding on init " "[always when non-interactive].\n"); printf(" --help: display this message and quit.\n"); printf(" --nb-cores=N: set the number of forwarding cores " "(1 <= N <= %d).\n", nb_lcores); printf(" --nb-ports=N: set the number of forwarding ports " "(1 <= N <= %d).\n", nb_ports); printf(" --coremask=COREMASK: hexadecimal bitmask of cores running " "the packet forwarding test. The master lcore is reserved for " "command line parsing only, and cannot be masked on for " "packet forwarding.\n"); printf(" --portmask=PORTMASK: hexadecimal bitmask of ports used " "by the packet forwarding test.\n"); printf(" --numa: enable NUMA-aware allocation of RX/TX rings and of " "RX memory buffers (mbufs).\n"); printf(" --port-numa-config=(port,socket)[,(port,socket)]: " "specify the socket on which the memory pool " "used by the port will be allocated.\n"); printf(" --ring-numa-config=(port,flag,socket)[,(port,flag,socket)]: " "specify the socket on which the TX/RX rings for " "the port will be allocated " "(flag: 1 for RX; 2 for TX; 3 for RX and TX).\n"); printf(" --socket-num=N: set socket from which all memory is allocated " "in NUMA mode.\n"); printf(" --mbuf-size=N: set the data size of mbuf to N bytes.\n"); printf(" --total-num-mbufs=N: set the number of mbufs to be allocated " "in mbuf pools.\n"); printf(" --max-pkt-len=N: set the maximum size of packet to N bytes.\n"); #ifdef RTE_LIBRTE_CMDLINE printf(" --eth-peers-configfile=name: config file with ethernet addresses " "of peer ports.\n"); printf(" --eth-peer=X,M:M:M:M:M:M: set the MAC address of the X peer " "port (0 <= X < %d).\n", RTE_MAX_ETHPORTS); #endif printf(" --pkt-filter-mode=N: set Flow Director mode " "(N: none (default mode) or signature or perfect).\n"); printf(" --pkt-filter-report-hash=N: set Flow Director report mode " "(N: none or match (default) or always).\n"); printf(" --pkt-filter-size=N: set Flow Director mode " "(N: 64K (default mode) or 128K or 256K).\n"); printf(" --pkt-filter-drop-queue=N: set drop-queue. " "In perfect mode, when you add a rule with queue = -1 " "the packet will be enqueued into the rx drop-queue. " "If the drop-queue doesn't exist, the packet is dropped. " "By default drop-queue=127.\n"); printf(" --crc-strip: enable CRC stripping by hardware.\n"); printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n"); printf(" --disable-hw-vlan: disable hardware vlan.\n"); printf(" --disable-hw-vlan-filter: disable hardware vlan filter.\n"); printf(" --disable-hw-vlan-strip: disable hardware vlan strip.\n"); printf(" --disable-hw-vlan-extend: disable hardware vlan extend.\n"); printf(" --enable-drop-en: enable per queue packet drop.\n"); printf(" --disable-rss: disable rss.\n"); printf(" --port-topology=N: set port topology (N: paired (default) or " "chained).\n"); printf(" --forward-mode=N: set forwarding mode (N: %s).\n", list_pkt_forwarding_modes()); printf(" --rss-ip: set RSS functions to IPv4/IPv6 only .\n"); printf(" --rss-udp: set RSS functions to IPv4/IPv6 + UDP.\n"); printf(" --rxq=N: set the number of RX queues per port to N.\n"); printf(" --rxd=N: set the number of descriptors in RX rings to N.\n"); printf(" --txq=N: set the number of TX queues per port to N.\n"); printf(" --txd=N: set the number of descriptors in TX rings to N.\n"); printf(" --burst=N: set the number of packets per burst to N.\n"); printf(" --mbcache=N: set the cache of mbuf memory pool to N.\n"); printf(" --rxpt=N: set prefetch threshold register of RX rings to N.\n"); printf(" --rxht=N: set the host threshold register of RX rings to N.\n"); printf(" --rxfreet=N: set the free threshold of RX descriptors to N " "(0 <= N < value of rxd).\n"); printf(" --rxwt=N: set the write-back threshold register of RX rings to N.\n"); printf(" --txpt=N: set the prefetch threshold register of TX rings to N.\n"); printf(" --txht=N: set the nhost threshold register of TX rings to N.\n"); printf(" --txwt=N: set the write-back threshold register of TX rings to N.\n"); printf(" --txfreet=N: set the transmit free threshold of TX rings to N " "(0 <= N <= value of txd).\n"); printf(" --txrst=N: set the transmit RS bit threshold of TX rings to N " "(0 <= N <= value of txd).\n"); printf(" --txqflags=0xXXXXXXXX: hexadecimal bitmask of TX queue flags " "(0 <= N <= 0x7FFFFFFF).\n"); printf(" --tx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: " "tx queues statistics counters mapping " "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); printf(" --rx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: " "rx queues statistics counters mapping " "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); printf(" --no-flush-rx: Don't flush RX streams before forwarding." " Used mainly with PCAP drivers.\n"); printf(" --txpkts=X[,Y]*: set TX segment sizes.\n"); printf(" --disable-link-check: disable check on link status when " "starting/stopping ports.\n"); } #ifdef RTE_LIBRTE_CMDLINE static int init_peer_eth_addrs(char *config_filename) { FILE *config_file; portid_t i; char buf[50]; config_file = fopen(config_filename, "r"); if (config_file == NULL) { perror("Failed to open eth config file\n"); return -1; } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (fgets(buf, sizeof(buf), config_file) == NULL) break; if (cmdline_parse_etheraddr(NULL, buf, &peer_eth_addrs[i], sizeof(peer_eth_addrs[i])) < 0) { printf("Bad MAC address format on line %d\n", i+1); fclose(config_file); return -1; } } fclose(config_file); nb_peer_eth_addrs = (portid_t) i; return 0; } #endif /* * Parse the coremask given as argument (hexadecimal string) and set * the global configuration of forwarding cores. */ static void parse_fwd_coremask(const char *coremask) { char *end; unsigned long long int cm; /* parse hexadecimal string */ end = NULL; cm = strtoull(coremask, &end, 16); if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0')) rte_exit(EXIT_FAILURE, "Invalid fwd core mask\n"); else if (set_fwd_lcores_mask((uint64_t) cm) < 0) rte_exit(EXIT_FAILURE, "coremask is not valid\n"); } /* * Parse the coremask given as argument (hexadecimal string) and set * the global configuration of forwarding cores. */ static void parse_fwd_portmask(const char *portmask) { char *end; unsigned long long int pm; /* parse hexadecimal string */ end = NULL; pm = strtoull(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) rte_exit(EXIT_FAILURE, "Invalid fwd port mask\n"); else set_fwd_ports_mask((uint64_t) pm); } static int parse_queue_stats_mapping_config(const char *q_arg, int is_rx) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_STATS_COUNTER, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; /* reset from value set at definition */ is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0); while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++){ errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */ if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) { printf("Stats counter not in the correct range 0..%d\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1); return -1; } if (!is_rx) { if ((nb_tx_queue_stats_mappings >= MAX_TX_QUEUE_STATS_MAPPINGS)) { printf("exceeded max number of TX queue " "statistics mappings: %hu\n", nb_tx_queue_stats_mappings); return -1; } tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id = (uint8_t)int_fld[FLD_PORT]; tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id = (uint8_t)int_fld[FLD_QUEUE]; tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id = (uint8_t)int_fld[FLD_STATS_COUNTER]; ++nb_tx_queue_stats_mappings; } else { if ((nb_rx_queue_stats_mappings >= MAX_RX_QUEUE_STATS_MAPPINGS)) { printf("exceeded max number of RX queue " "statistics mappings: %hu\n", nb_rx_queue_stats_mappings); return -1; } rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id = (uint8_t)int_fld[FLD_PORT]; rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id = (uint8_t)int_fld[FLD_QUEUE]; rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id = (uint8_t)int_fld[FLD_STATS_COUNTER]; ++nb_rx_queue_stats_mappings; } } /* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */ /* than to the default array (that was set at its definition) */ is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) : (tx_queue_stats_mappings = tx_queue_stats_mappings_array); return 0; } static int parse_portnuma_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; uint8_t i,port_id,socket_id; unsigned size; enum fieldnames { FLD_PORT = 0, FLD_SOCKET, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; portid_t pid; /* reset from value set at definition */ while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } port_id = (uint8_t)int_fld[FLD_PORT]; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return -1; } socket_id = (uint8_t)int_fld[FLD_SOCKET]; if(socket_id >= MAX_SOCKET) { printf("Invalid socket id, range is [0, %d]\n", MAX_SOCKET - 1); return -1; } port_numa[port_id] = socket_id; } return 0; } static int parse_ringnuma_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; uint8_t i,port_id,ring_flag,socket_id; unsigned size; enum fieldnames { FLD_PORT = 0, FLD_FLAG, FLD_SOCKET, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; portid_t pid; #define RX_RING_ONLY 0x1 #define TX_RING_ONLY 0x2 #define RXTX_RING 0x3 /* reset from value set at definition */ while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } port_id = (uint8_t)int_fld[FLD_PORT]; if (port_id_is_invalid(port_id, ENABLED_WARN)) { printf("Valid port range is [0"); FOREACH_PORT(pid, ports) printf(", %d", pid); printf("]\n"); return -1; } socket_id = (uint8_t)int_fld[FLD_SOCKET]; if (socket_id >= MAX_SOCKET) { printf("Invalid socket id, range is [0, %d]\n", MAX_SOCKET - 1); return -1; } ring_flag = (uint8_t)int_fld[FLD_FLAG]; if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) { printf("Invalid ring-flag=%d config for port =%d\n", ring_flag,port_id); return -1; } switch (ring_flag & RXTX_RING) { case RX_RING_ONLY: rxring_numa[port_id] = socket_id; break; case TX_RING_ONLY: txring_numa[port_id] = socket_id; break; case RXTX_RING: rxring_numa[port_id] = socket_id; txring_numa[port_id] = socket_id; break; default: printf("Invalid ring-flag=%d config for port=%d\n", ring_flag,port_id); break; } } return 0; } void launch_args_parse(int argc, char** argv) { int n, opt; char **argvopt; int opt_idx; enum { TX, RX }; static struct option lgopts[] = { { "help", 0, 0, 0 }, #ifdef RTE_LIBRTE_CMDLINE { "interactive", 0, 0, 0 }, { "auto-start", 0, 0, 0 }, { "eth-peers-configfile", 1, 0, 0 }, { "eth-peer", 1, 0, 0 }, #endif { "ports", 1, 0, 0 }, { "nb-cores", 1, 0, 0 }, { "nb-ports", 1, 0, 0 }, { "coremask", 1, 0, 0 }, { "portmask", 1, 0, 0 }, { "numa", 0, 0, 0 }, { "mp-anon", 0, 0, 0 }, { "port-numa-config", 1, 0, 0 }, { "ring-numa-config", 1, 0, 0 }, { "socket-num", 1, 0, 0 }, { "mbuf-size", 1, 0, 0 }, { "total-num-mbufs", 1, 0, 0 }, { "max-pkt-len", 1, 0, 0 }, { "pkt-filter-mode", 1, 0, 0 }, { "pkt-filter-report-hash", 1, 0, 0 }, { "pkt-filter-size", 1, 0, 0 }, { "pkt-filter-drop-queue", 1, 0, 0 }, { "crc-strip", 0, 0, 0 }, { "enable-rx-cksum", 0, 0, 0 }, { "disable-hw-vlan", 0, 0, 0 }, { "disable-hw-vlan-filter", 0, 0, 0 }, { "disable-hw-vlan-strip", 0, 0, 0 }, { "disable-hw-vlan-extend", 0, 0, 0 }, { "enable-drop-en", 0, 0, 0 }, { "disable-rss", 0, 0, 0 }, { "port-topology", 1, 0, 0 }, { "forward-mode", 1, 0, 0 }, { "rss-ip", 0, 0, 0 }, { "rss-udp", 0, 0, 0 }, { "rxq", 1, 0, 0 }, { "txq", 1, 0, 0 }, { "rxd", 1, 0, 0 }, { "txd", 1, 0, 0 }, { "burst", 1, 0, 0 }, { "mbcache", 1, 0, 0 }, { "txpt", 1, 0, 0 }, { "txht", 1, 0, 0 }, { "txwt", 1, 0, 0 }, { "txfreet", 1, 0, 0 }, { "txrst", 1, 0, 0 }, { "txqflags", 1, 0, 0 }, { "rxpt", 1, 0, 0 }, { "rxht", 1, 0, 0 }, { "rxwt", 1, 0, 0 }, { "rxfreet", 1, 0, 0 }, { "tx-queue-stats-mapping", 1, 0, 0 }, { "rx-queue-stats-mapping", 1, 0, 0 }, { "no-flush-rx", 0, 0, 0 }, { "txpkts", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { 0, 0, 0, 0 }, }; argvopt = argv; #ifdef RTE_LIBRTE_CMDLINE #define SHORTOPTS "i" #else #define SHORTOPTS "" #endif while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah", lgopts, &opt_idx)) != EOF) { switch (opt) { #ifdef RTE_LIBRTE_CMDLINE case 'i': printf("Interactive-mode selected\n"); interactive = 1; break; #endif case 'a': printf("Auto-start selected\n"); auto_start = 1; break; case 0: /*long options */ if (!strcmp(lgopts[opt_idx].name, "help")) { usage(argv[0]); rte_exit(EXIT_SUCCESS, "Displayed help\n"); } #ifdef RTE_LIBRTE_CMDLINE if (!strcmp(lgopts[opt_idx].name, "interactive")) { printf("Interactive-mode selected\n"); interactive = 1; } if (!strcmp(lgopts[opt_idx].name, "auto-start")) { printf("Auto-start selected\n"); auto_start = 1; } if (!strcmp(lgopts[opt_idx].name, "eth-peers-configfile")) { if (init_peer_eth_addrs(optarg) != 0) rte_exit(EXIT_FAILURE, "Cannot open logfile\n"); } if (!strcmp(lgopts[opt_idx].name, "eth-peer")) { char *port_end; uint8_t c, peer_addr[6]; errno = 0; n = strtoul(optarg, &port_end, 10); if (errno != 0 || port_end == optarg || *port_end++ != ',') rte_exit(EXIT_FAILURE, "Invalid eth-peer: %s", optarg); if (n >= RTE_MAX_ETHPORTS) rte_exit(EXIT_FAILURE, "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n", n, RTE_MAX_ETHPORTS); if (cmdline_parse_etheraddr(NULL, port_end, &peer_addr, sizeof(peer_addr)) < 0) rte_exit(EXIT_FAILURE, "Invalid ethernet address: %s\n", port_end); for (c = 0; c < 6; c++) peer_eth_addrs[n].addr_bytes[c] = peer_addr[c]; nb_peer_eth_addrs++; } #endif if (!strcmp(lgopts[opt_idx].name, "nb-ports")) { n = atoi(optarg); if (n > 0 && n <= nb_ports) nb_fwd_ports = (uint8_t) n; else rte_exit(EXIT_FAILURE, "Invalid port %d\n", n); } if (!strcmp(lgopts[opt_idx].name, "nb-cores")) { n = atoi(optarg); if (n > 0 && n <= nb_lcores) nb_fwd_lcores = (uint8_t) n; else rte_exit(EXIT_FAILURE, "nb-cores should be > 0 and <= %d\n", nb_lcores); } if (!strcmp(lgopts[opt_idx].name, "coremask")) parse_fwd_coremask(optarg); if (!strcmp(lgopts[opt_idx].name, "portmask")) parse_fwd_portmask(optarg); if (!strcmp(lgopts[opt_idx].name, "numa")) { numa_support = 1; memset(port_numa,NUMA_NO_CONFIG,RTE_MAX_ETHPORTS); memset(rxring_numa,NUMA_NO_CONFIG,RTE_MAX_ETHPORTS); memset(txring_numa,NUMA_NO_CONFIG,RTE_MAX_ETHPORTS); } if (!strcmp(lgopts[opt_idx].name, "mp-anon")) { mp_anon = 1; } if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) { if (parse_portnuma_config(optarg)) rte_exit(EXIT_FAILURE, "invalid port-numa configuration\n"); } if (!strcmp(lgopts[opt_idx].name, "ring-numa-config")) if (parse_ringnuma_config(optarg)) rte_exit(EXIT_FAILURE, "invalid ring-numa configuration\n"); if (!strcmp(lgopts[opt_idx].name, "socket-num")) { n = atoi(optarg); if(n < MAX_SOCKET) socket_num = (uint8_t)n; else rte_exit(EXIT_FAILURE, "The socket number should be < %d\n", MAX_SOCKET); } if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) { n = atoi(optarg); if (n > 0 && n <= 0xFFFF) mbuf_data_size = (uint16_t) n; else rte_exit(EXIT_FAILURE, "mbuf-size should be > 0 and < 65536\n"); } if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) { n = atoi(optarg); if (n > 1024) param_total_num_mbufs = (unsigned)n; else rte_exit(EXIT_FAILURE, "total-num-mbufs should be > 1024\n"); } if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) { n = atoi(optarg); if (n >= ETHER_MIN_LEN) { rx_mode.max_rx_pkt_len = (uint32_t) n; if (n > ETHER_MAX_LEN) rx_mode.jumbo_frame = 1; } else rte_exit(EXIT_FAILURE, "Invalid max-pkt-len=%d - should be > %d\n", n, ETHER_MIN_LEN); } if (!strcmp(lgopts[opt_idx].name, "pkt-filter-mode")) { if (!strcmp(optarg, "signature")) fdir_conf.mode = RTE_FDIR_MODE_SIGNATURE; else if (!strcmp(optarg, "perfect")) fdir_conf.mode = RTE_FDIR_MODE_PERFECT; else if (!strcmp(optarg, "none")) fdir_conf.mode = RTE_FDIR_MODE_NONE; else rte_exit(EXIT_FAILURE, "pkt-mode-invalid %s invalid - must be: " "none, signature or perfect\n", optarg); } if (!strcmp(lgopts[opt_idx].name, "pkt-filter-report-hash")) { if (!strcmp(optarg, "none")) fdir_conf.status = RTE_FDIR_NO_REPORT_STATUS; else if (!strcmp(optarg, "match")) fdir_conf.status = RTE_FDIR_REPORT_STATUS; else if (!strcmp(optarg, "always")) fdir_conf.status = RTE_FDIR_REPORT_STATUS_ALWAYS; else rte_exit(EXIT_FAILURE, "pkt-filter-report-hash %s invalid " "- must be: none or match or always\n", optarg); } if (!strcmp(lgopts[opt_idx].name, "pkt-filter-size")) { if (!strcmp(optarg, "64K")) fdir_conf.pballoc = RTE_FDIR_PBALLOC_64K; else if (!strcmp(optarg, "128K")) fdir_conf.pballoc = RTE_FDIR_PBALLOC_128K; else if (!strcmp(optarg, "256K")) fdir_conf.pballoc = RTE_FDIR_PBALLOC_256K; else rte_exit(EXIT_FAILURE, "pkt-filter-size %s invalid -" " must be: 64K or 128K or 256K\n", optarg); } if (!strcmp(lgopts[opt_idx].name, "pkt-filter-drop-queue")) { n = atoi(optarg); if (n >= 0) fdir_conf.drop_queue = (uint8_t) n; else rte_exit(EXIT_FAILURE, "drop queue %d invalid - must" "be >= 0 \n", n); } if (!strcmp(lgopts[opt_idx].name, "crc-strip")) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum")) rx_mode.hw_ip_checksum = 1; if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan")) { rx_mode.hw_vlan_filter = 0; rx_mode.hw_vlan_strip = 0; rx_mode.hw_vlan_extend = 0; } if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan-filter")) rx_mode.hw_vlan_filter = 0; if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan-strip")) rx_mode.hw_vlan_strip = 0; if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan-extend")) rx_mode.hw_vlan_extend = 0; if (!strcmp(lgopts[opt_idx].name, "enable-drop-en")) rx_drop_en = 1; if (!strcmp(lgopts[opt_idx].name, "disable-rss")) rss_hf = 0; if (!strcmp(lgopts[opt_idx].name, "port-topology")) { if (!strcmp(optarg, "paired")) port_topology = PORT_TOPOLOGY_PAIRED; else if (!strcmp(optarg, "chained")) port_topology = PORT_TOPOLOGY_CHAINED; else if (!strcmp(optarg, "loop")) port_topology = PORT_TOPOLOGY_LOOP; else rte_exit(EXIT_FAILURE, "port-topology %s invalid -" " must be: paired or chained \n", optarg); } if (!strcmp(lgopts[opt_idx].name, "forward-mode")) set_pkt_forwarding_mode(optarg); if (!strcmp(lgopts[opt_idx].name, "rss-ip")) rss_hf = ETH_RSS_IP; if (!strcmp(lgopts[opt_idx].name, "rss-udp")) rss_hf = ETH_RSS_UDP; if (!strcmp(lgopts[opt_idx].name, "rxq")) { n = atoi(optarg); if (n >= 1 && n <= (int) MAX_QUEUE_ID) nb_rxq = (queueid_t) n; else rte_exit(EXIT_FAILURE, "rxq %d invalid - must be" " >= 1 && <= %d\n", n, (int) MAX_QUEUE_ID); } if (!strcmp(lgopts[opt_idx].name, "txq")) { n = atoi(optarg); if (n >= 1 && n <= (int) MAX_QUEUE_ID) nb_txq = (queueid_t) n; else rte_exit(EXIT_FAILURE, "txq %d invalid - must be" " >= 1 && <= %d\n", n, (int) MAX_QUEUE_ID); } if (!strcmp(lgopts[opt_idx].name, "burst")) { n = atoi(optarg); if ((n >= 1) && (n <= MAX_PKT_BURST)) nb_pkt_per_burst = (uint16_t) n; else rte_exit(EXIT_FAILURE, "burst must >= 1 and <= %d]", MAX_PKT_BURST); } if (!strcmp(lgopts[opt_idx].name, "mbcache")) { n = atoi(optarg); if ((n >= 0) && (n <= RTE_MEMPOOL_CACHE_MAX_SIZE)) mb_mempool_cache = (uint16_t) n; else rte_exit(EXIT_FAILURE, "mbcache must be >= 0 and <= %d\n", RTE_MEMPOOL_CACHE_MAX_SIZE); } if (!strcmp(lgopts[opt_idx].name, "txfreet")) { n = atoi(optarg); if (n >= 0) tx_free_thresh = (int16_t)n; else rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "txrst")) { n = atoi(optarg); if (n >= 0) tx_rs_thresh = (int16_t)n; else rte_exit(EXIT_FAILURE, "txrst must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "txqflags")) { char *end = NULL; n = strtoul(optarg, &end, 16); if (n >= 0) txq_flags = (int32_t)n; else rte_exit(EXIT_FAILURE, "txqflags must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "rxd")) { n = atoi(optarg); if (n > 0) { if (rx_free_thresh >= n) rte_exit(EXIT_FAILURE, "rxd must be > " "rx_free_thresh(%d)\n", (int)rx_free_thresh); else nb_rxd = (uint16_t) n; } else rte_exit(EXIT_FAILURE, "rxd(%d) invalid - must be > 0\n", n); } if (!strcmp(lgopts[opt_idx].name, "txd")) { n = atoi(optarg); if (n > 0) nb_txd = (uint16_t) n; else rte_exit(EXIT_FAILURE, "txd must be in > 0\n"); } if (!strcmp(lgopts[opt_idx].name, "txpt")) { n = atoi(optarg); if (n >= 0) tx_pthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "txpt must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "txht")) { n = atoi(optarg); if (n >= 0) tx_hthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "txht must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "txwt")) { n = atoi(optarg); if (n >= 0) tx_wthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "txwt must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "rxpt")) { n = atoi(optarg); if (n >= 0) rx_pthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "rxht")) { n = atoi(optarg); if (n >= 0) rx_hthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "rxht must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "rxwt")) { n = atoi(optarg); if (n >= 0) rx_wthresh = (int8_t)n; else rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "rxfreet")) { n = atoi(optarg); if (n >= 0) rx_free_thresh = (int16_t)n; else rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n"); } if (!strcmp(lgopts[opt_idx].name, "tx-queue-stats-mapping")) { if (parse_queue_stats_mapping_config(optarg, TX)) { rte_exit(EXIT_FAILURE, "invalid TX queue statistics mapping config entered\n"); } } if (!strcmp(lgopts[opt_idx].name, "rx-queue-stats-mapping")) { if (parse_queue_stats_mapping_config(optarg, RX)) { rte_exit(EXIT_FAILURE, "invalid RX queue statistics mapping config entered\n"); } } if (!strcmp(lgopts[opt_idx].name, "txpkts")) { unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT]; unsigned int nb_segs; nb_segs = parse_item_list(optarg, "txpkt segments", RTE_MAX_SEGS_PER_PKT, seg_lengths, 0); if (nb_segs > 0) set_tx_pkt_segments(seg_lengths, nb_segs); else rte_exit(EXIT_FAILURE, "bad txpkts\n"); } if (!strcmp(lgopts[opt_idx].name, "no-flush-rx")) no_flush_rx = 1; if (!strcmp(lgopts[opt_idx].name, "disable-link-check")) no_link_check = 1; break; case 'h': usage(argv[0]); rte_exit(EXIT_SUCCESS, "Displayed help\n"); break; default: usage(argv[0]); rte_exit(EXIT_FAILURE, "Command line is incomplete or incorrect\n"); break; } } } ================================================ FILE: app/test-pmd/rxonly.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" static inline void print_ether_addr(const char *what, struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", what, buf); } /* * Received a burst of packets. */ static void pkt_burst_receive(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *mb; struct ether_hdr *eth_hdr; uint16_t eth_type; uint64_t ol_flags; uint16_t nb_rx; uint16_t i, packet_type; #ifdef RTE_NEXT_ABI uint16_t is_encapsulation; #else uint64_t is_encapsulation; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif /* * Receive a burst of packets. */ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst, nb_pkt_per_burst); if (unlikely(nb_rx == 0)) return; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; #endif fs->rx_packets += nb_rx; /* * Dump each received packet if verbose_level > 0. */ if (verbose_level > 0) printf("port %u/queue %u: received %u packets\n", (unsigned) fs->rx_port, (unsigned) fs->rx_queue, (unsigned) nb_rx); for (i = 0; i < nb_rx; i++) { mb = pkts_burst[i]; if (verbose_level == 0) { rte_pktmbuf_free(mb); continue; } eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *); eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type); ol_flags = mb->ol_flags; packet_type = mb->packet_type; #ifdef RTE_NEXT_ABI is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type); #else is_encapsulation = ol_flags & (PKT_RX_TUNNEL_IPV4_HDR | PKT_RX_TUNNEL_IPV6_HDR); #endif print_ether_addr(" src=", ð_hdr->s_addr); print_ether_addr(" - dst=", ð_hdr->d_addr); printf(" - type=0x%04x - length=%u - nb_segs=%d", eth_type, (unsigned) mb->pkt_len, (int)mb->nb_segs); if (ol_flags & PKT_RX_RSS_HASH) { printf(" - RSS hash=0x%x", (unsigned) mb->hash.rss); printf(" - RSS queue=0x%x",(unsigned) fs->rx_queue); } else if (ol_flags & PKT_RX_FDIR) { printf(" - FDIR matched "); if (ol_flags & PKT_RX_FDIR_ID) printf("ID=0x%x", mb->hash.fdir.hi); else if (ol_flags & PKT_RX_FDIR_FLX) printf("flex bytes=0x%08x %08x", mb->hash.fdir.hi, mb->hash.fdir.lo); else printf("hash=0x%x ID=0x%x ", mb->hash.fdir.hash, mb->hash.fdir.id); } if (ol_flags & PKT_RX_VLAN_PKT) printf(" - VLAN tci=0x%x", mb->vlan_tci); if (ol_flags & PKT_RX_QINQ_PKT) printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x", mb->vlan_tci, mb->vlan_tci_outer); #ifdef RTE_NEXT_ABI if (mb->packet_type) { uint32_t ptype; /* (outer) L2 packet type */ ptype = mb->packet_type & RTE_PTYPE_L2_MASK; switch (ptype) { case RTE_PTYPE_L2_ETHER: printf(" - (outer) L2 type: ETHER"); break; case RTE_PTYPE_L2_ETHER_TIMESYNC: printf(" - (outer) L2 type: ETHER_Timesync"); break; case RTE_PTYPE_L2_ETHER_ARP: printf(" - (outer) L2 type: ETHER_ARP"); break; case RTE_PTYPE_L2_ETHER_LLDP: printf(" - (outer) L2 type: ETHER_LLDP"); break; default: printf(" - (outer) L2 type: Unknown"); break; } /* (outer) L3 packet type */ ptype = mb->packet_type & RTE_PTYPE_L3_MASK; switch (ptype) { case RTE_PTYPE_L3_IPV4: printf(" - (outer) L3 type: IPV4"); break; case RTE_PTYPE_L3_IPV4_EXT: printf(" - (outer) L3 type: IPV4_EXT"); break; case RTE_PTYPE_L3_IPV6: printf(" - (outer) L3 type: IPV6"); break; case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN: printf(" - (outer) L3 type: IPV4_EXT_UNKNOWN"); break; case RTE_PTYPE_L3_IPV6_EXT: printf(" - (outer) L3 type: IPV6_EXT"); break; case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN: printf(" - (outer) L3 type: IPV6_EXT_UNKNOWN"); break; default: printf(" - (outer) L3 type: Unknown"); break; } /* (outer) L4 packet type */ ptype = mb->packet_type & RTE_PTYPE_L4_MASK; switch (ptype) { case RTE_PTYPE_L4_TCP: printf(" - (outer) L4 type: TCP"); break; case RTE_PTYPE_L4_UDP: printf(" - (outer) L4 type: UDP"); break; case RTE_PTYPE_L4_FRAG: printf(" - (outer) L4 type: L4_FRAG"); break; case RTE_PTYPE_L4_SCTP: printf(" - (outer) L4 type: SCTP"); break; case RTE_PTYPE_L4_ICMP: printf(" - (outer) L4 type: ICMP"); break; case RTE_PTYPE_L4_NONFRAG: printf(" - (outer) L4 type: L4_NONFRAG"); break; default: printf(" - (outer) L4 type: Unknown"); break; } /* packet tunnel type */ ptype = mb->packet_type & RTE_PTYPE_TUNNEL_MASK; switch (ptype) { case RTE_PTYPE_TUNNEL_IP: printf(" - Tunnel type: IP"); break; case RTE_PTYPE_TUNNEL_GRE: printf(" - Tunnel type: GRE"); break; case RTE_PTYPE_TUNNEL_VXLAN: printf(" - Tunnel type: VXLAN"); break; case RTE_PTYPE_TUNNEL_NVGRE: printf(" - Tunnel type: NVGRE"); break; case RTE_PTYPE_TUNNEL_GENEVE: printf(" - Tunnel type: GENEVE"); break; case RTE_PTYPE_TUNNEL_GRENAT: printf(" - Tunnel type: GRENAT"); break; default: printf(" - Tunnel type: Unknown"); break; } /* inner L2 packet type */ ptype = mb->packet_type & RTE_PTYPE_INNER_L2_MASK; switch (ptype) { case RTE_PTYPE_INNER_L2_ETHER: printf(" - Inner L2 type: ETHER"); break; case RTE_PTYPE_INNER_L2_ETHER_VLAN: printf(" - Inner L2 type: ETHER_VLAN"); break; default: printf(" - Inner L2 type: Unknown"); break; } /* inner L3 packet type */ ptype = mb->packet_type & RTE_PTYPE_INNER_L3_MASK; switch (ptype) { case RTE_PTYPE_INNER_L3_IPV4: printf(" - Inner L3 type: IPV4"); break; case RTE_PTYPE_INNER_L3_IPV4_EXT: printf(" - Inner L3 type: IPV4_EXT"); break; case RTE_PTYPE_INNER_L3_IPV6: printf(" - Inner L3 type: IPV6"); break; case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN: printf(" - Inner L3 type: IPV4_EXT_UNKNOWN"); break; case RTE_PTYPE_INNER_L3_IPV6_EXT: printf(" - Inner L3 type: IPV6_EXT"); break; case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN: printf(" - Inner L3 type: IPV6_EXT_UNKNOWN"); break; default: printf(" - Inner L3 type: Unknown"); break; } /* inner L4 packet type */ ptype = mb->packet_type & RTE_PTYPE_INNER_L4_MASK; switch (ptype) { case RTE_PTYPE_INNER_L4_TCP: printf(" - Inner L4 type: TCP"); break; case RTE_PTYPE_INNER_L4_UDP: printf(" - Inner L4 type: UDP"); break; case RTE_PTYPE_INNER_L4_FRAG: printf(" - Inner L4 type: L4_FRAG"); break; case RTE_PTYPE_INNER_L4_SCTP: printf(" - Inner L4 type: SCTP"); break; case RTE_PTYPE_INNER_L4_ICMP: printf(" - Inner L4 type: ICMP"); break; case RTE_PTYPE_INNER_L4_NONFRAG: printf(" - Inner L4 type: L4_NONFRAG"); break; default: printf(" - Inner L4 type: Unknown"); break; } printf("\n"); } else printf("Unknown packet type\n"); #endif /* RTE_NEXT_ABI */ if (is_encapsulation) { struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; struct udp_hdr *udp_hdr; uint8_t l2_len; uint8_t l3_len; uint8_t l4_len; uint8_t l4_proto; struct vxlan_hdr *vxlan_hdr; l2_len = sizeof(struct ether_hdr); /* Do not support ipv4 option field */ #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(packet_type)) { #else if (ol_flags & PKT_RX_TUNNEL_IPV4_HDR) { #endif l3_len = sizeof(struct ipv4_hdr); ipv4_hdr = rte_pktmbuf_mtod_offset(mb, struct ipv4_hdr *, l2_len); l4_proto = ipv4_hdr->next_proto_id; } else { l3_len = sizeof(struct ipv6_hdr); ipv6_hdr = rte_pktmbuf_mtod_offset(mb, struct ipv6_hdr *, l2_len); l4_proto = ipv6_hdr->proto; } if (l4_proto == IPPROTO_UDP) { udp_hdr = rte_pktmbuf_mtod_offset(mb, struct udp_hdr *, l2_len + l3_len); l4_len = sizeof(struct udp_hdr); vxlan_hdr = rte_pktmbuf_mtod_offset(mb, struct vxlan_hdr *, l2_len + l3_len + l4_len); printf(" - VXLAN packet: packet type =%d, " "Destination UDP port =%d, VNI = %d", packet_type, RTE_BE_TO_CPU_16(udp_hdr->dst_port), rte_be_to_cpu_32(vxlan_hdr->vx_vni) >> 8); } } printf(" - Receive queue=0x%x", (unsigned) fs->rx_queue); printf("\n"); if (ol_flags != 0) { unsigned rxf; const char *name; for (rxf = 0; rxf < sizeof(mb->ol_flags) * 8; rxf++) { if ((ol_flags & (1ULL << rxf)) == 0) continue; name = rte_get_rx_ol_flag_name(1ULL << rxf); if (name == NULL) continue; printf(" %s\n", name); } } rte_pktmbuf_free(mb); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } struct fwd_engine rx_only_engine = { .fwd_mode_name = "rxonly", .port_fwd_begin = NULL, .port_fwd_end = NULL, .packet_fwd = pkt_burst_receive, }; ================================================ FILE: app/test-pmd/testpmd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_PMD_XENVIRT #include #endif #include "testpmd.h" #include "mempool_osdep.h" uint16_t verbose_level = 0; /**< Silent by default. */ /* use master core for command line ? */ uint8_t interactive = 0; uint8_t auto_start = 0; /* * NUMA support configuration. * When set, the NUMA support attempts to dispatch the allocation of the * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the * probed ports among the CPU sockets 0 and 1. * Otherwise, all memory is allocated from CPU socket 0. */ uint8_t numa_support = 0; /**< No numa support by default */ /* * In UMA mode,all memory is allocated from socket 0 if --socket-num is * not configured. */ uint8_t socket_num = UMA_NO_CONFIG; /* * Use ANONYMOUS mapped memory (might be not physically continuous) for mbufs. */ uint8_t mp_anon = 0; /* * Record the Ethernet address of peer target ports to which packets are * forwarded. * Must be instanciated with the ethernet addresses of peer traffic generator * ports. */ struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS]; portid_t nb_peer_eth_addrs = 0; /* * Probed Target Environment. */ struct rte_port *ports; /**< For all probed ethernet ports. */ portid_t nb_ports; /**< Number of probed ethernet ports. */ struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */ lcoreid_t nb_lcores; /**< Number of probed logical cores. */ /* * Test Forwarding Configuration. * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores * nb_fwd_ports <= nb_cfg_ports <= nb_ports */ lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */ lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */ portid_t nb_cfg_ports; /**< Number of configured ports. */ portid_t nb_fwd_ports; /**< Number of forwarding ports. */ unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */ portid_t fwd_ports_ids[RTE_MAX_ETHPORTS]; /**< Port ids configuration. */ struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */ streamid_t nb_fwd_streams; /**< Is equal to (nb_ports * nb_rxq). */ /* * Forwarding engines. */ struct fwd_engine * fwd_engines[] = { &io_fwd_engine, &mac_fwd_engine, &mac_retry_fwd_engine, &mac_swap_engine, &flow_gen_engine, &rx_only_engine, &tx_only_engine, &csum_fwd_engine, &icmp_echo_engine, #ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif NULL, }; struct fwd_config cur_fwd_config; struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */ uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */ uint32_t param_total_num_mbufs = 0; /**< number of mbufs in all pools - if * specified on command-line. */ /* * Configuration of packet segments used by the "txonly" processing engine. */ uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */ uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = { TXONLY_DEF_PACKET_LEN, }; uint8_t tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */ uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */ uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */ /* current configuration is in DCB or not,0 means it is not in DCB mode */ uint8_t dcb_config = 0; /* Whether the dcb is in testing status */ uint8_t dcb_test = 0; /* DCB on and VT on mapping is default */ enum dcb_queue_mapping_mode dcb_q_mapping = DCB_VT_Q_MAPPING; /* * Configurable number of RX/TX queues. */ queueid_t nb_rxq = 1; /**< Number of RX queues per port. */ queueid_t nb_txq = 1; /**< Number of TX queues per port. */ /* * Configurable number of RX/TX ring descriptors. */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */ uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */ #define RTE_PMD_PARAM_UNSET -1 /* * Configurable values of RX and TX ring threshold registers. */ int8_t rx_pthresh = RTE_PMD_PARAM_UNSET; int8_t rx_hthresh = RTE_PMD_PARAM_UNSET; int8_t rx_wthresh = RTE_PMD_PARAM_UNSET; int8_t tx_pthresh = RTE_PMD_PARAM_UNSET; int8_t tx_hthresh = RTE_PMD_PARAM_UNSET; int8_t tx_wthresh = RTE_PMD_PARAM_UNSET; /* * Configurable value of RX free threshold. */ int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET; /* * Configurable value of RX drop enable. */ int8_t rx_drop_en = RTE_PMD_PARAM_UNSET; /* * Configurable value of TX free threshold. */ int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET; /* * Configurable value of TX RS bit threshold. */ int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET; /* * Configurable value of TX queue flags. */ int32_t txq_flags = RTE_PMD_PARAM_UNSET; /* * Receive Side Scaling (RSS) configuration. */ uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */ /* * Port topology configuration */ uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */ /* * Avoids to flush all the RX streams before starts forwarding. */ uint8_t no_flush_rx = 0; /* flush by default */ /* * Avoids to check link status when starting/stopping a port. */ uint8_t no_link_check = 0; /* check by default */ /* * NIC bypass mode configuration options. */ #ifdef RTE_NIC_BYPASS /* The NIC bypass watchdog timeout. */ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF; #endif /* * Ethernet device configuration. */ struct rte_eth_rxmode rx_mode = { .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */ .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled. */ .hw_ip_checksum = 0, /**< IP checksum offload disabled. */ .hw_vlan_filter = 1, /**< VLAN filtering enabled. */ .hw_vlan_strip = 1, /**< VLAN strip enabled. */ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */ .hw_strip_crc = 0, /**< CRC stripping by hardware disabled. */ }; struct rte_fdir_conf fdir_conf = { .mode = RTE_FDIR_MODE_NONE, .pballoc = RTE_FDIR_PBALLOC_64K, .status = RTE_FDIR_REPORT_STATUS, .mask = { .vlan_tci_mask = 0x0, .ipv4_mask = { .src_ip = 0xFFFFFFFF, .dst_ip = 0xFFFFFFFF, }, .ipv6_mask = { .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, }, .src_port_mask = 0xFFFF, .dst_port_mask = 0xFFFF, }, .drop_queue = 127, }; volatile int test_done = 1; /* stop packet forwarding when set to 1. */ struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS]; struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS]; struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array; struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array; uint16_t nb_tx_queue_stats_mappings = 0; uint16_t nb_rx_queue_stats_mappings = 0; /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); /* * Check if all the ports are started. * If yes, return positive value. If not, return zero. */ static int all_ports_started(void); /* * Find next enabled port */ portid_t find_next_port(portid_t p, struct rte_port *ports, int size) { if (ports == NULL) rte_exit(-EINVAL, "failed to find a next port id\n"); while ((p < size) && (ports[p].enabled == 0)) p++; return p; } /* * Setup default configuration. */ static void set_default_fwd_lcores_config(void) { unsigned int i; unsigned int nb_lc; nb_lc = 0; for (i = 0; i < RTE_MAX_LCORE; i++) { if (! rte_lcore_is_enabled(i)) continue; if (i == rte_get_master_lcore()) continue; fwd_lcores_cpuids[nb_lc++] = i; } nb_lcores = (lcoreid_t) nb_lc; nb_cfg_lcores = nb_lcores; nb_fwd_lcores = 1; } static void set_def_peer_eth_addrs(void) { portid_t i; for (i = 0; i < RTE_MAX_ETHPORTS; i++) { peer_eth_addrs[i].addr_bytes[0] = ETHER_LOCAL_ADMIN_ADDR; peer_eth_addrs[i].addr_bytes[5] = i; } } static void set_default_fwd_ports_config(void) { portid_t pt_id; for (pt_id = 0; pt_id < nb_ports; pt_id++) fwd_ports_ids[pt_id] = pt_id; nb_cfg_ports = nb_ports; nb_fwd_ports = nb_ports; } void set_def_fwd_config(void) { set_default_fwd_lcores_config(); set_def_peer_eth_addrs(); set_default_fwd_ports_config(); } /* * Configuration initialisation done once at init time. */ static void mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf, unsigned int socket_id) { char pool_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *rte_mp; uint32_t mb_size; mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size; mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name)); #ifdef RTE_LIBRTE_PMD_XENVIRT rte_mp = rte_mempool_gntalloc_create(pool_name, nb_mbuf, mb_size, (unsigned) mb_mempool_cache, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, socket_id, 0); #else if (mp_anon != 0) rte_mp = mempool_anon_create(pool_name, nb_mbuf, mb_size, (unsigned) mb_mempool_cache, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, socket_id, 0); else /* wrapper to rte_mempool_create() */ rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf, mb_mempool_cache, 0, mbuf_seg_size, socket_id); #endif if (rte_mp == NULL) { rte_exit(EXIT_FAILURE, "Creation of mbuf pool for socket %u " "failed\n", socket_id); } else if (verbose_level > 0) { rte_mempool_dump(stdout, rte_mp); } } /* * Check given socket id is valid or not with NUMA mode, * if valid, return 0, else return -1 */ static int check_socket_id(const unsigned int socket_id) { static int warning_once = 0; if (socket_id >= MAX_SOCKET) { if (!warning_once && numa_support) printf("Warning: NUMA should be configured manually by" " using --port-numa-config and" " --ring-numa-config parameters along with" " --numa.\n"); warning_once = 1; return -1; } return 0; } static void init_config(void) { portid_t pid; struct rte_port *port; struct rte_mempool *mbp; unsigned int nb_mbuf_per_pool; lcoreid_t lc_id; uint8_t port_per_socket[MAX_SOCKET]; memset(port_per_socket,0,MAX_SOCKET); /* Configuration of logical cores. */ fwd_lcores = rte_zmalloc("testpmd: fwd_lcores", sizeof(struct fwd_lcore *) * nb_lcores, RTE_CACHE_LINE_SIZE); if (fwd_lcores == NULL) { rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) " "failed\n", nb_lcores); } for (lc_id = 0; lc_id < nb_lcores; lc_id++) { fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore", sizeof(struct fwd_lcore), RTE_CACHE_LINE_SIZE); if (fwd_lcores[lc_id] == NULL) { rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) " "failed\n"); } fwd_lcores[lc_id]->cpuid_idx = lc_id; } /* * Create pools of mbuf. * If NUMA support is disabled, create a single pool of mbuf in * socket 0 memory by default. * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1. * * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and * nb_txd can be configured at run time. */ if (param_total_num_mbufs) nb_mbuf_per_pool = param_total_num_mbufs; else { nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + (nb_lcores * mb_mempool_cache) + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; if (!numa_support) nb_mbuf_per_pool = (nb_mbuf_per_pool * RTE_MAX_ETHPORTS); } if (!numa_support) { if (socket_num == UMA_NO_CONFIG) mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0); else mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, socket_num); } FOREACH_PORT(pid, ports) { port = &ports[pid]; rte_eth_dev_info_get(pid, &port->dev_info); if (numa_support) { if (port_numa[pid] != NUMA_NO_CONFIG) port_per_socket[port_numa[pid]]++; else { uint32_t socket_id = rte_eth_dev_socket_id(pid); /* if socket_id is invalid, set to 0 */ if (check_socket_id(socket_id) < 0) socket_id = 0; port_per_socket[socket_id]++; } } /* set flag to initialize port/queue */ port->need_reconfig = 1; port->need_reconfig_queues = 1; } if (numa_support) { uint8_t i; unsigned int nb_mbuf; if (param_total_num_mbufs) nb_mbuf_per_pool = nb_mbuf_per_pool/nb_ports; for (i = 0; i < MAX_SOCKET; i++) { nb_mbuf = (nb_mbuf_per_pool * RTE_MAX_ETHPORTS); if (nb_mbuf) mbuf_pool_create(mbuf_data_size, nb_mbuf,i); } } init_port_config(); /* * Records which Mbuf pool to use by each logical core, if needed. */ for (lc_id = 0; lc_id < nb_lcores; lc_id++) { mbp = mbuf_pool_find( rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id])); if (mbp == NULL) mbp = mbuf_pool_find(0); fwd_lcores[lc_id]->mbp = mbp; } /* Configuration of packet forwarding streams. */ if (init_fwd_streams() < 0) rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n"); } void reconfig(portid_t new_port_id, unsigned socket_id) { struct rte_port *port; /* Reconfiguration of Ethernet ports. */ port = &ports[new_port_id]; rte_eth_dev_info_get(new_port_id, &port->dev_info); /* set flag to initialize port/queue */ port->need_reconfig = 1; port->need_reconfig_queues = 1; port->socket_id = socket_id; init_port_config(); } int init_fwd_streams(void) { portid_t pid; struct rte_port *port; streamid_t sm_id, nb_fwd_streams_new; /* set socket id according to numa or not */ FOREACH_PORT(pid, ports) { port = &ports[pid]; if (nb_rxq > port->dev_info.max_rx_queues) { printf("Fail: nb_rxq(%d) is greater than " "max_rx_queues(%d)\n", nb_rxq, port->dev_info.max_rx_queues); return -1; } if (nb_txq > port->dev_info.max_tx_queues) { printf("Fail: nb_txq(%d) is greater than " "max_tx_queues(%d)\n", nb_txq, port->dev_info.max_tx_queues); return -1; } if (numa_support) { if (port_numa[pid] != NUMA_NO_CONFIG) port->socket_id = port_numa[pid]; else { port->socket_id = rte_eth_dev_socket_id(pid); /* if socket_id is invalid, set to 0 */ if (check_socket_id(port->socket_id) < 0) port->socket_id = 0; } } else { if (socket_num == UMA_NO_CONFIG) port->socket_id = 0; else port->socket_id = socket_num; } } nb_fwd_streams_new = (streamid_t)(nb_ports * nb_rxq); if (nb_fwd_streams_new == nb_fwd_streams) return 0; /* clear the old */ if (fwd_streams != NULL) { for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { if (fwd_streams[sm_id] == NULL) continue; rte_free(fwd_streams[sm_id]); fwd_streams[sm_id] = NULL; } rte_free(fwd_streams); fwd_streams = NULL; } /* init new */ nb_fwd_streams = nb_fwd_streams_new; fwd_streams = rte_zmalloc("testpmd: fwd_streams", sizeof(struct fwd_stream *) * nb_fwd_streams, RTE_CACHE_LINE_SIZE); if (fwd_streams == NULL) rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) " "failed\n", nb_fwd_streams); for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream", sizeof(struct fwd_stream), RTE_CACHE_LINE_SIZE); if (fwd_streams[sm_id] == NULL) rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)" " failed\n"); } return 0; } #ifdef RTE_TEST_PMD_RECORD_BURST_STATS static void pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs) { unsigned int total_burst; unsigned int nb_burst; unsigned int burst_stats[3]; uint16_t pktnb_stats[3]; uint16_t nb_pkt; int burst_percent[3]; /* * First compute the total number of packet bursts and the * two highest numbers of bursts of the same number of packets. */ total_burst = 0; burst_stats[0] = burst_stats[1] = burst_stats[2] = 0; pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0; for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) { nb_burst = pbs->pkt_burst_spread[nb_pkt]; if (nb_burst == 0) continue; total_burst += nb_burst; if (nb_burst > burst_stats[0]) { burst_stats[1] = burst_stats[0]; pktnb_stats[1] = pktnb_stats[0]; burst_stats[0] = nb_burst; pktnb_stats[0] = nb_pkt; } } if (total_burst == 0) return; burst_percent[0] = (burst_stats[0] * 100) / total_burst; printf(" %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst, burst_percent[0], (int) pktnb_stats[0]); if (burst_stats[0] == total_burst) { printf("]\n"); return; } if (burst_stats[0] + burst_stats[1] == total_burst) { printf(" + %d%% of %d pkts]\n", 100 - burst_percent[0], pktnb_stats[1]); return; } burst_percent[1] = (burst_stats[1] * 100) / total_burst; burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]); if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) { printf(" + %d%% of others]\n", 100 - burst_percent[0]); return; } printf(" + %d%% of %d pkts + %d%% of others]\n", burst_percent[1], (int) pktnb_stats[1], burst_percent[2]); } #endif /* RTE_TEST_PMD_RECORD_BURST_STATS */ static void fwd_port_stats_display(portid_t port_id, struct rte_eth_stats *stats) { struct rte_port *port; uint8_t i; static const char *fwd_stats_border = "----------------------"; port = &ports[port_id]; printf("\n %s Forward statistics for port %-2d %s\n", fwd_stats_border, port_id, fwd_stats_border); if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " "%-"PRIu64"\n", stats->ipackets, stats->imissed, (uint64_t) (stats->ipackets + stats->imissed)); if (cur_fwd_eng == &csum_fwd_engine) printf(" Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n", port->rx_bad_ip_csum, port->rx_bad_l4_csum); if (((stats->ierrors - stats->imissed) + stats->rx_nombuf) > 0) { printf(" RX-badcrc: %-14"PRIu64" RX-badlen: %-14"PRIu64 "RX-error: %-"PRIu64"\n", stats->ibadcrc, stats->ibadlen, stats->ierrors); printf(" RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf); } printf(" TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " "%-"PRIu64"\n", stats->opackets, port->tx_dropped, (uint64_t) (stats->opackets + port->tx_dropped)); } else { printf(" RX-packets: %14"PRIu64" RX-dropped:%14"PRIu64" RX-total:" "%14"PRIu64"\n", stats->ipackets, stats->imissed, (uint64_t) (stats->ipackets + stats->imissed)); if (cur_fwd_eng == &csum_fwd_engine) printf(" Bad-ipcsum:%14"PRIu64" Bad-l4csum:%14"PRIu64"\n", port->rx_bad_ip_csum, port->rx_bad_l4_csum); if (((stats->ierrors - stats->imissed) + stats->rx_nombuf) > 0) { printf(" RX-badcrc: %14"PRIu64" RX-badlen: %14"PRIu64 " RX-error:%"PRIu64"\n", stats->ibadcrc, stats->ibadlen, stats->ierrors); printf(" RX-nombufs: %14"PRIu64"\n", stats->rx_nombuf); } printf(" TX-packets: %14"PRIu64" TX-dropped:%14"PRIu64" TX-total:" "%14"PRIu64"\n", stats->opackets, port->tx_dropped, (uint64_t) (stats->opackets + port->tx_dropped)); } /* Display statistics of XON/XOFF pause frames, if any. */ if ((stats->tx_pause_xon | stats->rx_pause_xon | stats->tx_pause_xoff | stats->rx_pause_xoff) > 0) { printf(" RX-XOFF: %-14"PRIu64" RX-XON: %-14"PRIu64"\n", stats->rx_pause_xoff, stats->rx_pause_xon); printf(" TX-XOFF: %-14"PRIu64" TX-XON: %-14"PRIu64"\n", stats->tx_pause_xoff, stats->tx_pause_xon); } #ifdef RTE_TEST_PMD_RECORD_BURST_STATS if (port->rx_stream) pkt_burst_stats_display("RX", &port->rx_stream->rx_burst_stats); if (port->tx_stream) pkt_burst_stats_display("TX", &port->tx_stream->tx_burst_stats); #endif /* stats fdir */ if (fdir_conf.mode != RTE_FDIR_MODE_NONE) printf(" Fdirmiss:%14"PRIu64" Fdirmatch:%14"PRIu64"\n", stats->fdirmiss, stats->fdirmatch); if (port->rx_queue_stats_mapping_enabled) { printf("\n"); for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d RX-packets:%14"PRIu64 " RX-errors:%14"PRIu64 " RX-bytes:%14"PRIu64"\n", i, stats->q_ipackets[i], stats->q_errors[i], stats->q_ibytes[i]); } printf("\n"); } if (port->tx_queue_stats_mapping_enabled) { for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { printf(" Stats reg %2d TX-packets:%14"PRIu64 " TX-bytes:%14"PRIu64"\n", i, stats->q_opackets[i], stats->q_obytes[i]); } } printf(" %s--------------------------------%s\n", fwd_stats_border, fwd_stats_border); } static void fwd_stream_stats_display(streamid_t stream_id) { struct fwd_stream *fs; static const char *fwd_top_stats_border = "-------"; fs = fwd_streams[stream_id]; if ((fs->rx_packets == 0) && (fs->tx_packets == 0) && (fs->fwd_dropped == 0)) return; printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> " "TX Port=%2d/Queue=%2d %s\n", fwd_top_stats_border, fs->rx_port, fs->rx_queue, fs->tx_port, fs->tx_queue, fwd_top_stats_border); printf(" RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u", fs->rx_packets, fs->tx_packets, fs->fwd_dropped); /* if checksum mode */ if (cur_fwd_eng == &csum_fwd_engine) { printf(" RX- bad IP checksum: %-14u Rx- bad L4 checksum: " "%-14u\n", fs->rx_bad_ip_csum, fs->rx_bad_l4_csum); } #ifdef RTE_TEST_PMD_RECORD_BURST_STATS pkt_burst_stats_display("RX", &fs->rx_burst_stats); pkt_burst_stats_display("TX", &fs->tx_burst_stats); #endif } static void flush_fwd_rx_queues(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; portid_t rxp; portid_t port_id; queueid_t rxq; uint16_t nb_rx; uint16_t i; uint8_t j; for (j = 0; j < 2; j++) { for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) { for (rxq = 0; rxq < nb_rxq; rxq++) { port_id = fwd_ports_ids[rxp]; do { nb_rx = rte_eth_rx_burst(port_id, rxq, pkts_burst, MAX_PKT_BURST); for (i = 0; i < nb_rx; i++) rte_pktmbuf_free(pkts_burst[i]); } while (nb_rx > 0); } } rte_delay_ms(10); /* wait 10 milli-seconds before retrying */ } } static void run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) { struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); } while (! fc->stopped); } static int start_pkt_forward_on_core(void *fwd_arg) { run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg, cur_fwd_config.fwd_eng->packet_fwd); return 0; } /* * Run the TXONLY packet forwarding engine to send a single burst of packets. * Used to start communication flows in network loopback test configurations. */ static int run_one_txonly_burst_on_core(void *fwd_arg) { struct fwd_lcore *fwd_lc; struct fwd_lcore tmp_lcore; fwd_lc = (struct fwd_lcore *) fwd_arg; tmp_lcore = *fwd_lc; tmp_lcore.stopped = 1; run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd); return 0; } /* * Launch packet forwarding: * - Setup per-port forwarding context. * - launch logical cores with their forwarding configuration. */ static void launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore) { port_fwd_begin_t port_fwd_begin; unsigned int i; unsigned int lc_id; int diag; port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin; if (port_fwd_begin != NULL) { for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) (*port_fwd_begin)(fwd_ports_ids[i]); } for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) { lc_id = fwd_lcores_cpuids[i]; if ((interactive == 0) || (lc_id != rte_lcore_id())) { fwd_lcores[i]->stopped = 0; diag = rte_eal_remote_launch(pkt_fwd_on_lcore, fwd_lcores[i], lc_id); if (diag != 0) printf("launch lcore %u failed - diag=%d\n", lc_id, diag); } } } /* * Launch packet forwarding configuration. */ void start_packet_forwarding(int with_tx_first) { port_fwd_begin_t port_fwd_begin; port_fwd_end_t port_fwd_end; struct rte_port *port; unsigned int i; portid_t pt_id; streamid_t sm_id; if (all_ports_started() == 0) { printf("Not all ports were started\n"); return; } if (test_done == 0) { printf("Packet forwarding already started\n"); return; } if(dcb_test) { for (i = 0; i < nb_fwd_ports; i++) { pt_id = fwd_ports_ids[i]; port = &ports[pt_id]; if (!port->dcb_flag) { printf("In DCB mode, all forwarding ports must " "be configured in this mode.\n"); return; } } if (nb_fwd_lcores == 1) { printf("In DCB mode,the nb forwarding cores " "should be larger than 1.\n"); return; } } test_done = 0; if(!no_flush_rx) flush_fwd_rx_queues(); fwd_config_setup(); rxtx_config_display(); for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { pt_id = fwd_ports_ids[i]; port = &ports[pt_id]; rte_eth_stats_get(pt_id, &port->stats); port->tx_dropped = 0; map_port_queue_stats_mapping_registers(pt_id, port); } for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { fwd_streams[sm_id]->rx_packets = 0; fwd_streams[sm_id]->tx_packets = 0; fwd_streams[sm_id]->fwd_dropped = 0; fwd_streams[sm_id]->rx_bad_ip_csum = 0; fwd_streams[sm_id]->rx_bad_l4_csum = 0; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS memset(&fwd_streams[sm_id]->rx_burst_stats, 0, sizeof(fwd_streams[sm_id]->rx_burst_stats)); memset(&fwd_streams[sm_id]->tx_burst_stats, 0, sizeof(fwd_streams[sm_id]->tx_burst_stats)); #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES fwd_streams[sm_id]->core_cycles = 0; #endif } if (with_tx_first) { port_fwd_begin = tx_only_engine.port_fwd_begin; if (port_fwd_begin != NULL) { for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) (*port_fwd_begin)(fwd_ports_ids[i]); } launch_packet_forwarding(run_one_txonly_burst_on_core); rte_eal_mp_wait_lcore(); port_fwd_end = tx_only_engine.port_fwd_end; if (port_fwd_end != NULL) { for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) (*port_fwd_end)(fwd_ports_ids[i]); } } launch_packet_forwarding(start_pkt_forward_on_core); } void stop_packet_forwarding(void) { struct rte_eth_stats stats; struct rte_port *port; port_fwd_end_t port_fwd_end; int i; portid_t pt_id; streamid_t sm_id; lcoreid_t lc_id; uint64_t total_recv; uint64_t total_xmit; uint64_t total_rx_dropped; uint64_t total_tx_dropped; uint64_t total_rx_nombuf; uint64_t tx_dropped; uint64_t rx_bad_ip_csum; uint64_t rx_bad_l4_csum; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t fwd_cycles; #endif static const char *acc_stats_border = "+++++++++++++++"; if (all_ports_started() == 0) { printf("Not all ports were started\n"); return; } if (test_done) { printf("Packet forwarding not started\n"); return; } printf("Telling cores to stop..."); for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) fwd_lcores[lc_id]->stopped = 1; printf("\nWaiting for lcores to finish...\n"); rte_eal_mp_wait_lcore(); port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end; if (port_fwd_end != NULL) { for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { pt_id = fwd_ports_ids[i]; (*port_fwd_end)(pt_id); } } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES fwd_cycles = 0; #endif for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { if (cur_fwd_config.nb_fwd_streams > cur_fwd_config.nb_fwd_ports) { fwd_stream_stats_display(sm_id); ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL; ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL; } else { ports[fwd_streams[sm_id]->tx_port].tx_stream = fwd_streams[sm_id]; ports[fwd_streams[sm_id]->rx_port].rx_stream = fwd_streams[sm_id]; } tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped; tx_dropped = (uint64_t) (tx_dropped + fwd_streams[sm_id]->fwd_dropped); ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped; rx_bad_ip_csum = ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum; rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum + fwd_streams[sm_id]->rx_bad_ip_csum); ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum = rx_bad_ip_csum; rx_bad_l4_csum = ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum; rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum + fwd_streams[sm_id]->rx_bad_l4_csum); ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum = rx_bad_l4_csum; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES fwd_cycles = (uint64_t) (fwd_cycles + fwd_streams[sm_id]->core_cycles); #endif } total_recv = 0; total_xmit = 0; total_rx_dropped = 0; total_tx_dropped = 0; total_rx_nombuf = 0; for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { pt_id = fwd_ports_ids[i]; port = &ports[pt_id]; rte_eth_stats_get(pt_id, &stats); stats.ipackets -= port->stats.ipackets; port->stats.ipackets = 0; stats.opackets -= port->stats.opackets; port->stats.opackets = 0; stats.ibytes -= port->stats.ibytes; port->stats.ibytes = 0; stats.obytes -= port->stats.obytes; port->stats.obytes = 0; stats.imissed -= port->stats.imissed; port->stats.imissed = 0; stats.oerrors -= port->stats.oerrors; port->stats.oerrors = 0; stats.rx_nombuf -= port->stats.rx_nombuf; port->stats.rx_nombuf = 0; stats.fdirmatch -= port->stats.fdirmatch; port->stats.rx_nombuf = 0; stats.fdirmiss -= port->stats.fdirmiss; port->stats.rx_nombuf = 0; total_recv += stats.ipackets; total_xmit += stats.opackets; total_rx_dropped += stats.imissed; total_tx_dropped += port->tx_dropped; total_rx_nombuf += stats.rx_nombuf; fwd_port_stats_display(pt_id, &stats); } printf("\n %s Accumulated forward statistics for all ports" "%s\n", acc_stats_border, acc_stats_border); printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " "%-"PRIu64"\n" " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " "%-"PRIu64"\n", total_recv, total_rx_dropped, total_recv + total_rx_dropped, total_xmit, total_tx_dropped, total_xmit + total_tx_dropped); if (total_rx_nombuf > 0) printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf); printf(" %s++++++++++++++++++++++++++++++++++++++++++++++" "%s\n", acc_stats_border, acc_stats_border); #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES if (total_recv > 0) printf("\n CPU cycles/packet=%u (total cycles=" "%"PRIu64" / total RX packets=%"PRIu64")\n", (unsigned int)(fwd_cycles / total_recv), fwd_cycles, total_recv); #endif printf("\nDone.\n"); test_done = 1; } void dev_set_link_up(portid_t pid) { if (rte_eth_dev_set_link_up((uint8_t)pid) < 0) printf("\nSet link up fail.\n"); } void dev_set_link_down(portid_t pid) { if (rte_eth_dev_set_link_down((uint8_t)pid) < 0) printf("\nSet link down fail.\n"); } static int all_ports_started(void) { portid_t pi; struct rte_port *port; FOREACH_PORT(pi, ports) { port = &ports[pi]; /* Check if there is a port which is not started */ if ((port->port_status != RTE_PORT_STARTED) && (port->slave_flag == 0)) return 0; } /* No port is not started */ return 1; } int all_ports_stopped(void) { portid_t pi; struct rte_port *port; FOREACH_PORT(pi, ports) { port = &ports[pi]; if ((port->port_status != RTE_PORT_STOPPED) && (port->slave_flag == 0)) return 0; } return 1; } int port_is_started(portid_t port_id) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return 0; if (ports[port_id].port_status != RTE_PORT_STARTED) return 0; return 1; } static int port_is_closed(portid_t port_id) { if (port_id_is_invalid(port_id, ENABLED_WARN)) return 0; if (ports[port_id].port_status != RTE_PORT_CLOSED) return 0; return 1; } int start_port(portid_t pid) { int diag, need_check_link_status = -1; portid_t pi; queueid_t qi; struct rte_port *port; struct ether_addr mac_addr; if (test_done == 0) { printf("Please stop forwarding first\n"); return -1; } if (port_id_is_invalid(pid, ENABLED_WARN)) return 0; if (init_fwd_streams() < 0) { printf("Fail from init_fwd_streams()\n"); return -1; } if(dcb_config) dcb_test = 1; FOREACH_PORT(pi, ports) { if (pid != pi && pid != (portid_t)RTE_PORT_ALL) continue; need_check_link_status = 0; port = &ports[pi]; if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { printf("Port %d is now not stopped\n", pi); continue; } if (port->need_reconfig > 0) { port->need_reconfig = 0; printf("Configuring Port %d (socket %u)\n", pi, port->socket_id); /* configure port */ diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, &(port->dev_conf)); if (diag != 0) { if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) printf("Port %d can not be set back " "to stopped\n", pi); printf("Fail to configure port %d\n", pi); /* try to reconfigure port next time */ port->need_reconfig = 1; return -1; } } if (port->need_reconfig_queues > 0) { port->need_reconfig_queues = 0; /* setup tx queues */ for (qi = 0; qi < nb_txq; qi++) { if ((numa_support) && (txring_numa[pi] != NUMA_NO_CONFIG)) diag = rte_eth_tx_queue_setup(pi, qi, nb_txd,txring_numa[pi], &(port->tx_conf)); else diag = rte_eth_tx_queue_setup(pi, qi, nb_txd,port->socket_id, &(port->tx_conf)); if (diag == 0) continue; /* Fail to setup tx queue, return */ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) printf("Port %d can not be set back " "to stopped\n", pi); printf("Fail to configure port %d tx queues\n", pi); /* try to reconfigure queues next time */ port->need_reconfig_queues = 1; return -1; } /* setup rx queues */ for (qi = 0; qi < nb_rxq; qi++) { if ((numa_support) && (rxring_numa[pi] != NUMA_NO_CONFIG)) { struct rte_mempool * mp = mbuf_pool_find(rxring_numa[pi]); if (mp == NULL) { printf("Failed to setup RX queue:" "No mempool allocation" "on the socket %d\n", rxring_numa[pi]); return -1; } diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd,rxring_numa[pi], &(port->rx_conf),mp); } else diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd,port->socket_id, &(port->rx_conf), mbuf_pool_find(port->socket_id)); if (diag == 0) continue; /* Fail to setup rx queue, return */ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) printf("Port %d can not be set back " "to stopped\n", pi); printf("Fail to configure port %d rx queues\n", pi); /* try to reconfigure queues next time */ port->need_reconfig_queues = 1; return -1; } } /* start port */ if (rte_eth_dev_start(pi) < 0) { printf("Fail to start port %d\n", pi); /* Fail to setup rx queue, return */ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) printf("Port %d can not be set back to " "stopped\n", pi); continue; } if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0) printf("Port %d can not be set into started\n", pi); rte_eth_macaddr_get(pi, &mac_addr); printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi, mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]); /* at least one port started, need checking link status */ need_check_link_status = 1; } if (need_check_link_status == 1 && !no_link_check) check_all_ports_link_status(RTE_PORT_ALL); else if (need_check_link_status == 0) printf("Please stop the ports first\n"); printf("Done\n"); return 0; } void stop_port(portid_t pid) { portid_t pi; struct rte_port *port; int need_check_link_status = 0; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } if (dcb_test) { dcb_test = 0; dcb_config = 0; } if (port_id_is_invalid(pid, ENABLED_WARN)) return; printf("Stopping ports...\n"); FOREACH_PORT(pi, ports) { if (pid != pi && pid != (portid_t)RTE_PORT_ALL) continue; port = &ports[pi]; if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED, RTE_PORT_HANDLING) == 0) continue; rte_eth_dev_stop(pi); if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) printf("Port %d can not be set into stopped\n", pi); need_check_link_status = 1; } if (need_check_link_status && !no_link_check) check_all_ports_link_status(RTE_PORT_ALL); printf("Done\n"); } void close_port(portid_t pid) { portid_t pi; struct rte_port *port; if (test_done == 0) { printf("Please stop forwarding first\n"); return; } if (port_id_is_invalid(pid, ENABLED_WARN)) return; printf("Closing ports...\n"); FOREACH_PORT(pi, ports) { if (pid != pi && pid != (portid_t)RTE_PORT_ALL) continue; port = &ports[pi]; if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) { printf("Port %d is already closed\n", pi); continue; } if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { printf("Port %d is now not stopped\n", pi); continue; } rte_eth_dev_close(pi); if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) printf("Port %d can not be set into stopped\n", pi); } printf("Done\n"); } void attach_port(char *identifier) { portid_t i, j, pi = 0; printf("Attaching a new port...\n"); if (identifier == NULL) { printf("Invalid parameters are specified\n"); return; } if (test_done == 0) { printf("Please stop forwarding first\n"); return; } if (rte_eth_dev_attach(identifier, &pi)) return; ports[pi].enabled = 1; reconfig(pi, rte_eth_dev_socket_id(pi)); rte_eth_promiscuous_enable(pi); nb_ports = rte_eth_dev_count(); /* set_default_fwd_ports_config(); */ bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); i = 0; FOREACH_PORT(j, ports) { fwd_ports_ids[i] = j; i++; } nb_cfg_ports = nb_ports; nb_fwd_ports++; ports[pi].port_status = RTE_PORT_STOPPED; printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports); printf("Done\n"); } void detach_port(uint8_t port_id) { portid_t i, pi = 0; char name[RTE_ETH_NAME_MAX_LEN]; printf("Detaching a port...\n"); if (!port_is_closed(port_id)) { printf("Please close port first\n"); return; } if (rte_eth_dev_detach(port_id, name)) return; ports[port_id].enabled = 0; nb_ports = rte_eth_dev_count(); /* set_default_fwd_ports_config(); */ bzero(fwd_ports_ids, sizeof(fwd_ports_ids)); i = 0; FOREACH_PORT(pi, ports) { fwd_ports_ids[i] = pi; i++; } nb_cfg_ports = nb_ports; nb_fwd_ports--; printf("Port '%s' is detached. Now total ports is %d\n", name, nb_ports); printf("Done\n"); return; } void pmd_test_exit(void) { portid_t pt_id; if (test_done == 0) stop_packet_forwarding(); FOREACH_PORT(pt_id, ports) { printf("Stopping port %d...", pt_id); fflush(stdout); rte_eth_dev_close(pt_id); printf("done\n"); } printf("bye...\n"); } typedef void (*cmd_func_t)(void); struct pmd_test_command { const char *cmd_name; cmd_func_t cmd_func; }; #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0])) /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("Checking link statuses...\n"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; FOREACH_PORT(portid, ports) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; } } } static int set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) { uint16_t i; int diag; uint8_t mapping_found = 0; for (i = 0; i < nb_tx_queue_stats_mappings; i++) { if ((tx_queue_stats_mappings[i].port_id == port_id) && (tx_queue_stats_mappings[i].queue_id < nb_txq )) { diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id, tx_queue_stats_mappings[i].queue_id, tx_queue_stats_mappings[i].stats_counter_id); if (diag != 0) return diag; mapping_found = 1; } } if (mapping_found) port->tx_queue_stats_mapping_enabled = 1; return 0; } static int set_rx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) { uint16_t i; int diag; uint8_t mapping_found = 0; for (i = 0; i < nb_rx_queue_stats_mappings; i++) { if ((rx_queue_stats_mappings[i].port_id == port_id) && (rx_queue_stats_mappings[i].queue_id < nb_rxq )) { diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id, rx_queue_stats_mappings[i].queue_id, rx_queue_stats_mappings[i].stats_counter_id); if (diag != 0) return diag; mapping_found = 1; } } if (mapping_found) port->rx_queue_stats_mapping_enabled = 1; return 0; } static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port) { int diag = 0; diag = set_tx_queue_stats_mapping_registers(pi, port); if (diag != 0) { if (diag == -ENOTSUP) { port->tx_queue_stats_mapping_enabled = 0; printf("TX queue stats mapping not supported port id=%d\n", pi); } else rte_exit(EXIT_FAILURE, "set_tx_queue_stats_mapping_registers " "failed for port id=%d diag=%d\n", pi, diag); } diag = set_rx_queue_stats_mapping_registers(pi, port); if (diag != 0) { if (diag == -ENOTSUP) { port->rx_queue_stats_mapping_enabled = 0; printf("RX queue stats mapping not supported port id=%d\n", pi); } else rte_exit(EXIT_FAILURE, "set_rx_queue_stats_mapping_registers " "failed for port id=%d diag=%d\n", pi, diag); } } static void rxtx_port_config(struct rte_port *port) { port->rx_conf = port->dev_info.default_rxconf; port->tx_conf = port->dev_info.default_txconf; /* Check if any RX/TX parameters have been passed */ if (rx_pthresh != RTE_PMD_PARAM_UNSET) port->rx_conf.rx_thresh.pthresh = rx_pthresh; if (rx_hthresh != RTE_PMD_PARAM_UNSET) port->rx_conf.rx_thresh.hthresh = rx_hthresh; if (rx_wthresh != RTE_PMD_PARAM_UNSET) port->rx_conf.rx_thresh.wthresh = rx_wthresh; if (rx_free_thresh != RTE_PMD_PARAM_UNSET) port->rx_conf.rx_free_thresh = rx_free_thresh; if (rx_drop_en != RTE_PMD_PARAM_UNSET) port->rx_conf.rx_drop_en = rx_drop_en; if (tx_pthresh != RTE_PMD_PARAM_UNSET) port->tx_conf.tx_thresh.pthresh = tx_pthresh; if (tx_hthresh != RTE_PMD_PARAM_UNSET) port->tx_conf.tx_thresh.hthresh = tx_hthresh; if (tx_wthresh != RTE_PMD_PARAM_UNSET) port->tx_conf.tx_thresh.wthresh = tx_wthresh; if (tx_rs_thresh != RTE_PMD_PARAM_UNSET) port->tx_conf.tx_rs_thresh = tx_rs_thresh; if (tx_free_thresh != RTE_PMD_PARAM_UNSET) port->tx_conf.tx_free_thresh = tx_free_thresh; if (txq_flags != RTE_PMD_PARAM_UNSET) port->tx_conf.txq_flags = txq_flags; } void init_port_config(void) { portid_t pid; struct rte_port *port; FOREACH_PORT(pid, ports) { port = &ports[pid]; port->dev_conf.rxmode = rx_mode; port->dev_conf.fdir_conf = fdir_conf; if (nb_rxq > 1) { port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf; } else { port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0; } if (port->dcb_flag == 0 && port->dev_info.max_vfs == 0) { if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0) port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; else port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; } if (port->dev_info.max_vfs != 0) { if (port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0) port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_RSS; else port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; port->dev_conf.txmode.mq_mode = ETH_MQ_TX_NONE; } rxtx_port_config(port); rte_eth_macaddr_get(pid, &port->eth_addr); map_port_queue_stats_mapping_registers(pid, port); #ifdef RTE_NIC_BYPASS rte_eth_dev_bypass_init(pid); #endif } } void set_port_slave_flag(portid_t slave_pid) { struct rte_port *port; port = &ports[slave_pid]; port->slave_flag = 1; } void clear_port_slave_flag(portid_t slave_pid) { struct rte_port *port; port = &ports[slave_pid]; port->slave_flag = 0; } const uint16_t vlan_tags[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; static int get_eth_dcb_conf(struct rte_eth_conf *eth_conf, struct dcb_config *dcb_conf) { uint8_t i; /* * Builds up the correct configuration for dcb+vt based on the vlan tags array * given above, and the number of traffic classes available for use. */ if (dcb_conf->dcb_mode == DCB_VT_ENABLED) { struct rte_eth_vmdq_dcb_conf vmdq_rx_conf; struct rte_eth_vmdq_dcb_tx_conf vmdq_tx_conf; /* VMDQ+DCB RX and TX configrations */ vmdq_rx_conf.enable_default_pool = 0; vmdq_rx_conf.default_pool = 0; vmdq_rx_conf.nb_queue_pools = (dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); vmdq_tx_conf.nb_queue_pools = (dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); vmdq_rx_conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); for (i = 0; i < vmdq_rx_conf.nb_pool_maps; i++) { vmdq_rx_conf.pool_map[i].vlan_id = vlan_tags[ i ]; vmdq_rx_conf.pool_map[i].pools = 1 << (i % vmdq_rx_conf.nb_queue_pools); } for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { vmdq_rx_conf.dcb_queue[i] = i; vmdq_tx_conf.dcb_queue[i] = i; } /*set DCB mode of RX and TX of multiple queues*/ eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB; eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB; if (dcb_conf->pfc_en) eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT; else eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &vmdq_rx_conf, sizeof(struct rte_eth_vmdq_dcb_conf))); (void)(rte_memcpy(ð_conf->tx_adv_conf.vmdq_dcb_tx_conf, &vmdq_tx_conf, sizeof(struct rte_eth_vmdq_dcb_tx_conf))); } else { struct rte_eth_dcb_rx_conf rx_conf; struct rte_eth_dcb_tx_conf tx_conf; /* queue mapping configuration of DCB RX and TX */ if (dcb_conf->num_tcs == ETH_4_TCS) dcb_q_mapping = DCB_4_TCS_Q_MAPPING; else dcb_q_mapping = DCB_8_TCS_Q_MAPPING; rx_conf.nb_tcs = dcb_conf->num_tcs; tx_conf.nb_tcs = dcb_conf->num_tcs; for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ rx_conf.dcb_queue[i] = i; tx_conf.dcb_queue[i] = i; } eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB; eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB; if (dcb_conf->pfc_en) eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT; else eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; (void)(rte_memcpy(ð_conf->rx_adv_conf.dcb_rx_conf, &rx_conf, sizeof(struct rte_eth_dcb_rx_conf))); (void)(rte_memcpy(ð_conf->tx_adv_conf.dcb_tx_conf, &tx_conf, sizeof(struct rte_eth_dcb_tx_conf))); } return 0; } int init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf) { struct rte_eth_conf port_conf; struct rte_port *rte_port; int retval; uint16_t nb_vlan; uint16_t i; /* rxq and txq configuration in dcb mode */ nb_rxq = 128; nb_txq = 128; rx_free_thresh = 64; memset(&port_conf,0,sizeof(struct rte_eth_conf)); /* Enter DCB configuration status */ dcb_config = 1; nb_vlan = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); /*set configuration of DCB in vt mode and DCB in non-vt mode*/ retval = get_eth_dcb_conf(&port_conf, dcb_conf); if (retval < 0) return retval; rte_port = &ports[pid]; memcpy(&rte_port->dev_conf, &port_conf,sizeof(struct rte_eth_conf)); rxtx_port_config(rte_port); /* VLAN filter */ rte_port->dev_conf.rxmode.hw_vlan_filter = 1; for (i = 0; i < nb_vlan; i++){ rx_vft_set(pid, vlan_tags[i], 1); } rte_eth_macaddr_get(pid, &rte_port->eth_addr); map_port_queue_stats_mapping_registers(pid, rte_port); rte_port->dcb_flag = 1; return 0; } static void init_port(void) { portid_t pid; /* Configuration of Ethernet ports. */ ports = rte_zmalloc("testpmd: ports", sizeof(struct rte_port) * RTE_MAX_ETHPORTS, RTE_CACHE_LINE_SIZE); if (ports == NULL) { rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) failed\n", RTE_MAX_ETHPORTS); } /* enabled allocated ports */ for (pid = 0; pid < nb_ports; pid++) ports[pid].enabled = 1; } int main(int argc, char** argv) { int diag; uint8_t port_id; diag = rte_eal_init(argc, argv); if (diag < 0) rte_panic("Cannot init EAL\n"); nb_ports = (portid_t) rte_eth_dev_count(); if (nb_ports == 0) RTE_LOG(WARNING, EAL, "No probed ethernet devices\n"); /* allocate port structures, and init them */ init_port(); set_def_fwd_config(); if (nb_lcores == 0) rte_panic("Empty set of forwarding logical cores - check the " "core mask supplied in the command parameters\n"); argc -= diag; argv += diag; if (argc > 1) launch_args_parse(argc, argv); if (nb_rxq > nb_txq) printf("Warning: nb_rxq=%d enables RSS configuration, " "but nb_txq=%d will prevent to fully test it.\n", nb_rxq, nb_txq); init_config(); if (start_port(RTE_PORT_ALL) != 0) rte_exit(EXIT_FAILURE, "Start ports failed\n"); /* set all ports to promiscuous mode by default */ FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { printf("Start automatic packet forwarding\n"); start_packet_forwarding(0); } prompt(); } else #endif { char c; int rc; printf("No commandline core given, start packet forwarding\n"); start_packet_forwarding(0); printf("Press enter to exit\n"); rc = read(0, &c, 1); if (rc < 0) return 1; } return 0; } ================================================ FILE: app/test-pmd/testpmd.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _TESTPMD_H_ #define _TESTPMD_H_ #define RTE_PORT_ALL (~(portid_t)0x0) #define RTE_TEST_RX_DESC_MAX 2048 #define RTE_TEST_TX_DESC_MAX 2048 #define RTE_PORT_STOPPED (uint16_t)0 #define RTE_PORT_STARTED (uint16_t)1 #define RTE_PORT_CLOSED (uint16_t)2 #define RTE_PORT_HANDLING (uint16_t)3 /* * Default size of the mbuf data buffer to receive standard 1518-byte * Ethernet frames in a mono-segment memory buffer. */ #define DEFAULT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE /**< Default size of mbuf data buffer. */ /* * The maximum number of segments per packet is used when creating * scattered transmit packets composed of a list of mbufs. */ #define RTE_MAX_SEGS_PER_PKT 255 /**< nb_segs is a 8-bit unsigned char. */ #define MAX_PKT_BURST 512 #define DEF_PKT_BURST 32 #define DEF_MBUF_CACHE 250 #define RTE_CACHE_LINE_SIZE_ROUNDUP(size) \ (RTE_CACHE_LINE_SIZE * ((size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE)) #define NUMA_NO_CONFIG 0xFF #define UMA_NO_CONFIG 0xFF typedef uint8_t lcoreid_t; typedef uint8_t portid_t; typedef uint16_t queueid_t; typedef uint16_t streamid_t; #define MAX_QUEUE_ID ((1 << (sizeof(queueid_t) * 8)) - 1) enum { PORT_TOPOLOGY_PAIRED, PORT_TOPOLOGY_CHAINED, PORT_TOPOLOGY_LOOP, }; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS /** * The data structure associated with RX and TX packet burst statistics * that are recorded for each forwarding stream. */ struct pkt_burst_stats { unsigned int pkt_burst_spread[MAX_PKT_BURST]; }; #endif /** * The data structure associated with a forwarding stream between a receive * port/queue and a transmit port/queue. */ struct fwd_stream { /* "read-only" data */ portid_t rx_port; /**< port to poll for received packets */ queueid_t rx_queue; /**< RX queue to poll on "rx_port" */ portid_t tx_port; /**< forwarding port of received packets */ queueid_t tx_queue; /**< TX queue to send forwarded packets */ streamid_t peer_addr; /**< index of peer ethernet address of packets */ /* "read-write" results */ unsigned int rx_packets; /**< received packets */ unsigned int tx_packets; /**< received packets transmitted */ unsigned int fwd_dropped; /**< received packets not forwarded */ unsigned int rx_bad_ip_csum ; /**< received packets has bad ip checksum */ unsigned int rx_bad_l4_csum ; /**< received packets has bad l4 checksum */ #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t core_cycles; /**< used for RX and TX processing */ #endif #ifdef RTE_TEST_PMD_RECORD_BURST_STATS struct pkt_burst_stats rx_burst_stats; struct pkt_burst_stats tx_burst_stats; #endif }; /** Offload IP checksum in csum forward engine */ #define TESTPMD_TX_OFFLOAD_IP_CKSUM 0x0001 /** Offload UDP checksum in csum forward engine */ #define TESTPMD_TX_OFFLOAD_UDP_CKSUM 0x0002 /** Offload TCP checksum in csum forward engine */ #define TESTPMD_TX_OFFLOAD_TCP_CKSUM 0x0004 /** Offload SCTP checksum in csum forward engine */ #define TESTPMD_TX_OFFLOAD_SCTP_CKSUM 0x0008 /** Offload outer IP checksum in csum forward engine for recognized tunnels */ #define TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM 0x0010 /** Parse tunnel in csum forward engine. If set, dissect tunnel headers * of rx packets. If not set, treat inner headers as payload. */ #define TESTPMD_TX_OFFLOAD_PARSE_TUNNEL 0x0020 /** Insert VLAN header in forward engine */ #define TESTPMD_TX_OFFLOAD_INSERT_VLAN 0x0040 /** Insert double VLAN header in forward engine */ #define TESTPMD_TX_OFFLOAD_INSERT_QINQ 0x0080 /** * The data structure associated with each port. */ struct rte_port { uint8_t enabled; /**< Port enabled or not */ struct rte_eth_dev_info dev_info; /**< PCI info + driver name */ struct rte_eth_conf dev_conf; /**< Port configuration. */ struct ether_addr eth_addr; /**< Port ethernet address */ struct rte_eth_stats stats; /**< Last port statistics */ uint64_t tx_dropped; /**< If no descriptor in TX ring */ struct fwd_stream *rx_stream; /**< Port RX stream, if unique */ struct fwd_stream *tx_stream; /**< Port TX stream, if unique */ unsigned int socket_id; /**< For NUMA support */ uint16_t tx_ol_flags;/**< TX Offload Flags (TESTPMD_TX_OFFLOAD...). */ uint16_t tso_segsz; /**< MSS for segmentation offload. */ uint16_t tx_vlan_id;/**< The tag ID */ uint16_t tx_vlan_id_outer;/**< The outer tag ID */ void *fwd_ctx; /**< Forwarding mode context */ uint64_t rx_bad_ip_csum; /**< rx pkts with bad ip checksum */ uint64_t rx_bad_l4_csum; /**< rx pkts with bad l4 checksum */ uint8_t tx_queue_stats_mapping_enabled; uint8_t rx_queue_stats_mapping_enabled; volatile uint16_t port_status; /**< port started or not */ uint8_t need_reconfig; /**< need reconfiguring port or not */ uint8_t need_reconfig_queues; /**< need reconfiguring queues or not */ uint8_t rss_flag; /**< enable rss or not */ uint8_t dcb_flag; /**< enable dcb */ struct rte_eth_rxconf rx_conf; /**< rx configuration */ struct rte_eth_txconf tx_conf; /**< tx configuration */ struct ether_addr *mc_addr_pool; /**< pool of multicast addrs */ uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */ uint8_t slave_flag; /**< bonding slave port */ }; extern portid_t __rte_unused find_next_port(portid_t p, struct rte_port *ports, int size); #define FOREACH_PORT(p, ports) \ for (p = find_next_port(0, ports, RTE_MAX_ETHPORTS); \ p < RTE_MAX_ETHPORTS; \ p = find_next_port(p + 1, ports, RTE_MAX_ETHPORTS)) /** * The data structure associated with each forwarding logical core. * The logical cores are internally numbered by a core index from 0 to * the maximum number of logical cores - 1. * The system CPU identifier of all logical cores are setup in a global * CPU id. configuration table. */ struct fwd_lcore { struct rte_mempool *mbp; /**< The mbuf pool to use by this core */ streamid_t stream_idx; /**< index of 1st stream in "fwd_streams" */ streamid_t stream_nb; /**< number of streams in "fwd_streams" */ lcoreid_t cpuid_idx; /**< index of logical core in CPU id table */ queueid_t tx_queue; /**< TX queue to send forwarded packets */ volatile char stopped; /**< stop forwarding when set */ }; /* * Forwarding mode operations: * - IO forwarding mode (default mode) * Forwards packets unchanged. * * - MAC forwarding mode * Set the source and the destination Ethernet addresses of packets * before forwarding them. * * - IEEE1588 forwarding mode * Check that received IEEE1588 Precise Time Protocol (PTP) packets are * filtered and timestamped by the hardware. * Forwards packets unchanged on the same port. * Check that sent IEEE1588 PTP packets are timestamped by the hardware. */ typedef void (*port_fwd_begin_t)(portid_t pi); typedef void (*port_fwd_end_t)(portid_t pi); typedef void (*packet_fwd_t)(struct fwd_stream *fs); struct fwd_engine { const char *fwd_mode_name; /**< Forwarding mode name. */ port_fwd_begin_t port_fwd_begin; /**< NULL if nothing special to do. */ port_fwd_end_t port_fwd_end; /**< NULL if nothing special to do. */ packet_fwd_t packet_fwd; /**< Mandatory. */ }; extern struct fwd_engine io_fwd_engine; extern struct fwd_engine mac_fwd_engine; extern struct fwd_engine mac_retry_fwd_engine; extern struct fwd_engine mac_swap_engine; extern struct fwd_engine flow_gen_engine; extern struct fwd_engine rx_only_engine; extern struct fwd_engine tx_only_engine; extern struct fwd_engine csum_fwd_engine; extern struct fwd_engine icmp_echo_engine; #ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine; #endif extern struct fwd_engine * fwd_engines[]; /**< NULL terminated array. */ /** * Forwarding Configuration * */ struct fwd_config { struct fwd_engine *fwd_eng; /**< Packet forwarding mode. */ streamid_t nb_fwd_streams; /**< Nb. of forward streams to process. */ lcoreid_t nb_fwd_lcores; /**< Nb. of logical cores to launch. */ portid_t nb_fwd_ports; /**< Nb. of ports involved. */ }; /** * DCB mode enable */ enum dcb_mode_enable { DCB_VT_ENABLED, DCB_ENABLED }; /* * DCB general config info */ struct dcb_config { enum dcb_mode_enable dcb_mode; uint8_t vt_en; enum rte_eth_nb_tcs num_tcs; uint8_t pfc_en; }; /* * In DCB io FWD mode, 128 RX queue to 128 TX queue mapping */ enum dcb_queue_mapping_mode { DCB_VT_Q_MAPPING = 0, DCB_4_TCS_Q_MAPPING, DCB_8_TCS_Q_MAPPING }; #define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */ #define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */ struct queue_stats_mappings { uint8_t port_id; uint16_t queue_id; uint8_t stats_counter_id; } __rte_cache_aligned; extern struct queue_stats_mappings tx_queue_stats_mappings_array[]; extern struct queue_stats_mappings rx_queue_stats_mappings_array[]; /* Assign both tx and rx queue stats mappings to the same default values */ extern struct queue_stats_mappings *tx_queue_stats_mappings; extern struct queue_stats_mappings *rx_queue_stats_mappings; extern uint16_t nb_tx_queue_stats_mappings; extern uint16_t nb_rx_queue_stats_mappings; /* globals used for configuration */ extern uint16_t verbose_level; /**< Drives messages being displayed, if any. */ extern uint8_t interactive; extern uint8_t auto_start; extern uint8_t numa_support; /**< set by "--numa" parameter */ extern uint16_t port_topology; /**< set by "--port-topology" parameter */ extern uint8_t no_flush_rx; /**dev_info.pci_dev->mem_resource[0].addr + reg_off); reg_v = *((volatile uint32_t *)reg_addr); return rte_le_to_cpu_32(reg_v); } #define port_id_pci_reg_read(pt_id, reg_off) \ port_pci_reg_read(&ports[(pt_id)], (reg_off)) static inline void port_pci_reg_write(struct rte_port *port, uint32_t reg_off, uint32_t reg_v) { void *reg_addr; reg_addr = (void *) ((char *)port->dev_info.pci_dev->mem_resource[0].addr + reg_off); *((volatile uint32_t *)reg_addr) = rte_cpu_to_le_32(reg_v); } #define port_id_pci_reg_write(pt_id, reg_off, reg_value) \ port_pci_reg_write(&ports[(pt_id)], (reg_off), (reg_value)) /* Prototypes */ unsigned int parse_item_list(char* str, const char* item_name, unsigned int max_items, unsigned int *parsed_items, int check_unique_values); void launch_args_parse(int argc, char** argv); void prompt(void); void nic_stats_display(portid_t port_id); void nic_stats_clear(portid_t port_id); void nic_xstats_display(portid_t port_id); void nic_xstats_clear(portid_t port_id); void nic_stats_mapping_display(portid_t port_id); void port_infos_display(portid_t port_id); void fwd_lcores_config_display(void); void fwd_config_display(void); void rxtx_config_display(void); void fwd_config_setup(void); void set_def_fwd_config(void); void reconfig(portid_t new_port_id, unsigned socket_id); int init_fwd_streams(void); void port_mtu_set(portid_t port_id, uint16_t mtu); void port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_pos); void port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, uint8_t bit_v); void port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, uint8_t bit1_pos, uint8_t bit2_pos); void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value); void port_reg_display(portid_t port_id, uint32_t reg_off); void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value); void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id); void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id); int set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc); int set_fwd_lcores_mask(uint64_t lcoremask); void set_fwd_lcores_number(uint16_t nb_lc); void set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt); void set_fwd_ports_mask(uint64_t portmask); void set_fwd_ports_number(uint16_t nb_pt); void rx_vlan_strip_set(portid_t port_id, int on); void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on); void rx_vlan_filter_set(portid_t port_id, int on); void rx_vlan_all_filter_set(portid_t port_id, int on); int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on); void vlan_extend_set(portid_t port_id, int on); void vlan_tpid_set(portid_t port_id, uint16_t tp_id); void tx_vlan_set(portid_t port_id, uint16_t vlan_id); void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer); void tx_vlan_reset(portid_t port_id); void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on); void set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value); void set_verbose_level(uint16_t vb_level); void set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs); void set_nb_pkt_per_burst(uint16_t pkt_burst); char *list_pkt_forwarding_modes(void); void set_pkt_forwarding_mode(const char *fwd_mode); void start_packet_forwarding(int with_tx_first); void stop_packet_forwarding(void); void dev_set_link_up(portid_t pid); void dev_set_link_down(portid_t pid); void init_port_config(void); void set_port_slave_flag(portid_t slave_pid); void clear_port_slave_flag(portid_t slave_pid); int init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf); int start_port(portid_t pid); void stop_port(portid_t pid); void close_port(portid_t pid); void attach_port(char *identifier); void detach_port(uint8_t port_id); int all_ports_stopped(void); int port_is_started(portid_t port_id); void pmd_test_exit(void); void fdir_get_infos(portid_t port_id); void fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg); void fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg); void port_rss_reta_info(portid_t port_id, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t nb_entries); void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on); void set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on); int set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate); int set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk); void port_rss_hash_conf_show(portid_t port_id, int show_rss_key); void port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key); void get_syn_filter(uint8_t port_id); void get_ethertype_filter(uint8_t port_id, uint16_t index); void get_2tuple_filter(uint8_t port_id, uint16_t index); void get_5tuple_filter(uint8_t port_id, uint16_t index); int rx_queue_id_is_invalid(queueid_t rxq_id); int tx_queue_id_is_invalid(queueid_t txq_id); /* Functions to manage the set of filtered Multicast MAC addresses */ void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr); void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr); enum print_warning { ENABLED_WARN = 0, DISABLED_WARN }; int port_id_is_invalid(portid_t port_id, enum print_warning warning); /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. */ #ifdef __GCC__ #define RTE_BE_TO_CPU_16(be_16_v) rte_be_to_cpu_16((be_16_v)) #define RTE_CPU_TO_BE_16(cpu_16_v) rte_cpu_to_be_16((cpu_16_v)) #else #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN #define RTE_BE_TO_CPU_16(be_16_v) (be_16_v) #define RTE_CPU_TO_BE_16(cpu_16_v) (cpu_16_v) #else #define RTE_BE_TO_CPU_16(be_16_v) \ (uint16_t) ((((be_16_v) & 0xFF) << 8) | ((be_16_v) >> 8)) #define RTE_CPU_TO_BE_16(cpu_16_v) \ (uint16_t) ((((cpu_16_v) & 0xFF) << 8) | ((cpu_16_v) >> 8)) #endif #endif /* __GCC__ */ #endif /* _TESTPMD_H_ */ ================================================ FILE: app/test-pmd/txonly.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "testpmd.h" #define UDP_SRC_PORT 1024 #define UDP_DST_PORT 1024 #define IP_SRC_ADDR ((192U << 24) | (168 << 16) | (0 << 8) | 1) #define IP_DST_ADDR ((192U << 24) | (168 << 16) | (0 << 8) | 2) #define IP_DEFTTL 64 /* from RFC 1340. */ #define IP_VERSION 0x40 #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) static struct ipv4_hdr pkt_ip_hdr; /**< IP header of transmitted packets. */ static struct udp_hdr pkt_udp_hdr; /**< UDP header of transmitted packets. */ static inline struct rte_mbuf * tx_mbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return (m); } static void copy_buf_to_pkt_segs(void* buf, unsigned len, struct rte_mbuf *pkt, unsigned offset) { struct rte_mbuf *seg; void *seg_buf; unsigned copy_len; seg = pkt; while (offset >= seg->data_len) { offset -= seg->data_len; seg = seg->next; } copy_len = seg->data_len - offset; seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset); while (len > copy_len) { rte_memcpy(seg_buf, buf, (size_t) copy_len); len -= copy_len; buf = ((char*) buf + copy_len); seg = seg->next; seg_buf = rte_pktmbuf_mtod(seg, char *); } rte_memcpy(seg_buf, buf, (size_t) len); } static inline void copy_buf_to_pkt(void* buf, unsigned len, struct rte_mbuf *pkt, unsigned offset) { if (offset + len <= pkt->data_len) { rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset), buf, (size_t) len); return; } copy_buf_to_pkt_segs(buf, len, pkt, offset); } static void setup_pkt_udp_ip_headers(struct ipv4_hdr *ip_hdr, struct udp_hdr *udp_hdr, uint16_t pkt_data_len) { uint16_t *ptr16; uint32_t ip_cksum; uint16_t pkt_len; /* * Initialize UDP header. */ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct udp_hdr)); udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT); udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT); udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_len); udp_hdr->dgram_cksum = 0; /* No UDP checksum. */ /* * Initialize IP header. */ pkt_len = (uint16_t) (pkt_len + sizeof(struct ipv4_hdr)); ip_hdr->version_ihl = IP_VHL_DEF; ip_hdr->type_of_service = 0; ip_hdr->fragment_offset = 0; ip_hdr->time_to_live = IP_DEFTTL; ip_hdr->next_proto_id = IPPROTO_UDP; ip_hdr->packet_id = 0; ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_len); ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR); ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR); /* * Compute IP header checksum. */ ptr16 = (unaligned_uint16_t*) ip_hdr; ip_cksum = 0; ip_cksum += ptr16[0]; ip_cksum += ptr16[1]; ip_cksum += ptr16[2]; ip_cksum += ptr16[3]; ip_cksum += ptr16[4]; ip_cksum += ptr16[6]; ip_cksum += ptr16[7]; ip_cksum += ptr16[8]; ip_cksum += ptr16[9]; /* * Reduce 32 bit checksum to 16 bits and complement it. */ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) + (ip_cksum & 0x0000FFFF); if (ip_cksum > 65535) ip_cksum -= 65535; ip_cksum = (~ip_cksum) & 0x0000FFFF; if (ip_cksum == 0) ip_cksum = 0xFFFF; ip_hdr->hdr_checksum = (uint16_t) ip_cksum; } /* * Transmit a burst of multi-segments packets. */ static void pkt_burst_transmit(struct fwd_stream *fs) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_port *txp; struct rte_mbuf *pkt; struct rte_mbuf *pkt_seg; struct rte_mempool *mbp; struct ether_hdr eth_hdr; uint16_t nb_tx; uint16_t nb_pkt; uint16_t vlan_tci, vlan_tci_outer; uint64_t ol_flags = 0; uint8_t i; #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES uint64_t start_tsc; uint64_t end_tsc; uint64_t core_cycles; #endif #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES start_tsc = rte_rdtsc(); #endif mbp = current_fwd_lcore()->mbp; txp = &ports[fs->tx_port]; vlan_tci = txp->tx_vlan_id; vlan_tci_outer = txp->tx_vlan_id_outer; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN) ol_flags = PKT_TX_VLAN_PKT; if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ) ol_flags |= PKT_TX_QINQ_PKT; for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) { pkt = tx_mbuf_alloc(mbp); if (pkt == NULL) { nomore_mbuf: if (nb_pkt == 0) return; break; } pkt->data_len = tx_pkt_seg_lengths[0]; pkt_seg = pkt; for (i = 1; i < tx_pkt_nb_segs; i++) { pkt_seg->next = tx_mbuf_alloc(mbp); if (pkt_seg->next == NULL) { pkt->nb_segs = i; rte_pktmbuf_free(pkt); goto nomore_mbuf; } pkt_seg = pkt_seg->next; pkt_seg->data_len = tx_pkt_seg_lengths[i]; } pkt_seg->next = NULL; /* Last segment of packet. */ /* * Initialize Ethernet header. */ ether_addr_copy(&peer_eth_addrs[fs->peer_addr],ð_hdr.d_addr); ether_addr_copy(&ports[fs->tx_port].eth_addr, ð_hdr.s_addr); eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); /* * Copy headers in first packet segment(s). */ copy_buf_to_pkt(ð_hdr, sizeof(eth_hdr), pkt, 0); copy_buf_to_pkt(&pkt_ip_hdr, sizeof(pkt_ip_hdr), pkt, sizeof(struct ether_hdr)); copy_buf_to_pkt(&pkt_udp_hdr, sizeof(pkt_udp_hdr), pkt, sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr)); /* * Complete first mbuf of packet and append it to the * burst of packets to be transmitted. */ pkt->nb_segs = tx_pkt_nb_segs; pkt->pkt_len = tx_pkt_length; pkt->ol_flags = ol_flags; pkt->vlan_tci = vlan_tci; pkt->vlan_tci_outer = vlan_tci_outer; pkt->l2_len = sizeof(struct ether_hdr); pkt->l3_len = sizeof(struct ipv4_hdr); pkts_burst[nb_pkt] = pkt; } nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt); fs->tx_packets += nb_tx; #ifdef RTE_TEST_PMD_RECORD_BURST_STATS fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; #endif if (unlikely(nb_tx < nb_pkt)) { if (verbose_level > 0 && fs->fwd_dropped == 0) printf("port %d tx_queue %d - drop " "(nb_pkt:%u - nb_tx:%u)=%u packets\n", fs->tx_port, fs->tx_queue, (unsigned) nb_pkt, (unsigned) nb_tx, (unsigned) (nb_pkt - nb_tx)); fs->fwd_dropped += (nb_pkt - nb_tx); do { rte_pktmbuf_free(pkts_burst[nb_tx]); } while (++nb_tx < nb_pkt); } #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES end_tsc = rte_rdtsc(); core_cycles = (end_tsc - start_tsc); fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles); #endif } static void tx_only_begin(__attribute__((unused)) portid_t pi) { uint16_t pkt_data_len; pkt_data_len = (uint16_t) (tx_pkt_length - (sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr))); setup_pkt_udp_ip_headers(&pkt_ip_hdr, &pkt_udp_hdr, pkt_data_len); } struct fwd_engine tx_only_engine = { .fwd_mode_name = "txonly", .port_fwd_begin = tx_only_begin, .port_fwd_end = NULL, .packet_fwd = pkt_burst_transmit, }; ================================================ FILE: config/common_bsdapp ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # define executive environment # # CONFIG_RTE_EXEC_ENV can be linuxapp, bsdapp # CONFIG_RTE_EXEC_ENV="bsdapp" CONFIG_RTE_EXEC_ENV_BSDAPP=y ## ## machine can define specific variables or action for a specific board ## RTE_MACHINE can be: ## default nothing specific ## native current machine ## atm Intel® Atom™ microarchitecture ## nhm Intel® microarchitecture code name Nehalem ## wsm Intel® microarchitecture code name Westmere ## snb Intel® microarchitecture code name Sandy Bridge ## ivb Intel® microarchitecture code name Ivy Bridge ## ## Note: if your compiler does not support the relevant -march options, ## it will be compiled with whatever latest processor the compiler supports! ## #CONFIG_RTE_MACHINE="native" # ## ## define the architecture we compile for. ## CONFIG_RTE_ARCH can be i686, x86_64, x86_64_32 ## #CONFIG_RTE_ARCH="x86_64" #CONFIG_RTE_ARCH_X86_64=y # ## ## The compiler we use. ## Can be gcc, icc or clang. ## #CONFIG_RTE_TOOLCHAIN="gcc" #CONFIG_RTE_TOOLCHAIN_GCC=y # # Use intrinsics or assembly code for key routines # CONFIG_RTE_FORCE_INTRINSICS=n # # Machine forces strict alignment constraints. # CONFIG_RTE_ARCH_STRICT_ALIGN=n # # Compile to share library # CONFIG_RTE_BUILD_SHARED_LIB=n # # Combine to one single library # CONFIG_RTE_BUILD_COMBINE_LIBS=n # # Use newest code breaking previous ABI # CONFIG_RTE_NEXT_ABI=y # # Compile Environment Abstraction Layer # CONFIG_RTE_LIBRTE_EAL=y CONFIG_RTE_MAX_LCORE=128 CONFIG_RTE_MAX_NUMA_NODES=8 CONFIG_RTE_MAX_MEMSEG=256 CONFIG_RTE_MAX_MEMZONE=2560 CONFIG_RTE_MAX_TAILQ=32 CONFIG_RTE_LOG_LEVEL=8 CONFIG_RTE_LOG_HISTORY=256 CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n CONFIG_RTE_MALLOC_DEBUG=n # # FreeBSD contiguous memory driver settings # CONFIG_RTE_CONTIGMEM_MAX_NUM_BUFS=64 CONFIG_RTE_CONTIGMEM_DEFAULT_NUM_BUFS=2 CONFIG_RTE_CONTIGMEM_DEFAULT_BUF_SIZE=1024*1024*1024 # # Compile Environment Abstraction Layer for BSD # CONFIG_RTE_LIBRTE_EAL_BSDAPP=y # # Compile Environment Abstraction Layer for linux # CONFIG_RTE_LIBRTE_EAL_LINUXAPP=n # # Compile Environment Abstraction Layer to support Vmware TSC map # CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # # Compile the argument parser library # CONFIG_RTE_LIBRTE_KVARGS=y # # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n CONFIG_RTE_MAX_ETHPORTS=32 CONFIG_RTE_MAX_QUEUES_PER_PORT=256 CONFIG_RTE_LIBRTE_IEEE1588=n CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y # # Support NIC bypass logic # CONFIG_RTE_NIC_BYPASS=n # # Compile burst-oriented IGB & EM PMD drivers # CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n # # Compile burst-oriented IXGBE PMD driver # CONFIG_RTE_LIBRTE_IXGBE_PMD=y CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n CONFIG_RTE_IXGBE_INC_VECTOR=y CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y # # Compile burst-oriented I40E PMD driver # CONFIG_RTE_LIBRTE_I40E_PMD=y CONFIG_RTE_LIBRTE_I40E_DEBUG_INIT=n CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_I40E_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4 # interval up to 8160 us, aligned to 2 (or default value) CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1 # # Compile burst-oriented FM10K PMD # CONFIG_RTE_LIBRTE_FM10K_PMD=y CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y # # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD # CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4 CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0 CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8 CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1 # # Compile burst-oriented Broadcom PMD driver # CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n # # Compile burst-oriented Chelsio Terminator 10GbE/40GbE (CXGBE) PMD # CONFIG_RTE_LIBRTE_CXGBE_PMD=y CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n # # Compile burst-oriented Cisco ENIC PMD driver # CONFIG_RTE_LIBRTE_ENIC_PMD=y CONFIG_RTE_LIBRTE_ENIC_DEBUG=n # # Compile burst-oriented VIRTIO PMD driver # CONFIG_RTE_LIBRTE_VIRTIO_PMD=y CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n # # Compile burst-oriented VMXNET3 PMD driver # CONFIG_RTE_LIBRTE_VMXNET3_PMD=y CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n # # Compile example software rings based PMD # CONFIG_RTE_LIBRTE_PMD_RING=y CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16 CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16 # # Compile software PMD backed by PCAP files # CONFIG_RTE_LIBRTE_PMD_PCAP=y # # Compile link bonding PMD library # CONFIG_RTE_LIBRTE_PMD_BOND=y CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n # # Compile null PMD # CONFIG_RTE_LIBRTE_PMD_NULL=y # # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y # # Compile librte_ring # CONFIG_RTE_LIBRTE_RING=y CONFIG_RTE_LIBRTE_RING_DEBUG=n CONFIG_RTE_RING_SPLIT_PROD_CONS=n CONFIG_RTE_RING_PAUSE_REP_COUNT=0 # # Compile librte_mempool # CONFIG_RTE_LIBRTE_MEMPOOL=y CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512 CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n # # Compile librte_mbuf # CONFIG_RTE_LIBRTE_MBUF=y CONFIG_RTE_LIBRTE_MBUF_DEBUG=n CONFIG_RTE_MBUF_REFCNT_ATOMIC=y CONFIG_RTE_PKTMBUF_HEADROOM=128 # # Compile librte_timer # CONFIG_RTE_LIBRTE_TIMER=y CONFIG_RTE_LIBRTE_TIMER_DEBUG=n # # Compile librte_cfgfile # CONFIG_RTE_LIBRTE_CFGFILE=y # # Compile librte_cmdline # CONFIG_RTE_LIBRTE_CMDLINE=y CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n # # Compile librte_hash # CONFIG_RTE_LIBRTE_HASH=y CONFIG_RTE_LIBRTE_HASH_DEBUG=n # # Compile librte_jobstats # CONFIG_RTE_LIBRTE_JOBSTATS=y # # Compile librte_lpm # CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n # # Compile librte_acl # CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n # # Compile librte_power # CONFIG_RTE_LIBRTE_POWER=n CONFIG_RTE_LIBRTE_POWER_DEBUG=n CONFIG_RTE_MAX_LCORE_FREQS=64 # # Compile librte_net # CONFIG_RTE_LIBRTE_NET=y # # Compile librte_ip_frag # CONFIG_RTE_LIBRTE_IP_FRAG=y CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4 CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n # # Compile librte_meter # CONFIG_RTE_LIBRTE_METER=y # # Compile librte_sched # CONFIG_RTE_LIBRTE_SCHED=y CONFIG_RTE_SCHED_RED=n CONFIG_RTE_SCHED_COLLECT_STATS=n CONFIG_RTE_SCHED_SUBPORT_TC_OV=n CONFIG_RTE_SCHED_PORT_N_GRINDERS=8 # # Compile the distributor library # CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # # Compile the reorder library # CONFIG_RTE_LIBRTE_REORDER=y # # Compile librte_port # CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n # # Compile librte_table # CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n # # Compile librte_pipeline # CONFIG_RTE_LIBRTE_PIPELINE=y CONFIG_RTE_PIPELINE_STATS_COLLECT=n # # Enable warning directives # CONFIG_RTE_INSECURE_FUNCTION_WARNING=n # # Compile the test application # CONFIG_RTE_APP_TEST=y # # Compile the PMD test application # CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n ================================================ FILE: config/common_linuxapp ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # define executive environment # # CONFIG_RTE_EXEC_ENV can be linuxapp, bsdapp # CONFIG_RTE_EXEC_ENV="linuxapp" CONFIG_RTE_EXEC_ENV_LINUXAPP=y ## ## machine can define specific variables or action for a specific board ## RTE_MACHINE can be: ## default nothing specific ## native current machine ## atm Intel® Atom™ microarchitecture ## nhm Intel® microarchitecture code name Nehalem ## wsm Intel® microarchitecture code name Westmere ## snb Intel® microarchitecture code name Sandy Bridge ## ivb Intel® microarchitecture code name Ivy Bridge ## ## Note: if your compiler does not support the relevant -march options, ## it will be compiled with whatever latest processor the compiler supports! ## #CONFIG_RTE_MACHINE="native" # ## ## define the architecture we compile for. ## CONFIG_RTE_ARCH can be i686, x86_64, x86_64_32 ## #CONFIG_RTE_ARCH="x86_64" #CONFIG_RTE_ARCH_X86_64=y # ## ## The compiler we use. ## Can be gcc, icc or clang. ## #CONFIG_RTE_TOOLCHAIN="gcc" #CONFIG_RTE_TOOLCHAIN_GCC=y # # Use intrinsics or assembly code for key routines # CONFIG_RTE_FORCE_INTRINSICS=n # # Machine forces strict alignment constraints. # CONFIG_RTE_ARCH_STRICT_ALIGN=n # # Compile to share library # CONFIG_RTE_BUILD_SHARED_LIB=n # # Combine to one single library # CONFIG_RTE_BUILD_COMBINE_LIBS=n # # Use newest code breaking previous ABI # CONFIG_RTE_NEXT_ABI=y # # Compile Environment Abstraction Layer # CONFIG_RTE_LIBRTE_EAL=y CONFIG_RTE_MAX_LCORE=128 CONFIG_RTE_MAX_NUMA_NODES=8 CONFIG_RTE_MAX_MEMSEG=256 CONFIG_RTE_MAX_MEMZONE=2560 CONFIG_RTE_MAX_TAILQ=32 CONFIG_RTE_LOG_LEVEL=8 CONFIG_RTE_LOG_HISTORY=256 CONFIG_RTE_LIBEAL_USE_HPET=n CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID=n CONFIG_RTE_EAL_ALWAYS_PANIC_ON_ERROR=n CONFIG_RTE_EAL_IGB_UIO=y CONFIG_RTE_EAL_VFIO=y CONFIG_RTE_MALLOC_DEBUG=n # # Special configurations in PCI Config Space for high performance # CONFIG_RTE_PCI_CONFIG=n CONFIG_RTE_PCI_EXTENDED_TAG="" CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE=0 # # Compile Environment Abstraction Layer for linux # CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y # # Compile Environment Abstraction Layer to support Vmware TSC map # CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # # Compile the argument parser library # CONFIG_RTE_LIBRTE_KVARGS=y # # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n CONFIG_RTE_MAX_ETHPORTS=32 CONFIG_RTE_MAX_QUEUES_PER_PORT=256 CONFIG_RTE_LIBRTE_IEEE1588=n CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y # # Support NIC bypass logic # CONFIG_RTE_NIC_BYPASS=n # # Compile burst-oriented IGB & EM PMD drivers # CONFIG_RTE_LIBRTE_EM_PMD=y CONFIG_RTE_LIBRTE_IGB_PMD=y CONFIG_RTE_LIBRTE_E1000_DEBUG_INIT=n CONFIG_RTE_LIBRTE_E1000_DEBUG_RX=n CONFIG_RTE_LIBRTE_E1000_DEBUG_TX=n CONFIG_RTE_LIBRTE_E1000_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_E1000_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC=n # # Compile burst-oriented IXGBE PMD driver # CONFIG_RTE_LIBRTE_IXGBE_PMD=y CONFIG_RTE_LIBRTE_IXGBE_DEBUG_INIT=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_RX=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_IXGBE_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC=n CONFIG_RTE_IXGBE_INC_VECTOR=y CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y # # Compile burst-oriented I40E PMD driver # CONFIG_RTE_LIBRTE_I40E_PMD=y CONFIG_RTE_LIBRTE_I40E_DEBUG_INIT=n CONFIG_RTE_LIBRTE_I40E_DEBUG_RX=n CONFIG_RTE_LIBRTE_I40E_DEBUG_TX=n CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_I40E_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4 # interval up to 8160 us, aligned to 2 (or default value) CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL=-1 # # Compile burst-oriented FM10K PMD # CONFIG_RTE_LIBRTE_FM10K_PMD=y CONFIG_RTE_LIBRTE_FM10K_DEBUG_INIT=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_RX=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_FM10K_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE=y # # Compile burst-oriented Mellanox ConnectX-3 (MLX4) PMD # CONFIG_RTE_LIBRTE_MLX4_PMD=n CONFIG_RTE_LIBRTE_MLX4_DEBUG=n CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N=4 CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE=0 CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE=8 CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS=1 # # Compile burst-oriented Broadcom PMD driver # CONFIG_RTE_LIBRTE_BNX2X_PMD=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_INIT=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_RX=n CONFIG_RTE_LIBRTE_BNX2X_DEBUG_TX=n CONFIG_RTE_LIBRTE_BNX2X_MF_SUPPORT=n # # Compile burst-oriented Chelsio Terminator 10GbE/40GbE (CXGBE) PMD # CONFIG_RTE_LIBRTE_CXGBE_PMD=y CONFIG_RTE_LIBRTE_CXGBE_DEBUG=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX=n CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX=n # # Compile burst-oriented Cisco ENIC PMD driver # CONFIG_RTE_LIBRTE_ENIC_PMD=y CONFIG_RTE_LIBRTE_ENIC_DEBUG=n # # Compile burst-oriented VIRTIO PMD driver # CONFIG_RTE_LIBRTE_VIRTIO_PMD=y CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_INIT=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_RX=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_TX=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_VIRTIO_DEBUG_DUMP=n # # Compile burst-oriented VMXNET3 PMD driver # CONFIG_RTE_LIBRTE_VMXNET3_PMD=y CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_INIT=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_RX=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_VMXNET3_DEBUG_DRIVER=n # # Compile example software rings based PMD # CONFIG_RTE_LIBRTE_PMD_RING=y CONFIG_RTE_PMD_RING_MAX_RX_RINGS=16 CONFIG_RTE_PMD_RING_MAX_TX_RINGS=16 # # Compile software PMD backed by PCAP files # CONFIG_RTE_LIBRTE_PMD_PCAP=n # # Compile link bonding PMD library # CONFIG_RTE_LIBRTE_PMD_BOND=y CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB=n CONFIG_RTE_LIBRTE_BOND_DEBUG_ALB_L1=n # # Compile software PMD backed by AF_PACKET sockets (Linux only) # CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y # # Compile Xen PMD # CONFIG_RTE_LIBRTE_PMD_XENVIRT=n # # Compile null PMD # CONFIG_RTE_LIBRTE_PMD_NULL=y # # Do prefetch of packet data within PMD driver receive function # CONFIG_RTE_PMD_PACKET_PREFETCH=y # # Compile librte_ring # CONFIG_RTE_LIBRTE_RING=y CONFIG_RTE_LIBRTE_RING_DEBUG=n CONFIG_RTE_RING_SPLIT_PROD_CONS=n CONFIG_RTE_RING_PAUSE_REP_COUNT=0 # # Compile librte_mempool # CONFIG_RTE_LIBRTE_MEMPOOL=y CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE=512 CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG=n # # Compile librte_mbuf # CONFIG_RTE_LIBRTE_MBUF=y CONFIG_RTE_LIBRTE_MBUF_DEBUG=n CONFIG_RTE_MBUF_REFCNT_ATOMIC=y CONFIG_RTE_PKTMBUF_HEADROOM=128 # # Compile librte_timer # CONFIG_RTE_LIBRTE_TIMER=y CONFIG_RTE_LIBRTE_TIMER_DEBUG=n # # Compile librte_cfgfile # CONFIG_RTE_LIBRTE_CFGFILE=y # # Compile librte_cmdline # CONFIG_RTE_LIBRTE_CMDLINE=y CONFIG_RTE_LIBRTE_CMDLINE_DEBUG=n # # Compile librte_hash # CONFIG_RTE_LIBRTE_HASH=y CONFIG_RTE_LIBRTE_HASH_DEBUG=n # # Compile librte_jobstats # CONFIG_RTE_LIBRTE_JOBSTATS=y # # Compile librte_lpm # CONFIG_RTE_LIBRTE_LPM=y CONFIG_RTE_LIBRTE_LPM_DEBUG=n # # Compile librte_acl # CONFIG_RTE_LIBRTE_ACL=y CONFIG_RTE_LIBRTE_ACL_DEBUG=n # # Compile librte_power # CONFIG_RTE_LIBRTE_POWER=y CONFIG_RTE_LIBRTE_POWER_DEBUG=n CONFIG_RTE_MAX_LCORE_FREQS=64 # # Compile librte_net # CONFIG_RTE_LIBRTE_NET=y # # Compile librte_ip_frag # CONFIG_RTE_LIBRTE_IP_FRAG=y CONFIG_RTE_LIBRTE_IP_FRAG_DEBUG=n CONFIG_RTE_LIBRTE_IP_FRAG_MAX_FRAG=4 CONFIG_RTE_LIBRTE_IP_FRAG_TBL_STAT=n # # Compile librte_meter # CONFIG_RTE_LIBRTE_METER=y # # Compile librte_sched # CONFIG_RTE_LIBRTE_SCHED=y CONFIG_RTE_SCHED_RED=n CONFIG_RTE_SCHED_COLLECT_STATS=n CONFIG_RTE_SCHED_SUBPORT_TC_OV=n CONFIG_RTE_SCHED_PORT_N_GRINDERS=8 # # Compile the distributor library # CONFIG_RTE_LIBRTE_DISTRIBUTOR=y # # Compile the reorder library # CONFIG_RTE_LIBRTE_REORDER=y # # Compile librte_port # CONFIG_RTE_LIBRTE_PORT=y CONFIG_RTE_PORT_STATS_COLLECT=n # # Compile librte_table # CONFIG_RTE_LIBRTE_TABLE=y CONFIG_RTE_TABLE_STATS_COLLECT=n # # Compile librte_pipeline # CONFIG_RTE_LIBRTE_PIPELINE=y CONFIG_RTE_PIPELINE_STATS_COLLECT=n # # Compile librte_kni # CONFIG_RTE_LIBRTE_KNI=y CONFIG_RTE_KNI_KMOD=y CONFIG_RTE_KNI_PREEMPT_DEFAULT=y CONFIG_RTE_KNI_KO_DEBUG=n CONFIG_RTE_KNI_VHOST=n CONFIG_RTE_KNI_VHOST_MAX_CACHE_SIZE=1024 CONFIG_RTE_KNI_VHOST_VNET_HDR_EN=n CONFIG_RTE_KNI_VHOST_DEBUG_RX=n CONFIG_RTE_KNI_VHOST_DEBUG_TX=n # # Compile vhost library # fuse-devel is needed to run vhost-cuse. # fuse-devel enables user space char driver development # vhost-user is turned on by default. # CONFIG_RTE_LIBRTE_VHOST=y CONFIG_RTE_LIBRTE_VHOST_USER=y CONFIG_RTE_LIBRTE_VHOST_NUMA=n CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # #Compile Xen domain0 support # CONFIG_RTE_LIBRTE_XEN_DOM0=n # # Enable warning directives # CONFIG_RTE_INSECURE_FUNCTION_WARNING=n # # Compile the test application # CONFIG_RTE_APP_TEST=y # # Compile the PMD test application # CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n ================================================ FILE: config/defconfig_i686-native-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="i686" CONFIG_RTE_ARCH_I686=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y # # KNI is not supported on 32-bit # CONFIG_RTE_LIBRTE_KNI=n # # Vectorized PMD is not supported on 32-bit # CONFIG_RTE_IXGBE_INC_VECTOR=n ================================================ FILE: config/defconfig_i686-native-linuxapp-icc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="i686" CONFIG_RTE_ARCH_I686=y CONFIG_RTE_TOOLCHAIN="icc" CONFIG_RTE_TOOLCHAIN_ICC=y # # KNI is not supported on 32-bit # CONFIG_RTE_LIBRTE_KNI=n # # Vectorized PMD is not supported on 32-bit # CONFIG_RTE_IXGBE_INC_VECTOR=n ================================================ FILE: config/defconfig_ppc_64-power8-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright (C) IBM Corporation 2014. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of IBM Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common_linuxapp" CONFIG_RTE_MACHINE="power8" CONFIG_RTE_ARCH="ppc_64" CONFIG_RTE_ARCH_PPC_64=y CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y # Note: Power doesn't have this support CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n # Note: Initially, all of the PMD drivers compilation are turned off on Power # Will turn on them only after the successful testing on Power CONFIG_RTE_LIBRTE_IXGBE_PMD=n CONFIG_RTE_LIBRTE_I40E_PMD=n CONFIG_RTE_LIBRTE_VIRTIO_PMD=n CONFIG_RTE_LIBRTE_VMXNET3_PMD=n CONFIG_RTE_LIBRTE_PMD_BOND=n CONFIG_RTE_LIBRTE_ENIC_PMD=n # This following libraries are not available on Power. So they're turned off. CONFIG_RTE_LIBRTE_LPM=n CONFIG_RTE_LIBRTE_ACL=n CONFIG_RTE_LIBRTE_SCHED=n CONFIG_RTE_LIBRTE_PORT=n CONFIG_RTE_LIBRTE_TABLE=n CONFIG_RTE_LIBRTE_PIPELINE=n ================================================ FILE: config/defconfig_tile-tilegx-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright (C) EZchip Semiconductor 2015. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of EZchip Semiconductor nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common_linuxapp" CONFIG_RTE_MACHINE="tilegx" CONFIG_RTE_ARCH="tile" CONFIG_RTE_ARCH_TILE=y CONFIG_RTE_ARCH_64=y CONFIG_RTE_ARCH_STRICT_ALIGN=y CONFIG_RTE_FORCE_INTRINSICS=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y CONFIG_RTE_MEMPOOL_ALIGN=128 CONFIG_RTE_LIBRTE_MPIPE_PMD=y CONFIG_RTE_LIBRTE_MPIPE_PMD_DEBUG=n # Disable things that we don't support or need CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=n CONFIG_RTE_EAL_IGB_UIO=n CONFIG_RTE_EAL_VFIO=n CONFIG_RTE_LIBRTE_KNI=n CONFIG_RTE_LIBRTE_XEN_DOM0=n CONFIG_RTE_LIBRTE_IGB_PMD=n CONFIG_RTE_LIBRTE_EM_PMD=n CONFIG_RTE_LIBRTE_IXGBE_PMD=n CONFIG_RTE_LIBRTE_I40E_PMD=n CONFIG_RTE_LIBRTE_FM10K_PMD=n CONFIG_RTE_LIBRTE_VIRTIO_PMD=n CONFIG_RTE_LIBRTE_VMXNET3_PMD=n CONFIG_RTE_LIBRTE_ENIC_PMD=n # This following libraries are not available on the tile architecture. # So they're turned off. CONFIG_RTE_LIBRTE_LPM=n CONFIG_RTE_LIBRTE_ACL=n CONFIG_RTE_LIBRTE_SCHED=n CONFIG_RTE_LIBRTE_PORT=n CONFIG_RTE_LIBRTE_TABLE=n CONFIG_RTE_LIBRTE_PIPELINE=n ================================================ FILE: config/defconfig_x86_64-ivshmem-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # use default config # #include "defconfig_x86_64-native-linuxapp-gcc" # # Compile IVSHMEM library # CONFIG_RTE_LIBRTE_IVSHMEM=y CONFIG_RTE_LIBRTE_IVSHMEM_DEBUG=n CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS=4 CONFIG_RTE_LIBRTE_IVSHMEM_MAX_ENTRIES=128 CONFIG_RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES=32 # Set EAL to single file segments CONFIG_RTE_EAL_SINGLE_FILE_SEGMENTS=y ================================================ FILE: config/defconfig_x86_64-ivshmem-linuxapp-icc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # use default config # #include "defconfig_x86_64-native-linuxapp-icc" # # Compile IVSHMEM library # CONFIG_RTE_LIBRTE_IVSHMEM=y CONFIG_RTE_LIBRTE_IVSHMEM_DEBUG=n CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS=4 CONFIG_RTE_LIBRTE_IVSHMEM_MAX_ENTRIES=128 CONFIG_RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES=32 # Set EAL to single file segments CONFIG_RTE_EAL_SINGLE_FILE_SEGMENTS=y ================================================ FILE: config/defconfig_x86_64-native-bsdapp-clang ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_bsdapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_64" CONFIG_RTE_ARCH_X86_64=y CONFIG_RTE_TOOLCHAIN="clang" CONFIG_RTE_TOOLCHAIN_CLANG=y ================================================ FILE: config/defconfig_x86_64-native-bsdapp-gcc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_bsdapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_64" CONFIG_RTE_ARCH_X86_64=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y ================================================ FILE: config/defconfig_x86_64-native-linuxapp-clang ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_64" CONFIG_RTE_ARCH_X86_64=y CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN="clang" CONFIG_RTE_TOOLCHAIN_CLANG=y ================================================ FILE: config/defconfig_x86_64-native-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_64" CONFIG_RTE_ARCH_X86_64=y CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y ================================================ FILE: config/defconfig_x86_64-native-linuxapp-icc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_64" CONFIG_RTE_ARCH_X86_64=y CONFIG_RTE_ARCH_64=y CONFIG_RTE_TOOLCHAIN="icc" CONFIG_RTE_TOOLCHAIN_ICC=y ================================================ FILE: config/defconfig_x86_x32-native-linuxapp-gcc ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #include "common_linuxapp" CONFIG_RTE_MACHINE="native" CONFIG_RTE_ARCH="x86_x32" CONFIG_RTE_ARCH_X86_X32=y CONFIG_RTE_TOOLCHAIN="gcc" CONFIG_RTE_TOOLCHAIN_GCC=y # # KNI is not supported on 32-bit # CONFIG_RTE_LIBRTE_KNI=n ================================================ FILE: doc/api/doxy-api-index.md ================================================ API {#index} === There are many libraries, so their headers may be grouped by topics: - **device**: [dev] (@ref rte_dev.h), [ethdev] (@ref rte_ethdev.h), [ethctrl] (@ref rte_eth_ctrl.h), [devargs] (@ref rte_devargs.h), [bond] (@ref rte_eth_bond.h), [vhost] (@ref rte_virtio_net.h), [KNI] (@ref rte_kni.h), [PCI] (@ref rte_pci.h), [PCI IDs] (@ref rte_pci_dev_ids.h) - **memory**: [memseg] (@ref rte_memory.h), [memzone] (@ref rte_memzone.h), [mempool] (@ref rte_mempool.h), [malloc] (@ref rte_malloc.h), [memcpy] (@ref rte_memcpy.h) - **timers**: [cycles] (@ref rte_cycles.h), [timer] (@ref rte_timer.h), [alarm] (@ref rte_alarm.h) - **locks**: [atomic] (@ref rte_atomic.h), [rwlock] (@ref rte_rwlock.h), [spinlock] (@ref rte_spinlock.h) - **CPU arch**: [branch prediction] (@ref rte_branch_prediction.h), [cache prefetch] (@ref rte_prefetch.h), [byte order] (@ref rte_byteorder.h), [CPU flags] (@ref rte_cpuflags.h) - **CPU multicore**: [interrupts] (@ref rte_interrupts.h), [launch] (@ref rte_launch.h), [lcore] (@ref rte_lcore.h), [per-lcore] (@ref rte_per_lcore.h), [power/freq] (@ref rte_power.h) - **layers**: [ethernet] (@ref rte_ether.h), [ARP] (@ref rte_arp.h), [ICMP] (@ref rte_icmp.h), [IP] (@ref rte_ip.h), [SCTP] (@ref rte_sctp.h), [TCP] (@ref rte_tcp.h), [UDP] (@ref rte_udp.h), [frag/reass] (@ref rte_ip_frag.h), [LPM IPv4 route] (@ref rte_lpm.h), [LPM IPv6 route] (@ref rte_lpm6.h), [ACL] (@ref rte_acl.h) - **QoS**: [metering] (@ref rte_meter.h), [scheduler] (@ref rte_sched.h), [RED congestion] (@ref rte_red.h) - **hashes**: [hash] (@ref rte_hash.h), [jhash] (@ref rte_jhash.h), [thash] (@ref rte_thash.h), [FBK hash] (@ref rte_fbk_hash.h), [CRC hash] (@ref rte_hash_crc.h) - **containers**: [mbuf] (@ref rte_mbuf.h), [ring] (@ref rte_ring.h), [distributor] (@ref rte_distributor.h), [reorder] (@ref rte_reorder.h), [tailq] (@ref rte_tailq.h), [bitmap] (@ref rte_bitmap.h), [ivshmem] (@ref rte_ivshmem.h) - **packet framework**: * [port] (@ref rte_port.h): [ethdev] (@ref rte_port_ethdev.h), [ring] (@ref rte_port_ring.h), [frag] (@ref rte_port_frag.h), [reass] (@ref rte_port_ras.h), [sched] (@ref rte_port_sched.h), [src/sink] (@ref rte_port_source_sink.h) * [table] (@ref rte_table.h): [lpm IPv4] (@ref rte_table_lpm.h), [lpm IPv6] (@ref rte_table_lpm_ipv6.h), [ACL] (@ref rte_table_acl.h), [hash] (@ref rte_table_hash.h), [array] (@ref rte_table_array.h), [stub] (@ref rte_table_stub.h) * [pipeline] (@ref rte_pipeline.h) - **basic**: [approx fraction] (@ref rte_approx.h), [random] (@ref rte_random.h), [config file] (@ref rte_cfgfile.h), [key/value args] (@ref rte_kvargs.h), [string] (@ref rte_string_fns.h) - **debug**: [jobstats] (@ref rte_jobstats.h), [hexdump] (@ref rte_hexdump.h), [debug] (@ref rte_debug.h), [log] (@ref rte_log.h), [warnings] (@ref rte_warnings.h), [errno] (@ref rte_errno.h) - **misc**: [EAL config] (@ref rte_eal.h), [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [version] (@ref rte_version.h) ================================================ FILE: doc/api/doxy-api.conf ================================================ # BSD LICENSE # # Copyright 2013 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PROJECT_NAME = DPDK INPUT = doc/api/doxy-api-index.md \ drivers/net/bonding \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ lib/librte_distributor \ lib/librte_ether \ lib/librte_hash \ lib/librte_ip_frag \ lib/librte_ivshmem \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ lib/librte_net \ lib/librte_pipeline \ lib/librte_port \ lib/librte_power \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost FILE_PATTERNS = rte_*.h \ cmdline.h PREDEFINED = __DOXYGEN__ \ __attribute__(x)= OPTIMIZE_OUTPUT_FOR_C = YES ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES EXTRACT_STATIC = YES DISTRIBUTE_GROUP_DOC = YES HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_SCOPE_NAMES = YES GENERATE_DEPRECATEDLIST = NO VERBATIM_HEADERS = NO ALPHABETICAL_INDEX = NO HTML_TIMESTAMP = NO HTML_DYNAMIC_SECTIONS = YES SEARCHENGINE = NO SORT_MEMBER_DOCS = NO SOURCE_BROWSER = YES ================================================ FILE: doc/api/doxy-html-custom.sh ================================================ #! /bin/sh -e # BSD LICENSE # # Copyright 2013 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. CSS=$1 # space between item and its comment echo 'dd td:first-child {padding-right: 2em;}' >> $CSS ================================================ FILE: doc/build-sdk-quick.txt ================================================ Basic build make config T=x86_64-native-linuxapp-gcc && make Build commands config get configuration from target template (T=) all same as build (default rule) build build in a configured directory clean remove files but keep configuration install build many targets (wildcard allowed) and install in DESTDIR uninstall remove all installed targets examples build examples for given targets (T=) examples_clean clean examples for given targets (T=) Build variables EXTRA_CPPFLAGS preprocessor options EXTRA_CFLAGS compiler options EXTRA_LDFLAGS linker options EXTRA_LDLIBS linker library options RTE_KERNELDIR linux headers path CROSS toolchain prefix V verbose D debug dependencies O build directory (default: build/ - install default: ./) DESTDIR second-stage install directory T target template (install default: *) - used with config or install format: templates in config/defconfig_* ================================================ FILE: doc/guides/conf.py ================================================ # BSD LICENSE # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import subprocess from docutils import nodes from distutils.version import LooseVersion from sphinx import __version__ as sphinx_version from sphinx.highlighting import PygmentsBridge from pygments.formatters.latex import LatexFormatter project = 'DPDK' html_show_copyright = False highlight_language = 'none' version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion']).decode('utf-8') release = version master_doc = 'index' # Figures, tables and code-blocks automatically numbered if they have caption numfig = True latex_documents = [ ('index', 'doc.tex', '', '', 'manual') ] # Latex directives to be included directly in the latex/pdf docs. latex_preamble = r""" \usepackage[utf8]{inputenc} \usepackage{DejaVuSansMono} \usepackage[T1]{fontenc} \usepackage{helvet} \renewcommand{\familydefault}{\sfdefault} \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm} """ # Configuration for the latex/pdf docs. latex_elements = { 'papersize': 'a4paper', 'pointsize': '11pt', # remove blank pages 'classoptions': ',openany,oneside', 'babel': '\\usepackage[english]{babel}', # customize Latex formatting 'preamble': latex_preamble } # Override the default Latex formatter in order to modify the # code/verbatim blocks. class CustomLatexFormatter(LatexFormatter): def __init__(self, **options): super(CustomLatexFormatter, self).__init__(**options) # Use the second smallest font size for code/verbatim blocks. self.verboptions = r'formatcom=\footnotesize' # Replace the default latex formatter. PygmentsBridge.latex_formatter = CustomLatexFormatter ######## :numref: fallback ######## # The following hook functions add some simple handling for the :numref: # directive for Sphinx versions prior to 1.3.1. The functions replace the # :numref: reference with a link to the target (for all Sphinx doc types). # It doesn't try to label figures/tables. def numref_role(reftype, rawtext, text, lineno, inliner): """ Add a Sphinx role to handle numref references. Note, we can't convert the link here because the doctree isn't build and the target information isn't available. """ # Add an identifier to distinguish numref from other references. newnode = nodes.reference('', '', refuri='_local_numref_#%s' % text, internal=True) return [newnode], [] def process_numref(app, doctree, from_docname): """ Process the numref nodes once the doctree has been built and prior to writing the files. The processing involves replacing the numref with a link plus text to indicate if it is a Figure or Table link. """ # Iterate over the reference nodes in the doctree. for node in doctree.traverse(nodes.reference): target = node.get('refuri', '') # Look for numref nodes. if target.startswith('_local_numref_#'): target = target.replace('_local_numref_#', '') # Get the target label and link information from the Sphinx env. data = app.builder.env.domains['std'].data docname, label, _ = data['labels'].get(target, ('', '', '')) relative_url = app.builder.get_relative_uri(from_docname, docname) # Add a text label to the link. if target.startswith('figure'): caption = 'Figure' elif target.startswith('table'): caption = 'Table' else: caption = 'Link' # New reference node with the updated link information. newnode = nodes.reference('', caption, refuri='%s#%s' % (relative_url, label), internal=True) node.replace_self(newnode) def setup(app): if LooseVersion(sphinx_version) < LooseVersion('1.3.1'): print('Upgrade sphinx to version >= 1.3.1 for ' 'improved Figure/Table number handling.') # Add a role to handle :numref: references. app.add_role('numref', numref_role) # Process the numref references once the doctree has been created. app.connect('doctree-resolved', process_numref) ================================================ FILE: doc/guides/contributing/coding_style.rst ================================================ .. _coding_style: DPDK Coding Style ================= Description ----------- This document specifies the preferred style for source files in the DPDK source tree. It is based on the Linux Kernel coding guidelines and the FreeBSD 7.2 Kernel Developer's Manual (see man style(9)), but was heavily modified for the needs of the DPDK. General Guidelines ------------------ The rules and guidelines given in this document cannot cover every situation, so the following general guidelines should be used as a fallback: * The code style should be consistent within each individual file. * In the case of creating new files, the style should be consistent within each file in a given directory or module. * The primary reason for coding standards is to increase code readability and comprehensibility, therefore always use whatever option will make the code easiest to read. Line length is recommended to be not more than 80 characters, including comments. [Tab stop size should be assumed to be 8-characters wide]. .. note:: The above is recommendation, and not a hard limit. However, it is expected that the recommendations should be followed in all but the rarest situations. C Comment Style --------------- Usual Comments ~~~~~~~~~~~~~~ These comments should be used in normal cases. To document a public API, a doxygen-like format must be used: refer to :ref:`doxygen_guidelines`. .. code-block:: c /* * VERY important single-line comments look like this. */ /* Most single-line comments look like this. */ /* * Multi-line comments look like this. Make them real sentences. Fill * them so they look like real paragraphs. */ License Header ~~~~~~~~~~~~~~ Each file should begin with a special comment containing the appropriate copyright and license for the file. Generally this is the BSD License, except for code for Linux Kernel modules. After any copyright header, a blank line should be left before any other contents, e.g. include statements in a C file. C Preprocessor Directives ------------------------- Header Includes ~~~~~~~~~~~~~~~ In DPDK sources, the include files should be ordered as following: #. libc includes (system includes first) #. DPDK EAL includes #. DPDK misc libraries includes #. application-specific includes Include files from the local application directory are included using quotes, while includes from other paths are included using angle brackets: "<>". Example: .. code-block:: c #include #include #include #include #include #include "application.h" Header File Guards ~~~~~~~~~~~~~~~~~~ Headers should be protected against multiple inclusion with the usual: .. code-block:: c #ifndef _FILE_H_ #define _FILE_H_ /* Code */ #endif /* _FILE_H_ */ Macros ~~~~~~ Do not ``#define`` or declare names except with the standard DPDK prefix: ``RTE_``. This is to ensure there are no collisions with definitions in the application itself. The names of "unsafe" macros (ones that have side effects), and the names of macros for manifest constants, are all in uppercase. The expansions of expression-like macros are either a single token or have outer parentheses. If a macro is an inline expansion of a function, the function name is all in lowercase and the macro has the same name all in uppercase. If the macro encapsulates a compound statement, enclose it in a do-while loop, so that it can be used safely in if statements. Any final statement-terminating semicolon should be supplied by the macro invocation rather than the macro, to make parsing easier for pretty-printers and editors. For example: .. code-block:: c #define MACRO(x, y) do { \ variable = (x) + (y); \ (y) += 2; \ } while(0) .. note:: Wherever possible, enums and inline functions should be preferred to macros, since they provide additional degrees of type-safety and can allow compilers to emit extra warnings about unsafe code. Conditional Compilation ~~~~~~~~~~~~~~~~~~~~~~~ * When code is conditionally compiled using ``#ifdef`` or ``#if``, a comment may be added following the matching ``#endif`` or ``#else`` to permit the reader to easily discern where conditionally compiled code regions end. * This comment should be used only for (subjectively) long regions, regions greater than 20 lines, or where a series of nested ``#ifdef``'s may be confusing to the reader. Exceptions may be made for cases where code is conditionally not compiled for the purposes of lint(1), or other tools, even though the uncompiled region may be small. * The comment should be separated from the ``#endif`` or ``#else`` by a single space. * For short conditionally compiled regions, a closing comment should not be used. * The comment for ``#endif`` should match the expression used in the corresponding ``#if`` or ``#ifdef``. * The comment for ``#else`` and ``#elif`` should match the inverse of the expression(s) used in the preceding ``#if`` and/or ``#elif`` statements. * In the comments, the subexpression ``defined(FOO)`` is abbreviated as "FOO". For the purposes of comments, ``#ifndef FOO`` is treated as ``#if !defined(FOO)``. .. code-block:: c #ifdef KTRACE #include #endif #ifdef COMPAT_43 /* A large region here, or other conditional code. */ #else /* !COMPAT_43 */ /* Or here. */ #endif /* COMPAT_43 */ #ifndef COMPAT_43 /* Yet another large region here, or other conditional code. */ #else /* COMPAT_43 */ /* Or here. */ #endif /* !COMPAT_43 */ .. note:: Conditional compilation should be used only when absolutely necessary, as it increases the number of target binaries that need to be built and tested. C Types ------- Integers ~~~~~~~~ For fixed/minimum-size integer values, the project uses the form uintXX_t (from stdint.h) instead of older BSD-style integer identifiers of the form u_intXX_t. Enumerations ~~~~~~~~~~~~ * Enumeration values are all uppercase. .. code-block:: c enum enumtype { ONE, TWO } et; * Enum types should be used in preference to macros #defining a set of (sequential) values. * Enum types should be prefixed with ``rte_`` and the elements by a suitable prefix [generally starting ``RTE__`` - where is a shortname for the enum type] to avoid namespace collisions. Bitfields ~~~~~~~~~ The developer should group bitfields that are included in the same integer, as follows: .. code-block:: c struct grehdr { uint16_t rec:3, srr:1, seq:1, key:1, routing:1, csum:1, version:3, reserved:4, ack:1; /* ... */ } Variable Declarations ~~~~~~~~~~~~~~~~~~~~~ In declarations, do not put any whitespace between asterisks and adjacent tokens, except for tokens that are identifiers related to types. (These identifiers are the names of basic types, type qualifiers, and typedef-names other than the one being declared.) Separate these identifiers from asterisks using a single space. For example: .. code-block:: c int *x; /* no space after asterisk */ int * const x; /* space after asterisk when using a type qualifier */ * All externally-visible variables should have an ``rte_`` prefix in the name to avoid namespace collisions. * Do not use uppercase letters - either in the form of ALL_UPPERCASE, or CamelCase - in variable names. Lower-case letters and underscores only. Structure Declarations ~~~~~~~~~~~~~~~~~~~~~~ * In general, when declaring variables in new structures, declare them sorted by use, then by size (largest to smallest), and then in alphabetical order. Sorting by use means that commonly used variables are used together and that the structure layout makes logical sense. Ordering by size then ensures that as little padding is added to the structure as possible. * For existing structures, additions to structures should be added to the end so for backward compatibility reasons. * Each structure element gets its own line. * Try to make the structure readable by aligning the member names using spaces as shown below. * Names following extremely long types, which therefore cannot be easily aligned with the rest, should be separated by a single space. .. code-block:: c struct foo { struct foo *next; /* List of active foo. */ struct mumble amumble; /* Comment for mumble. */ int bar; /* Try to align the comments. */ struct verylongtypename *baz; /* Won't fit with other members */ }; * Major structures should be declared at the top of the file in which they are used, or in separate header files if they are used in multiple source files. * Use of the structures should be by separate variable declarations and those declarations must be extern if they are declared in a header file. * Externally visible structure definitions should have the structure name prefixed by ``rte_`` to avoid namespace collisions. Queues ~~~~~~ Use queue(3) macros rather than rolling your own lists, whenever possible. Thus, the previous example would be better written: .. code-block:: c #include struct foo { LIST_ENTRY(foo) link; /* Use queue macros for foo lists. */ struct mumble amumble; /* Comment for mumble. */ int bar; /* Try to align the comments. */ struct verylongtypename *baz; /* Won't fit with other members */ }; LIST_HEAD(, foo) foohead; /* Head of global foo list. */ DPDK also provides an optimized way to store elements in lockless rings. This should be used in all data-path code, when there are several consumer and/or producers to avoid locking for concurrent access. Typedefs ~~~~~~~~ Avoid using typedefs for structure types. For example, use: .. code-block:: c struct my_struct_type { /* ... */ }; struct my_struct_type my_var; rather than: .. code-block:: c typedef struct my_struct_type { /* ... */ } my_struct_type; my_struct_type my_var Typedefs are problematic because they do not properly hide their underlying type; for example, you need to know if the typedef is the structure itself, as shown above, or a pointer to the structure. In addition, they must be declared exactly once, whereas an incomplete structure type can be mentioned as many times as necessary. Typedefs are difficult to use in stand-alone header files. The header that defines the typedef must be included before the header that uses it, or by the header that uses it (which causes namespace pollution), or there must be a back-door mechanism for obtaining the typedef. Note that #defines used instead of typedefs also are problematic (since they do not propagate the pointer type correctly due to direct text replacement). For example, ``#define pint int *`` does not work as expected, while ``typedef int *pint`` does work. As stated when discussing macros, typedefs should be preferred to macros in cases like this. When convention requires a typedef; make its name match the struct tag. Avoid typedefs ending in ``_t``, except as specified in Standard C or by POSIX. .. note:: It is recommended to use typedefs to define function pointer types, for reasons of code readability. This is especially true when the function type is used as a parameter to another function. For example: .. code-block:: c /** * Definition of a remote launch function. */ typedef int (lcore_function_t)(void *); /* launch a function of lcore_function_t type */ int rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned slave_id); C Indentation ------------- General ~~~~~~~ * Indentation is a hard tab, that is, a tab character, not a sequence of spaces, .. note:: Global whitespace rule in DPDK, use tabs for indentation, spaces for alignment. * Do not put any spaces before a tab for indentation. * If you have to wrap a long statement, put the operator at the end of the line, and indent again. * For control statements (if, while, etc.), continuation it is recommended that the next line be indented by two tabs, rather than one, to prevent confusion as to whether the second line of the control statement forms part of the statement body or not. Alternatively, the line continuation may use additional spaces to line up to an appropriately point on the preceding line, for example, to align to an opening brace. .. note:: As with all style guidelines, code should match style already in use in an existing file. .. code-block:: c while (really_long_variable_name_1 == really_long_variable_name_2 && var3 == var4){ /* confusing to read as */ x = y + z; /* control stmt body lines up with second line of */ a = b + c; /* control statement itself if single indent used */ } if (really_long_variable_name_1 == really_long_variable_name_2 && var3 == var4){ /* two tabs used */ x = y + z; /* statement body no longer lines up */ a = b + c; } z = a + really + long + statement + that + needs + two + lines + gets + indented + on + the + second + and + subsequent + lines; * Do not add whitespace at the end of a line. * Do not add whitespace or a blank line at the end of a file. Control Statements and Loops ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Include a space after keywords (if, while, for, return, switch). * Do not use braces (``{`` and ``}``) for control statements with zero or just a single statement, unless that statement is more than a single line in which case the braces are permitted. .. code-block:: c for (p = buf; *p != '\0'; ++p) ; /* nothing */ for (;;) stmt; for (;;) { z = a + really + long + statement + that + needs + two + lines + gets + indented + on + the + second + and + subsequent + lines; } for (;;) { if (cond) stmt; } if (val != NULL) val = realloc(val, newsize); * Parts of a for loop may be left empty. .. code-block:: c for (; cnt < 15; cnt++) { stmt1; stmt2; } * Closing and opening braces go on the same line as the else keyword. * Braces that are not necessary should be left out. .. code-block:: c if (test) stmt; else if (bar) { stmt; stmt; } else stmt; Function Calls ~~~~~~~~~~~~~~ * Do not use spaces after function names. * Commas should have a space after them. * No spaces after ``(`` or ``[`` or preceding the ``]`` or ``)`` characters. .. code-block:: c error = function(a1, a2); if (error != 0) exit(error); Operators ~~~~~~~~~ * Unary operators do not require spaces, binary operators do. * Do not use parentheses unless they are required for precedence or unless the statement is confusing without them. However, remember that other people may be more easily confused than you. Exit ~~~~ Exits should be 0 on success, or 1 on failure. .. code-block:: c exit(0); /* * Avoid obvious comments such as * "Exit 0 on success." */ } Local Variables ~~~~~~~~~~~~~~~ * Variables should be declared at the start of a block of code rather than in the middle. The exception to this is when the variable is ``const`` in which case the declaration must be at the point of first use/assignment. * When declaring variables in functions, multiple variables per line are OK. However, if multiple declarations would cause the line to exceed a reasonable line length, begin a new set of declarations on the next line rather than using a line continuation. * Be careful to not obfuscate the code by initializing variables in the declarations, only the last variable on a line should be initialized. If multiple variables are to be initialised when defined, put one per line. * Do not use function calls in initializers, except for ``const`` variables. .. code-block:: c int i = 0, j = 0, k = 0; /* bad, too many initializer */ char a = 0; /* OK, one variable per line with initializer */ char b = 0; float x, y = 0.0; /* OK, only last variable has initializer */ Casts and sizeof ~~~~~~~~~~~~~~~~ * Casts and sizeof statements are not followed by a space. * Always write sizeof statements with parenthesis. The redundant parenthesis rules do not apply to sizeof(var) instances. C Function Definition, Declaration and Use ------------------------------------------- Prototypes ~~~~~~~~~~ * It is recommended (and generally required by the compiler) that all non-static functions are prototyped somewhere. * Functions local to one source module should be declared static, and should not be prototyped unless absolutely necessary. * Functions used from other parts of code (external API) must be prototyped in the relevant include file. * Function prototypes should be listed in a logical order, preferably alphabetical unless there is a compelling reason to use a different ordering. * Functions that are used locally in more than one module go into a separate header file, for example, "extern.h". * Do not use the ``__P`` macro. * Functions that are part of an external API should be documented using Doxygen-like comments above declarations. See :ref:`doxygen_guidelines` for details. * Functions that are part of the external API must have an ``rte_`` prefix on the function name. * Do not use uppercase letters - either in the form of ALL_UPPERCASE, or CamelCase - in function names. Lower-case letters and underscores only. * When prototyping functions, associate names with parameter types, for example: .. code-block:: c void function1(int fd); /* good */ void function2(int); /* bad */ * Short function prototypes should be contained on a single line. Longer prototypes, e.g. those with many parameters, can be split across multiple lines. The second and subsequent lines should be further indented as for line statement continuations as described in the previous section. .. code-block:: c static char *function1(int _arg, const char *_arg2, struct foo *_arg3, struct bar *_arg4, struct baz *_arg5); static void usage(void); .. note:: Unlike function definitions, the function prototypes do not need to place the function return type on a separate line. Definitions ~~~~~~~~~~~ * The function type should be on a line by itself preceding the function. * The opening brace of the function body should be on a line by itself. .. code-block:: c static char * function(int a1, int a2, float fl, int a4) { * Do not declare functions inside other functions. ANSI C states that such declarations have file scope regardless of the nesting of the declaration. Hiding file declarations in what appears to be a local scope is undesirable and will elicit complaints from a good compiler. * Old-style (K&R) function declaration should not be used, use ANSI function declarations instead as shown below. * Long argument lists should be wrapped as described above in the function prototypes section. .. code-block:: c /* * All major routines should have a comment briefly describing what * they do. The comment before the "main" routine should describe * what the program does. */ int main(int argc, char *argv[]) { char *ep; long num; int ch; C Statement Style and Conventions --------------------------------- NULL Pointers ~~~~~~~~~~~~~ * NULL is the preferred null pointer constant. Use NULL instead of ``(type *)0`` or ``(type *)NULL``, except where the compiler does not know the destination type e.g. for variadic args to a function. * Test pointers against NULL, for example, use: .. code-block:: c if (p == NULL) /* Good, compare pointer to NULL */ if (!p) /* Bad, using ! on pointer */ * Do not use ! for tests unless it is a boolean, for example, use: .. code-block:: c if (*p == '\0') /* check character against (char)0 */ Return Value ~~~~~~~~~~~~ * Functions which create objects, or allocate memory, should return pointer types, and NULL on error. The error type should be indicated may setting the variable ``rte_errno`` appropriately. * Functions which work on bursts of packets, such as RX-like or TX-like functions, should return the number of packets handled. * Other functions returning int should generally behave like system calls: returning 0 on success and -1 on error, setting ``rte_errno`` to indicate the specific type of error. * Where already standard in a given library, the alternative error approach may be used where the negative value is not -1 but is instead ``-errno`` if relevant, for example, ``-EINVAL``. Note, however, to allow consistency across functions returning integer or pointer types, the previous approach is preferred for any new libraries. * For functions where no error is possible, the function type should be ``void`` not ``int``. * Routines returning ``void *`` should not have their return values cast to any pointer type. (Typecasting can prevent the compiler from warning about missing prototypes as any implicit definition of a function returns int, which, unlike ``void *``, needs a typecast to assign to a pointer variable.) .. note:: The above rule about not typecasting ``void *`` applies to malloc, as well as to DPDK functions. * Values in return statements should not be enclosed in parentheses. Logging and Errors ~~~~~~~~~~~~~~~~~~ In the DPDK environment, use the logging interface provided: .. code-block:: c #define RTE_LOGTYPE_TESTAPP1 RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_TESTAPP2 RTE_LOGTYPE_USER2 /* enable these logs type */ rte_set_log_type(RTE_LOGTYPE_TESTAPP1, 1); rte_set_log_type(RTE_LOGTYPE_TESTAPP2, 1); /* log in debug level */ rte_set_log_level(RTE_LOG_DEBUG); RTE_LOG(DEBUG, TESTAPP1, "this is is a debug level message\n"); RTE_LOG(INFO, TESTAPP1, "this is is a info level message\n"); RTE_LOG(WARNING, TESTAPP1, "this is is a warning level message\n"); /* log in info level */ rte_set_log_level(RTE_LOG_INFO); RTE_LOG(DEBUG, TESTAPP2, "debug level message (not displayed)\n"); Branch Prediction ~~~~~~~~~~~~~~~~~ * When a test is done in a critical zone (called often or in a data path) the code can use the ``likely()`` and ``unlikely()`` macros to indicate the expected, or preferred fast path. They are expanded as a compiler builtin and allow the developer to indicate if the branch is likely to be taken or not. Example: .. code-block:: c #include if (likely(x > 1)) do_stuff(); .. note:: The use of ``likely()`` and ``unlikely()`` should only be done in performance critical paths, and only when there is a clearly preferred path, or a measured performance increase gained from doing so. These macros should be avoided in non-performance-critical code. Static Variables and Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * All functions and variables that are local to a file must be declared as ``static`` because it can often help the compiler to do some optimizations (such as, inlining the code). * Functions that should be inlined should to be declared as ``static inline`` and can be defined in a .c or a .h file. .. note:: Static functions defined in a header file must be declared as ``static inline`` in order to prevent compiler warnings about the function being unused. Const Attribute ~~~~~~~~~~~~~~~ The ``const`` attribute should be used as often as possible when a variable is read-only. Inline ASM in C code ~~~~~~~~~~~~~~~~~~~~ The ``asm`` and ``volatile`` keywords do not have underscores. The AT&T syntax should be used. Input and output operands should be named to avoid confusion, as shown in the following example: .. code-block:: c asm volatile("outb %[val], %[port]" : : [port] "dN" (port), [val] "a" (val)); Control Statements ~~~~~~~~~~~~~~~~~~ * Forever loops are done with for statements, not while statements. * Elements in a switch statement that cascade should have a FALLTHROUGH comment. For example: .. code-block:: c switch (ch) { /* Indent the switch. */ case 'a': /* Don't indent the case. */ aflag = 1; /* Indent case body one tab. */ /* FALLTHROUGH */ case 'b': bflag = 1; break; case '?': default: usage(); /* NOTREACHED */ } ================================================ FILE: doc/guides/contributing/design.rst ================================================ Design ====== Environment or Architecture-specific Sources -------------------------------------------- In DPDK and DPDK applications, some code is specific to an architecture (i686, x86_64) or to an executive environment (bsdapp or linuxapp) and so on. As far as is possible, all such instances of architecture or env-specific code should be provided via standard APIs in the EAL. By convention, a file is common if it is not located in a directory indicating that it is specific. For instance, a file located in a subdir of "x86_64" directory is specific to this architecture. A file located in a subdir of "linuxapp" is specific to this execution environment. .. note:: Code in DPDK libraries and applications should be generic. The correct location for architecture or executive environment specific code is in the EAL. When absolutely necessary, there are several ways to handle specific code: * Use a ``#ifdef`` with the CONFIG option in the C code. This can be done when the differences are small and they can be embedded in the same C file: .. code-block: console #ifdef RTE_ARCH_I686 toto(); #else titi(); #endif * Use the CONFIG option in the Makefile. This is done when the differences are more significant. In this case, the code is split into two separate files that are architecture or environment specific. This should only apply inside the EAL library. .. note: As in the linux kernel, the "CONFIG_" prefix is not used in C code. This is only needed in Makefiles or shell scripts. Per Architecture Sources ~~~~~~~~~~~~~~~~~~~~~~~~ The following config options can be used: * CONFIG_RTE_ARCH is a string that contains the name of the architecture. * CONFIG_RTE_ARCH_I686, CONFIG_RTE_ARCH_X86_64, CONFIG_RTE_ARCH_X86_64_32 or CONFIG_RTE_ARCH_PPC_64 are defined only if we are building for those architectures. Per Execution Environment Sources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following config options can be used: * CONFIG_RTE_EXEC_ENV is a string that contains the name of the executive environment. * CONFIG_RTE_EXEC_ENV_BSDAPP or CONFIG_RTE_EXEC_ENV_LINUXAPP are defined only if we are building for this execution environment. Library Statistics ------------------ Description ~~~~~~~~~~~ This document describes the guidelines for DPDK library-level statistics counter support. This includes guidelines for turning library statistics on and off and requirements for preventing ABI changes when implementing statistics. Mechanism to allow the application to turn library statistics on and off ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Each library that maintains statistics counters should provide a single build time flag that decides whether the statistics counter collection is enabled or not. This flag should be exposed as a variable within the DPDK configuration file. When this flag is set, all the counters supported by current library are collected for all the instances of every object type provided by the library. When this flag is cleared, none of the counters supported by the current library are collected for any instance of any object type provided by the library: .. code-block:: console # DPDK file config/common_linuxapp, config/common_bsdapp, etc. CONFIG_RTE__STATS_COLLECT=y/n The default value for this DPDK configuration file variable (either "yes" or "no") is decided by each library. Prevention of ABI changes due to library statistics support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The layout of data structures and prototype of functions that are part of the library API should not be affected by whether the collection of statistics counters is turned on or off for the current library. In practical terms, this means that space should always be allocated in the API data structures for statistics counters and the statistics related API functions are always built into the code, regardless of whether the statistics counter collection is turned on or off for the current library. When the collection of statistics counters for the current library is turned off, the counters retrieved through the statistics related API functions should have a default value of zero. Motivation to allow the application to turn library statistics on and off ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is highly recommended that each library provides statistics counters to allow an application to monitor the library-level run-time events. Typical counters are: number of packets received/dropped/transmitted, number of buffers allocated/freed, number of occurrences for specific events, etc. However, the resources consumed for library-level statistics counter collection have to be spent out of the application budget and the counters collected by some libraries might not be relevant to the current application. In order to avoid any unwanted waste of resources and/or performance impacts, the application should decide at build time whether the collection of library-level statistics counters should be turned on or off for each library individually. Library-level statistics counters can be relevant or not for specific applications: * For Application A, counters maintained by Library X are always relevant and the application needs to use them to implement certain features, such as traffic accounting, logging, application-level statistics, etc. In this case, the application requires that collection of statistics counters for Library X is always turned on. * For Application B, counters maintained by Library X are only useful during the application debug stage and are not relevant once debug phase is over. In this case, the application may decide to turn on the collection of Library X statistics counters during the debug phase and at a later stage turn them off. * For Application C, counters maintained by Library X are not relevant at all. It might be that the application maintains its own set of statistics counters that monitor a different set of run-time events (e.g. number of connection requests, number of active users, etc). It might also be that the application uses multiple libraries (Library X, Library Y, etc) and it is interested in the statistics counters of Library Y, but not in those of Library X. In this case, the application may decide to turn the collection of statistics counters off for Library X and on for Library Y. The statistics collection consumes a certain amount of CPU resources (cycles, cache bandwidth, memory bandwidth, etc) that depends on: * Number of libraries used by the current application that have statistics counters collection turned on. * Number of statistics counters maintained by each library per object type instance (e.g. per port, table, pipeline, thread, etc). * Number of instances created for each object type supported by each library. * Complexity of the statistics logic collection for each counter: when only some occurrences of a specific event are valid, additional logic is typically needed to decide whether the current occurrence of the event should be counted or not. For example, in the event of packet reception, when only TCP packets with destination port within a certain range should be recorded, conditional branches are usually required. When processing a burst of packets that have been validated for header integrity, counting the number of bits set in a bitmask might be needed. ================================================ FILE: doc/guides/contributing/documentation.rst ================================================ .. doc_guidelines: DPDK Documentation Guidelines ============================= This document outlines the guidelines for writing the DPDK Guides and API documentation in RST and Doxygen format. It also explains the structure of the DPDK documentation and shows how to build the Html and PDF versions of the documents. Structure of the Documentation ------------------------------ The DPDK source code repository contains input files to build the API documentation and User Guides. The main directories that contain files related to documentation are shown below:: lib |-- librte_acl |-- librte_cfgfile |-- librte_cmdline |-- librte_compat |-- librte_eal | |-- ... ... doc |-- api +-- guides |-- freebsd_gsg |-- linux_gsg |-- prog_guide |-- sample_app_ug |-- guidelines |-- testpmd_app_ug |-- rel_notes |-- nics |-- xen |-- ... The API documentation is built from `Doxygen `_ comments in the header files. These files are mainly in the ``lib/librte_*`` directories although some of the Poll Mode Drivers in ``drivers/net`` are also documented with Doxygen. The configuration files that are used to control the Doxygen output are in the ``doc/api`` directory. The user guides such as *The Programmers Guide* and the *FreeBSD* and *Linux Getting Started* Guides are generated from RST markup text files using the `Sphinx `_ Documentation Generator. These files are included in the ``doc/guides/`` directory. The output is controlled by the ``doc/guides/conf.py`` file. Role of the Documentation ------------------------- The following items outline the roles of the different parts of the documentation and when they need to be updated or added to by the developer. * **Release Notes** The Release Notes document which features have been added in the current and previous releases of DPDK and highlight any known issues. The Releases Notes also contain notifications of features that will change ABI compatibility in the next major release. Developers should update the Release Notes to add a short description of new or updated features. Developers should also update the Release Notes to add ABI announcements if necessary, (see :doc:`/contributing/versioning` for details). * **API documentation** The API documentation explains how to use the public DPDK functions. The `API index page `_ shows the generated API documentation with related groups of functions. The API documentation should be updated via Doxygen comments when new functions are added. * **Getting Started Guides** The Getting Started Guides show how to install and configure DPDK and how to run DPDK based applications on different OSes. A Getting Started Guide should be added when DPDK is ported to a new OS. * **The Programmers Guide** The Programmers Guide explains how the API components of DPDK such as the EAL, Memzone, Rings and the Hash Library work. It also explains how some higher level functionality such as Packet Distributor, Packet Framework and KNI work. It also shows the build system and explains how to add applications. The Programmers Guide should be expanded when new functionality is added to DPDK. * **App Guides** The app guides document the DPDK applications in the ``app`` directory such as ``testpmd``. The app guides should be updated if functionality is changed or added. * **Sample App Guides** The sample app guides document the DPDK example applications in the examples directory. Generally they demonstrate a major feature such as L2 or L3 Forwarding, Multi Process or Power Management. They explain the purpose of the sample application, how to run it and step through some of the code to explain the major functionality. A new sample application should be accompanied by a new sample app guide. The guide for the Skeleton Forwarding app is a good starting reference. * **Network Interface Controller Drivers** The NIC Drivers document explains the features of the individual Poll Mode Drivers, such as software requirements, configuration and initialization. New documentation should be added for new Poll Mode Drivers. * **Guidelines** The guideline documents record community process, expectations and design directions. They can be extended, amended or discussed by submitting a patch and getting community approval. Building the Documentation -------------------------- Dependencies ~~~~~~~~~~~~ The following dependencies must be installed to build the documentation: * Doxygen. * Sphinx (also called python-sphinx). * TexLive (at least TexLive-core, extra Latex support and extra fonts). * Inkscape. `Doxygen`_ generates documentation from commented source code. It can be installed as follows: .. code-block:: console # Ubuntu/Debian. sudo apt-get -y install doxygen # Red Hat/Fedora. sudo yum -y install doxygen `Sphinx`_ is a Python documentation tool for converting RST files to Html or to PDF (via LaTeX). It can be installed as follows: .. code-block:: console # Ubuntu/Debian. sudo apt-get -y install python-sphinx # Red Hat/Fedora. sudo yum -y install python-sphinx # Or, on any system with Python installed. sudo easy_install -U sphinx For further information on getting started with Sphinx see the `Sphinx Tutorial `_. .. Note:: To get full support for Figure and Table numbering it is best to install Sphinx 1.3.1 or later. `Inkscape`_ is a vector based graphics program which is used to create SVG images and also to convert SVG images to PDF images. It can be installed as follows: .. code-block:: console # Ubuntu/Debian. sudo apt-get -y install inkscape # Red Hat/Fedora. sudo yum -y install inkscape `TexLive `_ is an installation package for Tex/LaTeX. It is used to generate the PDF versions of the documentation. The main required packages can be installed as follows: .. code-block:: console # Ubuntu/Debian. sudo apt-get -y install texlive-latex-extra texlive-fonts-extra \ texlive-fonts-recommended # Red Hat/Fedora, selective install. sudo yum -y install texlive-collection-latexextra \ texlive-collection-fontsextra Build commands ~~~~~~~~~~~~~~ The documentation is built using the standard DPDK build system. Some examples are shown below: * Generate all the documentation targets:: make doc * Generate the Doxygen API documentation in Html:: make doc-api-html * Generate the guides documentation in Html:: make doc-guides-html * Generate the guides documentation in Pdf:: make doc-guides-pdf The output of these commands is generated in the ``build`` directory:: build/doc |-- html | |-- api | +-- guides | +-- pdf +-- guides .. Note:: Make sure to fix any Sphinx or Doxygen warnings when adding or updating documentation. The documentation output files can be removed as follows:: make doc-clean Document Guidelines ------------------- Here are some guidelines in relation to the style of the documentation: * Document the obvious as well as the obscure since it won't always be obvious to the reader. For example an instruction like "Set up 64 2MB Hugepages" is better when followed by a sample commandline or a link to the appropriate section of the documentation. * Use American English spellings throughout. This can be checked using the ``aspell`` utility:: aspell --lang=en_US --check doc/guides/sample_app_ug/mydoc.rst RST Guidelines -------------- The RST (reStructuredText) format is a plain text markup format that can be converted to Html, PDF or other formats. It is most closely associated with Python but it can be used to document any language. It is used in DPDK to document everything apart from the API. The Sphinx documentation contains a very useful `RST Primer `_ which is a good place to learn the minimal set of syntax required to format a document. The official `reStructuredText `_ website contains the specification for the RST format and also examples of how to use it. However, for most developers the RST Primer is a better resource. The most common guidelines for writing RST text are detailed in the `Documenting Python `_ guidelines. The additional guidelines below reiterate or expand upon those guidelines. Line Length ~~~~~~~~~~~ * The recommended style for the DPDK documentation is to put sentences on separate lines. This allows for easier reviewing of patches. Multiple sentences which are not separated by a blank line are joined automatically into paragraphs, for example:: Here is an example sentence. Long sentences over the limit shown below can be wrapped onto a new line. These three sentences will be joined into the same paragraph. This is a new paragraph, since it is separated from the previous paragraph by a blank line. This would be rendered as follows: *Here is an example sentence. Long sentences over the limit shown below can be wrapped onto a new line. These three sentences will be joined into the same paragraph.* *This is a new paragraph, since it is separated from the previous paragraph by a blank line.* * Long sentences should be wrapped at 120 characters +/- 10 characters. They should be wrapped at words. * Lines in literal blocks must by less than 80 characters since they aren't wrapped by the document formatters and can exceed the page width in PDF documents. Whitespace ~~~~~~~~~~ * Standard RST indentation is 3 spaces. Code can be indented 4 spaces, especially if it is copied from source files. * No tabs. Convert tabs in embedded code to 4 or 8 spaces. * No trailing whitespace. * Add 2 blank lines before each section header. * Add 1 blank line after each section header. * Add 1 blank line between each line of a list. Section Headers ~~~~~~~~~~~~~~~ * Section headers should use the use the following underline formats:: Level 1 Heading =============== Level 2 Heading --------------- Level 3 Heading ~~~~~~~~~~~~~~~ Level 4 Heading ^^^^^^^^^^^^^^^ * Level 4 headings should be used sparingly. * The underlines should match the length of the text. * In general, the heading should be less than 80 characters, for conciseness. * As noted above: * Add 2 blank lines before each section header. * Add 1 blank line after each section header. Lists ~~~~~ * Bullet lists should be formatted with a leading ``*`` as follows:: * Item one. * Item two is a long line that is wrapped and then indented to match the start of the previous line. * One space character between the bullet and the text is preferred. * Numbered lists can be formatted with a leading number but the preference is to use ``#.`` which will give automatic numbering. This is more convenient when adding or removing items:: #. Item one. #. Item two is a long line that is wrapped and then indented to match the start of the e first line. #. Item two is a long line that is wrapped and then indented to match the start of the previous line. * Definition lists can be written with or without a bullet:: * Item one. Some text about item one. * Item two. Some text about item two. * All lists, and sub-lists, must be separated from the preceding text by a blank line. This is a syntax requirement. * All list items should be separated by a blank line for readability. Code and Literal block sections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Inline text that is required to be rendered with a fixed width font should be enclosed in backquotes like this: \`\`text\`\`, so that it appears like this: ``text``. * Fixed width, literal blocks of texts should be indented at least 3 spaces and prefixed with ``::`` like this:: Here is some fixed width text:: 0x0001 0x0001 0x00FF 0x00FF * It is also possible to specify an encoding for a literal block using the ``.. code-block::`` directive so that syntax highlighting can be applied. Examples of supported highlighting are:: .. code-block:: console .. code-block:: c .. code-block:: python .. code-block:: diff .. code-block:: none That can be applied as follows:: .. code-block:: c #include int main() { printf("Hello World\n"); return 0; } Which would be rendered as: .. code-block:: c #include int main() { printf("Hello World\n"); return 0; } * The default encoding for a literal block using the simplified ``::`` directive is ``none``. * Lines in literal blocks must be less than 80 characters since they can exceed the page width when converted to PDF documentation. For long literal lines that exceed that limit try to wrap the text at sensible locations. For example a long command line could be documented like this and still work if copied directly from the docs:: build/app/testpmd -c7 -n3 --vdev=eth_pcap0,iface=eth0 \ --vdev=eth_pcap1,iface=eth1 \ -- -i --nb-cores=2 --nb-ports=2 \ --total-num-mbufs=2048 * Long lines that cannot be wrapped, such as application output, should be truncated to be less than 80 characters. Images ~~~~~~ * All images should be in SVG scalar graphics format. They should be true SVG XML files and should not include binary formats embedded in a SVG wrapper. * The DPDK documentation contains some legacy images in PNG format. These will be converted to SVG in time. * `Inkscape `_ is the recommended graphics editor for creating the images. Use some of the older images in ``doc/guides/prog_guide/img/`` as a template, for example ``mbuf1.svg`` or ``ring-enqueue.svg``. * The SVG images should include a copyright notice, as an XML comment. * Images in the documentation should be formatted as follows: * The image should be preceded by a label in the format ``.. _figure_XXXX:`` with a leading underscore and where ``XXXX`` is a unique descriptive name. * Images should be included using the ``.. figure::`` directive and the file type should be set to ``*`` (not ``.svg``). This allows the format of the image to be changed if required, without updating the documentation. * Images must have a caption as part of the ``.. figure::`` directive. * Here is an example of the previous three guidelines:: .. _figure_mempool: .. figure:: img/mempool.* A mempool in memory with its associated ring. .. _mock_label: * Images can then be linked to using the ``:numref:`` directive:: The mempool layout is shown in :numref:`figure_mempool`. This would be rendered as: *The mempool layout is shown in* :ref:`Fig 6.3 `. **Note**: The ``:numref:`` directive requires Sphinx 1.3.1 or later. With earlier versions it will still be rendered as a link but won't have an automatically generated number. * The caption of the image can be generated, with a link, using the ``:ref:`` directive:: :ref:`figure_mempool` This would be rendered as: *A mempool in memory with its associated ring.* Tables ~~~~~~ * RST tables should be used sparingly. They are hard to format and to edit, they are often rendered incorrectly in PDF format, and the same information can usually be shown just as clearly with a definition or bullet list. * Tables in the documentation should be formatted as follows: * The table should be preceded by a label in the format ``.. _table_XXXX:`` with a leading underscore and where ``XXXX`` is a unique descriptive name. * Tables should be included using the ``.. table::`` directive and must have a caption. * Here is an example of the previous two guidelines:: .. _table_qos_pipes: .. table:: Sample configuration for QOS pipes. +----------+----------+----------+ | Header 1 | Header 2 | Header 3 | | | | | +==========+==========+==========+ | Text | Text | Text | +----------+----------+----------+ | ... | ... | ... | +----------+----------+----------+ * Tables can be linked to using the ``:numref:`` and ``:ref:`` directives, as shown in the previous section for images. For example:: The QOS configuration is shown in :numref:`table_qos_pipes`. * Tables should not include merged cells since they are not supported by the PDF renderer. .. _links: Hyperlinks ~~~~~~~~~~ * Links to external websites can be plain URLs. The following is rendered as http://dpdk.org:: http://dpdk.org * They can contain alternative text. The following is rendered as `Check out DPDK `_:: `Check out DPDK `_ * An internal link can be generated by placing labels in the document with the format ``.. _label_name``. * The following links to the top of this section: :ref:`links`:: .. _links: Hyperlinks ~~~~~~~~~~ * The following links to the top of this section: :ref:`links`: .. Note:: The label must have a leading underscore but the reference to it must omit it. This is a frequent cause of errors and warnings. * The use of a label is preferred since it works across files and will still work if the header text changes. .. _doxygen_guidelines: Doxygen Guidelines ------------------ The DPDK API is documented using Doxygen comment annotations in the header files. Doxygen is a very powerful tool, it is extremely configurable and with a little effort can be used to create expressive documents. See the `Doxygen website `_ for full details on how to use it. The following are some guidelines for use of Doxygen in the DPDK API documentation: * New libraries that are documented with Doxygen should be added to the Doxygen configuration file: ``doc/api/doxy-api.conf``. It is only required to add the directory that contains the files. It isn't necessary to explicitly name each file since the configuration matches all ``rte_*.h`` files in the directory. * Use proper capitalization and punctuation in the Doxygen comments since they will become sentences in the documentation. This in particular applies to single line comments, which is the case the is most often forgotten. * Use ``@`` style Doxygen commands instead of ``\`` style commands. * Add a general description of each library at the head of the main header files: .. code-block:: c /** * @file * RTE Mempool. * * A memory pool is an allocator of fixed-size object. It is * identified by its name, and uses a ring to store free objects. * ... */ * Document the purpose of a function, the parameters used and the return value: .. code-block:: c /** * Attach a new Ethernet device specified by arguments. * * @param devargs * A pointer to a strings array describing the new device * to be attached. The strings should be a pci address like * `0000:01:00.0` or **virtual** device name like `eth_pcap0`. * @param port_id * A pointer to a port identifier actually attached. * * @return * 0 on success and port_id is filled, negative on error. */ int rte_eth_dev_attach(const char *devargs, uint8_t *port_id); * Doxygen supports Markdown style syntax such as bold, italics, fixed width text and lists. For example the second line in the ``devargs`` parameter in the previous example will be rendered as: The strings should be a pci address like ``0000:01:00.0`` or **virtual** device name like ``eth_pcap0``. * Use ``-`` instead of ``*`` for lists within the Doxygen comment since the latter can get confused with the comment delimiter. * Add an empty line between the function description, the ``@params`` and ``@return`` for readability. * Place the ``@params`` description on separate line and indent it by 2 spaces. (It would be better to use no indentation since this is more common and also because checkpatch complains about leading whitespace in comments. However this is the convention used in the existing DPDK code.) * Documented functions can be linked to simply by adding ``()`` to the function name: .. code-block:: c /** * The functions exported by the application Ethernet API to setup * a device designated by its port identifier must be invoked in * the following order: * - rte_eth_dev_configure() * - rte_eth_tx_queue_setup() * - rte_eth_rx_queue_setup() * - rte_eth_dev_start() */ In the API documentation the functions will be rendered as links, see the `online section of the rte_ethdev.h docs `_ that contains the above text. * The ``@see`` keyword can be used to create a *see also* link to another file or library. This directive should be placed on one line at the bottom of the documentation section. .. code-block:: c /** * ... * * Some text that references mempools. * * @see eal_memzone.c */ * Doxygen supports two types of comments for documenting variables, constants and members: prefix and postfix: .. code-block:: c /** This is a prefix comment. */ #define RTE_FOO_ERROR 0x023. #define RTE_BAR_ERROR 0x024. /**< This is a postfix comment. */ * Postfix comments are preferred for struct members and constants if they can be documented in the same way: .. code-block:: c struct rte_eth_stats { uint64_t ipackets; /**< Total number of received packets. */ uint64_t opackets; /**< Total number of transmitted packets.*/ uint64_t ibytes; /**< Total number of received bytes. */ uint64_t obytes; /**< Total number of transmitted bytes. */ uint64_t imissed; /**< Total of RX missed packets. */ uint64_t ibadcrc; /**< Total of RX packets with CRC error. */ uint64_t ibadlen; /**< Total of RX packets with bad length. */ } Note: postfix comments should be aligned with spaces not tabs in accordance with the :ref:`coding_style`. * If a single comment type can't be used, due to line length limitations then prefix comments should be preferred. For example this section of the code contains prefix comments, postfix comments on the same line and postfix comments on a separate line: .. code-block:: c /** Number of elements in the elt_pa array. */ uint32_t pg_num __rte_cache_aligned; uint32_t pg_shift; /**< LOG2 of the physical pages. */ uintptr_t pg_mask; /**< Physical page mask value. */ uintptr_t elt_va_start; /**< Virtual address of the first mempool object. */ uintptr_t elt_va_end; /**< Virtual address of the mempool object. */ phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT]; /**< Array of physical page addresses for the mempool buffer. */ This doesn't have an effect on the rendered documentation but it is confusing for the developer reading the code. It this case it would be clearer to use prefix comments throughout: .. code-block:: c /** Number of elements in the elt_pa array. */ uint32_t pg_num __rte_cache_aligned; /** LOG2 of the physical pages. */ uint32_t pg_shift; /** Physical page mask value. */ uintptr_t pg_mask; /** Virtual address of the first mempool object. */ uintptr_t elt_va_start; /** Virtual address of the mempool object. */ uintptr_t elt_va_end; /** Array of physical page addresses for the mempool buffer. */ phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT]; * Check for Doxygen warnings in new code by checking the API documentation build:: make doc-api-html >/dev/null * Read the rendered section of the documentation that you have added for correctness, clarity and consistency with the surrounding text. ================================================ FILE: doc/guides/contributing/index.rst ================================================ Contributor's Guidelines ======================== .. toctree:: :maxdepth: 2 :numbered: coding_style design versioning documentation ================================================ FILE: doc/guides/contributing/versioning.rst ================================================ Managing ABI updates ==================== Description ----------- This document details some methods for handling ABI management in the DPDK. Note this document is not exhaustive, in that C library versioning is flexible allowing multiple methods to achieve various goals, but it will provide the user with some introductory methods General Guidelines ------------------ #. Whenever possible, ABI should be preserved #. The addition of symbols is generally not problematic #. The modification of symbols can generally be managed with versioning #. The removal of symbols generally is an ABI break and requires bumping of the LIBABIVER macro What is an ABI -------------- An ABI (Application Binary Interface) is the set of runtime interfaces exposed by a library. It is similar to an API (Application Programming Interface) but is the result of compilation. It is also effectively cloned when applications link to dynamic libraries. That is to say when an application is compiled to link against dynamic libraries, it is assumed that the ABI remains constant between the time the application is compiled/linked, and the time that it runs. Therefore, in the case of dynamic linking, it is critical that an ABI is preserved, or (when modified), done in such a way that the application is unable to behave improperly or in an unexpected fashion. The DPDK ABI policy ------------------- ABI versions are set at the time of major release labeling, and the ABI may change multiple times, without warning, between the last release label and the HEAD label of the git tree. ABI versions, once released, are available until such time as their deprecation has been noted in the Release Notes for at least one major release cycle. For example consider the case where the ABI for DPDK 2.0 has been shipped and then a decision is made to modify it during the development of DPDK 2.1. The decision will be recorded in the Release Notes for the DPDK 2.1 release and the modification will be made available in the DPDK 2.2 release. ABI versions may be deprecated in whole or in part as needed by a given update. Some ABI changes may be too significant to reasonably maintain multiple versions. In those cases ABI's may be updated without backward compatibility being provided. The requirements for doing so are: #. At least 3 acknowledgments of the need to do so must be made on the dpdk.org mailing list. #. The changes (including an alternative map file) must be gated with the ``RTE_NEXT_ABI`` option, and provided with a deprecation notice at the same time. It will become the default ABI in the next release. #. A full deprecation cycle, as explained above, must be made to offer downstream consumers sufficient warning of the change. #. At the beginning of the next release cycle, every ``RTE_NEXT_ABI`` conditions will be removed, the ``LIBABIVER`` variable in the makefile(s) where the ABI is changed will be incremented, and the map files will be updated. Note that the above process for ABI deprecation should not be undertaken lightly. ABI stability is extremely important for downstream consumers of the DPDK, especially when distributed in shared object form. Every effort should be made to preserve the ABI whenever possible. The ABI should only be changed for significant reasons, such as performance enhancements. ABI breakage due to changes such as reorganizing public structure fields for aesthetic or readability purposes should be avoided. Examples of Deprecation Notices ------------------------------- The following are some examples of ABI deprecation notices which would be added to the Release Notes: * The Macro ``#RTE_FOO`` is deprecated and will be removed with version 2.0, to be replaced with the inline function ``rte_foo()``. * The function ``rte_mbuf_grok()`` has been updated to include a new parameter in version 2.0. Backwards compatibility will be maintained for this function until the release of version 2.1 * The members of ``struct rte_foo`` have been reorganized in release 2.0 for performance reasons. Existing binary applications will have backwards compatibility in release 2.0, while newly built binaries will need to reference the new structure variant ``struct rte_foo2``. Compatibility will be removed in release 2.2, and all applications will require updating and rebuilding to the new structure at that time, which will be renamed to the original ``struct rte_foo``. * Significant ABI changes are planned for the ``librte_dostuff`` library. The upcoming release 2.0 will not contain these changes, but release 2.1 will, and no backwards compatibility is planned due to the extensive nature of these changes. Binaries using this library built prior to version 2.1 will require updating and recompilation. Versioning Macros ----------------- When a symbol is exported from a library to provide an API, it also provides a calling convention (ABI) that is embodied in its name, return type and arguments. Occasionally that function may need to change to accommodate new functionality or behavior. When that occurs, it is desirable to allow for backward compatibility for a time with older binaries that are dynamically linked to the DPDK. To support backward compatibility the ``lib/librte_compat/rte_compat.h`` header file provides macros to use when updating exported functions. These macros are used in conjunction with the ``rte__version.map`` file for a given library to allow multiple versions of a symbol to exist in a shared library so that older binaries need not be immediately recompiled. The macros exported are: * ``VERSION_SYMBOL(b, e, n)``: Creates a symbol version table entry binding versioned symbol ``b@DPDK_n`` to the internal function ``b_e``. * ``BIND_DEFAULT_SYMBOL(b, e, n)``: Creates a symbol version entry instructing the linker to bind references to symbol ``b`` to the internal symbol ``b_e``. * ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the fully qualified function ``p``, so that if a symbol becomes versioned, it can still be mapped back to the public symbol name. Examples of ABI Macro use ------------------------- Updating a public API ~~~~~~~~~~~~~~~~~~~~~ Assume we have a function as follows .. code-block:: c /* * Create an acl context object for apps to * manipulate */ struct rte_acl_ctx * rte_acl_create(const struct rte_acl_param *param) { ... } Assume that struct rte_acl_ctx is a private structure, and that a developer wishes to enhance the acl api so that a debugging flag can be enabled on a per-context basis. This requires an addition to the structure (which, being private, is safe), but it also requires modifying the code as follows .. code-block:: c /* * Create an acl context object for apps to * manipulate */ struct rte_acl_ctx * rte_acl_create(const struct rte_acl_param *param, int debug) { ... } Note also that, being a public function, the header file prototype must also be changed, as must all the call sites, to reflect the new ABI footprint. We will maintain previous ABI versions that are accessible only to previously compiled binaries The addition of a parameter to the function is ABI breaking as the function is public, and existing application may use it in its current form. However, the compatibility macros in DPDK allow a developer to use symbol versioning so that multiple functions can be mapped to the same public symbol based on when an application was linked to it. To see how this is done, we start with the requisite libraries version map file. Initially the version map file for the acl library looks like this .. code-block:: none DPDK_2.0 { global: rte_acl_add_rules; rte_acl_build; rte_acl_classify; rte_acl_classify_alg; rte_acl_classify_scalar; rte_acl_create; rte_acl_dump; rte_acl_find_existing; rte_acl_free; rte_acl_ipv4vlan_add_rules; rte_acl_ipv4vlan_build; rte_acl_list_dump; rte_acl_reset; rte_acl_reset_rules; rte_acl_set_ctx_classify; local: *; }; This file needs to be modified as follows .. code-block:: none DPDK_2.0 { global: rte_acl_add_rules; rte_acl_build; rte_acl_classify; rte_acl_classify_alg; rte_acl_classify_scalar; rte_acl_create; rte_acl_dump; rte_acl_find_existing; rte_acl_free; rte_acl_ipv4vlan_add_rules; rte_acl_ipv4vlan_build; rte_acl_list_dump; rte_acl_reset; rte_acl_reset_rules; rte_acl_set_ctx_classify; local: *; }; DPDK_2.1 { global: rte_acl_create; } DPDK_2.0; The addition of the new block tells the linker that a new version node is available (DPDK_2.1), which contains the symbol rte_acl_create, and inherits the symbols from the DPDK_2.0 node. This list is directly translated into a list of exported symbols when DPDK is compiled as a shared library Next, we need to specify in the code which function map to the rte_acl_create symbol at which versions. First, at the site of the initial symbol definition, we need to update the function so that it is uniquely named, and not in conflict with the public symbol name .. code-block:: c struct rte_acl_ctx * -rte_acl_create(const struct rte_acl_param *param) +rte_acl_create_v20(const struct rte_acl_param *param) { size_t sz; struct rte_acl_ctx *ctx; ... Note that the base name of the symbol was kept intact, as this is condusive to the macros used for versioning symbols. That is our next step, mapping this new symbol name to the initial symbol name at version node 2.0. Immediately after the function, we add this line of code .. code-block:: c VERSION_SYMBOL(rte_acl_create, _v20, 2.0); Remembering to also add the rte_compat.h header to the requisite c file where these changes are being made. The above macro instructs the linker to create a new symbol ``rte_acl_create@DPDK_2.0``, which matches the symbol created in older builds, but now points to the above newly named function. We have now mapped the original rte_acl_create symbol to the original function (but with a new name) Next, we need to create the 2.1 version of the symbol. We create a new function name, with a different suffix, and implement it appropriately .. code-block:: c struct rte_acl_ctx * rte_acl_create_v21(const struct rte_acl_param *param, int debug); { struct rte_acl_ctx *ctx = rte_acl_create_v20(param); ctx->debug = debug; return ctx; } This code serves as our new API call. Its the same as our old call, but adds the new parameter in place. Next we need to map this function to the symbol ``rte_acl_create@DPDK_2.1``. To do this, we modify the public prototype of the call in the header file, adding the macro there to inform all including applications, that on re-link, the default rte_acl_create symbol should point to this function. Note that we could do this by simply naming the function above rte_acl_create, and the linker would chose the most recent version tag to apply in the version script, but we can also do this in the header file .. code-block:: c struct rte_acl_ctx * -rte_acl_create(const struct rte_acl_param *param); +rte_acl_create(const struct rte_acl_param *param, int debug); +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1); The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this header, to link to the rte_acl_create_v21 function and apply the DPDK_2.1 version node to it. This method is more explicit and flexible than just re-implementing the exact symbol name, and allows for other features (such as linking to the old symbol version by default, when the new ABI is to be opt-in for a period. One last thing we need to do. Note that we've taken what was a public symbol, and duplicated it into two uniquely and differently named symbols. We've then mapped each of those back to the public symbol ``rte_acl_create`` with different version tags. This only applies to dynamic linking, as static linking has no notion of versioning. That leaves this code in a position of no longer having a symbol simply named ``rte_acl_create`` and a static build will fail on that missing symbol. To correct this, we can simply map a function of our choosing back to the public symbol in the static build with the ``MAP_STATIC_SYMBOL`` macro. Generally the assumption is that the most recent version of the symbol is the one you want to map. So, back in the C file where, immediately after ``rte_acl_create_v21`` is defined, we add this .. code-block:: c struct rte_acl_create_v21(const struct rte_acl_param *param, int debug) { ... } MAP_STATIC_SYMBOL(struct rte_acl_create(const struct rte_acl_param *param, int debug), rte_acl_create_v21); That tells the compiler that, when building a static library, any calls to the symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21`` That's it, on the next shared library rebuild, there will be two versions of rte_acl_create, an old DPDK_2.0 version, used by previously built applications, and a new DPDK_2.1 version, used by future built applications. Deprecating part of a public API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Lets assume that you've done the above update, and after a few releases have passed you decide you would like to retire the old version of the function. After having gone through the ABI deprecation announcement process, removal is easy. Start by removing the symbol from the requisite version map file: .. code-block:: none DPDK_2.0 { global: rte_acl_add_rules; rte_acl_build; rte_acl_classify; rte_acl_classify_alg; rte_acl_classify_scalar; rte_acl_dump; - rte_acl_create rte_acl_find_existing; rte_acl_free; rte_acl_ipv4vlan_add_rules; rte_acl_ipv4vlan_build; rte_acl_list_dump; rte_acl_reset; rte_acl_reset_rules; rte_acl_set_ctx_classify; local: *; }; DPDK_2.1 { global: rte_acl_create; } DPDK_2.0; Next remove the corresponding versioned export .. code-block:: c -VERSION_SYMBOL(rte_acl_create, _v20, 2.0); Note that the internal function definition could also be removed, but its used in our example by the newer version _v21, so we leave it in place. This is a coding style choice. Lastly, we need to bump the LIBABIVER number for this library in the Makefile to indicate to applications doing dynamic linking that this is a later, and possibly incompatible library version: .. code-block:: c -LIBABIVER := 1 +LIBABIVER := 2 Deprecating an entire ABI version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ While removing a symbol from and ABI may be useful, it is often more practical to remove an entire version node at once. If a version node completely specifies an API, then removing part of it, typically makes it incomplete. In those cases it is better to remove the entire node To do this, start by modifying the version map file, such that all symbols from the node to be removed are merged into the next node in the map In the case of our map above, it would transform to look as follows .. code-block:: none DPDK_2.1 { global: rte_acl_add_rules; rte_acl_build; rte_acl_classify; rte_acl_classify_alg; rte_acl_classify_scalar; rte_acl_dump; rte_acl_create rte_acl_find_existing; rte_acl_free; rte_acl_ipv4vlan_add_rules; rte_acl_ipv4vlan_build; rte_acl_list_dump; rte_acl_reset; rte_acl_reset_rules; rte_acl_set_ctx_classify; local: *; }; Then any uses of BIND_DEFAULT_SYMBOL that pointed to the old node should be updated to point to the new version node in any header files for all affected symbols. .. code-block:: c -BIND_DEFAULT_SYMBOL(rte_acl_create, _v20, 2.0); +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 2.1); Lastly, any VERSION_SYMBOL macros that point to the old version node should be removed, taking care to keep, where need old code in place to support newer versions of the symbol. Running the ABI Validator ------------------------- The ``scripts`` directory in the DPDK source tree contains a utility program, ``validate-abi.sh``, for validating the DPDK ABI based on the Linux `ABI Compliance Checker `_. This has a dependency on the ``abi-compliance-checker`` and ``and abi-dumper`` utilities which can be installed via a package manager. For example:: sudo yum install abi-compliance-checker sudo yum install abi-dumper The syntax of the ``validate-abi.sh`` utility is:: ./scripts/validate-abi.sh Where ``TAG1`` and ``TAG2`` are valid git tags on the local repo and target is the usual DPDK compilation target. For example to test the current committed HEAD against a previous release tag we could add a temporary tag and run the utility as follows:: git tag MY_TEMP_TAG ./scripts/validate-abi.sh v2.0.0 MY_TEMP_TAG x86_64-native-linuxapp-gcc After the validation script completes (it can take a while since it need to compile both tags) it will create compatibility reports in the ``./compat_report`` directory. Listed incompatibilities can be found as follows:: grep -lr Incompatible compat_reports/ ================================================ FILE: doc/guides/faq/faq.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. What does "EAL: map_all_hugepages(): open failed: Permission denied Cannot init memory" mean? --------------------------------------------------------------------------------------------- This is most likely due to the test application not being run with sudo to promote the user to a superuser. Alternatively, applications can also be run as regular user. For more information, please refer to :ref:`DPDK Getting Started Guide `. If I want to change the number of TLB Hugepages allocated, how do I remove the original pages allocated? -------------------------------------------------------------------------------------------------------- The number of pages allocated can be seen by executing the following command:: grep Huge /proc/meminfo Once all the pages are mmapped by an application, they stay that way. If you start a test application with less than the maximum, then you have free pages. When you stop and restart the test application, it looks to see if the pages are available in the ``/dev/huge`` directory and mmaps them. If you look in the directory, you will see ``n`` number of 2M pages files. If you specified 1024, you will see 1024 page files. These are then placed in memory segments to get contiguous memory. If you need to change the number of pages, it is easier to first remove the pages. The tools/setup.sh script provides an option to do this. See the "Quick Start Setup Script" section in the :ref:`DPDK Getting Started Guide ` for more information. If I execute "l2fwd -c f -m 64 -n 3 -- -p 3", I get the following output, indicating that there are no socket 0 hugepages to allocate the mbuf and ring structures to? ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- I have set up a total of 1024 Hugepages (that is, allocated 512 2M pages to each NUMA node). The -m command line parameter does not guarantee that huge pages will be reserved on specific sockets. Therefore, allocated huge pages may not be on socket 0. To request memory to be reserved on a specific socket, please use the --socket-mem command-line parameter instead of -m. I am running a 32-bit DPDK application on a NUMA system, and sometimes the application initializes fine but cannot allocate memory. Why is that happening? ---------------------------------------------------------------------------------------------------------------------------------------------------------- 32-bit applications have limitations in terms of how much virtual memory is available, hence the number of hugepages they are able to allocate is also limited (1 GB per page size). If your system has a lot (>1 GB per page size) of hugepage memory, not all of it will be allocated. Due to hugepages typically being allocated on a local NUMA node, the hugepages allocation the application gets during the initialization depends on which NUMA node it is running on (the EAL does not affinitize cores until much later in the initialization process). Sometimes, the Linux OS runs the DPDK application on a core that is located on a different NUMA node from DPDK master core and therefore all the hugepages are allocated on the wrong socket. To avoid this scenario, either lower the amount of hugepage memory available to 1 GB per page size (or less), or run the application with taskset affinitizing the application to a would-be master core. For example, if your EAL coremask is 0xff0, the master core will usually be the first core in the coremask (0x10); this is what you have to supply to taskset:: taskset 0x10 ./l2fwd -c 0xff0 -n 2 In this way, the hugepages have a greater chance of being allocated to the correct socket. Additionally, a ``--socket-mem`` option could be used to ensure the availability of memory for each socket, so that if hugepages were allocated on the wrong socket, the application simply will not start. On application startup, there is a lot of EAL information printed. Is there any way to reduce this? --------------------------------------------------------------------------------------------------- Yes, each EAL has a configuration file that is located in the /config directory. Within each configuration file, you will find CONFIG_RTE_LOG_LEVEL=8. You can change this to a lower value, such as 6 to reduce this printout of debug information. The following is a list of LOG levels that can be found in the rte_log.h file. You must remove, then rebuild, the EAL directory for the change to become effective as the configuration file creates the rte_config.h file in the EAL directory. .. code-block:: c #define RTE_LOG_EMERG 1U /* System is unusable. */ #define RTE_LOG_ALERT 2U /* Action must be taken immediately. */ #define RTE_LOG_CRIT 3U /* Critical conditions. */ #define RTE_LOG_ERR 4U /* Error conditions. */ #define RTE_LOG_WARNING 5U /* Warning conditions. */ #define RTE_LOG_NOTICE 6U /* Normal but significant condition. */ #define RTE_LOG_INFO 7U /* Informational. */ #define RTE_LOG_DEBUG 8U /* Debug-level messages. */ How can I tune my network application to achieve lower latency? --------------------------------------------------------------- Traditionally, there is a trade-off between throughput and latency. An application can be tuned to achieve a high throughput, but the end-to-end latency of an average packet typically increases as a result. Similarly, the application can be tuned to have, on average, a low end-to-end latency at the cost of lower throughput. To achieve higher throughput, the DPDK attempts to aggregate the cost of processing each packet individually by processing packets in bursts. Using the testpmd application as an example, the "burst" size can be set on the command line to a value of 16 (also the default value). This allows the application to request 16 packets at a time from the PMD. The testpmd application then immediately attempts to transmit all the packets that were received, in this case, all 16 packets. The packets are not transmitted until the tail pointer is updated on the corresponding TX queue of the network port. This behavior is desirable when tuning for high throughput because the cost of tail pointer updates to both the RX and TX queues can be spread across 16 packets, effectively hiding the relatively slow MMIO cost of writing to the PCIe* device. However, this is not very desirable when tuning for low latency, because the first packet that was received must also wait for the other 15 packets to be received. It cannot be transmitted until the other 15 packets have also been processed because the NIC will not know to transmit the packets until the TX tail pointer has been updated, which is not done until all 16 packets have been processed for transmission. To consistently achieve low latency even under heavy system load, the application developer should avoid processing packets in bunches. The testpmd application can be configured from the command line to use a burst value of 1. This allows a single packet to be processed at a time, providing lower latency, but with the added cost of lower throughput. Without NUMA enabled, my network throughput is low, why? -------------------------------------------------------- I have a dual Intel® Xeon® E5645 processors 2.40 GHz with four Intel® 82599 10 Gigabit Ethernet NICs. Using eight logical cores on each processor with RSS set to distribute network load from two 10 GbE interfaces to the cores on each processor. Without NUMA enabled, memory is allocated from both sockets, since memory is interleaved. Therefore, each 64B chunk is interleaved across both memory domains. The first 64B chunk is mapped to node 0, the second 64B chunk is mapped to node 1, the third to node 0, the fourth to node 1. If you allocated 256B, you would get memory that looks like this: .. code-block:: console 256B buffer Offset 0x00 - Node 0 Offset 0x40 - Node 1 Offset 0x80 - Node 0 Offset 0xc0 - Node 1 Therefore, packet buffers and descriptor rings are allocated from both memory domains, thus incurring QPI bandwidth accessing the other memory and much higher latency. For best performance with NUMA disabled, only one socket should be populated. I am getting errors about not being able to open files. Why? ------------------------------------------------------------ As the DPDK operates, it opens a lot of files, which can result in reaching the open files limits, which is set using the ulimit command or in the limits.conf file. This is especially true when using a large number (>512) of 2 MB huge pages. Please increase the open file limit if your application is not able to open files. This can be done either by issuing a ulimit command or editing the limits.conf file. Please consult Linux* manpages for usage information. Does my kernel require patching to run the DPDK? ------------------------------------------------ Any kernel greater than version 2.6.33 can be used without any patches applied. The following kernels may require patches to provide hugepage support: * Kernel version 2.6.32 requires the following patches applied: * `mm: hugetlb: add hugepage support to pagemap `_ * `mm: hugetlb: fix hugepage memory leak in walk_page_range() `_ * `hugetlb: add nodemask arg to huge page alloc, free and surplus adjust functions `_ (not mandatory, but recommended on a NUMA system to support per-NUMA node hugepages allocation) * Kernel version 2.6.31, requires the above patches plus the following: * `UIO: Add name attributes for mappings and port regions `_ VF driver for IXGBE devices cannot be initialized ------------------------------------------------- Some versions of Linux* IXGBE driver do not assign a random MAC address to VF devices at initialization. In this case, this has to be done manually on the VM host, using the following command: .. code-block:: console ip link set vf mac where being the interface providing the virtual functions for example, eth0, being the virtual function number, for example 0, and being the desired MAC address. Is it safe to add an entry to the hash table while running? ------------------------------------------------------------ Currently the table implementation is not a thread safe implementation and assumes that locking between threads and processes is handled by the user's application. This is likely to be supported in future releases. What is the purpose of setting iommu=pt? ---------------------------------------- DPDK uses a 1:1 mapping and does not support IOMMU. IOMMU allows for simpler VM physical address translation. The second role of IOMMU is to allow protection from unwanted memory access by an unsafe device that has DMA privileges. Unfortunately, the protection comes with an extremely high performance cost for high speed NICs. Setting ``iommu=pt`` disables IOMMU support for the hypervisor. When trying to send packets from an application to itself, meaning smac==dmac, using Intel(R) 82599 VF packets are lost. ------------------------------------------------------------------------------------------------------------------------ Check on register ``LLE(PFVMTXSSW[n])``, which allows an individual pool to send traffic and have it looped back to itself. Can I split packet RX to use DPDK and have an application's higher order functions continue using Linux* pthread? ----------------------------------------------------------------------------------------------------------------- The DPDK's lcore threads are Linux* pthreads bound onto specific cores. Configure the DPDK to do work on the same cores and run the application's other work on other cores using the DPDK's "coremask" setting to specify which cores it should launch itself on. Is it possible to exchange data between DPDK processes and regular userspace processes via some shared memory or IPC mechanism? ------------------------------------------------------------------------------------------------------------------------------- Yes - DPDK processes are regular Linux/BSD processes, and can use all OS provided IPC mechanisms. Can the multiple queues in Intel(R) I350 be used with DPDK? ----------------------------------------------------------- I350 has RSS support and 8 queue pairs can be used in RSS mode. It should work with multi-queue DPDK applications using RSS. How can hugepage-backed memory be shared among multiple processes? ------------------------------------------------------------------ See the Primary and Secondary examples in the :ref:`multi-process sample application `. ================================================ FILE: doc/guides/faq/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK FAQ ======== This document contains some Frequently Asked Questions that arise when working with DPDK. Contents .. toctree:: :maxdepth: 2 :numbered: faq ================================================ FILE: doc/guides/freebsd_gsg/build_dpdk.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _building_from_source: Compiling the DPDK Target from Source ===================================== .. note:: Testing has been performed using FreeBSD* 10.0-RELEASE (x86_64) and requires the installation of the kernel sources, which should be included during the installation of FreeBSD*. The DPDK also requires the use of FreeBSD* ports to compile and function. System Requirements ------------------- The DPDK and its applications require the GNU make system (gmake) to build on FreeBSD*. Optionally, gcc may also be used in place of clang to build the DPDK, in which case it too must be installed prior to compiling the DPDK. The installation of these tools is covered in this section. Compiling the DPDK requires the FreeBSD kernel sources, which should be included during the installation of FreeBSD* on the development platform. The DPDK also requires the use of FreeBSD* ports to compile and function. To use the FreeBSD* ports system, it is required to update and extract the FreeBSD* ports tree by issuing the following commands: .. code-block:: console root@host:~ # portsnap fetch root@host:~ # portsnap extract If the environment requires proxies for external communication, these can be set using: .. code-block:: console root@host:~ # setenv http_proxy : root@host:~ # setenv ftp_proxy : The FreeBSD* ports below need to be installed prior to building the DPDK. In general these can be installed using the following set of commands: #. cd /usr/ports/ #. make config-recursive #. make install #. make clean Each port location can be found using: .. code-block:: console user@host:~ # whereis The ports required and their locations are as follows: dialog4ports /usr/ports/ports-mgmt/dialog4ports GNU make(gmake) /usr/ports/devel/gmake coreutils /usr/ports/sysutils/coreutils For compiling and using the DPDK with gcc, it too must be installed from the ports collection: gcc: version 4.8 is recommended /usr/ports/lang/gcc48 (Ensure that CPU_OPTS is selected (default is OFF)) When running the make config-recursive command, a dialog may be presented to the user. For the installation of the DPDK, the default options were used. .. note:: To avoid multiple dialogs being presented to the user during make install, it is advisable before running the make install command to re-run the make config -recursive command until no more dialogs are seen. Install the DPDK and Browse Sources ----------------------------------- First, uncompress the archive and move to the DPDK source directory: .. code-block:: console user@host:~ # unzip DPDK-zip user@host:~ # cd DPDK- user@host:~/DPDK # ls app/ config/ examples/ lib/ LICENSE.GPL LICENSE.LGPL Makefile mk/ scripts/ tools/ The DPDK is composed of several directories: * lib: Source code of DPDK libraries * app: Source code of DPDK applications (automatic tests) * examples: Source code of DPDK applications * config, tools, scripts, mk: Framework-related makefiles, scripts and configuration Installation of the DPDK Target Environments -------------------------------------------- The format of a DPDK target is: ARCH-MACHINE-EXECENV-TOOLCHAIN Where: * ARCH is: x86_64 * MACHINE is: native * EXECENV is: bsdapp * TOOLCHAIN is: gcc | clang The configuration files for the DPDK targets can be found in the DPDK/config directory in the form of: :: defconfig_ARCH-MACHINE-EXECENV-TOOLCHAIN .. note:: Configuration files are provided with the RTE_MACHINE optimization level set. Within the configuration files, the RTE_MACHINE configuration value is set to native, which means that the compiled software is tuned for the platform on which it is built. For more information on this setting, and its possible values, see the *DPDK Programmers Guide*. To install and make the target, use "gmake install T=". For example to compile for FreeBSD* use: .. code-block:: console gmake install T=x86_64-native-bsdapp-clang .. note:: If the compiler binary to be used does not correspond to that given in the TOOLCHAIN part of the target, the compiler command may need to be explicitly specified. For example, if compiling for gcc, where the gcc binary is called gcc4.8, the command would need to be "gmake install T= CC=gcc4.8". Browsing the Installed DPDK Environment Target ---------------------------------------------- Once a target is created, it contains all the libraries and header files for the DPDK environment that are required to build customer applications. In addition, the test and testpmd applications are built under the build/app directory, which may be used for testing. A kmod directory is also present that contains the kernel modules to install: .. code-block:: console user@host:~/DPDK # ls x86_64-native-bsdapp-gcc app build hostapp include kmod lib Makefile .. _loading_contigmem: Loading the DPDK contigmem Module --------------------------------- To run a DPDK application, physically contiguous memory is required. In the absence of non-transparent superpages, the included sources for the contigmem kernel module provides the ability to present contiguous blocks of memory for the DPDK to use. The contigmem module must be loaded into the running kernel before any DPDK is run. The module is found in the kmod sub-directory of the DPDK target directory. The amount of physically contiguous memory along with the number of physically contiguous blocks to be reserved by the module can be set at runtime prior to module loading using: .. code-block:: console root@host:~ # kenv hw.contigmem.num_buffers=n root@host:~ # kenv hw.contigmem.buffer_size=m The kernel environment variables can also be specified during boot by placing the following in /boot/loader.conf: :: hw.contigmem.num_buffers=n hw.contigmem.buffer_size=m The variables can be inspected using the following command: .. code-block:: console root@host:~ # sysctl -a hw.contigmem Where n is the number of blocks and m is the size in bytes of each area of contiguous memory. A default of two buffers of size 1073741824 bytes (1 Gigabyte) each is set during module load if they are not specified in the environment. The module can then be loaded using kldload (assuming that the current directory is the DPDK target directory): .. code-block:: console kldload ./kmod/contigmem.ko It is advisable to include the loading of the contigmem module during the boot process to avoid issues with potential memory fragmentation during later system up time. This can be achieved by copying the module to the /boot/kernel/ directory and placing the following into /boot/loader.conf: :: contigmem_load="YES" .. note:: The contigmem_load directive should be placed after any definitions of hw.contigmem.num_buffers and hw.contigmem.buffer_size if the default values are not to be used. An error such as: .. code-block:: console kldload: can't load ./x86_64-native-bsdapp-gcc/kmod/contigmem.ko: Exec format error is generally attributed to not having enough contiguous memory available and can be verified via dmesg or /var/log/messages: .. code-block:: console kernel: contigmalloc failed for buffer To avoid this error, reduce the number of buffers or the buffer size. .. _loading_nic_uio: Loading the DPDK nic_uio Module ------------------------------- After loading the contigmem module, the nic_uio must also be loaded into the running kernel prior to running any DPDK application. This module must be loaded using the kldload command as shown below (assuming that the current directory is the DPDK target directory). .. code-block:: console kldload ./kmod/nic_uio.ko .. note:: If the ports to be used are currently bound to a existing kernel driver then the hw.nic_uio.bdfs sysctl value will need to be set before loading the module. Setting this value is described in the next section below. Currently loaded modules can be seen by using the "kldstat" command and a module can be removed from the running kernel by using "kldunload ". To load the module during boot, copy the nic_uio module to /boot/kernel and place the following into /boot/loader.conf: :: nic_uio_load="YES" .. note:: nic_uio_load="YES" must appear after the contigmem_load directive, if it exists. By default, the nic_uio module will take ownership of network ports if they are recognized DPDK devices and are not owned by another module. However, since the FreeBSD kernel includes support, either built-in, or via a separate driver module, for most network card devices, it is likely that the ports to be used are already bound to a driver other than nic_uio. The following sub-section describe how to query and modify the device ownership of the ports to be used by DPDK applications. .. _binding_network_ports: Binding Network Ports to the nic_uio Module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Device ownership can be viewed using the pciconf -l command. The example below shows four Intel® 82599 network ports under "if_ixgbe" module ownership. .. code-block:: console user@host:~ # pciconf -l ix0@pci0:1:0:0: class=0x020000 card=0x00038086 chip=0x10fb8086 rev=0x01 hdr=0x00 ix1@pci0:1:0:1: class=0x020000 card=0x00038086 chip=0x10fb8086 rev=0x01 hdr=0x00 ix2@pci0:2:0:0: class=0x020000 card=0x00038086 chip=0x10fb8086 rev=0x01 hdr=0x00 ix3@pci0:2:0:1: class=0x020000 card=0x00038086 chip=0x10fb8086 rev=0x01 hdr=0x00 The first column constitutes three components: #. Device name: ixN #. Unit name: pci0 #. Selector (Bus:Device:Function): 1:0:0 Where no driver is associated with a device, the device name will be none. By default, the FreeBSD* kernel will include built-in drivers for the most common devices; a kernel rebuild would normally be required to either remove the drivers or configure them as loadable modules. To avoid building a custom kernel, the nic_uio module can detach a network port from its current device driver. This is achieved by setting the hw.nic_uio.bdfs kernel environment variable prior to loading nic_uio, as follows: :: hw.nic_uio.bdfs="b:d:f,b:d:f,..." Where a comma separated list of selectors is set, the list must not contain any whitespace. For example to re-bind "ix2\@pci0:2:0:0" and "ix3\@pci0:2:0:1" to the nic_uio module upon loading, use the following command: .. code-block:: console kenv hw.nic_uio.bdfs="2:0:0,2:0:1" The variable can also be specified during boot by placing the following into "/boot/loader.conf", before the previously-described "nic_uio_load" line - as shown. :: hw.nic_uio.bdfs="2:0:0,2:0:1" nic_uio_load="YES" Binding Network Ports Back to their Original Kernel Driver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the original driver for a network port has been compiled into the kernel, it is necessary to reboot FreeBSD* to restore the original device binding. Before doing so, update or remove the "hw.nic_uio.bdfs" in "/boot/loader.conf". If rebinding to a driver that is a loadable module, the network port binding can be reset without rebooting. To do so, unload both the target kernel module and the nic_uio module, modify or clear the "hw.nic_uio.bdfs" kernel environment (kenv) value, and reload the two drivers - first the original kernel driver, and then the nic_uio driver. [The latter does not need to be reloaded unless there are ports that are still to be bound to it]. Example commands to perform these steps are shown below: .. code-block:: console kldunload nic_uio kldunload kenv -u hw.nic_uio.bdfs # to clear the value completely kenv hw.nic_uio.bdfs="b:d:f,b:d:f,..." # to update the list of ports to bind kldload kldload nic_uio # optional ================================================ FILE: doc/guides/freebsd_gsg/build_sample_apps.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _compiling_sample_apps: Compiling and Running Sample Applications ========================================= The chapter describes how to compile and run applications in a DPDK environment. It also provides a pointer to where sample applications are stored. Compiling a Sample Application ------------------------------ Once a DPDK target environment directory has been created (such as x86_64-native-bsdapp-clang), it contains all libraries and header files required to build an application. When compiling an application in the FreeBSD* environment on the DPDK, the following variables must be exported: * RTE_SDK - Points to the DPDK installation directory. * RTE_TARGET - Points to the DPDK target environment directory. For FreeBSD*, this is the x86_64-native-bsdapp-clang or x86_64-native-bsdapp-gcc directory. The following is an example of creating the helloworld application, which runs in the DPDK FreeBSD* environment. While the example demonstrates compiling using gcc version 4.8, compiling with clang will be similar, except that the "CC=" parameter can probably be omitted. The "helloworld" example may be found in the ${RTE_SDK}/examples directory. The directory contains the main.c file. This file, when combined with the libraries in the DPDK target environment, calls the various functions to initialize the DPDK environment, then launches an entry point (dispatch application) for each core to be utilized. By default, the binary is generated in the build directory. .. code-block:: console user@host:~/DPDK$ cd examples/helloworld/ user@host:~/DPDK/examples/helloworld$ setenv RTE_SDK $HOME/DPDK user@host:~/DPDK/examples/helloworld$ setenv RTE_TARGET x86_64-native-bsdapp-gcc user@host:~/DPDK/examples/helloworld$ gmake CC=gcc48 CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map user@host:~/DPDK/examples/helloworld$ ls build/app helloworld helloworld.map .. note:: In the above example, helloworld was in the directory structure of the DPDK. However, it could have been located outside the directory structure to keep the DPDK structure intact. In the following case, the helloworld application is copied to a new directory as a new starting point. .. code-block:: console user@host:~$ setenv RTE_SDK /home/user/DPDK user@host:~$ cp -r $(RTE_SDK)/examples/helloworld my_rte_app user@host:~$ cd my_rte_app/ user@host:~$ setenv RTE_TARGET x86_64-native-bsdapp-gcc user@host:~/my_rte_app$ gmake CC=gcc48 CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map .. _running_sample_app: Running a Sample Application ---------------------------- #. The contigmem and nic_uio modules must be set up prior to running an application. #. Any ports to be used by the application must be already bound to the nic_uio module, as described in section :ref:`binding_network_ports`, prior to running the application. The application is linked with the DPDK target environment's Environment Abstraction Layer (EAL) library, which provides some options that are generic to every DPDK application. The following is the list of options that can be given to the EAL: .. code-block:: console ./rte-app -c COREMASK -n NUM [-b ] [-r NUM] [-v] [--proc-type ] .. note:: EAL has a common interface between all operating systems and is based on the Linux* notation for PCI devices. For example, a FreeBSD* device selector of pci0:2:0:1 is referred to as 02:00.1 in EAL. The EAL options for FreeBSD* are as follows: * -c COREMASK : A hexadecimal bit mask of the cores to run on. Note that core numbering can change between platforms and should be determined beforehand. * -n NUM : Number of memory channels per processor socket. * -b : blacklisting of ports; prevent EAL from using specified PCI device (multiple -b options are allowed). * --use-device : use the specified Ethernet device(s) only. Use comma-separate <[domain:]bus:devid.func> values. Cannot be used with -b option. * -r NUM : Number of memory ranks. * -v : Display version information on startup. * --proc-type : The type of process instance. Other options, specific to Linux* and are not supported under FreeBSD* are as follows: * socket-mem : Memory to allocate from hugepages on specific sockets. * --huge-dir : The directory where hugetlbfs is mounted. * --file-prefix : The prefix text used for hugepage filenames. * -m MB : Memory to allocate from hugepages, regardless of processor socket. It is recommended that --socket-mem be used instead of this option. The -c and the -n options are mandatory; the others are optional. Copy the DPDK application binary to your target, then run the application as follows (assuming the platform has four memory channels, and that cores 0-3 are present and are to be used for running the application): .. code-block:: console root@target:~$ ./helloworld -c f -n 4 .. note:: The --proc-type and --file-prefix EAL options are used for running multiple DPDK processes. See the “Multi-process Sample Application” chapter in the *DPDK Sample Applications User Guide and the DPDK Programmers Guide* for more details. .. _running_non_root: Running DPDK Applications Without Root Privileges ------------------------------------------------- Although applications using the DPDK use network ports and other hardware resources directly, with a number of small permission adjustments, it is possible to run these applications as a user other than “root”. To do so, the ownership, or permissions, on the following file system objects should be adjusted to ensure that the user account being used to run the DPDK application has access to them: * The userspace-io device files in /dev, for example, /dev/uio0, /dev/uio1, and so on * The userspace contiguous memory device: /dev/contigmem .. note:: Please refer to the DPDK Release Notes for supported applications. ================================================ FILE: doc/guides/freebsd_gsg/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _freebsd_gsg: Getting Started Guide for FreeBSD ================================= |today| **Contents** .. toctree:: :maxdepth: 2 :numbered: intro install_from_ports build_dpdk build_sample_apps ================================================ FILE: doc/guides/freebsd_gsg/install_from_ports.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _install_from_ports: Installing DPDK from the Ports Collection ========================================= The easiest way to get up and running with the DPDK on FreeBSD is to install it from the ports collection. Details of getting and using the ports collection are documented in the FreeBSD Handbook at: https://www.freebsd.org/doc/handbook/ports-using.html .. note:: Testing has been performed using FreeBSD* 10.0-RELEASE (x86_64) and requires the installation of the kernel sources, which should be included during the installation of FreeBSD*. Installing the DPDK FreeBSD Port -------------------------------- On a system with the ports collection installed in /usr/ports, the DPDK can be installed using the commands: .. code-block:: console root@host:~ # cd /usr/ports/net/dpdk root@host:~ # make install After the installation of the DPDK port, instructions will be printed on how to install the kernel modules required to use the DPDK. A more complete version of these instructions can be found in the sections :ref:`loading_contigmem` and :ref:`loading_nic_uio`. Normally, lines like those below would be added to the file "/boot/loader.conf". .. code-block:: console # reserve 2 x 1G blocks of contiguous memory using contigmem driver hw.contigmem.num_buffers=2 hw.contigmem.buffer_size=1073741824 contigmem_load="YES" # identify NIC devices for DPDK apps to use and load nic_uio driver hw.nic_uio.bdfs="2:0:0,2:0:1" nic_uio_load="YES" Compiling and Running the Example Applications ---------------------------------------------- When the DPDK has been installed from the ports collection it installs its example applications in "/usr/local/share/dpdk/examples" - also accessible via symlink as "/usr/local/share/examples/dpdk". These examples can be compiled and run as described in :ref:`compiling_sample_apps`. In this case, the required environmental variables should be set as below: * RTE_SDK=/usr/local/share/dpdk * RTE_TARGET=x86_64-native-bsdapp-clang .. note:: To install a copy of the DPDK compiled using gcc, please download the official DPDK package from http://dpdk.org/ and install manually using the instructions given in the next chapter, :ref:`building_from_source` An example application can therefore be copied to a user's home directory and compiled and run as below: .. code-block:: console user@host:~$ export RTE_SDK=/usr/local/share/dpdk user@host:~$ export RTE_TARGET=x86_64-native-bsdapp-clang user@host:~$ cp -r /usr/local/share/dpdk/examples/helloworld . user@host:~$ cd helloworld/ user@host:~/helloworld$ gmake CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map user@host:~/helloworld$ sudo ./build/helloworld -c F -n 2 EAL: Contigmem driver has 2 buffers, each of size 1GB EAL: Sysctl reports 8 cpus EAL: Detected lcore 0 EAL: Detected lcore 1 EAL: Detected lcore 2 EAL: Detected lcore 3 EAL: Support maximum 64 logical core(s) by configuration. EAL: Detected 4 lcore(s) EAL: Setting up physically contiguous memory... EAL: Mapped memory segment 1 @ 0x802400000: physaddr:0x40000000, len 1073741824 EAL: Mapped memory segment 2 @ 0x842400000: physaddr:0x100000000, len 1073741824 EAL: WARNING: clock_gettime cannot use CLOCK_MONOTONIC_RAW and HPET is not available - clock timings may be less accurate. EAL: TSC frequency is ~3569023 KHz EAL: PCI scan found 24 devices EAL: Master core 0 is ready (tid=0x802006400) EAL: Core 1 is ready (tid=0x802006800) EAL: Core 3 is ready (tid=0x802007000) EAL: Core 2 is ready (tid=0x802006c00) EAL: PCI device 0000:01:00.0 on NUMA socket 0 EAL: probe driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory mapped at 0x80074a000 EAL: PCI memory mapped at 0x8007ca000 EAL: PCI device 0000:01:00.1 on NUMA socket 0 EAL: probe driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory mapped at 0x8007ce000 EAL: PCI memory mapped at 0x80084e000 EAL: PCI device 0000:02:00.0 on NUMA socket 0 EAL: probe driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory mapped at 0x800852000 EAL: PCI memory mapped at 0x8008d2000 EAL: PCI device 0000:02:00.1 on NUMA socket 0 EAL: probe driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory mapped at 0x801b3f000 EAL: PCI memory mapped at 0x8008d6000 hello from core 1 hello from core 2 hello from core 3 hello from core 0 .. note:: To run a DPDK process as a non-root user, adjust the permissions on the /dev/contigmem and /dev/uio device nodes as described in section :ref:`running_non_root` .. note:: For an explanation of the command-line parameters that can be passed to an DPDK application, see section :ref:`running_sample_app`. ================================================ FILE: doc/guides/freebsd_gsg/intro.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ This document contains instructions for installing and configuring the Data Plane Development Kit (DPDK) software. It is designed to get customers up and running quickly and describes how to compile and run a DPDK application in a FreeBSD* application (bsdapp) environment, without going deeply into detail. For a comprehensive guide to installing and using FreeBSD*, the following handbook is available from the FreeBSD* Documentation Project: `http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/index.html `_ .. note:: The DPDK is now available as part of the FreeBSD ports collection. Installing via the ports collection infrastructure is now the recommended way to install the DPDK on FreeBSD, and is documented in the next chapter, :ref:`install_from_ports`. Documentation Roadmap --------------------- The following is a list of DPDK documents in the suggested reading order: * **Release Notes** : Provides release-specific information, including supported features, limitations, fixed issues, known issues and so on. Also, provides the answers to frequently asked questions in FAQ format. * **Getting Started Guide** (this document): Describes how to install and configure the DPDK; designed to get users up and running quickly with the software. * **Programmer's Guide**: Describes: * The software architecture and how to use it (through examples), specifically in a Linux* application (linuxapp) environment * The content of the DPDK, the build system (including the commands that can be used in the root DPDK Makefile to build the development kit and an application) and guidelines for porting an application * Optimizations used in the software and those that should be considered for new development A glossary of terms is also provided. * **API Reference**: Provides detailed information about DPDK functions, data structures and other programming constructs. * **Sample Applications User Guide**: Describes a set of sample applications. Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. .. note:: These documents are available for download as a separate documentation package at the same location as the DPDK code package. ================================================ FILE: doc/guides/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK documentation ================== Contents: .. toctree:: :maxdepth: 1 :titlesonly: linux_gsg/index freebsd_gsg/index xen/index prog_guide/index nics/index sample_app_ug/index testpmd_app_ug/index faq/index rel_notes/index contributing/index ================================================ FILE: doc/guides/linux_gsg/build_dpdk.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Compiling the DPDK Target from Source ===================================== .. note:: Parts of this process can also be done using the setup script described in Chapter 6 of this document. Install the DPDK and Browse Sources ----------------------------------- First, uncompress the archive and move to the uncompressed DPDK source directory: .. code-block:: console user@host:~$ unzip DPDK-.zip user@host:~$ cd DPDK- user@host:~/DPDK-$ ls app/ config/ drivers/ examples/ lib/ LICENSE.GPL LICENSE.LGPL Makefile mk/ scripts/ tools/ The DPDK is composed of several directories: * lib: Source code of DPDK libraries * drivers: Source code of DPDK poll-mode drivers * app: Source code of DPDK applications (automatic tests) * examples: Source code of DPDK application examples * config, tools, scripts, mk: Framework-related makefiles, scripts and configuration Installation of DPDK Target Environments ---------------------------------------- The format of a DPDK target is: ARCH-MACHINE-EXECENV-TOOLCHAIN where: * ARCH can be: i686, x86_64, ppc_64 * MACHINE can be: native, ivshmem, power8 * EXECENV can be: linuxapp, bsdapp * TOOLCHAIN can be: gcc, icc The targets to be installed depend on the 32-bit and/or 64-bit packages and compilers installed on the host. Available targets can be found in the DPDK/config directory. The defconfig\_ prefix should not be used. .. note:: Configuration files are provided with the RTE_MACHINE optimization level set. Within the configuration files, the RTE_MACHINE configuration value is set to native, which means that the compiled software is tuned for the platform on which it is built. For more information on this setting, and its possible values, see the *DPDK Programmers Guide*. When using the Intel® C++ Compiler (icc), one of the following commands should be invoked for 64-bit or 32-bit use respectively. Notice that the shell scripts update the $PATH variable and therefore should not be performed in the same session. Also, verify the compiler's installation directory since the path may be different: .. code-block:: console source /opt/intel/bin/iccvars.sh intel64 source /opt/intel/bin/iccvars.sh ia32 To install and make targets, use the make install T= command in the top-level DPDK directory. For example, to compile a 64-bit target using icc, run: .. code-block:: console make install T=x86_64-native-linuxapp-icc To compile a 32-bit build using gcc, the make command should be: .. code-block:: console make install T=i686-native-linuxapp-gcc To compile all 64-bit targets using gcc, use: .. code-block:: console make install T=x86_64*gcc To compile all 64-bit targets using both gcc and icc, use: .. code-block:: console make install T=x86_64-* .. note:: The wildcard operator (*) can be used to create multiple targets at the same time. To prepare a target without building it, for example, if the configuration changes need to be made before compilation, use the make config T= command: .. code-block:: console make config T=x86_64-native-linuxapp-gcc .. warning:: Any kernel modules to be used, e.g. igb_uio, kni, must be compiled with the same kernel as the one running on the target. If the DPDK is not being built on the target machine, the RTE_KERNELDIR environment variable should be used to point the compilation at a copy of the kernel version to be used on the target machine. Once the target environment is created, the user may move to the target environment directory and continue to make code changes and re-compile. The user may also make modifications to the compile-time DPDK configuration by editing the .config file in the build directory. (This is a build-local copy of the defconfig file from the top- level config directory). .. code-block:: console cd x86_64-native-linuxapp-gcc vi .config make In addition, the make clean command can be used to remove any existing compiled files for a subsequent full, clean rebuild of the code. Browsing the Installed DPDK Environment Target ---------------------------------------------- Once a target is created it contains all libraries, including poll-mode drivers, and header files for the DPDK environment that are required to build customer applications. In addition, the test and testpmd applications are built under the build/app directory, which may be used for testing. A kmod directory is also present that contains kernel modules which may be loaded if needed. .. code-block:: console $ ls x86_64-native-linuxapp-gcc app build hostapp include kmod lib Makefile Loading Modules to Enable Userspace IO for DPDK ----------------------------------------------- To run any DPDK application, a suitable uio module can be loaded into the running kernel. In many cases, the standard uio_pci_generic module included in the Linux kernel can provide the uio capability. This module can be loaded using the command .. code-block:: console sudo modprobe uio_pci_generic As an alternative to the uio_pci_generic, the DPDK also includes the igb_uio module which can be found in the kmod subdirectory referred to above. It can be loaded as shown below: .. code-block:: console sudo modprobe uio sudo insmod kmod/igb_uio.ko .. note:: For some devices which lack support for legacy interrupts, e.g. virtual function (VF) devices, the igb_uio module may be needed in place of uio_pci_generic. Since DPDK release 1.7 onward provides VFIO support, use of UIO is optional for platforms that support using VFIO. Loading VFIO Module ------------------- To run an DPDK application and make use of VFIO, the vfio-pci module must be loaded: .. code-block:: console sudo modprobe vfio-pci Note that in order to use VFIO, your kernel must support it. VFIO kernel modules have been included in the Linux kernel since version 3.6.0 and are usually present by default, however please consult your distributions documentation to make sure that is the case. Also, to use VFIO, both kernel and BIOS must support and be configured to use IO virtualization (such as Intel® VT-d). For proper operation of VFIO when running DPDK applications as a non-privileged user, correct permissions should also be set up. This can be done by using the DPDK setup script (called setup.sh and located in the tools directory). Binding and Unbinding Network Ports to/from the Kernel Modules ---------------------------------------------------------------------- As of release 1.4, DPDK applications no longer automatically unbind all supported network ports from the kernel driver in use. Instead, all ports that are to be used by an DPDK application must be bound to the uio_pci_generic, igb_uio or vfio-pci module before the application is run. Any network ports under Linux* control will be ignored by the DPDK poll-mode drivers and cannot be used by the application. .. warning:: The DPDK will, by default, no longer automatically unbind network ports from the kernel driver at startup. Any ports to be used by an DPDK application must be unbound from Linux* control and bound to the uio_pci_generic, igb_uio or vfio-pci module before the application is run. To bind ports to the uio_pci_generic, igb_uio or vfio-pci module for DPDK use, and then subsequently return ports to Linux* control, a utility script called dpdk_nic _bind.py is provided in the tools subdirectory. This utility can be used to provide a view of the current state of the network ports on the system, and to bind and unbind those ports from the different kernel modules, including the uio and vfio modules. The following are some examples of how the script can be used. A full description of the script and its parameters can be obtained by calling the script with the --help or --usage options. Note that the uio or vfio kernel modules to be used, should be loaded into the kernel before running the dpdk_nic_bind.py script. .. warning:: Due to the way VFIO works, there are certain limitations to which devices can be used with VFIO. Mainly it comes down to how IOMMU groups work. Any Virtual Function device can be used with VFIO on its own, but physical devices will require either all ports bound to VFIO, or some of them bound to VFIO while others not being bound to anything at all. If your device is behind a PCI-to-PCI bridge, the bridge will then be part of the IOMMU group in which your device is in. Therefore, the bridge driver should also be unbound from the bridge PCI device for VFIO to work with devices behind the bridge. .. warning:: While any user can run the dpdk_nic_bind.py script to view the status of the network ports, binding or unbinding network ports requires root privileges. To see the status of all network ports on the system: .. code-block:: console root@host:DPDK# ./tools/dpdk_nic_bind.py --status Network devices using DPDK-compatible driver ============================================ 0000:82:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=ixgbe 0000:82:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=ixgbe Network devices using kernel driver =================================== 0000:04:00.0 'I350 Gigabit Network Connection' if=em0 drv=igb unused=uio_pci_generic *Active* 0000:04:00.1 'I350 Gigabit Network Connection' if=eth1 drv=igb unused=uio_pci_generic 0000:04:00.2 'I350 Gigabit Network Connection' if=eth2 drv=igb unused=uio_pci_generic 0000:04:00.3 'I350 Gigabit Network Connection' if=eth3 drv=igb unused=uio_pci_generic Other network devices ===================== To bind device eth1, 04:00.1, to the uio_pci_generic driver: .. code-block:: console root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=uio_pci_generic 04:00.1 or, alternatively, .. code-block:: console root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=uio_pci_generic eth1 To restore device 82:00.0 to its original kernel binding: .. code-block:: console root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=ixgbe 82:00.0 ================================================ FILE: doc/guides/linux_gsg/build_sample_apps.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Compiling and Running Sample Applications ========================================= The chapter describes how to compile and run applications in an DPDK environment. It also provides a pointer to where sample applications are stored. .. note:: Parts of this process can also be done using the setup script described in **Chapter 6** of this document. Compiling a Sample Application ------------------------------ Once an DPDK target environment directory has been created (such as x86_64-native-linuxapp-gcc), it contains all libraries and header files required to build an application. When compiling an application in the Linux* environment on the DPDK, the following variables must be exported: * RTE_SDK - Points to the DPDK installation directory. * RTE_TARGET - Points to the DPDK target environment directory. The following is an example of creating the helloworld application, which runs in the DPDK Linux environment. This example may be found in the ${RTE_SDK}/examples directory. The directory contains the main.c file. This file, when combined with the libraries in the DPDK target environment, calls the various functions to initialize the DPDK environment, then launches an entry point (dispatch application) for each core to be utilized. By default, the binary is generated in the build directory. .. code-block:: console user@host:~/DPDK$ cd examples/helloworld/ user@host:~/DPDK/examples/helloworld$ export RTE_SDK=$HOME/DPDK user@host:~/DPDK/examples/helloworld$ export RTE_TARGET=x86_64-native-linuxapp-gcc user@host:~/DPDK/examples/helloworld$ make CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map user@host:~/DPDK/examples/helloworld$ ls build/app helloworld helloworld.map .. note:: In the above example, helloworld was in the directory structure of the DPDK. However, it could have been located outside the directory structure to keep the DPDK structure intact. In the following case, the helloworld application is copied to a new directory as a new starting point. .. code-block:: console user@host:~$ export RTE_SDK=/home/user/DPDK user@host:~$ cp -r $(RTE_SDK)/examples/helloworld my_rte_app user@host:~$ cd my_rte_app/ user@host:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc user@host:~/my_rte_app$ make CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map Running a Sample Application ---------------------------- .. warning:: The UIO drivers and hugepages must be setup prior to running an application. .. warning:: Any ports to be used by the application must be already bound to an appropriate kernel module, as described in Section 3.5, prior to running the application. The application is linked with the DPDK target environment's Environmental Abstraction Layer (EAL) library, which provides some options that are generic to every DPDK application. The following is the list of options that can be given to the EAL: .. code-block:: console ./rte-app -c COREMASK -n NUM [-b ] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type ] [-- xen-dom0] The EAL options are as follows: * -c COREMASK: An hexadecimal bit mask of the cores to run on. Note that core numbering can change between platforms and should be determined beforehand. * -n NUM: Number of memory channels per processor socket * -b : blacklisting of ports; prevent EAL from using specified PCI device (multiple -b options are allowed) * --use-device: use the specified Ethernet device(s) only. Use comma-separate <[domain:]bus:devid.func> values. Cannot be used with -b option * --socket-mem: Memory to allocate from hugepages on specific sockets * -m MB: Memory to allocate from hugepages, regardless of processor socket. It is recommended that --socket-mem be used instead of this option. * -r NUM: Number of memory ranks * -v: Display version information on startup * --huge-dir: The directory where hugetlbfs is mounted * --file-prefix: The prefix text used for hugepage filenames * --proc-type: The type of process instance * --xen-dom0: Support application running on Xen Domain0 without hugetlbfs * --vmware-tsc-map: use VMware TSC map instead of native RDTSC * --base-virtaddr: specify base virtual address * --vfio-intr: specify interrupt type to be used by VFIO (has no effect if VFIO is not used) The -c and the -n options are mandatory; the others are optional. Copy the DPDK application binary to your target, then run the application as follows (assuming the platform has four memory channels per processor socket, and that cores 0-3 are present and are to be used for running the application): .. code-block:: console user@target:~$ ./helloworld -c f -n 4 .. note:: The --proc-type and --file-prefix EAL options are used for running multiple DPDK processes. See the “Multi-process Sample Application” chapter in the *DPDK Sample Applications User Guide* and the *DPDK Programmers Guide* for more details. Logical Core Use by Applications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The coremask parameter is always mandatory for DPDK applications. Each bit of the mask corresponds to the equivalent logical core number as reported by Linux. Since these logical core numbers, and their mapping to specific cores on specific NUMA sockets, can vary from platform to platform, it is recommended that the core layout for each platform be considered when choosing the coremask to use in each case. On initialization of the EAL layer by an DPDK application, the logical cores to be used and their socket location are displayed. This information can also be determined for all cores on the system by examining the /proc/cpuinfo file, for example, by running cat /proc/cpuinfo. The physical id attribute listed for each processor indicates the CPU socket to which it belongs. This can be useful when using other processors to understand the mapping of the logical cores to the sockets. .. note:: A more graphical view of the logical core layout may be obtained using the lstopo Linux utility. On Fedora* Linux, this may be installed and run using the following command: .. code-block:: console sudo yum install hwloc ./lstopo .. warning:: The logical core layout can change between different board layouts and should be checked before selecting an application coremask. Hugepage Memory Use by Applications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When running an application, it is recommended to use the same amount of memory as that allocated for hugepages. This is done automatically by the DPDK application at startup, if no -m or --socket-mem parameter is passed to it when run. If more memory is requested by explicitly passing a -m or --socket-mem value, the application fails. However, the application itself can also fail if the user requests less memory than the reserved amount of hugepage-memory, particularly if using the -m option. The reason is as follows. Suppose the system has 1024 reserved 2 MB pages in socket 0 and 1024 in socket 1. If the user requests 128 MB of memory, the 64 pages may not match the constraints: * The hugepage memory by be given to the application by the kernel in socket 1 only. In this case, if the application attempts to create an object, such as a ring or memory pool in socket 0, it fails. To avoid this issue, it is recommended that the -- socket-mem option be used instead of the -m option. * These pages can be located anywhere in physical memory, and, although the DPDK EAL will attempt to allocate memory in contiguous blocks, it is possible that the pages will not be contiguous. In this case, the application is not able to allocate big memory pools. The socket-mem option can be used to request specific amounts of memory for specific sockets. This is accomplished by supplying the --socket-mem flag followed by amounts of memory requested on each socket, for example, supply --socket-mem=0,512 to try and reserve 512 MB for socket 1 only. Similarly, on a four socket system, to allocate 1 GB memory on each of sockets 0 and 2 only, the parameter --socket-mem=1024,0,1024 can be used. No memory will be reserved on any CPU socket that is not explicitly referenced, for example, socket 3 in this case. If the DPDK cannot allocate enough memory on each socket, the EAL initialization fails. Additional Sample Applications ------------------------------ Additional sample applications are included in the ${RTE_SDK}/examples directory. These sample applications may be built and run in a manner similar to that described in earlier sections in this manual. In addition, see the *DPDK Sample Applications User Guide* for a description of the application, specific instructions on compilation and execution and some explanation of the code. Additional Test Applications ---------------------------- In addition, there are two other applications that are built when the libraries are created. The source files for these are in the DPDK/app directory and are called test and testpmd. Once the libraries are created, they can be found in the build/app directory. * The test application provides a variety of specific tests for the various functions in the DPDK. * The testpmd application provides a number of different packet throughput tests and examples of features such as how to use the Flow Director found in the Intel® 82599 10 Gigabit Ethernet Controller. ================================================ FILE: doc/guides/linux_gsg/enable_func.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Enabling_Additional_Functionality: Enabling Additional Functionality ================================= .. _High_Precision_Event_Timer: High Precision Event Timer HPET) Functionality ---------------------------------------------- BIOS Support ~~~~~~~~~~~~ The High Precision Timer (HPET) must be enabled in the platform BIOS if the HPET is to be used. Otherwise, the Time Stamp Counter (TSC) is used by default. The BIOS is typically accessed by pressing F2 while the platform is starting up. The user can then navigate to the HPET option. On the Crystal Forest platform BIOS, the path is: **Advanced -> PCH-IO Configuration -> High Precision Timer ->** (Change from Disabled to Enabled if necessary). On a system that has already booted, the following command can be issued to check if HPET is enabled: .. code-block:: console # grep hpet /proc/timer_list If no entries are returned, HPET must be enabled in the BIOS (as per the instructions above) and the system rebooted. Linux Kernel Support ~~~~~~~~~~~~~~~~~~~~ The DPDK makes use of the platform HPET timer by mapping the timer counter into the process address space, and as such, requires that the HPET_MMAP kernel configuration option be enabled. .. warning:: On Fedora*, and other common distributions such as Ubuntu*, the HPET_MMAP kernel option is not enabled by default. To recompile the Linux kernel with this option enabled, please consult the distributions documentation for the relevant instructions. Enabling HPET in the DPDK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, HPET support is disabled in the DPDK build configuration files. To use HPET, the CONFIG_RTE_LIBEAL_USE_HPET setting should be changed to “y”, which will enable the HPET settings at compile time. For an application to use the rte_get_hpet_cycles() and rte_get_hpet_hz() API calls, and optionally to make the HPET the default time source for the rte_timer library, the new rte_eal_hpet_init() API call should be called at application initialization. This API call will ensure that the HPET is accessible, returning an error to the application if it is not, for example, if HPET_MMAP is not enabled in the kernel. The application can then determine what action to take, if any, if the HPET is not available at run-time. .. note:: For applications that require timing APIs, but not the HPET timer specifically, it is recommended that the rte_get_timer_cycles() and rte_get_timer_hz() API calls be used instead of the HPET-specific APIs. These generic APIs can work with either TSC or HPET time sources, depending on what is requested by an application call to rte_eal_hpet_init(), if any, and on what is available on the system at runtime. Running DPDK Applications Without Root Privileges -------------------------------------------------------- Although applications using the DPDK use network ports and other hardware resources directly, with a number of small permission adjustments it is possible to run these applications as a user other than “root”. To do so, the ownership, or permissions, on the following Linux file system objects should be adjusted to ensure that the Linux user account being used to run the DPDK application has access to them: * All directories which serve as hugepage mount points, for example, /mnt/huge * The userspace-io device files in /dev, for example, /dev/uio0, /dev/uio1, and so on * The userspace-io sysfs config and resource files, for example for uio0: /sys/class/uio/uio0/device/config /sys/class/uio/uio0/device/resource* * If the HPET is to be used, /dev/hpet .. note:: On some Linux installations, /dev/hugepages is also a hugepage mount point created by default. Power Management and Power Saving Functionality ----------------------------------------------- Enhanced Intel SpeedStep® Technology must be enabled in the platform BIOS if the power management feature of DPDK is to be used. Otherwise, the sys file folder /sys/devices/system/cpu/cpu0/cpufreq will not exist, and the CPU frequency- based power management cannot be used. Consult the relevant BIOS documentation to determine how these settings can be accessed. For example, on some Intel reference platform BIOS variants, the path to Enhanced Intel SpeedStep® Technology is: **Advanced->Processor Configuration->Enhanced Intel SpeedStep® Tech** In addition, C3 and C6 should be enabled as well for power management. The path of C3 and C6 on the same platform BIOS is: **Advanced->Processor Configuration->Processor C3 Advanced->Processor Configuration-> Processor C6** Using Linux* Core Isolation to Reduce Context Switches ------------------------------------------------------ While the threads used by an DPDK application are pinned to logical cores on the system, it is possible for the Linux scheduler to run other tasks on those cores also. To help prevent additional workloads from running on those cores, it is possible to use the isolcpus Linux* kernel parameter to isolate them from the general Linux scheduler. For example, if DPDK applications are to run on logical cores 2, 4 and 6, the following should be added to the kernel parameter list: .. code-block:: console isolcpus=2,4,6 Loading the DPDK KNI Kernel Module ----------------------------------------- To run the DPDK Kernel NIC Interface (KNI) sample application, an extra kernel module (the kni module) must be loaded into the running kernel. The module is found in the kmod sub-directory of the DPDK target directory. Similar to the loading of the igb_uio module, this module should be loaded using the insmod command as shown below (assuming that the current directory is the DPDK target directory): .. code-block:: console #insmod kmod/rte_kni.ko .. note:: See the “Kernel NIC Interface Sample Application” chapter in the *DPDK Sample Applications User Guide* for more details. Using Linux IOMMU Pass-Through to Run DPDK with Intel® VT-d ----------------------------------------------------------- To enable Intel® VT-d in a Linux kernel, a number of kernel configuration options must be set. These include: * IOMMU_SUPPORT * IOMMU_API * INTEL_IOMMU In addition, to run the DPDK with Intel® VT-d, the iommu=pt kernel parameter must be used when using igb_uio driver. This results in pass-through of the DMAR (DMA Remapping) lookup in the host. Also, if INTEL_IOMMU_DEFAULT_ON is not set in the kernel, the intel_iommu=on kernel parameter must be used too. This ensures that the Intel IOMMU is being initialized as expected. Please note that while using iommu=pt is compulsory for igb_uio driver, the vfio-pci driver can actually work with both iommu=pt and iommu=on. High Performance of Small Packets on 40G NIC -------------------------------------------- As there might be firmware fixes for performance enhancement in latest version of firmware image, the firmware update might be needed for getting high performance. Check with the local Intel's Network Division application engineers for firmware updates. The base driver to support firmware version of FVL3E will be integrated in the next DPDK release, so currently the validated firmware version is 4.2.6. Enabling Extended Tag and Setting Max Read Request Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PCI configurations of extended_tag and max _read_requ st_size have big impacts on performance of small packets on 40G NIC. Enabling extended_tag and setting max _read_requ st_size to small size such as 128 bytes provide great helps to high performance of small packets. * These can be done in some BIOS implementations. * For other BIOS implementations, PCI configurations can be changed by using command of setpci, or special configurations in DPDK config file of common_linux. * Bits 7:5 at address of 0xA8 of each PCI device is used for setting the max_read_request_size, and bit 8 of 0xA8 of each PCI device is used for enabling/disabling the extended_tag. lspci and setpci can be used to read the values of 0xA8 and then write it back after being changed. * In config file of common_linux, below three configurations can be changed for the same purpose. CONFIG_RTE_PCI_CONFIG CONFIG_RTE_PCI_EXTENDED_TAG CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE Use 16 Bytes RX Descriptor Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As i40e PMD supports both 16 and 32 bytes RX descriptor sizes, and 16 bytes size can provide helps to high performance of small packets. Configuration of CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC in config files can be changed to use 16 bytes size RX descriptors. High Performance and per Packet Latency Tradeoff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Due to the hardware design, the interrupt signal inside NIC is needed for per packet descriptor write-back. The minimum interval of interrupts could be set at compile time by CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL in configuration files. Though there is a default configuration, the interval could be tuned by the users with that configuration item depends on what the user cares about more, performance or per packet latency. ================================================ FILE: doc/guides/linux_gsg/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _linux_gsg: Getting Started Guide for Linux =============================== |today| Contents .. toctree:: :maxdepth: 2 :numbered: intro sys_reqs build_dpdk build_sample_apps enable_func quick_start ================================================ FILE: doc/guides/linux_gsg/intro.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ This document contains instructions for installing and configuring the Intel® Data Plane Development Kit (DPDK) software. It is designed to get customers up and running quickly. The document describes how to compile and run a DPDK application in a Linux* application (linuxapp) environment, without going deeply into detail. Documentation Roadmap --------------------- The following is a list of DPDK documents in the suggested reading order: * Release Notes: Provides release-specific information, including supported features, limitations, fixed issues, known issues and so on. Also, provides the answers to frequently asked questions in FAQ format. * Getting Started Guide (this document): Describes how to install and configure the DPDK; designed to get users up and running quickly with the software. * Programmer's Guide: Describes: * The software architecture and how to use it (through examples), specifically in a Linux* application (linuxapp) environment * The content of the DPDK, the build system (including the commands that can be used in the root DPDK Makefile to build the development kit and an application) and guidelines for porting an application * Optimizations used in the software and those that should be considered for new development A glossary of terms is also provided. * API Reference: Provides detailed information about DPDK functions, data structures and other programming constructs. * Sample Applications User Guide: Describes a set of sample applications. Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. .. note:: These documents are available for download as a separate documentation package at the same location as the DPDK code package. ================================================ FILE: doc/guides/linux_gsg/quick_start.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Quick Start Setup Script ======================== The setup.sh script, found in the tools subdirectory, allows the user to perform the following tasks: * Build the DPDK libraries * Insert and remove the DPDK IGB_UIO kernel module * Insert and remove VFIO kernel modules * Insert and remove the DPDK KNI kernel module * Create and delete hugepages for NUMA and non-NUMA cases * View network port status and reserve ports for DPDK application use * Set up permissions for using VFIO as a non-privileged user * Run the test and testpmd applications * Look at hugepages in the meminfo * List hugepages in /mnt/huge * Remove built DPDK libraries Once these steps have been completed for one of the EAL targets, the user may compile their own application that links in the EAL libraries to create the DPDK image. Script Organization ------------------- The setup.sh script is logically organized into a series of steps that a user performs in sequence. Each step provides a number of options that guide the user to completing the desired task. The following is a brief synopsis of each step. **Step 1: Build DPDK Libraries** Initially, the user must select a DPDK target to choose the correct target type and compiler options to use when building the libraries. The user must have all libraries, modules, updates and compilers installed in the system prior to this, as described in the earlier chapters in this Getting Started Guide. **Step 2: Setup Environment** The user configures the Linux* environment to support the running of DPDK applications. Hugepages can be set up for NUMA or non-NUMA systems. Any existing hugepages will be removed. The DPDK kernel module that is needed can also be inserted in this step, and network ports may be bound to this module for DPDK application use. **Step 3: Run an Application** The user may run the test application once the other steps have been performed. The test application allows the user to run a series of functional tests for the DPDK. The testpmd application, which supports the receiving and sending of packets, can also be run. **Step 4: Examining the System** This step provides some tools for examining the status of hugepage mappings. **Step 5: System Cleanup** The final step has options for restoring the system to its original state. Use Cases --------- The following are some example of how to use the setup.sh script. The script should be run using the source command. Some options in the script prompt the user for further data before proceeding. .. warning:: The setup.sh script should be run with root privileges. .. code-block:: console user@host:~/rte$ source tools/setup.sh ------------------------------------------------------------------------ RTE_SDK exported as /home/user/rte ------------------------------------------------------------------------ Step 1: Select the DPDK environment to build ------------------------------------------------------------------------ [1] i686-native-linuxapp-gcc [2] i686-native-linuxapp-icc [3] ppc_64-power8-linuxapp-gcc [4] x86_64-ivshmem-linuxapp-gcc [5] x86_64-ivshmem-linuxapp-icc [6] x86_64-native-bsdapp-clang [7] x86_64-native-bsdapp-gcc [8] x86_64-native-linuxapp-clang [9] x86_64-native-linuxapp-gcc [10] x86_64-native-linuxapp-icc ------------------------------------------------------------------------ Step 2: Setup linuxapp environment ------------------------------------------------------------------------ [11] Insert IGB UIO module [12] Insert VFIO module [13] Insert KNI module [14] Setup hugepage mappings for non-NUMA systems [15] Setup hugepage mappings for NUMA systems [16] Display current Ethernet device settings [17] Bind Ethernet device to IGB UIO module [18] Bind Ethernet device to VFIO module [19] Setup VFIO permissions ------------------------------------------------------------------------ Step 3: Run test application for linuxapp environment ------------------------------------------------------------------------ [20] Run test application ($RTE_TARGET/app/test) [21] Run testpmd application in interactive mode ($RTE_TARGET/app/testpmd) ------------------------------------------------------------------------ Step 4: Other tools ------------------------------------------------------------------------ [22] List hugepage info from /proc/meminfo ------------------------------------------------------------------------ Step 5: Uninstall and system cleanup ------------------------------------------------------------------------ [23] Uninstall all targets [24] Unbind NICs from IGB UIO driver [25] Remove IGB UIO module [26] Remove VFIO module [27] Remove KNI module [28] Remove hugepage mappings [29] Exit Script Option: The following selection demonstrates the creation of the x86_64-native-linuxapp-gcc DPDK library. .. code-block:: console Option: 9 ================== Installing x86_64-native-linuxapp-gcc Configuration done == Build lib ... Build complete RTE_TARGET exported as x86_64-native -linuxapp-gcc The following selection demonstrates the starting of the DPDK UIO driver. .. code-block:: console Option: 25 Unloading any existing DPDK UIO module Loading DPDK UIO module The following selection demonstrates the creation of hugepages in a NUMA system. 1024 2 MByte pages are assigned to each node. The result is that the application should use -m 4096 for starting the application to access both memory areas (this is done automatically if the -m option is not provided). .. note:: If prompts are displayed to remove temporary files, type 'y'. .. code-block:: console Option: 15 Removing currently reserved hugepages mounting /mnt/huge and removing directory Input the number of 2MB pages for each node Example: to have 128MB of hugepages available per node, enter '64' to reserve 64 * 2MB pages on each node Number of pages for node0: 1024 Number of pages for node1: 1024 Reserving hugepages Creating /mnt/huge and mounting as hugetlbfs The following selection demonstrates the launch of the test application to run on a single core. .. code-block:: console Option: 20 Enter hex bitmask of cores to execute test app on Example: to execute app on cores 0 to 7, enter 0xff bitmask: 0x01 Launching app EAL: coremask set to 1 EAL: Detected lcore 0 on socket 0 ... EAL: Master core 0 is ready (tid=1b2ad720) RTE>> Applications ------------ Once the user has run the setup.sh script, built one of the EAL targets and set up hugepages (if using one of the Linux EAL targets), the user can then move on to building and running their application or one of the examples provided. The examples in the /examples directory provide a good starting point to gain an understanding of the operation of the DPDK. The following command sequence shows how the helloworld sample application is built and run. As recommended in Section 4.2.1 , "Logical Core Use by Applications", the logical core layout of the platform should be determined when selecting a core mask to use for an application. .. code-block:: console rte@rte-desktop:~/rte/examples$ cd helloworld/ rte@rte-desktop:~/rte/examples/helloworld$ make CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map rte@rte-desktop:~/rte/examples/helloworld$ sudo ./build/app/helloworld -c 0xf -n 3 [sudo] password for rte: EAL: coremask set to f EAL: Detected lcore 0 as core 0 on socket 0 EAL: Detected lcore 1 as core 0 on socket 1 EAL: Detected lcore 2 as core 1 on socket 0 EAL: Detected lcore 3 as core 1 on socket 1 EAL: Setting up hugepage memory... EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f0add800000 (size = 0x200000) EAL: Ask a virtual area of 0x3d400000 bytes EAL: Virtual area found at 0x7f0aa0200000 (size = 0x3d400000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9fc00000 (size = 0x400000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9f600000 (size = 0x400000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9f000000 (size = 0x400000) EAL: Ask a virtual area of 0x800000 bytes EAL: Virtual area found at 0x7f0a9e600000 (size = 0x800000) EAL: Ask a virtual area of 0x800000 bytes EAL: Virtual area found at 0x7f0a9dc00000 (size = 0x800000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9d600000 (size = 0x400000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9d000000 (size = 0x400000) EAL: Ask a virtual area of 0x400000 bytes EAL: Virtual area found at 0x7f0a9ca00000 (size = 0x400000) EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f0a9c600000 (size = 0x200000) EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f0a9c200000 (size = 0x200000) EAL: Ask a virtual area of 0x3fc00000 bytes EAL: Virtual area found at 0x7f0a5c400000 (size = 0x3fc00000) EAL: Ask a virtual area of 0x200000 bytes EAL: Virtual area found at 0x7f0a5c000000 (size = 0x200000) EAL: Requesting 1024 pages of size 2MB from socket 0 EAL: Requesting 1024 pages of size 2MB from socket 1 EAL: Master core 0 is ready (tid=de25b700) EAL: Core 1 is ready (tid=5b7fe700) EAL: Core 3 is ready (tid=5a7fc700) EAL: Core 2 is ready (tid=5affd700) hello from core 1 hello from core 2 hello from core 3 hello from core 0 ================================================ FILE: doc/guides/linux_gsg/sys_reqs.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. System Requirements =================== This chapter describes the packages required to compile the DPDK. .. note:: If the DPDK is being used on an Intel® Communications Chipset 89xx Series platform, please consult the *Intel® Communications Chipset 89xx Series Software for Linux* Getting Started Guide*. BIOS Setting Prerequisite on x86 -------------------------------- For the majority of platforms, no special BIOS settings are needed to use basic DPDK functionality. However, for additional HPET timer and power management functionality, and high performance of small packets on 40G NIC, BIOS setting changes may be needed. Consult :ref:`Chapter 5. Enabling Additional Functionality ` for more information on the required changes. Compilation of the DPDK ----------------------- **Required Tools:** .. note:: Testing has been performed using Fedora* 18. The setup commands and installed packages needed on other systems may be different. For details on other Linux distributions and the versions tested, please consult the DPDK Release Notes. * GNU make * coreutils: cmp, sed, grep, arch * gcc: versions 4.5.x or later is recommended for i686/x86_64. versions 4.8.x or later is recommended for ppc_64 and x86_x32 ABI. On some distributions, some specific compiler flags and linker flags are enabled by default and affect performance (- fstack-protector, for example). Please refer to the documentation of your distribution and to gcc -dumpspecs. * libc headers (glibc-devel.i686 / libc6-dev-i386; glibc-devel.x86_64 for 64-bit compilation on Intel architecture; glibc-devel.ppc64 for 64 bit IBM Power architecture;) * Linux kernel headers or sources required to build kernel modules. (kernel - devel.x86_64; kernel - devel.ppc64) * Additional packages required for 32-bit compilation on 64-bit systems are: glibc.i686, libgcc.i686, libstdc++.i686 and glibc-devel.i686 for Intel i686/x86_64; glibc.ppc64, libgcc.ppc64, libstdc++.ppc64 and glibc-devel.ppc64 for IBM ppc_64; .. note:: x86_x32 ABI is currently supported with distribution packages only on Ubuntu higher than 13.10 or recent Debian distribution. The only supported compiler is gcc 4.8+. .. note:: Python, version 2.6 or 2.7, to use various helper scripts included in the DPDK package **Optional Tools:** * Intel® C++ Compiler (icc). For installation, additional libraries may be required. See the icc Installation Guide found in the Documentation directory under the compiler installation. This release has been tested using version 12.1. * IBM® Advance ToolChain for Powerlinux. This is a set of open source development tools and runtime libraries which allows users to take leading edge advantage of IBM's latest POWER hardware features on Linux. To install it, see the IBM official installation document. * libpcap headers and libraries (libpcap-devel) to compile and use the libpcap-based poll-mode driver. This driver is disabled by default and can be enabled by setting CONFIG_RTE_LIBRTE_PMD_PCAP=y in the build time config file. Running DPDK Applications ------------------------- To run an DPDK application, some customization may be required on the target machine. System Software ~~~~~~~~~~~~~~~ **Required:** * Kernel version >= 2.6.33 The kernel version in use can be checked using the command: .. code-block:: console uname -r For details of the patches needed to use the DPDK with earlier kernel versions, see the DPDK FAQ included in the *DPDK Release Notes*. Note also that Red hat* Linux* 6.2 and 6.3 uses a 2.6.32 kernel that already has all the necessary patches applied. * glibc >= 2.7 (for features related to cpuset) The version can be checked using the ldd --version command. A sample output is shown below: .. code-block:: console # ldd --version ldd (GNU libc) 2.14.90 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. * Kernel configuration In the Fedora* OS and other common distributions, such as Ubuntu*, or Red Hat Enterprise Linux*, the vendor supplied kernel configurations can be used to run most DPDK applications. For other kernel builds, options which should be enabled for DPDK include: * UIO support * HUGETLBFS * PROC_PAGE_MONITOR support * HPET and HPET_MMAP configuration options should also be enabled if HPET support is required. See :ref:`Section 5.1 High Precision Event Timer (HPET) Functionality ` for more details. Use of Hugepages in the Linux* Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hugepage support is required for the large memory pool allocation used for packet buffers (the HUGETLBFS option must be enabled in the running kernel as indicated in Section 2.3). By using hugepage allocations, performance is increased since fewer pages are needed, and therefore less Translation Lookaside Buffers (TLBs, high speed translation caches), which reduce the time it takes to translate a virtual page address to a physical page address. Without hugepages, high TLB miss rates would occur with the standard 4k page size, slowing performance. Reserving Hugepages for DPDK Use ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The allocation of hugepages should be done at boot time or as soon as possible after system boot to prevent memory from being fragmented in physical memory. To reserve hugepages at boot time, a parameter is passed to the Linux* kernel on the kernel command line. For 2 MB pages, just pass the hugepages option to the kernel. For example, to reserve 1024 pages of 2 MB, use: .. code-block:: console hugepages=1024 For other hugepage sizes, for example 1G pages, the size must be specified explicitly and can also be optionally set as the default hugepage size for the system. For example, to reserve 4G of hugepage memory in the form of four 1G pages, the following options should be passed to the kernel: .. code-block:: console default_hugepagesz=1G hugepagesz=1G hugepages=4 .. note:: The hugepage sizes that a CPU supports can be determined from the CPU flags on Intel architecture. If pse exists, 2M hugepages are supported; if pdpe1gb exists, 1G hugepages are supported. On IBM Power architecture, the supported hugepage sizes are 16MB and 16GB. .. note:: For 64-bit applications, it is recommended to use 1 GB hugepages if the platform supports them. In the case of a dual-socket NUMA system, the number of hugepages reserved at boot time is generally divided equally between the two sockets (on the assumption that sufficient memory is present on both sockets). See the Documentation/kernel-parameters.txt file in your Linux* source tree for further details of these and other kernel options. **Alternative:** For 2 MB pages, there is also the option of allocating hugepages after the system has booted. This is done by echoing the number of hugepages required to a nr_hugepages file in the /sys/devices/ directory. For a single-node system, the command to use is as follows (assuming that 1024 pages are required): .. code-block:: console echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages On a NUMA machine, pages should be allocated explicitly on separate nodes: .. code-block:: console echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages .. note:: For 1G pages, it is not possible to reserve the hugepage memory after the system has booted. Using Hugepages with the DPDK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Once the hugepage memory is reserved, to make the memory available for DPDK use, perform the following steps: .. code-block:: console mkdir /mnt/huge mount -t hugetlbfs nodev /mnt/huge The mount point can be made permanent across reboots, by adding the following line to the /etc/fstab file: .. code-block:: console nodev /mnt/huge hugetlbfs defaults 0 0 For 1GB pages, the page size must be specified as a mount option: .. code-block:: console nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0 Xen Domain0 Support in the Linux* Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The existing memory management implementation is based on the Linux* kernel hugepage mechanism. On the Xen hypervisor, hugepage support for DomainU (DomU) Guests means that DPDK applications work as normal for guests. However, Domain0 (Dom0) does not support hugepages. To work around this limitation, a new kernel module rte_dom0_mm is added to facilitate the allocation and mapping of memory via **IOCTL** (allocation) and **MMAP** (mapping). Enabling Xen Dom0 Mode in the DPDK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default, Xen Dom0 mode is disabled in the DPDK build configuration files. To support Xen Dom0, the CONFIG_RTE_LIBRTE_XEN_DOM0 setting should be changed to “y”, which enables the Xen Dom0 mode at compile time. Furthermore, the CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID setting should also be changed to “y” in the case of the wrong socket ID being received. Loading the DPDK rte_dom0_mm Module ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To run any DPDK application on Xen Dom0, the rte_dom0_mm module must be loaded into the running kernel with rsv_memsize option. The module is found in the kmod sub-directory of the DPDK target directory. This module should be loaded using the insmod command as shown below (assuming that the current directory is the DPDK target directory): .. code-block:: console sudo insmod kmod/rte_dom0_mm.ko rsv_memsize=X The value X cannot be greater than 4096(MB). Configuring Memory for DPDK Use ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ After the rte_dom0_mm.ko kernel module has been loaded, the user must configure the memory size for DPDK usage. This is done by echoing the memory size to a memsize file in the /sys/devices/ directory. Use the following command (assuming that 2048 MB is required): .. code-block:: console echo 2048 > /sys/kernel/mm/dom0-mm/memsize-mB/memsize The user can also check how much memory has already been used: .. code-block:: console cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_rsvd Xen Domain0 does not support NUMA configuration, as a result the --socket-mem command line option is invalid for Xen Domain0. .. note:: The memsize value cannot be greater than the rsv_memsize value. Running the DPDK Application on Xen Domain0 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To run the DPDK application on Xen Domain0, an extra command line option --xen-dom0 is required. ================================================ FILE: doc/guides/nics/cxgbe.rst ================================================ .. BSD LICENSE Copyright 2015 Chelsio Communications. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Chelsio Communications nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. CXGBE Poll Mode Driver ====================== The CXGBE PMD (**librte_pmd_cxgbe**) provides poll mode driver support for **Chelsio T5** 10/40 Gbps family of adapters. CXGBE PMD has support for the latest Linux and FreeBSD operating systems. More information can be found at `Chelsio Communications Official Website `_. Features -------- CXGBE PMD has support for: - Multiple queues for TX and RX - Receiver Side Steering (RSS) - VLAN filtering - Checksum offload - Promiscuous mode - All multicast mode - Port hardware statistics Limitations ----------- The Chelsio T5 devices provide two/four ports but expose a single PCI bus address, thus, librte_pmd_cxgbe registers itself as a PCI driver that allocates one Ethernet device per detected port. For this reason, one cannot whitelist/blacklist a single port without whitelisting/blacklisting the other ports on the same device. Supported Chelsio T5 NICs ------------------------- - 1G NICs: T502-BT - 10G NICs: T520-BT, T520-CR, T520-LL-CR, T520-SO-CR, T540-CR - 40G NICs: T580-CR, T580-LP-CR, T580-SO-CR - Other T5 NICs: T522-CR Prerequisites ------------- - Requires firmware version **1.13.32.0** and higher. Visit `Chelsio Download Center `_ to get latest firmware bundled with the latest Chelsio Unified Wire package. For Linux, installing and loading the latest cxgb4 kernel driver from the Chelsio Unified Wire package should get you the latest firmware. More information can be obtained from the User Guide that is bundled with the Chelsio Unified Wire package. For FreeBSD, the latest firmware obtained from the Chelsio Unified Wire package must be manually flashed via cxgbetool available in FreeBSD source repository. Instructions on how to manually flash the firmware are given in section :ref:`linux-installation` for Linux and section :ref:`freebsd-installation` for FreeBSD. Pre-Installation Configuration ------------------------------ Config File Options ~~~~~~~~~~~~~~~~~~~ The following options can be modified in the ``.config`` file. Please note that enabling debugging options may affect system performance. - ``CONFIG_RTE_LIBRTE_CXGBE_PMD`` (default **y**) Toggle compilation of librte_pmd_cxgbe driver. - ``CONFIG_RTE_LIBRTE_CXGBE_DEBUG`` (default **n**) Toggle display of generic debugging messages. - ``CONFIG_RTE_LIBRTE_CXGBE_DEBUG_REG`` (default **n**) Toggle display of registers related run-time check messages. - ``CONFIG_RTE_LIBRTE_CXGBE_DEBUG_MBOX`` (default **n**) Toggle display of firmware mailbox related run-time check messages. - ``CONFIG_RTE_LIBRTE_CXGBE_DEBUG_TX`` (default **n**) Toggle display of transmission data path run-time check messages. - ``CONFIG_RTE_LIBRTE_CXGBE_DEBUG_RX`` (default **n**) Toggle display of receiving data path run-time check messages. .. _driver-compilation: Driver Compilation ~~~~~~~~~~~~~~~~~~ To compile CXGBE PMD for Linux x86_64 gcc target, run the following "make" command: .. code-block:: console cd make config T=x86_64-native-linuxapp-gcc install To compile CXGBE PMD for FreeBSD x86_64 clang target, run the following "gmake" command: .. code-block:: console cd gmake config T=x86_64-native-bsdapp-clang install Linux ----- .. _linux-installation: Linux Installation ~~~~~~~~~~~~~~~~~~ Steps to manually install the latest firmware from the downloaded Chelsio Unified Wire package for Linux operating system are as follows: #. Load the kernel module: .. code-block:: console modprobe cxgb4 #. Use ifconfig to get the interface name assigned to Chelsio card: .. code-block:: console ifconfig -a | grep "00:07:43" Example output: .. code-block:: console p1p1 Link encap:Ethernet HWaddr 00:07:43:2D:EA:C0 p1p2 Link encap:Ethernet HWaddr 00:07:43:2D:EA:C8 #. Install cxgbtool: .. code-block:: console cd /tools/cxgbtool make install #. Use cxgbtool to load the firmware config file onto the card: .. code-block:: console cxgbtool p1p1 loadcfg /src/network/firmware/t5-config.txt #. Use cxgbtool to load the firmware image onto the card: .. code-block:: console cxgbtool p1p1 loadfw /src/network/firmware/t5fw-*.bin #. Unload and reload the kernel module: .. code-block:: console modprobe -r cxgb4 modprobe cxgb4 #. Verify with ethtool: .. code-block:: console ethtool -i p1p1 | grep "firmware" Example output: .. code-block:: console firmware-version: 1.13.32.0, TP 0.1.4.8 Sample Application Notes ~~~~~~~~~~~~~~~~~~~~~~~~ This section demonstrates how to launch **testpmd** with Chelsio T5 devices managed by librte_pmd_cxgbe in Linux operating system. #. Change to DPDK source directory where the target has been compiled in section :ref:`driver-compilation`: .. code-block:: console cd #. Load the kernel module: .. code-block:: console modprobe cxgb4 #. Get the PCI bus addresses of the interfaces bound to cxgb4 driver: .. code-block:: console dmesg | tail -2 Example output: .. code-block:: console cxgb4 0000:02:00.4 p1p1: renamed from eth0 cxgb4 0000:02:00.4 p1p2: renamed from eth1 .. note:: Both the interfaces of a Chelsio T5 2-port adapter are bound to the same PCI bus address. #. Unload the kernel module: .. code-block:: console modprobe -ar cxgb4 csiostor #. Request huge pages: .. code-block:: console echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages/nr_hugepages #. Load igb_uio or vfio-pci driver: .. code-block:: console insmod ./x86_64-native-linuxapp-gcc/kmod/igb_uio.ko or .. code-block:: console modprobe vfio-pci #. Bind the Chelsio T5 adapters to igb_uio or vfio-pci loaded in the previous step: .. code-block:: console ./tools/dpdk_nic_bind.py --bind igb_uio 0000:02:00.4 or Setup VFIO permissions for regular users and then bind to vfio-pci: .. code-block:: console sudo chmod a+x /dev/vfio sudo chmod 0666 /dev/vfio/* ./tools/dpdk_nic_bind.py --bind vfio-pci 0000:02:00.4 .. note:: Currently, CXGBE PMD only supports the binding of PF4 for Chelsio T5 NICs. #. Start testpmd with basic parameters: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c 0xf -n 4 -w 0000:02:00.4 -- -i Example output: .. code-block:: console [...] EAL: PCI device 0000:02:00.4 on NUMA socket -1 EAL: probe driver: 1425:5401 rte_cxgbe_pmd EAL: PCI memory mapped at 0x7fd7c0200000 EAL: PCI memory mapped at 0x7fd77cdfd000 EAL: PCI memory mapped at 0x7fd7c10b7000 PMD: rte_cxgbe_pmd: fw: 1.13.32.0, TP: 0.1.4.8 PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter Interactive-mode selected Configuring Port 0 (socket 0) Port 0: 00:07:43:2D:EA:C0 Configuring Port 1 (socket 0) Port 1: 00:07:43:2D:EA:C8 Checking link statuses... PMD: rte_cxgbe_pmd: Port0: passive DA port module inserted PMD: rte_cxgbe_pmd: Port1: passive DA port module inserted Port 0 Link Up - speed 10000 Mbps - full-duplex Port 1 Link Up - speed 10000 Mbps - full-duplex Done testpmd> .. note:: Flow control pause TX/RX is disabled by default and can be enabled via testpmd as follows: .. code-block:: console testpmd> set flow_ctrl rx on tx on 0 0 0 0 mac_ctrl_frame_fwd off autoneg on 0 testpmd> set flow_ctrl rx on tx on 0 0 0 0 mac_ctrl_frame_fwd off autoneg on 1 To disable again, use: .. code-block:: console testpmd> set flow_ctrl rx off tx off 0 0 0 0 mac_ctrl_frame_fwd off autoneg off 0 testpmd> set flow_ctrl rx off tx off 0 0 0 0 mac_ctrl_frame_fwd off autoneg off 1 FreeBSD ------- .. _freebsd-installation: FreeBSD Installation ~~~~~~~~~~~~~~~~~~~~ Steps to manually install the latest firmware from the downloaded Chelsio Unified Wire package for FreeBSD operating system are as follows: #. Load the kernel module: .. code-block:: console kldload if_cxgbe #. Use dmesg to get the t5nex instance assigned to the Chelsio card: .. code-block:: console dmesg | grep "t5nex" Example output: .. code-block:: console t5nex0: irq 16 at device 0.4 on pci2 cxl0: on t5nex0 cxl1: on t5nex0 t5nex0: PCIe x8, 2 ports, 14 MSI-X interrupts, 31 eq, 13 iq In the example above, a Chelsio T520-CR card is bound to a t5nex0 instance. #. Install cxgbetool from FreeBSD source repository: .. code-block:: console cd /tools/tools/cxgbetool/ make && make install #. Use cxgbetool to load the firmware image onto the card: .. code-block:: console cxgbetool t5nex0 loadfw /src/network/firmware/t5fw-*.bin #. Unload and reload the kernel module: .. code-block:: console kldunload if_cxgbe kldload if_cxgbe #. Verify with sysctl: .. code-block:: console sysctl -a | grep "t5nex" | grep "firmware" Example output: .. code-block:: console dev.t5nex.0.firmware_version: 1.13.32.0 Sample Application Notes ~~~~~~~~~~~~~~~~~~~~~~~~ This section demonstrates how to launch **testpmd** with Chelsio T5 devices managed by librte_pmd_cxgbe in FreeBSD operating system. #. Change to DPDK source directory where the target has been compiled in section :ref:`driver-compilation`: .. code-block:: console cd #. Copy the contigmem kernel module to /boot/kernel directory: .. code-block:: console cp x86_64-native-bsdapp-clang/kmod/contigmem.ko /boot/kernel/ #. Add the following lines to /boot/loader.conf: .. code-block:: console # reserve 2 x 1G blocks of contiguous memory using contigmem driver hw.contigmem.num_buffers=2 hw.contigmem.buffer_size=1073741824 # load contigmem module during boot process contigmem_load="YES" The above lines load the contigmem kernel module during boot process and allocate 2 x 1G blocks of contiguous memory to be used for DPDK later on. This is to avoid issues with potential memory fragmentation during later system up time, which may result in failure of allocating the contiguous memory required for the contigmem kernel module. #. Restart the system and ensure the contigmem module is loaded successfully: .. code-block:: console reboot kldstat | grep "contigmem" Example output: .. code-block:: console 2 1 0xffffffff817f1000 3118 contigmem.ko #. Repeat step 1 to ensure that you are in the DPDK source directory. #. Load the cxgbe kernel module: .. code-block:: console kldload if_cxgbe #. Get the PCI bus addresses of the interfaces bound to t5nex driver: .. code-block:: console pciconf -l | grep "t5nex" Example output: .. code-block:: console t5nex0@pci0:2:0:4: class=0x020000 card=0x00001425 chip=0x54011425 rev=0x00 In the above example, the t5nex0 is bound to 2:0:4 bus address. .. note:: Both the interfaces of a Chelsio T5 2-port adapter are bound to the same PCI bus address. #. Unload the kernel module: .. code-block:: console kldunload if_cxgbe #. Set the PCI bus addresses to hw.nic_uio.bdfs kernel environment parameter: .. code-block:: console kenv hw.nic_uio.bdfs="2:0:4" This automatically binds 2:0:4 to nic_uio kernel driver when it is loaded in the next step. .. note:: Currently, CXGBE PMD only supports the binding of PF4 for Chelsio T5 NICs. #. Load nic_uio kernel driver: .. code-block:: console kldload ./x86_64-native-bsdapp-clang/kmod/nic_uio.ko #. Start testpmd with basic parameters: .. code-block:: console ./x86_64-native-bsdapp-clang/app/testpmd -c 0xf -n 4 -w 0000:02:00.4 -- -i Example output: .. code-block:: console [...] EAL: PCI device 0000:02:00.4 on NUMA socket 0 EAL: probe driver: 1425:5401 rte_cxgbe_pmd EAL: PCI memory mapped at 0x8007ec000 EAL: PCI memory mapped at 0x842800000 EAL: PCI memory mapped at 0x80086c000 PMD: rte_cxgbe_pmd: fw: 1.13.32.0, TP: 0.1.4.8 PMD: rte_cxgbe_pmd: Coming up as MASTER: Initializing adapter Interactive-mode selected Configuring Port 0 (socket 0) Port 0: 00:07:43:2D:EA:C0 Configuring Port 1 (socket 0) Port 1: 00:07:43:2D:EA:C8 Checking link statuses... PMD: rte_cxgbe_pmd: Port0: passive DA port module inserted PMD: rte_cxgbe_pmd: Port1: passive DA port module inserted Port 0 Link Up - speed 10000 Mbps - full-duplex Port 1 Link Up - speed 10000 Mbps - full-duplex Done testpmd> .. note:: Flow control pause TX/RX is disabled by default and can be enabled via testpmd as follows: .. code-block:: console testpmd> set flow_ctrl rx on tx on 0 0 0 0 mac_ctrl_frame_fwd off autoneg on 0 testpmd> set flow_ctrl rx on tx on 0 0 0 0 mac_ctrl_frame_fwd off autoneg on 1 To disable again, use: .. code-block:: console testpmd> set flow_ctrl rx off tx off 0 0 0 0 mac_ctrl_frame_fwd off autoneg off 0 testpmd> set flow_ctrl rx off tx off 0 0 0 0 mac_ctrl_frame_fwd off autoneg off 1 ================================================ FILE: doc/guides/nics/e1000em.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Driver for VM Emulated Devices ============================== The DPDK EM poll mode driver supports the following emulated devices: * qemu-kvm emulated Intel® 82540EM Gigabit Ethernet Controller (qemu e1000 device) * VMware* emulated Intel® 82545EM Gigabit Ethernet Controller * VMware emulated Intel® 8274L Gigabit Ethernet Controller. Validated Hypervisors --------------------- The validated hypervisors are: * KVM (Kernel Virtual Machine) with Qemu, version 0.14.0 * KVM (Kernel Virtual Machine) with Qemu, version 0.15.1 * VMware ESXi 5.0, Update 1 Recommended Guest Operating System in Virtual Machine ----------------------------------------------------- The recommended guest operating system in a virtualized environment is: * Fedora* 18 (64-bit) For supported kernel versions, refer to the *DPDK Release Notes*. Setting Up a KVM Virtual Machine -------------------------------- The following describes a target environment: * Host Operating System: Fedora 14 * Hypervisor: KVM (Kernel Virtual Machine) with Qemu version, 0.14.0 * Guest Operating System: Fedora 14 * Linux Kernel Version: Refer to the DPDK Getting Started Guide * Target Applications: testpmd The setup procedure is as follows: #. Download qemu-kvm-0.14.0 from `http://sourceforge.net/projects/kvm/files/qemu-kvm/ `_ and install it in the Host OS using the following steps: When using a recent kernel (2.6.25+) with kvm modules included: .. code-block:: console tar xzf qemu-kvm-release.tar.gz cd qemu-kvm-release ./configure --prefix=/usr/local/kvm make sudo make install sudo /sbin/modprobe kvm-intel When using an older kernel or a kernel from a distribution without the kvm modules, you must download (from the same link), compile and install the modules yourself: .. code-block:: console tar xjf kvm-kmod-release.tar.bz2 cd kvm-kmod-release ./configure make sudo make install sudo /sbin/modprobe kvm-intel Note that qemu-kvm installs in the /usr/local/bin directory. For more details about KVM configuration and usage, please refer to: `http://www.linux-kvm.org/page/HOWTO1 `_. #. Create a Virtual Machine and install Fedora 14 on the Virtual Machine. This is referred to as the Guest Operating System (Guest OS). #. Start the Virtual Machine with at least one emulated e1000 device. .. note:: The Qemu provides several choices for the emulated network device backend. Most commonly used is a TAP networking backend that uses a TAP networking device in the host. For more information about Qemu supported networking backends and different options for configuring networking at Qemu, please refer to: — `http://www.linux-kvm.org/page/Networking `_ — `http://wiki.qemu.org/Documentation/Networking `_ — `http://qemu.weilnetz.de/qemu-doc.html `_ For example, to start a VM with two emulated e1000 devices, issue the following command: .. code-block:: console /usr/local/kvm/bin/qemu-system-x86_64 -cpu host -smp 4 -hda qemu1.raw -m 1024 -net nic,model=e1000,vlan=1,macaddr=DE:AD:1E:00:00:01 -net tap,vlan=1,ifname=tapvm01,script=no,downscript=no -net nic,model=e1000,vlan=2,macaddr=DE:AD:1E:00:00:02 -net tap,vlan=2,ifname=tapvm02,script=no,downscript=no where: — -m = memory to assign — -smp = number of smp cores — -hda = virtual disk image This command starts a new virtual machine with two emulated 82540EM devices, backed up with two TAP networking host interfaces, tapvm01 and tapvm02. .. code-block:: console # ip tuntap show tapvm01: tap tapvm02: tap #. Configure your TAP networking interfaces using ip/ifconfig tools. #. Log in to the guest OS and check that the expected emulated devices exist: .. code-block:: console # lspci -d 8086:100e 00:04.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03) 00:05.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03) #. Install the DPDK and run testpmd. Known Limitations of Emulated Devices ------------------------------------- The following are known limitations: #. The Qemu e1000 RX path does not support multiple descriptors/buffers per packet. Therefore, rte_mbuf should be big enough to hold the whole packet. For example, to allow testpmd to receive jumbo frames, use the following: testpmd [options] -- --mbuf-size= #. Qemu e1000 does not validate the checksum of incoming packets. ================================================ FILE: doc/guides/nics/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Network Interface Controller Drivers ==================================== |today| **Contents** .. toctree:: :maxdepth: 3 :numbered: cxgbe e1000em ixgbe intel_vf mlx4 virtio vmxnet3 pcap_ring **Figures** :numref:`figure_single_port_nic` :ref:`figure_single_port_nic` :numref:`figure_perf_benchmark` :ref:`figure_perf_benchmark` :numref:`figure_fast_pkt_proc` :ref:`figure_fast_pkt_proc` :numref:`figure_inter_vm_comms` :ref:`figure_inter_vm_comms` :numref:`figure_host_vm_comms` :ref:`figure_host_vm_comms` :numref:`figure_host_vm_comms_qemu` :ref:`figure_host_vm_comms_qemu` :numref:`figure_vmxnet3_int` :ref:`figure_vmxnet3_int` :numref:`figure_vswitch_vm` :ref:`figure_vswitch_vm` :numref:`figure_vm_vm_comms` :ref:`figure_vm_vm_comms` ================================================ FILE: doc/guides/nics/intel_vf.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. I40E/IXGBE/IGB Virtual Function Driver ====================================== Supported Intel® Ethernet Controllers (see the *DPDK Release Notes* for details) support the following modes of operation in a virtualized environment: * **SR-IOV mode**: Involves direct assignment of part of the port resources to different guest operating systems using the PCI-SIG Single Root I/O Virtualization (SR IOV) standard, also known as "native mode" or "pass-through" mode. In this chapter, this mode is referred to as IOV mode. * **VMDq mode**: Involves central management of the networking resources by an IO Virtual Machine (IOVM) or a Virtual Machine Monitor (VMM), also known as software switch acceleration mode. In this chapter, this mode is referred to as the Next Generation VMDq mode. SR-IOV Mode Utilization in a DPDK Environment --------------------------------------------- The DPDK uses the SR-IOV feature for hardware-based I/O sharing in IOV mode. Therefore, it is possible to partition SR-IOV capability on Ethernet controller NIC resources logically and expose them to a virtual machine as a separate PCI function called a "Virtual Function". Refer to :numref:`figure_single_port_nic`. Therefore, a NIC is logically distributed among multiple virtual machines (as shown in :numref:`figure_single_port_nic`), while still having global data in common to share with the Physical Function and other Virtual Functions. The DPDK fm10kvf, i40evf, igbvf or ixgbevf as a Poll Mode Driver (PMD) serves for the Intel® 82576 Gigabit Ethernet Controller, Intel® Ethernet Controller I350 family, Intel® 82599 10 Gigabit Ethernet Controller NIC, Intel® Fortville 10/40 Gigabit Ethernet Controller NIC's virtual PCI function, or PCIe host-interface of the Intel Ethernet Switch FM10000 Series. Meanwhile the DPDK Poll Mode Driver (PMD) also supports "Physical Function" of such NIC's on the host. The DPDK PF/VF Poll Mode Driver (PMD) supports the Layer 2 switch on Intel® 82576 Gigabit Ethernet Controller, Intel® Ethernet Controller I350 family, Intel® 82599 10 Gigabit Ethernet Controller, and Intel® Fortville 10/40 Gigabit Ethernet Controller NICs so that guest can choose it for inter virtual machine traffic in SR-IOV mode. For more detail on SR-IOV, please refer to the following documents: * `SR-IOV provides hardware based I/O sharing `_ * `PCI-SIG-Single Root I/O Virtualization Support on IA `_ * `Scalable I/O Virtualized Servers `_ .. _figure_single_port_nic: .. figure:: img/single_port_nic.* Virtualization for a Single Port NIC in SR-IOV Mode Physical and Virtual Function Infrastructure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following describes the Physical Function and Virtual Functions infrastructure for the supported Ethernet Controller NICs. Virtual Functions operate under the respective Physical Function on the same NIC Port and therefore have no access to the global NIC resources that are shared between other functions for the same NIC port. A Virtual Function has basic access to the queue resources and control structures of the queues assigned to it. For global resource access, a Virtual Function has to send a request to the Physical Function for that port, and the Physical Function operates on the global resources on behalf of the Virtual Function. For this out-of-band communication, an SR-IOV enabled NIC provides a memory buffer for each Virtual Function, which is called a "Mailbox". The PCIE host-interface of Intel Ethernet Switch FM10000 Series VF infrastructure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In a virtualized environment, the programmer can enable a maximum of *64 Virtual Functions (VF)* globally per PCIE host-interface of the Intel Ethernet Switch FM10000 Series device. Each VF can have a maximum of 16 queue pairs. The Physical Function in host could be only configured by the Linux* fm10k driver (in the case of the Linux Kernel-based Virtual Machine [KVM]), DPDK PMD PF driver doesn't support it yet. For example, * Using Linux* fm10k driver: .. code-block:: console rmmod fm10k (To remove the fm10k module) insmod fm0k.ko max_vfs=2,2 (To enable two Virtual Functions per port) Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC. When you enable the four Virtual Functions with the above command, the four enabled functions have a Function# represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3. However: * Virtual Functions 0 and 2 belong to Physical Function 0 * Virtual Functions 1 and 3 belong to Physical Function 1 .. note:: The above is an important consideration to take into account when targeting specific packets to a selected port. Intel® Fortville 10/40 Gigabit Ethernet Controller VF Infrastructure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In a virtualized environment, the programmer can enable a maximum of *128 Virtual Functions (VF)* globally per Intel® Fortville 10/40 Gigabit Ethernet Controller NIC device. Each VF can have a maximum of 16 queue pairs. The Physical Function in host could be either configured by the Linux* i40e driver (in the case of the Linux Kernel-based Virtual Machine [KVM]) or by DPDK PMD PF driver. When using both DPDK PMD PF/VF drivers, the whole NIC will be taken over by DPDK based application. For example, * Using Linux* i40e driver: .. code-block:: console rmmod i40e (To remove the i40e module) insmod i40e.ko max_vfs=2,2 (To enable two Virtual Functions per port) * Using the DPDK PMD PF i40e driver: Kernel Params: iommu=pt, intel_iommu=on .. code-block:: console modprobe uio insmod igb_uio ./dpdk_nic_bind.py -b igb_uio bb:ss.f echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific PCI device) Launch the DPDK testpmd/example or your own host daemon application using the DPDK PMD library. * Using the DPDK PMD PF ixgbe driver to enable VF RSS: Same steps as above to install the modules of uio, igb_uio, specify max_vfs for PCI device, and launch the DPDK testpmd/example or your own host daemon application using the DPDK PMD library. The available queue number(at most 4) per VF depends on the total number of pool, which is determined by the max number of VF at PF initialization stage and the number of queue specified in config: * If the max number of VF is set in the range of 1 to 32: If the number of rxq is specified as 4(e.g. '--rxq 4' in testpmd), then there are totally 32 pools(ETH_32_POOLS), and each VF could have 4 or less(e.g. 2) queues; If the number of rxq is specified as 2(e.g. '--rxq 2' in testpmd), then there are totally 32 pools(ETH_32_POOLS), and each VF could have 2 queues; * If the max number of VF is in the range of 33 to 64: If the number of rxq is 4 ('--rxq 4' in testpmd), then error message is expected as rxq is not correct at this case; If the number of rxq is 2 ('--rxq 2' in testpmd), then there is totally 64 pools(ETH_64_POOLS), and each VF have 2 queues; On host, to enable VF RSS functionality, rx mq mode should be set as ETH_MQ_RX_VMDQ_RSS or ETH_MQ_RX_RSS mode, and SRIOV mode should be activated(max_vfs >= 1). It also needs config VF RSS information like hash function, RSS key, RSS key length. .. code-block:: console testpmd -c 0xffff -n 4 -- --coremask= --rxq=4 --txq=4 -i The limitation for VF RSS on Intel® 82599 10 Gigabit Ethernet Controller is: The hash and key are shared among PF and all VF, the RETA table with 128 entries is also shared among PF and all VF; So it could not to provide a method to query the hash and reta content per VF on guest, while, if possible, please query them on host(PF) for the shared RETA information. Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC. When you enable the four Virtual Functions with the above command, the four enabled functions have a Function# represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3. However: * Virtual Functions 0 and 2 belong to Physical Function 0 * Virtual Functions 1 and 3 belong to Physical Function 1 .. note:: The above is an important consideration to take into account when targeting specific packets to a selected port. Intel® 82599 10 Gigabit Ethernet Controller VF Infrastructure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The programmer can enable a maximum of *63 Virtual Functions* and there must be *one Physical Function* per Intel® 82599 10 Gigabit Ethernet Controller NIC port. The reason for this is that the device allows for a maximum of 128 queues per port and a virtual/physical function has to have at least one queue pair (RX/TX). The current implementation of the DPDK ixgbevf driver supports a single queue pair (RX/TX) per Virtual Function. The Physical Function in host could be either configured by the Linux* ixgbe driver (in the case of the Linux Kernel-based Virtual Machine [KVM]) or by DPDK PMD PF driver. When using both DPDK PMD PF/VF drivers, the whole NIC will be taken over by DPDK based application. For example, * Using Linux* ixgbe driver: .. code-block:: console rmmod ixgbe (To remove the ixgbe module) insmod ixgbe max_vfs=2,2 (To enable two Virtual Functions per port) * Using the DPDK PMD PF ixgbe driver: Kernel Params: iommu=pt, intel_iommu=on .. code-block:: console modprobe uio insmod igb_uio ./dpdk_nic_bind.py -b igb_uio bb:ss.f echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific PCI device) Launch the DPDK testpmd/example or your own host daemon application using the DPDK PMD library. Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a dual-port NIC. When you enable the four Virtual Functions with the above command, the four enabled functions have a Function# represented by (Bus#, Device#, Function#) in sequence starting from 0 to 3. However: * Virtual Functions 0 and 2 belong to Physical Function 0 * Virtual Functions 1 and 3 belong to Physical Function 1 .. note:: The above is an important consideration to take into account when targeting specific packets to a selected port. Intel® 82576 Gigabit Ethernet Controller and Intel® Ethernet Controller I350 Family VF Infrastructure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In a virtualized environment, an Intel® 82576 Gigabit Ethernet Controller serves up to eight virtual machines (VMs). The controller has 16 TX and 16 RX queues. They are generally referred to (or thought of) as queue pairs (one TX and one RX queue). This gives the controller 16 queue pairs. A pool is a group of queue pairs for assignment to the same VF, used for transmit and receive operations. The controller has eight pools, with each pool containing two queue pairs, that is, two TX and two RX queues assigned to each VF. In a virtualized environment, an Intel® Ethernet Controller I350 family device serves up to eight virtual machines (VMs) per port. The eight queues can be accessed by eight different VMs if configured correctly (the i350 has 4x1GbE ports each with 8T X and 8 RX queues), that means, one Transmit and one Receive queue assigned to each VF. For example, * Using Linux* igb driver: .. code-block:: console rmmod igb (To remove the igb module) insmod igb max_vfs=2,2 (To enable two Virtual Functions per port) * Using Intel® DPDK PMD PF igb driver: Kernel Params: iommu=pt, intel_iommu=on modprobe uio .. code-block:: console insmod igb_uio ./dpdk_nic_bind.py -b igb_uio bb:ss.f echo 2 > /sys/bus/pci/devices/0000\:bb\:ss.f/max_vfs (To enable two VFs on a specific pci device) Launch DPDK testpmd/example or your own host daemon application using the DPDK PMD library. Virtual Function enumeration is performed in the following sequence by the Linux* pci driver for a four-port NIC. When you enable the four Virtual Functions with the above command, the four enabled functions have a Function# represented by (Bus#, Device#, Function#) in sequence, starting from 0 to 7. However: * Virtual Functions 0 and 4 belong to Physical Function 0 * Virtual Functions 1 and 5 belong to Physical Function 1 * Virtual Functions 2 and 6 belong to Physical Function 2 * Virtual Functions 3 and 7 belong to Physical Function 3 .. note:: The above is an important consideration to take into account when targeting specific packets to a selected port. Validated Hypervisors ~~~~~~~~~~~~~~~~~~~~~ The validated hypervisor is: * KVM (Kernel Virtual Machine) with Qemu, version 0.14.0 However, the hypervisor is bypassed to configure the Virtual Function devices using the Mailbox interface, the solution is hypervisor-agnostic. Xen* and VMware* (when SR- IOV is supported) will also be able to support the DPDK with Virtual Function driver support. Expected Guest Operating System in Virtual Machine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The expected guest operating systems in a virtualized environment are: * Fedora* 14 (64-bit) * Ubuntu* 10.04 (64-bit) For supported kernel versions, refer to the *DPDK Release Notes*. Setting Up a KVM Virtual Machine Monitor ---------------------------------------- The following describes a target environment: * Host Operating System: Fedora 14 * Hypervisor: KVM (Kernel Virtual Machine) with Qemu version 0.14.0 * Guest Operating System: Fedora 14 * Linux Kernel Version: Refer to the *DPDK Getting Started Guide* * Target Applications: l2fwd, l3fwd-vf The setup procedure is as follows: #. Before booting the Host OS, open **BIOS setup** and enable **Intel® VT features**. #. While booting the Host OS kernel, pass the intel_iommu=on kernel command line argument using GRUB. When using DPDK PF driver on host, pass the iommu=pt kernel command line argument in GRUB. #. Download qemu-kvm-0.14.0 from `http://sourceforge.net/projects/kvm/files/qemu-kvm/ `_ and install it in the Host OS using the following steps: When using a recent kernel (2.6.25+) with kvm modules included: .. code-block:: console tar xzf qemu-kvm-release.tar.gz cd qemu-kvm-release ./configure --prefix=/usr/local/kvm make sudo make install sudo /sbin/modprobe kvm-intel When using an older kernel, or a kernel from a distribution without the kvm modules, you must download (from the same link), compile and install the modules yourself: .. code-block:: console tar xjf kvm-kmod-release.tar.bz2 cd kvm-kmod-release ./configure make sudo make install sudo /sbin/modprobe kvm-intel qemu-kvm installs in the /usr/local/bin directory. For more details about KVM configuration and usage, please refer to: `http://www.linux-kvm.org/page/HOWTO1 `_. #. Create a Virtual Machine and install Fedora 14 on the Virtual Machine. This is referred to as the Guest Operating System (Guest OS). #. Download and install the latest ixgbe driver from: `http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=14687 `_ #. In the Host OS When using Linux kernel ixgbe driver, unload the Linux ixgbe driver and reload it with the max_vfs=2,2 argument: .. code-block:: console rmmod ixgbe modprobe ixgbe max_vfs=2,2 When using DPDK PMD PF driver, insert DPDK kernel module igb_uio and set the number of VF by sysfs max_vfs: .. code-block:: console modprobe uio insmod igb_uio ./dpdk_nic_bind.py -b igb_uio 02:00.0 02:00.1 0e:00.0 0e:00.1 echo 2 > /sys/bus/pci/devices/0000\:02\:00.0/max_vfs echo 2 > /sys/bus/pci/devices/0000\:02\:00.1/max_vfs echo 2 > /sys/bus/pci/devices/0000\:0e\:00.0/max_vfs echo 2 > /sys/bus/pci/devices/0000\:0e\:00.1/max_vfs .. note:: You need to explicitly specify number of vfs for each port, for example, in the command above, it creates two vfs for the first two ixgbe ports. Let say we have a machine with four physical ixgbe ports: 0000:02:00.0 0000:02:00.1 0000:0e:00.0 0000:0e:00.1 The command above creates two vfs for device 0000:02:00.0: .. code-block:: console ls -alrt /sys/bus/pci/devices/0000\:02\:00.0/virt* lrwxrwxrwx. 1 root root 0 Apr 13 05:40 /sys/bus/pci/devices/0000:02:00.0/virtfn1 -> ../0000:02:10.2 lrwxrwxrwx. 1 root root 0 Apr 13 05:40 /sys/bus/pci/devices/0000:02:00.0/virtfn0 -> ../0000:02:10.0 It also creates two vfs for device 0000:02:00.1: .. code-block:: console ls -alrt /sys/bus/pci/devices/0000\:02\:00.1/virt* lrwxrwxrwx. 1 root root 0 Apr 13 05:51 /sys/bus/pci/devices/0000:02:00.1/virtfn1 -> ../0000:02:10.3 lrwxrwxrwx. 1 root root 0 Apr 13 05:51 /sys/bus/pci/devices/0000:02:00.1/virtfn0 -> ../0000:02:10.1 #. List the PCI devices connected and notice that the Host OS shows two Physical Functions (traditional ports) and four Virtual Functions (two for each port). This is the result of the previous step. #. Insert the pci_stub module to hold the PCI devices that are freed from the default driver using the following command (see http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM Section 4 for more information): .. code-block:: console sudo /sbin/modprobe pci-stub Unbind the default driver from the PCI devices representing the Virtual Functions. A script to perform this action is as follows: .. code-block:: console echo "8086 10ed" > /sys/bus/pci/drivers/pci-stub/new_id echo 0000:08:10.0 > /sys/bus/pci/devices/0000:08:10.0/driver/unbind echo 0000:08:10.0 > /sys/bus/pci/drivers/pci-stub/bind where, 0000:08:10.0 belongs to the Virtual Function visible in the Host OS. #. Now, start the Virtual Machine by running the following command: .. code-block:: console /usr/local/kvm/bin/qemu-system-x86_64 -m 4096 -smp 4 -boot c -hda lucid.qcow2 -device pci-assign,host=08:10.0 where: — -m = memory to assign — -smp = number of smp cores — -boot = boot option — -hda = virtual disk image — -device = device to attach .. note:: — The pci-assign,host=08:10.0 alue indicates that you want to attach a PCI device to a Virtual Machine and the respective (Bus:Device.Function) numbers should be passed for the Virtual Function to be attached. — qemu-kvm-0.14.0 allows a maximum of four PCI devices assigned to a VM, but this is qemu-kvm version dependent since qemu-kvm-0.14.1 allows a maximum of five PCI devices. — qemu-system-x86_64 also has a -cpu command line option that is used to select the cpu_model to emulate in a Virtual Machine. Therefore, it can be used as: .. code-block:: console /usr/local/kvm/bin/qemu-system-x86_64 -cpu ? (to list all available cpu_models) /usr/local/kvm/bin/qemu-system-x86_64 -m 4096 -cpu host -smp 4 -boot c -hda lucid.qcow2 -device pci-assign,host=08:10.0 (to use the same cpu_model equivalent to the host cpu) For more information, please refer to: `http://wiki.qemu.org/Features/CPUModels `_. #. Install and run DPDK host app to take over the Physical Function. Eg. .. code-block:: console make install T=x86_64-native-linuxapp-gcc ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 -- -i #. Finally, access the Guest OS using vncviewer with the localhost:5900 port and check the lspci command output in the Guest OS. The virtual functions will be listed as available for use. #. Configure and install the DPDK with an x86_64-native-linuxapp-gcc configuration on the Guest OS as normal, that is, there is no change to the normal installation procedure. .. code-block:: console make config T=x86_64-native-linuxapp-gcc O=x86_64-native-linuxapp-gcc cd x86_64-native-linuxapp-gcc make .. note:: If you are unable to compile the DPDK and you are getting "error: CPU you selected does not support x86-64 instruction set", power off the Guest OS and start the virtual machine with the correct -cpu option in the qemu- system-x86_64 command as shown in step 9. You must select the best x86_64 cpu_model to emulate or you can select host option if available. .. note:: Run the DPDK l2fwd sample application in the Guest OS with Hugepages enabled. For the expected benchmark performance, you must pin the cores from the Guest OS to the Host OS (taskset can be used to do this) and you must also look at the PCI Bus layout on the board to ensure you are not running the traffic over the QPI Interface. .. note:: * The Virtual Machine Manager (the Fedora package name is virt-manager) is a utility for virtual machine management that can also be used to create, start, stop and delete virtual machines. If this option is used, step 2 and 6 in the instructions provided will be different. * virsh, a command line utility for virtual machine management, can also be used to bind and unbind devices to a virtual machine in Ubuntu. If this option is used, step 6 in the instructions provided will be different. * The Virtual Machine Monitor (see :numref:`figure_perf_benchmark`) is equivalent to a Host OS with KVM installed as described in the instructions. .. _figure_perf_benchmark: .. figure:: img/perf_benchmark.* Performance Benchmark Setup DPDK SR-IOV PMD PF/VF Driver Usage Model ---------------------------------------- Fast Host-based Packet Processing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Software Defined Network (SDN) trends are demanding fast host-based packet handling. In a virtualization environment, the DPDK VF PMD driver performs the same throughput result as a non-VT native environment. With such host instance fast packet processing, lots of services such as filtering, QoS, DPI can be offloaded on the host fast path. :numref:`figure_fast_pkt_proc` shows the scenario where some VMs directly communicate externally via a VFs, while others connect to a virtual switch and share the same uplink bandwidth. .. _figure_fast_pkt_proc: .. figure:: img/fast_pkt_proc.* Fast Host-based Packet Processing SR-IOV (PF/VF) Approach for Inter-VM Communication -------------------------------------------------- Inter-VM data communication is one of the traffic bottle necks in virtualization platforms. SR-IOV device assignment helps a VM to attach the real device, taking advantage of the bridge in the NIC. So VF-to-VF traffic within the same physical port (VM0<->VM1) have hardware acceleration. However, when VF crosses physical ports (VM0<->VM2), there is no such hardware bridge. In this case, the DPDK PMD PF driver provides host forwarding between such VMs. :numref:`figure_inter_vm_comms` shows an example. In this case an update of the MAC address lookup tables in both the NIC and host DPDK application is required. In the NIC, writing the destination of a MAC address belongs to another cross device VM to the PF specific pool. So when a packet comes in, its destination MAC address will match and forward to the host DPDK PMD application. In the host DPDK application, the behavior is similar to L2 forwarding, that is, the packet is forwarded to the correct PF pool. The SR-IOV NIC switch forwards the packet to a specific VM according to the MAC destination address which belongs to the destination VF on the VM. .. _figure_inter_vm_comms: .. figure:: img/inter_vm_comms.* Inter-VM Communication ================================================ FILE: doc/guides/nics/ixgbe.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IXGBE Driver ============ Vector PMD for IXGBE -------------------- Vector PMD uses Intel® SIMD instructions to optimize packet I/O. It improves load/store bandwidth efficiency of L1 data cache by using a wider SSE/AVX register 1 (1). The wider register gives space to hold multiple packet buffers so as to save instruction number when processing bulk of packets. There is no change to PMD API. The RX/TX handler are the only two entries for vPMD packet I/O. They are transparently registered at runtime RX/TX execution if all condition checks pass. 1. To date, only an SSE version of IX GBE vPMD is available. To ensure that vPMD is in the binary code, ensure that the option CONFIG_RTE_IXGBE_INC_VECTOR=y is in the configure file. Some constraints apply as pre-conditions for specific optimizations on bulk packet transfers. The following sections explain RX and TX constraints in the vPMD. RX Constraints ~~~~~~~~~~~~~~ Prerequisites and Pre-conditions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following prerequisites apply: * To enable vPMD to work for RX, bulk allocation for Rx must be allowed. Ensure that the following pre-conditions are satisfied: * rxq->rx_free_thresh >= RTE_PMD_IXGBE_RX_MAX_BURST * rxq->rx_free_thresh < rxq->nb_rx_desc * (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0 * rxq->nb_rx_desc < (IXGBE_MAX_RING_DESC - RTE_PMD_IXGBE_RX_MAX_BURST) These conditions are checked in the code. Scattered packets are not supported in this mode. If an incoming packet is greater than the maximum acceptable length of one "mbuf" data size (by default, the size is 2 KB), vPMD for RX would be disabled. By default, IXGBE_MAX_RING_DESC is set to 4096 and RTE_PMD_IXGBE_RX_MAX_BURST is set to 32. Feature not Supported by RX Vector PMD ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some features are not supported when trying to increase the throughput in vPMD. They are: * IEEE1588 * FDIR * Header split * RX checksum off load Other features are supported using optional MACRO configuration. They include: * HW VLAN strip * HW extend dual VLAN * Enabled by RX_OLFLAGS (RTE_IXGBE_RX_OLFLAGS_ENABLE=y) To guarantee the constraint, configuration flags in dev_conf.rxmode will be checked: * hw_vlan_strip * hw_vlan_extend * hw_ip_checksum * header_split * dev_conf fdir_conf->mode will also be checked. RX Burst Size ^^^^^^^^^^^^^ As vPMD is focused on high throughput, it assumes that the RX burst size is equal to or greater than 32 per burst. It returns zero if using nb_pkt < 32 as the expected packet number in the receive handler. TX Constraint ~~~~~~~~~~~~~ Prerequisite ^^^^^^^^^^^^ The only prerequisite is related to tx_rs_thresh. The tx_rs_thresh value must be greater than or equal to RTE_PMD_IXGBE_TX_MAX_BURST, but less or equal to RTE_IXGBE_TX_MAX_FREE_BUF_SZ. Consequently, by default the tx_rs_thresh value is in the range 32 to 64. Feature not Supported by RX Vector PMD ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TX vPMD only works when txq_flags is set to IXGBE_SIMPLE_FLAGS. This means that it does not support TX multi-segment, VLAN offload and TX csum offload. The following MACROs are used for these three features: * ETH_TXQ_FLAGS_NOMULTSEGS * ETH_TXQ_FLAGS_NOVLANOFFL * ETH_TXQ_FLAGS_NOXSUMSCTP * ETH_TXQ_FLAGS_NOXSUMUDP * ETH_TXQ_FLAGS_NOXSUMTCP Sample Application Notes ~~~~~~~~~~~~~~~~~~~~~~~~ testpmd ^^^^^^^ By default, using CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=y: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c 300 -n 4 -- -i --burst=32 --rxfreet=32 --mbcache=250 --txpt=32 --rxht=8 --rxwt=0 --txfreet=32 --txrst=32 --txqflags=0xf01 When CONFIG_RTE_IXGBE_RX_OLFLAGS_ENABLE=n, better performance can be achieved: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c 300 -n 4 -- -i --burst=32 --rxfreet=32 --mbcache=250 --txpt=32 --rxht=8 --rxwt=0 --txfreet=32 --txrst=32 --txqflags=0xf01 --disable-hw-vlan l3fwd ^^^^^ When running l3fwd with vPMD, there is one thing to note. In the configuration, ensure that port_conf.rxmode.hw_ip_checksum=0. Otherwise, by default, RX vPMD is disabled. load_balancer ^^^^^^^^^^^^^ As in the case of l3fwd, set configure port_conf.rxmode.hw_ip_checksum=0 to enable vPMD. In addition, for improved performance, use -bsz "(32,32),(64,64),(32,32)" in load_balancer to avoid using the default burst size of 144. ================================================ FILE: doc/guides/nics/mlx4.rst ================================================ .. BSD LICENSE Copyright 2012-2015 6WIND S.A. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of 6WIND S.A. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MLX4 poll mode driver library ============================= The MLX4 poll mode driver library (**librte_pmd_mlx4**) implements support for **Mellanox ConnectX-3 EN** 10/40 Gbps adapters as well as their virtual functions (VF) in SR-IOV context. Information and documentation about this family of adapters can be found on the `Mellanox website `_. Help is also provided by the `Mellanox community `_. There is also a `section dedicated to this poll mode driver `_. .. note:: Due to external dependencies, this driver is disabled by default. It must be enabled manually by setting ``CONFIG_RTE_LIBRTE_MLX4_PMD=y`` and recompiling DPDK. .. warning:: ``CONFIG_RTE_BUILD_COMBINE_LIBS`` with ``CONFIG_RTE_BUILD_SHARED_LIB`` is not supported and thus the compilation will fail with this configuration. Implementation details ---------------------- Most Mellanox ConnectX-3 devices provide two ports but expose a single PCI bus address, thus unlike most drivers, librte_pmd_mlx4 registers itself as a PCI driver that allocates one Ethernet device per detected port. For this reason, one cannot white/blacklist a single port without also white/blacklisting the others on the same device. Besides its dependency on libibverbs (that implies libmlx4 and associated kernel support), librte_pmd_mlx4 relies heavily on system calls for control operations such as querying/updating the MTU and flow control parameters. For security reasons and robustness, this driver only deals with virtual memory addresses. The way resources allocations are handled by the kernel combined with hardware specifications that allow it to handle virtual memory addresses directly ensure that DPDK applications cannot access random physical memory (or memory that does not belong to the current process). This capability allows the PMD to coexist with kernel network interfaces which remain functional, although they stop receiving unicast packets as long as they share the same MAC address. Compiling librte_pmd_mlx4 causes DPDK to be linked against libibverbs. Features and limitations ------------------------ - RSS, also known as RCA, is supported. In this mode the number of configured RX queues must be a power of two. - VLAN filtering is supported. - Link state information is provided. - Promiscuous mode is supported. - All multicast mode is supported. - Multiple MAC addresses (unicast, multicast) can be configured. - Scattered packets are supported for TX and RX. - Inner L3/L4 (IP, TCP and UDP) TX/RX checksum offloading and validation. - Outer L3 (IP) TX/RX checksum offloading and validation for VXLAN frames. .. break - RSS hash key cannot be modified. - Hardware counters are not implemented (they are software counters). Configuration ------------- Compilation options ~~~~~~~~~~~~~~~~~~~ These options can be modified in the ``.config`` file. - ``CONFIG_RTE_LIBRTE_MLX4_PMD`` (default **n**) Toggle compilation of librte_pmd_mlx4 itself. - ``CONFIG_RTE_LIBRTE_MLX4_DEBUG`` (default **n**) Toggle debugging code and stricter compilation flags. Enabling this option adds additional run-time checks and debugging messages at the cost of lower performance. - ``CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N`` (default **4**) Number of scatter/gather elements (SGEs) per work request (WR). Lowering this number improves performance but also limits the ability to receive scattered packets (packets that do not fit a single mbuf). The default value is a safe tradeoff. - ``CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE`` (default **0**) Amount of data to be inlined during TX operations. Improves latency but lowers throughput. - ``CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE`` (default **8**) Maximum number of cached memory pools (MPs) per TX queue. Each MP from which buffers are to be transmitted must be associated to memory regions (MRs). This is a slow operation that must be cached. This value is always 1 for RX queues since they use a single MP. - ``CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS`` (default **1**) Toggle software counters. No counters are available if this option is disabled since hardware counters are not supported. Environment variables ~~~~~~~~~~~~~~~~~~~~~ - ``MLX4_INLINE_RECV_SIZE`` A nonzero value enables inline receive for packets up to that size. May significantly improve performance in some cases but lower it in others. Requires careful testing. Run-time configuration ~~~~~~~~~~~~~~~~~~~~~~ - The only constraint when RSS mode is requested is to make sure the number of RX queues is a power of two. This is a hardware requirement. - librte_pmd_mlx4 brings kernel network interfaces up during initialization because it is affected by their state. Forcing them down prevents packets reception. - **ethtool** operations on related kernel interfaces also affect the PMD. Kernel module parameters ~~~~~~~~~~~~~~~~~~~~~~~~ The **mlx4_core** kernel module has several parameters that affect the behavior and/or the performance of librte_pmd_mlx4. Some of them are described below. - **num_vfs** (integer or triplet, optionally prefixed by device address strings) Create the given number of VFs on the specified devices. - **log_num_mgm_entry_size** (integer) Device-managed flow steering (DMFS) is required by DPDK applications. It is enabled by using a negative value, the last four bits of which have a special meaning. - **-1**: force device-managed flow steering (DMFS). - **-7**: configure optimized steering mode to improve performance with the following limitation: VLAN filtering is not supported with this mode. This is the recommended mode in case VLAN filter is not needed. Prerequisites ------------- This driver relies on external libraries and kernel drivers for resources allocations and initialization. The following dependencies are not part of DPDK and must be installed separately: - **libibverbs** User space verbs framework used by librte_pmd_mlx4. This library provides a generic interface between the kernel and low-level user space drivers such as libmlx4. It allows slow and privileged operations (context initialization, hardware resources allocations) to be managed by the kernel and fast operations to never leave user space. - **libmlx4** Low-level user space driver library for Mellanox ConnectX-3 devices, it is automatically loaded by libibverbs. This library basically implements send/receive calls to the hardware queues. - **Kernel modules** (mlnx-ofed-kernel) They provide the kernel-side verbs API and low level device drivers that manage actual hardware initialization and resources sharing with user space processes. Unlike most other PMDs, these modules must remain loaded and bound to their devices: - mlx4_core: hardware driver managing Mellanox ConnectX-3 devices. - mlx4_en: Ethernet device driver that provides kernel network interfaces. - mlx4_ib: InifiniBand device driver. - ib_uverbs: user space driver for verbs (entry point for libibverbs). - **Firmware update** Mellanox OFED releases include firmware updates for ConnectX-3 adapters. Because each release provides new features, these updates must be applied to match the kernel modules and libraries they come with. .. note:: Both libraries are BSD and GPL licensed. Linux kernel modules are GPL licensed. Currently supported by DPDK: - Mellanox OFED **3.0**. - Firmware version **2.34.5000** and higher. Getting Mellanox OFED ~~~~~~~~~~~~~~~~~~~~~ While these libraries and kernel modules are available on OpenFabrics Alliance's `website `_ and provided by package managers on most distributions, this PMD requires Ethernet extensions that may not be supported at the moment (this is a work in progress). `Mellanox OFED `_ includes the necessary support and should be used in the meantime. For DPDK, only libibverbs, libmlx4, mlnx-ofed-kernel packages and firmware updates are required from that distribution. .. note:: Several versions of Mellanox OFED are available. Installing the version this DPDK release was developed and tested against is strongly recommended. Please check the `prerequisites`_. Usage example ------------- This section demonstrates how to launch **testpmd** with Mellanox ConnectX-3 devices managed by librte_pmd_mlx4. #. Load the kernel modules: .. code-block:: console modprobe -a ib_uverbs mlx4_en mlx4_core mlx4_ib .. note:: User space I/O kernel modules (uio and igb_uio) are not used and do not have to be loaded. #. Make sure Ethernet interfaces are in working order and linked to kernel verbs. Related sysfs entries should be present: .. code-block:: console ls -d /sys/class/net/*/device/infiniband_verbs/uverbs* | cut -d / -f 5 Example output: .. code-block:: console eth2 eth3 eth4 eth5 #. Optionally, retrieve their PCI bus addresses for whitelisting: .. code-block:: console { for intf in eth2 eth3 eth4 eth5; do (cd "/sys/class/net/${intf}/device/" && pwd -P); done; } | sed -n 's,.*/\(.*\),-w \1,p' Example output: .. code-block:: console -w 0000:83:00.0 -w 0000:83:00.0 -w 0000:84:00.0 -w 0000:84:00.0 .. note:: There are only two distinct PCI bus addresses because the Mellanox ConnectX-3 adapters installed on this system are dual port. #. Request huge pages: .. code-block:: console echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages/nr_hugepages #. Start testpmd with basic parameters: .. code-block:: console testpmd -c 0xff00 -n 4 -w 0000:83:00.0 -w 0000:84:00.0 -- --rxq=2 --txq=2 -i Example output: .. code-block:: console [...] EAL: PCI device 0000:83:00.0 on NUMA socket 1 EAL: probe driver: 15b3:1007 librte_pmd_mlx4 PMD: librte_pmd_mlx4: PCI information matches, using device "mlx4_0" (VF: false) PMD: librte_pmd_mlx4: 2 port(s) detected PMD: librte_pmd_mlx4: port 1 MAC address is 00:02:c9:b5:b7:50 PMD: librte_pmd_mlx4: port 2 MAC address is 00:02:c9:b5:b7:51 EAL: PCI device 0000:84:00.0 on NUMA socket 1 EAL: probe driver: 15b3:1007 librte_pmd_mlx4 PMD: librte_pmd_mlx4: PCI information matches, using device "mlx4_1" (VF: false) PMD: librte_pmd_mlx4: 2 port(s) detected PMD: librte_pmd_mlx4: port 1 MAC address is 00:02:c9:b5:ba:b0 PMD: librte_pmd_mlx4: port 2 MAC address is 00:02:c9:b5:ba:b1 Interactive-mode selected Configuring Port 0 (socket 0) PMD: librte_pmd_mlx4: 0x867d60: TX queues number update: 0 -> 2 PMD: librte_pmd_mlx4: 0x867d60: RX queues number update: 0 -> 2 Port 0: 00:02:C9:B5:B7:50 Configuring Port 1 (socket 0) PMD: librte_pmd_mlx4: 0x867da0: TX queues number update: 0 -> 2 PMD: librte_pmd_mlx4: 0x867da0: RX queues number update: 0 -> 2 Port 1: 00:02:C9:B5:B7:51 Configuring Port 2 (socket 0) PMD: librte_pmd_mlx4: 0x867de0: TX queues number update: 0 -> 2 PMD: librte_pmd_mlx4: 0x867de0: RX queues number update: 0 -> 2 Port 2: 00:02:C9:B5:BA:B0 Configuring Port 3 (socket 0) PMD: librte_pmd_mlx4: 0x867e20: TX queues number update: 0 -> 2 PMD: librte_pmd_mlx4: 0x867e20: RX queues number update: 0 -> 2 Port 3: 00:02:C9:B5:BA:B1 Checking link statuses... Port 0 Link Up - speed 10000 Mbps - full-duplex Port 1 Link Up - speed 40000 Mbps - full-duplex Port 2 Link Up - speed 10000 Mbps - full-duplex Port 3 Link Up - speed 40000 Mbps - full-duplex Done testpmd> ================================================ FILE: doc/guides/nics/pcap_ring.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Libpcap and Ring Based Poll Mode Drivers ======================================== In addition to Poll Mode Drivers (PMDs) for physical and virtual hardware, the DPDK also includes two pure-software PMDs. These two drivers are: * A libpcap -based PMD (librte_pmd_pcap) that reads and writes packets using libpcap, - both from files on disk, as well as from physical NIC devices using standard Linux kernel drivers. * A ring-based PMD (librte_pmd_ring) that allows a set of software FIFOs (that is, rte_ring) to be accessed using the PMD APIs, as though they were physical NICs. .. note:: The libpcap -based PMD is disabled by default in the build configuration files, owing to an external dependency on the libpcap development files which must be installed on the board. Once the libpcap development files are installed, the library can be enabled by setting CONFIG_RTE_LIBRTE_PMD_PCAP=y and recompiling the Intel® DPDK. Using the Drivers from the EAL Command Line ------------------------------------------- For ease of use, the DPDK EAL also has been extended to allow pseudo-Ethernet devices, using one or more of these drivers, to be created at application startup time during EAL initialization. To do so, the --vdev= parameter must be passed to the EAL. This takes take options to allow ring and pcap-based Ethernet to be allocated and used transparently by the application. This can be used, for example, for testing on a virtual machine where there are no Ethernet ports. Libpcap-based PMD ~~~~~~~~~~~~~~~~~ Pcap-based devices can be created using the virtual device --vdev option. The device name must start with the eth_pcap prefix followed by numbers or letters. The name is unique for each device. Each device can have multiple stream options and multiple devices can be used. Multiple device definitions can be arranged using multiple --vdev. Device name and stream options must be separated by commas as shown below: .. code-block:: console $RTE_TARGET/app/testpmd -c f -n 4 --vdev 'eth_pcap0,stream_opt0=..,stream_opt1=..' --vdev='eth_pcap1,stream_opt0=..' Device Streams ^^^^^^^^^^^^^^ Multiple ways of stream definitions can be assessed and combined as long as the following two rules are respected: * A device is provided with two different streams - reception and transmission. * A device is provided with one network interface name used for reading and writing packets. The different stream types are: * rx_pcap: Defines a reception stream based on a pcap file. The driver reads each packet within the given pcap file as if it was receiving it from the wire. The value is a path to a valid pcap file. rx_pcap=/path/to/file.pcap * tx_pcap: Defines a transmission stream based on a pcap file. The driver writes each received packet to the given pcap file. The value is a path to a pcap file. The file is overwritten if it already exists and it is created if it does not. tx_pcap=/path/to/file.pcap * rx_iface: Defines a reception stream based on a network interface name. The driver reads packets coming from the given interface using the Linux kernel driver for that interface. The value is an interface name. rx_iface=eth0 * tx_iface: Defines a transmission stream based on a network interface name. The driver sends packets to the given interface using the Linux kernel driver for that interface. The value is an interface name. tx_iface=eth0 * iface: Defines a device mapping a network interface. The driver both reads and writes packets from and to the given interface. The value is an interface name. iface=eth0 Examples of Usage ^^^^^^^^^^^^^^^^^ Read packets from one pcap file and write them to another: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_pcap0,rx_pcap=/path/to/ file_rx.pcap,tx_pcap=/path/to/file_tx.pcap' -- --port-topology=chained Read packets from a network interface and write them to a pcap file: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_pcap0,rx_iface=eth0,tx_pcap=/path/to/file_tx.pcap' -- --port-topology=chained Read packets from a pcap file and write them to a network interface: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_pcap0,rx_pcap=/path/to/ file_rx.pcap,tx_iface=eth1' -- --port-topology=chained Forward packets through two network interfaces: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_pcap0,iface=eth0' --vdev='eth_pcap1;iface=eth1' Using libpcap-based PMD with the testpmd Application ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One of the first things that testpmd does before starting to forward packets is to flush the RX streams by reading the first 512 packets on every RX stream and discarding them. When using a libpcap-based PMD this behavior can be turned off using the following command line option: .. code-block:: console --no-flush-rx It is also available in the runtime command line: .. code-block:: console set flush_rx on/off It is useful for the case where the rx_pcap is being used and no packets are meant to be discarded. Otherwise, the first 512 packets from the input pcap file will be discarded by the RX flushing operation. .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_pcap0,rx_pcap=/path/to/ file_rx.pcap,tx_pcap=/path/to/file_tx.pcap' -- --port-topology=chained --no-flush-rx Rings-based PMD ~~~~~~~~~~~~~~~ To run a DPDK application on a machine without any Ethernet devices, a pair of ring-based rte_ethdevs can be used as below. The device names passed to the --vdev option must start with eth_ring and take no additional parameters. Multiple devices may be specified, separated by commas. .. code-block:: console ./testpmd -c E -n 4 --vdev=eth_ring0 --vdev=eth_ring1 -- -i EAL: Detected lcore 1 as core 1 on socket 0 ... Interactive-mode selected Configuring Port 0 (socket 0) Configuring Port 1 (socket 0) Checking link statuses... Port 0 Link Up - speed 10000 Mbps - full-duplex Port 1 Link Up - speed 10000 Mbps - full-duplex Done testpmd> start tx_first io packet forwarding - CRC stripping disabled - packets/burst=16 nb forwarding cores=1 - nb forwarding ports=2 RX queues=1 - RX desc=128 - RX free threshold=0 RX threshold registers: pthresh=8 hthresh=8 wthresh=4 TX queues=1 - TX desc=512 - TX free threshold=0 TX threshold registers: pthresh=36 hthresh=0 wthresh=0 TX RS bit threshold=0 - TXQ flags=0x0 testpmd> stop Telling cores to stop... Waiting for lcores to finish... .. image:: img/forward_stats.* .. code-block:: console +++++++++++++++ Accumulated forward statistics for allports++++++++++ RX-packets: 462384736 RX-dropped: 0 RX-total: 462384736 TX-packets: 462384768 TX-dropped: 0 TX-total: 462384768 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Done. Using the Poll Mode Driver from an Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Both drivers can provide similar APIs to allow the user to create a PMD, that is, rte_ethdev structure, instances at run-time in the end-application, for example, using rte_eth_from_rings() or rte_eth_from_pcaps() APIs. For the rings- based PMD, this functionality could be used, for example, to allow data exchange between cores using rings to be done in exactly the same way as sending or receiving packets from an Ethernet device. For the libpcap-based PMD, it allows an application to open one or more pcap files and use these as a source of packet input to the application. Usage Examples ^^^^^^^^^^^^^^ To create two pseudo-Ethernet ports where all traffic sent to a port is looped back for reception on the same port (error handling omitted for clarity): .. code-block:: c struct rte_ring *r1, *r2; int port1, port2; r1 = rte_ring_create("R1", 256, SOCKET0,RING_F_SP_ENQ|RING_F_SC_DEQ); r2 = rte_ring_create("R2", 256, SOCKET0, RING_F_SP_ENQ|RING_F_SC_DEQ); /* create an ethdev where RX and TX are done to/from r1, and * another from r2 */ port1 = rte_eth_from_rings(r1, 1, r1, 1, SOCKET0); port2 = rte_eth_from_rings(r2, 1, r2, 1, SOCKET0); To create two pseudo-Ethernet ports where the traffic is switched between them, that is, traffic sent to port 1 is read back from port 2 and vice-versa, the final two lines could be changed as below: .. code-block:: c port1 = rte_eth_from_rings(r1, 1, r2, 1, SOCKET0); port2 = rte_eth_from_rings(r2, 1, r1, 1, SOCKET0); This type of configuration could be useful in a pipeline model, for example, where one may want to have inter-core communication using pseudo Ethernet devices rather than raw rings, for reasons of API consistency. Enqueuing and dequeuing items from an rte_ring using the rings-based PMD may be slower than using the native rings API. This is because DPDK Ethernet drivers make use of function pointers to call the appropriate enqueue or dequeue functions, while the rte_ring specific functions are direct function calls in the code and are often inlined by the compiler. Once an ethdev has been created, for either a ring or a pcap-based PMD, it should be configured and started in the same way as a regular Ethernet device, that is, by calling rte_eth_dev_configure() to set the number of receive and transmit queues, then calling rte_eth_rx_queue_setup() / tx_queue_setup() for each of those queues and finally calling rte_eth_dev_start() to allow transmission and reception of packets to begin. ================================================ FILE: doc/guides/nics/virtio.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Poll Mode Driver for Emulated Virtio NIC ======================================== Virtio is a para-virtualization framework initiated by IBM, and supported by KVM hypervisor. In the Data Plane Development Kit (DPDK), we provide a virtio Poll Mode Driver (PMD) as a software solution, comparing to SRIOV hardware solution, for fast guest VM to guest VM communication and guest VM to host communication. Vhost is a kernel acceleration module for virtio qemu backend. The DPDK extends kni to support vhost raw socket interface, which enables vhost to directly read/ write packets from/to a physical port. With this enhancement, virtio could achieve quite promising performance. In future release, we will also make enhancement to vhost backend, releasing peak performance of virtio PMD driver. For basic qemu-KVM installation and other Intel EM poll mode driver in guest VM, please refer to Chapter "Driver for VM Emulated Devices". In this chapter, we will demonstrate usage of virtio PMD driver with two backends, standard qemu vhost back end and vhost kni back end. Virtio Implementation in DPDK ----------------------------- For details about the virtio spec, refer to Virtio PCI Card Specification written by Rusty Russell. As a PMD, virtio provides packet reception and transmission callbacks virtio_recv_pkts and virtio_xmit_pkts. In virtio_recv_pkts, index in range [vq->vq_used_cons_idx , vq->vq_ring.used->idx) in vring is available for virtio to burst out. In virtio_xmit_pkts, same index range in vring is available for virtio to clean. Virtio will enqueue to be transmitted packets into vring, advance the vq->vq_ring.avail->idx, and then notify the host back end if necessary. Features and Limitations of virtio PMD -------------------------------------- In this release, the virtio PMD driver provides the basic functionality of packet reception and transmission. * It supports merge-able buffers per packet when receiving packets and scattered buffer per packet when transmitting packets. The packet size supported is from 64 to 1518. * It supports multicast packets and promiscuous mode. * The descriptor number for the RX/TX queue is hard-coded to be 256 by qemu. If given a different descriptor number by the upper application, the virtio PMD generates a warning and fall back to the hard-coded value. * Features of mac/vlan filter are supported, negotiation with vhost/backend are needed to support them. When backend can't support vlan filter, virtio app on guest should disable vlan filter to make sure the virtio port is configured correctly. E.g. specify '--disable-hw-vlan' in testpmd command line. * RTE_PKTMBUF_HEADROOM should be defined larger than sizeof(struct virtio_net_hdr), which is 10 bytes. * Virtio does not support runtime configuration. * Virtio supports Link State interrupt. * Virtio supports software vlan stripping and inserting. * Virtio supports using port IO to get PCI resource when uio/igb_uio module is not available. Prerequisites ------------- The following prerequisites apply: * In the BIOS, turn VT-x and VT-d on * Linux kernel with KVM module; vhost module loaded and ioeventfd supported. Qemu standard backend without vhost support isn't tested, and probably isn't supported. Virtio with kni vhost Back End ------------------------------ This section demonstrates kni vhost back end example setup for Phy-VM Communication. .. _figure_host_vm_comms: .. figure:: img/host_vm_comms.* Host2VM Communication Example Using kni vhost Back End Host2VM communication example #. Load the kni kernel module: .. code-block:: console insmod rte_kni.ko Other basic DPDK preparations like hugepage enabling, uio port binding are not listed here. Please refer to the *DPDK Getting Started Guide* for detailed instructions. #. Launch the kni user application: .. code-block:: console examples/kni/build/app/kni -c 0xf -n 4 -- -p 0x1 -P --config="(0,1,3)" This command generates one network device vEth0 for physical port. If specify more physical ports, the generated network device will be vEth1, vEth2, and so on. For each physical port, kni creates two user threads. One thread loops to fetch packets from the physical NIC port into the kni receive queue. The other user thread loops to send packets in the kni transmit queue. For each physical port, kni also creates a kernel thread that retrieves packets from the kni receive queue, place them onto kni's raw socket's queue and wake up the vhost kernel thread to exchange packets with the virtio virt queue. For more details about kni, please refer to Chapter 24 "Kernel NIC Interface". #. Enable the kni raw socket functionality for the specified physical NIC port, get the generated file descriptor and set it in the qemu command line parameter. Always remember to set ioeventfd_on and vhost_on. Example: .. code-block:: console echo 1 > /sys/class/net/vEth0/sock_en fd=`cat /sys/class/net/vEth0/sock_fd` exec qemu-system-x86_64 -enable-kvm -cpu host \ -m 2048 -smp 4 -name dpdk-test1-vm1 \ -drive file=/data/DPDKVMS/dpdk-vm.img \ -netdev tap, fd=$fd,id=mynet_kni, script=no,vhost=on \ -device virtio-net-pci,netdev=mynet_kni,bus=pci.0,addr=0x3,ioeventfd=on \ -vnc:1 -daemonize In the above example, virtio port 0 in the guest VM will be associated with vEth0, which in turns corresponds to a physical port, which means received packets come from vEth0, and transmitted packets is sent to vEth0. #. In the guest, bind the virtio device to the uio_pci_generic kernel module and start the forwarding application. When the virtio port in guest bursts rx, it is getting packets from the raw socket's receive queue. When the virtio port bursts tx, it is sending packet to the tx_q. .. code-block:: console modprobe uio echo 512 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages modprobe uio_pci_generic python tools/dpdk_nic_bind.py -b uio_pci_generic 00:03.0 We use testpmd as the forwarding application in this example. .. figure:: img/console.* Running testpmd #. Use IXIA packet generator to inject a packet stream into the KNI physical port. The packet reception and transmission flow path is: IXIA packet generator->82599 PF->KNI rx queue->KNI raw socket queue->Guest VM virtio port 0 rx burst->Guest VM virtio port 0 tx burst-> KNI tx queue->82599 PF-> IXIA packet generator Virtio with qemu virtio Back End -------------------------------- .. _figure_host_vm_comms_qemu: .. figure:: img/host_vm_comms_qemu.* Host2VM Communication Example Using qemu vhost Back End .. code-block:: console qemu-system-x86_64 -enable-kvm -cpu host -m 2048 -smp 2 -mem-path /dev/ hugepages -mem-prealloc -drive file=/data/DPDKVMS/dpdk-vm1 -netdev tap,id=vm1_p1,ifname=tap0,script=no,vhost=on -device virtio-net-pci,netdev=vm1_p1,bus=pci.0,addr=0x3,ioeventfd=on -device pci-assign,host=04:10.1 \ In this example, the packet reception flow path is: IXIA packet generator->82599 PF->Linux Bridge->TAP0's socket queue-> Guest VM virtio port 0 rx burst-> Guest VM 82599 VF port1 tx burst-> IXIA packet generator The packet transmission flow is: IXIA packet generator-> Guest VM 82599 VF port1 rx burst-> Guest VM virtio port 0 tx burst-> tap -> Linux Bridge->82599 PF-> IXIA packet generator ================================================ FILE: doc/guides/nics/vmxnet3.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Poll Mode Driver for Paravirtual VMXNET3 NIC ============================================ The VMXNET3 adapter is the next generation of a paravirtualized NIC, introduced by VMware* ESXi. It is designed for performance and is not related to VMXNET or VMXENET2. It offers all the features available in VMXNET2, and adds several new features such as, multi-queue support (also known as Receive Side Scaling, RSS), IPv6 offloads, and MSI/MSI-X interrupt delivery. Because operating system vendors do not provide built-in drivers for this card, VMware Tools must be installed to have a driver for the VMXNET3 network adapter available. One can use the same device in a DPDK application with VMXNET3 PMD introduced in DPDK API. Currently, the driver provides basic support for using the device in a DPDK application running on a guest OS. Optimization is needed on the backend, that is, the VMware* ESXi vmkernel switch, to achieve optimal performance end-to-end. In this chapter, two setups with the use of the VMXNET3 PMD are demonstrated: #. Vmxnet3 with a native NIC connected to a vSwitch #. Vmxnet3 chaining VMs connected to a vSwitch VMXNET3 Implementation in the DPDK ---------------------------------- For details on the VMXNET3 device, refer to the VMXNET3 driver's vmxnet3 directory and support manual from VMware*. For performance details, refer to the following link from VMware: `http://www.vmware.com/pdf/vsp_4_vmxnet3_perf.pdf `_ As a PMD, the VMXNET3 driver provides the packet reception and transmission callbacks, vmxnet3_recv_pkts and vmxnet3_xmit_pkts. It does not support scattered packet reception as part of vmxnet3_recv_pkts and vmxnet3_xmit_pkts. Also, it does not support scattered packet reception as part of the device operations supported. The VMXNET3 PMD handles all the packet buffer memory allocation and resides in guest address space and it is solely responsible to free that memory when not needed. The packet buffers and features to be supported are made available to hypervisor via VMXNET3 PCI configuration space BARs. During RX/TX, the packet buffers are exchanged by their GPAs, and the hypervisor loads the buffers with packets in the RX case and sends packets to vSwitch in the TX case. The VMXNET3 PMD is compiled with vmxnet3 device headers. The interface is similar to that of the other PMDs available in the DPDK API. The driver pre-allocates the packet buffers and loads the command ring descriptors in advance. The hypervisor fills those packet buffers on packet arrival and write completion ring descriptors, which are eventually pulled by the PMD. After reception, the DPDK application frees the descriptors and loads new packet buffers for the coming packets. The interrupts are disabled and there is no notification required. This keeps performance up on the RX side, even though the device provides a notification feature. In the transmit routine, the DPDK application fills packet buffer pointers in the descriptors of the command ring and notifies the hypervisor. In response the hypervisor takes packets and passes them to the vSwitch. It writes into the completion descriptors ring. The rings are read by the PMD in the next transmit routine call and the buffers and descriptors are freed from memory. Features and Limitations of VMXNET3 PMD --------------------------------------- In release 1.6.0, the VMXNET3 PMD provides the basic functionality of packet reception and transmission. There are several options available for filtering packets at VMXNET3 device level including: #. MAC Address based filtering: * Unicast, Broadcast, All Multicast modes - SUPPORTED BY DEFAULT * Multicast with Multicast Filter table - NOT SUPPORTED * Promiscuous mode - SUPPORTED * RSS based load balancing between queues - SUPPORTED #. VLAN filtering: * VLAN tag based filtering without load balancing - SUPPORTED .. note:: * Release 1.6.0 does not support separate headers and body receive cmd_ring and hence, multiple segment buffers are not supported. Only cmd_ring_0 is used for packet buffers, one for each descriptor. * Receive and transmit of scattered packets is not supported. * Multicast with Multicast Filter table is not supported. Prerequisites ------------- The following prerequisites apply: * Before starting a VM, a VMXNET3 interface to a VM through VMware vSphere Client must be assigned. This is shown in the figure below. .. _figure_vmxnet3_int: .. figure:: img/vmxnet3_int.* Assigning a VMXNET3 interface to a VM using VMware vSphere Client .. note:: Depending on the Virtual Machine type, the VMware vSphere Client shows Ethernet adaptors while adding an Ethernet device. Ensure that the VM type used offers a VMXNET3 device. Refer to the VMware documentation for a listed of VMs. .. note:: Follow the *DPDK Getting Started Guide* to setup the basic DPDK environment. .. note:: Follow the *DPDK Sample Application's User Guide*, L2 Forwarding/L3 Forwarding and TestPMD for instructions on how to run a DPDK application using an assigned VMXNET3 device. VMXNET3 with a Native NIC Connected to a vSwitch ------------------------------------------------ This section describes an example setup for Phy-vSwitch-VM-Phy communication. .. _figure_vswitch_vm: .. figure:: img/vswitch_vm.* VMXNET3 with a Native NIC Connected to a vSwitch .. note:: Other instructions on preparing to use DPDK such as, hugepage enabling, uio port binding are not listed here. Please refer to *DPDK Getting Started Guide and DPDK Sample Application's User Guide* for detailed instructions. The packet reception and transmission flow path is:: Packet generator -> 82576 -> VMware ESXi vSwitch -> VMXNET3 device -> Guest VM VMXNET3 port 0 rx burst -> Guest VM 82599 VF port 0 tx burst -> 82599 VF -> Packet generator VMXNET3 Chaining VMs Connected to a vSwitch ------------------------------------------- The following figure shows an example VM-to-VM communication over a Phy-VM-vSwitch-VM-Phy communication channel. .. _figure_vm_vm_comms: .. figure:: img/vm_vm_comms.* VMXNET3 Chaining VMs Connected to a vSwitch .. note:: When using the L2 Forwarding or L3 Forwarding applications, a destination MAC address needs to be written in packets to hit the other VM's VMXNET3 interface. In this example, the packet flow path is:: Packet generator -> 82599 VF -> Guest VM 82599 port 0 rx burst -> Guest VM VMXNET3 port 1 tx burst -> VMXNET3 device -> VMware ESXi vSwitch -> VMXNET3 device -> Guest VM VMXNET3 port 0 rx burst -> Guest VM 82599 VF port 1 tx burst -> 82599 VF -> Packet generator ================================================ FILE: doc/guides/prog_guide/build_app.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Building_Your_Own_Application: Building Your Own Application ============================= Compiling a Sample Application in the Development Kit Directory --------------------------------------------------------------- When compiling a sample application (for example, hello world), the following variables must be exported: RTE_SDK and RTE_TARGET. .. code-block:: console ~/DPDK$ cd examples/helloworld/ ~/DPDK/examples/helloworld$ export RTE_SDK=/home/user/DPDK ~/DPDK/examples/helloworld$ export RTE_TARGET=x86_64-native-linuxapp-gcc ~/DPDK/examples/helloworld$ make CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map The binary is generated in the build directory by default: .. code-block:: console ~/DPDK/examples/helloworld$ ls build/app helloworld helloworld.map Build Your Own Application Outside the Development Kit ------------------------------------------------------ The sample application (Hello World) can be duplicated in a new directory as a starting point for your development: .. code-block:: console ~$ cp -r DPDK/examples/helloworld my_rte_app ~$ cd my_rte_app/ ~/my_rte_app$ export RTE_SDK=/home/user/DPDK ~/my_rte_app$ export RTE_TARGET=x86_64-native-linuxapp-gcc ~/my_rte_app$ make CC main.o LD helloworld INSTALL-APP helloworld INSTALL-MAP helloworld.map Customizing Makefiles --------------------- Application Makefile ~~~~~~~~~~~~~~~~~~~~ The default makefile provided with the Hello World sample application is a good starting point. It includes: * $(RTE_SDK)/mk/rte.vars.mk at the beginning * $(RTE_SDK)/mk/rte.extapp.mk at the end The user must define several variables: * APP: Contains the name of the application. * SRCS-y: List of source files (\*.c, \*.S). Library Makefile ~~~~~~~~~~~~~~~~ It is also possible to build a library in the same way: * Include $(RTE_SDK)/mk/rte.vars.mk at the beginning. * Include $(RTE_SDK)/mk/rte.extlib.mk at the end. The only difference is that APP should be replaced by LIB, which contains the name of the library. For example, libfoo.a. Customize Makefile Actions ~~~~~~~~~~~~~~~~~~~~~~~~~~ Some variables can be defined to customize Makefile actions. The most common are listed below. Refer to :ref:`Makefile Description ` section in :ref:`Development Kit Build System ` chapter for details. * VPATH: The path list where the build system will search for sources. By default, RTE_SRCDIR will be included in VPATH. * CFLAGS_my_file.o: The specific flags to add for C compilation of my_file.c. * CFLAGS: The flags to use for C compilation. * LDFLAGS: The flags to use for linking. * CPPFLAGS: The flags to use to provide flags to the C preprocessor (only useful when assembling .S files) * LDLIBS: A list of libraries to link with (for example, -L /path/to/libfoo - lfoo) ================================================ FILE: doc/guides/prog_guide/dev_kit_build_system.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Development_Kit_Build_System: Development Kit Build System ============================ The DPDK requires a build system for compilation activities and so on. This section describes the constraints and the mechanisms used in the DPDK framework. There are two use-cases for the framework: * Compilation of the DPDK libraries and sample applications; the framework generates specific binary libraries, include files and sample applications * Compilation of an external application or library, using an installed binary DPDK Building the Development Kit Binary ----------------------------------- The following provides details on how to build the DPDK binary. Build Directory Concept ~~~~~~~~~~~~~~~~~~~~~~~ After installation, a build directory structure is created. Each build directory contains include files, libraries, and applications: .. code-block:: console ~/DPDK$ ls app MAINTAINERS config Makefile COPYRIGHT mk doc scripts examples lib tools x86_64-native-linuxapp-gcc x86_64-native-linuxapp-icc i686-native-linuxapp-gcc i686-native-linuxapp-icc ... ~/DEV/DPDK$ ls i686-native-linuxapp-gcc app build hostapp include kmod lib Makefile ~/DEV/DPDK$ ls i686-native-linuxapp-gcc/app/ cmdline_test dump_cfg test testpmd cmdline_test.map dump_cfg.map test.map testpmd.map ~/DEV/DPDK$ ls i686-native-linuxapp-gcc/lib/ libethdev.a librte_hash.a librte_mbuf.a librte_pmd_ixgbe.a librte_cmdline.a librte_lpm.a librte_mempool.a librte_ring.a librte_eal.a librte_malloc.a librte_pmd_e1000.a librte_timer.a ~/DEV/DPDK$ ls i686-native-linuxapp-gcc/include/ arch rte_cpuflags.h rte_memcpy.h cmdline_cirbuf.h rte_cycles.h rte_memory.h cmdline.h rte_debug.h rte_mempool.h cmdline_parse_etheraddr.h rte_eal.h rte_memzone.h cmdline_parse.h rte_errno.h rte_pci_dev_ids.h cmdline_parse_ipaddr.h rte_ethdev.h rte_pci.h cmdline_parse_num.h rte_ether.h rte_per_lcore.h cmdline_parse_portlist.h rte_fbk_hash.h rte_prefetch.h cmdline_parse_string.h rte_hash_crc.h rte_random.h cmdline_rdline.h rte_hash.h rte_ring.h cmdline_socket.h rte_interrupts.h rte_rwlock.h cmdline_vt100.h rte_ip.h rte_sctp.h exec-env rte_jhash.h rte_spinlock.h rte_alarm.h rte_launch.h rte_string_fns.h rte_atomic.h rte_lcore.h rte_tailq.h rte_branch_prediction.h rte_log.h rte_tcp.h rte_byteorder.h rte_lpm.h rte_timer.h rte_common.h rte_malloc.h rte_udp.h rte_config.h rte_mbuf.h A build directory is specific to a configuration that includes architecture + execution environment + toolchain. It is possible to have several build directories sharing the same sources with different configurations. For instance, to create a new build directory called my_sdk_build_dir using the default configuration template config/defconfig_x86_64-linuxapp, we use: .. code-block:: console cd ${RTE_SDK} make config T=x86_64-native-linuxapp-gcc O=my_sdk_build_dir This creates a new my_sdk_build_dir directory. After that, we can compile by doing: .. code-block:: console cd my_sdk_build_dir make which is equivalent to: .. code-block:: console make O=my_sdk_build_dir The content of the my_sdk_build_dir is then: :: -- .config # used configuration -- Makefile # wrapper that calls head Makefile # with $PWD as build directory -- build #All temporary files used during build +--app # process, including . o, .d, and .cmd files. | +-- test # For libraries, we have the .a file. | +-- test.o # For applications, we have the elf file. | `-- ... +-- lib +-- librte_eal | `-- ... +-- librte_mempool | +-- mempool-file1.o | +-- .mempool-file1.o.cmd | +-- .mempool-file1.o.d | +-- mempool-file2.o | +-- .mempool-file2.o.cmd | +-- .mempool-file2.o.d | `-- mempool.a `-- ... -- include # All include files installed by libraries +-- librte_mempool.h # and applications are located in this +-- rte_eal.h # directory. The installed files can depend +-- rte_spinlock.h # on configuration if needed (environment, +-- rte_atomic.h # architecture, ..) `-- \*.h ... -- lib # all compiled libraries are copied in this +-- librte_eal.a # directory +-- librte_mempool.a `-- \*.a ... -- app # All compiled applications are installed + --test # here. It includes the binary in elf format Refer to :ref:`Development Kit Root Makefile Help ` for details about make commands that can be used from the root of DPDK. Building External Applications ------------------------------ Since DPDK is in essence a development kit, the first objective of end users will be to create an application using this SDK. To compile an application, the user must set the RTE_SDK and RTE_TARGET environment variables. .. code-block:: console export RTE_SDK=/opt/DPDK export RTE_TARGET=x86_64-native-linuxapp-gcc cd /path/to/my_app For a new application, the user must create their own Makefile that includes some .mk files, such as ${RTE_SDK}/mk/rte.vars.mk, and ${RTE_SDK}/mk/ rte.app.mk. This is described in :ref:`Building Your Own Application `. Depending on the chosen target (architecture, machine, executive environment, toolchain) defined in the Makefile or as an environment variable, the applications and libraries will compile using the appropriate .h files and will link with the appropriate .a files. These files are located in ${RTE_SDK}/arch-machine-execenv-toolchain, which is referenced internally by ${RTE_BIN_SDK}. To compile their application, the user just has to call make. The compilation result will be located in /path/to/my_app/build directory. Sample applications are provided in the examples directory. .. _Makefile_Description: Makefile Description -------------------- General Rules For DPDK Makefiles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the DPDK, Makefiles always follow the same scheme: #. Include $(RTE_SDK)/mk/rte.vars.mk at the beginning. #. Define specific variables for RTE build system. #. Include a specific $(RTE_SDK)/mk/rte.XYZ.mk, where XYZ can be app, lib, extapp, extlib, obj, gnuconfigure, and so on, depending on what kind of object you want to build. :ref:`See Makefile Types ` below. #. Include user-defined rules and variables. The following is a very simple example of an external application Makefile: .. code-block:: make include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = helloworld # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk .. _Makefile_Types: Makefile Types ~~~~~~~~~~~~~~ Depending on the .mk file which is included at the end of the user Makefile, the Makefile will have a different role. Note that it is not possible to build a library and an application in the same Makefile. For that, the user must create two separate Makefiles, possibly in two different directories. In any case, the rte.vars.mk file must be included in the user Makefile as soon as possible. Application ^^^^^^^^^^^ These Makefiles generate a binary application. * rte.app.mk: Application in the development kit framework * rte.extapp.mk: External application * rte.hostapp.mk: Host application in the development kit framework Library ^^^^^^^ Generate a .a library. * rte.lib.mk: Library in the development kit framework * rte.extlib.mk: external library * rte.hostlib.mk: host library in the development kit framework Install ^^^^^^^ * rte.install.mk: Does not build anything, it is only used to create links or copy files to the installation directory. This is useful for including files in the development kit framework. Kernel Module ^^^^^^^^^^^^^ * rte.module.mk: Build a kernel module in the development kit framework. Objects ^^^^^^^ * rte.obj.mk: Object aggregation (merge several .o in one) in the development kit framework. * rte.extobj.mk: Object aggregation (merge several .o in one) outside the development kit framework. Misc ^^^^ * rte.doc.mk: Documentation in the development kit framework * rte.gnuconfigure.mk: Build an application that is configure-based. * rte.subdir.mk: Build several directories in the development kit framework. .. _Useful_Variables_Provided_by_the_Build_System: Useful Variables Provided by the Build System ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * RTE_SDK: The absolute path to the DPDK sources. When compiling the development kit, this variable is automatically set by the framework. It has to be defined by the user as an environment variable if compiling an external application. * RTE_SRCDIR: The path to the root of the sources. When compiling the development kit, RTE_SRCDIR = RTE_SDK. When compiling an external application, the variable points to the root of external application sources. * RTE_OUTPUT: The path to which output files are written. Typically, it is $(RTE_SRCDIR)/build, but it can be overridden by the O= option in the make command line. * RTE_TARGET: A string identifying the target for which we are building. The format is arch-machine-execenv-toolchain. When compiling the SDK, the target is deduced by the build system from the configuration (.config). When building an external application, it must be specified by the user in the Makefile or as an environment variable. * RTE_SDK_BIN: References $(RTE_SDK)/$(RTE_TARGET). * RTE_ARCH: Defines the architecture (i686, x86_64). It is the same value as CONFIG_RTE_ARCH but without the double-quotes around the string. * RTE_MACHINE: Defines the machine. It is the same value as CONFIG_RTE_MACHINE but without the double-quotes around the string. * RTE_TOOLCHAIN: Defines the toolchain (gcc , icc). It is the same value as CONFIG_RTE_TOOLCHAIN but without the double-quotes around the string. * RTE_EXEC_ENV: Defines the executive environment (linuxapp). It is the same value as CONFIG_RTE_EXEC_ENV but without the double-quotes around the string. * RTE_KERNELDIR: This variable contains the absolute path to the kernel sources that will be used to compile the kernel modules. The kernel headers must be the same as the ones that will be used on the target machine (the machine that will run the application). By default, the variable is set to /lib/modules/$(shell uname -r)/build, which is correct when the target machine is also the build machine. Variables that Can be Set/Overridden in a Makefile Only ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * VPATH: The path list that the build system will search for sources. By default, RTE_SRCDIR will be included in VPATH. * CFLAGS: Flags to use for C compilation. The user should use += to append data in this variable. * LDFLAGS: Flags to use for linking. The user should use += to append data in this variable. * ASFLAGS: Flags to use for assembly. The user should use += to append data in this variable. * CPPFLAGS: Flags to use to give flags to C preprocessor (only useful when assembling .S files). The user should use += to append data in this variable. * LDLIBS: In an application, the list of libraries to link with (for example, -L /path/to/libfoo -lfoo ). The user should use += to append data in this variable. * SRC-y: A list of source files (.c, .S, or .o if the source is a binary) in case of application, library or object Makefiles. The sources must be available from VPATH. * INSTALL-y-$(INSTPATH): A list of files to be installed in $(INSTPATH). The files must be available from VPATH and will be copied in $(RTE_OUTPUT)/$(INSTPATH). Can be used in almost any RTE Makefile. * SYMLINK-y-$(INSTPATH): A list of files to be installed in $(INSTPATH). The files must be available from VPATH and will be linked (symbolically) in $(RTE_OUTPUT)/$(INSTPATH). This variable can be used in almost any DPDK Makefile. * PREBUILD: A list of prerequisite actions to be taken before building. The user should use += to append data in this variable. * POSTBUILD: A list of actions to be taken after the main build. The user should use += to append data in this variable. * PREINSTALL: A list of prerequisite actions to be taken before installing. The user should use += to append data in this variable. * POSTINSTALL: A list of actions to be taken after installing. The user should use += to append data in this variable. * PRECLEAN: A list of prerequisite actions to be taken before cleaning. The user should use += to append data in this variable. * POSTCLEAN: A list of actions to be taken after cleaning. The user should use += to append data in this variable. * DEPDIR-y: Only used in the development kit framework to specify if the build of the current directory depends on build of another one. This is needed to support parallel builds correctly. Variables that can be Set/Overridden by the User on the Command Line Only ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some variables can be used to configure the build system behavior. They are documented in :ref:`Development Kit Root Makefile Help ` and :ref:`External Application/Library Makefile Help ` * WERROR_CFLAGS: By default, this is set to a specific value that depends on the compiler. Users are encouraged to use this variable as follows: CFLAGS += $(WERROR_CFLAGS) This avoids the use of different cases depending on the compiler (icc or gcc). Also, this variable can be overridden from the command line, which allows bypassing of the flags for testing purposes. Variables that Can be Set/Overridden by the User in a Makefile or Command Line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * CFLAGS_my_file.o: Specific flags to add for C compilation of my_file.c. * LDFLAGS_my_app: Specific flags to add when linking my_app. * EXTRA_CFLAGS: The content of this variable is appended after CFLAGS when compiling. * EXTRA_LDFLAGS: The content of this variable is appended after LDFLAGS when linking. * EXTRA_LDLIBS: The content of this variable is appended after LDLIBS when linking. * EXTRA_ASFLAGS: The content of this variable is appended after ASFLAGS when assembling. * EXTRA_CPPFLAGS: The content of this variable is appended after CPPFLAGS when using a C preprocessor on assembly files. ================================================ FILE: doc/guides/prog_guide/dev_kit_root_make_help.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Development_Kit_Root_Makefile_Help: Development Kit Root Makefile Help ================================== The DPDK provides a root level Makefile with targets for configuration, building, cleaning, testing, installation and others. These targets are explained in the following sections. Configuration Targets --------------------- The configuration target requires the name of the target, which is specified using T=mytarget and it is mandatory. The list of available targets are in $(RTE_SDK)/config (remove the defconfig _ prefix). Configuration targets also support the specification of the name of the output directory, using O=mybuilddir. This is an optional parameter, the default output directory is build. * Config This will create a build directory, and generates a configuration from a template. A Makefile is also created in the new build directory. Example: .. code-block:: console make config O=mybuild T=x86_64-native-linuxapp-gcc Build Targets ------------- Build targets support the optional specification of the name of the output directory, using O=mybuilddir. The default output directory is build. * all, build or just make Build the DPDK in the output directory previously created by a make config. Example: .. code-block:: console make O=mybuild * clean Clean all objects created using make build. Example: .. code-block:: console make clean O=mybuild * %_sub Build a subdirectory only, without managing dependencies on other directories. Example: .. code-block:: console make lib/librte_eal_sub O=mybuild * %_clean Clean a subdirectory only. Example: .. code-block:: console make lib/librte_eal_clean O=mybuild Install Targets --------------- * Install Build the DPDK binary. Actually, this builds each supported target in a separate directory. The name of each directory is the name of the target. The name of the targets to install can be optionally specified using T=mytarget. The target name can contain wildcard \* characters. The list of available targets are in $(RTE_SDK)/config (remove the defconfig\_ prefix). Example: .. code-block:: console make install T=x86_64-* * Uninstall Remove installed target directories. Test Targets ------------ * test Launch automatic tests for a build directory specified using O=mybuilddir. It is optional, the default output directory is build. Example: .. code-block:: console make test O=mybuild * testall Launch automatic tests for all installed target directories (after a make install). The name of the targets to test can be optionally specified using T=mytarget. The target name can contain wildcard (\*) characters. The list of available targets are in $(RTE_SDK)/config (remove the defconfig\_ prefix). Examples: .. code-block:: console make testall, make testall T=x86_64-* Documentation Targets --------------------- * doc Generate the Doxygen documentation (API, html and pdf). * doc-api-html Generate the Doxygen API documentation in html. * doc-guides-html Generate the guides documentation in html. * doc-guides-pdf Generate the guides documentation in pdf. Deps Targets ------------ * depdirs This target is implicitly called by make config. Typically, there is no need for a user to call it, except if DEPDIRS-y variables have been updated in Makefiles. It will generate the file $(RTE_OUTPUT)/.depdirs. Example: .. code-block:: console make depdirs O=mybuild * depgraph This command generates a dot graph of dependencies. It can be displayed to debug circular dependency issues, or just to understand the dependencies. Example: .. code-block:: console make depgraph O=mybuild > /tmp/graph.dot && dotty /tmp/ graph.dot Misc Targets ------------ * help Show this help. Other Useful Command-line Variables ----------------------------------- The following variables can be specified on the command line: * V= Enable verbose build (show full compilation command line, and some intermediate commands). * D= Enable dependency debugging. This provides some useful information about why a target is built or not. * EXTRA_CFLAGS=, EXTRA_LDFLAGS=, EXTRA_LDLIBS=, EXTRA_ASFLAGS=, EXTRA_CPPFLAGS= Append specific compilation, link or asm flags. * CROSS= Specify a cross toolchain header that will prefix all gcc/binutils applications. This only works when using gcc. Make in a Build Directory ------------------------- All targets described above are called from the SDK root $(RTE_SDK). It is possible to run the same Makefile targets inside the build directory. For instance, the following command: .. code-block:: console cd $(RTE_SDK) make config O=mybuild T=x86_64-native-linuxapp-gcc make O=mybuild is equivalent to: .. code-block:: console cd $(RTE_SDK) make config O=mybuild T=x86_64-native-linuxapp-gcc cd mybuild # no need to specify O= now make Compiling for Debug ------------------- To compile the DPDK and sample applications with debugging information included and the optimization level set to 0, the EXTRA_CFLAGS environment variable should be set before compiling as follows: .. code-block:: console export EXTRA_CFLAGS='-O0 -g' The DPDK and any user or sample applications can then be compiled in the usual way. For example: .. code-block:: console make install T=x86_64-native-linuxapp-gcc make -C examples/ ================================================ FILE: doc/guides/prog_guide/env_abstraction_layer.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Environment_Abstraction_Layer: Environment Abstraction Layer ============================= The Environment Abstraction Layer (EAL) is responsible for gaining access to low-level resources such as hardware and memory space. It provides a generic interface that hides the environment specifics from the applications and libraries. It is the responsibility of the initialization routine to decide how to allocate these resources (that is, memory space, PCI devices, timers, consoles, and so on). Typical services expected from the EAL are: * DPDK Loading and Launching: The DPDK and its application are linked as a single application and must be loaded by some means. * Core Affinity/Assignment Procedures: The EAL provides mechanisms for assigning execution units to specific cores as well as creating execution instances. * System Memory Reservation: The EAL facilitates the reservation of different memory zones, for example, physical memory areas for device interactions. * PCI Address Abstraction: The EAL provides an interface to access PCI address space. * Trace and Debug Functions: Logs, dump_stack, panic and so on. * Utility Functions: Spinlocks and atomic counters that are not provided in libc. * CPU Feature Identification: Determine at runtime if a particular feature, for example, Intel® AVX is supported. Determine if the current CPU supports the feature set that the binary was compiled for. * Interrupt Handling: Interfaces to register/unregister callbacks to specific interrupt sources. * Alarm Functions: Interfaces to set/remove callbacks to be run at a specific time. EAL in a Linux-userland Execution Environment --------------------------------------------- In a Linux user space environment, the DPDK application runs as a user-space application using the pthread library. PCI information about devices and address space is discovered through the /sys kernel interface and through kernel modules such as uio_pci_generic, or igb_uio. Refer to the UIO: User-space drivers documentation in the Linux kernel. This memory is mmap'd in the application. The EAL performs physical memory allocation using mmap() in hugetlbfs (using huge page sizes to increase performance). This memory is exposed to DPDK service layers such as the :ref:`Mempool Library `. At this point, the DPDK services layer will be initialized, then through pthread setaffinity calls, each execution unit will be assigned to a specific logical core to run as a user-level thread. The time reference is provided by the CPU Time-Stamp Counter (TSC) or by the HPET kernel API through a mmap() call. Initialization and Core Launching ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Part of the initialization is done by the start function of glibc. A check is also performed at initialization time to ensure that the micro architecture type chosen in the config file is supported by the CPU. Then, the main() function is called. The core initialization and launch is done in rte_eal_init() (see the API documentation). It consist of calls to the pthread library (more specifically, pthread_self(), pthread_create(), and pthread_setaffinity_np()). .. _figure_linuxapp_launch: .. figure:: img/linuxapp_launch.* EAL Initialization in a Linux Application Environment .. note:: Initialization of objects, such as memory zones, rings, memory pools, lpm tables and hash tables, should be done as part of the overall application initialization on the master lcore. The creation and initialization functions for these objects are not multi-thread safe. However, once initialized, the objects themselves can safely be used in multiple threads simultaneously. Multi-process Support ~~~~~~~~~~~~~~~~~~~~~ The Linuxapp EAL allows a multi-process as well as a multi-threaded (pthread) deployment model. See chapter 2.20 :ref:`Multi-process Support ` for more details. Memory Mapping Discovery and Memory Reservation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The allocation of large contiguous physical memory is done using the hugetlbfs kernel filesystem. The EAL provides an API to reserve named memory zones in this contiguous memory. The physical address of the reserved memory for that memory zone is also returned to the user by the memory zone reservation API. .. note:: Memory reservations done using the APIs provided by the rte_malloc library are also backed by pages from the hugetlbfs filesystem. Xen Dom0 support without hugetbls ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The existing memory management implementation is based on the Linux kernel hugepage mechanism. However, Xen Dom0 does not support hugepages, so a new Linux kernel module rte_dom0_mm is added to workaround this limitation. The EAL uses IOCTL interface to notify the Linux kernel module rte_dom0_mm to allocate memory of specified size, and get all memory segments information from the module, and the EAL uses MMAP interface to map the allocated memory. For each memory segment, the physical addresses are contiguous within it but actual hardware addresses are contiguous within 2MB. PCI Access ~~~~~~~~~~ The EAL uses the /sys/bus/pci utilities provided by the kernel to scan the content on the PCI bus. To access PCI memory, a kernel module called uio_pci_generic provides a /dev/uioX device file and resource files in /sys that can be mmap'd to obtain access to PCI address space from the application. The DPDK-specific igb_uio module can also be used for this. Both drivers use the uio kernel feature (userland driver). Per-lcore and Shared Variables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. note:: lcore refers to a logical execution unit of the processor, sometimes called a hardware *thread*. Shared variables are the default behavior. Per-lcore variables are implemented using *Thread Local Storage* (TLS) to provide per-thread local storage. Logs ~~~~ A logging API is provided by EAL. By default, in a Linux application, logs are sent to syslog and also to the console. However, the log function can be overridden by the user to use a different logging mechanism. Trace and Debug Functions ^^^^^^^^^^^^^^^^^^^^^^^^^ There are some debug functions to dump the stack in glibc. The rte_panic() function can voluntarily provoke a SIG_ABORT, which can trigger the generation of a core file, readable by gdb. CPU Feature Identification ~~~~~~~~~~~~~~~~~~~~~~~~~~ The EAL can query the CPU at runtime (using the rte_cpu_get_feature() function) to determine which CPU features are available. User Space Interrupt Event ~~~~~~~~~~~~~~~~~~~~~~~~~~ + User Space Interrupt and Alarm Handling in Host Thread The EAL creates a host thread to poll the UIO device file descriptors to detect the interrupts. Callbacks can be registered or unregistered by the EAL functions for a specific interrupt event and are called in the host thread asynchronously. The EAL also allows timed callbacks to be used in the same way as for NIC interrupts. .. note:: In DPDK PMD, the only interrupts handled by the dedicated host thread are those for link status change, i.e. link up and link down notification. + RX Interrupt Event The receive and transmit routines provided by each PMD don't limit themselves to execute in polling thread mode. To ease the idle polling with tiny throughput, it's useful to pause the polling and wait until the wake-up event happens. The RX interrupt is the first choice to be such kind of wake-up event, but probably won't be the only one. EAL provides the event APIs for this event-driven thread mode. Taking linuxapp as an example, the implementation relies on epoll. Each thread can monitor an epoll instance in which all the wake-up events' file descriptors are added. The event file descriptors are created and mapped to the interrupt vectors according to the UIO/VFIO spec. From bsdapp's perspective, kqueue is the alternative way, but not implemented yet. EAL initializes the mapping between event file descriptors and interrupt vectors, while each device initializes the mapping between interrupt vectors and queues. In this way, EAL actually is unaware of the interrupt cause on the specific vector. The eth_dev driver takes responsibility to program the latter mapping. .. note:: Per queue RX interrupt event is only allowed in VFIO which supports multiple MSI-X vector. In UIO, the RX interrupt together with other interrupt causes shares the same vector. In this case, when RX interrupt and LSC(link status change) interrupt are both enabled(intr_conf.lsc == 1 && intr_conf.rxq == 1), only the former is capable. The RX interrupt are controlled/enabled/disabled by ethdev APIs - 'rte_eth_dev_rx_intr_*'. They return failure if the PMD hasn't support them yet. The intr_conf.rxq flag is used to turn on the capability of RX interrupt per device. Blacklisting ~~~~~~~~~~~~ The EAL PCI device blacklist functionality can be used to mark certain NIC ports as blacklisted, so they are ignored by the DPDK. The ports to be blacklisted are identified using the PCIe* description (Domain:Bus:Device.Function). Misc Functions ~~~~~~~~~~~~~~ Locks and atomic operations are per-architecture (i686 and x86_64). Memory Segments and Memory Zones (memzone) ------------------------------------------ The mapping of physical memory is provided by this feature in the EAL. As physical memory can have gaps, the memory is described in a table of descriptors, and each descriptor (called rte_memseg ) describes a contiguous portion of memory. On top of this, the memzone allocator's role is to reserve contiguous portions of physical memory. These zones are identified by a unique name when the memory is reserved. The rte_memzone descriptors are also located in the configuration structure. This structure is accessed using rte_eal_get_configuration(). The lookup (by name) of a memory zone returns a descriptor containing the physical address of the memory zone. Memory zones can be reserved with specific start address alignment by supplying the align parameter (by default, they are aligned to cache line size). The alignment value should be a power of two and not less than the cache line size (64 bytes). Memory zones can also be reserved from either 2 MB or 1 GB hugepages, provided that both are available on the system. Multiple pthread ---------------- DPDK usually pins one pthread per core to avoid the overhead of task switching. This allows for significant performance gains, but lacks flexibility and is not always efficient. Power management helps to improve the CPU efficiency by limiting the CPU runtime frequency. However, alternately it is possible to utilize the idle cycles available to take advantage of the full capability of the CPU. By taking advantage of cgroup, the CPU utilization quota can be simply assigned. This gives another way to improve the CPU efficiency, however, there is a prerequisite; DPDK must handle the context switching between multiple pthreads per core. For further flexibility, it is useful to set pthread affinity not only to a CPU but to a CPU set. EAL pthread and lcore Affinity ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The term "lcore" refers to an EAL thread, which is really a Linux/FreeBSD pthread. "EAL pthreads" are created and managed by EAL and execute the tasks issued by *remote_launch*. In each EAL pthread, there is a TLS (Thread Local Storage) called *_lcore_id* for unique identification. As EAL pthreads usually bind 1:1 to the physical CPU, the *_lcore_id* is typically equal to the CPU ID. When using multiple pthreads, however, the binding is no longer always 1:1 between an EAL pthread and a specified physical CPU. The EAL pthread may have affinity to a CPU set, and as such the *_lcore_id* will not be the same as the CPU ID. For this reason, there is an EAL long option '--lcores' defined to assign the CPU affinity of lcores. For a specified lcore ID or ID group, the option allows setting the CPU set for that EAL pthread. The format pattern: --lcores='[@cpu_set][,[@cpu_set],...]' 'lcore_set' and 'cpu_set' can be a single number, range or a group. A number is a "digit([0-9]+)"; a range is "-"; a group is "([,,...])". If a '\@cpu_set' value is not supplied, the value of 'cpu_set' will default to the value of 'lcore_set'. :: For example, "--lcores='1,2@(5-7),(3-5)@(0,2),(0,6),7-8'" which means start 9 EAL thread; lcore 0 runs on cpuset 0x41 (cpu 0,6); lcore 1 runs on cpuset 0x2 (cpu 1); lcore 2 runs on cpuset 0xe0 (cpu 5,6,7); lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2); lcore 6 runs on cpuset 0x41 (cpu 0,6); lcore 7 runs on cpuset 0x80 (cpu 7); lcore 8 runs on cpuset 0x100 (cpu 8). Using this option, for each given lcore ID, the associated CPUs can be assigned. It's also compatible with the pattern of corelist('-l') option. non-EAL pthread support ~~~~~~~~~~~~~~~~~~~~~~~ It is possible to use the DPDK execution context with any user pthread (aka. Non-EAL pthreads). In a non-EAL pthread, the *_lcore_id* is always LCORE_ID_ANY which identifies that it is not an EAL thread with a valid, unique, *_lcore_id*. Some libraries will use an alternative unique ID (e.g. TID), some will not be impacted at all, and some will work but with limitations (e.g. timer and mempool libraries). All these impacts are mentioned in :ref:`known_issue_label` section. Public Thread API ~~~~~~~~~~~~~~~~~ There are two public APIs ``rte_thread_set_affinity()`` and ``rte_pthread_get_affinity()`` introduced for threads. When they're used in any pthread context, the Thread Local Storage(TLS) will be set/get. Those TLS include *_cpuset* and *_socket_id*: * *_cpuset* stores the CPUs bitmap to which the pthread is affinitized. * *_socket_id* stores the NUMA node of the CPU set. If the CPUs in CPU set belong to different NUMA node, the *_socket_id* will be set to SOCKET_ID_ANY. .. _known_issue_label: Known Issues ~~~~~~~~~~~~ + rte_mempool The rte_mempool uses a per-lcore cache inside the mempool. For non-EAL pthreads, ``rte_lcore_id()`` will not return a valid number. So for now, when rte_mempool is used with non-EAL pthreads, the put/get operations will bypass the mempool cache and there is a performance penalty because of this bypass. Support for non-EAL mempool cache is currently being enabled. + rte_ring rte_ring supports multi-producer enqueue and multi-consumer dequeue. However, it is non-preemptive, this has a knock on effect of making rte_mempool non-preemptable. .. note:: The "non-preemptive" constraint means: - a pthread doing multi-producers enqueues on a given ring must not be preempted by another pthread doing a multi-producer enqueue on the same ring. - a pthread doing multi-consumers dequeues on a given ring must not be preempted by another pthread doing a multi-consumer dequeue on the same ring. Bypassing this constraint it may cause the 2nd pthread to spin until the 1st one is scheduled again. Moreover, if the 1st pthread is preempted by a context that has an higher priority, it may even cause a dead lock. This does not mean it cannot be used, simply, there is a need to narrow down the situation when it is used by multi-pthread on the same core. 1. It CAN be used for any single-producer or single-consumer situation. 2. It MAY be used by multi-producer/consumer pthread whose scheduling policy are all SCHED_OTHER(cfs). User SHOULD be aware of the performance penalty before using it. 3. It MUST not be used by multi-producer/consumer pthreads, whose scheduling policies are SCHED_FIFO or SCHED_RR. ``RTE_RING_PAUSE_REP_COUNT`` is defined for rte_ring to reduce contention. It's mainly for case 2, a yield is issued after number of times pause repeat. It adds a sched_yield() syscall if the thread spins for too long while waiting on the other thread to finish its operations on the ring. This gives the preempted thread a chance to proceed and finish with the ring enqueue/dequeue operation. + rte_timer Running ``rte_timer_manager()`` on a non-EAL pthread is not allowed. However, resetting/stopping the timer from a non-EAL pthread is allowed. + rte_log In non-EAL pthreads, there is no per thread loglevel and logtype, global loglevels are used. + misc The debug statistics of rte_ring, rte_mempool and rte_timer are not supported in a non-EAL pthread. cgroup control ~~~~~~~~~~~~~~ The following is a simple example of cgroup control usage, there are two pthreads(t0 and t1) doing packet I/O on the same core ($CPU). We expect only 50% of CPU spend on packet IO. .. code-block:: console mkdir /sys/fs/cgroup/cpu/pkt_io mkdir /sys/fs/cgroup/cpuset/pkt_io echo $cpu > /sys/fs/cgroup/cpuset/cpuset.cpus echo $t0 > /sys/fs/cgroup/cpu/pkt_io/tasks echo $t0 > /sys/fs/cgroup/cpuset/pkt_io/tasks echo $t1 > /sys/fs/cgroup/cpu/pkt_io/tasks echo $t1 > /sys/fs/cgroup/cpuset/pkt_io/tasks cd /sys/fs/cgroup/cpu/pkt_io echo 100000 > pkt_io/cpu.cfs_period_us echo 50000 > pkt_io/cpu.cfs_quota_us Malloc ------ The EAL provides a malloc API to allocate any-sized memory. The objective of this API is to provide malloc-like functions to allow allocation from hugepage memory and to facilitate application porting. The *DPDK API Reference* manual describes the available functions. Typically, these kinds of allocations should not be done in data plane processing because they are slower than pool-based allocation and make use of locks within the allocation and free paths. However, they can be used in configuration code. Refer to the rte_malloc() function description in the *DPDK API Reference* manual for more information. Cookies ~~~~~~~ When CONFIG_RTE_MALLOC_DEBUG is enabled, the allocated memory contains overwrite protection fields to help identify buffer overflows. Alignment and NUMA Constraints ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The rte_malloc() takes an align argument that can be used to request a memory area that is aligned on a multiple of this value (which must be a power of two). On systems with NUMA support, a call to the rte_malloc() function will return memory that has been allocated on the NUMA socket of the core which made the call. A set of APIs is also provided, to allow memory to be explicitly allocated on a NUMA socket directly, or by allocated on the NUMA socket where another core is located, in the case where the memory is to be used by a logical core other than on the one doing the memory allocation. Use Cases ~~~~~~~~~ This API is meant to be used by an application that requires malloc-like functions at initialization time. For allocating/freeing data at runtime, in the fast-path of an application, the memory pool library should be used instead. Internal Implementation ~~~~~~~~~~~~~~~~~~~~~~~ Data Structures ^^^^^^^^^^^^^^^ There are two data structure types used internally in the malloc library: * struct malloc_heap - used to track free space on a per-socket basis * struct malloc_elem - the basic element of allocation and free-space tracking inside the library. Structure: malloc_heap """""""""""""""""""""" The malloc_heap structure is used to manage free space on a per-socket basis. Internally, there is one heap structure per NUMA node, which allows us to allocate memory to a thread based on the NUMA node on which this thread runs. While this does not guarantee that the memory will be used on that NUMA node, it is no worse than a scheme where the memory is always allocated on a fixed or random node. The key fields of the heap structure and their function are described below (see also diagram above): * lock - the lock field is needed to synchronize access to the heap. Given that the free space in the heap is tracked using a linked list, we need a lock to prevent two threads manipulating the list at the same time. * free_head - this points to the first element in the list of free nodes for this malloc heap. .. note:: The malloc_heap structure does not keep track of in-use blocks of memory, since these are never touched except when they are to be freed again - at which point the pointer to the block is an input to the free() function. .. _figure_malloc_heap: .. figure:: img/malloc_heap.* Example of a malloc heap and malloc elements within the malloc library .. _malloc_elem: Structure: malloc_elem """""""""""""""""""""" The malloc_elem structure is used as a generic header structure for various blocks of memory. It is used in three different ways - all shown in the diagram above: #. As a header on a block of free or allocated memory - normal case #. As a padding header inside a block of memory #. As an end-of-memseg marker The most important fields in the structure and how they are used are described below. .. note:: If the usage of a particular field in one of the above three usages is not described, the field can be assumed to have an undefined value in that situation, for example, for padding headers only the "state" and "pad" fields have valid values. * heap - this pointer is a reference back to the heap structure from which this block was allocated. It is used for normal memory blocks when they are being freed, to add the newly-freed block to the heap's free-list. * prev - this pointer points to the header element/block in the memseg immediately behind the current one. When freeing a block, this pointer is used to reference the previous block to check if that block is also free. If so, then the two free blocks are merged to form a single larger block. * next_free - this pointer is used to chain the free-list of unallocated memory blocks together. It is only used in normal memory blocks; on ``malloc()`` to find a suitable free block to allocate and on ``free()`` to add the newly freed element to the free-list. * state - This field can have one of three values: ``FREE``, ``BUSY`` or ``PAD``. The former two are to indicate the allocation state of a normal memory block and the latter is to indicate that the element structure is a dummy structure at the end of the start-of-block padding, i.e. where the start of the data within a block is not at the start of the block itself, due to alignment constraints. In that case, the pad header is used to locate the actual malloc element header for the block. For the end-of-memseg structure, this is always a ``BUSY`` value, which ensures that no element, on being freed, searches beyond the end of the memseg for other blocks to merge with into a larger free area. * pad - this holds the length of the padding present at the start of the block. In the case of a normal block header, it is added to the address of the end of the header to give the address of the start of the data area, i.e. the value passed back to the application on a malloc. Within a dummy header inside the padding, this same value is stored, and is subtracted from the address of the dummy header to yield the address of the actual block header. * size - the size of the data block, including the header itself. For end-of-memseg structures, this size is given as zero, though it is never actually checked. For normal blocks which are being freed, this size value is used in place of a "next" pointer to identify the location of the next block of memory that in the case of being ``FREE``, the two free blocks can be merged into one. Memory Allocation ^^^^^^^^^^^^^^^^^ On EAL initialisation, all memsegs are setup as part of the malloc heap. This setup involves placing a dummy structure at the end with ``BUSY`` state, which may contain a sentinel value if ``CONFIG_RTE_MALLOC_DEBUG`` is enabled, and a proper :ref:`element header` with ``FREE`` at the start for each memseg. The ``FREE`` element is then added to the ``free_list`` for the malloc heap. When an application makes a call to a malloc-like function, the malloc function will first index the ``lcore_config`` structure for the calling thread, and determine the NUMA node of that thread. The NUMA node is used to index the array of ``malloc_heap`` structures which is passed as a parameter to the ``heap_alloc()`` function, along with the requested size, type, alignment and boundary parameters. The ``heap_alloc()`` function will scan the free_list of the heap, and attempt to find a free block suitable for storing data of the requested size, with the requested alignment and boundary constraints. When a suitable free element has been identified, the pointer to be returned to the user is calculated. The cache-line of memory immediately preceding this pointer is filled with a struct malloc_elem header. Because of alignment and boundary constraints, there could be free space at the start and/or end of the element, resulting in the following behavior: #. Check for trailing space. If the trailing space is big enough, i.e. > 128 bytes, then the free element is split. If it is not, then we just ignore it (wasted space). #. Check for space at the start of the element. If the space at the start is small, i.e. <=128 bytes, then a pad header is used, and the remaining space is wasted. If, however, the remaining space is greater, then the free element is split. The advantage of allocating the memory from the end of the existing element is that no adjustment of the free list needs to take place - the existing element on the free list just has its size pointer adjusted, and the following element has its "prev" pointer redirected to the newly created element. Freeing Memory ^^^^^^^^^^^^^^ To free an area of memory, the pointer to the start of the data area is passed to the free function. The size of the ``malloc_elem`` structure is subtracted from this pointer to get the element header for the block. If this header is of type ``PAD`` then the pad length is further subtracted from the pointer to get the proper element header for the entire block. From this element header, we get pointers to the heap from which the block was allocated and to where it must be freed, as well as the pointer to the previous element, and via the size field, we can calculate the pointer to the next element. These next and previous elements are then checked to see if they are also ``FREE``, and if so, they are merged with the current element. This means that we can never have two ``FREE`` memory blocks adjacent to one another, as they are always merged into a single block. ================================================ FILE: doc/guides/prog_guide/ext_app_lib_make_help.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _External_Application/Library_Makefile_help: External Application/Library Makefile help ========================================== External applications or libraries should include specific Makefiles from RTE_SDK, located in mk directory. These Makefiles are: * ${RTE_SDK}/mk/rte.extapp.mk: Build an application * ${RTE_SDK}/mk/rte.extlib.mk: Build a static library * ${RTE_SDK}/mk/rte.extobj.mk: Build objects (.o) Prerequisites ------------- The following variables must be defined: * ${RTE_SDK}: Points to the root directory of the DPDK. * ${RTE_TARGET}: Reference the target to be used for compilation (for example, x86_64-native-linuxapp-gcc). Build Targets ------------- Build targets support the specification of the name of the output directory, using O=mybuilddir. This is optional; the default output directory is build. * all, "nothing" (meaning just make) Build the application or the library in the specified output directory. Example: .. code-block:: console make O=mybuild * clean Clean all objects created using make build. Example: .. code-block:: console make clean O=mybuild Help Targets ------------ * help Show this help. Other Useful Command-line Variables ----------------------------------- The following variables can be specified at the command line: * S= Specify the directory in which the sources are located. By default, it is the current directory. * M= Specify the Makefile to call once the output directory is created. By default, it uses $(S)/Makefile. * V= Enable verbose build (show full compilation command line and some intermediate commands). * D= Enable dependency debugging. This provides some useful information about why a target must be rebuilt or not. * EXTRA_CFLAGS=, EXTRA_LDFLAGS=, EXTRA_ASFLAGS=, EXTRA_CPPFLAGS= Append specific compilation, link or asm flags. * CROSS= Specify a cross-toolchain header that will prefix all gcc/binutils applications. This only works when using gcc. Make from Another Directory --------------------------- It is possible to run the Makefile from another directory, by specifying the output and the source dir. For example: .. code-block:: console export RTE_SDK=/path/to/DPDK export RTE_TARGET=x86_64-native-linuxapp-icc make -f /path/to/my_app/Makefile S=/path/to/my_app O=/path/to/build_dir ================================================ FILE: doc/guides/prog_guide/extend_intel_dpdk.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Extending the DPDK ========================= This chapter describes how a developer can extend the DPDK to provide a new library, a new target, or support a new target. Example: Adding a New Library libfoo ------------------------------------ To add a new library to the DPDK, proceed as follows: #. Add a new configuration option: .. code-block:: bash for f in config/\*; do \ echo CONFIG_RTE_LIBFOO=y >> $f; done #. Create a new directory with sources: .. code-block:: console mkdir ${RTE_SDK}/lib/libfoo touch ${RTE_SDK}/lib/libfoo/foo.c touch ${RTE_SDK}/lib/libfoo/foo.h #. Add a foo() function in libfoo. Definition is in foo.c: .. code-block:: c void foo(void) { } Declaration is in foo.h: .. code-block:: c extern void foo(void); #. Update lib/Makefile: .. code-block:: console vi ${RTE_SDK}/lib/Makefile # add: # DIRS-$(CONFIG_RTE_LIBFOO) += libfoo #. Create a new Makefile for this library, for example, derived from mempool Makefile: .. code-block:: console cp ${RTE_SDK}/lib/librte_mempool/Makefile ${RTE_SDK}/lib/libfoo/ vi ${RTE_SDK}/lib/libfoo/Makefile # replace: # librte_mempool -> libfoo # rte_mempool -> foo #. Update mk/DPDK.app.mk, and add -lfoo in LDLIBS variable when the option is enabled. This will automatically add this flag when linking a DPDK application. #. Build the DPDK with the new library (we only show a specific target here): .. code-block:: console cd ${RTE_SDK} make config T=x86_64-native-linuxapp-gcc make #. Check that the library is installed: .. code-block:: console ls build/lib ls build/include Example: Using libfoo in the Test Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The test application is used to validate all functionality of the DPDK. Once you have added a library, a new test case should be added in the test application. * A new test_foo.c file should be added, that includes foo.h and calls the foo() function from test_foo(). When the test passes, the test_foo() function should return 0. * Makefile, test.h and commands.c must be updated also, to handle the new test case. * Test report generation: autotest.py is a script that is used to generate the test report that is available in the ${RTE_SDK}/doc/rst/test_report/autotests directory. This script must be updated also. If libfoo is in a new test family, the links in ${RTE_SDK}/doc/rst/test_report/test_report.rst must be updated. * Build the DPDK with the updated test application (we only show a specific target here): .. code-block:: console cd ${RTE_SDK} make config T=x86_64-native-linuxapp-gcc make ================================================ FILE: doc/guides/prog_guide/glossary.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Glossary ======== ACL Access Control List API Application Programming Interface ASLR Linux* kernel Address-Space Layout Randomization BSD Berkeley Software Distribution Clr Clear CIDR Classless Inter-Domain Routing Control Plane The control plane is concerned with the routing of packets and with providing a start or end point. Core A core may include several lcores or threads if the processor supports hyperthreading. Core Components A set of libraries provided by the DPDK, including eal, ring, mempool, mbuf, timers, and so on. CPU Central Processing Unit CRC Cyclic Redundancy Check ctrlmbuf An *mbuf* carrying control data. Data Plane In contrast to the control plane, the data plane in a network architecture are the layers involved when forwarding packets. These layers must be highly optimized to achieve good performance. DIMM Dual In-line Memory Module Doxygen A documentation generator used in the DPDK to generate the API reference. DPDK Data Plane Development Kit DRAM Dynamic Random Access Memory EAL The Environment Abstraction Layer (EAL) provides a generic interface that hides the environment specifics from the applications and libraries. The services expected from the EAL are: development kit loading and launching, core affinity/ assignment procedures, system memory allocation/description, PCI bus access, inter-partition communication. FIFO First In First Out FPGA Field Programmable Gate Array GbE Gigabit Ethernet HW Hardware HPET High Precision Event Timer; a hardware timer that provides a precise time reference on x86 platforms. ID Identifier IOCTL Input/Output Control I/O Input/Output IP Internet Protocol IPv4 Internet Protocol version 4 IPv6 Internet Protocol version 6 lcore A logical execution unit of the processor, sometimes called a *hardware thread*. KNI Kernel Network Interface L1 Layer 1 L2 Layer 2 L3 Layer 3 L4 Layer 4 LAN Local Area Network LPM Longest Prefix Match master lcore The execution unit that executes the main() function and that launches other lcores. mbuf An mbuf is a data structure used internally to carry messages (mainly network packets). The name is derived from BSD stacks. To understand the concepts of packet buffers or mbuf, refer to *TCP/IP Illustrated, Volume 2: The Implementation*. MESI Modified Exclusive Shared Invalid (CPU cache coherency protocol) MTU Maximum Transfer Unit NIC Network Interface Card OOO Out Of Order (execution of instructions within the CPU pipeline) NUMA Non-uniform Memory Access PCI Peripheral Connect Interface PHY An abbreviation for the physical layer of the OSI model. pktmbuf An *mbuf* carrying a network packet. PMD Poll Mode Driver QoS Quality of Service RCU Read-Copy-Update algorithm, an alternative to simple rwlocks. Rd Read RED Random Early Detection RSS Receive Side Scaling RTE Run Time Environment. Provides a fast and simple framework for fast packet processing, in a lightweight environment as a Linux* application and using Poll Mode Drivers (PMDs) to increase speed. Rx Reception Slave lcore Any *lcore* that is not the *master lcore*. Socket A physical CPU, that includes several *cores*. SLA Service Level Agreement srTCM Single Rate Three Color Marking SRTD Scheduler Round Trip Delay SW Software Target In the DPDK, the target is a combination of architecture, machine, executive environment and toolchain. For example: i686-native-linuxapp-gcc. TCP Transmission Control Protocol TC Traffic Class TLB Translation Lookaside Buffer TLS Thread Local Storage trTCM Two Rate Three Color Marking TSC Time Stamp Counter Tx Transmission TUN/TAP TUN and TAP are virtual network kernel devices. VLAN Virtual Local Area Network Wr Write WRED Weighted Random Early Detection WRR Weighted Round Robin ================================================ FILE: doc/guides/prog_guide/hash_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Hash_Library: Hash Library ============ The DPDK provides a Hash Library for creating hash table for fast lookup. The hash table is a data structure optimized for searching through a set of entries that are each identified by a unique key. For increased performance the DPDK Hash requires that all the keys have the same number of bytes which is set at the hash creation time. Hash API Overview ----------------- The main configuration parameters for the hash are: * Total number of hash entries * Size of the key in bytes The hash also allows the configuration of some low-level implementation related parameters such as: * Hash function to translate the key into a bucket index The main methods exported by the hash are: * Add entry with key: The key is provided as input. If a new entry is successfully added to the hash for the specified key, or there is already an entry in the hash for the specified key, then the position of the entry is returned. If the operation was not successful, for example due to lack of free entries in the hash, then a negative value is returned; * Delete entry with key: The key is provided as input. If an entry with the specified key is found in the hash, then the entry is removed from the hash and the position where the entry was found in the hash is returned. If no entry with the specified key exists in the hash, then a negative value is returned * Lookup for entry with key: The key is provided as input. If an entry with the specified key is found in the hash (lookup hit), then the position of the entry is returned, otherwise (lookup miss) a negative value is returned. Apart from these method explained above, the API allows the user three more options: * Add / lookup / delete with key and precomputed hash: Both the key and its precomputed hash are provided as input. This allows the user to perform these operations faster, as hash is already computed. * Add / lookup with key and data: A pair of key-value is provided as input. This allows the user to store not only the key, but also data which may be either a 8-byte integer or a pointer to external data (if data size is more than 8 bytes). * Combination of the two options above: User can provide key, precomputed hash and data. Also, the API contains a method to allow the user to look up entries in bursts, achieving higher performance than looking up individual entries, as the function prefetches next entries at the time it is operating with the first ones, which reduces significantly the impact of the necessary memory accesses. Notice that this method uses a pipeline of 8 entries (4 stages of 2 entries), so it is highly recommended to use at least 8 entries per burst. The actual data associated with each key can be either managed by the user using a separate table that mirrors the hash in terms of number of entries and position of each entry, as shown in the Flow Classification use case describes in the following sections, or stored in the hash table itself. The example hash tables in the L2/L3 Forwarding sample applications defines which port to forward a packet to based on a packet flow identified by the five-tuple lookup. However, this table could also be used for more sophisticated features and provide many other functions and actions that could be performed on the packets and flows. Implementation Details ---------------------- The hash table has two main tables: * First table is an array of entries which is further divided into buckets, with the same number of consecutive array entries in each bucket. Each entry contains the computed primary and secondary hashes of a given key (explained below), and an index to the second table. * The second table is an array of all the keys stored in the hash table and its data associated to each key. The hash library uses the cuckoo hash method to resolve collisions. For any input key, there are two possible buckets (primary and secondary/alternative location) where that key can be stored in the hash, therefore only the entries within those bucket need to be examined when the key is looked up. The lookup speed is achieved by reducing the number of entries to be scanned from the total number of hash entries down to the number of entries in the two hash buckets, as opposed to the basic method of linearly scanning all the entries in the array. The hash uses a hash function (configurable) to translate the input key into a 4-byte key signature. The bucket index is the key signature modulo the number of hash buckets. Once the buckets are identified, the scope of the hash add, delete and lookup operations is reduced to the entries in those buckets (it is very likely that entries are in the primary bucket). To speed up the search logic within the bucket, each hash entry stores the 4-byte key signature together with the full key for each hash entry. For large key sizes, comparing the input key against a key from the bucket can take significantly more time than comparing the 4-byte signature of the input key against the signature of a key from the bucket. Therefore, the signature comparison is done first and the full key comparison done only when the signatures matches. The full key comparison is still necessary, as two input keys from the same bucket can still potentially have the same 4-byte hash signature, although this event is relatively rare for hash functions providing good uniform distributions for the set of input keys. Example of lookup: First of all, the primary bucket is identified and entry is likely to be stored there. If signature was stored there, we compare its key against the one provided and return the position where it was stored and/or the data associated to that key if there is a match. If signature is not in the primary bucket, the secondary bucket is looked up, where same procedure is carried out. If there is no match there either, key is considered not to be in the table. Example of addition: Like lookup, the primary and secondary buckets are indentified. If there is an empty slot in the primary bucket, primary and secondary signatures are stored in that slot, key and data (if any) are added to the second table and an index to the position in the second table is stored in the slot of the first table. If there is no space in the primary bucket, one of the entries on that bucket is pushed to its alternative location, and the key to be added is inserted in its position. To know where the alternative bucket of the evicted entry is, the secondary signature is looked up and alternative bucket index is calculated from doing the modulo, as seen above. If there is room in the alternative bucket, the evicted entry is stored in it. If not, same process is repeated (one of the entries gets pushed) until a non full bucket is found. Notice that despite all the entry movement in the first table, the second table is not touched, which would impact greatly in performance. In the very unlikely event that table enters in a loop where same entries are being evicted indefinitely, key is considered not able to be stored. With random keys, this method allows the user to get around 90% of the table utilization, without having to drop any stored entry (LRU) or allocate more memory (extended buckets). Entry distribution in hash table -------------------------------- As mentioned above, Cuckoo hash implementation pushes elements out of their bucket, if there is a new entry to be added which primary location coincides with their current bucket, being pushed to their alternative location. Therefore, as user adds more entries to the hash table, distribution of the hash values in the buckets will change, being most of them in their primary location and a few in their secondary location, which the later will increase, as table gets busier. This information is quite useful, as performance may be lower as more entries are evicted to their secondary location. See the tables below showing example entry distribution as table utilization increases. .. _table_hash_lib_1: .. table:: Entry distribution measured with an example table with 1024 random entries using jhash algorithm +--------------+-----------------------+-------------------------+ | % Table used | % In Primary location | % In Secondary location | +==============+=======================+=========================+ | 25 | 100 | 0 | +--------------+-----------------------+-------------------------+ | 50 | 96.1 | 3.9 | +--------------+-----------------------+-------------------------+ | 75 | 88.2 | 11.8 | +--------------+-----------------------+-------------------------+ | 80 | 86.3 | 13.7 | +--------------+-----------------------+-------------------------+ | 85 | 83.1 | 16.9 | +--------------+-----------------------+-------------------------+ | 90 | 77.3 | 22.7 | +--------------+-----------------------+-------------------------+ | 95.8 | 64.5 | 35.5 | +--------------+-----------------------+-------------------------+ | .. _table_hash_lib_2: .. table:: Entry distribution measured with an example table with 1 million random entries using jhash algorithm +--------------+-----------------------+-------------------------+ | % Table used | % In Primary location | % In Secondary location | +==============+=======================+=========================+ | 50 | 96 | 4 | +--------------+-----------------------+-------------------------+ | 75 | 86.9 | 13.1 | +--------------+-----------------------+-------------------------+ | 80 | 83.9 | 16.1 | +--------------+-----------------------+-------------------------+ | 85 | 80.1 | 19.9 | +--------------+-----------------------+-------------------------+ | 90 | 74.8 | 25.2 | +--------------+-----------------------+-------------------------+ | 94.5 | 67.4 | 32.6 | +--------------+-----------------------+-------------------------+ .. note:: Last values on the tables above are the average maximum table utilization with random keys and using Jenkins hash function. Use Case: Flow Classification ----------------------------- Flow classification is used to map each input packet to the connection/flow it belongs to. This operation is necessary as the processing of each input packet is usually done in the context of their connection, so the same set of operations is applied to all the packets from the same flow. Applications using flow classification typically have a flow table to manage, with each separate flow having an entry associated with it in this table. The size of the flow table entry is application specific, with typical values of 4, 16, 32 or 64 bytes. Each application using flow classification typically has a mechanism defined to uniquely identify a flow based on a number of fields read from the input packet that make up the flow key. One example is to use the DiffServ 5-tuple made up of the following fields of the IP and transport layer packet headers: Source IP Address, Destination IP Address, Protocol, Source Port, Destination Port. The DPDK hash provides a generic method to implement an application specific flow classification mechanism. Given a flow table implemented as an array, the application should create a hash object with the same number of entries as the flow table and with the hash key size set to the number of bytes in the selected flow key. The flow table operations on the application side are described below: * Add flow: Add the flow key to hash. If the returned position is valid, use it to access the flow entry in the flow table for adding a new flow or updating the information associated with an existing flow. Otherwise, the flow addition failed, for example due to lack of free entries for storing new flows. * Delete flow: Delete the flow key from the hash. If the returned position is valid, use it to access the flow entry in the flow table to invalidate the information associated with the flow. * Lookup flow: Lookup for the flow key in the hash. If the returned position is valid (flow lookup hit), use the returned position to access the flow entry in the flow table. Otherwise (flow lookup miss) there is no flow registered for the current packet. References ---------- * Donald E. Knuth, The Art of Computer Programming, Volume 3: Sorting and Searching (2nd Edition), 1998, Addison-Wesley Professional ================================================ FILE: doc/guides/prog_guide/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Programmer's Guide ================== |today| **Contents** .. toctree:: :maxdepth: 3 :numbered: intro overview env_abstraction_layer ring_lib mempool_lib mbuf_lib poll_mode_drv ivshmem_lib link_bonding_poll_mode_drv_lib timer_lib hash_lib lpm_lib lpm6_lib packet_distrib_lib reorder_lib ip_fragment_reassembly_lib multi_proc_support kernel_nic_interface thread_safety_intel_dpdk_functions qos_framework power_man packet_classif_access_ctrl packet_framework vhost_lib port_hotplug_framework source_org dev_kit_build_system dev_kit_root_make_help extend_intel_dpdk build_app ext_app_lib_make_help perf_opt_guidelines writing_efficient_code profile_app glossary **Figures** :numref:`figure_architecture-overview` :ref:`figure_architecture-overview` :numref:`figure_linuxapp_launch` :ref:`figure_linuxapp_launch` :numref:`figure_malloc_heap` :ref:`figure_malloc_heap` :numref:`figure_ring1` :ref:`figure_ring1` :numref:`figure_ring-enqueue1` :ref:`figure_ring-enqueue1` :numref:`figure_ring-enqueue2` :ref:`figure_ring-enqueue2` :numref:`figure_ring-enqueue3` :ref:`figure_ring-enqueue3` :numref:`figure_ring-dequeue1` :ref:`figure_ring-dequeue1` :numref:`figure_ring-dequeue2` :ref:`figure_ring-dequeue2` :numref:`figure_ring-dequeue3` :ref:`figure_ring-dequeue3` :numref:`figure_ring-mp-enqueue1` :ref:`figure_ring-mp-enqueue1` :numref:`figure_ring-mp-enqueue2` :ref:`figure_ring-mp-enqueue2` :numref:`figure_ring-mp-enqueue3` :ref:`figure_ring-mp-enqueue3` :numref:`figure_ring-mp-enqueue4` :ref:`figure_ring-mp-enqueue4` :numref:`figure_ring-mp-enqueue5` :ref:`figure_ring-mp-enqueue5` :numref:`figure_ring-modulo1` :ref:`figure_ring-modulo1` :numref:`figure_ring-modulo2` :ref:`figure_ring-modulo2` :numref:`figure_memory-management` :ref:`figure_memory-management` :numref:`figure_memory-management2` :ref:`figure_memory-management2` :numref:`figure_mempool` :ref:`figure_mempool` :numref:`figure_mbuf1` :ref:`figure_mbuf1` :numref:`figure_mbuf2` :ref:`figure_mbuf2` :numref:`figure_multi_process_memory` :ref:`figure_multi_process_memory` :numref:`figure_kernel_nic_intf` :ref:`figure_kernel_nic_intf` :numref:`figure_pkt_flow_kni` :ref:`figure_pkt_flow_kni` :numref:`figure_vhost_net_arch2` :ref:`figure_vhost_net_arch2` :numref:`figure_kni_traffic_flow` :ref:`figure_kni_traffic_flow` :numref:`figure_pkt_proc_pipeline_qos` :ref:`figure_pkt_proc_pipeline_qos` :numref:`figure_hier_sched_blk` :ref:`figure_hier_sched_blk` :numref:`figure_sched_hier_per_port` :ref:`figure_sched_hier_per_port` :numref:`figure_data_struct_per_port` :ref:`figure_data_struct_per_port` :numref:`figure_prefetch_pipeline` :ref:`figure_prefetch_pipeline` :numref:`figure_pipe_prefetch_sm` :ref:`figure_pipe_prefetch_sm` :numref:`figure_blk_diag_dropper` :ref:`figure_blk_diag_dropper` :numref:`figure_flow_tru_droppper` :ref:`figure_flow_tru_droppper` :numref:`figure_ex_data_flow_tru_dropper` :ref:`figure_ex_data_flow_tru_dropper` :numref:`figure_pkt_drop_probability` :ref:`figure_pkt_drop_probability` :numref:`figure_drop_probability_graph` :ref:`figure_drop_probability_graph` :numref:`figure_figure32` :ref:`figure_figure32` :numref:`figure_figure33` :ref:`figure_figure33` :numref:`figure_figure34` :ref:`figure_figure34` :numref:`figure_figure35` :ref:`figure_figure35` :numref:`figure_figure37` :ref:`figure_figure37` :numref:`figure_figure38` :ref:`figure_figure38` :numref:`figure_figure39` :ref:`figure_figure39` **Tables** :numref:`table_qos_1` :ref:`table_qos_1` :numref:`table_qos_2` :ref:`table_qos_2` :numref:`table_qos_3` :ref:`table_qos_3` :numref:`table_qos_4` :ref:`table_qos_4` :numref:`table_qos_5` :ref:`table_qos_5` :numref:`table_qos_6` :ref:`table_qos_6` :numref:`table_qos_7` :ref:`table_qos_7` :numref:`table_qos_8` :ref:`table_qos_8` :numref:`table_qos_9` :ref:`table_qos_9` :numref:`table_qos_10` :ref:`table_qos_10` :numref:`table_qos_11` :ref:`table_qos_11` :numref:`table_qos_12` :ref:`table_qos_12` :numref:`table_qos_13` :ref:`table_qos_13` :numref:`table_qos_14` :ref:`table_qos_14` :numref:`table_qos_15` :ref:`table_qos_15` :numref:`table_qos_16` :ref:`table_qos_16` :numref:`table_qos_17` :ref:`table_qos_17` :numref:`table_qos_18` :ref:`table_qos_18` :numref:`table_qos_19` :ref:`table_qos_19` :numref:`table_qos_20` :ref:`table_qos_20` :numref:`table_qos_21` :ref:`table_qos_21` :numref:`table_qos_22` :ref:`table_qos_22` :numref:`table_qos_23` :ref:`table_qos_23` :numref:`table_qos_24` :ref:`table_qos_24` :numref:`table_qos_25` :ref:`table_qos_25` :numref:`table_qos_26` :ref:`table_qos_26` :numref:`table_qos_27` :ref:`table_qos_27` :numref:`table_qos_28` :ref:`table_qos_28` :numref:`table_qos_29` :ref:`table_qos_29` :numref:`table_qos_30` :ref:`table_qos_30` :numref:`table_qos_31` :ref:`table_qos_31` :numref:`table_qos_32` :ref:`table_qos_32` :numref:`table_qos_33` :ref:`table_qos_33` :numref:`table_qos_34` :ref:`table_qos_34` :numref:`table_hash_lib_1` :ref:`table_hash_lib_1` :numref:`table_hash_lib_2` :ref:`table_hash_lib_2` ================================================ FILE: doc/guides/prog_guide/intro.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ This document provides software architecture information, development environment information and optimization guidelines. For programming examples and for instructions on compiling and running each sample application, see the *DPDK Sample Applications User Guide* for details. For general information on compiling and running applications, see the *DPDK Getting Started Guide*. Documentation Roadmap --------------------- The following is a list of DPDK documents in the suggested reading order: * **Release Notes** (this document): Provides release-specific information, including supported features, limitations, fixed issues, known issues and so on. Also, provides the answers to frequently asked questions in FAQ format. * **Getting Started Guide** : Describes how to install and configure the DPDK software; designed to get users up and running quickly with the software. * **FreeBSD* Getting Started Guide** : A document describing the use of the DPDK with FreeBSD* has been added in DPDK Release 1.6.0. Refer to this guide for installation and configuration instructions to get started using the DPDK with FreeBSD*. * **Programmer's Guide** (this document): Describes: * The software architecture and how to use it (through examples), specifically in a Linux* application (linuxapp) environment * The content of the DPDK, the build system (including the commands that can be used in the root DPDK Makefile to build the development kit and an application) and guidelines for porting an application * Optimizations used in the software and those that should be considered for new development A glossary of terms is also provided. * **API Reference** : Provides detailed information about DPDK functions, data structures and other programming constructs. * **Sample Applications User Guide**: Describes a set of sample applications. Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. Related Publications -------------------- The following documents provide information that is relevant to the development of applications using the DPDK: * Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide ================================================ FILE: doc/guides/prog_guide/ip_fragment_reassembly_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IP Fragmentation and Reassembly Library ======================================= The IP Fragmentation and Reassembly Library implements IPv4 and IPv6 packet fragmentation and reassembly. Packet fragmentation -------------------- Packet fragmentation routines divide input packet into number of fragments. Both rte_ipv4_fragment_packet() and rte_ipv6_fragment_packet() functions assume that input mbuf data points to the start of the IP header of the packet (i.e. L2 header is already stripped out). To avoid copying of the actual packet's data zero-copy technique is used (rte_pktmbuf_attach). For each fragment two new mbufs are created: * Direct mbuf -- mbuf that will contain L3 header of the new fragment. * Indirect mbuf -- mbuf that is attached to the mbuf with the original packet. It's data field points to the start of the original packets data plus fragment offset. Then L3 header is copied from the original mbuf into the 'direct' mbuf and updated to reflect new fragmented status. Note that for IPv4, header checksum is not recalculated and is set to zero. Finally 'direct' and 'indirect' mbufs for each fragment are linked together via mbuf's next filed to compose a packet for the new fragment. The caller has an ability to explicitly specify which mempools should be used to allocate 'direct' and 'indirect' mbufs from. For more information about direct and indirect mbufs, refer to the *DPDK Programmers guide 7.7 Direct and Indirect Buffers.* Packet reassembly ----------------- IP Fragment Table ~~~~~~~~~~~~~~~~~ Fragment table maintains information about already received fragments of the packet. Each IP packet is uniquely identified by triple , , . Note that all update/lookup operations on Fragment Table are not thread safe. So if different execution contexts (threads/processes) will access the same table simultaneously, then some external syncing mechanism have to be provided. Each table entry can hold information about packets consisting of up to RTE_LIBRTE_IP_FRAG_MAX (by default: 4) fragments. Code example, that demonstrates creation of a new Fragment table: .. code-block:: c frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl; bucket_num = max_flow_num + max_flow_num / 4; frag_tbl = rte_ip_frag_table_create(max_flow_num, bucket_entries, max_flow_num, frag_cycles, socket_id); Internally Fragment table is a simple hash table. The basic idea is to use two hash functions and \* associativity. This provides 2 \* possible locations in the hash table for each key. When the collision occurs and all 2 \* are occupied, instead of reinserting existing keys into alternative locations, ip_frag_tbl_add() just returns a failure. Also, entries that resides in the table longer then are considered as invalid, and could be removed/replaced by the new ones. Note that reassembly demands a lot of mbuf's to be allocated. At any given time up to (2 \* bucket_entries \* RTE_LIBRTE_IP_FRAG_MAX \* ) can be stored inside Fragment Table waiting for remaining fragments. Packet Reassembly ~~~~~~~~~~~~~~~~~ Fragmented packets processing and reassembly is done by the rte_ipv4_frag_reassemble_packet()/rte_ipv6_frag_reassemble_packet. Functions. They either return a pointer to valid mbuf that contains reassembled packet, or NULL (if the packet can't be reassembled for some reason). These functions are responsible for: #. Search the Fragment Table for entry with packet's . #. If the entry is found, then check if that entry already timed-out. If yes, then free all previously received fragments, and remove information about them from the entry. #. If no entry with such key is found, then try to create a new one by one of two ways: a) Use as empty entry. b) Delete a timed-out entry, free mbufs associated with it mbufs and store a new entry with specified key in it. #. Update the entry with new fragment information and check if a packet can be reassembled (the packet's entry contains all fragments). a) If yes, then, reassemble the packet, mark table's entry as empty and return the reassembled mbuf to the caller. b) If no, then return a NULL to the caller. If at any stage of packet processing an error is encountered (e.g: can't insert new entry into the Fragment Table, or invalid/timed-out fragment), then the function will free all associated with the packet fragments, mark the table entry as invalid and return NULL to the caller. Debug logging and Statistics Collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The RTE_LIBRTE_IP_FRAG_TBL_STAT config macro controls statistics collection for the Fragment Table. This macro is not enabled by default. The RTE_LIBRTE_IP_FRAG_DEBUG controls debug logging of IP fragments processing and reassembling. This macro is disabled by default. Note that while logging contains a lot of detailed information, it slows down packet processing and might cause the loss of a lot of packets. ================================================ FILE: doc/guides/prog_guide/ivshmem_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IVSHMEM Library =============== The DPDK IVSHMEM library facilitates fast zero-copy data sharing among virtual machines (host-to-guest or guest-to-guest) by means of QEMU's IVSHMEM mechanism. The library works by providing a command line for QEMU to map several hugepages into a single IVSHMEM device. For the guest to know what is inside any given IVSHMEM device (and to distinguish between DPDK and non-DPDK IVSHMEM devices), a metadata file is also mapped into the IVSHMEM segment. No work needs to be done by the guest application to map IVSHMEM devices into memory; they are automatically recognized by the DPDK Environment Abstraction Layer (EAL). A typical DPDK IVSHMEM use case looks like the following. .. figure:: img/ivshmem.* Typical Ivshmem use case The same could work with several virtual machines, providing host-to-VM or VM-to-VM communication. The maximum number of metadata files is 32 (by default) and each metadata file can contain different (or even the same) hugepages. The only constraint is that each VM has to have access to the memory it is sharing with other entities (be it host or another VM). For example, if the user wants to share the same memzone across two VMs, each VM must have that memzone in its metadata file. IVHSHMEM Library API Overview ----------------------------- The following is a simple guide to using the IVSHMEM Library API: * Call rte_ivshmem_metadata_create() to create a new metadata file. The metadata name is used to distinguish between multiple metadata files. * Populate each metadata file with DPDK data structures. This can be done using the following API calls: * rte_ivhshmem_metadata_add_memzone() to add rte_memzone to metadata file * rte_ivshmem_metadata_add_ring() to add rte_ring to metadata file * rte_ivshmem_metadata_add_mempool() to add rte_mempool to metadata file * Finally, call rte_ivshmem_metadata_cmdline_generate() to generate the command line for QEMU. Multiple metadata files (and thus multiple command lines) can be supplied to a single VM. .. note:: Only data structures fully residing in DPDK hugepage memory work correctly. Supported data structures created by malloc(), mmap() or otherwise using non-DPDK memory cause undefined behavior and even a segmentation fault. IVSHMEM Environment Configuration --------------------------------- The steps needed to successfully run IVSHMEM applications are the following: * Compile a special version of QEMU from sources. The source code can be found on the QEMU website (currently, version 1.4.x is supported, but version 1.5.x is known to work also), however, the source code will need to be patched to support using regular files as the IVSHMEM memory backend. The patch is not included in the DPDK package, but is available on the `Intel®DPDK-vswitch project webpage `_ (either separately or in a DPDK vSwitch package). * Enable IVSHMEM library in the DPDK build configuration. In the default configuration, IVSHMEM library is not compiled. To compile the IVSHMEM library, one has to either use one of the provided IVSHMEM targets (for example, x86_64-ivshmem-linuxapp-gcc), or set CONFIG_RTE_LIBRTE_IVSHMEM to "y" in the build configuration. * Set up hugepage memory on the virtual machine. The guest applications run as regular DPDK (primary) processes and thus need their own hugepage memory set up inside the VM. The process is identical to the one described in the *DPDK Getting Started Guide*. Best Practices for Writing IVSHMEM Applications ----------------------------------------------- When considering the use of IVSHMEM for sharing memory, security implications need to be carefully evaluated. IVSHMEM is not suitable for untrusted guests, as IVSHMEM is essentially a window into the host process memory. This also has implications for the multiple VM scenarios. While the IVSHMEM library tries to share as little memory as possible, it is quite probable that data designated for one VM might also be present in an IVSMHMEM device designated for another VM. Consequently, any shared memory corruption will affect both host and all VMs sharing that particular memory. IVSHMEM applications essentially behave like multi-process applications, so it is important to implement access serialization to data and thread safety. DPDK ring structures are already thread-safe, however, any custom data structures that the user might need would have to be thread-safe also. Similar to regular DPDK multi-process applications, it is not recommended to use function pointers as functions might have different memory addresses in different processes. It is best to avoid freeing the rte_mbuf structure on a different machine from where it was allocated, that is, if the mbuf was allocated on the host, the host should free it. Consequently, any packet transmission and reception should also happen on the same machine (whether virtual or physical). Failing to do so may lead to data corruption in the mempool cache. Despite the IVSHMEM mechanism being zero-copy and having good performance, it is still desirable to do processing in batches and follow other procedures described in :ref:`Performance Optimization `. Best Practices for Running IVSHMEM Applications ----------------------------------------------- For performance reasons, it is best to pin host processes and QEMU processes to different cores so that they do not interfere with each other. If NUMA support is enabled, it is also desirable to keep host process' hugepage memory and QEMU process on the same NUMA node. For the best performance across all NUMA nodes, each QEMU core should be pinned to host CPU core on the appropriate NUMA node. QEMU's virtual NUMA nodes should also be set up to correspond to physical NUMA nodes. More on how to set up DPDK and QEMU NUMA support can be found in *DPDK Getting Started Guide* and `QEMU documentation `_ respectively. A script called cpu_layout.py is provided with the DPDK package (in the tools directory) that can be used to identify which CPU cores correspond to which NUMA node. The QEMU IVSHMEM command line creation should be considered the last step before starting the virtual machine. Currently, there is no hot plug support for QEMU IVSHMEM devices, so one cannot add additional memory to an IVSHMEM device once it has been created. Therefore, the correct sequence to run an IVSHMEM application is to run host application first, obtain the command lines for each IVSHMEM device and then run all QEMU instances with guest applications afterwards. It is important to note that once QEMU is started, it holds on to the hugepages it uses for IVSHMEM devices. As a result, if the user wishes to shut down or restart the IVSHMEM host application, it is not enough to simply shut the application down. The virtual machine must also be shut down (if not, it will hold onto outdated host data). ================================================ FILE: doc/guides/prog_guide/kernel_nic_interface.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Kernel NIC Interface ==================== The DPDK Kernel NIC Interface (KNI) allows userspace applications access to the Linux* control plane. The benefits of using the DPDK KNI are: * Faster than existing Linux TUN/TAP interfaces (by eliminating system calls and copy_to_user()/copy_from_user() operations. * Allows management of DPDK ports using standard Linux net tools such as ethtool, ifconfig and tcpdump. * Allows an interface with the kernel network stack. The components of an application using the DPDK Kernel NIC Interface are shown in :numref:`figure_kernel_nic_intf`. .. _figure_kernel_nic_intf: .. figure:: img/kernel_nic_intf.* Components of a DPDK KNI Application The DPDK KNI Kernel Module -------------------------- The KNI kernel loadable module provides support for two types of devices: * A Miscellaneous device (/dev/kni) that: * Creates net devices (via ioctl calls). * Maintains a kernel thread context shared by all KNI instances (simulating the RX side of the net driver). * For single kernel thread mode, maintains a kernel thread context shared by all KNI instances (simulating the RX side of the net driver). * For multiple kernel thread mode, maintains a kernel thread context for each KNI instance (simulating the RX side of the new driver). * Net device: * Net functionality provided by implementing several operations such as netdev_ops, header_ops, ethtool_ops that are defined by struct net_device, including support for DPDK mbufs and FIFOs. * The interface name is provided from userspace. * The MAC address can be the real NIC MAC address or random. KNI Creation and Deletion ------------------------- The KNI interfaces are created by a DPDK application dynamically. The interface name and FIFO details are provided by the application through an ioctl call using the rte_kni_device_info struct which contains: * The interface name. * Physical addresses of the corresponding memzones for the relevant FIFOs. * Mbuf mempool details, both physical and virtual (to calculate the offset for mbuf pointers). * PCI information. * Core affinity. Refer to rte_kni_common.h in the DPDK source code for more details. The physical addresses will be re-mapped into the kernel address space and stored in separate KNI contexts. Once KNI interfaces are created, the KNI context information can be queried by calling the rte_kni_info_get() function. The KNI interfaces can be deleted by a DPDK application dynamically after being created. Furthermore, all those KNI interfaces not deleted will be deleted on the release operation of the miscellaneous device (when the DPDK application is closed). DPDK mbuf Flow -------------- To minimize the amount of DPDK code running in kernel space, the mbuf mempool is managed in userspace only. The kernel module will be aware of mbufs, but all mbuf allocation and free operations will be handled by the DPDK application only. :numref:`figure_pkt_flow_kni` shows a typical scenario with packets sent in both directions. .. _figure_pkt_flow_kni: .. figure:: img/pkt_flow_kni.* Packet Flow via mbufs in the DPDK KNI Use Case: Ingress ----------------- On the DPDK RX side, the mbuf is allocated by the PMD in the RX thread context. This thread will enqueue the mbuf in the rx_q FIFO. The KNI thread will poll all KNI active devices for the rx_q. If an mbuf is dequeued, it will be converted to a sk_buff and sent to the net stack via netif_rx(). The dequeued mbuf must be freed, so the same pointer is sent back in the free_q FIFO. The RX thread, in the same main loop, polls this FIFO and frees the mbuf after dequeuing it. Use Case: Egress ---------------- For packet egress the DPDK application must first enqueue several mbufs to create an mbuf cache on the kernel side. The packet is received from the Linux net stack, by calling the kni_net_tx() callback. The mbuf is dequeued (without waiting due the cache) and filled with data from sk_buff. The sk_buff is then freed and the mbuf sent in the tx_q FIFO. The DPDK TX thread dequeues the mbuf and sends it to the PMD (via rte_eth_tx_burst()). It then puts the mbuf back in the cache. Ethtool ------- Ethtool is a Linux-specific tool with corresponding support in the kernel where each net device must register its own callbacks for the supported operations. The current implementation uses the igb/ixgbe modified Linux drivers for ethtool support. Ethtool is not supported in i40e and VMs (VF or EM devices). Link state and MTU change ------------------------- Link state and MTU change are network interface specific operations usually done via ifconfig. The request is initiated from the kernel side (in the context of the ifconfig process) and handled by the user space DPDK application. The application polls the request, calls the application handler and returns the response back into the kernel space. The application handlers can be registered upon interface creation or explicitly registered/unregistered in runtime. This provides flexibility in multiprocess scenarios (where the KNI is created in the primary process but the callbacks are handled in the secondary one). The constraint is that a single process can register and handle the requests. KNI Working as a Kernel vHost Backend ------------------------------------- vHost is a kernel module usually working as the backend of virtio (a para- virtualization driver framework) to accelerate the traffic from the guest to the host. The DPDK Kernel NIC interface provides the ability to hookup vHost traffic into userspace DPDK application. Together with the DPDK PMD virtio, it significantly improves the throughput between guest and host. In the scenario where DPDK is running as fast path in the host, kni-vhost is an efficient path for the traffic. Overview ~~~~~~~~ vHost-net has three kinds of real backend implementations. They are: 1) tap, 2) macvtap and 3) RAW socket. The main idea behind kni-vhost is making the KNI work as a RAW socket, attaching it as the backend instance of vHost-net. It is using the existing interface with vHost-net, so it does not require any kernel hacking, and is fully-compatible with the kernel vhost module. As vHost is still taking responsibility for communicating with the front-end virtio, it naturally supports both legacy virtio -net and the DPDK PMD virtio. There is a little penalty that comes from the non-polling mode of vhost. However, it scales throughput well when using KNI in multi-thread mode. .. _figure_vhost_net_arch2: .. figure:: img/vhost_net_arch.* vHost-net Architecture Overview Packet Flow ~~~~~~~~~~~ There is only a minor difference from the original KNI traffic flows. On transmit side, vhost kthread calls the RAW socket's ops sendmsg and it puts the packets into the KNI transmit FIFO. On the receive side, the kni kthread gets packets from the KNI receive FIFO, puts them into the queue of the raw socket, and wakes up the task in vhost kthread to begin receiving. All the packet copying, irrespective of whether it is on the transmit or receive side, happens in the context of vhost kthread. Every vhost-net device is exposed to a front end virtio device in the guest. .. _figure_kni_traffic_flow: .. figure:: img/kni_traffic_flow.* KNI Traffic Flow Sample Usage ~~~~~~~~~~~~ Before starting to use KNI as the backend of vhost, the CONFIG_RTE_KNI_VHOST configuration option must be turned on. Otherwise, by default, KNI will not enable its backend support capability. Of course, as a prerequisite, the vhost/vhost-net kernel CONFIG should be chosen before compiling the kernel. #. Compile the DPDK and insert uio_pci_generic/igb_uio kernel modules as normal. #. Insert the KNI kernel module: .. code-block:: console insmod ./rte_kni.ko If using KNI in multi-thread mode, use the following command line: .. code-block:: console insmod ./rte_kni.ko kthread_mode=multiple #. Running the KNI sample application: .. code-block:: console examples/kni/build/app/kni -c -0xf0 -n 4 -- -p 0x3 -P --config="(0,4,6),(1,5,7)" This command runs the kni sample application with two physical ports. Each port pins two forwarding cores (ingress/egress) in user space. #. Assign a raw socket to vhost-net during qemu-kvm startup. The DPDK does not provide a script to do this since it is easy for the user to customize. The following shows the key steps to launch qemu-kvm with kni-vhost: .. code-block:: bash #!/bin/bash echo 1 > /sys/class/net/vEth0/sock_en fd=`cat /sys/class/net/vEth0/sock_fd` qemu-kvm \ -name vm1 -cpu host -m 2048 -smp 1 -hda /opt/vm-fc16.img \ -netdev tap,fd=$fd,id=hostnet1,vhost=on \ -device virti-net-pci,netdev=hostnet1,id=net1,bus=pci.0,addr=0x4 It is simple to enable raw socket using sysfs sock_en and get raw socket fd using sock_fd under the KNI device node. Then, using the qemu-kvm command with the -netdev option to assign such raw socket fd as vhost's backend. .. note:: The key word tap must exist as qemu-kvm now only supports vhost with a tap backend, so here we cheat qemu-kvm by an existing fd. Compatibility Configure Option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There is a CONFIG_RTE_KNI_VHOST_VNET_HDR_EN configuration option in DPDK configuration file. By default, it set to n, which means do not turn on the virtio net header, which is used to support additional features (such as, csum offload, vlan offload, generic-segmentation and so on), since the kni-vhost does not yet support those features. Even if the option is turned on, kni-vhost will ignore the information that the header contains. When working with legacy virtio on the guest, it is better to turn off unsupported offload features using ethtool -K. Otherwise, there may be problems such as an incorrect L4 checksum error. ================================================ FILE: doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Link Bonding Poll Mode Driver Library ===================================== In addition to Poll Mode Drivers (PMDs) for physical and virtual hardware, DPDK also includes a pure-software library that allows physical PMD's to be bonded together to create a single logical PMD. .. figure:: img/bond-overview.* Bonded PMDs The Link Bonding PMD library(librte_pmd_bond) supports bonding of groups of ``rte_eth_dev`` ports of the same speed and duplex to provide similar the capabilities to that found in Linux bonding driver to allow the aggregation of multiple (slave) NICs into a single logical interface between a server and a switch. The new bonded PMD will then process these interfaces based on the mode of operation specified to provide support for features such as redundant links, fault tolerance and/or load balancing. The librte_pmd_bond library exports a C API which provides an API for the creation of bonded devices as well as the configuration and management of the bonded device and its slave devices. .. note:: The Link Bonding PMD Library is enabled by default in the build configuration files, the library can be disabled by setting ``CONFIG_RTE_LIBRTE_PMD_BOND=n`` and recompiling the DPDK. Link Bonding Modes Overview --------------------------- Currently the Link Bonding PMD library supports 4 modes of operation: * **Round-Robin (Mode 0):** .. figure:: img/bond-mode-0.* Round-Robin (Mode 0) This mode provides load balancing and fault tolerance by transmission of packets in sequential order from the first available slave device through the last. Packets are bulk dequeued from devices then serviced in a round-robin manner. This mode does not guarantee in order reception of packets and down stream should be able to handle out of order packets. * **Active Backup (Mode 1):** .. figure:: img/bond-mode-1.* Active Backup (Mode 1) In this mode only one slave in the bond is active at any time, a different slave becomes active if, and only if, the primary active slave fails, thereby providing fault tolerance to slave failure. The single logical bonded interface's MAC address is externally visible on only one NIC (port) to avoid confusing the network switch. * **Balance XOR (Mode 2):** .. figure:: img/bond-mode-2.* Balance XOR (Mode 2) This mode provides transmit load balancing (based on the selected transmission policy) and fault tolerance. The default policy (layer2) uses a simple calculation based on the packet flow source and destination MAC addresses as well as the number of active slaves available to the bonded device to classify the packet to a specific slave to transmit on. Alternate transmission policies supported are layer 2+3, this takes the IP source and destination addresses into the calculation of the transmit slave port and the final supported policy is layer 3+4, this uses IP source and destination addresses as well as the TCP/UDP source and destination port. .. note:: The coloring differences of the packets are used to identify different flow classification calculated by the selected transmit policy * **Broadcast (Mode 3):** .. figure:: img/bond-mode-3.* Broadcast (Mode 3) This mode provides fault tolerance by transmission of packets on all slave ports. * **Link Aggregation 802.3AD (Mode 4):** .. figure:: img/bond-mode-4.* Link Aggregation 802.3AD (Mode 4) This mode provides dynamic link aggregation according to the 802.3ad specification. It negotiates and monitors aggregation groups that share the same speed and duplex settings using the selected balance transmit policy for balancing outgoing traffic. DPDK implementation of this mode provide some additional requirements of the application. #. It needs to call ``rte_eth_tx_burst`` and ``rte_eth_rx_burst`` with intervals period of less than 100ms. #. Calls to ``rte_eth_tx_burst`` must have a buffer size of at least 2xN, where N is the number of slaves. This is a space required for LACP frames. Additionally LACP packets are included in the statistics, but they are not returned to the application. * **Transmit Load Balancing (Mode 5):** .. figure:: img/bond-mode-5.* Transmit Load Balancing (Mode 5) This mode provides an adaptive transmit load balancing. It dynamically changes the transmitting slave, according to the computed load. Statistics are collected in 100ms intervals and scheduled every 10ms. Implementation Details ---------------------- The librte_pmd_bond bonded device are compatible with the Ethernet device API exported by the Ethernet PMDs described in the *DPDK API Reference*. The Link Bonding Library supports the creation of bonded devices at application startup time during EAL initialization using the ``--vdev`` option as well as programmatically via the C API ``rte_eth_bond_create`` function. Bonded devices support the dynamical addition and removal of slave devices using the ``rte_eth_bond_slave_add`` / ``rte_eth_bond_slave_remove`` APIs. After a slave device is added to a bonded device slave is stopped using ``rte_eth_dev_stop`` and then reconfigured using ``rte_eth_dev_configure`` the RX and TX queues are also reconfigured using ``rte_eth_tx_queue_setup`` / ``rte_eth_rx_queue_setup`` with the parameters use to configure the bonding device. Link Status Change Interrupts / Polling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link bonding devices support the registration of a link status change callback, using the ``rte_eth_dev_callback_register`` API, this will be called when the status of the bonding device changes. For example in the case of a bonding device which has 3 slaves, the link status will change to up when one slave becomes active or change to down when all slaves become inactive. There is no callback notification when a single slave changes state and the previous conditions are not met. If a user wishes to monitor individual slaves then they must register callbacks with that slave directly. The link bonding library also supports devices which do not implement link status change interrupts, this is achieve by polling the devices link status at a defined period which is set using the ``rte_eth_bond_link_monitoring_set`` API, the default polling interval is 10ms. When a device is added as a slave to a bonding device it is determined using the ``RTE_PCI_DRV_INTR_LSC`` flag whether the device supports interrupts or whether the link status should be monitored by polling it. Requirements / Limitations ~~~~~~~~~~~~~~~~~~~~~~~~~~ The current implementation only supports devices that support the same speed and duplex to be added as a slaves to the same bonded device. The bonded device inherits these attributes from the first active slave added to the bonded device and then all further slaves added to the bonded device must support these parameters. A bonding device must have a minimum of one slave before the bonding device itself can be started. Like all other PMD, all functions exported by a PMD are lock-free functions that are assumed not to be invoked in parallel on different logical cores to work on the same target object. It should also be noted that the PMD receive function should not be invoked directly on a slave devices after they have been to a bonded device since packets read directly from the slave device will no longer be available to the bonded device to read. Configuration ~~~~~~~~~~~~~ Link bonding devices are created using the ``rte_eth_bond_create`` API which requires a unique device name, the bonding mode, and the socket Id to allocate the bonding device's resources on. The other configurable parameters for a bonded device are its slave devices, its primary slave, a user defined MAC address and transmission policy to use if the device is in balance XOR mode. Slave Devices ^^^^^^^^^^^^^ Bonding devices support up to a maximum of ``RTE_MAX_ETHPORTS`` slave devices of the same speed and duplex. Ethernet devices can be added as a slave to a maximum of one bonded device. Slave devices are reconfigured with the configuration of the bonded device on being added to a bonded device. The bonded also guarantees to return the MAC address of the slave device to its original value of removal of a slave from it. Primary Slave ^^^^^^^^^^^^^ The primary slave is used to define the default port to use when a bonded device is in active backup mode. A different port will only be used if, and only if, the current primary port goes down. If the user does not specify a primary port it will default to being the first port added to the bonded device. MAC Address ^^^^^^^^^^^ The bonded device can be configured with a user specified MAC address, this address will be inherited by the some/all slave devices depending on the operating mode. If the device is in active backup mode then only the primary device will have the user specified MAC, all other slaves will retain their original MAC address. In mode 0, 2, 3, 4 all slaves devices are configure with the bonded devices MAC address. If a user defined MAC address is not defined then the bonded device will default to using the primary slaves MAC address. Balance XOR Transmit Policies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There are 3 supported transmission policies for bonded device running in Balance XOR mode. Layer 2, Layer 2+3, Layer 3+4. * **Layer 2:** Ethernet MAC address based balancing is the default transmission policy for Balance XOR bonding mode. It uses a simple XOR calculation on the source MAC address and destination MAC address of the packet and then calculate the modulus of this value to calculate the slave device to transmit the packet on. * **Layer 2 + 3:** Ethernet MAC address & IP Address based balancing uses a combination of source/destination MAC addresses and the source/destination IP addresses of the data packet to decide which slave port the packet will be transmitted on. * **Layer 3 + 4:** IP Address & UDP Port based balancing uses a combination of source/destination IP Address and the source/destination UDP ports of the packet of the data packet to decide which slave port the packet will be transmitted on. All these policies support 802.1Q VLAN Ethernet packets, as well as IPv4, IPv6 and UDP protocols for load balancing. Using Link Bonding Devices -------------------------- The librte_pmd_bond library support two modes of device creation, the libraries export full C API or using the EAL command line to statically configure link bonding devices at application startup. Using the EAL option it is possible to use link bonding functionality transparently without specific knowledge of the libraries API, this can be used, for example, to add bonding functionality, such as active backup, to an existing application which has no knowledge of the link bonding C API. Using the Poll Mode Driver from an Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Using the librte_pmd_bond libraries API it is possible to dynamically create and manage link bonding device from within any application. Link bonding device are created using the ``rte_eth_bond_create`` API which requires a unique device name, the link bonding mode to initial the device in and finally the socket Id which to allocate the devices resources onto. After successful creation of a bonding device it must be configured using the generic Ethernet device configure API ``rte_eth_dev_configure`` and then the RX and TX queues which will be used must be setup using ``rte_eth_tx_queue_setup`` / ``rte_eth_rx_queue_setup``. Slave devices can be dynamically added and removed from a link bonding device using the ``rte_eth_bond_slave_add`` / ``rte_eth_bond_slave_remove`` APIs but at least one slave device must be added to the link bonding device before it can be started using ``rte_eth_dev_start``. The link status of a bonded device is dictated by that of its slaves, if all slave device link status are down or if all slaves are removed from the link bonding device then the link status of the bonding device will go down. It is also possible to configure / query the configuration of the control parameters of a bonded device using the provided APIs ``rte_eth_bond_mode_set/ get``, ``rte_eth_bond_primary_set/get``, ``rte_eth_bond_mac_set/reset`` and ``rte_eth_bond_xmit_policy_set/get``. Using Link Bonding Devices from the EAL Command Line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link bonding devices can be created at application startup time using the ``--vdev`` EAL command line option. The device name must start with the eth_bond prefix followed by numbers or letters. The name must be unique for each device. Each device can have multiple options arranged in a comma separated list. Multiple devices definitions can be arranged by calling the ``--vdev`` option multiple times. Device names and bonding options must be separated by commas as shown below: .. code-block:: console $RTE_TARGET/app/testpmd -c f -n 4 --vdev 'eth_bond0,bond_opt0=..,bond opt1=..'--vdev 'eth_bond1,bond _opt0=..,bond_opt1=..' Link Bonding EAL Options ^^^^^^^^^^^^^^^^^^^^^^^^ There are multiple ways of definitions that can be assessed and combined as long as the following two rules are respected: * A unique device name, in the format of eth_bondX is provided, where X can be any combination of numbers and/or letters, and the name is no greater than 32 characters long. * A least one slave device is provided with for each bonded device definition. * The operation mode of the bonded device being created is provided. The different options are: * mode: Integer value defining the bonding mode of the device. Currently supports modes 0,1,2,3,4,5 (round-robin, active backup, balance, broadcast, link aggregation, transmit load balancing). .. code-block:: console mode=2 * slave: Defines the PMD device which will be added as slave to the bonded device. This option can be selected multiple time, for each device to be added as a slave. Physical devices should be specified using their PCI address, in the format domain:bus:devid.function .. code-block:: console slave=0000:0a:00.0,slave=0000:0a:00.1 * primary: Optional parameter which defines the primary slave port, is used in active backup mode to select the primary slave for data TX/RX if it is available. The primary port also is used to select the MAC address to use when it is not defined by the user. This defaults to the first slave added to the device if it is specified. The primary device must be a slave of the bonded device. .. code-block:: console primary=0000:0a:00.0 * socket_id: Optional parameter used to select which socket on a NUMA device the bonded devices resources will be allocated on. .. code-block:: console socket_id=0 * mac: Optional parameter to select a MAC address for link bonding device, this overrides the value of the primary slave device. .. code-block:: console mac=00:1e:67:1d:fd:1d * xmit_policy: Optional parameter which defines the transmission policy when the bonded device is in balance mode. If not user specified this defaults to l2 (layer 2) forwarding, the other transmission policies available are l23 (layer 2+3) and l34 (layer 3+4) .. code-block:: console xmit_policy=l23 * lsc_poll_period_ms: Optional parameter which defines the polling interval in milli-seconds at which devices which don't support lsc interrupts are checked for a change in the devices link status .. code-block:: console lsc_poll_period_ms=100 * up_delay: Optional parameter which adds a delay in milli-seconds to the propagation of a devices link status changing to up, by default this parameter is zero. .. code-block:: console up_delay=10 * down_delay: Optional parameter which adds a delay in milli-seconds to the propagation of a devices link status changing to down, by default this parameter is zero. .. code-block:: console down_delay=50 Examples of Usage ^^^^^^^^^^^^^^^^^ Create a bonded device in round robin mode with two slaves specified by their PCI address: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_bond0,mode=0, slave=0000:00a:00.01,slave=0000:004:00.00' -- --port-topology=chained Create a bonded device in round robin mode with two slaves specified by their PCI address and an overriding MAC address: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_bond0,mode=0, slave=0000:00a:00.01,slave=0000:004:00.00,mac=00:1e:67:1d:fd:1d' -- --port-topology=chained Create a bonded device in active backup mode with two slaves specified, and a primary slave specified by their PCI addresses: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_bond0,mode=1, slave=0000:00a:00.01,slave=0000:004:00.00,primary=0000:00a:00.01' -- --port-topology=chained Create a bonded device in balance mode with two slaves specified by their PCI addresses, and a transmission policy of layer 3 + 4 forwarding: .. code-block:: console $RTE_TARGET/app/testpmd -c '0xf' -n 4 --vdev 'eth_bond0,mode=2, slave=0000:00a:00.01,slave=0000:004:00.00,xmit_policy=l34' -- --port-topology=chained ================================================ FILE: doc/guides/prog_guide/lpm6_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LPM6 Library ============ The LPM6 (LPM for IPv6) library component implements the Longest Prefix Match (LPM) table search method for 128-bit keys that is typically used to find the best match route in IPv6 forwarding applications. LPM6 API Overview ----------------- The main configuration parameters for the LPM6 library are: * Maximum number of rules: This defines the size of the table that holds the rules, and therefore the maximum number of rules that can be added. * Number of tbl8s: A tbl8 is a node of the trie that the LPM6 algorithm is based on. This parameter is related to the number of rules you can have, but there is no way to accurately predict the number needed to hold a specific number of rules, since it strongly depends on the depth and IP address of every rule. One tbl8 consumes 1 kb of memory. As a recommendation, 65536 tbl8s should be sufficient to store several thousand IPv6 rules, but the number can vary depending on the case. An LPM prefix is represented by a pair of parameters (128-bit key, depth), with depth in the range of 1 to 128. An LPM rule is represented by an LPM prefix and some user data associated with the prefix. The prefix serves as the unique identifier for the LPM rule. In this implementation, the user data is 1-byte long and is called "next hop", which corresponds to its main use of storing the ID of the next hop in a routing table entry. The main methods exported for the LPM component are: * Add LPM rule: The LPM rule is provided as input. If there is no rule with the same prefix present in the table, then the new rule is added to the LPM table. If a rule with the same prefix is already present in the table, the next hop of the rule is updated. An error is returned when there is no available space left. * Delete LPM rule: The prefix of the LPM rule is provided as input. If a rule with the specified prefix is present in the LPM table, then it is removed. * Lookup LPM key: The 128-bit key is provided as input. The algorithm selects the rule that represents the best match for the given key and returns the next hop of that rule. In the case that there are multiple rules present in the LPM table that have the same 128-bit value, the algorithm picks the rule with the highest depth as the best match rule, which means the rule has the highest number of most significant bits matching between the input key and the rule key. Implementation Details ~~~~~~~~~~~~~~~~~~~~~~ This is a modification of the algorithm used for IPv4 (see Section 19.2 "Implementation Details"). In this case, instead of using two levels, one with a tbl24 and a second with a tbl8, 14 levels are used. The implementation can be seen as a multi-bit trie where the *stride* or number of bits inspected on each level varies from level to level. Specifically, 24 bits are inspected on the root node, and the remaining 104 bits are inspected in groups of 8 bits. This effectively means that the trie has 14 levels at the most, depending on the rules that are added to the table. The algorithm allows the lookup operation to be performed with a number of memory accesses that directly depends on the length of the rule and whether there are other rules with bigger depths and the same key in the data structure. It can vary from 1 to 14 memory accesses, with 5 being the average value for the lengths that are most commonly used in IPv6. The main data structure is built using the following elements: * A table with 224 entries * A number of tables, configurable by the user through the API, with 28 entries The first table, called tbl24, is indexed using the first 24 bits of the IP address be looked up, while the rest of the tables, called tbl8s, are indexed using the rest of the bytes of the IP address, in chunks of 8 bits. This means that depending on the outcome of trying to match the IP address of an incoming packet to the rule stored in the tbl24 or the subsequent tbl8s we might need to continue the lookup process in deeper levels of the tree. Similar to the limitation presented in the algorithm for IPv4, to store every possible IPv6 rule, we would need a table with 2^128 entries. This is not feasible due to resource restrictions. By splitting the process in different tables/levels and limiting the number of tbl8s, we can greatly reduce memory consumption while maintaining a very good lookup speed (one memory access per level). .. figure:: img/tbl24_tbl8_tbl8.* Table split into different levels An entry in a table contains the following fields: * next hop / index to the tbl8 * depth of the rule (length) * valid flag * valid group flag * external entry flag The first field can either contain a number indicating the tbl8 in which the lookup process should continue or the next hop itself if the longest prefix match has already been found. The depth or length of the rule is the number of bits of the rule that is stored in a specific entry. The flags are used to determine whether the entry/table is valid or not and whether the search process have finished or not respectively. Both types of tables share the same structure. The other main data structure is a table containing the main information about the rules (IP, next hop and depth). This is a higher level table, used for different things: * Check whether a rule already exists or not, prior to addition or deletion, without having to actually perform a lookup. When deleting, to check whether there is a rule containing the one that is to be deleted. This is important, since the main data structure will have to be updated accordingly. Addition ~~~~~~~~ When adding a rule, there are different possibilities. If the rule's depth is exactly 24 bits, then: * Use the rule (IP address) as an index to the tbl24. * If the entry is invalid (i.e. it doesn't already contain a rule) then set its next hop to its value, the valid flag to 1 (meaning this entry is in use), and the external entry flag to 0 (meaning the lookup process ends at this point, since this is the longest prefix that matches). If the rule's depth is bigger than 24 bits but a multiple of 8, then: * Use the first 24 bits of the rule as an index to the tbl24. * If the entry is invalid (i.e. it doesn't already contain a rule) then look for a free tbl8, set the index to the tbl8 to this value, the valid flag to 1 (meaning this entry is in use), and the external entry flag to 1 (meaning the lookup process must continue since the rule hasn't been explored completely). * Use the following 8 bits of the rule as an index to the next tbl8. * Repeat the process until the tbl8 at the right level (depending on the depth) has been reached and fill it with the next hop, setting the next entry flag to 0. If the rule's depth is any other value, prefix expansion must be performed. This means the rule is copied to all the entries (as long as they are not in use) which would also cause a match. As a simple example, let's assume the depth is 20 bits. This means that there are 2^(24-20) = 16 different combinations of the first 24 bits of an IP address that would cause a match. Hence, in this case, we copy the exact same entry to every position indexed by one of these combinations. By doing this we ensure that during the lookup process, if a rule matching the IP address exists, it is found in, at the most, 14 memory accesses, depending on how many times we need to move to the next table. Prefix expansion is one of the keys of this algorithm, since it improves the speed dramatically by adding redundancy. Prefix expansion can be performed at any level. So, for example, is the depth is 34 bits, it will be performed in the third level (second tbl8-based level). Lookup ~~~~~~ The lookup process is much simpler and quicker. In this case: * Use the first 24 bits of the IP address as an index to the tbl24. If the entry is not in use, then it means we don't have a rule matching this IP. If it is valid and the external entry flag is set to 0, then the next hop is returned. * If it is valid and the external entry flag is set to 1, then we use the tbl8 index to find out the tbl8 to be checked, and the next 8 bits of the IP address as an index to this table. Similarly, if the entry is not in use, then we don't have a rule matching this IP address. If it is valid then check the external entry flag for a new tbl8 to be inspected. * Repeat the process until either we find an invalid entry (lookup miss) or a valid entry with the external entry flag set to 0. Return the next hop in the latter case. Limitations in the Number of Rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are different things that limit the number of rules that can be added. The first one is the maximum number of rules, which is a parameter passed through the API. Once this number is reached, it is not possible to add any more rules to the routing table unless one or more are removed. The second limitation is in the number of tbl8s available. If we exhaust tbl8s, we won't be able to add any more rules. How to know how many of them are necessary for a specific routing table is hard to determine in advance. In this algorithm, the maximum number of tbl8s a single rule can consume is 13, which is the number of levels minus one, since the first three bytes are resolved in the tbl24. However: * Typically, on IPv6, routes are not longer than 48 bits, which means rules usually take up to 3 tbl8s. As explained in the LPM for IPv4 algorithm, it is possible and very likely that several rules will share one or more tbl8s, depending on what their first bytes are. If they share the same first 24 bits, for instance, the tbl8 at the second level will be shared. This might happen again in deeper levels, so, effectively, two 48 bit-long rules may use the same three tbl8s if the only difference is in their last byte. The number of tbl8s is a parameter exposed to the user through the API in this version of the algorithm, due to its impact in memory consumption and the number or rules that can be added to the LPM table. One tbl8 consumes 1 kilobyte of memory. Use Case: IPv6 Forwarding ------------------------- The LPM algorithm is used to implement the Classless Inter-Domain Routing (CIDR) strategy used by routers implementing IP forwarding. ================================================ FILE: doc/guides/prog_guide/lpm_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _LPM_Library: LPM Library =========== The DPDK LPM library component implements the Longest Prefix Match (LPM) table search method for 32-bit keys that is typically used to find the best route match in IP forwarding applications. LPM API Overview ---------------- The main configuration parameter for LPM component instances is the maximum number of rules to support. An LPM prefix is represented by a pair of parameters (32- bit key, depth), with depth in the range of 1 to 32. An LPM rule is represented by an LPM prefix and some user data associated with the prefix. The prefix serves as the unique identifier of the LPM rule. In this implementation, the user data is 1-byte long and is called next hop, in correlation with its main use of storing the ID of the next hop in a routing table entry. The main methods exported by the LPM component are: * Add LPM rule: The LPM rule is provided as input. If there is no rule with the same prefix present in the table, then the new rule is added to the LPM table. If a rule with the same prefix is already present in the table, the next hop of the rule is updated. An error is returned when there is no available rule space left. * Delete LPM rule: The prefix of the LPM rule is provided as input. If a rule with the specified prefix is present in the LPM table, then it is removed. * Lookup LPM key: The 32-bit key is provided as input. The algorithm selects the rule that represents the best match for the given key and returns the next hop of that rule. In the case that there are multiple rules present in the LPM table that have the same 32-bit key, the algorithm picks the rule with the highest depth as the best match rule, which means that the rule has the highest number of most significant bits matching between the input key and the rule key. Implementation Details ---------------------- The current implementation uses a variation of the DIR-24-8 algorithm that trades memory usage for improved LPM lookup speed. The algorithm allows the lookup operation to be performed with typically a single memory read access. In the statistically rare case when the best match rule is having a depth bigger than 24, the lookup operation requires two memory read accesses. Therefore, the performance of the LPM lookup operation is greatly influenced by whether the specific memory location is present in the processor cache or not. The main data structure is built using the following elements: * A table with 2^24 entries. * A number of tables (RTE_LPM_TBL8_NUM_GROUPS) with 2^8 entries. The first table, called tbl24, is indexed using the first 24 bits of the IP address to be looked up, while the second table(s), called tbl8, is indexed using the last 8 bits of the IP address. This means that depending on the outcome of trying to match the IP address of an incoming packet to the rule stored in the tbl24 we might need to continue the lookup process in the second level. Since every entry of the tbl24 can potentially point to a tbl8, ideally, we would have 2^24 tbl8s, which would be the same as having a single table with 2^32 entries. This is not feasible due to resource restrictions. Instead, this approach takes advantage of the fact that rules longer than 24 bits are very rare. By splitting the process in two different tables/levels and limiting the number of tbl8s, we can greatly reduce memory consumption while maintaining a very good lookup speed (one memory access, most of the times). .. figure:: img/tbl24_tbl8.* Table split into different levels An entry in tbl24 contains the following fields: * next hop / index to the tbl8 * valid flag * external entry flag * depth of the rule (length) The first field can either contain a number indicating the tbl8 in which the lookup process should continue or the next hop itself if the longest prefix match has already been found. The two flags are used to determine whether the entry is valid or not and whether the search process have finished or not respectively. The depth or length of the rule is the number of bits of the rule that is stored in a specific entry. An entry in a tbl8 contains the following fields: * next hop * valid * valid group * depth Next hop and depth contain the same information as in the tbl24. The two flags show whether the entry and the table are valid respectively. The other main data structure is a table containing the main information about the rules (IP and next hop). This is a higher level table, used for different things: * Check whether a rule already exists or not, prior to addition or deletion, without having to actually perform a lookup. * When deleting, to check whether there is a rule containing the one that is to be deleted. This is important, since the main data structure will have to be updated accordingly. Addition ~~~~~~~~ When adding a rule, there are different possibilities. If the rule's depth is exactly 24 bits, then: * Use the rule (IP address) as an index to the tbl24. * If the entry is invalid (i.e. it doesn't already contain a rule) then set its next hop to its value, the valid flag to 1 (meaning this entry is in use), and the external entry flag to 0 (meaning the lookup process ends at this point, since this is the longest prefix that matches). If the rule's depth is exactly 32 bits, then: * Use the first 24 bits of the rule as an index to the tbl24. * If the entry is invalid (i.e. it doesn't already contain a rule) then look for a free tbl8, set the index to the tbl8 to this value, the valid flag to 1 (meaning this entry is in use), and the external entry flag to 1 (meaning the lookup process must continue since the rule hasn't been explored completely). If the rule's depth is any other value, prefix expansion must be performed. This means the rule is copied to all the entries (as long as they are not in use) which would also cause a match. As a simple example, let's assume the depth is 20 bits. This means that there are 2^(24 - 20) = 16 different combinations of the first 24 bits of an IP address that would cause a match. Hence, in this case, we copy the exact same entry to every position indexed by one of these combinations. By doing this we ensure that during the lookup process, if a rule matching the IP address exists, it is found in either one or two memory accesses, depending on whether we need to move to the next table or not. Prefix expansion is one of the keys of this algorithm, since it improves the speed dramatically by adding redundancy. Lookup ~~~~~~ The lookup process is much simpler and quicker. In this case: * Use the first 24 bits of the IP address as an index to the tbl24. If the entry is not in use, then it means we don't have a rule matching this IP. If it is valid and the external entry flag is set to 0, then the next hop is returned. * If it is valid and the external entry flag is set to 1, then we use the tbl8 index to find out the tbl8 to be checked, and the last 8 bits of the IP address as an index to this table. Similarly, if the entry is not in use, then we don't have a rule matching this IP address. If it is valid then the next hop is returned. Limitations in the Number of Rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are different things that limit the number of rules that can be added. The first one is the maximum number of rules, which is a parameter passed through the API. Once this number is reached, it is not possible to add any more rules to the routing table unless one or more are removed. The second reason is an intrinsic limitation of the algorithm. As explained before, to avoid high memory consumption, the number of tbl8s is limited in compilation time (this value is by default 256). If we exhaust tbl8s, we won't be able to add any more rules. How many of them are necessary for a specific routing table is hard to determine in advance. A tbl8 is consumed whenever we have a new rule with depth bigger than 24, and the first 24 bits of this rule are not the same as the first 24 bits of a rule previously added. If they are, then the new rule will share the same tbl8 than the previous one, since the only difference between the two rules is within the last byte. With the default value of 256, we can have up to 256 rules longer than 24 bits that differ on their first three bytes. Since routes longer than 24 bits are unlikely, this shouldn't be a problem in most setups. Even if it is, however, the number of tbl8s can be modified. Use Case: IPv4 Forwarding ~~~~~~~~~~~~~~~~~~~~~~~~~ The LPM algorithm is used to implement Classless Inter-Domain Routing (CIDR) strategy used by routers implementing IPv4 forwarding. References ~~~~~~~~~~ * RFC1519 Classless Inter-Domain Routing (CIDR): an Address Assignment and Aggregation Strategy, `http://www.ietf.org/rfc/rfc1519 `_ * Pankaj Gupta, Algorithms for Routing Lookups and Packet Classification, PhD Thesis, Stanford University, 2000 (`http://klamath.stanford.edu/~pankaj/thesis/ thesis_1sided.pdf `_ ) ================================================ FILE: doc/guides/prog_guide/mbuf_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Mbuf_Library: Mbuf Library ============ The mbuf library provides the ability to allocate and free buffers (mbufs) that may be used by the DPDK application to store message buffers. The message buffers are stored in a mempool, using the :ref:`Mempool Library `. A rte_mbuf struct can carry network packet buffers or generic control buffers (indicated by the CTRL_MBUF_FLAG). This can be extended to other types. The rte_mbuf header structure is kept as small as possible and currently uses just two cache lines, with the most frequently used fields being on the first of the two cache lines. Design of Packet Buffers ------------------------ For the storage of the packet data (including protocol headers), two approaches were considered: #. Embed metadata within a single memory buffer the structure followed by a fixed size area for the packet data. #. Use separate memory buffers for the metadata structure and for the packet data. The advantage of the first method is that it only needs one operation to allocate/free the whole memory representation of a packet. On the other hand, the second method is more flexible and allows the complete separation of the allocation of metadata structures from the allocation of packet data buffers. The first method was chosen for the DPDK. The metadata contains control information such as message type, length, offset to the start of the data and a pointer for additional mbuf structures allowing buffer chaining. Message buffers that are used to carry network packets can handle buffer chaining where multiple buffers are required to hold the complete packet. This is the case for jumbo frames that are composed of many mbufs linked together through their next field. For a newly allocated mbuf, the area at which the data begins in the message buffer is RTE_PKTMBUF_HEADROOM bytes after the beginning of the buffer, which is cache aligned. Message buffers may be used to carry control information, packets, events, and so on between different entities in the system. Message buffers may also use their buffer pointers to point to other message buffer data sections or other structures. :numref:`figure_mbuf1` and :numref:`figure_mbuf2` show some of these scenarios. .. _figure_mbuf1: .. figure:: img/mbuf1.* An mbuf with One Segment .. _figure_mbuf2: .. figure:: img/mbuf2.* An mbuf with Three Segments The Buffer Manager implements a fairly standard set of buffer access functions to manipulate network packets. Buffers Stored in Memory Pools ------------------------------ The Buffer Manager uses the :ref:`Mempool Library ` to allocate buffers. Therefore, it ensures that the packet header is interleaved optimally across the channels and ranks for L3 processing. An mbuf contains a field indicating the pool that it originated from. When calling rte_ctrlmbuf_free(m) or rte_pktmbuf_free(m), the mbuf returns to its original pool. Constructors ------------ Packet and control mbuf constructors are provided by the API. The rte_pktmbuf_init() and rte_ctrlmbuf_init() functions initialize some fields in the mbuf structure that are not modified by the user once created (mbuf type, origin pool, buffer start address, and so on). This function is given as a callback function to the rte_mempool_create() function at pool creation time. Allocating and Freeing mbufs ---------------------------- Allocating a new mbuf requires the user to specify the mempool from which the mbuf should be taken. For any newly-allocated mbuf, it contains one segment, with a length of 0. The offset to data is initialized to have some bytes of headroom in the buffer (RTE_PKTMBUF_HEADROOM). Freeing a mbuf means returning it into its original mempool. The content of an mbuf is not modified when it is stored in a pool (as a free mbuf). Fields initialized by the constructor do not need to be re-initialized at mbuf allocation. When freeing a packet mbuf that contains several segments, all of them are freed and returned to their original mempool. Manipulating mbufs ------------------ This library provides some functions for manipulating the data in a packet mbuf. For instance: * Get data length * Get a pointer to the start of data * Prepend data before data * Append data after data * Remove data at the beginning of the buffer (rte_pktmbuf_adj()) * Remove data at the end of the buffer (rte_pktmbuf_trim()) Refer to the *DPDK API Reference* for details. Meta Information ---------------- Some information is retrieved by the network driver and stored in an mbuf to make processing easier. For instance, the VLAN, the RSS hash result (see :ref:`Poll Mode Driver `) and a flag indicating that the checksum was computed by hardware. An mbuf also contains the input port (where it comes from), and the number of segment mbufs in the chain. For chained buffers, only the first mbuf of the chain stores this meta information. For instance, this is the case on RX side for the IEEE1588 packet timestamp mechanism, the VLAN tagging and the IP checksum computation. On TX side, it is also possible for an application to delegate some processing to the hardware if it supports it. For instance, the PKT_TX_IP_CKSUM flag allows to offload the computation of the IPv4 checksum. The following examples explain how to configure different TX offloads on a vxlan-encapsulated tcp packet: ``out_eth/out_ip/out_udp/vxlan/in_eth/in_ip/in_tcp/payload`` - calculate checksum of out_ip:: mb->l2_len = len(out_eth) mb->l3_len = len(out_ip) mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM set out_ip checksum to 0 in the packet This is supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM. - calculate checksum of out_ip and out_udp:: mb->l2_len = len(out_eth) mb->l3_len = len(out_ip) mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_UDP_CKSUM set out_ip checksum to 0 in the packet set out_udp checksum to pseudo header using rte_ipv4_phdr_cksum() This is supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM and DEV_TX_OFFLOAD_UDP_CKSUM. - calculate checksum of in_ip:: mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth) mb->l3_len = len(in_ip) mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM set in_ip checksum to 0 in the packet This is similar to case 1), but l2_len is different. It is supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM. Note that it can only work if outer L4 checksum is 0. - calculate checksum of in_ip and in_tcp:: mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth) mb->l3_len = len(in_ip) mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_TCP_CKSUM set in_ip checksum to 0 in the packet set in_tcp checksum to pseudo header using rte_ipv4_phdr_cksum() This is similar to case 2), but l2_len is different. It is supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM and DEV_TX_OFFLOAD_TCP_CKSUM. Note that it can only work if outer L4 checksum is 0. - segment inner TCP:: mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth) mb->l3_len = len(in_ip) mb->l4_len = len(in_tcp) mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_TCP_SEG; set in_ip checksum to 0 in the packet set in_tcp checksum to pseudo header without including the IP payload length using rte_ipv4_phdr_cksum() This is supported on hardware advertising DEV_TX_OFFLOAD_TCP_TSO. Note that it can only work if outer L4 checksum is 0. - calculate checksum of out_ip, in_ip, in_tcp:: mb->outer_l2_len = len(out_eth) mb->outer_l3_len = len(out_ip) mb->l2_len = len(out_udp + vxlan + in_eth) mb->l3_len = len(in_ip) mb->ol_flags |= PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IP_CKSUM | \ PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM; set out_ip checksum to 0 in the packet set in_ip checksum to 0 in the packet set in_tcp checksum to pseudo header using rte_ipv4_phdr_cksum() This is supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM, DEV_TX_OFFLOAD_UDP_CKSUM and DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM. The list of flags and their precise meaning is described in the mbuf API documentation (rte_mbuf.h). Also refer to the testpmd source code (specifically the csumonly.c file) for details. Direct and Indirect Buffers --------------------------- A direct buffer is a buffer that is completely separate and self-contained. An indirect buffer behaves like a direct buffer but for the fact that the buffer pointer and data offset in it refer to data in another direct buffer. This is useful in situations where packets need to be duplicated or fragmented, since indirect buffers provide the means to reuse the same packet data across multiple buffers. A buffer becomes indirect when it is "attached" to a direct buffer using the rte_pktmbuf_attach() function. Each buffer has a reference counter field and whenever an indirect buffer is attached to the direct buffer, the reference counter on the direct buffer is incremented. Similarly, whenever the indirect buffer is detached, the reference counter on the direct buffer is decremented. If the resulting reference counter is equal to 0, the direct buffer is freed since it is no longer in use. There are a few things to remember when dealing with indirect buffers. First of all, it is not possible to attach an indirect buffer to another indirect buffer. Secondly, for a buffer to become indirect, its reference counter must be equal to 1, that is, it must not be already referenced by another indirect buffer. Finally, it is not possible to reattach an indirect buffer to the direct buffer (unless it is detached first). While the attach/detach operations can be invoked directly using the recommended rte_pktmbuf_attach() and rte_pktmbuf_detach() functions, it is suggested to use the higher-level rte_pktmbuf_clone() function, which takes care of the correct initialization of an indirect buffer and can clone buffers with multiple segments. Since indirect buffers are not supposed to actually hold any data, the memory pool for indirect buffers should be configured to indicate the reduced memory consumption. Examples of the initialization of a memory pool for indirect buffers (as well as use case examples for indirect buffers) can be found in several of the sample applications, for example, the IPv4 Multicast sample application. Debug ----- In debug mode (CONFIG_RTE_MBUF_DEBUG is enabled), the functions of the mbuf library perform sanity checks before any operation (such as, buffer corruption, bad type, and so on). Use Cases --------- All networking application should use mbufs to transport network packets. ================================================ FILE: doc/guides/prog_guide/mempool_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Mempool_Library: Mempool Library =============== A memory pool is an allocator of a fixed-sized object. In the DPDK, it is identified by name and uses a ring to store free objects. It provides some other optional services such as a per-core object cache and an alignment helper to ensure that objects are padded to spread them equally on all DRAM or DDR3 channels. This library is used by the :ref:`Mbuf Library ` and the :ref:`Environment Abstraction Layer ` (for logging history). Cookies ------- In debug mode (CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG is enabled), cookies are added at the beginning and end of allocated blocks. The allocated objects then contain overwrite protection fields to help debugging buffer overflows. Stats ----- In debug mode (CONFIG_RTE_LIBRTE_MEMPOOL_DEBUG is enabled), statistics about get from/put in the pool are stored in the mempool structure. Statistics are per-lcore to avoid concurrent access to statistics counters. Memory Alignment Constraints ---------------------------- Depending on hardware memory configuration, performance can be greatly improved by adding a specific padding between objects. The objective is to ensure that the beginning of each object starts on a different channel and rank in memory so that all channels are equally loaded. This is particularly true for packet buffers when doing L3 forwarding or flow classification. Only the first 64 bytes are accessed, so performance can be increased by spreading the start addresses of objects among the different channels. The number of ranks on any DIMM is the number of independent sets of DRAMs that can be accessed for the full data bit-width of the DIMM. The ranks cannot be accessed simultaneously since they share the same data path. The physical layout of the DRAM chips on the DIMM itself does not necessarily relate to the number of ranks. When running an application, the EAL command line options provide the ability to add the number of memory channels and ranks. .. note:: The command line must always have the number of memory channels specified for the processor. Examples of alignment for different DIMM architectures are shown in :numref:`figure_memory-management` and :numref:`figure_memory-management2`. .. _figure_memory-management: .. figure:: img/memory-management.* Two Channels and Quad-ranked DIMM Example In this case, the assumption is that a packet is 16 blocks of 64 bytes, which is not true. The Intel® 5520 chipset has three channels, so in most cases, no padding is required between objects (except for objects whose size are n x 3 x 64 bytes blocks). .. _figure_memory-management2: .. figure:: img/memory-management2.* Three Channels and Two Dual-ranked DIMM Example When creating a new pool, the user can specify to use this feature or not. Local Cache ----------- In terms of CPU usage, the cost of multiple cores accessing a memory pool's ring of free buffers may be high since each access requires a compare-and-set (CAS) operation. To avoid having too many access requests to the memory pool's ring, the memory pool allocator can maintain a per-core cache and do bulk requests to the memory pool's ring, via the cache with many fewer locks on the actual memory pool structure. In this way, each core has full access to its own cache (with locks) of free objects and only when the cache fills does the core need to shuffle some of the free objects back to the pools ring or obtain more objects when the cache is empty. While this may mean a number of buffers may sit idle on some core's cache, the speed at which a core can access its own cache for a specific memory pool without locks provides performance gains. The cache is composed of a small, per-core table of pointers and its length (used as a stack). This cache can be enabled or disabled at creation of the pool. The maximum size of the cache is static and is defined at compilation time (CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE). :numref:`figure_mempool` shows a cache in operation. .. _figure_mempool: .. figure:: img/mempool.* A mempool in Memory with its Associated Ring Use Cases --------- All allocations that require a high level of performance should use a pool-based memory allocator. Below are some examples: * :ref:`Mbuf Library ` * :ref:`Environment Abstraction Layer ` , for logging service * Any application that needs to allocate fixed-sized objects in the data plane and that will be continuously utilized by the system. ================================================ FILE: doc/guides/prog_guide/multi_proc_support.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Multi-process_Support: Multi-process Support ===================== In the DPDK, multi-process support is designed to allow a group of DPDK processes to work together in a simple transparent manner to perform packet processing, or other workloads, on Intel® architecture hardware. To support this functionality, a number of additions have been made to the core DPDK Environment Abstraction Layer (EAL). The EAL has been modified to allow different types of DPDK processes to be spawned, each with different permissions on the hugepage memory used by the applications. For now, there are two types of process specified: * primary processes, which can initialize and which have full permissions on shared memory * secondary processes, which cannot initialize shared memory, but can attach to pre- initialized shared memory and create objects in it. Standalone DPDK processes are primary processes, while secondary processes can only run alongside a primary process or after a primary process has already configured the hugepage shared memory for them. To support these two process types, and other multi-process setups described later, two additional command-line parameters are available to the EAL: * --proc-type: for specifying a given process instance as the primary or secondary DPDK instance * --file-prefix: to allow processes that do not want to co-operate to have different memory regions A number of example applications are provided that demonstrate how multiple DPDK processes can be used together. These are more fully documented in the "Multi- process Sample Application" chapter in the *DPDK Sample Application's User Guide*. Memory Sharing -------------- The key element in getting a multi-process application working using the DPDK is to ensure that memory resources are properly shared among the processes making up the multi-process application. Once there are blocks of shared memory available that can be accessed by multiple processes, then issues such as inter-process communication (IPC) becomes much simpler. On application start-up in a primary or standalone process, the DPDK records to memory-mapped files the details of the memory configuration it is using - hugepages in use, the virtual addresses they are mapped at, the number of memory channels present, etc. When a secondary process is started, these files are read and the EAL recreates the same memory configuration in the secondary process so that all memory zones are shared between processes and all pointers to that memory are valid, and point to the same objects, in both processes. .. note:: Refer to Section 23.3 "Multi-process Limitations" for details of how Linux kernel Address-Space Layout Randomization (ASLR) can affect memory sharing. .. _figure_multi_process_memory: .. figure:: img/multi_process_memory.* Memory Sharing in the DPDK Multi-process Sample Application The EAL also supports an auto-detection mode (set by EAL --proc-type=auto flag ), whereby an DPDK process is started as a secondary instance if a primary instance is already running. Deployment Models ----------------- Symmetric/Peer Processes ~~~~~~~~~~~~~~~~~~~~~~~~ DPDK multi-process support can be used to create a set of peer processes where each process performs the same workload. This model is equivalent to having multiple threads each running the same main-loop function, as is done in most of the supplied DPDK sample applications. In this model, the first of the processes spawned should be spawned using the --proc-type=primary EAL flag, while all subsequent instances should be spawned using the --proc-type=secondary flag. The simple_mp and symmetric_mp sample applications demonstrate this usage model. They are described in the "Multi-process Sample Application" chapter in the *DPDK Sample Application's User Guide*. Asymmetric/Non-Peer Processes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An alternative deployment model that can be used for multi-process applications is to have a single primary process instance that acts as a load-balancer or server distributing received packets among worker or client threads, which are run as secondary processes. In this case, extensive use of rte_ring objects is made, which are located in shared hugepage memory. The client_server_mp sample application shows this usage model. It is described in the "Multi-process Sample Application" chapter in the *DPDK Sample Application's User Guide*. Running Multiple Independent DPDK Applications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In addition to the above scenarios involving multiple DPDK processes working together, it is possible to run multiple DPDK processes side-by-side, where those processes are all working independently. Support for this usage scenario is provided using the --file-prefix parameter to the EAL. By default, the EAL creates hugepage files on each hugetlbfs filesystem using the rtemap_X filename, where X is in the range 0 to the maximum number of hugepages -1. Similarly, it creates shared configuration files, memory mapped in each process, using the /var/run/.rte_config filename, when run as root (or $HOME/.rte_config when run as a non-root user; if filesystem and device permissions are set up to allow this). The rte part of the filenames of each of the above is configurable using the file-prefix parameter. In addition to specifying the file-prefix parameter, any DPDK applications that are to be run side-by-side must explicitly limit their memory use. This is done by passing the -m flag to each process to specify how much hugepage memory, in megabytes, each process can use (or passing --socket-mem to specify how much hugepage memory on each socket each process can use). .. note:: Independent DPDK instances running side-by-side on a single machine cannot share any network ports. Any network ports being used by one process should be blacklisted in every other process. Running Multiple Independent Groups of DPDK Applications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the same way that it is possible to run independent DPDK applications side- by-side on a single system, this can be trivially extended to multi-process groups of DPDK applications running side-by-side. In this case, the secondary processes must use the same --file-prefix parameter as the primary process whose shared memory they are connecting to. .. note:: All restrictions and issues with multiple independent DPDK processes running side-by-side apply in this usage scenario also. Multi-process Limitations ------------------------- There are a number of limitations to what can be done when running DPDK multi-process applications. Some of these are documented below: * The multi-process feature requires that the exact same hugepage memory mappings be present in all applications. The Linux security feature - Address-Space Layout Randomization (ASLR) can interfere with this mapping, so it may be necessary to disable this feature in order to reliably run multi-process applications. .. warning:: Disabling Address-Space Layout Randomization (ASLR) may have security implications, so it is recommended that it be disabled only when absolutely necessary, and only when the implications of this change have been understood. * All DPDK processes running as a single application and using shared memory must have distinct coremask arguments. It is not possible to have a primary and secondary instance, or two secondary instances, using any of the same logical cores. Attempting to do so can cause corruption of memory pool caches, among other issues. * The delivery of interrupts, such as Ethernet* device link status interrupts, do not work in secondary processes. All interrupts are triggered inside the primary process only. Any application needing interrupt notification in multiple processes should provide its own mechanism to transfer the interrupt information from the primary process to any secondary process that needs the information. * The use of function pointers between multiple processes running based of different compiled binaries is not supported, since the location of a given function in one process may be different to its location in a second. This prevents the librte_hash library from behaving properly as in a multi-threaded instance, since it uses a pointer to the hash function internally. To work around this issue, it is recommended that multi-process applications perform the hash calculations by directly calling the hashing function from the code and then using the rte_hash_add_with_hash()/rte_hash_lookup_with_hash() functions instead of the functions which do the hashing internally, such as rte_hash_add()/rte_hash_lookup(). * Depending upon the hardware in use, and the number of DPDK processes used, it may not be possible to have HPET timers available in each DPDK instance. The minimum number of HPET comparators available to Linux* userspace can be just a single comparator, which means that only the first, primary DPDK process instance can open and mmap /dev/hpet. If the number of required DPDK processes exceeds that of the number of available HPET comparators, the TSC (which is the default timer in this release) must be used as a time source across all processes instead of the HPET. ================================================ FILE: doc/guides/prog_guide/overview.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **Part 1: Architecture Overview** Overview ======== This section gives a global overview of the architecture of Data Plane Development Kit (DPDK). The main goal of the DPDK is to provide a simple, complete framework for fast packet processing in data plane applications. Users may use the code to understand some of the techniques employed, to build upon for prototyping or to add their own protocol stacks. Alternative ecosystem options that use the DPDK are available. The framework creates a set of libraries for specific environments through the creation of an Environment Abstraction Layer (EAL), which may be specific to a mode of the Intel® architecture (32-bit or 64-bit), Linux* user space compilers or a specific platform. These environments are created through the use of make files and configuration files. Once the EAL library is created, the user may link with the library to create their own applications. Other libraries, outside of EAL, including the Hash, Longest Prefix Match (LPM) and rings libraries are also provided. Sample applications are provided to help show the user how to use various features of the DPDK. The DPDK implements a run to completion model for packet processing, where all resources must be allocated prior to calling Data Plane applications, running as execution units on logical processing cores. The model does not support a scheduler and all devices are accessed by polling. The primary reason for not using interrupts is the performance overhead imposed by interrupt processing. In addition to the run-to-completion model, a pipeline model may also be used by passing packets or messages between cores via the rings. This allows work to be performed in stages and may allow more efficient use of code on cores. Development Environment ----------------------- The DPDK project installation requires Linux and the associated toolchain, such as one or more compilers, assembler, make utility, editor and various libraries to create the DPDK components and libraries. Once these libraries are created for the specific environment and architecture, they may then be used to create the user's data plane application. When creating applications for the Linux user space, the glibc library is used. For DPDK applications, two environmental variables (RTE_SDK and RTE_TARGET) must be configured before compiling the applications. The following are examples of how the variables can be set: .. code-block:: console export RTE_SDK=/home/user/DPDK export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for information on setting up the development environment. Environment Abstraction Layer ----------------------------- The Environment Abstraction Layer (EAL) provides a generic interface that hides the environment specifics from the applications and libraries. The services provided by the EAL are: * DPDK loading and launching * Support for multi-process and multi-thread execution types * Core affinity/assignment procedures * System memory allocation/de-allocation * Atomic/lock operations * Time reference * PCI bus access * Trace and debug functions * CPU feature identification * Interrupt handling * Alarm operations * Memory managenent (malloc) The EAL is fully described in :ref:`Environment Abstraction Layer `. Core Components --------------- The *core components* are a set of libraries that provide all the elements needed for high-performance packet processing applications. .. _figure_architecture-overview: .. figure:: img/architecture-overview.* Core Components Architecture Ring Manager (librte_ring) ~~~~~~~~~~~~~~~~~~~~~~~~~~ The ring structure provides a lockless multi-producer, multi-consumer FIFO API in a finite size table. It has some advantages over lockless queues; easier to implement, adapted to bulk operations and faster. A ring is used by the :ref:`Memory Pool Manager (librte_mempool) ` and may be used as a general communication mechanism between cores and/or execution blocks connected together on a logical core. This ring buffer and its usage are fully described in :ref:`Ring Library `. Memory Pool Manager (librte_mempool) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Memory Pool Manager is responsible for allocating pools of objects in memory. A pool is identified by name and uses a ring to store free objects. It provides some other optional services, such as a per-core object cache and an alignment helper to ensure that objects are padded to spread them equally on all RAM channels. This memory pool allocator is described in :ref:`Mempool Library `. Network Packet Buffer Management (librte_mbuf) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The mbuf library provides the facility to create and destroy buffers that may be used by the DPDK application to store message buffers. The message buffers are created at startup time and stored in a mempool, using the DPDK mempool library. This library provide an API to allocate/free mbufs, manipulate control message buffers (ctrlmbuf) which are generic message buffers, and packet buffers (pktmbuf) which are used to carry network packets. Network Packet Buffer Management is described in :ref:`Mbuf Library `. Timer Manager (librte_timer) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This library provides a timer service to DPDK execution units, providing the ability to execute a function asynchronously. It can be periodic function calls, or just a one-shot call. It uses the timer interface provided by the Environment Abstraction Layer (EAL) to get a precise time reference and can be initiated on a per-core basis as required. The library documentation is available in :ref:`Timer Library `. Ethernet* Poll Mode Driver Architecture --------------------------------------- The DPDK includes Poll Mode Drivers (PMDs) for 1 GbE, 10 GbE and 40GbE, and para virtualized virtio Ethernet controllers which are designed to work without asynchronous, interrupt-based signaling mechanisms. See :ref:`Poll Mode Driver `. Packet Forwarding Algorithm Support ----------------------------------- The DPDK includes Hash (librte_hash) and Longest Prefix Match (LPM,librte_lpm) libraries to support the corresponding packet forwarding algorithms. See :ref:`Hash Library ` and :ref:`LPM Library ` for more information. librte_net ---------- The librte_net library is a collection of IP protocol definitions and convenience macros. It is based on code from the FreeBSD* IP stack and contains protocol numbers (for use in IP headers), IP-related macros, IPv4/IPv6 header structures and TCP, UDP and SCTP header structures. ================================================ FILE: doc/guides/prog_guide/packet_classif_access_ctrl.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Packet Classification and Access Control ======================================== The DPDK provides an Access Control library that gives the ability to classify an input packet based on a set of classification rules. The ACL library is used to perform an N-tuple search over a set of rules with multiple categories and find the best match (highest priority) for each category. The library API provides the following basic operations: * Create a new Access Control (AC) context. * Add rules into the context. * For all rules in the context, build the runtime structures necessary to perform packet classification. * Perform input packet classifications. * Destroy an AC context and its runtime structures and free the associated memory. Overview -------- Rule definition ~~~~~~~~~~~~~~~ The current implementation allows the user for each AC context to specify its own rule (set of fields) over which packet classification will be performed. Though there are few restrictions on the rule fields layout: * First field in the rule definition has to be one byte long. * All subsequent fields has to be grouped into sets of 4 consecutive bytes. This is done mainly for performance reasons - search function processes the first input byte as part of the flow setup and then the inner loop of the search function is unrolled to process four input bytes at a time. To define each field inside an AC rule, the following structure is used: .. code-block:: c struct rte_acl_field_def { uint8_t type; /*< type - ACL_FIELD_TYPE. */ uint8_t size; /*< size of field 1,2,4, or 8. */ uint8_t field_index; /*< index of field inside the rule. */ uint8_t input_index; /*< 0-N input index. */ uint32_t offset; /*< offset to start of field. */ }; * type The field type is one of three choices: * _MASK - for fields such as IP addresses that have a value and a mask defining the number of relevant bits. * _RANGE - for fields such as ports that have a lower and upper value for the field. * _BITMASK - for fields such as protocol identifiers that have a value and a bit mask. * size The size parameter defines the length of the field in bytes. Allowable values are 1, 2, 4, or 8 bytes. Note that due to the grouping of input bytes, 1 or 2 byte fields must be defined as consecutive fields that make up 4 consecutive input bytes. Also, it is best to define fields of 8 or more bytes as 4 byte fields so that the build processes can eliminate fields that are all wild. * field_index A zero-based value that represents the position of the field inside the rule; 0 to N-1 for N fields. * input_index As mentioned above, all input fields, except the very first one, must be in groups of 4 consecutive bytes. The input index specifies to which input group that field belongs to. * offset The offset field defines the offset for the field. This is the offset from the beginning of the buffer parameter for the search. For example, to define classification for the following IPv4 5-tuple structure: .. code-block:: c struct ipv4_5tuple { uint8_t proto; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; }; The following array of field definitions can be used: .. code-block:: c struct rte_acl_field_def ipv4_defs[5] = { /* first input field - always one byte long. */ { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof (uint8_t), .field_index = 0, .input_index = 0, .offset = offsetof (struct ipv4_5tuple, proto), }, /* next input field (IPv4 source address) - 4 consecutive bytes. */ { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 1, .input_index = 1, .offset = offsetof (struct ipv4_5tuple, ip_src), }, /* next input field (IPv4 destination address) - 4 consecutive bytes. */ { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 2, .input_index = 2, .offset = offsetof (struct ipv4_5tuple, ip_dst), }, /* * Next 2 fields (src & dst ports) form 4 consecutive bytes. * They share the same input index. */ { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof (uint16_t), .field_index = 3, .input_index = 3, .offset = offsetof (struct ipv4_5tuple, port_src), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof (uint16_t), .field_index = 4, .input_index = 3, .offset = offsetof (struct ipv4_5tuple, port_dst), }, }; A typical example of such an IPv4 5-tuple rule is a follows: :: source addr/mask destination addr/mask source ports dest ports protocol/mask 192.168.1.0/24 192.168.2.31/32 0:65535 1234:1234 17/0xff Any IPv4 packets with protocol ID 17 (UDP), source address 192.168.1.[0-255], destination address 192.168.2.31, source port [0-65535] and destination port 1234 matches the above rule. To define classification for the IPv6 2-tuple: over the following IPv6 header structure: .. code-block:: c struct struct ipv6_hdr { uint32_t vtc_flow; /* IP version, traffic class & flow label. */ uint16_t payload_len; /* IP packet length - includes sizeof(ip_header). */ uint8_t proto; /* Protocol, next header. */ uint8_t hop_limits; /* Hop limits. */ uint8_t src_addr[16]; /* IP address of source host. */ uint8_t dst_addr[16]; /* IP address of destination host(s). */ } __attribute__((__packed__)); The following array of field definitions can be used: .. code-block:: c struct struct rte_acl_field_def ipv6_2tuple_defs[5] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof (uint8_t), .field_index = 0, .input_index = 0, .offset = offsetof (struct ipv6_hdr, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 1, .input_index = 1, .offset = offsetof (struct ipv6_hdr, src_addr[0]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 2, .input_index = 2, .offset = offsetof (struct ipv6_hdr, src_addr[4]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 3, .input_index = 3, .offset = offsetof (struct ipv6_hdr, src_addr[8]), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof (uint32_t), .field_index = 4, .input_index = 4, .offset = offsetof (struct ipv6_hdr, src_addr[12]), }, }; A typical example of such an IPv6 2-tuple rule is a follows: :: source addr/mask protocol/mask 2001:db8:1234:0000:0000:0000:0000:0000/48 6/0xff Any IPv6 packets with protocol ID 6 (TCP), and source address inside the range [2001:db8:1234:0000:0000:0000:0000:0000 - 2001:db8:1234:ffff:ffff:ffff:ffff:ffff] matches the above rule. When creating a set of rules, for each rule, additional information must be supplied also: * **priority**: A weight to measure the priority of the rules (higher is better). If the input tuple matches more than one rule, then the rule with the higher priority is returned. Note that if the input tuple matches more than one rule and these rules have equal priority, it is undefined which rule is returned as a match. It is recommended to assign a unique priority for each rule. * **category_mask**: Each rule uses a bit mask value to select the relevant category(s) for the rule. When a lookup is performed, the result for each category is returned. This effectively provides a "parallel lookup" by enabling a single search to return multiple results if, for example, there were four different sets of ACL rules, one for access control, one for routing, and so on. Each set could be assigned its own category and by combining them into a single database, one lookup returns a result for each of the four sets. * **userdata**: A user-defined field that could be any value except zero. For each category, a successful match returns the userdata field of the highest priority matched rule. .. note:: When adding new rules into an ACL context, all fields must be in host byte order (LSB). When the search is performed for an input tuple, all fields in that tuple must be in network byte order (MSB). RT memory size limit ~~~~~~~~~~~~~~~~~~~~ Build phase (rte_acl_build()) creates for a given set of rules internal structure for further run-time traversal. With current implementation it is a set of multi-bit tries (with stride == 8). Depending on the rules set, that could consume significant amount of memory. In attempt to conserve some space ACL build process tries to split the given rule-set into several non-intersecting subsets and construct a separate trie for each of them. Depending on the rule-set, it might reduce RT memory requirements but might increase classification time. There is a possibility at build-time to specify maximum memory limit for internal RT structures for given AC context. It could be done via **max_size** field of the **rte_acl_config** structure. Setting it to the value greater than zero, instructs rte_acl_build() to: * attempt to minimize number of tries in the RT table, but * make sure that size of RT table wouldn't exceed given value. Setting it to zero makes rte_acl_build() to use the default behavior: try to minimize size of the RT structures, but doesn't expose any hard limit on it. That gives the user the ability to decisions about performance/space trade-off. For example: .. code-block:: c struct rte_acl_ctx * acx; struct rte_acl_config cfg; int ret; /* * assuming that acx points to already created and * populated with rules AC context and cfg filled properly. */ /* try to build AC context, with RT structures less then 8MB. */ cfg.max_size = 0x800000; ret = rte_acl_build(acx, &cfg); /* * RT structures can't fit into 8MB for given context. * Try to build without exposing any hard limit. */ if (ret == -ERANGE) { cfg.max_size = 0; ret = rte_acl_build(acx, &cfg); } Classification methods ~~~~~~~~~~~~~~~~~~~~~~ After rte_acl_build() over given AC context has finished successfully, it can be used to perform classification - search for a rule with highest priority over the input data. There are several implementations of classify algorithm: * **RTE_ACL_CLASSIFY_SCALAR**: generic implementation, doesn't require any specific HW support. * **RTE_ACL_CLASSIFY_SSE**: vector implementation, can process up to 8 flows in parallel. Requires SSE 4.1 support. * **RTE_ACL_CLASSIFY_AVX2**: vector implementation, can process up to 16 flows in parallel. Requires AVX2 support. It is purely a runtime decision which method to choose, there is no build-time difference. All implementations operates over the same internal RT structures and use similar principles. The main difference is that vector implementations can manually exploit IA SIMD instructions and process several input data flows in parallel. At startup ACL library determines the highest available classify method for the given platform and sets it as default one. Though the user has an ability to override the default classifier function for a given ACL context or perform particular search using non-default classify method. In that case it is user responsibility to make sure that given platform supports selected classify implementation. Application Programming Interface (API) Usage --------------------------------------------- .. note:: For more details about the Access Control API, please refer to the *DPDK API Reference*. The following example demonstrates IPv4, 5-tuple classification for rules defined above with multiple categories in more detail. Classify with Multiple Categories ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: c struct rte_acl_ctx * acx; struct rte_acl_config cfg; int ret; /* define a structure for the rule with up to 5 fields. */ RTE_ACL_RULE_DEF(acl_ipv4_rule, RTE_DIM(ipv4_defs)); /* AC context creation parameters. */ struct rte_acl_param prm = { .name = "ACL_example", .socket_id = SOCKET_ID_ANY, .rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ipv4_defs)), /* number of fields per rule. */ .max_rule_num = 8, /* maximum number of rules in the AC context. */ }; struct acl_ipv4_rule acl_rules[] = { /* matches all packets traveling to 192.168.0.0/16, applies for categories: 0,1 */ { .data = {.userdata = 1, .category_mask = 3, .priority = 1}, /* destination IPv4 */ .field[2] = {.value.u32 = IPv4(192,168,0,0),. mask_range.u32 = 16,}, /* source port */ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, /* destination port */ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, }, /* matches all packets traveling to 192.168.1.0/24, applies for categories: 0 */ { .data = {.userdata = 2, .category_mask = 1, .priority = 2}, /* destination IPv4 */ .field[2] = {.value.u32 = IPv4(192,168,1,0),. mask_range.u32 = 24,}, /* source port */ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, /* destination port */ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, }, /* matches all packets traveling from 10.1.1.1, applies for categories: 1 */ { .data = {.userdata = 3, .category_mask = 2, .priority = 3}, /* source IPv4 */ .field[1] = {.value.u32 = IPv4(10,1,1,1),. mask_range.u32 = 32,}, /* source port */ .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, /* destination port */ .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, }, }; /* create an empty AC context */ if ((acx = rte_acl_create(&prm)) == NULL) { /* handle context create failure. */ } /* add rules to the context */ ret = rte_acl_add_rules(acx, acl_rules, RTE_DIM(acl_rules)); if (ret != 0) { /* handle error at adding ACL rules. */ } /* prepare AC build config. */ cfg.num_categories = 2; cfg.num_fields = RTE_DIM(ipv4_defs); memcpy(cfg.defs, ipv4_defs, sizeof (ipv4_defs)); /* build the runtime structures for added rules, with 2 categories. */ ret = rte_acl_build(acx, &cfg); if (ret != 0) { /* handle error at build runtime structures for ACL context. */ } For a tuple with source IP address: 10.1.1.1 and destination IP address: 192.168.1.15, once the following lines are executed: .. code-block:: c uint32_t results[4]; /* make classify for 4 categories. */ rte_acl_classify(acx, data, results, 1, 4); then the results[] array contains: .. code-block:: c results[4] = {2, 3, 0, 0}; * For category 0, both rules 1 and 2 match, but rule 2 has higher priority, therefore results[0] contains the userdata for rule 2. * For category 1, both rules 1 and 3 match, but rule 3 has higher priority, therefore results[1] contains the userdata for rule 3. * For categories 2 and 3, there are no matches, so results[2] and results[3] contain zero, which indicates that no matches were found for those categories. For a tuple with source IP address: 192.168.1.1 and destination IP address: 192.168.2.11, once the following lines are executed: .. code-block:: c uint32_t results[4]; /* make classify by 4 categories. */ rte_acl_classify(acx, data, results, 1, 4); the results[] array contains: .. code-block:: c results[4] = {1, 1, 0, 0}; * For categories 0 and 1, only rule 1 matches. * For categories 2 and 3, there are no matches. For a tuple with source IP address: 10.1.1.1 and destination IP address: 201.212.111.12, once the following lines are executed: .. code-block:: c uint32_t results[4]; /* make classify by 4 categories. */ rte_acl_classify(acx, data, results, 1, 4); the results[] array contains: .. code-block:: c results[4] = {0, 3, 0, 0}; * For category 1, only rule 3 matches. * For categories 0, 2 and 3, there are no matches. ================================================ FILE: doc/guides/prog_guide/packet_distrib_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Packet Distributor Library ========================== The DPDK Packet Distributor library is a library designed to be used for dynamic load balancing of traffic while supporting single packet at a time operation. When using this library, the logical cores in use are to be considered in two roles: firstly a distributor lcore, which is responsible for load balancing or distributing packets, and a set of worker lcores which are responsible for receiving the packets from the distributor and operating on them. The model of operation is shown in the diagram below. .. figure:: img/packet_distributor1.* Packet Distributor mode of operation Distributor Core Operation -------------------------- The distributor core does the majority of the processing for ensuring that packets are fairly shared among workers. The operation of the distributor is as follows: #. Packets are passed to the distributor component by having the distributor lcore thread call the "rte_distributor_process()" API #. The worker lcores all share a single cache line with the distributor core in order to pass messages and packets to and from the worker. The process API call will poll all the worker cache lines to see what workers are requesting packets. #. As workers request packets, the distributor takes packets from the set of packets passed in and distributes them to the workers. As it does so, it examines the "tag" -- stored in the RSS hash field in the mbuf -- for each packet and records what tags are being processed by each worker. #. If the next packet in the input set has a tag which is already being processed by a worker, then that packet will be queued up for processing by that worker and given to it in preference to other packets when that work next makes a request for work. This ensures that no two packets with the same tag are processed in parallel, and that all packets with the same tag are processed in input order. #. Once all input packets passed to the process API have either been distributed to workers or been queued up for a worker which is processing a given tag, then the process API returns to the caller. Other functions which are available to the distributor lcore are: * rte_distributor_returned_pkts() * rte_distributor_flush() * rte_distributor_clear_returns() Of these the most important API call is "rte_distributor_returned_pkts()" which should only be called on the lcore which also calls the process API. It returns to the caller all packets which have finished processing by all worker cores. Within this set of returned packets, all packets sharing the same tag will be returned in their original order. **NOTE:** If worker lcores buffer up packets internally for transmission in bulk afterwards, the packets sharing a tag will likely get out of order. Once a worker lcore requests a new packet, the distributor assumes that it has completely finished with the previous packet and therefore that additional packets with the same tag can safely be distributed to other workers -- who may then flush their buffered packets sooner and cause packets to get out of order. **NOTE:** No packet ordering guarantees are made about packets which do not share a common packet tag. Using the process and returned_pkts API, the following application workflow can be used, while allowing packet order within a packet flow -- identified by a tag -- to be maintained. .. figure:: img/packet_distributor2.* Application workflow The flush and clear_returns API calls, mentioned previously, are likely of less use that the process and returned_pkts APIS, and are principally provided to aid in unit testing of the library. Descriptions of these functions and their use can be found in the DPDK API Reference document. Worker Operation ---------------- Worker cores are the cores which do the actual manipulation of the packets distributed by the packet distributor. Each worker calls "rte_distributor_get_pkt()" API to request a new packet when it has finished processing the previous one. [The previous packet should be returned to the distributor component by passing it as the final parameter to this API call.] Since it may be desirable to vary the number of worker cores, depending on the traffic load i.e. to save power at times of lighter load, it is possible to have a worker stop processing packets by calling "rte_distributor_return_pkt()" to indicate that it has finished the current packet and does not want a new one. ================================================ FILE: doc/guides/prog_guide/packet_framework.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Packet Framework ================ Design Objectives ----------------- The main design objectives for the DPDK Packet Framework are: * Provide standard methodology to build complex packet processing pipelines. Provide reusable and extensible templates for the commonly used pipeline functional blocks; * Provide capability to switch between pure software and hardware-accelerated implementations for the same pipeline functional block; * Provide the best trade-off between flexibility and performance. Hardcoded pipelines usually provide the best performance, but are not flexible, while developing flexible frameworks is never a problem, but performance is usually low; * Provide a framework that is logically similar to Open Flow. Overview -------- Packet processing applications are frequently structured as pipelines of multiple stages, with the logic of each stage glued around a lookup table. For each incoming packet, the table defines the set of actions to be applied to the packet, as well as the next stage to send the packet to. The DPDK Packet Framework minimizes the development effort required to build packet processing pipelines by defining a standard methodology for pipeline development, as well as providing libraries of reusable templates for the commonly used pipeline blocks. The pipeline is constructed by connecting the set of input ports with the set of output ports through the set of tables in a tree-like topology. As result of lookup operation for the current packet in the current table, one of the table entries (on lookup hit) or the default table entry (on lookup miss) provides the set of actions to be applied on the current packet, as well as the next hop for the packet, which can be either another table, an output port or packet drop. An example of packet processing pipeline is presented in :numref:`figure_figure32`: .. _figure_figure32: .. figure:: img/figure32.* Example of Packet Processing Pipeline where Input Ports 0 and 1 are Connected with Output Ports 0, 1 and 2 through Tables 0 and 1 Port Library Design ------------------- Port Types ~~~~~~~~~~ :numref:`table_qos_19` is a non-exhaustive list of ports that can be implemented with the Packet Framework. .. _table_qos_19: .. table:: Port Types +---+------------------+---------------------------------------------------------------------------------------+ | # | Port type | Description | | | | | +===+==================+=======================================================================================+ | 1 | SW ring | SW circular buffer used for message passing between the application threads. Uses | | | | the DPDK rte_ring primitive. Expected to be the most commonly used type of | | | | port. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 2 | HW ring | Queue of buffer descriptors used to interact with NIC, switch or accelerator ports. | | | | For NIC ports, it uses the DPDK rte_eth_rx_queue or rte_eth_tx_queue | | | | primitives. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 3 | IP reassembly | Input packets are either IP fragments or complete IP datagrams. Output packets are | | | | complete IP datagrams. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 4 | IP fragmentation | Input packets are jumbo (IP datagrams with length bigger than MTU) or non-jumbo | | | | packets. Output packets are non-jumbo packets. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 5 | Traffic manager | Traffic manager attached to a specific NIC output port, performing congestion | | | | management and hierarchical scheduling according to pre-defined SLAs. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 6 | KNI | Send/receive packets to/from Linux kernel space. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 7 | Source | Input port used as packet generator. Similar to Linux kernel /dev/zero character | | | | device. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ | 8 | Sink | Output port used to drop all input packets. Similar to Linux kernel /dev/null | | | | character device. | | | | | +---+------------------+---------------------------------------------------------------------------------------+ Port Interface ~~~~~~~~~~~~~~ Each port is unidirectional, i.e. either input port or output port. Each input/output port is required to implement an abstract interface that defines the initialization and run-time operation of the port. The port abstract interface is described in. .. _table_qos_20: .. table:: 20 Port Abstract Interface +---+----------------+-----------------------------------------------------------------------------------------+ | # | Port Operation | Description | | | | | +===+================+=========================================================================================+ | 1 | Create | Create the low-level port object (e.g. queue). Can internally allocate memory. | | | | | +---+----------------+-----------------------------------------------------------------------------------------+ | 2 | Free | Free the resources (e.g. memory) used by the low-level port object. | | | | | +---+----------------+-----------------------------------------------------------------------------------------+ | 3 | RX | Read a burst of input packets. Non-blocking operation. Only defined for input ports. | | | | | +---+----------------+-----------------------------------------------------------------------------------------+ | 4 | TX | Write a burst of input packets. Non-blocking operation. Only defined for output ports. | | | | | +---+----------------+-----------------------------------------------------------------------------------------+ | 5 | Flush | Flush the output buffer. Only defined for output ports. | | | | | +---+----------------+-----------------------------------------------------------------------------------------+ Table Library Design -------------------- Table Types ~~~~~~~~~~~ :numref:`table_qos_21` is a non-exhaustive list of types of tables that can be implemented with the Packet Framework. .. _table_qos_21: .. table:: Table Types +---+----------------------------+-----------------------------------------------------------------------------+ | # | Table Type | Description | | | | | +===+============================+=============================================================================+ | 1 | Hash table | Lookup key is n-tuple based. | | | | | | | | Typically, the lookup key is hashed to produce a signature that is used to | | | | identify a bucket of entries where the lookup key is searched next. | | | | | | | | The signature associated with the lookup key of each input packet is either | | | | read from the packet descriptor (pre-computed signature) or computed at | | | | table lookup time. | | | | | | | | The table lookup, add entry and delete entry operations, as well as any | | | | other pipeline block that pre-computes the signature all have to use the | | | | same hashing algorithm to generate the signature. | | | | | | | | Typically used to implement flow classification tables, ARP caches, routing | | | | table for tunnelling protocols, etc. | | | | | +---+----------------------------+-----------------------------------------------------------------------------+ | 2 | Longest Prefix Match (LPM) | Lookup key is the IP address. | | | | | | | | Each table entries has an associated IP prefix (IP and depth). | | | | | | | | The table lookup operation selects the IP prefix that is matched by the | | | | lookup key; in case of multiple matches, the entry with the longest prefix | | | | depth wins. | | | | | | | | Typically used to implement IP routing tables. | | | | | +---+----------------------------+-----------------------------------------------------------------------------+ | 3 | Access Control List (ACLs) | Lookup key is 7-tuple of two VLAN/MPLS labels, IP destination address, | | | | IP source addresses, L4 protocol, L4 destination port, L4 source port. | | | | | | | | Each table entry has an associated ACL and priority. The ACL contains bit | | | | masks for the VLAN/MPLS labels, IP prefix for IP destination address, IP | | | | prefix for IP source addresses, L4 protocol and bitmask, L4 destination | | | | port and bit mask, L4 source port and bit mask. | | | | | | | | The table lookup operation selects the ACL that is matched by the lookup | | | | key; in case of multiple matches, the entry with the highest priority wins. | | | | | | | | Typically used to implement rule databases for firewalls, etc. | | | | | +---+----------------------------+-----------------------------------------------------------------------------+ | 4 | Pattern matching search | Lookup key is the packet payload. | | | | | | | | Table is a database of patterns, with each pattern having a priority | | | | assigned. | | | | | | | | The table lookup operation selects the patterns that is matched by the | | | | input packet; in case of multiple matches, the matching pattern with the | | | | highest priority wins. | | | | | +---+----------------------------+-----------------------------------------------------------------------------+ | 5 | Array | Lookup key is the table entry index itself. | | | | | +---+----------------------------+-----------------------------------------------------------------------------+ Table Interface ~~~~~~~~~~~~~~~ Each table is required to implement an abstract interface that defines the initialization and run-time operation of the table. The table abstract interface is described in :numref:`table_qos_29_1`. .. _table_qos_29_1: .. table:: Table Abstract Interface +---+-----------------+----------------------------------------------------------------------------------------+ | # | Table operation | Description | | | | | +===+=================+========================================================================================+ | 1 | Create | Create the low-level data structures of the lookup table. Can internally allocate | | | | memory. | | | | | +---+-----------------+----------------------------------------------------------------------------------------+ | 2 | Free | Free up all the resources used by the lookup table. | | | | | +---+-----------------+----------------------------------------------------------------------------------------+ | 3 | Add entry | Add new entry to the lookup table. | | | | | +---+-----------------+----------------------------------------------------------------------------------------+ | 4 | Delete entry | Delete specific entry from the lookup table. | | | | | +---+-----------------+----------------------------------------------------------------------------------------+ | 5 | Lookup | Look up a burst of input packets and return a bit mask specifying the result of the | | | | lookup operation for each packet: a set bit signifies lookup hit for the corresponding | | | | packet, while a cleared bit a lookup miss. | | | | | | | | For each lookup hit packet, the lookup operation also returns a pointer to the table | | | | entry that was hit, which contains the actions to be applied on the packet and any | | | | associated metadata. | | | | | | | | For each lookup miss packet, the actions to be applied on the packet and any | | | | associated metadata are specified by the default table entry preconfigured for lookup | | | | miss. | | | | | +---+-----------------+----------------------------------------------------------------------------------------+ Hash Table Design ~~~~~~~~~~~~~~~~~ Hash Table Overview ^^^^^^^^^^^^^^^^^^^ Hash tables are important because the key lookup operation is optimized for speed: instead of having to linearly search the lookup key through all the keys in the table, the search is limited to only the keys stored in a single table bucket. **Associative Arrays** An associative array is a function that can be specified as a set of (key, value) pairs, with each key from the possible set of input keys present at most once. For a given associative array, the possible operations are: #. *add (key, value)*: When no value is currently associated with *key*, then the (key, *value* ) association is created. When *key* is already associated value *value0*, then the association (*key*, *value0*) is removed and association *(key, value)* is created; #. *delete key*: When no value is currently associated with *key*, this operation has no effect. When *key* is already associated *value*, then association *(key, value)* is removed; #. *lookup key*: When no value is currently associated with *key*, then this operation returns void value (lookup miss). When *key* is associated with *value*, then this operation returns *value*. The *(key, value)* association is not changed. The matching criterion used to compare the input key against the keys in the associative array is *exact match*, as the key size (number of bytes) and the key value (array of bytes) have to match exactly for the two keys under comparison. **Hash Function** A hash function deterministically maps data of variable length (key) to data of fixed size (hash value or key signature). Typically, the size of the key is bigger than the size of the key signature. The hash function basically compresses a long key into a short signature. Several keys can share the same signature (collisions). High quality hash functions have uniform distribution. For large number of keys, when dividing the space of signature values into a fixed number of equal intervals (buckets), it is desirable to have the key signatures evenly distributed across these intervals (uniform distribution), as opposed to most of the signatures going into only a few of the intervals and the rest of the intervals being largely unused (non-uniform distribution). **Hash Table** A hash table is an associative array that uses a hash function for its operation. The reason for using a hash function is to optimize the performance of the lookup operation by minimizing the number of table keys that have to be compared against the input key. Instead of storing the (key, value) pairs in a single list, the hash table maintains multiple lists (buckets). For any given key, there is a single bucket where that key might exist, and this bucket is uniquely identified based on the key signature. Once the key signature is computed and the hash table bucket identified, the key is either located in this bucket or it is not present in the hash table at all, so the key search can be narrowed down from the full set of keys currently in the table to just the set of keys currently in the identified table bucket. The performance of the hash table lookup operation is greatly improved, provided that the table keys are evenly distributed among the hash table buckets, which can be achieved by using a hash function with uniform distribution. The rule to map a key to its bucket can simply be to use the key signature (modulo the number of table buckets) as the table bucket ID: *bucket_id = f_hash(key) % n_buckets;* By selecting the number of buckets to be a power of two, the modulo operator can be replaced by a bitwise AND logical operation: *bucket_id = f_hash(key) & (n_buckets - 1);* considering *n_bits* as the number of bits set in *bucket_mask = n_buckets - 1*, this means that all the keys that end up in the same hash table bucket have the lower *n_bits* of their signature identical. In order to reduce the number of keys in the same bucket (collisions), the number of hash table buckets needs to be increased. In packet processing context, the sequence of operations involved in hash table operations is described in :numref:`figure_figure33`: .. _figure_figure33: .. figure:: img/figure33.* Sequence of Steps for Hash Table Operations in a Packet Processing Context Hash Table Use Cases ^^^^^^^^^^^^^^^^^^^^ **Flow Classification** *Description:* The flow classification is executed at least once for each input packet. This operation maps each incoming packet against one of the known traffic flows in the flow database that typically contains millions of flows. *Hash table name:* Flow classification table *Number of keys:* Millions *Key format:* n-tuple of packet fields that uniquely identify a traffic flow/connection. Example: DiffServ 5-tuple of (Source IP address, Destination IP address, L4 protocol, L4 protocol source port, L4 protocol destination port). For IPv4 protocol and L4 protocols like TCP, UDP or SCTP, the size of the DiffServ 5-tuple is 13 bytes, while for IPv6 it is 37 bytes. *Key value (key data):* actions and action meta-data describing what processing to be applied for the packets of the current flow. The size of the data associated with each traffic flow can vary from 8 bytes to kilobytes. **Address Resolution Protocol (ARP)** *Description:* Once a route has been identified for an IP packet (so the output interface and the IP address of the next hop station are known), the MAC address of the next hop station is needed in order to send this packet onto the next leg of the journey towards its destination (as identified by its destination IP address). The MAC address of the next hop station becomes the destination MAC address of the outgoing Ethernet frame. *Hash table name:* ARP table *Number of keys:* Thousands *Key format:* The pair of (Output interface, Next Hop IP address), which is typically 5 bytes for IPv4 and 17 bytes for IPv6. *Key value (key data):* MAC address of the next hop station (6 bytes). Hash Table Types ^^^^^^^^^^^^^^^^ :numref:`table_qos_22` lists the hash table configuration parameters shared by all different hash table types. .. _table_qos_22: .. table:: Configuration Parameters Common for All Hash Table Types +---+---------------------------+------------------------------------------------------------------------------+ | # | Parameter | Details | | | | | +===+===========================+==============================================================================+ | 1 | Key size | Measured as number of bytes. All keys have the same size. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 2 | Key value (key data) size | Measured as number of bytes. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 3 | Number of buckets | Needs to be a power of two. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 4 | Maximum number of keys | Needs to be a power of two. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 5 | Hash function | Examples: jhash, CRC hash, etc. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 6 | Hash function seed | Parameter to be passed to the hash function. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 7 | Key offset | Offset of the lookup key byte array within the packet meta-data stored in | | | | the packet buffer. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ Bucket Full Problem """"""""""""""""""" On initialization, each hash table bucket is allocated space for exactly 4 keys. As keys are added to the table, it can happen that a given bucket already has 4 keys when a new key has to be added to this bucket. The possible options are: #. **Least Recently Used (LRU) Hash Table.** One of the existing keys in the bucket is deleted and the new key is added in its place. The number of keys in each bucket never grows bigger than 4. The logic to pick the key to be dropped from the bucket is LRU. The hash table lookup operation maintains the order in which the keys in the same bucket are hit, so every time a key is hit, it becomes the new Most Recently Used (MRU) key, i.e. the last candidate for drop. When a key is added to the bucket, it also becomes the new MRU key. When a key needs to be picked and dropped, the first candidate for drop, i.e. the current LRU key, is always picked. The LRU logic requires maintaining specific data structures per each bucket. #. **Extendable Bucket Hash Table.** The bucket is extended with space for 4 more keys. This is done by allocating additional memory at table initialization time, which is used to create a pool of free keys (the size of this pool is configurable and always a multiple of 4). On key add operation, the allocation of a group of 4 keys only happens successfully within the limit of free keys, otherwise the key add operation fails. On key delete operation, a group of 4 keys is freed back to the pool of free keys when the key to be deleted is the only key that was used within its group of 4 keys at that time. On key lookup operation, if the current bucket is in extended state and a match is not found in the first group of 4 keys, the search continues beyond the first group of 4 keys, potentially until all keys in this bucket are examined. The extendable bucket logic requires maintaining specific data structures per table and per each bucket. .. _table_qos_23: .. table:: Configuration Parameters Specific to Extendible Bucket Hash Table +---+---------------------------+--------------------------------------------------+ | # | Parameter | Details | | | | | +===+===========================+==================================================+ | 1 | Number of additional keys | Needs to be a power of two, at least equal to 4. | | | | | +---+---------------------------+--------------------------------------------------+ Signature Computation """"""""""""""""""""" The possible options for key signature computation are: #. **Pre-computed key signature.** The key lookup operation is split between two CPU cores. The first CPU core (typically the CPU core that performs packet RX) extracts the key from the input packet, computes the key signature and saves both the key and the key signature in the packet buffer as packet meta-data. The second CPU core reads both the key and the key signature from the packet meta-data and performs the bucket search step of the key lookup operation. #. **Key signature computed on lookup ("do-sig" version).** The same CPU core reads the key from the packet meta-data, uses it to compute the key signature and also performs the bucket search step of the key lookup operation. .. _table_qos_24: .. table:: Configuration Parameters Specific to Pre-computed Key Signature Hash Table +---+------------------+-----------------------------------------------------------------------+ | # | Parameter | Details | | | | | +===+==================+=======================================================================+ | 1 | Signature offset | Offset of the pre-computed key signature within the packet meta-data. | | | | | +---+------------------+-----------------------------------------------------------------------+ Key Size Optimized Hash Tables """""""""""""""""""""""""""""" For specific key sizes, the data structures and algorithm of key lookup operation can be specially handcrafted for further performance improvements, so following options are possible: #. **Implementation supporting configurable key size.** #. **Implementation supporting a single key size.** Typical key sizes are 8 bytes and 16 bytes. Bucket Search Logic for Configurable Key Size Hash Tables ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The performance of the bucket search logic is one of the main factors influencing the performance of the key lookup operation. The data structures and algorithm are designed to make the best use of Intel CPU architecture resources like: cache memory space, cache memory bandwidth, external memory bandwidth, multiple execution units working in parallel, out of order instruction execution, special CPU instructions, etc. The bucket search logic handles multiple input packets in parallel. It is built as a pipeline of several stages (3 or 4), with each pipeline stage handling two different packets from the burst of input packets. On each pipeline iteration, the packets are pushed to the next pipeline stage: for the 4-stage pipeline, two packets (that just completed stage 3) exit the pipeline, two packets (that just completed stage 2) are now executing stage 3, two packets (that just completed stage 1) are now executing stage 2, two packets (that just completed stage 0) are now executing stage 1 and two packets (next two packets to read from the burst of input packets) are entering the pipeline to execute stage 0. The pipeline iterations continue until all packets from the burst of input packets execute the last stage of the pipeline. The bucket search logic is broken into pipeline stages at the boundary of the next memory access. Each pipeline stage uses data structures that are stored (with high probability) into the L1 or L2 cache memory of the current CPU core and breaks just before the next memory access required by the algorithm. The current pipeline stage finalizes by prefetching the data structures required by the next pipeline stage, so given enough time for the prefetch to complete, when the next pipeline stage eventually gets executed for the same packets, it will read the data structures it needs from L1 or L2 cache memory and thus avoid the significant penalty incurred by L2 or L3 cache memory miss. By prefetching the data structures required by the next pipeline stage in advance (before they are used) and switching to executing another pipeline stage for different packets, the number of L2 or L3 cache memory misses is greatly reduced, hence one of the main reasons for improved performance. This is because the cost of L2/L3 cache memory miss on memory read accesses is high, as usually due to data dependency between instructions, the CPU execution units have to stall until the read operation is completed from L3 cache memory or external DRAM memory. By using prefetch instructions, the latency of memory read accesses is hidden, provided that it is preformed early enough before the respective data structure is actually used. By splitting the processing into several stages that are executed on different packets (the packets from the input burst are interlaced), enough work is created to allow the prefetch instructions to complete successfully (before the prefetched data structures are actually accessed) and also the data dependency between instructions is loosened. For example, for the 4-stage pipeline, stage 0 is executed on packets 0 and 1 and then, before same packets 0 and 1 are used (i.e. before stage 1 is executed on packets 0 and 1), different packets are used: packets 2 and 3 (executing stage 1), packets 4 and 5 (executing stage 2) and packets 6 and 7 (executing stage 3). By executing useful work while the data structures are brought into the L1 or L2 cache memory, the latency of the read memory accesses is hidden. By increasing the gap between two consecutive accesses to the same data structure, the data dependency between instructions is loosened; this allows making the best use of the super-scalar and out-of-order execution CPU architecture, as the number of CPU core execution units that are active (rather than idle or stalled due to data dependency constraints between instructions) is maximized. The bucket search logic is also implemented without using any branch instructions. This avoids the important cost associated with flushing the CPU core execution pipeline on every instance of branch misprediction. Configurable Key Size Hash Table """""""""""""""""""""""""""""""" :numref:`figure_figure34`, :numref:`table_qos_25` and :numref:`table_qos_26` detail the main data structures used to implement configurable key size hash tables (either LRU or extendable bucket, either with pre-computed signature or "do-sig"). .. _figure_figure34: .. figure:: img/figure34.* Data Structures for Configurable Key Size Hash Tables .. _table_qos_25: .. table:: Main Large Data Structures (Arrays) used for Configurable Key Size Hash Tables +---+-------------------------+------------------------------+---------------------------+-------------------------------+ | # | Array name | Number of entries | Entry size (bytes) | Description | | | | | | | +===+=========================+==============================+===========================+===============================+ | 1 | Bucket array | n_buckets (configurable) | 32 | Buckets of the hash table. | | | | | | | +---+-------------------------+------------------------------+---------------------------+-------------------------------+ | 2 | Bucket extensions array | n_buckets_ext (configurable) | 32 | This array is only created | | | | | | for extendible bucket tables. | | | | | | | +---+-------------------------+------------------------------+---------------------------+-------------------------------+ | 3 | Key array | n_keys | key_size (configurable) | Keys added to the hash table. | | | | | | | +---+-------------------------+------------------------------+---------------------------+-------------------------------+ | 4 | Data array | n_keys | entry_size (configurable) | Key values (key data) | | | | | | associated with the hash | | | | | | table keys. | | | | | | | +---+-------------------------+------------------------------+---------------------------+-------------------------------+ .. _table_qos_26: .. table:: Field Description for Bucket Array Entry (Configurable Key Size Hash Tables) +---+------------------+--------------------+------------------------------------------------------------------+ | # | Field name | Field size (bytes) | Description | | | | | | +===+==================+====================+==================================================================+ | 1 | Next Ptr/LRU | 8 | For LRU tables, this fields represents the LRU list for the | | | | | current bucket stored as array of 4 entries of 2 bytes each. | | | | | Entry 0 stores the index (0 .. 3) of the MRU key, while entry 3 | | | | | stores the index of the LRU key. | | | | | | | | | | For extendible bucket tables, this field represents the next | | | | | pointer (i.e. the pointer to the next group of 4 keys linked to | | | | | the current bucket). The next pointer is not NULL if the bucket | | | | | is currently extended or NULL otherwise. | | | | | To help the branchless implementation, bit 0 (least significant | | | | | bit) of this field is set to 1 if the next pointer is not NULL | | | | | and to 0 otherwise. | | | | | | +---+------------------+--------------------+------------------------------------------------------------------+ | 2 | Sig[0 .. 3] | 4 x 2 | If key X (X = 0 .. 3) is valid, then sig X bits 15 .. 1 store | | | | | the most significant 15 bits of key X signature and sig X bit 0 | | | | | is set to 1. | | | | | | | | | | If key X is not valid, then sig X is set to zero. | | | | | | +---+------------------+--------------------+------------------------------------------------------------------+ | 3 | Key Pos [0 .. 3] | 4 x 4 | If key X is valid (X = 0 .. 3), then Key Pos X represents the | | | | | index into the key array where key X is stored, as well as the | | | | | index into the data array where the value associated with key X | | | | | is stored. | | | | | | | | | | If key X is not valid, then the value of Key Pos X is undefined. | | | | | | +---+------------------+--------------------+------------------------------------------------------------------+ :numref:`figure_figure35` and :numref:`table_qos_27` detail the bucket search pipeline stages (either LRU or extendable bucket, either with pre-computed signature or "do-sig"). For each pipeline stage, the described operations are applied to each of the two packets handled by that stage. .. _figure_figure35: .. figure:: img/figure35.* Bucket Search Pipeline for Key Lookup Operation (Configurable Key Size Hash Tables) .. _table_qos_27: .. table:: Description of the Bucket Search Pipeline Stages (Configurable Key Size Hash Tables) +---+---------------------------+------------------------------------------------------------------------------+ | # | Stage name | Description | | | | | +===+===========================+==============================================================================+ | 0 | Prefetch packet meta-data | Select next two packets from the burst of input packets. | | | | | | | | Prefetch packet meta-data containing the key and key signature. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 1 | Prefetch table bucket | Read the key signature from the packet meta-data (for extendable bucket hash | | | | tables) or read the key from the packet meta-data and compute key signature | | | | (for LRU tables). | | | | | | | | Identify the bucket ID using the key signature. | | | | | | | | Set bit 0 of the signature to 1 (to match only signatures of valid keys from | | | | the table). | | | | | | | | Prefetch the bucket. | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 2 | Prefetch table key | Read the key signatures from the bucket. | | | | | | | | Compare the signature of the input key against the 4 key signatures from the | | | | packet. As result, the following is obtained: | | | | | | | | *match* | | | | = equal to TRUE if there was at least one signature match and to FALSE in | | | | the case of no signature match; | | | | | | | | *match_many* | | | | = equal to TRUE is there were more than one signature matches (can be up to | | | | 4 signature matches in the worst case scenario) and to FALSE otherwise; | | | | | | | | *match_pos* | | | | = the index of the first key that produced signature match (only valid if | | | | match is true). | | | | | | | | For extendable bucket hash tables only, set | | | | *match_many* | | | | to TRUE if next pointer is valid. | | | | | | | | Prefetch the bucket key indicated by | | | | *match_pos* | | | | (even if | | | | *match_pos* | | | | does not point to valid key valid). | | | | | +---+---------------------------+------------------------------------------------------------------------------+ | 3 | Prefetch table data | Read the bucket key indicated by | | | | *match_pos*. | | | | | | | | Compare the bucket key against the input key. As result, the following is | | | | obtained: | | | | *match_key* | | | | = equal to TRUE if the two keys match and to FALSE otherwise. | | | | | | | | Report input key as lookup hit only when both | | | | *match* | | | | and | | | | *match_key* | | | | are equal to TRUE and as lookup miss otherwise. | | | | | | | | For LRU tables only, use branchless logic to update the bucket LRU list | | | | (the current key becomes the new MRU) only on lookup hit. | | | | | | | | Prefetch the key value (key data) associated with the current key (to avoid | | | | branches, this is done on both lookup hit and miss). | | | | | +---+---------------------------+------------------------------------------------------------------------------+ Additional notes: #. The pipelined version of the bucket search algorithm is executed only if there are at least 7 packets in the burst of input packets. If there are less than 7 packets in the burst of input packets, a non-optimized implementation of the bucket search algorithm is executed. #. Once the pipelined version of the bucket search algorithm has been executed for all the packets in the burst of input packets, the non-optimized implementation of the bucket search algorithm is also executed for any packets that did not produce a lookup hit, but have the *match_many* flag set. As result of executing the non-optimized version, some of these packets may produce a lookup hit or lookup miss. This does not impact the performance of the key lookup operation, as the probability of matching more than one signature in the same group of 4 keys or of having the bucket in extended state (for extendable bucket hash tables only) is relatively small. **Key Signature Comparison Logic** The key signature comparison logic is described in :numref:`table_qos_28`. .. _table_qos_28: .. table:: Lookup Tables for Match, Match_Many and Match_Pos +----+------+---------------+--------------------+--------------------+ | # | mask | match (1 bit) | match_many (1 bit) | match_pos (2 bits) | | | | | | | +----+------+---------------+--------------------+--------------------+ | 0 | 0000 | 0 | 0 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 1 | 0001 | 1 | 0 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 2 | 0010 | 1 | 0 | 01 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 3 | 0011 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 4 | 0100 | 1 | 0 | 10 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 5 | 0101 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 6 | 0110 | 1 | 1 | 01 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 7 | 0111 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 8 | 1000 | 1 | 0 | 11 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 9 | 1001 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 10 | 1010 | 1 | 1 | 01 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 11 | 1011 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 12 | 1100 | 1 | 1 | 10 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 13 | 1101 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 14 | 1110 | 1 | 1 | 01 | | | | | | | +----+------+---------------+--------------------+--------------------+ | 15 | 1111 | 1 | 1 | 00 | | | | | | | +----+------+---------------+--------------------+--------------------+ The input *mask* hash bit X (X = 0 .. 3) set to 1 if input signature is equal to bucket signature X and set to 0 otherwise. The outputs *match*, *match_many* and *match_pos* are 1 bit, 1 bit and 2 bits in size respectively and their meaning has been explained above. As displayed in :numref:`table_qos_29`, the lookup tables for *match* and *match_many* can be collapsed into a single 32-bit value and the lookup table for *match_pos* can be collapsed into a 64-bit value. Given the input *mask*, the values for *match*, *match_many* and *match_pos* can be obtained by indexing their respective bit array to extract 1 bit, 1 bit and 2 bits respectively with branchless logic. .. _table_qos_29: .. table:: Collapsed Lookup Tables for Match, Match_Many and Match_Pos +------------+------------------------------------------+-------------------+ | | Bit array | Hexadecimal value | | | | | +------------+------------------------------------------+-------------------+ | match | 1111_1111_1111_1110 | 0xFFFELLU | | | | | +------------+------------------------------------------+-------------------+ | match_many | 1111_1110_1110_1000 | 0xFEE8LLU | | | | | +------------+------------------------------------------+-------------------+ | match_pos | 0001_0010_0001_0011__0001_0010_0001_0000 | 0x12131210LLU | | | | | +------------+------------------------------------------+-------------------+ The pseudo-code for match, match_many and match_pos is:: match = (0xFFFELLU >> mask) & 1; match_many = (0xFEE8LLU >> mask) & 1; match_pos = (0x12131210LLU >> (mask << 1)) & 3; Single Key Size Hash Tables """"""""""""""""""""""""""" :numref:`figure_figure37`, :numref:`figure_figure38`, :numref:`table_qos_30` and :numref:`table_qos_31` detail the main data structures used to implement 8-byte and 16-byte key hash tables (either LRU or extendable bucket, either with pre-computed signature or "do-sig"). .. _figure_figure37: .. figure:: img/figure37.* Data Structures for 8-byte Key Hash Tables .. _figure_figure38: .. figure:: img/figure38.* Data Structures for 16-byte Key Hash Tables .. _table_qos_30: .. table:: Main Large Data Structures (Arrays) used for 8-byte and 16-byte Key Size Hash Tables +---+-------------------------+------------------------------+----------------------+------------------------------------+ | # | Array name | Number of entries | Entry size (bytes) | Description | | | | | | | +===+=========================+==============================+======================+====================================+ | 1 | Bucket array | n_buckets (configurable) | *8-byte key size:* | Buckets of the hash table. | | | | | | | | | | | 64 + 4 x entry_size | | | | | | | | | | | | | | | | | | *16-byte key size:* | | | | | | | | | | | | 128 + 4 x entry_size | | | | | | | | +---+-------------------------+------------------------------+----------------------+------------------------------------+ | 2 | Bucket extensions array | n_buckets_ext (configurable) | *8-byte key size:* | This array is only created for | | | | | | extendible bucket tables. | | | | | | | | | | | 64 + 4 x entry_size | | | | | | | | | | | | | | | | | | *16-byte key size:* | | | | | | | | | | | | 128 + 4 x entry_size | | | | | | | | +---+-------------------------+------------------------------+----------------------+------------------------------------+ .. _table_qos_31: .. table:: Field Description for Bucket Array Entry (8-byte and 16-byte Key Hash Tables) +---+---------------+--------------------+-------------------------------------------------------------------------------+ | # | Field name | Field size (bytes) | Description | | | | | | +===+===============+====================+===============================================================================+ | 1 | Valid | 8 | Bit X (X = 0 .. 3) is set to 1 if key X is valid or to 0 otherwise. | | | | | | | | | | Bit 4 is only used for extendible bucket tables to help with the | | | | | implementation of the branchless logic. In this case, bit 4 is set to 1 if | | | | | next pointer is valid (not NULL) or to 0 otherwise. | | | | | | +---+---------------+--------------------+-------------------------------------------------------------------------------+ | 2 | Next Ptr/LRU | 8 | For LRU tables, this fields represents the LRU list for the current bucket | | | | | stored as array of 4 entries of 2 bytes each. Entry 0 stores the index | | | | | (0 .. 3) of the MRU key, while entry 3 stores the index of the LRU key. | | | | | | | | | | For extendible bucket tables, this field represents the next pointer (i.e. | | | | | the pointer to the next group of 4 keys linked to the current bucket). The | | | | | next pointer is not NULL if the bucket is currently extended or NULL | | | | | otherwise. | | | | | | +---+---------------+--------------------+-------------------------------------------------------------------------------+ | 3 | Key [0 .. 3] | 4 x key_size | Full keys. | | | | | | +---+---------------+--------------------+-------------------------------------------------------------------------------+ | 4 | Data [0 .. 3] | 4 x entry_size | Full key values (key data) associated with keys 0 .. 3. | | | | | | +---+---------------+--------------------+-------------------------------------------------------------------------------+ and detail the bucket search pipeline used to implement 8-byte and 16-byte key hash tables (either LRU or extendable bucket, either with pre-computed signature or "do-sig"). For each pipeline stage, the described operations are applied to each of the two packets handled by that stage. .. _figure_figure39: .. figure:: img/figure39.* Bucket Search Pipeline for Key Lookup Operation (Single Key Size Hash Tables) .. _table_qos_32: .. table:: Description of the Bucket Search Pipeline Stages (8-byte and 16-byte Key Hash Tables) +---+---------------------------+-----------------------------------------------------------------------------+ | # | Stage name | Description | | | | | +===+===========================+=============================================================================+ | 0 | Prefetch packet meta-data | #. Select next two packets from the burst of input packets. | | | | | | | | #. Prefetch packet meta-data containing the key and key signature. | | | | | +---+---------------------------+-----------------------------------------------------------------------------+ | 1 | Prefetch table bucket | #. Read the key signature from the packet meta-data (for extendable bucket | | | | hash tables) or read the key from the packet meta-data and compute key | | | | signature (for LRU tables). | | | | | | | | #. Identify the bucket ID using the key signature. | | | | | | | | #. Prefetch the bucket. | | | | | +---+---------------------------+-----------------------------------------------------------------------------+ | 2 | Prefetch table data | #. Read the bucket. | | | | | | | | #. Compare all 4 bucket keys against the input key. | | | | | | | | #. Report input key as lookup hit only when a match is identified (more | | | | than one key match is not possible) | | | | | | | | #. For LRU tables only, use branchless logic to update the bucket LRU list | | | | (the current key becomes the new MRU) only on lookup hit. | | | | | | | | #. Prefetch the key value (key data) associated with the matched key (to | | | | avoid branches, this is done on both lookup hit and miss). | | | | | +---+---------------------------+-----------------------------------------------------------------------------+ Additional notes: #. The pipelined version of the bucket search algorithm is executed only if there are at least 5 packets in the burst of input packets. If there are less than 5 packets in the burst of input packets, a non-optimized implementation of the bucket search algorithm is executed. #. For extendable bucket hash tables only, once the pipelined version of the bucket search algorithm has been executed for all the packets in the burst of input packets, the non-optimized implementation of the bucket search algorithm is also executed for any packets that did not produce a lookup hit, but have the bucket in extended state. As result of executing the non-optimized version, some of these packets may produce a lookup hit or lookup miss. This does not impact the performance of the key lookup operation, as the probability of having the bucket in extended state is relatively small. Pipeline Library Design ----------------------- A pipeline is defined by: #. The set of input ports; #. The set of output ports; #. The set of tables; #. The set of actions. The input ports are connected with the output ports through tree-like topologies of interconnected tables. The table entries contain the actions defining the operations to be executed on the input packets and the packet flow within the pipeline. Connectivity of Ports and Tables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To avoid any dependencies on the order in which pipeline elements are created, the connectivity of pipeline elements is defined after all the pipeline input ports, output ports and tables have been created. General connectivity rules: #. Each input port is connected to a single table. No input port should be left unconnected; #. The table connectivity to other tables or to output ports is regulated by the next hop actions of each table entry and the default table entry. The table connectivity is fluid, as the table entries and the default table entry can be updated during run-time. * A table can have multiple entries (including the default entry) connected to the same output port. A table can have different entries connected to different output ports. Different tables can have entries (including default table entry) connected to the same output port. * A table can have multiple entries (including the default entry) connected to another table, in which case all these entries have to point to the same table. This constraint is enforced by the API and prevents tree-like topologies from being created (allowing table chaining only), with the purpose of simplifying the implementation of the pipeline run-time execution engine. Port Actions ~~~~~~~~~~~~ Port Action Handler ^^^^^^^^^^^^^^^^^^^ An action handler can be assigned to each input/output port to define actions to be executed on each input packet that is received by the port. Defining the action handler for a specific input/output port is optional (i.e. the action handler can be disabled). For input ports, the action handler is executed after RX function. For output ports, the action handler is executed before the TX function. The action handler can decide to drop packets. Table Actions ~~~~~~~~~~~~~ Table Action Handler ^^^^^^^^^^^^^^^^^^^^ An action handler to be executed on each input packet can be assigned to each table. Defining the action handler for a specific table is optional (i.e. the action handler can be disabled). The action handler is executed after the table lookup operation is performed and the table entry associated with each input packet is identified. The action handler can only handle the user-defined actions, while the reserved actions (e.g. the next hop actions) are handled by the Packet Framework. The action handler can decide to drop the input packet. Reserved Actions ^^^^^^^^^^^^^^^^ The reserved actions are handled directly by the Packet Framework without the user being able to change their meaning through the table action handler configuration. A special category of the reserved actions is represented by the next hop actions, which regulate the packet flow between input ports, tables and output ports through the pipeline. :numref:`table_qos_33` lists the next hop actions. .. _table_qos_33: .. table:: Next Hop Actions (Reserved) +---+---------------------+-----------------------------------------------------------------------------------+ | # | Next hop action | Description | | | | | +===+=====================+===================================================================================+ | 1 | Drop | Drop the current packet. | | | | | +---+---------------------+-----------------------------------------------------------------------------------+ | 2 | Send to output port | Send the current packet to specified output port. The output port ID is metadata | | | | stored in the same table entry. | | | | | +---+---------------------+-----------------------------------------------------------------------------------+ | 3 | Send to table | Send the current packet to specified table. The table ID is metadata stored in | | | | the same table entry. | | | | | +---+---------------------+-----------------------------------------------------------------------------------+ User Actions ^^^^^^^^^^^^ For each table, the meaning of user actions is defined through the configuration of the table action handler. Different tables can be configured with different action handlers, therefore the meaning of the user actions and their associated meta-data is private to each table. Within the same table, all the table entries (including the table default entry) share the same definition for the user actions and their associated meta-data, with each table entry having its own set of enabled user actions and its own copy of the action meta-data. :numref:`table_qos_34` contains a non-exhaustive list of user action examples. .. _table_qos_34: .. table:: User Action Examples +---+-----------------------------------+---------------------------------------------------------------------+ | # | User action | Description | | | | | +===+===================================+=====================================================================+ | 1 | Metering | Per flow traffic metering using the srTCM and trTCM algorithms. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ | 2 | Statistics | Update the statistics counters maintained per flow. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ | 3 | App ID | Per flow state machine fed by variable length sequence of packets | | | | at the flow initialization with the purpose of identifying the | | | | traffic type and application. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ | 4 | Push/pop labels | Push/pop VLAN/MPLS labels to/from the current packet. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ | 5 | Network Address Translation (NAT) | Translate between the internal (LAN) and external (WAN) IP | | | | destination/source address and/or L4 protocol destination/source | | | | port. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ | 6 | TTL update | Decrement IP TTL and, in case of IPv4 packets, update the IP | | | | checksum. | | | | | +---+-----------------------------------+---------------------------------------------------------------------+ Multicore Scaling ----------------- A complex application is typically split across multiple cores, with cores communicating through SW queues. There is usually a performance limit on the number of table lookups and actions that can be fitted on the same CPU core due to HW constraints like: available CPU cycles, cache memory size, cache transfer BW, memory transfer BW, etc. As the application is split across multiple CPU cores, the Packet Framework facilitates the creation of several pipelines, the assignment of each such pipeline to a different CPU core and the interconnection of all CPU core-level pipelines into a single application-level complex pipeline. For example, if CPU core A is assigned to run pipeline P1 and CPU core B pipeline P2, then the interconnection of P1 with P2 could be achieved by having the same set of SW queues act like output ports for P1 and input ports for P2. This approach enables the application development using the pipeline, run-to-completion (clustered) or hybrid (mixed) models. It is allowed for the same core to run several pipelines, but it is not allowed for several cores to run the same pipeline. Shared Data Structures ~~~~~~~~~~~~~~~~~~~~~~ The threads performing table lookup are actually table writers rather than just readers. Even if the specific table lookup algorithm is thread-safe for multiple readers (e. g. read-only access of the search algorithm data structures is enough to conduct the lookup operation), once the table entry for the current packet is identified, the thread is typically expected to update the action meta-data stored in the table entry (e.g. increment the counter tracking the number of packets that hit this table entry), and thus modify the table entry. During the time this thread is accessing this table entry (either writing or reading; duration is application specific), for data consistency reasons, no other threads (threads performing table lookup or entry add/delete operations) are allowed to modify this table entry. Mechanisms to share the same table between multiple threads: #. **Multiple writer threads.** Threads need to use synchronization primitives like semaphores (distinct semaphore per table entry) or atomic instructions. The cost of semaphores is usually high, even when the semaphore is free. The cost of atomic instructions is normally higher than the cost of regular instructions. #. **Multiple writer threads, with single thread performing table lookup operations and multiple threads performing table entry add/delete operations.** The threads performing table entry add/delete operations send table update requests to the reader (typically through message passing queues), which does the actual table updates and then sends the response back to the request initiator. #. **Single writer thread performing table entry add/delete operations and multiple reader threads that perform table lookup operations with read-only access to the table entries.** The reader threads use the main table copy while the writer is updating the mirror copy. Once the writer update is done, the writer can signal to the readers and busy wait until all readers swaps between the mirror copy (which now becomes the main copy) and the mirror copy (which now becomes the main copy). Interfacing with Accelerators ----------------------------- The presence of accelerators is usually detected during the initialization phase by inspecting the HW devices that are part of the system (e.g. by PCI bus enumeration). Typical devices with acceleration capabilities are: * Inline accelerators: NICs, switches, FPGAs, etc; * Look-aside accelerators: chipsets, FPGAs, etc. Usually, to support a specific functional block, specific implementation of Packet Framework tables and/or ports and/or actions has to be provided for each accelerator, with all the implementations sharing the same API: pure SW implementation (no acceleration), implementation using accelerator A, implementation using accelerator B, etc. The selection between these implementations could be done at build time or at run-time (recommended), based on which accelerators are present in the system, with no application changes required. ================================================ FILE: doc/guides/prog_guide/perf_opt_guidelines.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Performance_Optimization: **Part 3: Performance Optimization** Performance Optimization Guidelines =================================== Introduction ------------ The following sections describe optimizations used in the DPDK and optimizations that should be considered for a new applications. They also highlight the performance-impacting coding techniques that should, and should not be, used when developing an application using the DPDK. And finally, they give an introduction to application profiling using a Performance Analyzer from Intel to optimize the software. ================================================ FILE: doc/guides/prog_guide/poll_mode_drv.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Poll_Mode_Driver: Poll Mode Driver ================ The DPDK includes 1 Gigabit, 10 Gigabit and 40 Gigabit and para virtualized virtio Poll Mode Drivers. A Poll Mode Driver (PMD) consists of APIs, provided through the BSD driver running in user space, to configure the devices and their respective queues. In addition, a PMD accesses the RX and TX descriptors directly without any interrupts (with the exception of Link Status Change interrupts) to quickly receive, process and deliver packets in the user's application. This section describes the requirements of the PMDs, their global design principles and proposes a high-level architecture and a generic external API for the Ethernet PMDs. Requirements and Assumptions ---------------------------- The DPDK environment for packet processing applications allows for two models, run-to-completion and pipe-line: * In the *run-to-completion* model, a specific port's RX descriptor ring is polled for packets through an API. Packets are then processed on the same core and placed on a port's TX descriptor ring through an API for transmission. * In the *pipe-line* model, one core polls one or more port's RX descriptor ring through an API. Packets are received and passed to another core via a ring. The other core continues to process the packet which then may be placed on a port's TX descriptor ring through an API for transmission. In a synchronous run-to-completion model, each logical core assigned to the DPDK executes a packet processing loop that includes the following steps: * Retrieve input packets through the PMD receive API * Process each received packet one at a time, up to its forwarding * Send pending output packets through the PMD transmit API Conversely, in an asynchronous pipe-line model, some logical cores may be dedicated to the retrieval of received packets and other logical cores to the processing of previously received packets. Received packets are exchanged between logical cores through rings. The loop for packet retrieval includes the following steps: * Retrieve input packets through the PMD receive API * Provide received packets to processing lcores through packet queues The loop for packet processing includes the following steps: * Retrieve the received packet from the packet queue * Process the received packet, up to its retransmission if forwarded To avoid any unnecessary interrupt processing overhead, the execution environment must not use any asynchronous notification mechanisms. Whenever needed and appropriate, asynchronous communication should be introduced as much as possible through the use of rings. Avoiding lock contention is a key issue in a multi-core environment. To address this issue, PMDs are designed to work with per-core private resources as much as possible. For example, a PMD maintains a separate transmit queue per-core, per-port. In the same way, every receive queue of a port is assigned to and polled by a single logical core (lcore). To comply with Non-Uniform Memory Access (NUMA), memory management is designed to assign to each logical core a private buffer pool in local memory to minimize remote memory access. The configuration of packet buffer pools should take into account the underlying physical memory architecture in terms of DIMMS, channels and ranks. The application must ensure that appropriate parameters are given at memory pool creation time. See :ref:`Mempool Library `. Design Principles ----------------- The API and architecture of the Ethernet* PMDs are designed with the following guidelines in mind. PMDs must help global policy-oriented decisions to be enforced at the upper application level. Conversely, NIC PMD functions should not impede the benefits expected by upper-level global policies, or worse prevent such policies from being applied. For instance, both the receive and transmit functions of a PMD have a maximum number of packets/descriptors to poll. This allows a run-to-completion processing stack to statically fix or to dynamically adapt its overall behavior through different global loop policies, such as: * Receive, process immediately and transmit packets one at a time in a piecemeal fashion. * Receive as many packets as possible, then process all received packets, transmitting them immediately. * Receive a given maximum number of packets, process the received packets, accumulate them and finally send all accumulated packets to transmit. To achieve optimal performance, overall software design choices and pure software optimization techniques must be considered and balanced against available low-level hardware-based optimization features (CPU cache properties, bus speed, NIC PCI bandwidth, and so on). The case of packet transmission is an example of this software/hardware tradeoff issue when optimizing burst-oriented network packet processing engines. In the initial case, the PMD could export only an rte_eth_tx_one function to transmit one packet at a time on a given queue. On top of that, one can easily build an rte_eth_tx_burst function that loops invoking the rte_eth_tx_one function to transmit several packets at a time. However, an rte_eth_tx_burst function is effectively implemented by the PMD to minimize the driver-level transmit cost per packet through the following optimizations: * Share among multiple packets the un-amortized cost of invoking the rte_eth_tx_one function. * Enable the rte_eth_tx_burst function to take advantage of burst-oriented hardware features (prefetch data in cache, use of NIC head/tail registers) to minimize the number of CPU cycles per packet, for example by avoiding unnecessary read memory accesses to ring transmit descriptors, or by systematically using arrays of pointers that exactly fit cache line boundaries and sizes. * Apply burst-oriented software optimization techniques to remove operations that would otherwise be unavoidable, such as ring index wrap back management. Burst-oriented functions are also introduced via the API for services that are intensively used by the PMD. This applies in particular to buffer allocators used to populate NIC rings, which provide functions to allocate/free several buffers at a time. For example, an mbuf_multiple_alloc function returning an array of pointers to rte_mbuf buffers which speeds up the receive poll function of the PMD when replenishing multiple descriptors of the receive ring. Logical Cores, Memory and NIC Queues Relationships -------------------------------------------------- The DPDK supports NUMA allowing for better performance when a processor's logical cores and interfaces utilize its local memory. Therefore, mbuf allocation associated with local PCIe* interfaces should be allocated from memory pools created in the local memory. The buffers should, if possible, remain on the local processor to obtain the best performance results and RX and TX buffer descriptors should be populated with mbufs allocated from a mempool allocated from local memory. The run-to-completion model also performs better if packet or data manipulation is in local memory instead of a remote processors memory. This is also true for the pipe-line model provided all logical cores used are located on the same processor. Multiple logical cores should never share receive or transmit queues for interfaces since this would require global locks and hinder performance. Device Identification and Configuration --------------------------------------- Device Identification ~~~~~~~~~~~~~~~~~~~~~ Each NIC port is uniquely designated by its (bus/bridge, device, function) PCI identifiers assigned by the PCI probing/enumeration function executed at DPDK initialization. Based on their PCI identifier, NIC ports are assigned two other identifiers: * A port index used to designate the NIC port in all functions exported by the PMD API. * A port name used to designate the port in console messages, for administration or debugging purposes. For ease of use, the port name includes the port index. Device Configuration ~~~~~~~~~~~~~~~~~~~~ The configuration of each NIC port includes the following operations: * Allocate PCI resources * Reset the hardware (issue a Global Reset) to a well-known default state * Set up the PHY and the link * Initialize statistics counters The PMD API must also export functions to start/stop the all-multicast feature of a port and functions to set/unset the port in promiscuous mode. Some hardware offload features must be individually configured at port initialization through specific configuration parameters. This is the case for the Receive Side Scaling (RSS) and Data Center Bridging (DCB) features for example. On-the-Fly Configuration ~~~~~~~~~~~~~~~~~~~~~~~~ All device features that can be started or stopped "on the fly" (that is, without stopping the device) do not require the PMD API to export dedicated functions for this purpose. All that is required is the mapping address of the device PCI registers to implement the configuration of these features in specific functions outside of the drivers. For this purpose, the PMD API exports a function that provides all the information associated with a device that can be used to set up a given device feature outside of the driver. This includes the PCI vendor identifier, the PCI device identifier, the mapping address of the PCI device registers, and the name of the driver. The main advantage of this approach is that it gives complete freedom on the choice of the API used to configure, to start, and to stop such features. As an example, refer to the configuration of the IEEE1588 feature for the Intel® 82576 Gigabit Ethernet Controller and the Intel® 82599 10 Gigabit Ethernet Controller controllers in the testpmd application. Other features such as the L3/L4 5-Tuple packet filtering feature of a port can be configured in the same way. Ethernet* flow control (pause frame) can be configured on the individual port. Refer to the testpmd source code for details. Also, L4 (UDP/TCP/ SCTP) checksum offload by the NIC can be enabled for an individual packet as long as the packet mbuf is set up correctly. See `Hardware Offload`_ for details. Configuration of Transmit and Receive Queues ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Each transmit queue is independently configured with the following information: * The number of descriptors of the transmit ring * The socket identifier used to identify the appropriate DMA memory zone from which to allocate the transmit ring in NUMA architectures * The values of the Prefetch, Host and Write-Back threshold registers of the transmit queue * The *minimum* transmit packets to free threshold (tx_free_thresh). When the number of descriptors used to transmit packets exceeds this threshold, the network adaptor should be checked to see if it has written back descriptors. A value of 0 can be passed during the TX queue configuration to indicate the default value should be used. The default value for tx_free_thresh is 32. This ensures that the PMD does not search for completed descriptors until at least 32 have been processed by the NIC for this queue. * The *minimum* RS bit threshold. The minimum number of transmit descriptors to use before setting the Report Status (RS) bit in the transmit descriptor. Note that this parameter may only be valid for Intel 10 GbE network adapters. The RS bit is set on the last descriptor used to transmit a packet if the number of descriptors used since the last RS bit setting, up to the first descriptor used to transmit the packet, exceeds the transmit RS bit threshold (tx_rs_thresh). In short, this parameter controls which transmit descriptors are written back to host memory by the network adapter. A value of 0 can be passed during the TX queue configuration to indicate that the default value should be used. The default value for tx_rs_thresh is 32. This ensures that at least 32 descriptors are used before the network adapter writes back the most recently used descriptor. This saves upstream PCIe* bandwidth resulting from TX descriptor write-backs. It is important to note that the TX Write-back threshold (TX wthresh) should be set to 0 when tx_rs_thresh is greater than 1. Refer to the Intel® 82599 10 Gigabit Ethernet Controller Datasheet for more details. The following constraints must be satisfied for tx_free_thresh and tx_rs_thresh: * tx_rs_thresh must be greater than 0. * tx_rs_thresh must be less than the size of the ring minus 2. * tx_rs_thresh must be less than or equal to tx_free_thresh. * tx_free_thresh must be greater than 0. * tx_free_thresh must be less than the size of the ring minus 3. * For optimal performance, TX wthresh should be set to 0 when tx_rs_thresh is greater than 1. One descriptor in the TX ring is used as a sentinel to avoid a hardware race condition, hence the maximum threshold constraints. .. note:: When configuring for DCB operation, at port initialization, both the number of transmit queues and the number of receive queues must be set to 128. Hardware Offload ~~~~~~~~~~~~~~~~ Depending on driver capabilities advertised by ``rte_eth_dev_info_get()``, the PMD may support hardware offloading feature like checksumming, TCP segmentation or VLAN insertion. The support of these offload features implies the addition of dedicated status bit(s) and value field(s) into the rte_mbuf data structure, along with their appropriate handling by the receive/transmit functions exported by each PMD. The list of flags and their precise meaning is described in the mbuf API documentation and in the in :ref:`Mbuf Library `, section "Meta Information". Poll Mode Driver API -------------------- Generalities ~~~~~~~~~~~~ By default, all functions exported by a PMD are lock-free functions that are assumed not to be invoked in parallel on different logical cores to work on the same target object. For instance, a PMD receive function cannot be invoked in parallel on two logical cores to poll the same RX queue of the same port. Of course, this function can be invoked in parallel by different logical cores on different RX queues. It is the responsibility of the upper-level application to enforce this rule. If needed, parallel accesses by multiple logical cores to shared queues can be explicitly protected by dedicated inline lock-aware functions built on top of their corresponding lock-free functions of the PMD API. Generic Packet Representation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A packet is represented by an rte_mbuf structure, which is a generic metadata structure containing all necessary housekeeping information. This includes fields and status bits corresponding to offload hardware features, such as checksum computation of IP headers or VLAN tags. The rte_mbuf data structure includes specific fields to represent, in a generic way, the offload features provided by network controllers. For an input packet, most fields of the rte_mbuf structure are filled in by the PMD receive function with the information contained in the receive descriptor. Conversely, for output packets, most fields of rte_mbuf structures are used by the PMD transmit function to initialize transmit descriptors. The mbuf structure is fully described in the :ref:`Mbuf Library ` chapter. Ethernet Device API ~~~~~~~~~~~~~~~~~~~ The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*. ================================================ FILE: doc/guides/prog_guide/port_hotplug_framework.rst ================================================ .. BSD LICENSE Copyright(c) 2015 IGEL Co.,Ltd. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of IGEL Co.,Ltd. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Port Hotplug Framework ====================== The Port Hotplug Framework provides DPDK applications with the ability to attach and detach ports at runtime. Because the framework depends on PMD implementation, the ports that PMDs cannot handle are out of scope of this framework. Furthermore, after detaching a port from a DPDK application, the framework doesn't provide a way for removing the devices from the system. For the ports backed by a physical NIC, the kernel will need to support PCI Hotplug feature. Overview -------- The basic requirements of the Port Hotplug Framework are: * DPDK applications that use the Port Hotplug Framework must manage their own ports. The Port Hotplug Framework is implemented to allow DPDK applications to manage ports. For example, when DPDK applications call the port attach function, the attached port number is returned. DPDK applications can also detach the port by port number. * Kernel support is needed for attaching or detaching physical device ports. To attach new physical device ports, the device will be recognized by userspace driver I/O framework in kernel at first. Then DPDK applications can call the Port Hotplug functions to attach the ports. For detaching, steps are vice versa. * Before detaching, they must be stopped and closed. DPDK applications must call "rte_eth_dev_stop()" and "rte_eth_dev_close()" APIs before detaching ports. These functions will start finalization sequence of the PMDs. * The framework doesn't affect legacy DPDK applications behavior. If the Port Hotplug functions aren't called, all legacy DPDK apps can still work without modifications. Port Hotplug API overview ------------------------- * Attaching a port "rte_eth_dev_attach()" API attaches a port to DPDK application, and returns the attached port number. Before calling the API, the device should be recognized by an userspace driver I/O framework. The API receives a pci address like "0000:01:00.0" or a virtual device name like "eth_pcap0,iface=eth0". In the case of virtual device name, the format is the same as the general "--vdev" option of DPDK. * Detaching a port "rte_eth_dev_detach()" API detaches a port from DPDK application, and returns a pci address of the detached device or a virtual device name of the device. Reference --------- "testpmd" supports the Port Hotplug Framework. Limitations ----------- * The Port Hotplug APIs are not thread safe. * The framework can only be enabled with Linux. BSD is not supported. * To detach a port, the port should be backed by a device that igb_uio manages. VFIO is not supported. * Not all PMDs support detaching feature. To know whether a PMD can support detaching, search for the "RTE_PCI_DRV_DETACHABLE" flag in PMD implementation. If the flag is defined in the PMD, detaching is supported. ================================================ FILE: doc/guides/prog_guide/power_man.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Power Management ================ The DPDK Power Management feature allows users space applications to save power by dynamically adjusting CPU frequency or entering into different C-States. * Adjusting the CPU frequency dynamically according to the utilization of RX queue. * Entering into different deeper C-States according to the adaptive algorithms to speculate brief periods of time suspending the application if no packets are received. The interfaces for adjusting the operating CPU frequency are in the power management library. C-State control is implemented in applications according to the different use cases. CPU Frequency Scaling --------------------- The Linux kernel provides a cpufreq module for CPU frequency scaling for each lcore. For example, for cpuX, /sys/devices/system/cpu/cpuX/cpufreq/ has the following sys files for frequency scaling: * affected_cpus * bios_limit * cpuinfo_cur_freq * cpuinfo_max_freq * cpuinfo_min_freq * cpuinfo_transition_latency * related_cpus * scaling_available_frequencies * scaling_available_governors * scaling_cur_freq * scaling_driver * scaling_governor * scaling_max_freq * scaling_min_freq * scaling_setspeed In the DPDK, scaling_governor is configured in user space. Then, a user space application can prompt the kernel by writing scaling_setspeed to adjust the CPU frequency according to the strategies defined by the user space application. Core-load Throttling through C-States ------------------------------------- Core state can be altered by speculative sleeps whenever the specified lcore has nothing to do. In the DPDK, if no packet is received after polling, speculative sleeps can be triggered according the strategies defined by the user space application. API Overview of the Power Library --------------------------------- The main methods exported by power library are for CPU frequency scaling and include the following: * **Freq up**: Prompt the kernel to scale up the frequency of the specific lcore. * **Freq down**: Prompt the kernel to scale down the frequency of the specific lcore. * **Freq max**: Prompt the kernel to scale up the frequency of the specific lcore to the maximum. * **Freq min**: Prompt the kernel to scale down the frequency of the specific lcore to the minimum. * **Get available freqs**: Read the available frequencies of the specific lcore from the sys file. * **Freq get**: Get the current frequency of the specific lcore. * **Freq set**: Prompt the kernel to set the frequency for the specific lcore. User Cases ---------- The power management mechanism is used to save power when performing L3 forwarding. References ---------- * l3fwd-power: The sample application in DPDK that performs L3 forwarding with power management. * The "L3 Forwarding with Power Management Sample Application" chapter in the *DPDK Sample Application's User Guide*. ================================================ FILE: doc/guides/prog_guide/profile_app.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Profile Your Application ======================== Intel processors provide performance counters to monitor events. Some tools provided by Intel can be used to profile and benchmark an application. See the *VTune Performance Analyzer Essentials* publication from Intel Press for more information. For a DPDK application, this can be done in a Linux* application environment only. The main situations that should be monitored through event counters are: * Cache misses * Branch mis-predicts * DTLB misses * Long latency instructions and exceptions Refer to the `Intel Performance Analysis Guide `_ for details about application profiling. ================================================ FILE: doc/guides/prog_guide/qos_framework.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Quality of Service (QoS) Framework ================================== This chapter describes the DPDK Quality of Service (QoS) framework. Packet Pipeline with QoS Support -------------------------------- An example of a complex packet processing pipeline with QoS support is shown in the following figure. .. _figure_pkt_proc_pipeline_qos: .. figure:: img/pkt_proc_pipeline_qos.* Complex Packet Processing Pipeline with QoS Support This pipeline can be built using reusable DPDK software libraries. The main blocks implementing QoS in this pipeline are: the policer, the dropper and the scheduler. A functional description of each block is provided in the following table. .. _table_qos_1: .. table:: Packet Processing Pipeline Implementing QoS +---+------------------------+--------------------------------------------------------------------------------+ | # | Block | Functional Description | | | | | +===+========================+================================================================================+ | 1 | Packet I/O RX & TX | Packet reception/ transmission from/to multiple NIC ports. Poll mode drivers | | | | (PMDs) for Intel 1 GbE/10 GbE NICs. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 2 | Packet parser | Identify the protocol stack of the input packet. Check the integrity of the | | | | packet headers. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 3 | Flow classification | Map the input packet to one of the known traffic flows. Exact match table | | | | lookup using configurable hash function (jhash, CRC and so on) and bucket | | | | logic to handle collisions. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 4 | Policer | Packet metering using srTCM (RFC 2697) or trTCM (RFC2698) algorithms. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 5 | Load Balancer | Distribute the input packets to the application workers. Provide uniform load | | | | to each worker. Preserve the affinity of traffic flows to workers and the | | | | packet order within each flow. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 6 | Worker threads | Placeholders for the customer specific application workload (for example, IP | | | | stack and so on). | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 7 | Dropper | Congestion management using the Random Early Detection (RED) algorithm | | | | (specified by the Sally Floyd - Van Jacobson paper) or Weighted RED (WRED). | | | | Drop packets based on the current scheduler queue load level and packet | | | | priority. When congestion is experienced, lower priority packets are dropped | | | | first. | | | | | +---+------------------------+--------------------------------------------------------------------------------+ | 8 | Hierarchical Scheduler | 5-level hierarchical scheduler (levels are: output port, subport, pipe, | | | | traffic class and queue) with thousands (typically 64K) leaf nodes (queues). | | | | Implements traffic shaping (for subport and pipe levels), strict priority | | | | (for traffic class level) and Weighted Round Robin (WRR) (for queues within | | | | each pipe traffic class). | | | | | +---+------------------------+--------------------------------------------------------------------------------+ The infrastructure blocks used throughout the packet processing pipeline are listed in the following table. .. _table_qos_2: .. table:: Infrastructure Blocks Used by the Packet Processing Pipeline +---+-----------------------+-----------------------------------------------------------------------+ | # | Block | Functional Description | | | | | +===+=======================+=======================================================================+ | 1 | Buffer manager | Support for global buffer pools and private per-thread buffer caches. | | | | | +---+-----------------------+-----------------------------------------------------------------------+ | 2 | Queue manager | Support for message passing between pipeline blocks. | | | | | +---+-----------------------+-----------------------------------------------------------------------+ | 3 | Power saving | Support for power saving during low activity periods. | | | | | +---+-----------------------+-----------------------------------------------------------------------+ The mapping of pipeline blocks to CPU cores is configurable based on the performance level required by each specific application and the set of features enabled for each block. Some blocks might consume more than one CPU core (with each CPU core running a different instance of the same block on different input packets), while several other blocks could be mapped to the same CPU core. Hierarchical Scheduler ---------------------- The hierarchical scheduler block, when present, usually sits on the TX side just before the transmission stage. Its purpose is to prioritize the transmission of packets from different users and different traffic classes according to the policy specified by the Service Level Agreements (SLAs) of each network node. Overview ~~~~~~~~ The hierarchical scheduler block is similar to the traffic manager block used by network processors that typically implement per flow (or per group of flows) packet queuing and scheduling. It typically acts like a buffer that is able to temporarily store a large number of packets just before their transmission (enqueue operation); as the NIC TX is requesting more packets for transmission, these packets are later on removed and handed over to the NIC TX with the packet selection logic observing the predefined SLAs (dequeue operation). .. _figure_hier_sched_blk: .. figure:: img/hier_sched_blk.* Hierarchical Scheduler Block Internal Diagram The hierarchical scheduler is optimized for a large number of packet queues. When only a small number of queues are needed, message passing queues should be used instead of this block. See Section 26.2.5 "Worst Case Scenarios for Performance" for a more detailed discussion. Scheduling Hierarchy ~~~~~~~~~~~~~~~~~~~~ The scheduling hierarchy is shown in :numref:`figure_sched_hier_per_port`. The first level of the hierarchy is the Ethernet TX port 1/10/40 GbE, with subsequent hierarchy levels defined as subport, pipe, traffic class and queue. Typically, each subport represents a predefined group of users, while each pipe represents an individual user/subscriber. Each traffic class is the representation of a different traffic type with specific loss rate, delay and jitter requirements, such as voice, video or data transfers. Each queue hosts packets from one or multiple connections of the same type belonging to the same user. .. _figure_sched_hier_per_port: .. figure:: img/sched_hier_per_port.* Scheduling Hierarchy per Port The functionality of each hierarchical level is detailed in the following table. .. _table_qos_3: .. table:: Port Scheduling Hierarchy +---+--------------------+----------------------------+---------------------------------------------------------------+ | # | Level | Siblings per Parent | Functional Description | | | | | | +===+====================+============================+===============================================================+ | 1 | Port | - | #. Output Ethernet port 1/10/40 GbE. | | | | | | | | | | #. Multiple ports are scheduled in round robin order with | | | | | all ports having equal priority. | | | | | | +---+--------------------+----------------------------+---------------------------------------------------------------+ | 2 | Subport | Configurable (default: 8) | #. Traffic shaping using token bucket algorithm (one token | | | | | bucket per subport). | | | | | | | | | | #. Upper limit enforced per Traffic Class (TC) at the | | | | | subport level. | | | | | | | | | | #. Lower priority TCs able to reuse subport bandwidth | | | | | currently unused by higher priority TCs. | | | | | | +---+--------------------+----------------------------+---------------------------------------------------------------+ | 3 | Pipe | Configurable (default: 4K) | #. Traffic shaping using the token bucket algorithm (one | | | | | token bucket per pipe. | | | | | | +---+--------------------+----------------------------+---------------------------------------------------------------+ | 4 | Traffic Class (TC) | 4 | #. TCs of the same pipe handled in strict priority order. | | | | | | | | | | #. Upper limit enforced per TC at the pipe level. | | | | | | | | | | #. Lower priority TCs able to reuse pipe bandwidth currently | | | | | unused by higher priority TCs. | | | | | | | | | | #. When subport TC is oversubscribed (configuration time | | | | | event), pipe TC upper limit is capped to a dynamically | | | | | adjusted value that is shared by all the subport pipes. | | | | | | +---+--------------------+----------------------------+---------------------------------------------------------------+ | 5 | Queue | 4 | #. Queues of the same TC are serviced using Weighted Round | | | | | Robin (WRR) according to predefined weights. | | | | | | +---+--------------------+----------------------------+---------------------------------------------------------------+ Application Programming Interface (API) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Port Scheduler Configuration API ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The rte_sched.h file contains configuration functions for port, subport and pipe. Port Scheduler Enqueue API ^^^^^^^^^^^^^^^^^^^^^^^^^^ The port scheduler enqueue API is very similar to the API of the DPDK PMD TX function. .. code-block:: c int rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts); Port Scheduler Dequeue API ^^^^^^^^^^^^^^^^^^^^^^^^^^ The port scheduler dequeue API is very similar to the API of the DPDK PMD RX function. .. code-block:: c int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts); Usage Example ^^^^^^^^^^^^^ .. code-block:: c /* File "application.c" */ #define N_PKTS_RX 64 #define N_PKTS_TX 48 #define NIC_RX_PORT 0 #define NIC_RX_QUEUE 0 #define NIC_TX_PORT 1 #define NIC_TX_QUEUE 0 struct rte_sched_port *port = NULL; struct rte_mbuf *pkts_rx[N_PKTS_RX], *pkts_tx[N_PKTS_TX]; uint32_t n_pkts_rx, n_pkts_tx; /* Initialization */ /* Runtime */ while (1) { /* Read packets from NIC RX queue */ n_pkts_rx = rte_eth_rx_burst(NIC_RX_PORT, NIC_RX_QUEUE, pkts_rx, N_PKTS_RX); /* Hierarchical scheduler enqueue */ rte_sched_port_enqueue(port, pkts_rx, n_pkts_rx); /* Hierarchical scheduler dequeue */ n_pkts_tx = rte_sched_port_dequeue(port, pkts_tx, N_PKTS_TX); /* Write packets to NIC TX queue */ rte_eth_tx_burst(NIC_TX_PORT, NIC_TX_QUEUE, pkts_tx, n_pkts_tx); } Implementation ~~~~~~~~~~~~~~ Internal Data Structures per Port ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A schematic of the internal data structures in shown in with details in. .. _figure_data_struct_per_port: .. figure:: img/data_struct_per_port.* Internal Data Structures per Port .. _table_qos_4: .. table:: Scheduler Internal Data Structures per Port +---+----------------------+-------------------------+---------------------+------------------------------+---------------------------------------------------+ | # | Data structure | Size (bytes) | # per port | Access type | Description | | | | | | | | | | | | +-------------+----------------+---------------------------------------------------+ | | | | | Enq | Deq | | | | | | | | | | +===+======================+=========================+=====================+=============+================+===================================================+ | 1 | Subport table entry | 64 | # subports per port | - | Rd, Wr | Persistent subport data (credits, etc). | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ | 2 | Pipe table entry | 64 | # pipes per port | - | Rd, Wr | Persistent data for pipe, its TCs and its queues | | | | | | | | (credits, etc) that is updated during run-time. | | | | | | | | | | | | | | | | The pipe configuration parameters do not change | | | | | | | | during run-time. The same pipe configuration | | | | | | | | parameters are shared by multiple pipes, | | | | | | | | therefore they are not part of pipe table entry. | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ | 3 | Queue table entry | 4 | #queues per port | Rd, Wr | Rd, Wr | Persistent queue data (read and write pointers). | | | | | | | | The queue size is the same per TC for all queues, | | | | | | | | allowing the queue base address to be computed | | | | | | | | using a fast formula, so these two parameters are | | | | | | | | not part of queue table entry. | | | | | | | | | | | | | | | | The queue table entries for any given pipe are | | | | | | | | stored in the same cache line. | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ | 4 | Queue storage area | Config (default: 64 x8) | # queues per port | Wr | Rd | Array of elements per queue; each element is 8 | | | | | | | | byte in size (mbuf pointer). | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ | 5 | Active queues bitmap | 1 bit per queue | 1 | Wr (Set) | Rd, Wr (Clear) | The bitmap maintains one status bit per queue: | | | | | | | | queue not active (queue is empty) or queue active | | | | | | | | (queue is not empty). | | | | | | | | | | | | | | | | Queue bit is set by the scheduler enqueue and | | | | | | | | cleared by the scheduler dequeue when queue | | | | | | | | becomes empty. | | | | | | | | | | | | | | | | Bitmap scan operation returns the next non-empty | | | | | | | | pipe and its status (16-bit mask of active queue | | | | | | | | in the pipe). | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ | 6 | Grinder | ~128 | Config (default: 8) | - | Rd, Wr | Short list of active pipes currently under | | | | | | | | processing. The grinder contains temporary data | | | | | | | | during pipe processing. | | | | | | | | | | | | | | | | Once the current pipe exhausts packets or | | | | | | | | credits, it is replaced with another active pipe | | | | | | | | from the bitmap. | | | | | | | | | +---+----------------------+-------------------------+---------------------+-------------+----------------+---------------------------------------------------+ Multicore Scaling Strategy ^^^^^^^^^^^^^^^^^^^^^^^^^^ The multicore scaling strategy is: #. Running different physical ports on different threads. The enqueue and dequeue of the same port are run by the same thread. #. Splitting the same physical port to different threads by running different sets of subports of the same physical port (virtual ports) on different threads. Similarly, a subport can be split into multiple subports that are each run by a different thread. The enqueue and dequeue of the same port are run by the same thread. This is only required if, for performance reasons, it is not possible to handle a full port with a single core. Enqueue and Dequeue for the Same Output Port """""""""""""""""""""""""""""""""""""""""""" Running enqueue and dequeue operations for the same output port from different cores is likely to cause significant impact on scheduler's performance and it is therefore not recommended. The port enqueue and dequeue operations share access to the following data structures: #. Packet descriptors #. Queue table #. Queue storage area #. Bitmap of active queues The expected drop in performance is due to: #. Need to make the queue and bitmap operations thread safe, which requires either using locking primitives for access serialization (for example, spinlocks/ semaphores) or using atomic primitives for lockless access (for example, Test and Set, Compare And Swap, an so on). The impact is much higher in the former case. #. Ping-pong of cache lines storing the shared data structures between the cache hierarchies of the two cores (done transparently by the MESI protocol cache coherency CPU hardware). Therefore, the scheduler enqueue and dequeue operations have to be run from the same thread, which allows the queues and the bitmap operations to be non-thread safe and keeps the scheduler data structures internal to the same core. Performance Scaling """"""""""""""""""" Scaling up the number of NIC ports simply requires a proportional increase in the number of CPU cores to be used for traffic scheduling. Enqueue Pipeline ^^^^^^^^^^^^^^^^ The sequence of steps per packet: #. *Access* the mbuf to read the data fields required to identify the destination queue for the packet. These fields are: port, subport, traffic class and queue within traffic class, and are typically set by the classification stage. #. *Access* the queue structure to identify the write location in the queue array. If the queue is full, then the packet is discarded. #. *Access* the queue array location to store the packet (i.e. write the mbuf pointer). It should be noted the strong data dependency between these steps, as steps 2 and 3 cannot start before the result from steps 1 and 2 becomes available, which prevents the processor out of order execution engine to provide any significant performance optimizations. Given the high rate of input packets and the large amount of queues, it is expected that the data structures accessed to enqueue the current packet are not present in the L1 or L2 data cache of the current core, thus the above 3 memory accesses would result (on average) in L1 and L2 data cache misses. A number of 3 L1/L2 cache misses per packet is not acceptable for performance reasons. The workaround is to prefetch the required data structures in advance. The prefetch operation has an execution latency during which the processor should not attempt to access the data structure currently under prefetch, so the processor should execute other work. The only other work available is to execute different stages of the enqueue sequence of operations on other input packets, thus resulting in a pipelined implementation for the enqueue operation. :numref:`figure_prefetch_pipeline` illustrates a pipelined implementation for the enqueue operation with 4 pipeline stages and each stage executing 2 different input packets. No input packet can be part of more than one pipeline stage at a given time. .. _figure_prefetch_pipeline: .. figure:: img/prefetch_pipeline.* Prefetch Pipeline for the Hierarchical Scheduler Enqueue Operation The congestion management scheme implemented by the enqueue pipeline described above is very basic: packets are enqueued until a specific queue becomes full, then all the packets destined to the same queue are dropped until packets are consumed (by the dequeue operation). This can be improved by enabling RED/WRED as part of the enqueue pipeline which looks at the queue occupancy and packet priority in order to yield the enqueue/drop decision for a specific packet (as opposed to enqueuing all packets / dropping all packets indiscriminately). Dequeue State Machine ^^^^^^^^^^^^^^^^^^^^^ The sequence of steps to schedule the next packet from the current pipe is: #. Identify the next active pipe using the bitmap scan operation, *prefetch* pipe. #. *Read* pipe data structure. Update the credits for the current pipe and its subport. Identify the first active traffic class within the current pipe, select the next queue using WRR, *prefetch* queue pointers for all the 16 queues of the current pipe. #. *Read* next element from the current WRR queue and *prefetch* its packet descriptor. #. *Read* the packet length from the packet descriptor (mbuf structure). Based on the packet length and the available credits (of current pipe, pipe traffic class, subport and subport traffic class), take the go/no go scheduling decision for the current packet. To avoid the cache misses, the above data structures (pipe, queue, queue array, mbufs) are prefetched in advance of being accessed. The strategy of hiding the latency of the prefetch operations is to switch from the current pipe (in grinder A) to another pipe (in grinder B) immediately after a prefetch is issued for the current pipe. This gives enough time to the prefetch operation to complete before the execution switches back to this pipe (in grinder A). The dequeue pipe state machine exploits the data presence into the processor cache, therefore it tries to send as many packets from the same pipe TC and pipe as possible (up to the available packets and credits) before moving to the next active TC from the same pipe (if any) or to another active pipe. .. _figure_pipe_prefetch_sm: .. figure:: img/pipe_prefetch_sm.* Pipe Prefetch State Machine for the Hierarchical Scheduler Dequeue Operation Timing and Synchronization ^^^^^^^^^^^^^^^^^^^^^^^^^^ The output port is modeled as a conveyor belt of byte slots that need to be filled by the scheduler with data for transmission. For 10 GbE, there are 1.25 billion byte slots that need to be filled by the port scheduler every second. If the scheduler is not fast enough to fill the slots, provided that enough packets and credits exist, then some slots will be left unused and bandwidth will be wasted. In principle, the hierarchical scheduler dequeue operation should be triggered by NIC TX. Usually, once the occupancy of the NIC TX input queue drops below a predefined threshold, the port scheduler is woken up (interrupt based or polling based, by continuously monitoring the queue occupancy) to push more packets into the queue. Internal Time Reference """"""""""""""""""""""" The scheduler needs to keep track of time advancement for the credit logic, which requires credit updates based on time (for example, subport and pipe traffic shaping, traffic class upper limit enforcement, and so on). Every time the scheduler decides to send a packet out to the NIC TX for transmission, the scheduler will increment its internal time reference accordingly. Therefore, it is convenient to keep the internal time reference in units of bytes, where a byte signifies the time duration required by the physical interface to send out a byte on the transmission medium. This way, as a packet is scheduled for transmission, the time is incremented with (n + h), where n is the packet length in bytes and h is the number of framing overhead bytes per packet. Internal Time Reference Re-synchronization """""""""""""""""""""""""""""""""""""""""" The scheduler needs to align its internal time reference to the pace of the port conveyor belt. The reason is to make sure that the scheduler does not feed the NIC TX with more bytes than the line rate of the physical medium in order to prevent packet drop (by the scheduler, due to the NIC TX input queue being full, or later on, internally by the NIC TX). The scheduler reads the current time on every dequeue invocation. The CPU time stamp can be obtained by reading either the Time Stamp Counter (TSC) register or the High Precision Event Timer (HPET) register. The current CPU time stamp is converted from number of CPU clocks to number of bytes: *time_bytes = time_cycles / cycles_per_byte, where cycles_per_byte* is the amount of CPU cycles that is equivalent to the transmission time for one byte on the wire (e.g. for a CPU frequency of 2 GHz and a 10GbE port,*cycles_per_byte = 1.6*). The scheduler maintains an internal time reference of the NIC time. Whenever a packet is scheduled, the NIC time is incremented with the packet length (including framing overhead). On every dequeue invocation, the scheduler checks its internal reference of the NIC time against the current time: #. If NIC time is in the future (NIC time >= current time), no adjustment of NIC time is needed. This means that scheduler is able to schedule NIC packets before the NIC actually needs those packets, so the NIC TX is well supplied with packets; #. If NIC time is in the past (NIC time < current time), then NIC time should be adjusted by setting it to the current time. This means that the scheduler is not able to keep up with the speed of the NIC byte conveyor belt, so NIC bandwidth is wasted due to poor packet supply to the NIC TX. Scheduler Accuracy and Granularity """""""""""""""""""""""""""""""""" The scheduler round trip delay (SRTD) is the time (number of CPU cycles) between two consecutive examinations of the same pipe by the scheduler. To keep up with the output port (that is, avoid bandwidth loss), the scheduler should be able to schedule n packets faster than the same n packets are transmitted by NIC TX. The scheduler needs to keep up with the rate of each individual pipe, as configured for the pipe token bucket, assuming that no port oversubscription is taking place. This means that the size of the pipe token bucket should be set high enough to prevent it from overflowing due to big SRTD, as this would result in credit loss (and therefore bandwidth loss) for the pipe. Credit Logic ^^^^^^^^^^^^ Scheduling Decision """"""""""""""""""" The scheduling decision to send next packet from (subport S, pipe P, traffic class TC, queue Q) is favorable (packet is sent) when all the conditions below are met: * Pipe P of subport S is currently selected by one of the port grinders; * Traffic class TC is the highest priority active traffic class of pipe P; * Queue Q is the next queue selected by WRR within traffic class TC of pipe P; * Subport S has enough credits to send the packet; * Subport S has enough credits for traffic class TC to send the packet; * Pipe P has enough credits to send the packet; * Pipe P has enough credits for traffic class TC to send the packet. If all the above conditions are met, then the packet is selected for transmission and the necessary credits are subtracted from subport S, subport S traffic class TC, pipe P, pipe P traffic class TC. Framing Overhead """""""""""""""" As the greatest common divisor for all packet lengths is one byte, the unit of credit is selected as one byte. The number of credits required for the transmission of a packet of n bytes is equal to (n+h), where h is equal to the number of framing overhead bytes per packet. .. _table_qos_5: .. table:: Ethernet Frame Overhead Fields +---+--------------------------------+----------------+---------------------------------------------------------------------------+ | # | Packet field | Length (bytes) | Comments | | | | | | +===+================================+================+===========================================================================+ | 1 | Preamble | 7 | | | | | | | +---+--------------------------------+----------------+---------------------------------------------------------------------------+ | 2 | Start of Frame Delimiter (SFD) | 1 | | | | | | | +---+--------------------------------+----------------+---------------------------------------------------------------------------+ | 3 | Frame Check Sequence (FCS) | 4 | Considered overhead only if not included in the mbuf packet length field. | | | | | | +---+--------------------------------+----------------+---------------------------------------------------------------------------+ | 4 | Inter Frame Gap (IFG) | 12 | | | | | | | +---+--------------------------------+----------------+---------------------------------------------------------------------------+ | 5 | Total | 24 | | | | | | | +---+--------------------------------+----------------+---------------------------------------------------------------------------+ Traffic Shaping """"""""""""""" The traffic shaping for subport and pipe is implemented using a token bucket per subport/per pipe. Each token bucket is implemented using one saturated counter that keeps track of the number of available credits. The token bucket generic parameters and operations are presented in :numref:`table_qos_6` and :numref:`table_qos_7`. .. _table_qos_6: .. table:: Token Bucket Generic Operations +---+------------------------+--------------------+---------------------------------------------------------+ | # | Token Bucket Parameter | Unit | Description | | | | | | +===+========================+====================+=========================================================+ | 1 | bucket_rate | Credits per second | Rate of adding credits to the bucket. | | | | | | +---+------------------------+--------------------+---------------------------------------------------------+ | 2 | bucket_size | Credits | Max number of credits that can be stored in the bucket. | | | | | | +---+------------------------+--------------------+---------------------------------------------------------+ .. _table_qos_7: .. table:: Token Bucket Generic Parameters +---+------------------------+------------------------------------------------------------------------------+ | # | Token Bucket Operation | Description | | | | | +===+========================+==============================================================================+ | 1 | Initialization | Bucket set to a predefined value, e.g. zero or half of the bucket size. | | | | | +---+------------------------+------------------------------------------------------------------------------+ | 2 | Credit update | Credits are added to the bucket on top of existing ones, either periodically | | | | or on demand, based on the bucket_rate. Credits cannot exceed the upper | | | | limit defined by the bucket_size, so any credits to be added to the bucket | | | | while the bucket is full are dropped. | | | | | +---+------------------------+------------------------------------------------------------------------------+ | 3 | Credit consumption | As result of packet scheduling, the necessary number of credits is removed | | | | from the bucket. The packet can only be sent if enough credits are in the | | | | bucket to send the full packet (packet bytes and framing overhead for the | | | | packet). | | | | | +---+------------------------+------------------------------------------------------------------------------+ To implement the token bucket generic operations described above, the current design uses the persistent data structure presented in :numref:`table_qos_8`, while the implementation of the token bucket operations is described in :numref:`table_qos_9`. .. _table_qos_8: .. table:: Token Bucket Persistent Data Structure +---+------------------------+-------+----------------------------------------------------------------------+ | # | Token bucket field | Unit | Description | | | | | | +===+========================+=======+======================================================================+ | 1 | tb_time | Bytes | Time of the last credit update. Measured in bytes instead of seconds | | | | | or CPU cycles for ease of credit consumption operation | | | | | (as the current time is also maintained in bytes). | | | | | | | | | | See Section 26.2.4.5.1 "Internal Time Reference" for an | | | | | explanation of why the time is maintained in byte units. | | | | | | +---+------------------------+-------+----------------------------------------------------------------------+ | 2 | tb_period | Bytes | Time period that should elapse since the last credit update in order | | | | | for the bucket to be awarded tb_credits_per_period worth or credits. | | | | | | +---+------------------------+-------+----------------------------------------------------------------------+ | 3 | tb_credits_per_period | Bytes | Credit allowance per tb_period. | | | | | | +---+------------------------+-------+----------------------------------------------------------------------+ | 4 | tb_size | Bytes | Bucket size, i.e. upper limit for the tb_credits. | | | | | | +---+------------------------+-------+----------------------------------------------------------------------+ | 5 | tb_credits | Bytes | Number of credits currently in the bucket. | | | | | | +---+------------------------+-------+----------------------------------------------------------------------+ The bucket rate (in bytes per second) can be computed with the following formula: *bucket_rate = (tb_credits_per_period / tb_period) * r* where, r = port line rate (in bytes per second). .. _table_qos_9: .. table:: Token Bucket Operations +---+-------------------------+-----------------------------------------------------------------------------+ | # | Token bucket operation | Description | | | | | +===+=========================+=============================================================================+ | 1 | Initialization | *tb_credits = 0; or tb_credits = tb_size / 2;* | | | | | +---+-------------------------+-----------------------------------------------------------------------------+ | 2 | Credit update | Credit update options: | | | | | | | | * Every time a packet is sent for a port, update the credits of all the | | | | the subports and pipes of that port. Not feasible. | | | | | | | | * Every time a packet is sent, update the credits for the pipe and | | | | subport. Very accurate, but not needed (a lot of calculations). | | | | | | | | * Every time a pipe is selected (that is, picked by one | | | | of the grinders), update the credits for the pipe and its subport. | | | | | | | | The current implementation is using option 3. According to Section | | | | 26.2.4.4 "Dequeue State Machine", the pipe and subport credits are | | | | updated every time a pipe is selected by the dequeue process before the | | | | pipe and subport credits are actually used. | | | | | | | | The implementation uses a tradeoff between accuracy and speed by updating | | | | the bucket credits only when at least a full *tb_period* has elapsed since | | | | the last update. | | | | | | | | * Full accuracy can be achieved by selecting the value for *tb_period* | | | | for which *tb_credits_per_period = 1*. | | | | | | | | * When full accuracy is not required, better performance is achieved by | | | | setting *tb_credits* to a larger value. | | | | | | | | Update operations: | | | | | | | | * n_periods = (time - tb_time) / tb_period; | | | | | | | | * tb_credits += n_periods * tb_credits_per_period; | | | | | | | | * tb_credits = min(tb_credits, tb_size); | | | | | | | | * tb_time += n_periods * tb_period; | | | | | +---+-------------------------+-----------------------------------------------------------------------------+ | 3 | Credit consumption | As result of packet scheduling, the necessary number of credits is removed | | | (on packet scheduling) | from the bucket. The packet can only be sent if enough credits are in the | | | | bucket to send the full packet (packet bytes and framing overhead for the | | | | packet). | | | | | | | | Scheduling operations: | | | | | | | | pkt_credits = pkt_len + frame_overhead; | | | | if (tb_credits >= pkt_credits){tb_credits -= pkt_credits;} | | | | | +---+-------------------------+-----------------------------------------------------------------------------+ Traffic Classes """"""""""""""" Implementation of Strict Priority Scheduling '''''''''''''''''''''''''''''''''''''''''''' Strict priority scheduling of traffic classes within the same pipe is implemented by the pipe dequeue state machine, which selects the queues in ascending order. Therefore, queues 0..3 (associated with TC 0, highest priority TC) are handled before queues 4..7 (TC 1, lower priority than TC 0), which are handled before queues 8..11 (TC 2), which are handled before queues 12..15 (TC 3, lowest priority TC). Upper Limit Enforcement ''''''''''''''''''''''' The traffic classes at the pipe and subport levels are not traffic shaped, so there is no token bucket maintained in this context. The upper limit for the traffic classes at the subport and pipe levels is enforced by periodically refilling the subport / pipe traffic class credit counter, out of which credits are consumed every time a packet is scheduled for that subport / pipe, as described in :numref:`table_qos_10` and :numref:`table_qos_11`. .. _table_qos_10: .. table:: Subport/Pipe Traffic Class Upper Limit Enforcement Persistent Data Structure +---+-----------------------+-------+-----------------------------------------------------------------------+ | # | Subport or pipe field | Unit | Description | | | | | | +===+=======================+=======+=======================================================================+ | 1 | tc_time | Bytes | Time of the next update (upper limit refill) for the 4 TCs of the | | | | | current subport / pipe. | | | | | | | | | | See Section 26.2.4.5.1, "Internal Time Reference" for the | | | | | explanation of why the time is maintained in byte units. | | | | | | +---+-----------------------+-------+-----------------------------------------------------------------------+ | 2 | tc_period | Bytes | Time between two consecutive updates for the 4 TCs of the current | | | | | subport / pipe. This is expected to be many times bigger than the | | | | | typical value of the token bucket tb_period. | | | | | | +---+-----------------------+-------+-----------------------------------------------------------------------+ | 3 | tc_credits_per_period | Bytes | Upper limit for the number of credits allowed to be consumed by the | | | | | current TC during each enforcement period tc_period. | | | | | | +---+-----------------------+-------+-----------------------------------------------------------------------+ | 4 | tc_credits | Bytes | Current upper limit for the number of credits that can be consumed by | | | | | the current traffic class for the remainder of the current | | | | | enforcement period. | | | | | | +---+-----------------------+-------+-----------------------------------------------------------------------+ .. _table_qos_11: .. table:: Subport/Pipe Traffic Class Upper Limit Enforcement Operations +---+--------------------------+----------------------------------------------------------------------------+ | # | Traffic Class Operation | Description | | | | | +===+==========================+============================================================================+ | 1 | Initialization | tc_credits = tc_credits_per_period; | | | | | | | | tc_time = tc_period; | | | | | +---+--------------------------+----------------------------------------------------------------------------+ | 2 | Credit update | Update operations: | | | | | | | | if (time >= tc_time) { | | | | | | | | tc_credits = tc_credits_per_period; | | | | | | | | tc_time = time + tc_period; | | | | | | | | } | | | | | +---+--------------------------+----------------------------------------------------------------------------+ | 3 | Credit consumption | As result of packet scheduling, the TC limit is decreased with the | | | (on packet scheduling) | necessary number of credits. The packet can only be sent if enough credits | | | | are currently available in the TC limit to send the full packet | | | | (packet bytes and framing overhead for the packet). | | | | | | | | Scheduling operations: | | | | | | | | pkt_credits = pk_len + frame_overhead; | | | | | | | | if (tc_credits >= pkt_credits) {tc_credits -= pkt_credits;} | | | | | +---+--------------------------+----------------------------------------------------------------------------+ Weighted Round Robin (WRR) """""""""""""""""""""""""" The evolution of the WRR design solution from simple to complex is shown in :numref:`table_qos_12`. .. _table_qos_12: .. table:: Weighted Round Robin (WRR) +---+------------+-----------------+-------------+----------------------------------------------------------+ | # | All Queues | Equal Weights | All Packets | Strategy | | | Active? | for All Queues? | Equal? | | +===+============+=================+=============+==========================================================+ | 1 | Yes | Yes | Yes | **Byte level round robin** | | | | | | | | | | | | *Next queue* queue #i, i = *(i + 1) % n* | | | | | | | +---+------------+-----------------+-------------+----------------------------------------------------------+ | 2 | Yes | Yes | No | **Packet level round robin** | | | | | | | | | | | | Consuming one byte from queue #i requires consuming | | | | | | exactly one token for queue #i. | | | | | | | | | | | | T(i) = Accumulated number of tokens previously consumed | | | | | | from queue #i. Every time a packet is consumed from | | | | | | queue #i, T(i) is updated as: T(i) += *pkt_len*. | | | | | | | | | | | | *Next queue* : queue with the smallest T. | | | | | | | | | | | | | +---+------------+-----------------+-------------+----------------------------------------------------------+ | 3 | Yes | No | No | **Packet level weighted round robin** | | | | | | | | | | | | This case can be reduced to the previous case by | | | | | | introducing a cost per byte that is different for each | | | | | | queue. Queues with lower weights have a higher cost per | | | | | | byte. This way, it is still meaningful to compare the | | | | | | consumption amongst different queues in order to select | | | | | | the next queue. | | | | | | | | | | | | w(i) = Weight of queue #i | | | | | | | | | | | | t(i) = Tokens per byte for queue #i, defined as the | | | | | | inverse weight of queue #i. | | | | | | For example, if w[0..3] = [1:2:4:8], | | | | | | then t[0..3] = [8:4:2:1]; if w[0..3] = [1:4:15:20], | | | | | | then t[0..3] = [60:15:4:3]. | | | | | | Consuming one byte from queue #i requires consuming t(i) | | | | | | tokens for queue #i. | | | | | | | | | | | | T(i) = Accumulated number of tokens previously consumed | | | | | | from queue #i. Every time a packet is consumed from | | | | | | queue #i, T(i) is updated as: *T(i) += pkt_len * t(i)*. | | | | | | *Next queue* : queue with the smallest T. | | | | | | | +---+------------+-----------------+-------------+----------------------------------------------------------+ | 4 | No | No | No | **Packet level weighted round robin with variable queue | | | | | | status** | | | | | | | | | | | | Reduce this case to the previous case by setting the | | | | | | consumption of inactive queues to a high number, so that | | | | | | the inactive queues will never be selected by the | | | | | | smallest T logic. | | | | | | | | | | | | To prevent T from overflowing as result of successive | | | | | | accumulations, T(i) is truncated after each packet | | | | | | consumption for all queues. | | | | | | For example, T[0..3] = [1000, 1100, 1200, 1300] | | | | | | is truncated to T[0..3] = [0, 100, 200, 300] | | | | | | by subtracting the min T from T(i), i = 0..n. | | | | | | | | | | | | This requires having at least one active queue in the | | | | | | set of input queues, which is guaranteed by the dequeue | | | | | | state machine never selecting an inactive traffic class. | | | | | | | | | | | | *mask(i) = Saturation mask for queue #i, defined as:* | | | | | | | | | | | | mask(i) = (queue #i is active)? 0 : 0xFFFFFFFF; | | | | | | | | | | | | w(i) = Weight of queue #i | | | | | | | | | | | | t(i) = Tokens per byte for queue #i, defined as the | | | | | | inverse weight of queue #i. | | | | | | | | | | | | T(i) = Accumulated numbers of tokens previously consumed | | | | | | from queue #i. | | | | | | | | | | | | *Next queue* : queue with smallest T. | | | | | | | | | | | | Before packet consumption from queue #i: | | | | | | | | | | | | *T(i) |= mask(i)* | | | | | | | | | | | | After packet consumption from queue #i: | | | | | | | | | | | | T(j) -= T(i), j != i | | | | | | | | | | | | T(i) = pkt_len * t(i) | | | | | | | | | | | | Note: T(j) uses the T(i) value before T(i) is updated. | | | | | | | +---+------------+-----------------+-------------+----------------------------------------------------------+ Subport Traffic Class Oversubscription """""""""""""""""""""""""""""""""""""" Problem Statement ''''''''''''''''' Oversubscription for subport traffic class X is a configuration-time event that occurs when more bandwidth is allocated for traffic class X at the level of subport member pipes than allocated for the same traffic class at the parent subport level. The existence of the oversubscription for a specific subport and traffic class is solely the result of pipe and subport-level configuration as opposed to being created due to dynamic evolution of the traffic load at run-time (as congestion is). When the overall demand for traffic class X for the current subport is low, the existence of the oversubscription condition does not represent a problem, as demand for traffic class X is completely satisfied for all member pipes. However, this can no longer be achieved when the aggregated demand for traffic class X for all subport member pipes exceeds the limit configured at the subport level. Solution Space '''''''''''''' summarizes some of the possible approaches for handling this problem, with the third approach selected for implementation. .. _table_qos_13: .. table:: Subport Traffic Class Oversubscription +-----+---------------------------+-------------------------------------------------------------------------+ | No. | Approach | Description | | | | | +=====+===========================+=========================================================================+ | 1 | Don't care | First come, first served. | | | | | | | | This approach is not fair amongst subport member pipes, as pipes that | | | | are served first will use up as much bandwidth for TC X as they need, | | | | while pipes that are served later will receive poor service due to | | | | bandwidth for TC X at the subport level being scarce. | | | | | +-----+---------------------------+-------------------------------------------------------------------------+ | 2 | Scale down all pipes | All pipes within the subport have their bandwidth limit for TC X scaled | | | | down by the same factor. | | | | | | | | This approach is not fair among subport member pipes, as the low end | | | | pipes (that is, pipes configured with low bandwidth) can potentially | | | | experience severe service degradation that might render their service | | | | unusable (if available bandwidth for these pipes drops below the | | | | minimum requirements for a workable service), while the service | | | | degradation for high end pipes might not be noticeable at all. | | | | | +-----+---------------------------+-------------------------------------------------------------------------+ | 3 | Cap the high demand pipes | Each subport member pipe receives an equal share of the bandwidth | | | | available at run-time for TC X at the subport level. Any bandwidth left | | | | unused by the low-demand pipes is redistributed in equal portions to | | | | the high-demand pipes. This way, the high-demand pipes are truncated | | | | while the low-demand pipes are not impacted. | | | | | +-----+---------------------------+-------------------------------------------------------------------------+ Typically, the subport TC oversubscription feature is enabled only for the lowest priority traffic class (TC 3), which is typically used for best effort traffic, with the management plane preventing this condition from occurring for the other (higher priority) traffic classes. To ease implementation, it is also assumed that the upper limit for subport TC 3 is set to 100% of the subport rate, and that the upper limit for pipe TC 3 is set to 100% of pipe rate for all subport member pipes. Implementation Overview ''''''''''''''''''''''' The algorithm computes a watermark, which is periodically updated based on the current demand experienced by the subport member pipes, whose purpose is to limit the amount of traffic that each pipe is allowed to send for TC 3. The watermark is computed at the subport level at the beginning of each traffic class upper limit enforcement period and the same value is used by all the subport member pipes throughout the current enforcement period. illustrates how the watermark computed as subport level at the beginning of each period is propagated to all subport member pipes. At the beginning of the current enforcement period (which coincides with the end of the previous enforcement period), the value of the watermark is adjusted based on the amount of bandwidth allocated to TC 3 at the beginning of the previous period that was not left unused by the subport member pipes at the end of the previous period. If there was subport TC 3 bandwidth left unused, the value of the watermark for the current period is increased to encourage the subport member pipes to consume more bandwidth. Otherwise, the value of the watermark is decreased to enforce equality of bandwidth consumption among subport member pipes for TC 3. The increase or decrease in the watermark value is done in small increments, so several enforcement periods might be required to reach the equilibrium state. This state can change at any moment due to variations in the demand experienced by the subport member pipes for TC 3, for example, as a result of demand increase (when the watermark needs to be lowered) or demand decrease (when the watermark needs to be increased). When demand is low, the watermark is set high to prevent it from impeding the subport member pipes from consuming more bandwidth. The highest value for the watermark is picked as the highest rate configured for a subport member pipe. :numref:`table_qos_14` and :numref:`table_qos_15` illustrates the watermark operation. .. _table_qos_14: .. table:: Watermark Propagation from Subport Level to Member Pipes at the Beginning of Each Traffic Class Upper Limit Enforcement Period +-----+---------------------------------+----------------------------------------------------+ | No. | Subport Traffic Class Operation | Description | | | | | +=====+=================================+====================================================+ | 1 | Initialization | **Subport level**: subport_period_id= 0 | | | | | | | | **Pipe level**: pipe_period_id = 0 | | | | | +-----+---------------------------------+----------------------------------------------------+ | 2 | Credit update | **Subport Level**: | | | | | | | | if (time>=subport_tc_time) | | | | | | | | { | | | | subport_wm = water_mark_update(); | | | | | | | | subport_tc_time = time + subport_tc_period; | | | | | | | | subport_period_id++; | | | | | | | | } | | | | | | | | **Pipelevel:** | | | | | | | | if(pipe_period_id != subport_period_id) | | | | | | | | { | | | | | | | | pipe_ov_credits = subport_wm \* pipe_weight; | | | | | | | | pipe_period_id = subport_period_id; | | | | | | | | } | | | | | +-----+---------------------------------+----------------------------------------------------+ | 3 | Credit consumption | **Pipe level:** | | | (on packet scheduling) | | | | | pkt_credits = pk_len + frame_overhead; | | | | | | | | if(pipe_ov_credits >= pkt_credits{ | | | | | | | | pipe_ov_credits -= pkt_credits; | | | | | | | | } | | | | | +-----+---------------------------------+----------------------------------------------------+ .. _table_qos_15: .. table:: Watermark Calculation +-----+------------------+----------------------------------------------------------------------------------+ | No. | Subport Traffic | Description | | | Class Operation | | +=====+==================+==================================================================================+ | 1 | Initialization | **Subport level:** | | | | | | | | wm = WM_MAX | | | | | +-----+------------------+----------------------------------------------------------------------------------+ | 2 | Credit update | **Subport level (water_mark_update):** | | | | | | | | tc0_cons = subport_tc0_credits_per_period - subport_tc0_credits; | | | | | | | | tc1_cons = subport_tc1_credits_per_period - subport_tc1_credits; | | | | | | | | tc2_cons = subport_tc2_credits_per_period - subport_tc2_credits; | | | | | | | | tc3_cons = subport_tc3_credits_per_period - subport_tc3_credits; | | | | | | | | tc3_cons_max = subport_tc3_credits_per_period - (tc0_cons + tc1_cons + | | | | tc2_cons); | | | | | | | | if(tc3_consumption > (tc3_consumption_max - MTU)){ | | | | | | | | wm -= wm >> 7; | | | | | | | | if(wm < WM_MIN) wm = WM_MIN; | | | | | | | | } else { | | | | | | | | wm += (wm >> 7) + 1; | | | | | | | | if(wm > WM_MAX) wm = WM_MAX; | | | | | | | | } | | | | | +-----+------------------+----------------------------------------------------------------------------------+ Worst Case Scenarios for Performance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Lots of Active Queues with Not Enough Credits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The more queues the scheduler has to examine for packets and credits in order to select one packet, the lower the performance of the scheduler is. The scheduler maintains the bitmap of active queues, which skips the non-active queues, but in order to detect whether a specific pipe has enough credits, the pipe has to be drilled down using the pipe dequeue state machine, which consumes cycles regardless of the scheduling result (no packets are produced or at least one packet is produced). This scenario stresses the importance of the policer for the scheduler performance: if the pipe does not have enough credits, its packets should be dropped as soon as possible (before they reach the hierarchical scheduler), thus rendering the pipe queues as not active, which allows the dequeue side to skip that pipe with no cycles being spent on investigating the pipe credits that would result in a "not enough credits" status. Single Queue with 100% Line Rate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The port scheduler performance is optimized for a large number of queues. If the number of queues is small, then the performance of the port scheduler for the same level of active traffic is expected to be worse than the performance of a small set of message passing queues. .. _Dropper: Dropper ------- The purpose of the DPDK dropper is to drop packets arriving at a packet scheduler to avoid congestion. The dropper supports the Random Early Detection (RED), Weighted Random Early Detection (WRED) and tail drop algorithms. :numref:`figure_blk_diag_dropper` illustrates how the dropper integrates with the scheduler. The DPDK currently does not support congestion management so the dropper provides the only method for congestion avoidance. .. _figure_blk_diag_dropper: .. figure:: img/blk_diag_dropper.* High-level Block Diagram of the DPDK Dropper The dropper uses the Random Early Detection (RED) congestion avoidance algorithm as documented in the reference publication. The purpose of the RED algorithm is to monitor a packet queue, determine the current congestion level in the queue and decide whether an arriving packet should be enqueued or dropped. The RED algorithm uses an Exponential Weighted Moving Average (EWMA) filter to compute average queue size which gives an indication of the current congestion level in the queue. For each enqueue operation, the RED algorithm compares the average queue size to minimum and maximum thresholds. Depending on whether the average queue size is below, above or in between these thresholds, the RED algorithm calculates the probability that an arriving packet should be dropped and makes a random decision based on this probability. The dropper also supports Weighted Random Early Detection (WRED) by allowing the scheduler to select different RED configurations for the same packet queue at run-time. In the case of severe congestion, the dropper resorts to tail drop. This occurs when a packet queue has reached maximum capacity and cannot store any more packets. In this situation, all arriving packets are dropped. The flow through the dropper is illustrated in :numref:`figure_flow_tru_droppper`. The RED/WRED algorithm is exercised first and tail drop second. .. _figure_flow_tru_droppper: .. figure:: img/flow_tru_droppper.* Flow Through the Dropper The use cases supported by the dropper are: * * Initialize configuration data * * Initialize run-time data * * Enqueue (make a decision to enqueue or drop an arriving packet) * * Mark empty (record the time at which a packet queue becomes empty) The configuration use case is explained in :ref:`Section2.23.3.1 `, the enqueue operation is explained in :ref:`Section 2.23.3.2 ` and the mark empty operation is explained in :ref:`Section 2.23.3.3 `. .. _Configuration: Configuration ~~~~~~~~~~~~~ A RED configuration contains the parameters given in :numref:`table_qos_16`. .. _table_qos_16: .. table:: RED Configuration Parameters +--------------------------+---------+---------+------------------+ | Parameter | Minimum | Maximum | Typical | | | | | | +==========================+=========+=========+==================+ | Minimum Threshold | 0 | 1022 | 1/4 x queue size | | | | | | +--------------------------+---------+---------+------------------+ | Maximum Threshold | 1 | 1023 | 1/2 x queue size | | | | | | +--------------------------+---------+---------+------------------+ | Inverse Mark Probability | 1 | 255 | 10 | | | | | | +--------------------------+---------+---------+------------------+ | EWMA Filter Weight | 1 | 12 | 9 | | | | | | +--------------------------+---------+---------+------------------+ The meaning of these parameters is explained in more detail in the following sections. The format of these parameters as specified to the dropper module API corresponds to the format used by Cisco* in their RED implementation. The minimum and maximum threshold parameters are specified to the dropper module in terms of number of packets. The mark probability parameter is specified as an inverse value, for example, an inverse mark probability parameter value of 10 corresponds to a mark probability of 1/10 (that is, 1 in 10 packets will be dropped). The EWMA filter weight parameter is specified as an inverse log value, for example, a filter weight parameter value of 9 corresponds to a filter weight of 1/29. .. _Enqueue_Operation: Enqueue Operation ~~~~~~~~~~~~~~~~~ In the example shown in :numref:`figure_ex_data_flow_tru_dropper`, q (actual queue size) is the input value, avg (average queue size) and count (number of packets since the last drop) are run-time values, decision is the output value and the remaining values are configuration parameters. .. _figure_ex_data_flow_tru_dropper: .. figure:: img/ex_data_flow_tru_dropper.* Example Data Flow Through Dropper EWMA Filter Microblock ^^^^^^^^^^^^^^^^^^^^^^ The purpose of the EWMA Filter microblock is to filter queue size values to smooth out transient changes that result from "bursty" traffic. The output value is the average queue size which gives a more stable view of the current congestion level in the queue. The EWMA filter has one configuration parameter, filter weight, which determines how quickly or slowly the average queue size output responds to changes in the actual queue size input. Higher values of filter weight mean that the average queue size responds more quickly to changes in actual queue size. Average Queue Size Calculation when the Queue is not Empty """""""""""""""""""""""""""""""""""""""""""""""""""""""""" The definition of the EWMA filter is given in the following equation. .. image:: img/ewma_filter_eq_1.* Where: * *avg* = average queue size * *wq* = filter weight * *q* = actual queue size .. note:: The filter weight, wq = 1/2^n, where n is the filter weight parameter value passed to the dropper module on configuration (see :ref:`Section2.23.3.1 ` ). Average Queue Size Calculation when the Queue is Empty ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The EWMA filter does not read time stamps and instead assumes that enqueue operations will happen quite regularly. Special handling is required when the queue becomes empty as the queue could be empty for a short time or a long time. When the queue becomes empty, average queue size should decay gradually to zero instead of dropping suddenly to zero or remaining stagnant at the last computed value. When a packet is enqueued on an empty queue, the average queue size is computed using the following formula: .. image:: img/ewma_filter_eq_2.* Where: * *m* = the number of enqueue operations that could have occurred on this queue while the queue was empty In the dropper module, *m* is defined as: .. image:: img/m_definition.* Where: * *time* = current time * *qtime* = time the queue became empty * *s* = typical time between successive enqueue operations on this queue The time reference is in units of bytes, where a byte signifies the time duration required by the physical interface to send out a byte on the transmission medium (see Section 26.2.4.5.1 "Internal Time Reference"). The parameter s is defined in the dropper module as a constant with the value: s=2^22. This corresponds to the time required by every leaf node in a hierarchy with 64K leaf nodes to transmit one 64-byte packet onto the wire and represents the worst case scenario. For much smaller scheduler hierarchies, it may be necessary to reduce the parameter s, which is defined in the red header source file (rte_red.h) as: .. code-block:: c #define RTE_RED_S Since the time reference is in bytes, the port speed is implied in the expression: *time-qtime*. The dropper does not have to be configured with the actual port speed. It adjusts automatically to low speed and high speed links. Implementation """""""""""""" A numerical method is used to compute the factor (1-wq)^m that appears in Equation 2. This method is based on the following identity: .. image:: img/eq2_factor.* This allows us to express the following: .. image:: img/eq2_expression.* In the dropper module, a look-up table is used to compute log2(1-wq) for each value of wq supported by the dropper module. The factor (1-wq)^m can then be obtained by multiplying the table value by *m* and applying shift operations. To avoid overflow in the multiplication, the value, *m*, and the look-up table values are limited to 16 bits. The total size of the look-up table is 56 bytes. Once the factor (1-wq)^m is obtained using this method, the average queue size can be calculated from Equation 2. Alternative Approaches """""""""""""""""""""" Other methods for calculating the factor (1-wq)^m in the expression for computing average queue size when the queue is empty (Equation 2) were considered. These approaches include: * Floating-point evaluation * Fixed-point evaluation using a small look-up table (512B) and up to 16 multiplications (this is the approach used in the FreeBSD* ALTQ RED implementation) * Fixed-point evaluation using a small look-up table (512B) and 16 SSE multiplications (SSE optimized version of the approach used in the FreeBSD* ALTQ RED implementation) * Large look-up table (76 KB) The method that was finally selected (described above in Section 26.3.2.2.1) out performs all of these approaches in terms of run-time performance and memory requirements and also achieves accuracy comparable to floating-point evaluation. :numref:`table_qos_17` lists the performance of each of these alternative approaches relative to the method that is used in the dropper. As can be seen, the floating-point implementation achieved the worst performance. .. _table_qos_17: .. table:: Relative Performance of Alternative Approaches +------------------------------------------------------------------------------------+----------------------+ | Method | Relative Performance | | | | +====================================================================================+======================+ | Current dropper method (see :ref:`Section 23.3.2.1.3 `) | 100% | | | | +------------------------------------------------------------------------------------+----------------------+ | Fixed-point method with small (512B) look-up table | 148% | | | | +------------------------------------------------------------------------------------+----------------------+ | SSE method with small (512B) look-up table | 114% | | | | +------------------------------------------------------------------------------------+----------------------+ | Large (76KB) look-up table | 118% | | | | +------------------------------------------------------------------------------------+----------------------+ | Floating-point | 595% | | | | +------------------------------------------------------------------------------------+----------------------+ | **Note**: In this case, since performance is expressed as time spent executing the operation in a | | specific condition, any relative performance value above 100% runs slower than the reference method. | | | +-----------------------------------------------------------------------------------------------------------+ Drop Decision Block ^^^^^^^^^^^^^^^^^^^ The Drop Decision block: * Compares the average queue size with the minimum and maximum thresholds * Calculates a packet drop probability * Makes a random decision to enqueue or drop an arriving packet The calculation of the drop probability occurs in two stages. An initial drop probability is calculated based on the average queue size, the minimum and maximum thresholds and the mark probability. An actual drop probability is then computed from the initial drop probability. The actual drop probability takes the count run-time value into consideration so that the actual drop probability increases as more packets arrive to the packet queue since the last packet was dropped. Initial Packet Drop Probability """"""""""""""""""""""""""""""" The initial drop probability is calculated using the following equation. .. image:: img/drop_probability_eq3.* Where: * *maxp* = mark probability * *avg* = average queue size * *minth* = minimum threshold * *maxth* = maximum threshold The calculation of the packet drop probability using Equation 3 is illustrated in :numref:`figure_pkt_drop_probability`. If the average queue size is below the minimum threshold, an arriving packet is enqueued. If the average queue size is at or above the maximum threshold, an arriving packet is dropped. If the average queue size is between the minimum and maximum thresholds, a drop probability is calculated to determine if the packet should be enqueued or dropped. .. _figure_pkt_drop_probability: .. figure:: img/pkt_drop_probability.* Packet Drop Probability for a Given RED Configuration Actual Drop Probability """"""""""""""""""""""" If the average queue size is between the minimum and maximum thresholds, then the actual drop probability is calculated from the following equation. .. image:: img/drop_probability_eq4.* Where: * *Pb* = initial drop probability (from Equation 3) * *count* = number of packets that have arrived since the last drop The constant 2, in Equation 4 is the only deviation from the drop probability formulae given in the reference document where a value of 1 is used instead. It should be noted that the value pa computed from can be negative or greater than 1. If this is the case, then a value of 1 should be used instead. The initial and actual drop probabilities are shown in :numref:`figure_drop_probability_graph`. The actual drop probability is shown for the case where the formula given in the reference document1 is used (blue curve) and also for the case where the formula implemented in the dropper module, is used (red curve). The formula in the reference document results in a significantly higher drop rate compared to the mark probability configuration parameter specified by the user. The choice to deviate from the reference document is simply a design decision and one that has been taken by other RED implementations, for example, FreeBSD* ALTQ RED. .. _figure_drop_probability_graph: .. figure:: img/drop_probability_graph.* Initial Drop Probability (pb), Actual Drop probability (pa) Computed Using a Factor 1 (Blue Curve) and a Factor 2 (Red Curve) .. _Queue_Empty_Operation: Queue Empty Operation ~~~~~~~~~~~~~~~~~~~~~ The time at which a packet queue becomes empty must be recorded and saved with the RED run-time data so that the EWMA filter block can calculate the average queue size on the next enqueue operation. It is the responsibility of the calling application to inform the dropper module through the API that a queue has become empty. Source Files Location ~~~~~~~~~~~~~~~~~~~~~ The source files for the DPDK dropper are located at: * DPDK/lib/librte_sched/rte_red.h * DPDK/lib/librte_sched/rte_red.c Integration with the DPDK QoS Scheduler ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RED functionality in the DPDK QoS scheduler is disabled by default. To enable it, use the DPDK configuration parameter: :: CONFIG_RTE_SCHED_RED=y This parameter must be set to y. The parameter is found in the build configuration files in the DPDK/config directory, for example, DPDK/config/common_linuxapp. RED configuration parameters are specified in the rte_red_params structure within the rte_sched_port_params structure that is passed to the scheduler on initialization. RED parameters are specified separately for four traffic classes and three packet colors (green, yellow and red) allowing the scheduler to implement Weighted Random Early Detection (WRED). Integration with the DPDK QoS Scheduler Sample Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The DPDK QoS Scheduler Application reads a configuration file on start-up. The configuration file includes a section containing RED parameters. The format of these parameters is described in :ref:`Section2.23.3.1 `. A sample RED configuration is shown below. In this example, the queue size is 64 packets. .. note:: For correct operation, the same EWMA filter weight parameter (wred weight) should be used for each packet color (green, yellow, red) in the same traffic class (tc). :: ; RED params per traffic class and color (Green / Yellow / Red) [red] tc 0 wred min = 28 22 16 tc 0 wred max = 32 32 32 tc 0 wred inv prob = 10 10 10 tc 0 wred weight = 9 9 9 tc 1 wred min = 28 22 16 tc 1 wred max = 32 32 32 tc 1 wred inv prob = 10 10 10 tc 1 wred weight = 9 9 9 tc 2 wred min = 28 22 16 tc 2 wred max = 32 32 32 tc 2 wred inv prob = 10 10 10 tc 2 wred weight = 9 9 9 tc 3 wred min = 28 22 16 tc 3 wred max = 32 32 32 tc 3 wred inv prob = 10 10 10 tc 3 wred weight = 9 9 9 With this configuration file, the RED configuration that applies to green, yellow and red packets in traffic class 0 is shown in :numref:`table_qos_18`. .. _table_qos_18: .. table:: RED Configuration Corresponding to RED Configuration File +--------------------+--------------------+-------+--------+-----+ | RED Parameter | Configuration Name | Green | Yellow | Red | | | | | | | +====================+====================+=======+========+=====+ | Minimum Threshold | tc 0 wred min | 28 | 22 | 16 | | | | | | | +--------------------+--------------------+-------+--------+-----+ | Maximum Threshold | tc 0 wred max | 32 | 32 | 32 | | | | | | | +--------------------+--------------------+-------+--------+-----+ | Mark Probability | tc 0 wred inv prob | 10 | 10 | 10 | | | | | | | +--------------------+--------------------+-------+--------+-----+ | EWMA Filter Weight | tc 0 wred weight | 9 | 9 | 9 | | | | | | | +--------------------+--------------------+-------+--------+-----+ Application Programming Interface (API) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enqueue API ^^^^^^^^^^^ The syntax of the enqueue API is as follows: .. code-block:: c int rte_red_enqueue(const struct rte_red_config *red_cfg, struct rte_red *red, const unsigned q, const uint64_t time) The arguments passed to the enqueue API are configuration data, run-time data, the current size of the packet queue (in packets) and a value representing the current time. The time reference is in units of bytes, where a byte signifies the time duration required by the physical interface to send out a byte on the transmission medium (see Section 26.2.4.5.1 "Internal Time Reference" ). The dropper reuses the scheduler time stamps for performance reasons. Empty API ^^^^^^^^^ The syntax of the empty API is as follows: .. code-block:: c void rte_red_mark_queue_empty(struct rte_red *red, const uint64_t time) The arguments passed to the empty API are run-time data and the current time in bytes. Traffic Metering ---------------- The traffic metering component implements the Single Rate Three Color Marker (srTCM) and Two Rate Three Color Marker (trTCM) algorithms, as defined by IETF RFC 2697 and 2698 respectively. These algorithms meter the stream of incoming packets based on the allowance defined in advance for each traffic flow. As result, each incoming packet is tagged as green, yellow or red based on the monitored consumption of the flow the packet belongs to. Functional Overview ~~~~~~~~~~~~~~~~~~~ The srTCM algorithm defines two token buckets for each traffic flow, with the two buckets sharing the same token update rate: * Committed (C) bucket: fed with tokens at the rate defined by the Committed Information Rate (CIR) parameter (measured in IP packet bytes per second). The size of the C bucket is defined by the Committed Burst Size (CBS) parameter (measured in bytes); * Excess (E) bucket: fed with tokens at the same rate as the C bucket. The size of the E bucket is defined by the Excess Burst Size (EBS) parameter (measured in bytes). The trTCM algorithm defines two token buckets for each traffic flow, with the two buckets being updated with tokens at independent rates: * Committed (C) bucket: fed with tokens at the rate defined by the Committed Information Rate (CIR) parameter (measured in bytes of IP packet per second). The size of the C bucket is defined by the Committed Burst Size (CBS) parameter (measured in bytes); * Peak (P) bucket: fed with tokens at the rate defined by the Peak Information Rate (PIR) parameter (measured in IP packet bytes per second). The size of the P bucket is defined by the Peak Burst Size (PBS) parameter (measured in bytes). Please refer to RFC 2697 (for srTCM) and RFC 2698 (for trTCM) for details on how tokens are consumed from the buckets and how the packet color is determined. Color Blind and Color Aware Modes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For both algorithms, the color blind mode is functionally equivalent to the color aware mode with input color set as green. For color aware mode, a packet with red input color can only get the red output color, while a packet with yellow input color can only get the yellow or red output colors. The reason why the color blind mode is still implemented distinctly than the color aware mode is that color blind mode can be implemented with fewer operations than the color aware mode. Implementation Overview ~~~~~~~~~~~~~~~~~~~~~~~ For each input packet, the steps for the srTCM / trTCM algorithms are: * Update the C and E / P token buckets. This is done by reading the current time (from the CPU timestamp counter), identifying the amount of time since the last bucket update and computing the associated number of tokens (according to the pre-configured bucket rate). The number of tokens in the bucket is limited by the pre-configured bucket size; * Identify the output color for the current packet based on the size of the IP packet and the amount of tokens currently available in the C and E / P buckets; for color aware mode only, the input color of the packet is also considered. When the output color is not red, a number of tokens equal to the length of the IP packet are subtracted from the C or E /P or both buckets, depending on the algorithm and the output color of the packet. ================================================ FILE: doc/guides/prog_guide/reorder_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Reorder_Library: Reorder Library ================= The Reorder Library provides a mechanism for reordering mbufs based on their sequence number. Operation ---------- The reorder library is essentially a buffer that reorders mbufs. The user inserts out of order mbufs into the reorder buffer and pulls in-order mbufs from it. At a given time, the reorder buffer contains mbufs whose sequence number are inside the sequence window. The sequence window is determined by the minimum sequence number and the number of entries that the buffer was configured to hold. For example, given a reorder buffer with 200 entries and a minimum sequence number of 350, the sequence window has low and high limits of 350 and 550 respectively. When inserting mbufs, the reorder library differentiates between valid, early and late mbufs depending on the sequence number of the inserted mbuf: * valid: the sequence number is inside the window. * late: the sequence number is outside the window and less than the low limit. * early: the sequence number is outside the window and greater than the high limit. The reorder buffer directly returns late mbufs and tries to accommodate early mbufs. Implementation Details ------------------------- The reorder library is implemented as a pair of buffers, which referred to as the *Order* buffer and the *Ready* buffer. On an insert call, valid mbufs are inserted directly into the Order buffer and late mbufs are returned to the user with an error. In the case of early mbufs, the reorder buffer will try to move the window (incrementing the minimum sequence number) so that the mbuf becomes a valid one. To that end, mbufs in the Order buffer are moved into the Ready buffer. Any mbufs that have not arrived yet are ignored and therefore will become late mbufs. This means that as long as there is room in the Ready buffer, the window will be moved to accommodate early mbufs that would otherwise be outside the reordering window. For example, assuming that we have a buffer of 200 entries with a 350 minimum sequence number, and we need to insert an early mbuf with 565 sequence number. That means that we would need to move the windows at least 15 positions to accommodate the mbuf. The reorder buffer would try to move mbufs from at least the next 15 slots in the Order buffer to the Ready buffer, as long as there is room in the Ready buffer. Any gaps in the Order buffer at that point are skipped, and those packet will be reported as late packets when they arrive. The process of moving packets to the Ready buffer continues beyond the minimum required until a gap, i.e. missing mbuf, in the Order buffer is encountered. When draining mbufs, the reorder buffer would return mbufs in the Ready buffer first and then from the Order buffer until a gap is found (mbufs that have not arrived yet). Use Case: Packet Distributor ------------------------------- An application using the DPDK packet distributor could make use of the reorder library to transmit packets in the same order they were received. A basic packet distributor use case would consist of a distributor with multiple workers cores. The processing of packets by the workers is not guaranteed to be in order, hence a reorder buffer can be used to order as many packets as possible. In such a scenario, the distributor assigns a sequence number to mbufs before delivering them to the workers. As the workers finish processing the packets, the distributor inserts those mbufs into the reorder buffer and finally transmit drained mbufs. NOTE: Currently the reorder buffer is not thread safe so the same thread is responsible for inserting and draining mbufs. ================================================ FILE: doc/guides/prog_guide/ring_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Ring_Library: Ring Library ============ The ring allows the management of queues. Instead of having a linked list of infinite size, the rte_ring has the following properties: * FIFO * Maximum size is fixed, the pointers are stored in a table * Lockless implementation * Multi-consumer or single-consumer dequeue * Multi-producer or single-producer enqueue * Bulk dequeue - Dequeues the specified count of objects if successful; otherwise fails * Bulk enqueue - Enqueues the specified count of objects if successful; otherwise fails * Burst dequeue - Dequeue the maximum available objects if the specified count cannot be fulfilled * Burst enqueue - Enqueue the maximum available objects if the specified count cannot be fulfilled The advantages of this data structure over a linked list queue are as follows: * Faster; only requires a single Compare-And-Swap instruction of sizeof(void \*) instead of several double-Compare-And-Swap instructions. * Simpler than a full lockless queue. * Adapted to bulk enqueue/dequeue operations. As pointers are stored in a table, a dequeue of several objects will not produce as many cache misses as in a linked queue. Also, a bulk dequeue of many objects does not cost more than a dequeue of a simple object. The disadvantages: * Size is fixed * Having many rings costs more in terms of memory than a linked list queue. An empty ring contains at least N pointers. A simplified representation of a Ring is shown in with consumer and producer head and tail pointers to objects stored in the data structure. .. _figure_ring1: .. figure:: img/ring1.* Ring Structure References for Ring Implementation in FreeBSD* ---------------------------------------------- The following code was added in FreeBSD 8.0, and is used in some network device drivers (at least in Intel drivers): * `bufring.h in FreeBSD `_ * `bufring.c in FreeBSD `_ Lockless Ring Buffer in Linux* ------------------------------ The following is a link describing the `Linux Lockless Ring Buffer Design `_. Additional Features ------------------- Name ~~~~ A ring is identified by a unique name. It is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted). Water Marking ~~~~~~~~~~~~~ The ring can have a high water mark (threshold). Once an enqueue operation reaches the high water mark, the producer is notified, if the water mark is configured. This mechanism can be used, for example, to exert a back pressure on I/O to inform the LAN to PAUSE. Debug ~~~~~ When debug is enabled (CONFIG_RTE_LIBRTE_RING_DEBUG is set), the library stores some per-ring statistic counters about the number of enqueues/dequeues. These statistics are per-core to avoid concurrent accesses or atomic operations. Use Cases --------- Use cases for the Ring library include: * Communication between applications in the DPDK * Used by memory pool allocator Anatomy of a Ring Buffer ------------------------ This section explains how a ring buffer operates. The ring structure is composed of two head and tail couples; one is used by producers and one is used by the consumers. The figures of the following sections refer to them as prod_head, prod_tail, cons_head and cons_tail. Each figure represents a simplified state of the ring, which is a circular buffer. The content of the function local variables is represented on the top of the figure, and the content of ring structure is represented on the bottom of the figure. Single Producer Enqueue ~~~~~~~~~~~~~~~~~~~~~~~ This section explains what occurs when a producer adds an object to the ring. In this example, only the producer head and tail (prod_head and prod_tail) are modified, and there is only one producer. The initial state is to have a prod_head and prod_tail pointing at the same location. Enqueue First Step ^^^^^^^^^^^^^^^^^^ First, *ring->prod_head* and ring->cons_tail are copied in local variables. The prod_next local variable points to the next element of the table, or several elements after in case of bulk enqueue. If there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. .. _figure_ring-enqueue1: .. figure:: img/ring-enqueue1.* Enqueue first step Enqueue Second Step ^^^^^^^^^^^^^^^^^^^ The second step is to modify *ring->prod_head* in ring structure to point to the same location as prod_next. A pointer to the added object is copied in the ring (obj4). .. _figure_ring-enqueue2: .. figure:: img/ring-enqueue2.* Enqueue second step Enqueue Last Step ^^^^^^^^^^^^^^^^^ Once the object is added in the ring, ring->prod_tail in the ring structure is modified to point to the same location as *ring->prod_head*. The enqueue operation is finished. .. _figure_ring-enqueue3: .. figure:: img/ring-enqueue3.* Enqueue last step Single Consumer Dequeue ~~~~~~~~~~~~~~~~~~~~~~~ This section explains what occurs when a consumer dequeues an object from the ring. In this example, only the consumer head and tail (cons_head and cons_tail) are modified and there is only one consumer. The initial state is to have a cons_head and cons_tail pointing at the same location. Dequeue First Step ^^^^^^^^^^^^^^^^^^ First, ring->cons_head and ring->prod_tail are copied in local variables. The cons_next local variable points to the next element of the table, or several elements after in the case of bulk dequeue. If there are not enough objects in the ring (this is detected by checking prod_tail), it returns an error. .. _figure_ring-dequeue1: .. figure:: img/ring-dequeue1.* Dequeue last step Dequeue Second Step ^^^^^^^^^^^^^^^^^^^ The second step is to modify ring->cons_head in the ring structure to point to the same location as cons_next. The pointer to the dequeued object (obj1) is copied in the pointer given by the user. .. _figure_ring-dequeue2: .. figure:: img/ring-dequeue2.* Dequeue second step Dequeue Last Step ^^^^^^^^^^^^^^^^^ Finally, ring->cons_tail in the ring structure is modified to point to the same location as ring->cons_head. The dequeue operation is finished. .. _figure_ring-dequeue3: .. figure:: img/ring-dequeue3.* Dequeue last step Multiple Producers Enqueue ~~~~~~~~~~~~~~~~~~~~~~~~~~ This section explains what occurs when two producers concurrently add an object to the ring. In this example, only the producer head and tail (prod_head and prod_tail) are modified. The initial state is to have a prod_head and prod_tail pointing at the same location. Multiple Consumer Enqueue First Step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ On both cores, *ring->prod_head* and ring->cons_tail are copied in local variables. The prod_next local variable points to the next element of the table, or several elements after in the case of bulk enqueue. If there is not enough room in the ring (this is detected by checking cons_tail), it returns an error. .. _figure_ring-mp-enqueue1: .. figure:: img/ring-mp-enqueue1.* Multiple consumer enqueue first step Multiple Consumer Enqueue Second Step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The second step is to modify ring->prod_head in the ring structure to point to the same location as prod_next. This operation is done using a Compare And Swap (CAS) instruction, which does the following operations atomically: * If ring->prod_head is different to local variable prod_head, the CAS operation fails, and the code restarts at first step. * Otherwise, ring->prod_head is set to local prod_next, the CAS operation is successful, and processing continues. In the figure, the operation succeeded on core 1, and step one restarted on core 2. .. _figure_ring-mp-enqueue2: .. figure:: img/ring-mp-enqueue2.* Multiple consumer enqueue second step Multiple Consumer Enqueue Third Step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The CAS operation is retried on core 2 with success. The core 1 updates one element of the ring(obj4), and the core 2 updates another one (obj5). .. _figure_ring-mp-enqueue3: .. figure:: img/ring-mp-enqueue3.* Multiple consumer enqueue third step Multiple Consumer Enqueue Fourth Step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each core now wants to update ring->prod_tail. A core can only update it if ring->prod_tail is equal to the prod_head local variable. This is only true on core 1. The operation is finished on core 1. .. _figure_ring-mp-enqueue4: .. figure:: img/ring-mp-enqueue4.* Multiple consumer enqueue fourth step Multiple Consumer Enqueue Last Step ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Once ring->prod_tail is updated by core 1, core 2 is allowed to update it too. The operation is also finished on core 2. .. _figure_ring-mp-enqueue5: .. figure:: img/ring-mp-enqueue5.* Multiple consumer enqueue last step Modulo 32-bit Indexes ~~~~~~~~~~~~~~~~~~~~~ In the preceding figures, the prod_head, prod_tail, cons_head and cons_tail indexes are represented by arrows. In the actual implementation, these values are not between 0 and size(ring)-1 as would be assumed. The indexes are between 0 and 2^32 -1, and we mask their value when we access the pointer table (the ring itself). 32-bit modulo also implies that operations on indexes (such as, add/subtract) will automatically do 2^32 modulo if the result overflows the 32-bit number range. The following are two examples that help to explain how indexes are used in a ring. .. note:: To simplify the explanation, operations with modulo 16-bit are used instead of modulo 32-bit. In addition, the four indexes are defined as unsigned 16-bit integers, as opposed to unsigned 32-bit integers in the more realistic case. .. _figure_ring-modulo1: .. figure:: img/ring-modulo1.* Modulo 32-bit indexes - Example 1 This ring contains 11000 entries. .. _figure_ring-modulo2: .. figure:: img/ring-modulo2.* Modulo 32-bit indexes - Example 2 This ring contains 12536 entries. .. note:: For ease of understanding, we use modulo 65536 operations in the above examples. In real execution cases, this is redundant for low efficiency, but is done automatically when the result overflows. The code always maintains a distance between producer and consumer between 0 and size(ring)-1. Thanks to this property, we can do subtractions between 2 index values in a modulo-32bit base: that's why the overflow of the indexes is not a problem. At any time, entries and free_entries are between 0 and size(ring)-1, even if only the first term of subtraction has overflowed: .. code-block:: c uint32_t entries = (prod_tail - cons_head); uint32_t free_entries = (mask + cons_tail -prod_head); References ---------- * `bufring.h in FreeBSD `_ (version 8) * `bufring.c in FreeBSD `_ (version 8) * `Linux Lockless Ring Buffer Design `_ ================================================ FILE: doc/guides/prog_guide/source_org.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **Part 2: Development Environment** Source Organization =================== This section describes the organization of sources in the DPDK framework. Makefiles and Config -------------------- .. note:: In the following descriptions, ``RTE_SDK`` is the environment variable that points to the base directory into which the tarball was extracted. See :ref:`Useful_Variables_Provided_by_the_Build_System` for descriptions of other variables. Makefiles that are provided by the DPDK libraries and applications are located in ``$(RTE_SDK)/mk``. Config templates are located in ``$(RTE_SDK)/config``. The templates describe the options that are enabled for each target. The config file also contains items that can be enabled and disabled for many of the DPDK libraries, including debug options. The user should look at the config file and become familiar with these options. The config file is also used to create a header file, which will be located in the new build directory. Libraries --------- Libraries are located in subdirectories of ``$(RTE_SDK)/lib``. By convention a library refers to any code that provides an API to an application. Typically, it generates an archive file (``.a``), but a kernel module would also go in the same directory. The lib directory contains:: lib +-- librte_cmdline # Command line interface helper +-- librte_distributor # Packet distributor +-- librte_eal # Environment abstraction layer +-- librte_ether # Generic interface to poll mode driver +-- librte_hash # Hash library +-- librte_ip_frag # IP fragmentation library +-- librte_ivshmem # QEMU IVSHMEM library +-- librte_kni # Kernel NIC interface +-- librte_kvargs # Argument parsing library +-- librte_lpm # Longest prefix match library +-- librte_malloc # Malloc-like functions +-- librte_mbuf # Packet and control mbuf manipulation +-- librte_mempool # Memory pool manager (fixed sized objects) +-- librte_meter # QoS metering library +-- librte_net # Various IP-related headers +-- librte_power # Power management library +-- librte_ring # Software rings (act as lockless FIFOs) +-- librte_sched # QoS scheduler and dropper library +-- librte_timer # Timer library Drivers ------- Drivers are special libraries which provide poll-mode driver implementations for devices: either hardware devices or pseudo/virtual devices. They are contained in the *drivers* subdirectory, classified by type, and each compiles to a library with the format ``librte_pmd_X.a`` where ``X`` is the driver name. The drivers directory has a *net* subdirectory which contains:: drivers/net +-- af_packet # Poll mode driver based on Linux af_packet +-- bonding # Bonding poll mode driver +-- cxgbe # Chelsio Terminator 10GbE/40GbE poll mode driver +-- e1000 # 1GbE poll mode drivers (igb and em) +-- enic # Cisco VIC Ethernet NIC Poll-mode Driver +-- fm10k # Host interface PMD driver for FM10000 Series +-- i40e # 40GbE poll mode driver +-- ixgbe # 10GbE poll mode driver +-- mlx4 # Mellanox ConnectX-3 poll mode driver +-- null # NULL poll mode driver for testing +-- pcap # PCAP poll mode driver +-- ring # Ring poll mode driver +-- virtio # Virtio poll mode driver +-- vmxnet3 # VMXNET3 poll mode driver +-- xenvirt # Xen virtio poll mode driver .. note:: Several of the ``driver/net`` directories contain a ``base`` sub-directory. The ``base`` directory generally contains code the shouldn't be modified directly by the user. Any enhancements should be done via the ``X_osdep.c`` and/or ``X_osdep.h`` files in that directory. Refer to the local README in the base directories for driver specific instructions. Applications ------------ Applications are source files that contain a ``main()`` function. They are located in the ``$(RTE_SDK)/app`` and ``$(RTE_SDK)/examples`` directories. The app directory contains sample applications that are used to test DPDK (such as autotests) or the Poll Mode Drivers (test-pmd):: app +-- chkincs # Test program to check include dependencies +-- cmdline_test # Test the commandline library +-- test # Autotests to validate DPDK features +-- test-acl # Test the ACL library +-- test-pipeline # Test the IP Pipeline framework +-- test-pmd # Test and benchmark poll mode drivers The examples directory contains sample applications that show how libraries can be used:: examples +-- cmdline # Example of using the cmdline library +-- dpdk_qat # Sample integration with Intel QuickAssist +-- exception_path # Sending packets to and from Linux TAP device +-- helloworld # Basic Hello World example +-- ip_reassembly # Example showing IP reassembly +-- ip_fragmentation # Example showing IPv4 fragmentation +-- ipv4_multicast # Example showing IPv4 multicast +-- kni # Kernel NIC Interface (KNI) example +-- l2fwd # L2 forwarding with and without SR-IOV +-- l3fwd # L3 forwarding example +-- l3fwd-power # L3 forwarding example with power management +-- l3fwd-vf # L3 forwarding example with SR-IOV +-- link_status_interrupt # Link status change interrupt example +-- load_balancer # Load balancing across multiple cores/sockets +-- multi_process # Example apps using multiple DPDK processes +-- qos_meter # QoS metering example +-- qos_sched # QoS scheduler and dropper example +-- timer # Example of using librte_timer library +-- vmdq_dcb # Example of VMDQ and DCB receiving +-- vmdq # Example of VMDQ receiving +-- vhost # Example of userspace vhost and switch .. note:: The actual examples directory may contain additional sample applications to those shown above. Check the latest DPDK source files for details. ================================================ FILE: doc/guides/prog_guide/thread_safety_intel_dpdk_functions.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Thread Safety of DPDK Functions =============================== The DPDK is comprised of several libraries. Some of the functions in these libraries can be safely called from multiple threads simultaneously, while others cannot. This section allows the developer to take these issues into account when building their own application. The run-time environment of the DPDK is typically a single thread per logical core. In some cases, it is not only multi-threaded, but multi-process. Typically, it is best to avoid sharing data structures between threads and/or processes where possible. Where this is not possible, then the execution blocks must access the data in a thread- safe manner. Mechanisms such as atomics or locking can be used that will allow execution blocks to operate serially. However, this can have an effect on the performance of the application. Fast-Path APIs -------------- Applications operating in the data plane are performance sensitive but certain functions within those libraries may not be safe to call from multiple threads simultaneously. The hash, LPM and mempool libraries and RX/TX in the PMD are examples of this. The hash and LPM libraries are, by design, thread unsafe in order to maintain performance. However, if required the developer can add layers on top of these libraries to provide thread safety. Locking is not needed in all situations, and in both the hash and LPM libraries, lookups of values can be performed in parallel in multiple threads. Adding, removing or modifying values, however, cannot be done in multiple threads without using locking when a single hash or LPM table is accessed. Another alternative to locking would be to create multiple instances of these tables allowing each thread its own copy. The RX and TX of the PMD are the most critical aspects of a DPDK application and it is recommended that no locking be used as it will impact performance. Note, however, that these functions can safely be used from multiple threads when each thread is performing I/O on a different NIC queue. If multiple threads are to use the same hardware queue on the same NIC port, then locking, or some other form of mutual exclusion, is necessary. The ring library is based on a lockless ring-buffer algorithm that maintains its original design for thread safety. Moreover, it provides high performance for either multi- or single-consumer/producer enqueue/dequeue operations. The mempool library is based on the DPDK lockless ring library and therefore is also multi-thread safe. Performance Insensitive API --------------------------- Outside of the performance sensitive areas described in Section 25.1, the DPDK provides a thread-safe API for most other libraries. For example, malloc(librte_malloc) and memzone functions are safe for use in multi-threaded and multi-process environments. The setup and configuration of the PMD is not performance sensitive, but is not thread safe either. It is possible that the multiple read/writes during PMD setup and configuration could be corrupted in a multi-thread environment. Since this is not performance sensitive, the developer can choose to add their own layer to provide thread-safe setup and configuration. It is expected that, in most applications, the initial configuration of the network ports would be done by a single thread at startup. Library Initialization ---------------------- It is recommended that DPDK libraries are initialized in the main thread at application startup rather than subsequently in the forwarding threads. However, the DPDK performs checks to ensure that libraries are only initialized once. If initialization is attempted more than once, an error is returned. In the multi-process case, the configuration information of shared memory will only be initialized by the master process. Thereafter, both master and secondary processes can allocate/release any objects of memory that finally rely on rte_malloc or memzones. Interrupt Thread ---------------- The DPDK works almost entirely in Linux user space in polling mode. For certain infrequent operations, such as receiving a PMD link status change notification, callbacks may be called in an additional thread outside the main DPDK processing threads. These function callbacks should avoid manipulating DPDK objects that are also managed by the normal DPDK threads, and if they need to do so, it is up to the application to provide the appropriate locking or mutual exclusion restrictions around those objects. ================================================ FILE: doc/guides/prog_guide/timer_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _Timer_Library: Timer Library ============= The Timer library provides a timer service to DPDK execution units to enable execution of callback functions asynchronously. Features of the library are: * Timers can be periodic (multi-shot) or single (one-shot). * Timers can be loaded from one core and executed on another. It has to be specified in the call to rte_timer_reset(). * Timers provide high precision (depends on the call frequency to rte_timer_manage() that checks timer expiration for the local core). * If not required in the application, timers can be disabled at compilation time by not calling the rte_timer_manage() to increase performance. The timer library uses the rte_get_timer_cycles() function that uses the High Precision Event Timer (HPET) or the CPUs Time Stamp Counter (TSC) to provide a reliable time reference. This library provides an interface to add, delete and restart a timer. The API is based on BSD callout() with a few differences. Refer to the `callout manual `_. Implementation Details ---------------------- Timers are tracked on a per-lcore basis, with all pending timers for a core being maintained in order of timer expiry in a skiplist data structure. The skiplist used has ten levels and each entry in the table appears in each level with probability ¼^level. This means that all entries are present in level 0, 1 in every 4 entries is present at level 1, one in every 16 at level 2 and so on up to level 9. This means that adding and removing entries from the timer list for a core can be done in log(n) time, up to 4^10 entries, that is, approximately 1,000,000 timers per lcore. A timer structure contains a special field called status, which is a union of a timer state (stopped, pending, running, config) and an owner (lcore id). Depending on the timer state, we know if a timer is present in a list or not: * STOPPED: no owner, not in a list * CONFIG: owned by a core, must not be modified by another core, maybe in a list or not, depending on previous state * PENDING: owned by a core, present in a list * RUNNING: owned by a core, must not be modified by another core, present in a list Resetting or stopping a timer while it is in a CONFIG or RUNNING state is not allowed. When modifying the state of a timer, a Compare And Swap instruction should be used to guarantee that the status (state+owner) is modified atomically. Inside the rte_timer_manage() function, the skiplist is used as a regular list by iterating along the level 0 list, which contains all timer entries, until an entry which has not yet expired has been encountered. To improve performance in the case where there are entries in the timer list but none of those timers have yet expired, the expiry time of the first list entry is maintained within the per-core timer list structure itself. On 64-bit platforms, this value can be checked without the need to take a lock on the overall structure. (Since expiry times are maintained as 64-bit values, a check on the value cannot be done on 32-bit platforms without using either a compare-and-swap (CAS) instruction or using a lock, so this additional check is skipped in favor of checking as normal once the lock has been taken.) On both 64-bit and 32-bit platforms, a call to rte_timer_manage() returns without taking a lock in the case where the timer list for the calling core is empty. Use Cases --------- The timer library is used for periodic calls, such as garbage collectors, or some state machines (ARP, bridging, and so on). References ---------- * `callout manual `_ - The callout facility that provides timers with a mechanism to execute a function at a given time. * `HPET `_ - Information about the High Precision Event Timer (HPET). ================================================ FILE: doc/guides/prog_guide/vhost_lib.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Vhost Library ============= The vhost library implements a user space vhost driver. It supports both vhost-cuse (cuse: user space character device) and vhost-user(user space socket server). It also creates, manages and destroys vhost devices for corresponding virtio devices in the guest. Vhost supported vSwitch could register callbacks to this library, which will be called when a vhost device is activated or deactivated by guest virtual machine. Vhost API Overview ------------------ * Vhost driver registration rte_vhost_driver_register registers the vhost driver into the system. For vhost-cuse, character device file will be created under the /dev directory. Character device name is specified as the parameter. For vhost-user, a Unix domain socket server will be created with the parameter as the local socket path. * Vhost session start rte_vhost_driver_session_start starts the vhost session loop. Vhost session is an infinite blocking loop. Put the session in a dedicate DPDK thread. * Callback register Vhost supported vSwitch could call rte_vhost_driver_callback_register to register two callbacks, new_destory and destroy_device. When virtio device is activated or deactivated by guest virtual machine, the callback will be called, then vSwitch could put the device onto data core or remove the device from data core by setting or unsetting VIRTIO_DEV_RUNNING on the device flags. * Read/write packets from/to guest virtual machine rte_vhost_enqueue_burst transmit host packets to guest. rte_vhost_dequeue_burst receives packets from guest. * Feature enable/disable Now one negotiate-able feature in vhost is merge-able. vSwitch could enable/disable this feature for performance consideration. Vhost Implementation -------------------- Vhost cuse implementation ~~~~~~~~~~~~~~~~~~~~~~~~~ When vSwitch registers the vhost driver, it will register a cuse device driver into the system and creates a character device file. This cuse driver will receive vhost open/release/IOCTL message from QEMU simulator. When the open call is received, vhost driver will create a vhost device for the virtio device in the guest. When VHOST_SET_MEM_TABLE IOCTL is received, vhost searches the memory region to find the starting user space virtual address that maps the memory of guest virtual machine. Through this virtual address and the QEMU pid, vhost could find the file QEMU uses to map the guest memory. Vhost maps this file into its address space, in this way vhost could fully access the guest physical memory, which means vhost could access the shared virtio ring and the guest physical address specified in the entry of the ring. The guest virtual machine tells the vhost whether the virtio device is ready for processing or is de-activated through VHOST_NET_SET_BACKEND message. The registered callback from vSwitch will be called. When the release call is released, vhost will destroy the device. Vhost user implementation ~~~~~~~~~~~~~~~~~~~~~~~~~ When vSwitch registers a vhost driver, it will create a Unix domain socket server into the system. This server will listen for a connection and process the vhost message from QEMU simulator. When there is a new socket connection, it means a new virtio device has been created in the guest virtual machine, and the vhost driver will create a vhost device for this virtio device. For messages with a file descriptor, the file descriptor could be directly used in the vhost process as it is already installed by Unix domain socket. * VHOST_SET_MEM_TABLE * VHOST_SET_VRING_KICK * VHOST_SET_VRING_CALL * VHOST_SET_LOG_FD * VHOST_SET_VRING_ERR For VHOST_SET_MEM_TABLE message, QEMU will send us information for each memory region and its file descriptor in the ancillary data of the message. The fd is used to map that region. There is no VHOST_NET_SET_BACKEND message as in vhost cuse to signal us whether virtio device is ready or should be stopped. VHOST_SET_VRING_KICK is used as the signal to put the vhost device onto data plane. VHOST_GET_VRING_BASE is used as the signal to remove vhost device from data plane. When the socket connection is closed, vhost will destroy the device. Vhost supported vSwitch reference --------------------------------- For more vhost details and how to support vhost in vSwitch, please refer to vhost example in the DPDK Sample Applications Guide. ================================================ FILE: doc/guides/prog_guide/writing_efficient_code.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Writing Efficient Code ====================== This chapter provides some tips for developing efficient code using the DPDK. For additional and more general information, please refer to the *Intel® 64 and IA-32 Architectures Optimization Reference Manual* which is a valuable reference to writing efficient code. Memory ------ This section describes some key memory considerations when developing applications in the DPDK environment. Memory Copy: Do not Use libc in the Data Plane ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Many libc functions are available in the DPDK, via the Linux* application environment. This can ease the porting of applications and the development of the configuration plane. However, many of these functions are not designed for performance. Functions such as memcpy() or strcpy() should not be used in the data plane. To copy small structures, the preference is for a simpler technique that can be optimized by the compiler. Refer to the *VTune™ Performance Analyzer Essentials* publication from Intel Press for recommendations. For specific functions that are called often, it is also a good idea to provide a self-made optimized function, which should be declared as static inline. The DPDK API provides an optimized rte_memcpy() function. Memory Allocation ~~~~~~~~~~~~~~~~~ Other functions of libc, such as malloc(), provide a flexible way to allocate and free memory. In some cases, using dynamic allocation is necessary, but it is really not advised to use malloc-like functions in the data plane because managing a fragmented heap can be costly and the allocator may not be optimized for parallel allocation. If you really need dynamic allocation in the data plane, it is better to use a memory pool of fixed-size objects. This API is provided by librte_mempool. This data structure provides several services that increase performance, such as memory alignment of objects, lockless access to objects, NUMA awareness, bulk get/put and per-lcore cache. The rte_malloc () function uses a similar concept to mempools. Concurrent Access to the Same Memory Area ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Read-Write (RW) access operations by several lcores to the same memory area can generate a lot of data cache misses, which are very costly. It is often possible to use per-lcore variables, for example, in the case of statistics. There are at least two solutions for this: * Use RTE_PER_LCORE variables. Note that in this case, data on lcore X is not available to lcore Y. * Use a table of structures (one per lcore). In this case, each structure must be cache-aligned. Read-mostly variables can be shared among lcores without performance losses if there are no RW variables in the same cache line. NUMA ~~~~ On a NUMA system, it is preferable to access local memory since remote memory access is slower. In the DPDK, the memzone, ring, rte_malloc and mempool APIs provide a way to create a pool on a specific socket. Sometimes, it can be a good idea to duplicate data to optimize speed. For read-mostly variables that are often accessed, it should not be a problem to keep them in one socket only, since data will be present in cache. Distribution Across Memory Channels ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modern memory controllers have several memory channels that can load or store data in parallel. Depending on the memory controller and its configuration, the number of channels and the way the memory is distributed across the channels varies. Each channel has a bandwidth limit, meaning that if all memory access operations are done on the first channel only, there is a potential bottleneck. By default, the :ref:`Mempool Library ` spreads the addresses of objects among memory channels. Communication Between lcores ---------------------------- To provide a message-based communication between lcores, it is advised to use the DPDK ring API, which provides a lockless ring implementation. The ring supports bulk and burst access, meaning that it is possible to read several elements from the ring with only one costly atomic operation (see Chapter 5 "Ring Library"). Performance is greatly improved when using bulk access operations. The code algorithm that dequeues messages may be something similar to the following: .. code-block:: c #define MAX_BULK 32 while (1) { /* Process as many elements as can be dequeued. */ count = rte_ring_dequeue_burst(ring, obj_table, MAX_BULK); if (unlikely(count == 0)) continue; my_process_bulk(obj_table, count); } PMD Driver ---------- The DPDK Poll Mode Driver (PMD) is also able to work in bulk/burst mode, allowing the factorization of some code for each call in the send or receive function. Avoid partial writes. When PCI devices write to system memory through DMA, it costs less if the write operation is on a full cache line as opposed to part of it. In the PMD code, actions have been taken to avoid partial writes as much as possible. Lower Packet Latency ~~~~~~~~~~~~~~~~~~~~ Traditionally, there is a trade-off between throughput and latency. An application can be tuned to achieve a high throughput, but the end-to-end latency of an average packet will typically increase as a result. Similarly, the application can be tuned to have, on average, a low end-to-end latency, at the cost of lower throughput. In order to achieve higher throughput, the DPDK attempts to aggregate the cost of processing each packet individually by processing packets in bursts. Using the testpmd application as an example, the burst size can be set on the command line to a value of 16 (also the default value). This allows the application to request 16 packets at a time from the PMD. The testpmd application then immediately attempts to transmit all the packets that were received, in this case, all 16 packets. The packets are not transmitted until the tail pointer is updated on the corresponding TX queue of the network port. This behavior is desirable when tuning for high throughput because the cost of tail pointer updates to both the RX and TX queues can be spread across 16 packets, effectively hiding the relatively slow MMIO cost of writing to the PCIe* device. However, this is not very desirable when tuning for low latency because the first packet that was received must also wait for another 15 packets to be received. It cannot be transmitted until the other 15 packets have also been processed because the NIC will not know to transmit the packets until the TX tail pointer has been updated, which is not done until all 16 packets have been processed for transmission. To consistently achieve low latency, even under heavy system load, the application developer should avoid processing packets in bunches. The testpmd application can be configured from the command line to use a burst value of 1. This will allow a single packet to be processed at a time, providing lower latency, but with the added cost of lower throughput. Locks and Atomic Operations --------------------------- Atomic operations imply a lock prefix before the instruction, causing the processor's LOCK# signal to be asserted during execution of the following instruction. This has a big impact on performance in a multicore environment. Performance can be improved by avoiding lock mechanisms in the data plane. It can often be replaced by other solutions like per-lcore variables. Also, some locking techniques are more efficient than others. For instance, the Read-Copy-Update (RCU) algorithm can frequently replace simple rwlocks. Coding Considerations --------------------- Inline Functions ~~~~~~~~~~~~~~~~ Small functions can be declared as static inline in the header file. This avoids the cost of a call instruction (and the associated context saving). However, this technique is not always efficient; it depends on many factors including the compiler. Branch Prediction ~~~~~~~~~~~~~~~~~ The Intel® C/C++ Compiler (icc)/gcc built-in helper functions likely() and unlikely() allow the developer to indicate if a code branch is likely to be taken or not. For instance: .. code-block:: c if (likely(x > 1)) do_stuff(); Setting the Target CPU Type --------------------------- The DPDK supports CPU microarchitecture-specific optimizations by means of CONFIG_RTE_MACHINE option in the DPDK configuration file. The degree of optimization depends on the compiler's ability to optimize for a specific microarchitecture, therefore it is preferable to use the latest compiler versions whenever possible. If the compiler version does not support the specific feature set (for example, the Intel® AVX instruction set), the build process gracefully degrades to whatever latest feature set is supported by the compiler. Since the build and runtime targets may not be the same, the resulting binary also contains a platform check that runs before the main() function and checks if the current machine is suitable for running the binary. Along with compiler optimizations, a set of preprocessor defines are automatically added to the build process (regardless of the compiler version). These defines correspond to the instruction sets that the target CPU should be able to support. For example, a binary compiled for any SSE4.2-capable processor will have RTE_MACHINE_CPUFLAG_SSE4_2 defined, thus enabling compile-time code path selection for different platforms. ================================================ FILE: doc/guides/rel_notes/deprecation.rst ================================================ ABI and API Deprecation ======================= See the :doc:`guidelines document for details of the ABI policy `. API and ABI deprecation notices are to be posted here. Deprecation Notices ------------------- * Significant ABI changes are planned for struct rte_eth_dev to support up to 1024 queues per port. This change will be in release 2.2. There is no backward compatibility planned from release 2.2. All binaries will need to be rebuilt from release 2.2. * ABI changes are planned for struct rte_intr_handle, struct rte_eth_conf and struct eth_dev_ops to support interrupt mode feature from release 2.1. Those changes may be enabled in the release 2.1 with CONFIG_RTE_NEXT_ABI. * The EAL function rte_eal_pci_close_one is deprecated because renamed to rte_eal_pci_detach. * The Macros RTE_HASH_BUCKET_ENTRIES_MAX and RTE_HASH_KEY_LENGTH_MAX are deprecated and will be removed with version 2.2. * The function rte_jhash2 is deprecated and should be removed. * The field mem_location of the rte_lpm structure is deprecated and should be removed as well as the macros RTE_LPM_HEAP and RTE_LPM_MEMZONE. * Significant ABI changes are planned for struct rte_mbuf, struct rte_kni_mbuf, and several ``PKT_RX_`` flags will be removed, to support unified packet type from release 2.1. Those changes may be enabled in the upcoming release 2.1 with CONFIG_RTE_NEXT_ABI. * librte_malloc library has been integrated into librte_eal. The 2.1 release creates a dummy/empty malloc library to fulfill binaries with dynamic linking dependencies on librte_malloc.so. Such dummy library will not be created from release 2.2 so binaries will need to be rebuilt. * The following fields have been deprecated in rte_eth_stats: imissed, ibadcrc, ibadlen, imcasts, fdirmatch, fdirmiss, tx_pause_xon, rx_pause_xon, tx_pause_xoff, rx_pause_xoff * API for flow director filters has been replaced by rte_eth_dev_filter_ctrl. Following old API is deprecated and will be removed with version 2.2 without backward compatibility. Functions: rte_eth_dev_fdir_*. Structures: rte_fdir_*, rte_eth_fdir. Enums: rte_l4type, rte_iptype. * ABI changes are planned for struct rte_eth_fdir_flow_ext in order to support flow director filtering in VF. The release 2.1 does not contain these ABI changes, but release 2.2 will, and no backwards compatibility is planned. * ABI change is planned to extend the SCTP flow's key input from release 2.1. The change may be enabled in the release 2.1 with CONFIG_RTE_NEXT_ABI. * ABI changes are planned for struct rte_eth_fdir_filter and rte_eth_fdir_masks in order to support new flow director modes, MAC VLAN and Cloud, on x550. The MAC VLAN mode means the MAC and VLAN are monitored. The Cloud mode is for VxLAN and NVGRE, and the tunnel type, TNI/VNI, inner MAC and inner VLAN are monitored. The release 2.2 will contain these changes without backwards compatibility. * librte_kni: Functions based on port id are deprecated for a long time and should be removed (rte_kni_create, rte_kni_get_port_id and rte_kni_info_get). * librte_pmd_ring: The deprecated functions rte_eth_ring_pair_create and rte_eth_ring_pair_attach should be removed. * ABI changes are planned for struct virtio_net in order to support vhost-user multiple queues feature. It should be integrated in release 2.2 without backward compatibility. * The scheduler hierarchy structure (rte_sched_port_hierarchy) will change to allow for a larger number of subport entries. The number of available traffic_classes and queues may also change. The mbuf structure element for sched hierarchy will also change from a single 32 bit to a 64 bit structure. * The scheduler statistics structure will change to allow keeping track of RED actions. * librte_acl: The structure rte_acl_ipv4vlan_rule is deprecated and should be removed as well as the associated functions rte_acl_ipv4vlan_add_rules and rte_acl_ipv4vlan_build. * librte_cfgfile: In order to allow for longer names and values, the value of macros CFG_NAME_LEN and CFG_NAME_VAL will be increased. Most likely, the new values will be 64 and 256, respectively. * librte_port: Macros to access the packet meta-data stored within the packet buffer will be adjusted to cover the packet mbuf structure as well, as currently they are able to access any packet buffer location except the packet mbuf structure. * librte_table LPM: A new parameter to hold the table name will be added to the LPM table parameter structure. * librte_table: New functions for table entry bulk add/delete will be added to the table operations structure. * librte_table hash: Key mask parameter will be added to the hash table parameter structure for 8-byte key and 16-byte key extendible bucket and LRU tables. * librte_pipeline: The prototype for the pipeline input port, output port and table action handlers will be updated: the pipeline parameter will be added, the packets mask parameter will be either removed (for input port action handler) or made input-only. ================================================ FILE: doc/guides/rel_notes/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK Release Notes ================== |today| Contents .. toctree:: :maxdepth: 1 :numbered: rel_description release_2_1 release_2_0 release_1_8 supported_os known_issues deprecation ================================================ FILE: doc/guides/rel_notes/known_issues.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Known Issues and Limitations in Legacy Releases =============================================== This section describes known issues with the DPDK software that aren't covered in the version specific release notes sections. Unit Test for Link Bonding may fail at test_tlb_tx_burst() ---------------------------------------------------------- **Description**: Unit tests will fail in ``test_tlb_tx_burst()`` function with error for uneven distribution of packets. **Implication**: Unit test link_bonding_autotest will fail. **Resolution/Workaround**: There is no workaround available. **Affected Environment/Platform**: Fedora 20. **Driver/Module**: Link Bonding. Pause Frame Forwarding does not work properly on igb ---------------------------------------------------- **Description**: For igb devices rte_eth_flow_ctrl_set does not work as expected. Pause frames are always forwarded on igb, regardless of the ``RFCE``, ``MPMCF`` and ``DPF`` registers. **Implication**: Pause frames will never be rejected by the host on 1G NICs and they will always be forwarded. **Resolution/Workaround**: There is no workaround available. **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). In packets provided by the PMD, some flags are missing ------------------------------------------------------ **Description**: In packets provided by the PMD, some flags are missing. The application does not have access to information provided by the hardware (packet is broadcast, packet is multicast, packet is IPv4 and so on). **Implication**: The ``ol_flags`` field in the ``rte_mbuf`` structure is not correct and should not be used. **Resolution/Workaround**: The application has to parse the Ethernet header itself to get the information, which is slower. **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). The rte_malloc library is not fully implemented ----------------------------------------------- **Description**: The ``rte_malloc`` library is not fully implemented. **Implication**: All debugging features of rte_malloc library described in architecture documentation are not yet implemented. **Resolution/Workaround**: No workaround available. **Affected Environment/Platform**: All. **Driver/Module**: ``rte_malloc``. HPET reading is slow -------------------- **Description**: Reading the HPET chip is slow. **Implication**: An application that calls ``rte_get_hpet_cycles()`` or ``rte_timer_manage()`` runs slower. **Resolution/Workaround**: The application should not call these functions too often in the main loop. An alternative is to use the TSC register through ``rte_rdtsc()`` which is faster, but specific to an lcore and is a cycle reference, not a time reference. **Affected Environment/Platform**: All. **Driver/Module**: Environment Abstraction Layer (EAL). HPET timers do not work on the Osage customer reference platform ---------------------------------------------------------------- **Description**: HPET timers do not work on the Osage customer reference platform which includes an Intel® Xeon® processor 5500 series processor) using the released BIOS from Intel. **Implication**: On Osage boards, the implementation of the ``rte_delay_us()`` function must be changed to not use the HPET timer. **Resolution/Workaround**: This can be addressed by building the system with the ``CONFIG_RTE_LIBEAL_USE_HPET=n`` configuration option or by using the ``--no-hpet`` EAL option. **Affected Environment/Platform**: The Osage customer reference platform. Other vendor platforms with Intel® Xeon® processor 5500 series processors should work correctly, provided the BIOS supports HPET. **Driver/Module**: ``lib/librte_eal/common/include/rte_cycles.h`` Not all variants of supported NIC types have been used in testing ----------------------------------------------------------------- **Description**: The supported network interface cards can come in a number of variants with different device ID's. Not all of these variants have been tested with the Intel® DPDK. The NIC device identifiers used during testing: * Intel® Ethernet Controller XL710 for 40GbE QSFP+ [8086:1584] * Intel® Ethernet Controller XL710 for 40GbE QSFP+ [8086:1583] * Intel® Ethernet Controller X710 for 10GbE SFP+ [8086:1572] * Intel® 82576 Gigabit Ethernet Controller [8086:10c9] * Intel® 82576 Quad Copper Gigabit Ethernet Controller [8086:10e8] * Intel® 82580 Dual Copper Gigabit Ethernet Controller [8086:150e] * Intel® I350 Quad Copper Gigabit Ethernet Controller [8086:1521] * Intel® 82599 Dual Fibre 10 Gigabit Ethernet Controller [8086:10fb] * Intel® Ethernet Server Adapter X520-T2 [8086: 151c] * Intel® Ethernet Controller X540-T2 [8086:1528] * Intel® 82574L Gigabit Network Connection [8086:10d3] * Emulated Intel® 82540EM Gigabit Ethernet Controller [8086:100e] * Emulated Intel® 82545EM Gigabit Ethernet Controller [8086:100f] * Intel® Ethernet Server Adapter X520-4 [8086:154a] * Intel® Ethernet Controller I210 [8086:1533] **Implication**: Risk of issues with untested variants. **Resolution/Workaround**: Use tested NIC variants. For those supported Ethernet controllers, additional device IDs may be added to the software if required. **Affected Environment/Platform**: All. **Driver/Module**: Poll-mode drivers Multi-process sample app requires exact memory mapping ------------------------------------------------------ **Description**: The multi-process example application assumes that it is possible to map the hugepage memory to the same virtual addresses in client and server applications. Occasionally, very rarely with 64-bit, this does not occur and a client application will fail on startup. The Linux "address-space layout randomization" security feature can sometimes cause this to occur. **Implication**: A multi-process client application fails to initialize. **Resolution/Workaround**: See the "Multi-process Limitations" section in the Intel® DPDK Programmer's Guide for more information. **Affected Environment/Platform**: All. **Driver/Module**: Multi-process example application Packets are not sent by the 1 GbE/10 GbE SR-IOV driver when the source MAC is not the MAC assigned to the VF NIC ---------------------------------------------------------------------------------------------------------------- **Description**: The 1 GbE/10 GbE SR-IOV driver can only send packets when the Ethernet header's source MAC address is the same as that of the VF NIC. The reason for this is that the Linux ``ixgbe`` driver module in the host OS has its anti-spoofing feature enabled. **Implication**: Packets sent using the 1 GbE/10 GbE SR-IOV driver must have the source MAC address correctly set to that of the VF NIC. Packets with other source address values are dropped by the NIC if the application attempts to transmit them. **Resolution/Workaround**: Configure the Ethernet source address in each packet to match that of the VF NIC. **Affected Environment/Platform**: All. **Driver/Module**: 1 GbE/10 GbE VF Poll Mode Driver (PMD). SR-IOV drivers do not fully implement the rte_ethdev API -------------------------------------------------------- **Description**: The SR-IOV drivers only supports the following rte_ethdev API functions: * rte_eth_dev_configure() * rte_eth_tx_queue_setup() * rte_eth_rx_queue_setup() * rte_eth_dev_info_get() * rte_eth_dev_start() * rte_eth_tx_burst() * rte_eth_rx_burst() * rte_eth_dev_stop() * rte_eth_stats_get() * rte_eth_stats_reset() * rte_eth_link_get() * rte_eth_link_get_no_wait() **Implication**: Calling an unsupported function will result in an application error. **Resolution/Workaround**: Do not use other rte_ethdev API functions in applications that use the SR-IOV drivers. **Affected Environment/Platform**: All. **Driver/Module**: VF Poll Mode Driver (PMD). PMD does not work with --no-huge EAL command line parameter ----------------------------------------------------------- **Description**: Currently, the DPDK does not store any information about memory allocated by ``malloc()` (for example, NUMA node, physical address), hence PMD drivers do not work when the ``--no-huge`` command line parameter is supplied to EAL. **Implication**: Sending and receiving data with PMD will not work. **Resolution/Workaround**: Use huge page memory or use VFIO to map devices. **Affected Environment/Platform**: Systems running the DPDK on Linux **Driver/Module**: Poll Mode Driver (PMD). Some hardware off-load functions are not supported by the VF Driver ------------------------------------------------------------------- **Description**: Currently, configuration of the following items is not supported by the VF driver: * IP/UDP/TCP checksum offload * Jumbo Frame Receipt * HW Strip CRC **Implication**: Any configuration for these items in the VF register will be ignored. The behavior is dependent on the current PF setting. **Resolution/Workaround**: For the PF (Physical Function) status on which the VF driver depends, there is an option item under PMD in the config file. For others, the VF will keep the same behavior as PF setting. **Affected Environment/Platform**: All. **Driver/Module**: VF (SR-IOV) Poll Mode Driver (PMD). Kernel crash on IGB port unbinding ---------------------------------- **Description**: Kernel crash may occur when unbinding 1G ports from the igb_uio driver, on 2.6.3x kernels such as shipped with Fedora 14. **Implication**: Kernel crash occurs. **Resolution/Workaround**: Use newer kernels or do not unbind ports. **Affected Environment/Platform**: 2.6.3x kernels such as shipped with Fedora 14 **Driver/Module**: IGB Poll Mode Driver (PMD). Twinpond and Ironpond NICs do not report link status correctly -------------------------------------------------------------- **Description**: Twin Pond/Iron Pond NICs do not bring the physical link down when shutting down the port. **Implication**: The link is reported as up even after issuing ``shutdown`` command unless the cable is physically disconnected. **Resolution/Workaround**: None. **Affected Environment/Platform**: Twin Pond and Iron Pond NICs **Driver/Module**: Poll Mode Driver (PMD). Discrepancies between statistics reported by different NICs ----------------------------------------------------------- **Description**: Gigabit Ethernet devices from Intel include CRC bytes when calculating packet reception statistics regardless of hardware CRC stripping state, while 10-Gigabit Ethernet devices from Intel do so only when hardware CRC stripping is disabled. **Implication**: There may be a discrepancy in how different NICs display packet reception statistics. **Resolution/Workaround**: None **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). Error reported opening files on DPDK initialization --------------------------------------------------- **Description**: On DPDK application startup, errors may be reported when opening files as part of the initialization process. This occurs if a large number, for example, 500 or more, or if hugepages are used, due to the per-process limit on the number of open files. **Implication**: The DPDK application may fail to run. **Resolution/Workaround**: If using 2 MB hugepages, consider switching to a fewer number of 1 GB pages. Alternatively, use the ``ulimit`` command to increase the number of files which can be opened by a process. **Affected Environment/Platform**: All. **Driver/Module**: Environment Abstraction Layer (EAL). Intel® QuickAssist Technology sample application does not work on a 32-bit OS on Shumway ---------------------------------------------------------------------------------------- **Description**: The Intel® Communications Chipset 89xx Series device does not fully support NUMA on a 32-bit OS. Consequently, the sample application cannot work properly on Shumway, since it requires NUMA on both nodes. **Implication**: The sample application cannot work in 32-bit mode with emulated NUMA, on multi-socket boards. **Resolution/Workaround**: There is no workaround available. **Affected Environment/Platform**: Shumway **Driver/Module**: All. IEEE1588 support possibly not working with an Intel® Ethernet Controller I210 NIC --------------------------------------------------------------------------------- **Description**: IEEE1588 support is not working with an Intel® Ethernet Controller I210 NIC. **Implication**: IEEE1588 packets are not forwarded correctly by the Intel® Ethernet Controller I210 NIC. **Resolution/Workaround**: There is no workaround available. **Affected Environment/Platform**: All. **Driver/Module**: IGB Poll Mode Driver Differences in how different Intel NICs handle maximum packet length for jumbo frame ------------------------------------------------------------------------------------ **Description**: 10 Gigabit Ethernet devices from Intel do not take VLAN tags into account when calculating packet size while Gigabit Ethernet devices do so for jumbo frames. **Implication**: When receiving packets with VLAN tags, the actual maximum size of useful payload that Intel Gigabit Ethernet devices are able to receive is 4 bytes (or 8 bytes in the case of packets with extended VLAN tags) less than that of Intel 10 Gigabit Ethernet devices. **Resolution/Workaround**: Increase the configured maximum packet size when using Intel Gigabit Ethernet devices. **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). Binding PCI devices to igb_uio fails on Linux kernel 3.9 when more than one device is used ------------------------------------------------------------------------------------------ **Description**: A known bug in the uio driver included in Linux kernel version 3.9 prevents more than one PCI device to be bound to the igb_uio driver. **Implication**: The Poll Mode Driver (PMD) will crash on initialization. **Resolution/Workaround**: Use earlier or later kernel versions, or apply the following `patch `_. **Affected Environment/Platform**: Linux systems with kernel version 3.9 **Driver/Module**: igb_uio module GCC might generate Intel® AVX instructions for processors without Intel® AVX support ------------------------------------------------------------------------------------ **Description**: When compiling Intel® DPDK (and any DPDK app), gcc may generate Intel® AVX instructions, even when the processor does not support Intel® AVX. **Implication**: Any DPDK app might crash while starting up. **Resolution/Workaround**: Either compile using icc or set ``EXTRA_CFLAGS='-O3'`` prior to compilation. **Affected Environment/Platform**: Platforms which processor does not support Intel® AVX. **Driver/Module**: Environment Abstraction Layer (EAL). Ethertype filter could receive other packets (non-assigned) in Niantic ---------------------------------------------------------------------- **Description**: On Intel® Ethernet Controller 82599EB When Ethertype filter (priority enable) was set, unmatched packets also could be received on the assigned queue, such as ARP packets without 802.1q tags or with the user priority not equal to set value. Launch the testpmd by disabling RSS and with multiply queues, then add the ethertype filter like the following and then start forwarding:: add_ethertype_filter 0 ethertype 0x0806 priority enable 3 queue 2 index 1 When sending ARP packets without 802.1q tag and with user priority as non-3 by tester, all the ARP packets can be received on the assigned queue. **Implication**: The user priority comparing in Ethertype filter cannot work probably. It is a NIC's issue due to the following: "In fact, ETQF.UP is not functional, and the information will be added in errata of 82599 and X540." **Resolution/Workaround**: None **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). Cannot set link speed on Intel® 40G Ethernet controller ------------------------------------------------------- **Description**: On Intel® 40G Ethernet Controller you cannot set the link to specific speed. **Implication**: The link speed cannot be changed forcibly, though it can be configured by application. **Resolution/Workaround**: None **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). Stopping the port does not down the link on Intel® 40G Ethernet controller -------------------------------------------------------------------------- **Description**: On Intel® 40G Ethernet Controller stopping the port does not really down the port link. **Implication**: The port link will be still up after stopping the port. **Resolution/Workaround**: None **Affected Environment/Platform**: All. **Driver/Module**: Poll Mode Driver (PMD). Devices bound to igb_uio with VT-d enabled do not work on Linux kernel 3.15-3.17 -------------------------------------------------------------------------------- **Description**: When VT-d is enabled (``iommu=pt intel_iommu=on``), devices are 1:1 mapped. In the Linux kernel unbinding devices from drivers removes that mapping which result in IOMMU errors. Introduced in Linux `kernel 3.15 commit `_, solved in Linux `kernel 3.18 commit `_. **Implication**: Devices will not be allowed to access memory, resulting in following kernel errors:: dmar: DRHD: handling fault status reg 2 dmar: DMAR:[DMA Read] Request device [02:00.0] fault addr a0c58000 DMAR:[fault reason 02] Present bit in context entry is clear **Resolution/Workaround**: Use earlier or later kernel versions, or avoid driver binding on boot by blacklisting the driver modules. I.e., in the case of ``ixgbe``, we can pass the kernel command line option: ``modprobe.blacklist=ixgbe``. This way we do not need to unbind the device to bind it to igb_uio. **Affected Environment/Platform**: Linux systems with kernel versions 3.15 to 3.17. **Driver/Module**: ``igb_uio`` module. VM power manager may not work on systems with more than 64 cores ---------------------------------------------------------------- **Description**: When using VM power manager on a system with more than 64 cores, VM(s) should not use cores 64 or higher. **Implication**: VM power manager should not be used with VM(s) that are using cores 64 or above. **Resolution/Workaround**: Do not use cores 64 or above. **Affected Environment/Platform**: Platforms with more than 64 cores. **Driver/Module**: VM power manager application. ================================================ FILE: doc/guides/rel_notes/rel_description.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Description of Release ====================== This document contains the release notes for Data Plane Development Kit (DPDK) release version |release| and previous releases. It lists new features, fixed bugs, API and ABI changes and known issues. For instructions on compiling and running the release, see the :ref:`DPDK Getting Started Guide `. ================================================ FILE: doc/guides/rel_notes/release_1_8.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK Release 1.8 ================ New Features ------------ * Link Bonding * Support for 802.3ad link aggregation (mode 4) and transmit load balancing (mode 5) to the link bonding library. * Support for registration of link status change callbacks with link bonding devices. * Support for slaves devices which do not support link status change interrupts in the link bonding library via a link status polling mechanism. * Poll Mode Driver - 40 GbE Controllers (librte_pmd_i40e) * Support for Flow Director * Support for ethertype filter * Support RSS in VF * Support configuring redirection table with different size from 1GbE and 10 GbE - 128/512 entries of 40GbE PF - 64 entries of 40GbE VF * Support configuring hash functions * Support for VXLAN packet on Intel® 40GbE Controllers * Packet Distributor Sample Application ================================================ FILE: doc/guides/rel_notes/release_2_0.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK Release 2.0 ================ New Features ------------ * Poll-mode driver support for an early release of the PCIE host interface of the Intel(R) Ethernet Switch FM10000. * Basic Rx/Tx functions for PF/VF * Interrupt handling support for PF/VF * Per queue start/stop functions for PF/VF * Support Mailbox handling between PF/VF and PF/Switch Manager * Receive Side Scaling (RSS) for PF/VF * Scatter receive function for PF/VF * Reta update/query for PF/VF * VLAN filter set for PF * Link status query for PF/VF .. note:: The software is intended to run on pre-release hardware and may contain unknown or unresolved defects or issues related to functionality and performance. The poll mode driver is also pre-release and will be updated to a released version post hardware and base driver release. Should the official hardware release be made between DPDK releases an updated poll-mode driver will be made available. * Link Bonding * Support for adaptive load balancing (mode 6) to the link bonding library. * Support for registration of link status change callbacks with link bonding devices. * Support for slaves devices which do not support link status change interrupts in the link bonding library via a link status polling mechanism. * PCI Hotplug with NULL PMD sample application * ABI versioning * x32 ABI * Non-EAL Thread Support * Multi-pthread Support * Re-order Library * ACL for AVX2 * Architecture Independent CRC Hash * uio_pci_generic Support * KNI Optimizations * Vhost-user support * Virtio (link, vlan, mac, port IO, perf) * IXGBE-VF RSS * RX/TX Callbacks * Unified Flow Types * Indirect Attached MBUF Flag * Use default port configuration in TestPMD * Tunnel offloading in TestPMD * Poll Mode Driver - 40 GbE Controllers (librte_pmd_i40e) * Support for Flow Director * Support for ethertype filter * Support RSS in VF * Support configuring redirection table with different size from 1GbE and 10 GbE - 128/512 entries of 40GbE PF - 64 entries of 40GbE VF * Support configuring hash functions * Support for VXLAN packet on Intel® 40GbE Controllers * Poll Mode Driver for Mellanox ConnectX-3 EN adapters (mlx4) .. note:: This PMD is only available for Linux and is disabled by default due to external dependencies (libibverbs and libmlx4). Please refer to the NIC drivers guide for more information. * Packet Distributor Sample Application * Job Stats library and Sample Application. * Enhanced Jenkins hash (jhash) library .. note:: The hash values returned by the new jhash library are different from the ones returned by the previous library. ================================================ FILE: doc/guides/rel_notes/release_2_1.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK Release 2.1 ================ New Features ------------ * **Enabled cloning of indirect mbufs.** This feature removes a limitation of ``rte_pktmbuf_attach()`` which generated the warning: "mbuf we're attaching to must be direct". Now, when attaching to an indirect mbuf it is possible to: * Copy all relevant fields (address, length, offload, ...) as before. * Get the pointer to the mbuf that embeds the data buffer (direct mbuf), and increase the reference counter. When detaching the mbuf, we can now retrieve this direct mbuf as the pointer is determined from the buffer address. * **Extended packet type support.** In previous releases mbuf packet types were indicated by 6 bits in the ``ol_flags``. This was not enough for some supported NICs. For example i40e hardware can recognize more than 150 packet types. Not being able to identify these additional packet types limits access to hardware offload capabilities So an extended "unified" packet type was added to support all possible PMDs. The 16 bit packet_type in the mbuf structure was changed to 32 bits and used for this purpose. To avoid breaking ABI compatibility, the code changes for this feature are enclosed in a ``RTE_NEXT_ABI`` ifdef. This is enabled by default but can be turned off for ABI compatibility with DPDK R2.0. * **Reworked memzone to be allocated by malloc and also support freeing.** In the memory hierarchy, memsegs are groups of physically contiguous hugepages, memzones are slices of memsegs, and malloc slices memzones into smaller memory chunks. This feature modifies ``malloc()`` so it partitions memsegs instead of memzones. Now memzones allocate their memory from the malloc heap. Backward compatibility with API and ABI are maintained. This allow memzones, and any other structure based on memzones, for example mempools, to be freed. Currently only the API from freeing memzones is supported. * **Interrupt mode PMD.** This feature introduces a low-latency one-shot RX interrupt into DPDK. It also adds a polling and interrupt mode switch control example. DPDK userspace interrupt notification and handling mechanism is based on UIO/VFIO with the following limitations: * Per queue RX interrupt events are only allowed in VFIO which supports multiple MSI-X vectors. * In UIO, the RX interrupt shares the same vector with other interrupts. When the RX interrupt and LSC interrupt are both enabled, only the former is available. * RX interrupt is only implemented for the linuxapp target. * The feature is only currently enabled for tow PMDs: ixgbe and igb. * **Packet Framework enhancements.** Several enhancements were made to the Packet Framework: * A new configuration file syntax has been introduced for IP pipeline applications. Parsing of the configuration file is changed. * Implementation of the IP pipeline application is modified to make it more structured and user friendly. * Implementation of the command line interface (CLI) for each pipeline type has been moved to the separate compilation unit. Syntax of pipeline CLI commands has been changed. * Initialization of IP pipeline is modified to match the new parameters structure. * New implementation of pass-through pipeline, firewall pipeline, routing pipeline, and flow classification has been added. * Master pipeline with CLI interface has been added. * Added extended documentation of the IP Pipeline. * **Added API for IEEE1588 timestamping.** This feature adds an ethdev API to enable, disable and read IEEE1588/802.1AS PTP timestamps from devices that support it. The following functions were added: * ``rte_eth_timesync_enable()`` * ``rte_eth_timesync_disable()`` * ``rte_eth_timesync_read_rx_timestamp()`` * ``rte_eth_timesync_read_tx_timestamp()`` The "ieee1588" forwarding mode in testpmd was also refactored to demonstrate the new API. * **Added multicast address filtering.** Added multicast address filtering via a new ethdev function ``set_mc_addr_list()``. This overcomes a limitation in previous releases where the receipt of multicast packets on a given port could only be enabled by invoking the ``rte_eth_allmulticast_enable()`` function. This method did not work for VFs in SR-IOV architectures when the host PF driver does not allow these operation on VFs. In such cases, joined multicast addresses had to be added individually to the set of multicast addresses that are filtered by the [VF] port. * **Added Flow Director extensions.** Several Flow Director extensions were added such as: * Support for RSS and Flow Director hashes in vector RX. * Added Flow Director for L2 payload. * **Added RSS hash key size query per port.** This feature supports querying the RSS hash key size of each port. A new field ``hash_key_size`` has been added in the ``rte_eth_dev_info`` struct for storing hash key size in bytes. * **Added userspace ethtool support.** Added userspace ethtool support to provide a familiar interface for applications that manage devices via kernel-space ``ethtool_op`` and ``net_device_op``. The initial implementation focuses on operations that can be implemented through existing ``netdev`` APIs. More operations will be supported in later releases. * **Updated the ixgbe base driver.** The ixgbe base driver was updated with several changes including the following: * Added a new 82599 device id. * Added new X550 PHY ids. * Added SFP+ dual-speed support. * Added wait helper for X550 IOSF accesses. * Added X550em features. * Added X557 PHY LEDs support. * Commands for flow director. * Issue firmware command when resetting X550em. See the git log for full details of the ixgbe/base changes. * **Added additional hotplug support.** Port hotplug support was added to the following PMDs: * e1000/igb. * ixgbe. * i40e. * fm10k. * ring. * bonding. * virtio. Port hotplug support was added to BSD. * **Added ixgbe LRO support.** Added LRO support for x540 and 82599 devices. * **Added extended statistics for ixgbe.** Implemented ``xstats_get()`` and ``xstats_reset()`` in dev_ops for ixgbe to expose detailed error statistics to DPDK applications. These will be implemented for other PMDs in later releases. * **Added proc_info application.** Created a new ``proc_info`` application, by refactoring the existing ``dump_cfg`` application, to demonstrate the usage of retrieving statistics, and the new extended statistics (see above), for DPDK interfaces. * **Updated the i40e base driver.** The i40e base driver was updated with several changes including the following: * Support for building both PF and VF driver together. * Support for CEE DCBX on recent firmware versions. * Replacement of ``i40e_debug_read_register()``. * Rework of ``i40e_hmc_get_object_va``. * Update of shadow RAM read/write functions. * Enhancement of polling NVM semaphore. * Enhancements on adminq init and sending asq command. * Update of get/set LED functions. * Addition of AOC phy types to case statement in get_media_type. * Support for iSCSI capability. * Setting of FLAG_RD when sending driver version to FW. See the git log for full details of the i40e/base changes. * **Added support for port mirroring in i40e.** Enabled mirror functionality in the i40e driver. * **Added support for i40e double VLAN, QinQ, stripping and insertion.** Added support to the i40e driver for offloading double VLAN (QinQ) tags to the mbuf header, and inserting double vlan tags by hardware to the packets to be transmitted. Added a new field ``vlan_tci_outer`` in the ``rte_mbuf`` struct, and new flags in ``ol_flags`` to support this feature. * **Added fm10k promiscuous mode support.** Added support for promiscuous/allmulticast enable and disable in the fm10k PF function. VF is not supported yet. * **Added fm10k jumbo frame support.** Added support for jumbo frame less than 15K in both VF and PF functions in the fm10k pmd. * **Added fm10k mac vlan filtering support.** Added support for the fm10k MAC filter, only available in PF. Updated the VLAN filter to add/delete one static entry in the MAC table for each combination of VLAN and MAC address. * **Added support for the Broadcom bnx2x driver.** Added support for the Broadcom NetXtreme II bnx2x driver. It is supported only on Linux 64-bit and disabled by default. * **Added support for the Chelsio CXGBE driver.** Added support for the CXGBE Poll Mode Driver for the Chelsio Terminator 5 series of 10G/40G adapters. * **Enhanced support for Mellanox ConnectX-3 driver (mlx4).** * Support Mellanox OFED 3.0. * Improved performance for both RX and TX operations. * Better link status information. * Outer L3/L4 checksum offload support. * Inner L3/L4 checksum offload support for VXLAN. * **Enabled VMXNET3 vlan filtering.** Added support for the VLAN filter functionality of the VMXNET3 interface. * **Added support for vhost live migration.** Added support to allow live migration of vhost. Without this feature, qemu will report the following error: "migrate: Migration disabled: vhost lacks VHOST_F_LOG_ALL feature". * **Added support for pcap jumbo frames.** Extended the PCAP PMD to support jumbo frames for RX and TX. * **Added support for the TILE-Gx architecture.** Added support for the EZchip TILE-Gx family of SoCs. * **Added hardware memory transactions/lock elision for x86.** Added the use of hardware memory transactions (HTM) on fast-path for rwlock and spinlock (a.k.a. lock elision). The methods are implemented for x86 using Restricted Transactional Memory instructions (Intel(r) Transactional Synchronization Extensions). The implementation fall-backs to the normal rwlock if HTM is not available or memory transactions fail. This is not a replacement for all rwlock usages since not all critical sections protected by locks are friendly to HTM. For example, an attempt to perform a HW I/O operation inside a hardware memory transaction always aborts the transaction since the CPU is not able to roll-back should the transaction fail. Therefore, hardware transactional locks are not advised to be used around ``rte_eth_rx_burst()`` and ``rte_eth_tx_burst()`` calls. * **Updated Jenkins Hash function** Updated the version of the Jenkins Hash (jhash) function used in DPDK from the 1996 version to the 2006 version. This gives up to 35% better performance, compared to the original one. Note, the hashes generated by the updated version differ from the hashes generated by the previous version. * **Added software implementation of the Toeplitz RSS hash** Added a software implementation of the Toeplitz hash function used by RSS. It can be used either for packet distribution on a single queue NIC or for simulating RSS computation on a specific NIC (for example after GRE header de-encapsulation). * **Replaced the existing hash library with a Cuckoo hash implementation.** Replaced the existing hash library with another approach, using the Cuckoo Hash method to resolve collisions (open addressing). This method pushes items from a full bucket when a new entry must be added to it, storing the evicted entry in an alternative location, using a secondary hash function. This gives the user the ability to store more entries when a bucket is full, in comparison with the previous implementation. The API has not been changed, although new fields have been added in the ``rte_hash`` structure, which has been changed to internal use only. The main change when creating a new table is that the number of entries per bucket is now fixed, so its parameter is ignored now (it is still there to maintain the same parameters structure). Also, the maximum burst size in lookup_burst function hash been increased to 64, to improve performance. * **Optimized KNI RX burst size computation.** Optimized KNI RX burst size computation by avoiding checking how many entries are in ``kni->rx_q`` prior to actually pulling them from the fifo. * **Added KNI multicast.** Enabled adding multicast addresses to KNI interfaces by adding an empty callback for ``set_rx_mode`` (typically used for setting up hardware) so that the ioctl succeeds. This is the same thing as the Linux tap interface does. * **Added cmdline polling mode.** Added the ability to process console input in the same thread as packet processing by using the ``poll()`` function. * **Added VXLAN Tunnel End point sample application.** Added a Tunnel End point (TEP) sample application that simulates a VXLAN Tunnel Endpoint (VTEP) termination in DPDK. It is used to demonstrate the offload and filtering capabilities of Intel XL710 10/40 GbE NICsfor VXLAN packets. * **Enabled combining of the ``-m`` and ``--no-huge`` EAL options.** Added option to allow combining of the ``-m`` and ``--no-huge`` EAL command line options. This allows user application to run as non-root but with higher memory allocations, and removes a constraint on ``--no-huge`` mode being limited to 64M. Resolved Issues --------------- * **acl: Fix ambiguity between test rules.** Some test rules had equal priority for the same category. That could cause an ambiguity in building the trie and test results. * **acl: Fix invalid rule wildness calculation for bitmask field type.** * **acl: Fix matching rule.** * **acl: Fix unneeded trie splitting for subset of rules.** When rebuilding a trie for limited rule-set, don't try to split the rule-set even further. * **app/testpmd: Fix crash when port id out of bound.** Fixed issues in testpmd where using a port greater than 32 would cause a seg fault. Fixes: edab33b1c01d ("app/testpmd: support port hotplug") * **app/testpmd: Fix reply to a multicast ICMP request.** Set the IP source and destination addresses in the IP header of the ICMP reply. * **app/testpmd: fix MAC address in ARP reply.** Fixed issue where in the ``icmpecho`` forwarding mode, ARP replies from testpmd contain invalid zero-filled MAC addresses. Fixes: 31db4d38de72 ("net: change arp header struct declaration") * **app/testpmd: fix default flow control values.** Fixes: 422a20a4e62d ("app/testpmd: fix uninitialized flow control variables") * **bonding: Fix crash when stopping inactive slave.** * **bonding: Fix device initialization error handling.** * **bonding: Fix initial link status of slave.** On Fortville NIC, link status change interrupt callback was not executed when slave in bonding was (re-)started. * **bonding: Fix socket id for LACP slave.** Fixes: 46fb43683679 ("bond: add mode 4") * **bonding: Fix device initialization error handling.** * **cmdline: Fix small memory leak.** A function in ``cmdline.c`` had a return that did not free the buf properly. * **config: Enable same drivers options for Linux and BSD.** Enabled vector ixgbe and i40e bulk alloc for BSD as it is already done for Linux. Fixes: 304caba12643 ("config: fix bsd options") Fixes: 0ff3324da2eb ("ixgbe: rework vector pmd following mbuf changes") * **devargs: Fix crash on failure.** This problem occurred when passing an invalid PCI id to the blacklist API in devargs. * **e1000/i40e: Fix descriptor done flag with odd address.** * **e1000/igb: fix ieee1588 timestamping initialization.** Fixed issue with e1000 ieee1588 timestamp initialization. On initialization the IEEE1588 functions read the system time to set their timestamp. However, on some 1G NICs, for example, i350, system time is disabled by default and the IEEE1588 timestamp was always 0. * **eal/bsd: Fix inappropriate header guards.** * **eal/bsd: Fix virtio on FreeBSD.** Closing the ``/dev/io`` fd caused a SIGBUS in inb/outb instructions as the process lost the IOPL privileges once the fd is closed. Fixes: 8a312224bcde ("eal/bsd: fix fd leak") * **eal/linux: Fix comments on vfio MSI.** * **eal/linux: Fix irq handling with igb_uio.** Fixed an issue where the the introduction of ``uio_pci_generic`` broke interrupt handling with igb_uio. Fixes: c112df6875a5 ("eal/linux: toggle interrupt for uio_pci_generic") * **eal/linux: Fix numa node detection.** * **eal/linux: Fix socket value for undetermined numa node.** Sets zero as the default value of pci device numa_node if the socket could not be determined. This provides the same default value as FreeBSD which has no NUMA support, and makes the return value of ``rte_eth_dev_socket_id()`` be consistent with the API description. * **eal/ppc: Fix cpu cycle count for little endian.** On IBM POWER8 PPC64 little endian architecture, the definition of tsc union will be different. This fix enables the right output from ``rte_rdtsc()``. * **ethdev: Fix check of threshold for TX freeing.** Fixed issue where the parameter to ``tx_free_thresh`` was not consistent between the drivers. * **ethdev: Fix crash if malloc of user callback fails.** If ``rte_zmalloc()`` failed in ``rte_eth_dev_callback_register`` then the NULL pointer would be dereferenced. * **ethdev: Fix illegal port access.** To obtain a detachable flag, ``pci_drv`` is accessed in ``rte_eth_dev_is_detachable()``. However ``pci_drv`` is only valid if port is enabled. Fixed by checking ``rte_eth_dev_is_valid_port()`` first. * **ethdev: Make tables const.** * **ethdev: Rename and extend the mirror type.** * **examples/distributor: Fix debug macro.** The macro to turn on additional debug output when the app was compiled with ``-DDEBUG`` was broken. Fixes: 07db4a975094 ("examples/distributor: new sample app") * **examples/kni: Fix crash on exit.** * **examples/vhost: Fix build with debug enabled.** Fixes: 72ec8d77ac68 ("examples/vhost: rework duplicated code") * **fm10k: Fix RETA table initialization.** The fm10k driver has 128 RETA entries in 32 registers, but it only initialized the first 32 when doing multiple RX queue configurations. This fix initializes all 128 entries. * **fm10k: Fix RX buffer size.** * **fm10k: Fix TX multi-segment frame.** * **fm10k: Fix TX queue cleaning after start error.** * **fm10k: Fix Tx queue cleaning after start error.** * **fm10k: Fix default mac/vlan in switch.** * **fm10k: Fix interrupt fault handling.** * **fm10k: Fix jumbo frame issue.** * **fm10k: Fix mac/vlan filtering.** * **fm10k: Fix maximum VF number.** * **fm10k: Fix maximum queue number for VF.** Both PF and VF shared code in function ``fm10k_stats_get()``. The function worked with PF, but had problems with VF since it has less queues than PF. Fixes: a6061d9e7075 ("fm10k: register PF driver") * **fm10k: Fix queue disabling.** * **fm10k: Fix switch synchronization.** * **i40e/base: Fix error handling of NVM state update.** * **i40e/base: Fix hardware port number for pass-through.** * **i40e/base: Rework virtual address retrieval for lan queue.** * **i40e/base: Update LED blinking.** * **i40e/base: Workaround for PHY type with firmware < 4.4.** * **i40e: Disable setting of PHY configuration.** * **i40e: Fix SCTP flow director.** * **i40e: Fix check of descriptor done flag.** Fixes: 4861cde46116 ("i40e: new poll mode driver") Fixes: 05999aab4ca6 ("i40e: add or delete flow director") * **i40e: Fix condition to get VMDQ info.** * **i40e: Fix registers access from big endian CPU.** * **i40evf: Clear command when error occurs.** * **i40evf: Fix RSS with less RX queues than TX queues.** * **i40evf: Fix crash when setup TX queues.** * **i40evf: Fix jumbo frame support.** * **i40evf: Fix offload capability flags.** Added checksum offload capability flags which have already been supported for a long time. * **ivshmem: Fix crash in corner case.** Fixed issues where depending on the configured segments it was possible to hit a segmentation fault as a result of decrementing an unsigned index with value 0. Fixes: 40b966a211ab ("ivshmem: library changes for mmaping using ivshmem") * **ixgbe/base: Fix SFP probing.** * **ixgbe/base: Fix TX pending clearing.** * **ixgbe/base: Fix X550 CS4227 address.** * **ixgbe/base: Fix X550 PCIe master disabling.** * **ixgbe/base: Fix X550 check.** * **ixgbe/base: Fix X550 init early return.** * **ixgbe/base: Fix X550 link speed.** * **ixgbe/base: Fix X550em CS4227 speed mode.** * **ixgbe/base: Fix X550em SFP+ link stability.** * **ixgbe/base: Fix X550em UniPHY link configuration.** * **ixgbe/base: Fix X550em flow control for KR backplane.** * **ixgbe/base: Fix X550em flow control to be KR only.** * **ixgbe/base: Fix X550em link setup without SFP.** * **ixgbe/base: Fix X550em mux after MAC reset.** Fixes: d2e72774e58c ("ixgbe/base: support X550") * **ixgbe/base: Fix bus type overwrite.** * **ixgbe/base: Fix init handling of X550em link down.** * **ixgbe/base: Fix lan id before first i2c access.** * **ixgbe/base: Fix mac type checks.** * **ixgbe/base: Fix tunneled UDP and TCP frames in flow director.** * **ixgbe: Check mbuf refcnt when clearing a ring.** The function to clear the TX ring when a port was being closed, e.g. on exit in testpmd, was not checking the mbuf refcnt before freeing it. Since the function in the vector driver to clear the ring after TX does not setting the pointer to NULL post-free, this caused crashes if mbuf debugging was turned on. * **ixgbe: Fix RX with buffer address not word aligned.** Niantic HW expects the Header Buffer Address in the RXD must be word aligned. * **ixgbe: Fix RX with buffer address not word aligned.** * **ixgbe: Fix Rx queue reset.** Fix to reset vector related RX queue fields to their initial values. Fixes: c95584dc2b18 ("ixgbe: new vectorized functions for Rx/Tx") * **ixgbe: Fix TSO in IPv6.** When TSO was used with IPv6, the generated frames were incorrect. The L4 frame was OK, but the length field of IPv6 header was not populated correctly. * **ixgbe: Fix X550 flow director check.** * **ixgbe: Fix check for split packets.** The check for split packets to be reassembled in the vector ixgbe PMD was incorrectly only checking the first 16 elements of the array instead of all 32. Fixes: cf4b4708a88a ("ixgbe: improve slow-path perf with vector scattered Rx") * **ixgbe: Fix data access on big endian cpu.** * **ixgbe: Fix flow director flexbytes offset.** Fixes: d54a9888267c ("ixgbe: support flexpayload configuration of flow director") * **ixgbe: Fix number of segments with vector scattered Rx.** Fixes: cf4b4708a88a (ixgbe: improve slow-path perf with vector scattered Rx) * **ixgbe: Fix offload config option name.** The RX_OLFLAGS option was renamed from DISABLE to ENABLE in the driver code and Linux config. It is now renamed also in the BSD config and documentation. Fixes: 359f106a69a9 ("ixgbe: prefer enabling olflags rather than not disabling") * **ixgbe: Fix release queue mbufs.** The calculations of what mbufs were valid in the RX and TX queues were incorrect when freeing the mbufs for the vector PMD. This led to crashes due to invalid reference counts when mbuf debugging was turned on, and possibly other more subtle problems (such as mbufs being freed when in use) in other cases. Fixes: c95584dc2b18 ("ixgbe: new vectorized functions for Rx/Tx") * **ixgbe: Move PMD specific fields out of base driver.** Move ``rx_bulk_alloc_allowed`` and ``rx_vec_allowed`` from ``ixgbe_hw`` to ``ixgbe_adapter``. Fixes: 01fa1d6215fa ("ixgbe: unify Rx setup") * **ixgbe: Rename TX queue release function.** * **ixgbevf: Fix RX function selection.** The logic to select ixgbe the VF RX function is different than the PF. * **ixgbevf: Fix link status for PF up/down events.** * **kni: Fix RX loop limit.** Loop processing packets dequeued from rx_q was using the number of packets requested, not how many it actually received. * **kni: Fix ioctl in containers, like Docker.** * **kni: Fix multicast ioctl handling.** * **log: Fix crash after log_history dump.** * **lpm: Fix big endian support.** * **lpm: Fix depth small entry add.** * **mbuf: Fix cloning with private mbuf data.** Added a new ``priv_size`` field in mbuf structure that should be initialized at mbuf pool creation. This field contains the size of the application private data in mbufs. Introduced new static inline functions ``rte_mbuf_from_indirect()`` and ``rte_mbuf_to_baddr()`` to replace the existing macros, which take the private size into account when attaching and detaching mbufs. * **mbuf: Fix data room size calculation in pool init.** Deduct the mbuf data room size from ``mempool->elt_size`` and ``priv_size``, instead of using an hardcoded value that is not related to the real buffer size. To use ``rte_pktmbuf_pool_init()``, the user can either: * Give a NULL parameter to rte_pktmbuf_pool_init(): in this case, the private size is assumed to be 0, and the room size is ``mp->elt_size`` - ``sizeof(struct rte_mbuf)``. * Give the ``rte_pktmbuf_pool_private`` filled with appropriate data_room_size and priv_size values. * **mbuf: Fix init when private size is not zero.** Allow the user to use the default ``rte_pktmbuf_init()`` function even if the mbuf private size is not 0. * **mempool: Add structure for object headers.** Each object stored in mempools are prefixed by a header, allowing for instance to retrieve the mempool pointer from the object. When debug is enabled, a cookie is also added in this header that helps to detect corruptions and double-frees. Introduced a structure that materializes the content of this header, and will simplify future patches adding things in this header. * **mempool: Fix pages computation to determine number of objects.** * **mempool: Fix returned value after counting objects.** Fixes: 148f963fb532 ("xen: core library changes") * **mlx4: Avoid requesting TX completion events to improve performance.** Instead of requesting a completion event for each TX burst, request it on a fixed schedule once every MLX4_PMD_TX_PER_COMP_REQ (currently 64) packets to improve performance. * **mlx4: Fix compilation as a shared library and on 32 bit platforms.** * **mlx4: Fix possible crash on scattered mbuf allocation failure.** Fixes issue where failing to allocate a segment, ``mlx4_rx_burst_sp()`` could call ``rte_pktmbuf_free()`` on an incomplete scattered mbuf whose next pointer in the last segment is not set. * **mlx4: Fix support for multiple vlan filters.** This fixes the "Multiple RX VLAN filters can be configured, but only the first one works" bug. * **pcap: Fix storage of name and type in queues.** pcap_rx_queue/pcap_tx_queue should store it's own copy of name/type values, not the pointer to temporary allocated space. * **pci: Fix memory leaks and needless increment of map address.** * **pci: Fix uio mapping differences between linux and bsd.** * **port: Fix unaligned access to metadata.** Fix RTE_MBUF_METADATA macros to allow for unaligned accesses to meta-data fields. * **ring: Fix return of new port id on creation.** * **timer: Fix race condition.** Eliminate problematic race condition in ``rte_timer_manage()`` that can lead to corruption of per-lcore pending-lists (implemented as skip-lists). * **vfio: Fix overflow of BAR region offset and size.** Fixes: 90a1633b2347 ("eal/Linux: allow to map BARs with MSI-X tables") * **vhost: Fix enqueue/dequeue to handle chained vring descriptors.** * **vhost: Fix race for connection fd.** * **vhost: Fix virtio freeze due to missed interrupt.** * **virtio: Fix crash if CQ is not negotiated.** Fix NULL dereference if virtio control queue is not negotiated. * **virtio: Fix ring size negotiation.** Negotiate the virtio ring size. The host may allow for very large rings but application may only want a smaller ring. Conversely, if the number of descriptors requested exceeds the virtio host queue size, then just silently use the smaller host size. This fixes issues with virtio in non-QEMU environments. For example Google Compute Engine allows up to 16K elements in ring. * **vmxnet3: Fix link state handling.** Known Issues ------------ * When running the ``vmdq`` sample or ``vhost`` sample applications with the Intel(R) XL710 (i40e) NIC, the configuration option ``CONFIG_RTE_MAX_QUEUES_PER_PORT`` should be increased from 256 to 1024. * VM power manager may not work on systems with more than 64 cores. API Changes ----------- * The order that user supplied RX and TX callbacks are called in has been changed to the order that they were added (fifo) in line with end-user expectations. The previous calling order was the reverse of this (lifo) and was counter intuitive for users. The actual API is unchanged. ABI Changes ----------- * The ``rte_hash`` structure has been changed to internal use only. ================================================ FILE: doc/guides/rel_notes/supported_os.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Supported Operating Systems =========================== The following Linux distributions were successfully used to compiler or run DPDK. * FreeBSD 10 * Fedora release 20 * Ubuntu 14.04 LTS * Wind River Linux 6 * Red Hat Enterprise Linux 6.5 * SUSE Enterprise Linux 11 SP3 These distributions may need additional packages that are not installed by default, or a specific kernel. Refer to the :ref:`Linux guide ` and :ref:`FreeBSD guide ` for details. ================================================ FILE: doc/guides/sample_app_ug/cmd_line.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Command Line Sample Application =============================== This chapter describes the Command Line sample application that is part of the Data Plane Development Kit (DPDK). Overview -------- The Command Line sample application is a simple application that demonstrates the use of the command line interface in the DPDK. This application is a readline-like interface that can be used to debug a DPDK application, in a Linux* application environment. .. note:: The rte_cmdline library should not be used in production code since it is not validated to the same standard as other Intel® DPDK libraries. See also the "rte_cmdline library should not be used in production code due to limited testing" item in the "Known Issues" section of the Release Notes. The Command Line sample application supports some of the features of the GNU readline library such as, completion, cut/paste and some other special bindings that make configuration and debug faster and easier. The application shows how the rte_cmdline application can be extended to handle a list of objects. There are three simple commands: * add obj_name IP: Add a new object with an IP/IPv6 address associated to it. * del obj_name: Delete the specified object. * show obj_name: Show the IP associated with the specified object. .. note:: To terminate the application, use **Ctrl-d**. Compiling the Application ------------------------- #. Go to example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/cmdline #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc Refer to the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- To run the application in linuxapp environment, issue the following command: .. code-block:: console $ ./build/cmdline -c f -n 4 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. EAL Initialization and cmdline Start ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The first task is the initialization of the Environment Abstraction Layer (EAL). This is achieved as follows: .. code-block:: c int main(int argc, char **argv) { ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); Then, a new command line object is created and started to interact with the user through the console: .. code-block:: c cl = cmdline_stdin_new(main_ctx, "example> "); cmdline_interact(cl); cmdline_stdin_exit(cl); The cmd line_interact() function returns when the user types **Ctrl-d** and in this case, the application exits. Defining a cmdline Context ~~~~~~~~~~~~~~~~~~~~~~~~~~ A cmdline context is a list of commands that are listed in a NULL-terminated table, for example: .. code-block:: c cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *) &cmd_obj_del_show, (cmdline_parse_inst_t *) &cmd_obj_add, (cmdline_parse_inst_t *) &cmd_help, NULL, }; Each command (of type cmdline_parse_inst_t) is defined statically. It contains a pointer to a callback function that is executed when the command is parsed, an opaque pointer, a help string and a list of tokens in a NULL-terminated table. The rte_cmdline application provides a list of pre-defined token types: * String Token: Match a static string, a list of static strings or any string. * Number Token: Match a number that can be signed or unsigned, from 8-bit to 32-bit. * IP Address Token: Match an IPv4 or IPv6 address or network. * Ethernet* Address Token: Match a MAC address. In this example, a new token type obj_list is defined and implemented in the parse_obj_list.c and parse_obj_list.h files. For example, the cmd_obj_del_show command is defined as shown below: .. code-block:: c struct cmd_obj_add_result { cmdline_fixed_string_t action; cmdline_fixed_string_t name; struct object *obj; }; static void cmd_obj_del_show_parsed(void *parsed_result, struct cmdline *cl, attribute ((unused)) void *data) { /* ... */ } cmdline_parse_token_string_t cmd_obj_action = TOKEN_STRING_INITIALIZER(struct cmd_obj_del_show_result, action, "show#del"); parse_token_obj_list_t cmd_obj_obj = TOKEN_OBJ_LIST_INITIALIZER(struct cmd_obj_del_show_result, obj, &global_obj_list); cmdline_parse_inst_t cmd_obj_del_show = { .f = cmd_obj_del_show_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "Show/del an object", .tokens = { /* token list, NULL terminated */ (void *)&cmd_obj_action, (void *)&cmd_obj_obj, NULL, }, }; This command is composed of two tokens: * The first token is a string token that can be show or del. * The second token is an object that was previously added using the add command in the global_obj_list variable. Once the command is parsed, the rte_cmdline application fills a cmd_obj_del_show_result structure. A pointer to this structure is given as an argument to the callback function and can be used in the body of this function. ================================================ FILE: doc/guides/sample_app_ug/dist_app.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Distributor Sample Application ============================== The distributor sample application is a simple example of packet distribution to cores using the Data Plane Development Kit (DPDK). Overview -------- The distributor application performs the distribution of packets that are received on an RX_PORT to different cores. When processed by the cores, the destination port of a packet is the port from the enabled port mask adjacent to the one on which the packet was received, that is, if the first four ports are enabled (port mask 0xf), ports 0 and 1 RX/TX into each other, and ports 2 and 3 RX/TX into each other. This application can be used to benchmark performance using the traffic generator as shown in the figure below. .. _figure_dist_perf: .. figure:: img/dist_perf.* Performance Benchmarking Setup (Basic Environment) Compiling the Application ------------------------- #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/distributor #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the DPDK Getting Started Guide for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- #. The application has a number of command line options: .. code-block:: console ./build/distributor_app [EAL options] -- -p PORTMASK where, * -p PORTMASK: Hexadecimal bitmask of ports to configure #. To run the application in linuxapp environment with 10 lcores, 4 ports, issue the command: .. code-block:: console $ ./build/distributor_app -c 0x4003fe -n 4 -- -p f #. Refer to the DPDK Getting Started Guide for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The distributor application consists of three types of threads: a receive thread (lcore_rx()), a set of worker threads(lcore_worker()) and a transmit thread(lcore_tx()). How these threads work together is shown in :numref:`figure_dist_app` below. The main() function launches threads of these three types. Each thread has a while loop which will be doing processing and which is terminated only upon SIGINT or ctrl+C. The receive and transmit threads communicate using a software ring (rte_ring structure). The receive thread receives the packets using rte_eth_rx_burst() and gives them to the distributor (using rte_distributor_process() API) which will be called in context of the receive thread itself. The distributor distributes the packets to workers threads based on the tagging of the packet - indicated by the hash field in the mbuf. For IP traffic, this field is automatically filled by the NIC with the "usr" hash value for the packet, which works as a per-flow tag. More than one worker thread can exist as part of the application, and these worker threads do simple packet processing by requesting packets from the distributor, doing a simple XOR operation on the input port mbuf field (to indicate the output port which will be used later for packet transmission) and then finally returning the packets back to the distributor in the RX thread. Meanwhile, the receive thread will call the distributor api rte_distributor_returned_pkts() to get the packets processed, and will enqueue them to a ring for transfer to the TX thread for transmission on the output port. The transmit thread will dequeue the packets from the ring and transmit them on the output port specified in packet mbuf. Users who wish to terminate the running of the application have to press ctrl+C (or send SIGINT to the app). Upon this signal, a signal handler provided in the application will terminate all running threads gracefully and print final statistics to the user. .. _figure_dist_app: .. figure:: img/dist_app.* Distributor Sample Application Layout Debug Logging Support --------------------- Debug logging is provided as part of the application; the user needs to uncomment the line "#define DEBUG" defined in start of the application in main.c to enable debug logs. Statistics ---------- Upon SIGINT (or) ctrl+C, the print_stats() function displays the count of packets processed at the different stages in the application. Application Initialization -------------------------- Command line parsing is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.1, "Command Line Arguments". Mbuf pool initialization is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.2, "Mbuf Pool Initialization". Driver Initialization is done in same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.3, "Driver Initialization". RX queue initialization is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.4, "RX Queue Initialization". TX queue initialization is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.5, "TX Queue Initialization". ================================================ FILE: doc/guides/sample_app_ug/exception_path.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Exception Path Sample Application ================================= The Exception Path sample application is a simple example that demonstrates the use of the DPDK to set up an exception path for packets to go through the Linux* kernel. This is done by using virtual TAP network interfaces. These can be read from and written to by the DPDK application and appear to the kernel as a standard network interface. Overview -------- The application creates two threads for each NIC port being used. One thread reads from the port and writes the data unmodified to a thread-specific TAP interface. The second thread reads from a TAP interface and writes the data unmodified to the NIC port. The packet flow through the exception path application is as shown in the following figure. .. _figure_exception_path_example: .. figure:: img/exception_path_example.* Packet Flow To make throughput measurements, kernel bridges must be setup to forward data between the bridges appropriately. Compiling the Application ------------------------- #. Go to example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/exception_path #. Set the target (a default target will be used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc This application is intended as a linuxapp only. See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application requires a number of command line options: .. code-block:: console .build/exception_path [EAL options] -- -p PORTMASK -i IN_CORES -o OUT_CORES where: * -p PORTMASK: A hex bitmask of ports to use * -i IN_CORES: A hex bitmask of cores which read from NIC * -o OUT_CORES: A hex bitmask of cores which write to NIC Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. The number of bits set in each bitmask must be the same. The coremask -c parameter of the EAL options should include IN_CORES and OUT_CORES. The same bit must not be set in IN_CORES and OUT_CORES. The affinities between ports and cores are set beginning with the least significant bit of each mask, that is, the port represented by the lowest bit in PORTMASK is read from by the core represented by the lowest bit in IN_CORES, and written to by the core represented by the lowest bit in OUT_CORES. For example to run the application with two ports and four cores: .. code-block:: console ./build/exception_path -c f -n 4 -- -p 3 -i 3 -o c Getting Statistics ~~~~~~~~~~~~~~~~~~ While the application is running, statistics on packets sent and received can be displayed by sending the SIGUSR1 signal to the application from another terminal: .. code-block:: console killall -USR1 exception_path The statistics can be reset by sending a SIGUSR2 signal in a similar way. Explanation ----------- The following sections provide some explanation of the code. Initialization ~~~~~~~~~~~~~~ Setup of the mbuf pool, driver and queues is similar to the setup done in the L2 Forwarding sample application (see Chapter 9 "L2 forwarding Sample Application (in Real and Virtualized Environments" for details). In addition, the TAP interfaces must also be created. A TAP interface is created for each lcore that is being used. The code for creating the TAP interface is as follows: .. code-block:: c /* * Create a tap network interface, or use existing one with same name. * If name[0]='\0' then a name is automatically assigned and returned in name. */ static int tap_create(char *name) { struct ifreq ifr; int fd, ret; fd = open("/dev/net/tun", O_RDWR); if (fd < 0) return fd; memset(&ifr, 0, sizeof(ifr)); /* TAP device without packet information */ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if (name && *name) rte_snprinf(ifr.ifr_name, IFNAMSIZ, name); ret = ioctl(fd, TUNSETIFF, (void *) &ifr); if (ret < 0) { close(fd); return ret; } if (name) rte_snprintf(name, IFNAMSIZ, ifr.ifr_name); return fd; } The other step in the initialization process that is unique to this sample application is the association of each port with two cores: * One core to read from the port and write to a TAP interface * A second core to read from a TAP interface and write to the port This is done using an array called port_ids[], which is indexed by the lcore IDs. The population of this array is shown below: .. code-block:: c tx_port = 0; rx_port = 0; RTE_LCORE_FOREACH(i) { if (input_cores_mask & (1ULL << i)) { /* Skip ports that are not enabled */ while ((ports_mask & (1 << rx_port)) == 0) { rx_port++; if (rx_port > (sizeof(ports_mask) * 8)) goto fail; /* not enough ports */ } port_ids[i] = rx_port++; } else if (output_cores_mask & (1ULL << i)) { /* Skip ports that are not enabled */ while ((ports_mask & (1 << tx_port)) == 0) { tx_port++; if (tx_port > (sizeof(ports_mask) * 8)) goto fail; /* not enough ports */ } port_ids[i] = tx_port++; } } Packet Forwarding ~~~~~~~~~~~~~~~~~ After the initialization steps are complete, the main_loop() function is run on each lcore. This function first checks the lcore_id against the user provided input_cores_mask and output_cores_mask to see if this core is reading from or writing to a TAP interface. For the case that reads from a NIC port, the packet reception is the same as in the L2 Forwarding sample application (see Section 9.4.6, "Receive, Process and Transmit Packets"). The packet transmission is done by calling write() with the file descriptor of the appropriate TAP interface and then explicitly freeing the mbuf back to the pool. .. code-block:: c /* Loop forever reading from NIC and writing to tap */ for (;;) { struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; unsigned i; const unsigned nb_rx = rte_eth_rx_burst(port_ids[lcore_id], 0, pkts_burst, PKT_BURST_SZ); lcore_stats[lcore_id].rx += nb_rx; for (i = 0; likely(i < nb_rx); i++) { struct rte_mbuf *m = pkts_burst[i]; int ret = write(tap_fd, rte_pktmbuf_mtod(m, void*), rte_pktmbuf_data_len(m)); rte_pktmbuf_free(m); if (unlikely(ret<0)) lcore_stats[lcore_id].dropped++; else lcore_stats[lcore_id].tx++; } } For the other case that reads from a TAP interface and writes to a NIC port, packets are retrieved by doing a read() from the file descriptor of the appropriate TAP interface. This fills in the data into the mbuf, then other fields are set manually. The packet can then be transmitted as normal. .. code-block:: c /* Loop forever reading from tap and writing to NIC */ for (;;) { int ret; struct rte_mbuf *m = rte_pktmbuf_alloc(pktmbuf_pool); if (m == NULL) continue; ret = read(tap_fd, m->pkt.data, MAX_PACKET_SZ); lcore_stats[lcore_id].rx++; if (unlikely(ret < 0)) { FATAL_ERROR("Reading from %s interface failed", tap_name); } m->pkt.nb_segs = 1; m->pkt.next = NULL; m->pkt.data_len = (uint16_t)ret; ret = rte_eth_tx_burst(port_ids[lcore_id], 0, &m, 1); if (unlikely(ret < 1)) { rte_pktmuf_free(m); lcore_stats[lcore_id].dropped++; } else { lcore_stats[lcore_id].tx++; } } To set up loops for measuring throughput, TAP interfaces can be connected using bridging. The steps to do this are described in the section that follows. Managing TAP Interfaces and Bridges ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Exception Path sample application creates TAP interfaces with names of the format tap_dpdk_nn, where nn is the lcore ID. These TAP interfaces need to be configured for use: .. code-block:: console ifconfig tap_dpdk_00 up To set up a bridge between two interfaces so that packets sent to one interface can be read from another, use the brctl tool: .. code-block:: console brctl addbr "br0" brctl addif br0 tap_dpdk_00 brctl addif br0 tap_dpdk_03 ifconfig br0 up The TAP interfaces created by this application exist only when the application is running, so the steps above need to be repeated each time the application is run. To avoid this, persistent TAP interfaces can be created using openvpn: .. code-block:: console openvpn --mktun --dev tap_dpdk_00 If this method is used, then the steps above have to be done only once and the same TAP interfaces can be reused each time the application is run. To remove bridges and persistent TAP interfaces, the following commands are used: .. code-block:: console ifconfig br0 down brctl delbr br0 openvpn --rmtun --dev tap_dpdk_00 ================================================ FILE: doc/guides/sample_app_ug/hello_world.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Hello World Sample Application ============================== The Hello World sample application is an example of the simplest DPDK application that can be written. The application simply prints an "helloworld" message on every enabled lcore. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/helloworld #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started* Guide for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- To run the example in a linuxapp environment: .. code-block:: console $ ./build/helloworld -c f -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of code. EAL Initialization ~~~~~~~~~~~~~~~~~~ The first task is to initialize the Environment Abstraction Layer (EAL). This is done in the main() function using the following code: .. code-block:: c int main(int argc, char **argv) { ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); This call finishes the initialization process that was started before main() is called (in case of a Linuxapp environment). The argc and argv arguments are provided to the rte_eal_init() function. The value returned is the number of parsed arguments. Starting Application Unit Lcores ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once the EAL is initialized, the application is ready to launch a function on an lcore. In this example, lcore_hello() is called on every available lcore. The following is the definition of the function: .. code-block:: c static int lcore_hello( attribute ((unused)) void *arg) { unsigned lcore_id; lcore_id = rte_lcore_id(); printf("hello from core %u\n", lcore_id); return 0; } The code that launches the function on each lcore is as follows: .. code-block:: c /* call lcore_hello() on every slave lcore */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_hello, NULL, lcore_id); } /* call it on master lcore too */ lcore_hello(NULL); The following code is equivalent and simpler: .. code-block:: c rte_eal_mp_remote_launch(lcore_hello, NULL, CALL_MASTER); Refer to the *DPDK API Reference* for detailed information on the rte_eal_mp_remote_launch() function. ================================================ FILE: doc/guides/sample_app_ug/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Sample Applications User Guide ============================== |today| **Contents** .. toctree:: :maxdepth: 2 :numbered: intro cmd_line exception_path hello_world skeleton rxtx_callbacks ip_frag ipv4_multicast ip_reassembly kernel_nic_interface l2_forward_job_stats l2_forward_real_virtual l3_forward l3_forward_power_man l3_forward_access_ctrl l3_forward_virtual link_status_intr load_balancer multi_process qos_metering qos_scheduler intel_quickassist quota_watermark timer packet_ordering vmdq_dcb_forwarding vhost netmap_compatibility ip_pipeline test_pipeline dist_app vm_power_management tep_termination proc_info **Figures** :numref:`figure_exception_path_example` :ref:`figure_exception_path_example` :numref:`figure_kernel_nic` :ref:`figure_kernel_nic` :numref:`figure_l2_fwd_benchmark_setup_jobstats` :ref:`figure_l2_fwd_benchmark_setup_jobstats` :numref:`figure_l2_fwd_virtenv_benchmark_setup_jobstats` :ref:`figure_l2_fwd_virtenv_benchmark_setup_jobstats` :numref:`figure_l2_fwd_benchmark_setup` :ref:`figure_l2_fwd_benchmark_setup` :numref:`figure_l2_fwd_virtenv_benchmark_setup` :ref:`figure_l2_fwd_virtenv_benchmark_setup` :numref:`figure_ipv4_acl_rule` :ref:`figure_ipv4_acl_rule` :numref:`figure_example_rules` :ref:`figure_example_rules` :numref:`figure_load_bal_app_arch` :ref:`figure_load_bal_app_arch` :numref:`figure_sym_multi_proc_app` :ref:`figure_sym_multi_proc_app` :numref:`figure_client_svr_sym_multi_proc_app` :ref:`figure_client_svr_sym_multi_proc_app` :numref:`figure_master_slave_proc` :ref:`figure_master_slave_proc` :numref:`figure_slave_proc_recov` :ref:`figure_slave_proc_recov` :numref:`figure_qos_sched_app_arch` :ref:`figure_qos_sched_app_arch` :numref:`figure_quickassist_block_diagram` :ref:`figure_quickassist_block_diagram` :numref:`figure_pipeline_overview` :ref:`figure_pipeline_overview` :numref:`figure_ring_pipeline_perf_setup` :ref:`figure_ring_pipeline_perf_setup` :numref:`figure_threads_pipelines` :ref:`figure_threads_pipelines` :numref:`figure_vmdq_dcb_example` :ref:`figure_vmdq_dcb_example` :numref:`figure_qemu_virtio_net` :ref:`figure_qemu_virtio_net` :numref:`figure_virtio_linux_vhost` :ref:`figure_virtio_linux_vhost` :numref:`figure_vhost_net_arch` :ref:`figure_vhost_net_arch` :numref:`figure_vhost_net_sample_app` :ref:`figure_vhost_net_sample_app` :numref:`figure_tx_dpdk_testpmd` :ref:`figure_tx_dpdk_testpmd` :numref:`figure_test_pipeline_app` :ref:`figure_test_pipeline_app` :numref:`figure_dist_perf` :ref:`figure_dist_perf` :numref:`figure_dist_app` :ref:`figure_dist_app` :numref:`figure_vm_power_mgr_highlevel` :ref:`figure_vm_power_mgr_highlevel` :numref:`figure_vm_power_mgr_vm_request_seq` :ref:`figure_vm_power_mgr_vm_request_seq` :numref:`figure_overlay_networking` :ref:`figure_overlay_networking` :numref:`figure_tep_termination_arch` :ref:`figure_tep_termination_arch` **Tables** :numref:`table_qos_metering_1` :ref:`table_qos_metering_1` :numref:`table_qos_scheduler_1` :ref:`table_qos_scheduler_1` :numref:`table_test_pipeline_1` :ref:`table_test_pipeline_1` ================================================ FILE: doc/guides/sample_app_ug/intel_quickassist.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Intel® QuickAssist Technology Sample Application ================================================ This sample application demonstrates the use of the cryptographic operations provided by the Intel® QuickAssist Technology from within the DPDK environment. Therefore, building and running this application requires having both the DPDK and the QuickAssist Technology Software Library installed, as well as at least one Intel® QuickAssist Technology hardware device present in the system. For this sample application, there is a dependency on either of: * Intel® Communications Chipset 8900 to 8920 Series Software for Linux* package * Intel® Communications Chipset 8925 to 8955 Series Software for Linux* package Overview -------- An overview of the application is provided in :numref:`figure_quickassist_block_diagram`. For simplicity, only two NIC ports and one Intel® QuickAssist Technology device are shown in this diagram, although the number of NIC ports and Intel® QuickAssist Technology devices can be different. .. _figure_quickassist_block_diagram: .. figure:: img/quickassist_block_diagram.* Intel® QuickAssist Technology Application Block Diagram The application allows the configuration of the following items: * Number of NIC ports * Number of logical cores (lcores) * Mapping of NIC RX queues to logical cores Each lcore communicates with every cryptographic acceleration engine in the system through a pair of dedicated input - output queues. Each lcore has a dedicated NIC TX queue with every NIC port in the system. Therefore, each lcore reads packets from its NIC RX queues and cryptographic accelerator output queues and writes packets to its NIC TX queues and cryptographic accelerator input queues. Each incoming packet that is read from a NIC RX queue is either directly forwarded to its destination NIC TX port (forwarding path) or first sent to one of the Intel® QuickAssist Technology devices for either encryption or decryption before being sent out on its destination NIC TX port (cryptographic path). The application supports IPv4 input packets only. For each input packet, the decision between the forwarding path and the cryptographic path is taken at the classification stage based on the value of the IP source address field read from the input packet. Assuming that the IP source address is A.B.C.D, then if: * D = 0: the forwarding path is selected (the packet is forwarded out directly) * D = 1: the cryptographic path for encryption is selected (the packet is first encrypted and then forwarded out) * D = 2: the cryptographic path for decryption is selected (the packet is first decrypted and then forwarded out) For the cryptographic path cases (D = 1 or D = 2), byte C specifies the cipher algorithm and byte B the cryptographic hash algorithm to be used for the current packet. Byte A is not used and can be any value. The cipher and cryptographic hash algorithms supported by this application are listed in the crypto.h header file. For each input packet, the destination NIC TX port is decided at the forwarding stage (executed after the cryptographic stage, if enabled for the packet) by looking at the RX port index of the dst_ports[ ] array, which was initialized at startup, being the outport the adjacent enabled port. For example, if ports 1,3,5 and 6 are enabled, for input port 1, outport port will be 3 and vice versa, and for input port 5, output port will be 6 and vice versa. For the cryptographic path, it is the payload of the IPv4 packet that is encrypted or decrypted. Setup ~~~~~ Building and running this application requires having both the DPDK package and the QuickAssist Technology Software Library installed, as well as at least one Intel® QuickAssist Technology hardware device present in the system. For more details on how to build and run DPDK and Intel® QuickAssist Technology applications, please refer to the following documents: * *DPDK Getting Started Guide* * Intel® Communications Chipset 8900 to 8920 Series Software for Linux* Getting Started Guide (440005) * Intel® Communications Chipset 8925 to 8955 Series Software for Linux* Getting Started Guide (523128) For more details on the actual platforms used to validate this application, as well as performance numbers, please refer to the Test Report, which is accessible by contacting your Intel representative. Building the Application ------------------------ Steps to build the application: #. Set up the following environment variables: .. code-block:: console export RTE_SDK= export ICP_ROOT= #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc Refer to the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console cd ${RTE_SDK}/examples/dpdk_qat make Running the Application ----------------------- Intel® QuickAssist Technology Configuration Files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Intel® QuickAssist Technology configuration files used by the application are located in the config_files folder in the application folder. There following sets of configuration files are included in the DPDK package: * Stargo CRB (single CPU socket): located in the stargo folder * dh89xxcc_qa_dev0.conf * Shumway CRB (dual CPU socket): located in the shumway folder * dh89xxcc_qa_dev0.conf * dh89xxcc_qa_dev1.conf * Coleto Creek: located in the coleto folder * dh895xcc_qa_dev0.conf The relevant configuration file(s) must be copied to the /etc/ directory. Please note that any change to these configuration files requires restarting the Intel® QuickAssist Technology driver using the following command: .. code-block:: console # service qat_service restart Refer to the following documents for information on the Intel® QuickAssist Technology configuration files: * Intel® Communications Chipset 8900 to 8920 Series Software Programmer's Guide * Intel® Communications Chipset 8925 to 8955 Series Software Programmer's Guide * Intel® Communications Chipset 8900 to 8920 Series Software for Linux* Getting Started Guide. * Intel® Communications Chipset 8925 to 8955 Series Software for Linux* Getting Started Guide. Traffic Generator Setup and Application Startup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The application has a number of command line options: dpdk_qat [EAL options] -- -p PORTMASK [--no-promisc] [--config '(port,queue,lcore)[,(port,queue,lcore)]'] where, * -p PORTMASK: Hexadecimal bitmask of ports to configure * --no-promisc: Disables promiscuous mode for all ports, so that only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. By default promiscuous mode is enabled so that packets are accepted regardless of the packet's Ethernet MAC destination address. * --config'(port,queue,lcore)[,(port,queue,lcore)]': determines which queues from which ports are mapped to which cores. Refer to Chapter 10 , "L3 Forwarding Sample Application" for more detailed descriptions of the --config command line option. As an example, to run the application with two ports and two cores, which are using different Intel® QuickAssist Technology execution engines, performing AES-CBC-128 encryption with AES-XCBC-MAC-96 hash, the following settings can be used: * Traffic generator source IP address: 0.9.6.1 * Command line: .. code-block:: console ./build/dpdk_qat -c 0xff -n 2 -- -p 0x3 --config '(0,0,1),(1,0,2)' Refer to the *DPDK Test Report* for more examples of traffic generator setup and the application startup command lines. If no errors are generated in response to the startup commands, the application is running correctly. ================================================ FILE: doc/guides/sample_app_ug/intro.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ This document describes the sample applications that are included in the Data Plane Development Kit (DPDK). Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. Documentation Roadmap --------------------- The following is a list of DPDK documents in suggested reading order: * **Release Notes** : Provides release-specific information, including supported features, limitations, fixed issues, known issues and so on. Also, provides the answers to frequently asked questions in FAQ format. * **Getting Started Guides** : Describes how to install and configure the DPDK software for your operating system; designed to get users up and running quickly with the software. * **Programmer's Guide:** Describes: * The software architecture and how to use it (through examples), specifically in a Linux* application (linuxapp) environment. * The content of the DPDK, the build system (including the commands that can be used in the root DPDK Makefile to build the development kit and an application) and guidelines for porting an application. * Optimizations used in the software and those that should be considered for new development A glossary of terms is also provided. * **API Reference** : Provides detailed information about DPDK functions, data structures and other programming constructs. * **Sample Applications User Guide** : Describes a set of sample applications. Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. ================================================ FILE: doc/guides/sample_app_ug/ip_frag.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IP Fragmentation Sample Application =================================== The IPv4 Fragmentation application is a simple example of packet processing using the Data Plane Development Kit (DPDK). The application does L3 forwarding with IPv4 and IPv6 packet fragmentation. Overview -------- The application demonstrates the use of zero-copy buffers for packet fragmentation. The initialization and run-time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Simple Application (in Real and Virtualized Environments)" for more information). This guide highlights the differences between the two applications. There are three key differences from the L2 Forwarding sample application: * The first difference is that the IP Fragmentation sample application makes use of indirect buffers. * The second difference is that the forwarding decision is taken based on information read from the input packet's IP header. * The third difference is that the application differentiates between IP and non-IP traffic by means of offload flags. The Longest Prefix Match (LPM for IPv4, LPM6 for IPv6) table is used to store/lookup an outgoing port number, associated with that IP address. Any unmatched packets are forwarded to the originating port. By default, input frame sizes up to 9.5 KB are supported. Before forwarding, the input IP packet is fragmented to fit into the "standard" Ethernet* v2 MTU (1500 bytes). Building the Application ------------------------ To build the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/ip_fragmentation #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The LPM object is created and loaded with the pre-configured entries read from global l3fwd_ipv4_route_array and l3fwd_ipv6_route_array tables. For each input packet, the packet forwarding decision (that is, the identification of the output interface for the packet) is taken as a result of LPM lookup. If the IP packet size is greater than default output MTU, then the input packet is fragmented and several fragments are sent via the output interface. Application usage: .. code-block:: console ./build/ip_fragmentation [EAL options] -- -p PORTMASK [-q NQ] where: * -p PORTMASK is a hexadecimal bitmask of ports to configure * -q NQ is the number of queue (=ports) per lcore (the default is 1) To run the example in linuxapp environment with 2 lcores (2,4) over 2 ports(0,2) with 1 RX queue per lcore: .. code-block:: console ./build/ip_fragmentation -c 0x14 -n 3 -- -p 5 EAL: coremask set to 14 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 1 EAL: Detected lcore 2 on socket 0 EAL: Detected lcore 3 on socket 1 EAL: Detected lcore 4 on socket 0 ... Initializing port 0 on lcore 2... Address:00:1B:21:76:FA:2C, rxq=0 txq=2,0 txq=4,1 done: Link Up - speed 10000 Mbps - full-duplex Skipping disabled port 1 Initializing port 2 on lcore 4... Address:00:1B:21:5C:FF:54, rxq=0 txq=2,0 txq=4,1 done: Link Up - speed 10000 Mbps - full-duplex Skipping disabled port 3IP_FRAG: Socket 0: adding route 100.10.0.0/16 (port 0) IP_FRAG: Socket 0: adding route 100.20.0.0/16 (port 1) ... IP_FRAG: Socket 0: adding route 0101:0101:0101:0101:0101:0101:0101:0101/48 (port 0) IP_FRAG: Socket 0: adding route 0201:0101:0101:0101:0101:0101:0101:0101/48 (port 1) ... IP_FRAG: entering main loop on lcore 4 IP_FRAG: -- lcoreid=4 portid=2 IP_FRAG: entering main loop on lcore 2 IP_FRAG: -- lcoreid=2 portid=0 To run the example in linuxapp environment with 1 lcore (4) over 2 ports(0,2) with 2 RX queues per lcore: .. code-block:: console ./build/ip_fragmentation -c 0x10 -n 3 -- -p 5 -q 2 To test the application, flows should be set up in the flow generator that match the values in the l3fwd_ipv4_route_array and/or l3fwd_ipv6_route_array table. The default l3fwd_ipv4_route_array table is: .. code-block:: c struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = { {IPv4(100, 10, 0, 0), 16, 0}, {IPv4(100, 20, 0, 0), 16, 1}, {IPv4(100, 30, 0, 0), 16, 2}, {IPv4(100, 40, 0, 0), 16, 3}, {IPv4(100, 50, 0, 0), 16, 4}, {IPv4(100, 60, 0, 0), 16, 5}, {IPv4(100, 70, 0, 0), 16, 6}, {IPv4(100, 80, 0, 0), 16, 7}, }; The default l3fwd_ipv6_route_array table is: .. code-block:: c struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = { {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 0}, {{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 1}, {{3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 2}, {{4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 3}, {{5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 4}, {{6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 5}, {{7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 6}, {{8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 7}, }; For example, for the input IPv4 packet with destination address: 100.10.1.1 and packet length 9198 bytes, seven IPv4 packets will be sent out from port #0 to the destination address 100.10.1.1: six of those packets will have length 1500 bytes and one packet will have length 318 bytes. IP Fragmentation sample application provides basic NUMA support in that all the memory structures are allocated on all sockets that have active lcores on them. Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. ================================================ FILE: doc/guides/sample_app_ug/ip_pipeline.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Internet Protocol (IP) Pipeline Application =========================================== Application overview -------------------- The *Internet Protocol (IP) Pipeline* application is intended to be a vehicle for rapid development of packet processing applications running on multi-core CPUs. The application provides a library of reusable functional blocks called pipelines. These pipelines can be seen as prefabricated blocks that can be instantiated and inter-connected through packet queues to create complete applications (super-pipelines). Pipelines are created and inter-connected through the application configuration file. By using different configuration files, different applications are effectively created, therefore this application can be seen as an application generator. The configuration of each pipeline can be updated at run-time through the application Command Line Interface (CLI). Main application components are: **A Library of reusable pipelines** * Each pipeline represents a functional block, e.g. flow classification, firewall, routing, master, etc. * Each pipeline type can be instantiated several times in the same application, which each instance configured separately and mapped to a single CPU core. Each CPU core can run one or several pipeline instances, which can be of same or different type. * Pipeline instances are inter-connected through packet queues (for packet processing) and message queues (for run-time configuration). * Pipelines are implemented using DPDK Packet Framework. * More pipeline types can always be built and added to the existing pipeline types. **The Configuration file** * The configuration file defines the application structure. By using different configuration files, different applications are created. * All the application resources are created and configured through the application configuration file: pipeline instances, buffer pools, links (i.e. network interfaces), hardware device RX/TX queues, software queues, traffic manager devices, EAL startup arguments, etc. * The configuration file syntax is “define by reference”, meaning that resources are defined as they are referenced. First time a resource name is detected, it is registered with default parameters. Optionally, the resource parameters can be further refined through a configuration file section dedicated to that resource. * Command Line Interface (CLI) **Global CLI commands: link configuration, etc.** * Common pipeline CLI commands: ping (keep-alive), statistics, etc. * Pipeline type specific CLI commands: used to configure instances of specific pipeline type. These commands are registered with the application when the pipeline type is registered. For example, the commands for routing pipeline instances include: route add, route delete, route list, etc. * CLI commands can be grouped into scripts that can be invoked at initialization and at runtime. Design goals ------------ Rapid development ~~~~~~~~~~~~~~~~~ This application enables rapid development through quick connectivity of standard components called pipelines. These components are built using DPDK Packet Framework and encapsulate packet processing features at different levels: ports, tables, actions, pipelines and complete applications. Pipeline instances are instantiated, configured and inter-connected through low complexity configuration files loaded during application initialization. Each pipeline instance is mapped to a single CPU core, with each CPU core able to run one or multiple pipeline instances of same or different types. By loading a different configuration file, a different application is effectively started. Flexibility ~~~~~~~~~~~ Each packet processing application is typically represented as a chain of functional stages which is often called the functional pipeline of the application. These stages are mapped to CPU cores to create chains of CPU cores (pipeline model), clusters of CPU cores (run-to-completion model) or chains of clusters of CPU cores (hybrid model). This application allows all the above programming models. By applying changes to the configuration file, the application provides the flexibility to reshuffle its building blocks in different ways until the configuration providing the best performance is identified. Move pipelines around ^^^^^^^^^^^^^^^^^^^^^ The mapping of pipeline instances to CPU cores can be reshuffled through the configuration file. One or several pipeline instances can be mapped to the same CPU core. .. _figure_ip_pipelines_1: .. figure:: img/ip_pipelines_1.* Example of moving pipeline instances across different CPU cores Move tables around ^^^^^^^^^^^^^^^^^^ There is some degree of flexibility for moving tables from one pipeline instance to another. Based on the configuration arguments passed to each pipeline instance in the configuration file, specific tables can be enabled or disabled. This way, a specific table can be “moved” from pipeline instance A to pipeline instance B by simply disabling its associated functionality for pipeline instance A while enabling it for pipeline instance B. Due to requirement to have simple syntax for the configuration file, moving tables across different pipeline instances is not as flexible as the mapping of pipeline instances to CPU cores, or mapping actions to pipeline tables. Complete flexibility in moving tables from one pipeline to another could be achieved through a complex pipeline description language that would detail the structural elements of the pipeline (ports, tables and actions) and their connectivity, resulting in complex syntax for the configuration file, which is not acceptable. Good configuration file readability through simple syntax is preferred. *Example*: the IP routing pipeline can run the routing function only (with ARP function run by a different pipeline instance), or it can run both the routing and ARP functions as part of the same pipeline instance. .. _figure_ip_pipelines_2: .. figure:: img/ip_pipelines_2.* Example of moving tables across different pipeline instances Move actions around ^^^^^^^^^^^^^^^^^^^ When it makes sense, packet processing actions can be moved from one pipeline instance to another. Based on the configuration arguments passed to each pipeline instance in the configuration file, specific actions can be enabled or disabled. This way, a specific action can be "moved" from pipeline instance A to pipeline instance B by simply disabling its associated functionality for pipeline instance A while enabling it for pipeline instance B. *Example*: The flow actions of accounting, traffic metering, application identification, NAT, etc can be run as part of the flow classification pipeline instance or split across several flow actions pipeline instances, depending on the number of flow instances and their compute requirements. .. _figure_ip_pipelines_3: .. figure:: img/ip_pipelines_3.* Example of moving actions across different tables and pipeline instances Performance ~~~~~~~~~~~ Performance of the application is the highest priority requirement. Flexibility is not provided at the expense of performance. The purpose of flexibility is to provide an incremental development methodology that allows monitoring the performance evolution: * Apply incremental changes in the configuration (e.g. mapping on pipeline instances to CPU cores) in order to identify the configuration providing the best performance for a given application; * Add more processing incrementally (e.g. by enabling more actions for specific pipeline instances) until the application is feature complete while checking the performance impact at each step. Debug capabilities ~~~~~~~~~~~~~~~~~~ The application provides a significant set of debug capabilities: * Command Line Interface (CLI) support for statistics polling: pipeline instance ping (keep-alive checks), pipeline instance statistics per input port/output port/table, link statistics, etc; * Logging: Turn on/off application log messages based on priority level; Running the application ----------------------- The application startup command line is:: ip_pipeline [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK [-l LOG_LEVEL] The application startup arguments are: ``-f CONFIG_FILE`` * Optional: Yes * Default: ``./config/ip_pipeline.cfg`` * Argument: Path to the configuration file to be loaded by the application. Please refer to the :ref:`ip_pipeline_configuration_file` for details on how to write the configuration file. ``-s SCRIPT_FILE`` * Optional: Yes * Default: Not present * Argument: Path to the CLI script file to be run by the master pipeline at application startup. No CLI script file will be run at startup of this argument is not present. ``-p PORT_MASK`` * Optional: No * Default: N/A * Argument: Hexadecimal mask of NIC port IDs to be used by the application. First port enabled in this mask will be referenced as LINK0 as part of the application configuration file, next port as LINK1, etc. ``-l LOG_LEVEL`` * Optional: Yes * Default: 1 (High priority) * Argument: Log level to determine which application messages are to be printed to standard output. Available log levels are: 0 (None), 1 (High priority), 2 (Low priority). Only application messages whose priority is higher than or equal to the application log level will be printed. Application stages ------------------ Configuration ~~~~~~~~~~~~~ During this stage, the application configuration file is parsed and its content is loaded into the application data structures. In case of any configuration file parse error, an error message is displayed and the application is terminated. Please refer to the :ref:`ip_pipeline_configuration_file` for a description of the application configuration file format. Configuration checking ~~~~~~~~~~~~~~~~~~~~~~ In the absence of any parse errors, the loaded content of application data structures is checked for overall consistency. In case of any configuration check error, an error message is displayed and the application is terminated. Initialization ~~~~~~~~~~~~~~ During this stage, the application resources are initialized and the handles to access them are saved into the application data structures. In case of any initialization error, an error message is displayed and the application is terminated. The typical resources to be initialized are: pipeline instances, buffer pools, links (i.e. network interfaces), hardware device RX/TX queues, software queues, traffic management devices, etc. .. _ip_pipeline_runtime: Run-time ~~~~~~~~ Each CPU core runs the pipeline instances assigned to it in time sharing mode and in round robin order: 1. *Packet processing task*: The pipeline run-time code is typically a packet *processing* task built on top of DPDK Packet Framework rte_pipeline library, which reads bursts of packets from the pipeline input ports, performs table lookups and executes the identified actions for all tables in the pipeline, with packet eventually written to pipeline output ports or dropped. 2. *Message handling task*: Each CPU core will also periodically execute the *message handling* code of each of the pipelines mapped to it. The pipeline message handling code is processing the messages that are pending in the pipeline input message queues, which are typically sent by the master CPU core for the on-the-fly pipeline configuration: check that pipeline is still alive (ping), add/delete entries in the pipeline tables, get statistics, etc. The frequency of executing the message handling code is usually much smaller than the frequency of executing the packet processing work. Please refer to the :ref:`ip_pipeline_pipeline_section` for more details about the application pipeline module encapsulation. .. _ip_pipeline_configuration_file: Configuration file syntax ------------------------- Syntax overview ~~~~~~~~~~~~~~~ The syntax of the configuration file is designed to be simple, which favors readability. The configuration file is parsed using the DPDK library librte_cfgfile, which supports simple `INI file format `__ for configuration files. As result, the configuration file is split into several sections, with each section containing one or more entries. The scope of each entry is its section, and each entry specifies a variable that is assigned a specific value. Any text after the ``;`` character is considered a comment and is therefore ignored. The following are application specific: number of sections, name of each section, number of entries of each section, name of the variables used for each section entry, the value format (e.g. signed/unsigned integer, string, etc) and range of each section entry variable. Generic example of configuration file section: .. code-block:: ini [] = ... = Application resources present in the configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_resource_name: .. tabularcolumns:: |p{4cm}|p{6cm}|p{6cm}| .. table:: Application resource names in the configuration file +--------------------------+-----------------------------+-------------------------------------------------+ | Resource type | Format | Examples | +==========================+=============================+=================================================+ | Pipeline | ``PIPELINE`` | ``PIPELINE0``, ``PIPELINE1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Mempool | ``MEMPOOL`` | ``MEMPOOL0``, ``MEMPOOL1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Link (network interface) | ``LINK`` | ``LINK0``, ``LINK1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Link RX queue | ``RXQ.`` | ``RXQ0.0``, ``RXQ1.5`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Link TX queue | ``TXQ.`` | ``TXQ0.0``, ``TXQ1.5`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Software queue | ``SWQ`` | ``SWQ0``, ``SWQ1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Traffic Manager | ``TM`` | ``TM0``, ``TM1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Source | ``SOURCE`` | ``SOURCE0``, ``SOURCE1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Sink | ``SINK`` | ``SINK0``, ``SINK1`` | +--------------------------+-----------------------------+-------------------------------------------------+ | Message queue | ``MSGQ`` | ``MSGQ0``, ``MSGQ1``, | | | ``MSGQ-REQ-PIPELINE`` | ``MSGQ-REQ-PIPELINE2``, ``MSGQ-RSP-PIPELINE2,`` | | | ``MSGQ-RSP-PIPELINE`` | ``MSGQ-REQ-CORE-s0c1``, ``MSGQ-RSP-CORE-s0c1`` | | | ``MSGQ-REQ-CORE-`` | | | | ``MSGQ-RSP-CORE-`` | | +--------------------------+-----------------------------+-------------------------------------------------+ ``LINK`` instances are created implicitly based on the ``PORT_MASK`` application startup argument. ``LINK0`` is the first port enabled in the ``PORT_MASK``, port 1 is the next one, etc. The LINK ID is different than the DPDK PMD-level NIC port ID, which is the actual position in the bitmask mentioned above. For example, if bit 5 is the first bit set in the bitmask, then ``LINK0`` is having the PMD ID of 5. This mechanism creates a contiguous LINK ID space and isolates the configuration file against changes in the board PCIe slots where NICs are plugged in. ``RXQ``, ``TXQ`` and ``TM`` instances have the LINK ID as part of their name. For example, ``RXQ2.1``, ``TXQ2.1`` and ``TM2`` are all associated with ``LINK2``. Rules to parse the configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main rules used to parse the configuration file are: 1. Application resource name determines the type of resource based on the name prefix. *Example*: all software queues need to start with ``SWQ`` prefix, so ``SWQ0`` and ``SWQ5`` are valid software queue names. 2. An application resource is defined by creating a configuration file section with its name. The configuration file section allows fine tuning on any of the resource parameters. Some resource parameters are mandatory, in which case it is required to have them specified as part of the section, while some others are optional, in which case they get assigned their default value when not present. *Example*: section ``SWQ0`` defines a software queue named SWQ0, whose parameters are detailed as part of this section. 3. An application resource can also be defined by referencing it. Referencing a resource takes place by simply using its name as part of the value assigned to a variable in any configuration file section. In this case, the resource is registered with all its parameters having their default values. Optionally, a section with the resource name can be added to the configuration file to fine tune some or all of the resource parameters. *Example*: in section ``PIPELINE3``, variable ``pktq_in`` includes ``SWQ5`` as part of its list, which results in defining a software queue named ``SWQ5``; when there is no ``SWQ5`` section present in the configuration file, ``SWQ5`` gets registered with default parameters. .. _ip_pipeline_pipeline_section: PIPELINE section ~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_pipeline_section_1: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}| .. table:: Configuration file PIPELINE section (1/2) +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | Section | Description | Optional | Range | Default value | +===============+===========================================================+===============+========================+================+ | type | Pipeline type. Defines the functionality to be | NO | See "List | N/A | | | executed. | | of pipeline types" | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | core | CPU core to run the current pipeline. | YES | See "CPU Core | CPU socket 0, | | | | | notation" | core 0, | | | | | | hyper-thread 0 | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | pktq_in | Packet queues to serve as input ports for the | YES | List of input | Empty list | | | current pipeline instance. The acceptable packet | | packet queue IDs | | | | queue types are: ``RXQ``, ``SWQ``, ``TM`` and ``SOURCE``. | | | | | | First device in this list is used as pipeline input port | | | | | | 0, second as pipeline input port 1, etc. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | pktq_out | Packet queues to serve as output ports for the | YES | List of output | Empty list | | | current pipeline instance. The acceptable packet | | packet queue IDs. | | | | queue types are: ``TXQ``, ``SWQ``, ``TM`` and ``SINK``. | | | | | | First device in this list is used as pipeline output | | | | | | port 0, second as pipeline output port 1, etc. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ .. _table_ip_pipelines_pipeline_section_2: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}| .. table:: Configuration file PIPELINE section (2/2) +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | Section | Description | Optional | Range | Default value | +===============+===========================================================+===============+========================+================+ | msgq_in | Input message queues. These queues contain | YES | List of message | Empty list | | | request messages that need to be handled by the | | queue IDs | | | | current pipeline instance. The type and format of | | | | | | request messages is defined by the pipeline type. | | | | | | For each pipeline instance, there is an input | | | | | | message queue defined implicitly, whose name is: | | | | | | ``MSGQ-REQ-``. This message queue | | | | | | should not be mentioned as part of msgq_in list. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | msgq_out | Output message queues. These queues are used by | YES | List of message | Empty list | | | the current pipeline instance to write response | | queue IDs | | | | messages as result of request messages being | | | | | | handled. The type and format of response | | | | | | messages is defined by the pipeline type. | | | | | | For each pipeline instance, there is an output | | | | | | message queue defined implicitly, whose name is: | | | | | | ``MSGQ-RSP-``. This message queue | | | | | | should not be mentioned as part of msgq_out list. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | timer_period | Time period, measured in milliseconds, | YES | milliseconds | 1 ms | | | for handling the input message queues. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ | | Arguments to be passed to the current pipeline | Depends on | Depends on | Depends on | | | instance. Format of the arguments, their type, | pipeline type | pipeline type | pipeline type | | | whether each argument is optional or mandatory | | | | | | and its default value (when optional) are defined | | | | | | by the pipeline type. | | | | | | The value of the arguments is applicable to the | | | | | | current pipeline instance only. | | | | +---------------+-----------------------------------------------------------+---------------+------------------------+----------------+ CPU core notation ^^^^^^^^^^^^^^^^^ The CPU Core notation is:: ::= [s|S][c|C][h|H] For example:: CPU socket 0, core 0, hyper-thread 0: 0, c0, s0c0 CPU socket 0, core 0, hyper-thread 1: 0h, c0h, s0c0h CPU socket 3, core 9, hyper-thread 1: s3c9h MEMPOOL section ~~~~~~~~~~~~~~~ .. _table_ip_pipelines_mempool_section: .. tabularcolumns:: |p{2.5cm}|p{6cm}|p{1.5cm}|p{1.5cm}|p{3cm}| .. table:: Configuration file MEMPOOL section +---------------+-----------------------------------------------+----------+----------+---------------------------+ | Section | Description | Optional | Type | Default value | +===============+===============================================+==========+==========+===========================+ | buffer_size | Buffer size (in bytes) for the current | YES | uint32_t | 2048 | | | buffer pool. | | | + sizeof(struct rte_mbuf) | | | | | | + HEADROOM | +---------------+-----------------------------------------------+----------+----------+---------------------------+ | pool_size | Number of buffers in the current buffer pool. | YES | uint32_t | 32K | +---------------+-----------------------------------------------+----------+----------+---------------------------+ | cache_size | Per CPU thread cache size (in number of | YES | uint32_t | 256 | | | buffers) for the current buffer pool. | | | | +---------------+-----------------------------------------------+----------+----------+---------------------------+ | cpu | CPU socket ID where to allocate memory for | YES | uint32_t | 0 | | | the current buffer pool. | | | | +---------------+-----------------------------------------------+----------+----------+---------------------------+ LINK section ~~~~~~~~~~~~ .. _table_ip_pipelines_link_section: .. tabularcolumns:: |p{3cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{2cm}| .. table:: Configuration file LINK section +-----------------+----------------------------------------------+----------+----------+-------------------+ | Section entry | Description | Optional | Type | Default value | +=================+==============================================+==========+==========+===================+ | arp_q | NIC RX queue where ARP packets should | YES | 0 .. 127 | 0 (default queue) | | | be filtered. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | tcp_syn_local_q | NIC RX queue where TCP packets with SYN | YES | 0 .. 127 | 0 (default queue) | | | flag should be filtered. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | ip_local_q | NIC RX queue where IP packets with local | YES | 0 .. 127 | 0 (default queue) | | | destination should be filtered. | | | | | | When TCP, UDP and SCTP local queues are | | | | | | defined, they take higher priority than this | | | | | | queue. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | tcp_local_q | NIC RX queue where TCP packets with local | YES | 0 .. 127 | 0 (default queue) | | | destination should be filtered. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | udp_local_q | NIC RX queue where TCP packets with local | YES | 0 .. 127 | 0 (default queue) | | | destination should be filtered. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | sctp_local_q | NIC RX queue where TCP packets with local | YES | 0 .. 127 | 0 (default queue) | | | destination should be filtered. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ | promisc | Indicates whether current link should be | YES | YES/NO | YES | | | started in promiscuous mode. | | | | +-----------------+----------------------------------------------+----------+----------+-------------------+ RXQ section ~~~~~~~~~~~ .. _table_ip_pipelines_rxq_section: .. tabularcolumns:: |p{3cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{2cm}| .. table:: Configuration file RXQ section +---------------+--------------------------------------------+----------+----------+---------------+ | Section | Description | Optional | Type | Default value | +===============+============================================+==========+==========+===============+ | mempool | Mempool to use for buffer allocation for | YES | uint32_t | MEMPOOL0 | | | current NIC RX queue. The mempool ID has | | | | | | to be associated with a valid instance | | | | | | defined in the mempool entry of the global | | | | | | section. | | | | +---------------+--------------------------------------------+----------+----------+---------------+ | Size | NIC RX queue size (number of descriptors) | YES | uint32_t | 128 | +---------------+--------------------------------------------+----------+----------+---------------+ | burst | Read burst size (number of descriptors) | YES | uint32_t | 32 | +---------------+--------------------------------------------+----------+----------+---------------+ TXQ section ~~~~~~~~~~~ .. _table_ip_pipelines_txq_section: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{2cm}|p{1.5cm}| .. table:: Configuration file TXQ section +---------------+----------------------------------------------+----------+------------------+---------------+ | Section | Description | Optional | Type | Default value | +===============+==============================================+==========+==================+===============+ | size | NIC TX queue size (number of descriptors) | YES | uint32_t | 512 | | | | | power of 2 | | | | | | > 0 | | +---------------+----------------------------------------------+----------+------------------+---------------+ | burst | Write burst size (number of descriptors) | YES | uint32_t | 32 | | | | | power of 2 | | | | | | 0 < burst < size | | +---------------+----------------------------------------------+----------+------------------+---------------+ | dropless | When dropless is set to NO, packets can be | YES | YES/NO | NO | | | dropped if not enough free slots are | | | | | | currently available in the queue, so the | | | | | | write operation to the queue is non- | | | | | | blocking. | | | | | | When dropless is set to YES, packets cannot | | | | | | be dropped if not enough free slots are | | | | | | currently available in the queue, so the | | | | | | write operation to the queue is blocking, as | | | | | | the write operation is retried until enough | | | | | | free slots become available and all the | | | | | | packets are successfully written to the | | | | | | queue. | | | | +---------------+----------------------------------------------+----------+------------------+---------------+ | n_retries | Number of retries. Valid only when dropless | YES | uint32_t | 0 | | | is set to YES. When set to 0, it indicates | | | | | | unlimited number of retries. | | | | +---------------+----------------------------------------------+----------+------------------+---------------+ SWQ section ~~~~~~~~~~~ .. _table_ip_pipelines_swq_section: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}| .. table:: Configuration file SWQ section +---------------+----------------------------------------------+----------+------------------+---------------+ | Section | Description | Optional | Type | Default value | +===============+==============================================+==========+==================+===============+ | size | Queue size (number of packets) | YES | uint32_t | 256 | | | | | power of 2 | | +---------------+----------------------------------------------+----------+------------------+---------------+ | burst_read | Read burst size (number of packets) | YES | uint32_t | 32 | | | | | power of 2 | | | | | | 0 < burst < size | | +---------------+----------------------------------------------+----------+------------------+---------------+ | burst_write | Write burst size (number of packets) | YES | uint32_t | 32 | | | | | power of 2 | | | | | | 0 < burst < size | | +---------------+----------------------------------------------+----------+------------------+---------------+ | dropless | When dropless is set to NO, packets can be | YES | YES/NO | NO | | | dropped if not enough free slots are | | | | | | currently available in the queue, so the | | | | | | write operation to the queue is non- | | | | | | blocking. | | | | | | When dropless is set to YES, packets cannot | | | | | | be dropped if not enough free slots are | | | | | | currently available in the queue, so the | | | | | | write operation to the queue is blocking, as | | | | | | the write operation is retried until enough | | | | | | free slots become available and all the | | | | | | packets are successfully written to the | | | | | | queue. | | | | +---------------+----------------------------------------------+----------+------------------+---------------+ | n_retries | Number of retries. Valid only when dropless | YES | uint32_t | 0 | | | is set to YES. When set to 0, it indicates | | | | | | unlimited number of retries. | | | | +---------------+----------------------------------------------+----------+------------------+---------------+ | cpu | CPU socket ID where to allocate memory | YES | uint32_t | 0 | | | for this SWQ. | | | | +---------------+----------------------------------------------+----------+------------------+---------------+ TM section ~~~~~~~~~~ .. _table_ip_pipelines_tm_section: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}| .. table:: Configuration file TM section +---------------+---------------------------------------------+----------+----------+---------------+ | Section | Description | Optional | Type | Default value | +===============+=============================================+==========+==========+===============+ | Cfg | File name to parse for the TM configuration | YES | string | tm_profile | | | to be applied. The syntax of this file is | | | | | | described in the examples/qos_sched DPDK | | | | | | application documentation. | | | | +---------------+---------------------------------------------+----------+----------+---------------+ | burst_read | Read burst size (number of packets) | YES | uint32_t | 64 | +---------------+---------------------------------------------+----------+----------+---------------+ | burst_write | Write burst size (number of packets) | YES | uint32_t | 32 | +---------------+---------------------------------------------+----------+----------+---------------+ SOURCE section ~~~~~~~~~~~~~~ .. _table_ip_pipelines_source_section: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{2cm}| .. table:: Configuration file SOURCE section +---------------+---------------------------------------+----------+----------+---------------+ | Section | Description | Optional | Type | Default value | +===============+=======================================+==========+==========+===============+ | Mempool | Mempool to use for buffer allocation. | YES | uint32_t | MEMPOOL0 | +---------------+---------------------------------------+----------+----------+---------------+ | Burst | Read burst size (number of packets) | | uint32_t | 32 | +---------------+---------------------------------------+----------+----------+---------------+ SINK section ~~~~~~~~~~~~ Currently, there are no parameters to be passed to a sink device, so SINK section is not allowed. MSGQ section ~~~~~~~~~~~~ .. _table_ip_pipelines_msgq_section: .. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}| .. table:: Configuration file MSGQ section +---------+--------------------------------------------+----------+------------+---------------+ | Section | Description | Optional | Type | Default value | +=========+============================================+==========+============+===============+ | size | Queue size (number of packets) | YES | uint32_t | 64 | | | | | != 0 | | | | | | power of 2 | | +---------+--------------------------------------------+----------+------------+---------------+ | cpu | CPU socket ID where to allocate memory for | YES | uint32_t | 0 | | | the current queue. | | | | +---------+--------------------------------------------+----------+------------+---------------+ EAL section ~~~~~~~~~~~ The application generates the EAL parameters rather than reading them from the command line. The CPU core mask parameter is generated based on the core entry of all PIPELINE sections. All the other EAL parameters can be set from this section of the application configuration file. Library of pipeline types ------------------------- Pipeline module ~~~~~~~~~~~~~~~ A pipeline is a self-contained module that implements a packet processing function and is typically implemented on top of the DPDK Packet Framework *librte_pipeline* library. The application provides a run-time mechanism to register different pipeline types. Depending on the required configuration, each registered pipeline type (pipeline class) is instantiated one or several times, with each pipeline instance (pipeline object) assigned to one of the available CPU cores. Each CPU core can run one or more pipeline instances, which might be of same or different types. For more information of the CPU core threading model, please refer to the :ref:`ip_pipeline_runtime` section. Pipeline type ^^^^^^^^^^^^^ Each pipeline type is made up of a back-end and a front-end. The back-end represents the packet processing engine of the pipeline, typically implemented using the DPDK Packet Framework libraries, which reads packets from the input packet queues, handles them and eventually writes them to the output packet queues or drops them. The front-end represents the run-time configuration interface of the pipeline, which is exposed as CLI commands. The front-end communicates with the back-end through message queues. .. _table_ip_pipelines_back_end: .. tabularcolumns:: |p{1cm}|p{2cm}|p{12cm}| .. table:: Pipeline back-end +------------+------------------+--------------------------------------------------------------------+ | Field name | Field type | Description | +============+==================+====================================================================+ | f_init | Function pointer | Function to initialize the back-end of the current pipeline | | | | instance. Typical work implemented by this function for the | | | | current pipeline instance: | | | | Memory allocation; | | | | Parse the pipeline type specific arguments; | | | | Initialize the pipeline input ports, output ports and tables, | | | | interconnect input ports to tables; | | | | Set the message handlers. | +------------+------------------+--------------------------------------------------------------------+ | f_free | Function pointer | Function to free the resources allocated by the back-end of the | | | | current pipeline instance. | +------------+------------------+--------------------------------------------------------------------+ | f_run | Function pointer | Set to NULL for pipelines implemented using the DPDK library | | | | librte_pipeline (typical case), and to non-NULL otherwise. This | | | | mechanism is made available to support quick integration of | | | | legacy code. | | | | This function is expected to provide the packet processing | | | | related code to be called as part of the CPU thread dispatch | | | | loop, so this function is not allowed to contain an infinite loop. | +------------+------------------+--------------------------------------------------------------------+ | f_timer | Function pointer | Function to read the pipeline input message queues, handle | | | | the request messages, create response messages and write | | | | the response queues. The format of request and response | | | | messages is defined by each pipeline type, with the exception | | | | of some requests which are mandatory for all pipelines (e.g. | | | | ping, statistics). | +------------+------------------+--------------------------------------------------------------------+ | f_track | Function pointer | See section Tracking pipeline output port to physical link | +------------+------------------+--------------------------------------------------------------------+ .. _table_ip_pipelines_front_end: .. tabularcolumns:: |p{1cm}|p{2cm}|p{12cm}| .. table:: Pipeline front-end +------------+-----------------------+-------------------------------------------------------------------+ | Field name | Field type | Description | +============+=======================+===================================================================+ | f_init | Function pointer | Function to initialize the front-end of the current pipeline | | | | instance. | +------------+-----------------------+-------------------------------------------------------------------+ | f_free | Function pointer | Function to free the resources allocated by the front-end of | | | | the current pipeline instance. | +------------+-----------------------+-------------------------------------------------------------------+ | cmds | Array of CLI commands | Array of CLI commands to be registered to the application CLI | | | | for the current pipeline type. Even though the CLI is executed | | | | by a different pipeline (typically, this is the master pipeline), | | | | from modularity perspective is more efficient to keep the | | | | message client side (part of the front-end) together with the | | | | message server side (part of the back-end). | +------------+-----------------------+-------------------------------------------------------------------+ Tracking pipeline output port to physical link ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each pipeline instance is a standalone block that does not have visibility into the other pipeline instances or the application-level pipeline inter-connectivity. In some cases, it is useful for a pipeline instance to get application level information related to pipeline connectivity, such as to identify the output link (e.g. physical NIC port) where one of its output ports connected, either directly or indirectly by traversing other pipeline instances. Tracking can be successful or unsuccessful. Typically, tracking for a specific pipeline instance is successful when each one of its input ports can be mapped to a single output port, meaning that all packets read from the current input port can only go out on a single output port. Depending on the pipeline type, some exceptions may be allowed: a small portion of the packets, considered exception packets, are sent out on an output port that is pre-configured for this purpose. For pass-through pipeline type, the tracking is always successful. For pipeline types as flow classification, firewall or routing, the tracking is only successful when the number of output ports for the current pipeline instance is 1. This feature is used by the IP routing pipeline for adding/removing implicit routes every time a link is brought up/down. Table copies ^^^^^^^^^^^^ Fast table copy: pipeline table used by pipeline for the packet processing task, updated through messages, table data structures are optimized for lookup operation. Slow table copy: used by the configuration layer, typically updated through CLI commands, kept in sync with the fast copy (its update triggers the fast copy update). Required for executing advanced table queries without impacting the packet processing task, therefore the slow copy is typically organized using different criteria than the fast copy. Examples: * Flow classification: Search through current set of flows (e.g. list all flows with a specific source IP address); * Firewall: List rules in descending order of priority; * Routing table: List routes sorted by prefix depth and their type (local, remote, default); * ARP: List entries sorted per output interface. Packet meta-data ^^^^^^^^^^^^^^^^ Packet meta-data field offsets provided as argument to pipeline instances are essentially defining the data structure for the packet meta-data used by the current application use-case. It is very useful to put it in the configuration file as a comment in order to facilitate the readability of the configuration file. The reason to use field offsets for defining the data structure for the packet meta-data is due to the C language limitation of not being able to define data structures at run-time. Feature to consider: have the configuration file parser automatically generate and print the data structure defining the packet meta-data for the current application use-case. Packet meta-data typically contains: 1. Pure meta-data: intermediate data per packet that is computed internally, passed between different tables of the same pipeline instance (e.g. lookup key for the ARP table is obtained from the routing table), or between different pipeline instances (e.g. flow ID, traffic metering color, etc); 2. Packet fields: typically, packet header fields that are read directly from the packet, or read from the packet and saved (duplicated) as a working copy at a different location within the packet meta-data (e.g. Diffserv 5-tuple, IP destination address, etc). Several strategies are used to design the packet meta-data, as described in the next subsections. Store packet meta-data in a different cache line as the packet headers """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" This approach is able to support protocols with variable header length, like MPLS, where the offset of IP header from the start of the packet (and, implicitly, the offset of the IP header in the packet buffer) is not fixed. Since the pipelines typically require the specification of a fixed offset to the packet fields (e.g. Diffserv 5-tuple, used by the flow classification pipeline, or the IP destination address, used by the IP routing pipeline), the workaround is to have the packet RX pipeline copy these fields at fixed offsets within the packet meta-data. As this approach duplicates some of the packet fields, it requires accessing more cache lines per packet for filling in selected packet meta-data fields (on RX), as well as flushing selected packet meta-data fields into the packet (on TX). Example: .. code-block:: ini ; struct app_pkt_metadata { ; uint32_t ip_da; ; uint32_t hash; ; uint32_t flow_id; ; uint32_t color; ; } __attribute__((__packed__)); ; [PIPELINE1] ; Packet meta-data offsets ip_da_offset = 0; Used by: routing hash_offset = 4; Used by: RX, flow classification flow_id_offset = 8; Used by: flow classification, flow actions color_offset = 12; Used by: flow actions, routing Overlay the packet meta-data in the same cache line with the packet headers """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" This approach is minimizing the number of cache line accessed per packet by storing the packet metadata in the same cache line with the packet headers. To enable this strategy, either some headroom is reserved for meta-data at the beginning of the packet headers cache line (e.g. if 16 bytes are needed for meta-data, then the packet headroom can be set to 128+16 bytes, so that NIC writes the first byte of the packet at offset 16 from the start of the first packet cache line), or meta-data is reusing the space of some packet headers that are discarded from the packet (e.g. input Ethernet header). Example: .. code-block:: ini ; struct app_pkt_metadata { ; uint8_t headroom[RTE_PKTMBUF_HEADROOM]; /* 128 bytes (default) */ ; union { ; struct { ; struct ether_hdr ether; /* 14 bytes */ ; struct qinq_hdr qinq; /* 8 bytes */ ; }; ; struct { ; uint32_t hash; ; uint32_t flow_id; ; uint32_t color; ; }; ; }; ; struct ipv4_hdr ip; /* 20 bytes */ ; } __attribute__((__packed__)); ; [PIPELINE2] ; Packet meta-data offsets qinq_offset = 142; Used by: RX, flow classification ip_da_offset = 166; Used by: routing hash_offset = 128; Used by: RX, flow classification flow_id_offset = 132; Used by: flow classification, flow actions color_offset = 136; Used by: flow actions, routing List of pipeline types ~~~~~~~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_types: .. tabularcolumns:: |p{3cm}|p{5cm}|p{4cm}|p{4cm}| .. table:: List of pipeline types provided with the application +-----------------------+-----------------------------+-----------------------+------------------------------------------+ | Name | Table(s) | Actions | Messages | +=======================+=============================+=======================+==========================================+ | Pass-through | Passthrough | 1. Pkt metadata build | 1. Ping | | | | 2. Flow hash | 2. Stats | | Note: depending on | | 3. Pkt checks | | | port type, can be | | 4. Load balancing | | | used for RX, TX, IP | | | | | fragmentation, IP | | | | | reassembly or Traffic | | | | | Management | | | | +-----------------------+-----------------------------+-----------------------+------------------------------------------+ | Flow classification | Exact match | 1. Flow ID | 1. Ping | | | | | | | | * Key = byte array | 2. Flow stats | 2. Stats | | | (source: pkt metadata) | 3. Metering | 3. Flow stats | | | * Data = action dependent | 4. Network Address | 4. Action stats | | | | 5. Translation (NAT) | 5. Flow add/ update/ delete | | | | | 6. Default flow add/ update/ delete | | | | | 7. Action update | +-----------------------+-----------------------------+-----------------------+------------------------------------------+ | Flow actions | Array | 1. Flow stats | 1. Ping | | | | | | | | * Key = Flow ID | 2. Metering | 2. Stats | | | (source: pkt metadata) | 3. Network Address | 3. Action stats | | | * Data = action dependent | 4. Translation (NAT) | 4. Action update | +-----------------------+-----------------------------+-----------------------+------------------------------------------+ | Firewall | ACL | 1. Allow/Drop | 1. Ping | | | | | | | | * Key = n-tuple | | 2. Stats | | | (source: pkt headers) | | 3. Rule add/ update/ delete | | | * Data = none | | 4. Default rule add/ update/ delete | +-----------------------+-----------------------------+-----------------------+------------------------------------------+ | IP routing | LPM (IPv4 or IPv6, | 1. TTL decrement and | 1. Ping | | | depending on pipeline type) | 2. IPv4 checksum | 2. Stats | | | | | | | | * Key = IP destination | 3. update | 3. Route add/ update/ delete | | | (source: pkt metadata) | 4. Header | 4. Default route add/ update/ delete | | | * Data = Dependent on | 5. encapsulation | 5. ARP entry add/ update/ delete | | | actions and next hop | 6. (based on next hop | 6. Default ARP entry add/ update/ delete | | | type | 7. type) | | | | | | | | | Hash table (for ARP, only | | | | | | | | | | when ARP is enabled) | | | | | | | | | | * Key = (Port ID, | | | | | next hop IP address) | | | | | (source: pkt meta-data) | | | | | * Data: MAC address | | | +-----------------------+-----------------------------+-----------------------+------------------------------------------+ Command Line Interface (CLI) ---------------------------- Global CLI commands ~~~~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_cli_commands: .. tabularcolumns:: |p{3cm}|p{6cm}|p{6cm}| .. table:: Global CLI commands +---------+---------------------------------------+--------------------------------------------+ | Command | Description | Syntax | +=========+=======================================+============================================+ | run | Run CLI commands script file. | run | | | | = path to file with CLI commands to | | | | execute | +---------+---------------------------------------+--------------------------------------------+ | quit | Gracefully terminate the application. | quit | +---------+---------------------------------------+--------------------------------------------+ CLI commands for link configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_runtime_config: .. tabularcolumns:: |p{3cm}|p{6cm}|p{6cm}| .. table:: List of run-time configuration commands for link configuration +-------------+--------------------+--------------------------------------------+ | Command | Description | Syntax | +=============+====================+============================================+ | link config | Link configuration | link config | +-------------+--------------------+--------------------------------------------+ | link up | Link up | link up | +-------------+--------------------+--------------------------------------------+ | link down | Link down | link down | +-------------+--------------------+--------------------------------------------+ | link ls | Link list | link ls | +-------------+--------------------+--------------------------------------------+ CLI commands common for all pipeline types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _table_ip_pipelines_mandatory: .. tabularcolumns:: |p{3cm}|p{6cm}|p{6cm}| .. table:: CLI commands mandatory for all pipelines +--------------------+------------------------------------------------------+----------------------------------------------+ | Command | Description | Syntax | +====================+======================================================+==============================================+ | ping | Check whether specific pipeline instance is alive. | p ping | | | The master pipeline sends a ping request | | | | message to given pipeline instance and waits for | | | | a response message back. | | | | Timeout message is displayed when the response | | | | message is not received before the timer | | | | expires. | | +--------------------+------------------------------------------------------+----------------------------------------------+ | stats | Display statistics for specific pipeline input port, | p stats port in | | | output port or table. | p stats port out | | | | p stats table | +--------------------+------------------------------------------------------+----------------------------------------------+ | input port enable | Enable given input port for specific pipeline | p port in enable | | | instance. | | +--------------------+------------------------------------------------------+----------------------------------------------+ | input port disable | Disable given input port for specific pipeline | p port in disable | | | instance. | | +--------------------+------------------------------------------------------+----------------------------------------------+ Pipeline type specific CLI commands ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The pipeline specific CLI commands are part of the pipeline type front-end. ================================================ FILE: doc/guides/sample_app_ug/ip_reassembly.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IP Reassembly Sample Application ================================ The L3 Forwarding application is a simple example of packet processing using the DPDK. The application performs L3 forwarding with reassembly for fragmented IPv4 and IPv6 packets. Overview -------- The application demonstrates the use of the DPDK libraries to implement packet forwarding with reassembly for IPv4 and IPv6 fragmented packets. The initialization and run- time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Sample Application" for more information). The main difference from the L2 Forwarding sample application is that it reassembles fragmented IPv4 and IPv6 packets before forwarding. The maximum allowed size of reassembled packet is 9.5 KB. There are two key differences from the L2 Forwarding sample application: * The first difference is that the forwarding decision is taken based on information read from the input packet's IP header. * The second difference is that the application differentiates between IP and non-IP traffic by means of offload flags. The Longest Prefix Match (LPM for IPv4, LPM6 for IPv6) table is used to store/lookup an outgoing port number, associated with that IPv4 address. Any unmatched packets are forwarded to the originating port.Compiling the Application -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/ip_reassembly #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/ip_reassembly [EAL options] -- -p PORTMASK [-q NQ] [--maxflows=FLOWS>] [--flowttl=TTL[(s|ms)]] where: * -p PORTMASK: Hexadecimal bitmask of ports to configure * -q NQ: Number of RX queues per lcore * --maxflows=FLOWS: determines maximum number of active fragmented flows (1-65535). Default value: 4096. * --flowttl=TTL[(s|ms)]: determines maximum Time To Live for fragmented packet. If all fragments of the packet wouldn't appear within given time-out, then they are considered as invalid and will be dropped. Valid range is 1ms - 3600s. Default value: 1s. To run the example in linuxapp environment with 2 lcores (2,4) over 2 ports(0,2) with 1 RX queue per lcore: .. code-block:: console ./build/ip_reassembly -c 0x14 -n 3 -- -p 5 EAL: coremask set to 14 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 1 EAL: Detected lcore 2 on socket 0 EAL: Detected lcore 3 on socket 1 EAL: Detected lcore 4 on socket 0 ... Initializing port 0 on lcore 2... Address:00:1B:21:76:FA:2C, rxq=0 txq=2,0 txq=4,1 done: Link Up - speed 10000 Mbps - full-duplex Skipping disabled port 1 Initializing port 2 on lcore 4... Address:00:1B:21:5C:FF:54, rxq=0 txq=2,0 txq=4,1 done: Link Up - speed 10000 Mbps - full-duplex Skipping disabled port 3IP_FRAG: Socket 0: adding route 100.10.0.0/16 (port 0) IP_RSMBL: Socket 0: adding route 100.20.0.0/16 (port 1) ... IP_RSMBL: Socket 0: adding route 0101:0101:0101:0101:0101:0101:0101:0101/48 (port 0) IP_RSMBL: Socket 0: adding route 0201:0101:0101:0101:0101:0101:0101:0101/48 (port 1) ... IP_RSMBL: entering main loop on lcore 4 IP_RSMBL: -- lcoreid=4 portid=2 IP_RSMBL: entering main loop on lcore 2 IP_RSMBL: -- lcoreid=2 portid=0 To run the example in linuxapp environment with 1 lcore (4) over 2 ports(0,2) with 2 RX queues per lcore: .. code-block:: console ./build/ip_reassembly -c 0x10 -n 3 -- -p 5 -q 2 To test the application, flows should be set up in the flow generator that match the values in the l3fwd_ipv4_route_array and/or l3fwd_ipv6_route_array table. Please note that in order to test this application, the traffic generator should be generating valid fragmented IP packets. For IPv6, the only supported case is when no other extension headers other than fragment extension header are present in the packet. The default l3fwd_ipv4_route_array table is: .. code-block:: c struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = { {IPv4(100, 10, 0, 0), 16, 0}, {IPv4(100, 20, 0, 0), 16, 1}, {IPv4(100, 30, 0, 0), 16, 2}, {IPv4(100, 40, 0, 0), 16, 3}, {IPv4(100, 50, 0, 0), 16, 4}, {IPv4(100, 60, 0, 0), 16, 5}, {IPv4(100, 70, 0, 0), 16, 6}, {IPv4(100, 80, 0, 0), 16, 7}, }; The default l3fwd_ipv6_route_array table is: .. code-block:: c struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = { {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 0}, {{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 1}, {{3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 2}, {{4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 3}, {{5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 4}, {{6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 5}, {{7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 6}, {{8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 48, 7}, }; For example, for the fragmented input IPv4 packet with destination address: 100.10.1.1, a reassembled IPv4 packet be sent out from port #0 to the destination address 100.10.1.1 once all the fragments are collected. Explanation ----------- The following sections provide some explanation of the sample application code. As mentioned in the overview section, the initialization and run-time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Sample Application" for more information). The following sections describe aspects that are specific to the IP reassemble sample application. IPv4 Fragment Table Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This application uses the rte_ip_frag library. Please refer to Programmer's Guide for more detailed explanation of how to use this library. Fragment table maintains information about already received fragments of the packet. Each IP packet is uniquely identified by triple , , . To avoid lock contention, each RX queue has its own Fragment Table, e.g. the application can't handle the situation when different fragments of the same packet arrive through different RX queues. Each table entry can hold information about packet consisting of up to RTE_LIBRTE_IP_FRAG_MAX_FRAGS fragments. .. code-block:: c frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl; if ((qconf->frag_tbl[queue] = rte_ip_frag_tbl_create(max_flow_num, IPV4_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles, socket)) == NULL) { RTE_LOG(ERR, IP_RSMBL, "ip_frag_tbl_create(%u) on " "lcore: %u for queue: %u failed\n", max_flow_num, lcore, queue); return -1; } Mempools Initialization ~~~~~~~~~~~~~~~~~~~~~~~ The reassembly application demands a lot of mbuf's to be allocated. At any given time up to (2 \* max_flow_num \* RTE_LIBRTE_IP_FRAG_MAX_FRAGS \* ) can be stored inside Fragment Table waiting for remaining fragments. To keep mempool size under reasonable limits and to avoid situation when one RX queue can starve other queues, each RX queue uses its own mempool. .. code-block:: c nb_mbuf = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * RTE_LIBRTE_IP_FRAG_MAX_FRAGS; nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE; nb_mbuf *= 2; /* ipv4 and ipv6 */ nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + RTE_TEST_TX_DESC_DEFAULT; nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)NB_MBUF); rte_snprintf(buf, sizeof(buf), "mbuf_pool_%u_%u", lcore, queue); if ((rxq->pool = rte_mempool_create(buf, nb_mbuf, MBUF_SIZE, 0, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, socket, MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET)) == NULL) { RTE_LOG(ERR, IP_RSMBL, "mempool_create(%s) failed", buf); return -1; } Packet Reassembly and Forwarding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each input packet, the packet forwarding operation is done by the l3fwd_simple_forward() function. If the packet is an IPv4 or IPv6 fragment, then it calls rte_ipv4_reassemble_packet() for IPv4 packets, or rte_ipv6_reassemble_packet() for IPv6 packets. These functions either return a pointer to valid mbuf that contains reassembled packet, or NULL (if the packet can't be reassembled for some reason). Then l3fwd_simple_forward() continues with the code for the packet forwarding decision (that is, the identification of the output interface for the packet) and actual transmit of the packet. The rte_ipv4_reassemble_packet() or rte_ipv6_reassemble_packet() are responsible for: #. Searching the Fragment Table for entry with packet's #. If the entry is found, then check if that entry already timed-out. If yes, then free all previously received fragments, and remove information about them from the entry. #. If no entry with such key is found, then try to create a new one by one of two ways: #. Use as empty entry #. Delete a timed-out entry, free mbufs associated with it mbufs and store a new entry with specified key in it. #. Update the entry with new fragment information and check if a packet can be reassembled (the packet's entry contains all fragments). #. If yes, then, reassemble the packet, mark table's entry as empty and return the reassembled mbuf to the caller. #. If no, then just return a NULL to the caller. If at any stage of packet processing a reassembly function encounters an error (can't insert new entry into the Fragment table, or invalid/timed-out fragment), then it will free all associated with the packet fragments, mark the table entry as invalid and return NULL to the caller. Debug logging and Statistics Collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The RTE_LIBRTE_IP_FRAG_TBL_STAT controls statistics collection for the IP Fragment Table. This macro is disabled by default. To make ip_reassembly print the statistics to the standard output, the user must send either an USR1, INT or TERM signal to the process. For all of these signals, the ip_reassembly process prints Fragment table statistics for each RX queue, plus the INT and TERM will cause process termination as usual. ================================================ FILE: doc/guides/sample_app_ug/ipv4_multicast.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IPv4 Multicast Sample Application ================================= The IPv4 Multicast application is a simple example of packet processing using the Data Plane Development Kit (DPDK). The application performs L3 multicasting. Overview -------- The application demonstrates the use of zero-copy buffers for packet forwarding. The initialization and run-time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Sample Application (in Real and Virtualized Environments)" for details more information). This guide highlights the differences between the two applications. There are two key differences from the L2 Forwarding sample application: * The IPv4 Multicast sample application makes use of indirect buffers. * The forwarding decision is taken based on information read from the input packet's IPv4 header. The lookup method is the Four-byte Key (FBK) hash-based method. The lookup table is composed of pairs of destination IPv4 address (the FBK) and a port mask associated with that IPv4 address. For convenience and simplicity, this sample application does not take IANA-assigned multicast addresses into account, but instead equates the last four bytes of the multicast group (that is, the last four bytes of the destination IP address) with the mask of ports to multicast packets to. Also, the application does not consider the Ethernet addresses; it looks only at the IPv4 destination address for any given packet. Building the Application ------------------------ To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/ipv4_multicast #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make .. note:: The compiled application is written to the build subdirectory. To have the application written to a different location, the O=/path/to/build/directory option may be specified in the make command. Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/ipv4_multicast [EAL options] -- -p PORTMASK [-q NQ] where, * -p PORTMASK: Hexadecimal bitmask of ports to configure * -q NQ: determines the number of queues per lcore .. note:: Unlike the basic L2/L3 Forwarding sample applications, NUMA support is not provided in the IPv4 Multicast sample application. Typically, to run the IPv4 Multicast sample application, issue the following command (as root): .. code-block:: console ./build/ipv4_multicast -c 0x00f -n 3 -- -p 0x3 -q 1 In this command: * The -c option enables cores 0, 1, 2 and 3 * The -n option specifies 3 memory channels * The -p option enables ports 0 and 1 * The -q option assigns 1 queue to each lcore Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. As mentioned in the overview section, the initialization and run-time paths are very similar to those of the L2 Forwarding sample application (see Chapter 9 "L2 Forwarding Sample Application in Real and Virtualized Environments" for more information). The following sections describe aspects that are specific to the IPv4 Multicast sample application. Memory Pool Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~ The IPv4 Multicast sample application uses three memory pools. Two of the pools are for indirect buffers used for packet duplication purposes. Memory pools for indirect buffers are initialized differently from the memory pool for direct buffers: .. code-block:: c packet_pool = rte_mempool_create("packet_pool", NB_PKT_MBUF, PKT_MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); header_pool = rte_mempool_create("header_pool", NB_HDR_MBUF, HDR_MBUF_SIZE, 32, 0, NULL, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); clone_pool = rte_mempool_create("clone_pool", NB_CLONE_MBUF, CLONE_MBUF_SIZE, 32, 0, NULL, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); The reason for this is because indirect buffers are not supposed to hold any packet data and therefore can be initialized with lower amount of reserved memory for each buffer. Hash Initialization ~~~~~~~~~~~~~~~~~~~ The hash object is created and loaded with the pre-configured entries read from a global array: .. code-block:: c static int init_mcast_hash(void) { uint32_t i; mcast_hash_params.socket_id = rte_socket_id(); mcast_hash = rte_fbk_hash_create(&mcast_hash_params); if (mcast_hash == NULL){ return -1; } for (i = 0; i < N_MCAST_GROUPS; i ++){ if (rte_fbk_hash_add_key(mcast_hash, mcast_group_table[i].ip, mcast_group_table[i].port_mask) < 0) { return -1; } } return 0; } Forwarding ~~~~~~~~~~ All forwarding is done inside the mcast_forward() function. Firstly, the Ethernet* header is removed from the packet and the IPv4 address is extracted from the IPv4 header: .. code-block:: c /* Remove the Ethernet header from the input packet */ iphdr = (struct ipv4_hdr *)rte_pktmbuf_adj(m, sizeof(struct ether_hdr)); RTE_MBUF_ASSERT(iphdr != NULL); dest_addr = rte_be_to_cpu_32(iphdr->dst_addr); Then, the packet is checked to see if it has a multicast destination address and if the routing table has any ports assigned to the destination address: .. code-block:: c if (!IS_IPV4_MCAST(dest_addr) || (hash = rte_fbk_hash_lookup(mcast_hash, dest_addr)) <= 0 || (port_mask = hash & enabled_port_mask) == 0) { rte_pktmbuf_free(m); return; } Then, the number of ports in the destination portmask is calculated with the help of the bitcnt() function: .. code-block:: c /* Get number of bits set. */ static inline uint32_t bitcnt(uint32_t v) { uint32_t n; for (n = 0; v != 0; v &= v - 1, n++) ; return (n); } This is done to determine which forwarding algorithm to use. This is explained in more detail in the next section. Thereafter, a destination Ethernet address is constructed: .. code-block:: c /* construct destination Ethernet address */ dst_eth_addr = ETHER_ADDR_FOR_IPV4_MCAST(dest_addr); Since Ethernet addresses are also part of the multicast process, each outgoing packet carries the same destination Ethernet address. The destination Ethernet address is constructed from the lower 23 bits of the multicast group OR-ed with the Ethernet address 01:00:5e:00:00:00, as per RFC 1112: .. code-block:: c #define ETHER_ADDR_FOR_IPV4_MCAST(x) \ (rte_cpu_to_be_64(0x01005e000000ULL | ((x) & 0x7fffff)) >> 16) Then, packets are dispatched to the destination ports according to the portmask associated with a multicast group: .. code-block:: c for (port = 0; use_clone != port_mask; port_mask >>= 1, port++) { /* Prepare output packet and send it out. */ if ((port_mask & 1) != 0) { if (likely ((mc = mcast_out_pkt(m, use_clone)) != NULL)) mcast_send_pkt(mc, &dst_eth_addr.as_addr, qconf, port); else if (use_clone == 0) rte_pktmbuf_free(m); } } The actual packet transmission is done in the mcast_send_pkt() function: .. code-block:: c static inline void mcast_send_pkt(struct rte_mbuf *pkt, struct ether_addr *dest_addr, struct lcore_queue_conf *qconf, uint8_t port) { struct ether_hdr *ethdr; uint16_t len; /* Construct Ethernet header. */ ethdr = (struct ether_hdr *)rte_pktmbuf_prepend(pkt, (uint16_t) sizeof(*ethdr)); RTE_MBUF_ASSERT(ethdr != NULL); ether_addr_copy(dest_addr, ðdr->d_addr); ether_addr_copy(&ports_eth_addr[port], ðdr->s_addr); ethdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); /* Put new packet into the output queue */ len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = pkt; qconf->tx_mbufs[port].len = ++len; /* Transmit packets */ if (unlikely(MAX_PKT_BURST == len)) send_burst(qconf, port); } Buffer Cloning ~~~~~~~~~~~~~~ This is the most important part of the application since it demonstrates the use of zero- copy buffer cloning. There are two approaches for creating the outgoing packet and although both are based on the data zero-copy idea, there are some differences in the detail. The first approach creates a clone of the input packet, for example, walk though all segments of the input packet and for each of segment, create a new buffer and attach that new buffer to the segment (refer to rte_pktmbuf_clone() in the rte_mbuf library for more details). A new buffer is then allocated for the packet header and is prepended to the cloned buffer. The second approach does not make a clone, it just increments the reference counter for all input packet segment, allocates a new buffer for the packet header and prepends it to the input packet. Basically, the first approach reuses only the input packet's data, but creates its own copy of packet's metadata. The second approach reuses both input packet's data and metadata. The advantage of first approach is that each outgoing packet has its own copy of the metadata, so we can safely modify the data pointer of the input packet. That allows us to skip creation if the output packet is for the last destination port and instead modify input packet's header in place. For example, for N destination ports, we need to invoke mcast_out_pkt() (N-1) times. The advantage of the second approach is that there is less work to be done for each outgoing packet, that is, the "clone" operation is skipped completely. However, there is a price to pay. The input packet's metadata must remain intact, so for N destination ports, we need to invoke mcast_out_pkt() (N) times. Therefore, for a small number of outgoing ports (and segments in the input packet), first approach is faster. As the number of outgoing ports (and/or input segments) grows, the second approach becomes more preferable. Depending on the number of segments or the number of ports in the outgoing portmask, either the first (with cloning) or the second (without cloning) approach is taken: .. code-block:: c use_clone = (port_num <= MCAST_CLONE_PORTS && m->pkt.nb_segs <= MCAST_CLONE_SEGS); It is the mcast_out_pkt() function that performs the packet duplication (either with or without actually cloning the buffers): .. code-block:: c static inline struct rte_mbuf *mcast_out_pkt(struct rte_mbuf *pkt, int use_clone) { struct rte_mbuf *hdr; /* Create new mbuf for the header. */ if (unlikely ((hdr = rte_pktmbuf_alloc(header_pool)) == NULL)) return (NULL); /* If requested, then make a new clone packet. */ if (use_clone != 0 && unlikely ((pkt = rte_pktmbuf_clone(pkt, clone_pool)) == NULL)) { rte_pktmbuf_free(hdr); return (NULL); } /* prepend new header */ hdr->pkt.next = pkt; /* update header's fields */ hdr->pkt.pkt_len = (uint16_t)(hdr->pkt.data_len + pkt->pkt.pkt_len); hdr->pkt.nb_segs = (uint8_t)(pkt->pkt.nb_segs + 1); /* copy metadata from source packet */ hdr->pkt.in_port = pkt->pkt.in_port; hdr->pkt.vlan_macip = pkt->pkt.vlan_macip; hdr->pkt.hash = pkt->pkt.hash; hdr->ol_flags = pkt->ol_flags; rte_mbuf_sanity_check(hdr, RTE_MBUF_PKT, 1); return (hdr); } ================================================ FILE: doc/guides/sample_app_ug/kernel_nic_interface.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Kernel NIC Interface Sample Application ======================================= The Kernel NIC Interface (KNI) is a DPDK control plane solution that allows userspace applications to exchange packets with the kernel networking stack. To accomplish this, DPDK userspace applications use an IOCTL call to request the creation of a KNI virtual device in the Linux* kernel. The IOCTL call provides interface information and the DPDK's physical address space, which is re-mapped into the kernel address space by the KNI kernel loadable module that saves the information to a virtual device context. The DPDK creates FIFO queues for packet ingress and egress to the kernel module for each device allocated. The KNI kernel loadable module is a standard net driver, which upon receiving the IOCTL call access the DPDK's FIFO queue to receive/transmit packets from/to the DPDK userspace application. The FIFO queues contain pointers to data packets in the DPDK. This: * Provides a faster mechanism to interface with the kernel net stack and eliminates system calls * Facilitates the DPDK using standard Linux* userspace net tools (tcpdump, ftp, and so on) * Eliminate the copy_to_user and copy_from_user operations on packets. The Kernel NIC Interface sample application is a simple example that demonstrates the use of the DPDK to create a path for packets to go through the Linux* kernel. This is done by creating one or more kernel net devices for each of the DPDK ports. The application allows the use of standard Linux tools (ethtool, ifconfig, tcpdump) with the DPDK ports and also the exchange of packets between the DPDK application and the Linux* kernel. Overview -------- The Kernel NIC Interface sample application uses two threads in user space for each physical NIC port being used, and allocates one or more KNI device for each physical NIC port with kernel module's support. For a physical NIC port, one thread reads from the port and writes to KNI devices, and another thread reads from KNI devices and writes the data unmodified to the physical NIC port. It is recommended to configure one KNI device for each physical NIC port. If configured with more than one KNI devices for a physical NIC port, it is just for performance testing, or it can work together with VMDq support in future. The packet flow through the Kernel NIC Interface application is as shown in the following figure. .. _figure_kernel_nic: .. figure:: img/kernel_nic.* Kernel NIC Application Packet Flow Compiling the Application ------------------------- Compile the application as follows: #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/kni #. Set the target (a default target is used if not specified) .. note:: This application is intended as a linuxapp only. .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application: .. code-block:: console make Loading the Kernel Module ------------------------- Loading the KNI kernel module without any parameter is the typical way a DPDK application gets packets into and out of the kernel net stack. This way, only one kernel thread is created for all KNI devices for packet receiving in kernel side: .. code-block:: console #insmod rte_kni.ko Pinning the kernel thread to a specific core can be done using a taskset command such as following: .. code-block:: console #taskset -p 100000 `pgrep --fl kni_thread | awk '{print $1}'` This command line tries to pin the specific kni_thread on the 20th lcore (lcore numbering starts at 0), which means it needs to check if that lcore is available on the board. This command must be sent after the application has been launched, as insmod does not start the kni thread. For optimum performance, the lcore in the mask must be selected to be on the same socket as the lcores used in the KNI application. To provide flexibility of performance, the kernel module of the KNI, located in the kmod sub-directory of the DPDK target directory, can be loaded with parameter of kthread_mode as follows: * #insmod rte_kni.ko kthread_mode=single This mode will create only one kernel thread for all KNI devices for packet receiving in kernel side. By default, it is in this single kernel thread mode. It can set core affinity for this kernel thread by using Linux command taskset. * #insmod rte_kni.ko kthread_mode =multiple This mode will create a kernel thread for each KNI device for packet receiving in kernel side. The core affinity of each kernel thread is set when creating the KNI device. The lcore ID for each kernel thread is provided in the command line of launching the application. Multiple kernel thread mode can provide scalable higher performance. To measure the throughput in a loopback mode, the kernel module of the KNI, located in the kmod sub-directory of the DPDK target directory, can be loaded with parameters as follows: * #insmod rte_kni.ko lo_mode=lo_mode_fifo This loopback mode will involve ring enqueue/dequeue operations in kernel space. * #insmod rte_kni.ko lo_mode=lo_mode_fifo_skb This loopback mode will involve ring enqueue/dequeue operations and sk buffer copies in kernel space. Running the Application ----------------------- The application requires a number of command line options: .. code-block:: console kni [EAL options] -- -P -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,port,lcore_rx,lcore_tx[,lcore_kthread,...]]" Where: * -P: Set all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. * -p PORTMASK: Hexadecimal bitmask of ports to configure. * --config="(port,lcore_rx, lcore_tx[,lcore_kthread, ...]) [, port,lcore_rx, lcore_tx[,lcore_kthread, ...]]": Determines which lcores of RX, TX, kernel thread are mapped to which ports. Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. The -c coremask parameter of the EAL options should include the lcores indicated by the lcore_rx and lcore_tx, but does not need to include lcores indicated by lcore_kthread as they are used to pin the kernel thread on. The -p PORTMASK parameter should include the ports indicated by the port in --config, neither more nor less. The lcore_kthread in --config can be configured none, one or more lcore IDs. In multiple kernel thread mode, if configured none, a KNI device will be allocated for each port, while no specific lcore affinity will be set for its kernel thread. If configured one or more lcore IDs, one or more KNI devices will be allocated for each port, while specific lcore affinity will be set for its kernel thread. In single kernel thread mode, if configured none, a KNI device will be allocated for each port. If configured one or more lcore IDs, one or more KNI devices will be allocated for each port while no lcore affinity will be set as there is only one kernel thread for all KNI devices. For example, to run the application with two ports served by six lcores, one lcore of RX, one lcore of TX, and one lcore of kernel thread for each port: .. code-block:: console ./build/kni -c 0xf0 -n 4 -- -P -p 0x3 -config="(0,4,6,8),(1,5,7,9)" KNI Operations -------------- Once the KNI application is started, one can use different Linux* commands to manage the net interfaces. If more than one KNI devices configured for a physical port, only the first KNI device will be paired to the physical device. Operations on other KNI devices will not affect the physical port handled in user space application. Assigning an IP address: .. code-block:: console #ifconfig vEth0_0 192.168.0.1 Displaying the NIC registers: .. code-block:: console #ethtool -d vEth0_0 Dumping the network traffic: .. code-block:: console #tcpdump -i vEth0_0 When the DPDK userspace application is closed, all the KNI devices are deleted from Linux*. Explanation ----------- The following sections provide some explanation of code. Initialization ~~~~~~~~~~~~~~ Setup of mbuf pool, driver and queues is similar to the setup done in the L2 Forwarding sample application (see Chapter 9 "L2 Forwarding Sample Application (in Real and Virtualized Environments" for details). In addition, one or more kernel NIC interfaces are allocated for each of the configured ports according to the command line parameters. The code for creating the kernel NIC interface for a specific port is as follows: .. code-block:: c kni = rte_kni_create(port, MAX_PACKET_SZ, pktmbuf_pool, &kni_ops); if (kni == NULL) rte_exit(EXIT_FAILURE, "Fail to create kni dev " "for port: %d\n", port); The code for allocating the kernel NIC interfaces for a specific port is as follows: .. code-block:: c static int kni_alloc(uint8_t port_id) { uint8_t i; struct rte_kni *kni; struct rte_kni_conf conf; struct kni_port_params **params = kni_port_params_array; if (port_id >= RTE_MAX_ETHPORTS || !params[port_id]) return -1; params[port_id]->nb_kni = params[port_id]->nb_lcore_k ? params[port_id]->nb_lcore_k : 1; for (i = 0; i < params[port_id]->nb_kni; i++) { /* Clear conf at first */ memset(&conf, 0, sizeof(conf)); if (params[port_id]->nb_lcore_k) { rte_snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u_%u", port_id, i); conf.core_id = params[port_id]->lcore_k[i]; conf.force_bind = 1; } else rte_snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", port_id); conf.group_id = (uint16_t)port_id; conf.mbuf_size = MAX_PACKET_SZ; /* * The first KNI device associated to a port * is the master, for multiple kernel thread * environment. */ if (i == 0) { struct rte_kni_ops ops; struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); conf.addr = dev_info.pci_dev->addr; conf.id = dev_info.pci_dev->id; memset(&ops, 0, sizeof(ops)); ops.port_id = port_id; ops.change_mtu = kni_change_mtu; ops.config_network_if = kni_config_network_interface; kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops); } else kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL); if (!kni) rte_exit(EXIT_FAILURE, "Fail to create kni for " "port: %d\n", port_id); params[port_id]->kni[i] = kni; } return 0; } The other step in the initialization process that is unique to this sample application is the association of each port with lcores for RX, TX and kernel threads. * One lcore to read from the port and write to the associated one or more KNI devices * Another lcore to read from one or more KNI devices and write to the port * Other lcores for pinning the kernel threads on one by one This is done by using the`kni_port_params_array[]` array, which is indexed by the port ID. The code is as follows: .. code-block:: console static int parse_config(const char *arg) { const char *p, *p0 = arg; char s[256], *end; unsigned size; enum fieldnames { FLD_PORT = 0, FLD_LCORE_RX, FLD_LCORE_TX, _NUM_FLD = KNI_MAX_KTHREAD + 3, }; int i, j, nb_token; char *str_fld[_NUM_FLD]; unsigned long int_fld[_NUM_FLD]; uint8_t port_id, nb_kni_port_params = 0; memset(&kni_port_params_array, 0, sizeof(kni_port_params_array)); while (((p = strchr(p0, '(')) != NULL) && nb_kni_port_params < RTE_MAX_ETHPORTS) { p++; if ((p0 = strchr(p, ')')) == NULL) goto fail; size = p0 - p; if (size >= sizeof(s)) { printf("Invalid config parameters\n"); goto fail; } rte_snprintf(s, sizeof(s), "%.*s", size, p); nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ','); if (nb_token <= FLD_LCORE_TX) { printf("Invalid config parameters\n"); goto fail; } for (i = 0; i < nb_token; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i]) { printf("Invalid config parameters\n"); goto fail; } } i = 0; port_id = (uint8_t)int_fld[i++]; if (port_id >= RTE_MAX_ETHPORTS) { printf("Port ID %u could not exceed the maximum %u\n", port_id, RTE_MAX_ETHPORTS); goto fail; } if (kni_port_params_array[port_id]) { printf("Port %u has been configured\n", port_id); goto fail; } kni_port_params_array[port_id] = (struct kni_port_params*)rte_zmalloc("KNI_port_params", sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE); kni_port_params_array[port_id]->port_id = port_id; kni_port_params_array[port_id]->lcore_rx = (uint8_t)int_fld[i++]; kni_port_params_array[port_id]->lcore_tx = (uint8_t)int_fld[i++]; if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE || kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) { printf("lcore_rx %u or lcore_tx %u ID could not " "exceed the maximum %u\n", kni_port_params_array[port_id]->lcore_rx, kni_port_params_array[port_id]->lcore_tx, RTE_MAX_LCORE); goto fail; } for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++) kni_port_params_array[port_id]->lcore_k[j] = (uint8_t)int_fld[i]; kni_port_params_array[port_id]->nb_lcore_k = j; } print_config(); return 0; fail: for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (kni_port_params_array[i]) { rte_free(kni_port_params_array[i]); kni_port_params_array[i] = NULL; } } return -1; } Packet Forwarding ~~~~~~~~~~~~~~~~~ After the initialization steps are completed, the main_loop() function is run on each lcore. This function first checks the lcore_id against the user provided lcore_rx and lcore_tx to see if this lcore is reading from or writing to kernel NIC interfaces. For the case that reads from a NIC port and writes to the kernel NIC interfaces, the packet reception is the same as in L2 Forwarding sample application (see Section 9.4.6 "Receive, Process and Transmit Packets"). The packet transmission is done by sending mbufs into the kernel NIC interfaces by rte_kni_tx_burst(). The KNI library automatically frees the mbufs after the kernel successfully copied the mbufs. .. code-block:: c /** * Interface to burst rx and enqueue mbufs into rx_q */ static void kni_ingress(struct kni_port_params *p) { uint8_t i, nb_kni, port_id; unsigned nb_rx, num; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; if (p == NULL) return; nb_kni = p->nb_kni; port_id = p->port_id; for (i = 0; i < nb_kni; i++) { /* Burst rx from eth */ nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ); if (unlikely(nb_rx > PKT_BURST_SZ)) { RTE_LOG(ERR, APP, "Error receiving from eth\n"); return; } /* Burst tx to kni */ num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx); kni_stats[port_id].rx_packets += num; rte_kni_handle_request(p->kni[i]); if (unlikely(num < nb_rx)) { /* Free mbufs not tx to kni interface */ kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num); kni_stats[port_id].rx_dropped += nb_rx - num; } } } For the other case that reads from kernel NIC interfaces and writes to a physical NIC port, packets are retrieved by reading mbufs from kernel NIC interfaces by `rte_kni_rx_burst()`. The packet transmission is the same as in the L2 Forwarding sample application (see Section 9.4.6 "Receive, Process and Transmit Packet's"). .. code-block:: c /** * Interface to dequeue mbufs from tx_q and burst tx */ static void kni_egress(struct kni_port_params *p) { uint8_t i, nb_kni, port_id; unsigned nb_tx, num; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; if (p == NULL) return; nb_kni = p->nb_kni; port_id = p->port_id; for (i = 0; i < nb_kni; i++) { /* Burst rx from kni */ num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ); if (unlikely(num > PKT_BURST_SZ)) { RTE_LOG(ERR, APP, "Error receiving from KNI\n"); return; } /* Burst tx to eth */ nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num); kni_stats[port_id].tx_packets += nb_tx; if (unlikely(nb_tx < num)) { /* Free mbufs not tx to NIC */ kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx); kni_stats[port_id].tx_dropped += num - nb_tx; } } } Callbacks for Kernel Requests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To execute specific PMD operations in user space requested by some Linux* commands, callbacks must be implemented and filled in the struct rte_kni_ops structure. Currently, setting a new MTU and configuring the network interface (up/ down) are supported. .. code-block:: c static struct rte_kni_ops kni_ops = { .change_mtu = kni_change_mtu, .config_network_if = kni_config_network_interface, }; /* Callback for request of changing MTU */ static int kni_change_mtu(uint8_t port_id, unsigned new_mtu) { int ret; struct rte_eth_conf conf; if (port_id >= rte_eth_dev_count()) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu); /* Stop specific port */ rte_eth_dev_stop(port_id); memcpy(&conf, &port_conf, sizeof(conf)); /* Set new MTU */ if (new_mtu > ETHER_MAX_LEN) conf.rxmode.jumbo_frame = 1; else conf.rxmode.jumbo_frame = 0; /* mtu + length of header + length of FCS = max pkt length */ conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE + KNI_ENET_FCS_SIZE; ret = rte_eth_dev_configure(port_id, 1, 1, &conf); if (ret < 0) { RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id); return ret; } /* Restart specific port */ ret = rte_eth_dev_start(port_id); if (ret < 0) { RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id); return ret; } return 0; } /* Callback for request of configuring network interface up/down */ static int kni_config_network_interface(uint8_t port_id, uint8_t if_up) { int ret = 0; if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } RTE_LOG(INFO, APP, "Configure network interface of %d %s\n", port_id, if_up ? "up" : "down"); if (if_up != 0) { /* Configure network interface up */ rte_eth_dev_stop(port_id); ret = rte_eth_dev_start(port_id); } else /* Configure network interface down */ rte_eth_dev_stop(port_id); if (ret < 0) RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id); return ret; } ================================================ FILE: doc/guides/sample_app_ug/l2_forward_job_stats.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L2 Forwarding Sample Application (in Real and Virtualized Environments) with core load statistics. ================================================================================================== The L2 Forwarding sample application is a simple example of packet processing using the Data Plane Development Kit (DPDK) which also takes advantage of Single Root I/O Virtualization (SR-IOV) features in a virtualized environment. .. note:: This application is a variation of L2 Forwarding sample application. It demonstrate possible scheme of job stats library usage therefore some parts of this document is identical with original L2 forwarding application. Overview -------- The L2 Forwarding sample application, which can operate in real and virtualized environments, performs L2 forwarding for each packet that is received. The destination port is the adjacent port from the enabled portmask, that is, if the first four ports are enabled (portmask 0xf), ports 1 and 2 forward into each other, and ports 3 and 4 forward into each other. Also, the MAC addresses are affected as follows: * The source MAC address is replaced by the TX port MAC address * The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID This application can be used to benchmark performance using a traffic-generator, as shown in the :numref:`figure_l2_fwd_benchmark_setup_jobstats`. The application can also be used in a virtualized environment as shown in :numref:`figure_l2_fwd_virtenv_benchmark_setup_jobstats`. The L2 Forwarding application can also be used as a starting point for developing a new application based on the DPDK. .. _figure_l2_fwd_benchmark_setup_jobstats: .. figure:: img/l2_fwd_benchmark_setup.* Performance Benchmark Setup (Basic Environment) .. _figure_l2_fwd_virtenv_benchmark_setup_jobstats: .. figure:: img/l2_fwd_virtenv_benchmark_setup.* Performance Benchmark Setup (Virtualized Environment) Virtual Function Setup Instructions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This application can use the virtual function available in the system and therefore can be used in a virtual machine without passing through the whole Network Device into a guest machine in a virtualized scenario. The virtual functions can be enabled in the host machine or the hypervisor with the respective physical function driver. For example, in a Linux* host machine, it is possible to enable a virtual function using the following command: .. code-block:: console modprobe ixgbe max_vfs=2,2 This command enables two Virtual Functions on each of Physical Function of the NIC, with two physical ports in the PCI configuration space. It is important to note that enabled Virtual Function 0 and 2 would belong to Physical Function 0 and Virtual Function 1 and 3 would belong to Physical Function 1, in this case enabling a total of four Virtual Functions. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l2fwd-jobstats #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc *See the DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application requires a number of command line options: .. code-block:: console ./build/l2fwd-jobstats [EAL options] -- -p PORTMASK [-q NQ] [-l] where, * p PORTMASK: A hexadecimal bitmask of the ports to configure * q NQ: A number of queues (=ports) per lcore (default is 1) * l: Use locale thousands separator when formatting big numbers. To run the application in linuxapp environment with 4 lcores, 16 ports, 8 RX queues per lcore and thousands separator printing, issue the command: .. code-block:: console $ ./build/l2fwd-jobstats -c f -n 4 -- -q 8 -p ffff -l Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. Command Line Arguments ~~~~~~~~~~~~~~~~~~~~~~ The L2 Forwarding sample application takes specific parameters, in addition to Environment Abstraction Layer (EAL) arguments (see Section 9.3). The preferred way to parse parameters is to use the getopt() function, since it is part of a well-defined and portable library. The parsing of arguments is done in the l2fwd_parse_args() function. The method of argument parsing is not described here. Refer to the *glibc getopt(3)* man page for details. EAL arguments are parsed first, then application-specific arguments. This is done at the beginning of the main() function: .. code-block:: c /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); Mbuf Pool Initialization ~~~~~~~~~~~~~~~~~~~~~~~~ Once the arguments are parsed, the mbuf pool is created. The mbuf pool contains a set of mbuf objects that will be used by the driver and the application to store network packet data: .. code-block:: c /* create the mbuf pool */ l2fwd_pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); The rte_mempool is a generic structure used to handle pools of objects. In this case, it is necessary to create a pool that will be used by the driver, which expects to have some reserved space in the mempool structure, sizeof(struct rte_pktmbuf_pool_private) bytes. The number of allocated pkt mbufs is NB_MBUF, with a size of MBUF_SIZE each. A per-lcore cache of 32 mbufs is kept. The memory is allocated in rte_socket_id() socket, but it is possible to extend this code to allocate one mbuf pool per socket. Two callback pointers are also given to the rte_mempool_create() function: * The first callback pointer is to rte_pktmbuf_pool_init() and is used to initialize the private data of the mempool, which is needed by the driver. This function is provided by the mbuf API, but can be copied and extended by the developer. * The second callback pointer given to rte_mempool_create() is the mbuf initializer. The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. If a more complex application wants to extend the rte_pktmbuf structure for its own needs, a new function derived from rte_pktmbuf_init( ) can be created. Driver Initialization ~~~~~~~~~~~~~~~~~~~~~ The main part of the code in the main() function relates to the initialization of the driver. To fully understand this code, it is recommended to study the chapters that related to the Poll Mode Driver in the *DPDK Programmer's Guide* and the *DPDK API Reference*. .. code-block:: c nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* reset l2fwd_dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { l2fwd_dst_ports[portid] = last_port; l2fwd_dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get((uint8_t) portid, &dev_info); } The next step is to configure the RX and TX queues. For each port, there is only one RX queue (only one lcore is able to poll a given port). The number of TX queues depends on the number of available lcores. The rte_eth_dev_configure() function is used to configure the number of queues for a port: .. code-block:: c ret = rte_eth_dev_configure((uint8_t)portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%u\n", ret, portid); The global configuration is stored in a static structure: .. code-block:: c static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc= 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_DCB_NONE }, }; RX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ The application uses one lcore to poll one or several ports, depending on the -q option, which specifies the number of queues per lcore. For example, if the user specifies -q 4, the application is able to poll four ports with one lcore. If there are 16 ports on the target (and if the portmask argument is -p ffff ), the application will need four lcores to poll all the ports. .. code-block:: c ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, l2fwd_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); The list of queues that must be polled for a given lcore is stored in a private structure called struct lcore_queue_conf. .. code-block:: c struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; truct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; struct rte_timer rx_timers[MAX_RX_QUEUE_PER_LCORE]; struct rte_jobstats port_fwd_jobs[MAX_RX_QUEUE_PER_LCORE]; struct rte_timer flush_timer; struct rte_jobstats flush_job; struct rte_jobstats idle_job; struct rte_jobstats_context jobs_context; rte_atomic16_t stats_read_pending; rte_spinlock_t lock; } __rte_cache_aligned; Values of struct lcore_queue_conf: * n_rx_port and rx_port_list[] are used in the main packet processing loop (see Section 9.4.6 "Receive, Process and Transmit Packets" later in this chapter). * rx_timers and flush_timer are used to ensure forced TX on low packet rate. * flush_job, idle_job and jobs_context are librte_jobstats objects used for managing l2fwd jobs. * stats_read_pending and lock are used during job stats read phase. TX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ Each lcore should be able to transmit on any port. For every port, a single TX queue is initialized. .. code-block:: c /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); Jobs statistics initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are several statistics objects available: * Flush job statistics .. code-block:: c rte_jobstats_init(&qconf->flush_job, "flush", drain_tsc, drain_tsc, drain_tsc, 0); rte_timer_init(&qconf->flush_timer); ret = rte_timer_reset(&qconf->flush_timer, drain_tsc, PERIODICAL, lcore_id, &l2fwd_flush_job, NULL); if (ret < 0) { rte_exit(1, "Failed to reset flush job timer for lcore %u: %s", lcore_id, rte_strerror(-ret)); } * Statistics per RX port .. code-block:: c rte_jobstats_init(job, name, 0, drain_tsc, 0, MAX_PKT_BURST); rte_jobstats_set_update_period_function(job, l2fwd_job_update_cb); rte_timer_init(&qconf->rx_timers[i]); ret = rte_timer_reset(&qconf->rx_timers[i], 0, PERIODICAL, lcore_id, l2fwd_fwd_job, (void *)(uintptr_t)i); if (ret < 0) { rte_exit(1, "Failed to reset lcore %u port %u job timer: %s", lcore_id, qconf->rx_port_list[i], rte_strerror(-ret)); } Following parameters are passed to rte_jobstats_init(): * 0 as minimal poll period * drain_tsc as maximum poll period * MAX_PKT_BURST as desired target value (RX burst size) Main loop ~~~~~~~~~ The forwarding path is reworked comparing to original L2 Forwarding application. In the l2fwd_main_loop() function three loops are placed. .. code-block:: c for (;;) { rte_spinlock_lock(&qconf->lock); do { rte_jobstats_context_start(&qconf->jobs_context); /* Do the Idle job: * - Read stats_read_pending flag * - check if some real job need to be executed */ rte_jobstats_start(&qconf->jobs_context, &qconf->idle_job); do { uint8_t i; uint64_t now = rte_get_timer_cycles(); need_manage = qconf->flush_timer.expire < now; /* Check if we was esked to give a stats. */ stats_read_pending = rte_atomic16_read(&qconf->stats_read_pending); need_manage |= stats_read_pending; for (i = 0; i < qconf->n_rx_port && !need_manage; i++) need_manage = qconf->rx_timers[i].expire < now; } while (!need_manage); rte_jobstats_finish(&qconf->idle_job, qconf->idle_job.target); rte_timer_manage(); rte_jobstats_context_finish(&qconf->jobs_context); } while (likely(stats_read_pending == 0)); rte_spinlock_unlock(&qconf->lock); rte_pause(); } First infinite for loop is to minimize impact of stats reading. Lock is only locked/unlocked when asked. Second inner while loop do the whole jobs management. When any job is ready, the use rte_timer_manage() is used to call the job handler. In this place functions l2fwd_fwd_job() and l2fwd_flush_job() are called when needed. Then rte_jobstats_context_finish() is called to mark loop end - no other jobs are ready to execute. By this time stats are ready to be read and if stats_read_pending is set, loop breaks allowing stats to be read. Third do-while loop is the idle job (idle stats counter). Its only purpose is monitoring if any job is ready or stats job read is pending for this lcore. Statistics from this part of code is considered as the headroom available for additional processing. Receive, Process and Transmit Packets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main task of l2fwd_fwd_job() function is to read ingress packets from the RX queue of particular port and forward it. This is done using the following code: .. code-block:: c total_nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); for (j = 0; j < total_nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } Packets are read in a burst of size MAX_PKT_BURST. Then, each mbuf in the table is processed by the l2fwd_simple_forward() function. The processing is very simple: process the TX port from the RX port, then replace the source and destination MAC addresses. The rte_eth_rx_burst() function writes the mbuf pointers in a local table and returns the number of available mbufs in the table. After first read second try is issued. .. code-block:: c if (total_nb_rx == MAX_PKT_BURST) { const uint16_t nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); total_nb_rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } } This second read is important to give job stats library a feedback how many packets was processed. .. code-block:: c /* Adjust period time in which we are running here. */ if (rte_jobstats_finish(job, total_nb_rx) != 0) { rte_timer_reset(&qconf->rx_timers[port_idx], job->period, PERIODICAL, lcore_id, l2fwd_fwd_job, arg); } To maximize performance exactly MAX_PKT_BURST is expected (the target value) to be read for each l2fwd_fwd_job() call. If total_nb_rx is smaller than target value job->period will be increased. If it is greater the period will be decreased. .. note:: In the following code, one line for getting the output port requires some explanation. During the initialization process, a static array of destination ports (l2fwd_dst_ports[]) is filled such that for each source port, a destination port is assigned that is either the next or previous enabled port from the portmask. Naturally, the number of ports in the portmask must be even, otherwise, the application exits. .. code-block:: c static void l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port; dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t) dst_port << 40); /* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); l2fwd_send_packet(m, (uint8_t) dst_port); } Then, the packet is sent using the l2fwd_send_packet (m, dst_port) function. For this test application, the processing is exactly the same for all packets arriving on the same RX port. Therefore, it would have been possible to call the l2fwd_send_burst() function directly from the main loop to send all the received packets on the same TX port, using the burst-oriented send function, which is more efficient. However, in real-life applications (such as, L3 routing), packet N is not necessarily forwarded on the same port as packet N-1. The application is implemented to illustrate that, so the same approach can be reused in a more complex application. The l2fwd_send_packet() function stores the packet in a per-lcore and per-txport table. If the table is full, the whole packets table is transmitted using the l2fwd_send_burst() function: .. code-block:: c /* Send the packet on an output interface */ static int l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { l2fwd_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } To ensure that no packets remain in the tables, the flush job exists. The l2fwd_flush_job() is called periodically to for each lcore draining TX queue of each port. This technique introduces some latency when there are not many packets to send, however it improves performance: .. code-block:: c static void l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg) { uint64_t now; unsigned lcore_id; struct lcore_queue_conf *qconf; struct mbuf_table *m_table; uint8_t portid; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; rte_jobstats_start(&qconf->jobs_context, &qconf->flush_job); now = rte_get_timer_cycles(); lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { m_table = &qconf->tx_mbufs[portid]; if (m_table->len == 0 || m_table->next_flush_time <= now) continue; l2fwd_send_burst(qconf, portid); } /* Pass target to indicate that this job is happy of time interval * in which it was called. */ rte_jobstats_finish(&qconf->flush_job, qconf->flush_job.target); } ================================================ FILE: doc/guides/sample_app_ug/l2_forward_real_virtual.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L2 Forwarding Sample Application (in Real and Virtualized Environments) ======================================================================= The L2 Forwarding sample application is a simple example of packet processing using the Data Plane Development Kit (DPDK) which also takes advantage of Single Root I/O Virtualization (SR-IOV) features in a virtualized environment. .. note:: Please note that previously a separate L2 Forwarding in Virtualized Environments sample application was used, however, in later DPDK versions these sample applications have been merged. Overview -------- The L2 Forwarding sample application, which can operate in real and virtualized environments, performs L2 forwarding for each packet that is received on an RX_PORT. The destination port is the adjacent port from the enabled portmask, that is, if the first four ports are enabled (portmask 0xf), ports 1 and 2 forward into each other, and ports 3 and 4 forward into each other. Also, the MAC addresses are affected as follows: * The source MAC address is replaced by the TX_PORT MAC address * The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID This application can be used to benchmark performance using a traffic-generator, as shown in the :numref:`figure_l2_fwd_benchmark_setup`. The application can also be used in a virtualized environment as shown in :numref:`figure_l2_fwd_virtenv_benchmark_setup`. The L2 Forwarding application can also be used as a starting point for developing a new application based on the DPDK. .. _figure_l2_fwd_benchmark_setup: .. figure:: img/l2_fwd_benchmark_setup.* Performance Benchmark Setup (Basic Environment) .. _figure_l2_fwd_virtenv_benchmark_setup: .. figure:: img/l2_fwd_virtenv_benchmark_setup.* Performance Benchmark Setup (Virtualized Environment) Virtual Function Setup Instructions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This application can use the virtual function available in the system and therefore can be used in a virtual machine without passing through the whole Network Device into a guest machine in a virtualized scenario. The virtual functions can be enabled in the host machine or the hypervisor with the respective physical function driver. For example, in a Linux* host machine, it is possible to enable a virtual function using the following command: .. code-block:: console modprobe ixgbe max_vfs=2,2 This command enables two Virtual Functions on each of Physical Function of the NIC, with two physical ports in the PCI configuration space. It is important to note that enabled Virtual Function 0 and 2 would belong to Physical Function 0 and Virtual Function 1 and 3 would belong to Physical Function 1, in this case enabling a total of four Virtual Functions. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l2fwd #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc *See the DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application requires a number of command line options: .. code-block:: console ./build/l2fwd [EAL options] -- -p PORTMASK [-q NQ] where, * p PORTMASK: A hexadecimal bitmask of the ports to configure * q NQ: A number of queues (=ports) per lcore (default is 1) To run the application in linuxapp environment with 4 lcores, 16 ports and 8 RX queues per lcore, issue the command: .. code-block:: console $ ./build/l2fwd -c f -n 4 -- -q 8 -p ffff Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. Command Line Arguments ~~~~~~~~~~~~~~~~~~~~~~ The L2 Forwarding sample application takes specific parameters, in addition to Environment Abstraction Layer (EAL) arguments (see Section 9.3). The preferred way to parse parameters is to use the getopt() function, since it is part of a well-defined and portable library. The parsing of arguments is done in the l2fwd_parse_args() function. The method of argument parsing is not described here. Refer to the *glibc getopt(3)* man page for details. EAL arguments are parsed first, then application-specific arguments. This is done at the beginning of the main() function: .. code-block:: c /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); Mbuf Pool Initialization ~~~~~~~~~~~~~~~~~~~~~~~~ Once the arguments are parsed, the mbuf pool is created. The mbuf pool contains a set of mbuf objects that will be used by the driver and the application to store network packet data: .. code-block:: c /* create the mbuf pool */ l2fwd_pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, SOCKET0, 0); if (l2fwd_pktmbuf_pool == NULL) rte_panic("Cannot init mbuf pool\n"); The rte_mempool is a generic structure used to handle pools of objects. In this case, it is necessary to create a pool that will be used by the driver, which expects to have some reserved space in the mempool structure, sizeof(struct rte_pktmbuf_pool_private) bytes. The number of allocated pkt mbufs is NB_MBUF, with a size of MBUF_SIZE each. A per-lcore cache of 32 mbufs is kept. The memory is allocated in NUMA socket 0, but it is possible to extend this code to allocate one mbuf pool per socket. Two callback pointers are also given to the rte_mempool_create() function: * The first callback pointer is to rte_pktmbuf_pool_init() and is used to initialize the private data of the mempool, which is needed by the driver. This function is provided by the mbuf API, but can be copied and extended by the developer. * The second callback pointer given to rte_mempool_create() is the mbuf initializer. The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. If a more complex application wants to extend the rte_pktmbuf structure for its own needs, a new function derived from rte_pktmbuf_init( ) can be created. Driver Initialization ~~~~~~~~~~~~~~~~~~~~~ The main part of the code in the main() function relates to the initialization of the driver. To fully understand this code, it is recommended to study the chapters that related to the Poll Mode Driver in the *DPDK Programmer's Guide* - Rel 1.4 EAR and the *DPDK API Reference*. .. code-block:: c if (rte_eal_pci_probe() < 0) rte_exit(EXIT_FAILURE, "Cannot probe PCI\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* reset l2fwd_dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { l2fwd_dst_ports[portid] = last_port; l2fwd_dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get((uint8_t) portid, &dev_info); } Observe that: * rte_igb_pmd_init_all() simultaneously registers the driver as a PCI driver and as an Ethernet* Poll Mode Driver. * rte_eal_pci_probe() parses the devices on the PCI bus and initializes recognized devices. The next step is to configure the RX and TX queues. For each port, there is only one RX queue (only one lcore is able to poll a given port). The number of TX queues depends on the number of available lcores. The rte_eth_dev_configure() function is used to configure the number of queues for a port: .. code-block:: c ret = rte_eth_dev_configure((uint8_t)portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%u\n", ret, portid); The global configuration is stored in a static structure: .. code-block:: c static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc= 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_DCB_NONE }, }; RX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ The application uses one lcore to poll one or several ports, depending on the -q option, which specifies the number of queues per lcore. For example, if the user specifies -q 4, the application is able to poll four ports with one lcore. If there are 16 ports on the target (and if the portmask argument is -p ffff ), the application will need four lcores to poll all the ports. .. code-block:: c ret = rte_eth_rx_queue_setup((uint8_t) portid, 0, nb_rxd, SOCKET0, &rx_conf, l2fwd_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: " "err=%d, port=%u\n", ret, portid); The list of queues that must be polled for a given lcore is stored in a private structure called struct lcore_queue_conf. .. code-block:: c struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[L2FWD_MAX_PORTS]; } rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; The values n_rx_port and rx_port_list[] are used in the main packet processing loop (see Section 9.4.6 "Receive, Process and Transmit Packets" later in this chapter). The global configuration for the RX queues is stored in a static structure: .. code-block:: c static const struct rte_eth_rxconf rx_conf = { .rx_thresh = { .pthresh = RX_PTHRESH, .hthresh = RX_HTHRESH, .wthresh = RX_WTHRESH, }, }; TX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ Each lcore should be able to transmit on any port. For every port, a single TX queue is initialized. .. code-block:: c /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup((uint8_t) portid, 0, nb_txd, rte_eth_dev_socket_id(portid), &tx_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); The global configuration for TX queues is stored in a static structure: .. code-block:: c static const struct rte_eth_txconf tx_conf = { .tx_thresh = { .pthresh = TX_PTHRESH, .hthresh = TX_HTHRESH, .wthresh = TX_WTHRESH, }, .tx_free_thresh = RTE_TEST_TX_DESC_DEFAULT + 1, /* disable feature */ }; Receive, Process and Transmit Packets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the l2fwd_main_loop() function, the main task is to read ingress packets from the RX queues. This is done using the following code: .. code-block:: c /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0[rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } } Packets are read in a burst of size MAX_PKT_BURST. The rte_eth_rx_burst() function writes the mbuf pointers in a local table and returns the number of available mbufs in the table. Then, each mbuf in the table is processed by the l2fwd_simple_forward() function. The processing is very simple: process the TX port from the RX port, then replace the source and destination MAC addresses. .. note:: In the following code, one line for getting the output port requires some explanation. During the initialization process, a static array of destination ports (l2fwd_dst_ports[]) is filled such that for each source port, a destination port is assigned that is either the next or previous enabled port from the portmask. Naturally, the number of ports in the portmask must be even, otherwise, the application exits. .. code-block:: c static void l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port; dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t) dst_port << 40); /* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); l2fwd_send_packet(m, (uint8_t) dst_port); } Then, the packet is sent using the l2fwd_send_packet (m, dst_port) function. For this test application, the processing is exactly the same for all packets arriving on the same RX port. Therefore, it would have been possible to call the l2fwd_send_burst() function directly from the main loop to send all the received packets on the same TX port, using the burst-oriented send function, which is more efficient. However, in real-life applications (such as, L3 routing), packet N is not necessarily forwarded on the same port as packet N-1. The application is implemented to illustrate that, so the same approach can be reused in a more complex application. The l2fwd_send_packet() function stores the packet in a per-lcore and per-txport table. If the table is full, the whole packets table is transmitted using the l2fwd_send_burst() function: .. code-block:: c /* Send the packet on an output interface */ static int l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf \*qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { l2fwd_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } To ensure that no packets remain in the tables, each lcore does a draining of TX queue in its main loop. This technique introduces some latency when there are not many packets to send, however it improves performance: .. code-block:: c cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; l2fwd_send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } ================================================ FILE: doc/guides/sample_app_ug/l3_forward.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L3 Forwarding Sample Application ================================ The L3 Forwarding application is a simple example of packet processing using the DPDK. The application performs L3 forwarding. Overview -------- The application demonstrates the use of the hash and LPM libraries in the DPDK to implement packet forwarding. The initialization and run-time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Sample Application (in Real and Virtualized Environments)" for more information). The main difference from the L2 Forwarding sample application is that the forwarding decision is made based on information read from the input packet. The lookup method is either hash-based or LPM-based and is selected at compile time. When the selected lookup method is hash-based, a hash object is used to emulate the flow classification stage. The hash object is used in correlation with a flow table to map each input packet to its flow at runtime. The hash lookup key is represented by a DiffServ 5-tuple composed of the following fields read from the input packet: Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port. The ID of the output interface for the input packet is read from the identified flow table entry. The set of flows used by the application is statically configured and loaded into the hash at initialization time. When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets. The LPM object is used as the routing table to identify the next hop for each input packet at runtime. The LPM lookup key is represented by the Destination IP Address field read from the input packet. The ID of the output interface for the input packet is the next hop returned by the LPM lookup. The set of LPM rules used by the application is statically configured and loaded into the LPM object at initialization time. In the sample application, hash-based forwarding supports IPv4 and IPv6. LPM-based forwarding supports IPv4 only. Compiling the Application ------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l3fwd #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/l3fwd [EAL options] -- -p PORTMASK [-P] --config(port,queue,lcore)[,(port,queue,lcore)] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa][--hash-entry-num][--ipv6] where, * -p PORTMASK: Hexadecimal bitmask of ports to configure * -P: optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. * --config (port,queue,lcore)[,(port,queue,lcore)]: determines which queues from which ports are mapped to which cores * --enable-jumbo: optional, enables jumbo frames * --max-pkt-len: optional, maximum packet length in decimal (64-9600) * --no-numa: optional, disables numa awareness * --hash-entry-num: optional, specifies the hash entry number in hexadecimal to be setup * --ipv6: optional, set it if running ipv6 packets For example, consider a dual processor socket platform where cores 0-7 and 16-23 appear on socket 0, while cores 8-15 and 24-31 appear on socket 1. Let's say that the programmer wants to use memory from both NUMA nodes, the platform has only two ports, one connected to each NUMA node, and the programmer wants to use two cores from each processor socket to do the packet processing. To enable L3 forwarding between two ports, using two cores, cores 1 and 2, from each processor, while also taking advantage of local memory access by optimizing around NUMA, the programmer must enable two queues from each port, pin to the appropriate cores and allocate memory from the appropriate NUMA node. This is achieved using the following command: .. code-block:: console ./build/l3fwd -c 606 -n 4 -- -p 0x3 --config="(0,0,1),(0,1,2),(1,0,9),(1,1,10)" In this command: * The -c option enables cores 0, 1, 2, 3 * The -p option enables ports 0 and 1 * The --config option enables two queues on each port and maps each (port,queue) pair to a specific core. Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes is included in the application and is done transparently. The following table shows the mapping in this example: +----------+-----------+-----------+-------------------------------------+ | **Port** | **Queue** | **lcore** | **Description** | | | | | | +----------+-----------+-----------+-------------------------------------+ | 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0. | | | | | | +----------+-----------+-----------+-------------------------------------+ | 0 | 1 | 2 | Map queue 1 from port 0 to lcore 2. | | | | | | +----------+-----------+-----------+-------------------------------------+ | 1 | 0 | 1 | Map queue 0 from port 1 to lcore 1. | | | | | | +----------+-----------+-----------+-------------------------------------+ | 1 | 1 | 3 | Map queue 1 from port 1 to lcore 3. | | | | | | +----------+-----------+-----------+-------------------------------------+ Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the sample application code. As mentioned in the overview section, the initialization and run-time paths are very similar to those of the L2 forwarding application (see Chapter 9 "L2 Forwarding Sample Application (in Real and Virtualized Environments)" for more information). The following sections describe aspects that are specific to the L3 Forwarding sample application. Hash Initialization ~~~~~~~~~~~~~~~~~~~ The hash object is created and loaded with the pre-configured entries read from a global array, and then generate the expected 5-tuple as key to keep consistence with those of real flow for the convenience to execute hash performance test on 4M/8M/16M flows. .. note:: The Hash initialization will setup both ipv4 and ipv6 hash table, and populate the either table depending on the value of variable ipv6. To support the hash performance test with up to 8M single direction flows/16M bi-direction flows, populate_ipv4_many_flow_into_table() function will populate the hash table with specified hash table entry number(default 4M). .. note:: Value of global variable ipv6 can be specified with --ipv6 in the command line. Value of global variable hash_entry_number, which is used to specify the total hash entry number for all used ports in hash performance test, can be specified with --hash-entry-num VALUE in command line, being its default value 4. .. code-block:: c #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void setup_hash(int socketid) { // ... if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { if (ipv6 == 0) { /* populate the ipv4 hash */ populate_ipv4_many_flow_into_table(ipv4_l3fwd_lookup_struct[socketid], hash_entry_number); } else { /* populate the ipv6 hash */ populate_ipv6_many_flow_into_table( ipv6_l3fwd_lookup_struct[socketid], hash_entry_number); } } else if (ipv6 == 0) { /* populate the ipv4 hash */ populate_ipv4_few_flow_into_table(ipv4_l3fwd_lookup_struct[socketid]); } else { /* populate the ipv6 hash */ populate_ipv6_few_flow_into_table(ipv6_l3fwd_lookup_struct[socketid]); } } } #endif LPM Initialization ~~~~~~~~~~~~~~~~~~ The LPM object is created and loaded with the pre-configured entries read from a global array. .. code-block:: c #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static void setup_lpm(int socketid) { unsigned i; int ret; char s[64]; /* create the LPM table */ rte_snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid); ipv4_l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid, IPV4_L3FWD_LPM_MAX_RULES, 0); if (ipv4_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" " on socket %d\n", socketid); /* populate the LPM table */ for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { /* skip unused ports */ if ((1 << ipv4_l3fwd_route_array[i].if_out & enabled_port_mask) == 0) continue; ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid], ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " "l3fwd LPM table on socket %d\n", i, socketid); } printf("LPM: Adding route 0x%08x / %d (%d)\n", (unsigned)ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); } } #endif Packet Forwarding for Hash-based Lookups ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each input packet, the packet forwarding operation is done by the l3fwd_simple_forward() or simple_ipv4_fwd_4pkts() function for IPv4 packets or the simple_ipv6_fwd_4pkts() function for IPv6 packets. The l3fwd_simple_forward() function provides the basic functionality for both IPv4 and IPv6 packet forwarding for any number of burst packets received, and the packet forwarding decision (that is, the identification of the output interface for the packet) for hash-based lookups is done by the get_ipv4_dst_port() or get_ipv6_dst_port() function. The get_ipv4_dst_port() function is shown below: .. code-block:: c static inline uint8_t get_ipv4_dst_port(void *ipv4_hdr, uint8_t portid, lookup_struct_t *ipv4_l3fwd_lookup_struct) { int ret = 0; union ipv4_5tuple_host key; ipv4_hdr = (uint8_t \*)ipv4_hdr + offsetof(struct ipv4_hdr, time_to_live); m128i data = _mm_loadu_si128(( m128i*)(ipv4_hdr)); /* Get 5 tuple: dst port, src port, dst IP address, src IP address and protocol */ key.xmm = _mm_and_si128(data, mask0); /* Find destination port */ ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : ipv4_l3fwd_out_if[ret]); } The get_ipv6_dst_port() function is similar to the get_ipv4_dst_port() function. The simple_ipv4_fwd_4pkts() and simple_ipv6_fwd_4pkts() function are optimized for continuous 4 valid ipv4 and ipv6 packets, they leverage the multiple buffer optimization to boost the performance of forwarding packets with the exact match on hash table. The key code snippet of simple_ipv4_fwd_4pkts() is shown below: .. code-block:: c static inline void simple_ipv4_fwd_4pkts(struct rte_mbuf* m[4], uint8_t portid, struct lcore_conf *qconf) { // ... data[0] = _mm_loadu_si128(( m128i*)(rte_pktmbuf_mtod(m[0], unsigned char *) + sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[1] = _mm_loadu_si128(( m128i*)(rte_pktmbuf_mtod(m[1], unsigned char *) + sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[2] = _mm_loadu_si128(( m128i*)(rte_pktmbuf_mtod(m[2], unsigned char *) + sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[3] = _mm_loadu_si128(( m128i*)(rte_pktmbuf_mtod(m[3], unsigned char *) + sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); key[0].xmm = _mm_and_si128(data[0], mask0); key[1].xmm = _mm_and_si128(data[1], mask0); key[2].xmm = _mm_and_si128(data[2], mask0); key[3].xmm = _mm_and_si128(data[3], mask0); const void *key_array[4] = {&key[0], &key[1], &key[2],&key[3]}; rte_hash_lookup_multi(qconf->ipv4_lookup_struct, &key_array[0], 4, ret); dst_port[0] = (ret[0] < 0)? portid:ipv4_l3fwd_out_if[ret[0]]; dst_port[1] = (ret[1] < 0)? portid:ipv4_l3fwd_out_if[ret[1]]; dst_port[2] = (ret[2] < 0)? portid:ipv4_l3fwd_out_if[ret[2]]; dst_port[3] = (ret[3] < 0)? portid:ipv4_l3fwd_out_if[ret[3]]; // ... } The simple_ipv6_fwd_4pkts() function is similar to the simple_ipv4_fwd_4pkts() function. Packet Forwarding for LPM-based Lookups ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For each input packet, the packet forwarding operation is done by the l3fwd_simple_forward() function, but the packet forwarding decision (that is, the identification of the output interface for the packet) for LPM-based lookups is done by the get_ipv4_dst_port() function below: .. code-block:: c static inline uint8_t get_ipv4_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid, lookup_struct_t *ipv4_l3fwd_lookup_struct) { uint8_t next_hop; return (uint8_t) ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid); } ================================================ FILE: doc/guides/sample_app_ug/l3_forward_access_ctrl.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L3 Forwarding with Access Control Sample Application ==================================================== The L3 Forwarding with Access Control application is a simple example of packet processing using the DPDK. The application performs a security check on received packets. Packets that are in the Access Control List (ACL), which is loaded during initialization, are dropped. Others are forwarded to the correct port. Overview -------- The application demonstrates the use of the ACL library in the DPDK to implement access control and packet L3 forwarding. The application loads two types of rules at initialization: * Route information rules, which are used for L3 forwarding * Access Control List (ACL) rules that blacklist (or block) packets with a specific characteristic When packets are received from a port, the application extracts the necessary information from the TCP/IP header of the received packet and performs a lookup in the rule database to figure out whether the packets should be dropped (in the ACL range) or forwarded to desired ports. The initialization and run-time paths are similar to those of the L3 forwarding application (see Chapter 10, "L3 Forwarding Sample Application" for more information). However, there are significant differences in the two applications. For example, the original L3 forwarding application uses either LPM or an exact match algorithm to perform forwarding port lookup, while this application uses the ACL library to perform both ACL and route entry lookup. The following sections provide more detail. Classification for both IPv4 and IPv6 packets is supported in this application. The application also assumes that all the packets it processes are TCP/UDP packets and always extracts source/destination port information from the packets. Tuple Packet Syntax ~~~~~~~~~~~~~~~~~~~ The application implements packet classification for the IPv4/IPv6 5-tuple syntax specifically. The 5-tuple syntax consist of a source IP address, a destination IP address, a source port, a destination port and a protocol identifier. The fields in the 5-tuple syntax have the following formats: * **Source IP address and destination IP address** : Each is either a 32-bit field (for IPv4), or a set of 4 32-bit fields (for IPv6) represented by a value and a mask length. For example, an IPv4 range of 192.168.1.0 to 192.168.1.255 could be represented by a value = [192, 168, 1, 0] and a mask length = 24. * **Source port and destination port** : Each is a 16-bit field, represented by a lower start and a higher end. For example, a range of ports 0 to 8192 could be represented by lower = 0 and higher = 8192. * **Protocol identifier** : An 8-bit field, represented by a value and a mask, that covers a range of values. To verify that a value is in the range, use the following expression: "(VAL & mask) == value" The trick in how to represent a range with a mask and value is as follows. A range can be enumerated in binary numbers with some bits that are never changed and some bits that are dynamically changed. Set those bits that dynamically changed in mask and value with 0. Set those bits that never changed in the mask with 1, in value with number expected. For example, a range of 6 to 7 is enumerated as 0b110 and 0b111. Bit 1-7 are bits never changed and bit 0 is the bit dynamically changed. Therefore, set bit 0 in mask and value with 0, set bits 1-7 in mask with 1, and bits 1-7 in value with number 0b11. So, mask is 0xfe, value is 0x6. .. note:: The library assumes that each field in the rule is in LSB or Little Endian order when creating the database. It internally converts them to MSB or Big Endian order. When performing a lookup, the library assumes the input is in MSB or Big Endian order. Access Rule Syntax ~~~~~~~~~~~~~~~~~~ In this sample application, each rule is a combination of the following: * 5-tuple field: This field has a format described in Section. * priority field: A weight to measure the priority of the rules. The rule with the higher priority will ALWAYS be returned if the specific input has multiple matches in the rule database. Rules with lower priority will NEVER be returned in any cases. * userdata field: A user-defined field that could be any value. It can be the forwarding port number if the rule is a route table entry or it can be a pointer to a mapping address if the rule is used for address mapping in the NAT application. The key point is that it is a useful reserved field for user convenience. ACL and Route Rules ~~~~~~~~~~~~~~~~~~~ The application needs to acquire ACL and route rules before it runs. Route rules are mandatory, while ACL rules are optional. To simplify the complexity of the priority field for each rule, all ACL and route entries are assumed to be in the same file. To read data from the specified file successfully, the application assumes the following: * Each rule occupies a single line. * Only the following four rule line types are valid in this application: * ACL rule line, which starts with a leading character '@' * Route rule line, which starts with a leading character 'R' * Comment line, which starts with a leading character '#' * Empty line, which consists of a space, form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), or vertical tab ('\v'). Other lines types are considered invalid. * Rules are organized in descending order of priority, which means rules at the head of the file always have a higher priority than those further down in the file. * A typical IPv4 ACL rule line should have a format as shown below: .. _figure_ipv4_acl_rule: .. figure:: img/ipv4_acl_rule.* A typical IPv4 ACL rule IPv4 addresses are specified in CIDR format as specified in RFC 4632. They consist of the dot notation for the address and a prefix length separated by '/'. For example, 192.168.0.34/32, where the address is 192.168.0.34 and the prefix length is 32. Ports are specified as a range of 16-bit numbers in the format MIN:MAX, where MIN and MAX are the inclusive minimum and maximum values of the range. The range 0:65535 represents all possible ports in a range. When MIN and MAX are the same value, a single port is represented, for example, 20:20. The protocol identifier is an 8-bit value and a mask separated by '/'. For example: 6/0xfe matches protocol values 6 and 7. * Route rules start with a leading character 'R' and have the same format as ACL rules except an extra field at the tail that indicates the forwarding port number. Rules File Example ~~~~~~~~~~~~~~~~~~ .. _figure_example_rules: .. figure:: img/example_rules.* Rules example Each rule is explained as follows: * Rule 1 (the first line) tells the application to drop those packets with source IP address = [1.2.3.*], destination IP address = [192.168.0.36], protocol = [6]/[7] * Rule 2 (the second line) is similar to Rule 1, except the source IP address is ignored. It tells the application to forward packets with destination IP address = [192.168.0.36], protocol = [6]/[7], destined to port 1. * Rule 3 (the third line) tells the application to forward all packets to port 0. This is something like a default route entry. As described earlier, the application assume rules are listed in descending order of priority, therefore Rule 1 has the highest priority, then Rule 2, and finally, Rule 3 has the lowest priority. Consider the arrival of the following three packets: * Packet 1 has source IP address = [1.2.3.4], destination IP address = [192.168.0.36], and protocol = [6] * Packet 2 has source IP address = [1.2.4.4], destination IP address = [192.168.0.36], and protocol = [6] * Packet 3 has source IP address = [1.2.3.4], destination IP address = [192.168.0.36], and protocol = [8] Observe that: * Packet 1 matches all of the rules * Packet 2 matches Rule 2 and Rule 3 * Packet 3 only matches Rule 3 For priority reasons, Packet 1 matches Rule 1 and is dropped. Packet 2 matches Rule 2 and is forwarded to port 1. Packet 3 matches Rule 3 and is forwarded to port 0. For more details on the rule file format, please refer to rule_ipv4.db and rule_ipv6.db files (inside /examples/l3fwd-acl/). Application Phases ~~~~~~~~~~~~~~~~~~ Once the application starts, it transitions through three phases: * **Initialization Phase** - Perform the following tasks: * Parse command parameters. Check the validity of rule file(s) name(s), number of logical cores, receive and transmit queues. Bind ports, queues and logical cores. Check ACL search options, and so on. * Call Environmental Abstraction Layer (EAL) and Poll Mode Driver (PMD) functions to initialize the environment and detect possible NICs. The EAL creates several threads and sets affinity to a specific hardware thread CPU based on the configuration specified by the command line arguments. * Read the rule files and format the rules into the representation that the ACL library can recognize. Call the ACL library function to add the rules into the database and compile them as a trie of pattern sets. Note that application maintains a separate AC contexts for IPv4 and IPv6 rules. * **Runtime Phase** - Process the incoming packets from a port. Packets are processed in three steps: * Retrieval: Gets a packet from the receive queue. Each logical core may process several queues for different ports. This depends on the configuration specified by command line arguments. * Lookup: Checks that the packet type is supported (IPv4/IPv6) and performs a 5-tuple lookup over corresponding AC context. If an ACL rule is matched, the packets will be dropped and return back to step 1. If a route rule is matched, it indicates the packet is not in the ACL list and should be forwarded. If there is no matches for the packet, then the packet is dropped. * Forwarding: Forwards the packet to the corresponding port. * **Final Phase** - Perform the following tasks: Calls the EAL, PMD driver and ACL library to free resource, then quits. Compiling the Application ------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l3fwd-acl #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK IPL Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/l3fwd-acl [EAL options] -- -p PORTMASK [-P] --config(port,queue,lcore)[,(port,queue,lcore)] --rule_ipv4 FILENAME rule_ipv6 FILENAME [--scalar] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa] where, * -p PORTMASK: Hexadecimal bitmask of ports to configure * -P: Sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. * --config (port,queue,lcore)[,(port,queue,lcore)]: determines which queues from which ports are mapped to which cores * --rule_ipv4 FILENAME: Specifies the IPv4 ACL and route rules file * --rule_ipv6 FILENAME: Specifies the IPv6 ACL and route rules file * --scalar: Use a scalar function to perform rule lookup * --enable-jumbo: optional, enables jumbo frames * --max-pkt-len: optional, maximum packet length in decimal (64-9600) * --no-numa: optional, disables numa awareness As an example, consider a dual processor socket platform where cores 0, 2, 4, 6, 8 and 10 appear on socket 0, while cores 1, 3, 5, 7, 9 and 11 appear on socket 1. Let's say that the user wants to use memory from both NUMA nodes, the platform has only two ports and the user wants to use two cores from each processor socket to do the packet processing. To enable L3 forwarding between two ports, using two cores from each processor, while also taking advantage of local memory access by optimizing around NUMA, the user must enable two queues from each port, pin to the appropriate cores and allocate memory from the appropriate NUMA node. This is achieved using the following command: .. code-block:: console ./build/l3fwd-acl -c f -n 4 -- -p 0x3 --config="(0,0,0),(0,1,2),(1,0,1),(1,1,3)" --rule_ipv4="./rule_ipv4.db" -- rule_ipv6="./rule_ipv6.db" --scalar In this command: * The -c option enables cores 0, 1, 2, 3 * The -p option enables ports 0 and 1 * The --config option enables two queues on each port and maps each (port,queue) pair to a specific core. Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes is included in the application and is done transparently. The following table shows the mapping in this example: +----------+------------+-----------+------------------------------------------------+ | **Port** | **Queue** | **lcore** | **Description** | | | | | | +==========+============+===========+================================================+ | 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0. | | | | | | +----------+------------+-----------+------------------------------------------------+ | 0 | 1 | 2 | Map queue 1 from port 0 to lcore 2. | | | | | | +----------+------------+-----------+------------------------------------------------+ | 1 | 0 | 1 | Map queue 0 from port 1 to lcore 1. | | | | | | +----------+------------+-----------+------------------------------------------------+ | 1 | 1 | 3 | Map queue 1 from port 1 to lcore 3. | | | | | | +----------+------------+-----------+------------------------------------------------+ * The --rule_ipv4 option specifies the reading of IPv4 rules sets from the ./ rule_ipv4.db file. * The --rule_ipv6 option specifies the reading of IPv6 rules sets from the ./ rule_ipv6.db file. * The --scalar option specifies the performing of rule lookup with a scalar function. Explanation ----------- The following sections provide some explanation of the sample application code. The aspects of port, device and CPU configuration are similar to those of the L3 forwarding application (see Chapter 10, "L3 Forwarding Sample Application" for more information). The following sections describe aspects that are specific to L3 forwarding with access control. Parse Rules from File ~~~~~~~~~~~~~~~~~~~~~ As described earlier, both ACL and route rules are assumed to be saved in the same file. The application parses the rules from the file and adds them to the database by calling the ACL library function. It ignores empty and comment lines, and parses and validates the rules it reads. If errors are detected, the application exits with messages to identify the errors encountered. The application needs to consider the userdata and priority fields. The ACL rules save the index to the specific rules in the userdata field, while route rules save the forwarding port number. In order to differentiate the two types of rules, ACL rules add a signature in the userdata field. As for the priority field, the application assumes rules are organized in descending order of priority. Therefore, the code only decreases the priority number with each rule it parses. Setting Up the ACL Context ~~~~~~~~~~~~~~~~~~~~~~~~~~ For each supported AC rule format (IPv4 5-tuple, IPv6 6-tuple) application creates a separate context handler from the ACL library for each CPU socket on the board and adds parsed rules into that context. Note, that for each supported rule type, application needs to calculate the expected offset of the fields from the start of the packet. That's why only packets with fixed IPv4/ IPv6 header are supported. That allows to perform ACL classify straight over incoming packet buffer - no extra protocol field retrieval need to be performed. Subsequently, the application checks whether NUMA is enabled. If it is, the application records the socket IDs of the CPU cores involved in the task. Finally, the application creates contexts handler from the ACL library, adds rules parsed from the file into the database and build an ACL trie. It is important to note that the application creates an independent copy of each database for each socket CPU involved in the task to reduce the time for remote memory access. ================================================ FILE: doc/guides/sample_app_ug/l3_forward_power_man.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L3 Forwarding with Power Management Sample Application ====================================================== Introduction ------------ The L3 Forwarding with Power Management application is an example of power-aware packet processing using the DPDK. The application is based on existing L3 Forwarding sample application, with the power management algorithms to control the P-states and C-states of the Intel processor via a power management library. Overview -------- The application demonstrates the use of the Power libraries in the DPDK to implement packet forwarding. The initialization and run-time paths are very similar to those of the L3 forwarding sample application (see Chapter 10 "L3 Forwarding Sample Application" for more information). The main difference from the L3 Forwarding sample application is that this application introduces power-aware optimization algorithms by leveraging the Power library to control P-state and C-state of processor based on packet load. The DPDK includes poll-mode drivers to configure Intel NIC devices and their receive (Rx) and transmit (Tx) queues. The design principle of this PMD is to access the Rx and Tx descriptors directly without any interrupts to quickly receive, process and deliver packets in the user space. In general, the DPDK executes an endless packet processing loop on dedicated IA cores that include the following steps: * Retrieve input packets through the PMD to poll Rx queue * Process each received packet or provide received packets to other processing cores through software queues * Send pending output packets to Tx queue through the PMD In this way, the PMD achieves better performance than a traditional interrupt-mode driver, at the cost of keeping cores active and running at the highest frequency, hence consuming the maximum power all the time. However, during the period of processing light network traffic, which happens regularly in communication infrastructure systems due to well-known "tidal effect", the PMD is still busy waiting for network packets, which wastes a lot of power. Processor performance states (P-states) are the capability of an Intel processor to switch between different supported operating frequencies and voltages. If configured correctly, according to system workload, this feature provides power savings. CPUFreq is the infrastructure provided by the Linux* kernel to control the processor performance state capability. CPUFreq supports a user space governor that enables setting frequency via manipulating the virtual file device from a user space application. The Power library in the DPDK provides a set of APIs for manipulating a virtual file device to allow user space application to set the CPUFreq governor and set the frequency of specific cores. This application includes a P-state power management algorithm to generate a frequency hint to be sent to CPUFreq. The algorithm uses the number of received and available Rx packets on recent polls to make a heuristic decision to scale frequency up/down. Specifically, some thresholds are checked to see whether a specific core running an DPDK polling thread needs to increase frequency a step up based on the near to full trend of polled Rx queues. Also, it decreases frequency a step if packet processed per loop is far less than the expected threshold or the thread's sleeping time exceeds a threshold. C-States are also known as sleep states. They allow software to put an Intel core into a low power idle state from which it is possible to exit via an event, such as an interrupt. However, there is a tradeoff between the power consumed in the idle state and the time required to wake up from the idle state (exit latency). Therefore, as you go into deeper C-states, the power consumed is lower but the exit latency is increased. Each C-state has a target residency. It is essential that when entering into a C-state, the core remains in this C-state for at least as long as the target residency in order to fully realize the benefits of entering the C-state. CPUIdle is the infrastructure provide by the Linux kernel to control the processor C-state capability. Unlike CPUFreq, CPUIdle does not provide a mechanism that allows the application to change C-state. It actually has its own heuristic algorithms in kernel space to select target C-state to enter by executing privileged instructions like HLT and MWAIT, based on the speculative sleep duration of the core. In this application, we introduce a heuristic algorithm that allows packet processing cores to sleep for a short period if there is no Rx packet received on recent polls. In this way, CPUIdle automatically forces the corresponding cores to enter deeper C-states instead of always running to the C0 state waiting for packets. .. note:: To fully demonstrate the power saving capability of using C-states, it is recommended to enable deeper C3 and C6 states in the BIOS during system boot up. Compiling the Application ------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l3fwd-power #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/l3fwd_power [EAL options] -- -p PORTMASK [-P] --config(port,queue,lcore)[,(port,queue,lcore)] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa] where, * -p PORTMASK: Hexadecimal bitmask of ports to configure * -P: Sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address. Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. * --config (port,queue,lcore)[,(port,queue,lcore)]: determines which queues from which ports are mapped to which cores. * --enable-jumbo: optional, enables jumbo frames * --max-pkt-len: optional, maximum packet length in decimal (64-9600) * --no-numa: optional, disables numa awareness See Chapter 10 "L3 Forwarding Sample Application" for details. The L3fwd-power example reuses the L3fwd command line options. Explanation ----------- The following sections provide some explanation of the sample application code. As mentioned in the overview section, the initialization and run-time paths are identical to those of the L3 forwarding application. The following sections describe aspects that are specific to the L3 Forwarding with Power Management sample application. Power Library Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Power library is initialized in the main routine. It changes the P-state governor to userspace for specific cores that are under control. The Timer library is also initialized and several timers are created later on, responsible for checking if it needs to scale down frequency at run time by checking CPU utilization statistics. .. note:: Only the power management related initialization is shown. .. code-block:: c int main(int argc, char **argv) { struct lcore_conf *qconf; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcore_id; uint64_t hz; uint32_t n_tx_queue, nb_lcores; uint8_t portid, nb_rx_queue, queue, socketid; // ... /* init RTE timer library to be used to initialize per-core timers */ rte_timer_subsystem_init(); // ... /* per-core initialization */ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; /* init power management library for a specified core */ ret = rte_power_init(lcore_id); if (ret) rte_exit(EXIT_FAILURE, "Power management library " "initialization failed on core%d\n", lcore_id); /* init timer structures for each enabled lcore */ rte_timer_init(&power_timers[lcore_id]); hz = rte_get_hpet_hz(); rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, SINGLE, lcore_id, power_timer_cb, NULL); // ... } // ... } Monitoring Loads of Rx Queues ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In general, the polling nature of the DPDK prevents the OS power management subsystem from knowing if the network load is actually heavy or light. In this sample, sampling network load work is done by monitoring received and available descriptors on NIC Rx queues in recent polls. Based on the number of returned and available Rx descriptors, this example implements algorithms to generate frequency scaling hints and speculative sleep duration, and use them to control P-state and C-state of processors via the power management library. Frequency (P-state) control and sleep state (C-state) control work individually for each logical core, and the combination of them contributes to a power efficient packet processing solution when serving light network loads. The rte_eth_rx_burst() function and the newly-added rte_eth_rx_queue_count() function are used in the endless packet processing loop to return the number of received and available Rx descriptors. And those numbers of specific queue are passed to P-state and C-state heuristic algorithms to generate hints based on recent network load trends. .. note:: Only power control related code is shown. .. code-block:: c static attribute ((noreturn)) int main_loop( attribute ((unused)) void *dummy) { // ... while (1) { // ... /** * Read packet from RX queues */ lcore_scaleup_hint = FREQ_CURRENT; lcore_rx_idle_count = 0; for (i = 0; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); rx_queue->idle_hint = 0; portid = rx_queue->port_id; queueid = rx_queue->queue_id; nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); stats[lcore_id].nb_rx_processed += nb_rx; if (unlikely(nb_rx == 0)) { /** * no packet received from rx queue, try to * sleep for a while forcing CPU enter deeper * C states. */ rx_queue->zero_rx_packet_count++; if (rx_queue->zero_rx_packet_count <= MIN_ZERO_POLL_COUNT) continue; rx_queue->idle_hint = power_idle_heuristic(rx_queue->zero_rx_packet_count); lcore_rx_idle_count++; } else { rx_ring_length = rte_eth_rx_queue_count(portid, queueid); rx_queue->zero_rx_packet_count = 0; /** * do not scale up frequency immediately as * user to kernel space communication is costly * which might impact packet I/O for received * packets. */ rx_queue->freq_up_hint = power_freq_scaleup_heuristic(lcore_id, rx_ring_length); } /* Prefetch and forward packets */ // ... } if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) { for (i = 1, lcore_scaleup_hint = qconf->rx_queue_list[0].freq_up_hint; i < qconf->n_rx_queue; ++i) { x_queue = &(qconf->rx_queue_list[i]); if (rx_queue->freq_up_hint > lcore_scaleup_hint) lcore_scaleup_hint = rx_queue->freq_up_hint; } if (lcore_scaleup_hint == FREQ_HIGHEST) rte_power_freq_max(lcore_id); else if (lcore_scaleup_hint == FREQ_HIGHER) rte_power_freq_up(lcore_id); } else { /** * All Rx queues empty in recent consecutive polls, * sleep in a conservative manner, meaning sleep as * less as possible. */ for (i = 1, lcore_idle_hint = qconf->rx_queue_list[0].idle_hint; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); if (rx_queue->idle_hint < lcore_idle_hint) lcore_idle_hint = rx_queue->idle_hint; } if ( lcore_idle_hint < SLEEP_GEAR1_THRESHOLD) /** * execute "pause" instruction to avoid context * switch for short sleep. */ rte_delay_us(lcore_idle_hint); else /* long sleep force ruining thread to suspend */ usleep(lcore_idle_hint); stats[lcore_id].sleep_time += lcore_idle_hint; } } } P-State Heuristic Algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The power_freq_scaleup_heuristic() function is responsible for generating a frequency hint for the specified logical core according to available descriptor number returned from rte_eth_rx_queue_count(). On every poll for new packets, the length of available descriptor on an Rx queue is evaluated, and the algorithm used for frequency hinting is as follows: * If the size of available descriptors exceeds 96, the maximum frequency is hinted. * If the size of available descriptors exceeds 64, a trend counter is incremented by 100. * If the length of the ring exceeds 32, the trend counter is incremented by 1. * When the trend counter reached 10000 the frequency hint is changed to the next higher frequency. .. note:: The assumption is that the Rx queue size is 128 and the thresholds specified above must be adjusted accordingly based on actual hardware Rx queue size, which are configured via the rte_eth_rx_queue_setup() function. In general, a thread needs to poll packets from multiple Rx queues. Most likely, different queue have different load, so they would return different frequency hints. The algorithm evaluates all the hints and then scales up frequency in an aggressive manner by scaling up to highest frequency as long as one Rx queue requires. In this way, we can minimize any negative performance impact. On the other hand, frequency scaling down is controlled in the timer callback function. Specifically, if the sleep times of a logical core indicate that it is sleeping more than 25% of the sampling period, or if the average packet per iteration is less than expectation, the frequency is decreased by one step. C-State Heuristic Algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Whenever recent rte_eth_rx_burst() polls return 5 consecutive zero packets, an idle counter begins incrementing for each successive zero poll. At the same time, the function power_idle_heuristic() is called to generate speculative sleep duration in order to force logical to enter deeper sleeping C-state. There is no way to control C- state directly, and the CPUIdle subsystem in OS is intelligent enough to select C-state to enter based on actual sleep period time of giving logical core. The algorithm has the following sleeping behavior depending on the idle counter: * If idle count less than 100, the counter value is used as a microsecond sleep value through rte_delay_us() which execute pause instructions to avoid costly context switch but saving power at the same time. * If idle count is between 100 and 999, a fixed sleep interval of 100 μs is used. A 100 μs sleep interval allows the core to enter the C1 state while keeping a fast response time in case new traffic arrives. * If idle count is greater than 1000, a fixed sleep value of 1 ms is used until the next timer expiration is used. This allows the core to enter the C3/C6 states. .. note:: The thresholds specified above need to be adjusted for different Intel processors and traffic profiles. If a thread polls multiple Rx queues and different queue returns different sleep duration values, the algorithm controls the sleep time in a conservative manner by sleeping for the least possible time in order to avoid a potential performance impact. ================================================ FILE: doc/guides/sample_app_ug/l3_forward_virtual.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. L3 Forwarding in a Virtualization Environment Sample Application ================================================================ The L3 Forwarding in a Virtualization Environment sample application is a simple example of packet processing using the DPDK. The application performs L3 forwarding that takes advantage of Single Root I/O Virtualization (SR-IOV) features in a virtualized environment. Overview -------- The application demonstrates the use of the hash and LPM libraries in the DPDK to implement packet forwarding. The initialization and run-time paths are very similar to those of the L3 forwarding application (see Chapter 10 "L3 Forwarding Sample Application" for more information). The forwarding decision is taken based on information read from the input packet. The lookup method is either hash-based or LPM-based and is selected at compile time. When the selected lookup method is hash-based, a hash object is used to emulate the flow classification stage. The hash object is used in correlation with the flow table to map each input packet to its flow at runtime. The hash lookup key is represented by the DiffServ 5-tuple composed of the following fields read from the input packet: Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port. The ID of the output interface for the input packet is read from the identified flow table entry. The set of flows used by the application is statically configured and loaded into the hash at initialization time. When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets. The LPM object is used as the routing table to identify the next hop for each input packet at runtime. The LPM lookup key is represented by the Destination IP Address field read from the input packet. The ID of the output interface for the input packet is the next hop returned by the LPM lookup. The set of LPM rules used by the application is statically configured and loaded into the LPM object at the initialization time. .. note:: Please refer to Section 9.1.1 "Virtual Function Setup Instructions" for virtualized test case setup. Compiling the Application ------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/l3fwd-vf #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make .. note:: The compiled application is written to the build subdirectory. To have the application written to a different location, the O=/path/to/build/directory option may be specified in the make command. Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./build/l3fwd-vf [EAL options] -- -p PORTMASK --config(port,queue,lcore)[,(port,queue,lcore)] [--no-numa] where, * --p PORTMASK: Hexadecimal bitmask of ports to configure * --config (port,queue,lcore)[,(port,queue,lcore]: determines which queues from which ports are mapped to which cores * --no-numa: optional, disables numa awareness For example, consider a dual processor socket platform where cores 0,2,4,6, 8, and 10 appear on socket 0, while cores 1,3,5,7,9, and 11 appear on socket 1. Let's say that the programmer wants to use memory from both NUMA nodes, the platform has only two ports and the programmer wants to use one core from each processor socket to do the packet processing since only one Rx/Tx queue pair can be used in virtualization mode. To enable L3 forwarding between two ports, using one core from each processor, while also taking advantage of local memory accesses by optimizing around NUMA, the programmer can pin to the appropriate cores and allocate memory from the appropriate NUMA node. This is achieved using the following command: .. code-block:: console ./build/l3fwd-vf -c 0x03 -n 3 -- -p 0x3 --config="(0,0,0),(1,0,1)" In this command: * The -c option enables cores 0 and 1 * The -p option enables ports 0 and 1 * The --config option enables one queue on each port and maps each (port,queue) pair to a specific core. Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes is included in the application and is done transparently. The following table shows the mapping in this example: +----------+-----------+-----------+------------------------------------+ | **Port** | **Queue** | **lcore** | **Description** | | | | | | +==========+===========+===========+====================================+ | 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0 | | | | | | +----------+-----------+-----------+------------------------------------+ | 1 | 1 | 1 | Map queue 0 from port 1 to lcore 1 | | | | | | +----------+-----------+-----------+------------------------------------+ Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The operation of this application is similar to that of the basic L3 Forwarding Sample Application. See Section 10.4 "Explanation" for more information. ================================================ FILE: doc/guides/sample_app_ug/link_status_intr.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Link Status Interrupt Sample Application ======================================== The Link Status Interrupt sample application is a simple example of packet processing using the Data Plane Development Kit (DPDK) that demonstrates how network link status changes for a network port can be captured and used by a DPDK application. Overview -------- The Link Status Interrupt sample application registers a user space callback for the link status interrupt of each port and performs L2 forwarding for each packet that is received on an RX_PORT. The following operations are performed: * RX_PORT and TX_PORT are paired with available ports one-by-one according to the core mask * The source MAC address is replaced by the TX_PORT MAC address * The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID This application can be used to demonstrate the usage of link status interrupt and its user space callbacks and the behavior of L2 forwarding each time the link status changes. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/link_status_interrupt #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make .. note:: The compiled application is written to the build subdirectory. To have the application written to a different location, the O=/path/to/build/directory option may be specified on the make command line. Running the Application ----------------------- The application requires a number of command line options: .. code-block:: console ./build/link_status_interrupt [EAL options] -- -p PORTMASK [-q NQ][-T PERIOD] where, * -p PORTMASK: A hexadecimal bitmask of the ports to configure * -q NQ: A number of queues (=ports) per lcore (default is 1) * -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default) To run the application in a linuxapp environment with 4 lcores, 4 memory channels, 16 ports and 8 RX queues per lcore, issue the command: .. code-block:: console $ ./build/link_status_interrupt -c f -n 4-- -q 8 -p ffff Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. Command Line Arguments ~~~~~~~~~~~~~~~~~~~~~~ The Link Status Interrupt sample application takes specific parameters, in addition to Environment Abstraction Layer (EAL) arguments (see Section 13.3). Command line parsing is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.1, "Command Line Arguments" for more information. Mbuf Pool Initialization ~~~~~~~~~~~~~~~~~~~~~~~~ Mbuf pool initialization is done in the same way as it is done in the L2 Forwarding Sample Application. See Section 9.4.2, "Mbuf Pool Initialization" for more information. Driver Initialization ~~~~~~~~~~~~~~~~~~~~~ The main part of the code in the main() function relates to the initialization of the driver. To fully understand this code, it is recommended to study the chapters that related to the Poll Mode Driver in the *DPDK Programmer's Guide and the DPDK API Reference*. .. code-block:: c if (rte_eal_pci_probe() < 0) rte_exit(EXIT_FAILURE, "Cannot probe PCI\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((lsi_enabled_port_mask & (1 << portid)) == 0) continue; /* save the destination port id */ if (nb_ports_in_mask % 2) { lsi_dst_ports[portid] = portid_last; lsi_dst_ports[portid_last] = portid; } else portid_last = portid; nb_ports_in_mask++; rte_eth_dev_info_get((uint8_t) portid, &dev_info); } Observe that: * rte_eal_pci_probe() parses the devices on the PCI bus and initializes recognized devices. The next step is to configure the RX and TX queues. For each port, there is only one RX queue (only one lcore is able to poll a given port). The number of TX queues depends on the number of available lcores. The rte_eth_dev_configure() function is used to configure the number of queues for a port: .. code-block:: c ret = rte_eth_dev_configure((uint8_t) portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, portid); The global configuration is stored in a static structure: .. code-block:: c static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .hw_strip_crc= 0, /**< CRC stripped by hardware */ }, .txmode = {}, .intr_conf = { .lsc = 1, /**< link status interrupt feature enabled */ }, }; Configuring lsc to 0 (the default) disables the generation of any link status change interrupts in kernel space and no user space interrupt event is received. The public interface rte_eth_link_get() accesses the NIC registers directly to update the link status. Configuring lsc to non-zero enables the generation of link status change interrupts in kernel space when a link status change is present and calls the user space callbacks registered by the application. The public interface rte_eth_link_get() just reads the link status in a global structure that would be updated in the interrupt host thread only. Interrupt Callback Registration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The application can register one or more callbacks to a specific port and interrupt event. An example callback function that has been written as indicated below. .. code-block:: c static void lsi_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param) { struct rte_eth_link link; RTE_SET_USED(param); printf("\n\nIn registered callback...\n"); printf("Event type: %s\n", type == RTE_ETH_EVENT_INTR_LSC ? "LSC interrupt" : "unknown event"); rte_eth_link_get_nowait(port_id, &link); if (link.link_status) { printf("Port %d Link Up - speed %u Mbps - %s\n\n", port_id, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); } else printf("Port %d Link Down\n\n", port_id); } This function is called when a link status interrupt is present for the right port. The port_id indicates which port the interrupt applies to. The type parameter identifies the interrupt event type, which currently can be RTE_ETH_EVENT_INTR_LSC only, but other types can be added in the future. The param parameter is the address of the parameter for the callback. This function should be implemented with care since it will be called in the interrupt host thread, which is different from the main thread of its caller. The application registers the lsi_event_callback and a NULL parameter to the link status interrupt event on each port: .. code-block:: c rte_eth_dev_callback_register((uint8_t)portid, RTE_ETH_EVENT_INTR_LSC, lsi_event_callback, NULL); This registration can be done only after calling the rte_eth_dev_configure() function and before calling any other function. If lsc is initialized with 0, the callback is never called since no interrupt event would ever be present. RX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ The application uses one lcore to poll one or several ports, depending on the -q option, which specifies the number of queues per lcore. For example, if the user specifies -q 4, the application is able to poll four ports with one lcore. If there are 16 ports on the target (and if the portmask argument is -p ffff), the application will need four lcores to poll all the ports. .. code-block:: c ret = rte_eth_rx_queue_setup((uint8_t) portid, 0, nb_rxd, SOCKET0, &rx_conf, lsi_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d, port=%u\n", ret, portid); The list of queues that must be polled for a given lcore is stored in a private structure called struct lcore_queue_conf. .. code-block:: c struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; unsigned tx_queue_id; struct mbuf_table tx_mbufs[LSI_MAX_PORTS]; } rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; The n_rx_port and rx_port_list[] fields are used in the main packet processing loop (see Section 13.4.7, "Receive, Process and Transmit Packets" later in this chapter). The global configuration for the RX queues is stored in a static structure: .. code-block:: c static const struct rte_eth_rxconf rx_conf = { .rx_thresh = { .pthresh = RX_PTHRESH, .hthresh = RX_HTHRESH, .wthresh = RX_WTHRESH, }, }; TX Queue Initialization ~~~~~~~~~~~~~~~~~~~~~~~ Each lcore should be able to transmit on any port. For every port, a single TX queue is initialized. .. code-block:: c /* init one TX queue logical core on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), &tx_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d,port=%u\n", ret, (unsigned) portid); The global configuration for TX queues is stored in a static structure: .. code-block:: c static const struct rte_eth_txconf tx_conf = { .tx_thresh = { .pthresh = TX_PTHRESH, .hthresh = TX_HTHRESH, .wthresh = TX_WTHRESH, }, .tx_free_thresh = RTE_TEST_TX_DESC_DEFAULT + 1, /* disable feature */ }; Receive, Process and Transmit Packets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the lsi_main_loop() function, the main task is to read ingress packets from the RX queues. This is done using the following code: .. code-block:: c /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); port_statistics[portid].rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); lsi_simple_forward(m, portid); } } Packets are read in a burst of size MAX_PKT_BURST. The rte_eth_rx_burst() function writes the mbuf pointers in a local table and returns the number of available mbufs in the table. Then, each mbuf in the table is processed by the lsi_simple_forward() function. The processing is very simple: processes the TX port from the RX port and then replaces the source and destination MAC addresses. .. note:: In the following code, the two lines for calculating the output port require some explanation. If portId is even, the first line does nothing (as portid & 1 will be 0), and the second line adds 1. If portId is odd, the first line subtracts one and the second line does nothing. Therefore, 0 goes to 1, and 1 to 0, 2 goes to 3 and 3 to 2, and so on. .. code-block:: c static void lsi_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port = lsi_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + (dst_port << 40); /* src addr */ ether_addr_copy(&lsi_ports_eth_addr[dst_port], ð->s_addr); lsi_send_packet(m, dst_port); } Then, the packet is sent using the lsi_send_packet(m, dst_port) function. For this test application, the processing is exactly the same for all packets arriving on the same RX port. Therefore, it would have been possible to call the lsi_send_burst() function directly from the main loop to send all the received packets on the same TX port using the burst-oriented send function, which is more efficient. However, in real-life applications (such as, L3 routing), packet N is not necessarily forwarded on the same port as packet N-1. The application is implemented to illustrate that so the same approach can be reused in a more complex application. The lsi_send_packet() function stores the packet in a per-lcore and per-txport table. If the table is full, the whole packets table is transmitted using the lsi_send_burst() function: .. code-block:: c /* Send the packet on an output interface */ static int lsi_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { lsi_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } To ensure that no packets remain in the tables, each lcore does a draining of the TX queue in its main loop. This technique introduces some latency when there are not many packets to send. However, it improves performance: .. code-block:: c cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* this could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; lsi_send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } ================================================ FILE: doc/guides/sample_app_ug/load_balancer.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Load Balancer Sample Application ================================ The Load Balancer sample application demonstrates the concept of isolating the packet I/O task from the application-specific workload. Depending on the performance target, a number of logical cores (lcores) are dedicated to handle the interaction with the NIC ports (I/O lcores), while the rest of the lcores are dedicated to performing the application processing (worker lcores). The worker lcores are totally oblivious to the intricacies of the packet I/O activity and use the NIC-agnostic interface provided by software rings to exchange packets with the I/O cores. Overview -------- The architecture of the Load Balance application is presented in the following figure. .. _figure_load_bal_app_arch: .. figure:: img/load_bal_app_arch.* Load Balancer Application Architecture For the sake of simplicity, the diagram illustrates a specific case of two I/O RX and two I/O TX lcores off loading the packet I/O overhead incurred by four NIC ports from four worker cores, with each I/O lcore handling RX/TX for two NIC ports. I/O RX Logical Cores ~~~~~~~~~~~~~~~~~~~~ Each I/O RX lcore performs packet RX from its assigned NIC RX rings and then distributes the received packets to the worker threads. The application allows each I/O RX lcore to communicate with any of the worker threads, therefore each (I/O RX lcore, worker lcore) pair is connected through a dedicated single producer - single consumer software ring. The worker lcore to handle the current packet is determined by reading a predefined 1-byte field from the input packet: worker_id = packet[load_balancing_field] % n_workers Since all the packets that are part of the same traffic flow are expected to have the same value for the load balancing field, this scheme also ensures that all the packets that are part of the same traffic flow are directed to the same worker lcore (flow affinity) in the same order they enter the system (packet ordering). I/O TX Logical Cores ~~~~~~~~~~~~~~~~~~~~ Each I/O lcore owns the packet TX for a predefined set of NIC ports. To enable each worker thread to send packets to any NIC TX port, the application creates a software ring for each (worker lcore, NIC TX port) pair, with each I/O TX core handling those software rings that are associated with NIC ports that it handles. Worker Logical Cores ~~~~~~~~~~~~~~~~~~~~ Each worker lcore reads packets from its set of input software rings and routes them to the NIC ports for transmission by dispatching them to output software rings. The routing logic is LPM based, with all the worker threads sharing the same LPM rules. Compiling the Application ------------------------- The sequence of steps used to build the application is: #. Export the required environment variables: .. code-block:: console export RTE_SDK= export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application executable file: .. code-block:: console cd ${RTE_SDK}/examples/load_balancer make For more details on how to build the DPDK libraries and sample applications, please refer to the *DPDK Getting Started Guide.* Running the Application ----------------------- To successfully run the application, the command line used to start the application has to be in sync with the traffic flows configured on the traffic generator side. For examples of application command lines and traffic generator flows, please refer to the DPDK Test Report. For more details on how to set up and run the sample applications provided with DPDK package, please refer to the *DPDK Getting Started Guide*. Explanation ----------- Application Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~ The application run-time configuration is done through the application command line parameters. Any parameter that is not specified as mandatory is optional, with the default value hard-coded in the main.h header file from the application folder. The list of application command line parameters is listed below: #. --rx "(PORT, QUEUE, LCORE), ...": The list of NIC RX ports and queues handled by the I/O RX lcores. This parameter also implicitly defines the list of I/O RX lcores. This is a mandatory parameter. #. --tx "(PORT, LCORE), ... ": The list of NIC TX ports handled by the I/O TX lcores. This parameter also implicitly defines the list of I/O TX lcores. This is a mandatory parameter. #. --w "LCORE, ...": The list of the worker lcores. This is a mandatory parameter. #. --lpm "IP / PREFIX => PORT; ...": The list of LPM rules used by the worker lcores for packet forwarding. This is a mandatory parameter. #. --rsz "A, B, C, D": Ring sizes: #. A = The size (in number of buffer descriptors) of each of the NIC RX rings read by the I/O RX lcores. #. B = The size (in number of elements) of each of the software rings used by the I/O RX lcores to send packets to worker lcores. #. C = The size (in number of elements) of each of the software rings used by the worker lcores to send packets to I/O TX lcores. #. D = The size (in number of buffer descriptors) of each of the NIC TX rings written by I/O TX lcores. #. --bsz "(A, B), (C, D), (E, F)": Burst sizes: #. A = The I/O RX lcore read burst size from NIC RX. #. B = The I/O RX lcore write burst size to the output software rings. #. C = The worker lcore read burst size from the input software rings. #. D = The worker lcore write burst size to the output software rings. #. E = The I/O TX lcore read burst size from the input software rings. #. F = The I/O TX lcore write burst size to the NIC TX. #. --pos-lb POS: The position of the 1-byte field within the input packet used by the I/O RX lcores to identify the worker lcore for the current packet. This field needs to be within the first 64 bytes of the input packet. The infrastructure of software rings connecting I/O lcores and worker lcores is built by the application as a result of the application configuration provided by the user through the application command line parameters. A specific lcore performing the I/O RX role for a specific set of NIC ports can also perform the I/O TX role for the same or a different set of NIC ports. A specific lcore cannot perform both the I/O role (either RX or TX) and the worker role during the same session. Example: .. code-block:: console ./load_balancer -c 0xf8 -n 4 -- --rx "(0,0,3),(1,0,3)" --tx "(0,3),(1,3)" --w "4,5,6,7" --lpm "1.0.0.0/24=>0; 1.0.1.0/24=>1;" --pos-lb 29 There is a single I/O lcore (lcore 3) that handles RX and TX for two NIC ports (ports 0 and 1) that handles packets to/from four worker lcores (lcores 4, 5, 6 and 7) that are assigned worker IDs 0 to 3 (worker ID for lcore 4 is 0, for lcore 5 is 1, for lcore 6 is 2 and for lcore 7 is 3). Assuming that all the input packets are IPv4 packets with no VLAN label and the source IP address of the current packet is A.B.C.D, the worker lcore for the current packet is determined by byte D (which is byte 29). There are two LPM rules that are used by each worker lcore to route packets to the output NIC ports. The following table illustrates the packet flow through the system for several possible traffic flows: +------------+----------------+-----------------+------------------------------+--------------+ | **Flow #** | **Source** | **Destination** | **Worker ID (Worker lcore)** | **Output** | | | **IP Address** | **IP Address** | | **NIC Port** | | | | | | | +============+================+=================+==============================+==============+ | 1 | 0.0.0.0 | 1.0.0.1 | 0 (4) | 0 | | | | | | | +------------+----------------+-----------------+------------------------------+--------------+ | 2 | 0.0.0.1 | 1.0.1.2 | 1 (5) | 1 | | | | | | | +------------+----------------+-----------------+------------------------------+--------------+ | 3 | 0.0.0.14 | 1.0.0.3 | 2 (6) | 0 | | | | | | | +------------+----------------+-----------------+------------------------------+--------------+ | 4 | 0.0.0.15 | 1.0.1.4 | 3 (7) | 1 | | | | | | | +------------+----------------+-----------------+------------------------------+--------------+ NUMA Support ~~~~~~~~~~~~ The application has built-in performance enhancements for the NUMA case: #. One buffer pool per each CPU socket. #. One LPM table per each CPU socket. #. Memory for the NIC RX or TX rings is allocated on the same socket with the lcore handling the respective ring. In the case where multiple CPU sockets are used in the system, it is recommended to enable at least one lcore to fulfill the I/O role for the NIC ports that are directly attached to that CPU socket through the PCI Express* bus. It is always recommended to handle the packet I/O with lcores from the same CPU socket as the NICs. Depending on whether the I/O RX lcore (same CPU socket as NIC RX), the worker lcore and the I/O TX lcore (same CPU socket as NIC TX) handling a specific input packet, are on the same or different CPU sockets, the following run-time scenarios are possible: #. AAA: The packet is received, processed and transmitted without going across CPU sockets. #. AAB: The packet is received and processed on socket A, but as it has to be transmitted on a NIC port connected to socket B, the packet is sent to socket B through software rings. #. ABB: The packet is received on socket A, but as it has to be processed by a worker lcore on socket B, the packet is sent to socket B through software rings. The packet is transmitted by a NIC port connected to the same CPU socket as the worker lcore that processed it. #. ABC: The packet is received on socket A, it is processed by an lcore on socket B, then it has to be transmitted out by a NIC connected to socket C. The performance price for crossing the CPU socket boundary is paid twice for this packet. ================================================ FILE: doc/guides/sample_app_ug/multi_process.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .. _multi_process_app: Multi-process Sample Application ================================ This chapter describes the example applications for multi-processing that are included in the DPDK. Example Applications -------------------- Building the Sample Applications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The multi-process example applications are built in the same way as other sample applications, and as documented in the *DPDK Getting Started Guide*. To build all the example applications: #. Set RTE_SDK and go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/multi_process #. Set the target (a default target will be used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the applications: .. code-block:: console make .. note:: If just a specific multi-process application needs to be built, the final make command can be run just in that application's directory, rather than at the top-level multi-process directory. Basic Multi-process Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The examples/simple_mp folder in the DPDK release contains a basic example application to demonstrate how two DPDK processes can work together using queues and memory pools to share information. Running the Application ^^^^^^^^^^^^^^^^^^^^^^^ To run the application, start one copy of the simple_mp binary in one terminal, passing at least two cores in the coremask, as follows: .. code-block:: console ./build/simple_mp -c 3 -n 4 --proc-type=primary For the first DPDK process run, the proc-type flag can be omitted or set to auto, since all DPDK processes will default to being a primary instance, meaning they have control over the hugepage shared memory regions. The process should start successfully and display a command prompt as follows: .. code-block:: console $ ./build/simple_mp -c 3 -n 4 --proc-type=primary EAL: coremask set to 3 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 0 EAL: Detected lcore 2 on socket 0 EAL: Detected lcore 3 on socket 0 ... EAL: Requesting 2 pages of size 1073741824 EAL: Requesting 768 pages of size 2097152 EAL: Ask a virtual area of 0x40000000 bytes EAL: Virtual area found at 0x7ff200000000 (size = 0x40000000) ... EAL: check igb_uio module EAL: check module finished EAL: Master core 0 is ready (tid=54e41820) EAL: Core 1 is ready (tid=53b32700) Starting core 1 simple_mp > To run the secondary process to communicate with the primary process, again run the same binary setting at least two cores in the coremask: .. code-block:: console ./build/simple_mp -c C -n 4 --proc-type=secondary When running a secondary process such as that shown above, the proc-type parameter can again be specified as auto. However, omitting the parameter altogether will cause the process to try and start as a primary rather than secondary process. Once the process type is specified correctly, the process starts up, displaying largely similar status messages to the primary instance as it initializes. Once again, you will be presented with a command prompt. Once both processes are running, messages can be sent between them using the send command. At any stage, either process can be terminated using the quit command. .. code-block:: console EAL: Master core 10 is ready (tid=b5f89820) EAL: Master core 8 is ready (tid=864a3820) EAL: Core 11 is ready (tid=84ffe700) EAL: Core 9 is ready (tid=85995700) Starting core 11 Starting core 9 simple_mp > send hello_secondary simple_mp > core 9: Received 'hello_secondary' simple_mp > core 11: Received 'hello_primary' simple_mp > send hello_primary simple_mp > quit simple_mp > quit .. note:: If the primary instance is terminated, the secondary instance must also be shut-down and restarted after the primary. This is necessary because the primary instance will clear and reset the shared memory regions on startup, invalidating the secondary process's pointers. The secondary process can be stopped and restarted without affecting the primary process. How the Application Works ^^^^^^^^^^^^^^^^^^^^^^^^^ The core of this example application is based on using two queues and a single memory pool in shared memory. These three objects are created at startup by the primary process, since the secondary process cannot create objects in memory as it cannot reserve memory zones, and the secondary process then uses lookup functions to attach to these objects as it starts up. .. code-block:: c if (rte_eal_process_type() == RTE_PROC_PRIMARY){ send_ring = rte_ring_create(_PRI_2_SEC, ring_size, SOCKET0, flags); recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, SOCKET0, flags); message_pool = rte_mempool_create(_MSG_POOL, pool_size, string_size, pool_cache, priv_data_sz, NULL, NULL, NULL, NULL, SOCKET0, flags); } else { recv_ring = rte_ring_lookup(_PRI_2_SEC); send_ring = rte_ring_lookup(_SEC_2_PRI); message_pool = rte_mempool_lookup(_MSG_POOL); } Note, however, that the named ring structure used as send_ring in the primary process is the recv_ring in the secondary process. Once the rings and memory pools are all available in both the primary and secondary processes, the application simply dedicates two threads to sending and receiving messages respectively. The receive thread simply dequeues any messages on the receive ring, prints them, and frees the buffer space used by the messages back to the memory pool. The send thread makes use of the command-prompt library to interactively request user input for messages to send. Once a send command is issued by the user, a buffer is allocated from the memory pool, filled in with the message contents, then enqueued on the appropriate rte_ring. Symmetric Multi-process Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The second example of DPDK multi-process support demonstrates how a set of processes can run in parallel, with each process performing the same set of packet- processing operations. (Since each process is identical in functionality to the others, we refer to this as symmetric multi-processing, to differentiate it from asymmetric multi- processing - such as a client-server mode of operation seen in the next example, where different processes perform different tasks, yet co-operate to form a packet-processing system.) The following diagram shows the data-flow through the application, using two processes. .. _figure_sym_multi_proc_app: .. figure:: img/sym_multi_proc_app.* Example Data Flow in a Symmetric Multi-process Application As the diagram shows, each process reads packets from each of the network ports in use. RSS is used to distribute incoming packets on each port to different hardware RX queues. Each process reads a different RX queue on each port and so does not contend with any other process for that queue access. Similarly, each process writes outgoing packets to a different TX queue on each port. Running the Application ^^^^^^^^^^^^^^^^^^^^^^^ As with the simple_mp example, the first instance of the symmetric_mp process must be run as the primary instance, though with a number of other application- specific parameters also provided after the EAL arguments. These additional parameters are: * -p , where portmask is a hexadecimal bitmask of what ports on the system are to be used. For example: -p 3 to use ports 0 and 1 only. * --num-procs , where N is the total number of symmetric_mp instances that will be run side-by-side to perform packet processing. This parameter is used to configure the appropriate number of receive queues on each network port. * --proc-id , where n is a numeric value in the range 0 <= n < N (number of processes, specified above). This identifies which symmetric_mp instance is being run, so that each process can read a unique receive queue on each network port. The secondary symmetric_mp instances must also have these parameters specified, and the first two must be the same as those passed to the primary instance, or errors result. For example, to run a set of four symmetric_mp instances, running on lcores 1-4, all performing level-2 forwarding of packets between ports 0 and 1, the following commands can be used (assuming run as root): .. code-block:: console # ./build/symmetric_mp -c 2 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=0 # ./build/symmetric_mp -c 4 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=1 # ./build/symmetric_mp -c 8 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=2 # ./build/symmetric_mp -c 10 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=3 .. note:: In the above example, the process type can be explicitly specified as primary or secondary, rather than auto. When using auto, the first process run creates all the memory structures needed for all processes - irrespective of whether it has a proc-id of 0, 1, 2 or 3. .. note:: For the symmetric multi-process example, since all processes work in the same manner, once the hugepage shared memory and the network ports are initialized, it is not necessary to restart all processes if the primary instance dies. Instead, that process can be restarted as a secondary, by explicitly setting the proc-type to secondary on the command line. (All subsequent instances launched will also need this explicitly specified, as auto-detection will detect no primary processes running and therefore attempt to re-initialize shared memory.) How the Application Works ^^^^^^^^^^^^^^^^^^^^^^^^^ The initialization calls in both the primary and secondary instances are the same for the most part, calling the rte_eal_init(), 1 G and 10 G driver initialization and then rte_eal_pci_probe() functions. Thereafter, the initialization done depends on whether the process is configured as a primary or secondary instance. In the primary instance, a memory pool is created for the packet mbufs and the network ports to be used are initialized - the number of RX and TX queues per port being determined by the num-procs parameter passed on the command-line. The structures for the initialized network ports are stored in shared memory and therefore will be accessible by the secondary process as it initializes. .. code-block:: c if (num_ports & 1) rte_exit(EXIT_FAILURE, "Application must use an even number of ports\n"); for(i = 0; i < num_ports; i++){ if(proc_type == RTE_PROC_PRIMARY) if (smp_port_init(ports[i], mp, (uint16_t)num_procs) < 0) rte_exit(EXIT_FAILURE, "Error initializing ports\n"); } In the secondary instance, rather than initializing the network ports, the port information exported by the primary process is used, giving the secondary process access to the hardware and software rings for each network port. Similarly, the memory pool of mbufs is accessed by doing a lookup for it by name: .. code-block:: c mp = (proc_type == RTE_PROC_SECONDARY) ? rte_mempool_lookup(_SMP_MBUF_POOL) : rte_mempool_create(_SMP_MBUF_POOL, NB_MBUFS, MBUF_SIZE, ... ) Once this initialization is complete, the main loop of each process, both primary and secondary, is exactly the same - each process reads from each port using the queue corresponding to its proc-id parameter, and writes to the corresponding transmit queue on the output port. Client-Server Multi-process Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The third example multi-process application included with the DPDK shows how one can use a client-server type multi-process design to do packet processing. In this example, a single server process performs the packet reception from the ports being used and distributes these packets using round-robin ordering among a set of client processes, which perform the actual packet processing. In this case, the client applications just perform level-2 forwarding of packets by sending each packet out on a different network port. The following diagram shows the data-flow through the application, using two client processes. .. _figure_client_svr_sym_multi_proc_app: .. figure:: img/client_svr_sym_multi_proc_app.* Example Data Flow in a Client-Server Symmetric Multi-process Application Running the Application ^^^^^^^^^^^^^^^^^^^^^^^ The server process must be run initially as the primary process to set up all memory structures for use by the clients. In addition to the EAL parameters, the application- specific parameters are: * -p , where portmask is a hexadecimal bitmask of what ports on the system are to be used. For example: -p 3 to use ports 0 and 1 only. * -n , where the num-clients parameter is the number of client processes that will process the packets received by the server application. .. note:: In the server process, a single thread, the master thread, that is, the lowest numbered lcore in the coremask, performs all packet I/O. If a coremask is specified with more than a single lcore bit set in it, an additional lcore will be used for a thread to periodically print packet count statistics. Since the server application stores configuration data in shared memory, including the network ports to be used, the only application parameter needed by a client process is its client instance ID. Therefore, to run a server application on lcore 1 (with lcore 2 printing statistics) along with two client processes running on lcores 3 and 4, the following commands could be used: .. code-block:: console # ./mp_server/build/mp_server -c 6 -n 4 -- -p 3 -n 2 # ./mp_client/build/mp_client -c 8 -n 4 --proc-type=auto -- -n 0 # ./mp_client/build/mp_client -c 10 -n 4 --proc-type=auto -- -n 1 .. note:: If the server application dies and needs to be restarted, all client applications also need to be restarted, as there is no support in the server application for it to run as a secondary process. Any client processes that need restarting can be restarted without affecting the server process. How the Application Works ^^^^^^^^^^^^^^^^^^^^^^^^^ The server process performs the network port and data structure initialization much as the symmetric multi-process application does when run as primary. One additional enhancement in this sample application is that the server process stores its port configuration data in a memory zone in hugepage shared memory. This eliminates the need for the client processes to have the portmask parameter passed into them on the command line, as is done for the symmetric multi-process application, and therefore eliminates mismatched parameters as a potential source of errors. In the same way that the server process is designed to be run as a primary process instance only, the client processes are designed to be run as secondary instances only. They have no code to attempt to create shared memory objects. Instead, handles to all needed rings and memory pools are obtained via calls to rte_ring_lookup() and rte_mempool_lookup(). The network ports for use by the processes are obtained by loading the network port drivers and probing the PCI bus, which will, as in the symmetric multi-process example, automatically get access to the network ports using the settings already configured by the primary/server process. Once all applications are initialized, the server operates by reading packets from each network port in turn and distributing those packets to the client queues (software rings, one for each client process) in round-robin order. On the client side, the packets are read from the rings in as big of bursts as possible, then routed out to a different network port. The routing used is very simple. All packets received on the first NIC port are transmitted back out on the second port and vice versa. Similarly, packets are routed between the 3rd and 4th network ports and so on. The sending of packets is done by writing the packets directly to the network ports; they are not transferred back via the server process. In both the server and the client processes, outgoing packets are buffered before being sent, so as to allow the sending of multiple packets in a single burst to improve efficiency. For example, the client process will buffer packets to send, until either the buffer is full or until we receive no further packets from the server. Master-slave Multi-process Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The fourth example of DPDK multi-process support demonstrates a master-slave model that provide the capability of application recovery if a slave process crashes or meets unexpected conditions. In addition, it also demonstrates the floating process, which can run among different cores in contrast to the traditional way of binding a process/thread to a specific CPU core, using the local cache mechanism of mempool structures. This application performs the same functionality as the L2 Forwarding sample application, therefore this chapter does not cover that part but describes functionality that is introduced in this multi-process example only. Please refer to Chapter 9, "L2 Forwarding Sample Application (in Real and Virtualized Environments)" for more information. Unlike previous examples where all processes are started from the command line with input arguments, in this example, only one process is spawned from the command line and that process creates other processes. The following section describes this in more detail. Master-slave Process Models ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The process spawned from the command line is called the *master process* in this document. A process created by the master is called a *slave process*. The application has only one master process, but could have multiple slave processes. Once the master process begins to run, it tries to initialize all the resources such as memory, CPU cores, driver, ports, and so on, as the other examples do. Thereafter, it creates slave processes, as shown in the following figure. .. _figure_master_slave_proc: .. figure:: img/master_slave_proc.* Master-slave Process Workflow The master process calls the rte_eal_mp_remote_launch() EAL function to launch an application function for each pinned thread through the pipe. Then, it waits to check if any slave processes have exited. If so, the process tries to re-initialize the resources that belong to that slave and launch them in the pinned thread entry again. The following section describes the recovery procedures in more detail. For each pinned thread in EAL, after reading any data from the pipe, it tries to call the function that the application specified. In this master specified function, a fork() call creates a slave process that performs the L2 forwarding task. Then, the function waits until the slave exits, is killed or crashes. Thereafter, it notifies the master of this event and returns. Finally, the EAL pinned thread waits until the new function is launched. After discussing the master-slave model, it is necessary to mention another issue, global and static variables. For multiple-thread cases, all global and static variables have only one copy and they can be accessed by any thread if applicable. So, they can be used to sync or share data among threads. In the previous examples, each process has separate global and static variables in memory and are independent of each other. If it is necessary to share the knowledge, some communication mechanism should be deployed, such as, memzone, ring, shared memory, and so on. The global or static variables are not a valid approach to share data among processes. For variables in this example, on the one hand, the slave process inherits all the knowledge of these variables after being created by the master. On the other hand, other processes cannot know if one or more processes modifies them after slave creation since that is the nature of a multiple process address space. But this does not mean that these variables cannot be used to share or sync data; it depends on the use case. The following are the possible use cases: #. The master process starts and initializes a variable and it will never be changed after slave processes created. This case is OK. #. After the slave processes are created, the master or slave cores need to change a variable, but other processes do not need to know the change. This case is also OK. #. After the slave processes are created, the master or a slave needs to change a variable. In the meantime, one or more other process needs to be aware of the change. In this case, global and static variables cannot be used to share knowledge. Another communication mechanism is needed. A simple approach without lock protection can be a heap buffer allocated by rte_malloc or mem zone. Slave Process Recovery Mechanism ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Before talking about the recovery mechanism, it is necessary to know what is needed before a new slave instance can run if a previous one exited. When a slave process exits, the system returns all the resources allocated for this process automatically. However, this does not include the resources that were allocated by the DPDK. All the hardware resources are shared among the processes, which include memzone, mempool, ring, a heap buffer allocated by the rte_malloc library, and so on. If the new instance runs and the allocated resource is not returned, either resource allocation failed or the hardware resource is lost forever. When a slave process runs, it may have dependencies on other processes. They could have execution sequence orders; they could share the ring to communicate; they could share the same port for reception and forwarding; they could use lock structures to do exclusive access in some critical path. What happens to the dependent process(es) if the peer leaves? The consequence are varied since the dependency cases are complex. It depends on what the processed had shared. However, it is necessary to notify the peer(s) if one slave exited. Then, the peer(s) will be aware of that and wait until the new instance begins to run. Therefore, to provide the capability to resume the new slave instance if the previous one exited, it is necessary to provide several mechanisms: #. Keep a resource list for each slave process. Before a slave process run, the master should prepare a resource list. After it exits, the master could either delete the allocated resources and create new ones, or re-initialize those for use by the new instance. #. Set up a notification mechanism for slave process exit cases. After the specific slave leaves, the master should be notified and then help to create a new instance. This mechanism is provided in Section 15.1.5.1, "Master-slave Process Models". #. Use a synchronization mechanism among dependent processes. The master should have the capability to stop or kill slave processes that have a dependency on the one that has exited. Then, after the new instance of exited slave process begins to run, the dependency ones could resume or run from the start. The example sends a STOP command to slave processes dependent on the exited one, then they will exit. Thereafter, the master creates new instances for the exited slave processes. The following diagram describes slave process recovery. .. _figure_slave_proc_recov: .. figure:: img/slave_proc_recov.* Slave Process Recovery Process Flow Floating Process Support ^^^^^^^^^^^^^^^^^^^^^^^^ When the DPDK application runs, there is always a -c option passed in to indicate the cores that are enabled. Then, the DPDK creates a thread for each enabled core. By doing so, it creates a 1:1 mapping between the enabled core and each thread. The enabled core always has an ID, therefore, each thread has a unique core ID in the DPDK execution environment. With the ID, each thread can easily access the structures or resources exclusively belonging to it without using function parameter passing. It can easily use the rte_lcore_id() function to get the value in every function that is called. For threads/processes not created in that way, either pinned to a core or not, they will not own a unique ID and the rte_lcore_id() function will not work in the correct way. However, sometimes these threads/processes still need the unique ID mechanism to do easy access on structures or resources. For example, the DPDK mempool library provides a local cache mechanism (refer to *DPDK Programmer's Guide* , Section 6.4, "Local Cache") for fast element allocation and freeing. If using a non-unique ID or a fake one, a race condition occurs if two or more threads/ processes with the same core ID try to use the local cache. Therefore, unused core IDs from the passing of parameters with the -c option are used to organize the core ID allocation array. Once the floating process is spawned, it tries to allocate a unique core ID from the array and release it on exit. A natural way to spawn a floating process is to use the fork() function and allocate a unique core ID from the unused core ID array. However, it is necessary to write new code to provide a notification mechanism for slave exit and make sure the process recovery mechanism can work with it. To avoid producing redundant code, the Master-Slave process model is still used to spawn floating processes, then cancel the affinity to specific cores. Besides that, clear the core ID assigned to the DPDK spawning a thread that has a 1:1 mapping with the core mask. Thereafter, get a new core ID from the unused core ID allocation array. Run the Application ^^^^^^^^^^^^^^^^^^^ This example has a command line similar to the L2 Forwarding sample application with a few differences. To run the application, start one copy of the l2fwd_fork binary in one terminal. Unlike the L2 Forwarding example, this example requires at least three cores since the master process will wait and be accountable for slave process recovery. The command is as follows: .. code-block:: console #./build/l2fwd_fork -c 1c -n 4 -- -p 3 -f This example provides another -f option to specify the use of floating process. If not specified, the example will use a pinned process to perform the L2 forwarding task. To verify the recovery mechanism, proceed as follows: First, check the PID of the slave processes: .. code-block:: console #ps -fe | grep l2fwd_fork root 5136 4843 29 11:11 pts/1 00:00:05 ./build/l2fwd_fork root 5145 5136 98 11:11 pts/1 00:00:11 ./build/l2fwd_fork root 5146 5136 98 11:11 pts/1 00:00:11 ./build/l2fwd_fork Then, kill one of the slaves: .. code-block:: console #kill -9 5145 After 1 or 2 seconds, check whether the slave has resumed: .. code-block:: console #ps -fe | grep l2fwd_fork root 5136 4843 3 11:11 pts/1 00:00:06 ./build/l2fwd_fork root 5247 5136 99 11:14 pts/1 00:00:01 ./build/l2fwd_fork root 5248 5136 99 11:14 pts/1 00:00:01 ./build/l2fwd_fork It can also monitor the traffic generator statics to see whether slave processes have resumed. Explanation ^^^^^^^^^^^ As described in previous sections, not all global and static variables need to change to be accessible in multiple processes; it depends on how they are used. In this example, the statics info on packets dropped/forwarded/received count needs to be updated by the slave process, and the master needs to see the update and print them out. So, it needs to allocate a heap buffer using rte_zmalloc. In addition, if the -f option is specified, an array is needed to store the allocated core ID for the floating process so that the master can return it after a slave has exited accidentally. .. code-block:: c static int l2fwd_malloc_shared_struct(void) { port_statistics = rte_zmalloc("port_stat", sizeof(struct l2fwd_port_statistics) * RTE_MAX_ETHPORTS, 0); if (port_statistics == NULL) return -1; /* allocate mapping_id array */ if (float_proc) { int i; mapping_id = rte_malloc("mapping_id", sizeof(unsigned) * RTE_MAX_LCORE, 0); if (mapping_id == NULL) return -1; for (i = 0 ;i < RTE_MAX_LCORE; i++) mapping_id[i] = INVALID_MAPPING_ID; } return 0; } For each slave process, packets are received from one port and forwarded to another port that another slave is operating on. If the other slave exits accidentally, the port it is operating on may not work normally, so the first slave cannot forward packets to that port. There is a dependency on the port in this case. So, the master should recognize the dependency. The following is the code to detect this dependency: .. code-block:: c for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; /* Find pair ports' lcores */ find_lcore = find_pair_lcore = 0; pair_port = l2fwd_dst_ports[portid]; for (i = 0; i < RTE_MAX_LCORE; i++) { if (!rte_lcore_is_enabled(i)) continue; for (j = 0; j < lcore_queue_conf[i].n_rx_port;j++) { if (lcore_queue_conf[i].rx_port_list[j] == portid) { lcore = i; find_lcore = 1; break; } if (lcore_queue_conf[i].rx_port_list[j] == pair_port) { pair_lcore = i; find_pair_lcore = 1; break; } } if (find_lcore && find_pair_lcore) break; } if (!find_lcore || !find_pair_lcore) rte_exit(EXIT_FAILURE, "Not find port=%d pair\\n", portid); printf("lcore %u and %u paired\\n", lcore, pair_lcore); lcore_resource[lcore].pair_id = pair_lcore; lcore_resource[pair_lcore].pair_id = lcore; } Before launching the slave process, it is necessary to set up the communication channel between the master and slave so that the master can notify the slave if its peer process with the dependency exited. In addition, the master needs to register a callback function in the case where a specific slave exited. .. code-block:: c for (i = 0; i < RTE_MAX_LCORE; i++) { if (lcore_resource[i].enabled) { /* Create ring for master and slave communication */ ret = create_ms_ring(i); if (ret != 0) rte_exit(EXIT_FAILURE, "Create ring for lcore=%u failed",i); if (flib_register_slave_exit_notify(i,slave_exit_cb) != 0) rte_exit(EXIT_FAILURE, "Register master_trace_slave_exit failed"); } } After launching the slave process, the master waits and prints out the port statics periodically. If an event indicating that a slave process exited is detected, it sends the STOP command to the peer and waits until it has also exited. Then, it tries to clean up the execution environment and prepare new resources. Finally, the new slave instance is launched. .. code-block:: c while (1) { sleep(1); cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { print_stats(); /* reset the timer */ timer_tsc = 0; } } prev_tsc = cur_tsc; /* Check any slave need restart or recreate */ rte_spinlock_lock(&res_lock); for (i = 0; i < RTE_MAX_LCORE; i++) { struct lcore_resource_struct *res = &lcore_resource[i]; struct lcore_resource_struct *pair = &lcore_resource[res->pair_id]; /* If find slave exited, try to reset pair */ if (res->enabled && res->flags && pair->enabled) { if (!pair->flags) { master_sendcmd_with_ack(pair->lcore_id, CMD_STOP); rte_spinlock_unlock(&res_lock); sleep(1); rte_spinlock_lock(&res_lock); if (pair->flags) continue; } if (reset_pair(res->lcore_id, pair->lcore_id) != 0) rte_exit(EXIT_FAILURE, "failed to reset slave"); res->flags = 0; pair->flags = 0; } } rte_spinlock_unlock(&res_lock); } When the slave process is spawned and starts to run, it checks whether the floating process option is applied. If so, it clears the affinity to a specific core and also sets the unique core ID to 0. Then, it tries to allocate a new core ID. Since the core ID has changed, the resource allocated by the master cannot work, so it remaps the resource to the new core ID slot. .. code-block:: c static int l2fwd_launch_one_lcore( attribute ((unused)) void *dummy) { unsigned lcore_id = rte_lcore_id(); if (float_proc) { unsigned flcore_id; /* Change it to floating process, also change it's lcore_id */ clear_cpu_affinity(); RTE_PER_LCORE(_lcore_id) = 0; /* Get a lcore_id */ if (flib_assign_lcore_id() < 0 ) { printf("flib_assign_lcore_id failed\n"); return -1; } flcore_id = rte_lcore_id(); /* Set mapping id, so master can return it after slave exited */ mapping_id[lcore_id] = flcore_id; printf("Org lcore_id = %u, cur lcore_id = %u\n",lcore_id, flcore_id); remapping_slave_resource(lcore_id, flcore_id); } l2fwd_main_loop(); /* return lcore_id before return */ if (float_proc) { flib_free_lcore_id(rte_lcore_id()); mapping_id[lcore_id] = INVALID_MAPPING_ID; } return 0; } ================================================ FILE: doc/guides/sample_app_ug/netmap_compatibility.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Netmap Compatibility Sample Application ======================================= Introduction ------------ The Netmap compatibility library provides a minimal set of APIs to give the ability to programs written against the Netmap APIs to be run with minimal changes to their source code, using the DPDK to perform the actual packet I/O. Since Netmap applications use regular system calls, like open(), ioctl() and mmap() to communicate with the Netmap kernel module performing the packet I/O, the compat_netmap library provides a set of similar APIs to use in place of those system calls, effectively turning a Netmap application into a DPDK one. The provided library is currently minimal and doesn't support all the features that Netmap supports, but is enough to run simple applications, such as the bridge example detailed below. Knowledge of Netmap is required to understand the rest of this section. Please refer to the Netmap distribution for details about Netmap. Available APIs -------------- The library provides the following drop-in replacements for system calls usually used in Netmap applications:rte_netmap_close() * rte_netmap_ioctl() * rte_netmap_open() * rte_netmap_mmap() * rte_netmap_poll() They use the same signature as their libc counterparts, and can be used as drop-in replacements in most cases. Caveats ------- Given the difference between the way Netmap and the DPDK approach packet I/O, there are caveats and limitations to be aware of when trying to use the compat_netmap library, the most important of which are listed below. Additional caveats are presented in the $RTE_SDK/examples/netmap_compat/README.md file. These can change as the library is updated: * Any system call that can potentially affect file descriptors cannot be used with a descriptor returned by the rte_netmap_open() function. Note that: * rte_netmap_mmap() merely returns the address of a DPDK memzone. The address, length, flags, offset, and so on arguments are therefore ignored completely. * rte_netmap_poll() only supports infinite (negative) or zero time outs. It effectively turns calls to the poll() system call made in a Netmap application into polling of the DPDK ports, changing the semantics of the usual POSIX defined poll. * Not all of Netmap's features are supported: "host rings", slot flags and so on are not supported or are simply not relevant in the DPDK model. * The Netmap manual page states that "a device obtained through /dev/netmap also supports the ioctl supported by network devices". It is not the case with this compatibility layer. * The Netmap kernel module exposes a sysfs interface to change some internal parameters, such as the size of the shared memory region. This interface is not available when using this compatibility layer. Porting Netmap Applications --------------------------- Porting Netmap applications typically involves two major steps: * Changing the system calls to use their compat_netmap library counterparts * Adding further DPDK initialization code Since the compat_netmap functions have the same signature as the usual libc calls, the change is in most cases trivial. The usual DPDK initialization code involving rte_eal_init() and rte_eal_pci_probe() has to be added to the Netmap application in the same way it is used in all other DPDK sample applications. Please refer to the *DPDK Programmer's Guide* - Rel 1.4 EAR and example source code for details about initialization. In addition of the regular DPDK initialization code, the ported application needs to call initialization functions for the compat_netmap library, namely rte_netmap_init() and rte_netmap_init_port(). These two initialization functions take compat_netmap specific data structures as parameters: struct rte_netmap_conf and struct rte_netmap_port_conf. Those structures' fields are Netmap related and are self-explanatory for developers familiar with Netmap. They are defined in $RTE_SDK/examples/netmap_compat/ lib/compat_netmap.h. The bridge application is an example largely based on the bridge example shipped with the Netmap distribution. It shows how a minimal Netmap application with minimal and straightforward source code changes can be run on top of the DPDK. Please refer to $RTE_SDK/examples/netmap_compat/bridge/bridge.c for an example of ported application. Compiling the "bridge" Sample Application ----------------------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/netmap_compat #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the "bridge" Sample Application --------------------------------------- The application requires a single command line option: .. code-block:: console ./build/packet_ordering [EAL options] -- -p PORT_A [-p PORT_B] where, * -p INTERFACE is the number of a valid DPDK port to use. If a single -p parameter is given, the interface will send back all the traffic it receives. If two -p parameters are given, the two interfaces form a bridge, where traffic received on one interface is replicated and sent by the other interface. To run the application in a linuxapp environment using port 0 and 2, issue the following command: .. code-block:: console ./build/packet_ordering [EAL options] -- -p 0 -p 2 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Note that unlike a traditional bridge or the l2fwd sample application, no MAC address changes are done on the frames. Do not forget to take that into account when configuring your traffic generators if you decide to test this sample application. ================================================ FILE: doc/guides/sample_app_ug/packet_ordering.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Packet Ordering Application ============================ The Packet Ordering sample app simply shows the impact of reordering a stream. It's meant to stress the library with different configurations for performance. Overview -------- The application uses at least three CPU cores: * RX core (maser core) receives traffic from the NIC ports and feeds Worker cores with traffic through SW queues. * Worker core (slave core) basically do some light work on the packet. Currently it modifies the output port of the packet for configurations with more than one port enabled. * TX Core (slave core) receives traffic from Worker cores through software queues, inserts out-of-order packets into reorder buffer, extracts ordered packets from the reorder buffer and sends them to the NIC ports for transmission. Compiling the Application -------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/helloworld #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started* Guide for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Application Command Line ~~~~~~~~~~~~~~~~~~~~~~~~ The application execution command line is: .. code-block:: console ./test-pipeline [EAL options] -- -p PORTMASK [--disable-reorder] The -c EAL CPU_COREMASK option has to contain at least 3 CPU cores. The first CPU core in the core mask is the master core and would be assigned to RX core, the last to TX core and the rest to Worker cores. The PORTMASK parameter must contain either 1 or even enabled port numbers. When setting more than 1 port, traffic would be forwarded in pairs. For example, if we enable 4 ports, traffic from port 0 to 1 and from 1 to 0, then the other pair from 2 to 3 and from 3 to 2, having [0,1] and [2,3] pairs. The disable-reorder long option does, as its name implies, disable the reordering of traffic, which should help evaluate reordering performance impact. ================================================ FILE: doc/guides/sample_app_ug/proc_info.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. proc_info Application ======================== The proc_info application is a Data Plane Development Kit (DPDK) application that runs as a DPDK secondary process and is capable of retrieving port statistics, resetting port statistics and printing DPDK memory information. This application extends the original functionality that was supported by dump_cfg. Running the Application ----------------------- The application has a number of command line options: .. code-block:: console ./$(RTE_TARGET)/app/proc_info -- -m | [-p PORTMASK] [--stats | --xstats | --stats-reset | --xstats-reset] Parameters ~~~~~~~~~~ **-p PORTMASK**: Hexadecimal bitmask of ports to configure. **--stats** The stats parameter controls the printing of generic port statistics. If no port mask is specified stats are printed for all DPDK ports. **--xstats** The stats parameter controls the printing of extended port statistics. If no port mask is specified xstats are printed for all DPDK ports. **--stats-reset** The stats-reset parameter controls the resetting of generic port statistics. If no port mask is specified, the generic stats are reset for all DPDK ports. **--xstats-reset** The xstats-reset parameter controls the resetting of extended port statistics. If no port mask is specified xstats are reset for all DPDK ports. **-m**: Print DPDK memory information. ================================================ FILE: doc/guides/sample_app_ug/qos_metering.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. QoS Metering Sample Application =============================== The QoS meter sample application is an example that demonstrates the use of DPDK to provide QoS marking and metering, as defined by RFC2697 for Single Rate Three Color Marker (srTCM) and RFC 2698 for Two Rate Three Color Marker (trTCM) algorithm. Overview -------- The application uses a single thread for reading the packets from the RX port, metering, marking them with the appropriate color (green, yellow or red) and writing them to the TX port. A policing scheme can be applied before writing the packets to the TX port by dropping or changing the color of the packet in a static manner depending on both the input and output colors of the packets that are processed by the meter. The operation mode can be selected as compile time out of the following options: * Simple forwarding * srTCM color blind * srTCM color aware * srTCM color blind * srTCM color aware Please refer to RFC2697 and RFC2698 for details about the srTCM and trTCM configurable parameters (CIR, CBS and EBS for srTCM; CIR, PIR, CBS and PBS for trTCM). The color blind modes are functionally equivalent with the color-aware modes when all the incoming packets are colored as green. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/qos_meter #. Set the target (a default target is used if not specified): .. note:: This application is intended as a linuxapp only. .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application: .. code-block:: console make Running the Application ----------------------- The application execution command line is as below: .. code-block:: console ./qos_meter [EAL options] -- -p PORTMASK The application is constrained to use a single core in the EAL core mask and 2 ports only in the application port mask (first port from the port mask is used for RX and the other port in the core mask is used for TX). Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- Selecting one of the metering modes is done with these defines: .. code-block:: c #define APP_MODE_FWD 0 #define APP_MODE_SRTCM_COLOR_BLIND 1 #define APP_MODE_SRTCM_COLOR_AWARE 2 #define APP_MODE_TRTCM_COLOR_BLIND 3 #define APP_MODE_TRTCM_COLOR_AWARE 4 #define APP_MODE APP_MODE_SRTCM_COLOR_BLIND To simplify debugging (for example, by using the traffic generator RX side MAC address based packet filtering feature), the color is defined as the LSB byte of the destination MAC address. The traffic meter parameters are configured in the application source code with following default values: .. code-block:: c struct rte_meter_srtcm_params app_srtcm_params[] = { {.cir = 1000000 * 46, .cbs = 2048, .ebs = 2048}, }; struct rte_meter_trtcm_params app_trtcm_params[] = { {.cir = 1000000 * 46, .pir = 1500000 * 46, .cbs = 2048, .pbs = 2048}, }; Assuming the input traffic is generated at line rate and all packets are 64 bytes Ethernet frames (IPv4 packet size of 46 bytes) and green, the expected output traffic should be marked as shown in the following table: .. _table_qos_metering_1: .. table:: Output Traffic Marking +-------------+------------------+-------------------+----------------+ | **Mode** | **Green (Mpps)** | **Yellow (Mpps)** | **Red (Mpps)** | | | | | | +=============+==================+===================+================+ | srTCM blind | 1 | 1 | 12.88 | | | | | | +-------------+------------------+-------------------+----------------+ | srTCM color | 1 | 1 | 12.88 | | | | | | +-------------+------------------+-------------------+----------------+ | trTCM blind | 1 | 0.5 | 13.38 | | | | | | +-------------+------------------+-------------------+----------------+ | trTCM color | 1 | 0.5 | 13.38 | | | | | | +-------------+------------------+-------------------+----------------+ | FWD | 14.88 | 0 | 0 | | | | | | +-------------+------------------+-------------------+----------------+ To set up the policing scheme as desired, it is necessary to modify the main.h source file, where this policy is implemented as a static structure, as follows: .. code-block:: c int policer_table[e_RTE_METER_COLORS][e_RTE_METER_COLORS] = { { GREEN, RED, RED}, { DROP, YELLOW, RED}, { DROP, DROP, RED} }; Where rows indicate the input color, columns indicate the output color, and the value that is stored in the table indicates the action to be taken for that particular case. There are four different actions: * GREEN: The packet's color is changed to green. * YELLOW: The packet's color is changed to yellow. * RED: The packet's color is changed to red. * DROP: The packet is dropped. In this particular case: * Every packet which input and output color are the same, keeps the same color. * Every packet which color has improved is dropped (this particular case can't happen, so these values will not be used). * For the rest of the cases, the color is changed to red. ================================================ FILE: doc/guides/sample_app_ug/qos_scheduler.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. QoS Scheduler Sample Application ================================ The QoS sample application demonstrates the use of the DPDK to provide QoS scheduling. Overview -------- The architecture of the QoS scheduler application is shown in the following figure. .. _figure_qos_sched_app_arch: .. figure:: img/qos_sched_app_arch.* QoS Scheduler Application Architecture There are two flavors of the runtime execution for this application, with two or three threads per each packet flow configuration being used. The RX thread reads packets from the RX port, classifies the packets based on the double VLAN (outer and inner) and the lower two bytes of the IP destination address and puts them into the ring queue. The worker thread dequeues the packets from the ring and calls the QoS scheduler enqueue/dequeue functions. If a separate TX core is used, these are sent to the TX ring. Otherwise, they are sent directly to the TX port. The TX thread, if present, reads from the TX ring and write the packets to the TX port. Compiling the Application ------------------------- To compile the application: #. Go to the sample application directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/qos_sched #. Set the target (a default target is used if not specified). For example: .. note:: This application is intended as a linuxapp only. .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application: .. code-block:: console make .. note:: To get statistics on the sample app using the command line interface as described in the next section, DPDK must be compiled defining *CONFIG_RTE_SCHED_COLLECT_STATS*, which can be done by changing the configuration file for the specific target to be compiled. Running the Application ----------------------- .. note:: In order to run the application, a total of at least 4 G of huge pages must be set up for each of the used sockets (depending on the cores in use). The application has a number of command line options: .. code-block:: console ./qos_sched [EAL options] -- Mandatory application parameters include: * --pfc "RX PORT, TX PORT, RX LCORE, WT LCORE, TX CORE": Packet flow configuration. Multiple pfc entities can be configured in the command line, having 4 or 5 items (if TX core defined or not). Optional application parameters include: * -i: It makes the application to start in the interactive mode. In this mode, the application shows a command line that can be used for obtaining statistics while scheduling is taking place (see interactive mode below for more information). * --mst n: Master core index (the default value is 1). * --rsz "A, B, C": Ring sizes: * A = Size (in number of buffer descriptors) of each of the NIC RX rings read by the I/O RX lcores (the default value is 128). * B = Size (in number of elements) of each of the software rings used by the I/O RX lcores to send packets to worker lcores (the default value is 8192). * C = Size (in number of buffer descriptors) of each of the NIC TX rings written by worker lcores (the default value is 256) * --bsz "A, B, C, D": Burst sizes * A = I/O RX lcore read burst size from the NIC RX (the default value is 64) * B = I/O RX lcore write burst size to the output software rings, worker lcore read burst size from input software rings,QoS enqueue size (the default value is 64) * C = QoS dequeue size (the default value is 32) * D = Worker lcore write burst size to the NIC TX (the default value is 64) * --msz M: Mempool size (in number of mbufs) for each pfc (default 2097152) * --rth "A, B, C": The RX queue threshold parameters * A = RX prefetch threshold (the default value is 8) * B = RX host threshold (the default value is 8) * C = RX write-back threshold (the default value is 4) * --tth "A, B, C": TX queue threshold parameters * A = TX prefetch threshold (the default value is 36) * B = TX host threshold (the default value is 0) * C = TX write-back threshold (the default value is 0) * --cfg FILE: Profile configuration to load Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. The profile configuration file defines all the port/subport/pipe/traffic class/queue parameters needed for the QoS scheduler configuration. The profile file has the following format: :: ; port configuration [port] frame overhead = 24 number of subports per port = 1 number of pipes per subport = 4096 queue sizes = 64 64 64 64 ; Subport configuration [subport 0] tb rate = 1250000000; Bytes per second tb size = 1000000; Bytes tc 0 rate = 1250000000; Bytes per second tc 1 rate = 1250000000; Bytes per second tc 2 rate = 1250000000; Bytes per second tc 3 rate = 1250000000; Bytes per second tc period = 10; Milliseconds tc oversubscription period = 10; Milliseconds pipe 0-4095 = 0; These pipes are configured with pipe profile 0 ; Pipe configuration [pipe profile 0] tb rate = 305175; Bytes per second tb size = 1000000; Bytes tc 0 rate = 305175; Bytes per second tc 1 rate = 305175; Bytes per second tc 2 rate = 305175; Bytes per second tc 3 rate = 305175; Bytes per second tc period = 40; Milliseconds tc 0 oversubscription weight = 1 tc 1 oversubscription weight = 1 tc 2 oversubscription weight = 1 tc 3 oversubscription weight = 1 tc 0 wrr weights = 1 1 1 1 tc 1 wrr weights = 1 1 1 1 tc 2 wrr weights = 1 1 1 1 tc 3 wrr weights = 1 1 1 1 ; RED params per traffic class and color (Green / Yellow / Red) [red] tc 0 wred min = 48 40 32 tc 0 wred max = 64 64 64 tc 0 wred inv prob = 10 10 10 tc 0 wred weight = 9 9 9 tc 1 wred min = 48 40 32 tc 1 wred max = 64 64 64 tc 1 wred inv prob = 10 10 10 tc 1 wred weight = 9 9 9 tc 2 wred min = 48 40 32 tc 2 wred max = 64 64 64 tc 2 wred inv prob = 10 10 10 tc 2 wred weight = 9 9 9 tc 3 wred min = 48 40 32 tc 3 wred max = 64 64 64 tc 3 wred inv prob = 10 10 10 tc 3 wred weight = 9 9 9 Interactive mode ~~~~~~~~~~~~~~~~ These are the commands that are currently working under the command line interface: * Control Commands * --quit: Quits the application. * General Statistics * stats app: Shows a table with in-app calculated statistics. * stats port X subport Y: For a specific subport, it shows the number of packets that went through the scheduler properly and the number of packets that were dropped. The same information is shown in bytes. The information is displayed in a table separating it in different traffic classes. * stats port X subport Y pipe Z: For a specific pipe, it shows the number of packets that went through the scheduler properly and the number of packets that were dropped. The same information is shown in bytes. This information is displayed in a table separating it in individual queues. * Average queue size All of these commands work the same way, averaging the number of packets throughout a specific subset of queues. Two parameters can be configured for this prior to calling any of these commands: * qavg n X: n is the number of times that the calculation will take place. Bigger numbers provide higher accuracy. The default value is 10. * qavg period X: period is the number of microseconds that will be allowed between each calculation. The default value is 100. The commands that can be used for measuring average queue size are: * qavg port X subport Y: Show average queue size per subport. * qavg port X subport Y tc Z: Show average queue size per subport for a specific traffic class. * qavg port X subport Y pipe Z: Show average queue size per pipe. * qavg port X subport Y pipe Z tc A: Show average queue size per pipe for a specific traffic class. * qavg port X subport Y pipe Z tc A q B: Show average queue size of a specific queue. Example ~~~~~~~ The following is an example command with a single packet flow configuration: .. code-block:: console ./qos_sched -c a2 -n 4 -- --pfc "3,2,5,7" --cfg ./profile.cfg This example uses a single packet flow configuration which creates one RX thread on lcore 5 reading from port 3 and a worker thread on lcore 7 writing to port 2. Another example with 2 packet flow configurations using different ports but sharing the same core for QoS scheduler is given below: .. code-block:: console ./qos_sched -c c6 -n 4 -- --pfc "3,2,2,6,7" --pfc "1,0,2,6,7" --cfg ./profile.cfg Note that independent cores for the packet flow configurations for each of the RX, WT and TX thread are also supported, providing flexibility to balance the work. The EAL coremask is constrained to contain the default mastercore 1 and the RX, WT and TX cores only. Explanation ----------- The Port/Subport/Pipe/Traffic Class/Queue are the hierarchical entities in a typical QoS application: * A subport represents a predefined group of users. * A pipe represents an individual user/subscriber. * A traffic class is the representation of a different traffic type with a specific loss rate, delay and jitter requirements; such as data voice, video or data transfers. * A queue hosts packets from one or multiple connections of the same type belonging to the same user. The traffic flows that need to be configured are application dependent. This application classifies based on the QinQ double VLAN tags and the IP destination address as indicated in the following table. .. _table_qos_scheduler_1: .. table:: Entity Types +----------------+-------------------------+--------------------------------------------------+----------------------------------+ | **Level Name** | **Siblings per Parent** | **QoS Functional Description** | **Selected By** | | | | | | +================+=========================+==================================================+==================================+ | Port | - | Ethernet port | Physical port | | | | | | +----------------+-------------------------+--------------------------------------------------+----------------------------------+ | Subport | Config (8) | Traffic shaped (token bucket) | Outer VLAN tag | | | | | | +----------------+-------------------------+--------------------------------------------------+----------------------------------+ | Pipe | Config (4k) | Traffic shaped (token bucket) | Inner VLAN tag | | | | | | +----------------+-------------------------+--------------------------------------------------+----------------------------------+ | Traffic Class | 4 | TCs of the same pipe services in strict priority | Destination IP address (0.0.X.0) | | | | | | +----------------+-------------------------+--------------------------------------------------+----------------------------------+ | Queue | 4 | Queue of the same TC serviced in WRR | Destination IP address (0.0.0.X) | | | | | | +----------------+-------------------------+--------------------------------------------------+----------------------------------+ Please refer to the "QoS Scheduler" chapter in the *DPDK Programmer's Guide* for more information about these parameters. ================================================ FILE: doc/guides/sample_app_ug/quota_watermark.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Quota and Watermark Sample Application ====================================== The Quota and Watermark sample application is a simple example of packet processing using Data Plane Development Kit (DPDK) that showcases the use of a quota as the maximum number of packets enqueue/dequeue at a time and low and high watermarks to signal low and high ring usage respectively. Additionally, it shows how ring watermarks can be used to feedback congestion notifications to data producers by temporarily stopping processing overloaded rings and sending Ethernet flow control frames. This sample application is split in two parts: * qw - The core quota and watermark sample application * qwctl - A command line tool to alter quota and watermarks while qw is running Overview -------- The Quota and Watermark sample application performs forwarding for each packet that is received on a given port. The destination port is the adjacent port from the enabled port mask, that is, if the first four ports are enabled (port mask 0xf), ports 0 and 1 forward into each other, and ports 2 and 3 forward into each other. The MAC addresses of the forwarded Ethernet frames are not affected. Internally, packets are pulled from the ports by the master logical core and put on a variable length processing pipeline, each stage of which being connected by rings, as shown in :numref:`figure_pipeline_overview`. .. _figure_pipeline_overview: .. figure:: img/pipeline_overview.* Pipeline Overview An adjustable quota value controls how many packets are being moved through the pipeline per enqueue and dequeue. Adjustable watermark values associated with the rings control a back-off mechanism that tries to prevent the pipeline from being overloaded by: * Stopping enqueuing on rings for which the usage has crossed the high watermark threshold * Sending Ethernet pause frames * Only resuming enqueuing on a ring once its usage goes below a global low watermark threshold This mechanism allows congestion notifications to go up the ring pipeline and eventually lead to an Ethernet flow control frame being send to the source. On top of serving as an example of quota and watermark usage, this application can be used to benchmark ring based processing pipelines performance using a traffic- generator, as shown in :numref:`figure_ring_pipeline_perf_setup`. .. _figure_ring_pipeline_perf_setup: .. figure:: img/ring_pipeline_perf_setup.* Ring-based Processing Pipeline Performance Setup Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/quota_watermark #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- The core application, qw, has to be started first. Once it is up and running, one can alter quota and watermarks while it runs using the control application, qwctl. Running the Core Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The application requires a single command line option: .. code-block:: console ./qw/build/qw [EAL options] -- -p PORTMASK where, -p PORTMASK: A hexadecimal bitmask of the ports to configure To run the application in a linuxapp environment with four logical cores and ports 0 and 2, issue the following command: .. code-block:: console ./qw/build/qw -c f -n 4 -- -p 5 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Running the Control Application ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The control application requires a number of command line options: .. code-block:: console ./qwctl/build/qwctl [EAL options] --proc-type=secondary The --proc-type=secondary option is necessary for the EAL to properly initialize the control application to use the same huge pages as the core application and thus be able to access its rings. To run the application in a linuxapp environment on logical core 0, issue the following command: .. code-block:: console ./qwctl/build/qwctl -c 1 -n 4 --proc-type=secondary Refer to the *DPDK Getting Started* Guide for general information on running applications and the Environment Abstraction Layer (EAL) options. qwctl is an interactive command line that let the user change variables in a running instance of qw. The help command gives a list of available commands: .. code-block:: console $ qwctl > help Code Overview ------------- The following sections provide a quick guide to the application's source code. Core Application - qw ~~~~~~~~~~~~~~~~~~~~~ EAL and Drivers Setup ^^^^^^^^^^^^^^^^^^^^^ The EAL arguments are parsed at the beginning of the main() function: .. code-block:: c ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); argc -= ret; argv += ret; Then, a call to init_dpdk(), defined in init.c, is made to initialize the poll mode drivers: .. code-block:: c void init_dpdk(void) { int ret; /* Bind the drivers to usable devices */ ret = rte_eal_pci_probe(); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eal_pci_probe(): error %d\n", ret); if (rte_eth_dev_count() < 2) rte_exit(EXIT_FAILURE, "Not enough Ethernet port available\n"); } To fully understand this code, it is recommended to study the chapters that relate to the *Poll Mode Driver* in the *DPDK Getting Started Guide* and the *DPDK API Reference*. Shared Variables Setup ^^^^^^^^^^^^^^^^^^^^^^ The quota and low_watermark shared variables are put into an rte_memzone using a call to setup_shared_variables(): .. code-block:: c void setup_shared_variables(void) { const struct rte_memzone *qw_memzone; qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, 2 * sizeof(int), rte_socket_id(), RTE_MEMZONE_2MB); if (qw_memzone == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); quota = qw_memzone->addr; low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); } These two variables are initialized to a default value in main() and can be changed while qw is running using the qwctl control program. Application Arguments ^^^^^^^^^^^^^^^^^^^^^ The qw application only takes one argument: a port mask that specifies which ports should be used by the application. At least two ports are needed to run the application and there should be an even number of ports given in the port mask. The port mask parsing is done in parse_qw_args(), defined in args.c. Mbuf Pool Initialization ^^^^^^^^^^^^^^^^^^^^^^^^ Once the application's arguments are parsed, an mbuf pool is created. It contains a set of mbuf objects that are used by the driver and the application to store network packets: .. code-block:: c /* Create a pool of mbuf to store packets */ mbuf_pool = rte_mempool_create("mbuf_pool", MBUF_PER_POOL, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); if (mbuf_pool == NULL) rte_panic("%s\n", rte_strerror(rte_errno)); The rte_mempool is a generic structure used to handle pools of objects. In this case, it is necessary to create a pool that will be used by the driver, which expects to have some reserved space in the mempool structure, sizeof(struct rte_pktmbuf_pool_private) bytes. The number of allocated pkt mbufs is MBUF_PER_POOL, with a size of MBUF_SIZE each. A per-lcore cache of 32 mbufs is kept. The memory is allocated in on the master lcore's socket, but it is possible to extend this code to allocate one mbuf pool per socket. Two callback pointers are also given to the rte_mempool_create() function: * The first callback pointer is to rte_pktmbuf_pool_init() and is used to initialize the private data of the mempool, which is needed by the driver. This function is provided by the mbuf API, but can be copied and extended by the developer. * The second callback pointer given to rte_mempool_create() is the mbuf initializer. The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. If a more complex application wants to extend the rte_pktmbuf structure for its own needs, a new function derived from rte_pktmbuf_init() can be created. Ports Configuration and Pairing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each port in the port mask is configured and a corresponding ring is created in the master lcore's array of rings. This ring is the first in the pipeline and will hold the packets directly coming from the port. .. code-block:: c for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) if (is_bit_set(port_id, portmask)) { configure_eth_port(port_id); init_ring(master_lcore_id, port_id); } pair_ports(); The configure_eth_port() and init_ring() functions are used to configure a port and a ring respectively and are defined in init.c. They make use of the DPDK APIs defined in rte_eth.h and rte_ring.h. pair_ports() builds the port_pairs[] array so that its key-value pairs are a mapping between reception and transmission ports. It is defined in init.c. Logical Cores Assignment ^^^^^^^^^^^^^^^^^^^^^^^^ The application uses the master logical core to poll all the ports for new packets and enqueue them on a ring associated with the port. Each logical core except the last runs pipeline_stage() after a ring for each used port is initialized on that core. pipeline_stage() on core X dequeues packets from core X-1's rings and enqueue them on its own rings. See :numref:`figure_threads_pipelines`. .. code-block:: c /* Start pipeline_stage() on all the available slave lcore but the last */ for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) { for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) if (is_bit_set(port_id, portmask)) init_ring(lcore_id, port_id); rte_eal_remote_launch(pipeline_stage, NULL, lcore_id); } } The last available logical core runs send_stage(), which is the last stage of the pipeline dequeuing packets from the last ring in the pipeline and sending them out on the destination port setup by pair_ports(). .. code-block:: c /* Start send_stage() on the last slave core */ rte_eal_remote_launch(send_stage, NULL, last_lcore_id); Receive, Process and Transmit Packets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. _figure_threads_pipelines: .. figure:: img/threads_pipelines.* Threads and Pipelines In the receive_stage() function running on the master logical core, the main task is to read ingress packets from the RX ports and enqueue them on the port's corresponding first ring in the pipeline. This is done using the following code: .. code-block:: c lcore_id = rte_lcore_id(); /* Process each port round robin style */ for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; ring = rings[lcore_id][port_id]; if (ring_state[port_id] != RING_READY) { if (rte_ring_count(ring) > *low_watermark) continue; else ring_state[port_id] = RING_READY; } /* Enqueue received packets on the RX ring */ nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, *quota); ret = rte_ring_enqueue_bulk(ring, (void *) pkts, nb_rx_pkts); if (ret == -EDQUOT) { ring_state[port_id] = RING_OVERLOADED; send_pause_frame(port_id, 1337); } } For each port in the port mask, the corresponding ring's pointer is fetched into ring and that ring's state is checked: * If it is in the RING_READY state, \*quota packets are grabbed from the port and put on the ring. Should this operation make the ring's usage cross its high watermark, the ring is marked as overloaded and an Ethernet flow control frame is sent to the source. * If it is not in the RING_READY state, this port is ignored until the ring's usage crosses the \*low_watermark value. The pipeline_stage() function's task is to process and move packets from the preceding pipeline stage. This thread is running on most of the logical cores to create and arbitrarily long pipeline. .. code-block:: c lcore_id = rte_lcore_id(); previous_lcore_id = get_previous_lcore_id(lcore_id); for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; tx = rings[lcore_id][port_id]; rx = rings[previous_lcore_id][port_id]; if (ring_state[port_id] != RING_READY) { if (rte_ring_count(tx) > *low_watermark) continue; else ring_state[port_id] = RING_READY; } /* Dequeue up to quota mbuf from rx */ nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, *quota); if (unlikely(nb_dq_pkts < 0)) continue; /* Enqueue them on tx */ ret = rte_ring_enqueue_bulk(tx, pkts, nb_dq_pkts); if (ret == -EDQUOT) ring_state[port_id] = RING_OVERLOADED; } The thread's logic works mostly like receive_stage(), except that packets are moved from ring to ring instead of port to ring. In this example, no actual processing is done on the packets, but pipeline_stage() is an ideal place to perform any processing required by the application. Finally, the send_stage() function's task is to read packets from the last ring in a pipeline and send them on the destination port defined in the port_pairs[] array. It is running on the last available logical core only. .. code-block:: c lcore_id = rte_lcore_id(); previous_lcore_id = get_previous_lcore_id(lcore_id); for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; dest_port_id = port_pairs[port_id]; tx = rings[previous_lcore_id][port_id]; if (rte_ring_empty(tx)) continue; /* Dequeue packets from tx and send them */ nb_dq_pkts = rte_ring_dequeue_burst(tx, (void *) tx_pkts, *quota); nb_tx_pkts = rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts); } For each port in the port mask, up to \*quota packets are pulled from the last ring in its pipeline and sent on the destination port paired with the current port. Control Application - qwctl ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The qwctl application uses the rte_cmdline library to provide the user with an interactive command line that can be used to modify and inspect parameters in a running qw application. Those parameters are the global quota and low_watermark value as well as each ring's built-in high watermark. Command Definitions ^^^^^^^^^^^^^^^^^^^ The available commands are defined in commands.c. It is advised to use the cmdline sample application user guide as a reference for everything related to the rte_cmdline library. Accessing Shared Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^ The setup_shared_variables() function retrieves the shared variables quota and low_watermark from the rte_memzone previously created by qw. .. code-block:: c static void setup_shared_variables(void) { const struct rte_memzone *qw_memzone; qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME); if (qw_memzone == NULL) rte_exit(EXIT_FAILURE, "Couldn't find memzone\n"); quota = qw_memzone->addr; low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); } ================================================ FILE: doc/guides/sample_app_ug/rxtx_callbacks.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. RX/TX Callbacks Sample Application ================================== The RX/TX Callbacks sample application is a packet forwarding application that demonstrates the use of user defined callbacks on received and transmitted packets. The application performs a simple latency check, using callbacks, to determine the time packets spend within the application. In the sample application a user defined callback is applied to all received packets to add a timestamp. A separate callback is applied to all packets prior to transmission to calculate the elapsed time, in CPU cycles. Compiling the Application ------------------------- To compile the application export the path to the DPDK source tree and go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/rxtx_callbacks Set the target, for example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values. The callbacks feature requires that the ``CONFIG_RTE_ETHDEV_RXTX_CALLBACKS`` setting is on in the ``config/common_`` config file that applies to the target. This is generally on by default: .. code-block:: console CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y Build the application as follows: .. code-block:: console make Running the Application ----------------------- To run the example in a ``linuxapp`` environment: .. code-block:: console ./build/rxtx_callbacks -c 2 -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The ``rxtx_callbacks`` application is mainly a simple forwarding application based on the :doc:`skeleton`. See that section of the documentation for more details of the forwarding part of the application. The sections below explain the additional RX/TX callback code. The Main Function ~~~~~~~~~~~~~~~~~ The ``main()`` function performs the application initialization and calls the execution threads for each lcore. This function is effectively identical to the ``main()`` function explained in :doc:`skeleton`. The ``lcore_main()`` function is also identical. The main difference is in the user defined ``port_init()`` function where the callbacks are added. This is explained in the next section: The Port Initialization Function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main functional part of the port initialization is shown below with comments: .. code-block:: c static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf = port_conf_default; const uint16_t rx_rings = 1, tx_rings = 1; struct ether_addr addr; int retval; uint16_t q; if (port >= rte_eth_dev_count()) return -1; /* Configure the Ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; /* Allocate and set up 1 RX queue per Ethernet port. */ for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } /* Start the Ethernet port. */ retval = rte_eth_dev_start(port); if (retval < 0) return retval; /* Enable RX in promiscuous mode for the Ethernet device. */ rte_eth_promiscuous_enable(port); /* Add the callbacks for RX and TX.*/ rte_eth_add_rx_callback(port, 0, add_timestamps, NULL); rte_eth_add_tx_callback(port, 0, calc_latency, NULL); return 0; } The RX and TX callbacks are added to the ports/queues as function pointers: .. code-block:: c rte_eth_add_rx_callback(port, 0, add_timestamps, NULL); rte_eth_add_tx_callback(port, 0, calc_latency, NULL); More than one callback can be added and additional information can be passed to callback function pointers as a ``void*``. In the examples above ``NULL`` is used. The ``add_timestamps()`` and ``calc_latency()`` functions are explained below. The add_timestamps() Callback ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``add_timestamps()`` callback is added to the RX port and is applied to all packets received: .. code-block:: c static uint16_t add_timestamps(uint8_t port __rte_unused, uint16_t qidx __rte_unused, struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused) { unsigned i; uint64_t now = rte_rdtsc(); for (i = 0; i < nb_pkts; i++) pkts[i]->udata64 = now; return nb_pkts; } The DPDK function ``rte_rdtsc()`` is used to add a cycle count timestamp to each packet (see the *cycles* section of the *DPDK API Documentation* for details). The calc_latency() Callback ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``calc_latency()`` callback is added to the TX port and is applied to all packets prior to transmission: .. code-block:: c static uint16_t calc_latency(uint8_t port __rte_unused, uint16_t qidx __rte_unused, struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused) { uint64_t cycles = 0; uint64_t now = rte_rdtsc(); unsigned i; for (i = 0; i < nb_pkts; i++) cycles += now - pkts[i]->udata64; latency_numbers.total_cycles += cycles; latency_numbers.total_pkts += nb_pkts; if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) { printf("Latency = %"PRIu64" cycles\n", latency_numbers.total_cycles / latency_numbers.total_pkts); latency_numbers.total_cycles = latency_numbers.total_pkts = 0; } return nb_pkts; } The ``calc_latency()`` function accumulates the total number of packets and the total number of cycles used. Once more than 100 million packets have been transmitted the average cycle count per packet is printed out and the counters are reset. ================================================ FILE: doc/guides/sample_app_ug/skeleton.rst ================================================ .. BSD LICENSE Copyright(c) 2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Basic Forwarding Sample Application =================================== The Basic Forwarding sample application is a simple *skeleton* example of a forwarding application. It is intended as a demonstration of the basic components of a DPDK forwarding application. For more detailed implementations see the L2 and L3 forwarding sample applications. Compiling the Application ------------------------- To compile the application export the path to the DPDK source tree and go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/skeleton Set the target, for example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values. Build the application as follows: .. code-block:: console make Running the Application ----------------------- To run the example in a ``linuxapp`` environment: .. code-block:: console ./build/basicfwd -c 2 -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide an explanation of the main components of the code. All DPDK library functions used in the sample code are prefixed with ``rte_`` and are explained in detail in the *DPDK API Documentation*. The Main Function ~~~~~~~~~~~~~~~~~ The ``main()`` function performs the initialization and calls the execution threads for each lcore. The first task is to initialize the Environment Abstraction Layer (EAL). The ``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()`` function. The value returned is the number of parsed arguments: .. code-block:: c int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); The ``main()`` also allocates a mempool to hold the mbufs (Message Buffers) used by the application: .. code-block:: c mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_SIZE, MBUF_CACHE_SIZE, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); Mbufs are the packet buffer structure used by DPDK. They are explained in detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*. The ``main()`` function also initializes all the ports using the user defined ``port_init()`` function which is explained in the next section: .. code-block:: c for (portid = 0; portid < nb_ports; portid++) { if (port_init(portid, mbuf_pool) != 0) { rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu8 "\n", portid); } } Once the initialization is complete, the application is ready to launch a function on an lcore. In this example ``lcore_main()`` is called on a single lcore. .. code-block:: c lcore_main(); The ``lcore_main()`` function is explained below. The Port Initialization Function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The main functional part of the port initialization used in the Basic Forwarding application is shown below: .. code-block:: c static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf = port_conf_default; const uint16_t rx_rings = 1, tx_rings = 1; struct ether_addr addr; int retval; uint16_t q; if (port >= rte_eth_dev_count()) return -1; /* Configure the Ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; /* Allocate and set up 1 RX queue per Ethernet port. */ for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } /* Start the Ethernet port. */ retval = rte_eth_dev_start(port); if (retval < 0) return retval; /* Enable RX in promiscuous mode for the Ethernet device. */ rte_eth_promiscuous_enable(port); return 0; } The Ethernet ports are configured with default settings using the ``rte_eth_dev_configure()`` function and the ``port_conf_default`` struct: .. code-block:: c static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN } }; For this example the ports are set up with 1 RX and 1 TX queue using the ``rte_eth_rx_queue_setup()`` and ``rte_eth_tx_queue_setup()`` functions. The Ethernet port is then started: .. code-block:: c retval = rte_eth_dev_start(port); Finally the RX port is set in promiscuous mode: .. code-block:: c rte_eth_promiscuous_enable(port); The Lcores Main ~~~~~~~~~~~~~~~ As we saw above the ``main()`` function calls an application function on the available lcores. For the Basic Forwarding application the lcore function looks like the following: .. code-block:: c static __attribute__((noreturn)) void lcore_main(void) { const uint8_t nb_ports = rte_eth_dev_count(); uint8_t port; /* * Check that the port is on the same NUMA node as the polling thread * for best performance. */ for (port = 0; port < nb_ports; port++) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) printf("WARNING, port %u is on remote NUMA node to " "polling thread.\n\tPerformance will " "not be optimal.\n", port); printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id()); /* Run until the application is quit or killed. */ for (;;) { /* * Receive packets on a port and forward them on the paired * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ for (port = 0; port < nb_ports; port++) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx == 0)) continue; /* Send burst of TX packets, to second port of pair. */ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); /* Free any unsent packets. */ if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf = nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } } } The main work of the application is done within the loop: .. code-block:: c for (;;) { for (port = 0; port < nb_ports; port++) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx == 0)) continue; /* Send burst of TX packets, to second port of pair. */ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); /* Free any unsent packets. */ if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf = nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } } Packets are received in bursts on the RX ports and transmitted in bursts on the TX ports. The ports are grouped in pairs with a simple mapping scheme using the an XOR on the port number:: 0 -> 1 1 -> 0 2 -> 3 3 -> 2 etc. The ``rte_eth_tx_burst()`` function frees the memory buffers of packets that are transmitted. If packets fail to transmit, ``(nb_tx < nb_rx)``, then they must be freed explicitly using ``rte_pktmbuf_free()``. The forwarding loop can be interrupted and the application closed using ``Ctrl-C``. ================================================ FILE: doc/guides/sample_app_ug/tep_termination.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. TEP termination Sample Application ================================== The TEP (Tunnel End point) termination sample application simulates a VXLAN Tunnel Endpoint (VTEP) termination in DPDK, which is used to demonstrate the offload and filtering capabilities of Intel® XL710 10/40 Gigabit Ethernet Controller for VXLAN packet. This sample uses the basic virtio devices management mechanism from vhost example, and also uses the us-vHost interface and tunnel filtering mechanism to direct a specified traffic to a specific VM. In addition, this sample is also designed to show how tunneling protocols can be handled. Background ---------- With virtualization, overlay networks allow a network structure to be built or imposed across physical nodes which is abstracted away from the actual underlining physical network connections. This allows network isolation, QOS, etc to be provided on a per client basis. .. _figure_overlay_networking: .. figure:: img/overlay_networking.* Overlay Networking. In a typical setup, the network overlay tunnel is terminated at the Virtual/Tunnel End Point (VEP/TEP). The TEP is normally located at the physical host level ideally in the software switch. Due to processing constraints and the inevitable bottleneck that the switch becomes the ability to offload overlay support features becomes an important requirement. Intel® XL710 10/40 G Ethernet network card provides hardware filtering and offload capabilities to support overlay networks implementations such as MAC in UDP and MAC in GRE. Sample Code Overview -------------------- The DPDK TEP termination sample code demonstrates the offload and filtering capabilities of Intel® XL710 10/40 Gigabit Ethernet Controller for VXLAN packet. The sample code is based on vhost library. The vhost library is developed for user space Ethernet switch to easily integrate with vhost functionality. The sample will support the followings: * Tunneling packet recognition. * The port of UDP tunneling is configurable * Directing incoming traffic to the correct queue based on the tunnel filter type. The supported filter type are listed below. * Inner MAC and VLAN and tenant ID * Inner MAC and tenant ID, and Outer MAC * Inner MAC and tenant ID The tenant ID will be assigned from a static internal table based on the us-vhost device ID. Each device will receive a unique device ID. The inner MAC will be learned by the first packet transmitted from a device. * Decapsulation of RX VXLAN traffic. This is a software only operation. * Encapsulation of TX VXLAN traffic. This is a software only operation. * Inner IP and inner L4 checksum offload. * TSO offload support for tunneling packet. The following figure shows the framework of the TEP termination sample application based on vhost-cuse. .. _figure_tep_termination_arch: .. figure:: img/tep_termination_arch.* TEP termination Framework Overview Supported Distributions ----------------------- The example in this section have been validated with the following distributions: * Fedora* 18 * Fedora* 19 * Fedora* 20 Prerequisites ------------- Refer to the guide in section 27.4 in the vhost sample. Compiling the Sample Code ------------------------- #. Compile vhost lib: To enable vhost, turn on vhost library in the configure file config/common_linuxapp. .. code-block:: console CONFIG_RTE_LIBRTE_VHOST=n vhost user is turned on by default in the configure file config/common_linuxapp. To enable vhost cuse, disable vhost user. .. code-block:: console CONFIG_RTE_LIBRTE_VHOST_USER=y After vhost is enabled and the implementation is selected, build the vhost library. #. Go to the examples directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/tep_termination #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the DPDK Getting Started Guide for possible RTE_TARGET values. #. Build the application: .. code-block:: console cd ${RTE_SDK} make config ${RTE_TARGET} make install ${RTE_TARGET} cd ${RTE_SDK}/examples/tep_termination make #. Go to the eventfd_link directory(vhost cuse required): .. code-block:: console cd ${RTE_SDK}/lib/librte_vhost/eventfd_link #. Build the eventfd_link kernel module(vhost cuse required): .. code-block:: console make Running the Sample Code ----------------------- #. Install the cuse kernel module(vhost cuse required): .. code-block:: console modprobe cuse #. Go to the eventfd_link directory(vhost cuse required): .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/lib/librte_vhost/eventfd_link #. Install the eventfd_link module(vhost cuse required): .. code-block:: console insmod ./eventfd_link.ko #. Go to the examples directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/tep_termination #. Run the tep_termination sample code: .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- -p 0x1 --dev-basename tep-termination --nb-devices 4 --udp-port 4789 --filter-type 1 .. note:: Please note the huge-dir parameter instructs the DPDK to allocate its memory from the 2 MB page hugetlbfs. Parameters ~~~~~~~~~~ **The same parameters with the vhost sample.** Refer to the guide in section 27.6.1 in the vhost sample for the meanings of 'Basename', 'Stats', 'RX Retry', 'RX Retry Number' and 'RX Retry Delay Time'. **Number of Devices.** The nb-devices option specifies the number of virtIO device. The default value is 2. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 2 **Tunneling UDP port.** The udp-port option is used to specify the destination UDP number for UDP tunneling packet. The default value is 4789. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --udp-port 4789 **Filter Type.** The filter-type option is used to specify which filter type is used to filter UDP tunneling packet to a specified queue. The default value is 1, which means the filter type of inner MAC and tenant ID is used. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --udp-port 4789 --filter-type 1 **TX Checksum.** The tx-checksum option is used to enable or disable the inner header checksum offload. The default value is 0, which means the checksum offload is disabled. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --tx-checksum **TCP segment sise.** The tso-segsz option specifies the TCP segment size for TSO offload for tunneling packet. The default value is 0, which means TSO offload is disabled. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --tx-checksum --tso-segsz 800 **Decapsulation option.** The decap option is used to enable or disable decapsulation operation for received VXLAN packet. The default value is 1. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 4 --udp-port 4789 --decap 1 **Encapsulation option.** The encap option is used to enable or disable encapsulation operation for transmitted packet. The default value is 1. .. code-block:: console user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- --nb-devices 4 --udp-port 4789 --encap 1 Running the Virtual Machine (QEMU) ---------------------------------- Refer to the guide in section 27.7 in the vhost sample. Running DPDK in the Virtual Machine ----------------------------------- Refer to the guide in section 27.8 in the vHost sample. Passing Traffic to the Virtual Machine Device --------------------------------------------- For a virtio-net device to receive traffic, the traffic's Layer 2 header must include both the virtio-net device's MAC address. The DPDK sample code behaves in a similar manner to a learning switch in that it learns the MAC address of the virtio-net devices from the first transmitted packet. On learning the MAC address, the DPDK vhost sample code prints a message with the MAC address and tenant ID virtio-net device. For example: .. code-block:: console DATA: (0) MAC_ADDRESS cc:bb:bb:bb:bb:bb and VNI 1000 registered The above message indicates that device 0 has been registered with MAC address cc:bb:bb:bb:bb:bb and VNI 1000. Any packets received on the NIC with these values are placed on the devices receive queue. ================================================ FILE: doc/guides/sample_app_ug/test_pipeline.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Test Pipeline Application ========================= The Test Pipeline application illustrates the use of the DPDK Packet Framework tool suite. Its purpose is to demonstrate the performance of single-table DPDK pipelines. Overview -------- The application uses three CPU cores: * Core A ("RX core") receives traffic from the NIC ports and feeds core B with traffic through SW queues. * Core B ("Pipeline core") implements a single-table DPDK pipeline whose type is selectable through specific command line parameter. Core B receives traffic from core A through software queues, processes it according to the actions configured in the table entries that are hit by the input packets and feeds it to core C through another set of software queues. * Core C ("TX core") receives traffic from core B through software queues and sends it to the NIC ports for transmission. .. _figure_test_pipeline_app: .. figure:: img/test_pipeline_app.* Test Pipeline Application Compiling the Application ------------------------- #. Go to the app/test directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/app/test/test-pipeline #. Set the target (a default target is used if not specified): .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application: .. code-block:: console make Running the Application ----------------------- Application Command Line ~~~~~~~~~~~~~~~~~~~~~~~~ The application execution command line is: .. code-block:: console ./test-pipeline [EAL options] -- -p PORTMASK --TABLE_TYPE The -c EAL CPU core mask option has to contain exactly 3 CPU cores. The first CPU core in the core mask is assigned for core A, the second for core B and the third for core C. The PORTMASK parameter must contain 2 or 4 ports. Table Types and Behavior ~~~~~~~~~~~~~~~~~~~~~~~~ :numref:`table_test_pipeline_1` describes the table types used and how they are populated. The hash tables are pre-populated with 16 million keys. For hash tables, the following parameters can be selected: * **Configurable key size implementation or fixed (specialized) key size implementation (e.g. hash-8-ext or hash-spec-8-ext).** The key size specialized implementations are expected to provide better performance for 8-byte and 16-byte key sizes, while the key-size-non-specialized implementation is expected to provide better performance for larger key sizes; * **Key size (e.g. hash-spec-8-ext or hash-spec-16-ext).** The available options are 8, 16 and 32 bytes; * **Table type (e.g. hash-spec-16-ext or hash-spec-16-lru).** The available options are ext (extendable bucket) or lru (least recently used). .. _table_test_pipeline_1: .. table:: Table Types +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | **#** | **TABLE_TYPE** | **Description of Core B Table** | **Pre-added Table Entries** | | | | | | +=======+========================+==========================================================+=======================================================+ | 1 | none | Core B is not implementing a DPDK pipeline. | N/A | | | | Core B is implementing a pass-through from its input set | | | | | of software queues to its output set of software queues. | | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 2 | stub | Stub table. Core B is implementing the same pass-through | N/A | | | | functionality as described for the "none" option by | | | | | using the DPDK Packet Framework by using one | | | | | stub table for each input NIC port. | | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 3 | hash-[spec]-8-lru | LRU hash table with 8-byte key size and 16 million | 16 million entries are successfully added to the | | | | entries. | hash table with the following key format: | | | | | | | | | | [4-byte index, 4 bytes of 0] | | | | | | | | | | The action configured for all table entries is | | | | | "Sendto output port", with the output port index | | | | | uniformly distributed for the range of output ports. | | | | | | | | | | The default table rule (used in the case of a lookup | | | | | miss) is to drop the packet. | | | | | | | | | | At run time, core A is creating the following lookup | | | | | key and storing it into the packet meta data for | | | | | core B to use for table lookup: | | | | | | | | | | [destination IPv4 address, 4 bytes of 0] | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 4 | hash-[spec]-8-ext | Extendible bucket hash table with 8-byte key size | Same as hash-[spec]-8-lru table entries, above. | | | | and 16 million entries. | | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 5 | hash-[spec]-16-lru | LRU hash table with 16-byte key size and 16 million | 16 million entries are successfully added to the hash | | | | entries. | table with the following key format: | | | | | | | | | | [4-byte index, 12 bytes of 0] | | | | | | | | | | The action configured for all table entries is | | | | | "Send to output port", with the output port index | | | | | uniformly distributed for the range of output ports. | | | | | | | | | | The default table rule (used in the case of a lookup | | | | | miss) is to drop the packet. | | | | | | | | | | At run time, core A is creating the following lookup | | | | | key and storing it into the packet meta data for core | | | | | B to use for table lookup: | | | | | | | | | | [destination IPv4 address, 12 bytes of 0] | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 6 | hash-[spec]-16-ext | Extendible bucket hash table with 16-byte key size | Same as hash-[spec]-16-lru table entries, above. | | | | and 16 million entries. | | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 7 | hash-[spec]-32-lru | LRU hash table with 32-byte key size and 16 million | 16 million entries are successfully added to the hash | | | | entries. | table with the following key format: | | | | | | | | | | [4-byte index, 28 bytes of 0]. | | | | | | | | | | The action configured for all table entries is | | | | | "Send to output port", with the output port index | | | | | uniformly distributed for the range of output ports. | | | | | | | | | | The default table rule (used in the case of a lookup | | | | | miss) is to drop the packet. | | | | | | | | | | At run time, core A is creating the following lookup | | | | | key and storing it into the packet meta data for | | | | | Lpmcore B to use for table lookup: | | | | | | | | | | [destination IPv4 address, 28 bytes of 0] | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 8 | hash-[spec]-32-ext | Extendible bucket hash table with 32-byte key size | Same as hash-[spec]-32-lru table entries, above. | | | | and 16 million entries. | | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 9 | lpm | Longest Prefix Match (LPM) IPv4 table. | In the case of two ports, two routes | | | | | are added to the table: | | | | | | | | | | [0.0.0.0/9 => send to output port 0] | | | | | | | | | | [0.128.0.0/9 => send to output port 1] | | | | | | | | | | In case of four ports, four entries are added to the | | | | | table: | | | | | | | | | | [0.0.0.0/10 => send to output port 0] | | | | | | | | | | [0.64.0.0/10 => send to output port 1] | | | | | | | | | | [0.128.0.0/10 => send to output port 2] | | | | | | | | | | [0.192.0.0/10 => send to output port 3] | | | | | | | | | | The default table rule (used in the case of a lookup | | | | | miss) is to drop the packet. | | | | | | | | | | At run time, core A is storing the IPv4 destination | | | | | within the packet meta data to be later used by core | | | | | B as the lookup key. | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ | 10 | acl | Access Control List (ACL) table | In the case of two ports, two ACL rules are added to | | | | | the table: | | | | | | | | | | [priority = 0 (highest), | | | | | | | | | | IPv4 source = ANY, | | | | | | | | | | IPv4 destination = 0.0.0.0/9, | | | | | | | | | | L4 protocol = ANY, | | | | | | | | | | TCP source port = ANY, | | | | | | | | | | TCP destination port = ANY | | | | | | | | | | => send to output port 0] | | | | | | | | | | | | | | | [priority = 0 (highest), | | | | | | | | | | IPv4 source = ANY, | | | | | | | | | | IPv4 destination = 0.128.0.0/9, | | | | | | | | | | L4 protocol = ANY, | | | | | | | | | | TCP source port = ANY, | | | | | | | | | | TCP destination port = ANY | | | | | | | | | | => send to output port 0]. | | | | | | | | | | | | | | | The default table rule (used in the case of a lookup | | | | | miss) is to drop the packet. | | | | | | +-------+------------------------+----------------------------------------------------------+-------------------------------------------------------+ Input Traffic ~~~~~~~~~~~~~ Regardless of the table type used for the core B pipeline, the same input traffic can be used to hit all table entries with uniform distribution, which results in uniform distribution of packets sent out on the set of output NIC ports. The profile for input traffic is TCP/IPv4 packets with: * destination IP address as A.B.C.D with A fixed to 0 and B, C,D random * source IP address fixed to 0.0.0.0 * destination TCP port fixed to 0 * source TCP port fixed to 0 ================================================ FILE: doc/guides/sample_app_ug/timer.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Timer Sample Application ======================== The Timer sample application is a simple application that demonstrates the use of a timer in a DPDK application. This application prints some messages from different lcores regularly, demonstrating the use of timers. Compiling the Application ------------------------- #. Go to the example directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/timer #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible *RTE_TARGET* values. #. Build the application: .. code-block:: console make Running the Application ----------------------- To run the example in linuxapp environment: .. code-block:: console $ ./build/timer -c f -n 4 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. Initialization and Main Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In addition to EAL initialization, the timer subsystem must be initialized, by calling the rte_timer_subsystem_init() function. .. code-block:: c /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); /* init RTE timer library */ rte_timer_subsystem_init(); After timer creation (see the next paragraph), the main loop is executed on each slave lcore using the well-known rte_eal_remote_launch() and also on the master. .. code-block:: c /* call lcore_mainloop() on every slave lcore */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id); } /* call it on master lcore too */ (void) lcore_mainloop(NULL); The main loop is very simple in this example: .. code-block:: c while (1) { /* * Call the timer handler on each core: as we don't * need a very precise timer, so only call * rte_timer_manage() every ~10ms (at 2 GHz). In a real * application, this will enhance performances as * reading the HPET timer is not efficient. */ cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; if (diff_tsc > TIMER_RESOLUTION_CYCLES) { rte_timer_manage(); prev_tsc = cur_tsc; } } As explained in the comment, it is better to use the TSC register (as it is a per-lcore register) to check if the rte_timer_manage() function must be called or not. In this example, the resolution of the timer is 10 milliseconds. Managing Timers ~~~~~~~~~~~~~~~ In the main() function, the two timers are initialized. This call to rte_timer_init() is necessary before doing any other operation on the timer structure. .. code-block:: c /* init timer structures */ rte_timer_init(&timer0); rte_timer_init(&timer1); Then, the two timers are configured: * The first timer (timer0) is loaded on the master lcore and expires every second. Since the PERIODICAL flag is provided, the timer is reloaded automatically by the timer subsystem. The callback function is timer0_cb(). * The second timer (timer1) is loaded on the next available lcore every 333 ms. The SINGLE flag means that the timer expires only once and must be reloaded manually if required. The callback function is timer1_cb(). .. code-block:: c /* load timer0, every second, on master lcore, reloaded automatically */ hz = rte_get_hpet_hz(); lcore_id = rte_lcore_id(); rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL); /* load timer1, every second/3, on next lcore, reloaded manually */ lcore_id = rte_get_next_lcore(lcore_id, 0, 1); rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL); The callback for the first timer (timer0) only displays a message until a global counter reaches 20 (after 20 seconds). In this case, the timer is stopped using the rte_timer_stop() function. .. code-block:: c /* timer0 callback */ static void timer0_cb( attribute ((unused)) struct rte_timer *tim, __attribute ((unused)) void *arg) { static unsigned counter = 0; unsigned lcore_id = rte_lcore_id(); printf("%s() on lcore %u\n", FUNCTION , lcore_id); /* this timer is automatically reloaded until we decide to stop it, when counter reaches 20. */ if ((counter ++) == 20) rte_timer_stop(tim); } The callback for the second timer (timer1) displays a message and reloads the timer on the next lcore, using the rte_timer_reset() function: .. code-block:: c /* timer1 callback */ static void timer1_cb( attribute ((unused)) struct rte_timer *tim, _attribute ((unused)) void *arg) { unsigned lcore_id = rte_lcore_id(); uint64_t hz; printf("%s() on lcore %u\\n", FUNCTION , lcore_id); /* reload it on another lcore */ hz = rte_get_hpet_hz(); lcore_id = rte_get_next_lcore(lcore_id, 0, 1); rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL); } ================================================ FILE: doc/guides/sample_app_ug/vhost.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Vhost Sample Application ======================== The vhost sample application demonstrates integration of the Data Plane Development Kit (DPDK) with the Linux* KVM hypervisor by implementing the vhost-net offload API. The sample application performs simple packet switching between virtual machines based on Media Access Control (MAC) address or Virtual Local Area Network (VLAN) tag. The splitting of Ethernet traffic from an external switch is performed in hardware by the Virtual Machine Device Queues (VMDQ) and Data Center Bridging (DCB) features of the Intel® 82599 10 Gigabit Ethernet Controller. Background ---------- Virtio networking (virtio-net) was developed as the Linux* KVM para-virtualized method for communicating network packets between host and guest. It was found that virtio-net performance was poor due to context switching and packet copying between host, guest, and QEMU. The following figure shows the system architecture for a virtio-based networking (virtio-net). .. _figure_qemu_virtio_net: .. figure:: img/qemu_virtio_net.* System Architecture for Virtio-based Networking (virtio-net). The Linux* Kernel vhost-net module was developed as an offload mechanism for virtio-net. The vhost-net module enables KVM (QEMU) to offload the servicing of virtio-net devices to the vhost-net kernel module, reducing the context switching and packet copies in the virtual dataplane. This is achieved by QEMU sharing the following information with the vhost-net module through the vhost-net API: * The layout of the guest memory space, to enable the vhost-net module to translate addresses. * The locations of virtual queues in QEMU virtual address space, to enable the vhost module to read/write directly to and from the virtqueues. * An event file descriptor (eventfd) configured in KVM to send interrupts to the virtio- net device driver in the guest. This enables the vhost-net module to notify (call) the guest. * An eventfd configured in KVM to be triggered on writes to the virtio-net device's Peripheral Component Interconnect (PCI) config space. This enables the vhost-net module to receive notifications (kicks) from the guest. The following figure shows the system architecture for virtio-net networking with vhost-net offload. .. _figure_virtio_linux_vhost: .. figure:: img/virtio_linux_vhost.* Virtio with Linux Sample Code Overview -------------------- The DPDK vhost-net sample code demonstrates KVM (QEMU) offloading the servicing of a Virtual Machine's (VM's) virtio-net devices to a DPDK-based application in place of the kernel's vhost-net module. The DPDK vhost-net sample code is based on vhost library. Vhost library is developed for user space Ethernet switch to easily integrate with vhost functionality. The vhost library implements the following features: * Management of virtio-net device creation/destruction events. * Mapping of the VM's physical memory into the DPDK vhost-net's address space. * Triggering/receiving notifications to/from VMs via eventfds. * A virtio-net back-end implementation providing a subset of virtio-net features. There are two vhost implementations in vhost library, vhost cuse and vhost user. In vhost cuse, a character device driver is implemented to receive and process vhost requests through ioctl messages. In vhost user, a socket server is created to received vhost requests through socket messages. Most of the messages share the same handler routine. .. note:: **Any vhost cuse specific requirement in the following sections will be emphasized**. Two implementations are turned on and off statically through configure file. Only one implementation could be turned on. They don't co-exist in current implementation. The vhost sample code application is a simple packet switching application with the following feature: * Packet switching between virtio-net devices and the network interface card, including using VMDQs to reduce the switching that needs to be performed in software. The following figure shows the architecture of the Vhost sample application based on vhost-cuse. .. _figure_vhost_net_arch: .. figure:: img/vhost_net_arch.* Vhost-net Architectural Overview The following figure shows the flow of packets through the vhost-net sample application. .. _figure_vhost_net_sample_app: .. figure:: img/vhost_net_sample_app.* Packet Flow Through the vhost-net Sample Application Supported Distributions ----------------------- The example in this section have been validated with the following distributions: * Fedora* 18 * Fedora* 19 * Fedora* 20 Prerequisites ------------- This section lists prerequisite packages that must be installed. Installing Packages on the Host(vhost cuse required) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The vhost cuse code uses the following packages; fuse, fuse-devel, and kernel-modules-extra. The vhost user code don't rely on those modules as eventfds are already installed into vhost process through Unix domain socket. #. Install Fuse Development Libraries and headers: .. code-block:: console yum -y install fuse fuse-devel #. Install the Cuse Kernel Module: .. code-block:: console yum -y install kernel-modules-extra QEMU simulator ~~~~~~~~~~~~~~ For vhost user, qemu 2.2 is required. Setting up the Execution Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The vhost sample code requires that QEMU allocates a VM's memory on the hugetlbfs file system. As the vhost sample code requires hugepages, the best practice is to partition the system into separate hugepage mount points for the VMs and the vhost sample code. .. note:: This is best-practice only and is not mandatory. For systems that only support 2 MB page sizes, both QEMU and vhost sample code can use the same hugetlbfs mount point without issue. **QEMU** VMs with gigabytes of memory can benefit from having QEMU allocate their memory from 1 GB huge pages. 1 GB huge pages must be allocated at boot time by passing kernel parameters through the grub boot loader. #. Calculate the maximum memory usage of all VMs to be run on the system. Then, round this value up to the nearest Gigabyte the execution environment will require. #. Edit the /etc/default/grub file, and add the following to the GRUB_CMDLINE_LINUX entry: .. code-block:: console GRUB_CMDLINE_LINUX="... hugepagesz=1G hugepages= default_hugepagesz=1G" #. Update the grub boot loader: .. code-block:: console grub2-mkconfig -o /boot/grub2/grub.cfg #. Reboot the system. #. The hugetlbfs mount point (/dev/hugepages) should now default to allocating gigabyte pages. .. note:: Making the above modification will change the system default hugepage size to 1 GB for all applications. **Vhost Sample Code** In this section, we create a second hugetlbs mount point to allocate hugepages for the DPDK vhost sample code. #. Allocate sufficient 2 MB pages for the DPDK vhost sample code: .. code-block:: console echo 256 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages #. Mount hugetlbs at a separate mount point for 2 MB pages: .. code-block:: console mount -t hugetlbfs nodev /mnt/huge -o pagesize=2M The above steps can be automated by doing the following: #. Edit /etc/fstab to add an entry to automatically mount the second hugetlbfs mount point: :: hugetlbfs /mnt/huge hugetlbfs defaults,pagesize=1G 0 0 #. Edit the /etc/default/grub file, and add the following to the GRUB_CMDLINE_LINUX entry: :: GRUB_CMDLINE_LINUX="... hugepagesz=2M hugepages=256 ... default_hugepagesz=1G" #. Update the grub bootloader: .. code-block:: console grub2-mkconfig -o /boot/grub2/grub.cfg #. Reboot the system. .. note:: Ensure that the default hugepage size after this setup is 1 GB. Setting up the Guest Execution Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is recommended for testing purposes that the DPDK testpmd sample application is used in the guest to forward packets, the reasons for this are discussed in Section 22.7, "Running the Virtual Machine (QEMU)". The testpmd application forwards packets between pairs of Ethernet devices, it requires an even number of Ethernet devices (virtio or otherwise) to execute. It is therefore recommended to create multiples of two virtio-net devices for each Virtual Machine either through libvirt or at the command line as follows. .. note:: Observe that in the example, "-device" and "-netdev" are repeated for two virtio-net devices. For vhost cuse: .. code-block:: console user@target:~$ qemu-system-x86_64 ... \ -netdev tap,id=hostnet1,vhost=on,vhostfd= \ -device virtio-net-pci, netdev=hostnet1,id=net1 \ -netdev tap,id=hostnet2,vhost=on,vhostfd= \ -device virtio-net-pci, netdev=hostnet2,id=net1 For vhost user: .. code-block:: console user@target:~$ qemu-system-x86_64 ... \ -chardev socket,id=char1,path= \ -netdev type=vhost-user,id=hostnet1,chardev=char1 \ -device virtio-net-pci,netdev=hostnet1,id=net1 \ -chardev socket,id=char2,path= \ -netdev type=vhost-user,id=hostnet2,chardev=char2 \ -device virtio-net-pci,netdev=hostnet2,id=net2 sock_path is the path for the socket file created by vhost. Compiling the Sample Code ------------------------- #. Compile vhost lib: To enable vhost, turn on vhost library in the configure file config/common_linuxapp. .. code-block:: console CONFIG_RTE_LIBRTE_VHOST=n vhost user is turned on by default in the configure file config/common_linuxapp. To enable vhost cuse, disable vhost user. .. code-block:: console CONFIG_RTE_LIBRTE_VHOST_USER=y After vhost is enabled and the implementation is selected, build the vhost library. #. Go to the examples directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/vhost #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the DPDK Getting Started Guide for possible RTE_TARGET values. #. Build the application: .. code-block:: console cd ${RTE_SDK} make config ${RTE_TARGET} make install ${RTE_TARGET} cd ${RTE_SDK}/examples/vhost make #. Go to the eventfd_link directory(vhost cuse required): .. code-block:: console cd ${RTE_SDK}/lib/librte_vhost/eventfd_link #. Build the eventfd_link kernel module(vhost cuse required): .. code-block:: console make Running the Sample Code ----------------------- #. Install the cuse kernel module(vhost cuse required): .. code-block:: console modprobe cuse #. Go to the eventfd_link directory(vhost cuse required): .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/lib/librte_vhost/eventfd_link #. Install the eventfd_link module(vhost cuse required): .. code-block:: console insmod ./eventfd_link.ko #. Go to the examples directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/vhost #. Run the vhost-switch sample code: vhost cuse: .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- -p 0x1 --dev-basename usvhost --dev-index 1 vhost user: a socket file named usvhost will be created under current directory. Use its path as the socket path in guest's qemu commandline. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- -p 0x1 --dev-basename usvhost .. note:: Please note the huge-dir parameter instructs the DPDK to allocate its memory from the 2 MB page hugetlbfs. Parameters ~~~~~~~~~~ **Basename and Index.** vhost cuse uses a Linux* character device to communicate with QEMU. The basename and the index are used to generate the character devices name. /dev/- The index parameter is provided for a situation where multiple instances of the virtual switch is required. For compatibility with the QEMU wrapper script, a base name of "usvhost" and an index of "1" should be used: .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- -p 0x1 --dev-basename usvhost --dev-index 1 **vm2vm.** The vm2vm parameter disable/set mode of packet switching between guests in the host. Value of "0" means disabling vm2vm implies that on virtual machine packet transmission will always go to the Ethernet port; Value of "1" means software mode packet forwarding between guests, it needs packets copy in vHOST, so valid only in one-copy implementation, and invalid for zero copy implementation; value of "2" means hardware mode packet forwarding between guests, it allows packets go to the Ethernet port, hardware L2 switch will determine which guest the packet should forward to or need send to external, which bases on the packet destination MAC address and VLAN tag. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir /mnt/huge -- --vm2vm [0,1,2] **Mergeable Buffers.** The mergeable buffers parameter controls how virtio-net descriptors are used for virtio-net headers. In a disabled state, one virtio-net header is used per packet buffer; in an enabled state one virtio-net header is used for multiple packets. The default value is 0 or disabled since recent kernels virtio-net drivers show performance degradation with this feature is enabled. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- --mergeable [0,1] **Stats.** The stats parameter controls the printing of virtio-net device statistics. The parameter specifies an interval second to print statistics, with an interval of 0 seconds disabling statistics. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- --stats [0,n] **RX Retry.** The rx-retry option enables/disables enqueue retries when the guests RX queue is full. This feature resolves a packet loss that is observed at high data-rates, by allowing it to delay and retry in the receive path. This option is enabled by default. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- --rx-retry [0,1] **RX Retry Number.** The rx-retry-num option specifies the number of retries on an RX burst, it takes effect only when rx retry is enabled. The default value is 4. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- --rx-retry 1 --rx-retry-num 5 **RX Retry Delay Time.** The rx-retry-delay option specifies the timeout (in micro seconds) between retries on an RX burst, it takes effect only when rx retry is enabled. The default value is 15. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir / mnt/huge -- --rx-retry 1 --rx-retry-delay 20 **Zero copy.** The zero copy option enables/disables the zero copy mode for RX/TX packet, in the zero copy mode the packet buffer address from guest translate into host physical address and then set directly as DMA address. If the zero copy mode is disabled, then one copy mode is utilized in the sample. This option is disabled by default. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir /mnt/huge -- --zero-copy [0,1] **RX descriptor number.** The RX descriptor number option specify the Ethernet RX descriptor number, Linux legacy virtio-net has different behavior in how to use the vring descriptor from DPDK based virtio-net PMD, the former likely allocate half for virtio header, another half for frame buffer, while the latter allocate all for frame buffer, this lead to different number for available frame buffer in vring, and then lead to different Ethernet RX descriptor number could be used in zero copy mode. So it is valid only in zero copy mode is enabled. The value is 32 by default. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir /mnt/huge -- --zero-copy 1 --rx-desc-num [0, n] **TX descriptor number.** The TX descriptor number option specify the Ethernet TX descriptor number, it is valid only in zero copy mode is enabled. The value is 64 by default. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir /mnt/huge -- --zero-copy 1 --tx-desc-num [0, n] **VLAN strip.** The VLAN strip option enable/disable the VLAN strip on host, if disabled, the guest will receive the packets with VLAN tag. It is enabled by default. .. code-block:: console user@target:~$ ./build/app/vhost-switch -c f -n 4 --huge-dir /mnt/huge -- --vlan-strip [0, 1] Running the Virtual Machine (QEMU) ---------------------------------- QEMU must be executed with specific parameters to: * Ensure the guest is configured to use virtio-net network adapters. .. code-block:: console user@target:~$ qemu-system-x86_64 ... -device virtio-net-pci,netdev=hostnet1,id=net1 ... * Ensure the guest's virtio-net network adapter is configured with offloads disabled. .. code-block:: console user@target:~$ qemu-system-x86_64 ... -device virtio-net-pci,netdev=hostnet1,id=net1,csum=off,gso=off,guest_tso4=off,guest_tso6=off,guest_ecn=off * Redirect QEMU to communicate with the DPDK vhost-net sample code in place of the vhost-net kernel module(vhost cuse). .. code-block:: console user@target:~$ qemu-system-x86_64 ... -netdev tap,id=hostnet1,vhost=on,vhostfd= ... * Enable the vhost-net sample code to map the VM's memory into its own process address space. .. code-block:: console user@target:~$ qemu-system-x86_64 ... -mem-prealloc -mem-path / dev/hugepages ... .. note:: The QEMU wrapper (qemu-wrap.py) is a Python script designed to automate the QEMU configuration described above. It also facilitates integration with libvirt, although the script may also be used standalone without libvirt. Redirecting QEMU to vhost-net Sample Code(vhost cuse) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To redirect QEMU to the vhost-net sample code implementation of the vhost-net API, an open file descriptor must be passed to QEMU running as a child process. .. code-block:: python #!/usr/bin/python fd = os.open("/dev/usvhost-1", os.O_RDWR) subprocess.call("qemu-system-x86_64 ... . -netdev tap,id=vhostnet0,vhost=on,vhostfd=" + fd +"...", shell=True) .. note:: This process is automated in the QEMU wrapper script discussed in Section 24.7.3. Mapping the Virtual Machine's Memory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For the DPDK vhost-net sample code to be run correctly, QEMU must allocate the VM's memory on hugetlbfs. This is done by specifying mem-prealloc and mem-path when executing QEMU. The vhost-net sample code accesses the virtio-net device's virtual rings and packet buffers by finding and mapping the VM's physical memory on hugetlbfs. In this case, the path passed to the guest should be that of the 1 GB page hugetlbfs: .. code-block:: console user@target:~$ qemu-system-x86_64 ... -mem-prealloc -mem-path / dev/hugepages ... .. note:: This process is automated in the QEMU wrapper script discussed in Section 24.7.3. The following two sections only applies to vhost cuse. For vhost-user, please make corresponding changes to qemu-wrapper script and guest XML file. QEMU Wrapper Script ~~~~~~~~~~~~~~~~~~~ The QEMU wrapper script automatically detects and calls QEMU with the necessary parameters required to integrate with the vhost sample code. It performs the following actions: * Automatically detects the location of the hugetlbfs and inserts this into the command line parameters. * Automatically open file descriptors for each virtio-net device and inserts this into the command line parameters. * Disables offloads on each virtio-net device. * Calls Qemu passing both the command line parameters passed to the script itself and those it has auto-detected. The QEMU wrapper script will automatically configure calls to QEMU: .. code-block:: console user@target:~$ qemu-wrap.py -machine pc-i440fx-1.4,accel=kvm,usb=off -cpu SandyBridge -smp 4,sockets=4,cores=1,threads=1 -netdev tap,id=hostnet1,vhost=on -device virtio-net-pci,netdev=hostnet1,id=net1 -hda -m 4096 which will become the following call to QEMU: .. code-block:: console /usr/local/bin/qemu-system-x86_64 -machine pc-i440fx-1.4,accel=kvm,usb=off -cpu SandyBridge -smp 4,sockets=4,cores=1,threads=1 -netdev tap,id=hostnet1,vhost=on,vhostfd= -device virtio-net-pci,netdev=hostnet1,id=net1, csum=off,gso=off,guest_tso4=off,guest_tso6=off,guest_ecn=off -hda -m 4096 -mem-path /dev/hugepages -mem-prealloc Libvirt Integration ~~~~~~~~~~~~~~~~~~~ The QEMU wrapper script (qemu-wrap.py) "wraps" libvirt calls to QEMU, such that QEMU is called with the correct parameters described above. To call the QEMU wrapper automatically from libvirt, the following configuration changes must be made: * Place the QEMU wrapper script in libvirt's binary search PATH ($PATH). A good location is in the directory that contains the QEMU binary. * Ensure that the script has the same owner/group and file permissions as the QEMU binary. * Update the VM xml file using virsh edit : * Set the VM to use the launch script * Set the emulator path contained in the # tags For example, replace /usr/bin/qemu-kvm with /usr/bin/qemu-wrap.py * Set the VM's virtio-net device's to use vhost-net offload: .. code-block:: xml * Enable libvirt to access the DPDK Vhost sample code's character device file by adding it to controllers cgroup for libvirtd using the following steps: .. code-block:: xml cgroup_controllers = [ ... "devices", ... ] clear_emulator_capabilities = 0 user = "root" group = "root" cgroup_device_acl = [ "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", "/dev/ptmx", "/dev/kvm", "/dev/kqemu", "/dev/rtc", "/dev/hpet", "/dev/net/tun", "/dev/-", ] * Disable SELinux or set to permissive mode. * Mount cgroup device controller: .. code-block:: console user@target:~$ mkdir /dev/cgroup user@target:~$ mount -t cgroup none /dev/cgroup -o devices * Restart the libvirtd system process For example, on Fedora* "systemctl restart libvirtd.service" * Edit the configuration parameters section of the script: * Configure the "emul_path" variable to point to the QEMU emulator. .. code-block:: xml emul_path = "/usr/local/bin/qemu-system-x86_64" * Configure the "us_vhost_path" variable to point to the DPDK vhost-net sample code's character devices name. DPDK vhost-net sample code's character device will be in the format "/dev/-". .. code-block:: xml us_vhost_path = "/dev/usvhost-1" Common Issues ~~~~~~~~~~~~~ * QEMU failing to allocate memory on hugetlbfs, with an error like the following:: file_ram_alloc: can't mmap RAM pages: Cannot allocate memory When running QEMU the above error indicates that it has failed to allocate memory for the Virtual Machine on the hugetlbfs. This is typically due to insufficient hugepages being free to support the allocation request. The number of free hugepages can be checked as follows: .. code-block:: console cat /sys/kernel/mm/hugepages/hugepages-/nr_hugepages The command above indicates how many hugepages are free to support QEMU's allocation request. * User space VHOST when the guest has 2MB sized huge pages: The guest may have 2MB or 1GB sized huge pages. The user space VHOST should work properly in both cases. * User space VHOST will not work with QEMU without the ``-mem-prealloc`` option: The current implementation works properly only when the guest memory is pre-allocated, so it is required to use a QEMU version (e.g. 1.6) which supports ``-mem-prealloc``. The ``-mem-prealloc`` option must be specified explicitly in the QEMU command line. * User space VHOST will not work with a QEMU version without shared memory mapping: As shared memory mapping is mandatory for user space VHOST to work properly with the guest, user space VHOST needs access to the shared memory from the guest to receive and transmit packets. It is important to make sure the QEMU version supports shared memory mapping. * Issues with ``virsh destroy`` not destroying the VM: Using libvirt ``virsh create`` the ``qemu-wrap.py`` spawns a new process to run ``qemu-kvm``. This impacts the behavior of ``virsh destroy`` which kills the process running ``qemu-wrap.py`` without actually destroying the VM (it leaves the ``qemu-kvm`` process running): This following patch should fix this issue: http://dpdk.org/ml/archives/dev/2014-June/003607.html * In an Ubuntu environment, QEMU fails to start a new guest normally with user space VHOST due to not being able to allocate huge pages for the new guest: The solution for this issue is to add ``-boot c`` into the QEMU command line to make sure the huge pages are allocated properly and then the guest should start normally. Use ``cat /proc/meminfo`` to check if there is any changes in the value of ``HugePages_Total`` and ``HugePages_Free`` after the guest startup. * Log message: ``eventfd_link: module verification failed: signature and/or required key missing - tainting kernel``: This log message may be ignored. The message occurs due to the kernel module ``eventfd_link``, which is not a standard Linux module but which is necessary for the user space VHOST current implementation (CUSE-based) to communicate with the guest. Running DPDK in the Virtual Machine ----------------------------------- For the DPDK vhost-net sample code to switch packets into the VM, the sample code must first learn the MAC address of the VM's virtio-net device. The sample code detects the address from packets being transmitted from the VM, similar to a learning switch. This behavior requires no special action or configuration with the Linux* virtio-net driver in the VM as the Linux* Kernel will automatically transmit packets during device initialization. However, DPDK-based applications must be modified to automatically transmit packets during initialization to facilitate the DPDK vhost- net sample code's MAC learning. The DPDK testpmd application can be configured to automatically transmit packets during initialization and to act as an L2 forwarding switch. Testpmd MAC Forwarding ~~~~~~~~~~~~~~~~~~~~~~ At high packet rates, a minor packet loss may be observed. To resolve this issue, a "wait and retry" mode is implemented in the testpmd and vhost sample code. In the "wait and retry" mode if the virtqueue is found to be full, then testpmd waits for a period of time before retrying to enqueue packets. The "wait and retry" algorithm is implemented in DPDK testpmd as a forwarding method call "mac_retry". The following sequence diagram describes the algorithm in detail. .. _figure_tx_dpdk_testpmd: .. figure:: img/tx_dpdk_testpmd.* Packet Flow on TX in DPDK-testpmd Running Testpmd ~~~~~~~~~~~~~~~ The testpmd application is automatically built when DPDK is installed. Run the testpmd application as follows: .. code-block:: console user@target:~$ x86_64-native-linuxapp-gcc/app/testpmd -c 0x3 -- n 4 -socket-mem 128 -- --burst=64 -i The destination MAC address for packets transmitted on each port can be set at the command line: .. code-block:: console user@target:~$ x86_64-native-linuxapp-gcc/app/testpmd -c 0x3 -- n 4 -socket-mem 128 -- --burst=64 -i --eth- peer=0,aa:bb:cc:dd:ee:ff --eth-peer=1,ff,ee,dd,cc,bb,aa * Packets received on port 1 will be forwarded on port 0 to MAC address aa:bb:cc:dd:ee:ff. * Packets received on port 0 will be forwarded on port 1 to MAC address ff,ee,dd,cc,bb,aa. The testpmd application can then be configured to act as an L2 forwarding application: .. code-block:: console testpmd> set fwd mac_retry The testpmd can then be configured to start processing packets, transmitting packets first so the DPDK vhost sample code on the host can learn the MAC address: .. code-block:: console testpmd> start tx_first .. note:: Please note "set fwd mac_retry" is used in place of "set fwd mac_fwd" to ensure the retry feature is activated. Passing Traffic to the Virtual Machine Device --------------------------------------------- For a virtio-net device to receive traffic, the traffic's Layer 2 header must include both the virtio-net device's MAC address and VLAN tag. The DPDK sample code behaves in a similar manner to a learning switch in that it learns the MAC address of the virtio-net devices from the first transmitted packet. On learning the MAC address, the DPDK vhost sample code prints a message with the MAC address and VLAN tag virtio-net device. For example: .. code-block:: console DATA: (0) MAC_ADDRESS cc:bb:bb:bb:bb:bb and VLAN_TAG 1000 registered The above message indicates that device 0 has been registered with MAC address cc:bb:bb:bb:bb:bb and VLAN tag 1000. Any packets received on the NIC with these values is placed on the devices receive queue. When a virtio-net device transmits packets, the VLAN tag is added to the packet by the DPDK vhost sample code. ================================================ FILE: doc/guides/sample_app_ug/vm_power_management.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. VM Power Management Application =============================== Introduction ------------ Applications running in Virtual Environments have an abstract view of the underlying hardware on the Host, in particular applications cannot see the binding of virtual to physical hardware. When looking at CPU resourcing, the pinning of Virtual CPUs(vCPUs) to Host Physical CPUs(pCPUS) is not apparent to an application and this pinning may change over time. Furthermore, Operating Systems on virtual machines do not have the ability to govern their own power policy; the Machine Specific Registers (MSRs) for enabling P-State transitions are not exposed to Operating Systems running on Virtual Machines(VMs). The Virtual Machine Power Management solution shows an example of how a DPDK application can indicate its processing requirements using VM local only information(vCPU/lcore) to a Host based Monitor which is responsible for accepting requests for frequency changes for a vCPU, translating the vCPU to a pCPU via libvirt and affecting the change in frequency. The solution is comprised of two high-level components: #. Example Host Application Using a Command Line Interface(CLI) for VM->Host communication channel management allows adding channels to the Monitor, setting and querying the vCPU to pCPU pinning, inspecting and manually changing the frequency for each CPU. The CLI runs on a single lcore while the thread responsible for managing VM requests runs on a second lcore. VM requests arriving on a channel for frequency changes are passed to the librte_power ACPI cpufreq sysfs based library. The Host Application relies on both qemu-kvm and libvirt to function. #. librte_power for Virtual Machines Using an alternate implementation for the librte_power API, requests for frequency changes are forwarded to the host monitor rather than the APCI cpufreq sysfs interface used on the host. The l3fwd-power application will use this implementation when deployed on a VM (see Chapter 11 "L3 Forwarding with Power Management Application"). .. _figure_vm_power_mgr_highlevel: .. figure:: img/vm_power_mgr_highlevel.* Highlevel Solution Overview -------- VM Power Management employs qemu-kvm to provide communications channels between the host and VMs in the form of Virtio-Serial which appears as a paravirtualized serial device on a VM and can be configured to use various backends on the host. For this example each Virtio-Serial endpoint on the host is configured as AF_UNIX file socket, supporting poll/select and epoll for event notification. In this example each channel endpoint on the host is monitored via epoll for EPOLLIN events. Each channel is specified as qemu-kvm arguments or as libvirt XML for each VM, where each VM can have a number of channels up to a maximum of 64 per VM, in this example each DPDK lcore on a VM has exclusive access to a channel. To enable frequency changes from within a VM, a request via the librte_power interface is forwarded via Virtio-Serial to the host, each request contains the vCPU and power command(scale up/down/min/max). The API for host and guest librte_power is consistent across environments, with the selection of VM or Host Implementation determined at automatically at runtime based on the environment. Upon receiving a request, the host translates the vCPU to a pCPU via the libvirt API before forwarding to the host librte_power. .. _figure_vm_power_mgr_vm_request_seq: .. figure:: img/vm_power_mgr_vm_request_seq.* VM request to scale frequency Performance Considerations ~~~~~~~~~~~~~~~~~~~~~~~~~~ While Haswell Microarchitecture allows for independent power control for each core, earlier Microarchtectures do not offer such fine grained control. When deployed on pre-Haswell platforms greater care must be taken in selecting which cores are assigned to a VM, for instance a core will not scale down until its sibling is similarly scaled. Configuration ------------- BIOS ~~~~ Enhanced Intel SpeedStep® Technology must be enabled in the platform BIOS if the power management feature of DPDK is to be used. Otherwise, the sys file folder /sys/devices/system/cpu/cpu0/cpufreq will not exist, and the CPU frequency-based power management cannot be used. Consult the relevant BIOS documentation to determine how these settings can be accessed. Host Operating System ~~~~~~~~~~~~~~~~~~~~~ The Host OS must also have the *apci_cpufreq* module installed, in some cases the *intel_pstate* driver may be the default Power Management environment. To enable *acpi_cpufreq* and disable *intel_pstate*, add the following to the grub Linux command line: .. code-block:: console intel_pstate=disable Upon rebooting, load the *acpi_cpufreq* module: .. code-block:: console modprobe acpi_cpufreq Hypervisor Channel Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Virtio-Serial channels are configured via libvirt XML: .. code-block:: xml {vm_name}
Where a single controller of type *virtio-serial* is created and up to 32 channels can be associated with a single controller and multiple controllers can be specified. The convention is to use the name of the VM in the host path *{vm_name}* and to increment *{channel_num}* for each channel, likewise the port value *{N}* must be incremented for each channel. Each channel on the host will appear in *path*, the directory */tmp/powermonitor/* must first be created and given qemu permissions .. code-block:: console mkdir /tmp/powermonitor/ chown qemu:qemu /tmp/powermonitor Note that files and directories within /tmp are generally removed upon rebooting the host and the above steps may need to be carried out after each reboot. The serial device as it appears on a VM is configured with the *target* element attribute *name* and must be in the form of *virtio.serial.port.poweragent.{vm_channel_num}*, where *vm_channel_num* is typically the lcore channel to be used in DPDK VM applications. Each channel on a VM will be present at */dev/virtio-ports/virtio.serial.port.poweragent.{vm_channel_num}* Compiling and Running the Host Application ------------------------------------------ Compiling ~~~~~~~~~ #. export RTE_SDK=/path/to/rte_sdk #. cd ${RTE_SDK}/examples/vm_power_manager #. make Running ~~~~~~~ The application does not have any specific command line options other than *EAL*: .. code-block:: console ./build/vm_power_mgr [EAL options] The application requires exactly two cores to run, one core is dedicated to the CLI, while the other is dedicated to the channel endpoint monitor, for example to run on cores 0 & 1 on a system with 4 memory channels: .. code-block:: console ./build/vm_power_mgr -c 0x3 -n 4 After successful initialization the user is presented with VM Power Manager CLI: .. code-block:: console vm_power> Virtual Machines can now be added to the VM Power Manager: .. code-block:: console vm_power> add_vm {vm_name} When a {vm_name} is specified with the *add_vm* command a lookup is performed with libvirt to ensure that the VM exists, {vm_name} is used as an unique identifier to associate channels with a particular VM and for executing operations on a VM within the CLI. VMs do not have to be running in order to add them. A number of commands can be issued via the CLI in relation to VMs: Remove a Virtual Machine identified by {vm_name} from the VM Power Manager. .. code-block:: console rm_vm {vm_name} Add communication channels for the specified VM, the virtio channels must be enabled in the VM configuration(qemu/libvirt) and the associated VM must be active. {list} is a comma-separated list of channel numbers to add, using the keyword 'all' will attempt to add all channels for the VM: .. code-block:: console add_channels {vm_name} {list}|all Enable or disable the communication channels in {list}(comma-separated) for the specified VM, alternatively list can be replaced with keyword 'all'. Disabled channels will still receive packets on the host, however the commands they specify will be ignored. Set status to 'enabled' to begin processing requests again: .. code-block:: console set_channel_status {vm_name} {list}|all enabled|disabled Print to the CLI the information on the specified VM, the information lists the number of vCPUS, the pinning to pCPU(s) as a bit mask, along with any communication channels associated with each VM, along with the status of each channel: .. code-block:: console show_vm {vm_name} Set the binding of Virtual CPU on VM with name {vm_name} to the Physical CPU mask: .. code-block:: console set_pcpu_mask {vm_name} {vcpu} {pcpu} Set the binding of Virtual CPU on VM to the Physical CPU: .. code-block:: console set_pcpu {vm_name} {vcpu} {pcpu} Manual control and inspection can also be carried in relation CPU frequency scaling: Get the current frequency for each core specified in the mask: .. code-block:: console show_cpu_freq_mask {mask} Set the current frequency for the cores specified in {core_mask} by scaling each up/down/min/max: .. code-block:: console set_cpu_freq {core_mask} up|down|min|max Get the current frequency for the specified core: .. code-block:: console show_cpu_freq {core_num} Set the current frequency for the specified core by scaling up/down/min/max: .. code-block:: console set_cpu_freq {core_num} up|down|min|max Compiling and Running the Guest Applications -------------------------------------------- For compiling and running l3fwd-power, see Chapter 11 "L3 Forwarding with Power Management Application". A guest CLI is also provided for validating the setup. For both l3fwd-power and guest CLI, the channels for the VM must be monitored by the host application using the *add_channels* command on the host. Compiling ~~~~~~~~~ #. export RTE_SDK=/path/to/rte_sdk #. cd ${RTE_SDK}/examples/vm_power_manager/guest_cli #. make Running ~~~~~~~ The application does not have any specific command line options other than *EAL*: .. code-block:: console ./build/vm_power_mgr [EAL options] The application for example purposes uses a channel for each lcore enabled, for example to run on cores 0,1,2,3 on a system with 4 memory channels: .. code-block:: console ./build/guest_vm_power_mgr -c 0xf -n 4 After successful initialization the user is presented with VM Power Manager Guest CLI: .. code-block:: console vm_power(guest)> To change the frequency of a lcore, use the set_cpu_freq command. Where {core_num} is the lcore and channel to change frequency by scaling up/down/min/max. .. code-block:: console set_cpu_freq {core_num} up|down|min|max ================================================ FILE: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. VMDQ and DCB Forwarding Sample Application ========================================== The VMDQ and DCB Forwarding sample application is a simple example of packet processing using the DPDK. The application performs L2 forwarding using VMDQ and DCB to divide the incoming traffic into 128 queues. The traffic splitting is performed in hardware by the VMDQ and DCB features of the Intel® 82599 10 Gigabit Ethernet Controller. Overview -------- This sample application can be used as a starting point for developing a new application that is based on the DPDK and uses VMDQ and DCB for traffic partitioning. The VMDQ and DCB filters work on VLAN traffic to divide the traffic into 128 input queues on the basis of the VLAN ID field and VLAN user priority field. VMDQ filters split the traffic into 16 or 32 groups based on the VLAN ID. Then, DCB places each packet into one of either 4 or 8 queues within that group, based upon the VLAN user priority field. In either case, 16 groups of 8 queues, or 32 groups of 4 queues, the traffic can be split into 128 hardware queues on the NIC, each of which can be polled individually by a DPDK application. All traffic is read from a single incoming port (port 0) and output on port 1, without any processing being performed. The traffic is split into 128 queues on input, where each thread of the application reads from multiple queues. For example, when run with 8 threads, that is, with the -c FF option, each thread receives and forwards packets from 16 queues. As supplied, the sample application configures the VMDQ feature to have 16 pools with 8 queues each as indicated in :numref:`figure_vmdq_dcb_example`. The Intel® 82599 10 Gigabit Ethernet Controller NIC also supports the splitting of traffic into 32 pools of 4 queues each and this can be used by changing the NUM_POOLS parameter in the supplied code. The NUM_POOLS parameter can be passed on the command line, after the EAL parameters: .. code-block:: console ./build/vmdq_dcb [EAL options] -- -p PORTMASK --nb-pools NP where, NP can be 16 or 32. .. _figure_vmdq_dcb_example: .. figure:: img/vmdq_dcb_example.* Packet Flow Through the VMDQ and DCB Sample Application In Linux* user space, the application can display statistics with the number of packets received on each queue. To have the application display the statistics, send a SIGHUP signal to the running application process, as follows: where, is the process id of the application process. The VMDQ and DCB Forwarding sample application is in many ways simpler than the L2 Forwarding application (see Chapter 9 , "L2 Forwarding Sample Application (in Real and Virtualized Environments)") as it performs unidirectional L2 forwarding of packets from one port to a second port. No command-line options are taken by this application apart from the standard EAL command-line options. .. note:: Since VMD queues are being used for VMM, this application works correctly when VTd is disabled in the BIOS or Linux* kernel (intel_iommu=off). Compiling the Application ------------------------- #. Go to the examples directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd ${RTE_SDK}/examples/vmdq_dcb #. Set the target (a default target is used if not specified). For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc See the *DPDK Getting Started Guide* for possible RTE_TARGET values. #. Build the application: .. code-block:: console make Running the Application ----------------------- To run the example in a linuxapp environment: .. code-block:: console user@target:~$ ./build/vmdq_dcb -c f -n 4 -- -p 0x3 --nb-pools 16 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. Explanation ----------- The following sections provide some explanation of the code. Initialization ~~~~~~~~~~~~~~ The EAL, driver and PCI configuration is performed largely as in the L2 Forwarding sample application, as is the creation of the mbuf pool. See Chapter 9, "L2 Forwarding Sample Application (in Real and Virtualized Environments)". Where this example application differs is in the configuration of the NIC port for RX. The VMDQ and DCB hardware feature is configured at port initialization time by setting the appropriate values in the rte_eth_conf structure passed to the rte_eth_dev_configure() API. Initially in the application, a default structure is provided for VMDQ and DCB configuration to be filled in later by the application. .. code-block:: c /* empty vmdq+dcb configuration structure. Filled in programmatically */ static const struct rte_eth_conf vmdq_dcb_conf_default = { .rxmode = { .mq_mode = ETH_VMDQ_DCB, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ }, .txmode = { .mq_mode = ETH_DCB_NONE, }, .rx_adv_conf = { /* * should be overridden separately in code with * appropriate values */ .vmdq_dcb_conf = { .nb_queue_pools = ETH_16_POOLS, .enable_default_pool = 0, .default_pool = 0, .nb_pool_maps = 0, .pool_map = {{0, 0},}, .dcb_queue = {0}, }, }, }; The get_eth_conf() function fills in an rte_eth_conf structure with the appropriate values, based on the global vlan_tags array, and dividing up the possible user priority values equally among the individual queues (also referred to as traffic classes) within each pool, that is, if the number of pools is 32, then the user priority fields are allocated two to a queue. If 16 pools are used, then each of the 8 user priority fields is allocated to its own queue within the pool. For the VLAN IDs, each one can be allocated to possibly multiple pools of queues, so the pools parameter in the rte_eth_vmdq_dcb_conf structure is specified as a bitmask value. .. code-block:: c const uint16_t vlan_tags[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array * given above, and the number of traffic classes available for use. */ static inline int get_eth_conf(struct rte_eth_conf *eth_conf, enum rte_eth_nb_pools num_pools) { struct rte_eth_vmdq_dcb_conf conf; unsigned i; if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS ) return -1; conf.nb_queue_pools = num_pools; conf.enable_default_pool = 0; conf.default_pool = 0; /* set explicit value, even if not used */ conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); for (i = 0; i < conf.nb_pool_maps; i++){ conf.pool_map[i].vlan_id = vlan_tags[ i ]; conf.pool_map[i].pools = 1 << (i % num_pools); } for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ conf.dcb_queue[i] = (uint8_t)(i % (NUM_QUEUES/num_pools)); } (void) rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(\*eth_conf)); (void) rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &conf, sizeof(eth_conf->rx_adv_conf.vmdq_dcb_conf)); return 0; } Once the network port has been initialized using the correct VMDQ and DCB values, the initialization of the port's RX and TX hardware rings is performed similarly to that in the L2 Forwarding sample application. See Chapter 9, "L2 Forwarding Sample Application (in Real and Virtualized Environments)" for more information. Statistics Display ~~~~~~~~~~~~~~~~~~ When run in a linuxapp environment, the VMDQ and DCB Forwarding sample application can display statistics showing the number of packets read from each RX queue. This is provided by way of a signal handler for the SIGHUP signal, which simply prints to standard output the packet counts in grid form. Each row of the output is a single pool with the columns being the queue number within that pool. To generate the statistics output, use the following command: .. code-block:: console user@host$ sudo killall -HUP vmdq_dcb_app Please note that the statistics output will appear on the terminal where the vmdq_dcb_app is running, rather than the terminal from which the HUP signal was sent. ================================================ FILE: doc/guides/testpmd_app_ug/build_app.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Compiling the Application ========================= The testpmd application is compiled as part of the main compilation of the DPDK libraries and tools. Refer to the DPDK Getting Started Guide for details. The basic compilation steps are: #. Set the required environmental variables and go to the source directory: .. code-block:: console export RTE_SDK=/path/to/rte_sdk cd $RTE_SDK #. Set the compilation target. For example: .. code-block:: console export RTE_TARGET=x86_64-native-linuxapp-gcc #. Build the application: .. code-block:: console make install T=$RTE_TARGET The compiled application will be located at: .. code-block:: console $RTE_SDK/$RTE_TARGET/build/app/testpmd ================================================ FILE: doc/guides/testpmd_app_ug/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Testpmd Application User Guide ============================== |today| **Contents** .. toctree:: :maxdepth: 3 :numbered: intro overview build_app run_app testpmd_funcs ================================================ FILE: doc/guides/testpmd_app_ug/intro.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ This document is a user guide for the testpmd example application that is shipped as part of the Data Plane Development Kit. The testpmd application can be used to test the DPDK in a packet forwarding mode and also to access NIC hardware features such as Flow Director. It also serves as a example of how to build a more fully-featured application using the DPDK SDK. Documentation Roadmap --------------------- The following is a list of DPDK documents in the suggested reading order: * **Release Notes** : Provides release-specific information, including supported features, limitations, fixed issues, known issues and so on. Also, provides the answers to frequently asked questions in FAQ format. * **Getting Started Guide** (this document): Describes how to install and configure the DPDK; designed to get users up and running quickly with the software. * **Programmer's Guide** : Describes: * The software architecture and how to use it (through examples), specifically in a Linux* application (linuxapp) environment * The content of the DPDK, the build system (including the commands that can be used in the root DPDK Makefile to build the development kit and an application) and guidelines for porting an application * Optimizations used in the software and those that should be considered for new development A glossary of terms is also provided. * **API Reference** : Provides detailed information about DPDK functions, data structures and other programming constructs. * **Sample Applications User Guide** : Describes a set of sample applications. Each chapter describes a sample application that showcases specific functionality and provides instructions on how to compile, run and use the sample application. .. note:: These documents are available for download as a separate documentation package at the same location as the DPDK code package. ================================================ FILE: doc/guides/testpmd_app_ug/overview.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Overview ======== The following sections show how to build and run the testpmd application and how to configure the application from the command line and the run-time environment. ================================================ FILE: doc/guides/testpmd_app_ug/run_app.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Running the Application ======================= EAL Command-line Options ------------------------ The following are the EAL command-line options that can be used in conjunction with the testpmd, or any other DPDK application. See the DPDK Getting Started Guide for more information on these options. * -c COREMASK Set the hexadecimal bitmask of the cores to run on. * -l CORELIST List of cores to run on The argument format is [-c2][,c3[-c4],...] where c1, c2, etc are core indexes between 0 and 128 * --lcores COREMAP Map lcore set to physical cpu set The argument format is '[<,lcores[@cpus]>...]' lcores and cpus list are grouped by '(' and ')' Within the group, '-' is used for range separator, ',' is used for single number separator. '( )' can be omitted for single element group, '@' can be omitted if cpus and lcores have the same value * --master-lcore ID Core ID that is used as master * -n NUM Set the number of memory channels to use. * -b, --pci-blacklist domain:bus:devid.func Blacklist a PCI devise to prevent EAL from using it. Multiple -b options are allowed. * -d LIB.so Load an external driver. Multiple -d options are allowed. * -w, --pci-whitelist domain:bus:devid:func Add a PCI device in white list. * -m MB Memory to allocate. See also --socket-mem. * -r NUM Set the number of memory ranks (auto-detected by default). * -v Display the version information on startup. * --xen-dom0 Support application running on Xen Domain0 without hugetlbfs. * --syslog Set the syslog facility. * --socket-mem Set the memory to allocate on specific sockets (use comma separated values). * --huge-dir Specify the directory where the hugetlbfs is mounted. * --proc-type Set the type of the current process. * --file-prefix Prefix for hugepage filenames. * -vmware-tsc-map Use VMware TSC map instead of native RDTSC. * --vdev Add a virtual device, with format "[,key=val, ...]", e.g. --vdev=eth_pcap0,iface=eth2. * --base-virtaddr Specify base virtual address. * --create-uio-dev Create /dev/uioX (usually done by hotplug). * --no-shconf No shared config (mmap'd files). * --no-pci Disable pci. * --no-hpet Disable hpet. * --no-huge Use malloc instead of hugetlbfs. Testpmd Command-line Options ---------------------------- The following are the command-line options for the testpmd applications. They must be separated from the EAL options, shown in the previous section, with a -- separator: .. code-block:: console sudo ./testpmd -c 0xF -n 4 -- -i --portmask=0x1 --nb-cores=2 * -i, --interactive Run testpmd in interactive mode. In this mode, the testpmd starts with a prompt that can be used to start and stop forwarding, configure the application and display stats on the current packet processing session. See the Section 5.0, "Test Runtime Functions" section for more details. In non-interactive mode, the application starts with the configuration specified on the command-line and immediately enters forwarding mode. * -h, --help Display a help message and quit. * -a, --auto-start Start forwarding on init. * --nb-cores=N Set the number of forwarding cores, where 1 <= N <= number of cores or RTE_MAX_LCORE from the configuration file. The default value is 1. * --nb-ports=N Set the number of forwarding ports, where 1 <= N <= number of ports on the board or RTE_MAX_ETHPORTS from the configuration file. The default value is the number of ports on the board. * --coremask=0xXX Set the hexadecimal bitmask of the cores running the packet forwarding test. The master lcore is reserved for command line parsing only and cannot be masked on for packet forwarding. * --portmask=0xXX Set the hexadecimal bitmask of the ports used by the packet forwarding test. * --numa Enable NUMA-aware allocation of RX/TX rings and of RX memory buffers (mbufs). * --port-numa-config=(port,socket)[,(port,socket)] Specify the socket on which the memory pool to be used by the port will be allocated. * --ring-numa-config=(port,flag,socket)[,(port,flag,socket)] Specify the socket on which the TX/RX rings for the port will be allocated. Where flag is 1 for RX, 2 for TX, and 3 for RX and TX. * --socket-num=N Set the socket from which all memory is allocated in NUMA mode, where 0 <= N < number of sockets on the board. * --mbuf-size=N Set the data size of the mbufs used to N bytes, where N < 65536. The default value is 2048. * --total-num-mbufs=N Set the number of mbufs to be allocated in the mbuf pools, where N > 1024. * --max-pkt-len=N Set the maximum packet size to N bytes, where N >= 64. The default value is 1518. * --eth-peers-configfile=name Use a configuration file containing the Ethernet addresses of the peer ports. The configuration file should contain the Ethernet addresses on separate lines: XX:XX:XX:XX:XX:01 XX:XX:XX:XX:XX:02 ... * --eth-peer=N,XX:XX:XX:XX:XX:XX Set the MAC address XX:XX:XX:XX:XX:XX of the peer port N, where 0 <= N < RTE_MAX_ETHPORTS from the configuration file. * --pkt-filter-mode=mode Set Flow Director mode where mode is either none (the default), signature or perfect. See the Section 5.6, "Flow Director Functions" for more detail. * --pkt-filter-report-hash=mode Set Flow Director hash match reporting mode where mode is none, match (the default) or always. * --pkt-filter-size=N Set Flow Director allocated memory size, where N is 64K, 128K or 256K. Sizes are in kilobytes. The default is 64. * --pkt-filter-flexbytes-offset=N Set the flexbytes offset. The offset is defined in words (not bytes) counted from the first byte of the destination Ethernet MAC address, where N is 0 <= N <= 32. The default value is 0x6. * --pkt-filter-drop-queue=N Set the drop-queue. In perfect filter mode, when a rule is added with queue = -1, the packet will be enqueued into the RX drop-queue. If the drop-queue does not exist, the packet is dropped. The default value is N=127. * --crc-strip Enable hardware CRC stripping. * --enable-rx-cksum Enable hardware RX checksum offload. * --disable-hw-vlan Disable hardware VLAN. * --disable-hw-vlan-filter Disable hardware VLAN filter. * --disable-hw-vlan-strip Disable hardware VLAN strip. * --disable-hw-vlan-extend Disable hardware VLAN extend. * --enable-drop-en Enable per-queue packet drop for packets with no descriptors. * --disable-rss Disable RSS (Receive Side Scaling). * --port-topology=mode Set port topology, where mode is paired(the default) or chained. In paired mode, the forwarding is between pairs of ports, for example: (0,1), (2,3), (4,5). In chained mode, the forwarding is to the next available port in the port mask, for example: (0,1), (1,2), (2,0). The ordering of the ports can be changed using the portlist testpmd runtime function. * --forward-mode=N Set forwarding mode. (N: io|mac|mac_retry|mac_swap|flowgen|rxonly|txonly|csum|icmpecho|ieee1588) * --rss-ip Set RSS functions for IPv4/IPv6 only. * --rss-udp Set RSS functions for IPv4/IPv6 and UDP. * --rxq=N Set the number of RX queues per port to N, where 1 <= N <= 65535. The default value is 1. * --rxd=N Set the number of descriptors in the RX rings to N, where N > 0. The default value is 128. * --txq=N Set the number of TX queues per port to N, where 1 <= N <= 65535. The default value is 1. * --txd=N Set the number of descriptors in the TX rings to N, where N > 0. The default value is 512. * --burst=N Set the number of packets per burst to N, where 1 <= N <= 512. The default value is 16. * --mbcache=N Set the cache of mbuf memory pools to N, where 0 <= N <= 512. The default value is 16. * --rxpt=N Set the prefetch threshold register of RX rings to N, where N >= 0. The default value is 8. * --rxht=N Set the host threshold register of RX rings to N, where N >= 0. The default value is 8. * --rxfreet=N Set the free threshold of RX descriptors to N, where 0 <= N < value of --rxd. The default value is 0. * --rxwt=N Set the write-back threshold register of RX rings to N, where N >= 0. The default value is 4. * --txpt=N Set the prefetch threshold register of TX rings to N, where N >= 0. The default value is 36. * --txht=N Set the host threshold register of TX rings to N, where N >= 0. The default value is 0. * --txwt=N Set the write-back threshold register of TX rings to N, where N >= 0. The default value is 0. * --txfreet=N Set the transmit free threshold of TX rings to N, where 0 <= N <= value of --txd. The default value is 0. * --txrst=N Set the transmit RS bit threshold of TX rings to N, where 0 <= N <= value of --txd. The default value is 0. * --txqflags=0xXXXXXXXX Set the hexadecimal bitmask of TX queue flags, where 0 <= N <= 0x7FFFFFFF. The default value is 0. Note:: When using hardware offload functions such as vlan, checksum..., add txqflags=0, since depending on the PMD, txqflags might be set to a non-zero value. * --rx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping)] Set the RX queues statistics counters mapping 0 <= mapping <= 15. * --tx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping)] Set the TX queues statistics counters mapping 0 <= mapping <= 15. * --no-flush-rx Don't flush the RX streams before starting forwarding. Used mainly with PCAP drivers. * --txpkts=X[,Y] Set TX segment sizes. * --disable-link-check Disable check on link status when starting/stopping ports. ================================================ FILE: doc/guides/testpmd_app_ug/testpmd_funcs.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Testpmd Runtime Functions ========================= Where the testpmd application is started in interactive mode, (-i|--interactive), it displays a prompt that can be used to start and stop forwarding, configure the application, display statistics, set the Flow Director and other tasks. .. code-block:: console testpmd> The testpmd prompt has some, limited, readline support. Common bash command- line functions such as Ctrl+a and Ctrl+e to go to the start and end of the prompt line are supported as well as access to the command history via the up-arrow. There is also support for tab completion. If you type a partial command and hit you get a list of the available completions: .. code-block:: console testpmd> show port info [Mul-choice STRING]: show|clear port info|stats|fdir|stat_qmap X info [Mul-choice STRING]: show|clear port info|stats|fdir|stat_qmap all stats [Mul-choice STRING]: show|clear port info|stats|fdir|stat_qmap X stats [Mul-choice STRING]: show|clear port info|stats|fdir|stat_qmap all ... Help Functions -------------- The testpmd has on-line help for the functions that are available at runtime. These are divided into sections and can be accessed using help, help section or help all: .. code-block:: console testpmd> help Help is available for the following sections: help control : Start and stop forwarding. help display : Displaying port, stats and config information. help config : Configuration information. help ports : Configuring ports. help registers : Reading and setting port registers. help filters : Filters configuration help. help all : All of the above sections. Control Functions ----------------- start ~~~~~ Start packet forwarding with current configuration: start start tx_first ~~~~~~~~~~~~~~ Start packet forwarding with current configuration after sending one burst of packets: start tx_first stop ~~~~ Stop packet forwarding, and display accumulated statistics: stop quit ~~~~ Quit to prompt: quit Display Functions ----------------- The functions in the following sections are used to display information about the testpmd configuration or the NIC status. show port ~~~~~~~~~ Display information for a given port or all ports: show port (info|stats|fdir|stat_qmap) (port_id|all) The available information categories are: info : General port information such as MAC address. stats : RX/TX statistics. fdir : Flow Director information and statistics. stat_qmap : Queue statistics mapping. For example: .. code-block:: console testpmd> show port info 0 ********************* Infos for port 0 ********************* MAC address: XX:XX:XX:XX:XX:XX Connect to socket: 0 memory allocation on the socket: 0 Link status: up Link speed: 40000 Mbps Link duplex: full-duplex Promiscuous mode: enabled Allmulticast mode: disabled Maximum number of MAC addresses: 64 Maximum number of MAC addresses of hash filtering: 0 VLAN offload: strip on filter on qinq(extend) off Redirection table size: 512 Supported flow types: ipv4-frag ipv4-tcp ipv4-udp ipv4-sctp ipv4-other ipv6-frag ipv6-tcp ipv6-udp ipv6-sctp ipv6-other l2_payload show port rss reta ~~~~~~~~~~~~~~~~~~ Display the rss redirection table entry indicated by masks on port X: show port (port_id) rss reta (size) (mask0, mask1...) size is used to indicate the hardware supported reta size show port rss-hash ~~~~~~~~~~~~~~~~~~ Display the RSS hash functions and RSS hash key of a port: show port (port_id) rss-hash [key] clear port ~~~~~~~~~~ Clear the port statistics for a given port or for all ports: clear port (info|stats|fdir|stat_qmap) (port_id|all) For example: .. code-block:: console testpmd> clear port stats all show config ~~~~~~~~~~~ Displays the configuration of the application. The configuration comes from the command-line, the runtime or the application defaults: show config (rxtx|cores|fwd) The available information categories are: rxtx : RX/TX configuration items. cores : List of forwarding cores. fwd : Packet forwarding configuration. For example: .. code-block:: console testpmd> show config rxtx io packet forwarding - CRC stripping disabled - packets/burst=16 nb forwarding cores=2 - nb forwarding ports=1 RX queues=1 - RX desc=128 - RX free threshold=0 RX threshold registers: pthresh=8 hthresh=8 wthresh=4 TX queues=1 - TX desc=512 - TX free threshold=0 TX threshold registers: pthresh=36 hthresh=0 wthresh=0 TX RS bit threshold=0 - TXQ flags=0x0 read rxd ~~~~~~~~ Display an RX descriptor for a port RX queue: read rxd (port_id) (queue_id) (rxd_id) For example: .. code-block:: console testpmd> read rxd 0 0 4 0x0000000B - 0x001D0180 / 0x0000000B - 0x001D0180 read txd ~~~~~~~~ Display a TX descriptor for a port TX queue: read txd (port_id) (queue_id) (txd_id) For example: .. code-block:: console testpmd> read txd 0 0 4 0x00000001 - 0x24C3C440 / 0x000F0000 - 0x2330003C Configuration Functions ----------------------- The testpmd application can be configured from the runtime as well as from the command-line. This section details the available configuration functions that are available. .. note:: Configuration changes only become active when forwarding is started/restarted. set default ~~~~~~~~~~~ Reset forwarding to the default configuration: set default set verbose ~~~~~~~~~~~ Set the debug verbosity level: set verbose (level) Currently the only available levels are 0 (silent except for error) and 1 (fully verbose). set nbport ~~~~~~~~~~ Set the number of ports used by the application: set nbport (num) This is equivalent to the --nb-ports command-line option. set nbcore ~~~~~~~~~~ Set the number of cores used by the application: set nbcore (num) This is equivalent to the --nb-cores command-line option. .. note:: The number of cores used must not be greater than number of ports used multiplied by the number of queues per port. set coremask ~~~~~~~~~~~~ Set the forwarding cores hexadecimal mask: set coremask (mask) This is equivalent to the --coremask command-line option. .. note:: The master lcore is reserved for command line parsing only and cannot be masked on for packet forwarding. set portmask ~~~~~~~~~~~~ Set the forwarding ports hexadecimal mask: set portmask (mask) This is equivalent to the --portmask command-line option. set burst ~~~~~~~~~ Set number of packets per burst: set burst (num) This is equivalent to the --burst command-line option. In mac_retry forwarding mode, the transmit delay time and number of retries can also be set. set burst tx delay (micrseconds) retry (num) set txpkts ~~~~~~~~~~ Set the length of each segment of the TX-ONLY packets: set txpkts (x[,y]*) Where x[,y]* represents a CSV list of values, without white space. set corelist ~~~~~~~~~~~~ Set the list of forwarding cores: set corelist (x[,y]*) For example, to change the forwarding cores: .. code-block:: console testpmd> set corelist 3,1 testpmd> show config fwd io packet forwarding - ports=2 - cores=2 - streams=2 - NUMA support disabled Logical Core 3 (socket 0) forwards packets on 1 streams: RX P=0/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:01 Logical Core 1 (socket 0) forwards packets on 1 streams: RX P=1/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00 .. note:: The cores are used in the same order as specified on the command line. set portlist ~~~~~~~~~~~~ Set the list of forwarding ports: set portlist (x[,y]*) For example, to change the port forwarding: .. code-block:: console testpmd> set portlist 0,2,1,3 testpmd> show config fwd io packet forwarding - ports=4 - cores=1 - streams=4 Logical Core 3 (socket 0) forwards packets on 4 streams: RX P=0/Q=0 (socket 0) -> TX P=2/Q=0 (socket 0) peer=02:00:00:00:00:01 RX P=2/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00 RX P=1/Q=0 (socket 0) -> TX P=3/Q=0 (socket 0) peer=02:00:00:00:00:03 RX P=3/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:02 vlan set strip ~~~~~~~~~~~~~~ Set the VLAN strip on a port: vlan set strip (on|off) (port_id) vlan set stripq ~~~~~~~~~~~~~~~ Set the VLAN strip for a queue on a port: vlan set stripq (on|off) (port_id,queue_id) vlan set filter ~~~~~~~~~~~~~~~ Set the VLAN filter on a port: vlan set filter (on|off) (port_id) vlan set qinq ~~~~~~~~~~~~~ Set the VLAN QinQ (extended queue in queue) on for a port: vlan set qinq (on|off) (port_id) vlan set tpid ~~~~~~~~~~~~~ Set the outer VLAN TPID for packet filtering on a port: vlan set tpid (value) (port_id) .. note:: TPID value must be a 16-bit number (value <= 65536). rx_vlan add ~~~~~~~~~~~ Add a VLAN ID, or all identifiers, to the set of VLAN identifiers filtered by port ID: rx_vlan add (vlan_id|all) (port_id) .. note:: VLAN filter must be set on that port. VLAN ID < 4096. Depending on the NIC used, number of vlan_ids may be limited to the maximum entries in VFTA table. This is important if enabling all vlan_ids. rx_vlan rm ~~~~~~~~~~ Remove a VLAN ID, or all identifiers, from the set of VLAN identifiers filtered by port ID: rx_vlan rm (vlan_id|all) (port_id) rx_vlan add(for VF) ~~~~~~~~~~~~~~~~~~~ Add a VLAN ID, to the set of VLAN identifiers filtered for VF(s) for port ID: rx_vlan add (vlan_id) port (port_id) vf (vf_mask) rx_vlan rm(for VF) ~~~~~~~~~~~~~~~~~~ Remove a VLAN ID, from the set of VLAN identifiers filtered for VF(s) for port ID: rx_vlan rm (vlan_id) port (port_id) vf (vf_mask) rx_vlan set tpid ~~~~~~~~~~~~~~~~ Set the outer VLAN TPID for packet filtering on a port: rx_vlan set tpid (value) (port_id) tunnel_filter add ~~~~~~~~~~~~~~~~~ Add a tunnel filter on a port: tunnel_filter add (port_id) (outer_mac) (inner_mac) (ip_addr) (inner_vlan) (tunnel_type) (filter_type) (tenant_id) (queue_id) tunnel_filter remove ~~~~~~~~~~~~~~~~~~~~ Remove a tunnel filter on a port: tunnel_filter rm (port_id) (outer_mac) (inner_mac) (ip_addr) (inner_vlan) (tunnel_type) (filter_type) (tenant_id) (queue_id) rx_vxlan_port add ~~~~~~~~~~~~~~~~~ Add an UDP port for VXLAN packet filter on a port: rx_vxlan_port add (udp_port) (port_id) rx_vxlan_port remove ~~~~~~~~~~~~~~~~~~~~ Remove an UDP port for VXLAN packet filter on a port: rx_vxlan_port rm (udp_port) (port_id) tx_vlan set ~~~~~~~~~~~ Set hardware insertion of VLAN IDs in packets sent on a port: tx_vlan set (port_id) vlan_id[, vlan_id_outer] .. code-block:: console Set a single VLAN ID (5) insertion on port 0. tx_vlan set 0 5 Set double VLAN ID (inner: 2, outer: 3) insertion on port 1. tx_vlan set 1 2 3 tx_vlan set pvid ~~~~~~~~~~~~~~~~ Set port based hardware insertion of VLAN ID in packets sent on a port: tx_vlan set pvid (port_id) (vlan_id) (on|off) tx_vlan reset ~~~~~~~~~~~~~ Disable hardware insertion of a VLAN header in packets sent on a port: tx_vlan reset (port_id) csum set ~~~~~~~~ Select hardware or software calculation of the checksum when transmitting a packet using the csum forward engine: csum set (ip|udp|tcp|sctp|outer-ip) (hw|sw) (port_id) - ip|udp|tcp|sctp always concern the inner layer. - outer-ip concerns the outer IP layer (only for IPv4) in case the packet is recognized as a tunnel packet by the forward engine (vxlan, gre and ipip are supported). See "csum parse-tunnel" command. .. note:: Check the NIC Datasheet for hardware limits. csum parse-tunnel ~~~~~~~~~~~~~~~~~ Define how tunneled packets should be handled by the csum forward engine. csum parse-tunnel (on|off) (tx_port_id) If enabled, the csum forward engine will try to recognize supported tunnel headers (vxlan, gre, ipip). If disabled, treat tunnel packets as non-tunneled packets (a inner header is handled as a packet payload). .. note:: The port argument is the TX port like in the "csum set" command. Example: Consider a packet as following: "eth_out/ipv4_out/udp_out/vxlan/eth_in/ipv4_in/tcp_in" - If parse-tunnel is enabled, the ip|udp|tcp|sctp parameters of "csum set" command are about inner headers (here ipv4_in and tcp_in), and the outer-ip parameter is about outer headers (here ipv4_out). - If parse-tunnel is disabled, the ip|udp|tcp|sctp parameters of "csum set" command are about outer headers, here ipv4_out and udp_out. csum show ~~~~~~~~~ Display tx checksum offload configuration: csum show (port_id) tso set ~~~~~~~ Enable TCP Segmentation Offload in csum forward engine: tso set (segsize) (port_id) .. note:: Check the NIC datasheet for hardware limits tso show ~~~~~~~~ Display the status of TCP Segmentation Offload: tso show (port_id) set fwd ~~~~~~~ Set the packet forwarding mode: set fwd (io|mac|mac_retry|macswap|flowgen|rxonly|txonly|csum|icmpecho) The available information categories are: * io: forwards packets "as-is" in I/O mode. This is the fastest possible forwarding operation as it does not access packets data. This is the default mode. * mac: changes the source and the destination Ethernet addresses of packets before forwarding them. * mac_retry: same as "mac" forwarding mode, but includes retries if the destination queue is full. * macswap: MAC swap forwarding mode. Swaps the source and the destination Ethernet addresses of packets before forwarding them. * flowgen: multi-flow generation mode. Originates a bunch of flows (varying destination IP addresses), and terminate receive traffic. * rxonly: receives packets but doesn't transmit them. * txonly: generates and transmits packets without receiving any. * csum: changes the checksum field with HW or SW methods depending on the offload flags on the packet. * icmpecho: receives a burst of packets, lookup for IMCP echo requests and, if any, send back ICMP echo replies. * ieee1588: demonstrate L2 IEEE1588 V2 PTP timestamping for RX and TX. Requires ``CONFIG_RTE_LIBRTE_IEEE1588=y``. Note: TX timestamping is only available in the "Full Featured" TX path. To force ``testpmd`` into this mode set ``--txqflags=0``. Example: .. code-block:: console testpmd> set fwd rxonly Set rxonly packet forwarding mode mac_addr add ~~~~~~~~~~~~ Add an alternative MAC address to a port: mac_addr add (port_id) (XX:XX:XX:XX:XX:XX) mac_addr remove ~~~~~~~~~~~~~~~ Remove a MAC address from a port: mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX) mac_addr add(for VF) ~~~~~~~~~~~~~~~~~~~~ Add an alternative MAC address for a VF to a port: mac_add add port (port_id) vf (vf_id) (XX:XX:XX:XX:XX:XX) set port-uta ~~~~~~~~~~~~ Set the unicast hash filter(s) on/off for a port X: set port (port_id) uta (XX:XX:XX:XX:XX:XX|all) (on|off) set promisc ~~~~~~~~~~~ Set the promiscuous mode on for a port or for all ports. In promiscuous mode packets are not dropped if they aren't for the specified MAC address: set promisc (port_id|all) (on|off) set allmulti ~~~~~~~~~~~~ Set the allmulti mode for a port or for all ports: set allmulti (port_id|all) (on|off) Same as the ifconfig (8) option. Controls how multicast packets are handled. set flow_ctrl rx ~~~~~~~~~~~~~~~~ Set the link flow control parameter on a port: set flow_ctrl rx (on|off) tx (on|off) (high_water) (low_water) \ (pause_time) (send_xon) (port_id) Where: high_water (integer): High threshold value to trigger XOFF. low_water (integer) : Low threshold value to trigger XON. pause_time (integer): Pause quota in the Pause frame. send_xon (0/1) : Send XON frame. mac_ctrl_frame_fwd : Enable receiving MAC control frames set pfc_ctrl rx ~~~~~~~~~~~~~~~ Set the priority flow control parameter on a port: set pfc_ctrl rx (on|off) tx (on|off) (high_water) (low_water) \ (pause_time) (priority) (port_id) Where: priority (0-7): VLAN User Priority. set stat_qmap ~~~~~~~~~~~~~ Set statistics mapping (qmapping 0..15) for RX/TX queue on port: set stat_qmap (tx|rx) (port_id) (queue_id) (qmapping) For example, to set rx queue 2 on port 0 to mapping 5: .. code-block:: console testpmd>set stat_qmap rx 0 2 5 set port - rx/tx(for VF) ~~~~~~~~~~~~~~~~~~~~~~~~ Set VF receive/transmit from a port: set port (port_id) vf (vf_id) (rx|tx) (on|off) set port - mac address filter (for VF) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Add/Remove unicast or multicast MAC addr filter for a VF: set port (port_id) vf (vf_id) (mac_addr) (exact-mac|exact-mac-vlan|hashmac|hashmac-vlan) (on|off) set port - rx mode(for VF) ~~~~~~~~~~~~~~~~~~~~~~~~~~ Set the VF receive mode of a port: set port (port_id) vf (vf_id) rxmode (AUPE|ROPE|BAM|MPE) (on|off) The available receive modes are: * AUPE: accepts untagged VLAN. * ROPE: accepts unicast hash. * BAM: accepts broadcast packets * MPE: accepts all multicast packets set port - tx_rate (for Queue) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set TX rate limitation for queue of a port ID: set port (port_id) queue (queue_id) rate (rate_value) set port - tx_rate (for VF) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set TX rate limitation for queues in VF of a port ID: set port (port_id) vf (vf_id) rate (rate_value) queue_mask (queue_mask) set port - mirror rule ~~~~~~~~~~~~~~~~~~~~~~ Set pool or vlan type mirror rule for a port: set port (port_id) mirror-rule (rule_id) (pool-mirror-up|pool-mirror-down|vlan-mirror) (poolmask|vlanid[,vlanid]*) dst-pool (pool_id) (on|off) Set link mirror rule for a port: set port (port_id) mirror-rule (rule_id) (uplink-mirror|downlink-mirror) dst-pool (pool_id) (on|off) For example to enable mirror traffic with vlan 0,1 to pool 0: .. code-block:: console set port 0 mirror-rule 0 vlan-mirror 0,1 dst-pool 0 on reset port - mirror rule ~~~~~~~~~~~~~~~~~~~~~~~~ Reset a mirror rule for a port. reset port (port_id) mirror-rule (rule_id) set flush_rx ~~~~~~~~~~~~ Flush (default) or don't flush RX streams before forwarding. Mainly used with PCAP drivers to avoid the default behavior of flushing the first 512 packets on RX streams. set flush_rx off set bypass mode ~~~~~~~~~~~~~~~ Set the bypass mode for the lowest port on bypass enabled NIC. set bypass mode (normal|bypass|isolate) (port_id) set bypass event ~~~~~~~~~~~~~~~~ Set the event required to initiate specified bypass mode for the lowest port on a bypass enabled NIC where: * timeout: enable bypass after watchdog timeout. * os_on: enable bypass when OS/board is powered on. * os_off: enable bypass when OS/board is powered off. * power_on: enable bypass when power supply is turned on. * power_off: enable bypass when power supply is turned off. set bypass event (timeout|os_on|os_off|power_on|power_off) mode (normal|bypass|isolate) (port_id) set bypass timeout ~~~~~~~~~~~~~~~~~~ Set the bypass watchdog timeout to 'n' seconds where 0 = instant. set bypass timeout (0|1.5|2|3|4|8|16|32) show bypass config ~~~~~~~~~~~~~~~~~~ Show the bypass configuration for a bypass enabled NIC using the lowest port on the NIC. show bypass config (port_id) set link up ~~~~~~~~~~~ Set link up for a port. set link-up port (port id) set link down ~~~~~~~~~~~~~ Set link down for a port. set link-down port (port id) Port Functions -------------- The following sections show functions for configuring ports. .. note:: Port configuration changes only become active when forwarding is started/restarted. port attach ~~~~~~~~~~~ Attach a port specified by pci address or virtual device args. To attach a new pci device, the device should be recognized by kernel first. Then it should be moved under DPDK management. Finally the port can be attached to testpmd. For example, to move a pci device using ixgbe under DPDK management: .. code-block:: console ./tools/dpdk_nic_bind.py --status Network devices using DPDK-compatible driver ============================================ Network devices using kernel driver =================================== 0000:0a:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth2 drv=ixgbe unused= ./tools/dpdk_nic_bind.py -b igb_uio 0000:0a:00.0 ./tools/dpdk_nic_bind.py --status Network devices using DPDK-compatible driver ============================================ 0000:0a:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused= To attach a port created by virtual device, above steps are not needed. port attach (identifier) For example, to attach a port whose pci address is 0000:0a:00.0. .. code-block:: console testpmd> port attach 0000:0a:00.0 Attaching a new port... EAL: PCI device 0000:0a:00.0 on NUMA socket -1 EAL: probe driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory mapped at 0x7f83bfa00000 EAL: PCI memory mapped at 0x7f83bfa80000 PMD: eth_ixgbe_dev_init(): MAC: 2, PHY: 18, SFP+: 5 PMD: eth_ixgbe_dev_init(): port 0 vendorID=0x8086 deviceID=0x10fb Port 0 is attached. Now total ports is 1 Done testpmd> For example, to attach a port created by pcap PMD. .. code-block:: console testpmd> port attach eth_pcap0 Attaching a new port... PMD: Initializing pmd_pcap for eth_pcap0 PMD: Creating pcap-backed ethdev on numa socket 0 Port 0 is attached. Now total ports is 1 Done testpmd> In this case, identifier is "eth_pcap0". This identifier format is the same as "--vdev" format of DPDK applications. For example, to re-attach a bonded port which has been previously detached, the mode and slave parameters must be given. .. code-block:: console testpmd> port attach eth_bond_testpmd_0,mode=0,slave=1 Attaching a new port... EAL: Initializing pmd_bond for eth_bond_testpmd_0 EAL: Create bonded device eth_bond_testpmd_0 on port 0 in mode 0 on socket 0. Port 0 is attached. Now total ports is 1 Done port detach ~~~~~~~~~~~ Detach a specific port. Before detaching a port, the port should be closed. port detach (port_id) For example, to detach a pci device port 0. .. code-block:: console testpmd> port close 0 Closing ports... Done testpmd> port detach 0 Detaching a port... EAL: PCI device 0000:0a:00.0 on NUMA socket -1 EAL: remove driver: 8086:10fb rte_ixgbe_pmd EAL: PCI memory unmapped at 0x7f83bfa00000 EAL: PCI memory unmapped at 0x7f83bfa80000 Done testpmd> For example, to detach a virtual device port 0. .. code-block:: console testpmd> port close 0 Closing ports... Done testpmd> port detach 0 Detaching a port... PMD: Closing pcap ethdev on numa socket 0 Port 'eth_pcap0' is detached. Now total ports is 0 Done testpmd> To remove a pci device completely from the system, first detach the port from testpmd. Then the device should be moved under kernel management. Finally the device can be removed using kernel pci hotplug functionality. For example, to move a pci device under kernel management: .. code-block:: console ./tools/dpdk_nic_bind.py -b ixgbe 0000:0a:00.0 ./tools/dpdk_nic_bind.py --status Network devices using DPDK-compatible driver ============================================ Network devices using kernel driver =================================== 0000:0a:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth2 drv=ixgbe unused=igb_uio To remove a port created by a virtual device, above steps are not needed. port start ~~~~~~~~~~ Start all ports or a specific port: port start (port_id|all) port stop ~~~~~~~~~ Stop all ports or a specific port: port stop (port_id|all) port close ~~~~~~~~~~ Close all ports or a specific port: port close (port_id|all) port start/stop queue ~~~~~~~~~~~~~~~~~~~~~ Start/stop a rx/tx queue on a specific port: port (port_id) (rxq|txq) (queue_id) (start|stop) Only take effect when port is started. port config - speed ~~~~~~~~~~~~~~~~~~~ Set the speed and duplex mode for all ports or a specific port: port config (port_id|all) speed (10|100|1000|10000|auto) duplex (half|full|auto) port config - queues/descriptors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set number of queues/descriptors for rxq, txq, rxd and txd: port config all (rxq|txq|rxd|txd) (value) This is equivalent to the --rxq, --txq, --rxd and --txd command-line options. port config - max-pkt-len ~~~~~~~~~~~~~~~~~~~~~~~~~ Set the maximum packet length: port config all max-pkt-len (value) This is equivalent to the --max-pkt-len command-line option. port config - CRC Strip ~~~~~~~~~~~~~~~~~~~~~~~ Set hardware CRC stripping on or off for all ports: port config all crc-strip (on|off) CRC stripping is off by default. The on option is equivalent to the --crc-strip command-line option. port config - RX Checksum ~~~~~~~~~~~~~~~~~~~~~~~~~ Set hardware RX checksum offload to on or off for all ports: port config all rx-cksum (on|off) Checksum offload is off by default. The on option is equivalent to the --enable-rx-cksum command-line option. port config - VLAN ~~~~~~~~~~~~~~~~~~ Set hardware VLAN on or off for all ports: port config all hw-vlan (on|off) Hardware VLAN is on by default. The off option is equivalent to the --disable-hw-vlan command-line option. port config - VLAN filter ~~~~~~~~~~~~~~~~~~~~~~~~~ Set hardware VLAN filter on or off for all ports: port config all hw-vlan-filter (on|off) Hardware VLAN filter is on by default. The off option is equivalent to the --disable-hw-vlan-filter command-line option. port config - VLAN strip ~~~~~~~~~~~~~~~~~~~~~~~~ Set hardware VLAN strip on or off for all ports: port config all hw-vlan-strip (on|off) Hardware VLAN strip is on by default. The off option is equivalent to the --disable-hw-vlan-strip command-line option. port config - VLAN extend ~~~~~~~~~~~~~~~~~~~~~~~~~ Set hardware VLAN extend on or off for all ports: port config all hw-vlan-extend (on|off) Hardware VLAN extend is off by default. The off option is equivalent to the --disable-hw-vlan-extend command-line option. port config - Drop Packets ~~~~~~~~~~~~~~~~~~~~~~~~~~ Set packet drop for packets with no descriptors on or off for all ports: port config all drop-en (on|off) Packet dropping for packets with no descriptors is off by default. The on option is equivalent to the --enable-drop-en command-line option. port config - RSS ~~~~~~~~~~~~~~~~~ Set the RSS (Receive Side Scaling) mode on or off: port config all rss (all|ip|tcp|udp|sctp|ether|none) RSS is on by default. The off option is equivalent to the --disable-rss command-line option. port config - RSS Reta ~~~~~~~~~~~~~~~~~~~~~~ Set the RSS (Receive Side Scaling) redirection table: port config all rss reta (hash,queue)[,(hash,queue)] port config - DCB ~~~~~~~~~~~~~~~~~ Set the DCB mode for an individual port: port config (port_id) dcb vt (on|off) (traffic_class) pfc (on|off) The traffic class should be 4 or 8. port config - Burst ~~~~~~~~~~~~~~~~~~~ Set the number of packets per burst: port config all burst (value) This is equivalent to the --burst command-line option. port config - Threshold ~~~~~~~~~~~~~~~~~~~~~~~ Set thresholds for TX/RX queues: port config all (threshold) (value) Where the threshold type can be: * txpt: Set the prefetch threshold register of the TX rings, 0 <= value <= 255. * txht: Set the host threshold register of the TX rings, 0 <= value <= 255. * txwt: Set the write-back threshold register of the TX rings, 0 <= value <= 255. * rxpt: Set the prefetch threshold register of the RX rings, 0 <= value <= 255. * rxht: Set the host threshold register of the RX rings, 0 <= value <= 255. * rxwt: Set the write-back threshold register of the RX rings, 0 <= value <= 255. * txfreet: Set the transmit free threshold of the TX rings, 0 <= value <= txd. * rxfreet: Set the transmit free threshold of the RX rings, 0 <= value <= rxd. * txrst: Set the transmit RS bit threshold of TX rings, 0 <= value <= txd. These threshold options are also available from the command-line. Link Bonding Functions ---------------------- The Link Bonding functions make it possible to dynamically create and manage link bonding devices from within testpmd interactive prompt. create bonded device ~~~~~~~~~~~~~~~~~~~~ Create a new bonding device: create bonded device (mode) (socket) For example, to create a bonded device in mode 1 on socket 0. .. code-block:: console testpmd> create bonded 1 0 created new bonded device (port X) add bonding slave ~~~~~~~~~~~~~~~~~ Adds Ethernet device to a Link Bonding device: add bonding slave (slave id) (port id) For example, to add Ethernet device (port 6) to a Link Bonding device (port 10). .. code-block:: console testpmd> add bonding slave 6 10 remove bonding slave ~~~~~~~~~~~~~~~~~~~~ Removes an Ethernet slave device from a Link Bonding device: remove bonding slave (slave id) (port id) For example, to remove Ethernet slave device (port 6) to a Link Bonding device (port 10). .. code-block:: console testpmd> remove bonding slave 6 10 set bonding mode ~~~~~~~~~~~~~~~~ Set the Link Bonding mode of a Link Bonding device: set bonding mode (value) (port id) For example, to set the bonding mode of a Link Bonding device (port 10) to broadcast (mode 3). .. code-block:: console testpmd> set bonding mode 3 10 set bonding primary ~~~~~~~~~~~~~~~~~~~ Set an Ethernet slave device as the primary device on a Link Bonding device: set bonding primary (slave id) (port id) For example, to set the Ethernet slave device (port 6) as the primary port of a Link Bonding device (port 10). .. code-block:: console testpmd> set bonding primary 6 10 set bonding mac ~~~~~~~~~~~~~~~ Set the MAC address of a Link Bonding device: set bonding mac (port id) (mac) For example, to set the MAC address of a Link Bonding device (port 10) to 00:00:00:00:00:01 .. code-block:: console testpmd> set bonding mac 10 00:00:00:00:00:01 set bonding xmit_balance_policy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set the transmission policy for a Link Bonding device when it is in Balance XOR mode: set bonding xmit_balance_policy (port_id) (l2|l23|l34) For example, set a Link Bonding device (port 10) to use a balance policy of layer 3+4 (IP addresses & UDP ports ) .. code-block:: console testpmd> set bonding xmit_balance_policy 10 l34 set bonding mon_period ~~~~~~~~~~~~~~~~~~~~~~ Set the link status monitoring polling period in milliseconds for a bonding device. This adds support for PMD slave devices which do not support link status interrupts. When the mon_period is set to a value greater than 0 then all PMD's which do not support link status ISR will be queried every polling interval to check if their link status has changed. set bonding mon_period (port_id) (value) For example, to set the link status monitoring polling period of bonded device (port 5) to 150ms .. code-block:: console testpmd> set bonding mon_period 5 150 show bonding config ~~~~~~~~~~~~~~~~~~~ Show the current configuration of a Link Bonding device: show bonding config (port id) For example, to show the configuration a Link Bonding device (port 9) with 3 slave devices (1, 3, 4) in balance mode with a transmission policy of layer 2+3. .. code-block:: console testpmd> show bonding config 9 Bonding mode: 2 Balance Xmit Policy: BALANCE_XMIT_POLICY_LAYER23 Slaves (3): [1 3 4] Active Slaves (3): [1 3 4] Primary: [3] Register Functions ------------------ The Register functions can be used to read from and write to registers on the network card referenced by a port number. This is mainly useful for debugging purposes. Reference should be made to the appropriate datasheet for the network card for details on the register addresses and fields that can be accessed. read reg ~~~~~~~~ Display the value of a port register: read reg (port_id) (address) For example, to examine the Flow Director control register (FDIRCTL, 0x0000EE000) on an Intel® 82599 10 GbE Controller: .. code-block:: console testpmd> read reg 0 0xEE00 port 0 PCI register at offset 0xEE00: 0x4A060029 (1241907241) read regfield ~~~~~~~~~~~~~ Display a port register bit field: read regfield (port_id) (address) (bit_x) (bit_y) For example, reading the lowest two bits from the register in the example above: .. code-block:: console testpmd> read regfield 0 0xEE00 0 1 port 0 PCI register at offset 0xEE00: bits[0, 1]=0x1 (1) read regbit ~~~~~~~~~~~ Display a single port register bit: read regbit (port_id) (address) (bit_x) For example, reading the lowest bit from the register in the example above: .. code-block:: console testpmd> read regbit 0 0xEE00 0 port 0 PCI register at offset 0xEE00: bit 0=1 write reg ~~~~~~~~~ Set the value of a port register: write reg (port_id) (address) (value) For example, to clear a register: .. code-block:: console testpmd> write reg 0 0xEE00 0x0 port 0 PCI register at offset 0xEE00: 0x00000000 (0) write regfield ~~~~~~~~~~~~~~ Set bit field of a port register: write regfield (port_id) (address) (bit_x) (bit_y) (value) For example, writing to the register cleared in the example above: .. code-block:: console testpmd> write regfield 0 0xEE00 0 1 2 port 0 PCI register at offset 0xEE00: 0x00000002 (2) write regbit ~~~~~~~~~~~~ Set single bit value of a port register: write regbit (port_id) (address) (bit_x) (value) For example, to set the high bit in the register from the example above: .. code-block:: console testpmd> write regbit 0 0xEE00 31 1 port 0 PCI register at offset 0xEE00: 0x8000000A (2147483658) Filter Functions ---------------- This section details the available filter functions that are available. ethertype_filter ~~~~~~~~~~~~~~~~~~~~ Add or delete a L2 Ethertype filter, which identify packets by their L2 Ethertype mainly assign them to a receive queue. ethertype_filter (port_id) (add|del) (mac_addr|mac_ignr) (mac_address) ethertype (ether_type) (drop|fwd) queue (queue_id) The available information parameters are: * port_id: the port which the Ethertype filter assigned on. * mac_addr: compare destination mac address. * mac_ignr: ignore destination mac address match. * mac_address: destination mac address to match. * ether_type: the EtherType value want to match, for example 0x0806 for ARP packet. 0x0800 (IPv4) and 0x86DD (IPv6) are invalid. * queue_id : The receive queue associated with this EtherType filter. It is meaningless when deleting or dropping. Example, to add/remove an ethertype filter rule: .. code-block:: console testpmd> ethertype_filter 0 add mac_ignr ethertype 0x0806 fwd queue 3 testpmd> ethertype_filter 0 del mac_ignr ethertype 0x0806 fwd queue 3 2tuple_filter ~~~~~~~~~~~~~~~~~ Add or delete a 2-tuple filter, which identify packets by specific protocol and destination TCP/UDP port and forwards packets into one of the receive queues. 2tuple_filter (port_id) (add|del) dst_port (dst_port_value) protocol (protocol_value) mask (mask_value) tcp_flags (tcp_flags_value) priority (prio_value) queue (queue_id) The available information parameters are: * port_id: the port which the 2-tuple filter assigned on. * dst_port_value: destination port in L4. * protocol_value: IP L4 protocol. * mask_value: participates in the match or not by bit for field above, 1b means participate. * tcp_flags_value: TCP control bits. The non-zero value is invalid, when the pro_value is not set to 0x06 (TCP). * prio_value: priority of this filter. * queue_id: The receive queue associated with this 2-tuple filter. Example, to add/remove an 2tuple filter rule: .. code-block:: console testpmd> 2tuple_filter 0 add dst_port 32 protocol 0x06 mask 0x03 tcp_flags 0x02 priority 3 queue 3 testpmd> 2tuple_filter 0 del dst_port 32 protocol 0x06 mask 0x03 tcp_flags 0x02 priority 3 queue 3 5tuple_filter ~~~~~~~~~~~~~~~~~ Add or delete a 5-tuple filter, which consists of a 5-tuple (protocol, source and destination IP addresses, source and destination TCP/UDP/SCTP port) and routes packets into one of the receive queues. 5tuple_filter (port_id) (add|del) dst_ip (dst_address) src_ip (src_address) dst_port (dst_port_value) src_port (src_port_value) protocol (protocol_value) mask (mask_value) tcp_flags (tcp_flags_value) priority (prio_value) queue (queue_id) The available information parameters are: * port_id: the port which the 5-tuple filter assigned on. * dst_address: destination IP address. * src_address: source IP address. * dst_port_value: TCP/UDP destination port. * src_port_value: TCP/UDP source port. * protocol_value: L4 protocol. * mask_value: participates in the match or not by bit for field above, 1b means participate * tcp_flags_value: TCP control bits. The non-zero value is invalid, when the protocol_value is not set to 0x06 (TCP). * prio_value: the priority of this filter. * queue_id: The receive queue associated with this 5-tuple filter. Example, to add/remove an 5tuple filter rule: .. code-block:: console testpmd> 5tuple_filter 0 add dst_ip 2.2.2.5 src_ip 2.2.2.4 dst_port 64 src_port 32 protocol 0x06 mask 0x1F flags 0x0 priority 3 queue 3 testpmd> 5tuple_filter 0 del dst_ip 2.2.2.5 src_ip 2.2.2.4 dst_port 64 src_port 32 protocol 0x06 mask 0x1F flags 0x0 priority 3 queue 3 syn_filter ~~~~~~~~~~~~~~ By SYN filter, TCP packets whose *SYN* flag is set can be forwarded to a separate queue. syn_filter (port_id) (add|del) priority (high|low) queue (queue_id) The available information parameters are: * port_id: the port which the SYN filter assigned on. * high: this SYN filter has higher priority than other filters. * low: this SYN filter has lower priority than other filters. * queue_id: The receive queue associated with this SYN filter Example: .. code-block:: console testpmd> syn_filter 0 add priority high queue 3 flex_filter ~~~~~~~~~~~ With flex filter, packets can be recognized by any arbitrary pattern within the first 128 bytes of the packet and routes packets into one of the receive queues. flex_filter (port_id) (add|del) len (len_value) bytes (bytes_value) mask (mask_value) priority (prio_value) queue (queue_id) The available information parameters are: * port_id: the port which the Flex filter is assigned on. * len_value: filter length in bytes, no greater than 128. * bytes_value: a string in hexadecimal, means the value the flex filter needs to match. * mask_value: a string in hexadecimal, bit 1 means corresponding byte participates in the match. * prio_value: the priority of this filter. * queue_id: the receive queue associated with this Flex filter. Example: .. code-block:: console testpmd> flex_filter 0 add len 16 bytes 0x00000000000000000000000008060000 mask 000C priority 3 queue 3 testpmd> flex_filter 0 del len 16 bytes 0x00000000000000000000000008060000 mask 000C priority 3 queue 3 flow_director_filter ~~~~~~~~~~~~~~~~~~~~ The Flow Director works in receive mode to identify specific flows or sets of flows and route them to specific queues. Two types of filtering are supported which are referred to as Perfect Match and Signature filters, the match mode is set by the --pkt-filter-mode command-line parameter: * Perfect match filters. The hardware checks a match between the masked fields of the received packets and the programmed filters. * Signature filters. The hardware checks a match between a hash-based signature of the masked fields of the received packet. The Flow Director filters can match the different fields for different type of packet: flow type, specific input set per flow type and the flexible payload. The Flow Director can also mask out parts of all of these fields so that filters are only applied to certain fields or parts of the fields. Different NICs may have different capabilities, command show port fdir (port_id) can be used to acquire the information. # Commands to add flow director filters of different flow types. flow_director_filter (port_id) (add|del|update) flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag) src (src_ip_address) dst (dst_ip_address) vlan (vlan_value) flexbytes (flexbytes_value) (drop|fwd) queue (queue_id) fd_id (fd_id_value) flow_director_filter (port_id) (add|del|update) flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp) src (src_ip_address) (src_port) dst (dst_ip_address) (dst_port) vlan (vlan_value) flexbytes (flexbytes_value) (drop|fwd) queue (queue_id) fd_id (fd_id_value) flow_director_filter (port_id) (add|del|update) flow (ipv4-sctp|ipv6-sctp) src (src_ip_address) (src_port) dst (dst_ip_address) (dst_port) tag (verification_tag) vlan (vlan_value) flexbytes (flexbytes_value) (drop|fwd) queue (queue_id) fd_id (fd_id_value) flow_director_filter (port_id) (add|del|update) flow l2_payload ether (ethertype) flexbytes (flexbytes_value) (drop|fwd) queue (queue_id) fd_id (fd_id_value) For example, to add an ipv4-udp flow type filter: .. code-block:: console testpmd> flow_director_filter 0 add flow ipv4-udp src 2.2.2.3 32 dst 2.2.2.5 33 vlan 0x1 flexbytes (0x88,0x48) fwd queue 1 fd_id 1 For example, add an ipv4-other flow type filter: .. code-block:: console testpmd> flow_director_filter 0 add flow ipv4-other src 2.2.2.3 dst 2.2.2.5 vlan 0x1 flexbytes (0x88,0x48) fwd queue 1 fd_id 1 flush_flow_director ~~~~~~~~~~~~~~~~~~~ flush all flow director filters on a device: flush_flow_director (port_id) Example, to flush all flow director filter on port 0: .. code-block:: console testpmd> flush_flow_director 0 flow_director_mask ~~~~~~~~~~~~~~~~~~ set flow director's masks on match input set flow_director_mask (port_id) vlan (vlan_value) src_mask (ipv4_src) (ipv6_src) (src_port) dst_mask (ipv4_dst) (ipv6_dst) (dst_port) Example, to set flow director mask on port 0: .. code-block:: console testpmd> flow_director_mask 0 vlan 0xefff src_mask 255.255.255.255 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 0xFFFF dst_mask 255.255.255.255 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF 0xFFFF flow_director_flex_mask ~~~~~~~~~~~~~~~~~~~~~~~ set masks of flow director's flexible payload based on certain flow type: flow_director_flex_mask (port_id) flow (none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload|all) (mask) Example, to set flow director's flex mask for all flow type on port 0: .. code-block:: console testpmd> flow_director_flex_mask 0 flow all (0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0) flow_director_flex_payload ~~~~~~~~~~~~~~~~~~~~~~~~~~ Configure flexible payload selection. flow_director_flex_payload (port_id) (raw|l2|l3|l4) (config) For example, to select the first 16 bytes from the offset 4 (bytes) of packet's payload as flexible payload. .. code-block:: console testpmd> flow_director_flex_payload 0 l4 (4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) get_sym_hash_ena_per_port ~~~~~~~~~~~~~~~~~~~~~~~~~ Get symmetric hash enable configuration per port. get_sym_hash_ena_per_port (port_id) For example, to get symmetric hash enable configuration of port 1. .. code-block:: console testpmd> get_sym_hash_ena_per_port 1 set_sym_hash_ena_per_port ~~~~~~~~~~~~~~~~~~~~~~~~~ Set symmetric hash enable configuration per port to enable or disable. set_sym_hash_ena_per_port (port_id) (enable|disable) For example, to set symmetric hash enable configuration of port 1 to enable. .. code-block:: console testpmd> set_sym_hash_ena_per_port 1 enable get_hash_global_config ~~~~~~~~~~~~~~~~~~~~~~ Get the global configurations of hash filters. get_hash_global_config (port_id) For example, to get the global configurations of hash filters of port 1. .. code-block:: console testpmd> get_hash_global_config 1 set_hash_global_config ~~~~~~~~~~~~~~~~~~~~~~ Set the global configurations of hash filters. set_hash_global_config (port_id) (toeplitz|simple_xor|default) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload) (enable|disable) For example, to enable simple_xor for flow type of ipv6 on port 2. .. code-block:: console testpmd> set_hash_global_config 2 simple_xor ipv6 enable ================================================ FILE: doc/guides/xen/index.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Xen Guide ========= |today| **Contents** .. toctree:: :maxdepth: 2 :numbered: pkt_switch ================================================ FILE: doc/guides/xen/pkt_switch.rst ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DPDK Xen Based Packet-Switching Solution ======================================== Introduction ------------ DPDK provides a para-virtualization packet switching solution, based on the Xen hypervisor's Grant Table, Note 1, which provides simple and fast packet switching capability between guest domains and host domain based on MAC address or VLAN tag. This solution is comprised of two components; a Poll Mode Driver (PMD) as the front end in the guest domain and a switching back end in the host domain. XenStore is used to exchange configure information between the PMD front end and switching back end, including grant reference IDs for shared Virtio RX/TX rings, MAC address, device state, and so on. XenStore is an information storage space shared between domains, see further information on XenStore below. The front end PMD can be found in the DPDK directory lib/ librte_pmd_xenvirt and back end example in examples/vhost_xen. The PMD front end and switching back end use shared Virtio RX/TX rings as para- virtualized interface. The Virtio ring is created by the front end, and Grant table references for the ring are passed to host. The switching back end maps those grant table references and creates shared rings in a mapped address space. The following diagram describes the functionality of the DPDK Xen Packet- Switching Solution. .. _figure_dpdk_xen_pkt_switch: .. figure:: img/dpdk_xen_pkt_switch.* Functionality of the DPDK Xen Packet Switching Solution. Note 1 The Xen hypervisor uses a mechanism called a Grant Table to share memory between domains (`http://wiki.xen.org/wiki/Grant Table `_). A diagram of the design is shown below, where "gva" is the Guest Virtual Address, which is the data pointer of the mbuf, and "hva" is the Host Virtual Address: .. _figure_grant_table: .. figure:: img/grant_table.* DPDK Xen Layout In this design, a Virtio ring is used as a para-virtualized interface for better performance over a Xen private ring when packet switching to and from a VM. The additional performance is gained by avoiding a system call and memory map in each memory copy with a XEN private ring. Device Creation --------------- Poll Mode Driver Front End ~~~~~~~~~~~~~~~~~~~~~~~~~~ * Mbuf pool allocation: To use a Xen switching solution, the DPDK application should use rte_mempool_gntalloc_create() to reserve mbuf pools during initialization. rte_mempool_gntalloc_create() creates a mempool with objects from memory allocated and managed via gntalloc/gntdev. The DPDK now supports construction of mempools from allocated virtual memory through the rte_mempool_xmem_create() API. This front end constructs mempools based on memory allocated through the xen_gntalloc driver. rte_mempool_gntalloc_create() allocates Grant pages, maps them to continuous virtual address space, and calls rte_mempool_xmem_create() to build mempools. The Grant IDs for all Grant pages are passed to the host through XenStore. * Virtio Ring Creation: The Virtio queue size is defined as 256 by default in the VQ_DESC_NUM macro. Using the queue setup function, Grant pages are allocated based on ring size and are mapped to continuous virtual address space to form the Virtio ring. Normally, one ring is comprised of several pages. Their Grant IDs are passed to the host through XenStore. There is no requirement that this memory be physically continuous. * Interrupt and Kick: There are no interrupts in DPDK Xen Switching as both front and back ends work in polling mode. There is no requirement for notification. * Feature Negotiation: Currently, feature negotiation through XenStore is not supported. * Packet Reception & Transmission: With mempools and Virtio rings created, the front end can operate Virtio devices, as it does in Virtio PMD for KVM Virtio devices with the exception that the host does not require notifications or deal with interrupts. XenStore is a database that stores guest and host information in the form of (key, value) pairs. The following is an example of the information generated during the startup of the front end PMD in a guest VM (domain ID 1): .. code-block:: console xenstore -ls /local/domain/1/control/dpdk 0_mempool_gref="3042,3043,3044,3045" 0_mempool_va="0x7fcbc6881000" 0_tx_vring_gref="3049" 0_rx_vring_gref="3053" 0_ether_addr="4e:0b:d0:4e:aa:f1" 0_vring_flag="3054" ... Multiple mempools and multiple Virtios may exist in the guest domain, the first number is the index, starting from zero. The idx#_mempool_va stores the guest virtual address for mempool idx#. The idx#_ether_adder stores the MAC address of the guest Virtio device. For idx#_rx_ring_gref, idx#_tx_ring_gref, and idx#_mempool_gref, the value is a list of Grant references. Take idx#_mempool_gref node for example, the host maps those Grant references to a continuous virtual address space. The real Grant reference information is stored in this virtual address space, where (gref, pfn) pairs follow each other with -1 as the terminator. .. _figure_grant_refs: .. figure:: img/grant_refs.* Mapping Grant references to a continuous virtual address space After all gref# IDs are retrieved, the host maps them to a continuous virtual address space. With the guest mempool virtual address, the host establishes 1:1 address mapping. With multiple guest mempools, the host establishes multiple address translation regions. Switching Back End ~~~~~~~~~~~~~~~~~~ The switching back end monitors changes in XenStore. When the back end detects that a new Virtio device has been created in a guest domain, it will: #. Retrieve Grant and configuration information from XenStore. #. Map and create a Virtio ring. #. Map mempools in the host and establish address translation between the guest address and host address. #. Select a free VMDQ pool, set its affinity with the Virtio device, and set the MAC/ VLAN filter. Packet Reception ~~~~~~~~~~~~~~~~ When packets arrive from an external network, the MAC?VLAN filter classifies packets into queues in one VMDQ pool. As each pool is bonded to a Virtio device in some guest domain, the switching back end will: #. Fetch an available entry from the Virtio RX ring. #. Get gva, and translate it to hva. #. Copy the contents of the packet to the memory buffer pointed to by gva. The DPDK application in the guest domain, based on the PMD front end, is polling the shared Virtio RX ring for available packets and receives them on arrival. Packet Transmission ~~~~~~~~~~~~~~~~~~~ When a Virtio device in one guest domain is to transmit a packet, it puts the virtual address of the packet's data area into the shared Virtio TX ring. The packet switching back end is continuously polling the Virtio TX ring. When new packets are available for transmission from a guest, it will: #. Fetch an available entry from the Virtio TX ring. #. Get gva, and translate it to hva. #. Copy the packet from hva to the host mbuf's data area. #. Compare the destination MAC address with all the MAC addresses of the Virtio devices it manages. If a match exists, it directly copies the packet to the matched VIrtio RX ring. Otherwise, it sends the packet out through hardware. .. note:: The packet switching back end is for demonstration purposes only. The user could implement their switching logic based on this example. In this example, only one physical port on the host is supported. Multiple segments are not supported. The biggest mbuf supported is 4KB. When the back end is restarted, all front ends must also be restarted. Running the Application ----------------------- The following describes the steps required to run the application. Validated Environment ~~~~~~~~~~~~~~~~~~~~~ Host: Xen-hypervisor: 4.2.2 Distribution: Fedora release 18 Kernel: 3.10.0 Xen development package (including Xen, Xen-libs, xen-devel): 4.2.3 Guest: Distribution: Fedora 16 and 18 Kernel: 3.6.11 Xen Host Prerequisites ~~~~~~~~~~~~~~~~~~~~~~ Note that the following commands might not be the same on different Linux* distributions. * Install xen-devel package: .. code-block:: console yum install xen-devel.x86_64 * Start xend if not already started: .. code-block:: console /etc/init.d/xend start * Mount xenfs if not already mounted: .. code-block:: console mount -t xenfs none /proc/xen * Enlarge the limit for xen_gntdev driver: .. code-block:: console modprobe -r xen_gntdev modprobe xen_gntdev limit=1000000 .. note:: The default limit for earlier versions of the xen_gntdev driver is 1024. That is insufficient to support the mapping of multiple Virtio devices into multiple VMs, so it is necessary to enlarge the limit by reloading this module. The default limit of recent versions of xen_gntdev is 1048576. The rough calculation of this limit is: limit=nb_mbuf# * VM#. In DPDK examples, nb_mbuf# is normally 8192. Building and Running the Switching Backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #. Edit config/common_linuxapp, and change the default configuration value for the following two items: .. code-block:: console CONFIG_RTE_LIBRTE_XEN_DOM0=y CONFIG RTE_LIBRTE_PMD_XENVIRT=n #. Build the target: .. code-block:: console make install T=x86_64-native-linuxapp-gcc #. Ensure that RTE_SDK and RTE_TARGET are correctly set. Build the switching example: .. code-block:: console make -C examples/vhost_xen/ #. Load the Xen DPDK memory management module and preallocate memory: .. code-block:: console insmod ./x86_64-native-linuxapp-gcc/build/lib/librte_eal/linuxapp/xen_dom0/rte_dom0_mm.ko echo 2048> /sys/kernel/mm/dom0-mm/memsize-mB/memsize .. note:: On Xen Dom0, there is no hugepage support. Under Xen Dom0, the DPDK uses a special memory management kernel module to allocate chunks of physically continuous memory. Refer to the *DPDK Getting Started Guide* for more information on memory management in the DPDK. In the above command, 4 GB memory is reserved (2048 of 2 MB pages) for DPDK. #. Load uio_pci_generic and bind one Intel NIC controller to it: .. code-block:: console modprobe uio_pci_generic python tools/dpdk_nic_bind.py -b uio_pci_generic 0000:09:00:00.0 In this case, 0000:09:00.0 is the PCI address for the NIC controller. #. Run the switching back end example: .. code-block:: console examples/vhost_xen/build/vhost-switch -c f -n 3 --xen-dom0 -- -p1 .. note:: The -xen-dom0 option instructs the DPDK to use the Xen kernel module to allocate memory. Other Parameters: * -vm2vm The vm2vm parameter enables/disables packet switching in software. Disabling vm2vm implies that on a VM packet transmission will always go to the Ethernet port and will not be switched to another VM * -Stats The Stats parameter controls the printing of Virtio-net device statistics. The parameter specifies the interval (in seconds) at which to print statistics, an interval of 0 seconds will disable printing statistics. Xen PMD Frontend Prerequisites ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #. Install xen-devel package for accessing XenStore: .. code-block:: console yum install xen-devel.x86_64 #. Mount xenfs, if it is not already mounted: .. code-block:: console mount -t xenfs none /proc/xen #. Enlarge the default limit for xen_gntalloc driver: .. code-block:: console modprobe -r xen_gntalloc modprobe xen_gntalloc limit=6000 .. note:: Before the Linux kernel version 3.8-rc5, Jan 15th 2013, a critical defect occurs when a guest is heavily allocating Grant pages. The Grant driver allocates fewer pages than expected which causes kernel memory corruption. This happens, for example, when a guest uses the v1 format of a Grant table entry and allocates more than 8192 Grant pages (this number might be different on different hypervisor versions). To work around this issue, set the limit for gntalloc driver to 6000. (The kernel normally allocates hundreds of Grant pages with one Xen front end per virtualized device). If the kernel allocates a lot of Grant pages, for example, if the user uses multiple net front devices, it is best to upgrade the Grant alloc driver. This defect has been fixed in kernel version 3.8-rc5 and later. Building and Running the Front End ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #. Edit config/common_linuxapp, and change the default configuration value: .. code-block:: console CONFIG_RTE_LIBRTE_XEN_DOM0=n CONFIG_RTE_LIBRTE_PMD_XENVIRT=y #. Build the package: .. code-block:: console make install T=x86_64-native-linuxapp-gcc #. Enable hugepages. Refer to the *DPDK Getting Started Guide* for instructions on how to use hugepages in the DPDK. #. Run TestPMD. Refer to *DPDK TestPMD Application User Guide* for detailed parameter usage. .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 --vdev="eth_xenvirt0,mac=00:00:00:00:00:11" testpmd>set fwd mac testpmd>start As an example to run two TestPMD instances over 2 Xen Virtio devices: .. code-block:: console --vdev="eth_xenvirt0,mac=00:00:00:00:00:11" --vdev="eth_xenvirt1;mac=00:00:00:00:00:22" Usage Examples: Injecting a Packet Stream Using a Packet Generator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Loopback Mode ^^^^^^^^^^^^^ Run TestPMD in a guest VM: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 --vdev="eth_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22 testpmd> set fwd mac testpmd> start Example output of the vhost_switch would be: .. code-block:: console DATA:(0) MAC_ADDRESS 00:00:00:00:00:11 and VLAN_TAG 1000 registered. The above message indicates that device 0 has been registered with MAC address 00:00:00:00:00:11 and VLAN tag 1000. Any packets received on the NIC with these values is placed on the device's receive queue. Configure a packet stream in the packet generator, set the destination MAC address to 00:00:00:00:00:11, and VLAN to 1000, the guest Virtio receives these packets and sends them out with destination MAC address 00:00:00:00:00:22. Inter-VM Mode ^^^^^^^^^^^^^ Run TestPMD in guest VM1: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 --vdev="eth_xenvirt0,mac=00:00:00:00:00:11" -- -i --eth-peer=0,00:00:00:00:00:22 -- -i Run TestPMD in guest VM2: .. code-block:: console ./x86_64-native-linuxapp-gcc/app/testpmd -c f -n 4 --vdev="eth_xenvirt0,mac=00:00:00:00:00:22" -- -i --eth-peer=0,00:00:00:00:00:33 Configure a packet stream in the packet generator, and set the destination MAC address to 00:00:00:00:00:11 and VLAN to 1000. The packets received in Virtio in guest VM1 will be forwarded to Virtio in guest VM2 and then sent out through hardware with destination MAC address 00:00:00:00:00:33. The packet flow is: packet generator->Virtio in guest VM1->switching backend->Virtio in guest VM2->switching backend->wire ================================================ FILE: drivers/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += net include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: drivers/net/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += af_packet DIRS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x DIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += bonding DIRS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += cxgbe DIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000 DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e DIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe DIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4 DIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += mpipe DIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += null DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt include $(RTE_SDK)/mk/rte.sharelib.mk include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: drivers/net/af_packet/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2014 John W. Linville # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # Copyright(c) 2014 6WIND S.A. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_af_packet.a EXPORT_MAP := rte_pmd_af_packet_version.map LIBABIVER := 1 CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += rte_eth_af_packet.c # # Export include files # SYMLINK-y-include += rte_eth_af_packet.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += lib/librte_kvargs include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/af_packet/rte_eth_af_packet.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014 John W. Linville * * Originally based upon librte_pmd_pcap code: * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_eth_af_packet.h" #define ETH_AF_PACKET_IFACE_ARG "iface" #define ETH_AF_PACKET_NUM_Q_ARG "qpairs" #define ETH_AF_PACKET_BLOCKSIZE_ARG "blocksz" #define ETH_AF_PACKET_FRAMESIZE_ARG "framesz" #define ETH_AF_PACKET_FRAMECOUNT_ARG "framecnt" #define DFLT_BLOCK_SIZE (1 << 12) #define DFLT_FRAME_SIZE (1 << 11) #define DFLT_FRAME_COUNT (1 << 9) struct pkt_rx_queue { int sockfd; struct iovec *rd; uint8_t *map; unsigned int framecount; unsigned int framenum; struct rte_mempool *mb_pool; volatile unsigned long rx_pkts; volatile unsigned long err_pkts; }; struct pkt_tx_queue { int sockfd; struct iovec *rd; uint8_t *map; unsigned int framecount; unsigned int framenum; volatile unsigned long tx_pkts; volatile unsigned long err_pkts; }; struct pmd_internals { unsigned nb_queues; int if_index; struct ether_addr eth_addr; struct tpacket_req req; struct pkt_rx_queue rx_queue[RTE_PMD_AF_PACKET_MAX_RINGS]; struct pkt_tx_queue tx_queue[RTE_PMD_AF_PACKET_MAX_RINGS]; }; static const char *valid_arguments[] = { ETH_AF_PACKET_IFACE_ARG, ETH_AF_PACKET_NUM_Q_ARG, ETH_AF_PACKET_BLOCKSIZE_ARG, ETH_AF_PACKET_FRAMESIZE_ARG, ETH_AF_PACKET_FRAMECOUNT_ARG, NULL }; static const char *drivername = "AF_PACKET PMD"; static struct rte_eth_link pmd_link = { .link_speed = 10000, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = 0 }; static uint16_t eth_af_packet_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { unsigned i; struct tpacket2_hdr *ppd; struct rte_mbuf *mbuf; uint8_t *pbuf; struct pkt_rx_queue *pkt_q = queue; uint16_t num_rx = 0; unsigned int framecount, framenum; if (unlikely(nb_pkts == 0)) return 0; /* * Reads the given number of packets from the AF_PACKET socket one by * one and copies the packet data into a newly allocated mbuf. */ framecount = pkt_q->framecount; framenum = pkt_q->framenum; for (i = 0; i < nb_pkts; i++) { /* point at the next incoming frame */ ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base; if ((ppd->tp_status & TP_STATUS_USER) == 0) break; /* allocate the next mbuf */ mbuf = rte_pktmbuf_alloc(pkt_q->mb_pool); if (unlikely(mbuf == NULL)) break; /* packet will fit in the mbuf, go ahead and receive it */ rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf) = ppd->tp_snaplen; pbuf = (uint8_t *) ppd + ppd->tp_mac; memcpy(rte_pktmbuf_mtod(mbuf, void *), pbuf, rte_pktmbuf_data_len(mbuf)); /* release incoming frame and advance ring buffer */ ppd->tp_status = TP_STATUS_KERNEL; if (++framenum >= framecount) framenum = 0; /* account for the receive frame */ bufs[i] = mbuf; num_rx++; } pkt_q->framenum = framenum; pkt_q->rx_pkts += num_rx; return num_rx; } /* * Callback to handle sending packets through a real NIC. */ static uint16_t eth_af_packet_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct tpacket2_hdr *ppd; struct rte_mbuf *mbuf; uint8_t *pbuf; unsigned int framecount, framenum; struct pollfd pfd; struct pkt_tx_queue *pkt_q = queue; uint16_t num_tx = 0; int i; if (unlikely(nb_pkts == 0)) return 0; memset(&pfd, 0, sizeof(pfd)); pfd.fd = pkt_q->sockfd; pfd.events = POLLOUT; pfd.revents = 0; framecount = pkt_q->framecount; framenum = pkt_q->framenum; ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base; for (i = 0; i < nb_pkts; i++) { /* point at the next incoming frame */ if ((ppd->tp_status != TP_STATUS_AVAILABLE) && (poll(&pfd, 1, -1) < 0)) continue; /* copy the tx frame data */ mbuf = bufs[num_tx]; pbuf = (uint8_t *) ppd + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); memcpy(pbuf, rte_pktmbuf_mtod(mbuf, void*), rte_pktmbuf_data_len(mbuf)); ppd->tp_len = ppd->tp_snaplen = rte_pktmbuf_data_len(mbuf); /* release incoming frame and advance ring buffer */ ppd->tp_status = TP_STATUS_SEND_REQUEST; if (++framenum >= framecount) framenum = 0; ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base; num_tx++; rte_pktmbuf_free(mbuf); } /* kick-off transmits */ sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0); pkt_q->framenum = framenum; pkt_q->tx_pkts += num_tx; pkt_q->err_pkts += nb_pkts - num_tx; return num_tx; } static int eth_dev_start(struct rte_eth_dev *dev) { dev->data->dev_link.link_status = 1; return 0; } /* * This function gets called when the current port gets stopped. */ static void eth_dev_stop(struct rte_eth_dev *dev) { unsigned i; int sockfd; struct pmd_internals *internals = dev->data->dev_private; for (i = 0; i < internals->nb_queues; i++) { sockfd = internals->rx_queue[i].sockfd; if (sockfd != -1) close(sockfd); sockfd = internals->tx_queue[i].sockfd; if (sockfd != -1) close(sockfd); } dev->data->dev_link.link_status = 0; } static int eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; } static void eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_internals *internals = dev->data->dev_private; dev_info->driver_name = drivername; dev_info->if_index = internals->if_index; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)ETH_FRAME_LEN; dev_info->max_rx_queues = (uint16_t)internals->nb_queues; dev_info->max_tx_queues = (uint16_t)internals->nb_queues; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static void eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) { unsigned i, imax; unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0; const struct pmd_internals *internal = dev->data->dev_private; imax = (internal->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS ? internal->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS); for (i = 0; i < imax; i++) { igb_stats->q_ipackets[i] = internal->rx_queue[i].rx_pkts; rx_total += igb_stats->q_ipackets[i]; } imax = (internal->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS ? internal->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS); for (i = 0; i < imax; i++) { igb_stats->q_opackets[i] = internal->tx_queue[i].tx_pkts; igb_stats->q_errors[i] = internal->tx_queue[i].err_pkts; tx_total += igb_stats->q_opackets[i]; tx_err_total += igb_stats->q_errors[i]; } igb_stats->ipackets = rx_total; igb_stats->opackets = tx_total; igb_stats->oerrors = tx_err_total; } static void eth_stats_reset(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internal = dev->data->dev_private; for (i = 0; i < internal->nb_queues; i++) internal->rx_queue[i].rx_pkts = 0; for (i = 0; i < internal->nb_queues; i++) { internal->tx_queue[i].tx_pkts = 0; internal->tx_queue[i].err_pkts = 0; } } static void eth_dev_close(struct rte_eth_dev *dev __rte_unused) { } static void eth_queue_release(void *q __rte_unused) { } static int eth_link_update(struct rte_eth_dev *dev __rte_unused, int wait_to_complete __rte_unused) { return 0; } static int eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool) { struct pmd_internals *internals = dev->data->dev_private; struct pkt_rx_queue *pkt_q = &internals->rx_queue[rx_queue_id]; uint16_t buf_size; pkt_q->mb_pool = mb_pool; /* Now get the space available for data in the mbuf */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(pkt_q->mb_pool) - RTE_PKTMBUF_HEADROOM); if (ETH_FRAME_LEN > buf_size) { RTE_LOG(ERR, PMD, "%s: %d bytes will not fit in mbuf (%d bytes)\n", dev->data->name, ETH_FRAME_LEN, buf_size); return -ENOMEM; } dev->data->rx_queues[rx_queue_id] = pkt_q; return 0; } static int eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { struct pmd_internals *internals = dev->data->dev_private; dev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id]; return 0; } static const struct eth_dev_ops ops = { .dev_start = eth_dev_start, .dev_stop = eth_dev_stop, .dev_close = eth_dev_close, .dev_configure = eth_dev_configure, .dev_infos_get = eth_dev_info, .rx_queue_setup = eth_rx_queue_setup, .tx_queue_setup = eth_tx_queue_setup, .rx_queue_release = eth_queue_release, .tx_queue_release = eth_queue_release, .link_update = eth_link_update, .stats_get = eth_stats_get, .stats_reset = eth_stats_reset, }; /* * Opens an AF_PACKET socket */ static int open_packet_iface(const char *key __rte_unused, const char *value __rte_unused, void *extra_args) { int *sockfd = extra_args; /* Open an AF_PACKET socket... */ *sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (*sockfd == -1) { RTE_LOG(ERR, PMD, "Could not open AF_PACKET socket\n"); return -1; } return 0; } static int rte_pmd_init_internals(const char *name, const int sockfd, const unsigned nb_queues, unsigned int blocksize, unsigned int blockcnt, unsigned int framesize, unsigned int framecnt, const unsigned numa_node, struct pmd_internals **internals, struct rte_eth_dev **eth_dev, struct rte_kvargs *kvlist) { struct rte_eth_dev_data *data = NULL; struct rte_pci_device *pci_dev = NULL; struct rte_kvargs_pair *pair = NULL; struct ifreq ifr; size_t ifnamelen; unsigned k_idx; struct sockaddr_ll sockaddr; struct tpacket_req *req; struct pkt_rx_queue *rx_queue; struct pkt_tx_queue *tx_queue; int rc, tpver, discard; int qsockfd = -1; unsigned int i, q, rdsize; int fanout_arg __rte_unused, bypass __rte_unused; for (k_idx = 0; k_idx < kvlist->count; k_idx++) { pair = &kvlist->pairs[k_idx]; if (strstr(pair->key, ETH_AF_PACKET_IFACE_ARG) != NULL) break; } if (pair == NULL) { RTE_LOG(ERR, PMD, "%s: no interface specified for AF_PACKET ethdev\n", name); goto error; } RTE_LOG(INFO, PMD, "%s: creating AF_PACKET-backed ethdev on numa socket %u\n", name, numa_node); /* * now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (data == NULL) goto error; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node); if (pci_dev == NULL) goto error; *internals = rte_zmalloc_socket(name, sizeof(**internals), 0, numa_node); if (*internals == NULL) goto error; for (q = 0; q < nb_queues; q++) { (*internals)->rx_queue[q].map = MAP_FAILED; (*internals)->tx_queue[q].map = MAP_FAILED; } req = &((*internals)->req); req->tp_block_size = blocksize; req->tp_block_nr = blockcnt; req->tp_frame_size = framesize; req->tp_frame_nr = framecnt; ifnamelen = strlen(pair->value); if (ifnamelen < sizeof(ifr.ifr_name)) { memcpy(ifr.ifr_name, pair->value, ifnamelen); ifr.ifr_name[ifnamelen] = '\0'; } else { RTE_LOG(ERR, PMD, "%s: I/F name too long (%s)\n", name, pair->value); goto error; } if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) { RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCGIFINDEX)\n", name); goto error; } (*internals)->if_index = ifr.ifr_ifindex; if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) { RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCGIFHWADDR)\n", name); goto error; } memcpy(&(*internals)->eth_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sll_family = AF_PACKET; sockaddr.sll_protocol = htons(ETH_P_ALL); sockaddr.sll_ifindex = (*internals)->if_index; #if defined(PACKET_FANOUT) fanout_arg = (getpid() ^ (*internals)->if_index) & 0xffff; fanout_arg |= (PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_DEFRAG) << 16; #if defined(PACKET_FANOUT_FLAG_ROLLOVER) fanout_arg |= PACKET_FANOUT_FLAG_ROLLOVER << 16; #endif #endif for (q = 0; q < nb_queues; q++) { /* Open an AF_PACKET socket for this queue... */ qsockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (qsockfd == -1) { RTE_LOG(ERR, PMD, "%s: could not open AF_PACKET socket\n", name); return -1; } tpver = TPACKET_V2; rc = setsockopt(qsockfd, SOL_PACKET, PACKET_VERSION, &tpver, sizeof(tpver)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_VERSION on AF_PACKET " "socket for %s\n", name, pair->value); goto error; } discard = 1; rc = setsockopt(qsockfd, SOL_PACKET, PACKET_LOSS, &discard, sizeof(discard)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_LOSS on " "AF_PACKET socket for %s\n", name, pair->value); goto error; } #if defined(PACKET_QDISC_BYPASS) bypass = 1; rc = setsockopt(qsockfd, SOL_PACKET, PACKET_QDISC_BYPASS, &bypass, sizeof(bypass)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_QDISC_BYPASS " "on AF_PACKET socket for %s\n", name, pair->value); goto error; } #endif rc = setsockopt(qsockfd, SOL_PACKET, PACKET_RX_RING, req, sizeof(*req)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_RX_RING on AF_PACKET " "socket for %s\n", name, pair->value); goto error; } rc = setsockopt(qsockfd, SOL_PACKET, PACKET_TX_RING, req, sizeof(*req)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_TX_RING on AF_PACKET " "socket for %s\n", name, pair->value); goto error; } rx_queue = &((*internals)->rx_queue[q]); rx_queue->framecount = req->tp_frame_nr; rx_queue->map = mmap(NULL, 2 * req->tp_block_size * req->tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, qsockfd, 0); if (rx_queue->map == MAP_FAILED) { RTE_LOG(ERR, PMD, "%s: call to mmap failed on AF_PACKET socket for %s\n", name, pair->value); goto error; } /* rdsize is same for both Tx and Rx */ rdsize = req->tp_frame_nr * sizeof(*(rx_queue->rd)); rx_queue->rd = rte_zmalloc_socket(name, rdsize, 0, numa_node); if (rx_queue->rd == NULL) goto error; for (i = 0; i < req->tp_frame_nr; ++i) { rx_queue->rd[i].iov_base = rx_queue->map + (i * framesize); rx_queue->rd[i].iov_len = req->tp_frame_size; } rx_queue->sockfd = qsockfd; tx_queue = &((*internals)->tx_queue[q]); tx_queue->framecount = req->tp_frame_nr; tx_queue->map = rx_queue->map + req->tp_block_size * req->tp_block_nr; tx_queue->rd = rte_zmalloc_socket(name, rdsize, 0, numa_node); if (tx_queue->rd == NULL) goto error; for (i = 0; i < req->tp_frame_nr; ++i) { tx_queue->rd[i].iov_base = tx_queue->map + (i * framesize); tx_queue->rd[i].iov_len = req->tp_frame_size; } tx_queue->sockfd = qsockfd; rc = bind(qsockfd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not bind AF_PACKET socket to %s\n", name, pair->value); goto error; } #if defined(PACKET_FANOUT) rc = setsockopt(qsockfd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)); if (rc == -1) { RTE_LOG(ERR, PMD, "%s: could not set PACKET_FANOUT on AF_PACKET socket " "for %s\n", name, pair->value); goto error; } #endif } /* reserve an ethdev entry */ *eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (*eth_dev == NULL) goto error; /* * now put it all together * - store queue data in internals, * - store numa_node info in pci_driver * - point eth_dev_data to internals and pci_driver * - and point eth_dev structure to new eth_dev_data structure */ (*internals)->nb_queues = nb_queues; data->dev_private = *internals; data->port_id = (*eth_dev)->data->port_id; data->nb_rx_queues = (uint16_t)nb_queues; data->nb_tx_queues = (uint16_t)nb_queues; data->dev_link = pmd_link; data->mac_addrs = &(*internals)->eth_addr; pci_dev->numa_node = numa_node; (*eth_dev)->data = data; (*eth_dev)->dev_ops = &ops; (*eth_dev)->pci_dev = pci_dev; return 0; error: rte_free(data); rte_free(pci_dev); if (*internals) { for (q = 0; q < nb_queues; q++) { munmap((*internals)->rx_queue[q].map, 2 * req->tp_block_size * req->tp_block_nr); rte_free((*internals)->rx_queue[q].rd); rte_free((*internals)->tx_queue[q].rd); if (((*internals)->rx_queue[q].sockfd != 0) && ((*internals)->rx_queue[q].sockfd != qsockfd)) close((*internals)->rx_queue[q].sockfd); } rte_free(*internals); } if (qsockfd != -1) close(qsockfd); return -1; } static int rte_eth_from_packet(const char *name, int const *sockfd, const unsigned numa_node, struct rte_kvargs *kvlist) { struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; struct rte_kvargs_pair *pair = NULL; unsigned k_idx; unsigned int blockcount; unsigned int blocksize = DFLT_BLOCK_SIZE; unsigned int framesize = DFLT_FRAME_SIZE; unsigned int framecount = DFLT_FRAME_COUNT; unsigned int qpairs = 1; /* do some parameter checking */ if (*sockfd < 0) return -1; /* * Walk arguments for configurable settings */ for (k_idx = 0; k_idx < kvlist->count; k_idx++) { pair = &kvlist->pairs[k_idx]; if (strstr(pair->key, ETH_AF_PACKET_NUM_Q_ARG) != NULL) { qpairs = atoi(pair->value); if (qpairs < 1 || qpairs > RTE_PMD_AF_PACKET_MAX_RINGS) { RTE_LOG(ERR, PMD, "%s: invalid qpairs value\n", name); return -1; } continue; } if (strstr(pair->key, ETH_AF_PACKET_BLOCKSIZE_ARG) != NULL) { blocksize = atoi(pair->value); if (!blocksize) { RTE_LOG(ERR, PMD, "%s: invalid blocksize value\n", name); return -1; } continue; } if (strstr(pair->key, ETH_AF_PACKET_FRAMESIZE_ARG) != NULL) { framesize = atoi(pair->value); if (!framesize) { RTE_LOG(ERR, PMD, "%s: invalid framesize value\n", name); return -1; } continue; } if (strstr(pair->key, ETH_AF_PACKET_FRAMECOUNT_ARG) != NULL) { framecount = atoi(pair->value); if (!framecount) { RTE_LOG(ERR, PMD, "%s: invalid framecount value\n", name); return -1; } continue; } } if (framesize > blocksize) { RTE_LOG(ERR, PMD, "%s: AF_PACKET MMAP frame size exceeds block size!\n", name); return -1; } blockcount = framecount / (blocksize / framesize); if (!blockcount) { RTE_LOG(ERR, PMD, "%s: invalid AF_PACKET MMAP parameters\n", name); return -1; } RTE_LOG(INFO, PMD, "%s: AF_PACKET MMAP parameters:\n", name); RTE_LOG(INFO, PMD, "%s:\tblock size %d\n", name, blocksize); RTE_LOG(INFO, PMD, "%s:\tblock count %d\n", name, blockcount); RTE_LOG(INFO, PMD, "%s:\tframe size %d\n", name, framesize); RTE_LOG(INFO, PMD, "%s:\tframe count %d\n", name, framecount); if (rte_pmd_init_internals(name, *sockfd, qpairs, blocksize, blockcount, framesize, framecount, numa_node, &internals, ð_dev, kvlist) < 0) return -1; eth_dev->rx_pkt_burst = eth_af_packet_rx; eth_dev->tx_pkt_burst = eth_af_packet_tx; return 0; } int rte_pmd_af_packet_devinit(const char *name, const char *params) { unsigned numa_node; int ret = 0; struct rte_kvargs *kvlist; int sockfd = -1; RTE_LOG(INFO, PMD, "Initializing pmd_af_packet for %s\n", name); numa_node = rte_socket_id(); kvlist = rte_kvargs_parse(params, valid_arguments); if (kvlist == NULL) { ret = -1; goto exit; } /* * If iface argument is passed we open the NICs and use them for * reading / writing */ if (rte_kvargs_count(kvlist, ETH_AF_PACKET_IFACE_ARG) == 1) { ret = rte_kvargs_process(kvlist, ETH_AF_PACKET_IFACE_ARG, &open_packet_iface, &sockfd); if (ret < 0) goto exit; } ret = rte_eth_from_packet(name, &sockfd, numa_node, kvlist); close(sockfd); /* no longer needed */ exit: rte_kvargs_free(kvlist); return ret; } static struct rte_driver pmd_af_packet_drv = { .name = "eth_af_packet", .type = PMD_VDEV, .init = rte_pmd_af_packet_devinit, }; PMD_REGISTER_DRIVER(pmd_af_packet_drv); ================================================ FILE: drivers/net/af_packet/rte_eth_af_packet.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_AF_PACKET_H_ #define _RTE_ETH_AF_PACKET_H_ #ifdef __cplusplus extern "C" { #endif #define RTE_PMD_AF_PACKET_MAX_RINGS 16 /** * For use by the EAL only. Called as part of EAL init to set up any dummy NICs * configured on command line. */ int rte_pmd_af_packet_devinit(const char *name, const char *params); #ifdef __cplusplus } #endif #endif ================================================ FILE: drivers/net/bnx2x/Makefile ================================================ include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_bnx2x.a CFLAGS += -O3 -g CFLAGS += $(WERROR_FLAGS) CFLAGS += -DZLIB_CONST EXPORT_MAP := rte_pmd_bnx2x_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x_stats.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += ecore_sp.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += elink.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += bnx2x_vfpf.c SRCS-$(CONFIG_RTE_LIBRTE_BNX2X_DEBUG) += debug.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += lib/librte_eal lib/librte_ether lib/librte_hash DEPDIRS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += lib/librte_mempool lib/librte_mbuf include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/bnx2x/bnx2x.c ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #define BNX2X_DRIVER_VERSION "1.78.18" #include "bnx2x.h" #include "bnx2x_vfpf.h" #include "ecore_sp.h" #include "ecore_init.h" #include "ecore_init_ops.h" #include "rte_pci_dev_ids.h" #include #include #include #include static z_stream zlib_stream; #define EVL_VLID_MASK 0x0FFF #define BNX2X_DEF_SB_ATT_IDX 0x0001 #define BNX2X_DEF_SB_IDX 0x0002 /* * FLR Support - bnx2x_pf_flr_clnup() is called during nic_load in the per * function HW initialization. */ #define FLR_WAIT_USEC 10000 /* 10 msecs */ #define FLR_WAIT_INTERVAL 50 /* usecs */ #define FLR_POLL_CNT (FLR_WAIT_USEC / FLR_WAIT_INTERVAL) /* 200 */ struct pbf_pN_buf_regs { int pN; uint32_t init_crd; uint32_t crd; uint32_t crd_freed; }; struct pbf_pN_cmd_regs { int pN; uint32_t lines_occup; uint32_t lines_freed; }; /* resources needed for unloading a previously loaded device */ #define BNX2X_PREV_WAIT_NEEDED 1 rte_spinlock_t bnx2x_prev_mtx; struct bnx2x_prev_list_node { LIST_ENTRY(bnx2x_prev_list_node) node; uint8_t bus; uint8_t slot; uint8_t path; uint8_t aer; uint8_t undi; }; static LIST_HEAD(, bnx2x_prev_list_node) bnx2x_prev_list = LIST_HEAD_INITIALIZER(bnx2x_prev_list); static int load_count[2][3] = { { 0 } }; /* per-path: 0-common, 1-port0, 2-port1 */ static void bnx2x_cmng_fns_init(struct bnx2x_softc *sc, uint8_t read_cfg, uint8_t cmng_type); static int bnx2x_get_cmng_fns_mode(struct bnx2x_softc *sc); static void storm_memset_cmng(struct bnx2x_softc *sc, struct cmng_init *cmng, uint8_t port); static void bnx2x_set_reset_global(struct bnx2x_softc *sc); static void bnx2x_set_reset_in_progress(struct bnx2x_softc *sc); static uint8_t bnx2x_reset_is_done(struct bnx2x_softc *sc, int engine); static uint8_t bnx2x_clear_pf_load(struct bnx2x_softc *sc); static uint8_t bnx2x_chk_parity_attn(struct bnx2x_softc *sc, uint8_t * global, uint8_t print); static void bnx2x_int_disable(struct bnx2x_softc *sc); static int bnx2x_release_leader_lock(struct bnx2x_softc *sc); static void bnx2x_pf_disable(struct bnx2x_softc *sc); static void bnx2x_update_rx_prod(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, uint16_t rx_bd_prod, uint16_t rx_cq_prod); static void bnx2x_link_report(struct bnx2x_softc *sc); void bnx2x_link_status_update(struct bnx2x_softc *sc); static int bnx2x_alloc_mem(struct bnx2x_softc *sc); static void bnx2x_free_mem(struct bnx2x_softc *sc); static int bnx2x_alloc_fw_stats_mem(struct bnx2x_softc *sc); static void bnx2x_free_fw_stats_mem(struct bnx2x_softc *sc); static __attribute__ ((noinline)) int bnx2x_nic_load(struct bnx2x_softc *sc); static int bnx2x_handle_sp_tq(struct bnx2x_softc *sc); static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp, int scan_fp); static void bnx2x_periodic_stop(struct bnx2x_softc *sc); static void bnx2x_ack_sb(struct bnx2x_softc *sc, uint8_t igu_sb_id, uint8_t storm, uint16_t index, uint8_t op, uint8_t update); int bnx2x_test_bit(int nr, volatile unsigned long *addr) { int res; mb(); res = ((*addr) & (1UL << nr)) != 0; mb(); return res; } void bnx2x_set_bit(unsigned int nr, volatile unsigned long *addr) { __sync_fetch_and_or(addr, (1UL << nr)); } void bnx2x_clear_bit(int nr, volatile unsigned long *addr) { __sync_fetch_and_and(addr, ~(1UL << nr)); } int bnx2x_test_and_clear_bit(int nr, volatile unsigned long *addr) { unsigned long mask = (1UL << nr); return __sync_fetch_and_and(addr, ~mask) & mask; } int bnx2x_cmpxchg(volatile int *addr, int old, int new) { return __sync_val_compare_and_swap(addr, old, new); } int bnx2x_dma_alloc(struct bnx2x_softc *sc, size_t size, struct bnx2x_dma *dma, const char *msg, uint32_t align) { char mz_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *z; dma->sc = sc; if (IS_PF(sc)) sprintf(mz_name, "bnx2x%d_%s_%" PRIx64, SC_ABS_FUNC(sc), msg, rte_get_timer_cycles()); else sprintf(mz_name, "bnx2x%d_%s_%" PRIx64, sc->pcie_device, msg, rte_get_timer_cycles()); /* Caller must take care that strlen(mz_name) < RTE_MEMZONE_NAMESIZE */ z = rte_memzone_reserve_aligned(mz_name, (uint64_t) (size), rte_lcore_to_socket_id(rte_lcore_id()), 0, align); if (z == NULL) { PMD_DRV_LOG(ERR, "DMA alloc failed for %s", msg); return -ENOMEM; } dma->paddr = (uint64_t) z->phys_addr; dma->vaddr = z->addr; PMD_DRV_LOG(DEBUG, "%s: virt=%p phys=%" PRIx64, msg, dma->vaddr, dma->paddr); return 0; } static int bnx2x_acquire_hw_lock(struct bnx2x_softc *sc, uint32_t resource) { uint32_t lock_status; uint32_t resource_bit = (1 << resource); int func = SC_FUNC(sc); uint32_t hw_lock_control_reg; int cnt; PMD_INIT_FUNC_TRACE(); /* validate the resource is within range */ if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { PMD_DRV_LOG(NOTICE, "resource 0x%x > HW_LOCK_MAX_RESOURCE_VALUE", resource); return -1; } if (func <= 5) { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + (func * 8)); } else { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_7 + ((func - 6) * 8)); } /* validate the resource is not already taken */ lock_status = REG_RD(sc, hw_lock_control_reg); if (lock_status & resource_bit) { PMD_DRV_LOG(NOTICE, "resource in use (status 0x%x bit 0x%x)", lock_status, resource_bit); return -1; } /* try every 5ms for 5 seconds */ for (cnt = 0; cnt < 1000; cnt++) { REG_WR(sc, (hw_lock_control_reg + 4), resource_bit); lock_status = REG_RD(sc, hw_lock_control_reg); if (lock_status & resource_bit) { return 0; } DELAY(5000); } PMD_DRV_LOG(NOTICE, "Resource lock timeout!"); return -1; } static int bnx2x_release_hw_lock(struct bnx2x_softc *sc, uint32_t resource) { uint32_t lock_status; uint32_t resource_bit = (1 << resource); int func = SC_FUNC(sc); uint32_t hw_lock_control_reg; PMD_INIT_FUNC_TRACE(); /* validate the resource is within range */ if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { PMD_DRV_LOG(NOTICE, "resource 0x%x > HW_LOCK_MAX_RESOURCE_VALUE", resource); return -1; } if (func <= 5) { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + (func * 8)); } else { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_7 + ((func - 6) * 8)); } /* validate the resource is currently taken */ lock_status = REG_RD(sc, hw_lock_control_reg); if (!(lock_status & resource_bit)) { PMD_DRV_LOG(NOTICE, "resource not in use (status 0x%x bit 0x%x)", lock_status, resource_bit); return -1; } REG_WR(sc, hw_lock_control_reg, resource_bit); return 0; } /* copy command into DMAE command memory and set DMAE command Go */ void bnx2x_post_dmae(struct bnx2x_softc *sc, struct dmae_command *dmae, int idx) { uint32_t cmd_offset; uint32_t i; cmd_offset = (DMAE_REG_CMD_MEM + (sizeof(struct dmae_command) * idx)); for (i = 0; i < ((sizeof(struct dmae_command) / 4)); i++) { REG_WR(sc, (cmd_offset + (i * 4)), *(((uint32_t *) dmae) + i)); } REG_WR(sc, dmae_reg_go_c[idx], 1); } uint32_t bnx2x_dmae_opcode_add_comp(uint32_t opcode, uint8_t comp_type) { return (opcode | ((comp_type << DMAE_COMMAND_C_DST_SHIFT) | DMAE_COMMAND_C_TYPE_ENABLE)); } uint32_t bnx2x_dmae_opcode_clr_src_reset(uint32_t opcode) { return (opcode & ~DMAE_COMMAND_SRC_RESET); } uint32_t bnx2x_dmae_opcode(struct bnx2x_softc * sc, uint8_t src_type, uint8_t dst_type, uint8_t with_comp, uint8_t comp_type) { uint32_t opcode = 0; opcode |= ((src_type << DMAE_COMMAND_SRC_SHIFT) | (dst_type << DMAE_COMMAND_DST_SHIFT)); opcode |= (DMAE_COMMAND_SRC_RESET | DMAE_COMMAND_DST_RESET); opcode |= (SC_PORT(sc) ? DMAE_CMD_PORT_1 : DMAE_CMD_PORT_0); opcode |= ((SC_VN(sc) << DMAE_COMMAND_E1HVN_SHIFT) | (SC_VN(sc) << DMAE_COMMAND_DST_VN_SHIFT)); opcode |= (DMAE_COM_SET_ERR << DMAE_COMMAND_ERR_POLICY_SHIFT); #ifdef __BIG_ENDIAN opcode |= DMAE_CMD_ENDIANITY_B_DW_SWAP; #else opcode |= DMAE_CMD_ENDIANITY_DW_SWAP; #endif if (with_comp) { opcode = bnx2x_dmae_opcode_add_comp(opcode, comp_type); } return opcode; } static void bnx2x_prep_dmae_with_comp(struct bnx2x_softc *sc, struct dmae_command *dmae, uint8_t src_type, uint8_t dst_type) { memset(dmae, 0, sizeof(struct dmae_command)); /* set the opcode */ dmae->opcode = bnx2x_dmae_opcode(sc, src_type, dst_type, TRUE, DMAE_COMP_PCI); /* fill in the completion parameters */ dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, wb_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, wb_comp)); dmae->comp_val = DMAE_COMP_VAL; } /* issue a DMAE command over the init channel and wait for completion */ static int bnx2x_issue_dmae_with_comp(struct bnx2x_softc *sc, struct dmae_command *dmae) { uint32_t *wb_comp = BNX2X_SP(sc, wb_comp); int timeout = CHIP_REV_IS_SLOW(sc) ? 400000 : 4000; /* reset completion */ *wb_comp = 0; /* post the command on the channel used for initializations */ bnx2x_post_dmae(sc, dmae, INIT_DMAE_C(sc)); /* wait for completion */ DELAY(500); while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) { if (!timeout || (sc->recovery_state != BNX2X_RECOVERY_DONE && sc->recovery_state != BNX2X_RECOVERY_NIC_LOADING)) { PMD_DRV_LOG(INFO, "DMAE timeout!"); return DMAE_TIMEOUT; } timeout--; DELAY(50); } if (*wb_comp & DMAE_PCI_ERR_FLAG) { PMD_DRV_LOG(INFO, "DMAE PCI error!"); return DMAE_PCI_ERROR; } return 0; } void bnx2x_read_dmae(struct bnx2x_softc *sc, uint32_t src_addr, uint32_t len32) { struct dmae_command dmae; uint32_t *data; uint32_t i; int rc; if (!sc->dmae_ready) { data = BNX2X_SP(sc, wb_data[0]); for (i = 0; i < len32; i++) { data[i] = REG_RD(sc, (src_addr + (i * 4))); } return; } /* set opcode and fixed command fields */ bnx2x_prep_dmae_with_comp(sc, &dmae, DMAE_SRC_GRC, DMAE_DST_PCI); /* fill in addresses and len */ dmae.src_addr_lo = (src_addr >> 2); /* GRC addr has dword resolution */ dmae.src_addr_hi = 0; dmae.dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, wb_data)); dmae.dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, wb_data)); dmae.len = len32; /* issue the command and wait for completion */ if ((rc = bnx2x_issue_dmae_with_comp(sc, &dmae)) != 0) { rte_panic("DMAE failed (%d)", rc); }; } void bnx2x_write_dmae(struct bnx2x_softc *sc, phys_addr_t dma_addr, uint32_t dst_addr, uint32_t len32) { struct dmae_command dmae; int rc; if (!sc->dmae_ready) { ecore_init_str_wr(sc, dst_addr, BNX2X_SP(sc, wb_data[0]), len32); return; } /* set opcode and fixed command fields */ bnx2x_prep_dmae_with_comp(sc, &dmae, DMAE_SRC_PCI, DMAE_DST_GRC); /* fill in addresses and len */ dmae.src_addr_lo = U64_LO(dma_addr); dmae.src_addr_hi = U64_HI(dma_addr); dmae.dst_addr_lo = (dst_addr >> 2); /* GRC addr has dword resolution */ dmae.dst_addr_hi = 0; dmae.len = len32; /* issue the command and wait for completion */ if ((rc = bnx2x_issue_dmae_with_comp(sc, &dmae)) != 0) { rte_panic("DMAE failed (%d)", rc); } } static void bnx2x_write_dmae_phys_len(struct bnx2x_softc *sc, phys_addr_t phys_addr, uint32_t addr, uint32_t len) { uint32_t dmae_wr_max = DMAE_LEN32_WR_MAX(sc); uint32_t offset = 0; while (len > dmae_wr_max) { bnx2x_write_dmae(sc, (phys_addr + offset), /* src DMA address */ (addr + offset), /* dst GRC address */ dmae_wr_max); offset += (dmae_wr_max * 4); len -= dmae_wr_max; } bnx2x_write_dmae(sc, (phys_addr + offset), /* src DMA address */ (addr + offset), /* dst GRC address */ len); } void bnx2x_set_ctx_validation(struct bnx2x_softc *sc, struct eth_context *cxt, uint32_t cid) { /* ustorm cxt validation */ cxt->ustorm_ag_context.cdu_usage = CDU_RSRVD_VALUE_TYPE_A(HW_CID(sc, cid), CDU_REGION_NUMBER_UCM_AG, ETH_CONNECTION_TYPE); /* xcontext validation */ cxt->xstorm_ag_context.cdu_reserved = CDU_RSRVD_VALUE_TYPE_A(HW_CID(sc, cid), CDU_REGION_NUMBER_XCM_AG, ETH_CONNECTION_TYPE); } static void bnx2x_storm_memset_hc_timeout(struct bnx2x_softc *sc, uint8_t fw_sb_id, uint8_t sb_index, uint8_t ticks) { uint32_t addr = (BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index)); REG_WR8(sc, addr, ticks); } static void bnx2x_storm_memset_hc_disable(struct bnx2x_softc *sc, uint16_t fw_sb_id, uint8_t sb_index, uint8_t disable) { uint32_t enable_flag = (disable) ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT); uint32_t addr = (BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index)); uint8_t flags; /* clear and set */ flags = REG_RD8(sc, addr); flags &= ~HC_INDEX_DATA_HC_ENABLED; flags |= enable_flag; REG_WR8(sc, addr, flags); } void bnx2x_update_coalesce_sb_index(struct bnx2x_softc *sc, uint8_t fw_sb_id, uint8_t sb_index, uint8_t disable, uint16_t usec) { uint8_t ticks = (usec / 4); bnx2x_storm_memset_hc_timeout(sc, fw_sb_id, sb_index, ticks); disable = (disable) ? 1 : ((usec) ? 0 : 1); bnx2x_storm_memset_hc_disable(sc, fw_sb_id, sb_index, disable); } uint32_t elink_cb_reg_read(struct bnx2x_softc *sc, uint32_t reg_addr) { return REG_RD(sc, reg_addr); } void elink_cb_reg_write(struct bnx2x_softc *sc, uint32_t reg_addr, uint32_t val) { REG_WR(sc, reg_addr, val); } void elink_cb_event_log(__rte_unused struct bnx2x_softc *sc, __rte_unused const elink_log_id_t elink_log_id, ...) { PMD_DRV_LOG(DEBUG, "ELINK EVENT LOG (%d)", elink_log_id); } static int bnx2x_set_spio(struct bnx2x_softc *sc, int spio, uint32_t mode) { uint32_t spio_reg; /* Only 2 SPIOs are configurable */ if ((spio != MISC_SPIO_SPIO4) && (spio != MISC_SPIO_SPIO5)) { PMD_DRV_LOG(NOTICE, "Invalid SPIO 0x%x", spio); return -1; } bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_SPIO); /* read SPIO and mask except the float bits */ spio_reg = (REG_RD(sc, MISC_REG_SPIO) & MISC_SPIO_FLOAT); switch (mode) { case MISC_SPIO_OUTPUT_LOW: /* clear FLOAT and set CLR */ spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS); spio_reg |= (spio << MISC_SPIO_CLR_POS); break; case MISC_SPIO_OUTPUT_HIGH: /* clear FLOAT and set SET */ spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS); spio_reg |= (spio << MISC_SPIO_SET_POS); break; case MISC_SPIO_INPUT_HI_Z: /* set FLOAT */ spio_reg |= (spio << MISC_SPIO_FLOAT_POS); break; default: break; } REG_WR(sc, MISC_REG_SPIO, spio_reg); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_SPIO); return 0; } static int bnx2x_gpio_read(struct bnx2x_softc *sc, int gpio_num, uint8_t port) { /* The GPIO should be swapped if swap register is set and active */ int gpio_port = ((REG_RD(sc, NIG_REG_PORT_SWAP) && REG_RD(sc, NIG_REG_STRAP_OVERRIDE)) ^ port); int gpio_shift = gpio_num; if (gpio_port) gpio_shift += MISC_REGISTERS_GPIO_PORT_SHIFT; uint32_t gpio_mask = (1 << gpio_shift); uint32_t gpio_reg; if (gpio_num > MISC_REGISTERS_GPIO_3) { PMD_DRV_LOG(NOTICE, "Invalid GPIO %d", gpio_num); return -1; } /* read GPIO value */ gpio_reg = REG_RD(sc, MISC_REG_GPIO); /* get the requested pin value */ return ((gpio_reg & gpio_mask) == gpio_mask) ? 1 : 0; } static int bnx2x_gpio_write(struct bnx2x_softc *sc, int gpio_num, uint32_t mode, uint8_t port) { /* The GPIO should be swapped if swap register is set and active */ int gpio_port = ((REG_RD(sc, NIG_REG_PORT_SWAP) && REG_RD(sc, NIG_REG_STRAP_OVERRIDE)) ^ port); int gpio_shift = gpio_num; if (gpio_port) gpio_shift += MISC_REGISTERS_GPIO_PORT_SHIFT; uint32_t gpio_mask = (1 << gpio_shift); uint32_t gpio_reg; if (gpio_num > MISC_REGISTERS_GPIO_3) { PMD_DRV_LOG(NOTICE, "Invalid GPIO %d", gpio_num); return -1; } bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); /* read GPIO and mask except the float bits */ gpio_reg = (REG_RD(sc, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT); switch (mode) { case MISC_REGISTERS_GPIO_OUTPUT_LOW: /* clear FLOAT and set CLR */ gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS); break; case MISC_REGISTERS_GPIO_OUTPUT_HIGH: /* clear FLOAT and set SET */ gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_SET_POS); break; case MISC_REGISTERS_GPIO_INPUT_HI_Z: /* set FLOAT */ gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); break; default: break; } REG_WR(sc, MISC_REG_GPIO, gpio_reg); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); return 0; } static int bnx2x_gpio_mult_write(struct bnx2x_softc *sc, uint8_t pins, uint32_t mode) { uint32_t gpio_reg; /* any port swapping should be handled by caller */ bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); /* read GPIO and mask except the float bits */ gpio_reg = REG_RD(sc, MISC_REG_GPIO); gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS); gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS); gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS); switch (mode) { case MISC_REGISTERS_GPIO_OUTPUT_LOW: /* set CLR */ gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS); break; case MISC_REGISTERS_GPIO_OUTPUT_HIGH: /* set SET */ gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS); break; case MISC_REGISTERS_GPIO_INPUT_HI_Z: /* set FLOAT */ gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS); break; default: PMD_DRV_LOG(NOTICE, "Invalid GPIO mode assignment %d", mode); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); return -1; } REG_WR(sc, MISC_REG_GPIO, gpio_reg); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); return 0; } static int bnx2x_gpio_int_write(struct bnx2x_softc *sc, int gpio_num, uint32_t mode, uint8_t port) { /* The GPIO should be swapped if swap register is set and active */ int gpio_port = ((REG_RD(sc, NIG_REG_PORT_SWAP) && REG_RD(sc, NIG_REG_STRAP_OVERRIDE)) ^ port); int gpio_shift = gpio_num; if (gpio_port) gpio_shift += MISC_REGISTERS_GPIO_PORT_SHIFT; uint32_t gpio_mask = (1 << gpio_shift); uint32_t gpio_reg; if (gpio_num > MISC_REGISTERS_GPIO_3) { PMD_DRV_LOG(NOTICE, "Invalid GPIO %d", gpio_num); return -1; } bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); /* read GPIO int */ gpio_reg = REG_RD(sc, MISC_REG_GPIO_INT); switch (mode) { case MISC_REGISTERS_GPIO_INT_OUTPUT_CLR: /* clear SET and set CLR */ gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS); gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS); break; case MISC_REGISTERS_GPIO_INT_OUTPUT_SET: /* clear CLR and set SET */ gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS); gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS); break; default: break; } REG_WR(sc, MISC_REG_GPIO_INT, gpio_reg); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_GPIO); return 0; } uint32_t elink_cb_gpio_read(struct bnx2x_softc * sc, uint16_t gpio_num, uint8_t port) { return bnx2x_gpio_read(sc, gpio_num, port); } uint8_t elink_cb_gpio_write(struct bnx2x_softc * sc, uint16_t gpio_num, uint8_t mode, /* 0=low 1=high */ uint8_t port) { return bnx2x_gpio_write(sc, gpio_num, mode, port); } uint8_t elink_cb_gpio_mult_write(struct bnx2x_softc * sc, uint8_t pins, uint8_t mode /* 0=low 1=high */ ) { return bnx2x_gpio_mult_write(sc, pins, mode); } uint8_t elink_cb_gpio_int_write(struct bnx2x_softc * sc, uint16_t gpio_num, uint8_t mode, /* 0=low 1=high */ uint8_t port) { return bnx2x_gpio_int_write(sc, gpio_num, mode, port); } void elink_cb_notify_link_changed(struct bnx2x_softc *sc) { REG_WR(sc, (MISC_REG_AEU_GENERAL_ATTN_12 + (SC_FUNC(sc) * sizeof(uint32_t))), 1); } /* send the MCP a request, block until there is a reply */ uint32_t elink_cb_fw_command(struct bnx2x_softc *sc, uint32_t command, uint32_t param) { int mb_idx = SC_FW_MB_IDX(sc); uint32_t seq; uint32_t rc = 0; uint32_t cnt = 1; uint8_t delay = CHIP_REV_IS_SLOW(sc) ? 100 : 10; seq = ++sc->fw_seq; SHMEM_WR(sc, func_mb[mb_idx].drv_mb_param, param); SHMEM_WR(sc, func_mb[mb_idx].drv_mb_header, (command | seq)); PMD_DRV_LOG(DEBUG, "wrote command 0x%08x to FW MB param 0x%08x", (command | seq), param); /* Let the FW do it's magic. GIve it up to 5 seconds... */ do { DELAY(delay * 1000); rc = SHMEM_RD(sc, func_mb[mb_idx].fw_mb_header); } while ((seq != (rc & FW_MSG_SEQ_NUMBER_MASK)) && (cnt++ < 500)); /* is this a reply to our command? */ if (seq == (rc & FW_MSG_SEQ_NUMBER_MASK)) { rc &= FW_MSG_CODE_MASK; } else { /* Ruh-roh! */ PMD_DRV_LOG(NOTICE, "FW failed to respond!"); rc = 0; } return rc; } static uint32_t bnx2x_fw_command(struct bnx2x_softc *sc, uint32_t command, uint32_t param) { return elink_cb_fw_command(sc, command, param); } static void __storm_memset_dma_mapping(struct bnx2x_softc *sc, uint32_t addr, phys_addr_t mapping) { REG_WR(sc, addr, U64_LO(mapping)); REG_WR(sc, (addr + 4), U64_HI(mapping)); } static void storm_memset_spq_addr(struct bnx2x_softc *sc, phys_addr_t mapping, uint16_t abs_fid) { uint32_t addr = (XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PAGE_BASE_OFFSET(abs_fid)); __storm_memset_dma_mapping(sc, addr, mapping); } static void storm_memset_vf_to_pf(struct bnx2x_softc *sc, uint16_t abs_fid, uint16_t pf_id) { REG_WR8(sc, (BAR_XSTRORM_INTMEM + XSTORM_VF_TO_PF_OFFSET(abs_fid)), pf_id); REG_WR8(sc, (BAR_CSTRORM_INTMEM + CSTORM_VF_TO_PF_OFFSET(abs_fid)), pf_id); REG_WR8(sc, (BAR_TSTRORM_INTMEM + TSTORM_VF_TO_PF_OFFSET(abs_fid)), pf_id); REG_WR8(sc, (BAR_USTRORM_INTMEM + USTORM_VF_TO_PF_OFFSET(abs_fid)), pf_id); } static void storm_memset_func_en(struct bnx2x_softc *sc, uint16_t abs_fid, uint8_t enable) { REG_WR8(sc, (BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(abs_fid)), enable); REG_WR8(sc, (BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(abs_fid)), enable); REG_WR8(sc, (BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(abs_fid)), enable); REG_WR8(sc, (BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(abs_fid)), enable); } static void storm_memset_eq_data(struct bnx2x_softc *sc, struct event_ring_data *eq_data, uint16_t pfid) { uint32_t addr; size_t size; addr = (BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_DATA_OFFSET(pfid)); size = sizeof(struct event_ring_data); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) eq_data); } static void storm_memset_eq_prod(struct bnx2x_softc *sc, uint16_t eq_prod, uint16_t pfid) { uint32_t addr = (BAR_CSTRORM_INTMEM + CSTORM_EVENT_RING_PROD_OFFSET(pfid)); REG_WR16(sc, addr, eq_prod); } /* * Post a slowpath command. * * A slowpath command is used to propogate a configuration change through * the controller in a controlled manner, allowing each STORM processor and * other H/W blocks to phase in the change. The commands sent on the * slowpath are referred to as ramrods. Depending on the ramrod used the * completion of the ramrod will occur in different ways. Here's a * breakdown of ramrods and how they complete: * * RAMROD_CMD_ID_ETH_PORT_SETUP * Used to setup the leading connection on a port. Completes on the * Receive Completion Queue (RCQ) of that port (typically fp[0]). * * RAMROD_CMD_ID_ETH_CLIENT_SETUP * Used to setup an additional connection on a port. Completes on the * RCQ of the multi-queue/RSS connection being initialized. * * RAMROD_CMD_ID_ETH_STAT_QUERY * Used to force the storm processors to update the statistics database * in host memory. This ramrod is send on the leading connection CID and * completes as an index increment of the CSTORM on the default status * block. * * RAMROD_CMD_ID_ETH_UPDATE * Used to update the state of the leading connection, usually to udpate * the RSS indirection table. Completes on the RCQ of the leading * connection. (Not currently used under FreeBSD until OS support becomes * available.) * * RAMROD_CMD_ID_ETH_HALT * Used when tearing down a connection prior to driver unload. Completes * on the RCQ of the multi-queue/RSS connection being torn down. Don't * use this on the leading connection. * * RAMROD_CMD_ID_ETH_SET_MAC * Sets the Unicast/Broadcast/Multicast used by the port. Completes on * the RCQ of the leading connection. * * RAMROD_CMD_ID_ETH_CFC_DEL * Used when tearing down a conneciton prior to driver unload. Completes * on the RCQ of the leading connection (since the current connection * has been completely removed from controller memory). * * RAMROD_CMD_ID_ETH_PORT_DEL * Used to tear down the leading connection prior to driver unload, * typically fp[0]. Completes as an index increment of the CSTORM on the * default status block. * * RAMROD_CMD_ID_ETH_FORWARD_SETUP * Used for connection offload. Completes on the RCQ of the multi-queue * RSS connection that is being offloaded. (Not currently used under * FreeBSD.) * * There can only be one command pending per function. * * Returns: * 0 = Success, !0 = Failure. */ /* must be called under the spq lock */ static inline struct eth_spe *bnx2x_sp_get_next(struct bnx2x_softc *sc) { struct eth_spe *next_spe = sc->spq_prod_bd; if (sc->spq_prod_bd == sc->spq_last_bd) { /* wrap back to the first eth_spq */ sc->spq_prod_bd = sc->spq; sc->spq_prod_idx = 0; } else { sc->spq_prod_bd++; sc->spq_prod_idx++; } return next_spe; } /* must be called under the spq lock */ static void bnx2x_sp_prod_update(struct bnx2x_softc *sc) { int func = SC_FUNC(sc); /* * Make sure that BD data is updated before writing the producer. * BD data is written to the memory, the producer is read from the * memory, thus we need a full memory barrier to ensure the ordering. */ mb(); REG_WR16(sc, (BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func)), sc->spq_prod_idx); mb(); } /** * bnx2x_is_contextless_ramrod - check if the current command ends on EQ * * @cmd: command to check * @cmd_type: command type */ static int bnx2x_is_contextless_ramrod(int cmd, int cmd_type) { if ((cmd_type == NONE_CONNECTION_TYPE) || (cmd == RAMROD_CMD_ID_ETH_FORWARD_SETUP) || (cmd == RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES) || (cmd == RAMROD_CMD_ID_ETH_FILTER_RULES) || (cmd == RAMROD_CMD_ID_ETH_MULTICAST_RULES) || (cmd == RAMROD_CMD_ID_ETH_SET_MAC) || (cmd == RAMROD_CMD_ID_ETH_RSS_UPDATE)) { return TRUE; } else { return FALSE; } } /** * bnx2x_sp_post - place a single command on an SP ring * * @sc: driver handle * @command: command to place (e.g. SETUP, FILTER_RULES, etc.) * @cid: SW CID the command is related to * @data_hi: command private data address (high 32 bits) * @data_lo: command private data address (low 32 bits) * @cmd_type: command type (e.g. NONE, ETH) * * SP data is handled as if it's always an address pair, thus data fields are * not swapped to little endian in upper functions. Instead this function swaps * data as if it's two uint32 fields. */ int bnx2x_sp_post(struct bnx2x_softc *sc, int command, int cid, uint32_t data_hi, uint32_t data_lo, int cmd_type) { struct eth_spe *spe; uint16_t type; int common; common = bnx2x_is_contextless_ramrod(command, cmd_type); if (common) { if (!atomic_load_acq_long(&sc->eq_spq_left)) { PMD_DRV_LOG(INFO, "EQ ring is full!"); return -1; } } else { if (!atomic_load_acq_long(&sc->cq_spq_left)) { PMD_DRV_LOG(INFO, "SPQ ring is full!"); return -1; } } spe = bnx2x_sp_get_next(sc); /* CID needs port number to be encoded int it */ spe->hdr.conn_and_cmd_data = htole32((command << SPE_HDR_CMD_ID_SHIFT) | HW_CID(sc, cid)); type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE; /* TBD: Check if it works for VFs */ type |= ((SC_FUNC(sc) << SPE_HDR_FUNCTION_ID_SHIFT) & SPE_HDR_FUNCTION_ID); spe->hdr.type = htole16(type); spe->data.update_data_addr.hi = htole32(data_hi); spe->data.update_data_addr.lo = htole32(data_lo); /* * It's ok if the actual decrement is issued towards the memory * somewhere between the lock and unlock. Thus no more explict * memory barrier is needed. */ if (common) { atomic_subtract_acq_long(&sc->eq_spq_left, 1); } else { atomic_subtract_acq_long(&sc->cq_spq_left, 1); } PMD_DRV_LOG(DEBUG, "SPQE[%x] (%x:%x) (cmd, common?) (%d,%d) hw_cid %x" "data (%x:%x) type(0x%x) left (CQ, EQ) (%lx,%lx)", sc->spq_prod_idx, (uint32_t) U64_HI(sc->spq_dma.paddr), (uint32_t) (U64_LO(sc->spq_dma.paddr) + (uint8_t *) sc->spq_prod_bd - (uint8_t *) sc->spq), command, common, HW_CID(sc, cid), data_hi, data_lo, type, atomic_load_acq_long(&sc->cq_spq_left), atomic_load_acq_long(&sc->eq_spq_left)); bnx2x_sp_prod_update(sc); return 0; } static void bnx2x_drv_pulse(struct bnx2x_softc *sc) { SHMEM_WR(sc, func_mb[SC_FW_MB_IDX(sc)].drv_pulse_mb, sc->fw_drv_pulse_wr_seq); } static int bnx2x_tx_queue_has_work(const struct bnx2x_fastpath *fp) { uint16_t hw_cons; struct bnx2x_tx_queue *txq = fp->sc->tx_queues[fp->index]; if (unlikely(!txq)) { PMD_TX_LOG(ERR, "ERROR: TX queue is NULL"); return 0; } mb(); /* status block fields can change */ hw_cons = le16toh(*fp->tx_cons_sb); return (hw_cons != txq->tx_pkt_head); } static uint8_t bnx2x_has_tx_work(struct bnx2x_fastpath *fp) { /* expand this for multi-cos if ever supported */ return bnx2x_tx_queue_has_work(fp); } static int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) { uint16_t rx_cq_cons_sb; struct bnx2x_rx_queue *rxq; rxq = fp->sc->rx_queues[fp->index]; if (unlikely(!rxq)) { PMD_RX_LOG(ERR, "ERROR: RX queue is NULL"); return 0; } mb(); /* status block fields can change */ rx_cq_cons_sb = le16toh(*fp->rx_cq_cons_sb); if (unlikely((rx_cq_cons_sb & MAX_RCQ_ENTRIES(rxq)) == MAX_RCQ_ENTRIES(rxq))) rx_cq_cons_sb++; return (rxq->rx_cq_head != rx_cq_cons_sb); } static void bnx2x_sp_event(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) { #ifdef RTE_LIBRTE_BNX2X_DEBUG int cid = SW_CID(rr_cqe->ramrod_cqe.conn_and_cmd_data); #endif int command = CQE_CMD(rr_cqe->ramrod_cqe.conn_and_cmd_data); enum ecore_queue_cmd drv_cmd = ECORE_Q_CMD_MAX; struct ecore_queue_sp_obj *q_obj = &BNX2X_SP_OBJ(sc, fp).q_obj; PMD_DRV_LOG(DEBUG, "fp=%d cid=%d got ramrod #%d state is %x type is %d", fp->index, cid, command, sc->state, rr_cqe->ramrod_cqe.ramrod_type); switch (command) { case (RAMROD_CMD_ID_ETH_CLIENT_UPDATE): PMD_DRV_LOG(DEBUG, "got UPDATE ramrod. CID %d", cid); drv_cmd = ECORE_Q_CMD_UPDATE; break; case (RAMROD_CMD_ID_ETH_CLIENT_SETUP): PMD_DRV_LOG(DEBUG, "got MULTI[%d] setup ramrod", cid); drv_cmd = ECORE_Q_CMD_SETUP; break; case (RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP): PMD_DRV_LOG(DEBUG, "got MULTI[%d] tx-only setup ramrod", cid); drv_cmd = ECORE_Q_CMD_SETUP_TX_ONLY; break; case (RAMROD_CMD_ID_ETH_HALT): PMD_DRV_LOG(DEBUG, "got MULTI[%d] halt ramrod", cid); drv_cmd = ECORE_Q_CMD_HALT; break; case (RAMROD_CMD_ID_ETH_TERMINATE): PMD_DRV_LOG(DEBUG, "got MULTI[%d] teminate ramrod", cid); drv_cmd = ECORE_Q_CMD_TERMINATE; break; case (RAMROD_CMD_ID_ETH_EMPTY): PMD_DRV_LOG(DEBUG, "got MULTI[%d] empty ramrod", cid); drv_cmd = ECORE_Q_CMD_EMPTY; break; default: PMD_DRV_LOG(DEBUG, "ERROR: unexpected MC reply (%d)" "on fp[%d]", command, fp->index); return; } if ((drv_cmd != ECORE_Q_CMD_MAX) && q_obj->complete_cmd(sc, q_obj, drv_cmd)) { /* * q_obj->complete_cmd() failure means that this was * an unexpected completion. * * In this case we don't want to increase the sc->spq_left * because apparently we haven't sent this command the first * place. */ // rte_panic("Unexpected SP completion"); return; } atomic_add_acq_long(&sc->cq_spq_left, 1); PMD_DRV_LOG(DEBUG, "sc->cq_spq_left 0x%lx", atomic_load_acq_long(&sc->cq_spq_left)); } static uint8_t bnx2x_rxeof(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp) { struct bnx2x_rx_queue *rxq; uint16_t bd_cons, bd_prod, bd_prod_fw, comp_ring_cons; uint16_t hw_cq_cons, sw_cq_cons, sw_cq_prod; rxq = sc->rx_queues[fp->index]; if (!rxq) { PMD_RX_LOG(ERR, "RX queue %d is NULL", fp->index); return 0; } /* CQ "next element" is of the size of the regular element */ hw_cq_cons = le16toh(*fp->rx_cq_cons_sb); if (unlikely((hw_cq_cons & USABLE_RCQ_ENTRIES_PER_PAGE) == USABLE_RCQ_ENTRIES_PER_PAGE)) { hw_cq_cons++; } bd_cons = rxq->rx_bd_head; bd_prod = rxq->rx_bd_tail; bd_prod_fw = bd_prod; sw_cq_cons = rxq->rx_cq_head; sw_cq_prod = rxq->rx_cq_tail; /* * Memory barrier necessary as speculative reads of the rx * buffer can be ahead of the index in the status block */ rmb(); while (sw_cq_cons != hw_cq_cons) { union eth_rx_cqe *cqe; struct eth_fast_path_rx_cqe *cqe_fp; uint8_t cqe_fp_flags; enum eth_rx_cqe_type cqe_fp_type; comp_ring_cons = RCQ_ENTRY(sw_cq_cons, rxq); bd_prod = RX_BD(bd_prod, rxq); bd_cons = RX_BD(bd_cons, rxq); cqe = &rxq->cq_ring[comp_ring_cons]; cqe_fp = &cqe->fast_path_cqe; cqe_fp_flags = cqe_fp->type_error_flags; cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE; /* is this a slowpath msg? */ if (CQE_TYPE_SLOW(cqe_fp_type)) { bnx2x_sp_event(sc, fp, cqe); goto next_cqe; } /* is this an error packet? */ if (unlikely(cqe_fp_flags & ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG)) { PMD_RX_LOG(DEBUG, "flags 0x%x rx packet %u", cqe_fp_flags, sw_cq_cons); goto next_rx; } PMD_RX_LOG(DEBUG, "Dropping fastpath called from attn poller!"); next_rx: bd_cons = NEXT_RX_BD(bd_cons); bd_prod = NEXT_RX_BD(bd_prod); bd_prod_fw = NEXT_RX_BD(bd_prod_fw); next_cqe: sw_cq_prod = NEXT_RCQ_IDX(sw_cq_prod); sw_cq_cons = NEXT_RCQ_IDX(sw_cq_cons); } /* while work to do */ rxq->rx_bd_head = bd_cons; rxq->rx_bd_tail = bd_prod_fw; rxq->rx_cq_head = sw_cq_cons; rxq->rx_cq_tail = sw_cq_prod; /* Update producers */ bnx2x_update_rx_prod(sc, fp, bd_prod_fw, sw_cq_prod); return (sw_cq_cons != hw_cq_cons); } static uint16_t bnx2x_free_tx_pkt(__rte_unused struct bnx2x_fastpath *fp, struct bnx2x_tx_queue *txq, uint16_t pkt_idx, uint16_t bd_idx) { struct eth_tx_start_bd *tx_start_bd = &txq->tx_ring[TX_BD(bd_idx, txq)].start_bd; uint16_t nbd = rte_le_to_cpu_16(tx_start_bd->nbd); struct rte_mbuf *tx_mbuf = txq->sw_ring[TX_BD(pkt_idx, txq)]; if (likely(tx_mbuf != NULL)) { rte_pktmbuf_free(tx_mbuf); } else { PMD_RX_LOG(ERR, "fp[%02d] lost mbuf %lu", fp->index, (unsigned long)TX_BD(pkt_idx, txq)); } txq->sw_ring[TX_BD(pkt_idx, txq)] = NULL; txq->nb_tx_avail += nbd; while (nbd--) bd_idx = NEXT_TX_BD(bd_idx); return bd_idx; } /* processes transmit completions */ uint8_t bnx2x_txeof(__rte_unused struct bnx2x_softc * sc, struct bnx2x_fastpath * fp) { uint16_t bd_cons, hw_cons, sw_cons; __rte_unused uint16_t tx_bd_avail; struct bnx2x_tx_queue *txq = fp->sc->tx_queues[fp->index]; if (unlikely(!txq)) { PMD_TX_LOG(ERR, "ERROR: TX queue is NULL"); return 0; } bd_cons = txq->tx_bd_head; hw_cons = rte_le_to_cpu_16(*fp->tx_cons_sb); sw_cons = txq->tx_pkt_head; while (sw_cons != hw_cons) { bd_cons = bnx2x_free_tx_pkt(fp, txq, sw_cons, bd_cons); sw_cons++; } txq->tx_pkt_head = sw_cons; txq->tx_bd_head = bd_cons; tx_bd_avail = txq->nb_tx_avail; PMD_TX_LOG(DEBUG, "fp[%02d] avail=%u cons_sb=%u, " "pkt_head=%u pkt_tail=%u bd_head=%u bd_tail=%u", fp->index, tx_bd_avail, hw_cons, txq->tx_pkt_head, txq->tx_pkt_tail, txq->tx_bd_head, txq->tx_bd_tail); return TRUE; } static void bnx2x_drain_tx_queues(struct bnx2x_softc *sc) { struct bnx2x_fastpath *fp; int i, count; /* wait until all TX fastpath tasks have completed */ for (i = 0; i < sc->num_queues; i++) { fp = &sc->fp[i]; count = 1000; while (bnx2x_has_tx_work(fp)) { bnx2x_txeof(sc, fp); if (count == 0) { PMD_TX_LOG(ERR, "Timeout waiting for fp[%d] " "transmits to complete!", i); rte_panic("tx drain failure"); return; } count--; DELAY(1000); rmb(); } } return; } static int bnx2x_del_all_macs(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *mac_obj, int mac_type, uint8_t wait_for_comp) { unsigned long ramrod_flags = 0, vlan_mac_flags = 0; int rc; /* wait for completion of requested */ if (wait_for_comp) { bnx2x_set_bit(RAMROD_COMP_WAIT, &ramrod_flags); } /* Set the mac type of addresses we want to clear */ bnx2x_set_bit(mac_type, &vlan_mac_flags); rc = mac_obj->delete_all(sc, mac_obj, &vlan_mac_flags, &ramrod_flags); if (rc < 0) PMD_DRV_LOG(ERR, "Failed to delete MACs (%d)", rc); return rc; } int bnx2x_fill_accept_flags(struct bnx2x_softc *sc, uint32_t rx_mode, unsigned long *rx_accept_flags, unsigned long *tx_accept_flags) { /* Clear the flags first */ *rx_accept_flags = 0; *tx_accept_flags = 0; switch (rx_mode) { case BNX2X_RX_MODE_NONE: /* * 'drop all' supersedes any accept flags that may have been * passed to the function. */ break; case BNX2X_RX_MODE_NORMAL: bnx2x_set_bit(ECORE_ACCEPT_UNICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_MULTICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, rx_accept_flags); /* internal switching mode */ bnx2x_set_bit(ECORE_ACCEPT_UNICAST, tx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_MULTICAST, tx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, tx_accept_flags); break; case BNX2X_RX_MODE_ALLMULTI: bnx2x_set_bit(ECORE_ACCEPT_UNICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_ALL_MULTICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, rx_accept_flags); /* internal switching mode */ bnx2x_set_bit(ECORE_ACCEPT_UNICAST, tx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_ALL_MULTICAST, tx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, tx_accept_flags); break; case BNX2X_RX_MODE_PROMISC: /* * According to deffinition of SI mode, iface in promisc mode * should receive matched and unmatched (in resolution of port) * unicast packets. */ bnx2x_set_bit(ECORE_ACCEPT_UNMATCHED, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_UNICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_ALL_MULTICAST, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, rx_accept_flags); /* internal switching mode */ bnx2x_set_bit(ECORE_ACCEPT_ALL_MULTICAST, tx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_BROADCAST, tx_accept_flags); if (IS_MF_SI(sc)) { bnx2x_set_bit(ECORE_ACCEPT_ALL_UNICAST, tx_accept_flags); } else { bnx2x_set_bit(ECORE_ACCEPT_UNICAST, tx_accept_flags); } break; default: PMD_RX_LOG(ERR, "Unknown rx_mode (%d)", rx_mode); return -1; } /* Set ACCEPT_ANY_VLAN as we do not enable filtering by VLAN */ if (rx_mode != BNX2X_RX_MODE_NONE) { bnx2x_set_bit(ECORE_ACCEPT_ANY_VLAN, rx_accept_flags); bnx2x_set_bit(ECORE_ACCEPT_ANY_VLAN, tx_accept_flags); } return 0; } static int bnx2x_set_q_rx_mode(struct bnx2x_softc *sc, uint8_t cl_id, unsigned long rx_mode_flags, unsigned long rx_accept_flags, unsigned long tx_accept_flags, unsigned long ramrod_flags) { struct ecore_rx_mode_ramrod_params ramrod_param; int rc; memset(&ramrod_param, 0, sizeof(ramrod_param)); /* Prepare ramrod parameters */ ramrod_param.cid = 0; ramrod_param.cl_id = cl_id; ramrod_param.rx_mode_obj = &sc->rx_mode_obj; ramrod_param.func_id = SC_FUNC(sc); ramrod_param.pstate = &sc->sp_state; ramrod_param.state = ECORE_FILTER_RX_MODE_PENDING; ramrod_param.rdata = BNX2X_SP(sc, rx_mode_rdata); ramrod_param.rdata_mapping = (phys_addr_t)BNX2X_SP_MAPPING(sc, rx_mode_rdata), bnx2x_set_bit(ECORE_FILTER_RX_MODE_PENDING, &sc->sp_state); ramrod_param.ramrod_flags = ramrod_flags; ramrod_param.rx_mode_flags = rx_mode_flags; ramrod_param.rx_accept_flags = rx_accept_flags; ramrod_param.tx_accept_flags = tx_accept_flags; rc = ecore_config_rx_mode(sc, &ramrod_param); if (rc < 0) { PMD_RX_LOG(ERR, "Set rx_mode %d failed", sc->rx_mode); return rc; } return 0; } int bnx2x_set_storm_rx_mode(struct bnx2x_softc *sc) { unsigned long rx_mode_flags = 0, ramrod_flags = 0; unsigned long rx_accept_flags = 0, tx_accept_flags = 0; int rc; rc = bnx2x_fill_accept_flags(sc, sc->rx_mode, &rx_accept_flags, &tx_accept_flags); if (rc) { return rc; } bnx2x_set_bit(RAMROD_RX, &ramrod_flags); bnx2x_set_bit(RAMROD_TX, &ramrod_flags); bnx2x_set_bit(RAMROD_COMP_WAIT, &ramrod_flags); return bnx2x_set_q_rx_mode(sc, sc->fp[0].cl_id, rx_mode_flags, rx_accept_flags, tx_accept_flags, ramrod_flags); } /* returns the "mcp load_code" according to global load_count array */ static int bnx2x_nic_load_no_mcp(struct bnx2x_softc *sc) { int path = SC_PATH(sc); int port = SC_PORT(sc); PMD_DRV_LOG(INFO, "NO MCP - load counts[%d] %d, %d, %d", path, load_count[path][0], load_count[path][1], load_count[path][2]); load_count[path][0]++; load_count[path][1 + port]++; PMD_DRV_LOG(INFO, "NO MCP - new load counts[%d] %d, %d, %d", path, load_count[path][0], load_count[path][1], load_count[path][2]); if (load_count[path][0] == 1) return FW_MSG_CODE_DRV_LOAD_COMMON; else if (load_count[path][1 + port] == 1) return FW_MSG_CODE_DRV_LOAD_PORT; else return FW_MSG_CODE_DRV_LOAD_FUNCTION; } /* returns the "mcp load_code" according to global load_count array */ static int bnx2x_nic_unload_no_mcp(struct bnx2x_softc *sc) { int port = SC_PORT(sc); int path = SC_PATH(sc); PMD_DRV_LOG(INFO, "NO MCP - load counts[%d] %d, %d, %d", path, load_count[path][0], load_count[path][1], load_count[path][2]); load_count[path][0]--; load_count[path][1 + port]--; PMD_DRV_LOG(INFO, "NO MCP - new load counts[%d] %d, %d, %d", path, load_count[path][0], load_count[path][1], load_count[path][2]); if (load_count[path][0] == 0) { return FW_MSG_CODE_DRV_UNLOAD_COMMON; } else if (load_count[path][1 + port] == 0) { return FW_MSG_CODE_DRV_UNLOAD_PORT; } else { return FW_MSG_CODE_DRV_UNLOAD_FUNCTION; } } /* request unload mode from the MCP: COMMON, PORT or FUNCTION */ static uint32_t bnx2x_send_unload_req(struct bnx2x_softc *sc, int unload_mode) { uint32_t reset_code = 0; /* Select the UNLOAD request mode */ if (unload_mode == UNLOAD_NORMAL) { reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; } else { reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; } /* Send the request to the MCP */ if (!BNX2X_NOMCP(sc)) { reset_code = bnx2x_fw_command(sc, reset_code, 0); } else { reset_code = bnx2x_nic_unload_no_mcp(sc); } return reset_code; } /* send UNLOAD_DONE command to the MCP */ static void bnx2x_send_unload_done(struct bnx2x_softc *sc, uint8_t keep_link) { uint32_t reset_param = keep_link ? DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET : 0; /* Report UNLOAD_DONE to MCP */ if (!BNX2X_NOMCP(sc)) { bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_DONE, reset_param); } } static int bnx2x_func_wait_started(struct bnx2x_softc *sc) { int tout = 50; if (!sc->port.pmf) { return 0; } /* * (assumption: No Attention from MCP at this stage) * PMF probably in the middle of TX disable/enable transaction * 1. Sync IRS for default SB * 2. Sync SP queue - this guarantees us that attention handling started * 3. Wait, that TX disable/enable transaction completes * * 1+2 guarantee that if DCBX attention was scheduled it already changed * pending bit of transaction from STARTED-->TX_STOPPED, if we already * received completion for the transaction the state is TX_STOPPED. * State will return to STARTED after completion of TX_STOPPED-->STARTED * transaction. */ while (ecore_func_get_state(sc, &sc->func_obj) != ECORE_F_STATE_STARTED && tout--) { DELAY(20000); } if (ecore_func_get_state(sc, &sc->func_obj) != ECORE_F_STATE_STARTED) { /* * Failed to complete the transaction in a "good way" * Force both transactions with CLR bit. */ struct ecore_func_state_params func_params = { NULL }; PMD_DRV_LOG(NOTICE, "Unexpected function state! " "Forcing STARTED-->TX_STOPPED-->STARTED"); func_params.f_obj = &sc->func_obj; bnx2x_set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags); /* STARTED-->TX_STOPPED */ func_params.cmd = ECORE_F_CMD_TX_STOP; ecore_func_state_change(sc, &func_params); /* TX_STOPPED-->STARTED */ func_params.cmd = ECORE_F_CMD_TX_START; return ecore_func_state_change(sc, &func_params); } return 0; } static int bnx2x_stop_queue(struct bnx2x_softc *sc, int index) { struct bnx2x_fastpath *fp = &sc->fp[index]; struct ecore_queue_state_params q_params = { NULL }; int rc; PMD_DRV_LOG(DEBUG, "stopping queue %d cid %d", index, fp->index); q_params.q_obj = &sc->sp_objs[fp->index].q_obj; /* We want to wait for completion in this context */ bnx2x_set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); /* Stop the primary connection: */ /* ...halt the connection */ q_params.cmd = ECORE_Q_CMD_HALT; rc = ecore_queue_state_change(sc, &q_params); if (rc) { return rc; } /* ...terminate the connection */ q_params.cmd = ECORE_Q_CMD_TERMINATE; memset(&q_params.params.terminate, 0, sizeof(q_params.params.terminate)); q_params.params.terminate.cid_index = FIRST_TX_COS_INDEX; rc = ecore_queue_state_change(sc, &q_params); if (rc) { return rc; } /* ...delete cfc entry */ q_params.cmd = ECORE_Q_CMD_CFC_DEL; memset(&q_params.params.cfc_del, 0, sizeof(q_params.params.cfc_del)); q_params.params.cfc_del.cid_index = FIRST_TX_COS_INDEX; return ecore_queue_state_change(sc, &q_params); } /* wait for the outstanding SP commands */ static uint8_t bnx2x_wait_sp_comp(struct bnx2x_softc *sc, unsigned long mask) { unsigned long tmp; int tout = 5000; /* wait for 5 secs tops */ while (tout--) { mb(); if (!(atomic_load_acq_long(&sc->sp_state) & mask)) { return TRUE; } DELAY(1000); } mb(); tmp = atomic_load_acq_long(&sc->sp_state); if (tmp & mask) { PMD_DRV_LOG(INFO, "Filtering completion timed out: " "sp_state 0x%lx, mask 0x%lx", tmp, mask); return FALSE; } return FALSE; } static int bnx2x_func_stop(struct bnx2x_softc *sc) { struct ecore_func_state_params func_params = { NULL }; int rc; /* prepare parameters for function state transitions */ bnx2x_set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); func_params.f_obj = &sc->func_obj; func_params.cmd = ECORE_F_CMD_STOP; /* * Try to stop the function the 'good way'. If it fails (in case * of a parity error during bnx2x_chip_cleanup()) and we are * not in a debug mode, perform a state transaction in order to * enable further HW_RESET transaction. */ rc = ecore_func_state_change(sc, &func_params); if (rc) { PMD_DRV_LOG(NOTICE, "FUNC_STOP ramrod failed. " "Running a dry transaction"); bnx2x_set_bit(RAMROD_DRV_CLR_ONLY, &func_params.ramrod_flags); return ecore_func_state_change(sc, &func_params); } return 0; } static int bnx2x_reset_hw(struct bnx2x_softc *sc, uint32_t load_code) { struct ecore_func_state_params func_params = { NULL }; /* Prepare parameters for function state transitions */ bnx2x_set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); func_params.f_obj = &sc->func_obj; func_params.cmd = ECORE_F_CMD_HW_RESET; func_params.params.hw_init.load_phase = load_code; return ecore_func_state_change(sc, &func_params); } static void bnx2x_int_disable_sync(struct bnx2x_softc *sc, int disable_hw) { if (disable_hw) { /* prevent the HW from sending interrupts */ bnx2x_int_disable(sc); } } static void bnx2x_chip_cleanup(struct bnx2x_softc *sc, uint32_t unload_mode, uint8_t keep_link) { int port = SC_PORT(sc); struct ecore_mcast_ramrod_params rparam = { NULL }; uint32_t reset_code; int i, rc = 0; bnx2x_drain_tx_queues(sc); /* give HW time to discard old tx messages */ DELAY(1000); /* Clean all ETH MACs */ rc = bnx2x_del_all_macs(sc, &sc->sp_objs[0].mac_obj, ECORE_ETH_MAC, FALSE); if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to delete all ETH MACs (%d)", rc); } /* Clean up UC list */ rc = bnx2x_del_all_macs(sc, &sc->sp_objs[0].mac_obj, ECORE_UC_LIST_MAC, TRUE); if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to delete UC MACs list (%d)", rc); } /* Disable LLH */ REG_WR(sc, NIG_REG_LLH0_FUNC_EN + port * 8, 0); /* Set "drop all" to stop Rx */ /* * We need to take the if_maddr_lock() here in order to prevent * a race between the completion code and this code. */ if (bnx2x_test_bit(ECORE_FILTER_RX_MODE_PENDING, &sc->sp_state)) { bnx2x_set_bit(ECORE_FILTER_RX_MODE_SCHED, &sc->sp_state); } else { bnx2x_set_storm_rx_mode(sc); } /* Clean up multicast configuration */ rparam.mcast_obj = &sc->mcast_obj; rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_DEL); if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to send DEL MCAST command (%d)", rc); } /* * Send the UNLOAD_REQUEST to the MCP. This will return if * this function should perform FUNCTION, PORT, or COMMON HW * reset. */ reset_code = bnx2x_send_unload_req(sc, unload_mode); /* * (assumption: No Attention from MCP at this stage) * PMF probably in the middle of TX disable/enable transaction */ rc = bnx2x_func_wait_started(sc); if (rc) { PMD_DRV_LOG(NOTICE, "bnx2x_func_wait_started failed"); } /* * Close multi and leading connections * Completions for ramrods are collected in a synchronous way */ for (i = 0; i < sc->num_queues; i++) { if (bnx2x_stop_queue(sc, i)) { goto unload_error; } } /* * If SP settings didn't get completed so far - something * very wrong has happen. */ if (!bnx2x_wait_sp_comp(sc, ~0x0UL)) { PMD_DRV_LOG(NOTICE, "Common slow path ramrods got stuck!"); } unload_error: rc = bnx2x_func_stop(sc); if (rc) { PMD_DRV_LOG(NOTICE, "Function stop failed!"); } /* disable HW interrupts */ bnx2x_int_disable_sync(sc, TRUE); /* Reset the chip */ rc = bnx2x_reset_hw(sc, reset_code); if (rc) { PMD_DRV_LOG(NOTICE, "Hardware reset failed"); } /* Report UNLOAD_DONE to MCP */ bnx2x_send_unload_done(sc, keep_link); } static void bnx2x_disable_close_the_gate(struct bnx2x_softc *sc) { uint32_t val; PMD_DRV_LOG(DEBUG, "Disabling 'close the gates'"); val = REG_RD(sc, MISC_REG_AEU_GENERAL_MASK); val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK | MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK); REG_WR(sc, MISC_REG_AEU_GENERAL_MASK, val); } /* * Cleans the object that have internal lists without sending * ramrods. Should be run when interrutps are disabled. */ static void bnx2x_squeeze_objects(struct bnx2x_softc *sc) { unsigned long ramrod_flags = 0, vlan_mac_flags = 0; struct ecore_mcast_ramrod_params rparam = { NULL }; struct ecore_vlan_mac_obj *mac_obj = &sc->sp_objs->mac_obj; int rc; /* Cleanup MACs' object first... */ /* Wait for completion of requested */ bnx2x_set_bit(RAMROD_COMP_WAIT, &ramrod_flags); /* Perform a dry cleanup */ bnx2x_set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags); /* Clean ETH primary MAC */ bnx2x_set_bit(ECORE_ETH_MAC, &vlan_mac_flags); rc = mac_obj->delete_all(sc, &sc->sp_objs->mac_obj, &vlan_mac_flags, &ramrod_flags); if (rc != 0) { PMD_DRV_LOG(NOTICE, "Failed to clean ETH MACs (%d)", rc); } /* Cleanup UC list */ vlan_mac_flags = 0; bnx2x_set_bit(ECORE_UC_LIST_MAC, &vlan_mac_flags); rc = mac_obj->delete_all(sc, mac_obj, &vlan_mac_flags, &ramrod_flags); if (rc != 0) { PMD_DRV_LOG(NOTICE, "Failed to clean UC list MACs (%d)", rc); } /* Now clean mcast object... */ rparam.mcast_obj = &sc->mcast_obj; bnx2x_set_bit(RAMROD_DRV_CLR_ONLY, &rparam.ramrod_flags); /* Add a DEL command... */ rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_DEL); if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to send DEL MCAST command (%d)", rc); } /* now wait until all pending commands are cleared */ rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_CONT); while (rc != 0) { if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to clean MCAST object (%d)", rc); return; } rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_CONT); } } /* stop the controller */ __attribute__ ((noinline)) int bnx2x_nic_unload(struct bnx2x_softc *sc, uint32_t unload_mode, uint8_t keep_link) { uint8_t global = FALSE; uint32_t val; PMD_DRV_LOG(DEBUG, "Starting NIC unload..."); /* stop the periodic callout */ bnx2x_periodic_stop(sc); /* mark driver as unloaded in shmem2 */ if (IS_PF(sc) && SHMEM2_HAS(sc, drv_capabilities_flag)) { val = SHMEM2_RD(sc, drv_capabilities_flag[SC_FW_MB_IDX(sc)]); SHMEM2_WR(sc, drv_capabilities_flag[SC_FW_MB_IDX(sc)], val & ~DRV_FLAGS_CAPABILITIES_LOADED_L2); } if (IS_PF(sc) && sc->recovery_state != BNX2X_RECOVERY_DONE && (sc->state == BNX2X_STATE_CLOSED || sc->state == BNX2X_STATE_ERROR)) { /* * We can get here if the driver has been unloaded * during parity error recovery and is either waiting for a * leader to complete or for other functions to unload and * then ifconfig down has been issued. In this case we want to * unload and let other functions to complete a recovery * process. */ sc->recovery_state = BNX2X_RECOVERY_DONE; sc->is_leader = 0; bnx2x_release_leader_lock(sc); mb(); PMD_DRV_LOG(NOTICE, "Can't unload in closed or error state"); return -1; } /* * Nothing to do during unload if previous bnx2x_nic_load() * did not completed succesfully - all resourses are released. */ if ((sc->state == BNX2X_STATE_CLOSED) || (sc->state == BNX2X_STATE_ERROR)) { return 0; } sc->state = BNX2X_STATE_CLOSING_WAITING_HALT; mb(); sc->rx_mode = BNX2X_RX_MODE_NONE; bnx2x_set_rx_mode(sc); mb(); if (IS_PF(sc)) { /* set ALWAYS_ALIVE bit in shmem */ sc->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE; bnx2x_drv_pulse(sc); bnx2x_stats_handle(sc, STATS_EVENT_STOP); bnx2x_save_statistics(sc); } /* wait till consumers catch up with producers in all queues */ bnx2x_drain_tx_queues(sc); /* if VF indicate to PF this function is going down (PF will delete sp * elements and clear initializations */ if (IS_VF(sc)) { bnx2x_vf_unload(sc); } else if (unload_mode != UNLOAD_RECOVERY) { /* if this is a normal/close unload need to clean up chip */ bnx2x_chip_cleanup(sc, unload_mode, keep_link); } else { /* Send the UNLOAD_REQUEST to the MCP */ bnx2x_send_unload_req(sc, unload_mode); /* * Prevent transactions to host from the functions on the * engine that doesn't reset global blocks in case of global * attention once gloabl blocks are reset and gates are opened * (the engine which leader will perform the recovery * last). */ if (!CHIP_IS_E1x(sc)) { bnx2x_pf_disable(sc); } /* disable HW interrupts */ bnx2x_int_disable_sync(sc, TRUE); /* Report UNLOAD_DONE to MCP */ bnx2x_send_unload_done(sc, FALSE); } /* * At this stage no more interrupts will arrive so we may safely clean * the queue'able objects here in case they failed to get cleaned so far. */ if (IS_PF(sc)) { bnx2x_squeeze_objects(sc); } /* There should be no more pending SP commands at this stage */ sc->sp_state = 0; sc->port.pmf = 0; if (IS_PF(sc)) { bnx2x_free_mem(sc); } bnx2x_free_fw_stats_mem(sc); sc->state = BNX2X_STATE_CLOSED; /* * Check if there are pending parity attentions. If there are - set * RECOVERY_IN_PROGRESS. */ if (IS_PF(sc) && bnx2x_chk_parity_attn(sc, &global, FALSE)) { bnx2x_set_reset_in_progress(sc); /* Set RESET_IS_GLOBAL if needed */ if (global) { bnx2x_set_reset_global(sc); } } /* * The last driver must disable a "close the gate" if there is no * parity attention or "process kill" pending. */ if (IS_PF(sc) && !bnx2x_clear_pf_load(sc) && bnx2x_reset_is_done(sc, SC_PATH(sc))) { bnx2x_disable_close_the_gate(sc); } PMD_DRV_LOG(DEBUG, "Ended NIC unload"); return 0; } /* * Encapsulte an mbuf cluster into the tx bd chain and makes the memory * visible to the controller. * * If an mbuf is submitted to this routine and cannot be given to the * controller (e.g. it has too many fragments) then the function may free * the mbuf and return to the caller. * * Returns: * 0 = Success, !0 = Failure * Note the side effect that an mbuf may be freed if it causes a problem. */ int bnx2x_tx_encap(struct bnx2x_tx_queue *txq, struct rte_mbuf **m_head, int m_pkts) { struct rte_mbuf *m0; struct eth_tx_start_bd *tx_start_bd; uint16_t bd_prod, pkt_prod; int m_tx; struct bnx2x_softc *sc; uint32_t nbds = 0; struct bnx2x_fastpath *fp; sc = txq->sc; fp = &sc->fp[txq->queue_id]; bd_prod = txq->tx_bd_tail; pkt_prod = txq->tx_pkt_tail; for (m_tx = 0; m_tx < m_pkts; m_tx++) { m0 = *m_head++; if (unlikely(txq->nb_tx_avail < 3)) { PMD_TX_LOG(ERR, "no enough bds %d/%d", bd_prod, txq->nb_tx_avail); return -ENOMEM; } txq->sw_ring[TX_BD(pkt_prod, txq)] = m0; tx_start_bd = &txq->tx_ring[TX_BD(bd_prod, txq)].start_bd; tx_start_bd->addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR(m0)); tx_start_bd->nbytes = rte_cpu_to_le_16(m0->data_len); tx_start_bd->bd_flags.as_bitfield = ETH_TX_BD_FLAGS_START_BD; tx_start_bd->general_data = (1 << ETH_TX_START_BD_HDR_NBDS_SHIFT); tx_start_bd->nbd = rte_cpu_to_le_16(2); if (m0->ol_flags & PKT_TX_VLAN_PKT) { tx_start_bd->vlan_or_ethertype = rte_cpu_to_le_16(m0->vlan_tci); tx_start_bd->bd_flags.as_bitfield |= (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT); } else { if (IS_PF(sc)) tx_start_bd->vlan_or_ethertype = rte_cpu_to_le_16(pkt_prod); else { struct ether_hdr *eh = rte_pktmbuf_mtod(m0, struct ether_hdr *); tx_start_bd->vlan_or_ethertype = eh->ether_type; } } bd_prod = NEXT_TX_BD(bd_prod); if (IS_VF(sc)) { struct eth_tx_parse_bd_e2 *tx_parse_bd; uint8_t *data = rte_pktmbuf_mtod(m0, uint8_t *); tx_parse_bd = &txq->tx_ring[TX_BD(bd_prod, txq)].parse_bd_e2; tx_parse_bd->parsing_data = (1 << ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT); rte_memcpy(&tx_parse_bd->data.mac_addr.dst_hi, &data[0], 2); rte_memcpy(&tx_parse_bd->data.mac_addr.dst_mid, &data[2], 2); rte_memcpy(&tx_parse_bd->data.mac_addr.dst_lo, &data[4], 2); rte_memcpy(&tx_parse_bd->data.mac_addr.src_hi, &data[6], 2); rte_memcpy(&tx_parse_bd->data.mac_addr.src_mid, &data[8], 2); rte_memcpy(&tx_parse_bd->data.mac_addr.src_lo, &data[10], 2); tx_parse_bd->data.mac_addr.dst_hi = rte_cpu_to_be_16(tx_parse_bd->data.mac_addr.dst_hi); tx_parse_bd->data.mac_addr.dst_mid = rte_cpu_to_be_16(tx_parse_bd->data. mac_addr.dst_mid); tx_parse_bd->data.mac_addr.dst_lo = rte_cpu_to_be_16(tx_parse_bd->data.mac_addr.dst_lo); tx_parse_bd->data.mac_addr.src_hi = rte_cpu_to_be_16(tx_parse_bd->data.mac_addr.src_hi); tx_parse_bd->data.mac_addr.src_mid = rte_cpu_to_be_16(tx_parse_bd->data. mac_addr.src_mid); tx_parse_bd->data.mac_addr.src_lo = rte_cpu_to_be_16(tx_parse_bd->data.mac_addr.src_lo); PMD_TX_LOG(DEBUG, "PBD dst %x %x %x src %x %x %x p_data %x", tx_parse_bd->data.mac_addr.dst_hi, tx_parse_bd->data.mac_addr.dst_mid, tx_parse_bd->data.mac_addr.dst_lo, tx_parse_bd->data.mac_addr.src_hi, tx_parse_bd->data.mac_addr.src_mid, tx_parse_bd->data.mac_addr.src_lo, tx_parse_bd->parsing_data); } PMD_TX_LOG(DEBUG, "start bd: nbytes %d flags %x vlan %x\n", tx_start_bd->nbytes, tx_start_bd->bd_flags.as_bitfield, tx_start_bd->vlan_or_ethertype); bd_prod = NEXT_TX_BD(bd_prod); pkt_prod++; if (TX_IDX(bd_prod) < 2) { nbds++; } } txq->nb_tx_avail -= m_pkts << 1; txq->tx_bd_tail = bd_prod; txq->tx_pkt_tail = pkt_prod; mb(); fp->tx_db.data.prod += (m_pkts << 1) + nbds; DOORBELL(sc, txq->queue_id, fp->tx_db.raw); mb(); return 0; } static uint16_t bnx2x_cid_ilt_lines(struct bnx2x_softc *sc) { return L2_ILT_LINES(sc); } static void bnx2x_ilt_set_info(struct bnx2x_softc *sc) { struct ilt_client_info *ilt_client; struct ecore_ilt *ilt = sc->ilt; uint16_t line = 0; PMD_INIT_FUNC_TRACE(); ilt->start_line = FUNC_ILT_BASE(SC_FUNC(sc)); /* CDU */ ilt_client = &ilt->clients[ILT_CLIENT_CDU]; ilt_client->client_num = ILT_CLIENT_CDU; ilt_client->page_size = CDU_ILT_PAGE_SZ; ilt_client->flags = ILT_CLIENT_SKIP_MEM; ilt_client->start = line; line += bnx2x_cid_ilt_lines(sc); if (CNIC_SUPPORT(sc)) { line += CNIC_ILT_LINES; } ilt_client->end = (line - 1); /* QM */ if (QM_INIT(sc->qm_cid_count)) { ilt_client = &ilt->clients[ILT_CLIENT_QM]; ilt_client->client_num = ILT_CLIENT_QM; ilt_client->page_size = QM_ILT_PAGE_SZ; ilt_client->flags = 0; ilt_client->start = line; /* 4 bytes for each cid */ line += DIV_ROUND_UP(sc->qm_cid_count * QM_QUEUES_PER_FUNC * 4, QM_ILT_PAGE_SZ); ilt_client->end = (line - 1); } if (CNIC_SUPPORT(sc)) { /* SRC */ ilt_client = &ilt->clients[ILT_CLIENT_SRC]; ilt_client->client_num = ILT_CLIENT_SRC; ilt_client->page_size = SRC_ILT_PAGE_SZ; ilt_client->flags = 0; ilt_client->start = line; line += SRC_ILT_LINES; ilt_client->end = (line - 1); /* TM */ ilt_client = &ilt->clients[ILT_CLIENT_TM]; ilt_client->client_num = ILT_CLIENT_TM; ilt_client->page_size = TM_ILT_PAGE_SZ; ilt_client->flags = 0; ilt_client->start = line; line += TM_ILT_LINES; ilt_client->end = (line - 1); } assert((line <= ILT_MAX_LINES)); } static void bnx2x_set_fp_rx_buf_size(struct bnx2x_softc *sc) { int i; for (i = 0; i < sc->num_queues; i++) { /* get the Rx buffer size for RX frames */ sc->fp[i].rx_buf_size = (IP_HEADER_ALIGNMENT_PADDING + ETH_OVERHEAD + sc->mtu); /* get the mbuf allocation size for RX frames */ if (sc->fp[i].rx_buf_size <= MCLBYTES) { sc->fp[i].mbuf_alloc_size = MCLBYTES; } else if (sc->fp[i].rx_buf_size <= BNX2X_PAGE_SIZE) { sc->fp[i].mbuf_alloc_size = PAGE_SIZE; } else { sc->fp[i].mbuf_alloc_size = MJUM9BYTES; } } } int bnx2x_alloc_ilt_mem(struct bnx2x_softc *sc) { sc->ilt = rte_malloc("", sizeof(struct ecore_ilt), RTE_CACHE_LINE_SIZE); return sc->ilt == NULL; } static int bnx2x_alloc_ilt_lines_mem(struct bnx2x_softc *sc) { sc->ilt->lines = rte_calloc("", sizeof(struct ilt_line), ILT_MAX_LINES, RTE_CACHE_LINE_SIZE); return sc->ilt->lines == NULL; } void bnx2x_free_ilt_mem(struct bnx2x_softc *sc) { rte_free(sc->ilt); sc->ilt = NULL; } static void bnx2x_free_ilt_lines_mem(struct bnx2x_softc *sc) { if (sc->ilt->lines != NULL) { rte_free(sc->ilt->lines); sc->ilt->lines = NULL; } } static void bnx2x_free_mem(struct bnx2x_softc *sc) { uint32_t i; for (i = 0; i < L2_ILT_LINES(sc); i++) { sc->context[i].vcxt = NULL; sc->context[i].size = 0; } ecore_ilt_mem_op(sc, ILT_MEMOP_FREE); bnx2x_free_ilt_lines_mem(sc); } static int bnx2x_alloc_mem(struct bnx2x_softc *sc) { int context_size; int allocated; int i; char cdu_name[RTE_MEMZONE_NAMESIZE]; /* * Allocate memory for CDU context: * This memory is allocated separately and not in the generic ILT * functions because CDU differs in few aspects: * 1. There can be multiple entities allocating memory for context - * regular L2, CNIC, and SRIOV drivers. Each separately controls * its own ILT lines. * 2. Since CDU page-size is not a single 4KB page (which is the case * for the other ILT clients), to be efficient we want to support * allocation of sub-page-size in the last entry. * 3. Context pointers are used by the driver to pass to FW / update * the context (for the other ILT clients the pointers are used just to * free the memory during unload). */ context_size = (sizeof(union cdu_context) * BNX2X_L2_CID_COUNT(sc)); for (i = 0, allocated = 0; allocated < context_size; i++) { sc->context[i].size = min(CDU_ILT_PAGE_SZ, (context_size - allocated)); snprintf(cdu_name, sizeof(cdu_name), "cdu_%d", i); if (bnx2x_dma_alloc(sc, sc->context[i].size, &sc->context[i].vcxt_dma, cdu_name, BNX2X_PAGE_SIZE) != 0) { bnx2x_free_mem(sc); return -1; } sc->context[i].vcxt = (union cdu_context *)sc->context[i].vcxt_dma.vaddr; allocated += sc->context[i].size; } bnx2x_alloc_ilt_lines_mem(sc); if (ecore_ilt_mem_op(sc, ILT_MEMOP_ALLOC)) { PMD_DRV_LOG(NOTICE, "ecore_ilt_mem_op ILT_MEMOP_ALLOC failed"); bnx2x_free_mem(sc); return -1; } return 0; } static void bnx2x_free_fw_stats_mem(struct bnx2x_softc *sc) { sc->fw_stats_num = 0; sc->fw_stats_req_size = 0; sc->fw_stats_req = NULL; sc->fw_stats_req_mapping = 0; sc->fw_stats_data_size = 0; sc->fw_stats_data = NULL; sc->fw_stats_data_mapping = 0; } static int bnx2x_alloc_fw_stats_mem(struct bnx2x_softc *sc) { uint8_t num_queue_stats; int num_groups, vf_headroom = 0; /* number of queues for statistics is number of eth queues */ num_queue_stats = BNX2X_NUM_ETH_QUEUES(sc); /* * Total number of FW statistics requests = * 1 for port stats + 1 for PF stats + num of queues */ sc->fw_stats_num = (2 + num_queue_stats); /* * Request is built from stats_query_header and an array of * stats_query_cmd_group each of which contains STATS_QUERY_CMD_COUNT * rules. The real number or requests is configured in the * stats_query_header. */ num_groups = (sc->fw_stats_num + vf_headroom) / STATS_QUERY_CMD_COUNT; if ((sc->fw_stats_num + vf_headroom) % STATS_QUERY_CMD_COUNT) num_groups++; sc->fw_stats_req_size = (sizeof(struct stats_query_header) + (num_groups * sizeof(struct stats_query_cmd_group))); /* * Data for statistics requests + stats_counter. * stats_counter holds per-STORM counters that are incremented when * STORM has finished with the current request. Memory for FCoE * offloaded statistics are counted anyway, even if they will not be sent. * VF stats are not accounted for here as the data of VF stats is stored * in memory allocated by the VF, not here. */ sc->fw_stats_data_size = (sizeof(struct stats_counter) + sizeof(struct per_port_stats) + sizeof(struct per_pf_stats) + /* sizeof(struct fcoe_statistics_params) + */ (sizeof(struct per_queue_stats) * num_queue_stats)); if (bnx2x_dma_alloc(sc, (sc->fw_stats_req_size + sc->fw_stats_data_size), &sc->fw_stats_dma, "fw_stats", RTE_CACHE_LINE_SIZE) != 0) { bnx2x_free_fw_stats_mem(sc); return -1; } /* set up the shortcuts */ sc->fw_stats_req = (struct bnx2x_fw_stats_req *)sc->fw_stats_dma.vaddr; sc->fw_stats_req_mapping = sc->fw_stats_dma.paddr; sc->fw_stats_data = (struct bnx2x_fw_stats_data *)((uint8_t *) sc->fw_stats_dma.vaddr + sc->fw_stats_req_size); sc->fw_stats_data_mapping = (sc->fw_stats_dma.paddr + sc->fw_stats_req_size); return 0; } /* * Bits map: * 0-7 - Engine0 load counter. * 8-15 - Engine1 load counter. * 16 - Engine0 RESET_IN_PROGRESS bit. * 17 - Engine1 RESET_IN_PROGRESS bit. * 18 - Engine0 ONE_IS_LOADED. Set when there is at least one active * function on the engine * 19 - Engine1 ONE_IS_LOADED. * 20 - Chip reset flow bit. When set none-leader must wait for both engines * leader to complete (check for both RESET_IN_PROGRESS bits and not * for just the one belonging to its engine). */ #define BNX2X_RECOVERY_GLOB_REG MISC_REG_GENERIC_POR_1 #define BNX2X_PATH0_LOAD_CNT_MASK 0x000000ff #define BNX2X_PATH0_LOAD_CNT_SHIFT 0 #define BNX2X_PATH1_LOAD_CNT_MASK 0x0000ff00 #define BNX2X_PATH1_LOAD_CNT_SHIFT 8 #define BNX2X_PATH0_RST_IN_PROG_BIT 0x00010000 #define BNX2X_PATH1_RST_IN_PROG_BIT 0x00020000 #define BNX2X_GLOBAL_RESET_BIT 0x00040000 /* set the GLOBAL_RESET bit, should be run under rtnl lock */ static void bnx2x_set_reset_global(struct bnx2x_softc *sc) { uint32_t val; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val | BNX2X_GLOBAL_RESET_BIT); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); } /* clear the GLOBAL_RESET bit, should be run under rtnl lock */ static void bnx2x_clear_reset_global(struct bnx2x_softc *sc) { uint32_t val; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val & (~BNX2X_GLOBAL_RESET_BIT)); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); } /* checks the GLOBAL_RESET bit, should be run under rtnl lock */ static uint8_t bnx2x_reset_is_global(struct bnx2x_softc *sc) { return (REG_RD(sc, BNX2X_RECOVERY_GLOB_REG) & BNX2X_GLOBAL_RESET_BIT); } /* clear RESET_IN_PROGRESS bit for the engine, should be run under rtnl lock */ static void bnx2x_set_reset_done(struct bnx2x_softc *sc) { uint32_t val; uint32_t bit = SC_PATH(sc) ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); /* Clear the bit */ val &= ~bit; REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); } /* set RESET_IN_PROGRESS for the engine, should be run under rtnl lock */ static void bnx2x_set_reset_in_progress(struct bnx2x_softc *sc) { uint32_t val; uint32_t bit = SC_PATH(sc) ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); /* Set the bit */ val |= bit; REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); } /* check RESET_IN_PROGRESS bit for an engine, should be run under rtnl lock */ static uint8_t bnx2x_reset_is_done(struct bnx2x_softc *sc, int engine) { uint32_t val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); uint32_t bit = engine ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; /* return false if bit is set */ return (val & bit) ? FALSE : TRUE; } /* get the load status for an engine, should be run under rtnl lock */ static uint8_t bnx2x_get_load_status(struct bnx2x_softc *sc, int engine) { uint32_t mask = engine ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK; uint32_t shift = engine ? BNX2X_PATH1_LOAD_CNT_SHIFT : BNX2X_PATH0_LOAD_CNT_SHIFT; uint32_t val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); val = ((val & mask) >> shift); return (val != 0); } /* set pf load mark */ static void bnx2x_set_pf_load(struct bnx2x_softc *sc) { uint32_t val; uint32_t val1; uint32_t mask = SC_PATH(sc) ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK; uint32_t shift = SC_PATH(sc) ? BNX2X_PATH1_LOAD_CNT_SHIFT : BNX2X_PATH0_LOAD_CNT_SHIFT; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); PMD_INIT_FUNC_TRACE(); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); /* get the current counter value */ val1 = ((val & mask) >> shift); /* set bit of this PF */ val1 |= (1 << SC_ABS_FUNC(sc)); /* clear the old value */ val &= ~mask; /* set the new one */ val |= ((val1 << shift) & mask); REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); } /* clear pf load mark */ static uint8_t bnx2x_clear_pf_load(struct bnx2x_softc *sc) { uint32_t val1, val; uint32_t mask = SC_PATH(sc) ? BNX2X_PATH1_LOAD_CNT_MASK : BNX2X_PATH0_LOAD_CNT_MASK; uint32_t shift = SC_PATH(sc) ? BNX2X_PATH1_LOAD_CNT_SHIFT : BNX2X_PATH0_LOAD_CNT_SHIFT; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); val = REG_RD(sc, BNX2X_RECOVERY_GLOB_REG); /* get the current counter value */ val1 = (val & mask) >> shift; /* clear bit of that PF */ val1 &= ~(1 << SC_ABS_FUNC(sc)); /* clear the old value */ val &= ~mask; /* set the new one */ val |= ((val1 << shift) & mask); REG_WR(sc, BNX2X_RECOVERY_GLOB_REG, val); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RECOVERY_REG); return val1 != 0; } /* send load requrest to mcp and analyze response */ static int bnx2x_nic_load_request(struct bnx2x_softc *sc, uint32_t * load_code) { PMD_INIT_FUNC_TRACE(); /* init fw_seq */ sc->fw_seq = (SHMEM_RD(sc, func_mb[SC_FW_MB_IDX(sc)].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); PMD_DRV_LOG(DEBUG, "initial fw_seq 0x%04x", sc->fw_seq); #ifdef BNX2X_PULSE /* get the current FW pulse sequence */ sc->fw_drv_pulse_wr_seq = (SHMEM_RD(sc, func_mb[SC_FW_MB_IDX(sc)].drv_pulse_mb) & DRV_PULSE_SEQ_MASK); #else /* set ALWAYS_ALIVE bit in shmem */ sc->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE; bnx2x_drv_pulse(sc); #endif /* load request */ (*load_code) = bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_REQ, DRV_MSG_CODE_LOAD_REQ_WITH_LFA); /* if the MCP fails to respond we must abort */ if (!(*load_code)) { PMD_DRV_LOG(NOTICE, "MCP response failure!"); return -1; } /* if MCP refused then must abort */ if ((*load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED) { PMD_DRV_LOG(NOTICE, "MCP refused load request"); return -1; } return 0; } /* * Check whether another PF has already loaded FW to chip. In virtualized * environments a pf from anoth VM may have already initialized the device * including loading FW. */ static int bnx2x_nic_load_analyze_req(struct bnx2x_softc *sc, uint32_t load_code) { uint32_t my_fw, loaded_fw; /* is another pf loaded on this engine? */ if ((load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) && (load_code != FW_MSG_CODE_DRV_LOAD_COMMON)) { /* build my FW version dword */ my_fw = (BNX2X_5710_FW_MAJOR_VERSION + (BNX2X_5710_FW_MINOR_VERSION << 8) + (BNX2X_5710_FW_REVISION_VERSION << 16) + (BNX2X_5710_FW_ENGINEERING_VERSION << 24)); /* read loaded FW from chip */ loaded_fw = REG_RD(sc, XSEM_REG_PRAM); PMD_DRV_LOG(DEBUG, "loaded FW 0x%08x / my FW 0x%08x", loaded_fw, my_fw); /* abort nic load if version mismatch */ if (my_fw != loaded_fw) { PMD_DRV_LOG(NOTICE, "FW 0x%08x already loaded (mine is 0x%08x)", loaded_fw, my_fw); return -1; } } return 0; } /* mark PMF if applicable */ static void bnx2x_nic_load_pmf(struct bnx2x_softc *sc, uint32_t load_code) { uint32_t ncsi_oem_data_addr; PMD_INIT_FUNC_TRACE(); if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) || (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) { /* * Barrier here for ordering between the writing to sc->port.pmf here * and reading it from the periodic task. */ sc->port.pmf = 1; mb(); } else { sc->port.pmf = 0; } PMD_DRV_LOG(DEBUG, "pmf %d", sc->port.pmf); if (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) { if (SHMEM2_HAS(sc, ncsi_oem_data_addr)) { ncsi_oem_data_addr = SHMEM2_RD(sc, ncsi_oem_data_addr); if (ncsi_oem_data_addr) { REG_WR(sc, (ncsi_oem_data_addr + offsetof(struct glob_ncsi_oem_data, driver_version)), 0); } } } } static void bnx2x_read_mf_cfg(struct bnx2x_softc *sc) { int n = (CHIP_IS_MODE_4_PORT(sc) ? 2 : 1); int abs_func; int vn; if (BNX2X_NOMCP(sc)) { return; /* what should be the default bvalue in this case */ } /* * The formula for computing the absolute function number is... * For 2 port configuration (4 functions per port): * abs_func = 2 * vn + SC_PORT + SC_PATH * For 4 port configuration (2 functions per port): * abs_func = 4 * vn + 2 * SC_PORT + SC_PATH */ for (vn = VN_0; vn < SC_MAX_VN_NUM(sc); vn++) { abs_func = (n * (2 * vn + SC_PORT(sc)) + SC_PATH(sc)); if (abs_func >= E1H_FUNC_MAX) { break; } sc->devinfo.mf_info.mf_config[vn] = MFCFG_RD(sc, func_mf_config[abs_func].config); } if (sc->devinfo.mf_info.mf_config[SC_VN(sc)] & FUNC_MF_CFG_FUNC_DISABLED) { PMD_DRV_LOG(DEBUG, "mf_cfg function disabled"); sc->flags |= BNX2X_MF_FUNC_DIS; } else { PMD_DRV_LOG(DEBUG, "mf_cfg function enabled"); sc->flags &= ~BNX2X_MF_FUNC_DIS; } } /* acquire split MCP access lock register */ static int bnx2x_acquire_alr(struct bnx2x_softc *sc) { uint32_t j, val; for (j = 0; j < 1000; j++) { val = (1UL << 31); REG_WR(sc, GRCBASE_MCP + 0x9c, val); val = REG_RD(sc, GRCBASE_MCP + 0x9c); if (val & (1L << 31)) break; DELAY(5000); } if (!(val & (1L << 31))) { PMD_DRV_LOG(NOTICE, "Cannot acquire MCP access lock register"); return -1; } return 0; } /* release split MCP access lock register */ static void bnx2x_release_alr(struct bnx2x_softc *sc) { REG_WR(sc, GRCBASE_MCP + 0x9c, 0); } static void bnx2x_fan_failure(struct bnx2x_softc *sc) { int port = SC_PORT(sc); uint32_t ext_phy_config; /* mark the failure */ ext_phy_config = SHMEM_RD(sc, dev_info.port_hw_config[port].external_phy_config); ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK; ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE; SHMEM_WR(sc, dev_info.port_hw_config[port].external_phy_config, ext_phy_config); /* log the failure */ PMD_DRV_LOG(INFO, "Fan Failure has caused the driver to shutdown " "the card to prevent permanent damage. " "Please contact OEM Support for assistance"); rte_panic("Schedule task to handle fan failure"); } /* this function is called upon a link interrupt */ static void bnx2x_link_attn(struct bnx2x_softc *sc) { uint32_t pause_enabled = 0; struct host_port_stats *pstats; int cmng_fns; /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(sc, STATS_EVENT_STOP); elink_link_update(&sc->link_params, &sc->link_vars); if (sc->link_vars.link_up) { /* dropless flow control */ if (sc->dropless_fc) { pause_enabled = 0; if (sc->link_vars.flow_ctrl & ELINK_FLOW_CTRL_TX) { pause_enabled = 1; } REG_WR(sc, (BAR_USTRORM_INTMEM + USTORM_ETH_PAUSE_ENABLED_OFFSET(SC_PORT(sc))), pause_enabled); } if (sc->link_vars.mac_type != ELINK_MAC_TYPE_EMAC) { pstats = BNX2X_SP(sc, port_stats); /* reset old mac stats */ memset(&(pstats->mac_stx[0]), 0, sizeof(struct mac_stx)); } if (sc->state == BNX2X_STATE_OPEN) { bnx2x_stats_handle(sc, STATS_EVENT_LINK_UP); } } if (sc->link_vars.link_up && sc->link_vars.line_speed) { cmng_fns = bnx2x_get_cmng_fns_mode(sc); if (cmng_fns != CMNG_FNS_NONE) { bnx2x_cmng_fns_init(sc, FALSE, cmng_fns); storm_memset_cmng(sc, &sc->cmng, SC_PORT(sc)); } } bnx2x_link_report(sc); if (IS_MF(sc)) { bnx2x_link_sync_notify(sc); } } static void bnx2x_attn_int_asserted(struct bnx2x_softc *sc, uint32_t asserted) { int port = SC_PORT(sc); uint32_t aeu_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : MISC_REG_AEU_MASK_ATTN_FUNC_0; uint32_t nig_int_mask_addr = port ? NIG_REG_MASK_INTERRUPT_PORT1 : NIG_REG_MASK_INTERRUPT_PORT0; uint32_t aeu_mask; uint32_t nig_mask = 0; uint32_t reg_addr; uint32_t igu_acked; uint32_t cnt; if (sc->attn_state & asserted) { PMD_DRV_LOG(ERR, "IGU ERROR attn=0x%08x", asserted); } bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port); aeu_mask = REG_RD(sc, aeu_addr); aeu_mask &= ~(asserted & 0x3ff); REG_WR(sc, aeu_addr, aeu_mask); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port); sc->attn_state |= asserted; if (asserted & ATTN_HARD_WIRED_MASK) { if (asserted & ATTN_NIG_FOR_FUNC) { /* save nig interrupt mask */ nig_mask = REG_RD(sc, nig_int_mask_addr); /* If nig_mask is not set, no need to call the update function */ if (nig_mask) { REG_WR(sc, nig_int_mask_addr, 0); bnx2x_link_attn(sc); } /* handle unicore attn? */ } if (asserted & ATTN_SW_TIMER_4_FUNC) { PMD_DRV_LOG(DEBUG, "ATTN_SW_TIMER_4_FUNC!"); } if (asserted & GPIO_2_FUNC) { PMD_DRV_LOG(DEBUG, "GPIO_2_FUNC!"); } if (asserted & GPIO_3_FUNC) { PMD_DRV_LOG(DEBUG, "GPIO_3_FUNC!"); } if (asserted & GPIO_4_FUNC) { PMD_DRV_LOG(DEBUG, "GPIO_4_FUNC!"); } if (port == 0) { if (asserted & ATTN_GENERAL_ATTN_1) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_1!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_1, 0x0); } if (asserted & ATTN_GENERAL_ATTN_2) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_2!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_2, 0x0); } if (asserted & ATTN_GENERAL_ATTN_3) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_3!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_3, 0x0); } } else { if (asserted & ATTN_GENERAL_ATTN_4) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_4!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_4, 0x0); } if (asserted & ATTN_GENERAL_ATTN_5) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_5!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_5, 0x0); } if (asserted & ATTN_GENERAL_ATTN_6) { PMD_DRV_LOG(DEBUG, "ATTN_GENERAL_ATTN_6!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_6, 0x0); } } } /* hardwired */ if (sc->devinfo.int_block == INT_BLOCK_HC) { reg_addr = (HC_REG_COMMAND_REG + port * 32 + COMMAND_REG_ATTN_BITS_SET); } else { reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_SET_UPPER * 8); } PMD_DRV_LOG(DEBUG, "about to mask 0x%08x at %s addr 0x%08x", asserted, (sc->devinfo.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr); REG_WR(sc, reg_addr, asserted); /* now set back the mask */ if (asserted & ATTN_NIG_FOR_FUNC) { /* * Verify that IGU ack through BAR was written before restoring * NIG mask. This loop should exit after 2-3 iterations max. */ if (sc->devinfo.int_block != INT_BLOCK_HC) { cnt = 0; do { igu_acked = REG_RD(sc, IGU_REG_ATTENTION_ACK_BITS); } while (((igu_acked & ATTN_NIG_FOR_FUNC) == 0) && (++cnt < MAX_IGU_ATTN_ACK_TO)); if (!igu_acked) { PMD_DRV_LOG(ERR, "Failed to verify IGU ack on time"); } mb(); } REG_WR(sc, nig_int_mask_addr, nig_mask); } } static void bnx2x_print_next_block(__rte_unused struct bnx2x_softc *sc, __rte_unused int idx, __rte_unused const char *blk) { PMD_DRV_LOG(INFO, "%s%s", idx ? ", " : "", blk); } static int bnx2x_check_blocks_with_parity0(struct bnx2x_softc *sc, uint32_t sig, int par_num, uint8_t print) { uint32_t cur_bit = 0; int i = 0; for (i = 0; sig; i++) { cur_bit = ((uint32_t) 0x1 << i); if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "BRB"); break; case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "PARSER"); break; case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "TSDM"); break; case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "SEARCHER"); break; case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "TCM"); break; case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "TSEMI"); break; case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "XPB"); break; } /* Clear the bit */ sig &= ~cur_bit; } } return par_num; } static int bnx2x_check_blocks_with_parity1(struct bnx2x_softc *sc, uint32_t sig, int par_num, uint8_t * global, uint8_t print) { int i = 0; uint32_t cur_bit = 0; for (i = 0; sig; i++) { cur_bit = ((uint32_t) 0x1 << i); if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "PBF"); break; case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "QM"); break; case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "TM"); break; case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "XSDM"); break; case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "XCM"); break; case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "XSEMI"); break; case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "DOORBELLQ"); break; case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "NIG"); break; case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "VAUX PCI CORE"); *global = TRUE; break; case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "DEBUG"); break; case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "USDM"); break; case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "UCM"); break; case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "USEMI"); break; case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "UPB"); break; case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "CSDM"); break; case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "CCM"); break; } /* Clear the bit */ sig &= ~cur_bit; } } return par_num; } static int bnx2x_check_blocks_with_parity2(struct bnx2x_softc *sc, uint32_t sig, int par_num, uint8_t print) { uint32_t cur_bit = 0; int i = 0; for (i = 0; sig; i++) { cur_bit = ((uint32_t) 0x1 << i); if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "CSEMI"); break; case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "PXP"); break; case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "PXPPCICLOCKCLIENT"); break; case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "CFC"); break; case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "CDU"); break; case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "DMAE"); break; case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "IGU"); break; case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "MISC"); break; } /* Clear the bit */ sig &= ~cur_bit; } } return par_num; } static int bnx2x_check_blocks_with_parity3(struct bnx2x_softc *sc, uint32_t sig, int par_num, uint8_t * global, uint8_t print) { uint32_t cur_bit = 0; int i = 0; for (i = 0; sig; i++) { cur_bit = ((uint32_t) 0x1 << i); if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY: if (print) bnx2x_print_next_block(sc, par_num++, "MCP ROM"); *global = TRUE; break; case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY: if (print) bnx2x_print_next_block(sc, par_num++, "MCP UMP RX"); *global = TRUE; break; case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY: if (print) bnx2x_print_next_block(sc, par_num++, "MCP UMP TX"); *global = TRUE; break; case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY: if (print) bnx2x_print_next_block(sc, par_num++, "MCP SCPAD"); *global = TRUE; break; } /* Clear the bit */ sig &= ~cur_bit; } } return par_num; } static int bnx2x_check_blocks_with_parity4(struct bnx2x_softc *sc, uint32_t sig, int par_num, uint8_t print) { uint32_t cur_bit = 0; int i = 0; for (i = 0; sig; i++) { cur_bit = ((uint32_t) 0x1 << i); if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "PGLUE_B"); break; case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR: if (print) bnx2x_print_next_block(sc, par_num++, "ATC"); break; } /* Clear the bit */ sig &= ~cur_bit; } } return par_num; } static uint8_t bnx2x_parity_attn(struct bnx2x_softc *sc, uint8_t * global, uint8_t print, uint32_t * sig) { int par_num = 0; if ((sig[0] & HW_PRTY_ASSERT_SET_0) || (sig[1] & HW_PRTY_ASSERT_SET_1) || (sig[2] & HW_PRTY_ASSERT_SET_2) || (sig[3] & HW_PRTY_ASSERT_SET_3) || (sig[4] & HW_PRTY_ASSERT_SET_4)) { PMD_DRV_LOG(ERR, "Parity error: HW block parity attention:" "[0]:0x%08x [1]:0x%08x [2]:0x%08x [3]:0x%08x [4]:0x%08x", (uint32_t) (sig[0] & HW_PRTY_ASSERT_SET_0), (uint32_t) (sig[1] & HW_PRTY_ASSERT_SET_1), (uint32_t) (sig[2] & HW_PRTY_ASSERT_SET_2), (uint32_t) (sig[3] & HW_PRTY_ASSERT_SET_3), (uint32_t) (sig[4] & HW_PRTY_ASSERT_SET_4)); if (print) PMD_DRV_LOG(INFO, "Parity errors detected in blocks: "); par_num = bnx2x_check_blocks_with_parity0(sc, sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print); par_num = bnx2x_check_blocks_with_parity1(sc, sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print); par_num = bnx2x_check_blocks_with_parity2(sc, sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print); par_num = bnx2x_check_blocks_with_parity3(sc, sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print); par_num = bnx2x_check_blocks_with_parity4(sc, sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print); if (print) PMD_DRV_LOG(INFO, ""); return TRUE; } return FALSE; } static uint8_t bnx2x_chk_parity_attn(struct bnx2x_softc *sc, uint8_t * global, uint8_t print) { struct attn_route attn = { {0} }; int port = SC_PORT(sc); attn.sig[0] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + port * 4); attn.sig[1] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port * 4); attn.sig[2] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port * 4); attn.sig[3] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port * 4); if (!CHIP_IS_E1x(sc)) attn.sig[4] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port * 4); return bnx2x_parity_attn(sc, global, print, attn.sig); } static void bnx2x_attn_int_deasserted4(struct bnx2x_softc *sc, uint32_t attn) { uint32_t val; if (attn & AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT) { val = REG_RD(sc, PGLUE_B_REG_PGLUE_B_INT_STS_CLR); PMD_DRV_LOG(INFO, "ERROR: PGLUE hw attention 0x%08x", val); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN"); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW) PMD_DRV_LOG(INFO, "ERROR: PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW"); } if (attn & AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT) { val = REG_RD(sc, ATC_REG_ATC_INT_STS_CLR); PMD_DRV_LOG(INFO, "ERROR: ATC hw attention 0x%08x", val); if (val & ATC_ATC_INT_STS_REG_ADDRESS_ERROR) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ADDRESS_ERROR"); if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND"); if (val & ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS"); if (val & ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT"); if (val & ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR"); if (val & ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU) PMD_DRV_LOG(INFO, "ERROR: ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU"); } if (attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)) { PMD_DRV_LOG(INFO, "ERROR: FATAL parity attention set4 0x%08x", (uint32_t) (attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR))); } } static void bnx2x_e1h_disable(struct bnx2x_softc *sc) { int port = SC_PORT(sc); REG_WR(sc, NIG_REG_LLH0_FUNC_EN + port * 8, 0); } static void bnx2x_e1h_enable(struct bnx2x_softc *sc) { int port = SC_PORT(sc); REG_WR(sc, NIG_REG_LLH0_FUNC_EN + port * 8, 1); } /* * called due to MCP event (on pmf): * reread new bandwidth configuration * configure FW * notify others function about the change */ static void bnx2x_config_mf_bw(struct bnx2x_softc *sc) { if (sc->link_vars.link_up) { bnx2x_cmng_fns_init(sc, TRUE, CMNG_FNS_MINMAX); bnx2x_link_sync_notify(sc); } storm_memset_cmng(sc, &sc->cmng, SC_PORT(sc)); } static void bnx2x_set_mf_bw(struct bnx2x_softc *sc) { bnx2x_config_mf_bw(sc); bnx2x_fw_command(sc, DRV_MSG_CODE_SET_MF_BW_ACK, 0); } static void bnx2x_handle_eee_event(struct bnx2x_softc *sc) { bnx2x_fw_command(sc, DRV_MSG_CODE_EEE_RESULTS_ACK, 0); } #define DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED 3 static void bnx2x_drv_info_ether_stat(struct bnx2x_softc *sc) { struct eth_stats_info *ether_stat = &sc->sp->drv_info_to_mcp.ether_stat; strncpy(ether_stat->version, BNX2X_DRIVER_VERSION, ETH_STAT_INFO_VERSION_LEN); sc->sp_objs[0].mac_obj.get_n_elements(sc, &sc->sp_objs[0].mac_obj, DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED, ether_stat->mac_local + MAC_PAD, MAC_PAD, ETH_ALEN); ether_stat->mtu_size = sc->mtu; ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK; ether_stat->promiscuous_mode = 0; // (flags & PROMISC) ? 1 : 0; ether_stat->txq_size = sc->tx_ring_size; ether_stat->rxq_size = sc->rx_ring_size; } static void bnx2x_handle_drv_info_req(struct bnx2x_softc *sc) { enum drv_info_opcode op_code; uint32_t drv_info_ctl = SHMEM2_RD(sc, drv_info_control); /* if drv_info version supported by MFW doesn't match - send NACK */ if ((drv_info_ctl & DRV_INFO_CONTROL_VER_MASK) != DRV_INFO_CUR_VER) { bnx2x_fw_command(sc, DRV_MSG_CODE_DRV_INFO_NACK, 0); return; } op_code = ((drv_info_ctl & DRV_INFO_CONTROL_OP_CODE_MASK) >> DRV_INFO_CONTROL_OP_CODE_SHIFT); memset(&sc->sp->drv_info_to_mcp, 0, sizeof(union drv_info_to_mcp)); switch (op_code) { case ETH_STATS_OPCODE: bnx2x_drv_info_ether_stat(sc); break; case FCOE_STATS_OPCODE: case ISCSI_STATS_OPCODE: default: /* if op code isn't supported - send NACK */ bnx2x_fw_command(sc, DRV_MSG_CODE_DRV_INFO_NACK, 0); return; } /* * If we got drv_info attn from MFW then these fields are defined in * shmem2 for sure */ SHMEM2_WR(sc, drv_info_host_addr_lo, U64_LO(BNX2X_SP_MAPPING(sc, drv_info_to_mcp))); SHMEM2_WR(sc, drv_info_host_addr_hi, U64_HI(BNX2X_SP_MAPPING(sc, drv_info_to_mcp))); bnx2x_fw_command(sc, DRV_MSG_CODE_DRV_INFO_ACK, 0); } static void bnx2x_dcc_event(struct bnx2x_softc *sc, uint32_t dcc_event) { if (dcc_event & DRV_STATUS_DCC_DISABLE_ENABLE_PF) { /* * This is the only place besides the function initialization * where the sc->flags can change so it is done without any * locks */ if (sc->devinfo. mf_info.mf_config[SC_VN(sc)] & FUNC_MF_CFG_FUNC_DISABLED) { PMD_DRV_LOG(DEBUG, "mf_cfg function disabled"); sc->flags |= BNX2X_MF_FUNC_DIS; bnx2x_e1h_disable(sc); } else { PMD_DRV_LOG(DEBUG, "mf_cfg function enabled"); sc->flags &= ~BNX2X_MF_FUNC_DIS; bnx2x_e1h_enable(sc); } dcc_event &= ~DRV_STATUS_DCC_DISABLE_ENABLE_PF; } if (dcc_event & DRV_STATUS_DCC_BANDWIDTH_ALLOCATION) { bnx2x_config_mf_bw(sc); dcc_event &= ~DRV_STATUS_DCC_BANDWIDTH_ALLOCATION; } /* Report results to MCP */ if (dcc_event) bnx2x_fw_command(sc, DRV_MSG_CODE_DCC_FAILURE, 0); else bnx2x_fw_command(sc, DRV_MSG_CODE_DCC_OK, 0); } static void bnx2x_pmf_update(struct bnx2x_softc *sc) { int port = SC_PORT(sc); uint32_t val; sc->port.pmf = 1; /* * We need the mb() to ensure the ordering between the writing to * sc->port.pmf here and reading it from the bnx2x_periodic_task(). */ mb(); /* enable nig attention */ val = (0xff0f | (1 << (SC_VN(sc) + 4))); if (sc->devinfo.int_block == INT_BLOCK_HC) { REG_WR(sc, HC_REG_TRAILING_EDGE_0 + port * 8, val); REG_WR(sc, HC_REG_LEADING_EDGE_0 + port * 8, val); } else if (!CHIP_IS_E1x(sc)) { REG_WR(sc, IGU_REG_TRAILING_EDGE_LATCH, val); REG_WR(sc, IGU_REG_LEADING_EDGE_LATCH, val); } bnx2x_stats_handle(sc, STATS_EVENT_PMF); } static int bnx2x_mc_assert(struct bnx2x_softc *sc) { char last_idx; int i, rc = 0; __rte_unused uint32_t row0, row1, row2, row3; /* XSTORM */ last_idx = REG_RD8(sc, BAR_XSTRORM_INTMEM + XSTORM_ASSERT_LIST_INDEX_OFFSET); if (last_idx) PMD_DRV_LOG(ERR, "XSTORM_ASSERT_LIST_INDEX 0x%x", last_idx); /* print the asserts */ for (i = 0; i < STORM_ASSERT_ARRAY_SIZE; i++) { row0 = REG_RD(sc, BAR_XSTRORM_INTMEM + XSTORM_ASSERT_LIST_OFFSET(i)); row1 = REG_RD(sc, BAR_XSTRORM_INTMEM + XSTORM_ASSERT_LIST_OFFSET(i) + 4); row2 = REG_RD(sc, BAR_XSTRORM_INTMEM + XSTORM_ASSERT_LIST_OFFSET(i) + 8); row3 = REG_RD(sc, BAR_XSTRORM_INTMEM + XSTORM_ASSERT_LIST_OFFSET(i) + 12); if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) { PMD_DRV_LOG(ERR, "XSTORM_ASSERT_INDEX 0x%x = 0x%08x 0x%08x 0x%08x 0x%08x", i, row3, row2, row1, row0); rc++; } else { break; } } /* TSTORM */ last_idx = REG_RD8(sc, BAR_TSTRORM_INTMEM + TSTORM_ASSERT_LIST_INDEX_OFFSET); if (last_idx) { PMD_DRV_LOG(ERR, "TSTORM_ASSERT_LIST_INDEX 0x%x", last_idx); } /* print the asserts */ for (i = 0; i < STORM_ASSERT_ARRAY_SIZE; i++) { row0 = REG_RD(sc, BAR_TSTRORM_INTMEM + TSTORM_ASSERT_LIST_OFFSET(i)); row1 = REG_RD(sc, BAR_TSTRORM_INTMEM + TSTORM_ASSERT_LIST_OFFSET(i) + 4); row2 = REG_RD(sc, BAR_TSTRORM_INTMEM + TSTORM_ASSERT_LIST_OFFSET(i) + 8); row3 = REG_RD(sc, BAR_TSTRORM_INTMEM + TSTORM_ASSERT_LIST_OFFSET(i) + 12); if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) { PMD_DRV_LOG(ERR, "TSTORM_ASSERT_INDEX 0x%x = 0x%08x 0x%08x 0x%08x 0x%08x", i, row3, row2, row1, row0); rc++; } else { break; } } /* CSTORM */ last_idx = REG_RD8(sc, BAR_CSTRORM_INTMEM + CSTORM_ASSERT_LIST_INDEX_OFFSET); if (last_idx) { PMD_DRV_LOG(ERR, "CSTORM_ASSERT_LIST_INDEX 0x%x", last_idx); } /* print the asserts */ for (i = 0; i < STORM_ASSERT_ARRAY_SIZE; i++) { row0 = REG_RD(sc, BAR_CSTRORM_INTMEM + CSTORM_ASSERT_LIST_OFFSET(i)); row1 = REG_RD(sc, BAR_CSTRORM_INTMEM + CSTORM_ASSERT_LIST_OFFSET(i) + 4); row2 = REG_RD(sc, BAR_CSTRORM_INTMEM + CSTORM_ASSERT_LIST_OFFSET(i) + 8); row3 = REG_RD(sc, BAR_CSTRORM_INTMEM + CSTORM_ASSERT_LIST_OFFSET(i) + 12); if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) { PMD_DRV_LOG(ERR, "CSTORM_ASSERT_INDEX 0x%x = 0x%08x 0x%08x 0x%08x 0x%08x", i, row3, row2, row1, row0); rc++; } else { break; } } /* USTORM */ last_idx = REG_RD8(sc, BAR_USTRORM_INTMEM + USTORM_ASSERT_LIST_INDEX_OFFSET); if (last_idx) { PMD_DRV_LOG(ERR, "USTORM_ASSERT_LIST_INDEX 0x%x", last_idx); } /* print the asserts */ for (i = 0; i < STORM_ASSERT_ARRAY_SIZE; i++) { row0 = REG_RD(sc, BAR_USTRORM_INTMEM + USTORM_ASSERT_LIST_OFFSET(i)); row1 = REG_RD(sc, BAR_USTRORM_INTMEM + USTORM_ASSERT_LIST_OFFSET(i) + 4); row2 = REG_RD(sc, BAR_USTRORM_INTMEM + USTORM_ASSERT_LIST_OFFSET(i) + 8); row3 = REG_RD(sc, BAR_USTRORM_INTMEM + USTORM_ASSERT_LIST_OFFSET(i) + 12); if (row0 != COMMON_ASM_INVALID_ASSERT_OPCODE) { PMD_DRV_LOG(ERR, "USTORM_ASSERT_INDEX 0x%x = 0x%08x 0x%08x 0x%08x 0x%08x", i, row3, row2, row1, row0); rc++; } else { break; } } return rc; } static void bnx2x_attn_int_deasserted3(struct bnx2x_softc *sc, uint32_t attn) { int func = SC_FUNC(sc); uint32_t val; if (attn & EVEREST_GEN_ATTN_IN_USE_MASK) { if (attn & BNX2X_PMF_LINK_ASSERT(sc)) { REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_12 + func * 4, 0); bnx2x_read_mf_cfg(sc); sc->devinfo.mf_info.mf_config[SC_VN(sc)] = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].config); val = SHMEM_RD(sc, func_mb[SC_FW_MB_IDX(sc)].drv_status); if (val & DRV_STATUS_DCC_EVENT_MASK) bnx2x_dcc_event(sc, (val & DRV_STATUS_DCC_EVENT_MASK)); if (val & DRV_STATUS_SET_MF_BW) bnx2x_set_mf_bw(sc); if (val & DRV_STATUS_DRV_INFO_REQ) bnx2x_handle_drv_info_req(sc); if ((sc->port.pmf == 0) && (val & DRV_STATUS_PMF)) bnx2x_pmf_update(sc); if (val & DRV_STATUS_EEE_NEGOTIATION_RESULTS) bnx2x_handle_eee_event(sc); if (sc->link_vars.periodic_flags & ELINK_PERIODIC_FLAGS_LINK_EVENT) { /* sync with link */ sc->link_vars.periodic_flags &= ~ELINK_PERIODIC_FLAGS_LINK_EVENT; if (IS_MF(sc)) { bnx2x_link_sync_notify(sc); } bnx2x_link_report(sc); } /* * Always call it here: bnx2x_link_report() will * prevent the link indication duplication. */ bnx2x_link_status_update(sc); } else if (attn & BNX2X_MC_ASSERT_BITS) { PMD_DRV_LOG(ERR, "MC assert!"); bnx2x_mc_assert(sc); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_10, 0); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_9, 0); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_8, 0); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_7, 0); rte_panic("MC assert!"); } else if (attn & BNX2X_MCP_ASSERT) { PMD_DRV_LOG(ERR, "MCP assert!"); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_11, 0); } else { PMD_DRV_LOG(ERR, "Unknown HW assert! (attn 0x%08x)", attn); } } if (attn & EVEREST_LATCHED_ATTN_IN_USE_MASK) { PMD_DRV_LOG(ERR, "LATCHED attention 0x%08x (masked)", attn); if (attn & BNX2X_GRC_TIMEOUT) { val = REG_RD(sc, MISC_REG_GRC_TIMEOUT_ATTN); PMD_DRV_LOG(ERR, "GRC time-out 0x%08x", val); } if (attn & BNX2X_GRC_RSV) { val = REG_RD(sc, MISC_REG_GRC_RSV_ATTN); PMD_DRV_LOG(ERR, "GRC reserved 0x%08x", val); } REG_WR(sc, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x7ff); } } static void bnx2x_attn_int_deasserted2(struct bnx2x_softc *sc, uint32_t attn) { int port = SC_PORT(sc); int reg_offset; uint32_t val0, mask0, val1, mask1; uint32_t val; if (attn & AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT) { val = REG_RD(sc, CFC_REG_CFC_INT_STS_CLR); PMD_DRV_LOG(ERR, "CFC hw attention 0x%08x", val); /* CFC error attention */ if (val & 0x2) { PMD_DRV_LOG(ERR, "FATAL error from CFC"); } } if (attn & AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT) { val = REG_RD(sc, PXP_REG_PXP_INT_STS_CLR_0); PMD_DRV_LOG(ERR, "PXP hw attention-0 0x%08x", val); /* RQ_USDMDP_FIFO_OVERFLOW */ if (val & 0x18000) { PMD_DRV_LOG(ERR, "FATAL error from PXP"); } if (!CHIP_IS_E1x(sc)) { val = REG_RD(sc, PXP_REG_PXP_INT_STS_CLR_1); PMD_DRV_LOG(ERR, "PXP hw attention-1 0x%08x", val); } } #define PXP2_EOP_ERROR_BIT PXP2_PXP2_INT_STS_CLR_0_REG_WR_PGLUE_EOP_ERROR #define AEU_PXP2_HW_INT_BIT AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT if (attn & AEU_PXP2_HW_INT_BIT) { /* CQ47854 workaround do not panic on * PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR */ if (!CHIP_IS_E1x(sc)) { mask0 = REG_RD(sc, PXP2_REG_PXP2_INT_MASK_0); val1 = REG_RD(sc, PXP2_REG_PXP2_INT_STS_1); mask1 = REG_RD(sc, PXP2_REG_PXP2_INT_MASK_1); val0 = REG_RD(sc, PXP2_REG_PXP2_INT_STS_0); /* * If the olny PXP2_EOP_ERROR_BIT is set in * STS0 and STS1 - clear it * * probably we lose additional attentions between * STS0 and STS_CLR0, in this case user will not * be notified about them */ if (val0 & mask0 & PXP2_EOP_ERROR_BIT && !(val1 & mask1)) val0 = REG_RD(sc, PXP2_REG_PXP2_INT_STS_CLR_0); /* print the register, since no one can restore it */ PMD_DRV_LOG(ERR, "PXP2_REG_PXP2_INT_STS_CLR_0 0x%08x", val0); /* * if PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR * then notify */ if (val0 & PXP2_EOP_ERROR_BIT) { PMD_DRV_LOG(ERR, "PXP2_WR_PGLUE_EOP_ERROR"); /* * if only PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR is * set then clear attention from PXP2 block without panic */ if (((val0 & mask0) == PXP2_EOP_ERROR_BIT) && ((val1 & mask1) == 0)) attn &= ~AEU_PXP2_HW_INT_BIT; } } } if (attn & HW_INTERRUT_ASSERT_SET_2) { reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2); val = REG_RD(sc, reg_offset); val &= ~(attn & HW_INTERRUT_ASSERT_SET_2); REG_WR(sc, reg_offset, val); PMD_DRV_LOG(ERR, "FATAL HW block attention set2 0x%x", (uint32_t) (attn & HW_INTERRUT_ASSERT_SET_2)); rte_panic("HW block attention set2"); } } static void bnx2x_attn_int_deasserted1(struct bnx2x_softc *sc, uint32_t attn) { int port = SC_PORT(sc); int reg_offset; uint32_t val; if (attn & AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT) { val = REG_RD(sc, DORQ_REG_DORQ_INT_STS_CLR); PMD_DRV_LOG(ERR, "DB hw attention 0x%08x", val); /* DORQ discard attention */ if (val & 0x2) { PMD_DRV_LOG(ERR, "FATAL error from DORQ"); } } if (attn & HW_INTERRUT_ASSERT_SET_1) { reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1); val = REG_RD(sc, reg_offset); val &= ~(attn & HW_INTERRUT_ASSERT_SET_1); REG_WR(sc, reg_offset, val); PMD_DRV_LOG(ERR, "FATAL HW block attention set1 0x%08x", (uint32_t) (attn & HW_INTERRUT_ASSERT_SET_1)); rte_panic("HW block attention set1"); } } static void bnx2x_attn_int_deasserted0(struct bnx2x_softc *sc, uint32_t attn) { int port = SC_PORT(sc); int reg_offset; uint32_t val; reg_offset = (port) ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0; if (attn & AEU_INPUTS_ATTN_BITS_SPIO5) { val = REG_RD(sc, reg_offset); val &= ~AEU_INPUTS_ATTN_BITS_SPIO5; REG_WR(sc, reg_offset, val); PMD_DRV_LOG(WARNING, "SPIO5 hw attention"); /* Fan failure attention */ elink_hw_reset_phy(&sc->link_params); bnx2x_fan_failure(sc); } if ((attn & sc->link_vars.aeu_int_mask) && sc->port.pmf) { elink_handle_module_detect_int(&sc->link_params); } if (attn & HW_INTERRUT_ASSERT_SET_0) { val = REG_RD(sc, reg_offset); val &= ~(attn & HW_INTERRUT_ASSERT_SET_0); REG_WR(sc, reg_offset, val); rte_panic("FATAL HW block attention set0 0x%lx", (attn & HW_INTERRUT_ASSERT_SET_0)); } } static void bnx2x_attn_int_deasserted(struct bnx2x_softc *sc, uint32_t deasserted) { struct attn_route attn; struct attn_route *group_mask; int port = SC_PORT(sc); int index; uint32_t reg_addr; uint32_t val; uint32_t aeu_mask; uint8_t global = FALSE; /* * Need to take HW lock because MCP or other port might also * try to handle this event. */ bnx2x_acquire_alr(sc); if (bnx2x_chk_parity_attn(sc, &global, TRUE)) { sc->recovery_state = BNX2X_RECOVERY_INIT; /* disable HW interrupts */ bnx2x_int_disable(sc); bnx2x_release_alr(sc); return; } attn.sig[0] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + port * 4); attn.sig[1] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 + port * 4); attn.sig[2] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 + port * 4); attn.sig[3] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 + port * 4); if (!CHIP_IS_E1x(sc)) { attn.sig[4] = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 + port * 4); } else { attn.sig[4] = 0; } for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) { if (deasserted & (1 << index)) { group_mask = &sc->attn_group[index]; bnx2x_attn_int_deasserted4(sc, attn. sig[4] & group_mask->sig[4]); bnx2x_attn_int_deasserted3(sc, attn. sig[3] & group_mask->sig[3]); bnx2x_attn_int_deasserted1(sc, attn. sig[1] & group_mask->sig[1]); bnx2x_attn_int_deasserted2(sc, attn. sig[2] & group_mask->sig[2]); bnx2x_attn_int_deasserted0(sc, attn. sig[0] & group_mask->sig[0]); } } bnx2x_release_alr(sc); if (sc->devinfo.int_block == INT_BLOCK_HC) { reg_addr = (HC_REG_COMMAND_REG + port * 32 + COMMAND_REG_ATTN_BITS_CLR); } else { reg_addr = (BAR_IGU_INTMEM + IGU_CMD_ATTN_BIT_CLR_UPPER * 8); } val = ~deasserted; PMD_DRV_LOG(DEBUG, "about to mask 0x%08x at %s addr 0x%08x", val, (sc->devinfo.int_block == INT_BLOCK_HC) ? "HC" : "IGU", reg_addr); REG_WR(sc, reg_addr, val); if (~sc->attn_state & deasserted) { PMD_DRV_LOG(ERR, "IGU error"); } reg_addr = port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 : MISC_REG_AEU_MASK_ATTN_FUNC_0; bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port); aeu_mask = REG_RD(sc, reg_addr); aeu_mask |= (deasserted & 0x3ff); REG_WR(sc, reg_addr, aeu_mask); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_PORT0_ATT_MASK + port); sc->attn_state &= ~deasserted; } static void bnx2x_attn_int(struct bnx2x_softc *sc) { /* read local copy of bits */ uint32_t attn_bits = le32toh(sc->def_sb->atten_status_block.attn_bits); uint32_t attn_ack = le32toh(sc->def_sb->atten_status_block.attn_bits_ack); uint32_t attn_state = sc->attn_state; /* look for changed bits */ uint32_t asserted = attn_bits & ~attn_ack & ~attn_state; uint32_t deasserted = ~attn_bits & attn_ack & attn_state; PMD_DRV_LOG(DEBUG, "attn_bits 0x%08x attn_ack 0x%08x asserted 0x%08x deasserted 0x%08x", attn_bits, attn_ack, asserted, deasserted); if (~(attn_bits ^ attn_ack) & (attn_bits ^ attn_state)) { PMD_DRV_LOG(ERR, "BAD attention state"); } /* handle bits that were raised */ if (asserted) { bnx2x_attn_int_asserted(sc, asserted); } if (deasserted) { bnx2x_attn_int_deasserted(sc, deasserted); } } static uint16_t bnx2x_update_dsb_idx(struct bnx2x_softc *sc) { struct host_sp_status_block *def_sb = sc->def_sb; uint16_t rc = 0; mb(); /* status block is written to by the chip */ if (sc->def_att_idx != def_sb->atten_status_block.attn_bits_index) { sc->def_att_idx = def_sb->atten_status_block.attn_bits_index; rc |= BNX2X_DEF_SB_ATT_IDX; } if (sc->def_idx != def_sb->sp_sb.running_index) { sc->def_idx = def_sb->sp_sb.running_index; rc |= BNX2X_DEF_SB_IDX; } mb(); return rc; } static struct ecore_queue_sp_obj *bnx2x_cid_to_q_obj(struct bnx2x_softc *sc, uint32_t cid) { return &sc->sp_objs[CID_TO_FP(cid, sc)].q_obj; } static void bnx2x_handle_mcast_eqe(struct bnx2x_softc *sc) { struct ecore_mcast_ramrod_params rparam; int rc; memset(&rparam, 0, sizeof(rparam)); rparam.mcast_obj = &sc->mcast_obj; /* clear pending state for the last command */ sc->mcast_obj.raw.clear_pending(&sc->mcast_obj.raw); /* if there are pending mcast commands - send them */ if (sc->mcast_obj.check_pending(&sc->mcast_obj)) { rc = ecore_config_mcast(sc, &rparam, ECORE_MCAST_CMD_CONT); if (rc < 0) { PMD_DRV_LOG(INFO, "Failed to send pending mcast commands (%d)", rc); } } } static void bnx2x_handle_classification_eqe(struct bnx2x_softc *sc, union event_ring_elem *elem) { unsigned long ramrod_flags = 0; int rc = 0; uint32_t cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK; struct ecore_vlan_mac_obj *vlan_mac_obj; /* always push next commands out, don't wait here */ bnx2x_set_bit(RAMROD_CONT, &ramrod_flags); switch (le32toh(elem->message.data.eth_event.echo) >> BNX2X_SWCID_SHIFT) { case ECORE_FILTER_MAC_PENDING: PMD_DRV_LOG(DEBUG, "Got SETUP_MAC completions"); vlan_mac_obj = &sc->sp_objs[cid].mac_obj; break; case ECORE_FILTER_MCAST_PENDING: PMD_DRV_LOG(DEBUG, "Got SETUP_MCAST completions"); bnx2x_handle_mcast_eqe(sc); return; default: PMD_DRV_LOG(NOTICE, "Unsupported classification command: %d", elem->message.data.eth_event.echo); return; } rc = vlan_mac_obj->complete(sc, vlan_mac_obj, elem, &ramrod_flags); if (rc < 0) { PMD_DRV_LOG(NOTICE, "Failed to schedule new commands (%d)", rc); } else if (rc > 0) { PMD_DRV_LOG(DEBUG, "Scheduled next pending commands..."); } } static void bnx2x_handle_rx_mode_eqe(struct bnx2x_softc *sc) { bnx2x_clear_bit(ECORE_FILTER_RX_MODE_PENDING, &sc->sp_state); /* send rx_mode command again if was requested */ if (bnx2x_test_and_clear_bit(ECORE_FILTER_RX_MODE_SCHED, &sc->sp_state)) { bnx2x_set_storm_rx_mode(sc); } } static void bnx2x_update_eq_prod(struct bnx2x_softc *sc, uint16_t prod) { storm_memset_eq_prod(sc, prod, SC_FUNC(sc)); wmb(); /* keep prod updates ordered */ } static void bnx2x_eq_int(struct bnx2x_softc *sc) { uint16_t hw_cons, sw_cons, sw_prod; union event_ring_elem *elem; uint8_t echo; uint32_t cid; uint8_t opcode; int spqe_cnt = 0; struct ecore_queue_sp_obj *q_obj; struct ecore_func_sp_obj *f_obj = &sc->func_obj; struct ecore_raw_obj *rss_raw = &sc->rss_conf_obj.raw; hw_cons = le16toh(*sc->eq_cons_sb); /* * The hw_cons range is 1-255, 257 - the sw_cons range is 0-254, 256. * when we get to the next-page we need to adjust so the loop * condition below will be met. The next element is the size of a * regular element and hence incrementing by 1 */ if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE) { hw_cons++; } /* * This function may never run in parallel with itself for a * specific sc and no need for a read memory barrier here. */ sw_cons = sc->eq_cons; sw_prod = sc->eq_prod; for (; sw_cons != hw_cons; sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) { elem = &sc->eq[EQ_DESC(sw_cons)]; /* elem CID originates from FW, actually LE */ cid = SW_CID(elem->message.data.cfc_del_event.cid); opcode = elem->message.opcode; /* handle eq element */ switch (opcode) { case EVENT_RING_OPCODE_STAT_QUERY: PMD_DRV_LOG(DEBUG, "got statistics completion event %d", sc->stats_comp++); /* nothing to do with stats comp */ goto next_spqe; case EVENT_RING_OPCODE_CFC_DEL: /* handle according to cid range */ /* we may want to verify here that the sc state is HALTING */ PMD_DRV_LOG(DEBUG, "got delete ramrod for MULTI[%d]", cid); q_obj = bnx2x_cid_to_q_obj(sc, cid); if (q_obj->complete_cmd(sc, q_obj, ECORE_Q_CMD_CFC_DEL)) { break; } goto next_spqe; case EVENT_RING_OPCODE_STOP_TRAFFIC: PMD_DRV_LOG(DEBUG, "got STOP TRAFFIC"); if (f_obj->complete_cmd(sc, f_obj, ECORE_F_CMD_TX_STOP)) { break; } goto next_spqe; case EVENT_RING_OPCODE_START_TRAFFIC: PMD_DRV_LOG(DEBUG, "got START TRAFFIC"); if (f_obj->complete_cmd (sc, f_obj, ECORE_F_CMD_TX_START)) { break; } goto next_spqe; case EVENT_RING_OPCODE_FUNCTION_UPDATE: echo = elem->message.data.function_update_event.echo; if (echo == SWITCH_UPDATE) { PMD_DRV_LOG(DEBUG, "got FUNC_SWITCH_UPDATE ramrod"); if (f_obj->complete_cmd(sc, f_obj, ECORE_F_CMD_SWITCH_UPDATE)) { break; } } else { PMD_DRV_LOG(DEBUG, "AFEX: ramrod completed FUNCTION_UPDATE"); f_obj->complete_cmd(sc, f_obj, ECORE_F_CMD_AFEX_UPDATE); } goto next_spqe; case EVENT_RING_OPCODE_FORWARD_SETUP: q_obj = &bnx2x_fwd_sp_obj(sc, q_obj); if (q_obj->complete_cmd(sc, q_obj, ECORE_Q_CMD_SETUP_TX_ONLY)) { break; } goto next_spqe; case EVENT_RING_OPCODE_FUNCTION_START: PMD_DRV_LOG(DEBUG, "got FUNC_START ramrod"); if (f_obj->complete_cmd(sc, f_obj, ECORE_F_CMD_START)) { break; } goto next_spqe; case EVENT_RING_OPCODE_FUNCTION_STOP: PMD_DRV_LOG(DEBUG, "got FUNC_STOP ramrod"); if (f_obj->complete_cmd(sc, f_obj, ECORE_F_CMD_STOP)) { break; } goto next_spqe; } switch (opcode | sc->state) { case (EVENT_RING_OPCODE_RSS_UPDATE_RULES | BNX2X_STATE_OPEN): case (EVENT_RING_OPCODE_RSS_UPDATE_RULES | BNX2X_STATE_OPENING_WAITING_PORT): cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK; PMD_DRV_LOG(DEBUG, "got RSS_UPDATE ramrod. CID %d", cid); rss_raw->clear_pending(rss_raw); break; case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN): case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG): case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_CLOSING_WAITING_HALT): case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | BNX2X_STATE_OPEN): case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | BNX2X_STATE_DIAG): case (EVENT_RING_OPCODE_CLASSIFICATION_RULES | BNX2X_STATE_CLOSING_WAITING_HALT): PMD_DRV_LOG(DEBUG, "got (un)set mac ramrod"); bnx2x_handle_classification_eqe(sc, elem); break; case (EVENT_RING_OPCODE_MULTICAST_RULES | BNX2X_STATE_OPEN): case (EVENT_RING_OPCODE_MULTICAST_RULES | BNX2X_STATE_DIAG): case (EVENT_RING_OPCODE_MULTICAST_RULES | BNX2X_STATE_CLOSING_WAITING_HALT): PMD_DRV_LOG(DEBUG, "got mcast ramrod"); bnx2x_handle_mcast_eqe(sc); break; case (EVENT_RING_OPCODE_FILTERS_RULES | BNX2X_STATE_OPEN): case (EVENT_RING_OPCODE_FILTERS_RULES | BNX2X_STATE_DIAG): case (EVENT_RING_OPCODE_FILTERS_RULES | BNX2X_STATE_CLOSING_WAITING_HALT): PMD_DRV_LOG(DEBUG, "got rx_mode ramrod"); bnx2x_handle_rx_mode_eqe(sc); break; default: /* unknown event log error and continue */ PMD_DRV_LOG(INFO, "Unknown EQ event %d, sc->state 0x%x", elem->message.opcode, sc->state); } next_spqe: spqe_cnt++; } /* for */ mb(); atomic_add_acq_long(&sc->eq_spq_left, spqe_cnt); sc->eq_cons = sw_cons; sc->eq_prod = sw_prod; /* make sure that above mem writes were issued towards the memory */ wmb(); /* update producer */ bnx2x_update_eq_prod(sc, sc->eq_prod); } static int bnx2x_handle_sp_tq(struct bnx2x_softc *sc) { uint16_t status; int rc = 0; /* what work needs to be performed? */ status = bnx2x_update_dsb_idx(sc); /* HW attentions */ if (status & BNX2X_DEF_SB_ATT_IDX) { PMD_DRV_LOG(DEBUG, "---> ATTN INTR <---"); bnx2x_attn_int(sc); status &= ~BNX2X_DEF_SB_ATT_IDX; rc = 1; } /* SP events: STAT_QUERY and others */ if (status & BNX2X_DEF_SB_IDX) { /* handle EQ completions */ PMD_DRV_LOG(DEBUG, "---> EQ INTR <---"); bnx2x_eq_int(sc); bnx2x_ack_sb(sc, sc->igu_dsb_id, USTORM_ID, le16toh(sc->def_idx), IGU_INT_NOP, 1); status &= ~BNX2X_DEF_SB_IDX; } /* if status is non zero then something went wrong */ if (unlikely(status)) { PMD_DRV_LOG(INFO, "Got an unknown SP interrupt! (0x%04x)", status); } /* ack status block only if something was actually handled */ bnx2x_ack_sb(sc, sc->igu_dsb_id, ATTENTION_ID, le16toh(sc->def_att_idx), IGU_INT_ENABLE, 1); return rc; } static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp, int scan_fp) { struct bnx2x_softc *sc = fp->sc; uint8_t more_rx = FALSE; /* update the fastpath index */ bnx2x_update_fp_sb_idx(fp); if (scan_fp) { if (bnx2x_has_rx_work(fp)) { more_rx = bnx2x_rxeof(sc, fp); } if (more_rx) { /* still more work to do */ bnx2x_handle_fp_tq(fp, scan_fp); return; } } bnx2x_ack_sb(sc, fp->igu_sb_id, USTORM_ID, le16toh(fp->fp_hc_idx), IGU_INT_ENABLE, 1); } /* * Legacy interrupt entry point. * * Verifies that the controller generated the interrupt and * then calls a separate routine to handle the various * interrupt causes: link, RX, and TX. */ int bnx2x_intr_legacy(struct bnx2x_softc *sc, int scan_fp) { struct bnx2x_fastpath *fp; uint32_t status, mask; int i, rc = 0; /* * 0 for ustorm, 1 for cstorm * the bits returned from ack_int() are 0-15 * bit 0 = attention status block * bit 1 = fast path status block * a mask of 0x2 or more = tx/rx event * a mask of 1 = slow path event */ status = bnx2x_ack_int(sc); /* the interrupt is not for us */ if (unlikely(status == 0)) { return 0; } PMD_DRV_LOG(DEBUG, "Interrupt status 0x%04x", status); //bnx2x_dump_status_block(sc); FOR_EACH_ETH_QUEUE(sc, i) { fp = &sc->fp[i]; mask = (0x2 << (fp->index + CNIC_SUPPORT(sc))); if (status & mask) { bnx2x_handle_fp_tq(fp, scan_fp); status &= ~mask; } } if (unlikely(status & 0x1)) { rc = bnx2x_handle_sp_tq(sc); status &= ~0x1; } if (unlikely(status)) { PMD_DRV_LOG(WARNING, "Unexpected fastpath status (0x%08x)!", status); } return rc; } static int bnx2x_init_hw_common_chip(struct bnx2x_softc *sc); static int bnx2x_init_hw_common(struct bnx2x_softc *sc); static int bnx2x_init_hw_port(struct bnx2x_softc *sc); static int bnx2x_init_hw_func(struct bnx2x_softc *sc); static void bnx2x_reset_common(struct bnx2x_softc *sc); static void bnx2x_reset_port(struct bnx2x_softc *sc); static void bnx2x_reset_func(struct bnx2x_softc *sc); static int bnx2x_init_firmware(struct bnx2x_softc *sc); static void bnx2x_release_firmware(struct bnx2x_softc *sc); static struct ecore_func_sp_drv_ops bnx2x_func_sp_drv = { .init_hw_cmn_chip = bnx2x_init_hw_common_chip, .init_hw_cmn = bnx2x_init_hw_common, .init_hw_port = bnx2x_init_hw_port, .init_hw_func = bnx2x_init_hw_func, .reset_hw_cmn = bnx2x_reset_common, .reset_hw_port = bnx2x_reset_port, .reset_hw_func = bnx2x_reset_func, .init_fw = bnx2x_init_firmware, .release_fw = bnx2x_release_firmware, }; static void bnx2x_init_func_obj(struct bnx2x_softc *sc) { sc->dmae_ready = 0; PMD_INIT_FUNC_TRACE(); ecore_init_func_obj(sc, &sc->func_obj, BNX2X_SP(sc, func_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, func_rdata), BNX2X_SP(sc, func_afex_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, func_afex_rdata), &bnx2x_func_sp_drv); } static int bnx2x_init_hw(struct bnx2x_softc *sc, uint32_t load_code) { struct ecore_func_state_params func_params = { NULL }; int rc; PMD_INIT_FUNC_TRACE(); /* prepare the parameters for function state transitions */ bnx2x_set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); func_params.f_obj = &sc->func_obj; func_params.cmd = ECORE_F_CMD_HW_INIT; func_params.params.hw_init.load_phase = load_code; /* * Via a plethora of function pointers, we will eventually reach * bnx2x_init_hw_common(), bnx2x_init_hw_port(), or bnx2x_init_hw_func(). */ rc = ecore_func_state_change(sc, &func_params); return rc; } static void bnx2x_fill(struct bnx2x_softc *sc, uint32_t addr, int fill, uint32_t len) { uint32_t i; if (!(len % 4) && !(addr % 4)) { for (i = 0; i < len; i += 4) { REG_WR(sc, (addr + i), fill); } } else { for (i = 0; i < len; i++) { REG_WR8(sc, (addr + i), fill); } } } /* writes FP SP data to FW - data_size in dwords */ static void bnx2x_wr_fp_sb_data(struct bnx2x_softc *sc, int fw_sb_id, uint32_t * sb_data_p, uint32_t data_size) { uint32_t index; for (index = 0; index < data_size; index++) { REG_WR(sc, (BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_OFFSET(fw_sb_id) + (sizeof(uint32_t) * index)), *(sb_data_p + index)); } } static void bnx2x_zero_fp_sb(struct bnx2x_softc *sc, int fw_sb_id) { struct hc_status_block_data_e2 sb_data_e2; struct hc_status_block_data_e1x sb_data_e1x; uint32_t *sb_data_p; uint32_t data_size = 0; if (!CHIP_IS_E1x(sc)) { memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2)); sb_data_e2.common.state = SB_DISABLED; sb_data_e2.common.p_func.vf_valid = FALSE; sb_data_p = (uint32_t *) & sb_data_e2; data_size = (sizeof(struct hc_status_block_data_e2) / sizeof(uint32_t)); } else { memset(&sb_data_e1x, 0, sizeof(struct hc_status_block_data_e1x)); sb_data_e1x.common.state = SB_DISABLED; sb_data_e1x.common.p_func.vf_valid = FALSE; sb_data_p = (uint32_t *) & sb_data_e1x; data_size = (sizeof(struct hc_status_block_data_e1x) / sizeof(uint32_t)); } bnx2x_wr_fp_sb_data(sc, fw_sb_id, sb_data_p, data_size); bnx2x_fill(sc, (BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(fw_sb_id)), 0, CSTORM_STATUS_BLOCK_SIZE); bnx2x_fill(sc, (BAR_CSTRORM_INTMEM + CSTORM_SYNC_BLOCK_OFFSET(fw_sb_id)), 0, CSTORM_SYNC_BLOCK_SIZE); } static void bnx2x_wr_sp_sb_data(struct bnx2x_softc *sc, struct hc_sp_status_block_data *sp_sb_data) { uint32_t i; for (i = 0; i < (sizeof(struct hc_sp_status_block_data) / sizeof(uint32_t)); i++) { REG_WR(sc, (BAR_CSTRORM_INTMEM + CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(SC_FUNC(sc)) + (i * sizeof(uint32_t))), *((uint32_t *) sp_sb_data + i)); } } static void bnx2x_zero_sp_sb(struct bnx2x_softc *sc) { struct hc_sp_status_block_data sp_sb_data; memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data)); sp_sb_data.state = SB_DISABLED; sp_sb_data.p_func.vf_valid = FALSE; bnx2x_wr_sp_sb_data(sc, &sp_sb_data); bnx2x_fill(sc, (BAR_CSTRORM_INTMEM + CSTORM_SP_STATUS_BLOCK_OFFSET(SC_FUNC(sc))), 0, CSTORM_SP_STATUS_BLOCK_SIZE); bnx2x_fill(sc, (BAR_CSTRORM_INTMEM + CSTORM_SP_SYNC_BLOCK_OFFSET(SC_FUNC(sc))), 0, CSTORM_SP_SYNC_BLOCK_SIZE); } static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm, int igu_sb_id, int igu_seg_id) { hc_sm->igu_sb_id = igu_sb_id; hc_sm->igu_seg_id = igu_seg_id; hc_sm->timer_value = 0xFF; hc_sm->time_to_expire = 0xFFFFFFFF; } static void bnx2x_map_sb_state_machines(struct hc_index_data *index_data) { /* zero out state machine indices */ /* rx indices */ index_data[HC_INDEX_ETH_RX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID; /* tx indices */ index_data[HC_INDEX_OOO_TX_CQ_CONS].flags &= ~HC_INDEX_DATA_SM_ID; index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags &= ~HC_INDEX_DATA_SM_ID; index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags &= ~HC_INDEX_DATA_SM_ID; index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags &= ~HC_INDEX_DATA_SM_ID; /* map indices */ /* rx indices */ index_data[HC_INDEX_ETH_RX_CQ_CONS].flags |= (SM_RX_ID << HC_INDEX_DATA_SM_ID_SHIFT); /* tx indices */ index_data[HC_INDEX_OOO_TX_CQ_CONS].flags |= (SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT); index_data[HC_INDEX_ETH_TX_CQ_CONS_COS0].flags |= (SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT); index_data[HC_INDEX_ETH_TX_CQ_CONS_COS1].flags |= (SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT); index_data[HC_INDEX_ETH_TX_CQ_CONS_COS2].flags |= (SM_TX_ID << HC_INDEX_DATA_SM_ID_SHIFT); } static void bnx2x_init_sb(struct bnx2x_softc *sc, phys_addr_t busaddr, int vfid, uint8_t vf_valid, int fw_sb_id, int igu_sb_id) { struct hc_status_block_data_e2 sb_data_e2; struct hc_status_block_data_e1x sb_data_e1x; struct hc_status_block_sm *hc_sm_p; uint32_t *sb_data_p; int igu_seg_id; int data_size; if (CHIP_INT_MODE_IS_BC(sc)) { igu_seg_id = HC_SEG_ACCESS_NORM; } else { igu_seg_id = IGU_SEG_ACCESS_NORM; } bnx2x_zero_fp_sb(sc, fw_sb_id); if (!CHIP_IS_E1x(sc)) { memset(&sb_data_e2, 0, sizeof(struct hc_status_block_data_e2)); sb_data_e2.common.state = SB_ENABLED; sb_data_e2.common.p_func.pf_id = SC_FUNC(sc); sb_data_e2.common.p_func.vf_id = vfid; sb_data_e2.common.p_func.vf_valid = vf_valid; sb_data_e2.common.p_func.vnic_id = SC_VN(sc); sb_data_e2.common.same_igu_sb_1b = TRUE; sb_data_e2.common.host_sb_addr.hi = U64_HI(busaddr); sb_data_e2.common.host_sb_addr.lo = U64_LO(busaddr); hc_sm_p = sb_data_e2.common.state_machine; sb_data_p = (uint32_t *) & sb_data_e2; data_size = (sizeof(struct hc_status_block_data_e2) / sizeof(uint32_t)); bnx2x_map_sb_state_machines(sb_data_e2.index_data); } else { memset(&sb_data_e1x, 0, sizeof(struct hc_status_block_data_e1x)); sb_data_e1x.common.state = SB_ENABLED; sb_data_e1x.common.p_func.pf_id = SC_FUNC(sc); sb_data_e1x.common.p_func.vf_id = 0xff; sb_data_e1x.common.p_func.vf_valid = FALSE; sb_data_e1x.common.p_func.vnic_id = SC_VN(sc); sb_data_e1x.common.same_igu_sb_1b = TRUE; sb_data_e1x.common.host_sb_addr.hi = U64_HI(busaddr); sb_data_e1x.common.host_sb_addr.lo = U64_LO(busaddr); hc_sm_p = sb_data_e1x.common.state_machine; sb_data_p = (uint32_t *) & sb_data_e1x; data_size = (sizeof(struct hc_status_block_data_e1x) / sizeof(uint32_t)); bnx2x_map_sb_state_machines(sb_data_e1x.index_data); } bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_RX_ID], igu_sb_id, igu_seg_id); bnx2x_setup_ndsb_state_machine(&hc_sm_p[SM_TX_ID], igu_sb_id, igu_seg_id); /* write indices to HW - PCI guarantees endianity of regpairs */ bnx2x_wr_fp_sb_data(sc, fw_sb_id, sb_data_p, data_size); } static uint8_t bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp) { if (CHIP_IS_E1x(fp->sc)) { return (fp->cl_id + SC_PORT(fp->sc) * ETH_MAX_RX_CLIENTS_E1H); } else { return (fp->cl_id); } } static uint32_t bnx2x_rx_ustorm_prods_offset(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp) { uint32_t offset = BAR_USTRORM_INTMEM; if (IS_VF(sc)) { return (PXP_VF_ADDR_USDM_QUEUES_START + (sc->acquire_resp.resc.hw_qid[fp->index] * sizeof(struct ustorm_queue_zone_data))); } else if (!CHIP_IS_E1x(sc)) { offset += USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id); } else { offset += USTORM_RX_PRODS_E1X_OFFSET(SC_PORT(sc), fp->cl_id); } return offset; } static void bnx2x_init_eth_fp(struct bnx2x_softc *sc, int idx) { struct bnx2x_fastpath *fp = &sc->fp[idx]; uint32_t cids[ECORE_MULTI_TX_COS] = { 0 }; unsigned long q_type = 0; int cos; fp->sc = sc; fp->index = idx; fp->igu_sb_id = (sc->igu_base_sb + idx + CNIC_SUPPORT(sc)); fp->fw_sb_id = (sc->base_fw_ndsb + idx + CNIC_SUPPORT(sc)); if (CHIP_IS_E1x(sc)) fp->cl_id = SC_L_ID(sc) + idx; else /* want client ID same as IGU SB ID for non-E1 */ fp->cl_id = fp->igu_sb_id; fp->cl_qzone_id = bnx2x_fp_qzone_id(fp); /* setup sb indices */ if (!CHIP_IS_E1x(sc)) { fp->sb_index_values = fp->status_block.e2_sb->sb.index_values; fp->sb_running_index = fp->status_block.e2_sb->sb.running_index; } else { fp->sb_index_values = fp->status_block.e1x_sb->sb.index_values; fp->sb_running_index = fp->status_block.e1x_sb->sb.running_index; } /* init shortcut */ fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(sc, fp); fp->rx_cq_cons_sb = &fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS]; for (cos = 0; cos < sc->max_cos; cos++) { cids[cos] = idx; } fp->tx_cons_sb = &fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0]; /* nothing more for a VF to do */ if (IS_VF(sc)) { return; } bnx2x_init_sb(sc, fp->sb_dma.paddr, BNX2X_VF_ID_INVALID, FALSE, fp->fw_sb_id, fp->igu_sb_id); bnx2x_update_fp_sb_idx(fp); /* Configure Queue State object */ bnx2x_set_bit(ECORE_Q_TYPE_HAS_RX, &q_type); bnx2x_set_bit(ECORE_Q_TYPE_HAS_TX, &q_type); ecore_init_queue_obj(sc, &sc->sp_objs[idx].q_obj, fp->cl_id, cids, sc->max_cos, SC_FUNC(sc), BNX2X_SP(sc, q_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, q_rdata), q_type); /* configure classification DBs */ ecore_init_mac_obj(sc, &sc->sp_objs[idx].mac_obj, fp->cl_id, idx, SC_FUNC(sc), BNX2X_SP(sc, mac_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, mac_rdata), ECORE_FILTER_MAC_PENDING, &sc->sp_state, ECORE_OBJ_TYPE_RX_TX, &sc->macs_pool); } static void bnx2x_update_rx_prod(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, uint16_t rx_bd_prod, uint16_t rx_cq_prod) { union ustorm_eth_rx_producers rx_prods; uint32_t i; /* update producers */ rx_prods.prod.bd_prod = rx_bd_prod; rx_prods.prod.cqe_prod = rx_cq_prod; rx_prods.prod.reserved = 0; /* * Make sure that the BD and SGE data is updated before updating the * producers since FW might read the BD/SGE right after the producer * is updated. * This is only applicable for weak-ordered memory model archs such * as IA-64. The following barrier is also mandatory since FW will * assumes BDs must have buffers. */ wmb(); for (i = 0; i < (sizeof(rx_prods) / 4); i++) { REG_WR(sc, (fp->ustorm_rx_prods_offset + (i * 4)), rx_prods.raw_data[i]); } wmb(); /* keep prod updates ordered */ } static void bnx2x_init_rx_rings(struct bnx2x_softc *sc) { struct bnx2x_fastpath *fp; int i; struct bnx2x_rx_queue *rxq; for (i = 0; i < sc->num_queues; i++) { fp = &sc->fp[i]; rxq = sc->rx_queues[fp->index]; if (!rxq) { PMD_RX_LOG(ERR, "RX queue is NULL"); return; } /* * Activate the BD ring... * Warning, this will generate an interrupt (to the TSTORM) * so this can only be done after the chip is initialized */ bnx2x_update_rx_prod(sc, fp, rxq->rx_bd_tail, rxq->rx_cq_tail); if (i != 0) { continue; } } } static void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp) { struct bnx2x_tx_queue *txq = fp->sc->tx_queues[fp->index]; fp->tx_db.data.header.header = 1 << DOORBELL_HDR_DB_TYPE_SHIFT; fp->tx_db.data.zero_fill1 = 0; fp->tx_db.data.prod = 0; if (!txq) { PMD_TX_LOG(ERR, "ERROR: TX queue is NULL"); return; } txq->tx_pkt_tail = 0; txq->tx_pkt_head = 0; txq->tx_bd_tail = 0; txq->tx_bd_head = 0; } static void bnx2x_init_tx_rings(struct bnx2x_softc *sc) { int i; for (i = 0; i < sc->num_queues; i++) { bnx2x_init_tx_ring_one(&sc->fp[i]); } } static void bnx2x_init_def_sb(struct bnx2x_softc *sc) { struct host_sp_status_block *def_sb = sc->def_sb; phys_addr_t mapping = sc->def_sb_dma.paddr; int igu_sp_sb_index; int igu_seg_id; int port = SC_PORT(sc); int func = SC_FUNC(sc); int reg_offset, reg_offset_en5; uint64_t section; int index, sindex; struct hc_sp_status_block_data sp_sb_data; memset(&sp_sb_data, 0, sizeof(struct hc_sp_status_block_data)); if (CHIP_INT_MODE_IS_BC(sc)) { igu_sp_sb_index = DEF_SB_IGU_ID; igu_seg_id = HC_SEG_ACCESS_DEF; } else { igu_sp_sb_index = sc->igu_dsb_id; igu_seg_id = IGU_SEG_ACCESS_DEF; } /* attentions */ section = ((uint64_t) mapping + offsetof(struct host_sp_status_block, atten_status_block)); def_sb->atten_status_block.status_block_id = igu_sp_sb_index; sc->attn_state = 0; reg_offset = (port) ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0; reg_offset_en5 = (port) ? MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0; for (index = 0; index < MAX_DYNAMIC_ATTN_GRPS; index++) { /* take care of sig[0]..sig[4] */ for (sindex = 0; sindex < 4; sindex++) { sc->attn_group[index].sig[sindex] = REG_RD(sc, (reg_offset + (sindex * 0x4) + (0x10 * index))); } if (!CHIP_IS_E1x(sc)) { /* * enable5 is separate from the rest of the registers, * and the address skip is 4 and not 16 between the * different groups */ sc->attn_group[index].sig[4] = REG_RD(sc, (reg_offset_en5 + (0x4 * index))); } else { sc->attn_group[index].sig[4] = 0; } } if (sc->devinfo.int_block == INT_BLOCK_HC) { reg_offset = port ? HC_REG_ATTN_MSG1_ADDR_L : HC_REG_ATTN_MSG0_ADDR_L; REG_WR(sc, reg_offset, U64_LO(section)); REG_WR(sc, (reg_offset + 4), U64_HI(section)); } else if (!CHIP_IS_E1x(sc)) { REG_WR(sc, IGU_REG_ATTN_MSG_ADDR_L, U64_LO(section)); REG_WR(sc, IGU_REG_ATTN_MSG_ADDR_H, U64_HI(section)); } section = ((uint64_t) mapping + offsetof(struct host_sp_status_block, sp_sb)); bnx2x_zero_sp_sb(sc); /* PCI guarantees endianity of regpair */ sp_sb_data.state = SB_ENABLED; sp_sb_data.host_sb_addr.lo = U64_LO(section); sp_sb_data.host_sb_addr.hi = U64_HI(section); sp_sb_data.igu_sb_id = igu_sp_sb_index; sp_sb_data.igu_seg_id = igu_seg_id; sp_sb_data.p_func.pf_id = func; sp_sb_data.p_func.vnic_id = SC_VN(sc); sp_sb_data.p_func.vf_id = 0xff; bnx2x_wr_sp_sb_data(sc, &sp_sb_data); bnx2x_ack_sb(sc, sc->igu_dsb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0); } static void bnx2x_init_sp_ring(struct bnx2x_softc *sc) { atomic_store_rel_long(&sc->cq_spq_left, MAX_SPQ_PENDING); sc->spq_prod_idx = 0; sc->dsb_sp_prod = &sc->def_sb->sp_sb.index_values[HC_SP_INDEX_ETH_DEF_CONS]; sc->spq_prod_bd = sc->spq; sc->spq_last_bd = (sc->spq_prod_bd + MAX_SP_DESC_CNT); } static void bnx2x_init_eq_ring(struct bnx2x_softc *sc) { union event_ring_elem *elem; int i; for (i = 1; i <= NUM_EQ_PAGES; i++) { elem = &sc->eq[EQ_DESC_CNT_PAGE * i - 1]; elem->next_page.addr.hi = htole32(U64_HI(sc->eq_dma.paddr + BNX2X_PAGE_SIZE * (i % NUM_EQ_PAGES))); elem->next_page.addr.lo = htole32(U64_LO(sc->eq_dma.paddr + BNX2X_PAGE_SIZE * (i % NUM_EQ_PAGES))); } sc->eq_cons = 0; sc->eq_prod = NUM_EQ_DESC; sc->eq_cons_sb = &sc->def_sb->sp_sb.index_values[HC_SP_INDEX_EQ_CONS]; atomic_store_rel_long(&sc->eq_spq_left, (min((MAX_SP_DESC_CNT - MAX_SPQ_PENDING), NUM_EQ_DESC) - 1)); } static void bnx2x_init_internal_common(struct bnx2x_softc *sc) { int i; if (IS_MF_SI(sc)) { /* * In switch independent mode, the TSTORM needs to accept * packets that failed classification, since approximate match * mac addresses aren't written to NIG LLH. */ REG_WR8(sc, (BAR_TSTRORM_INTMEM + TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET), 2); } else REG_WR8(sc, (BAR_TSTRORM_INTMEM + TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET), 0); /* * Zero this manually as its initialization is currently missing * in the initTool. */ for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++) { REG_WR(sc, (BAR_USTRORM_INTMEM + USTORM_AGG_DATA_OFFSET + (i * 4)), 0); } if (!CHIP_IS_E1x(sc)) { REG_WR8(sc, (BAR_CSTRORM_INTMEM + CSTORM_IGU_MODE_OFFSET), CHIP_INT_MODE_IS_BC(sc) ? HC_IGU_BC_MODE : HC_IGU_NBC_MODE); } } static void bnx2x_init_internal(struct bnx2x_softc *sc, uint32_t load_code) { switch (load_code) { case FW_MSG_CODE_DRV_LOAD_COMMON: case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: bnx2x_init_internal_common(sc); /* no break */ case FW_MSG_CODE_DRV_LOAD_PORT: /* nothing to do */ /* no break */ case FW_MSG_CODE_DRV_LOAD_FUNCTION: /* internal memory per function is initialized inside bnx2x_pf_init */ break; default: PMD_DRV_LOG(NOTICE, "Unknown load_code (0x%x) from MCP", load_code); break; } } static void storm_memset_func_cfg(struct bnx2x_softc *sc, struct tstorm_eth_function_common_config *tcfg, uint16_t abs_fid) { uint32_t addr; size_t size; addr = (BAR_TSTRORM_INTMEM + TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid)); size = sizeof(struct tstorm_eth_function_common_config); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) tcfg); } static void bnx2x_func_init(struct bnx2x_softc *sc, struct bnx2x_func_init_params *p) { struct tstorm_eth_function_common_config tcfg = { 0 }; if (CHIP_IS_E1x(sc)) { storm_memset_func_cfg(sc, &tcfg, p->func_id); } /* Enable the function in the FW */ storm_memset_vf_to_pf(sc, p->func_id, p->pf_id); storm_memset_func_en(sc, p->func_id, 1); /* spq */ if (p->func_flgs & FUNC_FLG_SPQ) { storm_memset_spq_addr(sc, p->spq_map, p->func_id); REG_WR(sc, (XSEM_REG_FAST_MEMORY + XSTORM_SPQ_PROD_OFFSET(p->func_id)), p->spq_prod); } } /* * Calculates the sum of vn_min_rates. * It's needed for further normalizing of the min_rates. * Returns: * sum of vn_min_rates. * or * 0 - if all the min_rates are 0. * In the later case fainess algorithm should be deactivated. * If all min rates are not zero then those that are zeroes will be set to 1. */ static void bnx2x_calc_vn_min(struct bnx2x_softc *sc, struct cmng_init_input *input) { uint32_t vn_cfg; uint32_t vn_min_rate; int all_zero = 1; int vn; for (vn = VN_0; vn < SC_MAX_VN_NUM(sc); vn++) { vn_cfg = sc->devinfo.mf_info.mf_config[vn]; vn_min_rate = (((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT) * 100); if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) { /* skip hidden VNs */ vn_min_rate = 0; } else if (!vn_min_rate) { /* If min rate is zero - set it to 100 */ vn_min_rate = DEF_MIN_RATE; } else { all_zero = 0; } input->vnic_min_rate[vn] = vn_min_rate; } /* if ETS or all min rates are zeros - disable fairness */ if (all_zero) { input->flags.cmng_enables &= ~CMNG_FLAGS_PER_PORT_FAIRNESS_VN; } else { input->flags.cmng_enables |= CMNG_FLAGS_PER_PORT_FAIRNESS_VN; } } static uint16_t bnx2x_extract_max_cfg(__rte_unused struct bnx2x_softc *sc, uint32_t mf_cfg) { uint16_t max_cfg = ((mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT); if (!max_cfg) { PMD_DRV_LOG(DEBUG, "Max BW configured to 0 - using 100 instead"); max_cfg = 100; } return max_cfg; } static void bnx2x_calc_vn_max(struct bnx2x_softc *sc, int vn, struct cmng_init_input *input) { uint16_t vn_max_rate; uint32_t vn_cfg = sc->devinfo.mf_info.mf_config[vn]; uint32_t max_cfg; if (vn_cfg & FUNC_MF_CFG_FUNC_HIDE) { vn_max_rate = 0; } else { max_cfg = bnx2x_extract_max_cfg(sc, vn_cfg); if (IS_MF_SI(sc)) { /* max_cfg in percents of linkspeed */ vn_max_rate = ((sc->link_vars.line_speed * max_cfg) / 100); } else { /* SD modes */ /* max_cfg is absolute in 100Mb units */ vn_max_rate = (max_cfg * 100); } } input->vnic_max_rate[vn] = vn_max_rate; } static void bnx2x_cmng_fns_init(struct bnx2x_softc *sc, uint8_t read_cfg, uint8_t cmng_type) { struct cmng_init_input input; int vn; memset(&input, 0, sizeof(struct cmng_init_input)); input.port_rate = sc->link_vars.line_speed; if (cmng_type == CMNG_FNS_MINMAX) { /* read mf conf from shmem */ if (read_cfg) { bnx2x_read_mf_cfg(sc); } /* get VN min rate and enable fairness if not 0 */ bnx2x_calc_vn_min(sc, &input); /* get VN max rate */ if (sc->port.pmf) { for (vn = VN_0; vn < SC_MAX_VN_NUM(sc); vn++) { bnx2x_calc_vn_max(sc, vn, &input); } } /* always enable rate shaping and fairness */ input.flags.cmng_enables |= CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN; ecore_init_cmng(&input, &sc->cmng); return; } } static int bnx2x_get_cmng_fns_mode(struct bnx2x_softc *sc) { if (CHIP_REV_IS_SLOW(sc)) { return CMNG_FNS_NONE; } if (IS_MF(sc)) { return CMNG_FNS_MINMAX; } return CMNG_FNS_NONE; } static void storm_memset_cmng(struct bnx2x_softc *sc, struct cmng_init *cmng, uint8_t port) { int vn; int func; uint32_t addr; size_t size; addr = (BAR_XSTRORM_INTMEM + XSTORM_CMNG_PER_PORT_VARS_OFFSET(port)); size = sizeof(struct cmng_struct_per_port); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) & cmng->port); for (vn = VN_0; vn < SC_MAX_VN_NUM(sc); vn++) { func = func_by_vn(sc, vn); addr = (BAR_XSTRORM_INTMEM + XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(func)); size = sizeof(struct rate_shaping_vars_per_vn); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) & cmng-> vnic.vnic_max_rate[vn]); addr = (BAR_XSTRORM_INTMEM + XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(func)); size = sizeof(struct fairness_vars_per_vn); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) & cmng-> vnic.vnic_min_rate[vn]); } } static void bnx2x_pf_init(struct bnx2x_softc *sc) { struct bnx2x_func_init_params func_init; struct event_ring_data eq_data; uint16_t flags; memset(&eq_data, 0, sizeof(struct event_ring_data)); memset(&func_init, 0, sizeof(struct bnx2x_func_init_params)); if (!CHIP_IS_E1x(sc)) { /* reset IGU PF statistics: MSIX + ATTN */ /* PF */ REG_WR(sc, (IGU_REG_STATISTIC_NUM_MESSAGE_SENT + (BNX2X_IGU_STAS_MSG_VF_CNT * 4) + ((CHIP_IS_MODE_4_PORT(sc) ? SC_FUNC(sc) : SC_VN(sc)) * 4)), 0); /* ATTN */ REG_WR(sc, (IGU_REG_STATISTIC_NUM_MESSAGE_SENT + (BNX2X_IGU_STAS_MSG_VF_CNT * 4) + (BNX2X_IGU_STAS_MSG_PF_CNT * 4) + ((CHIP_IS_MODE_4_PORT(sc) ? SC_FUNC(sc) : SC_VN(sc)) * 4)), 0); } /* function setup flags */ flags = (FUNC_FLG_STATS | FUNC_FLG_LEADING | FUNC_FLG_SPQ); func_init.func_flgs = flags; func_init.pf_id = SC_FUNC(sc); func_init.func_id = SC_FUNC(sc); func_init.spq_map = sc->spq_dma.paddr; func_init.spq_prod = sc->spq_prod_idx; bnx2x_func_init(sc, &func_init); memset(&sc->cmng, 0, sizeof(struct cmng_struct_per_port)); /* * Congestion management values depend on the link rate. * There is no active link so initial link rate is set to 10Gbps. * When the link comes up the congestion management values are * re-calculated according to the actual link rate. */ sc->link_vars.line_speed = SPEED_10000; bnx2x_cmng_fns_init(sc, TRUE, bnx2x_get_cmng_fns_mode(sc)); /* Only the PMF sets the HW */ if (sc->port.pmf) { storm_memset_cmng(sc, &sc->cmng, SC_PORT(sc)); } /* init Event Queue - PCI bus guarantees correct endainity */ eq_data.base_addr.hi = U64_HI(sc->eq_dma.paddr); eq_data.base_addr.lo = U64_LO(sc->eq_dma.paddr); eq_data.producer = sc->eq_prod; eq_data.index_id = HC_SP_INDEX_EQ_CONS; eq_data.sb_id = DEF_SB_ID; storm_memset_eq_data(sc, &eq_data, SC_FUNC(sc)); } static void bnx2x_hc_int_enable(struct bnx2x_softc *sc) { int port = SC_PORT(sc); uint32_t addr = (port) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; uint32_t val = REG_RD(sc, addr); uint8_t msix = (sc->interrupt_mode == INTR_MODE_MSIX) || (sc->interrupt_mode == INTR_MODE_SINGLE_MSIX); uint8_t single_msix = (sc->interrupt_mode == INTR_MODE_SINGLE_MSIX); uint8_t msi = (sc->interrupt_mode == INTR_MODE_MSI); if (msix) { val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | HC_CONFIG_0_REG_INT_LINE_EN_0); val |= (HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); if (single_msix) { val |= HC_CONFIG_0_REG_SINGLE_ISR_EN_0; } } else if (msi) { val &= ~HC_CONFIG_0_REG_INT_LINE_EN_0; val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); } else { val |= (HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | HC_CONFIG_0_REG_INT_LINE_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); REG_WR(sc, addr, val); val &= ~HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0; } REG_WR(sc, addr, val); /* ensure that HC_CONFIG is written before leading/trailing edge config */ mb(); /* init leading/trailing edge */ if (IS_MF(sc)) { val = (0xee0f | (1 << (SC_VN(sc) + 4))); if (sc->port.pmf) { /* enable nig and gpio3 attention */ val |= 0x1100; } } else { val = 0xffff; } REG_WR(sc, (HC_REG_TRAILING_EDGE_0 + port * 8), val); REG_WR(sc, (HC_REG_LEADING_EDGE_0 + port * 8), val); /* make sure that interrupts are indeed enabled from here on */ mb(); } static void bnx2x_igu_int_enable(struct bnx2x_softc *sc) { uint32_t val; uint8_t msix = (sc->interrupt_mode == INTR_MODE_MSIX) || (sc->interrupt_mode == INTR_MODE_SINGLE_MSIX); uint8_t single_msix = (sc->interrupt_mode == INTR_MODE_SINGLE_MSIX); uint8_t msi = (sc->interrupt_mode == INTR_MODE_MSI); val = REG_RD(sc, IGU_REG_PF_CONFIGURATION); if (msix) { val &= ~(IGU_PF_CONF_INT_LINE_EN | IGU_PF_CONF_SINGLE_ISR_EN); val |= (IGU_PF_CONF_MSI_MSIX_EN | IGU_PF_CONF_ATTN_BIT_EN); if (single_msix) { val |= IGU_PF_CONF_SINGLE_ISR_EN; } } else if (msi) { val &= ~IGU_PF_CONF_INT_LINE_EN; val |= (IGU_PF_CONF_MSI_MSIX_EN | IGU_PF_CONF_ATTN_BIT_EN | IGU_PF_CONF_SINGLE_ISR_EN); } else { val &= ~IGU_PF_CONF_MSI_MSIX_EN; val |= (IGU_PF_CONF_INT_LINE_EN | IGU_PF_CONF_ATTN_BIT_EN | IGU_PF_CONF_SINGLE_ISR_EN); } /* clean previous status - need to configure igu prior to ack */ if ((!msix) || single_msix) { REG_WR(sc, IGU_REG_PF_CONFIGURATION, val); bnx2x_ack_int(sc); } val |= IGU_PF_CONF_FUNC_EN; PMD_DRV_LOG(DEBUG, "write 0x%x to IGU mode %s", val, ((msix) ? "MSI-X" : ((msi) ? "MSI" : "INTx"))); REG_WR(sc, IGU_REG_PF_CONFIGURATION, val); mb(); /* init leading/trailing edge */ if (IS_MF(sc)) { val = (0xee0f | (1 << (SC_VN(sc) + 4))); if (sc->port.pmf) { /* enable nig and gpio3 attention */ val |= 0x1100; } } else { val = 0xffff; } REG_WR(sc, IGU_REG_TRAILING_EDGE_LATCH, val); REG_WR(sc, IGU_REG_LEADING_EDGE_LATCH, val); /* make sure that interrupts are indeed enabled from here on */ mb(); } static void bnx2x_int_enable(struct bnx2x_softc *sc) { if (sc->devinfo.int_block == INT_BLOCK_HC) { bnx2x_hc_int_enable(sc); } else { bnx2x_igu_int_enable(sc); } } static void bnx2x_hc_int_disable(struct bnx2x_softc *sc) { int port = SC_PORT(sc); uint32_t addr = (port) ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0; uint32_t val = REG_RD(sc, addr); val &= ~(HC_CONFIG_0_REG_SINGLE_ISR_EN_0 | HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 | HC_CONFIG_0_REG_INT_LINE_EN_0 | HC_CONFIG_0_REG_ATTN_BIT_EN_0); /* flush all outstanding writes */ mb(); REG_WR(sc, addr, val); if (REG_RD(sc, addr) != val) { PMD_DRV_LOG(ERR, "proper val not read from HC IGU!"); } } static void bnx2x_igu_int_disable(struct bnx2x_softc *sc) { uint32_t val = REG_RD(sc, IGU_REG_PF_CONFIGURATION); val &= ~(IGU_PF_CONF_MSI_MSIX_EN | IGU_PF_CONF_INT_LINE_EN | IGU_PF_CONF_ATTN_BIT_EN); PMD_DRV_LOG(DEBUG, "write %x to IGU", val); /* flush all outstanding writes */ mb(); REG_WR(sc, IGU_REG_PF_CONFIGURATION, val); if (REG_RD(sc, IGU_REG_PF_CONFIGURATION) != val) { PMD_DRV_LOG(ERR, "proper val not read from IGU!"); } } static void bnx2x_int_disable(struct bnx2x_softc *sc) { if (sc->devinfo.int_block == INT_BLOCK_HC) { bnx2x_hc_int_disable(sc); } else { bnx2x_igu_int_disable(sc); } } static void bnx2x_nic_init(struct bnx2x_softc *sc, int load_code) { int i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < sc->num_queues; i++) { bnx2x_init_eth_fp(sc, i); } rmb(); /* ensure status block indices were read */ bnx2x_init_rx_rings(sc); bnx2x_init_tx_rings(sc); if (IS_VF(sc)) { bnx2x_memset_stats(sc); return; } /* initialize MOD_ABS interrupts */ elink_init_mod_abs_int(sc, &sc->link_vars, sc->devinfo.chip_id, sc->devinfo.shmem_base, sc->devinfo.shmem2_base, SC_PORT(sc)); bnx2x_init_def_sb(sc); bnx2x_update_dsb_idx(sc); bnx2x_init_sp_ring(sc); bnx2x_init_eq_ring(sc); bnx2x_init_internal(sc, load_code); bnx2x_pf_init(sc); bnx2x_stats_init(sc); /* flush all before enabling interrupts */ mb(); bnx2x_int_enable(sc); /* check for SPIO5 */ bnx2x_attn_int_deasserted0(sc, REG_RD(sc, (MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + SC_PORT(sc) * 4)) & AEU_INPUTS_ATTN_BITS_SPIO5); } static void bnx2x_init_objs(struct bnx2x_softc *sc) { /* mcast rules must be added to tx if tx switching is enabled */ ecore_obj_type o_type; if (sc->flags & BNX2X_TX_SWITCHING) o_type = ECORE_OBJ_TYPE_RX_TX; else o_type = ECORE_OBJ_TYPE_RX; /* RX_MODE controlling object */ ecore_init_rx_mode_obj(sc, &sc->rx_mode_obj); /* multicast configuration controlling object */ ecore_init_mcast_obj(sc, &sc->mcast_obj, sc->fp[0].cl_id, sc->fp[0].index, SC_FUNC(sc), SC_FUNC(sc), BNX2X_SP(sc, mcast_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, mcast_rdata), ECORE_FILTER_MCAST_PENDING, &sc->sp_state, o_type); /* Setup CAM credit pools */ ecore_init_mac_credit_pool(sc, &sc->macs_pool, SC_FUNC(sc), CHIP_IS_E1x(sc) ? VNICS_PER_PORT(sc) : VNICS_PER_PATH(sc)); ecore_init_vlan_credit_pool(sc, &sc->vlans_pool, SC_ABS_FUNC(sc) >> 1, CHIP_IS_E1x(sc) ? VNICS_PER_PORT(sc) : VNICS_PER_PATH(sc)); /* RSS configuration object */ ecore_init_rss_config_obj(&sc->rss_conf_obj, sc->fp[0].cl_id, sc->fp[0].index, SC_FUNC(sc), SC_FUNC(sc), BNX2X_SP(sc, rss_rdata), (phys_addr_t)BNX2X_SP_MAPPING(sc, rss_rdata), ECORE_FILTER_RSS_CONF_PENDING, &sc->sp_state, ECORE_OBJ_TYPE_RX); } /* * Initialize the function. This must be called before sending CLIENT_SETUP * for the first client. */ static int bnx2x_func_start(struct bnx2x_softc *sc) { struct ecore_func_state_params func_params = { NULL }; struct ecore_func_start_params *start_params = &func_params.params.start; /* Prepare parameters for function state transitions */ bnx2x_set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); func_params.f_obj = &sc->func_obj; func_params.cmd = ECORE_F_CMD_START; /* Function parameters */ start_params->mf_mode = sc->devinfo.mf_info.mf_mode; start_params->sd_vlan_tag = OVLAN(sc); if (CHIP_IS_E2(sc) || CHIP_IS_E3(sc)) { start_params->network_cos_mode = STATIC_COS; } else { /* CHIP_IS_E1X */ start_params->network_cos_mode = FW_WRR; } start_params->gre_tunnel_mode = 0; start_params->gre_tunnel_rss = 0; return ecore_func_state_change(sc, &func_params); } static int bnx2x_set_power_state(struct bnx2x_softc *sc, uint8_t state) { uint16_t pmcsr; /* If there is no power capability, silently succeed */ if (!(sc->devinfo.pcie_cap_flags & BNX2X_PM_CAPABLE_FLAG)) { PMD_DRV_LOG(WARNING, "No power capability"); return 0; } pci_read(sc, (sc->devinfo.pcie_pm_cap_reg + PCIR_POWER_STATUS), &pmcsr, 2); switch (state) { case PCI_PM_D0: pci_write_word(sc, (sc->devinfo.pcie_pm_cap_reg + PCIR_POWER_STATUS), ((pmcsr & ~PCIM_PSTAT_DMASK) | PCIM_PSTAT_PME)); if (pmcsr & PCIM_PSTAT_DMASK) { /* delay required during transition out of D3hot */ DELAY(20000); } break; case PCI_PM_D3hot: /* don't shut down the power for emulation and FPGA */ if (CHIP_REV_IS_SLOW(sc)) { return 0; } pmcsr &= ~PCIM_PSTAT_DMASK; pmcsr |= PCIM_PSTAT_D3; if (sc->wol) { pmcsr |= PCIM_PSTAT_PMEENABLE; } pci_write_long(sc, (sc->devinfo.pcie_pm_cap_reg + PCIR_POWER_STATUS), pmcsr); /* * No more memory access after this point until device is brought back * to D0 state. */ break; default: PMD_DRV_LOG(NOTICE, "Can't support PCI power state = %d", state); return -1; } return 0; } /* return true if succeeded to acquire the lock */ static uint8_t bnx2x_trylock_hw_lock(struct bnx2x_softc *sc, uint32_t resource) { uint32_t lock_status; uint32_t resource_bit = (1 << resource); int func = SC_FUNC(sc); uint32_t hw_lock_control_reg; /* Validating that the resource is within range */ if (resource > HW_LOCK_MAX_RESOURCE_VALUE) { PMD_DRV_LOG(INFO, "resource(0x%x) > HW_LOCK_MAX_RESOURCE_VALUE(0x%x)", resource, HW_LOCK_MAX_RESOURCE_VALUE); return FALSE; } if (func <= 5) { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_1 + func * 8); } else { hw_lock_control_reg = (MISC_REG_DRIVER_CONTROL_7 + (func - 6) * 8); } /* try to acquire the lock */ REG_WR(sc, hw_lock_control_reg + 4, resource_bit); lock_status = REG_RD(sc, hw_lock_control_reg); if (lock_status & resource_bit) { return TRUE; } PMD_DRV_LOG(NOTICE, "Failed to get a resource lock 0x%x", resource); return FALSE; } /* * Get the recovery leader resource id according to the engine this function * belongs to. Currently only only 2 engines is supported. */ static int bnx2x_get_leader_lock_resource(struct bnx2x_softc *sc) { if (SC_PATH(sc)) { return HW_LOCK_RESOURCE_RECOVERY_LEADER_1; } else { return HW_LOCK_RESOURCE_RECOVERY_LEADER_0; } } /* try to acquire a leader lock for current engine */ static uint8_t bnx2x_trylock_leader_lock(struct bnx2x_softc *sc) { return bnx2x_trylock_hw_lock(sc, bnx2x_get_leader_lock_resource(sc)); } static int bnx2x_release_leader_lock(struct bnx2x_softc *sc) { return bnx2x_release_hw_lock(sc, bnx2x_get_leader_lock_resource(sc)); } /* close gates #2, #3 and #4 */ static void bnx2x_set_234_gates(struct bnx2x_softc *sc, uint8_t close) { uint32_t val; /* gates #2 and #4a are closed/opened */ /* #4 */ REG_WR(sc, PXP_REG_HST_DISCARD_DOORBELLS, ! !close); /* #2 */ REG_WR(sc, PXP_REG_HST_DISCARD_INTERNAL_WRITES, ! !close); /* #3 */ if (CHIP_IS_E1x(sc)) { /* prevent interrupts from HC on both ports */ val = REG_RD(sc, HC_REG_CONFIG_1); if (close) REG_WR(sc, HC_REG_CONFIG_1, (val & ~(uint32_t) HC_CONFIG_1_REG_BLOCK_DISABLE_1)); else REG_WR(sc, HC_REG_CONFIG_1, (val | HC_CONFIG_1_REG_BLOCK_DISABLE_1)); val = REG_RD(sc, HC_REG_CONFIG_0); if (close) REG_WR(sc, HC_REG_CONFIG_0, (val & ~(uint32_t) HC_CONFIG_0_REG_BLOCK_DISABLE_0)); else REG_WR(sc, HC_REG_CONFIG_0, (val | HC_CONFIG_0_REG_BLOCK_DISABLE_0)); } else { /* Prevent incomming interrupts in IGU */ val = REG_RD(sc, IGU_REG_BLOCK_CONFIGURATION); if (close) REG_WR(sc, IGU_REG_BLOCK_CONFIGURATION, (val & ~(uint32_t) IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE)); else REG_WR(sc, IGU_REG_BLOCK_CONFIGURATION, (val | IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE)); } wmb(); } /* poll for pending writes bit, it should get cleared in no more than 1s */ static int bnx2x_er_poll_igu_vq(struct bnx2x_softc *sc) { uint32_t cnt = 1000; uint32_t pend_bits = 0; do { pend_bits = REG_RD(sc, IGU_REG_PENDING_BITS_STATUS); if (pend_bits == 0) { break; } DELAY(1000); } while (cnt-- > 0); if (cnt <= 0) { PMD_DRV_LOG(NOTICE, "Still pending IGU requests bits=0x%08x!", pend_bits); return -1; } return 0; } #define SHARED_MF_CLP_MAGIC 0x80000000 /* 'magic' bit */ static void bnx2x_clp_reset_prep(struct bnx2x_softc *sc, uint32_t * magic_val) { /* Do some magic... */ uint32_t val = MFCFG_RD(sc, shared_mf_config.clp_mb); *magic_val = val & SHARED_MF_CLP_MAGIC; MFCFG_WR(sc, shared_mf_config.clp_mb, val | SHARED_MF_CLP_MAGIC); } /* restore the value of the 'magic' bit */ static void bnx2x_clp_reset_done(struct bnx2x_softc *sc, uint32_t magic_val) { /* Restore the 'magic' bit value... */ uint32_t val = MFCFG_RD(sc, shared_mf_config.clp_mb); MFCFG_WR(sc, shared_mf_config.clp_mb, (val & (~SHARED_MF_CLP_MAGIC)) | magic_val); } /* prepare for MCP reset, takes care of CLP configurations */ static void bnx2x_reset_mcp_prep(struct bnx2x_softc *sc, uint32_t * magic_val) { uint32_t shmem; uint32_t validity_offset; /* set `magic' bit in order to save MF config */ bnx2x_clp_reset_prep(sc, magic_val); /* get shmem offset */ shmem = REG_RD(sc, MISC_REG_SHARED_MEM_ADDR); validity_offset = offsetof(struct shmem_region, validity_map[SC_PORT(sc)]); /* Clear validity map flags */ if (shmem > 0) { REG_WR(sc, shmem + validity_offset, 0); } } #define MCP_TIMEOUT 5000 /* 5 seconds (in ms) */ #define MCP_ONE_TIMEOUT 100 /* 100 ms */ static void bnx2x_mcp_wait_one(struct bnx2x_softc *sc) { /* special handling for emulation and FPGA (10 times longer) */ if (CHIP_REV_IS_SLOW(sc)) { DELAY((MCP_ONE_TIMEOUT * 10) * 1000); } else { DELAY((MCP_ONE_TIMEOUT) * 1000); } } /* initialize shmem_base and waits for validity signature to appear */ static int bnx2x_init_shmem(struct bnx2x_softc *sc) { int cnt = 0; uint32_t val = 0; do { sc->devinfo.shmem_base = sc->link_params.shmem_base = REG_RD(sc, MISC_REG_SHARED_MEM_ADDR); if (sc->devinfo.shmem_base) { val = SHMEM_RD(sc, validity_map[SC_PORT(sc)]); if (val & SHR_MEM_VALIDITY_MB) return 0; } bnx2x_mcp_wait_one(sc); } while (cnt++ < (MCP_TIMEOUT / MCP_ONE_TIMEOUT)); PMD_DRV_LOG(NOTICE, "BAD MCP validity signature"); return -1; } static int bnx2x_reset_mcp_comp(struct bnx2x_softc *sc, uint32_t magic_val) { int rc = bnx2x_init_shmem(sc); /* Restore the `magic' bit value */ bnx2x_clp_reset_done(sc, magic_val); return rc; } static void bnx2x_pxp_prep(struct bnx2x_softc *sc) { REG_WR(sc, PXP2_REG_RD_START_INIT, 0); REG_WR(sc, PXP2_REG_RQ_RBC_DONE, 0); wmb(); } /* * Reset the whole chip except for: * - PCIE core * - PCI Glue, PSWHST, PXP/PXP2 RF (all controlled by one reset bit) * - IGU * - MISC (including AEU) * - GRC * - RBCN, RBCP */ static void bnx2x_process_kill_chip_reset(struct bnx2x_softc *sc, uint8_t global) { uint32_t not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2; uint32_t global_bits2, stay_reset2; /* * Bits that have to be set in reset_mask2 if we want to reset 'global' * (per chip) blocks. */ global_bits2 = MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU | MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE; /* * Don't reset the following blocks. * Important: per port blocks (such as EMAC, BMAC, UMAC) can't be * reset, as in 4 port device they might still be owned * by the MCP (there is only one leader per path). */ not_reset_mask1 = MISC_REGISTERS_RESET_REG_1_RST_HC | MISC_REGISTERS_RESET_REG_1_RST_PXPV | MISC_REGISTERS_RESET_REG_1_RST_PXP; not_reset_mask2 = MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO | MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE | MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE | MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE | MISC_REGISTERS_RESET_REG_2_RST_RBCN | MISC_REGISTERS_RESET_REG_2_RST_GRC | MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE | MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B | MISC_REGISTERS_RESET_REG_2_RST_ATC | MISC_REGISTERS_RESET_REG_2_PGLC | MISC_REGISTERS_RESET_REG_2_RST_BMAC0 | MISC_REGISTERS_RESET_REG_2_RST_BMAC1 | MISC_REGISTERS_RESET_REG_2_RST_EMAC0 | MISC_REGISTERS_RESET_REG_2_RST_EMAC1 | MISC_REGISTERS_RESET_REG_2_UMAC0 | MISC_REGISTERS_RESET_REG_2_UMAC1; /* * Keep the following blocks in reset: * - all xxMACs are handled by the elink code. */ stay_reset2 = MISC_REGISTERS_RESET_REG_2_XMAC | MISC_REGISTERS_RESET_REG_2_XMAC_SOFT; /* Full reset masks according to the chip */ reset_mask1 = 0xffffffff; if (CHIP_IS_E1H(sc)) reset_mask2 = 0x1ffff; else if (CHIP_IS_E2(sc)) reset_mask2 = 0xfffff; else /* CHIP_IS_E3 */ reset_mask2 = 0x3ffffff; /* Don't reset global blocks unless we need to */ if (!global) reset_mask2 &= ~global_bits2; /* * In case of attention in the QM, we need to reset PXP * (MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR) before QM * because otherwise QM reset would release 'close the gates' shortly * before resetting the PXP, then the PSWRQ would send a write * request to PGLUE. Then when PXP is reset, PGLUE would try to * read the payload data from PSWWR, but PSWWR would not * respond. The write queue in PGLUE would stuck, dmae commands * would not return. Therefore it's important to reset the second * reset register (containing the * MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR bit) before the * first one (containing the MISC_REGISTERS_RESET_REG_1_RST_QM * bit). */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, reset_mask2 & (~not_reset_mask2)); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, reset_mask1 & (~not_reset_mask1)); mb(); wmb(); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, reset_mask2 & (~stay_reset2)); mb(); wmb(); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1); wmb(); } static int bnx2x_process_kill(struct bnx2x_softc *sc, uint8_t global) { int cnt = 1000; uint32_t val = 0; uint32_t sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2; uint32_t tags_63_32 = 0; /* Empty the Tetris buffer, wait for 1s */ do { sr_cnt = REG_RD(sc, PXP2_REG_RD_SR_CNT); blk_cnt = REG_RD(sc, PXP2_REG_RD_BLK_CNT); port_is_idle_0 = REG_RD(sc, PXP2_REG_RD_PORT_IS_IDLE_0); port_is_idle_1 = REG_RD(sc, PXP2_REG_RD_PORT_IS_IDLE_1); pgl_exp_rom2 = REG_RD(sc, PXP2_REG_PGL_EXP_ROM2); if (CHIP_IS_E3(sc)) { tags_63_32 = REG_RD(sc, PGLUE_B_REG_TAGS_63_32); } if ((sr_cnt == 0x7e) && (blk_cnt == 0xa0) && ((port_is_idle_0 & 0x1) == 0x1) && ((port_is_idle_1 & 0x1) == 0x1) && (pgl_exp_rom2 == 0xffffffff) && (!CHIP_IS_E3(sc) || (tags_63_32 == 0xffffffff))) break; DELAY(1000); } while (cnt-- > 0); if (cnt <= 0) { PMD_DRV_LOG(NOTICE, "ERROR: Tetris buffer didn't get empty or there " "are still outstanding read requests after 1s! " "sr_cnt=0x%08x, blk_cnt=0x%08x, port_is_idle_0=0x%08x, " "port_is_idle_1=0x%08x, pgl_exp_rom2=0x%08x", sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2); return -1; } mb(); /* Close gates #2, #3 and #4 */ bnx2x_set_234_gates(sc, TRUE); /* Poll for IGU VQs for 57712 and newer chips */ if (!CHIP_IS_E1x(sc) && bnx2x_er_poll_igu_vq(sc)) { return -1; } /* clear "unprepared" bit */ REG_WR(sc, MISC_REG_UNPREPARED, 0); mb(); /* Make sure all is written to the chip before the reset */ wmb(); /* * Wait for 1ms to empty GLUE and PCI-E core queues, * PSWHST, GRC and PSWRD Tetris buffer. */ DELAY(1000); /* Prepare to chip reset: */ /* MCP */ if (global) { bnx2x_reset_mcp_prep(sc, &val); } /* PXP */ bnx2x_pxp_prep(sc); mb(); /* reset the chip */ bnx2x_process_kill_chip_reset(sc, global); mb(); /* Recover after reset: */ /* MCP */ if (global && bnx2x_reset_mcp_comp(sc, val)) { return -1; } /* Open the gates #2, #3 and #4 */ bnx2x_set_234_gates(sc, FALSE); return 0; } static int bnx2x_leader_reset(struct bnx2x_softc *sc) { int rc = 0; uint8_t global = bnx2x_reset_is_global(sc); uint32_t load_code; /* * If not going to reset MCP, load "fake" driver to reset HW while * driver is owner of the HW. */ if (!global && !BNX2X_NOMCP(sc)) { load_code = bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_REQ, DRV_MSG_CODE_LOAD_REQ_WITH_LFA); if (!load_code) { PMD_DRV_LOG(NOTICE, "MCP response failure, aborting"); rc = -1; goto exit_leader_reset; } if ((load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) && (load_code != FW_MSG_CODE_DRV_LOAD_COMMON)) { PMD_DRV_LOG(NOTICE, "MCP unexpected response, aborting"); rc = -1; goto exit_leader_reset2; } load_code = bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_DONE, 0); if (!load_code) { PMD_DRV_LOG(NOTICE, "MCP response failure, aborting"); rc = -1; goto exit_leader_reset2; } } /* try to recover after the failure */ if (bnx2x_process_kill(sc, global)) { PMD_DRV_LOG(NOTICE, "Something bad occurred on engine %d!", SC_PATH(sc)); rc = -1; goto exit_leader_reset2; } /* * Clear the RESET_IN_PROGRESS and RESET_GLOBAL bits and update the driver * state. */ bnx2x_set_reset_done(sc); if (global) { bnx2x_clear_reset_global(sc); } exit_leader_reset2: /* unload "fake driver" if it was loaded */ if (!global &&!BNX2X_NOMCP(sc)) { bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_DONE, 0); } exit_leader_reset: sc->is_leader = 0; bnx2x_release_leader_lock(sc); mb(); return rc; } /* * prepare INIT transition, parameters configured: * - HC configuration * - Queue's CDU context */ static void bnx2x_pf_q_prep_init(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct ecore_queue_init_params *init_params) { uint8_t cos; int cxt_index, cxt_offset; bnx2x_set_bit(ECORE_Q_FLG_HC, &init_params->rx.flags); bnx2x_set_bit(ECORE_Q_FLG_HC, &init_params->tx.flags); bnx2x_set_bit(ECORE_Q_FLG_HC_EN, &init_params->rx.flags); bnx2x_set_bit(ECORE_Q_FLG_HC_EN, &init_params->tx.flags); /* HC rate */ init_params->rx.hc_rate = sc->hc_rx_ticks ? (1000000 / sc->hc_rx_ticks) : 0; init_params->tx.hc_rate = sc->hc_tx_ticks ? (1000000 / sc->hc_tx_ticks) : 0; /* FW SB ID */ init_params->rx.fw_sb_id = init_params->tx.fw_sb_id = fp->fw_sb_id; /* CQ index among the SB indices */ init_params->rx.sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS; init_params->tx.sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS; /* set maximum number of COSs supported by this queue */ init_params->max_cos = sc->max_cos; /* set the context pointers queue object */ for (cos = FIRST_TX_COS_INDEX; cos < init_params->max_cos; cos++) { cxt_index = fp->index / ILT_PAGE_CIDS; cxt_offset = fp->index - (cxt_index * ILT_PAGE_CIDS); init_params->cxts[cos] = &sc->context[cxt_index].vcxt[cxt_offset].eth; } } /* set flags that are common for the Tx-only and not normal connections */ static unsigned long bnx2x_get_common_flags(struct bnx2x_softc *sc, uint8_t zero_stats) { unsigned long flags = 0; /* PF driver will always initialize the Queue to an ACTIVE state */ bnx2x_set_bit(ECORE_Q_FLG_ACTIVE, &flags); /* * tx only connections collect statistics (on the same index as the * parent connection). The statistics are zeroed when the parent * connection is initialized. */ bnx2x_set_bit(ECORE_Q_FLG_STATS, &flags); if (zero_stats) { bnx2x_set_bit(ECORE_Q_FLG_ZERO_STATS, &flags); } /* * tx only connections can support tx-switching, though their * CoS-ness doesn't survive the loopback */ if (sc->flags & BNX2X_TX_SWITCHING) { bnx2x_set_bit(ECORE_Q_FLG_TX_SWITCH, &flags); } bnx2x_set_bit(ECORE_Q_FLG_PCSUM_ON_PKT, &flags); return flags; } static unsigned long bnx2x_get_q_flags(struct bnx2x_softc *sc, uint8_t leading) { unsigned long flags = 0; if (IS_MF_SD(sc)) { bnx2x_set_bit(ECORE_Q_FLG_OV, &flags); } if (leading) { bnx2x_set_bit(ECORE_Q_FLG_LEADING_RSS, &flags); bnx2x_set_bit(ECORE_Q_FLG_MCAST, &flags); } bnx2x_set_bit(ECORE_Q_FLG_VLAN, &flags); /* merge with common flags */ return flags | bnx2x_get_common_flags(sc, TRUE); } static void bnx2x_pf_q_prep_general(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct ecore_general_setup_params *gen_init, uint8_t cos) { gen_init->stat_id = bnx2x_stats_id(fp); gen_init->spcl_id = fp->cl_id; gen_init->mtu = sc->mtu; gen_init->cos = cos; } static void bnx2x_pf_rx_q_prep(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct rxq_pause_params *pause, struct ecore_rxq_setup_params *rxq_init) { struct bnx2x_rx_queue *rxq; rxq = sc->rx_queues[fp->index]; if (!rxq) { PMD_RX_LOG(ERR, "RX queue is NULL"); return; } /* pause */ pause->bd_th_lo = BD_TH_LO(sc); pause->bd_th_hi = BD_TH_HI(sc); pause->rcq_th_lo = RCQ_TH_LO(sc); pause->rcq_th_hi = RCQ_TH_HI(sc); /* validate rings have enough entries to cross high thresholds */ if (sc->dropless_fc && pause->bd_th_hi + FW_PREFETCH_CNT > sc->rx_ring_size) { PMD_DRV_LOG(WARNING, "rx bd ring threshold limit"); } if (sc->dropless_fc && pause->rcq_th_hi + FW_PREFETCH_CNT > USABLE_RCQ_ENTRIES(rxq)) { PMD_DRV_LOG(WARNING, "rcq ring threshold limit"); } pause->pri_map = 1; /* rxq setup */ rxq_init->dscr_map = (phys_addr_t)rxq->rx_ring_phys_addr; rxq_init->rcq_map = (phys_addr_t)rxq->cq_ring_phys_addr; rxq_init->rcq_np_map = (phys_addr_t)(rxq->cq_ring_phys_addr + BNX2X_PAGE_SIZE); /* * This should be a maximum number of data bytes that may be * placed on the BD (not including paddings). */ rxq_init->buf_sz = (fp->rx_buf_size - IP_HEADER_ALIGNMENT_PADDING); rxq_init->cl_qzone_id = fp->cl_qzone_id; rxq_init->rss_engine_id = SC_FUNC(sc); rxq_init->mcast_engine_id = SC_FUNC(sc); rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT; rxq_init->fw_sb_id = fp->fw_sb_id; rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS; /* * configure silent vlan removal * if multi function mode is afex, then mask default vlan */ if (IS_MF_AFEX(sc)) { rxq_init->silent_removal_value = sc->devinfo.mf_info.afex_def_vlan_tag; rxq_init->silent_removal_mask = EVL_VLID_MASK; } } static void bnx2x_pf_tx_q_prep(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct ecore_txq_setup_params *txq_init, uint8_t cos) { struct bnx2x_tx_queue *txq = fp->sc->tx_queues[fp->index]; if (!txq) { PMD_TX_LOG(ERR, "ERROR: TX queue is NULL"); return; } txq_init->dscr_map = (phys_addr_t)txq->tx_ring_phys_addr; txq_init->sb_cq_index = HC_INDEX_ETH_FIRST_TX_CQ_CONS + cos; txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW; txq_init->fw_sb_id = fp->fw_sb_id; /* * set the TSS leading client id for TX classfication to the * leading RSS client id */ txq_init->tss_leading_cl_id = BNX2X_FP(sc, 0, cl_id); } /* * This function performs 2 steps in a queue state machine: * 1) RESET->INIT * 2) INIT->SETUP */ static int bnx2x_setup_queue(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, uint8_t leading) { struct ecore_queue_state_params q_params = { NULL }; struct ecore_queue_setup_params *setup_params = &q_params.params.setup; int rc; PMD_DRV_LOG(DEBUG, "setting up queue %d", fp->index); bnx2x_ack_sb(sc, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_ENABLE, 0); q_params.q_obj = &BNX2X_SP_OBJ(sc, fp).q_obj; /* we want to wait for completion in this context */ bnx2x_set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); /* prepare the INIT parameters */ bnx2x_pf_q_prep_init(sc, fp, &q_params.params.init); /* Set the command */ q_params.cmd = ECORE_Q_CMD_INIT; /* Change the state to INIT */ rc = ecore_queue_state_change(sc, &q_params); if (rc) { PMD_DRV_LOG(NOTICE, "Queue(%d) INIT failed", fp->index); return rc; } PMD_DRV_LOG(DEBUG, "init complete"); /* now move the Queue to the SETUP state */ memset(setup_params, 0, sizeof(*setup_params)); /* set Queue flags */ setup_params->flags = bnx2x_get_q_flags(sc, leading); /* set general SETUP parameters */ bnx2x_pf_q_prep_general(sc, fp, &setup_params->gen_params, FIRST_TX_COS_INDEX); bnx2x_pf_rx_q_prep(sc, fp, &setup_params->pause_params, &setup_params->rxq_params); bnx2x_pf_tx_q_prep(sc, fp, &setup_params->txq_params, FIRST_TX_COS_INDEX); /* Set the command */ q_params.cmd = ECORE_Q_CMD_SETUP; /* change the state to SETUP */ rc = ecore_queue_state_change(sc, &q_params); if (rc) { PMD_DRV_LOG(NOTICE, "Queue(%d) SETUP failed", fp->index); return rc; } return rc; } static int bnx2x_setup_leading(struct bnx2x_softc *sc) { if (IS_PF(sc)) return bnx2x_setup_queue(sc, &sc->fp[0], TRUE); else /* VF */ return bnx2x_vf_setup_queue(sc, &sc->fp[0], TRUE); } static int bnx2x_config_rss_pf(struct bnx2x_softc *sc, struct ecore_rss_config_obj *rss_obj, uint8_t config_hash) { struct ecore_config_rss_params params = { NULL }; uint32_t i; /* * Although RSS is meaningless when there is a single HW queue we * still need it enabled in order to have HW Rx hash generated. */ params.rss_obj = rss_obj; bnx2x_set_bit(RAMROD_COMP_WAIT, ¶ms.ramrod_flags); bnx2x_set_bit(ECORE_RSS_MODE_REGULAR, ¶ms.rss_flags); /* RSS configuration */ bnx2x_set_bit(ECORE_RSS_IPV4, ¶ms.rss_flags); bnx2x_set_bit(ECORE_RSS_IPV4_TCP, ¶ms.rss_flags); bnx2x_set_bit(ECORE_RSS_IPV6, ¶ms.rss_flags); bnx2x_set_bit(ECORE_RSS_IPV6_TCP, ¶ms.rss_flags); if (rss_obj->udp_rss_v4) { bnx2x_set_bit(ECORE_RSS_IPV4_UDP, ¶ms.rss_flags); } if (rss_obj->udp_rss_v6) { bnx2x_set_bit(ECORE_RSS_IPV6_UDP, ¶ms.rss_flags); } /* Hash bits */ params.rss_result_mask = MULTI_MASK; (void)rte_memcpy(params.ind_table, rss_obj->ind_table, sizeof(params.ind_table)); if (config_hash) { /* RSS keys */ for (i = 0; i < sizeof(params.rss_key) / 4; i++) { params.rss_key[i] = (uint32_t) rte_rand(); } bnx2x_set_bit(ECORE_RSS_SET_SRCH, ¶ms.rss_flags); } if (IS_PF(sc)) return ecore_config_rss(sc, ¶ms); else return bnx2x_vf_config_rss(sc, ¶ms); } static int bnx2x_config_rss_eth(struct bnx2x_softc *sc, uint8_t config_hash) { return bnx2x_config_rss_pf(sc, &sc->rss_conf_obj, config_hash); } static int bnx2x_init_rss_pf(struct bnx2x_softc *sc) { uint8_t num_eth_queues = BNX2X_NUM_ETH_QUEUES(sc); uint32_t i; /* * Prepare the initial contents of the indirection table if * RSS is enabled */ for (i = 0; i < sizeof(sc->rss_conf_obj.ind_table); i++) { sc->rss_conf_obj.ind_table[i] = (sc->fp->cl_id + (i % num_eth_queues)); } if (sc->udp_rss) { sc->rss_conf_obj.udp_rss_v4 = sc->rss_conf_obj.udp_rss_v6 = 1; } /* * For 57711 SEARCHER configuration (rss_keys) is * per-port, so if explicit configuration is needed, do it only * for a PMF. * * For 57712 and newer it's a per-function configuration. */ return bnx2x_config_rss_eth(sc, sc->port.pmf || !CHIP_IS_E1x(sc)); } static int bnx2x_set_mac_one(struct bnx2x_softc *sc, uint8_t * mac, struct ecore_vlan_mac_obj *obj, uint8_t set, int mac_type, unsigned long *ramrod_flags) { struct ecore_vlan_mac_ramrod_params ramrod_param; int rc; memset(&ramrod_param, 0, sizeof(ramrod_param)); /* fill in general parameters */ ramrod_param.vlan_mac_obj = obj; ramrod_param.ramrod_flags = *ramrod_flags; /* fill a user request section if needed */ if (!bnx2x_test_bit(RAMROD_CONT, ramrod_flags)) { (void)rte_memcpy(ramrod_param.user_req.u.mac.mac, mac, ETH_ALEN); bnx2x_set_bit(mac_type, &ramrod_param.user_req.vlan_mac_flags); /* Set the command: ADD or DEL */ ramrod_param.user_req.cmd = (set) ? ECORE_VLAN_MAC_ADD : ECORE_VLAN_MAC_DEL; } rc = ecore_config_vlan_mac(sc, &ramrod_param); if (rc == ECORE_EXISTS) { PMD_DRV_LOG(INFO, "Failed to schedule ADD operations (EEXIST)"); /* do not treat adding same MAC as error */ rc = 0; } else if (rc < 0) { PMD_DRV_LOG(ERR, "%s MAC failed (%d)", (set ? "Set" : "Delete"), rc); } return rc; } static int bnx2x_set_eth_mac(struct bnx2x_softc *sc, uint8_t set) { unsigned long ramrod_flags = 0; PMD_DRV_LOG(DEBUG, "Adding Ethernet MAC"); bnx2x_set_bit(RAMROD_COMP_WAIT, &ramrod_flags); /* Eth MAC is set on RSS leading client (fp[0]) */ return bnx2x_set_mac_one(sc, sc->link_params.mac_addr, &sc->sp_objs->mac_obj, set, ECORE_ETH_MAC, &ramrod_flags); } static int bnx2x_get_cur_phy_idx(struct bnx2x_softc *sc) { uint32_t sel_phy_idx = 0; if (sc->link_params.num_phys <= 1) { return ELINK_INT_PHY; } if (sc->link_vars.link_up) { sel_phy_idx = ELINK_EXT_PHY1; /* In case link is SERDES, check if the ELINK_EXT_PHY2 is the one */ if ((sc->link_vars.link_status & LINK_STATUS_SERDES_LINK) && (sc->link_params.phy[ELINK_EXT_PHY2].supported & ELINK_SUPPORTED_FIBRE)) sel_phy_idx = ELINK_EXT_PHY2; } else { switch (elink_phy_selection(&sc->link_params)) { case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: sel_phy_idx = ELINK_EXT_PHY1; break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: sel_phy_idx = ELINK_EXT_PHY2; break; } } return sel_phy_idx; } static int bnx2x_get_link_cfg_idx(struct bnx2x_softc *sc) { uint32_t sel_phy_idx = bnx2x_get_cur_phy_idx(sc); /* * The selected activated PHY is always after swapping (in case PHY * swapping is enabled). So when swapping is enabled, we need to reverse * the configuration */ if (sc->link_params.multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED) { if (sel_phy_idx == ELINK_EXT_PHY1) sel_phy_idx = ELINK_EXT_PHY2; else if (sel_phy_idx == ELINK_EXT_PHY2) sel_phy_idx = ELINK_EXT_PHY1; } return ELINK_LINK_CONFIG_IDX(sel_phy_idx); } static void bnx2x_set_requested_fc(struct bnx2x_softc *sc) { /* * Initialize link parameters structure variables * It is recommended to turn off RX FC for jumbo frames * for better performance */ if (CHIP_IS_E1x(sc) && (sc->mtu > 5000)) { sc->link_params.req_fc_auto_adv = ELINK_FLOW_CTRL_TX; } else { sc->link_params.req_fc_auto_adv = ELINK_FLOW_CTRL_BOTH; } } static void bnx2x_calc_fc_adv(struct bnx2x_softc *sc) { uint8_t cfg_idx = bnx2x_get_link_cfg_idx(sc); switch (sc->link_vars.ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: default: sc->port.advertising[cfg_idx] &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause); break; case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH: sc->port.advertising[cfg_idx] |= (ADVERTISED_Asym_Pause | ADVERTISED_Pause); break; case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC: sc->port.advertising[cfg_idx] |= ADVERTISED_Asym_Pause; break; } } static uint16_t bnx2x_get_mf_speed(struct bnx2x_softc *sc) { uint16_t line_speed = sc->link_vars.line_speed; if (IS_MF(sc)) { uint16_t maxCfg = bnx2x_extract_max_cfg(sc, sc->devinfo. mf_info.mf_config[SC_VN (sc)]); /* calculate the current MAX line speed limit for the MF devices */ if (IS_MF_SI(sc)) { line_speed = (line_speed * maxCfg) / 100; } else { /* SD mode */ uint16_t vn_max_rate = maxCfg * 100; if (vn_max_rate < line_speed) { line_speed = vn_max_rate; } } } return line_speed; } static void bnx2x_fill_report_data(struct bnx2x_softc *sc, struct bnx2x_link_report_data *data) { uint16_t line_speed = bnx2x_get_mf_speed(sc); memset(data, 0, sizeof(*data)); /* fill the report data with the effective line speed */ data->line_speed = line_speed; /* Link is down */ if (!sc->link_vars.link_up || (sc->flags & BNX2X_MF_FUNC_DIS)) { bnx2x_set_bit(BNX2X_LINK_REPORT_LINK_DOWN, &data->link_report_flags); } /* Full DUPLEX */ if (sc->link_vars.duplex == DUPLEX_FULL) { bnx2x_set_bit(BNX2X_LINK_REPORT_FULL_DUPLEX, &data->link_report_flags); } /* Rx Flow Control is ON */ if (sc->link_vars.flow_ctrl & ELINK_FLOW_CTRL_RX) { bnx2x_set_bit(BNX2X_LINK_REPORT_RX_FC_ON, &data->link_report_flags); } /* Tx Flow Control is ON */ if (sc->link_vars.flow_ctrl & ELINK_FLOW_CTRL_TX) { bnx2x_set_bit(BNX2X_LINK_REPORT_TX_FC_ON, &data->link_report_flags); } } /* report link status to OS, should be called under phy_lock */ static void bnx2x_link_report(struct bnx2x_softc *sc) { struct bnx2x_link_report_data cur_data; /* reread mf_cfg */ if (IS_PF(sc)) { bnx2x_read_mf_cfg(sc); } /* Read the current link report info */ bnx2x_fill_report_data(sc, &cur_data); /* Don't report link down or exactly the same link status twice */ if (!memcmp(&cur_data, &sc->last_reported_link, sizeof(cur_data)) || (bnx2x_test_bit(BNX2X_LINK_REPORT_LINK_DOWN, &sc->last_reported_link.link_report_flags) && bnx2x_test_bit(BNX2X_LINK_REPORT_LINK_DOWN, &cur_data.link_report_flags))) { return; } sc->link_cnt++; /* report new link params and remember the state for the next time */ (void)rte_memcpy(&sc->last_reported_link, &cur_data, sizeof(cur_data)); if (bnx2x_test_bit(BNX2X_LINK_REPORT_LINK_DOWN, &cur_data.link_report_flags)) { PMD_DRV_LOG(INFO, "NIC Link is Down"); } else { __rte_unused const char *duplex; __rte_unused const char *flow; if (bnx2x_test_and_clear_bit(BNX2X_LINK_REPORT_FULL_DUPLEX, &cur_data.link_report_flags)) { duplex = "full"; } else { duplex = "half"; } /* * Handle the FC at the end so that only these flags would be * possibly set. This way we may easily check if there is no FC * enabled. */ if (cur_data.link_report_flags) { if (bnx2x_test_bit(BNX2X_LINK_REPORT_RX_FC_ON, &cur_data.link_report_flags) && bnx2x_test_bit(BNX2X_LINK_REPORT_TX_FC_ON, &cur_data.link_report_flags)) { flow = "ON - receive & transmit"; } else if (bnx2x_test_bit(BNX2X_LINK_REPORT_RX_FC_ON, &cur_data.link_report_flags) && !bnx2x_test_bit(BNX2X_LINK_REPORT_TX_FC_ON, &cur_data.link_report_flags)) { flow = "ON - receive"; } else if (!bnx2x_test_bit(BNX2X_LINK_REPORT_RX_FC_ON, &cur_data.link_report_flags) && bnx2x_test_bit(BNX2X_LINK_REPORT_TX_FC_ON, &cur_data.link_report_flags)) { flow = "ON - transmit"; } else { flow = "none"; /* possible? */ } } else { flow = "none"; } PMD_DRV_LOG(INFO, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s", cur_data.line_speed, duplex, flow); } } void bnx2x_link_status_update(struct bnx2x_softc *sc) { if (sc->state != BNX2X_STATE_OPEN) { return; } if (IS_PF(sc) && !CHIP_REV_IS_SLOW(sc)) { elink_link_status_update(&sc->link_params, &sc->link_vars); } else { sc->port.supported[0] |= (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_2500baseX_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); sc->port.advertising[0] = sc->port.supported[0]; sc->link_params.sc = sc; sc->link_params.port = SC_PORT(sc); sc->link_params.req_duplex[0] = DUPLEX_FULL; sc->link_params.req_flow_ctrl[0] = ELINK_FLOW_CTRL_NONE; sc->link_params.req_line_speed[0] = SPEED_10000; sc->link_params.speed_cap_mask[0] = 0x7f0000; sc->link_params.switch_cfg = ELINK_SWITCH_CFG_10G; if (CHIP_REV_IS_FPGA(sc)) { sc->link_vars.mac_type = ELINK_MAC_TYPE_EMAC; sc->link_vars.line_speed = ELINK_SPEED_1000; sc->link_vars.link_status = (LINK_STATUS_LINK_UP | LINK_STATUS_SPEED_AND_DUPLEX_1000TFD); } else { sc->link_vars.mac_type = ELINK_MAC_TYPE_BMAC; sc->link_vars.line_speed = ELINK_SPEED_10000; sc->link_vars.link_status = (LINK_STATUS_LINK_UP | LINK_STATUS_SPEED_AND_DUPLEX_10GTFD); } sc->link_vars.link_up = 1; sc->link_vars.duplex = DUPLEX_FULL; sc->link_vars.flow_ctrl = ELINK_FLOW_CTRL_NONE; if (IS_PF(sc)) { REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + sc->link_params.port * 4, 0); bnx2x_stats_handle(sc, STATS_EVENT_LINK_UP); bnx2x_link_report(sc); } } if (IS_PF(sc)) { if (sc->link_vars.link_up) { bnx2x_stats_handle(sc, STATS_EVENT_LINK_UP); } else { bnx2x_stats_handle(sc, STATS_EVENT_STOP); } bnx2x_link_report(sc); } else { bnx2x_link_report(sc); bnx2x_stats_handle(sc, STATS_EVENT_LINK_UP); } } static void bnx2x_periodic_start(struct bnx2x_softc *sc) { atomic_store_rel_long(&sc->periodic_flags, PERIODIC_GO); } static void bnx2x_periodic_stop(struct bnx2x_softc *sc) { atomic_store_rel_long(&sc->periodic_flags, PERIODIC_STOP); } static int bnx2x_initial_phy_init(struct bnx2x_softc *sc, int load_mode) { int rc, cfg_idx = bnx2x_get_link_cfg_idx(sc); uint16_t req_line_speed = sc->link_params.req_line_speed[cfg_idx]; struct elink_params *lp = &sc->link_params; bnx2x_set_requested_fc(sc); if (CHIP_REV_IS_SLOW(sc)) { uint32_t bond = CHIP_BOND_ID(sc); uint32_t feat = 0; if (CHIP_IS_E2(sc) && CHIP_IS_MODE_4_PORT(sc)) { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC; } else if (bond & 0x4) { if (CHIP_IS_E3(sc)) { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC; } else { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC; } } else if (bond & 0x8) { if (CHIP_IS_E3(sc)) { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_UMAC; } else { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC; } } /* disable EMAC for E3 and above */ if (bond & 0x2) { feat |= ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC; } sc->link_params.feature_config_flags |= feat; } if (load_mode == LOAD_DIAG) { lp->loopback_mode = ELINK_LOOPBACK_XGXS; /* Prefer doing PHY loopback at 10G speed, if possible */ if (lp->req_line_speed[cfg_idx] < ELINK_SPEED_10000) { if (lp->speed_cap_mask[cfg_idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { lp->req_line_speed[cfg_idx] = ELINK_SPEED_10000; } else { lp->req_line_speed[cfg_idx] = ELINK_SPEED_1000; } } } if (load_mode == LOAD_LOOPBACK_EXT) { lp->loopback_mode = ELINK_LOOPBACK_EXT; } rc = elink_phy_init(&sc->link_params, &sc->link_vars); bnx2x_calc_fc_adv(sc); if (sc->link_vars.link_up) { bnx2x_stats_handle(sc, STATS_EVENT_LINK_UP); bnx2x_link_report(sc); } if (!CHIP_REV_IS_SLOW(sc)) { bnx2x_periodic_start(sc); } sc->link_params.req_line_speed[cfg_idx] = req_line_speed; return rc; } /* update flags in shmem */ static void bnx2x_update_drv_flags(struct bnx2x_softc *sc, uint32_t flags, uint32_t set) { uint32_t drv_flags; if (SHMEM2_HAS(sc, drv_flags)) { bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_DRV_FLAGS); drv_flags = SHMEM2_RD(sc, drv_flags); if (set) { drv_flags |= flags; } else { drv_flags &= ~flags; } SHMEM2_WR(sc, drv_flags, drv_flags); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_DRV_FLAGS); } } /* periodic timer callout routine, only runs when the interface is up */ void bnx2x_periodic_callout(struct bnx2x_softc *sc) { if ((sc->state != BNX2X_STATE_OPEN) || (atomic_load_acq_long(&sc->periodic_flags) == PERIODIC_STOP)) { PMD_DRV_LOG(WARNING, "periodic callout exit (state=0x%x)", sc->state); return; } if (!CHIP_REV_IS_SLOW(sc)) { /* * This barrier is needed to ensure the ordering between the writing * to the sc->port.pmf in the bnx2x_nic_load() or bnx2x_pmf_update() and * the reading here. */ mb(); if (sc->port.pmf) { elink_period_func(&sc->link_params, &sc->link_vars); } } #ifdef BNX2X_PULSE if (IS_PF(sc) && !BNX2X_NOMCP(sc)) { int mb_idx = SC_FW_MB_IDX(sc); uint32_t drv_pulse; uint32_t mcp_pulse; ++sc->fw_drv_pulse_wr_seq; sc->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK; drv_pulse = sc->fw_drv_pulse_wr_seq; bnx2x_drv_pulse(sc); mcp_pulse = (SHMEM_RD(sc, func_mb[mb_idx].mcp_pulse_mb) & MCP_PULSE_SEQ_MASK); /* * The delta between driver pulse and mcp response should * be 1 (before mcp response) or 0 (after mcp response). */ if ((drv_pulse != mcp_pulse) && (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK))) { /* someone lost a heartbeat... */ PMD_DRV_LOG(ERR, "drv_pulse (0x%x) != mcp_pulse (0x%x)", drv_pulse, mcp_pulse); } } #endif } /* start the controller */ static __attribute__ ((noinline)) int bnx2x_nic_load(struct bnx2x_softc *sc) { uint32_t val; uint32_t load_code = 0; int i, rc = 0; PMD_INIT_FUNC_TRACE(); sc->state = BNX2X_STATE_OPENING_WAITING_LOAD; if (IS_PF(sc)) { /* must be called before memory allocation and HW init */ bnx2x_ilt_set_info(sc); } bnx2x_set_fp_rx_buf_size(sc); if (IS_PF(sc)) { if (bnx2x_alloc_mem(sc) != 0) { sc->state = BNX2X_STATE_CLOSED; rc = -ENOMEM; goto bnx2x_nic_load_error0; } } if (bnx2x_alloc_fw_stats_mem(sc) != 0) { sc->state = BNX2X_STATE_CLOSED; rc = -ENOMEM; goto bnx2x_nic_load_error0; } if (IS_VF(sc)) { rc = bnx2x_vf_init(sc); if (rc) { sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error0; } } if (IS_PF(sc)) { /* set pf load just before approaching the MCP */ bnx2x_set_pf_load(sc); /* if MCP exists send load request and analyze response */ if (!BNX2X_NOMCP(sc)) { /* attempt to load pf */ if (bnx2x_nic_load_request(sc, &load_code) != 0) { sc->state = BNX2X_STATE_CLOSED; rc = -ENXIO; goto bnx2x_nic_load_error1; } /* what did the MCP say? */ if (bnx2x_nic_load_analyze_req(sc, load_code) != 0) { bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_DONE, 0); sc->state = BNX2X_STATE_CLOSED; rc = -ENXIO; goto bnx2x_nic_load_error2; } } else { PMD_DRV_LOG(INFO, "Device has no MCP!"); load_code = bnx2x_nic_load_no_mcp(sc); } /* mark PMF if applicable */ bnx2x_nic_load_pmf(sc, load_code); /* Init Function state controlling object */ bnx2x_init_func_obj(sc); /* Initialize HW */ if (bnx2x_init_hw(sc, load_code) != 0) { PMD_DRV_LOG(NOTICE, "HW init failed"); bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_DONE, 0); sc->state = BNX2X_STATE_CLOSED; rc = -ENXIO; goto bnx2x_nic_load_error2; } } bnx2x_nic_init(sc, load_code); /* Init per-function objects */ if (IS_PF(sc)) { bnx2x_init_objs(sc); /* set AFEX default VLAN tag to an invalid value */ sc->devinfo.mf_info.afex_def_vlan_tag = -1; sc->state = BNX2X_STATE_OPENING_WAITING_PORT; rc = bnx2x_func_start(sc); if (rc) { PMD_DRV_LOG(NOTICE, "Function start failed!"); bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_DONE, 0); sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } /* send LOAD_DONE command to MCP */ if (!BNX2X_NOMCP(sc)) { load_code = bnx2x_fw_command(sc, DRV_MSG_CODE_LOAD_DONE, 0); if (!load_code) { PMD_DRV_LOG(NOTICE, "MCP response failure, aborting"); sc->state = BNX2X_STATE_ERROR; rc = -ENXIO; goto bnx2x_nic_load_error3; } } } rc = bnx2x_setup_leading(sc); if (rc) { PMD_DRV_LOG(NOTICE, "Setup leading failed!"); sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } FOR_EACH_NONDEFAULT_ETH_QUEUE(sc, i) { if (IS_PF(sc)) rc = bnx2x_setup_queue(sc, &sc->fp[i], FALSE); else /* IS_VF(sc) */ rc = bnx2x_vf_setup_queue(sc, &sc->fp[i], FALSE); if (rc) { PMD_DRV_LOG(NOTICE, "Queue(%d) setup failed", i); sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } } rc = bnx2x_init_rss_pf(sc); if (rc) { PMD_DRV_LOG(NOTICE, "PF RSS init failed"); sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } /* now when Clients are configured we are ready to work */ sc->state = BNX2X_STATE_OPEN; /* Configure a ucast MAC */ if (IS_PF(sc)) { rc = bnx2x_set_eth_mac(sc, TRUE); } else { /* IS_VF(sc) */ rc = bnx2x_vf_set_mac(sc, TRUE); } if (rc) { PMD_DRV_LOG(NOTICE, "Setting Ethernet MAC failed"); sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } if (sc->port.pmf) { rc = bnx2x_initial_phy_init(sc, LOAD_OPEN); if (rc) { sc->state = BNX2X_STATE_ERROR; goto bnx2x_nic_load_error3; } } sc->link_params.feature_config_flags &= ~ELINK_FEATURE_CONFIG_BOOT_FROM_SAN; /* start the Tx */ switch (LOAD_OPEN) { case LOAD_NORMAL: case LOAD_OPEN: break; case LOAD_DIAG: case LOAD_LOOPBACK_EXT: sc->state = BNX2X_STATE_DIAG; break; default: break; } if (sc->port.pmf) { bnx2x_update_drv_flags(sc, 1 << DRV_FLAGS_PORT_MASK, 0); } else { bnx2x_link_status_update(sc); } if (IS_PF(sc) && SHMEM2_HAS(sc, drv_capabilities_flag)) { /* mark driver is loaded in shmem2 */ val = SHMEM2_RD(sc, drv_capabilities_flag[SC_FW_MB_IDX(sc)]); SHMEM2_WR(sc, drv_capabilities_flag[SC_FW_MB_IDX(sc)], (val | DRV_FLAGS_CAPABILITIES_LOADED_SUPPORTED | DRV_FLAGS_CAPABILITIES_LOADED_L2)); } /* start fast path */ /* Initialize Rx filter */ bnx2x_set_rx_mode(sc); /* wait for all pending SP commands to complete */ if (IS_PF(sc) && !bnx2x_wait_sp_comp(sc, ~0x0UL)) { PMD_DRV_LOG(NOTICE, "Timeout waiting for all SPs to complete!"); bnx2x_periodic_stop(sc); bnx2x_nic_unload(sc, UNLOAD_CLOSE, FALSE); return -ENXIO; } PMD_DRV_LOG(DEBUG, "NIC successfully loaded"); return 0; bnx2x_nic_load_error3: if (IS_PF(sc)) { bnx2x_int_disable_sync(sc, 1); /* clean out queued objects */ bnx2x_squeeze_objects(sc); } bnx2x_nic_load_error2: if (IS_PF(sc) && !BNX2X_NOMCP(sc)) { bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_DONE, 0); } sc->port.pmf = 0; bnx2x_nic_load_error1: /* clear pf_load status, as it was already set */ if (IS_PF(sc)) { bnx2x_clear_pf_load(sc); } bnx2x_nic_load_error0: bnx2x_free_fw_stats_mem(sc); bnx2x_free_mem(sc); return rc; } /* * Handles controller initialization. */ int bnx2x_init(struct bnx2x_softc *sc) { int other_engine = SC_PATH(sc) ? 0 : 1; uint8_t other_load_status, load_status; uint8_t global = FALSE; int rc; /* Check if the driver is still running and bail out if it is. */ if (sc->link_vars.link_up) { PMD_DRV_LOG(DEBUG, "Init called while driver is running!"); rc = 0; goto bnx2x_init_done; } bnx2x_set_power_state(sc, PCI_PM_D0); /* * If parity occurred during the unload, then attentions and/or * RECOVERY_IN_PROGRESS may still be set. If so we want the first function * loaded on the current engine to complete the recovery. Parity recovery * is only relevant for PF driver. */ if (IS_PF(sc)) { other_load_status = bnx2x_get_load_status(sc, other_engine); load_status = bnx2x_get_load_status(sc, SC_PATH(sc)); if (!bnx2x_reset_is_done(sc, SC_PATH(sc)) || bnx2x_chk_parity_attn(sc, &global, TRUE)) { do { /* * If there are attentions and they are in global blocks, set * the GLOBAL_RESET bit regardless whether it will be this * function that will complete the recovery or not. */ if (global) { bnx2x_set_reset_global(sc); } /* * Only the first function on the current engine should try * to recover in open. In case of attentions in global blocks * only the first in the chip should try to recover. */ if ((!load_status && (!global ||!other_load_status)) && bnx2x_trylock_leader_lock(sc) && !bnx2x_leader_reset(sc)) { PMD_DRV_LOG(INFO, "Recovered during init"); break; } /* recovery has failed... */ bnx2x_set_power_state(sc, PCI_PM_D3hot); sc->recovery_state = BNX2X_RECOVERY_FAILED; PMD_DRV_LOG(NOTICE, "Recovery flow hasn't properly " "completed yet, try again later. " "If you still see this message after a " "few retries then power cycle is required."); rc = -ENXIO; goto bnx2x_init_done; } while (0); } } sc->recovery_state = BNX2X_RECOVERY_DONE; rc = bnx2x_nic_load(sc); bnx2x_init_done: if (rc) { PMD_DRV_LOG(NOTICE, "Initialization failed, " "stack notified driver is NOT running!"); } return rc; } static void bnx2x_get_function_num(struct bnx2x_softc *sc) { uint32_t val = 0; /* * Read the ME register to get the function number. The ME register * holds the relative-function number and absolute-function number. The * absolute-function number appears only in E2 and above. Before that * these bits always contained zero, therefore we cannot blindly use them. */ val = REG_RD(sc, BAR_ME_REGISTER); sc->pfunc_rel = (uint8_t) ((val & ME_REG_PF_NUM) >> ME_REG_PF_NUM_SHIFT); sc->path_id = (uint8_t) ((val & ME_REG_ABS_PF_NUM) >> ME_REG_ABS_PF_NUM_SHIFT) & 1; if (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) { sc->pfunc_abs = ((sc->pfunc_rel << 1) | sc->path_id); } else { sc->pfunc_abs = (sc->pfunc_rel | sc->path_id); } PMD_DRV_LOG(DEBUG, "Relative function %d, Absolute function %d, Path %d", sc->pfunc_rel, sc->pfunc_abs, sc->path_id); } static uint32_t bnx2x_get_shmem_mf_cfg_base(struct bnx2x_softc *sc) { uint32_t shmem2_size; uint32_t offset; uint32_t mf_cfg_offset_value; /* Non 57712 */ offset = (SHMEM_ADDR(sc, func_mb) + (MAX_FUNC_NUM * sizeof(struct drv_func_mb))); /* 57712 plus */ if (sc->devinfo.shmem2_base != 0) { shmem2_size = SHMEM2_RD(sc, size); if (shmem2_size > offsetof(struct shmem2_region, mf_cfg_addr)) { mf_cfg_offset_value = SHMEM2_RD(sc, mf_cfg_addr); if (SHMEM_MF_CFG_ADDR_NONE != mf_cfg_offset_value) { offset = mf_cfg_offset_value; } } } return offset; } static uint32_t bnx2x_pcie_capability_read(struct bnx2x_softc *sc, int reg) { uint32_t ret; struct bnx2x_pci_cap *caps; /* ensure PCIe capability is enabled */ caps = pci_find_cap(sc, PCIY_EXPRESS, BNX2X_PCI_CAP); if (NULL != caps) { PMD_DRV_LOG(DEBUG, "Found PCIe capability: " "id=0x%04X type=0x%04X addr=0x%08X", caps->id, caps->type, caps->addr); pci_read(sc, (caps->addr + reg), &ret, 2); return ret; } PMD_DRV_LOG(WARNING, "PCIe capability NOT FOUND!!!"); return 0; } static uint8_t bnx2x_is_pcie_pending(struct bnx2x_softc *sc) { return (bnx2x_pcie_capability_read(sc, PCIR_EXPRESS_DEVICE_STA) & PCIM_EXP_STA_TRANSACTION_PND); } /* * Walk the PCI capabiites list for the device to find what features are * supported. These capabilites may be enabled/disabled by firmware so it's * best to walk the list rather than make assumptions. */ static void bnx2x_probe_pci_caps(struct bnx2x_softc *sc) { PMD_INIT_FUNC_TRACE(); struct bnx2x_pci_cap *caps; uint16_t link_status; #ifdef RTE_LIBRTE_BNX2X_DEBUG int reg = 0; #endif /* check if PCI Power Management is enabled */ caps = pci_find_cap(sc, PCIY_PMG, BNX2X_PCI_CAP); if (NULL != caps) { PMD_DRV_LOG(DEBUG, "Found PM capability: " "id=0x%04X type=0x%04X addr=0x%08X", caps->id, caps->type, caps->addr); sc->devinfo.pcie_cap_flags |= BNX2X_PM_CAPABLE_FLAG; sc->devinfo.pcie_pm_cap_reg = caps->addr; } link_status = bnx2x_pcie_capability_read(sc, PCIR_EXPRESS_LINK_STA); sc->devinfo.pcie_link_speed = (link_status & PCIM_LINK_STA_SPEED); sc->devinfo.pcie_link_width = ((link_status & PCIM_LINK_STA_WIDTH) >> 4); PMD_DRV_LOG(DEBUG, "PCIe link speed=%d width=%d", sc->devinfo.pcie_link_speed, sc->devinfo.pcie_link_width); sc->devinfo.pcie_cap_flags |= BNX2X_PCIE_CAPABLE_FLAG; /* check if MSI capability is enabled */ caps = pci_find_cap(sc, PCIY_MSI, BNX2X_PCI_CAP); if (NULL != caps) { PMD_DRV_LOG(DEBUG, "Found MSI capability at 0x%04x", reg); sc->devinfo.pcie_cap_flags |= BNX2X_MSI_CAPABLE_FLAG; sc->devinfo.pcie_msi_cap_reg = caps->addr; } /* check if MSI-X capability is enabled */ caps = pci_find_cap(sc, PCIY_MSIX, BNX2X_PCI_CAP); if (NULL != caps) { PMD_DRV_LOG(DEBUG, "Found MSI-X capability at 0x%04x", reg); sc->devinfo.pcie_cap_flags |= BNX2X_MSIX_CAPABLE_FLAG; sc->devinfo.pcie_msix_cap_reg = caps->addr; } } static int bnx2x_get_shmem_mf_cfg_info_sd(struct bnx2x_softc *sc) { struct bnx2x_mf_info *mf_info = &sc->devinfo.mf_info; uint32_t val; /* get the outer vlan if we're in switch-dependent mode */ val = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].e1hov_tag); mf_info->ext_id = (uint16_t) val; mf_info->multi_vnics_mode = 1; if (!VALID_OVLAN(mf_info->ext_id)) { PMD_DRV_LOG(NOTICE, "Invalid VLAN (%d)", mf_info->ext_id); return 1; } /* get the capabilities */ if ((mf_info->mf_config[SC_VN(sc)] & FUNC_MF_CFG_PROTOCOL_MASK) == FUNC_MF_CFG_PROTOCOL_ISCSI) { mf_info->mf_protos_supported |= MF_PROTO_SUPPORT_ISCSI; } else if ((mf_info->mf_config[SC_VN(sc)] & FUNC_MF_CFG_PROTOCOL_MASK) == FUNC_MF_CFG_PROTOCOL_FCOE) { mf_info->mf_protos_supported |= MF_PROTO_SUPPORT_FCOE; } else { mf_info->mf_protos_supported |= MF_PROTO_SUPPORT_ETHERNET; } mf_info->vnics_per_port = (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) ? 2 : 4; return 0; } static uint32_t bnx2x_get_shmem_ext_proto_support_flags(struct bnx2x_softc *sc) { uint32_t retval = 0; uint32_t val; val = MFCFG_RD(sc, func_ext_config[SC_ABS_FUNC(sc)].func_cfg); if (val & MACP_FUNC_CFG_FLAGS_ENABLED) { if (val & MACP_FUNC_CFG_FLAGS_ETHERNET) { retval |= MF_PROTO_SUPPORT_ETHERNET; } if (val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) { retval |= MF_PROTO_SUPPORT_ISCSI; } if (val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) { retval |= MF_PROTO_SUPPORT_FCOE; } } return retval; } static int bnx2x_get_shmem_mf_cfg_info_si(struct bnx2x_softc *sc) { struct bnx2x_mf_info *mf_info = &sc->devinfo.mf_info; uint32_t val; /* * There is no outer vlan if we're in switch-independent mode. * If the mac is valid then assume multi-function. */ val = MFCFG_RD(sc, func_ext_config[SC_ABS_FUNC(sc)].func_cfg); mf_info->multi_vnics_mode = ((val & MACP_FUNC_CFG_FLAGS_MASK) != 0); mf_info->mf_protos_supported = bnx2x_get_shmem_ext_proto_support_flags(sc); mf_info->vnics_per_port = (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) ? 2 : 4; return 0; } static int bnx2x_get_shmem_mf_cfg_info_niv(struct bnx2x_softc *sc) { struct bnx2x_mf_info *mf_info = &sc->devinfo.mf_info; uint32_t e1hov_tag; uint32_t func_config; uint32_t niv_config; mf_info->multi_vnics_mode = 1; e1hov_tag = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].e1hov_tag); func_config = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].config); niv_config = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].afex_config); mf_info->ext_id = (uint16_t) ((e1hov_tag & FUNC_MF_CFG_E1HOV_TAG_MASK) >> FUNC_MF_CFG_E1HOV_TAG_SHIFT); mf_info->default_vlan = (uint16_t) ((e1hov_tag & FUNC_MF_CFG_AFEX_VLAN_MASK) >> FUNC_MF_CFG_AFEX_VLAN_SHIFT); mf_info->niv_allowed_priorities = (uint8_t) ((niv_config & FUNC_MF_CFG_AFEX_COS_FILTER_MASK) >> FUNC_MF_CFG_AFEX_COS_FILTER_SHIFT); mf_info->niv_default_cos = (uint8_t) ((func_config & FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK) >> FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT); mf_info->afex_vlan_mode = ((niv_config & FUNC_MF_CFG_AFEX_VLAN_MODE_MASK) >> FUNC_MF_CFG_AFEX_VLAN_MODE_SHIFT); mf_info->niv_mba_enabled = ((niv_config & FUNC_MF_CFG_AFEX_MBA_ENABLED_MASK) >> FUNC_MF_CFG_AFEX_MBA_ENABLED_SHIFT); mf_info->mf_protos_supported = bnx2x_get_shmem_ext_proto_support_flags(sc); mf_info->vnics_per_port = (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) ? 2 : 4; return 0; } static int bnx2x_check_valid_mf_cfg(struct bnx2x_softc *sc) { struct bnx2x_mf_info *mf_info = &sc->devinfo.mf_info; uint32_t mf_cfg1; uint32_t mf_cfg2; uint32_t ovlan1; uint32_t ovlan2; uint8_t i, j; /* various MF mode sanity checks... */ if (mf_info->mf_config[SC_VN(sc)] & FUNC_MF_CFG_FUNC_HIDE) { PMD_DRV_LOG(NOTICE, "Enumerated function %d is marked as hidden", SC_PORT(sc)); return 1; } if ((mf_info->vnics_per_port > 1) && !mf_info->multi_vnics_mode) { PMD_DRV_LOG(NOTICE, "vnics_per_port=%d multi_vnics_mode=%d", mf_info->vnics_per_port, mf_info->multi_vnics_mode); return 1; } if (mf_info->mf_mode == MULTI_FUNCTION_SD) { /* vnic id > 0 must have valid ovlan in switch-dependent mode */ if ((SC_VN(sc) > 0) && !VALID_OVLAN(OVLAN(sc))) { PMD_DRV_LOG(NOTICE, "mf_mode=SD vnic_id=%d ovlan=%d", SC_VN(sc), OVLAN(sc)); return 1; } if (!VALID_OVLAN(OVLAN(sc)) && mf_info->multi_vnics_mode) { PMD_DRV_LOG(NOTICE, "mf_mode=SD multi_vnics_mode=%d ovlan=%d", mf_info->multi_vnics_mode, OVLAN(sc)); return 1; } /* * Verify all functions are either MF or SF mode. If MF, make sure * sure that all non-hidden functions have a valid ovlan. If SF, * make sure that all non-hidden functions have an invalid ovlan. */ FOREACH_ABS_FUNC_IN_PORT(sc, i) { mf_cfg1 = MFCFG_RD(sc, func_mf_config[i].config); ovlan1 = MFCFG_RD(sc, func_mf_config[i].e1hov_tag); if (!(mf_cfg1 & FUNC_MF_CFG_FUNC_HIDE) && (((mf_info->multi_vnics_mode) && !VALID_OVLAN(ovlan1)) || ((!mf_info->multi_vnics_mode) && VALID_OVLAN(ovlan1)))) { PMD_DRV_LOG(NOTICE, "mf_mode=SD function %d MF config " "mismatch, multi_vnics_mode=%d ovlan=%d", i, mf_info->multi_vnics_mode, ovlan1); return 1; } } /* Verify all funcs on the same port each have a different ovlan. */ FOREACH_ABS_FUNC_IN_PORT(sc, i) { mf_cfg1 = MFCFG_RD(sc, func_mf_config[i].config); ovlan1 = MFCFG_RD(sc, func_mf_config[i].e1hov_tag); /* iterate from the next function on the port to the max func */ for (j = i + 2; j < MAX_FUNC_NUM; j += 2) { mf_cfg2 = MFCFG_RD(sc, func_mf_config[j].config); ovlan2 = MFCFG_RD(sc, func_mf_config[j].e1hov_tag); if (!(mf_cfg1 & FUNC_MF_CFG_FUNC_HIDE) && VALID_OVLAN(ovlan1) && !(mf_cfg2 & FUNC_MF_CFG_FUNC_HIDE) && VALID_OVLAN(ovlan2) && (ovlan1 == ovlan2)) { PMD_DRV_LOG(NOTICE, "mf_mode=SD functions %d and %d " "have the same ovlan (%d)", i, j, ovlan1); return 1; } } } } /* MULTI_FUNCTION_SD */ return 0; } static int bnx2x_get_mf_cfg_info(struct bnx2x_softc *sc) { struct bnx2x_mf_info *mf_info = &sc->devinfo.mf_info; uint32_t val, mac_upper; uint8_t i, vnic; /* initialize mf_info defaults */ mf_info->vnics_per_port = 1; mf_info->multi_vnics_mode = FALSE; mf_info->path_has_ovlan = FALSE; mf_info->mf_mode = SINGLE_FUNCTION; if (!CHIP_IS_MF_CAP(sc)) { return 0; } if (sc->devinfo.mf_cfg_base == SHMEM_MF_CFG_ADDR_NONE) { PMD_DRV_LOG(NOTICE, "Invalid mf_cfg_base!"); return 1; } /* get the MF mode (switch dependent / independent / single-function) */ val = SHMEM_RD(sc, dev_info.shared_feature_config.config); switch (val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) { case SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT: mac_upper = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].mac_upper); /* check for legal upper mac bytes */ if (mac_upper != FUNC_MF_CFG_UPPERMAC_DEFAULT) { mf_info->mf_mode = MULTI_FUNCTION_SI; } else { PMD_DRV_LOG(NOTICE, "Invalid config for Switch Independent mode"); } break; case SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED: case SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4: /* get outer vlan configuration */ val = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].e1hov_tag); if ((val & FUNC_MF_CFG_E1HOV_TAG_MASK) != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { mf_info->mf_mode = MULTI_FUNCTION_SD; } else { PMD_DRV_LOG(NOTICE, "Invalid config for Switch Dependent mode"); } break; case SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF: /* not in MF mode, vnics_per_port=1 and multi_vnics_mode=FALSE */ return 0; case SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE: /* * Mark MF mode as NIV if MCP version includes NPAR-SD support * and the MAC address is valid. */ mac_upper = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].mac_upper); if ((SHMEM2_HAS(sc, afex_driver_support)) && (mac_upper != FUNC_MF_CFG_UPPERMAC_DEFAULT)) { mf_info->mf_mode = MULTI_FUNCTION_AFEX; } else { PMD_DRV_LOG(NOTICE, "Invalid config for AFEX mode"); } break; default: PMD_DRV_LOG(NOTICE, "Unknown MF mode (0x%08x)", (val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK)); return 1; } /* set path mf_mode (which could be different than function mf_mode) */ if (mf_info->mf_mode == MULTI_FUNCTION_SD) { mf_info->path_has_ovlan = TRUE; } else if (mf_info->mf_mode == SINGLE_FUNCTION) { /* * Decide on path multi vnics mode. If we're not in MF mode and in * 4-port mode, this is good enough to check vnic-0 of the other port * on the same path */ if (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) { uint8_t other_port = !(PORT_ID(sc) & 1); uint8_t abs_func_other_port = (SC_PATH(sc) + (2 * other_port)); val = MFCFG_RD(sc, func_mf_config [abs_func_other_port].e1hov_tag); mf_info->path_has_ovlan = VALID_OVLAN((uint16_t) val); } } if (mf_info->mf_mode == SINGLE_FUNCTION) { /* invalid MF config */ if (SC_VN(sc) >= 1) { PMD_DRV_LOG(NOTICE, "VNIC ID >= 1 in SF mode"); return 1; } return 0; } /* get the MF configuration */ mf_info->mf_config[SC_VN(sc)] = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].config); switch (mf_info->mf_mode) { case MULTI_FUNCTION_SD: bnx2x_get_shmem_mf_cfg_info_sd(sc); break; case MULTI_FUNCTION_SI: bnx2x_get_shmem_mf_cfg_info_si(sc); break; case MULTI_FUNCTION_AFEX: bnx2x_get_shmem_mf_cfg_info_niv(sc); break; default: PMD_DRV_LOG(NOTICE, "Get MF config failed (mf_mode=0x%08x)", mf_info->mf_mode); return 1; } /* get the congestion management parameters */ vnic = 0; FOREACH_ABS_FUNC_IN_PORT(sc, i) { /* get min/max bw */ val = MFCFG_RD(sc, func_mf_config[i].config); mf_info->min_bw[vnic] = ((val & FUNC_MF_CFG_MIN_BW_MASK) >> FUNC_MF_CFG_MIN_BW_SHIFT); mf_info->max_bw[vnic] = ((val & FUNC_MF_CFG_MAX_BW_MASK) >> FUNC_MF_CFG_MAX_BW_SHIFT); vnic++; } return bnx2x_check_valid_mf_cfg(sc); } static int bnx2x_get_shmem_info(struct bnx2x_softc *sc) { int port; uint32_t mac_hi, mac_lo, val; PMD_INIT_FUNC_TRACE(); port = SC_PORT(sc); mac_hi = mac_lo = 0; sc->link_params.sc = sc; sc->link_params.port = port; /* get the hardware config info */ sc->devinfo.hw_config = SHMEM_RD(sc, dev_info.shared_hw_config.config); sc->devinfo.hw_config2 = SHMEM_RD(sc, dev_info.shared_hw_config.config2); sc->link_params.hw_led_mode = ((sc->devinfo.hw_config & SHARED_HW_CFG_LED_MODE_MASK) >> SHARED_HW_CFG_LED_MODE_SHIFT); /* get the port feature config */ sc->port.config = SHMEM_RD(sc, dev_info.port_feature_config[port].config); /* get the link params */ sc->link_params.speed_cap_mask[ELINK_INT_PHY] = SHMEM_RD(sc, dev_info.port_hw_config[port].speed_capability_mask) & PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK; sc->link_params.speed_cap_mask[ELINK_EXT_PHY1] = SHMEM_RD(sc, dev_info.port_hw_config[port].speed_capability_mask2) & PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK; /* get the lane config */ sc->link_params.lane_config = SHMEM_RD(sc, dev_info.port_hw_config[port].lane_config); /* get the link config */ val = SHMEM_RD(sc, dev_info.port_feature_config[port].link_config); sc->port.link_config[ELINK_INT_PHY] = val; sc->link_params.switch_cfg = (val & PORT_FEATURE_CONNECTED_SWITCH_MASK); sc->port.link_config[ELINK_EXT_PHY1] = SHMEM_RD(sc, dev_info.port_feature_config[port].link_config2); /* get the override preemphasis flag and enable it or turn it off */ val = SHMEM_RD(sc, dev_info.shared_feature_config.config); if (val & SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED) { sc->link_params.feature_config_flags |= ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED; } else { sc->link_params.feature_config_flags &= ~ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED; } /* get the initial value of the link params */ sc->link_params.multi_phy_config = SHMEM_RD(sc, dev_info.port_hw_config[port].multi_phy_config); /* get external phy info */ sc->port.ext_phy_config = SHMEM_RD(sc, dev_info.port_hw_config[port].external_phy_config); /* get the multifunction configuration */ bnx2x_get_mf_cfg_info(sc); /* get the mac address */ if (IS_MF(sc)) { mac_hi = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].mac_upper); mac_lo = MFCFG_RD(sc, func_mf_config[SC_ABS_FUNC(sc)].mac_lower); } else { mac_hi = SHMEM_RD(sc, dev_info.port_hw_config[port].mac_upper); mac_lo = SHMEM_RD(sc, dev_info.port_hw_config[port].mac_lower); } if ((mac_lo == 0) && (mac_hi == 0)) { *sc->mac_addr_str = 0; PMD_DRV_LOG(NOTICE, "No Ethernet address programmed!"); } else { sc->link_params.mac_addr[0] = (uint8_t) (mac_hi >> 8); sc->link_params.mac_addr[1] = (uint8_t) (mac_hi); sc->link_params.mac_addr[2] = (uint8_t) (mac_lo >> 24); sc->link_params.mac_addr[3] = (uint8_t) (mac_lo >> 16); sc->link_params.mac_addr[4] = (uint8_t) (mac_lo >> 8); sc->link_params.mac_addr[5] = (uint8_t) (mac_lo); snprintf(sc->mac_addr_str, sizeof(sc->mac_addr_str), "%02x:%02x:%02x:%02x:%02x:%02x", sc->link_params.mac_addr[0], sc->link_params.mac_addr[1], sc->link_params.mac_addr[2], sc->link_params.mac_addr[3], sc->link_params.mac_addr[4], sc->link_params.mac_addr[5]); PMD_DRV_LOG(DEBUG, "Ethernet address: %s", sc->mac_addr_str); } return 0; } static void bnx2x_media_detect(struct bnx2x_softc *sc) { uint32_t phy_idx = bnx2x_get_cur_phy_idx(sc); switch (sc->link_params.phy[phy_idx].media_type) { case ELINK_ETH_PHY_SFPP_10G_FIBER: case ELINK_ETH_PHY_SFP_1G_FIBER: case ELINK_ETH_PHY_XFP_FIBER: case ELINK_ETH_PHY_KR: case ELINK_ETH_PHY_CX4: PMD_DRV_LOG(INFO, "Found 10GBase-CX4 media."); sc->media = IFM_10G_CX4; break; case ELINK_ETH_PHY_DA_TWINAX: PMD_DRV_LOG(INFO, "Found 10Gb Twinax media."); sc->media = IFM_10G_TWINAX; break; case ELINK_ETH_PHY_BASE_T: PMD_DRV_LOG(INFO, "Found 10GBase-T media."); sc->media = IFM_10G_T; break; case ELINK_ETH_PHY_NOT_PRESENT: PMD_DRV_LOG(INFO, "Media not present."); sc->media = 0; break; case ELINK_ETH_PHY_UNSPECIFIED: default: PMD_DRV_LOG(INFO, "Unknown media!"); sc->media = 0; break; } } #define GET_FIELD(value, fname) \ (((value) & (fname##_MASK)) >> (fname##_SHIFT)) #define IGU_FID(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID) #define IGU_VEC(val) GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR) static int bnx2x_get_igu_cam_info(struct bnx2x_softc *sc) { int pfid = SC_FUNC(sc); int igu_sb_id; uint32_t val; uint8_t fid, igu_sb_cnt = 0; sc->igu_base_sb = 0xff; if (CHIP_INT_MODE_IS_BC(sc)) { int vn = SC_VN(sc); igu_sb_cnt = sc->igu_sb_cnt; sc->igu_base_sb = ((CHIP_IS_MODE_4_PORT(sc) ? pfid : vn) * FP_SB_MAX_E1x); sc->igu_dsb_id = (E1HVN_MAX * FP_SB_MAX_E1x + (CHIP_IS_MODE_4_PORT(sc) ? pfid : vn)); return 0; } /* IGU in normal mode - read CAM */ for (igu_sb_id = 0; igu_sb_id < IGU_REG_MAPPING_MEMORY_SIZE; igu_sb_id++) { val = REG_RD(sc, IGU_REG_MAPPING_MEMORY + igu_sb_id * 4); if (!(val & IGU_REG_MAPPING_MEMORY_VALID)) { continue; } fid = IGU_FID(val); if ((fid & IGU_FID_ENCODE_IS_PF)) { if ((fid & IGU_FID_PF_NUM_MASK) != pfid) { continue; } if (IGU_VEC(val) == 0) { /* default status block */ sc->igu_dsb_id = igu_sb_id; } else { if (sc->igu_base_sb == 0xff) { sc->igu_base_sb = igu_sb_id; } igu_sb_cnt++; } } } /* * Due to new PF resource allocation by MFW T7.4 and above, it's optional * that number of CAM entries will not be equal to the value advertised in * PCI. Driver should use the minimal value of both as the actual status * block count */ sc->igu_sb_cnt = min(sc->igu_sb_cnt, igu_sb_cnt); if (igu_sb_cnt == 0) { PMD_DRV_LOG(ERR, "CAM configuration error"); return -1; } return 0; } /* * Gather various information from the device config space, the device itself, * shmem, and the user input. */ static int bnx2x_get_device_info(struct bnx2x_softc *sc) { uint32_t val; int rc; /* get the chip revision (chip metal comes from pci config space) */ sc->devinfo.chip_id = sc->link_params.chip_id = (((REG_RD(sc, MISC_REG_CHIP_NUM) & 0xffff) << 16) | ((REG_RD(sc, MISC_REG_CHIP_REV) & 0xf) << 12) | (((REG_RD(sc, PCICFG_OFFSET + PCI_ID_VAL3) >> 24) & 0xf) << 4) | ((REG_RD(sc, MISC_REG_BOND_ID) & 0xf) << 0)); /* force 57811 according to MISC register */ if (REG_RD(sc, MISC_REG_CHIP_TYPE) & MISC_REG_CHIP_TYPE_57811_MASK) { if (CHIP_IS_57810(sc)) { sc->devinfo.chip_id = ((CHIP_NUM_57811 << 16) | (sc-> devinfo.chip_id & 0x0000ffff)); } else if (CHIP_IS_57810_MF(sc)) { sc->devinfo.chip_id = ((CHIP_NUM_57811_MF << 16) | (sc-> devinfo.chip_id & 0x0000ffff)); } sc->devinfo.chip_id |= 0x1; } PMD_DRV_LOG(DEBUG, "chip_id=0x%08x (num=0x%04x rev=0x%01x metal=0x%02x bond=0x%01x)", sc->devinfo.chip_id, ((sc->devinfo.chip_id >> 16) & 0xffff), ((sc->devinfo.chip_id >> 12) & 0xf), ((sc->devinfo.chip_id >> 4) & 0xff), ((sc->devinfo.chip_id >> 0) & 0xf)); val = (REG_RD(sc, 0x2874) & 0x55); if ((sc->devinfo.chip_id & 0x1) || (CHIP_IS_E1H(sc) && (val == 0x55))) { sc->flags |= BNX2X_ONE_PORT_FLAG; PMD_DRV_LOG(DEBUG, "single port device"); } /* set the doorbell size */ sc->doorbell_size = (1 << BNX2X_DB_SHIFT); /* determine whether the device is in 2 port or 4 port mode */ sc->devinfo.chip_port_mode = CHIP_PORT_MODE_NONE; /* E1h */ if (CHIP_IS_E2E3(sc)) { /* * Read port4mode_en_ovwr[0]: * If 1, four port mode is in port4mode_en_ovwr[1]. * If 0, four port mode is in port4mode_en[0]. */ val = REG_RD(sc, MISC_REG_PORT4MODE_EN_OVWR); if (val & 1) { val = ((val >> 1) & 1); } else { val = REG_RD(sc, MISC_REG_PORT4MODE_EN); } sc->devinfo.chip_port_mode = (val) ? CHIP_4_PORT_MODE : CHIP_2_PORT_MODE; PMD_DRV_LOG(DEBUG, "Port mode = %s", (val) ? "4" : "2"); } /* get the function and path info for the device */ bnx2x_get_function_num(sc); /* get the shared memory base address */ sc->devinfo.shmem_base = sc->link_params.shmem_base = REG_RD(sc, MISC_REG_SHARED_MEM_ADDR); sc->devinfo.shmem2_base = REG_RD(sc, (SC_PATH(sc) ? MISC_REG_GENERIC_CR_1 : MISC_REG_GENERIC_CR_0)); if (!sc->devinfo.shmem_base) { /* this should ONLY prevent upcoming shmem reads */ PMD_DRV_LOG(INFO, "MCP not active"); sc->flags |= BNX2X_NO_MCP_FLAG; return 0; } /* make sure the shared memory contents are valid */ val = SHMEM_RD(sc, validity_map[SC_PORT(sc)]); if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) { PMD_DRV_LOG(NOTICE, "Invalid SHMEM validity signature: 0x%08x", val); return 0; } /* get the bootcode version */ sc->devinfo.bc_ver = SHMEM_RD(sc, dev_info.bc_rev); snprintf(sc->devinfo.bc_ver_str, sizeof(sc->devinfo.bc_ver_str), "%d.%d.%d", ((sc->devinfo.bc_ver >> 24) & 0xff), ((sc->devinfo.bc_ver >> 16) & 0xff), ((sc->devinfo.bc_ver >> 8) & 0xff)); PMD_DRV_LOG(INFO, "Bootcode version: %s", sc->devinfo.bc_ver_str); /* get the bootcode shmem address */ sc->devinfo.mf_cfg_base = bnx2x_get_shmem_mf_cfg_base(sc); /* clean indirect addresses as they're not used */ pci_write_long(sc, PCICFG_GRC_ADDRESS, 0); if (IS_PF(sc)) { REG_WR(sc, PXP2_REG_PGL_ADDR_88_F0, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_8C_F0, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_90_F0, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_94_F0, 0); if (CHIP_IS_E1x(sc)) { REG_WR(sc, PXP2_REG_PGL_ADDR_88_F1, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_8C_F1, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_90_F1, 0); REG_WR(sc, PXP2_REG_PGL_ADDR_94_F1, 0); } /* * Enable internal target-read (in case we are probed after PF * FLR). Must be done prior to any BAR read access. Only for * 57712 and up */ if (!CHIP_IS_E1x(sc)) { REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); } } /* get the nvram size */ val = REG_RD(sc, MCP_REG_MCPR_NVM_CFG4); sc->devinfo.flash_size = (NVRAM_1MB_SIZE << (val & MCPR_NVM_CFG4_FLASH_SIZE)); bnx2x_set_power_state(sc, PCI_PM_D0); /* get various configuration parameters from shmem */ bnx2x_get_shmem_info(sc); /* initialize IGU parameters */ if (CHIP_IS_E1x(sc)) { sc->devinfo.int_block = INT_BLOCK_HC; sc->igu_dsb_id = DEF_SB_IGU_ID; sc->igu_base_sb = 0; } else { sc->devinfo.int_block = INT_BLOCK_IGU; /* do not allow device reset during IGU info preocessing */ bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RESET); val = REG_RD(sc, IGU_REG_BLOCK_CONFIGURATION); if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) { int tout = 5000; val &= ~(IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN); REG_WR(sc, IGU_REG_BLOCK_CONFIGURATION, val); REG_WR(sc, IGU_REG_RESET_MEMORIES, 0x7f); while (tout && REG_RD(sc, IGU_REG_RESET_MEMORIES)) { tout--; DELAY(1000); } if (REG_RD(sc, IGU_REG_RESET_MEMORIES)) { PMD_DRV_LOG(NOTICE, "FORCING IGU Normal Mode failed!!!"); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RESET); return -1; } } if (val & IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN) { PMD_DRV_LOG(DEBUG, "IGU Backward Compatible Mode"); sc->devinfo.int_block |= INT_BLOCK_MODE_BW_COMP; } else { PMD_DRV_LOG(DEBUG, "IGU Normal Mode"); } rc = bnx2x_get_igu_cam_info(sc); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RESET); if (rc) { return rc; } } /* * Get base FW non-default (fast path) status block ID. This value is * used to initialize the fw_sb_id saved on the fp/queue structure to * determine the id used by the FW. */ if (CHIP_IS_E1x(sc)) { sc->base_fw_ndsb = ((SC_PORT(sc) * FP_SB_MAX_E1x) + SC_L_ID(sc)); } else { /* * 57712+ - We currently use one FW SB per IGU SB (Rx and Tx of * the same queue are indicated on the same IGU SB). So we prefer * FW and IGU SBs to be the same value. */ sc->base_fw_ndsb = sc->igu_base_sb; } elink_phy_probe(&sc->link_params); return 0; } static void bnx2x_link_settings_supported(struct bnx2x_softc *sc, uint32_t switch_cfg) { uint32_t cfg_size = 0; uint32_t idx; uint8_t port = SC_PORT(sc); /* aggregation of supported attributes of all external phys */ sc->port.supported[0] = 0; sc->port.supported[1] = 0; switch (sc->link_params.num_phys) { case 1: sc->port.supported[0] = sc->link_params.phy[ELINK_INT_PHY].supported; cfg_size = 1; break; case 2: sc->port.supported[0] = sc->link_params.phy[ELINK_EXT_PHY1].supported; cfg_size = 1; break; case 3: if (sc->link_params.multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED) { sc->port.supported[1] = sc->link_params.phy[ELINK_EXT_PHY1].supported; sc->port.supported[0] = sc->link_params.phy[ELINK_EXT_PHY2].supported; } else { sc->port.supported[0] = sc->link_params.phy[ELINK_EXT_PHY1].supported; sc->port.supported[1] = sc->link_params.phy[ELINK_EXT_PHY2].supported; } cfg_size = 2; break; } if (!(sc->port.supported[0] || sc->port.supported[1])) { PMD_DRV_LOG(ERR, "Invalid phy config in NVRAM (PHY1=0x%08x PHY2=0x%08x)", SHMEM_RD(sc, dev_info.port_hw_config [port].external_phy_config), SHMEM_RD(sc, dev_info.port_hw_config [port].external_phy_config2)); return; } if (CHIP_IS_E3(sc)) sc->port.phy_addr = REG_RD(sc, MISC_REG_WC0_CTRL_PHY_ADDR); else { switch (switch_cfg) { case ELINK_SWITCH_CFG_1G: sc->port.phy_addr = REG_RD(sc, NIG_REG_SERDES0_CTRL_PHY_ADDR + port * 0x10); break; case ELINK_SWITCH_CFG_10G: sc->port.phy_addr = REG_RD(sc, NIG_REG_XGXS0_CTRL_PHY_ADDR + port * 0x18); break; default: PMD_DRV_LOG(ERR, "Invalid switch config in" "link_config=0x%08x", sc->port.link_config[0]); return; } } PMD_DRV_LOG(INFO, "PHY addr 0x%08x", sc->port.phy_addr); /* mask what we support according to speed_cap_mask per configuration */ for (idx = 0; idx < cfg_size; idx++) { if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_10baseT_Half; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_10baseT_Full; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_100baseT_Half; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_100baseT_Full; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_1000baseT_Full; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_2500baseX_Full; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_10000baseT_Full; } if (!(sc->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) { sc->port.supported[idx] &= ~ELINK_SUPPORTED_20000baseKR2_Full; } } PMD_DRV_LOG(INFO, "PHY supported 0=0x%08x 1=0x%08x", sc->port.supported[0], sc->port.supported[1]); } static void bnx2x_link_settings_requested(struct bnx2x_softc *sc) { uint32_t link_config; uint32_t idx; uint32_t cfg_size = 0; sc->port.advertising[0] = 0; sc->port.advertising[1] = 0; switch (sc->link_params.num_phys) { case 1: case 2: cfg_size = 1; break; case 3: cfg_size = 2; break; } for (idx = 0; idx < cfg_size; idx++) { sc->link_params.req_duplex[idx] = DUPLEX_FULL; link_config = sc->port.link_config[idx]; switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { case PORT_FEATURE_LINK_SPEED_AUTO: if (sc->port.supported[idx] & ELINK_SUPPORTED_Autoneg) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_AUTO_NEG; sc->port.advertising[idx] |= sc->port.supported[idx]; if (sc->link_params.phy[ELINK_EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) sc->port.advertising[idx] |= (ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full); } else { /* force 10G, no AN */ sc->link_params.req_line_speed[idx] = ELINK_SPEED_10000; sc->port.advertising[idx] |= (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); continue; } break; case PORT_FEATURE_LINK_SPEED_10M_FULL: if (sc-> port.supported[idx] & ELINK_SUPPORTED_10baseT_Full) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_10; sc->port.advertising[idx] |= (ADVERTISED_10baseT_Full | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_10M_HALF: if (sc-> port.supported[idx] & ELINK_SUPPORTED_10baseT_Half) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_10; sc->link_params.req_duplex[idx] = DUPLEX_HALF; sc->port.advertising[idx] |= (ADVERTISED_10baseT_Half | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_100M_FULL: if (sc-> port.supported[idx] & ELINK_SUPPORTED_100baseT_Full) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_100; sc->port.advertising[idx] |= (ADVERTISED_100baseT_Full | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_100M_HALF: if (sc-> port.supported[idx] & ELINK_SUPPORTED_100baseT_Half) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_100; sc->link_params.req_duplex[idx] = DUPLEX_HALF; sc->port.advertising[idx] |= (ADVERTISED_100baseT_Half | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_1G: if (sc->port.supported[idx] & ELINK_SUPPORTED_1000baseT_Full) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_1000; sc->port.advertising[idx] |= (ADVERTISED_1000baseT_Full | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_2_5G: if (sc->port.supported[idx] & ELINK_SUPPORTED_2500baseX_Full) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_2500; sc->port.advertising[idx] |= (ADVERTISED_2500baseX_Full | ADVERTISED_TP); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_10G_CX4: if (sc->port.supported[idx] & ELINK_SUPPORTED_10000baseT_Full) { sc->link_params.req_line_speed[idx] = ELINK_SPEED_10000; sc->port.advertising[idx] |= (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); } else { PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc-> link_params.speed_cap_mask[idx]); return; } break; case PORT_FEATURE_LINK_SPEED_20G: sc->link_params.req_line_speed[idx] = ELINK_SPEED_20000; break; default: PMD_DRV_LOG(ERR, "Invalid NVRAM config link_config=0x%08x " "speed_cap_mask=0x%08x", link_config, sc->link_params.speed_cap_mask[idx]); sc->link_params.req_line_speed[idx] = ELINK_SPEED_AUTO_NEG; sc->port.advertising[idx] = sc->port.supported[idx]; break; } sc->link_params.req_flow_ctrl[idx] = (link_config & PORT_FEATURE_FLOW_CONTROL_MASK); if (sc->link_params.req_flow_ctrl[idx] == ELINK_FLOW_CTRL_AUTO) { if (! (sc-> port.supported[idx] & ELINK_SUPPORTED_Autoneg)) { sc->link_params.req_flow_ctrl[idx] = ELINK_FLOW_CTRL_NONE; } else { bnx2x_set_requested_fc(sc); } } } } static void bnx2x_get_phy_info(struct bnx2x_softc *sc) { uint8_t port = SC_PORT(sc); uint32_t eee_mode; PMD_INIT_FUNC_TRACE(); /* shmem data already read in bnx2x_get_shmem_info() */ bnx2x_link_settings_supported(sc, sc->link_params.switch_cfg); bnx2x_link_settings_requested(sc); /* configure link feature according to nvram value */ eee_mode = (((SHMEM_RD(sc, dev_info.port_feature_config[port].eee_power_mode)) & PORT_FEAT_CFG_EEE_POWER_MODE_MASK) >> PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT); if (eee_mode != PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED) { sc->link_params.eee_mode = (ELINK_EEE_MODE_ADV_LPI | ELINK_EEE_MODE_ENABLE_LPI | ELINK_EEE_MODE_OUTPUT_TIME); } else { sc->link_params.eee_mode = 0; } /* get the media type */ bnx2x_media_detect(sc); } static void bnx2x_set_modes_bitmap(struct bnx2x_softc *sc) { uint32_t flags = MODE_ASIC | MODE_PORT2; if (CHIP_IS_E2(sc)) { flags |= MODE_E2; } else if (CHIP_IS_E3(sc)) { flags |= MODE_E3; if (CHIP_REV(sc) == CHIP_REV_Ax) { flags |= MODE_E3_A0; } else { /*if (CHIP_REV(sc) == CHIP_REV_Bx) */ flags |= MODE_E3_B0 | MODE_COS3; } } if (IS_MF(sc)) { flags |= MODE_MF; switch (sc->devinfo.mf_info.mf_mode) { case MULTI_FUNCTION_SD: flags |= MODE_MF_SD; break; case MULTI_FUNCTION_SI: flags |= MODE_MF_SI; break; case MULTI_FUNCTION_AFEX: flags |= MODE_MF_AFEX; break; } } else { flags |= MODE_SF; } #if defined(__LITTLE_ENDIAN) flags |= MODE_LITTLE_ENDIAN; #else /* __BIG_ENDIAN */ flags |= MODE_BIG_ENDIAN; #endif INIT_MODE_FLAGS(sc) = flags; } int bnx2x_alloc_hsi_mem(struct bnx2x_softc *sc) { struct bnx2x_fastpath *fp; char buf[32]; uint32_t i; if (IS_PF(sc)) { /************************/ /* DEFAULT STATUS BLOCK */ /************************/ if (bnx2x_dma_alloc(sc, sizeof(struct host_sp_status_block), &sc->def_sb_dma, "def_sb", RTE_CACHE_LINE_SIZE) != 0) { return -1; } sc->def_sb = (struct host_sp_status_block *)sc->def_sb_dma.vaddr; /***************/ /* EVENT QUEUE */ /***************/ if (bnx2x_dma_alloc(sc, BNX2X_PAGE_SIZE, &sc->eq_dma, "ev_queue", RTE_CACHE_LINE_SIZE) != 0) { sc->def_sb = NULL; return -1; } sc->eq = (union event_ring_elem *)sc->eq_dma.vaddr; /*************/ /* SLOW PATH */ /*************/ if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_slowpath), &sc->sp_dma, "sp", RTE_CACHE_LINE_SIZE) != 0) { sc->eq = NULL; sc->def_sb = NULL; return -1; } sc->sp = (struct bnx2x_slowpath *)sc->sp_dma.vaddr; /*******************/ /* SLOW PATH QUEUE */ /*******************/ if (bnx2x_dma_alloc(sc, BNX2X_PAGE_SIZE, &sc->spq_dma, "sp_queue", RTE_CACHE_LINE_SIZE) != 0) { sc->sp = NULL; sc->eq = NULL; sc->def_sb = NULL; return -1; } sc->spq = (struct eth_spe *)sc->spq_dma.vaddr; /***************************/ /* FW DECOMPRESSION BUFFER */ /***************************/ if (bnx2x_dma_alloc(sc, FW_BUF_SIZE, &sc->gz_buf_dma, "fw_dec_buf", RTE_CACHE_LINE_SIZE) != 0) { sc->spq = NULL; sc->sp = NULL; sc->eq = NULL; sc->def_sb = NULL; return -1; } sc->gz_buf = (void *)sc->gz_buf_dma.vaddr; } /*************/ /* FASTPATHS */ /*************/ /* allocate DMA memory for each fastpath structure */ for (i = 0; i < sc->num_queues; i++) { fp = &sc->fp[i]; fp->sc = sc; fp->index = i; /*******************/ /* FP STATUS BLOCK */ /*******************/ snprintf(buf, sizeof(buf), "fp_%d_sb", i); if (bnx2x_dma_alloc(sc, sizeof(union bnx2x_host_hc_status_block), &fp->sb_dma, buf, RTE_CACHE_LINE_SIZE) != 0) { PMD_DRV_LOG(NOTICE, "Failed to alloc %s", buf); return -1; } else { if (CHIP_IS_E2E3(sc)) { fp->status_block.e2_sb = (struct host_hc_status_block_e2 *) fp->sb_dma.vaddr; } else { fp->status_block.e1x_sb = (struct host_hc_status_block_e1x *) fp->sb_dma.vaddr; } } } return 0; } void bnx2x_free_hsi_mem(struct bnx2x_softc *sc) { struct bnx2x_fastpath *fp; int i; for (i = 0; i < sc->num_queues; i++) { fp = &sc->fp[i]; /*******************/ /* FP STATUS BLOCK */ /*******************/ memset(&fp->status_block, 0, sizeof(fp->status_block)); } /***************************/ /* FW DECOMPRESSION BUFFER */ /***************************/ sc->gz_buf = NULL; /*******************/ /* SLOW PATH QUEUE */ /*******************/ sc->spq = NULL; /*************/ /* SLOW PATH */ /*************/ sc->sp = NULL; /***************/ /* EVENT QUEUE */ /***************/ sc->eq = NULL; /************************/ /* DEFAULT STATUS BLOCK */ /************************/ sc->def_sb = NULL; } /* * Previous driver DMAE transaction may have occurred when pre-boot stage * ended and boot began. This would invalidate the addresses of the * transaction, resulting in was-error bit set in the PCI causing all * hw-to-host PCIe transactions to timeout. If this happened we want to clear * the interrupt which detected this from the pglueb and the was-done bit */ static void bnx2x_prev_interrupted_dmae(struct bnx2x_softc *sc) { uint32_t val; if (!CHIP_IS_E1x(sc)) { val = REG_RD(sc, PGLUE_B_REG_PGLUE_B_INT_STS); if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { REG_WR(sc, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << SC_FUNC(sc)); } } } static int bnx2x_prev_mcp_done(struct bnx2x_softc *sc) { uint32_t rc = bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_DONE, DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET); if (!rc) { PMD_DRV_LOG(NOTICE, "MCP response failure, aborting"); return -1; } return 0; } static struct bnx2x_prev_list_node *bnx2x_prev_path_get_entry(struct bnx2x_softc *sc) { struct bnx2x_prev_list_node *tmp; LIST_FOREACH(tmp, &bnx2x_prev_list, node) { if ((sc->pcie_bus == tmp->bus) && (sc->pcie_device == tmp->slot) && (SC_PATH(sc) == tmp->path)) { return tmp; } } return NULL; } static uint8_t bnx2x_prev_is_path_marked(struct bnx2x_softc *sc) { struct bnx2x_prev_list_node *tmp; int rc = FALSE; rte_spinlock_lock(&bnx2x_prev_mtx); tmp = bnx2x_prev_path_get_entry(sc); if (tmp) { if (tmp->aer) { PMD_DRV_LOG(DEBUG, "Path %d/%d/%d was marked by AER", sc->pcie_bus, sc->pcie_device, SC_PATH(sc)); } else { rc = TRUE; PMD_DRV_LOG(DEBUG, "Path %d/%d/%d was already cleaned from previous drivers", sc->pcie_bus, sc->pcie_device, SC_PATH(sc)); } } rte_spinlock_unlock(&bnx2x_prev_mtx); return rc; } static int bnx2x_prev_mark_path(struct bnx2x_softc *sc, uint8_t after_undi) { struct bnx2x_prev_list_node *tmp; rte_spinlock_lock(&bnx2x_prev_mtx); /* Check whether the entry for this path already exists */ tmp = bnx2x_prev_path_get_entry(sc); if (tmp) { if (!tmp->aer) { PMD_DRV_LOG(DEBUG, "Re-marking AER in path %d/%d/%d", sc->pcie_bus, sc->pcie_device, SC_PATH(sc)); } else { PMD_DRV_LOG(DEBUG, "Removing AER indication from path %d/%d/%d", sc->pcie_bus, sc->pcie_device, SC_PATH(sc)); tmp->aer = 0; } rte_spinlock_unlock(&bnx2x_prev_mtx); return 0; } rte_spinlock_unlock(&bnx2x_prev_mtx); /* Create an entry for this path and add it */ tmp = rte_malloc("", sizeof(struct bnx2x_prev_list_node), RTE_CACHE_LINE_SIZE); if (!tmp) { PMD_DRV_LOG(NOTICE, "Failed to allocate 'bnx2x_prev_list_node'"); return -1; } tmp->bus = sc->pcie_bus; tmp->slot = sc->pcie_device; tmp->path = SC_PATH(sc); tmp->aer = 0; tmp->undi = after_undi ? (1 << SC_PORT(sc)) : 0; rte_spinlock_lock(&bnx2x_prev_mtx); LIST_INSERT_HEAD(&bnx2x_prev_list, tmp, node); rte_spinlock_unlock(&bnx2x_prev_mtx); return 0; } static int bnx2x_do_flr(struct bnx2x_softc *sc) { int i; /* only E2 and onwards support FLR */ if (CHIP_IS_E1x(sc)) { PMD_DRV_LOG(WARNING, "FLR not supported in E1H"); return -1; } /* only bootcode REQ_BC_VER_4_INITIATE_FLR and onwards support flr */ if (sc->devinfo.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { PMD_DRV_LOG(WARNING, "FLR not supported by BC_VER: 0x%08x", sc->devinfo.bc_ver); return -1; } /* Wait for Transaction Pending bit clean */ for (i = 0; i < 4; i++) { if (i) { DELAY(((1 << (i - 1)) * 100) * 1000); } if (!bnx2x_is_pcie_pending(sc)) { goto clear; } } PMD_DRV_LOG(NOTICE, "PCIE transaction is not cleared, " "proceeding with reset anyway"); clear: bnx2x_fw_command(sc, DRV_MSG_CODE_INITIATE_FLR, 0); return 0; } struct bnx2x_mac_vals { uint32_t xmac_addr; uint32_t xmac_val; uint32_t emac_addr; uint32_t emac_val; uint32_t umac_addr; uint32_t umac_val; uint32_t bmac_addr; uint32_t bmac_val[2]; }; static void bnx2x_prev_unload_close_mac(struct bnx2x_softc *sc, struct bnx2x_mac_vals *vals) { uint32_t val, base_addr, offset, mask, reset_reg; uint8_t mac_stopped = FALSE; uint8_t port = SC_PORT(sc); uint32_t wb_data[2]; /* reset addresses as they also mark which values were changed */ vals->bmac_addr = 0; vals->umac_addr = 0; vals->xmac_addr = 0; vals->emac_addr = 0; reset_reg = REG_RD(sc, MISC_REG_RESET_REG_2); if (!CHIP_IS_E3(sc)) { val = REG_RD(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4); mask = MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port; if ((mask & reset_reg) && val) { base_addr = SC_PORT(sc) ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; offset = CHIP_IS_E2(sc) ? BIGMAC2_REGISTER_BMAC_CONTROL : BIGMAC_REGISTER_BMAC_CONTROL; /* * use rd/wr since we cannot use dmae. This is safe * since MCP won't access the bus due to the request * to unload, and no function on the path can be * loaded at this time. */ wb_data[0] = REG_RD(sc, base_addr + offset); wb_data[1] = REG_RD(sc, base_addr + offset + 0x4); vals->bmac_addr = base_addr + offset; vals->bmac_val[0] = wb_data[0]; vals->bmac_val[1] = wb_data[1]; wb_data[0] &= ~ELINK_BMAC_CONTROL_RX_ENABLE; REG_WR(sc, vals->bmac_addr, wb_data[0]); REG_WR(sc, vals->bmac_addr + 0x4, wb_data[1]); } vals->emac_addr = NIG_REG_NIG_EMAC0_EN + SC_PORT(sc) * 4; vals->emac_val = REG_RD(sc, vals->emac_addr); REG_WR(sc, vals->emac_addr, 0); mac_stopped = TRUE; } else { if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { base_addr = SC_PORT(sc) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; val = REG_RD(sc, base_addr + XMAC_REG_PFC_CTRL_HI); REG_WR(sc, base_addr + XMAC_REG_PFC_CTRL_HI, val & ~(1 << 1)); REG_WR(sc, base_addr + XMAC_REG_PFC_CTRL_HI, val | (1 << 1)); vals->xmac_addr = base_addr + XMAC_REG_CTRL; vals->xmac_val = REG_RD(sc, vals->xmac_addr); REG_WR(sc, vals->xmac_addr, 0); mac_stopped = TRUE; } mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; if (mask & reset_reg) { base_addr = SC_PORT(sc) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; vals->umac_val = REG_RD(sc, vals->umac_addr); REG_WR(sc, vals->umac_addr, 0); mac_stopped = TRUE; } } if (mac_stopped) { DELAY(20000); } } #define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4)) #define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff) #define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff) #define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq)) static void bnx2x_prev_unload_undi_inc(struct bnx2x_softc *sc, uint8_t port, uint8_t inc) { uint16_t rcq, bd; uint32_t tmp_reg = REG_RD(sc, BNX2X_PREV_UNDI_PROD_ADDR(port)); rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc; bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc; tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd); REG_WR(sc, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg); } static int bnx2x_prev_unload_common(struct bnx2x_softc *sc) { uint32_t reset_reg, tmp_reg = 0, rc; uint8_t prev_undi = FALSE; struct bnx2x_mac_vals mac_vals; uint32_t timer_count = 1000; uint32_t prev_brb; /* * It is possible a previous function received 'common' answer, * but hasn't loaded yet, therefore creating a scenario of * multiple functions receiving 'common' on the same path. */ memset(&mac_vals, 0, sizeof(mac_vals)); if (bnx2x_prev_is_path_marked(sc)) { return bnx2x_prev_mcp_done(sc); } reset_reg = REG_RD(sc, MISC_REG_RESET_REG_1); /* Reset should be performed after BRB is emptied */ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) { /* Close the MAC Rx to prevent BRB from filling up */ bnx2x_prev_unload_close_mac(sc, &mac_vals); /* close LLH filters towards the BRB */ elink_set_rx_filter(&sc->link_params, 0); /* * Check if the UNDI driver was previously loaded. * UNDI driver initializes CID offset for normal bell to 0x7 */ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_DORQ) { tmp_reg = REG_RD(sc, DORQ_REG_NORM_CID_OFST); if (tmp_reg == 0x7) { PMD_DRV_LOG(DEBUG, "UNDI previously loaded"); prev_undi = TRUE; /* clear the UNDI indication */ REG_WR(sc, DORQ_REG_NORM_CID_OFST, 0); /* clear possible idle check errors */ REG_RD(sc, NIG_REG_NIG_INT_STS_CLR_0); } } /* wait until BRB is empty */ tmp_reg = REG_RD(sc, BRB1_REG_NUM_OF_FULL_BLOCKS); while (timer_count) { prev_brb = tmp_reg; tmp_reg = REG_RD(sc, BRB1_REG_NUM_OF_FULL_BLOCKS); if (!tmp_reg) { break; } PMD_DRV_LOG(DEBUG, "BRB still has 0x%08x", tmp_reg); /* reset timer as long as BRB actually gets emptied */ if (prev_brb > tmp_reg) { timer_count = 1000; } else { timer_count--; } /* If UNDI resides in memory, manually increment it */ if (prev_undi) { bnx2x_prev_unload_undi_inc(sc, SC_PORT(sc), 1); } DELAY(10); } if (!timer_count) { PMD_DRV_LOG(NOTICE, "Failed to empty BRB"); } } /* No packets are in the pipeline, path is ready for reset */ bnx2x_reset_common(sc); if (mac_vals.xmac_addr) { REG_WR(sc, mac_vals.xmac_addr, mac_vals.xmac_val); } if (mac_vals.umac_addr) { REG_WR(sc, mac_vals.umac_addr, mac_vals.umac_val); } if (mac_vals.emac_addr) { REG_WR(sc, mac_vals.emac_addr, mac_vals.emac_val); } if (mac_vals.bmac_addr) { REG_WR(sc, mac_vals.bmac_addr, mac_vals.bmac_val[0]); REG_WR(sc, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); } rc = bnx2x_prev_mark_path(sc, prev_undi); if (rc) { bnx2x_prev_mcp_done(sc); return rc; } return bnx2x_prev_mcp_done(sc); } static int bnx2x_prev_unload_uncommon(struct bnx2x_softc *sc) { int rc; /* Test if previous unload process was already finished for this path */ if (bnx2x_prev_is_path_marked(sc)) { return bnx2x_prev_mcp_done(sc); } /* * If function has FLR capabilities, and existing FW version matches * the one required, then FLR will be sufficient to clean any residue * left by previous driver */ rc = bnx2x_nic_load_analyze_req(sc, FW_MSG_CODE_DRV_LOAD_FUNCTION); if (!rc) { /* fw version is good */ rc = bnx2x_do_flr(sc); } if (!rc) { /* FLR was performed */ return 0; } PMD_DRV_LOG(INFO, "Could not FLR"); /* Close the MCP request, return failure */ rc = bnx2x_prev_mcp_done(sc); if (!rc) { rc = BNX2X_PREV_WAIT_NEEDED; } return rc; } static int bnx2x_prev_unload(struct bnx2x_softc *sc) { int time_counter = 10; uint32_t fw, hw_lock_reg, hw_lock_val; uint32_t rc = 0; /* * Clear HW from errors which may have resulted from an interrupted * DMAE transaction. */ bnx2x_prev_interrupted_dmae(sc); /* Release previously held locks */ if (SC_FUNC(sc) <= 5) hw_lock_reg = (MISC_REG_DRIVER_CONTROL_1 + SC_FUNC(sc) * 8); else hw_lock_reg = (MISC_REG_DRIVER_CONTROL_7 + (SC_FUNC(sc) - 6) * 8); hw_lock_val = (REG_RD(sc, hw_lock_reg)); if (hw_lock_val) { if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) { REG_WR(sc, MCP_REG_MCPR_NVM_SW_ARB, (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << SC_PORT(sc))); } REG_WR(sc, hw_lock_reg, 0xffffffff); } if (MCPR_ACCESS_LOCK_LOCK & REG_RD(sc, MCP_REG_MCPR_ACCESS_LOCK)) { REG_WR(sc, MCP_REG_MCPR_ACCESS_LOCK, 0); } do { /* Lock MCP using an unload request */ fw = bnx2x_fw_command(sc, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0); if (!fw) { PMD_DRV_LOG(NOTICE, "MCP response failure, aborting"); rc = -1; break; } if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) { rc = bnx2x_prev_unload_common(sc); break; } /* non-common reply from MCP might require looping */ rc = bnx2x_prev_unload_uncommon(sc); if (rc != BNX2X_PREV_WAIT_NEEDED) { break; } DELAY(20000); } while (--time_counter); if (!time_counter || rc) { PMD_DRV_LOG(NOTICE, "Failed to unload previous driver!"); rc = -1; } return rc; } static void bnx2x_dcbx_set_state(struct bnx2x_softc *sc, uint8_t dcb_on, uint32_t dcbx_enabled) { if (!CHIP_IS_E1x(sc)) { sc->dcb_state = dcb_on; sc->dcbx_enabled = dcbx_enabled; } else { sc->dcb_state = FALSE; sc->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID; } PMD_DRV_LOG(DEBUG, "DCB state [%s:%s]", dcb_on ? "ON" : "OFF", (dcbx_enabled == BNX2X_DCBX_ENABLED_OFF) ? "user-mode" : (dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF) ? "on-chip static" : (dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON) ? "on-chip with negotiation" : "invalid"); } static int bnx2x_set_qm_cid_count(struct bnx2x_softc *sc) { int cid_count = BNX2X_L2_MAX_CID(sc); if (CNIC_SUPPORT(sc)) { cid_count += CNIC_CID_MAX; } return roundup(cid_count, QM_CID_ROUND); } static void bnx2x_init_multi_cos(struct bnx2x_softc *sc) { int pri, cos; uint32_t pri_map = 0; for (pri = 0; pri < BNX2X_MAX_PRIORITY; pri++) { cos = ((pri_map & (0xf << (pri * 4))) >> (pri * 4)); if (cos < sc->max_cos) { sc->prio_to_cos[pri] = cos; } else { PMD_DRV_LOG(WARNING, "Invalid COS %d for priority %d " "(max COS is %d), setting to 0", cos, pri, (sc->max_cos - 1)); sc->prio_to_cos[pri] = 0; } } } static int bnx2x_pci_get_caps(struct bnx2x_softc *sc) { struct { uint8_t id; uint8_t next; } pci_cap; uint16_t status; struct bnx2x_pci_cap *cap; cap = sc->pci_caps = rte_zmalloc("caps", sizeof(struct bnx2x_pci_cap), RTE_CACHE_LINE_SIZE); if (!cap) { PMD_DRV_LOG(NOTICE, "Failed to allocate memory"); return -ENOMEM; } pci_read(sc, PCI_STATUS, &status, 2); if (!(status & PCI_STATUS_CAP_LIST)) { PMD_DRV_LOG(NOTICE, "PCIe capability reading failed"); return -1; } pci_read(sc, PCI_CAPABILITY_LIST, &pci_cap.next, 1); while (pci_cap.next) { cap->addr = pci_cap.next & ~3; pci_read(sc, pci_cap.next & ~3, &pci_cap, 2); if (pci_cap.id == 0xff) break; cap->id = pci_cap.id; cap->type = BNX2X_PCI_CAP; cap->next = rte_zmalloc("pci_cap", sizeof(struct bnx2x_pci_cap), RTE_CACHE_LINE_SIZE); if (!cap->next) { PMD_DRV_LOG(NOTICE, "Failed to allocate memory"); return -ENOMEM; } cap = cap->next; } return 0; } static void bnx2x_init_rte(struct bnx2x_softc *sc) { sc->max_tx_queues = 128; sc->max_rx_queues = 128; } #define FW_HEADER_LEN 104 #define FW_NAME_57711 "/lib/firmware/bnx2x/bnx2x-e1h-7.2.51.0.fw" #define FW_NAME_57810 "/lib/firmware/bnx2x/bnx2x-e2-7.2.51.0.fw" void bnx2x_load_firmware(struct bnx2x_softc *sc) { const char *fwname; int f; struct stat st; fwname = sc->devinfo.device_id == BNX2X_DEV_ID_57711 ? FW_NAME_57711 : FW_NAME_57810; f = open(fwname, O_RDONLY); if (f < 0) { PMD_DRV_LOG(NOTICE, "Can't open firmware file"); return; } if (fstat(f, &st) < 0) { PMD_DRV_LOG(NOTICE, "Can't stat firmware file"); close(f); return; } sc->firmware = rte_zmalloc("bnx2x_fw", st.st_size, RTE_CACHE_LINE_SIZE); if (!sc->firmware) { PMD_DRV_LOG(NOTICE, "Can't allocate memory for firmware"); close(f); return; } if (read(f, sc->firmware, st.st_size) != st.st_size) { PMD_DRV_LOG(NOTICE, "Can't read firmware data"); close(f); return; } close(f); sc->fw_len = st.st_size; if (sc->fw_len < FW_HEADER_LEN) { PMD_DRV_LOG(NOTICE, "Invalid fw size: %" PRIu64, sc->fw_len); return; } PMD_DRV_LOG(DEBUG, "fw_len = %" PRIu64, sc->fw_len); } static void bnx2x_data_to_init_ops(uint8_t * data, struct raw_op *dst, uint32_t len) { uint32_t *src = (uint32_t *) data; uint32_t i, j, tmp; for (i = 0, j = 0; i < len / 8; ++i, j += 2) { tmp = rte_be_to_cpu_32(src[j]); dst[i].op = (tmp >> 24) & 0xFF; dst[i].offset = tmp & 0xFFFFFF; dst[i].raw_data = rte_be_to_cpu_32(src[j + 1]); } } static void bnx2x_data_to_init_offsets(uint8_t * data, uint16_t * dst, uint32_t len) { uint16_t *src = (uint16_t *) data; uint32_t i; for (i = 0; i < len / 2; ++i) dst[i] = rte_be_to_cpu_16(src[i]); } static void bnx2x_data_to_init_data(uint8_t * data, uint32_t * dst, uint32_t len) { uint32_t *src = (uint32_t *) data; uint32_t i; for (i = 0; i < len / 4; ++i) dst[i] = rte_be_to_cpu_32(src[i]); } static void bnx2x_data_to_iro_array(uint8_t * data, struct iro *dst, uint32_t len) { uint32_t *src = (uint32_t *) data; uint32_t i, j, tmp; for (i = 0, j = 0; i < len / sizeof(struct iro); ++i, ++j) { dst[i].base = rte_be_to_cpu_32(src[j++]); tmp = rte_be_to_cpu_32(src[j]); dst[i].m1 = (tmp >> 16) & 0xFFFF; dst[i].m2 = tmp & 0xFFFF; ++j; tmp = rte_be_to_cpu_32(src[j]); dst[i].m3 = (tmp >> 16) & 0xFFFF; dst[i].size = tmp & 0xFFFF; } } /* * Device attach function. * * Allocates device resources, performs secondary chip identification, and * initializes driver instance variables. This function is called from driver * load after a successful probe. * * Returns: * 0 = Success, >0 = Failure */ int bnx2x_attach(struct bnx2x_softc *sc) { int rc; PMD_DRV_LOG(DEBUG, "Starting attach..."); rc = bnx2x_pci_get_caps(sc); if (rc) { PMD_DRV_LOG(NOTICE, "PCIe caps reading was failed"); return rc; } sc->state = BNX2X_STATE_CLOSED; /* Init RTE stuff */ bnx2x_init_rte(sc); pci_write_long(sc, PCICFG_GRC_ADDRESS, PCICFG_VENDOR_ID_OFFSET); sc->igu_base_addr = IS_VF(sc) ? PXP_VF_ADDR_IGU_START : BAR_IGU_INTMEM; /* get PCI capabilites */ bnx2x_probe_pci_caps(sc); if (sc->devinfo.pcie_msix_cap_reg != 0) { uint32_t val; pci_read(sc, (sc->devinfo.pcie_msix_cap_reg + PCIR_MSIX_CTRL), &val, 2); sc->igu_sb_cnt = (val & PCIM_MSIXCTRL_TABLE_SIZE); } else { sc->igu_sb_cnt = 1; } if (IS_PF(sc)) { /* get device info and set params */ if (bnx2x_get_device_info(sc) != 0) { PMD_DRV_LOG(NOTICE, "getting device info"); return -ENXIO; } /* get phy settings from shmem and 'and' against admin settings */ bnx2x_get_phy_info(sc); } else { /* Left mac of VF unfilled, PF should set it for VF */ memset(sc->link_params.mac_addr, 0, ETHER_ADDR_LEN); } sc->wol = 0; /* set the default MTU (changed via ifconfig) */ sc->mtu = ETHER_MTU; bnx2x_set_modes_bitmap(sc); /* need to reset chip if UNDI was active */ if (IS_PF(sc) && !BNX2X_NOMCP(sc)) { /* init fw_seq */ sc->fw_seq = (SHMEM_RD(sc, func_mb[SC_FW_MB_IDX(sc)].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); bnx2x_prev_unload(sc); } bnx2x_dcbx_set_state(sc, FALSE, BNX2X_DCBX_ENABLED_OFF); /* calculate qm_cid_count */ sc->qm_cid_count = bnx2x_set_qm_cid_count(sc); sc->max_cos = 1; bnx2x_init_multi_cos(sc); return 0; } static void bnx2x_igu_ack_sb(struct bnx2x_softc *sc, uint8_t igu_sb_id, uint8_t segment, uint16_t index, uint8_t op, uint8_t update) { uint32_t igu_addr = sc->igu_base_addr; igu_addr += (IGU_CMD_INT_ACK_BASE + igu_sb_id) * 8; bnx2x_igu_ack_sb_gen(sc, segment, index, op, update, igu_addr); } static void bnx2x_ack_sb(struct bnx2x_softc *sc, uint8_t igu_sb_id, uint8_t storm, uint16_t index, uint8_t op, uint8_t update) { if (unlikely(sc->devinfo.int_block == INT_BLOCK_HC)) bnx2x_hc_ack_sb(sc, igu_sb_id, storm, index, op, update); else { uint8_t segment; if (CHIP_INT_MODE_IS_BC(sc)) { segment = storm; } else if (igu_sb_id != sc->igu_dsb_id) { segment = IGU_SEG_ACCESS_DEF; } else if (storm == ATTENTION_ID) { segment = IGU_SEG_ACCESS_ATTN; } else { segment = IGU_SEG_ACCESS_DEF; } bnx2x_igu_ack_sb(sc, igu_sb_id, segment, index, op, update); } } static void bnx2x_igu_clear_sb_gen(struct bnx2x_softc *sc, uint8_t func, uint8_t idu_sb_id, uint8_t is_pf) { uint32_t data, ctl, cnt = 100; uint32_t igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA; uint32_t igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL; uint32_t igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id / 32) * 4; uint32_t sb_bit = 1 << (idu_sb_id % 32); uint32_t func_encode = func | (is_pf ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT; uint32_t addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id; /* Not supported in BC mode */ if (CHIP_INT_MODE_IS_BC(sc)) { return; } data = ((IGU_USE_REGISTER_cstorm_type_0_sb_cleanup << IGU_REGULAR_CLEANUP_TYPE_SHIFT) | IGU_REGULAR_CLEANUP_SET | IGU_REGULAR_BCLEANUP); ctl = ((addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT) | (func_encode << IGU_CTRL_REG_FID_SHIFT) | (IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT)); REG_WR(sc, igu_addr_data, data); mb(); PMD_DRV_LOG(DEBUG, "write 0x%08x to IGU(via GRC) addr 0x%x", ctl, igu_addr_ctl); REG_WR(sc, igu_addr_ctl, ctl); mb(); /* wait for clean up to finish */ while (!(REG_RD(sc, igu_addr_ack) & sb_bit) && --cnt) { DELAY(20000); } if (!(REG_RD(sc, igu_addr_ack) & sb_bit)) { PMD_DRV_LOG(DEBUG, "Unable to finish IGU cleanup: " "idu_sb_id %d offset %d bit %d (cnt %d)", idu_sb_id, idu_sb_id / 32, idu_sb_id % 32, cnt); } } static void bnx2x_igu_clear_sb(struct bnx2x_softc *sc, uint8_t idu_sb_id) { bnx2x_igu_clear_sb_gen(sc, SC_FUNC(sc), idu_sb_id, TRUE /*PF*/); } /*******************/ /* ECORE CALLBACKS */ /*******************/ static void bnx2x_reset_common(struct bnx2x_softc *sc) { uint32_t val = 0x1400; PMD_INIT_FUNC_TRACE(); /* reset_common */ REG_WR(sc, (GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR), 0xd3ffff7f); if (CHIP_IS_E3(sc)) { val |= MISC_REGISTERS_RESET_REG_2_MSTAT0; val |= MISC_REGISTERS_RESET_REG_2_MSTAT1; } REG_WR(sc, (GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR), val); } static void bnx2x_common_init_phy(struct bnx2x_softc *sc) { uint32_t shmem_base[2]; uint32_t shmem2_base[2]; /* Avoid common init in case MFW supports LFA */ if (SHMEM2_RD(sc, size) > (uint32_t) offsetof(struct shmem2_region, lfa_host_addr[SC_PORT(sc)])) { return; } shmem_base[0] = sc->devinfo.shmem_base; shmem2_base[0] = sc->devinfo.shmem2_base; if (!CHIP_IS_E1x(sc)) { shmem_base[1] = SHMEM2_RD(sc, other_shmem_base_addr); shmem2_base[1] = SHMEM2_RD(sc, other_shmem2_base_addr); } elink_common_init_phy(sc, shmem_base, shmem2_base, sc->devinfo.chip_id, 0); } static void bnx2x_pf_disable(struct bnx2x_softc *sc) { uint32_t val = REG_RD(sc, IGU_REG_PF_CONFIGURATION); val &= ~IGU_PF_CONF_FUNC_EN; REG_WR(sc, IGU_REG_PF_CONFIGURATION, val); REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0); REG_WR(sc, CFC_REG_WEAK_ENABLE_PF, 0); } static void bnx2x_init_pxp(struct bnx2x_softc *sc) { uint16_t devctl; int r_order, w_order; devctl = bnx2x_pcie_capability_read(sc, PCIR_EXPRESS_DEVICE_CTL); w_order = ((devctl & PCIM_EXP_CTL_MAX_PAYLOAD) >> 5); r_order = ((devctl & PCIM_EXP_CTL_MAX_READ_REQUEST) >> 12); ecore_init_pxp_arb(sc, r_order, w_order); } static uint32_t bnx2x_get_pretend_reg(struct bnx2x_softc *sc) { uint32_t base = PXP2_REG_PGL_PRETEND_FUNC_F0; uint32_t stride = (PXP2_REG_PGL_PRETEND_FUNC_F1 - base); return (base + (SC_ABS_FUNC(sc)) * stride); } /* * Called only on E1H or E2. * When pretending to be PF, the pretend value is the function number 0..7. * When pretending to be VF, the pretend val is the PF-num:VF-valid:ABS-VFID * combination. */ static int bnx2x_pretend_func(struct bnx2x_softc *sc, uint16_t pretend_func_val) { uint32_t pretend_reg; if (CHIP_IS_E1H(sc) && (pretend_func_val > E1H_FUNC_MAX)) return -1; /* get my own pretend register */ pretend_reg = bnx2x_get_pretend_reg(sc); REG_WR(sc, pretend_reg, pretend_func_val); REG_RD(sc, pretend_reg); return 0; } static void bnx2x_setup_fan_failure_detection(struct bnx2x_softc *sc) { int is_required; uint32_t val; int port; is_required = 0; val = (SHMEM_RD(sc, dev_info.shared_hw_config.config2) & SHARED_HW_CFG_FAN_FAILURE_MASK); if (val == SHARED_HW_CFG_FAN_FAILURE_ENABLED) { is_required = 1; } /* * The fan failure mechanism is usually related to the PHY type since * the power consumption of the board is affected by the PHY. Currently, * fan is required for most designs with SFX7101, BNX2X8727 and BNX2X8481. */ else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE) { for (port = PORT_0; port < PORT_MAX; port++) { is_required |= elink_fan_failure_det_req(sc, sc-> devinfo.shmem_base, sc-> devinfo.shmem2_base, port); } } if (is_required == 0) { return; } /* Fan failure is indicated by SPIO 5 */ bnx2x_set_spio(sc, MISC_SPIO_SPIO5, MISC_SPIO_INPUT_HI_Z); /* set to active low mode */ val = REG_RD(sc, MISC_REG_SPIO_INT); val |= (MISC_SPIO_SPIO5 << MISC_SPIO_INT_OLD_SET_POS); REG_WR(sc, MISC_REG_SPIO_INT, val); /* enable interrupt to signal the IGU */ val = REG_RD(sc, MISC_REG_SPIO_EVENT_EN); val |= MISC_SPIO_SPIO5; REG_WR(sc, MISC_REG_SPIO_EVENT_EN, val); } static void bnx2x_enable_blocks_attention(struct bnx2x_softc *sc) { uint32_t val; REG_WR(sc, PXP_REG_PXP_INT_MASK_0, 0); if (!CHIP_IS_E1x(sc)) { REG_WR(sc, PXP_REG_PXP_INT_MASK_1, 0x40); } else { REG_WR(sc, PXP_REG_PXP_INT_MASK_1, 0); } REG_WR(sc, DORQ_REG_DORQ_INT_MASK, 0); REG_WR(sc, CFC_REG_CFC_INT_MASK, 0); /* * mask read length error interrupts in brb for parser * (parsing unit and 'checksum and crc' unit) * these errors are legal (PU reads fixed length and CAC can cause * read length error on truncated packets) */ REG_WR(sc, BRB1_REG_BRB1_INT_MASK, 0xFC00); REG_WR(sc, QM_REG_QM_INT_MASK, 0); REG_WR(sc, TM_REG_TM_INT_MASK, 0); REG_WR(sc, XSDM_REG_XSDM_INT_MASK_0, 0); REG_WR(sc, XSDM_REG_XSDM_INT_MASK_1, 0); REG_WR(sc, XCM_REG_XCM_INT_MASK, 0); /* REG_WR(sc, XSEM_REG_XSEM_INT_MASK_0, 0); */ /* REG_WR(sc, XSEM_REG_XSEM_INT_MASK_1, 0); */ REG_WR(sc, USDM_REG_USDM_INT_MASK_0, 0); REG_WR(sc, USDM_REG_USDM_INT_MASK_1, 0); REG_WR(sc, UCM_REG_UCM_INT_MASK, 0); /* REG_WR(sc, USEM_REG_USEM_INT_MASK_0, 0); */ /* REG_WR(sc, USEM_REG_USEM_INT_MASK_1, 0); */ REG_WR(sc, GRCBASE_UPB + PB_REG_PB_INT_MASK, 0); REG_WR(sc, CSDM_REG_CSDM_INT_MASK_0, 0); REG_WR(sc, CSDM_REG_CSDM_INT_MASK_1, 0); REG_WR(sc, CCM_REG_CCM_INT_MASK, 0); /* REG_WR(sc, CSEM_REG_CSEM_INT_MASK_0, 0); */ /* REG_WR(sc, CSEM_REG_CSEM_INT_MASK_1, 0); */ val = (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF | PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN); if (!CHIP_IS_E1x(sc)) { val |= (PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED | PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED); } REG_WR(sc, PXP2_REG_PXP2_INT_MASK_0, val); REG_WR(sc, TSDM_REG_TSDM_INT_MASK_0, 0); REG_WR(sc, TSDM_REG_TSDM_INT_MASK_1, 0); REG_WR(sc, TCM_REG_TCM_INT_MASK, 0); /* REG_WR(sc, TSEM_REG_TSEM_INT_MASK_0, 0); */ if (!CHIP_IS_E1x(sc)) { /* enable VFC attentions: bits 11 and 12, bits 31:13 reserved */ REG_WR(sc, TSEM_REG_TSEM_INT_MASK_1, 0x07ff); } REG_WR(sc, CDU_REG_CDU_INT_MASK, 0); REG_WR(sc, DMAE_REG_DMAE_INT_MASK, 0); /* REG_WR(sc, MISC_REG_MISC_INT_MASK, 0); */ REG_WR(sc, PBF_REG_PBF_INT_MASK, 0x18); /* bit 3,4 masked */ } /** * bnx2x_init_hw_common - initialize the HW at the COMMON phase. * * @sc: driver handle */ static int bnx2x_init_hw_common(struct bnx2x_softc *sc) { uint8_t abs_func_id; uint32_t val; PMD_DRV_LOG(DEBUG, "starting common init for func %d", SC_ABS_FUNC(sc)); /* * take the RESET lock to protect undi_unload flow from accessing * registers while we are resetting the chip */ bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_RESET); bnx2x_reset_common(sc); REG_WR(sc, (GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET), 0xffffffff); val = 0xfffc; if (CHIP_IS_E3(sc)) { val |= MISC_REGISTERS_RESET_REG_2_MSTAT0; val |= MISC_REGISTERS_RESET_REG_2_MSTAT1; } REG_WR(sc, (GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET), val); bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_RESET); ecore_init_block(sc, BLOCK_MISC, PHASE_COMMON); if (!CHIP_IS_E1x(sc)) { /* * 4-port mode or 2-port mode we need to turn off master-enable for * everyone. After that we turn it back on for self. So, we disregard * multi-function, and always disable all functions on the given path, * this means 0,2,4,6 for path 0 and 1,3,5,7 for path 1 */ for (abs_func_id = SC_PATH(sc); abs_func_id < (E2_FUNC_MAX * 2); abs_func_id += 2) { if (abs_func_id == SC_ABS_FUNC(sc)) { REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); continue; } bnx2x_pretend_func(sc, abs_func_id); /* clear pf enable */ bnx2x_pf_disable(sc); bnx2x_pretend_func(sc, SC_ABS_FUNC(sc)); } } ecore_init_block(sc, BLOCK_PXP, PHASE_COMMON); ecore_init_block(sc, BLOCK_PXP2, PHASE_COMMON); bnx2x_init_pxp(sc); #ifdef __BIG_ENDIAN REG_WR(sc, PXP2_REG_RQ_QM_ENDIAN_M, 1); REG_WR(sc, PXP2_REG_RQ_TM_ENDIAN_M, 1); REG_WR(sc, PXP2_REG_RQ_SRC_ENDIAN_M, 1); REG_WR(sc, PXP2_REG_RQ_CDU_ENDIAN_M, 1); REG_WR(sc, PXP2_REG_RQ_DBG_ENDIAN_M, 1); /* make sure this value is 0 */ REG_WR(sc, PXP2_REG_RQ_HC_ENDIAN_M, 0); //REG_WR(sc, PXP2_REG_RD_PBF_SWAP_MODE, 1); REG_WR(sc, PXP2_REG_RD_QM_SWAP_MODE, 1); REG_WR(sc, PXP2_REG_RD_TM_SWAP_MODE, 1); REG_WR(sc, PXP2_REG_RD_SRC_SWAP_MODE, 1); REG_WR(sc, PXP2_REG_RD_CDURD_SWAP_MODE, 1); #endif ecore_ilt_init_page_size(sc, INITOP_SET); if (CHIP_REV_IS_FPGA(sc) && CHIP_IS_E1H(sc)) { REG_WR(sc, PXP2_REG_PGL_TAGS_LIMIT, 0x1); } /* let the HW do it's magic... */ DELAY(100000); /* finish PXP init */ val = REG_RD(sc, PXP2_REG_RQ_CFG_DONE); if (val != 1) { PMD_DRV_LOG(NOTICE, "PXP2 CFG failed"); return -1; } val = REG_RD(sc, PXP2_REG_RD_INIT_DONE); if (val != 1) { PMD_DRV_LOG(NOTICE, "PXP2 RD_INIT failed"); return -1; } /* * Timer bug workaround for E2 only. We need to set the entire ILT to have * entries with value "0" and valid bit on. This needs to be done by the * first PF that is loaded in a path (i.e. common phase) */ if (!CHIP_IS_E1x(sc)) { /* * In E2 there is a bug in the timers block that can cause function 6 / 7 * (i.e. vnic3) to start even if it is marked as "scan-off". * This occurs when a different function (func2,3) is being marked * as "scan-off". Real-life scenario for example: if a driver is being * load-unloaded while func6,7 are down. This will cause the timer to access * the ilt, translate to a logical address and send a request to read/write. * Since the ilt for the function that is down is not valid, this will cause * a translation error which is unrecoverable. * The Workaround is intended to make sure that when this happens nothing * fatal will occur. The workaround: * 1. First PF driver which loads on a path will: * a. After taking the chip out of reset, by using pretend, * it will write "0" to the following registers of * the other vnics. * REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0); * REG_WR(pdev, CFC_REG_WEAK_ENABLE_PF,0); * REG_WR(pdev, CFC_REG_STRONG_ENABLE_PF,0); * And for itself it will write '1' to * PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER to enable * dmae-operations (writing to pram for example.) * note: can be done for only function 6,7 but cleaner this * way. * b. Write zero+valid to the entire ILT. * c. Init the first_timers_ilt_entry, last_timers_ilt_entry of * VNIC3 (of that port). The range allocated will be the * entire ILT. This is needed to prevent ILT range error. * 2. Any PF driver load flow: * a. ILT update with the physical addresses of the allocated * logical pages. * b. Wait 20msec. - note that this timeout is needed to make * sure there are no requests in one of the PXP internal * queues with "old" ILT addresses. * c. PF enable in the PGLC. * d. Clear the was_error of the PF in the PGLC. (could have * occurred while driver was down) * e. PF enable in the CFC (WEAK + STRONG) * f. Timers scan enable * 3. PF driver unload flow: * a. Clear the Timers scan_en. * b. Polling for scan_on=0 for that PF. * c. Clear the PF enable bit in the PXP. * d. Clear the PF enable in the CFC (WEAK + STRONG) * e. Write zero+valid to all ILT entries (The valid bit must * stay set) * f. If this is VNIC 3 of a port then also init * first_timers_ilt_entry to zero and last_timers_ilt_entry * to the last enrty in the ILT. * * Notes: * Currently the PF error in the PGLC is non recoverable. * In the future the there will be a recovery routine for this error. * Currently attention is masked. * Having an MCP lock on the load/unload process does not guarantee that * there is no Timer disable during Func6/7 enable. This is because the * Timers scan is currently being cleared by the MCP on FLR. * Step 2.d can be done only for PF6/7 and the driver can also check if * there is error before clearing it. But the flow above is simpler and * more general. * All ILT entries are written by zero+valid and not just PF6/7 * ILT entries since in the future the ILT entries allocation for * PF-s might be dynamic. */ struct ilt_client_info ilt_cli; struct ecore_ilt ilt; memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); memset(&ilt, 0, sizeof(struct ecore_ilt)); /* initialize dummy TM client */ ilt_cli.start = 0; ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1; ilt_cli.client_num = ILT_CLIENT_TM; /* * Step 1: set zeroes to all ilt page entries with valid bit on * Step 2: set the timers first/last ilt entry to point * to the entire range to prevent ILT range error for 3rd/4th * vnic (this code assumes existence of the vnic) * * both steps performed by call to ecore_ilt_client_init_op() * with dummy TM client * * we must use pretend since PXP2_REG_RQ_##blk##_FIRST_ILT * and his brother are split registers */ bnx2x_pretend_func(sc, (SC_PATH(sc) + 6)); ecore_ilt_client_init_op_ilt(sc, &ilt, &ilt_cli, INITOP_CLEAR); bnx2x_pretend_func(sc, SC_ABS_FUNC(sc)); REG_WR(sc, PXP2_REG_RQ_DRAM_ALIGN, BNX2X_PXP_DRAM_ALIGN); REG_WR(sc, PXP2_REG_RQ_DRAM_ALIGN_RD, BNX2X_PXP_DRAM_ALIGN); REG_WR(sc, PXP2_REG_RQ_DRAM_ALIGN_SEL, 1); } REG_WR(sc, PXP2_REG_RQ_DISABLE_INPUTS, 0); REG_WR(sc, PXP2_REG_RD_DISABLE_INPUTS, 0); if (!CHIP_IS_E1x(sc)) { int factor = 0; ecore_init_block(sc, BLOCK_PGLUE_B, PHASE_COMMON); ecore_init_block(sc, BLOCK_ATC, PHASE_COMMON); /* let the HW do it's magic... */ do { DELAY(200000); val = REG_RD(sc, ATC_REG_ATC_INIT_DONE); } while (factor-- && (val != 1)); if (val != 1) { PMD_DRV_LOG(NOTICE, "ATC_INIT failed"); return -1; } } ecore_init_block(sc, BLOCK_DMAE, PHASE_COMMON); /* clean the DMAE memory */ sc->dmae_ready = 1; ecore_init_fill(sc, TSEM_REG_PRAM, 0, 8); ecore_init_block(sc, BLOCK_TCM, PHASE_COMMON); ecore_init_block(sc, BLOCK_UCM, PHASE_COMMON); ecore_init_block(sc, BLOCK_CCM, PHASE_COMMON); ecore_init_block(sc, BLOCK_XCM, PHASE_COMMON); bnx2x_read_dmae(sc, XSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(sc, CSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(sc, TSEM_REG_PASSIVE_BUFFER, 3); bnx2x_read_dmae(sc, USEM_REG_PASSIVE_BUFFER, 3); ecore_init_block(sc, BLOCK_QM, PHASE_COMMON); /* QM queues pointers table */ ecore_qm_init_ptr_table(sc, sc->qm_cid_count, INITOP_SET); /* soft reset pulse */ REG_WR(sc, QM_REG_SOFT_RESET, 1); REG_WR(sc, QM_REG_SOFT_RESET, 0); if (CNIC_SUPPORT(sc)) ecore_init_block(sc, BLOCK_TM, PHASE_COMMON); ecore_init_block(sc, BLOCK_DORQ, PHASE_COMMON); REG_WR(sc, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT); if (!CHIP_REV_IS_SLOW(sc)) { /* enable hw interrupt from doorbell Q */ REG_WR(sc, DORQ_REG_DORQ_INT_MASK, 0); } ecore_init_block(sc, BLOCK_BRB1, PHASE_COMMON); ecore_init_block(sc, BLOCK_PRS, PHASE_COMMON); REG_WR(sc, PRS_REG_A_PRSU_20, 0xf); REG_WR(sc, PRS_REG_E1HOV_MODE, sc->devinfo.mf_info.path_has_ovlan); if (!CHIP_IS_E1x(sc) && !CHIP_IS_E3B0(sc)) { if (IS_MF_AFEX(sc)) { /* * configure that AFEX and VLAN headers must be * received in AFEX mode */ REG_WR(sc, PRS_REG_HDRS_AFTER_BASIC, 0xE); REG_WR(sc, PRS_REG_MUST_HAVE_HDRS, 0xA); REG_WR(sc, PRS_REG_HDRS_AFTER_TAG_0, 0x6); REG_WR(sc, PRS_REG_TAG_ETHERTYPE_0, 0x8926); REG_WR(sc, PRS_REG_TAG_LEN_0, 0x4); } else { /* * Bit-map indicating which L2 hdrs may appear * after the basic Ethernet header */ REG_WR(sc, PRS_REG_HDRS_AFTER_BASIC, sc->devinfo.mf_info.path_has_ovlan ? 7 : 6); } } ecore_init_block(sc, BLOCK_TSDM, PHASE_COMMON); ecore_init_block(sc, BLOCK_CSDM, PHASE_COMMON); ecore_init_block(sc, BLOCK_USDM, PHASE_COMMON); ecore_init_block(sc, BLOCK_XSDM, PHASE_COMMON); if (!CHIP_IS_E1x(sc)) { /* reset VFC memories */ REG_WR(sc, TSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST, VFC_MEMORIES_RST_REG_CAM_RST | VFC_MEMORIES_RST_REG_RAM_RST); REG_WR(sc, XSEM_REG_FAST_MEMORY + VFC_REG_MEMORIES_RST, VFC_MEMORIES_RST_REG_CAM_RST | VFC_MEMORIES_RST_REG_RAM_RST); DELAY(20000); } ecore_init_block(sc, BLOCK_TSEM, PHASE_COMMON); ecore_init_block(sc, BLOCK_USEM, PHASE_COMMON); ecore_init_block(sc, BLOCK_CSEM, PHASE_COMMON); ecore_init_block(sc, BLOCK_XSEM, PHASE_COMMON); /* sync semi rtc */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR, 0x80000000); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0x80000000); ecore_init_block(sc, BLOCK_UPB, PHASE_COMMON); ecore_init_block(sc, BLOCK_XPB, PHASE_COMMON); ecore_init_block(sc, BLOCK_PBF, PHASE_COMMON); if (!CHIP_IS_E1x(sc)) { if (IS_MF_AFEX(sc)) { /* * configure that AFEX and VLAN headers must be * sent in AFEX mode */ REG_WR(sc, PBF_REG_HDRS_AFTER_BASIC, 0xE); REG_WR(sc, PBF_REG_MUST_HAVE_HDRS, 0xA); REG_WR(sc, PBF_REG_HDRS_AFTER_TAG_0, 0x6); REG_WR(sc, PBF_REG_TAG_ETHERTYPE_0, 0x8926); REG_WR(sc, PBF_REG_TAG_LEN_0, 0x4); } else { REG_WR(sc, PBF_REG_HDRS_AFTER_BASIC, sc->devinfo.mf_info.path_has_ovlan ? 7 : 6); } } REG_WR(sc, SRC_REG_SOFT_RST, 1); ecore_init_block(sc, BLOCK_SRC, PHASE_COMMON); if (CNIC_SUPPORT(sc)) { REG_WR(sc, SRC_REG_KEYSEARCH_0, 0x63285672); REG_WR(sc, SRC_REG_KEYSEARCH_1, 0x24b8f2cc); REG_WR(sc, SRC_REG_KEYSEARCH_2, 0x223aef9b); REG_WR(sc, SRC_REG_KEYSEARCH_3, 0x26001e3a); REG_WR(sc, SRC_REG_KEYSEARCH_4, 0x7ae91116); REG_WR(sc, SRC_REG_KEYSEARCH_5, 0x5ce5230b); REG_WR(sc, SRC_REG_KEYSEARCH_6, 0x298d8adf); REG_WR(sc, SRC_REG_KEYSEARCH_7, 0x6eb0ff09); REG_WR(sc, SRC_REG_KEYSEARCH_8, 0x1830f82f); REG_WR(sc, SRC_REG_KEYSEARCH_9, 0x01e46be7); } REG_WR(sc, SRC_REG_SOFT_RST, 0); if (sizeof(union cdu_context) != 1024) { /* we currently assume that a context is 1024 bytes */ PMD_DRV_LOG(NOTICE, "please adjust the size of cdu_context(%ld)", (long)sizeof(union cdu_context)); } ecore_init_block(sc, BLOCK_CDU, PHASE_COMMON); val = (4 << 24) + (0 << 12) + 1024; REG_WR(sc, CDU_REG_CDU_GLOBAL_PARAMS, val); ecore_init_block(sc, BLOCK_CFC, PHASE_COMMON); REG_WR(sc, CFC_REG_INIT_REG, 0x7FF); /* enable context validation interrupt from CFC */ REG_WR(sc, CFC_REG_CFC_INT_MASK, 0); /* set the thresholds to prevent CFC/CDU race */ REG_WR(sc, CFC_REG_DEBUG0, 0x20020000); ecore_init_block(sc, BLOCK_HC, PHASE_COMMON); if (!CHIP_IS_E1x(sc) && BNX2X_NOMCP(sc)) { REG_WR(sc, IGU_REG_RESET_MEMORIES, 0x36); } ecore_init_block(sc, BLOCK_IGU, PHASE_COMMON); ecore_init_block(sc, BLOCK_MISC_AEU, PHASE_COMMON); /* Reset PCIE errors for debug */ REG_WR(sc, 0x2814, 0xffffffff); REG_WR(sc, 0x3820, 0xffffffff); if (!CHIP_IS_E1x(sc)) { REG_WR(sc, PCICFG_OFFSET + PXPCS_TL_CONTROL_5, (PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 | PXPCS_TL_CONTROL_5_ERR_UNSPPORT)); REG_WR(sc, PCICFG_OFFSET + PXPCS_TL_FUNC345_STAT, (PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4 | PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3 | PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2)); REG_WR(sc, PCICFG_OFFSET + PXPCS_TL_FUNC678_STAT, (PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7 | PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6 | PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5)); } ecore_init_block(sc, BLOCK_NIG, PHASE_COMMON); /* in E3 this done in per-port section */ if (!CHIP_IS_E3(sc)) REG_WR(sc, NIG_REG_LLH_MF_MODE, IS_MF(sc)); if (CHIP_IS_E1H(sc)) { /* not applicable for E2 (and above ...) */ REG_WR(sc, NIG_REG_LLH_E1HOV_MODE, IS_MF_SD(sc)); } if (CHIP_REV_IS_SLOW(sc)) { DELAY(200000); } /* finish CFC init */ val = reg_poll(sc, CFC_REG_LL_INIT_DONE, 1, 100, 10); if (val != 1) { PMD_DRV_LOG(NOTICE, "CFC LL_INIT failed"); return -1; } val = reg_poll(sc, CFC_REG_AC_INIT_DONE, 1, 100, 10); if (val != 1) { PMD_DRV_LOG(NOTICE, "CFC AC_INIT failed"); return -1; } val = reg_poll(sc, CFC_REG_CAM_INIT_DONE, 1, 100, 10); if (val != 1) { PMD_DRV_LOG(NOTICE, "CFC CAM_INIT failed"); return -1; } REG_WR(sc, CFC_REG_DEBUG0, 0); bnx2x_setup_fan_failure_detection(sc); /* clear PXP2 attentions */ REG_RD(sc, PXP2_REG_PXP2_INT_STS_CLR_0); bnx2x_enable_blocks_attention(sc); if (!CHIP_REV_IS_SLOW(sc)) { ecore_enable_blocks_parity(sc); } if (!BNX2X_NOMCP(sc)) { if (CHIP_IS_E1x(sc)) { bnx2x_common_init_phy(sc); } } return 0; } /** * bnx2x_init_hw_common_chip - init HW at the COMMON_CHIP phase. * * @sc: driver handle */ static int bnx2x_init_hw_common_chip(struct bnx2x_softc *sc) { int rc = bnx2x_init_hw_common(sc); if (rc) { return rc; } /* In E2 2-PORT mode, same ext phy is used for the two paths */ if (!BNX2X_NOMCP(sc)) { bnx2x_common_init_phy(sc); } return 0; } static int bnx2x_init_hw_port(struct bnx2x_softc *sc) { int port = SC_PORT(sc); int init_phase = port ? PHASE_PORT1 : PHASE_PORT0; uint32_t low, high; uint32_t val; PMD_DRV_LOG(DEBUG, "starting port init for port %d", port); REG_WR(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4, 0); ecore_init_block(sc, BLOCK_MISC, init_phase); ecore_init_block(sc, BLOCK_PXP, init_phase); ecore_init_block(sc, BLOCK_PXP2, init_phase); /* * Timers bug workaround: disables the pf_master bit in pglue at * common phase, we need to enable it here before any dmae access are * attempted. Therefore we manually added the enable-master to the * port phase (it also happens in the function phase) */ if (!CHIP_IS_E1x(sc)) { REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); } ecore_init_block(sc, BLOCK_ATC, init_phase); ecore_init_block(sc, BLOCK_DMAE, init_phase); ecore_init_block(sc, BLOCK_PGLUE_B, init_phase); ecore_init_block(sc, BLOCK_QM, init_phase); ecore_init_block(sc, BLOCK_TCM, init_phase); ecore_init_block(sc, BLOCK_UCM, init_phase); ecore_init_block(sc, BLOCK_CCM, init_phase); ecore_init_block(sc, BLOCK_XCM, init_phase); /* QM cid (connection) count */ ecore_qm_init_cid_count(sc, sc->qm_cid_count, INITOP_SET); if (CNIC_SUPPORT(sc)) { ecore_init_block(sc, BLOCK_TM, init_phase); REG_WR(sc, TM_REG_LIN0_SCAN_TIME + port * 4, 20); REG_WR(sc, TM_REG_LIN0_MAX_ACTIVE_CID + port * 4, 31); } ecore_init_block(sc, BLOCK_DORQ, init_phase); ecore_init_block(sc, BLOCK_BRB1, init_phase); if (CHIP_IS_E1H(sc)) { if (IS_MF(sc)) { low = (BNX2X_ONE_PORT(sc) ? 160 : 246); } else if (sc->mtu > 4096) { if (BNX2X_ONE_PORT(sc)) { low = 160; } else { val = sc->mtu; /* (24*1024 + val*4)/256 */ low = (96 + (val / 64) + ((val % 64) ? 1 : 0)); } } else { low = (BNX2X_ONE_PORT(sc) ? 80 : 160); } high = (low + 56); /* 14*1024/256 */ REG_WR(sc, BRB1_REG_PAUSE_LOW_THRESHOLD_0 + port * 4, low); REG_WR(sc, BRB1_REG_PAUSE_HIGH_THRESHOLD_0 + port * 4, high); } if (CHIP_IS_MODE_4_PORT(sc)) { REG_WR(sc, SC_PORT(sc) ? BRB1_REG_MAC_GUARANTIED_1 : BRB1_REG_MAC_GUARANTIED_0, 40); } ecore_init_block(sc, BLOCK_PRS, init_phase); if (CHIP_IS_E3B0(sc)) { if (IS_MF_AFEX(sc)) { /* configure headers for AFEX mode */ if (SC_PORT(sc)) { REG_WR(sc, PRS_REG_HDRS_AFTER_BASIC_PORT_1, 0xE); REG_WR(sc, PRS_REG_HDRS_AFTER_TAG_0_PORT_1, 0x6); REG_WR(sc, PRS_REG_MUST_HAVE_HDRS_PORT_1, 0xA); } else { REG_WR(sc, PRS_REG_HDRS_AFTER_BASIC_PORT_0, 0xE); REG_WR(sc, PRS_REG_HDRS_AFTER_TAG_0_PORT_0, 0x6); REG_WR(sc, PRS_REG_MUST_HAVE_HDRS_PORT_0, 0xA); } } else { /* Ovlan exists only if we are in multi-function + * switch-dependent mode, in switch-independent there * is no ovlan headers */ REG_WR(sc, SC_PORT(sc) ? PRS_REG_HDRS_AFTER_BASIC_PORT_1 : PRS_REG_HDRS_AFTER_BASIC_PORT_0, (sc->devinfo.mf_info.path_has_ovlan ? 7 : 6)); } } ecore_init_block(sc, BLOCK_TSDM, init_phase); ecore_init_block(sc, BLOCK_CSDM, init_phase); ecore_init_block(sc, BLOCK_USDM, init_phase); ecore_init_block(sc, BLOCK_XSDM, init_phase); ecore_init_block(sc, BLOCK_TSEM, init_phase); ecore_init_block(sc, BLOCK_USEM, init_phase); ecore_init_block(sc, BLOCK_CSEM, init_phase); ecore_init_block(sc, BLOCK_XSEM, init_phase); ecore_init_block(sc, BLOCK_UPB, init_phase); ecore_init_block(sc, BLOCK_XPB, init_phase); ecore_init_block(sc, BLOCK_PBF, init_phase); if (CHIP_IS_E1x(sc)) { /* configure PBF to work without PAUSE mtu 9000 */ REG_WR(sc, PBF_REG_P0_PAUSE_ENABLE + port * 4, 0); /* update threshold */ REG_WR(sc, PBF_REG_P0_ARB_THRSH + port * 4, (9040 / 16)); /* update init credit */ REG_WR(sc, PBF_REG_P0_INIT_CRD + port * 4, (9040 / 16) + 553 - 22); /* probe changes */ REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 1); DELAY(50); REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 0); } if (CNIC_SUPPORT(sc)) { ecore_init_block(sc, BLOCK_SRC, init_phase); } ecore_init_block(sc, BLOCK_CDU, init_phase); ecore_init_block(sc, BLOCK_CFC, init_phase); ecore_init_block(sc, BLOCK_HC, init_phase); ecore_init_block(sc, BLOCK_IGU, init_phase); ecore_init_block(sc, BLOCK_MISC_AEU, init_phase); /* init aeu_mask_attn_func_0/1: * - SF mode: bits 3-7 are masked. only bits 0-2 are in use * - MF mode: bit 3 is masked. bits 0-2 are in use as in SF * bits 4-7 are used for "per vn group attention" */ val = IS_MF(sc) ? 0xF7 : 0x7; val |= 0x10; REG_WR(sc, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port * 4, val); ecore_init_block(sc, BLOCK_NIG, init_phase); if (!CHIP_IS_E1x(sc)) { /* Bit-map indicating which L2 hdrs may appear after the * basic Ethernet header */ if (IS_MF_AFEX(sc)) { REG_WR(sc, SC_PORT(sc) ? NIG_REG_P1_HDRS_AFTER_BASIC : NIG_REG_P0_HDRS_AFTER_BASIC, 0xE); } else { REG_WR(sc, SC_PORT(sc) ? NIG_REG_P1_HDRS_AFTER_BASIC : NIG_REG_P0_HDRS_AFTER_BASIC, IS_MF_SD(sc) ? 7 : 6); } if (CHIP_IS_E3(sc)) { REG_WR(sc, SC_PORT(sc) ? NIG_REG_LLH1_MF_MODE : NIG_REG_LLH_MF_MODE, IS_MF(sc)); } } if (!CHIP_IS_E3(sc)) { REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 1); } /* 0x2 disable mf_ov, 0x1 enable */ REG_WR(sc, NIG_REG_LLH0_BRB1_DRV_MASK_MF + port * 4, (IS_MF_SD(sc) ? 0x1 : 0x2)); if (!CHIP_IS_E1x(sc)) { val = 0; switch (sc->devinfo.mf_info.mf_mode) { case MULTI_FUNCTION_SD: val = 1; break; case MULTI_FUNCTION_SI: case MULTI_FUNCTION_AFEX: val = 2; break; } REG_WR(sc, (SC_PORT(sc) ? NIG_REG_LLH1_CLS_TYPE : NIG_REG_LLH0_CLS_TYPE), val); } REG_WR(sc, NIG_REG_LLFC_ENABLE_0 + port * 4, 0); REG_WR(sc, NIG_REG_LLFC_OUT_EN_0 + port * 4, 0); REG_WR(sc, NIG_REG_PAUSE_ENABLE_0 + port * 4, 1); /* If SPIO5 is set to generate interrupts, enable it for this port */ val = REG_RD(sc, MISC_REG_SPIO_EVENT_EN); if (val & MISC_SPIO_SPIO5) { uint32_t reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); val = REG_RD(sc, reg_addr); val |= AEU_INPUTS_ATTN_BITS_SPIO5; REG_WR(sc, reg_addr, val); } return 0; } static uint32_t bnx2x_flr_clnup_reg_poll(struct bnx2x_softc *sc, uint32_t reg, uint32_t expected, uint32_t poll_count) { uint32_t cur_cnt = poll_count; uint32_t val; while ((val = REG_RD(sc, reg)) != expected && cur_cnt--) { DELAY(FLR_WAIT_INTERVAL); } return val; } static int bnx2x_flr_clnup_poll_hw_counter(struct bnx2x_softc *sc, uint32_t reg, __rte_unused const char *msg, uint32_t poll_cnt) { uint32_t val = bnx2x_flr_clnup_reg_poll(sc, reg, 0, poll_cnt); if (val != 0) { PMD_DRV_LOG(NOTICE, "%s usage count=%d", msg, val); return -1; } return 0; } /* Common routines with VF FLR cleanup */ static uint32_t bnx2x_flr_clnup_poll_count(struct bnx2x_softc *sc) { /* adjust polling timeout */ if (CHIP_REV_IS_EMUL(sc)) { return (FLR_POLL_CNT * 2000); } if (CHIP_REV_IS_FPGA(sc)) { return (FLR_POLL_CNT * 120); } return FLR_POLL_CNT; } static int bnx2x_poll_hw_usage_counters(struct bnx2x_softc *sc, uint32_t poll_cnt) { /* wait for CFC PF usage-counter to zero (includes all the VFs) */ if (bnx2x_flr_clnup_poll_hw_counter(sc, CFC_REG_NUM_LCIDS_INSIDE_PF, "CFC PF usage counter timed out", poll_cnt)) { return -1; } /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */ if (bnx2x_flr_clnup_poll_hw_counter(sc, DORQ_REG_PF_USAGE_CNT, "DQ PF usage counter timed out", poll_cnt)) { return -1; } /* Wait for QM PF usage-counter to zero (until DQ cleanup) */ if (bnx2x_flr_clnup_poll_hw_counter(sc, QM_REG_PF_USG_CNT_0 + 4 * SC_FUNC(sc), "QM PF usage counter timed out", poll_cnt)) { return -1; } /* Wait for Timer PF usage-counters to zero (until DQ cleanup) */ if (bnx2x_flr_clnup_poll_hw_counter(sc, TM_REG_LIN0_VNIC_UC + 4 * SC_PORT(sc), "Timers VNIC usage counter timed out", poll_cnt)) { return -1; } if (bnx2x_flr_clnup_poll_hw_counter(sc, TM_REG_LIN0_NUM_SCANS + 4 * SC_PORT(sc), "Timers NUM_SCANS usage counter timed out", poll_cnt)) { return -1; } /* Wait DMAE PF usage counter to zero */ if (bnx2x_flr_clnup_poll_hw_counter(sc, dmae_reg_go_c[INIT_DMAE_C(sc)], "DMAE dommand register timed out", poll_cnt)) { return -1; } return 0; } #define OP_GEN_PARAM(param) \ (((param) << SDM_OP_GEN_COMP_PARAM_SHIFT) & SDM_OP_GEN_COMP_PARAM) #define OP_GEN_TYPE(type) \ (((type) << SDM_OP_GEN_COMP_TYPE_SHIFT) & SDM_OP_GEN_COMP_TYPE) #define OP_GEN_AGG_VECT(index) \ (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX) static int bnx2x_send_final_clnup(struct bnx2x_softc *sc, uint8_t clnup_func, uint32_t poll_cnt) { uint32_t op_gen_command = 0; uint32_t comp_addr = (BAR_CSTRORM_INTMEM + CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func)); int ret = 0; if (REG_RD(sc, comp_addr)) { PMD_DRV_LOG(NOTICE, "Cleanup complete was not 0 before sending"); return -1; } op_gen_command |= OP_GEN_PARAM(XSTORM_AGG_INT_FINAL_CLEANUP_INDEX); op_gen_command |= OP_GEN_TYPE(XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE); op_gen_command |= OP_GEN_AGG_VECT(clnup_func); op_gen_command |= 1 << SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT; REG_WR(sc, XSDM_REG_OPERATION_GEN, op_gen_command); if (bnx2x_flr_clnup_reg_poll(sc, comp_addr, 1, poll_cnt) != 1) { PMD_DRV_LOG(NOTICE, "FW final cleanup did not succeed"); PMD_DRV_LOG(DEBUG, "At timeout completion address contained %x", (REG_RD(sc, comp_addr))); rte_panic("FLR cleanup failed"); return -1; } /* Zero completion for nxt FLR */ REG_WR(sc, comp_addr, 0); return ret; } static void bnx2x_pbf_pN_buf_flushed(struct bnx2x_softc *sc, struct pbf_pN_buf_regs *regs, uint32_t poll_count) { uint32_t init_crd, crd, crd_start, crd_freed, crd_freed_start; uint32_t cur_cnt = poll_count; crd_freed = crd_freed_start = REG_RD(sc, regs->crd_freed); crd = crd_start = REG_RD(sc, regs->crd); init_crd = REG_RD(sc, regs->init_crd); while ((crd != init_crd) && ((uint32_t) ((int32_t) crd_freed - (int32_t) crd_freed_start) < (init_crd - crd_start))) { if (cur_cnt--) { DELAY(FLR_WAIT_INTERVAL); crd = REG_RD(sc, regs->crd); crd_freed = REG_RD(sc, regs->crd_freed); } else { break; } } } static void bnx2x_pbf_pN_cmd_flushed(struct bnx2x_softc *sc, struct pbf_pN_cmd_regs *regs, uint32_t poll_count) { uint32_t occup, to_free, freed, freed_start; uint32_t cur_cnt = poll_count; occup = to_free = REG_RD(sc, regs->lines_occup); freed = freed_start = REG_RD(sc, regs->lines_freed); while (occup && ((uint32_t) ((int32_t) freed - (int32_t) freed_start) < to_free)) { if (cur_cnt--) { DELAY(FLR_WAIT_INTERVAL); occup = REG_RD(sc, regs->lines_occup); freed = REG_RD(sc, regs->lines_freed); } else { break; } } } static void bnx2x_tx_hw_flushed(struct bnx2x_softc *sc, uint32_t poll_count) { struct pbf_pN_cmd_regs cmd_regs[] = { {0, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_OCCUPANCY_Q0 : PBF_REG_P0_TQ_OCCUPANCY, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_LINES_FREED_CNT_Q0 : PBF_REG_P0_TQ_LINES_FREED_CNT}, {1, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_OCCUPANCY_Q1 : PBF_REG_P1_TQ_OCCUPANCY, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_LINES_FREED_CNT_Q1 : PBF_REG_P1_TQ_LINES_FREED_CNT}, {4, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_OCCUPANCY_LB_Q : PBF_REG_P4_TQ_OCCUPANCY, (CHIP_IS_E3B0(sc)) ? PBF_REG_TQ_LINES_FREED_CNT_LB_Q : PBF_REG_P4_TQ_LINES_FREED_CNT} }; struct pbf_pN_buf_regs buf_regs[] = { {0, (CHIP_IS_E3B0(sc)) ? PBF_REG_INIT_CRD_Q0 : PBF_REG_P0_INIT_CRD, (CHIP_IS_E3B0(sc)) ? PBF_REG_CREDIT_Q0 : PBF_REG_P0_CREDIT, (CHIP_IS_E3B0(sc)) ? PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 : PBF_REG_P0_INTERNAL_CRD_FREED_CNT}, {1, (CHIP_IS_E3B0(sc)) ? PBF_REG_INIT_CRD_Q1 : PBF_REG_P1_INIT_CRD, (CHIP_IS_E3B0(sc)) ? PBF_REG_CREDIT_Q1 : PBF_REG_P1_CREDIT, (CHIP_IS_E3B0(sc)) ? PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 : PBF_REG_P1_INTERNAL_CRD_FREED_CNT}, {4, (CHIP_IS_E3B0(sc)) ? PBF_REG_INIT_CRD_LB_Q : PBF_REG_P4_INIT_CRD, (CHIP_IS_E3B0(sc)) ? PBF_REG_CREDIT_LB_Q : PBF_REG_P4_CREDIT, (CHIP_IS_E3B0(sc)) ? PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q : PBF_REG_P4_INTERNAL_CRD_FREED_CNT}, }; uint32_t i; /* Verify the command queues are flushed P0, P1, P4 */ for (i = 0; i < ARRAY_SIZE(cmd_regs); i++) { bnx2x_pbf_pN_cmd_flushed(sc, &cmd_regs[i], poll_count); } /* Verify the transmission buffers are flushed P0, P1, P4 */ for (i = 0; i < ARRAY_SIZE(buf_regs); i++) { bnx2x_pbf_pN_buf_flushed(sc, &buf_regs[i], poll_count); } } static void bnx2x_hw_enable_status(struct bnx2x_softc *sc) { __rte_unused uint32_t val; val = REG_RD(sc, CFC_REG_WEAK_ENABLE_PF); PMD_DRV_LOG(DEBUG, "CFC_REG_WEAK_ENABLE_PF is 0x%x", val); val = REG_RD(sc, PBF_REG_DISABLE_PF); PMD_DRV_LOG(DEBUG, "PBF_REG_DISABLE_PF is 0x%x", val); val = REG_RD(sc, IGU_REG_PCI_PF_MSI_EN); PMD_DRV_LOG(DEBUG, "IGU_REG_PCI_PF_MSI_EN is 0x%x", val); val = REG_RD(sc, IGU_REG_PCI_PF_MSIX_EN); PMD_DRV_LOG(DEBUG, "IGU_REG_PCI_PF_MSIX_EN is 0x%x", val); val = REG_RD(sc, IGU_REG_PCI_PF_MSIX_FUNC_MASK); PMD_DRV_LOG(DEBUG, "IGU_REG_PCI_PF_MSIX_FUNC_MASK is 0x%x", val); val = REG_RD(sc, PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR); PMD_DRV_LOG(DEBUG, "PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR is 0x%x", val); val = REG_RD(sc, PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR); PMD_DRV_LOG(DEBUG, "PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR is 0x%x", val); val = REG_RD(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); PMD_DRV_LOG(DEBUG, "PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER is 0x%x", val); } /** * bnx2x_pf_flr_clnup * a. re-enable target read on the PF * b. poll cfc per function usgae counter * c. poll the qm perfunction usage counter * d. poll the tm per function usage counter * e. poll the tm per function scan-done indication * f. clear the dmae channel associated wit hthe PF * g. zero the igu 'trailing edge' and 'leading edge' regs (attentions) * h. call the common flr cleanup code with -1 (pf indication) */ static int bnx2x_pf_flr_clnup(struct bnx2x_softc *sc) { uint32_t poll_cnt = bnx2x_flr_clnup_poll_count(sc); /* Re-enable PF target read access */ REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); /* Poll HW usage counters */ if (bnx2x_poll_hw_usage_counters(sc, poll_cnt)) { return -1; } /* Zero the igu 'trailing edge' and 'leading edge' */ /* Send the FW cleanup command */ if (bnx2x_send_final_clnup(sc, (uint8_t) SC_FUNC(sc), poll_cnt)) { return -1; } /* ATC cleanup */ /* Verify TX hw is flushed */ bnx2x_tx_hw_flushed(sc, poll_cnt); /* Wait 100ms (not adjusted according to platform) */ DELAY(100000); /* Verify no pending pci transactions */ if (bnx2x_is_pcie_pending(sc)) { PMD_DRV_LOG(NOTICE, "PCIE Transactions still pending"); } /* Debug */ bnx2x_hw_enable_status(sc); /* * Master enable - Due to WB DMAE writes performed before this * register is re-initialized as part of the regular function init */ REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); return 0; } static int bnx2x_init_hw_func(struct bnx2x_softc *sc) { int port = SC_PORT(sc); int func = SC_FUNC(sc); int init_phase = PHASE_PF0 + func; struct ecore_ilt *ilt = sc->ilt; uint16_t cdu_ilt_start; uint32_t addr, val; uint32_t main_mem_base, main_mem_size, main_mem_prty_clr; int main_mem_width, rc; uint32_t i; PMD_DRV_LOG(DEBUG, "starting func init for func %d", func); /* FLR cleanup */ if (!CHIP_IS_E1x(sc)) { rc = bnx2x_pf_flr_clnup(sc); if (rc) { PMD_DRV_LOG(NOTICE, "FLR cleanup failed!"); return rc; } } /* set MSI reconfigure capability */ if (sc->devinfo.int_block == INT_BLOCK_HC) { addr = (port ? HC_REG_CONFIG_1 : HC_REG_CONFIG_0); val = REG_RD(sc, addr); val |= HC_CONFIG_0_REG_MSI_ATTN_EN_0; REG_WR(sc, addr, val); } ecore_init_block(sc, BLOCK_PXP, init_phase); ecore_init_block(sc, BLOCK_PXP2, init_phase); ilt = sc->ilt; cdu_ilt_start = ilt->clients[ILT_CLIENT_CDU].start; for (i = 0; i < L2_ILT_LINES(sc); i++) { ilt->lines[cdu_ilt_start + i].page = sc->context[i].vcxt; ilt->lines[cdu_ilt_start + i].page_mapping = (phys_addr_t)sc->context[i].vcxt_dma.paddr; ilt->lines[cdu_ilt_start + i].size = sc->context[i].size; } ecore_ilt_init_op(sc, INITOP_SET); REG_WR(sc, PRS_REG_NIC_MODE, 1); if (!CHIP_IS_E1x(sc)) { uint32_t pf_conf = IGU_PF_CONF_FUNC_EN; /* Turn on a single ISR mode in IGU if driver is going to use * INT#x or MSI */ if ((sc->interrupt_mode != INTR_MODE_MSIX) || (sc->interrupt_mode != INTR_MODE_SINGLE_MSIX)) { pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; } /* * Timers workaround bug: function init part. * Need to wait 20msec after initializing ILT, * needed to make sure there are no requests in * one of the PXP internal queues with "old" ILT addresses */ DELAY(20000); /* * Master enable - Due to WB DMAE writes performed before this * register is re-initialized as part of the regular function * init */ REG_WR(sc, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); /* Enable the function in IGU */ REG_WR(sc, IGU_REG_PF_CONFIGURATION, pf_conf); } sc->dmae_ready = 1; ecore_init_block(sc, BLOCK_PGLUE_B, init_phase); if (!CHIP_IS_E1x(sc)) REG_WR(sc, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, func); ecore_init_block(sc, BLOCK_ATC, init_phase); ecore_init_block(sc, BLOCK_DMAE, init_phase); ecore_init_block(sc, BLOCK_NIG, init_phase); ecore_init_block(sc, BLOCK_SRC, init_phase); ecore_init_block(sc, BLOCK_MISC, init_phase); ecore_init_block(sc, BLOCK_TCM, init_phase); ecore_init_block(sc, BLOCK_UCM, init_phase); ecore_init_block(sc, BLOCK_CCM, init_phase); ecore_init_block(sc, BLOCK_XCM, init_phase); ecore_init_block(sc, BLOCK_TSEM, init_phase); ecore_init_block(sc, BLOCK_USEM, init_phase); ecore_init_block(sc, BLOCK_CSEM, init_phase); ecore_init_block(sc, BLOCK_XSEM, init_phase); if (!CHIP_IS_E1x(sc)) REG_WR(sc, QM_REG_PF_EN, 1); if (!CHIP_IS_E1x(sc)) { REG_WR(sc, TSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); REG_WR(sc, USEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); REG_WR(sc, CSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); REG_WR(sc, XSEM_REG_VFPF_ERR_NUM, BNX2X_MAX_NUM_OF_VFS + func); } ecore_init_block(sc, BLOCK_QM, init_phase); ecore_init_block(sc, BLOCK_TM, init_phase); ecore_init_block(sc, BLOCK_DORQ, init_phase); ecore_init_block(sc, BLOCK_BRB1, init_phase); ecore_init_block(sc, BLOCK_PRS, init_phase); ecore_init_block(sc, BLOCK_TSDM, init_phase); ecore_init_block(sc, BLOCK_CSDM, init_phase); ecore_init_block(sc, BLOCK_USDM, init_phase); ecore_init_block(sc, BLOCK_XSDM, init_phase); ecore_init_block(sc, BLOCK_UPB, init_phase); ecore_init_block(sc, BLOCK_XPB, init_phase); ecore_init_block(sc, BLOCK_PBF, init_phase); if (!CHIP_IS_E1x(sc)) REG_WR(sc, PBF_REG_DISABLE_PF, 0); ecore_init_block(sc, BLOCK_CDU, init_phase); ecore_init_block(sc, BLOCK_CFC, init_phase); if (!CHIP_IS_E1x(sc)) REG_WR(sc, CFC_REG_WEAK_ENABLE_PF, 1); if (IS_MF(sc)) { REG_WR(sc, NIG_REG_LLH0_FUNC_EN + port * 8, 1); REG_WR(sc, NIG_REG_LLH0_FUNC_VLAN_ID + port * 8, OVLAN(sc)); } ecore_init_block(sc, BLOCK_MISC_AEU, init_phase); /* HC init per function */ if (sc->devinfo.int_block == INT_BLOCK_HC) { if (CHIP_IS_E1H(sc)) { REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_12 + func * 4, 0); REG_WR(sc, HC_REG_LEADING_EDGE_0 + port * 8, 0); REG_WR(sc, HC_REG_TRAILING_EDGE_0 + port * 8, 0); } ecore_init_block(sc, BLOCK_HC, init_phase); } else { uint32_t num_segs, sb_idx, prod_offset; REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_12 + func * 4, 0); if (!CHIP_IS_E1x(sc)) { REG_WR(sc, IGU_REG_LEADING_EDGE_LATCH, 0); REG_WR(sc, IGU_REG_TRAILING_EDGE_LATCH, 0); } ecore_init_block(sc, BLOCK_IGU, init_phase); if (!CHIP_IS_E1x(sc)) { int dsb_idx = 0; /** * Producer memory: * E2 mode: address 0-135 match to the mapping memory; * 136 - PF0 default prod; 137 - PF1 default prod; * 138 - PF2 default prod; 139 - PF3 default prod; * 140 - PF0 attn prod; 141 - PF1 attn prod; * 142 - PF2 attn prod; 143 - PF3 attn prod; * 144-147 reserved. * * E1.5 mode - In backward compatible mode; * for non default SB; each even line in the memory * holds the U producer and each odd line hold * the C producer. The first 128 producers are for * NDSB (PF0 - 0-31; PF1 - 32-63 and so on). The last 20 * producers are for the DSB for each PF. * Each PF has five segments: (the order inside each * segment is PF0; PF1; PF2; PF3) - 128-131 U prods; * 132-135 C prods; 136-139 X prods; 140-143 T prods; * 144-147 attn prods; */ /* non-default-status-blocks */ num_segs = CHIP_INT_MODE_IS_BC(sc) ? IGU_BC_NDSB_NUM_SEGS : IGU_NORM_NDSB_NUM_SEGS; for (sb_idx = 0; sb_idx < sc->igu_sb_cnt; sb_idx++) { prod_offset = (sc->igu_base_sb + sb_idx) * num_segs; for (i = 0; i < num_segs; i++) { addr = IGU_REG_PROD_CONS_MEMORY + (prod_offset + i) * 4; REG_WR(sc, addr, 0); } /* send consumer update with value 0 */ bnx2x_ack_sb(sc, sc->igu_base_sb + sb_idx, USTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_igu_clear_sb(sc, sc->igu_base_sb + sb_idx); } /* default-status-blocks */ num_segs = CHIP_INT_MODE_IS_BC(sc) ? IGU_BC_DSB_NUM_SEGS : IGU_NORM_DSB_NUM_SEGS; if (CHIP_IS_MODE_4_PORT(sc)) dsb_idx = SC_FUNC(sc); else dsb_idx = SC_VN(sc); prod_offset = (CHIP_INT_MODE_IS_BC(sc) ? IGU_BC_BASE_DSB_PROD + dsb_idx : IGU_NORM_BASE_DSB_PROD + dsb_idx); /* * igu prods come in chunks of E1HVN_MAX (4) - * does not matters what is the current chip mode */ for (i = 0; i < (num_segs * E1HVN_MAX); i += E1HVN_MAX) { addr = IGU_REG_PROD_CONS_MEMORY + (prod_offset + i) * 4; REG_WR(sc, addr, 0); } /* send consumer update with 0 */ if (CHIP_INT_MODE_IS_BC(sc)) { bnx2x_ack_sb(sc, sc->igu_dsb_id, USTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_ack_sb(sc, sc->igu_dsb_id, CSTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_ack_sb(sc, sc->igu_dsb_id, XSTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_ack_sb(sc, sc->igu_dsb_id, TSTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_ack_sb(sc, sc->igu_dsb_id, ATTENTION_ID, 0, IGU_INT_NOP, 1); } else { bnx2x_ack_sb(sc, sc->igu_dsb_id, USTORM_ID, 0, IGU_INT_NOP, 1); bnx2x_ack_sb(sc, sc->igu_dsb_id, ATTENTION_ID, 0, IGU_INT_NOP, 1); } bnx2x_igu_clear_sb(sc, sc->igu_dsb_id); /* !!! these should become driver const once rf-tool supports split-68 const */ REG_WR(sc, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0); REG_WR(sc, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0); REG_WR(sc, IGU_REG_SB_MASK_LSB, 0); REG_WR(sc, IGU_REG_SB_MASK_MSB, 0); REG_WR(sc, IGU_REG_PBA_STATUS_LSB, 0); REG_WR(sc, IGU_REG_PBA_STATUS_MSB, 0); } } /* Reset PCIE errors for debug */ REG_WR(sc, 0x2114, 0xffffffff); REG_WR(sc, 0x2120, 0xffffffff); if (CHIP_IS_E1x(sc)) { main_mem_size = HC_REG_MAIN_MEMORY_SIZE / 2; /*dwords */ main_mem_base = HC_REG_MAIN_MEMORY + SC_PORT(sc) * (main_mem_size * 4); main_mem_prty_clr = HC_REG_HC_PRTY_STS_CLR; main_mem_width = 8; val = REG_RD(sc, main_mem_prty_clr); if (val) { PMD_DRV_LOG(DEBUG, "Parity errors in HC block during function init (0x%x)!", val); } /* Clear "false" parity errors in MSI-X table */ for (i = main_mem_base; i < main_mem_base + main_mem_size * 4; i += main_mem_width) { bnx2x_read_dmae(sc, i, main_mem_width / 4); bnx2x_write_dmae(sc, BNX2X_SP_MAPPING(sc, wb_data), i, main_mem_width / 4); } /* Clear HC parity attention */ REG_RD(sc, main_mem_prty_clr); } /* Enable STORMs SP logging */ REG_WR8(sc, BAR_USTRORM_INTMEM + USTORM_RECORD_SLOW_PATH_OFFSET(SC_FUNC(sc)), 1); REG_WR8(sc, BAR_TSTRORM_INTMEM + TSTORM_RECORD_SLOW_PATH_OFFSET(SC_FUNC(sc)), 1); REG_WR8(sc, BAR_CSTRORM_INTMEM + CSTORM_RECORD_SLOW_PATH_OFFSET(SC_FUNC(sc)), 1); REG_WR8(sc, BAR_XSTRORM_INTMEM + XSTORM_RECORD_SLOW_PATH_OFFSET(SC_FUNC(sc)), 1); elink_phy_probe(&sc->link_params); return 0; } static void bnx2x_link_reset(struct bnx2x_softc *sc) { if (!BNX2X_NOMCP(sc)) { elink_lfa_reset(&sc->link_params, &sc->link_vars); } else { if (!CHIP_REV_IS_SLOW(sc)) { PMD_DRV_LOG(WARNING, "Bootcode is missing - cannot reset link"); } } } static void bnx2x_reset_port(struct bnx2x_softc *sc) { int port = SC_PORT(sc); uint32_t val; /* reset physical Link */ bnx2x_link_reset(sc); REG_WR(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4, 0); /* Do not rcv packets to BRB */ REG_WR(sc, NIG_REG_LLH0_BRB1_DRV_MASK + port * 4, 0x0); /* Do not direct rcv packets that are not for MCP to the BRB */ REG_WR(sc, (port ? NIG_REG_LLH1_BRB1_NOT_MCP : NIG_REG_LLH0_BRB1_NOT_MCP), 0x0); /* Configure AEU */ REG_WR(sc, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port * 4, 0); DELAY(100000); /* Check for BRB port occupancy */ val = REG_RD(sc, BRB1_REG_PORT_NUM_OCC_BLOCKS_0 + port * 4); if (val) { PMD_DRV_LOG(DEBUG, "BRB1 is not empty, %d blocks are occupied", val); } } static void bnx2x_ilt_wr(struct bnx2x_softc *sc, uint32_t index, phys_addr_t addr) { int reg; uint32_t wb_write[2]; reg = PXP2_REG_RQ_ONCHIP_AT_B0 + index * 8; wb_write[0] = ONCHIP_ADDR1(addr); wb_write[1] = ONCHIP_ADDR2(addr); REG_WR_DMAE(sc, reg, wb_write, 2); } static void bnx2x_clear_func_ilt(struct bnx2x_softc *sc, uint32_t func) { uint32_t i, base = FUNC_ILT_BASE(func); for (i = base; i < base + ILT_PER_FUNC; i++) { bnx2x_ilt_wr(sc, i, 0); } } static void bnx2x_reset_func(struct bnx2x_softc *sc) { struct bnx2x_fastpath *fp; int port = SC_PORT(sc); int func = SC_FUNC(sc); int i; /* Disable the function in the FW */ REG_WR8(sc, BAR_XSTRORM_INTMEM + XSTORM_FUNC_EN_OFFSET(func), 0); REG_WR8(sc, BAR_CSTRORM_INTMEM + CSTORM_FUNC_EN_OFFSET(func), 0); REG_WR8(sc, BAR_TSTRORM_INTMEM + TSTORM_FUNC_EN_OFFSET(func), 0); REG_WR8(sc, BAR_USTRORM_INTMEM + USTORM_FUNC_EN_OFFSET(func), 0); /* FP SBs */ FOR_EACH_ETH_QUEUE(sc, i) { fp = &sc->fp[i]; REG_WR8(sc, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(fp->fw_sb_id), SB_DISABLED); } /* SP SB */ REG_WR8(sc, BAR_CSTRORM_INTMEM + CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func), SB_DISABLED); for (i = 0; i < XSTORM_SPQ_DATA_SIZE / 4; i++) { REG_WR(sc, BAR_XSTRORM_INTMEM + XSTORM_SPQ_DATA_OFFSET(func), 0); } /* Configure IGU */ if (sc->devinfo.int_block == INT_BLOCK_HC) { REG_WR(sc, HC_REG_LEADING_EDGE_0 + port * 8, 0); REG_WR(sc, HC_REG_TRAILING_EDGE_0 + port * 8, 0); } else { REG_WR(sc, IGU_REG_LEADING_EDGE_LATCH, 0); REG_WR(sc, IGU_REG_TRAILING_EDGE_LATCH, 0); } if (CNIC_LOADED(sc)) { /* Disable Timer scan */ REG_WR(sc, TM_REG_EN_LINEAR0_TIMER + port * 4, 0); /* * Wait for at least 10ms and up to 2 second for the timers * scan to complete */ for (i = 0; i < 200; i++) { DELAY(10000); if (!REG_RD(sc, TM_REG_LIN0_SCAN_ON + port * 4)) break; } } /* Clear ILT */ bnx2x_clear_func_ilt(sc, func); /* * Timers workaround bug for E2: if this is vnic-3, * we need to set the entire ilt range for this timers. */ if (!CHIP_IS_E1x(sc) && SC_VN(sc) == 3) { struct ilt_client_info ilt_cli; /* use dummy TM client */ memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); ilt_cli.start = 0; ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1; ilt_cli.client_num = ILT_CLIENT_TM; ecore_ilt_boundry_init_op(sc, &ilt_cli, 0); } /* this assumes that reset_port() called before reset_func() */ if (!CHIP_IS_E1x(sc)) { bnx2x_pf_disable(sc); } sc->dmae_ready = 0; } static void bnx2x_release_firmware(struct bnx2x_softc *sc) { rte_free(sc->init_ops); rte_free(sc->init_ops_offsets); rte_free(sc->init_data); rte_free(sc->iro_array); } static int bnx2x_init_firmware(struct bnx2x_softc *sc) { uint32_t len, i; uint8_t *p = sc->firmware; uint32_t off[24]; for (i = 0; i < 24; ++i) off[i] = rte_be_to_cpu_32(*((uint32_t *) sc->firmware + i)); len = off[0]; sc->init_ops = rte_zmalloc("", len, RTE_CACHE_LINE_SIZE); if (!sc->init_ops) goto alloc_failed; bnx2x_data_to_init_ops(p + off[1], sc->init_ops, len); len = off[2]; sc->init_ops_offsets = rte_zmalloc("", len, RTE_CACHE_LINE_SIZE); if (!sc->init_ops_offsets) goto alloc_failed; bnx2x_data_to_init_offsets(p + off[3], sc->init_ops_offsets, len); len = off[4]; sc->init_data = rte_zmalloc("", len, RTE_CACHE_LINE_SIZE); if (!sc->init_data) goto alloc_failed; bnx2x_data_to_init_data(p + off[5], sc->init_data, len); sc->tsem_int_table_data = p + off[7]; sc->tsem_pram_data = p + off[9]; sc->usem_int_table_data = p + off[11]; sc->usem_pram_data = p + off[13]; sc->csem_int_table_data = p + off[15]; sc->csem_pram_data = p + off[17]; sc->xsem_int_table_data = p + off[19]; sc->xsem_pram_data = p + off[21]; len = off[22]; sc->iro_array = rte_zmalloc("", len, RTE_CACHE_LINE_SIZE); if (!sc->iro_array) goto alloc_failed; bnx2x_data_to_iro_array(p + off[23], sc->iro_array, len); return 0; alloc_failed: bnx2x_release_firmware(sc); return -1; } static int cut_gzip_prefix(const uint8_t * zbuf, int len) { #define MIN_PREFIX_SIZE (10) int n = MIN_PREFIX_SIZE; uint16_t xlen; if (!(zbuf[0] == 0x1f && zbuf[1] == 0x8b && zbuf[2] == Z_DEFLATED) || len <= MIN_PREFIX_SIZE) { return -1; } /* optional extra fields are present */ if (zbuf[3] & 0x4) { xlen = zbuf[13]; xlen <<= 8; xlen += zbuf[12]; n += xlen; } /* file name is present */ if (zbuf[3] & 0x8) { while ((zbuf[n++] != 0) && (n < len)) ; } return n; } static int ecore_gunzip(struct bnx2x_softc *sc, const uint8_t * zbuf, int len) { int ret; int data_begin = cut_gzip_prefix(zbuf, len); PMD_DRV_LOG(DEBUG, "ecore_gunzip %d", len); if (data_begin <= 0) { PMD_DRV_LOG(NOTICE, "bad gzip prefix"); return -1; } memset(&zlib_stream, 0, sizeof(zlib_stream)); zlib_stream.next_in = zbuf + data_begin; zlib_stream.avail_in = len - data_begin; zlib_stream.next_out = sc->gz_buf; zlib_stream.avail_out = FW_BUF_SIZE; ret = inflateInit2(&zlib_stream, -MAX_WBITS); if (ret != Z_OK) { PMD_DRV_LOG(NOTICE, "zlib inflateInit2 error"); return ret; } ret = inflate(&zlib_stream, Z_FINISH); if ((ret != Z_STREAM_END) && (ret != Z_OK)) { PMD_DRV_LOG(NOTICE, "zlib inflate error: %d %s", ret, zlib_stream.msg); } sc->gz_outlen = zlib_stream.total_out; if (sc->gz_outlen & 0x3) { PMD_DRV_LOG(NOTICE, "firmware is not aligned. gz_outlen == %d", sc->gz_outlen); } sc->gz_outlen >>= 2; inflateEnd(&zlib_stream); if (ret == Z_STREAM_END) return 0; return ret; } static void ecore_write_dmae_phys_len(struct bnx2x_softc *sc, phys_addr_t phys_addr, uint32_t addr, uint32_t len) { bnx2x_write_dmae_phys_len(sc, phys_addr, addr, len); } void ecore_storm_memset_struct(struct bnx2x_softc *sc, uint32_t addr, size_t size, uint32_t * data) { uint8_t i; for (i = 0; i < size / 4; i++) { REG_WR(sc, addr + (i * 4), data[i]); } } static const char *get_ext_phy_type(uint32_t ext_phy_type) { uint32_t phy_type_idx = ext_phy_type >> 8; static const char *types[] = { "DIRECT", "BNX2X-8071", "BNX2X-8072", "BNX2X-8073", "BNX2X-8705", "BNX2X-8706", "BNX2X-8726", "BNX2X-8481", "SFX-7101", "BNX2X-8727", "BNX2X-8727-NOC", "BNX2X-84823", "NOT_CONN", "FAILURE" }; if (phy_type_idx < 12) return types[phy_type_idx]; else if (PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN == ext_phy_type) return types[12]; else return types[13]; } static const char *get_state(uint32_t state) { uint32_t state_idx = state >> 12; static const char *states[] = { "CLOSED", "OPENING_WAIT4_LOAD", "OPENING_WAIT4_PORT", "OPEN", "CLOSING_WAIT4_HALT", "CLOSING_WAIT4_DELETE", "CLOSING_WAIT4_UNLOAD", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN", "DISABLED", "DIAG", "ERROR", "UNDEFINED" }; if (state_idx <= 0xF) return states[state_idx]; else return states[0x10]; } static const char *get_recovery_state(uint32_t state) { static const char *states[] = { "NONE", "DONE", "INIT", "WAIT", "FAILED", "NIC_LOADING" }; return states[state]; } static const char *get_rx_mode(uint32_t mode) { static const char *modes[] = { "NONE", "NORMAL", "ALLMULTI", "PROMISC", "MAX_MULTICAST", "ERROR" }; if (mode < 0x4) return modes[mode]; else if (BNX2X_MAX_MULTICAST == mode) return modes[4]; else return modes[5]; } #define BNX2X_INFO_STR_MAX 256 static const char *get_bnx2x_flags(uint32_t flags) { int i; static const char *flag[] = { "ONE_PORT ", "NO_ISCSI ", "NO_FCOE ", "NO_WOL ", "USING_DAC ", "USING_MSIX ", "USING_MSI ", "DISABLE_MSI ", "UNKNOWN ", "NO_MCP ", "SAFC_TX_FLAG ", "MF_FUNC_DIS ", "TX_SWITCHING " }; static char flag_str[BNX2X_INFO_STR_MAX]; memset(flag_str, 0, BNX2X_INFO_STR_MAX); for (i = 0; i < 5; i++) if (flags & (1 << i)) { strcat(flag_str, flag[i]); flags ^= (1 << i); } if (flags) { static char unknown[BNX2X_INFO_STR_MAX]; snprintf(unknown, 32, "Unknown flag mask %x", flags); strcat(flag_str, unknown); } return flag_str; } /* * Prints useful adapter info. */ void bnx2x_print_adapter_info(struct bnx2x_softc *sc) { int i = 0; __rte_unused uint32_t ext_phy_type; PMD_INIT_FUNC_TRACE(); if (sc->link_vars.phy_flags & PHY_XGXS_FLAG) ext_phy_type = ELINK_XGXS_EXT_PHY_TYPE(REG_RD(sc, sc-> devinfo.shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config [0].external_phy_config))); else ext_phy_type = ELINK_SERDES_EXT_PHY_TYPE(REG_RD(sc, sc-> devinfo.shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config [0].external_phy_config))); PMD_INIT_LOG(DEBUG, "\n\n===================================\n"); /* Hardware chip info. */ PMD_INIT_LOG(DEBUG, "%10s : %#08x\n", "ASIC", sc->devinfo.chip_id); PMD_INIT_LOG(DEBUG, "%10s : %c%d\n", "Rev", (CHIP_REV(sc) >> 12) + 'A', (CHIP_METAL(sc) >> 4)); /* Bus info. */ PMD_INIT_LOG(DEBUG, "%10s : %d, ", "Bus PCIe", sc->devinfo.pcie_link_width); switch (sc->devinfo.pcie_link_speed) { case 1: PMD_INIT_LOG(DEBUG, "2.5 Gbps\n"); break; case 2: PMD_INIT_LOG(DEBUG, "5 Gbps\n"); break; case 4: PMD_INIT_LOG(DEBUG, "8 Gbps\n"); break; default: PMD_INIT_LOG(DEBUG, "Unknown link speed\n"); } /* Device features. */ PMD_INIT_LOG(DEBUG, "%10s : ", "Flags"); /* Miscellaneous flags. */ if (sc->devinfo.pcie_cap_flags & BNX2X_MSI_CAPABLE_FLAG) { PMD_INIT_LOG(DEBUG, "MSI"); i++; } if (sc->devinfo.pcie_cap_flags & BNX2X_MSIX_CAPABLE_FLAG) { if (i > 0) PMD_INIT_LOG(DEBUG, "|"); PMD_INIT_LOG(DEBUG, "MSI-X"); i++; } PMD_INIT_LOG(DEBUG, "\n"); if (IS_PF(sc)) { PMD_INIT_LOG(DEBUG, "\n%10s : ", "Queues"); switch (sc->sp->rss_rdata.rss_mode) { case ETH_RSS_MODE_DISABLED: PMD_INIT_LOG(DEBUG, "None\n"); break; case ETH_RSS_MODE_REGULAR: PMD_INIT_LOG(DEBUG, "RSS : %d\n", sc->num_queues); break; default: PMD_INIT_LOG(DEBUG, "Unknown\n"); break; } } /* Firmware versions and device features. */ PMD_INIT_LOG(DEBUG, "%10s : %d.%d.%d\n%10s : %s\n", "Firmware", BNX2X_5710_FW_MAJOR_VERSION, BNX2X_5710_FW_MINOR_VERSION, BNX2X_5710_FW_REVISION_VERSION, "Bootcode", sc->devinfo.bc_ver_str); PMD_INIT_LOG(DEBUG, "===================================\n"); PMD_INIT_LOG(DEBUG, "%10s : %u\n", "Bnx2x Func", sc->pcie_func); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "Bnx2x Flags", get_bnx2x_flags(sc->flags)); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "DMAE Is", (sc->dmae_ready ? "Ready" : "Not Ready")); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "OVLAN", (OVLAN(sc) ? "YES" : "NO")); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "MF", (IS_MF(sc) ? "YES" : "NO")); PMD_INIT_LOG(DEBUG, "%10s : %u\n", "MTU", sc->mtu); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "PHY Type", get_ext_phy_type(ext_phy_type)); PMD_INIT_LOG(DEBUG, "%10s : ", "MAC Addr"); for (i = 0; i < 6; i++) PMD_INIT_LOG(DEBUG, "%x%s", sc->link_params.mac_addr[i], i < 5 ? ":" : "\n"); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "RX Mode", get_rx_mode(sc->rx_mode)); PMD_INIT_LOG(DEBUG, "%10s : %s\n", "State", get_state(sc->state)); if (sc->recovery_state) PMD_INIT_LOG(DEBUG, "%10s : %s\n", "Recovery", get_recovery_state(sc->recovery_state)); PMD_INIT_LOG(DEBUG, "%10s : CQ = %lx, EQ = %lx\n", "SPQ Left", sc->cq_spq_left, sc->eq_spq_left); PMD_INIT_LOG(DEBUG, "%10s : %x\n", "Switch", sc->link_params.switch_cfg); PMD_INIT_LOG(DEBUG, "===================================\n\n"); } ================================================ FILE: drivers/net/bnx2x/bnx2x.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __BNX2X_H__ #define __BNX2X_H__ #include "bnx2x_ethdev.h" #if __BYTE_ORDER == __LITTLE_ENDIAN #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN #endif #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN #endif #undef BIG_ENDIAN #undef __BIG_ENDIAN #else /* _BIG_ENDIAN */ #ifndef BIG_ENDIAN #define BIG_ENDIAN #endif #ifndef __BIG_ENDIAN #define __BIG_ENDIAN #endif #undef LITTLE_ENDIAN #undef __LITTLE_ENDIAN #endif #include "ecore_mfw_req.h" #include "ecore_fw_defs.h" #include "ecore_hsi.h" #include "ecore_reg.h" #include "bnx2x_stats.h" #include "bnx2x_vfpf.h" #include "elink.h" #include #define PCIY_PMG PCI_CAP_ID_PM #define PCIY_MSI PCI_CAP_ID_MSI #define PCIY_EXPRESS PCI_CAP_ID_EXP #define PCIY_MSIX PCI_CAP_ID_MSIX #define PCIR_EXPRESS_DEVICE_STA PCI_EXP_TYPE_RC_EC #define PCIM_EXP_STA_TRANSACTION_PND PCI_EXP_DEVSTA_TRPND #define PCIR_EXPRESS_LINK_STA PCI_EXP_LNKSTA #define PCIM_LINK_STA_WIDTH PCI_EXP_LNKSTA_NLW #define PCIM_LINK_STA_SPEED PCI_EXP_LNKSTA_CLS #define PCIR_EXPRESS_DEVICE_CTL PCI_EXP_DEVCTL #define PCIM_EXP_CTL_MAX_PAYLOAD PCI_EXP_DEVCTL_PAYLOAD #define PCIM_EXP_CTL_MAX_READ_REQUEST PCI_EXP_DEVCTL_READRQ #define PCIR_POWER_STATUS PCI_PM_CTRL #define PCIM_PSTAT_DMASK PCI_PM_CTRL_STATE_MASK #define PCIM_PSTAT_PME PCI_PM_CTRL_PME_STATUS #define PCIM_PSTAT_D3 0x3 #define PCIM_PSTAT_PMEENABLE PCI_PM_CTRL_PME_ENABLE #define PCIR_MSIX_CTRL PCI_MSIX_FLAGS #define PCIM_MSIXCTRL_TABLE_SIZE PCI_MSIX_FLAGS_QSIZE #define IFM_10G_CX4 20 /* 10GBase CX4 copper */ #define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */ #define IFM_10G_T 26 /* 10GBase-T - RJ45 */ #define PCIR_EXPRESS_DEVICE_STA PCI_EXP_TYPE_RC_EC #define PCIM_EXP_STA_TRANSACTION_PND PCI_EXP_DEVSTA_TRPND #define PCIR_EXPRESS_LINK_STA PCI_EXP_LNKSTA #define PCIM_LINK_STA_WIDTH PCI_EXP_LNKSTA_NLW #define PCIM_LINK_STA_SPEED PCI_EXP_LNKSTA_CLS #define PCIR_EXPRESS_DEVICE_CTL PCI_EXP_DEVCTL #define PCIM_EXP_CTL_MAX_PAYLOAD PCI_EXP_DEVCTL_PAYLOAD #define PCIM_EXP_CTL_MAX_READ_REQUEST PCI_EXP_DEVCTL_READRQ #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif #ifndef ARRSIZE #define ARRSIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif #ifndef DIV_ROUND_UP #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) #endif #ifndef roundup #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) #endif #ifndef ilog2 static inline int bnx2x_ilog2(int x) { int log = 0; x >>= 1; while(x) { log++; x >>= 1; } return log; } #define ilog2(x) bnx2x_ilog2(x) #endif #include "ecore_sp.h" struct bnx2x_device_type { uint16_t bnx2x_vid; uint16_t bnx2x_did; uint16_t bnx2x_svid; uint16_t bnx2x_sdid; char *bnx2x_name; }; #define RTE_MBUF_DATA_DMA_ADDR(mb) \ ((uint64_t)((mb)->buf_physaddr + (mb)->data_off)) #define BNX2X_PAGE_SHIFT 12 #define BNX2X_PAGE_SIZE (1 << BNX2X_PAGE_SHIFT) #define BNX2X_PAGE_MASK (~(BNX2X_PAGE_SIZE - 1)) #define BNX2X_PAGE_ALIGN(addr) ((addr + BNX2X_PAGE_SIZE - 1) & BNX2X_PAGE_MASK) #if BNX2X_PAGE_SIZE != 4096 #error Page sizes other than 4KB are unsupported! #endif #define U64_LO(addr) ((uint32_t)(((uint64_t)(addr)) & 0xFFFFFFFF)) #define U64_HI(addr) ((uint32_t)(((uint64_t)(addr)) >> 32)) #define HILO_U64(hi, lo) ((((uint64_t)(hi)) << 32) + (lo)) /* dropless fc FW/HW related params */ #define BRB_SIZE(sc) (CHIP_IS_E3(sc) ? 1024 : 512) #define MAX_AGG_QS(sc) ETH_MAX_AGGREGATION_QUEUES_E1H_E2 #define FW_DROP_LEVEL(sc) (3 + MAX_SPQ_PENDING + MAX_AGG_QS(sc)) #define FW_PREFETCH_CNT 16U #define DROPLESS_FC_HEADROOM 100 #ifndef MCLSHIFT #define MCLSHIFT 11 #endif #define MCLBYTES (1 << MCLSHIFT) #if BNX2X_PAGE_SIZE < 2048 #define MJUMPAGESIZE MCLBYTES #elif BNX2X_PAGE_SIZE <= 8192 #define MJUMPAGESIZE BNX2X_PAGE_SIZE #else #define MJUMPAGESIZE (8 * 1024) #endif #define MJUM9BYTES (9 * 1024) #define MJUM16BYTES (16 * 1024) /* * Transmit Buffer Descriptor (tx_bd) definitions* */ /* NUM_TX_PAGES must be a power of 2. */ #define TOTAL_TX_BD_PER_PAGE (BNX2X_PAGE_SIZE / sizeof(union eth_tx_bd_types)) /* 256 */ #define USABLE_TX_BD_PER_PAGE (TOTAL_TX_BD_PER_PAGE - 1) /* 255 */ #define TOTAL_TX_BD(q) (TOTAL_TX_BD_PER_PAGE * q->nb_tx_pages) /* 512 */ #define USABLE_TX_BD(q) (USABLE_TX_BD_PER_PAGE * q->nb_tx_pages) /* 510 */ #define MAX_TX_BD(q) (TOTAL_TX_BD(q) - 1) /* 511 */ #define NEXT_TX_BD(x) \ ((((x) & USABLE_TX_BD_PER_PAGE) == \ (USABLE_TX_BD_PER_PAGE - 1)) ? (x) + 2 : (x) + 1) #define TX_BD(x, q) ((x) & MAX_TX_BD(q)) #define TX_PAGE(x) (((x) & ~USABLE_TX_BD_PER_PAGE) >> 8) #define TX_IDX(x) ((x) & USABLE_TX_BD_PER_PAGE) /* * Trigger pending transmits when the number of available BDs is greater * than 1/8 of the total number of usable BDs. */ #define BNX2X_TX_CLEANUP_THRESHOLD(q) (USABLE_TX_BD(q) / 8) #define BNX2X_TX_TIMEOUT 5 /* * Receive Buffer Descriptor (rx_bd) definitions* */ //#define NUM_RX_PAGES 1 #define TOTAL_RX_BD_PER_PAGE (BNX2X_PAGE_SIZE / sizeof(struct eth_rx_bd)) /* 512 */ #define USABLE_RX_BD_PER_PAGE (TOTAL_RX_BD_PER_PAGE - 2) /* 510 */ #define RX_BD_PER_PAGE_MASK (TOTAL_RX_BD_PER_PAGE - 1) /* 511 */ #define TOTAL_RX_BD(q) (TOTAL_RX_BD_PER_PAGE * q->nb_rx_pages) /* 512 */ #define USABLE_RX_BD(q) (USABLE_RX_BD_PER_PAGE * q->nb_rx_pages) /* 510 */ #define MAX_RX_BD(q) (TOTAL_RX_BD(q) - 1) /* 511 */ #define RX_BD_NEXT_PAGE_DESC_CNT 2 #define NEXT_RX_BD(x) \ ((((x) & RX_BD_PER_PAGE_MASK) == \ (USABLE_RX_BD_PER_PAGE - 1)) ? (x) + 3 : (x) + 1) /* x & 0x3ff */ #define RX_BD(x, q) ((x) & MAX_RX_BD(q)) #define RX_PAGE(x) (((x) & ~RX_BD_PER_PAGE_MASK) >> 9) #define RX_IDX(x) ((x) & RX_BD_PER_PAGE_MASK) /* * Receive Completion Queue definitions* */ //#define NUM_RCQ_PAGES (NUM_RX_PAGES * 4) #define TOTAL_RCQ_ENTRIES_PER_PAGE (BNX2X_PAGE_SIZE / sizeof(union eth_rx_cqe)) /* 128 */ #define USABLE_RCQ_ENTRIES_PER_PAGE (TOTAL_RCQ_ENTRIES_PER_PAGE - 1) /* 127 */ #define TOTAL_RCQ_ENTRIES(q) (TOTAL_RCQ_ENTRIES_PER_PAGE * q->nb_cq_pages) /* 512 */ #define USABLE_RCQ_ENTRIES(q) (USABLE_RCQ_ENTRIES_PER_PAGE * q->nb_cq_pages) /* 508 */ #define MAX_RCQ_ENTRIES(q) (TOTAL_RCQ_ENTRIES(q) - 1) /* 511 */ #define RCQ_NEXT_PAGE_DESC_CNT 1 #define NEXT_RCQ_IDX(x) \ ((((x) & USABLE_RCQ_ENTRIES_PER_PAGE) == \ (USABLE_RCQ_ENTRIES_PER_PAGE - 1)) ? (x) + 2 : (x) + 1) #define CQE_BD_REL \ (sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd)) #define RCQ_BD_PAGES(q) \ (q->nb_rx_pages * CQE_BD_REL) #define RCQ_ENTRY(x, q) ((x) & MAX_RCQ_ENTRIES(q)) #define RCQ_PAGE(x) (((x) & ~USABLE_RCQ_ENTRIES_PER_PAGE) >> 7) #define RCQ_IDX(x) ((x) & USABLE_RCQ_ENTRIES_PER_PAGE) /* * dropless fc calculations for BDs * Number of BDs should be as number of buffers in BRB: * Low threshold takes into account RX_BD_NEXT_PAGE_DESC_CNT * "next" elements on each page */ #define NUM_BD_REQ(sc) \ BRB_SIZE(sc) #define NUM_BD_PG_REQ(sc) \ ((NUM_BD_REQ(sc) + USABLE_RX_BD_PER_PAGE - 1) / USABLE_RX_BD_PER_PAGE) #define BD_TH_LO(sc) \ (NUM_BD_REQ(sc) + \ NUM_BD_PG_REQ(sc) * RX_BD_NEXT_PAGE_DESC_CNT + \ FW_DROP_LEVEL(sc)) #define BD_TH_HI(sc) \ (BD_TH_LO(sc) + DROPLESS_FC_HEADROOM) #define MIN_RX_AVAIL(sc) \ ((sc)->dropless_fc ? BD_TH_HI(sc) + 128 : 128) /* * dropless fc calculations for RCQs * Number of RCQs should be as number of buffers in BRB: * Low threshold takes into account RCQ_NEXT_PAGE_DESC_CNT * "next" elements on each page */ #define NUM_RCQ_REQ(sc) \ BRB_SIZE(sc) #define NUM_RCQ_PG_REQ(sc) \ ((NUM_RCQ_REQ(sc) + USABLE_RCQ_ENTRIES_PER_PAGE - 1) / USABLE_RCQ_ENTRIES_PER_PAGE) #define RCQ_TH_LO(sc) \ (NUM_RCQ_REQ(sc) + \ NUM_RCQ_PG_REQ(sc) * RCQ_NEXT_PAGE_DESC_CNT + \ FW_DROP_LEVEL(sc)) #define RCQ_TH_HI(sc) \ (RCQ_TH_LO(sc) + DROPLESS_FC_HEADROOM) /* Load / Unload modes */ #define LOAD_NORMAL 0 #define LOAD_OPEN 1 #define LOAD_DIAG 2 #define LOAD_LOOPBACK_EXT 3 #define UNLOAD_NORMAL 0 #define UNLOAD_CLOSE 1 #define UNLOAD_RECOVERY 2 /* Some constants... */ //#define MAX_PATH_NUM 2 //#define E2_MAX_NUM_OF_VFS 64 //#define E1H_FUNC_MAX 8 //#define E2_FUNC_MAX 4 /* per path */ #define MAX_VNIC_NUM 4 #define MAX_FUNC_NUM 8 /* common to all chips */ //#define MAX_NDSB HC_SB_MAX_SB_E2 /* max non-default status block */ #define MAX_RSS_CHAINS 16 /* a constant for HW limit */ #define MAX_MSI_VECTOR 8 /* a constant for HW limit */ #define ILT_NUM_PAGE_ENTRIES 3072 /* * 57711 we use whole table since we have 8 functions. * 57712 we have only 4 functions, but use same size per func, so only half * of the table is used. */ #define ILT_PER_FUNC (ILT_NUM_PAGE_ENTRIES / 8) #define FUNC_ILT_BASE(func) (func * ILT_PER_FUNC) /* * the phys address is shifted right 12 bits and has an added * 1=valid bit added to the 53rd bit * then since this is a wide register(TM) * we split it into two 32 bit writes */ #define ONCHIP_ADDR1(x) ((uint32_t)(((uint64_t)x >> 12) & 0xFFFFFFFF)) #define ONCHIP_ADDR2(x) ((uint32_t)((1 << 20) | ((uint64_t)x >> 44))) /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ #define ETH_HLEN 14 #define ETH_OVERHEAD (ETH_HLEN + 8 + 8) #define ETH_MIN_PACKET_SIZE 60 #define ETH_MAX_PACKET_SIZE ETHERMTU /* 1500 */ #define ETH_MAX_JUMBO_PACKET_SIZE 9600 /* TCP with Timestamp Option (32) + IPv6 (40) */ /* max supported alignment is 256 (8 shift) */ #define BNX2X_RX_ALIGN_SHIFT 8 /* FW uses 2 cache lines alignment for start packet and size */ #define BNX2X_FW_RX_ALIGN_START (1 << BNX2X_RX_ALIGN_SHIFT) #define BNX2X_FW_RX_ALIGN_END (1 << BNX2X_RX_ALIGN_SHIFT) #define BNX2X_PXP_DRAM_ALIGN (BNX2X_RX_ALIGN_SHIFT - 5) struct bnx2x_bar { void *base_addr; }; /* Used to manage DMA allocations. */ struct bnx2x_dma { struct bnx2x_softc *sc; phys_addr_t paddr; void *vaddr; int nseg; char msg[RTE_MEMZONE_NAMESIZE - 6]; }; /* attn group wiring */ #define MAX_DYNAMIC_ATTN_GRPS 8 struct attn_route { uint32_t sig[5]; }; struct iro { uint32_t base; uint16_t m1; uint16_t m2; uint16_t m3; uint16_t size; }; union bnx2x_host_hc_status_block { /* pointer to fp status block e2 */ struct host_hc_status_block_e2 *e2_sb; /* pointer to fp status block e1x */ struct host_hc_status_block_e1x *e1x_sb; }; union bnx2x_db_prod { struct doorbell_set_prod data; uint32_t raw; }; struct bnx2x_sw_tx_bd { struct mbuf *m; uint16_t first_bd; uint8_t flags; /* set on the first BD descriptor when there is a split BD */ #define BNX2X_TSO_SPLIT_BD (1 << 0) }; /* * This is the HSI fastpath data structure. There can be up to MAX_RSS_CHAIN * instances of the fastpath structure when using multiple queues. */ struct bnx2x_fastpath { /* pointer back to parent structure */ struct bnx2x_softc *sc; /* status block */ struct bnx2x_dma sb_dma; union bnx2x_host_hc_status_block status_block; phys_addr_t tx_desc_mapping; phys_addr_t rx_desc_mapping; phys_addr_t rx_comp_mapping; uint16_t *sb_index_values; uint16_t *sb_running_index; uint32_t ustorm_rx_prods_offset; uint8_t igu_sb_id; /* status block number in HW */ uint8_t fw_sb_id; /* status block number in FW */ uint32_t rx_buf_size; int mbuf_alloc_size; int state; #define BNX2X_FP_STATE_CLOSED 0x01 #define BNX2X_FP_STATE_IRQ 0x02 #define BNX2X_FP_STATE_OPENING 0x04 #define BNX2X_FP_STATE_OPEN 0x08 #define BNX2X_FP_STATE_HALTING 0x10 #define BNX2X_FP_STATE_HALTED 0x20 /* reference back to this fastpath queue number */ uint8_t index; /* this is also the 'cid' */ #define FP_IDX(fp) (fp->index) /* ethernet client ID (each fastpath set of RX/TX/CQE is a client) */ uint8_t cl_id; #define FP_CL_ID(fp) (fp->cl_id) uint8_t cl_qzone_id; uint16_t fp_hc_idx; union bnx2x_db_prod tx_db; struct tstorm_per_queue_stats old_tclient; struct ustorm_per_queue_stats old_uclient; struct xstorm_per_queue_stats old_xclient; struct bnx2x_eth_q_stats eth_q_stats; struct bnx2x_eth_q_stats_old eth_q_stats_old; /* Pointer to the receive consumer in the status block */ uint16_t *rx_cq_cons_sb; /* Pointer to the transmit consumer in the status block */ uint16_t *tx_cons_sb; /* transmit timeout until chip reset */ int watchdog_timer; }; /* struct bnx2x_fastpath */ #define BNX2X_MAX_NUM_OF_VFS 64 #define BNX2X_VF_ID_INVALID 0xFF /* maximum number of fast-path interrupt contexts */ #define FP_SB_MAX_E1x 16 #define FP_SB_MAX_E2 HC_SB_MAX_SB_E2 union cdu_context { struct eth_context eth; char pad[1024]; }; /* CDU host DB constants */ #define CDU_ILT_PAGE_SZ_HW 2 #define CDU_ILT_PAGE_SZ (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */ #define ILT_PAGE_CIDS (CDU_ILT_PAGE_SZ / sizeof(union cdu_context)) #define CNIC_ISCSI_CID_MAX 256 #define CNIC_FCOE_CID_MAX 2048 #define CNIC_CID_MAX (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX) #define CNIC_ILT_LINES DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS) #define QM_ILT_PAGE_SZ_HW 0 #define QM_ILT_PAGE_SZ (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */ #define QM_CID_ROUND 1024 /* TM (timers) host DB constants */ #define TM_ILT_PAGE_SZ_HW 0 #define TM_ILT_PAGE_SZ (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */ /*#define TM_CONN_NUM (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */ #define TM_CONN_NUM 1024 #define TM_ILT_SZ (8 * TM_CONN_NUM) #define TM_ILT_LINES DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ) /* SRC (Searcher) host DB constants */ #define SRC_ILT_PAGE_SZ_HW 0 #define SRC_ILT_PAGE_SZ (4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */ #define SRC_HASH_BITS 10 #define SRC_CONN_NUM (1 << SRC_HASH_BITS) /* 1024 */ #define SRC_ILT_SZ (sizeof(struct src_ent) * SRC_CONN_NUM) #define SRC_T2_SZ SRC_ILT_SZ #define SRC_ILT_LINES DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ) struct hw_context { struct bnx2x_dma vcxt_dma; union cdu_context *vcxt; //phys_addr_t cxt_mapping; size_t size; }; #define SM_RX_ID 0 #define SM_TX_ID 1 /* defines for multiple tx priority indices */ #define FIRST_TX_ONLY_COS_INDEX 1 #define FIRST_TX_COS_INDEX 0 #define CID_TO_FP(cid, sc) ((cid) % BNX2X_NUM_NON_CNIC_QUEUES(sc)) #define HC_INDEX_ETH_RX_CQ_CONS 1 #define HC_INDEX_OOO_TX_CQ_CONS 4 #define HC_INDEX_ETH_TX_CQ_CONS_COS0 5 #define HC_INDEX_ETH_TX_CQ_CONS_COS1 6 #define HC_INDEX_ETH_TX_CQ_CONS_COS2 7 #define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0 /* congestion management fairness mode */ #define CMNG_FNS_NONE 0 #define CMNG_FNS_MINMAX 1 /* CMNG constants, as derived from system spec calculations */ /* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */ #define DEF_MIN_RATE 100 /* resolution of the rate shaping timer - 400 usec */ #define RS_PERIODIC_TIMEOUT_USEC 400 /* number of bytes in single QM arbitration cycle - * coefficient for calculating the fairness timer */ #define QM_ARB_BYTES 160000 /* resolution of Min algorithm 1:100 */ #define MIN_RES 100 /* how many bytes above threshold for the minimal credit of Min algorithm*/ #define MIN_ABOVE_THRESH 32768 /* fairness algorithm integration time coefficient - * for calculating the actual Tfair */ #define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES) /* memory of fairness algorithm - 2 cycles */ #define FAIR_MEM 2 #define HC_SEG_ACCESS_DEF 0 /* Driver decision 0-3 */ #define HC_SEG_ACCESS_ATTN 4 #define HC_SEG_ACCESS_NORM 0 /* Driver decision 0-1 */ /* * The total number of L2 queues, MSIX vectors and HW contexts (CIDs) is * control by the number of fast-path status blocks supported by the * device (HW/FW). Each fast-path status block (FP-SB) aka non-default * status block represents an independent interrupts context that can * serve a regular L2 networking queue. However special L2 queues such * as the FCoE queue do not require a FP-SB and other components like * the CNIC may consume FP-SB reducing the number of possible L2 queues * * If the maximum number of FP-SB available is X then: * a. If CNIC is supported it consumes 1 FP-SB thus the max number of * regular L2 queues is Y=X-1 * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor) * c. If the FCoE L2 queue is supported the actual number of L2 queues * is Y+1 * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for * slow-path interrupts) or Y+2 if CNIC is supported (one additional * FP interrupt context for the CNIC). * e. The number of HW context (CID count) is always X or X+1 if FCoE * L2 queue is supported. the cid for the FCoE L2 queue is always X. * * So this is quite simple for now as no ULPs are supported yet. :-) */ #define BNX2X_NUM_QUEUES(sc) ((sc)->num_queues) #define BNX2X_NUM_ETH_QUEUES(sc) BNX2X_NUM_QUEUES(sc) #define BNX2X_NUM_NON_CNIC_QUEUES(sc) BNX2X_NUM_QUEUES(sc) #define BNX2X_NUM_RX_QUEUES(sc) BNX2X_NUM_QUEUES(sc) #define FOR_EACH_QUEUE(sc, var) \ for ((var) = 0; (var) < BNX2X_NUM_QUEUES(sc); (var)++) #define FOR_EACH_NONDEFAULT_QUEUE(sc, var) \ for ((var) = 1; (var) < BNX2X_NUM_QUEUES(sc); (var)++) #define FOR_EACH_ETH_QUEUE(sc, var) \ for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(sc); (var)++) #define FOR_EACH_NONDEFAULT_ETH_QUEUE(sc, var) \ for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(sc); (var)++) #define FOR_EACH_COS_IN_TX_QUEUE(sc, var) \ for ((var) = 0; (var) < (sc)->max_cos; (var)++) #define FOR_EACH_CNIC_QUEUE(sc, var) \ for ((var) = BNX2X_NUM_ETH_QUEUES(sc); \ (var) < BNX2X_NUM_QUEUES(sc); \ (var)++) enum { OOO_IDX_OFFSET, FCOE_IDX_OFFSET, FWD_IDX_OFFSET, }; #define FCOE_IDX(sc) (BNX2X_NUM_NON_CNIC_QUEUES(sc) + FCOE_IDX_OFFSET) #define bnx2x_fcoe_fp(sc) (&sc->fp[FCOE_IDX(sc)]) #define bnx2x_fcoe(sc, var) (bnx2x_fcoe_fp(sc)->var) #define bnx2x_fcoe_inner_sp_obj(sc) (&sc->sp_objs[FCOE_IDX(sc)]) #define bnx2x_fcoe_sp_obj(sc, var) (bnx2x_fcoe_inner_sp_obj(sc)->var) #define bnx2x_fcoe_tx(sc, var) (bnx2x_fcoe_fp(sc)->txdata_ptr[FIRST_TX_COS_INDEX]->var) #define OOO_IDX(sc) (BNX2X_NUM_NON_CNIC_QUEUES(sc) + OOO_IDX_OFFSET) #define bnx2x_ooo_fp(sc) (&sc->fp[OOO_IDX(sc)]) #define bnx2x_ooo(sc, var) (bnx2x_ooo_fp(sc)->var) #define bnx2x_ooo_inner_sp_obj(sc) (&sc->sp_objs[OOO_IDX(sc)]) #define bnx2x_ooo_sp_obj(sc, var) (bnx2x_ooo_inner_sp_obj(sc)->var) #define FWD_IDX(sc) (BNX2X_NUM_NON_CNIC_QUEUES(sc) + FWD_IDX_OFFSET) #define bnx2x_fwd_fp(sc) (&sc->fp[FWD_IDX(sc)]) #define bnx2x_fwd(sc, var) (bnx2x_fwd_fp(sc)->var) #define bnx2x_fwd_inner_sp_obj(sc) (&sc->sp_objs[FWD_IDX(sc)]) #define bnx2x_fwd_sp_obj(sc, var) (bnx2x_fwd_inner_sp_obj(sc)->var) #define bnx2x_fwd_txdata(fp) (fp->txdata_ptr[FIRST_TX_COS_INDEX]) #define IS_ETH_FP(fp) ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->sc)) #define IS_FCOE_FP(fp) ((fp)->index == FCOE_IDX((fp)->sc)) #define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(sc)) #define IS_FWD_FP(fp) ((fp)->index == FWD_IDX((fp)->sc)) #define IS_FWD_IDX(idx) ((idx) == FWD_IDX(sc)) #define IS_OOO_FP(fp) ((fp)->index == OOO_IDX((fp)->sc)) #define IS_OOO_IDX(idx) ((idx) == OOO_IDX(sc)) enum { BNX2X_PORT_QUERY_IDX, BNX2X_PF_QUERY_IDX, BNX2X_FCOE_QUERY_IDX, BNX2X_FIRST_QUEUE_QUERY_IDX, }; struct bnx2x_fw_stats_req { struct stats_query_header hdr; struct stats_query_entry query[FP_SB_MAX_E1x + BNX2X_FIRST_QUEUE_QUERY_IDX]; }; struct bnx2x_fw_stats_data { struct stats_counter storm_counters; struct per_port_stats port; struct per_pf_stats pf; struct per_queue_stats queue_stats[1]; }; /* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */ #define BNX2X_IGU_STAS_MSG_VF_CNT 64 #define BNX2X_IGU_STAS_MSG_PF_CNT 4 #define MAX_DMAE_C 8 /* * This is the slowpath data structure. It is mapped into non-paged memory * so that the hardware can access it's contents directly and must be page * aligned. */ struct bnx2x_slowpath { /* used by the DMAE command executer */ struct dmae_command dmae[MAX_DMAE_C]; /* statistics completion */ uint32_t stats_comp; /* firmware defined statistics blocks */ union mac_stats mac_stats; struct nig_stats nig_stats; struct host_port_stats port_stats; struct host_func_stats func_stats; /* DMAE completion value and data source/sink */ uint32_t wb_comp; uint32_t wb_data[4]; union { struct mac_configuration_cmd e1x; struct eth_classify_rules_ramrod_data e2; } mac_rdata; union { struct tstorm_eth_mac_filter_config e1x; struct eth_filter_rules_ramrod_data e2; } rx_mode_rdata; struct eth_rss_update_ramrod_data rss_rdata; union { struct mac_configuration_cmd e1; struct eth_multicast_rules_ramrod_data e2; } mcast_rdata; union { struct function_start_data func_start; struct flow_control_configuration pfc_config; /* for DCBX ramrod */ } func_rdata; /* Queue State related ramrods */ union { struct client_init_ramrod_data init_data; struct client_update_ramrod_data update_data; } q_rdata; /* * AFEX ramrod can not be a part of func_rdata union because these * events might arrive in parallel to other events from func_rdata. * If they were defined in the same union the data can get corrupted. */ struct afex_vif_list_ramrod_data func_afex_rdata; union drv_info_to_mcp drv_info_to_mcp; }; /* struct bnx2x_slowpath */ /* * Port specifc data structure. */ struct bnx2x_port { /* * Port Management Function (for 57711E only). * When this field is set the driver instance is * responsible for managing port specifc * configurations such as handling link attentions. */ uint32_t pmf; /* Ethernet maximum transmission unit. */ uint16_t ether_mtu; uint32_t link_config[ELINK_LINK_CONFIG_SIZE]; uint32_t ext_phy_config; /* Port feature config.*/ uint32_t config; /* Defines the features supported by the PHY. */ uint32_t supported[ELINK_LINK_CONFIG_SIZE]; /* Defines the features advertised by the PHY. */ uint32_t advertising[ELINK_LINK_CONFIG_SIZE]; #define ADVERTISED_10baseT_Half (1 << 1) #define ADVERTISED_10baseT_Full (1 << 2) #define ADVERTISED_100baseT_Half (1 << 3) #define ADVERTISED_100baseT_Full (1 << 4) #define ADVERTISED_1000baseT_Half (1 << 5) #define ADVERTISED_1000baseT_Full (1 << 6) #define ADVERTISED_TP (1 << 7) #define ADVERTISED_FIBRE (1 << 8) #define ADVERTISED_Autoneg (1 << 9) #define ADVERTISED_Asym_Pause (1 << 10) #define ADVERTISED_Pause (1 << 11) #define ADVERTISED_2500baseX_Full (1 << 15) #define ADVERTISED_10000baseT_Full (1 << 16) uint32_t phy_addr; /* * MCP scratchpad address for port specific statistics. * The device is responsible for writing statistcss * back to the MCP for use with management firmware such * as UMP/NC-SI. */ uint32_t port_stx; struct nig_stats old_nig_stats; }; /* struct bnx2x_port */ struct bnx2x_mf_info { uint32_t mf_config[E1HVN_MAX]; uint32_t vnics_per_port; /* 1, 2 or 4 */ uint32_t multi_vnics_mode; /* can be set even if vnics_per_port = 1 */ uint32_t path_has_ovlan; /* MF mode in the path (can be different than the MF mode of the function */ #define IS_MULTI_VNIC(sc) ((sc)->devinfo.mf_info.multi_vnics_mode) #define VNICS_PER_PORT(sc) ((sc)->devinfo.mf_info.vnics_per_port) #define VNICS_PER_PATH(sc) \ ((sc)->devinfo.mf_info.vnics_per_port * \ ((CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) ? 2 : 1 )) uint8_t min_bw[MAX_VNIC_NUM]; uint8_t max_bw[MAX_VNIC_NUM]; uint16_t ext_id; /* vnic outer vlan or VIF ID */ #define VALID_OVLAN(ovlan) ((ovlan) <= 4096) #define INVALID_VIF_ID 0xFFFF #define OVLAN(sc) ((sc)->devinfo.mf_info.ext_id) #define VIF_ID(sc) ((sc)->devinfo.mf_info.ext_id) uint16_t default_vlan; #define NIV_DEFAULT_VLAN(sc) ((sc)->devinfo.mf_info.default_vlan) uint8_t niv_allowed_priorities; #define NIV_ALLOWED_PRIORITIES(sc) ((sc)->devinfo.mf_info.niv_allowed_priorities) uint8_t niv_default_cos; #define NIV_DEFAULT_COS(sc) ((sc)->devinfo.mf_info.niv_default_cos) uint8_t niv_mba_enabled; enum mf_cfg_afex_vlan_mode afex_vlan_mode; #define AFEX_VLAN_MODE(sc) ((sc)->devinfo.mf_info.afex_vlan_mode) int afex_def_vlan_tag; uint32_t pending_max; uint16_t flags; #define MF_INFO_VALID_MAC 0x0001 uint16_t mf_ov; uint8_t mf_mode; /* Switch-Dependent or Switch-Independent */ #define IS_MF(sc) \ (IS_MULTI_VNIC(sc) && \ ((sc)->devinfo.mf_info.mf_mode != 0)) #define IS_MF_SD(sc) \ (IS_MULTI_VNIC(sc) && \ ((sc)->devinfo.mf_info.mf_mode == MULTI_FUNCTION_SD)) #define IS_MF_SI(sc) \ (IS_MULTI_VNIC(sc) && \ ((sc)->devinfo.mf_info.mf_mode == MULTI_FUNCTION_SI)) #define IS_MF_AFEX(sc) \ (IS_MULTI_VNIC(sc) && \ ((sc)->devinfo.mf_info.mf_mode == MULTI_FUNCTION_AFEX)) #define IS_MF_SD_MODE(sc) IS_MF_SD(sc) #define IS_MF_SI_MODE(sc) IS_MF_SI(sc) #define IS_MF_AFEX_MODE(sc) IS_MF_AFEX(sc) uint32_t mf_protos_supported; #define MF_PROTO_SUPPORT_ETHERNET 0x1 #define MF_PROTO_SUPPORT_ISCSI 0x2 #define MF_PROTO_SUPPORT_FCOE 0x4 }; /* struct bnx2x_mf_info */ /* Device information data structure. */ struct bnx2x_devinfo { /* PCIe info */ uint16_t vendor_id; uint16_t device_id; uint16_t subvendor_id; uint16_t subdevice_id; /* * chip_id = 0b'CCCCCCCCCCCCCCCCRRRRMMMMMMMMBBBB' * C = Chip Number (bits 16-31) * R = Chip Revision (bits 12-15) * M = Chip Metal (bits 4-11) * B = Chip Bond ID (bits 0-3) */ uint32_t chip_id; #define CHIP_ID(sc) ((sc)->devinfo.chip_id & 0xffff0000) #define CHIP_NUM(sc) ((sc)->devinfo.chip_id >> 16) /* device ids */ #define CHIP_NUM_57711 0x164f #define CHIP_NUM_57711E 0x1650 #define CHIP_NUM_57712 0x1662 #define CHIP_NUM_57712_MF 0x1663 #define CHIP_NUM_57712_VF 0x166f #define CHIP_NUM_57800 0x168a #define CHIP_NUM_57800_MF 0x16a5 #define CHIP_NUM_57800_VF 0x16a9 #define CHIP_NUM_57810 0x168e #define CHIP_NUM_57810_MF 0x16ae #define CHIP_NUM_57810_VF 0x16af #define CHIP_NUM_57811 0x163d #define CHIP_NUM_57811_MF 0x163e #define CHIP_NUM_57811_VF 0x163f #define CHIP_NUM_57840_OBS 0x168d #define CHIP_NUM_57840_OBS_MF 0x16ab #define CHIP_NUM_57840_4_10 0x16a1 #define CHIP_NUM_57840_2_20 0x16a2 #define CHIP_NUM_57840_MF 0x16a4 #define CHIP_NUM_57840_VF 0x16ad #define CHIP_REV_SHIFT 12 #define CHIP_REV_MASK (0xF << CHIP_REV_SHIFT) #define CHIP_REV(sc) ((sc)->devinfo.chip_id & CHIP_REV_MASK) #define CHIP_REV_Ax (0x0 << CHIP_REV_SHIFT) #define CHIP_REV_Bx (0x1 << CHIP_REV_SHIFT) #define CHIP_REV_Cx (0x2 << CHIP_REV_SHIFT) #define CHIP_REV_IS_SLOW(sc) \ (CHIP_REV(sc) > 0x00005000) #define CHIP_REV_IS_FPGA(sc) \ (CHIP_REV_IS_SLOW(sc) && (CHIP_REV(sc) & 0x00001000)) #define CHIP_REV_IS_EMUL(sc) \ (CHIP_REV_IS_SLOW(sc) && !(CHIP_REV(sc) & 0x00001000)) #define CHIP_REV_IS_ASIC(sc) \ (!CHIP_REV_IS_SLOW(sc)) #define CHIP_METAL(sc) ((sc->devinfo.chip_id) & 0x00000ff0) #define CHIP_BOND_ID(sc) ((sc->devinfo.chip_id) & 0x0000000f) #define CHIP_IS_57711(sc) (CHIP_NUM(sc) == CHIP_NUM_57711) #define CHIP_IS_57711E(sc) (CHIP_NUM(sc) == CHIP_NUM_57711E) #define CHIP_IS_E1H(sc) ((CHIP_IS_57711(sc)) || \ (CHIP_IS_57711E(sc))) #define CHIP_IS_E1x(sc) CHIP_IS_E1H(sc) #define CHIP_IS_57712(sc) (CHIP_NUM(sc) == CHIP_NUM_57712) #define CHIP_IS_57712_MF(sc) (CHIP_NUM(sc) == CHIP_NUM_57712_MF) #define CHIP_IS_57712_VF(sc) (CHIP_NUM(sc) == CHIP_NUM_57712_VF) #define CHIP_IS_E2(sc) (CHIP_IS_57712(sc) || \ CHIP_IS_57712_MF(sc)) #define CHIP_IS_57800(sc) (CHIP_NUM(sc) == CHIP_NUM_57800) #define CHIP_IS_57800_MF(sc) (CHIP_NUM(sc) == CHIP_NUM_57800_MF) #define CHIP_IS_57800_VF(sc) (CHIP_NUM(sc) == CHIP_NUM_57800_VF) #define CHIP_IS_57810(sc) (CHIP_NUM(sc) == CHIP_NUM_57810) #define CHIP_IS_57810_MF(sc) (CHIP_NUM(sc) == CHIP_NUM_57810_MF) #define CHIP_IS_57810_VF(sc) (CHIP_NUM(sc) == CHIP_NUM_57810_VF) #define CHIP_IS_57811(sc) (CHIP_NUM(sc) == CHIP_NUM_57811) #define CHIP_IS_57811_MF(sc) (CHIP_NUM(sc) == CHIP_NUM_57811_MF) #define CHIP_IS_57811_VF(sc) (CHIP_NUM(sc) == CHIP_NUM_57811_VF) #define CHIP_IS_57840(sc) ((CHIP_NUM(sc) == CHIP_NUM_57840_OBS) || \ (CHIP_NUM(sc) == CHIP_NUM_57840_4_10) || \ (CHIP_NUM(sc) == CHIP_NUM_57840_2_20)) #define CHIP_IS_57840_MF(sc) ((CHIP_NUM(sc) == CHIP_NUM_57840_OBS_MF) || \ (CHIP_NUM(sc) == CHIP_NUM_57840_MF)) #define CHIP_IS_57840_VF(sc) (CHIP_NUM(sc) == CHIP_NUM_57840_VF) #define CHIP_IS_E3(sc) (CHIP_IS_57800(sc) || \ CHIP_IS_57800_MF(sc) || \ CHIP_IS_57800_VF(sc) || \ CHIP_IS_57810(sc) || \ CHIP_IS_57810_MF(sc) || \ CHIP_IS_57810_VF(sc) || \ CHIP_IS_57811(sc) || \ CHIP_IS_57811_MF(sc) || \ CHIP_IS_57811_VF(sc) || \ CHIP_IS_57840(sc) || \ CHIP_IS_57840_MF(sc) || \ CHIP_IS_57840_VF(sc)) #define CHIP_IS_E3A0(sc) (CHIP_IS_E3(sc) && \ (CHIP_REV(sc) == CHIP_REV_Ax)) #define CHIP_IS_E3B0(sc) (CHIP_IS_E3(sc) && \ (CHIP_REV(sc) == CHIP_REV_Bx)) #define USES_WARPCORE(sc) (CHIP_IS_E3(sc)) #define CHIP_IS_E2E3(sc) (CHIP_IS_E2(sc) || \ CHIP_IS_E3(sc)) #define CHIP_IS_MF_CAP(sc) (CHIP_IS_57711E(sc) || \ CHIP_IS_57712_MF(sc) || \ CHIP_IS_E3(sc)) #define IS_VF(sc) ((sc)->flags & BNX2X_IS_VF_FLAG) #define IS_PF(sc) (!IS_VF(sc)) /* * This define is used in two main places: * 1. In the early stages of nic_load, to know if to configure Parser/Searcher * to nic-only mode or to offload mode. Offload mode is configured if either * the chip is E1x (where NIC_MODE register is not applicable), or if cnic * already registered for this port (which means that the user wants storage * services). * 2. During cnic-related load, to know if offload mode is already configured * in the HW or needs to be configrued. Since the transition from nic-mode to * offload-mode in HW causes traffic coruption, nic-mode is configured only * in ports on which storage services where never requested. */ #define CONFIGURE_NIC_MODE(sc) (!CHIP_IS_E1x(sc) && !CNIC_ENABLED(sc)) uint8_t chip_port_mode; #define CHIP_4_PORT_MODE 0x0 #define CHIP_2_PORT_MODE 0x1 #define CHIP_PORT_MODE_NONE 0x2 #define CHIP_PORT_MODE(sc) ((sc)->devinfo.chip_port_mode) #define CHIP_IS_MODE_4_PORT(sc) (CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) uint8_t int_block; #define INT_BLOCK_HC 0 #define INT_BLOCK_IGU 1 #define INT_BLOCK_MODE_NORMAL 0 #define INT_BLOCK_MODE_BW_COMP 2 #define CHIP_INT_MODE_IS_NBC(sc) \ (!CHIP_IS_E1x(sc) && \ !((sc)->devinfo.int_block & INT_BLOCK_MODE_BW_COMP)) #define CHIP_INT_MODE_IS_BC(sc) (!CHIP_INT_MODE_IS_NBC(sc)) uint32_t shmem_base; uint32_t shmem2_base; uint32_t bc_ver; char bc_ver_str[32]; uint32_t mf_cfg_base; /* bootcode shmem address in BAR memory */ struct bnx2x_mf_info mf_info; uint32_t flash_size; #define NVRAM_1MB_SIZE 0x20000 #define NVRAM_TIMEOUT_COUNT 30000 #define NVRAM_PAGE_SIZE 256 /* PCIe capability information */ uint32_t pcie_cap_flags; #define BNX2X_PM_CAPABLE_FLAG 0x00000001 #define BNX2X_PCIE_CAPABLE_FLAG 0x00000002 #define BNX2X_MSI_CAPABLE_FLAG 0x00000004 #define BNX2X_MSIX_CAPABLE_FLAG 0x00000008 uint16_t pcie_pm_cap_reg; uint16_t pcie_link_width; uint16_t pcie_link_speed; uint16_t pcie_msi_cap_reg; uint16_t pcie_msix_cap_reg; /* device configuration read from bootcode shared memory */ uint32_t hw_config; uint32_t hw_config2; }; /* struct bnx2x_devinfo */ struct bnx2x_sp_objs { struct ecore_vlan_mac_obj mac_obj; /* MACs object */ struct ecore_queue_sp_obj q_obj; /* Queue State object */ }; /* struct bnx2x_sp_objs */ /* * Data that will be used to create a link report message. We will keep the * data used for the last link report in order to prevent reporting the same * link parameters twice. */ struct bnx2x_link_report_data { uint16_t line_speed; /* Effective line speed */ unsigned long link_report_flags; /* BNX2X_LINK_REPORT_XXX flags */ }; enum { BNX2X_LINK_REPORT_FULL_DUPLEX, BNX2X_LINK_REPORT_LINK_DOWN, BNX2X_LINK_REPORT_RX_FC_ON, BNX2X_LINK_REPORT_TX_FC_ON }; #define BNX2X_RX_CHAIN_PAGE_SZ BNX2X_PAGE_SIZE struct bnx2x_pci_cap { struct bnx2x_pci_cap *next; uint16_t id; uint16_t type; uint16_t addr; }; struct bnx2x_vfdb; /* Top level device private data structure. */ struct bnx2x_softc { void **rx_queues; void **tx_queues; uint32_t max_tx_queues; uint32_t max_rx_queues; const struct rte_pci_device *pci_dev; uint32_t pci_val; struct bnx2x_pci_cap *pci_caps; #define BNX2X_INTRS_POLL_PERIOD 1 void *firmware; uint64_t fw_len; /* MAC address operations */ struct bnx2x_mac_ops mac_ops; /* structures for VF mbox/response/bulletin */ struct bnx2x_vf_mbx_msg *vf2pf_mbox; struct bnx2x_dma vf2pf_mbox_mapping; struct vf_acquire_resp_tlv acquire_resp; struct bnx2x_vf_bulletin *pf2vf_bulletin; struct bnx2x_dma pf2vf_bulletin_mapping; struct bnx2x_vf_bulletin old_bulletin; int media; int state; /* device state */ #define BNX2X_STATE_CLOSED 0x0000 #define BNX2X_STATE_OPENING_WAITING_LOAD 0x1000 #define BNX2X_STATE_OPENING_WAITING_PORT 0x2000 #define BNX2X_STATE_OPEN 0x3000 #define BNX2X_STATE_CLOSING_WAITING_HALT 0x4000 #define BNX2X_STATE_CLOSING_WAITING_DELETE 0x5000 #define BNX2X_STATE_CLOSING_WAITING_UNLOAD 0x6000 #define BNX2X_STATE_DISABLED 0xD000 #define BNX2X_STATE_DIAG 0xE000 #define BNX2X_STATE_ERROR 0xF000 int flags; #define BNX2X_ONE_PORT_FLAG 0x1 #define BNX2X_NO_FCOE_FLAG 0x2 #define BNX2X_NO_WOL_FLAG 0x4 #define BNX2X_NO_MCP_FLAG 0x8 #define BNX2X_NO_ISCSI_OOO_FLAG 0x10 #define BNX2X_NO_ISCSI_FLAG 0x20 #define BNX2X_MF_FUNC_DIS 0x40 #define BNX2X_TX_SWITCHING 0x80 #define BNX2X_IS_VF_FLAG 0x100 #define BNX2X_ONE_PORT(sc) (sc->flags & BNX2X_ONE_PORT_FLAG) #define BNX2X_NOFCOE(sc) (sc->flags & BNX2X_NO_FCOE_FLAG) #define BNX2X_NOMCP(sc) (sc->flags & BNX2X_NO_MCP_FLAG) #define MAX_BARS 5 struct bnx2x_bar bar[MAX_BARS]; /* map BARs 0, 2, 4 */ uint16_t doorbell_size; /* periodic timer callout */ #define PERIODIC_STOP 0 #define PERIODIC_GO 1 volatile unsigned long periodic_flags; struct bnx2x_fastpath fp[MAX_RSS_CHAINS]; struct bnx2x_sp_objs sp_objs[MAX_RSS_CHAINS]; uint8_t unit; /* driver instance number */ int pcie_bus; /* PCIe bus number */ int pcie_device; /* PCIe device/slot number */ int pcie_func; /* PCIe function number */ uint8_t pfunc_rel; /* function relative */ uint8_t pfunc_abs; /* function absolute */ uint8_t path_id; /* function absolute */ #define SC_PATH(sc) (sc->path_id) #define SC_PORT(sc) (sc->pfunc_rel & 1) #define SC_FUNC(sc) (sc->pfunc_rel) #define SC_ABS_FUNC(sc) (sc->pfunc_abs) #define SC_VN(sc) (sc->pfunc_rel >> 1) #define SC_L_ID(sc) (SC_VN(sc) << 2) #define PORT_ID(sc) SC_PORT(sc) #define PATH_ID(sc) SC_PATH(sc) #define VNIC_ID(sc) SC_VN(sc) #define FUNC_ID(sc) SC_FUNC(sc) #define ABS_FUNC_ID(sc) SC_ABS_FUNC(sc) #define SC_FW_MB_IDX_VN(sc, vn) \ (SC_PORT(sc) + (vn) * \ ((CHIP_IS_E1x(sc) || (CHIP_IS_MODE_4_PORT(sc))) ? 2 : 1)) #define SC_FW_MB_IDX(sc) SC_FW_MB_IDX_VN(sc, SC_VN(sc)) int if_capen; /* enabled interface capabilities */ struct bnx2x_devinfo devinfo; char fw_ver_str[32]; char mf_mode_str[32]; char pci_link_str[32]; struct iro *iro_array; int dmae_ready; #define DMAE_READY(sc) (sc->dmae_ready) struct ecore_credit_pool_obj vlans_pool; struct ecore_credit_pool_obj macs_pool; struct ecore_rx_mode_obj rx_mode_obj; struct ecore_mcast_obj mcast_obj; struct ecore_rss_config_obj rss_conf_obj; struct ecore_func_sp_obj func_obj; uint16_t fw_seq; uint16_t fw_drv_pulse_wr_seq; uint32_t func_stx; struct elink_params link_params; struct elink_vars link_vars; uint32_t link_cnt; struct bnx2x_link_report_data last_reported_link; char mac_addr_str[32]; uint32_t tx_ring_size; uint32_t rx_ring_size; int wol; int is_leader; int recovery_state; #define BNX2X_RECOVERY_DONE 1 #define BNX2X_RECOVERY_INIT 2 #define BNX2X_RECOVERY_WAIT 3 #define BNX2X_RECOVERY_FAILED 4 #define BNX2X_RECOVERY_NIC_LOADING 5 uint32_t rx_mode; #define BNX2X_RX_MODE_NONE 0 #define BNX2X_RX_MODE_NORMAL 1 #define BNX2X_RX_MODE_ALLMULTI 2 #define BNX2X_RX_MODE_PROMISC 3 #define BNX2X_MAX_MULTICAST 64 struct bnx2x_port port; struct cmng_init cmng; /* user configs */ uint8_t num_queues; int hc_rx_ticks; int hc_tx_ticks; uint32_t rx_budget; int interrupt_mode; #define INTR_MODE_INTX 0 #define INTR_MODE_MSI 1 #define INTR_MODE_MSIX 2 #define INTR_MODE_SINGLE_MSIX 3 int udp_rss; uint8_t igu_dsb_id; uint8_t igu_base_sb; uint8_t igu_sb_cnt; uint32_t igu_base_addr; uint8_t base_fw_ndsb; #define DEF_SB_IGU_ID 16 #define DEF_SB_ID HC_SP_SB_ID /* default status block */ struct bnx2x_dma def_sb_dma; struct host_sp_status_block *def_sb; uint16_t def_idx; uint16_t def_att_idx; uint32_t attn_state; struct attn_route attn_group[MAX_DYNAMIC_ATTN_GRPS]; /* general SP events - stats query, cfc delete, etc */ #define HC_SP_INDEX_ETH_DEF_CONS 3 /* EQ completions */ #define HC_SP_INDEX_EQ_CONS 7 /* FCoE L2 connection completions */ #define HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS 6 #define HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS 4 /* iSCSI L2 */ #define HC_SP_INDEX_ETH_ISCSI_CQ_CONS 5 #define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS 1 /* event queue */ struct bnx2x_dma eq_dma; union event_ring_elem *eq; uint16_t eq_prod; uint16_t eq_cons; uint16_t *eq_cons_sb; #define NUM_EQ_PAGES 1 /* must be a power of 2 */ #define EQ_DESC_CNT_PAGE (BNX2X_PAGE_SIZE / sizeof(union event_ring_elem)) #define EQ_DESC_MAX_PAGE (EQ_DESC_CNT_PAGE - 1) #define NUM_EQ_DESC (EQ_DESC_CNT_PAGE * NUM_EQ_PAGES) #define EQ_DESC_MASK (NUM_EQ_DESC - 1) #define MAX_EQ_AVAIL (EQ_DESC_MAX_PAGE * NUM_EQ_PAGES - 2) /* depends on EQ_DESC_CNT_PAGE being a power of 2 */ #define NEXT_EQ_IDX(x) \ ((((x) & EQ_DESC_MAX_PAGE) == (EQ_DESC_MAX_PAGE - 1)) ? \ ((x) + 2) : ((x) + 1)) /* depends on the above and on NUM_EQ_PAGES being a power of 2 */ #define EQ_DESC(x) ((x) & EQ_DESC_MASK) /* slow path */ struct bnx2x_dma sp_dma; struct bnx2x_slowpath *sp; unsigned long sp_state; /* slow path queue */ struct bnx2x_dma spq_dma; struct eth_spe *spq; #define SP_DESC_CNT (BNX2X_PAGE_SIZE / sizeof(struct eth_spe)) #define MAX_SP_DESC_CNT (SP_DESC_CNT - 1) #define MAX_SPQ_PENDING 8 uint16_t spq_prod_idx; struct eth_spe *spq_prod_bd; struct eth_spe *spq_last_bd; uint16_t *dsb_sp_prod; volatile unsigned long eq_spq_left; /* COMMON_xxx ramrod credit */ volatile unsigned long cq_spq_left; /* ETH_xxx ramrod credit */ /* fw decompression buffer */ struct bnx2x_dma gz_buf_dma; void *gz_buf; uint32_t gz_outlen; #define GUNZIP_BUF(sc) (sc->gz_buf) #define GUNZIP_OUTLEN(sc) (sc->gz_outlen) #define GUNZIP_PHYS(sc) (phys_addr_t)(sc->gz_buf_dma.paddr) #define FW_BUF_SIZE 0x40000 struct raw_op *init_ops; uint16_t *init_ops_offsets; /* init block offsets inside init_ops */ uint32_t *init_data; /* data blob, 32 bit granularity */ uint32_t init_mode_flags; #define INIT_MODE_FLAGS(sc) (sc->init_mode_flags) /* PRAM blobs - raw data */ const uint8_t *tsem_int_table_data; const uint8_t *tsem_pram_data; const uint8_t *usem_int_table_data; const uint8_t *usem_pram_data; const uint8_t *xsem_int_table_data; const uint8_t *xsem_pram_data; const uint8_t *csem_int_table_data; const uint8_t *csem_pram_data; #define INIT_OPS(sc) (sc->init_ops) #define INIT_OPS_OFFSETS(sc) (sc->init_ops_offsets) #define INIT_DATA(sc) (sc->init_data) #define INIT_TSEM_INT_TABLE_DATA(sc) (sc->tsem_int_table_data) #define INIT_TSEM_PRAM_DATA(sc) (sc->tsem_pram_data) #define INIT_USEM_INT_TABLE_DATA(sc) (sc->usem_int_table_data) #define INIT_USEM_PRAM_DATA(sc) (sc->usem_pram_data) #define INIT_XSEM_INT_TABLE_DATA(sc) (sc->xsem_int_table_data) #define INIT_XSEM_PRAM_DATA(sc) (sc->xsem_pram_data) #define INIT_CSEM_INT_TABLE_DATA(sc) (sc->csem_int_table_data) #define INIT_CSEM_PRAM_DATA(sc) (sc->csem_pram_data) #define PHY_FW_VER_LEN 20 char fw_ver[32]; /* ILT * For max 196 cids (64*3 + non-eth), 32KB ILT page size and 1KB * context size we need 8 ILT entries. */ #define ILT_MAX_L2_LINES 8 struct hw_context context[ILT_MAX_L2_LINES]; struct ecore_ilt *ilt; #define ILT_MAX_LINES 256 /* max supported number of RSS queues: IGU SBs minus one for CNIC */ #define BNX2X_MAX_RSS_COUNT(sc) ((sc)->igu_sb_cnt - CNIC_SUPPORT(sc)) /* max CID count: Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI */ #define BNX2X_L2_MAX_CID(sc) \ (BNX2X_MAX_RSS_COUNT(sc) * ECORE_MULTI_TX_COS + 2 * CNIC_SUPPORT(sc)) #define BNX2X_L2_CID_COUNT(sc) \ (BNX2X_NUM_ETH_QUEUES(sc) * ECORE_MULTI_TX_COS + 2 * CNIC_SUPPORT(sc)) #define L2_ILT_LINES(sc) \ (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(sc), ILT_PAGE_CIDS)) int qm_cid_count; uint8_t dropless_fc; /* total number of FW statistics requests */ uint8_t fw_stats_num; /* * This is a memory buffer that will contain both statistics ramrod * request and data. */ struct bnx2x_dma fw_stats_dma; /* * FW statistics request shortcut (points at the beginning of fw_stats * buffer). */ int fw_stats_req_size; struct bnx2x_fw_stats_req *fw_stats_req; phys_addr_t fw_stats_req_mapping; /* * FW statistics data shortcut (points at the beginning of fw_stats * buffer + fw_stats_req_size). */ int fw_stats_data_size; struct bnx2x_fw_stats_data *fw_stats_data; phys_addr_t fw_stats_data_mapping; /* tracking a pending STAT_QUERY ramrod */ uint16_t stats_pending; /* number of completed statistics ramrods */ uint16_t stats_comp; uint16_t stats_counter; uint8_t stats_init; int stats_state; struct bnx2x_eth_stats eth_stats; struct host_func_stats func_stats; struct bnx2x_eth_stats_old eth_stats_old; struct bnx2x_net_stats_old net_stats_old; struct bnx2x_fw_port_stats_old fw_stats_old; struct dmae_command stats_dmae; /* used by dmae command loader */ int executer_idx; int mtu; /* DCB support on/off */ int dcb_state; #define BNX2X_DCB_STATE_OFF 0 #define BNX2X_DCB_STATE_ON 1 /* DCBX engine mode */ int dcbx_enabled; #define BNX2X_DCBX_ENABLED_OFF 0 #define BNX2X_DCBX_ENABLED_ON_NEG_OFF 1 #define BNX2X_DCBX_ENABLED_ON_NEG_ON 2 #define BNX2X_DCBX_ENABLED_INVALID -1 uint8_t cnic_support; uint8_t cnic_enabled; uint8_t cnic_loaded; #define CNIC_SUPPORT(sc) 0 /* ((sc)->cnic_support) */ #define CNIC_ENABLED(sc) 0 /* ((sc)->cnic_enabled) */ #define CNIC_LOADED(sc) 0 /* ((sc)->cnic_loaded) */ /* multiple tx classes of service */ uint8_t max_cos; #define BNX2X_MAX_PRIORITY 8 /* priority to cos mapping */ uint8_t prio_to_cos[BNX2X_MAX_PRIORITY]; int panic; }; /* struct bnx2x_softc */ /* IOCTL sub-commands for edebug and firmware upgrade */ #define BNX2X_IOC_RD_NVRAM 1 #define BNX2X_IOC_WR_NVRAM 2 #define BNX2X_IOC_STATS_SHOW_NUM 3 #define BNX2X_IOC_STATS_SHOW_STR 4 #define BNX2X_IOC_STATS_SHOW_CNT 5 struct bnx2x_nvram_data { uint32_t op; /* ioctl sub-command */ uint32_t offset; uint32_t len; uint32_t value[1]; /* variable */ }; union bnx2x_stats_show_data { uint32_t op; /* ioctl sub-command */ struct { uint32_t num; /* return number of stats */ uint32_t len; /* length of each string item */ } desc; /* variable length... */ char str[1]; /* holds names of desc.num stats, each desc.len in length */ /* variable length... */ uint64_t stats[1]; /* holds all stats */ }; /* function init flags */ #define FUNC_FLG_RSS 0x0001 #define FUNC_FLG_STATS 0x0002 /* FUNC_FLG_UNMATCHED 0x0004 */ #define FUNC_FLG_SPQ 0x0010 #define FUNC_FLG_LEADING 0x0020 /* PF only */ struct bnx2x_func_init_params { phys_addr_t fw_stat_map; /* (dma) valid if FUNC_FLG_STATS */ phys_addr_t spq_map; /* (dma) valid if FUNC_FLG_SPQ */ uint16_t func_flgs; uint16_t func_id; /* abs function id */ uint16_t pf_id; uint16_t spq_prod; /* valid if FUNC_FLG_SPQ */ }; /* memory resources reside at BARs 0, 2, 4 */ /* Run `pciconf -lb` to see mappings */ #define BAR0 0 #define BAR1 2 #define BAR2 4 #ifdef RTE_LIBRTE_BNX2X_DEBUG uint8_t bnx2x_reg_read8(struct bnx2x_softc *sc, size_t offset); uint16_t bnx2x_reg_read16(struct bnx2x_softc *sc, size_t offset); uint32_t bnx2x_reg_read32(struct bnx2x_softc *sc, size_t offset); void bnx2x_reg_write8(struct bnx2x_softc *sc, size_t offset, uint8_t val); void bnx2x_reg_write16(struct bnx2x_softc *sc, size_t offset, uint16_t val); void bnx2x_reg_write32(struct bnx2x_softc *sc, size_t offset, uint32_t val); #else #define bnx2x_reg_write8(sc, offset, val)\ *((volatile uint8_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val #define bnx2x_reg_write16(sc, offset, val)\ *((volatile uint16_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val #define bnx2x_reg_write32(sc, offset, val)\ *((volatile uint32_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val #define bnx2x_reg_read8(sc, offset)\ (*((volatile uint8_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))) #define bnx2x_reg_read16(sc, offset)\ (*((volatile uint16_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))) #define bnx2x_reg_read32(sc, offset)\ (*((volatile uint32_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))) #endif #define REG_ADDR(sc, offset) (((uint64_t)sc->bar[BAR0].base_addr) + (offset)) #define REG_RD8(sc, offset) bnx2x_reg_read8(sc, (offset)) #define REG_RD16(sc, offset) bnx2x_reg_read16(sc, (offset)) #define REG_RD32(sc, offset) bnx2x_reg_read32(sc, (offset)) #define REG_WR8(sc, offset, val) bnx2x_reg_write8(sc, (offset), val) #define REG_WR16(sc, offset, val) bnx2x_reg_write16(sc, (offset), val) #define REG_WR32(sc, offset, val) bnx2x_reg_write32(sc, (offset), val) #define REG_RD(sc, offset) REG_RD32(sc, offset) #define REG_WR(sc, offset, val) REG_WR32(sc, offset, val) #define BNX2X_SP(sc, var) (&(sc)->sp->var) #define BNX2X_SP_MAPPING(sc, var) \ (sc->sp_dma.paddr + offsetof(struct bnx2x_slowpath, var)) #define BNX2X_FP(sc, nr, var) ((sc)->fp[(nr)].var) #define BNX2X_SP_OBJ(sc, fp) ((sc)->sp_objs[(fp)->index]) #define bnx2x_fp(sc, nr, var) ((sc)->fp[nr].var) #define REG_RD_DMAE(sc, offset, valp, len32) \ do { \ (void)bnx2x_read_dmae(sc, offset, len32); \ (void)rte_memcpy(valp, BNX2X_SP(sc, wb_data[0]), (len32) * 4); \ } while (0) #define REG_WR_DMAE(sc, offset, valp, len32) \ do { \ (void)rte_memcpy(BNX2X_SP(sc, wb_data[0]), valp, (len32) * 4); \ (void)bnx2x_write_dmae(sc, BNX2X_SP_MAPPING(sc, wb_data), offset, len32); \ } while (0) #define REG_WR_DMAE_LEN(sc, offset, valp, len32) \ REG_WR_DMAE(sc, offset, valp, len32) #define REG_RD_DMAE_LEN(sc, offset, valp, len32) \ REG_RD_DMAE(sc, offset, valp, len32) #define VIRT_WR_DMAE_LEN(sc, data, addr, len32, le32_swap) \ do { \ /* if (le32_swap) { */ \ /* PMD_PWARN_LOG(sc, "VIRT_WR_DMAE_LEN with le32_swap=1"); */ \ /* } */ \ rte_memcpy(GUNZIP_BUF(sc), data, len32 * 4); \ ecore_write_big_buf_wb(sc, addr, len32); \ } while (0) #define BNX2X_DB_MIN_SHIFT 3 /* 8 bytes */ #define BNX2X_DB_SHIFT 7 /* 128 bytes */ #if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT) #error "Minimum DB doorbell stride is 8" #endif #define DPM_TRIGGER_TYPE 0x40 /* Doorbell macro */ #define BNX2X_DB_WRITE(db_bar, val) \ *((volatile uint32_t *)(db_bar)) = (val) #define BNX2X_DB_READ(db_bar) \ *((volatile uint32_t *)(db_bar)) #define DOORBELL_ADDR(sc, offset) \ (volatile uint32_t *)(((char *)(sc)->bar[BAR1].base_addr + (offset))) #define DOORBELL(sc, cid, val) \ if (IS_PF(sc)) \ BNX2X_DB_WRITE((DOORBELL_ADDR(sc, sc->doorbell_size * (cid) + DPM_TRIGGER_TYPE)), (val)); \ else \ BNX2X_DB_WRITE((DOORBELL_ADDR(sc, sc->doorbell_size * (cid))), (val)) \ #define SHMEM_ADDR(sc, field) \ (sc->devinfo.shmem_base + offsetof(struct shmem_region, field)) #define SHMEM_RD(sc, field) REG_RD(sc, SHMEM_ADDR(sc, field)) #define SHMEM_RD16(sc, field) REG_RD16(sc, SHMEM_ADDR(sc, field)) #define SHMEM_WR(sc, field, val) REG_WR(sc, SHMEM_ADDR(sc, field), val) #define SHMEM2_ADDR(sc, field) \ (sc->devinfo.shmem2_base + offsetof(struct shmem2_region, field)) #define SHMEM2_HAS(sc, field) \ (sc->devinfo.shmem2_base && (REG_RD(sc, SHMEM2_ADDR(sc, size)) > \ offsetof(struct shmem2_region, field))) #define SHMEM2_RD(sc, field) REG_RD(sc, SHMEM2_ADDR(sc, field)) #define SHMEM2_WR(sc, field, val) REG_WR(sc, SHMEM2_ADDR(sc, field), val) #define MFCFG_ADDR(sc, field) \ (sc->devinfo.mf_cfg_base + offsetof(struct mf_cfg, field)) #define MFCFG_RD(sc, field) REG_RD(sc, MFCFG_ADDR(sc, field)) #define MFCFG_RD16(sc, field) REG_RD16(sc, MFCFG_ADDR(sc, field)) #define MFCFG_WR(sc, field, val) REG_WR(sc, MFCFG_ADDR(sc, field), val) /* DMAE command defines */ #define DMAE_TIMEOUT -1 #define DMAE_PCI_ERROR -2 /* E2 and onward */ #define DMAE_NOT_RDY -3 #define DMAE_PCI_ERR_FLAG 0x80000000 #define DMAE_SRC_PCI 0 #define DMAE_SRC_GRC 1 #define DMAE_DST_NONE 0 #define DMAE_DST_PCI 1 #define DMAE_DST_GRC 2 #define DMAE_COMP_PCI 0 #define DMAE_COMP_GRC 1 #define DMAE_COMP_REGULAR 0 #define DMAE_COM_SET_ERR 1 #define DMAE_CMD_SRC_PCI (DMAE_SRC_PCI << DMAE_COMMAND_SRC_SHIFT) #define DMAE_CMD_SRC_GRC (DMAE_SRC_GRC << DMAE_COMMAND_SRC_SHIFT) #define DMAE_CMD_DST_PCI (DMAE_DST_PCI << DMAE_COMMAND_DST_SHIFT) #define DMAE_CMD_DST_GRC (DMAE_DST_GRC << DMAE_COMMAND_DST_SHIFT) #define DMAE_CMD_C_DST_PCI (DMAE_COMP_PCI << DMAE_COMMAND_C_DST_SHIFT) #define DMAE_CMD_C_DST_GRC (DMAE_COMP_GRC << DMAE_COMMAND_C_DST_SHIFT) #define DMAE_CMD_ENDIANITY_NO_SWAP (0 << DMAE_COMMAND_ENDIANITY_SHIFT) #define DMAE_CMD_ENDIANITY_B_SWAP (1 << DMAE_COMMAND_ENDIANITY_SHIFT) #define DMAE_CMD_ENDIANITY_DW_SWAP (2 << DMAE_COMMAND_ENDIANITY_SHIFT) #define DMAE_CMD_ENDIANITY_B_DW_SWAP (3 << DMAE_COMMAND_ENDIANITY_SHIFT) #define DMAE_CMD_PORT_0 0 #define DMAE_CMD_PORT_1 DMAE_COMMAND_PORT #define DMAE_SRC_PF 0 #define DMAE_SRC_VF 1 #define DMAE_DST_PF 0 #define DMAE_DST_VF 1 #define DMAE_C_SRC 0 #define DMAE_C_DST 1 #define DMAE_LEN32_RD_MAX 0x80 #define DMAE_LEN32_WR_MAX(sc) 0x2000 #define DMAE_COMP_VAL 0x60d0d0ae /* E2 and beyond, upper bit indicates error */ #define MAX_DMAE_C_PER_PORT 8 #define INIT_DMAE_C(sc) ((SC_PORT(sc) * MAX_DMAE_C_PER_PORT) + SC_VN(sc)) #define PMF_DMAE_C(sc) ((SC_PORT(sc) * MAX_DMAE_C_PER_PORT) + E1HVN_MAX) static const uint32_t dmae_reg_go_c[] = { DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3, DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7, DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11, DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15 }; #define ATTN_NIG_FOR_FUNC (1L << 8) #define ATTN_SW_TIMER_4_FUNC (1L << 9) #define GPIO_2_FUNC (1L << 10) #define GPIO_3_FUNC (1L << 11) #define GPIO_4_FUNC (1L << 12) #define ATTN_GENERAL_ATTN_1 (1L << 13) #define ATTN_GENERAL_ATTN_2 (1L << 14) #define ATTN_GENERAL_ATTN_3 (1L << 15) #define ATTN_GENERAL_ATTN_4 (1L << 13) #define ATTN_GENERAL_ATTN_5 (1L << 14) #define ATTN_GENERAL_ATTN_6 (1L << 15) #define ATTN_HARD_WIRED_MASK 0xff00 #define ATTENTION_ID 4 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \ AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR #define MAX_IGU_ATTN_ACK_TO 100 #define STORM_ASSERT_ARRAY_SIZE 50 #define BNX2X_PMF_LINK_ASSERT(sc) \ GENERAL_ATTEN_OFFSET(LINK_SYNC_ATTENTION_BIT_FUNC_0 + SC_FUNC(sc)) #define BNX2X_MC_ASSERT_BITS \ (GENERAL_ATTEN_OFFSET(TSTORM_FATAL_ASSERT_ATTENTION_BIT) | \ GENERAL_ATTEN_OFFSET(USTORM_FATAL_ASSERT_ATTENTION_BIT) | \ GENERAL_ATTEN_OFFSET(CSTORM_FATAL_ASSERT_ATTENTION_BIT) | \ GENERAL_ATTEN_OFFSET(XSTORM_FATAL_ASSERT_ATTENTION_BIT)) #define BNX2X_MCP_ASSERT \ GENERAL_ATTEN_OFFSET(MCP_FATAL_ASSERT_ATTENTION_BIT) #define BNX2X_GRC_TIMEOUT GENERAL_ATTEN_OFFSET(LATCHED_ATTN_TIMEOUT_GRC) #define BNX2X_GRC_RSV (GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCR) | \ GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCT) | \ GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCN) | \ GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCU) | \ GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCP) | \ GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RSVD_GRC)) #define MULTI_MASK 0x7f #define PFS_PER_PORT(sc) \ ((CHIP_PORT_MODE(sc) == CHIP_4_PORT_MODE) ? 2 : 4) #define SC_MAX_VN_NUM(sc) PFS_PER_PORT(sc) #define FIRST_ABS_FUNC_IN_PORT(sc) \ ((CHIP_PORT_MODE(sc) == CHIP_PORT_MODE_NONE) ? \ PORT_ID(sc) : (PATH_ID(sc) + (2 * PORT_ID(sc)))) #define FOREACH_ABS_FUNC_IN_PORT(sc, i) \ for ((i) = FIRST_ABS_FUNC_IN_PORT(sc); \ (i) < MAX_FUNC_NUM; \ (i) += (MAX_FUNC_NUM / PFS_PER_PORT(sc))) #define BNX2X_SWCID_SHIFT 17 #define BNX2X_SWCID_MASK ((0x1 << BNX2X_SWCID_SHIFT) - 1) #define SW_CID(x) (le32toh(x) & BNX2X_SWCID_MASK) #define CQE_CMD(x) (le32toh(x) >> COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT) #define CQE_TYPE(cqe_fp_flags) ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE) #define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG) #define CQE_TYPE_STOP(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG) #define CQE_TYPE_SLOW(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD) #define CQE_TYPE_FAST(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH) /* must be used on a CID before placing it on a HW ring */ #define HW_CID(sc, x) \ ((SC_PORT(sc) << 23) | (SC_VN(sc) << BNX2X_SWCID_SHIFT) | (x)) #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 #define SPEED_2500 2500 #define SPEED_10000 10000 #define PCI_PM_D0 1 #define PCI_PM_D3hot 2 int bnx2x_test_bit(int nr, volatile unsigned long * addr); void bnx2x_set_bit(unsigned int nr, volatile unsigned long * addr); void bnx2x_clear_bit(int nr, volatile unsigned long * addr); int bnx2x_test_and_clear_bit(int nr, volatile unsigned long * addr); int bnx2x_cmpxchg(volatile int *addr, int old, int new); int bnx2x_dma_alloc(struct bnx2x_softc *sc, size_t size, struct bnx2x_dma *dma, const char *msg, uint32_t align); uint32_t bnx2x_dmae_opcode_add_comp(uint32_t opcode, uint8_t comp_type); uint32_t bnx2x_dmae_opcode_clr_src_reset(uint32_t opcode); uint32_t bnx2x_dmae_opcode(struct bnx2x_softc *sc, uint8_t src_type, uint8_t dst_type, uint8_t with_comp, uint8_t comp_type); void bnx2x_post_dmae(struct bnx2x_softc *sc, struct dmae_command *dmae, int idx); void bnx2x_read_dmae(struct bnx2x_softc *sc, uint32_t src_addr, uint32_t len32); void bnx2x_write_dmae(struct bnx2x_softc *sc, phys_addr_t dma_addr, uint32_t dst_addr, uint32_t len32); void bnx2x_set_ctx_validation(struct bnx2x_softc *sc, struct eth_context *cxt, uint32_t cid); void bnx2x_update_coalesce_sb_index(struct bnx2x_softc *sc, uint8_t fw_sb_id, uint8_t sb_index, uint8_t disable, uint16_t usec); int bnx2x_sp_post(struct bnx2x_softc *sc, int command, int cid, uint32_t data_hi, uint32_t data_lo, int cmd_type); void ecore_init_e1h_firmware(struct bnx2x_softc *sc); void ecore_init_e2_firmware(struct bnx2x_softc *sc); void ecore_storm_memset_struct(struct bnx2x_softc *sc, uint32_t addr, size_t size, uint32_t *data); #define CATC_TRIGGER(sc, data) REG_WR((sc), 0x2000, (data)); #define CATC_TRIGGER_START(sc) CATC_TRIGGER((sc), 0xcafecafe) #define BNX2X_MAC_FMT "%pM" #define BNX2X_MAC_PRN_LIST(mac) (mac) /***********/ /* INLINES */ /***********/ static inline uint32_t reg_poll(struct bnx2x_softc *sc, uint32_t reg, uint32_t expected, int ms, int wait) { uint32_t val; do { val = REG_RD(sc, reg); if (val == expected) { break; } ms -= wait; DELAY(wait * 1000); } while (ms > 0); return val; } static inline void bnx2x_update_fp_sb_idx(struct bnx2x_fastpath *fp) { mb(); /* status block is written to by the chip */ fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID]; } static inline void bnx2x_igu_ack_sb_gen(struct bnx2x_softc *sc, uint8_t segment, uint16_t index, uint8_t op, uint8_t update, uint32_t igu_addr) { struct igu_regular cmd_data = {0}; cmd_data.sb_id_and_flags = ((index << IGU_REGULAR_SB_INDEX_SHIFT) | (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) | (update << IGU_REGULAR_BUPDATE_SHIFT) | (op << IGU_REGULAR_ENABLE_INT_SHIFT)); REG_WR(sc, igu_addr, cmd_data.sb_id_and_flags); /* Make sure that ACK is written */ mb(); } static inline void bnx2x_hc_ack_sb(struct bnx2x_softc *sc, uint8_t sb_id, uint8_t storm, uint16_t index, uint8_t op, uint8_t update) { uint32_t hc_addr = (HC_REG_COMMAND_REG + SC_PORT(sc) * 32 + COMMAND_REG_INT_ACK); union igu_ack_register igu_ack; igu_ack.sb.status_block_index = index; igu_ack.sb.sb_id_and_flags = ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) | (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) | (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) | (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT)); REG_WR(sc, hc_addr, igu_ack.raw_data); /* Make sure that ACK is written */ mb(); } static inline uint32_t bnx2x_hc_ack_int(struct bnx2x_softc *sc) { uint32_t hc_addr = (HC_REG_COMMAND_REG + SC_PORT(sc) * 32 + COMMAND_REG_SIMD_MASK); uint32_t result = REG_RD(sc, hc_addr); mb(); return result; } static inline uint32_t bnx2x_igu_ack_int(struct bnx2x_softc *sc) { uint32_t igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER * 8); uint32_t result = REG_RD(sc, igu_addr); /* PMD_PDEBUG_LOG(sc, DBG_INTR, "read 0x%08x from IGU addr 0x%x", result, igu_addr); */ mb(); return result; } static inline uint32_t bnx2x_ack_int(struct bnx2x_softc *sc) { mb(); if (sc->devinfo.int_block == INT_BLOCK_HC) { return bnx2x_hc_ack_int(sc); } else { return bnx2x_igu_ack_int(sc); } } static inline int func_by_vn(struct bnx2x_softc *sc, int vn) { return (2 * vn + SC_PORT(sc)); } /* * send notification to other functions. */ static inline void bnx2x_link_sync_notify(struct bnx2x_softc *sc) { int func, vn; /* Set the attention towards other drivers on the same port */ for (vn = VN_0; vn < SC_MAX_VN_NUM(sc); vn++) { if (vn == SC_VN(sc)) continue; func = func_by_vn(sc, vn); REG_WR(sc, MISC_REG_AEU_GENERAL_ATTN_0 + (LINK_SYNC_ATTENTION_BIT_FUNC_0 + func) * 4, 1); } } /* * Statistics ID are global per chip/path, while Client IDs for E1x * are per port. */ static inline uint8_t bnx2x_stats_id(struct bnx2x_fastpath *fp) { struct bnx2x_softc *sc = fp->sc; if (!CHIP_IS_E1x(sc)) { return fp->cl_id; } return (fp->cl_id + SC_PORT(sc) * FP_SB_MAX_E1x); } int bnx2x_init(struct bnx2x_softc *sc); void bnx2x_load_firmware(struct bnx2x_softc *sc); int bnx2x_attach(struct bnx2x_softc *sc); int bnx2x_nic_unload(struct bnx2x_softc *sc, uint32_t unload_mode, uint8_t keep_link); int bnx2x_alloc_hsi_mem(struct bnx2x_softc *sc); int bnx2x_alloc_ilt_mem(struct bnx2x_softc *sc); void bnx2x_free_ilt_mem(struct bnx2x_softc *sc); void bnx2x_dump_tx_chain(struct bnx2x_fastpath * fp, int bd_prod, int count); int bnx2x_tx_encap(struct bnx2x_tx_queue *txq, struct rte_mbuf **m_head, int m_pkts); uint8_t bnx2x_txeof(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp); void bnx2x_print_adapter_info(struct bnx2x_softc *sc); int bnx2x_intr_legacy(struct bnx2x_softc *sc, int scan_fp); void bnx2x_link_status_update(struct bnx2x_softc *sc); int bnx2x_complete_sp(struct bnx2x_softc *sc); int bnx2x_set_storm_rx_mode(struct bnx2x_softc *sc); void bnx2x_periodic_callout(struct bnx2x_softc *sc); int bnx2x_vf_get_resources(struct bnx2x_softc *sc, uint8_t tx_count, uint8_t rx_count); void bnx2x_vf_close(struct bnx2x_softc *sc); int bnx2x_vf_init(struct bnx2x_softc *sc); void bnx2x_vf_unload(struct bnx2x_softc *sc); int bnx2x_vf_setup_queue(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, int leading); void bnx2x_free_hsi_mem(struct bnx2x_softc *sc); int bnx2x_vf_set_rx_mode(struct bnx2x_softc *sc); int bnx2x_fill_accept_flags(struct bnx2x_softc *sc, uint32_t rx_mode, unsigned long *rx_accept_flags, unsigned long *tx_accept_flags); int bnx2x_check_bull(struct bnx2x_softc *sc); //#define BNX2X_PULSE #define BNX2X_PCI_CAP 1 #define BNX2X_PCI_ECAP 2 static inline struct bnx2x_pci_cap* pci_find_cap(struct bnx2x_softc *sc, uint8_t id, uint8_t type) { struct bnx2x_pci_cap *cap = sc->pci_caps; while (cap) { if (cap->id == id && cap->type == type) return cap; cap = cap->next; } return NULL; } static inline int is_valid_ether_addr(uint8_t *addr) { if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) return 0; else return 1; } static inline void bnx2x_set_rx_mode(struct bnx2x_softc *sc) { if (sc->state == BNX2X_STATE_OPEN) { if (IS_PF(sc)) { bnx2x_set_storm_rx_mode(sc); } else { sc->rx_mode = BNX2X_RX_MODE_PROMISC; bnx2x_vf_set_rx_mode(sc); } } else { PMD_DRV_LOG(NOTICE, "Card is not ready to change mode"); } } static inline int pci_read(struct bnx2x_softc *sc, size_t addr, void *val, uint8_t size) { if (rte_eal_pci_read_config(sc->pci_dev, val, size, addr) <= 0) { PMD_DRV_LOG(ERR, "Can't read from PCI config space"); return ENXIO; } return 0; } static inline int pci_write_word(struct bnx2x_softc *sc, size_t addr, off_t val) { uint16_t val16 = val; if (rte_eal_pci_write_config(sc->pci_dev, &val16, sizeof(val16), addr) <= 0) { PMD_DRV_LOG(ERR, "Can't write to PCI config space"); return ENXIO; } return 0; } static inline int pci_write_long(struct bnx2x_softc *sc, size_t addr, off_t val) { uint32_t val32 = val; if (rte_eal_pci_write_config(sc->pci_dev, &val32, sizeof(val32), addr) <= 0) { PMD_DRV_LOG(ERR, "Can't write to PCI config space"); return ENXIO; } return 0; } #endif /* __BNX2X_H__ */ ================================================ FILE: drivers/net/bnx2x/bnx2x_ethdev.c ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #include "bnx2x.h" #include "bnx2x_rxtx.h" #include /* * The set of PCI devices this driver supports */ static struct rte_pci_id pci_id_bnx2x_map[] = { #define RTE_PCI_DEV_ID_DECL_BNX2X(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, } }; static struct rte_pci_id pci_id_bnx2xvf_map[] = { #define RTE_PCI_DEV_ID_DECL_BNX2XVF(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, } }; static void bnx2x_link_update(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); bnx2x_link_status_update(sc); mb(); dev->data->dev_link.link_speed = sc->link_vars.line_speed; switch (sc->link_vars.duplex) { case DUPLEX_FULL: dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; break; case DUPLEX_HALF: dev->data->dev_link.link_duplex = ETH_LINK_HALF_DUPLEX; break; default: dev->data->dev_link.link_duplex = ETH_LINK_AUTONEG_DUPLEX; } dev->data->dev_link.link_status = sc->link_vars.link_up; } static void bnx2x_interrupt_action(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; uint32_t link_status; PMD_DRV_LOG(INFO, "Interrupt handled"); if (bnx2x_intr_legacy(sc, 0)) DELAY_MS(250); if (sc->periodic_flags & PERIODIC_GO) bnx2x_periodic_callout(sc); link_status = REG_RD(sc, sc->link_params.shmem_base + offsetof(struct shmem_region, port_mb[sc->link_params.port].link_status)); if ((link_status & LINK_STATUS_LINK_UP) != dev->data->dev_link.link_status) bnx2x_link_update(dev); } static __rte_unused void bnx2x_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; bnx2x_interrupt_action(dev); rte_intr_enable(&(dev->pci_dev->intr_handle)); } /* * Devops - helper functions can be called from user application */ static int bnx2x_dev_configure(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; int mp_ncpus = sysconf(_SC_NPROCESSORS_CONF); int ret; PMD_INIT_FUNC_TRACE(); if (dev->data->dev_conf.rxmode.jumbo_frame) sc->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len; if (dev->data->nb_tx_queues > dev->data->nb_rx_queues) { PMD_DRV_LOG(ERR, "The number of TX queues is greater than number of RX queues"); return -EINVAL; } sc->num_queues = MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues); if (sc->num_queues > mp_ncpus) { PMD_DRV_LOG(ERR, "The number of queues is more than number of CPUs"); return -EINVAL; } PMD_DRV_LOG(DEBUG, "num_queues=%d, mtu=%d", sc->num_queues, sc->mtu); /* allocate ilt */ if (bnx2x_alloc_ilt_mem(sc) != 0) { PMD_DRV_LOG(ERR, "bnx2x_alloc_ilt_mem was failed"); return -ENXIO; } /* allocate the host hardware/software hsi structures */ if (bnx2x_alloc_hsi_mem(sc) != 0) { PMD_DRV_LOG(ERR, "bnx2x_alloc_hsi_mem was failed"); bnx2x_free_ilt_mem(sc); return -ENXIO; } if (IS_VF(sc)) { if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_mbx_msg), &sc->vf2pf_mbox_mapping, "vf2pf_mbox", RTE_CACHE_LINE_SIZE) != 0) return -ENOMEM; sc->vf2pf_mbox = (struct bnx2x_vf_mbx_msg *)sc->vf2pf_mbox_mapping.vaddr; if (bnx2x_dma_alloc(sc, sizeof(struct bnx2x_vf_bulletin), &sc->pf2vf_bulletin_mapping, "vf2pf_bull", RTE_CACHE_LINE_SIZE) != 0) return -ENOMEM; sc->pf2vf_bulletin = (struct bnx2x_vf_bulletin *)sc->pf2vf_bulletin_mapping.vaddr; ret = bnx2x_vf_get_resources(sc, sc->num_queues, sc->num_queues); if (ret) return ret; } return 0; } static int bnx2x_dev_start(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; int ret = 0; PMD_INIT_FUNC_TRACE(); ret = bnx2x_init(sc); if (ret) { PMD_DRV_LOG(DEBUG, "bnx2x_init failed (%d)", ret); return -1; } if (IS_PF(sc)) { rte_intr_callback_register(&(dev->pci_dev->intr_handle), bnx2x_interrupt_handler, (void *)dev); if(rte_intr_enable(&(dev->pci_dev->intr_handle))) PMD_DRV_LOG(ERR, "rte_intr_enable failed"); } ret = bnx2x_dev_rx_init(dev); if (ret != 0) { PMD_DRV_LOG(DEBUG, "bnx2x_dev_rx_init returned error code"); return -3; } /* Print important adapter info for the user. */ bnx2x_print_adapter_info(sc); DELAY_MS(2500); return ret; } static void bnx2x_dev_stop(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; int ret = 0; PMD_INIT_FUNC_TRACE(); if (IS_PF(sc)) { rte_intr_disable(&(dev->pci_dev->intr_handle)); rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), bnx2x_interrupt_handler, (void *)dev); } ret = bnx2x_nic_unload(sc, UNLOAD_NORMAL, FALSE); if (ret) { PMD_DRV_LOG(DEBUG, "bnx2x_nic_unload failed (%d)", ret); return; } return; } static void bnx2x_dev_close(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); if (IS_VF(sc)) bnx2x_vf_close(sc); bnx2x_dev_clear_queues(dev); memset(&(dev->data->dev_link), 0 , sizeof(struct rte_eth_link)); /* free the host hardware/software hsi structures */ bnx2x_free_hsi_mem(sc); /* free ilt */ bnx2x_free_ilt_mem(sc); } static void bnx2x_promisc_enable(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); sc->rx_mode = BNX2X_RX_MODE_PROMISC; bnx2x_set_rx_mode(sc); } static void bnx2x_promisc_disable(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); sc->rx_mode = BNX2X_RX_MODE_NORMAL; bnx2x_set_rx_mode(sc); } static void bnx2x_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); sc->rx_mode = BNX2X_RX_MODE_ALLMULTI; bnx2x_set_rx_mode(sc); } static void bnx2x_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); sc->rx_mode = BNX2X_RX_MODE_NORMAL; bnx2x_set_rx_mode(sc); } static int bnx2x_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) { PMD_INIT_FUNC_TRACE(); int old_link_status = dev->data->dev_link.link_status; bnx2x_link_update(dev); return old_link_status == dev->data->dev_link.link_status ? -1 : 0; } static int bnx2xvf_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) { int old_link_status = dev->data->dev_link.link_status; struct bnx2x_softc *sc = dev->data->dev_private; bnx2x_link_update(dev); bnx2x_check_bull(sc); if (sc->old_bulletin.valid_bitmap & (1 << CHANNEL_DOWN)) { PMD_DRV_LOG(ERR, "PF indicated channel is down." "VF device is no longer operational"); dev->data->dev_link.link_status = 0; } return old_link_status == dev->data->dev_link.link_status ? -1 : 0; } static void bnx2x_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct bnx2x_softc *sc = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); bnx2x_stats_handle(sc, STATS_EVENT_UPDATE); memset(stats, 0, sizeof (struct rte_eth_stats)); stats->ipackets = HILO_U64(sc->eth_stats.total_unicast_packets_received_hi, sc->eth_stats.total_unicast_packets_received_lo) + HILO_U64(sc->eth_stats.total_multicast_packets_received_hi, sc->eth_stats.total_multicast_packets_received_lo) + HILO_U64(sc->eth_stats.total_broadcast_packets_received_hi, sc->eth_stats.total_broadcast_packets_received_lo); stats->opackets = HILO_U64(sc->eth_stats.total_unicast_packets_transmitted_hi, sc->eth_stats.total_unicast_packets_transmitted_lo) + HILO_U64(sc->eth_stats.total_multicast_packets_transmitted_hi, sc->eth_stats.total_multicast_packets_transmitted_lo) + HILO_U64(sc->eth_stats.total_broadcast_packets_transmitted_hi, sc->eth_stats.total_broadcast_packets_transmitted_lo); stats->ibytes = HILO_U64(sc->eth_stats.total_bytes_received_hi, sc->eth_stats.total_bytes_received_lo); stats->obytes = HILO_U64(sc->eth_stats.total_bytes_transmitted_hi, sc->eth_stats.total_bytes_transmitted_lo); stats->ierrors = HILO_U64(sc->eth_stats.error_bytes_received_hi, sc->eth_stats.error_bytes_received_lo); stats->oerrors = 0; stats->rx_nombuf = HILO_U64(sc->eth_stats.no_buff_discard_hi, sc->eth_stats.no_buff_discard_lo); } static void bnx2x_dev_infos_get(struct rte_eth_dev *dev, __rte_unused struct rte_eth_dev_info *dev_info) { struct bnx2x_softc *sc = dev->data->dev_private; dev_info->max_rx_queues = sc->max_rx_queues; dev_info->max_tx_queues = sc->max_tx_queues; dev_info->min_rx_bufsize = BNX2X_MIN_RX_BUF_SIZE; dev_info->max_rx_pktlen = BNX2X_MAX_RX_PKT_LEN; dev_info->max_mac_addrs = BNX2X_MAX_MAC_ADDRS; } static void bnx2x_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool) { struct bnx2x_softc *sc = dev->data->dev_private; if (sc->mac_ops.mac_addr_add) sc->mac_ops.mac_addr_add(dev, mac_addr, index, pool); } static void bnx2x_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) { struct bnx2x_softc *sc = dev->data->dev_private; if (sc->mac_ops.mac_addr_remove) sc->mac_ops.mac_addr_remove(dev, index); } static struct eth_dev_ops bnx2x_eth_dev_ops = { .dev_configure = bnx2x_dev_configure, .dev_start = bnx2x_dev_start, .dev_stop = bnx2x_dev_stop, .dev_close = bnx2x_dev_close, .promiscuous_enable = bnx2x_promisc_enable, .promiscuous_disable = bnx2x_promisc_disable, .allmulticast_enable = bnx2x_dev_allmulticast_enable, .allmulticast_disable = bnx2x_dev_allmulticast_disable, .link_update = bnx2x_dev_link_update, .stats_get = bnx2x_dev_stats_get, .dev_infos_get = bnx2x_dev_infos_get, .rx_queue_setup = bnx2x_dev_rx_queue_setup, .rx_queue_release = bnx2x_dev_rx_queue_release, .tx_queue_setup = bnx2x_dev_tx_queue_setup, .tx_queue_release = bnx2x_dev_tx_queue_release, .mac_addr_add = bnx2x_mac_addr_add, .mac_addr_remove = bnx2x_mac_addr_remove, }; /* * dev_ops for virtual function */ static struct eth_dev_ops bnx2xvf_eth_dev_ops = { .dev_configure = bnx2x_dev_configure, .dev_start = bnx2x_dev_start, .dev_stop = bnx2x_dev_stop, .dev_close = bnx2x_dev_close, .promiscuous_enable = bnx2x_promisc_enable, .promiscuous_disable = bnx2x_promisc_disable, .allmulticast_enable = bnx2x_dev_allmulticast_enable, .allmulticast_disable = bnx2x_dev_allmulticast_disable, .link_update = bnx2xvf_dev_link_update, .stats_get = bnx2x_dev_stats_get, .dev_infos_get = bnx2x_dev_infos_get, .rx_queue_setup = bnx2x_dev_rx_queue_setup, .rx_queue_release = bnx2x_dev_rx_queue_release, .tx_queue_setup = bnx2x_dev_tx_queue_setup, .tx_queue_release = bnx2x_dev_tx_queue_release, .mac_addr_add = bnx2x_mac_addr_add, .mac_addr_remove = bnx2x_mac_addr_remove, }; static int bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf) { int ret = 0; struct rte_pci_device *pci_dev; struct bnx2x_softc *sc; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = is_vf ? &bnx2xvf_eth_dev_ops : &bnx2x_eth_dev_ops; pci_dev = eth_dev->pci_dev; sc = eth_dev->data->dev_private; sc->pcie_bus = pci_dev->addr.bus; sc->pcie_device = pci_dev->addr.devid; if (is_vf) sc->flags = BNX2X_IS_VF_FLAG; sc->devinfo.vendor_id = pci_dev->id.vendor_id; sc->devinfo.device_id = pci_dev->id.device_id; sc->devinfo.subvendor_id = pci_dev->id.subsystem_vendor_id; sc->devinfo.subdevice_id = pci_dev->id.subsystem_device_id; sc->pcie_func = pci_dev->addr.function; sc->bar[BAR0].base_addr = (void *)pci_dev->mem_resource[0].addr; if (is_vf) sc->bar[BAR1].base_addr = (void *) ((uint64_t)pci_dev->mem_resource[0].addr + PXP_VF_ADDR_DB_START); else sc->bar[BAR1].base_addr = pci_dev->mem_resource[2].addr; assert(sc->bar[BAR0].base_addr); assert(sc->bar[BAR1].base_addr); bnx2x_load_firmware(sc); assert(sc->firmware); if (eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) sc->udp_rss = 1; sc->rx_budget = BNX2X_RX_BUDGET; sc->hc_rx_ticks = BNX2X_RX_TICKS; sc->hc_tx_ticks = BNX2X_TX_TICKS; sc->interrupt_mode = INTR_MODE_SINGLE_MSIX; sc->rx_mode = BNX2X_RX_MODE_NORMAL; sc->pci_dev = pci_dev; ret = bnx2x_attach(sc); if (ret) { PMD_DRV_LOG(ERR, "bnx2x_attach failed (%d)", ret); } eth_dev->data->mac_addrs = (struct ether_addr *)sc->link_params.mac_addr; PMD_DRV_LOG(INFO, "pcie_bus=%d, pcie_device=%d", sc->pcie_bus, sc->pcie_device); PMD_DRV_LOG(INFO, "bar0.addr=%p, bar1.addr=%p", sc->bar[BAR0].base_addr, sc->bar[BAR1].base_addr); PMD_DRV_LOG(INFO, "port=%d, path=%d, vnic=%d, func=%d", PORT_ID(sc), PATH_ID(sc), VNIC_ID(sc), FUNC_ID(sc)); PMD_DRV_LOG(INFO, "portID=%d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); return ret; } static int eth_bnx2x_dev_init(struct rte_eth_dev *eth_dev) { PMD_INIT_FUNC_TRACE(); return bnx2x_common_dev_init(eth_dev, 0); } static int eth_bnx2xvf_dev_init(struct rte_eth_dev *eth_dev) { PMD_INIT_FUNC_TRACE(); return bnx2x_common_dev_init(eth_dev, 1); } static struct eth_driver rte_bnx2x_pmd = { .pci_drv = { .name = "rte_bnx2x_pmd", .id_table = pci_id_bnx2x_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_bnx2x_dev_init, .dev_private_size = sizeof(struct bnx2x_softc), }; /* * virtual function driver struct */ static struct eth_driver rte_bnx2xvf_pmd = { .pci_drv = { .name = "rte_bnx2xvf_pmd", .id_table = pci_id_bnx2xvf_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING, }, .eth_dev_init = eth_bnx2xvf_dev_init, .dev_private_size = sizeof(struct bnx2x_softc), }; static int rte_bnx2x_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_bnx2x_pmd); return 0; } static int rte_bnx2xvf_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_bnx2xvf_pmd); return 0; } static struct rte_driver rte_bnx2x_driver = { .type = PMD_PDEV, .init = rte_bnx2x_pmd_init, }; static struct rte_driver rte_bnx2xvf_driver = { .type = PMD_PDEV, .init = rte_bnx2xvf_pmd_init, }; PMD_REGISTER_DRIVER(rte_bnx2x_driver); PMD_REGISTER_DRIVER(rte_bnx2xvf_driver); ================================================ FILE: drivers/net/bnx2x/bnx2x_ethdev.h ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #ifndef PMD_BNX2X_ETHDEV_H #define PMD_BNX2X_ETHDEV_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bnx2x_rxtx.h" #include "bnx2x_logs.h" #define DELAY(x) rte_delay_us(x) #define DELAY_MS(x) rte_delay_ms(x) #define usec_delay(x) DELAY(x) #define msec_delay(x) DELAY(1000*(x)) #define FALSE 0 #define TRUE 1 #define false 0 #define true 1 #define min(a,b) RTE_MIN(a,b) #define mb() rte_mb() #define wmb() rte_wmb() #define rmb() rte_rmb() #define MAX_QUEUES sysconf(_SC_NPROCESSORS_CONF) #define BNX2X_MIN_RX_BUF_SIZE 1024 #define BNX2X_MAX_RX_PKT_LEN 15872 #define BNX2X_MAX_MAC_ADDRS 1 /* Hardware RX tick timer (usecs) */ #define BNX2X_RX_TICKS 25 /* Hardware TX tick timer (usecs) */ #define BNX2X_TX_TICKS 50 /* Maximum number of Rx packets to process at a time */ #define BNX2X_RX_BUDGET 0xffffffff #endif /* MAC address operations */ struct bnx2x_mac_ops { void (*mac_addr_add)(struct rte_eth_dev *dev, struct ether_addr *addr, uint16_t index, uint32_t pool); /* not implemented yet */ void (*mac_addr_remove)(struct rte_eth_dev *dev, uint16_t index); /* not implemented yet */ }; ================================================ FILE: drivers/net/bnx2x/bnx2x_logs.h ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #ifndef _PMD_LOGS_H_ #define _PMD_LOGS_H_ #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) #ifdef RTE_LIBRTE_BNX2X_DEBUG_INIT #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_BNX2X_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_BNX2X_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_BNX2X_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_BNX2X_DEBUG #define PMD_DRV_LOG_RAW(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) #else #define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) #endif #define PMD_DRV_LOG(level, fmt, args...) \ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) #endif /* _PMD_LOGS_H_ */ ================================================ FILE: drivers/net/bnx2x/bnx2x_rxtx.c ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #include "bnx2x.h" #include "bnx2x_rxtx.h" static inline struct rte_mbuf * bnx2x_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check(m, 0); return m; } static const struct rte_memzone * ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); mz = rte_memzone_lookup(z_name); if (mz) return mz; return rte_memzone_reserve_aligned(z_name, ring_size, socket_id, 0, BNX2X_PAGE_SIZE); } static void bnx2x_rx_queue_release(struct bnx2x_rx_queue *rx_queue) { uint16_t i; struct rte_mbuf **sw_ring; if (NULL != rx_queue) { sw_ring = rx_queue->sw_ring; if (NULL != sw_ring) { for (i = 0; i < rx_queue->nb_rx_desc; i++) { if (NULL != sw_ring[i]) rte_pktmbuf_free(sw_ring[i]); } rte_free(sw_ring); } rte_free(rx_queue); } } void bnx2x_dev_rx_queue_release(void *rxq) { bnx2x_rx_queue_release(rxq); } int bnx2x_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { uint16_t j, idx; const struct rte_memzone *dma; struct bnx2x_rx_queue *rxq; uint32_t dma_size; struct rte_mbuf *mbuf; struct bnx2x_softc *sc = dev->data->dev_private; struct bnx2x_fastpath *fp = &sc->fp[queue_idx]; struct eth_rx_cqe_next_page *nextpg; phys_addr_t *rx_bd; phys_addr_t busaddr; /* First allocate the rx queue data structure */ rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct bnx2x_rx_queue), RTE_CACHE_LINE_SIZE, socket_id); if (NULL == rxq) { PMD_INIT_LOG(ERR, "rte_zmalloc for rxq failed!"); return (-ENOMEM); } rxq->sc = sc; rxq->mb_pool = mp; rxq->queue_id = queue_idx; rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t)((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); rxq->nb_rx_pages = 1; while (USABLE_RX_BD(rxq) < nb_desc) rxq->nb_rx_pages <<= 1; rxq->nb_rx_desc = TOTAL_RX_BD(rxq); sc->rx_ring_size = USABLE_RX_BD(rxq); rxq->nb_cq_pages = RCQ_BD_PAGES(rxq); rxq->rx_free_thresh = rx_conf->rx_free_thresh ? rx_conf->rx_free_thresh : DEFAULT_RX_FREE_THRESH; PMD_INIT_LOG(DEBUG, "fp[%02d] req_bd=%u, thresh=%u, usable_bd=%lu, " "total_bd=%lu, rx_pages=%u, cq_pages=%u", queue_idx, nb_desc, rxq->rx_free_thresh, USABLE_RX_BD(rxq), TOTAL_RX_BD(rxq), rxq->nb_rx_pages, rxq->nb_cq_pages); /* Allocate RX ring hardware descriptors */ dma_size = rxq->nb_rx_desc * sizeof(struct eth_rx_bd); dma = ring_dma_zone_reserve(dev, "hw_ring", queue_idx, dma_size, socket_id); if (NULL == dma) { PMD_RX_LOG(ERR, "ring_dma_zone_reserve for rx_ring failed!"); bnx2x_rx_queue_release(rxq); return (-ENOMEM); } fp->rx_desc_mapping = rxq->rx_ring_phys_addr = (uint64_t)dma->phys_addr; rxq->rx_ring = (uint64_t*)dma->addr; memset((void *)rxq->rx_ring, 0, dma_size); /* Link the RX chain pages. */ for (j = 1; j <= rxq->nb_rx_pages; j++) { rx_bd = &rxq->rx_ring[TOTAL_RX_BD_PER_PAGE * j - 2]; busaddr = rxq->rx_ring_phys_addr + BNX2X_PAGE_SIZE * (j % rxq->nb_rx_pages); *rx_bd = busaddr; } /* Allocate software ring */ dma_size = rxq->nb_rx_desc * sizeof(struct bnx2x_rx_entry); rxq->sw_ring = rte_zmalloc_socket("sw_ring", dma_size, RTE_CACHE_LINE_SIZE, socket_id); if (NULL == rxq->sw_ring) { PMD_RX_LOG(ERR, "rte_zmalloc for sw_ring failed!"); bnx2x_rx_queue_release(rxq); return (-ENOMEM); } /* Initialize software ring entries */ rxq->rx_mbuf_alloc = 0; for (idx = 0; idx < rxq->nb_rx_desc; idx = NEXT_RX_BD(idx)) { mbuf = bnx2x_rxmbuf_alloc(mp); if (NULL == mbuf) { PMD_RX_LOG(ERR, "RX mbuf alloc failed queue_id=%u, idx=%d", (unsigned)rxq->queue_id, idx); bnx2x_rx_queue_release(rxq); return (-ENOMEM); } rxq->sw_ring[idx] = mbuf; rxq->rx_ring[idx] = mbuf->buf_physaddr; rxq->rx_mbuf_alloc++; } rxq->pkt_first_seg = NULL; rxq->pkt_last_seg = NULL; rxq->rx_bd_head = 0; rxq->rx_bd_tail = idx; /* Allocate CQ chain. */ dma_size = BNX2X_RX_CHAIN_PAGE_SZ * rxq->nb_cq_pages; dma = ring_dma_zone_reserve(dev, "bnx2x_rcq", queue_idx, dma_size, socket_id); if (NULL == dma) { PMD_RX_LOG(ERR, "RCQ alloc failed"); return (-ENOMEM); } fp->rx_comp_mapping = rxq->cq_ring_phys_addr = (uint64_t)dma->phys_addr; rxq->cq_ring = (union eth_rx_cqe*)dma->addr; /* Link the CQ chain pages. */ for (j = 1; j <= rxq->nb_cq_pages; j++) { nextpg = &rxq->cq_ring[TOTAL_RCQ_ENTRIES_PER_PAGE * j - 1].next_page_cqe; busaddr = rxq->cq_ring_phys_addr + BNX2X_PAGE_SIZE * (j % rxq->nb_cq_pages); nextpg->addr_hi = rte_cpu_to_le_32(U64_HI(busaddr)); nextpg->addr_lo = rte_cpu_to_le_32(U64_LO(busaddr)); } rxq->rx_cq_head = 0; rxq->rx_cq_tail = TOTAL_RCQ_ENTRIES(rxq); dev->data->rx_queues[queue_idx] = rxq; if (!sc->rx_queues) sc->rx_queues = dev->data->rx_queues; return 0; } static void bnx2x_tx_queue_release(struct bnx2x_tx_queue *tx_queue) { uint16_t i; struct rte_mbuf **sw_ring; if (NULL != tx_queue) { sw_ring = tx_queue->sw_ring; if (NULL != sw_ring) { for (i = 0; i < tx_queue->nb_tx_desc; i++) { if (NULL != sw_ring[i]) rte_pktmbuf_free(sw_ring[i]); } rte_free(sw_ring); } rte_free(tx_queue); } } void bnx2x_dev_tx_queue_release(void *txq) { bnx2x_tx_queue_release(txq); } static uint16_t bnx2x_xmit_pkts(void *p_txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct bnx2x_tx_queue *txq; struct bnx2x_softc *sc; struct bnx2x_fastpath *fp; uint32_t burst, nb_tx; struct rte_mbuf **m = tx_pkts; int ret; txq = p_txq; sc = txq->sc; fp = &sc->fp[txq->queue_id]; nb_tx = nb_pkts; do { burst = RTE_MIN(nb_pkts, RTE_PMD_BNX2X_TX_MAX_BURST); ret = bnx2x_tx_encap(txq, m, burst); if (unlikely(ret)) { PMD_TX_LOG(ERR, "tx_encap failed!"); } bnx2x_update_fp_sb_idx(fp); if ((txq->nb_tx_desc - txq->nb_tx_avail) > txq->tx_free_thresh) { bnx2x_txeof(sc, fp); } if (unlikely(ret == ENOMEM)) { break; } m += burst; nb_pkts -= burst; } while (nb_pkts); return nb_tx - nb_pkts; } int bnx2x_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { uint16_t i; unsigned int tsize; const struct rte_memzone *tz; struct bnx2x_tx_queue *txq; struct eth_tx_next_bd *tx_n_bd; uint64_t busaddr; struct bnx2x_softc *sc = dev->data->dev_private; struct bnx2x_fastpath *fp = &sc->fp[queue_idx]; /* First allocate the tx queue data structure */ txq = rte_zmalloc("ethdev TX queue", sizeof(struct bnx2x_tx_queue), RTE_CACHE_LINE_SIZE); if (txq == NULL) return (-ENOMEM); txq->sc = sc; txq->nb_tx_pages = 1; while (USABLE_TX_BD(txq) < nb_desc) txq->nb_tx_pages <<= 1; txq->nb_tx_desc = TOTAL_TX_BD(txq); sc->tx_ring_size = TOTAL_TX_BD(txq); txq->tx_free_thresh = tx_conf->tx_free_thresh ? tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH; PMD_INIT_LOG(DEBUG, "fp[%02d] req_bd=%u, thresh=%u, usable_bd=%lu, " "total_bd=%lu, tx_pages=%u", queue_idx, nb_desc, txq->tx_free_thresh, USABLE_TX_BD(txq), TOTAL_TX_BD(txq), txq->nb_tx_pages); /* Allocate TX ring hardware descriptors */ tsize = txq->nb_tx_desc * sizeof(union eth_tx_bd_types); tz = ring_dma_zone_reserve(dev, "tx_hw_ring", queue_idx, tsize, socket_id); if (tz == NULL) { bnx2x_tx_queue_release(txq); return (-ENOMEM); } fp->tx_desc_mapping = txq->tx_ring_phys_addr = (uint64_t)tz->phys_addr; txq->tx_ring = (union eth_tx_bd_types *) tz->addr; memset(txq->tx_ring, 0, tsize); /* Allocate software ring */ tsize = txq->nb_tx_desc * sizeof(struct rte_mbuf *); txq->sw_ring = rte_zmalloc("tx_sw_ring", tsize, RTE_CACHE_LINE_SIZE); if (txq->sw_ring == NULL) { bnx2x_tx_queue_release(txq); return (-ENOMEM); } /* PMD_DRV_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); */ /* Link TX pages */ for (i = 1; i <= txq->nb_tx_pages; i++) { tx_n_bd = &txq->tx_ring[TOTAL_TX_BD_PER_PAGE * i - 1].next_bd; busaddr = txq->tx_ring_phys_addr + BNX2X_PAGE_SIZE * (i % txq->nb_tx_pages); tx_n_bd->addr_hi = rte_cpu_to_le_32(U64_HI(busaddr)); tx_n_bd->addr_lo = rte_cpu_to_le_32(U64_LO(busaddr)); /* PMD_DRV_LOG(DEBUG, "link tx page %lu", (TOTAL_TX_BD_PER_PAGE * i - 1)); */ } txq->queue_id = queue_idx; txq->port_id = dev->data->port_id; txq->tx_pkt_tail = 0; txq->tx_pkt_head = 0; txq->tx_bd_tail = 0; txq->tx_bd_head = 0; txq->nb_tx_avail = txq->nb_tx_desc; dev->tx_pkt_burst = bnx2x_xmit_pkts; dev->data->tx_queues[queue_idx] = txq; if (!sc->tx_queues) sc->tx_queues = dev->data->tx_queues; return 0; } static inline void bnx2x_upd_rx_prod_fast(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, uint16_t rx_bd_prod, uint16_t rx_cq_prod) { union ustorm_eth_rx_producers rx_prods; rx_prods.prod.bd_prod = rx_bd_prod; rx_prods.prod.cqe_prod = rx_cq_prod; REG_WR(sc, fp->ustorm_rx_prods_offset, rx_prods.raw_data[0]); } static uint16_t bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct bnx2x_rx_queue *rxq = p_rxq; struct bnx2x_softc *sc = rxq->sc; struct bnx2x_fastpath *fp = &sc->fp[rxq->queue_id]; uint32_t nb_rx = 0; uint16_t hw_cq_cons, sw_cq_cons, sw_cq_prod; uint16_t bd_cons, bd_prod; struct rte_mbuf *new_mb; uint16_t rx_pref; struct eth_fast_path_rx_cqe *cqe_fp; uint16_t len, pad; struct rte_mbuf *rx_mb = NULL; hw_cq_cons = le16toh(*fp->rx_cq_cons_sb); if ((hw_cq_cons & USABLE_RCQ_ENTRIES_PER_PAGE) == USABLE_RCQ_ENTRIES_PER_PAGE) { ++hw_cq_cons; } bd_cons = rxq->rx_bd_head; bd_prod = rxq->rx_bd_tail; sw_cq_cons = rxq->rx_cq_head; sw_cq_prod = rxq->rx_cq_tail; while (nb_rx < nb_pkts && sw_cq_cons != hw_cq_cons) { bd_prod &= MAX_RX_BD(rxq); bd_cons &= MAX_RX_BD(rxq); cqe_fp = &rxq->cq_ring[sw_cq_cons & MAX_RX_BD(rxq)].fast_path_cqe; if (unlikely(CQE_TYPE_SLOW(cqe_fp->type_error_flags & ETH_FAST_PATH_RX_CQE_TYPE))) { PMD_RX_LOG(ERR, "slowpath event during traffic processing"); break; } if (unlikely(cqe_fp->type_error_flags & ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG)) { PMD_RX_LOG(ERR, "flags 0x%x rx packet %u", cqe_fp->type_error_flags, sw_cq_cons); goto next_rx; } len = cqe_fp->pkt_len_or_gro_seg_len; pad = cqe_fp->placement_offset; new_mb = bnx2x_rxmbuf_alloc(rxq->mb_pool); if (unlikely(!new_mb)) { PMD_RX_LOG(ERR, "mbuf alloc fail fp[%02d]", fp->index); goto next_rx; } rx_mb = rxq->sw_ring[bd_cons]; rxq->sw_ring[bd_cons] = new_mb; rxq->rx_ring[bd_prod] = new_mb->buf_physaddr; rx_pref = NEXT_RX_BD(bd_cons) & MAX_RX_BD(rxq); rte_prefetch0(rxq->sw_ring[rx_pref]); if ((rx_pref & 0x3) == 0) { rte_prefetch0(&rxq->rx_ring[rx_pref]); rte_prefetch0(&rxq->sw_ring[rx_pref]); } rx_mb->data_off = pad; rx_mb->nb_segs = 1; rx_mb->next = NULL; rx_mb->pkt_len = rx_mb->data_len = len; rx_mb->port = rxq->port_id; rx_mb->buf_len = len + pad; rte_prefetch1(rte_pktmbuf_mtod(rx_mb, void *)); /* * If we received a packet with a vlan tag, * attach that information to the packet. */ if (cqe_fp->pars_flags.flags & PARSING_FLAGS_VLAN) { rx_mb->vlan_tci = cqe_fp->vlan_tag; rx_mb->ol_flags |= PKT_RX_VLAN_PKT; } rx_pkts[nb_rx] = rx_mb; nb_rx++; /* limit spinning on the queue */ if (unlikely(nb_rx == sc->rx_budget)) { PMD_RX_LOG(ERR, "Limit spinning on the queue"); break; } next_rx: bd_cons = NEXT_RX_BD(bd_cons); bd_prod = NEXT_RX_BD(bd_prod); sw_cq_prod = NEXT_RCQ_IDX(sw_cq_prod); sw_cq_cons = NEXT_RCQ_IDX(sw_cq_cons); } rxq->rx_bd_head = bd_cons; rxq->rx_bd_tail = bd_prod; rxq->rx_cq_head = sw_cq_cons; rxq->rx_cq_tail = sw_cq_prod; bnx2x_upd_rx_prod_fast(sc, fp, bd_prod, sw_cq_prod); return nb_rx; } int bnx2x_dev_rx_init(struct rte_eth_dev *dev) { dev->rx_pkt_burst = bnx2x_recv_pkts; return 0; } void bnx2x_dev_clear_queues(struct rte_eth_dev *dev) { uint8_t i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_tx_queues; i++) { struct bnx2x_tx_queue *txq = dev->data->tx_queues[i]; if (txq != NULL) { bnx2x_tx_queue_release(txq); dev->data->tx_queues[i] = NULL; } } for (i = 0; i < dev->data->nb_rx_queues; i++) { struct bnx2x_rx_queue *rxq = dev->data->rx_queues[i]; if (rxq != NULL) { bnx2x_rx_queue_release(rxq); dev->data->rx_queues[i] = NULL; } } } ================================================ FILE: drivers/net/bnx2x/bnx2x_rxtx.h ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #ifndef _BNX2X_RXTX_H_ #define _BNX2X_RXTX_H_ #define DEFAULT_RX_FREE_THRESH 0 #define DEFAULT_TX_FREE_THRESH 512 #define RTE_PMD_BNX2X_TX_MAX_BURST 1 /** * Structure associated with each descriptor of the RX ring of a RX queue. */ struct bnx2x_rx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ }; /** * Structure associated with each RX queue. */ struct bnx2x_rx_queue { struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ union eth_rx_cqe *cq_ring; /**< RCQ ring virtual address. */ uint64_t cq_ring_phys_addr; /**< RCQ ring DMA address. */ uint64_t *rx_ring; /**< RX ring virtual address. */ uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ struct rte_mbuf **sw_ring; /**< address of RX software ring. */ struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ uint16_t nb_cq_pages; /**< number of RCQ pages. */ uint16_t nb_rx_desc; /**< number of RX descriptors. */ uint16_t nb_rx_pages; /**< number of RX pages. */ uint16_t rx_bd_head; /**< Index of current rx bd. */ uint16_t rx_bd_tail; /**< Index of last rx bd. */ uint16_t rx_cq_head; /**< Index of current rcq bd. */ uint16_t rx_cq_tail; /**< Index of last rcq bd. */ uint16_t nb_rx_hold; /**< number of held free RX desc. */ uint16_t rx_free_thresh; /**< max free RX desc to hold. */ uint16_t queue_id; /**< RX queue index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ struct bnx2x_softc *sc; /**< Ptr to dev_private data. */ uint64_t rx_mbuf_alloc; /**< Number of allocated mbufs. */ }; /** * Structure associated with each TX queue. */ struct bnx2x_tx_queue { /** TX ring virtual address. */ union eth_tx_bd_types *tx_ring; /**< TX ring virtual address. */ uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ struct rte_mbuf **sw_ring; /**< virtual address of SW ring. */ uint16_t tx_pkt_tail; /**< Index of current tx pkt. */ uint16_t tx_pkt_head; /**< Index of last pkt counted by txeof. */ uint16_t tx_bd_tail; /**< Index of current tx bd. */ uint16_t tx_bd_head; /**< Index of last bd counted by txeof. */ uint16_t nb_tx_desc; /**< number of TX descriptors. */ uint16_t tx_free_thresh; /**< minimum TX before freeing. */ uint16_t nb_tx_avail; /**< Number of TX descriptors available. */ uint16_t nb_tx_pages; /**< number of TX pages */ uint16_t queue_id; /**< TX queue index. */ uint8_t port_id; /**< Device port identifier. */ struct bnx2x_softc *sc; /**< Ptr to dev_private data */ }; int bnx2x_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); int bnx2x_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); void bnx2x_dev_rx_queue_release(void *rxq); void bnx2x_dev_tx_queue_release(void *txq); int bnx2x_dev_rx_init(struct rte_eth_dev *dev); void bnx2x_dev_clear_queues(struct rte_eth_dev *dev); #endif /* _BNX2X_RXTX_H_ */ ================================================ FILE: drivers/net/bnx2x/bnx2x_stats.c ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "bnx2x.h" #include "bnx2x_stats.h" #ifdef __i386__ #define BITS_PER_LONG 32 #else #define BITS_PER_LONG 64 #endif static inline uint16_t bnx2x_get_port_stats_dma_len(struct bnx2x_softc *sc) { uint16_t res = 0; uint32_t size; /* 'newest' convention - shmem2 contains the size of the port stats */ if (SHMEM2_HAS(sc, sizeof_port_stats)) { size = SHMEM2_RD(sc, sizeof_port_stats); if (size) { res = size; } /* prevent newer BC from causing buffer overflow */ if (res > sizeof(struct host_port_stats)) { res = sizeof(struct host_port_stats); } } /* * Older convention - all BCs support the port stats fields up until * the 'not_used' field */ if (!res) { res = (offsetof(struct host_port_stats, not_used) + 4); /* if PFC stats are supported by the MFW, DMA them as well */ if (sc->devinfo.bc_ver >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) { res += (offsetof(struct host_port_stats, pfc_frames_rx_lo) - offsetof(struct host_port_stats, pfc_frames_tx_hi) + 4); } } res >>= 2; return res; } /* * Init service functions */ /* * Post the next statistics ramrod. Protect it with the lock in * order to ensure the strict order between statistics ramrods * (each ramrod has a sequence number passed in a * sc->fw_stats_req->hdr.drv_stats_counter and ramrods must be * sent in order). */ static void bnx2x_storm_stats_post(struct bnx2x_softc *sc) { int rc; if (!sc->stats_pending) { if (sc->stats_pending) { return; } sc->fw_stats_req->hdr.drv_stats_counter = htole16(sc->stats_counter++); PMD_DRV_LOG(DEBUG, "sending statistics ramrod %d", le16toh(sc->fw_stats_req->hdr.drv_stats_counter)); /* adjust the ramrod to include VF queues statistics */ /* send FW stats ramrod */ rc = bnx2x_sp_post(sc, RAMROD_CMD_ID_COMMON_STAT_QUERY, 0, U64_HI(sc->fw_stats_req_mapping), U64_LO(sc->fw_stats_req_mapping), NONE_CONNECTION_TYPE); if (rc == 0) { sc->stats_pending = 1; } } } static void bnx2x_hw_stats_post(struct bnx2x_softc *sc) { struct dmae_command *dmae = &sc->stats_dmae; uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); int loader_idx; uint32_t opcode; *stats_comp = DMAE_COMP_VAL; if (CHIP_REV_IS_SLOW(sc)) { return; } /* Update MCP's statistics if possible */ if (sc->func_stx) { rte_memcpy(BNX2X_SP(sc, func_stats), &sc->func_stats, sizeof(sc->func_stats)); } /* loader */ if (sc->executer_idx) { loader_idx = PMF_DMAE_C(sc); opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, TRUE, DMAE_COMP_GRC); opcode = bnx2x_dmae_opcode_clr_src_reset(opcode); memset(dmae, 0, sizeof(struct dmae_command)); dmae->opcode = opcode; dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, dmae[0])); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, dmae[0])); dmae->dst_addr_lo = ((DMAE_REG_CMD_MEM + sizeof(struct dmae_command) * (loader_idx + 1)) >> 2); dmae->dst_addr_hi = 0; dmae->len = sizeof(struct dmae_command) >> 2; dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx + 1] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; *stats_comp = 0; bnx2x_post_dmae(sc, dmae, loader_idx); } else if (sc->func_stx) { *stats_comp = 0; bnx2x_post_dmae(sc, dmae, INIT_DMAE_C(sc)); } } static int bnx2x_stats_comp(struct bnx2x_softc *sc) { uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); int cnt = 10; while (*stats_comp != DMAE_COMP_VAL) { if (!cnt) { PMD_DRV_LOG(ERR, "Timeout waiting for stats finished"); break; } cnt--; DELAY(1000); } return 1; } /* * Statistics service functions */ static void bnx2x_stats_pmf_update(struct bnx2x_softc *sc) { struct dmae_command *dmae; uint32_t opcode; int loader_idx = PMF_DMAE_C(sc); uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); if (sc->devinfo.bc_ver <= 0x06001400) { /* * Bootcode v6.0.21 fixed a GRC timeout that occurs when accessing * BRB registers while the BRB block is in reset. The DMA transfer * below triggers this issue resulting in the DMAE to stop * functioning. Skip this initial stats transfer for old bootcode * versions <= 6.0.20. */ return; } /* sanity */ if (!sc->port.pmf || !sc->port.port_stx) { PMD_DRV_LOG(ERR, "BUG!"); return; } sc->executer_idx = 0; opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI, FALSE, 0); dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC); dmae->src_addr_lo = (sc->port.port_stx >> 2); dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, port_stats)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, port_stats)); dmae->len = DMAE_LEN32_RD_MAX; dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI); dmae->src_addr_lo = ((sc->port.port_stx >> 2) + DMAE_LEN32_RD_MAX); dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, port_stats) + DMAE_LEN32_RD_MAX * 4); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, port_stats) + DMAE_LEN32_RD_MAX * 4); dmae->len = (bnx2x_get_port_stats_dma_len(sc) - DMAE_LEN32_RD_MAX); dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; bnx2x_hw_stats_post(sc); bnx2x_stats_comp(sc); } static void bnx2x_port_stats_init(struct bnx2x_softc *sc) { struct dmae_command *dmae; int port = SC_PORT(sc); uint32_t opcode; int loader_idx = PMF_DMAE_C(sc); uint32_t mac_addr; uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); /* sanity */ if (!sc->link_vars.link_up || !sc->port.pmf) { PMD_DRV_LOG(ERR, "BUG!"); return; } sc->executer_idx = 0; /* MCP */ opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, TRUE, DMAE_COMP_GRC); if (sc->port.port_stx) { dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, port_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, port_stats)); dmae->dst_addr_lo = sc->port.port_stx >> 2; dmae->dst_addr_hi = 0; dmae->len = bnx2x_get_port_stats_dma_len(sc); dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; dmae->comp_addr_hi = 0; dmae->comp_val = 1; } if (sc->func_stx) { dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, func_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, func_stats)); dmae->dst_addr_lo = (sc->func_stx >> 2); dmae->dst_addr_hi = 0; dmae->len = (sizeof(struct host_func_stats) >> 2); dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; } /* MAC */ opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI, TRUE, DMAE_COMP_GRC); /* EMAC is special */ if (sc->link_vars.mac_type == ELINK_MAC_TYPE_EMAC) { mac_addr = (port ? GRCBASE_EMAC1 : GRCBASE_EMAC0); /* EMAC_REG_EMAC_RX_STAT_AC (EMAC_REG_EMAC_RX_STAT_AC_COUNT)*/ dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = (mac_addr + EMAC_REG_EMAC_RX_STAT_AC) >> 2; dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, mac_stats)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, mac_stats)); dmae->len = EMAC_REG_EMAC_RX_STAT_AC_COUNT; dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; /* EMAC_REG_EMAC_RX_STAT_AC_28 */ dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = ((mac_addr + EMAC_REG_EMAC_RX_STAT_AC_28) >> 2); dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, mac_stats) + offsetof(struct emac_stats, rx_stat_falsecarriererrors)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, mac_stats) + offsetof(struct emac_stats, rx_stat_falsecarriererrors)); dmae->len = 1; dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; /* EMAC_REG_EMAC_TX_STAT_AC (EMAC_REG_EMAC_TX_STAT_AC_COUNT)*/ dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = ((mac_addr + EMAC_REG_EMAC_TX_STAT_AC) >> 2); dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, mac_stats) + offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, mac_stats) + offsetof(struct emac_stats, tx_stat_ifhcoutoctets)); dmae->len = EMAC_REG_EMAC_TX_STAT_AC_COUNT; dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; } else { uint32_t tx_src_addr_lo, rx_src_addr_lo; uint16_t rx_len, tx_len; /* configure the params according to MAC type */ switch (sc->link_vars.mac_type) { case ELINK_MAC_TYPE_BMAC: mac_addr = (port) ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; /* BIGMAC_REGISTER_TX_STAT_GTPKT .. BIGMAC_REGISTER_TX_STAT_GTBYT */ if (CHIP_IS_E1x(sc)) { tx_src_addr_lo = ((mac_addr + BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2); tx_len = ((8 + BIGMAC_REGISTER_TX_STAT_GTBYT - BIGMAC_REGISTER_TX_STAT_GTPKT) >> 2); rx_src_addr_lo = ((mac_addr + BIGMAC_REGISTER_RX_STAT_GR64) >> 2); rx_len = ((8 + BIGMAC_REGISTER_RX_STAT_GRIPJ - BIGMAC_REGISTER_RX_STAT_GR64) >> 2); } else { tx_src_addr_lo = ((mac_addr + BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2); tx_len = ((8 + BIGMAC2_REGISTER_TX_STAT_GTBYT - BIGMAC2_REGISTER_TX_STAT_GTPOK) >> 2); rx_src_addr_lo = ((mac_addr + BIGMAC2_REGISTER_RX_STAT_GR64) >> 2); rx_len = ((8 + BIGMAC2_REGISTER_RX_STAT_GRIPJ - BIGMAC2_REGISTER_RX_STAT_GR64) >> 2); } break; case ELINK_MAC_TYPE_UMAC: /* handled by MSTAT */ case ELINK_MAC_TYPE_XMAC: /* handled by MSTAT */ default: mac_addr = (port) ? GRCBASE_MSTAT1 : GRCBASE_MSTAT0; tx_src_addr_lo = ((mac_addr + MSTAT_REG_TX_STAT_GTXPOK_LO) >> 2); rx_src_addr_lo = ((mac_addr + MSTAT_REG_RX_STAT_GR64_LO) >> 2); tx_len = (sizeof(sc->sp->mac_stats.mstat_stats.stats_tx) >> 2); rx_len = (sizeof(sc->sp->mac_stats.mstat_stats.stats_rx) >> 2); break; } /* TX stats */ dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = tx_src_addr_lo; dmae->src_addr_hi = 0; dmae->len = tx_len; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, mac_stats)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, mac_stats)); dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; dmae->comp_addr_hi = 0; dmae->comp_val = 1; /* RX stats */ dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_hi = 0; dmae->src_addr_lo = rx_src_addr_lo; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, mac_stats) + (tx_len << 2)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, mac_stats) + (tx_len << 2)); dmae->len = rx_len; dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; dmae->comp_addr_hi = 0; dmae->comp_val = 1; } /* NIG */ if (!CHIP_IS_E3(sc)) { dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT0 : NIG_REG_STAT0_EGRESS_MAC_PKT0) >> 2; dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, nig_stats) + offsetof(struct nig_stats, egress_mac_pkt0_lo)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, nig_stats) + offsetof(struct nig_stats, egress_mac_pkt0_lo)); dmae->len = ((2 * sizeof(uint32_t)) >> 2); dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = opcode; dmae->src_addr_lo = (port ? NIG_REG_STAT1_EGRESS_MAC_PKT1 : NIG_REG_STAT0_EGRESS_MAC_PKT1) >> 2; dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, nig_stats) + offsetof(struct nig_stats, egress_mac_pkt1_lo)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, nig_stats) + offsetof(struct nig_stats, egress_mac_pkt1_lo)); dmae->len = ((2 * sizeof(uint32_t)) >> 2); dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; } dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_GRC, DMAE_DST_PCI, TRUE, DMAE_COMP_PCI); dmae->src_addr_lo = (port ? NIG_REG_STAT1_BRB_DISCARD : NIG_REG_STAT0_BRB_DISCARD) >> 2; dmae->src_addr_hi = 0; dmae->dst_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, nig_stats)); dmae->dst_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, nig_stats)); dmae->len = (sizeof(struct nig_stats) - 4*sizeof(uint32_t)) >> 2; dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; } static void bnx2x_func_stats_init(struct bnx2x_softc *sc) { struct dmae_command *dmae = &sc->stats_dmae; uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); /* sanity */ if (!sc->func_stx) { PMD_DRV_LOG(ERR, "BUG!"); return; } sc->executer_idx = 0; memset(dmae, 0, sizeof(struct dmae_command)); dmae->opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, TRUE, DMAE_COMP_PCI); dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, func_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, func_stats)); dmae->dst_addr_lo = (sc->func_stx >> 2); dmae->dst_addr_hi = 0; dmae->len = (sizeof(struct host_func_stats) >> 2); dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; } static void bnx2x_stats_start(struct bnx2x_softc *sc) { /* * VFs travel through here as part of the statistics FSM, but no action * is required */ if (IS_VF(sc)) { return; } if (sc->port.pmf) { bnx2x_port_stats_init(sc); } else if (sc->func_stx) { bnx2x_func_stats_init(sc); } bnx2x_hw_stats_post(sc); bnx2x_storm_stats_post(sc); } static void bnx2x_stats_pmf_start(struct bnx2x_softc *sc) { bnx2x_stats_comp(sc); bnx2x_stats_pmf_update(sc); bnx2x_stats_start(sc); } static void bnx2x_stats_restart(struct bnx2x_softc *sc) { /* * VFs travel through here as part of the statistics FSM, but no action * is required */ if (IS_VF(sc)) { return; } bnx2x_stats_comp(sc); bnx2x_stats_start(sc); } static void bnx2x_bmac_stats_update(struct bnx2x_softc *sc) { struct host_port_stats *pstats = BNX2X_SP(sc, port_stats); struct bnx2x_eth_stats *estats = &sc->eth_stats; struct { uint32_t lo; uint32_t hi; } diff; if (CHIP_IS_E1x(sc)) { struct bmac1_stats *new = BNX2X_SP(sc, mac_stats.bmac1_stats); /* the macros below will use "bmac1_stats" type */ UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets); UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors); UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts); UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong); UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments); UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers); UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived); UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered); UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf); UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent); UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone); UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets); UPDATE_STAT64(tx_stat_gt127, tx_stat_etherstatspkts65octetsto127octets); UPDATE_STAT64(tx_stat_gt255, tx_stat_etherstatspkts128octetsto255octets); UPDATE_STAT64(tx_stat_gt511, tx_stat_etherstatspkts256octetsto511octets); UPDATE_STAT64(tx_stat_gt1023, tx_stat_etherstatspkts512octetsto1023octets); UPDATE_STAT64(tx_stat_gt1518, tx_stat_etherstatspkts1024octetsto1522octets); UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047); UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095); UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216); UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383); UPDATE_STAT64(tx_stat_gterr, tx_stat_dot3statsinternalmactransmiterrors); UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl); } else { struct bmac2_stats *new = BNX2X_SP(sc, mac_stats.bmac2_stats); struct bnx2x_fw_port_stats_old *fwstats = &sc->fw_stats_old; /* the macros below will use "bmac2_stats" type */ UPDATE_STAT64(rx_stat_grerb, rx_stat_ifhcinbadoctets); UPDATE_STAT64(rx_stat_grfcs, rx_stat_dot3statsfcserrors); UPDATE_STAT64(rx_stat_grund, rx_stat_etherstatsundersizepkts); UPDATE_STAT64(rx_stat_grovr, rx_stat_dot3statsframestoolong); UPDATE_STAT64(rx_stat_grfrg, rx_stat_etherstatsfragments); UPDATE_STAT64(rx_stat_grjbr, rx_stat_etherstatsjabbers); UPDATE_STAT64(rx_stat_grxcf, rx_stat_maccontrolframesreceived); UPDATE_STAT64(rx_stat_grxpf, rx_stat_xoffstateentered); UPDATE_STAT64(rx_stat_grxpf, rx_stat_mac_xpf); UPDATE_STAT64(tx_stat_gtxpf, tx_stat_outxoffsent); UPDATE_STAT64(tx_stat_gtxpf, tx_stat_flowcontroldone); UPDATE_STAT64(tx_stat_gt64, tx_stat_etherstatspkts64octets); UPDATE_STAT64(tx_stat_gt127, tx_stat_etherstatspkts65octetsto127octets); UPDATE_STAT64(tx_stat_gt255, tx_stat_etherstatspkts128octetsto255octets); UPDATE_STAT64(tx_stat_gt511, tx_stat_etherstatspkts256octetsto511octets); UPDATE_STAT64(tx_stat_gt1023, tx_stat_etherstatspkts512octetsto1023octets); UPDATE_STAT64(tx_stat_gt1518, tx_stat_etherstatspkts1024octetsto1522octets); UPDATE_STAT64(tx_stat_gt2047, tx_stat_mac_2047); UPDATE_STAT64(tx_stat_gt4095, tx_stat_mac_4095); UPDATE_STAT64(tx_stat_gt9216, tx_stat_mac_9216); UPDATE_STAT64(tx_stat_gt16383, tx_stat_mac_16383); UPDATE_STAT64(tx_stat_gterr, tx_stat_dot3statsinternalmactransmiterrors); UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl); /* collect PFC stats */ pstats->pfc_frames_tx_hi = new->tx_stat_gtpp_hi; pstats->pfc_frames_tx_lo = new->tx_stat_gtpp_lo; ADD_64(pstats->pfc_frames_tx_hi, fwstats->pfc_frames_tx_hi, pstats->pfc_frames_tx_lo, fwstats->pfc_frames_tx_lo); pstats->pfc_frames_rx_hi = new->rx_stat_grpp_hi; pstats->pfc_frames_rx_lo = new->rx_stat_grpp_lo; ADD_64(pstats->pfc_frames_rx_hi, fwstats->pfc_frames_rx_hi, pstats->pfc_frames_rx_lo, fwstats->pfc_frames_rx_lo); } estats->pause_frames_received_hi = pstats->mac_stx[1].rx_stat_mac_xpf_hi; estats->pause_frames_received_lo = pstats->mac_stx[1].rx_stat_mac_xpf_lo; estats->pause_frames_sent_hi = pstats->mac_stx[1].tx_stat_outxoffsent_hi; estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo; estats->pfc_frames_received_hi = pstats->pfc_frames_rx_hi; estats->pfc_frames_received_lo = pstats->pfc_frames_rx_lo; estats->pfc_frames_sent_hi = pstats->pfc_frames_tx_hi; estats->pfc_frames_sent_lo = pstats->pfc_frames_tx_lo; } static void bnx2x_mstat_stats_update(struct bnx2x_softc *sc) { struct host_port_stats *pstats = BNX2X_SP(sc, port_stats); struct bnx2x_eth_stats *estats = &sc->eth_stats; struct mstat_stats *new = BNX2X_SP(sc, mac_stats.mstat_stats); ADD_STAT64(stats_rx.rx_grerb, rx_stat_ifhcinbadoctets); ADD_STAT64(stats_rx.rx_grfcs, rx_stat_dot3statsfcserrors); ADD_STAT64(stats_rx.rx_grund, rx_stat_etherstatsundersizepkts); ADD_STAT64(stats_rx.rx_grovr, rx_stat_dot3statsframestoolong); ADD_STAT64(stats_rx.rx_grfrg, rx_stat_etherstatsfragments); ADD_STAT64(stats_rx.rx_grxcf, rx_stat_maccontrolframesreceived); ADD_STAT64(stats_rx.rx_grxpf, rx_stat_xoffstateentered); ADD_STAT64(stats_rx.rx_grxpf, rx_stat_mac_xpf); ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent); ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone); /* collect pfc stats */ ADD_64(pstats->pfc_frames_tx_hi, new->stats_tx.tx_gtxpp_hi, pstats->pfc_frames_tx_lo, new->stats_tx.tx_gtxpp_lo); ADD_64(pstats->pfc_frames_rx_hi, new->stats_rx.rx_grxpp_hi, pstats->pfc_frames_rx_lo, new->stats_rx.rx_grxpp_lo); ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets); ADD_STAT64(stats_tx.tx_gt127, tx_stat_etherstatspkts65octetsto127octets); ADD_STAT64(stats_tx.tx_gt255, tx_stat_etherstatspkts128octetsto255octets); ADD_STAT64(stats_tx.tx_gt511, tx_stat_etherstatspkts256octetsto511octets); ADD_STAT64(stats_tx.tx_gt1023, tx_stat_etherstatspkts512octetsto1023octets); ADD_STAT64(stats_tx.tx_gt1518, tx_stat_etherstatspkts1024octetsto1522octets); ADD_STAT64(stats_tx.tx_gt2047, tx_stat_mac_2047); ADD_STAT64(stats_tx.tx_gt4095, tx_stat_mac_4095); ADD_STAT64(stats_tx.tx_gt9216, tx_stat_mac_9216); ADD_STAT64(stats_tx.tx_gt16383, tx_stat_mac_16383); ADD_STAT64(stats_tx.tx_gterr, tx_stat_dot3statsinternalmactransmiterrors); ADD_STAT64(stats_tx.tx_gtufl, tx_stat_mac_ufl); estats->etherstatspkts1024octetsto1522octets_hi = pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_hi; estats->etherstatspkts1024octetsto1522octets_lo = pstats->mac_stx[1].tx_stat_etherstatspkts1024octetsto1522octets_lo; estats->etherstatspktsover1522octets_hi = pstats->mac_stx[1].tx_stat_mac_2047_hi; estats->etherstatspktsover1522octets_lo = pstats->mac_stx[1].tx_stat_mac_2047_lo; ADD_64(estats->etherstatspktsover1522octets_hi, pstats->mac_stx[1].tx_stat_mac_4095_hi, estats->etherstatspktsover1522octets_lo, pstats->mac_stx[1].tx_stat_mac_4095_lo); ADD_64(estats->etherstatspktsover1522octets_hi, pstats->mac_stx[1].tx_stat_mac_9216_hi, estats->etherstatspktsover1522octets_lo, pstats->mac_stx[1].tx_stat_mac_9216_lo); ADD_64(estats->etherstatspktsover1522octets_hi, pstats->mac_stx[1].tx_stat_mac_16383_hi, estats->etherstatspktsover1522octets_lo, pstats->mac_stx[1].tx_stat_mac_16383_lo); estats->pause_frames_received_hi = pstats->mac_stx[1].rx_stat_mac_xpf_hi; estats->pause_frames_received_lo = pstats->mac_stx[1].rx_stat_mac_xpf_lo; estats->pause_frames_sent_hi = pstats->mac_stx[1].tx_stat_outxoffsent_hi; estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo; estats->pfc_frames_received_hi = pstats->pfc_frames_rx_hi; estats->pfc_frames_received_lo = pstats->pfc_frames_rx_lo; estats->pfc_frames_sent_hi = pstats->pfc_frames_tx_hi; estats->pfc_frames_sent_lo = pstats->pfc_frames_tx_lo; } static void bnx2x_emac_stats_update(struct bnx2x_softc *sc) { struct emac_stats *new = BNX2X_SP(sc, mac_stats.emac_stats); struct host_port_stats *pstats = BNX2X_SP(sc, port_stats); struct bnx2x_eth_stats *estats = &sc->eth_stats; UPDATE_EXTEND_STAT(rx_stat_ifhcinbadoctets); UPDATE_EXTEND_STAT(tx_stat_ifhcoutbadoctets); UPDATE_EXTEND_STAT(rx_stat_dot3statsfcserrors); UPDATE_EXTEND_STAT(rx_stat_dot3statsalignmenterrors); UPDATE_EXTEND_STAT(rx_stat_dot3statscarriersenseerrors); UPDATE_EXTEND_STAT(rx_stat_falsecarriererrors); UPDATE_EXTEND_STAT(rx_stat_etherstatsundersizepkts); UPDATE_EXTEND_STAT(rx_stat_dot3statsframestoolong); UPDATE_EXTEND_STAT(rx_stat_etherstatsfragments); UPDATE_EXTEND_STAT(rx_stat_etherstatsjabbers); UPDATE_EXTEND_STAT(rx_stat_maccontrolframesreceived); UPDATE_EXTEND_STAT(rx_stat_xoffstateentered); UPDATE_EXTEND_STAT(rx_stat_xonpauseframesreceived); UPDATE_EXTEND_STAT(rx_stat_xoffpauseframesreceived); UPDATE_EXTEND_STAT(tx_stat_outxonsent); UPDATE_EXTEND_STAT(tx_stat_outxoffsent); UPDATE_EXTEND_STAT(tx_stat_flowcontroldone); UPDATE_EXTEND_STAT(tx_stat_etherstatscollisions); UPDATE_EXTEND_STAT(tx_stat_dot3statssinglecollisionframes); UPDATE_EXTEND_STAT(tx_stat_dot3statsmultiplecollisionframes); UPDATE_EXTEND_STAT(tx_stat_dot3statsdeferredtransmissions); UPDATE_EXTEND_STAT(tx_stat_dot3statsexcessivecollisions); UPDATE_EXTEND_STAT(tx_stat_dot3statslatecollisions); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts64octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts65octetsto127octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts128octetsto255octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts256octetsto511octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts512octetsto1023octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspkts1024octetsto1522octets); UPDATE_EXTEND_STAT(tx_stat_etherstatspktsover1522octets); UPDATE_EXTEND_STAT(tx_stat_dot3statsinternalmactransmiterrors); estats->pause_frames_received_hi = pstats->mac_stx[1].rx_stat_xonpauseframesreceived_hi; estats->pause_frames_received_lo = pstats->mac_stx[1].rx_stat_xonpauseframesreceived_lo; ADD_64(estats->pause_frames_received_hi, pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_hi, estats->pause_frames_received_lo, pstats->mac_stx[1].rx_stat_xoffpauseframesreceived_lo); estats->pause_frames_sent_hi = pstats->mac_stx[1].tx_stat_outxonsent_hi; estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxonsent_lo; ADD_64(estats->pause_frames_sent_hi, pstats->mac_stx[1].tx_stat_outxoffsent_hi, estats->pause_frames_sent_lo, pstats->mac_stx[1].tx_stat_outxoffsent_lo); } static int bnx2x_hw_stats_update(struct bnx2x_softc *sc) { struct nig_stats *new = BNX2X_SP(sc, nig_stats); struct nig_stats *old = &(sc->port.old_nig_stats); struct host_port_stats *pstats = BNX2X_SP(sc, port_stats); struct bnx2x_eth_stats *estats = &sc->eth_stats; uint32_t lpi_reg, nig_timer_max; struct { uint32_t lo; uint32_t hi; } diff; switch (sc->link_vars.mac_type) { case ELINK_MAC_TYPE_BMAC: bnx2x_bmac_stats_update(sc); break; case ELINK_MAC_TYPE_EMAC: bnx2x_emac_stats_update(sc); break; case ELINK_MAC_TYPE_UMAC: case ELINK_MAC_TYPE_XMAC: bnx2x_mstat_stats_update(sc); break; case ELINK_MAC_TYPE_NONE: /* unreached */ PMD_DRV_LOG(DEBUG, "stats updated by DMAE but no MAC active"); return -1; default: /* unreached */ PMD_DRV_LOG(ERR, "stats update failed, unknown MAC type"); } ADD_EXTEND_64(pstats->brb_drop_hi, pstats->brb_drop_lo, new->brb_discard - old->brb_discard); ADD_EXTEND_64(estats->brb_truncate_hi, estats->brb_truncate_lo, new->brb_truncate - old->brb_truncate); if (!CHIP_IS_E3(sc)) { UPDATE_STAT64_NIG(egress_mac_pkt0, etherstatspkts1024octetsto1522octets); UPDATE_STAT64_NIG(egress_mac_pkt1, etherstatspktsover1522octets); } rte_memcpy(old, new, sizeof(struct nig_stats)); rte_memcpy(&(estats->rx_stat_ifhcinbadoctets_hi), &(pstats->mac_stx[1]), sizeof(struct mac_stx)); estats->brb_drop_hi = pstats->brb_drop_hi; estats->brb_drop_lo = pstats->brb_drop_lo; pstats->host_port_stats_counter++; if (CHIP_IS_E3(sc)) { lpi_reg = (SC_PORT(sc)) ? MISC_REG_CPMU_LP_SM_ENT_CNT_P1 : MISC_REG_CPMU_LP_SM_ENT_CNT_P0; estats->eee_tx_lpi += REG_RD(sc, lpi_reg); } if (!BNX2X_NOMCP(sc)) { nig_timer_max = SHMEM_RD(sc, port_mb[SC_PORT(sc)].stat_nig_timer); if (nig_timer_max != estats->nig_timer_max) { estats->nig_timer_max = nig_timer_max; PMD_DRV_LOG(ERR, "invalid NIG timer max (%u)", estats->nig_timer_max); } } return 0; } static int bnx2x_storm_stats_validate_counters(struct bnx2x_softc *sc) { struct stats_counter *counters = &sc->fw_stats_data->storm_counters; uint16_t cur_stats_counter; /* * Make sure we use the value of the counter * used for sending the last stats ramrod. */ cur_stats_counter = (sc->stats_counter - 1); /* are storm stats valid? */ if (le16toh(counters->xstats_counter) != cur_stats_counter) { PMD_DRV_LOG(DEBUG, "stats not updated by xstorm, " "counter 0x%x != stats_counter 0x%x", le16toh(counters->xstats_counter), sc->stats_counter); return -EAGAIN; } if (le16toh(counters->ustats_counter) != cur_stats_counter) { PMD_DRV_LOG(DEBUG, "stats not updated by ustorm, " "counter 0x%x != stats_counter 0x%x", le16toh(counters->ustats_counter), sc->stats_counter); return -EAGAIN; } if (le16toh(counters->cstats_counter) != cur_stats_counter) { PMD_DRV_LOG(DEBUG, "stats not updated by cstorm, " "counter 0x%x != stats_counter 0x%x", le16toh(counters->cstats_counter), sc->stats_counter); return -EAGAIN; } if (le16toh(counters->tstats_counter) != cur_stats_counter) { PMD_DRV_LOG(DEBUG, "stats not updated by tstorm, " "counter 0x%x != stats_counter 0x%x", le16toh(counters->tstats_counter), sc->stats_counter); return -EAGAIN; } return 0; } static int bnx2x_storm_stats_update(struct bnx2x_softc *sc) { struct tstorm_per_port_stats *tport = &sc->fw_stats_data->port.tstorm_port_statistics; struct tstorm_per_pf_stats *tfunc = &sc->fw_stats_data->pf.tstorm_pf_statistics; struct host_func_stats *fstats = &sc->func_stats; struct bnx2x_eth_stats *estats = &sc->eth_stats; struct bnx2x_eth_stats_old *estats_old = &sc->eth_stats_old; int i; /* vfs stat counter is managed by pf */ if (IS_PF(sc) && bnx2x_storm_stats_validate_counters(sc)) { return -EAGAIN; } estats->error_bytes_received_hi = 0; estats->error_bytes_received_lo = 0; for (i = 0; i < sc->num_queues; i++) { struct bnx2x_fastpath *fp = &sc->fp[i]; struct tstorm_per_queue_stats *tclient = &sc->fw_stats_data->queue_stats[i].tstorm_queue_statistics; struct tstorm_per_queue_stats *old_tclient = &fp->old_tclient; struct ustorm_per_queue_stats *uclient = &sc->fw_stats_data->queue_stats[i].ustorm_queue_statistics; struct ustorm_per_queue_stats *old_uclient = &fp->old_uclient; struct xstorm_per_queue_stats *xclient = &sc->fw_stats_data->queue_stats[i].xstorm_queue_statistics; struct xstorm_per_queue_stats *old_xclient = &fp->old_xclient; struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; struct bnx2x_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old; uint32_t diff; /* PMD_DRV_LOG(DEBUG, "queue[%d]: ucast_sent 0x%x bcast_sent 0x%x mcast_sent 0x%x", i, xclient->ucast_pkts_sent, xclient->bcast_pkts_sent, xclient->mcast_pkts_sent); PMD_DRV_LOG(DEBUG, "---------------"); */ UPDATE_QSTAT(tclient->rcv_bcast_bytes, total_broadcast_bytes_received); UPDATE_QSTAT(tclient->rcv_mcast_bytes, total_multicast_bytes_received); UPDATE_QSTAT(tclient->rcv_ucast_bytes, total_unicast_bytes_received); /* * sum to total_bytes_received all * unicast/multicast/broadcast */ qstats->total_bytes_received_hi = qstats->total_broadcast_bytes_received_hi; qstats->total_bytes_received_lo = qstats->total_broadcast_bytes_received_lo; ADD_64(qstats->total_bytes_received_hi, qstats->total_multicast_bytes_received_hi, qstats->total_bytes_received_lo, qstats->total_multicast_bytes_received_lo); ADD_64(qstats->total_bytes_received_hi, qstats->total_unicast_bytes_received_hi, qstats->total_bytes_received_lo, qstats->total_unicast_bytes_received_lo); qstats->valid_bytes_received_hi = qstats->total_bytes_received_hi; qstats->valid_bytes_received_lo = qstats->total_bytes_received_lo; UPDATE_EXTEND_TSTAT(rcv_ucast_pkts, total_unicast_packets_received); UPDATE_EXTEND_TSTAT(rcv_mcast_pkts, total_multicast_packets_received); UPDATE_EXTEND_TSTAT(rcv_bcast_pkts, total_broadcast_packets_received); UPDATE_EXTEND_E_TSTAT(pkts_too_big_discard, etherstatsoverrsizepkts, 32); UPDATE_EXTEND_E_TSTAT(no_buff_discard, no_buff_discard, 16); SUB_EXTEND_USTAT(ucast_no_buff_pkts, total_unicast_packets_received); SUB_EXTEND_USTAT(mcast_no_buff_pkts, total_multicast_packets_received); SUB_EXTEND_USTAT(bcast_no_buff_pkts, total_broadcast_packets_received); UPDATE_EXTEND_E_USTAT(ucast_no_buff_pkts, no_buff_discard); UPDATE_EXTEND_E_USTAT(mcast_no_buff_pkts, no_buff_discard); UPDATE_EXTEND_E_USTAT(bcast_no_buff_pkts, no_buff_discard); UPDATE_QSTAT(xclient->bcast_bytes_sent, total_broadcast_bytes_transmitted); UPDATE_QSTAT(xclient->mcast_bytes_sent, total_multicast_bytes_transmitted); UPDATE_QSTAT(xclient->ucast_bytes_sent, total_unicast_bytes_transmitted); /* * sum to total_bytes_transmitted all * unicast/multicast/broadcast */ qstats->total_bytes_transmitted_hi = qstats->total_unicast_bytes_transmitted_hi; qstats->total_bytes_transmitted_lo = qstats->total_unicast_bytes_transmitted_lo; ADD_64(qstats->total_bytes_transmitted_hi, qstats->total_broadcast_bytes_transmitted_hi, qstats->total_bytes_transmitted_lo, qstats->total_broadcast_bytes_transmitted_lo); ADD_64(qstats->total_bytes_transmitted_hi, qstats->total_multicast_bytes_transmitted_hi, qstats->total_bytes_transmitted_lo, qstats->total_multicast_bytes_transmitted_lo); UPDATE_EXTEND_XSTAT(ucast_pkts_sent, total_unicast_packets_transmitted); UPDATE_EXTEND_XSTAT(mcast_pkts_sent, total_multicast_packets_transmitted); UPDATE_EXTEND_XSTAT(bcast_pkts_sent, total_broadcast_packets_transmitted); UPDATE_EXTEND_TSTAT(checksum_discard, total_packets_received_checksum_discarded); UPDATE_EXTEND_TSTAT(ttl0_discard, total_packets_received_ttl0_discarded); UPDATE_EXTEND_XSTAT(error_drop_pkts, total_transmitted_dropped_packets_error); UPDATE_FSTAT_QSTAT(total_bytes_received); UPDATE_FSTAT_QSTAT(total_bytes_transmitted); UPDATE_FSTAT_QSTAT(total_unicast_packets_received); UPDATE_FSTAT_QSTAT(total_multicast_packets_received); UPDATE_FSTAT_QSTAT(total_broadcast_packets_received); UPDATE_FSTAT_QSTAT(total_unicast_packets_transmitted); UPDATE_FSTAT_QSTAT(total_multicast_packets_transmitted); UPDATE_FSTAT_QSTAT(total_broadcast_packets_transmitted); UPDATE_FSTAT_QSTAT(valid_bytes_received); } ADD_64(estats->total_bytes_received_hi, estats->rx_stat_ifhcinbadoctets_hi, estats->total_bytes_received_lo, estats->rx_stat_ifhcinbadoctets_lo); ADD_64_LE(estats->total_bytes_received_hi, tfunc->rcv_error_bytes.hi, estats->total_bytes_received_lo, tfunc->rcv_error_bytes.lo); ADD_64_LE(estats->error_bytes_received_hi, tfunc->rcv_error_bytes.hi, estats->error_bytes_received_lo, tfunc->rcv_error_bytes.lo); UPDATE_ESTAT(etherstatsoverrsizepkts, rx_stat_dot3statsframestoolong); ADD_64(estats->error_bytes_received_hi, estats->rx_stat_ifhcinbadoctets_hi, estats->error_bytes_received_lo, estats->rx_stat_ifhcinbadoctets_lo); if (sc->port.pmf) { struct bnx2x_fw_port_stats_old *fwstats = &sc->fw_stats_old; UPDATE_FW_STAT(mac_filter_discard); UPDATE_FW_STAT(mf_tag_discard); UPDATE_FW_STAT(brb_truncate_discard); UPDATE_FW_STAT(mac_discard); } fstats->host_func_stats_start = ++fstats->host_func_stats_end; sc->stats_pending = 0; return 0; } static void bnx2x_drv_stats_update(struct bnx2x_softc *sc) { struct bnx2x_eth_stats *estats = &sc->eth_stats; int i; for (i = 0; i < sc->num_queues; i++) { struct bnx2x_eth_q_stats *qstats = &sc->fp[i].eth_q_stats; struct bnx2x_eth_q_stats_old *qstats_old = &sc->fp[i].eth_q_stats_old; UPDATE_ESTAT_QSTAT(rx_calls); UPDATE_ESTAT_QSTAT(rx_pkts); UPDATE_ESTAT_QSTAT(rx_soft_errors); UPDATE_ESTAT_QSTAT(rx_hw_csum_errors); UPDATE_ESTAT_QSTAT(rx_ofld_frames_csum_ip); UPDATE_ESTAT_QSTAT(rx_ofld_frames_csum_tcp_udp); UPDATE_ESTAT_QSTAT(rx_budget_reached); UPDATE_ESTAT_QSTAT(tx_pkts); UPDATE_ESTAT_QSTAT(tx_soft_errors); UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_ip); UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_tcp); UPDATE_ESTAT_QSTAT(tx_ofld_frames_csum_udp); UPDATE_ESTAT_QSTAT(tx_encap_failures); UPDATE_ESTAT_QSTAT(tx_hw_queue_full); UPDATE_ESTAT_QSTAT(tx_hw_max_queue_depth); UPDATE_ESTAT_QSTAT(tx_dma_mapping_failure); UPDATE_ESTAT_QSTAT(tx_max_drbr_queue_depth); UPDATE_ESTAT_QSTAT(tx_window_violation_std); UPDATE_ESTAT_QSTAT(tx_chain_lost_mbuf); UPDATE_ESTAT_QSTAT(tx_frames_deferred); UPDATE_ESTAT_QSTAT(tx_queue_xoff); /* mbuf driver statistics */ UPDATE_ESTAT_QSTAT(mbuf_defrag_attempts); UPDATE_ESTAT_QSTAT(mbuf_defrag_failures); UPDATE_ESTAT_QSTAT(mbuf_rx_bd_alloc_failed); UPDATE_ESTAT_QSTAT(mbuf_rx_bd_mapping_failed); /* track the number of allocated mbufs */ UPDATE_ESTAT_QSTAT(mbuf_alloc_tx); UPDATE_ESTAT_QSTAT(mbuf_alloc_rx); } } static uint8_t bnx2x_edebug_stats_stopped(struct bnx2x_softc *sc) { uint32_t val; if (SHMEM2_HAS(sc, edebug_driver_if[1])) { val = SHMEM2_RD(sc, edebug_driver_if[1]); if (val == EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT) { return TRUE; } } return FALSE; } static void bnx2x_stats_update(struct bnx2x_softc *sc) { uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); if (bnx2x_edebug_stats_stopped(sc)) { return; } if (IS_PF(sc)) { bnx2x_storm_stats_update(sc); bnx2x_hw_stats_post(sc); bnx2x_storm_stats_post(sc); DELAY_MS(5); if (*stats_comp != DMAE_COMP_VAL) { return; } if (sc->port.pmf) { bnx2x_hw_stats_update(sc); } if (bnx2x_storm_stats_update(sc)) { if (sc->stats_pending++ == 3) { rte_panic("storm stats not updated for 3 times"); } return; } } else { /* * VF doesn't collect HW statistics, and doesn't get completions, * performs only update. */ bnx2x_storm_stats_update(sc); } bnx2x_drv_stats_update(sc); } static void bnx2x_port_stats_stop(struct bnx2x_softc *sc) { struct dmae_command *dmae; uint32_t opcode; int loader_idx = PMF_DMAE_C(sc); uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); sc->executer_idx = 0; opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, FALSE, 0); if (sc->port.port_stx) { dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); if (sc->func_stx) { dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_GRC); } else { dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI); } dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, port_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, port_stats)); dmae->dst_addr_lo = sc->port.port_stx >> 2; dmae->dst_addr_hi = 0; dmae->len = bnx2x_get_port_stats_dma_len(sc); if (sc->func_stx) { dmae->comp_addr_lo = (dmae_reg_go_c[loader_idx] >> 2); dmae->comp_addr_hi = 0; dmae->comp_val = 1; } else { dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; } } if (sc->func_stx) { dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = bnx2x_dmae_opcode_add_comp(opcode, DMAE_COMP_PCI); dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, func_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, func_stats)); dmae->dst_addr_lo = (sc->func_stx >> 2); dmae->dst_addr_hi = 0; dmae->len = (sizeof(struct host_func_stats) >> 2); dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; } } static void bnx2x_stats_stop(struct bnx2x_softc *sc) { uint8_t update = FALSE; bnx2x_stats_comp(sc); if (sc->port.pmf) { update = bnx2x_hw_stats_update(sc) == 0; } update |= bnx2x_storm_stats_update(sc) == 0; if (update) { if (sc->port.pmf) { bnx2x_port_stats_stop(sc); } bnx2x_hw_stats_post(sc); bnx2x_stats_comp(sc); } } static void bnx2x_stats_do_nothing(__rte_unused struct bnx2x_softc *sc) { return; } static const struct { void (*action)(struct bnx2x_softc *sc); enum bnx2x_stats_state next_state; } bnx2x_stats_stm[STATS_STATE_MAX][STATS_EVENT_MAX] = { { /* DISABLED PMF */ { bnx2x_stats_pmf_update, STATS_STATE_DISABLED }, /* LINK_UP */ { bnx2x_stats_start, STATS_STATE_ENABLED }, /* UPDATE */ { bnx2x_stats_do_nothing, STATS_STATE_DISABLED }, /* STOP */ { bnx2x_stats_do_nothing, STATS_STATE_DISABLED } }, { /* ENABLED PMF */ { bnx2x_stats_pmf_start, STATS_STATE_ENABLED }, /* LINK_UP */ { bnx2x_stats_restart, STATS_STATE_ENABLED }, /* UPDATE */ { bnx2x_stats_update, STATS_STATE_ENABLED }, /* STOP */ { bnx2x_stats_stop, STATS_STATE_DISABLED } } }; void bnx2x_stats_handle(struct bnx2x_softc *sc, enum bnx2x_stats_event event) { enum bnx2x_stats_state state; if (unlikely(sc->panic)) { return; } state = sc->stats_state; sc->stats_state = bnx2x_stats_stm[state][event].next_state; bnx2x_stats_stm[state][event].action(sc); if (event != STATS_EVENT_UPDATE) { PMD_DRV_LOG(DEBUG, "state %d -> event %d -> state %d", state, event, sc->stats_state); } } static void bnx2x_port_stats_base_init(struct bnx2x_softc *sc) { struct dmae_command *dmae; uint32_t *stats_comp = BNX2X_SP(sc, stats_comp); /* sanity */ if (!sc->port.pmf || !sc->port.port_stx) { PMD_DRV_LOG(ERR, "BUG!"); return; } sc->executer_idx = 0; dmae = BNX2X_SP(sc, dmae[sc->executer_idx++]); dmae->opcode = bnx2x_dmae_opcode(sc, DMAE_SRC_PCI, DMAE_DST_GRC, TRUE, DMAE_COMP_PCI); dmae->src_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, port_stats)); dmae->src_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, port_stats)); dmae->dst_addr_lo = (sc->port.port_stx >> 2); dmae->dst_addr_hi = 0; dmae->len = bnx2x_get_port_stats_dma_len(sc); dmae->comp_addr_lo = U64_LO(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_addr_hi = U64_HI(BNX2X_SP_MAPPING(sc, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; *stats_comp = 0; bnx2x_hw_stats_post(sc); bnx2x_stats_comp(sc); } /* * This function will prepare the statistics ramrod data the way * we will only have to increment the statistics counter and * send the ramrod each time we have to. */ static void bnx2x_prep_fw_stats_req(struct bnx2x_softc *sc) { int i; int first_queue_query_index; struct stats_query_header *stats_hdr = &sc->fw_stats_req->hdr; phys_addr_t cur_data_offset; struct stats_query_entry *cur_query_entry; stats_hdr->cmd_num = sc->fw_stats_num; stats_hdr->drv_stats_counter = 0; /* * The storm_counters struct contains the counters of completed * statistics requests per storm which are incremented by FW * each time it completes hadning a statistics ramrod. We will * check these counters in the timer handler and discard a * (statistics) ramrod completion. */ cur_data_offset = (sc->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, storm_counters)); stats_hdr->stats_counters_addrs.hi = htole32(U64_HI(cur_data_offset)); stats_hdr->stats_counters_addrs.lo = htole32(U64_LO(cur_data_offset)); /* * Prepare the first stats ramrod (will be completed with * the counters equal to zero) - init counters to somethig different. */ memset(&sc->fw_stats_data->storm_counters, 0xff, sizeof(struct stats_counter)); /**** Port FW statistics data ****/ cur_data_offset = (sc->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, port)); cur_query_entry = &sc->fw_stats_req->query[BNX2X_PORT_QUERY_IDX]; cur_query_entry->kind = STATS_TYPE_PORT; /* For port query index is a DONT CARE */ cur_query_entry->index = SC_PORT(sc); /* For port query funcID is a DONT CARE */ cur_query_entry->funcID = htole16(SC_FUNC(sc)); cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset)); cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset)); /**** PF FW statistics data ****/ cur_data_offset = (sc->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, pf)); cur_query_entry = &sc->fw_stats_req->query[BNX2X_PF_QUERY_IDX]; cur_query_entry->kind = STATS_TYPE_PF; /* For PF query index is a DONT CARE */ cur_query_entry->index = SC_PORT(sc); cur_query_entry->funcID = htole16(SC_FUNC(sc)); cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset)); cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset)); /**** Clients' queries ****/ cur_data_offset = (sc->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, queue_stats)); /* * First queue query index depends whether FCoE offloaded request will * be included in the ramrod */ first_queue_query_index = (BNX2X_FIRST_QUEUE_QUERY_IDX - 1); for (i = 0; i < sc->num_queues; i++) { cur_query_entry = &sc->fw_stats_req->query[first_queue_query_index + i]; cur_query_entry->kind = STATS_TYPE_QUEUE; cur_query_entry->index = bnx2x_stats_id(&sc->fp[i]); cur_query_entry->funcID = htole16(SC_FUNC(sc)); cur_query_entry->address.hi = htole32(U64_HI(cur_data_offset)); cur_query_entry->address.lo = htole32(U64_LO(cur_data_offset)); cur_data_offset += sizeof(struct per_queue_stats); } } void bnx2x_memset_stats(struct bnx2x_softc *sc) { int i; /* function stats */ for (i = 0; i < sc->num_queues; i++) { struct bnx2x_fastpath *fp = &sc->fp[i]; memset(&fp->old_tclient, 0, sizeof(fp->old_tclient)); memset(&fp->old_uclient, 0, sizeof(fp->old_uclient)); memset(&fp->old_xclient, 0, sizeof(fp->old_xclient)); if (sc->stats_init) { memset(&fp->eth_q_stats, 0, sizeof(fp->eth_q_stats)); memset(&fp->eth_q_stats_old, 0, sizeof(fp->eth_q_stats_old)); } } if (sc->stats_init) { memset(&sc->net_stats_old, 0, sizeof(sc->net_stats_old)); memset(&sc->fw_stats_old, 0, sizeof(sc->fw_stats_old)); memset(&sc->eth_stats_old, 0, sizeof(sc->eth_stats_old)); memset(&sc->eth_stats, 0, sizeof(sc->eth_stats)); memset(&sc->func_stats, 0, sizeof(sc->func_stats)); } sc->stats_state = STATS_STATE_DISABLED; if (sc->port.pmf && sc->port.port_stx) bnx2x_port_stats_base_init(sc); /* mark the end of statistics initializiation */ sc->stats_init = false; } void bnx2x_stats_init(struct bnx2x_softc *sc) { int /*abs*/port = SC_PORT(sc); int mb_idx = SC_FW_MB_IDX(sc); int i; sc->stats_pending = 0; sc->executer_idx = 0; sc->stats_counter = 0; sc->stats_init = TRUE; /* port and func stats for management */ if (!BNX2X_NOMCP(sc)) { sc->port.port_stx = SHMEM_RD(sc, port_mb[port].port_stx); sc->func_stx = SHMEM_RD(sc, func_mb[mb_idx].fw_mb_param); } else { sc->port.port_stx = 0; sc->func_stx = 0; } PMD_DRV_LOG(DEBUG, "port_stx 0x%x func_stx 0x%x", sc->port.port_stx, sc->func_stx); /* pmf should retrieve port statistics from SP on a non-init*/ if (!sc->stats_init && sc->port.pmf && sc->port.port_stx) { bnx2x_stats_handle(sc, STATS_EVENT_PMF); } port = SC_PORT(sc); /* port stats */ memset(&(sc->port.old_nig_stats), 0, sizeof(struct nig_stats)); sc->port.old_nig_stats.brb_discard = REG_RD(sc, NIG_REG_STAT0_BRB_DISCARD + port*0x38); sc->port.old_nig_stats.brb_truncate = REG_RD(sc, NIG_REG_STAT0_BRB_TRUNCATE + port*0x38); if (!CHIP_IS_E3(sc)) { REG_RD_DMAE(sc, NIG_REG_STAT0_EGRESS_MAC_PKT0 + port*0x50, &(sc->port.old_nig_stats.egress_mac_pkt0_lo), 2); REG_RD_DMAE(sc, NIG_REG_STAT0_EGRESS_MAC_PKT1 + port*0x50, &(sc->port.old_nig_stats.egress_mac_pkt1_lo), 2); } /* function stats */ for (i = 0; i < sc->num_queues; i++) { memset(&sc->fp[i].old_tclient, 0, sizeof(sc->fp[i].old_tclient)); memset(&sc->fp[i].old_uclient, 0, sizeof(sc->fp[i].old_uclient)); memset(&sc->fp[i].old_xclient, 0, sizeof(sc->fp[i].old_xclient)); if (sc->stats_init) { memset(&sc->fp[i].eth_q_stats, 0, sizeof(sc->fp[i].eth_q_stats)); memset(&sc->fp[i].eth_q_stats_old, 0, sizeof(sc->fp[i].eth_q_stats_old)); } } /* prepare statistics ramrod data */ bnx2x_prep_fw_stats_req(sc); if (sc->stats_init) { memset(&sc->net_stats_old, 0, sizeof(sc->net_stats_old)); memset(&sc->fw_stats_old, 0, sizeof(sc->fw_stats_old)); memset(&sc->eth_stats_old, 0, sizeof(sc->eth_stats_old)); memset(&sc->eth_stats, 0, sizeof(sc->eth_stats)); memset(&sc->func_stats, 0, sizeof(sc->func_stats)); /* Clean SP from previous statistics */ if (sc->func_stx) { memset(BNX2X_SP(sc, func_stats), 0, sizeof(struct host_func_stats)); bnx2x_func_stats_init(sc); bnx2x_hw_stats_post(sc); bnx2x_stats_comp(sc); } } sc->stats_state = STATS_STATE_DISABLED; if (sc->port.pmf && sc->port.port_stx) { bnx2x_port_stats_base_init(sc); } /* mark the end of statistics initializiation */ sc->stats_init = FALSE; } void bnx2x_save_statistics(struct bnx2x_softc *sc) { int i; /* save queue statistics */ for (i = 0; i < sc->num_queues; i++) { struct bnx2x_fastpath *fp = &sc->fp[i]; struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats; struct bnx2x_eth_q_stats_old *qstats_old = &fp->eth_q_stats_old; UPDATE_QSTAT_OLD(total_unicast_bytes_received_hi); UPDATE_QSTAT_OLD(total_unicast_bytes_received_lo); UPDATE_QSTAT_OLD(total_broadcast_bytes_received_hi); UPDATE_QSTAT_OLD(total_broadcast_bytes_received_lo); UPDATE_QSTAT_OLD(total_multicast_bytes_received_hi); UPDATE_QSTAT_OLD(total_multicast_bytes_received_lo); UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_hi); UPDATE_QSTAT_OLD(total_unicast_bytes_transmitted_lo); UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_hi); UPDATE_QSTAT_OLD(total_broadcast_bytes_transmitted_lo); UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_hi); UPDATE_QSTAT_OLD(total_multicast_bytes_transmitted_lo); } /* store port firmware statistics */ if (sc->port.pmf) { struct bnx2x_eth_stats *estats = &sc->eth_stats; struct bnx2x_fw_port_stats_old *fwstats = &sc->fw_stats_old; struct host_port_stats *pstats = BNX2X_SP(sc, port_stats); fwstats->pfc_frames_rx_hi = pstats->pfc_frames_rx_hi; fwstats->pfc_frames_rx_lo = pstats->pfc_frames_rx_lo; fwstats->pfc_frames_tx_hi = pstats->pfc_frames_tx_hi; fwstats->pfc_frames_tx_lo = pstats->pfc_frames_tx_lo; if (IS_MF(sc)) { UPDATE_FW_STAT_OLD(mac_filter_discard); UPDATE_FW_STAT_OLD(mf_tag_discard); UPDATE_FW_STAT_OLD(brb_truncate_discard); UPDATE_FW_STAT_OLD(mac_discard); } } } ================================================ FILE: drivers/net/bnx2x/bnx2x_stats.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef BNX2X_STATS_H #define BNX2X_STATS_H #include struct nig_stats { uint32_t brb_discard; uint32_t brb_packet; uint32_t brb_truncate; uint32_t flow_ctrl_discard; uint32_t flow_ctrl_octets; uint32_t flow_ctrl_packet; uint32_t mng_discard; uint32_t mng_octet_inp; uint32_t mng_octet_out; uint32_t mng_packet_inp; uint32_t mng_packet_out; uint32_t pbf_octets; uint32_t pbf_packet; uint32_t safc_inp; uint32_t egress_mac_pkt0_lo; uint32_t egress_mac_pkt0_hi; uint32_t egress_mac_pkt1_lo; uint32_t egress_mac_pkt1_hi; }; enum bnx2x_stats_event { STATS_EVENT_PMF = 0, STATS_EVENT_LINK_UP, STATS_EVENT_UPDATE, STATS_EVENT_STOP, STATS_EVENT_MAX }; enum bnx2x_stats_state { STATS_STATE_DISABLED = 0, STATS_STATE_ENABLED, STATS_STATE_MAX }; struct bnx2x_eth_stats { uint32_t total_bytes_received_hi; uint32_t total_bytes_received_lo; uint32_t total_bytes_transmitted_hi; uint32_t total_bytes_transmitted_lo; uint32_t total_unicast_packets_received_hi; uint32_t total_unicast_packets_received_lo; uint32_t total_multicast_packets_received_hi; uint32_t total_multicast_packets_received_lo; uint32_t total_broadcast_packets_received_hi; uint32_t total_broadcast_packets_received_lo; uint32_t total_unicast_packets_transmitted_hi; uint32_t total_unicast_packets_transmitted_lo; uint32_t total_multicast_packets_transmitted_hi; uint32_t total_multicast_packets_transmitted_lo; uint32_t total_broadcast_packets_transmitted_hi; uint32_t total_broadcast_packets_transmitted_lo; uint32_t valid_bytes_received_hi; uint32_t valid_bytes_received_lo; uint32_t error_bytes_received_hi; uint32_t error_bytes_received_lo; uint32_t etherstatsoverrsizepkts_hi; uint32_t etherstatsoverrsizepkts_lo; uint32_t no_buff_discard_hi; uint32_t no_buff_discard_lo; uint32_t rx_stat_ifhcinbadoctets_hi; uint32_t rx_stat_ifhcinbadoctets_lo; uint32_t tx_stat_ifhcoutbadoctets_hi; uint32_t tx_stat_ifhcoutbadoctets_lo; uint32_t rx_stat_dot3statsfcserrors_hi; uint32_t rx_stat_dot3statsfcserrors_lo; uint32_t rx_stat_dot3statsalignmenterrors_hi; uint32_t rx_stat_dot3statsalignmenterrors_lo; uint32_t rx_stat_dot3statscarriersenseerrors_hi; uint32_t rx_stat_dot3statscarriersenseerrors_lo; uint32_t rx_stat_falsecarriererrors_hi; uint32_t rx_stat_falsecarriererrors_lo; uint32_t rx_stat_etherstatsundersizepkts_hi; uint32_t rx_stat_etherstatsundersizepkts_lo; uint32_t rx_stat_dot3statsframestoolong_hi; uint32_t rx_stat_dot3statsframestoolong_lo; uint32_t rx_stat_etherstatsfragments_hi; uint32_t rx_stat_etherstatsfragments_lo; uint32_t rx_stat_etherstatsjabbers_hi; uint32_t rx_stat_etherstatsjabbers_lo; uint32_t rx_stat_maccontrolframesreceived_hi; uint32_t rx_stat_maccontrolframesreceived_lo; uint32_t rx_stat_bmac_xpf_hi; uint32_t rx_stat_bmac_xpf_lo; uint32_t rx_stat_bmac_xcf_hi; uint32_t rx_stat_bmac_xcf_lo; uint32_t rx_stat_xoffstateentered_hi; uint32_t rx_stat_xoffstateentered_lo; uint32_t rx_stat_xonpauseframesreceived_hi; uint32_t rx_stat_xonpauseframesreceived_lo; uint32_t rx_stat_xoffpauseframesreceived_hi; uint32_t rx_stat_xoffpauseframesreceived_lo; uint32_t tx_stat_outxonsent_hi; uint32_t tx_stat_outxonsent_lo; uint32_t tx_stat_outxoffsent_hi; uint32_t tx_stat_outxoffsent_lo; uint32_t tx_stat_flowcontroldone_hi; uint32_t tx_stat_flowcontroldone_lo; uint32_t tx_stat_etherstatscollisions_hi; uint32_t tx_stat_etherstatscollisions_lo; uint32_t tx_stat_dot3statssinglecollisionframes_hi; uint32_t tx_stat_dot3statssinglecollisionframes_lo; uint32_t tx_stat_dot3statsmultiplecollisionframes_hi; uint32_t tx_stat_dot3statsmultiplecollisionframes_lo; uint32_t tx_stat_dot3statsdeferredtransmissions_hi; uint32_t tx_stat_dot3statsdeferredtransmissions_lo; uint32_t tx_stat_dot3statsexcessivecollisions_hi; uint32_t tx_stat_dot3statsexcessivecollisions_lo; uint32_t tx_stat_dot3statslatecollisions_hi; uint32_t tx_stat_dot3statslatecollisions_lo; uint32_t tx_stat_etherstatspkts64octets_hi; uint32_t tx_stat_etherstatspkts64octets_lo; uint32_t tx_stat_etherstatspkts65octetsto127octets_hi; uint32_t tx_stat_etherstatspkts65octetsto127octets_lo; uint32_t tx_stat_etherstatspkts128octetsto255octets_hi; uint32_t tx_stat_etherstatspkts128octetsto255octets_lo; uint32_t tx_stat_etherstatspkts256octetsto511octets_hi; uint32_t tx_stat_etherstatspkts256octetsto511octets_lo; uint32_t tx_stat_etherstatspkts512octetsto1023octets_hi; uint32_t tx_stat_etherstatspkts512octetsto1023octets_lo; uint32_t tx_stat_etherstatspkts1024octetsto1522octets_hi; uint32_t tx_stat_etherstatspkts1024octetsto1522octets_lo; uint32_t tx_stat_etherstatspktsover1522octets_hi; uint32_t tx_stat_etherstatspktsover1522octets_lo; uint32_t tx_stat_bmac_2047_hi; uint32_t tx_stat_bmac_2047_lo; uint32_t tx_stat_bmac_4095_hi; uint32_t tx_stat_bmac_4095_lo; uint32_t tx_stat_bmac_9216_hi; uint32_t tx_stat_bmac_9216_lo; uint32_t tx_stat_bmac_16383_hi; uint32_t tx_stat_bmac_16383_lo; uint32_t tx_stat_dot3statsinternalmactransmiterrors_hi; uint32_t tx_stat_dot3statsinternalmactransmiterrors_lo; uint32_t tx_stat_bmac_ufl_hi; uint32_t tx_stat_bmac_ufl_lo; uint32_t pause_frames_received_hi; uint32_t pause_frames_received_lo; uint32_t pause_frames_sent_hi; uint32_t pause_frames_sent_lo; uint32_t etherstatspkts1024octetsto1522octets_hi; uint32_t etherstatspkts1024octetsto1522octets_lo; uint32_t etherstatspktsover1522octets_hi; uint32_t etherstatspktsover1522octets_lo; uint32_t brb_drop_hi; uint32_t brb_drop_lo; uint32_t brb_truncate_hi; uint32_t brb_truncate_lo; uint32_t mac_filter_discard; uint32_t mf_tag_discard; uint32_t brb_truncate_discard; uint32_t mac_discard; uint32_t nig_timer_max; /* PFC */ uint32_t pfc_frames_received_hi; uint32_t pfc_frames_received_lo; uint32_t pfc_frames_sent_hi; uint32_t pfc_frames_sent_lo; /* Recovery */ uint32_t recoverable_error; uint32_t unrecoverable_error; /* src: Clear-on-Read register; Will not survive PMF Migration */ uint32_t eee_tx_lpi; /* receive path driver statistics */ uint32_t rx_calls; uint32_t rx_pkts; uint32_t rx_soft_errors; uint32_t rx_hw_csum_errors; uint32_t rx_ofld_frames_csum_ip; uint32_t rx_ofld_frames_csum_tcp_udp; uint32_t rx_budget_reached; /* tx path driver statistics */ uint32_t tx_pkts; uint32_t tx_soft_errors; uint32_t tx_ofld_frames_csum_ip; uint32_t tx_ofld_frames_csum_tcp; uint32_t tx_ofld_frames_csum_udp; uint32_t tx_encap_failures; uint32_t tx_hw_queue_full; uint32_t tx_hw_max_queue_depth; uint32_t tx_dma_mapping_failure; uint32_t tx_max_drbr_queue_depth; uint32_t tx_window_violation_std; uint32_t tx_chain_lost_mbuf; uint32_t tx_frames_deferred; uint32_t tx_queue_xoff; /* mbuf driver statistics */ uint32_t mbuf_defrag_attempts; uint32_t mbuf_defrag_failures; uint32_t mbuf_rx_bd_alloc_failed; uint32_t mbuf_rx_bd_mapping_failed; /* track the number of allocated mbufs */ uint32_t mbuf_alloc_tx; uint32_t mbuf_alloc_rx; }; struct bnx2x_eth_q_stats { uint32_t total_unicast_bytes_received_hi; uint32_t total_unicast_bytes_received_lo; uint32_t total_broadcast_bytes_received_hi; uint32_t total_broadcast_bytes_received_lo; uint32_t total_multicast_bytes_received_hi; uint32_t total_multicast_bytes_received_lo; uint32_t total_bytes_received_hi; uint32_t total_bytes_received_lo; uint32_t total_unicast_bytes_transmitted_hi; uint32_t total_unicast_bytes_transmitted_lo; uint32_t total_broadcast_bytes_transmitted_hi; uint32_t total_broadcast_bytes_transmitted_lo; uint32_t total_multicast_bytes_transmitted_hi; uint32_t total_multicast_bytes_transmitted_lo; uint32_t total_bytes_transmitted_hi; uint32_t total_bytes_transmitted_lo; uint32_t total_unicast_packets_received_hi; uint32_t total_unicast_packets_received_lo; uint32_t total_multicast_packets_received_hi; uint32_t total_multicast_packets_received_lo; uint32_t total_broadcast_packets_received_hi; uint32_t total_broadcast_packets_received_lo; uint32_t total_unicast_packets_transmitted_hi; uint32_t total_unicast_packets_transmitted_lo; uint32_t total_multicast_packets_transmitted_hi; uint32_t total_multicast_packets_transmitted_lo; uint32_t total_broadcast_packets_transmitted_hi; uint32_t total_broadcast_packets_transmitted_lo; uint32_t valid_bytes_received_hi; uint32_t valid_bytes_received_lo; uint32_t etherstatsoverrsizepkts_hi; uint32_t etherstatsoverrsizepkts_lo; uint32_t no_buff_discard_hi; uint32_t no_buff_discard_lo; uint32_t total_packets_received_checksum_discarded_hi; uint32_t total_packets_received_checksum_discarded_lo; uint32_t total_packets_received_ttl0_discarded_hi; uint32_t total_packets_received_ttl0_discarded_lo; uint32_t total_transmitted_dropped_packets_error_hi; uint32_t total_transmitted_dropped_packets_error_lo; /* receive path driver statistics */ uint32_t rx_calls; uint32_t rx_pkts; uint32_t rx_soft_errors; uint32_t rx_hw_csum_errors; uint32_t rx_ofld_frames_csum_ip; uint32_t rx_ofld_frames_csum_tcp_udp; uint32_t rx_budget_reached; /* tx path driver statistics */ uint32_t tx_pkts; uint32_t tx_soft_errors; uint32_t tx_ofld_frames_csum_ip; uint32_t tx_ofld_frames_csum_tcp; uint32_t tx_ofld_frames_csum_udp; uint32_t tx_encap_failures; uint32_t tx_hw_queue_full; uint32_t tx_hw_max_queue_depth; uint32_t tx_dma_mapping_failure; uint32_t tx_max_drbr_queue_depth; uint32_t tx_window_violation_std; uint32_t tx_chain_lost_mbuf; uint32_t tx_frames_deferred; uint32_t tx_queue_xoff; /* mbuf driver statistics */ uint32_t mbuf_defrag_attempts; uint32_t mbuf_defrag_failures; uint32_t mbuf_rx_bd_alloc_failed; uint32_t mbuf_rx_bd_mapping_failed; /* track the number of allocated mbufs */ uint32_t mbuf_alloc_tx; uint32_t mbuf_alloc_rx; }; struct bnx2x_eth_stats_old { uint32_t rx_stat_dot3statsframestoolong_hi; uint32_t rx_stat_dot3statsframestoolong_lo; }; struct bnx2x_eth_q_stats_old { /* Fields to perserve over fw reset*/ uint32_t total_unicast_bytes_received_hi; uint32_t total_unicast_bytes_received_lo; uint32_t total_broadcast_bytes_received_hi; uint32_t total_broadcast_bytes_received_lo; uint32_t total_multicast_bytes_received_hi; uint32_t total_multicast_bytes_received_lo; uint32_t total_unicast_bytes_transmitted_hi; uint32_t total_unicast_bytes_transmitted_lo; uint32_t total_broadcast_bytes_transmitted_hi; uint32_t total_broadcast_bytes_transmitted_lo; uint32_t total_multicast_bytes_transmitted_hi; uint32_t total_multicast_bytes_transmitted_lo; /* Fields to perserve last of */ uint32_t total_bytes_received_hi; uint32_t total_bytes_received_lo; uint32_t total_bytes_transmitted_hi; uint32_t total_bytes_transmitted_lo; uint32_t total_unicast_packets_received_hi; uint32_t total_unicast_packets_received_lo; uint32_t total_multicast_packets_received_hi; uint32_t total_multicast_packets_received_lo; uint32_t total_broadcast_packets_received_hi; uint32_t total_broadcast_packets_received_lo; uint32_t total_unicast_packets_transmitted_hi; uint32_t total_unicast_packets_transmitted_lo; uint32_t total_multicast_packets_transmitted_hi; uint32_t total_multicast_packets_transmitted_lo; uint32_t total_broadcast_packets_transmitted_hi; uint32_t total_broadcast_packets_transmitted_lo; uint32_t valid_bytes_received_hi; uint32_t valid_bytes_received_lo; /* receive path driver statistics */ uint32_t rx_calls_old; uint32_t rx_pkts_old; uint32_t rx_soft_errors_old; uint32_t rx_hw_csum_errors_old; uint32_t rx_ofld_frames_csum_ip_old; uint32_t rx_ofld_frames_csum_tcp_udp_old; uint32_t rx_budget_reached_old; /* tx path driver statistics */ uint32_t tx_pkts_old; uint32_t tx_soft_errors_old; uint32_t tx_ofld_frames_csum_ip_old; uint32_t tx_ofld_frames_csum_tcp_old; uint32_t tx_ofld_frames_csum_udp_old; uint32_t tx_encap_failures_old; uint32_t tx_hw_queue_full_old; uint32_t tx_hw_max_queue_depth_old; uint32_t tx_dma_mapping_failure_old; uint32_t tx_max_drbr_queue_depth_old; uint32_t tx_window_violation_std_old; uint32_t tx_chain_lost_mbuf_old; uint32_t tx_frames_deferred_old; uint32_t tx_queue_xoff_old; /* mbuf driver statistics */ uint32_t mbuf_defrag_attempts_old; uint32_t mbuf_defrag_failures_old; uint32_t mbuf_rx_bd_alloc_failed_old; uint32_t mbuf_rx_bd_mapping_failed_old; /* track the number of allocated mbufs */ int mbuf_alloc_tx_old; int mbuf_alloc_rx_old; }; struct bnx2x_net_stats_old { uint32_t rx_dropped; }; struct bnx2x_fw_port_stats_old { uint32_t pfc_frames_tx_hi; uint32_t pfc_frames_tx_lo; uint32_t pfc_frames_rx_hi; uint32_t pfc_frames_rx_lo; uint32_t mac_filter_discard; uint32_t mf_tag_discard; uint32_t brb_truncate_discard; uint32_t mac_discard; }; /* sum[hi:lo] += add[hi:lo] */ #define ADD_64(s_hi, a_hi, s_lo, a_lo) \ do { \ s_lo += a_lo; \ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \ } while (0) #define LE32_0 ((uint32_t) 0) #define LE16_0 ((uint16_t) 0) /* The _force is for cases where high value is 0 */ #define ADD_64_LE(s_hi, a_hi_le, s_lo, a_lo_le) \ ADD_64(s_hi, le32toh(a_hi_le), \ s_lo, le32toh(a_lo_le)) #define ADD_64_LE16(s_hi, a_hi_le, s_lo, a_lo_le) \ ADD_64(s_hi, le16toh(a_hi_le), \ s_lo, le16toh(a_lo_le)) /* difference = minuend - subtrahend */ #define DIFF_64(d_hi, m_hi, s_hi, d_lo, m_lo, s_lo) \ do { \ if (m_lo < s_lo) { \ /* underflow */ \ d_hi = m_hi - s_hi; \ if (d_hi > 0) { \ /* we can 'loan' 1 */ \ d_hi--; \ d_lo = m_lo + (UINT_MAX - s_lo) + 1; \ } else { \ /* m_hi <= s_hi */ \ d_hi = 0; \ d_lo = 0; \ } \ } else { \ /* m_lo >= s_lo */ \ if (m_hi < s_hi) { \ d_hi = 0; \ d_lo = 0; \ } else { \ /* m_hi >= s_hi */ \ d_hi = m_hi - s_hi; \ d_lo = m_lo - s_lo; \ } \ } \ } while (0) #define UPDATE_STAT64(s, t) \ do { \ DIFF_64(diff.hi, new->s##_hi, pstats->mac_stx[0].t##_hi, \ diff.lo, new->s##_lo, pstats->mac_stx[0].t##_lo); \ pstats->mac_stx[0].t##_hi = new->s##_hi; \ pstats->mac_stx[0].t##_lo = new->s##_lo; \ ADD_64(pstats->mac_stx[1].t##_hi, diff.hi, \ pstats->mac_stx[1].t##_lo, diff.lo); \ } while (0) #define UPDATE_STAT64_NIG(s, t) \ do { \ DIFF_64(diff.hi, new->s##_hi, old->s##_hi, \ diff.lo, new->s##_lo, old->s##_lo); \ ADD_64(estats->t##_hi, diff.hi, \ estats->t##_lo, diff.lo); \ } while (0) /* sum[hi:lo] += add */ #define ADD_EXTEND_64(s_hi, s_lo, a) \ do { \ s_lo += a; \ s_hi += (s_lo < a) ? 1 : 0; \ } while (0) #define ADD_STAT64(diff, t) \ do { \ ADD_64(pstats->mac_stx[1].t##_hi, new->diff##_hi, \ pstats->mac_stx[1].t##_lo, new->diff##_lo); \ } while (0) #define UPDATE_EXTEND_STAT(s) \ do { \ ADD_EXTEND_64(pstats->mac_stx[1].s##_hi, \ pstats->mac_stx[1].s##_lo, \ new->s); \ } while (0) #define UPDATE_EXTEND_TSTAT_X(s, t, size) \ do { \ diff = le##size##toh(tclient->s) - \ le##size##toh(old_tclient->s); \ old_tclient->s = tclient->s; \ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ } while (0) #define UPDATE_EXTEND_TSTAT(s, t) UPDATE_EXTEND_TSTAT_X(s, t, 32) #define UPDATE_EXTEND_E_TSTAT(s, t, size) \ do { \ UPDATE_EXTEND_TSTAT_X(s, t, size); \ ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \ } while (0) #define UPDATE_EXTEND_USTAT(s, t) \ do { \ diff = le32toh(uclient->s) - le32toh(old_uclient->s); \ old_uclient->s = uclient->s; \ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ } while (0) #define UPDATE_EXTEND_E_USTAT(s, t) \ do { \ UPDATE_EXTEND_USTAT(s, t); \ ADD_EXTEND_64(estats->t##_hi, estats->t##_lo, diff); \ } while (0) #define UPDATE_EXTEND_XSTAT(s, t) \ do { \ diff = le32toh(xclient->s) - le32toh(old_xclient->s); \ old_xclient->s = xclient->s; \ ADD_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ } while (0) #define UPDATE_QSTAT(s, t) \ do { \ qstats->t##_hi = qstats_old->t##_hi + le32toh(s.hi); \ qstats->t##_lo = qstats_old->t##_lo + le32toh(s.lo); \ } while (0) #define UPDATE_QSTAT_OLD(f) \ do { \ qstats_old->f = qstats->f; \ } while (0) #define UPDATE_ESTAT_QSTAT_64(s) \ do { \ ADD_64(estats->s##_hi, qstats->s##_hi, \ estats->s##_lo, qstats->s##_lo); \ SUB_64(estats->s##_hi, qstats_old->s##_hi_old, \ estats->s##_lo, qstats_old->s##_lo_old); \ qstats_old->s##_hi_old = qstats->s##_hi; \ qstats_old->s##_lo_old = qstats->s##_lo; \ } while (0) #define UPDATE_ESTAT_QSTAT(s) \ do { \ estats->s += qstats->s; \ estats->s -= qstats_old->s##_old; \ qstats_old->s##_old = qstats->s; \ } while (0) #define UPDATE_FSTAT_QSTAT(s) \ do { \ ADD_64(fstats->s##_hi, qstats->s##_hi, \ fstats->s##_lo, qstats->s##_lo); \ SUB_64(fstats->s##_hi, qstats_old->s##_hi, \ fstats->s##_lo, qstats_old->s##_lo); \ estats->s##_hi = fstats->s##_hi; \ estats->s##_lo = fstats->s##_lo; \ qstats_old->s##_hi = qstats->s##_hi; \ qstats_old->s##_lo = qstats->s##_lo; \ } while (0) #define UPDATE_FW_STAT(s) \ do { \ estats->s = le32toh(tport->s) + fwstats->s; \ } while (0) #define UPDATE_FW_STAT_OLD(f) \ do { \ fwstats->f = estats->f; \ } while (0) #define UPDATE_ESTAT(s, t) \ do { \ SUB_64(estats->s##_hi, estats_old->t##_hi, \ estats->s##_lo, estats_old->t##_lo); \ ADD_64(estats->s##_hi, estats->t##_hi, \ estats->s##_lo, estats->t##_lo); \ estats_old->t##_hi = estats->t##_hi; \ estats_old->t##_lo = estats->t##_lo; \ } while (0) /* minuend -= subtrahend */ #define SUB_64(m_hi, s_hi, m_lo, s_lo) \ do { \ DIFF_64(m_hi, m_hi, s_hi, m_lo, m_lo, s_lo); \ } while (0) /* minuend[hi:lo] -= subtrahend */ #define SUB_EXTEND_64(m_hi, m_lo, s) \ do { \ uint32_t s_hi = 0; \ SUB_64(m_hi, s_hi, m_lo, s); \ } while (0) #define SUB_EXTEND_USTAT(s, t) \ do { \ diff = le32toh(uclient->s) - le32toh(old_uclient->s); \ SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ } while (0) struct bnx2x_softc; void bnx2x_stats_init(struct bnx2x_softc *sc); void bnx2x_stats_handle(struct bnx2x_softc *sc, enum bnx2x_stats_event event); void bnx2x_save_statistics(struct bnx2x_softc *sc); void bnx2x_memset_stats(struct bnx2x_softc *sc); #endif /* BNX2X_STATS_H */ ================================================ FILE: drivers/net/bnx2x/bnx2x_vfpf.c ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #include "bnx2x.h" /* calculate the crc in the bulletin board */ static inline uint32_t bnx2x_vf_crc(struct bnx2x_vf_bulletin *bull) { uint32_t crc_sz = sizeof(bull->crc), length = bull->length - crc_sz; return ECORE_CRC32_LE(0, (uint8_t *)bull + crc_sz, length); } /* Checks are there mac/channel updates for VF * returns TRUE if something was updated */ int bnx2x_check_bull(struct bnx2x_softc *sc) { struct bnx2x_vf_bulletin *bull; uint8_t tries = 0; uint16_t old_version = sc->old_bulletin.version; uint64_t valid_bitmap; bull = sc->pf2vf_bulletin; if (old_version == bull->version) { return FALSE; } else { /* Check the crc until we get the correct data */ while (tries < BNX2X_VF_BULLETIN_TRIES) { bull = sc->pf2vf_bulletin; if (bull->crc == bnx2x_vf_crc(bull)) break; PMD_DRV_LOG(ERR, "bad crc on bulletin board. contained %x computed %x", bull->crc, bnx2x_vf_crc(bull)); ++tries; } if (tries == BNX2X_VF_BULLETIN_TRIES) { PMD_DRV_LOG(ERR, "pf to vf bulletin board crc was wrong %d consecutive times. Aborting", tries); return FALSE; } } valid_bitmap = bull->valid_bitmap; /* check the mac address and VLAN and allocate memory if valid */ if (valid_bitmap & (1 << MAC_ADDR_VALID) && memcmp(bull->mac, sc->old_bulletin.mac, ETH_ALEN)) rte_memcpy(&sc->link_params.mac_addr, bull->mac, ETH_ALEN); if (valid_bitmap & (1 << VLAN_VALID)) rte_memcpy(&bull->vlan, &sc->old_bulletin.vlan, VLAN_HLEN); sc->old_bulletin = *bull; return TRUE; } /* add tlv to a buffer */ #define BNX2X_TLV_APPEND(_tlvs, _offset, _type, _length) \ ((struct vf_first_tlv *)((uint64_t)_tlvs + _offset))->type = _type; \ ((struct vf_first_tlv *)((uint64_t)_tlvs + _offset))->length = _length /* Initiliaze header of the first tlv and clear mailbox*/ static void bnx2x_init_first_tlv(struct bnx2x_softc *sc, struct vf_first_tlv *tlv, uint16_t type, uint16_t len) { struct bnx2x_vf_mbx_msg *mbox = sc->vf2pf_mbox; PMD_DRV_LOG(DEBUG, "Preparing %d tlv for sending", type); memset(mbox, 0, sizeof(struct bnx2x_vf_mbx_msg)); BNX2X_TLV_APPEND(tlv, 0, type, len); /* Initialize header of the first tlv */ tlv->reply_offset = sizeof(mbox->query); } #define BNX2X_VF_CMD_ADDR_LO PXP_VF_ADDR_CSDM_GLOBAL_START #define BNX2X_VF_CMD_ADDR_HI BNX2X_VF_CMD_ADDR_LO + 4 #define BNX2X_VF_CMD_TRIGGER BNX2X_VF_CMD_ADDR_HI + 4 #define BNX2X_VF_CHANNEL_DELAY 100 #define BNX2X_VF_CHANNEL_TRIES 100 static int bnx2x_do_req4pf(struct bnx2x_softc *sc, phys_addr_t phys_addr) { uint8_t *status = &sc->vf2pf_mbox->resp.common_reply.status; uint8_t i; if (!*status) { bnx2x_check_bull(sc); if (sc->old_bulletin.valid_bitmap & (1 << CHANNEL_DOWN)) { PMD_DRV_LOG(ERR, "channel is down. Aborting message sending"); *status = BNX2X_VF_STATUS_SUCCESS; return 0; } REG_WR(sc, BNX2X_VF_CMD_ADDR_LO, U64_LO(phys_addr)); REG_WR(sc, BNX2X_VF_CMD_ADDR_HI, U64_HI(phys_addr)); /* memory barrier to ensure that FW can read phys_addr */ wmb(); REG_WR8(sc, BNX2X_VF_CMD_TRIGGER, 1); /* Do several attempts until PF completes * "." is used to show progress */ for (i = 0; i < BNX2X_VF_CHANNEL_TRIES; i++) { DELAY_MS(BNX2X_VF_CHANNEL_DELAY); if (*status) break; } if (i == BNX2X_VF_CHANNEL_TRIES) { PMD_DRV_LOG(ERR, "Response from PF timed out"); return -EAGAIN; } if (BNX2X_VF_STATUS_SUCCESS != *status) { PMD_DRV_LOG(ERR, "Bad reply from PF : %u", *status); return -EINVAL; } } else { PMD_DRV_LOG(ERR, "status should be zero before message" "to pf was sent"); return -EINVAL; } PMD_DRV_LOG(DEBUG, "Response from PF was received"); return 0; } static inline uint16_t bnx2x_check_me_flags(uint32_t val) { if (((val) & ME_REG_VF_VALID) && (!((val) & ME_REG_VF_ERR))) return ME_REG_VF_VALID; else return 0; } #define BNX2X_ME_ANSWER_DELAY 100 #define BNX2X_ME_ANSWER_TRIES 10 static inline int bnx2x_read_vf_id(struct bnx2x_softc *sc) { uint32_t val; uint8_t i = 0; while (i <= BNX2X_ME_ANSWER_TRIES) { val = BNX2X_DB_READ(DOORBELL_ADDR(sc, 0)); if (bnx2x_check_me_flags(val)) return VF_ID(val); DELAY_MS(BNX2X_ME_ANSWER_DELAY); i++; } return -EINVAL; } #define BNX2X_VF_OBTAIN_MAX_TRIES 3 #define BNX2X_VF_OBTAIN_MAC_FILTERS 1 #define BNX2X_VF_OBTAIN_MC_FILTERS 10 struct bnx2x_obtain_status { int success; int err_code; }; static struct bnx2x_obtain_status bnx2x_loop_obtain_resources(struct bnx2x_softc *sc) { int tries = 0; struct vf_acquire_resp_tlv *resp = &sc->vf2pf_mbox->resp.acquire_resp, *sc_resp = &sc->acquire_resp; struct vf_resource_query *res_query; struct vf_resc *resc; struct bnx2x_obtain_status status; int res_obtained = false; do { PMD_DRV_LOG(DEBUG, "trying to get resources"); if ( bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr) ) { /* timeout */ status.success = 0; status.err_code = 0; return status; } memcpy(sc_resp, resp, sizeof(sc->acquire_resp)); tries++; /* check PF to request acceptance */ if (sc_resp->status == BNX2X_VF_STATUS_SUCCESS) { PMD_DRV_LOG(DEBUG, "resources obtained successfully"); res_obtained = true; } else if (sc_resp->status == BNX2X_VF_STATUS_NO_RESOURCES && tries < BNX2X_VF_OBTAIN_MAX_TRIES) { PMD_DRV_LOG(DEBUG, "PF cannot allocate requested amount of resources"); res_query = &sc->vf2pf_mbox->query[0].acquire.res_query; resc = &sc_resp->resc; /* PF refused our request. Try to decrease request params */ res_query->num_txqs = min(res_query->num_txqs, resc->num_txqs); res_query->num_rxqs = min(res_query->num_rxqs, resc->num_rxqs); res_query->num_sbs = min(res_query->num_sbs, resc->num_sbs); res_query->num_mac_filters = min(res_query->num_mac_filters, resc->num_mac_filters); res_query->num_vlan_filters = min(res_query->num_vlan_filters, resc->num_vlan_filters); res_query->num_mc_filters = min(res_query->num_mc_filters, resc->num_mc_filters); memset(&sc->vf2pf_mbox->resp, 0, sizeof(union resp_tlvs)); } else { PMD_DRV_LOG(ERR, "Resources cannot be obtained. Status of handling: %d. Aborting", sc_resp->status); status.success = 0; status.err_code = -EAGAIN; return status; } } while (!res_obtained); status.success = 1; return status; } int bnx2x_vf_get_resources(struct bnx2x_softc *sc, uint8_t tx_count, uint8_t rx_count) { struct vf_acquire_tlv *acq = &sc->vf2pf_mbox->query[0].acquire; int vf_id; struct bnx2x_obtain_status obtain_status; bnx2x_vf_close(sc); bnx2x_init_first_tlv(sc, &acq->first_tlv, BNX2X_VF_TLV_ACQUIRE, sizeof(*acq)); vf_id = bnx2x_read_vf_id(sc); if (vf_id < 0) return -EAGAIN; acq->vf_id = vf_id; acq->res_query.num_rxqs = rx_count; acq->res_query.num_txqs = tx_count; acq->res_query.num_sbs = sc->igu_sb_cnt; acq->res_query.num_mac_filters = BNX2X_VF_OBTAIN_MAC_FILTERS; acq->res_query.num_mc_filters = BNX2X_VF_OBTAIN_MC_FILTERS; acq->bulletin_addr = sc->pf2vf_bulletin_mapping.paddr; BNX2X_TLV_APPEND(acq, acq->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); /* requesting the resources in loop */ obtain_status = bnx2x_loop_obtain_resources(sc); if (!obtain_status.success) return obtain_status.err_code; struct vf_acquire_resp_tlv sc_resp = sc->acquire_resp; sc->devinfo.chip_id |= (sc_resp.chip_num & 0xFFFF); sc->devinfo.int_block = INT_BLOCK_IGU; sc->devinfo.chip_port_mode = CHIP_2_PORT_MODE; sc->devinfo.mf_info.mf_ov = 0; sc->devinfo.mf_info.mf_mode = 0; sc->devinfo.flash_size = 0; sc->igu_sb_cnt = sc_resp.resc.num_sbs; sc->igu_base_sb = sc_resp.resc.hw_sbs[0] & 0xFF; sc->igu_dsb_id = -1; sc->link_params.chip_id = sc->devinfo.chip_id; sc->doorbell_size = sc_resp.db_size; sc->flags |= BNX2X_NO_WOL_FLAG | BNX2X_NO_ISCSI_OOO_FLAG | BNX2X_NO_ISCSI_FLAG | BNX2X_NO_FCOE_FLAG; PMD_DRV_LOG(DEBUG, "status block count = %d, base status block = %x", sc->igu_sb_cnt, sc->igu_base_sb); strncpy(sc->fw_ver, sc_resp.fw_ver, sizeof(sc->fw_ver)); if (is_valid_ether_addr(sc_resp.resc.current_mac_addr)) (void)rte_memcpy(sc->link_params.mac_addr, sc_resp.resc.current_mac_addr, ETH_ALEN); return 0; } /* Ask PF to release VF's resources */ void bnx2x_vf_close(struct bnx2x_softc *sc) { struct vf_release_tlv *query; int vf_id = bnx2x_read_vf_id(sc); int ret; if (vf_id >= 0) { query = &sc->vf2pf_mbox->query[0].release; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_RELEASE, sizeof(*query)); query->vf_id = vf_id; BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to release VF"); } } } /* Let PF know the VF status blocks phys_addrs */ int bnx2x_vf_init(struct bnx2x_softc *sc) { struct vf_init_tlv *query; int i, ret; query = &sc->vf2pf_mbox->query[0].init; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_INIT, sizeof(*query)); FOR_EACH_QUEUE(sc, i) { query->sb_addr[i] = (unsigned long)(sc->fp[i].sb_dma.paddr); } query->stats_step = sizeof(struct per_queue_stats); query->stats_addr = sc->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, queue_stats); BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to init VF"); return ret; } PMD_DRV_LOG(DEBUG, "VF was initialized"); return 0; } void bnx2x_vf_unload(struct bnx2x_softc *sc) { struct vf_close_tlv *query; struct vf_q_op_tlv *query_op; int i, vf_id, ret; vf_id = bnx2x_read_vf_id(sc); if (vf_id > 0) { FOR_EACH_QUEUE(sc, i) { query_op = &sc->vf2pf_mbox->query[0].q_op; bnx2x_init_first_tlv(sc, &query_op->first_tlv, BNX2X_VF_TLV_TEARDOWN_Q, sizeof(*query_op)); query_op->vf_qid = i; BNX2X_TLV_APPEND(query_op, query_op->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) PMD_DRV_LOG(ERR, "Bad reply for vf_q %d teardown", i); } bnx2x_vf_set_mac(sc, false); query = &sc->vf2pf_mbox->query[0].close; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_CLOSE, sizeof(*query)); query->vf_id = vf_id; BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) PMD_DRV_LOG(ERR, "Bad reply from PF for close message"); } } static inline uint16_t bnx2x_vf_q_flags(uint8_t leading) { uint16_t flags = leading ? BNX2X_VF_Q_FLAG_LEADING_RSS : 0; flags |= BNX2X_VF_Q_FLAG_CACHE_ALIGN; flags |= BNX2X_VF_Q_FLAG_STATS; flags |= BNX2X_VF_Q_FLAG_VLAN; return flags; } static void bnx2x_vf_rx_q_prep(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct vf_rxq_params *rxq_init, uint16_t flags) { struct bnx2x_rx_queue *rxq; rxq = sc->rx_queues[fp->index]; if (!rxq) { PMD_DRV_LOG(ERR, "RX queue %d is NULL", fp->index); return; } rxq_init->rcq_addr = rxq->cq_ring_phys_addr; rxq_init->rcq_np_addr = rxq->cq_ring_phys_addr + BNX2X_PAGE_SIZE; rxq_init->rxq_addr = rxq->rx_ring_phys_addr; rxq_init->vf_sb_id = fp->index; rxq_init->sb_cq_index = HC_INDEX_ETH_RX_CQ_CONS; rxq_init->mtu = sc->mtu; rxq_init->buf_sz = fp->rx_buf_size; rxq_init->flags = flags; rxq_init->stat_id = -1; rxq_init->cache_line_log = BNX2X_RX_ALIGN_SHIFT; } static void bnx2x_vf_tx_q_prep(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, struct vf_txq_params *txq_init, uint16_t flags) { struct bnx2x_tx_queue *txq; txq = sc->tx_queues[fp->index]; if (!txq) { PMD_DRV_LOG(ERR, "TX queue %d is NULL", fp->index); return; } txq_init->txq_addr = txq->tx_ring_phys_addr; txq_init->sb_index = HC_INDEX_ETH_TX_CQ_CONS_COS0; txq_init->flags = flags; txq_init->traffic_type = LLFC_TRAFFIC_TYPE_NW; txq_init->vf_sb_id = fp->index; } int bnx2x_vf_setup_queue(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp, int leading) { struct vf_setup_q_tlv *query; uint16_t flags = bnx2x_vf_q_flags(leading); int ret; query = &sc->vf2pf_mbox->query[0].setup_q; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_SETUP_Q, sizeof(*query)); query->vf_qid = fp->index; query->param_valid = VF_RXQ_VALID | VF_TXQ_VALID; bnx2x_vf_rx_q_prep(sc, fp, &query->rxq, flags); bnx2x_vf_tx_q_prep(sc, fp, &query->txq, flags); BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to setup VF queue[%d]", fp->index); return -EINVAL; } return 0; } int bnx2x_vf_set_mac(struct bnx2x_softc *sc, int set) { struct vf_set_q_filters_tlv *query; struct vf_common_reply_tlv *reply; query = &sc->vf2pf_mbox->query[0].set_q_filters; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_SET_Q_FILTERS, sizeof(*query)); query->vf_qid = sc->fp->index; query->mac_filters_cnt = 1; query->flags = BNX2X_VF_MAC_VLAN_CHANGED; query->filters[0].flags = (set ? BNX2X_VF_Q_FILTER_SET_MAC : 0) | BNX2X_VF_Q_FILTER_DEST_MAC_VALID; bnx2x_check_bull(sc); rte_memcpy(query->filters[0].mac, sc->link_params.mac_addr, ETH_ALEN); BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); reply = &sc->vf2pf_mbox->resp.common_reply; while (BNX2X_VF_STATUS_FAILURE == reply->status && bnx2x_check_bull(sc)) { /* A new mac was configured by PF for us */ rte_memcpy(sc->link_params.mac_addr, sc->pf2vf_bulletin->mac, ETH_ALEN); rte_memcpy(query->filters[0].mac, sc->pf2vf_bulletin->mac, ETH_ALEN); bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); } if (BNX2X_VF_STATUS_SUCCESS != reply->status) { PMD_DRV_LOG(ERR, "Bad reply from PF for SET MAC message: %d", reply->status); return -EINVAL; } return 0; } int bnx2x_vf_config_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *params) { struct vf_rss_tlv *query; int ret; query = &sc->vf2pf_mbox->query[0].update_rss; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_UPDATE_RSS, sizeof(*query)); /* add list termination tlv */ BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); rte_memcpy(query->rss_key, params->rss_key, sizeof(params->rss_key)); query->rss_key_size = T_ETH_RSS_KEY; rte_memcpy(query->ind_table, params->ind_table, T_ETH_INDIRECTION_TABLE_SIZE); query->ind_table_size = T_ETH_INDIRECTION_TABLE_SIZE; query->rss_result_mask = params->rss_result_mask; query->rss_flags = params->rss_flags; ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to send message to PF, rc %d", ret); return ret; } return 0; } int bnx2x_vf_set_rx_mode(struct bnx2x_softc *sc) { struct vf_set_q_filters_tlv *query; unsigned long tx_mask; int ret; query = &sc->vf2pf_mbox->query[0].set_q_filters; bnx2x_init_first_tlv(sc, &query->first_tlv, BNX2X_VF_TLV_SET_Q_FILTERS, sizeof(*query)); query->vf_qid = 0; query->flags = BNX2X_VF_RX_MASK_CHANGED; if (bnx2x_fill_accept_flags(sc, sc->rx_mode, &query->rx_mask, &tx_mask)) { return -EINVAL; } BNX2X_TLV_APPEND(query, query->first_tlv.length, BNX2X_VF_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); ret = bnx2x_do_req4pf(sc, sc->vf2pf_mbox_mapping.paddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to send message to PF, rc %d", ret); return ret; } return 0; } ================================================ FILE: drivers/net/bnx2x/bnx2x_vfpf.h ================================================ /* * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * * All rights reserved. */ #ifndef BNX2X_VFPF_H #define BNX2X_VFPF_H #include "ecore_sp.h" #define VLAN_HLEN 4 struct vf_resource_query { uint8_t num_rxqs; uint8_t num_txqs; uint8_t num_sbs; uint8_t num_mac_filters; uint8_t num_vlan_filters; uint8_t num_mc_filters; }; #define BNX2X_VF_STATUS_SUCCESS 1 #define BNX2X_VF_STATUS_FAILURE 2 #define BNX2X_VF_STATUS_NO_RESOURCES 4 #define BNX2X_VF_BULLETIN_TRIES 5 #define BNX2X_VF_Q_FLAG_CACHE_ALIGN 0x0008 #define BNX2X_VF_Q_FLAG_STATS 0x0010 #define BNX2X_VF_Q_FLAG_OV 0x0020 #define BNX2X_VF_Q_FLAG_VLAN 0x0040 #define BNX2X_VF_Q_FLAG_COS 0x0080 #define BNX2X_VF_Q_FLAG_HC 0x0100 #define BNX2X_VF_Q_FLAG_DHC 0x0200 #define BNX2X_VF_Q_FLAG_LEADING_RSS 0x0400 struct vf_first_tlv { uint16_t type; uint16_t length; uint32_t reply_offset; }; /* tlv struct for all PF replies except acquire */ struct vf_common_reply_tlv { uint16_t type; uint16_t length; uint8_t status; uint8_t pad[3]; }; /* used to terminate and pad a tlv list */ struct channel_list_end_tlv { uint16_t type; uint16_t length; uint32_t pad; }; /* Acquire */ struct vf_acquire_tlv { struct vf_first_tlv first_tlv; uint8_t vf_id; uint8_t pad[3]; struct vf_resource_query res_query; uint64_t bulletin_addr; }; /* simple operation request on queue */ struct vf_q_op_tlv { struct vf_first_tlv first_tlv; uint8_t vf_qid; uint8_t pad[3]; }; /* receive side scaling tlv */ struct vf_rss_tlv { struct vf_first_tlv first_tlv; uint32_t rss_flags; uint8_t rss_result_mask; uint8_t ind_table_size; uint8_t rss_key_size; uint8_t pad; uint8_t ind_table[T_ETH_INDIRECTION_TABLE_SIZE]; uint32_t rss_key[T_ETH_RSS_KEY]; /* hash values */ }; struct vf_resc { #define BNX2X_VF_MAX_QUEUES_PER_VF 16 #define BNX2X_VF_MAX_SBS_PER_VF 16 uint16_t hw_sbs[BNX2X_VF_MAX_SBS_PER_VF]; uint8_t hw_qid[BNX2X_VF_MAX_QUEUES_PER_VF]; uint8_t num_rxqs; uint8_t num_txqs; uint8_t num_sbs; uint8_t num_mac_filters; uint8_t num_vlan_filters; uint8_t num_mc_filters; uint8_t permanent_mac_addr[ETH_ALEN]; uint8_t current_mac_addr[ETH_ALEN]; uint16_t pf_link_speed; uint32_t pf_link_supported; }; /* tlv struct holding reply for acquire */ struct vf_acquire_resp_tlv { uint16_t type; uint16_t length; uint8_t status; uint8_t pad1[3]; uint32_t chip_num; uint8_t pad2[4]; char fw_ver[32]; uint16_t db_size; uint8_t pad3[2]; struct vf_resc resc; }; /* Init VF */ struct vf_init_tlv { struct vf_first_tlv first_tlv; uint64_t sb_addr[BNX2X_VF_MAX_SBS_PER_VF]; uint64_t spq_addr; uint64_t stats_addr; uint16_t stats_step; uint32_t flags; uint32_t pad[2]; }; struct vf_rxq_params { /* physical addresses */ uint64_t rcq_addr; uint64_t rcq_np_addr; uint64_t rxq_addr; uint64_t pad1; /* sb + hc info */ uint8_t vf_sb_id; uint8_t sb_cq_index; uint16_t hc_rate; /* desired interrupts per sec. */ /* rx buffer info */ uint16_t mtu; uint16_t buf_sz; uint16_t flags; /* for BNX2X_VF_Q_FLAG_X flags */ uint16_t stat_id; /* valid if BNX2X_VF_Q_FLAG_STATS */ uint8_t pad2[5]; uint8_t drop_flags; uint8_t cache_line_log; /* BNX2X_VF_Q_FLAG_CACHE_ALIGN */ uint8_t pad3; }; struct vf_txq_params { /* physical addresses */ uint64_t txq_addr; /* sb + hc info */ uint8_t vf_sb_id; /* index in hw_sbs[] */ uint8_t sb_index; /* Index in the SB */ uint16_t hc_rate; /* desired interrupts per sec. */ uint32_t flags; /* for BNX2X_VF_Q_FLAG_X flags */ uint16_t stat_id; /* valid if BNX2X_VF_Q_FLAG_STATS */ uint8_t traffic_type; /* see in setup_context() */ uint8_t pad; }; /* Setup Queue */ struct vf_setup_q_tlv { struct vf_first_tlv first_tlv; struct vf_rxq_params rxq; struct vf_txq_params txq; uint8_t vf_qid; /* index in hw_qid[] */ uint8_t param_valid; #define VF_RXQ_VALID 0x01 #define VF_TXQ_VALID 0x02 uint8_t pad[2]; }; /* Set Queue Filters */ struct vf_q_mac_vlan_filter { uint32_t flags; #define BNX2X_VF_Q_FILTER_DEST_MAC_VALID 0x01 #define BNX2X_VF_Q_FILTER_VLAN_TAG_VALID 0x02 #define BNX2X_VF_Q_FILTER_SET_MAC 0x100 /* set/clear */ uint8_t mac[ETH_ALEN]; uint16_t vlan_tag; }; #define _UP_ETH_ALEN (6) /* configure queue filters */ struct vf_set_q_filters_tlv { struct vf_first_tlv first_tlv; uint32_t flags; #define BNX2X_VF_MAC_VLAN_CHANGED 0x01 #define BNX2X_VF_MULTICAST_CHANGED 0x02 #define BNX2X_VF_RX_MASK_CHANGED 0x04 uint8_t vf_qid; /* index in hw_qid[] */ uint8_t mac_filters_cnt; uint8_t multicast_cnt; uint8_t pad; #define VF_MAX_MAC_FILTERS 16 #define VF_MAX_VLAN_FILTERS 16 #define VF_MAX_FILTERS (VF_MAX_MAC_FILTERS +\ VF_MAX_VLAN_FILTERS) struct vf_q_mac_vlan_filter filters[VF_MAX_FILTERS]; #define VF_MAX_MULTICAST_PER_VF 32 uint8_t multicast[VF_MAX_MULTICAST_PER_VF][_UP_ETH_ALEN]; unsigned long rx_mask; }; /* close VF (disable VF) */ struct vf_close_tlv { struct vf_first_tlv first_tlv; uint16_t vf_id; /* for debug */ uint8_t pad[2]; }; /* rlease the VF's acquired resources */ struct vf_release_tlv { struct vf_first_tlv first_tlv; uint16_t vf_id; /* for debug */ uint8_t pad[2]; }; union query_tlvs { struct vf_first_tlv first_tlv; struct vf_acquire_tlv acquire; struct vf_init_tlv init; struct vf_close_tlv close; struct vf_q_op_tlv q_op; struct vf_setup_q_tlv setup_q; struct vf_set_q_filters_tlv set_q_filters; struct vf_release_tlv release; struct vf_rss_tlv update_rss; struct channel_list_end_tlv list_end; }; union resp_tlvs { struct vf_common_reply_tlv common_reply; struct vf_acquire_resp_tlv acquire_resp; struct channel_list_end_tlv list_end; }; /* struct allocated by VF driver, PF sends updates to VF via bulletin */ struct bnx2x_vf_bulletin { uint32_t crc; /* crc of structure to ensure is not in * mid-update */ uint16_t version; uint16_t length; uint64_t valid_bitmap; /* bitmap indicating wich fields * hold valid values */ #define MAC_ADDR_VALID 0 /* alert the vf that a new mac address * is available for it */ #define VLAN_VALID 1 /* when set, the vf should no access the * vf channel */ #define CHANNEL_DOWN 2 /* vf channel is disabled. VFs are not * to attempt to send messages on the * channel after this bit is set */ uint8_t mac[ETH_ALEN]; uint8_t mac_pad[2]; uint16_t vlan; uint8_t vlan_pad[6]; }; #define MAX_TLVS_IN_LIST 50 enum channel_tlvs { BNX2X_VF_TLV_NONE, /* ends tlv sequence */ BNX2X_VF_TLV_ACQUIRE, BNX2X_VF_TLV_INIT, BNX2X_VF_TLV_SETUP_Q, BNX2X_VF_TLV_SET_Q_FILTERS, BNX2X_VF_TLV_ACTIVATE_Q, BNX2X_VF_TLV_DEACTIVATE_Q, BNX2X_VF_TLV_TEARDOWN_Q, BNX2X_VF_TLV_CLOSE, BNX2X_VF_TLV_RELEASE, BNX2X_VF_TLV_UPDATE_RSS_OLD, BNX2X_VF_TLV_PF_RELEASE_VF, BNX2X_VF_TLV_LIST_END, BNX2X_VF_TLV_FLR, BNX2X_VF_TLV_PF_SET_MAC, BNX2X_VF_TLV_PF_SET_VLAN, BNX2X_VF_TLV_UPDATE_RSS, BNX2X_VF_TLV_MAX }; struct bnx2x_vf_mbx_msg { union query_tlvs query[BNX2X_VF_MAX_QUEUES_PER_VF]; union resp_tlvs resp; }; void bnx2x_add_tlv(void *tlvs_list, uint16_t offset, uint16_t type, uint16_t length); int bnx2x_vf_set_mac(struct bnx2x_softc *sc, int set); int bnx2x_vf_config_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *params); #endif /* BNX2X_VFPF_H */ ================================================ FILE: drivers/net/bnx2x/debug.c ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "bnx2x.h" /* * Debug versions of the 8/16/32 bit OS register read/write functions to * capture/display values read/written from/to the controller. */ void bnx2x_reg_write8(struct bnx2x_softc *sc, size_t offset, uint8_t val) { PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%02x", offset, val); *((volatile uint8_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val; } void bnx2x_reg_write16(struct bnx2x_softc *sc, size_t offset, uint16_t val) { if ((offset % 2) != 0) { PMD_DRV_LOG(DEBUG, "Unaligned 16-bit write to 0x%08lx", offset); } PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%04x", offset, val); *((volatile uint16_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val; } void bnx2x_reg_write32(struct bnx2x_softc *sc, size_t offset, uint32_t val) { if ((offset % 4) != 0) { PMD_DRV_LOG(DEBUG, "Unaligned 32-bit write to 0x%08lx", offset); } PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%08x", offset, val); *((volatile uint32_t*)((uint64_t)sc->bar[BAR0].base_addr + offset)) = val; } uint8_t bnx2x_reg_read8(struct bnx2x_softc *sc, size_t offset) { uint8_t val; val = (uint8_t)(*((volatile uint8_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))); PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%02x", offset, val); return (val); } uint16_t bnx2x_reg_read16(struct bnx2x_softc *sc, size_t offset) { uint16_t val; if ((offset % 2) != 0) { PMD_DRV_LOG(DEBUG, "Unaligned 16-bit read from 0x%08lx", offset); } val = (uint16_t)(*((volatile uint16_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))); PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%08x", offset, val); return (val); } uint32_t bnx2x_reg_read32(struct bnx2x_softc *sc, size_t offset) { uint32_t val; if ((offset % 4) != 0) { PMD_DRV_LOG(DEBUG, "Unaligned 32-bit read from 0x%08lx", offset); return 0; } val = (uint32_t)(*((volatile uint32_t*)((uint64_t)sc->bar[BAR0].base_addr + offset))); PMD_DRV_LOG(DEBUG, "offset=0x%08lx val=0x%08x", offset, val); return (val); } ================================================ FILE: drivers/net/bnx2x/ecore_fw_defs.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_FW_DEFS_H #define ECORE_FW_DEFS_H #define CSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[148].base) #define CSTORM_ASSERT_LIST_OFFSET(assertListEntry) \ (IRO[147].base + ((assertListEntry) * IRO[147].m1)) #define CSTORM_EVENT_RING_DATA_OFFSET(pfId) \ (IRO[153].base + (((pfId)>>1) * IRO[153].m1) + (((pfId)&1) * \ IRO[153].m2)) #define CSTORM_EVENT_RING_PROD_OFFSET(pfId) \ (IRO[154].base + (((pfId)>>1) * IRO[154].m1) + (((pfId)&1) * \ IRO[154].m2)) #define CSTORM_VF_PF_CHANNEL_STATE_OFFSET(vfId) \ (IRO[155].base + ((vfId) * IRO[155].m1)) #define CSTORM_VF_PF_CHANNEL_VALID_OFFSET(vfId) \ (IRO[156].base + ((vfId) * IRO[156].m1)) #define CSTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[150].base + ((funcId) * IRO[150].m1)) #define CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(funcId) \ (IRO[159].base + ((funcId) * IRO[159].m1)) #define CSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[149].base + ((funcId) * IRO[149].m1)) #define CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hcIndex, sbId) \ (IRO[139].base + ((hcIndex) * IRO[139].m1) + ((sbId) * IRO[139].m2)) #define CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hcIndex, sbId) \ (IRO[138].base + (((hcIndex)>>2) * IRO[138].m1) + (((hcIndex)&3) \ * IRO[138].m2) + ((sbId) * IRO[138].m3)) #define CSTORM_IGU_MODE_OFFSET (IRO[157].base) #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \ (IRO[317].base + ((pfId) * IRO[317].m1)) #define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ (IRO[318].base + ((pfId) * IRO[318].m1)) #define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \ (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2)) #define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \ (IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2)) #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \ (IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2)) #define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \ (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2)) #define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \ (IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2)) #define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \ (IRO[315].base + ((pfId) * IRO[315].m1) + ((iscsiEqId) * IRO[315].m2)) #define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \ (IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2)) #define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \ (IRO[316].base + ((pfId) * IRO[316].m1)) #define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ (IRO[308].base + ((pfId) * IRO[308].m1)) #define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ (IRO[307].base + ((pfId) * IRO[307].m1)) #define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ (IRO[306].base + ((pfId) * IRO[306].m1)) #define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[151].base + ((funcId) * IRO[151].m1)) #define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \ (IRO[142].base + ((pfId) * IRO[142].m1)) #define CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(pfId) \ (IRO[143].base + ((pfId) * IRO[143].m1)) #define CSTORM_SP_STATUS_BLOCK_OFFSET(pfId) \ (IRO[141].base + ((pfId) * IRO[141].m1)) #define CSTORM_SP_STATUS_BLOCK_SIZE (IRO[141].size) #define CSTORM_SP_SYNC_BLOCK_OFFSET(pfId) \ (IRO[144].base + ((pfId) * IRO[144].m1)) #define CSTORM_SP_SYNC_BLOCK_SIZE (IRO[144].size) #define CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(sbId, hcIndex) \ (IRO[136].base + ((sbId) * IRO[136].m1) + ((hcIndex) * IRO[136].m2)) #define CSTORM_STATUS_BLOCK_DATA_OFFSET(sbId) \ (IRO[133].base + ((sbId) * IRO[133].m1)) #define CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(sbId) \ (IRO[134].base + ((sbId) * IRO[134].m1)) #define CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(sbId, hcIndex) \ (IRO[135].base + ((sbId) * IRO[135].m1) + ((hcIndex) * IRO[135].m2)) #define CSTORM_STATUS_BLOCK_OFFSET(sbId) \ (IRO[132].base + ((sbId) * IRO[132].m1)) #define CSTORM_STATUS_BLOCK_SIZE (IRO[132].size) #define CSTORM_SYNC_BLOCK_OFFSET(sbId) \ (IRO[137].base + ((sbId) * IRO[137].m1)) #define CSTORM_SYNC_BLOCK_SIZE (IRO[137].size) #define CSTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[150].base + ((funcId) * IRO[150].m1)) #define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base) #define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \ (IRO[203].base + ((pfId) * IRO[203].m1)) #define TSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[102].base) #define TSTORM_ASSERT_LIST_OFFSET(assertListEntry) \ (IRO[101].base + ((assertListEntry) * IRO[101].m1)) #define TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(pfId) \ (IRO[201].base + ((pfId) * IRO[201].m1)) #define TSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[103].base + ((funcId) * IRO[103].m1)) #define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \ (IRO[272].base + ((pfId) * IRO[272].m1)) #define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ (IRO[271].base + ((pfId) * IRO[271].m1)) #define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ (IRO[270].base + ((pfId) * IRO[270].m1)) #define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ (IRO[269].base + ((pfId) * IRO[269].m1)) #define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \ (IRO[268].base + ((pfId) * IRO[268].m1)) #define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \ (IRO[278].base + ((pfId) * IRO[278].m1)) #define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \ (IRO[264].base + ((pfId) * IRO[264].m1)) #define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[265].base + ((pfId) * IRO[265].m1)) #define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[266].base + ((pfId) * IRO[266].m1)) #define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \ (IRO[267].base + ((pfId) * IRO[267].m1)) #define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \ (IRO[202].base + ((pfId) * IRO[202].m1)) #define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[105].base + ((funcId) * IRO[105].m1)) #define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \ (IRO[217].base + ((pfId) * IRO[217].m1)) #define TSTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[104].base + ((funcId) * IRO[104].m1)) #define USTORM_AGG_DATA_OFFSET (IRO[206].base) #define USTORM_AGG_DATA_SIZE (IRO[206].size) #define USTORM_ASSERT_LIST_INDEX_OFFSET (IRO[177].base) #define USTORM_ASSERT_LIST_OFFSET(assertListEntry) \ (IRO[176].base + ((assertListEntry) * IRO[176].m1)) #define USTORM_CQE_PAGE_NEXT_OFFSET(portId, clientId) \ (IRO[205].base + ((portId) * IRO[205].m1) + ((clientId) * IRO[205].m2)) #define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \ (IRO[183].base + ((portId) * IRO[183].m1)) #define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \ (IRO[319].base + ((pfId) * IRO[319].m1)) #define USTORM_FUNC_EN_OFFSET(funcId) \ (IRO[178].base + ((funcId) * IRO[178].m1)) #define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \ (IRO[283].base + ((pfId) * IRO[283].m1)) #define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \ (IRO[284].base + ((pfId) * IRO[284].m1)) #define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \ (IRO[288].base + ((pfId) * IRO[288].m1)) #define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \ (IRO[285].base + ((pfId) * IRO[285].m1)) #define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ (IRO[281].base + ((pfId) * IRO[281].m1)) #define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ (IRO[280].base + ((pfId) * IRO[280].m1)) #define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ (IRO[279].base + ((pfId) * IRO[279].m1)) #define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \ (IRO[282].base + ((pfId) * IRO[282].m1)) #define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \ (IRO[286].base + ((pfId) * IRO[286].m1)) #define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \ (IRO[287].base + ((pfId) * IRO[287].m1)) #define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \ (IRO[182].base + ((pfId) * IRO[182].m1)) #define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[180].base + ((funcId) * IRO[180].m1)) #define USTORM_RX_PRODS_E1X_OFFSET(portId, clientId) \ (IRO[209].base + ((portId) * IRO[209].m1) + ((clientId) * \ IRO[209].m2)) #define USTORM_RX_PRODS_E2_OFFSET(qzoneId) \ (IRO[210].base + ((qzoneId) * IRO[210].m1)) #define USTORM_TPA_BTR_OFFSET (IRO[207].base) #define USTORM_TPA_BTR_SIZE (IRO[207].size) #define USTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[179].base + ((funcId) * IRO[179].m1)) #define XSTORM_AGG_INT_FINAL_CLEANUP_COMP_TYPE (IRO[67].base) #define XSTORM_AGG_INT_FINAL_CLEANUP_INDEX (IRO[66].base) #define XSTORM_ASSERT_LIST_INDEX_OFFSET (IRO[51].base) #define XSTORM_ASSERT_LIST_OFFSET(assertListEntry) \ (IRO[50].base + ((assertListEntry) * IRO[50].m1)) #define XSTORM_CMNG_PER_PORT_VARS_OFFSET(portId) \ (IRO[43].base + ((portId) * IRO[43].m1)) #define XSTORM_FAIRNESS_PER_VN_VARS_OFFSET(pfId) \ (IRO[45].base + ((pfId) * IRO[45].m1)) #define XSTORM_FUNC_EN_OFFSET(funcId) \ (IRO[47].base + ((funcId) * IRO[47].m1)) #define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \ (IRO[296].base + ((pfId) * IRO[296].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \ (IRO[299].base + ((pfId) * IRO[299].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \ (IRO[300].base + ((pfId) * IRO[300].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \ (IRO[301].base + ((pfId) * IRO[301].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \ (IRO[302].base + ((pfId) * IRO[302].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \ (IRO[303].base + ((pfId) * IRO[303].m1)) #define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \ (IRO[304].base + ((pfId) * IRO[304].m1)) #define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \ (IRO[305].base + ((pfId) * IRO[305].m1)) #define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \ (IRO[295].base + ((pfId) * IRO[295].m1)) #define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \ (IRO[294].base + ((pfId) * IRO[294].m1)) #define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \ (IRO[293].base + ((pfId) * IRO[293].m1)) #define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \ (IRO[298].base + ((pfId) * IRO[298].m1)) #define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \ (IRO[297].base + ((pfId) * IRO[297].m1)) #define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \ (IRO[292].base + ((pfId) * IRO[292].m1)) #define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \ (IRO[291].base + ((pfId) * IRO[291].m1)) #define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \ (IRO[290].base + ((pfId) * IRO[290].m1)) #define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \ (IRO[289].base + ((pfId) * IRO[289].m1)) #define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \ (IRO[44].base + ((pfId) * IRO[44].m1)) #define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \ (IRO[49].base + ((funcId) * IRO[49].m1)) #define XSTORM_SPQ_DATA_OFFSET(funcId) \ (IRO[32].base + ((funcId) * IRO[32].m1)) #define XSTORM_SPQ_DATA_SIZE (IRO[32].size) #define XSTORM_SPQ_PAGE_BASE_OFFSET(funcId) \ (IRO[30].base + ((funcId) * IRO[30].m1)) #define XSTORM_SPQ_PROD_OFFSET(funcId) \ (IRO[31].base + ((funcId) * IRO[31].m1)) #define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_ENABLED_OFFSET(portId) \ (IRO[211].base + ((portId) * IRO[211].m1)) #define XSTORM_TCP_GLOBAL_DEL_ACK_COUNTER_MAX_COUNT_OFFSET(portId) \ (IRO[212].base + ((portId) * IRO[212].m1)) #define XSTORM_TCP_TX_SWS_TIMER_VAL_OFFSET(pfId) \ (IRO[214].base + (((pfId)>>1) * IRO[214].m1) + (((pfId)&1) * \ IRO[214].m2)) #define XSTORM_VF_TO_PF_OFFSET(funcId) \ (IRO[48].base + ((funcId) * IRO[48].m1)) #define COMMON_ASM_INVALID_ASSERT_OPCODE (IRO[7].base) /* Ethernet Ring parameters */ #define X_ETH_LOCAL_RING_SIZE 13 #define FIRST_BD_IN_PKT 0 #define PARSE_BD_INDEX 1 #define NUM_OF_ETH_BDS_IN_PAGE ((PAGE_SIZE)/(STRUCT_SIZE(eth_tx_bd)/8)) /* Rx ring params */ #define U_ETH_LOCAL_BD_RING_SIZE 8 #define U_ETH_SGL_SIZE 8 /* The fw will padd the buffer with this value, so the IP header \ will be align to 4 Byte */ #define IP_HEADER_ALIGNMENT_PADDING 2 #define TU_ETH_CQES_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_cqe)/8)) #define U_ETH_BDS_PER_PAGE (PAGE_SIZE/(STRUCT_SIZE(eth_rx_bd)/8)) #define U_ETH_BDS_PER_PAGE_MASK (U_ETH_BDS_PER_PAGE-1) #define U_ETH_CQE_PER_PAGE_MASK (TU_ETH_CQES_PER_PAGE-1) #define U_ETH_UNDEFINED_Q 0xFF #define T_ETH_INDIRECTION_TABLE_SIZE 128 #define T_ETH_RSS_KEY 10 #define ETH_NUM_OF_RSS_ENGINES_E2 72 #define FILTER_RULES_COUNT 16 #define MULTICAST_RULES_COUNT 16 #define CLASSIFY_RULES_COUNT 16 /*The CRC32 seed, that is used for the hash(reduction) multicast address */ #define ETH_CRC32_HASH_SEED 0x00000000 #define ETH_CRC32_HASH_BIT_SIZE (8) #define ETH_CRC32_HASH_MASK EVAL((1< * David Christensen * Gary Zambrano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_HSI_H #define ECORE_HSI_H #define FW_ENCODE_32BIT_PATTERN 0x1e1e1e1e struct license_key { uint32_t reserved[6]; uint32_t max_iscsi_conn; #define LICENSE_MAX_ISCSI_TRGT_CONN_MASK 0xFFFF #define LICENSE_MAX_ISCSI_TRGT_CONN_SHIFT 0 #define LICENSE_MAX_ISCSI_INIT_CONN_MASK 0xFFFF0000 #define LICENSE_MAX_ISCSI_INIT_CONN_SHIFT 16 uint32_t reserved_a; uint32_t max_fcoe_conn; #define LICENSE_MAX_FCOE_TRGT_CONN_MASK 0xFFFF #define LICENSE_MAX_FCOE_TRGT_CONN_SHIFT 0 #define LICENSE_MAX_FCOE_INIT_CONN_MASK 0xFFFF0000 #define LICENSE_MAX_FCOE_INIT_CONN_SHIFT 16 uint32_t reserved_b[4]; }; typedef struct license_key license_key_t; /**************************************************************************** * Shared HW configuration * ****************************************************************************/ #define PIN_CFG_NA 0x00000000 #define PIN_CFG_GPIO0_P0 0x00000001 #define PIN_CFG_GPIO1_P0 0x00000002 #define PIN_CFG_GPIO2_P0 0x00000003 #define PIN_CFG_GPIO3_P0 0x00000004 #define PIN_CFG_GPIO0_P1 0x00000005 #define PIN_CFG_GPIO1_P1 0x00000006 #define PIN_CFG_GPIO2_P1 0x00000007 #define PIN_CFG_GPIO3_P1 0x00000008 #define PIN_CFG_EPIO0 0x00000009 #define PIN_CFG_EPIO1 0x0000000a #define PIN_CFG_EPIO2 0x0000000b #define PIN_CFG_EPIO3 0x0000000c #define PIN_CFG_EPIO4 0x0000000d #define PIN_CFG_EPIO5 0x0000000e #define PIN_CFG_EPIO6 0x0000000f #define PIN_CFG_EPIO7 0x00000010 #define PIN_CFG_EPIO8 0x00000011 #define PIN_CFG_EPIO9 0x00000012 #define PIN_CFG_EPIO10 0x00000013 #define PIN_CFG_EPIO11 0x00000014 #define PIN_CFG_EPIO12 0x00000015 #define PIN_CFG_EPIO13 0x00000016 #define PIN_CFG_EPIO14 0x00000017 #define PIN_CFG_EPIO15 0x00000018 #define PIN_CFG_EPIO16 0x00000019 #define PIN_CFG_EPIO17 0x0000001a #define PIN_CFG_EPIO18 0x0000001b #define PIN_CFG_EPIO19 0x0000001c #define PIN_CFG_EPIO20 0x0000001d #define PIN_CFG_EPIO21 0x0000001e #define PIN_CFG_EPIO22 0x0000001f #define PIN_CFG_EPIO23 0x00000020 #define PIN_CFG_EPIO24 0x00000021 #define PIN_CFG_EPIO25 0x00000022 #define PIN_CFG_EPIO26 0x00000023 #define PIN_CFG_EPIO27 0x00000024 #define PIN_CFG_EPIO28 0x00000025 #define PIN_CFG_EPIO29 0x00000026 #define PIN_CFG_EPIO30 0x00000027 #define PIN_CFG_EPIO31 0x00000028 /* EPIO definition */ #define EPIO_CFG_NA 0x00000000 #define EPIO_CFG_EPIO0 0x00000001 #define EPIO_CFG_EPIO1 0x00000002 #define EPIO_CFG_EPIO2 0x00000003 #define EPIO_CFG_EPIO3 0x00000004 #define EPIO_CFG_EPIO4 0x00000005 #define EPIO_CFG_EPIO5 0x00000006 #define EPIO_CFG_EPIO6 0x00000007 #define EPIO_CFG_EPIO7 0x00000008 #define EPIO_CFG_EPIO8 0x00000009 #define EPIO_CFG_EPIO9 0x0000000a #define EPIO_CFG_EPIO10 0x0000000b #define EPIO_CFG_EPIO11 0x0000000c #define EPIO_CFG_EPIO12 0x0000000d #define EPIO_CFG_EPIO13 0x0000000e #define EPIO_CFG_EPIO14 0x0000000f #define EPIO_CFG_EPIO15 0x00000010 #define EPIO_CFG_EPIO16 0x00000011 #define EPIO_CFG_EPIO17 0x00000012 #define EPIO_CFG_EPIO18 0x00000013 #define EPIO_CFG_EPIO19 0x00000014 #define EPIO_CFG_EPIO20 0x00000015 #define EPIO_CFG_EPIO21 0x00000016 #define EPIO_CFG_EPIO22 0x00000017 #define EPIO_CFG_EPIO23 0x00000018 #define EPIO_CFG_EPIO24 0x00000019 #define EPIO_CFG_EPIO25 0x0000001a #define EPIO_CFG_EPIO26 0x0000001b #define EPIO_CFG_EPIO27 0x0000001c #define EPIO_CFG_EPIO28 0x0000001d #define EPIO_CFG_EPIO29 0x0000001e #define EPIO_CFG_EPIO30 0x0000001f #define EPIO_CFG_EPIO31 0x00000020 struct mac_addr { uint32_t upper; uint32_t lower; }; struct shared_hw_cfg { /* NVRAM Offset */ /* Up to 16 bytes of NULL-terminated string */ uint8_t part_num[16]; /* 0x104 */ uint32_t config; /* 0x114 */ #define SHARED_HW_CFG_MDIO_VOLTAGE_MASK 0x00000001 #define SHARED_HW_CFG_MDIO_VOLTAGE_SHIFT 0 #define SHARED_HW_CFG_MDIO_VOLTAGE_1_2V 0x00000000 #define SHARED_HW_CFG_MDIO_VOLTAGE_2_5V 0x00000001 #define SHARED_HW_CFG_PORT_SWAP 0x00000004 #define SHARED_HW_CFG_BEACON_WOL_EN 0x00000008 #define SHARED_HW_CFG_PCIE_GEN3_DISABLED 0x00000000 #define SHARED_HW_CFG_PCIE_GEN3_ENABLED 0x00000010 #define SHARED_HW_CFG_MFW_SELECT_MASK 0x00000700 #define SHARED_HW_CFG_MFW_SELECT_SHIFT 8 /* Whatever MFW found in NVM (if multiple found, priority order is: NC-SI, UMP, IPMI) */ #define SHARED_HW_CFG_MFW_SELECT_DEFAULT 0x00000000 #define SHARED_HW_CFG_MFW_SELECT_NC_SI 0x00000100 #define SHARED_HW_CFG_MFW_SELECT_UMP 0x00000200 #define SHARED_HW_CFG_MFW_SELECT_IPMI 0x00000300 /* Use SPIO4 as an arbiter between: 0-NC_SI, 1-IPMI (can only be used when an add-in board, not BMC, pulls-down SPIO4) */ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_IPMI 0x00000400 /* Use SPIO4 as an arbiter between: 0-UMP, 1-IPMI (can only be used when an add-in board, not BMC, pulls-down SPIO4) */ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_UMP_IPMI 0x00000500 /* Use SPIO4 as an arbiter between: 0-NC-SI, 1-UMP (can only be used when an add-in board, not BMC, pulls-down SPIO4) */ #define SHARED_HW_CFG_MFW_SELECT_SPIO4_NC_SI_UMP 0x00000600 /* Adjust the PCIe G2 Tx amplitude driver for all Tx lanes. For backwards compatibility, value of 0 is disabling this feature. That means that though 0 is a valid value, it cannot be configured. */ #define SHARED_HW_CFG_G2_TX_DRIVE_MASK 0x0000F000 #define SHARED_HW_CFG_G2_TX_DRIVE_SHIFT 12 #define SHARED_HW_CFG_LED_MODE_MASK 0x000F0000 #define SHARED_HW_CFG_LED_MODE_SHIFT 16 #define SHARED_HW_CFG_LED_MAC1 0x00000000 #define SHARED_HW_CFG_LED_PHY1 0x00010000 #define SHARED_HW_CFG_LED_PHY2 0x00020000 #define SHARED_HW_CFG_LED_PHY3 0x00030000 #define SHARED_HW_CFG_LED_MAC2 0x00040000 #define SHARED_HW_CFG_LED_PHY4 0x00050000 #define SHARED_HW_CFG_LED_PHY5 0x00060000 #define SHARED_HW_CFG_LED_PHY6 0x00070000 #define SHARED_HW_CFG_LED_MAC3 0x00080000 #define SHARED_HW_CFG_LED_PHY7 0x00090000 #define SHARED_HW_CFG_LED_PHY9 0x000a0000 #define SHARED_HW_CFG_LED_PHY11 0x000b0000 #define SHARED_HW_CFG_LED_MAC4 0x000c0000 #define SHARED_HW_CFG_LED_PHY8 0x000d0000 #define SHARED_HW_CFG_LED_EXTPHY1 0x000e0000 #define SHARED_HW_CFG_LED_EXTPHY2 0x000f0000 #define SHARED_HW_CFG_SRIOV_MASK 0x40000000 #define SHARED_HW_CFG_SRIOV_DISABLED 0x00000000 #define SHARED_HW_CFG_SRIOV_ENABLED 0x40000000 #define SHARED_HW_CFG_ATC_MASK 0x80000000 #define SHARED_HW_CFG_ATC_DISABLED 0x00000000 #define SHARED_HW_CFG_ATC_ENABLED 0x80000000 uint32_t config2; /* 0x118 */ #define SHARED_HW_CFG_PCIE_GEN2_MASK 0x00000100 #define SHARED_HW_CFG_PCIE_GEN2_SHIFT 8 #define SHARED_HW_CFG_PCIE_GEN2_DISABLED 0x00000000 #define SHARED_HW_CFG_PCIE_GEN2_ENABLED 0x00000100 #define SHARED_HW_CFG_SMBUS_TIMING_MASK 0x00001000 #define SHARED_HW_CFG_SMBUS_TIMING_100KHZ 0x00000000 #define SHARED_HW_CFG_SMBUS_TIMING_400KHZ 0x00001000 #define SHARED_HW_CFG_HIDE_PORT1 0x00002000 /* Output low when PERST is asserted */ #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_MASK 0x00008000 #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_DISABLED 0x00000000 #define SHARED_HW_CFG_SPIO4_FOLLOW_PERST_ENABLED 0x00008000 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_MASK 0x00070000 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_SHIFT 16 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_HW 0x00000000 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_0DB 0x00010000 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_3_5DB 0x00020000 #define SHARED_HW_CFG_PCIE_GEN2_PREEMPHASIS_6_0DB 0x00030000 /* The fan failure mechanism is usually related to the PHY type since the power consumption of the board is determined by the PHY. Currently, fan is required for most designs with SFX7101, BNX2X8727 and BNX2X8481. If a fan is not required for a board which uses one of those PHYs, this field should be set to "Disabled". If a fan is required for a different PHY type, this option should be set to "Enabled". The fan failure indication is expected on SPIO5 */ #define SHARED_HW_CFG_FAN_FAILURE_MASK 0x00180000 #define SHARED_HW_CFG_FAN_FAILURE_SHIFT 19 #define SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE 0x00000000 #define SHARED_HW_CFG_FAN_FAILURE_DISABLED 0x00080000 #define SHARED_HW_CFG_FAN_FAILURE_ENABLED 0x00100000 /* ASPM Power Management support */ #define SHARED_HW_CFG_ASPM_SUPPORT_MASK 0x00600000 #define SHARED_HW_CFG_ASPM_SUPPORT_SHIFT 21 #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_ENABLED 0x00000000 #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_DISABLED 0x00200000 #define SHARED_HW_CFG_ASPM_SUPPORT_L1_DISABLED 0x00400000 #define SHARED_HW_CFG_ASPM_SUPPORT_L0S_L1_DISABLED 0x00600000 /* The value of PM_TL_IGNORE_REQS (bit0) in PCI register tl_control_0 (register 0x2800) */ #define SHARED_HW_CFG_PREVENT_L1_ENTRY_MASK 0x00800000 #define SHARED_HW_CFG_PREVENT_L1_ENTRY_DISABLED 0x00000000 #define SHARED_HW_CFG_PREVENT_L1_ENTRY_ENABLED 0x00800000 /* Set the MDC/MDIO access for the first external phy */ #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK 0x1C000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT 26 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE 0x00000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0 0x04000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1 0x08000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH 0x0c000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED 0x10000000 /* Set the MDC/MDIO access for the second external phy */ #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK 0xE0000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT 29 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_PHY_TYPE 0x00000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC0 0x20000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_EMAC1 0x40000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_BOTH 0x60000000 #define SHARED_HW_CFG_MDC_MDIO_ACCESS2_SWAPPED 0x80000000 /* Max number of PF MSIX vectors */ uint32_t config_3; /* 0x11C */ #define SHARED_HW_CFG_PF_MSIX_MAX_NUM_MASK 0x0000007F #define SHARED_HW_CFG_PF_MSIX_MAX_NUM_SHIFT 0 uint32_t ump_nc_si_config; /* 0x120 */ #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MASK 0x00000003 #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_SHIFT 0 #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MAC 0x00000000 #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_PHY 0x00000001 #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_MII 0x00000000 #define SHARED_HW_CFG_UMP_NC_SI_MII_MODE_RMII 0x00000002 /* Reserved bits: 226-230 */ /* The output pin template BSC_SEL which selects the I2C for this port in the I2C Mux */ uint32_t board; /* 0x124 */ #define SHARED_HW_CFG_E3_I2C_MUX0_MASK 0x0000003F #define SHARED_HW_CFG_E3_I2C_MUX0_SHIFT 0 #define SHARED_HW_CFG_E3_I2C_MUX1_MASK 0x00000FC0 #define SHARED_HW_CFG_E3_I2C_MUX1_SHIFT 6 /* Use the PIN_CFG_XXX defines on top */ #define SHARED_HW_CFG_BOARD_REV_MASK 0x00FF0000 #define SHARED_HW_CFG_BOARD_REV_SHIFT 16 #define SHARED_HW_CFG_BOARD_MAJOR_VER_MASK 0x0F000000 #define SHARED_HW_CFG_BOARD_MAJOR_VER_SHIFT 24 #define SHARED_HW_CFG_BOARD_MINOR_VER_MASK 0xF0000000 #define SHARED_HW_CFG_BOARD_MINOR_VER_SHIFT 28 uint32_t wc_lane_config; /* 0x128 */ #define SHARED_HW_CFG_LANE_SWAP_CFG_MASK 0x0000FFFF #define SHARED_HW_CFG_LANE_SWAP_CFG_SHIFT 0 #define SHARED_HW_CFG_LANE_SWAP_CFG_32103210 0x00001b1b #define SHARED_HW_CFG_LANE_SWAP_CFG_32100123 0x00001be4 #define SHARED_HW_CFG_LANE_SWAP_CFG_31200213 0x000027d8 #define SHARED_HW_CFG_LANE_SWAP_CFG_02133120 0x0000d827 #define SHARED_HW_CFG_LANE_SWAP_CFG_01233210 0x0000e41b #define SHARED_HW_CFG_LANE_SWAP_CFG_01230123 0x0000e4e4 #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000FF #define SHARED_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0 #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000FF00 #define SHARED_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8 /* TX lane Polarity swap */ #define SHARED_HW_CFG_TX_LANE0_POL_FLIP_ENABLED 0x00010000 #define SHARED_HW_CFG_TX_LANE1_POL_FLIP_ENABLED 0x00020000 #define SHARED_HW_CFG_TX_LANE2_POL_FLIP_ENABLED 0x00040000 #define SHARED_HW_CFG_TX_LANE3_POL_FLIP_ENABLED 0x00080000 /* TX lane Polarity swap */ #define SHARED_HW_CFG_RX_LANE0_POL_FLIP_ENABLED 0x00100000 #define SHARED_HW_CFG_RX_LANE1_POL_FLIP_ENABLED 0x00200000 #define SHARED_HW_CFG_RX_LANE2_POL_FLIP_ENABLED 0x00400000 #define SHARED_HW_CFG_RX_LANE3_POL_FLIP_ENABLED 0x00800000 /* Selects the port layout of the board */ #define SHARED_HW_CFG_E3_PORT_LAYOUT_MASK 0x0F000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_SHIFT 24 #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_01 0x00000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_2P_10 0x01000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_0123 0x02000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_1032 0x03000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_2301 0x04000000 #define SHARED_HW_CFG_E3_PORT_LAYOUT_4P_3210 0x05000000 }; /**************************************************************************** * Port HW configuration * ****************************************************************************/ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ uint32_t pci_id; #define PORT_HW_CFG_PCI_DEVICE_ID_MASK 0x0000FFFF #define PORT_HW_CFG_PCI_DEVICE_ID_SHIFT 0 #define PORT_HW_CFG_PCI_VENDOR_ID_MASK 0xFFFF0000 #define PORT_HW_CFG_PCI_VENDOR_ID_SHIFT 16 uint32_t pci_sub_id; #define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_MASK 0x0000FFFF #define PORT_HW_CFG_PCI_SUBSYS_VENDOR_ID_SHIFT 0 #define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_MASK 0xFFFF0000 #define PORT_HW_CFG_PCI_SUBSYS_DEVICE_ID_SHIFT 16 uint32_t power_dissipated; #define PORT_HW_CFG_POWER_DIS_D0_MASK 0x000000FF #define PORT_HW_CFG_POWER_DIS_D0_SHIFT 0 #define PORT_HW_CFG_POWER_DIS_D1_MASK 0x0000FF00 #define PORT_HW_CFG_POWER_DIS_D1_SHIFT 8 #define PORT_HW_CFG_POWER_DIS_D2_MASK 0x00FF0000 #define PORT_HW_CFG_POWER_DIS_D2_SHIFT 16 #define PORT_HW_CFG_POWER_DIS_D3_MASK 0xFF000000 #define PORT_HW_CFG_POWER_DIS_D3_SHIFT 24 uint32_t power_consumed; #define PORT_HW_CFG_POWER_CONS_D0_MASK 0x000000FF #define PORT_HW_CFG_POWER_CONS_D0_SHIFT 0 #define PORT_HW_CFG_POWER_CONS_D1_MASK 0x0000FF00 #define PORT_HW_CFG_POWER_CONS_D1_SHIFT 8 #define PORT_HW_CFG_POWER_CONS_D2_MASK 0x00FF0000 #define PORT_HW_CFG_POWER_CONS_D2_SHIFT 16 #define PORT_HW_CFG_POWER_CONS_D3_MASK 0xFF000000 #define PORT_HW_CFG_POWER_CONS_D3_SHIFT 24 uint32_t mac_upper; uint32_t mac_lower; /* 0x140 */ #define PORT_HW_CFG_UPPERMAC_MASK 0x0000FFFF #define PORT_HW_CFG_UPPERMAC_SHIFT 0 uint32_t iscsi_mac_upper; /* Upper 16 bits are always zeroes */ uint32_t iscsi_mac_lower; uint32_t rdma_mac_upper; /* Upper 16 bits are always zeroes */ uint32_t rdma_mac_lower; uint32_t serdes_config; #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_MASK 0x0000FFFF #define PORT_HW_CFG_SERDES_TX_DRV_PRE_EMPHASIS_SHIFT 0 #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_MASK 0xFFFF0000 #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16 /* Default values: 2P-64, 4P-32 */ uint32_t reserved; uint32_t vf_config; /* 0x15C */ #define PORT_HW_CFG_VF_PCI_DEVICE_ID_MASK 0xFFFF0000 #define PORT_HW_CFG_VF_PCI_DEVICE_ID_SHIFT 16 uint32_t mf_pci_id; /* 0x160 */ #define PORT_HW_CFG_MF_PCI_DEVICE_ID_MASK 0x0000FFFF #define PORT_HW_CFG_MF_PCI_DEVICE_ID_SHIFT 0 /* Controls the TX laser of the SFP+ module */ uint32_t sfp_ctrl; /* 0x164 */ #define PORT_HW_CFG_TX_LASER_MASK 0x000000FF #define PORT_HW_CFG_TX_LASER_SHIFT 0 #define PORT_HW_CFG_TX_LASER_MDIO 0x00000000 #define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001 #define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002 #define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003 #define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004 /* Controls the fault module LED of the SFP+ */ #define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00 #define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300 #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400 /* The output pin TX_DIS that controls the TX laser of the SFP+ module. Use the PIN_CFG_XXX defines on top */ uint32_t e3_sfp_ctrl; /* 0x168 */ #define PORT_HW_CFG_E3_TX_LASER_MASK 0x000000FF #define PORT_HW_CFG_E3_TX_LASER_SHIFT 0 /* The output pin for SFPP_TYPE which turns on the Fault module LED */ #define PORT_HW_CFG_E3_FAULT_MDL_LED_MASK 0x0000FF00 #define PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT 8 /* The input pin MOD_ABS that indicates whether SFP+ module is present or not. Use the PIN_CFG_XXX defines on top */ #define PORT_HW_CFG_E3_MOD_ABS_MASK 0x00FF0000 #define PORT_HW_CFG_E3_MOD_ABS_SHIFT 16 /* The output pin PWRDIS_SFP_X which disable the power of the SFP+ module. Use the PIN_CFG_XXX defines on top */ #define PORT_HW_CFG_E3_PWR_DIS_MASK 0xFF000000 #define PORT_HW_CFG_E3_PWR_DIS_SHIFT 24 /* * The input pin which signals module transmit fault. Use the * PIN_CFG_XXX defines on top */ uint32_t e3_cmn_pin_cfg; /* 0x16C */ #define PORT_HW_CFG_E3_TX_FAULT_MASK 0x000000FF #define PORT_HW_CFG_E3_TX_FAULT_SHIFT 0 /* The output pin which reset the PHY. Use the PIN_CFG_XXX defines on top */ #define PORT_HW_CFG_E3_PHY_RESET_MASK 0x0000FF00 #define PORT_HW_CFG_E3_PHY_RESET_SHIFT 8 /* * The output pin which powers down the PHY. Use the PIN_CFG_XXX * defines on top */ #define PORT_HW_CFG_E3_PWR_DOWN_MASK 0x00FF0000 #define PORT_HW_CFG_E3_PWR_DOWN_SHIFT 16 /* The output pin values BSC_SEL which selects the I2C for this port in the I2C Mux */ #define PORT_HW_CFG_E3_I2C_MUX0_MASK 0x01000000 #define PORT_HW_CFG_E3_I2C_MUX1_MASK 0x02000000 /* * The input pin I_FAULT which indicate over-current has occurred. * Use the PIN_CFG_XXX defines on top */ uint32_t e3_cmn_pin_cfg1; /* 0x170 */ #define PORT_HW_CFG_E3_OVER_CURRENT_MASK 0x000000FF #define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT 0 /* pause on host ring */ uint32_t generic_features; /* 0x174 */ #define PORT_HW_CFG_PAUSE_ON_HOST_RING_MASK 0x00000001 #define PORT_HW_CFG_PAUSE_ON_HOST_RING_SHIFT 0 #define PORT_HW_CFG_PAUSE_ON_HOST_RING_DISABLED 0x00000000 #define PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED 0x00000001 /* SFP+ Tx Equalization: NIC recommended and tested value is 0xBEB2 * LOM recommended and tested value is 0xBEB2. Using a different * value means using a value not tested by BRCM */ uint32_t sfi_tap_values; /* 0x178 */ #define PORT_HW_CFG_TX_EQUALIZATION_MASK 0x0000FFFF #define PORT_HW_CFG_TX_EQUALIZATION_SHIFT 0 /* SFP+ Tx driver broadcast IDRIVER: NIC recommended and tested * value is 0x2. LOM recommended and tested value is 0x2. Using a * different value means using a value not tested by BRCM */ #define PORT_HW_CFG_TX_DRV_BROADCAST_MASK 0x000F0000 #define PORT_HW_CFG_TX_DRV_BROADCAST_SHIFT 16 uint32_t reserved0[5]; /* 0x17c */ uint32_t aeu_int_mask; /* 0x190 */ uint32_t media_type; /* 0x194 */ #define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK 0x000000FF #define PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT 0 #define PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK 0x0000FF00 #define PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT 8 #define PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK 0x00FF0000 #define PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT 16 /* 4 times 16 bits for all 4 lanes. In case external PHY is present (not direct mode), those values will not take effect on the 4 XGXS lanes. For some external PHYs (such as 8706 and 8726) the values will be used to configure the external PHY in those cases, not all 4 values are needed. */ uint16_t xgxs_config_rx[4]; /* 0x198 */ uint16_t xgxs_config_tx[4]; /* 0x1A0 */ /* For storing FCOE mac on shared memory */ uint32_t fcoe_fip_mac_upper; #define PORT_HW_CFG_FCOE_UPPERMAC_MASK 0x0000ffff #define PORT_HW_CFG_FCOE_UPPERMAC_SHIFT 0 uint32_t fcoe_fip_mac_lower; uint32_t fcoe_wwn_port_name_upper; uint32_t fcoe_wwn_port_name_lower; uint32_t fcoe_wwn_node_name_upper; uint32_t fcoe_wwn_node_name_lower; /* wwpn for npiv enabled */ uint32_t wwpn_for_npiv_config; /* 0x1C0 */ #define PORT_HW_CFG_WWPN_FOR_NPIV_ENABLED_MASK 0x00000001 #define PORT_HW_CFG_WWPN_FOR_NPIV_ENABLED_SHIFT 0 #define PORT_HW_CFG_WWPN_FOR_NPIV_ENABLED_DISABLED 0x00000000 #define PORT_HW_CFG_WWPN_FOR_NPIV_ENABLED_ENABLED 0x00000001 /* wwpn for npiv valid addresses */ uint32_t wwpn_for_npiv_valid_addresses; /* 0x1C4 */ #define PORT_HW_CFG_WWPN_FOR_NPIV_ADDRESS_BITMAP_MASK 0x0000FFFF #define PORT_HW_CFG_WWPN_FOR_NPIV_ADDRESS_BITMAP_SHIFT 0 struct mac_addr wwpn_for_niv_macs[16]; /* Reserved bits: 2272-2336 For storing FCOE mac on shared memory */ uint32_t Reserved1[14]; uint32_t pf_allocation; /* 0x280 */ /* number of vfs per PF, if 0 - sriov disabled */ #define PORT_HW_CFG_NUMBER_OF_VFS_MASK 0x000000FF #define PORT_HW_CFG_NUMBER_OF_VFS_SHIFT 0 /* Enable RJ45 magjack pair swapping on 10GBase-T PHY (0=default), 84833 only */ uint32_t xgbt_phy_cfg; /* 0x284 */ #define PORT_HW_CFG_RJ45_PAIR_SWAP_MASK 0x000000FF #define PORT_HW_CFG_RJ45_PAIR_SWAP_SHIFT 0 uint32_t default_cfg; /* 0x288 */ #define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003 #define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0 #define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000 #define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001 #define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002 #define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003 #define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C #define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2 #define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000 #define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004 #define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008 #define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c #define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030 #define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4 #define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000 #define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010 #define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020 #define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030 #define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0 #define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6 #define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000 #define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040 #define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080 #define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0 /* When KR link is required to be set to force which is not KR-compliant, this parameter determine what is the trigger for it. When GPIO is selected, low input will force the speed. Currently default speed is 1G. In the future, it may be widen to select the forced speed in with another parameter. Note when force-1G is enabled, it override option 56: Link Speed option. */ #define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00 #define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8 #define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700 #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800 #define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900 /* Enable to determine with which GPIO to reset the external phy */ #define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000 #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000 /* Enable BAM on KR */ #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED 0x00000000 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED 0x00100000 /* Enable Common Mode Sense */ #define PORT_HW_CFG_ENABLE_CMS_MASK 0x00200000 #define PORT_HW_CFG_ENABLE_CMS_SHIFT 21 #define PORT_HW_CFG_ENABLE_CMS_DISABLED 0x00000000 #define PORT_HW_CFG_ENABLE_CMS_ENABLED 0x00200000 /* Determine the Serdes electrical interface */ #define PORT_HW_CFG_NET_SERDES_IF_MASK 0x0F000000 #define PORT_HW_CFG_NET_SERDES_IF_SHIFT 24 #define PORT_HW_CFG_NET_SERDES_IF_SGMII 0x00000000 #define PORT_HW_CFG_NET_SERDES_IF_XFI 0x01000000 #define PORT_HW_CFG_NET_SERDES_IF_SFI 0x02000000 #define PORT_HW_CFG_NET_SERDES_IF_KR 0x03000000 #define PORT_HW_CFG_NET_SERDES_IF_DXGXS 0x04000000 #define PORT_HW_CFG_NET_SERDES_IF_KR2 0x05000000 /* SFP+ main TAP and post TAP volumes */ #define PORT_HW_CFG_TAP_LEVELS_MASK 0x70000000 #define PORT_HW_CFG_TAP_LEVELS_SHIFT 28 #define PORT_HW_CFG_TAP_LEVELS_POST_15_MAIN_43 0x00000000 #define PORT_HW_CFG_TAP_LEVELS_POST_14_MAIN_44 0x10000000 #define PORT_HW_CFG_TAP_LEVELS_POST_13_MAIN_45 0x20000000 #define PORT_HW_CFG_TAP_LEVELS_POST_12_MAIN_46 0x30000000 #define PORT_HW_CFG_TAP_LEVELS_POST_11_MAIN_47 0x40000000 #define PORT_HW_CFG_TAP_LEVELS_POST_10_MAIN_48 0x50000000 uint32_t speed_capability_mask2; /* 0x28C */ #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK 0x0000FFFF #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT 0 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_FULL 0x00000001 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10M_HALF 0x00000002 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_HALF 0x00000004 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_100M_FULL 0x00000008 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_1G 0x00000010 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_2_5G 0x00000020 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_10G 0x00000040 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_20G 0x00000080 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_MASK 0xFFFF0000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_SHIFT 16 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_FULL 0x00010000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10M_HALF 0x00020000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_HALF 0x00040000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_100M_FULL 0x00080000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_1G 0x00100000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_2_5G 0x00200000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G 0x00400000 #define PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G 0x00800000 /* In the case where two media types (e.g. copper and fiber) are present and electrically active at the same time, PHY Selection will determine which of the two PHYs will be designated as the Active PHY and used for a connection to the network. */ uint32_t multi_phy_config; /* 0x290 */ #define PORT_HW_CFG_PHY_SELECTION_MASK 0x00000007 #define PORT_HW_CFG_PHY_SELECTION_SHIFT 0 #define PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT 0x00000000 #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY 0x00000001 #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY 0x00000002 #define PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY 0x00000003 #define PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY 0x00000004 /* When enabled, all second phy nvram parameters will be swapped with the first phy parameters */ #define PORT_HW_CFG_PHY_SWAPPED_MASK 0x00000008 #define PORT_HW_CFG_PHY_SWAPPED_SHIFT 3 #define PORT_HW_CFG_PHY_SWAPPED_DISABLED 0x00000000 #define PORT_HW_CFG_PHY_SWAPPED_ENABLED 0x00000008 /* Address of the second external phy */ uint32_t external_phy_config2; /* 0x294 */ #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_MASK 0x000000FF #define PORT_HW_CFG_XGXS_EXT_PHY2_ADDR_SHIFT 0 /* The second XGXS external PHY type */ #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_MASK 0x0000FF00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SHIFT 8 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_DIRECT 0x00000000 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8071 0x00000100 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8072 0x00000200 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8073 0x00000300 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8705 0x00000400 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8706 0x00000500 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8726 0x00000600 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8481 0x00000700 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_SFX7101 0x00000800 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8727 0x00000900 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8727_NOC 0x00000a00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X84823 0x00000b00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X54640 0x00000c00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X84833 0x00000d00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X54618SE 0x00000e00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X8722 0x00000f00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X54616 0x00001000 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BNX2X84834 0x00001100 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN 0x0000ff00 /* 4 times 16 bits for all 4 lanes. For some external PHYs (such as 8706, 8726 and 8727) not all 4 values are needed. */ uint16_t xgxs_config2_rx[4]; /* 0x296 */ uint16_t xgxs_config2_tx[4]; /* 0x2A0 */ uint32_t lane_config; #define PORT_HW_CFG_LANE_SWAP_CFG_MASK 0x0000FFFF #define PORT_HW_CFG_LANE_SWAP_CFG_SHIFT 0 /* AN and forced */ #define PORT_HW_CFG_LANE_SWAP_CFG_01230123 0x00001b1b /* forced only */ #define PORT_HW_CFG_LANE_SWAP_CFG_01233210 0x00001be4 /* forced only */ #define PORT_HW_CFG_LANE_SWAP_CFG_31203120 0x0000d8d8 /* forced only */ #define PORT_HW_CFG_LANE_SWAP_CFG_32103210 0x0000e4e4 #define PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK 0x000000FF #define PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT 0 #define PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK 0x0000FF00 #define PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT 8 #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK 0x0000C000 #define PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT 14 /* Indicate whether to swap the external phy polarity */ #define PORT_HW_CFG_SWAP_PHY_POLARITY_MASK 0x00010000 #define PORT_HW_CFG_SWAP_PHY_POLARITY_DISABLED 0x00000000 #define PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED 0x00010000 uint32_t external_phy_config; #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK 0x000000FF #define PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT 0 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK 0x0000FF00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SHIFT 8 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT 0x00000000 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8071 0x00000100 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8072 0x00000200 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8073 0x00000300 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8705 0x00000400 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8706 0x00000500 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726 0x00000600 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8481 0x00000700 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727 0x00000900 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727_NOC 0x00000a00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823 0x00000b00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54640 0x00000c00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833 0x00000d00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE 0x00000e00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722 0x00000f00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54616 0x00001000 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834 0x00001100 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC 0x0000fc00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN 0x0000ff00 #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_MASK 0x00FF0000 #define PORT_HW_CFG_SERDES_EXT_PHY_ADDR_SHIFT 16 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK 0xFF000000 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_SHIFT 24 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT 0x00000000 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BNX2X5482 0x01000000 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD 0x02000000 #define PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN 0xff000000 uint32_t speed_capability_mask; #define PORT_HW_CFG_SPEED_CAPABILITY_D3_MASK 0x0000FFFF #define PORT_HW_CFG_SPEED_CAPABILITY_D3_SHIFT 0 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_FULL 0x00000001 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10M_HALF 0x00000002 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_HALF 0x00000004 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_100M_FULL 0x00000008 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_1G 0x00000010 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_2_5G 0x00000020 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_10G 0x00000040 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_20G 0x00000080 #define PORT_HW_CFG_SPEED_CAPABILITY_D3_RESERVED 0x0000f000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_MASK 0xFFFF0000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_SHIFT 16 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL 0x00010000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF 0x00020000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF 0x00040000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL 0x00080000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_1G 0x00100000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G 0x00200000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_10G 0x00400000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_20G 0x00800000 #define PORT_HW_CFG_SPEED_CAPABILITY_D0_RESERVED 0xf0000000 /* A place to hold the original MAC address as a backup */ uint32_t backup_mac_upper; /* 0x2B4 */ uint32_t backup_mac_lower; /* 0x2B8 */ }; /**************************************************************************** * Shared Feature configuration * ****************************************************************************/ struct shared_feat_cfg { /* NVRAM Offset */ uint32_t config; /* 0x450 */ #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001 /* Use NVRAM values instead of HW default values */ #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_MASK \ 0x00000002 #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED \ 0x00000000 #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED \ 0x00000002 #define SHARED_FEAT_CFG_NCSI_ID_METHOD_MASK 0x00000008 #define SHARED_FEAT_CFG_NCSI_ID_METHOD_SPIO 0x00000000 #define SHARED_FEAT_CFG_NCSI_ID_METHOD_NVRAM 0x00000008 #define SHARED_FEAT_CFG_NCSI_ID_MASK 0x00000030 #define SHARED_FEAT_CFG_NCSI_ID_SHIFT 4 /* Override the OTP back to single function mode. When using GPIO, high means only SF, 0 is according to CLP configuration */ #define SHARED_FEAT_CFG_FORCE_SF_MODE_MASK 0x00000700 #define SHARED_FEAT_CFG_FORCE_SF_MODE_SHIFT 8 #define SHARED_FEAT_CFG_FORCE_SF_MODE_MF_ALLOWED 0x00000000 #define SHARED_FEAT_CFG_FORCE_SF_MODE_FORCED_SF 0x00000100 #define SHARED_FEAT_CFG_FORCE_SF_MODE_SPIO4 0x00000200 #define SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT 0x00000300 #define SHARED_FEAT_CFG_FORCE_SF_MODE_AFEX_MODE 0x00000400 /* Act as if the FCoE license is invalid */ #define SHARED_FEAT_CFG_PREVENT_FCOE 0x00001000 /* Force FLR capability to all ports */ #define SHARED_FEAT_CFG_FORCE_FLR_CAPABILITY 0x00002000 /* Act as if the iSCSI license is invalid */ #define SHARED_FEAT_CFG_PREVENT_ISCSI_MASK 0x00004000 #define SHARED_FEAT_CFG_PREVENT_ISCSI_SHIFT 14 #define SHARED_FEAT_CFG_PREVENT_ISCSI_DISABLED 0x00000000 #define SHARED_FEAT_CFG_PREVENT_ISCSI_ENABLED 0x00004000 /* The interval in seconds between sending LLDP packets. Set to zero to disable the feature */ #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_MASK 0x00FF0000 #define SHARED_FEAT_CFG_LLDP_XMIT_INTERVAL_SHIFT 16 /* The assigned device type ID for LLDP usage */ #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_MASK 0xFF000000 #define SHARED_FEAT_CFG_LLDP_DEVICE_TYPE_ID_SHIFT 24 }; /**************************************************************************** * Port Feature configuration * ****************************************************************************/ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */ uint32_t config; #define PORT_FEAT_CFG_BAR1_SIZE_MASK 0x0000000F #define PORT_FEAT_CFG_BAR1_SIZE_SHIFT 0 #define PORT_FEAT_CFG_BAR1_SIZE_DISABLED 0x00000000 #define PORT_FEAT_CFG_BAR1_SIZE_64K 0x00000001 #define PORT_FEAT_CFG_BAR1_SIZE_128K 0x00000002 #define PORT_FEAT_CFG_BAR1_SIZE_256K 0x00000003 #define PORT_FEAT_CFG_BAR1_SIZE_512K 0x00000004 #define PORT_FEAT_CFG_BAR1_SIZE_1M 0x00000005 #define PORT_FEAT_CFG_BAR1_SIZE_2M 0x00000006 #define PORT_FEAT_CFG_BAR1_SIZE_4M 0x00000007 #define PORT_FEAT_CFG_BAR1_SIZE_8M 0x00000008 #define PORT_FEAT_CFG_BAR1_SIZE_16M 0x00000009 #define PORT_FEAT_CFG_BAR1_SIZE_32M 0x0000000a #define PORT_FEAT_CFG_BAR1_SIZE_64M 0x0000000b #define PORT_FEAT_CFG_BAR1_SIZE_128M 0x0000000c #define PORT_FEAT_CFG_BAR1_SIZE_256M 0x0000000d #define PORT_FEAT_CFG_BAR1_SIZE_512M 0x0000000e #define PORT_FEAT_CFG_BAR1_SIZE_1G 0x0000000f #define PORT_FEAT_CFG_BAR2_SIZE_MASK 0x000000F0 #define PORT_FEAT_CFG_BAR2_SIZE_SHIFT 4 #define PORT_FEAT_CFG_BAR2_SIZE_DISABLED 0x00000000 #define PORT_FEAT_CFG_BAR2_SIZE_64K 0x00000010 #define PORT_FEAT_CFG_BAR2_SIZE_128K 0x00000020 #define PORT_FEAT_CFG_BAR2_SIZE_256K 0x00000030 #define PORT_FEAT_CFG_BAR2_SIZE_512K 0x00000040 #define PORT_FEAT_CFG_BAR2_SIZE_1M 0x00000050 #define PORT_FEAT_CFG_BAR2_SIZE_2M 0x00000060 #define PORT_FEAT_CFG_BAR2_SIZE_4M 0x00000070 #define PORT_FEAT_CFG_BAR2_SIZE_8M 0x00000080 #define PORT_FEAT_CFG_BAR2_SIZE_16M 0x00000090 #define PORT_FEAT_CFG_BAR2_SIZE_32M 0x000000a0 #define PORT_FEAT_CFG_BAR2_SIZE_64M 0x000000b0 #define PORT_FEAT_CFG_BAR2_SIZE_128M 0x000000c0 #define PORT_FEAT_CFG_BAR2_SIZE_256M 0x000000d0 #define PORT_FEAT_CFG_BAR2_SIZE_512M 0x000000e0 #define PORT_FEAT_CFG_BAR2_SIZE_1G 0x000000f0 #define PORT_FEAT_CFG_DCBX_MASK 0x00000100 #define PORT_FEAT_CFG_DCBX_DISABLED 0x00000000 #define PORT_FEAT_CFG_DCBX_ENABLED 0x00000100 #define PORT_FEAT_CFG_AUTOGREEEN_MASK 0x00000200 #define PORT_FEAT_CFG_AUTOGREEEN_SHIFT 9 #define PORT_FEAT_CFG_AUTOGREEEN_DISABLED 0x00000000 #define PORT_FEAT_CFG_AUTOGREEEN_ENABLED 0x00000200 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_MASK 0x00000C00 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_SHIFT 10 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_DEFAULT 0x00000000 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_FCOE 0x00000400 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_ISCSI 0x00000800 #define PORT_FEAT_CFG_STORAGE_PERSONALITY_BOTH 0x00000c00 #define PORT_FEATURE_EN_SIZE_MASK 0x0f000000 #define PORT_FEATURE_EN_SIZE_SHIFT 24 #define PORT_FEATURE_WOL_ENABLED 0x01000000 #define PORT_FEATURE_MBA_ENABLED 0x02000000 #define PORT_FEATURE_MFW_ENABLED 0x04000000 /* Advertise expansion ROM even if MBA is disabled */ #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_MASK 0x08000000 #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_DISABLED 0x00000000 #define PORT_FEAT_CFG_FORCE_EXP_ROM_ADV_ENABLED 0x08000000 /* Check the optic vendor via i2c against a list of approved modules in a separate nvram image */ #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK 0xE0000000 #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_SHIFT 29 #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT \ 0x00000000 #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER \ 0x20000000 #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG 0x40000000 #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN 0x60000000 uint32_t wol_config; /* Default is used when driver sets to "auto" mode */ #define PORT_FEATURE_WOL_ACPI_UPON_MGMT 0x00000010 uint32_t mba_config; #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x00000007 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT 0 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0x00000000 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 0x00000001 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 0x00000002 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB 0x00000003 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT 0x00000004 #define PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE 0x00000007 #define PORT_FEATURE_MBA_BOOT_RETRY_MASK 0x00000038 #define PORT_FEATURE_MBA_BOOT_RETRY_SHIFT 3 #define PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x00000400 #define PORT_FEATURE_MBA_HOTKEY_MASK 0x00000800 #define PORT_FEATURE_MBA_HOTKEY_CTRL_S 0x00000000 #define PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x00000800 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0x000FF000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT 12 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0x00000000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x00001000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x00002000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x00003000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x00004000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x00005000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x00006000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x00007000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x00008000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0x00009000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0x0000a000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0x0000b000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0x0000c000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0x0000d000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0x0000e000 #define PORT_FEATURE_MBA_EXP_ROM_SIZE_32M 0x0000f000 #define PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0x00F00000 #define PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT 20 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x03000000 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT 24 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0x00000000 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x01000000 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x02000000 #define PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x03000000 #define PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3C000000 #define PORT_FEATURE_MBA_LINK_SPEED_SHIFT 26 #define PORT_FEATURE_MBA_LINK_SPEED_AUTO 0x00000000 #define PORT_FEATURE_MBA_LINK_SPEED_10M_HALF 0x04000000 #define PORT_FEATURE_MBA_LINK_SPEED_10M_FULL 0x08000000 #define PORT_FEATURE_MBA_LINK_SPEED_100M_HALF 0x0c000000 #define PORT_FEATURE_MBA_LINK_SPEED_100M_FULL 0x10000000 #define PORT_FEATURE_MBA_LINK_SPEED_1G 0x14000000 #define PORT_FEATURE_MBA_LINK_SPEED_2_5G 0x18000000 #define PORT_FEATURE_MBA_LINK_SPEED_10G 0x1c000000 #define PORT_FEATURE_MBA_LINK_SPEED_20G 0x20000000 uint32_t Reserved0; /* 0x460 */ uint32_t mba_vlan_cfg; #define PORT_FEATURE_MBA_VLAN_TAG_MASK 0x0000FFFF #define PORT_FEATURE_MBA_VLAN_TAG_SHIFT 0 #define PORT_FEATURE_MBA_VLAN_EN 0x00010000 uint32_t Reserved1; uint32_t smbus_config; #define PORT_FEATURE_SMBUS_ADDR_MASK 0x000000fe #define PORT_FEATURE_SMBUS_ADDR_SHIFT 1 uint32_t vf_config; #define PORT_FEAT_CFG_VF_BAR2_SIZE_MASK 0x0000000F #define PORT_FEAT_CFG_VF_BAR2_SIZE_SHIFT 0 #define PORT_FEAT_CFG_VF_BAR2_SIZE_DISABLED 0x00000000 #define PORT_FEAT_CFG_VF_BAR2_SIZE_4K 0x00000001 #define PORT_FEAT_CFG_VF_BAR2_SIZE_8K 0x00000002 #define PORT_FEAT_CFG_VF_BAR2_SIZE_16K 0x00000003 #define PORT_FEAT_CFG_VF_BAR2_SIZE_32K 0x00000004 #define PORT_FEAT_CFG_VF_BAR2_SIZE_64K 0x00000005 #define PORT_FEAT_CFG_VF_BAR2_SIZE_128K 0x00000006 #define PORT_FEAT_CFG_VF_BAR2_SIZE_256K 0x00000007 #define PORT_FEAT_CFG_VF_BAR2_SIZE_512K 0x00000008 #define PORT_FEAT_CFG_VF_BAR2_SIZE_1M 0x00000009 #define PORT_FEAT_CFG_VF_BAR2_SIZE_2M 0x0000000a #define PORT_FEAT_CFG_VF_BAR2_SIZE_4M 0x0000000b #define PORT_FEAT_CFG_VF_BAR2_SIZE_8M 0x0000000c #define PORT_FEAT_CFG_VF_BAR2_SIZE_16M 0x0000000d #define PORT_FEAT_CFG_VF_BAR2_SIZE_32M 0x0000000e #define PORT_FEAT_CFG_VF_BAR2_SIZE_64M 0x0000000f uint32_t link_config; /* Used as HW defaults for the driver */ #define PORT_FEATURE_FLOW_CONTROL_MASK 0x00000700 #define PORT_FEATURE_FLOW_CONTROL_SHIFT 8 #define PORT_FEATURE_FLOW_CONTROL_AUTO 0x00000000 #define PORT_FEATURE_FLOW_CONTROL_TX 0x00000100 #define PORT_FEATURE_FLOW_CONTROL_RX 0x00000200 #define PORT_FEATURE_FLOW_CONTROL_BOTH 0x00000300 #define PORT_FEATURE_FLOW_CONTROL_NONE 0x00000400 #define PORT_FEATURE_FLOW_CONTROL_SAFC_RX 0x00000500 #define PORT_FEATURE_FLOW_CONTROL_SAFC_TX 0x00000600 #define PORT_FEATURE_FLOW_CONTROL_SAFC_BOTH 0x00000700 #define PORT_FEATURE_LINK_SPEED_MASK 0x000F0000 #define PORT_FEATURE_LINK_SPEED_SHIFT 16 #define PORT_FEATURE_LINK_SPEED_AUTO 0x00000000 #define PORT_FEATURE_LINK_SPEED_10M_FULL 0x00010000 #define PORT_FEATURE_LINK_SPEED_10M_HALF 0x00020000 #define PORT_FEATURE_LINK_SPEED_100M_HALF 0x00030000 #define PORT_FEATURE_LINK_SPEED_100M_FULL 0x00040000 #define PORT_FEATURE_LINK_SPEED_1G 0x00050000 #define PORT_FEATURE_LINK_SPEED_2_5G 0x00060000 #define PORT_FEATURE_LINK_SPEED_10G_CX4 0x00070000 #define PORT_FEATURE_LINK_SPEED_20G 0x00080000 #define PORT_FEATURE_CONNECTED_SWITCH_MASK 0x03000000 #define PORT_FEATURE_CONNECTED_SWITCH_SHIFT 24 /* (forced) low speed switch (< 10G) */ #define PORT_FEATURE_CON_SWITCH_1G_SWITCH 0x00000000 /* (forced) high speed switch (>= 10G) */ #define PORT_FEATURE_CON_SWITCH_10G_SWITCH 0x01000000 #define PORT_FEATURE_CON_SWITCH_AUTO_DETECT 0x02000000 #define PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT 0x03000000 /* The default for MCP link configuration, uses the same defines as link_config */ uint32_t mfw_wol_link_cfg; /* The default for the driver of the second external phy, uses the same defines as link_config */ uint32_t link_config2; /* 0x47C */ /* The default for MCP of the second external phy, uses the same defines as link_config */ uint32_t mfw_wol_link_cfg2; /* 0x480 */ /* EEE power saving mode */ uint32_t eee_power_mode; /* 0x484 */ #define PORT_FEAT_CFG_EEE_POWER_MODE_MASK 0x000000FF #define PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT 0 #define PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED 0x00000000 #define PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED 0x00000001 #define PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE 0x00000002 #define PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY 0x00000003 uint32_t Reserved2[16]; /* 0x488 */ }; /**************************************************************************** * Device Information * ****************************************************************************/ struct shm_dev_info { /* size */ uint32_t bc_rev; /* 8 bits each: major, minor, build */ /* 4 */ struct shared_hw_cfg shared_hw_config; /* 40 */ struct port_hw_cfg port_hw_config[PORT_MAX]; /* 400*2=800 */ struct shared_feat_cfg shared_feature_config; /* 4 */ struct port_feat_cfg port_feature_config[PORT_MAX];/* 116*2=232 */ }; struct extended_dev_info_shared_cfg { /* NVRAM OFFSET */ /* Threshold in celcius to start using the fan */ uint32_t temperature_monitor1; /* 0x4000 */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_THRESH_MASK 0x0000007F #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_THRESH_SHIFT 0 /* Threshold in celcius to shut down the board */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_THRESH_MASK 0x00007F00 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_THRESH_SHIFT 8 /* EPIO of fan temperature status */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_SHIFT 16 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_NA 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO0 0x00010000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO1 0x00020000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO2 0x00030000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO3 0x00040000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO4 0x00050000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO5 0x00060000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO6 0x00070000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO7 0x00080000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO8 0x00090000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO9 0x000a0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO10 0x000b0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO11 0x000c0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO12 0x000d0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO13 0x000e0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO14 0x000f0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO15 0x00100000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO16 0x00110000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO17 0x00120000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO18 0x00130000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO19 0x00140000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO20 0x00150000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO21 0x00160000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO22 0x00170000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO23 0x00180000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO24 0x00190000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO25 0x001a0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO26 0x001b0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO27 0x001c0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO28 0x001d0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO29 0x001e0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO30 0x001f0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_FAN_EPIO_EPIO31 0x00200000 /* EPIO of shut down temperature status */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_MASK 0xFF000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_SHIFT 24 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_NA 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO0 0x01000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO1 0x02000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO2 0x03000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO3 0x04000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO4 0x05000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO5 0x06000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO6 0x07000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO7 0x08000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO8 0x09000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO9 0x0a000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO10 0x0b000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO11 0x0c000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO12 0x0d000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO13 0x0e000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO14 0x0f000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO15 0x10000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO16 0x11000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO17 0x12000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO18 0x13000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO19 0x14000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO20 0x15000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO21 0x16000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO22 0x17000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO23 0x18000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO24 0x19000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO25 0x1a000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO26 0x1b000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO27 0x1c000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO28 0x1d000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO29 0x1e000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO30 0x1f000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SHUT_EPIO_EPIO31 0x20000000 /* EPIO of shut down temperature status */ uint32_t temperature_monitor2; /* 0x4004 */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_PERIOD_MASK 0x0000FFFF #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_PERIOD_SHIFT 0 /* MFW flavor to be used */ uint32_t mfw_cfg; /* 0x4008 */ #define EXTENDED_DEV_INFO_SHARED_CFG_MFW_FLAVOR_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_MFW_FLAVOR_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_MFW_FLAVOR_NA 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_MFW_FLAVOR_A 0x00000001 /* Should NIC data query remain enabled upon last drv unload */ #define EXTENDED_DEV_INFO_SHARED_CFG_OCBB_EN_LAST_DRV_MASK 0x00000100 #define EXTENDED_DEV_INFO_SHARED_CFG_OCBB_EN_LAST_DRV_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_OCBB_EN_LAST_DRV_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_OCBB_EN_LAST_DRV_ENABLED 0x00000100 /* Hide DCBX feature in CCM/BACS menus */ #define EXTENDED_DEV_INFO_SHARED_CFG_HIDE_DCBX_FEAT_MASK 0x00010000 #define EXTENDED_DEV_INFO_SHARED_CFG_HIDE_DCBX_FEAT_SHIFT 16 #define EXTENDED_DEV_INFO_SHARED_CFG_HIDE_DCBX_FEAT_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_HIDE_DCBX_FEAT_ENABLED 0x00010000 uint32_t smbus_config; /* 0x400C */ #define EXTENDED_DEV_INFO_SHARED_CFG_SMBUS_ADDR_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_SMBUS_ADDR_SHIFT 0 /* Switching regulator loop gain */ uint32_t board_cfg; /* 0x4010 */ #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_MASK 0x0000000F #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_HW_DEFAULT 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_X2 0x00000008 #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_X4 0x00000009 #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_X8 0x0000000a #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_X16 0x0000000b #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_DIV8 0x0000000c #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_DIV4 0x0000000d #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_DIV2 0x0000000e #define EXTENDED_DEV_INFO_SHARED_CFG_LOOP_GAIN_X1 0x0000000f /* whether shadow swim feature is supported */ #define EXTENDED_DEV_INFO_SHARED_CFG_SHADOW_SWIM_MASK 0x00000100 #define EXTENDED_DEV_INFO_SHARED_CFG_SHADOW_SWIM_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_SHADOW_SWIM_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_SHADOW_SWIM_ENABLED 0x00000100 /* whether to show/hide SRIOV menu in CCM */ #define EXTENDED_DEV_INFO_SHARED_CFG_SRIOV_SHOW_MENU_MASK 0x00000200 #define EXTENDED_DEV_INFO_SHARED_CFG_SRIOV_SHOW_MENU_SHIFT 9 #define EXTENDED_DEV_INFO_SHARED_CFG_SRIOV_SHOW_MENU 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_SRIOV_HIDE_MENU 0x00000200 /* Threshold in celcius for max continuous operation */ uint32_t temperature_report; /* 0x4014 */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_MCOT_MASK 0x0000007F #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_MCOT_SHIFT 0 /* Threshold in celcius for sensor caution */ #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SCT_MASK 0x00007F00 #define EXTENDED_DEV_INFO_SHARED_CFG_TEMP_SCT_SHIFT 8 /* wwn node prefix to be used (unless value is 0) */ uint32_t wwn_prefix; /* 0x4018 */ #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_NODE_PREFIX0_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_NODE_PREFIX0_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_NODE_PREFIX1_MASK 0x0000FF00 #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_NODE_PREFIX1_SHIFT 8 /* wwn port prefix to be used (unless value is 0) */ #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_PORT_PREFIX0_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_PORT_PREFIX0_SHIFT 16 /* wwn port prefix to be used (unless value is 0) */ #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_PORT_PREFIX1_MASK 0xFF000000 #define EXTENDED_DEV_INFO_SHARED_CFG_WWN_PORT_PREFIX1_SHIFT 24 /* General debug nvm cfg */ uint32_t dbg_cfg_flags; /* 0x401C */ #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_MASK 0x000FFFFF #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_ENABLE 0x00000001 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_EN_SIGDET_FILTER 0x00000002 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SET_LP_TX_PRESET7 0x00000004 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SET_TX_ANA_DEFAULT 0x00000008 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SET_PLL_ANA_DEFAULT 0x00000010 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_FORCE_G1PLL_RETUNE 0x00000020 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SET_RX_ANA_DEFAULT 0x00000040 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_FORCE_SERDES_RX_CLK 0x00000080 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_DIS_RX_LP_EIEOS 0x00000100 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_FINALIZE_UCODE 0x00000200 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_HOLDOFF_REQ 0x00000400 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_RX_SIGDET_OVERRIDE 0x00000800 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_GP_PORG_UC_RESET 0x00001000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SUPPRESS_COMPEN_EVT 0x00002000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_ADJ_TXEQ_P0_P1 0x00004000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_G3_PLL_RETUNE 0x00008000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_SET_MAC_PHY_CTL8 0x00010000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_DIS_MAC_G3_FRM_ERR 0x00020000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_INFERRED_EI 0x00040000 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_GEN3_COMPLI_ENA 0x00080000 /* Debug signet rx threshold */ uint32_t dbg_rx_sigdet_threshold; /* 0x4020 */ #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_RX_SIGDET_MASK 0x00000007 #define EXTENDED_DEV_INFO_SHARED_CFG_DBG_RX_SIGDET_SHIFT 0 /* Enable IFFE feature */ uint32_t iffe_features; /* 0x4024 */ #define EXTENDED_DEV_INFO_SHARED_CFG_ENABLE_IFFE_MASK 0x00000001 #define EXTENDED_DEV_INFO_SHARED_CFG_ENABLE_IFFE_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_ENABLE_IFFE_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_ENABLE_IFFE_ENABLED 0x00000001 /* Allowable port enablement (bitmask for ports 3-1) */ #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_PORT_MASK 0x0000000E #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_PORT_SHIFT 1 /* Allow iSCSI offload override */ #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_ISCSI_MASK 0x00000010 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_ISCSI_SHIFT 4 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_ISCSI_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_ISCSI_ENABLED 0x00000010 /* Allow FCoE offload override */ #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_FCOE_MASK 0x00000020 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_FCOE_SHIFT 5 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_FCOE_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_OVERRIDE_FCOE_ENABLED 0x00000020 /* Tie to adaptor */ #define EXTENDED_DEV_INFO_SHARED_CFG_TIE_ADAPTOR_MASK 0x00008000 #define EXTENDED_DEV_INFO_SHARED_CFG_TIE_ADAPTOR_SHIFT 15 #define EXTENDED_DEV_INFO_SHARED_CFG_TIE_ADAPTOR_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_TIE_ADAPTOR_ENABLED 0x00008000 /* Currently enabled port(s) (bitmask for ports 3-1) */ uint32_t current_iffe_mask; /* 0x4028 */ #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_CFG_MASK 0x0000000E #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_CFG_SHIFT 1 /* Current iSCSI offload */ #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_ISCSI_MASK 0x00000010 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_ISCSI_SHIFT 4 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_ISCSI_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_ISCSI_ENABLED 0x00000010 /* Current FCoE offload */ #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_FCOE_MASK 0x00000020 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_FCOE_SHIFT 5 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_FCOE_DISABLED 0x00000000 #define EXTENDED_DEV_INFO_SHARED_CFG_CURRENT_FCOE_ENABLED 0x00000020 /* FW set this pin to "0" (assert) these signal if either of its MAC * or PHY specific threshold values is exceeded. * Values are standard GPIO/EPIO pins. */ uint32_t threshold_pin; /* 0x402C */ #define EXTENDED_DEV_INFO_SHARED_CFG_TCONTROL_PIN_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_TCONTROL_PIN_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_TWARNING_PIN_MASK 0x0000FF00 #define EXTENDED_DEV_INFO_SHARED_CFG_TWARNING_PIN_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_TCRITICAL_PIN_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_TCRITICAL_PIN_SHIFT 16 /* MAC die temperature threshold in Celsius. */ uint32_t mac_threshold_val; /* 0x4030 */ #define EXTENDED_DEV_INFO_SHARED_CFG_CONTROL_MAC_THRESH_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_CONTROL_MAC_THRESH_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_WARNING_MAC_THRESH_MASK 0x0000FF00 #define EXTENDED_DEV_INFO_SHARED_CFG_WARNING_MAC_THRESH_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_CRITICAL_MAC_THRESH_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_CRITICAL_MAC_THRESH_SHIFT 16 /* PHY die temperature threshold in Celsius. */ uint32_t phy_threshold_val; /* 0x4034 */ #define EXTENDED_DEV_INFO_SHARED_CFG_CONTROL_PHY_THRESH_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_CONTROL_PHY_THRESH_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_WARNING_PHY_THRESH_MASK 0x0000FF00 #define EXTENDED_DEV_INFO_SHARED_CFG_WARNING_PHY_THRESH_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_CRITICAL_PHY_THRESH_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_CRITICAL_PHY_THRESH_SHIFT 16 /* External pins to communicate with host. * Values are standard GPIO/EPIO pins. */ uint32_t host_pin; /* 0x4038 */ #define EXTENDED_DEV_INFO_SHARED_CFG_I2C_ISOLATE_MASK 0x000000FF #define EXTENDED_DEV_INFO_SHARED_CFG_I2C_ISOLATE_SHIFT 0 #define EXTENDED_DEV_INFO_SHARED_CFG_MEZZ_FAULT_MASK 0x0000FF00 #define EXTENDED_DEV_INFO_SHARED_CFG_MEZZ_FAULT_SHIFT 8 #define EXTENDED_DEV_INFO_SHARED_CFG_MEZZ_VPD_UPDATE_MASK 0x00FF0000 #define EXTENDED_DEV_INFO_SHARED_CFG_MEZZ_VPD_UPDATE_SHIFT 16 #define EXTENDED_DEV_INFO_SHARED_CFG_VPD_CACHE_COMP_MASK 0xFF000000 #define EXTENDED_DEV_INFO_SHARED_CFG_VPD_CACHE_COMP_SHIFT 24 }; #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) #error "Missing either LITTLE_ENDIAN or BIG_ENDIAN definition." #endif #define FUNC_0 0 #define FUNC_1 1 #define FUNC_2 2 #define FUNC_3 3 #define FUNC_4 4 #define FUNC_5 5 #define FUNC_6 6 #define FUNC_7 7 #define E1H_FUNC_MAX 8 #define E2_FUNC_MAX 4 /* per path */ #define VN_0 0 #define VN_1 1 #define VN_2 2 #define VN_3 3 #define E1VN_MAX 1 #define E1HVN_MAX 4 #define E2_VF_MAX 64 /* HC_REG_VF_CONFIGURATION_SIZE */ /* This value (in milliseconds) determines the frequency of the driver * issuing the PULSE message code. The firmware monitors this periodic * pulse to determine when to switch to an OS-absent mode. */ #define DRV_PULSE_PERIOD_MS 250 /* This value (in milliseconds) determines how long the driver should * wait for an acknowledgement from the firmware before timing out. Once * the firmware has timed out, the driver will assume there is no firmware * running and there won't be any firmware-driver synchronization during a * driver reset. */ #define FW_ACK_TIME_OUT_MS 5000 #define FW_ACK_POLL_TIME_MS 1 #define FW_ACK_NUM_OF_POLL (FW_ACK_TIME_OUT_MS/FW_ACK_POLL_TIME_MS) #define MFW_TRACE_SIGNATURE 0x54524342 /**************************************************************************** * Driver <-> FW Mailbox * ****************************************************************************/ struct drv_port_mb { uint32_t link_status; /* Driver should update this field on any link change event */ #define LINK_STATUS_NONE (0<<0) #define LINK_STATUS_LINK_FLAG_MASK 0x00000001 #define LINK_STATUS_LINK_UP 0x00000001 #define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001E #define LINK_STATUS_SPEED_AND_DUPLEX_AN_NOT_COMPLETE (0<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_10THD (1<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_10TFD (2<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_100TXHD (3<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_100T4 (4<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_100TXFD (5<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_1000THD (6<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (7<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_1000XFD (7<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_2500THD (8<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_2500TFD (9<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_2500XFD (9<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_10GTFD (10<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_10GXFD (10<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_20GTFD (11<<1) #define LINK_STATUS_SPEED_AND_DUPLEX_20GXFD (11<<1) #define LINK_STATUS_AUTO_NEGOTIATE_FLAG_MASK 0x00000020 #define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020 #define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040 #define LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK 0x00000080 #define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080 #define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200 #define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400 #define LINK_STATUS_LINK_PARTNER_100T4_CAPABLE 0x00000800 #define LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE 0x00001000 #define LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE 0x00002000 #define LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE 0x00004000 #define LINK_STATUS_LINK_PARTNER_10THD_CAPABLE 0x00008000 #define LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK 0x00010000 #define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00010000 #define LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK 0x00020000 #define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00020000 #define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000 #define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0<<18) #define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE (1<<18) #define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2<<18) #define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3<<18) #define LINK_STATUS_SERDES_LINK 0x00100000 #define LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE 0x00200000 #define LINK_STATUS_LINK_PARTNER_2500XHD_CAPABLE 0x00400000 #define LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE 0x00800000 #define LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE 0x10000000 #define LINK_STATUS_PFC_ENABLED 0x20000000 #define LINK_STATUS_PHYSICAL_LINK_FLAG 0x40000000 #define LINK_STATUS_SFP_TX_FAULT 0x80000000 uint32_t port_stx; uint32_t stat_nig_timer; /* MCP firmware does not use this field */ uint32_t ext_phy_fw_version; }; struct drv_func_mb { uint32_t drv_mb_header; #define DRV_MSG_CODE_MASK 0xffff0000 #define DRV_MSG_CODE_LOAD_REQ 0x10000000 #define DRV_MSG_CODE_LOAD_DONE 0x11000000 #define DRV_MSG_CODE_UNLOAD_REQ_WOL_EN 0x20000000 #define DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS 0x20010000 #define DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP 0x20020000 #define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 #define DRV_MSG_CODE_DCC_OK 0x30000000 #define DRV_MSG_CODE_DCC_FAILURE 0x31000000 #define DRV_MSG_CODE_DIAG_ENTER_REQ 0x50000000 #define DRV_MSG_CODE_DIAG_EXIT_REQ 0x60000000 #define DRV_MSG_CODE_VALIDATE_KEY 0x70000000 #define DRV_MSG_CODE_GET_CURR_KEY 0x80000000 #define DRV_MSG_CODE_GET_UPGRADE_KEY 0x81000000 #define DRV_MSG_CODE_GET_MANUF_KEY 0x82000000 #define DRV_MSG_CODE_LOAD_L2B_PRAM 0x90000000 /* * The optic module verification command requires bootcode * v5.0.6 or later, te specific optic module verification command * requires bootcode v5.2.12 or later */ #define DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL 0xa0000000 #define REQ_BC_VER_4_VRFY_FIRST_PHY_OPT_MDL 0x00050006 #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000 #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234 #define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED 0xa2000000 #define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED 0x00070002 #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014 #define REQ_BC_VER_4_MT_SUPPORTED 0x00070201 #define REQ_BC_VER_4_PFC_STATS_SUPPORTED 0x00070201 #define REQ_BC_VER_4_FCOE_FEATURES 0x00070209 #define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000 #define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000 #define REQ_BC_VER_4_DCBX_ADMIN_MSG_NON_PMF 0x00070401 #define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000 #define DRV_MSG_CODE_AFEX_DRIVER_SETMAC 0xd0000000 #define DRV_MSG_CODE_AFEX_LISTGET_ACK 0xd1000000 #define DRV_MSG_CODE_AFEX_LISTSET_ACK 0xd2000000 #define DRV_MSG_CODE_AFEX_STATSGET_ACK 0xd3000000 #define DRV_MSG_CODE_AFEX_VIFSET_ACK 0xd4000000 #define DRV_MSG_CODE_DRV_INFO_ACK 0xd8000000 #define DRV_MSG_CODE_DRV_INFO_NACK 0xd9000000 #define DRV_MSG_CODE_EEE_RESULTS_ACK 0xda000000 #define DRV_MSG_CODE_RMMOD 0xdb000000 #define REQ_BC_VER_4_RMMOD_CMD 0x0007080f #define DRV_MSG_CODE_SET_MF_BW 0xe0000000 #define REQ_BC_VER_4_SET_MF_BW 0x00060202 #define DRV_MSG_CODE_SET_MF_BW_ACK 0xe1000000 #define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000 #define DRV_MSG_CODE_INITIATE_FLR 0x02000000 #define REQ_BC_VER_4_INITIATE_FLR 0x00070213 #define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000 #define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000 #define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000 #define BIOS_MSG_CODE_VIRT_MAC_ISCSI 0xff040000 #define DRV_MSG_CODE_IMG_OFFSET_REQ 0xe2000000 #define DRV_MSG_CODE_IMG_SIZE_REQ 0xe3000000 #define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff uint32_t drv_mb_param; #define DRV_MSG_CODE_SET_MF_BW_MIN_MASK 0x00ff0000 #define DRV_MSG_CODE_SET_MF_BW_MAX_MASK 0xff000000 #define DRV_MSG_CODE_UNLOAD_NON_D3_POWER 0x00000001 #define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET 0x00000002 #define DRV_MSG_CODE_LOAD_REQ_WITH_LFA 0x0000100a #define DRV_MSG_CODE_LOAD_REQ_FORCE_LFA 0x00002000 #define DRV_MSG_CODE_USR_BLK_IMAGE_REQ 0x00000001 uint32_t fw_mb_header; #define FW_MSG_CODE_MASK 0xffff0000 #define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000 #define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000 #define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000 /* Load common chip is supported from bc 6.0.0 */ #define REQ_BC_VER_4_DRV_LOAD_COMMON_CHIP 0x00060000 #define FW_MSG_CODE_DRV_LOAD_COMMON_CHIP 0x10130000 #define FW_MSG_CODE_DRV_LOAD_REFUSED 0x10200000 #define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000 #define FW_MSG_CODE_DRV_UNLOAD_COMMON 0x20100000 #define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20110000 #define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20120000 #define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 #define FW_MSG_CODE_DCC_DONE 0x30100000 #define FW_MSG_CODE_LLDP_DONE 0x40100000 #define FW_MSG_CODE_DIAG_ENTER_DONE 0x50100000 #define FW_MSG_CODE_DIAG_REFUSE 0x50200000 #define FW_MSG_CODE_DIAG_EXIT_DONE 0x60100000 #define FW_MSG_CODE_VALIDATE_KEY_SUCCESS 0x70100000 #define FW_MSG_CODE_VALIDATE_KEY_FAILURE 0x70200000 #define FW_MSG_CODE_GET_KEY_DONE 0x80100000 #define FW_MSG_CODE_NO_KEY 0x80f00000 #define FW_MSG_CODE_LIC_INFO_NOT_READY 0x80f80000 #define FW_MSG_CODE_L2B_PRAM_LOADED 0x90100000 #define FW_MSG_CODE_L2B_PRAM_T_LOAD_FAILURE 0x90210000 #define FW_MSG_CODE_L2B_PRAM_C_LOAD_FAILURE 0x90220000 #define FW_MSG_CODE_L2B_PRAM_X_LOAD_FAILURE 0x90230000 #define FW_MSG_CODE_L2B_PRAM_U_LOAD_FAILURE 0x90240000 #define FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS 0xa0100000 #define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000 #define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000 #define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000 #define FW_MSG_CODE_HW_SET_INVALID_IMAGE 0xb0100000 #define FW_MSG_CODE_AFEX_DRIVER_SETMAC_DONE 0xd0100000 #define FW_MSG_CODE_AFEX_LISTGET_ACK 0xd1100000 #define FW_MSG_CODE_AFEX_LISTSET_ACK 0xd2100000 #define FW_MSG_CODE_AFEX_STATSGET_ACK 0xd3100000 #define FW_MSG_CODE_AFEX_VIFSET_ACK 0xd4100000 #define FW_MSG_CODE_DRV_INFO_ACK 0xd8100000 #define FW_MSG_CODE_DRV_INFO_NACK 0xd9100000 #define FW_MSG_CODE_EEE_RESULS_ACK 0xda100000 #define FW_MSG_CODE_RMMOD_ACK 0xdb100000 #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000 #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000 #define FW_MSG_CODE_LINK_CHANGED_ACK 0x01100000 #define FW_MSG_CODE_FLR_ACK 0x02000000 #define FW_MSG_CODE_FLR_NACK 0x02100000 #define FW_MSG_CODE_LIC_CHALLENGE 0xff010000 #define FW_MSG_CODE_LIC_RESPONSE 0xff020000 #define FW_MSG_CODE_VIRT_MAC_PRIM 0xff030000 #define FW_MSG_CODE_VIRT_MAC_ISCSI 0xff040000 #define FW_MSG_CODE_IMG_OFFSET_RESPONSE 0xe2100000 #define FW_MSG_CODE_IMG_SIZE_RESPONSE 0xe3100000 #define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff uint32_t fw_mb_param; #define FW_PARAM_INVALID_IMG 0xffffffff uint32_t drv_pulse_mb; #define DRV_PULSE_SEQ_MASK 0x00007fff #define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000 /* * The system time is in the format of * (year-2001)*12*32 + month*32 + day. */ #define DRV_PULSE_ALWAYS_ALIVE 0x00008000 /* * Indicate to the firmware not to go into the * OS-absent when it is not getting driver pulse. * This is used for debugging as well for PXE(MBA). */ uint32_t mcp_pulse_mb; #define MCP_PULSE_SEQ_MASK 0x00007fff #define MCP_PULSE_ALWAYS_ALIVE 0x00008000 /* Indicates to the driver not to assert due to lack * of MCP response */ #define MCP_EVENT_MASK 0xffff0000 #define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000 uint32_t iscsi_boot_signature; uint32_t iscsi_boot_block_offset; uint32_t drv_status; #define DRV_STATUS_PMF 0x00000001 #define DRV_STATUS_VF_DISABLED 0x00000002 #define DRV_STATUS_SET_MF_BW 0x00000004 #define DRV_STATUS_LINK_EVENT 0x00000008 #define DRV_STATUS_DCC_EVENT_MASK 0x0000ff00 #define DRV_STATUS_DCC_DISABLE_ENABLE_PF 0x00000100 #define DRV_STATUS_DCC_BANDWIDTH_ALLOCATION 0x00000200 #define DRV_STATUS_DCC_CHANGE_MAC_ADDRESS 0x00000400 #define DRV_STATUS_DCC_RESERVED1 0x00000800 #define DRV_STATUS_DCC_SET_PROTOCOL 0x00001000 #define DRV_STATUS_DCC_SET_PRIORITY 0x00002000 #define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000 #define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000 #define DRV_STATUS_AFEX_EVENT_MASK 0x03f00000 #define DRV_STATUS_AFEX_LISTGET_REQ 0x00100000 #define DRV_STATUS_AFEX_LISTSET_REQ 0x00200000 #define DRV_STATUS_AFEX_STATSGET_REQ 0x00400000 #define DRV_STATUS_AFEX_VIFSET_REQ 0x00800000 #define DRV_STATUS_DRV_INFO_REQ 0x04000000 #define DRV_STATUS_EEE_NEGOTIATION_RESULTS 0x08000000 uint32_t virt_mac_upper; #define VIRT_MAC_SIGN_MASK 0xffff0000 #define VIRT_MAC_SIGNATURE 0x564d0000 uint32_t virt_mac_lower; }; /**************************************************************************** * Management firmware state * ****************************************************************************/ /* Allocate 440 bytes for management firmware */ #define MGMTFW_STATE_WORD_SIZE 110 struct mgmtfw_state { uint32_t opaque[MGMTFW_STATE_WORD_SIZE]; }; /**************************************************************************** * Multi-Function configuration * ****************************************************************************/ struct shared_mf_cfg { uint32_t clp_mb; #define SHARED_MF_CLP_SET_DEFAULT 0x00000000 /* set by CLP */ #define SHARED_MF_CLP_EXIT 0x00000001 /* set by MCP */ #define SHARED_MF_CLP_EXIT_DONE 0x00010000 }; struct port_mf_cfg { uint32_t dynamic_cfg; /* device control channel */ #define PORT_MF_CFG_E1HOV_TAG_MASK 0x0000ffff #define PORT_MF_CFG_E1HOV_TAG_SHIFT 0 #define PORT_MF_CFG_E1HOV_TAG_DEFAULT PORT_MF_CFG_E1HOV_TAG_MASK uint32_t reserved[1]; }; struct func_mf_cfg { uint32_t config; /* E/R/I/D */ /* function 0 of each port cannot be hidden */ #define FUNC_MF_CFG_FUNC_HIDE 0x00000001 #define FUNC_MF_CFG_PROTOCOL_MASK 0x00000006 #define FUNC_MF_CFG_PROTOCOL_FCOE 0x00000000 #define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000002 #define FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA 0x00000004 #define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000006 #define FUNC_MF_CFG_PROTOCOL_DEFAULT \ FUNC_MF_CFG_PROTOCOL_ETHERNET_WITH_RDMA #define FUNC_MF_CFG_FUNC_DISABLED 0x00000008 #define FUNC_MF_CFG_FUNC_DELETED 0x00000010 #define FUNC_MF_CFG_FUNC_BOOT_MASK 0x00000060 #define FUNC_MF_CFG_FUNC_BOOT_BIOS_CTRL 0x00000000 #define FUNC_MF_CFG_FUNC_BOOT_VCM_DISABLED 0x00000020 #define FUNC_MF_CFG_FUNC_BOOT_VCM_ENABLED 0x00000040 /* PRI */ /* 0 - low priority, 3 - high priority */ #define FUNC_MF_CFG_TRANSMIT_PRIORITY_MASK 0x00000300 #define FUNC_MF_CFG_TRANSMIT_PRIORITY_SHIFT 8 #define FUNC_MF_CFG_TRANSMIT_PRIORITY_DEFAULT 0x00000000 /* MINBW, MAXBW */ /* value range - 0..100, increments in 100Mbps */ #define FUNC_MF_CFG_MIN_BW_MASK 0x00ff0000 #define FUNC_MF_CFG_MIN_BW_SHIFT 16 #define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000 #define FUNC_MF_CFG_MAX_BW_MASK 0xff000000 #define FUNC_MF_CFG_MAX_BW_SHIFT 24 #define FUNC_MF_CFG_MAX_BW_DEFAULT 0x64000000 uint32_t mac_upper; /* MAC */ #define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff #define FUNC_MF_CFG_UPPERMAC_SHIFT 0 #define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK uint32_t mac_lower; #define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff uint32_t e1hov_tag; /* VNI */ #define FUNC_MF_CFG_E1HOV_TAG_MASK 0x0000ffff #define FUNC_MF_CFG_E1HOV_TAG_SHIFT 0 #define FUNC_MF_CFG_E1HOV_TAG_DEFAULT FUNC_MF_CFG_E1HOV_TAG_MASK /* afex default VLAN ID - 12 bits */ #define FUNC_MF_CFG_AFEX_VLAN_MASK 0x0fff0000 #define FUNC_MF_CFG_AFEX_VLAN_SHIFT 16 uint32_t afex_config; #define FUNC_MF_CFG_AFEX_COS_FILTER_MASK 0x000000ff #define FUNC_MF_CFG_AFEX_COS_FILTER_SHIFT 0 #define FUNC_MF_CFG_AFEX_MBA_ENABLED_MASK 0x0000ff00 #define FUNC_MF_CFG_AFEX_MBA_ENABLED_SHIFT 8 #define FUNC_MF_CFG_AFEX_MBA_ENABLED_VAL 0x00000100 #define FUNC_MF_CFG_AFEX_VLAN_MODE_MASK 0x000f0000 #define FUNC_MF_CFG_AFEX_VLAN_MODE_SHIFT 16 uint32_t pf_allocation; /* number of vfs in function, if 0 - sriov disabled */ #define FUNC_MF_CFG_NUMBER_OF_VFS_MASK 0x000000FF #define FUNC_MF_CFG_NUMBER_OF_VFS_SHIFT 0 }; enum mf_cfg_afex_vlan_mode { FUNC_MF_CFG_AFEX_VLAN_TRUNK_MODE = 0, FUNC_MF_CFG_AFEX_VLAN_ACCESS_MODE, FUNC_MF_CFG_AFEX_VLAN_TRUNK_TAG_NATIVE_MODE }; /* This structure is not applicable and should not be accessed on 57711 */ struct func_ext_cfg { uint32_t func_cfg; #define MACP_FUNC_CFG_FLAGS_MASK 0x0000007F #define MACP_FUNC_CFG_FLAGS_SHIFT 0 #define MACP_FUNC_CFG_FLAGS_ENABLED 0x00000001 #define MACP_FUNC_CFG_FLAGS_ETHERNET 0x00000002 #define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD 0x00000004 #define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD 0x00000008 #define MACP_FUNC_CFG_PAUSE_ON_HOST_RING 0x00000080 uint32_t iscsi_mac_addr_upper; uint32_t iscsi_mac_addr_lower; uint32_t fcoe_mac_addr_upper; uint32_t fcoe_mac_addr_lower; uint32_t fcoe_wwn_port_name_upper; uint32_t fcoe_wwn_port_name_lower; uint32_t fcoe_wwn_node_name_upper; uint32_t fcoe_wwn_node_name_lower; uint32_t preserve_data; #define MF_FUNC_CFG_PRESERVE_L2_MAC (1<<0) #define MF_FUNC_CFG_PRESERVE_ISCSI_MAC (1<<1) #define MF_FUNC_CFG_PRESERVE_FCOE_MAC (1<<2) #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_P (1<<3) #define MF_FUNC_CFG_PRESERVE_FCOE_WWN_N (1<<4) #define MF_FUNC_CFG_PRESERVE_TX_BW (1<<5) }; struct mf_cfg { struct shared_mf_cfg shared_mf_config; /* 0x4 */ struct port_mf_cfg port_mf_config[NVM_PATH_MAX][PORT_MAX]; /* 0x10*2=0x20 */ /* for all chips, there are 8 mf functions */ struct func_mf_cfg func_mf_config[E1H_FUNC_MAX]; /* 0x18 * 8 = 0xc0 */ /* * Extended configuration per function - this array does not exist and * should not be accessed on 57711 */ struct func_ext_cfg func_ext_config[E1H_FUNC_MAX]; /* 0x28 * 8 = 0x140*/ }; /* 0x224 */ /**************************************************************************** * Shared Memory Region * ****************************************************************************/ struct shmem_region { /* SharedMem Offset (size) */ uint32_t validity_map[PORT_MAX]; /* 0x0 (4*2 = 0x8) */ #define SHR_MEM_FORMAT_REV_MASK 0xff000000 #define SHR_MEM_FORMAT_REV_ID ('A'<<24) /* validity bits */ #define SHR_MEM_VALIDITY_PCI_CFG 0x00100000 #define SHR_MEM_VALIDITY_MB 0x00200000 #define SHR_MEM_VALIDITY_DEV_INFO 0x00400000 #define SHR_MEM_VALIDITY_RESERVED 0x00000007 /* One licensing bit should be set */ #define SHR_MEM_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038 #define SHR_MEM_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008 #define SHR_MEM_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010 #define SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020 /* Active MFW */ #define SHR_MEM_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000 #define SHR_MEM_VALIDITY_ACTIVE_MFW_MASK 0x000001c0 #define SHR_MEM_VALIDITY_ACTIVE_MFW_IPMI 0x00000040 #define SHR_MEM_VALIDITY_ACTIVE_MFW_UMP 0x00000080 #define SHR_MEM_VALIDITY_ACTIVE_MFW_NCSI 0x000000c0 #define SHR_MEM_VALIDITY_ACTIVE_MFW_NONE 0x000001c0 struct shm_dev_info dev_info; /* 0x8 (0x438) */ license_key_t drv_lic_key[PORT_MAX]; /* 0x440 (52*2=0x68) */ /* FW information (for internal FW use) */ uint32_t fw_info_fio_offset; /* 0x4a8 (0x4) */ struct mgmtfw_state mgmtfw_state; /* 0x4ac (0x1b8) */ struct drv_port_mb port_mb[PORT_MAX]; /* 0x664 (16*2=0x20) */ #ifdef BMAPI /* This is a variable length array */ /* the number of function depends on the chip type */ struct drv_func_mb func_mb[1]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */ #else /* the number of function depends on the chip type */ struct drv_func_mb func_mb[]; /* 0x684 (44*2/4/8=0x58/0xb0/0x160) */ #endif /* BMAPI */ }; /* 57711 = 0x7E4 | 57712 = 0x734 */ /**************************************************************************** * Shared Memory 2 Region * ****************************************************************************/ /* The fw_flr_ack is actually built in the following way: */ /* 8 bit: PF ack */ /* 64 bit: VF ack */ /* 8 bit: ios_dis_ack */ /* In order to maintain endianity in the mailbox hsi, we want to keep using */ /* uint32_t. The fw must have the VF right after the PF since this is how it */ /* access arrays(it expects always the VF to reside after the PF, and that */ /* makes the calculation much easier for it. ) */ /* In order to answer both limitations, and keep the struct small, the code */ /* will abuse the structure defined here to achieve the actual partition */ /* above */ /****************************************************************************/ struct fw_flr_ack { uint32_t pf_ack; uint32_t vf_ack[1]; uint32_t iov_dis_ack; }; struct fw_flr_mb { uint32_t aggint; uint32_t opgen_addr; struct fw_flr_ack ack; }; struct eee_remote_vals { uint32_t tx_tw; uint32_t rx_tw; }; /**** SUPPORT FOR SHMEM ARRRAYS *** * The SHMEM HSI is aligned on 32 bit boundaries which makes it difficult to * define arrays with storage types smaller then unsigned dwords. * The macros below add generic support for SHMEM arrays with numeric elements * that can span 2,4,8 or 16 bits. The array underlying type is a 32 bit dword * array with individual bit-filed elements accessed using shifts and masks. * */ /* eb is the bitwidth of a single element */ #define SHMEM_ARRAY_MASK(eb) ((1<<(eb))-1) #define SHMEM_ARRAY_ENTRY(i, eb) ((i)/(32/(eb))) /* the bit-position macro allows the used to flip the order of the arrays * elements on a per byte or word boundary. * * example: an array with 8 entries each 4 bit wide. This array will fit into * a single dword. The diagrmas below show the array order of the nibbles. * * SHMEM_ARRAY_BITPOS(i, 4, 4) defines the stadard ordering: * * | | | | * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * | | | | * * SHMEM_ARRAY_BITPOS(i, 4, 8) defines a flip ordering per byte: * * | | | | * 1 | 0 | 3 | 2 | 5 | 4 | 7 | 6 | * | | | | * * SHMEM_ARRAY_BITPOS(i, 4, 16) defines a flip ordering per word: * * | | | | * 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | * | | | | */ #define SHMEM_ARRAY_BITPOS(i, eb, fb) \ ((((32/(fb)) - 1 - ((i)/((fb)/(eb))) % (32/(fb))) * (fb)) + \ (((i)%((fb)/(eb))) * (eb))) #define SHMEM_ARRAY_GET(a, i, eb, fb) \ ((a[SHMEM_ARRAY_ENTRY(i, eb)] >> SHMEM_ARRAY_BITPOS(i, eb, fb)) & \ SHMEM_ARRAY_MASK(eb)) #define SHMEM_ARRAY_SET(a, i, eb, fb, val) \ do { \ a[SHMEM_ARRAY_ENTRY(i, eb)] &= ~(SHMEM_ARRAY_MASK(eb) << \ SHMEM_ARRAY_BITPOS(i, eb, fb)); \ a[SHMEM_ARRAY_ENTRY(i, eb)] |= (((val) & SHMEM_ARRAY_MASK(eb)) << \ SHMEM_ARRAY_BITPOS(i, eb, fb)); \ } while (0) /****START OF DCBX STRUCTURES DECLARATIONS****/ #define DCBX_MAX_NUM_PRI_PG_ENTRIES 8 #define DCBX_PRI_PG_BITWIDTH 4 #define DCBX_PRI_PG_FBITS 8 #define DCBX_PRI_PG_GET(a, i) \ SHMEM_ARRAY_GET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS) #define DCBX_PRI_PG_SET(a, i, val) \ SHMEM_ARRAY_SET(a, i, DCBX_PRI_PG_BITWIDTH, DCBX_PRI_PG_FBITS, val) #define DCBX_MAX_NUM_PG_BW_ENTRIES 8 #define DCBX_BW_PG_BITWIDTH 8 #define DCBX_PG_BW_GET(a, i) \ SHMEM_ARRAY_GET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH) #define DCBX_PG_BW_SET(a, i, val) \ SHMEM_ARRAY_SET(a, i, DCBX_BW_PG_BITWIDTH, DCBX_BW_PG_BITWIDTH, val) #define DCBX_STRICT_PRI_PG 15 #define DCBX_MAX_APP_PROTOCOL 16 #define DCBX_MAX_APP_LOCAL 32 #define FCOE_APP_IDX 0 #define ISCSI_APP_IDX 1 #define PREDEFINED_APP_IDX_MAX 2 /* Big/Little endian have the same representation. */ struct dcbx_ets_feature { /* * For Admin MIB - is this feature supported by the * driver | For Local MIB - should this feature be enabled. */ uint32_t enabled; uint32_t pg_bw_tbl[2]; uint32_t pri_pg_tbl[1]; }; /* Driver structure in LE */ struct dcbx_pfc_feature { #ifdef __BIG_ENDIAN uint8_t pri_en_bitmap; #define DCBX_PFC_PRI_0 0x01 #define DCBX_PFC_PRI_1 0x02 #define DCBX_PFC_PRI_2 0x04 #define DCBX_PFC_PRI_3 0x08 #define DCBX_PFC_PRI_4 0x10 #define DCBX_PFC_PRI_5 0x20 #define DCBX_PFC_PRI_6 0x40 #define DCBX_PFC_PRI_7 0x80 uint8_t pfc_caps; uint8_t reserved; uint8_t enabled; #elif defined(__LITTLE_ENDIAN) uint8_t enabled; uint8_t reserved; uint8_t pfc_caps; uint8_t pri_en_bitmap; #define DCBX_PFC_PRI_0 0x01 #define DCBX_PFC_PRI_1 0x02 #define DCBX_PFC_PRI_2 0x04 #define DCBX_PFC_PRI_3 0x08 #define DCBX_PFC_PRI_4 0x10 #define DCBX_PFC_PRI_5 0x20 #define DCBX_PFC_PRI_6 0x40 #define DCBX_PFC_PRI_7 0x80 #endif }; struct dcbx_app_priority_entry { #ifdef __BIG_ENDIAN uint16_t app_id; uint8_t pri_bitmap; uint8_t appBitfield; #define DCBX_APP_ENTRY_VALID 0x01 #define DCBX_APP_ENTRY_SF_MASK 0x30 #define DCBX_APP_ENTRY_SF_SHIFT 4 #define DCBX_APP_SF_ETH_TYPE 0x10 #define DCBX_APP_SF_PORT 0x20 #elif defined(__LITTLE_ENDIAN) uint8_t appBitfield; #define DCBX_APP_ENTRY_VALID 0x01 #define DCBX_APP_ENTRY_SF_MASK 0x30 #define DCBX_APP_ENTRY_SF_SHIFT 4 #define DCBX_APP_SF_ETH_TYPE 0x10 #define DCBX_APP_SF_PORT 0x20 uint8_t pri_bitmap; uint16_t app_id; #endif }; /* FW structure in BE */ struct dcbx_app_priority_feature { #ifdef __BIG_ENDIAN uint8_t reserved; uint8_t default_pri; uint8_t tc_supported; uint8_t enabled; #elif defined(__LITTLE_ENDIAN) uint8_t enabled; uint8_t tc_supported; uint8_t default_pri; uint8_t reserved; #endif struct dcbx_app_priority_entry app_pri_tbl[DCBX_MAX_APP_PROTOCOL]; }; /* FW structure in BE */ struct dcbx_features { /* PG feature */ struct dcbx_ets_feature ets; /* PFC feature */ struct dcbx_pfc_feature pfc; /* APP feature */ struct dcbx_app_priority_feature app; }; /* LLDP protocol parameters */ /* FW structure in BE */ struct lldp_params { #ifdef __BIG_ENDIAN uint8_t msg_fast_tx_interval; uint8_t msg_tx_hold; uint8_t msg_tx_interval; uint8_t admin_status; #define LLDP_TX_ONLY 0x01 #define LLDP_RX_ONLY 0x02 #define LLDP_TX_RX 0x03 #define LLDP_DISABLED 0x04 uint8_t reserved1; uint8_t tx_fast; uint8_t tx_crd_max; uint8_t tx_crd; #elif defined(__LITTLE_ENDIAN) uint8_t admin_status; #define LLDP_TX_ONLY 0x01 #define LLDP_RX_ONLY 0x02 #define LLDP_TX_RX 0x03 #define LLDP_DISABLED 0x04 uint8_t msg_tx_interval; uint8_t msg_tx_hold; uint8_t msg_fast_tx_interval; uint8_t tx_crd; uint8_t tx_crd_max; uint8_t tx_fast; uint8_t reserved1; #endif #define REM_CHASSIS_ID_STAT_LEN 4 #define REM_PORT_ID_STAT_LEN 4 /* Holds remote Chassis ID TLV header, subtype and 9B of payload. */ uint32_t peer_chassis_id[REM_CHASSIS_ID_STAT_LEN]; /* Holds remote Port ID TLV header, subtype and 9B of payload. */ uint32_t peer_port_id[REM_PORT_ID_STAT_LEN]; }; struct lldp_dcbx_stat { #define LOCAL_CHASSIS_ID_STAT_LEN 2 #define LOCAL_PORT_ID_STAT_LEN 2 /* Holds local Chassis ID 8B payload of constant subtype 4. */ uint32_t local_chassis_id[LOCAL_CHASSIS_ID_STAT_LEN]; /* Holds local Port ID 8B payload of constant subtype 3. */ uint32_t local_port_id[LOCAL_PORT_ID_STAT_LEN]; /* Number of DCBX frames transmitted. */ uint32_t num_tx_dcbx_pkts; /* Number of DCBX frames received. */ uint32_t num_rx_dcbx_pkts; }; /* ADMIN MIB - DCBX local machine default configuration. */ struct lldp_admin_mib { uint32_t ver_cfg_flags; #define DCBX_ETS_CONFIG_TX_ENABLED 0x00000001 #define DCBX_PFC_CONFIG_TX_ENABLED 0x00000002 #define DCBX_APP_CONFIG_TX_ENABLED 0x00000004 #define DCBX_ETS_RECO_TX_ENABLED 0x00000008 #define DCBX_ETS_RECO_VALID 0x00000010 #define DCBX_ETS_WILLING 0x00000020 #define DCBX_PFC_WILLING 0x00000040 #define DCBX_APP_WILLING 0x00000080 #define DCBX_VERSION_CEE 0x00000100 #define DCBX_VERSION_IEEE 0x00000200 #define DCBX_DCBX_ENABLED 0x00000400 #define DCBX_CEE_VERSION_MASK 0x0000f000 #define DCBX_CEE_VERSION_SHIFT 12 #define DCBX_CEE_MAX_VERSION_MASK 0x000f0000 #define DCBX_CEE_MAX_VERSION_SHIFT 16 struct dcbx_features features; }; /* REMOTE MIB - remote machine DCBX configuration. */ struct lldp_remote_mib { uint32_t prefix_seq_num; uint32_t flags; #define DCBX_ETS_TLV_RX 0x00000001 #define DCBX_PFC_TLV_RX 0x00000002 #define DCBX_APP_TLV_RX 0x00000004 #define DCBX_ETS_RX_ERROR 0x00000010 #define DCBX_PFC_RX_ERROR 0x00000020 #define DCBX_APP_RX_ERROR 0x00000040 #define DCBX_ETS_REM_WILLING 0x00000100 #define DCBX_PFC_REM_WILLING 0x00000200 #define DCBX_APP_REM_WILLING 0x00000400 #define DCBX_REMOTE_ETS_RECO_VALID 0x00001000 #define DCBX_REMOTE_MIB_VALID 0x00002000 struct dcbx_features features; uint32_t suffix_seq_num; }; /* LOCAL MIB - operational DCBX configuration - transmitted on Tx LLDPDU. */ struct lldp_local_mib { uint32_t prefix_seq_num; /* Indicates if there is mismatch with negotiation results. */ uint32_t error; #define DCBX_LOCAL_ETS_ERROR 0x00000001 #define DCBX_LOCAL_PFC_ERROR 0x00000002 #define DCBX_LOCAL_APP_ERROR 0x00000004 #define DCBX_LOCAL_PFC_MISMATCH 0x00000010 #define DCBX_LOCAL_APP_MISMATCH 0x00000020 #define DCBX_REMOTE_MIB_ERROR 0x00000040 #define DCBX_REMOTE_ETS_TLV_NOT_FOUND 0x00000080 #define DCBX_REMOTE_PFC_TLV_NOT_FOUND 0x00000100 #define DCBX_REMOTE_APP_TLV_NOT_FOUND 0x00000200 struct dcbx_features features; uint32_t suffix_seq_num; }; struct lldp_local_mib_ext { uint32_t prefix_seq_num; /* APP TLV extension - 16 more entries for negotiation results*/ struct dcbx_app_priority_entry app_pri_tbl_ext[DCBX_MAX_APP_PROTOCOL]; uint32_t suffix_seq_num; }; /***END OF DCBX STRUCTURES DECLARATIONS***/ /***********************************************************/ /* Elink section */ /***********************************************************/ #define SHMEM_LINK_CONFIG_SIZE 2 struct shmem_lfa { uint32_t req_duplex; #define REQ_DUPLEX_PHY0_MASK 0x0000ffff #define REQ_DUPLEX_PHY0_SHIFT 0 #define REQ_DUPLEX_PHY1_MASK 0xffff0000 #define REQ_DUPLEX_PHY1_SHIFT 16 uint32_t req_flow_ctrl; #define REQ_FLOW_CTRL_PHY0_MASK 0x0000ffff #define REQ_FLOW_CTRL_PHY0_SHIFT 0 #define REQ_FLOW_CTRL_PHY1_MASK 0xffff0000 #define REQ_FLOW_CTRL_PHY1_SHIFT 16 uint32_t req_line_speed; /* Also determine AutoNeg */ #define REQ_LINE_SPD_PHY0_MASK 0x0000ffff #define REQ_LINE_SPD_PHY0_SHIFT 0 #define REQ_LINE_SPD_PHY1_MASK 0xffff0000 #define REQ_LINE_SPD_PHY1_SHIFT 16 uint32_t speed_cap_mask[SHMEM_LINK_CONFIG_SIZE]; uint32_t additional_config; #define REQ_FC_AUTO_ADV_MASK 0x0000ffff #define REQ_FC_AUTO_ADV0_SHIFT 0 #define NO_LFA_DUE_TO_DCC_MASK 0x00010000 uint32_t lfa_sts; #define LFA_LINK_FLAP_REASON_OFFSET 0 #define LFA_LINK_FLAP_REASON_MASK 0x000000ff #define LFA_LINK_DOWN 0x1 #define LFA_LOOPBACK_ENABLED 0x2 #define LFA_DUPLEX_MISMATCH 0x3 #define LFA_MFW_IS_TOO_OLD 0x4 #define LFA_LINK_SPEED_MISMATCH 0x5 #define LFA_FLOW_CTRL_MISMATCH 0x6 #define LFA_SPEED_CAP_MISMATCH 0x7 #define LFA_DCC_LFA_DISABLED 0x8 #define LFA_EEE_MISMATCH 0x9 #define LINK_FLAP_AVOIDANCE_COUNT_OFFSET 8 #define LINK_FLAP_AVOIDANCE_COUNT_MASK 0x0000ff00 #define LINK_FLAP_COUNT_OFFSET 16 #define LINK_FLAP_COUNT_MASK 0x00ff0000 #define LFA_FLAGS_MASK 0xff000000 #define SHMEM_LFA_DONT_CLEAR_STAT (1<<24) }; struct shmem2_region { uint32_t size; /* 0x0000 */ uint32_t dcc_support; /* 0x0004 */ #define SHMEM_DCC_SUPPORT_NONE 0x00000000 #define SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV 0x00000001 #define SHMEM_DCC_SUPPORT_BANDWIDTH_ALLOCATION_TLV 0x00000004 #define SHMEM_DCC_SUPPORT_CHANGE_MAC_ADDRESS_TLV 0x00000008 #define SHMEM_DCC_SUPPORT_SET_PROTOCOL_TLV 0x00000040 #define SHMEM_DCC_SUPPORT_SET_PRIORITY_TLV 0x00000080 uint32_t ext_phy_fw_version2[PORT_MAX]; /* 0x0008 */ /* * For backwards compatibility, if the mf_cfg_addr does not exist * (the size filed is smaller than 0xc) the mf_cfg resides at the * end of struct shmem_region */ uint32_t mf_cfg_addr; /* 0x0010 */ #define SHMEM_MF_CFG_ADDR_NONE 0x00000000 struct fw_flr_mb flr_mb; /* 0x0014 */ uint32_t dcbx_lldp_params_offset; /* 0x0028 */ #define SHMEM_LLDP_DCBX_PARAMS_NONE 0x00000000 uint32_t dcbx_neg_res_offset; /* 0x002c */ #define SHMEM_DCBX_NEG_RES_NONE 0x00000000 uint32_t dcbx_remote_mib_offset; /* 0x0030 */ #define SHMEM_DCBX_REMOTE_MIB_NONE 0x00000000 /* * The other shmemX_base_addr holds the other path's shmem address * required for example in case of common phy init, or for path1 to know * the address of mcp debug trace which is located in offset from shmem * of path0 */ uint32_t other_shmem_base_addr; /* 0x0034 */ uint32_t other_shmem2_base_addr; /* 0x0038 */ /* * mcp_vf_disabled is set by the MCP to indicate the driver about VFs * which were disabled/flred */ uint32_t mcp_vf_disabled[E2_VF_MAX / 32]; /* 0x003c */ /* * drv_ack_vf_disabled is set by the PF driver to ack handled disabled * VFs */ uint32_t drv_ack_vf_disabled[E2_FUNC_MAX][E2_VF_MAX / 32]; /* 0x0044 */ uint32_t dcbx_lldp_dcbx_stat_offset; /* 0x0064 */ #define SHMEM_LLDP_DCBX_STAT_NONE 0x00000000 /* * edebug_driver_if field is used to transfer messages between edebug * app to the driver through shmem2. * * message format: * bits 0-2 - function number / instance of driver to perform request * bits 3-5 - op code / is_ack? * bits 6-63 - data */ uint32_t edebug_driver_if[2]; /* 0x0068 */ #define EDEBUG_DRIVER_IF_OP_CODE_GET_PHYS_ADDR 1 #define EDEBUG_DRIVER_IF_OP_CODE_GET_BUS_ADDR 2 #define EDEBUG_DRIVER_IF_OP_CODE_DISABLE_STAT 3 uint32_t nvm_retain_bitmap_addr; /* 0x0070 */ /* afex support of that driver */ uint32_t afex_driver_support; /* 0x0074 */ #define SHMEM_AFEX_VERSION_MASK 0x100f #define SHMEM_AFEX_SUPPORTED_VERSION_ONE 0x1001 #define SHMEM_AFEX_REDUCED_DRV_LOADED 0x8000 /* driver receives addr in scratchpad to which it should respond */ uint32_t afex_scratchpad_addr_to_write[E2_FUNC_MAX]; /* * generic params from MCP to driver (value depends on the msg sent * to driver */ uint32_t afex_param1_to_driver[E2_FUNC_MAX]; /* 0x0088 */ uint32_t afex_param2_to_driver[E2_FUNC_MAX]; /* 0x0098 */ uint32_t swim_base_addr; /* 0x0108 */ uint32_t swim_funcs; uint32_t swim_main_cb; /* * bitmap notifying which VIF profiles stored in nvram are enabled by * switch */ uint32_t afex_profiles_enabled[2]; /* generic flags controlled by the driver */ uint32_t drv_flags; #define DRV_FLAGS_DCB_CONFIGURED 0x0 #define DRV_FLAGS_DCB_CONFIGURATION_ABORTED 0x1 #define DRV_FLAGS_DCB_MFW_CONFIGURED 0x2 #define DRV_FLAGS_PORT_MASK ((1 << DRV_FLAGS_DCB_CONFIGURED) | \ (1 << DRV_FLAGS_DCB_CONFIGURATION_ABORTED) | \ (1 << DRV_FLAGS_DCB_MFW_CONFIGURED)) /* Port offset*/ #define DRV_FLAGS_P0_OFFSET 0 #define DRV_FLAGS_P1_OFFSET 16 #define DRV_FLAGS_GET_PORT_OFFSET(_port) ((0 == _port) ? \ DRV_FLAGS_P0_OFFSET : \ DRV_FLAGS_P1_OFFSET) #define DRV_FLAGS_GET_PORT_MASK(_port) (DRV_FLAGS_PORT_MASK << \ DRV_FLAGS_GET_PORT_OFFSET(_port)) #define DRV_FLAGS_FILED_BY_PORT(_field_bit, _port) (1 << ( \ (_field_bit) + DRV_FLAGS_GET_PORT_OFFSET(_port))) /* pointer to extended dev_info shared data copied from nvm image */ uint32_t extended_dev_info_shared_addr; uint32_t ncsi_oem_data_addr; uint32_t sensor_data_addr; uint32_t buffer_block_addr; uint32_t sensor_data_req_update_interval; uint32_t temperature_in_half_celsius; uint32_t glob_struct_in_host; uint32_t dcbx_neg_res_ext_offset; #define SHMEM_DCBX_NEG_RES_EXT_NONE 0x00000000 uint32_t drv_capabilities_flag[E2_FUNC_MAX]; #define DRV_FLAGS_CAPABILITIES_LOADED_SUPPORTED 0x00000001 #define DRV_FLAGS_CAPABILITIES_LOADED_L2 0x00000002 #define DRV_FLAGS_CAPABILITIES_LOADED_FCOE 0x00000004 #define DRV_FLAGS_CAPABILITIES_LOADED_ISCSI 0x00000008 uint32_t extended_dev_info_shared_cfg_size; uint32_t dcbx_en[PORT_MAX]; /* The offset points to the multi threaded meta structure */ uint32_t multi_thread_data_offset; /* address of DMAable host address holding values from the drivers */ uint32_t drv_info_host_addr_lo; uint32_t drv_info_host_addr_hi; /* general values written by the MFW (such as current version) */ uint32_t drv_info_control; #define DRV_INFO_CONTROL_VER_MASK 0x000000ff #define DRV_INFO_CONTROL_VER_SHIFT 0 #define DRV_INFO_CONTROL_OP_CODE_MASK 0x0000ff00 #define DRV_INFO_CONTROL_OP_CODE_SHIFT 8 uint32_t ibft_host_addr; /* initialized by option ROM */ struct eee_remote_vals eee_remote_vals[PORT_MAX]; uint32_t pf_allocation[E2_FUNC_MAX]; #define PF_ALLOACTION_MSIX_VECTORS_MASK 0x000000ff /* real value, as PCI config space can show only maximum of 64 vectors */ #define PF_ALLOACTION_MSIX_VECTORS_SHIFT 0 /* the status of EEE auto-negotiation * bits 15:0 the configured tx-lpi entry timer value. Depends on bit 31. * bits 19:16 the supported modes for EEE. * bits 23:20 the speeds advertised for EEE. * bits 27:24 the speeds the Link partner advertised for EEE. * The supported/adv. modes in bits 27:19 originate from the * SHMEM_EEE_XXX_ADV definitions (where XXX is replaced by speed). * bit 28 when 1'b1 EEE was requested. * bit 29 when 1'b1 tx lpi was requested. * bit 30 when 1'b1 EEE was negotiated. Tx lpi will be asserted iff * 30:29 are 2'b11. * bit 31 when 1'b0 bits 15:0 contain a PORT_FEAT_CFG_EEE_ define as * value. When 1'b1 those bits contains a value times 16 microseconds. */ uint32_t eee_status[PORT_MAX]; #define SHMEM_EEE_TIMER_MASK 0x0000ffff #define SHMEM_EEE_SUPPORTED_MASK 0x000f0000 #define SHMEM_EEE_SUPPORTED_SHIFT 16 #define SHMEM_EEE_ADV_STATUS_MASK 0x00f00000 #define SHMEM_EEE_100M_ADV (1<<0) #define SHMEM_EEE_1G_ADV (1<<1) #define SHMEM_EEE_10G_ADV (1<<2) #define SHMEM_EEE_ADV_STATUS_SHIFT 20 #define SHMEM_EEE_LP_ADV_STATUS_MASK 0x0f000000 #define SHMEM_EEE_LP_ADV_STATUS_SHIFT 24 #define SHMEM_EEE_REQUESTED_BIT 0x10000000 #define SHMEM_EEE_LPI_REQUESTED_BIT 0x20000000 #define SHMEM_EEE_ACTIVE_BIT 0x40000000 #define SHMEM_EEE_TIME_OUTPUT_BIT 0x80000000 uint32_t sizeof_port_stats; /* Link Flap Avoidance */ uint32_t lfa_host_addr[PORT_MAX]; /* External PHY temperature in deg C. */ uint32_t extphy_temps_in_celsius; #define EXTPHY1_TEMP_MASK 0x0000ffff #define EXTPHY1_TEMP_SHIFT 0 uint32_t ocdata_info_addr; /* Offset 0x148 */ uint32_t drv_func_info_addr; /* Offset 0x14C */ uint32_t drv_func_info_size; /* Offset 0x150 */ uint32_t link_attr_sync[PORT_MAX]; /* Offset 0x154 */ #define LINK_ATTR_SYNC_KR2_ENABLE (1<<0) }; struct emac_stats { uint32_t rx_stat_ifhcinoctets; uint32_t rx_stat_ifhcinbadoctets; uint32_t rx_stat_etherstatsfragments; uint32_t rx_stat_ifhcinucastpkts; uint32_t rx_stat_ifhcinmulticastpkts; uint32_t rx_stat_ifhcinbroadcastpkts; uint32_t rx_stat_dot3statsfcserrors; uint32_t rx_stat_dot3statsalignmenterrors; uint32_t rx_stat_dot3statscarriersenseerrors; uint32_t rx_stat_xonpauseframesreceived; uint32_t rx_stat_xoffpauseframesreceived; uint32_t rx_stat_maccontrolframesreceived; uint32_t rx_stat_xoffstateentered; uint32_t rx_stat_dot3statsframestoolong; uint32_t rx_stat_etherstatsjabbers; uint32_t rx_stat_etherstatsundersizepkts; uint32_t rx_stat_etherstatspkts64octets; uint32_t rx_stat_etherstatspkts65octetsto127octets; uint32_t rx_stat_etherstatspkts128octetsto255octets; uint32_t rx_stat_etherstatspkts256octetsto511octets; uint32_t rx_stat_etherstatspkts512octetsto1023octets; uint32_t rx_stat_etherstatspkts1024octetsto1522octets; uint32_t rx_stat_etherstatspktsover1522octets; uint32_t rx_stat_falsecarriererrors; uint32_t tx_stat_ifhcoutoctets; uint32_t tx_stat_ifhcoutbadoctets; uint32_t tx_stat_etherstatscollisions; uint32_t tx_stat_outxonsent; uint32_t tx_stat_outxoffsent; uint32_t tx_stat_flowcontroldone; uint32_t tx_stat_dot3statssinglecollisionframes; uint32_t tx_stat_dot3statsmultiplecollisionframes; uint32_t tx_stat_dot3statsdeferredtransmissions; uint32_t tx_stat_dot3statsexcessivecollisions; uint32_t tx_stat_dot3statslatecollisions; uint32_t tx_stat_ifhcoutucastpkts; uint32_t tx_stat_ifhcoutmulticastpkts; uint32_t tx_stat_ifhcoutbroadcastpkts; uint32_t tx_stat_etherstatspkts64octets; uint32_t tx_stat_etherstatspkts65octetsto127octets; uint32_t tx_stat_etherstatspkts128octetsto255octets; uint32_t tx_stat_etherstatspkts256octetsto511octets; uint32_t tx_stat_etherstatspkts512octetsto1023octets; uint32_t tx_stat_etherstatspkts1024octetsto1522octets; uint32_t tx_stat_etherstatspktsover1522octets; uint32_t tx_stat_dot3statsinternalmactransmiterrors; }; struct bmac1_stats { uint32_t tx_stat_gtpkt_lo; uint32_t tx_stat_gtpkt_hi; uint32_t tx_stat_gtxpf_lo; uint32_t tx_stat_gtxpf_hi; uint32_t tx_stat_gtfcs_lo; uint32_t tx_stat_gtfcs_hi; uint32_t tx_stat_gtmca_lo; uint32_t tx_stat_gtmca_hi; uint32_t tx_stat_gtbca_lo; uint32_t tx_stat_gtbca_hi; uint32_t tx_stat_gtfrg_lo; uint32_t tx_stat_gtfrg_hi; uint32_t tx_stat_gtovr_lo; uint32_t tx_stat_gtovr_hi; uint32_t tx_stat_gt64_lo; uint32_t tx_stat_gt64_hi; uint32_t tx_stat_gt127_lo; uint32_t tx_stat_gt127_hi; uint32_t tx_stat_gt255_lo; uint32_t tx_stat_gt255_hi; uint32_t tx_stat_gt511_lo; uint32_t tx_stat_gt511_hi; uint32_t tx_stat_gt1023_lo; uint32_t tx_stat_gt1023_hi; uint32_t tx_stat_gt1518_lo; uint32_t tx_stat_gt1518_hi; uint32_t tx_stat_gt2047_lo; uint32_t tx_stat_gt2047_hi; uint32_t tx_stat_gt4095_lo; uint32_t tx_stat_gt4095_hi; uint32_t tx_stat_gt9216_lo; uint32_t tx_stat_gt9216_hi; uint32_t tx_stat_gt16383_lo; uint32_t tx_stat_gt16383_hi; uint32_t tx_stat_gtmax_lo; uint32_t tx_stat_gtmax_hi; uint32_t tx_stat_gtufl_lo; uint32_t tx_stat_gtufl_hi; uint32_t tx_stat_gterr_lo; uint32_t tx_stat_gterr_hi; uint32_t tx_stat_gtbyt_lo; uint32_t tx_stat_gtbyt_hi; uint32_t rx_stat_gr64_lo; uint32_t rx_stat_gr64_hi; uint32_t rx_stat_gr127_lo; uint32_t rx_stat_gr127_hi; uint32_t rx_stat_gr255_lo; uint32_t rx_stat_gr255_hi; uint32_t rx_stat_gr511_lo; uint32_t rx_stat_gr511_hi; uint32_t rx_stat_gr1023_lo; uint32_t rx_stat_gr1023_hi; uint32_t rx_stat_gr1518_lo; uint32_t rx_stat_gr1518_hi; uint32_t rx_stat_gr2047_lo; uint32_t rx_stat_gr2047_hi; uint32_t rx_stat_gr4095_lo; uint32_t rx_stat_gr4095_hi; uint32_t rx_stat_gr9216_lo; uint32_t rx_stat_gr9216_hi; uint32_t rx_stat_gr16383_lo; uint32_t rx_stat_gr16383_hi; uint32_t rx_stat_grmax_lo; uint32_t rx_stat_grmax_hi; uint32_t rx_stat_grpkt_lo; uint32_t rx_stat_grpkt_hi; uint32_t rx_stat_grfcs_lo; uint32_t rx_stat_grfcs_hi; uint32_t rx_stat_grmca_lo; uint32_t rx_stat_grmca_hi; uint32_t rx_stat_grbca_lo; uint32_t rx_stat_grbca_hi; uint32_t rx_stat_grxcf_lo; uint32_t rx_stat_grxcf_hi; uint32_t rx_stat_grxpf_lo; uint32_t rx_stat_grxpf_hi; uint32_t rx_stat_grxuo_lo; uint32_t rx_stat_grxuo_hi; uint32_t rx_stat_grjbr_lo; uint32_t rx_stat_grjbr_hi; uint32_t rx_stat_grovr_lo; uint32_t rx_stat_grovr_hi; uint32_t rx_stat_grflr_lo; uint32_t rx_stat_grflr_hi; uint32_t rx_stat_grmeg_lo; uint32_t rx_stat_grmeg_hi; uint32_t rx_stat_grmeb_lo; uint32_t rx_stat_grmeb_hi; uint32_t rx_stat_grbyt_lo; uint32_t rx_stat_grbyt_hi; uint32_t rx_stat_grund_lo; uint32_t rx_stat_grund_hi; uint32_t rx_stat_grfrg_lo; uint32_t rx_stat_grfrg_hi; uint32_t rx_stat_grerb_lo; uint32_t rx_stat_grerb_hi; uint32_t rx_stat_grfre_lo; uint32_t rx_stat_grfre_hi; uint32_t rx_stat_gripj_lo; uint32_t rx_stat_gripj_hi; }; struct bmac2_stats { uint32_t tx_stat_gtpk_lo; /* gtpok */ uint32_t tx_stat_gtpk_hi; /* gtpok */ uint32_t tx_stat_gtxpf_lo; /* gtpf */ uint32_t tx_stat_gtxpf_hi; /* gtpf */ uint32_t tx_stat_gtpp_lo; /* NEW BMAC2 */ uint32_t tx_stat_gtpp_hi; /* NEW BMAC2 */ uint32_t tx_stat_gtfcs_lo; uint32_t tx_stat_gtfcs_hi; uint32_t tx_stat_gtuca_lo; /* NEW BMAC2 */ uint32_t tx_stat_gtuca_hi; /* NEW BMAC2 */ uint32_t tx_stat_gtmca_lo; uint32_t tx_stat_gtmca_hi; uint32_t tx_stat_gtbca_lo; uint32_t tx_stat_gtbca_hi; uint32_t tx_stat_gtovr_lo; uint32_t tx_stat_gtovr_hi; uint32_t tx_stat_gtfrg_lo; uint32_t tx_stat_gtfrg_hi; uint32_t tx_stat_gtpkt1_lo; /* gtpkt */ uint32_t tx_stat_gtpkt1_hi; /* gtpkt */ uint32_t tx_stat_gt64_lo; uint32_t tx_stat_gt64_hi; uint32_t tx_stat_gt127_lo; uint32_t tx_stat_gt127_hi; uint32_t tx_stat_gt255_lo; uint32_t tx_stat_gt255_hi; uint32_t tx_stat_gt511_lo; uint32_t tx_stat_gt511_hi; uint32_t tx_stat_gt1023_lo; uint32_t tx_stat_gt1023_hi; uint32_t tx_stat_gt1518_lo; uint32_t tx_stat_gt1518_hi; uint32_t tx_stat_gt2047_lo; uint32_t tx_stat_gt2047_hi; uint32_t tx_stat_gt4095_lo; uint32_t tx_stat_gt4095_hi; uint32_t tx_stat_gt9216_lo; uint32_t tx_stat_gt9216_hi; uint32_t tx_stat_gt16383_lo; uint32_t tx_stat_gt16383_hi; uint32_t tx_stat_gtmax_lo; uint32_t tx_stat_gtmax_hi; uint32_t tx_stat_gtufl_lo; uint32_t tx_stat_gtufl_hi; uint32_t tx_stat_gterr_lo; uint32_t tx_stat_gterr_hi; uint32_t tx_stat_gtbyt_lo; uint32_t tx_stat_gtbyt_hi; uint32_t rx_stat_gr64_lo; uint32_t rx_stat_gr64_hi; uint32_t rx_stat_gr127_lo; uint32_t rx_stat_gr127_hi; uint32_t rx_stat_gr255_lo; uint32_t rx_stat_gr255_hi; uint32_t rx_stat_gr511_lo; uint32_t rx_stat_gr511_hi; uint32_t rx_stat_gr1023_lo; uint32_t rx_stat_gr1023_hi; uint32_t rx_stat_gr1518_lo; uint32_t rx_stat_gr1518_hi; uint32_t rx_stat_gr2047_lo; uint32_t rx_stat_gr2047_hi; uint32_t rx_stat_gr4095_lo; uint32_t rx_stat_gr4095_hi; uint32_t rx_stat_gr9216_lo; uint32_t rx_stat_gr9216_hi; uint32_t rx_stat_gr16383_lo; uint32_t rx_stat_gr16383_hi; uint32_t rx_stat_grmax_lo; uint32_t rx_stat_grmax_hi; uint32_t rx_stat_grpkt_lo; uint32_t rx_stat_grpkt_hi; uint32_t rx_stat_grfcs_lo; uint32_t rx_stat_grfcs_hi; uint32_t rx_stat_gruca_lo; uint32_t rx_stat_gruca_hi; uint32_t rx_stat_grmca_lo; uint32_t rx_stat_grmca_hi; uint32_t rx_stat_grbca_lo; uint32_t rx_stat_grbca_hi; uint32_t rx_stat_grxpf_lo; /* grpf */ uint32_t rx_stat_grxpf_hi; /* grpf */ uint32_t rx_stat_grpp_lo; uint32_t rx_stat_grpp_hi; uint32_t rx_stat_grxuo_lo; /* gruo */ uint32_t rx_stat_grxuo_hi; /* gruo */ uint32_t rx_stat_grjbr_lo; uint32_t rx_stat_grjbr_hi; uint32_t rx_stat_grovr_lo; uint32_t rx_stat_grovr_hi; uint32_t rx_stat_grxcf_lo; /* grcf */ uint32_t rx_stat_grxcf_hi; /* grcf */ uint32_t rx_stat_grflr_lo; uint32_t rx_stat_grflr_hi; uint32_t rx_stat_grpok_lo; uint32_t rx_stat_grpok_hi; uint32_t rx_stat_grmeg_lo; uint32_t rx_stat_grmeg_hi; uint32_t rx_stat_grmeb_lo; uint32_t rx_stat_grmeb_hi; uint32_t rx_stat_grbyt_lo; uint32_t rx_stat_grbyt_hi; uint32_t rx_stat_grund_lo; uint32_t rx_stat_grund_hi; uint32_t rx_stat_grfrg_lo; uint32_t rx_stat_grfrg_hi; uint32_t rx_stat_grerb_lo; /* grerrbyt */ uint32_t rx_stat_grerb_hi; /* grerrbyt */ uint32_t rx_stat_grfre_lo; /* grfrerr */ uint32_t rx_stat_grfre_hi; /* grfrerr */ uint32_t rx_stat_gripj_lo; uint32_t rx_stat_gripj_hi; }; struct mstat_stats { struct { /* OTE MSTAT on E3 has a bug where this register's contents are * actually tx_gtxpok + tx_gtxpf + (possibly)tx_gtxpp */ uint32_t tx_gtxpok_lo; uint32_t tx_gtxpok_hi; uint32_t tx_gtxpf_lo; uint32_t tx_gtxpf_hi; uint32_t tx_gtxpp_lo; uint32_t tx_gtxpp_hi; uint32_t tx_gtfcs_lo; uint32_t tx_gtfcs_hi; uint32_t tx_gtuca_lo; uint32_t tx_gtuca_hi; uint32_t tx_gtmca_lo; uint32_t tx_gtmca_hi; uint32_t tx_gtgca_lo; uint32_t tx_gtgca_hi; uint32_t tx_gtpkt_lo; uint32_t tx_gtpkt_hi; uint32_t tx_gt64_lo; uint32_t tx_gt64_hi; uint32_t tx_gt127_lo; uint32_t tx_gt127_hi; uint32_t tx_gt255_lo; uint32_t tx_gt255_hi; uint32_t tx_gt511_lo; uint32_t tx_gt511_hi; uint32_t tx_gt1023_lo; uint32_t tx_gt1023_hi; uint32_t tx_gt1518_lo; uint32_t tx_gt1518_hi; uint32_t tx_gt2047_lo; uint32_t tx_gt2047_hi; uint32_t tx_gt4095_lo; uint32_t tx_gt4095_hi; uint32_t tx_gt9216_lo; uint32_t tx_gt9216_hi; uint32_t tx_gt16383_lo; uint32_t tx_gt16383_hi; uint32_t tx_gtufl_lo; uint32_t tx_gtufl_hi; uint32_t tx_gterr_lo; uint32_t tx_gterr_hi; uint32_t tx_gtbyt_lo; uint32_t tx_gtbyt_hi; uint32_t tx_collisions_lo; uint32_t tx_collisions_hi; uint32_t tx_singlecollision_lo; uint32_t tx_singlecollision_hi; uint32_t tx_multiplecollisions_lo; uint32_t tx_multiplecollisions_hi; uint32_t tx_deferred_lo; uint32_t tx_deferred_hi; uint32_t tx_excessivecollisions_lo; uint32_t tx_excessivecollisions_hi; uint32_t tx_latecollisions_lo; uint32_t tx_latecollisions_hi; } stats_tx; struct { uint32_t rx_gr64_lo; uint32_t rx_gr64_hi; uint32_t rx_gr127_lo; uint32_t rx_gr127_hi; uint32_t rx_gr255_lo; uint32_t rx_gr255_hi; uint32_t rx_gr511_lo; uint32_t rx_gr511_hi; uint32_t rx_gr1023_lo; uint32_t rx_gr1023_hi; uint32_t rx_gr1518_lo; uint32_t rx_gr1518_hi; uint32_t rx_gr2047_lo; uint32_t rx_gr2047_hi; uint32_t rx_gr4095_lo; uint32_t rx_gr4095_hi; uint32_t rx_gr9216_lo; uint32_t rx_gr9216_hi; uint32_t rx_gr16383_lo; uint32_t rx_gr16383_hi; uint32_t rx_grpkt_lo; uint32_t rx_grpkt_hi; uint32_t rx_grfcs_lo; uint32_t rx_grfcs_hi; uint32_t rx_gruca_lo; uint32_t rx_gruca_hi; uint32_t rx_grmca_lo; uint32_t rx_grmca_hi; uint32_t rx_grbca_lo; uint32_t rx_grbca_hi; uint32_t rx_grxpf_lo; uint32_t rx_grxpf_hi; uint32_t rx_grxpp_lo; uint32_t rx_grxpp_hi; uint32_t rx_grxuo_lo; uint32_t rx_grxuo_hi; uint32_t rx_grovr_lo; uint32_t rx_grovr_hi; uint32_t rx_grxcf_lo; uint32_t rx_grxcf_hi; uint32_t rx_grflr_lo; uint32_t rx_grflr_hi; uint32_t rx_grpok_lo; uint32_t rx_grpok_hi; uint32_t rx_grbyt_lo; uint32_t rx_grbyt_hi; uint32_t rx_grund_lo; uint32_t rx_grund_hi; uint32_t rx_grfrg_lo; uint32_t rx_grfrg_hi; uint32_t rx_grerb_lo; uint32_t rx_grerb_hi; uint32_t rx_grfre_lo; uint32_t rx_grfre_hi; uint32_t rx_alignmenterrors_lo; uint32_t rx_alignmenterrors_hi; uint32_t rx_falsecarrier_lo; uint32_t rx_falsecarrier_hi; uint32_t rx_llfcmsgcnt_lo; uint32_t rx_llfcmsgcnt_hi; } stats_rx; }; union mac_stats { struct emac_stats emac_stats; struct bmac1_stats bmac1_stats; struct bmac2_stats bmac2_stats; struct mstat_stats mstat_stats; }; struct mac_stx { /* in_bad_octets */ uint32_t rx_stat_ifhcinbadoctets_hi; uint32_t rx_stat_ifhcinbadoctets_lo; /* out_bad_octets */ uint32_t tx_stat_ifhcoutbadoctets_hi; uint32_t tx_stat_ifhcoutbadoctets_lo; /* crc_receive_errors */ uint32_t rx_stat_dot3statsfcserrors_hi; uint32_t rx_stat_dot3statsfcserrors_lo; /* alignment_errors */ uint32_t rx_stat_dot3statsalignmenterrors_hi; uint32_t rx_stat_dot3statsalignmenterrors_lo; /* carrier_sense_errors */ uint32_t rx_stat_dot3statscarriersenseerrors_hi; uint32_t rx_stat_dot3statscarriersenseerrors_lo; /* false_carrier_detections */ uint32_t rx_stat_falsecarriererrors_hi; uint32_t rx_stat_falsecarriererrors_lo; /* runt_packets_received */ uint32_t rx_stat_etherstatsundersizepkts_hi; uint32_t rx_stat_etherstatsundersizepkts_lo; /* jabber_packets_received */ uint32_t rx_stat_dot3statsframestoolong_hi; uint32_t rx_stat_dot3statsframestoolong_lo; /* error_runt_packets_received */ uint32_t rx_stat_etherstatsfragments_hi; uint32_t rx_stat_etherstatsfragments_lo; /* error_jabber_packets_received */ uint32_t rx_stat_etherstatsjabbers_hi; uint32_t rx_stat_etherstatsjabbers_lo; /* control_frames_received */ uint32_t rx_stat_maccontrolframesreceived_hi; uint32_t rx_stat_maccontrolframesreceived_lo; uint32_t rx_stat_mac_xpf_hi; uint32_t rx_stat_mac_xpf_lo; uint32_t rx_stat_mac_xcf_hi; uint32_t rx_stat_mac_xcf_lo; /* xoff_state_entered */ uint32_t rx_stat_xoffstateentered_hi; uint32_t rx_stat_xoffstateentered_lo; /* pause_xon_frames_received */ uint32_t rx_stat_xonpauseframesreceived_hi; uint32_t rx_stat_xonpauseframesreceived_lo; /* pause_xoff_frames_received */ uint32_t rx_stat_xoffpauseframesreceived_hi; uint32_t rx_stat_xoffpauseframesreceived_lo; /* pause_xon_frames_transmitted */ uint32_t tx_stat_outxonsent_hi; uint32_t tx_stat_outxonsent_lo; /* pause_xoff_frames_transmitted */ uint32_t tx_stat_outxoffsent_hi; uint32_t tx_stat_outxoffsent_lo; /* flow_control_done */ uint32_t tx_stat_flowcontroldone_hi; uint32_t tx_stat_flowcontroldone_lo; /* ether_stats_collisions */ uint32_t tx_stat_etherstatscollisions_hi; uint32_t tx_stat_etherstatscollisions_lo; /* single_collision_transmit_frames */ uint32_t tx_stat_dot3statssinglecollisionframes_hi; uint32_t tx_stat_dot3statssinglecollisionframes_lo; /* multiple_collision_transmit_frames */ uint32_t tx_stat_dot3statsmultiplecollisionframes_hi; uint32_t tx_stat_dot3statsmultiplecollisionframes_lo; /* deferred_transmissions */ uint32_t tx_stat_dot3statsdeferredtransmissions_hi; uint32_t tx_stat_dot3statsdeferredtransmissions_lo; /* excessive_collision_frames */ uint32_t tx_stat_dot3statsexcessivecollisions_hi; uint32_t tx_stat_dot3statsexcessivecollisions_lo; /* late_collision_frames */ uint32_t tx_stat_dot3statslatecollisions_hi; uint32_t tx_stat_dot3statslatecollisions_lo; /* frames_transmitted_64_bytes */ uint32_t tx_stat_etherstatspkts64octets_hi; uint32_t tx_stat_etherstatspkts64octets_lo; /* frames_transmitted_65_127_bytes */ uint32_t tx_stat_etherstatspkts65octetsto127octets_hi; uint32_t tx_stat_etherstatspkts65octetsto127octets_lo; /* frames_transmitted_128_255_bytes */ uint32_t tx_stat_etherstatspkts128octetsto255octets_hi; uint32_t tx_stat_etherstatspkts128octetsto255octets_lo; /* frames_transmitted_256_511_bytes */ uint32_t tx_stat_etherstatspkts256octetsto511octets_hi; uint32_t tx_stat_etherstatspkts256octetsto511octets_lo; /* frames_transmitted_512_1023_bytes */ uint32_t tx_stat_etherstatspkts512octetsto1023octets_hi; uint32_t tx_stat_etherstatspkts512octetsto1023octets_lo; /* frames_transmitted_1024_1522_bytes */ uint32_t tx_stat_etherstatspkts1024octetsto1522octets_hi; uint32_t tx_stat_etherstatspkts1024octetsto1522octets_lo; /* frames_transmitted_1523_9022_bytes */ uint32_t tx_stat_etherstatspktsover1522octets_hi; uint32_t tx_stat_etherstatspktsover1522octets_lo; uint32_t tx_stat_mac_2047_hi; uint32_t tx_stat_mac_2047_lo; uint32_t tx_stat_mac_4095_hi; uint32_t tx_stat_mac_4095_lo; uint32_t tx_stat_mac_9216_hi; uint32_t tx_stat_mac_9216_lo; uint32_t tx_stat_mac_16383_hi; uint32_t tx_stat_mac_16383_lo; /* internal_mac_transmit_errors */ uint32_t tx_stat_dot3statsinternalmactransmiterrors_hi; uint32_t tx_stat_dot3statsinternalmactransmiterrors_lo; /* if_out_discards */ uint32_t tx_stat_mac_ufl_hi; uint32_t tx_stat_mac_ufl_lo; }; #define MAC_STX_IDX_MAX 2 struct host_port_stats { uint32_t host_port_stats_counter; struct mac_stx mac_stx[MAC_STX_IDX_MAX]; uint32_t brb_drop_hi; uint32_t brb_drop_lo; uint32_t not_used; /* obsolete as of MFW 7.2.1 */ uint32_t pfc_frames_tx_hi; uint32_t pfc_frames_tx_lo; uint32_t pfc_frames_rx_hi; uint32_t pfc_frames_rx_lo; uint32_t eee_lpi_count_hi; uint32_t eee_lpi_count_lo; }; struct host_func_stats { uint32_t host_func_stats_start; uint32_t total_bytes_received_hi; uint32_t total_bytes_received_lo; uint32_t total_bytes_transmitted_hi; uint32_t total_bytes_transmitted_lo; uint32_t total_unicast_packets_received_hi; uint32_t total_unicast_packets_received_lo; uint32_t total_multicast_packets_received_hi; uint32_t total_multicast_packets_received_lo; uint32_t total_broadcast_packets_received_hi; uint32_t total_broadcast_packets_received_lo; uint32_t total_unicast_packets_transmitted_hi; uint32_t total_unicast_packets_transmitted_lo; uint32_t total_multicast_packets_transmitted_hi; uint32_t total_multicast_packets_transmitted_lo; uint32_t total_broadcast_packets_transmitted_hi; uint32_t total_broadcast_packets_transmitted_lo; uint32_t valid_bytes_received_hi; uint32_t valid_bytes_received_lo; uint32_t host_func_stats_end; }; /* VIC definitions */ #define VICSTATST_UIF_INDEX 2 /* * stats collected for afex. * NOTE: structure is exactly as expected to be received by the switch. * order must remain exactly as is unless protocol changes ! */ struct afex_stats { uint32_t tx_unicast_frames_hi; uint32_t tx_unicast_frames_lo; uint32_t tx_unicast_bytes_hi; uint32_t tx_unicast_bytes_lo; uint32_t tx_multicast_frames_hi; uint32_t tx_multicast_frames_lo; uint32_t tx_multicast_bytes_hi; uint32_t tx_multicast_bytes_lo; uint32_t tx_broadcast_frames_hi; uint32_t tx_broadcast_frames_lo; uint32_t tx_broadcast_bytes_hi; uint32_t tx_broadcast_bytes_lo; uint32_t tx_frames_discarded_hi; uint32_t tx_frames_discarded_lo; uint32_t tx_frames_dropped_hi; uint32_t tx_frames_dropped_lo; uint32_t rx_unicast_frames_hi; uint32_t rx_unicast_frames_lo; uint32_t rx_unicast_bytes_hi; uint32_t rx_unicast_bytes_lo; uint32_t rx_multicast_frames_hi; uint32_t rx_multicast_frames_lo; uint32_t rx_multicast_bytes_hi; uint32_t rx_multicast_bytes_lo; uint32_t rx_broadcast_frames_hi; uint32_t rx_broadcast_frames_lo; uint32_t rx_broadcast_bytes_hi; uint32_t rx_broadcast_bytes_lo; uint32_t rx_frames_discarded_hi; uint32_t rx_frames_discarded_lo; uint32_t rx_frames_dropped_hi; uint32_t rx_frames_dropped_lo; }; /* To maintain backward compatibility between FW and drivers, new elements */ /* should be added to the end of the structure. */ /* Per Port Statistics */ struct port_info { uint32_t size; /* size of this structure (i.e. sizeof(port_info)) */ uint32_t enabled; /* 0 =Disabled, 1= Enabled */ uint32_t link_speed; /* multiplier of 100Mb */ uint32_t wol_support; /* WoL Support (i.e. Non-Zero if WOL supported ) */ uint32_t flow_control; /* 802.3X Flow Ctrl. 0=off 1=RX 2=TX 3=RX&TX.*/ uint32_t flex10; /* Flex10 mode enabled. non zero = yes */ uint32_t rx_drops; /* RX Discards. Counters roll over, never reset */ uint32_t rx_errors; /* RX Errors. Physical Port Stats L95, All PFs and NC-SI. This is flagged by Consumer as an error. */ uint32_t rx_uncast_lo; /* RX Unicast Packets. Free running counters: */ uint32_t rx_uncast_hi; /* RX Unicast Packets. Free running counters: */ uint32_t rx_mcast_lo; /* RX Multicast Packets */ uint32_t rx_mcast_hi; /* RX Multicast Packets */ uint32_t rx_bcast_lo; /* RX Broadcast Packets */ uint32_t rx_bcast_hi; /* RX Broadcast Packets */ uint32_t tx_uncast_lo; /* TX Unicast Packets */ uint32_t tx_uncast_hi; /* TX Unicast Packets */ uint32_t tx_mcast_lo; /* TX Multicast Packets */ uint32_t tx_mcast_hi; /* TX Multicast Packets */ uint32_t tx_bcast_lo; /* TX Broadcast Packets */ uint32_t tx_bcast_hi; /* TX Broadcast Packets */ uint32_t tx_errors; /* TX Errors */ uint32_t tx_discards; /* TX Discards */ uint32_t rx_frames_lo; /* RX Frames received */ uint32_t rx_frames_hi; /* RX Frames received */ uint32_t rx_bytes_lo; /* RX Bytes received */ uint32_t rx_bytes_hi; /* RX Bytes received */ uint32_t tx_frames_lo; /* TX Frames sent */ uint32_t tx_frames_hi; /* TX Frames sent */ uint32_t tx_bytes_lo; /* TX Bytes sent */ uint32_t tx_bytes_hi; /* TX Bytes sent */ uint32_t link_status; /* Port P Link Status. 1:0 bit for port enabled. 1:1 bit for link good, 2:1 Set if link changed between last poll. */ uint32_t tx_pfc_frames_lo; /* PFC Frames sent. */ uint32_t tx_pfc_frames_hi; /* PFC Frames sent. */ uint32_t rx_pfc_frames_lo; /* PFC Frames Received. */ uint32_t rx_pfc_frames_hi; /* PFC Frames Received. */ }; #define BNX2X_5710_FW_MAJOR_VERSION 7 #define BNX2X_5710_FW_MINOR_VERSION 2 #define BNX2X_5710_FW_REVISION_VERSION 51 #define BNX2X_5710_FW_ENGINEERING_VERSION 0 #define BNX2X_5710_FW_COMPILE_FLAGS 1 /* * attention bits $$KEEP_ENDIANNESS$$ */ struct atten_sp_status_block { uint32_t attn_bits /* 16 bit of attention signal lines */; uint32_t attn_bits_ack /* 16 bit of attention signal ack */; uint8_t status_block_id /* status block id */; uint8_t reserved0 /* resreved for padding */; uint16_t attn_bits_index /* attention bits running index */; uint32_t reserved1 /* resreved for padding */; }; /* * The eth aggregative context of Cstorm */ struct cstorm_eth_ag_context { uint32_t __reserved0[10]; }; /* * dmae command structure */ struct dmae_command { uint32_t opcode; #define DMAE_COMMAND_SRC (0x1<<0) /* BitField opcode Whether the source is the PCIe or the GRC. 0- The source is the PCIe 1- The source is the GRC. */ #define DMAE_COMMAND_SRC_SHIFT 0 #define DMAE_COMMAND_DST (0x3<<1) /* BitField opcode The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */ #define DMAE_COMMAND_DST_SHIFT 1 #define DMAE_COMMAND_C_DST (0x1<<3) /* BitField opcode The destination of the completion: 0-PCIe 1-GRC */ #define DMAE_COMMAND_C_DST_SHIFT 3 #define DMAE_COMMAND_C_TYPE_ENABLE (0x1<<4) /* BitField opcode Whether to write a completion word to the completion destination: 0-Do not write a completion word 1-Write the completion word */ #define DMAE_COMMAND_C_TYPE_ENABLE_SHIFT 4 #define DMAE_COMMAND_C_TYPE_CRC_ENABLE (0x1<<5) /* BitField opcode Whether to write a CRC word to the completion destination 0-Do not write a CRC word 1-Write a CRC word */ #define DMAE_COMMAND_C_TYPE_CRC_ENABLE_SHIFT 5 #define DMAE_COMMAND_C_TYPE_CRC_OFFSET (0x7<<6) /* BitField opcode The CRC word should be taken from the DMAE GRC space from address 9+X, where X is the value in these bits. */ #define DMAE_COMMAND_C_TYPE_CRC_OFFSET_SHIFT 6 #define DMAE_COMMAND_ENDIANITY (0x3<<9) /* BitField opcode swapping mode. */ #define DMAE_COMMAND_ENDIANITY_SHIFT 9 #define DMAE_COMMAND_PORT (0x1<<11) /* BitField opcode Which network port ID to present to the PCI request interface */ #define DMAE_COMMAND_PORT_SHIFT 11 #define DMAE_COMMAND_CRC_RESET (0x1<<12) /* BitField opcode reset crc result */ #define DMAE_COMMAND_CRC_RESET_SHIFT 12 #define DMAE_COMMAND_SRC_RESET (0x1<<13) /* BitField opcode reset source address in next go */ #define DMAE_COMMAND_SRC_RESET_SHIFT 13 #define DMAE_COMMAND_DST_RESET (0x1<<14) /* BitField opcode reset dest address in next go */ #define DMAE_COMMAND_DST_RESET_SHIFT 14 #define DMAE_COMMAND_E1HVN (0x3<<15) /* BitField opcode vnic number E2 and onwards source vnic */ #define DMAE_COMMAND_E1HVN_SHIFT 15 #define DMAE_COMMAND_DST_VN (0x3<<17) /* BitField opcode E2 and onwards dest vnic */ #define DMAE_COMMAND_DST_VN_SHIFT 17 #define DMAE_COMMAND_C_FUNC (0x1<<19) /* BitField opcode E2 and onwards which function gets the completion src_vn(e1hvn)-0 dst_vn-1 */ #define DMAE_COMMAND_C_FUNC_SHIFT 19 #define DMAE_COMMAND_ERR_POLICY (0x3<<20) /* BitField opcode E2 and onwards what to do when theres a completion and a PCI error regular-0 error indication-1 no completion-2 */ #define DMAE_COMMAND_ERR_POLICY_SHIFT 20 #define DMAE_COMMAND_RESERVED0 (0x3FF<<22) /* BitField opcode */ #define DMAE_COMMAND_RESERVED0_SHIFT 22 uint32_t src_addr_lo /* source address low/grc address */; uint32_t src_addr_hi /* source address hi */; uint32_t dst_addr_lo /* dest address low/grc address */; uint32_t dst_addr_hi /* dest address hi */; #if defined(__BIG_ENDIAN) uint16_t opcode_iov; #define DMAE_COMMAND_SRC_VFID (0x3F<<0) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility source VF id */ #define DMAE_COMMAND_SRC_VFID_SHIFT 0 #define DMAE_COMMAND_SRC_VFPF (0x1<<6) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility selects the source function PF-0, VF-1 */ #define DMAE_COMMAND_SRC_VFPF_SHIFT 6 #define DMAE_COMMAND_RESERVED1 (0x1<<7) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility */ #define DMAE_COMMAND_RESERVED1_SHIFT 7 #define DMAE_COMMAND_DST_VFID (0x3F<<8) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility destination VF id */ #define DMAE_COMMAND_DST_VFID_SHIFT 8 #define DMAE_COMMAND_DST_VFPF (0x1<<14) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility selects the destination function PF-0, VF-1 */ #define DMAE_COMMAND_DST_VFPF_SHIFT 14 #define DMAE_COMMAND_RESERVED2 (0x1<<15) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility */ #define DMAE_COMMAND_RESERVED2_SHIFT 15 uint16_t len /* copy length */; #elif defined(__LITTLE_ENDIAN) uint16_t len /* copy length */; uint16_t opcode_iov; #define DMAE_COMMAND_SRC_VFID (0x3F<<0) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility source VF id */ #define DMAE_COMMAND_SRC_VFID_SHIFT 0 #define DMAE_COMMAND_SRC_VFPF (0x1<<6) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility selects the source function PF-0, VF-1 */ #define DMAE_COMMAND_SRC_VFPF_SHIFT 6 #define DMAE_COMMAND_RESERVED1 (0x1<<7) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility */ #define DMAE_COMMAND_RESERVED1_SHIFT 7 #define DMAE_COMMAND_DST_VFID (0x3F<<8) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility destination VF id */ #define DMAE_COMMAND_DST_VFID_SHIFT 8 #define DMAE_COMMAND_DST_VFPF (0x1<<14) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility selects the destination function PF-0, VF-1 */ #define DMAE_COMMAND_DST_VFPF_SHIFT 14 #define DMAE_COMMAND_RESERVED2 (0x1<<15) /* BitField opcode_iovE2 and onward, set to 0 for backward compatibility */ #define DMAE_COMMAND_RESERVED2_SHIFT 15 #endif uint32_t comp_addr_lo /* completion address low/grc address */; uint32_t comp_addr_hi /* completion address hi */; uint32_t comp_val /* value to write to completion address */; uint32_t crc32 /* crc32 result */; uint32_t crc32_c /* crc32_c result */; #if defined(__BIG_ENDIAN) uint16_t crc16_c /* crc16_c result */; uint16_t crc16 /* crc16 result */; #elif defined(__LITTLE_ENDIAN) uint16_t crc16 /* crc16 result */; uint16_t crc16_c /* crc16_c result */; #endif #if defined(__BIG_ENDIAN) uint16_t reserved3; uint16_t crc_t10 /* crc_t10 result */; #elif defined(__LITTLE_ENDIAN) uint16_t crc_t10 /* crc_t10 result */; uint16_t reserved3; #endif #if defined(__BIG_ENDIAN) uint16_t xsum8 /* checksum8 result */; uint16_t xsum16 /* checksum16 result */; #elif defined(__LITTLE_ENDIAN) uint16_t xsum16 /* checksum16 result */; uint16_t xsum8 /* checksum8 result */; #endif }; /* * common data for all protocols */ struct doorbell_hdr { uint8_t header; #define DOORBELL_HDR_RX (0x1<<0) /* BitField header 1 for rx doorbell, 0 for tx doorbell */ #define DOORBELL_HDR_RX_SHIFT 0 #define DOORBELL_HDR_DB_TYPE (0x1<<1) /* BitField header 0 for normal doorbell, 1 for advertise wnd doorbell */ #define DOORBELL_HDR_DB_TYPE_SHIFT 1 #define DOORBELL_HDR_DPM_SIZE (0x3<<2) /* BitField header rdma tx only: DPM transaction size specifier (64/128/256/512 bytes) */ #define DOORBELL_HDR_DPM_SIZE_SHIFT 2 #define DOORBELL_HDR_CONN_TYPE (0xF<<4) /* BitField header connection type */ #define DOORBELL_HDR_CONN_TYPE_SHIFT 4 }; /* * Ethernet doorbell */ struct eth_tx_doorbell { #if defined(__BIG_ENDIAN) uint16_t npackets /* number of data bytes that were added in the doorbell */; uint8_t params; #define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0) /* BitField params number of buffer descriptors that were added in the doorbell */ #define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0 #define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6) /* BitField params tx fin command flag */ #define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6 #define ETH_TX_DOORBELL_SPARE (0x1<<7) /* BitField params doorbell queue spare flag */ #define ETH_TX_DOORBELL_SPARE_SHIFT 7 struct doorbell_hdr hdr; #elif defined(__LITTLE_ENDIAN) struct doorbell_hdr hdr; uint8_t params; #define ETH_TX_DOORBELL_NUM_BDS (0x3F<<0) /* BitField params number of buffer descriptors that were added in the doorbell */ #define ETH_TX_DOORBELL_NUM_BDS_SHIFT 0 #define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG (0x1<<6) /* BitField params tx fin command flag */ #define ETH_TX_DOORBELL_RESERVED_TX_FIN_FLAG_SHIFT 6 #define ETH_TX_DOORBELL_SPARE (0x1<<7) /* BitField params doorbell queue spare flag */ #define ETH_TX_DOORBELL_SPARE_SHIFT 7 uint16_t npackets /* number of data bytes that were added in the doorbell */; #endif }; /* * 3 lines. status block $$KEEP_ENDIANNESS$$ */ struct hc_status_block_e1x { uint16_t index_values[HC_SB_MAX_INDICES_E1X] /* indices reported by cstorm */; uint16_t running_index[HC_SB_MAX_SM] /* Status Block running indices */; uint32_t rsrv[11]; }; /* * host status block */ struct host_hc_status_block_e1x { struct hc_status_block_e1x sb /* fast path indices */; }; /* * 3 lines. status block $$KEEP_ENDIANNESS$$ */ struct hc_status_block_e2 { uint16_t index_values[HC_SB_MAX_INDICES_E2] /* indices reported by cstorm */; uint16_t running_index[HC_SB_MAX_SM] /* Status Block running indices */; uint32_t reserved[11]; }; /* * host status block */ struct host_hc_status_block_e2 { struct hc_status_block_e2 sb /* fast path indices */; }; /* * 5 lines. slow-path status block $$KEEP_ENDIANNESS$$ */ struct hc_sp_status_block { uint16_t index_values[HC_SP_SB_MAX_INDICES] /* indices reported by cstorm */; uint16_t running_index /* Status Block running index */; uint16_t rsrv; uint32_t rsrv1; }; /* * host status block */ struct host_sp_status_block { struct atten_sp_status_block atten_status_block /* attention bits section */; struct hc_sp_status_block sp_sb /* slow path indices */; }; /* * IGU driver acknowledgment register */ union igu_ack_register { struct { #if defined(__BIG_ENDIAN) uint16_t sb_id_and_flags; #define IGU_ACK_REGISTER_STATUS_BLOCK_ID (0x1F<<0) /* BitField sb_id_and_flags 0-15: non default status blocks, 16: default status block */ #define IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT 0 #define IGU_ACK_REGISTER_STORM_ID (0x7<<5) /* BitField sb_id_and_flags 0-3:storm id, 4: attn status block (valid in default sb only) */ #define IGU_ACK_REGISTER_STORM_ID_SHIFT 5 #define IGU_ACK_REGISTER_UPDATE_INDEX (0x1<<8) /* BitField sb_id_and_flags if set, acknowledges status block index */ #define IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT 8 #define IGU_ACK_REGISTER_INTERRUPT_MODE (0x3<<9) /* BitField sb_id_and_flags interrupt enable/disable/nop: use IGU_INT_xxx constants */ #define IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT 9 #define IGU_ACK_REGISTER_RESERVED (0x1F<<11) /* BitField sb_id_and_flags */ #define IGU_ACK_REGISTER_RESERVED_SHIFT 11 uint16_t status_block_index /* status block index acknowledgement */; #elif defined(__LITTLE_ENDIAN) uint16_t status_block_index /* status block index acknowledgement */; uint16_t sb_id_and_flags; #define IGU_ACK_REGISTER_STATUS_BLOCK_ID (0x1F<<0) /* BitField sb_id_and_flags 0-15: non default status blocks, 16: default status block */ #define IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT 0 #define IGU_ACK_REGISTER_STORM_ID (0x7<<5) /* BitField sb_id_and_flags 0-3:storm id, 4: attn status block (valid in default sb only) */ #define IGU_ACK_REGISTER_STORM_ID_SHIFT 5 #define IGU_ACK_REGISTER_UPDATE_INDEX (0x1<<8) /* BitField sb_id_and_flags if set, acknowledges status block index */ #define IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT 8 #define IGU_ACK_REGISTER_INTERRUPT_MODE (0x3<<9) /* BitField sb_id_and_flags interrupt enable/disable/nop: use IGU_INT_xxx constants */ #define IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT 9 #define IGU_ACK_REGISTER_RESERVED (0x1F<<11) /* BitField sb_id_and_flags */ #define IGU_ACK_REGISTER_RESERVED_SHIFT 11 #endif } sb; uint32_t raw_data; }; /* * IGU driver acknowledgement register */ struct igu_backward_compatible { uint32_t sb_id_and_flags; #define IGU_BACKWARD_COMPATIBLE_SB_INDEX (0xFFFF<<0) /* BitField sb_id_and_flags */ #define IGU_BACKWARD_COMPATIBLE_SB_INDEX_SHIFT 0 #define IGU_BACKWARD_COMPATIBLE_SB_SELECT (0x1F<<16) /* BitField sb_id_and_flags */ #define IGU_BACKWARD_COMPATIBLE_SB_SELECT_SHIFT 16 #define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS (0x7<<21) /* BitField sb_id_and_flags 0-3:storm id, 4: attn status block (valid in default sb only) */ #define IGU_BACKWARD_COMPATIBLE_SEGMENT_ACCESS_SHIFT 21 #define IGU_BACKWARD_COMPATIBLE_BUPDATE (0x1<<24) /* BitField sb_id_and_flags if set, acknowledges status block index */ #define IGU_BACKWARD_COMPATIBLE_BUPDATE_SHIFT 24 #define IGU_BACKWARD_COMPATIBLE_ENABLE_INT (0x3<<25) /* BitField sb_id_and_flags interrupt enable/disable/nop: use IGU_INT_xxx constants */ #define IGU_BACKWARD_COMPATIBLE_ENABLE_INT_SHIFT 25 #define IGU_BACKWARD_COMPATIBLE_RESERVED_0 (0x1F<<27) /* BitField sb_id_and_flags */ #define IGU_BACKWARD_COMPATIBLE_RESERVED_0_SHIFT 27 uint32_t reserved_2; }; /* * IGU driver acknowledgement register */ struct igu_regular { uint32_t sb_id_and_flags; #define IGU_REGULAR_SB_INDEX (0xFFFFF<<0) /* BitField sb_id_and_flags */ #define IGU_REGULAR_SB_INDEX_SHIFT 0 #define IGU_REGULAR_RESERVED0 (0x1<<20) /* BitField sb_id_and_flags */ #define IGU_REGULAR_RESERVED0_SHIFT 20 #define IGU_REGULAR_SEGMENT_ACCESS (0x7<<21) /* BitField sb_id_and_flags 21-23 (use enum igu_seg_access) */ #define IGU_REGULAR_SEGMENT_ACCESS_SHIFT 21 #define IGU_REGULAR_BUPDATE (0x1<<24) /* BitField sb_id_and_flags */ #define IGU_REGULAR_BUPDATE_SHIFT 24 #define IGU_REGULAR_ENABLE_INT (0x3<<25) /* BitField sb_id_and_flags interrupt enable/disable/nop (use enum igu_int_cmd) */ #define IGU_REGULAR_ENABLE_INT_SHIFT 25 #define IGU_REGULAR_RESERVED_1 (0x1<<27) /* BitField sb_id_and_flags */ #define IGU_REGULAR_RESERVED_1_SHIFT 27 #define IGU_REGULAR_CLEANUP_TYPE (0x3<<28) /* BitField sb_id_and_flags */ #define IGU_REGULAR_CLEANUP_TYPE_SHIFT 28 #define IGU_REGULAR_CLEANUP_SET (0x1<<30) /* BitField sb_id_and_flags */ #define IGU_REGULAR_CLEANUP_SET_SHIFT 30 #define IGU_REGULAR_BCLEANUP (0x1<<31) /* BitField sb_id_and_flags */ #define IGU_REGULAR_BCLEANUP_SHIFT 31 uint32_t reserved_2; }; /* * IGU driver acknowledgement register */ union igu_consprod_reg { struct igu_regular regular; struct igu_backward_compatible backward_compatible; }; /* * Igu control commands */ enum igu_ctrl_cmd { IGU_CTRL_CMD_TYPE_RD, IGU_CTRL_CMD_TYPE_WR, MAX_IGU_CTRL_CMD}; /* * Control register for the IGU command register */ struct igu_ctrl_reg { uint32_t ctrl_data; #define IGU_CTRL_REG_ADDRESS (0xFFF<<0) /* BitField ctrl_data */ #define IGU_CTRL_REG_ADDRESS_SHIFT 0 #define IGU_CTRL_REG_FID (0x7F<<12) /* BitField ctrl_data */ #define IGU_CTRL_REG_FID_SHIFT 12 #define IGU_CTRL_REG_RESERVED (0x1<<19) /* BitField ctrl_data */ #define IGU_CTRL_REG_RESERVED_SHIFT 19 #define IGU_CTRL_REG_TYPE (0x1<<20) /* BitField ctrl_data (use enum igu_ctrl_cmd) */ #define IGU_CTRL_REG_TYPE_SHIFT 20 #define IGU_CTRL_REG_UNUSED (0x7FF<<21) /* BitField ctrl_data */ #define IGU_CTRL_REG_UNUSED_SHIFT 21 }; /* * Igu interrupt command */ enum igu_int_cmd { IGU_INT_ENABLE, IGU_INT_DISABLE, IGU_INT_NOP, IGU_INT_NOP2, MAX_IGU_INT_CMD}; /* * Igu segments */ enum igu_seg_access { IGU_SEG_ACCESS_NORM, IGU_SEG_ACCESS_DEF, IGU_SEG_ACCESS_ATTN, MAX_IGU_SEG_ACCESS}; /* * Parser parsing flags field */ struct parsing_flags { uint16_t flags; #define PARSING_FLAGS_ETHERNET_ADDRESS_TYPE (0x1<<0) /* BitField flagscontext flags 0=non-unicast, 1=unicast (use enum prs_flags_eth_addr_type) */ #define PARSING_FLAGS_ETHERNET_ADDRESS_TYPE_SHIFT 0 #define PARSING_FLAGS_VLAN (0x1<<1) /* BitField flagscontext flags 0 or 1 */ #define PARSING_FLAGS_VLAN_SHIFT 1 #define PARSING_FLAGS_EXTRA_VLAN (0x1<<2) /* BitField flagscontext flags 0 or 1 */ #define PARSING_FLAGS_EXTRA_VLAN_SHIFT 2 #define PARSING_FLAGS_OVER_ETHERNET_PROTOCOL (0x3<<3) /* BitField flagscontext flags 0=un-known, 1=Ipv4, 2=Ipv6,3=LLC SNAP un-known. LLC SNAP here refers only to LLC/SNAP packets that do not have Ipv4 or Ipv6 above them. Ipv4 and Ipv6 indications are even if they are over LLC/SNAP and not directly over Ethernet (use enum prs_flags_over_eth) */ #define PARSING_FLAGS_OVER_ETHERNET_PROTOCOL_SHIFT 3 #define PARSING_FLAGS_IP_OPTIONS (0x1<<5) /* BitField flagscontext flags 0=no IP options / extension headers. 1=IP options / extension header exist */ #define PARSING_FLAGS_IP_OPTIONS_SHIFT 5 #define PARSING_FLAGS_FRAGMENTATION_STATUS (0x1<<6) /* BitField flagscontext flags 0=non-fragmented, 1=fragmented */ #define PARSING_FLAGS_FRAGMENTATION_STATUS_SHIFT 6 #define PARSING_FLAGS_OVER_IP_PROTOCOL (0x3<<7) /* BitField flagscontext flags 0=un-known, 1=TCP, 2=UDP (use enum prs_flags_over_ip) */ #define PARSING_FLAGS_OVER_IP_PROTOCOL_SHIFT 7 #define PARSING_FLAGS_PURE_ACK_INDICATION (0x1<<9) /* BitField flagscontext flags 0=packet with data, 1=pure-ACK (use enum prs_flags_ack_type) */ #define PARSING_FLAGS_PURE_ACK_INDICATION_SHIFT 9 #define PARSING_FLAGS_TCP_OPTIONS_EXIST (0x1<<10) /* BitField flagscontext flags 0=no TCP options. 1=TCP options */ #define PARSING_FLAGS_TCP_OPTIONS_EXIST_SHIFT 10 #define PARSING_FLAGS_TIME_STAMP_EXIST_FLAG (0x1<<11) /* BitField flagscontext flags According to the TCP header options parsing */ #define PARSING_FLAGS_TIME_STAMP_EXIST_FLAG_SHIFT 11 #define PARSING_FLAGS_CONNECTION_MATCH (0x1<<12) /* BitField flagscontext flags connection match in searcher indication */ #define PARSING_FLAGS_CONNECTION_MATCH_SHIFT 12 #define PARSING_FLAGS_LLC_SNAP (0x1<<13) /* BitField flagscontext flags LLC SNAP indication */ #define PARSING_FLAGS_LLC_SNAP_SHIFT 13 #define PARSING_FLAGS_RESERVED0 (0x3<<14) /* BitField flagscontext flags */ #define PARSING_FLAGS_RESERVED0_SHIFT 14 }; /* * Parsing flags for TCP ACK type */ enum prs_flags_ack_type { PRS_FLAG_PUREACK_PIGGY, PRS_FLAG_PUREACK_PURE, MAX_PRS_FLAGS_ACK_TYPE}; /* * Parsing flags for Ethernet address type */ enum prs_flags_eth_addr_type { PRS_FLAG_ETHTYPE_NON_UNICAST, PRS_FLAG_ETHTYPE_UNICAST, MAX_PRS_FLAGS_ETH_ADDR_TYPE}; /* * Parsing flags for over-ethernet protocol */ enum prs_flags_over_eth { PRS_FLAG_OVERETH_UNKNOWN, PRS_FLAG_OVERETH_IPV4, PRS_FLAG_OVERETH_IPV6, PRS_FLAG_OVERETH_LLCSNAP_UNKNOWN, MAX_PRS_FLAGS_OVER_ETH}; /* * Parsing flags for over-IP protocol */ enum prs_flags_over_ip { PRS_FLAG_OVERIP_UNKNOWN, PRS_FLAG_OVERIP_TCP, PRS_FLAG_OVERIP_UDP, MAX_PRS_FLAGS_OVER_IP}; /* * SDM operation gen command (generate aggregative interrupt) */ struct sdm_op_gen { uint32_t command; #define SDM_OP_GEN_COMP_PARAM (0x1F<<0) /* BitField commandcomp_param and comp_type thread ID/aggr interrupt number/counter depending on the completion type */ #define SDM_OP_GEN_COMP_PARAM_SHIFT 0 #define SDM_OP_GEN_COMP_TYPE (0x7<<5) /* BitField commandcomp_param and comp_type Direct messages to CM / PCI switch are not supported in operation_gen completion */ #define SDM_OP_GEN_COMP_TYPE_SHIFT 5 #define SDM_OP_GEN_AGG_VECT_IDX (0xFF<<8) /* BitField commandcomp_param and comp_type bit index in aggregated interrupt vector */ #define SDM_OP_GEN_AGG_VECT_IDX_SHIFT 8 #define SDM_OP_GEN_AGG_VECT_IDX_VALID (0x1<<16) /* BitField commandcomp_param and comp_type */ #define SDM_OP_GEN_AGG_VECT_IDX_VALID_SHIFT 16 #define SDM_OP_GEN_RESERVED (0x7FFF<<17) /* BitField commandcomp_param and comp_type */ #define SDM_OP_GEN_RESERVED_SHIFT 17 }; /* * Timers connection context */ struct timers_block_context { uint32_t __reserved_0 /* data of client 0 of the timers block*/; uint32_t __reserved_1 /* data of client 1 of the timers block*/; uint32_t __reserved_2 /* data of client 2 of the timers block*/; uint32_t flags; #define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS (0x3<<0) /* BitField flagscontext flags number of active timers running */ #define __TIMERS_BLOCK_CONTEXT_NUM_OF_ACTIVE_TIMERS_SHIFT 0 #define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG (0x1<<2) /* BitField flagscontext flags flag: is connection valid (should be set by driver to 1 in toe/iscsi connections) */ #define TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG_SHIFT 2 #define __TIMERS_BLOCK_CONTEXT_RESERVED0 (0x1FFFFFFF<<3) /* BitField flagscontext flags */ #define __TIMERS_BLOCK_CONTEXT_RESERVED0_SHIFT 3 }; /* * The eth aggregative context of Tstorm */ struct tstorm_eth_ag_context { uint32_t __reserved0[14]; }; /* * The eth aggregative context of Ustorm */ struct ustorm_eth_ag_context { uint32_t __reserved0; #if defined(__BIG_ENDIAN) uint8_t cdu_usage /* Will be used by the CDU for validation of the CID/connection type on doorbells. */; uint8_t __reserved2; uint16_t __reserved1; #elif defined(__LITTLE_ENDIAN) uint16_t __reserved1; uint8_t __reserved2; uint8_t cdu_usage /* Will be used by the CDU for validation of the CID/connection type on doorbells. */; #endif uint32_t __reserved3[6]; }; /* * The eth aggregative context of Xstorm */ struct xstorm_eth_ag_context { uint32_t reserved0; #if defined(__BIG_ENDIAN) uint8_t cdu_reserved /* Used by the CDU for validation and debugging */; uint8_t reserved2; uint16_t reserved1; #elif defined(__LITTLE_ENDIAN) uint16_t reserved1; uint8_t reserved2; uint8_t cdu_reserved /* Used by the CDU for validation and debugging */; #endif uint32_t reserved3[30]; }; /* * doorbell message sent to the chip */ struct doorbell { #if defined(__BIG_ENDIAN) uint16_t zero_fill2 /* driver must zero this field! */; uint8_t zero_fill1 /* driver must zero this field! */; struct doorbell_hdr header; #elif defined(__LITTLE_ENDIAN) struct doorbell_hdr header; uint8_t zero_fill1 /* driver must zero this field! */; uint16_t zero_fill2 /* driver must zero this field! */; #endif }; /* * doorbell message sent to the chip */ struct doorbell_set_prod { #if defined(__BIG_ENDIAN) uint16_t prod /* Producer index to be set */; uint8_t zero_fill1 /* driver must zero this field! */; struct doorbell_hdr header; #elif defined(__LITTLE_ENDIAN) struct doorbell_hdr header; uint8_t zero_fill1 /* driver must zero this field! */; uint16_t prod /* Producer index to be set */; #endif }; struct regpair { uint32_t lo /* low word for reg-pair */; uint32_t hi /* high word for reg-pair */; }; struct regpair_native { uint32_t lo /* low word for reg-pair */; uint32_t hi /* high word for reg-pair */; }; /* * Classify rule opcodes in E2/E3 */ enum classify_rule { CLASSIFY_RULE_OPCODE_MAC /* Add/remove a MAC address */, CLASSIFY_RULE_OPCODE_VLAN /* Add/remove a VLAN */, CLASSIFY_RULE_OPCODE_PAIR /* Add/remove a MAC-VLAN pair */, MAX_CLASSIFY_RULE}; /* * Classify rule types in E2/E3 */ enum classify_rule_action_type { CLASSIFY_RULE_REMOVE, CLASSIFY_RULE_ADD, MAX_CLASSIFY_RULE_ACTION_TYPE}; /* * client init ramrod data $$KEEP_ENDIANNESS$$ */ struct client_init_general_data { uint8_t client_id /* client_id */; uint8_t statistics_counter_id /* statistics counter id */; uint8_t statistics_en_flg /* statistics en flg */; uint8_t is_fcoe_flg /* is this an fcoe connection. (1 bit is used) */; uint8_t activate_flg /* if 0 - the client is deactivate else the client is activate client (1 bit is used) */; uint8_t sp_client_id /* the slow path rings client Id. */; uint16_t mtu /* Host MTU from client config */; uint8_t statistics_zero_flg /* if set FW will reset the statistic counter of this client */; uint8_t func_id /* PCI function ID (0-71) */; uint8_t cos /* The connection cos, if applicable */; uint8_t traffic_type; uint32_t reserved0; }; /* * client init rx data $$KEEP_ENDIANNESS$$ */ struct client_init_rx_data { uint8_t tpa_en; #define CLIENT_INIT_RX_DATA_TPA_EN_IPV4 (0x1<<0) /* BitField tpa_entpa_enable tpa enable flg ipv4 */ #define CLIENT_INIT_RX_DATA_TPA_EN_IPV4_SHIFT 0 #define CLIENT_INIT_RX_DATA_TPA_EN_IPV6 (0x1<<1) /* BitField tpa_entpa_enable tpa enable flg ipv6 */ #define CLIENT_INIT_RX_DATA_TPA_EN_IPV6_SHIFT 1 #define CLIENT_INIT_RX_DATA_TPA_MODE (0x1<<2) /* BitField tpa_entpa_enable tpa mode (LRO or GRO) (use enum tpa_mode) */ #define CLIENT_INIT_RX_DATA_TPA_MODE_SHIFT 2 #define CLIENT_INIT_RX_DATA_RESERVED5 (0x1F<<3) /* BitField tpa_entpa_enable */ #define CLIENT_INIT_RX_DATA_RESERVED5_SHIFT 3 uint8_t vmqueue_mode_en_flg /* If set, working in VMQueue mode (always consume one sge) */; uint8_t extra_data_over_sgl_en_flg /* if set, put over sgl data from end of input message */; uint8_t cache_line_alignment_log_size /* The log size of cache line alignment in bytes. Must be a power of 2. */; uint8_t enable_dynamic_hc /* If set, dynamic HC is enabled */; uint8_t max_sges_for_packet /* The maximal number of SGEs that can be used for one packet. depends on MTU and SGE size. must be 0 if SGEs are disabled */; uint8_t client_qzone_id /* used in E2 only, to specify the HW queue zone ID used for this client rx producers */; uint8_t drop_ip_cs_err_flg /* If set, this client drops packets with IP checksum error */; uint8_t drop_tcp_cs_err_flg /* If set, this client drops packets with TCP checksum error */; uint8_t drop_ttl0_flg /* If set, this client drops packets with TTL=0 */; uint8_t drop_udp_cs_err_flg /* If set, this client drops packets with UDP checksum error */; uint8_t inner_vlan_removal_enable_flg /* If set, inner VLAN removal is enabled for this client */; uint8_t outer_vlan_removal_enable_flg /* If set, outer VLAN removal is enabled for this client */; uint8_t status_block_id /* rx status block id */; uint8_t rx_sb_index_number /* status block indices */; uint8_t dont_verify_rings_pause_thr_flg /* If set, the rings pause thresholds will not be verified by firmware. */; uint8_t max_tpa_queues /* maximal TPA queues allowed for this client */; uint8_t silent_vlan_removal_flg /* if set, and the vlan is equal to requested vlan according to mask, the vlan will be remove without notifying the driver */; uint16_t max_bytes_on_bd /* Maximum bytes that can be placed on a BD. The BD allocated size should include 2 more bytes (ip alignment) and alignment size (in case the address is not aligned) */; uint16_t sge_buff_size /* Size of the buffers pointed by SGEs */; uint8_t approx_mcast_engine_id /* In Everest2, if is_approx_mcast is set, this field specified which approximate multicast engine is associate with this client */; uint8_t rss_engine_id /* In Everest2, if rss_mode is set, this field specified which RSS engine is associate with this client */; struct regpair bd_page_base /* BD page base address at the host */; struct regpair sge_page_base /* SGE page base address at the host */; struct regpair cqe_page_base /* Completion queue base address */; uint8_t is_leading_rss; uint8_t is_approx_mcast; uint16_t max_agg_size /* maximal size for the aggregated TPA packets, reprted by the host */; uint16_t state; #define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL (0x1<<0) /* BitField staterx filters state drop all unicast packets */ #define CLIENT_INIT_RX_DATA_UCAST_DROP_ALL_SHIFT 0 #define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL (0x1<<1) /* BitField staterx filters state accept all unicast packets (subject to vlan) */ #define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_ALL_SHIFT 1 #define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED (0x1<<2) /* BitField staterx filters state accept all unmatched unicast packets (subject to vlan) */ #define CLIENT_INIT_RX_DATA_UCAST_ACCEPT_UNMATCHED_SHIFT 2 #define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL (0x1<<3) /* BitField staterx filters state drop all multicast packets */ #define CLIENT_INIT_RX_DATA_MCAST_DROP_ALL_SHIFT 3 #define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL (0x1<<4) /* BitField staterx filters state accept all multicast packets (subject to vlan) */ #define CLIENT_INIT_RX_DATA_MCAST_ACCEPT_ALL_SHIFT 4 #define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL (0x1<<5) /* BitField staterx filters state accept all broadcast packets (subject to vlan) */ #define CLIENT_INIT_RX_DATA_BCAST_ACCEPT_ALL_SHIFT 5 #define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN (0x1<<6) /* BitField staterx filters state accept packets matched only by MAC (without checking vlan) */ #define CLIENT_INIT_RX_DATA_ACCEPT_ANY_VLAN_SHIFT 6 #define CLIENT_INIT_RX_DATA_RESERVED2 (0x1FF<<7) /* BitField staterx filters state */ #define CLIENT_INIT_RX_DATA_RESERVED2_SHIFT 7 uint16_t cqe_pause_thr_low /* number of remaining cqes under which, we send pause message */; uint16_t cqe_pause_thr_high /* number of remaining cqes above which, we send un-pause message */; uint16_t bd_pause_thr_low /* number of remaining bds under which, we send pause message */; uint16_t bd_pause_thr_high /* number of remaining bds above which, we send un-pause message */; uint16_t sge_pause_thr_low /* number of remaining sges under which, we send pause message */; uint16_t sge_pause_thr_high /* number of remaining sges above which, we send un-pause message */; uint16_t rx_cos_mask /* the bits that will be set on pfc/ safc paket whith will be genratet when this ring is full. for regular flow control set this to 1 */; uint16_t silent_vlan_value /* The vlan to compare, in case, silent vlan is set */; uint16_t silent_vlan_mask /* The vlan mask, in case, silent vlan is set */; uint32_t reserved6[2]; }; /* * client init tx data $$KEEP_ENDIANNESS$$ */ struct client_init_tx_data { uint8_t enforce_security_flg /* if set, security checks will be made for this connection */; uint8_t tx_status_block_id /* the number of status block to update */; uint8_t tx_sb_index_number /* the index to use inside the status block */; uint8_t tss_leading_client_id /* client ID of the leading TSS client, for TX classification source knock out */; uint8_t tx_switching_flg /* if set, tx switching will be done to packets on this connection */; uint8_t anti_spoofing_flg /* if set, anti spoofing check will be done to packets on this connection */; uint16_t default_vlan /* default vlan tag (id+pri). (valid if default_vlan_flg is set) */; struct regpair tx_bd_page_base /* BD page base address at the host for TxBdCons */; uint16_t state; #define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL (0x1<<0) /* BitField statetx filters state accept all unicast packets (subject to vlan) */ #define CLIENT_INIT_TX_DATA_UCAST_ACCEPT_ALL_SHIFT 0 #define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL (0x1<<1) /* BitField statetx filters state accept all multicast packets (subject to vlan) */ #define CLIENT_INIT_TX_DATA_MCAST_ACCEPT_ALL_SHIFT 1 #define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL (0x1<<2) /* BitField statetx filters state accept all broadcast packets (subject to vlan) */ #define CLIENT_INIT_TX_DATA_BCAST_ACCEPT_ALL_SHIFT 2 #define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN (0x1<<3) /* BitField statetx filters state accept packets matched only by MAC (without checking vlan) */ #define CLIENT_INIT_TX_DATA_ACCEPT_ANY_VLAN_SHIFT 3 #define CLIENT_INIT_TX_DATA_RESERVED0 (0xFFF<<4) /* BitField statetx filters state */ #define CLIENT_INIT_TX_DATA_RESERVED0_SHIFT 4 uint8_t default_vlan_flg /* is default vlan valid for this client. */; uint8_t force_default_pri_flg /* if set, force default priority */; uint8_t tunnel_lso_inc_ip_id /* In case of LSO over IPv4 tunnel, whether to increment IP ID on external IP header or internal IP header */; uint8_t refuse_outband_vlan_flg /* if set, the FW will not add outband vlan on packet (even if will exist on BD). */; uint8_t tunnel_non_lso_pcsum_location /* In case of non-Lso encapsulated packets with L4 checksum offload, the pseudo checksum location - on packet or on BD. */; uint8_t tunnel_non_lso_outer_ip_csum_location /* In case of non-Lso encapsulated packets with outer L3 ip checksum offload, the pseudo checksum location - on packet or on BD. */; }; /* * client init ramrod data $$KEEP_ENDIANNESS$$ */ struct client_init_ramrod_data { struct client_init_general_data general /* client init general data */; struct client_init_rx_data rx /* client init rx data */; struct client_init_tx_data tx /* client init tx data */; }; /* * client update ramrod data $$KEEP_ENDIANNESS$$ */ struct client_update_ramrod_data { uint8_t client_id /* the client to update */; uint8_t func_id /* PCI function ID this client belongs to (0-71) */; uint8_t inner_vlan_removal_enable_flg /* If set, inner VLAN removal is enabled for this client, will be change according to change flag */; uint8_t inner_vlan_removal_change_flg /* If set, inner VLAN removal flag will be set according to the enable flag */; uint8_t outer_vlan_removal_enable_flg /* If set, outer VLAN removal is enabled for this client, will be change according to change flag */; uint8_t outer_vlan_removal_change_flg /* If set, outer VLAN removal flag will be set according to the enable flag */; uint8_t anti_spoofing_enable_flg /* If set, anti spoofing is enabled for this client, will be change according to change flag */; uint8_t anti_spoofing_change_flg /* If set, anti spoofing flag will be set according to anti spoofing flag */; uint8_t activate_flg /* if 0 - the client is deactivate else the client is activate client (1 bit is used) */; uint8_t activate_change_flg /* If set, activate_flg will be checked */; uint16_t default_vlan /* default vlan tag (id+pri). (valid if default_vlan_flg is set) */; uint8_t default_vlan_enable_flg; uint8_t default_vlan_change_flg; uint16_t silent_vlan_value /* The vlan to compare, in case, silent vlan is set */; uint16_t silent_vlan_mask /* The vlan mask, in case, silent vlan is set */; uint8_t silent_vlan_removal_flg /* if set, and the vlan is equal to requested vlan according to mask, the vlan will be remove without notifying the driver */; uint8_t silent_vlan_change_flg; uint8_t refuse_outband_vlan_flg /* If set, the FW will not add outband vlan on packet (even if will exist on BD). */; uint8_t refuse_outband_vlan_change_flg /* If set, refuse_outband_vlan_flg will be updated. */; uint8_t tx_switching_flg /* If set, tx switching will be done to packets on this connection. */; uint8_t tx_switching_change_flg /* If set, tx_switching_flg will be updated. */; uint32_t reserved1; uint32_t echo /* echo value to be sent to driver on event ring */; }; /* * The eth storm context of Cstorm */ struct cstorm_eth_st_context { uint32_t __reserved0[4]; }; struct double_regpair { uint32_t regpair0_lo /* low word for reg-pair0 */; uint32_t regpair0_hi /* high word for reg-pair0 */; uint32_t regpair1_lo /* low word for reg-pair1 */; uint32_t regpair1_hi /* high word for reg-pair1 */; }; /* * Ethernet address typesm used in ethernet tx BDs */ enum eth_addr_type { UNKNOWN_ADDRESS, UNICAST_ADDRESS, MULTICAST_ADDRESS, BROADCAST_ADDRESS, MAX_ETH_ADDR_TYPE}; /* * $$KEEP_ENDIANNESS$$ */ struct eth_classify_cmd_header { uint8_t cmd_general_data; #define ETH_CLASSIFY_CMD_HEADER_RX_CMD (0x1<<0) /* BitField cmd_general_data should this cmd be applied for Rx */ #define ETH_CLASSIFY_CMD_HEADER_RX_CMD_SHIFT 0 #define ETH_CLASSIFY_CMD_HEADER_TX_CMD (0x1<<1) /* BitField cmd_general_data should this cmd be applied for Tx */ #define ETH_CLASSIFY_CMD_HEADER_TX_CMD_SHIFT 1 #define ETH_CLASSIFY_CMD_HEADER_OPCODE (0x3<<2) /* BitField cmd_general_data command opcode for MAC/VLAN/PAIR (use enum classify_rule) */ #define ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT 2 #define ETH_CLASSIFY_CMD_HEADER_IS_ADD (0x1<<4) /* BitField cmd_general_data (use enum classify_rule_action_type) */ #define ETH_CLASSIFY_CMD_HEADER_IS_ADD_SHIFT 4 #define ETH_CLASSIFY_CMD_HEADER_RESERVED0 (0x7<<5) /* BitField cmd_general_data */ #define ETH_CLASSIFY_CMD_HEADER_RESERVED0_SHIFT 5 uint8_t func_id /* the function id */; uint8_t client_id; uint8_t reserved1; }; /* * header for eth classification config ramrod $$KEEP_ENDIANNESS$$ */ struct eth_classify_header { uint8_t rule_cnt /* number of rules in classification config ramrod */; uint8_t reserved0; uint16_t reserved1; uint32_t echo /* echo value to be sent to driver on event ring */; }; /* * Command for adding/removing a MAC classification rule $$KEEP_ENDIANNESS$$ */ struct eth_classify_mac_cmd { struct eth_classify_cmd_header header; uint16_t reserved0; uint16_t inner_mac; uint16_t mac_lsb; uint16_t mac_mid; uint16_t mac_msb; uint16_t reserved1; }; /* * Command for adding/removing a MAC-VLAN pair classification rule $$KEEP_ENDIANNESS$$ */ struct eth_classify_pair_cmd { struct eth_classify_cmd_header header; uint16_t reserved0; uint16_t inner_mac; uint16_t mac_lsb; uint16_t mac_mid; uint16_t mac_msb; uint16_t vlan; }; /* * Command for adding/removing a VLAN classification rule $$KEEP_ENDIANNESS$$ */ struct eth_classify_vlan_cmd { struct eth_classify_cmd_header header; uint32_t reserved0; uint32_t reserved1; uint16_t reserved2; uint16_t vlan; }; /* * union for eth classification rule $$KEEP_ENDIANNESS$$ */ union eth_classify_rule_cmd { struct eth_classify_mac_cmd mac; struct eth_classify_vlan_cmd vlan; struct eth_classify_pair_cmd pair; }; /* * parameters for eth classification configuration ramrod $$KEEP_ENDIANNESS$$ */ struct eth_classify_rules_ramrod_data { struct eth_classify_header header; union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT]; }; /* * The data contain client ID need to the ramrod $$KEEP_ENDIANNESS$$ */ struct eth_common_ramrod_data { uint32_t client_id /* id of this client. (5 bits are used) */; uint32_t reserved1; }; /* * The eth storm context of Ustorm */ struct ustorm_eth_st_context { uint32_t reserved0[52]; }; /* * The eth storm context of Tstorm */ struct tstorm_eth_st_context { uint32_t __reserved0[28]; }; /* * The eth storm context of Xstorm */ struct xstorm_eth_st_context { uint32_t reserved0[60]; }; /* * Ethernet connection context */ struct eth_context { struct ustorm_eth_st_context ustorm_st_context /* Ustorm storm context */; struct tstorm_eth_st_context tstorm_st_context /* Tstorm storm context */; struct xstorm_eth_ag_context xstorm_ag_context /* Xstorm aggregative context */; struct tstorm_eth_ag_context tstorm_ag_context /* Tstorm aggregative context */; struct cstorm_eth_ag_context cstorm_ag_context /* Cstorm aggregative context */; struct ustorm_eth_ag_context ustorm_ag_context /* Ustorm aggregative context */; struct timers_block_context timers_context /* Timers block context */; struct xstorm_eth_st_context xstorm_st_context /* Xstorm storm context */; struct cstorm_eth_st_context cstorm_st_context /* Cstorm storm context */; }; /* * union for sgl and raw data. */ union eth_sgl_or_raw_data { uint16_t sgl[8] /* Scatter-gather list of SGEs used by this packet. This list includes the indices of the SGEs. */; uint32_t raw_data[4] /* raw data from Tstorm to the driver. */; }; /* * eth FP end aggregation CQE parameters struct $$KEEP_ENDIANNESS$$ */ struct eth_end_agg_rx_cqe { uint8_t type_error_flags; #define ETH_END_AGG_RX_CQE_TYPE (0x3<<0) /* BitField type_error_flags (use enum eth_rx_cqe_type) */ #define ETH_END_AGG_RX_CQE_TYPE_SHIFT 0 #define ETH_END_AGG_RX_CQE_SGL_RAW_SEL (0x1<<2) /* BitField type_error_flags (use enum eth_rx_fp_sel) */ #define ETH_END_AGG_RX_CQE_SGL_RAW_SEL_SHIFT 2 #define ETH_END_AGG_RX_CQE_RESERVED0 (0x1F<<3) /* BitField type_error_flags */ #define ETH_END_AGG_RX_CQE_RESERVED0_SHIFT 3 uint8_t reserved1; uint8_t queue_index /* The aggregation queue index of this packet */; uint8_t reserved2; uint32_t timestamp_delta /* timestamp delta between first packet to last packet in aggregation */; uint16_t num_of_coalesced_segs /* Num of coalesced segments. */; uint16_t pkt_len /* Packet length */; uint8_t pure_ack_count /* Number of pure acks coalesced. */; uint8_t reserved3; uint16_t reserved4; union eth_sgl_or_raw_data sgl_or_raw_data /* union for sgl and raw data. */; uint32_t reserved5[8]; }; /* * regular eth FP CQE parameters struct $$KEEP_ENDIANNESS$$ */ struct eth_fast_path_rx_cqe { uint8_t type_error_flags; #define ETH_FAST_PATH_RX_CQE_TYPE (0x3<<0) /* BitField type_error_flags (use enum eth_rx_cqe_type) */ #define ETH_FAST_PATH_RX_CQE_TYPE_SHIFT 0 #define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL (0x1<<2) /* BitField type_error_flags (use enum eth_rx_fp_sel) */ #define ETH_FAST_PATH_RX_CQE_SGL_RAW_SEL_SHIFT 2 #define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG (0x1<<3) /* BitField type_error_flags Physical layer errors */ #define ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG_SHIFT 3 #define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG (0x1<<4) /* BitField type_error_flags IP checksum error */ #define ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG_SHIFT 4 #define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG (0x1<<5) /* BitField type_error_flags TCP/UDP checksum error */ #define ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG_SHIFT 5 #define ETH_FAST_PATH_RX_CQE_RESERVED0 (0x3<<6) /* BitField type_error_flags */ #define ETH_FAST_PATH_RX_CQE_RESERVED0_SHIFT 6 uint8_t status_flags; #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE (0x7<<0) /* BitField status_flags (use enum eth_rss_hash_type) */ #define ETH_FAST_PATH_RX_CQE_RSS_HASH_TYPE_SHIFT 0 #define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG (0x1<<3) /* BitField status_flags RSS hashing on/off */ #define ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG_SHIFT 3 #define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG (0x1<<4) /* BitField status_flags if set to 1, this is a broadcast packet */ #define ETH_FAST_PATH_RX_CQE_BROADCAST_FLG_SHIFT 4 #define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG (0x1<<5) /* BitField status_flags if set to 1, the MAC address was matched in the tstorm CAM search */ #define ETH_FAST_PATH_RX_CQE_MAC_MATCH_FLG_SHIFT 5 #define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG (0x1<<6) /* BitField status_flags IP checksum validation was not performed (if packet is not IPv4) */ #define ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG_SHIFT 6 #define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG (0x1<<7) /* BitField status_flags TCP/UDP checksum validation was not performed (if packet is not TCP/UDP or IPv6 extheaders exist) */ #define ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG_SHIFT 7 uint8_t queue_index /* The aggregation queue index of this packet */; uint8_t placement_offset /* Placement offset from the start of the BD, in bytes */; uint32_t rss_hash_result /* RSS toeplitz hash result */; uint16_t vlan_tag /* Ethernet VLAN tag field */; uint16_t pkt_len_or_gro_seg_len /* Packet length (for non-TPA CQE) or GRO Segment Length (for TPA in GRO Mode) otherwise 0 */; uint16_t len_on_bd /* Number of bytes placed on the BD */; struct parsing_flags pars_flags; union eth_sgl_or_raw_data sgl_or_raw_data /* union for sgl and raw data. */; uint32_t reserved1[8]; }; /* * Command for setting classification flags for a client $$KEEP_ENDIANNESS$$ */ struct eth_filter_rules_cmd { uint8_t cmd_general_data; #define ETH_FILTER_RULES_CMD_RX_CMD (0x1<<0) /* BitField cmd_general_data should this cmd be applied for Rx */ #define ETH_FILTER_RULES_CMD_RX_CMD_SHIFT 0 #define ETH_FILTER_RULES_CMD_TX_CMD (0x1<<1) /* BitField cmd_general_data should this cmd be applied for Tx */ #define ETH_FILTER_RULES_CMD_TX_CMD_SHIFT 1 #define ETH_FILTER_RULES_CMD_RESERVED0 (0x3F<<2) /* BitField cmd_general_data */ #define ETH_FILTER_RULES_CMD_RESERVED0_SHIFT 2 uint8_t func_id /* the function id */; uint8_t client_id /* the client id */; uint8_t reserved1; uint16_t state; #define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL (0x1<<0) /* BitField state drop all unicast packets */ #define ETH_FILTER_RULES_CMD_UCAST_DROP_ALL_SHIFT 0 #define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL (0x1<<1) /* BitField state accept all unicast packets (subject to vlan) */ #define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL_SHIFT 1 #define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED (0x1<<2) /* BitField state accept all unmatched unicast packets */ #define ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED_SHIFT 2 #define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL (0x1<<3) /* BitField state drop all multicast packets */ #define ETH_FILTER_RULES_CMD_MCAST_DROP_ALL_SHIFT 3 #define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL (0x1<<4) /* BitField state accept all multicast packets (subject to vlan) */ #define ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL_SHIFT 4 #define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL (0x1<<5) /* BitField state accept all broadcast packets (subject to vlan) */ #define ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL_SHIFT 5 #define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN (0x1<<6) /* BitField state accept packets matched only by MAC (without checking vlan) */ #define ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN_SHIFT 6 #define ETH_FILTER_RULES_CMD_RESERVED2 (0x1FF<<7) /* BitField state */ #define ETH_FILTER_RULES_CMD_RESERVED2_SHIFT 7 uint16_t reserved3; struct regpair reserved4; }; /* * parameters for eth classification filters ramrod $$KEEP_ENDIANNESS$$ */ struct eth_filter_rules_ramrod_data { struct eth_classify_header header; struct eth_filter_rules_cmd rules[FILTER_RULES_COUNT]; }; /* * parameters for eth classification configuration ramrod $$KEEP_ENDIANNESS$$ */ struct eth_general_rules_ramrod_data { struct eth_classify_header header; union eth_classify_rule_cmd rules[CLASSIFY_RULES_COUNT]; }; /* * The data for Halt ramrod */ struct eth_halt_ramrod_data { uint32_t client_id /* id of this client. (5 bits are used) */; uint32_t reserved0; }; /* * destination and source mac address. */ struct eth_mac_addresses { #if defined(__BIG_ENDIAN) uint16_t dst_mid /* destination mac address 16 middle bits */; uint16_t dst_lo /* destination mac address 16 low bits */; #elif defined(__LITTLE_ENDIAN) uint16_t dst_lo /* destination mac address 16 low bits */; uint16_t dst_mid /* destination mac address 16 middle bits */; #endif #if defined(__BIG_ENDIAN) uint16_t src_lo /* source mac address 16 low bits */; uint16_t dst_hi /* destination mac address 16 high bits */; #elif defined(__LITTLE_ENDIAN) uint16_t dst_hi /* destination mac address 16 high bits */; uint16_t src_lo /* source mac address 16 low bits */; #endif #if defined(__BIG_ENDIAN) uint16_t src_hi /* source mac address 16 high bits */; uint16_t src_mid /* source mac address 16 middle bits */; #elif defined(__LITTLE_ENDIAN) uint16_t src_mid /* source mac address 16 middle bits */; uint16_t src_hi /* source mac address 16 high bits */; #endif }; /* * tunneling related data. */ struct eth_tunnel_data { #if defined(__BIG_ENDIAN) uint16_t dst_mid /* destination mac address 16 middle bits */; uint16_t dst_lo /* destination mac address 16 low bits */; #elif defined(__LITTLE_ENDIAN) uint16_t dst_lo /* destination mac address 16 low bits */; uint16_t dst_mid /* destination mac address 16 middle bits */; #endif #if defined(__BIG_ENDIAN) uint16_t fw_ip_hdr_csum /* Fw Ip header checksum (with ALL ip header fields) for the outer IP header */; uint16_t dst_hi /* destination mac address 16 high bits */; #elif defined(__LITTLE_ENDIAN) uint16_t dst_hi /* destination mac address 16 high bits */; uint16_t fw_ip_hdr_csum /* Fw Ip header checksum (with ALL ip header fields) for the outer IP header */; #endif #if defined(__BIG_ENDIAN) uint8_t flags; #define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER (0x1<<0) /* BitField flags Set in case outer IP header is ipV6 */ #define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER_SHIFT 0 #define ETH_TUNNEL_DATA_RESERVED (0x7F<<1) /* BitField flags Should be set with 0 */ #define ETH_TUNNEL_DATA_RESERVED_SHIFT 1 uint8_t ip_hdr_start_inner_w /* Inner IP header offset in WORDs (16-bit) from start of packet */; uint16_t pseudo_csum /* Pseudo checksum with length field=0 */; #elif defined(__LITTLE_ENDIAN) uint16_t pseudo_csum /* Pseudo checksum with length field=0 */; uint8_t ip_hdr_start_inner_w /* Inner IP header offset in WORDs (16-bit) from start of packet */; uint8_t flags; #define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER (0x1<<0) /* BitField flags Set in case outer IP header is ipV6 */ #define ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER_SHIFT 0 #define ETH_TUNNEL_DATA_RESERVED (0x7F<<1) /* BitField flags Should be set with 0 */ #define ETH_TUNNEL_DATA_RESERVED_SHIFT 1 #endif }; /* * union for mac addresses and for tunneling data. considered as tunneling data only if (tunnel_exist == 1). */ union eth_mac_addr_or_tunnel_data { struct eth_mac_addresses mac_addr /* destination and source mac addresses. */; struct eth_tunnel_data tunnel_data /* tunneling related data. */; }; /* * Command for setting multicast classification for a client $$KEEP_ENDIANNESS$$ */ struct eth_multicast_rules_cmd { uint8_t cmd_general_data; #define ETH_MULTICAST_RULES_CMD_RX_CMD (0x1<<0) /* BitField cmd_general_data should this cmd be applied for Rx */ #define ETH_MULTICAST_RULES_CMD_RX_CMD_SHIFT 0 #define ETH_MULTICAST_RULES_CMD_TX_CMD (0x1<<1) /* BitField cmd_general_data should this cmd be applied for Tx */ #define ETH_MULTICAST_RULES_CMD_TX_CMD_SHIFT 1 #define ETH_MULTICAST_RULES_CMD_IS_ADD (0x1<<2) /* BitField cmd_general_data 1 for add rule, 0 for remove rule */ #define ETH_MULTICAST_RULES_CMD_IS_ADD_SHIFT 2 #define ETH_MULTICAST_RULES_CMD_RESERVED0 (0x1F<<3) /* BitField cmd_general_data */ #define ETH_MULTICAST_RULES_CMD_RESERVED0_SHIFT 3 uint8_t func_id /* the function id */; uint8_t bin_id /* the bin to add this function to (0-255) */; uint8_t engine_id /* the approximate multicast engine id */; uint32_t reserved2; struct regpair reserved3; }; /* * parameters for multicast classification ramrod $$KEEP_ENDIANNESS$$ */ struct eth_multicast_rules_ramrod_data { struct eth_classify_header header; struct eth_multicast_rules_cmd rules[MULTICAST_RULES_COUNT]; }; /* * Place holder for ramrods protocol specific data */ struct ramrod_data { uint32_t data_lo; uint32_t data_hi; }; /* * union for ramrod data for Ethernet protocol (CQE) (force size of 16 bits) */ union eth_ramrod_data { struct ramrod_data general; }; /* * RSS toeplitz hash type, as reported in CQE */ enum eth_rss_hash_type { DEFAULT_HASH_TYPE, IPV4_HASH_TYPE, TCP_IPV4_HASH_TYPE, IPV6_HASH_TYPE, TCP_IPV6_HASH_TYPE, VLAN_PRI_HASH_TYPE, E1HOV_PRI_HASH_TYPE, DSCP_HASH_TYPE, MAX_ETH_RSS_HASH_TYPE}; /* * Ethernet RSS mode */ enum eth_rss_mode { ETH_RSS_MODE_DISABLED, ETH_RSS_MODE_ESX51 /* RSS mode for Vmware ESX 5.1 (Only do RSS if packet is UDP with dst port that matches the UDP 4-tuble Destination Port mask and value) */, ETH_RSS_MODE_REGULAR /* Regular (ndis-like) RSS */, ETH_RSS_MODE_VLAN_PRI /* RSS based on inner-vlan priority field */, ETH_RSS_MODE_E1HOV_PRI /* RSS based on outer-vlan priority field */, ETH_RSS_MODE_IP_DSCP /* RSS based on IPv4 DSCP field */, MAX_ETH_RSS_MODE}; /* * parameters for RSS update ramrod (E2) $$KEEP_ENDIANNESS$$ */ struct eth_rss_update_ramrod_data { uint8_t rss_engine_id; uint8_t capabilities; #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY (0x1<<0) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV4 2-tupple capability */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY_SHIFT 0 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY (0x1<<1) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV4 4-tupple capability for TCP */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY_SHIFT 1 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY (0x1<<2) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV4 4-tupple capability for UDP */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY_SHIFT 2 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY (0x1<<3) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV6 2-tupple capability */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY_SHIFT 3 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY (0x1<<4) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV6 4-tupple capability for TCP */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY_SHIFT 4 #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY (0x1<<5) /* BitField capabilitiesFunction RSS capabilities configuration of the IpV6 4-tupple capability for UDP */ #define ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY_SHIFT 5 #define ETH_RSS_UPDATE_RAMROD_DATA_EN_5_TUPLE_CAPABILITY (0x1<<6) /* BitField capabilitiesFunction RSS capabilities configuration of the 5-tupple capability */ #define ETH_RSS_UPDATE_RAMROD_DATA_EN_5_TUPLE_CAPABILITY_SHIFT 6 #define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY (0x1<<7) /* BitField capabilitiesFunction RSS capabilities if set update the rss keys */ #define ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY_SHIFT 7 uint8_t rss_result_mask /* The mask for the lower byte of RSS result - defines which section of the indirection table will be used. To enable all table put here 0x7F */; uint8_t rss_mode /* The RSS mode for this function */; uint16_t udp_4tuple_dst_port_mask /* If UDP 4-tuple enabled, packets that match the mask and value are 4-tupled, the rest are 2-tupled. (Set to 0 to match all) */; uint16_t udp_4tuple_dst_port_value /* If UDP 4-tuple enabled, packets that match the mask and value are 4-tupled, the rest are 2-tupled. (Set to 0 to match all) */; uint8_t indirection_table[T_ETH_INDIRECTION_TABLE_SIZE] /* RSS indirection table */; uint32_t rss_key[T_ETH_RSS_KEY] /* RSS key supplied as by OS */; uint32_t echo; uint32_t reserved3; }; /* * The eth Rx Buffer Descriptor */ struct eth_rx_bd { uint32_t addr_lo /* Single continuous buffer low pointer */; uint32_t addr_hi /* Single continuous buffer high pointer */; }; /* * Eth Rx Cqe structure- general structure for ramrods $$KEEP_ENDIANNESS$$ */ struct common_ramrod_eth_rx_cqe { uint8_t ramrod_type; #define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x3<<0) /* BitField ramrod_type (use enum eth_rx_cqe_type) */ #define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0 #define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<2) /* BitField ramrod_type */ #define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 2 #define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x1F<<3) /* BitField ramrod_type */ #define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 3 uint8_t conn_type /* only 3 bits are used */; uint16_t reserved1 /* protocol specific data */; uint32_t conn_and_cmd_data; #define COMMON_RAMROD_ETH_RX_CQE_CID (0xFFFFFF<<0) /* BitField conn_and_cmd_data */ #define COMMON_RAMROD_ETH_RX_CQE_CID_SHIFT 0 #define COMMON_RAMROD_ETH_RX_CQE_CMD_ID (0xFF<<24) /* BitField conn_and_cmd_data command id of the ramrod- use RamrodCommandIdEnum */ #define COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT 24 struct ramrod_data protocol_data /* protocol specific data */; uint32_t echo; uint32_t reserved2[11]; }; /* * Rx Last CQE in page (in ETH) */ struct eth_rx_cqe_next_page { uint32_t addr_lo /* Next page low pointer */; uint32_t addr_hi /* Next page high pointer */; uint32_t reserved[14]; }; /* * union for all eth rx cqe types (fix their sizes) */ union eth_rx_cqe { struct eth_fast_path_rx_cqe fast_path_cqe; struct common_ramrod_eth_rx_cqe ramrod_cqe; struct eth_rx_cqe_next_page next_page_cqe; struct eth_end_agg_rx_cqe end_agg_cqe; }; /* * Values for RX ETH CQE type field */ enum eth_rx_cqe_type { RX_ETH_CQE_TYPE_ETH_FASTPATH /* Fast path CQE */, RX_ETH_CQE_TYPE_ETH_RAMROD /* Slow path CQE */, RX_ETH_CQE_TYPE_ETH_START_AGG /* Fast path CQE */, RX_ETH_CQE_TYPE_ETH_STOP_AGG /* Slow path CQE */, MAX_ETH_RX_CQE_TYPE}; /* * Type of SGL/Raw field in ETH RX fast path CQE */ enum eth_rx_fp_sel { ETH_FP_CQE_REGULAR /* Regular CQE- no extra data */, ETH_FP_CQE_RAW /* Extra data is raw data- iscsi OOO */, MAX_ETH_RX_FP_SEL}; /* * The eth Rx SGE Descriptor */ struct eth_rx_sge { uint32_t addr_lo /* Single continuous buffer low pointer */; uint32_t addr_hi /* Single continuous buffer high pointer */; }; /* * common data for all protocols $$KEEP_ENDIANNESS$$ */ struct spe_hdr { uint32_t conn_and_cmd_data; #define SPE_HDR_CID (0xFFFFFF<<0) /* BitField conn_and_cmd_data */ #define SPE_HDR_CID_SHIFT 0 #define SPE_HDR_CMD_ID (0xFF<<24) /* BitField conn_and_cmd_data command id of the ramrod- use enum common_spqe_cmd_id/eth_spqe_cmd_id/toe_spqe_cmd_id */ #define SPE_HDR_CMD_ID_SHIFT 24 uint16_t type; #define SPE_HDR_CONN_TYPE (0xFF<<0) /* BitField type connection type. (3 bits are used) (use enum connection_type) */ #define SPE_HDR_CONN_TYPE_SHIFT 0 #define SPE_HDR_FUNCTION_ID (0xFF<<8) /* BitField type */ #define SPE_HDR_FUNCTION_ID_SHIFT 8 uint16_t reserved1; }; /* * specific data for ethernet slow path element */ union eth_specific_data { uint8_t protocol_data[8] /* to fix this structure size to 8 bytes */; struct regpair client_update_ramrod_data /* The address of the data for client update ramrod */; struct regpair client_init_ramrod_init_data /* The data for client setup ramrod */; struct eth_halt_ramrod_data halt_ramrod_data /* Includes the client id to be deleted */; struct regpair update_data_addr /* physical address of the eth_rss_update_ramrod_data struct, as allocated by the driver */; struct eth_common_ramrod_data common_ramrod_data /* The data contain client ID need to the ramrod */; struct regpair classify_cfg_addr /* physical address of the eth_classify_rules_ramrod_data struct, as allocated by the driver */; struct regpair filter_cfg_addr /* physical address of the eth_filter_cfg_ramrod_data struct, as allocated by the driver */; struct regpair mcast_cfg_addr /* physical address of the eth_mcast_cfg_ramrod_data struct, as allocated by the driver */; }; /* * Ethernet slow path element */ struct eth_spe { struct spe_hdr hdr /* common data for all protocols */; union eth_specific_data data /* data specific to ethernet protocol */; }; /* * Ethernet command ID for slow path elements */ enum eth_spqe_cmd_id { RAMROD_CMD_ID_ETH_UNUSED, RAMROD_CMD_ID_ETH_CLIENT_SETUP /* Setup a new L2 client */, RAMROD_CMD_ID_ETH_HALT /* Halt an L2 client */, RAMROD_CMD_ID_ETH_FORWARD_SETUP /* Setup a new FW channel */, RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP /* Setup a new Tx only queue */, RAMROD_CMD_ID_ETH_CLIENT_UPDATE /* Update an L2 client configuration */, RAMROD_CMD_ID_ETH_EMPTY /* Empty ramrod - used to synchronize iSCSI OOO */, RAMROD_CMD_ID_ETH_TERMINATE /* Terminate an L2 client */, RAMROD_CMD_ID_ETH_TPA_UPDATE /* update the tpa roles in L2 client */, RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES /* Add/remove classification filters for L2 client (in E2/E3 only) */, RAMROD_CMD_ID_ETH_FILTER_RULES /* Add/remove classification filters for L2 client (in E2/E3 only) */, RAMROD_CMD_ID_ETH_MULTICAST_RULES /* Add/remove multicast classification bin (in E2/E3 only) */, RAMROD_CMD_ID_ETH_RSS_UPDATE /* Update RSS configuration */, RAMROD_CMD_ID_ETH_SET_MAC /* Update RSS configuration */, MAX_ETH_SPQE_CMD_ID}; /* * eth tpa update command */ enum eth_tpa_update_command { TPA_UPDATE_NONE_COMMAND /* nop command */, TPA_UPDATE_ENABLE_COMMAND /* enable command */, TPA_UPDATE_DISABLE_COMMAND /* disable command */, MAX_ETH_TPA_UPDATE_COMMAND}; /* * In case of LSO over IPv4 tunnel, whether to increment IP ID on external IP header or internal IP header */ enum eth_tunnel_lso_inc_ip_id { EXT_HEADER /* Increment IP ID of external header (HW works on external, FW works on internal */, INT_HEADER /* Increment IP ID of internal header (HW works on internal, FW works on external */, MAX_ETH_TUNNEL_LSO_INC_IP_ID}; /* * In case tunnel exist and L4 checksum offload (or outer ip header checksum), the pseudo checksum location, on packet or on BD. */ enum eth_tunnel_non_lso_csum_location { CSUM_ON_PKT /* checksum is on the packet. */, CSUM_ON_BD /* checksum is on the BD. */, MAX_ETH_TUNNEL_NON_LSO_CSUM_LOCATION}; /* * Tx regular BD structure $$KEEP_ENDIANNESS$$ */ struct eth_tx_bd { uint32_t addr_lo /* Single continuous buffer low pointer */; uint32_t addr_hi /* Single continuous buffer high pointer */; uint16_t total_pkt_bytes /* Size of the entire packet, valid for non-LSO packets */; uint16_t nbytes /* Size of the data represented by the BD */; uint8_t reserved[4] /* keeps same size as other eth tx bd types */; }; /* * structure for easy accessibility to assembler */ struct eth_tx_bd_flags { uint8_t as_bitfield; #define ETH_TX_BD_FLAGS_IP_CSUM (0x1<<0) /* BitField as_bitfield IP CKSUM flag,Relevant in START */ #define ETH_TX_BD_FLAGS_IP_CSUM_SHIFT 0 #define ETH_TX_BD_FLAGS_L4_CSUM (0x1<<1) /* BitField as_bitfield L4 CKSUM flag,Relevant in START */ #define ETH_TX_BD_FLAGS_L4_CSUM_SHIFT 1 #define ETH_TX_BD_FLAGS_VLAN_MODE (0x3<<2) /* BitField as_bitfield 00 - no vlan; 01 - inband Vlan; 10 outband Vlan (use enum eth_tx_vlan_type) */ #define ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT 2 #define ETH_TX_BD_FLAGS_START_BD (0x1<<4) /* BitField as_bitfield Start of packet BD */ #define ETH_TX_BD_FLAGS_START_BD_SHIFT 4 #define ETH_TX_BD_FLAGS_IS_UDP (0x1<<5) /* BitField as_bitfield flag that indicates that the current packet is a udp packet */ #define ETH_TX_BD_FLAGS_IS_UDP_SHIFT 5 #define ETH_TX_BD_FLAGS_SW_LSO (0x1<<6) /* BitField as_bitfield LSO flag, Relevant in START */ #define ETH_TX_BD_FLAGS_SW_LSO_SHIFT 6 #define ETH_TX_BD_FLAGS_IPV6 (0x1<<7) /* BitField as_bitfield set in case ipV6 packet, Relevant in START */ #define ETH_TX_BD_FLAGS_IPV6_SHIFT 7 }; /* * The eth Tx Buffer Descriptor $$KEEP_ENDIANNESS$$ */ struct eth_tx_start_bd { uint64_t addr; uint16_t nbd /* Num of BDs in packet: include parsInfoBD, Relevant in START(only in Everest) */; uint16_t nbytes /* Size of the data represented by the BD */; uint16_t vlan_or_ethertype /* Vlan structure: vlan_id is in lsb, then cfi and then priority vlan_id 12 bits (lsb), cfi 1 bit, priority 3 bits. In E2, this field should be set with etherType for VFs with no vlan */; struct eth_tx_bd_flags bd_flags; uint8_t general_data; #define ETH_TX_START_BD_HDR_NBDS (0xF<<0) /* BitField general_data contains the number of BDs that contain Ethernet/IP/TCP headers, for full/partial LSO modes */ #define ETH_TX_START_BD_HDR_NBDS_SHIFT 0 #define ETH_TX_START_BD_FORCE_VLAN_MODE (0x1<<4) /* BitField general_data force vlan mode according to bds (vlan mode can change accroding to global configuration) */ #define ETH_TX_START_BD_FORCE_VLAN_MODE_SHIFT 4 #define ETH_TX_START_BD_PARSE_NBDS (0x3<<5) /* BitField general_data Determines the number of parsing BDs in packet. Number of parsing BDs in packet is (parse_nbds+1). */ #define ETH_TX_START_BD_PARSE_NBDS_SHIFT 5 #define ETH_TX_START_BD_TUNNEL_EXIST (0x1<<7) /* BitField general_data set in case of tunneling encapsulated packet */ #define ETH_TX_START_BD_TUNNEL_EXIST_SHIFT 7 }; /* * Tx parsing BD structure for ETH E1h $$KEEP_ENDIANNESS$$ */ struct eth_tx_parse_bd_e1x { uint16_t global_data; #define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W (0xF<<0) /* BitField global_data IP header Offset in WORDs from start of packet */ #define ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT 0 #define ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE (0x3<<4) /* BitField global_data marks ethernet address type (use enum eth_addr_type) */ #define ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT 4 #define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN (0x1<<6) /* BitField global_data */ #define ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN_SHIFT 6 #define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN (0x1<<7) /* BitField global_data */ #define ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT 7 #define ETH_TX_PARSE_BD_E1X_NS_FLG (0x1<<8) /* BitField global_data an optional addition to ECN that protects against accidental or malicious concealment of marked packets from the TCP sender. */ #define ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT 8 #define ETH_TX_PARSE_BD_E1X_RESERVED0 (0x7F<<9) /* BitField global_data reserved bit, should be set with 0 */ #define ETH_TX_PARSE_BD_E1X_RESERVED0_SHIFT 9 uint8_t tcp_flags; #define ETH_TX_PARSE_BD_E1X_FIN_FLG (0x1<<0) /* BitField tcp_flagsState flags End of data flag */ #define ETH_TX_PARSE_BD_E1X_FIN_FLG_SHIFT 0 #define ETH_TX_PARSE_BD_E1X_SYN_FLG (0x1<<1) /* BitField tcp_flagsState flags Synchronize sequence numbers flag */ #define ETH_TX_PARSE_BD_E1X_SYN_FLG_SHIFT 1 #define ETH_TX_PARSE_BD_E1X_RST_FLG (0x1<<2) /* BitField tcp_flagsState flags Reset connection flag */ #define ETH_TX_PARSE_BD_E1X_RST_FLG_SHIFT 2 #define ETH_TX_PARSE_BD_E1X_PSH_FLG (0x1<<3) /* BitField tcp_flagsState flags Push flag */ #define ETH_TX_PARSE_BD_E1X_PSH_FLG_SHIFT 3 #define ETH_TX_PARSE_BD_E1X_ACK_FLG (0x1<<4) /* BitField tcp_flagsState flags Acknowledgment number valid flag */ #define ETH_TX_PARSE_BD_E1X_ACK_FLG_SHIFT 4 #define ETH_TX_PARSE_BD_E1X_URG_FLG (0x1<<5) /* BitField tcp_flagsState flags Urgent pointer valid flag */ #define ETH_TX_PARSE_BD_E1X_URG_FLG_SHIFT 5 #define ETH_TX_PARSE_BD_E1X_ECE_FLG (0x1<<6) /* BitField tcp_flagsState flags ECN-Echo */ #define ETH_TX_PARSE_BD_E1X_ECE_FLG_SHIFT 6 #define ETH_TX_PARSE_BD_E1X_CWR_FLG (0x1<<7) /* BitField tcp_flagsState flags Congestion Window Reduced */ #define ETH_TX_PARSE_BD_E1X_CWR_FLG_SHIFT 7 uint8_t ip_hlen_w /* IP header length in WORDs */; uint16_t total_hlen_w /* IP+TCP+ETH */; uint16_t tcp_pseudo_csum /* Checksum of pseudo header with length field=0 */; uint16_t lso_mss /* for LSO mode */; uint16_t ip_id /* for LSO mode */; uint32_t tcp_send_seq /* for LSO mode */; }; /* * Tx parsing BD structure for ETH E2 $$KEEP_ENDIANNESS$$ */ struct eth_tx_parse_bd_e2 { union eth_mac_addr_or_tunnel_data data /* union for mac addresses and for tunneling data. considered as tunneling data only if (tunnel_exist == 1). */; uint32_t parsing_data; #define ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W (0x7FF<<0) /* BitField parsing_data TCP/UDP header Offset in WORDs from start of packet */ #define ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT 0 #define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW (0xF<<11) /* BitField parsing_data TCP header size in DOUBLE WORDS */ #define ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT 11 #define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR (0x1<<15) /* BitField parsing_data a flag to indicate an ipv6 packet with extension headers. If set on LSO packet, pseudo CS should be placed in TCP CS field without length field */ #define ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR_SHIFT 15 #define ETH_TX_PARSE_BD_E2_LSO_MSS (0x3FFF<<16) /* BitField parsing_data for LSO mode */ #define ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT 16 #define ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE (0x3<<30) /* BitField parsing_data marks ethernet address type (use enum eth_addr_type) */ #define ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT 30 }; /* * Tx 2nd parsing BD structure for ETH packet $$KEEP_ENDIANNESS$$ */ struct eth_tx_parse_2nd_bd { uint16_t global_data; #define ETH_TX_PARSE_2ND_BD_IP_HDR_START_OUTER_W (0xF<<0) /* BitField global_data Outer IP header offset in WORDs (16-bit) from start of packet */ #define ETH_TX_PARSE_2ND_BD_IP_HDR_START_OUTER_W_SHIFT 0 #define ETH_TX_PARSE_2ND_BD_RESERVED0 (0x1<<4) /* BitField global_data should be set with 0 */ #define ETH_TX_PARSE_2ND_BD_RESERVED0_SHIFT 4 #define ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN (0x1<<5) /* BitField global_data */ #define ETH_TX_PARSE_2ND_BD_LLC_SNAP_EN_SHIFT 5 #define ETH_TX_PARSE_2ND_BD_NS_FLG (0x1<<6) /* BitField global_data an optional addition to ECN that protects against accidental or malicious concealment of marked packets from the TCP sender. */ #define ETH_TX_PARSE_2ND_BD_NS_FLG_SHIFT 6 #define ETH_TX_PARSE_2ND_BD_TUNNEL_UDP_EXIST (0x1<<7) /* BitField global_data Set in case UDP header exists in tunnel outer hedears. */ #define ETH_TX_PARSE_2ND_BD_TUNNEL_UDP_EXIST_SHIFT 7 #define ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W (0x1F<<8) /* BitField global_data Outer IP header length in WORDs (16-bit). Valid only for IpV4. */ #define ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W_SHIFT 8 #define ETH_TX_PARSE_2ND_BD_RESERVED1 (0x7<<13) /* BitField global_data should be set with 0 */ #define ETH_TX_PARSE_2ND_BD_RESERVED1_SHIFT 13 uint16_t reserved2; uint8_t tcp_flags; #define ETH_TX_PARSE_2ND_BD_FIN_FLG (0x1<<0) /* BitField tcp_flagsState flags End of data flag */ #define ETH_TX_PARSE_2ND_BD_FIN_FLG_SHIFT 0 #define ETH_TX_PARSE_2ND_BD_SYN_FLG (0x1<<1) /* BitField tcp_flagsState flags Synchronize sequence numbers flag */ #define ETH_TX_PARSE_2ND_BD_SYN_FLG_SHIFT 1 #define ETH_TX_PARSE_2ND_BD_RST_FLG (0x1<<2) /* BitField tcp_flagsState flags Reset connection flag */ #define ETH_TX_PARSE_2ND_BD_RST_FLG_SHIFT 2 #define ETH_TX_PARSE_2ND_BD_PSH_FLG (0x1<<3) /* BitField tcp_flagsState flags Push flag */ #define ETH_TX_PARSE_2ND_BD_PSH_FLG_SHIFT 3 #define ETH_TX_PARSE_2ND_BD_ACK_FLG (0x1<<4) /* BitField tcp_flagsState flags Acknowledgment number valid flag */ #define ETH_TX_PARSE_2ND_BD_ACK_FLG_SHIFT 4 #define ETH_TX_PARSE_2ND_BD_URG_FLG (0x1<<5) /* BitField tcp_flagsState flags Urgent pointer valid flag */ #define ETH_TX_PARSE_2ND_BD_URG_FLG_SHIFT 5 #define ETH_TX_PARSE_2ND_BD_ECE_FLG (0x1<<6) /* BitField tcp_flagsState flags ECN-Echo */ #define ETH_TX_PARSE_2ND_BD_ECE_FLG_SHIFT 6 #define ETH_TX_PARSE_2ND_BD_CWR_FLG (0x1<<7) /* BitField tcp_flagsState flags Congestion Window Reduced */ #define ETH_TX_PARSE_2ND_BD_CWR_FLG_SHIFT 7 uint8_t reserved3; uint8_t tunnel_udp_hdr_start_w /* Offset (in WORDs) from start of packet to tunnel UDP header. (if exist) */; uint8_t fw_ip_hdr_to_payload_w /* In IpV4, the length (in WORDs) from the FW IpV4 header start to the payload start. In IpV6, the length (in WORDs) from the FW IpV6 header end to the payload start. However, if extension headers are included, their length is counted here as well. */; uint16_t fw_ip_csum_wo_len_flags_frag /* For the IP header which is set by the FW, the IP checksum without length, flags and fragment offset. */; uint16_t hw_ip_id /* The IP ID to be set by HW for LSO packets in tunnel mode. */; uint32_t tcp_send_seq /* The TCP sequence number for LSO packets. */; }; /* * The last BD in the BD memory will hold a pointer to the next BD memory */ struct eth_tx_next_bd { uint32_t addr_lo /* Single continuous buffer low pointer */; uint32_t addr_hi /* Single continuous buffer high pointer */; uint8_t reserved[8] /* keeps same size as other eth tx bd types */; }; /* * union for 4 Bd types */ union eth_tx_bd_types { struct eth_tx_start_bd start_bd /* the first bd in a packets */; struct eth_tx_bd reg_bd /* the common bd */; struct eth_tx_parse_bd_e1x parse_bd_e1x /* parsing info BD for e1/e1h */; struct eth_tx_parse_bd_e2 parse_bd_e2 /* parsing info BD for e2 */; struct eth_tx_parse_2nd_bd parse_2nd_bd /* 2nd parsing info BD */; struct eth_tx_next_bd next_bd /* Bd that contains the address of the next page */; }; /* * array of 13 bds as appears in the eth xstorm context */ struct eth_tx_bds_array { union eth_tx_bd_types bds[13]; }; /* * VLAN mode on TX BDs */ enum eth_tx_vlan_type { X_ETH_NO_VLAN, X_ETH_OUTBAND_VLAN, X_ETH_INBAND_VLAN, X_ETH_FW_ADDED_VLAN /* Driver should not use this! */, MAX_ETH_TX_VLAN_TYPE}; /* * Ethernet VLAN filtering mode in E1x */ enum eth_vlan_filter_mode { ETH_VLAN_FILTER_ANY_VLAN /* Dont filter by vlan */, ETH_VLAN_FILTER_SPECIFIC_VLAN /* Only the vlan_id is allowed */, ETH_VLAN_FILTER_CLASSIFY /* Vlan will be added to CAM for classification */, MAX_ETH_VLAN_FILTER_MODE}; /* * MAC filtering configuration command header $$KEEP_ENDIANNESS$$ */ struct mac_configuration_hdr { uint8_t length /* number of entries valid in this command (6 bits) */; uint8_t offset /* offset of the first entry in the list */; uint16_t client_id /* the client id which this ramrod is sent on. 5b is used. */; uint32_t echo /* echo value to be sent to driver on event ring */; }; /* * MAC address in list for ramrod $$KEEP_ENDIANNESS$$ */ struct mac_configuration_entry { uint16_t lsb_mac_addr /* 2 LSB of MAC address (should be given in big endien - driver should do hton to this number!!!) */; uint16_t middle_mac_addr /* 2 middle bytes of MAC address (should be given in big endien - driver should do hton to this number!!!) */; uint16_t msb_mac_addr /* 2 MSB of MAC address (should be given in big endien - driver should do hton to this number!!!) */; uint16_t vlan_id /* The inner vlan id (12b). Used either in vlan_in_cam for mac_valn pair or for vlan filtering */; uint8_t pf_id /* The pf id, for multi function mode */; uint8_t flags; #define MAC_CONFIGURATION_ENTRY_ACTION_TYPE (0x1<<0) /* BitField flags configures the action to be done in cam (used only is slow path handlers) (use enum set_mac_action_type) */ #define MAC_CONFIGURATION_ENTRY_ACTION_TYPE_SHIFT 0 #define MAC_CONFIGURATION_ENTRY_RDMA_MAC (0x1<<1) /* BitField flags If set, this MAC also belongs to RDMA client */ #define MAC_CONFIGURATION_ENTRY_RDMA_MAC_SHIFT 1 #define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE (0x3<<2) /* BitField flags (use enum eth_vlan_filter_mode) */ #define MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE_SHIFT 2 #define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL (0x1<<4) /* BitField flags BitField flags 0 - cant remove vlan 1 - can remove vlan. relevant only to everest1 */ #define MAC_CONFIGURATION_ENTRY_OVERRIDE_VLAN_REMOVAL_SHIFT 4 #define MAC_CONFIGURATION_ENTRY_BROADCAST (0x1<<5) /* BitField flags BitField flags 0 - not broadcast 1 - broadcast. relevant only to everest1 */ #define MAC_CONFIGURATION_ENTRY_BROADCAST_SHIFT 5 #define MAC_CONFIGURATION_ENTRY_RESERVED1 (0x3<<6) /* BitField flags */ #define MAC_CONFIGURATION_ENTRY_RESERVED1_SHIFT 6 uint16_t reserved0; uint32_t clients_bit_vector /* Bit vector for the clients which should receive this MAC. */; }; /* * MAC filtering configuration command */ struct mac_configuration_cmd { struct mac_configuration_hdr hdr /* header */; struct mac_configuration_entry config_table[64] /* table of 64 MAC configuration entries: addresses and target table entries */; }; /* * Set-MAC command type (in E1x) */ enum set_mac_action_type { T_ETH_MAC_COMMAND_INVALIDATE, T_ETH_MAC_COMMAND_SET, MAX_SET_MAC_ACTION_TYPE}; /* * Ethernet TPA Modes */ enum tpa_mode { TPA_LRO /* LRO mode TPA */, TPA_GRO /* GRO mode TPA */, MAX_TPA_MODE}; /* * tpa update ramrod data $$KEEP_ENDIANNESS$$ */ struct tpa_update_ramrod_data { uint8_t update_ipv4 /* none, enable or disable */; uint8_t update_ipv6 /* none, enable or disable */; uint8_t client_id /* client init flow control data */; uint8_t max_tpa_queues /* maximal TPA queues allowed for this client */; uint8_t max_sges_for_packet /* The maximal number of SGEs that can be used for one packet. depends on MTU and SGE size. must be 0 if SGEs are disabled */; uint8_t complete_on_both_clients /* If set and the client has different sp_client, completion will be sent to both rings */; uint8_t dont_verify_rings_pause_thr_flg /* If set, the rings pause thresholds will not be verified by firmware. */; uint8_t tpa_mode /* TPA mode to use (LRO or GRO) */; uint16_t sge_buff_size /* Size of the buffers pointed by SGEs */; uint16_t max_agg_size /* maximal size for the aggregated TPA packets, reprted by the host */; uint32_t sge_page_base_lo /* The address to fetch the next sges from (low) */; uint32_t sge_page_base_hi /* The address to fetch the next sges from (high) */; uint16_t sge_pause_thr_low /* number of remaining sges under which, we send pause message */; uint16_t sge_pause_thr_high /* number of remaining sges above which, we send un-pause message */; }; /* * approximate-match multicast filtering for E1H per function in Tstorm */ struct tstorm_eth_approximate_match_multicast_filtering { uint32_t mcast_add_hash_bit_array[8] /* Bit array for multicast hash filtering.Each bit supports a hash function result if to accept this multicast dst address. */; }; /* * Common configuration parameters per function in Tstorm $$KEEP_ENDIANNESS$$ */ struct tstorm_eth_function_common_config { uint16_t config_flags; #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY (0x1<<0) /* BitField config_flagsGeneral configuration flags configuration of the port RSS IpV4 2-tupple capability */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY_SHIFT 0 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY (0x1<<1) /* BitField config_flagsGeneral configuration flags configuration of the port RSS IpV4 4-tupple capability */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY_SHIFT 1 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY (0x1<<2) /* BitField config_flagsGeneral configuration flags configuration of the port RSS IpV4 2-tupple capability */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY_SHIFT 2 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY (0x1<<3) /* BitField config_flagsGeneral configuration flags configuration of the port RSS IpV6 4-tupple capability */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY_SHIFT 3 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE (0x7<<4) /* BitField config_flagsGeneral configuration flags RSS mode of operation (use enum eth_rss_mode) */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT 4 #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE (0x1<<7) /* BitField config_flagsGeneral configuration flags 0 - Dont filter by vlan, 1 - Filter according to the vlans specificied in mac_filter_config */ #define TSTORM_ETH_FUNCTION_COMMON_CONFIG_VLAN_FILTERING_ENABLE_SHIFT 7 #define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0 (0xFF<<8) /* BitField config_flagsGeneral configuration flags */ #define __TSTORM_ETH_FUNCTION_COMMON_CONFIG_RESERVED0_SHIFT 8 uint8_t rss_result_mask /* The mask for the lower byte of RSS result - defines which section of the indirection table will be used. To enable all table put here 0x7F */; uint8_t reserved1; uint16_t vlan_id[2] /* VLANs of this function. VLAN filtering is determine according to vlan_filtering_enable. */; }; /* * MAC filtering configuration parameters per port in Tstorm $$KEEP_ENDIANNESS$$ */ struct tstorm_eth_mac_filter_config { uint32_t ucast_drop_all /* bit vector in which the clients which drop all unicast packets are set */; uint32_t ucast_accept_all /* bit vector in which clients that accept all unicast packets are set */; uint32_t mcast_drop_all /* bit vector in which the clients which drop all multicast packets are set */; uint32_t mcast_accept_all /* bit vector in which clients that accept all multicast packets are set */; uint32_t bcast_accept_all /* bit vector in which clients that accept all broadcast packets are set */; uint32_t vlan_filter[2] /* bit vector for VLAN filtering. Clients which enforce filtering of vlan[x] should be marked in vlan_filter[x]. The primary vlan is taken from the CAM target table. */; uint32_t unmatched_unicast /* bit vector in which clients that accept unmatched unicast packets are set */; }; /* * tx only queue init ramrod data $$KEEP_ENDIANNESS$$ */ struct tx_queue_init_ramrod_data { struct client_init_general_data general /* client init general data */; struct client_init_tx_data tx /* client init tx data */; }; /* * Three RX producers for ETH */ union ustorm_eth_rx_producers { struct { #if defined(__BIG_ENDIAN) uint16_t bd_prod /* Producer of the RX BD ring */; uint16_t cqe_prod /* Producer of the RX CQE ring */; #elif defined(__LITTLE_ENDIAN) uint16_t cqe_prod /* Producer of the RX CQE ring */; uint16_t bd_prod /* Producer of the RX BD ring */; #endif #if defined(__BIG_ENDIAN) uint16_t reserved; uint16_t sge_prod /* Producer of the RX SGE ring */; #elif defined(__LITTLE_ENDIAN) uint16_t sge_prod /* Producer of the RX SGE ring */; uint16_t reserved; #endif } prod; uint32_t raw_data[2]; }; /* * The data afex vif list ramrod need $$KEEP_ENDIANNESS$$ */ struct afex_vif_list_ramrod_data { uint8_t afex_vif_list_command /* set get, clear all a VIF list id defined by enum vif_list_rule_kind */; uint8_t func_bit_map /* the function bit map to set */; uint16_t vif_list_index /* the VIF list, in a per pf vector to add this function to */; uint8_t func_to_clear /* the func id to clear in case of clear func mode */; uint8_t echo; uint16_t reserved1; }; /* * cfc delete event data $$KEEP_ENDIANNESS$$ */ struct cfc_del_event_data { uint32_t cid /* cid of deleted connection */; uint32_t reserved0; uint32_t reserved1; }; /* * per-port SAFC demo variables */ struct cmng_flags_per_port { uint32_t cmng_enables; #define CMNG_FLAGS_PER_PORT_FAIRNESS_VN (0x1<<0) /* BitField cmng_enablesenables flag for fairness and rate shaping between protocols, vnics and COSes if set, enable fairness between vnics */ #define CMNG_FLAGS_PER_PORT_FAIRNESS_VN_SHIFT 0 #define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN (0x1<<1) /* BitField cmng_enablesenables flag for fairness and rate shaping between protocols, vnics and COSes if set, enable rate shaping between vnics */ #define CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN_SHIFT 1 #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS (0x1<<2) /* BitField cmng_enablesenables flag for fairness and rate shaping between protocols, vnics and COSes if set, enable fairness between COSes */ #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_SHIFT 2 #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE (0x1<<3) /* BitField cmng_enablesenables flag for fairness and rate shaping between protocols, vnics and COSes (use enum fairness_mode) */ #define CMNG_FLAGS_PER_PORT_FAIRNESS_COS_MODE_SHIFT 3 #define __CMNG_FLAGS_PER_PORT_RESERVED0 (0xFFFFFFF<<4) /* BitField cmng_enablesenables flag for fairness and rate shaping between protocols, vnics and COSes reserved */ #define __CMNG_FLAGS_PER_PORT_RESERVED0_SHIFT 4 uint32_t __reserved1; }; /* * per-port rate shaping variables */ struct rate_shaping_vars_per_port { uint32_t rs_periodic_timeout /* timeout of periodic timer */; uint32_t rs_threshold /* threshold, below which we start to stop queues */; }; /* * per-port fairness variables */ struct fairness_vars_per_port { uint32_t upper_bound /* Quota for a protocol/vnic */; uint32_t fair_threshold /* almost-empty threshold */; uint32_t fairness_timeout /* timeout of fairness timer */; uint32_t reserved0; }; /* * per-port SAFC variables */ struct safc_struct_per_port { #if defined(__BIG_ENDIAN) uint16_t __reserved1; uint8_t __reserved0; uint8_t safc_timeout_usec /* timeout to stop queues on SAFC pause command */; #elif defined(__LITTLE_ENDIAN) uint8_t safc_timeout_usec /* timeout to stop queues on SAFC pause command */; uint8_t __reserved0; uint16_t __reserved1; #endif uint8_t cos_to_traffic_types[MAX_COS_NUMBER] /* translate cos to service traffics types */; uint16_t cos_to_pause_mask[NUM_OF_SAFC_BITS] /* QM pause mask for each class of service in the SAFC frame */; }; /* * Per-port congestion management variables */ struct cmng_struct_per_port { struct rate_shaping_vars_per_port rs_vars; struct fairness_vars_per_port fair_vars; struct safc_struct_per_port safc_vars; struct cmng_flags_per_port flags; }; /* * a single rate shaping counter. can be used as protocol or vnic counter */ struct rate_shaping_counter { uint32_t quota /* Quota for a protocol/vnic */; #if defined(__BIG_ENDIAN) uint16_t __reserved0; uint16_t rate /* Vnic/Protocol rate in units of Mega-bits/sec */; #elif defined(__LITTLE_ENDIAN) uint16_t rate /* Vnic/Protocol rate in units of Mega-bits/sec */; uint16_t __reserved0; #endif }; /* * per-vnic rate shaping variables */ struct rate_shaping_vars_per_vn { struct rate_shaping_counter vn_counter /* per-vnic counter */; }; /* * per-vnic fairness variables */ struct fairness_vars_per_vn { uint32_t cos_credit_delta[MAX_COS_NUMBER] /* used for incrementing the credit */; uint32_t vn_credit_delta /* used for incrementing the credit */; uint32_t __reserved0; }; /* * cmng port init state */ struct cmng_vnic { struct rate_shaping_vars_per_vn vnic_max_rate[4]; struct fairness_vars_per_vn vnic_min_rate[4]; }; /* * cmng port init state */ struct cmng_init { struct cmng_struct_per_port port; struct cmng_vnic vnic; }; /* * driver parameters for congestion management init, all rates are in Mbps */ struct cmng_init_input { uint32_t port_rate; uint16_t vnic_min_rate[4] /* rates are in Mbps */; uint16_t vnic_max_rate[4] /* rates are in Mbps */; uint16_t cos_min_rate[MAX_COS_NUMBER] /* rates are in Mbps */; uint16_t cos_to_pause_mask[MAX_COS_NUMBER]; struct cmng_flags_per_port flags; }; /* * Protocol-common command ID for slow path elements */ enum common_spqe_cmd_id { RAMROD_CMD_ID_COMMON_UNUSED, RAMROD_CMD_ID_COMMON_FUNCTION_START /* Start a function (for PFs only) */, RAMROD_CMD_ID_COMMON_FUNCTION_STOP /* Stop a function (for PFs only) */, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE /* niv update function */, RAMROD_CMD_ID_COMMON_CFC_DEL /* Delete a connection from CFC */, RAMROD_CMD_ID_COMMON_CFC_DEL_WB /* Delete a connection from CFC (with write back) */, RAMROD_CMD_ID_COMMON_STAT_QUERY /* Collect statistics counters */, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC /* Stop Tx traffic (before DCB updates) */, RAMROD_CMD_ID_COMMON_START_TRAFFIC /* Start Tx traffic (after DCB updates) */, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS /* niv vif lists */, RAMROD_CMD_ID_COMMON_SET_TIMESYNC /* Set Timesync Parameters (E3 Only) */, MAX_COMMON_SPQE_CMD_ID}; /* * Per-protocol connection types */ enum connection_type { ETH_CONNECTION_TYPE /* Ethernet */, TOE_CONNECTION_TYPE /* TOE */, RDMA_CONNECTION_TYPE /* RDMA */, ISCSI_CONNECTION_TYPE /* iSCSI */, FCOE_CONNECTION_TYPE /* FCoE */, RESERVED_CONNECTION_TYPE_0, RESERVED_CONNECTION_TYPE_1, RESERVED_CONNECTION_TYPE_2, NONE_CONNECTION_TYPE /* General- used for common slow path */, MAX_CONNECTION_TYPE}; /* * Cos modes */ enum cos_mode { OVERRIDE_COS /* Firmware deduce cos according to DCB */, STATIC_COS /* Firmware has constant queues per CoS */, FW_WRR /* Firmware keep fairness between different CoSes */, MAX_COS_MODE}; /* * Dynamic HC counters set by the driver */ struct hc_dynamic_drv_counter { uint32_t val[HC_SB_MAX_DYNAMIC_INDICES] /* 4 bytes * 4 indices = 2 lines */; }; /* * zone A per-queue data */ struct cstorm_queue_zone_data { struct hc_dynamic_drv_counter hc_dyn_drv_cnt /* 4 bytes * 4 indices = 2 lines */; struct regpair reserved[2]; }; /* * Vf-PF channel data in cstorm ram (non-triggered zone) */ struct vf_pf_channel_zone_data { uint32_t msg_addr_lo /* the message address on VF memory */; uint32_t msg_addr_hi /* the message address on VF memory */; }; /* * zone for VF non-triggered data */ struct non_trigger_vf_zone { struct vf_pf_channel_zone_data vf_pf_channel /* vf-pf channel zone data */; }; /* * Vf-PF channel trigger zone in cstorm ram */ struct vf_pf_channel_zone_trigger { uint8_t addr_valid /* indicates that a vf-pf message is pending. MUST be set AFTER the message address. */; }; /* * zone that triggers the in-bound interrupt */ struct trigger_vf_zone { #if defined(__BIG_ENDIAN) uint16_t reserved1; uint8_t reserved0; struct vf_pf_channel_zone_trigger vf_pf_channel; #elif defined(__LITTLE_ENDIAN) struct vf_pf_channel_zone_trigger vf_pf_channel; uint8_t reserved0; uint16_t reserved1; #endif uint32_t reserved2; }; /* * zone B per-VF data */ struct cstorm_vf_zone_data { struct non_trigger_vf_zone non_trigger /* zone for VF non-triggered data */; struct trigger_vf_zone trigger /* zone that triggers the in-bound interrupt */; }; /* * Dynamic host coalescing init parameters, per state machine */ struct dynamic_hc_sm_config { uint32_t threshold[3] /* thresholds of number of outstanding bytes */; uint8_t shift_per_protocol[HC_SB_MAX_DYNAMIC_INDICES] /* bytes difference of each protocol is shifted right by this value */; uint8_t hc_timeout0[HC_SB_MAX_DYNAMIC_INDICES] /* timeout for level 0 for each protocol, in units of usec */; uint8_t hc_timeout1[HC_SB_MAX_DYNAMIC_INDICES] /* timeout for level 1 for each protocol, in units of usec */; uint8_t hc_timeout2[HC_SB_MAX_DYNAMIC_INDICES] /* timeout for level 2 for each protocol, in units of usec */; uint8_t hc_timeout3[HC_SB_MAX_DYNAMIC_INDICES] /* timeout for level 3 for each protocol, in units of usec */; }; /* * Dynamic host coalescing init parameters */ struct dynamic_hc_config { struct dynamic_hc_sm_config sm_config[HC_SB_MAX_SM] /* Configuration per state machine */; }; struct e2_integ_data { #if defined(__BIG_ENDIAN) uint8_t flags; #define E2_INTEG_DATA_TESTING_EN (0x1<<0) /* BitField flags integration testing enabled */ #define E2_INTEG_DATA_TESTING_EN_SHIFT 0 #define E2_INTEG_DATA_LB_TX (0x1<<1) /* BitField flags flag indicating this connection will transmit on loopback */ #define E2_INTEG_DATA_LB_TX_SHIFT 1 #define E2_INTEG_DATA_COS_TX (0x1<<2) /* BitField flags flag indicating this connection will transmit according to cos field */ #define E2_INTEG_DATA_COS_TX_SHIFT 2 #define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3) /* BitField flags flag indicating this connection will activate the opportunistic QM credit flow */ #define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3 #define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4) /* BitField flags flag indicating this connection will release the door bell queue (DQ) */ #define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4 #define E2_INTEG_DATA_RESERVED (0x7<<5) /* BitField flags */ #define E2_INTEG_DATA_RESERVED_SHIFT 5 uint8_t cos /* cos of the connection (relevant only in cos transmitting connections, when cosTx is set */; uint8_t voq /* voq to return credit on. Normally equal to port (i.e. always 0 in E2 operational connections). in cos tests equal to cos. in loopback tests equal to LB_PORT (=4) */; uint8_t pbf_queue /* pbf queue to transmit on. Normally equal to port (i.e. always 0 in E2 operational connections). in cos tests equal to cos. in loopback tests equal to LB_PORT (=4) */; #elif defined(__LITTLE_ENDIAN) uint8_t pbf_queue /* pbf queue to transmit on. Normally equal to port (i.e. always 0 in E2 operational connections). in cos tests equal to cos. in loopback tests equal to LB_PORT (=4) */; uint8_t voq /* voq to return credit on. Normally equal to port (i.e. always 0 in E2 operational connections). in cos tests equal to cos. in loopback tests equal to LB_PORT (=4) */; uint8_t cos /* cos of the connection (relevant only in cos transmitting connections, when cosTx is set */; uint8_t flags; #define E2_INTEG_DATA_TESTING_EN (0x1<<0) /* BitField flags integration testing enabled */ #define E2_INTEG_DATA_TESTING_EN_SHIFT 0 #define E2_INTEG_DATA_LB_TX (0x1<<1) /* BitField flags flag indicating this connection will transmit on loopback */ #define E2_INTEG_DATA_LB_TX_SHIFT 1 #define E2_INTEG_DATA_COS_TX (0x1<<2) /* BitField flags flag indicating this connection will transmit according to cos field */ #define E2_INTEG_DATA_COS_TX_SHIFT 2 #define E2_INTEG_DATA_OPPORTUNISTICQM (0x1<<3) /* BitField flags flag indicating this connection will activate the opportunistic QM credit flow */ #define E2_INTEG_DATA_OPPORTUNISTICQM_SHIFT 3 #define E2_INTEG_DATA_DPMTESTRELEASEDQ (0x1<<4) /* BitField flags flag indicating this connection will release the door bell queue (DQ) */ #define E2_INTEG_DATA_DPMTESTRELEASEDQ_SHIFT 4 #define E2_INTEG_DATA_RESERVED (0x7<<5) /* BitField flags */ #define E2_INTEG_DATA_RESERVED_SHIFT 5 #endif #if defined(__BIG_ENDIAN) uint16_t reserved3; uint8_t reserved2; uint8_t ramEn /* context area reserved for reading enable bit from ram */; #elif defined(__LITTLE_ENDIAN) uint8_t ramEn /* context area reserved for reading enable bit from ram */; uint8_t reserved2; uint16_t reserved3; #endif }; /* * set mac event data $$KEEP_ENDIANNESS$$ */ struct eth_event_data { uint32_t echo /* set mac echo data to return to driver */; uint32_t reserved0; uint32_t reserved1; }; /* * pf-vf event data $$KEEP_ENDIANNESS$$ */ struct vf_pf_event_data { uint8_t vf_id /* VF ID (0-63) */; uint8_t reserved0; uint16_t reserved1; uint32_t msg_addr_lo /* message address on Vf (low 32 bits) */; uint32_t msg_addr_hi /* message address on Vf (high 32 bits) */; }; /* * VF FLR event data $$KEEP_ENDIANNESS$$ */ struct vf_flr_event_data { uint8_t vf_id /* VF ID (0-63) */; uint8_t reserved0; uint16_t reserved1; uint32_t reserved2; uint32_t reserved3; }; /* * malicious VF event data $$KEEP_ENDIANNESS$$ */ struct malicious_vf_event_data { uint8_t vf_id /* VF ID (0-63) */; uint8_t err_id /* reason for malicious notification */; uint16_t reserved1; uint32_t reserved2; uint32_t reserved3; }; /* * vif list event data $$KEEP_ENDIANNESS$$ */ struct vif_list_event_data { uint8_t func_bit_map /* bit map of pf indice */; uint8_t echo; uint16_t reserved0; uint32_t reserved1; uint32_t reserved2; }; /* * function update event data $$KEEP_ENDIANNESS$$ */ struct function_update_event_data { uint8_t echo; uint8_t reserved; uint16_t reserved0; uint32_t reserved1; uint32_t reserved2; }; /* * union for all event ring message types */ union event_data { struct vf_pf_event_data vf_pf_event /* vf-pf event data */; struct eth_event_data eth_event /* set mac event data */; struct cfc_del_event_data cfc_del_event /* cfc delete event data */; struct vf_flr_event_data vf_flr_event /* vf flr event data */; struct malicious_vf_event_data malicious_vf_event /* malicious vf event data */; struct vif_list_event_data vif_list_event /* vif list event data */; struct function_update_event_data function_update_event /* function update event data */; }; /* * per PF event ring data */ struct event_ring_data { struct regpair_native base_addr /* ring base address */; #if defined(__BIG_ENDIAN) uint8_t index_id /* index ID within the status block */; uint8_t sb_id /* status block ID */; uint16_t producer /* event ring producer */; #elif defined(__LITTLE_ENDIAN) uint16_t producer /* event ring producer */; uint8_t sb_id /* status block ID */; uint8_t index_id /* index ID within the status block */; #endif uint32_t reserved0; }; /* * event ring message element (each element is 128 bits) $$KEEP_ENDIANNESS$$ */ struct event_ring_msg { uint8_t opcode; uint8_t error /* error on the mesasage */; uint16_t reserved1; union event_data data /* message data (96 bits data) */; }; /* * event ring next page element (128 bits) */ struct event_ring_next { struct regpair addr /* Address of the next page of the ring */; uint32_t reserved[2]; }; /* * union for event ring element types (each element is 128 bits) */ union event_ring_elem { struct event_ring_msg message /* event ring message */; struct event_ring_next next_page /* event ring next page */; }; /* * Common event ring opcodes */ enum event_ring_opcode { EVENT_RING_OPCODE_VF_PF_CHANNEL, EVENT_RING_OPCODE_FUNCTION_START /* Start a function (for PFs only) */, EVENT_RING_OPCODE_FUNCTION_STOP /* Stop a function (for PFs only) */, EVENT_RING_OPCODE_CFC_DEL /* Delete a connection from CFC */, EVENT_RING_OPCODE_CFC_DEL_WB /* Delete a connection from CFC (with write back) */, EVENT_RING_OPCODE_STAT_QUERY /* Collect statistics counters */, EVENT_RING_OPCODE_STOP_TRAFFIC /* Stop Tx traffic (before DCB updates) */, EVENT_RING_OPCODE_START_TRAFFIC /* Start Tx traffic (after DCB updates) */, EVENT_RING_OPCODE_VF_FLR /* VF FLR indication for PF */, EVENT_RING_OPCODE_MALICIOUS_VF /* Malicious VF operation detected */, EVENT_RING_OPCODE_FORWARD_SETUP /* Initialize forward channel */, EVENT_RING_OPCODE_RSS_UPDATE_RULES /* Update RSS configuration */, EVENT_RING_OPCODE_FUNCTION_UPDATE /* function update */, EVENT_RING_OPCODE_AFEX_VIF_LISTS /* event ring opcode niv vif lists */, EVENT_RING_OPCODE_SET_MAC /* Add/remove MAC (in E1x only) */, EVENT_RING_OPCODE_CLASSIFICATION_RULES /* Add/remove MAC or VLAN (in E2/E3 only) */, EVENT_RING_OPCODE_FILTERS_RULES /* Add/remove classification filters for L2 client (in E2/E3 only) */, EVENT_RING_OPCODE_MULTICAST_RULES /* Add/remove multicast classification bin (in E2/E3 only) */, EVENT_RING_OPCODE_SET_TIMESYNC /* Set Timesync Parameters (E3 Only) */, MAX_EVENT_RING_OPCODE}; /* * Modes for fairness algorithm */ enum fairness_mode { FAIRNESS_COS_WRR_MODE /* Weighted round robin mode (used in Google) */, FAIRNESS_COS_ETS_MODE /* ETS mode (used in FCoE) */, MAX_FAIRNESS_MODE}; /* * Priority and cos $$KEEP_ENDIANNESS$$ */ struct priority_cos { uint8_t priority /* Priority */; uint8_t cos /* Cos */; uint16_t reserved1; }; /* * The data for flow control configuration $$KEEP_ENDIANNESS$$ */ struct flow_control_configuration { struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES] /* traffic_type to priority cos */; uint8_t dcb_enabled /* If DCB mode is enabled then traffic class to priority array is fully initialized and there must be inner VLAN */; uint8_t dcb_version /* DCB version Increase by one on each DCB update */; uint8_t dont_add_pri_0 /* In case, the priority is 0, and the packet has no vlan, the firmware wont add vlan */; uint8_t reserved1; uint32_t reserved2; }; /* * $$KEEP_ENDIANNESS$$ */ struct function_start_data { uint8_t function_mode /* the function mode */; uint8_t allow_npar_tx_switching /* If set, inter-pf tx switching is allowed in Switch Independant function mode. (E2/E3 Only) */; uint16_t sd_vlan_tag /* value of Vlan in case of switch depended multi-function mode */; uint16_t vif_id /* value of VIF id in case of NIV multi-function mode */; uint8_t path_id; uint8_t network_cos_mode /* The cos mode for network traffic. */; uint8_t dmae_cmd_id /* The DMAE command id to use for FW DMAE transactions */; uint8_t gre_tunnel_mode /* GRE Tunnel Mode to enable on the Function (E2/E3 Only) */; uint8_t gre_tunnel_rss /* Type of RSS to perform on GRE Tunneled packets */; uint8_t nvgre_clss_en /* If set, NVGRE tunneled packets are classified according to their inner MAC (gre_mode must be NVGRE_TUNNEL) */; uint16_t reserved1[2]; }; /* * $$KEEP_ENDIANNESS$$ */ struct function_update_data { uint8_t vif_id_change_flg /* If set, vif_id will be checked */; uint8_t afex_default_vlan_change_flg /* If set, afex_default_vlan will be checked */; uint8_t allowed_priorities_change_flg /* If set, allowed_priorities will be checked */; uint8_t network_cos_mode_change_flg /* If set, network_cos_mode will be checked */; uint16_t vif_id /* value of VIF id in case of NIV multi-function mode */; uint16_t afex_default_vlan /* value of default Vlan in case of NIV mf */; uint8_t allowed_priorities /* bit vector of allowed Vlan priorities for this VIF */; uint8_t network_cos_mode /* The cos mode for network traffic. */; uint8_t lb_mode_en_change_flg /* If set, lb_mode_en will be checked */; uint8_t lb_mode_en /* If set, niv loopback mode will be enabled */; uint8_t tx_switch_suspend_change_flg /* If set, tx_switch_suspend will be checked */; uint8_t tx_switch_suspend /* If set, TX switching TO this function will be disabled and packets will be dropped */; uint8_t echo; uint8_t reserved1; uint8_t update_gre_cfg_flg /* If set, GRE config for the function will be updated according to the gre_tunnel_rss and nvgre_clss_en fields */; uint8_t gre_tunnel_mode /* GRE Tunnel Mode to enable on the Function (E2/E3 Only) */; uint8_t gre_tunnel_rss /* Type of RSS to perform on GRE Tunneled packets */; uint8_t nvgre_clss_en /* If set, NVGRE tunneled packets are classified according to their inner MAC (gre_mode must be NVGRE_TUNNEL) */; uint32_t reserved3; }; /* * FW version stored in the Xstorm RAM */ struct fw_version { #if defined(__BIG_ENDIAN) uint8_t engineering /* firmware current engineering version */; uint8_t revision /* firmware current revision version */; uint8_t minor /* firmware current minor version */; uint8_t major /* firmware current major version */; #elif defined(__LITTLE_ENDIAN) uint8_t major /* firmware current major version */; uint8_t minor /* firmware current minor version */; uint8_t revision /* firmware current revision version */; uint8_t engineering /* firmware current engineering version */; #endif uint32_t flags; #define FW_VERSION_OPTIMIZED (0x1<<0) /* BitField flags if set, this is optimized ASM */ #define FW_VERSION_OPTIMIZED_SHIFT 0 #define FW_VERSION_BIG_ENDIEN (0x1<<1) /* BitField flags if set, this is big-endien ASM */ #define FW_VERSION_BIG_ENDIEN_SHIFT 1 #define FW_VERSION_CHIP_VERSION (0x3<<2) /* BitField flags 1 - E1H */ #define FW_VERSION_CHIP_VERSION_SHIFT 2 #define __FW_VERSION_RESERVED (0xFFFFFFF<<4) /* BitField flags */ #define __FW_VERSION_RESERVED_SHIFT 4 }; /* * GRE RSS Mode */ enum gre_rss_mode { GRE_OUTER_HEADERS_RSS /* RSS for GRE Packets is performed on the outer headers */, GRE_INNER_HEADERS_RSS /* RSS for GRE Packets is performed on the inner headers */, NVGRE_KEY_ENTROPY_RSS /* RSS for NVGRE Packets is done based on a hash containing the entropy bits from the GRE Key Field (gre_tunnel must be NVGRE_TUNNEL) */, MAX_GRE_RSS_MODE}; /* * GRE Tunnel Mode */ enum gre_tunnel_type { NO_GRE_TUNNEL, NVGRE_TUNNEL /* NV-GRE Tunneling Microsoft L2 over GRE. GRE header contains mandatory Key Field. */, L2GRE_TUNNEL /* L2-GRE Tunneling General L2 over GRE. GRE can contain Key field with Tenant ID and Sequence Field */, IPGRE_TUNNEL /* IP-GRE Tunneling IP over GRE. GRE may contain Key field with Tenant ID, Sequence Field and/or Checksum Field */, MAX_GRE_TUNNEL_TYPE}; /* * Dynamic Host-Coalescing - Driver(host) counters */ struct hc_dynamic_sb_drv_counters { uint32_t dynamic_hc_drv_counter[HC_SB_MAX_DYNAMIC_INDICES] /* Dynamic HC counters written by drivers */; }; /* * 2 bytes. configuration/state parameters for a single protocol index */ struct hc_index_data { #if defined(__BIG_ENDIAN) uint8_t flags; #define HC_INDEX_DATA_SM_ID (0x1<<0) /* BitField flags Index to a state machine. Can be 0 or 1 */ #define HC_INDEX_DATA_SM_ID_SHIFT 0 #define HC_INDEX_DATA_HC_ENABLED (0x1<<1) /* BitField flags if set, host coalescing would be done for this index */ #define HC_INDEX_DATA_HC_ENABLED_SHIFT 1 #define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2) /* BitField flags if set, dynamic HC will be done for this index */ #define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2 #define HC_INDEX_DATA_RESERVE (0x1F<<3) /* BitField flags */ #define HC_INDEX_DATA_RESERVE_SHIFT 3 uint8_t timeout /* the timeout values for this index. Units are 4 usec */; #elif defined(__LITTLE_ENDIAN) uint8_t timeout /* the timeout values for this index. Units are 4 usec */; uint8_t flags; #define HC_INDEX_DATA_SM_ID (0x1<<0) /* BitField flags Index to a state machine. Can be 0 or 1 */ #define HC_INDEX_DATA_SM_ID_SHIFT 0 #define HC_INDEX_DATA_HC_ENABLED (0x1<<1) /* BitField flags if set, host coalescing would be done for this index */ #define HC_INDEX_DATA_HC_ENABLED_SHIFT 1 #define HC_INDEX_DATA_DYNAMIC_HC_ENABLED (0x1<<2) /* BitField flags if set, dynamic HC will be done for this index */ #define HC_INDEX_DATA_DYNAMIC_HC_ENABLED_SHIFT 2 #define HC_INDEX_DATA_RESERVE (0x1F<<3) /* BitField flags */ #define HC_INDEX_DATA_RESERVE_SHIFT 3 #endif }; /* * HC state-machine */ struct hc_status_block_sm { #if defined(__BIG_ENDIAN) uint8_t igu_seg_id; uint8_t igu_sb_id /* sb_id within the IGU */; uint8_t timer_value /* Determines the time_to_expire */; uint8_t __flags; #elif defined(__LITTLE_ENDIAN) uint8_t __flags; uint8_t timer_value /* Determines the time_to_expire */; uint8_t igu_sb_id /* sb_id within the IGU */; uint8_t igu_seg_id; #endif uint32_t time_to_expire /* The time in which it expects to wake up */; }; /* * hold PCI identification variables- used in various places in firmware */ struct pci_entity { #if defined(__BIG_ENDIAN) uint8_t vf_valid /* If set, this is a VF, otherwise it is PF */; uint8_t vf_id /* VF ID (0-63). Value of 0xFF means VF not valid */; uint8_t vnic_id /* Virtual NIC ID (0-3) */; uint8_t pf_id /* PCI physical function number (0-7). The LSB of this field is the port ID */; #elif defined(__LITTLE_ENDIAN) uint8_t pf_id /* PCI physical function number (0-7). The LSB of this field is the port ID */; uint8_t vnic_id /* Virtual NIC ID (0-3) */; uint8_t vf_id /* VF ID (0-63). Value of 0xFF means VF not valid */; uint8_t vf_valid /* If set, this is a VF, otherwise it is PF */; #endif }; /* * The fast-path status block meta-data, common to all chips */ struct hc_sb_data { struct regpair_native host_sb_addr /* Host status block address */; struct hc_status_block_sm state_machine[HC_SB_MAX_SM] /* Holds the state machines of the status block */; struct pci_entity p_func /* vnic / port of the status block to be set by the driver */; #if defined(__BIG_ENDIAN) uint8_t rsrv0; uint8_t state; uint8_t dhc_qzone_id /* used in E2 only, to specify the HW queue zone ID used for this status block dynamic HC counters */; uint8_t same_igu_sb_1b /* Indicate that both state-machines acts like single sm */; #elif defined(__LITTLE_ENDIAN) uint8_t same_igu_sb_1b /* Indicate that both state-machines acts like single sm */; uint8_t dhc_qzone_id /* used in E2 only, to specify the HW queue zone ID used for this status block dynamic HC counters */; uint8_t state; uint8_t rsrv0; #endif struct regpair_native rsrv1[2]; }; /* * Segment types for host coaslescing */ enum hc_segment { HC_REGULAR_SEGMENT, HC_DEFAULT_SEGMENT, MAX_HC_SEGMENT}; /* * The fast-path status block meta-data */ struct hc_sp_status_block_data { struct regpair_native host_sb_addr /* Host status block address */; #if defined(__BIG_ENDIAN) uint8_t rsrv1; uint8_t state; uint8_t igu_seg_id /* segment id of the IGU */; uint8_t igu_sb_id /* sb_id within the IGU */; #elif defined(__LITTLE_ENDIAN) uint8_t igu_sb_id /* sb_id within the IGU */; uint8_t igu_seg_id /* segment id of the IGU */; uint8_t state; uint8_t rsrv1; #endif struct pci_entity p_func /* vnic / port of the status block to be set by the driver */; }; /* * The fast-path status block meta-data */ struct hc_status_block_data_e1x { struct hc_index_data index_data[HC_SB_MAX_INDICES_E1X] /* configuration/state parameters for a single protocol index */; struct hc_sb_data common /* The fast-path status block meta-data, common to all chips */; }; /* * The fast-path status block meta-data */ struct hc_status_block_data_e2 { struct hc_index_data index_data[HC_SB_MAX_INDICES_E2] /* configuration/state parameters for a single protocol index */; struct hc_sb_data common /* The fast-path status block meta-data, common to all chips */; }; /* * IGU block operartion modes (in Everest2) */ enum igu_mode { HC_IGU_BC_MODE /* Backward compatible mode */, HC_IGU_NBC_MODE /* Non-backward compatible mode */, MAX_IGU_MODE}; /* * IP versions */ enum ip_ver { IP_V4, IP_V6, MAX_IP_VER}; /* * Malicious VF error ID */ enum malicious_vf_error_id { VF_PF_CHANNEL_NOT_READY /* Writing to VF/PF channel when it is not ready */, ETH_ILLEGAL_BD_LENGTHS /* TX BD lengths error was detected */, ETH_PACKET_TOO_SHORT /* TX packet is shorter then reported on BDs */, ETH_PAYLOAD_TOO_BIG /* TX packet is greater then MTU */, ETH_ILLEGAL_ETH_TYPE /* TX packet reported without VLAN but eth type is 0x8100 */, ETH_ILLEGAL_LSO_HDR_LEN /* LSO header length on BDs and on hdr_nbd do not match */, ETH_TOO_MANY_BDS /* Tx packet has too many BDs */, ETH_ZERO_HDR_NBDS /* hdr_nbds field is zero */, ETH_START_BD_NOT_SET /* start_bd should be set on first TX BD in packet */, ETH_ILLEGAL_PARSE_NBDS /* Tx packet with parse_nbds field which is not legal */, ETH_IPV6_AND_CHECKSUM /* Tx packet with IP checksum on IPv6 */, ETH_VLAN_FLG_INCORRECT /* Tx packet with incorrect VLAN flag */, ETH_ILLEGAL_LSO_MSS /* Tx LSO packet with illegal MSS value */, ETH_TUNNEL_NOT_SUPPORTED /* Tunneling packets are not supported in current connection */, MAX_MALICIOUS_VF_ERROR_ID}; /* * Multi-function modes */ enum mf_mode { SINGLE_FUNCTION, MULTI_FUNCTION_SD /* Switch dependent (vlan based) */, MULTI_FUNCTION_SI /* Switch independent (mac based) */, MULTI_FUNCTION_AFEX /* Switch dependent (niv based) */, MAX_MF_MODE}; /* * Protocol-common statistics collected by the Tstorm (per pf) $$KEEP_ENDIANNESS$$ */ struct tstorm_per_pf_stats { struct regpair rcv_error_bytes /* number of bytes received with errors */; }; /* * $$KEEP_ENDIANNESS$$ */ struct per_pf_stats { struct tstorm_per_pf_stats tstorm_pf_statistics; }; /* * Protocol-common statistics collected by the Tstorm (per port) $$KEEP_ENDIANNESS$$ */ struct tstorm_per_port_stats { uint32_t mac_discard /* number of packets with mac errors */; uint32_t mac_filter_discard /* the number of good frames dropped because of no perfect match to MAC/VLAN address */; uint32_t brb_truncate_discard /* the number of packtes that were dropped because they were truncated in BRB */; uint32_t mf_tag_discard /* the number of good frames dropped because of no match to the outer vlan/VNtag */; uint32_t packet_drop /* general packet drop conter- incremented for every packet drop */; uint32_t reserved; }; /* * $$KEEP_ENDIANNESS$$ */ struct per_port_stats { struct tstorm_per_port_stats tstorm_port_statistics; }; /* * Protocol-common statistics collected by the Tstorm (per client) $$KEEP_ENDIANNESS$$ */ struct tstorm_per_queue_stats { struct regpair rcv_ucast_bytes /* number of bytes in unicast packets received without errors and pass the filter */; uint32_t rcv_ucast_pkts /* number of unicast packets received without errors and pass the filter */; uint32_t checksum_discard /* number of total packets received with checksum error */; struct regpair rcv_bcast_bytes /* number of bytes in broadcast packets received without errors and pass the filter */; uint32_t rcv_bcast_pkts /* number of packets in broadcast packets received without errors and pass the filter */; uint32_t pkts_too_big_discard /* number of too long packets received */; struct regpair rcv_mcast_bytes /* number of bytes in multicast packets received without errors and pass the filter */; uint32_t rcv_mcast_pkts /* number of packets in multicast packets received without errors and pass the filter */; uint32_t ttl0_discard /* the number of good frames dropped because of TTL=0 */; uint16_t no_buff_discard; uint16_t reserved0; uint32_t reserved1; }; /* * Protocol-common statistics collected by the Ustorm (per client) $$KEEP_ENDIANNESS$$ */ struct ustorm_per_queue_stats { struct regpair ucast_no_buff_bytes /* the number of unicast bytes received from network dropped because of no buffer at host */; struct regpair mcast_no_buff_bytes /* the number of multicast bytes received from network dropped because of no buffer at host */; struct regpair bcast_no_buff_bytes /* the number of broadcast bytes received from network dropped because of no buffer at host */; uint32_t ucast_no_buff_pkts /* the number of unicast frames received from network dropped because of no buffer at host */; uint32_t mcast_no_buff_pkts /* the number of unicast frames received from network dropped because of no buffer at host */; uint32_t bcast_no_buff_pkts /* the number of unicast frames received from network dropped because of no buffer at host */; uint32_t coalesced_pkts /* the number of packets coalesced in all aggregations */; struct regpair coalesced_bytes /* the number of bytes coalesced in all aggregations */; uint32_t coalesced_events /* the number of aggregations */; uint32_t coalesced_aborts /* the number of exception which avoid aggregation */; }; /* * Protocol-common statistics collected by the Xstorm (per client) $$KEEP_ENDIANNESS$$ */ struct xstorm_per_queue_stats { struct regpair ucast_bytes_sent /* number of total bytes sent without errors */; struct regpair mcast_bytes_sent /* number of total bytes sent without errors */; struct regpair bcast_bytes_sent /* number of total bytes sent without errors */; uint32_t ucast_pkts_sent /* number of total packets sent without errors */; uint32_t mcast_pkts_sent /* number of total packets sent without errors */; uint32_t bcast_pkts_sent /* number of total packets sent without errors */; uint32_t error_drop_pkts /* number of total packets drooped due to errors */; }; /* * $$KEEP_ENDIANNESS$$ */ struct per_queue_stats { struct tstorm_per_queue_stats tstorm_queue_statistics; struct ustorm_per_queue_stats ustorm_queue_statistics; struct xstorm_per_queue_stats xstorm_queue_statistics; }; /* * FW version stored in first line of pram $$KEEP_ENDIANNESS$$ */ struct pram_fw_version { uint8_t major /* firmware current major version */; uint8_t minor /* firmware current minor version */; uint8_t revision /* firmware current revision version */; uint8_t engineering /* firmware current engineering version */; uint8_t flags; #define PRAM_FW_VERSION_OPTIMIZED (0x1<<0) /* BitField flags if set, this is optimized ASM */ #define PRAM_FW_VERSION_OPTIMIZED_SHIFT 0 #define PRAM_FW_VERSION_STORM_ID (0x3<<1) /* BitField flags storm_id identification */ #define PRAM_FW_VERSION_STORM_ID_SHIFT 1 #define PRAM_FW_VERSION_BIG_ENDIEN (0x1<<3) /* BitField flags if set, this is big-endien ASM */ #define PRAM_FW_VERSION_BIG_ENDIEN_SHIFT 3 #define PRAM_FW_VERSION_CHIP_VERSION (0x3<<4) /* BitField flags 1 - E1H */ #define PRAM_FW_VERSION_CHIP_VERSION_SHIFT 4 #define __PRAM_FW_VERSION_RESERVED0 (0x3<<6) /* BitField flags */ #define __PRAM_FW_VERSION_RESERVED0_SHIFT 6 }; /* * Ethernet slow path element */ union protocol_common_specific_data { uint8_t protocol_data[8] /* to fix this structure size to 8 bytes */; struct regpair phy_address /* SPE physical address */; struct regpair mac_config_addr /* physical address of the MAC configuration command, as allocated by the driver */; struct afex_vif_list_ramrod_data afex_vif_list_data /* The data afex vif list ramrod need */; }; /* * The send queue element */ struct protocol_common_spe { struct spe_hdr hdr /* SPE header */; union protocol_common_specific_data data /* data specific to common protocol */; }; /* * The data for the Set Timesync Ramrod $$KEEP_ENDIANNESS$$ */ struct set_timesync_ramrod_data { uint8_t drift_adjust_cmd /* Timesync Drift Adjust Command */; uint8_t offset_cmd /* Timesync Offset Command */; uint8_t add_sub_drift_adjust_value /* Whether to add(1)/subtract(0) Drift Adjust Value from the Offset */; uint8_t drift_adjust_value /* Drift Adjust Value (in ns) */; uint32_t drift_adjust_period /* Drift Adjust Period (in us) */; struct regpair offset_delta /* Timesync Offset Delta (in ns) */; }; /* * The send queue element */ struct slow_path_element { struct spe_hdr hdr /* common data for all protocols */; struct regpair protocol_data /* additional data specific to the protocol */; }; /* * Protocol-common statistics counter $$KEEP_ENDIANNESS$$ */ struct stats_counter { uint16_t xstats_counter /* xstorm statistics counter */; uint16_t reserved0; uint32_t reserved1; uint16_t tstats_counter /* tstorm statistics counter */; uint16_t reserved2; uint32_t reserved3; uint16_t ustats_counter /* ustorm statistics counter */; uint16_t reserved4; uint32_t reserved5; uint16_t cstats_counter /* ustorm statistics counter */; uint16_t reserved6; uint32_t reserved7; }; /* * $$KEEP_ENDIANNESS$$ */ struct stats_query_entry { uint8_t kind; uint8_t index /* queue index */; uint16_t funcID /* the func the statistic will send to */; uint32_t reserved; struct regpair address /* pxp address */; }; /* * statistic command $$KEEP_ENDIANNESS$$ */ struct stats_query_cmd_group { struct stats_query_entry query[STATS_QUERY_CMD_COUNT]; }; /* * statistic command header $$KEEP_ENDIANNESS$$ */ struct stats_query_header { uint8_t cmd_num /* command number */; uint8_t reserved0; uint16_t drv_stats_counter; uint32_t reserved1; struct regpair stats_counters_addrs /* stats counter */; }; /* * Types of statistcis query entry */ enum stats_query_type { STATS_TYPE_QUEUE, STATS_TYPE_PORT, STATS_TYPE_PF, STATS_TYPE_TOE, STATS_TYPE_FCOE, MAX_STATS_QUERY_TYPE}; /* * Indicate of the function status block state */ enum status_block_state { SB_DISABLED, SB_ENABLED, SB_CLEANED, MAX_STATUS_BLOCK_STATE}; /* * Storm IDs (including attentions for IGU related enums) */ enum storm_id { USTORM_ID, CSTORM_ID, XSTORM_ID, TSTORM_ID, ATTENTION_ID, MAX_STORM_ID}; /* * Taffic types used in ETS and flow control algorithms */ enum traffic_type { LLFC_TRAFFIC_TYPE_NW /* Networking */, LLFC_TRAFFIC_TYPE_FCOE /* FCoE */, LLFC_TRAFFIC_TYPE_ISCSI /* iSCSI */, MAX_TRAFFIC_TYPE}; /* * zone A per-queue data */ struct tstorm_queue_zone_data { struct regpair reserved[4]; }; /* * zone B per-VF data */ struct tstorm_vf_zone_data { struct regpair reserved; }; /* * Add or Subtract Value for Set Timesync Ramrod */ enum ts_add_sub_value { TS_SUB_VALUE /* Subtract Value */, TS_ADD_VALUE /* Add Value */, MAX_TS_ADD_SUB_VALUE}; /* * Drift-Adjust Commands for Set Timesync Ramrod */ enum ts_drift_adjust_cmd { TS_DRIFT_ADJUST_KEEP /* Keep Drift-Adjust at current values */, TS_DRIFT_ADJUST_SET /* Set Drift-Adjust */, TS_DRIFT_ADJUST_RESET /* Reset Drift-Adjust */, MAX_TS_DRIFT_ADJUST_CMD}; /* * Offset Commands for Set Timesync Ramrod */ enum ts_offset_cmd { TS_OFFSET_KEEP /* Keep Offset at current values */, TS_OFFSET_INC /* Increase Offset by Offset Delta */, TS_OFFSET_DEC /* Decrease Offset by Offset Delta */, MAX_TS_OFFSET_CMD}; /* * zone A per-queue data */ struct ustorm_queue_zone_data { union ustorm_eth_rx_producers eth_rx_producers /* ETH RX rings producers */; struct regpair reserved[3]; }; /* * zone B per-VF data */ struct ustorm_vf_zone_data { struct regpair reserved; }; /* * data per VF-PF channel */ struct vf_pf_channel_data { #if defined(__BIG_ENDIAN) uint16_t reserved0; uint8_t valid /* flag for channel validity. (cleared when identify a VF as malicious) */; uint8_t state /* channel state (ready / waiting for ack) */; #elif defined(__LITTLE_ENDIAN) uint8_t state /* channel state (ready / waiting for ack) */; uint8_t valid /* flag for channel validity. (cleared when identify a VF as malicious) */; uint16_t reserved0; #endif uint32_t reserved1; }; /* * State of VF-PF channel */ enum vf_pf_channel_state { VF_PF_CHANNEL_STATE_READY /* Channel is ready to accept a message from VF */, VF_PF_CHANNEL_STATE_WAITING_FOR_ACK /* Channel waits for an ACK from PF */, MAX_VF_PF_CHANNEL_STATE}; /* * vif_list_rule_kind */ enum vif_list_rule_kind { VIF_LIST_RULE_SET, VIF_LIST_RULE_GET, VIF_LIST_RULE_CLEAR_ALL, VIF_LIST_RULE_CLEAR_FUNC, MAX_VIF_LIST_RULE_KIND}; /* * zone A per-queue data */ struct xstorm_queue_zone_data { struct regpair reserved[4]; }; /* * zone B per-VF data */ struct xstorm_vf_zone_data { struct regpair reserved; }; #endif /* ECORE_HSI_H */ ================================================ FILE: drivers/net/bnx2x/ecore_init.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_INIT_H #define ECORE_INIT_H /* Init operation types and structures */ enum { OP_RD = 0x1, /* read a single register */ OP_WR, /* write a single register */ OP_SW, /* copy a string to the device */ OP_ZR, /* clear memory */ OP_ZP, /* unzip then copy with DMAE */ OP_WR_64, /* write 64 bit pattern */ OP_WB, /* copy a string using DMAE */ OP_WB_ZR, /* Clear a string using DMAE or indirect-wr */ OP_IF_MODE_OR, /* Skip the following ops if all init modes don't match */ OP_IF_MODE_AND, /* Skip the following ops if any init modes don't match */ OP_IF_PHASE, OP_RT, OP_DELAY, OP_VERIFY, OP_MAX }; enum { STAGE_START, STAGE_END, }; /* Returns the index of start or end of a specific block stage in ops array*/ #define BLOCK_OPS_IDX(block, stage, end) \ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) /* structs for the various opcodes */ struct raw_op { uint32_t op:8; uint32_t offset:24; uint32_t raw_data; }; struct op_read { uint32_t op:8; uint32_t offset:24; uint32_t val; }; struct op_write { uint32_t op:8; uint32_t offset:24; uint32_t val; }; struct op_arr_write { uint32_t op:8; uint32_t offset:24; #ifdef __BIG_ENDIAN uint16_t data_len; uint16_t data_off; #else /* __LITTLE_ENDIAN */ uint16_t data_off; uint16_t data_len; #endif }; struct op_zero { uint32_t op:8; uint32_t offset:24; uint32_t len; }; struct op_if_mode { uint32_t op:8; uint32_t cmd_offset:24; uint32_t mode_bit_map; }; struct op_if_phase { uint32_t op:8; uint32_t cmd_offset:24; uint32_t phase_bit_map; }; struct op_delay { uint32_t op:8; uint32_t reserved:24; uint32_t delay; }; union init_op { struct op_read read; struct op_write write; struct op_arr_write arr_wr; struct op_zero zero; struct raw_op raw; struct op_if_mode if_mode; struct op_if_phase if_phase; struct op_delay delay; }; /* Init Phases */ enum { PHASE_COMMON, PHASE_PORT0, PHASE_PORT1, PHASE_PF0, PHASE_PF1, PHASE_PF2, PHASE_PF3, PHASE_PF4, PHASE_PF5, PHASE_PF6, PHASE_PF7, NUM_OF_INIT_PHASES }; /* Init Modes */ enum { MODE_ASIC = 0x00000001, MODE_FPGA = 0x00000002, MODE_EMUL = 0x00000004, MODE_E2 = 0x00000008, MODE_E3 = 0x00000010, MODE_PORT2 = 0x00000020, MODE_PORT4 = 0x00000040, MODE_SF = 0x00000080, MODE_MF = 0x00000100, MODE_MF_SD = 0x00000200, MODE_MF_SI = 0x00000400, MODE_MF_AFEX = 0x00000800, MODE_E3_A0 = 0x00001000, MODE_E3_B0 = 0x00002000, MODE_COS3 = 0x00004000, MODE_COS6 = 0x00008000, MODE_LITTLE_ENDIAN = 0x00010000, MODE_BIG_ENDIAN = 0x00020000, }; /* Init Blocks */ enum { BLOCK_ATC, BLOCK_BRB1, BLOCK_CCM, BLOCK_CDU, BLOCK_CFC, BLOCK_CSDM, BLOCK_CSEM, BLOCK_DBG, BLOCK_DMAE, BLOCK_DORQ, BLOCK_HC, BLOCK_IGU, BLOCK_MISC, BLOCK_NIG, BLOCK_PBF, BLOCK_PGLUE_B, BLOCK_PRS, BLOCK_PXP2, BLOCK_PXP, BLOCK_QM, BLOCK_SRC, BLOCK_TCM, BLOCK_TM, BLOCK_TSDM, BLOCK_TSEM, BLOCK_UCM, BLOCK_UPB, BLOCK_USDM, BLOCK_USEM, BLOCK_XCM, BLOCK_XPB, BLOCK_XSDM, BLOCK_XSEM, BLOCK_MISC_AEU, NUM_OF_INIT_BLOCKS }; /* Vnics per mode */ #define ECORE_PORT2_MODE_NUM_VNICS 4 /* QM queue numbers */ #define ECORE_ETH_Q 0 #define ECORE_TOE_Q 3 #define ECORE_TOE_ACK_Q 6 #define ECORE_ISCSI_Q 9 #define ECORE_ISCSI_ACK_Q 11 #define ECORE_FCOE_Q 10 /* Vnics per mode */ #define ECORE_PORT4_MODE_NUM_VNICS 2 /* COS offset for port1 in E3 B0 4port mode */ #define ECORE_E3B0_PORT1_COS_OFFSET 3 /* QM Register addresses */ #define ECORE_Q_VOQ_REG_ADDR(pf_q_num)\ (QM_REG_QVOQIDX_0 + 4 * (pf_q_num)) #define ECORE_VOQ_Q_REG_ADDR(cos, pf_q_num)\ (QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5))) #define ECORE_Q_CMDQ_REG_ADDR(pf_q_num)\ (QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4)) /* extracts the QM queue number for the specified port and vnic */ #define ECORE_PF_Q_NUM(q_num, port, vnic)\ ((((port) << 1) | (vnic)) * 16 + (q_num)) /* Maps the specified queue to the specified COS */ static inline void ecore_map_q_cos(struct bnx2x_softc *sc, uint32_t q_num, uint32_t new_cos) { /* find current COS mapping */ uint32_t curr_cos = REG_RD(sc, QM_REG_QVOQIDX_0 + q_num * 4); /* check if queue->COS mapping has changed */ if (curr_cos != new_cos) { uint32_t num_vnics = ECORE_PORT2_MODE_NUM_VNICS; uint32_t reg_addr, reg_bit_map, vnic; /* update parameters for 4port mode */ if (INIT_MODE_FLAGS(sc) & MODE_PORT4) { num_vnics = ECORE_PORT4_MODE_NUM_VNICS; if (PORT_ID(sc)) { curr_cos += ECORE_E3B0_PORT1_COS_OFFSET; new_cos += ECORE_E3B0_PORT1_COS_OFFSET; } } /* change queue mapping for each VNIC */ for (vnic = 0; vnic < num_vnics; vnic++) { uint32_t pf_q_num = ECORE_PF_Q_NUM(q_num, PORT_ID(sc), vnic); uint32_t q_bit_map = 1 << (pf_q_num & 0x1f); /* overwrite queue->VOQ mapping */ REG_WR(sc, ECORE_Q_VOQ_REG_ADDR(pf_q_num), new_cos); /* clear queue bit from current COS bit map */ reg_addr = ECORE_VOQ_Q_REG_ADDR(curr_cos, pf_q_num); reg_bit_map = REG_RD(sc, reg_addr); REG_WR(sc, reg_addr, reg_bit_map & (~q_bit_map)); /* set queue bit in new COS bit map */ reg_addr = ECORE_VOQ_Q_REG_ADDR(new_cos, pf_q_num); reg_bit_map = REG_RD(sc, reg_addr); REG_WR(sc, reg_addr, reg_bit_map | q_bit_map); /* set/clear queue bit in command-queue bit map (E2/E3A0 only, valid COS values are 0/1) */ if (!(INIT_MODE_FLAGS(sc) & MODE_E3_B0)) { reg_addr = ECORE_Q_CMDQ_REG_ADDR(pf_q_num); reg_bit_map = REG_RD(sc, reg_addr); q_bit_map = 1 << (2 * (pf_q_num & 0xf)); reg_bit_map = new_cos ? (reg_bit_map | q_bit_map) : (reg_bit_map & (~q_bit_map)); REG_WR(sc, reg_addr, reg_bit_map); } } } } /* Configures the QM according to the specified per-traffic-type COSes */ static inline void ecore_dcb_config_qm(struct bnx2x_softc *sc, enum cos_mode mode, struct priority_cos *traffic_cos) { ecore_map_q_cos(sc, ECORE_FCOE_Q, traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos); ecore_map_q_cos(sc, ECORE_ISCSI_Q, traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); ecore_map_q_cos(sc, ECORE_ISCSI_ACK_Q, traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos); if (mode != STATIC_COS) { /* required only in OVERRIDE_COS mode */ ecore_map_q_cos(sc, ECORE_ETH_Q, traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); ecore_map_q_cos(sc, ECORE_TOE_Q, traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); ecore_map_q_cos(sc, ECORE_TOE_ACK_Q, traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos); } } /* * congestion managment port init api description * the api works as follows: * the driver should pass the cmng_init_input struct, the port_init function * will prepare the required internal ram structure which will be passed back * to the driver (cmng_init) that will write it into the internal ram. * * IMPORTANT REMARKS: * 1. the cmng_init struct does not represent the contiguous internal ram * structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET * offset in order to write the port sub struct and the * PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other * words - don't use memcpy!). * 2. although the cmng_init struct is filled for the maximal vnic number * possible, the driver should only write the valid vnics into the internal * ram according to the appropriate port mode. */ #define BITS_TO_BYTES(x) ((x)/8) /* CMNG constants, as derived from system spec calculations */ /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */ #define DEF_MIN_RATE 100 /* resolution of the rate shaping timer - 400 usec */ #define RS_PERIODIC_TIMEOUT_USEC 400 /* * number of bytes in single QM arbitration cycle - * coefficient for calculating the fairness timer */ #define QM_ARB_BYTES 160000 /* resolution of Min algorithm 1:100 */ #define MIN_RES 100 /* * how many bytes above threshold for * the minimal credit of Min algorithm */ #define MIN_ABOVE_THRESH 32768 /* * Fairness algorithm integration time coefficient - * for calculating the actual Tfair */ #define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES) /* Memory of fairness algorithm - 2 cycles */ #define FAIR_MEM 2 #define SAFC_TIMEOUT_USEC 52 #define SDM_TICKS 4 static inline void ecore_init_max(const struct cmng_init_input *input_data, uint32_t r_param, struct cmng_init *ram_data) { uint32_t vnic; struct cmng_vnic *vdata = &ram_data->vnic; struct cmng_struct_per_port *pdata = &ram_data->port; /* * rate shaping per-port variables * 100 micro seconds in SDM ticks = 25 * since each tick is 4 microSeconds */ pdata->rs_vars.rs_periodic_timeout = RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS; /* this is the threshold below which no timer arming will occur. * 1.25 coefficient is for the threshold to be a little bigger * then the real time to compensate for timer in-accuracy */ pdata->rs_vars.rs_threshold = (5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4; /* rate shaping per-vnic variables */ for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { /* global vnic counter */ vdata->vnic_max_rate[vnic].vn_counter.rate = input_data->vnic_max_rate[vnic]; /* * maximal Mbps for this vnic * the quota in each timer period - number of bytes * transmitted in this period */ vdata->vnic_max_rate[vnic].vn_counter.quota = RS_PERIODIC_TIMEOUT_USEC * (uint32_t)vdata->vnic_max_rate[vnic].vn_counter.rate / 8; } } static inline void ecore_init_max_per_vn(uint16_t vnic_max_rate, struct rate_shaping_vars_per_vn *ram_data) { /* global vnic counter */ ram_data->vn_counter.rate = vnic_max_rate; /* * maximal Mbps for this vnic * the quota in each timer period - number of bytes * transmitted in this period */ ram_data->vn_counter.quota = RS_PERIODIC_TIMEOUT_USEC * (uint32_t)vnic_max_rate / 8; } static inline void ecore_init_min(const struct cmng_init_input *input_data, uint32_t r_param, struct cmng_init *ram_data) { uint32_t vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair; struct cmng_vnic *vdata = &ram_data->vnic; struct cmng_struct_per_port *pdata = &ram_data->port; /* this is the resolution of the fairness timer */ fair_periodic_timeout_usec = QM_ARB_BYTES / r_param; /* * fairness per-port variables * for 10G it is 1000usec. for 1G it is 10000usec. */ tFair = T_FAIR_COEF / input_data->port_rate; /* this is the threshold below which we won't arm the timer anymore */ pdata->fair_vars.fair_threshold = QM_ARB_BYTES; /* * we multiply by 1e3/8 to get bytes/msec. We don't want the credits * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution) */ pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM; /* since each tick is 4 microSeconds */ pdata->fair_vars.fairness_timeout = fair_periodic_timeout_usec / SDM_TICKS; /* calculate sum of weights */ vnicWeightSum = 0; for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) vnicWeightSum += input_data->vnic_min_rate[vnic]; /* global vnic counter */ if (vnicWeightSum > 0) { /* fairness per-vnic variables */ for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { /* * this is the credit for each period of the fairness * algorithm - number of bytes in T_FAIR (this vnic * share of the port rate) */ vdata->vnic_min_rate[vnic].vn_credit_delta = ((uint32_t)(input_data->vnic_min_rate[vnic]) * 100 * (T_FAIR_COEF / (8 * 100 * vnicWeightSum))); if (vdata->vnic_min_rate[vnic].vn_credit_delta < pdata->fair_vars.fair_threshold + MIN_ABOVE_THRESH) { vdata->vnic_min_rate[vnic].vn_credit_delta = pdata->fair_vars.fair_threshold + MIN_ABOVE_THRESH; } } } } static inline void ecore_init_fw_wrr(const struct cmng_init_input *input_data, struct cmng_init *ram_data) { uint32_t vnic, cos; uint32_t cosWeightSum = 0; struct cmng_vnic *vdata = &ram_data->vnic; struct cmng_struct_per_port *pdata = &ram_data->port; for (cos = 0; cos < MAX_COS_NUMBER; cos++) cosWeightSum += input_data->cos_min_rate[cos]; if (cosWeightSum > 0) { for (vnic = 0; vnic < ECORE_PORT2_MODE_NUM_VNICS; vnic++) { /* * Since cos and vnic shouldn't work together the rate * to divide between the coses is the port rate. */ uint32_t *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta; for (cos = 0; cos < MAX_COS_NUMBER; cos++) { /* * this is the credit for each period of * the fairness algorithm - number of bytes * in T_FAIR (this cos share of the vnic rate) */ ccd[cos] = ((uint32_t)input_data->cos_min_rate[cos] * 100 * (T_FAIR_COEF / (8 * 100 * cosWeightSum))); if (ccd[cos] < pdata->fair_vars.fair_threshold + MIN_ABOVE_THRESH) { ccd[cos] = pdata->fair_vars.fair_threshold + MIN_ABOVE_THRESH; } } } } } static inline void ecore_init_safc(struct cmng_init *ram_data) { /* in microSeconds */ ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC; } /* Congestion management port init */ static inline void ecore_init_cmng(const struct cmng_init_input *input_data, struct cmng_init *ram_data) { uint32_t r_param; ECORE_MEMSET(ram_data, 0,sizeof(struct cmng_init)); ram_data->port.flags = input_data->flags; /* * number of bytes transmitted in a rate of 10Gbps * in one usec = 1.25KB. */ r_param = BITS_TO_BYTES(input_data->port_rate); ecore_init_max(input_data, r_param, ram_data); ecore_init_min(input_data, r_param, ram_data); ecore_init_fw_wrr(input_data, ram_data); ecore_init_safc(ram_data); } /* Returns the index of start or end of a specific block stage in ops array*/ #define BLOCK_OPS_IDX(block, stage, end) \ (2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end)) #define INITOP_SET 0 /* set the HW directly */ #define INITOP_CLEAR 1 /* clear the HW directly */ #define INITOP_INIT 2 /* set the init-value array */ /**************************************************************************** * ILT management ****************************************************************************/ struct ilt_line { ecore_dma_addr_t page_mapping; void *page; uint32_t size; }; struct ilt_client_info { uint32_t page_size; uint16_t start; uint16_t end; uint16_t client_num; uint16_t flags; #define ILT_CLIENT_SKIP_INIT 0x1 #define ILT_CLIENT_SKIP_MEM 0x2 }; struct ecore_ilt { uint32_t start_line; struct ilt_line *lines; struct ilt_client_info clients[4]; #define ILT_CLIENT_CDU 0 #define ILT_CLIENT_QM 1 #define ILT_CLIENT_SRC 2 #define ILT_CLIENT_TM 3 }; /**************************************************************************** * SRC configuration ****************************************************************************/ struct src_ent { uint8_t opaque[56]; uint64_t next; }; /**************************************************************************** * Parity configuration ****************************************************************************/ #define BLOCK_PRTY_INFO(block, en_mask, m1h, m2, m3) \ { \ block##_REG_##block##_PRTY_MASK, \ block##_REG_##block##_PRTY_STS_CLR, \ en_mask, {m1h, m2, m3}, #block \ } #define BLOCK_PRTY_INFO_0(block, en_mask, m1h, m2, m3) \ { \ block##_REG_##block##_PRTY_MASK_0, \ block##_REG_##block##_PRTY_STS_CLR_0, \ en_mask, {m1h, m2, m3}, #block"_0" \ } #define BLOCK_PRTY_INFO_1(block, en_mask, m1h, m2, m3) \ { \ block##_REG_##block##_PRTY_MASK_1, \ block##_REG_##block##_PRTY_STS_CLR_1, \ en_mask, {m1h, m2, m3}, #block"_1" \ } static const struct { uint32_t mask_addr; uint32_t sts_clr_addr; uint32_t en_mask; /* Mask to enable parity attentions */ struct { uint32_t e1h; /* 57711 */ uint32_t e2; /* 57712 */ uint32_t e3; /* 578xx */ } reg_mask; /* Register mask (all valid bits) */ char name[8]; /* Block's longest name is 7 characters long * (name + suffix) */ } ecore_blocks_parity_data[] = { /* bit 19 masked */ /* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */ /* bit 5,18,20-31 */ /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */ /* bit 5 */ /* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20); */ /* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */ /* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */ /* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't * want to handle "system kill" flow at the moment. */ BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x7ffffff, 0x7ffffff), BLOCK_PRTY_INFO_0(PXP2, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(PXP2, 0x1ffffff, 0x7f, 0x7ff, 0x1ffffff), BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0, 0), BLOCK_PRTY_INFO(NIG, 0xffffffff, 0xffffffff, 0, 0), BLOCK_PRTY_INFO_0(NIG, 0xffffffff, 0, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(NIG, 0xffff, 0, 0xff, 0xffff), BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0x7ff, 0x7ff), BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1), BLOCK_PRTY_INFO(QM, 0, 0xfff, 0xfff, 0xfff), BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0x1f, 0x1f), BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0x3, 0x3), BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3), {GRCBASE_UPB + PB_REG_PB_PRTY_MASK, GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf, {0xf, 0xf, 0xf}, "UPB"}, {GRCBASE_XPB + PB_REG_PB_PRTY_MASK, GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0, {0xf, 0xf, 0xf}, "XPB"}, BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7), BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f), BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0x3f), BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1), BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf), BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf), BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff), BLOCK_PRTY_INFO(PBF, 0, 0x3ffff, 0xfffff, 0xfffffff), BLOCK_PRTY_INFO(TM, 0, 0x7f, 0x7f, 0x7f), BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff), BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff), BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff), BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff), BLOCK_PRTY_INFO(TCM, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), BLOCK_PRTY_INFO(CCM, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), BLOCK_PRTY_INFO(UCM, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff), BLOCK_PRTY_INFO(XCM, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff), BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(TSEM, 0, 0x1f, 0x3f, 0x3f), BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(USEM, 0, 0x1f, 0x1f, 0x1f), BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(CSEM, 0, 0x1f, 0x1f, 0x1f), BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff), BLOCK_PRTY_INFO_1(XSEM, 0, 0x1f, 0x3f, 0x3f), }; /* [28] MCP Latched rom_parity * [29] MCP Latched ump_rx_parity * [30] MCP Latched ump_tx_parity * [31] MCP Latched scpad_parity */ #define MISC_AEU_ENABLE_MCP_PRTY_BITS \ (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY) /* Below registers control the MCP parity attention output. When * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are * enabled, when cleared - disabled. */ static const uint32_t mcp_attn_ctl_regs[] = { MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0, MISC_REG_AEU_ENABLE4_NIG_0, MISC_REG_AEU_ENABLE4_PXP_0, MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0, MISC_REG_AEU_ENABLE4_NIG_1, MISC_REG_AEU_ENABLE4_PXP_1 }; static inline void ecore_set_mcp_parity(struct bnx2x_softc *sc, uint8_t enable) { uint32_t i; uint32_t reg_val; for (i = 0; i < ARRSIZE(mcp_attn_ctl_regs); i++) { reg_val = REG_RD(sc, mcp_attn_ctl_regs[i]); if (enable) reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS; else reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS; REG_WR(sc, mcp_attn_ctl_regs[i], reg_val); } } static inline uint32_t ecore_parity_reg_mask(struct bnx2x_softc *sc, int idx) { if (CHIP_IS_E1H(sc)) return ecore_blocks_parity_data[idx].reg_mask.e1h; else if (CHIP_IS_E2(sc)) return ecore_blocks_parity_data[idx].reg_mask.e2; else /* CHIP_IS_E3 */ return ecore_blocks_parity_data[idx].reg_mask.e3; } static inline void ecore_disable_blocks_parity(struct bnx2x_softc *sc) { uint32_t i; for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { uint32_t dis_mask = ecore_parity_reg_mask(sc, i); if (dis_mask) { REG_WR(sc, ecore_blocks_parity_data[i].mask_addr, dis_mask); ECORE_MSG("Setting parity mask " "for %s to\t\t0x%x", ecore_blocks_parity_data[i].name, dis_mask); } } /* Disable MCP parity attentions */ ecore_set_mcp_parity(sc, FALSE); } /** * Clear the parity error status registers. */ static inline void ecore_clear_blocks_parity(struct bnx2x_softc *sc) { uint32_t i; uint32_t reg_val, mcp_aeu_bits = AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY; /* Clear SEM_FAST parities */ REG_WR(sc, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); REG_WR(sc, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); REG_WR(sc, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); REG_WR(sc, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1); for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { uint32_t reg_mask = ecore_parity_reg_mask(sc, i); if (reg_mask) { reg_val = REG_RD(sc, ecore_blocks_parity_data[i]. sts_clr_addr); if (reg_val & reg_mask) ECORE_MSG("Parity errors in %s: 0x%x", ecore_blocks_parity_data[i].name, reg_val & reg_mask); } } /* Check if there were parity attentions in MCP */ reg_val = REG_RD(sc, MISC_REG_AEU_AFTER_INVERT_4_MCP); if (reg_val & mcp_aeu_bits) ECORE_MSG("Parity error in MCP: 0x%x", reg_val & mcp_aeu_bits); /* Clear parity attentions in MCP: * [7] clears Latched rom_parity * [8] clears Latched ump_rx_parity * [9] clears Latched ump_tx_parity * [10] clears Latched scpad_parity (both ports) */ REG_WR(sc, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780); } static inline void ecore_enable_blocks_parity(struct bnx2x_softc *sc) { uint32_t i; for (i = 0; i < ARRSIZE(ecore_blocks_parity_data); i++) { uint32_t reg_mask = ecore_parity_reg_mask(sc, i); if (reg_mask) REG_WR(sc, ecore_blocks_parity_data[i].mask_addr, ecore_blocks_parity_data[i].en_mask & reg_mask); } /* Enable MCP parity attentions */ ecore_set_mcp_parity(sc, TRUE); } #endif /* ECORE_INIT_H */ ================================================ FILE: drivers/net/bnx2x/ecore_init_ops.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_INIT_OPS_H #define ECORE_INIT_OPS_H static int ecore_gunzip(struct bnx2x_softc *sc, const uint8_t *zbuf, int len); static void ecore_write_dmae_phys_len(struct bnx2x_softc *sc, ecore_dma_addr_t phys_addr, uint32_t addr, uint32_t len); static void ecore_init_str_wr(struct bnx2x_softc *sc, uint32_t addr, const uint32_t *data, uint32_t len) { uint32_t i; for (i = 0; i < len; i++) REG_WR(sc, addr + i*4, data[i]); } static void ecore_write_big_buf(struct bnx2x_softc *sc, uint32_t addr, uint32_t len) { if (DMAE_READY(sc)) ecore_write_dmae_phys_len(sc, GUNZIP_PHYS(sc), addr, len); else ecore_init_str_wr(sc, addr, GUNZIP_BUF(sc), len); } static void ecore_init_fill(struct bnx2x_softc *sc, uint32_t addr, int fill, uint32_t len) { uint32_t buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4)); uint32_t buf_len32 = buf_len/4; uint32_t i; ECORE_MEMSET(GUNZIP_BUF(sc), (uint8_t)fill, buf_len); for (i = 0; i < len; i += buf_len32) { uint32_t cur_len = min(buf_len32, len - i); ecore_write_big_buf(sc, addr + i*4, cur_len); } } static void ecore_write_big_buf_wb(struct bnx2x_softc *sc, uint32_t addr, uint32_t len) { if (DMAE_READY(sc)) ecore_write_dmae_phys_len(sc, GUNZIP_PHYS(sc), addr, len); else ecore_init_str_wr(sc, addr, GUNZIP_BUF(sc), len); } static void ecore_init_wr_64(struct bnx2x_softc *sc, uint32_t addr, const uint32_t *data, uint32_t len64) { uint32_t buf_len32 = FW_BUF_SIZE/4; uint32_t len = len64*2; uint64_t data64 = 0; uint32_t i; /* 64 bit value is in a blob: first low DWORD, then high DWORD */ data64 = HILO_U64((*(data + 1)), (*data)); len64 = min((uint32_t)(FW_BUF_SIZE/8), len64); for (i = 0; i < len64; i++) { uint64_t *pdata = ((uint64_t *)(GUNZIP_BUF(sc))) + i; *pdata = data64; } for (i = 0; i < len; i += buf_len32) { uint32_t cur_len = min(buf_len32, len - i); ecore_write_big_buf_wb(sc, addr + i*4, cur_len); } } /********************************************************* There are different blobs for each PRAM section. In addition, each blob write operation is divided into a few operations in order to decrease the amount of phys. contiguous buffer needed. Thus, when we select a blob the address may be with some offset from the beginning of PRAM section. The same holds for the INT_TABLE sections. **********************************************************/ #define IF_IS_INT_TABLE_ADDR(base, addr) \ if (((base) <= (addr)) && ((base) + 0x400 >= (addr))) #define IF_IS_PRAM_ADDR(base, addr) \ if (((base) <= (addr)) && ((base) + 0x40000 >= (addr))) static const uint8_t *ecore_sel_blob(struct bnx2x_softc *sc, uint32_t addr, const uint8_t *data) { IF_IS_INT_TABLE_ADDR(TSEM_REG_INT_TABLE, addr) data = INIT_TSEM_INT_TABLE_DATA(sc); else IF_IS_INT_TABLE_ADDR(CSEM_REG_INT_TABLE, addr) data = INIT_CSEM_INT_TABLE_DATA(sc); else IF_IS_INT_TABLE_ADDR(USEM_REG_INT_TABLE, addr) data = INIT_USEM_INT_TABLE_DATA(sc); else IF_IS_INT_TABLE_ADDR(XSEM_REG_INT_TABLE, addr) data = INIT_XSEM_INT_TABLE_DATA(sc); else IF_IS_PRAM_ADDR(TSEM_REG_PRAM, addr) data = INIT_TSEM_PRAM_DATA(sc); else IF_IS_PRAM_ADDR(CSEM_REG_PRAM, addr) data = INIT_CSEM_PRAM_DATA(sc); else IF_IS_PRAM_ADDR(USEM_REG_PRAM, addr) data = INIT_USEM_PRAM_DATA(sc); else IF_IS_PRAM_ADDR(XSEM_REG_PRAM, addr) data = INIT_XSEM_PRAM_DATA(sc); return data; } static void ecore_init_wr_wb(struct bnx2x_softc *sc, uint32_t addr, const uint32_t *data, uint32_t len) { if (DMAE_READY(sc)) VIRT_WR_DMAE_LEN(sc, data, addr, len, 0); else ecore_init_str_wr(sc, addr, data, len); } static void ecore_wr_64(struct bnx2x_softc *sc, uint32_t reg, uint32_t val_lo, uint32_t val_hi) { uint32_t wb_write[2]; wb_write[0] = val_lo; wb_write[1] = val_hi; REG_WR_DMAE_LEN(sc, reg, wb_write, 2); } static void ecore_init_wr_zp(struct bnx2x_softc *sc, uint32_t addr, uint32_t len, uint32_t blob_off) { const uint8_t *data = NULL; int rc; uint32_t i; data = ecore_sel_blob(sc, addr, data) + blob_off*4; rc = ecore_gunzip(sc, data, len); if (rc) return; /* gunzip_outlen is in dwords */ len = GUNZIP_OUTLEN(sc); for (i = 0; i < len; i++) ((uint32_t *)GUNZIP_BUF(sc))[i] = (uint32_t) ECORE_CPU_TO_LE32(((uint32_t *)GUNZIP_BUF(sc))[i]); ecore_write_big_buf_wb(sc, addr, len); } static void ecore_init_block(struct bnx2x_softc *sc, uint32_t block, uint32_t stage) { uint16_t op_start = INIT_OPS_OFFSETS(sc)[BLOCK_OPS_IDX(block, stage, STAGE_START)]; uint16_t op_end = INIT_OPS_OFFSETS(sc)[BLOCK_OPS_IDX(block, stage, STAGE_END)]; const union init_op *op; uint32_t op_idx, op_type, addr, len; const uint32_t *data, *data_base; /* If empty block */ if (op_start == op_end) return; data_base = INIT_DATA(sc); for (op_idx = op_start; op_idx < op_end; op_idx++) { op = (const union init_op *)&(INIT_OPS(sc)[op_idx]); /* Get generic data */ op_type = op->raw.op; addr = op->raw.offset; /* Get data that's used for OP_SW, OP_WB, OP_FW, OP_ZP and * OP_WR64 (we assume that op_arr_write and op_write have the * same structure). */ len = op->arr_wr.data_len; data = data_base + op->arr_wr.data_off; switch (op_type) { case OP_RD: REG_RD(sc, addr); break; case OP_WR: REG_WR(sc, addr, op->write.val); break; case OP_SW: ecore_init_str_wr(sc, addr, data, len); break; case OP_WB: ecore_init_wr_wb(sc, addr, data, len); break; case OP_ZR: case OP_WB_ZR: ecore_init_fill(sc, addr, 0, op->zero.len); break; case OP_ZP: ecore_init_wr_zp(sc, addr, len, op->arr_wr.data_off); break; case OP_WR_64: ecore_init_wr_64(sc, addr, data, len); break; case OP_IF_MODE_AND: /* if any of the flags doesn't match, skip the * conditional block. */ if ((INIT_MODE_FLAGS(sc) & op->if_mode.mode_bit_map) != op->if_mode.mode_bit_map) op_idx += op->if_mode.cmd_offset; break; case OP_IF_MODE_OR: /* if all the flags don't match, skip the conditional * block. */ if ((INIT_MODE_FLAGS(sc) & op->if_mode.mode_bit_map) == 0) op_idx += op->if_mode.cmd_offset; break; /* the following opcodes are unused at the moment. */ case OP_IF_PHASE: case OP_RT: case OP_DELAY: case OP_VERIFY: default: /* Should never get here! */ break; } } } /**************************************************************************** * PXP Arbiter ****************************************************************************/ /* * This code configures the PCI read/write arbiter * which implements a weighted round robin * between the virtual queues in the chip. * * The values were derived for each PCI max payload and max request size. * since max payload and max request size are only known at run time, * this is done as a separate init stage. */ #define NUM_WR_Q 13 #define NUM_RD_Q 29 #define MAX_RD_ORD 3 #define MAX_WR_ORD 2 /* configuration for one arbiter queue */ struct arb_line { int l; int add; int ubound; }; /* derived configuration for each read queue for each max request size */ static const struct arb_line read_arb_data[NUM_RD_Q][MAX_RD_ORD + 1] = { /* 1 */ { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, { {4, 8, 4}, {4, 8, 4}, {4, 8, 4}, {4, 8, 4} }, { {4, 3, 3}, {4, 3, 3}, {4, 3, 3}, {4, 3, 3} }, { {8, 3, 6}, {16, 3, 11}, {16, 3, 11}, {16, 3, 11} }, { {8, 64, 25}, {16, 64, 25}, {32, 64, 25}, {64, 64, 41} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {64, 3, 41} }, /* 10 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 64, 6}, {16, 64, 11}, {32, 64, 21}, {32, 64, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, /* 20 */{ {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 3, 6}, {16, 3, 11}, {32, 3, 21}, {32, 3, 21} }, { {8, 64, 25}, {16, 64, 41}, {32, 64, 81}, {64, 64, 120} } }; /* derived configuration for each write queue for each max request size */ static const struct arb_line write_arb_data[NUM_WR_Q][MAX_WR_ORD + 1] = { /* 1 */ { {4, 6, 3}, {4, 6, 3}, {4, 6, 3} }, { {4, 2, 3}, {4, 2, 3}, {4, 2, 3} }, { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, { {8, 2, 6}, {16, 2, 11}, {32, 2, 21} }, { {8, 64, 25}, {16, 64, 25}, {32, 64, 25} }, { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, { {8, 2, 6}, {16, 2, 11}, {16, 2, 11} }, /* 10 */{ {8, 9, 6}, {16, 9, 11}, {32, 9, 21} }, { {8, 47, 19}, {16, 47, 19}, {32, 47, 21} }, { {8, 9, 6}, {16, 9, 11}, {16, 9, 11} }, { {8, 64, 25}, {16, 64, 41}, {32, 64, 81} } }; /* register addresses for read queues */ static const struct arb_line read_arb_addr[NUM_RD_Q-1] = { /* 1 */ {PXP2_REG_RQ_BW_RD_L0, PXP2_REG_RQ_BW_RD_ADD0, PXP2_REG_RQ_BW_RD_UBOUND0}, {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, PXP2_REG_PSWRQ_BW_UB1}, {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, PXP2_REG_PSWRQ_BW_UB2}, {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, PXP2_REG_PSWRQ_BW_UB3}, {PXP2_REG_RQ_BW_RD_L4, PXP2_REG_RQ_BW_RD_ADD4, PXP2_REG_RQ_BW_RD_UBOUND4}, {PXP2_REG_RQ_BW_RD_L5, PXP2_REG_RQ_BW_RD_ADD5, PXP2_REG_RQ_BW_RD_UBOUND5}, {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, PXP2_REG_PSWRQ_BW_UB6}, {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, PXP2_REG_PSWRQ_BW_UB7}, {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, PXP2_REG_PSWRQ_BW_UB8}, /* 10 */{PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, PXP2_REG_PSWRQ_BW_UB9}, {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, PXP2_REG_PSWRQ_BW_UB10}, {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, PXP2_REG_PSWRQ_BW_UB11}, {PXP2_REG_RQ_BW_RD_L12, PXP2_REG_RQ_BW_RD_ADD12, PXP2_REG_RQ_BW_RD_UBOUND12}, {PXP2_REG_RQ_BW_RD_L13, PXP2_REG_RQ_BW_RD_ADD13, PXP2_REG_RQ_BW_RD_UBOUND13}, {PXP2_REG_RQ_BW_RD_L14, PXP2_REG_RQ_BW_RD_ADD14, PXP2_REG_RQ_BW_RD_UBOUND14}, {PXP2_REG_RQ_BW_RD_L15, PXP2_REG_RQ_BW_RD_ADD15, PXP2_REG_RQ_BW_RD_UBOUND15}, {PXP2_REG_RQ_BW_RD_L16, PXP2_REG_RQ_BW_RD_ADD16, PXP2_REG_RQ_BW_RD_UBOUND16}, {PXP2_REG_RQ_BW_RD_L17, PXP2_REG_RQ_BW_RD_ADD17, PXP2_REG_RQ_BW_RD_UBOUND17}, {PXP2_REG_RQ_BW_RD_L18, PXP2_REG_RQ_BW_RD_ADD18, PXP2_REG_RQ_BW_RD_UBOUND18}, /* 20 */{PXP2_REG_RQ_BW_RD_L19, PXP2_REG_RQ_BW_RD_ADD19, PXP2_REG_RQ_BW_RD_UBOUND19}, {PXP2_REG_RQ_BW_RD_L20, PXP2_REG_RQ_BW_RD_ADD20, PXP2_REG_RQ_BW_RD_UBOUND20}, {PXP2_REG_RQ_BW_RD_L22, PXP2_REG_RQ_BW_RD_ADD22, PXP2_REG_RQ_BW_RD_UBOUND22}, {PXP2_REG_RQ_BW_RD_L23, PXP2_REG_RQ_BW_RD_ADD23, PXP2_REG_RQ_BW_RD_UBOUND23}, {PXP2_REG_RQ_BW_RD_L24, PXP2_REG_RQ_BW_RD_ADD24, PXP2_REG_RQ_BW_RD_UBOUND24}, {PXP2_REG_RQ_BW_RD_L25, PXP2_REG_RQ_BW_RD_ADD25, PXP2_REG_RQ_BW_RD_UBOUND25}, {PXP2_REG_RQ_BW_RD_L26, PXP2_REG_RQ_BW_RD_ADD26, PXP2_REG_RQ_BW_RD_UBOUND26}, {PXP2_REG_RQ_BW_RD_L27, PXP2_REG_RQ_BW_RD_ADD27, PXP2_REG_RQ_BW_RD_UBOUND27}, {PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, PXP2_REG_PSWRQ_BW_UB28} }; /* register addresses for write queues */ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { /* 1 */ {PXP2_REG_PSWRQ_BW_L1, PXP2_REG_PSWRQ_BW_ADD1, PXP2_REG_PSWRQ_BW_UB1}, {PXP2_REG_PSWRQ_BW_L2, PXP2_REG_PSWRQ_BW_ADD2, PXP2_REG_PSWRQ_BW_UB2}, {PXP2_REG_PSWRQ_BW_L3, PXP2_REG_PSWRQ_BW_ADD3, PXP2_REG_PSWRQ_BW_UB3}, {PXP2_REG_PSWRQ_BW_L6, PXP2_REG_PSWRQ_BW_ADD6, PXP2_REG_PSWRQ_BW_UB6}, {PXP2_REG_PSWRQ_BW_L7, PXP2_REG_PSWRQ_BW_ADD7, PXP2_REG_PSWRQ_BW_UB7}, {PXP2_REG_PSWRQ_BW_L8, PXP2_REG_PSWRQ_BW_ADD8, PXP2_REG_PSWRQ_BW_UB8}, {PXP2_REG_PSWRQ_BW_L9, PXP2_REG_PSWRQ_BW_ADD9, PXP2_REG_PSWRQ_BW_UB9}, {PXP2_REG_PSWRQ_BW_L10, PXP2_REG_PSWRQ_BW_ADD10, PXP2_REG_PSWRQ_BW_UB10}, {PXP2_REG_PSWRQ_BW_L11, PXP2_REG_PSWRQ_BW_ADD11, PXP2_REG_PSWRQ_BW_UB11}, /* 10 */{PXP2_REG_PSWRQ_BW_L28, PXP2_REG_PSWRQ_BW_ADD28, PXP2_REG_PSWRQ_BW_UB28}, {PXP2_REG_RQ_BW_WR_L29, PXP2_REG_RQ_BW_WR_ADD29, PXP2_REG_RQ_BW_WR_UBOUND29}, {PXP2_REG_RQ_BW_WR_L30, PXP2_REG_RQ_BW_WR_ADD30, PXP2_REG_RQ_BW_WR_UBOUND30} }; static void ecore_init_pxp_arb(struct bnx2x_softc *sc, int r_order, int w_order) { uint32_t val, i; if (r_order > MAX_RD_ORD) { ECORE_MSG("read order of %d order adjusted to %d", r_order, MAX_RD_ORD); r_order = MAX_RD_ORD; } if (w_order > MAX_WR_ORD) { ECORE_MSG("write order of %d order adjusted to %d", w_order, MAX_WR_ORD); w_order = MAX_WR_ORD; } if (CHIP_REV_IS_FPGA(sc)) { ECORE_MSG("write order adjusted to 1 for FPGA"); w_order = 0; } ECORE_MSG("read order %d write order %d", r_order, w_order); for (i = 0; i < NUM_RD_Q-1; i++) { REG_WR(sc, read_arb_addr[i].l, read_arb_data[i][r_order].l); REG_WR(sc, read_arb_addr[i].add, read_arb_data[i][r_order].add); REG_WR(sc, read_arb_addr[i].ubound, read_arb_data[i][r_order].ubound); } for (i = 0; i < NUM_WR_Q-1; i++) { if ((write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L29) || (write_arb_addr[i].l == PXP2_REG_RQ_BW_WR_L30)) { REG_WR(sc, write_arb_addr[i].l, write_arb_data[i][w_order].l); REG_WR(sc, write_arb_addr[i].add, write_arb_data[i][w_order].add); REG_WR(sc, write_arb_addr[i].ubound, write_arb_data[i][w_order].ubound); } else { val = REG_RD(sc, write_arb_addr[i].l); REG_WR(sc, write_arb_addr[i].l, val | (write_arb_data[i][w_order].l << 10)); val = REG_RD(sc, write_arb_addr[i].add); REG_WR(sc, write_arb_addr[i].add, val | (write_arb_data[i][w_order].add << 10)); val = REG_RD(sc, write_arb_addr[i].ubound); REG_WR(sc, write_arb_addr[i].ubound, val | (write_arb_data[i][w_order].ubound << 7)); } } val = write_arb_data[NUM_WR_Q-1][w_order].add; val += write_arb_data[NUM_WR_Q-1][w_order].ubound << 10; val += write_arb_data[NUM_WR_Q-1][w_order].l << 17; REG_WR(sc, PXP2_REG_PSWRQ_BW_RD, val); val = read_arb_data[NUM_RD_Q-1][r_order].add; val += read_arb_data[NUM_RD_Q-1][r_order].ubound << 10; val += read_arb_data[NUM_RD_Q-1][r_order].l << 17; REG_WR(sc, PXP2_REG_PSWRQ_BW_WR, val); REG_WR(sc, PXP2_REG_RQ_WR_MBS0, w_order); REG_WR(sc, PXP2_REG_RQ_WR_MBS1, w_order); REG_WR(sc, PXP2_REG_RQ_RD_MBS0, r_order); REG_WR(sc, PXP2_REG_RQ_RD_MBS1, r_order); if (CHIP_IS_E1H(sc) && (r_order == MAX_RD_ORD)) REG_WR(sc, PXP2_REG_RQ_PDR_LIMIT, 0xe00); if (CHIP_IS_E3(sc)) REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x4 << w_order)); else if (CHIP_IS_E2(sc)) REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x8 << w_order)); else REG_WR(sc, PXP2_REG_WR_USDMDP_TH, (0x18 << w_order)); /* MPS w_order optimal TH presently TH * 128 0 0 2 * 256 1 1 3 * >=512 2 2 3 */ /* DMAE is special */ if (!CHIP_IS_E1H(sc)) { /* E2 can use optimal TH */ val = w_order; REG_WR(sc, PXP2_REG_WR_DMAE_MPS, val); } else { val = ((w_order == 0) ? 2 : 3); REG_WR(sc, PXP2_REG_WR_DMAE_MPS, 2); } REG_WR(sc, PXP2_REG_WR_HC_MPS, val); REG_WR(sc, PXP2_REG_WR_USDM_MPS, val); REG_WR(sc, PXP2_REG_WR_CSDM_MPS, val); REG_WR(sc, PXP2_REG_WR_TSDM_MPS, val); REG_WR(sc, PXP2_REG_WR_XSDM_MPS, val); REG_WR(sc, PXP2_REG_WR_QM_MPS, val); REG_WR(sc, PXP2_REG_WR_TM_MPS, val); REG_WR(sc, PXP2_REG_WR_SRC_MPS, val); REG_WR(sc, PXP2_REG_WR_DBG_MPS, val); REG_WR(sc, PXP2_REG_WR_CDU_MPS, val); /* Validate number of tags suppoted by device */ #define PCIE_REG_PCIER_TL_HDR_FC_ST 0x2980 val = REG_RD(sc, PCIE_REG_PCIER_TL_HDR_FC_ST); val &= 0xFF; if (val <= 0x20) REG_WR(sc, PXP2_REG_PGL_TAGS_LIMIT, 0x20); } /**************************************************************************** * ILT management ****************************************************************************/ /* * This codes hides the low level HW interaction for ILT management and * configuration. The API consists of a shadow ILT table which is set by the * driver and a set of routines to use it to configure the HW. * */ /* ILT HW init operations */ /* ILT memory management operations */ #define ILT_MEMOP_ALLOC 0 #define ILT_MEMOP_FREE 1 /* the phys address is shifted right 12 bits and has an added * 1=valid bit added to the 53rd bit * then since this is a wide register(TM) * we split it into two 32 bit writes */ #define ILT_ADDR1(x) ((uint32_t)(((uint64_t)x >> 12) & 0xFFFFFFFF)) #define ILT_ADDR2(x) ((uint32_t)((1 << 20) | ((uint64_t)x >> 44))) #define ILT_RANGE(f, l) (((l) << 10) | f) static int ecore_ilt_line_mem_op(struct bnx2x_softc *sc, struct ilt_line *line, uint32_t size, uint8_t memop, int cli_num, int i) { #define ECORE_ILT_NAMESIZE 10 char str[ECORE_ILT_NAMESIZE]; if (memop == ILT_MEMOP_FREE) { ECORE_ILT_FREE(line->page, line->page_mapping, line->size); return 0; } snprintf(str, ECORE_ILT_NAMESIZE, "ILT_%d_%d", cli_num, i); ECORE_ILT_ZALLOC(line->page, &line->page_mapping, size, str); if (!line->page) return -1; line->size = size; return 0; } static int ecore_ilt_client_mem_op(struct bnx2x_softc *sc, int cli_num, uint8_t memop) { int i, rc = 0; struct ecore_ilt *ilt = SC_ILT(sc); struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; if (!ilt || !ilt->lines) return -1; if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM)) return 0; for (i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) { rc = ecore_ilt_line_mem_op(sc, &ilt->lines[i], ilt_cli->page_size, memop, cli_num, i); } return rc; } static inline int ecore_ilt_mem_op_cnic(struct bnx2x_softc *sc, uint8_t memop) { int rc = 0; if (CONFIGURE_NIC_MODE(sc)) rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_SRC, memop); if (!rc) rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_TM, memop); return rc; } static int ecore_ilt_mem_op(struct bnx2x_softc *sc, uint8_t memop) { int rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_CDU, memop); if (!rc) rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_QM, memop); if (!rc && CNIC_SUPPORT(sc) && !CONFIGURE_NIC_MODE(sc)) rc = ecore_ilt_client_mem_op(sc, ILT_CLIENT_SRC, memop); return rc; } static void ecore_ilt_line_wr(struct bnx2x_softc *sc, int abs_idx, ecore_dma_addr_t page_mapping) { uint32_t reg; reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8; ecore_wr_64(sc, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping)); } static void ecore_ilt_line_init_op(struct bnx2x_softc *sc, struct ecore_ilt *ilt, int idx, uint8_t initop) { ecore_dma_addr_t null_mapping; int abs_idx = ilt->start_line + idx; switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET: ecore_ilt_line_wr(sc, abs_idx, ilt->lines[idx].page_mapping); break; case INITOP_CLEAR: null_mapping = 0; ecore_ilt_line_wr(sc, abs_idx, null_mapping); break; } } static void ecore_ilt_boundry_init_op(struct bnx2x_softc *sc, struct ilt_client_info *ilt_cli, uint32_t ilt_start) { uint32_t start_reg = 0; uint32_t end_reg = 0; /* The boundary is either SET or INIT, CLEAR => SET and for now SET ~~ INIT */ /* find the appropriate regs */ switch (ilt_cli->client_num) { case ILT_CLIENT_CDU: start_reg = PXP2_REG_RQ_CDU_FIRST_ILT; end_reg = PXP2_REG_RQ_CDU_LAST_ILT; break; case ILT_CLIENT_QM: start_reg = PXP2_REG_RQ_QM_FIRST_ILT; end_reg = PXP2_REG_RQ_QM_LAST_ILT; break; case ILT_CLIENT_SRC: start_reg = PXP2_REG_RQ_SRC_FIRST_ILT; end_reg = PXP2_REG_RQ_SRC_LAST_ILT; break; case ILT_CLIENT_TM: start_reg = PXP2_REG_RQ_TM_FIRST_ILT; end_reg = PXP2_REG_RQ_TM_LAST_ILT; break; } REG_WR(sc, start_reg, (ilt_start + ilt_cli->start)); REG_WR(sc, end_reg, (ilt_start + ilt_cli->end)); } static void ecore_ilt_client_init_op_ilt(struct bnx2x_softc *sc, struct ecore_ilt *ilt, struct ilt_client_info *ilt_cli, uint8_t initop) { int i; if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) return; for (i = ilt_cli->start; i <= ilt_cli->end; i++) ecore_ilt_line_init_op(sc, ilt, i, initop); /* init/clear the ILT boundries */ ecore_ilt_boundry_init_op(sc, ilt_cli, ilt->start_line); } static void ecore_ilt_client_init_op(struct bnx2x_softc *sc, struct ilt_client_info *ilt_cli, uint8_t initop) { struct ecore_ilt *ilt = SC_ILT(sc); ecore_ilt_client_init_op_ilt(sc, ilt, ilt_cli, initop); } static void ecore_ilt_client_id_init_op(struct bnx2x_softc *sc, int cli_num, uint8_t initop) { struct ecore_ilt *ilt = SC_ILT(sc); struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; ecore_ilt_client_init_op(sc, ilt_cli, initop); } static inline void ecore_ilt_init_op_cnic(struct bnx2x_softc *sc, uint8_t initop) { if (CONFIGURE_NIC_MODE(sc)) ecore_ilt_client_id_init_op(sc, ILT_CLIENT_SRC, initop); ecore_ilt_client_id_init_op(sc, ILT_CLIENT_TM, initop); } static void ecore_ilt_init_op(struct bnx2x_softc *sc, uint8_t initop) { ecore_ilt_client_id_init_op(sc, ILT_CLIENT_CDU, initop); ecore_ilt_client_id_init_op(sc, ILT_CLIENT_QM, initop); if (CNIC_SUPPORT(sc) && !CONFIGURE_NIC_MODE(sc)) ecore_ilt_client_id_init_op(sc, ILT_CLIENT_SRC, initop); } static void ecore_ilt_init_client_psz(struct bnx2x_softc *sc, int cli_num, uint32_t psz_reg, uint8_t initop) { struct ecore_ilt *ilt = SC_ILT(sc); struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) return; switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET: REG_WR(sc, psz_reg, ILOG2(ilt_cli->page_size >> 12)); break; case INITOP_CLEAR: break; } } /* * called during init common stage, ilt clients should be initialized * prioir to calling this function */ static void ecore_ilt_init_page_size(struct bnx2x_softc *sc, uint8_t initop) { ecore_ilt_init_client_psz(sc, ILT_CLIENT_CDU, PXP2_REG_RQ_CDU_P_SIZE, initop); ecore_ilt_init_client_psz(sc, ILT_CLIENT_QM, PXP2_REG_RQ_QM_P_SIZE, initop); ecore_ilt_init_client_psz(sc, ILT_CLIENT_SRC, PXP2_REG_RQ_SRC_P_SIZE, initop); ecore_ilt_init_client_psz(sc, ILT_CLIENT_TM, PXP2_REG_RQ_TM_P_SIZE, initop); } /**************************************************************************** * QM initializations ****************************************************************************/ #define QM_QUEUES_PER_FUNC 16 #define QM_INIT_MIN_CID_COUNT 31 #define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT) /* called during init port stage */ static void ecore_qm_init_cid_count(struct bnx2x_softc *sc, int qm_cid_count, uint8_t initop) { int port = SC_PORT(sc); if (QM_INIT(qm_cid_count)) { switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET: REG_WR(sc, QM_REG_CONNNUM_0 + port*4, qm_cid_count/16 - 1); break; case INITOP_CLEAR: break; } } } static void ecore_qm_set_ptr_table(struct bnx2x_softc *sc, int qm_cid_count, uint32_t base_reg, uint32_t reg) { int i; uint32_t wb_data[2] = {0, 0}; for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) { REG_WR(sc, base_reg + i*4, qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); ecore_init_wr_wb(sc, reg + i*8, wb_data, 2); } } /* called during init common stage */ static void ecore_qm_init_ptr_table(struct bnx2x_softc *sc, int qm_cid_count, uint8_t initop) { if (!QM_INIT(qm_cid_count)) return; switch (initop) { case INITOP_INIT: /* set in the init-value array */ case INITOP_SET: ecore_qm_set_ptr_table(sc, qm_cid_count, QM_REG_BASEADDR, QM_REG_PTRTBL); if (CHIP_IS_E1H(sc)) ecore_qm_set_ptr_table(sc, qm_cid_count, QM_REG_BASEADDR_EXT_A, QM_REG_PTRTBL_EXT_A); break; case INITOP_CLEAR: break; } } /**************************************************************************** * SRC initializations ****************************************************************************/ #ifdef ECORE_L5 /* called during init func stage */ static void ecore_src_init_t2(struct bnx2x_softc *sc, struct src_ent *t2, ecore_dma_addr_t t2_mapping, int src_cid_count) { int i; int port = SC_PORT(sc); /* Initialize T2 */ for (i = 0; i < src_cid_count-1; i++) t2[i].next = (uint64_t)(t2_mapping + (i+1)*sizeof(struct src_ent)); /* tell the searcher where the T2 table is */ REG_WR(sc, SRC_REG_COUNTFREE0 + port*4, src_cid_count); ecore_wr_64(sc, SRC_REG_FIRSTFREE0 + port*16, U64_LO(t2_mapping), U64_HI(t2_mapping)); ecore_wr_64(sc, SRC_REG_LASTFREE0 + port*16, U64_LO((uint64_t)t2_mapping + (src_cid_count-1) * sizeof(struct src_ent)), U64_HI((uint64_t)t2_mapping + (src_cid_count-1) * sizeof(struct src_ent))); } #endif #endif /* ECORE_INIT_OPS_H */ ================================================ FILE: drivers/net/bnx2x/ecore_mfw_req.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_MFW_REQ_H #define ECORE_MFW_REQ_H #define PORT_0 0 #define PORT_1 1 #define PORT_MAX 2 #define NVM_PATH_MAX 2 /* FCoE capabilities required from the driver */ struct fcoe_capabilities { uint32_t capability1; /* Maximum number of I/Os per connection */ #define FCOE_IOS_PER_CONNECTION_MASK 0x0000ffff #define FCOE_IOS_PER_CONNECTION_SHIFT 0 /* Maximum number of Logins per port */ #define FCOE_LOGINS_PER_PORT_MASK 0xffff0000 #define FCOE_LOGINS_PER_PORT_SHIFT 16 uint32_t capability2; /* Maximum number of exchanges */ #define FCOE_NUMBER_OF_EXCHANGES_MASK 0x0000ffff #define FCOE_NUMBER_OF_EXCHANGES_SHIFT 0 /* Maximum NPIV WWN per port */ #define FCOE_NPIV_WWN_PER_PORT_MASK 0xffff0000 #define FCOE_NPIV_WWN_PER_PORT_SHIFT 16 uint32_t capability3; /* Maximum number of targets supported */ #define FCOE_TARGETS_SUPPORTED_MASK 0x0000ffff #define FCOE_TARGETS_SUPPORTED_SHIFT 0 /* Maximum number of outstanding commands across all connections */ #define FCOE_OUTSTANDING_COMMANDS_MASK 0xffff0000 #define FCOE_OUTSTANDING_COMMANDS_SHIFT 16 uint32_t capability4; #define FCOE_CAPABILITY4_STATEFUL 0x00000001 #define FCOE_CAPABILITY4_STATELESS 0x00000002 #define FCOE_CAPABILITY4_CAPABILITIES_REPORTED_VALID 0x00000004 }; struct glob_ncsi_oem_data { uint32_t driver_version; uint32_t unused[3]; struct fcoe_capabilities fcoe_features[NVM_PATH_MAX][PORT_MAX]; }; /* current drv_info version */ #define DRV_INFO_CUR_VER 2 /* drv_info op codes supported */ enum drv_info_opcode { ETH_STATS_OPCODE, FCOE_STATS_OPCODE, ISCSI_STATS_OPCODE }; #define ETH_STAT_INFO_VERSION_LEN 12 /* Per PCI Function Ethernet Statistics required from the driver */ struct eth_stats_info { /* Function's Driver Version. padded to 12 */ char version[ETH_STAT_INFO_VERSION_LEN]; /* Locally Admin Addr. BigEndian EIU48. Actual size is 6 bytes */ uint8_t mac_local[8]; uint8_t mac_add1[8]; /* Additional Programmed MAC Addr 1. */ uint8_t mac_add2[8]; /* Additional Programmed MAC Addr 2. */ uint32_t mtu_size; /* MTU Size. Note : Negotiated MTU */ uint32_t feature_flags; /* Feature_Flags. */ #define FEATURE_ETH_CHKSUM_OFFLOAD_MASK 0x01 #define FEATURE_ETH_LSO_MASK 0x02 #define FEATURE_ETH_BOOTMODE_MASK 0x1C #define FEATURE_ETH_BOOTMODE_SHIFT 2 #define FEATURE_ETH_BOOTMODE_NONE (0x0 << 2) #define FEATURE_ETH_BOOTMODE_PXE (0x1 << 2) #define FEATURE_ETH_BOOTMODE_ISCSI (0x2 << 2) #define FEATURE_ETH_BOOTMODE_FCOE (0x3 << 2) #define FEATURE_ETH_TOE_MASK 0x20 uint32_t lso_max_size; /* LSO MaxOffloadSize. */ uint32_t lso_min_seg_cnt; /* LSO MinSegmentCount. */ /* Num Offloaded Connections TCP_IPv4. */ uint32_t ipv4_ofld_cnt; /* Num Offloaded Connections TCP_IPv6. */ uint32_t ipv6_ofld_cnt; uint32_t promiscuous_mode; /* Promiscuous Mode. non-zero true */ uint32_t txq_size; /* TX Descriptors Queue Size */ uint32_t rxq_size; /* RX Descriptors Queue Size */ /* TX Descriptor Queue Avg Depth. % Avg Queue Depth since last poll */ uint32_t txq_avg_depth; /* RX Descriptors Queue Avg Depth. % Avg Queue Depth since last poll */ uint32_t rxq_avg_depth; /* IOV_Offload. 0=none; 1=MultiQueue, 2=VEB 3= VEPA*/ uint32_t iov_offload; /* Number of NetQueue/VMQ Config'd. */ uint32_t netq_cnt; uint32_t vf_cnt; /* Num VF assigned to this PF. */ }; /* Per PCI Function FCOE Statistics required from the driver */ struct fcoe_stats_info { uint8_t version[12]; /* Function's Driver Version. */ uint8_t mac_local[8]; /* Locally Admin Addr. */ uint8_t mac_add1[8]; /* Additional Programmed MAC Addr 1. */ uint8_t mac_add2[8]; /* Additional Programmed MAC Addr 2. */ /* QoS Priority (per 802.1p). 0-7255 */ uint32_t qos_priority; uint32_t txq_size; /* FCoE TX Descriptors Queue Size. */ uint32_t rxq_size; /* FCoE RX Descriptors Queue Size. */ /* FCoE TX Descriptor Queue Avg Depth. */ uint32_t txq_avg_depth; /* FCoE RX Descriptors Queue Avg Depth. */ uint32_t rxq_avg_depth; uint32_t rx_frames_lo; /* FCoE RX Frames received. */ uint32_t rx_frames_hi; /* FCoE RX Frames received. */ uint32_t rx_bytes_lo; /* FCoE RX Bytes received. */ uint32_t rx_bytes_hi; /* FCoE RX Bytes received. */ uint32_t tx_frames_lo; /* FCoE TX Frames sent. */ uint32_t tx_frames_hi; /* FCoE TX Frames sent. */ uint32_t tx_bytes_lo; /* FCoE TX Bytes sent. */ uint32_t tx_bytes_hi; /* FCoE TX Bytes sent. */ uint32_t rx_fcs_errors; /* number of receive packets with FCS errors */ uint32_t rx_fc_crc_errors; /* number of FC frames with CRC errors*/ uint32_t fip_login_failures; /* number of FCoE/FIP Login failures */ }; /* Per PCI Function iSCSI Statistics required from the driver*/ struct iscsi_stats_info { uint8_t version[12]; /* Function's Driver Version. */ uint8_t mac_local[8]; /* Locally Admin iSCSI MAC Addr. */ uint8_t mac_add1[8]; /* Additional Programmed MAC Addr 1. */ /* QoS Priority (per 802.1p). 0-7255 */ uint32_t qos_priority; uint8_t initiator_name[64]; /* iSCSI Boot Initiator Node name. */ uint8_t ww_port_name[64]; /* iSCSI World wide port name */ uint8_t boot_target_name[64];/* iSCSI Boot Target Name. */ uint8_t boot_target_ip[16]; /* iSCSI Boot Target IP. */ uint32_t boot_target_portal; /* iSCSI Boot Target Portal. */ uint8_t boot_init_ip[16]; /* iSCSI Boot Initiator IP Address. */ uint32_t max_frame_size; /* Max Frame Size. bytes */ uint32_t txq_size; /* PDU TX Descriptors Queue Size. */ uint32_t rxq_size; /* PDU RX Descriptors Queue Size. */ uint32_t txq_avg_depth; /*PDU TX Descriptor Queue Avg Depth. */ uint32_t rxq_avg_depth; /*PDU RX Descriptors Queue Avg Depth. */ uint32_t rx_pdus_lo; /* iSCSI PDUs received. */ uint32_t rx_pdus_hi; /* iSCSI PDUs received. */ uint32_t rx_bytes_lo; /* iSCSI RX Bytes received. */ uint32_t rx_bytes_hi; /* iSCSI RX Bytes received. */ uint32_t tx_pdus_lo; /* iSCSI PDUs sent. */ uint32_t tx_pdus_hi; /* iSCSI PDUs sent. */ uint32_t tx_bytes_lo; /* iSCSI PDU TX Bytes sent. */ uint32_t tx_bytes_hi; /* iSCSI PDU TX Bytes sent. */ uint32_t pcp_prior_map_tbl; /*C-PCP to S-PCP Priority MapTable. 9 nibbles, the position of each nibble represents the C-PCP value, the value of the nibble = S-PCP value.*/ }; union drv_info_to_mcp { struct eth_stats_info ether_stat; struct fcoe_stats_info fcoe_stat; struct iscsi_stats_info iscsi_stat; }; #endif /* ECORE_MFW_REQ_H */ ================================================ FILE: drivers/net/bnx2x/ecore_reg.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_REG_H #define ECORE_REG_H #define ATC_ATC_INT_STS_REG_ADDRESS_ERROR \ (0x1<<0) #define ATC_ATC_INT_STS_REG_ATC_GPA_MULTIPLE_HITS \ (0x1<<2) #define ATC_ATC_INT_STS_REG_ATC_IREQ_LESS_THAN_STU \ (0x1<<5) #define ATC_ATC_INT_STS_REG_ATC_RCPL_TO_EMPTY_CNT \ (0x1<<3) #define ATC_ATC_INT_STS_REG_ATC_TCPL_ERROR \ (0x1<<4) #define ATC_ATC_INT_STS_REG_ATC_TCPL_TO_NOT_PEND \ (0x1<<1) #define ATC_REG_ATC_INIT_DONE \ 0x1100bcUL #define ATC_REG_ATC_INT_STS_CLR \ 0x1101c0UL #define ATC_REG_ATC_PRTY_MASK \ 0x1101d8UL #define ATC_REG_ATC_PRTY_STS_CLR \ 0x1101d0UL #define BRB1_REG_BRB1_INT_MASK \ 0x60128UL #define BRB1_REG_BRB1_PRTY_MASK \ 0x60138UL #define BRB1_REG_BRB1_PRTY_STS_CLR \ 0x60130UL #define BRB1_REG_MAC_GUARANTIED_0 \ 0x601e8UL #define BRB1_REG_MAC_GUARANTIED_1 \ 0x60240UL #define BRB1_REG_NUM_OF_FULL_BLOCKS \ 0x60090UL #define BRB1_REG_PAUSE_HIGH_THRESHOLD_0 \ 0x60078UL #define BRB1_REG_PAUSE_LOW_THRESHOLD_0 \ 0x60068UL #define BRB1_REG_PORT_NUM_OCC_BLOCKS_0 \ 0x60094UL #define CCM_REG_CCM_INT_MASK \ 0xd01e4UL #define CCM_REG_CCM_PRTY_MASK \ 0xd01f4UL #define CCM_REG_CCM_PRTY_STS_CLR \ 0xd01ecUL #define CDU_REG_CDU_GLOBAL_PARAMS \ 0x101020UL #define CDU_REG_CDU_INT_MASK \ 0x10103cUL #define CDU_REG_CDU_PRTY_MASK \ 0x10104cUL #define CDU_REG_CDU_PRTY_STS_CLR \ 0x101044UL #define CFC_REG_AC_INIT_DONE \ 0x104078UL #define CFC_REG_CAM_INIT_DONE \ 0x10407cUL #define CFC_REG_CFC_INT_MASK \ 0x104108UL #define CFC_REG_CFC_INT_STS_CLR \ 0x104100UL #define CFC_REG_CFC_PRTY_MASK \ 0x104118UL #define CFC_REG_CFC_PRTY_STS_CLR \ 0x104110UL #define CFC_REG_DEBUG0 \ 0x104050UL #define CFC_REG_INIT_REG \ 0x10404cUL #define CFC_REG_LL_INIT_DONE \ 0x104074UL #define CFC_REG_NUM_LCIDS_INSIDE_PF \ 0x104120UL #define CFC_REG_STRONG_ENABLE_PF \ 0x104128UL #define CFC_REG_WEAK_ENABLE_PF \ 0x104124UL #define CSDM_REG_CSDM_INT_MASK_0 \ 0xc229cUL #define CSDM_REG_CSDM_INT_MASK_1 \ 0xc22acUL #define CSDM_REG_CSDM_PRTY_MASK \ 0xc22bcUL #define CSDM_REG_CSDM_PRTY_STS_CLR \ 0xc22b4UL #define CSEM_REG_CSEM_INT_MASK_0 \ 0x200110UL #define CSEM_REG_CSEM_INT_MASK_1 \ 0x200120UL #define CSEM_REG_CSEM_PRTY_MASK_0 \ 0x200130UL #define CSEM_REG_CSEM_PRTY_MASK_1 \ 0x200140UL #define CSEM_REG_CSEM_PRTY_STS_CLR_0 \ 0x200128UL #define CSEM_REG_CSEM_PRTY_STS_CLR_1 \ 0x200138UL #define CSEM_REG_FAST_MEMORY \ 0x220000UL #define CSEM_REG_INT_TABLE \ 0x200400UL #define CSEM_REG_PASSIVE_BUFFER \ 0x202000UL #define CSEM_REG_PRAM \ 0x240000UL #define CSEM_REG_VFPF_ERR_NUM \ 0x200380UL #define DBG_REG_DBG_PRTY_MASK \ 0xc0a8UL #define DBG_REG_DBG_PRTY_STS_CLR \ 0xc0a0UL #define DMAE_REG_BACKWARD_COMP_EN \ 0x10207cUL #define DMAE_REG_CMD_MEM \ 0x102400UL #define DMAE_REG_DMAE_INT_MASK \ 0x102054UL #define DMAE_REG_DMAE_PRTY_MASK \ 0x102064UL #define DMAE_REG_DMAE_PRTY_STS_CLR \ 0x10205cUL #define DMAE_REG_GO_C0 \ 0x102080UL #define DMAE_REG_GO_C1 \ 0x102084UL #define DMAE_REG_GO_C10 \ 0x102088UL #define DMAE_REG_GO_C11 \ 0x10208cUL #define DMAE_REG_GO_C12 \ 0x102090UL #define DMAE_REG_GO_C13 \ 0x102094UL #define DMAE_REG_GO_C14 \ 0x102098UL #define DMAE_REG_GO_C15 \ 0x10209cUL #define DMAE_REG_GO_C2 \ 0x1020a0UL #define DMAE_REG_GO_C3 \ 0x1020a4UL #define DMAE_REG_GO_C4 \ 0x1020a8UL #define DMAE_REG_GO_C5 \ 0x1020acUL #define DMAE_REG_GO_C6 \ 0x1020b0UL #define DMAE_REG_GO_C7 \ 0x1020b4UL #define DMAE_REG_GO_C8 \ 0x1020b8UL #define DMAE_REG_GO_C9 \ 0x1020bcUL #define DORQ_REG_DORQ_INT_MASK \ 0x170180UL #define DORQ_REG_DORQ_INT_STS_CLR \ 0x170178UL #define DORQ_REG_DORQ_PRTY_MASK \ 0x170190UL #define DORQ_REG_DORQ_PRTY_STS_CLR \ 0x170188UL #define DORQ_REG_DPM_CID_OFST \ 0x170030UL #define DORQ_REG_MAX_RVFID_SIZE \ 0x1701ecUL #define DORQ_REG_NORM_CID_OFST \ 0x17002cUL #define DORQ_REG_PF_USAGE_CNT \ 0x1701d0UL #define DORQ_REG_VF_NORM_CID_BASE \ 0x1701a0UL #define DORQ_REG_VF_NORM_CID_OFST \ 0x1701f4UL #define DORQ_REG_VF_NORM_CID_WND_SIZE \ 0x1701a4UL #define DORQ_REG_VF_NORM_MAX_CID_COUNT \ 0x1701e4UL #define DORQ_REG_VF_NORM_VF_BASE \ 0x1701a8UL #define DORQ_REG_VF_TYPE_MASK_0 \ 0x170218UL #define DORQ_REG_VF_TYPE_MAX_MCID_0 \ 0x1702d8UL #define DORQ_REG_VF_TYPE_MIN_MCID_0 \ 0x170298UL #define DORQ_REG_VF_TYPE_VALUE_0 \ 0x170258UL #define DORQ_REG_VF_USAGE_CNT \ 0x170320UL #define DORQ_REG_VF_USAGE_CT_LIMIT \ 0x170340UL #define HC_CONFIG_0_REG_ATTN_BIT_EN_0 \ (0x1<<4) #define HC_CONFIG_0_REG_BLOCK_DISABLE_0 \ (0x1<<0) #define HC_CONFIG_0_REG_INT_LINE_EN_0 \ (0x1<<3) #define HC_CONFIG_0_REG_MSI_ATTN_EN_0 \ (0x1<<7) #define HC_CONFIG_0_REG_MSI_MSIX_INT_EN_0 \ (0x1<<2) #define HC_CONFIG_0_REG_SINGLE_ISR_EN_0 \ (0x1<<1) #define HC_CONFIG_1_REG_BLOCK_DISABLE_1 \ (0x1<<0) #define HC_REG_ATTN_MSG0_ADDR_L \ 0x108018UL #define HC_REG_ATTN_MSG1_ADDR_L \ 0x108020UL #define HC_REG_COMMAND_REG \ 0x108180UL #define HC_REG_CONFIG_0 \ 0x108000UL #define HC_REG_CONFIG_1 \ 0x108004UL #define HC_REG_HC_PRTY_MASK \ 0x1080a0UL #define HC_REG_HC_PRTY_STS_CLR \ 0x108098UL #define HC_REG_INT_MASK \ 0x108108UL #define HC_REG_LEADING_EDGE_0 \ 0x108040UL #define HC_REG_MAIN_MEMORY \ 0x108800UL #define HC_REG_MAIN_MEMORY_SIZE \ 152 #define HC_REG_TRAILING_EDGE_0 \ 0x108044UL #define IGU_BLOCK_CONFIGURATION_REG_BACKWARD_COMP_EN \ (0x1<<1) #define IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE \ (0x1<<0) #define IGU_REG_ATTENTION_ACK_BITS \ 0x130108UL #define IGU_REG_ATTN_MSG_ADDR_H \ 0x13011cUL #define IGU_REG_ATTN_MSG_ADDR_L \ 0x130120UL #define IGU_REG_BLOCK_CONFIGURATION \ 0x130000UL #define IGU_REG_COMMAND_REG_32LSB_DATA \ 0x130124UL #define IGU_REG_COMMAND_REG_CTRL \ 0x13012cUL #define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP \ 0x130200UL #define IGU_REG_IGU_PRTY_MASK \ 0x1300a8UL #define IGU_REG_IGU_PRTY_STS_CLR \ 0x1300a0UL #define IGU_REG_LEADING_EDGE_LATCH \ 0x130134UL #define IGU_REG_MAPPING_MEMORY \ 0x131000UL #define IGU_REG_MAPPING_MEMORY_SIZE \ 136 #define IGU_REG_PBA_STATUS_LSB \ 0x130138UL #define IGU_REG_PBA_STATUS_MSB \ 0x13013cUL #define IGU_REG_PCI_PF_MSIX_EN \ 0x130144UL #define IGU_REG_PCI_PF_MSIX_FUNC_MASK \ 0x130148UL #define IGU_REG_PCI_PF_MSI_EN \ 0x130140UL #define IGU_REG_PENDING_BITS_STATUS \ 0x130300UL #define IGU_REG_PF_CONFIGURATION \ 0x130154UL #define IGU_REG_PROD_CONS_MEMORY \ 0x132000UL #define IGU_REG_RESET_MEMORIES \ 0x130158UL #define IGU_REG_SB_INT_BEFORE_MASK_LSB \ 0x13015cUL #define IGU_REG_SB_INT_BEFORE_MASK_MSB \ 0x130160UL #define IGU_REG_SB_MASK_LSB \ 0x130164UL #define IGU_REG_SB_MASK_MSB \ 0x130168UL #define IGU_REG_STATISTIC_NUM_MESSAGE_SENT \ 0x130800UL #define IGU_REG_TRAILING_EDGE_LATCH \ 0x130104UL #define IGU_REG_VF_CONFIGURATION \ 0x130170UL #define MCP_REG_MCPR_ACCESS_LOCK \ 0x8009c #define MCP_REG_MCPR_GP_INPUTS \ 0x800c0 #define MCP_REG_MCPR_GP_OENABLE \ 0x800c8 #define MCP_REG_MCPR_GP_OUTPUTS \ 0x800c4 #define MCP_REG_MCPR_IMC_COMMAND \ 0x85900 #define MCP_REG_MCPR_IMC_DATAREG0 \ 0x85920 #define MCP_REG_MCPR_IMC_SLAVE_CONTROL \ 0x85904 #define MCP_REG_MCPR_NVM_ACCESS_ENABLE \ 0x86424 #define MCP_REG_MCPR_NVM_ADDR \ 0x8640c #define MCP_REG_MCPR_NVM_CFG4 \ 0x8642c #define MCP_REG_MCPR_NVM_COMMAND \ 0x86400 #define MCP_REG_MCPR_NVM_READ \ 0x86410 #define MCP_REG_MCPR_NVM_SW_ARB \ 0x86420 #define MCP_REG_MCPR_NVM_WRITE \ 0x86408 #define MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK \ (0x1<<1) #define MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK \ (0x1<<0) #define MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 \ 0xa42cUL #define MISC_REG_AEU_AFTER_INVERT_2_FUNC_0 \ 0xa438UL #define MISC_REG_AEU_AFTER_INVERT_3_FUNC_0 \ 0xa444UL #define MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 \ 0xa450UL #define MISC_REG_AEU_AFTER_INVERT_4_MCP \ 0xa458UL #define MISC_REG_AEU_AFTER_INVERT_5_FUNC_0 \ 0xa700UL #define MISC_REG_AEU_CLR_LATCH_SIGNAL \ 0xa45cUL #define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0 \ 0xa06cUL #define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_1 \ 0xa07cUL #define MISC_REG_AEU_ENABLE1_FUNC_0_OUT_2 \ 0xa08cUL #define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 \ 0xa10cUL #define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_1 \ 0xa11cUL #define MISC_REG_AEU_ENABLE1_FUNC_1_OUT_2 \ 0xa12cUL #define MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0 \ 0xa078UL #define MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0 \ 0xa118UL #define MISC_REG_AEU_ENABLE4_NIG_0 \ 0xa0f8UL #define MISC_REG_AEU_ENABLE4_NIG_1 \ 0xa198UL #define MISC_REG_AEU_ENABLE4_PXP_0 \ 0xa108UL #define MISC_REG_AEU_ENABLE4_PXP_1 \ 0xa1a8UL #define MISC_REG_AEU_ENABLE5_FUNC_0_OUT_0 \ 0xa688UL #define MISC_REG_AEU_ENABLE5_FUNC_1_OUT_0 \ 0xa6b0UL #define MISC_REG_AEU_GENERAL_ATTN_0 \ 0xa000UL #define MISC_REG_AEU_GENERAL_ATTN_1 \ 0xa004UL #define MISC_REG_AEU_GENERAL_ATTN_10 \ 0xa028UL #define MISC_REG_AEU_GENERAL_ATTN_11 \ 0xa02cUL #define MISC_REG_AEU_GENERAL_ATTN_12 \ 0xa030UL #define MISC_REG_AEU_GENERAL_ATTN_2 \ 0xa008UL #define MISC_REG_AEU_GENERAL_ATTN_3 \ 0xa00cUL #define MISC_REG_AEU_GENERAL_ATTN_4 \ 0xa010UL #define MISC_REG_AEU_GENERAL_ATTN_5 \ 0xa014UL #define MISC_REG_AEU_GENERAL_ATTN_6 \ 0xa018UL #define MISC_REG_AEU_GENERAL_ATTN_7 \ 0xa01cUL #define MISC_REG_AEU_GENERAL_ATTN_8 \ 0xa020UL #define MISC_REG_AEU_GENERAL_ATTN_9 \ 0xa024UL #define MISC_REG_AEU_GENERAL_MASK \ 0xa61cUL #define MISC_REG_AEU_MASK_ATTN_FUNC_0 \ 0xa060UL #define MISC_REG_AEU_MASK_ATTN_FUNC_1 \ 0xa064UL #define MISC_REG_BOND_ID \ 0xa400UL #define MISC_REG_CHIP_NUM \ 0xa408UL #define MISC_REG_CHIP_REV \ 0xa40cUL #define MISC_REG_CHIP_TYPE \ 0xac60UL #define MISC_REG_CHIP_TYPE_57811_MASK \ (1<<1) #define MISC_REG_CPMU_LP_DR_ENABLE \ 0xa858UL #define MISC_REG_CPMU_LP_FW_ENABLE_P0 \ 0xa84cUL #define MISC_REG_CPMU_LP_IDLE_THR_P0 \ 0xa8a0UL #define MISC_REG_CPMU_LP_MASK_ENT_P0 \ 0xa880UL #define MISC_REG_CPMU_LP_MASK_EXT_P0 \ 0xa888UL #define MISC_REG_CPMU_LP_SM_ENT_CNT_P0 \ 0xa8b8UL #define MISC_REG_CPMU_LP_SM_ENT_CNT_P1 \ 0xa8bcUL #define MISC_REG_DRIVER_CONTROL_1 \ 0xa510UL #define MISC_REG_DRIVER_CONTROL_7 \ 0xa3c8UL #define MISC_REG_FOUR_PORT_PATH_SWAP \ 0xa75cUL #define MISC_REG_FOUR_PORT_PATH_SWAP_OVWR \ 0xa738UL #define MISC_REG_FOUR_PORT_PORT_SWAP \ 0xa754UL #define MISC_REG_FOUR_PORT_PORT_SWAP_OVWR \ 0xa734UL #define MISC_REG_GENERIC_CR_0 \ 0xa460UL #define MISC_REG_GENERIC_CR_1 \ 0xa464UL #define MISC_REG_GENERIC_POR_1 \ 0xa474UL #define MISC_REG_GEN_PURP_HWG \ 0xa9a0UL #define MISC_REG_GPIO \ 0xa490UL #define MISC_REG_GPIO_EVENT_EN \ 0xa2bcUL #define MISC_REG_GPIO_INT \ 0xa494UL #define MISC_REG_GRC_RSV_ATTN \ 0xa3c0UL #define MISC_REG_GRC_TIMEOUT_ATTN \ 0xa3c4UL #define MISC_REG_LCPLL_E40_PWRDWN \ 0xaa74UL #define MISC_REG_LCPLL_E40_RESETB_ANA \ 0xaa78UL #define MISC_REG_LCPLL_E40_RESETB_DIG \ 0xaa7cUL #define MISC_REG_MISC_INT_MASK \ 0xa388UL #define MISC_REG_MISC_PRTY_MASK \ 0xa398UL #define MISC_REG_MISC_PRTY_STS_CLR \ 0xa390UL #define MISC_REG_PORT4MODE_EN \ 0xa750UL #define MISC_REG_PORT4MODE_EN_OVWR \ 0xa720UL #define MISC_REG_RESET_REG_1 \ 0xa580UL #define MISC_REG_RESET_REG_2 \ 0xa590UL #define MISC_REG_SHARED_MEM_ADDR \ 0xa2b4UL #define MISC_REG_SPIO \ 0xa4fcUL #define MISC_REG_SPIO_EVENT_EN \ 0xa2b8UL #define MISC_REG_SPIO_INT \ 0xa500UL #define MISC_REG_TWO_PORT_PATH_SWAP \ 0xa758UL #define MISC_REG_TWO_PORT_PATH_SWAP_OVWR \ 0xa72cUL #define MISC_REG_UNPREPARED \ 0xa424UL #define MISC_REG_WC0_CTRL_PHY_ADDR \ 0xa9ccUL #define MISC_REG_WC0_RESET \ 0xac30UL #define MISC_REG_XMAC_CORE_PORT_MODE \ 0xa964UL #define MISC_REG_XMAC_PHY_PORT_MODE \ 0xa960UL #define MSTAT_REG_RX_STAT_GR64_LO \ 0x200UL #define MSTAT_REG_TX_STAT_GTXPOK_LO \ 0UL #define NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN \ (0x1<<0) #define NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN \ (0x1<<0) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT \ (0x1<<0) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS \ (0x1<<9) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G \ (0x1<<15) #define NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS \ (0xf<<18) #define NIG_REG_BMAC0_IN_EN \ 0x100acUL #define NIG_REG_BMAC0_OUT_EN \ 0x100e0UL #define NIG_REG_BMAC0_PAUSE_OUT_EN \ 0x10110UL #define NIG_REG_BMAC0_REGS_OUT_EN \ 0x100e8UL #define NIG_REG_BRB0_PAUSE_IN_EN \ 0x100c4UL #define NIG_REG_BRB1_PAUSE_IN_EN \ 0x100c8UL #define NIG_REG_DEBUG_PACKET_LB \ 0x10800UL #define NIG_REG_EGRESS_DRAIN0_MODE \ 0x10060UL #define NIG_REG_EGRESS_EMAC0_OUT_EN \ 0x10120UL #define NIG_REG_EGRESS_EMAC0_PORT \ 0x10058UL #define NIG_REG_EMAC0_IN_EN \ 0x100a4UL #define NIG_REG_EMAC0_PAUSE_OUT_EN \ 0x10118UL #define NIG_REG_EMAC0_STATUS_MISC_MI_INT \ 0x10494UL #define NIG_REG_INGRESS_BMAC0_MEM \ 0x10c00UL #define NIG_REG_INGRESS_BMAC1_MEM \ 0x11000UL #define NIG_REG_INGRESS_EOP_LB_EMPTY \ 0x104e0UL #define NIG_REG_INGRESS_EOP_LB_FIFO \ 0x104e4UL #define NIG_REG_LATCH_BC_0 \ 0x16210UL #define NIG_REG_LATCH_STATUS_0 \ 0x18000UL #define NIG_REG_LED_10G_P0 \ 0x10320UL #define NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 \ 0x10318UL #define NIG_REG_LED_CONTROL_BLINK_RATE_P0 \ 0x10310UL #define NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 \ 0x10308UL #define NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 \ 0x102f8UL #define NIG_REG_LED_CONTROL_TRAFFIC_P0 \ 0x10300UL #define NIG_REG_LED_MODE_P0 \ 0x102f0UL #define NIG_REG_LLFC_EGRESS_SRC_ENABLE_0 \ 0x16070UL #define NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 \ 0x16074UL #define NIG_REG_LLFC_ENABLE_0 \ 0x16208UL #define NIG_REG_LLFC_ENABLE_1 \ 0x1620cUL #define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0 \ 0x16058UL #define NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 \ 0x1605cUL #define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0 \ 0x16060UL #define NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 \ 0x16064UL #define NIG_REG_LLFC_OUT_EN_0 \ 0x160c8UL #define NIG_REG_LLFC_OUT_EN_1 \ 0x160ccUL #define NIG_REG_LLH0_BRB1_DRV_MASK \ 0x10244UL #define NIG_REG_LLH0_BRB1_DRV_MASK_MF \ 0x16048UL #define NIG_REG_LLH0_BRB1_NOT_MCP \ 0x1025cUL #define NIG_REG_LLH0_CLS_TYPE \ 0x16080UL #define NIG_REG_LLH0_FUNC_EN \ 0x160fcUL #define NIG_REG_LLH0_FUNC_MEM \ 0x16180UL #define NIG_REG_LLH0_FUNC_MEM_ENABLE \ 0x16140UL #define NIG_REG_LLH0_FUNC_VLAN_ID \ 0x16100UL #define NIG_REG_LLH0_XCM_MASK \ 0x10130UL #define NIG_REG_LLH1_BRB1_NOT_MCP \ 0x102dcUL #define NIG_REG_LLH1_CLS_TYPE \ 0x16084UL #define NIG_REG_LLH1_FUNC_MEM \ 0x161c0UL #define NIG_REG_LLH1_FUNC_MEM_ENABLE \ 0x16160UL #define NIG_REG_LLH1_FUNC_MEM_SIZE \ 16 #define NIG_REG_LLH1_MF_MODE \ 0x18614UL #define NIG_REG_LLH1_XCM_MASK \ 0x10134UL #define NIG_REG_LLH_E1HOV_MODE \ 0x160d8UL #define NIG_REG_LLH_MF_MODE \ 0x16024UL #define NIG_REG_MASK_INTERRUPT_PORT0 \ 0x10330UL #define NIG_REG_MASK_INTERRUPT_PORT1 \ 0x10334UL #define NIG_REG_NIG_EMAC0_EN \ 0x1003cUL #define NIG_REG_NIG_INGRESS_EMAC0_NO_CRC \ 0x10044UL #define NIG_REG_NIG_INT_STS_CLR_0 \ 0x103b4UL #define NIG_REG_NIG_PRTY_MASK \ 0x103dcUL #define NIG_REG_NIG_PRTY_MASK_0 \ 0x183c8UL #define NIG_REG_NIG_PRTY_MASK_1 \ 0x183d8UL #define NIG_REG_NIG_PRTY_STS_CLR \ 0x103d4UL #define NIG_REG_NIG_PRTY_STS_CLR_0 \ 0x183c0UL #define NIG_REG_NIG_PRTY_STS_CLR_1 \ 0x183d0UL #define NIG_REG_P0_HDRS_AFTER_BASIC \ 0x18038UL #define NIG_REG_P0_HWPFC_ENABLE \ 0x18078UL #define NIG_REG_P0_LLH_FUNC_MEM2 \ 0x18480UL #define NIG_REG_P0_MAC_IN_EN \ 0x185acUL #define NIG_REG_P0_MAC_OUT_EN \ 0x185b0UL #define NIG_REG_P0_MAC_PAUSE_OUT_EN \ 0x185b4UL #define NIG_REG_P0_PKT_PRIORITY_TO_COS \ 0x18054UL #define NIG_REG_P0_RX_COS0_PRIORITY_MASK \ 0x18058UL #define NIG_REG_P0_RX_COS1_PRIORITY_MASK \ 0x1805cUL #define NIG_REG_P0_RX_COS2_PRIORITY_MASK \ 0x186b0UL #define NIG_REG_P0_RX_COS3_PRIORITY_MASK \ 0x186b4UL #define NIG_REG_P0_RX_COS4_PRIORITY_MASK \ 0x186b8UL #define NIG_REG_P0_RX_COS5_PRIORITY_MASK \ 0x186bcUL #define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP \ 0x180f0UL #define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB \ 0x18688UL #define NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB \ 0x1868cUL #define NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT \ 0x180e8UL #define NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ \ 0x180ecUL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0 \ 0x1810cUL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1 \ 0x18110UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2 \ 0x18114UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3 \ 0x18118UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4 \ 0x1811cUL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5 \ 0x186a0UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6 \ 0x186a4UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7 \ 0x186a8UL #define NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8 \ 0x186acUL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0 \ 0x180f8UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1 \ 0x180fcUL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2 \ 0x18100UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3 \ 0x18104UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4 \ 0x18108UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5 \ 0x18690UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6 \ 0x18694UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7 \ 0x18698UL #define NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8 \ 0x1869cUL #define NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS \ 0x180f4UL #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT \ 0x180e4UL #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB \ 0x18680UL #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB \ 0x18684UL #define NIG_REG_P1_HDRS_AFTER_BASIC \ 0x1818cUL #define NIG_REG_P1_HWPFC_ENABLE \ 0x181d0UL #define NIG_REG_P1_LLH_FUNC_MEM2 \ 0x184c0UL #define NIG_REG_P1_MAC_IN_EN \ 0x185c0UL #define NIG_REG_P1_MAC_OUT_EN \ 0x185c4UL #define NIG_REG_P1_MAC_PAUSE_OUT_EN \ 0x185c8UL #define NIG_REG_P1_PKT_PRIORITY_TO_COS \ 0x181a8UL #define NIG_REG_P1_RX_COS0_PRIORITY_MASK \ 0x181acUL #define NIG_REG_P1_RX_COS1_PRIORITY_MASK \ 0x181b0UL #define NIG_REG_P1_RX_COS2_PRIORITY_MASK \ 0x186f8UL #define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB \ 0x186e8UL #define NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB \ 0x186ecUL #define NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT \ 0x18234UL #define NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ \ 0x18238UL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 \ 0x18258UL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 \ 0x1825cUL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 \ 0x18260UL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 \ 0x18264UL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 \ 0x18268UL #define NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 \ 0x186f4UL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 \ 0x18244UL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 \ 0x18248UL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 \ 0x1824cUL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 \ 0x18250UL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 \ 0x18254UL #define NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 \ 0x186f0UL #define NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS \ 0x18240UL #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB \ 0x186e0UL #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB \ 0x186e4UL #define NIG_REG_PAUSE_ENABLE_0 \ 0x160c0UL #define NIG_REG_PAUSE_ENABLE_1 \ 0x160c4UL #define NIG_REG_PORT_SWAP \ 0x10394UL #define NIG_REG_PPP_ENABLE_0 \ 0x160b0UL #define NIG_REG_PPP_ENABLE_1 \ 0x160b4UL #define NIG_REG_PRS_REQ_IN_EN \ 0x100b8UL #define NIG_REG_SERDES0_CTRL_MD_DEVAD \ 0x10370UL #define NIG_REG_SERDES0_CTRL_MD_ST \ 0x1036cUL #define NIG_REG_SERDES0_CTRL_PHY_ADDR \ 0x10374UL #define NIG_REG_SERDES0_STATUS_LINK_STATUS \ 0x10578UL #define NIG_REG_STAT0_BRB_DISCARD \ 0x105f0UL #define NIG_REG_STAT0_BRB_TRUNCATE \ 0x105f8UL #define NIG_REG_STAT0_EGRESS_MAC_PKT0 \ 0x10750UL #define NIG_REG_STAT0_EGRESS_MAC_PKT1 \ 0x10760UL #define NIG_REG_STAT1_BRB_DISCARD \ 0x10628UL #define NIG_REG_STAT1_EGRESS_MAC_PKT0 \ 0x107a0UL #define NIG_REG_STAT1_EGRESS_MAC_PKT1 \ 0x107b0UL #define NIG_REG_STAT2_BRB_OCTET \ 0x107e0UL #define NIG_REG_STATUS_INTERRUPT_PORT0 \ 0x10328UL #define NIG_REG_STRAP_OVERRIDE \ 0x10398UL #define NIG_REG_XCM0_OUT_EN \ 0x100f0UL #define NIG_REG_XCM1_OUT_EN \ 0x100f4UL #define NIG_REG_XGXS0_CTRL_MD_DEVAD \ 0x1033cUL #define NIG_REG_XGXS0_CTRL_MD_ST \ 0x10338UL #define NIG_REG_XGXS0_CTRL_PHY_ADDR \ 0x10340UL #define NIG_REG_XGXS0_STATUS_LINK10G \ 0x10680UL #define NIG_REG_XGXS0_STATUS_LINK_STATUS \ 0x10684UL #define NIG_REG_XGXS_LANE_SEL_P0 \ 0x102e8UL #define NIG_REG_XGXS_SERDES0_MODE_SEL \ 0x102e0UL #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT \ (0x1<<0) #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS \ (0x1<<9) #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G \ (0x1<<15) #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS \ (0xf<<18) #define NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE \ 18 #define PBF_REG_COS0_UPPER_BOUND \ 0x15c05cUL #define PBF_REG_COS0_UPPER_BOUND_P0 \ 0x15c2ccUL #define PBF_REG_COS0_UPPER_BOUND_P1 \ 0x15c2e4UL #define PBF_REG_COS0_WEIGHT \ 0x15c054UL #define PBF_REG_COS0_WEIGHT_P0 \ 0x15c2a8UL #define PBF_REG_COS0_WEIGHT_P1 \ 0x15c2c0UL #define PBF_REG_COS1_UPPER_BOUND \ 0x15c060UL #define PBF_REG_COS1_WEIGHT \ 0x15c058UL #define PBF_REG_COS1_WEIGHT_P0 \ 0x15c2acUL #define PBF_REG_COS1_WEIGHT_P1 \ 0x15c2c4UL #define PBF_REG_COS2_WEIGHT_P0 \ 0x15c2b0UL #define PBF_REG_COS2_WEIGHT_P1 \ 0x15c2c8UL #define PBF_REG_COS3_WEIGHT_P0 \ 0x15c2b4UL #define PBF_REG_COS4_WEIGHT_P0 \ 0x15c2b8UL #define PBF_REG_COS5_WEIGHT_P0 \ 0x15c2bcUL #define PBF_REG_CREDIT_LB_Q \ 0x140338UL #define PBF_REG_CREDIT_Q0 \ 0x14033cUL #define PBF_REG_CREDIT_Q1 \ 0x140340UL #define PBF_REG_DISABLE_NEW_TASK_PROC_P0 \ 0x14005cUL #define PBF_REG_DISABLE_PF \ 0x1402e8UL #define PBF_REG_DISABLE_VF \ 0x1402ecUL #define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0 \ 0x15c288UL #define PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1 \ 0x15c28cUL #define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 \ 0x15c278UL #define PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 \ 0x15c27cUL #define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 \ 0x15c280UL #define PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 \ 0x15c284UL #define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 \ 0x15c2a0UL #define PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 \ 0x15c2a4UL #define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 \ 0x15c270UL #define PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 \ 0x15c274UL #define PBF_REG_ETS_ENABLED \ 0x15c050UL #define PBF_REG_HDRS_AFTER_BASIC \ 0x15c0a8UL #define PBF_REG_HDRS_AFTER_TAG_0 \ 0x15c0b8UL #define PBF_REG_HIGH_PRIORITY_COS_NUM \ 0x15c04cUL #define PBF_REG_INIT_CRD_LB_Q \ 0x15c248UL #define PBF_REG_INIT_CRD_Q0 \ 0x15c230UL #define PBF_REG_INIT_CRD_Q1 \ 0x15c234UL #define PBF_REG_INIT_P0 \ 0x140004UL #define PBF_REG_INTERNAL_CRD_FREED_CNT_LB_Q \ 0x140354UL #define PBF_REG_INTERNAL_CRD_FREED_CNT_Q0 \ 0x140358UL #define PBF_REG_INTERNAL_CRD_FREED_CNT_Q1 \ 0x14035cUL #define PBF_REG_MUST_HAVE_HDRS \ 0x15c0c4UL #define PBF_REG_NUM_STRICT_ARB_SLOTS \ 0x15c064UL #define PBF_REG_P0_ARB_THRSH \ 0x1400e4UL #define PBF_REG_P0_CREDIT \ 0x140200UL #define PBF_REG_P0_INIT_CRD \ 0x1400d0UL #define PBF_REG_P0_INTERNAL_CRD_FREED_CNT \ 0x140308UL #define PBF_REG_P0_PAUSE_ENABLE \ 0x140014UL #define PBF_REG_P0_TQ_LINES_FREED_CNT \ 0x1402f0UL #define PBF_REG_P0_TQ_OCCUPANCY \ 0x1402fcUL #define PBF_REG_P1_CREDIT \ 0x140208UL #define PBF_REG_P1_INIT_CRD \ 0x1400d4UL #define PBF_REG_P1_INTERNAL_CRD_FREED_CNT \ 0x14030cUL #define PBF_REG_P1_TQ_LINES_FREED_CNT \ 0x1402f4UL #define PBF_REG_P1_TQ_OCCUPANCY \ 0x140300UL #define PBF_REG_P4_CREDIT \ 0x140210UL #define PBF_REG_P4_INIT_CRD \ 0x1400e0UL #define PBF_REG_P4_INTERNAL_CRD_FREED_CNT \ 0x140310UL #define PBF_REG_P4_TQ_LINES_FREED_CNT \ 0x1402f8UL #define PBF_REG_P4_TQ_OCCUPANCY \ 0x140304UL #define PBF_REG_PBF_INT_MASK \ 0x1401d4UL #define PBF_REG_PBF_PRTY_MASK \ 0x1401e4UL #define PBF_REG_PBF_PRTY_STS_CLR \ 0x1401dcUL #define PBF_REG_TAG_ETHERTYPE_0 \ 0x15c090UL #define PBF_REG_TAG_LEN_0 \ 0x15c09cUL #define PBF_REG_TQ_LINES_FREED_CNT_LB_Q \ 0x14038cUL #define PBF_REG_TQ_LINES_FREED_CNT_Q0 \ 0x140390UL #define PBF_REG_TQ_LINES_FREED_CNT_Q1 \ 0x140394UL #define PBF_REG_TQ_OCCUPANCY_LB_Q \ 0x1403a8UL #define PBF_REG_TQ_OCCUPANCY_Q0 \ 0x1403acUL #define PBF_REG_TQ_OCCUPANCY_Q1 \ 0x1403b0UL #define PB_REG_PB_INT_MASK \ 0x28UL #define PB_REG_PB_PRTY_MASK \ 0x38UL #define PB_REG_PB_PRTY_STS_CLR \ 0x30UL #define PGLUE_B_PGLUE_B_INT_STS_REG_ADDRESS_ERROR \ (0x1<<0) #define PGLUE_B_PGLUE_B_INT_STS_REG_CSSNOOP_FIFO_OVERFLOW \ (0x1<<8) #define PGLUE_B_PGLUE_B_INT_STS_REG_INCORRECT_RCV_BEHAVIOR \ (0x1<<1) #define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_ERROR_ATTN \ (0x1<<6) #define PGLUE_B_PGLUE_B_INT_STS_REG_TCPL_IN_TWO_RCBS_ATTN \ (0x1<<7) #define PGLUE_B_PGLUE_B_INT_STS_REG_VF_GRC_SPACE_VIOLATION_ATTN \ (0x1<<4) #define PGLUE_B_PGLUE_B_INT_STS_REG_VF_LENGTH_VIOLATION_ATTN \ (0x1<<3) #define PGLUE_B_PGLUE_B_INT_STS_REG_VF_MSIX_BAR_VIOLATION_ATTN \ (0x1<<5) #define PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN \ (0x1<<2) #define PGLUE_B_REG_FLR_REQUEST_PF_7_0_CLR \ 0x9418UL #define PGLUE_B_REG_WAS_ERROR_VF_31_0_CLR \ 0x9478UL #define PGLUE_B_REG_WAS_ERROR_VF_63_32_CLR \ 0x947cUL #define PGLUE_B_REG_WAS_ERROR_VF_95_64_CLR \ 0x9480UL #define PGLUE_B_REG_WAS_ERROR_VF_127_96_CLR \ 0x9474UL #define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER \ 0x942cUL #define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ \ 0x9430UL #define PGLUE_B_REG_INTERNAL_VFID_ENABLE \ 0x9438UL #define PGLUE_B_REG_PGLUE_B_INT_STS \ 0x9298UL #define PGLUE_B_REG_PGLUE_B_INT_STS_CLR \ 0x929cUL #define PGLUE_B_REG_PGLUE_B_PRTY_MASK \ 0x92b4UL #define PGLUE_B_REG_PGLUE_B_PRTY_STS_CLR \ 0x92acUL #define PGLUE_B_REG_SHADOW_BME_PF_7_0_CLR \ 0x9458UL #define PGLUE_B_REG_TAGS_63_32 \ 0x9244UL #define PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR \ 0x9470UL #define PRS_REG_A_PRSU_20 \ 0x40134UL #define PRS_REG_CFC_SEARCH_INITIAL_CREDIT \ 0x4011cUL #define PRS_REG_E1HOV_MODE \ 0x401c8UL #define PRS_REG_HDRS_AFTER_BASIC \ 0x40238UL #define PRS_REG_HDRS_AFTER_BASIC_PORT_0 \ 0x40270UL #define PRS_REG_HDRS_AFTER_BASIC_PORT_1 \ 0x40290UL #define PRS_REG_HDRS_AFTER_TAG_0 \ 0x40248UL #define PRS_REG_HDRS_AFTER_TAG_0_PORT_0 \ 0x40280UL #define PRS_REG_HDRS_AFTER_TAG_0_PORT_1 \ 0x402a0UL #define PRS_REG_MUST_HAVE_HDRS \ 0x40254UL #define PRS_REG_MUST_HAVE_HDRS_PORT_0 \ 0x4028cUL #define PRS_REG_MUST_HAVE_HDRS_PORT_1 \ 0x402acUL #define PRS_REG_NIC_MODE \ 0x40138UL #define PRS_REG_NUM_OF_PACKETS \ 0x40124UL #define PRS_REG_PRS_PRTY_MASK \ 0x401a4UL #define PRS_REG_PRS_PRTY_STS_CLR \ 0x4019cUL #define PRS_REG_TAG_ETHERTYPE_0 \ 0x401d4UL #define PRS_REG_TAG_LEN_0 \ 0x4022cUL #define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT \ (0x1<<19) #define PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF \ (0x1<<20) #define PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN \ (0x1<<22) #define PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED \ (0x1<<23) #define PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED \ (0x1<<24) #define PXP2_PXP2_INT_STS_0_REG_WR_PGLUE_EOP_ERROR \ (0x1<<7) #define PXP2_PXP2_INT_STS_CLR_0_REG_WR_PGLUE_EOP_ERROR \ (0x1<<7) #define PXP2_REG_PGL_ADDR_88_F0 \ 0x120534UL #define PXP2_REG_PGL_ADDR_88_F1 \ 0x120544UL #define PXP2_REG_PGL_ADDR_8C_F0 \ 0x120538UL #define PXP2_REG_PGL_ADDR_8C_F1 \ 0x120548UL #define PXP2_REG_PGL_ADDR_90_F0 \ 0x12053cUL #define PXP2_REG_PGL_ADDR_90_F1 \ 0x12054cUL #define PXP2_REG_PGL_ADDR_94_F0 \ 0x120540UL #define PXP2_REG_PGL_ADDR_94_F1 \ 0x120550UL #define PXP2_REG_PGL_EXP_ROM2 \ 0x120808UL #define PXP2_REG_PGL_PRETEND_FUNC_F0 \ 0x120674UL #define PXP2_REG_PGL_PRETEND_FUNC_F1 \ 0x120678UL #define PXP2_REG_PGL_TAGS_LIMIT \ 0x1205a8UL #define PXP2_REG_PSWRQ_BW_ADD1 \ 0x1201c0UL #define PXP2_REG_PSWRQ_BW_ADD10 \ 0x1201e4UL #define PXP2_REG_PSWRQ_BW_ADD11 \ 0x1201e8UL #define PXP2_REG_PSWRQ_BW_ADD2 \ 0x1201c4UL #define PXP2_REG_PSWRQ_BW_ADD28 \ 0x120228UL #define PXP2_REG_PSWRQ_BW_ADD3 \ 0x1201c8UL #define PXP2_REG_PSWRQ_BW_ADD6 \ 0x1201d4UL #define PXP2_REG_PSWRQ_BW_ADD7 \ 0x1201d8UL #define PXP2_REG_PSWRQ_BW_ADD8 \ 0x1201dcUL #define PXP2_REG_PSWRQ_BW_ADD9 \ 0x1201e0UL #define PXP2_REG_PSWRQ_BW_L1 \ 0x1202b0UL #define PXP2_REG_PSWRQ_BW_L10 \ 0x1202d4UL #define PXP2_REG_PSWRQ_BW_L11 \ 0x1202d8UL #define PXP2_REG_PSWRQ_BW_L2 \ 0x1202b4UL #define PXP2_REG_PSWRQ_BW_L28 \ 0x120318UL #define PXP2_REG_PSWRQ_BW_L3 \ 0x1202b8UL #define PXP2_REG_PSWRQ_BW_L6 \ 0x1202c4UL #define PXP2_REG_PSWRQ_BW_L7 \ 0x1202c8UL #define PXP2_REG_PSWRQ_BW_L8 \ 0x1202ccUL #define PXP2_REG_PSWRQ_BW_L9 \ 0x1202d0UL #define PXP2_REG_PSWRQ_BW_RD \ 0x120324UL #define PXP2_REG_PSWRQ_BW_UB1 \ 0x120238UL #define PXP2_REG_PSWRQ_BW_UB10 \ 0x12025cUL #define PXP2_REG_PSWRQ_BW_UB11 \ 0x120260UL #define PXP2_REG_PSWRQ_BW_UB2 \ 0x12023cUL #define PXP2_REG_PSWRQ_BW_UB28 \ 0x1202a0UL #define PXP2_REG_PSWRQ_BW_UB3 \ 0x120240UL #define PXP2_REG_PSWRQ_BW_UB6 \ 0x12024cUL #define PXP2_REG_PSWRQ_BW_UB7 \ 0x120250UL #define PXP2_REG_PSWRQ_BW_UB8 \ 0x120254UL #define PXP2_REG_PSWRQ_BW_UB9 \ 0x120258UL #define PXP2_REG_PSWRQ_BW_WR \ 0x120328UL #define PXP2_REG_PSWRQ_CDU0_L2P \ 0x120000UL #define PXP2_REG_PSWRQ_QM0_L2P \ 0x120038UL #define PXP2_REG_PSWRQ_SRC0_L2P \ 0x120054UL #define PXP2_REG_PSWRQ_TM0_L2P \ 0x12001cUL #define PXP2_REG_PXP2_INT_MASK_0 \ 0x120578UL #define PXP2_REG_PXP2_INT_MASK_1 \ 0x120614UL #define PXP2_REG_PXP2_INT_STS_0 \ 0x12056cUL #define PXP2_REG_PXP2_INT_STS_1 \ 0x120608UL #define PXP2_REG_PXP2_INT_STS_CLR_0 \ 0x120570UL #define PXP2_REG_PXP2_PRTY_MASK_0 \ 0x120588UL #define PXP2_REG_PXP2_PRTY_MASK_1 \ 0x120598UL #define PXP2_REG_PXP2_PRTY_STS_CLR_0 \ 0x120580UL #define PXP2_REG_PXP2_PRTY_STS_CLR_1 \ 0x120590UL #define PXP2_REG_RD_BLK_CNT \ 0x120418UL #define PXP2_REG_RD_CDURD_SWAP_MODE \ 0x120404UL #define PXP2_REG_RD_DISABLE_INPUTS \ 0x120374UL #define PXP2_REG_RD_INIT_DONE \ 0x120370UL #define PXP2_REG_RD_PBF_SWAP_MODE \ 0x1203f4UL #define PXP2_REG_RD_PORT_IS_IDLE_0 \ 0x12041cUL #define PXP2_REG_RD_PORT_IS_IDLE_1 \ 0x120420UL #define PXP2_REG_RD_QM_SWAP_MODE \ 0x1203f8UL #define PXP2_REG_RD_SRC_SWAP_MODE \ 0x120400UL #define PXP2_REG_RD_SR_CNT \ 0x120414UL #define PXP2_REG_RD_START_INIT \ 0x12036cUL #define PXP2_REG_RD_TM_SWAP_MODE \ 0x1203fcUL #define PXP2_REG_RQ_BW_RD_ADD0 \ 0x1201bcUL #define PXP2_REG_RQ_BW_RD_ADD12 \ 0x1201ecUL #define PXP2_REG_RQ_BW_RD_ADD13 \ 0x1201f0UL #define PXP2_REG_RQ_BW_RD_ADD14 \ 0x1201f4UL #define PXP2_REG_RQ_BW_RD_ADD15 \ 0x1201f8UL #define PXP2_REG_RQ_BW_RD_ADD16 \ 0x1201fcUL #define PXP2_REG_RQ_BW_RD_ADD17 \ 0x120200UL #define PXP2_REG_RQ_BW_RD_ADD18 \ 0x120204UL #define PXP2_REG_RQ_BW_RD_ADD19 \ 0x120208UL #define PXP2_REG_RQ_BW_RD_ADD20 \ 0x12020cUL #define PXP2_REG_RQ_BW_RD_ADD22 \ 0x120210UL #define PXP2_REG_RQ_BW_RD_ADD23 \ 0x120214UL #define PXP2_REG_RQ_BW_RD_ADD24 \ 0x120218UL #define PXP2_REG_RQ_BW_RD_ADD25 \ 0x12021cUL #define PXP2_REG_RQ_BW_RD_ADD26 \ 0x120220UL #define PXP2_REG_RQ_BW_RD_ADD27 \ 0x120224UL #define PXP2_REG_RQ_BW_RD_ADD4 \ 0x1201ccUL #define PXP2_REG_RQ_BW_RD_ADD5 \ 0x1201d0UL #define PXP2_REG_RQ_BW_RD_L0 \ 0x1202acUL #define PXP2_REG_RQ_BW_RD_L12 \ 0x1202dcUL #define PXP2_REG_RQ_BW_RD_L13 \ 0x1202e0UL #define PXP2_REG_RQ_BW_RD_L14 \ 0x1202e4UL #define PXP2_REG_RQ_BW_RD_L15 \ 0x1202e8UL #define PXP2_REG_RQ_BW_RD_L16 \ 0x1202ecUL #define PXP2_REG_RQ_BW_RD_L17 \ 0x1202f0UL #define PXP2_REG_RQ_BW_RD_L18 \ 0x1202f4UL #define PXP2_REG_RQ_BW_RD_L19 \ 0x1202f8UL #define PXP2_REG_RQ_BW_RD_L20 \ 0x1202fcUL #define PXP2_REG_RQ_BW_RD_L22 \ 0x120300UL #define PXP2_REG_RQ_BW_RD_L23 \ 0x120304UL #define PXP2_REG_RQ_BW_RD_L24 \ 0x120308UL #define PXP2_REG_RQ_BW_RD_L25 \ 0x12030cUL #define PXP2_REG_RQ_BW_RD_L26 \ 0x120310UL #define PXP2_REG_RQ_BW_RD_L27 \ 0x120314UL #define PXP2_REG_RQ_BW_RD_L4 \ 0x1202bcUL #define PXP2_REG_RQ_BW_RD_L5 \ 0x1202c0UL #define PXP2_REG_RQ_BW_RD_UBOUND0 \ 0x120234UL #define PXP2_REG_RQ_BW_RD_UBOUND12 \ 0x120264UL #define PXP2_REG_RQ_BW_RD_UBOUND13 \ 0x120268UL #define PXP2_REG_RQ_BW_RD_UBOUND14 \ 0x12026cUL #define PXP2_REG_RQ_BW_RD_UBOUND15 \ 0x120270UL #define PXP2_REG_RQ_BW_RD_UBOUND16 \ 0x120274UL #define PXP2_REG_RQ_BW_RD_UBOUND17 \ 0x120278UL #define PXP2_REG_RQ_BW_RD_UBOUND18 \ 0x12027cUL #define PXP2_REG_RQ_BW_RD_UBOUND19 \ 0x120280UL #define PXP2_REG_RQ_BW_RD_UBOUND20 \ 0x120284UL #define PXP2_REG_RQ_BW_RD_UBOUND22 \ 0x120288UL #define PXP2_REG_RQ_BW_RD_UBOUND23 \ 0x12028cUL #define PXP2_REG_RQ_BW_RD_UBOUND24 \ 0x120290UL #define PXP2_REG_RQ_BW_RD_UBOUND25 \ 0x120294UL #define PXP2_REG_RQ_BW_RD_UBOUND26 \ 0x120298UL #define PXP2_REG_RQ_BW_RD_UBOUND27 \ 0x12029cUL #define PXP2_REG_RQ_BW_RD_UBOUND4 \ 0x120244UL #define PXP2_REG_RQ_BW_RD_UBOUND5 \ 0x120248UL #define PXP2_REG_RQ_BW_WR_ADD29 \ 0x12022cUL #define PXP2_REG_RQ_BW_WR_ADD30 \ 0x120230UL #define PXP2_REG_RQ_BW_WR_L29 \ 0x12031cUL #define PXP2_REG_RQ_BW_WR_L30 \ 0x120320UL #define PXP2_REG_RQ_BW_WR_UBOUND29 \ 0x1202a4UL #define PXP2_REG_RQ_BW_WR_UBOUND30 \ 0x1202a8UL #define PXP2_REG_RQ_CDU_ENDIAN_M \ 0x1201a0UL #define PXP2_REG_RQ_CDU_FIRST_ILT \ 0x12061cUL #define PXP2_REG_RQ_CDU_LAST_ILT \ 0x120620UL #define PXP2_REG_RQ_CDU_P_SIZE \ 0x120018UL #define PXP2_REG_RQ_CFG_DONE \ 0x1201b4UL #define PXP2_REG_RQ_DBG_ENDIAN_M \ 0x1201a4UL #define PXP2_REG_RQ_DISABLE_INPUTS \ 0x120330UL #define PXP2_REG_RQ_DRAM_ALIGN \ 0x1205b0UL #define PXP2_REG_RQ_DRAM_ALIGN_RD \ 0x12092cUL #define PXP2_REG_RQ_DRAM_ALIGN_SEL \ 0x120930UL #define PXP2_REG_RQ_HC_ENDIAN_M \ 0x1201a8UL #define PXP2_REG_RQ_ONCHIP_AT \ 0x122000UL #define PXP2_REG_RQ_ONCHIP_AT_B0 \ 0x128000UL #define PXP2_REG_RQ_PDR_LIMIT \ 0x12033cUL #define PXP2_REG_RQ_QM_ENDIAN_M \ 0x120194UL #define PXP2_REG_RQ_QM_FIRST_ILT \ 0x120634UL #define PXP2_REG_RQ_QM_LAST_ILT \ 0x120638UL #define PXP2_REG_RQ_QM_P_SIZE \ 0x120050UL #define PXP2_REG_RQ_RBC_DONE \ 0x1201b0UL #define PXP2_REG_RQ_RD_MBS0 \ 0x120160UL #define PXP2_REG_RQ_RD_MBS1 \ 0x120168UL #define PXP2_REG_RQ_SRC_ENDIAN_M \ 0x12019cUL #define PXP2_REG_RQ_SRC_FIRST_ILT \ 0x12063cUL #define PXP2_REG_RQ_SRC_LAST_ILT \ 0x120640UL #define PXP2_REG_RQ_SRC_P_SIZE \ 0x12006cUL #define PXP2_REG_RQ_TM_ENDIAN_M \ 0x120198UL #define PXP2_REG_RQ_TM_FIRST_ILT \ 0x120644UL #define PXP2_REG_RQ_TM_LAST_ILT \ 0x120648UL #define PXP2_REG_RQ_TM_P_SIZE \ 0x120034UL #define PXP2_REG_RQ_WR_MBS0 \ 0x12015cUL #define PXP2_REG_RQ_WR_MBS1 \ 0x120164UL #define PXP2_REG_WR_CDU_MPS \ 0x1205f0UL #define PXP2_REG_WR_CSDM_MPS \ 0x1205d0UL #define PXP2_REG_WR_DBG_MPS \ 0x1205e8UL #define PXP2_REG_WR_DMAE_MPS \ 0x1205ecUL #define PXP2_REG_WR_HC_MPS \ 0x1205c8UL #define PXP2_REG_WR_QM_MPS \ 0x1205dcUL #define PXP2_REG_WR_SRC_MPS \ 0x1205e4UL #define PXP2_REG_WR_TM_MPS \ 0x1205e0UL #define PXP2_REG_WR_TSDM_MPS \ 0x1205d4UL #define PXP2_REG_WR_USDMDP_TH \ 0x120348UL #define PXP2_REG_WR_USDM_MPS \ 0x1205ccUL #define PXP2_REG_WR_XSDM_MPS \ 0x1205d8UL #define PXP_REG_HST_DISCARD_DOORBELLS \ 0x1030a4UL #define PXP_REG_HST_DISCARD_INTERNAL_WRITES \ 0x1030a8UL #define PXP_REG_HST_ZONE_PERMISSION_TABLE \ 0x103400UL #define PXP_REG_PXP_INT_MASK_0 \ 0x103074UL #define PXP_REG_PXP_INT_MASK_1 \ 0x103084UL #define PXP_REG_PXP_INT_STS_CLR_0 \ 0x10306cUL #define PXP_REG_PXP_INT_STS_CLR_1 \ 0x10307cUL #define PXP_REG_PXP_PRTY_MASK \ 0x103094UL #define PXP_REG_PXP_PRTY_STS_CLR \ 0x10308cUL #define QM_REG_BASEADDR \ 0x168900UL #define QM_REG_BASEADDR_EXT_A \ 0x16e100UL #define QM_REG_BYTECRDCMDQ_0 \ 0x16e6e8UL #define QM_REG_CONNNUM_0 \ 0x168020UL #define QM_REG_PF_EN \ 0x16e70cUL #define QM_REG_PF_USG_CNT_0 \ 0x16e040UL #define QM_REG_PTRTBL \ 0x168a00UL #define QM_REG_PTRTBL_EXT_A \ 0x16e200UL #define QM_REG_QM_INT_MASK \ 0x168444UL #define QM_REG_QM_PRTY_MASK \ 0x168454UL #define QM_REG_QM_PRTY_STS_CLR \ 0x16844cUL #define QM_REG_QVOQIDX_0 \ 0x1680f4UL #define QM_REG_SOFT_RESET \ 0x168428UL #define QM_REG_VOQQMASK_0_LSB \ 0x168240UL #define SEM_FAST_REG_PARITY_RST \ 0x18840UL #define SRC_REG_COUNTFREE0 \ 0x40500UL #define SRC_REG_FIRSTFREE0 \ 0x40510UL #define SRC_REG_KEYSEARCH_0 \ 0x40458UL #define SRC_REG_KEYSEARCH_1 \ 0x4045cUL #define SRC_REG_KEYSEARCH_2 \ 0x40460UL #define SRC_REG_KEYSEARCH_3 \ 0x40464UL #define SRC_REG_KEYSEARCH_4 \ 0x40468UL #define SRC_REG_KEYSEARCH_5 \ 0x4046cUL #define SRC_REG_KEYSEARCH_6 \ 0x40470UL #define SRC_REG_KEYSEARCH_7 \ 0x40474UL #define SRC_REG_KEYSEARCH_8 \ 0x40478UL #define SRC_REG_KEYSEARCH_9 \ 0x4047cUL #define SRC_REG_LASTFREE0 \ 0x40530UL #define SRC_REG_NUMBER_HASH_BITS0 \ 0x40400UL #define SRC_REG_SOFT_RST \ 0x4049cUL #define SRC_REG_SRC_PRTY_MASK \ 0x404c8UL #define SRC_REG_SRC_PRTY_STS_CLR \ 0x404c0UL #define TCM_REG_PRS_IFEN \ 0x50020UL #define TCM_REG_TCM_INT_MASK \ 0x501dcUL #define TCM_REG_TCM_PRTY_MASK \ 0x501ecUL #define TCM_REG_TCM_PRTY_STS_CLR \ 0x501e4UL #define TM_REG_EN_LINEAR0_TIMER \ 0x164014UL #define TM_REG_LIN0_MAX_ACTIVE_CID \ 0x164048UL #define TM_REG_LIN0_NUM_SCANS \ 0x1640a0UL #define TM_REG_LIN0_SCAN_ON \ 0x1640d0UL #define TM_REG_LIN0_SCAN_TIME \ 0x16403cUL #define TM_REG_LIN0_VNIC_UC \ 0x164128UL #define TM_REG_TM_INT_MASK \ 0x1640fcUL #define TM_REG_TM_PRTY_MASK \ 0x16410cUL #define TM_REG_TM_PRTY_STS_CLR \ 0x164104UL #define TSDM_REG_ENABLE_IN1 \ 0x42238UL #define TSDM_REG_TSDM_INT_MASK_0 \ 0x4229cUL #define TSDM_REG_TSDM_INT_MASK_1 \ 0x422acUL #define TSDM_REG_TSDM_PRTY_MASK \ 0x422bcUL #define TSDM_REG_TSDM_PRTY_STS_CLR \ 0x422b4UL #define TSEM_REG_FAST_MEMORY \ 0x1a0000UL #define TSEM_REG_INT_TABLE \ 0x180400UL #define TSEM_REG_PASSIVE_BUFFER \ 0x181000UL #define TSEM_REG_PRAM \ 0x1c0000UL #define TSEM_REG_TSEM_INT_MASK_0 \ 0x180100UL #define TSEM_REG_TSEM_INT_MASK_1 \ 0x180110UL #define TSEM_REG_TSEM_PRTY_MASK_0 \ 0x180120UL #define TSEM_REG_TSEM_PRTY_MASK_1 \ 0x180130UL #define TSEM_REG_TSEM_PRTY_STS_CLR_0 \ 0x180118UL #define TSEM_REG_TSEM_PRTY_STS_CLR_1 \ 0x180128UL #define TSEM_REG_VFPF_ERR_NUM \ 0x180380UL #define UCM_REG_UCM_INT_MASK \ 0xe01d4UL #define UCM_REG_UCM_PRTY_MASK \ 0xe01e4UL #define UCM_REG_UCM_PRTY_STS_CLR \ 0xe01dcUL #define UMAC_COMMAND_CONFIG_REG_HD_ENA \ (0x1<<10) #define UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE \ (0x1<<28) #define UMAC_COMMAND_CONFIG_REG_LOOP_ENA \ (0x1<<15) #define UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK \ (0x1<<24) #define UMAC_COMMAND_CONFIG_REG_PAD_EN \ (0x1<<5) #define UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE \ (0x1<<8) #define UMAC_COMMAND_CONFIG_REG_PROMIS_EN \ (0x1<<4) #define UMAC_COMMAND_CONFIG_REG_RX_ENA \ (0x1<<1) #define UMAC_COMMAND_CONFIG_REG_SW_RESET \ (0x1<<13) #define UMAC_COMMAND_CONFIG_REG_TX_ENA \ (0x1<<0) #define UMAC_REG_COMMAND_CONFIG \ 0x8UL #define UMAC_REG_EEE_WAKE_TIMER \ 0x6cUL #define UMAC_REG_MAC_ADDR0 \ 0xcUL #define UMAC_REG_MAC_ADDR1 \ 0x10UL #define UMAC_REG_MAXFR \ 0x14UL #define UMAC_REG_UMAC_EEE_CTRL \ 0x64UL #define UMAC_UMAC_EEE_CTRL_REG_EEE_EN \ (0x1<<3) #define USDM_REG_USDM_INT_MASK_0 \ 0xc42a0UL #define USDM_REG_USDM_INT_MASK_1 \ 0xc42b0UL #define USDM_REG_USDM_PRTY_MASK \ 0xc42c0UL #define USDM_REG_USDM_PRTY_STS_CLR \ 0xc42b8UL #define USEM_REG_FAST_MEMORY \ 0x320000UL #define USEM_REG_INT_TABLE \ 0x300400UL #define USEM_REG_PASSIVE_BUFFER \ 0x302000UL #define USEM_REG_PRAM \ 0x340000UL #define USEM_REG_USEM_INT_MASK_0 \ 0x300110UL #define USEM_REG_USEM_INT_MASK_1 \ 0x300120UL #define USEM_REG_USEM_PRTY_MASK_0 \ 0x300130UL #define USEM_REG_USEM_PRTY_MASK_1 \ 0x300140UL #define USEM_REG_USEM_PRTY_STS_CLR_0 \ 0x300128UL #define USEM_REG_USEM_PRTY_STS_CLR_1 \ 0x300138UL #define USEM_REG_VFPF_ERR_NUM \ 0x300380UL #define VFC_MEMORIES_RST_REG_CAM_RST \ (0x1<<0) #define VFC_MEMORIES_RST_REG_RAM_RST \ (0x1<<1) #define VFC_REG_MEMORIES_RST \ 0x1943cUL #define XCM_REG_XCM_INT_MASK \ 0x202b4UL #define XCM_REG_XCM_PRTY_MASK \ 0x202c4UL #define XCM_REG_XCM_PRTY_STS_CLR \ 0x202bcUL #define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS \ (0x1<<0) #define XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS \ (0x1<<1) #define XMAC_CTRL_REG_LINE_LOCAL_LPBK \ (0x1<<2) #define XMAC_CTRL_REG_RX_EN \ (0x1<<1) #define XMAC_CTRL_REG_SOFT_RESET \ (0x1<<6) #define XMAC_CTRL_REG_TX_EN \ (0x1<<0) #define XMAC_CTRL_REG_XLGMII_ALIGN_ENB \ (0x1<<7) #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN \ (0x1<<18) #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN \ (0x1<<17) #define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON \ (0x1<<1) #define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN \ (0x1<<0) #define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN \ (0x1<<3) #define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN \ (0x1<<4) #define XMAC_PFC_CTRL_HI_REG_TX_PFC_EN \ (0x1<<5) #define XMAC_REG_CLEAR_RX_LSS_STATUS \ 0x60UL #define XMAC_REG_CTRL \ 0UL #define XMAC_REG_CTRL_SA_HI \ 0x2cUL #define XMAC_REG_CTRL_SA_LO \ 0x28UL #define XMAC_REG_EEE_CTRL \ 0xd8UL #define XMAC_REG_EEE_TIMERS_HI \ 0xe4UL #define XMAC_REG_PAUSE_CTRL \ 0x68UL #define XMAC_REG_PFC_CTRL \ 0x70UL #define XMAC_REG_PFC_CTRL_HI \ 0x74UL #define XMAC_REG_RX_LSS_CTRL \ 0x50UL #define XMAC_REG_RX_LSS_STATUS \ 0x58UL #define XMAC_REG_RX_MAX_SIZE \ 0x40UL #define XMAC_REG_TX_CTRL \ 0x20UL #define XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE \ (0x1<<0) #define XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE \ (0x1<<1) #define XSDM_REG_OPERATION_GEN \ 0x1664c4UL #define XSDM_REG_XSDM_INT_MASK_0 \ 0x16629cUL #define XSDM_REG_XSDM_INT_MASK_1 \ 0x1662acUL #define XSDM_REG_XSDM_PRTY_MASK \ 0x1662bcUL #define XSDM_REG_XSDM_PRTY_STS_CLR \ 0x1662b4UL #define XSEM_REG_FAST_MEMORY \ 0x2a0000UL #define XSEM_REG_INT_TABLE \ 0x280400UL #define XSEM_REG_PASSIVE_BUFFER \ 0x282000UL #define XSEM_REG_PRAM \ 0x2c0000UL #define XSEM_REG_VFPF_ERR_NUM \ 0x280380UL #define XSEM_REG_XSEM_INT_MASK_0 \ 0x280110UL #define XSEM_REG_XSEM_INT_MASK_1 \ 0x280120UL #define XSEM_REG_XSEM_PRTY_MASK_0 \ 0x280130UL #define XSEM_REG_XSEM_PRTY_MASK_1 \ 0x280140UL #define XSEM_REG_XSEM_PRTY_STS_CLR_0 \ 0x280128UL #define XSEM_REG_XSEM_PRTY_STS_CLR_1 \ 0x280138UL #define MCPR_ACCESS_LOCK_LOCK (1L<<31) #define MCPR_IMC_COMMAND_ENABLE (1L<<31) #define MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT 16 #define MCPR_IMC_COMMAND_OPERATION_BITSHIFT 28 #define MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT 8 #define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0) #define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1) #define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) #define MCPR_NVM_CFG4_FLASH_SIZE (0x7L<<0) #define MCPR_NVM_COMMAND_DOIT (1L<<4) #define MCPR_NVM_COMMAND_DONE (1L<<3) #define MCPR_NVM_COMMAND_FIRST (1L<<7) #define MCPR_NVM_COMMAND_LAST (1L<<8) #define MCPR_NVM_COMMAND_WR (1L<<5) #define MCPR_NVM_SW_ARB_ARB_ARB1 (1L<<9) #define MCPR_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5) #define MCPR_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1) #define BIGMAC_REGISTER_BMAC_CONTROL (0x00<<3) #define BIGMAC_REGISTER_BMAC_XGXS_CONTROL (0x01<<3) #define BIGMAC_REGISTER_CNT_MAX_SIZE (0x05<<3) #define BIGMAC_REGISTER_RX_CONTROL (0x21<<3) #define BIGMAC_REGISTER_RX_LLFC_MSG_FLDS (0x46<<3) #define BIGMAC_REGISTER_RX_LSS_STATUS (0x43<<3) #define BIGMAC_REGISTER_RX_MAX_SIZE (0x23<<3) #define BIGMAC_REGISTER_RX_STAT_GR64 (0x26<<3) #define BIGMAC_REGISTER_RX_STAT_GRIPJ (0x42<<3) #define BIGMAC_REGISTER_TX_CONTROL (0x07<<3) #define BIGMAC_REGISTER_TX_MAX_SIZE (0x09<<3) #define BIGMAC_REGISTER_TX_PAUSE_THRESHOLD (0x0A<<3) #define BIGMAC_REGISTER_TX_SOURCE_ADDR (0x08<<3) #define BIGMAC_REGISTER_TX_STAT_GTBYT (0x20<<3) #define BIGMAC_REGISTER_TX_STAT_GTPKT (0x0C<<3) #define BIGMAC2_REGISTER_BMAC_CONTROL (0x00<<3) #define BIGMAC2_REGISTER_BMAC_XGXS_CONTROL (0x01<<3) #define BIGMAC2_REGISTER_CNT_MAX_SIZE (0x05<<3) #define BIGMAC2_REGISTER_PFC_CONTROL (0x06<<3) #define BIGMAC2_REGISTER_RX_CONTROL (0x3A<<3) #define BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS (0x62<<3) #define BIGMAC2_REGISTER_RX_LSS_STAT (0x3E<<3) #define BIGMAC2_REGISTER_RX_MAX_SIZE (0x3C<<3) #define BIGMAC2_REGISTER_RX_STAT_GR64 (0x40<<3) #define BIGMAC2_REGISTER_RX_STAT_GRIPJ (0x5f<<3) #define BIGMAC2_REGISTER_TX_CONTROL (0x1C<<3) #define BIGMAC2_REGISTER_TX_MAX_SIZE (0x1E<<3) #define BIGMAC2_REGISTER_TX_PAUSE_CONTROL (0x20<<3) #define BIGMAC2_REGISTER_TX_SOURCE_ADDR (0x1D<<3) #define BIGMAC2_REGISTER_TX_STAT_GTBYT (0x39<<3) #define BIGMAC2_REGISTER_TX_STAT_GTPOK (0x22<<3) #define EMAC_LED_1000MB_OVERRIDE (1L<<1) #define EMAC_LED_100MB_OVERRIDE (1L<<2) #define EMAC_LED_10MB_OVERRIDE (1L<<3) #define EMAC_LED_OVERRIDE (1L<<0) #define EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26) #define EMAC_MDIO_COMM_COMMAND_READ_22 (2L<<26) #define EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26) #define EMAC_MDIO_COMM_COMMAND_WRITE_22 (1L<<26) #define EMAC_MDIO_COMM_COMMAND_WRITE_45 (1L<<26) #define EMAC_MDIO_COMM_DATA (0xffffL<<0) #define EMAC_MDIO_COMM_START_BUSY (1L<<29) #define EMAC_MDIO_MODE_AUTO_POLL (1L<<4) #define EMAC_MDIO_MODE_CLAUSE_45 (1L<<31) #define EMAC_MDIO_MODE_CLOCK_CNT (0x3ffL<<16) #define EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT 16 #define EMAC_MDIO_STATUS_10MB (1L<<1) #define EMAC_MODE_25G_MODE (1L<<5) #define EMAC_MODE_HALF_DUPLEX (1L<<1) #define EMAC_MODE_PORT_GMII (2L<<2) #define EMAC_MODE_PORT_MII (1L<<2) #define EMAC_MODE_PORT_MII_10M (3L<<2) #define EMAC_MODE_RESET (1L<<0) #define EMAC_REG_EMAC_LED 0xc #define EMAC_REG_EMAC_MAC_MATCH 0x10 #define EMAC_REG_EMAC_MDIO_COMM 0xac #define EMAC_REG_EMAC_MDIO_MODE 0xb4 #define EMAC_REG_EMAC_MDIO_STATUS 0xb0 #define EMAC_REG_EMAC_MODE 0x0 #define EMAC_REG_EMAC_RX_MODE 0xc8 #define EMAC_REG_EMAC_RX_MTU_SIZE 0x9c #define EMAC_REG_EMAC_RX_STAT_AC 0x180 #define EMAC_REG_EMAC_RX_STAT_AC_28 0x1f4 #define EMAC_REG_EMAC_RX_STAT_AC_COUNT 23 #define EMAC_REG_EMAC_TX_MODE 0xbc #define EMAC_REG_EMAC_TX_STAT_AC 0x280 #define EMAC_REG_EMAC_TX_STAT_AC_COUNT 22 #define EMAC_REG_RX_PFC_MODE 0x320 #define EMAC_REG_RX_PFC_MODE_PRIORITIES (1L<<2) #define EMAC_REG_RX_PFC_MODE_RX_EN (1L<<1) #define EMAC_REG_RX_PFC_MODE_TX_EN (1L<<0) #define EMAC_REG_RX_PFC_PARAM 0x324 #define EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT 0 #define EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT 16 #define EMAC_REG_RX_PFC_STATS_XOFF_RCVD 0x328 #define EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT (0xffff<<0) #define EMAC_REG_RX_PFC_STATS_XOFF_SENT 0x330 #define EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT (0xffff<<0) #define EMAC_REG_RX_PFC_STATS_XON_RCVD 0x32c #define EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT (0xffff<<0) #define EMAC_REG_RX_PFC_STATS_XON_SENT 0x334 #define EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT (0xffff<<0) #define EMAC_RX_MODE_FLOW_EN (1L<<2) #define EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3) #define EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10) #define EMAC_RX_MODE_PROMISCUOUS (1L<<8) #define EMAC_RX_MODE_RESET (1L<<0) #define EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31) #define EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) #define EMAC_TX_MODE_FLOW_EN (1L<<4) #define EMAC_TX_MODE_RESET (1L<<0) #define MISC_REGISTERS_GPIO_0 0 #define MISC_REGISTERS_GPIO_1 1 #define MISC_REGISTERS_GPIO_2 2 #define MISC_REGISTERS_GPIO_3 3 #define MISC_REGISTERS_GPIO_CLR_POS 16 #define MISC_REGISTERS_GPIO_FLOAT (0xffL<<24) #define MISC_REGISTERS_GPIO_FLOAT_POS 24 #define MISC_REGISTERS_GPIO_HIGH 1 #define MISC_REGISTERS_GPIO_INPUT_HI_Z 2 #define MISC_REGISTERS_GPIO_INT_CLR_POS 24 #define MISC_REGISTERS_GPIO_INT_OUTPUT_CLR 0 #define MISC_REGISTERS_GPIO_INT_OUTPUT_SET 1 #define MISC_REGISTERS_GPIO_INT_SET_POS 16 #define MISC_REGISTERS_GPIO_LOW 0 #define MISC_REGISTERS_GPIO_OUTPUT_HIGH 1 #define MISC_REGISTERS_GPIO_OUTPUT_LOW 0 #define MISC_REGISTERS_GPIO_PORT_SHIFT 4 #define MISC_REGISTERS_GPIO_SET_POS 8 #define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588 #define MISC_REGISTERS_RESET_REG_1_RST_BRB1 (0x1<<0) #define MISC_REGISTERS_RESET_REG_1_RST_DORQ \ (0x1<<19) #define MISC_REGISTERS_RESET_REG_1_RST_HC \ (0x1<<29) #define MISC_REGISTERS_RESET_REG_1_RST_PXP \ (0x1<<26) #define MISC_REGISTERS_RESET_REG_1_RST_PXPV \ (0x1<<27) #define MISC_REGISTERS_RESET_REG_1_RST_QM \ (0x1<<17) #define MISC_REGISTERS_RESET_REG_1_SET 0x584 #define MISC_REGISTERS_RESET_REG_2_CLEAR 0x598 #define MISC_REGISTERS_RESET_REG_2_MSTAT0 \ (0x1<<24) #define MISC_REGISTERS_RESET_REG_2_MSTAT1 \ (0x1<<25) #define MISC_REGISTERS_RESET_REG_2_PGLC \ (0x1<<19) #define MISC_REGISTERS_RESET_REG_2_RST_ATC \ (0x1<<17) #define MISC_REGISTERS_RESET_REG_2_RST_BMAC0 (0x1<<0) #define MISC_REGISTERS_RESET_REG_2_RST_BMAC1 (0x1<<1) #define MISC_REGISTERS_RESET_REG_2_RST_EMAC0 (0x1<<2) #define MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE \ (0x1<<14) #define MISC_REGISTERS_RESET_REG_2_RST_EMAC1 (0x1<<3) #define MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE \ (0x1<<15) #define MISC_REGISTERS_RESET_REG_2_RST_GRC (0x1<<4) #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B (0x1<<6) #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE (0x1<<8) #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU (0x1<<7) #define MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE (0x1<<5) #define MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE \ (0x1<<11) #define MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO \ (0x1<<13) #define MISC_REGISTERS_RESET_REG_2_RST_PXP_RQ_RD_WR \ (0x1<<16) #define MISC_REGISTERS_RESET_REG_2_RST_RBCN (0x1<<9) #define MISC_REGISTERS_RESET_REG_2_SET 0x594 #define MISC_REGISTERS_RESET_REG_2_UMAC0 \ (0x1<<20) #define MISC_REGISTERS_RESET_REG_2_UMAC1 \ (0x1<<21) #define MISC_REGISTERS_RESET_REG_2_XMAC \ (0x1<<22) #define MISC_REGISTERS_RESET_REG_2_XMAC_SOFT \ (0x1<<23) #define MISC_REGISTERS_RESET_REG_3_CLEAR 0x5a8 #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ (0x1<<1) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN (0x1<<2) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD (0x1<<3) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW (0x1<<0) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ (0x1<<5) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN (0x1<<6) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD (0x1<<7) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW (0x1<<4) #define MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB (0x1<<8) #define MISC_REGISTERS_RESET_REG_3_SET 0x5a4 #define MISC_SPIO_CLR_POS 16 #define MISC_SPIO_FLOAT (0xffL<<24) #define MISC_SPIO_FLOAT_POS 24 #define MISC_SPIO_INPUT_HI_Z 2 #define MISC_SPIO_INT_OLD_SET_POS 16 #define MISC_SPIO_OUTPUT_HIGH 1 #define MISC_SPIO_OUTPUT_LOW 0 #define MISC_SPIO_SET_POS 8 #define MISC_SPIO_SPIO4 0x10 #define MISC_SPIO_SPIO5 0x20 #define HW_LOCK_MAX_RESOURCE_VALUE 31 #define HW_LOCK_RESOURCE_DRV_FLAGS 10 #define HW_LOCK_RESOURCE_GPIO 1 #define HW_LOCK_RESOURCE_NVRAM 12 #define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3 #define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8 #define HW_LOCK_RESOURCE_RECOVERY_LEADER_1 9 #define HW_LOCK_RESOURCE_RECOVERY_REG 11 #define HW_LOCK_RESOURCE_RESET 5 #define HW_LOCK_RESOURCE_SPIO 2 #define AEU_INPUTS_ATTN_BITS_ATC_HW_INTERRUPT (0x1<<4) #define AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR (0x1<<5) #define AEU_INPUTS_ATTN_BITS_BRB_HW_INTERRUPT (0x1<<19) #define AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR (0x1<<18) #define AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT (0x1<<31) #define AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR (0x1<<30) #define AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT (0x1<<9) #define AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR (0x1<<8) #define AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT (0x1<<7) #define AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR (0x1<<6) #define AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT (0x1<<29) #define AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR (0x1<<28) #define AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT (0x1<<1) #define AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR (0x1<<0) #define AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR (0x1<<18) #define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT (0x1<<11) #define AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR (0x1<<10) #define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT (0x1<<13) #define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR (0x1<<12) #define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 (0x1<<2) #define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR (0x1<<12) #define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY (0x1<<28) #define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY (0x1UL<<31) #define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY (0x1<<29) #define AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY (0x1<<30) #define AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT (0x1<<15) #define AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR (0x1<<14) #define AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR (0x1<<14) #define AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR (0x1<<20) #define AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT (0x1UL<<31) #define AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR (0x1<<30) #define AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR (0x1<<0) #define AEU_INPUTS_ATTN_BITS_PGLUE_HW_INTERRUPT (0x1<<2) #define AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR (0x1<<3) #define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT (0x1<<5) #define AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR (0x1<<4) #define AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT (0x1<<3) #define AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR (0x1<<2) #define AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT (0x1<<3) #define AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR (0x1<<2) #define AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR (0x1<<22) #define AEU_INPUTS_ATTN_BITS_SPIO5 (0x1<<15) #define AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT (0x1<<27) #define AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR (0x1<<26) #define AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT (0x1<<5) #define AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR (0x1<<4) #define AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT (0x1<<25) #define AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR (0x1<<24) #define AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT (0x1<<29) #define AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR (0x1<<28) #define AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT (0x1<<23) #define AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR (0x1<<22) #define AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT (0x1<<27) #define AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR (0x1<<26) #define AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT (0x1<<21) #define AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR (0x1<<20) #define AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT (0x1<<25) #define AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR (0x1<<24) #define AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR (0x1<<16) #define AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT (0x1<<9) #define AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR (0x1<<8) #define AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT (0x1<<7) #define AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR (0x1<<6) #define AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT (0x1<<11) #define AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR (0x1<<10) #define HW_PRTY_ASSERT_SET_0 \ (AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR) #define HW_PRTY_ASSERT_SET_1 \ (AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR) #define HW_PRTY_ASSERT_SET_2 \ (AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR) #define HW_PRTY_ASSERT_SET_3 \ (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \ AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY) #define HW_PRTY_ASSERT_SET_4 \ (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR |\ AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR) #define HW_INTERRUT_ASSERT_SET_0 \ (AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_BRB_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT) #define HW_INTERRUT_ASSERT_SET_1 \ (AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT) #define HW_INTERRUT_ASSERT_SET_2 \ (AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_PXP_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_CFC_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT |\ AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT) #define RESERVED_GENERAL_ATTENTION_BIT_0 0 #define EVEREST_GEN_ATTN_IN_USE_MASK 0x7ffe0 #define EVEREST_LATCHED_ATTN_IN_USE_MASK 0xffe00000 #define RESERVED_GENERAL_ATTENTION_BIT_6 6 #define RESERVED_GENERAL_ATTENTION_BIT_7 7 #define RESERVED_GENERAL_ATTENTION_BIT_8 8 #define RESERVED_GENERAL_ATTENTION_BIT_9 9 #define RESERVED_GENERAL_ATTENTION_BIT_10 10 #define RESERVED_GENERAL_ATTENTION_BIT_11 11 #define RESERVED_GENERAL_ATTENTION_BIT_12 12 #define RESERVED_GENERAL_ATTENTION_BIT_13 13 #define RESERVED_GENERAL_ATTENTION_BIT_14 14 #define RESERVED_GENERAL_ATTENTION_BIT_15 15 #define RESERVED_GENERAL_ATTENTION_BIT_16 16 #define RESERVED_GENERAL_ATTENTION_BIT_17 17 #define RESERVED_GENERAL_ATTENTION_BIT_18 18 #define RESERVED_GENERAL_ATTENTION_BIT_19 19 #define RESERVED_GENERAL_ATTENTION_BIT_20 20 #define RESERVED_GENERAL_ATTENTION_BIT_21 21 /* storm asserts attention bits */ #define TSTORM_FATAL_ASSERT_ATTENTION_BIT RESERVED_GENERAL_ATTENTION_BIT_7 #define USTORM_FATAL_ASSERT_ATTENTION_BIT RESERVED_GENERAL_ATTENTION_BIT_8 #define CSTORM_FATAL_ASSERT_ATTENTION_BIT RESERVED_GENERAL_ATTENTION_BIT_9 #define XSTORM_FATAL_ASSERT_ATTENTION_BIT RESERVED_GENERAL_ATTENTION_BIT_10 /* mcp error attention bit */ #define MCP_FATAL_ASSERT_ATTENTION_BIT RESERVED_GENERAL_ATTENTION_BIT_11 /*E1H NIG status sync attention mapped to group 4-7*/ #define LINK_SYNC_ATTENTION_BIT_FUNC_0 RESERVED_GENERAL_ATTENTION_BIT_12 #define LINK_SYNC_ATTENTION_BIT_FUNC_1 RESERVED_GENERAL_ATTENTION_BIT_13 #define LINK_SYNC_ATTENTION_BIT_FUNC_2 RESERVED_GENERAL_ATTENTION_BIT_14 #define LINK_SYNC_ATTENTION_BIT_FUNC_3 RESERVED_GENERAL_ATTENTION_BIT_15 #define LINK_SYNC_ATTENTION_BIT_FUNC_4 RESERVED_GENERAL_ATTENTION_BIT_16 #define LINK_SYNC_ATTENTION_BIT_FUNC_5 RESERVED_GENERAL_ATTENTION_BIT_17 #define LINK_SYNC_ATTENTION_BIT_FUNC_6 RESERVED_GENERAL_ATTENTION_BIT_18 #define LINK_SYNC_ATTENTION_BIT_FUNC_7 RESERVED_GENERAL_ATTENTION_BIT_19 /* Used For Error Recovery: changing this will require more \ changes in code that assume * error recovery uses general attn bit20 ! */ #define ERROR_RECOVERY_ATTENTION_BIT \ RESERVED_GENERAL_ATTENTION_BIT_20 #define RESERVED_ATTENTION_BIT \ RESERVED_GENERAL_ATTENTION_BIT_21 #define LATCHED_ATTN_RBCR 23 #define LATCHED_ATTN_RBCT 24 #define LATCHED_ATTN_RBCN 25 #define LATCHED_ATTN_RBCU 26 #define LATCHED_ATTN_RBCP 27 #define LATCHED_ATTN_TIMEOUT_GRC 28 #define LATCHED_ATTN_RSVD_GRC 29 #define LATCHED_ATTN_ROM_PARITY_MCP 30 #define LATCHED_ATTN_UM_RX_PARITY_MCP 31 #define LATCHED_ATTN_UM_TX_PARITY_MCP 32 #define LATCHED_ATTN_SCPAD_PARITY_MCP 33 #define GENERAL_ATTEN_WORD(atten_name) ((94 + atten_name) / 32) #define GENERAL_ATTEN_OFFSET(atten_name) (1UL << ((94 + atten_name) % 32)) /* * This file defines GRC base address for every block. * This file is included by chipsim, asm microcode and cpp microcode. * These values are used in Design.xml on regBase attribute * Use the base with the generated offsets of specific registers. */ #define GRCBASE_PXPCS 0x000000 #define GRCBASE_PCICONFIG 0x002000 #define GRCBASE_PCIREG 0x002400 #define GRCBASE_EMAC0 0x008000 #define GRCBASE_EMAC1 0x008400 #define GRCBASE_DBU 0x008800 #define GRCBASE_PGLUE_B 0x009000 #define GRCBASE_MISC 0x00A000 #define GRCBASE_DBG 0x00C000 #define GRCBASE_NIG 0x010000 #define GRCBASE_XCM 0x020000 #define GRCBASE_PRS 0x040000 #define GRCBASE_SRCH 0x040400 #define GRCBASE_TSDM 0x042000 #define GRCBASE_TCM 0x050000 #define GRCBASE_BRB1 0x060000 #define GRCBASE_MCP 0x080000 #define GRCBASE_UPB 0x0C1000 #define GRCBASE_CSDM 0x0C2000 #define GRCBASE_USDM 0x0C4000 #define GRCBASE_CCM 0x0D0000 #define GRCBASE_UCM 0x0E0000 #define GRCBASE_CDU 0x101000 #define GRCBASE_DMAE 0x102000 #define GRCBASE_PXP 0x103000 #define GRCBASE_CFC 0x104000 #define GRCBASE_HC 0x108000 #define GRCBASE_ATC 0x110000 #define GRCBASE_PXP2 0x120000 #define GRCBASE_IGU 0x130000 #define GRCBASE_PBF 0x140000 #define GRCBASE_UMAC0 0x160000 #define GRCBASE_UMAC1 0x160400 #define GRCBASE_XPB 0x161000 #define GRCBASE_MSTAT0 0x162000 #define GRCBASE_MSTAT1 0x162800 #define GRCBASE_XMAC0 0x163000 #define GRCBASE_XMAC1 0x163800 #define GRCBASE_TIMERS 0x164000 #define GRCBASE_XSDM 0x166000 #define GRCBASE_QM 0x168000 #define GRCBASE_QM_4PORT 0x168000 #define GRCBASE_DQ 0x170000 #define GRCBASE_TSEM 0x180000 #define GRCBASE_CSEM 0x200000 #define GRCBASE_XSEM 0x280000 #define GRCBASE_XSEM_4PORT 0x280000 #define GRCBASE_USEM 0x300000 #define GRCBASE_MCP_A 0x380000 #define GRCBASE_MISC_AEU GRCBASE_MISC #define GRCBASE_Tstorm GRCBASE_TSEM #define GRCBASE_Cstorm GRCBASE_CSEM #define GRCBASE_Xstorm GRCBASE_XSEM #define GRCBASE_Ustorm GRCBASE_USEM /* offset of configuration space in the pci core register */ #define PCICFG_OFFSET 0x2000 #define PCICFG_VENDOR_ID_OFFSET 0x00 #define PCICFG_DEVICE_ID_OFFSET 0x02 #define PCICFG_COMMAND_OFFSET 0x04 #define PCICFG_COMMAND_IO_SPACE (1<<0) #define PCICFG_COMMAND_MEM_SPACE (1<<1) #define PCICFG_COMMAND_BUS_MASTER (1<<2) #define PCICFG_COMMAND_SPECIAL_CYCLES (1<<3) #define PCICFG_COMMAND_MWI_CYCLES (1<<4) #define PCICFG_COMMAND_VGA_SNOOP (1<<5) #define PCICFG_COMMAND_PERR_ENA (1<<6) #define PCICFG_COMMAND_STEPPING (1<<7) #define PCICFG_COMMAND_SERR_ENA (1<<8) #define PCICFG_COMMAND_FAST_B2B (1<<9) #define PCICFG_COMMAND_INT_DISABLE (1<<10) #define PCICFG_COMMAND_RESERVED (0x1f<<11) #define PCICFG_STATUS_OFFSET 0x06 #define PCICFG_REVISION_ID_OFFSET 0x08 #define PCICFG_REVESION_ID_MASK 0xff #define PCICFG_REVESION_ID_ERROR_VAL 0xff #define PCICFG_CACHE_LINE_SIZE 0x0c #define PCICFG_LATENCY_TIMER 0x0d #define PCICFG_HEADER_TYPE 0x0e #define PCICFG_HEADER_TYPE_NORMAL 0 #define PCICFG_HEADER_TYPE_BRIDGE 1 #define PCICFG_HEADER_TYPE_CARDBUS 2 #define PCICFG_BAR_1_LOW 0x10 #define PCICFG_BAR_1_HIGH 0x14 #define PCICFG_BAR_2_LOW 0x18 #define PCICFG_BAR_2_HIGH 0x1c #define PCICFG_BAR_3_LOW 0x20 #define PCICFG_BAR_3_HIGH 0x24 #define PCICFG_SUBSYSTEM_VENDOR_ID_OFFSET 0x2c #define PCICFG_SUBSYSTEM_ID_OFFSET 0x2e #define PCICFG_INT_LINE 0x3c #define PCICFG_INT_PIN 0x3d #define PCICFG_PM_CAPABILITY 0x48 #define PCICFG_PM_CAPABILITY_VERSION (0x3<<16) #define PCICFG_PM_CAPABILITY_CLOCK (1<<19) #define PCICFG_PM_CAPABILITY_RESERVED (1<<20) #define PCICFG_PM_CAPABILITY_DSI (1<<21) #define PCICFG_PM_CAPABILITY_AUX_CURRENT (0x7<<22) #define PCICFG_PM_CAPABILITY_D1_SUPPORT (1<<25) #define PCICFG_PM_CAPABILITY_D2_SUPPORT (1<<26) #define PCICFG_PM_CAPABILITY_PME_IN_D0 (1<<27) #define PCICFG_PM_CAPABILITY_PME_IN_D1 (1<<28) #define PCICFG_PM_CAPABILITY_PME_IN_D2 (1<<29) #define PCICFG_PM_CAPABILITY_PME_IN_D3_HOT (1<<30) #define PCICFG_PM_CAPABILITY_PME_IN_D3_COLD (1<<31) #define PCICFG_PM_CSR_OFFSET 0x4c #define PCICFG_PM_CSR_STATE (0x3<<0) #define PCICFG_PM_CSR_PME_ENABLE (1<<8) #define PCICFG_PM_CSR_PME_STATUS (1<<15) #define PCICFG_VPD_FLAG_ADDR_OFFSET 0x50 #define PCICFG_VPD_DATA_OFFSET 0x54 #define PCICFG_MSI_CAP_ID_OFFSET 0x58 #define PCICFG_MSI_CONTROL_ENABLE (0x1<<16) #define PCICFG_MSI_CONTROL_MCAP (0x7<<17) #define PCICFG_MSI_CONTROL_MENA (0x7<<20) #define PCICFG_MSI_CONTROL_64_BIT_ADDR_CAP (0x1<<23) #define PCICFG_MSI_CONTROL_MSI_PVMASK_CAPABLE (0x1<<24) #define PCICFG_MSI_ADDR_LOW_OFFSET 0x5c #define PCICFG_MSI_ADDR_HIGH_OFFSET 0x60 #define PCICFG_MSI_DATA_OFFSET 0x64 #define PCICFG_GRC_ADDRESS 0x78 #define PCICFG_GRC_DATA 0x80 #define PCICFG_ME_REGISTER 0x98 #define PCICFG_MSIX_CAP_ID_OFFSET 0xa0 #define PCICFG_MSIX_CONTROL_TABLE_SIZE (0x7ff<<16) #define PCICFG_MSIX_CONTROL_RESERVED (0x7<<27) #define PCICFG_MSIX_CONTROL_FUNC_MASK (0x1<<30) #define PCICFG_MSIX_CONTROL_MSIX_ENABLE (0x1<<31) #define PCICFG_DEVICE_CONTROL 0xb4 #define PCICFG_DEVICE_CONTROL_NP_TRANSACTION_PEND (1<<21) #define PCICFG_DEVICE_STATUS 0xb6 #define PCICFG_DEVICE_STATUS_CORR_ERR_DET (1<<0) #define PCICFG_DEVICE_STATUS_NON_FATAL_ERR_DET (1<<1) #define PCICFG_DEVICE_STATUS_FATAL_ERR_DET (1<<2) #define PCICFG_DEVICE_STATUS_UNSUP_REQ_DET (1<<3) #define PCICFG_DEVICE_STATUS_AUX_PWR_DET (1<<4) #define PCICFG_DEVICE_STATUS_NO_PEND (1<<5) #define PCICFG_LINK_CONTROL 0xbc /* config_2 offset */ #define GRC_CONFIG_2_SIZE_REG 0x408 #define PCI_CONFIG_2_BAR1_SIZE (0xfL<<0) #define PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0) #define PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0) #define PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0) #define PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0) #define PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0) #define PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0) #define PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0) #define PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0) #define PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0) #define PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0) #define PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0) #define PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0) #define PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0) #define PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0) #define PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0) #define PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0) #define PCI_CONFIG_2_BAR1_64ENA (1L<<4) #define PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5) #define PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6) #define PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7) #define PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_2K (1L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_4K (2L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_8K (3L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_16K (4L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_32K (5L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_64K (6L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_128K (7L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_256K (8L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_512K (9L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_1M (10L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_2M (11L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_4M (12L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_8M (13L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_16M (14L<<8) #define PCI_CONFIG_2_EXP_ROM_SIZE_32M (15L<<8) #define PCI_CONFIG_2_BAR_PREFETCH (1L<<16) #define PCI_CONFIG_2_RESERVED0 (0x7fffL<<17) /* config_3 offset */ #define GRC_CONFIG_3_SIZE_REG 0x40c #define PCI_CONFIG_3_STICKY_BYTE (0xffL<<0) #define PCI_CONFIG_3_FORCE_PME (1L<<24) #define PCI_CONFIG_3_PME_STATUS (1L<<25) #define PCI_CONFIG_3_PME_ENABLE (1L<<26) #define PCI_CONFIG_3_PM_STATE (0x3L<<27) #define PCI_CONFIG_3_VAUX_PRESET (1L<<30) #define PCI_CONFIG_3_PCI_POWER (1L<<31) #define GRC_REG_DEVICE_CONTROL 0x4d8 #define PCIE_SRIOV_DISABLE_IN_PROGRESS \ (1 << 29) /*When VF Enable is cleared(after it was previously set), this register will read a value of 1, indicating that all the VFs that belong to this PF should be flushed. Software should clear this bit within 1 second of VF Enable being set by writing a 1 to it, so that VFs are visible to the system again. WC */ #define PCIE_FLR_IN_PROGRESS \ (1 << 27) /*When FLR is initiated, this register will read a \ value of 1 indicating that the Function is in FLR state. Func can be brought out of FLR state either by writing 1 to this register (at least 50 ms after FLR was initiated), or it can also be cleared automatically after 55 ms if auto_clear bit in private reg space is set. This bit also exists in VF register space WC */ #define GRC_BAR2_CONFIG 0x4e0 #define PCI_CONFIG_2_BAR2_SIZE (0xfL<<0) #define PCI_CONFIG_2_BAR2_SIZE_DISABLED (0L<<0) #define PCI_CONFIG_2_BAR2_SIZE_64K (1L<<0) #define PCI_CONFIG_2_BAR2_SIZE_128K (2L<<0) #define PCI_CONFIG_2_BAR2_SIZE_256K (3L<<0) #define PCI_CONFIG_2_BAR2_SIZE_512K (4L<<0) #define PCI_CONFIG_2_BAR2_SIZE_1M (5L<<0) #define PCI_CONFIG_2_BAR2_SIZE_2M (6L<<0) #define PCI_CONFIG_2_BAR2_SIZE_4M (7L<<0) #define PCI_CONFIG_2_BAR2_SIZE_8M (8L<<0) #define PCI_CONFIG_2_BAR2_SIZE_16M (9L<<0) #define PCI_CONFIG_2_BAR2_SIZE_32M (10L<<0) #define PCI_CONFIG_2_BAR2_SIZE_64M (11L<<0) #define PCI_CONFIG_2_BAR2_SIZE_128M (12L<<0) #define PCI_CONFIG_2_BAR2_SIZE_256M (13L<<0) #define PCI_CONFIG_2_BAR2_SIZE_512M (14L<<0) #define PCI_CONFIG_2_BAR2_SIZE_1G (15L<<0) #define PCI_CONFIG_2_BAR2_64ENA (1L<<4) #define GRC_BAR3_CONFIG 0x4f4 #define PCI_CONFIG_2_BAR3_SIZE (0xfL<<0) #define PCI_CONFIG_2_BAR3_SIZE_DISABLED (0L<<0) #define PCI_CONFIG_2_BAR3_SIZE_64K (1L<<0) #define PCI_CONFIG_2_BAR3_SIZE_128K (2L<<0) #define PCI_CONFIG_2_BAR3_SIZE_256K (3L<<0) #define PCI_CONFIG_2_BAR3_SIZE_512K (4L<<0) #define PCI_CONFIG_2_BAR3_SIZE_1M (5L<<0) #define PCI_CONFIG_2_BAR3_SIZE_2M (6L<<0) #define PCI_CONFIG_2_BAR3_SIZE_4M (7L<<0) #define PCI_CONFIG_2_BAR3_SIZE_8M (8L<<0) #define PCI_CONFIG_2_BAR3_SIZE_16M (9L<<0) #define PCI_CONFIG_2_BAR3_SIZE_32M (10L<<0) #define PCI_CONFIG_2_BAR3_SIZE_64M (11L<<0) #define PCI_CONFIG_2_BAR3_SIZE_128M (12L<<0) #define PCI_CONFIG_2_BAR3_SIZE_256M (13L<<0) #define PCI_CONFIG_2_BAR3_SIZE_512M (14L<<0) #define PCI_CONFIG_2_BAR3_SIZE_1G (15L<<0) #define PCI_CONFIG_2_BAR3_64ENA (1L<<4) #define PCI_PM_DATA_A 0x410 #define PCI_PM_DATA_B 0x414 #define PCI_ID_VAL1 0x434 #define PCI_ID_VAL2 0x438 #define PCI_ID_VAL3 0x43c #define PCI_ID_VAL3_REVISION_ID_ERROR (0xffL<<24) #define GRC_CONFIG_REG_VF_BAR_REG_1 0x608 #define GRC_CONFIG_REG_VF_BAR_REG_BAR0_SIZE 0xf #define GRC_CONFIG_REG_VF_MSIX_CONTROL 0x61C #define GRC_CR_VF_MSIX_CTRL_VF_MSIX_TBL_SIZE_MASK \ 0x3F /*This field resides in VF only and does not exist in PF. This register controls the read value of the MSIX_CONTROL[10:0] register in the VF configuration space. A value of "00000000011" indicates a table size of 4. The value is controlled by IOV_MSIX_TBL_SIZ define in version.v */ #define GRC_CONFIG_REG_PF_INIT_VF 0x624 #define GRC_CR_PF_INIT_VF_PF_FIRST_VF_NUM_MASK \ 0xf /*First VF_NUM for PF is encoded in this register. The number of VFs assigned to a PF is assumed to be a multiple of 8. Software should program these bits based on Total Number of VFs \ programmed for each PF. Since registers from 0x000-0x7ff are spilt across functions, each PF will have the same location for the same 4 bits*/ #define PXPCS_TL_CONTROL_5 0x814 #define PXPCS_TL_CONTROL_5_UNKNOWNTYPE_ERR_ATTN (1 << 29) /*WC*/ #define PXPCS_TL_CONTROL_5_BOUNDARY4K_ERR_ATTN (1 << 28) /*WC*/ #define PXPCS_TL_CONTROL_5_MRRS_ERR_ATTN (1 << 27) /*WC*/ #define PXPCS_TL_CONTROL_5_MPS_ERR_ATTN (1 << 26) /*WC*/ #define PXPCS_TL_CONTROL_5_TTX_BRIDGE_FORWARD_ERR (1 << 25) /*WC*/ #define PXPCS_TL_CONTROL_5_TTX_TXINTF_OVERFLOW (1 << 24) /*WC*/ #define PXPCS_TL_CONTROL_5_PHY_ERR_ATTN (1 << 23) /*RO*/ #define PXPCS_TL_CONTROL_5_DL_ERR_ATTN (1 << 22) /*RO*/ #define PXPCS_TL_CONTROL_5_TTX_ERR_NP_TAG_IN_USE (1 << 21) /*WC*/ #define PXPCS_TL_CONTROL_5_TRX_ERR_UNEXP_RTAG (1 << 20) /*WC*/ #define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT1 (1 << 19) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_UNSPPORT1 (1 << 18) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_ECRC1 (1 << 17) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_MALF_TLP1 (1 << 16) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW1 (1 << 15) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL1 (1 << 14) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT1 (1 << 13) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT1 (1 << 12) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_FC_PRTL1 (1 << 11) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_PSND_TLP1 (1 << 10) /*WC*/ #define PXPCS_TL_CONTROL_5_PRI_SIG_TARGET_ABORT (1 << 9) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_UNSPPORT (1 << 8) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_ECRC (1 << 7) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_MALF_TLP (1 << 6) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_RX_OFLOW (1 << 5) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_UNEXP_CPL (1 << 4) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_MASTER_ABRT (1 << 3) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_CPL_TIMEOUT (1 << 2) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_FC_PRTL (1 << 1) /*WC*/ #define PXPCS_TL_CONTROL_5_ERR_PSND_TLP (1 << 0) /*WC*/ #define PXPCS_TL_FUNC345_STAT 0x854 #define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT4 (1 << 29) /* WC */ #define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT4 \ (1 << 28) /* Unsupported Request Error Status in function4, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_ECRC4 \ (1 << 27) /* ECRC Error TLP Status Status in function 4, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP4 \ (1 << 26) /* Malformed TLP Status Status in function 4, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW4 \ (1 << 25) /* Receiver Overflow Status Status in function 4, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL4 \ (1 << 24) /* Unexpected Completion Status Status in function 4, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT4 \ (1 << 23) /* Receive UR Statusin function 4. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT4 \ (1 << 22) /* Completer Timeout Status Status in function 4, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL4 \ (1 << 21) /* Flow Control Protocol Error Status Status in \ function 4, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP4 \ (1 << 20) /* Poisoned Error Status Status in function 4, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT3 (1 << 19) /* WC */ #define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT3 \ (1 << 18) /* Unsupported Request Error Status in function3, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_ECRC3 \ (1 << 17) /* ECRC Error TLP Status Status in function 3, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP3 \ (1 << 16) /* Malformed TLP Status Status in function 3, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW3 \ (1 << 15) /* Receiver Overflow Status Status in function 3, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL3 \ (1 << 14) /* Unexpected Completion Status Status in function 3, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT3 \ (1 << 13) /* Receive UR Statusin function 3. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT3 \ (1 << 12) /* Completer Timeout Status Status in function 3, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL3 \ (1 << 11) /* Flow Control Protocol Error Status Status in \ function 3, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP3 \ (1 << 10) /* Poisoned Error Status Status in function 3, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_PRI_SIG_TARGET_ABORT2 (1 << 9) /* WC */ #define PXPCS_TL_FUNC345_STAT_ERR_UNSPPORT2 \ (1 << 8) /* Unsupported Request Error Status for Function 2, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_ECRC2 \ (1 << 7) /* ECRC Error TLP Status Status for Function 2, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_MALF_TLP2 \ (1 << 6) /* Malformed TLP Status Status for Function 2, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_RX_OFLOW2 \ (1 << 5) /* Receiver Overflow Status Status for Function 2, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_UNEXP_CPL2 \ (1 << 4) /* Unexpected Completion Status Status for Function 2, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC345_STAT_ERR_MASTER_ABRT2 \ (1 << 3) /* Receive UR Statusfor Function 2. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_CPL_TIMEOUT2 \ (1 << 2) /* Completer Timeout Status Status for Function 2, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_FC_PRTL2 \ (1 << 1) /* Flow Control Protocol Error Status Status for \ Function 2, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC345_STAT_ERR_PSND_TLP2 \ (1 << 0) /* Poisoned Error Status Status for Function 2, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT 0x85C #define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT7 (1 << 29) /* WC */ #define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT7 \ (1 << 28) /* Unsupported Request Error Status in function7, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_ECRC7 \ (1 << 27) /* ECRC Error TLP Status Status in function 7, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP7 \ (1 << 26) /* Malformed TLP Status Status in function 7, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW7 \ (1 << 25) /* Receiver Overflow Status Status in function 7, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL7 \ (1 << 24) /* Unexpected Completion Status Status in function 7, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT7 \ (1 << 23) /* Receive UR Statusin function 7. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT7 \ (1 << 22) /* Completer Timeout Status Status in function 7, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL7 \ (1 << 21) /* Flow Control Protocol Error Status Status in \ function 7, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP7 \ (1 << 20) /* Poisoned Error Status Status in function 7, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT6 (1 << 19) /* WC */ #define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT6 \ (1 << 18) /* Unsupported Request Error Status in function6, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_ECRC6 \ (1 << 17) /* ECRC Error TLP Status Status in function 6, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP6 \ (1 << 16) /* Malformed TLP Status Status in function 6, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW6 \ (1 << 15) /* Receiver Overflow Status Status in function 6, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL6 \ (1 << 14) /* Unexpected Completion Status Status in function 6, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT6 \ (1 << 13) /* Receive UR Statusin function 6. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT6 \ (1 << 12) /* Completer Timeout Status Status in function 6, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL6 \ (1 << 11) /* Flow Control Protocol Error Status Status in \ function 6, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP6 \ (1 << 10) /* Poisoned Error Status Status in function 6, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_PRI_SIG_TARGET_ABORT5 (1 << 9) /* WC */ #define PXPCS_TL_FUNC678_STAT_ERR_UNSPPORT5 \ (1 << 8) /* Unsupported Request Error Status for Function 5, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_ECRC5 \ (1 << 7) /* ECRC Error TLP Status Status for Function 5, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_MALF_TLP5 \ (1 << 6) /* Malformed TLP Status Status for Function 5, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_RX_OFLOW5 \ (1 << 5) /* Receiver Overflow Status Status for Function 5, if \ set, generate pcie_err_attn output when this error is seen.. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_UNEXP_CPL5 \ (1 << 4) /* Unexpected Completion Status Status for Function 5, \ if set, generate pcie_err_attn output when this error is seen. WC \ */ #define PXPCS_TL_FUNC678_STAT_ERR_MASTER_ABRT5 \ (1 << 3) /* Receive UR Statusfor Function 5. If set, generate \ pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_CPL_TIMEOUT5 \ (1 << 2) /* Completer Timeout Status Status for Function 5, if \ set, generate pcie_err_attn output when this error is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_FC_PRTL5 \ (1 << 1) /* Flow Control Protocol Error Status Status for \ Function 5, if set, generate pcie_err_attn output when this error \ is seen. WC */ #define PXPCS_TL_FUNC678_STAT_ERR_PSND_TLP5 \ (1 << 0) /* Poisoned Error Status Status for Function 5, if set, \ generate pcie_err_attn output when this error is seen.. WC */ #define BAR_USTRORM_INTMEM 0x400000 #define BAR_CSTRORM_INTMEM 0x410000 #define BAR_XSTRORM_INTMEM 0x420000 #define BAR_TSTRORM_INTMEM 0x430000 /* for accessing the IGU in case of status block ACK */ #define BAR_IGU_INTMEM 0x440000 #define BAR_DOORBELL_OFFSET 0x800000 #define BAR_ME_REGISTER 0x450000 #define ME_REG_PF_NUM_SHIFT 0 #define ME_REG_PF_NUM \ (7L<> ME_REG_VF_NUM_SHIFT) #define ME_REG_VF_ERR (0x1<<3) #define ME_REG_ABS_PF_NUM_SHIFT 16 #define ME_REG_ABS_PF_NUM \ (7L< * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "bnx2x.h" #include "ecore_init.h" /**** Exe Queue interfaces ****/ /** * ecore_exe_queue_init - init the Exe Queue object * * @o: pointer to the object * @exe_len: length * @owner: pointer to the owner * @validate: validate function pointer * @optimize: optimize function pointer * @exec: execute function pointer * @get: get function pointer */ static void ecore_exe_queue_init(struct bnx2x_softc *sc __rte_unused, struct ecore_exe_queue_obj *o, int exe_len, union ecore_qable_obj *owner, exe_q_validate validate, exe_q_remove remove, exe_q_optimize optimize, exe_q_execute exec, exe_q_get get) { ECORE_MEMSET(o, 0, sizeof(*o)); ECORE_LIST_INIT(&o->exe_queue); ECORE_LIST_INIT(&o->pending_comp); ECORE_SPIN_LOCK_INIT(&o->lock, sc); o->exe_chunk_len = exe_len; o->owner = owner; /* Owner specific callbacks */ o->validate = validate; o->remove = remove; o->optimize = optimize; o->execute = exec; o->get = get; ECORE_MSG("Setup the execution queue with the chunk length of %d", exe_len); } static void ecore_exe_queue_free_elem(struct bnx2x_softc *sc __rte_unused, struct ecore_exeq_elem *elem) { ECORE_MSG("Deleting an exe_queue element"); ECORE_FREE(sc, elem, sizeof(*elem)); } static inline int ecore_exe_queue_length(struct ecore_exe_queue_obj *o) { struct ecore_exeq_elem *elem; int cnt = 0; ECORE_SPIN_LOCK_BH(&o->lock); ECORE_LIST_FOR_EACH_ENTRY(elem, &o->exe_queue, link, struct ecore_exeq_elem) cnt++; ECORE_SPIN_UNLOCK_BH(&o->lock); return cnt; } /** * ecore_exe_queue_add - add a new element to the execution queue * * @sc: driver handle * @o: queue * @cmd: new command to add * @restore: true - do not optimize the command * * If the element is optimized or is illegal, frees it. */ static int ecore_exe_queue_add(struct bnx2x_softc *sc, struct ecore_exe_queue_obj *o, struct ecore_exeq_elem *elem, int restore) { int rc; ECORE_SPIN_LOCK_BH(&o->lock); if (!restore) { /* Try to cancel this element queue */ rc = o->optimize(sc, o->owner, elem); if (rc) goto free_and_exit; /* Check if this request is ok */ rc = o->validate(sc, o->owner, elem); if (rc) { ECORE_MSG("Preamble failed: %d", rc); goto free_and_exit; } } /* If so, add it to the execution queue */ ECORE_LIST_PUSH_TAIL(&elem->link, &o->exe_queue); ECORE_SPIN_UNLOCK_BH(&o->lock); return ECORE_SUCCESS; free_and_exit: ecore_exe_queue_free_elem(sc, elem); ECORE_SPIN_UNLOCK_BH(&o->lock); return rc; } static void __ecore_exe_queue_reset_pending(struct bnx2x_softc *sc, struct ecore_exe_queue_obj *o) { struct ecore_exeq_elem *elem; while (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) { elem = ECORE_LIST_FIRST_ENTRY(&o->pending_comp, struct ecore_exeq_elem, link); ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->pending_comp); ecore_exe_queue_free_elem(sc, elem); } } static inline void ecore_exe_queue_reset_pending(struct bnx2x_softc *sc, struct ecore_exe_queue_obj *o) { ECORE_SPIN_LOCK_BH(&o->lock); __ecore_exe_queue_reset_pending(sc, o); ECORE_SPIN_UNLOCK_BH(&o->lock); } /** * ecore_exe_queue_step - execute one execution chunk atomically * * @sc: driver handle * @o: queue * @ramrod_flags: flags * * (Should be called while holding the exe_queue->lock). */ static int ecore_exe_queue_step(struct bnx2x_softc *sc, struct ecore_exe_queue_obj *o, unsigned long *ramrod_flags) { struct ecore_exeq_elem *elem, spacer; int cur_len = 0, rc; ECORE_MEMSET(&spacer, 0, sizeof(spacer)); /* Next step should not be performed until the current is finished, * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to * properly clear object internals without sending any command to the FW * which also implies there won't be any completion to clear the * 'pending' list. */ if (!ECORE_LIST_IS_EMPTY(&o->pending_comp)) { if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags)) { ECORE_MSG ("RAMROD_DRV_CLR_ONLY requested: resetting a pending_comp list"); __ecore_exe_queue_reset_pending(sc, o); } else { return ECORE_PENDING; } } /* Run through the pending commands list and create a next * execution chunk. */ while (!ECORE_LIST_IS_EMPTY(&o->exe_queue)) { elem = ECORE_LIST_FIRST_ENTRY(&o->exe_queue, struct ecore_exeq_elem, link); ECORE_DBG_BREAK_IF(!elem->cmd_len); if (cur_len + elem->cmd_len <= o->exe_chunk_len) { cur_len += elem->cmd_len; /* Prevent from both lists being empty when moving an * element. This will allow the call of * ecore_exe_queue_empty() without locking. */ ECORE_LIST_PUSH_TAIL(&spacer.link, &o->pending_comp); mb(); ECORE_LIST_REMOVE_ENTRY(&elem->link, &o->exe_queue); ECORE_LIST_PUSH_TAIL(&elem->link, &o->pending_comp); ECORE_LIST_REMOVE_ENTRY(&spacer.link, &o->pending_comp); } else break; } /* Sanity check */ if (!cur_len) return ECORE_SUCCESS; rc = o->execute(sc, o->owner, &o->pending_comp, ramrod_flags); if (rc < 0) /* In case of an error return the commands back to the queue * and reset the pending_comp. */ ECORE_LIST_SPLICE_INIT(&o->pending_comp, &o->exe_queue); else if (!rc) /* If zero is returned, means there are no outstanding pending * completions and we may dismiss the pending list. */ __ecore_exe_queue_reset_pending(sc, o); return rc; } static inline int ecore_exe_queue_empty(struct ecore_exe_queue_obj *o) { int empty = ECORE_LIST_IS_EMPTY(&o->exe_queue); /* Don't reorder!!! */ mb(); return empty && ECORE_LIST_IS_EMPTY(&o->pending_comp); } static struct ecore_exeq_elem *ecore_exe_queue_alloc_elem(struct bnx2x_softc *sc __rte_unused) { ECORE_MSG("Allocating a new exe_queue element"); return ECORE_ZALLOC(sizeof(struct ecore_exeq_elem), GFP_ATOMIC, sc); } /************************ raw_obj functions ***********************************/ static int ecore_raw_check_pending(struct ecore_raw_obj *o) { /* * !! converts the value returned by ECORE_TEST_BIT such that it * is guaranteed not to be truncated regardless of int definition. * * Note we cannot simply define the function's return value type * to match the type returned by ECORE_TEST_BIT, as it varies by * platform/implementation. */ return ! !ECORE_TEST_BIT(o->state, o->pstate); } static void ecore_raw_clear_pending(struct ecore_raw_obj *o) { ECORE_SMP_MB_BEFORE_CLEAR_BIT(); ECORE_CLEAR_BIT(o->state, o->pstate); ECORE_SMP_MB_AFTER_CLEAR_BIT(); } static void ecore_raw_set_pending(struct ecore_raw_obj *o) { ECORE_SMP_MB_BEFORE_CLEAR_BIT(); ECORE_SET_BIT(o->state, o->pstate); ECORE_SMP_MB_AFTER_CLEAR_BIT(); } /** * ecore_state_wait - wait until the given bit(state) is cleared * * @sc: device handle * @state: state which is to be cleared * @state_p: state buffer * */ static int ecore_state_wait(struct bnx2x_softc *sc, int state, unsigned long *pstate) { /* can take a while if any port is running */ int cnt = 5000; if (CHIP_REV_IS_EMUL(sc)) cnt *= 20; ECORE_MSG("waiting for state to become %d", state); ECORE_MIGHT_SLEEP(); while (cnt--) { bnx2x_intr_legacy(sc, 1); if (!ECORE_TEST_BIT(state, pstate)) { #ifdef ECORE_STOP_ON_ERROR ECORE_MSG("exit (cnt %d)", 5000 - cnt); #endif return ECORE_SUCCESS; } ECORE_WAIT(sc, delay_us); if (sc->panic) return ECORE_IO; } /* timeout! */ PMD_DRV_LOG(ERR, "timeout waiting for state %d", state); #ifdef ECORE_STOP_ON_ERROR ecore_panic(); #endif return ECORE_TIMEOUT; } static int ecore_raw_wait(struct bnx2x_softc *sc, struct ecore_raw_obj *raw) { return ecore_state_wait(sc, raw->state, raw->pstate); } /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/ /* credit handling callbacks */ static int ecore_get_cam_offset_mac(struct ecore_vlan_mac_obj *o, int *offset) { struct ecore_credit_pool_obj *mp = o->macs_pool; ECORE_DBG_BREAK_IF(!mp); return mp->get_entry(mp, offset); } static int ecore_get_credit_mac(struct ecore_vlan_mac_obj *o) { struct ecore_credit_pool_obj *mp = o->macs_pool; ECORE_DBG_BREAK_IF(!mp); return mp->get(mp, 1); } static int ecore_put_cam_offset_mac(struct ecore_vlan_mac_obj *o, int offset) { struct ecore_credit_pool_obj *mp = o->macs_pool; return mp->put_entry(mp, offset); } static int ecore_put_credit_mac(struct ecore_vlan_mac_obj *o) { struct ecore_credit_pool_obj *mp = o->macs_pool; return mp->put(mp, 1); } /** * __ecore_vlan_mac_h_write_trylock - try getting the writer lock on vlan mac * head list. * * @sc: device handle * @o: vlan_mac object * * @details: Non-blocking implementation; should be called under execution * queue lock. */ static int __ecore_vlan_mac_h_write_trylock(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o) { if (o->head_reader) { ECORE_MSG("vlan_mac_lock writer - There are readers; Busy"); return ECORE_BUSY; } ECORE_MSG("vlan_mac_lock writer - Taken"); return ECORE_SUCCESS; } /** * __ecore_vlan_mac_h_exec_pending - execute step instead of a previous step * which wasn't able to run due to a taken lock on vlan mac head list. * * @sc: device handle * @o: vlan_mac object * * @details Should be called under execution queue lock; notice it might release * and reclaim it during its run. */ static void __ecore_vlan_mac_h_exec_pending(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { int rc; unsigned long ramrod_flags = o->saved_ramrod_flags; ECORE_MSG("vlan_mac_lock execute pending command with ramrod flags %lu", ramrod_flags); o->head_exe_request = FALSE; o->saved_ramrod_flags = 0; rc = ecore_exe_queue_step(sc, &o->exe_queue, &ramrod_flags); if (rc != ECORE_SUCCESS) { PMD_DRV_LOG(ERR, "execution of pending commands failed with rc %d", rc); #ifdef ECORE_STOP_ON_ERROR ecore_panic(); #endif } } /** * __ecore_vlan_mac_h_pend - Pend an execution step which couldn't have been * called due to vlan mac head list lock being taken. * * @sc: device handle * @o: vlan_mac object * @ramrod_flags: ramrod flags of missed execution * * @details Should be called under execution queue lock. */ static void __ecore_vlan_mac_h_pend(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o, unsigned long ramrod_flags) { o->head_exe_request = TRUE; o->saved_ramrod_flags = ramrod_flags; ECORE_MSG("Placing pending execution with ramrod flags %lu", ramrod_flags); } /** * __ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock * * @sc: device handle * @o: vlan_mac object * * @details Should be called under execution queue lock. Notice if a pending * execution exists, it would perform it - possibly releasing and * reclaiming the execution queue lock. */ static void __ecore_vlan_mac_h_write_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { /* It's possible a new pending execution was added since this writer * executed. If so, execute again. [Ad infinitum] */ while (o->head_exe_request) { ECORE_MSG ("vlan_mac_lock - writer release encountered a pending request"); __ecore_vlan_mac_h_exec_pending(sc, o); } } /** * ecore_vlan_mac_h_write_unlock - unlock the vlan mac head list writer lock * * @sc: device handle * @o: vlan_mac object * * @details Notice if a pending execution exists, it would perform it - * possibly releasing and reclaiming the execution queue lock. */ void ecore_vlan_mac_h_write_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { ECORE_SPIN_LOCK_BH(&o->exe_queue.lock); __ecore_vlan_mac_h_write_unlock(sc, o); ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock); } /** * __ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock * * @sc: device handle * @o: vlan_mac object * * @details Should be called under the execution queue lock. May sleep. May * release and reclaim execution queue lock during its run. */ static int __ecore_vlan_mac_h_read_lock(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o) { /* If we got here, we're holding lock --> no WRITER exists */ o->head_reader++; ECORE_MSG("vlan_mac_lock - locked reader - number %d", o->head_reader); return ECORE_SUCCESS; } /** * ecore_vlan_mac_h_read_lock - lock the vlan mac head list reader lock * * @sc: device handle * @o: vlan_mac object * * @details May sleep. Claims and releases execution queue lock during its run. */ static int ecore_vlan_mac_h_read_lock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { int rc; ECORE_SPIN_LOCK_BH(&o->exe_queue.lock); rc = __ecore_vlan_mac_h_read_lock(sc, o); ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock); return rc; } /** * __ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock * * @sc: device handle * @o: vlan_mac object * * @details Should be called under execution queue lock. Notice if a pending * execution exists, it would be performed if this was the last * reader. possibly releasing and reclaiming the execution queue lock. */ static void __ecore_vlan_mac_h_read_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { if (!o->head_reader) { PMD_DRV_LOG(ERR, "Need to release vlan mac reader lock, but lock isn't taken"); #ifdef ECORE_STOP_ON_ERROR ecore_panic(); #endif } else { o->head_reader--; PMD_DRV_LOG(INFO, "vlan_mac_lock - decreased readers to %d", o->head_reader); } /* It's possible a new pending execution was added, and that this reader * was last - if so we need to execute the command. */ if (!o->head_reader && o->head_exe_request) { PMD_DRV_LOG(INFO, "vlan_mac_lock - reader release encountered a pending request"); /* Writer release will do the trick */ __ecore_vlan_mac_h_write_unlock(sc, o); } } /** * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock * * @sc: device handle * @o: vlan_mac object * * @details Notice if a pending execution exists, it would be performed if this * was the last reader. Claims and releases the execution queue lock * during its run. */ void ecore_vlan_mac_h_read_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { ECORE_SPIN_LOCK_BH(&o->exe_queue.lock); __ecore_vlan_mac_h_read_unlock(sc, o); ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock); } /** * ecore_vlan_mac_h_read_unlock - unlock the vlan mac head list reader lock * * @sc: device handle * @o: vlan_mac object * @n: number of elements to get * @base: base address for element placement * @stride: stride between elements (in bytes) */ static int ecore_get_n_elements(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, int n, uint8_t * base, uint8_t stride, uint8_t size) { struct ecore_vlan_mac_registry_elem *pos; uint8_t *next = base; int counter = 0, read_lock; ECORE_MSG("get_n_elements - taking vlan_mac_lock (reader)"); read_lock = ecore_vlan_mac_h_read_lock(sc, o); if (read_lock != ECORE_SUCCESS) PMD_DRV_LOG(ERR, "get_n_elements failed to get vlan mac reader lock; Access without lock"); /* traverse list */ ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link, struct ecore_vlan_mac_registry_elem) { if (counter < n) { ECORE_MEMCPY(next, &pos->u, size); counter++; ECORE_MSG ("copied element number %d to address %p element was:", counter, next); next += stride + size; } } if (read_lock == ECORE_SUCCESS) { ECORE_MSG("get_n_elements - releasing vlan_mac_lock (reader)"); ecore_vlan_mac_h_read_unlock(sc, o); } return counter * ETH_ALEN; } /* check_add() callbacks */ static int ecore_check_mac_add(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o, union ecore_classification_ramrod_data *data) { struct ecore_vlan_mac_registry_elem *pos; ECORE_MSG("Checking MAC %02x:%02x:%02x:%02x:%02x:%02x for ADD command", data->mac.mac[0], data->mac.mac[1], data->mac.mac[2], data->mac.mac[3], data->mac.mac[4], data->mac.mac[5]); if (!ECORE_IS_VALID_ETHER_ADDR(data->mac.mac)) return ECORE_INVAL; /* Check if a requested MAC already exists */ ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link, struct ecore_vlan_mac_registry_elem) if (!ECORE_MEMCMP(data->mac.mac, pos->u.mac.mac, ETH_ALEN) && (data->mac.is_inner_mac == pos->u.mac.is_inner_mac)) return ECORE_EXISTS; return ECORE_SUCCESS; } /* check_del() callbacks */ static struct ecore_vlan_mac_registry_elem *ecore_check_mac_del(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o, union ecore_classification_ramrod_data *data) { struct ecore_vlan_mac_registry_elem *pos; ECORE_MSG("Checking MAC %02x:%02x:%02x:%02x:%02x:%02x for DEL command", data->mac.mac[0], data->mac.mac[1], data->mac.mac[2], data->mac.mac[3], data->mac.mac[4], data->mac.mac[5]); ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link, struct ecore_vlan_mac_registry_elem) if ((!ECORE_MEMCMP(data->mac.mac, pos->u.mac.mac, ETH_ALEN)) && (data->mac.is_inner_mac == pos->u.mac.is_inner_mac)) return pos; return NULL; } /* check_move() callback */ static int ecore_check_move(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *src_o, struct ecore_vlan_mac_obj *dst_o, union ecore_classification_ramrod_data *data) { struct ecore_vlan_mac_registry_elem *pos; int rc; /* Check if we can delete the requested configuration from the first * object. */ pos = src_o->check_del(sc, src_o, data); /* check if configuration can be added */ rc = dst_o->check_add(sc, dst_o, data); /* If this classification can not be added (is already set) * or can't be deleted - return an error. */ if (rc || !pos) return FALSE; return TRUE; } static int ecore_check_move_always_err(__rte_unused struct bnx2x_softc *sc, __rte_unused struct ecore_vlan_mac_obj *src_o, __rte_unused struct ecore_vlan_mac_obj *dst_o, __rte_unused union ecore_classification_ramrod_data *data) { return FALSE; } static uint8_t ecore_vlan_mac_get_rx_tx_flag(struct ecore_vlan_mac_obj *o) { struct ecore_raw_obj *raw = &o->raw; uint8_t rx_tx_flag = 0; if ((raw->obj_type == ECORE_OBJ_TYPE_TX) || (raw->obj_type == ECORE_OBJ_TYPE_RX_TX)) rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_TX_CMD; if ((raw->obj_type == ECORE_OBJ_TYPE_RX) || (raw->obj_type == ECORE_OBJ_TYPE_RX_TX)) rx_tx_flag |= ETH_CLASSIFY_CMD_HEADER_RX_CMD; return rx_tx_flag; } static void ecore_set_mac_in_nig(struct bnx2x_softc *sc, int add, unsigned char *dev_addr, int index) { uint32_t wb_data[2]; uint32_t reg_offset = ECORE_PORT_ID(sc) ? NIG_REG_LLH1_FUNC_MEM : NIG_REG_LLH0_FUNC_MEM; if (!ECORE_IS_MF_SI_MODE(sc) && !IS_MF_AFEX(sc)) return; if (index > ECORE_LLH_CAM_MAX_PF_LINE) return; ECORE_MSG("Going to %s LLH configuration at entry %d", (add ? "ADD" : "DELETE"), index); if (add) { /* LLH_FUNC_MEM is a uint64_t WB register */ reg_offset += 8 * index; wb_data[0] = ((dev_addr[2] << 24) | (dev_addr[3] << 16) | (dev_addr[4] << 8) | dev_addr[5]); wb_data[1] = ((dev_addr[0] << 8) | dev_addr[1]); ECORE_REG_WR_DMAE_LEN(sc, reg_offset, wb_data, 2); } REG_WR(sc, (ECORE_PORT_ID(sc) ? NIG_REG_LLH1_FUNC_MEM_ENABLE : NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4 * index, add); } /** * ecore_vlan_mac_set_cmd_hdr_e2 - set a header in a single classify ramrod * * @sc: device handle * @o: queue for which we want to configure this rule * @add: if TRUE the command is an ADD command, DEL otherwise * @opcode: CLASSIFY_RULE_OPCODE_XXX * @hdr: pointer to a header to setup * */ static void ecore_vlan_mac_set_cmd_hdr_e2(struct ecore_vlan_mac_obj *o, int add, int opcode, struct eth_classify_cmd_header *hdr) { struct ecore_raw_obj *raw = &o->raw; hdr->client_id = raw->cl_id; hdr->func_id = raw->func_id; /* Rx or/and Tx (internal switching) configuration ? */ hdr->cmd_general_data |= ecore_vlan_mac_get_rx_tx_flag(o); if (add) hdr->cmd_general_data |= ETH_CLASSIFY_CMD_HEADER_IS_ADD; hdr->cmd_general_data |= (opcode << ETH_CLASSIFY_CMD_HEADER_OPCODE_SHIFT); } /** * ecore_vlan_mac_set_rdata_hdr_e2 - set the classify ramrod data header * * @cid: connection id * @type: ECORE_FILTER_XXX_PENDING * @hdr: pointer to header to setup * @rule_cnt: * * currently we always configure one rule and echo field to contain a CID and an * opcode type. */ static void ecore_vlan_mac_set_rdata_hdr_e2(uint32_t cid, int type, struct eth_classify_header *hdr, int rule_cnt) { hdr->echo = ECORE_CPU_TO_LE32((cid & ECORE_SWCID_MASK) | (type << ECORE_SWCID_SHIFT)); hdr->rule_cnt = (uint8_t) rule_cnt; } /* hw_config() callbacks */ static void ecore_set_one_mac_e2(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, struct ecore_exeq_elem *elem, int rule_idx, __rte_unused int cam_offset) { struct ecore_raw_obj *raw = &o->raw; struct eth_classify_rules_ramrod_data *data = (struct eth_classify_rules_ramrod_data *)(raw->rdata); int rule_cnt = rule_idx + 1, cmd = elem->cmd_data.vlan_mac.cmd; union eth_classify_rule_cmd *rule_entry = &data->rules[rule_idx]; int add = (cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE; unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags; uint8_t *mac = elem->cmd_data.vlan_mac.u.mac.mac; /* Set LLH CAM entry: currently only iSCSI and ETH macs are * relevant. In addition, current implementation is tuned for a * single ETH MAC. * * When multiple unicast ETH MACs PF configuration in switch * independent mode is required (NetQ, multiple netdev MACs, * etc.), consider better utilisation of 8 per function MAC * entries in the LLH register. There is also * NIG_REG_P[01]_LLH_FUNC_MEM2 registers that complete the * total number of CAM entries to 16. * * Currently we won't configure NIG for MACs other than a primary ETH * MAC and iSCSI L2 MAC. * * If this MAC is moving from one Queue to another, no need to change * NIG configuration. */ if (cmd != ECORE_VLAN_MAC_MOVE) { if (ECORE_TEST_BIT(ECORE_ISCSI_ETH_MAC, vlan_mac_flags)) ecore_set_mac_in_nig(sc, add, mac, ECORE_LLH_CAM_ISCSI_ETH_LINE); else if (ECORE_TEST_BIT(ECORE_ETH_MAC, vlan_mac_flags)) ecore_set_mac_in_nig(sc, add, mac, ECORE_LLH_CAM_ETH_LINE); } /* Reset the ramrod data buffer for the first rule */ if (rule_idx == 0) ECORE_MEMSET(data, 0, sizeof(*data)); /* Setup a command header */ ecore_vlan_mac_set_cmd_hdr_e2(o, add, CLASSIFY_RULE_OPCODE_MAC, &rule_entry->mac.header); ECORE_MSG("About to %s MAC %02x:%02x:%02x:%02x:%02x:%02x for Queue %d", (add ? "add" : "delete"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], raw->cl_id); /* Set a MAC itself */ ecore_set_fw_mac_addr(&rule_entry->mac.mac_msb, &rule_entry->mac.mac_mid, &rule_entry->mac.mac_lsb, mac); rule_entry->mac.inner_mac = elem->cmd_data.vlan_mac.u.mac.is_inner_mac; /* MOVE: Add a rule that will add this MAC to the target Queue */ if (cmd == ECORE_VLAN_MAC_MOVE) { rule_entry++; rule_cnt++; /* Setup ramrod data */ ecore_vlan_mac_set_cmd_hdr_e2(elem->cmd_data. vlan_mac.target_obj, TRUE, CLASSIFY_RULE_OPCODE_MAC, &rule_entry->mac.header); /* Set a MAC itself */ ecore_set_fw_mac_addr(&rule_entry->mac.mac_msb, &rule_entry->mac.mac_mid, &rule_entry->mac.mac_lsb, mac); rule_entry->mac.inner_mac = elem->cmd_data.vlan_mac.u.mac.is_inner_mac; } /* Set the ramrod data header */ ecore_vlan_mac_set_rdata_hdr_e2(raw->cid, raw->state, &data->header, rule_cnt); } /** * ecore_vlan_mac_set_rdata_hdr_e1x - set a header in a single classify ramrod * * @sc: device handle * @o: queue * @type: * @cam_offset: offset in cam memory * @hdr: pointer to a header to setup * * E1H */ static void ecore_vlan_mac_set_rdata_hdr_e1x(struct ecore_vlan_mac_obj *o, int type, int cam_offset, struct mac_configuration_hdr *hdr) { struct ecore_raw_obj *r = &o->raw; hdr->length = 1; hdr->offset = (uint8_t) cam_offset; hdr->client_id = ECORE_CPU_TO_LE16(0xff); hdr->echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) | (type << ECORE_SWCID_SHIFT)); } static void ecore_vlan_mac_set_cfg_entry_e1x(struct ecore_vlan_mac_obj *o, int add, int opcode, uint8_t * mac, uint16_t vlan_id, struct mac_configuration_entry *cfg_entry) { struct ecore_raw_obj *r = &o->raw; uint32_t cl_bit_vec = (1 << r->cl_id); cfg_entry->clients_bit_vector = ECORE_CPU_TO_LE32(cl_bit_vec); cfg_entry->pf_id = r->func_id; cfg_entry->vlan_id = ECORE_CPU_TO_LE16(vlan_id); if (add) { ECORE_SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE, T_ETH_MAC_COMMAND_SET); ECORE_SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_VLAN_FILTERING_MODE, opcode); /* Set a MAC in a ramrod data */ ecore_set_fw_mac_addr(&cfg_entry->msb_mac_addr, &cfg_entry->middle_mac_addr, &cfg_entry->lsb_mac_addr, mac); } else ECORE_SET_FLAG(cfg_entry->flags, MAC_CONFIGURATION_ENTRY_ACTION_TYPE, T_ETH_MAC_COMMAND_INVALIDATE); } static void ecore_vlan_mac_set_rdata_e1x(struct bnx2x_softc *sc __rte_unused, struct ecore_vlan_mac_obj *o, int type, int cam_offset, int add, uint8_t * mac, uint16_t vlan_id, int opcode, struct mac_configuration_cmd *config) { struct mac_configuration_entry *cfg_entry = &config->config_table[0]; ecore_vlan_mac_set_rdata_hdr_e1x(o, type, cam_offset, &config->hdr); ecore_vlan_mac_set_cfg_entry_e1x(o, add, opcode, mac, vlan_id, cfg_entry); ECORE_MSG("%s MAC %02x:%02x:%02x:%02x:%02x:%02x CLID %d CAM offset %d", (add ? "setting" : "clearing"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], o->raw.cl_id, cam_offset); } /** * ecore_set_one_mac_e1x - fill a single MAC rule ramrod data * * @sc: device handle * @o: ecore_vlan_mac_obj * @elem: ecore_exeq_elem * @rule_idx: rule_idx * @cam_offset: cam_offset */ static void ecore_set_one_mac_e1x(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, struct ecore_exeq_elem *elem, __rte_unused int rule_idx, int cam_offset) { struct ecore_raw_obj *raw = &o->raw; struct mac_configuration_cmd *config = (struct mac_configuration_cmd *)(raw->rdata); /* 57711 do not support MOVE command, * so it's either ADD or DEL */ int add = (elem->cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) ? TRUE : FALSE; /* Reset the ramrod data buffer */ ECORE_MEMSET(config, 0, sizeof(*config)); ecore_vlan_mac_set_rdata_e1x(sc, o, raw->state, cam_offset, add, elem->cmd_data.vlan_mac.u.mac.mac, 0, ETH_VLAN_FILTER_ANY_VLAN, config); } /** * ecore_vlan_mac_restore - reconfigure next MAC/VLAN/VLAN-MAC element * * @sc: device handle * @p: command parameters * @ppos: pointer to the cookie * * reconfigure next MAC/VLAN/VLAN-MAC element from the * previously configured elements list. * * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is taken * into an account * * pointer to the cookie - that should be given back in the next call to make * function handle the next element. If *ppos is set to NULL it will restart the * iterator. If returned *ppos == NULL this means that the last element has been * handled. * */ static int ecore_vlan_mac_restore(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p, struct ecore_vlan_mac_registry_elem **ppos) { struct ecore_vlan_mac_registry_elem *pos; struct ecore_vlan_mac_obj *o = p->vlan_mac_obj; /* If list is empty - there is nothing to do here */ if (ECORE_LIST_IS_EMPTY(&o->head)) { *ppos = NULL; return 0; } /* make a step... */ if (*ppos == NULL) *ppos = ECORE_LIST_FIRST_ENTRY(&o->head, struct ecore_vlan_mac_registry_elem, link); else *ppos = ECORE_LIST_NEXT(*ppos, link, struct ecore_vlan_mac_registry_elem); pos = *ppos; /* If it's the last step - return NULL */ if (ECORE_LIST_IS_LAST(&pos->link, &o->head)) *ppos = NULL; /* Prepare a 'user_req' */ ECORE_MEMCPY(&p->user_req.u, &pos->u, sizeof(pos->u)); /* Set the command */ p->user_req.cmd = ECORE_VLAN_MAC_ADD; /* Set vlan_mac_flags */ p->user_req.vlan_mac_flags = pos->vlan_mac_flags; /* Set a restore bit */ ECORE_SET_BIT_NA(RAMROD_RESTORE, &p->ramrod_flags); return ecore_config_vlan_mac(sc, p); } /* ecore_exeq_get_mac/ecore_exeq_get_vlan/ecore_exeq_get_vlan_mac return a * pointer to an element with a specific criteria and NULL if such an element * hasn't been found. */ static struct ecore_exeq_elem *ecore_exeq_get_mac(struct ecore_exe_queue_obj *o, struct ecore_exeq_elem *elem) { struct ecore_exeq_elem *pos; struct ecore_mac_ramrod_data *data = &elem->cmd_data.vlan_mac.u.mac; /* Check pending for execution commands */ ECORE_LIST_FOR_EACH_ENTRY(pos, &o->exe_queue, link, struct ecore_exeq_elem) if (!ECORE_MEMCMP(&pos->cmd_data.vlan_mac.u.mac, data, sizeof(*data)) && (pos->cmd_data.vlan_mac.cmd == elem->cmd_data.vlan_mac.cmd)) return pos; return NULL; } /** * ecore_validate_vlan_mac_add - check if an ADD command can be executed * * @sc: device handle * @qo: ecore_qable_obj * @elem: ecore_exeq_elem * * Checks that the requested configuration can be added. If yes and if * requested, consume CAM credit. * * The 'validate' is run after the 'optimize'. * */ static int ecore_validate_vlan_mac_add(struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { struct ecore_vlan_mac_obj *o = &qo->vlan_mac; struct ecore_exe_queue_obj *exeq = &o->exe_queue; int rc; /* Check the registry */ rc = o->check_add(sc, o, &elem->cmd_data.vlan_mac.u); if (rc) { ECORE_MSG ("ADD command is not allowed considering current registry state."); return rc; } /* Check if there is a pending ADD command for this * MAC/VLAN/VLAN-MAC. Return an error if there is. */ if (exeq->get(exeq, elem)) { ECORE_MSG("There is a pending ADD command already"); return ECORE_EXISTS; } /* Consume the credit if not requested not to */ if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT, &elem->cmd_data.vlan_mac.vlan_mac_flags) || o->get_credit(o))) return ECORE_INVAL; return ECORE_SUCCESS; } /** * ecore_validate_vlan_mac_del - check if the DEL command can be executed * * @sc: device handle * @qo: quable object to check * @elem: element that needs to be deleted * * Checks that the requested configuration can be deleted. If yes and if * requested, returns a CAM credit. * * The 'validate' is run after the 'optimize'. */ static int ecore_validate_vlan_mac_del(struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { struct ecore_vlan_mac_obj *o = &qo->vlan_mac; struct ecore_vlan_mac_registry_elem *pos; struct ecore_exe_queue_obj *exeq = &o->exe_queue; struct ecore_exeq_elem query_elem; /* If this classification can not be deleted (doesn't exist) * - return a ECORE_EXIST. */ pos = o->check_del(sc, o, &elem->cmd_data.vlan_mac.u); if (!pos) { ECORE_MSG ("DEL command is not allowed considering current registry state"); return ECORE_EXISTS; } /* Check if there are pending DEL or MOVE commands for this * MAC/VLAN/VLAN-MAC. Return an error if so. */ ECORE_MEMCPY(&query_elem, elem, sizeof(query_elem)); /* Check for MOVE commands */ query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_MOVE; if (exeq->get(exeq, &query_elem)) { PMD_DRV_LOG(ERR, "There is a pending MOVE command already"); return ECORE_INVAL; } /* Check for DEL commands */ if (exeq->get(exeq, elem)) { ECORE_MSG("There is a pending DEL command already"); return ECORE_EXISTS; } /* Return the credit to the credit pool if not requested not to */ if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT, &elem->cmd_data.vlan_mac.vlan_mac_flags) || o->put_credit(o))) { PMD_DRV_LOG(ERR, "Failed to return a credit"); return ECORE_INVAL; } return ECORE_SUCCESS; } /** * ecore_validate_vlan_mac_move - check if the MOVE command can be executed * * @sc: device handle * @qo: quable object to check (source) * @elem: element that needs to be moved * * Checks that the requested configuration can be moved. If yes and if * requested, returns a CAM credit. * * The 'validate' is run after the 'optimize'. */ static int ecore_validate_vlan_mac_move(struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { struct ecore_vlan_mac_obj *src_o = &qo->vlan_mac; struct ecore_vlan_mac_obj *dest_o = elem->cmd_data.vlan_mac.target_obj; struct ecore_exeq_elem query_elem; struct ecore_exe_queue_obj *src_exeq = &src_o->exe_queue; struct ecore_exe_queue_obj *dest_exeq = &dest_o->exe_queue; /* Check if we can perform this operation based on the current registry * state. */ if (!src_o->check_move(sc, src_o, dest_o, &elem->cmd_data.vlan_mac.u)) { ECORE_MSG ("MOVE command is not allowed considering current registry state"); return ECORE_INVAL; } /* Check if there is an already pending DEL or MOVE command for the * source object or ADD command for a destination object. Return an * error if so. */ ECORE_MEMCPY(&query_elem, elem, sizeof(query_elem)); /* Check DEL on source */ query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_DEL; if (src_exeq->get(src_exeq, &query_elem)) { PMD_DRV_LOG(ERR, "There is a pending DEL command on the source queue already"); return ECORE_INVAL; } /* Check MOVE on source */ if (src_exeq->get(src_exeq, elem)) { ECORE_MSG("There is a pending MOVE command already"); return ECORE_EXISTS; } /* Check ADD on destination */ query_elem.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_ADD; if (dest_exeq->get(dest_exeq, &query_elem)) { PMD_DRV_LOG(ERR, "There is a pending ADD command on the destination queue already"); return ECORE_INVAL; } /* Consume the credit if not requested not to */ if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT_DEST, &elem->cmd_data.vlan_mac.vlan_mac_flags) || dest_o->get_credit(dest_o))) return ECORE_INVAL; if (!(ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT, &elem->cmd_data.vlan_mac.vlan_mac_flags) || src_o->put_credit(src_o))) { /* return the credit taken from dest... */ dest_o->put_credit(dest_o); return ECORE_INVAL; } return ECORE_SUCCESS; } static int ecore_validate_vlan_mac(struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { switch (elem->cmd_data.vlan_mac.cmd) { case ECORE_VLAN_MAC_ADD: return ecore_validate_vlan_mac_add(sc, qo, elem); case ECORE_VLAN_MAC_DEL: return ecore_validate_vlan_mac_del(sc, qo, elem); case ECORE_VLAN_MAC_MOVE: return ecore_validate_vlan_mac_move(sc, qo, elem); default: return ECORE_INVAL; } } static int ecore_remove_vlan_mac(__rte_unused struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { int rc = 0; /* If consumption wasn't required, nothing to do */ if (ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT, &elem->cmd_data.vlan_mac.vlan_mac_flags)) return ECORE_SUCCESS; switch (elem->cmd_data.vlan_mac.cmd) { case ECORE_VLAN_MAC_ADD: case ECORE_VLAN_MAC_MOVE: rc = qo->vlan_mac.put_credit(&qo->vlan_mac); break; case ECORE_VLAN_MAC_DEL: rc = qo->vlan_mac.get_credit(&qo->vlan_mac); break; default: return ECORE_INVAL; } if (rc != TRUE) return ECORE_INVAL; return ECORE_SUCCESS; } /** * ecore_wait_vlan_mac - passively wait for 5 seconds until all work completes. * * @sc: device handle * @o: ecore_vlan_mac_obj * */ static int ecore_wait_vlan_mac(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o) { int cnt = 5000, rc; struct ecore_exe_queue_obj *exeq = &o->exe_queue; struct ecore_raw_obj *raw = &o->raw; while (cnt--) { /* Wait for the current command to complete */ rc = raw->wait_comp(sc, raw); if (rc) return rc; /* Wait until there are no pending commands */ if (!ecore_exe_queue_empty(exeq)) ECORE_WAIT(sc, 1000); else return ECORE_SUCCESS; } return ECORE_TIMEOUT; } static int __ecore_vlan_mac_execute_step(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, unsigned long *ramrod_flags) { int rc = ECORE_SUCCESS; ECORE_SPIN_LOCK_BH(&o->exe_queue.lock); ECORE_MSG("vlan_mac_execute_step - trying to take writer lock"); rc = __ecore_vlan_mac_h_write_trylock(sc, o); if (rc != ECORE_SUCCESS) { __ecore_vlan_mac_h_pend(sc, o, *ramrod_flags); /** Calling function should not diffrentiate between this case * and the case in which there is already a pending ramrod */ rc = ECORE_PENDING; } else { rc = ecore_exe_queue_step(sc, &o->exe_queue, ramrod_flags); } ECORE_SPIN_UNLOCK_BH(&o->exe_queue.lock); return rc; } /** * ecore_complete_vlan_mac - complete one VLAN-MAC ramrod * * @sc: device handle * @o: ecore_vlan_mac_obj * @cqe: * @cont: if TRUE schedule next execution chunk * */ static int ecore_complete_vlan_mac(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, union event_ring_elem *cqe, unsigned long *ramrod_flags) { struct ecore_raw_obj *r = &o->raw; int rc; /* Reset pending list */ ecore_exe_queue_reset_pending(sc, &o->exe_queue); /* Clear pending */ r->clear_pending(r); /* If ramrod failed this is most likely a SW bug */ if (cqe->message.error) return ECORE_INVAL; /* Run the next bulk of pending commands if requested */ if (ECORE_TEST_BIT(RAMROD_CONT, ramrod_flags)) { rc = __ecore_vlan_mac_execute_step(sc, o, ramrod_flags); if (rc < 0) return rc; } /* If there is more work to do return PENDING */ if (!ecore_exe_queue_empty(&o->exe_queue)) return ECORE_PENDING; return ECORE_SUCCESS; } /** * ecore_optimize_vlan_mac - optimize ADD and DEL commands. * * @sc: device handle * @o: ecore_qable_obj * @elem: ecore_exeq_elem */ static int ecore_optimize_vlan_mac(struct bnx2x_softc *sc, union ecore_qable_obj *qo, struct ecore_exeq_elem *elem) { struct ecore_exeq_elem query, *pos; struct ecore_vlan_mac_obj *o = &qo->vlan_mac; struct ecore_exe_queue_obj *exeq = &o->exe_queue; ECORE_MEMCPY(&query, elem, sizeof(query)); switch (elem->cmd_data.vlan_mac.cmd) { case ECORE_VLAN_MAC_ADD: query.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_DEL; break; case ECORE_VLAN_MAC_DEL: query.cmd_data.vlan_mac.cmd = ECORE_VLAN_MAC_ADD; break; default: /* Don't handle anything other than ADD or DEL */ return 0; } /* If we found the appropriate element - delete it */ pos = exeq->get(exeq, &query); if (pos) { /* Return the credit of the optimized command */ if (!ECORE_TEST_BIT(ECORE_DONT_CONSUME_CAM_CREDIT, &pos->cmd_data.vlan_mac.vlan_mac_flags)) { if ((query.cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) && !o->put_credit(o)) { PMD_DRV_LOG(ERR, "Failed to return the credit for the optimized ADD command"); return ECORE_INVAL; } else if (!o->get_credit(o)) { /* VLAN_MAC_DEL */ PMD_DRV_LOG(ERR, "Failed to recover the credit from the optimized DEL command"); return ECORE_INVAL; } } ECORE_MSG("Optimizing %s command", (elem->cmd_data.vlan_mac.cmd == ECORE_VLAN_MAC_ADD) ? "ADD" : "DEL"); ECORE_LIST_REMOVE_ENTRY(&pos->link, &exeq->exe_queue); ecore_exe_queue_free_elem(sc, pos); return 1; } return 0; } /** * ecore_vlan_mac_get_registry_elem - prepare a registry element * * @sc: device handle * @o: * @elem: * @restore: * @re: * * prepare a registry element according to the current command request. */ static int ecore_vlan_mac_get_registry_elem(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, struct ecore_exeq_elem *elem, int restore, struct ecore_vlan_mac_registry_elem **re) { enum ecore_vlan_mac_cmd cmd = elem->cmd_data.vlan_mac.cmd; struct ecore_vlan_mac_registry_elem *reg_elem; /* Allocate a new registry element if needed. */ if (!restore && ((cmd == ECORE_VLAN_MAC_ADD) || (cmd == ECORE_VLAN_MAC_MOVE))) { reg_elem = ECORE_ZALLOC(sizeof(*reg_elem), GFP_ATOMIC, sc); if (!reg_elem) return ECORE_NOMEM; /* Get a new CAM offset */ if (!o->get_cam_offset(o, ®_elem->cam_offset)) { /* This shall never happen, because we have checked the * CAM availability in the 'validate'. */ ECORE_DBG_BREAK_IF(1); ECORE_FREE(sc, reg_elem, sizeof(*reg_elem)); return ECORE_INVAL; } ECORE_MSG("Got cam offset %d", reg_elem->cam_offset); /* Set a VLAN-MAC data */ ECORE_MEMCPY(®_elem->u, &elem->cmd_data.vlan_mac.u, sizeof(reg_elem->u)); /* Copy the flags (needed for DEL and RESTORE flows) */ reg_elem->vlan_mac_flags = elem->cmd_data.vlan_mac.vlan_mac_flags; } else /* DEL, RESTORE */ reg_elem = o->check_del(sc, o, &elem->cmd_data.vlan_mac.u); *re = reg_elem; return ECORE_SUCCESS; } /** * ecore_execute_vlan_mac - execute vlan mac command * * @sc: device handle * @qo: * @exe_chunk: * @ramrod_flags: * * go and send a ramrod! */ static int ecore_execute_vlan_mac(struct bnx2x_softc *sc, union ecore_qable_obj *qo, ecore_list_t * exe_chunk, unsigned long *ramrod_flags) { struct ecore_exeq_elem *elem; struct ecore_vlan_mac_obj *o = &qo->vlan_mac, *cam_obj; struct ecore_raw_obj *r = &o->raw; int rc, idx = 0; int restore = ECORE_TEST_BIT(RAMROD_RESTORE, ramrod_flags); int drv_only = ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags); struct ecore_vlan_mac_registry_elem *reg_elem; enum ecore_vlan_mac_cmd cmd; /* If DRIVER_ONLY execution is requested, cleanup a registry * and exit. Otherwise send a ramrod to FW. */ if (!drv_only) { /* Set pending */ r->set_pending(r); /* Fill the ramrod data */ ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link, struct ecore_exeq_elem) { cmd = elem->cmd_data.vlan_mac.cmd; /* We will add to the target object in MOVE command, so * change the object for a CAM search. */ if (cmd == ECORE_VLAN_MAC_MOVE) cam_obj = elem->cmd_data.vlan_mac.target_obj; else cam_obj = o; rc = ecore_vlan_mac_get_registry_elem(sc, cam_obj, elem, restore, ®_elem); if (rc) goto error_exit; ECORE_DBG_BREAK_IF(!reg_elem); /* Push a new entry into the registry */ if (!restore && ((cmd == ECORE_VLAN_MAC_ADD) || (cmd == ECORE_VLAN_MAC_MOVE))) ECORE_LIST_PUSH_HEAD(®_elem->link, &cam_obj->head); /* Configure a single command in a ramrod data buffer */ o->set_one_rule(sc, o, elem, idx, reg_elem->cam_offset); /* MOVE command consumes 2 entries in the ramrod data */ if (cmd == ECORE_VLAN_MAC_MOVE) idx += 2; else idx++; } /* * No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ rc = ecore_sp_post(sc, o->ramrod_cmd, r->cid, r->rdata_mapping, ETH_CONNECTION_TYPE); if (rc) goto error_exit; } /* Now, when we are done with the ramrod - clean up the registry */ ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link, struct ecore_exeq_elem) { cmd = elem->cmd_data.vlan_mac.cmd; if ((cmd == ECORE_VLAN_MAC_DEL) || (cmd == ECORE_VLAN_MAC_MOVE)) { reg_elem = o->check_del(sc, o, &elem->cmd_data.vlan_mac.u); ECORE_DBG_BREAK_IF(!reg_elem); o->put_cam_offset(o, reg_elem->cam_offset); ECORE_LIST_REMOVE_ENTRY(®_elem->link, &o->head); ECORE_FREE(sc, reg_elem, sizeof(*reg_elem)); } } if (!drv_only) return ECORE_PENDING; else return ECORE_SUCCESS; error_exit: r->clear_pending(r); /* Cleanup a registry in case of a failure */ ECORE_LIST_FOR_EACH_ENTRY(elem, exe_chunk, link, struct ecore_exeq_elem) { cmd = elem->cmd_data.vlan_mac.cmd; if (cmd == ECORE_VLAN_MAC_MOVE) cam_obj = elem->cmd_data.vlan_mac.target_obj; else cam_obj = o; /* Delete all newly added above entries */ if (!restore && ((cmd == ECORE_VLAN_MAC_ADD) || (cmd == ECORE_VLAN_MAC_MOVE))) { reg_elem = o->check_del(sc, cam_obj, &elem->cmd_data.vlan_mac.u); if (reg_elem) { ECORE_LIST_REMOVE_ENTRY(®_elem->link, &cam_obj->head); ECORE_FREE(sc, reg_elem, sizeof(*reg_elem)); } } } return rc; } static int ecore_vlan_mac_push_new_cmd(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p) { struct ecore_exeq_elem *elem; struct ecore_vlan_mac_obj *o = p->vlan_mac_obj; int restore = ECORE_TEST_BIT(RAMROD_RESTORE, &p->ramrod_flags); /* Allocate the execution queue element */ elem = ecore_exe_queue_alloc_elem(sc); if (!elem) return ECORE_NOMEM; /* Set the command 'length' */ switch (p->user_req.cmd) { case ECORE_VLAN_MAC_MOVE: elem->cmd_len = 2; break; default: elem->cmd_len = 1; } /* Fill the object specific info */ ECORE_MEMCPY(&elem->cmd_data.vlan_mac, &p->user_req, sizeof(p->user_req)); /* Try to add a new command to the pending list */ return ecore_exe_queue_add(sc, &o->exe_queue, elem, restore); } /** * ecore_config_vlan_mac - configure VLAN/MAC/VLAN_MAC filtering rules. * * @sc: device handle * @p: * */ int ecore_config_vlan_mac(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p) { int rc = ECORE_SUCCESS; struct ecore_vlan_mac_obj *o = p->vlan_mac_obj; unsigned long *ramrod_flags = &p->ramrod_flags; int cont = ECORE_TEST_BIT(RAMROD_CONT, ramrod_flags); struct ecore_raw_obj *raw = &o->raw; /* * Add new elements to the execution list for commands that require it. */ if (!cont) { rc = ecore_vlan_mac_push_new_cmd(sc, p); if (rc) return rc; } /* If nothing will be executed further in this iteration we want to * return PENDING if there are pending commands */ if (!ecore_exe_queue_empty(&o->exe_queue)) rc = ECORE_PENDING; if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ramrod_flags)) { ECORE_MSG ("RAMROD_DRV_CLR_ONLY requested: clearing a pending bit."); raw->clear_pending(raw); } /* Execute commands if required */ if (cont || ECORE_TEST_BIT(RAMROD_EXEC, ramrod_flags) || ECORE_TEST_BIT(RAMROD_COMP_WAIT, ramrod_flags)) { rc = __ecore_vlan_mac_execute_step(sc, p->vlan_mac_obj, &p->ramrod_flags); if (rc < 0) return rc; } /* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set * then user want to wait until the last command is done. */ if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) { /* Wait maximum for the current exe_queue length iterations plus * one (for the current pending command). */ int max_iterations = ecore_exe_queue_length(&o->exe_queue) + 1; while (!ecore_exe_queue_empty(&o->exe_queue) && max_iterations--) { /* Wait for the current command to complete */ rc = raw->wait_comp(sc, raw); if (rc) return rc; /* Make a next step */ rc = __ecore_vlan_mac_execute_step(sc, p->vlan_mac_obj, &p->ramrod_flags); if (rc < 0) return rc; } return ECORE_SUCCESS; } return rc; } /** * ecore_vlan_mac_del_all - delete elements with given vlan_mac_flags spec * * @sc: device handle * @o: * @vlan_mac_flags: * @ramrod_flags: execution flags to be used for this deletion * * if the last operation has completed successfully and there are no * more elements left, positive value if the last operation has completed * successfully and there are more previously configured elements, negative * value is current operation has failed. */ static int ecore_vlan_mac_del_all(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, unsigned long *vlan_mac_flags, unsigned long *ramrod_flags) { struct ecore_vlan_mac_registry_elem *pos = NULL; int rc = 0, read_lock; struct ecore_vlan_mac_ramrod_params p; struct ecore_exe_queue_obj *exeq = &o->exe_queue; struct ecore_exeq_elem *exeq_pos, *exeq_pos_n; /* Clear pending commands first */ ECORE_SPIN_LOCK_BH(&exeq->lock); ECORE_LIST_FOR_EACH_ENTRY_SAFE(exeq_pos, exeq_pos_n, &exeq->exe_queue, link, struct ecore_exeq_elem) { if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags == *vlan_mac_flags) { rc = exeq->remove(sc, exeq->owner, exeq_pos); if (rc) { PMD_DRV_LOG(ERR, "Failed to remove command"); ECORE_SPIN_UNLOCK_BH(&exeq->lock); return rc; } ECORE_LIST_REMOVE_ENTRY(&exeq_pos->link, &exeq->exe_queue); ecore_exe_queue_free_elem(sc, exeq_pos); } } ECORE_SPIN_UNLOCK_BH(&exeq->lock); /* Prepare a command request */ ECORE_MEMSET(&p, 0, sizeof(p)); p.vlan_mac_obj = o; p.ramrod_flags = *ramrod_flags; p.user_req.cmd = ECORE_VLAN_MAC_DEL; /* Add all but the last VLAN-MAC to the execution queue without actually * execution anything. */ ECORE_CLEAR_BIT_NA(RAMROD_COMP_WAIT, &p.ramrod_flags); ECORE_CLEAR_BIT_NA(RAMROD_EXEC, &p.ramrod_flags); ECORE_CLEAR_BIT_NA(RAMROD_CONT, &p.ramrod_flags); ECORE_MSG("vlan_mac_del_all -- taking vlan_mac_lock (reader)"); read_lock = ecore_vlan_mac_h_read_lock(sc, o); if (read_lock != ECORE_SUCCESS) return read_lock; ECORE_LIST_FOR_EACH_ENTRY(pos, &o->head, link, struct ecore_vlan_mac_registry_elem) { if (pos->vlan_mac_flags == *vlan_mac_flags) { p.user_req.vlan_mac_flags = pos->vlan_mac_flags; ECORE_MEMCPY(&p.user_req.u, &pos->u, sizeof(pos->u)); rc = ecore_config_vlan_mac(sc, &p); if (rc < 0) { PMD_DRV_LOG(ERR, "Failed to add a new DEL command"); ecore_vlan_mac_h_read_unlock(sc, o); return rc; } } } ECORE_MSG("vlan_mac_del_all -- releasing vlan_mac_lock (reader)"); ecore_vlan_mac_h_read_unlock(sc, o); p.ramrod_flags = *ramrod_flags; ECORE_SET_BIT_NA(RAMROD_CONT, &p.ramrod_flags); return ecore_config_vlan_mac(sc, &p); } static void ecore_init_raw_obj(struct ecore_raw_obj *raw, uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type) { raw->func_id = func_id; raw->cid = cid; raw->cl_id = cl_id; raw->rdata = rdata; raw->rdata_mapping = rdata_mapping; raw->state = state; raw->pstate = pstate; raw->obj_type = type; raw->check_pending = ecore_raw_check_pending; raw->clear_pending = ecore_raw_clear_pending; raw->set_pending = ecore_raw_set_pending; raw->wait_comp = ecore_raw_wait; } static void ecore_init_vlan_mac_common(struct ecore_vlan_mac_obj *o, uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type, struct ecore_credit_pool_obj *macs_pool, struct ecore_credit_pool_obj *vlans_pool) { ECORE_LIST_INIT(&o->head); o->head_reader = 0; o->head_exe_request = FALSE; o->saved_ramrod_flags = 0; o->macs_pool = macs_pool; o->vlans_pool = vlans_pool; o->delete_all = ecore_vlan_mac_del_all; o->restore = ecore_vlan_mac_restore; o->complete = ecore_complete_vlan_mac; o->wait = ecore_wait_vlan_mac; ecore_init_raw_obj(&o->raw, cl_id, cid, func_id, rdata, rdata_mapping, state, pstate, type); } void ecore_init_mac_obj(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *mac_obj, uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type, struct ecore_credit_pool_obj *macs_pool) { union ecore_qable_obj *qable_obj = (union ecore_qable_obj *)mac_obj; ecore_init_vlan_mac_common(mac_obj, cl_id, cid, func_id, rdata, rdata_mapping, state, pstate, type, macs_pool, NULL); /* CAM credit pool handling */ mac_obj->get_credit = ecore_get_credit_mac; mac_obj->put_credit = ecore_put_credit_mac; mac_obj->get_cam_offset = ecore_get_cam_offset_mac; mac_obj->put_cam_offset = ecore_put_cam_offset_mac; if (CHIP_IS_E1x(sc)) { mac_obj->set_one_rule = ecore_set_one_mac_e1x; mac_obj->check_del = ecore_check_mac_del; mac_obj->check_add = ecore_check_mac_add; mac_obj->check_move = ecore_check_move_always_err; mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_SET_MAC; /* Exe Queue */ ecore_exe_queue_init(sc, &mac_obj->exe_queue, 1, qable_obj, ecore_validate_vlan_mac, ecore_remove_vlan_mac, ecore_optimize_vlan_mac, ecore_execute_vlan_mac, ecore_exeq_get_mac); } else { mac_obj->set_one_rule = ecore_set_one_mac_e2; mac_obj->check_del = ecore_check_mac_del; mac_obj->check_add = ecore_check_mac_add; mac_obj->check_move = ecore_check_move; mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; mac_obj->get_n_elements = ecore_get_n_elements; /* Exe Queue */ ecore_exe_queue_init(sc, &mac_obj->exe_queue, CLASSIFY_RULES_COUNT, qable_obj, ecore_validate_vlan_mac, ecore_remove_vlan_mac, ecore_optimize_vlan_mac, ecore_execute_vlan_mac, ecore_exeq_get_mac); } } /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */ static void __storm_memset_mac_filters(struct bnx2x_softc *sc, struct tstorm_eth_mac_filter_config *mac_filters, uint16_t pf_id) { size_t size = sizeof(struct tstorm_eth_mac_filter_config); uint32_t addr = BAR_TSTRORM_INTMEM + TSTORM_MAC_FILTER_CONFIG_OFFSET(pf_id); ecore_storm_memset_struct(sc, addr, size, (uint32_t *) mac_filters); } static int ecore_set_rx_mode_e1x(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p) { /* update the sc MAC filter structure */ uint32_t mask = (1 << p->cl_id); struct tstorm_eth_mac_filter_config *mac_filters = (struct tstorm_eth_mac_filter_config *)p->rdata; /* initial setting is drop-all */ uint8_t drop_all_ucast = 1, drop_all_mcast = 1; uint8_t accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0; uint8_t unmatched_unicast = 0; /* In e1x there we only take into account rx accept flag since tx switching * isn't enabled. */ if (ECORE_TEST_BIT(ECORE_ACCEPT_UNICAST, &p->rx_accept_flags)) /* accept matched ucast */ drop_all_ucast = 0; if (ECORE_TEST_BIT(ECORE_ACCEPT_MULTICAST, &p->rx_accept_flags)) /* accept matched mcast */ drop_all_mcast = 0; if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_UNICAST, &p->rx_accept_flags)) { /* accept all mcast */ drop_all_ucast = 0; accp_all_ucast = 1; } if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_MULTICAST, &p->rx_accept_flags)) { /* accept all mcast */ drop_all_mcast = 0; accp_all_mcast = 1; } if (ECORE_TEST_BIT(ECORE_ACCEPT_BROADCAST, &p->rx_accept_flags)) /* accept (all) bcast */ accp_all_bcast = 1; if (ECORE_TEST_BIT(ECORE_ACCEPT_UNMATCHED, &p->rx_accept_flags)) /* accept unmatched unicasts */ unmatched_unicast = 1; mac_filters->ucast_drop_all = drop_all_ucast ? mac_filters->ucast_drop_all | mask : mac_filters->ucast_drop_all & ~mask; mac_filters->mcast_drop_all = drop_all_mcast ? mac_filters->mcast_drop_all | mask : mac_filters->mcast_drop_all & ~mask; mac_filters->ucast_accept_all = accp_all_ucast ? mac_filters->ucast_accept_all | mask : mac_filters->ucast_accept_all & ~mask; mac_filters->mcast_accept_all = accp_all_mcast ? mac_filters->mcast_accept_all | mask : mac_filters->mcast_accept_all & ~mask; mac_filters->bcast_accept_all = accp_all_bcast ? mac_filters->bcast_accept_all | mask : mac_filters->bcast_accept_all & ~mask; mac_filters->unmatched_unicast = unmatched_unicast ? mac_filters->unmatched_unicast | mask : mac_filters->unmatched_unicast & ~mask; ECORE_MSG("drop_ucast 0x%xdrop_mcast 0x%x accp_ucast 0x%x" "accp_mcast 0x%xaccp_bcast 0x%x", mac_filters->ucast_drop_all, mac_filters->mcast_drop_all, mac_filters->ucast_accept_all, mac_filters->mcast_accept_all, mac_filters->bcast_accept_all); /* write the MAC filter structure */ __storm_memset_mac_filters(sc, mac_filters, p->func_id); /* The operation is completed */ ECORE_CLEAR_BIT(p->state, p->pstate); ECORE_SMP_MB_AFTER_CLEAR_BIT(); return ECORE_SUCCESS; } /* Setup ramrod data */ static void ecore_rx_mode_set_rdata_hdr_e2(uint32_t cid, struct eth_classify_header *hdr, uint8_t rule_cnt) { hdr->echo = ECORE_CPU_TO_LE32(cid); hdr->rule_cnt = rule_cnt; } static void ecore_rx_mode_set_cmd_state_e2(unsigned long *accept_flags, struct eth_filter_rules_cmd *cmd, int clear_accept_all) { uint16_t state; /* start with 'drop-all' */ state = ETH_FILTER_RULES_CMD_UCAST_DROP_ALL | ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; if (ECORE_TEST_BIT(ECORE_ACCEPT_UNICAST, accept_flags)) state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; if (ECORE_TEST_BIT(ECORE_ACCEPT_MULTICAST, accept_flags)) state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_UNICAST, accept_flags)) { state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL; } if (ECORE_TEST_BIT(ECORE_ACCEPT_ALL_MULTICAST, accept_flags)) { state |= ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL; state &= ~ETH_FILTER_RULES_CMD_MCAST_DROP_ALL; } if (ECORE_TEST_BIT(ECORE_ACCEPT_BROADCAST, accept_flags)) state |= ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL; if (ECORE_TEST_BIT(ECORE_ACCEPT_UNMATCHED, accept_flags)) { state &= ~ETH_FILTER_RULES_CMD_UCAST_DROP_ALL; state |= ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED; } if (ECORE_TEST_BIT(ECORE_ACCEPT_ANY_VLAN, accept_flags)) state |= ETH_FILTER_RULES_CMD_ACCEPT_ANY_VLAN; /* Clear ACCEPT_ALL_XXX flags for FCoE L2 Queue */ if (clear_accept_all) { state &= ~ETH_FILTER_RULES_CMD_MCAST_ACCEPT_ALL; state &= ~ETH_FILTER_RULES_CMD_BCAST_ACCEPT_ALL; state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_ALL; state &= ~ETH_FILTER_RULES_CMD_UCAST_ACCEPT_UNMATCHED; } cmd->state = ECORE_CPU_TO_LE16(state); } static int ecore_set_rx_mode_e2(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p) { struct eth_filter_rules_ramrod_data *data = p->rdata; int rc; uint8_t rule_idx = 0; /* Reset the ramrod data buffer */ ECORE_MEMSET(data, 0, sizeof(*data)); /* Setup ramrod data */ /* Tx (internal switching) */ if (ECORE_TEST_BIT(RAMROD_TX, &p->ramrod_flags)) { data->rules[rule_idx].client_id = p->cl_id; data->rules[rule_idx].func_id = p->func_id; data->rules[rule_idx].cmd_general_data = ETH_FILTER_RULES_CMD_TX_CMD; ecore_rx_mode_set_cmd_state_e2(&p->tx_accept_flags, &(data->rules[rule_idx++]), FALSE); } /* Rx */ if (ECORE_TEST_BIT(RAMROD_RX, &p->ramrod_flags)) { data->rules[rule_idx].client_id = p->cl_id; data->rules[rule_idx].func_id = p->func_id; data->rules[rule_idx].cmd_general_data = ETH_FILTER_RULES_CMD_RX_CMD; ecore_rx_mode_set_cmd_state_e2(&p->rx_accept_flags, &(data->rules[rule_idx++]), FALSE); } /* If FCoE Queue configuration has been requested configure the Rx and * internal switching modes for this queue in separate rules. * * FCoE queue shell never be set to ACCEPT_ALL packets of any sort: * MCAST_ALL, UCAST_ALL, BCAST_ALL and UNMATCHED. */ if (ECORE_TEST_BIT(ECORE_RX_MODE_FCOE_ETH, &p->rx_mode_flags)) { /* Tx (internal switching) */ if (ECORE_TEST_BIT(RAMROD_TX, &p->ramrod_flags)) { data->rules[rule_idx].client_id = ECORE_FCOE_CID(sc); data->rules[rule_idx].func_id = p->func_id; data->rules[rule_idx].cmd_general_data = ETH_FILTER_RULES_CMD_TX_CMD; ecore_rx_mode_set_cmd_state_e2(&p->tx_accept_flags, &(data->rules [rule_idx++]), TRUE); } /* Rx */ if (ECORE_TEST_BIT(RAMROD_RX, &p->ramrod_flags)) { data->rules[rule_idx].client_id = ECORE_FCOE_CID(sc); data->rules[rule_idx].func_id = p->func_id; data->rules[rule_idx].cmd_general_data = ETH_FILTER_RULES_CMD_RX_CMD; ecore_rx_mode_set_cmd_state_e2(&p->rx_accept_flags, &(data->rules [rule_idx++]), TRUE); } } /* Set the ramrod header (most importantly - number of rules to * configure). */ ecore_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx); ECORE_MSG ("About to configure %d rules, rx_accept_flags 0x%lx, tx_accept_flags 0x%lx", data->header.rule_cnt, p->rx_accept_flags, p->tx_accept_flags); /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ /* Send a ramrod */ rc = ecore_sp_post(sc, RAMROD_CMD_ID_ETH_FILTER_RULES, p->cid, p->rdata_mapping, ETH_CONNECTION_TYPE); if (rc) return rc; /* Ramrod completion is pending */ return ECORE_PENDING; } static int ecore_wait_rx_mode_comp_e2(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p) { return ecore_state_wait(sc, p->state, p->pstate); } static int ecore_empty_rx_mode_wait(__rte_unused struct bnx2x_softc *sc, __rte_unused struct ecore_rx_mode_ramrod_params *p) { /* Do nothing */ return ECORE_SUCCESS; } int ecore_config_rx_mode(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p) { int rc; /* Configure the new classification in the chip */ if (p->rx_mode_obj->config_rx_mode) { rc = p->rx_mode_obj->config_rx_mode(sc, p); if (rc < 0) return rc; /* Wait for a ramrod completion if was requested */ if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) { rc = p->rx_mode_obj->wait_comp(sc, p); if (rc) return rc; } } else { ECORE_MSG("ERROR: config_rx_mode is NULL"); return -1; } return rc; } void ecore_init_rx_mode_obj(struct bnx2x_softc *sc, struct ecore_rx_mode_obj *o) { if (CHIP_IS_E1x(sc)) { o->wait_comp = ecore_empty_rx_mode_wait; o->config_rx_mode = ecore_set_rx_mode_e1x; } else { o->wait_comp = ecore_wait_rx_mode_comp_e2; o->config_rx_mode = ecore_set_rx_mode_e2; } } /********************* Multicast verbs: SET, CLEAR ****************************/ static uint8_t ecore_mcast_bin_from_mac(uint8_t * mac) { return (ECORE_CRC32_LE(0, mac, ETH_ALEN) >> 24) & 0xff; } struct ecore_mcast_mac_elem { ecore_list_entry_t link; uint8_t mac[ETH_ALEN]; uint8_t pad[2]; /* For a natural alignment of the following buffer */ }; struct ecore_pending_mcast_cmd { ecore_list_entry_t link; int type; /* ECORE_MCAST_CMD_X */ union { ecore_list_t macs_head; uint32_t macs_num; /* Needed for DEL command */ int next_bin; /* Needed for RESTORE flow with aprox match */ } data; int done; /* set to TRUE, when the command has been handled, * practically used in 57712 handling only, where one pending * command may be handled in a few operations. As long as for * other chips every operation handling is completed in a * single ramrod, there is no need to utilize this field. */ }; static int ecore_mcast_wait(struct bnx2x_softc *sc, struct ecore_mcast_obj *o) { if (ecore_state_wait(sc, o->sched_state, o->raw.pstate) || o->raw.wait_comp(sc, &o->raw)) return ECORE_TIMEOUT; return ECORE_SUCCESS; } static int ecore_mcast_enqueue_cmd(struct bnx2x_softc *sc __rte_unused, struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { int total_sz; struct ecore_pending_mcast_cmd *new_cmd; struct ecore_mcast_mac_elem *cur_mac = NULL; struct ecore_mcast_list_elem *pos; int macs_list_len = ((cmd == ECORE_MCAST_CMD_ADD) ? p->mcast_list_len : 0); /* If the command is empty ("handle pending commands only"), break */ if (!p->mcast_list_len) return ECORE_SUCCESS; total_sz = sizeof(*new_cmd) + macs_list_len * sizeof(struct ecore_mcast_mac_elem); /* Add mcast is called under spin_lock, thus calling with GFP_ATOMIC */ new_cmd = ECORE_ZALLOC(total_sz, GFP_ATOMIC, sc); if (!new_cmd) return ECORE_NOMEM; ECORE_MSG("About to enqueue a new %d command. macs_list_len=%d", cmd, macs_list_len); ECORE_LIST_INIT(&new_cmd->data.macs_head); new_cmd->type = cmd; new_cmd->done = FALSE; switch (cmd) { case ECORE_MCAST_CMD_ADD: cur_mac = (struct ecore_mcast_mac_elem *) ((uint8_t *) new_cmd + sizeof(*new_cmd)); /* Push the MACs of the current command into the pending command * MACs list: FIFO */ ECORE_LIST_FOR_EACH_ENTRY(pos, &p->mcast_list, link, struct ecore_mcast_list_elem) { ECORE_MEMCPY(cur_mac->mac, pos->mac, ETH_ALEN); ECORE_LIST_PUSH_TAIL(&cur_mac->link, &new_cmd->data.macs_head); cur_mac++; } break; case ECORE_MCAST_CMD_DEL: new_cmd->data.macs_num = p->mcast_list_len; break; case ECORE_MCAST_CMD_RESTORE: new_cmd->data.next_bin = 0; break; default: ECORE_FREE(sc, new_cmd, total_sz); PMD_DRV_LOG(ERR, "Unknown command: %d", cmd); return ECORE_INVAL; } /* Push the new pending command to the tail of the pending list: FIFO */ ECORE_LIST_PUSH_TAIL(&new_cmd->link, &o->pending_cmds_head); o->set_sched(o); return ECORE_PENDING; } /** * ecore_mcast_get_next_bin - get the next set bin (index) * * @o: * @last: index to start looking from (including) * * returns the next found (set) bin or a negative value if none is found. */ static int ecore_mcast_get_next_bin(struct ecore_mcast_obj *o, int last) { int i, j, inner_start = last % BIT_VEC64_ELEM_SZ; for (i = last / BIT_VEC64_ELEM_SZ; i < ECORE_MCAST_VEC_SZ; i++) { if (o->registry.aprox_match.vec[i]) for (j = inner_start; j < BIT_VEC64_ELEM_SZ; j++) { int cur_bit = j + BIT_VEC64_ELEM_SZ * i; if (BIT_VEC64_TEST_BIT (o->registry.aprox_match.vec, cur_bit)) { return cur_bit; } } inner_start = 0; } /* None found */ return -1; } /** * ecore_mcast_clear_first_bin - find the first set bin and clear it * * @o: * * returns the index of the found bin or -1 if none is found */ static int ecore_mcast_clear_first_bin(struct ecore_mcast_obj *o) { int cur_bit = ecore_mcast_get_next_bin(o, 0); if (cur_bit >= 0) BIT_VEC64_CLEAR_BIT(o->registry.aprox_match.vec, cur_bit); return cur_bit; } static uint8_t ecore_mcast_get_rx_tx_flag(struct ecore_mcast_obj *o) { struct ecore_raw_obj *raw = &o->raw; uint8_t rx_tx_flag = 0; if ((raw->obj_type == ECORE_OBJ_TYPE_TX) || (raw->obj_type == ECORE_OBJ_TYPE_RX_TX)) rx_tx_flag |= ETH_MULTICAST_RULES_CMD_TX_CMD; if ((raw->obj_type == ECORE_OBJ_TYPE_RX) || (raw->obj_type == ECORE_OBJ_TYPE_RX_TX)) rx_tx_flag |= ETH_MULTICAST_RULES_CMD_RX_CMD; return rx_tx_flag; } static void ecore_mcast_set_one_rule_e2(struct bnx2x_softc *sc __rte_unused, struct ecore_mcast_obj *o, int idx, union ecore_mcast_config_data *cfg_data, enum ecore_mcast_cmd cmd) { struct ecore_raw_obj *r = &o->raw; struct eth_multicast_rules_ramrod_data *data = (struct eth_multicast_rules_ramrod_data *)(r->rdata); uint8_t func_id = r->func_id; uint8_t rx_tx_add_flag = ecore_mcast_get_rx_tx_flag(o); int bin; if ((cmd == ECORE_MCAST_CMD_ADD) || (cmd == ECORE_MCAST_CMD_RESTORE)) rx_tx_add_flag |= ETH_MULTICAST_RULES_CMD_IS_ADD; data->rules[idx].cmd_general_data |= rx_tx_add_flag; /* Get a bin and update a bins' vector */ switch (cmd) { case ECORE_MCAST_CMD_ADD: bin = ecore_mcast_bin_from_mac(cfg_data->mac); BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bin); break; case ECORE_MCAST_CMD_DEL: /* If there were no more bins to clear * (ecore_mcast_clear_first_bin() returns -1) then we would * clear any (0xff) bin. * See ecore_mcast_validate_e2() for explanation when it may * happen. */ bin = ecore_mcast_clear_first_bin(o); break; case ECORE_MCAST_CMD_RESTORE: bin = cfg_data->bin; break; default: PMD_DRV_LOG(ERR, "Unknown command: %d", cmd); return; } ECORE_MSG("%s bin %d", ((rx_tx_add_flag & ETH_MULTICAST_RULES_CMD_IS_ADD) ? "Setting" : "Clearing"), bin); data->rules[idx].bin_id = (uint8_t) bin; data->rules[idx].func_id = func_id; data->rules[idx].engine_id = o->engine_id; } /** * ecore_mcast_handle_restore_cmd_e2 - restore configuration from the registry * * @sc: device handle * @o: * @start_bin: index in the registry to start from (including) * @rdata_idx: index in the ramrod data to start from * * returns last handled bin index or -1 if all bins have been handled */ static int ecore_mcast_handle_restore_cmd_e2(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, int start_bin, int *rdata_idx) { int cur_bin, cnt = *rdata_idx; union ecore_mcast_config_data cfg_data = { NULL }; /* go through the registry and configure the bins from it */ for (cur_bin = ecore_mcast_get_next_bin(o, start_bin); cur_bin >= 0; cur_bin = ecore_mcast_get_next_bin(o, cur_bin + 1)) { cfg_data.bin = (uint8_t) cur_bin; o->set_one_rule(sc, o, cnt, &cfg_data, ECORE_MCAST_CMD_RESTORE); cnt++; ECORE_MSG("About to configure a bin %d", cur_bin); /* Break if we reached the maximum number * of rules. */ if (cnt >= o->max_cmd_len) break; } *rdata_idx = cnt; return cur_bin; } static void ecore_mcast_hdl_pending_add_e2(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos, int *line_idx) { struct ecore_mcast_mac_elem *pmac_pos, *pmac_pos_n; int cnt = *line_idx; union ecore_mcast_config_data cfg_data = { NULL }; ECORE_LIST_FOR_EACH_ENTRY_SAFE(pmac_pos, pmac_pos_n, &cmd_pos->data.macs_head, link, struct ecore_mcast_mac_elem) { cfg_data.mac = &pmac_pos->mac[0]; o->set_one_rule(sc, o, cnt, &cfg_data, cmd_pos->type); cnt++; ECORE_MSG ("About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC", pmac_pos->mac[0], pmac_pos->mac[1], pmac_pos->mac[2], pmac_pos->mac[3], pmac_pos->mac[4], pmac_pos->mac[5]); ECORE_LIST_REMOVE_ENTRY(&pmac_pos->link, &cmd_pos->data.macs_head); /* Break if we reached the maximum number * of rules. */ if (cnt >= o->max_cmd_len) break; } *line_idx = cnt; /* if no more MACs to configure - we are done */ if (ECORE_LIST_IS_EMPTY(&cmd_pos->data.macs_head)) cmd_pos->done = TRUE; } static void ecore_mcast_hdl_pending_del_e2(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos, int *line_idx) { int cnt = *line_idx; while (cmd_pos->data.macs_num) { o->set_one_rule(sc, o, cnt, NULL, cmd_pos->type); cnt++; cmd_pos->data.macs_num--; ECORE_MSG("Deleting MAC. %d left,cnt is %d", cmd_pos->data.macs_num, cnt); /* Break if we reached the maximum * number of rules. */ if (cnt >= o->max_cmd_len) break; } *line_idx = cnt; /* If we cleared all bins - we are done */ if (!cmd_pos->data.macs_num) cmd_pos->done = TRUE; } static void ecore_mcast_hdl_pending_restore_e2(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_pending_mcast_cmd *cmd_pos, int *line_idx) { cmd_pos->data.next_bin = o->hdl_restore(sc, o, cmd_pos->data.next_bin, line_idx); if (cmd_pos->data.next_bin < 0) /* If o->set_restore returned -1 we are done */ cmd_pos->done = TRUE; else /* Start from the next bin next time */ cmd_pos->data.next_bin++; } static int ecore_mcast_handle_pending_cmds_e2(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p) { struct ecore_pending_mcast_cmd *cmd_pos, *cmd_pos_n; int cnt = 0; struct ecore_mcast_obj *o = p->mcast_obj; ECORE_LIST_FOR_EACH_ENTRY_SAFE(cmd_pos, cmd_pos_n, &o->pending_cmds_head, link, struct ecore_pending_mcast_cmd) { switch (cmd_pos->type) { case ECORE_MCAST_CMD_ADD: ecore_mcast_hdl_pending_add_e2(sc, o, cmd_pos, &cnt); break; case ECORE_MCAST_CMD_DEL: ecore_mcast_hdl_pending_del_e2(sc, o, cmd_pos, &cnt); break; case ECORE_MCAST_CMD_RESTORE: ecore_mcast_hdl_pending_restore_e2(sc, o, cmd_pos, &cnt); break; default: PMD_DRV_LOG(ERR, "Unknown command: %d", cmd_pos->type); return ECORE_INVAL; } /* If the command has been completed - remove it from the list * and free the memory */ if (cmd_pos->done) { ECORE_LIST_REMOVE_ENTRY(&cmd_pos->link, &o->pending_cmds_head); ECORE_FREE(sc, cmd_pos, cmd_pos->alloc_len); } /* Break if we reached the maximum number of rules */ if (cnt >= o->max_cmd_len) break; } return cnt; } static void ecore_mcast_hdl_add(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p, int *line_idx) { struct ecore_mcast_list_elem *mlist_pos; union ecore_mcast_config_data cfg_data = { NULL }; int cnt = *line_idx; ECORE_LIST_FOR_EACH_ENTRY(mlist_pos, &p->mcast_list, link, struct ecore_mcast_list_elem) { cfg_data.mac = mlist_pos->mac; o->set_one_rule(sc, o, cnt, &cfg_data, ECORE_MCAST_CMD_ADD); cnt++; ECORE_MSG ("About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC", mlist_pos->mac[0], mlist_pos->mac[1], mlist_pos->mac[2], mlist_pos->mac[3], mlist_pos->mac[4], mlist_pos->mac[5]); } *line_idx = cnt; } static void ecore_mcast_hdl_del(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p, int *line_idx) { int cnt = *line_idx, i; for (i = 0; i < p->mcast_list_len; i++) { o->set_one_rule(sc, o, cnt, NULL, ECORE_MCAST_CMD_DEL); cnt++; ECORE_MSG("Deleting MAC. %d left", p->mcast_list_len - i - 1); } *line_idx = cnt; } /** * ecore_mcast_handle_current_cmd - * * @sc: device handle * @p: * @cmd: * @start_cnt: first line in the ramrod data that may be used * * This function is called iff there is enough place for the current command in * the ramrod data. * Returns number of lines filled in the ramrod data in total. */ static int ecore_mcast_handle_current_cmd(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd, int start_cnt) { struct ecore_mcast_obj *o = p->mcast_obj; int cnt = start_cnt; ECORE_MSG("p->mcast_list_len=%d", p->mcast_list_len); switch (cmd) { case ECORE_MCAST_CMD_ADD: ecore_mcast_hdl_add(sc, o, p, &cnt); break; case ECORE_MCAST_CMD_DEL: ecore_mcast_hdl_del(sc, o, p, &cnt); break; case ECORE_MCAST_CMD_RESTORE: o->hdl_restore(sc, o, 0, &cnt); break; default: PMD_DRV_LOG(ERR, "Unknown command: %d", cmd); return ECORE_INVAL; } /* The current command has been handled */ p->mcast_list_len = 0; return cnt; } static int ecore_mcast_validate_e2(__rte_unused struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { struct ecore_mcast_obj *o = p->mcast_obj; int reg_sz = o->get_registry_size(o); switch (cmd) { /* DEL command deletes all currently configured MACs */ case ECORE_MCAST_CMD_DEL: o->set_registry_size(o, 0); /* Don't break */ /* RESTORE command will restore the entire multicast configuration */ case ECORE_MCAST_CMD_RESTORE: /* Here we set the approximate amount of work to do, which in * fact may be only less as some MACs in postponed ADD * command(s) scheduled before this command may fall into * the same bin and the actual number of bins set in the * registry would be less than we estimated here. See * ecore_mcast_set_one_rule_e2() for further details. */ p->mcast_list_len = reg_sz; break; case ECORE_MCAST_CMD_ADD: case ECORE_MCAST_CMD_CONT: /* Here we assume that all new MACs will fall into new bins. * However we will correct the real registry size after we * handle all pending commands. */ o->set_registry_size(o, reg_sz + p->mcast_list_len); break; default: PMD_DRV_LOG(ERR, "Unknown command: %d", cmd); return ECORE_INVAL; } /* Increase the total number of MACs pending to be configured */ o->total_pending_num += p->mcast_list_len; return ECORE_SUCCESS; } static void ecore_mcast_revert_e2(__rte_unused struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, int old_num_bins) { struct ecore_mcast_obj *o = p->mcast_obj; o->set_registry_size(o, old_num_bins); o->total_pending_num -= p->mcast_list_len; } /** * ecore_mcast_set_rdata_hdr_e2 - sets a header values * * @sc: device handle * @p: * @len: number of rules to handle */ static void ecore_mcast_set_rdata_hdr_e2(__rte_unused struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, uint8_t len) { struct ecore_raw_obj *r = &p->mcast_obj->raw; struct eth_multicast_rules_ramrod_data *data = (struct eth_multicast_rules_ramrod_data *)(r->rdata); data->header.echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) | (ECORE_FILTER_MCAST_PENDING << ECORE_SWCID_SHIFT)); data->header.rule_cnt = len; } /** * ecore_mcast_refresh_registry_e2 - recalculate the actual number of set bins * * @sc: device handle * @o: * * Recalculate the actual number of set bins in the registry using Brian * Kernighan's algorithm: it's execution complexity is as a number of set bins. */ static int ecore_mcast_refresh_registry_e2(struct ecore_mcast_obj *o) { int i, cnt = 0; uint64_t elem; for (i = 0; i < ECORE_MCAST_VEC_SZ; i++) { elem = o->registry.aprox_match.vec[i]; for (; elem; cnt++) elem &= elem - 1; } o->set_registry_size(o, cnt); return ECORE_SUCCESS; } static int ecore_mcast_setup_e2(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { struct ecore_raw_obj *raw = &p->mcast_obj->raw; struct ecore_mcast_obj *o = p->mcast_obj; struct eth_multicast_rules_ramrod_data *data = (struct eth_multicast_rules_ramrod_data *)(raw->rdata); int cnt = 0, rc; /* Reset the ramrod data buffer */ ECORE_MEMSET(data, 0, sizeof(*data)); cnt = ecore_mcast_handle_pending_cmds_e2(sc, p); /* If there are no more pending commands - clear SCHEDULED state */ if (ECORE_LIST_IS_EMPTY(&o->pending_cmds_head)) o->clear_sched(o); /* The below may be TRUE iff there was enough room in ramrod * data for all pending commands and for the current * command. Otherwise the current command would have been added * to the pending commands and p->mcast_list_len would have been * zeroed. */ if (p->mcast_list_len > 0) cnt = ecore_mcast_handle_current_cmd(sc, p, cmd, cnt); /* We've pulled out some MACs - update the total number of * outstanding. */ o->total_pending_num -= cnt; /* send a ramrod */ ECORE_DBG_BREAK_IF(o->total_pending_num < 0); ECORE_DBG_BREAK_IF(cnt > o->max_cmd_len); ecore_mcast_set_rdata_hdr_e2(sc, p, (uint8_t) cnt); /* Update a registry size if there are no more pending operations. * * We don't want to change the value of the registry size if there are * pending operations because we want it to always be equal to the * exact or the approximate number (see ecore_mcast_validate_e2()) of * set bins after the last requested operation in order to properly * evaluate the size of the next DEL/RESTORE operation. * * Note that we update the registry itself during command(s) handling * - see ecore_mcast_set_one_rule_e2(). That's because for 57712 we * aggregate multiple commands (ADD/DEL/RESTORE) into one ramrod but * with a limited amount of update commands (per MAC/bin) and we don't * know in this scope what the actual state of bins configuration is * going to be after this ramrod. */ if (!o->total_pending_num) ecore_mcast_refresh_registry_e2(o); /* If CLEAR_ONLY was requested - don't send a ramrod and clear * RAMROD_PENDING status immediately. */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { raw->clear_pending(raw); return ECORE_SUCCESS; } else { /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ /* Send a ramrod */ rc = ecore_sp_post(sc, RAMROD_CMD_ID_ETH_MULTICAST_RULES, raw->cid, raw->rdata_mapping, ETH_CONNECTION_TYPE); if (rc) return rc; /* Ramrod completion is pending */ return ECORE_PENDING; } } static int ecore_mcast_validate_e1h(__rte_unused struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { /* Mark, that there is a work to do */ if ((cmd == ECORE_MCAST_CMD_DEL) || (cmd == ECORE_MCAST_CMD_RESTORE)) p->mcast_list_len = 1; return ECORE_SUCCESS; } static void ecore_mcast_revert_e1h(__rte_unused struct bnx2x_softc *sc, __rte_unused struct ecore_mcast_ramrod_params *p, __rte_unused int old_num_bins) { /* Do nothing */ } #define ECORE_57711_SET_MC_FILTER(filter, bit) \ do { \ (filter)[(bit) >> 5] |= (1 << ((bit) & 0x1f)); \ } while (0) static void ecore_mcast_hdl_add_e1h(struct bnx2x_softc *sc __rte_unused, struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p, uint32_t * mc_filter) { struct ecore_mcast_list_elem *mlist_pos; int bit; ECORE_LIST_FOR_EACH_ENTRY(mlist_pos, &p->mcast_list, link, struct ecore_mcast_list_elem) { bit = ecore_mcast_bin_from_mac(mlist_pos->mac); ECORE_57711_SET_MC_FILTER(mc_filter, bit); ECORE_MSG ("About to configure %02x:%02x:%02x:%02x:%02x:%02x mcast MAC, bin %d", mlist_pos->mac[0], mlist_pos->mac[1], mlist_pos->mac[2], mlist_pos->mac[3], mlist_pos->mac[4], mlist_pos->mac[5], bit); /* bookkeeping... */ BIT_VEC64_SET_BIT(o->registry.aprox_match.vec, bit); } } static void ecore_mcast_hdl_restore_e1h(struct bnx2x_softc *sc __rte_unused, struct ecore_mcast_obj *o, uint32_t * mc_filter) { int bit; for (bit = ecore_mcast_get_next_bin(o, 0); bit >= 0; bit = ecore_mcast_get_next_bin(o, bit + 1)) { ECORE_57711_SET_MC_FILTER(mc_filter, bit); ECORE_MSG("About to set bin %d", bit); } } /* On 57711 we write the multicast MACs' approximate match * table by directly into the TSTORM's internal RAM. So we don't * really need to handle any tricks to make it work. */ static int ecore_mcast_setup_e1h(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { int i; struct ecore_mcast_obj *o = p->mcast_obj; struct ecore_raw_obj *r = &o->raw; /* If CLEAR_ONLY has been requested - clear the registry * and clear a pending bit. */ if (!ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { uint32_t mc_filter[ECORE_MC_HASH_SIZE] = { 0 }; /* Set the multicast filter bits before writing it into * the internal memory. */ switch (cmd) { case ECORE_MCAST_CMD_ADD: ecore_mcast_hdl_add_e1h(sc, o, p, mc_filter); break; case ECORE_MCAST_CMD_DEL: ECORE_MSG("Invalidating multicast MACs configuration"); /* clear the registry */ ECORE_MEMSET(o->registry.aprox_match.vec, 0, sizeof(o->registry.aprox_match.vec)); break; case ECORE_MCAST_CMD_RESTORE: ecore_mcast_hdl_restore_e1h(sc, o, mc_filter); break; default: PMD_DRV_LOG(ERR, "Unknown command: %d", cmd); return ECORE_INVAL; } /* Set the mcast filter in the internal memory */ for (i = 0; i < ECORE_MC_HASH_SIZE; i++) REG_WR(sc, ECORE_MC_HASH_OFFSET(sc, i), mc_filter[i]); } else /* clear the registry */ ECORE_MEMSET(o->registry.aprox_match.vec, 0, sizeof(o->registry.aprox_match.vec)); /* We are done */ r->clear_pending(r); return ECORE_SUCCESS; } static int ecore_mcast_get_registry_size_aprox(struct ecore_mcast_obj *o) { return o->registry.aprox_match.num_bins_set; } static void ecore_mcast_set_registry_size_aprox(struct ecore_mcast_obj *o, int n) { o->registry.aprox_match.num_bins_set = n; } int ecore_config_mcast(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd) { struct ecore_mcast_obj *o = p->mcast_obj; struct ecore_raw_obj *r = &o->raw; int rc = 0, old_reg_size; /* This is needed to recover number of currently configured mcast macs * in case of failure. */ old_reg_size = o->get_registry_size(o); /* Do some calculations and checks */ rc = o->validate(sc, p, cmd); if (rc) return rc; /* Return if there is no work to do */ if ((!p->mcast_list_len) && (!o->check_sched(o))) return ECORE_SUCCESS; ECORE_MSG ("o->total_pending_num=%d p->mcast_list_len=%d o->max_cmd_len=%d", o->total_pending_num, p->mcast_list_len, o->max_cmd_len); /* Enqueue the current command to the pending list if we can't complete * it in the current iteration */ if (r->check_pending(r) || ((o->max_cmd_len > 0) && (o->total_pending_num > o->max_cmd_len))) { rc = o->enqueue_cmd(sc, p->mcast_obj, p, cmd); if (rc < 0) goto error_exit1; /* As long as the current command is in a command list we * don't need to handle it separately. */ p->mcast_list_len = 0; } if (!r->check_pending(r)) { /* Set 'pending' state */ r->set_pending(r); /* Configure the new classification in the chip */ rc = o->config_mcast(sc, p, cmd); if (rc < 0) goto error_exit2; /* Wait for a ramrod completion if was requested */ if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) rc = o->wait_comp(sc, o); } return rc; error_exit2: r->clear_pending(r); error_exit1: o->revert(sc, p, old_reg_size); return rc; } static void ecore_mcast_clear_sched(struct ecore_mcast_obj *o) { ECORE_SMP_MB_BEFORE_CLEAR_BIT(); ECORE_CLEAR_BIT(o->sched_state, o->raw.pstate); ECORE_SMP_MB_AFTER_CLEAR_BIT(); } static void ecore_mcast_set_sched(struct ecore_mcast_obj *o) { ECORE_SMP_MB_BEFORE_CLEAR_BIT(); ECORE_SET_BIT(o->sched_state, o->raw.pstate); ECORE_SMP_MB_AFTER_CLEAR_BIT(); } static int ecore_mcast_check_sched(struct ecore_mcast_obj *o) { return ! !ECORE_TEST_BIT(o->sched_state, o->raw.pstate); } static int ecore_mcast_check_pending(struct ecore_mcast_obj *o) { return o->raw.check_pending(&o->raw) || o->check_sched(o); } void ecore_init_mcast_obj(struct bnx2x_softc *sc, struct ecore_mcast_obj *mcast_obj, uint8_t mcast_cl_id, uint32_t mcast_cid, uint8_t func_id, uint8_t engine_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type) { ECORE_MEMSET(mcast_obj, 0, sizeof(*mcast_obj)); ecore_init_raw_obj(&mcast_obj->raw, mcast_cl_id, mcast_cid, func_id, rdata, rdata_mapping, state, pstate, type); mcast_obj->engine_id = engine_id; ECORE_LIST_INIT(&mcast_obj->pending_cmds_head); mcast_obj->sched_state = ECORE_FILTER_MCAST_SCHED; mcast_obj->check_sched = ecore_mcast_check_sched; mcast_obj->set_sched = ecore_mcast_set_sched; mcast_obj->clear_sched = ecore_mcast_clear_sched; if (CHIP_IS_E1H(sc)) { mcast_obj->config_mcast = ecore_mcast_setup_e1h; mcast_obj->enqueue_cmd = NULL; mcast_obj->hdl_restore = NULL; mcast_obj->check_pending = ecore_mcast_check_pending; /* 57711 doesn't send a ramrod, so it has unlimited credit * for one command. */ mcast_obj->max_cmd_len = -1; mcast_obj->wait_comp = ecore_mcast_wait; mcast_obj->set_one_rule = NULL; mcast_obj->validate = ecore_mcast_validate_e1h; mcast_obj->revert = ecore_mcast_revert_e1h; mcast_obj->get_registry_size = ecore_mcast_get_registry_size_aprox; mcast_obj->set_registry_size = ecore_mcast_set_registry_size_aprox; } else { mcast_obj->config_mcast = ecore_mcast_setup_e2; mcast_obj->enqueue_cmd = ecore_mcast_enqueue_cmd; mcast_obj->hdl_restore = ecore_mcast_handle_restore_cmd_e2; mcast_obj->check_pending = ecore_mcast_check_pending; mcast_obj->max_cmd_len = 16; mcast_obj->wait_comp = ecore_mcast_wait; mcast_obj->set_one_rule = ecore_mcast_set_one_rule_e2; mcast_obj->validate = ecore_mcast_validate_e2; mcast_obj->revert = ecore_mcast_revert_e2; mcast_obj->get_registry_size = ecore_mcast_get_registry_size_aprox; mcast_obj->set_registry_size = ecore_mcast_set_registry_size_aprox; } } /*************************** Credit handling **********************************/ /** * atomic_add_ifless - add if the result is less than a given value. * * @v: pointer of type ecore_atomic_t * @a: the amount to add to v... * @u: ...if (v + a) is less than u. * * returns TRUE if (v + a) was less than u, and FALSE otherwise. * */ static int __atomic_add_ifless(ecore_atomic_t * v, int a, int u) { int c, old; c = ECORE_ATOMIC_READ(v); for (;;) { if (ECORE_UNLIKELY(c + a >= u)) return FALSE; old = ECORE_ATOMIC_CMPXCHG((v), c, c + a); if (ECORE_LIKELY(old == c)) break; c = old; } return TRUE; } /** * atomic_dec_ifmoe - dec if the result is more or equal than a given value. * * @v: pointer of type ecore_atomic_t * @a: the amount to dec from v... * @u: ...if (v - a) is more or equal than u. * * returns TRUE if (v - a) was more or equal than u, and FALSE * otherwise. */ static int __atomic_dec_ifmoe(ecore_atomic_t * v, int a, int u) { int c, old; c = ECORE_ATOMIC_READ(v); for (;;) { if (ECORE_UNLIKELY(c - a < u)) return FALSE; old = ECORE_ATOMIC_CMPXCHG((v), c, c - a); if (ECORE_LIKELY(old == c)) break; c = old; } return TRUE; } static int ecore_credit_pool_get(struct ecore_credit_pool_obj *o, int cnt) { int rc; ECORE_SMP_MB(); rc = __atomic_dec_ifmoe(&o->credit, cnt, 0); ECORE_SMP_MB(); return rc; } static int ecore_credit_pool_put(struct ecore_credit_pool_obj *o, int cnt) { int rc; ECORE_SMP_MB(); /* Don't let to refill if credit + cnt > pool_sz */ rc = __atomic_add_ifless(&o->credit, cnt, o->pool_sz + 1); ECORE_SMP_MB(); return rc; } static int ecore_credit_pool_check(struct ecore_credit_pool_obj *o) { int cur_credit; ECORE_SMP_MB(); cur_credit = ECORE_ATOMIC_READ(&o->credit); return cur_credit; } static int ecore_credit_pool_always_TRUE(__rte_unused struct ecore_credit_pool_obj *o, __rte_unused int cnt) { return TRUE; } static int ecore_credit_pool_get_entry(struct ecore_credit_pool_obj *o, int *offset) { int idx, vec, i; *offset = -1; /* Find "internal cam-offset" then add to base for this object... */ for (vec = 0; vec < ECORE_POOL_VEC_SIZE; vec++) { /* Skip the current vector if there are no free entries in it */ if (!o->pool_mirror[vec]) continue; /* If we've got here we are going to find a free entry */ for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0; i < BIT_VEC64_ELEM_SZ; idx++, i++) if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) { /* Got one!! */ BIT_VEC64_CLEAR_BIT(o->pool_mirror, idx); *offset = o->base_pool_offset + idx; return TRUE; } } return FALSE; } static int ecore_credit_pool_put_entry(struct ecore_credit_pool_obj *o, int offset) { if (offset < o->base_pool_offset) return FALSE; offset -= o->base_pool_offset; if (offset >= o->pool_sz) return FALSE; /* Return the entry to the pool */ BIT_VEC64_SET_BIT(o->pool_mirror, offset); return TRUE; } static int ecore_credit_pool_put_entry_always_TRUE(__rte_unused struct ecore_credit_pool_obj *o, __rte_unused int offset) { return TRUE; } static int ecore_credit_pool_get_entry_always_TRUE(__rte_unused struct ecore_credit_pool_obj *o, __rte_unused int *offset) { *offset = -1; return TRUE; } /** * ecore_init_credit_pool - initialize credit pool internals. * * @p: * @base: Base entry in the CAM to use. * @credit: pool size. * * If base is negative no CAM entries handling will be performed. * If credit is negative pool operations will always succeed (unlimited pool). * */ static void ecore_init_credit_pool(struct ecore_credit_pool_obj *p, int base, int credit) { /* Zero the object first */ ECORE_MEMSET(p, 0, sizeof(*p)); /* Set the table to all 1s */ ECORE_MEMSET(&p->pool_mirror, 0xff, sizeof(p->pool_mirror)); /* Init a pool as full */ ECORE_ATOMIC_SET(&p->credit, credit); /* The total poll size */ p->pool_sz = credit; p->base_pool_offset = base; /* Commit the change */ ECORE_SMP_MB(); p->check = ecore_credit_pool_check; /* if pool credit is negative - disable the checks */ if (credit >= 0) { p->put = ecore_credit_pool_put; p->get = ecore_credit_pool_get; p->put_entry = ecore_credit_pool_put_entry; p->get_entry = ecore_credit_pool_get_entry; } else { p->put = ecore_credit_pool_always_TRUE; p->get = ecore_credit_pool_always_TRUE; p->put_entry = ecore_credit_pool_put_entry_always_TRUE; p->get_entry = ecore_credit_pool_get_entry_always_TRUE; } /* If base is negative - disable entries handling */ if (base < 0) { p->put_entry = ecore_credit_pool_put_entry_always_TRUE; p->get_entry = ecore_credit_pool_get_entry_always_TRUE; } } void ecore_init_mac_credit_pool(struct bnx2x_softc *sc, struct ecore_credit_pool_obj *p, uint8_t func_id, uint8_t func_num) { #define ECORE_CAM_SIZE_EMUL 5 int cam_sz; if (CHIP_IS_E1H(sc)) { /* CAM credit is equally divided between all active functions * on the PORT!. */ if ((func_num > 0)) { if (!CHIP_REV_IS_SLOW(sc)) cam_sz = (MAX_MAC_CREDIT_E1H / (2 * func_num)); else cam_sz = ECORE_CAM_SIZE_EMUL; ecore_init_credit_pool(p, func_id * cam_sz, cam_sz); } else { /* this should never happen! Block MAC operations. */ ecore_init_credit_pool(p, 0, 0); } } else { /* * CAM credit is equaly divided between all active functions * on the PATH. */ if ((func_num > 0)) { if (!CHIP_REV_IS_SLOW(sc)) cam_sz = (MAX_MAC_CREDIT_E2 / func_num); else cam_sz = ECORE_CAM_SIZE_EMUL; /* No need for CAM entries handling for 57712 and * newer. */ ecore_init_credit_pool(p, -1, cam_sz); } else { /* this should never happen! Block MAC operations. */ ecore_init_credit_pool(p, 0, 0); } } } void ecore_init_vlan_credit_pool(struct bnx2x_softc *sc, struct ecore_credit_pool_obj *p, uint8_t func_id, uint8_t func_num) { if (CHIP_IS_E1x(sc)) { /* There is no VLAN credit in HW on 57711 only * MAC / MAC-VLAN can be set */ ecore_init_credit_pool(p, 0, -1); } else { /* CAM credit is equally divided between all active functions * on the PATH. */ if (func_num > 0) { int credit = MAX_VLAN_CREDIT_E2 / func_num; ecore_init_credit_pool(p, func_id * credit, credit); } else /* this should never happen! Block VLAN operations. */ ecore_init_credit_pool(p, 0, 0); } } /****************** RSS Configuration ******************/ /** * ecore_setup_rss - configure RSS * * @sc: device handle * @p: rss configuration * * sends on UPDATE ramrod for that matter. */ static int ecore_setup_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *p) { struct ecore_rss_config_obj *o = p->rss_obj; struct ecore_raw_obj *r = &o->raw; struct eth_rss_update_ramrod_data *data = (struct eth_rss_update_ramrod_data *)(r->rdata); uint8_t rss_mode = 0; int rc; ECORE_MEMSET(data, 0, sizeof(*data)); ECORE_MSG("Configuring RSS"); /* Set an echo field */ data->echo = ECORE_CPU_TO_LE32((r->cid & ECORE_SWCID_MASK) | (r->state << ECORE_SWCID_SHIFT)); /* RSS mode */ if (ECORE_TEST_BIT(ECORE_RSS_MODE_DISABLED, &p->rss_flags)) rss_mode = ETH_RSS_MODE_DISABLED; else if (ECORE_TEST_BIT(ECORE_RSS_MODE_REGULAR, &p->rss_flags)) rss_mode = ETH_RSS_MODE_REGULAR; data->rss_mode = rss_mode; ECORE_MSG("rss_mode=%d", rss_mode); /* RSS capabilities */ if (ECORE_TEST_BIT(ECORE_RSS_IPV4, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_IPV4_TCP, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_IPV4_UDP, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_IPV6, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_IPV6_TCP, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_IPV6_UDP, &p->rss_flags)) data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY; if (ECORE_TEST_BIT(ECORE_RSS_TUNNELING, &p->rss_flags)) { data->udp_4tuple_dst_port_mask = ECORE_CPU_TO_LE16(p->tunnel_mask); data->udp_4tuple_dst_port_value = ECORE_CPU_TO_LE16(p->tunnel_value); } /* Hashing mask */ data->rss_result_mask = p->rss_result_mask; /* RSS engine ID */ data->rss_engine_id = o->engine_id; ECORE_MSG("rss_engine_id=%d", data->rss_engine_id); /* Indirection table */ ECORE_MEMCPY(data->indirection_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE); /* Remember the last configuration */ ECORE_MEMCPY(o->ind_table, p->ind_table, T_ETH_INDIRECTION_TABLE_SIZE); /* RSS keys */ if (ECORE_TEST_BIT(ECORE_RSS_SET_SRCH, &p->rss_flags)) { ECORE_MEMCPY(&data->rss_key[0], &p->rss_key[0], sizeof(data->rss_key)); data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY; } /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ /* Send a ramrod */ rc = ecore_sp_post(sc, RAMROD_CMD_ID_ETH_RSS_UPDATE, r->cid, r->rdata_mapping, ETH_CONNECTION_TYPE); if (rc < 0) return rc; return ECORE_PENDING; } int ecore_config_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *p) { int rc; struct ecore_rss_config_obj *o = p->rss_obj; struct ecore_raw_obj *r = &o->raw; /* Do nothing if only driver cleanup was requested */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) return ECORE_SUCCESS; r->set_pending(r); rc = o->config_rss(sc, p); if (rc < 0) { r->clear_pending(r); return rc; } if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, &p->ramrod_flags)) rc = r->wait_comp(sc, r); return rc; } void ecore_init_rss_config_obj(struct ecore_rss_config_obj *rss_obj, uint8_t cl_id, uint32_t cid, uint8_t func_id, uint8_t engine_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type) { ecore_init_raw_obj(&rss_obj->raw, cl_id, cid, func_id, rdata, rdata_mapping, state, pstate, type); rss_obj->engine_id = engine_id; rss_obj->config_rss = ecore_setup_rss; } /********************** Queue state object ***********************************/ /** * ecore_queue_state_change - perform Queue state change transition * * @sc: device handle * @params: parameters to perform the transition * * returns 0 in case of successfully completed transition, negative error * code in case of failure, positive (EBUSY) value if there is a completion * to that is still pending (possible only if RAMROD_COMP_WAIT is * not set in params->ramrod_flags for asynchronous commands). * */ int ecore_queue_state_change(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; int rc, pending_bit; unsigned long *pending = &o->pending; /* Check that the requested transition is legal */ rc = o->check_transition(sc, o, params); if (rc) { PMD_DRV_LOG(ERR, "check transition returned an error. rc %d", rc); return ECORE_INVAL; } /* Set "pending" bit */ ECORE_MSG("pending bit was=%lx", o->pending); pending_bit = o->set_pending(o, params); ECORE_MSG("pending bit now=%lx", o->pending); /* Don't send a command if only driver cleanup was requested */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) o->complete_cmd(sc, o, pending_bit); else { /* Send a ramrod */ rc = o->send_cmd(sc, params); if (rc) { o->next_state = ECORE_Q_STATE_MAX; ECORE_CLEAR_BIT(pending_bit, pending); ECORE_SMP_MB_AFTER_CLEAR_BIT(); return rc; } if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) { rc = o->wait_comp(sc, o, pending_bit); if (rc) return rc; return ECORE_SUCCESS; } } return ECORE_RET_PENDING(pending_bit, pending); } static int ecore_queue_set_pending(struct ecore_queue_sp_obj *obj, struct ecore_queue_state_params *params) { enum ecore_queue_cmd cmd = params->cmd, bit; /* ACTIVATE and DEACTIVATE commands are implemented on top of * UPDATE command. */ if ((cmd == ECORE_Q_CMD_ACTIVATE) || (cmd == ECORE_Q_CMD_DEACTIVATE)) bit = ECORE_Q_CMD_UPDATE; else bit = cmd; ECORE_SET_BIT(bit, &obj->pending); return bit; } static int ecore_queue_wait_comp(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *o, enum ecore_queue_cmd cmd) { return ecore_state_wait(sc, cmd, &o->pending); } /** * ecore_queue_comp_cmd - complete the state change command. * * @sc: device handle * @o: * @cmd: * * Checks that the arrived completion is expected. */ static int ecore_queue_comp_cmd(struct bnx2x_softc *sc __rte_unused, struct ecore_queue_sp_obj *o, enum ecore_queue_cmd cmd) { unsigned long cur_pending = o->pending; if (!ECORE_TEST_AND_CLEAR_BIT(cmd, &cur_pending)) { PMD_DRV_LOG(ERR, "Bad MC reply %d for queue %d in state %d pending 0x%lx, next_state %d", cmd, o->cids[ECORE_PRIMARY_CID_INDEX], o->state, cur_pending, o->next_state); return ECORE_INVAL; } if (o->next_tx_only >= o->max_cos) /* >= because tx only must always be smaller than cos since the * primary connection supports COS 0 */ PMD_DRV_LOG(ERR, "illegal value for next tx_only: %d. max cos was %d", o->next_tx_only, o->max_cos); ECORE_MSG("Completing command %d for queue %d, setting state to %d", cmd, o->cids[ECORE_PRIMARY_CID_INDEX], o->next_state); if (o->next_tx_only) /* print num tx-only if any exist */ ECORE_MSG("primary cid %d: num tx-only cons %d", o->cids[ECORE_PRIMARY_CID_INDEX], o->next_tx_only); o->state = o->next_state; o->num_tx_only = o->next_tx_only; o->next_state = ECORE_Q_STATE_MAX; /* It's important that o->state and o->next_state are * updated before o->pending. */ wmb(); ECORE_CLEAR_BIT(cmd, &o->pending); ECORE_SMP_MB_AFTER_CLEAR_BIT(); return ECORE_SUCCESS; } static void ecore_q_fill_setup_data_e2(struct ecore_queue_state_params *cmd_params, struct client_init_ramrod_data *data) { struct ecore_queue_setup_params *params = &cmd_params->params.setup; /* Rx data */ /* IPv6 TPA supported for E2 and above only */ data->rx.tpa_en |= ECORE_TEST_BIT(ECORE_Q_FLG_TPA_IPV6, ¶ms->flags) * CLIENT_INIT_RX_DATA_TPA_EN_IPV6; } static void ecore_q_fill_init_general_data(struct bnx2x_softc *sc __rte_unused, struct ecore_queue_sp_obj *o, struct ecore_general_setup_params *params, struct client_init_general_data *gen_data, unsigned long *flags) { gen_data->client_id = o->cl_id; if (ECORE_TEST_BIT(ECORE_Q_FLG_STATS, flags)) { gen_data->statistics_counter_id = params->stat_id; gen_data->statistics_en_flg = 1; gen_data->statistics_zero_flg = ECORE_TEST_BIT(ECORE_Q_FLG_ZERO_STATS, flags); } else gen_data->statistics_counter_id = DISABLE_STATISTIC_COUNTER_ID_VALUE; gen_data->is_fcoe_flg = ECORE_TEST_BIT(ECORE_Q_FLG_FCOE, flags); gen_data->activate_flg = ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE, flags); gen_data->sp_client_id = params->spcl_id; gen_data->mtu = ECORE_CPU_TO_LE16(params->mtu); gen_data->func_id = o->func_id; gen_data->cos = params->cos; gen_data->traffic_type = ECORE_TEST_BIT(ECORE_Q_FLG_FCOE, flags) ? LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW; ECORE_MSG("flags: active %d, cos %d, stats en %d", gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg); } static void ecore_q_fill_init_tx_data(struct ecore_txq_setup_params *params, struct client_init_tx_data *tx_data, unsigned long *flags) { tx_data->enforce_security_flg = ECORE_TEST_BIT(ECORE_Q_FLG_TX_SEC, flags); tx_data->default_vlan = ECORE_CPU_TO_LE16(params->default_vlan); tx_data->default_vlan_flg = ECORE_TEST_BIT(ECORE_Q_FLG_DEF_VLAN, flags); tx_data->tx_switching_flg = ECORE_TEST_BIT(ECORE_Q_FLG_TX_SWITCH, flags); tx_data->anti_spoofing_flg = ECORE_TEST_BIT(ECORE_Q_FLG_ANTI_SPOOF, flags); tx_data->force_default_pri_flg = ECORE_TEST_BIT(ECORE_Q_FLG_FORCE_DEFAULT_PRI, flags); tx_data->refuse_outband_vlan_flg = ECORE_TEST_BIT(ECORE_Q_FLG_REFUSE_OUTBAND_VLAN, flags); tx_data->tunnel_non_lso_pcsum_location = ECORE_TEST_BIT(ECORE_Q_FLG_PCSUM_ON_PKT, flags) ? CSUM_ON_PKT : CSUM_ON_BD; tx_data->tx_status_block_id = params->fw_sb_id; tx_data->tx_sb_index_number = params->sb_cq_index; tx_data->tss_leading_client_id = params->tss_leading_cl_id; tx_data->tx_bd_page_base.lo = ECORE_CPU_TO_LE32(U64_LO(params->dscr_map)); tx_data->tx_bd_page_base.hi = ECORE_CPU_TO_LE32(U64_HI(params->dscr_map)); /* Don't configure any Tx switching mode during queue SETUP */ tx_data->state = 0; } static void ecore_q_fill_init_pause_data(struct rxq_pause_params *params, struct client_init_rx_data *rx_data) { /* flow control data */ rx_data->cqe_pause_thr_low = ECORE_CPU_TO_LE16(params->rcq_th_lo); rx_data->cqe_pause_thr_high = ECORE_CPU_TO_LE16(params->rcq_th_hi); rx_data->bd_pause_thr_low = ECORE_CPU_TO_LE16(params->bd_th_lo); rx_data->bd_pause_thr_high = ECORE_CPU_TO_LE16(params->bd_th_hi); rx_data->sge_pause_thr_low = ECORE_CPU_TO_LE16(params->sge_th_lo); rx_data->sge_pause_thr_high = ECORE_CPU_TO_LE16(params->sge_th_hi); rx_data->rx_cos_mask = ECORE_CPU_TO_LE16(params->pri_map); } static void ecore_q_fill_init_rx_data(struct ecore_rxq_setup_params *params, struct client_init_rx_data *rx_data, unsigned long *flags) { rx_data->tpa_en = ECORE_TEST_BIT(ECORE_Q_FLG_TPA, flags) * CLIENT_INIT_RX_DATA_TPA_EN_IPV4; rx_data->tpa_en |= ECORE_TEST_BIT(ECORE_Q_FLG_TPA_GRO, flags) * CLIENT_INIT_RX_DATA_TPA_MODE; rx_data->vmqueue_mode_en_flg = 0; rx_data->extra_data_over_sgl_en_flg = ECORE_TEST_BIT(ECORE_Q_FLG_OOO, flags); rx_data->cache_line_alignment_log_size = params->cache_line_log; rx_data->enable_dynamic_hc = ECORE_TEST_BIT(ECORE_Q_FLG_DHC, flags); rx_data->client_qzone_id = params->cl_qzone_id; rx_data->max_agg_size = ECORE_CPU_TO_LE16(params->tpa_agg_sz); /* Always start in DROP_ALL mode */ rx_data->state = ECORE_CPU_TO_LE16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | CLIENT_INIT_RX_DATA_MCAST_DROP_ALL); /* We don't set drop flags */ rx_data->drop_ip_cs_err_flg = 0; rx_data->drop_tcp_cs_err_flg = 0; rx_data->drop_ttl0_flg = 0; rx_data->drop_udp_cs_err_flg = 0; rx_data->inner_vlan_removal_enable_flg = ECORE_TEST_BIT(ECORE_Q_FLG_VLAN, flags); rx_data->outer_vlan_removal_enable_flg = ECORE_TEST_BIT(ECORE_Q_FLG_OV, flags); rx_data->status_block_id = params->fw_sb_id; rx_data->rx_sb_index_number = params->sb_cq_index; rx_data->max_tpa_queues = params->max_tpa_queues; rx_data->max_bytes_on_bd = ECORE_CPU_TO_LE16(params->buf_sz); rx_data->bd_page_base.lo = ECORE_CPU_TO_LE32(U64_LO(params->dscr_map)); rx_data->bd_page_base.hi = ECORE_CPU_TO_LE32(U64_HI(params->dscr_map)); rx_data->cqe_page_base.lo = ECORE_CPU_TO_LE32(U64_LO(params->rcq_map)); rx_data->cqe_page_base.hi = ECORE_CPU_TO_LE32(U64_HI(params->rcq_map)); rx_data->is_leading_rss = ECORE_TEST_BIT(ECORE_Q_FLG_LEADING_RSS, flags); if (ECORE_TEST_BIT(ECORE_Q_FLG_MCAST, flags)) { rx_data->approx_mcast_engine_id = params->mcast_engine_id; rx_data->is_approx_mcast = 1; } rx_data->rss_engine_id = params->rss_engine_id; /* silent vlan removal */ rx_data->silent_vlan_removal_flg = ECORE_TEST_BIT(ECORE_Q_FLG_SILENT_VLAN_REM, flags); rx_data->silent_vlan_value = ECORE_CPU_TO_LE16(params->silent_removal_value); rx_data->silent_vlan_mask = ECORE_CPU_TO_LE16(params->silent_removal_mask); } /* initialize the general, tx and rx parts of a queue object */ static void ecore_q_fill_setup_data_cmn(struct bnx2x_softc *sc, struct ecore_queue_state_params *cmd_params, struct client_init_ramrod_data *data) { ecore_q_fill_init_general_data(sc, cmd_params->q_obj, &cmd_params->params.setup.gen_params, &data->general, &cmd_params->params.setup.flags); ecore_q_fill_init_tx_data(&cmd_params->params.setup.txq_params, &data->tx, &cmd_params->params.setup.flags); ecore_q_fill_init_rx_data(&cmd_params->params.setup.rxq_params, &data->rx, &cmd_params->params.setup.flags); ecore_q_fill_init_pause_data(&cmd_params->params.setup.pause_params, &data->rx); } /* initialize the general and tx parts of a tx-only queue object */ static void ecore_q_fill_setup_tx_only(struct bnx2x_softc *sc, struct ecore_queue_state_params *cmd_params, struct tx_queue_init_ramrod_data *data) { ecore_q_fill_init_general_data(sc, cmd_params->q_obj, &cmd_params->params.tx_only.gen_params, &data->general, &cmd_params->params.tx_only.flags); ecore_q_fill_init_tx_data(&cmd_params->params.tx_only.txq_params, &data->tx, &cmd_params->params.tx_only.flags); ECORE_MSG("cid %d, tx bd page lo %x hi %x", cmd_params->q_obj->cids[0], data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi); } /** * ecore_q_init - init HW/FW queue * * @sc: device handle * @params: * * HW/FW initial Queue configuration: * - HC: Rx and Tx * - CDU context validation * */ static int ecore_q_init(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; struct ecore_queue_init_params *init = ¶ms->params.init; uint16_t hc_usec; uint8_t cos; /* Tx HC configuration */ if (ECORE_TEST_BIT(ECORE_Q_TYPE_HAS_TX, &o->type) && ECORE_TEST_BIT(ECORE_Q_FLG_HC, &init->tx.flags)) { hc_usec = init->tx.hc_rate ? 1000000 / init->tx.hc_rate : 0; ECORE_UPDATE_COALESCE_SB_INDEX(sc, init->tx.fw_sb_id, init->tx.sb_cq_index, !ECORE_TEST_BIT (ECORE_Q_FLG_HC_EN, &init->tx.flags), hc_usec); } /* Rx HC configuration */ if (ECORE_TEST_BIT(ECORE_Q_TYPE_HAS_RX, &o->type) && ECORE_TEST_BIT(ECORE_Q_FLG_HC, &init->rx.flags)) { hc_usec = init->rx.hc_rate ? 1000000 / init->rx.hc_rate : 0; ECORE_UPDATE_COALESCE_SB_INDEX(sc, init->rx.fw_sb_id, init->rx.sb_cq_index, !ECORE_TEST_BIT (ECORE_Q_FLG_HC_EN, &init->rx.flags), hc_usec); } /* Set CDU context validation values */ for (cos = 0; cos < o->max_cos; cos++) { ECORE_MSG("setting context validation. cid %d, cos %d", o->cids[cos], cos); ECORE_MSG("context pointer %p", init->cxts[cos]); ECORE_SET_CTX_VALIDATION(sc, init->cxts[cos], o->cids[cos]); } /* As no ramrod is sent, complete the command immediately */ o->complete_cmd(sc, o, ECORE_Q_CMD_INIT); ECORE_MMIOWB(); ECORE_SMP_MB(); return ECORE_SUCCESS; } static int ecore_q_send_setup_e1x(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; struct client_init_ramrod_data *rdata = (struct client_init_ramrod_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP; /* Clear the ramrod data */ ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data */ ecore_q_fill_setup_data_cmn(sc, params, rdata); /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ return ecore_sp_post(sc, ramrod, o->cids[ECORE_PRIMARY_CID_INDEX], data_mapping, ETH_CONNECTION_TYPE); } static int ecore_q_send_setup_e2(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; struct client_init_ramrod_data *rdata = (struct client_init_ramrod_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; int ramrod = RAMROD_CMD_ID_ETH_CLIENT_SETUP; /* Clear the ramrod data */ ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data */ ecore_q_fill_setup_data_cmn(sc, params, rdata); ecore_q_fill_setup_data_e2(params, rdata); /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ return ecore_sp_post(sc, ramrod, o->cids[ECORE_PRIMARY_CID_INDEX], data_mapping, ETH_CONNECTION_TYPE); } static int ecore_q_send_setup_tx_only(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; struct tx_queue_init_ramrod_data *rdata = (struct tx_queue_init_ramrod_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP; struct ecore_queue_setup_tx_only_params *tx_only_params = ¶ms->params.tx_only; uint8_t cid_index = tx_only_params->cid_index; if (ECORE_TEST_BIT(ECORE_Q_TYPE_FWD, &o->type)) ramrod = RAMROD_CMD_ID_ETH_FORWARD_SETUP; ECORE_MSG("sending forward tx-only ramrod"); if (cid_index >= o->max_cos) { PMD_DRV_LOG(ERR, "queue[%d]: cid_index (%d) is out of range", o->cl_id, cid_index); return ECORE_INVAL; } ECORE_MSG("parameters received: cos: %d sp-id: %d", tx_only_params->gen_params.cos, tx_only_params->gen_params.spcl_id); /* Clear the ramrod data */ ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data */ ecore_q_fill_setup_tx_only(sc, params, rdata); ECORE_MSG ("sending tx-only ramrod: cid %d, client-id %d, sp-client id %d, cos %d", o->cids[cid_index], rdata->general.client_id, rdata->general.sp_client_id, rdata->general.cos); /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ return ecore_sp_post(sc, ramrod, o->cids[cid_index], data_mapping, ETH_CONNECTION_TYPE); } static void ecore_q_fill_update_data(struct ecore_queue_sp_obj *obj, struct ecore_queue_update_params *params, struct client_update_ramrod_data *data) { /* Client ID of the client to update */ data->client_id = obj->cl_id; /* Function ID of the client to update */ data->func_id = obj->func_id; /* Default VLAN value */ data->default_vlan = ECORE_CPU_TO_LE16(params->def_vlan); /* Inner VLAN stripping */ data->inner_vlan_removal_enable_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_IN_VLAN_REM, ¶ms->update_flags); data->inner_vlan_removal_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_IN_VLAN_REM_CHNG, ¶ms->update_flags); /* Outer VLAN stripping */ data->outer_vlan_removal_enable_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_OUT_VLAN_REM, ¶ms->update_flags); data->outer_vlan_removal_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_OUT_VLAN_REM_CHNG, ¶ms->update_flags); /* Drop packets that have source MAC that doesn't belong to this * Queue. */ data->anti_spoofing_enable_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_ANTI_SPOOF, ¶ms->update_flags); data->anti_spoofing_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_ANTI_SPOOF_CHNG, ¶ms->update_flags); /* Activate/Deactivate */ data->activate_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, ¶ms->update_flags); data->activate_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG, ¶ms->update_flags); /* Enable default VLAN */ data->default_vlan_enable_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_DEF_VLAN_EN, ¶ms->update_flags); data->default_vlan_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_DEF_VLAN_EN_CHNG, ¶ms->update_flags); /* silent vlan removal */ data->silent_vlan_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_SILENT_VLAN_REM_CHNG, ¶ms->update_flags); data->silent_vlan_removal_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_SILENT_VLAN_REM, ¶ms->update_flags); data->silent_vlan_value = ECORE_CPU_TO_LE16(params->silent_removal_value); data->silent_vlan_mask = ECORE_CPU_TO_LE16(params->silent_removal_mask); /* tx switching */ data->tx_switching_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_TX_SWITCHING, ¶ms->update_flags); data->tx_switching_change_flg = ECORE_TEST_BIT(ECORE_Q_UPDATE_TX_SWITCHING_CHNG, ¶ms->update_flags); } static int ecore_q_send_update(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; struct client_update_ramrod_data *rdata = (struct client_update_ramrod_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; struct ecore_queue_update_params *update_params = ¶ms->params.update; uint8_t cid_index = update_params->cid_index; if (cid_index >= o->max_cos) { PMD_DRV_LOG(ERR, "queue[%d]: cid_index (%d) is out of range", o->cl_id, cid_index); return ECORE_INVAL; } /* Clear the ramrod data */ ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data */ ecore_q_fill_update_data(o, update_params, rdata); /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, o->cids[cid_index], data_mapping, ETH_CONNECTION_TYPE); } /** * ecore_q_send_deactivate - send DEACTIVATE command * * @sc: device handle * @params: * * implemented using the UPDATE command. */ static int ecore_q_send_deactivate(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_update_params *update = ¶ms->params.update; ECORE_MEMSET(update, 0, sizeof(*update)); ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags); return ecore_q_send_update(sc, params); } /** * ecore_q_send_activate - send ACTIVATE command * * @sc: device handle * @params: * * implemented using the UPDATE command. */ static int ecore_q_send_activate(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_update_params *update = ¶ms->params.update; ECORE_MEMSET(update, 0, sizeof(*update)); ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE, &update->update_flags); ECORE_SET_BIT_NA(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update->update_flags); return ecore_q_send_update(sc, params); } static int ecore_q_send_update_tpa(__rte_unused struct bnx2x_softc *sc, __rte_unused struct ecore_queue_state_params *params) { /* Not implemented yet. */ return -1; } static int ecore_q_send_halt(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; /* build eth_halt_ramrod_data.client_id in a big-endian friendly way */ ecore_dma_addr_t data_mapping = 0; data_mapping = (ecore_dma_addr_t) o->cl_id; return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_HALT, o->cids[ECORE_PRIMARY_CID_INDEX], data_mapping, ETH_CONNECTION_TYPE); } static int ecore_q_send_cfc_del(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; uint8_t cid_idx = params->params.cfc_del.cid_index; if (cid_idx >= o->max_cos) { PMD_DRV_LOG(ERR, "queue[%d]: cid_index (%d) is out of range", o->cl_id, cid_idx); return ECORE_INVAL; } return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_CFC_DEL, o->cids[cid_idx], 0, NONE_CONNECTION_TYPE); } static int ecore_q_send_terminate(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; uint8_t cid_index = params->params.terminate.cid_index; if (cid_index >= o->max_cos) { PMD_DRV_LOG(ERR, "queue[%d]: cid_index (%d) is out of range", o->cl_id, cid_index); return ECORE_INVAL; } return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_TERMINATE, o->cids[cid_index], 0, ETH_CONNECTION_TYPE); } static int ecore_q_send_empty(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { struct ecore_queue_sp_obj *o = params->q_obj; return ecore_sp_post(sc, RAMROD_CMD_ID_ETH_EMPTY, o->cids[ECORE_PRIMARY_CID_INDEX], 0, ETH_CONNECTION_TYPE); } static int ecore_queue_send_cmd_cmn(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { switch (params->cmd) { case ECORE_Q_CMD_INIT: return ecore_q_init(sc, params); case ECORE_Q_CMD_SETUP_TX_ONLY: return ecore_q_send_setup_tx_only(sc, params); case ECORE_Q_CMD_DEACTIVATE: return ecore_q_send_deactivate(sc, params); case ECORE_Q_CMD_ACTIVATE: return ecore_q_send_activate(sc, params); case ECORE_Q_CMD_UPDATE: return ecore_q_send_update(sc, params); case ECORE_Q_CMD_UPDATE_TPA: return ecore_q_send_update_tpa(sc, params); case ECORE_Q_CMD_HALT: return ecore_q_send_halt(sc, params); case ECORE_Q_CMD_CFC_DEL: return ecore_q_send_cfc_del(sc, params); case ECORE_Q_CMD_TERMINATE: return ecore_q_send_terminate(sc, params); case ECORE_Q_CMD_EMPTY: return ecore_q_send_empty(sc, params); default: PMD_DRV_LOG(ERR, "Unknown command: %d", params->cmd); return ECORE_INVAL; } } static int ecore_queue_send_cmd_e1x(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { switch (params->cmd) { case ECORE_Q_CMD_SETUP: return ecore_q_send_setup_e1x(sc, params); case ECORE_Q_CMD_INIT: case ECORE_Q_CMD_SETUP_TX_ONLY: case ECORE_Q_CMD_DEACTIVATE: case ECORE_Q_CMD_ACTIVATE: case ECORE_Q_CMD_UPDATE: case ECORE_Q_CMD_UPDATE_TPA: case ECORE_Q_CMD_HALT: case ECORE_Q_CMD_CFC_DEL: case ECORE_Q_CMD_TERMINATE: case ECORE_Q_CMD_EMPTY: return ecore_queue_send_cmd_cmn(sc, params); default: PMD_DRV_LOG(ERR, "Unknown command: %d", params->cmd); return ECORE_INVAL; } } static int ecore_queue_send_cmd_e2(struct bnx2x_softc *sc, struct ecore_queue_state_params *params) { switch (params->cmd) { case ECORE_Q_CMD_SETUP: return ecore_q_send_setup_e2(sc, params); case ECORE_Q_CMD_INIT: case ECORE_Q_CMD_SETUP_TX_ONLY: case ECORE_Q_CMD_DEACTIVATE: case ECORE_Q_CMD_ACTIVATE: case ECORE_Q_CMD_UPDATE: case ECORE_Q_CMD_UPDATE_TPA: case ECORE_Q_CMD_HALT: case ECORE_Q_CMD_CFC_DEL: case ECORE_Q_CMD_TERMINATE: case ECORE_Q_CMD_EMPTY: return ecore_queue_send_cmd_cmn(sc, params); default: PMD_DRV_LOG(ERR, "Unknown command: %d", params->cmd); return ECORE_INVAL; } } /** * ecore_queue_chk_transition - check state machine of a regular Queue * * @sc: device handle * @o: * @params: * * (not Forwarding) * It both checks if the requested command is legal in a current * state and, if it's legal, sets a `next_state' in the object * that will be used in the completion flow to set the `state' * of the object. * * returns 0 if a requested command is a legal transition, * ECORE_INVAL otherwise. */ static int ecore_queue_chk_transition(struct bnx2x_softc *sc __rte_unused, struct ecore_queue_sp_obj *o, struct ecore_queue_state_params *params) { enum ecore_q_state state = o->state, next_state = ECORE_Q_STATE_MAX; enum ecore_queue_cmd cmd = params->cmd; struct ecore_queue_update_params *update_params = ¶ms->params.update; uint8_t next_tx_only = o->num_tx_only; /* Forget all pending for completion commands if a driver only state * transition has been requested. */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { o->pending = 0; o->next_state = ECORE_Q_STATE_MAX; } /* Don't allow a next state transition if we are in the middle of * the previous one. */ if (o->pending) { PMD_DRV_LOG(ERR, "Blocking transition since pending was %lx", o->pending); return ECORE_BUSY; } switch (state) { case ECORE_Q_STATE_RESET: if (cmd == ECORE_Q_CMD_INIT) next_state = ECORE_Q_STATE_INITIALIZED; break; case ECORE_Q_STATE_INITIALIZED: if (cmd == ECORE_Q_CMD_SETUP) { if (ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE, ¶ms->params.setup.flags)) next_state = ECORE_Q_STATE_ACTIVE; else next_state = ECORE_Q_STATE_INACTIVE; } break; case ECORE_Q_STATE_ACTIVE: if (cmd == ECORE_Q_CMD_DEACTIVATE) next_state = ECORE_Q_STATE_INACTIVE; else if ((cmd == ECORE_Q_CMD_EMPTY) || (cmd == ECORE_Q_CMD_UPDATE_TPA)) next_state = ECORE_Q_STATE_ACTIVE; else if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) { next_state = ECORE_Q_STATE_MULTI_COS; next_tx_only = 1; } else if (cmd == ECORE_Q_CMD_HALT) next_state = ECORE_Q_STATE_STOPPED; else if (cmd == ECORE_Q_CMD_UPDATE) { /* If "active" state change is requested, update the * state accordingly. */ if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update_params->update_flags) && !ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, &update_params->update_flags)) next_state = ECORE_Q_STATE_INACTIVE; else next_state = ECORE_Q_STATE_ACTIVE; } break; case ECORE_Q_STATE_MULTI_COS: if (cmd == ECORE_Q_CMD_TERMINATE) next_state = ECORE_Q_STATE_MCOS_TERMINATED; else if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) { next_state = ECORE_Q_STATE_MULTI_COS; next_tx_only = o->num_tx_only + 1; } else if ((cmd == ECORE_Q_CMD_EMPTY) || (cmd == ECORE_Q_CMD_UPDATE_TPA)) next_state = ECORE_Q_STATE_MULTI_COS; else if (cmd == ECORE_Q_CMD_UPDATE) { /* If "active" state change is requested, update the * state accordingly. */ if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update_params->update_flags) && !ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, &update_params->update_flags)) next_state = ECORE_Q_STATE_INACTIVE; else next_state = ECORE_Q_STATE_MULTI_COS; } break; case ECORE_Q_STATE_MCOS_TERMINATED: if (cmd == ECORE_Q_CMD_CFC_DEL) { next_tx_only = o->num_tx_only - 1; if (next_tx_only == 0) next_state = ECORE_Q_STATE_ACTIVE; else next_state = ECORE_Q_STATE_MULTI_COS; } break; case ECORE_Q_STATE_INACTIVE: if (cmd == ECORE_Q_CMD_ACTIVATE) next_state = ECORE_Q_STATE_ACTIVE; else if ((cmd == ECORE_Q_CMD_EMPTY) || (cmd == ECORE_Q_CMD_UPDATE_TPA)) next_state = ECORE_Q_STATE_INACTIVE; else if (cmd == ECORE_Q_CMD_HALT) next_state = ECORE_Q_STATE_STOPPED; else if (cmd == ECORE_Q_CMD_UPDATE) { /* If "active" state change is requested, update the * state accordingly. */ if (ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE_CHNG, &update_params->update_flags) && ECORE_TEST_BIT(ECORE_Q_UPDATE_ACTIVATE, &update_params->update_flags)) { if (o->num_tx_only == 0) next_state = ECORE_Q_STATE_ACTIVE; else /* tx only queues exist for this queue */ next_state = ECORE_Q_STATE_MULTI_COS; } else next_state = ECORE_Q_STATE_INACTIVE; } break; case ECORE_Q_STATE_STOPPED: if (cmd == ECORE_Q_CMD_TERMINATE) next_state = ECORE_Q_STATE_TERMINATED; break; case ECORE_Q_STATE_TERMINATED: if (cmd == ECORE_Q_CMD_CFC_DEL) next_state = ECORE_Q_STATE_RESET; break; default: PMD_DRV_LOG(ERR, "Illegal state: %d", state); } /* Transition is assured */ if (next_state != ECORE_Q_STATE_MAX) { ECORE_MSG("Good state transition: %d(%d)->%d", state, cmd, next_state); o->next_state = next_state; o->next_tx_only = next_tx_only; return ECORE_SUCCESS; } ECORE_MSG("Bad state transition request: %d %d", state, cmd); return ECORE_INVAL; } /** * ecore_queue_chk_fwd_transition - check state machine of a Forwarding Queue. * * @sc: device handle * @o: * @params: * * It both checks if the requested command is legal in a current * state and, if it's legal, sets a `next_state' in the object * that will be used in the completion flow to set the `state' * of the object. * * returns 0 if a requested command is a legal transition, * ECORE_INVAL otherwise. */ static int ecore_queue_chk_fwd_transition(struct bnx2x_softc *sc __rte_unused, struct ecore_queue_sp_obj *o, struct ecore_queue_state_params *params) { enum ecore_q_state state = o->state, next_state = ECORE_Q_STATE_MAX; enum ecore_queue_cmd cmd = params->cmd; switch (state) { case ECORE_Q_STATE_RESET: if (cmd == ECORE_Q_CMD_INIT) next_state = ECORE_Q_STATE_INITIALIZED; break; case ECORE_Q_STATE_INITIALIZED: if (cmd == ECORE_Q_CMD_SETUP_TX_ONLY) { if (ECORE_TEST_BIT(ECORE_Q_FLG_ACTIVE, ¶ms->params.tx_only.flags)) next_state = ECORE_Q_STATE_ACTIVE; else next_state = ECORE_Q_STATE_INACTIVE; } break; case ECORE_Q_STATE_ACTIVE: case ECORE_Q_STATE_INACTIVE: if (cmd == ECORE_Q_CMD_CFC_DEL) next_state = ECORE_Q_STATE_RESET; break; default: PMD_DRV_LOG(ERR, "Illegal state: %d", state); } /* Transition is assured */ if (next_state != ECORE_Q_STATE_MAX) { ECORE_MSG("Good state transition: %d(%d)->%d", state, cmd, next_state); o->next_state = next_state; return ECORE_SUCCESS; } ECORE_MSG("Bad state transition request: %d %d", state, cmd); return ECORE_INVAL; } void ecore_init_queue_obj(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *obj, uint8_t cl_id, uint32_t * cids, uint8_t cid_cnt, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, unsigned long type) { ECORE_MEMSET(obj, 0, sizeof(*obj)); /* We support only ECORE_MULTI_TX_COS Tx CoS at the moment */ ECORE_BUG_ON(ECORE_MULTI_TX_COS < cid_cnt); rte_memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt); obj->max_cos = cid_cnt; obj->cl_id = cl_id; obj->func_id = func_id; obj->rdata = rdata; obj->rdata_mapping = rdata_mapping; obj->type = type; obj->next_state = ECORE_Q_STATE_MAX; if (CHIP_IS_E1x(sc)) obj->send_cmd = ecore_queue_send_cmd_e1x; else obj->send_cmd = ecore_queue_send_cmd_e2; if (ECORE_TEST_BIT(ECORE_Q_TYPE_FWD, &type)) obj->check_transition = ecore_queue_chk_fwd_transition; else obj->check_transition = ecore_queue_chk_transition; obj->complete_cmd = ecore_queue_comp_cmd; obj->wait_comp = ecore_queue_wait_comp; obj->set_pending = ecore_queue_set_pending; } /********************** Function state object *********************************/ enum ecore_func_state ecore_func_get_state(__rte_unused struct bnx2x_softc *sc, struct ecore_func_sp_obj *o) { /* in the middle of transaction - return INVALID state */ if (o->pending) return ECORE_F_STATE_MAX; /* unsure the order of reading of o->pending and o->state * o->pending should be read first */ rmb(); return o->state; } static int ecore_func_wait_comp(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o, enum ecore_func_cmd cmd) { return ecore_state_wait(sc, cmd, &o->pending); } /** * ecore_func_state_change_comp - complete the state machine transition * * @sc: device handle * @o: * @cmd: * * Called on state change transition. Completes the state * machine transition only - no HW interaction. */ static int ecore_func_state_change_comp(struct bnx2x_softc *sc __rte_unused, struct ecore_func_sp_obj *o, enum ecore_func_cmd cmd) { unsigned long cur_pending = o->pending; if (!ECORE_TEST_AND_CLEAR_BIT(cmd, &cur_pending)) { PMD_DRV_LOG(ERR, "Bad MC reply %d for func %d in state %d pending 0x%lx, next_state %d", cmd, ECORE_FUNC_ID(sc), o->state, cur_pending, o->next_state); return ECORE_INVAL; } ECORE_MSG("Completing command %d for func %d, setting state to %d", cmd, ECORE_FUNC_ID(sc), o->next_state); o->state = o->next_state; o->next_state = ECORE_F_STATE_MAX; /* It's important that o->state and o->next_state are * updated before o->pending. */ wmb(); ECORE_CLEAR_BIT(cmd, &o->pending); ECORE_SMP_MB_AFTER_CLEAR_BIT(); return ECORE_SUCCESS; } /** * ecore_func_comp_cmd - complete the state change command * * @sc: device handle * @o: * @cmd: * * Checks that the arrived completion is expected. */ static int ecore_func_comp_cmd(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o, enum ecore_func_cmd cmd) { /* Complete the state machine part first, check if it's a * legal completion. */ int rc = ecore_func_state_change_comp(sc, o, cmd); return rc; } /** * ecore_func_chk_transition - perform function state machine transition * * @sc: device handle * @o: * @params: * * It both checks if the requested command is legal in a current * state and, if it's legal, sets a `next_state' in the object * that will be used in the completion flow to set the `state' * of the object. * * returns 0 if a requested command is a legal transition, * ECORE_INVAL otherwise. */ static int ecore_func_chk_transition(struct bnx2x_softc *sc __rte_unused, struct ecore_func_sp_obj *o, struct ecore_func_state_params *params) { enum ecore_func_state state = o->state, next_state = ECORE_F_STATE_MAX; enum ecore_func_cmd cmd = params->cmd; /* Forget all pending for completion commands if a driver only state * transition has been requested. */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { o->pending = 0; o->next_state = ECORE_F_STATE_MAX; } /* Don't allow a next state transition if we are in the middle of * the previous one. */ if (o->pending) return ECORE_BUSY; switch (state) { case ECORE_F_STATE_RESET: if (cmd == ECORE_F_CMD_HW_INIT) next_state = ECORE_F_STATE_INITIALIZED; break; case ECORE_F_STATE_INITIALIZED: if (cmd == ECORE_F_CMD_START) next_state = ECORE_F_STATE_STARTED; else if (cmd == ECORE_F_CMD_HW_RESET) next_state = ECORE_F_STATE_RESET; break; case ECORE_F_STATE_STARTED: if (cmd == ECORE_F_CMD_STOP) next_state = ECORE_F_STATE_INITIALIZED; /* afex ramrods can be sent only in started mode, and only * if not pending for function_stop ramrod completion * for these events - next state remained STARTED. */ else if ((cmd == ECORE_F_CMD_AFEX_UPDATE) && (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending))) next_state = ECORE_F_STATE_STARTED; else if ((cmd == ECORE_F_CMD_AFEX_VIFLISTS) && (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending))) next_state = ECORE_F_STATE_STARTED; /* Switch_update ramrod can be sent in either started or * tx_stopped state, and it doesn't change the state. */ else if ((cmd == ECORE_F_CMD_SWITCH_UPDATE) && (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending))) next_state = ECORE_F_STATE_STARTED; else if (cmd == ECORE_F_CMD_TX_STOP) next_state = ECORE_F_STATE_TX_STOPPED; break; case ECORE_F_STATE_TX_STOPPED: if ((cmd == ECORE_F_CMD_SWITCH_UPDATE) && (!ECORE_TEST_BIT(ECORE_F_CMD_STOP, &o->pending))) next_state = ECORE_F_STATE_TX_STOPPED; else if (cmd == ECORE_F_CMD_TX_START) next_state = ECORE_F_STATE_STARTED; break; default: PMD_DRV_LOG(ERR, "Unknown state: %d", state); } /* Transition is assured */ if (next_state != ECORE_F_STATE_MAX) { ECORE_MSG("Good function state transition: %d(%d)->%d", state, cmd, next_state); o->next_state = next_state; return ECORE_SUCCESS; } ECORE_MSG("Bad function state transition request: %d %d", state, cmd); return ECORE_INVAL; } /** * ecore_func_init_func - performs HW init at function stage * * @sc: device handle * @drv: * * Init HW when the current phase is * FW_MSG_CODE_DRV_LOAD_FUNCTION: initialize only FUNCTION-only * HW blocks. */ static int ecore_func_init_func(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { return drv->init_hw_func(sc); } /** * ecore_func_init_port - performs HW init at port stage * * @sc: device handle * @drv: * * Init HW when the current phase is * FW_MSG_CODE_DRV_LOAD_PORT: initialize PORT-only and * FUNCTION-only HW blocks. * */ static int ecore_func_init_port(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { int rc = drv->init_hw_port(sc); if (rc) return rc; return ecore_func_init_func(sc, drv); } /** * ecore_func_init_cmn_chip - performs HW init at chip-common stage * * @sc: device handle * @drv: * * Init HW when the current phase is * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON_CHIP, * PORT-only and FUNCTION-only HW blocks. */ static int ecore_func_init_cmn_chip(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { int rc = drv->init_hw_cmn_chip(sc); if (rc) return rc; return ecore_func_init_port(sc, drv); } /** * ecore_func_init_cmn - performs HW init at common stage * * @sc: device handle * @drv: * * Init HW when the current phase is * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: initialize COMMON, * PORT-only and FUNCTION-only HW blocks. */ static int ecore_func_init_cmn(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { int rc = drv->init_hw_cmn(sc); if (rc) return rc; return ecore_func_init_port(sc, drv); } static int ecore_func_hw_init(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { uint32_t load_code = params->params.hw_init.load_phase; struct ecore_func_sp_obj *o = params->f_obj; const struct ecore_func_sp_drv_ops *drv = o->drv; int rc = 0; ECORE_MSG("function %d load_code %x", ECORE_ABS_FUNC_ID(sc), load_code); /* Prepare FW */ rc = drv->init_fw(sc); if (rc) { PMD_DRV_LOG(ERR, "Error loading firmware"); goto init_err; } /* Handle the beginning of COMMON_XXX pases separately... */ switch (load_code) { case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: rc = ecore_func_init_cmn_chip(sc, drv); if (rc) goto init_err; break; case FW_MSG_CODE_DRV_LOAD_COMMON: rc = ecore_func_init_cmn(sc, drv); if (rc) goto init_err; break; case FW_MSG_CODE_DRV_LOAD_PORT: rc = ecore_func_init_port(sc, drv); if (rc) goto init_err; break; case FW_MSG_CODE_DRV_LOAD_FUNCTION: rc = ecore_func_init_func(sc, drv); if (rc) goto init_err; break; default: PMD_DRV_LOG(ERR, "Unknown load_code (0x%x) from MCP", load_code); rc = ECORE_INVAL; } init_err: /* In case of success, complete the command immediately: no ramrods * have been sent. */ if (!rc) o->complete_cmd(sc, o, ECORE_F_CMD_HW_INIT); return rc; } /** * ecore_func_reset_func - reset HW at function stage * * @sc: device handle * @drv: * * Reset HW at FW_MSG_CODE_DRV_UNLOAD_FUNCTION stage: reset only * FUNCTION-only HW blocks. */ static void ecore_func_reset_func(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { drv->reset_hw_func(sc); } /** * ecore_func_reset_port - reser HW at port stage * * @sc: device handle * @drv: * * Reset HW at FW_MSG_CODE_DRV_UNLOAD_PORT stage: reset * FUNCTION-only and PORT-only HW blocks. * * !!!IMPORTANT!!! * * It's important to call reset_port before reset_func() as the last thing * reset_func does is pf_disable() thus disabling PGLUE_B, which * makes impossible any DMAE transactions. */ static void ecore_func_reset_port(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { drv->reset_hw_port(sc); ecore_func_reset_func(sc, drv); } /** * ecore_func_reset_cmn - reser HW at common stage * * @sc: device handle * @drv: * * Reset HW at FW_MSG_CODE_DRV_UNLOAD_COMMON and * FW_MSG_CODE_DRV_UNLOAD_COMMON_CHIP stages: reset COMMON, * COMMON_CHIP, FUNCTION-only and PORT-only HW blocks. */ static void ecore_func_reset_cmn(struct bnx2x_softc *sc, const struct ecore_func_sp_drv_ops *drv) { ecore_func_reset_port(sc, drv); drv->reset_hw_cmn(sc); } static int ecore_func_hw_reset(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { uint32_t reset_phase = params->params.hw_reset.reset_phase; struct ecore_func_sp_obj *o = params->f_obj; const struct ecore_func_sp_drv_ops *drv = o->drv; ECORE_MSG("function %d reset_phase %x", ECORE_ABS_FUNC_ID(sc), reset_phase); switch (reset_phase) { case FW_MSG_CODE_DRV_UNLOAD_COMMON: ecore_func_reset_cmn(sc, drv); break; case FW_MSG_CODE_DRV_UNLOAD_PORT: ecore_func_reset_port(sc, drv); break; case FW_MSG_CODE_DRV_UNLOAD_FUNCTION: ecore_func_reset_func(sc, drv); break; default: PMD_DRV_LOG(ERR, "Unknown reset_phase (0x%x) from MCP", reset_phase); break; } /* Complete the command immediately: no ramrods have been sent. */ o->complete_cmd(sc, o, ECORE_F_CMD_HW_RESET); return ECORE_SUCCESS; } static int ecore_func_send_start(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; struct function_start_data *rdata = (struct function_start_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; struct ecore_func_start_params *start_params = ¶ms->params.start; ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data with provided parameters */ rdata->function_mode = (uint8_t) start_params->mf_mode; rdata->sd_vlan_tag = ECORE_CPU_TO_LE16(start_params->sd_vlan_tag); rdata->path_id = ECORE_PATH_ID(sc); rdata->network_cos_mode = start_params->network_cos_mode; rdata->gre_tunnel_mode = start_params->gre_tunnel_mode; rdata->gre_tunnel_rss = start_params->gre_tunnel_rss; /* * No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_START, 0, data_mapping, NONE_CONNECTION_TYPE); } static int ecore_func_send_switch_update(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; struct function_update_data *rdata = (struct function_update_data *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; struct ecore_func_switch_update_params *switch_update_params = ¶ms->params.switch_update; ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data with provided parameters */ rdata->tx_switch_suspend_change_flg = 1; rdata->tx_switch_suspend = switch_update_params->suspend; rdata->echo = SWITCH_UPDATE; return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0, data_mapping, NONE_CONNECTION_TYPE); } static int ecore_func_send_afex_update(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; struct function_update_data *rdata = (struct function_update_data *)o->afex_rdata; ecore_dma_addr_t data_mapping = o->afex_rdata_mapping; struct ecore_func_afex_update_params *afex_update_params = ¶ms->params.afex_update; ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data with provided parameters */ rdata->vif_id_change_flg = 1; rdata->vif_id = ECORE_CPU_TO_LE16(afex_update_params->vif_id); rdata->afex_default_vlan_change_flg = 1; rdata->afex_default_vlan = ECORE_CPU_TO_LE16(afex_update_params->afex_default_vlan); rdata->allowed_priorities_change_flg = 1; rdata->allowed_priorities = afex_update_params->allowed_priorities; rdata->echo = AFEX_UPDATE; /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ ECORE_MSG("afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x", rdata->vif_id, rdata->afex_default_vlan, rdata->allowed_priorities); return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0, data_mapping, NONE_CONNECTION_TYPE); } static inline int ecore_func_send_afex_viflists(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; struct afex_vif_list_ramrod_data *rdata = (struct afex_vif_list_ramrod_data *)o->afex_rdata; struct ecore_func_afex_viflists_params *afex_vif_params = ¶ms->params.afex_viflists; uint64_t *p_rdata = (uint64_t *) rdata; ECORE_MEMSET(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data with provided parameters */ rdata->vif_list_index = ECORE_CPU_TO_LE16(afex_vif_params->vif_list_index); rdata->func_bit_map = afex_vif_params->func_bit_map; rdata->afex_vif_list_command = afex_vif_params->afex_vif_list_command; rdata->func_to_clear = afex_vif_params->func_to_clear; /* send in echo type of sub command */ rdata->echo = afex_vif_params->afex_vif_list_command; /* No need for an explicit memory barrier here as long we would * need to ensure the ordering of writing to the SPQ element * and updating of the SPQ producer which involves a memory * read and we will have to put a full memory barrier there * (inside ecore_sp_post()). */ ECORE_MSG ("afex: ramrod lists, cmd 0x%x index 0x%x func_bit_map 0x%x func_to_clr 0x%x", rdata->afex_vif_list_command, rdata->vif_list_index, rdata->func_bit_map, rdata->func_to_clear); /* this ramrod sends data directly and not through DMA mapping */ return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_AFEX_VIF_LISTS, 0, *p_rdata, NONE_CONNECTION_TYPE); } static int ecore_func_send_stop(struct bnx2x_softc *sc, __rte_unused struct ecore_func_state_params *params) { return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_FUNCTION_STOP, 0, 0, NONE_CONNECTION_TYPE); } static int ecore_func_send_tx_stop(struct bnx2x_softc *sc, __rte_unused struct ecore_func_state_params *params) { return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC, 0, 0, NONE_CONNECTION_TYPE); } static int ecore_func_send_tx_start(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; struct flow_control_configuration *rdata = (struct flow_control_configuration *)o->rdata; ecore_dma_addr_t data_mapping = o->rdata_mapping; struct ecore_func_tx_start_params *tx_start_params = ¶ms->params.tx_start; uint32_t i; ECORE_MEMSET(rdata, 0, sizeof(*rdata)); rdata->dcb_enabled = tx_start_params->dcb_enabled; rdata->dcb_version = tx_start_params->dcb_version; rdata->dont_add_pri_0 = tx_start_params->dont_add_pri_0; for (i = 0; i < ARRAY_SIZE(rdata->traffic_type_to_priority_cos); i++) rdata->traffic_type_to_priority_cos[i] = tx_start_params->traffic_type_to_priority_cos[i]; return ecore_sp_post(sc, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0, data_mapping, NONE_CONNECTION_TYPE); } static int ecore_func_send_cmd(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { switch (params->cmd) { case ECORE_F_CMD_HW_INIT: return ecore_func_hw_init(sc, params); case ECORE_F_CMD_START: return ecore_func_send_start(sc, params); case ECORE_F_CMD_STOP: return ecore_func_send_stop(sc, params); case ECORE_F_CMD_HW_RESET: return ecore_func_hw_reset(sc, params); case ECORE_F_CMD_AFEX_UPDATE: return ecore_func_send_afex_update(sc, params); case ECORE_F_CMD_AFEX_VIFLISTS: return ecore_func_send_afex_viflists(sc, params); case ECORE_F_CMD_TX_STOP: return ecore_func_send_tx_stop(sc, params); case ECORE_F_CMD_TX_START: return ecore_func_send_tx_start(sc, params); case ECORE_F_CMD_SWITCH_UPDATE: return ecore_func_send_switch_update(sc, params); default: PMD_DRV_LOG(ERR, "Unknown command: %d", params->cmd); return ECORE_INVAL; } } void ecore_init_func_obj(__rte_unused struct bnx2x_softc *sc, struct ecore_func_sp_obj *obj, void *rdata, ecore_dma_addr_t rdata_mapping, void *afex_rdata, ecore_dma_addr_t afex_rdata_mapping, struct ecore_func_sp_drv_ops *drv_iface) { ECORE_MEMSET(obj, 0, sizeof(*obj)); ECORE_MUTEX_INIT(&obj->one_pending_mutex); obj->rdata = rdata; obj->rdata_mapping = rdata_mapping; obj->afex_rdata = afex_rdata; obj->afex_rdata_mapping = afex_rdata_mapping; obj->send_cmd = ecore_func_send_cmd; obj->check_transition = ecore_func_chk_transition; obj->complete_cmd = ecore_func_comp_cmd; obj->wait_comp = ecore_func_wait_comp; obj->drv = drv_iface; } /** * ecore_func_state_change - perform Function state change transition * * @sc: device handle * @params: parameters to perform the transaction * * returns 0 in case of successfully completed transition, * negative error code in case of failure, positive * (EBUSY) value if there is a completion to that is * still pending (possible only if RAMROD_COMP_WAIT is * not set in params->ramrod_flags for asynchronous * commands). */ int ecore_func_state_change(struct bnx2x_softc *sc, struct ecore_func_state_params *params) { struct ecore_func_sp_obj *o = params->f_obj; int rc, cnt = 300; enum ecore_func_cmd cmd = params->cmd; unsigned long *pending = &o->pending; ECORE_MUTEX_LOCK(&o->one_pending_mutex); /* Check that the requested transition is legal */ rc = o->check_transition(sc, o, params); if ((rc == ECORE_BUSY) && (ECORE_TEST_BIT(RAMROD_RETRY, ¶ms->ramrod_flags))) { while ((rc == ECORE_BUSY) && (--cnt > 0)) { ECORE_MUTEX_UNLOCK(&o->one_pending_mutex); ECORE_MSLEEP(10); ECORE_MUTEX_LOCK(&o->one_pending_mutex); rc = o->check_transition(sc, o, params); } if (rc == ECORE_BUSY) { ECORE_MUTEX_UNLOCK(&o->one_pending_mutex); PMD_DRV_LOG(ERR, "timeout waiting for previous ramrod completion"); return rc; } } else if (rc) { ECORE_MUTEX_UNLOCK(&o->one_pending_mutex); return rc; } /* Set "pending" bit */ ECORE_SET_BIT(cmd, pending); /* Don't send a command if only driver cleanup was requested */ if (ECORE_TEST_BIT(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { ecore_func_state_change_comp(sc, o, cmd); ECORE_MUTEX_UNLOCK(&o->one_pending_mutex); } else { /* Send a ramrod */ rc = o->send_cmd(sc, params); ECORE_MUTEX_UNLOCK(&o->one_pending_mutex); if (rc) { o->next_state = ECORE_F_STATE_MAX; ECORE_CLEAR_BIT(cmd, pending); ECORE_SMP_MB_AFTER_CLEAR_BIT(); return rc; } if (ECORE_TEST_BIT(RAMROD_COMP_WAIT, ¶ms->ramrod_flags)) { rc = o->wait_comp(sc, o, cmd); if (rc) return rc; return ECORE_SUCCESS; } } return ECORE_RET_PENDING(cmd, pending); } /****************************************************************************** * Description: * Calculates crc 8 on a word value: polynomial 0-1-2-8 * Code was translated from Verilog. * Return: *****************************************************************************/ uint8_t ecore_calc_crc8(uint32_t data, uint8_t crc) { uint8_t D[32]; uint8_t NewCRC[8]; uint8_t C[8]; uint8_t crc_res; uint8_t i; /* split the data into 31 bits */ for (i = 0; i < 32; i++) { D[i] = (uint8_t) (data & 1); data = data >> 1; } /* split the crc into 8 bits */ for (i = 0; i < 8; i++) { C[i] = crc & 1; crc = crc >> 1; } NewCRC[0] = D[31] ^ D[30] ^ D[28] ^ D[23] ^ D[21] ^ D[19] ^ D[18] ^ D[16] ^ D[14] ^ D[12] ^ D[8] ^ D[7] ^ D[6] ^ D[0] ^ C[4] ^ C[6] ^ C[7]; NewCRC[1] = D[30] ^ D[29] ^ D[28] ^ D[24] ^ D[23] ^ D[22] ^ D[21] ^ D[20] ^ D[18] ^ D[17] ^ D[16] ^ D[15] ^ D[14] ^ D[13] ^ D[12] ^ D[9] ^ D[6] ^ D[1] ^ D[0] ^ C[0] ^ C[4] ^ C[5] ^ C[6]; NewCRC[2] = D[29] ^ D[28] ^ D[25] ^ D[24] ^ D[22] ^ D[17] ^ D[15] ^ D[13] ^ D[12] ^ D[10] ^ D[8] ^ D[6] ^ D[2] ^ D[1] ^ D[0] ^ C[0] ^ C[1] ^ C[4] ^ C[5]; NewCRC[3] = D[30] ^ D[29] ^ D[26] ^ D[25] ^ D[23] ^ D[18] ^ D[16] ^ D[14] ^ D[13] ^ D[11] ^ D[9] ^ D[7] ^ D[3] ^ D[2] ^ D[1] ^ C[1] ^ C[2] ^ C[5] ^ C[6]; NewCRC[4] = D[31] ^ D[30] ^ D[27] ^ D[26] ^ D[24] ^ D[19] ^ D[17] ^ D[15] ^ D[14] ^ D[12] ^ D[10] ^ D[8] ^ D[4] ^ D[3] ^ D[2] ^ C[0] ^ C[2] ^ C[3] ^ C[6] ^ C[7]; NewCRC[5] = D[31] ^ D[28] ^ D[27] ^ D[25] ^ D[20] ^ D[18] ^ D[16] ^ D[15] ^ D[13] ^ D[11] ^ D[9] ^ D[5] ^ D[4] ^ D[3] ^ C[1] ^ C[3] ^ C[4] ^ C[7]; NewCRC[6] = D[29] ^ D[28] ^ D[26] ^ D[21] ^ D[19] ^ D[17] ^ D[16] ^ D[14] ^ D[12] ^ D[10] ^ D[6] ^ D[5] ^ D[4] ^ C[2] ^ C[4] ^ C[5]; NewCRC[7] = D[30] ^ D[29] ^ D[27] ^ D[22] ^ D[20] ^ D[18] ^ D[17] ^ D[15] ^ D[13] ^ D[11] ^ D[7] ^ D[6] ^ D[5] ^ C[3] ^ C[5] ^ C[6]; crc_res = 0; for (i = 0; i < 8; i++) { crc_res |= (NewCRC[i] << i); } return crc_res; } uint32_t ecore_calc_crc32(uint32_t crc, uint8_t const *p, uint32_t len, uint32_t magic) { int i; while (len--) { crc ^= *p++; for (i = 0; i < 8; i++) crc = (crc >> 1) ^ ((crc & 1) ? magic : 0); } return crc; } ================================================ FILE: drivers/net/bnx2x/ecore_sp.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ECORE_SP_H #define ECORE_SP_H #if __BYTE_ORDER == __LITTLE_ENDIAN #ifndef LITTLE_ENDIAN #define LITTLE_ENDIAN #endif #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN #endif #undef BIG_ENDIAN #undef __BIG_ENDIAN #else /* _BIG_ENDIAN */ #ifndef BIG_ENDIAN #define BIG_ENDIAN #endif #ifndef __BIG_ENDIAN #define __BIG_ENDIAN #endif #undef LITTLE_ENDIAN #undef __LITTLE_ENDIAN #endif #include "ecore_mfw_req.h" #include "ecore_fw_defs.h" #include "ecore_hsi.h" #include "ecore_reg.h" struct bnx2x_softc; typedef phys_addr_t ecore_dma_addr_t; /* expected to be 64 bit wide */ typedef volatile int ecore_atomic_t; #define ETH_ALEN ETHER_ADDR_LEN /* 6 */ #define ECORE_SWCID_SHIFT 17 #define ECORE_SWCID_MASK ((0x1 << ECORE_SWCID_SHIFT) - 1) #define ECORE_MC_HASH_SIZE 8 #define ECORE_MC_HASH_OFFSET(sc, i) \ (BAR_TSTRORM_INTMEM + \ TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(FUNC_ID(sc)) + i*4) #define ECORE_MAX_MULTICAST 64 #define ECORE_MAX_EMUL_MULTI 1 #define IRO sc->iro_array typedef rte_spinlock_t ECORE_MUTEX; #define ECORE_MUTEX_INIT(_mutex) rte_spinlock_init(_mutex) #define ECORE_MUTEX_LOCK(_mutex) rte_spinlock_lock(_mutex) #define ECORE_MUTEX_UNLOCK(_mutex) rte_spinlock_unlock(_mutex) typedef rte_spinlock_t ECORE_MUTEX_SPIN; #define ECORE_SPIN_LOCK_INIT(_spin, _sc) rte_spinlock_init(_spin) #define ECORE_SPIN_LOCK_BH(_spin) rte_spinlock_lock(_spin) /* bh = bottom-half */ #define ECORE_SPIN_UNLOCK_BH(_spin) rte_spinlock_unlock(_spin) /* bh = bottom-half */ #define ECORE_SMP_MB_AFTER_CLEAR_BIT() mb() #define ECORE_SMP_MB_BEFORE_CLEAR_BIT() mb() #define ECORE_SMP_MB() mb() #define ECORE_SMP_RMB() rmb() #define ECORE_SMP_WMB() wmb() #define ECORE_MMIOWB() wmb() #define ECORE_SET_BIT_NA(bit, var) (*var |= (1 << bit)) #define ECORE_CLEAR_BIT_NA(bit, var) (*var &= ~(1 << bit)) #define ECORE_TEST_BIT(bit, var) bnx2x_test_bit(bit, var) #define ECORE_SET_BIT(bit, var) bnx2x_set_bit(bit, var) #define ECORE_CLEAR_BIT(bit, var) bnx2x_clear_bit(bit, var) #define ECORE_TEST_AND_CLEAR_BIT(bit, var) bnx2x_test_and_clear_bit(bit, var) #define atomic_load_acq_int (int)* #define atomic_store_rel_int(a, v) (*a = v) #define atomic_cmpset_acq_int(a, o, n) ((*a = (o & (n)) | (n)) ^ o) #define atomic_load_acq_long (long)* #define atomic_store_rel_long(a, v) (*a = v) #define atomic_set_acq_long(a, v) (*a |= v) #define atomic_clear_acq_long(a, v) (*a &= ~v) #define atomic_cmpset_acq_long(a, o, n) ((*a = (o & (n)) | (n)) ^ o) #define atomic_subtract_acq_long(a, v) (*a -= v) #define atomic_add_acq_long(a, v) (*a += v) #define ECORE_ATOMIC_READ(a) atomic_load_acq_int((volatile int *)a) #define ECORE_ATOMIC_SET(a, v) atomic_store_rel_int((volatile int *)a, v) #define ECORE_ATOMIC_CMPXCHG(a, o, n) bnx2x_cmpxchg((volatile int *)a, o, n) #define ECORE_RET_PENDING(pending_bit, pending) \ (ECORE_TEST_BIT(pending_bit, pending) ? ECORE_PENDING : ECORE_SUCCESS) #define ECORE_SET_FLAG(value, mask, flag) \ do { \ (value) &= ~(mask); \ (value) |= ((flag) << (mask##_SHIFT)); \ } while (0) #define ECORE_GET_FLAG(value, mask) \ (((value) &= (mask)) >> (mask##_SHIFT)) #define ECORE_MIGHT_SLEEP() #define ECORE_FCOE_CID(sc) ((sc)->fp[FCOE_IDX(sc)].cl_id) #define ECORE_MEMCMP(_a, _b, _s) memcmp(_a, _b, _s) #define ECORE_MEMCPY(_a, _b, _s) (void)rte_memcpy(_a, _b, _s) #define ECORE_MEMSET(_a, _c, _s) memset(_a, _c, _s) #define ECORE_CPU_TO_LE16(x) htole16(x) #define ECORE_CPU_TO_LE32(x) htole32(x) #define ECORE_WAIT(_s, _t) DELAY(1000) #define ECORE_MSLEEP(_t) DELAY((_t) * 1000) #define ECORE_LIKELY(x) likely(x) #define ECORE_UNLIKELY(x) unlikely(x) #define ECORE_ZALLOC(_size, _flags, _sc) \ rte_zmalloc("", _size, RTE_CACHE_LINE_SIZE) #define ECORE_CALLOC(_len, _size, _flags, _sc) \ rte_calloc("", _len, _size, RTE_CACHE_LINE_SIZE) #define ECORE_FREE(_s, _buf, _size) \ rte_free(_buf) #define SC_ILT(sc) ((sc)->ilt) #define ILOG2(x) bnx2x_ilog2(x) #define ECORE_ILT_ZALLOC(x, y, size, str) \ do { \ x = rte_malloc("", sizeof(struct bnx2x_dma), RTE_CACHE_LINE_SIZE); \ if (x) { \ if (bnx2x_dma_alloc((struct bnx2x_softc *)sc, \ size, (struct bnx2x_dma *)x, \ str, RTE_CACHE_LINE_SIZE) != 0) { \ rte_free(x); \ x = NULL; \ *y = 0; \ } else { \ *y = ((struct bnx2x_dma *)x)->paddr; \ } \ } \ } while (0) #define ECORE_ILT_FREE(x, y, size) \ do { \ if (x) { \ rte_free(x); \ x = NULL; \ y = 0; \ } \ } while (0) #define ECORE_IS_VALID_ETHER_ADDR(_mac) TRUE #define ECORE_IS_MF_SD_MODE IS_MF_SD_MODE #define ECORE_IS_MF_SI_MODE IS_MF_SI_MODE #define ECORE_IS_MF_AFEX_MODE IS_MF_AFEX_MODE #define ECORE_SET_CTX_VALIDATION bnx2x_set_ctx_validation #define ECORE_UPDATE_COALESCE_SB_INDEX bnx2x_update_coalesce_sb_index #define ECORE_ALIGN(x, a) ((((x) + (a) - 1) / (a)) * (a)) #define ECORE_REG_WR_DMAE_LEN REG_WR_DMAE_LEN #define ECORE_PATH_ID SC_PATH #define ECORE_PORT_ID SC_PORT #define ECORE_FUNC_ID SC_FUNC #define ECORE_ABS_FUNC_ID SC_ABS_FUNC #define CRCPOLY_LE 0xedb88320 uint32_t ecore_calc_crc32(uint32_t crc, uint8_t const *p, uint32_t len, uint32_t magic); uint8_t ecore_calc_crc8(uint32_t data, uint8_t crc); static inline uint32_t ECORE_CRC32_LE(uint32_t seed, uint8_t *mac, uint32_t len) { return ecore_calc_crc32(seed, mac, len, CRCPOLY_LE); } #define ecore_sp_post(_sc, _a, _b, _c, _d) \ bnx2x_sp_post(_sc, _a, _b, U64_HI(_c), U64_LO(_c), _d) #define ECORE_DBG_BREAK_IF(exp) \ do { \ if (unlikely(exp)) { \ rte_panic("ECORE"); \ } \ } while (0) #define ECORE_BUG() \ do { \ rte_panic("BUG (%s:%d)", __FILE__, __LINE__); \ } while(0); #define ECORE_BUG_ON(exp) \ do { \ if (likely(exp)) { \ rte_panic("BUG_ON (%s:%d)", __FILE__, __LINE__); \ } \ } while (0) #define ECORE_MSG(m, ...) \ PMD_DRV_LOG(DEBUG, m, ##__VA_ARGS__) typedef struct _ecore_list_entry_t { struct _ecore_list_entry_t *next, *prev; } ecore_list_entry_t; typedef struct ecore_list_t { ecore_list_entry_t *head, *tail; unsigned long cnt; } ecore_list_t; /* initialize the list */ #define ECORE_LIST_INIT(_list) \ do { \ (_list)->head = NULL; \ (_list)->tail = NULL; \ (_list)->cnt = 0; \ } while (0) /* return TRUE if the element is the last on the list */ #define ECORE_LIST_IS_LAST(_elem, _list) \ (_elem == (_list)->tail) /* return TRUE if the list is empty */ #define ECORE_LIST_IS_EMPTY(_list) \ ((_list)->cnt == 0) /* return the first element */ #define ECORE_LIST_FIRST_ENTRY(_list, cast, _link) \ (cast *)((_list)->head) /* return the next element */ #define ECORE_LIST_NEXT(_elem, _link, cast) \ (cast *)((&((_elem)->_link))->next) /* push an element on the head of the list */ #define ECORE_LIST_PUSH_HEAD(_elem, _list) \ do { \ (_elem)->prev = (ecore_list_entry_t *)0; \ (_elem)->next = (_list)->head; \ if ((_list)->tail == (ecore_list_entry_t *)0) { \ (_list)->tail = (_elem); \ } else { \ (_list)->head->prev = (_elem); \ } \ (_list)->head = (_elem); \ (_list)->cnt++; \ } while (0) /* push an element on the tail of the list */ #define ECORE_LIST_PUSH_TAIL(_elem, _list) \ do { \ (_elem)->next = (ecore_list_entry_t *)0; \ (_elem)->prev = (_list)->tail; \ if ((_list)->tail) { \ (_list)->tail->next = (_elem); \ } else { \ (_list)->head = (_elem); \ } \ (_list)->tail = (_elem); \ (_list)->cnt++; \ } while (0) /* push list1 on the head of list2 and return with list1 as empty */ #define ECORE_LIST_SPLICE_INIT(_list1, _list2) \ do { \ (_list1)->tail->next = (_list2)->head; \ if ((_list2)->head) { \ (_list2)->head->prev = (_list1)->tail; \ } else { \ (_list2)->tail = (_list1)->tail; \ } \ (_list2)->head = (_list1)->head; \ (_list2)->cnt += (_list1)->cnt; \ (_list1)->head = NULL; \ (_list1)->tail = NULL; \ (_list1)->cnt = 0; \ } while (0) /* remove an element from the list */ #define ECORE_LIST_REMOVE_ENTRY(_elem, _list) \ do { \ if ((_list)->head == (_elem)) { \ if ((_list)->head) { \ (_list)->head = (_list)->head->next; \ if ((_list)->head) { \ (_list)->head->prev = (ecore_list_entry_t *)0; \ } else { \ (_list)->tail = (ecore_list_entry_t *)0; \ } \ (_list)->cnt--; \ } \ } else if ((_list)->tail == (_elem)) { \ if ((_list)->tail) { \ (_list)->tail = (_list)->tail->prev; \ if ((_list)->tail) { \ (_list)->tail->next = (ecore_list_entry_t *)0; \ } else { \ (_list)->head = (ecore_list_entry_t *)0; \ } \ (_list)->cnt--; \ } \ } else { \ (_elem)->prev->next = (_elem)->next; \ (_elem)->next->prev = (_elem)->prev; \ (_list)->cnt--; \ } \ } while (0) /* walk the list */ #define ECORE_LIST_FOR_EACH_ENTRY(pos, _list, _link, cast) \ for (pos = ECORE_LIST_FIRST_ENTRY(_list, cast, _link); \ pos; \ pos = ECORE_LIST_NEXT(pos, _link, cast)) /* walk the list (safely) */ #define ECORE_LIST_FOR_EACH_ENTRY_SAFE(pos, n, _list, _link, cast) \ for (pos = ECORE_LIST_FIRST_ENTRY(_list, cast, _lint), \ n = (pos) ? ECORE_LIST_NEXT(pos, _link, cast) : NULL; \ pos != NULL; \ pos = (cast *)n, \ n = (pos) ? ECORE_LIST_NEXT(pos, _link, cast) : NULL) /* Manipulate a bit vector defined as an array of uint64_t */ /* Number of bits in one sge_mask array element */ #define BIT_VEC64_ELEM_SZ 64 #define BIT_VEC64_ELEM_SHIFT 6 #define BIT_VEC64_ELEM_MASK ((uint64_t)BIT_VEC64_ELEM_SZ - 1) #define __BIT_VEC64_SET_BIT(el, bit) \ do { \ el = ((el) | ((uint64_t)0x1 << (bit))); \ } while (0) #define __BIT_VEC64_CLEAR_BIT(el, bit) \ do { \ el = ((el) & (~((uint64_t)0x1 << (bit)))); \ } while (0) #define BIT_VEC64_SET_BIT(vec64, idx) \ __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \ (idx) & BIT_VEC64_ELEM_MASK) #define BIT_VEC64_CLEAR_BIT(vec64, idx) \ __BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \ (idx) & BIT_VEC64_ELEM_MASK) #define BIT_VEC64_TEST_BIT(vec64, idx) \ (((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \ ((idx) & BIT_VEC64_ELEM_MASK)) & 0x1) /* * Creates a bitmask of all ones in less significant bits. * idx - index of the most significant bit in the created mask */ #define BIT_VEC64_ONES_MASK(idx) \ (((uint64_t)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1) #define BIT_VEC64_ELEM_ONE_MASK ((uint64_t)(~0)) /* fill in a MAC address the way the FW likes it */ static inline void ecore_set_fw_mac_addr(uint16_t *fw_hi, uint16_t *fw_mid, uint16_t *fw_lo, uint8_t *mac) { ((uint8_t *)fw_hi)[0] = mac[1]; ((uint8_t *)fw_hi)[1] = mac[0]; ((uint8_t *)fw_mid)[0] = mac[3]; ((uint8_t *)fw_mid)[1] = mac[2]; ((uint8_t *)fw_lo)[0] = mac[5]; ((uint8_t *)fw_lo)[1] = mac[4]; } enum ecore_status_t { ECORE_EXISTS = -6, ECORE_IO = -5, ECORE_TIMEOUT = -4, ECORE_INVAL = -3, ECORE_BUSY = -2, ECORE_NOMEM = -1, ECORE_SUCCESS = 0, /* PENDING is not an error and should be positive */ ECORE_PENDING = 1, }; enum { SWITCH_UPDATE, AFEX_UPDATE, }; struct bnx2x_softc; struct eth_context; /* Bits representing general command's configuration */ enum { RAMROD_TX, RAMROD_RX, /* Wait until all pending commands complete */ RAMROD_COMP_WAIT, /* Don't send a ramrod, only update a registry */ RAMROD_DRV_CLR_ONLY, /* Configure HW according to the current object state */ RAMROD_RESTORE, /* Execute the next command now */ RAMROD_EXEC, /* Don't add a new command and continue execution of posponed * commands. If not set a new command will be added to the * pending commands list. */ RAMROD_CONT, /* If there is another pending ramrod, wait until it finishes and * re-try to submit this one. This flag can be set only in sleepable * context, and should not be set from the context that completes the * ramrods as deadlock will occur. */ RAMROD_RETRY, }; typedef enum { ECORE_OBJ_TYPE_RX, ECORE_OBJ_TYPE_TX, ECORE_OBJ_TYPE_RX_TX, } ecore_obj_type; /* Public slow path states */ enum { ECORE_FILTER_MAC_PENDING, ECORE_FILTER_VLAN_PENDING, ECORE_FILTER_VLAN_MAC_PENDING, ECORE_FILTER_RX_MODE_PENDING, ECORE_FILTER_RX_MODE_SCHED, ECORE_FILTER_ISCSI_ETH_START_SCHED, ECORE_FILTER_ISCSI_ETH_STOP_SCHED, ECORE_FILTER_FCOE_ETH_START_SCHED, ECORE_FILTER_FCOE_ETH_STOP_SCHED, ECORE_FILTER_MCAST_PENDING, ECORE_FILTER_MCAST_SCHED, ECORE_FILTER_RSS_CONF_PENDING, ECORE_AFEX_FCOE_Q_UPDATE_PENDING, ECORE_AFEX_PENDING_VIFSET_MCP_ACK }; struct ecore_raw_obj { uint8_t func_id; /* Queue params */ uint8_t cl_id; uint32_t cid; /* Ramrod data buffer params */ void *rdata; ecore_dma_addr_t rdata_mapping; /* Ramrod state params */ int state; /* "ramrod is pending" state bit */ unsigned long *pstate; /* pointer to state buffer */ ecore_obj_type obj_type; int (*wait_comp)(struct bnx2x_softc *sc, struct ecore_raw_obj *o); int (*check_pending)(struct ecore_raw_obj *o); void (*clear_pending)(struct ecore_raw_obj *o); void (*set_pending)(struct ecore_raw_obj *o); }; /************************* VLAN-MAC commands related parameters ***************/ struct ecore_mac_ramrod_data { uint8_t mac[ETH_ALEN]; uint8_t is_inner_mac; }; struct ecore_vlan_ramrod_data { uint16_t vlan; }; struct ecore_vlan_mac_ramrod_data { uint8_t mac[ETH_ALEN]; uint8_t is_inner_mac; uint16_t vlan; }; union ecore_classification_ramrod_data { struct ecore_mac_ramrod_data mac; struct ecore_vlan_ramrod_data vlan; struct ecore_vlan_mac_ramrod_data vlan_mac; }; /* VLAN_MAC commands */ enum ecore_vlan_mac_cmd { ECORE_VLAN_MAC_ADD, ECORE_VLAN_MAC_DEL, ECORE_VLAN_MAC_MOVE, }; struct ecore_vlan_mac_data { /* Requested command: ECORE_VLAN_MAC_XX */ enum ecore_vlan_mac_cmd cmd; /* used to contain the data related vlan_mac_flags bits from * ramrod parameters. */ unsigned long vlan_mac_flags; /* Needed for MOVE command */ struct ecore_vlan_mac_obj *target_obj; union ecore_classification_ramrod_data u; }; /*************************** Exe Queue obj ************************************/ union ecore_exe_queue_cmd_data { struct ecore_vlan_mac_data vlan_mac; struct { } mcast; }; struct ecore_exeq_elem { ecore_list_entry_t link; /* Length of this element in the exe_chunk. */ int cmd_len; union ecore_exe_queue_cmd_data cmd_data; }; union ecore_qable_obj; union ecore_exeq_comp_elem { union event_ring_elem *elem; }; struct ecore_exe_queue_obj; typedef int (*exe_q_validate)(struct bnx2x_softc *sc, union ecore_qable_obj *o, struct ecore_exeq_elem *elem); typedef int (*exe_q_remove)(struct bnx2x_softc *sc, union ecore_qable_obj *o, struct ecore_exeq_elem *elem); /* Return positive if entry was optimized, 0 - if not, negative * in case of an error. */ typedef int (*exe_q_optimize)(struct bnx2x_softc *sc, union ecore_qable_obj *o, struct ecore_exeq_elem *elem); typedef int (*exe_q_execute)(struct bnx2x_softc *sc, union ecore_qable_obj *o, ecore_list_t *exe_chunk, unsigned long *ramrod_flags); typedef struct ecore_exeq_elem * (*exe_q_get)(struct ecore_exe_queue_obj *o, struct ecore_exeq_elem *elem); struct ecore_exe_queue_obj { /* Commands pending for an execution. */ ecore_list_t exe_queue; /* Commands pending for an completion. */ ecore_list_t pending_comp; ECORE_MUTEX_SPIN lock; /* Maximum length of commands' list for one execution */ int exe_chunk_len; union ecore_qable_obj *owner; /****** Virtual functions ******/ /** * Called before commands execution for commands that are really * going to be executed (after 'optimize'). * * Must run under exe_queue->lock */ exe_q_validate validate; /** * Called before removing pending commands, cleaning allocated * resources (e.g., credits from validate) */ exe_q_remove remove; /** * This will try to cancel the current pending commands list * considering the new command. * * Returns the number of optimized commands or a negative error code * * Must run under exe_queue->lock */ exe_q_optimize optimize; /** * Run the next commands chunk (owner specific). */ exe_q_execute execute; /** * Return the exe_queue element containing the specific command * if any. Otherwise return NULL. */ exe_q_get get; }; /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/ /* * Element in the VLAN_MAC registry list having all current configured * rules. */ struct ecore_vlan_mac_registry_elem { ecore_list_entry_t link; /* Used to store the cam offset used for the mac/vlan/vlan-mac. * Relevant for 57711 only. VLANs and MACs share the * same CAM for these chips. */ int cam_offset; /* Needed for DEL and RESTORE flows */ unsigned long vlan_mac_flags; union ecore_classification_ramrod_data u; }; /* Bits representing VLAN_MAC commands specific flags */ enum { ECORE_UC_LIST_MAC, ECORE_ETH_MAC, ECORE_ISCSI_ETH_MAC, ECORE_NETQ_ETH_MAC, ECORE_DONT_CONSUME_CAM_CREDIT, ECORE_DONT_CONSUME_CAM_CREDIT_DEST, }; struct ecore_vlan_mac_ramrod_params { /* Object to run the command from */ struct ecore_vlan_mac_obj *vlan_mac_obj; /* General command flags: COMP_WAIT, etc. */ unsigned long ramrod_flags; /* Command specific configuration request */ struct ecore_vlan_mac_data user_req; }; struct ecore_vlan_mac_obj { struct ecore_raw_obj raw; /* Bookkeeping list: will prevent the addition of already existing * entries. */ ecore_list_t head; /* Implement a simple reader/writer lock on the head list. * all these fields should only be accessed under the exe_queue lock */ uint8_t head_reader; /* Num. of readers accessing head list */ int head_exe_request; /* Pending execution request. */ unsigned long saved_ramrod_flags; /* Ramrods of pending execution */ /* Execution queue interface instance */ struct ecore_exe_queue_obj exe_queue; /* MACs credit pool */ struct ecore_credit_pool_obj *macs_pool; /* VLANs credit pool */ struct ecore_credit_pool_obj *vlans_pool; /* RAMROD command to be used */ int ramrod_cmd; /* copy first n elements onto preallocated buffer * * @param n number of elements to get * @param buf buffer preallocated by caller into which elements * will be copied. Note elements are 4-byte aligned * so buffer size must be able to accommodate the * aligned elements. * * @return number of copied bytes */ int (*get_n_elements)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, int n, uint8_t *base, uint8_t stride, uint8_t size); /** * Checks if ADD-ramrod with the given params may be performed. * * @return zero if the element may be added */ int (*check_add)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, union ecore_classification_ramrod_data *data); /** * Checks if DEL-ramrod with the given params may be performed. * * @return TRUE if the element may be deleted */ struct ecore_vlan_mac_registry_elem * (*check_del)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, union ecore_classification_ramrod_data *data); /** * Checks if DEL-ramrod with the given params may be performed. * * @return TRUE if the element may be deleted */ int (*check_move)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *src_o, struct ecore_vlan_mac_obj *dst_o, union ecore_classification_ramrod_data *data); /** * Update the relevant credit object(s) (consume/return * correspondingly). */ int (*get_credit)(struct ecore_vlan_mac_obj *o); int (*put_credit)(struct ecore_vlan_mac_obj *o); int (*get_cam_offset)(struct ecore_vlan_mac_obj *o, int *offset); int (*put_cam_offset)(struct ecore_vlan_mac_obj *o, int offset); /** * Configures one rule in the ramrod data buffer. */ void (*set_one_rule)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, struct ecore_exeq_elem *elem, int rule_idx, int cam_offset); /** * Delete all configured elements having the given * vlan_mac_flags specification. Assumes no pending for * execution commands. Will schedule all all currently * configured MACs/VLANs/VLAN-MACs matching the vlan_mac_flags * specification for deletion and will use the given * ramrod_flags for the last DEL operation. * * @param sc * @param o * @param ramrod_flags RAMROD_XX flags * * @return 0 if the last operation has completed successfully * and there are no more elements left, positive value * if there are pending for completion commands, * negative value in case of failure. */ int (*delete_all)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, unsigned long *vlan_mac_flags, unsigned long *ramrod_flags); /** * Reconfigures the next MAC/VLAN/VLAN-MAC element from the previously * configured elements list. * * @param sc * @param p Command parameters (RAMROD_COMP_WAIT bit in * ramrod_flags is only taken into an account) * @param ppos a pointer to the cookie that should be given back in the * next call to make function handle the next element. If * *ppos is set to NULL it will restart the iterator. * If returned *ppos == NULL this means that the last * element has been handled. * * @return int */ int (*restore)(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p, struct ecore_vlan_mac_registry_elem **ppos); /** * Should be called on a completion arrival. * * @param sc * @param o * @param cqe Completion element we are handling * @param ramrod_flags if RAMROD_CONT is set the next bulk of * pending commands will be executed. * RAMROD_DRV_CLR_ONLY and RAMROD_RESTORE * may also be set if needed. * * @return 0 if there are neither pending nor waiting for * completion commands. Positive value if there are * pending for execution or for completion commands. * Negative value in case of an error (including an * error in the cqe). */ int (*complete)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o, union event_ring_elem *cqe, unsigned long *ramrod_flags); /** * Wait for completion of all commands. Don't schedule new ones, * just wait. It assumes that the completion code will schedule * for new commands. */ int (*wait)(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o); }; enum { ECORE_LLH_CAM_ISCSI_ETH_LINE = 0, ECORE_LLH_CAM_ETH_LINE, ECORE_LLH_CAM_MAX_PF_LINE = NIG_REG_LLH1_FUNC_MEM_SIZE / 2 }; /** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */ /* RX_MODE ramrod special flags: set in rx_mode_flags field in * a ecore_rx_mode_ramrod_params. */ enum { ECORE_RX_MODE_FCOE_ETH, ECORE_RX_MODE_ISCSI_ETH, }; enum { ECORE_ACCEPT_UNICAST, ECORE_ACCEPT_MULTICAST, ECORE_ACCEPT_ALL_UNICAST, ECORE_ACCEPT_ALL_MULTICAST, ECORE_ACCEPT_BROADCAST, ECORE_ACCEPT_UNMATCHED, ECORE_ACCEPT_ANY_VLAN }; struct ecore_rx_mode_ramrod_params { struct ecore_rx_mode_obj *rx_mode_obj; unsigned long *pstate; int state; uint8_t cl_id; uint32_t cid; uint8_t func_id; unsigned long ramrod_flags; unsigned long rx_mode_flags; /* rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to * a tstorm_eth_mac_filter_config (e1x). */ void *rdata; ecore_dma_addr_t rdata_mapping; /* Rx mode settings */ unsigned long rx_accept_flags; /* internal switching settings */ unsigned long tx_accept_flags; }; struct ecore_rx_mode_obj { int (*config_rx_mode)(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p); int (*wait_comp)(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p); }; /********************** Set multicast group ***********************************/ struct ecore_mcast_list_elem { ecore_list_entry_t link; uint8_t *mac; }; union ecore_mcast_config_data { uint8_t *mac; uint8_t bin; /* used in a RESTORE flow */ }; struct ecore_mcast_ramrod_params { struct ecore_mcast_obj *mcast_obj; /* Relevant options are RAMROD_COMP_WAIT and RAMROD_DRV_CLR_ONLY */ unsigned long ramrod_flags; ecore_list_t mcast_list; /* list of struct ecore_mcast_list_elem */ int mcast_list_len; }; enum ecore_mcast_cmd { ECORE_MCAST_CMD_ADD, ECORE_MCAST_CMD_CONT, ECORE_MCAST_CMD_DEL, ECORE_MCAST_CMD_RESTORE, }; struct ecore_mcast_obj { struct ecore_raw_obj raw; union { struct { #define ECORE_MCAST_BINS_NUM 256 #define ECORE_MCAST_VEC_SZ (ECORE_MCAST_BINS_NUM / 64) uint64_t vec[ECORE_MCAST_VEC_SZ]; /** Number of BINs to clear. Should be updated * immediately when a command arrives in order to * properly create DEL commands. */ int num_bins_set; } aprox_match; struct { ecore_list_t macs; int num_macs_set; } exact_match; } registry; /* Pending commands */ ecore_list_t pending_cmds_head; /* A state that is set in raw.pstate, when there are pending commands */ int sched_state; /* Maximal number of mcast MACs configured in one command */ int max_cmd_len; /* Total number of currently pending MACs to configure: both * in the pending commands list and in the current command. */ int total_pending_num; uint8_t engine_id; /** * @param cmd command to execute (ECORE_MCAST_CMD_X, see above) */ int (*config_mcast)(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd); /** * Fills the ramrod data during the RESTORE flow. * * @param sc * @param o * @param start_idx Registry index to start from * @param rdata_idx Index in the ramrod data to start from * * @return -1 if we handled the whole registry or index of the last * handled registry element. */ int (*hdl_restore)(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, int start_bin, int *rdata_idx); int (*enqueue_cmd)(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd); void (*set_one_rule)(struct bnx2x_softc *sc, struct ecore_mcast_obj *o, int idx, union ecore_mcast_config_data *cfg_data, enum ecore_mcast_cmd cmd); /** Checks if there are more mcast MACs to be set or a previous * command is still pending. */ int (*check_pending)(struct ecore_mcast_obj *o); /** * Set/Clear/Check SCHEDULED state of the object */ void (*set_sched)(struct ecore_mcast_obj *o); void (*clear_sched)(struct ecore_mcast_obj *o); int (*check_sched)(struct ecore_mcast_obj *o); /* Wait until all pending commands complete */ int (*wait_comp)(struct bnx2x_softc *sc, struct ecore_mcast_obj *o); /** * Handle the internal object counters needed for proper * commands handling. Checks that the provided parameters are * feasible. */ int (*validate)(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd); /** * Restore the values of internal counters in case of a failure. */ void (*revert)(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, int old_num_bins); int (*get_registry_size)(struct ecore_mcast_obj *o); void (*set_registry_size)(struct ecore_mcast_obj *o, int n); }; /*************************** Credit handling **********************************/ struct ecore_credit_pool_obj { /* Current amount of credit in the pool */ ecore_atomic_t credit; /* Maximum allowed credit. put() will check against it. */ int pool_sz; /* Allocate a pool table statically. * * Currently the maximum allowed size is MAX_MAC_CREDIT_E2(272) * * The set bit in the table will mean that the entry is available. */ #define ECORE_POOL_VEC_SIZE (MAX_MAC_CREDIT_E2 / 64) uint64_t pool_mirror[ECORE_POOL_VEC_SIZE]; /* Base pool offset (initialized differently */ int base_pool_offset; /** * Get the next free pool entry. * * @return TRUE if there was a free entry in the pool */ int (*get_entry)(struct ecore_credit_pool_obj *o, int *entry); /** * Return the entry back to the pool. * * @return TRUE if entry is legal and has been successfully * returned to the pool. */ int (*put_entry)(struct ecore_credit_pool_obj *o, int entry); /** * Get the requested amount of credit from the pool. * * @param cnt Amount of requested credit * @return TRUE if the operation is successful */ int (*get)(struct ecore_credit_pool_obj *o, int cnt); /** * Returns the credit to the pool. * * @param cnt Amount of credit to return * @return TRUE if the operation is successful */ int (*put)(struct ecore_credit_pool_obj *o, int cnt); /** * Reads the current amount of credit. */ int (*check)(struct ecore_credit_pool_obj *o); }; /*************************** RSS configuration ********************************/ enum { /* RSS_MODE bits are mutually exclusive */ ECORE_RSS_MODE_DISABLED, ECORE_RSS_MODE_REGULAR, ECORE_RSS_SET_SRCH, /* Setup searcher, E1x specific flag */ ECORE_RSS_IPV4, ECORE_RSS_IPV4_TCP, ECORE_RSS_IPV4_UDP, ECORE_RSS_IPV6, ECORE_RSS_IPV6_TCP, ECORE_RSS_IPV6_UDP, ECORE_RSS_TUNNELING, }; struct ecore_config_rss_params { struct ecore_rss_config_obj *rss_obj; /* may have RAMROD_COMP_WAIT set only */ unsigned long ramrod_flags; /* ECORE_RSS_X bits */ unsigned long rss_flags; /* Number hash bits to take into an account */ uint8_t rss_result_mask; /* Indirection table */ uint8_t ind_table[T_ETH_INDIRECTION_TABLE_SIZE]; /* RSS hash values */ uint32_t rss_key[10]; /* valid only iff ECORE_RSS_UPDATE_TOE is set */ uint16_t toe_rss_bitmap; /* valid iff ECORE_RSS_TUNNELING is set */ uint16_t tunnel_value; uint16_t tunnel_mask; }; struct ecore_rss_config_obj { struct ecore_raw_obj raw; /* RSS engine to use */ uint8_t engine_id; /* Last configured indirection table */ uint8_t ind_table[T_ETH_INDIRECTION_TABLE_SIZE]; /* flags for enabling 4-tupple hash on UDP */ uint8_t udp_rss_v4; uint8_t udp_rss_v6; int (*config_rss)(struct bnx2x_softc *sc, struct ecore_config_rss_params *p); }; /*********************** Queue state update ***********************************/ /* UPDATE command options */ enum { ECORE_Q_UPDATE_IN_VLAN_REM, ECORE_Q_UPDATE_IN_VLAN_REM_CHNG, ECORE_Q_UPDATE_OUT_VLAN_REM, ECORE_Q_UPDATE_OUT_VLAN_REM_CHNG, ECORE_Q_UPDATE_ANTI_SPOOF, ECORE_Q_UPDATE_ANTI_SPOOF_CHNG, ECORE_Q_UPDATE_ACTIVATE, ECORE_Q_UPDATE_ACTIVATE_CHNG, ECORE_Q_UPDATE_DEF_VLAN_EN, ECORE_Q_UPDATE_DEF_VLAN_EN_CHNG, ECORE_Q_UPDATE_SILENT_VLAN_REM_CHNG, ECORE_Q_UPDATE_SILENT_VLAN_REM, ECORE_Q_UPDATE_TX_SWITCHING_CHNG, ECORE_Q_UPDATE_TX_SWITCHING, }; /* Allowed Queue states */ enum ecore_q_state { ECORE_Q_STATE_RESET, ECORE_Q_STATE_INITIALIZED, ECORE_Q_STATE_ACTIVE, ECORE_Q_STATE_MULTI_COS, ECORE_Q_STATE_MCOS_TERMINATED, ECORE_Q_STATE_INACTIVE, ECORE_Q_STATE_STOPPED, ECORE_Q_STATE_TERMINATED, ECORE_Q_STATE_FLRED, ECORE_Q_STATE_MAX, }; /* Allowed Queue states */ enum ecore_q_logical_state { ECORE_Q_LOGICAL_STATE_ACTIVE, ECORE_Q_LOGICAL_STATE_STOPPED, }; /* Allowed commands */ enum ecore_queue_cmd { ECORE_Q_CMD_INIT, ECORE_Q_CMD_SETUP, ECORE_Q_CMD_SETUP_TX_ONLY, ECORE_Q_CMD_DEACTIVATE, ECORE_Q_CMD_ACTIVATE, ECORE_Q_CMD_UPDATE, ECORE_Q_CMD_UPDATE_TPA, ECORE_Q_CMD_HALT, ECORE_Q_CMD_CFC_DEL, ECORE_Q_CMD_TERMINATE, ECORE_Q_CMD_EMPTY, ECORE_Q_CMD_MAX, }; /* queue SETUP + INIT flags */ enum { ECORE_Q_FLG_TPA, ECORE_Q_FLG_TPA_IPV6, ECORE_Q_FLG_TPA_GRO, ECORE_Q_FLG_STATS, ECORE_Q_FLG_ZERO_STATS, ECORE_Q_FLG_ACTIVE, ECORE_Q_FLG_OV, ECORE_Q_FLG_VLAN, ECORE_Q_FLG_COS, ECORE_Q_FLG_HC, ECORE_Q_FLG_HC_EN, ECORE_Q_FLG_DHC, ECORE_Q_FLG_OOO, ECORE_Q_FLG_FCOE, ECORE_Q_FLG_LEADING_RSS, ECORE_Q_FLG_MCAST, ECORE_Q_FLG_DEF_VLAN, ECORE_Q_FLG_TX_SWITCH, ECORE_Q_FLG_TX_SEC, ECORE_Q_FLG_ANTI_SPOOF, ECORE_Q_FLG_SILENT_VLAN_REM, ECORE_Q_FLG_FORCE_DEFAULT_PRI, ECORE_Q_FLG_REFUSE_OUTBAND_VLAN, ECORE_Q_FLG_PCSUM_ON_PKT, ECORE_Q_FLG_TUN_INC_INNER_IP_ID }; /* Queue type options: queue type may be a combination of below. */ enum ecore_q_type { ECORE_Q_TYPE_FWD, ECORE_Q_TYPE_HAS_RX, ECORE_Q_TYPE_HAS_TX, }; #define ECORE_PRIMARY_CID_INDEX 0 #define ECORE_MULTI_TX_COS_E1X 3 /* QM only */ #define ECORE_MULTI_TX_COS_E2_E3A0 2 #define ECORE_MULTI_TX_COS_E3B0 3 #define ECORE_MULTI_TX_COS 3 /* Maximum possible */ #define MAC_PAD (ECORE_ALIGN(ETH_ALEN, sizeof(uint32_t)) - ETH_ALEN) struct ecore_queue_init_params { struct { unsigned long flags; uint16_t hc_rate; uint8_t fw_sb_id; uint8_t sb_cq_index; } tx; struct { unsigned long flags; uint16_t hc_rate; uint8_t fw_sb_id; uint8_t sb_cq_index; } rx; /* CID context in the host memory */ struct eth_context *cxts[ECORE_MULTI_TX_COS]; /* maximum number of cos supported by hardware */ uint8_t max_cos; }; struct ecore_queue_terminate_params { /* index within the tx_only cids of this queue object */ uint8_t cid_index; }; struct ecore_queue_cfc_del_params { /* index within the tx_only cids of this queue object */ uint8_t cid_index; }; struct ecore_queue_update_params { unsigned long update_flags; /* ECORE_Q_UPDATE_XX bits */ uint16_t def_vlan; uint16_t silent_removal_value; uint16_t silent_removal_mask; /* index within the tx_only cids of this queue object */ uint8_t cid_index; }; struct rxq_pause_params { uint16_t bd_th_lo; uint16_t bd_th_hi; uint16_t rcq_th_lo; uint16_t rcq_th_hi; uint16_t sge_th_lo; /* valid iff ECORE_Q_FLG_TPA */ uint16_t sge_th_hi; /* valid iff ECORE_Q_FLG_TPA */ uint16_t pri_map; }; /* general */ struct ecore_general_setup_params { /* valid iff ECORE_Q_FLG_STATS */ uint8_t stat_id; uint8_t spcl_id; uint16_t mtu; uint8_t cos; }; struct ecore_rxq_setup_params { /* dma */ ecore_dma_addr_t dscr_map; ecore_dma_addr_t rcq_map; ecore_dma_addr_t rcq_np_map; uint16_t drop_flags; uint16_t buf_sz; uint8_t fw_sb_id; uint8_t cl_qzone_id; /* valid iff ECORE_Q_FLG_TPA */ uint16_t tpa_agg_sz; uint8_t max_tpa_queues; uint8_t rss_engine_id; /* valid iff ECORE_Q_FLG_MCAST */ uint8_t mcast_engine_id; uint8_t cache_line_log; uint8_t sb_cq_index; /* valid iff BXN2X_Q_FLG_SILENT_VLAN_REM */ uint16_t silent_removal_value; uint16_t silent_removal_mask; }; struct ecore_txq_setup_params { /* dma */ ecore_dma_addr_t dscr_map; uint8_t fw_sb_id; uint8_t sb_cq_index; uint8_t cos; /* valid iff ECORE_Q_FLG_COS */ uint16_t traffic_type; /* equals to the leading rss client id, used for TX classification*/ uint8_t tss_leading_cl_id; /* valid iff ECORE_Q_FLG_DEF_VLAN */ uint16_t default_vlan; }; struct ecore_queue_setup_params { struct ecore_general_setup_params gen_params; struct ecore_txq_setup_params txq_params; struct ecore_rxq_setup_params rxq_params; struct rxq_pause_params pause_params; unsigned long flags; }; struct ecore_queue_setup_tx_only_params { struct ecore_general_setup_params gen_params; struct ecore_txq_setup_params txq_params; unsigned long flags; /* index within the tx_only cids of this queue object */ uint8_t cid_index; }; struct ecore_queue_state_params { struct ecore_queue_sp_obj *q_obj; /* Current command */ enum ecore_queue_cmd cmd; /* may have RAMROD_COMP_WAIT set only */ unsigned long ramrod_flags; /* Params according to the current command */ union { struct ecore_queue_update_params update; struct ecore_queue_setup_params setup; struct ecore_queue_init_params init; struct ecore_queue_setup_tx_only_params tx_only; struct ecore_queue_terminate_params terminate; struct ecore_queue_cfc_del_params cfc_del; } params; }; struct ecore_viflist_params { uint8_t echo_res; uint8_t func_bit_map_res; }; struct ecore_queue_sp_obj { uint32_t cids[ECORE_MULTI_TX_COS]; uint8_t cl_id; uint8_t func_id; /* number of traffic classes supported by queue. * The primary connection of the queue supports the first traffic * class. Any further traffic class is supported by a tx-only * connection. * * Therefore max_cos is also a number of valid entries in the cids * array. */ uint8_t max_cos; uint8_t num_tx_only, next_tx_only; enum ecore_q_state state, next_state; /* bits from enum ecore_q_type */ unsigned long type; /* ECORE_Q_CMD_XX bits. This object implements "one * pending" paradigm but for debug and tracing purposes it's * more convenient to have different bits for different * commands. */ unsigned long pending; /* Buffer to use as a ramrod data and its mapping */ void *rdata; ecore_dma_addr_t rdata_mapping; /** * Performs one state change according to the given parameters. * * @return 0 in case of success and negative value otherwise. */ int (*send_cmd)(struct bnx2x_softc *sc, struct ecore_queue_state_params *params); /** * Sets the pending bit according to the requested transition. */ int (*set_pending)(struct ecore_queue_sp_obj *o, struct ecore_queue_state_params *params); /** * Checks that the requested state transition is legal. */ int (*check_transition)(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *o, struct ecore_queue_state_params *params); /** * Completes the pending command. */ int (*complete_cmd)(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *o, enum ecore_queue_cmd); int (*wait_comp)(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *o, enum ecore_queue_cmd cmd); }; /********************** Function state update *********************************/ /* Allowed Function states */ enum ecore_func_state { ECORE_F_STATE_RESET, ECORE_F_STATE_INITIALIZED, ECORE_F_STATE_STARTED, ECORE_F_STATE_TX_STOPPED, ECORE_F_STATE_MAX, }; /* Allowed Function commands */ enum ecore_func_cmd { ECORE_F_CMD_HW_INIT, ECORE_F_CMD_START, ECORE_F_CMD_STOP, ECORE_F_CMD_HW_RESET, ECORE_F_CMD_AFEX_UPDATE, ECORE_F_CMD_AFEX_VIFLISTS, ECORE_F_CMD_TX_STOP, ECORE_F_CMD_TX_START, ECORE_F_CMD_SWITCH_UPDATE, ECORE_F_CMD_MAX, }; struct ecore_func_hw_init_params { /* A load phase returned by MCP. * * May be: * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP * FW_MSG_CODE_DRV_LOAD_COMMON * FW_MSG_CODE_DRV_LOAD_PORT * FW_MSG_CODE_DRV_LOAD_FUNCTION */ uint32_t load_phase; }; struct ecore_func_hw_reset_params { /* A load phase returned by MCP. * * May be: * FW_MSG_CODE_DRV_LOAD_COMMON_CHIP * FW_MSG_CODE_DRV_LOAD_COMMON * FW_MSG_CODE_DRV_LOAD_PORT * FW_MSG_CODE_DRV_LOAD_FUNCTION */ uint32_t reset_phase; }; struct ecore_func_start_params { /* Multi Function mode: * - Single Function * - Switch Dependent * - Switch Independent */ uint16_t mf_mode; /* Switch Dependent mode outer VLAN tag */ uint16_t sd_vlan_tag; /* Function cos mode */ uint8_t network_cos_mode; /* NVGRE classification enablement */ uint8_t nvgre_clss_en; /* NO_GRE_TUNNEL/NVGRE_TUNNEL/L2GRE_TUNNEL/IPGRE_TUNNEL */ uint8_t gre_tunnel_mode; /* GRE_OUTER_HEADERS_RSS/GRE_INNER_HEADERS_RSS/NVGRE_KEY_ENTROPY_RSS */ uint8_t gre_tunnel_rss; }; struct ecore_func_switch_update_params { uint8_t suspend; }; struct ecore_func_afex_update_params { uint16_t vif_id; uint16_t afex_default_vlan; uint8_t allowed_priorities; }; struct ecore_func_afex_viflists_params { uint16_t vif_list_index; uint8_t func_bit_map; uint8_t afex_vif_list_command; uint8_t func_to_clear; }; struct ecore_func_tx_start_params { struct priority_cos traffic_type_to_priority_cos[MAX_TRAFFIC_TYPES]; uint8_t dcb_enabled; uint8_t dcb_version; uint8_t dont_add_pri_0; }; struct ecore_func_state_params { struct ecore_func_sp_obj *f_obj; /* Current command */ enum ecore_func_cmd cmd; /* may have RAMROD_COMP_WAIT set only */ unsigned long ramrod_flags; /* Params according to the current command */ union { struct ecore_func_hw_init_params hw_init; struct ecore_func_hw_reset_params hw_reset; struct ecore_func_start_params start; struct ecore_func_switch_update_params switch_update; struct ecore_func_afex_update_params afex_update; struct ecore_func_afex_viflists_params afex_viflists; struct ecore_func_tx_start_params tx_start; } params; }; struct ecore_func_sp_drv_ops { /* Init tool + runtime initialization: * - Common Chip * - Common (per Path) * - Port * - Function phases */ int (*init_hw_cmn_chip)(struct bnx2x_softc *sc); int (*init_hw_cmn)(struct bnx2x_softc *sc); int (*init_hw_port)(struct bnx2x_softc *sc); int (*init_hw_func)(struct bnx2x_softc *sc); /* Reset Function HW: Common, Port, Function phases. */ void (*reset_hw_cmn)(struct bnx2x_softc *sc); void (*reset_hw_port)(struct bnx2x_softc *sc); void (*reset_hw_func)(struct bnx2x_softc *sc); /* Prepare/Release FW resources */ int (*init_fw)(struct bnx2x_softc *sc); void (*release_fw)(struct bnx2x_softc *sc); }; struct ecore_func_sp_obj { enum ecore_func_state state, next_state; /* ECORE_FUNC_CMD_XX bits. This object implements "one * pending" paradigm but for debug and tracing purposes it's * more convenient to have different bits for different * commands. */ unsigned long pending; /* Buffer to use as a ramrod data and its mapping */ void *rdata; ecore_dma_addr_t rdata_mapping; /* Buffer to use as a afex ramrod data and its mapping. * This can't be same rdata as above because afex ramrod requests * can arrive to the object in parallel to other ramrod requests. */ void *afex_rdata; ecore_dma_addr_t afex_rdata_mapping; /* this mutex validates that when pending flag is taken, the next * ramrod to be sent will be the one set the pending bit */ ECORE_MUTEX one_pending_mutex; /* Driver interface */ struct ecore_func_sp_drv_ops *drv; /** * Performs one state change according to the given parameters. * * @return 0 in case of success and negative value otherwise. */ int (*send_cmd)(struct bnx2x_softc *sc, struct ecore_func_state_params *params); /** * Checks that the requested state transition is legal. */ int (*check_transition)(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o, struct ecore_func_state_params *params); /** * Completes the pending command. */ int (*complete_cmd)(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o, enum ecore_func_cmd cmd); int (*wait_comp)(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o, enum ecore_func_cmd cmd); }; /********************** Interfaces ********************************************/ /* Queueable objects set */ union ecore_qable_obj { struct ecore_vlan_mac_obj vlan_mac; }; /************** Function state update *********/ void ecore_init_func_obj(struct bnx2x_softc *sc, struct ecore_func_sp_obj *obj, void *rdata, ecore_dma_addr_t rdata_mapping, void *afex_rdata, ecore_dma_addr_t afex_rdata_mapping, struct ecore_func_sp_drv_ops *drv_iface); int ecore_func_state_change(struct bnx2x_softc *sc, struct ecore_func_state_params *params); enum ecore_func_state ecore_func_get_state(struct bnx2x_softc *sc, struct ecore_func_sp_obj *o); /******************* Queue State **************/ void ecore_init_queue_obj(struct bnx2x_softc *sc, struct ecore_queue_sp_obj *obj, uint8_t cl_id, uint32_t *cids, uint8_t cid_cnt, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, unsigned long type); int ecore_queue_state_change(struct bnx2x_softc *sc, struct ecore_queue_state_params *params); /********************* VLAN-MAC ****************/ void ecore_init_mac_obj(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *mac_obj, uint8_t cl_id, uint32_t cid, uint8_t func_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type, struct ecore_credit_pool_obj *macs_pool); void ecore_vlan_mac_h_read_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o); int ecore_vlan_mac_h_write_lock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o); void ecore_vlan_mac_h_write_unlock(struct bnx2x_softc *sc, struct ecore_vlan_mac_obj *o); int ecore_config_vlan_mac(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p); int ecore_vlan_mac_move(struct bnx2x_softc *sc, struct ecore_vlan_mac_ramrod_params *p, struct ecore_vlan_mac_obj *dest_o); /********************* RX MODE ****************/ void ecore_init_rx_mode_obj(struct bnx2x_softc *sc, struct ecore_rx_mode_obj *o); /** * ecore_config_rx_mode - Send and RX_MODE ramrod according to the provided parameters. * * @p: Command parameters * * Return: 0 - if operation was successful and there is no pending completions, * positive number - if there are pending completions, * negative - if there were errors */ int ecore_config_rx_mode(struct bnx2x_softc *sc, struct ecore_rx_mode_ramrod_params *p); /****************** MULTICASTS ****************/ void ecore_init_mcast_obj(struct bnx2x_softc *sc, struct ecore_mcast_obj *mcast_obj, uint8_t mcast_cl_id, uint32_t mcast_cid, uint8_t func_id, uint8_t engine_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type); /** * ecore_config_mcast - Configure multicast MACs list. * * @cmd: command to execute: BNX2X_MCAST_CMD_X * * May configure a new list * provided in p->mcast_list (ECORE_MCAST_CMD_ADD), clean up * (ECORE_MCAST_CMD_DEL) or restore (ECORE_MCAST_CMD_RESTORE) a current * configuration, continue to execute the pending commands * (ECORE_MCAST_CMD_CONT). * * If previous command is still pending or if number of MACs to * configure is more that maximum number of MACs in one command, * the current command will be enqueued to the tail of the * pending commands list. * * Return: 0 is operation was successfull and there are no pending completions, * negative if there were errors, positive if there are pending * completions. */ int ecore_config_mcast(struct bnx2x_softc *sc, struct ecore_mcast_ramrod_params *p, enum ecore_mcast_cmd cmd); /****************** CREDIT POOL ****************/ void ecore_init_mac_credit_pool(struct bnx2x_softc *sc, struct ecore_credit_pool_obj *p, uint8_t func_id, uint8_t func_num); void ecore_init_vlan_credit_pool(struct bnx2x_softc *sc, struct ecore_credit_pool_obj *p, uint8_t func_id, uint8_t func_num); /****************** RSS CONFIGURATION ****************/ void ecore_init_rss_config_obj(struct ecore_rss_config_obj *rss_obj, uint8_t cl_id, uint32_t cid, uint8_t func_id, uint8_t engine_id, void *rdata, ecore_dma_addr_t rdata_mapping, int state, unsigned long *pstate, ecore_obj_type type); /** * ecore_config_rss - Updates RSS configuration according to provided parameters * * Return: 0 in case of success */ int ecore_config_rss(struct bnx2x_softc *sc, struct ecore_config_rss_params *p); #endif /* ECORE_SP_H */ ================================================ FILE: drivers/net/bnx2x/elink.c ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "bnx2x.h" #include "elink.h" #include "ecore_mfw_req.h" #include "ecore_fw_defs.h" #include "ecore_hsi.h" #include "ecore_reg.h" static elink_status_t elink_link_reset(struct elink_params *params, struct elink_vars *vars, uint8_t reset_ext_phy); static elink_status_t elink_check_half_open_conn(struct elink_params *params, struct elink_vars *vars, uint8_t notify); static elink_status_t elink_sfp_module_detection(struct elink_phy *phy, struct elink_params *params); #define MDIO_REG_BANK_CL73_IEEEB0 0x0 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN 0x0200 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN 0x1000 #define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_MAIN_RST 0x8000 #define MDIO_REG_BANK_CL73_IEEEB1 0x10 #define MDIO_CL73_IEEEB1_AN_ADV1 0x00 #define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE 0x0400 #define MDIO_CL73_IEEEB1_AN_ADV1_ASYMMETRIC 0x0800 #define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH 0x0C00 #define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK 0x0C00 #define MDIO_CL73_IEEEB1_AN_ADV2 0x01 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M 0x0000 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX 0x0020 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 0x0040 #define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR 0x0080 #define MDIO_CL73_IEEEB1_AN_LP_ADV1 0x03 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE 0x0400 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC 0x0800 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH 0x0C00 #define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK 0x0C00 #define MDIO_CL73_IEEEB1_AN_LP_ADV2 0x04 #define MDIO_REG_BANK_RX0 0x80b0 #define MDIO_RX0_RX_STATUS 0x10 #define MDIO_RX0_RX_STATUS_SIGDET 0x8000 #define MDIO_RX0_RX_STATUS_RX_SEQ_DONE 0x1000 #define MDIO_RX0_RX_EQ_BOOST 0x1c #define MDIO_RX0_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7 #define MDIO_RX0_RX_EQ_BOOST_OFFSET_CTRL 0x10 #define MDIO_REG_BANK_RX1 0x80c0 #define MDIO_RX1_RX_EQ_BOOST 0x1c #define MDIO_RX1_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7 #define MDIO_RX1_RX_EQ_BOOST_OFFSET_CTRL 0x10 #define MDIO_REG_BANK_RX2 0x80d0 #define MDIO_RX2_RX_EQ_BOOST 0x1c #define MDIO_RX2_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7 #define MDIO_RX2_RX_EQ_BOOST_OFFSET_CTRL 0x10 #define MDIO_REG_BANK_RX3 0x80e0 #define MDIO_RX3_RX_EQ_BOOST 0x1c #define MDIO_RX3_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7 #define MDIO_RX3_RX_EQ_BOOST_OFFSET_CTRL 0x10 #define MDIO_REG_BANK_RX_ALL 0x80f0 #define MDIO_RX_ALL_RX_EQ_BOOST 0x1c #define MDIO_RX_ALL_RX_EQ_BOOST_EQUALIZER_CTRL_MASK 0x7 #define MDIO_RX_ALL_RX_EQ_BOOST_OFFSET_CTRL 0x10 #define MDIO_REG_BANK_TX0 0x8060 #define MDIO_TX0_TX_DRIVER 0x17 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK 0xf000 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT 12 #define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00 #define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT 8 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK 0x00f0 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT 4 #define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK 0x000e #define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT 1 #define MDIO_TX0_TX_DRIVER_ICBUF1T 1 #define MDIO_REG_BANK_TX1 0x8070 #define MDIO_TX1_TX_DRIVER 0x17 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK 0xf000 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT 12 #define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00 #define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT 8 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK 0x00f0 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT 4 #define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK 0x000e #define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT 1 #define MDIO_TX0_TX_DRIVER_ICBUF1T 1 #define MDIO_REG_BANK_TX2 0x8080 #define MDIO_TX2_TX_DRIVER 0x17 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK 0xf000 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT 12 #define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00 #define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT 8 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK 0x00f0 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT 4 #define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK 0x000e #define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT 1 #define MDIO_TX0_TX_DRIVER_ICBUF1T 1 #define MDIO_REG_BANK_TX3 0x8090 #define MDIO_TX3_TX_DRIVER 0x17 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK 0xf000 #define MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT 12 #define MDIO_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00 #define MDIO_TX0_TX_DRIVER_IDRIVER_SHIFT 8 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_MASK 0x00f0 #define MDIO_TX0_TX_DRIVER_IPREDRIVER_SHIFT 4 #define MDIO_TX0_TX_DRIVER_IFULLSPD_MASK 0x000e #define MDIO_TX0_TX_DRIVER_IFULLSPD_SHIFT 1 #define MDIO_TX0_TX_DRIVER_ICBUF1T 1 #define MDIO_REG_BANK_XGXS_BLOCK0 0x8000 #define MDIO_BLOCK0_XGXS_CONTROL 0x10 #define MDIO_REG_BANK_XGXS_BLOCK1 0x8010 #define MDIO_BLOCK1_LANE_CTRL0 0x15 #define MDIO_BLOCK1_LANE_CTRL1 0x16 #define MDIO_BLOCK1_LANE_CTRL2 0x17 #define MDIO_BLOCK1_LANE_PRBS 0x19 #define MDIO_REG_BANK_XGXS_BLOCK2 0x8100 #define MDIO_XGXS_BLOCK2_RX_LN_SWAP 0x10 #define MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE 0x8000 #define MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE 0x4000 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP 0x11 #define MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE 0x8000 #define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G 0x14 #define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS 0x0001 #define MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS 0x0010 #define MDIO_XGXS_BLOCK2_TEST_MODE_LANE 0x15 #define MDIO_REG_BANK_GP_STATUS 0x8120 #define MDIO_GP_STATUS_TOP_AN_STATUS1 0x1B #define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE 0x0001 #define MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE 0x0002 #define MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS 0x0004 #define MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS 0x0008 #define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE 0x0010 #define MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_LP_NP_BAM_ABLE 0x0020 #define MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE 0x0040 #define MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE 0x0080 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK 0x3f00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M 0x0000 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M 0x0100 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G 0x0200 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G 0x0300 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G 0x0400 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G 0x0500 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG 0x0600 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4 0x0700 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12G_HIG 0x0800 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_12_5G 0x0900 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_13G 0x0A00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_15G 0x0B00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_16G 0x0C00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX 0x0D00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4 0x0E00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR 0x0F00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 0x1B00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 0x1E00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 0x1F00 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2 0x3900 #define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS 0x10 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK 0x8000 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL 0x11 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN 0x1 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK 0x13 #define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT (0xb71<<1) #define MDIO_REG_BANK_SERDES_DIGITAL 0x8300 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1 0x10 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE 0x0001 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_TBI_IF 0x0002 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN 0x0004 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT 0x0008 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET 0x0010 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE 0x0020 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2 0x11 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN 0x0001 #define MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_AN_FST_TMR 0x0040 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1 0x14 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SGMII 0x0001 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_LINK 0x0002 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_DUPLEX 0x0004 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_MASK 0x0018 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_SHIFT 3 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_2_5G 0x0018 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_1G 0x0010 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_100M 0x0008 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_10M 0x0000 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS2 0x15 #define MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED 0x0002 #define MDIO_SERDES_DIGITAL_MISC1 0x18 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_MASK 0xE000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_25M 0x0000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_100M 0x2000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_125M 0x4000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M 0x6000 #define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_187_5M 0x8000 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL 0x0010 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK 0x000f #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_2_5G 0x0000 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_5G 0x0001 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_6G 0x0002 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_HIG 0x0003 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4 0x0004 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_12G 0x0005 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_12_5G 0x0006 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G 0x0007 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_15G 0x0008 #define MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_16G 0x0009 #define MDIO_REG_BANK_OVER_1G 0x8320 #define MDIO_OVER_1G_DIGCTL_3_4 0x14 #define MDIO_OVER_1G_DIGCTL_3_4_MP_ID_MASK 0xffe0 #define MDIO_OVER_1G_DIGCTL_3_4_MP_ID_SHIFT 5 #define MDIO_OVER_1G_UP1 0x19 #define MDIO_OVER_1G_UP1_2_5G 0x0001 #define MDIO_OVER_1G_UP1_5G 0x0002 #define MDIO_OVER_1G_UP1_6G 0x0004 #define MDIO_OVER_1G_UP1_10G 0x0010 #define MDIO_OVER_1G_UP1_10GH 0x0008 #define MDIO_OVER_1G_UP1_12G 0x0020 #define MDIO_OVER_1G_UP1_12_5G 0x0040 #define MDIO_OVER_1G_UP1_13G 0x0080 #define MDIO_OVER_1G_UP1_15G 0x0100 #define MDIO_OVER_1G_UP1_16G 0x0200 #define MDIO_OVER_1G_UP2 0x1A #define MDIO_OVER_1G_UP2_IPREDRIVER_MASK 0x0007 #define MDIO_OVER_1G_UP2_IDRIVER_MASK 0x0038 #define MDIO_OVER_1G_UP2_PREEMPHASIS_MASK 0x03C0 #define MDIO_OVER_1G_UP3 0x1B #define MDIO_OVER_1G_UP3_HIGIG2 0x0001 #define MDIO_OVER_1G_LP_UP1 0x1C #define MDIO_OVER_1G_LP_UP2 0x1D #define MDIO_OVER_1G_LP_UP2_MR_ADV_OVER_1G_MASK 0x03ff #define MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK 0x0780 #define MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT 7 #define MDIO_OVER_1G_LP_UP3 0x1E #define MDIO_REG_BANK_REMOTE_PHY 0x8330 #define MDIO_REMOTE_PHY_MISC_RX_STATUS 0x10 #define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG 0x0010 #define MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG 0x0600 #define MDIO_REG_BANK_BAM_NEXT_PAGE 0x8350 #define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL 0x10 #define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE 0x0001 #define MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN 0x0002 #define MDIO_REG_BANK_CL73_USERB0 0x8370 #define MDIO_CL73_USERB0_CL73_UCTRL 0x10 #define MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL 0x0002 #define MDIO_CL73_USERB0_CL73_USTAT1 0x11 #define MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK 0x0100 #define MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37 0x0400 #define MDIO_CL73_USERB0_CL73_BAM_CTRL1 0x12 #define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN 0x8000 #define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN 0x4000 #define MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN 0x2000 #define MDIO_CL73_USERB0_CL73_BAM_CTRL3 0x14 #define MDIO_CL73_USERB0_CL73_BAM_CTRL3_USE_CL73_HCD_MR 0x0001 #define MDIO_REG_BANK_AER_BLOCK 0xFFD0 #define MDIO_AER_BLOCK_AER_REG 0x1E #define MDIO_REG_BANK_COMBO_IEEE0 0xFFE0 #define MDIO_COMBO_IEEE0_MII_CONTROL 0x10 #define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK 0x2040 #define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_10 0x0000 #define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100 0x2000 #define MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000 0x0040 #define MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX 0x0100 #define MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN 0x0200 #define MDIO_COMBO_IEEO_MII_CONTROL_AN_EN 0x1000 #define MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK 0x4000 #define MDIO_COMBO_IEEO_MII_CONTROL_RESET 0x8000 #define MDIO_COMBO_IEEE0_MII_STATUS 0x11 #define MDIO_COMBO_IEEE0_MII_STATUS_LINK_PASS 0x0004 #define MDIO_COMBO_IEEE0_MII_STATUS_AUTONEG_COMPLETE 0x0020 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV 0x14 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX 0x0020 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_HALF_DUPLEX 0x0040 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK 0x0180 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE 0x0000 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC 0x0080 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC 0x0100 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH 0x0180 #define MDIO_COMBO_IEEE0_AUTO_NEG_ADV_NEXT_PAGE 0x8000 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1 0x15 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_NEXT_PAGE 0x8000 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_ACK 0x4000 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_MASK 0x0180 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_NONE 0x0000 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_PAUSE_BOTH 0x0180 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_HALF_DUP_CAP 0x0040 #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_FULL_DUP_CAP 0x0020 /*WhenthelinkpartnerisinSGMIImode(bit0=1),then bit15=link,bit12=duplex,bits11:10=speed,bit14=acknowledge. Theotherbitsarereservedandshouldbezero*/ #define MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1_SGMII_MODE 0x0001 #define MDIO_PMA_DEVAD 0x1 /*ieee*/ #define MDIO_PMA_REG_CTRL 0x0 #define MDIO_PMA_REG_STATUS 0x1 #define MDIO_PMA_REG_10G_CTRL2 0x7 #define MDIO_PMA_REG_TX_DISABLE 0x0009 #define MDIO_PMA_REG_RX_SD 0xa /*bnx2x*/ #define MDIO_PMA_REG_BNX2X_CTRL 0x0096 #define MDIO_PMA_REG_FEC_CTRL 0x00ab #define MDIO_PMA_LASI_RXCTRL 0x9000 #define MDIO_PMA_LASI_TXCTRL 0x9001 #define MDIO_PMA_LASI_CTRL 0x9002 #define MDIO_PMA_LASI_RXSTAT 0x9003 #define MDIO_PMA_LASI_TXSTAT 0x9004 #define MDIO_PMA_LASI_STAT 0x9005 #define MDIO_PMA_REG_PHY_IDENTIFIER 0xc800 #define MDIO_PMA_REG_DIGITAL_CTRL 0xc808 #define MDIO_PMA_REG_DIGITAL_STATUS 0xc809 #define MDIO_PMA_REG_TX_POWER_DOWN 0xca02 #define MDIO_PMA_REG_CMU_PLL_BYPASS 0xca09 #define MDIO_PMA_REG_MISC_CTRL 0xca0a #define MDIO_PMA_REG_GEN_CTRL 0xca10 #define MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP 0x0188 #define MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET 0x018a #define MDIO_PMA_REG_M8051_MSGIN_REG 0xca12 #define MDIO_PMA_REG_M8051_MSGOUT_REG 0xca13 #define MDIO_PMA_REG_ROM_VER1 0xca19 #define MDIO_PMA_REG_ROM_VER2 0xca1a #define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b #define MDIO_PMA_REG_PLL_BANDWIDTH 0xca1d #define MDIO_PMA_REG_PLL_CTRL 0xca1e #define MDIO_PMA_REG_MISC_CTRL0 0xca23 #define MDIO_PMA_REG_LRM_MODE 0xca3f #define MDIO_PMA_REG_CDR_BANDWIDTH 0xca46 #define MDIO_PMA_REG_MISC_CTRL1 0xca85 #define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL 0x8000 #define MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK 0x000c #define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE 0x0000 #define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE 0x0004 #define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IN_PROGRESS 0x0008 #define MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_FAILED 0x000c #define MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT 0x8002 #define MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR 0x8003 #define MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF 0xc820 #define MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK 0xff #define MDIO_PMA_REG_8726_TX_CTRL1 0xca01 #define MDIO_PMA_REG_8726_TX_CTRL2 0xca05 #define MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR 0x8005 #define MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF 0x8007 #define MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK 0xff #define MDIO_PMA_REG_8727_MISC_CTRL 0x8309 #define MDIO_PMA_REG_8727_TX_CTRL1 0xca02 #define MDIO_PMA_REG_8727_TX_CTRL2 0xca05 #define MDIO_PMA_REG_8727_PCS_OPT_CTRL 0xc808 #define MDIO_PMA_REG_8727_GPIO_CTRL 0xc80e #define MDIO_PMA_REG_8727_PCS_GP 0xc842 #define MDIO_PMA_REG_8727_OPT_CFG_REG 0xc8e4 #define MDIO_AN_REG_8727_MISC_CTRL 0x8309 #define MDIO_PMA_REG_8073_CHIP_REV 0xc801 #define MDIO_PMA_REG_8073_SPEED_LINK_STATUS 0xc820 #define MDIO_PMA_REG_8073_XAUI_WA 0xc841 #define MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL 0xcd08 #define MDIO_PMA_REG_7101_RESET 0xc000 #define MDIO_PMA_REG_7107_LED_CNTL 0xc007 #define MDIO_PMA_REG_7107_LINK_LED_CNTL 0xc009 #define MDIO_PMA_REG_7101_VER1 0xc026 #define MDIO_PMA_REG_7101_VER2 0xc027 #define MDIO_PMA_REG_8481_PMD_SIGNAL 0xa811 #define MDIO_PMA_REG_8481_LED1_MASK 0xa82c #define MDIO_PMA_REG_8481_LED2_MASK 0xa82f #define MDIO_PMA_REG_8481_LED3_MASK 0xa832 #define MDIO_PMA_REG_8481_LED3_BLINK 0xa834 #define MDIO_PMA_REG_8481_LED5_MASK 0xa838 #define MDIO_PMA_REG_8481_SIGNAL_MASK 0xa835 #define MDIO_PMA_REG_8481_LINK_SIGNAL 0xa83b #define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK 0x800 #define MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT 11 #define MDIO_WIS_DEVAD 0x2 /*bnx2x*/ #define MDIO_WIS_REG_LASI_CNTL 0x9002 #define MDIO_WIS_REG_LASI_STATUS 0x9005 #define MDIO_PCS_DEVAD 0x3 #define MDIO_PCS_REG_STATUS 0x0020 #define MDIO_PCS_REG_LASI_STATUS 0x9005 #define MDIO_PCS_REG_7101_DSP_ACCESS 0xD000 #define MDIO_PCS_REG_7101_SPI_MUX 0xD008 #define MDIO_PCS_REG_7101_SPI_CTRL_ADDR 0xE12A #define MDIO_PCS_REG_7101_SPI_RESET_BIT (5) #define MDIO_PCS_REG_7101_SPI_FIFO_ADDR 0xE02A #define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_WRITE_ENABLE_CMD (6) #define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_BULK_ERASE_CMD (0xC7) #define MDIO_PCS_REG_7101_SPI_FIFO_ADDR_PAGE_PROGRAM_CMD (2) #define MDIO_PCS_REG_7101_SPI_BYTES_TO_TRANSFER_ADDR 0xE028 #define MDIO_XS_DEVAD 0x4 #define MDIO_XS_REG_STATUS 0x0001 #define MDIO_XS_PLL_SEQUENCER 0x8000 #define MDIO_XS_SFX7101_XGXS_TEST1 0xc00a #define MDIO_XS_8706_REG_BANK_RX0 0x80bc #define MDIO_XS_8706_REG_BANK_RX1 0x80cc #define MDIO_XS_8706_REG_BANK_RX2 0x80dc #define MDIO_XS_8706_REG_BANK_RX3 0x80ec #define MDIO_XS_8706_REG_BANK_RXA 0x80fc #define MDIO_XS_REG_8073_RX_CTRL_PCIE 0x80FA #define MDIO_AN_DEVAD 0x7 /*ieee*/ #define MDIO_AN_REG_CTRL 0x0000 #define MDIO_AN_REG_STATUS 0x0001 #define MDIO_AN_REG_STATUS_AN_COMPLETE 0x0020 #define MDIO_AN_REG_ADV_PAUSE 0x0010 #define MDIO_AN_REG_ADV_PAUSE_PAUSE 0x0400 #define MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC 0x0800 #define MDIO_AN_REG_ADV_PAUSE_BOTH 0x0C00 #define MDIO_AN_REG_ADV_PAUSE_MASK 0x0C00 #define MDIO_AN_REG_ADV 0x0011 #define MDIO_AN_REG_ADV2 0x0012 #define MDIO_AN_REG_LP_AUTO_NEG 0x0013 #define MDIO_AN_REG_LP_AUTO_NEG2 0x0014 #define MDIO_AN_REG_MASTER_STATUS 0x0021 #define MDIO_AN_REG_EEE_ADV 0x003c #define MDIO_AN_REG_LP_EEE_ADV 0x003d /*bnx2x*/ #define MDIO_AN_REG_LINK_STATUS 0x8304 #define MDIO_AN_REG_CL37_CL73 0x8370 #define MDIO_AN_REG_CL37_AN 0xffe0 #define MDIO_AN_REG_CL37_FC_LD 0xffe4 #define MDIO_AN_REG_CL37_FC_LP 0xffe5 #define MDIO_AN_REG_1000T_STATUS 0xffea #define MDIO_AN_REG_8073_2_5G 0x8329 #define MDIO_AN_REG_8073_BAM 0x8350 #define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL 0x0020 #define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0 #define MDIO_AN_REG_8481_MII_CTRL_FORCE_1G 0x40 #define MDIO_AN_REG_8481_LEGACY_MII_STATUS 0xffe1 #define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4 #define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION 0xffe6 #define MDIO_AN_REG_8481_1000T_CTRL 0xffe9 #define MDIO_AN_REG_8481_1G_100T_EXT_CTRL 0xfff0 #define MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF 0x0008 #define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW 0xfff5 #define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS 0xfff7 #define MDIO_AN_REG_8481_AUX_CTRL 0xfff8 #define MDIO_AN_REG_8481_LEGACY_SHADOW 0xfffc /* BNX2X84823 only */ #define MDIO_CTL_DEVAD 0x1e #define MDIO_CTL_REG_84823_MEDIA 0x401a #define MDIO_CTL_REG_84823_MEDIA_MAC_MASK 0x0018 /* These pins configure the BNX2X84823 interface to MAC after reset. */ #define MDIO_CTL_REG_84823_CTRL_MAC_XFI 0x0008 #define MDIO_CTL_REG_84823_MEDIA_MAC_XAUI_M 0x0010 /* These pins configure the BNX2X84823 interface to Line after reset. */ #define MDIO_CTL_REG_84823_MEDIA_LINE_MASK 0x0060 #define MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L 0x0020 #define MDIO_CTL_REG_84823_MEDIA_LINE_XFI 0x0040 /* When this pin is active high during reset, 10GBASE-T core is power * down, When it is active low the 10GBASE-T is power up */ #define MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN 0x0080 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK 0x0100 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER 0x0000 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER 0x0100 #define MDIO_CTL_REG_84823_MEDIA_FIBER_1G 0x1000 #define MDIO_CTL_REG_84823_USER_CTRL_REG 0x4005 #define MDIO_CTL_REG_84823_USER_CTRL_CMS 0x0080 #define MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH 0xa82b #define MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ 0x2f #define MDIO_PMA_REG_84823_CTL_LED_CTL_1 0xa8e3 #define MDIO_PMA_REG_84833_CTL_LED_CTL_1 0xa8ec #define MDIO_PMA_REG_84823_LED3_STRETCH_EN 0x0080 /* BNX2X84833 only */ #define MDIO_84833_TOP_CFG_FW_REV 0x400f #define MDIO_84833_TOP_CFG_FW_EEE 0x10b1 #define MDIO_84833_TOP_CFG_FW_NO_EEE 0x1f81 #define MDIO_84833_TOP_CFG_XGPHY_STRAP1 0x401a #define MDIO_84833_SUPER_ISOLATE 0x8000 /* These are mailbox register set used by 84833. */ #define MDIO_84833_TOP_CFG_SCRATCH_REG0 0x4005 #define MDIO_84833_TOP_CFG_SCRATCH_REG1 0x4006 #define MDIO_84833_TOP_CFG_SCRATCH_REG2 0x4007 #define MDIO_84833_TOP_CFG_SCRATCH_REG3 0x4008 #define MDIO_84833_TOP_CFG_SCRATCH_REG4 0x4009 #define MDIO_84833_TOP_CFG_SCRATCH_REG26 0x4037 #define MDIO_84833_TOP_CFG_SCRATCH_REG27 0x4038 #define MDIO_84833_TOP_CFG_SCRATCH_REG28 0x4039 #define MDIO_84833_TOP_CFG_SCRATCH_REG29 0x403a #define MDIO_84833_TOP_CFG_SCRATCH_REG30 0x403b #define MDIO_84833_TOP_CFG_SCRATCH_REG31 0x403c #define MDIO_84833_CMD_HDLR_COMMAND MDIO_84833_TOP_CFG_SCRATCH_REG0 #define MDIO_84833_CMD_HDLR_STATUS MDIO_84833_TOP_CFG_SCRATCH_REG26 #define MDIO_84833_CMD_HDLR_DATA1 MDIO_84833_TOP_CFG_SCRATCH_REG27 #define MDIO_84833_CMD_HDLR_DATA2 MDIO_84833_TOP_CFG_SCRATCH_REG28 #define MDIO_84833_CMD_HDLR_DATA3 MDIO_84833_TOP_CFG_SCRATCH_REG29 #define MDIO_84833_CMD_HDLR_DATA4 MDIO_84833_TOP_CFG_SCRATCH_REG30 #define MDIO_84833_CMD_HDLR_DATA5 MDIO_84833_TOP_CFG_SCRATCH_REG31 /* Mailbox command set used by 84833. */ #define PHY84833_CMD_SET_PAIR_SWAP 0x8001 #define PHY84833_CMD_GET_EEE_MODE 0x8008 #define PHY84833_CMD_SET_EEE_MODE 0x8009 #define PHY84833_CMD_GET_CURRENT_TEMP 0x8031 /* Mailbox status set used by 84833. */ #define PHY84833_STATUS_CMD_RECEIVED 0x0001 #define PHY84833_STATUS_CMD_IN_PROGRESS 0x0002 #define PHY84833_STATUS_CMD_COMPLETE_PASS 0x0004 #define PHY84833_STATUS_CMD_COMPLETE_ERROR 0x0008 #define PHY84833_STATUS_CMD_OPEN_FOR_CMDS 0x0010 #define PHY84833_STATUS_CMD_SYSTEM_BOOT 0x0020 #define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS 0x0040 #define PHY84833_STATUS_CMD_CLEAR_COMPLETE 0x0080 #define PHY84833_STATUS_CMD_OPEN_OVERRIDE 0xa5a5 /* Warpcore clause 45 addressing */ #define MDIO_WC_DEVAD 0x3 #define MDIO_WC_REG_IEEE0BLK_MIICNTL 0x0 #define MDIO_WC_REG_IEEE0BLK_AUTONEGNP 0x7 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT0 0x10 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1 0x11 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2 0x12 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY 0x4000 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ 0x8000 #define MDIO_WC_REG_PCS_STATUS2 0x0021 #define MDIO_WC_REG_PMD_KR_CONTROL 0x0096 #define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL 0x8000 #define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1 0x800e #define MDIO_WC_REG_XGXSBLK1_DESKEW 0x8010 #define MDIO_WC_REG_XGXSBLK1_LANECTRL0 0x8015 #define MDIO_WC_REG_XGXSBLK1_LANECTRL1 0x8016 #define MDIO_WC_REG_XGXSBLK1_LANECTRL2 0x8017 #define MDIO_WC_REG_XGXSBLK1_LANECTRL3 0x8018 #define MDIO_WC_REG_XGXSBLK1_LANETEST0 0x801a #define MDIO_WC_REG_TX0_ANA_CTRL0 0x8061 #define MDIO_WC_REG_TX1_ANA_CTRL0 0x8071 #define MDIO_WC_REG_TX2_ANA_CTRL0 0x8081 #define MDIO_WC_REG_TX3_ANA_CTRL0 0x8091 #define MDIO_WC_REG_TX0_TX_DRIVER 0x8067 #define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET 0x04 #define MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_MASK 0x00f0 #define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET 0x08 #define MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_MASK 0x0f00 #define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET 0x0c #define MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_MASK 0x7000 #define MDIO_WC_REG_TX1_TX_DRIVER 0x8077 #define MDIO_WC_REG_TX2_TX_DRIVER 0x8087 #define MDIO_WC_REG_TX3_TX_DRIVER 0x8097 #define MDIO_WC_REG_RX0_ANARXCONTROL1G 0x80b9 #define MDIO_WC_REG_RX2_ANARXCONTROL1G 0x80d9 #define MDIO_WC_REG_RX0_PCI_CTRL 0x80ba #define MDIO_WC_REG_RX1_PCI_CTRL 0x80ca #define MDIO_WC_REG_RX2_PCI_CTRL 0x80da #define MDIO_WC_REG_RX3_PCI_CTRL 0x80ea #define MDIO_WC_REG_XGXSBLK2_UNICORE_MODE_10G 0x8104 #define MDIO_WC_REG_XGXS_STATUS3 0x8129 #define MDIO_WC_REG_PAR_DET_10G_STATUS 0x8130 #define MDIO_WC_REG_PAR_DET_10G_CTRL 0x8131 #define MDIO_WC_REG_XGXS_STATUS4 0x813c #define MDIO_WC_REG_XGXS_X2_CONTROL2 0x8141 #define MDIO_WC_REG_XGXS_X2_CONTROL3 0x8142 #define MDIO_WC_REG_XGXS_RX_LN_SWAP1 0x816B #define MDIO_WC_REG_XGXS_TX_LN_SWAP1 0x8169 #define MDIO_WC_REG_GP2_STATUS_GP_2_0 0x81d0 #define MDIO_WC_REG_GP2_STATUS_GP_2_1 0x81d1 #define MDIO_WC_REG_GP2_STATUS_GP_2_2 0x81d2 #define MDIO_WC_REG_GP2_STATUS_GP_2_3 0x81d3 #define MDIO_WC_REG_GP2_STATUS_GP_2_4 0x81d4 #define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL 0x1000 #define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CMPL 0x0100 #define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP 0x0010 #define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CAP 0x1 #define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP 0x81EE #define MDIO_WC_REG_UC_INFO_B1_VERSION 0x81F0 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE 0x81F2 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE0_OFFSET 0x0 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT 0x0 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_OPT_LR 0x1 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC 0x2 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_XLAUI 0x3 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_LONG_CH_6G 0x4 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE1_OFFSET 0x4 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE2_OFFSET 0x8 #define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_LANE3_OFFSET 0xc #define MDIO_WC_REG_UC_INFO_B1_CRC 0x81FE #define MDIO_WC_REG_DSC1B0_UC_CTRL 0x820e #define MDIO_WC_REG_DSC1B0_UC_CTRL_RDY4CMD (1<<7) #define MDIO_WC_REG_DSC_SMC 0x8213 #define MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0 0x821e #define MDIO_WC_REG_TX_FIR_TAP 0x82e2 #define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET 0x00 #define MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_MASK 0x000f #define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET 0x04 #define MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_MASK 0x03f0 #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET 0x0a #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK 0x7c00 #define MDIO_WC_REG_TX_FIR_TAP_ENABLE 0x8000 #define MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP 0x82e2 #define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL 0x82e3 #define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL 0x82e6 #define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL 0x82e7 #define MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL 0x82e8 #define MDIO_WC_REG_CL72_USERB0_CL72_MISC4_CONTROL 0x82ec #define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1 0x8300 #define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2 0x8301 #define MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3 0x8302 #define MDIO_WC_REG_SERDESDIGITAL_STATUS1000X1 0x8304 #define MDIO_WC_REG_SERDESDIGITAL_MISC1 0x8308 #define MDIO_WC_REG_SERDESDIGITAL_MISC2 0x8309 #define MDIO_WC_REG_DIGITAL3_UP1 0x8329 #define MDIO_WC_REG_DIGITAL3_LP_UP1 0x832c #define MDIO_WC_REG_DIGITAL4_MISC3 0x833c #define MDIO_WC_REG_DIGITAL4_MISC5 0x833e #define MDIO_WC_REG_DIGITAL5_MISC6 0x8345 #define MDIO_WC_REG_DIGITAL5_MISC7 0x8349 #define MDIO_WC_REG_DIGITAL5_LINK_STATUS 0x834d #define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED 0x834e #define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL 0x8350 #define MDIO_WC_REG_CL49_USERB0_CTRL 0x8368 #define MDIO_WC_REG_CL73_USERB0_CTRL 0x8370 #define MDIO_WC_REG_CL73_USERB0_USTAT 0x8371 #define MDIO_WC_REG_CL73_BAM_CTRL1 0x8372 #define MDIO_WC_REG_CL73_BAM_CTRL2 0x8373 #define MDIO_WC_REG_CL73_BAM_CTRL3 0x8374 #define MDIO_WC_REG_CL73_BAM_CODE_FIELD 0x837b #define MDIO_WC_REG_EEE_COMBO_CONTROL0 0x8390 #define MDIO_WC_REG_TX66_CONTROL 0x83b0 #define MDIO_WC_REG_RX66_CONTROL 0x83c0 #define MDIO_WC_REG_RX66_SCW0 0x83c2 #define MDIO_WC_REG_RX66_SCW1 0x83c3 #define MDIO_WC_REG_RX66_SCW2 0x83c4 #define MDIO_WC_REG_RX66_SCW3 0x83c5 #define MDIO_WC_REG_RX66_SCW0_MASK 0x83c6 #define MDIO_WC_REG_RX66_SCW1_MASK 0x83c7 #define MDIO_WC_REG_RX66_SCW2_MASK 0x83c8 #define MDIO_WC_REG_RX66_SCW3_MASK 0x83c9 #define MDIO_WC_REG_FX100_CTRL1 0x8400 #define MDIO_WC_REG_FX100_CTRL3 0x8402 #define MDIO_WC_REG_CL82_USERB1_TX_CTRL5 0x8436 #define MDIO_WC_REG_CL82_USERB1_TX_CTRL6 0x8437 #define MDIO_WC_REG_CL82_USERB1_TX_CTRL7 0x8438 #define MDIO_WC_REG_CL82_USERB1_TX_CTRL9 0x8439 #define MDIO_WC_REG_CL82_USERB1_RX_CTRL10 0x843a #define MDIO_WC_REG_CL82_USERB1_RX_CTRL11 0x843b #define MDIO_WC_REG_ETA_CL73_OUI1 0x8453 #define MDIO_WC_REG_ETA_CL73_OUI2 0x8454 #define MDIO_WC_REG_ETA_CL73_OUI3 0x8455 #define MDIO_WC_REG_ETA_CL73_LD_BAM_CODE 0x8456 #define MDIO_WC_REG_ETA_CL73_LD_UD_CODE 0x8457 #define MDIO_WC_REG_MICROBLK_CMD 0xffc2 #define MDIO_WC_REG_MICROBLK_DL_STATUS 0xffc5 #define MDIO_WC_REG_MICROBLK_CMD3 0xffcc #define MDIO_WC_REG_AERBLK_AER 0xffde #define MDIO_WC_REG_COMBO_IEEE0_MIICTRL 0xffe0 #define MDIO_WC_REG_COMBO_IEEE0_MIIISTAT 0xffe1 #define MDIO_WC0_XGXS_BLK2_LANE_RESET 0x810A #define MDIO_WC0_XGXS_BLK2_LANE_RESET_RX_BITSHIFT 0 #define MDIO_WC0_XGXS_BLK2_LANE_RESET_TX_BITSHIFT 4 #define MDIO_WC0_XGXS_BLK6_XGXS_X2_CONTROL2 0x8141 #define DIGITAL5_ACTUAL_SPEED_TX_MASK 0x003f /* 54618se */ #define MDIO_REG_GPHY_MII_STATUS 0x1 #define MDIO_REG_GPHY_PHYID_LSB 0x3 #define MDIO_REG_GPHY_CL45_ADDR_REG 0xd #define MDIO_REG_GPHY_CL45_REG_WRITE 0x4000 #define MDIO_REG_GPHY_CL45_REG_READ 0xc000 #define MDIO_REG_GPHY_CL45_DATA_REG 0xe #define MDIO_REG_GPHY_EEE_RESOLVED 0x803e #define MDIO_REG_GPHY_EXP_ACCESS_GATE 0x15 #define MDIO_REG_GPHY_EXP_ACCESS 0x17 #define MDIO_REG_GPHY_EXP_ACCESS_TOP 0xd00 #define MDIO_REG_GPHY_EXP_TOP_2K_BUF 0x40 #define MDIO_REG_GPHY_AUX_STATUS 0x19 #define MDIO_REG_INTR_STATUS 0x1a #define MDIO_REG_INTR_MASK 0x1b #define MDIO_REG_INTR_MASK_LINK_STATUS (0x1 << 1) #define MDIO_REG_GPHY_SHADOW 0x1c #define MDIO_REG_GPHY_SHADOW_LED_SEL1 (0x0d << 10) #define MDIO_REG_GPHY_SHADOW_LED_SEL2 (0x0e << 10) #define MDIO_REG_GPHY_SHADOW_WR_ENA (0x1 << 15) #define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED (0x1e << 10) #define MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD (0x1 << 8) typedef elink_status_t(*read_sfp_module_eeprom_func_p) (struct elink_phy * phy, struct elink_params * params, uint8_t dev_addr, uint16_t addr, uint8_t byte_cnt, uint8_t * o_buf, uint8_t); /********************************************************/ #define ELINK_ETH_HLEN 14 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ #define ELINK_ETH_OVREHEAD (ELINK_ETH_HLEN + 8 + 8) #define ELINK_ETH_MIN_PACKET_SIZE 60 #define ELINK_ETH_MAX_PACKET_SIZE 1500 #define ELINK_ETH_MAX_JUMBO_PACKET_SIZE 9600 #define ELINK_MDIO_ACCESS_TIMEOUT 1000 #define WC_LANE_MAX 4 #define I2C_SWITCH_WIDTH 2 #define I2C_BSC0 0 #define I2C_BSC1 1 #define I2C_WA_RETRY_CNT 3 #define I2C_WA_PWR_ITER (I2C_WA_RETRY_CNT - 1) #define MCPR_IMC_COMMAND_READ_OP 1 #define MCPR_IMC_COMMAND_WRITE_OP 2 /* LED Blink rate that will achieve ~15.9Hz */ #define LED_BLINK_RATE_VAL_E3 354 #define LED_BLINK_RATE_VAL_E1X_E2 480 /***********************************************************/ /* Shortcut definitions */ /***********************************************************/ #define ELINK_NIG_LATCH_BC_ENABLE_MI_INT 0 #define ELINK_NIG_STATUS_EMAC0_MI_INT \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT #define ELINK_NIG_STATUS_XGXS0_LINK10G \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G #define ELINK_NIG_STATUS_XGXS0_LINK_STATUS \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS #define ELINK_NIG_STATUS_XGXS0_LINK_STATUS_SIZE \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE #define ELINK_NIG_STATUS_SERDES0_LINK_STATUS \ NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS #define ELINK_NIG_MASK_MI_INT \ NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT #define ELINK_NIG_MASK_XGXS0_LINK10G \ NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G #define ELINK_NIG_MASK_XGXS0_LINK_STATUS \ NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS #define ELINK_NIG_MASK_SERDES0_LINK_STATUS \ NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS #define ELINK_MDIO_AN_CL73_OR_37_COMPLETE \ (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \ MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE) #define ELINK_XGXS_RESET_BITS \ (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB) #define ELINK_SERDES_RESET_BITS \ (MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN | \ MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD) #define ELINK_AUTONEG_CL37 SHARED_HW_CFG_AN_ENABLE_CL37 #define ELINK_AUTONEG_CL73 SHARED_HW_CFG_AN_ENABLE_CL73 #define ELINK_AUTONEG_BAM SHARED_HW_CFG_AN_ENABLE_BAM #define ELINK_AUTONEG_PARALLEL \ SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION #define ELINK_AUTONEG_SGMII_FIBER_AUTODET \ SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT #define ELINK_AUTONEG_REMOTE_PHY SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY #define ELINK_GP_STATUS_PAUSE_RSOLUTION_TXSIDE \ MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE #define ELINK_GP_STATUS_PAUSE_RSOLUTION_RXSIDE \ MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE #define ELINK_GP_STATUS_SPEED_MASK \ MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK #define ELINK_GP_STATUS_10M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M #define ELINK_GP_STATUS_100M MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M #define ELINK_GP_STATUS_1G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G #define ELINK_GP_STATUS_2_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G #define ELINK_GP_STATUS_5G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G #define ELINK_GP_STATUS_6G MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G #define ELINK_GP_STATUS_10G_HIG \ MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG #define ELINK_GP_STATUS_10G_CX4 \ MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4 #define ELINK_GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX #define ELINK_GP_STATUS_10G_KX4 \ MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4 #define ELINK_GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR #define ELINK_GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI #define ELINK_GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS #define ELINK_GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI #define ELINK_GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2 #define ELINK_LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD #define ELINK_LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD #define ELINK_LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD #define ELINK_LINK_100T4 LINK_STATUS_SPEED_AND_DUPLEX_100T4 #define ELINK_LINK_100TXFD LINK_STATUS_SPEED_AND_DUPLEX_100TXFD #define ELINK_LINK_1000THD LINK_STATUS_SPEED_AND_DUPLEX_1000THD #define ELINK_LINK_1000TFD LINK_STATUS_SPEED_AND_DUPLEX_1000TFD #define ELINK_LINK_1000XFD LINK_STATUS_SPEED_AND_DUPLEX_1000XFD #define ELINK_LINK_2500THD LINK_STATUS_SPEED_AND_DUPLEX_2500THD #define ELINK_LINK_2500TFD LINK_STATUS_SPEED_AND_DUPLEX_2500TFD #define ELINK_LINK_2500XFD LINK_STATUS_SPEED_AND_DUPLEX_2500XFD #define ELINK_LINK_10GTFD LINK_STATUS_SPEED_AND_DUPLEX_10GTFD #define ELINK_LINK_10GXFD LINK_STATUS_SPEED_AND_DUPLEX_10GXFD #define ELINK_LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD #define ELINK_LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD #define ELINK_LINK_UPDATE_MASK \ (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ LINK_STATUS_LINK_UP | \ LINK_STATUS_PHYSICAL_LINK_FLAG | \ LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE) #define ELINK_SFP_EEPROM_CON_TYPE_ADDR 0x2 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_LC 0x7 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21 #define ELINK_SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22 #define ELINK_SFP_EEPROM_COMP_CODE_ADDR 0x3 #define ELINK_SFP_EEPROM_COMP_CODE_SR_MASK (1<<4) #define ELINK_SFP_EEPROM_COMP_CODE_LR_MASK (1<<5) #define ELINK_SFP_EEPROM_COMP_CODE_LRM_MASK (1<<6) #define ELINK_SFP_EEPROM_FC_TX_TECH_ADDR 0x8 #define ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4 #define ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE 0x8 #define ELINK_SFP_EEPROM_OPTIONS_ADDR 0x40 #define ELINK_SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1 #define ELINK_SFP_EEPROM_OPTIONS_SIZE 2 #define ELINK_EDC_MODE_LINEAR 0x0022 #define ELINK_EDC_MODE_LIMITING 0x0044 #define ELINK_EDC_MODE_PASSIVE_DAC 0x0055 #define ELINK_EDC_MODE_ACTIVE_DAC 0x0066 /* ETS defines*/ #define DCBX_INVALID_COS (0xFF) #define ELINK_ETS_BW_LIMIT_CREDIT_UPPER_BOUND (0x5000) #define ELINK_ETS_BW_LIMIT_CREDIT_WEIGHT (0x5000) #define ELINK_ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS (1360) #define ELINK_ETS_E3B0_NIG_MIN_W_VAL_20GBPS (2720) #define ELINK_ETS_E3B0_PBF_MIN_W_VAL (10000) #define ELINK_MAX_PACKET_SIZE (9700) #define MAX_KR_LINK_RETRY 4 /**********************************************************/ /* INTERFACE */ /**********************************************************/ #define CL22_WR_OVER_CL45(_sc, _phy, _bank, _addr, _val) \ elink_cl45_write(_sc, _phy, \ (_phy)->def_md_devad, \ (_bank + (_addr & 0xf)), \ _val) #define CL22_RD_OVER_CL45(_sc, _phy, _bank, _addr, _val) \ elink_cl45_read(_sc, _phy, \ (_phy)->def_md_devad, \ (_bank + (_addr & 0xf)), \ _val) static uint32_t elink_bits_en(struct bnx2x_softc *sc, uint32_t reg, uint32_t bits) { uint32_t val = REG_RD(sc, reg); val |= bits; REG_WR(sc, reg, val); return val; } static uint32_t elink_bits_dis(struct bnx2x_softc *sc, uint32_t reg, uint32_t bits) { uint32_t val = REG_RD(sc, reg); val &= ~bits; REG_WR(sc, reg, val); return val; } /* * elink_check_lfa - This function checks if link reinitialization is required, * or link flap can be avoided. * * @params: link parameters * Returns 0 if Link Flap Avoidance conditions are met otherwise, the failed * condition code. */ static int elink_check_lfa(struct elink_params *params) { uint32_t link_status, cfg_idx, lfa_mask, cfg_size; uint32_t cur_speed_cap_mask, cur_req_fc_auto_adv, additional_config; uint32_t saved_val, req_val, eee_status; struct bnx2x_softc *sc = params->sc; additional_config = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, additional_config)); /* NOTE: must be first condition checked - * to verify DCC bit is cleared in any case! */ if (additional_config & NO_LFA_DUE_TO_DCC_MASK) { PMD_DRV_LOG(DEBUG, "No LFA due to DCC flap after clp exit"); REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, additional_config), additional_config & ~NO_LFA_DUE_TO_DCC_MASK); return LFA_DCC_LFA_DISABLED; } /* Verify that link is up */ link_status = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, port_mb[params->port].link_status)); if (!(link_status & LINK_STATUS_LINK_UP)) return LFA_LINK_DOWN; /* if loaded after BOOT from SAN, don't flap the link in any case and * rely on link set by preboot driver */ if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BOOT_FROM_SAN) return 0; /* Verify that loopback mode is not set */ if (params->loopback_mode) return LFA_LOOPBACK_ENABLED; /* Verify that MFW supports LFA */ if (!params->lfa_base) return LFA_MFW_IS_TOO_OLD; if (params->num_phys == 3) { cfg_size = 2; lfa_mask = 0xffffffff; } else { cfg_size = 1; lfa_mask = 0xffff; } /* Compare Duplex */ saved_val = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, req_duplex)); req_val = params->req_duplex[0] | (params->req_duplex[1] << 16); if ((saved_val & lfa_mask) != (req_val & lfa_mask)) { PMD_DRV_LOG(INFO, "Duplex mismatch %x vs. %x", (saved_val & lfa_mask), (req_val & lfa_mask)); return LFA_DUPLEX_MISMATCH; } /* Compare Flow Control */ saved_val = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, req_flow_ctrl)); req_val = params->req_flow_ctrl[0] | (params->req_flow_ctrl[1] << 16); if ((saved_val & lfa_mask) != (req_val & lfa_mask)) { PMD_DRV_LOG(DEBUG, "Flow control mismatch %x vs. %x", (saved_val & lfa_mask), (req_val & lfa_mask)); return LFA_FLOW_CTRL_MISMATCH; } /* Compare Link Speed */ saved_val = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, req_line_speed)); req_val = params->req_line_speed[0] | (params->req_line_speed[1] << 16); if ((saved_val & lfa_mask) != (req_val & lfa_mask)) { PMD_DRV_LOG(DEBUG, "Link speed mismatch %x vs. %x", (saved_val & lfa_mask), (req_val & lfa_mask)); return LFA_LINK_SPEED_MISMATCH; } for (cfg_idx = 0; cfg_idx < cfg_size; cfg_idx++) { cur_speed_cap_mask = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, speed_cap_mask[cfg_idx])); if (cur_speed_cap_mask != params->speed_cap_mask[cfg_idx]) { PMD_DRV_LOG(DEBUG, "Speed Cap mismatch %x vs. %x", cur_speed_cap_mask, params->speed_cap_mask[cfg_idx]); return LFA_SPEED_CAP_MISMATCH; } } cur_req_fc_auto_adv = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, additional_config)) & REQ_FC_AUTO_ADV_MASK; if ((uint16_t) cur_req_fc_auto_adv != params->req_fc_auto_adv) { PMD_DRV_LOG(DEBUG, "Flow Ctrl AN mismatch %x vs. %x", cur_req_fc_auto_adv, params->req_fc_auto_adv); return LFA_FLOW_CTRL_MISMATCH; } eee_status = REG_RD(sc, params->shmem2_base + offsetof(struct shmem2_region, eee_status[params->port])); if (((eee_status & SHMEM_EEE_LPI_REQUESTED_BIT) ^ (params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI)) || ((eee_status & SHMEM_EEE_REQUESTED_BIT) ^ (params->eee_mode & ELINK_EEE_MODE_ADV_LPI))) { PMD_DRV_LOG(DEBUG, "EEE mismatch %x vs. %x", params->eee_mode, eee_status); return LFA_EEE_MISMATCH; } /* LFA conditions are met */ return 0; } /******************************************************************/ /* EPIO/GPIO section */ /******************************************************************/ static void elink_get_epio(struct bnx2x_softc *sc, uint32_t epio_pin, uint32_t * en) { uint32_t epio_mask, gp_oenable; *en = 0; /* Sanity check */ if (epio_pin > 31) { PMD_DRV_LOG(DEBUG, "Invalid EPIO pin %d to get", epio_pin); return; } epio_mask = 1 << epio_pin; /* Set this EPIO to output */ gp_oenable = REG_RD(sc, MCP_REG_MCPR_GP_OENABLE); REG_WR(sc, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask); *en = (REG_RD(sc, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin; } static void elink_set_epio(struct bnx2x_softc *sc, uint32_t epio_pin, uint32_t en) { uint32_t epio_mask, gp_output, gp_oenable; /* Sanity check */ if (epio_pin > 31) { PMD_DRV_LOG(DEBUG, "Invalid EPIO pin %d to set", epio_pin); return; } PMD_DRV_LOG(DEBUG, "Setting EPIO pin %d to %d", epio_pin, en); epio_mask = 1 << epio_pin; /* Set this EPIO to output */ gp_output = REG_RD(sc, MCP_REG_MCPR_GP_OUTPUTS); if (en) gp_output |= epio_mask; else gp_output &= ~epio_mask; REG_WR(sc, MCP_REG_MCPR_GP_OUTPUTS, gp_output); /* Set the value for this EPIO */ gp_oenable = REG_RD(sc, MCP_REG_MCPR_GP_OENABLE); REG_WR(sc, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask); } static void elink_set_cfg_pin(struct bnx2x_softc *sc, uint32_t pin_cfg, uint32_t val) { if (pin_cfg == PIN_CFG_NA) return; if (pin_cfg >= PIN_CFG_EPIO0) { elink_set_epio(sc, pin_cfg - PIN_CFG_EPIO0, val); } else { uint8_t gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3; uint8_t gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2; elink_cb_gpio_write(sc, gpio_num, (uint8_t) val, gpio_port); } } static uint32_t elink_get_cfg_pin(struct bnx2x_softc *sc, uint32_t pin_cfg, uint32_t * val) { if (pin_cfg == PIN_CFG_NA) return ELINK_STATUS_ERROR; if (pin_cfg >= PIN_CFG_EPIO0) { elink_get_epio(sc, pin_cfg - PIN_CFG_EPIO0, val); } else { uint8_t gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3; uint8_t gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2; *val = elink_cb_gpio_read(sc, gpio_num, gpio_port); } return ELINK_STATUS_OK; } /******************************************************************/ /* PFC section */ /******************************************************************/ static void elink_update_pfc_xmac(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint32_t xmac_base; uint32_t pause_val, pfc0_val, pfc1_val; /* XMAC base adrr */ xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; /* Initialize pause and pfc registers */ pause_val = 0x18000; pfc0_val = 0xFFFF8000; pfc1_val = 0x2; /* No PFC support */ if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)) { /* RX flow control - Process pause frame in receive direction */ if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX) pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN; /* TX flow control - Send pause packet when buffer is full */ if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX) pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN; } else { /* PFC support */ pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN | XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN | XMAC_PFC_CTRL_HI_REG_RX_PFC_EN | XMAC_PFC_CTRL_HI_REG_TX_PFC_EN | XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON; /* Write pause and PFC registers */ REG_WR(sc, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val); pfc1_val &= ~XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON; } /* Write pause and PFC registers */ REG_WR(sc, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val); /* Set MAC address for source TX Pause/PFC frames */ REG_WR(sc, xmac_base + XMAC_REG_CTRL_SA_LO, ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) | (params->mac_addr[5]))); REG_WR(sc, xmac_base + XMAC_REG_CTRL_SA_HI, ((params->mac_addr[0] << 8) | (params->mac_addr[1]))); DELAY(30); } /******************************************************************/ /* MAC/PBF section */ /******************************************************************/ static void elink_set_mdio_clk(struct bnx2x_softc *sc, uint32_t emac_base) { uint32_t new_mode, cur_mode; uint32_t clc_cnt; /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz * (a value of 49==0x31) and make sure that the AUTO poll is off */ cur_mode = REG_RD(sc, emac_base + EMAC_REG_EMAC_MDIO_MODE); if (USES_WARPCORE(sc)) clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT; else clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT; if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) && (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45))) return; new_mode = cur_mode & ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT); new_mode |= clc_cnt; new_mode |= (EMAC_MDIO_MODE_CLAUSE_45); PMD_DRV_LOG(DEBUG, "Changing emac_mode from 0x%x to 0x%x", cur_mode, new_mode); REG_WR(sc, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode); DELAY(40); } static void elink_set_mdio_emac_per_phy(struct bnx2x_softc *sc, struct elink_params *params) { uint8_t phy_index; /* Set mdio clock per phy */ for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys; phy_index++) elink_set_mdio_clk(sc, params->phy[phy_index].mdio_ctrl); } static uint8_t elink_is_4_port_mode(struct bnx2x_softc *sc) { uint32_t port4mode_ovwr_val; /* Check 4-port override enabled */ port4mode_ovwr_val = REG_RD(sc, MISC_REG_PORT4MODE_EN_OVWR); if (port4mode_ovwr_val & (1 << 0)) { /* Return 4-port mode override value */ return ((port4mode_ovwr_val & (1 << 1)) == (1 << 1)); } /* Return 4-port mode from input pin */ return (uint8_t) REG_RD(sc, MISC_REG_PORT4MODE_EN); } static void elink_emac_init(struct elink_params *params) { /* reset and unreset the emac core */ struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; uint32_t val; uint16_t timeout; REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port)); DELAY(5); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port)); /* init emac - use read-modify-write */ /* self clear reset */ val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET)); timeout = 200; do { val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE); PMD_DRV_LOG(DEBUG, "EMAC reset reg is %u", val); if (!timeout) { PMD_DRV_LOG(DEBUG, "EMAC timeout!"); return; } timeout--; } while (val & EMAC_MODE_RESET); elink_set_mdio_emac_per_phy(sc, params); /* Set mac address */ val = ((params->mac_addr[0] << 8) | params->mac_addr[1]); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_MAC_MATCH, val); val = ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) | params->mac_addr[5]); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_MAC_MATCH + 4, val); } static void elink_set_xumac_nig(struct elink_params *params, uint16_t tx_pause_en, uint8_t enable) { struct bnx2x_softc *sc = params->sc; REG_WR(sc, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN, enable); REG_WR(sc, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN, enable); REG_WR(sc, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN : NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en); } static void elink_set_umac_rxtx(struct elink_params *params, uint8_t en) { uint32_t umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0; uint32_t val; struct bnx2x_softc *sc = params->sc; if (!(REG_RD(sc, MISC_REG_RESET_REG_2) & (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port))) return; val = REG_RD(sc, umac_base + UMAC_REG_COMMAND_CONFIG); if (en) val |= (UMAC_COMMAND_CONFIG_REG_TX_ENA | UMAC_COMMAND_CONFIG_REG_RX_ENA); else val &= ~(UMAC_COMMAND_CONFIG_REG_TX_ENA | UMAC_COMMAND_CONFIG_REG_RX_ENA); /* Disable RX and TX */ REG_WR(sc, umac_base + UMAC_REG_COMMAND_CONFIG, val); } static void elink_umac_enable(struct elink_params *params, struct elink_vars *vars, uint8_t lb) { uint32_t val; uint32_t umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0; struct bnx2x_softc *sc = params->sc; /* Reset UMAC */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port)); DELAY(1000 * 1); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port)); PMD_DRV_LOG(DEBUG, "enabling UMAC"); /* This register opens the gate for the UMAC despite its name */ REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + params->port * 4, 1); val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN | UMAC_COMMAND_CONFIG_REG_PAD_EN | UMAC_COMMAND_CONFIG_REG_SW_RESET | UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK; switch (vars->line_speed) { case ELINK_SPEED_10: val |= (0 << 2); break; case ELINK_SPEED_100: val |= (1 << 2); break; case ELINK_SPEED_1000: val |= (2 << 2); break; case ELINK_SPEED_2500: val |= (3 << 2); break; default: PMD_DRV_LOG(DEBUG, "Invalid speed for UMAC %d", vars->line_speed); break; } if (!(vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE; if (!(vars->flow_ctrl & ELINK_FLOW_CTRL_RX)) val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE; if (vars->duplex == DUPLEX_HALF) val |= UMAC_COMMAND_CONFIG_REG_HD_ENA; REG_WR(sc, umac_base + UMAC_REG_COMMAND_CONFIG, val); DELAY(50); /* Configure UMAC for EEE */ if (vars->eee_status & SHMEM_EEE_ADV_STATUS_MASK) { PMD_DRV_LOG(DEBUG, "configured UMAC for EEE"); REG_WR(sc, umac_base + UMAC_REG_UMAC_EEE_CTRL, UMAC_UMAC_EEE_CTRL_REG_EEE_EN); REG_WR(sc, umac_base + UMAC_REG_EEE_WAKE_TIMER, 0x11); } else { REG_WR(sc, umac_base + UMAC_REG_UMAC_EEE_CTRL, 0x0); } /* Set MAC address for source TX Pause/PFC frames (under SW reset) */ REG_WR(sc, umac_base + UMAC_REG_MAC_ADDR0, ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) | (params->mac_addr[5]))); REG_WR(sc, umac_base + UMAC_REG_MAC_ADDR1, ((params->mac_addr[0] << 8) | (params->mac_addr[1]))); /* Enable RX and TX */ val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN; val |= UMAC_COMMAND_CONFIG_REG_TX_ENA | UMAC_COMMAND_CONFIG_REG_RX_ENA; REG_WR(sc, umac_base + UMAC_REG_COMMAND_CONFIG, val); DELAY(50); /* Remove SW Reset */ val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET; /* Check loopback mode */ if (lb) val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA; REG_WR(sc, umac_base + UMAC_REG_COMMAND_CONFIG, val); /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame * length used by the MAC receive logic to check frames. */ REG_WR(sc, umac_base + UMAC_REG_MAXFR, 0x2710); elink_set_xumac_nig(params, ((vars->flow_ctrl & ELINK_FLOW_CTRL_TX) != 0), 1); vars->mac_type = ELINK_MAC_TYPE_UMAC; } /* Define the XMAC mode */ static void elink_xmac_init(struct elink_params *params, uint32_t max_speed) { struct bnx2x_softc *sc = params->sc; uint32_t is_port4mode = elink_is_4_port_mode(sc); /* In 4-port mode, need to set the mode only once, so if XMAC is * already out of reset, it means the mode has already been set, * and it must not* reset the XMAC again, since it controls both * ports of the path */ if (((CHIP_NUM(sc) == CHIP_NUM_57840_4_10) || (CHIP_NUM(sc) == CHIP_NUM_57840_2_20) || (CHIP_NUM(sc) == CHIP_NUM_57840_OBS)) && is_port4mode && (REG_RD(sc, MISC_REG_RESET_REG_2) & MISC_REGISTERS_RESET_REG_2_XMAC)) { PMD_DRV_LOG(DEBUG, "XMAC already out of reset in 4-port mode"); return; } /* Hard reset */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, MISC_REGISTERS_RESET_REG_2_XMAC); DELAY(1000 * 1); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, MISC_REGISTERS_RESET_REG_2_XMAC); if (is_port4mode) { PMD_DRV_LOG(DEBUG, "Init XMAC to 2 ports x 10G per path"); /* Set the number of ports on the system side to up to 2 */ REG_WR(sc, MISC_REG_XMAC_CORE_PORT_MODE, 1); /* Set the number of ports on the Warp Core to 10G */ REG_WR(sc, MISC_REG_XMAC_PHY_PORT_MODE, 3); } else { /* Set the number of ports on the system side to 1 */ REG_WR(sc, MISC_REG_XMAC_CORE_PORT_MODE, 0); if (max_speed == ELINK_SPEED_10000) { PMD_DRV_LOG(DEBUG, "Init XMAC to 10G x 1 port per path"); /* Set the number of ports on the Warp Core to 10G */ REG_WR(sc, MISC_REG_XMAC_PHY_PORT_MODE, 3); } else { PMD_DRV_LOG(DEBUG, "Init XMAC to 20G x 2 ports per path"); /* Set the number of ports on the Warp Core to 20G */ REG_WR(sc, MISC_REG_XMAC_PHY_PORT_MODE, 1); } } /* Soft reset */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, MISC_REGISTERS_RESET_REG_2_XMAC_SOFT); DELAY(1000 * 1); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, MISC_REGISTERS_RESET_REG_2_XMAC_SOFT); } static void elink_set_xmac_rxtx(struct elink_params *params, uint8_t en) { uint8_t port = params->port; struct bnx2x_softc *sc = params->sc; uint32_t pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; uint32_t val; if (REG_RD(sc, MISC_REG_RESET_REG_2) & MISC_REGISTERS_RESET_REG_2_XMAC) { /* Send an indication to change the state in the NIG back to XON * Clearing this bit enables the next set of this bit to get * rising edge */ pfc_ctrl = REG_RD(sc, xmac_base + XMAC_REG_PFC_CTRL_HI); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL_HI, (pfc_ctrl & ~(1 << 1))); REG_WR(sc, xmac_base + XMAC_REG_PFC_CTRL_HI, (pfc_ctrl | (1 << 1))); PMD_DRV_LOG(DEBUG, "Disable XMAC on port %x", port); val = REG_RD(sc, xmac_base + XMAC_REG_CTRL); if (en) val |= (XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN); else val &= ~(XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN); REG_WR(sc, xmac_base + XMAC_REG_CTRL, val); } } static elink_status_t elink_xmac_enable(struct elink_params *params, struct elink_vars *vars, uint8_t lb) { uint32_t val, xmac_base; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "enabling XMAC"); xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; elink_xmac_init(params, vars->line_speed); /* This register determines on which events the MAC will assert * error on the i/f to the NIG along w/ EOP. */ /* This register tells the NIG whether to send traffic to UMAC * or XMAC */ REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + params->port * 4, 0); /* When XMAC is in XLGMII mode, disable sending idles for fault * detection. */ if (!(params->phy[ELINK_INT_PHY].flags & ELINK_FLAGS_TX_ERROR_CHECK)) { REG_WR(sc, xmac_base + XMAC_REG_RX_LSS_CTRL, (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE | XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE)); REG_WR(sc, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0); REG_WR(sc, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS | XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS); } /* Set Max packet size */ REG_WR(sc, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710); /* CRC append for Tx packets */ REG_WR(sc, xmac_base + XMAC_REG_TX_CTRL, 0xC800); /* update PFC */ elink_update_pfc_xmac(params, vars); if (vars->eee_status & SHMEM_EEE_ADV_STATUS_MASK) { PMD_DRV_LOG(DEBUG, "Setting XMAC for EEE"); REG_WR(sc, xmac_base + XMAC_REG_EEE_TIMERS_HI, 0x1380008); REG_WR(sc, xmac_base + XMAC_REG_EEE_CTRL, 0x1); } else { REG_WR(sc, xmac_base + XMAC_REG_EEE_CTRL, 0x0); } /* Enable TX and RX */ val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN; /* Set MAC in XLGMII mode for dual-mode */ if ((vars->line_speed == ELINK_SPEED_20000) && (params->phy[ELINK_INT_PHY].supported & ELINK_SUPPORTED_20000baseKR2_Full)) val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB; /* Check loopback mode */ if (lb) val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK; REG_WR(sc, xmac_base + XMAC_REG_CTRL, val); elink_set_xumac_nig(params, ((vars->flow_ctrl & ELINK_FLOW_CTRL_TX) != 0), 1); vars->mac_type = ELINK_MAC_TYPE_XMAC; return ELINK_STATUS_OK; } static elink_status_t elink_emac_enable(struct elink_params *params, struct elink_vars *vars, uint8_t lb) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; uint32_t val; PMD_DRV_LOG(DEBUG, "enabling EMAC"); /* Disable BMAC */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); /* enable emac and not bmac */ REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + port * 4, 1); #ifdef ELINK_INCLUDE_EMUL /* for paladium */ if (CHIP_REV_IS_EMUL(sc)) { /* Use lane 1 (of lanes 0-3) */ REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, 1); REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 1); } /* for fpga */ else #endif #ifdef ELINK_INCLUDE_FPGA if (CHIP_REV_IS_FPGA(sc)) { /* Use lane 1 (of lanes 0-3) */ PMD_DRV_LOG(DEBUG, "elink_emac_enable: Setting FPGA"); REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, 1); REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 0); } else #endif /* ASIC */ if (vars->phy_flags & PHY_XGXS_FLAG) { uint32_t ser_lane = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); PMD_DRV_LOG(DEBUG, "XGXS"); /* select the master lanes (out of 0-3) */ REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, ser_lane); /* select XGXS */ REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 1); } else { /* SerDes */ PMD_DRV_LOG(DEBUG, "SerDes"); /* select SerDes */ REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 0); } elink_bits_en(sc, emac_base + EMAC_REG_EMAC_RX_MODE, EMAC_RX_MODE_RESET); elink_bits_en(sc, emac_base + EMAC_REG_EMAC_TX_MODE, EMAC_TX_MODE_RESET); #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) if (CHIP_REV_IS_SLOW(sc)) { /* config GMII mode */ val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_MODE, (val | EMAC_MODE_PORT_GMII)); } else { /* ASIC */ #endif /* pause enable/disable */ elink_bits_dis(sc, emac_base + EMAC_REG_EMAC_RX_MODE, EMAC_RX_MODE_FLOW_EN); elink_bits_dis(sc, emac_base + EMAC_REG_EMAC_TX_MODE, (EMAC_TX_MODE_EXT_PAUSE_EN | EMAC_TX_MODE_FLOW_EN)); if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)) { if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX) elink_bits_en(sc, emac_base + EMAC_REG_EMAC_RX_MODE, EMAC_RX_MODE_FLOW_EN); if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX) elink_bits_en(sc, emac_base + EMAC_REG_EMAC_TX_MODE, (EMAC_TX_MODE_EXT_PAUSE_EN | EMAC_TX_MODE_FLOW_EN)); } else elink_bits_en(sc, emac_base + EMAC_REG_EMAC_TX_MODE, EMAC_TX_MODE_FLOW_EN); #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) } #endif /* KEEP_VLAN_TAG, promiscuous */ val = REG_RD(sc, emac_base + EMAC_REG_EMAC_RX_MODE); val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS; /* Setting this bit causes MAC control frames (except for pause * frames) to be passed on for processing. This setting has no * affect on the operation of the pause frames. This bit effects * all packets regardless of RX Parser packet sorting logic. * Turn the PFC off to make sure we are in Xon state before * enabling it. */ elink_cb_reg_write(sc, emac_base + EMAC_REG_RX_PFC_MODE, 0); if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) { PMD_DRV_LOG(DEBUG, "PFC is enabled"); /* Enable PFC again */ elink_cb_reg_write(sc, emac_base + EMAC_REG_RX_PFC_MODE, EMAC_REG_RX_PFC_MODE_RX_EN | EMAC_REG_RX_PFC_MODE_TX_EN | EMAC_REG_RX_PFC_MODE_PRIORITIES); elink_cb_reg_write(sc, emac_base + EMAC_REG_RX_PFC_PARAM, ((0x0101 << EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) | (0x00ff << EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT))); val |= EMAC_RX_MODE_KEEP_MAC_CONTROL; } elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_RX_MODE, val); /* Set Loopback */ val = REG_RD(sc, emac_base + EMAC_REG_EMAC_MODE); if (lb) val |= 0x810; else val &= ~0x810; elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_MODE, val); /* Enable emac */ REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 1); /* Enable emac for jumbo packets */ elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_RX_MTU_SIZE, (EMAC_RX_MTU_SIZE_JUMBO_ENA | (ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD))); /* Strip CRC */ REG_WR(sc, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port * 4, 0x1); /* Disable the NIG in/out to the bmac */ REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0x0); REG_WR(sc, NIG_REG_BMAC0_PAUSE_OUT_EN + port * 4, 0x0); REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0x0); /* Enable the NIG in/out to the emac */ REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0x1); val = 0; if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) || (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val = 1; REG_WR(sc, NIG_REG_EMAC0_PAUSE_OUT_EN + port * 4, val); REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0x1); #ifdef ELINK_INCLUDE_EMUL if (CHIP_REV_IS_EMUL(sc)) { /* Take the BigMac out of reset */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); /* Enable access for bmac registers */ REG_WR(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4, 0x1); } else #endif REG_WR(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4, 0x0); vars->mac_type = ELINK_MAC_TYPE_EMAC; return ELINK_STATUS_OK; } static void elink_update_pfc_bmac1(struct elink_params *params, struct elink_vars *vars) { uint32_t wb_data[2]; struct bnx2x_softc *sc = params->sc; uint32_t bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; uint32_t val = 0x14; if ((!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)) && (vars->flow_ctrl & ELINK_FLOW_CTRL_RX)) /* Enable BigMAC to react on received Pause packets */ val |= (1 << 5); wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2); /* TX control */ val = 0xc0; if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) && (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val |= 0x800000; wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2); } static void elink_update_pfc_bmac2(struct elink_params *params, struct elink_vars *vars, uint8_t is_lb) { /* Set rx control: Strip CRC and enable BigMAC to relay * control packets to the system as well */ uint32_t wb_data[2]; struct bnx2x_softc *sc = params->sc; uint32_t bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; uint32_t val = 0x14; if ((!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED)) && (vars->flow_ctrl & ELINK_FLOW_CTRL_RX)) /* Enable BigMAC to react on received Pause packets */ val |= (1 << 5); wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2); DELAY(30); /* Tx control */ val = 0xc0; if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) && (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val |= 0x800000; wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2); if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) { PMD_DRV_LOG(DEBUG, "PFC is enabled"); /* Enable PFC RX & TX & STATS and set 8 COS */ wb_data[0] = 0x0; wb_data[0] |= (1 << 0); /* RX */ wb_data[0] |= (1 << 1); /* TX */ wb_data[0] |= (1 << 2); /* Force initial Xon */ wb_data[0] |= (1 << 3); /* 8 cos */ wb_data[0] |= (1 << 5); /* STATS */ wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2); /* Clear the force Xon */ wb_data[0] &= ~(1 << 2); } else { PMD_DRV_LOG(DEBUG, "PFC is disabled"); /* Disable PFC RX & TX & STATS and set 8 COS */ wb_data[0] = 0x8; wb_data[1] = 0; } REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2); /* Set Time (based unit is 512 bit time) between automatic * re-sending of PP packets amd enable automatic re-send of * Per-Priroity Packet as long as pp_gen is asserted and * pp_disable is low. */ val = 0x8000; if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) val |= (1 << 16); /* enable automatic re-send */ wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL, wb_data, 2); /* mac control */ val = 0x3; /* Enable RX and TX */ if (is_lb) { val |= 0x4; /* Local loopback */ PMD_DRV_LOG(DEBUG, "enable bmac loopback"); } /* When PFC enabled, Pass pause frames towards the NIG. */ if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) val |= ((1 << 6) | (1 << 5)); wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2); } /****************************************************************************** * Description: * This function is needed because NIG ARB_CREDIT_WEIGHT_X are * not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable. ******************************************************************************/ static elink_status_t elink_pfc_nig_rx_priority_mask(struct bnx2x_softc *sc, uint8_t cos_entry, uint32_t priority_mask, uint8_t port) { uint32_t nig_reg_rx_priority_mask_add = 0; switch (cos_entry) { case 0: nig_reg_rx_priority_mask_add = (port) ? NIG_REG_P1_RX_COS0_PRIORITY_MASK : NIG_REG_P0_RX_COS0_PRIORITY_MASK; break; case 1: nig_reg_rx_priority_mask_add = (port) ? NIG_REG_P1_RX_COS1_PRIORITY_MASK : NIG_REG_P0_RX_COS1_PRIORITY_MASK; break; case 2: nig_reg_rx_priority_mask_add = (port) ? NIG_REG_P1_RX_COS2_PRIORITY_MASK : NIG_REG_P0_RX_COS2_PRIORITY_MASK; break; case 3: if (port) return ELINK_STATUS_ERROR; nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK; break; case 4: if (port) return ELINK_STATUS_ERROR; nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK; break; case 5: if (port) return ELINK_STATUS_ERROR; nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK; break; } REG_WR(sc, nig_reg_rx_priority_mask_add, priority_mask); return ELINK_STATUS_OK; } static void elink_update_mng(struct elink_params *params, uint32_t link_status) { struct bnx2x_softc *sc = params->sc; REG_WR(sc, params->shmem_base + offsetof(struct shmem_region, port_mb[params->port].link_status), link_status); } static void elink_update_link_attr(struct elink_params *params, uint32_t link_attr) { struct bnx2x_softc *sc = params->sc; if (SHMEM2_HAS(sc, link_attr_sync)) REG_WR(sc, params->shmem2_base + offsetof(struct shmem2_region, link_attr_sync[params->port]), link_attr); } static void elink_update_pfc_nig(struct elink_params *params, struct elink_nig_brb_pfc_port_params *nig_params) { uint32_t xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0; uint32_t llfc_enable = 0, xcm_out_en = 0, hwpfc_enable = 0; uint32_t pkt_priority_to_cos = 0; struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; int set_pfc = params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED; PMD_DRV_LOG(DEBUG, "updating pfc nig parameters"); /* When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set * MAC control frames (that are not pause packets) * will be forwarded to the XCM. */ xcm_mask = REG_RD(sc, port ? NIG_REG_LLH1_XCM_MASK : NIG_REG_LLH0_XCM_MASK); /* NIG params will override non PFC params, since it's possible to * do transition from PFC to SAFC */ if (set_pfc) { pause_enable = 0; llfc_out_en = 0; llfc_enable = 0; if (CHIP_IS_E3(sc)) ppp_enable = 0; else ppp_enable = 1; xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN : NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN); xcm_out_en = 0; hwpfc_enable = 1; } else { if (nig_params) { llfc_out_en = nig_params->llfc_out_en; llfc_enable = nig_params->llfc_enable; pause_enable = nig_params->pause_enable; } else /* Default non PFC mode - PAUSE */ pause_enable = 1; xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN : NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN); xcm_out_en = 1; } if (CHIP_IS_E3(sc)) REG_WR(sc, port ? NIG_REG_BRB1_PAUSE_IN_EN : NIG_REG_BRB0_PAUSE_IN_EN, pause_enable); REG_WR(sc, port ? NIG_REG_LLFC_OUT_EN_1 : NIG_REG_LLFC_OUT_EN_0, llfc_out_en); REG_WR(sc, port ? NIG_REG_LLFC_ENABLE_1 : NIG_REG_LLFC_ENABLE_0, llfc_enable); REG_WR(sc, port ? NIG_REG_PAUSE_ENABLE_1 : NIG_REG_PAUSE_ENABLE_0, pause_enable); REG_WR(sc, port ? NIG_REG_PPP_ENABLE_1 : NIG_REG_PPP_ENABLE_0, ppp_enable); REG_WR(sc, port ? NIG_REG_LLH1_XCM_MASK : NIG_REG_LLH0_XCM_MASK, xcm_mask); REG_WR(sc, port ? NIG_REG_LLFC_EGRESS_SRC_ENABLE_1 : NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7); /* Output enable for RX_XCM # IF */ REG_WR(sc, port ? NIG_REG_XCM1_OUT_EN : NIG_REG_XCM0_OUT_EN, xcm_out_en); /* HW PFC TX enable */ REG_WR(sc, port ? NIG_REG_P1_HWPFC_ENABLE : NIG_REG_P0_HWPFC_ENABLE, hwpfc_enable); if (nig_params) { uint8_t i = 0; pkt_priority_to_cos = nig_params->pkt_priority_to_cos; for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++) elink_pfc_nig_rx_priority_mask(sc, i, nig_params-> rx_cos_priority_mask[i], port); REG_WR(sc, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 : NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0, nig_params->llfc_high_priority_classes); REG_WR(sc, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 : NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0, nig_params->llfc_low_priority_classes); } REG_WR(sc, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS : NIG_REG_P0_PKT_PRIORITY_TO_COS, pkt_priority_to_cos); } elink_status_t elink_update_pfc(struct elink_params *params, struct elink_vars *vars, struct elink_nig_brb_pfc_port_params *pfc_params) { /* The PFC and pause are orthogonal to one another, meaning when * PFC is enabled, the pause are disabled, and when PFC is * disabled, pause are set according to the pause result. */ uint32_t val; struct bnx2x_softc *sc = params->sc; elink_status_t elink_status = ELINK_STATUS_OK; uint8_t bmac_loopback = (params->loopback_mode == ELINK_LOOPBACK_BMAC); if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) vars->link_status |= LINK_STATUS_PFC_ENABLED; else vars->link_status &= ~LINK_STATUS_PFC_ENABLED; elink_update_mng(params, vars->link_status); /* Update NIG params */ elink_update_pfc_nig(params, pfc_params); if (!vars->link_up) return elink_status; PMD_DRV_LOG(DEBUG, "About to update PFC in BMAC"); if (CHIP_IS_E3(sc)) { if (vars->mac_type == ELINK_MAC_TYPE_XMAC) elink_update_pfc_xmac(params, vars); } else { val = REG_RD(sc, MISC_REG_RESET_REG_2); if ((val & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) == 0) { PMD_DRV_LOG(DEBUG, "About to update PFC in EMAC"); elink_emac_enable(params, vars, 0); return elink_status; } if (CHIP_IS_E2(sc)) elink_update_pfc_bmac2(params, vars, bmac_loopback); else elink_update_pfc_bmac1(params, vars); val = 0; if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) || (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val = 1; REG_WR(sc, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port * 4, val); } return elink_status; } static elink_status_t elink_bmac1_enable(struct elink_params *params, struct elink_vars *vars, uint8_t is_lb) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; uint32_t wb_data[2]; uint32_t val; PMD_DRV_LOG(DEBUG, "Enabling BigMAC1"); /* XGXS control */ wb_data[0] = 0x3c; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL, wb_data, 2); /* TX MAC SA */ wb_data[0] = ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) | params->mac_addr[5]); wb_data[1] = ((params->mac_addr[0] << 8) | params->mac_addr[1]); REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2); /* MAC control */ val = 0x3; if (is_lb) { val |= 0x4; PMD_DRV_LOG(DEBUG, "enable bmac loopback"); } wb_data[0] = val; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2); /* Set rx mtu */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2); elink_update_pfc_bmac1(params, vars); /* Set tx mtu */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2); /* Set cnt max size */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2); /* Configure SAFC */ wb_data[0] = 0x1000200; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS, wb_data, 2); #ifdef ELINK_INCLUDE_EMUL /* Fix for emulation */ if (CHIP_REV_IS_EMUL(sc)) { wb_data[0] = 0xf000; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD, wb_data, 2); } #endif return ELINK_STATUS_OK; } static elink_status_t elink_bmac2_enable(struct elink_params *params, struct elink_vars *vars, uint8_t is_lb) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; uint32_t wb_data[2]; PMD_DRV_LOG(DEBUG, "Enabling BigMAC2"); wb_data[0] = 0; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2); DELAY(30); /* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */ wb_data[0] = 0x3c; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_BMAC_XGXS_CONTROL, wb_data, 2); DELAY(30); /* TX MAC SA */ wb_data[0] = ((params->mac_addr[2] << 24) | (params->mac_addr[3] << 16) | (params->mac_addr[4] << 8) | params->mac_addr[5]); wb_data[1] = ((params->mac_addr[0] << 8) | params->mac_addr[1]); REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR, wb_data, 2); DELAY(30); /* Configure SAFC */ wb_data[0] = 0x1000200; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS, wb_data, 2); DELAY(30); /* Set RX MTU */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2); DELAY(30); /* Set TX MTU */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2); DELAY(30); /* Set cnt max size */ wb_data[0] = ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD - 2; wb_data[1] = 0; REG_WR_DMAE(sc, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2); DELAY(30); elink_update_pfc_bmac2(params, vars, is_lb); return ELINK_STATUS_OK; } static elink_status_t elink_bmac_enable(struct elink_params *params, struct elink_vars *vars, uint8_t is_lb, uint8_t reset_bmac) { elink_status_t rc = ELINK_STATUS_OK; uint8_t port = params->port; struct bnx2x_softc *sc = params->sc; uint32_t val; /* Reset and unreset the BigMac */ if (reset_bmac) { REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); DELAY(1000 * 1); } REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); /* Enable access for bmac registers */ REG_WR(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4, 0x1); /* Enable BMAC according to BMAC type */ if (CHIP_IS_E2(sc)) rc = elink_bmac2_enable(params, vars, is_lb); else rc = elink_bmac1_enable(params, vars, is_lb); REG_WR(sc, NIG_REG_XGXS_SERDES0_MODE_SEL + port * 4, 0x1); REG_WR(sc, NIG_REG_XGXS_LANE_SEL_P0 + port * 4, 0x0); REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + port * 4, 0x0); val = 0; if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) || (vars->flow_ctrl & ELINK_FLOW_CTRL_TX)) val = 1; REG_WR(sc, NIG_REG_BMAC0_PAUSE_OUT_EN + port * 4, val); REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0x0); REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0x0); REG_WR(sc, NIG_REG_EMAC0_PAUSE_OUT_EN + port * 4, 0x0); REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0x1); REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0x1); vars->mac_type = ELINK_MAC_TYPE_BMAC; return rc; } static void elink_set_bmac_rx(struct bnx2x_softc *sc, uint8_t port, uint8_t en) { uint32_t bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; uint32_t wb_data[2]; uint32_t nig_bmac_enable = REG_RD(sc, NIG_REG_BMAC0_REGS_OUT_EN + port * 4); if (CHIP_IS_E2(sc)) bmac_addr += BIGMAC2_REGISTER_BMAC_CONTROL; else bmac_addr += BIGMAC_REGISTER_BMAC_CONTROL; /* Only if the bmac is out of reset */ if (REG_RD(sc, MISC_REG_RESET_REG_2) & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) && nig_bmac_enable) { /* Clear Rx Enable bit in BMAC_CONTROL register */ REG_RD_DMAE(sc, bmac_addr, wb_data, 2); if (en) wb_data[0] |= ELINK_BMAC_CONTROL_RX_ENABLE; else wb_data[0] &= ~ELINK_BMAC_CONTROL_RX_ENABLE; REG_WR_DMAE(sc, bmac_addr, wb_data, 2); DELAY(1000 * 1); } } static elink_status_t elink_pbf_update(struct elink_params *params, uint32_t flow_ctrl, uint32_t line_speed) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t init_crd, crd; uint32_t count = 1000; /* Disable port */ REG_WR(sc, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port * 4, 0x1); /* Wait for init credit */ init_crd = REG_RD(sc, PBF_REG_P0_INIT_CRD + port * 4); crd = REG_RD(sc, PBF_REG_P0_CREDIT + port * 8); PMD_DRV_LOG(DEBUG, "init_crd 0x%x crd 0x%x", init_crd, crd); while ((init_crd != crd) && count) { DELAY(1000 * 5); crd = REG_RD(sc, PBF_REG_P0_CREDIT + port * 8); count--; } crd = REG_RD(sc, PBF_REG_P0_CREDIT + port * 8); if (init_crd != crd) { PMD_DRV_LOG(DEBUG, "BUG! init_crd 0x%x != crd 0x%x", init_crd, crd); return ELINK_STATUS_ERROR; } if (flow_ctrl & ELINK_FLOW_CTRL_RX || line_speed == ELINK_SPEED_10 || line_speed == ELINK_SPEED_100 || line_speed == ELINK_SPEED_1000 || line_speed == ELINK_SPEED_2500) { REG_WR(sc, PBF_REG_P0_PAUSE_ENABLE + port * 4, 1); /* Update threshold */ REG_WR(sc, PBF_REG_P0_ARB_THRSH + port * 4, 0); /* Update init credit */ init_crd = 778; /* (800-18-4) */ } else { uint32_t thresh = (ELINK_ETH_MAX_JUMBO_PACKET_SIZE + ELINK_ETH_OVREHEAD) / 16; REG_WR(sc, PBF_REG_P0_PAUSE_ENABLE + port * 4, 0); /* Update threshold */ REG_WR(sc, PBF_REG_P0_ARB_THRSH + port * 4, thresh); /* Update init credit */ switch (line_speed) { case ELINK_SPEED_10000: init_crd = thresh + 553 - 22; break; default: PMD_DRV_LOG(DEBUG, "Invalid line_speed 0x%x", line_speed); return ELINK_STATUS_ERROR; } } REG_WR(sc, PBF_REG_P0_INIT_CRD + port * 4, init_crd); PMD_DRV_LOG(DEBUG, "PBF updated to speed %d credit %d", line_speed, init_crd); /* Probe the credit changes */ REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 0x1); DELAY(1000 * 5); REG_WR(sc, PBF_REG_INIT_P0 + port * 4, 0x0); /* Enable port */ REG_WR(sc, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port * 4, 0x0); return ELINK_STATUS_OK; } /** * elink_get_emac_base - retrive emac base address * * @bp: driver handle * @mdc_mdio_access: access type * @port: port id * * This function selects the MDC/MDIO access (through emac0 or * emac1) depend on the mdc_mdio_access, port, port swapped. Each * phy has a default access mode, which could also be overridden * by nvram configuration. This parameter, whether this is the * default phy configuration, or the nvram overrun * configuration, is passed here as mdc_mdio_access and selects * the emac_base for the CL45 read/writes operations */ static uint32_t elink_get_emac_base(struct bnx2x_softc *sc, uint32_t mdc_mdio_access, uint8_t port) { uint32_t emac_base = 0; switch (mdc_mdio_access) { case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE: break; case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0: if (REG_RD(sc, NIG_REG_PORT_SWAP)) emac_base = GRCBASE_EMAC1; else emac_base = GRCBASE_EMAC0; break; case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1: if (REG_RD(sc, NIG_REG_PORT_SWAP)) emac_base = GRCBASE_EMAC0; else emac_base = GRCBASE_EMAC1; break; case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH: emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; break; case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED: emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1; break; default: break; } return emac_base; } /******************************************************************/ /* CL22 access functions */ /******************************************************************/ static elink_status_t elink_cl22_write(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t reg, uint16_t val) { uint32_t tmp, mode; uint8_t i; elink_status_t rc = ELINK_STATUS_OK; /* Switch to CL22 */ mode = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode & ~EMAC_MDIO_MODE_CLAUSE_45); /* Address */ tmp = ((phy->addr << 21) | (reg << 16) | val | EMAC_MDIO_COMM_COMMAND_WRITE_22 | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); for (i = 0; i < 50; i++) { DELAY(10); tmp = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { DELAY(5); break; } } if (tmp & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "write phy register failed"); rc = ELINK_STATUS_TIMEOUT; } REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode); return rc; } static elink_status_t elink_cl22_read(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t reg, uint16_t * ret_val) { uint32_t val, mode; uint16_t i; elink_status_t rc = ELINK_STATUS_OK; /* Switch to CL22 */ mode = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode & ~EMAC_MDIO_MODE_CLAUSE_45); /* Address */ val = ((phy->addr << 21) | (reg << 16) | EMAC_MDIO_COMM_COMMAND_READ_22 | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); for (i = 0; i < 50; i++) { DELAY(10); val = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(val & EMAC_MDIO_COMM_START_BUSY)) { *ret_val = (uint16_t) (val & EMAC_MDIO_COMM_DATA); DELAY(5); break; } } if (val & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "read phy register failed"); *ret_val = 0; rc = ELINK_STATUS_TIMEOUT; } REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode); return rc; } /******************************************************************/ /* CL45 access functions */ /******************************************************************/ static elink_status_t elink_cl45_read(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t devad, uint16_t reg, uint16_t * ret_val) { uint32_t val; uint16_t i; elink_status_t rc = ELINK_STATUS_OK; if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_G) { elink_set_mdio_clk(sc, phy->mdio_ctrl); } if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0) elink_bits_en(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); /* Address */ val = ((phy->addr << 21) | (devad << 16) | reg | EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); for (i = 0; i < 50; i++) { DELAY(10); val = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(val & EMAC_MDIO_COMM_START_BUSY)) { DELAY(5); break; } } if (val & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "read phy register failed"); elink_cb_event_log(sc, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout" *ret_val = 0; rc = ELINK_STATUS_TIMEOUT; } else { /* Data */ val = ((phy->addr << 21) | (devad << 16) | EMAC_MDIO_COMM_COMMAND_READ_45 | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); for (i = 0; i < 50; i++) { DELAY(10); val = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(val & EMAC_MDIO_COMM_START_BUSY)) { *ret_val = (uint16_t) (val & EMAC_MDIO_COMM_DATA); break; } } if (val & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "read phy register failed"); elink_cb_event_log(sc, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout" *ret_val = 0; rc = ELINK_STATUS_TIMEOUT; } } /* Work around for E3 A0 */ if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA) { phy->flags ^= ELINK_FLAGS_DUMMY_READ; if (phy->flags & ELINK_FLAGS_DUMMY_READ) { uint16_t temp_val; elink_cl45_read(sc, phy, devad, 0xf, &temp_val); } } if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0) elink_bits_dis(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); return rc; } static elink_status_t elink_cl45_write(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t devad, uint16_t reg, uint16_t val) { uint32_t tmp; uint8_t i; elink_status_t rc = ELINK_STATUS_OK; if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_G) { elink_set_mdio_clk(sc, phy->mdio_ctrl); } if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0) elink_bits_en(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); /* Address */ tmp = ((phy->addr << 21) | (devad << 16) | reg | EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); for (i = 0; i < 50; i++) { DELAY(10); tmp = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { DELAY(5); break; } } if (tmp & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "write phy register failed"); elink_cb_event_log(sc, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout" rc = ELINK_STATUS_TIMEOUT; } else { /* Data */ tmp = ((phy->addr << 21) | (devad << 16) | val | EMAC_MDIO_COMM_COMMAND_WRITE_45 | EMAC_MDIO_COMM_START_BUSY); REG_WR(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); for (i = 0; i < 50; i++) { DELAY(10); tmp = REG_RD(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { DELAY(5); break; } } if (tmp & EMAC_MDIO_COMM_START_BUSY) { PMD_DRV_LOG(DEBUG, "write phy register failed"); elink_cb_event_log(sc, ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT); // "MDC/MDIO access timeout" rc = ELINK_STATUS_TIMEOUT; } } /* Work around for E3 A0 */ if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA) { phy->flags ^= ELINK_FLAGS_DUMMY_READ; if (phy->flags & ELINK_FLAGS_DUMMY_READ) { uint16_t temp_val; elink_cl45_read(sc, phy, devad, 0xf, &temp_val); } } if (phy->flags & ELINK_FLAGS_MDC_MDIO_WA_B0) elink_bits_dis(sc, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS, EMAC_MDIO_STATUS_10MB); return rc; } /******************************************************************/ /* EEE section */ /******************************************************************/ static uint8_t elink_eee_has_cap(struct elink_params *params) { struct bnx2x_softc *sc = params->sc; if (REG_RD(sc, params->shmem2_base) <= offsetof(struct shmem2_region, eee_status[params->port])) return 0; return 1; } static elink_status_t elink_eee_nvram_to_time(uint32_t nvram_mode, uint32_t * idle_timer) { switch (nvram_mode) { case PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED: *idle_timer = ELINK_EEE_MODE_NVRAM_BALANCED_TIME; break; case PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE: *idle_timer = ELINK_EEE_MODE_NVRAM_AGGRESSIVE_TIME; break; case PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY: *idle_timer = ELINK_EEE_MODE_NVRAM_LATENCY_TIME; break; default: *idle_timer = 0; break; } return ELINK_STATUS_OK; } static elink_status_t elink_eee_time_to_nvram(uint32_t idle_timer, uint32_t * nvram_mode) { switch (idle_timer) { case ELINK_EEE_MODE_NVRAM_BALANCED_TIME: *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED; break; case ELINK_EEE_MODE_NVRAM_AGGRESSIVE_TIME: *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE; break; case ELINK_EEE_MODE_NVRAM_LATENCY_TIME: *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY; break; default: *nvram_mode = PORT_FEAT_CFG_EEE_POWER_MODE_DISABLED; break; } return ELINK_STATUS_OK; } static uint32_t elink_eee_calc_timer(struct elink_params *params) { uint32_t eee_mode, eee_idle; struct bnx2x_softc *sc = params->sc; if (params->eee_mode & ELINK_EEE_MODE_OVERRIDE_NVRAM) { if (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME) { /* time value in eee_mode --> used directly */ eee_idle = params->eee_mode & ELINK_EEE_MODE_TIMER_MASK; } else { /* hsi value in eee_mode --> time */ if (elink_eee_nvram_to_time(params->eee_mode & ELINK_EEE_MODE_NVRAM_MASK, &eee_idle)) return 0; } } else { /* hsi values in nvram --> time */ eee_mode = ((REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config [params-> port].eee_power_mode)) & PORT_FEAT_CFG_EEE_POWER_MODE_MASK) >> PORT_FEAT_CFG_EEE_POWER_MODE_SHIFT); if (elink_eee_nvram_to_time(eee_mode, &eee_idle)) return 0; } return eee_idle; } static elink_status_t elink_eee_set_timers(struct elink_params *params, struct elink_vars *vars) { uint32_t eee_idle = 0, eee_mode; struct bnx2x_softc *sc = params->sc; eee_idle = elink_eee_calc_timer(params); if (eee_idle) { REG_WR(sc, MISC_REG_CPMU_LP_IDLE_THR_P0 + (params->port << 2), eee_idle); } else if ((params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI) && (params->eee_mode & ELINK_EEE_MODE_OVERRIDE_NVRAM) && (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME)) { PMD_DRV_LOG(DEBUG, "Error: Tx LPI is enabled with timer 0"); return ELINK_STATUS_ERROR; } vars->eee_status &= ~(SHMEM_EEE_TIMER_MASK | SHMEM_EEE_TIME_OUTPUT_BIT); if (params->eee_mode & ELINK_EEE_MODE_OUTPUT_TIME) { /* eee_idle in 1u --> eee_status in 16u */ eee_idle >>= 4; vars->eee_status |= (eee_idle & SHMEM_EEE_TIMER_MASK) | SHMEM_EEE_TIME_OUTPUT_BIT; } else { if (elink_eee_time_to_nvram(eee_idle, &eee_mode)) return ELINK_STATUS_ERROR; vars->eee_status |= eee_mode; } return ELINK_STATUS_OK; } static elink_status_t elink_eee_initial_config(struct elink_params *params, struct elink_vars *vars, uint8_t mode) { vars->eee_status |= ((uint32_t) mode) << SHMEM_EEE_SUPPORTED_SHIFT; /* Propogate params' bits --> vars (for migration exposure) */ if (params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI) vars->eee_status |= SHMEM_EEE_LPI_REQUESTED_BIT; else vars->eee_status &= ~SHMEM_EEE_LPI_REQUESTED_BIT; if (params->eee_mode & ELINK_EEE_MODE_ADV_LPI) vars->eee_status |= SHMEM_EEE_REQUESTED_BIT; else vars->eee_status &= ~SHMEM_EEE_REQUESTED_BIT; return elink_eee_set_timers(params, vars); } static elink_status_t elink_eee_disable(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; /* Make Certain LPI is disabled */ REG_WR(sc, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2), 0); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, 0x0); vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK; return ELINK_STATUS_OK; } static elink_status_t elink_eee_advertise(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars, uint8_t modes) { struct bnx2x_softc *sc = params->sc; uint16_t val = 0; /* Mask events preventing LPI generation */ REG_WR(sc, MISC_REG_CPMU_LP_MASK_EXT_P0 + (params->port << 2), 0xfc20); if (modes & SHMEM_EEE_10G_ADV) { PMD_DRV_LOG(DEBUG, "Advertise 10GBase-T EEE"); val |= 0x8; } if (modes & SHMEM_EEE_1G_ADV) { PMD_DRV_LOG(DEBUG, "Advertise 1GBase-T EEE"); val |= 0x4; } elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, val); vars->eee_status &= ~SHMEM_EEE_ADV_STATUS_MASK; vars->eee_status |= (modes << SHMEM_EEE_ADV_STATUS_SHIFT); return ELINK_STATUS_OK; } static void elink_update_mng_eee(struct elink_params *params, uint32_t eee_status) { struct bnx2x_softc *sc = params->sc; if (elink_eee_has_cap(params)) REG_WR(sc, params->shmem2_base + offsetof(struct shmem2_region, eee_status[params->port]), eee_status); } static void elink_eee_an_resolve(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t adv = 0, lp = 0; uint32_t lp_adv = 0; uint8_t neg = 0; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, &adv); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_EEE_ADV, &lp); if (lp & 0x2) { lp_adv |= SHMEM_EEE_100M_ADV; if (adv & 0x2) { if (vars->line_speed == ELINK_SPEED_100) neg = 1; PMD_DRV_LOG(DEBUG, "EEE negotiated - 100M"); } } if (lp & 0x14) { lp_adv |= SHMEM_EEE_1G_ADV; if (adv & 0x14) { if (vars->line_speed == ELINK_SPEED_1000) neg = 1; PMD_DRV_LOG(DEBUG, "EEE negotiated - 1G"); } } if (lp & 0x68) { lp_adv |= SHMEM_EEE_10G_ADV; if (adv & 0x68) { if (vars->line_speed == ELINK_SPEED_10000) neg = 1; PMD_DRV_LOG(DEBUG, "EEE negotiated - 10G"); } } vars->eee_status &= ~SHMEM_EEE_LP_ADV_STATUS_MASK; vars->eee_status |= (lp_adv << SHMEM_EEE_LP_ADV_STATUS_SHIFT); if (neg) { PMD_DRV_LOG(DEBUG, "EEE is active"); vars->eee_status |= SHMEM_EEE_ACTIVE_BIT; } } /******************************************************************/ /* BSC access functions from E3 */ /******************************************************************/ static void elink_bsc_module_sel(struct elink_params *params) { int idx; uint32_t board_cfg, sfp_ctrl; uint32_t i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH]; struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; /* Read I2C output PINs */ board_cfg = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.shared_hw_config.board)); i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK; i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >> SHARED_HW_CFG_E3_I2C_MUX1_SHIFT; /* Read I2C output value */ sfp_ctrl = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. e3_cmn_pin_cfg)); i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0; i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0; PMD_DRV_LOG(DEBUG, "Setting BSC switch"); for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++) elink_set_cfg_pin(sc, i2c_pins[idx], i2c_val[idx]); } static elink_status_t elink_bsc_read(struct elink_params *params, struct bnx2x_softc *sc, uint8_t sl_devid, uint16_t sl_addr, uint8_t lc_addr, uint8_t xfer_cnt, uint32_t * data_array) { uint32_t val, i; elink_status_t rc = ELINK_STATUS_OK; if (xfer_cnt > 16) { PMD_DRV_LOG(DEBUG, "invalid xfer_cnt %d. Max is 16 bytes", xfer_cnt); return ELINK_STATUS_ERROR; } if (params) elink_bsc_module_sel(params); xfer_cnt = 16 - lc_addr; /* Enable the engine */ val = REG_RD(sc, MCP_REG_MCPR_IMC_COMMAND); val |= MCPR_IMC_COMMAND_ENABLE; REG_WR(sc, MCP_REG_MCPR_IMC_COMMAND, val); /* Program slave device ID */ val = (sl_devid << 16) | sl_addr; REG_WR(sc, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val); /* Start xfer with 0 byte to update the address pointer ??? */ val = (MCPR_IMC_COMMAND_ENABLE) | (MCPR_IMC_COMMAND_WRITE_OP << MCPR_IMC_COMMAND_OPERATION_BITSHIFT) | (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0); REG_WR(sc, MCP_REG_MCPR_IMC_COMMAND, val); /* Poll for completion */ i = 0; val = REG_RD(sc, MCP_REG_MCPR_IMC_COMMAND); while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) { DELAY(10); val = REG_RD(sc, MCP_REG_MCPR_IMC_COMMAND); if (i++ > 1000) { PMD_DRV_LOG(DEBUG, "wr 0 byte timed out after %d try", i); rc = ELINK_STATUS_TIMEOUT; break; } } if (rc == ELINK_STATUS_TIMEOUT) return rc; /* Start xfer with read op */ val = (MCPR_IMC_COMMAND_ENABLE) | (MCPR_IMC_COMMAND_READ_OP << MCPR_IMC_COMMAND_OPERATION_BITSHIFT) | (lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (xfer_cnt); REG_WR(sc, MCP_REG_MCPR_IMC_COMMAND, val); /* Poll for completion */ i = 0; val = REG_RD(sc, MCP_REG_MCPR_IMC_COMMAND); while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) { DELAY(10); val = REG_RD(sc, MCP_REG_MCPR_IMC_COMMAND); if (i++ > 1000) { PMD_DRV_LOG(DEBUG, "rd op timed out after %d try", i); rc = ELINK_STATUS_TIMEOUT; break; } } if (rc == ELINK_STATUS_TIMEOUT) return rc; for (i = (lc_addr >> 2); i < 4; i++) { data_array[i] = REG_RD(sc, (MCP_REG_MCPR_IMC_DATAREG0 + i * 4)); #ifdef __BIG_ENDIAN data_array[i] = ((data_array[i] & 0x000000ff) << 24) | ((data_array[i] & 0x0000ff00) << 8) | ((data_array[i] & 0x00ff0000) >> 8) | ((data_array[i] & 0xff000000) >> 24); #endif } return rc; } static void elink_cl45_read_or_write(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t devad, uint16_t reg, uint16_t or_val) { uint16_t val; elink_cl45_read(sc, phy, devad, reg, &val); elink_cl45_write(sc, phy, devad, reg, val | or_val); } static void elink_cl45_read_and_write(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t devad, uint16_t reg, uint16_t and_val) { uint16_t val; elink_cl45_read(sc, phy, devad, reg, &val); elink_cl45_write(sc, phy, devad, reg, val & and_val); } static uint8_t elink_get_warpcore_lane(struct elink_params *params) { uint8_t lane = 0; struct bnx2x_softc *sc = params->sc; uint32_t path_swap, path_swap_ovr; uint8_t path, port; path = SC_PATH(sc); port = params->port; if (elink_is_4_port_mode(sc)) { uint32_t port_swap, port_swap_ovr; /* Figure out path swap value */ path_swap_ovr = REG_RD(sc, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR); if (path_swap_ovr & 0x1) path_swap = (path_swap_ovr & 0x2); else path_swap = REG_RD(sc, MISC_REG_FOUR_PORT_PATH_SWAP); if (path_swap) path = path ^ 1; /* Figure out port swap value */ port_swap_ovr = REG_RD(sc, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR); if (port_swap_ovr & 0x1) port_swap = (port_swap_ovr & 0x2); else port_swap = REG_RD(sc, MISC_REG_FOUR_PORT_PORT_SWAP); if (port_swap) port = port ^ 1; lane = (port << 1) + path; } else { /* Two port mode - no port swap */ /* Figure out path swap value */ path_swap_ovr = REG_RD(sc, MISC_REG_TWO_PORT_PATH_SWAP_OVWR); if (path_swap_ovr & 0x1) { path_swap = (path_swap_ovr & 0x2); } else { path_swap = REG_RD(sc, MISC_REG_TWO_PORT_PATH_SWAP); } if (path_swap) path = path ^ 1; lane = path << 1; } return lane; } static void elink_set_aer_mmd(struct elink_params *params, struct elink_phy *phy) { uint32_t ser_lane; uint16_t offset, aer_val; struct bnx2x_softc *sc = params->sc; ser_lane = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ? (phy->addr + ser_lane) : 0; if (USES_WARPCORE(sc)) { aer_val = elink_get_warpcore_lane(params); /* In Dual-lane mode, two lanes are joined together, * so in order to configure them, the AER broadcast method is * used here. * 0x200 is the broadcast address for lanes 0,1 * 0x201 is the broadcast address for lanes 2,3 */ if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) aer_val = (aer_val >> 1) | 0x200; } else if (CHIP_IS_E2(sc)) aer_val = 0x3800 + offset - 1; else aer_val = 0x3800 + offset; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, aer_val); } /******************************************************************/ /* Internal phy section */ /******************************************************************/ static void elink_set_serdes_access(struct bnx2x_softc *sc, uint8_t port) { uint32_t emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; /* Set Clause 22 */ REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_ST + port * 0x10, 1); REG_WR(sc, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000); DELAY(500); REG_WR(sc, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f); DELAY(500); /* Set Clause 45 */ REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_ST + port * 0x10, 0); } static void elink_serdes_deassert(struct bnx2x_softc *sc, uint8_t port) { uint32_t val; PMD_DRV_LOG(DEBUG, "elink_serdes_deassert"); val = ELINK_SERDES_RESET_BITS << (port * 16); /* Reset and unreset the SerDes/XGXS */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); DELAY(500); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); elink_set_serdes_access(sc, port); REG_WR(sc, NIG_REG_SERDES0_CTRL_MD_DEVAD + port * 0x10, ELINK_DEFAULT_PHY_DEV_ADDR); } static void elink_xgxs_specific_func(struct elink_phy *phy, struct elink_params *params, uint32_t action) { struct bnx2x_softc *sc = params->sc; switch (action) { case ELINK_PHY_INIT: /* Set correct devad */ REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_ST + params->port * 0x18, 0); REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port * 0x18, phy->def_md_devad); break; } } static void elink_xgxs_deassert(struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t port; uint32_t val; PMD_DRV_LOG(DEBUG, "elink_xgxs_deassert"); port = params->port; val = ELINK_XGXS_RESET_BITS << (port * 16); /* Reset and unreset the SerDes/XGXS */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); DELAY(500); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); elink_xgxs_specific_func(¶ms->phy[ELINK_INT_PHY], params, ELINK_PHY_INIT); } static void elink_calc_ieee_aneg_adv(struct elink_phy *phy, struct elink_params *params, uint16_t * ieee_fc) { *ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX; /* Resolve pause mode and advertisement Please refer to Table * 28B-3 of the 802.3ab-1999 spec */ switch (phy->req_flow_ctrl) { case ELINK_FLOW_CTRL_AUTO: switch (params->req_fc_auto_adv) { case ELINK_FLOW_CTRL_BOTH: *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; break; case ELINK_FLOW_CTRL_RX: case ELINK_FLOW_CTRL_TX: *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; break; default: break; } break; case ELINK_FLOW_CTRL_TX: *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; break; case ELINK_FLOW_CTRL_RX: case ELINK_FLOW_CTRL_BOTH: *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; break; case ELINK_FLOW_CTRL_NONE: default: *ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE; break; } PMD_DRV_LOG(DEBUG, "ieee_fc = 0x%x", *ieee_fc); } static void set_phy_vars(struct elink_params *params, struct elink_vars *vars) { uint8_t actual_phy_idx, phy_index, link_cfg_idx; uint8_t phy_config_swapped = params->multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED; for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys; phy_index++) { link_cfg_idx = ELINK_LINK_CONFIG_IDX(phy_index); actual_phy_idx = phy_index; if (phy_config_swapped) { if (phy_index == ELINK_EXT_PHY1) actual_phy_idx = ELINK_EXT_PHY2; else if (phy_index == ELINK_EXT_PHY2) actual_phy_idx = ELINK_EXT_PHY1; } params->phy[actual_phy_idx].req_flow_ctrl = params->req_flow_ctrl[link_cfg_idx]; params->phy[actual_phy_idx].req_line_speed = params->req_line_speed[link_cfg_idx]; params->phy[actual_phy_idx].speed_cap_mask = params->speed_cap_mask[link_cfg_idx]; params->phy[actual_phy_idx].req_duplex = params->req_duplex[link_cfg_idx]; if (params->req_line_speed[link_cfg_idx] == ELINK_SPEED_AUTO_NEG) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED; PMD_DRV_LOG(DEBUG, "req_flow_ctrl %x, req_line_speed %x," " speed_cap_mask %x", params->phy[actual_phy_idx].req_flow_ctrl, params->phy[actual_phy_idx].req_line_speed, params->phy[actual_phy_idx].speed_cap_mask); } } static void elink_ext_phy_set_pause(struct elink_params *params, struct elink_phy *phy, struct elink_vars *vars) { uint16_t val; struct bnx2x_softc *sc = params->sc; /* Read modify write pause advertizing */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val); val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; } if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { val |= MDIO_AN_REG_ADV_PAUSE_PAUSE; } PMD_DRV_LOG(DEBUG, "Ext phy AN advertize 0x%x", val); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val); } static void elink_pause_resolve(struct elink_vars *vars, uint32_t pause_result) { /* LD LP */ switch (pause_result) { /* ASYM P ASYM P */ case 0xb: /* 1 0 1 1 */ vars->flow_ctrl = ELINK_FLOW_CTRL_TX; break; case 0xe: /* 1 1 1 0 */ vars->flow_ctrl = ELINK_FLOW_CTRL_RX; break; case 0x5: /* 0 1 0 1 */ case 0x7: /* 0 1 1 1 */ case 0xd: /* 1 1 0 1 */ case 0xf: /* 1 1 1 1 */ vars->flow_ctrl = ELINK_FLOW_CTRL_BOTH; break; default: break; } if (pause_result & (1 << 0)) vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE; if (pause_result & (1 << 1)) vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE; } static void elink_ext_phy_update_adv_fc(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint16_t ld_pause; /* local */ uint16_t lp_pause; /* link partner */ uint16_t pause_result; struct bnx2x_softc *sc = params->sc; if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE) { elink_cl22_read(sc, phy, 0x4, &ld_pause); elink_cl22_read(sc, phy, 0x5, &lp_pause); } else if (CHIP_IS_E3(sc) && ELINK_SINGLE_MEDIA_DIRECT(params)) { uint8_t lane = elink_get_warpcore_lane(params); uint16_t gp_status, gp_mask; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4, &gp_status); gp_mask = (MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL | MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP) << lane; if ((gp_status & gp_mask) == gp_mask) { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &ld_pause); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG, &lp_pause); } else { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &ld_pause); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, &lp_pause); ld_pause = ((ld_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) << 3); lp_pause = ((lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) << 3); } } else { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &ld_pause); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG, &lp_pause); } pause_result = (ld_pause & MDIO_AN_REG_ADV_PAUSE_MASK) >> 8; pause_result |= (lp_pause & MDIO_AN_REG_ADV_PAUSE_MASK) >> 10; PMD_DRV_LOG(DEBUG, "Ext PHY pause result 0x%x", pause_result); elink_pause_resolve(vars, pause_result); } static uint8_t elink_ext_phy_resolve_fc(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint8_t ret = 0; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; if (phy->req_flow_ctrl != ELINK_FLOW_CTRL_AUTO) { /* Update the advertised flow-controled of LD/LP in AN */ if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) elink_ext_phy_update_adv_fc(phy, params, vars); /* But set the flow-control result as the requested one */ vars->flow_ctrl = phy->req_flow_ctrl; } else if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG) vars->flow_ctrl = params->req_fc_auto_adv; else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { ret = 1; elink_ext_phy_update_adv_fc(phy, params, vars); } return ret; } /******************************************************************/ /* Warpcore section */ /******************************************************************/ /* The init_internal_warpcore should mirror the xgxs, * i.e. reset the lane (if needed), set aer for the * init configuration, and set/clear SGMII flag. Internal * phy init is done purely in phy_init stage. */ #define WC_TX_DRIVER(post2, idriver, ipre) \ ((post2 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | \ (idriver << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | \ (ipre << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)) #define WC_TX_FIR(post, main, pre) \ ((post << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | \ (main << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) | \ (pre << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET)) static void elink_warpcore_enable_AN_KR2(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t i; static struct elink_reg_set reg_set[] = { /* Step 1 - Program the TX/RX alignment markers */ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537}, /* Step 2 - Configure the NP registers */ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620} }; PMD_DRV_LOG(DEBUG, "Enabling 20G-KR2"); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL49_USERB0_CTRL, (3 << 6)); for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); /* Start KR2 work-around timer which handles BNX2X8073 link-parner */ vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE; elink_update_link_attr(params, vars->link_attr_sync); } static void elink_disable_kr2(struct elink_params *params, struct elink_vars *vars, struct elink_phy *phy) { struct bnx2x_softc *sc = params->sc; uint32_t i; static struct elink_reg_set reg_set[] = { /* Step 1 - Program the TX/RX alignment markers */ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002}, {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000} }; PMD_DRV_LOG(DEBUG, "Disabling 20G-KR2"); for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; elink_update_link_attr(params, vars->link_attr_sync); vars->check_kr2_recovery_cnt = ELINK_CHECK_KR2_RECOVERY_CNT; } static void elink_warpcore_set_lpi_passthrough(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Configure WC for LPI pass through"); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_EEE_COMBO_CONTROL0, 0x7c); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC5, 0xc000); } static void elink_warpcore_restart_AN_KR(struct elink_phy *phy, struct elink_params *params) { /* Restart autoneg on the leading lane only */ struct bnx2x_softc *sc = params->sc; uint16_t lane = elink_get_warpcore_lane(params); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, lane); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200); /* Restore AER */ elink_set_aer_mmd(params, phy); } static void elink_warpcore_enable_AN_KR(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint16_t lane, i, cl72_ctrl, an_adv = 0; struct bnx2x_softc *sc = params->sc; static struct elink_reg_set reg_set[] = { {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, /* Disable Autoneg: re-enable it after adv is done. */ {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0}, {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0}, }; PMD_DRV_LOG(DEBUG, "Enable Auto Negotiation for KR"); /* Set to default registers that may be overriden by 10G force */ for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); cl72_ctrl &= 0x08ff; cl72_ctrl |= 0x3800; elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); /* Check adding advertisement for 1G KX */ if (((vars->line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (vars->line_speed == ELINK_SPEED_1000)) { uint16_t addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; an_adv |= (1 << 5); /* Enable CL37 1G Parallel Detect */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, addr, 0x1); PMD_DRV_LOG(DEBUG, "Advertize 1G"); } if (((vars->line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || (vars->line_speed == ELINK_SPEED_10000)) { /* Check adding advertisement for 10G KR */ an_adv |= (1 << 7); /* Enable 10G Parallel Detect */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 1); elink_set_aer_mmd(params, phy); PMD_DRV_LOG(DEBUG, "Advertize 10G"); } /* Set Transmit PMD settings */ lane = elink_get_warpcore_lane(params); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX0_TX_DRIVER + 0x10 * lane, WC_TX_DRIVER(0x02, 0x06, 0x09)); /* Configure the next lane if dual mode */ if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX0_TX_DRIVER + 0x10 * (lane + 1), WC_TX_DRIVER(0x02, 0x06, 0x09)); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL, 0x03f0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL, 0x03f0); /* Advertised speeds */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv); /* Advertised and set FEC (Forward Error Correction) */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2, (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY | MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ)); /* Enable CL37 BAM */ if (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. default_cfg)) & PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) { elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, 1); PMD_DRV_LOG(DEBUG, "Enable CL37 BAM on KR"); } /* Advertise pause */ elink_ext_phy_set_pause(params, phy, vars); vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY; elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0x100); /* Over 1G - AN local device user page 1 */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1f); if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) || (phy->req_line_speed == ELINK_SPEED_20000)) { CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, lane); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX1_PCI_CTRL + (0x10 * lane), (1 << 11)); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7); elink_set_aer_mmd(params, phy); elink_warpcore_enable_AN_KR2(phy, params, vars); } else { elink_disable_kr2(params, vars, phy); } /* Enable Autoneg: only on the main lane */ elink_warpcore_restart_AN_KR(phy, params); } static void elink_warpcore_set_10G_KR(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t val16, i, lane; static struct elink_reg_set reg_set[] = { /* Disable Autoneg */ {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00}, {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0}, {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, /* Leave cl72 training enable, needed for KR */ {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2} }; for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); lane = elink_get_warpcore_lane(params); /* Global registers */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); /* Disable CL36 PCS Tx */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); val16 &= ~(0x0011 << lane); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); val16 |= (0x0303 << (lane << 1)); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); /* Restore AER */ elink_set_aer_mmd(params, phy); /* Set speed via PMA/PMD register */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB); /* Enable encoded forced speed */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30); /* Turn TX scramble payload only the 64/66 scrambler */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX66_CONTROL, 0x9); /* Turn RX scramble payload only the 64/66 scrambler */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0xF9); /* Set and clear loopback to cause a reset to 64/66 decoder */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0); } static void elink_warpcore_set_10G_XFI(struct elink_phy *phy, struct elink_params *params, uint8_t is_xfi) { struct bnx2x_softc *sc = params->sc; uint16_t misc1_val, tap_val, tx_driver_val, lane, val; uint32_t cfg_tap_val, tx_drv_brdct, tx_equal; /* Hold rxSeqStart */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x8000); /* Hold tx_fifo_reset */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x1); /* Disable CL73 AN */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0); /* Disable 100FX Enable and Auto-Detect */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL1, 0xFFFA); /* Disable 100FX Idle detect */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL3, 0x0080); /* Set Block address to Remote PHY & Clear forced_speed[5] */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F); /* Turn off auto-detect & fiber mode */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0xFFEE); /* Set filter_force_link, disable_false_link and parallel_detect */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, ((val | 0x0006) & 0xFFFE)); /* Set XFI / SFI */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val); misc1_val &= ~(0x1f); if (is_xfi) { misc1_val |= 0x5; tap_val = WC_TX_FIR(0x08, 0x37, 0x00); tx_driver_val = WC_TX_DRIVER(0x00, 0x02, 0x03); } else { cfg_tap_val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params-> port].sfi_tap_values)); tx_equal = cfg_tap_val & PORT_HW_CFG_TX_EQUALIZATION_MASK; tx_drv_brdct = (cfg_tap_val & PORT_HW_CFG_TX_DRV_BROADCAST_MASK) >> PORT_HW_CFG_TX_DRV_BROADCAST_SHIFT; misc1_val |= 0x9; /* TAP values are controlled by nvram, if value there isn't 0 */ if (tx_equal) tap_val = (uint16_t) tx_equal; else tap_val = WC_TX_FIR(0x0f, 0x2b, 0x02); if (tx_drv_brdct) tx_driver_val = WC_TX_DRIVER(0x03, (uint16_t) tx_drv_brdct, 0x06); else tx_driver_val = WC_TX_DRIVER(0x03, 0x02, 0x06); } elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val); /* Set Transmit PMD settings */ lane = elink_get_warpcore_lane(params); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX_FIR_TAP, tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX0_TX_DRIVER + 0x10 * lane, tx_driver_val); /* Enable fiber mode, enable and invert sig_det */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0xd); /* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, 0x8080); elink_warpcore_set_lpi_passthrough(phy, params); /* 10G XFI Full Duplex */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100); /* Release tx_fifo_reset */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0xFFFE); /* Release rxSeqStart */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF); } static void elink_warpcore_set_20G_force_KR2(struct elink_phy *phy, struct elink_params *params) { uint16_t val; struct bnx2x_softc *sc = params->sc; /* Set global registers, so set AER lane to 0 */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); /* Disable sequencer */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1 << 13)); elink_set_aer_mmd(params, phy); elink_cl45_read_and_write(sc, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, ~(1 << 1)); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0); /* Turn off CL73 */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, &val); val &= ~(1 << 5); val |= (1 << 6); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, val); /* Set 20G KR2 force speed */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, (1 << 7)); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val); val &= ~(3 << 14); val |= (1 << 15); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A); /* Enable sequencer (over lane 0) */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1 << 13)); elink_set_aer_mmd(params, phy); } static void elink_warpcore_set_20G_DXGXS(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t lane) { /* Rx0 anaRxControl1G */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90); /* Rx2 anaRxControl1G */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW0, 0xE070); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW1, 0xC0D0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW2, 0xA0B0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW3, 0x8090); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0); /* Serdes Digital Misc1 */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008); /* Serdes Digital4 Misc3 */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, 0x8088); /* Set Transmit PMD settings */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX_FIR_TAP, (WC_TX_FIR(0x12, 0x2d, 0x00) | MDIO_WC_REG_TX_FIR_TAP_ENABLE)); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX0_TX_DRIVER + 0x10 * lane, WC_TX_DRIVER(0x02, 0x02, 0x02)); } static void elink_warpcore_set_sgmii_speed(struct elink_phy *phy, struct elink_params *params, uint8_t fiber_mode, uint8_t always_autoneg) { struct bnx2x_softc *sc = params->sc; uint16_t val16, digctrl_kx1, digctrl_kx2; /* Clear XFI clock comp in non-10G single lane mode. */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, ~(3 << 13)); elink_warpcore_set_lpi_passthrough(phy, params); if (always_autoneg || phy->req_line_speed == ELINK_SPEED_AUTO_NEG) { /* SGMII Autoneg */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x1000); PMD_DRV_LOG(DEBUG, "set SGMII AUTONEG"); } else { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); val16 &= 0xcebf; switch (phy->req_line_speed) { case ELINK_SPEED_10: break; case ELINK_SPEED_100: val16 |= 0x2000; break; case ELINK_SPEED_1000: val16 |= 0x0040; break; default: PMD_DRV_LOG(DEBUG, "Speed not supported: 0x%x", phy->req_line_speed); return; } if (phy->req_duplex == DUPLEX_FULL) val16 |= 0x0100; elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16); PMD_DRV_LOG(DEBUG, "set SGMII force speed %d", phy->req_line_speed); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); PMD_DRV_LOG(DEBUG, " (readback) %x", val16); } /* SGMII Slave mode and disable signal detect */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1); if (fiber_mode) digctrl_kx1 = 1; else digctrl_kx1 &= 0xff4a; elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, digctrl_kx1); /* Turn off parallel detect */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, (digctrl_kx2 & ~(1 << 2))); /* Re-enable parallel detect */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, (digctrl_kx2 | (1 << 2))); /* Enable autodet */ elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, (digctrl_kx1 | 0x10)); } static void elink_warpcore_reset_lane(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t reset) { uint16_t val; /* Take lane out of reset after configuration is finished */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC6, &val); if (reset) val |= 0xC000; else val &= 0x3FFF; elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC6, val); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC6, &val); } /* Clear SFI/XFI link settings registers */ static void elink_warpcore_clear_regs(struct elink_phy *phy, struct elink_params *params, uint16_t lane) { struct bnx2x_softc *sc = params->sc; uint16_t i; static struct elink_reg_set wc_regs[] = { {MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0}, {MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL1, 0x014a}, {MDIO_WC_DEVAD, MDIO_WC_REG_FX100_CTRL3, 0x0800}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL4_MISC3, 0x8008}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000}, {MDIO_WC_DEVAD, MDIO_WC_REG_TX_FIR_TAP, 0x0000}, {MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040}, {MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140} }; /* Set XFI clock comp as default. */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, (3 << 13)); for (i = 0; i < ARRAY_SIZE(wc_regs); i++) elink_cl45_write(sc, phy, wc_regs[i].devad, wc_regs[i].reg, wc_regs[i].val); lane = elink_get_warpcore_lane(params); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_TX0_TX_DRIVER + 0x10 * lane, 0x0990); } static elink_status_t elink_get_mod_abs_int_cfg(struct bnx2x_softc *sc, uint32_t shmem_base, uint8_t port, uint8_t * gpio_num, uint8_t * gpio_port) { uint32_t cfg_pin; *gpio_num = 0; *gpio_port = 0; if (CHIP_IS_E3(sc)) { cfg_pin = (REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. e3_sfp_ctrl)) & PORT_HW_CFG_E3_MOD_ABS_MASK) >> PORT_HW_CFG_E3_MOD_ABS_SHIFT; /* Should not happen. This function called upon interrupt * triggered by GPIO ( since EPIO can only generate interrupts * to MCP). * So if this function was called and none of the GPIOs was set, * it means the shit hit the fan. */ if ((cfg_pin < PIN_CFG_GPIO0_P0) || (cfg_pin > PIN_CFG_GPIO3_P1)) { PMD_DRV_LOG(DEBUG, "No cfg pin %x for module detect indication", cfg_pin); return ELINK_STATUS_ERROR; } *gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3; *gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2; } else { *gpio_num = MISC_REGISTERS_GPIO_3; *gpio_port = port; } return ELINK_STATUS_OK; } static int elink_is_sfp_module_plugged(struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t gpio_num, gpio_port; uint32_t gpio_val; if (elink_get_mod_abs_int_cfg(sc, params->shmem_base, params->port, &gpio_num, &gpio_port) != ELINK_STATUS_OK) return 0; gpio_val = elink_cb_gpio_read(sc, gpio_num, gpio_port); /* Call the handling function in case module is detected */ if (gpio_val == 0) return 1; else return 0; } static int elink_warpcore_get_sigdet(struct elink_phy *phy, struct elink_params *params) { uint16_t gp2_status_reg0, lane; struct bnx2x_softc *sc = params->sc; lane = elink_get_warpcore_lane(params); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0, &gp2_status_reg0); return (gp2_status_reg0 >> (8 + lane)) & 0x1; } static void elink_warpcore_config_runtime(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint32_t serdes_net_if; uint16_t gp_status1 = 0, lnkup = 0, lnkup_kr = 0; vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1; if (!vars->turn_to_run_wc_rt) return; if (vars->rx_tx_asic_rst) { uint16_t lane = elink_get_warpcore_lane(params); serdes_net_if = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config [params->port]. default_cfg)) & PORT_HW_CFG_NET_SERDES_IF_MASK); switch (serdes_net_if) { case PORT_HW_CFG_NET_SERDES_IF_KR: /* Do we get link yet? */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, 0x81d1, &gp_status1); lnkup = (gp_status1 >> (8 + lane)) & 0x1; /* 1G */ /*10G KR */ lnkup_kr = (gp_status1 >> (12 + lane)) & 0x1; if (lnkup_kr || lnkup) { vars->rx_tx_asic_rst = 0; } else { /* Reset the lane to see if link comes up. */ elink_warpcore_reset_lane(sc, phy, 1); elink_warpcore_reset_lane(sc, phy, 0); /* Restart Autoneg */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200); vars->rx_tx_asic_rst--; PMD_DRV_LOG(DEBUG, "0x%x retry left", vars->rx_tx_asic_rst); } break; default: break; } } /*params->rx_tx_asic_rst */ } static void elink_warpcore_config_sfi(struct elink_phy *phy, struct elink_params *params) { uint16_t lane = elink_get_warpcore_lane(params); elink_warpcore_clear_regs(phy, params, lane); if ((params->req_line_speed[ELINK_LINK_CONFIG_IDX(ELINK_INT_PHY)] == ELINK_SPEED_10000) && (phy->media_type != ELINK_ETH_PHY_SFP_1G_FIBER)) { PMD_DRV_LOG(DEBUG, "Setting 10G SFI"); elink_warpcore_set_10G_XFI(phy, params, 0); } else { PMD_DRV_LOG(DEBUG, "Setting 1G Fiber"); elink_warpcore_set_sgmii_speed(phy, params, 1, 0); } } static void elink_sfp_e3_set_transmitter(struct elink_params *params, struct elink_phy *phy, uint8_t tx_en) { struct bnx2x_softc *sc = params->sc; uint32_t cfg_pin; uint8_t port = params->port; cfg_pin = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].e3_sfp_ctrl)) & PORT_HW_CFG_E3_TX_LASER_MASK; /* Set the !tx_en since this pin is DISABLE_TX_LASER */ PMD_DRV_LOG(DEBUG, "Setting WC TX to %d", tx_en); /* For 20G, the expected pin to be used is 3 pins after the current */ elink_set_cfg_pin(sc, cfg_pin, tx_en ^ 1); if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G) elink_set_cfg_pin(sc, cfg_pin + 3, tx_en ^ 1); } static void elink_warpcore_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint32_t serdes_net_if; uint8_t fiber_mode; uint16_t lane = elink_get_warpcore_lane(params); serdes_net_if = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. default_cfg)) & PORT_HW_CFG_NET_SERDES_IF_MASK); PMD_DRV_LOG(DEBUG, "Begin Warpcore init, link_speed %d, " "serdes_net_if = 0x%x", vars->line_speed, serdes_net_if); elink_set_aer_mmd(params, phy); elink_warpcore_reset_lane(sc, phy, 1); vars->phy_flags |= PHY_XGXS_FLAG; if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) || (phy->req_line_speed && ((phy->req_line_speed == ELINK_SPEED_100) || (phy->req_line_speed == ELINK_SPEED_10)))) { vars->phy_flags |= PHY_SGMII_FLAG; PMD_DRV_LOG(DEBUG, "Setting SGMII mode"); elink_warpcore_clear_regs(phy, params, lane); elink_warpcore_set_sgmii_speed(phy, params, 0, 1); } else { switch (serdes_net_if) { case PORT_HW_CFG_NET_SERDES_IF_KR: /* Enable KR Auto Neg */ if (params->loopback_mode != ELINK_LOOPBACK_EXT) elink_warpcore_enable_AN_KR(phy, params, vars); else { PMD_DRV_LOG(DEBUG, "Setting KR 10G-Force"); elink_warpcore_set_10G_KR(phy, params); } break; case PORT_HW_CFG_NET_SERDES_IF_XFI: elink_warpcore_clear_regs(phy, params, lane); if (vars->line_speed == ELINK_SPEED_10000) { PMD_DRV_LOG(DEBUG, "Setting 10G XFI"); elink_warpcore_set_10G_XFI(phy, params, 1); } else { if (ELINK_SINGLE_MEDIA_DIRECT(params)) { PMD_DRV_LOG(DEBUG, "1G Fiber"); fiber_mode = 1; } else { PMD_DRV_LOG(DEBUG, "10/100/1G SGMII"); fiber_mode = 0; } elink_warpcore_set_sgmii_speed(phy, params, fiber_mode, 0); } break; case PORT_HW_CFG_NET_SERDES_IF_SFI: /* Issue Module detection if module is plugged, or * enabled transmitter to avoid current leakage in case * no module is connected */ if ((params->loopback_mode == ELINK_LOOPBACK_NONE) || (params->loopback_mode == ELINK_LOOPBACK_EXT)) { if (elink_is_sfp_module_plugged(params)) elink_sfp_module_detection(phy, params); else elink_sfp_e3_set_transmitter(params, phy, 1); } elink_warpcore_config_sfi(phy, params); break; case PORT_HW_CFG_NET_SERDES_IF_DXGXS: if (vars->line_speed != ELINK_SPEED_20000) { PMD_DRV_LOG(DEBUG, "Speed not supported yet"); return; } PMD_DRV_LOG(DEBUG, "Setting 20G DXGXS"); elink_warpcore_set_20G_DXGXS(sc, phy, lane); /* Issue Module detection */ elink_sfp_module_detection(phy, params); break; case PORT_HW_CFG_NET_SERDES_IF_KR2: if (!params->loopback_mode) { elink_warpcore_enable_AN_KR(phy, params, vars); } else { PMD_DRV_LOG(DEBUG, "Setting KR 20G-Force"); elink_warpcore_set_20G_force_KR2(phy, params); } break; default: PMD_DRV_LOG(DEBUG, "Unsupported Serdes Net Interface 0x%x", serdes_net_if); return; } } /* Take lane out of reset after configuration is finished */ elink_warpcore_reset_lane(sc, phy, 0); PMD_DRV_LOG(DEBUG, "Exit config init"); } static void elink_warpcore_link_reset(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t val16, lane; elink_sfp_e3_set_transmitter(params, phy, 0); elink_set_mdio_emac_per_phy(sc, params); elink_set_aer_mmd(params, phy); /* Global register */ elink_warpcore_reset_lane(sc, phy, 1); /* Clear loopback settings (if any) */ /* 10G & 20G */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF); elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe); /* Update those 1-copy registers */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); /* Enable 1G MDIO (1-copy) */ elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~0x10); elink_cl45_read_and_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00); lane = elink_get_warpcore_lane(params); /* Disable CL36 PCS Tx */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); val16 |= (0x11 << lane); if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) val16 |= (0x22 << lane); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); val16 &= ~(0x0303 << (lane << 1)); val16 |= (0x0101 << (lane << 1)); if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) { val16 &= ~(0x0c0c << (lane << 1)); val16 |= (0x0404 << (lane << 1)); } elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); /* Restore AER */ elink_set_aer_mmd(params, phy); } static void elink_set_warpcore_loopback(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t val16; uint32_t lane; PMD_DRV_LOG(DEBUG, "Setting Warpcore loopback type %x, speed %d", params->loopback_mode, phy->req_line_speed); if (phy->req_line_speed < ELINK_SPEED_10000 || phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) { /* 10/100/1000/20G-KR2 */ /* Update those 1-copy registers */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, 0); /* Enable 1G MDIO (1-copy) */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, 0x10); /* Set 1G loopback based on lane (1-copy) */ lane = elink_get_warpcore_lane(params); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16); val16 |= (1 << lane); if (phy->flags & ELINK_FLAGS_WC_DUAL_MODE) val16 |= (2 << lane); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL2, val16); /* Switch back to 4-copy registers */ elink_set_aer_mmd(params, phy); } else { /* 10G / 20G-DXGXS */ elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x4000); elink_cl45_read_or_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1); } } static void elink_sync_link(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t link_10g_plus; if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP); if (vars->link_up) { PMD_DRV_LOG(DEBUG, "phy link up"); vars->phy_link_up = 1; vars->duplex = DUPLEX_FULL; switch (vars->link_status & LINK_STATUS_SPEED_AND_DUPLEX_MASK) { case ELINK_LINK_10THD: vars->duplex = DUPLEX_HALF; /* Fall thru */ case ELINK_LINK_10TFD: vars->line_speed = ELINK_SPEED_10; break; case ELINK_LINK_100TXHD: vars->duplex = DUPLEX_HALF; /* Fall thru */ case ELINK_LINK_100T4: case ELINK_LINK_100TXFD: vars->line_speed = ELINK_SPEED_100; break; case ELINK_LINK_1000THD: vars->duplex = DUPLEX_HALF; /* Fall thru */ case ELINK_LINK_1000TFD: vars->line_speed = ELINK_SPEED_1000; break; case ELINK_LINK_2500THD: vars->duplex = DUPLEX_HALF; /* Fall thru */ case ELINK_LINK_2500TFD: vars->line_speed = ELINK_SPEED_2500; break; case ELINK_LINK_10GTFD: vars->line_speed = ELINK_SPEED_10000; break; case ELINK_LINK_20GTFD: vars->line_speed = ELINK_SPEED_20000; break; default: break; } vars->flow_ctrl = 0; if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED) vars->flow_ctrl |= ELINK_FLOW_CTRL_TX; if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED) vars->flow_ctrl |= ELINK_FLOW_CTRL_RX; if (!vars->flow_ctrl) vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; if (vars->line_speed && ((vars->line_speed == ELINK_SPEED_10) || (vars->line_speed == ELINK_SPEED_100))) { vars->phy_flags |= PHY_SGMII_FLAG; } else { vars->phy_flags &= ~PHY_SGMII_FLAG; } if (vars->line_speed && USES_WARPCORE(sc) && (vars->line_speed == ELINK_SPEED_1000)) vars->phy_flags |= PHY_SGMII_FLAG; /* Anything 10 and over uses the bmac */ link_10g_plus = (vars->line_speed >= ELINK_SPEED_10000); if (link_10g_plus) { if (USES_WARPCORE(sc)) vars->mac_type = ELINK_MAC_TYPE_XMAC; else vars->mac_type = ELINK_MAC_TYPE_BMAC; } else { if (USES_WARPCORE(sc)) vars->mac_type = ELINK_MAC_TYPE_UMAC; else vars->mac_type = ELINK_MAC_TYPE_EMAC; } } else { /* Link down */ PMD_DRV_LOG(DEBUG, "phy link down"); vars->phy_link_up = 0; vars->line_speed = 0; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; /* Indicate no mac active */ vars->mac_type = ELINK_MAC_TYPE_NONE; if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG) vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; if (vars->link_status & LINK_STATUS_SFP_TX_FAULT) vars->phy_flags |= PHY_SFP_TX_FAULT_FLAG; } } void elink_link_status_update(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t sync_offset, media_types; /* Update PHY configuration */ set_phy_vars(params, vars); vars->link_status = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, port_mb[port].link_status)); /* Force link UP in non LOOPBACK_EXT loopback mode(s) */ if (params->loopback_mode != ELINK_LOOPBACK_NONE && params->loopback_mode != ELINK_LOOPBACK_EXT) vars->link_status |= LINK_STATUS_LINK_UP; if (elink_eee_has_cap(params)) vars->eee_status = REG_RD(sc, params->shmem2_base + offsetof(struct shmem2_region, eee_status[params->port])); vars->phy_flags = PHY_XGXS_FLAG; elink_sync_link(params, vars); /* Sync media type */ sync_offset = params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].media_type); media_types = REG_RD(sc, sync_offset); params->phy[ELINK_INT_PHY].media_type = (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >> PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT; params->phy[ELINK_EXT_PHY1].media_type = (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >> PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT; params->phy[ELINK_EXT_PHY2].media_type = (media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >> PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT; PMD_DRV_LOG(DEBUG, "media_types = 0x%x", media_types); /* Sync AEU offset */ sync_offset = params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].aeu_int_mask); vars->aeu_int_mask = REG_RD(sc, sync_offset); /* Sync PFC status */ if (vars->link_status & LINK_STATUS_PFC_ENABLED) params->feature_config_flags |= ELINK_FEATURE_CONFIG_PFC_ENABLED; else params->feature_config_flags &= ~ELINK_FEATURE_CONFIG_PFC_ENABLED; if (SHMEM2_HAS(sc, link_attr_sync)) vars->link_attr_sync = SHMEM2_RD(sc, link_attr_sync[params->port]); PMD_DRV_LOG(DEBUG, "link_status 0x%x phy_link_up %x int_mask 0x%x", vars->link_status, vars->phy_link_up, vars->aeu_int_mask); PMD_DRV_LOG(DEBUG, "line_speed %x duplex %x flow_ctrl 0x%x", vars->line_speed, vars->duplex, vars->flow_ctrl); } static void elink_set_master_ln(struct elink_params *params, struct elink_phy *phy) { struct bnx2x_softc *sc = params->sc; uint16_t new_master_ln, ser_lane; ser_lane = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); /* Set the master_ln for AN */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TEST_MODE_LANE, &new_master_ln); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TEST_MODE_LANE, (new_master_ln | ser_lane)); } static elink_status_t elink_reset_unicore(struct elink_params *params, struct elink_phy *phy, uint8_t set_serdes) { struct bnx2x_softc *sc = params->sc; uint16_t mii_control; uint16_t i; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control); /* Reset the unicore */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, (mii_control | MDIO_COMBO_IEEO_MII_CONTROL_RESET)); if (set_serdes) elink_set_serdes_access(sc, params->port); /* Wait for the reset to self clear */ for (i = 0; i < ELINK_MDIO_ACCESS_TIMEOUT; i++) { DELAY(5); /* The reset erased the previous bank value */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control); if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) { DELAY(5); return ELINK_STATUS_OK; } } elink_cb_event_log(sc, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized," // " Port %d", PMD_DRV_LOG(DEBUG, "BUG! XGXS is still in reset!"); return ELINK_STATUS_ERROR; } static void elink_set_swap_lanes(struct elink_params *params, struct elink_phy *phy) { struct bnx2x_softc *sc = params->sc; /* Each two bits represents a lane number: * No swap is 0123 => 0x1b no need to enable the swap */ uint16_t rx_lane_swap, tx_lane_swap; rx_lane_swap = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT); tx_lane_swap = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT); if (rx_lane_swap != 0x1b) { CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_RX_LN_SWAP, (rx_lane_swap | MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE | MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE)); } else { CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0); } if (tx_lane_swap != 0x1b) { CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TX_LN_SWAP, (tx_lane_swap | MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE)); } else { CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0); } } static void elink_set_parallel_detection(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t control2; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, &control2); if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; else control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN; PMD_DRV_LOG(DEBUG, "phy->speed_cap_mask = 0x%x, control2 = 0x%x", phy->speed_cap_mask, control2); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL2, control2); if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { PMD_DRV_LOG(DEBUG, "XGXS"); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_10G_PARALLEL_DETECT, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT); CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_10G_PARALLEL_DETECT, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, &control2); control2 |= MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_10G_PARALLEL_DETECT, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL, control2); /* Disable parallel detection of HiG */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_XGXS_BLOCK2, MDIO_XGXS_BLOCK2_UNICORE_MODE_10G, MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS | MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS); } } static void elink_set_autoneg(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars, uint8_t enable_cl73) { struct bnx2x_softc *sc = params->sc; uint16_t reg_val; /* CL37 Autoneg */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, ®_val); /* CL37 Autoneg Enabled */ if (vars->line_speed == ELINK_SPEED_AUTO_NEG) reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN; else /* CL37 Autoneg Disabled */ reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, reg_val); /* Enable/Disable Autodetection */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val); reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT); reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE; if (vars->line_speed == ELINK_SPEED_AUTO_NEG) reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; else reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val); /* Enable TetonII and BAM autoneg */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_BAM_NEXT_PAGE, MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, ®_val); if (vars->line_speed == ELINK_SPEED_AUTO_NEG) { /* Enable BAM aneg Mode and TetonII aneg Mode */ reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN); } else { /* TetonII and BAM Autoneg Disabled */ reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN); } CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_BAM_NEXT_PAGE, MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, reg_val); if (enable_cl73) { /* Enable Cl73 FSM status bits */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_UCTRL, 0xe); /* Enable BAM Station Manager */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_BAM_CTRL1, MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); /* Advertise CL73 link speeds */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, ®_val); if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4; if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV2, reg_val); /* CL73 Autoneg Enabled */ reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; } else /* CL73 Autoneg Disabled */ reg_val = 0; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val); } /* Program SerDes, forced speed */ static void elink_program_serdes(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t reg_val; /* Program duplex, disable autoneg and sgmii */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, ®_val); reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK); if (phy->req_duplex == DUPLEX_FULL) reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, reg_val); /* Program speed * - needed only if the speed is greater than 1G (2.5G or 10G) */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_MISC1, ®_val); /* Clearing the speed value before setting the right speed */ PMD_DRV_LOG(DEBUG, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x", reg_val); reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL); if (!((vars->line_speed == ELINK_SPEED_1000) || (vars->line_speed == ELINK_SPEED_100) || (vars->line_speed == ELINK_SPEED_10))) { reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M | MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL); if (vars->line_speed == ELINK_SPEED_10000) reg_val |= MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4; } CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_MISC1, reg_val); } static void elink_set_brcm_cl37_advertisement(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t val = 0; /* Set extended capabilities */ if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) val |= MDIO_OVER_1G_UP1_2_5G; if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) val |= MDIO_OVER_1G_UP1_10G; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_UP1, val); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_UP3, 0x400); } static void elink_set_ieee_aneg_advertisement(struct elink_phy *phy, struct elink_params *params, uint16_t ieee_fc) { struct bnx2x_softc *sc = params->sc; uint16_t val; /* For AN, we are always publishing full duplex */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc); CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1, &val); val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH; val |= ((ieee_fc << 3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1, val); } static void elink_restart_autoneg(struct elink_phy *phy, struct elink_params *params, uint8_t enable_cl73) { struct bnx2x_softc *sc = params->sc; uint16_t mii_control; PMD_DRV_LOG(DEBUG, "elink_restart_autoneg"); /* Enable and restart BAM/CL37 aneg */ if (enable_cl73) { CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, &mii_control); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, (mii_control | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN)); } else { CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control); PMD_DRV_LOG(DEBUG, "elink_restart_autoneg mii_control before = 0x%x", mii_control); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, (mii_control | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN)); } } static void elink_initialize_sgmii_process(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t control1; /* In SGMII mode, the unicore is always slave */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &control1); control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT; /* Set sgmii mode (and not fiber) */ control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, control1); /* If forced speed */ if (!(vars->line_speed == ELINK_SPEED_AUTO_NEG)) { /* Set speed, disable autoneg */ uint16_t mii_control; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control); mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK | MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX); switch (vars->line_speed) { case ELINK_SPEED_100: mii_control |= MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100; break; case ELINK_SPEED_1000: mii_control |= MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000; break; case ELINK_SPEED_10: /* There is nothing to set for 10M */ break; default: /* Invalid speed for SGMII */ PMD_DRV_LOG(DEBUG, "Invalid line_speed 0x%x", vars->line_speed); break; } /* Setting the full duplex */ if (phy->req_duplex == DUPLEX_FULL) mii_control |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX; CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_MII_CONTROL, mii_control); } else { /* AN mode */ /* Enable and restart AN */ elink_restart_autoneg(phy, params, 0); } } /* Link management */ static elink_status_t elink_direct_parallel_detect_used(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t pd_10g, status2_1000x; if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG) return ELINK_STATUS_OK; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_STATUS2, &status2_1000x); CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_SERDES_DIGITAL, MDIO_SERDES_DIGITAL_A_1000X_STATUS2, &status2_1000x); if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) { PMD_DRV_LOG(DEBUG, "1G parallel detect link on port %d", params->port); return 1; } CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_10G_PARALLEL_DETECT, MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS, &pd_10g); if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) { PMD_DRV_LOG(DEBUG, "10G parallel detect link on port %d", params->port); return 1; } return ELINK_STATUS_OK; } static void elink_update_adv_fc(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars, uint32_t gp_status) { uint16_t ld_pause; /* local driver */ uint16_t lp_pause; /* link partner */ uint16_t pause_result; struct bnx2x_softc *sc = params->sc; if ((gp_status & (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) == (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) { CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_ADV1, &ld_pause); CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_LP_ADV1, &lp_pause); pause_result = (ld_pause & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK) >> 8; pause_result |= (lp_pause & MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK) >> 10; PMD_DRV_LOG(DEBUG, "pause_result CL73 0x%x", pause_result); } else { CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_ADV, &ld_pause); CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_COMBO_IEEE0, MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1, &lp_pause); pause_result = (ld_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) >> 5; pause_result |= (lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) >> 7; PMD_DRV_LOG(DEBUG, "pause_result CL37 0x%x", pause_result); } elink_pause_resolve(vars, pause_result); } static void elink_flow_ctrl_resolve(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars, uint32_t gp_status) { vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; /* Resolve from gp_status in case of AN complete and not sgmii */ if (phy->req_flow_ctrl != ELINK_FLOW_CTRL_AUTO) { /* Update the advertised flow-controled of LD/LP in AN */ if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) elink_update_adv_fc(phy, params, vars, gp_status); /* But set the flow-control result as the requested one */ vars->flow_ctrl = phy->req_flow_ctrl; } else if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG) vars->flow_ctrl = params->req_fc_auto_adv; else if ((gp_status & ELINK_MDIO_AN_CL73_OR_37_COMPLETE) && (!(vars->phy_flags & PHY_SGMII_FLAG))) { if (elink_direct_parallel_detect_used(phy, params)) { vars->flow_ctrl = params->req_fc_auto_adv; return; } elink_update_adv_fc(phy, params, vars, gp_status); } PMD_DRV_LOG(DEBUG, "flow_ctrl 0x%x", vars->flow_ctrl); } static void elink_check_fallback_to_cl37(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t rx_status, ustat_val, cl37_fsm_received; PMD_DRV_LOG(DEBUG, "elink_check_fallback_to_cl37"); /* Step 1: Make sure signal is detected */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_RX0, MDIO_RX0_RX_STATUS, &rx_status); if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) != (MDIO_RX0_RX_STATUS_SIGDET)) { PMD_DRV_LOG(DEBUG, "Signal is not detected. Restoring CL73." "rx_status(0x80b0) = 0x%x", rx_status); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN); return; } /* Step 2: Check CL73 state machine */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_USERB0, MDIO_CL73_USERB0_CL73_USTAT1, &ustat_val); if ((ustat_val & (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK | MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) != (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK | MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) { PMD_DRV_LOG(DEBUG, "CL73 state-machine is not stable. " "ustat_val(0x8371) = 0x%x", ustat_val); return; } /* Step 3: Check CL37 Message Pages received to indicate LP * supports only CL37 */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_REMOTE_PHY, MDIO_REMOTE_PHY_MISC_RX_STATUS, &cl37_fsm_received); if ((cl37_fsm_received & (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG | MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) != (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG | MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) { PMD_DRV_LOG(DEBUG, "No CL37 FSM were received. " "misc_rx_status(0x8330) = 0x%x", cl37_fsm_received); return; } /* The combined cl37/cl73 fsm state information indicating that * we are connected to a device which does not support cl73, but * does support cl37 BAM. In this case we disable cl73 and * restart cl37 auto-neg */ /* Disable CL73 */ CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB0, MDIO_CL73_IEEEB0_CL73_AN_CONTROL, 0); /* Restart CL37 autoneg */ elink_restart_autoneg(phy, params, 0); PMD_DRV_LOG(DEBUG, "Disabling CL73, and restarting CL37 autoneg"); } static void elink_xgxs_an_resolve(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars, uint32_t gp_status) { if (gp_status & ELINK_MDIO_AN_CL73_OR_37_COMPLETE) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; if (elink_direct_parallel_detect_used(phy, params)) vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; } static elink_status_t elink_get_link_speed_duplex(struct elink_phy *phy, struct elink_params *params __rte_unused, struct elink_vars *vars, uint16_t is_link_up, uint16_t speed_mask, uint16_t is_duplex) { if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED; if (is_link_up) { PMD_DRV_LOG(DEBUG, "phy link up"); vars->phy_link_up = 1; vars->link_status |= LINK_STATUS_LINK_UP; switch (speed_mask) { case ELINK_GP_STATUS_10M: vars->line_speed = ELINK_SPEED_10; if (is_duplex == DUPLEX_FULL) vars->link_status |= ELINK_LINK_10TFD; else vars->link_status |= ELINK_LINK_10THD; break; case ELINK_GP_STATUS_100M: vars->line_speed = ELINK_SPEED_100; if (is_duplex == DUPLEX_FULL) vars->link_status |= ELINK_LINK_100TXFD; else vars->link_status |= ELINK_LINK_100TXHD; break; case ELINK_GP_STATUS_1G: case ELINK_GP_STATUS_1G_KX: vars->line_speed = ELINK_SPEED_1000; if (is_duplex == DUPLEX_FULL) vars->link_status |= ELINK_LINK_1000TFD; else vars->link_status |= ELINK_LINK_1000THD; break; case ELINK_GP_STATUS_2_5G: vars->line_speed = ELINK_SPEED_2500; if (is_duplex == DUPLEX_FULL) vars->link_status |= ELINK_LINK_2500TFD; else vars->link_status |= ELINK_LINK_2500THD; break; case ELINK_GP_STATUS_5G: case ELINK_GP_STATUS_6G: PMD_DRV_LOG(DEBUG, "link speed unsupported gp_status 0x%x", speed_mask); return ELINK_STATUS_ERROR; case ELINK_GP_STATUS_10G_KX4: case ELINK_GP_STATUS_10G_HIG: case ELINK_GP_STATUS_10G_CX4: case ELINK_GP_STATUS_10G_KR: case ELINK_GP_STATUS_10G_SFI: case ELINK_GP_STATUS_10G_XFI: vars->line_speed = ELINK_SPEED_10000; vars->link_status |= ELINK_LINK_10GTFD; break; case ELINK_GP_STATUS_20G_DXGXS: case ELINK_GP_STATUS_20G_KR2: vars->line_speed = ELINK_SPEED_20000; vars->link_status |= ELINK_LINK_20GTFD; break; default: PMD_DRV_LOG(DEBUG, "link speed unsupported gp_status 0x%x", speed_mask); return ELINK_STATUS_ERROR; } } else { /* link_down */ PMD_DRV_LOG(DEBUG, "phy link down"); vars->phy_link_up = 0; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_NONE; } PMD_DRV_LOG(DEBUG, " phy_link_up %x line_speed %d", vars->phy_link_up, vars->line_speed); return ELINK_STATUS_OK; } static elink_status_t elink_link_settings_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask; elink_status_t rc = ELINK_STATUS_OK; /* Read gp_status */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_GP_STATUS, MDIO_GP_STATUS_TOP_AN_STATUS1, &gp_status); if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS) duplex = DUPLEX_FULL; if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) link_up = 1; speed_mask = gp_status & ELINK_GP_STATUS_SPEED_MASK; PMD_DRV_LOG(DEBUG, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x", gp_status, link_up, speed_mask); rc = elink_get_link_speed_duplex(phy, params, vars, link_up, speed_mask, duplex); if (rc == ELINK_STATUS_ERROR) return rc; if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { if (ELINK_SINGLE_MEDIA_DIRECT(params)) { vars->duplex = duplex; elink_flow_ctrl_resolve(phy, params, vars, gp_status); if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) elink_xgxs_an_resolve(phy, params, vars, gp_status); } } else { /* Link_down */ if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && ELINK_SINGLE_MEDIA_DIRECT(params)) { /* Check signal is detected */ elink_check_fallback_to_cl37(phy, params); } } /* Read LP advertised speeds */ if (ELINK_SINGLE_MEDIA_DIRECT(params) && (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)) { uint16_t val; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_CL73_IEEEB1, MDIO_CL73_IEEEB1_AN_LP_ADV2, &val); if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE; if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_LP_UP1, &val); if (val & MDIO_OVER_1G_UP1_2_5G) vars->link_status |= LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE; if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; } PMD_DRV_LOG(DEBUG, "duplex %x flow_ctrl 0x%x link_status 0x%x", vars->duplex, vars->flow_ctrl, vars->link_status); return rc; } static elink_status_t elink_warpcore_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t lane; uint16_t gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL; elink_status_t rc = ELINK_STATUS_OK; lane = elink_get_warpcore_lane(params); /* Read gp_status */ if ((params->loopback_mode) && (phy->flags & ELINK_FLAGS_WC_DUAL_MODE)) { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up); link_up &= 0x1; } else if ((phy->req_line_speed > ELINK_SPEED_10000) && (phy->supported & ELINK_SUPPORTED_20000baseMLD2_Full)) { uint16_t temp_link_up; elink_cl45_read(sc, phy, MDIO_WC_DEVAD, 1, &temp_link_up); elink_cl45_read(sc, phy, MDIO_WC_DEVAD, 1, &link_up); PMD_DRV_LOG(DEBUG, "PCS RX link status = 0x%x-->0x%x", temp_link_up, link_up); link_up &= (1 << 2); if (link_up) elink_ext_phy_resolve_fc(phy, params, vars); } else { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1); PMD_DRV_LOG(DEBUG, "0x81d1 = 0x%x", gp_status1); /* Check for either KR, 1G, or AN up. */ link_up = ((gp_status1 >> 8) | (gp_status1 >> 12) | (gp_status1)) & (1 << lane); if (phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) { uint16_t an_link; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &an_link); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &an_link); link_up |= (an_link & (1 << 2)); } if (link_up && ELINK_SINGLE_MEDIA_DIRECT(params)) { uint16_t pd, gp_status4; if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) { /* Check Autoneg complete */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4, &gp_status4); if (gp_status4 & ((1 << 12) << lane)) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; /* Check parallel detect used */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_PAR_DET_10G_STATUS, &pd); if (pd & (1 << 15)) vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; } elink_ext_phy_resolve_fc(phy, params, vars); vars->duplex = duplex; } } if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) && ELINK_SINGLE_MEDIA_DIRECT(params)) { uint16_t val; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG2, &val); if (val & MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE; if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_LP_UP1, &val); if (val & MDIO_OVER_1G_UP1_2_5G) vars->link_status |= LINK_STATUS_LINK_PARTNER_2500XFD_CAPABLE; if (val & (MDIO_OVER_1G_UP1_10G | MDIO_OVER_1G_UP1_10GH)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; } if (lane < 2) { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed); } else { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed); } PMD_DRV_LOG(DEBUG, "lane %d gp_speed 0x%x", lane, gp_speed); if ((lane & 1) == 0) gp_speed <<= 8; gp_speed &= 0x3f00; link_up = ! !link_up; /* Reset the TX FIFO to fix SGMII issue */ rc = elink_get_link_speed_duplex(phy, params, vars, link_up, gp_speed, duplex); /* In case of KR link down, start up the recovering procedure */ if ((!link_up) && (phy->media_type == ELINK_ETH_PHY_KR) && (!(phy->flags & ELINK_FLAGS_WC_DUAL_MODE))) vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY; PMD_DRV_LOG(DEBUG, "duplex %x flow_ctrl 0x%x link_status 0x%x", vars->duplex, vars->flow_ctrl, vars->link_status); return rc; } static void elink_set_gmii_tx_driver(struct elink_params *params) { struct bnx2x_softc *sc = params->sc; struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY]; uint16_t lp_up2; uint16_t tx_driver; uint16_t bank; /* Read precomp */ CL22_RD_OVER_CL45(sc, phy, MDIO_REG_BANK_OVER_1G, MDIO_OVER_1G_LP_UP2, &lp_up2); /* Bits [10:7] at lp_up2, positioned at [15:12] */ lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >> MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) << MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT); if (lp_up2 == 0) return; for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3; bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) { CL22_RD_OVER_CL45(sc, phy, bank, MDIO_TX0_TX_DRIVER, &tx_driver); /* Replace tx_driver bits [15:12] */ if (lp_up2 != (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) { tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK; tx_driver |= lp_up2; CL22_WR_OVER_CL45(sc, phy, bank, MDIO_TX0_TX_DRIVER, tx_driver); } } } static elink_status_t elink_emac_program(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint16_t mode = 0; PMD_DRV_LOG(DEBUG, "setting link speed & duplex"); elink_bits_dis(sc, GRCBASE_EMAC0 + port * 0x400 + EMAC_REG_EMAC_MODE, (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_MII_10M | EMAC_MODE_HALF_DUPLEX)); switch (vars->line_speed) { case ELINK_SPEED_10: mode |= EMAC_MODE_PORT_MII_10M; break; case ELINK_SPEED_100: mode |= EMAC_MODE_PORT_MII; break; case ELINK_SPEED_1000: mode |= EMAC_MODE_PORT_GMII; break; case ELINK_SPEED_2500: mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII); break; default: /* 10G not valid for EMAC */ PMD_DRV_LOG(DEBUG, "Invalid line_speed 0x%x", vars->line_speed); return ELINK_STATUS_ERROR; } if (vars->duplex == DUPLEX_HALF) mode |= EMAC_MODE_HALF_DUPLEX; elink_bits_en(sc, GRCBASE_EMAC0 + port * 0x400 + EMAC_REG_EMAC_MODE, mode); elink_set_led(params, vars, ELINK_LED_MODE_OPER, vars->line_speed); return ELINK_STATUS_OK; } static void elink_set_preemphasis(struct elink_phy *phy, struct elink_params *params) { uint16_t bank, i = 0; struct bnx2x_softc *sc = params->sc; for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3; bank += (MDIO_REG_BANK_RX1 - MDIO_REG_BANK_RX0), i++) { CL22_WR_OVER_CL45(sc, phy, bank, MDIO_RX0_RX_EQ_BOOST, phy->rx_preemphasis[i]); } for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3; bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) { CL22_WR_OVER_CL45(sc, phy, bank, MDIO_TX0_TX_DRIVER, phy->tx_preemphasis[i]); } } static void elink_xgxs_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint8_t enable_cl73 = (ELINK_SINGLE_MEDIA_DIRECT(params) || (params->loopback_mode == ELINK_LOOPBACK_XGXS)); if (!(vars->phy_flags & PHY_SGMII_FLAG)) { if (ELINK_SINGLE_MEDIA_DIRECT(params) && (params->feature_config_flags & ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) elink_set_preemphasis(phy, params); /* Forced speed requested? */ if (vars->line_speed != ELINK_SPEED_AUTO_NEG || (ELINK_SINGLE_MEDIA_DIRECT(params) && params->loopback_mode == ELINK_LOOPBACK_EXT)) { PMD_DRV_LOG(DEBUG, "not SGMII, no AN"); /* Disable autoneg */ elink_set_autoneg(phy, params, vars, 0); /* Program speed and duplex */ elink_program_serdes(phy, params, vars); } else { /* AN_mode */ PMD_DRV_LOG(DEBUG, "not SGMII, AN"); /* AN enabled */ elink_set_brcm_cl37_advertisement(phy, params); /* Program duplex & pause advertisement (for aneg) */ elink_set_ieee_aneg_advertisement(phy, params, vars->ieee_fc); /* Enable autoneg */ elink_set_autoneg(phy, params, vars, enable_cl73); /* Enable and restart AN */ elink_restart_autoneg(phy, params, enable_cl73); } } else { /* SGMII mode */ PMD_DRV_LOG(DEBUG, "SGMII"); elink_initialize_sgmii_process(phy, params, vars); } } static elink_status_t elink_prepare_xgxs(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { elink_status_t rc; vars->phy_flags |= PHY_XGXS_FLAG; if ((phy->req_line_speed && ((phy->req_line_speed == ELINK_SPEED_100) || (phy->req_line_speed == ELINK_SPEED_10))) || (!phy->req_line_speed && (phy->speed_cap_mask >= PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) && (phy->speed_cap_mask < PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD)) vars->phy_flags |= PHY_SGMII_FLAG; else vars->phy_flags &= ~PHY_SGMII_FLAG; elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); elink_set_aer_mmd(params, phy); if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) elink_set_master_ln(params, phy); rc = elink_reset_unicore(params, phy, 0); /* Reset the SerDes and wait for reset bit return low */ if (rc != ELINK_STATUS_OK) return rc; elink_set_aer_mmd(params, phy); /* Setting the masterLn_def again after the reset */ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) { elink_set_master_ln(params, phy); elink_set_swap_lanes(params, phy); } return rc; } static uint16_t elink_wait_reset_complete(struct bnx2x_softc *sc, struct elink_phy *phy, struct elink_params *params) { uint16_t cnt, ctrl; /* Wait for soft reset to get cleared up to 1 sec */ for (cnt = 0; cnt < 1000; cnt++) { if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE) elink_cl22_read(sc, phy, MDIO_PMA_REG_CTRL, &ctrl); else elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl); if (!(ctrl & (1 << 15))) break; DELAY(1000 * 1); } if (cnt == 1000) elink_cb_event_log(sc, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized," // " Port %d", PMD_DRV_LOG(DEBUG, "control reg 0x%x (after %d ms)", ctrl, cnt); return cnt; } static void elink_link_int_enable(struct elink_params *params) { uint8_t port = params->port; uint32_t mask; struct bnx2x_softc *sc = params->sc; /* Setting the status to report on link up for either XGXS or SerDes */ if (CHIP_IS_E3(sc)) { mask = ELINK_NIG_MASK_XGXS0_LINK_STATUS; if (!(ELINK_SINGLE_MEDIA_DIRECT(params))) mask |= ELINK_NIG_MASK_MI_INT; } else if (params->switch_cfg == ELINK_SWITCH_CFG_10G) { mask = (ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_XGXS0_LINK_STATUS); PMD_DRV_LOG(DEBUG, "enabled XGXS interrupt"); if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) && params->phy[ELINK_INT_PHY].type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) { mask |= ELINK_NIG_MASK_MI_INT; PMD_DRV_LOG(DEBUG, "enabled external phy int"); } } else { /* SerDes */ mask = ELINK_NIG_MASK_SERDES0_LINK_STATUS; PMD_DRV_LOG(DEBUG, "enabled SerDes interrupt"); if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) && params->phy[ELINK_INT_PHY].type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) { mask |= ELINK_NIG_MASK_MI_INT; PMD_DRV_LOG(DEBUG, "enabled external phy int"); } } elink_bits_en(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4, mask); PMD_DRV_LOG(DEBUG, "port %x, is_xgxs %x, int_status 0x%x", port, (params->switch_cfg == ELINK_SWITCH_CFG_10G), REG_RD(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4)); PMD_DRV_LOG(DEBUG, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x", REG_RD(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4), REG_RD(sc, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port * 0x18), REG_RD(sc, NIG_REG_SERDES0_STATUS_LINK_STATUS + port * 0x3c)); PMD_DRV_LOG(DEBUG, " 10G %x, XGXS_LINK %x", REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK10G + port * 0x68), REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK_STATUS + port * 0x68)); } static void elink_rearm_latch_signal(struct bnx2x_softc *sc, uint8_t port, uint8_t exp_mi_int) { uint32_t latch_status = 0; /* Disable the MI INT ( external phy int ) by writing 1 to the * status register. Link down indication is high-active-signal, * so in this case we need to write the status to clear the XOR */ /* Read Latched signals */ latch_status = REG_RD(sc, NIG_REG_LATCH_STATUS_0 + port * 8); PMD_DRV_LOG(DEBUG, "latch_status = 0x%x", latch_status); /* Handle only those with latched-signal=up. */ if (exp_mi_int) elink_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4, ELINK_NIG_STATUS_EMAC0_MI_INT); else elink_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4, ELINK_NIG_STATUS_EMAC0_MI_INT); if (latch_status & 1) { /* For all latched-signal=up : Re-Arm Latch signals */ REG_WR(sc, NIG_REG_LATCH_STATUS_0 + port * 8, (latch_status & 0xfffe) | (latch_status & 1)); } /* For all latched-signal=up,Write original_signal to status */ } static void elink_link_int_ack(struct elink_params *params, struct elink_vars *vars, uint8_t is_10g_plus) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; uint32_t mask; /* First reset all status we assume only one line will be * change at a time */ elink_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4, (ELINK_NIG_STATUS_XGXS0_LINK10G | ELINK_NIG_STATUS_XGXS0_LINK_STATUS | ELINK_NIG_STATUS_SERDES0_LINK_STATUS)); if (vars->phy_link_up) { if (USES_WARPCORE(sc)) mask = ELINK_NIG_STATUS_XGXS0_LINK_STATUS; else { if (is_10g_plus) mask = ELINK_NIG_STATUS_XGXS0_LINK10G; else if (params->switch_cfg == ELINK_SWITCH_CFG_10G) { /* Disable the link interrupt by writing 1 to * the relevant lane in the status register */ uint32_t ser_lane = ((params->lane_config & PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); mask = ((1 << ser_lane) << ELINK_NIG_STATUS_XGXS0_LINK_STATUS_SIZE); } else mask = ELINK_NIG_STATUS_SERDES0_LINK_STATUS; } PMD_DRV_LOG(DEBUG, "Ack link up interrupt with mask 0x%x", mask); elink_bits_en(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4, mask); } } static elink_status_t elink_format_ver(uint32_t num, uint8_t * str, uint16_t * len) { uint8_t *str_ptr = str; uint32_t mask = 0xf0000000; uint8_t shift = 8 * 4; uint8_t digit; uint8_t remove_leading_zeros = 1; if (*len < 10) { /* Need more than 10chars for this format */ *str_ptr = '\0'; (*len)--; return ELINK_STATUS_ERROR; } while (shift > 0) { shift -= 4; digit = ((num & mask) >> shift); if (digit == 0 && remove_leading_zeros) { mask = mask >> 4; continue; } else if (digit < 0xa) *str_ptr = digit + '0'; else *str_ptr = digit - 0xa + 'a'; remove_leading_zeros = 0; str_ptr++; (*len)--; mask = mask >> 4; if (shift == 4 * 4) { *str_ptr = '.'; str_ptr++; (*len)--; remove_leading_zeros = 1; } } return ELINK_STATUS_OK; } static elink_status_t elink_null_format_ver(__rte_unused uint32_t spirom_ver, uint8_t * str, uint16_t * len) { str[0] = '\0'; (*len)--; return ELINK_STATUS_OK; } static void elink_set_xgxs_loopback(struct elink_phy *phy, struct elink_params *params) { uint8_t port = params->port; struct bnx2x_softc *sc = params->sc; if (phy->req_line_speed != ELINK_SPEED_1000) { uint32_t md_devad = 0; PMD_DRV_LOG(DEBUG, "XGXS 10G loopback enable"); if (!CHIP_IS_E3(sc)) { /* Change the uni_phy_addr in the nig */ md_devad = REG_RD(sc, (NIG_REG_XGXS0_CTRL_MD_DEVAD + port * 0x18)); REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + port * 0x18, 0x5); } elink_cl45_write(sc, phy, 5, (MDIO_REG_BANK_AER_BLOCK + (MDIO_AER_BLOCK_AER_REG & 0xf)), 0x2800); elink_cl45_write(sc, phy, 5, (MDIO_REG_BANK_CL73_IEEEB0 + (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), 0x6041); DELAY(1000 * 200); /* Set aer mmd back */ elink_set_aer_mmd(params, phy); if (!CHIP_IS_E3(sc)) { /* And md_devad */ REG_WR(sc, NIG_REG_XGXS0_CTRL_MD_DEVAD + port * 0x18, md_devad); } } else { uint16_t mii_ctrl; PMD_DRV_LOG(DEBUG, "XGXS 1G loopback enable"); elink_cl45_read(sc, phy, 5, (MDIO_REG_BANK_COMBO_IEEE0 + (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), &mii_ctrl); elink_cl45_write(sc, phy, 5, (MDIO_REG_BANK_COMBO_IEEE0 + (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), mii_ctrl | MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK); } } elink_status_t elink_set_led(struct elink_params *params, struct elink_vars *vars, uint8_t mode, uint32_t speed) { uint8_t port = params->port; uint16_t hw_led_mode = params->hw_led_mode; elink_status_t rc = ELINK_STATUS_OK; uint8_t phy_idx; uint32_t tmp; uint32_t emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "elink_set_led: port %x, mode %d", port, mode); PMD_DRV_LOG(DEBUG, "speed 0x%x, hw_led_mode 0x%x", speed, hw_led_mode); /* In case */ for (phy_idx = ELINK_EXT_PHY1; phy_idx < ELINK_MAX_PHYS; phy_idx++) { if (params->phy[phy_idx].set_link_led) { params->phy[phy_idx].set_link_led(¶ms->phy[phy_idx], params, mode); } } #ifdef ELINK_INCLUDE_EMUL if (params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC) return rc; #endif switch (mode) { case ELINK_LED_MODE_FRONT_PANEL_OFF: case ELINK_LED_MODE_OFF: REG_WR(sc, NIG_REG_LED_10G_P0 + port * 4, 0); REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, SHARED_HW_CFG_LED_MAC1); tmp = elink_cb_reg_read(sc, emac_base + EMAC_REG_EMAC_LED); if (params->phy[ELINK_EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE) tmp &= ~(EMAC_LED_1000MB_OVERRIDE | EMAC_LED_100MB_OVERRIDE | EMAC_LED_10MB_OVERRIDE); else tmp |= EMAC_LED_OVERRIDE; elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_LED, tmp); break; case ELINK_LED_MODE_OPER: /* For all other phys, OPER mode is same as ON, so in case * link is down, do nothing */ if (!vars->link_up) break; case ELINK_LED_MODE_ON: if (((params->phy[ELINK_EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727) || (params->phy[ELINK_EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722)) && CHIP_IS_E2(sc) && params->num_phys == 2) { /* This is a work-around for E2+8727 Configurations */ if (mode == ELINK_LED_MODE_ON || speed == ELINK_SPEED_10000) { REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, 0); REG_WR(sc, NIG_REG_LED_10G_P0 + port * 4, 1); tmp = elink_cb_reg_read(sc, emac_base + EMAC_REG_EMAC_LED); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE)); /* Return here without enabling traffic * LED blink and setting rate in ON mode. * In oper mode, enabling LED blink * and setting rate is needed. */ if (mode == ELINK_LED_MODE_ON) return rc; } } else if (ELINK_SINGLE_MEDIA_DIRECT(params)) { /* This is a work-around for HW issue found when link * is up in CL73 */ if ((!CHIP_IS_E3(sc)) || (CHIP_IS_E3(sc) && mode == ELINK_LED_MODE_ON)) REG_WR(sc, NIG_REG_LED_10G_P0 + port * 4, 1); if (CHIP_IS_E1x(sc) || CHIP_IS_E2(sc) || (mode == ELINK_LED_MODE_ON)) REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, 0); else REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, hw_led_mode); } else if ((params->phy[ELINK_EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE) && (mode == ELINK_LED_MODE_ON)) { REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, 0); tmp = elink_cb_reg_read(sc, emac_base + EMAC_REG_EMAC_LED); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_LED, tmp | EMAC_LED_OVERRIDE | EMAC_LED_1000MB_OVERRIDE); /* Break here; otherwise, it'll disable the * intended override. */ break; } else { uint32_t nig_led_mode = ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY2) ? (SHARED_HW_CFG_LED_PHY1 >> SHARED_HW_CFG_LED_MODE_SHIFT) : hw_led_mode; REG_WR(sc, NIG_REG_LED_MODE_P0 + port * 4, nig_led_mode); } REG_WR(sc, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port * 4, 0); /* Set blinking rate to ~15.9Hz */ if (CHIP_IS_E3(sc)) REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port * 4, LED_BLINK_RATE_VAL_E3); else REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port * 4, LED_BLINK_RATE_VAL_E1X_E2); REG_WR(sc, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 + port * 4, 1); tmp = elink_cb_reg_read(sc, emac_base + EMAC_REG_EMAC_LED); elink_cb_reg_write(sc, emac_base + EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE))); break; default: rc = ELINK_STATUS_ERROR; PMD_DRV_LOG(DEBUG, "elink_set_led: Invalid led mode %d", mode); break; } return rc; } static elink_status_t elink_link_initialize(struct elink_params *params, struct elink_vars *vars) { elink_status_t rc = ELINK_STATUS_OK; uint8_t phy_index, non_ext_phy; struct bnx2x_softc *sc = params->sc; /* In case of external phy existence, the line speed would be the * line speed linked up by the external phy. In case it is direct * only, then the line_speed during initialization will be * equal to the req_line_speed */ vars->line_speed = params->phy[ELINK_INT_PHY].req_line_speed; /* Initialize the internal phy in case this is a direct board * (no external phys), or this board has external phy which requires * to first. */ if (!USES_WARPCORE(sc)) elink_prepare_xgxs(¶ms->phy[ELINK_INT_PHY], params, vars); /* init ext phy and enable link state int */ non_ext_phy = (ELINK_SINGLE_MEDIA_DIRECT(params) || (params->loopback_mode == ELINK_LOOPBACK_XGXS)); if (non_ext_phy || (params->phy[ELINK_EXT_PHY1].flags & ELINK_FLAGS_INIT_XGXS_FIRST) || (params->loopback_mode == ELINK_LOOPBACK_EXT_PHY)) { struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY]; if (vars->line_speed == ELINK_SPEED_AUTO_NEG && (CHIP_IS_E1x(sc) || CHIP_IS_E2(sc))) elink_set_parallel_detection(phy, params); if (params->phy[ELINK_INT_PHY].config_init) params->phy[ELINK_INT_PHY].config_init(phy, params, vars); } /* Re-read this value in case it was changed inside config_init due to * limitations of optic module */ vars->line_speed = params->phy[ELINK_INT_PHY].req_line_speed; /* Init external phy */ if (non_ext_phy) { if (params->phy[ELINK_INT_PHY].supported & ELINK_SUPPORTED_FIBRE) vars->link_status |= LINK_STATUS_SERDES_LINK; } else { for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys; phy_index++) { /* No need to initialize second phy in case of first * phy only selection. In case of second phy, we do * need to initialize the first phy, since they are * connected. */ if (params->phy[phy_index].supported & ELINK_SUPPORTED_FIBRE) vars->link_status |= LINK_STATUS_SERDES_LINK; if (phy_index == ELINK_EXT_PHY2 && (elink_phy_selection(params) == PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) { PMD_DRV_LOG(DEBUG, "Not initializing second phy"); continue; } params->phy[phy_index].config_init(¶ms-> phy[phy_index], params, vars); } } /* Reset the interrupt indication after phy was initialized */ elink_bits_dis(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + params->port * 4, (ELINK_NIG_STATUS_XGXS0_LINK10G | ELINK_NIG_STATUS_XGXS0_LINK_STATUS | ELINK_NIG_STATUS_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); return rc; } static void elink_int_link_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { /* Reset the SerDes/XGXS */ REG_WR(params->sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, (0x1ff << (params->port * 16))); } static void elink_common_ext_link_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t gpio_port; /* HW reset */ if (CHIP_IS_E2(sc)) gpio_port = SC_PATH(sc); else gpio_port = params->port; elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, gpio_port); elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_LOW, gpio_port); PMD_DRV_LOG(DEBUG, "reset external PHY"); } static elink_status_t elink_update_link_down(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t port = params->port; PMD_DRV_LOG(DEBUG, "Port %x: Link is down", port); elink_set_led(params, vars, ELINK_LED_MODE_OFF, 0); vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG; /* Indicate no mac active */ vars->mac_type = ELINK_MAC_TYPE_NONE; /* Update shared memory */ vars->link_status &= ~ELINK_LINK_UPDATE_MASK; vars->line_speed = 0; elink_update_mng(params, vars->link_status); /* Activate nig drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 1); /* Disable emac */ if (!CHIP_IS_E3(sc)) REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0); DELAY(1000 * 10); /* Reset BigMac/Xmac */ if (CHIP_IS_E1x(sc) || CHIP_IS_E2(sc)) elink_set_bmac_rx(sc, params->port, 0); if (CHIP_IS_E3(sc)) { /* Prevent LPI Generation by chip */ REG_WR(sc, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2), 0); REG_WR(sc, MISC_REG_CPMU_LP_MASK_ENT_P0 + (params->port << 2), 0); vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK | SHMEM_EEE_ACTIVE_BIT); elink_update_mng_eee(params, vars->eee_status); elink_set_xmac_rxtx(params, 0); elink_set_umac_rxtx(params, 0); } return ELINK_STATUS_OK; } static elink_status_t elink_update_link_up(struct elink_params *params, struct elink_vars *vars, uint8_t link_10g) { struct bnx2x_softc *sc = params->sc; uint8_t phy_idx, port = params->port; elink_status_t rc = ELINK_STATUS_OK; vars->link_status |= (LINK_STATUS_LINK_UP | LINK_STATUS_PHYSICAL_LINK_FLAG); vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG; if (vars->flow_ctrl & ELINK_FLOW_CTRL_TX) vars->link_status |= LINK_STATUS_TX_FLOW_CONTROL_ENABLED; if (vars->flow_ctrl & ELINK_FLOW_CTRL_RX) vars->link_status |= LINK_STATUS_RX_FLOW_CONTROL_ENABLED; if (USES_WARPCORE(sc)) { if (link_10g) { if (elink_xmac_enable(params, vars, 0) == ELINK_STATUS_NO_LINK) { PMD_DRV_LOG(DEBUG, "Found errors on XMAC"); vars->link_up = 0; vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; vars->link_status &= ~LINK_STATUS_LINK_UP; } } else elink_umac_enable(params, vars, 0); elink_set_led(params, vars, ELINK_LED_MODE_OPER, vars->line_speed); if ((vars->eee_status & SHMEM_EEE_ACTIVE_BIT) && (vars->eee_status & SHMEM_EEE_LPI_REQUESTED_BIT)) { PMD_DRV_LOG(DEBUG, "Enabling LPI assertion"); REG_WR(sc, MISC_REG_CPMU_LP_FW_ENABLE_P0 + (params->port << 2), 1); REG_WR(sc, MISC_REG_CPMU_LP_DR_ENABLE, 1); REG_WR(sc, MISC_REG_CPMU_LP_MASK_ENT_P0 + (params->port << 2), 0xfc20); } } if ((CHIP_IS_E1x(sc) || CHIP_IS_E2(sc))) { if (link_10g) { if (elink_bmac_enable(params, vars, 0, 1) == ELINK_STATUS_NO_LINK) { PMD_DRV_LOG(DEBUG, "Found errors on BMAC"); vars->link_up = 0; vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG; vars->link_status &= ~LINK_STATUS_LINK_UP; } elink_set_led(params, vars, ELINK_LED_MODE_OPER, ELINK_SPEED_10000); } else { rc = elink_emac_program(params, vars); elink_emac_enable(params, vars, 0); /* AN complete? */ if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) && (!(vars->phy_flags & PHY_SGMII_FLAG)) && ELINK_SINGLE_MEDIA_DIRECT(params)) elink_set_gmii_tx_driver(params); } } /* PBF - link up */ if (CHIP_IS_E1x(sc)) rc |= elink_pbf_update(params, vars->flow_ctrl, vars->line_speed); /* Disable drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 0); /* Update shared memory */ elink_update_mng(params, vars->link_status); elink_update_mng_eee(params, vars->eee_status); /* Check remote fault */ for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) { if (params->phy[phy_idx].flags & ELINK_FLAGS_TX_ERROR_CHECK) { elink_check_half_open_conn(params, vars, 0); break; } } DELAY(1000 * 20); return rc; } /* The elink_link_update function should be called upon link * interrupt. * Link is considered up as follows: * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs * to be up * - SINGLE_MEDIA - The link between the 577xx and the external * phy (XGXS) need to up as well as the external link of the * phy (PHY_EXT1) * - DUAL_MEDIA - The link between the 577xx and the first * external phy needs to be up, and at least one of the 2 * external phy link must be up. */ elink_status_t elink_link_update(struct elink_params * params, struct elink_vars * vars) { struct bnx2x_softc *sc = params->sc; struct elink_vars phy_vars[ELINK_MAX_PHYS]; uint8_t port = params->port; uint8_t link_10g_plus, phy_index; uint8_t ext_phy_link_up = 0, cur_link_up; elink_status_t rc = ELINK_STATUS_OK; __rte_unused uint8_t is_mi_int = 0; uint16_t ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; uint8_t active_external_phy = ELINK_INT_PHY; vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; vars->link_status &= ~ELINK_LINK_UPDATE_MASK; for (phy_index = ELINK_INT_PHY; phy_index < params->num_phys; phy_index++) { phy_vars[phy_index].flow_ctrl = 0; phy_vars[phy_index].link_status = 0; phy_vars[phy_index].line_speed = 0; phy_vars[phy_index].duplex = DUPLEX_FULL; phy_vars[phy_index].phy_link_up = 0; phy_vars[phy_index].link_up = 0; phy_vars[phy_index].fault_detected = 0; /* different consideration, since vars holds inner state */ phy_vars[phy_index].eee_status = vars->eee_status; } if (USES_WARPCORE(sc)) elink_set_aer_mmd(params, ¶ms->phy[ELINK_INT_PHY]); PMD_DRV_LOG(DEBUG, "port %x, XGXS?%x, int_status 0x%x", port, (vars->phy_flags & PHY_XGXS_FLAG), REG_RD(sc, NIG_REG_STATUS_INTERRUPT_PORT0 + port * 4)); is_mi_int = (uint8_t) (REG_RD(sc, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port * 0x18) > 0); PMD_DRV_LOG(DEBUG, "int_mask 0x%x MI_INT %x, SERDES_LINK %x", REG_RD(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4), is_mi_int, REG_RD(sc, NIG_REG_SERDES0_STATUS_LINK_STATUS + port * 0x3c)); PMD_DRV_LOG(DEBUG, " 10G %x, XGXS_LINK %x", REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK10G + port * 0x68), REG_RD(sc, NIG_REG_XGXS0_STATUS_LINK_STATUS + port * 0x68)); /* Disable emac */ if (!CHIP_IS_E3(sc)) REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0); /* Step 1: * Check external link change only for external phys, and apply * priority selection between them in case the link on both phys * is up. Note that instead of the common vars, a temporary * vars argument is used since each phy may have different link/ * speed/duplex result */ for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys; phy_index++) { struct elink_phy *phy = ¶ms->phy[phy_index]; if (!phy->read_status) continue; /* Read link status and params of this ext phy */ cur_link_up = phy->read_status(phy, params, &phy_vars[phy_index]); if (cur_link_up) { PMD_DRV_LOG(DEBUG, "phy in index %d link is up", phy_index); } else { PMD_DRV_LOG(DEBUG, "phy in index %d link is down", phy_index); continue; } if (!ext_phy_link_up) { ext_phy_link_up = 1; active_external_phy = phy_index; } else { switch (elink_phy_selection(params)) { case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: /* In this option, the first PHY makes sure to pass the * traffic through itself only. * Its not clear how to reset the link on the second phy */ active_external_phy = ELINK_EXT_PHY1; break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: /* In this option, the first PHY makes sure to pass the * traffic through the second PHY. */ active_external_phy = ELINK_EXT_PHY2; break; default: /* Link indication on both PHYs with the following cases * is invalid: * - FIRST_PHY means that second phy wasn't initialized, * hence its link is expected to be down * - SECOND_PHY means that first phy should not be able * to link up by itself (using configuration) * - DEFAULT should be overriden during initialiazation */ PMD_DRV_LOG(DEBUG, "Invalid link indication" "mpc=0x%x. DISABLING LINK !!!", params->multi_phy_config); ext_phy_link_up = 0; break; } } } prev_line_speed = vars->line_speed; /* Step 2: * Read the status of the internal phy. In case of * DIRECT_SINGLE_MEDIA board, this link is the external link, * otherwise this is the link between the 577xx and the first * external phy */ if (params->phy[ELINK_INT_PHY].read_status) params->phy[ELINK_INT_PHY].read_status(¶ms-> phy[ELINK_INT_PHY], params, vars); /* The INT_PHY flow control reside in the vars. This include the * case where the speed or flow control are not set to AUTO. * Otherwise, the active external phy flow control result is set * to the vars. The ext_phy_line_speed is needed to check if the * speed is different between the internal phy and external phy. * This case may be result of intermediate link speed change. */ if (active_external_phy > ELINK_INT_PHY) { vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl; /* Link speed is taken from the XGXS. AN and FC result from * the external phy. */ vars->link_status |= phy_vars[active_external_phy].link_status; /* if active_external_phy is first PHY and link is up - disable * disable TX on second external PHY */ if (active_external_phy == ELINK_EXT_PHY1) { if (params->phy[ELINK_EXT_PHY2].phy_specific_func) { PMD_DRV_LOG(DEBUG, "Disabling TX on EXT_PHY2"); params->phy[ELINK_EXT_PHY2]. phy_specific_func(¶ms-> phy[ELINK_EXT_PHY2], params, ELINK_DISABLE_TX); } } ext_phy_line_speed = phy_vars[active_external_phy].line_speed; vars->duplex = phy_vars[active_external_phy].duplex; if (params->phy[active_external_phy].supported & ELINK_SUPPORTED_FIBRE) vars->link_status |= LINK_STATUS_SERDES_LINK; else vars->link_status &= ~LINK_STATUS_SERDES_LINK; vars->eee_status = phy_vars[active_external_phy].eee_status; PMD_DRV_LOG(DEBUG, "Active external phy selected: %x", active_external_phy); } for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys; phy_index++) { if (params->phy[phy_index].flags & ELINK_FLAGS_REARM_LATCH_SIGNAL) { elink_rearm_latch_signal(sc, port, phy_index == active_external_phy); break; } } PMD_DRV_LOG(DEBUG, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," " ext_phy_line_speed = %d", vars->flow_ctrl, vars->link_status, ext_phy_line_speed); /* Upon link speed change set the NIG into drain mode. Comes to * deals with possible FIFO glitch due to clk change when speed * is decreased without link down indicator */ if (vars->phy_link_up) { if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up && (ext_phy_line_speed != vars->line_speed)) { PMD_DRV_LOG(DEBUG, "Internal link speed %d is" " different than the external" " link speed %d", vars->line_speed, ext_phy_line_speed); vars->phy_link_up = 0; } else if (prev_line_speed != vars->line_speed) { REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); DELAY(1000 * 1); } } /* Anything 10 and over uses the bmac */ link_10g_plus = (vars->line_speed >= ELINK_SPEED_10000); elink_link_int_ack(params, vars, link_10g_plus); /* In case external phy link is up, and internal link is down * (not initialized yet probably after link initialization, it * needs to be initialized. * Note that after link down-up as result of cable plug, the xgxs * link would probably become up again without the need * initialize it */ if (!(ELINK_SINGLE_MEDIA_DIRECT(params))) { PMD_DRV_LOG(DEBUG, "ext_phy_link_up = %d, int_link_up = %d," " init_preceding = %d", ext_phy_link_up, vars->phy_link_up, params->phy[ELINK_EXT_PHY1].flags & ELINK_FLAGS_INIT_XGXS_FIRST); if (!(params->phy[ELINK_EXT_PHY1].flags & ELINK_FLAGS_INIT_XGXS_FIRST) && ext_phy_link_up && !vars->phy_link_up) { vars->line_speed = ext_phy_line_speed; if (vars->line_speed < ELINK_SPEED_1000) vars->phy_flags |= PHY_SGMII_FLAG; else vars->phy_flags &= ~PHY_SGMII_FLAG; if (params->phy[ELINK_INT_PHY].config_init) params->phy[ELINK_INT_PHY].config_init(¶ms-> phy [ELINK_INT_PHY], params, vars); } } /* Link is up only if both local phy and external phy (in case of * non-direct board) are up and no fault detected on active PHY. */ vars->link_up = (vars->phy_link_up && (ext_phy_link_up || ELINK_SINGLE_MEDIA_DIRECT(params)) && (phy_vars[active_external_phy].fault_detected == 0)); /* Update the PFC configuration in case it was changed */ if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) vars->link_status |= LINK_STATUS_PFC_ENABLED; else vars->link_status &= ~LINK_STATUS_PFC_ENABLED; if (vars->link_up) rc = elink_update_link_up(params, vars, link_10g_plus); else rc = elink_update_link_down(params, vars); /* Update MCP link status was changed */ if (params-> feature_config_flags & ELINK_FEATURE_CONFIG_BC_SUPPORTS_AFEX) elink_cb_fw_command(sc, DRV_MSG_CODE_LINK_STATUS_CHANGED, 0); return rc; } /*****************************************************************************/ /* External Phy section */ /*****************************************************************************/ static void elink_ext_phy_hw_reset(struct bnx2x_softc *sc, uint8_t port) { elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); DELAY(1000 * 1); elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); } static void elink_save_spirom_version(struct bnx2x_softc *sc, __rte_unused uint8_t port, uint32_t spirom_ver, uint32_t ver_addr) { PMD_DRV_LOG(DEBUG, "FW version 0x%x:0x%x for port %d", (uint16_t) (spirom_ver >> 16), (uint16_t) spirom_ver, port); if (ver_addr) REG_WR(sc, ver_addr, spirom_ver); } static void elink_save_bnx2x_spirom_ver(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t port) { uint16_t fw_ver1, fw_ver2; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &fw_ver1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &fw_ver2); elink_save_spirom_version(sc, port, (uint32_t) (fw_ver1 << 16 | fw_ver2), phy->ver_addr); } static void elink_ext_phy_10G_an_resolve(struct bnx2x_softc *sc, struct elink_phy *phy, struct elink_vars *vars) { uint16_t val; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &val); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_STATUS, &val); if (val & (1 << 5)) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; if ((val & (1 << 0)) == 0) vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; } /******************************************************************/ /* common BNX2X8073/BNX2X8727 PHY SECTION */ /******************************************************************/ static void elink_8073_resolve_fc(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; if (phy->req_line_speed == ELINK_SPEED_10 || phy->req_line_speed == ELINK_SPEED_100) { vars->flow_ctrl = phy->req_flow_ctrl; return; } if (elink_ext_phy_resolve_fc(phy, params, vars) && (vars->flow_ctrl == ELINK_FLOW_CTRL_NONE)) { uint16_t pause_result; uint16_t ld_pause; /* local */ uint16_t lp_pause; /* link partner */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &ld_pause); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, &lp_pause); pause_result = (ld_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5; pause_result |= (lp_pause & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; elink_pause_resolve(vars, pause_result); PMD_DRV_LOG(DEBUG, "Ext PHY CL37 pause result 0x%x", pause_result); } } static elink_status_t elink_8073_8727_external_rom_boot(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t port) { uint32_t count = 0; uint16_t fw_ver1, fw_msgout; elink_status_t rc = ELINK_STATUS_OK; /* Boot port from external ROM */ /* EDC grst */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001); /* Ucode reboot and rst */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x008c); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL1, 0x0001); /* Reset internal microprocessor */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); /* Release srst bit */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); /* Delay 100ms per the PHY specifications */ DELAY(1000 * 100); /* 8073 sometimes taking longer to download */ do { count++; if (count > 300) { PMD_DRV_LOG(DEBUG, "elink_8073_8727_external_rom_boot port %x:" "Download failed. fw version = 0x%x", port, fw_ver1); rc = ELINK_STATUS_ERROR; break; } elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &fw_ver1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout); DELAY(1000 * 1); } while (fw_ver1 == 0 || fw_ver1 == 0x4321 || ((fw_msgout & 0xff) != 0x03 && (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8073))); /* Clear ser_boot_ctl bit */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL1, 0x0000); elink_save_bnx2x_spirom_ver(sc, phy, port); PMD_DRV_LOG(DEBUG, "elink_8073_8727_external_rom_boot port %x:" "Download complete. fw version = 0x%x", port, fw_ver1); return rc; } /******************************************************************/ /* BNX2X8073 PHY SECTION */ /******************************************************************/ static elink_status_t elink_8073_is_snr_needed(struct bnx2x_softc *sc, struct elink_phy *phy) { /* This is only required for 8073A1, version 102 only */ uint16_t val; /* Read 8073 HW revision */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val); if (val != 1) { /* No need to workaround in 8073 A1 */ return ELINK_STATUS_OK; } elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &val); /* SNR should be applied only for version 0x102 */ if (val != 0x102) return ELINK_STATUS_OK; return 1; } static elink_status_t elink_8073_xaui_wa(struct bnx2x_softc *sc, struct elink_phy *phy) { uint16_t val, cnt, cnt1; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val); if (val > 0) { /* No need to workaround in 8073 A1 */ return ELINK_STATUS_OK; } /* XAUI workaround in 8073 A0: */ /* After loading the boot ROM and restarting Autoneg, poll * Dev1, Reg $C820: */ for (cnt = 0; cnt < 1000; cnt++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &val); /* If bit [14] = 0 or bit [13] = 0, continue on with * system initialization (XAUI work-around not required, as * these bits indicate 2.5G or 1G link up). */ if (!(val & (1 << 14)) || !(val & (1 << 13))) { PMD_DRV_LOG(DEBUG, "XAUI work-around not required"); return ELINK_STATUS_OK; } else if (!(val & (1 << 15))) { PMD_DRV_LOG(DEBUG, "bit 15 went off"); /* If bit 15 is 0, then poll Dev1, Reg $C841 until it's * MSB (bit15) goes to 1 (indicating that the XAUI * workaround has completed), then continue on with * system initialization. */ for (cnt1 = 0; cnt1 < 1000; cnt1++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_XAUI_WA, &val); if (val & (1 << 15)) { PMD_DRV_LOG(DEBUG, "XAUI workaround has completed"); return ELINK_STATUS_OK; } DELAY(1000 * 3); } break; } DELAY(1000 * 3); } PMD_DRV_LOG(DEBUG, "Warning: XAUI work-around timeout !!!"); return ELINK_STATUS_ERROR; } static void elink_807x_force_10G(struct bnx2x_softc *sc, struct elink_phy *phy) { /* Force KR or KX */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_BNX2X_CTRL, 0x0000); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000); } static void elink_8073_set_pause_cl37(struct elink_params *params, struct elink_phy *phy, struct elink_vars *vars) { uint16_t cl37_val; struct bnx2x_softc *sc = params->sc; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val); cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) { cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC; } if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; } if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; } PMD_DRV_LOG(DEBUG, "Ext phy AN advertize cl37 0x%x", cl37_val); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val); DELAY(1000 * 500); } static void elink_8073_specific_func(struct elink_phy *phy, struct elink_params *params, uint32_t action) { struct bnx2x_softc *sc = params->sc; switch (action) { case ELINK_PHY_INIT: /* Enable LASI */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1 << 2)); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0004); break; } } static elink_status_t elink_8073_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t val = 0, tmp1; uint8_t gpio_port; PMD_DRV_LOG(DEBUG, "Init 8073"); if (CHIP_IS_E2(sc)) gpio_port = SC_PATH(sc); else gpio_port = params->port; /* Restore normal power mode */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); elink_8073_specific_func(phy, params, ELINK_PHY_INIT); elink_8073_set_pause_cl37(params, phy, vars); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1); PMD_DRV_LOG(DEBUG, "Before rom RX_ALARM(port1): 0x%x", tmp1); /* Swap polarity if required - Must be done only in non-1G mode */ if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) { /* Configure the 8073 to swap _P and _N of the KR lines */ PMD_DRV_LOG(DEBUG, "Swapping polarity for the 8073"); /* 10G Rx/Tx and 1G Tx signal polarity swap */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, &val); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, (val | (3 << 9))); } /* Enable CL37 BAM */ if (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. default_cfg)) & PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_BAM, &val); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_BAM, val | 1); PMD_DRV_LOG(DEBUG, "Enable CL37 BAM on KR"); } if (params->loopback_mode == ELINK_LOOPBACK_EXT) { elink_807x_force_10G(sc, phy); PMD_DRV_LOG(DEBUG, "Forced speed 10G on 807X"); return ELINK_STATUS_OK; } else { elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_BNX2X_CTRL, 0x0002); } if (phy->req_line_speed != ELINK_SPEED_AUTO_NEG) { if (phy->req_line_speed == ELINK_SPEED_10000) { val = (1 << 7); } else if (phy->req_line_speed == ELINK_SPEED_2500) { val = (1 << 5); /* Note that 2.5G works only when used with 1G * advertisement */ } else val = (1 << 5); } else { val = 0; if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) val |= (1 << 7); /* Note that 2.5G works only when used with 1G advertisement */ if (phy->speed_cap_mask & (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) val |= (1 << 5); PMD_DRV_LOG(DEBUG, "807x autoneg val = 0x%x", val); } elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1); if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) && (phy->req_line_speed == ELINK_SPEED_AUTO_NEG)) || (phy->req_line_speed == ELINK_SPEED_2500)) { uint16_t phy_ver; /* Allow 2.5G for A1 and above */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &phy_ver); PMD_DRV_LOG(DEBUG, "Add 2.5G"); if (phy_ver > 0) tmp1 |= 1; else tmp1 &= 0xfffe; } else { PMD_DRV_LOG(DEBUG, "Disable 2.5G"); tmp1 &= 0xfffe; } elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1); /* Add support for CL37 (passive mode) II */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ? 0x20 : 0x40))); /* Add support for CL37 (passive mode) III */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000); /* The SNR will improve about 2db by changing BW and FEE main * tap. Rest commands are executed after link is up * Change FFE main cursor to 5 in EDC register */ if (elink_8073_is_snr_needed(sc, phy)) elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN, 0xFB0C); /* Enable FEC (Forware Error Correction) Request in the AN */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1); tmp1 |= (1 << 15); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1); elink_ext_phy_set_pause(params, phy, vars); /* Restart autoneg */ DELAY(1000 * 500); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); PMD_DRV_LOG(DEBUG, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x", ((val & (1 << 5)) > 0), ((val & (1 << 7)) > 0)); return ELINK_STATUS_OK; } static uint8_t elink_8073_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t link_up = 0; uint16_t val1, val2; uint16_t link_status = 0; uint16_t an1000_status = 0; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1); PMD_DRV_LOG(DEBUG, "8703 LASI status 0x%x", val1); /* Clear the interrupt LASI status register */ elink_cl45_read(sc, phy, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); elink_cl45_read(sc, phy, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1); PMD_DRV_LOG(DEBUG, "807x PCS status 0x%x->0x%x", val2, val1); /* Clear MSG-OUT */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1); /* Check the LASI */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2); PMD_DRV_LOG(DEBUG, "KR 0x9003 0x%x", val2); /* Check the link status */ elink_cl45_read(sc, phy, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); PMD_DRV_LOG(DEBUG, "KR PCS status 0x%x", val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); link_up = ((val1 & 4) == 4); PMD_DRV_LOG(DEBUG, "PMA_REG_STATUS=0x%x", val1); if (link_up && ((phy->req_line_speed != ELINK_SPEED_10000))) { if (elink_8073_xaui_wa(sc, phy) != 0) return 0; } elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); /* Check the link status on 1.1.2 */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); PMD_DRV_LOG(DEBUG, "KR PMA status 0x%x->0x%x," "an_link_status=0x%x", val2, val1, an1000_status); link_up = (((val1 & 4) == 4) || (an1000_status & (1 << 1))); if (link_up && elink_8073_is_snr_needed(sc, phy)) { /* The SNR will improve about 2dbby changing the BW and FEE main * tap. The 1st write to change FFE main tap is set before * restart AN. Change PLL Bandwidth in EDC register */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH, 0x26BC); /* Change CDR Bandwidth in EDC register */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH, 0x0333); } elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status); /* Bits 0..2 --> speed detected, bits 13..15--> link is down */ if ((link_status & (1 << 2)) && (!(link_status & (1 << 15)))) { link_up = 1; vars->line_speed = ELINK_SPEED_10000; PMD_DRV_LOG(DEBUG, "port %x: External link up in 10G", params->port); } else if ((link_status & (1 << 1)) && (!(link_status & (1 << 14)))) { link_up = 1; vars->line_speed = ELINK_SPEED_2500; PMD_DRV_LOG(DEBUG, "port %x: External link up in 2.5G", params->port); } else if ((link_status & (1 << 0)) && (!(link_status & (1 << 13)))) { link_up = 1; vars->line_speed = ELINK_SPEED_1000; PMD_DRV_LOG(DEBUG, "port %x: External link up in 1G", params->port); } else { link_up = 0; PMD_DRV_LOG(DEBUG, "port %x: External link is down", params->port); } if (link_up) { /* Swap polarity if required */ if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) { /* Configure the 8073 to swap P and N of the KR lines */ elink_cl45_read(sc, phy, MDIO_XS_DEVAD, MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1); /* Set bit 3 to invert Rx in 1G mode and clear this bit * when it`s in 10G mode. */ if (vars->line_speed == ELINK_SPEED_1000) { PMD_DRV_LOG(DEBUG, "Swapping 1G polarity for" "the 8073"); val1 |= (1 << 3); } else val1 &= ~(1 << 3); elink_cl45_write(sc, phy, MDIO_XS_DEVAD, MDIO_XS_REG_8073_RX_CTRL_PCIE, val1); } elink_ext_phy_10G_an_resolve(sc, phy, vars); elink_8073_resolve_fc(phy, params, vars); vars->duplex = DUPLEX_FULL; } if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG2, &val1); if (val1 & (1 << 5)) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE; if (val1 & (1 << 7)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; } return link_up; } static void elink_8073_link_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t gpio_port; if (CHIP_IS_E2(sc)) gpio_port = SC_PATH(sc); else gpio_port = params->port; PMD_DRV_LOG(DEBUG, "Setting 8073 port %d into low power mode", gpio_port); elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_LOW, gpio_port); } /******************************************************************/ /* BNX2X8705 PHY SECTION */ /******************************************************************/ static elink_status_t elink_8705_config_init(struct elink_phy *phy, struct elink_params *params, __rte_unused struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "init 8705"); /* Restore normal power mode */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); /* HW reset */ elink_ext_phy_hw_reset(sc, params->port); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040); elink_wait_reset_complete(sc, phy, params); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100); elink_cl45_write(sc, phy, MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1); /* BNX2X8705 doesn't have microcode, hence the 0 */ elink_save_spirom_version(sc, params->port, params->shmem_base, 0); return ELINK_STATUS_OK; } static uint8_t elink_8705_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint8_t link_up = 0; uint16_t val1, rx_sd; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "read status 8705"); elink_cl45_read(sc, phy, MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); PMD_DRV_LOG(DEBUG, "8705 LASI status 0x%x", val1); elink_cl45_read(sc, phy, MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); PMD_DRV_LOG(DEBUG, "8705 LASI status 0x%x", val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xc809, &val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xc809, &val1); PMD_DRV_LOG(DEBUG, "8705 1.c809 val=0x%x", val1); link_up = ((rx_sd & 0x1) && (val1 & (1 << 9)) && ((val1 & (1 << 8)) == 0)); if (link_up) { vars->line_speed = ELINK_SPEED_10000; elink_ext_phy_resolve_fc(phy, params, vars); } return link_up; } /******************************************************************/ /* SFP+ module Section */ /******************************************************************/ static void elink_set_disable_pmd_transmit(struct elink_params *params, struct elink_phy *phy, uint8_t pmd_dis) { struct bnx2x_softc *sc = params->sc; /* Disable transmitter only for bootcodes which can enable it afterwards * (for D3 link) */ if (pmd_dis) { if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED) { PMD_DRV_LOG(DEBUG, "Disabling PMD transmitter"); } else { PMD_DRV_LOG(DEBUG, "NOT disabling PMD transmitter"); return; } } else { PMD_DRV_LOG(DEBUG, "Enabling PMD transmitter"); } elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_DISABLE, pmd_dis); } static uint8_t elink_get_gpio_port(struct elink_params *params) { uint8_t gpio_port; uint32_t swap_val, swap_override; struct bnx2x_softc *sc = params->sc; if (CHIP_IS_E2(sc)) { gpio_port = SC_PATH(sc); } else { gpio_port = params->port; } swap_val = REG_RD(sc, NIG_REG_PORT_SWAP); swap_override = REG_RD(sc, NIG_REG_STRAP_OVERRIDE); return gpio_port ^ (swap_val && swap_override); } static void elink_sfp_e1e2_set_transmitter(struct elink_params *params, struct elink_phy *phy, uint8_t tx_en) { uint16_t val; uint8_t port = params->port; struct bnx2x_softc *sc = params->sc; uint32_t tx_en_mode; /* Disable/Enable transmitter ( TX laser of the SFP+ module.) */ tx_en_mode = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].sfp_ctrl)) & PORT_HW_CFG_TX_LASER_MASK; PMD_DRV_LOG(DEBUG, "Setting transmitter tx_en=%x for port %x " "mode = %x", tx_en, port, tx_en_mode); switch (tx_en_mode) { case PORT_HW_CFG_TX_LASER_MDIO: elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val); if (tx_en) val &= ~(1 << 15); else val |= (1 << 15); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, val); break; case PORT_HW_CFG_TX_LASER_GPIO0: case PORT_HW_CFG_TX_LASER_GPIO1: case PORT_HW_CFG_TX_LASER_GPIO2: case PORT_HW_CFG_TX_LASER_GPIO3: { uint16_t gpio_pin; uint8_t gpio_port, gpio_mode; if (tx_en) gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH; else gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW; gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0; gpio_port = elink_get_gpio_port(params); elink_cb_gpio_write(sc, gpio_pin, gpio_mode, gpio_port); break; } default: PMD_DRV_LOG(DEBUG, "Invalid TX_LASER_MDIO 0x%x", tx_en_mode); break; } } static void elink_sfp_set_transmitter(struct elink_params *params, struct elink_phy *phy, uint8_t tx_en) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Setting SFP+ transmitter to %d", tx_en); if (CHIP_IS_E3(sc)) elink_sfp_e3_set_transmitter(params, phy, tx_en); else elink_sfp_e1e2_set_transmitter(params, phy, tx_en); } static elink_status_t elink_8726_read_sfp_module_eeprom(struct elink_phy *phy, struct elink_params *params, uint8_t dev_addr, uint16_t addr, uint8_t byte_cnt, uint8_t * o_buf, __rte_unused uint8_t is_init) { struct bnx2x_softc *sc = params->sc; uint16_t val = 0; uint16_t i; if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) { PMD_DRV_LOG(DEBUG, "Reading from eeprom is limited to 0xf"); return ELINK_STATUS_ERROR; } /* Set the read command byte count */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT, (byte_cnt | (dev_addr << 8))); /* Set the read command address */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR, addr); /* Activate read command */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, 0x2c0f); /* Wait up to 500us for command complete status */ for (i = 0; i < 100; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) break; DELAY(5); } if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) != MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) { PMD_DRV_LOG(DEBUG, "Got bad status 0x%x when reading from SFP+ EEPROM", (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK)); return ELINK_STATUS_ERROR; } /* Read the buffer */ for (i = 0; i < byte_cnt; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val); o_buf[i] = (uint8_t) (val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK); } for (i = 0; i < 100; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) return ELINK_STATUS_OK; DELAY(1000 * 1); } return ELINK_STATUS_ERROR; } static void elink_warpcore_power_module(struct elink_params *params, uint8_t power) { uint32_t pin_cfg; struct bnx2x_softc *sc = params->sc; pin_cfg = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. e3_sfp_ctrl)) & PORT_HW_CFG_E3_PWR_DIS_MASK) >> PORT_HW_CFG_E3_PWR_DIS_SHIFT; if (pin_cfg == PIN_CFG_NA) return; PMD_DRV_LOG(DEBUG, "Setting SFP+ module power to %d using pin cfg %d", power, pin_cfg); /* Low ==> corresponding SFP+ module is powered * high ==> the SFP+ module is powered down */ elink_set_cfg_pin(sc, pin_cfg, power ^ 1); } static elink_status_t elink_warpcore_read_sfp_module_eeprom(__rte_unused struct elink_phy *phy, struct elink_params *params, uint8_t dev_addr, uint16_t addr, uint8_t byte_cnt, uint8_t * o_buf, uint8_t is_init) { elink_status_t rc = ELINK_STATUS_OK; uint8_t i, j = 0, cnt = 0; uint32_t data_array[4]; uint16_t addr32; struct bnx2x_softc *sc = params->sc; if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) { PMD_DRV_LOG(DEBUG, "Reading from eeprom is limited to 16 bytes"); return ELINK_STATUS_ERROR; } /* 4 byte aligned address */ addr32 = addr & (~0x3); do { if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) { elink_warpcore_power_module(params, 0); /* Note that 100us are not enough here */ DELAY(1000 * 1); elink_warpcore_power_module(params, 1); } rc = elink_bsc_read(params, sc, dev_addr, addr32, 0, byte_cnt, data_array); } while ((rc != ELINK_STATUS_OK) && (++cnt < I2C_WA_RETRY_CNT)); if (rc == ELINK_STATUS_OK) { for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) { o_buf[j] = *((uint8_t *) data_array + i); j++; } } return rc; } static elink_status_t elink_8727_read_sfp_module_eeprom(struct elink_phy *phy, struct elink_params *params, uint8_t dev_addr, uint16_t addr, uint8_t byte_cnt, uint8_t * o_buf, __rte_unused uint8_t is_init) { struct bnx2x_softc *sc = params->sc; uint16_t val, i; if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) { PMD_DRV_LOG(DEBUG, "Reading from eeprom is limited to 0xf"); return ELINK_STATUS_ERROR; } /* Set 2-wire transfer rate of SFP+ module EEPROM * to 100Khz since some DACs(direct attached cables) do * not work at 400Khz. */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR, ((dev_addr << 8) | 1)); /* Need to read from 1.8000 to clear it */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); /* Set the read command byte count */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT, ((byte_cnt < 2) ? 2 : byte_cnt)); /* Set the read command address */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR, addr); /* Set the destination address */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, 0x8004, MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF); /* Activate read command */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, 0x8002); /* Wait appropriate time for two-wire command to finish before * polling the status register */ DELAY(1000 * 1); /* Wait up to 500us for command complete status */ for (i = 0; i < 100; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) break; DELAY(5); } if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) != MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) { PMD_DRV_LOG(DEBUG, "Got bad status 0x%x when reading from SFP+ EEPROM", (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK)); return ELINK_STATUS_TIMEOUT; } /* Read the buffer */ for (i = 0; i < byte_cnt; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val); o_buf[i] = (uint8_t) (val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK); } for (i = 0; i < 100; i++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) return ELINK_STATUS_OK; DELAY(1000 * 1); } return ELINK_STATUS_ERROR; } static elink_status_t elink_read_sfp_module_eeprom(struct elink_phy *phy, struct elink_params *params, uint8_t dev_addr, uint16_t addr, uint16_t byte_cnt, uint8_t * o_buf) { elink_status_t rc = 0; uint8_t xfer_size; uint8_t *user_data = o_buf; read_sfp_module_eeprom_func_p read_func; if ((dev_addr != 0xa0) && (dev_addr != 0xa2)) { PMD_DRV_LOG(DEBUG, "invalid dev_addr 0x%x", dev_addr); return ELINK_STATUS_ERROR; } switch (phy->type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726: read_func = elink_8726_read_sfp_module_eeprom; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722: read_func = elink_8727_read_sfp_module_eeprom; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: read_func = elink_warpcore_read_sfp_module_eeprom; break; default: return ELINK_OP_NOT_SUPPORTED; } while (!rc && (byte_cnt > 0)) { xfer_size = (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) ? ELINK_SFP_EEPROM_PAGE_SIZE : byte_cnt; rc = read_func(phy, params, dev_addr, addr, xfer_size, user_data, 0); byte_cnt -= xfer_size; user_data += xfer_size; addr += xfer_size; } return rc; } static elink_status_t elink_get_edc_mode(struct elink_phy *phy, struct elink_params *params, uint16_t * edc_mode) { struct bnx2x_softc *sc = params->sc; uint32_t sync_offset = 0, phy_idx, media_types; uint8_t gport, val[2], check_limiting_mode = 0; *edc_mode = ELINK_EDC_MODE_LIMITING; phy->media_type = ELINK_ETH_PHY_UNSPECIFIED; /* First check for copper cable */ if (elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, ELINK_SFP_EEPROM_CON_TYPE_ADDR, 2, (uint8_t *) val) != 0) { PMD_DRV_LOG(DEBUG, "Failed to read from SFP+ module EEPROM"); return ELINK_STATUS_ERROR; } switch (val[0]) { case ELINK_SFP_EEPROM_CON_TYPE_VAL_COPPER: { uint8_t copper_module_type; phy->media_type = ELINK_ETH_PHY_DA_TWINAX; /* Check if its active cable (includes SFP+ module) * of passive cable */ if (elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, ELINK_SFP_EEPROM_FC_TX_TECH_ADDR, 1, &copper_module_type) != 0) { PMD_DRV_LOG(DEBUG, "Failed to read copper-cable-type" " from SFP+ EEPROM"); return ELINK_STATUS_ERROR; } if (copper_module_type & ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) { PMD_DRV_LOG(DEBUG, "Active Copper cable detected"); if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) *edc_mode = ELINK_EDC_MODE_ACTIVE_DAC; else check_limiting_mode = 1; } else if (copper_module_type & ELINK_SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) { PMD_DRV_LOG(DEBUG, "Passive Copper cable detected"); *edc_mode = ELINK_EDC_MODE_PASSIVE_DAC; } else { PMD_DRV_LOG(DEBUG, "Unknown copper-cable-type 0x%x !!!", copper_module_type); return ELINK_STATUS_ERROR; } break; } case ELINK_SFP_EEPROM_CON_TYPE_VAL_LC: case ELINK_SFP_EEPROM_CON_TYPE_VAL_RJ45: check_limiting_mode = 1; if ((val[1] & (ELINK_SFP_EEPROM_COMP_CODE_SR_MASK | ELINK_SFP_EEPROM_COMP_CODE_LR_MASK | ELINK_SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) { PMD_DRV_LOG(DEBUG, "1G SFP module detected"); gport = params->port; phy->media_type = ELINK_ETH_PHY_SFP_1G_FIBER; if (phy->req_line_speed != ELINK_SPEED_1000) { phy->req_line_speed = ELINK_SPEED_1000; if (!CHIP_IS_E1x(sc)) { gport = SC_PATH(sc) + (params->port << 1); } elink_cb_event_log(sc, ELINK_LOG_ID_NON_10G_MODULE, gport); //"Warning: Link speed was forced to 1000Mbps." // " Current SFP module in port %d is not" // " compliant with 10G Ethernet", } } else { int idx, cfg_idx = 0; PMD_DRV_LOG(DEBUG, "10G Optic module detected"); for (idx = ELINK_INT_PHY; idx < ELINK_MAX_PHYS; idx++) { if (params->phy[idx].type == phy->type) { cfg_idx = ELINK_LINK_CONFIG_IDX(idx); break; } } phy->media_type = ELINK_ETH_PHY_SFPP_10G_FIBER; phy->req_line_speed = params->req_line_speed[cfg_idx]; } break; default: PMD_DRV_LOG(DEBUG, "Unable to determine module type 0x%x !!!", val[0]); return ELINK_STATUS_ERROR; } sync_offset = params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port].media_type); media_types = REG_RD(sc, sync_offset); /* Update media type for non-PMF sync */ for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) { if (&(params->phy[phy_idx]) == phy) { media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK << (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx)); media_types |= ((phy-> media_type & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) << (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx)); break; } } REG_WR(sc, sync_offset, media_types); if (check_limiting_mode) { uint8_t options[ELINK_SFP_EEPROM_OPTIONS_SIZE]; if (elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, ELINK_SFP_EEPROM_OPTIONS_ADDR, ELINK_SFP_EEPROM_OPTIONS_SIZE, options) != 0) { PMD_DRV_LOG(DEBUG, "Failed to read Option field from module EEPROM"); return ELINK_STATUS_ERROR; } if ((options[0] & ELINK_SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK)) *edc_mode = ELINK_EDC_MODE_LINEAR; else *edc_mode = ELINK_EDC_MODE_LIMITING; } PMD_DRV_LOG(DEBUG, "EDC mode is set to 0x%x", *edc_mode); return ELINK_STATUS_OK; } /* This function read the relevant field from the module (SFP+), and verify it * is compliant with this board */ static elink_status_t elink_verify_sfp_module(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint32_t val, cmd; uint32_t fw_resp, fw_cmd_param; char vendor_name[ELINK_SFP_EEPROM_VENDOR_NAME_SIZE + 1]; char vendor_pn[ELINK_SFP_EEPROM_PART_NO_SIZE + 1]; phy->flags &= ~ELINK_FLAGS_SFP_NOT_APPROVED; val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config[params->port]. config)); if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) { PMD_DRV_LOG(DEBUG, "NOT enforcing module verification"); return ELINK_STATUS_OK; } if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) { /* Use specific phy request */ cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL; } else if (params->feature_config_flags & ELINK_FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) { /* Use first phy request only in case of non-dual media */ if (ELINK_DUAL_MEDIA(params)) { PMD_DRV_LOG(DEBUG, "FW does not support OPT MDL verification"); return ELINK_STATUS_ERROR; } cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL; } else { /* No support in OPT MDL detection */ PMD_DRV_LOG(DEBUG, "FW does not support OPT MDL verification"); return ELINK_STATUS_ERROR; } fw_cmd_param = ELINK_FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl); fw_resp = elink_cb_fw_command(sc, cmd, fw_cmd_param); if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) { PMD_DRV_LOG(DEBUG, "Approved module"); return ELINK_STATUS_OK; } /* Format the warning message */ if (elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, ELINK_SFP_EEPROM_VENDOR_NAME_ADDR, ELINK_SFP_EEPROM_VENDOR_NAME_SIZE, (uint8_t *) vendor_name)) vendor_name[0] = '\0'; else vendor_name[ELINK_SFP_EEPROM_VENDOR_NAME_SIZE] = '\0'; if (elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, ELINK_SFP_EEPROM_PART_NO_ADDR, ELINK_SFP_EEPROM_PART_NO_SIZE, (uint8_t *) vendor_pn)) vendor_pn[0] = '\0'; else vendor_pn[ELINK_SFP_EEPROM_PART_NO_SIZE] = '\0'; elink_cb_event_log(sc, ELINK_LOG_ID_UNQUAL_IO_MODULE, params->port, vendor_name, vendor_pn); // "Warning: Unqualified SFP+ module detected," // " Port %d from %s part number %s", if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG) phy->flags |= ELINK_FLAGS_SFP_NOT_APPROVED; return ELINK_STATUS_ERROR; } static elink_status_t elink_wait_for_sfp_module_initialized(struct elink_phy *phy, struct elink_params *params) { uint8_t val; elink_status_t rc; uint16_t timeout; /* Initialization time after hot-plug may take up to 300ms for * some phys type ( e.g. JDSU ) */ for (timeout = 0; timeout < 60; timeout++) { if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) rc = elink_warpcore_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, 1, 1, &val, 1); else rc = elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, 1, 1, &val); if (rc == 0) { PMD_DRV_LOG(DEBUG, "SFP+ module initialization took %d ms", timeout * 5); return ELINK_STATUS_OK; } DELAY(1000 * 5); } rc = elink_read_sfp_module_eeprom(phy, params, ELINK_I2C_DEV_ADDR_A0, 1, 1, &val); return rc; } static void elink_8727_power_module(struct bnx2x_softc *sc, struct elink_phy *phy, uint8_t is_power_up) { /* Make sure GPIOs are not using for LED mode */ uint16_t val; /* In the GPIO register, bit 4 is use to determine if the GPIOs are * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for * output * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0 * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1 * where the 1st bit is the over-current(only input), and 2nd bit is * for power( only output ) * * In case of NOC feature is disabled and power is up, set GPIO control * as input to enable listening of over-current indication */ if (phy->flags & ELINK_FLAGS_NOC) return; if (is_power_up) val = (1 << 4); else /* Set GPIO control to OUTPUT, and set the power bit * to according to the is_power_up */ val = (1 << 1); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL, val); } static elink_status_t elink_8726_set_limiting_mode(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t edc_mode) { uint16_t cur_limiting_mode; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &cur_limiting_mode); PMD_DRV_LOG(DEBUG, "Current Limiting mode is 0x%x", cur_limiting_mode); if (edc_mode == ELINK_EDC_MODE_LIMITING) { PMD_DRV_LOG(DEBUG, "Setting LIMITING MODE"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, ELINK_EDC_MODE_LIMITING); } else { /* LRM mode ( default ) */ PMD_DRV_LOG(DEBUG, "Setting LRM MODE"); /* Changing to LRM mode takes quite few seconds. So do it only * if current mode is limiting (default is LRM) */ if (cur_limiting_mode != ELINK_EDC_MODE_LIMITING) return ELINK_STATUS_OK; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LRM_MODE, 0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, 0x128); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL0, 0x4008); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LRM_MODE, 0xaaaa); } return ELINK_STATUS_OK; } static elink_status_t elink_8727_set_limiting_mode(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t edc_mode) { uint16_t phy_identifier; uint16_t rom_ver2_val; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &phy_identifier); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, (phy_identifier & ~(1 << 9))); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, &rom_ver2_val); /* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER2, (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff)); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, (phy_identifier | (1 << 9))); return ELINK_STATUS_OK; } static void elink_8727_specific_func(struct elink_phy *phy, struct elink_params *params, uint32_t action) { struct bnx2x_softc *sc = params->sc; uint16_t val; switch (action) { case ELINK_DISABLE_TX: elink_sfp_set_transmitter(params, phy, 0); break; case ELINK_ENABLE_TX: if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED)) elink_sfp_set_transmitter(params, phy, 1); break; case ELINK_PHY_INIT: elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1 << 2) | (1 << 5)); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL, 0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0006); /* Make MOD_ABS give interrupt on change */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, &val); val |= (1 << 12); if (phy->flags & ELINK_FLAGS_NOC) val |= (3 << 5); /* Set 8727 GPIOs to input to allow reading from the 8727 GPIO0 * status which reflect SFP+ module over-current */ if (!(phy->flags & ELINK_FLAGS_NOC)) val &= 0xff8f; /* Reset bits 4-6 */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val); break; default: PMD_DRV_LOG(DEBUG, "Function 0x%x not supported by 8727", action); return; } } static void elink_set_e1e2_module_fault_led(struct elink_params *params, uint8_t gpio_mode) { struct bnx2x_softc *sc = params->sc; uint32_t fault_led_gpio = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info. port_hw_config[params->port]. sfp_ctrl)) & PORT_HW_CFG_FAULT_MODULE_LED_MASK; switch (fault_led_gpio) { case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED: return; case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0: case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1: case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2: case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3: { uint8_t gpio_port = elink_get_gpio_port(params); uint16_t gpio_pin = fault_led_gpio - PORT_HW_CFG_FAULT_MODULE_LED_GPIO0; PMD_DRV_LOG(DEBUG, "Set fault module-detected led " "pin %x port %x mode %x", gpio_pin, gpio_port, gpio_mode); elink_cb_gpio_write(sc, gpio_pin, gpio_mode, gpio_port); } break; default: PMD_DRV_LOG(DEBUG, "Error: Invalid fault led mode 0x%x", fault_led_gpio); } } static void elink_set_e3_module_fault_led(struct elink_params *params, uint8_t gpio_mode) { uint32_t pin_cfg; uint8_t port = params->port; struct bnx2x_softc *sc = params->sc; pin_cfg = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].e3_sfp_ctrl)) & PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >> PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT; PMD_DRV_LOG(DEBUG, "Setting Fault LED to %d using pin cfg %d", gpio_mode, pin_cfg); elink_set_cfg_pin(sc, pin_cfg, gpio_mode); } static void elink_set_sfp_module_fault_led(struct elink_params *params, uint8_t gpio_mode) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Setting SFP+ module fault LED to %d", gpio_mode); if (CHIP_IS_E3(sc)) { /* Low ==> if SFP+ module is supported otherwise * High ==> if SFP+ module is not on the approved vendor list */ elink_set_e3_module_fault_led(params, gpio_mode); } else elink_set_e1e2_module_fault_led(params, gpio_mode); } static void elink_warpcore_hw_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; elink_warpcore_power_module(params, 0); /* Put Warpcore in low power mode */ REG_WR(sc, MISC_REG_WC0_RESET, 0x0c0e); /* Put LCPLL in low power mode */ REG_WR(sc, MISC_REG_LCPLL_E40_PWRDWN, 1); REG_WR(sc, MISC_REG_LCPLL_E40_RESETB_ANA, 0); REG_WR(sc, MISC_REG_LCPLL_E40_RESETB_DIG, 0); } static void elink_power_sfp_module(struct elink_params *params, struct elink_phy *phy, uint8_t power) { PMD_DRV_LOG(DEBUG, "Setting SFP+ power to %x", power); switch (phy->type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722: elink_8727_power_module(params->sc, phy, power); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: elink_warpcore_power_module(params, power); break; default: break; } } static void elink_warpcore_set_limiting_mode(struct elink_params *params, struct elink_phy *phy, uint16_t edc_mode) { uint16_t val = 0; uint16_t mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT; struct bnx2x_softc *sc = params->sc; uint8_t lane = elink_get_warpcore_lane(params); /* This is a global register which controls all lanes */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val); val &= ~(0xf << (lane << 2)); switch (edc_mode) { case ELINK_EDC_MODE_LINEAR: case ELINK_EDC_MODE_LIMITING: mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT; break; case ELINK_EDC_MODE_PASSIVE_DAC: case ELINK_EDC_MODE_ACTIVE_DAC: mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC; break; default: break; } val |= (mode << (lane << 2)); elink_cl45_write(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val); /* A must read */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val); /* Restart microcode to re-read the new mode */ elink_warpcore_reset_lane(sc, phy, 1); elink_warpcore_reset_lane(sc, phy, 0); } static void elink_set_limiting_mode(struct elink_params *params, struct elink_phy *phy, uint16_t edc_mode) { switch (phy->type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726: elink_8726_set_limiting_mode(params->sc, phy, edc_mode); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722: elink_8727_set_limiting_mode(params->sc, phy, edc_mode); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: elink_warpcore_set_limiting_mode(params, phy, edc_mode); break; } } static elink_status_t elink_sfp_module_detection(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t edc_mode; elink_status_t rc = ELINK_STATUS_OK; uint32_t val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config[params-> port]. config)); /* Enabled transmitter by default */ elink_sfp_set_transmitter(params, phy, 1); PMD_DRV_LOG(DEBUG, "SFP+ module plugged in/out detected on port %d", params->port); /* Power up module */ elink_power_sfp_module(params, phy, 1); if (elink_get_edc_mode(phy, params, &edc_mode) != 0) { PMD_DRV_LOG(DEBUG, "Failed to get valid module type"); return ELINK_STATUS_ERROR; } else if (elink_verify_sfp_module(phy, params) != 0) { /* Check SFP+ module compatibility */ PMD_DRV_LOG(DEBUG, "Module verification failed!!"); rc = ELINK_STATUS_ERROR; /* Turn on fault module-detected led */ elink_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH); /* Check if need to power down the SFP+ module */ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) { PMD_DRV_LOG(DEBUG, "Shutdown SFP+ module!!"); elink_power_sfp_module(params, phy, 0); return rc; } } else { /* Turn off fault module-detected led */ elink_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW); } /* Check and set limiting mode / LRM mode on 8726. On 8727 it * is done automatically */ elink_set_limiting_mode(params, phy, edc_mode); /* Disable transmit for this module if the module is not approved, and * laser needs to be disabled. */ if ((rc != 0) && ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)) elink_sfp_set_transmitter(params, phy, 0); return rc; } void elink_handle_module_detect_int(struct elink_params *params) { struct bnx2x_softc *sc = params->sc; struct elink_phy *phy; uint32_t gpio_val; uint8_t gpio_num, gpio_port; if (CHIP_IS_E3(sc)) { phy = ¶ms->phy[ELINK_INT_PHY]; /* Always enable TX laser,will be disabled in case of fault */ elink_sfp_set_transmitter(params, phy, 1); } else { phy = ¶ms->phy[ELINK_EXT_PHY1]; } if (elink_get_mod_abs_int_cfg(sc, params->shmem_base, params->port, &gpio_num, &gpio_port) == ELINK_STATUS_ERROR) { PMD_DRV_LOG(DEBUG, "Failed to get MOD_ABS interrupt config"); return; } /* Set valid module led off */ elink_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH); /* Get current gpio val reflecting module plugged in / out */ gpio_val = elink_cb_gpio_read(sc, gpio_num, gpio_port); /* Call the handling function in case module is detected */ if (gpio_val == 0) { elink_set_mdio_emac_per_phy(sc, params); elink_set_aer_mmd(params, phy); elink_power_sfp_module(params, phy, 1); elink_cb_gpio_int_write(sc, gpio_num, MISC_REGISTERS_GPIO_INT_OUTPUT_CLR, gpio_port); if (elink_wait_for_sfp_module_initialized(phy, params) == 0) { elink_sfp_module_detection(phy, params); if (CHIP_IS_E3(sc)) { uint16_t rx_tx_in_reset; /* In case WC is out of reset, reconfigure the * link speed while taking into account 1G * module limitation. */ elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC6, &rx_tx_in_reset); if ((!rx_tx_in_reset) && (params->link_flags & ELINK_PHY_INITIALIZED)) { elink_warpcore_reset_lane(sc, phy, 1); elink_warpcore_config_sfi(phy, params); elink_warpcore_reset_lane(sc, phy, 0); } } } else { PMD_DRV_LOG(DEBUG, "SFP+ module is not initialized"); } } else { elink_cb_gpio_int_write(sc, gpio_num, MISC_REGISTERS_GPIO_INT_OUTPUT_SET, gpio_port); /* Module was plugged out. * Disable transmit for this module */ phy->media_type = ELINK_ETH_PHY_NOT_PRESENT; } } /******************************************************************/ /* Used by 8706 and 8727 */ /******************************************************************/ static void elink_sfp_mask_fault(struct bnx2x_softc *sc, struct elink_phy *phy, uint16_t alarm_status_offset, uint16_t alarm_ctrl_offset) { uint16_t alarm_status, val; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, alarm_status_offset, &alarm_status); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, alarm_status_offset, &alarm_status); /* Mask or enable the fault event. */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val); if (alarm_status & (1 << 0)) val &= ~(1 << 0); else val |= (1 << 0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val); } /******************************************************************/ /* common BNX2X8706/BNX2X8726 PHY SECTION */ /******************************************************************/ static uint8_t elink_8706_8726_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint8_t link_up = 0; uint16_t val1, val2, rx_sd, pcs_status; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "XGXS 8706/8726"); /* Clear RX Alarm */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2); elink_sfp_mask_fault(sc, phy, MDIO_PMA_LASI_TXSTAT, MDIO_PMA_LASI_TXCTRL); /* Clear LASI indication */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2); PMD_DRV_LOG(DEBUG, "8706/8726 LASI status 0x%x--> 0x%x", val1, val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); elink_cl45_read(sc, phy, MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); PMD_DRV_LOG(DEBUG, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps" " link_status 0x%x", rx_sd, pcs_status, val2); /* Link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status * are set, or if the autoneg bit 1 is set */ link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1 << 1))); if (link_up) { if (val2 & (1 << 1)) vars->line_speed = ELINK_SPEED_1000; else vars->line_speed = ELINK_SPEED_10000; elink_ext_phy_resolve_fc(phy, params, vars); vars->duplex = DUPLEX_FULL; } /* Capture 10G link fault. Read twice to clear stale value. */ if (vars->line_speed == ELINK_SPEED_10000) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXSTAT, &val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXSTAT, &val1); if (val1 & (1 << 0)) vars->fault_detected = 1; } return link_up; } /******************************************************************/ /* BNX2X8706 PHY SECTION */ /******************************************************************/ static uint8_t elink_8706_config_init(struct elink_phy *phy, struct elink_params *params, __rte_unused struct elink_vars *vars) { uint32_t tx_en_mode; uint16_t cnt, val, tmp1; struct bnx2x_softc *sc = params->sc; elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); /* HW reset */ elink_ext_phy_hw_reset(sc, params->port); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040); elink_wait_reset_complete(sc, phy, params); /* Wait until fw is loaded */ for (cnt = 0; cnt < 100; cnt++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val); if (val) break; DELAY(1000 * 10); } PMD_DRV_LOG(DEBUG, "XGXS 8706 is initialized after %d ms", cnt); if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) { uint8_t i; uint16_t reg; for (i = 0; i < 4; i++) { reg = MDIO_XS_8706_REG_BANK_RX0 + i * (MDIO_XS_8706_REG_BANK_RX1 - MDIO_XS_8706_REG_BANK_RX0); elink_cl45_read(sc, phy, MDIO_XS_DEVAD, reg, &val); /* Clear first 3 bits of the control */ val &= ~0x7; /* Set control bits according to configuration */ val |= (phy->rx_preemphasis[i] & 0x7); PMD_DRV_LOG(DEBUG, "Setting RX Equalizer to BNX2X8706" " reg 0x%x <-- val 0x%x", reg, val); elink_cl45_write(sc, phy, MDIO_XS_DEVAD, reg, val); } } /* Force speed */ if (phy->req_line_speed == ELINK_SPEED_10000) { PMD_DRV_LOG(DEBUG, "XGXS 8706 force 10Gbps"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, 0x400); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL, 0); /* Arm LASI for link and Tx fault. */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3); } else { /* Force 1Gbps using autoneg with 1G advertisement */ /* Allow CL37 through CL73 */ PMD_DRV_LOG(DEBUG, "XGXS 8706 AutoNeg"); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c); /* Enable Full-Duplex advertisement on CL37 */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020); /* Enable CL37 AN */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000); /* 1G support */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1 << 5)); /* Enable clause 73 AN */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, 0x0400); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x0004); } elink_save_bnx2x_spirom_ver(sc, phy, params->port); /* If TX Laser is controlled by GPIO_0, do not let PHY go into low * power mode, if TX Laser is disabled */ tx_en_mode = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. sfp_ctrl)) & PORT_HW_CFG_TX_LASER_MASK; if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) { PMD_DRV_LOG(DEBUG, "Enabling TXONOFF_PWRDN_DIS"); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1); tmp1 |= 0x1; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1); } return ELINK_STATUS_OK; } static elink_status_t elink_8706_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { return elink_8706_8726_read_status(phy, params, vars); } /******************************************************************/ /* BNX2X8726 PHY SECTION */ /******************************************************************/ static void elink_8726_config_loopback(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "PMA/PMD ext_phy_loopback: 8726"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001); } static void elink_8726_external_rom_boot(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; /* Need to wait 100ms after reset */ DELAY(1000 * 100); /* Micro controller re-boot */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B); /* Set soft reset */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL1, 0x0001); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); /* Wait for 150ms for microcode load */ DELAY(1000 * 150); /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL1, 0x0000); DELAY(1000 * 200); elink_save_bnx2x_spirom_ver(sc, phy, params->port); } static uint8_t elink_8726_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t val1; uint8_t link_up = elink_8706_8726_read_status(phy, params, vars); if (link_up) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); if (val1 & (1 << 15)) { PMD_DRV_LOG(DEBUG, "Tx is disabled"); link_up = 0; vars->line_speed = 0; } } return link_up; } static elink_status_t elink_8726_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Initializing BNX2X8726"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1 << 15); elink_wait_reset_complete(sc, phy, params); elink_8726_external_rom_boot(phy, params); /* Need to call module detected on initialization since the module * detection triggered by actual module insertion might occur before * driver is loaded, and when driver is loaded, it reset all * registers, including the transmitter */ elink_sfp_module_detection(phy, params); if (phy->req_line_speed == ELINK_SPEED_1000) { PMD_DRV_LOG(DEBUG, "Setting 1G force"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, 0x400); } else if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) && ((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) != PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { PMD_DRV_LOG(DEBUG, "Setting 1G clause37"); /* Set Flow control */ elink_ext_phy_set_pause(params, phy, vars); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); /* Enable RX-ALARM control to receive interrupt for 1G speed * change */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, 0x400); } else { /* Default 10G. Set only LASI control */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1); } /* Set TX PreEmphasis if needed */ if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) { PMD_DRV_LOG(DEBUG, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x", phy->tx_preemphasis[0], phy->tx_preemphasis[1]); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8726_TX_CTRL1, phy->tx_preemphasis[0]); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8726_TX_CTRL2, phy->tx_preemphasis[1]); } return ELINK_STATUS_OK; } static void elink_8726_link_reset(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "elink_8726_link_reset port %d", params->port); /* Set serial boot control for external load */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001); } /******************************************************************/ /* BNX2X8727 PHY SECTION */ /******************************************************************/ static void elink_8727_set_link_led(struct elink_phy *phy, struct elink_params *params, uint8_t mode) { struct bnx2x_softc *sc = params->sc; uint16_t led_mode_bitmask = 0; uint16_t gpio_pins_bitmask = 0; uint16_t val; /* Only NOC flavor requires to set the LED specifically */ if (!(phy->flags & ELINK_FLAGS_NOC)) return; switch (mode) { case ELINK_LED_MODE_FRONT_PANEL_OFF: case ELINK_LED_MODE_OFF: led_mode_bitmask = 0; gpio_pins_bitmask = 0x03; break; case ELINK_LED_MODE_ON: led_mode_bitmask = 0; gpio_pins_bitmask = 0x02; break; case ELINK_LED_MODE_OPER: led_mode_bitmask = 0x60; gpio_pins_bitmask = 0x11; break; } elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, &val); val &= 0xff8f; val |= led_mode_bitmask; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL, &val); val &= 0xffe0; val |= gpio_pins_bitmask; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL, val); } static void elink_8727_hw_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { uint32_t swap_val, swap_override; uint8_t port; /* The PHY reset is controlled by GPIO 1. Fake the port number * to cancel the swap done in set_gpio() */ struct bnx2x_softc *sc = params->sc; swap_val = REG_RD(sc, NIG_REG_PORT_SWAP); swap_override = REG_RD(sc, NIG_REG_STRAP_OVERRIDE); port = (swap_val && swap_override) ^ 1; elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); } static void elink_8727_config_speed(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t tmp1, val; /* Set option 1G speed */ if ((phy->req_line_speed == ELINK_SPEED_1000) || (phy->media_type == ELINK_ETH_PHY_SFP_1G_FIBER)) { PMD_DRV_LOG(DEBUG, "Setting 1G force"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1); PMD_DRV_LOG(DEBUG, "1.7 = 0x%x", tmp1); /* Power down the XAUI until link is up in case of dual-media * and 1G */ if (ELINK_DUAL_MEDIA(params)) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_GP, &val); val |= (3 << 10); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_GP, val); } } else if ((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && ((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) && ((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) != PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { PMD_DRV_LOG(DEBUG, "Setting 1G clause37"); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300); } else { /* Since the 8727 has only single reset pin, need to set the 10G * registers although it is default */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0x0020); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x0008); } } static elink_status_t elink_8727_config_init(struct elink_phy *phy, struct elink_params *params, __rte_unused struct elink_vars *vars) { uint32_t tx_en_mode; uint16_t tmp1, mod_abs, tmp2; struct bnx2x_softc *sc = params->sc; /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ elink_wait_reset_complete(sc, phy, params); PMD_DRV_LOG(DEBUG, "Initializing BNX2X8727"); elink_8727_specific_func(phy, params, ELINK_PHY_INIT); /* Initially configure MOD_ABS to interrupt when module is * presence( bit 8) */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs); /* Set EDC off by setting OPTXLOS signal input to low (bit 9). * When the EDC is off it locks onto a reference clock and avoids * becoming 'lost' */ mod_abs &= ~(1 << 8); if (!(phy->flags & ELINK_FLAGS_NOC)) mod_abs &= ~(1 << 9); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs); /* Enable/Disable PHY transmitter output */ elink_set_disable_pmd_transmit(params, phy, 0); elink_8727_power_module(sc, phy, 1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1); elink_8727_config_speed(phy, params); /* Set TX PreEmphasis if needed */ if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) { PMD_DRV_LOG(DEBUG, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x", phy->tx_preemphasis[0], phy->tx_preemphasis[1]); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1, phy->tx_preemphasis[0]); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2, phy->tx_preemphasis[1]); } /* If TX Laser is controlled by GPIO_0, do not let PHY go into low * power mode, if TX Laser is disabled */ tx_en_mode = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. sfp_ctrl)) & PORT_HW_CFG_TX_LASER_MASK; if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) { PMD_DRV_LOG(DEBUG, "Enabling TXONOFF_PWRDN_DIS"); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2); tmp2 |= 0x1000; tmp2 &= 0xFFEF; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &tmp2); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, (tmp2 & 0x7fff)); } return ELINK_STATUS_OK; } static void elink_8727_handle_mod_abs(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t mod_abs, rx_alarm_status; uint32_t val = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config[params-> port].config)); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs); if (mod_abs & (1 << 8)) { /* Module is absent */ PMD_DRV_LOG(DEBUG, "MOD_ABS indication show module is absent"); phy->media_type = ELINK_ETH_PHY_NOT_PRESENT; /* 1. Set mod_abs to detect next module * presence event * 2. Set EDC off by setting OPTXLOS signal input to low * (bit 9). * When the EDC is off it locks onto a reference clock and * avoids becoming 'lost'. */ mod_abs &= ~(1 << 8); if (!(phy->flags & ELINK_FLAGS_NOC)) mod_abs &= ~(1 << 9); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs); /* Clear RX alarm since it stays up as long as * the mod_abs wasn't changed */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &rx_alarm_status); } else { /* Module is present */ PMD_DRV_LOG(DEBUG, "MOD_ABS indication show module is present"); /* First disable transmitter, and if the module is ok, the * module_detection will enable it * 1. Set mod_abs to detect next module absent event ( bit 8) * 2. Restore the default polarity of the OPRXLOS signal and * this signal will then correctly indicate the presence or * absence of the Rx signal. (bit 9) */ mod_abs |= (1 << 8); if (!(phy->flags & ELINK_FLAGS_NOC)) mod_abs |= (1 << 9); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs); /* Clear RX alarm since it stays up as long as the mod_abs * wasn't changed. This is need to be done before calling the * module detection, otherwise it will clear* the link update * alarm */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &rx_alarm_status); if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) elink_sfp_set_transmitter(params, phy, 0); if (elink_wait_for_sfp_module_initialized(phy, params) == 0) { elink_sfp_module_detection(phy, params); } else { PMD_DRV_LOG(DEBUG, "SFP+ module is not initialized"); } /* Reconfigure link speed based on module type limitations */ elink_8727_config_speed(phy, params); } PMD_DRV_LOG(DEBUG, "8727 RX_ALARM_STATUS 0x%x", rx_alarm_status); /* No need to check link status in case of module plugged in/out */ } static uint8_t elink_8727_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t link_up = 0, oc_port = params->port; uint16_t link_status = 0; uint16_t rx_alarm_status, lasi_ctrl, val1; /* If PHY is not initialized, do not check link status */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, &lasi_ctrl); if (!lasi_ctrl) return 0; /* Check the LASI on Rx */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &rx_alarm_status); vars->line_speed = 0; PMD_DRV_LOG(DEBUG, "8727 RX_ALARM_STATUS 0x%x", rx_alarm_status); elink_sfp_mask_fault(sc, phy, MDIO_PMA_LASI_TXSTAT, MDIO_PMA_LASI_TXCTRL); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1); PMD_DRV_LOG(DEBUG, "8727 LASI status 0x%x", val1); /* Clear MSG-OUT */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1); /* If a module is present and there is need to check * for over current */ if (!(phy->flags & ELINK_FLAGS_NOC) && !(rx_alarm_status & (1 << 5))) { /* Check over-current using 8727 GPIO0 input */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL, &val1); if ((val1 & (1 << 8)) == 0) { if (!CHIP_IS_E1x(sc)) oc_port = SC_PATH(sc) + (params->port << 1); PMD_DRV_LOG(DEBUG, "8727 Power fault has been detected on port %d", oc_port); elink_cb_event_log(sc, ELINK_LOG_ID_OVER_CURRENT, oc_port); //"Error: Power fault on Port %d has " // "been detected and the power to " // "that SFP+ module has been removed " // "to prevent failure of the card. " // "Please remove the SFP+ module and " // "restart the system to clear this " // "error.", /* Disable all RX_ALARMs except for mod_abs */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1 << 5)); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1); /* Wait for module_absent_event */ val1 |= (1 << 8); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, val1); /* Clear RX alarm */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &rx_alarm_status); elink_8727_power_module(params->sc, phy, 0); return 0; } } /* Over current check */ /* When module absent bit is set, check module */ if (rx_alarm_status & (1 << 5)) { elink_8727_handle_mod_abs(phy, params); /* Enable all mod_abs and link detection bits */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, ((1 << 5) | (1 << 2))); } if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED)) { PMD_DRV_LOG(DEBUG, "Enabling 8727 TX laser"); elink_sfp_set_transmitter(params, phy, 1); } else { PMD_DRV_LOG(DEBUG, "Tx is disabled"); return 0; } elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status); /* Bits 0..2 --> speed detected, * Bits 13..15--> link is down */ if ((link_status & (1 << 2)) && (!(link_status & (1 << 15)))) { link_up = 1; vars->line_speed = ELINK_SPEED_10000; PMD_DRV_LOG(DEBUG, "port %x: External link up in 10G", params->port); } else if ((link_status & (1 << 0)) && (!(link_status & (1 << 13)))) { link_up = 1; vars->line_speed = ELINK_SPEED_1000; PMD_DRV_LOG(DEBUG, "port %x: External link up in 1G", params->port); } else { link_up = 0; PMD_DRV_LOG(DEBUG, "port %x: External link is down", params->port); } /* Capture 10G link fault. */ if (vars->line_speed == ELINK_SPEED_10000) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXSTAT, &val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXSTAT, &val1); if (val1 & (1 << 0)) { vars->fault_detected = 1; } } if (link_up) { elink_ext_phy_resolve_fc(phy, params, vars); vars->duplex = DUPLEX_FULL; PMD_DRV_LOG(DEBUG, "duplex = 0x%x", vars->duplex); } if ((ELINK_DUAL_MEDIA(params)) && (phy->req_line_speed == ELINK_SPEED_1000)) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_GP, &val1); /* In case of dual-media board and 1G, power up the XAUI side, * otherwise power it down. For 10G it is done automatically */ if (link_up) val1 &= ~(3 << 10); else val1 |= (3 << 10); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_GP, val1); } return link_up; } static void elink_8727_link_reset(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; /* Enable/Disable PHY transmitter output */ elink_set_disable_pmd_transmit(params, phy, 1); /* Disable Transmitter */ elink_sfp_set_transmitter(params, phy, 0); /* Clear LASI */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0); } /******************************************************************/ /* BNX2X8481/BNX2X84823/BNX2X84833 PHY SECTION */ /******************************************************************/ static void elink_save_848xx_spirom_version(struct elink_phy *phy, struct bnx2x_softc *sc, uint8_t port) { uint16_t val, fw_ver2, cnt, i; static struct elink_reg_set reg_set[] = { {MDIO_PMA_DEVAD, 0xA819, 0x0014}, {MDIO_PMA_DEVAD, 0xA81A, 0xc200}, {MDIO_PMA_DEVAD, 0xA81B, 0x0000}, {MDIO_PMA_DEVAD, 0xA81C, 0x0300}, {MDIO_PMA_DEVAD, 0xA817, 0x0009} }; uint16_t fw_ver1; if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) { elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1); elink_save_spirom_version(sc, port, fw_ver1 & 0xfff, phy->ver_addr); } else { /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */ /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */ for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); for (cnt = 0; cnt < 100; cnt++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xA818, &val); if (val & 1) break; DELAY(5); } if (cnt == 100) { PMD_DRV_LOG(DEBUG, "Unable to read 848xx " "phy fw version(1)"); elink_save_spirom_version(sc, port, 0, phy->ver_addr); return; } /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A); for (cnt = 0; cnt < 100; cnt++) { elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xA818, &val); if (val & 1) break; DELAY(5); } if (cnt == 100) { PMD_DRV_LOG(DEBUG, "Unable to read 848xx phy fw " "version(2)"); elink_save_spirom_version(sc, port, 0, phy->ver_addr); return; } /* lower 16 bits of the register SPI_FW_STATUS */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1); /* upper 16 bits of register SPI_FW_STATUS */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2); elink_save_spirom_version(sc, port, (fw_ver2 << 16) | fw_ver1, phy->ver_addr); } } static void elink_848xx_set_led(struct bnx2x_softc *sc, struct elink_phy *phy) { uint16_t val, offset, i; static struct elink_reg_set reg_set[] = { {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000}, {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH, MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ}, {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD} }; /* PHYC_CTL_LED_CTL */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, &val); val &= 0xFE00; val |= 0x0092; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); for (i = 0; i < ARRAY_SIZE(reg_set); i++) elink_cl45_write(sc, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1; else offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1; /* stretch_en for LED3 */ elink_cl45_read_or_write(sc, phy, MDIO_PMA_DEVAD, offset, MDIO_PMA_REG_84823_LED3_STRETCH_EN); } static void elink_848xx_specific_func(struct elink_phy *phy, struct elink_params *params, uint32_t action) { struct bnx2x_softc *sc = params->sc; switch (action) { case ELINK_PHY_INIT: if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) && (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) { /* Save spirom version */ elink_save_848xx_spirom_version(phy, sc, params->port); } /* This phy uses the NIG latch mechanism since link indication * arrives through its LED4 and not via its LASI signal, so we * get steady signal instead of clear on read */ elink_bits_en(sc, NIG_REG_LATCH_BC_0 + params->port * 4, 1 << ELINK_NIG_LATCH_BC_ENABLE_MI_INT); elink_848xx_set_led(sc, phy); break; } } static elink_status_t elink_848xx_cmn_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t autoneg_val, an_1000_val, an_10_100_val; elink_848xx_specific_func(phy, params, ELINK_PHY_INIT); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000); /* set 1000 speed advertisement */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, &an_1000_val); elink_ext_phy_set_pause(params, phy, vars); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV, &an_10_100_val); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, &autoneg_val); /* Disable forced speed */ autoneg_val &= ~((1 << 6) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 13)); an_10_100_val &= ~((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8)); if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (phy->req_line_speed == ELINK_SPEED_1000)) { an_1000_val |= (1 << 8); autoneg_val |= (1 << 9 | 1 << 12); if (phy->req_duplex == DUPLEX_FULL) an_1000_val |= (1 << 9); PMD_DRV_LOG(DEBUG, "Advertising 1G"); } else an_1000_val &= ~((1 << 8) | (1 << 9)); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, an_1000_val); /* Set 10/100 speed advertisement */ if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) { if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) { /* Enable autoneg and restart autoneg for legacy speeds */ autoneg_val |= (1 << 9 | 1 << 12); an_10_100_val |= (1 << 8); PMD_DRV_LOG(DEBUG, "Advertising 100M-FD"); } if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) { /* Enable autoneg and restart autoneg for legacy speeds */ autoneg_val |= (1 << 9 | 1 << 12); an_10_100_val |= (1 << 7); PMD_DRV_LOG(DEBUG, "Advertising 100M-HD"); } if ((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) && (phy->supported & ELINK_SUPPORTED_10baseT_Full)) { an_10_100_val |= (1 << 6); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 10M-FD"); } if ((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) && (phy->supported & ELINK_SUPPORTED_10baseT_Half)) { an_10_100_val |= (1 << 5); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 10M-HD"); } } /* Only 10/100 are allowed to work in FORCE mode */ if ((phy->req_line_speed == ELINK_SPEED_100) && (phy->supported & (ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full))) { autoneg_val |= (1 << 13); /* Enabled AUTO-MDIX when autoneg is disabled */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, (1 << 15 | 1 << 9 | 7 << 0)); /* The PHY needs this set even for forced link. */ an_10_100_val |= (1 << 8) | (1 << 7); PMD_DRV_LOG(DEBUG, "Setting 100M force"); } if ((phy->req_line_speed == ELINK_SPEED_10) && (phy->supported & (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full))) { /* Enabled AUTO-MDIX when autoneg is disabled */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, (1 << 15 | 1 << 9 | 7 << 0)); PMD_DRV_LOG(DEBUG, "Setting 10M force"); } elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV, an_10_100_val); if (phy->req_duplex == DUPLEX_FULL) autoneg_val |= (1 << 8); /* Always write this if this is not 84833/4. * For 84833/4, write it only when it's a forced speed. */ if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) && (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) || ((autoneg_val & (1 << 12)) == 0)) elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val); if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || (phy->req_line_speed == ELINK_SPEED_10000)) { PMD_DRV_LOG(DEBUG, "Advertising 10G"); /* Restart autoneg for 10G */ elink_cl45_read_or_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, 0x1000); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x3200); } else elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, 1); return ELINK_STATUS_OK; } static elink_status_t elink_8481_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; /* Restore normal power mode */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); /* HW reset */ elink_ext_phy_hw_reset(sc, params->port); elink_wait_reset_complete(sc, phy, params); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1 << 15); return elink_848xx_cmn_config_init(phy, params, vars); } #define PHY84833_CMDHDLR_WAIT 300 #define PHY84833_CMDHDLR_MAX_ARGS 5 static elink_status_t elink_84833_cmd_hdlr(struct elink_phy *phy, struct elink_params *params, uint16_t fw_cmd, uint16_t cmd_args[], int argc) { int idx; uint16_t val; struct bnx2x_softc *sc = params->sc; /* Write CMD_OPEN_OVERRIDE to STATUS reg */ elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_STATUS, PHY84833_STATUS_CMD_OPEN_OVERRIDE); for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) { elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_STATUS, &val); if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS) break; DELAY(1000 * 1); } if (idx >= PHY84833_CMDHDLR_WAIT) { PMD_DRV_LOG(DEBUG, "FW cmd: FW not ready."); return ELINK_STATUS_ERROR; } /* Prepare argument(s) and issue command */ for (idx = 0; idx < argc; idx++) { elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_DATA1 + idx, cmd_args[idx]); } elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_COMMAND, fw_cmd); for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) { elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_STATUS, &val); if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) || (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) break; DELAY(1000 * 1); } if ((idx >= PHY84833_CMDHDLR_WAIT) || (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) { PMD_DRV_LOG(DEBUG, "FW cmd failed."); return ELINK_STATUS_ERROR; } /* Gather returning data */ for (idx = 0; idx < argc; idx++) { elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_DATA1 + idx, &cmd_args[idx]); } elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_CMD_HDLR_STATUS, PHY84833_STATUS_CMD_CLEAR_COMPLETE); return ELINK_STATUS_OK; } static elink_status_t elink_84833_pair_swap_cfg(struct elink_phy *phy, struct elink_params *params, __rte_unused struct elink_vars *vars) { uint32_t pair_swap; uint16_t data[PHY84833_CMDHDLR_MAX_ARGS]; elink_status_t status; struct bnx2x_softc *sc = params->sc; /* Check for configuration. */ pair_swap = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. xgbt_phy_cfg)) & PORT_HW_CFG_RJ45_PAIR_SWAP_MASK; if (pair_swap == 0) return ELINK_STATUS_OK; /* Only the second argument is used for this command */ data[1] = (uint16_t) pair_swap; status = elink_84833_cmd_hdlr(phy, params, PHY84833_CMD_SET_PAIR_SWAP, data, PHY84833_CMDHDLR_MAX_ARGS); if (status == ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Pairswap OK, val=0x%x", data[1]); } return status; } static uint8_t elink_84833_get_reset_gpios(struct bnx2x_softc *sc, uint32_t shmem_base_path[], __rte_unused uint32_t chip_id) { uint32_t reset_pin[2]; uint32_t idx; uint8_t reset_gpios; if (CHIP_IS_E3(sc)) { /* Assume that these will be GPIOs, not EPIOs. */ for (idx = 0; idx < 2; idx++) { /* Map config param to register bit. */ reset_pin[idx] = REG_RD(sc, shmem_base_path[idx] + offsetof(struct shmem_region, dev_info. port_hw_config[0]. e3_cmn_pin_cfg)); reset_pin[idx] = (reset_pin[idx] & PORT_HW_CFG_E3_PHY_RESET_MASK) >> PORT_HW_CFG_E3_PHY_RESET_SHIFT; reset_pin[idx] -= PIN_CFG_GPIO0_P0; reset_pin[idx] = (1 << reset_pin[idx]); } reset_gpios = (uint8_t) (reset_pin[0] | reset_pin[1]); } else { /* E2, look from diff place of shmem. */ for (idx = 0; idx < 2; idx++) { reset_pin[idx] = REG_RD(sc, shmem_base_path[idx] + offsetof(struct shmem_region, dev_info. port_hw_config[0]. default_cfg)); reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK; reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0; reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT; reset_pin[idx] = (1 << reset_pin[idx]); } reset_gpios = (uint8_t) (reset_pin[0] | reset_pin[1]); } return reset_gpios; } static elink_status_t elink_84833_hw_reset_phy(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t reset_gpios; uint32_t other_shmem_base_addr = REG_RD(sc, params->shmem2_base + offsetof(struct shmem2_region, other_shmem_base_addr)); uint32_t shmem_base_path[2]; /* Work around for 84833 LED failure inside RESET status */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, MDIO_AN_REG_8481_MII_CTRL_FORCE_1G); elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_1G_100T_EXT_CTRL, MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF); shmem_base_path[0] = params->shmem_base; shmem_base_path[1] = other_shmem_base_addr; reset_gpios = elink_84833_get_reset_gpios(sc, shmem_base_path, params->chip_id); elink_cb_gpio_mult_write(sc, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW); DELAY(10); PMD_DRV_LOG(DEBUG, "84833 hw reset on pin values 0x%x", reset_gpios); return ELINK_STATUS_OK; } static elink_status_t elink_8483x_disable_eee(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { elink_status_t rc; uint16_t cmd_args = 0; PMD_DRV_LOG(DEBUG, "Don't Advertise 10GBase-T EEE"); /* Prevent Phy from working in EEE and advertising it */ rc = elink_84833_cmd_hdlr(phy, params, PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "EEE disable failed."); return rc; } return elink_eee_disable(phy, params, vars); } static elink_status_t elink_8483x_enable_eee(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { elink_status_t rc; uint16_t cmd_args = 1; rc = elink_84833_cmd_hdlr(phy, params, PHY84833_CMD_SET_EEE_MODE, &cmd_args, 1); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "EEE enable failed."); return rc; } return elink_eee_advertise(phy, params, vars, SHMEM_EEE_10G_ADV); } #define PHY84833_CONSTANT_LATENCY 1193 static elink_status_t elink_848x3_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t port, initialize = 1; uint16_t val; uint32_t actual_phy_selection; uint16_t cmd_args[PHY84833_CMDHDLR_MAX_ARGS]; elink_status_t rc = ELINK_STATUS_OK; DELAY(1000 * 1); if (!(CHIP_IS_E1x(sc))) port = SC_PATH(sc); else port = params->port; if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823) { elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); } else { /* MDIO reset */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x8000); } elink_wait_reset_complete(sc, phy, params); /* Wait for GPHY to come out of reset */ DELAY(1000 * 50); if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) && (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) { /* BNX2X84823 requires that XGXS links up first @ 10G for normal * behavior. */ uint16_t temp; temp = vars->line_speed; vars->line_speed = ELINK_SPEED_10000; elink_set_autoneg(¶ms->phy[ELINK_INT_PHY], params, vars, 0); elink_program_serdes(¶ms->phy[ELINK_INT_PHY], params, vars); vars->line_speed = temp; } elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_CTL_REG_84823_MEDIA, &val); val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK | MDIO_CTL_REG_84823_MEDIA_LINE_MASK | MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN | MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK | MDIO_CTL_REG_84823_MEDIA_FIBER_1G); if (CHIP_IS_E3(sc)) { val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK | MDIO_CTL_REG_84823_MEDIA_LINE_MASK); } else { val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI | MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L); } actual_phy_selection = elink_phy_selection(params); switch (actual_phy_selection) { case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT: /* Do nothing. Essentially this is like the priority copper */ break; case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER; break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER; break; case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: /* Do nothing here. The first PHY won't be initialized at all */ break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN; initialize = 0; break; } if (params->phy[ELINK_EXT_PHY2].req_line_speed == ELINK_SPEED_1000) val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G; elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_CTL_REG_84823_MEDIA, val); PMD_DRV_LOG(DEBUG, "Multi_phy config = 0x%x, Media control = 0x%x", params->multi_phy_config, val); if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) { elink_84833_pair_swap_cfg(phy, params, vars); /* Keep AutogrEEEn disabled. */ cmd_args[0] = 0x0; cmd_args[1] = 0x0; cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1; cmd_args[3] = PHY84833_CONSTANT_LATENCY; rc = elink_84833_cmd_hdlr(phy, params, PHY84833_CMD_SET_EEE_MODE, cmd_args, PHY84833_CMDHDLR_MAX_ARGS); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Cfg AutogrEEEn failed."); } } if (initialize) { rc = elink_848xx_cmn_config_init(phy, params, vars); } else { elink_save_848xx_spirom_version(phy, sc, params->port); } /* 84833 PHY has a better feature and doesn't need to support this. */ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823) { uint32_t cms_enable = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info. port_hw_config[params-> port]. default_cfg)) & PORT_HW_CFG_ENABLE_CMS_MASK; elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_CTL_REG_84823_USER_CTRL_REG, &val); if (cms_enable) val |= MDIO_CTL_REG_84823_USER_CTRL_CMS; else val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS; elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_CTL_REG_84823_USER_CTRL_REG, val); } elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_TOP_CFG_FW_REV, &val); /* Configure EEE support */ if ((val >= MDIO_84833_TOP_CFG_FW_EEE) && (val != MDIO_84833_TOP_CFG_FW_NO_EEE) && elink_eee_has_cap(params)) { rc = elink_eee_initial_config(params, vars, SHMEM_EEE_10G_ADV); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Failed to configure EEE timers"); elink_8483x_disable_eee(phy, params, vars); return rc; } if ((phy->req_duplex == DUPLEX_FULL) && (params->eee_mode & ELINK_EEE_MODE_ADV_LPI) && (elink_eee_calc_timer(params) || !(params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI))) rc = elink_8483x_enable_eee(phy, params, vars); else rc = elink_8483x_disable_eee(phy, params, vars); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Failed to set EEE advertisement"); return rc; } } else { vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK; } if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) { /* Bring PHY out of super isolate mode as the final step. */ elink_cl45_read_and_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_TOP_CFG_XGPHY_STRAP1, (uint16_t) ~ MDIO_84833_SUPER_ISOLATE); } return rc; } static uint8_t elink_848xx_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t val, val1, val2; uint8_t link_up = 0; /* Check 10G-BaseT link status */ /* Check PMD signal ok */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, 0xFFFA, &val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL, &val2); PMD_DRV_LOG(DEBUG, "BNX2X848xx: PMD_SIGNAL 1.a811 = 0x%x", val2); /* Check link 10G */ if (val2 & (1 << 11)) { vars->line_speed = ELINK_SPEED_10000; vars->duplex = DUPLEX_FULL; link_up = 1; elink_ext_phy_10G_an_resolve(sc, phy, vars); } else { /* Check Legacy speed link */ uint16_t legacy_status, legacy_speed, mii_ctrl; /* Enable expansion register 0x42 (Operation mode status) */ elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42); /* Get legacy speed operation status */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, &legacy_status); PMD_DRV_LOG(DEBUG, "Legacy speed status = 0x%x", legacy_status); link_up = ((legacy_status & (1 << 11)) == (1 << 11)); legacy_speed = (legacy_status & (3 << 9)); if (legacy_speed == (0 << 9)) vars->line_speed = ELINK_SPEED_10; else if (legacy_speed == (1 << 9)) vars->line_speed = ELINK_SPEED_100; else if (legacy_speed == (2 << 9)) vars->line_speed = ELINK_SPEED_1000; else { /* Should not happen: Treat as link down */ vars->line_speed = 0; link_up = 0; } if (params->feature_config_flags & ELINK_FEATURE_CONFIG_IEEE_PHY_TEST) { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, &mii_ctrl); /* For IEEE testing, check for a fake link. */ link_up |= ((mii_ctrl & 0x3040) == 0x40); } if (link_up) { if (legacy_status & (1 << 8)) vars->duplex = DUPLEX_FULL; else vars->duplex = DUPLEX_HALF; PMD_DRV_LOG(DEBUG, "Link is up in %dMbps, is_duplex_full= %d", vars->line_speed, (vars->duplex == DUPLEX_FULL)); /* Check legacy speed AN resolution */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_STATUS, &val); if (val & (1 << 5)) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_EXPANSION, &val); if ((val & (1 << 0)) == 0) vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; } } if (link_up) { PMD_DRV_LOG(DEBUG, "BNX2X848x3: link speed is %d", vars->line_speed); elink_ext_phy_resolve_fc(phy, params, vars); /* Read LP advertised speeds */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, &val); if (val & (1 << 5)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10THD_CAPABLE; if (val & (1 << 6)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE; if (val & (1 << 7)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE; if (val & (1 << 8)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE; if (val & (1 << 9)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100T4_CAPABLE; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_1000T_STATUS, &val); if (val & (1 << 10)) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE; if (val & (1 << 11)) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE; elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS, &val); if (val & (1 << 11)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; /* Determine if EEE was negotiated */ if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) elink_eee_an_resolve(phy, params, vars); } return link_up; } static elink_status_t elink_848xx_format_ver(uint32_t raw_ver, uint8_t * str, uint16_t * len) { elink_status_t status = ELINK_STATUS_OK; uint32_t spirom_ver; spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F); status = elink_format_ver(spirom_ver, str, len); return status; } static void elink_8481_hw_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { elink_cb_gpio_write(params->sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, 0); elink_cb_gpio_write(params->sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, 1); } static void elink_8481_link_reset(struct elink_phy *phy, struct elink_params *params) { elink_cl45_write(params->sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000); elink_cl45_write(params->sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1); } static void elink_848x3_link_reset(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint8_t port; uint16_t val16; if (!(CHIP_IS_E1x(sc))) port = SC_PATH(sc); else port = params->port; if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823) { elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_3, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); } else { elink_cl45_read(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val16); val16 |= MDIO_84833_SUPER_ISOLATE; elink_cl45_write(sc, phy, MDIO_CTL_DEVAD, MDIO_84833_TOP_CFG_XGPHY_STRAP1, val16); } } static void elink_848xx_set_link_led(struct elink_phy *phy, struct elink_params *params, uint8_t mode) { struct bnx2x_softc *sc = params->sc; uint16_t val; __rte_unused uint8_t port; if (!(CHIP_IS_E1x(sc))) port = SC_PATH(sc); else port = params->port; switch (mode) { case ELINK_LED_MODE_OFF: PMD_DRV_LOG(DEBUG, "Port 0x%x: LED MODE OFF", port); if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY1) { /* Set LED masks */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED5_MASK, 0x0); } else { elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); } break; case ELINK_LED_MODE_FRONT_PANEL_OFF: PMD_DRV_LOG(DEBUG, "Port 0x%x: LED MODE FRONT PANEL OFF", port); if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY1) { /* Set LED masks */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED5_MASK, 0x20); } else { elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834) { /* Disable MI_INT interrupt before setting LED4 * source to constant off. */ if (REG_RD(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4) & ELINK_NIG_MASK_MI_INT) { params->link_flags |= ELINK_LINK_FLAGS_INT_DISABLED; elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4, ELINK_NIG_MASK_MI_INT); } elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_SIGNAL_MASK, 0x0); } } break; case ELINK_LED_MODE_ON: PMD_DRV_LOG(DEBUG, "Port 0x%x: LED MODE ON", port); if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY1) { /* Set control reg */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, &val); val &= 0x8000; val |= 0x2492; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); /* Set LED masks */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x20); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x20); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED5_MASK, 0x0); } else { elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x20); if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834) { /* Disable MI_INT interrupt before setting LED4 * source to constant on. */ if (REG_RD(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4) & ELINK_NIG_MASK_MI_INT) { params->link_flags |= ELINK_LINK_FLAGS_INT_DISABLED; elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4, ELINK_NIG_MASK_MI_INT); } elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_SIGNAL_MASK, 0x20); } } break; case ELINK_LED_MODE_OPER: PMD_DRV_LOG(DEBUG, "Port 0x%x: LED MODE OPER", port); if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY1) { /* Set control reg */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, &val); if (!((val & MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK) >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) { PMD_DRV_LOG(DEBUG, "Setting LINK_SIGNAL"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, 0xa492); } /* Set LED masks */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x10); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x80); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x98); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED5_MASK, 0x40); } else { /* EXTPHY2 LED mode indicate that the 100M/1G/10G LED * sources are all wired through LED1, rather than only * 10G in other modes. */ val = ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) == SHARED_HW_CFG_LED_EXTPHY2) ? 0x98 : 0x80; elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, val); /* Tell LED3 to blink on source */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, &val); val &= ~(7 << 6); val |= (1 << 6); /* A83B[8:6]= 1 */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LINK_SIGNAL, val); if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834) { /* Restore LED4 source to external link, * and re-enable interrupts. */ elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_SIGNAL_MASK, 0x40); if (params->link_flags & ELINK_LINK_FLAGS_INT_DISABLED) { elink_link_int_enable(params); params->link_flags &= ~ELINK_LINK_FLAGS_INT_DISABLED; } } } break; } /* This is a workaround for E3+84833 until autoneg * restart is fixed in f/w */ if (CHIP_IS_E3(sc)) { elink_cl45_read(sc, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_1, &val); } } /******************************************************************/ /* 54618SE PHY SECTION */ /******************************************************************/ static void elink_54618se_specific_func(struct elink_phy *phy, struct elink_params *params, uint32_t action) { struct bnx2x_softc *sc = params->sc; uint16_t temp; switch (action) { case ELINK_PHY_INIT: /* Configure LED4: set to INTR (0x6). */ /* Accessing shadow register 0xe. */ elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_LED_SEL2); elink_cl22_read(sc, phy, MDIO_REG_GPHY_SHADOW, &temp); temp &= ~(0xf << 4); temp |= (0x6 << 4); elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_WR_ENA | temp); /* Configure INTR based on link status change. */ elink_cl22_write(sc, phy, MDIO_REG_INTR_MASK, ~MDIO_REG_INTR_MASK_LINK_STATUS); break; } } static elink_status_t elink_54618se_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t port; uint16_t autoneg_val, an_1000_val, an_10_100_val, fc_val, temp; uint32_t cfg_pin; PMD_DRV_LOG(DEBUG, "54618SE cfg init"); DELAY(1000 * 1); /* This works with E3 only, no need to check the chip * before determining the port. */ port = params->port; cfg_pin = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. e3_cmn_pin_cfg)) & PORT_HW_CFG_E3_PHY_RESET_MASK) >> PORT_HW_CFG_E3_PHY_RESET_SHIFT; /* Drive pin high to bring the GPHY out of reset. */ elink_set_cfg_pin(sc, cfg_pin, 1); /* wait for GPHY to reset */ DELAY(1000 * 50); /* reset phy */ elink_cl22_write(sc, phy, MDIO_PMA_REG_CTRL, 0x8000); elink_wait_reset_complete(sc, phy, params); /* Wait for GPHY to reset */ DELAY(1000 * 50); elink_54618se_specific_func(phy, params, ELINK_PHY_INIT); /* Flip the signal detect polarity (set 0x1c.0x1e[8]). */ elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_AUTO_DET_MED); elink_cl22_read(sc, phy, MDIO_REG_GPHY_SHADOW, &temp); temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD; elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_WR_ENA | temp); /* Set up fc */ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ elink_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); fc_val = 0; if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE; /* Read all advertisement */ elink_cl22_read(sc, phy, 0x09, &an_1000_val); elink_cl22_read(sc, phy, 0x04, &an_10_100_val); elink_cl22_read(sc, phy, MDIO_PMA_REG_CTRL, &autoneg_val); /* Disable forced speed */ autoneg_val &= ~((1 << 6) | (1 << 8) | (1 << 9) | (1 << 12) | (1 << 13)); an_10_100_val &= ~((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 10) | (1 << 11)); if (((phy->req_line_speed == ELINK_SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (phy->req_line_speed == ELINK_SPEED_1000)) { an_1000_val |= (1 << 8); autoneg_val |= (1 << 9 | 1 << 12); if (phy->req_duplex == DUPLEX_FULL) an_1000_val |= (1 << 9); PMD_DRV_LOG(DEBUG, "Advertising 1G"); } else an_1000_val &= ~((1 << 8) | (1 << 9)); elink_cl22_write(sc, phy, 0x09, an_1000_val); elink_cl22_read(sc, phy, 0x09, &an_1000_val); /* Advertise 10/100 link speed */ if (phy->req_line_speed == ELINK_SPEED_AUTO_NEG) { if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) { an_10_100_val |= (1 << 5); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 10M-HD"); } if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) { an_10_100_val |= (1 << 6); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 10M-FD"); } if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) { an_10_100_val |= (1 << 7); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 100M-HD"); } if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) { an_10_100_val |= (1 << 8); autoneg_val |= (1 << 9 | 1 << 12); PMD_DRV_LOG(DEBUG, "Advertising 100M-FD"); } } /* Only 10/100 are allowed to work in FORCE mode */ if (phy->req_line_speed == ELINK_SPEED_100) { autoneg_val |= (1 << 13); /* Enabled AUTO-MDIX when autoneg is disabled */ elink_cl22_write(sc, phy, 0x18, (1 << 15 | 1 << 9 | 7 << 0)); PMD_DRV_LOG(DEBUG, "Setting 100M force"); } if (phy->req_line_speed == ELINK_SPEED_10) { /* Enabled AUTO-MDIX when autoneg is disabled */ elink_cl22_write(sc, phy, 0x18, (1 << 15 | 1 << 9 | 7 << 0)); PMD_DRV_LOG(DEBUG, "Setting 10M force"); } if ((phy->flags & ELINK_FLAGS_EEE) && elink_eee_has_cap(params)) { elink_status_t rc; elink_cl22_write(sc, phy, MDIO_REG_GPHY_EXP_ACCESS, MDIO_REG_GPHY_EXP_ACCESS_TOP | MDIO_REG_GPHY_EXP_TOP_2K_BUF); elink_cl22_read(sc, phy, MDIO_REG_GPHY_EXP_ACCESS_GATE, &temp); temp &= 0xfffe; elink_cl22_write(sc, phy, MDIO_REG_GPHY_EXP_ACCESS_GATE, temp); rc = elink_eee_initial_config(params, vars, SHMEM_EEE_1G_ADV); if (rc != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Failed to configure EEE timers"); elink_eee_disable(phy, params, vars); } else if ((params->eee_mode & ELINK_EEE_MODE_ADV_LPI) && (phy->req_duplex == DUPLEX_FULL) && (elink_eee_calc_timer(params) || !(params->eee_mode & ELINK_EEE_MODE_ENABLE_LPI))) { /* Need to advertise EEE only when requested, * and either no LPI assertion was requested, * or it was requested and a valid timer was set. * Also notice full duplex is required for EEE. */ elink_eee_advertise(phy, params, vars, SHMEM_EEE_1G_ADV); } else { PMD_DRV_LOG(DEBUG, "Don't Advertise 1GBase-T EEE"); elink_eee_disable(phy, params, vars); } } else { vars->eee_status &= ~SHMEM_EEE_1G_ADV << SHMEM_EEE_SUPPORTED_SHIFT; if (phy->flags & ELINK_FLAGS_EEE) { /* Handle legacy auto-grEEEn */ if (params->feature_config_flags & ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED) { temp = 6; PMD_DRV_LOG(DEBUG, "Enabling Auto-GrEEEn"); } else { temp = 0; PMD_DRV_LOG(DEBUG, "Don't Adv. EEE"); } elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_EEE_ADV, temp); } } elink_cl22_write(sc, phy, 0x04, an_10_100_val | fc_val); if (phy->req_duplex == DUPLEX_FULL) autoneg_val |= (1 << 8); elink_cl22_write(sc, phy, MDIO_PMA_REG_CTRL, autoneg_val); return ELINK_STATUS_OK; } static void elink_5461x_set_link_led(struct elink_phy *phy, struct elink_params *params, uint8_t mode) { struct bnx2x_softc *sc = params->sc; uint16_t temp; elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_LED_SEL1); elink_cl22_read(sc, phy, MDIO_REG_GPHY_SHADOW, &temp); temp &= 0xff00; PMD_DRV_LOG(DEBUG, "54618x set link led (mode=%x)", mode); switch (mode) { case ELINK_LED_MODE_FRONT_PANEL_OFF: case ELINK_LED_MODE_OFF: temp |= 0x00ee; break; case ELINK_LED_MODE_OPER: temp |= 0x0001; break; case ELINK_LED_MODE_ON: temp |= 0x00ff; break; default: break; } elink_cl22_write(sc, phy, MDIO_REG_GPHY_SHADOW, MDIO_REG_GPHY_SHADOW_WR_ENA | temp); return; } static void elink_54618se_link_reset(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint32_t cfg_pin; uint8_t port; /* In case of no EPIO routed to reset the GPHY, put it * in low power mode. */ elink_cl22_write(sc, phy, MDIO_PMA_REG_CTRL, 0x800); /* This works with E3 only, no need to check the chip * before determining the port. */ port = params->port; cfg_pin = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. e3_cmn_pin_cfg)) & PORT_HW_CFG_E3_PHY_RESET_MASK) >> PORT_HW_CFG_E3_PHY_RESET_SHIFT; /* Drive pin low to put GPHY in reset. */ elink_set_cfg_pin(sc, cfg_pin, 0); } static uint8_t elink_54618se_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint16_t val; uint8_t link_up = 0; uint16_t legacy_status, legacy_speed; /* Get speed operation status */ elink_cl22_read(sc, phy, MDIO_REG_GPHY_AUX_STATUS, &legacy_status); PMD_DRV_LOG(DEBUG, "54618SE read_status: 0x%x", legacy_status); /* Read status to clear the PHY interrupt. */ elink_cl22_read(sc, phy, MDIO_REG_INTR_STATUS, &val); link_up = ((legacy_status & (1 << 2)) == (1 << 2)); if (link_up) { legacy_speed = (legacy_status & (7 << 8)); if (legacy_speed == (7 << 8)) { vars->line_speed = ELINK_SPEED_1000; vars->duplex = DUPLEX_FULL; } else if (legacy_speed == (6 << 8)) { vars->line_speed = ELINK_SPEED_1000; vars->duplex = DUPLEX_HALF; } else if (legacy_speed == (5 << 8)) { vars->line_speed = ELINK_SPEED_100; vars->duplex = DUPLEX_FULL; } /* Omitting 100Base-T4 for now */ else if (legacy_speed == (3 << 8)) { vars->line_speed = ELINK_SPEED_100; vars->duplex = DUPLEX_HALF; } else if (legacy_speed == (2 << 8)) { vars->line_speed = ELINK_SPEED_10; vars->duplex = DUPLEX_FULL; } else if (legacy_speed == (1 << 8)) { vars->line_speed = ELINK_SPEED_10; vars->duplex = DUPLEX_HALF; } else /* Should not happen */ vars->line_speed = 0; PMD_DRV_LOG(DEBUG, "Link is up in %dMbps, is_duplex_full= %d", vars->line_speed, (vars->duplex == DUPLEX_FULL)); /* Check legacy speed AN resolution */ elink_cl22_read(sc, phy, 0x01, &val); if (val & (1 << 5)) vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; elink_cl22_read(sc, phy, 0x06, &val); if ((val & (1 << 0)) == 0) vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; PMD_DRV_LOG(DEBUG, "BNX2X54618SE: link speed is %d", vars->line_speed); elink_ext_phy_resolve_fc(phy, params, vars); if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { /* Report LP advertised speeds */ elink_cl22_read(sc, phy, 0x5, &val); if (val & (1 << 5)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10THD_CAPABLE; if (val & (1 << 6)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10TFD_CAPABLE; if (val & (1 << 7)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100TXHD_CAPABLE; if (val & (1 << 8)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100TXFD_CAPABLE; if (val & (1 << 9)) vars->link_status |= LINK_STATUS_LINK_PARTNER_100T4_CAPABLE; elink_cl22_read(sc, phy, 0xa, &val); if (val & (1 << 10)) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE; if (val & (1 << 11)) vars->link_status |= LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE; if ((phy->flags & ELINK_FLAGS_EEE) && elink_eee_has_cap(params)) elink_eee_an_resolve(phy, params, vars); } } return link_up; } static void elink_54618se_config_loopback(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; uint16_t val; uint32_t umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0; PMD_DRV_LOG(DEBUG, "2PMA/PMD ext_phy_loopback: 54618se"); /* Enable master/slave manual mmode and set to master */ /* mii write 9 [bits set 11 12] */ elink_cl22_write(sc, phy, 0x09, 3 << 11); /* forced 1G and disable autoneg */ /* set val [mii read 0] */ /* set val [expr $val & [bits clear 6 12 13]] */ /* set val [expr $val | [bits set 6 8]] */ /* mii write 0 $val */ elink_cl22_read(sc, phy, 0x00, &val); val &= ~((1 << 6) | (1 << 12) | (1 << 13)); val |= (1 << 6) | (1 << 8); elink_cl22_write(sc, phy, 0x00, val); /* Set external loopback and Tx using 6dB coding */ /* mii write 0x18 7 */ /* set val [mii read 0x18] */ /* mii write 0x18 [expr $val | [bits set 10 15]] */ elink_cl22_write(sc, phy, 0x18, 7); elink_cl22_read(sc, phy, 0x18, &val); elink_cl22_write(sc, phy, 0x18, val | (1 << 10) | (1 << 15)); /* This register opens the gate for the UMAC despite its name */ REG_WR(sc, NIG_REG_EGRESS_EMAC0_PORT + params->port * 4, 1); /* Maximum Frame Length (RW). Defines a 14-Bit maximum frame * length used by the MAC receive logic to check frames. */ REG_WR(sc, umac_base + UMAC_REG_MAXFR, 0x2710); } /******************************************************************/ /* SFX7101 PHY SECTION */ /******************************************************************/ static void elink_7101_config_loopback(struct elink_phy *phy, struct elink_params *params) { struct bnx2x_softc *sc = params->sc; /* SFX7101_XGXS_TEST1 */ elink_cl45_write(sc, phy, MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100); } static elink_status_t elink_7101_config_init(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { uint16_t fw_ver1, fw_ver2, val; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Setting the SFX7101 LASI indication"); /* Restore normal power mode */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); /* HW reset */ elink_ext_phy_hw_reset(sc, params->port); elink_wait_reset_complete(sc, phy, params); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1); PMD_DRV_LOG(DEBUG, "Setting the SFX7101 LED to blink on traffic"); elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1 << 3)); elink_ext_phy_set_pause(params, phy, vars); /* Restart autoneg */ elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val); val |= 0x200; elink_cl45_write(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val); /* Save spirom version */ elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2); elink_save_spirom_version(sc, params->port, (uint32_t) (fw_ver1 << 16 | fw_ver2), phy->ver_addr); return ELINK_STATUS_OK; } static uint8_t elink_7101_read_status(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint8_t link_up; uint16_t val1, val2; elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1); PMD_DRV_LOG(DEBUG, "10G-base-T LASI status 0x%x->0x%x", val2, val1); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); elink_cl45_read(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); PMD_DRV_LOG(DEBUG, "10G-base-T PMA status 0x%x->0x%x", val2, val1); link_up = ((val1 & 4) == 4); /* If link is up print the AN outcome of the SFX7101 PHY */ if (link_up) { elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS, &val2); vars->line_speed = ELINK_SPEED_10000; vars->duplex = DUPLEX_FULL; PMD_DRV_LOG(DEBUG, "SFX7101 AN status 0x%x->Master=%x", val2, (val2 & (1 << 14))); elink_ext_phy_10G_an_resolve(sc, phy, vars); elink_ext_phy_resolve_fc(phy, params, vars); /* Read LP advertised speeds */ if (val2 & (1 << 11)) vars->link_status |= LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE; } return link_up; } static elink_status_t elink_7101_format_ver(uint32_t spirom_ver, uint8_t * str, uint16_t * len) { if (*len < 5) return ELINK_STATUS_ERROR; str[0] = (spirom_ver & 0xFF); str[1] = (spirom_ver & 0xFF00) >> 8; str[2] = (spirom_ver & 0xFF0000) >> 16; str[3] = (spirom_ver & 0xFF000000) >> 24; str[4] = '\0'; *len -= 5; return ELINK_STATUS_OK; } static void elink_7101_hw_reset(__rte_unused struct elink_phy *phy, struct elink_params *params) { /* Low power mode is controlled by GPIO 2 */ elink_cb_gpio_write(params->sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port); /* The PHY reset is controlled by GPIO 1 */ elink_cb_gpio_write(params->sc, MISC_REGISTERS_GPIO_1, MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port); } static void elink_7101_set_link_led(struct elink_phy *phy, struct elink_params *params, uint8_t mode) { uint16_t val = 0; struct bnx2x_softc *sc = params->sc; switch (mode) { case ELINK_LED_MODE_FRONT_PANEL_OFF: case ELINK_LED_MODE_OFF: val = 2; break; case ELINK_LED_MODE_ON: val = 1; break; case ELINK_LED_MODE_OPER: val = 0; break; } elink_cl45_write(sc, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LINK_LED_CNTL, val); } /******************************************************************/ /* STATIC PHY DECLARATION */ /******************************************************************/ static const struct elink_phy phy_null = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN, .addr = 0, .def_md_devad = 0, .flags = ELINK_FLAGS_INIT_XGXS_FIRST, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = 0, .media_type = ELINK_ETH_PHY_NOT_PRESENT, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) NULL, .read_status = (read_status_t) NULL, .link_reset = (link_reset_t) NULL, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) NULL, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_serdes = { .type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, .flags = 0, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_2500baseX_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_xgxs_config_init, .read_status = (read_status_t) elink_link_settings_status, .link_reset = (link_reset_t) elink_int_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) NULL, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_xgxs = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, .flags = 0, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_2500baseX_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_CX4, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_xgxs_config_init, .read_status = (read_status_t) elink_link_settings_status, .link_reset = (link_reset_t) elink_int_link_reset, .config_loopback = (config_loopback_t) elink_set_xgxs_loopback, .format_fw_ver = (format_fw_ver_t) NULL, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) elink_xgxs_specific_func }; static const struct elink_phy phy_warpcore = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_TX_ERROR_CHECK, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_20000baseKR2_Full | ELINK_SUPPORTED_20000baseMLD2_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_UNSPECIFIED, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, /* req_duplex = */ 0, /* rsrv = */ 0, .config_init = (config_init_t) elink_warpcore_config_init, .read_status = (read_status_t) elink_warpcore_read_status, .link_reset = (link_reset_t) elink_warpcore_link_reset, .config_loopback = (config_loopback_t) elink_set_warpcore_loopback, .format_fw_ver = (format_fw_ver_t) NULL, .hw_reset = (hw_reset_t) elink_warpcore_hw_reset, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_7101 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_FAN_FAILURE_DET_REQ, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_7101_config_init, .read_status = (read_status_t) elink_7101_read_status, .link_reset = (link_reset_t) elink_common_ext_link_reset, .config_loopback = (config_loopback_t) elink_7101_config_loopback, .format_fw_ver = (format_fw_ver_t) elink_7101_format_ver, .hw_reset = (hw_reset_t) elink_7101_hw_reset, .set_link_led = (set_link_led_t) elink_7101_set_link_led, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_8073 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8073, .addr = 0xff, .def_md_devad = 0, .flags = 0, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_2500baseX_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_KR, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8073_config_init, .read_status = (read_status_t) elink_8073_read_status, .link_reset = (link_reset_t) elink_8073_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_format_ver, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) elink_8073_specific_func }; static const struct elink_phy phy_8705 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8705, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_INIT_XGXS_FIRST, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_XFP_FIBER, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8705_config_init, .read_status = (read_status_t) elink_8705_read_status, .link_reset = (link_reset_t) elink_common_ext_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_null_format_ver, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_8706 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8706, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_INIT_XGXS_FIRST, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_SFPP_10G_FIBER, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8706_config_init, .read_status = (read_status_t) elink_8706_read_status, .link_reset = (link_reset_t) elink_common_ext_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_format_ver, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_8726 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726, .addr = 0xff, .def_md_devad = 0, .flags = (ELINK_FLAGS_INIT_XGXS_FIRST | ELINK_FLAGS_TX_ERROR_CHECK), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_NOT_PRESENT, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8726_config_init, .read_status = (read_status_t) elink_8726_read_status, .link_reset = (link_reset_t) elink_8726_link_reset, .config_loopback = (config_loopback_t) elink_8726_config_loopback, .format_fw_ver = (format_fw_ver_t) elink_format_ver, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) NULL, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_8727 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727, .addr = 0xff, .def_md_devad = 0, .flags = (ELINK_FLAGS_FAN_FAILURE_DET_REQ | ELINK_FLAGS_TX_ERROR_CHECK), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_NOT_PRESENT, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8727_config_init, .read_status = (read_status_t) elink_8727_read_status, .link_reset = (link_reset_t) elink_8727_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_format_ver, .hw_reset = (hw_reset_t) elink_8727_hw_reset, .set_link_led = (set_link_led_t) elink_8727_set_link_led, .phy_specific_func = (phy_specific_func_t) elink_8727_specific_func }; static const struct elink_phy phy_8481 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8481, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_FAN_FAILURE_DET_REQ | ELINK_FLAGS_REARM_LATCH_SIGNAL, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_8481_config_init, .read_status = (read_status_t) elink_848xx_read_status, .link_reset = (link_reset_t) elink_8481_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_848xx_format_ver, .hw_reset = (hw_reset_t) elink_8481_hw_reset, .set_link_led = (set_link_led_t) elink_848xx_set_link_led, .phy_specific_func = (phy_specific_func_t) NULL }; static const struct elink_phy phy_84823 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823, .addr = 0xff, .def_md_devad = 0, .flags = (ELINK_FLAGS_FAN_FAILURE_DET_REQ | ELINK_FLAGS_REARM_LATCH_SIGNAL | ELINK_FLAGS_TX_ERROR_CHECK), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_848x3_config_init, .read_status = (read_status_t) elink_848xx_read_status, .link_reset = (link_reset_t) elink_848x3_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_848xx_format_ver, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) elink_848xx_set_link_led, .phy_specific_func = (phy_specific_func_t) elink_848xx_specific_func }; static const struct elink_phy phy_84833 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833, .addr = 0xff, .def_md_devad = 0, .flags = (ELINK_FLAGS_FAN_FAILURE_DET_REQ | ELINK_FLAGS_REARM_LATCH_SIGNAL | ELINK_FLAGS_TX_ERROR_CHECK | ELINK_FLAGS_TEMPERATURE), .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_848x3_config_init, .read_status = (read_status_t) elink_848xx_read_status, .link_reset = (link_reset_t) elink_848x3_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_848xx_format_ver, .hw_reset = (hw_reset_t) elink_84833_hw_reset_phy, .set_link_led = (set_link_led_t) elink_848xx_set_link_led, .phy_specific_func = (phy_specific_func_t) elink_848xx_specific_func }; static const struct elink_phy phy_84834 = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_FAN_FAILURE_DET_REQ | ELINK_FLAGS_REARM_LATCH_SIGNAL, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, .req_duplex = 0, .rsrv = 0, .config_init = (config_init_t) elink_848x3_config_init, .read_status = (read_status_t) elink_848xx_read_status, .link_reset = (link_reset_t) elink_848x3_link_reset, .config_loopback = (config_loopback_t) NULL, .format_fw_ver = (format_fw_ver_t) elink_848xx_format_ver, .hw_reset = (hw_reset_t) elink_84833_hw_reset_phy, .set_link_led = (set_link_led_t) elink_848xx_set_link_led, .phy_specific_func = (phy_specific_func_t) elink_848xx_specific_func }; static const struct elink_phy phy_54618se = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE, .addr = 0xff, .def_md_devad = 0, .flags = ELINK_FLAGS_INIT_XGXS_FIRST, .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff}, .mdio_ctrl = 0, .supported = (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_TP | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause), .media_type = ELINK_ETH_PHY_BASE_T, .ver_addr = 0, .req_flow_ctrl = 0, .req_line_speed = 0, .speed_cap_mask = 0, /* req_duplex = */ 0, /* rsrv = */ 0, .config_init = (config_init_t) elink_54618se_config_init, .read_status = (read_status_t) elink_54618se_read_status, .link_reset = (link_reset_t) elink_54618se_link_reset, .config_loopback = (config_loopback_t) elink_54618se_config_loopback, .format_fw_ver = (format_fw_ver_t) NULL, .hw_reset = (hw_reset_t) NULL, .set_link_led = (set_link_led_t) elink_5461x_set_link_led, .phy_specific_func = (phy_specific_func_t) elink_54618se_specific_func }; /*****************************************************************/ /* */ /* Populate the phy according. Main function: elink_populate_phy */ /* */ /*****************************************************************/ static void elink_populate_preemphasis(struct bnx2x_softc *sc, uint32_t shmem_base, struct elink_phy *phy, uint8_t port, uint8_t phy_index) { /* Get the 4 lanes xgxs config rx and tx */ uint32_t rx = 0, tx = 0, i; for (i = 0; i < 2; i++) { /* INT_PHY and ELINK_EXT_PHY1 share the same value location in * the shmem. When num_phys is greater than 1, than this value * applies only to ELINK_EXT_PHY1 */ if (phy_index == ELINK_INT_PHY || phy_index == ELINK_EXT_PHY1) { rx = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. xgxs_config_rx[i << 1])); tx = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. xgxs_config_tx[i << 1])); } else { rx = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. xgxs_config2_rx[i << 1])); tx = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. xgxs_config2_rx[i << 1])); } phy->rx_preemphasis[i << 1] = ((rx >> 16) & 0xffff); phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff); phy->tx_preemphasis[i << 1] = ((tx >> 16) & 0xffff); phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff); } } static uint32_t elink_get_ext_phy_config(struct bnx2x_softc *sc, uint32_t shmem_base, uint8_t phy_index, uint8_t port) { uint32_t ext_phy_config = 0; switch (phy_index) { case ELINK_EXT_PHY1: ext_phy_config = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. external_phy_config)); break; case ELINK_EXT_PHY2: ext_phy_config = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. external_phy_config2)); break; default: PMD_DRV_LOG(DEBUG, "Invalid phy_index %d", phy_index); return ELINK_STATUS_ERROR; } return ext_phy_config; } static elink_status_t elink_populate_int_phy(struct bnx2x_softc *sc, uint32_t shmem_base, uint8_t port, struct elink_phy *phy) { uint32_t phy_addr; __rte_unused uint32_t chip_id; uint32_t switch_cfg = (REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info. port_feature_config[port]. link_config)) & PORT_FEATURE_CONNECTED_SWITCH_MASK); chip_id = (REG_RD(sc, MISC_REG_CHIP_NUM) << 16) | ((REG_RD(sc, MISC_REG_CHIP_REV) & 0xf) << 12); PMD_DRV_LOG(DEBUG, ":chip_id = 0x%x", chip_id); if (USES_WARPCORE(sc)) { uint32_t serdes_net_if; phy_addr = REG_RD(sc, MISC_REG_WC0_CTRL_PHY_ADDR); *phy = phy_warpcore; if (REG_RD(sc, MISC_REG_PORT4MODE_EN_OVWR) == 0x3) phy->flags |= ELINK_FLAGS_4_PORT_MODE; else phy->flags &= ~ELINK_FLAGS_4_PORT_MODE; /* Check Dual mode */ serdes_net_if = (REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. default_cfg)) & PORT_HW_CFG_NET_SERDES_IF_MASK); /* Set the appropriate supported and flags indications per * interface type of the chip */ switch (serdes_net_if) { case PORT_HW_CFG_NET_SERDES_IF_SGMII: phy->supported &= (ELINK_SUPPORTED_10baseT_Half | ELINK_SUPPORTED_10baseT_Full | ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); phy->media_type = ELINK_ETH_PHY_BASE_T; break; case PORT_HW_CFG_NET_SERDES_IF_XFI: phy->supported &= (ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); phy->media_type = ELINK_ETH_PHY_XFP_FIBER; break; case PORT_HW_CFG_NET_SERDES_IF_SFI: phy->supported &= (ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); phy->media_type = ELINK_ETH_PHY_SFPP_10G_FIBER; break; case PORT_HW_CFG_NET_SERDES_IF_KR: phy->media_type = ELINK_ETH_PHY_KR; phy->supported &= (ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); break; case PORT_HW_CFG_NET_SERDES_IF_DXGXS: phy->media_type = ELINK_ETH_PHY_KR; phy->flags |= ELINK_FLAGS_WC_DUAL_MODE; phy->supported &= (ELINK_SUPPORTED_20000baseMLD2_Full | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); break; case PORT_HW_CFG_NET_SERDES_IF_KR2: phy->media_type = ELINK_ETH_PHY_KR; phy->flags |= ELINK_FLAGS_WC_DUAL_MODE; phy->supported &= (ELINK_SUPPORTED_20000baseKR2_Full | ELINK_SUPPORTED_10000baseT_Full | ELINK_SUPPORTED_1000baseT_Full | ELINK_SUPPORTED_Autoneg | ELINK_SUPPORTED_FIBRE | ELINK_SUPPORTED_Pause | ELINK_SUPPORTED_Asym_Pause); phy->flags &= ~ELINK_FLAGS_TX_ERROR_CHECK; break; default: PMD_DRV_LOG(DEBUG, "Unknown WC interface type 0x%x", serdes_net_if); break; } /* Enable MDC/MDIO work-around for E3 A0 since free running MDC * was not set as expected. For B0, ECO will be enabled so there * won't be an issue there */ if (CHIP_REV(sc) == CHIP_REV_Ax) phy->flags |= ELINK_FLAGS_MDC_MDIO_WA; else phy->flags |= ELINK_FLAGS_MDC_MDIO_WA_B0; } else { switch (switch_cfg) { case ELINK_SWITCH_CFG_1G: phy_addr = REG_RD(sc, NIG_REG_SERDES0_CTRL_PHY_ADDR + port * 0x10); *phy = phy_serdes; break; case ELINK_SWITCH_CFG_10G: phy_addr = REG_RD(sc, NIG_REG_XGXS0_CTRL_PHY_ADDR + port * 0x18); *phy = phy_xgxs; break; default: PMD_DRV_LOG(DEBUG, "Invalid switch_cfg"); return ELINK_STATUS_ERROR; } } phy->addr = (uint8_t) phy_addr; phy->mdio_ctrl = elink_get_emac_base(sc, SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH, port); if (CHIP_IS_E2(sc)) phy->def_md_devad = ELINK_E2_DEFAULT_PHY_DEV_ADDR; else phy->def_md_devad = ELINK_DEFAULT_PHY_DEV_ADDR; PMD_DRV_LOG(DEBUG, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x", port, phy->addr, phy->mdio_ctrl); elink_populate_preemphasis(sc, shmem_base, phy, port, ELINK_INT_PHY); return ELINK_STATUS_OK; } static elink_status_t elink_populate_ext_phy(struct bnx2x_softc *sc, uint8_t phy_index, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port, struct elink_phy *phy) { uint32_t ext_phy_config, phy_type, config2; uint32_t mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH; ext_phy_config = elink_get_ext_phy_config(sc, shmem_base, phy_index, port); phy_type = ELINK_XGXS_EXT_PHY_TYPE(ext_phy_config); /* Select the phy type */ switch (phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8073: mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED; *phy = phy_8073; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8705: *phy = phy_8705; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8706: *phy = phy_8706; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726: mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1; *phy = phy_8726; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727_NOC: /* BNX2X8727_NOC => BNX2X8727 no over current */ mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1; *phy = phy_8727; phy->flags |= ELINK_FLAGS_NOC; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727: mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1; *phy = phy_8727; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8481: *phy = phy_8481; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84823: *phy = phy_84823; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833: *phy = phy_84833; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834: *phy = phy_84834; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54616: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE: *phy = phy_54618se; if (phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X54618SE) phy->flags |= ELINK_FLAGS_EEE; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: *phy = phy_7101; break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: *phy = phy_null; return ELINK_STATUS_ERROR; default: *phy = phy_null; /* In case external PHY wasn't found */ if ((phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && (phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) return ELINK_STATUS_ERROR; return ELINK_STATUS_OK; } phy->addr = ELINK_XGXS_EXT_PHY_ADDR(ext_phy_config); elink_populate_preemphasis(sc, shmem_base, phy, port, phy_index); /* The shmem address of the phy version is located on different * structures. In case this structure is too old, do not set * the address */ config2 = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info.shared_hw_config. config2)); if (phy_index == ELINK_EXT_PHY1) { phy->ver_addr = shmem_base + offsetof(struct shmem_region, port_mb[port]. ext_phy_fw_version); /* Check specific mdc mdio settings */ if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK) mdc_mdio_access = config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK; } else { uint32_t size = REG_RD(sc, shmem2_base); if (size > offsetof(struct shmem2_region, ext_phy_fw_version2)) { phy->ver_addr = shmem2_base + offsetof(struct shmem2_region, ext_phy_fw_version2[port]); } /* Check specific mdc mdio settings */ if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) mdc_mdio_access = (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >> (SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT - SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT); } phy->mdio_ctrl = elink_get_emac_base(sc, mdc_mdio_access, port); if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833) || (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834)) && (phy->ver_addr)) { /* Remove 100Mb link supported for BNX2X84833/4 when phy fw * version lower than or equal to 1.39 */ uint32_t raw_ver = REG_RD(sc, phy->ver_addr); if (((raw_ver & 0x7F) <= 39) && (((raw_ver & 0xF80) >> 7) <= 1)) phy->supported &= ~(ELINK_SUPPORTED_100baseT_Half | ELINK_SUPPORTED_100baseT_Full); } PMD_DRV_LOG(DEBUG, "phy_type 0x%x port %d found in index %d", phy_type, port, phy_index); PMD_DRV_LOG(DEBUG, " addr=0x%x, mdio_ctl=0x%x", phy->addr, phy->mdio_ctrl); return ELINK_STATUS_OK; } static elink_status_t elink_populate_phy(struct bnx2x_softc *sc, uint8_t phy_index, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port, struct elink_phy *phy) { elink_status_t status = ELINK_STATUS_OK; phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN; if (phy_index == ELINK_INT_PHY) return elink_populate_int_phy(sc, shmem_base, port, phy); status = elink_populate_ext_phy(sc, phy_index, shmem_base, shmem2_base, port, phy); return status; } static void elink_phy_def_cfg(struct elink_params *params, struct elink_phy *phy, uint8_t phy_index) { struct bnx2x_softc *sc = params->sc; uint32_t link_config; /* Populate the default phy configuration for MF mode */ if (phy_index == ELINK_EXT_PHY2) { link_config = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config [params->port].link_config2)); phy->speed_cap_mask = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config [params->port]. speed_capability_mask2)); } else { link_config = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_feature_config [params->port].link_config)); phy->speed_cap_mask = REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config [params->port]. speed_capability_mask)); } PMD_DRV_LOG(DEBUG, "Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x", phy_index, link_config, phy->speed_cap_mask); phy->req_duplex = DUPLEX_FULL; switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { case PORT_FEATURE_LINK_SPEED_10M_HALF: phy->req_duplex = DUPLEX_HALF; case PORT_FEATURE_LINK_SPEED_10M_FULL: phy->req_line_speed = ELINK_SPEED_10; break; case PORT_FEATURE_LINK_SPEED_100M_HALF: phy->req_duplex = DUPLEX_HALF; case PORT_FEATURE_LINK_SPEED_100M_FULL: phy->req_line_speed = ELINK_SPEED_100; break; case PORT_FEATURE_LINK_SPEED_1G: phy->req_line_speed = ELINK_SPEED_1000; break; case PORT_FEATURE_LINK_SPEED_2_5G: phy->req_line_speed = ELINK_SPEED_2500; break; case PORT_FEATURE_LINK_SPEED_10G_CX4: phy->req_line_speed = ELINK_SPEED_10000; break; default: phy->req_line_speed = ELINK_SPEED_AUTO_NEG; break; } switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) { case PORT_FEATURE_FLOW_CONTROL_AUTO: phy->req_flow_ctrl = ELINK_FLOW_CTRL_AUTO; break; case PORT_FEATURE_FLOW_CONTROL_TX: phy->req_flow_ctrl = ELINK_FLOW_CTRL_TX; break; case PORT_FEATURE_FLOW_CONTROL_RX: phy->req_flow_ctrl = ELINK_FLOW_CTRL_RX; break; case PORT_FEATURE_FLOW_CONTROL_BOTH: phy->req_flow_ctrl = ELINK_FLOW_CTRL_BOTH; break; default: phy->req_flow_ctrl = ELINK_FLOW_CTRL_NONE; break; } } uint32_t elink_phy_selection(struct elink_params *params) { uint32_t phy_config_swapped, prio_cfg; uint32_t return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT; phy_config_swapped = params->multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED; prio_cfg = params->multi_phy_config & PORT_HW_CFG_PHY_SELECTION_MASK; if (phy_config_swapped) { switch (prio_cfg) { case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY: return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY; break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY: return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY; break; case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY: return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY; break; case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY: return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY; break; } } else return_cfg = prio_cfg; return return_cfg; } elink_status_t elink_phy_probe(struct elink_params * params) { uint8_t phy_index, actual_phy_idx; uint32_t phy_config_swapped, sync_offset, media_types; struct bnx2x_softc *sc = params->sc; struct elink_phy *phy; params->num_phys = 0; PMD_DRV_LOG(DEBUG, "Begin phy probe"); #ifdef ELINK_INCLUDE_EMUL if (CHIP_REV_IS_EMUL(sc)) return ELINK_STATUS_OK; #endif phy_config_swapped = params->multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED; for (phy_index = ELINK_INT_PHY; phy_index < ELINK_MAX_PHYS; phy_index++) { actual_phy_idx = phy_index; if (phy_config_swapped) { if (phy_index == ELINK_EXT_PHY1) actual_phy_idx = ELINK_EXT_PHY2; else if (phy_index == ELINK_EXT_PHY2) actual_phy_idx = ELINK_EXT_PHY1; } PMD_DRV_LOG(DEBUG, "phy_config_swapped %x, phy_index %x," " actual_phy_idx %x", phy_config_swapped, phy_index, actual_phy_idx); phy = ¶ms->phy[actual_phy_idx]; if (elink_populate_phy(sc, phy_index, params->shmem_base, params->shmem2_base, params->port, phy) != ELINK_STATUS_OK) { params->num_phys = 0; PMD_DRV_LOG(DEBUG, "phy probe failed in phy index %d", phy_index); for (phy_index = ELINK_INT_PHY; phy_index < ELINK_MAX_PHYS; phy_index++) *phy = phy_null; return ELINK_STATUS_ERROR; } if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) break; if (params->feature_config_flags & ELINK_FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET) phy->flags &= ~ELINK_FLAGS_TX_ERROR_CHECK; if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_MT_SUPPORT)) phy->flags |= ELINK_FLAGS_MDC_MDIO_WA_G; sync_offset = params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port].media_type); media_types = REG_RD(sc, sync_offset); /* Update media type for non-PMF sync only for the first time * In case the media type changes afterwards, it will be updated * using the update_status function */ if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK << (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * actual_phy_idx))) == 0) { media_types |= ((phy->media_type & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) << (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * actual_phy_idx)); } REG_WR(sc, sync_offset, media_types); elink_phy_def_cfg(params, phy, phy_index); params->num_phys++; } PMD_DRV_LOG(DEBUG, "End phy probe. #phys found %x", params->num_phys); return ELINK_STATUS_OK; } #ifdef ELINK_INCLUDE_EMUL static elink_status_t elink_init_e3_emul_mac(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; vars->line_speed = params->req_line_speed[0]; /* In case link speed is auto, set speed the highest as possible */ if (params->req_line_speed[0] == ELINK_SPEED_AUTO_NEG) { if (params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC) vars->line_speed = ELINK_SPEED_2500; else if (elink_is_4_port_mode(sc)) vars->line_speed = ELINK_SPEED_10000; else vars->line_speed = ELINK_SPEED_20000; } if (vars->line_speed < ELINK_SPEED_10000) { if ((params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_UMAC)) { PMD_DRV_LOG(DEBUG, "Invalid line speed %d while UMAC is" " disabled!", params->req_line_speed[0]); return ELINK_STATUS_ERROR; } switch (vars->line_speed) { case ELINK_SPEED_10: vars->link_status = ELINK_LINK_10TFD; break; case ELINK_SPEED_100: vars->link_status = ELINK_LINK_100TXFD; break; case ELINK_SPEED_1000: vars->link_status = ELINK_LINK_1000TFD; break; case ELINK_SPEED_2500: vars->link_status = ELINK_LINK_2500TFD; break; default: PMD_DRV_LOG(DEBUG, "Invalid line speed %d for UMAC", vars->line_speed); return ELINK_STATUS_ERROR; } vars->link_status |= LINK_STATUS_LINK_UP; if (params->loopback_mode == ELINK_LOOPBACK_UMAC) elink_umac_enable(params, vars, 1); else elink_umac_enable(params, vars, 0); } else { /* Link speed >= 10000 requires XMAC enabled */ if (params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC) { PMD_DRV_LOG(DEBUG, "Invalid line speed %d while XMAC is" " disabled!", params->req_line_speed[0]); return ELINK_STATUS_ERROR; } /* Check link speed */ switch (vars->line_speed) { case ELINK_SPEED_10000: vars->link_status = ELINK_LINK_10GTFD; break; case ELINK_SPEED_20000: vars->link_status = ELINK_LINK_20GTFD; break; default: PMD_DRV_LOG(DEBUG, "Invalid line speed %d for XMAC", vars->line_speed); return ELINK_STATUS_ERROR; } vars->link_status |= LINK_STATUS_LINK_UP; if (params->loopback_mode == ELINK_LOOPBACK_XMAC) elink_xmac_enable(params, vars, 1); else elink_xmac_enable(params, vars, 0); } return ELINK_STATUS_OK; } static elink_status_t elink_init_emul(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; if (CHIP_IS_E3(sc)) { if (elink_init_e3_emul_mac(params, vars) != ELINK_STATUS_OK) return ELINK_STATUS_ERROR; } else { if (params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC) { vars->line_speed = ELINK_SPEED_1000; vars->link_status = (LINK_STATUS_LINK_UP | ELINK_LINK_1000XFD); if (params->loopback_mode == ELINK_LOOPBACK_EMAC) elink_emac_enable(params, vars, 1); else elink_emac_enable(params, vars, 0); } else { vars->line_speed = ELINK_SPEED_10000; vars->link_status = (LINK_STATUS_LINK_UP | ELINK_LINK_10GTFD); if (params->loopback_mode == ELINK_LOOPBACK_BMAC) elink_bmac_enable(params, vars, 1, 1); else elink_bmac_enable(params, vars, 0, 1); } } vars->link_up = 1; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; if (CHIP_IS_E1x(sc)) elink_pbf_update(params, vars->flow_ctrl, vars->line_speed); /* Disable drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); /* update shared memory */ elink_update_mng(params, vars->link_status); return ELINK_STATUS_OK; } #endif #ifdef ELINK_INCLUDE_FPGA static elink_status_t elink_init_fpga(struct elink_params *params, struct elink_vars *vars) { /* Enable on E1.5 FPGA */ struct bnx2x_softc *sc = params->sc; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->flow_ctrl = (ELINK_FLOW_CTRL_TX | ELINK_FLOW_CTRL_RX); vars->link_status |= (LINK_STATUS_TX_FLOW_CONTROL_ENABLED | LINK_STATUS_RX_FLOW_CONTROL_ENABLED); if (CHIP_IS_E3(sc)) { vars->line_speed = params->req_line_speed[0]; switch (vars->line_speed) { case ELINK_SPEED_AUTO_NEG: vars->line_speed = ELINK_SPEED_2500; case ELINK_SPEED_2500: vars->link_status = ELINK_LINK_2500TFD; break; case ELINK_SPEED_1000: vars->link_status = ELINK_LINK_1000XFD; break; case ELINK_SPEED_100: vars->link_status = ELINK_LINK_100TXFD; break; case ELINK_SPEED_10: vars->link_status = ELINK_LINK_10TFD; break; default: PMD_DRV_LOG(DEBUG, "Invalid link speed %d", params->req_line_speed[0]); return ELINK_STATUS_ERROR; } vars->link_status |= LINK_STATUS_LINK_UP; if (params->loopback_mode == ELINK_LOOPBACK_UMAC) elink_umac_enable(params, vars, 1); else elink_umac_enable(params, vars, 0); } else { vars->line_speed = ELINK_SPEED_10000; vars->link_status = (LINK_STATUS_LINK_UP | ELINK_LINK_10GTFD); if (params->loopback_mode == ELINK_LOOPBACK_EMAC) elink_emac_enable(params, vars, 1); else elink_emac_enable(params, vars, 0); } vars->link_up = 1; if (CHIP_IS_E1x(sc)) elink_pbf_update(params, vars->flow_ctrl, vars->line_speed); /* Disable drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); /* Update shared memory */ elink_update_mng(params, vars->link_status); return ELINK_STATUS_OK; } #endif static void elink_init_bmac_loopback(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; vars->link_up = 1; vars->line_speed = ELINK_SPEED_10000; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_BMAC; vars->phy_flags = PHY_XGXS_FLAG; elink_xgxs_deassert(params); /* Set bmac loopback */ elink_bmac_enable(params, vars, 1, 1); REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void elink_init_emac_loopback(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; vars->link_up = 1; vars->line_speed = ELINK_SPEED_1000; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_EMAC; vars->phy_flags = PHY_XGXS_FLAG; elink_xgxs_deassert(params); /* Set bmac loopback */ elink_emac_enable(params, vars, 1); elink_emac_program(params, vars); REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void elink_init_xmac_loopback(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; vars->link_up = 1; if (!params->req_line_speed[0]) vars->line_speed = ELINK_SPEED_10000; else vars->line_speed = params->req_line_speed[0]; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_XMAC; vars->phy_flags = PHY_XGXS_FLAG; /* Set WC to loopback mode since link is required to provide clock * to the XMAC in 20G mode */ elink_set_aer_mmd(params, ¶ms->phy[0]); elink_warpcore_reset_lane(sc, ¶ms->phy[0], 0); params->phy[ELINK_INT_PHY].config_loopback(¶ms->phy[ELINK_INT_PHY], params); elink_xmac_enable(params, vars, 1); REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void elink_init_umac_loopback(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; vars->link_up = 1; vars->line_speed = ELINK_SPEED_1000; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_UMAC; vars->phy_flags = PHY_XGXS_FLAG; elink_umac_enable(params, vars, 1); REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void elink_init_xgxs_loopback(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; struct elink_phy *int_phy = ¶ms->phy[ELINK_INT_PHY]; vars->link_up = 1; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->duplex = DUPLEX_FULL; if (params->req_line_speed[0] == ELINK_SPEED_1000) vars->line_speed = ELINK_SPEED_1000; else if ((params->req_line_speed[0] == ELINK_SPEED_20000) || (int_phy->flags & ELINK_FLAGS_WC_DUAL_MODE)) vars->line_speed = ELINK_SPEED_20000; else vars->line_speed = ELINK_SPEED_10000; if (!USES_WARPCORE(sc)) elink_xgxs_deassert(params); elink_link_initialize(params, vars); if (params->req_line_speed[0] == ELINK_SPEED_1000) { if (USES_WARPCORE(sc)) elink_umac_enable(params, vars, 0); else { elink_emac_program(params, vars); elink_emac_enable(params, vars, 0); } } else { if (USES_WARPCORE(sc)) elink_xmac_enable(params, vars, 0); else elink_bmac_enable(params, vars, 0, 1); } if (params->loopback_mode == ELINK_LOOPBACK_XGXS) { /* Set 10G XGXS loopback */ int_phy->config_loopback(int_phy, params); } else { /* Set external phy loopback */ uint8_t phy_index; for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys; phy_index++) if (params->phy[phy_index].config_loopback) params->phy[phy_index].config_loopback(¶ms-> phy [phy_index], params); } REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); elink_set_led(params, vars, ELINK_LED_MODE_OPER, vars->line_speed); } void elink_set_rx_filter(struct elink_params *params, uint8_t en) { struct bnx2x_softc *sc = params->sc; uint8_t val = en * 0x1F; /* Open / close the gate between the NIG and the BRB */ if (!CHIP_IS_E1x(sc)) val |= en * 0x20; REG_WR(sc, NIG_REG_LLH0_BRB1_DRV_MASK + params->port * 4, val); REG_WR(sc, NIG_REG_LLH0_BRB1_DRV_MASK_MF + params->port * 4, en * 0x3); REG_WR(sc, (params->port ? NIG_REG_LLH1_BRB1_NOT_MCP : NIG_REG_LLH0_BRB1_NOT_MCP), en); } static elink_status_t elink_avoid_link_flap(struct elink_params *params, struct elink_vars *vars) { uint32_t phy_idx; uint32_t dont_clear_stat, lfa_sts; struct bnx2x_softc *sc = params->sc; /* Sync the link parameters */ elink_link_status_update(params, vars); /* * The module verification was already done by previous link owner, * so this call is meant only to get warning message */ for (phy_idx = ELINK_INT_PHY; phy_idx < params->num_phys; phy_idx++) { struct elink_phy *phy = ¶ms->phy[phy_idx]; if (phy->phy_specific_func) { PMD_DRV_LOG(DEBUG, "Calling PHY specific func"); phy->phy_specific_func(phy, params, ELINK_PHY_INIT); } if ((phy->media_type == ELINK_ETH_PHY_SFPP_10G_FIBER) || (phy->media_type == ELINK_ETH_PHY_SFP_1G_FIBER) || (phy->media_type == ELINK_ETH_PHY_DA_TWINAX)) elink_verify_sfp_module(phy, params); } lfa_sts = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, lfa_sts)); dont_clear_stat = lfa_sts & SHMEM_LFA_DONT_CLEAR_STAT; /* Re-enable the NIG/MAC */ if (CHIP_IS_E3(sc)) { if (!dont_clear_stat) { REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_MSTAT0 << params->port)); REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, (MISC_REGISTERS_RESET_REG_2_MSTAT0 << params->port)); } if (vars->line_speed < ELINK_SPEED_10000) elink_umac_enable(params, vars, 0); else elink_xmac_enable(params, vars, 0); } else { if (vars->line_speed < ELINK_SPEED_10000) elink_emac_enable(params, vars, 0); else elink_bmac_enable(params, vars, 0, !dont_clear_stat); } /* Increment LFA count */ lfa_sts = ((lfa_sts & ~LINK_FLAP_AVOIDANCE_COUNT_MASK) | (((((lfa_sts & LINK_FLAP_AVOIDANCE_COUNT_MASK) >> LINK_FLAP_AVOIDANCE_COUNT_OFFSET) + 1) & 0xff) << LINK_FLAP_AVOIDANCE_COUNT_OFFSET)); /* Clear link flap reason */ lfa_sts &= ~LFA_LINK_FLAP_REASON_MASK; REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, lfa_sts), lfa_sts); /* Disable NIG DRAIN */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); /* Enable interrupts */ elink_link_int_enable(params); return ELINK_STATUS_OK; } static void elink_cannot_avoid_link_flap(struct elink_params *params, struct elink_vars *vars, int lfa_status) { uint32_t lfa_sts, cfg_idx, tmp_val; struct bnx2x_softc *sc = params->sc; elink_link_reset(params, vars, 1); if (!params->lfa_base) return; /* Store the new link parameters */ REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, req_duplex), params->req_duplex[0] | (params->req_duplex[1] << 16)); REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, req_flow_ctrl), params->req_flow_ctrl[0] | (params->req_flow_ctrl[1] << 16)); REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, req_line_speed), params->req_line_speed[0] | (params->req_line_speed[1] << 16)); for (cfg_idx = 0; cfg_idx < SHMEM_LINK_CONFIG_SIZE; cfg_idx++) { REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, speed_cap_mask[cfg_idx]), params->speed_cap_mask[cfg_idx]); } tmp_val = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, additional_config)); tmp_val &= ~REQ_FC_AUTO_ADV_MASK; tmp_val |= params->req_fc_auto_adv; REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, additional_config), tmp_val); lfa_sts = REG_RD(sc, params->lfa_base + offsetof(struct shmem_lfa, lfa_sts)); /* Clear the "Don't Clear Statistics" bit, and set reason */ lfa_sts &= ~SHMEM_LFA_DONT_CLEAR_STAT; /* Set link flap reason */ lfa_sts &= ~LFA_LINK_FLAP_REASON_MASK; lfa_sts |= ((lfa_status & LFA_LINK_FLAP_REASON_MASK) << LFA_LINK_FLAP_REASON_OFFSET); /* Increment link flap counter */ lfa_sts = ((lfa_sts & ~LINK_FLAP_COUNT_MASK) | (((((lfa_sts & LINK_FLAP_COUNT_MASK) >> LINK_FLAP_COUNT_OFFSET) + 1) & 0xff) << LINK_FLAP_COUNT_OFFSET)); REG_WR(sc, params->lfa_base + offsetof(struct shmem_lfa, lfa_sts), lfa_sts); /* Proceed with regular link initialization */ } elink_status_t elink_phy_init(struct elink_params *params, struct elink_vars *vars) { int lfa_status; struct bnx2x_softc *sc = params->sc; PMD_DRV_LOG(DEBUG, "Phy Initialization started"); PMD_DRV_LOG(DEBUG, "(1) req_speed %d, req_flowctrl %d", params->req_line_speed[0], params->req_flow_ctrl[0]); PMD_DRV_LOG(DEBUG, "(2) req_speed %d, req_flowctrl %d", params->req_line_speed[1], params->req_flow_ctrl[1]); PMD_DRV_LOG(DEBUG, "req_adv_flow_ctrl 0x%x", params->req_fc_auto_adv); vars->link_status = 0; vars->phy_link_up = 0; vars->link_up = 0; vars->line_speed = 0; vars->duplex = DUPLEX_FULL; vars->flow_ctrl = ELINK_FLOW_CTRL_NONE; vars->mac_type = ELINK_MAC_TYPE_NONE; vars->phy_flags = 0; vars->check_kr2_recovery_cnt = 0; params->link_flags = ELINK_PHY_INITIALIZED; /* Driver opens NIG-BRB filters */ elink_set_rx_filter(params, 1); /* Check if link flap can be avoided */ lfa_status = elink_check_lfa(params); if (lfa_status == 0) { PMD_DRV_LOG(DEBUG, "Link Flap Avoidance in progress"); return elink_avoid_link_flap(params, vars); } PMD_DRV_LOG(DEBUG, "Cannot avoid link flap lfa_sta=0x%x", lfa_status); elink_cannot_avoid_link_flap(params, vars, lfa_status); /* Disable attentions */ elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4, (ELINK_NIG_MASK_XGXS0_LINK_STATUS | ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); #ifdef ELINK_INCLUDE_EMUL if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC)) #endif elink_emac_init(params); if (params->feature_config_flags & ELINK_FEATURE_CONFIG_PFC_ENABLED) vars->link_status |= LINK_STATUS_PFC_ENABLED; if ((params->num_phys == 0) && !CHIP_REV_IS_SLOW(sc)) { PMD_DRV_LOG(DEBUG, "No phy found for initialization !!"); return ELINK_STATUS_ERROR; } set_phy_vars(params, vars); PMD_DRV_LOG(DEBUG, "Num of phys on board: %d", params->num_phys); #ifdef ELINK_INCLUDE_FPGA if (CHIP_REV_IS_FPGA(sc)) { return elink_init_fpga(params, vars); } else #endif #ifdef ELINK_INCLUDE_EMUL if (CHIP_REV_IS_EMUL(sc)) { return elink_init_emul(params, vars); } else #endif switch (params->loopback_mode) { case ELINK_LOOPBACK_BMAC: elink_init_bmac_loopback(params, vars); break; case ELINK_LOOPBACK_EMAC: elink_init_emac_loopback(params, vars); break; case ELINK_LOOPBACK_XMAC: elink_init_xmac_loopback(params, vars); break; case ELINK_LOOPBACK_UMAC: elink_init_umac_loopback(params, vars); break; case ELINK_LOOPBACK_XGXS: case ELINK_LOOPBACK_EXT_PHY: elink_init_xgxs_loopback(params, vars); break; default: if (!CHIP_IS_E3(sc)) { if (params->switch_cfg == ELINK_SWITCH_CFG_10G) elink_xgxs_deassert(params); else elink_serdes_deassert(sc, params->port); } elink_link_initialize(params, vars); DELAY(1000 * 30); elink_link_int_enable(params); break; } elink_update_mng(params, vars->link_status); elink_update_mng_eee(params, vars->eee_status); return ELINK_STATUS_OK; } static elink_status_t elink_link_reset(struct elink_params *params, struct elink_vars *vars, uint8_t reset_ext_phy) { struct bnx2x_softc *sc = params->sc; uint8_t phy_index, port = params->port, clear_latch_ind = 0; PMD_DRV_LOG(DEBUG, "Resetting the link of port %d", port); /* Disable attentions */ vars->link_status = 0; elink_update_mng(params, vars->link_status); vars->eee_status &= ~(SHMEM_EEE_LP_ADV_STATUS_MASK | SHMEM_EEE_ACTIVE_BIT); elink_update_mng_eee(params, vars->eee_status); elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port * 4, (ELINK_NIG_MASK_XGXS0_LINK_STATUS | ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); /* Activate nig drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + port * 4, 1); /* Disable nig egress interface */ if (!CHIP_IS_E3(sc)) { REG_WR(sc, NIG_REG_BMAC0_OUT_EN + port * 4, 0); REG_WR(sc, NIG_REG_EGRESS_EMAC0_OUT_EN + port * 4, 0); } #ifdef ELINK_INCLUDE_EMUL /* Stop BigMac rx */ if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC)) #endif if (!CHIP_IS_E3(sc)) elink_set_bmac_rx(sc, port, 0); #ifdef ELINK_INCLUDE_EMUL /* Stop XMAC/UMAC rx */ if (!(params->feature_config_flags & ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC)) #endif if (CHIP_IS_E3(sc) && !CHIP_REV_IS_FPGA(sc)) { elink_set_xmac_rxtx(params, 0); elink_set_umac_rxtx(params, 0); } /* Disable emac */ if (!CHIP_IS_E3(sc)) REG_WR(sc, NIG_REG_NIG_EMAC0_EN + port * 4, 0); DELAY(1000 * 10); /* The PHY reset is controlled by GPIO 1 * Hold it as vars low */ /* Clear link led */ elink_set_mdio_emac_per_phy(sc, params); elink_set_led(params, vars, ELINK_LED_MODE_OFF, 0); if (reset_ext_phy && (!CHIP_REV_IS_SLOW(sc))) { for (phy_index = ELINK_EXT_PHY1; phy_index < params->num_phys; phy_index++) { if (params->phy[phy_index].link_reset) { elink_set_aer_mmd(params, ¶ms->phy[phy_index]); params->phy[phy_index].link_reset(¶ms-> phy [phy_index], params); } if (params->phy[phy_index].flags & ELINK_FLAGS_REARM_LATCH_SIGNAL) clear_latch_ind = 1; } } if (clear_latch_ind) { /* Clear latching indication */ elink_rearm_latch_signal(sc, port, 0); elink_bits_dis(sc, NIG_REG_LATCH_BC_0 + port * 4, 1 << ELINK_NIG_LATCH_BC_ENABLE_MI_INT); } #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) if (!CHIP_REV_IS_SLOW(sc)) #endif if (params->phy[ELINK_INT_PHY].link_reset) params->phy[ELINK_INT_PHY].link_reset(¶ms-> phy [ELINK_INT_PHY], params); /* Disable nig ingress interface */ if (!CHIP_IS_E3(sc)) { /* Reset BigMac */ REG_WR(sc, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); REG_WR(sc, NIG_REG_BMAC0_IN_EN + port * 4, 0); REG_WR(sc, NIG_REG_EMAC0_IN_EN + port * 4, 0); } else { uint32_t xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; elink_set_xumac_nig(params, 0, 0); if (REG_RD(sc, MISC_REG_RESET_REG_2) & MISC_REGISTERS_RESET_REG_2_XMAC) REG_WR(sc, xmac_base + XMAC_REG_CTRL, XMAC_CTRL_REG_SOFT_RESET); } vars->link_up = 0; vars->phy_flags = 0; return ELINK_STATUS_OK; } elink_status_t elink_lfa_reset(struct elink_params * params, struct elink_vars * vars) { struct bnx2x_softc *sc = params->sc; vars->link_up = 0; vars->phy_flags = 0; params->link_flags &= ~ELINK_PHY_INITIALIZED; if (!params->lfa_base) return elink_link_reset(params, vars, 1); /* * Activate NIG drain so that during this time the device won't send * anything while it is unable to response. */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 1); /* * Close gracefully the gate from BMAC to NIG such that no half packets * are passed. */ if (!CHIP_IS_E3(sc)) elink_set_bmac_rx(sc, params->port, 0); if (CHIP_IS_E3(sc)) { elink_set_xmac_rxtx(params, 0); elink_set_umac_rxtx(params, 0); } /* Wait 10ms for the pipe to clean up */ DELAY(1000 * 10); /* Clean the NIG-BRB using the network filters in a way that will * not cut a packet in the middle. */ elink_set_rx_filter(params, 0); /* * Re-open the gate between the BMAC and the NIG, after verifying the * gate to the BRB is closed, otherwise packets may arrive to the * firmware before driver had initialized it. The target is to achieve * minimum management protocol down time. */ if (!CHIP_IS_E3(sc)) elink_set_bmac_rx(sc, params->port, 1); if (CHIP_IS_E3(sc)) { elink_set_xmac_rxtx(params, 1); elink_set_umac_rxtx(params, 1); } /* Disable NIG drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); return ELINK_STATUS_OK; } /****************************************************************************/ /* Common function */ /****************************************************************************/ static elink_status_t elink_8073_common_init_phy(struct bnx2x_softc *sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint8_t phy_index, __rte_unused uint32_t chip_id) { struct elink_phy phy[PORT_MAX]; struct elink_phy *phy_blk[PORT_MAX]; uint16_t val; int8_t port = 0; int8_t port_of_path = 0; uint32_t swap_val, swap_override; swap_val = REG_RD(sc, NIG_REG_PORT_SWAP); swap_override = REG_RD(sc, NIG_REG_STRAP_OVERRIDE); port ^= (swap_val && swap_override); elink_ext_phy_hw_reset(sc, port); /* PART1 - Reset both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { uint32_t shmem_base, shmem2_base; /* In E2, same phy is using for port0 of the two paths */ if (CHIP_IS_E1x(sc)) { shmem_base = shmem_base_path[0]; shmem2_base = shmem2_base_path[0]; port_of_path = port; } else { shmem_base = shmem_base_path[port]; shmem2_base = shmem2_base_path[port]; port_of_path = 0; } /* Extract the ext phy address for the port */ if (elink_populate_phy(sc, phy_index, shmem_base, shmem2_base, port_of_path, &phy[port]) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "populate_phy failed"); return ELINK_STATUS_ERROR; } /* Disable attentions */ elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port_of_path * 4, (ELINK_NIG_MASK_XGXS0_LINK_STATUS | ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); /* Need to take the phy out of low power mode in order * to write to access its registers */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); /* Reset the phy */ elink_cl45_write(sc, &phy[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1 << 15); } /* Add delay of 150ms after reset */ DELAY(1000 * 150); if (phy[PORT_0].addr & 0x1) { phy_blk[PORT_0] = &(phy[PORT_1]); phy_blk[PORT_1] = &(phy[PORT_0]); } else { phy_blk[PORT_0] = &(phy[PORT_0]); phy_blk[PORT_1] = &(phy[PORT_1]); } /* PART2 - Download firmware to both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { if (CHIP_IS_E1x(sc)) port_of_path = port; else port_of_path = 0; PMD_DRV_LOG(DEBUG, "Loading spirom for phy address 0x%x", phy_blk[port]->addr); if (elink_8073_8727_external_rom_boot(sc, phy_blk[port], port_of_path)) return ELINK_STATUS_ERROR; /* Only set bit 10 = 1 (Tx power down) */ elink_cl45_read(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_POWER_DOWN, &val); /* Phase1 of TX_POWER_DOWN reset */ elink_cl45_write(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_POWER_DOWN, (val | 1 << 10)); } /* Toggle Transmitter: Power down and then up with 600ms delay * between */ DELAY(1000 * 600); /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { /* Phase2 of POWER_DOWN_RESET */ /* Release bit 10 (Release Tx power down) */ elink_cl45_read(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_POWER_DOWN, &val); elink_cl45_write(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1 << 10)))); DELAY(1000 * 15); /* Read modify write the SPI-ROM version select register */ elink_cl45_read(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN, &val); elink_cl45_write(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1 << 12))); /* set GPIO2 back to LOW */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_2, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); } return ELINK_STATUS_OK; } static elink_status_t elink_8726_common_init_phy(struct bnx2x_softc *sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint8_t phy_index, __rte_unused uint32_t chip_id) { uint32_t val; int8_t port; struct elink_phy phy; /* Use port1 because of the static port-swap */ /* Enable the module detection interrupt */ val = REG_RD(sc, MISC_REG_GPIO_EVENT_EN); val |= ((1 << MISC_REGISTERS_GPIO_3) | (1 << (MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); REG_WR(sc, MISC_REG_GPIO_EVENT_EN, val); elink_ext_phy_hw_reset(sc, 0); DELAY(1000 * 5); for (port = 0; port < PORT_MAX; port++) { uint32_t shmem_base, shmem2_base; /* In E2, same phy is using for port0 of the two paths */ if (CHIP_IS_E1x(sc)) { shmem_base = shmem_base_path[0]; shmem2_base = shmem2_base_path[0]; } else { shmem_base = shmem_base_path[port]; shmem2_base = shmem2_base_path[port]; } /* Extract the ext phy address for the port */ if (elink_populate_phy(sc, phy_index, shmem_base, shmem2_base, port, &phy) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "populate phy failed"); return ELINK_STATUS_ERROR; } /* Reset phy */ elink_cl45_write(sc, &phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001); /* Set fault module detected LED on */ elink_cb_gpio_write(sc, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_HIGH, port); } return ELINK_STATUS_OK; } static void elink_get_ext_phy_reset_gpio(struct bnx2x_softc *sc, uint32_t shmem_base, uint8_t * io_gpio, uint8_t * io_port) { uint32_t phy_gpio_reset = REG_RD(sc, shmem_base + offsetof(struct shmem_region, dev_info. port_hw_config[PORT_0]. default_cfg)); switch (phy_gpio_reset) { case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0: *io_gpio = 0; *io_port = 0; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0: *io_gpio = 1; *io_port = 0; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0: *io_gpio = 2; *io_port = 0; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0: *io_gpio = 3; *io_port = 0; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1: *io_gpio = 0; *io_port = 1; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1: *io_gpio = 1; *io_port = 1; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1: *io_gpio = 2; *io_port = 1; break; case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1: *io_gpio = 3; *io_port = 1; break; default: /* Don't override the io_gpio and io_port */ break; } } static elink_status_t elink_8727_common_init_phy(struct bnx2x_softc *sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint8_t phy_index, __rte_unused uint32_t chip_id) { int8_t port, reset_gpio; uint32_t swap_val, swap_override; struct elink_phy phy[PORT_MAX]; struct elink_phy *phy_blk[PORT_MAX]; int8_t port_of_path; swap_val = REG_RD(sc, NIG_REG_PORT_SWAP); swap_override = REG_RD(sc, NIG_REG_STRAP_OVERRIDE); reset_gpio = MISC_REGISTERS_GPIO_1; port = 1; /* Retrieve the reset gpio/port which control the reset. * Default is GPIO1, PORT1 */ elink_get_ext_phy_reset_gpio(sc, shmem_base_path[0], (uint8_t *) & reset_gpio, (uint8_t *) & port); /* Calculate the port based on port swap */ port ^= (swap_val && swap_override); /* Initiate PHY reset */ elink_cb_gpio_write(sc, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW, port); DELAY(1000 * 1); elink_cb_gpio_write(sc, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); DELAY(1000 * 5); /* PART1 - Reset both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { uint32_t shmem_base, shmem2_base; /* In E2, same phy is using for port0 of the two paths */ if (CHIP_IS_E1x(sc)) { shmem_base = shmem_base_path[0]; shmem2_base = shmem2_base_path[0]; port_of_path = port; } else { shmem_base = shmem_base_path[port]; shmem2_base = shmem2_base_path[port]; port_of_path = 0; } /* Extract the ext phy address for the port */ if (elink_populate_phy(sc, phy_index, shmem_base, shmem2_base, port_of_path, &phy[port]) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "populate phy failed"); return ELINK_STATUS_ERROR; } /* disable attentions */ elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + port_of_path * 4, (ELINK_NIG_MASK_XGXS0_LINK_STATUS | ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); /* Reset the phy */ elink_cl45_write(sc, &phy[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1 << 15); } /* Add delay of 150ms after reset */ DELAY(1000 * 150); if (phy[PORT_0].addr & 0x1) { phy_blk[PORT_0] = &(phy[PORT_1]); phy_blk[PORT_1] = &(phy[PORT_0]); } else { phy_blk[PORT_0] = &(phy[PORT_0]); phy_blk[PORT_1] = &(phy[PORT_1]); } /* PART2 - Download firmware to both phys */ for (port = PORT_MAX - 1; port >= PORT_0; port--) { if (CHIP_IS_E1x(sc)) port_of_path = port; else port_of_path = 0; PMD_DRV_LOG(DEBUG, "Loading spirom for phy address 0x%x", phy_blk[port]->addr); if (elink_8073_8727_external_rom_boot(sc, phy_blk[port], port_of_path)) return ELINK_STATUS_ERROR; /* Disable PHY transmitter output */ elink_cl45_write(sc, phy_blk[port], MDIO_PMA_DEVAD, MDIO_PMA_REG_TX_DISABLE, 1); } return ELINK_STATUS_OK; } static elink_status_t elink_84833_common_init_phy(struct bnx2x_softc *sc, uint32_t shmem_base_path[], __rte_unused uint32_t shmem2_base_path[], __rte_unused uint8_t phy_index, uint32_t chip_id) { uint8_t reset_gpios; reset_gpios = elink_84833_get_reset_gpios(sc, shmem_base_path, chip_id); elink_cb_gpio_mult_write(sc, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW); DELAY(10); elink_cb_gpio_mult_write(sc, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH); PMD_DRV_LOG(DEBUG, "84833 reset pulse on pin values 0x%x", reset_gpios); return ELINK_STATUS_OK; } static elink_status_t elink_ext_phy_common_init(struct bnx2x_softc *sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint8_t phy_index, uint32_t ext_phy_type, uint32_t chip_id) { elink_status_t rc = ELINK_STATUS_OK; switch (ext_phy_type) { case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8073: rc = elink_8073_common_init_phy(sc, shmem_base_path, shmem2_base_path, phy_index, chip_id); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8722: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8727_NOC: rc = elink_8727_common_init_phy(sc, shmem_base_path, shmem2_base_path, phy_index, chip_id); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726: /* GPIO1 affects both ports, so there's need to pull * it for single port alone */ rc = elink_8726_common_init_phy(sc, shmem_base_path, shmem2_base_path, phy_index, chip_id); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84833: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X84834: /* GPIO3's are linked, and so both need to be toggled * to obtain required 2us pulse. */ rc = elink_84833_common_init_phy(sc, shmem_base_path, shmem2_base_path, phy_index, chip_id); break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: rc = ELINK_STATUS_ERROR; break; default: PMD_DRV_LOG(DEBUG, "ext_phy 0x%x common init not required", ext_phy_type); break; } if (rc != ELINK_STATUS_OK) elink_cb_event_log(sc, ELINK_LOG_ID_PHY_UNINITIALIZED, 0); // "Warning: PHY was not initialized," // " Port %d", return rc; } elink_status_t elink_common_init_phy(struct bnx2x_softc * sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint32_t chip_id, __rte_unused uint8_t one_port_enabled) { elink_status_t rc = ELINK_STATUS_OK; uint32_t phy_ver, val; uint8_t phy_index = 0; uint32_t ext_phy_type, ext_phy_config; #if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) if (CHIP_REV_IS_EMUL(sc) || CHIP_REV_IS_FPGA(sc)) return ELINK_STATUS_OK; #endif elink_set_mdio_clk(sc, GRCBASE_EMAC0); elink_set_mdio_clk(sc, GRCBASE_EMAC1); PMD_DRV_LOG(DEBUG, "Begin common phy init"); if (CHIP_IS_E3(sc)) { /* Enable EPIO */ val = REG_RD(sc, MISC_REG_GEN_PURP_HWG); REG_WR(sc, MISC_REG_GEN_PURP_HWG, val | 1); } /* Check if common init was already done */ phy_ver = REG_RD(sc, shmem_base_path[0] + offsetof(struct shmem_region, port_mb[PORT_0].ext_phy_fw_version)); if (phy_ver) { PMD_DRV_LOG(DEBUG, "Not doing common init; phy ver is 0x%x", phy_ver); return ELINK_STATUS_OK; } /* Read the ext_phy_type for arbitrary port(0) */ for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS; phy_index++) { ext_phy_config = elink_get_ext_phy_config(sc, shmem_base_path[0], phy_index, 0); ext_phy_type = ELINK_XGXS_EXT_PHY_TYPE(ext_phy_config); rc |= elink_ext_phy_common_init(sc, shmem_base_path, shmem2_base_path, phy_index, ext_phy_type, chip_id); } return rc; } static void elink_check_over_curr(struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint32_t cfg_pin; uint8_t port = params->port; uint32_t pin_val; cfg_pin = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port]. e3_cmn_pin_cfg1)) & PORT_HW_CFG_E3_OVER_CURRENT_MASK) >> PORT_HW_CFG_E3_OVER_CURRENT_SHIFT; /* Ignore check if no external input PIN available */ if (elink_get_cfg_pin(sc, cfg_pin, &pin_val) != ELINK_STATUS_OK) return; if (!pin_val) { if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) { elink_cb_event_log(sc, ELINK_LOG_ID_OVER_CURRENT, params->port); //"Error: Power fault on Port %d has" // " been detected and the power to " // "that SFP+ module has been removed" // " to prevent failure of the card." // " Please remove the SFP+ module and" // " restart the system to clear this" // " error.", vars->phy_flags |= PHY_OVER_CURRENT_FLAG; elink_warpcore_power_module(params, 0); } } else vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG; } /* Returns 0 if no change occured since last check; 1 otherwise. */ static uint8_t elink_analyze_link_error(struct elink_params *params, struct elink_vars *vars, uint32_t status, uint32_t phy_flag, uint32_t link_flag, uint8_t notify) { struct bnx2x_softc *sc = params->sc; /* Compare new value with previous value */ uint8_t led_mode; uint32_t old_status = (vars->phy_flags & phy_flag) ? 1 : 0; if ((status ^ old_status) == 0) return 0; /* If values differ */ switch (phy_flag) { case PHY_HALF_OPEN_CONN_FLAG: PMD_DRV_LOG(DEBUG, "Analyze Remote Fault"); break; case PHY_SFP_TX_FAULT_FLAG: PMD_DRV_LOG(DEBUG, "Analyze TX Fault"); break; default: PMD_DRV_LOG(DEBUG, "Analyze UNKNOWN"); } PMD_DRV_LOG(DEBUG, "Link changed:[%x %x]->%x", vars->link_up, old_status, status); /* a. Update shmem->link_status accordingly * b. Update elink_vars->link_up */ if (status) { vars->link_status &= ~LINK_STATUS_LINK_UP; vars->link_status |= link_flag; vars->link_up = 0; vars->phy_flags |= phy_flag; /* activate nig drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 1); /* Set LED mode to off since the PHY doesn't know about these * errors */ led_mode = ELINK_LED_MODE_OFF; } else { vars->link_status |= LINK_STATUS_LINK_UP; vars->link_status &= ~link_flag; vars->link_up = 1; vars->phy_flags &= ~phy_flag; led_mode = ELINK_LED_MODE_OPER; /* Clear nig drain */ REG_WR(sc, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } elink_sync_link(params, vars); /* Update the LED according to the link state */ elink_set_led(params, vars, led_mode, ELINK_SPEED_10000); /* Update link status in the shared memory */ elink_update_mng(params, vars->link_status); /* C. Trigger General Attention */ vars->periodic_flags |= ELINK_PERIODIC_FLAGS_LINK_EVENT; if (notify) elink_cb_notify_link_changed(sc); return 1; } /****************************************************************************** * Description: * This function checks for half opened connection change indication. * When such change occurs, it calls the elink_analyze_link_error * to check if Remote Fault is set or cleared. Reception of remote fault * status message in the MAC indicates that the peer's MAC has detected * a fault, for example, due to break in the TX side of fiber. * ******************************************************************************/ static elink_status_t elink_check_half_open_conn(struct elink_params *params, struct elink_vars *vars, uint8_t notify) { struct bnx2x_softc *sc = params->sc; uint32_t lss_status = 0; uint32_t mac_base; /* In case link status is physically up @ 10G do */ if (((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0) || (REG_RD(sc, NIG_REG_EGRESS_EMAC0_PORT + params->port * 4))) return ELINK_STATUS_OK; if (CHIP_IS_E3(sc) && (REG_RD(sc, MISC_REG_RESET_REG_2) & (MISC_REGISTERS_RESET_REG_2_XMAC))) { /* Check E3 XMAC */ /* Note that link speed cannot be queried here, since it may be * zero while link is down. In case UMAC is active, LSS will * simply not be set */ mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0; /* Clear stick bits (Requires rising edge) */ REG_WR(sc, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0); REG_WR(sc, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS | XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS); if (REG_RD(sc, mac_base + XMAC_REG_RX_LSS_STATUS)) lss_status = 1; elink_analyze_link_error(params, vars, lss_status, PHY_HALF_OPEN_CONN_FLAG, LINK_STATUS_NONE, notify); } else if (REG_RD(sc, MISC_REG_RESET_REG_2) & (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) { /* Check E1X / E2 BMAC */ uint32_t lss_status_reg; uint32_t wb_data[2]; mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM : NIG_REG_INGRESS_BMAC0_MEM; /* Read BIGMAC_REGISTER_RX_LSS_STATUS */ if (CHIP_IS_E2(sc)) lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT; else lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS; REG_RD_DMAE(sc, mac_base + lss_status_reg, wb_data, 2); lss_status = (wb_data[0] > 0); elink_analyze_link_error(params, vars, lss_status, PHY_HALF_OPEN_CONN_FLAG, LINK_STATUS_NONE, notify); } return ELINK_STATUS_OK; } static void elink_sfp_tx_fault_detection(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars) { struct bnx2x_softc *sc = params->sc; uint32_t cfg_pin, value = 0; uint8_t led_change, port = params->port; /* Get The SFP+ TX_Fault controlling pin ([eg]pio) */ cfg_pin = (REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info. port_hw_config [port]. e3_cmn_pin_cfg)) & PORT_HW_CFG_E3_TX_FAULT_MASK) >> PORT_HW_CFG_E3_TX_FAULT_SHIFT; if (elink_get_cfg_pin(sc, cfg_pin, &value)) { PMD_DRV_LOG(DEBUG, "Failed to read pin 0x%02x", cfg_pin); return; } led_change = elink_analyze_link_error(params, vars, value, PHY_SFP_TX_FAULT_FLAG, LINK_STATUS_SFP_TX_FAULT, 1); if (led_change) { /* Change TX_Fault led, set link status for further syncs */ uint8_t led_mode; if (vars->phy_flags & PHY_SFP_TX_FAULT_FLAG) { led_mode = MISC_REGISTERS_GPIO_HIGH; vars->link_status |= LINK_STATUS_SFP_TX_FAULT; } else { led_mode = MISC_REGISTERS_GPIO_LOW; vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT; } /* If module is unapproved, led should be on regardless */ if (!(phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED)) { PMD_DRV_LOG(DEBUG, "Change TX_Fault LED: ->%x", led_mode); elink_set_e3_module_fault_led(params, led_mode); } } } static void elink_kr2_recovery(struct elink_params *params, struct elink_vars *vars, struct elink_phy *phy) { PMD_DRV_LOG(DEBUG, "KR2 recovery"); elink_warpcore_enable_AN_KR2(phy, params, vars); elink_warpcore_restart_AN_KR(phy, params); } static void elink_check_kr2_wa(struct elink_params *params, struct elink_vars *vars, struct elink_phy *phy) { struct bnx2x_softc *sc = params->sc; uint16_t base_page, next_page, not_kr2_device, lane; int sigdet; /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery * Since some switches tend to reinit the AN process and clear the * the advertised BP/NP after ~2 seconds causing the KR2 to be disabled * and recovered many times */ if (vars->check_kr2_recovery_cnt > 0) { vars->check_kr2_recovery_cnt--; return; } sigdet = elink_warpcore_get_sigdet(phy, params); if (!sigdet) { if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { elink_kr2_recovery(params, vars, phy); PMD_DRV_LOG(DEBUG, "No sigdet"); } return; } lane = elink_get_warpcore_lane(params); CL22_WR_OVER_CL45(sc, phy, MDIO_REG_BANK_AER_BLOCK, MDIO_AER_BLOCK_AER_REG, lane); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG, &base_page); elink_cl45_read(sc, phy, MDIO_AN_DEVAD, MDIO_AN_REG_LP_AUTO_NEG2, &next_page); elink_set_aer_mmd(params, phy); /* CL73 has not begun yet */ if (base_page == 0) { if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { elink_kr2_recovery(params, vars, phy); PMD_DRV_LOG(DEBUG, "No BP"); } return; } /* In case NP bit is not set in the BasePage, or it is set, * but only KX is advertised, declare this link partner as non-KR2 * device. */ not_kr2_device = (((base_page & 0x8000) == 0) || (((base_page & 0x8000) && ((next_page & 0xe0) == 0x2)))); /* In case KR2 is already disabled, check if we need to re-enable it */ if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) { if (!not_kr2_device) { PMD_DRV_LOG(DEBUG, "BP=0x%x, NP=0x%x", base_page, next_page); elink_kr2_recovery(params, vars, phy); } return; } /* KR2 is enabled, but not KR2 device */ if (not_kr2_device) { /* Disable KR2 on both lanes */ PMD_DRV_LOG(DEBUG, "BP=0x%x, NP=0x%x", base_page, next_page); elink_disable_kr2(params, vars, phy); /* Restart AN on leading lane */ elink_warpcore_restart_AN_KR(phy, params); return; } } void elink_period_func(struct elink_params *params, struct elink_vars *vars) { uint16_t phy_idx; struct bnx2x_softc *sc = params->sc; for (phy_idx = ELINK_INT_PHY; phy_idx < ELINK_MAX_PHYS; phy_idx++) { if (params->phy[phy_idx].flags & ELINK_FLAGS_TX_ERROR_CHECK) { elink_set_aer_mmd(params, ¶ms->phy[phy_idx]); if (elink_check_half_open_conn(params, vars, 1) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "Fault detection failed"); } break; } } if (CHIP_IS_E3(sc)) { struct elink_phy *phy = ¶ms->phy[ELINK_INT_PHY]; elink_set_aer_mmd(params, phy); if ((phy->supported & ELINK_SUPPORTED_20000baseKR2_Full) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) elink_check_kr2_wa(params, vars, phy); elink_check_over_curr(params, vars); if (vars->rx_tx_asic_rst) elink_warpcore_config_runtime(phy, params, vars); if ((REG_RD(sc, params->shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[params->port]. default_cfg)) & PORT_HW_CFG_NET_SERDES_IF_MASK) == PORT_HW_CFG_NET_SERDES_IF_SFI) { if (elink_is_sfp_module_plugged(params)) { elink_sfp_tx_fault_detection(phy, params, vars); } else if (vars->link_status & LINK_STATUS_SFP_TX_FAULT) { /* Clean trail, interrupt corrects the leds */ vars->link_status &= ~LINK_STATUS_SFP_TX_FAULT; vars->phy_flags &= ~PHY_SFP_TX_FAULT_FLAG; /* Update link status in the shared memory */ elink_update_mng(params, vars->link_status); } } } } uint8_t elink_fan_failure_det_req(struct bnx2x_softc *sc, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port) { uint8_t phy_index, fan_failure_det_req = 0; struct elink_phy phy; for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS; phy_index++) { if (elink_populate_phy(sc, phy_index, shmem_base, shmem2_base, port, &phy) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "populate phy failed"); return 0; } fan_failure_det_req |= (phy.flags & ELINK_FLAGS_FAN_FAILURE_DET_REQ); } return fan_failure_det_req; } void elink_hw_reset_phy(struct elink_params *params) { uint8_t phy_index; struct bnx2x_softc *sc = params->sc; elink_update_mng(params, 0); elink_bits_dis(sc, NIG_REG_MASK_INTERRUPT_PORT0 + params->port * 4, (ELINK_NIG_MASK_XGXS0_LINK_STATUS | ELINK_NIG_MASK_XGXS0_LINK10G | ELINK_NIG_MASK_SERDES0_LINK_STATUS | ELINK_NIG_MASK_MI_INT)); for (phy_index = ELINK_INT_PHY; phy_index < ELINK_MAX_PHYS; phy_index++) { if (params->phy[phy_index].hw_reset) { params->phy[phy_index].hw_reset(¶ms->phy[phy_index], params); params->phy[phy_index] = phy_null; } } } void elink_init_mod_abs_int(struct bnx2x_softc *sc, struct elink_vars *vars, __rte_unused uint32_t chip_id, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port) { uint8_t gpio_num = 0xff, gpio_port = 0xff, phy_index; uint32_t val; uint32_t offset, aeu_mask, swap_val, swap_override, sync_offset; if (CHIP_IS_E3(sc)) { if (elink_get_mod_abs_int_cfg(sc, shmem_base, port, &gpio_num, &gpio_port) != ELINK_STATUS_OK) return; } else { struct elink_phy phy; for (phy_index = ELINK_EXT_PHY1; phy_index < ELINK_MAX_PHYS; phy_index++) { if (elink_populate_phy(sc, phy_index, shmem_base, shmem2_base, port, &phy) != ELINK_STATUS_OK) { PMD_DRV_LOG(DEBUG, "populate phy failed"); return; } if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BNX2X8726) { gpio_num = MISC_REGISTERS_GPIO_3; gpio_port = port; break; } } } if (gpio_num == 0xff) return; /* Set GPIO3 to trigger SFP+ module insertion/removal */ elink_cb_gpio_write(sc, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port); swap_val = REG_RD(sc, NIG_REG_PORT_SWAP); swap_override = REG_RD(sc, NIG_REG_STRAP_OVERRIDE); gpio_port ^= (swap_val && swap_override); vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 << (gpio_num + (gpio_port << 2)); sync_offset = shmem_base + offsetof(struct shmem_region, dev_info.port_hw_config[port].aeu_int_mask); REG_WR(sc, sync_offset, vars->aeu_int_mask); PMD_DRV_LOG(DEBUG, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x", gpio_num, gpio_port, vars->aeu_int_mask); if (port == 0) offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0; else offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0; /* Open appropriate AEU for interrupts */ aeu_mask = REG_RD(sc, offset); aeu_mask |= vars->aeu_int_mask; REG_WR(sc, offset, aeu_mask); /* Enable the GPIO to trigger interrupt */ val = REG_RD(sc, MISC_REG_GPIO_EVENT_EN); val |= 1 << (gpio_num + (gpio_port << 2)); REG_WR(sc, MISC_REG_GPIO_EVENT_EN, val); } ================================================ FILE: drivers/net/bnx2x/elink.h ================================================ /*- * Copyright (c) 2007-2013 QLogic Corporation. All rights reserved. * * Eric Davis * David Christensen * Gary Zambrano * * Copyright (c) 2013-2015 Brocade Communications Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Broadcom Corporation nor the name of its contributors * may be used to endorse or promote products derived from this software * without specific prior written consent. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ELINK_H #define ELINK_H #define ELINK_DEBUG /***********************************************************/ /* CLC Call backs functions */ /***********************************************************/ /* CLC device structure */ struct bnx2x_softc; extern uint32_t elink_cb_reg_read(struct bnx2x_softc *sc, uint32_t reg_addr); extern void elink_cb_reg_write(struct bnx2x_softc *sc, uint32_t reg_addr, uint32_t val); /* mode - 0( LOW ) /1(HIGH)*/ extern uint8_t elink_cb_gpio_write(struct bnx2x_softc *sc, uint16_t gpio_num, uint8_t mode, uint8_t port); extern uint8_t elink_cb_gpio_mult_write(struct bnx2x_softc *sc, uint8_t pins, uint8_t mode); extern uint32_t elink_cb_gpio_read(struct bnx2x_softc *sc, uint16_t gpio_num, uint8_t port); extern uint8_t elink_cb_gpio_int_write(struct bnx2x_softc *sc, uint16_t gpio_num, uint8_t mode, uint8_t port); extern uint32_t elink_cb_fw_command(struct bnx2x_softc *sc, uint32_t command, uint32_t param); /* This function is called every 1024 bytes downloading of phy firmware. Driver can use it to print to screen indication for download progress */ extern void elink_cb_download_progress(struct bnx2x_softc *sc, uint32_t cur, uint32_t total); /* Each log type has its own parameters */ typedef enum elink_log_id { ELINK_LOG_ID_UNQUAL_IO_MODULE = 0, /* uint8_t port, const char* vendor_name, const char* vendor_pn */ ELINK_LOG_ID_OVER_CURRENT = 1, /* uint8_t port */ ELINK_LOG_ID_PHY_UNINITIALIZED = 2, /* uint8_t port */ ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT= 3, /* No params */ ELINK_LOG_ID_NON_10G_MODULE = 4, /* uint8_t port */ }elink_log_id_t; typedef enum elink_status { ELINK_STATUS_OK = 0, ELINK_STATUS_ERROR, ELINK_STATUS_TIMEOUT, ELINK_STATUS_NO_LINK, ELINK_STATUS_INVALID_IMAGE, ELINK_OP_NOT_SUPPORTED = 122 } elink_status_t; extern void elink_cb_event_log(struct bnx2x_softc *sc, const elink_log_id_t log_id, ...); extern void elink_cb_load_warpcore_microcode(void); extern void elink_cb_notify_link_changed(struct bnx2x_softc *sc); #define ELINK_EVENT_LOG_LEVEL_ERROR 1 #define ELINK_EVENT_LOG_LEVEL_WARNING 2 #define ELINK_EVENT_ID_SFP_UNQUALIFIED_MODULE 1 #define ELINK_EVENT_ID_SFP_POWER_FAULT 2 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) /* Debug prints */ /***********************************************************/ /* Defines */ /***********************************************************/ #define ELINK_DEFAULT_PHY_DEV_ADDR 3 #define ELINK_E2_DEFAULT_PHY_DEV_ADDR 5 #define DUPLEX_FULL 1 #define DUPLEX_HALF 2 #define ELINK_FLOW_CTRL_AUTO PORT_FEATURE_FLOW_CONTROL_AUTO #define ELINK_FLOW_CTRL_TX PORT_FEATURE_FLOW_CONTROL_TX #define ELINK_FLOW_CTRL_RX PORT_FEATURE_FLOW_CONTROL_RX #define ELINK_FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH #define ELINK_FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE #define ELINK_NET_SERDES_IF_XFI 1 #define ELINK_NET_SERDES_IF_SFI 2 #define ELINK_NET_SERDES_IF_KR 3 #define ELINK_NET_SERDES_IF_DXGXS 4 #define ELINK_SPEED_AUTO_NEG 0 #define ELINK_SPEED_10 10 #define ELINK_SPEED_100 100 #define ELINK_SPEED_1000 1000 #define ELINK_SPEED_2500 2500 #define ELINK_SPEED_10000 10000 #define ELINK_SPEED_20000 20000 #define ELINK_I2C_DEV_ADDR_A0 0xa0 #define ELINK_I2C_DEV_ADDR_A2 0xa2 #define ELINK_SFP_EEPROM_PAGE_SIZE 16 #define ELINK_SFP_EEPROM_VENDOR_NAME_ADDR 0x14 #define ELINK_SFP_EEPROM_VENDOR_NAME_SIZE 16 #define ELINK_SFP_EEPROM_VENDOR_OUI_ADDR 0x25 #define ELINK_SFP_EEPROM_VENDOR_OUI_SIZE 3 #define ELINK_SFP_EEPROM_PART_NO_ADDR 0x28 #define ELINK_SFP_EEPROM_PART_NO_SIZE 16 #define ELINK_SFP_EEPROM_REVISION_ADDR 0x38 #define ELINK_SFP_EEPROM_REVISION_SIZE 4 #define ELINK_SFP_EEPROM_SERIAL_ADDR 0x44 #define ELINK_SFP_EEPROM_SERIAL_SIZE 16 #define ELINK_SFP_EEPROM_DATE_ADDR 0x54 /* ASCII YYMMDD */ #define ELINK_SFP_EEPROM_DATE_SIZE 6 #define ELINK_SFP_EEPROM_DIAG_TYPE_ADDR 0x5c #define ELINK_SFP_EEPROM_DIAG_TYPE_SIZE 1 #define ELINK_SFP_EEPROM_DIAG_ADDR_CHANGE_REQ (1<<2) #define ELINK_SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e #define ELINK_SFP_EEPROM_SFF_8472_COMP_SIZE 1 #define ELINK_SFP_EEPROM_A2_CHECKSUM_RANGE 0x5e #define ELINK_SFP_EEPROM_A2_CC_DMI_ADDR 0x5f #define ELINK_PWR_FLT_ERR_MSG_LEN 250 #define ELINK_XGXS_EXT_PHY_TYPE(ext_phy_config) \ ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK) #define ELINK_XGXS_EXT_PHY_ADDR(ext_phy_config) \ (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT) #define ELINK_SERDES_EXT_PHY_TYPE(ext_phy_config) \ ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) /* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */ #define ELINK_SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1) /* Single Media board contains single external phy */ #define ELINK_SINGLE_MEDIA(params) (params->num_phys == 2) /* Dual Media board contains two external phy with different media */ #define ELINK_DUAL_MEDIA(params) (params->num_phys == 3) #define ELINK_FW_PARAM_PHY_ADDR_MASK 0x000000FF #define ELINK_FW_PARAM_PHY_TYPE_MASK 0x0000FF00 #define ELINK_FW_PARAM_MDIO_CTRL_MASK 0xFFFF0000 #define ELINK_FW_PARAM_MDIO_CTRL_OFFSET 16 #define ELINK_FW_PARAM_PHY_ADDR(fw_param) (fw_param & \ ELINK_FW_PARAM_PHY_ADDR_MASK) #define ELINK_FW_PARAM_PHY_TYPE(fw_param) (fw_param & \ ELINK_FW_PARAM_PHY_TYPE_MASK) #define ELINK_FW_PARAM_MDIO_CTRL(fw_param) ((fw_param & \ ELINK_FW_PARAM_MDIO_CTRL_MASK) >> \ ELINK_FW_PARAM_MDIO_CTRL_OFFSET) #define ELINK_FW_PARAM_SET(phy_addr, phy_type, mdio_access) \ (phy_addr | phy_type | mdio_access << ELINK_FW_PARAM_MDIO_CTRL_OFFSET) #define ELINK_PFC_BRB_FULL_LB_XOFF_THRESHOLD 170 #define ELINK_PFC_BRB_FULL_LB_XON_THRESHOLD 250 #define ELINK_MAXVAL(a, b) (((a) > (b)) ? (a) : (b)) #define ELINK_BMAC_CONTROL_RX_ENABLE 2 /***********************************************************/ /* Structs */ /***********************************************************/ #define ELINK_INT_PHY 0 #define ELINK_EXT_PHY1 1 #define ELINK_EXT_PHY2 2 #define ELINK_MAX_PHYS 3 /* Same configuration is shared between the XGXS and the first external phy */ #define ELINK_LINK_CONFIG_SIZE (ELINK_MAX_PHYS - 1) #define ELINK_LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == ELINK_INT_PHY) ? \ 0 : (_phy_idx - 1)) /***********************************************************/ /* elink_phy struct */ /* Defines the required arguments and function per phy */ /***********************************************************/ struct elink_vars; struct elink_params; struct elink_phy; typedef uint8_t (*config_init_t)(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars); typedef uint8_t (*read_status_t)(struct elink_phy *phy, struct elink_params *params, struct elink_vars *vars); typedef void (*link_reset_t)(struct elink_phy *phy, struct elink_params *params); typedef void (*config_loopback_t)(struct elink_phy *phy, struct elink_params *params); typedef uint8_t (*format_fw_ver_t)(uint32_t raw, uint8_t *str, uint16_t *len); typedef void (*hw_reset_t)(struct elink_phy *phy, struct elink_params *params); typedef void (*set_link_led_t)(struct elink_phy *phy, struct elink_params *params, uint8_t mode); typedef void (*phy_specific_func_t)(struct elink_phy *phy, struct elink_params *params, uint32_t action); struct elink_reg_set { uint8_t devad; uint16_t reg; uint16_t val; }; struct elink_phy { uint32_t type; /* Loaded during init */ uint8_t addr; uint8_t def_md_devad; uint16_t flags; /* No Over-Current detection */ #define ELINK_FLAGS_NOC (1<<1) /* Fan failure detection required */ #define ELINK_FLAGS_FAN_FAILURE_DET_REQ (1<<2) /* Initialize first the XGXS and only then the phy itself */ #define ELINK_FLAGS_INIT_XGXS_FIRST (1<<3) #define ELINK_FLAGS_WC_DUAL_MODE (1<<4) #define ELINK_FLAGS_4_PORT_MODE (1<<5) #define ELINK_FLAGS_REARM_LATCH_SIGNAL (1<<6) #define ELINK_FLAGS_SFP_NOT_APPROVED (1<<7) #define ELINK_FLAGS_MDC_MDIO_WA (1<<8) #define ELINK_FLAGS_DUMMY_READ (1<<9) #define ELINK_FLAGS_MDC_MDIO_WA_B0 (1<<10) #define ELINK_FLAGS_SFP_MODULE_PLUGGED_IN_WC (1<<11) #define ELINK_FLAGS_TX_ERROR_CHECK (1<<12) #define ELINK_FLAGS_EEE (1<<13) #define ELINK_FLAGS_TEMPERATURE (1<<14) #define ELINK_FLAGS_MDC_MDIO_WA_G (1<<15) /* preemphasis values for the rx side */ uint16_t rx_preemphasis[4]; /* preemphasis values for the tx side */ uint16_t tx_preemphasis[4]; /* EMAC address for access MDIO */ uint32_t mdio_ctrl; uint32_t supported; #define ELINK_SUPPORTED_10baseT_Half (1<<0) #define ELINK_SUPPORTED_10baseT_Full (1<<1) #define ELINK_SUPPORTED_100baseT_Half (1<<2) #define ELINK_SUPPORTED_100baseT_Full (1<<3) #define ELINK_SUPPORTED_1000baseT_Full (1<<4) #define ELINK_SUPPORTED_2500baseX_Full (1<<5) #define ELINK_SUPPORTED_10000baseT_Full (1<<6) #define ELINK_SUPPORTED_TP (1<<7) #define ELINK_SUPPORTED_FIBRE (1<<8) #define ELINK_SUPPORTED_Autoneg (1<<9) #define ELINK_SUPPORTED_Pause (1<<10) #define ELINK_SUPPORTED_Asym_Pause (1<<11) #define ELINK_SUPPORTED_20000baseMLD2_Full (1<<21) #define ELINK_SUPPORTED_20000baseKR2_Full (1<<22) uint32_t media_type; #define ELINK_ETH_PHY_UNSPECIFIED 0x0 #define ELINK_ETH_PHY_SFPP_10G_FIBER 0x1 #define ELINK_ETH_PHY_XFP_FIBER 0x2 #define ELINK_ETH_PHY_DA_TWINAX 0x3 #define ELINK_ETH_PHY_BASE_T 0x4 #define ELINK_ETH_PHY_SFP_1G_FIBER 0x5 #define ELINK_ETH_PHY_KR 0xf0 #define ELINK_ETH_PHY_CX4 0xf1 #define ELINK_ETH_PHY_NOT_PRESENT 0xff /* The address in which version is located*/ uint32_t ver_addr; uint16_t req_flow_ctrl; uint16_t req_line_speed; uint32_t speed_cap_mask; uint16_t req_duplex; uint16_t rsrv; /* Called per phy/port init, and it configures LASI, speed, autoneg, duplex, flow control negotiation, etc. */ config_init_t config_init; /* Called due to interrupt. It determines the link, speed */ read_status_t read_status; /* Called when driver is unloading. Should reset the phy */ link_reset_t link_reset; /* Set the loopback configuration for the phy */ config_loopback_t config_loopback; /* Format the given raw number into str up to len */ format_fw_ver_t format_fw_ver; /* Reset the phy (both ports) */ hw_reset_t hw_reset; /* Set link led mode (on/off/oper)*/ set_link_led_t set_link_led; /* PHY Specific tasks */ phy_specific_func_t phy_specific_func; #define ELINK_DISABLE_TX 1 #define ELINK_ENABLE_TX 2 #define ELINK_PHY_INIT 3 }; /* Inputs parameters to the CLC */ struct elink_params { uint8_t port; /* Default / User Configuration */ uint8_t loopback_mode; #define ELINK_LOOPBACK_NONE 0 #define ELINK_LOOPBACK_EMAC 1 #define ELINK_LOOPBACK_BMAC 2 #define ELINK_LOOPBACK_XGXS 3 #define ELINK_LOOPBACK_EXT_PHY 4 #define ELINK_LOOPBACK_EXT 5 #define ELINK_LOOPBACK_UMAC 6 #define ELINK_LOOPBACK_XMAC 7 /* Device parameters */ uint8_t mac_addr[6]; uint16_t req_duplex[ELINK_LINK_CONFIG_SIZE]; uint16_t req_flow_ctrl[ELINK_LINK_CONFIG_SIZE]; uint16_t req_line_speed[ELINK_LINK_CONFIG_SIZE]; /* Also determine AutoNeg */ /* shmem parameters */ uint32_t shmem_base; uint32_t shmem2_base; uint32_t speed_cap_mask[ELINK_LINK_CONFIG_SIZE]; uint32_t switch_cfg; #define ELINK_SWITCH_CFG_1G PORT_FEATURE_CON_SWITCH_1G_SWITCH #define ELINK_SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH #define ELINK_SWITCH_CFG_AUTO_DETECT PORT_FEATURE_CON_SWITCH_AUTO_DETECT uint32_t lane_config; /* Phy register parameter */ uint32_t chip_id; /* features */ uint32_t feature_config_flags; #define ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0) #define ELINK_FEATURE_CONFIG_PFC_ENABLED (1<<1) #define ELINK_FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) #define ELINK_FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY (1<<3) #define ELINK_FEATURE_CONFIG_EMUL_DISABLE_EMAC (1<<4) #define ELINK_FEATURE_CONFIG_EMUL_DISABLE_BMAC (1<<5) #define ELINK_FEATURE_CONFIG_EMUL_DISABLE_UMAC (1<<6) #define ELINK_FEATURE_CONFIG_EMUL_DISABLE_XMAC (1<<7) #define ELINK_FEATURE_CONFIG_BC_SUPPORTS_AFEX (1<<8) #define ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED (1<<9) #define ELINK_FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED (1<<10) #define ELINK_FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET (1<<11) #define ELINK_FEATURE_CONFIG_IEEE_PHY_TEST (1<<12) #define ELINK_FEATURE_CONFIG_MT_SUPPORT (1<<13) #define ELINK_FEATURE_CONFIG_BOOT_FROM_SAN (1<<14) /* Will be populated during common init */ struct elink_phy phy[ELINK_MAX_PHYS]; /* Will be populated during common init */ uint8_t num_phys; uint8_t rsrv; /* Used to configure the EEE Tx LPI timer, has several modes of * operation, according to bits 29:28 - * 2'b00: Timer will be configured by nvram, output will be the value * from nvram. * 2'b01: Timer will be configured by nvram, output will be in * microseconds. * 2'b10: bits 1:0 contain an nvram value which will be used instead * of the one located in the nvram. Output will be that value. * 2'b11: bits 19:0 contain the idle timer in microseconds; output * will be in microseconds. * Bits 31:30 should be 2'b11 in order for EEE to be enabled. */ uint32_t eee_mode; #define ELINK_EEE_MODE_NVRAM_BALANCED_TIME (0xa00) #define ELINK_EEE_MODE_NVRAM_AGGRESSIVE_TIME (0x100) #define ELINK_EEE_MODE_NVRAM_LATENCY_TIME (0x6000) #define ELINK_EEE_MODE_NVRAM_MASK (0x3) #define ELINK_EEE_MODE_TIMER_MASK (0xfffff) #define ELINK_EEE_MODE_OUTPUT_TIME (1<<28) #define ELINK_EEE_MODE_OVERRIDE_NVRAM (1<<29) #define ELINK_EEE_MODE_ENABLE_LPI (1<<30) #define ELINK_EEE_MODE_ADV_LPI (1<<31) uint16_t hw_led_mode; /* part of the hw_config read from the shmem */ uint32_t multi_phy_config; /* Device pointer passed to all callback functions */ struct bnx2x_softc *sc; uint16_t req_fc_auto_adv; /* Should be set to TX / BOTH when req_flow_ctrl is set to AUTO */ uint16_t link_flags; #define ELINK_LINK_FLAGS_INT_DISABLED (1<<0) #define ELINK_PHY_INITIALIZED (1<<1) uint32_t lfa_base; }; /* Output parameters */ struct elink_vars { uint8_t phy_flags; #define PHY_XGXS_FLAG (1<<0) #define PHY_SGMII_FLAG (1<<1) #define PHY_PHYSICAL_LINK_FLAG (1<<2) #define PHY_HALF_OPEN_CONN_FLAG (1<<3) #define PHY_OVER_CURRENT_FLAG (1<<4) #define PHY_SFP_TX_FAULT_FLAG (1<<5) uint8_t mac_type; #define ELINK_MAC_TYPE_NONE 0 #define ELINK_MAC_TYPE_EMAC 1 #define ELINK_MAC_TYPE_BMAC 2 #define ELINK_MAC_TYPE_UMAC 3 #define ELINK_MAC_TYPE_XMAC 4 uint8_t phy_link_up; /* internal phy link indication */ uint8_t link_up; uint16_t line_speed; uint16_t duplex; uint16_t flow_ctrl; uint16_t ieee_fc; /* The same definitions as the shmem parameter */ uint32_t link_status; uint32_t eee_status; uint8_t fault_detected; uint8_t check_kr2_recovery_cnt; #define ELINK_CHECK_KR2_RECOVERY_CNT 5 uint16_t periodic_flags; #define ELINK_PERIODIC_FLAGS_LINK_EVENT 0x0001 uint32_t aeu_int_mask; uint8_t rx_tx_asic_rst; uint8_t turn_to_run_wc_rt; uint16_t rsrv2; /* The same definitions as the shmem2 parameter */ uint32_t link_attr_sync; }; /***********************************************************/ /* Functions */ /***********************************************************/ elink_status_t elink_phy_init(struct elink_params *params, struct elink_vars *vars); /* Reset the link. Should be called when driver or interface goes down Before calling phy firmware upgrade, the reset_ext_phy should be set to 0 */ elink_status_t elink_lfa_reset(struct elink_params *params, struct elink_vars *vars); /* elink_link_update should be called upon link interrupt */ elink_status_t elink_link_update(struct elink_params *params, struct elink_vars *vars); /* Reads the link_status from the shmem, and update the link vars accordingly */ void elink_link_status_update(struct elink_params *input, struct elink_vars *output); /* Set/Unset the led Basically, the CLC takes care of the led for the link, but in case one needs to set/unset the led unnaturally, set the "mode" to ELINK_LED_MODE_OPER to blink the led, and ELINK_LED_MODE_OFF to set the led off.*/ elink_status_t elink_set_led(struct elink_params *params, struct elink_vars *vars, uint8_t mode, uint32_t speed); #define ELINK_LED_MODE_OFF 0 #define ELINK_LED_MODE_ON 1 #define ELINK_LED_MODE_OPER 2 #define ELINK_LED_MODE_FRONT_PANEL_OFF 3 /* elink_handle_module_detect_int should be called upon module detection interrupt */ void elink_handle_module_detect_int(struct elink_params *params); /* One-time initialization for external phy after power up */ elink_status_t elink_common_init_phy(struct bnx2x_softc *sc, uint32_t shmem_base_path[], uint32_t shmem2_base_path[], uint32_t chip_id, uint8_t one_port_enabled); void elink_hw_reset_phy(struct elink_params *params); /* Check swap bit and adjust PHY order */ uint32_t elink_phy_selection(struct elink_params *params); /* Probe the phys on board, and populate them in "params" */ elink_status_t elink_phy_probe(struct elink_params *params); /* Checks if fan failure detection is required on one of the phys on board */ uint8_t elink_fan_failure_det_req(struct bnx2x_softc *sc, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port); /* Open / close the gate between the NIG and the BRB */ void elink_set_rx_filter(struct elink_params *params, uint8_t en); /* DCBX structs */ /* Number of maximum COS per chip */ #define ELINK_DCBX_E2E3_MAX_NUM_COS (2) #define ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0 (6) #define ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1 (3) #define ELINK_DCBX_E3B0_MAX_NUM_COS ( \ ELINK_MAXVAL(ELINK_DCBX_E3B0_MAX_NUM_COS_PORT0, \ ELINK_DCBX_E3B0_MAX_NUM_COS_PORT1)) #define ELINK_DCBX_MAX_NUM_COS ( \ ELINK_MAXVAL(ELINK_DCBX_E3B0_MAX_NUM_COS, \ ELINK_DCBX_E2E3_MAX_NUM_COS)) /* PFC port configuration params */ struct elink_nig_brb_pfc_port_params { /* NIG */ uint32_t pause_enable; uint32_t llfc_out_en; uint32_t llfc_enable; uint32_t pkt_priority_to_cos; uint8_t num_of_rx_cos_priority_mask; uint32_t rx_cos_priority_mask[ELINK_DCBX_MAX_NUM_COS]; uint32_t llfc_high_priority_classes; uint32_t llfc_low_priority_classes; }; /* ETS port configuration params */ struct elink_ets_bw_params { uint8_t bw; }; struct elink_ets_sp_params { /** * valid values are 0 - 5. 0 is highest strict priority. * There can't be two COS's with the same pri. */ uint8_t pri; }; enum elink_cos_state { elink_cos_state_strict = 0, elink_cos_state_bw = 1, }; struct elink_ets_cos_params { enum elink_cos_state state ; union { struct elink_ets_bw_params bw_params; struct elink_ets_sp_params sp_params; } params; }; struct elink_ets_params { uint8_t num_of_cos; /* Number of valid COS entries*/ struct elink_ets_cos_params cos[ELINK_DCBX_MAX_NUM_COS]; }; /* Used to update the PFC attributes in EMAC, BMAC, NIG and BRB * when link is already up */ elink_status_t elink_update_pfc(struct elink_params *params, struct elink_vars *vars, struct elink_nig_brb_pfc_port_params *pfc_params); void elink_init_mod_abs_int(struct bnx2x_softc *sc, struct elink_vars *vars, uint32_t chip_id, uint32_t shmem_base, uint32_t shmem2_base, uint8_t port); void elink_period_func(struct elink_params *params, struct elink_vars *vars); void elink_enable_pmd_tx(struct elink_params *params); #endif /* ELINK_H */ ================================================ FILE: drivers/net/bonding/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_bond.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_eth_bond_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_api.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_pmd.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_args.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_8023ad.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += rte_eth_bond_alb.c # # Export include files # SYMLINK-y-include += rte_eth_bond.h SYMLINK-y-include += rte_eth_bond_8023ad.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += lib/librte_kvargs include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/bonding/rte_eth_bond.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_BOND_H_ #define _RTE_ETH_BOND_H_ /** * @file rte_eth_bond.h * * RTE Link Bonding Ethernet Device * Link Bonding for 1GbE and 10GbE ports to allow the aggregation of multiple * (slave) NICs into a single logical interface. The bonded device processes * these interfaces based on the mode of operation specified and supported. * This implementation supports 4 modes of operation round robin, active backup * balance and broadcast. Providing redundant links, fault tolerance and/or * load balancing of network ports */ #ifdef __cplusplus extern "C" { #endif #include /* Supported modes of operation of link bonding library */ #define BONDING_MODE_ROUND_ROBIN (0) /**< Round Robin (Mode 0). * In this mode all transmitted packets will be balanced equally across all * active slaves of the bonded in a round robin fashion. */ #define BONDING_MODE_ACTIVE_BACKUP (1) /**< Active Backup (Mode 1). * In this mode all packets transmitted will be transmitted on the primary * slave until such point as the primary slave is no longer available and then * transmitted packets will be sent on the next available slaves. The primary * slave can be defined by the user but defaults to the first active slave * available if not specified. */ #define BONDING_MODE_BALANCE (2) /**< Balance (Mode 2). * In this mode all packets transmitted will be balanced across the available * slaves using one of three available transmit policies - l2, l2+3 or l3+4. * See BALANCE_XMIT_POLICY macros definitions for further details on transmit * policies. */ #define BONDING_MODE_BROADCAST (3) /**< Broadcast (Mode 3). * In this mode all transmitted packets will be transmitted on all available * active slaves of the bonded. */ #define BONDING_MODE_8023AD (4) /**< 802.3AD (Mode 4). * * This mode provides auto negotiation/configuration * of peers and well as link status changes monitoring using out of band * LACP (link aggregation control protocol) messages. For further details of * LACP specification see the IEEE 802.3ad/802.1AX standards. It is also * described here * https://www.kernel.org/doc/Documentation/networking/bonding.txt. * * Important Usage Notes: * - for LACP mode to work the rx/tx burst functions must be invoked * at least once every 100ms, otherwise the out-of-band LACP messages will not * be handled with the expected latency and this may cause the link status to be * incorrectly marked as down or failure to correctly negotiate with peers. * - For optimal performance during initial handshaking the array of mbufs provided * to rx_burst should be at least 2 times the slave count size. * */ #define BONDING_MODE_TLB (5) /**< Adaptive TLB (Mode 5) * This mode provides an adaptive transmit load balancing. It dynamically * changes the transmitting slave, according to the computed load. Statistics * are collected in 100ms intervals and scheduled every 10ms */ #define BONDING_MODE_ALB (6) /**< Adaptive Load Balancing (Mode 6) * This mode includes adaptive TLB and receive load balancing (RLB). In RLB the * bonding driver intercepts ARP replies send by local system and overwrites its * source MAC address, so that different peers send data to the server on * different slave interfaces. When local system sends ARP request, it saves IP * information from it. When ARP reply from that peer is received, its MAC is * stored, one of slave MACs assigned and ARP reply send to that peer. */ /* Balance Mode Transmit Policies */ #define BALANCE_XMIT_POLICY_LAYER2 (0) /**< Layer 2 (Ethernet MAC) */ #define BALANCE_XMIT_POLICY_LAYER23 (1) /**< Layer 2+3 (Ethernet MAC + IP Addresses) transmit load balancing */ #define BALANCE_XMIT_POLICY_LAYER34 (2) /**< Layer 3+4 (IP Addresses + UDP Ports) transmit load balancing */ /** * Create a bonded rte_eth_dev device * * @param name Name of new link bonding device. * @param mode Mode to initialize bonding device in. * @param socket_id Socket Id on which to allocate eth_dev resources. * * @return * Port Id of created rte_eth_dev on success, negative value otherwise */ int rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id); /** * Free a bonded rte_eth_dev device * * @param name Name of the link bonding device. * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_free(const char *name); /** * Add a rte_eth_dev device as a slave to the bonded device * * @param bonded_port_id Port ID of bonded device. * @param slave_port_id Port ID of slave device. * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id); /** * Remove a slave rte_eth_dev device from the bonded device * * @param bonded_port_id Port ID of bonded device. * @param slave_port_id Port ID of slave device. * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id); /** * Set link bonding mode of bonded device * * @param bonded_port_id Port ID of bonded device. * @param mode Bonding mode to set * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_mode_set(uint8_t bonded_port_id, uint8_t mode); /** * Get link bonding mode of bonded device * * @param bonded_port_id Port ID of bonded device. * * @return * link bonding mode on success, negative value otherwise */ int rte_eth_bond_mode_get(uint8_t bonded_port_id); /** * Set slave rte_eth_dev as primary slave of bonded device * * @param bonded_port_id Port ID of bonded device. * @param slave_port_id Port ID of slave device. * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id); /** * Get primary slave of bonded device * * @param bonded_port_id Port ID of bonded device. * * @return * Port Id of primary slave on success, -1 on failure */ int rte_eth_bond_primary_get(uint8_t bonded_port_id); /** * Populate an array with list of the slaves port id's of the bonded device * * @param bonded_port_id Port ID of bonded eth_dev to interrogate * @param slaves Array to be populated with the current active slaves * @param len Length of slaves array * * @return * Number of slaves associated with bonded device on success, * negative value otherwise */ int rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len); /** * Populate an array with list of the active slaves port id's of the bonded * device. * * @param bonded_port_id Port ID of bonded eth_dev to interrogate * @param slaves Array to be populated with the current active slaves * @param len Length of slaves array * * @return * Number of active slaves associated with bonded device on success, * negative value otherwise */ int rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len); /** * Set explicit MAC address to use on bonded device and it's slaves. * * @param bonded_port_id Port ID of bonded device. * @param mac_addr MAC Address to use on bonded device overriding * slaves MAC addresses * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_mac_address_set(uint8_t bonded_port_id, struct ether_addr *mac_addr); /** * Reset bonded device to use MAC from primary slave on bonded device and it's * slaves. * * @param bonded_port_id Port ID of bonded device. * * @return * 0 on success, negative value otherwise */ int rte_eth_bond_mac_address_reset(uint8_t bonded_port_id); /** * Set the transmit policy for bonded device to use when it is operating in * balance mode, this parameter is otherwise ignored in other modes of * operation. * * @param bonded_port_id Port ID of bonded device. * @param policy Balance mode transmission policy. * * @return * 0 on success, negative value otherwise. */ int rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy); /** * Get the transmit policy set on bonded device for balance mode operation * * @param bonded_port_id Port ID of bonded device. * * @return * Balance transmit policy on success, negative value otherwise. */ int rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id); /** * Set the link monitoring frequency (in ms) for monitoring the link status of * slave devices * * @param bonded_port_id Port ID of bonded device. * @param internal_ms Monitoring interval in milliseconds * * @return * 0 on success, negative value otherwise. */ int rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms); /** * Get the current link monitoring frequency (in ms) for monitoring of the link * status of slave devices * * @param bonded_port_id Port ID of bonded device. * * @return * Monitoring interval on success, negative value otherwise. */ int rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id); /** * Set the period in milliseconds for delaying the disabling of a bonded link * when the link down status has been detected * * @param bonded_port_id Port ID of bonded device. * @param delay_ms Delay period in milliseconds. * * @return * 0 on success, negative value otherwise. */ int rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms); /** * Get the period in milliseconds set for delaying the disabling of a bonded * link when the link down status has been detected * * @param bonded_port_id Port ID of bonded device. * * @return * Delay period on success, negative value otherwise. */ int rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id); /** * Set the period in milliseconds for delaying the enabling of a bonded link * when the link up status has been detected * * @param bonded_port_id Port ID of bonded device. * @param delay_ms Delay period in milliseconds. * * @return * 0 on success, negative value otherwise. */ int rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms); /** * Get the period in milliseconds set for delaying the enabling of a bonded * link when the link up status has been detected * * @param bonded_port_id Port ID of bonded device. * * @return * Delay period on success, negative value otherwise. */ int rte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id); #ifdef __cplusplus } #endif #endif ================================================ FILE: drivers/net/bonding/rte_eth_bond_8023ad.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_eth_bond_private.h" #ifdef RTE_LIBRTE_BOND_DEBUG_8023AD #define MODE4_DEBUG(fmt, ...) RTE_LOG(DEBUG, PMD, "%6u [Port %u: %s] " fmt, \ bond_dbg_get_time_diff_ms(), slave_id, \ __func__, ##__VA_ARGS__) static uint64_t start_time; static unsigned bond_dbg_get_time_diff_ms(void) { uint64_t now; now = rte_rdtsc(); if (start_time == 0) start_time = now; return ((now - start_time) * 1000) / rte_get_tsc_hz(); } static void bond_print_lacp(struct lacpdu *l) { char a_address[18]; char p_address[18]; char a_state[256] = { 0 }; char p_state[256] = { 0 }; static const char * const state_labels[] = { "ACT", "TIMEOUT", "AGG", "SYNC", "COL", "DIST", "DEF", "EXP" }; int a_len = 0; int p_len = 0; uint8_t i; uint8_t *addr; addr = l->actor.port_params.system.addr_bytes; snprintf(a_address, sizeof(a_address), "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); addr = l->partner.port_params.system.addr_bytes; snprintf(p_address, sizeof(p_address), "%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); for (i = 0; i < 8; i++) { if ((l->actor.state >> i) & 1) { a_len += snprintf(&a_state[a_len], RTE_DIM(a_state) - a_len, "%s ", state_labels[i]); } if ((l->partner.state >> i) & 1) { p_len += snprintf(&p_state[p_len], RTE_DIM(p_state) - p_len, "%s ", state_labels[i]); } } if (a_len && a_state[a_len-1] == ' ') a_state[a_len-1] = '\0'; if (p_len && p_state[p_len-1] == ' ') p_state[p_len-1] = '\0'; RTE_LOG(DEBUG, PMD, "LACP: {\n"\ " subtype= %02X\n"\ " ver_num=%02X\n"\ " actor={ tlv=%02X, len=%02X\n"\ " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"\ " state={ %s }\n"\ " }\n"\ " partner={ tlv=%02X, len=%02X\n"\ " pri=%04X, system=%s, key=%04X, p_pri=%04X p_num=%04X\n"\ " state={ %s }\n"\ " }\n"\ " collector={info=%02X, length=%02X, max_delay=%04X\n, " \ "type_term=%02X, terminator_length = %02X}\n",\ l->subtype,\ l->version_number,\ l->actor.tlv_type_info,\ l->actor.info_length,\ l->actor.port_params.system_priority,\ a_address,\ l->actor.port_params.key,\ l->actor.port_params.port_priority,\ l->actor.port_params.port_number,\ a_state,\ l->partner.tlv_type_info,\ l->partner.info_length,\ l->partner.port_params.system_priority,\ p_address,\ l->partner.port_params.key,\ l->partner.port_params.port_priority,\ l->partner.port_params.port_number,\ p_state,\ l->tlv_type_collector_info,\ l->collector_info_length,\ l->collector_max_delay,\ l->tlv_type_terminator,\ l->terminator_length); } #define BOND_PRINT_LACP(lacpdu) bond_print_lacp(lacpdu) #else #define BOND_PRINT_LACP(lacpdu) do { } while (0) #define MODE4_DEBUG(fmt, ...) do { } while (0) #endif static const struct ether_addr lacp_mac_addr = { .addr_bytes = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 } }; struct port mode_8023ad_ports[RTE_MAX_ETHPORTS]; static void timer_cancel(uint64_t *timer) { *timer = 0; } static void timer_set(uint64_t *timer, uint64_t timeout) { *timer = rte_rdtsc() + timeout; } /* Forces given timer to be in expired state. */ static void timer_force_expired(uint64_t *timer) { *timer = rte_rdtsc(); } static bool timer_is_stopped(uint64_t *timer) { return *timer == 0; } static bool timer_is_expired(uint64_t *timer) { return *timer < rte_rdtsc(); } /* Timer is in running state if it is not stopped nor expired */ static bool timer_is_running(uint64_t *timer) { return !timer_is_stopped(timer) && !timer_is_expired(timer); } static void set_warning_flags(struct port *port, uint16_t flags) { int retval; uint16_t old; uint16_t new_flag = 0; do { old = port->warnings_to_show; new_flag = old | flags; retval = rte_atomic16_cmpset(&port->warnings_to_show, old, new_flag); } while (unlikely(retval == 0)); } static void show_warnings(uint8_t slave_id) { struct port *port = &mode_8023ad_ports[slave_id]; uint8_t warnings; do { warnings = port->warnings_to_show; } while (rte_atomic16_cmpset(&port->warnings_to_show, warnings, 0) == 0); if (!warnings) return; if (!timer_is_expired(&port->warning_timer)) return; timer_set(&port->warning_timer, BOND_8023AD_WARNINGS_PERIOD_MS * rte_get_tsc_hz() / 1000); if (warnings & WRN_RX_QUEUE_FULL) { RTE_LOG(DEBUG, PMD, "Slave %u: failed to enqueue LACP packet into RX ring.\n" "Receive and transmit functions must be invoked on bonded\n" "interface at least 10 times per second or LACP will not\n" "work correctly\n", slave_id); } if (warnings & WRN_TX_QUEUE_FULL) { RTE_LOG(DEBUG, PMD, "Slave %u: failed to enqueue LACP packet into TX ring.\n" "Receive and transmit functions must be invoked on bonded\n" "interface at least 10 times per second or LACP will not\n" "work correctly\n", slave_id); } if (warnings & WRN_RX_MARKER_TO_FAST) RTE_LOG(INFO, PMD, "Slave %u: marker to early - ignoring.\n", slave_id); if (warnings & WRN_UNKNOWN_SLOW_TYPE) { RTE_LOG(INFO, PMD, "Slave %u: ignoring unknown slow protocol frame type", slave_id); } if (warnings & WRN_UNKNOWN_MARKER_TYPE) RTE_LOG(INFO, PMD, "Slave %u: ignoring unknown marker type", slave_id); if (warnings & WRN_NOT_LACP_CAPABLE) MODE4_DEBUG("Port %u is not LACP capable!\n", slave_id); } static void record_default(struct port *port) { /* Record default parameters for partner. Partner admin parameters * are not implemented so set them to arbitrary default (last known) and * mark actor that parner is in defaulted state. */ port->partner_state = STATE_LACP_ACTIVE; ACTOR_STATE_SET(port, DEFAULTED); } /** Function handles rx state machine. * * This function implements Receive State Machine from point 5.4.12 in * 802.1AX documentation. It should be called periodically. * * @param lacpdu LACPDU received. * @param port Port on which LACPDU was received. */ static void rx_machine(struct bond_dev_private *internals, uint8_t slave_id, struct lacpdu *lacp) { struct port *agg, *port = &mode_8023ad_ports[slave_id]; uint64_t timeout; if (SM_FLAG(port, BEGIN)) { /* Initialize stuff */ MODE4_DEBUG("-> INITIALIZE\n"); SM_FLAG_CLR(port, MOVED); port->selected = UNSELECTED; record_default(port); ACTOR_STATE_CLR(port, EXPIRED); timer_cancel(&port->current_while_timer); /* DISABLED: On initialization partner is out of sync */ PARTNER_STATE_CLR(port, SYNCHRONIZATION); /* LACP DISABLED stuff if LACP not enabled on this port */ if (!SM_FLAG(port, LACP_ENABLED)) PARTNER_STATE_CLR(port, AGGREGATION); else PARTNER_STATE_SET(port, AGGREGATION); } if (!SM_FLAG(port, LACP_ENABLED)) { /* Update parameters only if state changed */ if (!timer_is_stopped(&port->current_while_timer)) { port->selected = UNSELECTED; record_default(port); PARTNER_STATE_CLR(port, AGGREGATION); ACTOR_STATE_CLR(port, EXPIRED); timer_cancel(&port->current_while_timer); } return; } if (lacp) { MODE4_DEBUG("LACP -> CURRENT\n"); BOND_PRINT_LACP(lacp); /* Update selected flag. If partner parameters are defaulted assume they * are match. If not defaulted compare LACP actor with ports parner * params. */ if (!ACTOR_STATE(port, DEFAULTED) && (ACTOR_STATE(port, AGGREGATION) != PARTNER_STATE(port, AGGREGATION) || memcmp(&port->partner, &lacp->actor.port_params, sizeof(port->partner)) != 0)) { MODE4_DEBUG("selected <- UNSELECTED\n"); port->selected = UNSELECTED; } /* Record this PDU actor params as partner params */ memcpy(&port->partner, &lacp->actor.port_params, sizeof(struct port_params)); port->partner_state = lacp->actor.state; /* Partner parameters are not defaulted any more */ ACTOR_STATE_CLR(port, DEFAULTED); /* If LACP partner params match this port actor params */ agg = &mode_8023ad_ports[port->aggregator_port_id]; bool match = port->actor.system_priority == lacp->partner.port_params.system_priority && is_same_ether_addr(&agg->actor.system, &lacp->partner.port_params.system) && port->actor.port_priority == lacp->partner.port_params.port_priority && port->actor.port_number == lacp->partner.port_params.port_number; /* Update NTT if partners information are outdated (xored and masked * bits are set)*/ uint8_t state_mask = STATE_LACP_ACTIVE | STATE_LACP_SHORT_TIMEOUT | STATE_SYNCHRONIZATION | STATE_AGGREGATION; if (((port->actor_state ^ lacp->partner.state) & state_mask) || match == false) { SM_FLAG_SET(port, NTT); } /* If LACP partner params match this port actor params */ if (match == true && ACTOR_STATE(port, AGGREGATION) == PARTNER_STATE(port, AGGREGATION)) PARTNER_STATE_SET(port, SYNCHRONIZATION); else if (!PARTNER_STATE(port, AGGREGATION) && ACTOR_STATE(port, AGGREGATION)) PARTNER_STATE_SET(port, SYNCHRONIZATION); else PARTNER_STATE_CLR(port, SYNCHRONIZATION); if (ACTOR_STATE(port, LACP_SHORT_TIMEOUT)) timeout = internals->mode4.short_timeout; else timeout = internals->mode4.long_timeout; timer_set(&port->current_while_timer, timeout); ACTOR_STATE_CLR(port, EXPIRED); return; /* No state change */ } /* If CURRENT state timer is not running (stopped or expired) * transit to EXPIRED state from DISABLED or CURRENT */ if (!timer_is_running(&port->current_while_timer)) { ACTOR_STATE_SET(port, EXPIRED); PARTNER_STATE_CLR(port, SYNCHRONIZATION); PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT); timer_set(&port->current_while_timer, internals->mode4.short_timeout); } } /** * Function handles periodic tx state machine. * * Function implements Periodic Transmission state machine from point 5.4.13 * in 802.1AX documentation. It should be called periodically. * * @param port Port to handle state machine. */ static void periodic_machine(struct bond_dev_private *internals, uint8_t slave_id) { struct port *port = &mode_8023ad_ports[slave_id]; /* Calculate if either site is LACP enabled */ uint64_t timeout; uint8_t active = ACTOR_STATE(port, LACP_ACTIVE) || PARTNER_STATE(port, LACP_ACTIVE); uint8_t is_partner_fast, was_partner_fast; /* No periodic is on BEGIN, LACP DISABLE or when both sides are pasive */ if (SM_FLAG(port, BEGIN) || !SM_FLAG(port, LACP_ENABLED) || !active) { timer_cancel(&port->periodic_timer); timer_force_expired(&port->tx_machine_timer); SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT); MODE4_DEBUG("-> NO_PERIODIC ( %s%s%s)\n", SM_FLAG(port, BEGIN) ? "begind " : "", SM_FLAG(port, LACP_ENABLED) ? "" : "LACP disabled ", active ? "LACP active " : "LACP pasive "); return; } is_partner_fast = PARTNER_STATE(port, LACP_SHORT_TIMEOUT); was_partner_fast = SM_FLAG(port, PARTNER_SHORT_TIMEOUT); /* If periodic timer is not started, transit from NO PERIODIC to FAST/SLOW. * Other case: check if timer expire or partners settings changed. */ if (!timer_is_stopped(&port->periodic_timer)) { if (timer_is_expired(&port->periodic_timer)) { SM_FLAG_SET(port, NTT); } else if (is_partner_fast != was_partner_fast) { /* Partners timeout was slow and now it is fast -> send LACP. * In other case (was fast and now it is slow) just switch * timeout to slow without forcing send of LACP (because standard * say so)*/ if (!is_partner_fast) SM_FLAG_SET(port, NTT); } else return; /* Nothing changed */ } /* Handle state transition to FAST/SLOW LACP timeout */ if (is_partner_fast) { timeout = internals->mode4.fast_periodic_timeout; SM_FLAG_SET(port, PARTNER_SHORT_TIMEOUT); } else { timeout = internals->mode4.slow_periodic_timeout; SM_FLAG_CLR(port, PARTNER_SHORT_TIMEOUT); } timer_set(&port->periodic_timer, timeout); } /** * Function handles mux state machine. * * Function implements Mux Machine from point 5.4.15 in 802.1AX documentation. * It should be called periodically. * * @param port Port to handle state machine. */ static void mux_machine(struct bond_dev_private *internals, uint8_t slave_id) { struct port *port = &mode_8023ad_ports[slave_id]; /* Save current state for later use */ const uint8_t state_mask = STATE_SYNCHRONIZATION | STATE_DISTRIBUTING | STATE_COLLECTING; /* Enter DETACHED state on BEGIN condition or from any other state if * port was unselected */ if (SM_FLAG(port, BEGIN) || port->selected == UNSELECTED || (port->selected == STANDBY && (port->actor_state & state_mask) != 0)) { /* detach mux from aggregator */ port->actor_state &= ~state_mask; /* Set ntt to true if BEGIN condition or transition from any other state * which is indicated that wait_while_timer was started */ if (SM_FLAG(port, BEGIN) || !timer_is_stopped(&port->wait_while_timer)) { SM_FLAG_SET(port, NTT); MODE4_DEBUG("-> DETACHED\n"); } timer_cancel(&port->wait_while_timer); } if (timer_is_stopped(&port->wait_while_timer)) { if (port->selected == SELECTED || port->selected == STANDBY) { timer_set(&port->wait_while_timer, internals->mode4.aggregate_wait_timeout); MODE4_DEBUG("DETACHED -> WAITING\n"); } /* Waiting state entered */ return; } /* Transit next state if port is ready */ if (!timer_is_expired(&port->wait_while_timer)) return; if ((ACTOR_STATE(port, DISTRIBUTING) || ACTOR_STATE(port, COLLECTING)) && !PARTNER_STATE(port, SYNCHRONIZATION)) { /* If in COLLECTING or DISTRIBUTING state and partner becomes out of * sync transit to ATACHED state. */ ACTOR_STATE_CLR(port, DISTRIBUTING); ACTOR_STATE_CLR(port, COLLECTING); /* Clear actor sync to activate transit ATACHED in condition bellow */ ACTOR_STATE_CLR(port, SYNCHRONIZATION); MODE4_DEBUG("Out of sync -> ATTACHED\n"); } if (!ACTOR_STATE(port, SYNCHRONIZATION)) { /* attach mux to aggregator */ RTE_VERIFY((port->actor_state & (STATE_COLLECTING | STATE_DISTRIBUTING)) == 0); ACTOR_STATE_SET(port, SYNCHRONIZATION); SM_FLAG_SET(port, NTT); MODE4_DEBUG("ATTACHED Entered\n"); } else if (!ACTOR_STATE(port, COLLECTING)) { /* Start collecting if in sync */ if (PARTNER_STATE(port, SYNCHRONIZATION)) { MODE4_DEBUG("ATTACHED -> COLLECTING\n"); ACTOR_STATE_SET(port, COLLECTING); SM_FLAG_SET(port, NTT); } } else if (ACTOR_STATE(port, COLLECTING)) { /* Check if partner is in COLLECTING state. If so this port can * distribute frames to it */ if (!ACTOR_STATE(port, DISTRIBUTING)) { if (PARTNER_STATE(port, COLLECTING)) { /* Enable DISTRIBUTING if partner is collecting */ ACTOR_STATE_SET(port, DISTRIBUTING); SM_FLAG_SET(port, NTT); MODE4_DEBUG("COLLECTING -> DISTRIBUTING\n"); RTE_LOG(INFO, PMD, "Bond %u: slave id %u distributing started.\n", internals->port_id, slave_id); } } else { if (!PARTNER_STATE(port, COLLECTING)) { /* Disable DISTRIBUTING (enter COLLECTING state) if partner * is not collecting */ ACTOR_STATE_CLR(port, DISTRIBUTING); SM_FLAG_SET(port, NTT); MODE4_DEBUG("DISTRIBUTING -> COLLECTING\n"); RTE_LOG(INFO, PMD, "Bond %u: slave id %u distributing stopped.\n", internals->port_id, slave_id); } } } } /** * Function handles transmit state machine. * * Function implements Transmit Machine from point 5.4.16 in 802.1AX * documentation. * * @param port */ static void tx_machine(struct bond_dev_private *internals, uint8_t slave_id) { struct port *agg, *port = &mode_8023ad_ports[slave_id]; struct rte_mbuf *lacp_pkt = NULL; struct lacpdu_header *hdr; struct lacpdu *lacpdu; /* If periodic timer is not running periodic machine is in NO PERIODIC and * according to 802.3ax standard tx machine should not transmit any frames * and set ntt to false. */ if (timer_is_stopped(&port->periodic_timer)) SM_FLAG_CLR(port, NTT); if (!SM_FLAG(port, NTT)) return; if (!timer_is_expired(&port->tx_machine_timer)) return; lacp_pkt = rte_pktmbuf_alloc(port->mbuf_pool); if (lacp_pkt == NULL) { RTE_LOG(ERR, PMD, "Failed to allocate LACP packet from pool\n"); return; } lacp_pkt->data_len = sizeof(*hdr); lacp_pkt->pkt_len = sizeof(*hdr); hdr = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *); /* Source and destination MAC */ ether_addr_copy(&lacp_mac_addr, &hdr->eth_hdr.d_addr); rte_eth_macaddr_get(slave_id, &hdr->eth_hdr.s_addr); hdr->eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_SLOW); lacpdu = &hdr->lacpdu; memset(lacpdu, 0, sizeof(*lacpdu)); /* Initialize LACP part */ lacpdu->subtype = SLOW_SUBTYPE_LACP; lacpdu->version_number = 1; /* ACTOR */ lacpdu->actor.tlv_type_info = TLV_TYPE_ACTOR_INFORMATION; lacpdu->actor.info_length = sizeof(struct lacpdu_actor_partner_params); memcpy(&hdr->lacpdu.actor.port_params, &port->actor, sizeof(port->actor)); agg = &mode_8023ad_ports[port->aggregator_port_id]; ether_addr_copy(&agg->actor.system, &hdr->lacpdu.actor.port_params.system); lacpdu->actor.state = port->actor_state; /* PARTNER */ lacpdu->partner.tlv_type_info = TLV_TYPE_PARTNER_INFORMATION; lacpdu->partner.info_length = sizeof(struct lacpdu_actor_partner_params); memcpy(&lacpdu->partner.port_params, &port->partner, sizeof(struct port_params)); lacpdu->partner.state = port->partner_state; /* Other fields */ lacpdu->tlv_type_collector_info = TLV_TYPE_COLLECTOR_INFORMATION; lacpdu->collector_info_length = 0x10; lacpdu->collector_max_delay = 0; lacpdu->tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION; lacpdu->terminator_length = 0; if (rte_ring_enqueue(port->tx_ring, lacp_pkt) == -ENOBUFS) { /* If TX ring full, drop packet and free message. Retransmission * will happen in next function call. */ rte_pktmbuf_free(lacp_pkt); set_warning_flags(port, WRN_TX_QUEUE_FULL); return; } MODE4_DEBUG("sending LACP frame\n"); BOND_PRINT_LACP(lacpdu); timer_set(&port->tx_machine_timer, internals->mode4.tx_period_timeout); SM_FLAG_CLR(port, NTT); } /** * Function assigns port to aggregator. * * @param bond_dev_private Pointer to bond_dev_private structure. * @param port_pos Port to assign. */ static void selection_logic(struct bond_dev_private *internals, uint8_t slave_id) { struct port *agg, *port; uint8_t slaves_count, new_agg_id, i; uint8_t *slaves; slaves = internals->active_slaves; slaves_count = internals->active_slave_count; port = &mode_8023ad_ports[slave_id]; /* Search for aggregator suitable for this port */ for (i = 0; i < slaves_count; ++i) { agg = &mode_8023ad_ports[slaves[i]]; /* Skip ports that are not aggreagators */ if (agg->aggregator_port_id != slaves[i]) continue; /* Actors system ID is not checked since all slave device have the same * ID (MAC address). */ if ((agg->actor.key == port->actor.key && agg->partner.system_priority == port->partner.system_priority && is_same_ether_addr(&agg->partner.system, &port->partner.system) == 1 && (agg->partner.key == port->partner.key)) && is_zero_ether_addr(&port->partner.system) != 1 && (agg->actor.key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) != 0) { break; } } /* By default, port uses it self as agregator */ if (i == slaves_count) new_agg_id = slave_id; else new_agg_id = slaves[i]; if (new_agg_id != port->aggregator_port_id) { port->aggregator_port_id = new_agg_id; MODE4_DEBUG("-> SELECTED: ID=%3u\n" "\t%s aggregator ID=%3u\n", port->aggregator_port_id, port->aggregator_port_id == slave_id ? "aggregator not found, using default" : "aggregator found", port->aggregator_port_id); } port->selected = SELECTED; } /* Function maps DPDK speed to bonding speed stored in key field */ static uint16_t link_speed_key(uint16_t speed) { uint16_t key_speed; switch (speed) { case ETH_LINK_SPEED_AUTONEG: key_speed = 0x00; break; case ETH_LINK_SPEED_10: key_speed = BOND_LINK_SPEED_KEY_10M; break; case ETH_LINK_SPEED_100: key_speed = BOND_LINK_SPEED_KEY_100M; break; case ETH_LINK_SPEED_1000: key_speed = BOND_LINK_SPEED_KEY_1000M; break; case ETH_LINK_SPEED_10G: key_speed = BOND_LINK_SPEED_KEY_10G; break; case ETH_LINK_SPEED_20G: key_speed = BOND_LINK_SPEED_KEY_20G; break; case ETH_LINK_SPEED_40G: key_speed = BOND_LINK_SPEED_KEY_40G; break; default: /* Unknown speed*/ key_speed = 0xFFFF; } return key_speed; } static void bond_mode_8023ad_periodic_cb(void *arg) { struct rte_eth_dev *bond_dev = arg; struct bond_dev_private *internals = bond_dev->data->dev_private; struct port *port; struct rte_eth_link link_info; struct ether_addr slave_addr; void *pkt = NULL; uint8_t i, slave_id; /* Update link status on each port */ for (i = 0; i < internals->active_slave_count; i++) { uint16_t key; slave_id = internals->active_slaves[i]; rte_eth_link_get(slave_id, &link_info); rte_eth_macaddr_get(slave_id, &slave_addr); if (link_info.link_status != 0) { key = link_speed_key(link_info.link_speed) << 1; if (link_info.link_duplex == ETH_LINK_FULL_DUPLEX) key |= BOND_LINK_FULL_DUPLEX_KEY; } else key = 0; port = &mode_8023ad_ports[slave_id]; key = rte_cpu_to_be_16(key); if (key != port->actor.key) { if (!(key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY))) set_warning_flags(port, WRN_NOT_LACP_CAPABLE); port->actor.key = key; SM_FLAG_SET(port, NTT); } if (!is_same_ether_addr(&port->actor.system, &slave_addr)) { ether_addr_copy(&slave_addr, &port->actor.system); if (port->aggregator_port_id == slave_id) SM_FLAG_SET(port, NTT); } } for (i = 0; i < internals->active_slave_count; i++) { slave_id = internals->active_slaves[i]; port = &mode_8023ad_ports[slave_id]; if ((port->actor.key & rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY)) == 0) { SM_FLAG_SET(port, BEGIN); /* LACP is disabled on half duples or link is down */ if (SM_FLAG(port, LACP_ENABLED)) { /* If port was enabled set it to BEGIN state */ SM_FLAG_CLR(port, LACP_ENABLED); ACTOR_STATE_CLR(port, DISTRIBUTING); ACTOR_STATE_CLR(port, COLLECTING); } /* Skip this port processing */ continue; } SM_FLAG_SET(port, LACP_ENABLED); /* Find LACP packet to this port. Do not check subtype, it is done in * function that queued packet */ if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) { struct rte_mbuf *lacp_pkt = pkt; struct lacpdu_header *lacp; lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *); RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP); /* This is LACP frame so pass it to rx_machine */ rx_machine(internals, slave_id, &lacp->lacpdu); rte_pktmbuf_free(lacp_pkt); } else rx_machine(internals, slave_id, NULL); periodic_machine(internals, slave_id); mux_machine(internals, slave_id); tx_machine(internals, slave_id); selection_logic(internals, slave_id); SM_FLAG_CLR(port, BEGIN); show_warnings(slave_id); } rte_eal_alarm_set(internals->mode4.update_timeout_us, bond_mode_8023ad_periodic_cb, arg); } void bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev, uint8_t slave_id) { struct bond_dev_private *internals = bond_dev->data->dev_private; struct port *port = &mode_8023ad_ports[slave_id]; struct port_params initial = { .system = { { 0 } }, .system_priority = rte_cpu_to_be_16(0xFFFF), .key = rte_cpu_to_be_16(BOND_LINK_FULL_DUPLEX_KEY), .port_priority = rte_cpu_to_be_16(0x00FF), .port_number = 0, }; char mem_name[RTE_ETH_NAME_MAX_LEN]; int socket_id; unsigned element_size; /* Given slave mus not be in active list */ RTE_VERIFY(find_slave_by_id(internals->active_slaves, internals->active_slave_count, slave_id) == internals->active_slave_count); memcpy(&port->actor, &initial, sizeof(struct port_params)); /* Standard requires that port ID must be grater than 0. * Add 1 do get corresponding port_number */ port->actor.port_number = rte_cpu_to_be_16((uint16_t)slave_id + 1); memcpy(&port->partner, &initial, sizeof(struct port_params)); /* default states */ port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED; port->partner_state = STATE_LACP_ACTIVE; port->sm_flags = SM_FLAGS_BEGIN; /* use this port as agregator */ port->aggregator_port_id = slave_id; rte_eth_promiscuous_enable(slave_id); timer_cancel(&port->warning_timer); if (port->mbuf_pool != NULL) return; RTE_VERIFY(port->rx_ring == NULL); RTE_VERIFY(port->tx_ring == NULL); socket_id = rte_eth_devices[slave_id].pci_dev->numa_node; element_size = sizeof(struct slow_protocol_frame) + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM; /* How big memory pool should be? If driver will not * free packets quick enough there will be ENOMEM in tx_machine. * For now give 511 pkts * max number of queued TX packets per slave. * Hope it will be enough. */ snprintf(mem_name, RTE_DIM(mem_name), "slave_port%u_pool", slave_id); port->mbuf_pool = rte_mempool_create(mem_name, BOND_MODE_8023AX_SLAVE_TX_PKTS * 512 - 1, element_size, RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ? 32 : RTE_MEMPOOL_CACHE_MAX_SIZE, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, socket_id, MEMPOOL_F_NO_SPREAD); /* Any memory allocation failure in initalization is critical because * resources can't be free, so reinitialization is impossible. */ if (port->mbuf_pool == NULL) { rte_panic("Slave %u: Failed to create memory pool '%s': %s\n", slave_id, mem_name, rte_strerror(rte_errno)); } snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_rx", slave_id); port->rx_ring = rte_ring_create(mem_name, rte_align32pow2(BOND_MODE_8023AX_SLAVE_RX_PKTS), socket_id, 0); if (port->rx_ring == NULL) { rte_panic("Slave %u: Failed to create rx ring '%s': %s\n", slave_id, mem_name, rte_strerror(rte_errno)); } /* TX ring is at least one pkt longer to make room for marker packet. */ snprintf(mem_name, RTE_DIM(mem_name), "slave_%u_tx", slave_id); port->tx_ring = rte_ring_create(mem_name, rte_align32pow2(BOND_MODE_8023AX_SLAVE_TX_PKTS + 1), socket_id, 0); if (port->tx_ring == NULL) { rte_panic("Slave %u: Failed to create tx ring '%s': %s\n", slave_id, mem_name, rte_strerror(rte_errno)); } } int bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *bond_dev, uint8_t slave_id) { struct bond_dev_private *internals = bond_dev->data->dev_private; void *pkt = NULL; struct port *port; uint8_t i; /* Given slave mus be in active list */ RTE_VERIFY(find_slave_by_id(internals->active_slaves, internals->active_slave_count, slave_id) < internals->active_slave_count); /* Exclude slave from transmit policy. If this slave is an aggregator * make all aggregated slaves unselected to force sellection logic * to select suitable aggregator for this port. */ for (i = 0; i < internals->active_slave_count; i++) { port = &mode_8023ad_ports[internals->active_slaves[i]]; if (port->aggregator_port_id != slave_id) continue; port->selected = UNSELECTED; /* Use default aggregator */ port->aggregator_port_id = internals->active_slaves[i]; } port = &mode_8023ad_ports[slave_id]; port->selected = UNSELECTED; port->actor_state &= ~(STATE_SYNCHRONIZATION | STATE_DISTRIBUTING | STATE_COLLECTING); while (rte_ring_dequeue(port->rx_ring, &pkt) == 0) rte_pktmbuf_free((struct rte_mbuf *)pkt); while (rte_ring_dequeue(port->tx_ring, &pkt) == 0) rte_pktmbuf_free((struct rte_mbuf *)pkt); return 0; } void bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev) { struct bond_dev_private *internals = bond_dev->data->dev_private; struct ether_addr slave_addr; struct port *slave, *agg_slave; uint8_t slave_id, i, j; bond_mode_8023ad_stop(bond_dev); for (i = 0; i < internals->active_slave_count; i++) { slave_id = internals->active_slaves[i]; slave = &mode_8023ad_ports[slave_id]; rte_eth_macaddr_get(slave_id, &slave_addr); if (is_same_ether_addr(&slave_addr, &slave->actor.system)) continue; ether_addr_copy(&slave_addr, &slave->actor.system); /* Do nothing if this port is not an aggregator. In other case * Set NTT flag on every port that use this aggregator. */ if (slave->aggregator_port_id != slave_id) continue; for (j = 0; j < internals->active_slave_count; j++) { agg_slave = &mode_8023ad_ports[internals->active_slaves[j]]; if (agg_slave->aggregator_port_id == slave_id) SM_FLAG_SET(agg_slave, NTT); } } if (bond_dev->data->dev_started) bond_mode_8023ad_start(bond_dev); } void bond_mode_8023ad_conf_get(struct rte_eth_dev *dev, struct rte_eth_bond_8023ad_conf *conf) { struct bond_dev_private *internals = dev->data->dev_private; struct mode8023ad_private *mode4 = &internals->mode4; uint64_t ms_ticks = rte_get_tsc_hz() / 1000; conf->fast_periodic_ms = mode4->fast_periodic_timeout / ms_ticks; conf->slow_periodic_ms = mode4->slow_periodic_timeout / ms_ticks; conf->short_timeout_ms = mode4->short_timeout / ms_ticks; conf->long_timeout_ms = mode4->long_timeout / ms_ticks; conf->aggregate_wait_timeout_ms = mode4->aggregate_wait_timeout / ms_ticks; conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks; conf->update_timeout_ms = mode4->update_timeout_us / 1000; } void bond_mode_8023ad_setup(struct rte_eth_dev *dev, struct rte_eth_bond_8023ad_conf *conf) { struct rte_eth_bond_8023ad_conf def_conf; struct bond_dev_private *internals = dev->data->dev_private; struct mode8023ad_private *mode4 = &internals->mode4; uint64_t ms_ticks = rte_get_tsc_hz() / 1000; if (conf == NULL) { conf = &def_conf; conf->fast_periodic_ms = BOND_8023AD_FAST_PERIODIC_MS; conf->slow_periodic_ms = BOND_8023AD_SLOW_PERIODIC_MS; conf->short_timeout_ms = BOND_8023AD_SHORT_TIMEOUT_MS; conf->long_timeout_ms = BOND_8023AD_LONG_TIMEOUT_MS; conf->aggregate_wait_timeout_ms = BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS; conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS; conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS; conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS; } mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks; mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks; mode4->short_timeout = conf->short_timeout_ms * ms_ticks; mode4->long_timeout = conf->long_timeout_ms * ms_ticks; mode4->aggregate_wait_timeout = conf->aggregate_wait_timeout_ms * ms_ticks; mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks; mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks; mode4->update_timeout_us = conf->update_timeout_ms * 1000; } int bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev) { struct bond_dev_private *internals = bond_dev->data->dev_private; uint8_t i; for (i = 0; i < internals->active_slave_count; i++) bond_mode_8023ad_activate_slave(bond_dev, i); return 0; } int bond_mode_8023ad_start(struct rte_eth_dev *bond_dev) { return rte_eal_alarm_set(BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000, &bond_mode_8023ad_periodic_cb, bond_dev); } void bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev) { rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev); } void bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals, uint8_t slave_id, struct rte_mbuf *pkt) { struct mode8023ad_private *mode4 = &internals->mode4; struct port *port = &mode_8023ad_ports[slave_id]; struct marker_header *m_hdr; uint64_t marker_timer, old_marker_timer; int retval; uint8_t wrn, subtype; /* If packet is a marker, we send response now by reusing given packet * and update only source MAC, destination MAC is multicast so don't * update it. Other frames will be handled later by state machines */ subtype = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *)->slow_protocol.subtype; if (subtype == SLOW_SUBTYPE_MARKER) { m_hdr = rte_pktmbuf_mtod(pkt, struct marker_header *); if (likely(m_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_INFO)) { wrn = WRN_UNKNOWN_MARKER_TYPE; goto free_out; } /* Setup marker timer. Do it in loop in case concurent access. */ do { old_marker_timer = port->rx_marker_timer; if (!timer_is_expired(&old_marker_timer)) { wrn = WRN_RX_MARKER_TO_FAST; goto free_out; } timer_set(&marker_timer, mode4->rx_marker_timeout); retval = rte_atomic64_cmpset(&port->rx_marker_timer, old_marker_timer, marker_timer); } while (unlikely(retval == 0)); m_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_RESP; rte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr); if (unlikely(rte_ring_enqueue(port->tx_ring, pkt) == -ENOBUFS)) { /* reset timer */ port->rx_marker_timer = 0; wrn = WRN_TX_QUEUE_FULL; goto free_out; } } else if (likely(subtype == SLOW_SUBTYPE_LACP)) { if (unlikely(rte_ring_enqueue(port->rx_ring, pkt) == -ENOBUFS)) { /* If RX fing full free lacpdu message and drop packet */ wrn = WRN_RX_QUEUE_FULL; goto free_out; } } else { wrn = WRN_UNKNOWN_SLOW_TYPE; goto free_out; } return; free_out: set_warning_flags(port, wrn); rte_pktmbuf_free(pkt); } int rte_eth_bond_8023ad_conf_get(uint8_t port_id, struct rte_eth_bond_8023ad_conf *conf) { struct rte_eth_dev *bond_dev; if (valid_bonded_port_id(port_id) != 0) return -EINVAL; if (conf == NULL) return -EINVAL; bond_dev = &rte_eth_devices[port_id]; bond_mode_8023ad_conf_get(bond_dev, conf); return 0; } int rte_eth_bond_8023ad_setup(uint8_t port_id, struct rte_eth_bond_8023ad_conf *conf) { struct rte_eth_dev *bond_dev; if (valid_bonded_port_id(port_id) != 0) return -EINVAL; if (conf != NULL) { /* Basic sanity check */ if (conf->slow_periodic_ms == 0 || conf->fast_periodic_ms >= conf->slow_periodic_ms || conf->long_timeout_ms == 0 || conf->short_timeout_ms >= conf->long_timeout_ms || conf->aggregate_wait_timeout_ms == 0 || conf->tx_period_ms == 0 || conf->rx_marker_period_ms == 0 || conf->update_timeout_ms == 0) { RTE_LOG(ERR, PMD, "given mode 4 configuration is invalid\n"); return -EINVAL; } } bond_dev = &rte_eth_devices[port_id]; bond_mode_8023ad_setup(bond_dev, conf); return 0; } int rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id, struct rte_eth_bond_8023ad_slave_info *info) { struct rte_eth_dev *bond_dev; struct bond_dev_private *internals; struct port *port; if (info == NULL || valid_bonded_port_id(port_id) != 0 || rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD) return -EINVAL; bond_dev = &rte_eth_devices[port_id]; internals = bond_dev->data->dev_private; if (find_slave_by_id(internals->active_slaves, internals->active_slave_count, slave_id) == internals->active_slave_count) return -EINVAL; port = &mode_8023ad_ports[slave_id]; info->selected = port->selected; info->actor_state = port->actor_state; rte_memcpy(&info->actor, &port->actor, sizeof(port->actor)); info->partner_state = port->partner_state; rte_memcpy(&info->partner, &port->partner, sizeof(port->partner)); info->agg_port_id = port->aggregator_port_id; return 0; } ================================================ FILE: drivers/net/bonding/rte_eth_bond_8023ad.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_ETH_BOND_8023AD_H_ #define RTE_ETH_BOND_8023AD_H_ #include #ifdef __cplusplus extern "C" { #endif /** * Actor/partner states */ #define STATE_LACP_ACTIVE 0x01 #define STATE_LACP_SHORT_TIMEOUT 0x02 #define STATE_AGGREGATION 0x04 #define STATE_SYNCHRONIZATION 0x08 #define STATE_COLLECTING 0x10 #define STATE_DISTRIBUTING 0x20 /** Partners parameters are defaulted */ #define STATE_DEFAULTED 0x40 #define STATE_EXPIRED 0x80 #define TLV_TYPE_ACTOR_INFORMATION 0x01 #define TLV_TYPE_PARTNER_INFORMATION 0x02 #define TLV_TYPE_COLLECTOR_INFORMATION 0x03 #define TLV_TYPE_TERMINATOR_INFORMATION 0x00 #define SLOW_SUBTYPE_LACP 0x01 #define SLOW_SUBTYPE_MARKER 0x02 #define MARKER_TLV_TYPE_INFO 0x01 #define MARKER_TLV_TYPE_RESP 0x02 enum rte_bond_8023ad_selection { UNSELECTED, STANDBY, SELECTED }; /** Generic slow protocol structure */ struct slow_protocol { uint8_t subtype; uint8_t reserved_119[119]; } __attribute__((__packed__)); /** Generic slow protocol frame type structure */ struct slow_protocol_frame { struct ether_hdr eth_hdr; struct slow_protocol slow_protocol; } __attribute__((__packed__)); struct port_params { uint16_t system_priority; /**< System priority (unused in current implementation) */ struct ether_addr system; /**< System ID - Slave MAC address, same as bonding MAC address */ uint16_t key; /**< Speed information (implementation dependednt) and duplex. */ uint16_t port_priority; /**< Priority of this (unused in current implementation) */ uint16_t port_number; /**< Port number. It corresponds to slave port id. */ } __attribute__((__packed__)); struct lacpdu_actor_partner_params { uint8_t tlv_type_info; uint8_t info_length; struct port_params port_params; uint8_t state; uint8_t reserved_3[3]; } __attribute__((__packed__)); /** LACPDU structure (5.4.2 in 802.1AX documentation). */ struct lacpdu { uint8_t subtype; uint8_t version_number; struct lacpdu_actor_partner_params actor; struct lacpdu_actor_partner_params partner; uint8_t tlv_type_collector_info; uint8_t collector_info_length; uint16_t collector_max_delay; uint8_t reserved_12[12]; uint8_t tlv_type_terminator; uint8_t terminator_length; uint8_t reserved_50[50]; } __attribute__((__packed__)); /** LACPDU frame: Contains ethernet header and LACPDU. */ struct lacpdu_header { struct ether_hdr eth_hdr; struct lacpdu lacpdu; } __attribute__((__packed__)); struct marker { uint8_t subtype; uint8_t version_number; uint8_t tlv_type_marker; uint8_t info_length; uint16_t requester_port; struct ether_addr requester_system; uint32_t requester_transaction_id; uint8_t reserved_2[2]; uint8_t tlv_type_terminator; uint8_t terminator_length; uint8_t reserved_90[90]; } __attribute__((__packed__)); struct marker_header { struct ether_hdr eth_hdr; struct marker marker; } __attribute__((__packed__)); struct rte_eth_bond_8023ad_conf { uint32_t fast_periodic_ms; uint32_t slow_periodic_ms; uint32_t short_timeout_ms; uint32_t long_timeout_ms; uint32_t aggregate_wait_timeout_ms; uint32_t tx_period_ms; uint32_t rx_marker_period_ms; uint32_t update_timeout_ms; }; struct rte_eth_bond_8023ad_slave_info { enum rte_bond_8023ad_selection selected; uint8_t actor_state; struct port_params actor; uint8_t partner_state; struct port_params partner; uint8_t agg_port_id; }; /** * @internal * * Function returns current configuration of 802.3AX mode. * * @param port_id Bonding device id * @param conf Pointer to timeout structure. * * @return * 0 - if ok * -EINVAL if conf is NULL */ int rte_eth_bond_8023ad_conf_get(uint8_t port_id, struct rte_eth_bond_8023ad_conf *conf); /** * @internal * * Function set new configuration of 802.3AX mode. * * @param port_id Bonding device id * @param conf Configuration, if NULL set default configuration. * @return * 0 - if ok * -EINVAL if configuration is invalid. */ int rte_eth_bond_8023ad_setup(uint8_t port_id, struct rte_eth_bond_8023ad_conf *conf); /** * @internal * * Function returns current state of given slave device. * * @param slave_id Port id of valid slave. * @param conf buffer for configuration * @return * 0 - if ok * -EINVAL if conf is NULL or slave id is invalid (not a slave of given * bonded device or is not inactive). */ int rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id, struct rte_eth_bond_8023ad_slave_info *conf); #ifdef __cplusplus } #endif #endif /* RTE_ETH_BOND_8023AD_H_ */ ================================================ FILE: drivers/net/bonding/rte_eth_bond_8023ad_private.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_ETH_BOND_8023AD_PRIVATE_H_ #define RTE_ETH_BOND_8023AD_PRIVATE_H_ #include #include #include #include #include "rte_eth_bond_8023ad.h" #define BOND_MODE_8023AX_UPDATE_TIMEOUT_MS 100 /** Maximum number of packets to one slave queued in TX ring. */ #define BOND_MODE_8023AX_SLAVE_RX_PKTS 3 /** Maximum number of LACP packets from one slave queued in TX ring. */ #define BOND_MODE_8023AX_SLAVE_TX_PKTS 1 /** * Timeouts deffinitions (5.4.4 in 802.1AX documentation). */ #define BOND_8023AD_FAST_PERIODIC_MS 900 #define BOND_8023AD_SLOW_PERIODIC_MS 29000 #define BOND_8023AD_SHORT_TIMEOUT_MS 3000 #define BOND_8023AD_LONG_TIMEOUT_MS 90000 #define BOND_8023AD_CHURN_DETECTION_TIMEOUT_MS 60000 #define BOND_8023AD_AGGREGATE_WAIT_TIMEOUT_MS 2000 #define BOND_8023AD_TX_MACHINE_PERIOD_MS 500 #define BOND_8023AD_RX_MARKER_PERIOD_MS 2000 /** * Interval of showing warning message from state machines. All messages will * be held (and gathered together) to prevent flooding. * This is no parto of 802.1AX standard. */ #define BOND_8023AD_WARNINGS_PERIOD_MS 1000 /** * State machine flags */ #define SM_FLAGS_BEGIN 0x0001 #define SM_FLAGS_LACP_ENABLED 0x0002 #define SM_FLAGS_ACTOR_CHURN 0x0004 #define SM_FLAGS_PARTNER_CHURN 0x0008 #define SM_FLAGS_MOVED 0x0100 #define SM_FLAGS_PARTNER_SHORT_TIMEOUT 0x0200 #define SM_FLAGS_NTT 0x0400 #define BOND_LINK_FULL_DUPLEX_KEY 0x01 #define BOND_LINK_SPEED_KEY_10M 0x02 #define BOND_LINK_SPEED_KEY_100M 0x04 #define BOND_LINK_SPEED_KEY_1000M 0x08 #define BOND_LINK_SPEED_KEY_10G 0x10 #define BOND_LINK_SPEED_KEY_20G 0x11 #define BOND_LINK_SPEED_KEY_40G 0x12 #define WRN_RX_MARKER_TO_FAST 0x01 #define WRN_UNKNOWN_SLOW_TYPE 0x02 #define WRN_UNKNOWN_MARKER_TYPE 0x04 #define WRN_NOT_LACP_CAPABLE 0x08 #define WRN_RX_QUEUE_FULL 0x10 #define WRN_TX_QUEUE_FULL 0x20 #define CHECK_FLAGS(_variable, _f) ((_variable) & (_f)) #define SET_FLAGS(_variable, _f) ((_variable) |= (_f)) #define CLEAR_FLAGS(_variable, _f) ((_variable) &= ~(_f)) #define SM_FLAG(_p, _f) (!!CHECK_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f)) #define SM_FLAG_SET(_p, _f) SET_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f) #define SM_FLAG_CLR(_p, _f) CLEAR_FLAGS((_p)->sm_flags, SM_FLAGS_ ## _f) #define ACTOR_STATE(_p, _f) (!!CHECK_FLAGS((_p)->actor_state, STATE_ ## _f)) #define ACTOR_STATE_SET(_p, _f) SET_FLAGS((_p)->actor_state, STATE_ ## _f) #define ACTOR_STATE_CLR(_p, _f) CLEAR_FLAGS((_p)->actor_state, STATE_ ## _f) #define PARTNER_STATE(_p, _f) (!!CHECK_FLAGS((_p)->partner_state, STATE_ ## _f)) #define PARTNER_STATE_SET(_p, _f) SET_FLAGS((_p)->partner_state, STATE_ ## _f) #define PARTNER_STATE_CLR(_p, _f) CLEAR_FLAGS((_p)->partner_state, STATE_ ## _f) /** Variables associated with each port (5.4.7 in 802.1AX documentation). */ struct port { /** * The operational values of the Actor's state parameters. Bitmask * of port states. */ uint8_t actor_state; /** The operational Actor's port parameters */ struct port_params actor; /** * The operational value of the Actor's view of the current values of * the Partner's state parameters. The Actor sets this variable either * to the value received from the Partner in an LACPDU, or to the value * of Partner_Admin_Port_State. Bitmask of port states. */ uint8_t partner_state; /** The operational Partner's port parameters */ struct port_params partner; /* Additional port parameters not listed in documentation */ /** State machine flags */ uint16_t sm_flags; enum rte_bond_8023ad_selection selected; uint64_t current_while_timer; uint64_t periodic_timer; uint64_t wait_while_timer; uint64_t tx_machine_timer; uint64_t tx_marker_timer; /* Agregator parameters */ /** Used aggregator port ID */ uint16_t aggregator_port_id; /** Memory pool used to allocate rings */ struct rte_mempool *mbuf_pool; /** Ring of LACP packets from RX burst function */ struct rte_ring *rx_ring; /** Ring of slow protocol packets (LACP and MARKERS) to TX burst function */ struct rte_ring *tx_ring; /** Timer which is also used as mutex. If is 0 (not running) RX marker * packet might be responded. Otherwise shall be dropped. It is zeroed in * mode 4 callback function after expire. */ volatile uint64_t rx_marker_timer; uint64_t warning_timer; volatile uint16_t warnings_to_show; }; struct mode8023ad_private { uint64_t fast_periodic_timeout; uint64_t slow_periodic_timeout; uint64_t short_timeout; uint64_t long_timeout; uint64_t aggregate_wait_timeout; uint64_t tx_period_timeout; uint64_t rx_marker_timeout; uint64_t update_timeout_us; }; /** * @internal * The pool of *port* structures. The size of the pool * is configured at compile-time in the file. */ extern struct port mode_8023ad_ports[]; /* Forward declaration */ struct bond_dev_private; /** * @internal * * Get configuration of bonded interface. * * * @param dev Bonded interface * @param conf returned configuration */ void bond_mode_8023ad_conf_get(struct rte_eth_dev *dev, struct rte_eth_bond_8023ad_conf *conf); /** * @internal * * Set mode 4 configuration of bonded interface. * * @pre Bonded interface must be stopped. * * @param dev Bonded interface * @param conf new configuration. If NULL set default configuration. */ void bond_mode_8023ad_setup(struct rte_eth_dev *dev, struct rte_eth_bond_8023ad_conf *conf); /** * @internal * * Enables 802.1AX mode and all active slaves on bonded interface. * * @param dev Bonded interface * @return * 0 on success, negative value otherwise. */ int bond_mode_8023ad_enable(struct rte_eth_dev *dev); /** * @internal * * Disables 802.1AX mode of the bonded interface and slaves. * * @param dev Bonded interface * @return * 0 on success, negative value otherwise. */ int bond_mode_8023ad_disable(struct rte_eth_dev *dev); /** * @internal * * Starts 802.3AX state machines management logic. * @param dev Bonded interface * @return * 0 if machines was started, 1 if machines was already running, * negative value otherwise. */ int bond_mode_8023ad_start(struct rte_eth_dev *dev); /** * @internal * * Stops 802.3AX state machines management logic. * @param dev Bonded interface * @return * 0 if this call stopped state machines, -ENOENT if alarm was not set. */ void bond_mode_8023ad_stop(struct rte_eth_dev *dev); /** * @internal * * Passes given slow packet to state machines management logic. * @param internals Bonded device private data. * @param slave_id Slave port id. * @param slot_pkt Slow packet. */ void bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals, uint8_t slave_id, struct rte_mbuf *pkt); /** * @internal * * Appends given slave used slave * * @param dev Bonded interface. * @param port_id Slave port ID to be added * * @return * 0 on success, negative value otherwise. */ void bond_mode_8023ad_activate_slave(struct rte_eth_dev *dev, uint8_t port_id); /** * @internal * * Denitializes and removes given slave from 802.1AX mode. * * @param dev Bonded interface. * @param slave_num Position of slave in active_slaves array * * @return * 0 on success, negative value otherwise. */ int bond_mode_8023ad_deactivate_slave(struct rte_eth_dev *dev, uint8_t slave_pos); /** * Updates state when MAC was changed on bonded device or one of its slaves. * @param bond_dev Bonded device */ void bond_mode_8023ad_mac_address_update(struct rte_eth_dev *bond_dev); #endif /* RTE_ETH_BOND_8023AD_H_ */ ================================================ FILE: drivers/net/bonding/rte_eth_bond_alb.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "rte_eth_bond_private.h" #include "rte_eth_bond_alb.h" static inline uint8_t simple_hash(uint8_t *hash_start, int hash_size) { int i; uint8_t hash; hash = 0; for (i = 0; i < hash_size; ++i) hash ^= hash_start[i]; return hash; } static uint8_t calculate_slave(struct bond_dev_private *internals) { uint8_t idx; idx = (internals->mode6.last_slave + 1) % internals->active_slave_count; internals->mode6.last_slave = idx; return internals->active_slaves[idx]; } int bond_mode_alb_enable(struct rte_eth_dev *bond_dev) { struct bond_dev_private *internals = bond_dev->data->dev_private; struct client_data *hash_table = internals->mode6.client_table; uint16_t data_size; char mem_name[RTE_ETH_NAME_MAX_LEN]; int socket_id = bond_dev->pci_dev->numa_node; /* Fill hash table with initial values */ memset(hash_table, 0, sizeof(struct client_data) * ALB_HASH_TABLE_SIZE); rte_spinlock_init(&internals->mode6.lock); internals->mode6.last_slave = ALB_NULL_INDEX; internals->mode6.ntt = 0; /* Initialize memory pool for ARP packets to send */ if (internals->mode6.mempool == NULL) { /* * 256 is size of ETH header, ARP header and nested VLAN headers. * The value is chosen to be cache aligned. */ data_size = 256 + RTE_PKTMBUF_HEADROOM; snprintf(mem_name, sizeof(mem_name), "%s_MODE6", bond_dev->data->name); internals->mode6.mempool = rte_pktmbuf_pool_create(mem_name, 512 * RTE_MAX_ETHPORTS, RTE_MEMPOOL_CACHE_MAX_SIZE >= 32 ? 32 : RTE_MEMPOOL_CACHE_MAX_SIZE, 0, data_size, socket_id); if (internals->mode6.mempool == NULL) { RTE_LOG(ERR, PMD, "%s: Failed to initialize ALB mempool.\n", bond_dev->data->name); rte_panic( "Failed to allocate memory pool ('%s')\n" "for bond device '%s'\n", mem_name, bond_dev->data->name); } } return 0; } void bond_mode_alb_arp_recv(struct ether_hdr *eth_h, uint16_t offset, struct bond_dev_private *internals) { struct arp_hdr *arp; struct client_data *hash_table = internals->mode6.client_table; struct client_data *client_info; uint8_t hash_index; arp = (struct arp_hdr *) ((char *) (eth_h + 1) + offset); /* ARP Requests are forwarded to the application with no changes */ if (arp->arp_op != rte_cpu_to_be_16(ARP_OP_REPLY)) return; /* From now on, we analyze only ARP Reply packets */ hash_index = simple_hash((uint8_t *) &arp->arp_data.arp_sip, sizeof(arp->arp_data.arp_sip)); client_info = &hash_table[hash_index]; /* * We got reply for ARP Request send by the application. We need to * update client table when received data differ from what is stored * in ALB table and issue sending update packet to that slave. */ rte_spinlock_lock(&internals->mode6.lock); if (client_info->in_use == 0 || client_info->app_ip != arp->arp_data.arp_tip || client_info->cli_ip != arp->arp_data.arp_sip || !is_same_ether_addr(&client_info->cli_mac, &arp->arp_data.arp_sha) || client_info->vlan_count != offset / sizeof(struct vlan_hdr) || memcmp(client_info->vlan, eth_h + 1, offset) != 0 ) { client_info->in_use = 1; client_info->app_ip = arp->arp_data.arp_tip; client_info->cli_ip = arp->arp_data.arp_sip; ether_addr_copy(&arp->arp_data.arp_sha, &client_info->cli_mac); client_info->slave_idx = calculate_slave(internals); rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac); ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_tha); memcpy(client_info->vlan, eth_h + 1, offset); client_info->vlan_count = offset / sizeof(struct vlan_hdr); } internals->mode6.ntt = 1; rte_spinlock_unlock(&internals->mode6.lock); } uint8_t bond_mode_alb_arp_xmit(struct ether_hdr *eth_h, uint16_t offset, struct bond_dev_private *internals) { struct arp_hdr *arp; struct client_data *hash_table = internals->mode6.client_table; struct client_data *client_info; uint8_t hash_index; struct ether_addr bonding_mac; arp = (struct arp_hdr *)((char *)(eth_h + 1) + offset); /* * Traffic with src MAC other than bonding should be sent on * current primary port. */ rte_eth_macaddr_get(internals->port_id, &bonding_mac); if (!is_same_ether_addr(&bonding_mac, &arp->arp_data.arp_sha)) { rte_eth_macaddr_get(internals->current_primary_port, &arp->arp_data.arp_sha); return internals->current_primary_port; } hash_index = simple_hash((uint8_t *)&arp->arp_data.arp_tip, sizeof(uint32_t)); client_info = &hash_table[hash_index]; rte_spinlock_lock(&internals->mode6.lock); if (arp->arp_op == rte_cpu_to_be_16(ARP_OP_REPLY)) { if (client_info->in_use) { if (client_info->app_ip == arp->arp_data.arp_sip && client_info->cli_ip == arp->arp_data.arp_tip) { /* Entry is already assigned to this client */ if (!is_broadcast_ether_addr(&arp->arp_data.arp_tha)) { ether_addr_copy(&arp->arp_data.arp_tha, &client_info->cli_mac); } rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac); ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha); memcpy(client_info->vlan, eth_h + 1, offset); client_info->vlan_count = offset / sizeof(struct vlan_hdr); rte_spinlock_unlock(&internals->mode6.lock); return client_info->slave_idx; } } /* Assign new slave to this client and update src mac in ARP */ client_info->in_use = 1; client_info->ntt = 0; client_info->app_ip = arp->arp_data.arp_sip; ether_addr_copy(&arp->arp_data.arp_tha, &client_info->cli_mac); client_info->cli_ip = arp->arp_data.arp_tip; client_info->slave_idx = calculate_slave(internals); rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac); ether_addr_copy(&client_info->app_mac, &arp->arp_data.arp_sha); memcpy(client_info->vlan, eth_h + 1, offset); client_info->vlan_count = offset / sizeof(struct vlan_hdr); rte_spinlock_unlock(&internals->mode6.lock); return client_info->slave_idx; } /* If packet is not ARP Reply, send it on current primary port. */ rte_spinlock_unlock(&internals->mode6.lock); rte_eth_macaddr_get(internals->current_primary_port, &arp->arp_data.arp_sha); return internals->current_primary_port; } uint8_t bond_mode_alb_arp_upd(struct client_data *client_info, struct rte_mbuf *pkt, struct bond_dev_private *internals) { struct ether_hdr *eth_h; struct arp_hdr *arp_h; uint8_t slave_idx; rte_spinlock_lock(&internals->mode6.lock); eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *); ether_addr_copy(&client_info->app_mac, ð_h->s_addr); ether_addr_copy(&client_info->cli_mac, ð_h->d_addr); if (client_info->vlan_count > 0) eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); else eth_h->ether_type = rte_cpu_to_be_16(ETHER_TYPE_ARP); arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr) + client_info->vlan_count * sizeof(struct vlan_hdr)); memcpy(eth_h + 1, client_info->vlan, client_info->vlan_count * sizeof(struct vlan_hdr)); ether_addr_copy(&client_info->app_mac, &arp_h->arp_data.arp_sha); arp_h->arp_data.arp_sip = client_info->app_ip; ether_addr_copy(&client_info->cli_mac, &arp_h->arp_data.arp_tha); arp_h->arp_data.arp_tip = client_info->cli_ip; arp_h->arp_hrd = rte_cpu_to_be_16(ARP_HRD_ETHER); arp_h->arp_pro = rte_cpu_to_be_16(ETHER_TYPE_IPv4); arp_h->arp_hln = ETHER_ADDR_LEN; arp_h->arp_pln = sizeof(uint32_t); arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); slave_idx = client_info->slave_idx; rte_spinlock_unlock(&internals->mode6.lock); return slave_idx; } void bond_mode_alb_client_list_upd(struct rte_eth_dev *bond_dev) { struct bond_dev_private *internals = bond_dev->data->dev_private; struct client_data *client_info; int i; /* If active slave count is 0, it's pointless to refresh alb table */ if (internals->active_slave_count <= 0) return; rte_spinlock_lock(&internals->mode6.lock); internals->mode6.last_slave = ALB_NULL_INDEX; for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) { client_info = &internals->mode6.client_table[i]; if (client_info->in_use) { client_info->slave_idx = calculate_slave(internals); rte_eth_macaddr_get(client_info->slave_idx, &client_info->app_mac); internals->mode6.ntt = 1; } } rte_spinlock_unlock(&internals->mode6.lock); } ================================================ FILE: drivers/net/bonding/rte_eth_bond_alb.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_ETH_BOND_ALB_H_ #define RTE_ETH_BOND_ALB_H_ #include #include #define ALB_HASH_TABLE_SIZE 256 #define ALB_NULL_INDEX 0xFFFFFFFF struct client_data { /** ARP data of single client */ struct ether_addr app_mac; /**< MAC address of application running DPDK */ uint32_t app_ip; /**< IP address of application running DPDK */ struct ether_addr cli_mac; /**< Client MAC address */ uint32_t cli_ip; /**< Client IP address */ uint8_t slave_idx; /**< Index of slave on which we connect with that client */ uint8_t in_use; /**< Flag indicating if entry in client table is currently used */ uint8_t ntt; /**< Flag indicating if we need to send update to this client on next tx */ struct vlan_hdr vlan[2]; /**< Content of vlan headers */ uint8_t vlan_count; /**< Number of nested vlan headers */ }; struct mode_alb_private { struct client_data client_table[ALB_HASH_TABLE_SIZE]; /**< Hash table storing ARP data of every client connected */ struct rte_mempool *mempool; /**< Mempool for creating ARP update packets */ uint8_t ntt; /**< Flag indicating if we need to send update to any client on next tx */ uint32_t last_slave; /**< Index of last used slave in client table */ rte_spinlock_t lock; }; /** * ALB mode initialization. * * @param bond_dev Pointer to bonding device. * * @return * Error code - 0 on success. */ int bond_mode_alb_enable(struct rte_eth_dev *bond_dev); /** * Function handles ARP packet reception. If received ARP request, it is * forwarded to application without changes. If it is ARP reply, client table * is updated. * * @param eth_h ETH header of received packet. * @param offset Vlan header offset. * @param internals Bonding data. */ void bond_mode_alb_arp_recv(struct ether_hdr *eth_h, uint16_t offset, struct bond_dev_private *internals); /** * Function handles ARP packet transmission. It also decides on which slave * send that packet. If packet is ARP Request, it is send on primary slave. * If it is ARP Reply, it is send on slave stored in client table for that * connection. On Reply function also updates data in client table. * * @param eth_h ETH header of transmitted packet. * @param offset Vlan header offset. * @param internals Bonding data. * * @return * Index of slave on which packet should be sent. */ uint8_t bond_mode_alb_arp_xmit(struct ether_hdr *eth_h, uint16_t offset, struct bond_dev_private *internals); /** * Function fills packet with ARP data from client_info. * * @param client_info Data of client to which packet is sent. * @param pkt Pointer to packet which is sent. * @param internals Bonding data. * * @return * Index of slawe on which packet should be sent. */ uint8_t bond_mode_alb_arp_upd(struct client_data *client_info, struct rte_mbuf *pkt, struct bond_dev_private *internals); /** * Function updates slave indexes of active connections. * * @param bond_dev Pointer to bonded device struct. */ void bond_mode_alb_client_list_upd(struct rte_eth_dev *bond_dev); #endif /* RTE_ETH_BOND_ALB_H_ */ ================================================ FILE: drivers/net/bonding/rte_eth_bond_api.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_eth_bond.h" #include "rte_eth_bond_private.h" #include "rte_eth_bond_8023ad_private.h" #define DEFAULT_POLLING_INTERVAL_10_MS (10) int valid_bonded_ethdev(const struct rte_eth_dev *eth_dev) { /* Check valid pointer */ if (eth_dev->driver->pci_drv.name == NULL) return -1; /* return 0 if driver name matches */ return eth_dev->driver->pci_drv.name != pmd_bond_driver_name; } int valid_bonded_port_id(uint8_t port_id) { if (!rte_eth_dev_is_valid_port(port_id)) return -1; return valid_bonded_ethdev(&rte_eth_devices[port_id]); } int valid_slave_port_id(uint8_t port_id) { /* Verify that port id's are valid */ if (!rte_eth_dev_is_valid_port(port_id)) return -1; /* Verify that port_id refers to a non bonded port */ if (!valid_bonded_ethdev(&rte_eth_devices[port_id])) return -1; return 0; } void activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) { struct bond_dev_private *internals = eth_dev->data->dev_private; uint8_t active_count = internals->active_slave_count; if (internals->mode == BONDING_MODE_8023AD) bond_mode_8023ad_activate_slave(eth_dev, port_id); if (internals->mode == BONDING_MODE_TLB || internals->mode == BONDING_MODE_ALB) { internals->tlb_slaves_order[active_count] = port_id; } RTE_VERIFY(internals->active_slave_count < (RTE_DIM(internals->active_slaves) - 1)); internals->active_slaves[internals->active_slave_count] = port_id; internals->active_slave_count++; if (internals->mode == BONDING_MODE_TLB) bond_tlb_activate_slave(internals); if (internals->mode == BONDING_MODE_ALB) bond_mode_alb_client_list_upd(eth_dev); } void deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) { uint8_t slave_pos; struct bond_dev_private *internals = eth_dev->data->dev_private; uint8_t active_count = internals->active_slave_count; if (internals->mode == BONDING_MODE_8023AD) { bond_mode_8023ad_stop(eth_dev); bond_mode_8023ad_deactivate_slave(eth_dev, port_id); } else if (internals->mode == BONDING_MODE_TLB || internals->mode == BONDING_MODE_ALB) bond_tlb_disable(internals); slave_pos = find_slave_by_id(internals->active_slaves, active_count, port_id); /* If slave was not at the end of the list * shift active slaves up active array list */ if (slave_pos < active_count) { active_count--; memmove(internals->active_slaves + slave_pos, internals->active_slaves + slave_pos + 1, (active_count - slave_pos) * sizeof(internals->active_slaves[0])); } RTE_VERIFY(active_count < RTE_DIM(internals->active_slaves)); internals->active_slave_count = active_count; if (eth_dev->data->dev_started) { if (internals->mode == BONDING_MODE_8023AD) { bond_mode_8023ad_start(eth_dev); } else if (internals->mode == BONDING_MODE_TLB) { bond_tlb_enable(internals); } else if (internals->mode == BONDING_MODE_ALB) { bond_tlb_enable(internals); bond_mode_alb_client_list_upd(eth_dev); } } } uint8_t number_of_sockets(void) { int sockets = 0; int i; const struct rte_memseg *ms = rte_eal_get_physmem_layout(); for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) { if (sockets < ms[i].socket_id) sockets = ms[i].socket_id; } /* Number of sockets = maximum socket_id + 1 */ return ++sockets; } const char pmd_bond_driver_name[] = "rte_bond_pmd"; static struct rte_pci_id pci_id_table = { .device_id = PCI_ANY_ID, .subsystem_device_id = PCI_ANY_ID, .vendor_id = PCI_ANY_ID, .subsystem_vendor_id = PCI_ANY_ID, }; static struct eth_driver rte_bond_pmd = { .pci_drv = { .name = pmd_bond_driver_name, .drv_flags = RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, .id_table = &pci_id_table, }, }; int rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id) { struct rte_pci_device *pci_dev = NULL; struct bond_dev_private *internals = NULL; struct rte_eth_dev *eth_dev = NULL; struct rte_pci_driver *pci_drv = NULL; /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ if (name == NULL) { RTE_BOND_LOG(ERR, "Invalid name specified"); goto err; } if (socket_id >= number_of_sockets()) { RTE_BOND_LOG(ERR, "Invalid socket id specified to create bonded device on."); goto err; } pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id); if (pci_dev == NULL) { RTE_BOND_LOG(ERR, "Unable to malloc pci dev on socket"); goto err; } pci_drv = &rte_bond_pmd.pci_drv; internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id); if (internals == NULL) { RTE_BOND_LOG(ERR, "Unable to malloc internals on socket"); goto err; } /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (eth_dev == NULL) { RTE_BOND_LOG(ERR, "Unable to allocate rte_eth_dev"); goto err; } pci_dev->numa_node = socket_id; pci_drv->name = pmd_bond_driver_name; pci_dev->driver = pci_drv; eth_dev->driver = &rte_bond_pmd; eth_dev->data->dev_private = internals; eth_dev->data->nb_rx_queues = (uint16_t)1; eth_dev->data->nb_tx_queues = (uint16_t)1; TAILQ_INIT(&(eth_dev->link_intr_cbs)); eth_dev->data->dev_link.link_status = 0; eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0, socket_id); if (eth_dev->data->mac_addrs == NULL) { RTE_BOND_LOG(ERR, "Unable to malloc mac_addrs"); goto err; } eth_dev->data->dev_started = 0; eth_dev->data->promiscuous = 0; eth_dev->data->scattered_rx = 0; eth_dev->data->all_multicast = 0; eth_dev->dev_ops = &default_dev_ops; eth_dev->pci_dev = pci_dev; rte_spinlock_init(&internals->lock); internals->port_id = eth_dev->data->port_id; internals->mode = BONDING_MODE_INVALID; internals->current_primary_port = 0; internals->balance_xmit_policy = BALANCE_XMIT_POLICY_LAYER2; internals->xmit_hash = xmit_l2_hash; internals->user_defined_mac = 0; internals->link_props_set = 0; internals->link_status_polling_enabled = 0; internals->link_status_polling_interval_ms = DEFAULT_POLLING_INTERVAL_10_MS; internals->link_down_delay_ms = 0; internals->link_up_delay_ms = 0; internals->slave_count = 0; internals->active_slave_count = 0; internals->rx_offload_capa = 0; internals->tx_offload_capa = 0; memset(internals->active_slaves, 0, sizeof(internals->active_slaves)); memset(internals->slaves, 0, sizeof(internals->slaves)); /* Set mode 4 default configuration */ bond_mode_8023ad_setup(eth_dev, NULL); if (bond_ethdev_mode_set(eth_dev, mode)) { RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode too %d", eth_dev->data->port_id, mode); goto err; } return eth_dev->data->port_id; err: rte_free(pci_dev); rte_free(internals); if (eth_dev != NULL) { rte_free(eth_dev->data->mac_addrs); rte_eth_dev_release_port(eth_dev); } return -1; } int rte_eth_bond_free(const char *name) { struct rte_eth_dev *eth_dev = NULL; /* now free all data allocation - for eth_dev structure, * dummy pci driver and internal (private) data */ /* find an ethdev entry */ eth_dev = rte_eth_dev_allocated(name); if (eth_dev == NULL) return -ENODEV; if (eth_dev->data->dev_started == 1) { bond_ethdev_stop(eth_dev); bond_ethdev_close(eth_dev); } eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; rte_free(eth_dev->pci_dev); rte_free(eth_dev->data->dev_private); rte_free(eth_dev->data->mac_addrs); rte_eth_dev_release_port(eth_dev); return 0; } static int __eth_bond_slave_add_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; struct bond_dev_private *internals; struct bond_dev_private *temp_internals; struct rte_eth_link link_props; struct rte_eth_dev_info dev_info; int i, j; if (valid_slave_port_id(slave_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; /* Verify that new slave device is not already a slave of another * bonded device */ for (i = rte_eth_dev_count()-1; i >= 0; i--) { if (valid_bonded_ethdev(&rte_eth_devices[i]) == 0) { temp_internals = rte_eth_devices[i].data->dev_private; for (j = 0; j < temp_internals->slave_count; j++) { /* Device already a slave of a bonded device */ if (temp_internals->slaves[j].port_id == slave_port_id) { RTE_BOND_LOG(ERR, "Slave port %d is already a slave", slave_port_id); return -1; } } } } slave_eth_dev = &rte_eth_devices[slave_port_id]; /* Add slave details to bonded device */ slave_add(internals, slave_eth_dev); rte_eth_dev_info_get(slave_port_id, &dev_info); if (internals->slave_count < 1) { /* if MAC is not user defined then use MAC of first slave add to * bonded device */ if (!internals->user_defined_mac) mac_address_set(bonded_eth_dev, slave_eth_dev->data->mac_addrs); /* Inherit eth dev link properties from first slave */ link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); /* Make primary slave */ internals->primary_port = slave_port_id; /* Take the first dev's offload capabilities */ internals->rx_offload_capa = dev_info.rx_offload_capa; internals->tx_offload_capa = dev_info.tx_offload_capa; } else { /* Check slave link properties are supported if props are set, * all slaves must be the same */ if (internals->link_props_set) { if (link_properties_valid(&(bonded_eth_dev->data->dev_link), &(slave_eth_dev->data->dev_link))) { RTE_BOND_LOG(ERR, "Slave port %d link speed/duplex not supported", slave_port_id); return -1; } } else { link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); } internals->rx_offload_capa &= dev_info.rx_offload_capa; internals->tx_offload_capa &= dev_info.tx_offload_capa; } internals->slave_count++; /* Update all slave devices MACs*/ mac_address_slaves_update(bonded_eth_dev); if (bonded_eth_dev->data->dev_started) { if (slave_configure(bonded_eth_dev, slave_eth_dev) != 0) { RTE_BOND_LOG(ERR, "rte_bond_slaves_configure: port=%d", slave_port_id); return -1; } } /* Register link status change callback with bonded device pointer as * argument*/ rte_eth_dev_callback_register(slave_port_id, RTE_ETH_EVENT_INTR_LSC, bond_ethdev_lsc_event_callback, &bonded_eth_dev->data->port_id); /* If bonded device is started then we can add the slave to our active * slave array */ if (bonded_eth_dev->data->dev_started) { rte_eth_link_get_nowait(slave_port_id, &link_props); if (link_props.link_status == 1) activate_slave(bonded_eth_dev, slave_port_id); } return 0; } int rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; int retval; /* Verify that port id's are valid bonded and slave ports */ if (valid_bonded_port_id(bonded_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; rte_spinlock_lock(&internals->lock); retval = __eth_bond_slave_add_lock_free(bonded_port_id, slave_port_id); rte_spinlock_unlock(&internals->lock); return retval; } static int __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; int i, slave_idx; if (valid_slave_port_id(slave_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; /* first remove from active slave list */ slave_idx = find_slave_by_id(internals->active_slaves, internals->active_slave_count, slave_port_id); if (slave_idx < internals->active_slave_count) deactivate_slave(bonded_eth_dev, slave_port_id); slave_idx = -1; /* now find in slave list */ for (i = 0; i < internals->slave_count; i++) if (internals->slaves[i].port_id == slave_port_id) { slave_idx = i; break; } if (slave_idx < 0) { RTE_BOND_LOG(ERR, "Couldn't find slave in port list, slave count %d", internals->slave_count); return -1; } /* Un-register link status change callback with bonded device pointer as * argument*/ rte_eth_dev_callback_unregister(slave_port_id, RTE_ETH_EVENT_INTR_LSC, bond_ethdev_lsc_event_callback, &rte_eth_devices[bonded_port_id].data->port_id); /* Restore original MAC address of slave device */ mac_address_set(&rte_eth_devices[slave_port_id], &(internals->slaves[slave_idx].persisted_mac_addr)); slave_remove(internals, &rte_eth_devices[slave_port_id]); /* first slave in the active list will be the primary by default, * otherwise use first device in list */ if (internals->current_primary_port == slave_port_id) { if (internals->active_slave_count > 0) internals->current_primary_port = internals->active_slaves[0]; else if (internals->slave_count > 0) internals->current_primary_port = internals->slaves[0].port_id; else internals->primary_port = 0; } if (internals->active_slave_count < 1) { /* reset device link properties as no slaves are active */ link_properties_reset(&rte_eth_devices[bonded_port_id]); /* if no slaves are any longer attached to bonded device and MAC is not * user defined then clear MAC of bonded device as it will be reset * when a new slave is added */ if (internals->slave_count < 1 && !internals->user_defined_mac) memset(rte_eth_devices[bonded_port_id].data->mac_addrs, 0, sizeof(*(rte_eth_devices[bonded_port_id].data->mac_addrs))); } if (internals->slave_count == 0) { internals->rx_offload_capa = 0; internals->tx_offload_capa = 0; } return 0; } int rte_eth_bond_slave_remove(uint8_t bonded_port_id, uint8_t slave_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; int retval; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; rte_spinlock_lock(&internals->lock); retval = __eth_bond_slave_remove_lock_free(bonded_port_id, slave_port_id); rte_spinlock_unlock(&internals->lock); return retval; } int rte_eth_bond_mode_set(uint8_t bonded_port_id, uint8_t mode) { if (valid_bonded_port_id(bonded_port_id) != 0) return -1; return bond_ethdev_mode_set(&rte_eth_devices[bonded_port_id], mode); } int rte_eth_bond_mode_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; return internals->mode; } int rte_eth_bond_primary_set(uint8_t bonded_port_id, uint8_t slave_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; if (valid_slave_port_id(slave_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; internals->user_defined_primary_port = 1; internals->primary_port = slave_port_id; bond_ethdev_primary_set(internals, slave_port_id); return 0; } int rte_eth_bond_primary_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; if (internals->slave_count < 1) return -1; return internals->current_primary_port; } int rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len) { struct bond_dev_private *internals; uint8_t i; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; if (slaves == NULL) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; if (internals->slave_count > len) return -1; for (i = 0; i < internals->slave_count; i++) slaves[i] = internals->slaves[i].port_id; return internals->slave_count; } int rte_eth_bond_active_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_t len) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; if (slaves == NULL) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; if (internals->active_slave_count > len) return -1; memcpy(slaves, internals->active_slaves, internals->active_slave_count); return internals->active_slave_count; } int rte_eth_bond_mac_address_set(uint8_t bonded_port_id, struct ether_addr *mac_addr) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; /* Set MAC Address of Bonded Device */ if (mac_address_set(bonded_eth_dev, mac_addr)) return -1; internals->user_defined_mac = 1; /* Update all slave devices MACs*/ if (internals->slave_count > 0) return mac_address_slaves_update(bonded_eth_dev); return 0; } int rte_eth_bond_mac_address_reset(uint8_t bonded_port_id) { struct rte_eth_dev *bonded_eth_dev; struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; bonded_eth_dev = &rte_eth_devices[bonded_port_id]; internals = bonded_eth_dev->data->dev_private; internals->user_defined_mac = 0; if (internals->slave_count > 0) { /* Set MAC Address of Bonded Device */ if (mac_address_set(bonded_eth_dev, &internals->slaves[internals->primary_port].persisted_mac_addr) != 0) { RTE_BOND_LOG(ERR, "Failed to set MAC address on bonded device"); return -1; } /* Update all slave devices MAC addresses */ return mac_address_slaves_update(bonded_eth_dev); } /* No need to update anything as no slaves present */ return 0; } int rte_eth_bond_xmit_policy_set(uint8_t bonded_port_id, uint8_t policy) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; switch (policy) { case BALANCE_XMIT_POLICY_LAYER2: internals->balance_xmit_policy = policy; internals->xmit_hash = xmit_l2_hash; break; case BALANCE_XMIT_POLICY_LAYER23: internals->balance_xmit_policy = policy; internals->xmit_hash = xmit_l23_hash; break; case BALANCE_XMIT_POLICY_LAYER34: internals->balance_xmit_policy = policy; internals->xmit_hash = xmit_l34_hash; break; default: return -1; } return 0; } int rte_eth_bond_xmit_policy_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; return internals->balance_xmit_policy; } int rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t internal_ms) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; internals->link_status_polling_interval_ms = internal_ms; return 0; } int rte_eth_bond_link_monitoring_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; return internals->link_status_polling_interval_ms; } int rte_eth_bond_link_down_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; internals->link_down_delay_ms = delay_ms; return 0; } int rte_eth_bond_link_down_prop_delay_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; return internals->link_down_delay_ms; } int rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t delay_ms) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; internals->link_up_delay_ms = delay_ms; return 0; } int rte_eth_bond_link_up_prop_delay_get(uint8_t bonded_port_id) { struct bond_dev_private *internals; if (valid_bonded_port_id(bonded_port_id) != 0) return -1; internals = rte_eth_devices[bonded_port_id].data->dev_private; return internals->link_up_delay_ms; } ================================================ FILE: drivers/net/bonding/rte_eth_bond_args.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "rte_eth_bond.h" #include "rte_eth_bond_private.h" const char *pmd_bond_init_valid_arguments[] = { PMD_BOND_SLAVE_PORT_KVARG, PMD_BOND_PRIMARY_SLAVE_KVARG, PMD_BOND_MODE_KVARG, PMD_BOND_XMIT_POLICY_KVARG, PMD_BOND_SOCKET_ID_KVARG, PMD_BOND_MAC_ADDR_KVARG, NULL }; static inline int find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr) { struct rte_pci_addr *eth_pci_addr; unsigned i; for (i = 0; i < rte_eth_dev_count(); i++) { if (rte_eth_devices[i].pci_dev == NULL) continue; eth_pci_addr = &(rte_eth_devices[i].pci_dev->addr); if (pci_addr->bus == eth_pci_addr->bus && pci_addr->devid == eth_pci_addr->devid && pci_addr->domain == eth_pci_addr->domain && pci_addr->function == eth_pci_addr->function) return i; } return -1; } static inline int find_port_id_by_dev_name(const char *name) { unsigned i; for (i = 0; i < rte_eth_dev_count(); i++) { if (rte_eth_devices[i].data == NULL) continue; if (strcmp(rte_eth_devices[i].data->name, name) == 0) return i; } return -1; } /** * Parses a port identifier string to a port id by pci address, then by name, * and finally port id. */ static inline int parse_port_id(const char *port_str) { struct rte_pci_addr dev_addr; int port_id; /* try parsing as pci address, physical devices */ if (eal_parse_pci_DomBDF(port_str, &dev_addr) == 0) { port_id = find_port_id_by_pci_addr(&dev_addr); if (port_id < 0) return -1; } else { /* try parsing as device name, virtual devices */ port_id = find_port_id_by_dev_name(port_str); if (port_id < 0) { char *end; errno = 0; /* try parsing as port id */ port_id = strtol(port_str, &end, 10); if (*end != 0 || errno != 0) return -1; } } if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) { RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range", port_str); return -1; } return port_id; } int bond_ethdev_parse_slave_port_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { struct bond_ethdev_slave_ports *slave_ports; if (value == NULL || extra_args == NULL) return -1; slave_ports = extra_args; if (strcmp(key, PMD_BOND_SLAVE_PORT_KVARG) == 0) { int port_id = parse_port_id(value); if (port_id < 0) { RTE_BOND_LOG(ERR, "Invalid slave port value (%s) specified", value); return -1; } else slave_ports->slaves[slave_ports->slave_count++] = (uint8_t)port_id; } return 0; } int bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { uint8_t *mode; char *endptr; if (value == NULL || extra_args == NULL) return -1; mode = extra_args; errno = 0; *mode = strtol(value, &endptr, 10); if (*endptr != 0 || errno != 0) return -1; /* validate mode value */ switch (*mode) { case BONDING_MODE_ROUND_ROBIN: case BONDING_MODE_ACTIVE_BACKUP: case BONDING_MODE_BALANCE: case BONDING_MODE_BROADCAST: case BONDING_MODE_8023AD: case BONDING_MODE_TLB: case BONDING_MODE_ALB: return 0; default: RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) specified", value); return -1; } } int bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { int socket_id; char *endptr; if (value == NULL || extra_args == NULL) return -1; errno = 0; socket_id = (uint8_t)strtol(value, &endptr, 10); if (*endptr != 0 || errno != 0) return -1; /* validate mode value */ if (socket_id >= 0 && socket_id < number_of_sockets()) { *(uint8_t *)extra_args = (uint8_t)socket_id; return 0; } return -1; } int bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { int primary_slave_port_id; if (value == NULL || extra_args == NULL) return -1; primary_slave_port_id = parse_port_id(value); if (primary_slave_port_id < 0) return -1; *(uint8_t *)extra_args = (uint8_t)primary_slave_port_id; return 0; } int bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { uint8_t *xmit_policy; if (value == NULL || extra_args == NULL) return -1; xmit_policy = extra_args; if (strcmp(PMD_BOND_XMIT_POLICY_LAYER2_KVARG, value) == 0) *xmit_policy = BALANCE_XMIT_POLICY_LAYER2; else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER23_KVARG, value) == 0) *xmit_policy = BALANCE_XMIT_POLICY_LAYER23; else if (strcmp(PMD_BOND_XMIT_POLICY_LAYER34_KVARG, value) == 0) *xmit_policy = BALANCE_XMIT_POLICY_LAYER34; else return -1; return 0; } int bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { if (value == NULL || extra_args == NULL) return -1; /* Parse MAC */ return cmdline_parse_etheraddr(NULL, value, extra_args, sizeof(struct ether_addr)); } int bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, const char *value, void *extra_args) { uint32_t time_ms; char *endptr; if (value == NULL || extra_args == NULL) return -1; errno = 0; time_ms = (uint32_t)strtol(value, &endptr, 10); if (*endptr != 0 || errno != 0) return -1; *(uint32_t *)extra_args = time_ms; return 0; } ================================================ FILE: drivers/net/bonding/rte_eth_bond_pmd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_eth_bond.h" #include "rte_eth_bond_private.h" #include "rte_eth_bond_8023ad_private.h" #define REORDER_PERIOD_MS 10 #define HASH_L4_PORTS(h) ((h)->src_port ^ (h)->dst_port) /* Table for statistics in mode 5 TLB */ static uint64_t tlb_last_obytets[RTE_MAX_ETHPORTS]; static inline size_t get_vlan_offset(struct ether_hdr *eth_hdr, uint16_t *proto) { size_t vlan_offset = 0; if (rte_cpu_to_be_16(ETHER_TYPE_VLAN) == *proto) { struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); vlan_offset = sizeof(struct vlan_hdr); *proto = vlan_hdr->eth_proto; if (rte_cpu_to_be_16(ETHER_TYPE_VLAN) == *proto) { vlan_hdr = vlan_hdr + 1; *proto = vlan_hdr->eth_proto; vlan_offset += sizeof(struct vlan_hdr); } } return vlan_offset; } static uint16_t bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; uint16_t num_rx_slave = 0; uint16_t num_rx_total = 0; int i; /* Cast to structure, containing bonded device's port id and queue id */ struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue; internals = bd_rx_q->dev_private; for (i = 0; i < internals->active_slave_count && nb_pkts; i++) { /* Offset of pointer to *bufs increases as packets are received * from other slaves */ num_rx_slave = rte_eth_rx_burst(internals->active_slaves[i], bd_rx_q->queue_id, bufs + num_rx_total, nb_pkts); if (num_rx_slave) { num_rx_total += num_rx_slave; nb_pkts -= num_rx_slave; } } return num_rx_total; } static uint16_t bond_ethdev_rx_burst_active_backup(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; /* Cast to structure, containing bonded device's port id and queue id */ struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue; internals = bd_rx_q->dev_private; return rte_eth_rx_burst(internals->current_primary_port, bd_rx_q->queue_id, bufs, nb_pkts); } static uint16_t bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Cast to structure, containing bonded device's port id and queue id */ struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue; struct bond_dev_private *internals = bd_rx_q->dev_private; struct ether_addr bond_mac; struct ether_hdr *hdr; const uint16_t ether_type_slow_be = rte_be_to_cpu_16(ETHER_TYPE_SLOW); uint16_t num_rx_total = 0; /* Total number of received packets */ uint8_t slaves[RTE_MAX_ETHPORTS]; uint8_t slave_count; uint8_t collecting; /* current slave collecting status */ const uint8_t promisc = internals->promiscuous_en; uint8_t i, j, k; rte_eth_macaddr_get(internals->port_id, &bond_mac); /* Copy slave list to protect against slave up/down changes during tx * bursting */ slave_count = internals->active_slave_count; memcpy(slaves, internals->active_slaves, sizeof(internals->active_slaves[0]) * slave_count); for (i = 0; i < slave_count && num_rx_total < nb_pkts; i++) { j = num_rx_total; collecting = ACTOR_STATE(&mode_8023ad_ports[slaves[i]], COLLECTING); /* Read packets from this slave */ num_rx_total += rte_eth_rx_burst(slaves[i], bd_rx_q->queue_id, &bufs[num_rx_total], nb_pkts - num_rx_total); for (k = j; k < 2 && k < num_rx_total; k++) rte_prefetch0(rte_pktmbuf_mtod(bufs[k], void *)); /* Handle slow protocol packets. */ while (j < num_rx_total) { if (j + 3 < num_rx_total) rte_prefetch0(rte_pktmbuf_mtod(bufs[j + 3], void *)); hdr = rte_pktmbuf_mtod(bufs[j], struct ether_hdr *); /* Remove packet from array if it is slow packet or slave is not * in collecting state or bondign interface is not in promiscus * mode and packet address does not match. */ if (unlikely(hdr->ether_type == ether_type_slow_be || !collecting || (!promisc && !is_same_ether_addr(&bond_mac, &hdr->d_addr)))) { if (hdr->ether_type == ether_type_slow_be) { bond_mode_8023ad_handle_slow_pkt(internals, slaves[i], bufs[j]); } else rte_pktmbuf_free(bufs[j]); /* Packet is managed by mode 4 or dropped, shift the array */ num_rx_total--; if (j < num_rx_total) { memmove(&bufs[j], &bufs[j + 1], sizeof(bufs[0]) * (num_rx_total - j)); } } else j++; } } return num_rx_total; } #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) uint32_t burstnumberRX; uint32_t burstnumberTX; #ifdef RTE_LIBRTE_BOND_DEBUG_ALB static void arp_op_name(uint16_t arp_op, char *buf) { switch (arp_op) { case ARP_OP_REQUEST: snprintf(buf, sizeof("ARP Request"), "%s", "ARP Request"); return; case ARP_OP_REPLY: snprintf(buf, sizeof("ARP Reply"), "%s", "ARP Reply"); return; case ARP_OP_REVREQUEST: snprintf(buf, sizeof("Reverse ARP Request"), "%s", "Reverse ARP Request"); return; case ARP_OP_REVREPLY: snprintf(buf, sizeof("Reverse ARP Reply"), "%s", "Reverse ARP Reply"); return; case ARP_OP_INVREQUEST: snprintf(buf, sizeof("Peer Identify Request"), "%s", "Peer Identify Request"); return; case ARP_OP_INVREPLY: snprintf(buf, sizeof("Peer Identify Reply"), "%s", "Peer Identify Reply"); return; default: break; } snprintf(buf, sizeof("Unknown"), "%s", "Unknown"); return; } #endif #define MaxIPv4String 16 static void ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf, uint8_t buf_size) { uint32_t ipv4_addr; ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr); snprintf(buf, buf_size, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF, (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF, ipv4_addr & 0xFF); } #define MAX_CLIENTS_NUMBER 128 uint8_t active_clients; struct client_stats_t { uint8_t port; uint32_t ipv4_addr; uint32_t ipv4_rx_packets; uint32_t ipv4_tx_packets; }; struct client_stats_t client_stats[MAX_CLIENTS_NUMBER]; static void update_client_stats(uint32_t addr, uint8_t port, uint32_t *TXorRXindicator) { int i = 0; for (; i < MAX_CLIENTS_NUMBER; i++) { if ((client_stats[i].ipv4_addr == addr) && (client_stats[i].port == port)) { /* Just update RX packets number for this client */ if (TXorRXindicator == &burstnumberRX) client_stats[i].ipv4_rx_packets++; else client_stats[i].ipv4_tx_packets++; return; } } /* We have a new client. Insert him to the table, and increment stats */ if (TXorRXindicator == &burstnumberRX) client_stats[active_clients].ipv4_rx_packets++; else client_stats[active_clients].ipv4_tx_packets++; client_stats[active_clients].ipv4_addr = addr; client_stats[active_clients].port = port; active_clients++; } #ifdef RTE_LIBRTE_BOND_DEBUG_ALB #define MODE6_DEBUG(info, src_ip, dst_ip, eth_h, arp_op, port, burstnumber) \ RTE_LOG(DEBUG, PMD, \ "%s " \ "port:%d " \ "SrcMAC:%02X:%02X:%02X:%02X:%02X:%02X " \ "SrcIP:%s " \ "DstMAC:%02X:%02X:%02X:%02X:%02X:%02X " \ "DstIP:%s " \ "%s " \ "%d\n", \ info, \ port, \ eth_h->s_addr.addr_bytes[0], \ eth_h->s_addr.addr_bytes[1], \ eth_h->s_addr.addr_bytes[2], \ eth_h->s_addr.addr_bytes[3], \ eth_h->s_addr.addr_bytes[4], \ eth_h->s_addr.addr_bytes[5], \ src_ip, \ eth_h->d_addr.addr_bytes[0], \ eth_h->d_addr.addr_bytes[1], \ eth_h->d_addr.addr_bytes[2], \ eth_h->d_addr.addr_bytes[3], \ eth_h->d_addr.addr_bytes[4], \ eth_h->d_addr.addr_bytes[5], \ dst_ip, \ arp_op, \ ++burstnumber) #endif static void mode6_debug(const char __attribute__((unused)) *info, struct ether_hdr *eth_h, uint8_t port, uint32_t __attribute__((unused)) *burstnumber) { struct ipv4_hdr *ipv4_h; #ifdef RTE_LIBRTE_BOND_DEBUG_ALB struct arp_hdr *arp_h; char dst_ip[16]; char ArpOp[24]; char buf[16]; #endif char src_ip[16]; uint16_t ether_type = eth_h->ether_type; uint16_t offset = get_vlan_offset(eth_h, ðer_type); #ifdef RTE_LIBRTE_BOND_DEBUG_ALB snprintf(buf, 16, "%s", info); #endif if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { ipv4_h = (struct ipv4_hdr *)((char *)(eth_h + 1) + offset); ipv4_addr_to_dot(ipv4_h->src_addr, src_ip, MaxIPv4String); #ifdef RTE_LIBRTE_BOND_DEBUG_ALB ipv4_addr_to_dot(ipv4_h->dst_addr, dst_ip, MaxIPv4String); MODE6_DEBUG(buf, src_ip, dst_ip, eth_h, "", port, *burstnumber); #endif update_client_stats(ipv4_h->src_addr, port, burstnumber); } #ifdef RTE_LIBRTE_BOND_DEBUG_ALB else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) { arp_h = (struct arp_hdr *)((char *)(eth_h + 1) + offset); ipv4_addr_to_dot(arp_h->arp_data.arp_sip, src_ip, MaxIPv4String); ipv4_addr_to_dot(arp_h->arp_data.arp_tip, dst_ip, MaxIPv4String); arp_op_name(rte_be_to_cpu_16(arp_h->arp_op), ArpOp); MODE6_DEBUG(buf, src_ip, dst_ip, eth_h, ArpOp, port, *burstnumber); } #endif } #endif static uint16_t bond_ethdev_rx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue; struct bond_dev_private *internals = bd_tx_q->dev_private; struct ether_hdr *eth_h; uint16_t ether_type, offset; uint16_t nb_recv_pkts; int i; nb_recv_pkts = bond_ethdev_rx_burst(queue, bufs, nb_pkts); for (i = 0; i < nb_recv_pkts; i++) { eth_h = rte_pktmbuf_mtod(bufs[i], struct ether_hdr *); ether_type = eth_h->ether_type; offset = get_vlan_offset(eth_h, ðer_type); if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) { #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) mode6_debug("RX ARP:", eth_h, bufs[i]->port, &burstnumberRX); #endif bond_mode_alb_arp_recv(eth_h, offset, internals); } #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) mode6_debug("RX IPv4:", eth_h, bufs[i]->port, &burstnumberRX); #endif } return nb_recv_pkts; } static uint16_t bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; struct bond_tx_queue *bd_tx_q; struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts]; uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 }; uint8_t num_of_slaves; uint8_t slaves[RTE_MAX_ETHPORTS]; uint16_t num_tx_total = 0, num_tx_slave; static int slave_idx = 0; int i, cslave_idx = 0, tx_fail_total = 0; bd_tx_q = (struct bond_tx_queue *)queue; internals = bd_tx_q->dev_private; /* Copy slave list to protect against slave up/down changes during tx * bursting */ num_of_slaves = internals->active_slave_count; memcpy(slaves, internals->active_slaves, sizeof(internals->active_slaves[0]) * num_of_slaves); if (num_of_slaves < 1) return num_tx_total; /* Populate slaves mbuf with which packets are to be sent on it */ for (i = 0; i < nb_pkts; i++) { cslave_idx = (slave_idx + i) % num_of_slaves; slave_bufs[cslave_idx][(slave_nb_pkts[cslave_idx])++] = bufs[i]; } /* increment current slave index so the next call to tx burst starts on the * next slave */ slave_idx = ++cslave_idx; /* Send packet burst on each slave device */ for (i = 0; i < num_of_slaves; i++) { if (slave_nb_pkts[i] > 0) { num_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id, slave_bufs[i], slave_nb_pkts[i]); /* if tx burst fails move packets to end of bufs */ if (unlikely(num_tx_slave < slave_nb_pkts[i])) { int tx_fail_slave = slave_nb_pkts[i] - num_tx_slave; tx_fail_total += tx_fail_slave; memcpy(&bufs[nb_pkts - tx_fail_total], &slave_bufs[i][num_tx_slave], tx_fail_slave * sizeof(bufs[0])); } num_tx_total += num_tx_slave; } } return num_tx_total; } static uint16_t bond_ethdev_tx_burst_active_backup(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; struct bond_tx_queue *bd_tx_q; bd_tx_q = (struct bond_tx_queue *)queue; internals = bd_tx_q->dev_private; if (internals->active_slave_count < 1) return 0; return rte_eth_tx_burst(internals->current_primary_port, bd_tx_q->queue_id, bufs, nb_pkts); } static inline uint16_t ether_hash(struct ether_hdr *eth_hdr) { unaligned_uint16_t *word_src_addr = (unaligned_uint16_t *)eth_hdr->s_addr.addr_bytes; unaligned_uint16_t *word_dst_addr = (unaligned_uint16_t *)eth_hdr->d_addr.addr_bytes; return (word_src_addr[0] ^ word_dst_addr[0]) ^ (word_src_addr[1] ^ word_dst_addr[1]) ^ (word_src_addr[2] ^ word_dst_addr[2]); } static inline uint32_t ipv4_hash(struct ipv4_hdr *ipv4_hdr) { return (ipv4_hdr->src_addr ^ ipv4_hdr->dst_addr); } static inline uint32_t ipv6_hash(struct ipv6_hdr *ipv6_hdr) { unaligned_uint32_t *word_src_addr = (unaligned_uint32_t *)&(ipv6_hdr->src_addr[0]); unaligned_uint32_t *word_dst_addr = (unaligned_uint32_t *)&(ipv6_hdr->dst_addr[0]); return (word_src_addr[0] ^ word_dst_addr[0]) ^ (word_src_addr[1] ^ word_dst_addr[1]) ^ (word_src_addr[2] ^ word_dst_addr[2]) ^ (word_src_addr[3] ^ word_dst_addr[3]); } uint16_t xmit_l2_hash(const struct rte_mbuf *buf, uint8_t slave_count) { struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(buf, struct ether_hdr *); uint32_t hash = ether_hash(eth_hdr); return (hash ^= hash >> 8) % slave_count; } uint16_t xmit_l23_hash(const struct rte_mbuf *buf, uint8_t slave_count) { struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(buf, struct ether_hdr *); uint16_t proto = eth_hdr->ether_type; size_t vlan_offset = get_vlan_offset(eth_hdr, &proto); uint32_t hash, l3hash = 0; hash = ether_hash(eth_hdr); if (rte_cpu_to_be_16(ETHER_TYPE_IPv4) == proto) { struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *) ((char *)(eth_hdr + 1) + vlan_offset); l3hash = ipv4_hash(ipv4_hdr); } else if (rte_cpu_to_be_16(ETHER_TYPE_IPv6) == proto) { struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *) ((char *)(eth_hdr + 1) + vlan_offset); l3hash = ipv6_hash(ipv6_hdr); } hash = hash ^ l3hash; hash ^= hash >> 16; hash ^= hash >> 8; return hash % slave_count; } uint16_t xmit_l34_hash(const struct rte_mbuf *buf, uint8_t slave_count) { struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(buf, struct ether_hdr *); uint16_t proto = eth_hdr->ether_type; size_t vlan_offset = get_vlan_offset(eth_hdr, &proto); struct udp_hdr *udp_hdr = NULL; struct tcp_hdr *tcp_hdr = NULL; uint32_t hash, l3hash = 0, l4hash = 0; if (rte_cpu_to_be_16(ETHER_TYPE_IPv4) == proto) { struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *) ((char *)(eth_hdr + 1) + vlan_offset); size_t ip_hdr_offset; l3hash = ipv4_hash(ipv4_hdr); ip_hdr_offset = (ipv4_hdr->version_ihl & IPV4_HDR_IHL_MASK) * IPV4_IHL_MULTIPLIER; if (ipv4_hdr->next_proto_id == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + ip_hdr_offset); l4hash = HASH_L4_PORTS(tcp_hdr); } else if (ipv4_hdr->next_proto_id == IPPROTO_UDP) { udp_hdr = (struct udp_hdr *)((char *)ipv4_hdr + ip_hdr_offset); l4hash = HASH_L4_PORTS(udp_hdr); } } else if (rte_cpu_to_be_16(ETHER_TYPE_IPv6) == proto) { struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *) ((char *)(eth_hdr + 1) + vlan_offset); l3hash = ipv6_hash(ipv6_hdr); if (ipv6_hdr->proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)(ipv6_hdr + 1); l4hash = HASH_L4_PORTS(tcp_hdr); } else if (ipv6_hdr->proto == IPPROTO_UDP) { udp_hdr = (struct udp_hdr *)(ipv6_hdr + 1); l4hash = HASH_L4_PORTS(udp_hdr); } } hash = l3hash ^ l4hash; hash ^= hash >> 16; hash ^= hash >> 8; return hash % slave_count; } struct bwg_slave { uint64_t bwg_left_int; uint64_t bwg_left_remainder; uint8_t slave; }; void bond_tlb_activate_slave(struct bond_dev_private *internals) { int i; for (i = 0; i < internals->active_slave_count; i++) { tlb_last_obytets[internals->active_slaves[i]] = 0; } } static int bandwidth_cmp(const void *a, const void *b) { const struct bwg_slave *bwg_a = a; const struct bwg_slave *bwg_b = b; int64_t diff = (int64_t)bwg_b->bwg_left_int - (int64_t)bwg_a->bwg_left_int; int64_t diff2 = (int64_t)bwg_b->bwg_left_remainder - (int64_t)bwg_a->bwg_left_remainder; if (diff > 0) return 1; else if (diff < 0) return -1; else if (diff2 > 0) return 1; else if (diff2 < 0) return -1; else return 0; } static void bandwidth_left(uint8_t port_id, uint64_t load, uint8_t update_idx, struct bwg_slave *bwg_slave) { struct rte_eth_link link_status; rte_eth_link_get(port_id, &link_status); uint64_t link_bwg = link_status.link_speed * 1000000ULL / 8; if (link_bwg == 0) return; link_bwg = link_bwg * (update_idx+1) * REORDER_PERIOD_MS; bwg_slave->bwg_left_int = (link_bwg - 1000*load) / link_bwg; bwg_slave->bwg_left_remainder = (link_bwg - 1000*load) % link_bwg; } static void bond_ethdev_update_tlb_slave_cb(void *arg) { struct bond_dev_private *internals = arg; struct rte_eth_stats slave_stats; struct bwg_slave bwg_array[RTE_MAX_ETHPORTS]; uint8_t slave_count; uint64_t tx_bytes; uint8_t update_stats = 0; uint8_t i, slave_id; internals->slave_update_idx++; if (internals->slave_update_idx >= REORDER_PERIOD_MS) update_stats = 1; for (i = 0; i < internals->active_slave_count; i++) { slave_id = internals->active_slaves[i]; rte_eth_stats_get(slave_id, &slave_stats); tx_bytes = slave_stats.obytes - tlb_last_obytets[slave_id]; bandwidth_left(slave_id, tx_bytes, internals->slave_update_idx, &bwg_array[i]); bwg_array[i].slave = slave_id; if (update_stats) { tlb_last_obytets[slave_id] = slave_stats.obytes; } } if (update_stats == 1) internals->slave_update_idx = 0; slave_count = i; qsort(bwg_array, slave_count, sizeof(bwg_array[0]), bandwidth_cmp); for (i = 0; i < slave_count; i++) internals->tlb_slaves_order[i] = bwg_array[i].slave; rte_eal_alarm_set(REORDER_PERIOD_MS * 1000, bond_ethdev_update_tlb_slave_cb, (struct bond_dev_private *)internals); } static uint16_t bond_ethdev_tx_burst_tlb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue; struct bond_dev_private *internals = bd_tx_q->dev_private; struct rte_eth_dev *primary_port = &rte_eth_devices[internals->primary_port]; uint16_t num_tx_total = 0; uint8_t i, j; uint8_t num_of_slaves = internals->active_slave_count; uint8_t slaves[RTE_MAX_ETHPORTS]; struct ether_hdr *ether_hdr; struct ether_addr primary_slave_addr; struct ether_addr active_slave_addr; if (num_of_slaves < 1) return num_tx_total; memcpy(slaves, internals->tlb_slaves_order, sizeof(internals->tlb_slaves_order[0]) * num_of_slaves); ether_addr_copy(primary_port->data->mac_addrs, &primary_slave_addr); if (nb_pkts > 3) { for (i = 0; i < 3; i++) rte_prefetch0(rte_pktmbuf_mtod(bufs[i], void*)); } for (i = 0; i < num_of_slaves; i++) { rte_eth_macaddr_get(slaves[i], &active_slave_addr); for (j = num_tx_total; j < nb_pkts; j++) { if (j + 3 < nb_pkts) rte_prefetch0(rte_pktmbuf_mtod(bufs[j+3], void*)); ether_hdr = rte_pktmbuf_mtod(bufs[j], struct ether_hdr *); if (is_same_ether_addr(ðer_hdr->s_addr, &primary_slave_addr)) ether_addr_copy(&active_slave_addr, ðer_hdr->s_addr); #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) mode6_debug("TX IPv4:", ether_hdr, slaves[i], &burstnumberTX); #endif } num_tx_total += rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id, bufs + num_tx_total, nb_pkts - num_tx_total); if (num_tx_total == nb_pkts) break; } return num_tx_total; } void bond_tlb_disable(struct bond_dev_private *internals) { rte_eal_alarm_cancel(bond_ethdev_update_tlb_slave_cb, internals); } void bond_tlb_enable(struct bond_dev_private *internals) { bond_ethdev_update_tlb_slave_cb(internals); } static uint16_t bond_ethdev_tx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue; struct bond_dev_private *internals = bd_tx_q->dev_private; struct ether_hdr *eth_h; uint16_t ether_type, offset; struct client_data *client_info; /* * We create transmit buffers for every slave and one additional to send * through tlb. In worst case every packet will be send on one port. */ struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS + 1][nb_pkts]; uint16_t slave_bufs_pkts[RTE_MAX_ETHPORTS + 1] = { 0 }; /* * We create separate transmit buffers for update packets as they wont be * counted in num_tx_total. */ struct rte_mbuf *update_bufs[RTE_MAX_ETHPORTS][ALB_HASH_TABLE_SIZE]; uint16_t update_bufs_pkts[RTE_MAX_ETHPORTS] = { 0 }; struct rte_mbuf *upd_pkt; size_t pkt_size; uint16_t num_send, num_not_send = 0; uint16_t num_tx_total = 0; uint8_t slave_idx; int i, j; /* Search tx buffer for ARP packets and forward them to alb */ for (i = 0; i < nb_pkts; i++) { eth_h = rte_pktmbuf_mtod(bufs[i], struct ether_hdr *); ether_type = eth_h->ether_type; offset = get_vlan_offset(eth_h, ðer_type); if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) { slave_idx = bond_mode_alb_arp_xmit(eth_h, offset, internals); /* Change src mac in eth header */ rte_eth_macaddr_get(slave_idx, ð_h->s_addr); /* Add packet to slave tx buffer */ slave_bufs[slave_idx][slave_bufs_pkts[slave_idx]] = bufs[i]; slave_bufs_pkts[slave_idx]++; } else { /* If packet is not ARP, send it with TLB policy */ slave_bufs[RTE_MAX_ETHPORTS][slave_bufs_pkts[RTE_MAX_ETHPORTS]] = bufs[i]; slave_bufs_pkts[RTE_MAX_ETHPORTS]++; } } /* Update connected client ARP tables */ if (internals->mode6.ntt) { for (i = 0; i < ALB_HASH_TABLE_SIZE; i++) { client_info = &internals->mode6.client_table[i]; if (client_info->in_use) { /* Allocate new packet to send ARP update on current slave */ upd_pkt = rte_pktmbuf_alloc(internals->mode6.mempool); if (upd_pkt == NULL) { RTE_LOG(ERR, PMD, "Failed to allocate ARP packet from pool\n"); continue; } pkt_size = sizeof(struct ether_hdr) + sizeof(struct arp_hdr) + client_info->vlan_count * sizeof(struct vlan_hdr); upd_pkt->data_len = pkt_size; upd_pkt->pkt_len = pkt_size; slave_idx = bond_mode_alb_arp_upd(client_info, upd_pkt, internals); /* Add packet to update tx buffer */ update_bufs[slave_idx][update_bufs_pkts[slave_idx]] = upd_pkt; update_bufs_pkts[slave_idx]++; } } internals->mode6.ntt = 0; } /* Send ARP packets on proper slaves */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (slave_bufs_pkts[i] > 0) { num_send = rte_eth_tx_burst(i, bd_tx_q->queue_id, slave_bufs[i], slave_bufs_pkts[i]); for (j = 0; j < slave_bufs_pkts[i] - num_send; j++) { bufs[nb_pkts - 1 - num_not_send - j] = slave_bufs[i][nb_pkts - 1 - j]; } num_tx_total += num_send; num_not_send += slave_bufs_pkts[i] - num_send; #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) /* Print TX stats including update packets */ for (j = 0; j < slave_bufs_pkts[i]; j++) { eth_h = rte_pktmbuf_mtod(slave_bufs[i][j], struct ether_hdr *); mode6_debug("TX ARP:", eth_h, i, &burstnumberTX); } #endif } } /* Send update packets on proper slaves */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (update_bufs_pkts[i] > 0) { num_send = rte_eth_tx_burst(i, bd_tx_q->queue_id, update_bufs[i], update_bufs_pkts[i]); for (j = num_send; j < update_bufs_pkts[i]; j++) { rte_pktmbuf_free(update_bufs[i][j]); } #if defined(RTE_LIBRTE_BOND_DEBUG_ALB) || defined(RTE_LIBRTE_BOND_DEBUG_ALB_L1) for (j = 0; j < update_bufs_pkts[i]; j++) { eth_h = rte_pktmbuf_mtod(update_bufs[i][j], struct ether_hdr *); mode6_debug("TX ARPupd:", eth_h, i, &burstnumberTX); } #endif } } /* Send non-ARP packets using tlb policy */ if (slave_bufs_pkts[RTE_MAX_ETHPORTS] > 0) { num_send = bond_ethdev_tx_burst_tlb(queue, slave_bufs[RTE_MAX_ETHPORTS], slave_bufs_pkts[RTE_MAX_ETHPORTS]); for (j = 0; j < slave_bufs_pkts[RTE_MAX_ETHPORTS]; j++) { bufs[nb_pkts - 1 - num_not_send - j] = slave_bufs[RTE_MAX_ETHPORTS][nb_pkts - 1 - j]; } num_tx_total += num_send; num_not_send += slave_bufs_pkts[RTE_MAX_ETHPORTS] - num_send; } return num_tx_total; } static uint16_t bond_ethdev_tx_burst_balance(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; struct bond_tx_queue *bd_tx_q; uint8_t num_of_slaves; uint8_t slaves[RTE_MAX_ETHPORTS]; uint16_t num_tx_total = 0, num_tx_slave = 0, tx_fail_total = 0; int i, op_slave_id; struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts]; uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 }; bd_tx_q = (struct bond_tx_queue *)queue; internals = bd_tx_q->dev_private; /* Copy slave list to protect against slave up/down changes during tx * bursting */ num_of_slaves = internals->active_slave_count; memcpy(slaves, internals->active_slaves, sizeof(internals->active_slaves[0]) * num_of_slaves); if (num_of_slaves < 1) return num_tx_total; /* Populate slaves mbuf with the packets which are to be sent on it */ for (i = 0; i < nb_pkts; i++) { /* Select output slave using hash based on xmit policy */ op_slave_id = internals->xmit_hash(bufs[i], num_of_slaves); /* Populate slave mbuf arrays with mbufs for that slave */ slave_bufs[op_slave_id][slave_nb_pkts[op_slave_id]++] = bufs[i]; } /* Send packet burst on each slave device */ for (i = 0; i < num_of_slaves; i++) { if (slave_nb_pkts[i] > 0) { num_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id, slave_bufs[i], slave_nb_pkts[i]); /* if tx burst fails move packets to end of bufs */ if (unlikely(num_tx_slave < slave_nb_pkts[i])) { int slave_tx_fail_count = slave_nb_pkts[i] - num_tx_slave; tx_fail_total += slave_tx_fail_count; memcpy(&bufs[nb_pkts - tx_fail_total], &slave_bufs[i][num_tx_slave], slave_tx_fail_count * sizeof(bufs[0])); } num_tx_total += num_tx_slave; } } return num_tx_total; } static uint16_t bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; struct bond_tx_queue *bd_tx_q; uint8_t num_of_slaves; uint8_t slaves[RTE_MAX_ETHPORTS]; /* positions in slaves, not ID */ uint8_t distributing_offsets[RTE_MAX_ETHPORTS]; uint8_t distributing_count; uint16_t num_tx_slave, num_tx_total = 0, num_tx_fail_total = 0; uint16_t i, j, op_slave_idx; const uint16_t buffs_size = nb_pkts + BOND_MODE_8023AX_SLAVE_TX_PKTS + 1; /* Allocate additional packets in case 8023AD mode. */ struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][buffs_size]; void *slow_pkts[BOND_MODE_8023AX_SLAVE_TX_PKTS] = { NULL }; /* Total amount of packets in slave_bufs */ uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] = { 0 }; /* Slow packets placed in each slave */ uint8_t slave_slow_nb_pkts[RTE_MAX_ETHPORTS] = { 0 }; bd_tx_q = (struct bond_tx_queue *)queue; internals = bd_tx_q->dev_private; /* Copy slave list to protect against slave up/down changes during tx * bursting */ num_of_slaves = internals->active_slave_count; if (num_of_slaves < 1) return num_tx_total; memcpy(slaves, internals->active_slaves, sizeof(slaves[0]) * num_of_slaves); distributing_count = 0; for (i = 0; i < num_of_slaves; i++) { struct port *port = &mode_8023ad_ports[slaves[i]]; slave_slow_nb_pkts[i] = rte_ring_dequeue_burst(port->tx_ring, slow_pkts, BOND_MODE_8023AX_SLAVE_TX_PKTS); slave_nb_pkts[i] = slave_slow_nb_pkts[i]; for (j = 0; j < slave_slow_nb_pkts[i]; j++) slave_bufs[i][j] = slow_pkts[j]; if (ACTOR_STATE(port, DISTRIBUTING)) distributing_offsets[distributing_count++] = i; } if (likely(distributing_count > 0)) { /* Populate slaves mbuf with the packets which are to be sent on it */ for (i = 0; i < nb_pkts; i++) { /* Select output slave using hash based on xmit policy */ op_slave_idx = internals->xmit_hash(bufs[i], distributing_count); /* Populate slave mbuf arrays with mbufs for that slave. Use only * slaves that are currently distributing. */ uint8_t slave_offset = distributing_offsets[op_slave_idx]; slave_bufs[slave_offset][slave_nb_pkts[slave_offset]] = bufs[i]; slave_nb_pkts[slave_offset]++; } } /* Send packet burst on each slave device */ for (i = 0; i < num_of_slaves; i++) { if (slave_nb_pkts[i] == 0) continue; num_tx_slave = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id, slave_bufs[i], slave_nb_pkts[i]); /* If tx burst fails drop slow packets */ for ( ; num_tx_slave < slave_slow_nb_pkts[i]; num_tx_slave++) rte_pktmbuf_free(slave_bufs[i][num_tx_slave]); num_tx_total += num_tx_slave - slave_slow_nb_pkts[i]; num_tx_fail_total += slave_nb_pkts[i] - num_tx_slave; /* If tx burst fails move packets to end of bufs */ if (unlikely(num_tx_slave < slave_nb_pkts[i])) { uint16_t j = nb_pkts - num_tx_fail_total; for ( ; num_tx_slave < slave_nb_pkts[i]; j++, num_tx_slave++) bufs[j] = slave_bufs[i][num_tx_slave]; } } return num_tx_total; } static uint16_t bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { struct bond_dev_private *internals; struct bond_tx_queue *bd_tx_q; uint8_t tx_failed_flag = 0, num_of_slaves; uint8_t slaves[RTE_MAX_ETHPORTS]; uint16_t max_nb_of_tx_pkts = 0; int slave_tx_total[RTE_MAX_ETHPORTS]; int i, most_successful_tx_slave = -1; bd_tx_q = (struct bond_tx_queue *)queue; internals = bd_tx_q->dev_private; /* Copy slave list to protect against slave up/down changes during tx * bursting */ num_of_slaves = internals->active_slave_count; memcpy(slaves, internals->active_slaves, sizeof(internals->active_slaves[0]) * num_of_slaves); if (num_of_slaves < 1) return 0; /* Increment reference count on mbufs */ for (i = 0; i < nb_pkts; i++) rte_mbuf_refcnt_update(bufs[i], num_of_slaves - 1); /* Transmit burst on each active slave */ for (i = 0; i < num_of_slaves; i++) { slave_tx_total[i] = rte_eth_tx_burst(slaves[i], bd_tx_q->queue_id, bufs, nb_pkts); if (unlikely(slave_tx_total[i] < nb_pkts)) tx_failed_flag = 1; /* record the value and slave index for the slave which transmits the * maximum number of packets */ if (slave_tx_total[i] > max_nb_of_tx_pkts) { max_nb_of_tx_pkts = slave_tx_total[i]; most_successful_tx_slave = i; } } /* if slaves fail to transmit packets from burst, the calling application * is not expected to know about multiple references to packets so we must * handle failures of all packets except those of the most successful slave */ if (unlikely(tx_failed_flag)) for (i = 0; i < num_of_slaves; i++) if (i != most_successful_tx_slave) while (slave_tx_total[i] < nb_pkts) rte_pktmbuf_free(bufs[slave_tx_total[i]++]); return max_nb_of_tx_pkts; } void link_properties_set(struct rte_eth_dev *bonded_eth_dev, struct rte_eth_link *slave_dev_link) { struct rte_eth_link *bonded_dev_link = &bonded_eth_dev->data->dev_link; struct bond_dev_private *internals = bonded_eth_dev->data->dev_private; if (slave_dev_link->link_status && bonded_eth_dev->data->dev_started) { bonded_dev_link->link_duplex = slave_dev_link->link_duplex; bonded_dev_link->link_speed = slave_dev_link->link_speed; internals->link_props_set = 1; } } void link_properties_reset(struct rte_eth_dev *bonded_eth_dev) { struct bond_dev_private *internals = bonded_eth_dev->data->dev_private; memset(&(bonded_eth_dev->data->dev_link), 0, sizeof(bonded_eth_dev->data->dev_link)); internals->link_props_set = 0; } int link_properties_valid(struct rte_eth_link *bonded_dev_link, struct rte_eth_link *slave_dev_link) { if (bonded_dev_link->link_duplex != slave_dev_link->link_duplex || bonded_dev_link->link_speed != slave_dev_link->link_speed) return -1; return 0; } int mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr *dst_mac_addr) { struct ether_addr *mac_addr; if (eth_dev == NULL) { RTE_LOG(ERR, PMD, "%s: NULL pointer eth_dev specified\n", __func__); return -1; } if (dst_mac_addr == NULL) { RTE_LOG(ERR, PMD, "%s: NULL pointer MAC specified\n", __func__); return -1; } mac_addr = eth_dev->data->mac_addrs; ether_addr_copy(mac_addr, dst_mac_addr); return 0; } int mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr) { struct ether_addr *mac_addr; if (eth_dev == NULL) { RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified"); return -1; } if (new_mac_addr == NULL) { RTE_BOND_LOG(ERR, "NULL pointer MAC specified"); return -1; } mac_addr = eth_dev->data->mac_addrs; /* If new MAC is different to current MAC then update */ if (memcmp(mac_addr, new_mac_addr, sizeof(*mac_addr)) != 0) memcpy(mac_addr, new_mac_addr, sizeof(*mac_addr)); return 0; } int mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev) { struct bond_dev_private *internals = bonded_eth_dev->data->dev_private; int i; /* Update slave devices MAC addresses */ if (internals->slave_count < 1) return -1; switch (internals->mode) { case BONDING_MODE_ROUND_ROBIN: case BONDING_MODE_BALANCE: case BONDING_MODE_BROADCAST: for (i = 0; i < internals->slave_count; i++) { if (mac_address_set(&rte_eth_devices[internals->slaves[i].port_id], bonded_eth_dev->data->mac_addrs)) { RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address", internals->slaves[i].port_id); return -1; } } break; case BONDING_MODE_8023AD: bond_mode_8023ad_mac_address_update(bonded_eth_dev); break; case BONDING_MODE_ACTIVE_BACKUP: case BONDING_MODE_TLB: case BONDING_MODE_ALB: default: for (i = 0; i < internals->slave_count; i++) { if (internals->slaves[i].port_id == internals->current_primary_port) { if (mac_address_set(&rte_eth_devices[internals->primary_port], bonded_eth_dev->data->mac_addrs)) { RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address", internals->current_primary_port); return -1; } } else { if (mac_address_set( &rte_eth_devices[internals->slaves[i].port_id], &internals->slaves[i].persisted_mac_addr)) { RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address", internals->slaves[i].port_id); return -1; } } } } return 0; } int bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode) { struct bond_dev_private *internals; internals = eth_dev->data->dev_private; switch (mode) { case BONDING_MODE_ROUND_ROBIN: eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_round_robin; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst; break; case BONDING_MODE_ACTIVE_BACKUP: eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_active_backup; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup; break; case BONDING_MODE_BALANCE: eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_balance; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst; break; case BONDING_MODE_BROADCAST: eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_broadcast; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst; break; case BONDING_MODE_8023AD: if (bond_mode_8023ad_enable(eth_dev) != 0) return -1; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_8023ad; eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_8023ad; RTE_LOG(WARNING, PMD, "Using mode 4, it is necessary to do TX burst and RX burst " "at least every 100ms.\n"); break; case BONDING_MODE_TLB: eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_tlb; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_active_backup; break; case BONDING_MODE_ALB: if (bond_mode_alb_enable(eth_dev) != 0) return -1; eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb; eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb; break; default: return -1; } internals->mode = mode; return 0; } int slave_configure(struct rte_eth_dev *bonded_eth_dev, struct rte_eth_dev *slave_eth_dev) { struct bond_rx_queue *bd_rx_q; struct bond_tx_queue *bd_tx_q; int errval; uint16_t q_id; /* Stop slave */ rte_eth_dev_stop(slave_eth_dev->data->port_id); /* Enable interrupts on slave device if supported */ if (slave_eth_dev->driver->pci_drv.drv_flags & RTE_PCI_DRV_INTR_LSC) slave_eth_dev->data->dev_conf.intr_conf.lsc = 1; /* Configure device */ errval = rte_eth_dev_configure(slave_eth_dev->data->port_id, bonded_eth_dev->data->nb_rx_queues, bonded_eth_dev->data->nb_tx_queues, &(slave_eth_dev->data->dev_conf)); if (errval != 0) { RTE_BOND_LOG(ERR, "Cannot configure slave device: port %u , err (%d)", slave_eth_dev->data->port_id, errval); return errval; } /* Setup Rx Queues */ for (q_id = 0; q_id < bonded_eth_dev->data->nb_rx_queues; q_id++) { bd_rx_q = (struct bond_rx_queue *)bonded_eth_dev->data->rx_queues[q_id]; errval = rte_eth_rx_queue_setup(slave_eth_dev->data->port_id, q_id, bd_rx_q->nb_rx_desc, rte_eth_dev_socket_id(slave_eth_dev->data->port_id), &(bd_rx_q->rx_conf), bd_rx_q->mb_pool); if (errval != 0) { RTE_BOND_LOG(ERR, "rte_eth_rx_queue_setup: port=%d queue_id %d, err (%d)", slave_eth_dev->data->port_id, q_id, errval); return errval; } } /* Setup Tx Queues */ for (q_id = 0; q_id < bonded_eth_dev->data->nb_tx_queues; q_id++) { bd_tx_q = (struct bond_tx_queue *)bonded_eth_dev->data->tx_queues[q_id]; errval = rte_eth_tx_queue_setup(slave_eth_dev->data->port_id, q_id, bd_tx_q->nb_tx_desc, rte_eth_dev_socket_id(slave_eth_dev->data->port_id), &bd_tx_q->tx_conf); if (errval != 0) { RTE_BOND_LOG(ERR, "rte_eth_tx_queue_setup: port=%d queue_id %d, err (%d)", slave_eth_dev->data->port_id, q_id, errval); return errval; } } /* Start device */ errval = rte_eth_dev_start(slave_eth_dev->data->port_id); if (errval != 0) { RTE_BOND_LOG(ERR, "rte_eth_dev_start: port=%u, err (%d)", slave_eth_dev->data->port_id, errval); return -1; } /* If lsc interrupt is set, check initial slave's link status */ if (slave_eth_dev->driver->pci_drv.drv_flags & RTE_PCI_DRV_INTR_LSC) bond_ethdev_lsc_event_callback(slave_eth_dev->data->port_id, RTE_ETH_EVENT_INTR_LSC, &bonded_eth_dev->data->port_id); return 0; } void slave_remove(struct bond_dev_private *internals, struct rte_eth_dev *slave_eth_dev) { uint8_t i; for (i = 0; i < internals->slave_count; i++) if (internals->slaves[i].port_id == slave_eth_dev->data->port_id) break; if (i < (internals->slave_count - 1)) memmove(&internals->slaves[i], &internals->slaves[i + 1], sizeof(internals->slaves[0]) * (internals->slave_count - i - 1)); internals->slave_count--; } static void bond_ethdev_slave_link_status_change_monitor(void *cb_arg); void slave_add(struct bond_dev_private *internals, struct rte_eth_dev *slave_eth_dev) { struct bond_slave_details *slave_details = &internals->slaves[internals->slave_count]; slave_details->port_id = slave_eth_dev->data->port_id; slave_details->last_link_status = 0; /* If slave device doesn't support interrupts then we need to enabled * polling to monitor link status */ if (!(slave_eth_dev->pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { slave_details->link_status_poll_enabled = 1; if (!internals->link_status_polling_enabled) { internals->link_status_polling_enabled = 1; rte_eal_alarm_set(internals->link_status_polling_interval_ms * 1000, bond_ethdev_slave_link_status_change_monitor, (void *)&rte_eth_devices[internals->port_id]); } } slave_details->link_status_wait_to_complete = 0; /* clean tlb_last_obytes when adding port for bonding device */ memcpy(&(slave_details->persisted_mac_addr), slave_eth_dev->data->mac_addrs, sizeof(struct ether_addr)); } void bond_ethdev_primary_set(struct bond_dev_private *internals, uint8_t slave_port_id) { int i; if (internals->active_slave_count < 1) internals->current_primary_port = slave_port_id; else /* Search bonded device slave ports for new proposed primary port */ for (i = 0; i < internals->active_slave_count; i++) { if (internals->active_slaves[i] == slave_port_id) internals->current_primary_port = slave_port_id; } } static void bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev); static int bond_ethdev_start(struct rte_eth_dev *eth_dev) { struct bond_dev_private *internals; int i; /* slave eth dev will be started by bonded device */ if (valid_bonded_ethdev(eth_dev)) { RTE_BOND_LOG(ERR, "User tried to explicitly start a slave eth_dev (%d)", eth_dev->data->port_id); return -1; } eth_dev->data->dev_link.link_status = 0; eth_dev->data->dev_started = 1; internals = eth_dev->data->dev_private; if (internals->slave_count == 0) { RTE_BOND_LOG(ERR, "Cannot start port since there are no slave devices"); return -1; } if (internals->user_defined_mac == 0) { struct ether_addr *new_mac_addr = NULL; for (i = 0; i < internals->slave_count; i++) if (internals->slaves[i].port_id == internals->primary_port) new_mac_addr = &internals->slaves[i].persisted_mac_addr; if (new_mac_addr == NULL) return -1; if (mac_address_set(eth_dev, new_mac_addr) != 0) { RTE_BOND_LOG(ERR, "bonded port (%d) failed to update MAC address", eth_dev->data->port_id); return -1; } } /* Update all slave devices MACs*/ if (mac_address_slaves_update(eth_dev) != 0) return -1; /* If bonded device is configure in promiscuous mode then re-apply config */ if (internals->promiscuous_en) bond_ethdev_promiscuous_enable(eth_dev); /* Reconfigure each slave device if starting bonded device */ for (i = 0; i < internals->slave_count; i++) { if (slave_configure(eth_dev, &(rte_eth_devices[internals->slaves[i].port_id])) != 0) { RTE_BOND_LOG(ERR, "bonded port (%d) failed to reconfigure slave device (%d)", eth_dev->data->port_id, internals->slaves[i].port_id); return -1; } } if (internals->user_defined_primary_port) bond_ethdev_primary_set(internals, internals->primary_port); if (internals->mode == BONDING_MODE_8023AD) bond_mode_8023ad_start(eth_dev); if (internals->mode == BONDING_MODE_TLB || internals->mode == BONDING_MODE_ALB) bond_tlb_enable(internals); return 0; } static void bond_ethdev_free_queues(struct rte_eth_dev *dev) { uint8_t i; for (i = 0; i < dev->data->nb_rx_queues; i++) { rte_free(dev->data->rx_queues[i]); dev->data->rx_queues[i] = NULL; } dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) { rte_free(dev->data->tx_queues[i]); dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; } void bond_ethdev_stop(struct rte_eth_dev *eth_dev) { struct bond_dev_private *internals = eth_dev->data->dev_private; uint8_t i; if (internals->mode == BONDING_MODE_8023AD) { struct port *port; void *pkt = NULL; bond_mode_8023ad_stop(eth_dev); /* Discard all messages to/from mode 4 state machines */ for (i = 0; i < internals->active_slave_count; i++) { port = &mode_8023ad_ports[internals->active_slaves[i]]; RTE_VERIFY(port->rx_ring != NULL); while (rte_ring_dequeue(port->rx_ring, &pkt) != -ENOENT) rte_pktmbuf_free(pkt); RTE_VERIFY(port->tx_ring != NULL); while (rte_ring_dequeue(port->tx_ring, &pkt) != -ENOENT) rte_pktmbuf_free(pkt); } } if (internals->mode == BONDING_MODE_TLB || internals->mode == BONDING_MODE_ALB) { bond_tlb_disable(internals); for (i = 0; i < internals->active_slave_count; i++) tlb_last_obytets[internals->active_slaves[i]] = 0; } internals->active_slave_count = 0; internals->link_status_polling_enabled = 0; eth_dev->data->dev_link.link_status = 0; eth_dev->data->dev_started = 0; } void bond_ethdev_close(struct rte_eth_dev *dev) { bond_ethdev_free_queues(dev); } /* forward declaration */ static int bond_ethdev_configure(struct rte_eth_dev *dev); static void bond_ethdev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct bond_dev_private *internals = dev->data->dev_private; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)2048; dev_info->max_rx_queues = (uint16_t)128; dev_info->max_tx_queues = (uint16_t)512; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = dev->pci_dev; dev_info->rx_offload_capa = internals->rx_offload_capa; dev_info->tx_offload_capa = internals->tx_offload_capa; } static int bond_ethdev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool) { struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *) rte_zmalloc_socket(NULL, sizeof(struct bond_rx_queue), 0, dev->pci_dev->numa_node); if (bd_rx_q == NULL) return -1; bd_rx_q->queue_id = rx_queue_id; bd_rx_q->dev_private = dev->data->dev_private; bd_rx_q->nb_rx_desc = nb_rx_desc; memcpy(&(bd_rx_q->rx_conf), rx_conf, sizeof(struct rte_eth_rxconf)); bd_rx_q->mb_pool = mb_pool; dev->data->rx_queues[rx_queue_id] = bd_rx_q; return 0; } static int bond_ethdev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf) { struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *) rte_zmalloc_socket(NULL, sizeof(struct bond_tx_queue), 0, dev->pci_dev->numa_node); if (bd_tx_q == NULL) return -1; bd_tx_q->queue_id = tx_queue_id; bd_tx_q->dev_private = dev->data->dev_private; bd_tx_q->nb_tx_desc = nb_tx_desc; memcpy(&(bd_tx_q->tx_conf), tx_conf, sizeof(bd_tx_q->tx_conf)); dev->data->tx_queues[tx_queue_id] = bd_tx_q; return 0; } static void bond_ethdev_rx_queue_release(void *queue) { if (queue == NULL) return; rte_free(queue); } static void bond_ethdev_tx_queue_release(void *queue) { if (queue == NULL) return; rte_free(queue); } static void bond_ethdev_slave_link_status_change_monitor(void *cb_arg) { struct rte_eth_dev *bonded_ethdev, *slave_ethdev; struct bond_dev_private *internals; /* Default value for polling slave found is true as we don't want to * disable the polling thread if we cannot get the lock */ int i, polling_slave_found = 1; if (cb_arg == NULL) return; bonded_ethdev = (struct rte_eth_dev *)cb_arg; internals = (struct bond_dev_private *)bonded_ethdev->data->dev_private; if (!bonded_ethdev->data->dev_started || !internals->link_status_polling_enabled) return; /* If device is currently being configured then don't check slaves link * status, wait until next period */ if (rte_spinlock_trylock(&internals->lock)) { if (internals->slave_count > 0) polling_slave_found = 0; for (i = 0; i < internals->slave_count; i++) { if (!internals->slaves[i].link_status_poll_enabled) continue; slave_ethdev = &rte_eth_devices[internals->slaves[i].port_id]; polling_slave_found = 1; /* Update slave link status */ (*slave_ethdev->dev_ops->link_update)(slave_ethdev, internals->slaves[i].link_status_wait_to_complete); /* if link status has changed since last checked then call lsc * event callback */ if (slave_ethdev->data->dev_link.link_status != internals->slaves[i].last_link_status) { internals->slaves[i].last_link_status = slave_ethdev->data->dev_link.link_status; bond_ethdev_lsc_event_callback(internals->slaves[i].port_id, RTE_ETH_EVENT_INTR_LSC, &bonded_ethdev->data->port_id); } } rte_spinlock_unlock(&internals->lock); } if (polling_slave_found) /* Set alarm to continue monitoring link status of slave ethdev's */ rte_eal_alarm_set(internals->link_status_polling_interval_ms * 1000, bond_ethdev_slave_link_status_change_monitor, cb_arg); } static int bond_ethdev_link_update(struct rte_eth_dev *bonded_eth_dev, int wait_to_complete) { struct bond_dev_private *internals = bonded_eth_dev->data->dev_private; if (!bonded_eth_dev->data->dev_started || internals->active_slave_count == 0) { bonded_eth_dev->data->dev_link.link_status = 0; return 0; } else { struct rte_eth_dev *slave_eth_dev; int i, link_up = 0; for (i = 0; i < internals->active_slave_count; i++) { slave_eth_dev = &rte_eth_devices[internals->active_slaves[i]]; (*slave_eth_dev->dev_ops->link_update)(slave_eth_dev, wait_to_complete); if (slave_eth_dev->data->dev_link.link_status == 1) { link_up = 1; break; } } bonded_eth_dev->data->dev_link.link_status = link_up; } return 0; } static void bond_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct bond_dev_private *internals = dev->data->dev_private; struct rte_eth_stats slave_stats; int i; for (i = 0; i < internals->slave_count; i++) { rte_eth_stats_get(internals->slaves[i].port_id, &slave_stats); stats->ipackets += slave_stats.ipackets; stats->opackets += slave_stats.opackets; stats->ibytes += slave_stats.ibytes; stats->obytes += slave_stats.obytes; stats->ierrors += slave_stats.ierrors; stats->oerrors += slave_stats.oerrors; stats->imcasts += slave_stats.imcasts; stats->rx_nombuf += slave_stats.rx_nombuf; stats->fdirmatch += slave_stats.fdirmatch; stats->fdirmiss += slave_stats.fdirmiss; stats->tx_pause_xon += slave_stats.tx_pause_xon; stats->rx_pause_xon += slave_stats.rx_pause_xon; stats->tx_pause_xoff += slave_stats.tx_pause_xoff; stats->rx_pause_xoff += slave_stats.rx_pause_xoff; } } static void bond_ethdev_stats_reset(struct rte_eth_dev *dev) { struct bond_dev_private *internals = dev->data->dev_private; int i; for (i = 0; i < internals->slave_count; i++) rte_eth_stats_reset(internals->slaves[i].port_id); } static void bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev) { struct bond_dev_private *internals = eth_dev->data->dev_private; int i; internals->promiscuous_en = 1; switch (internals->mode) { /* Promiscuous mode is propagated to all slaves */ case BONDING_MODE_ROUND_ROBIN: case BONDING_MODE_BALANCE: case BONDING_MODE_BROADCAST: for (i = 0; i < internals->slave_count; i++) rte_eth_promiscuous_enable(internals->slaves[i].port_id); break; /* In mode4 promiscus mode is managed when slave is added/removed */ case BONDING_MODE_8023AD: break; /* Promiscuous mode is propagated only to primary slave */ case BONDING_MODE_ACTIVE_BACKUP: case BONDING_MODE_TLB: case BONDING_MODE_ALB: default: rte_eth_promiscuous_enable(internals->current_primary_port); } } static void bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev) { struct bond_dev_private *internals = dev->data->dev_private; int i; internals->promiscuous_en = 0; switch (internals->mode) { /* Promiscuous mode is propagated to all slaves */ case BONDING_MODE_ROUND_ROBIN: case BONDING_MODE_BALANCE: case BONDING_MODE_BROADCAST: for (i = 0; i < internals->slave_count; i++) rte_eth_promiscuous_disable(internals->slaves[i].port_id); break; /* In mode4 promiscus mode is set managed when slave is added/removed */ case BONDING_MODE_8023AD: break; /* Promiscuous mode is propagated only to primary slave */ case BONDING_MODE_ACTIVE_BACKUP: case BONDING_MODE_TLB: case BONDING_MODE_ALB: default: rte_eth_promiscuous_disable(internals->current_primary_port); } } static void bond_ethdev_delayed_lsc_propagation(void *arg) { if (arg == NULL) return; _rte_eth_dev_callback_process((struct rte_eth_dev *)arg, RTE_ETH_EVENT_INTR_LSC); } void bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param) { struct rte_eth_dev *bonded_eth_dev, *slave_eth_dev; struct bond_dev_private *internals; struct rte_eth_link link; int i, valid_slave = 0; uint8_t active_pos; uint8_t lsc_flag = 0; if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL) return; bonded_eth_dev = &rte_eth_devices[*(uint8_t *)param]; slave_eth_dev = &rte_eth_devices[port_id]; if (valid_bonded_ethdev(bonded_eth_dev)) return; internals = bonded_eth_dev->data->dev_private; /* If the device isn't started don't handle interrupts */ if (!bonded_eth_dev->data->dev_started) return; /* verify that port_id is a valid slave of bonded port */ for (i = 0; i < internals->slave_count; i++) { if (internals->slaves[i].port_id == port_id) { valid_slave = 1; break; } } if (!valid_slave) return; /* Search for port in active port list */ active_pos = find_slave_by_id(internals->active_slaves, internals->active_slave_count, port_id); rte_eth_link_get_nowait(port_id, &link); if (link.link_status) { if (active_pos < internals->active_slave_count) return; /* if no active slave ports then set this port to be primary port */ if (internals->active_slave_count < 1) { /* If first active slave, then change link status */ bonded_eth_dev->data->dev_link.link_status = 1; internals->current_primary_port = port_id; lsc_flag = 1; mac_address_slaves_update(bonded_eth_dev); /* Inherit eth dev link properties from first active slave */ link_properties_set(bonded_eth_dev, &(slave_eth_dev->data->dev_link)); } activate_slave(bonded_eth_dev, port_id); /* If user has defined the primary port then default to using it */ if (internals->user_defined_primary_port && internals->primary_port == port_id) bond_ethdev_primary_set(internals, port_id); } else { if (active_pos == internals->active_slave_count) return; /* Remove from active slave list */ deactivate_slave(bonded_eth_dev, port_id); /* No active slaves, change link status to down and reset other * link properties */ if (internals->active_slave_count < 1) { lsc_flag = 1; bonded_eth_dev->data->dev_link.link_status = 0; link_properties_reset(bonded_eth_dev); } /* Update primary id, take first active slave from list or if none * available set to -1 */ if (port_id == internals->current_primary_port) { if (internals->active_slave_count > 0) bond_ethdev_primary_set(internals, internals->active_slaves[0]); else internals->current_primary_port = internals->primary_port; } } if (lsc_flag) { /* Cancel any possible outstanding interrupts if delays are enabled */ if (internals->link_up_delay_ms > 0 || internals->link_down_delay_ms > 0) rte_eal_alarm_cancel(bond_ethdev_delayed_lsc_propagation, bonded_eth_dev); if (bonded_eth_dev->data->dev_link.link_status) { if (internals->link_up_delay_ms > 0) rte_eal_alarm_set(internals->link_up_delay_ms * 1000, bond_ethdev_delayed_lsc_propagation, (void *)bonded_eth_dev); else _rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC); } else { if (internals->link_down_delay_ms > 0) rte_eal_alarm_set(internals->link_down_delay_ms * 1000, bond_ethdev_delayed_lsc_propagation, (void *)bonded_eth_dev); else _rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC); } } } struct eth_dev_ops default_dev_ops = { .dev_start = bond_ethdev_start, .dev_stop = bond_ethdev_stop, .dev_close = bond_ethdev_close, .dev_configure = bond_ethdev_configure, .dev_infos_get = bond_ethdev_info, .rx_queue_setup = bond_ethdev_rx_queue_setup, .tx_queue_setup = bond_ethdev_tx_queue_setup, .rx_queue_release = bond_ethdev_rx_queue_release, .tx_queue_release = bond_ethdev_tx_queue_release, .link_update = bond_ethdev_link_update, .stats_get = bond_ethdev_stats_get, .stats_reset = bond_ethdev_stats_reset, .promiscuous_enable = bond_ethdev_promiscuous_enable, .promiscuous_disable = bond_ethdev_promiscuous_disable }; static int bond_init(const char *name, const char *params) { struct bond_dev_private *internals; struct rte_kvargs *kvlist; uint8_t bonding_mode, socket_id; int arg_count, port_id; RTE_LOG(INFO, EAL, "Initializing pmd_bond for %s\n", name); kvlist = rte_kvargs_parse(params, pmd_bond_init_valid_arguments); if (kvlist == NULL) return -1; /* Parse link bonding mode */ if (rte_kvargs_count(kvlist, PMD_BOND_MODE_KVARG) == 1) { if (rte_kvargs_process(kvlist, PMD_BOND_MODE_KVARG, &bond_ethdev_parse_slave_mode_kvarg, &bonding_mode) != 0) { RTE_LOG(ERR, EAL, "Invalid mode for bonded device %s\n", name); goto parse_error; } } else { RTE_LOG(ERR, EAL, "Mode must be specified only once for bonded " "device %s\n", name); goto parse_error; } /* Parse socket id to create bonding device on */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_SOCKET_ID_KVARG); if (arg_count == 1) { if (rte_kvargs_process(kvlist, PMD_BOND_SOCKET_ID_KVARG, &bond_ethdev_parse_socket_id_kvarg, &socket_id) != 0) { RTE_LOG(ERR, EAL, "Invalid socket Id specified for " "bonded device %s\n", name); goto parse_error; } } else if (arg_count > 1) { RTE_LOG(ERR, EAL, "Socket Id can be specified only once for " "bonded device %s\n", name); goto parse_error; } else { socket_id = rte_socket_id(); } /* Create link bonding eth device */ port_id = rte_eth_bond_create(name, bonding_mode, socket_id); if (port_id < 0) { RTE_LOG(ERR, EAL, "Failed to create socket %s in mode %u on " "socket %u.\n", name, bonding_mode, socket_id); goto parse_error; } internals = rte_eth_devices[port_id].data->dev_private; internals->kvlist = kvlist; RTE_LOG(INFO, EAL, "Create bonded device %s on port %d in mode %u on " "socket %u.\n", name, port_id, bonding_mode, socket_id); return 0; parse_error: rte_kvargs_free(kvlist); return -1; } static int bond_uninit(const char *name) { int ret; if (name == NULL) return -EINVAL; RTE_LOG(INFO, EAL, "Uninitializing pmd_bond for %s\n", name); /* free link bonding eth device */ ret = rte_eth_bond_free(name); if (ret < 0) RTE_LOG(ERR, EAL, "Failed to free %s\n", name); return ret; } /* this part will resolve the slave portids after all the other pdev and vdev * have been allocated */ static int bond_ethdev_configure(struct rte_eth_dev *dev) { char *name = dev->data->name; struct bond_dev_private *internals = dev->data->dev_private; struct rte_kvargs *kvlist = internals->kvlist; int arg_count; uint8_t port_id = dev - rte_eth_devices; /* * if no kvlist, it means that this bonded device has been created * through the bonding api. */ if (!kvlist) return 0; /* Parse MAC address for bonded device */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_MAC_ADDR_KVARG); if (arg_count == 1) { struct ether_addr bond_mac; if (rte_kvargs_process(kvlist, PMD_BOND_MAC_ADDR_KVARG, &bond_ethdev_parse_bond_mac_addr_kvarg, &bond_mac) < 0) { RTE_LOG(INFO, EAL, "Invalid mac address for bonded device %s\n", name); return -1; } /* Set MAC address */ if (rte_eth_bond_mac_address_set(port_id, &bond_mac) != 0) { RTE_LOG(ERR, EAL, "Failed to set mac address on bonded device %s\n", name); return -1; } } else if (arg_count > 1) { RTE_LOG(ERR, EAL, "MAC address can be specified only once for bonded device %s\n", name); return -1; } /* Parse/set balance mode transmit policy */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_XMIT_POLICY_KVARG); if (arg_count == 1) { uint8_t xmit_policy; if (rte_kvargs_process(kvlist, PMD_BOND_XMIT_POLICY_KVARG, &bond_ethdev_parse_balance_xmit_policy_kvarg, &xmit_policy) != 0) { RTE_LOG(INFO, EAL, "Invalid xmit policy specified for bonded device %s\n", name); return -1; } /* Set balance mode transmit policy*/ if (rte_eth_bond_xmit_policy_set(port_id, xmit_policy) != 0) { RTE_LOG(ERR, EAL, "Failed to set balance xmit policy on bonded device %s\n", name); return -1; } } else if (arg_count > 1) { RTE_LOG(ERR, EAL, "Transmit policy can be specified only once for bonded device" " %s\n", name); return -1; } /* Parse/add slave ports to bonded device */ if (rte_kvargs_count(kvlist, PMD_BOND_SLAVE_PORT_KVARG) > 0) { struct bond_ethdev_slave_ports slave_ports; unsigned i; memset(&slave_ports, 0, sizeof(slave_ports)); if (rte_kvargs_process(kvlist, PMD_BOND_SLAVE_PORT_KVARG, &bond_ethdev_parse_slave_port_kvarg, &slave_ports) != 0) { RTE_LOG(ERR, EAL, "Failed to parse slave ports for bonded device %s\n", name); return -1; } for (i = 0; i < slave_ports.slave_count; i++) { if (rte_eth_bond_slave_add(port_id, slave_ports.slaves[i]) != 0) { RTE_LOG(ERR, EAL, "Failed to add port %d as slave to bonded device %s\n", slave_ports.slaves[i], name); } } } else { RTE_LOG(INFO, EAL, "No slaves specified for bonded device %s\n", name); return -1; } /* Parse/set primary slave port id*/ arg_count = rte_kvargs_count(kvlist, PMD_BOND_PRIMARY_SLAVE_KVARG); if (arg_count == 1) { uint8_t primary_slave_port_id; if (rte_kvargs_process(kvlist, PMD_BOND_PRIMARY_SLAVE_KVARG, &bond_ethdev_parse_primary_slave_port_id_kvarg, &primary_slave_port_id) < 0) { RTE_LOG(INFO, EAL, "Invalid primary slave port id specified for bonded device" " %s\n", name); return -1; } /* Set balance mode transmit policy*/ if (rte_eth_bond_primary_set(port_id, (uint8_t)primary_slave_port_id) != 0) { RTE_LOG(ERR, EAL, "Failed to set primary slave port %d on bonded device %s\n", primary_slave_port_id, name); return -1; } } else if (arg_count > 1) { RTE_LOG(INFO, EAL, "Primary slave can be specified only once for bonded device" " %s\n", name); return -1; } /* Parse link status monitor polling interval */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LSC_POLL_PERIOD_KVARG); if (arg_count == 1) { uint32_t lsc_poll_interval_ms; if (rte_kvargs_process(kvlist, PMD_BOND_LSC_POLL_PERIOD_KVARG, &bond_ethdev_parse_time_ms_kvarg, &lsc_poll_interval_ms) < 0) { RTE_LOG(INFO, EAL, "Invalid lsc polling interval value specified for bonded" " device %s\n", name); return -1; } if (rte_eth_bond_link_monitoring_set(port_id, lsc_poll_interval_ms) != 0) { RTE_LOG(ERR, EAL, "Failed to set lsc monitor polling interval (%u ms) on" " bonded device %s\n", lsc_poll_interval_ms, name); return -1; } } else if (arg_count > 1) { RTE_LOG(INFO, EAL, "LSC polling interval can be specified only once for bonded" " device %s\n", name); return -1; } /* Parse link up interrupt propagation delay */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_UP_PROP_DELAY_KVARG); if (arg_count == 1) { uint32_t link_up_delay_ms; if (rte_kvargs_process(kvlist, PMD_BOND_LINK_UP_PROP_DELAY_KVARG, &bond_ethdev_parse_time_ms_kvarg, &link_up_delay_ms) < 0) { RTE_LOG(INFO, EAL, "Invalid link up propagation delay value specified for" " bonded device %s\n", name); return -1; } /* Set balance mode transmit policy*/ if (rte_eth_bond_link_up_prop_delay_set(port_id, link_up_delay_ms) != 0) { RTE_LOG(ERR, EAL, "Failed to set link up propagation delay (%u ms) on bonded" " device %s\n", link_up_delay_ms, name); return -1; } } else if (arg_count > 1) { RTE_LOG(INFO, EAL, "Link up propagation delay can be specified only once for" " bonded device %s\n", name); return -1; } /* Parse link down interrupt propagation delay */ arg_count = rte_kvargs_count(kvlist, PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG); if (arg_count == 1) { uint32_t link_down_delay_ms; if (rte_kvargs_process(kvlist, PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG, &bond_ethdev_parse_time_ms_kvarg, &link_down_delay_ms) < 0) { RTE_LOG(INFO, EAL, "Invalid link down propagation delay value specified for" " bonded device %s\n", name); return -1; } /* Set balance mode transmit policy*/ if (rte_eth_bond_link_down_prop_delay_set(port_id, link_down_delay_ms) != 0) { RTE_LOG(ERR, EAL, "Failed to set link down propagation delay (%u ms) on" " bonded device %s\n", link_down_delay_ms, name); return -1; } } else if (arg_count > 1) { RTE_LOG(INFO, EAL, "Link down propagation delay can be specified only once for" " bonded device %s\n", name); return -1; } return 0; } static struct rte_driver bond_drv = { .name = "eth_bond", .type = PMD_VDEV, .init = bond_init, .uninit = bond_uninit, }; PMD_REGISTER_DRIVER(bond_drv); ================================================ FILE: drivers/net/bonding/rte_eth_bond_private.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_BOND_PRIVATE_H_ #define _RTE_ETH_BOND_PRIVATE_H_ #include #include #include "rte_eth_bond.h" #include "rte_eth_bond_8023ad_private.h" #include "rte_eth_bond_alb.h" #define PMD_BOND_SLAVE_PORT_KVARG ("slave") #define PMD_BOND_PRIMARY_SLAVE_KVARG ("primary") #define PMD_BOND_MODE_KVARG ("mode") #define PMD_BOND_XMIT_POLICY_KVARG ("xmit_policy") #define PMD_BOND_SOCKET_ID_KVARG ("socket_id") #define PMD_BOND_MAC_ADDR_KVARG ("mac") #define PMD_BOND_LSC_POLL_PERIOD_KVARG ("lsc_poll_period_ms") #define PMD_BOND_LINK_UP_PROP_DELAY_KVARG ("up_delay") #define PMD_BOND_LINK_DOWN_PROP_DELAY_KVARG ("down_delay") #define PMD_BOND_XMIT_POLICY_LAYER2_KVARG ("l2") #define PMD_BOND_XMIT_POLICY_LAYER23_KVARG ("l23") #define PMD_BOND_XMIT_POLICY_LAYER34_KVARG ("l34") #define RTE_BOND_LOG(lvl, msg, ...) \ RTE_LOG(lvl, PMD, "%s(%d) - " msg "\n", __func__, __LINE__, ##__VA_ARGS__) #define BONDING_MODE_INVALID 0xFF extern const char *pmd_bond_init_valid_arguments[]; extern const char pmd_bond_driver_name[]; /** Port Queue Mapping Structure */ struct bond_rx_queue { uint16_t queue_id; /**< Queue Id */ struct bond_dev_private *dev_private; /**< Reference to eth_dev private structure */ uint16_t nb_rx_desc; /**< Number of RX descriptors available for the queue */ struct rte_eth_rxconf rx_conf; /**< Copy of RX configuration structure for queue */ struct rte_mempool *mb_pool; /**< Reference to mbuf pool to use for RX queue */ }; struct bond_tx_queue { uint16_t queue_id; /**< Queue Id */ struct bond_dev_private *dev_private; /**< Reference to dev private structure */ uint16_t nb_tx_desc; /**< Number of TX descriptors available for the queue */ struct rte_eth_txconf tx_conf; /**< Copy of TX configuration structure for queue */ }; /** Bonded slave devices structure */ struct bond_ethdev_slave_ports { uint8_t slaves[RTE_MAX_ETHPORTS]; /**< Slave port id array */ uint8_t slave_count; /**< Number of slaves */ }; struct bond_slave_details { uint8_t port_id; uint8_t link_status_poll_enabled; uint8_t link_status_wait_to_complete; uint8_t last_link_status; /**< Port Id of slave eth_dev */ struct ether_addr persisted_mac_addr; }; typedef uint16_t (*xmit_hash_t)(const struct rte_mbuf *buf, uint8_t slave_count); /** Link Bonding PMD device private configuration Structure */ struct bond_dev_private { uint8_t port_id; /**< Port Id of Bonded Port */ uint8_t mode; /**< Link Bonding Mode */ rte_spinlock_t lock; uint8_t primary_port; /**< Primary Slave Port */ uint8_t current_primary_port; /**< Primary Slave Port */ uint8_t user_defined_primary_port; /**< Flag for whether primary port is user defined or not */ uint8_t balance_xmit_policy; /**< Transmit policy - l2 / l23 / l34 for operation in balance mode */ xmit_hash_t xmit_hash; /**< Transmit policy hash function */ uint8_t user_defined_mac; /**< Flag for whether MAC address is user defined or not */ uint8_t promiscuous_en; /**< Enabled/disable promiscuous mode on bonding device */ uint8_t link_props_set; /**< flag to denote if the link properties are set */ uint8_t link_status_polling_enabled; uint32_t link_status_polling_interval_ms; uint32_t link_down_delay_ms; uint32_t link_up_delay_ms; uint16_t nb_rx_queues; /**< Total number of rx queues */ uint16_t nb_tx_queues; /**< Total number of tx queues*/ uint8_t active_slave_count; /**< Number of active slaves */ uint8_t active_slaves[RTE_MAX_ETHPORTS]; /**< Active slave list */ uint8_t slave_count; /**< Number of bonded slaves */ struct bond_slave_details slaves[RTE_MAX_ETHPORTS]; /**< Arary of bonded slaves details */ struct mode8023ad_private mode4; uint8_t tlb_slaves_order[RTE_MAX_ETHPORTS]; /* TLB active slaves send order */ struct mode_alb_private mode6; uint32_t rx_offload_capa; /** Rx offload capability */ uint32_t tx_offload_capa; /** Tx offload capability */ struct rte_kvargs *kvlist; uint8_t slave_update_idx; }; extern struct eth_dev_ops default_dev_ops; int valid_bonded_ethdev(const struct rte_eth_dev *eth_dev); /* Search given slave array to find possition of given id. * Return slave pos or slaves_count if not found. */ static inline uint8_t find_slave_by_id(uint8_t *slaves, uint8_t slaves_count, uint8_t slave_id) { uint8_t pos; for (pos = 0; pos < slaves_count; pos++) { if (slave_id == slaves[pos]) break; } return pos; } int valid_port_id(uint8_t port_id); int valid_bonded_port_id(uint8_t port_id); int valid_slave_port_id(uint8_t port_id); void deactivate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id); void activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id); void link_properties_set(struct rte_eth_dev *bonded_eth_dev, struct rte_eth_link *slave_dev_link); void link_properties_reset(struct rte_eth_dev *bonded_eth_dev); int link_properties_valid(struct rte_eth_link *bonded_dev_link, struct rte_eth_link *slave_dev_link); int mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr *new_mac_addr); int mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr *dst_mac_addr); int mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev); uint8_t number_of_sockets(void); int bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, int mode); int slave_configure(struct rte_eth_dev *bonded_eth_dev, struct rte_eth_dev *slave_eth_dev); void slave_remove(struct bond_dev_private *internals, struct rte_eth_dev *slave_eth_dev); void slave_add(struct bond_dev_private *internals, struct rte_eth_dev *slave_eth_dev); uint16_t xmit_l2_hash(const struct rte_mbuf *buf, uint8_t slave_count); uint16_t xmit_l23_hash(const struct rte_mbuf *buf, uint8_t slave_count); uint16_t xmit_l34_hash(const struct rte_mbuf *buf, uint8_t slave_count); void bond_ethdev_primary_set(struct bond_dev_private *internals, uint8_t slave_port_id); void bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param); int bond_ethdev_parse_slave_port_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_slave_mode_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_socket_id_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_primary_slave_port_id_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_balance_xmit_policy_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_bond_mac_addr_kvarg(const char *key __rte_unused, const char *value, void *extra_args); int bond_ethdev_parse_time_ms_kvarg(const char *key __rte_unused, const char *value, void *extra_args); void bond_tlb_disable(struct bond_dev_private *internals); void bond_tlb_enable(struct bond_dev_private *internals); void bond_tlb_activate_slave(struct bond_dev_private *internals); void bond_ethdev_stop(struct rte_eth_dev *eth_dev); void bond_ethdev_close(struct rte_eth_dev *dev); #endif ================================================ FILE: drivers/net/cxgbe/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2014-2015 Chelsio Communications. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Chelsio Communications nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_cxgbe.a CFLAGS += -I$(SRCDIR)/base/ CFLAGS += -I$(SRCDIR) CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_cxgbe_version.map LIBABIVER := 1 ifeq ($(CC), icc) # # CFLAGS for icc # CFLAGS_BASE_DRIVER = -wd188 else # # CFLAGS for gcc/clang # ifeq ($(shell test $(CC) = gcc && test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS += -Wno-deprecated endif CFLAGS_BASE_DRIVER = endif # # Add extra flags for base driver files (also known as shared code) # to disable warnings in them # BASE_DRIVER_OBJS=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(BASE_DRIVER_OBJS), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += cxgbe_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += cxgbe_main.c SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += sge.c SRCS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += t4_hw.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += lib/librte_net lib/librte_malloc include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/cxgbe/base/adapter.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* This file should not be included directly. Include common.h instead. */ #ifndef __T4_ADAPTER_H__ #define __T4_ADAPTER_H__ #include #include "cxgbe_compat.h" #include "t4_regs_values.h" enum { MAX_ETH_QSETS = 64, /* # of Ethernet Tx/Rx queue sets */ }; struct adapter; struct sge_rspq; enum { PORT_RSS_DONE = (1 << 0), }; struct port_info { struct adapter *adapter; /* adapter that this port belongs to */ struct rte_eth_dev *eth_dev; /* associated rte eth device */ struct port_stats stats_base; /* port statistics base */ struct link_config link_cfg; /* link configuration info */ unsigned long flags; /* port related flags */ short int xact_addr_filt; /* index of exact MAC address filter */ u16 viid; /* associated virtual interface id */ s8 mdio_addr; /* address of the PHY */ u8 port_type; /* firmware port type */ u8 mod_type; /* firmware module type */ u8 port_id; /* physical port ID */ u8 tx_chan; /* associated channel */ u8 n_rx_qsets; /* # of rx qsets */ u8 n_tx_qsets; /* # of tx qsets */ u8 first_qset; /* index of first qset */ u16 *rss; /* rss table */ u8 rss_mode; /* rss mode */ u16 rss_size; /* size of VI's RSS table slice */ }; /* Enable or disable autonegotiation. If this is set to enable, * the forced link modes above are completely ignored. */ #define AUTONEG_DISABLE 0x00 #define AUTONEG_ENABLE 0x01 enum { /* adapter flags */ FULL_INIT_DONE = (1 << 0), USING_MSI = (1 << 1), USING_MSIX = (1 << 2), FW_QUEUE_BOUND = (1 << 3), FW_OK = (1 << 4), CFG_QUEUES = (1 << 5), MASTER_PF = (1 << 6), }; struct rx_sw_desc { /* SW state per Rx descriptor */ void *buf; /* struct page or mbuf */ dma_addr_t dma_addr; }; struct sge_fl { /* SGE free-buffer queue state */ /* RO fields */ struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ dma_addr_t addr; /* bus address of HW ring start */ __be64 *desc; /* address of HW Rx descriptor ring */ void __iomem *bar2_addr; /* address of BAR2 Queue registers */ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */ unsigned int cntxt_id; /* SGE relative QID for the free list */ unsigned int size; /* capacity of free list */ unsigned int avail; /* # of available Rx buffers */ unsigned int pend_cred; /* new buffers since last FL DB ring */ unsigned int cidx; /* consumer index */ unsigned int pidx; /* producer index */ unsigned long alloc_failed; /* # of times buffer allocation failed */ unsigned long low; /* # of times momentarily starving */ }; #define MAX_MBUF_FRAGS (16384 / 512 + 2) /* A packet gather list */ struct pkt_gl { union { struct rte_mbuf *mbufs[MAX_MBUF_FRAGS]; } /* UNNAMED */; void *va; /* virtual address of first byte */ unsigned int nfrags; /* # of fragments */ unsigned int tot_len; /* total length of fragments */ bool usembufs; /* use mbufs for fragments */ }; typedef int (*rspq_handler_t)(struct sge_rspq *q, const __be64 *rsp, const struct pkt_gl *gl); struct sge_rspq { /* state for an SGE response queue */ struct adapter *adapter; /* adapter that this queue belongs to */ struct rte_eth_dev *eth_dev; /* associated rte eth device */ struct rte_mempool *mb_pool; /* associated mempool */ dma_addr_t phys_addr; /* physical address of the ring */ __be64 *desc; /* address of HW response ring */ const __be64 *cur_desc; /* current descriptor in queue */ void __iomem *bar2_addr; /* address of BAR2 Queue registers */ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */ unsigned int cidx; /* consumer index */ unsigned int gts_idx; /* last gts write sent */ unsigned int iqe_len; /* entry size */ unsigned int size; /* capacity of response queue */ int offset; /* offset into current Rx buffer */ u8 gen; /* current generation bit */ u8 intr_params; /* interrupt holdoff parameters */ u8 next_intr_params; /* holdoff params for next interrupt */ u8 pktcnt_idx; /* interrupt packet threshold */ u8 port_id; /* associated port-id */ u8 idx; /* queue index within its group */ u16 cntxt_id; /* SGE relative QID for the response Q */ u16 abs_id; /* absolute SGE id for the response q */ rspq_handler_t handler; /* associated handler for this response q */ }; struct sge_eth_rx_stats { /* Ethernet rx queue statistics */ u64 pkts; /* # of ethernet packets */ u64 rx_bytes; /* # of ethernet bytes */ u64 rx_cso; /* # of Rx checksum offloads */ u64 vlan_ex; /* # of Rx VLAN extractions */ u64 rx_drops; /* # of packets dropped due to no mem */ }; struct sge_eth_rxq { /* a SW Ethernet Rx queue */ struct sge_rspq rspq; struct sge_fl fl; struct sge_eth_rx_stats stats; bool usembufs; /* one ingress packet per mbuf FL buffer */ } __rte_cache_aligned; /* * Currently there are two types of coalesce WR. Type 0 needs 48 bytes per * packet (if one sgl is present) and type 1 needs 32 bytes. This means * that type 0 can fit a maximum of 10 packets per WR and type 1 can fit * 15 packets. We need to keep track of the mbuf pointers in a coalesce WR * to be able to free those mbufs when we get completions back from the FW. * Allocating the maximum number of pointers in every tx desc is a waste * of memory resources so we only store 2 pointers per tx desc which should * be enough since a tx desc can only fit 2 packets in the best case * scenario where a packet needs 32 bytes. */ #define ETH_COALESCE_PKT_NUM 15 #define ETH_COALESCE_PKT_PER_DESC 2 struct tx_eth_coal_desc { struct rte_mbuf *mbuf[ETH_COALESCE_PKT_PER_DESC]; struct ulptx_sgl *sgl[ETH_COALESCE_PKT_PER_DESC]; int idx; }; struct tx_desc { __be64 flit[8]; }; struct tx_sw_desc { /* SW state per Tx descriptor */ struct rte_mbuf *mbuf; struct ulptx_sgl *sgl; struct tx_eth_coal_desc coalesce; }; enum { EQ_STOPPED = (1 << 0), }; struct eth_coalesce { unsigned char *ptr; unsigned char type; unsigned int idx; unsigned int len; unsigned int flits; unsigned int max; }; struct sge_txq { struct tx_desc *desc; /* address of HW Tx descriptor ring */ struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */ struct sge_qstat *stat; /* queue status entry */ struct eth_coalesce coalesce; /* coalesce info */ uint64_t phys_addr; /* physical address of the ring */ void __iomem *bar2_addr; /* address of BAR2 Queue registers */ unsigned int bar2_qid; /* Queue ID for BAR2 Queue registers */ unsigned int cntxt_id; /* SGE relative QID for the Tx Q */ unsigned int in_use; /* # of in-use Tx descriptors */ unsigned int size; /* # of descriptors */ unsigned int cidx; /* SW consumer index */ unsigned int pidx; /* producer index */ unsigned int dbidx; /* last idx when db ring was done */ unsigned int equeidx; /* last sent credit request */ unsigned int last_pidx; /* last pidx recorded by tx monitor */ unsigned int last_coal_idx;/* last coal-idx recorded by tx monitor */ int db_disabled; /* doorbell state */ unsigned short db_pidx; /* doorbell producer index */ unsigned short db_pidx_inc; /* doorbell producer increment */ }; struct sge_eth_tx_stats { /* Ethernet tx queue statistics */ u64 pkts; /* # of ethernet packets */ u64 tx_bytes; /* # of ethernet bytes */ u64 tso; /* # of TSO requests */ u64 tx_cso; /* # of Tx checksum offloads */ u64 vlan_ins; /* # of Tx VLAN insertions */ u64 mapping_err; /* # of I/O MMU packet mapping errors */ u64 coal_wr; /* # of coalesced wr */ u64 coal_pkts; /* # of coalesced packets */ }; struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */ struct sge_txq q; struct rte_eth_dev *eth_dev; /* port that this queue belongs to */ struct sge_eth_tx_stats stats; /* queue statistics */ rte_spinlock_t txq_lock; unsigned int flags; /* flags for state of the queue */ } __rte_cache_aligned; struct sge { struct sge_eth_txq ethtxq[MAX_ETH_QSETS]; struct sge_eth_rxq ethrxq[MAX_ETH_QSETS]; struct sge_rspq fw_evtq __rte_cache_aligned; u16 max_ethqsets; /* # of available Ethernet queue sets */ u32 stat_len; /* length of status page at ring end */ u32 pktshift; /* padding between CPL & packet data */ /* response queue interrupt parameters */ u16 timer_val[SGE_NTIMERS]; u8 counter_val[SGE_NCOUNTERS]; u32 fl_align; /* response queue message alignment */ u32 fl_pg_order; /* large page allocation size */ u32 fl_starve_thres; /* Free List starvation threshold */ }; #define T4_OS_NEEDS_MBOX_LOCKING 1 /* * OS Lock/List primitives for those interfaces in the Common Code which * need this. */ struct mbox_entry { TAILQ_ENTRY(mbox_entry) next; }; TAILQ_HEAD(mbox_list, mbox_entry); struct adapter { struct rte_pci_device *pdev; /* associated rte pci device */ struct rte_eth_dev *eth_dev; /* first port's rte eth device */ struct adapter_params params; /* adapter parameters */ struct port_info port[MAX_NPORTS]; /* ports belonging to this adapter */ struct sge sge; /* associated SGE */ /* support for single-threading access to adapter mailbox registers */ struct mbox_list mbox_list; rte_spinlock_t mbox_lock; u8 *regs; /* pointer to registers region */ u8 *bar2; /* pointer to bar2 region */ unsigned long flags; /* adapter flags */ unsigned int mbox; /* associated mailbox */ unsigned int pf; /* associated physical function id */ int use_unpacked_mode; /* unpacked rx mode state */ }; #define CXGBE_PCI_REG(reg) (*((volatile uint32_t *)(reg))) static inline uint64_t cxgbe_read_addr64(volatile void *addr) { uint64_t val = CXGBE_PCI_REG(addr); uint64_t val2 = CXGBE_PCI_REG(((volatile uint8_t *)(addr) + 4)); val2 = (uint64_t)(val2 << 32); val += val2; return val; } static inline uint32_t cxgbe_read_addr(volatile void *addr) { return CXGBE_PCI_REG(addr); } #define CXGBE_PCI_REG_ADDR(adap, reg) \ ((volatile uint32_t *)((char *)(adap)->regs + (reg))) #define CXGBE_READ_REG(adap, reg) \ cxgbe_read_addr(CXGBE_PCI_REG_ADDR((adap), (reg))) #define CXGBE_READ_REG64(adap, reg) \ cxgbe_read_addr64(CXGBE_PCI_REG_ADDR((adap), (reg))) #define CXGBE_PCI_REG_WRITE(reg, value) ({ \ CXGBE_PCI_REG((reg)) = (value); }) #define CXGBE_WRITE_REG(adap, reg, value) \ CXGBE_PCI_REG_WRITE(CXGBE_PCI_REG_ADDR((adap), (reg)), (value)) static inline uint64_t cxgbe_write_addr64(volatile void *addr, uint64_t val) { CXGBE_PCI_REG(addr) = val; CXGBE_PCI_REG(((volatile uint8_t *)(addr) + 4)) = (val >> 32); return val; } #define CXGBE_WRITE_REG64(adap, reg, value) \ cxgbe_write_addr64(CXGBE_PCI_REG_ADDR((adap), (reg)), (value)) /** * t4_read_reg - read a HW register * @adapter: the adapter * @reg_addr: the register address * * Returns the 32-bit value of the given HW register. */ static inline u32 t4_read_reg(struct adapter *adapter, u32 reg_addr) { u32 val = CXGBE_READ_REG(adapter, reg_addr); CXGBE_DEBUG_REG(adapter, "read register 0x%x value 0x%x\n", reg_addr, val); return val; } /** * t4_write_reg - write a HW register * @adapter: the adapter * @reg_addr: the register address * @val: the value to write * * Write a 32-bit value into the given HW register. */ static inline void t4_write_reg(struct adapter *adapter, u32 reg_addr, u32 val) { CXGBE_DEBUG_REG(adapter, "setting register 0x%x to 0x%x\n", reg_addr, val); CXGBE_WRITE_REG(adapter, reg_addr, val); } /** * t4_read_reg64 - read a 64-bit HW register * @adapter: the adapter * @reg_addr: the register address * * Returns the 64-bit value of the given HW register. */ static inline u64 t4_read_reg64(struct adapter *adapter, u32 reg_addr) { u64 val = CXGBE_READ_REG64(adapter, reg_addr); CXGBE_DEBUG_REG(adapter, "64-bit read register %#x value %#llx\n", reg_addr, (unsigned long long)val); return val; } /** * t4_write_reg64 - write a 64-bit HW register * @adapter: the adapter * @reg_addr: the register address * @val: the value to write * * Write a 64-bit value into the given HW register. */ static inline void t4_write_reg64(struct adapter *adapter, u32 reg_addr, u64 val) { CXGBE_DEBUG_REG(adapter, "setting register %#x to %#llx\n", reg_addr, (unsigned long long)val); CXGBE_WRITE_REG64(adapter, reg_addr, val); } /** * t4_os_set_hw_addr - store a port's MAC address in SW * @adapter: the adapter * @port_idx: the port index * @hw_addr: the Ethernet address * * Store the Ethernet address of the given port in SW. Called by the * common code when it retrieves a port's Ethernet address from EEPROM. */ static inline void t4_os_set_hw_addr(struct adapter *adapter, int port_idx, u8 hw_addr[]) { struct port_info *pi = &adapter->port[port_idx]; ether_addr_copy((struct ether_addr *)hw_addr, &pi->eth_dev->data->mac_addrs[0]); } /** * t4_os_lock_init - initialize spinlock * @lock: the spinlock */ static inline void t4_os_lock_init(rte_spinlock_t *lock) { rte_spinlock_init(lock); } /** * t4_os_lock - spin until lock is acquired * @lock: the spinlock */ static inline void t4_os_lock(rte_spinlock_t *lock) { rte_spinlock_lock(lock); } /** * t4_os_unlock - unlock a spinlock * @lock: the spinlock */ static inline void t4_os_unlock(rte_spinlock_t *lock) { rte_spinlock_unlock(lock); } /** * t4_os_init_list_head - initialize * @head: head of list to initialize [to empty] */ static inline void t4_os_init_list_head(struct mbox_list *head) { TAILQ_INIT(head); } static inline struct mbox_entry *t4_os_list_first_entry(struct mbox_list *head) { return TAILQ_FIRST(head); } /** * t4_os_atomic_add_tail - Enqueue list element atomically onto list * @new: the entry to be addded to the queue * @head: current head of the linked list * @lock: lock to use to guarantee atomicity */ static inline void t4_os_atomic_add_tail(struct mbox_entry *entry, struct mbox_list *head, rte_spinlock_t *lock) { t4_os_lock(lock); TAILQ_INSERT_TAIL(head, entry, next); t4_os_unlock(lock); } /** * t4_os_atomic_list_del - Dequeue list element atomically from list * @entry: the entry to be remove/dequeued from the list. * @lock: the spinlock */ static inline void t4_os_atomic_list_del(struct mbox_entry *entry, struct mbox_list *head, rte_spinlock_t *lock) { t4_os_lock(lock); TAILQ_REMOVE(head, entry, next); t4_os_unlock(lock); } /** * adap2pinfo - return the port_info of a port * @adap: the adapter * @idx: the port index * * Return the port_info structure for the port of the given index. */ static inline struct port_info *adap2pinfo(struct adapter *adap, int idx) { return &adap->port[idx]; } void *t4_alloc_mem(size_t size); void t4_free_mem(void *addr); #define t4_os_alloc(_size) t4_alloc_mem((_size)) #define t4_os_free(_ptr) t4_free_mem((_ptr)) void t4_os_portmod_changed(const struct adapter *adap, int port_id); void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat); void reclaim_completed_tx(struct sge_txq *q); void t4_free_sge_resources(struct adapter *adap); void t4_sge_tx_monitor_start(struct adapter *adap); void t4_sge_tx_monitor_stop(struct adapter *adap); int t4_eth_xmit(struct sge_eth_txq *txq, struct rte_mbuf *mbuf); int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, const struct pkt_gl *gl); int t4_sge_init(struct adapter *adap); int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, struct rte_eth_dev *eth_dev, uint16_t queue_id, unsigned int iqid, int socket_id); int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *rspq, bool fwevtq, struct rte_eth_dev *eth_dev, int intr_idx, struct sge_fl *fl, rspq_handler_t handler, int cong, struct rte_mempool *mp, int queue_id, int socket_id); int t4_sge_eth_txq_start(struct sge_eth_txq *txq); int t4_sge_eth_txq_stop(struct sge_eth_txq *txq); void t4_sge_eth_txq_release(struct adapter *adap, struct sge_eth_txq *txq); int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq); int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq); void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq); void t4_sge_eth_clear_queues(struct port_info *pi); int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us, unsigned int cnt); int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts, unsigned int budget, unsigned int *work_done); int cxgb4_write_rss(const struct port_info *pi, const u16 *queues); #endif /* __T4_ADAPTER_H__ */ ================================================ FILE: drivers/net/cxgbe/base/common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __CHELSIO_COMMON_H #define __CHELSIO_COMMON_H #include "cxgbe_compat.h" #include "t4_hw.h" #include "t4_chip_type.h" #include "t4fw_interface.h" #ifdef __cplusplus extern "C" { #endif #define CXGBE_PAGE_SIZE RTE_PGSIZE_4K enum { MAX_NPORTS = 4, /* max # of ports */ }; enum { MEMWIN0_APERTURE = 2048, MEMWIN0_BASE = 0x1b800, }; enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST }; enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR }; enum { PAUSE_RX = 1 << 0, PAUSE_TX = 1 << 1, PAUSE_AUTONEG = 1 << 2 }; struct port_stats { u64 tx_octets; /* total # of octets in good frames */ u64 tx_frames; /* all good frames */ u64 tx_bcast_frames; /* all broadcast frames */ u64 tx_mcast_frames; /* all multicast frames */ u64 tx_ucast_frames; /* all unicast frames */ u64 tx_error_frames; /* all error frames */ u64 tx_frames_64; /* # of Tx frames in a particular range */ u64 tx_frames_65_127; u64 tx_frames_128_255; u64 tx_frames_256_511; u64 tx_frames_512_1023; u64 tx_frames_1024_1518; u64 tx_frames_1519_max; u64 tx_drop; /* # of dropped Tx frames */ u64 tx_pause; /* # of transmitted pause frames */ u64 tx_ppp0; /* # of transmitted PPP prio 0 frames */ u64 tx_ppp1; /* # of transmitted PPP prio 1 frames */ u64 tx_ppp2; /* # of transmitted PPP prio 2 frames */ u64 tx_ppp3; /* # of transmitted PPP prio 3 frames */ u64 tx_ppp4; /* # of transmitted PPP prio 4 frames */ u64 tx_ppp5; /* # of transmitted PPP prio 5 frames */ u64 tx_ppp6; /* # of transmitted PPP prio 6 frames */ u64 tx_ppp7; /* # of transmitted PPP prio 7 frames */ u64 rx_octets; /* total # of octets in good frames */ u64 rx_frames; /* all good frames */ u64 rx_bcast_frames; /* all broadcast frames */ u64 rx_mcast_frames; /* all multicast frames */ u64 rx_ucast_frames; /* all unicast frames */ u64 rx_too_long; /* # of frames exceeding MTU */ u64 rx_jabber; /* # of jabber frames */ u64 rx_fcs_err; /* # of received frames with bad FCS */ u64 rx_len_err; /* # of received frames with length error */ u64 rx_symbol_err; /* symbol errors */ u64 rx_runt; /* # of short frames */ u64 rx_frames_64; /* # of Rx frames in a particular range */ u64 rx_frames_65_127; u64 rx_frames_128_255; u64 rx_frames_256_511; u64 rx_frames_512_1023; u64 rx_frames_1024_1518; u64 rx_frames_1519_max; u64 rx_pause; /* # of received pause frames */ u64 rx_ppp0; /* # of received PPP prio 0 frames */ u64 rx_ppp1; /* # of received PPP prio 1 frames */ u64 rx_ppp2; /* # of received PPP prio 2 frames */ u64 rx_ppp3; /* # of received PPP prio 3 frames */ u64 rx_ppp4; /* # of received PPP prio 4 frames */ u64 rx_ppp5; /* # of received PPP prio 5 frames */ u64 rx_ppp6; /* # of received PPP prio 6 frames */ u64 rx_ppp7; /* # of received PPP prio 7 frames */ u64 rx_ovflow0; /* drops due to buffer-group 0 overflows */ u64 rx_ovflow1; /* drops due to buffer-group 1 overflows */ u64 rx_ovflow2; /* drops due to buffer-group 2 overflows */ u64 rx_ovflow3; /* drops due to buffer-group 3 overflows */ u64 rx_trunc0; /* buffer-group 0 truncated packets */ u64 rx_trunc1; /* buffer-group 1 truncated packets */ u64 rx_trunc2; /* buffer-group 2 truncated packets */ u64 rx_trunc3; /* buffer-group 3 truncated packets */ }; struct sge_params { u32 hps; /* host page size for our PF/VF */ u32 eq_qpp; /* egress queues/page for our PF/VF */ u32 iq_qpp; /* egress queues/page for our PF/VF */ }; struct tp_params { unsigned int ntxchan; /* # of Tx channels */ unsigned int tre; /* log2 of core clocks per TP tick */ unsigned int dack_re; /* DACK timer resolution */ unsigned int la_mask; /* what events are recorded by TP LA */ unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ u32 vlan_pri_map; /* cached TP_VLAN_PRI_MAP */ u32 ingress_config; /* cached TP_INGRESS_CONFIG */ /* * TP_VLAN_PRI_MAP Compressed Filter Tuple field offsets. This is a * subset of the set of fields which may be present in the Compressed * Filter Tuple portion of filters and TCP TCB connections. The * fields which are present are controlled by the TP_VLAN_PRI_MAP. * Since a variable number of fields may or may not be present, their * shifted field positions within the Compressed Filter Tuple may * vary, or not even be present if the field isn't selected in * TP_VLAN_PRI_MAP. Since some of these fields are needed in various * places we store their offsets here, or a -1 if the field isn't * present. */ int vlan_shift; int vnic_shift; int port_shift; int protocol_shift; }; struct vpd_params { unsigned int cclk; }; struct pci_params { uint16_t vendor_id; uint16_t device_id; uint32_t vpd_cap_addr; uint16_t speed; uint8_t width; }; /* * Firmware device log. */ struct devlog_params { u32 memtype; /* which memory (EDC0, EDC1, MC) */ u32 start; /* start of log in firmware memory */ u32 size; /* size of log */ }; struct arch_specific_params { u8 nchan; u16 mps_rplc_size; u16 vfcount; u32 sge_fl_db; u16 mps_tcam_size; }; struct adapter_params { struct sge_params sge; struct tp_params tp; struct vpd_params vpd; struct pci_params pci; struct devlog_params devlog; enum pcie_memwin drv_memwin; unsigned int sf_size; /* serial flash size in bytes */ unsigned int sf_nsec; /* # of flash sectors */ unsigned int fw_vers; unsigned int tp_vers; unsigned short mtus[NMTUS]; unsigned short a_wnd[NCCTRL_WIN]; unsigned short b_wnd[NCCTRL_WIN]; unsigned int mc_size; /* MC memory size */ unsigned int cim_la_size; unsigned char nports; /* # of ethernet ports */ unsigned char portvec; enum chip_type chip; /* chip code */ struct arch_specific_params arch; /* chip specific params */ bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */ }; struct link_config { unsigned short supported; /* link capabilities */ unsigned short advertising; /* advertised capabilities */ unsigned short requested_speed; /* speed user has requested */ unsigned short speed; /* actual link speed */ unsigned char requested_fc; /* flow control user has requested */ unsigned char fc; /* actual link flow control */ unsigned char autoneg; /* autonegotiating? */ unsigned char link_ok; /* link up? */ }; #include "adapter.h" void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask, u32 val); int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, int polarity, int attempts, int delay, u32 *valp); static inline int t4_wait_op_done(struct adapter *adapter, int reg, u32 mask, int polarity, int attempts, int delay) { return t4_wait_op_done_val(adapter, reg, mask, polarity, attempts, delay, NULL); } #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, unsigned int mask, unsigned int val); void t4_intr_enable(struct adapter *adapter); void t4_intr_disable(struct adapter *adapter); int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc); void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, const unsigned short *alpha, const unsigned short *beta); int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, enum dev_master master, enum dev_state *state); int t4_fw_bye(struct adapter *adap, unsigned int mbox); int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset); int t4_fw_halt(struct adapter *adap, unsigned int mbox, int reset); int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset); int t4_fixup_host_params_compat(struct adapter *adap, unsigned int page_size, unsigned int cache_line_size, enum chip_type chip_compat); int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, unsigned int cache_line_size); int t4_fw_initialize(struct adapter *adap, unsigned int mbox); int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, u32 *val); int t4_set_params_timeout(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, const u32 *val, int timeout); int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, const u32 *val); int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox, unsigned int port, unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, unsigned int *rss_size, unsigned int portfunc, unsigned int idstype); int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, unsigned int *rss_size); int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int viid); int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, int mtu, int promisc, int all_multi, int bcast, int vlanex, bool sleep_ok); int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, int idx, const u8 *addr, bool persist, bool add_smt); int t4_enable_vi_params(struct adapter *adap, unsigned int mbox, unsigned int viid, bool rx_en, bool tx_en, bool dcb_en); int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid, bool rx_en, bool tx_en); int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start, unsigned int pf, unsigned int vf, unsigned int iqid, unsigned int fl0id, unsigned int fl1id); int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int iqtype, unsigned int iqid, unsigned int fl0id, unsigned int fl1id); int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid); static inline unsigned int core_ticks_per_usec(const struct adapter *adap) { return adap->params.vpd.cclk / 1000; } static inline unsigned int us_to_core_ticks(const struct adapter *adap, unsigned int us) { return (us * adap->params.vpd.cclk) / 1000; } static inline unsigned int core_ticks_to_us(const struct adapter *adapter, unsigned int ticks) { /* add Core Clock / 2 to round ticks to nearest uS */ return ((ticks * 1000 + adapter->params.vpd.cclk / 2) / adapter->params.vpd.cclk); } int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl, bool sleep_ok, int timeout); int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void __attribute__((__may_alias__)) *cmd, int size, void *rpl, bool sleep_ok); static inline int t4_wr_mbox_timeout(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl, int timeout) { return t4_wr_mbox_meat_timeout(adap, mbox, cmd, size, rpl, true, timeout); } int t4_get_core_clock(struct adapter *adapter, struct vpd_params *p); static inline int t4_wr_mbox(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl) { return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, true); } static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl) { return t4_wr_mbox_meat(adap, mbox, cmd, size, rpl, false); } void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, u32 *vals, unsigned int nregs, unsigned int start_idx); void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, const u32 *vals, unsigned int nregs, unsigned int start_idx); int t4_get_vpd_params(struct adapter *adapter, struct vpd_params *p); int t4_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented); int t4_flash_cfg_addr(struct adapter *adapter); unsigned int t4_get_mps_bg_map(struct adapter *adapter, int idx); const char *t4_get_port_type_description(enum fw_port_type port_type); void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); void t4_get_port_stats_offset(struct adapter *adap, int idx, struct port_stats *stats, struct port_stats *offset); void t4_clr_port_stats(struct adapter *adap, int idx); void t4_reset_link_config(struct adapter *adap, int idx); int t4_get_fw_version(struct adapter *adapter, u32 *vers); int t4_get_tp_version(struct adapter *adapter, u32 *vers); int t4_get_flash_params(struct adapter *adapter); int t4_prep_adapter(struct adapter *adapter); int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); int t4_init_rss_mode(struct adapter *adap, int mbox); int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, int start, int n, const u16 *rspq, unsigned int nrspq); int t4_config_vi_rss(struct adapter *adapter, int mbox, unsigned int viid, unsigned int flags, unsigned int defq); enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS }; int t4_bar2_sge_qregs(struct adapter *adapter, unsigned int qid, unsigned int qtype, u64 *pbar2_qoffset, unsigned int *pbar2_qid); int t4_init_sge_params(struct adapter *adapter); int t4_init_tp_params(struct adapter *adap); int t4_filter_field_shift(const struct adapter *adap, unsigned int filter_sel); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); #endif /* __CHELSIO_COMMON_H */ ================================================ FILE: drivers/net/cxgbe/base/t4_chip_type.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __T4_CHIP_TYPE_H__ #define __T4_CHIP_TYPE_H__ /* * All T4 and later chips have their PCI-E Device IDs encoded as 0xVFPP where: * * V = "4" for T4; "5" for T5, etc. or * F = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs * PP = adapter product designation * * We use the "version" (V) of the adpater to code the Chip Version above. */ #define CHELSIO_PCI_ID_VER(devid) ((devid) >> 12) #define CHELSIO_PCI_ID_FUNC(devid) (((devid) >> 8) & 0xf) #define CHELSIO_PCI_ID_PROD(devid) ((devid) & 0xff) #define CHELSIO_T4 0x4 #define CHELSIO_T5 0x5 #define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) #define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf) #define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) enum chip_type { T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), T4_FIRST_REV = T4_A1, T4_LAST_REV = T4_A2, T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1), T5_FIRST_REV = T5_A0, T5_LAST_REV = T5_A1, }; static inline int is_t4(enum chip_type chip) { return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4); } static inline int is_t5(enum chip_type chip) { return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5); } #endif /* __T4_CHIP_TYPE_H__ */ ================================================ FILE: drivers/net/cxgbe/base/t4_hw.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "t4_regs.h" #include "t4_regs_values.h" #include "t4fw_interface.h" static void init_link_config(struct link_config *lc, unsigned int caps); /** * t4_read_mtu_tbl - returns the values in the HW path MTU table * @adap: the adapter * @mtus: where to store the MTU values * @mtu_log: where to store the MTU base-2 log (may be %NULL) * * Reads the HW path MTU table. */ void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log) { u32 v; int i; for (i = 0; i < NMTUS; ++i) { t4_write_reg(adap, A_TP_MTU_TABLE, V_MTUINDEX(0xff) | V_MTUVALUE(i)); v = t4_read_reg(adap, A_TP_MTU_TABLE); mtus[i] = G_MTUVALUE(v); if (mtu_log) mtu_log[i] = G_MTUWIDTH(v); } } /** * t4_tp_wr_bits_indirect - set/clear bits in an indirect TP register * @adap: the adapter * @addr: the indirect TP register address * @mask: specifies the field within the register to modify * @val: new value for the field * * Sets a field of an indirect TP register to the given value. */ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, unsigned int mask, unsigned int val) { t4_write_reg(adap, A_TP_PIO_ADDR, addr); val |= t4_read_reg(adap, A_TP_PIO_DATA) & ~mask; t4_write_reg(adap, A_TP_PIO_DATA, val); } /* The minimum additive increment value for the congestion control table */ #define CC_MIN_INCR 2U /** * t4_load_mtus - write the MTU and congestion control HW tables * @adap: the adapter * @mtus: the values for the MTU table * @alpha: the values for the congestion control alpha parameter * @beta: the values for the congestion control beta parameter * * Write the HW MTU table with the supplied MTUs and the high-speed * congestion control table with the supplied alpha, beta, and MTUs. * We write the two tables together because the additive increments * depend on the MTUs. */ void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, const unsigned short *alpha, const unsigned short *beta) { static const unsigned int avg_pkts[NCCTRL_WIN] = { 2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640, 896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480, 28672, 40960, 57344, 81920, 114688, 163840, 229376 }; unsigned int i, w; for (i = 0; i < NMTUS; ++i) { unsigned int mtu = mtus[i]; unsigned int log2 = cxgbe_fls(mtu); if (!(mtu & ((1 << log2) >> 2))) /* round */ log2--; t4_write_reg(adap, A_TP_MTU_TABLE, V_MTUINDEX(i) | V_MTUWIDTH(log2) | V_MTUVALUE(mtu)); for (w = 0; w < NCCTRL_WIN; ++w) { unsigned int inc; inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w], CC_MIN_INCR); t4_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) | (w << 16) | (beta[w] << 13) | inc); } } } /** * t4_wait_op_done_val - wait until an operation is completed * @adapter: the adapter performing the operation * @reg: the register to check for completion * @mask: a single-bit field within @reg that indicates completion * @polarity: the value of the field when the operation is completed * @attempts: number of check iterations * @delay: delay in usecs between iterations * @valp: where to store the value of the register at completion time * * Wait until an operation is completed by checking a bit in a register * up to @attempts times. If @valp is not NULL the value of the register * at the time it indicated completion is stored there. Returns 0 if the * operation completes and -EAGAIN otherwise. */ int t4_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, int polarity, int attempts, int delay, u32 *valp) { while (1) { u32 val = t4_read_reg(adapter, reg); if (!!(val & mask) == polarity) { if (valp) *valp = val; return 0; } if (--attempts == 0) return -EAGAIN; if (delay) udelay(delay); } } /** * t4_set_reg_field - set a register field to a value * @adapter: the adapter to program * @addr: the register address * @mask: specifies the portion of the register to modify * @val: the new value for the register field * * Sets a register field specified by the supplied mask to the * given value. */ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, u32 val) { u32 v = t4_read_reg(adapter, addr) & ~mask; t4_write_reg(adapter, addr, v | val); (void)t4_read_reg(adapter, addr); /* flush */ } /** * t4_read_indirect - read indirectly addressed registers * @adap: the adapter * @addr_reg: register holding the indirect address * @data_reg: register holding the value of the indirect register * @vals: where the read register values are stored * @nregs: how many indirect registers to read * @start_idx: index of first indirect register to read * * Reads registers that are accessed indirectly through an address/data * register pair. */ void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, u32 *vals, unsigned int nregs, unsigned int start_idx) { while (nregs--) { t4_write_reg(adap, addr_reg, start_idx); *vals++ = t4_read_reg(adap, data_reg); start_idx++; } } /** * t4_write_indirect - write indirectly addressed registers * @adap: the adapter * @addr_reg: register holding the indirect addresses * @data_reg: register holding the value for the indirect registers * @vals: values to write * @nregs: how many indirect registers to write * @start_idx: address of first indirect register to write * * Writes a sequential block of registers that are accessed indirectly * through an address/data register pair. */ void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, unsigned int data_reg, const u32 *vals, unsigned int nregs, unsigned int start_idx) { while (nregs--) { t4_write_reg(adap, addr_reg, start_idx++); t4_write_reg(adap, data_reg, *vals++); } } /** * t4_report_fw_error - report firmware error * @adap: the adapter * * The adapter firmware can indicate error conditions to the host. * If the firmware has indicated an error, print out the reason for * the firmware error. */ static void t4_report_fw_error(struct adapter *adap) { static const char * const reason[] = { "Crash", /* PCIE_FW_EVAL_CRASH */ "During Device Preparation", /* PCIE_FW_EVAL_PREP */ "During Device Configuration", /* PCIE_FW_EVAL_CONF */ "During Device Initialization", /* PCIE_FW_EVAL_INIT */ "Unexpected Event", /* PCIE_FW_EVAL_UNEXPECTEDEVENT */ "Insufficient Airflow", /* PCIE_FW_EVAL_OVERHEAT */ "Device Shutdown", /* PCIE_FW_EVAL_DEVICESHUTDOWN */ "Reserved", /* reserved */ }; u32 pcie_fw; pcie_fw = t4_read_reg(adap, A_PCIE_FW); if (pcie_fw & F_PCIE_FW_ERR) pr_err("%s: Firmware reports adapter error: %s\n", __func__, reason[G_PCIE_FW_EVAL(pcie_fw)]); } /* * Get the reply to a mailbox command and store it in @rpl in big-endian order. */ static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit, u32 mbox_addr) { for ( ; nflit; nflit--, mbox_addr += 8) *rpl++ = htobe64(t4_read_reg64(adap, mbox_addr)); } /* * Handle a FW assertion reported in a mailbox. */ static void fw_asrt(struct adapter *adap, u32 mbox_addr) { struct fw_debug_cmd asrt; get_mbox_rpl(adap, (__be64 *)&asrt, sizeof(asrt) / 8, mbox_addr); pr_warn("FW assertion at %.16s:%u, val0 %#x, val1 %#x\n", asrt.u.assert.filename_0_7, be32_to_cpu(asrt.u.assert.line), be32_to_cpu(asrt.u.assert.x), be32_to_cpu(asrt.u.assert.y)); } #define X_CIM_PF_NOACCESS 0xeeeeeeee /* * If the Host OS Driver needs locking arround accesses to the mailbox, this * can be turned on via the T4_OS_NEEDS_MBOX_LOCKING CPP define ... */ /* makes single-statement usage a bit cleaner ... */ #ifdef T4_OS_NEEDS_MBOX_LOCKING #define T4_OS_MBOX_LOCKING(x) x #else #define T4_OS_MBOX_LOCKING(x) do {} while (0) #endif /** * t4_wr_mbox_meat_timeout - send a command to FW through the given mailbox * @adap: the adapter * @mbox: index of the mailbox to use * @cmd: the command to write * @size: command length in bytes * @rpl: where to optionally store the reply * @sleep_ok: if true we may sleep while awaiting command completion * @timeout: time to wait for command to finish before timing out * (negative implies @sleep_ok=false) * * Sends the given command to FW through the selected mailbox and waits * for the FW to execute the command. If @rpl is not %NULL it is used to * store the FW's reply to the command. The command and its optional * reply are of the same length. Some FW commands like RESET and * INITIALIZE can take a considerable amount of time to execute. * @sleep_ok determines whether we may sleep while awaiting the response. * If sleeping is allowed we use progressive backoff otherwise we spin. * Note that passing in a negative @timeout is an alternate mechanism * for specifying @sleep_ok=false. This is useful when a higher level * interface allows for specification of @timeout but not @sleep_ok ... * * Returns 0 on success or a negative errno on failure. A * failure can happen either because we are not able to execute the * command or FW executes it but signals an error. In the latter case * the return value is the error code indicated by FW (negated). */ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void __attribute__((__may_alias__)) *cmd, int size, void *rpl, bool sleep_ok, int timeout) { /* * We delay in small increments at first in an effort to maintain * responsiveness for simple, fast executing commands but then back * off to larger delays to a maximum retry delay. */ static const int delay[] = { 1, 1, 3, 5, 10, 10, 20, 50, 100 }; u32 v; u64 res; int i, ms; unsigned int delay_idx; __be64 *temp = (__be64 *)malloc(size * sizeof(char)); __be64 *p = temp; u32 data_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_DATA); u32 ctl_reg = PF_REG(mbox, A_CIM_PF_MAILBOX_CTRL); u32 ctl; struct mbox_entry entry; u32 pcie_fw = 0; if ((size & 15) || size > MBOX_LEN) { free(temp); return -EINVAL; } bzero(p, size); memcpy(p, (const __be64 *)cmd, size); /* * If we have a negative timeout, that implies that we can't sleep. */ if (timeout < 0) { sleep_ok = false; timeout = -timeout; } #ifdef T4_OS_NEEDS_MBOX_LOCKING /* * Queue ourselves onto the mailbox access list. When our entry is at * the front of the list, we have rights to access the mailbox. So we * wait [for a while] till we're at the front [or bail out with an * EBUSY] ... */ t4_os_atomic_add_tail(&entry, &adap->mbox_list, &adap->mbox_lock); delay_idx = 0; ms = delay[0]; for (i = 0; ; i += ms) { /* * If we've waited too long, return a busy indication. This * really ought to be based on our initial position in the * mailbox access list but this is a start. We very rarely * contend on access to the mailbox ... Also check for a * firmware error which we'll report as a device error. */ pcie_fw = t4_read_reg(adap, A_PCIE_FW); if (i > 4 * timeout || (pcie_fw & F_PCIE_FW_ERR)) { t4_os_atomic_list_del(&entry, &adap->mbox_list, &adap->mbox_lock); t4_report_fw_error(adap); return (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -EBUSY; } /* * If we're at the head, break out and start the mailbox * protocol. */ if (t4_os_list_first_entry(&adap->mbox_list) == &entry) break; /* * Delay for a bit before checking again ... */ if (sleep_ok) { ms = delay[delay_idx]; /* last element may repeat */ if (delay_idx < ARRAY_SIZE(delay) - 1) delay_idx++; msleep(ms); } else { rte_delay_ms(ms); } } #endif /* T4_OS_NEEDS_MBOX_LOCKING */ /* * Attempt to gain access to the mailbox. */ for (i = 0; i < 4; i++) { ctl = t4_read_reg(adap, ctl_reg); v = G_MBOWNER(ctl); if (v != X_MBOWNER_NONE) break; } /* * If we were unable to gain access, dequeue ourselves from the * mailbox atomic access list and report the error to our caller. */ if (v != X_MBOWNER_PL) { T4_OS_MBOX_LOCKING(t4_os_atomic_list_del(&entry, &adap->mbox_list, &adap->mbox_lock)); t4_report_fw_error(adap); return (v == X_MBOWNER_FW ? -EBUSY : -ETIMEDOUT); } /* * If we gain ownership of the mailbox and there's a "valid" message * in it, this is likely an asynchronous error message from the * firmware. So we'll report that and then proceed on with attempting * to issue our own command ... which may well fail if the error * presaged the firmware crashing ... */ if (ctl & F_MBMSGVALID) { dev_err(adap, "found VALID command in mbox %u: " "%llx %llx %llx %llx %llx %llx %llx %llx\n", mbox, (unsigned long long)t4_read_reg64(adap, data_reg), (unsigned long long)t4_read_reg64(adap, data_reg + 8), (unsigned long long)t4_read_reg64(adap, data_reg + 16), (unsigned long long)t4_read_reg64(adap, data_reg + 24), (unsigned long long)t4_read_reg64(adap, data_reg + 32), (unsigned long long)t4_read_reg64(adap, data_reg + 40), (unsigned long long)t4_read_reg64(adap, data_reg + 48), (unsigned long long)t4_read_reg64(adap, data_reg + 56)); } /* * Copy in the new mailbox command and send it on its way ... */ for (i = 0; i < size; i += 8, p++) t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p)); CXGBE_DEBUG_MBOX(adap, "%s: mbox %u: %016llx %016llx %016llx %016llx " "%016llx %016llx %016llx %016llx\n", __func__, (mbox), (unsigned long long)t4_read_reg64(adap, data_reg), (unsigned long long)t4_read_reg64(adap, data_reg + 8), (unsigned long long)t4_read_reg64(adap, data_reg + 16), (unsigned long long)t4_read_reg64(adap, data_reg + 24), (unsigned long long)t4_read_reg64(adap, data_reg + 32), (unsigned long long)t4_read_reg64(adap, data_reg + 40), (unsigned long long)t4_read_reg64(adap, data_reg + 48), (unsigned long long)t4_read_reg64(adap, data_reg + 56)); t4_write_reg(adap, ctl_reg, F_MBMSGVALID | V_MBOWNER(X_MBOWNER_FW)); t4_read_reg(adap, ctl_reg); /* flush write */ delay_idx = 0; ms = delay[0]; /* * Loop waiting for the reply; bail out if we time out or the firmware * reports an error. */ pcie_fw = t4_read_reg(adap, A_PCIE_FW); for (i = 0; i < timeout && !(pcie_fw & F_PCIE_FW_ERR); i += ms) { if (sleep_ok) { ms = delay[delay_idx]; /* last element may repeat */ if (delay_idx < ARRAY_SIZE(delay) - 1) delay_idx++; msleep(ms); } else { msleep(ms); } pcie_fw = t4_read_reg(adap, A_PCIE_FW); v = t4_read_reg(adap, ctl_reg); if (v == X_CIM_PF_NOACCESS) continue; if (G_MBOWNER(v) == X_MBOWNER_PL) { if (!(v & F_MBMSGVALID)) { t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE)); continue; } CXGBE_DEBUG_MBOX(adap, "%s: mbox %u: %016llx %016llx %016llx %016llx " "%016llx %016llx %016llx %016llx\n", __func__, (mbox), (unsigned long long)t4_read_reg64(adap, data_reg), (unsigned long long)t4_read_reg64(adap, data_reg + 8), (unsigned long long)t4_read_reg64(adap, data_reg + 16), (unsigned long long)t4_read_reg64(adap, data_reg + 24), (unsigned long long)t4_read_reg64(adap, data_reg + 32), (unsigned long long)t4_read_reg64(adap, data_reg + 40), (unsigned long long)t4_read_reg64(adap, data_reg + 48), (unsigned long long)t4_read_reg64(adap, data_reg + 56)); CXGBE_DEBUG_MBOX(adap, "command %#x completed in %d ms (%ssleeping)\n", *(const u8 *)cmd, i + ms, sleep_ok ? "" : "non-"); res = t4_read_reg64(adap, data_reg); if (G_FW_CMD_OP(res >> 32) == FW_DEBUG_CMD) { fw_asrt(adap, data_reg); res = V_FW_CMD_RETVAL(EIO); } else if (rpl) { get_mbox_rpl(adap, rpl, size / 8, data_reg); } t4_write_reg(adap, ctl_reg, V_MBOWNER(X_MBOWNER_NONE)); T4_OS_MBOX_LOCKING( t4_os_atomic_list_del(&entry, &adap->mbox_list, &adap->mbox_lock)); return -G_FW_CMD_RETVAL((int)res); } } /* * We timed out waiting for a reply to our mailbox command. Report * the error and also check to see if the firmware reported any * errors ... */ dev_err(adap, "command %#x in mailbox %d timed out\n", *(const u8 *)cmd, mbox); T4_OS_MBOX_LOCKING(t4_os_atomic_list_del(&entry, &adap->mbox_list, &adap->mbox_lock)); t4_report_fw_error(adap); free(temp); return (pcie_fw & F_PCIE_FW_ERR) ? -ENXIO : -ETIMEDOUT; } int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, void *rpl, bool sleep_ok) { return t4_wr_mbox_meat_timeout(adap, mbox, cmd, size, rpl, sleep_ok, FW_CMD_MAX_TIMEOUT); } /** * t4_config_rss_range - configure a portion of the RSS mapping table * @adapter: the adapter * @mbox: mbox to use for the FW command * @viid: virtual interface whose RSS subtable is to be written * @start: start entry in the table to write * @n: how many table entries to write * @rspq: values for the "response queue" (Ingress Queue) lookup table * @nrspq: number of values in @rspq * * Programs the selected part of the VI's RSS mapping table with the * provided values. If @nrspq < @n the supplied values are used repeatedly * until the full table range is populated. * * The caller must ensure the values in @rspq are in the range allowed for * @viid. */ int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, int start, int n, const u16 *rspq, unsigned int nrspq) { int ret; const u16 *rsp = rspq; const u16 *rsp_end = rspq + nrspq; struct fw_rss_ind_tbl_cmd cmd; memset(&cmd, 0, sizeof(cmd)); cmd.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_IND_TBL_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | V_FW_RSS_IND_TBL_CMD_VIID(viid)); cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); /* * Each firmware RSS command can accommodate up to 32 RSS Ingress * Queue Identifiers. These Ingress Queue IDs are packed three to * a 32-bit word as 10-bit values with the upper remaining 2 bits * reserved. */ while (n > 0) { int nq = min(n, 32); int nq_packed = 0; __be32 *qp = &cmd.iq0_to_iq2; /* * Set up the firmware RSS command header to send the next * "nq" Ingress Queue IDs to the firmware. */ cmd.niqid = cpu_to_be16(nq); cmd.startidx = cpu_to_be16(start); /* * "nq" more done for the start of the next loop. */ start += nq; n -= nq; /* * While there are still Ingress Queue IDs to stuff into the * current firmware RSS command, retrieve them from the * Ingress Queue ID array and insert them into the command. */ while (nq > 0) { /* * Grab up to the next 3 Ingress Queue IDs (wrapping * around the Ingress Queue ID array if necessary) and * insert them into the firmware RSS command at the * current 3-tuple position within the commad. */ u16 qbuf[3]; u16 *qbp = qbuf; int nqbuf = min(3, nq); nq -= nqbuf; qbuf[0] = 0; qbuf[1] = 0; qbuf[2] = 0; while (nqbuf && nq_packed < 32) { nqbuf--; nq_packed++; *qbp++ = *rsp++; if (rsp >= rsp_end) rsp = rspq; } *qp++ = cpu_to_be32(V_FW_RSS_IND_TBL_CMD_IQ0(qbuf[0]) | V_FW_RSS_IND_TBL_CMD_IQ1(qbuf[1]) | V_FW_RSS_IND_TBL_CMD_IQ2(qbuf[2])); } /* * Send this portion of the RRS table update to the firmware; * bail out on any errors. */ ret = t4_wr_mbox(adapter, mbox, &cmd, sizeof(cmd), NULL); if (ret) return ret; } return 0; } /** * t4_config_vi_rss - configure per VI RSS settings * @adapter: the adapter * @mbox: mbox to use for the FW command * @viid: the VI id * @flags: RSS flags * @defq: id of the default RSS queue for the VI. * * Configures VI-specific RSS properties. */ int t4_config_vi_rss(struct adapter *adapter, int mbox, unsigned int viid, unsigned int flags, unsigned int defq) { struct fw_rss_vi_config_cmd c; memset(&c, 0, sizeof(c)); c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | V_FW_RSS_VI_CONFIG_CMD_VIID(viid)); c.retval_len16 = cpu_to_be32(FW_LEN16(c)); c.u.basicvirtual.defaultq_to_udpen = cpu_to_be32(flags | V_FW_RSS_VI_CONFIG_CMD_DEFAULTQ(defq)); return t4_wr_mbox(adapter, mbox, &c, sizeof(c), NULL); } /** * init_cong_ctrl - initialize congestion control parameters * @a: the alpha values for congestion control * @b: the beta values for congestion control * * Initialize the congestion control parameters. */ static void init_cong_ctrl(unsigned short *a, unsigned short *b) { int i; for (i = 0; i < 9; i++) { a[i] = 1; b[i] = 0; } a[9] = 2; a[10] = 3; a[11] = 4; a[12] = 5; a[13] = 6; a[14] = 7; a[15] = 8; a[16] = 9; a[17] = 10; a[18] = 14; a[19] = 17; a[20] = 21; a[21] = 25; a[22] = 30; a[23] = 35; a[24] = 45; a[25] = 60; a[26] = 80; a[27] = 100; a[28] = 200; a[29] = 300; a[30] = 400; a[31] = 500; b[9] = 1; b[10] = 1; b[11] = 2; b[12] = 2; b[13] = 3; b[14] = 3; b[15] = 3; b[16] = 3; b[17] = 4; b[18] = 4; b[19] = 4; b[20] = 4; b[21] = 4; b[22] = 5; b[23] = 5; b[24] = 5; b[25] = 5; b[26] = 5; b[27] = 5; b[28] = 6; b[29] = 6; b[30] = 7; b[31] = 7; } #define INIT_CMD(var, cmd, rd_wr) do { \ (var).op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_##cmd##_CMD) | \ F_FW_CMD_REQUEST | F_FW_CMD_##rd_wr); \ (var).retval_len16 = cpu_to_be32(FW_LEN16(var)); \ } while (0) int t4_get_core_clock(struct adapter *adapter, struct vpd_params *p) { u32 cclk_param, cclk_val; int ret; /* * Ask firmware for the Core Clock since it knows how to translate the * Reference Clock ('V2') VPD field into a Core Clock value ... */ cclk_param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK)); ret = t4_query_params(adapter, adapter->mbox, adapter->pf, 0, 1, &cclk_param, &cclk_val); if (ret) { dev_err(adapter, "%s: error in fetching from coreclock - %d\n", __func__, ret); return ret; } p->cclk = cclk_val; dev_debug(adapter, "%s: p->cclk = %u\n", __func__, p->cclk); return 0; } /* serial flash and firmware constants and flash config file constants */ enum { SF_ATTEMPTS = 10, /* max retries for SF operations */ /* flash command opcodes */ SF_PROG_PAGE = 2, /* program page */ SF_WR_DISABLE = 4, /* disable writes */ SF_RD_STATUS = 5, /* read status register */ SF_WR_ENABLE = 6, /* enable writes */ SF_RD_DATA_FAST = 0xb, /* read flash */ SF_RD_ID = 0x9f, /* read ID */ SF_ERASE_SECTOR = 0xd8, /* erase sector */ }; /** * sf1_read - read data from the serial flash * @adapter: the adapter * @byte_cnt: number of bytes to read * @cont: whether another operation will be chained * @lock: whether to lock SF for PL access only * @valp: where to store the read data * * Reads up to 4 bytes of data from the serial flash. The location of * the read needs to be specified prior to calling this by issuing the * appropriate commands to the serial flash. */ static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont, int lock, u32 *valp) { int ret; if (!byte_cnt || byte_cnt > 4) return -EINVAL; if (t4_read_reg(adapter, A_SF_OP) & F_BUSY) return -EBUSY; t4_write_reg(adapter, A_SF_OP, V_SF_LOCK(lock) | V_CONT(cont) | V_BYTECNT(byte_cnt - 1)); ret = t4_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 5); if (!ret) *valp = t4_read_reg(adapter, A_SF_DATA); return ret; } /** * sf1_write - write data to the serial flash * @adapter: the adapter * @byte_cnt: number of bytes to write * @cont: whether another operation will be chained * @lock: whether to lock SF for PL access only * @val: value to write * * Writes up to 4 bytes of data to the serial flash. The location of * the write needs to be specified prior to calling this by issuing the * appropriate commands to the serial flash. */ static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont, int lock, u32 val) { if (!byte_cnt || byte_cnt > 4) return -EINVAL; if (t4_read_reg(adapter, A_SF_OP) & F_BUSY) return -EBUSY; t4_write_reg(adapter, A_SF_DATA, val); t4_write_reg(adapter, A_SF_OP, V_SF_LOCK(lock) | V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1)); return t4_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 5); } /** * t4_read_flash - read words from serial flash * @adapter: the adapter * @addr: the start address for the read * @nwords: how many 32-bit words to read * @data: where to store the read data * @byte_oriented: whether to store data as bytes or as words * * Read the specified number of 32-bit words from the serial flash. * If @byte_oriented is set the read data is stored as a byte array * (i.e., big-endian), otherwise as 32-bit words in the platform's * natural endianness. */ int t4_read_flash(struct adapter *adapter, unsigned int addr, unsigned int nwords, u32 *data, int byte_oriented) { int ret; if (((addr + nwords * sizeof(u32)) > adapter->params.sf_size) || (addr & 3)) return -EINVAL; addr = rte_constant_bswap32(addr) | SF_RD_DATA_FAST; ret = sf1_write(adapter, 4, 1, 0, addr); if (ret != 0) return ret; ret = sf1_read(adapter, 1, 1, 0, data); if (ret != 0) return ret; for ( ; nwords; nwords--, data++) { ret = sf1_read(adapter, 4, nwords > 1, nwords == 1, data); if (nwords == 1) t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */ if (ret) return ret; if (byte_oriented) *data = cpu_to_be32(*data); } return 0; } /** * t4_get_fw_version - read the firmware version * @adapter: the adapter * @vers: where to place the version * * Reads the FW version from flash. */ int t4_get_fw_version(struct adapter *adapter, u32 *vers) { return t4_read_flash(adapter, FLASH_FW_START + offsetof(struct fw_hdr, fw_ver), 1, vers, 0); } /** * t4_get_tp_version - read the TP microcode version * @adapter: the adapter * @vers: where to place the version * * Reads the TP microcode version from flash. */ int t4_get_tp_version(struct adapter *adapter, u32 *vers) { return t4_read_flash(adapter, FLASH_FW_START + offsetof(struct fw_hdr, tp_microcode_ver), 1, vers, 0); } #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \ FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG) /** * t4_link_l1cfg - apply link configuration to MAC/PHY * @phy: the PHY to setup * @mac: the MAC to setup * @lc: the requested link configuration * * Set up a port's MAC and PHY according to a desired link configuration. * - If the PHY can auto-negotiate first decide what to advertise, then * enable/disable auto-negotiation as desired, and reset. * - If the PHY does not auto-negotiate just reset it. * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC, * otherwise do it later based on the outcome of auto-negotiation. */ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, struct link_config *lc) { struct fw_port_cmd c; unsigned int fc = 0, mdi = V_FW_PORT_CAP_MDI(FW_PORT_CAP_MDI_AUTO); lc->link_ok = 0; if (lc->requested_fc & PAUSE_RX) fc |= FW_PORT_CAP_FC_RX; if (lc->requested_fc & PAUSE_TX) fc |= FW_PORT_CAP_FC_TX; memset(&c, 0, sizeof(c)); c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_PORT_CMD_PORTID(port)); c.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | FW_LEN16(c)); if (!(lc->supported & FW_PORT_CAP_ANEG)) { c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) | fc); lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); } else if (lc->autoneg == AUTONEG_DISABLE) { c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi); lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); } else { c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi); } return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_flash_cfg_addr - return the address of the flash configuration file * @adapter: the adapter * * Return the address within the flash where the Firmware Configuration * File is stored, or an error if the device FLASH is too small to contain * a Firmware Configuration File. */ int t4_flash_cfg_addr(struct adapter *adapter) { /* * If the device FLASH isn't large enough to hold a Firmware * Configuration File, return an error. */ if (adapter->params.sf_size < FLASH_CFG_START + FLASH_CFG_MAX_SIZE) return -ENOSPC; return FLASH_CFG_START; } #define PF_INTR_MASK (F_PFSW | F_PFCIM) /** * t4_intr_enable - enable interrupts * @adapter: the adapter whose interrupts should be enabled * * Enable PF-specific interrupts for the calling function and the top-level * interrupt concentrator for global interrupts. Interrupts are already * enabled at each module, here we just enable the roots of the interrupt * hierarchies. * * Note: this function should be called only when the driver manages * non PF-specific interrupts from the various HW modules. Only one PCI * function at a time should be doing this. */ void t4_intr_enable(struct adapter *adapter) { u32 val = 0; u32 pf = G_SOURCEPF(t4_read_reg(adapter, A_PL_WHOAMI)); if (CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5) val = F_ERR_DROPPED_DB | F_ERR_EGR_CTXT_PRIO | F_DBFIFO_HP_INT; t4_write_reg(adapter, A_SGE_INT_ENABLE3, F_ERR_CPL_EXCEED_IQE_SIZE | F_ERR_INVALID_CIDX_INC | F_ERR_CPL_OPCODE_0 | F_ERR_DATA_CPL_ON_HIGH_QID1 | F_INGRESS_SIZE_ERR | F_ERR_DATA_CPL_ON_HIGH_QID0 | F_ERR_BAD_DB_PIDX3 | F_ERR_BAD_DB_PIDX2 | F_ERR_BAD_DB_PIDX1 | F_ERR_BAD_DB_PIDX0 | F_ERR_ING_CTXT_PRIO | F_DBFIFO_LP_INT | F_EGRESS_SIZE_ERR | val); t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), PF_INTR_MASK); t4_set_reg_field(adapter, A_PL_INT_MAP0, 0, 1 << pf); } /** * t4_intr_disable - disable interrupts * @adapter: the adapter whose interrupts should be disabled * * Disable interrupts. We only disable the top-level interrupt * concentrators. The caller must be a PCI function managing global * interrupts. */ void t4_intr_disable(struct adapter *adapter) { u32 pf = G_SOURCEPF(t4_read_reg(adapter, A_PL_WHOAMI)); t4_write_reg(adapter, MYPF_REG(A_PL_PF_INT_ENABLE), 0); t4_set_reg_field(adapter, A_PL_INT_MAP0, 1 << pf, 0); } /** * t4_get_port_type_description - return Port Type string description * @port_type: firmware Port Type enumeration */ const char *t4_get_port_type_description(enum fw_port_type port_type) { static const char * const port_type_description[] = { "Fiber_XFI", "Fiber_XAUI", "BT_SGMII", "BT_XFI", "BT_XAUI", "KX4", "CX4", "KX", "KR", "SFP", "BP_AP", "BP4_AP", "QSFP_10G", "QSA", "QSFP", "BP40_BA", }; if (port_type < ARRAY_SIZE(port_type_description)) return port_type_description[port_type]; return "UNKNOWN"; } /** * t4_get_mps_bg_map - return the buffer groups associated with a port * @adap: the adapter * @idx: the port index * * Returns a bitmap indicating which MPS buffer groups are associated * with the given port. Bit i is set if buffer group i is used by the * port. */ unsigned int t4_get_mps_bg_map(struct adapter *adap, int idx) { u32 n = G_NUMPORTS(t4_read_reg(adap, A_MPS_CMN_CTL)); if (n == 0) return idx == 0 ? 0xf : 0; if (n == 1) return idx < 2 ? (3 << (2 * idx)) : 0; return 1 << idx; } /** * t4_get_port_stats - collect port statistics * @adap: the adapter * @idx: the port index * @p: the stats structure to fill * * Collect statistics related to the given port from HW. */ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p) { u32 bgmap = t4_get_mps_bg_map(adap, idx); #define GET_STAT(name) \ t4_read_reg64(adap, \ (is_t4(adap->params.chip) ? \ PORT_REG(idx, A_MPS_PORT_STAT_##name##_L) :\ T5_PORT_REG(idx, A_MPS_PORT_STAT_##name##_L))) #define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L) p->tx_octets = GET_STAT(TX_PORT_BYTES); p->tx_frames = GET_STAT(TX_PORT_FRAMES); p->tx_bcast_frames = GET_STAT(TX_PORT_BCAST); p->tx_mcast_frames = GET_STAT(TX_PORT_MCAST); p->tx_ucast_frames = GET_STAT(TX_PORT_UCAST); p->tx_error_frames = GET_STAT(TX_PORT_ERROR); p->tx_frames_64 = GET_STAT(TX_PORT_64B); p->tx_frames_65_127 = GET_STAT(TX_PORT_65B_127B); p->tx_frames_128_255 = GET_STAT(TX_PORT_128B_255B); p->tx_frames_256_511 = GET_STAT(TX_PORT_256B_511B); p->tx_frames_512_1023 = GET_STAT(TX_PORT_512B_1023B); p->tx_frames_1024_1518 = GET_STAT(TX_PORT_1024B_1518B); p->tx_frames_1519_max = GET_STAT(TX_PORT_1519B_MAX); p->tx_drop = GET_STAT(TX_PORT_DROP); p->tx_pause = GET_STAT(TX_PORT_PAUSE); p->tx_ppp0 = GET_STAT(TX_PORT_PPP0); p->tx_ppp1 = GET_STAT(TX_PORT_PPP1); p->tx_ppp2 = GET_STAT(TX_PORT_PPP2); p->tx_ppp3 = GET_STAT(TX_PORT_PPP3); p->tx_ppp4 = GET_STAT(TX_PORT_PPP4); p->tx_ppp5 = GET_STAT(TX_PORT_PPP5); p->tx_ppp6 = GET_STAT(TX_PORT_PPP6); p->tx_ppp7 = GET_STAT(TX_PORT_PPP7); p->rx_octets = GET_STAT(RX_PORT_BYTES); p->rx_frames = GET_STAT(RX_PORT_FRAMES); p->rx_bcast_frames = GET_STAT(RX_PORT_BCAST); p->rx_mcast_frames = GET_STAT(RX_PORT_MCAST); p->rx_ucast_frames = GET_STAT(RX_PORT_UCAST); p->rx_too_long = GET_STAT(RX_PORT_MTU_ERROR); p->rx_jabber = GET_STAT(RX_PORT_MTU_CRC_ERROR); p->rx_fcs_err = GET_STAT(RX_PORT_CRC_ERROR); p->rx_len_err = GET_STAT(RX_PORT_LEN_ERROR); p->rx_symbol_err = GET_STAT(RX_PORT_SYM_ERROR); p->rx_runt = GET_STAT(RX_PORT_LESS_64B); p->rx_frames_64 = GET_STAT(RX_PORT_64B); p->rx_frames_65_127 = GET_STAT(RX_PORT_65B_127B); p->rx_frames_128_255 = GET_STAT(RX_PORT_128B_255B); p->rx_frames_256_511 = GET_STAT(RX_PORT_256B_511B); p->rx_frames_512_1023 = GET_STAT(RX_PORT_512B_1023B); p->rx_frames_1024_1518 = GET_STAT(RX_PORT_1024B_1518B); p->rx_frames_1519_max = GET_STAT(RX_PORT_1519B_MAX); p->rx_pause = GET_STAT(RX_PORT_PAUSE); p->rx_ppp0 = GET_STAT(RX_PORT_PPP0); p->rx_ppp1 = GET_STAT(RX_PORT_PPP1); p->rx_ppp2 = GET_STAT(RX_PORT_PPP2); p->rx_ppp3 = GET_STAT(RX_PORT_PPP3); p->rx_ppp4 = GET_STAT(RX_PORT_PPP4); p->rx_ppp5 = GET_STAT(RX_PORT_PPP5); p->rx_ppp6 = GET_STAT(RX_PORT_PPP6); p->rx_ppp7 = GET_STAT(RX_PORT_PPP7); p->rx_ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_DROP_FRAME) : 0; p->rx_ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_DROP_FRAME) : 0; p->rx_ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_DROP_FRAME) : 0; p->rx_ovflow3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_DROP_FRAME) : 0; p->rx_trunc0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_TRUNC_FRAME) : 0; p->rx_trunc1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_TRUNC_FRAME) : 0; p->rx_trunc2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_TRUNC_FRAME) : 0; p->rx_trunc3 = (bgmap & 8) ? GET_STAT_COM(RX_BG_3_MAC_TRUNC_FRAME) : 0; #undef GET_STAT #undef GET_STAT_COM } /** * t4_get_port_stats_offset - collect port stats relative to a previous snapshot * @adap: The adapter * @idx: The port * @stats: Current stats to fill * @offset: Previous stats snapshot */ void t4_get_port_stats_offset(struct adapter *adap, int idx, struct port_stats *stats, struct port_stats *offset) { u64 *s, *o; unsigned int i; t4_get_port_stats(adap, idx, stats); for (i = 0, s = (u64 *)stats, o = (u64 *)offset; i < (sizeof(struct port_stats) / sizeof(u64)); i++, s++, o++) *s -= *o; } /** * t4_clr_port_stats - clear port statistics * @adap: the adapter * @idx: the port index * * Clear HW statistics for the given port. */ void t4_clr_port_stats(struct adapter *adap, int idx) { unsigned int i; u32 bgmap = t4_get_mps_bg_map(adap, idx); u32 port_base_addr; if (is_t4(adap->params.chip)) port_base_addr = PORT_BASE(idx); else port_base_addr = T5_PORT_BASE(idx); for (i = A_MPS_PORT_STAT_TX_PORT_BYTES_L; i <= A_MPS_PORT_STAT_TX_PORT_PPP7_H; i += 8) t4_write_reg(adap, port_base_addr + i, 0); for (i = A_MPS_PORT_STAT_RX_PORT_BYTES_L; i <= A_MPS_PORT_STAT_RX_PORT_LESS_64B_H; i += 8) t4_write_reg(adap, port_base_addr + i, 0); for (i = 0; i < 4; i++) if (bgmap & (1 << i)) { t4_write_reg(adap, A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + i * 8, 0); t4_write_reg(adap, A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + i * 8, 0); } } /** * t4_fw_hello - establish communication with FW * @adap: the adapter * @mbox: mailbox to use for the FW command * @evt_mbox: mailbox to receive async FW events * @master: specifies the caller's willingness to be the device master * @state: returns the current device state (if non-NULL) * * Issues a command to establish communication with FW. Returns either * an error (negative integer) or the mailbox of the Master PF. */ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox, enum dev_master master, enum dev_state *state) { int ret; struct fw_hello_cmd c; u32 v; unsigned int master_mbox; int retries = FW_CMD_HELLO_RETRIES; retry: memset(&c, 0, sizeof(c)); INIT_CMD(c, HELLO, WRITE); c.err_to_clearinit = cpu_to_be32( V_FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) | V_FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) | V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox : M_FW_HELLO_CMD_MBMASTER) | V_FW_HELLO_CMD_MBASYNCNOT(evt_mbox) | V_FW_HELLO_CMD_STAGE(FW_HELLO_CMD_STAGE_OS) | F_FW_HELLO_CMD_CLEARINIT); /* * Issue the HELLO command to the firmware. If it's not successful * but indicates that we got a "busy" or "timeout" condition, retry * the HELLO until we exhaust our retry limit. If we do exceed our * retry limit, check to see if the firmware left us any error * information and report that if so ... */ ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret != FW_SUCCESS) { if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) goto retry; if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR) t4_report_fw_error(adap); return ret; } v = be32_to_cpu(c.err_to_clearinit); master_mbox = G_FW_HELLO_CMD_MBMASTER(v); if (state) { if (v & F_FW_HELLO_CMD_ERR) *state = DEV_STATE_ERR; else if (v & F_FW_HELLO_CMD_INIT) *state = DEV_STATE_INIT; else *state = DEV_STATE_UNINIT; } /* * If we're not the Master PF then we need to wait around for the * Master PF Driver to finish setting up the adapter. * * Note that we also do this wait if we're a non-Master-capable PF and * there is no current Master PF; a Master PF may show up momentarily * and we wouldn't want to fail pointlessly. (This can happen when an * OS loads lots of different drivers rapidly at the same time). In * this case, the Master PF returned by the firmware will be * M_PCIE_FW_MASTER so the test below will work ... */ if ((v & (F_FW_HELLO_CMD_ERR | F_FW_HELLO_CMD_INIT)) == 0 && master_mbox != mbox) { int waiting = FW_CMD_HELLO_TIMEOUT; /* * Wait for the firmware to either indicate an error or * initialized state. If we see either of these we bail out * and report the issue to the caller. If we exhaust the * "hello timeout" and we haven't exhausted our retries, try * again. Otherwise bail with a timeout error. */ for (;;) { u32 pcie_fw; msleep(50); waiting -= 50; /* * If neither Error nor Initialialized are indicated * by the firmware keep waiting till we exaust our * timeout ... and then retry if we haven't exhausted * our retries ... */ pcie_fw = t4_read_reg(adap, A_PCIE_FW); if (!(pcie_fw & (F_PCIE_FW_ERR | F_PCIE_FW_INIT))) { if (waiting <= 0) { if (retries-- > 0) goto retry; return -ETIMEDOUT; } continue; } /* * We either have an Error or Initialized condition * report errors preferentially. */ if (state) { if (pcie_fw & F_PCIE_FW_ERR) *state = DEV_STATE_ERR; else if (pcie_fw & F_PCIE_FW_INIT) *state = DEV_STATE_INIT; } /* * If we arrived before a Master PF was selected and * there's not a valid Master PF, grab its identity * for our caller. */ if (master_mbox == M_PCIE_FW_MASTER && (pcie_fw & F_PCIE_FW_MASTER_VLD)) master_mbox = G_PCIE_FW_MASTER(pcie_fw); break; } } return master_mbox; } /** * t4_fw_bye - end communication with FW * @adap: the adapter * @mbox: mailbox to use for the FW command * * Issues a command to terminate communication with FW. */ int t4_fw_bye(struct adapter *adap, unsigned int mbox) { struct fw_bye_cmd c; memset(&c, 0, sizeof(c)); INIT_CMD(c, BYE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_fw_reset - issue a reset to FW * @adap: the adapter * @mbox: mailbox to use for the FW command * @reset: specifies the type of reset to perform * * Issues a reset command of the specified type to FW. */ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) { struct fw_reset_cmd c; memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = cpu_to_be32(reset); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_fw_halt - issue a reset/halt to FW and put uP into RESET * @adap: the adapter * @mbox: mailbox to use for the FW RESET command (if desired) * @force: force uP into RESET even if FW RESET command fails * * Issues a RESET command to firmware (if desired) with a HALT indication * and then puts the microprocessor into RESET state. The RESET command * will only be issued if a legitimate mailbox is provided (mbox <= * M_PCIE_FW_MASTER). * * This is generally used in order for the host to safely manipulate the * adapter without fear of conflicting with whatever the firmware might * be doing. The only way out of this state is to RESTART the firmware * ... */ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force) { int ret = 0; /* * If a legitimate mailbox is provided, issue a RESET command * with a HALT indication. */ if (mbox <= M_PCIE_FW_MASTER) { struct fw_reset_cmd c; memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = cpu_to_be32(F_PIORST | F_PIORSTMODE); c.halt_pkd = cpu_to_be32(F_FW_RESET_CMD_HALT); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /* * Normally we won't complete the operation if the firmware RESET * command fails but if our caller insists we'll go ahead and put the * uP into RESET. This can be useful if the firmware is hung or even * missing ... We'll have to take the risk of putting the uP into * RESET without the cooperation of firmware in that case. * * We also force the firmware's HALT flag to be on in case we bypassed * the firmware RESET command above or we're dealing with old firmware * which doesn't have the HALT capability. This will serve as a flag * for the incoming firmware to know that it's coming out of a HALT * rather than a RESET ... if it's new enough to understand that ... */ if (ret == 0 || force) { t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST); t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, F_PCIE_FW_HALT); } /* * And we always return the result of the firmware RESET command * even when we force the uP into RESET ... */ return ret; } /** * t4_fw_restart - restart the firmware by taking the uP out of RESET * @adap: the adapter * @mbox: mailbox to use for the FW RESET command (if desired) * @reset: if we want to do a RESET to restart things * * Restart firmware previously halted by t4_fw_halt(). On successful * return the previous PF Master remains as the new PF Master and there * is no need to issue a new HELLO command, etc. * * We do this in two ways: * * 1. If we're dealing with newer firmware we'll simply want to take * the chip's microprocessor out of RESET. This will cause the * firmware to start up from its start vector. And then we'll loop * until the firmware indicates it's started again (PCIE_FW.HALT * reset to 0) or we timeout. * * 2. If we're dealing with older firmware then we'll need to RESET * the chip since older firmware won't recognize the PCIE_FW.HALT * flag and automatically RESET itself on startup. */ int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset) { if (reset) { /* * Since we're directing the RESET instead of the firmware * doing it automatically, we need to clear the PCIE_FW.HALT * bit. */ t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, 0); /* * If we've been given a valid mailbox, first try to get the * firmware to do the RESET. If that works, great and we can * return success. Otherwise, if we haven't been given a * valid mailbox or the RESET command failed, fall back to * hitting the chip with a hammer. */ if (mbox <= M_PCIE_FW_MASTER) { t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0); msleep(100); if (t4_fw_reset(adap, mbox, F_PIORST | F_PIORSTMODE) == 0) return 0; } t4_write_reg(adap, A_PL_RST, F_PIORST | F_PIORSTMODE); msleep(2000); } else { int ms; t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, 0); for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) { if (!(t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_HALT)) return FW_SUCCESS; msleep(100); ms += 100; } return -ETIMEDOUT; } return 0; } /** * t4_fixup_host_params_compat - fix up host-dependent parameters * @adap: the adapter * @page_size: the host's Base Page Size * @cache_line_size: the host's Cache Line Size * @chip_compat: maintain compatibility with designated chip * * Various registers in the chip contain values which are dependent on the * host's Base Page and Cache Line Sizes. This function will fix all of * those registers with the appropriate values as passed in ... * * @chip_compat is used to limit the set of changes that are made * to be compatible with the indicated chip release. This is used by * drivers to maintain compatibility with chip register settings when * the drivers haven't [yet] been updated with new chip support. */ int t4_fixup_host_params_compat(struct adapter *adap, unsigned int page_size, unsigned int cache_line_size, enum chip_type chip_compat) { unsigned int page_shift = cxgbe_fls(page_size) - 1; unsigned int sge_hps = page_shift - 10; unsigned int stat_len = cache_line_size > 64 ? 128 : 64; unsigned int fl_align = cache_line_size < 32 ? 32 : cache_line_size; unsigned int fl_align_log = cxgbe_fls(fl_align) - 1; t4_write_reg(adap, A_SGE_HOST_PAGE_SIZE, V_HOSTPAGESIZEPF0(sge_hps) | V_HOSTPAGESIZEPF1(sge_hps) | V_HOSTPAGESIZEPF2(sge_hps) | V_HOSTPAGESIZEPF3(sge_hps) | V_HOSTPAGESIZEPF4(sge_hps) | V_HOSTPAGESIZEPF5(sge_hps) | V_HOSTPAGESIZEPF6(sge_hps) | V_HOSTPAGESIZEPF7(sge_hps)); if (is_t4(adap->params.chip) || is_t4(chip_compat)) t4_set_reg_field(adap, A_SGE_CONTROL, V_INGPADBOUNDARY(M_INGPADBOUNDARY) | F_EGRSTATUSPAGESIZE, V_INGPADBOUNDARY(fl_align_log - X_INGPADBOUNDARY_SHIFT) | V_EGRSTATUSPAGESIZE(stat_len != 64)); else { /* * T5 introduced the separation of the Free List Padding and * Packing Boundaries. Thus, we can select a smaller Padding * Boundary to avoid uselessly chewing up PCIe Link and Memory * Bandwidth, and use a Packing Boundary which is large enough * to avoid false sharing between CPUs, etc. * * For the PCI Link, the smaller the Padding Boundary the * better. For the Memory Controller, a smaller Padding * Boundary is better until we cross under the Memory Line * Size (the minimum unit of transfer to/from Memory). If we * have a Padding Boundary which is smaller than the Memory * Line Size, that'll involve a Read-Modify-Write cycle on the * Memory Controller which is never good. For T5 the smallest * Padding Boundary which we can select is 32 bytes which is * larger than any known Memory Controller Line Size so we'll * use that. */ /* * N.B. T5 has a different interpretation of the "0" value for * the Packing Boundary. This corresponds to 16 bytes instead * of the expected 32 bytes. We never have a Packing Boundary * less than 32 bytes so we can't use that special value but * on the other hand, if we wanted 32 bytes, the best we can * really do is 64 bytes ... */ if (fl_align <= 32) { fl_align = 64; fl_align_log = 6; } t4_set_reg_field(adap, A_SGE_CONTROL, V_INGPADBOUNDARY(M_INGPADBOUNDARY) | F_EGRSTATUSPAGESIZE, V_INGPADBOUNDARY(X_INGPCIEBOUNDARY_32B) | V_EGRSTATUSPAGESIZE(stat_len != 64)); t4_set_reg_field(adap, A_SGE_CONTROL2, V_INGPACKBOUNDARY(M_INGPACKBOUNDARY), V_INGPACKBOUNDARY(fl_align_log - X_INGPACKBOUNDARY_SHIFT)); } /* * Adjust various SGE Free List Host Buffer Sizes. * * The first four entries are: * * 0: Host Page Size * 1: 64KB * 2: Buffer size corresponding to 1500 byte MTU (unpacked mode) * 3: Buffer size corresponding to 9000 byte MTU (unpacked mode) * * For the single-MTU buffers in unpacked mode we need to include * space for the SGE Control Packet Shift, 14 byte Ethernet header, * possible 4 byte VLAN tag, all rounded up to the next Ingress Packet * Padding boundary. All of these are accommodated in the Factory * Default Firmware Configuration File but we need to adjust it for * this host's cache line size. */ t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE0, page_size); t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE2, (t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE2) + fl_align - 1) & ~(fl_align - 1)); t4_write_reg(adap, A_SGE_FL_BUFFER_SIZE3, (t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE3) + fl_align - 1) & ~(fl_align - 1)); t4_write_reg(adap, A_ULP_RX_TDDP_PSZ, V_HPZ0(page_shift - 12)); return 0; } /** * t4_fixup_host_params - fix up host-dependent parameters (T4 compatible) * @adap: the adapter * @page_size: the host's Base Page Size * @cache_line_size: the host's Cache Line Size * * Various registers in T4 contain values which are dependent on the * host's Base Page and Cache Line Sizes. This function will fix all of * those registers with the appropriate values as passed in ... * * This routine makes changes which are compatible with T4 chips. */ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, unsigned int cache_line_size) { return t4_fixup_host_params_compat(adap, page_size, cache_line_size, T4_LAST_REV); } /** * t4_fw_initialize - ask FW to initialize the device * @adap: the adapter * @mbox: mailbox to use for the FW command * * Issues a command to FW to partially initialize the device. This * performs initialization that generally doesn't depend on user input. */ int t4_fw_initialize(struct adapter *adap, unsigned int mbox) { struct fw_initialize_cmd c; memset(&c, 0, sizeof(c)); INIT_CMD(c, INITIALIZE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_query_params_rw - query FW or device parameters * @adap: the adapter * @mbox: mailbox to use for the FW command * @pf: the PF * @vf: the VF * @nparams: the number of parameters * @params: the parameter names * @val: the parameter values * @rw: Write and read flag * * Reads the value of FW or device parameters. Up to 7 parameters can be * queried at once. */ static int t4_query_params_rw(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, u32 *val, int rw) { unsigned int i; int ret; struct fw_params_cmd c; __be32 *p = &c.param[0].mnem; if (nparams > 7) return -EINVAL; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ | V_FW_PARAMS_CMD_PFN(pf) | V_FW_PARAMS_CMD_VFN(vf)); c.retval_len16 = cpu_to_be32(FW_LEN16(c)); for (i = 0; i < nparams; i++) { *p++ = cpu_to_be32(*params++); if (rw) *p = cpu_to_be32(*(val + i)); p++; } ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret == 0) for (i = 0, p = &c.param[0].val; i < nparams; i++, p += 2) *val++ = be32_to_cpu(*p); return ret; } int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, u32 *val) { return t4_query_params_rw(adap, mbox, pf, vf, nparams, params, val, 0); } /** * t4_set_params_timeout - sets FW or device parameters * @adap: the adapter * @mbox: mailbox to use for the FW command * @pf: the PF * @vf: the VF * @nparams: the number of parameters * @params: the parameter names * @val: the parameter values * @timeout: the timeout time * * Sets the value of FW or device parameters. Up to 7 parameters can be * specified at once. */ int t4_set_params_timeout(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, const u32 *val, int timeout) { struct fw_params_cmd c; __be32 *p = &c.param[0].mnem; if (nparams > 7) return -EINVAL; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PARAMS_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | V_FW_PARAMS_CMD_PFN(pf) | V_FW_PARAMS_CMD_VFN(vf)); c.retval_len16 = cpu_to_be32(FW_LEN16(c)); while (nparams--) { *p++ = cpu_to_be32(*params++); *p++ = cpu_to_be32(*val++); } return t4_wr_mbox_timeout(adap, mbox, &c, sizeof(c), NULL, timeout); } int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, const u32 *val) { return t4_set_params_timeout(adap, mbox, pf, vf, nparams, params, val, FW_CMD_MAX_TIMEOUT); } /** * t4_alloc_vi_func - allocate a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @port: physical port associated with the VI * @pf: the PF owning the VI * @vf: the VF owning the VI * @nmac: number of MAC addresses needed (1 to 5) * @mac: the MAC addresses of the VI * @rss_size: size of RSS table slice associated with this VI * @portfunc: which Port Application Function MAC Address is desired * @idstype: Intrusion Detection Type * * Allocates a virtual interface for the given physical port. If @mac is * not %NULL it contains the MAC addresses of the VI as assigned by FW. * @mac should be large enough to hold @nmac Ethernet addresses, they are * stored consecutively so the space needed is @nmac * 6 bytes. * Returns a negative error number or the non-negative VI id. */ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox, unsigned int port, unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, unsigned int *rss_size, unsigned int portfunc, unsigned int idstype) { int ret; struct fw_vi_cmd c; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf)); c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_ALLOC | FW_LEN16(c)); c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_TYPE(idstype) | V_FW_VI_CMD_FUNC(portfunc)); c.portid_pkd = V_FW_VI_CMD_PORTID(port); c.nmac = nmac - 1; ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret) return ret; if (mac) { memcpy(mac, c.mac, sizeof(c.mac)); switch (nmac) { case 5: memcpy(mac + 24, c.nmac3, sizeof(c.nmac3)); /* FALLTHROUGH */ case 4: memcpy(mac + 18, c.nmac2, sizeof(c.nmac2)); /* FALLTHROUGH */ case 3: memcpy(mac + 12, c.nmac1, sizeof(c.nmac1)); /* FALLTHROUGH */ case 2: memcpy(mac + 6, c.nmac0, sizeof(c.nmac0)); /* FALLTHROUGH */ } } if (rss_size) *rss_size = G_FW_VI_CMD_RSSSIZE(be16_to_cpu(c.norss_rsssize)); return G_FW_VI_CMD_VIID(cpu_to_be16(c.type_to_viid)); } /** * t4_alloc_vi - allocate an [Ethernet Function] virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @port: physical port associated with the VI * @pf: the PF owning the VI * @vf: the VF owning the VI * @nmac: number of MAC addresses needed (1 to 5) * @mac: the MAC addresses of the VI * @rss_size: size of RSS table slice associated with this VI * * Backwards compatible and convieniance routine to allocate a Virtual * Interface with a Ethernet Port Application Function and Intrustion * Detection System disabled. */ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, unsigned int *rss_size) { return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size, FW_VI_FUNC_ETH, 0); } /** * t4_free_vi - free a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @pf: the PF owning the VI * @vf: the VF owning the VI * @viid: virtual interface identifiler * * Free a previously allocated virtual interface. */ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int viid) { struct fw_vi_cmd c; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_VI_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_VI_CMD_PFN(pf) | V_FW_VI_CMD_VFN(vf)); c.alloc_to_len16 = cpu_to_be32(F_FW_VI_CMD_FREE | FW_LEN16(c)); c.type_to_viid = cpu_to_be16(V_FW_VI_CMD_VIID(viid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); } /** * t4_set_rxmode - set Rx properties of a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @viid: the VI id * @mtu: the new MTU or -1 * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change * @bcast: 1 to enable broadcast Rx, 0 to disable it, -1 no change * @vlanex: 1 to enable hardware VLAN Tag extraction, 0 to disable it, * -1 no change * @sleep_ok: if true we may sleep while awaiting command completion * * Sets Rx properties of a virtual interface. */ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, int mtu, int promisc, int all_multi, int bcast, int vlanex, bool sleep_ok) { struct fw_vi_rxmode_cmd c; /* convert to FW values */ if (mtu < 0) mtu = M_FW_VI_RXMODE_CMD_MTU; if (promisc < 0) promisc = M_FW_VI_RXMODE_CMD_PROMISCEN; if (all_multi < 0) all_multi = M_FW_VI_RXMODE_CMD_ALLMULTIEN; if (bcast < 0) bcast = M_FW_VI_RXMODE_CMD_BROADCASTEN; if (vlanex < 0) vlanex = M_FW_VI_RXMODE_CMD_VLANEXEN; memset(&c, 0, sizeof(c)); c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_RXMODE_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | V_FW_VI_RXMODE_CMD_VIID(viid)); c.retval_len16 = cpu_to_be32(FW_LEN16(c)); c.mtu_to_vlanexen = cpu_to_be32(V_FW_VI_RXMODE_CMD_MTU(mtu) | V_FW_VI_RXMODE_CMD_PROMISCEN(promisc) | V_FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) | V_FW_VI_RXMODE_CMD_BROADCASTEN(bcast) | V_FW_VI_RXMODE_CMD_VLANEXEN(vlanex)); return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); } /** * t4_change_mac - modifies the exact-match filter for a MAC address * @adap: the adapter * @mbox: mailbox to use for the FW command * @viid: the VI id * @idx: index of existing filter for old value of MAC address, or -1 * @addr: the new MAC address value * @persist: whether a new MAC allocation should be persistent * @add_smt: if true also add the address to the HW SMT * * Modifies an exact-match filter and sets it to the new MAC address if * @idx >= 0, or adds the MAC address to a new filter if @idx < 0. In the * latter case the address is added persistently if @persist is %true. * * Note that in general it is not possible to modify the value of a given * filter so the generic way to modify an address filter is to free the one * being used by the old address value and allocate a new filter for the * new address value. * * Returns a negative error number or the index of the filter with the new * MAC value. Note that this index may differ from @idx. */ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, int idx, const u8 *addr, bool persist, bool add_smt) { int ret, mode; struct fw_vi_mac_cmd c; struct fw_vi_mac_exact *p = c.u.exact; int max_mac_addr = adap->params.arch.mps_tcam_size; if (idx < 0) /* new allocation */ idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC; mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY; memset(&c, 0, sizeof(c)); c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(viid)); c.freemacs_to_len16 = cpu_to_be32(V_FW_CMD_LEN16(1)); p->valid_to_idx = cpu_to_be16(F_FW_VI_MAC_CMD_VALID | V_FW_VI_MAC_CMD_SMAC_RESULT(mode) | V_FW_VI_MAC_CMD_IDX(idx)); memcpy(p->macaddr, addr, sizeof(p->macaddr)); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret == 0) { ret = G_FW_VI_MAC_CMD_IDX(be16_to_cpu(p->valid_to_idx)); if (ret >= max_mac_addr) ret = -ENOMEM; } return ret; } /** * t4_enable_vi_params - enable/disable a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @viid: the VI id * @rx_en: 1=enable Rx, 0=disable Rx * @tx_en: 1=enable Tx, 0=disable Tx * @dcb_en: 1=enable delivery of Data Center Bridging messages. * * Enables/disables a virtual interface. Note that setting DCB Enable * only makes sense when enabling a Virtual Interface ... */ int t4_enable_vi_params(struct adapter *adap, unsigned int mbox, unsigned int viid, bool rx_en, bool tx_en, bool dcb_en) { struct fw_vi_enable_cmd c; memset(&c, 0, sizeof(c)); c.op_to_viid = cpu_to_be32(V_FW_CMD_OP(FW_VI_ENABLE_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_VI_ENABLE_CMD_VIID(viid)); c.ien_to_len16 = cpu_to_be32(V_FW_VI_ENABLE_CMD_IEN(rx_en) | V_FW_VI_ENABLE_CMD_EEN(tx_en) | V_FW_VI_ENABLE_CMD_DCB_INFO(dcb_en) | FW_LEN16(c)); return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL); } /** * t4_enable_vi - enable/disable a virtual interface * @adap: the adapter * @mbox: mailbox to use for the FW command * @viid: the VI id * @rx_en: 1=enable Rx, 0=disable Rx * @tx_en: 1=enable Tx, 0=disable Tx * * Enables/disables a virtual interface. Note that setting DCB Enable * only makes sense when enabling a Virtual Interface ... */ int t4_enable_vi(struct adapter *adap, unsigned int mbox, unsigned int viid, bool rx_en, bool tx_en) { return t4_enable_vi_params(adap, mbox, viid, rx_en, tx_en, 0); } /** * t4_iq_start_stop - enable/disable an ingress queue and its FLs * @adap: the adapter * @mbox: mailbox to use for the FW command * @start: %true to enable the queues, %false to disable them * @pf: the PF owning the queues * @vf: the VF owning the queues * @iqid: ingress queue id * @fl0id: FL0 queue id or 0xffff if no attached FL0 * @fl1id: FL1 queue id or 0xffff if no attached FL1 * * Starts or stops an ingress queue and its associated FLs, if any. */ int t4_iq_start_stop(struct adapter *adap, unsigned int mbox, bool start, unsigned int pf, unsigned int vf, unsigned int iqid, unsigned int fl0id, unsigned int fl1id) { struct fw_iq_cmd c; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) | V_FW_IQ_CMD_VFN(vf)); c.alloc_to_len16 = cpu_to_be32(V_FW_IQ_CMD_IQSTART(start) | V_FW_IQ_CMD_IQSTOP(!start) | FW_LEN16(c)); c.iqid = cpu_to_be16(iqid); c.fl0id = cpu_to_be16(fl0id); c.fl1id = cpu_to_be16(fl1id); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_iq_free - free an ingress queue and its FLs * @adap: the adapter * @mbox: mailbox to use for the FW command * @pf: the PF owning the queues * @vf: the VF owning the queues * @iqtype: the ingress queue type (FW_IQ_TYPE_FL_INT_CAP, etc.) * @iqid: ingress queue id * @fl0id: FL0 queue id or 0xffff if no attached FL0 * @fl1id: FL1 queue id or 0xffff if no attached FL1 * * Frees an ingress queue and its associated FLs, if any. */ int t4_iq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int iqtype, unsigned int iqid, unsigned int fl0id, unsigned int fl1id) { struct fw_iq_cmd c; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(pf) | V_FW_IQ_CMD_VFN(vf)); c.alloc_to_len16 = cpu_to_be32(F_FW_IQ_CMD_FREE | FW_LEN16(c)); c.type_to_iqandstindex = cpu_to_be32(V_FW_IQ_CMD_TYPE(iqtype)); c.iqid = cpu_to_be16(iqid); c.fl0id = cpu_to_be16(fl0id); c.fl1id = cpu_to_be16(fl1id); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_eth_eq_free - free an Ethernet egress queue * @adap: the adapter * @mbox: mailbox to use for the FW command * @pf: the PF owning the queue * @vf: the VF owning the queue * @eqid: egress queue id * * Frees an Ethernet egress queue. */ int t4_eth_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid) { struct fw_eq_eth_cmd c; memset(&c, 0, sizeof(c)); c.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_EQ_ETH_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_EXEC | V_FW_EQ_ETH_CMD_PFN(pf) | V_FW_EQ_ETH_CMD_VFN(vf)); c.alloc_to_len16 = cpu_to_be32(F_FW_EQ_ETH_CMD_FREE | FW_LEN16(c)); c.eqid_pkd = cpu_to_be32(V_FW_EQ_ETH_CMD_EQID(eqid)); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } /** * t4_handle_fw_rpl - process a FW reply message * @adap: the adapter * @rpl: start of the FW message * * Processes a FW message, such as link state change messages. */ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) { u8 opcode = *(const u8 *)rpl; /* * This might be a port command ... this simplifies the following * conditionals ... We can get away with pre-dereferencing * action_to_len16 because it's in the first 16 bytes and all messages * will be at least that long. */ const struct fw_port_cmd *p = (const void *)rpl; unsigned int action = G_FW_PORT_CMD_ACTION(be32_to_cpu(p->action_to_len16)); if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) { /* link/module state change message */ int speed = 0, fc = 0, i; int chan = G_FW_PORT_CMD_PORTID(be32_to_cpu(p->op_to_portid)); struct port_info *pi = NULL; struct link_config *lc; u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype); int link_ok = (stat & F_FW_PORT_CMD_LSTATUS) != 0; u32 mod = G_FW_PORT_CMD_MODTYPE(stat); if (stat & F_FW_PORT_CMD_RXPAUSE) fc |= PAUSE_RX; if (stat & F_FW_PORT_CMD_TXPAUSE) fc |= PAUSE_TX; if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M)) speed = ETH_LINK_SPEED_100; else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G)) speed = ETH_LINK_SPEED_1000; else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G)) speed = ETH_LINK_SPEED_10000; else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G)) speed = ETH_LINK_SPEED_40G; for_each_port(adap, i) { pi = adap2pinfo(adap, i); if (pi->tx_chan == chan) break; } lc = &pi->link_cfg; if (mod != pi->mod_type) { pi->mod_type = mod; t4_os_portmod_changed(adap, i); } if (link_ok != lc->link_ok || speed != lc->speed || fc != lc->fc) { /* something changed */ if (!link_ok && lc->link_ok) { static const char * const reason[] = { "Link Down", "Remote Fault", "Auto-negotiation Failure", "Reserved", "Insufficient Airflow", "Unable To Determine Reason", "No RX Signal Detected", "Reserved", }; unsigned int rc = G_FW_PORT_CMD_LINKDNRC(stat); dev_warn(adap, "Port %d link down, reason: %s\n", chan, reason[rc]); } lc->link_ok = link_ok; lc->speed = speed; lc->fc = fc; lc->supported = be16_to_cpu(p->u.info.pcap); } } else { dev_warn(adap, "Unknown firmware reply %d\n", opcode); return -EINVAL; } return 0; } void t4_reset_link_config(struct adapter *adap, int idx) { struct port_info *pi = adap2pinfo(adap, idx); struct link_config *lc = &pi->link_cfg; lc->link_ok = 0; lc->requested_speed = 0; lc->requested_fc = 0; lc->speed = 0; lc->fc = 0; } /** * init_link_config - initialize a link's SW state * @lc: structure holding the link state * @caps: link capabilities * * Initializes the SW state maintained for each link, including the link's * capabilities and default speed/flow-control/autonegotiation settings. */ static void init_link_config(struct link_config *lc, unsigned int caps) { lc->supported = caps; lc->requested_speed = 0; lc->speed = 0; lc->requested_fc = 0; lc->fc = 0; if (lc->supported & FW_PORT_CAP_ANEG) { lc->advertising = lc->supported & ADVERT_MASK; lc->autoneg = AUTONEG_ENABLE; } else { lc->advertising = 0; lc->autoneg = AUTONEG_DISABLE; } } /** * t4_wait_dev_ready - wait till to reads of registers work * * Right after the device is RESET is can take a small amount of time * for it to respond to register reads. Until then, all reads will * return either 0xff...ff or 0xee...ee. Return an error if reads * don't work within a reasonable time frame. */ static int t4_wait_dev_ready(struct adapter *adapter) { u32 whoami; whoami = t4_read_reg(adapter, A_PL_WHOAMI); if (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS) return 0; msleep(500); whoami = t4_read_reg(adapter, A_PL_WHOAMI); return (whoami != 0xffffffff && whoami != X_CIM_PF_NOACCESS ? 0 : -EIO); } struct flash_desc { u32 vendor_and_model_id; u32 size_mb; }; int t4_get_flash_params(struct adapter *adapter) { /* * Table for non-Numonix supported flash parts. Numonix parts are left * to the preexisting well-tested code. All flash parts have 64KB * sectors. */ static struct flash_desc supported_flash[] = { { 0x150201, 4 << 20 }, /* Spansion 4MB S25FL032P */ }; int ret; unsigned int i; u32 info = 0; ret = sf1_write(adapter, 1, 1, 0, SF_RD_ID); if (!ret) ret = sf1_read(adapter, 3, 0, 1, &info); t4_write_reg(adapter, A_SF_OP, 0); /* unlock SF */ if (ret < 0) return ret; for (i = 0; i < ARRAY_SIZE(supported_flash); ++i) if (supported_flash[i].vendor_and_model_id == info) { adapter->params.sf_size = supported_flash[i].size_mb; adapter->params.sf_nsec = adapter->params.sf_size / SF_SEC_SIZE; return 0; } if ((info & 0xff) != 0x20) /* not a Numonix flash */ return -EINVAL; info >>= 16; /* log2 of size */ if (info >= 0x14 && info < 0x18) adapter->params.sf_nsec = 1 << (info - 16); else if (info == 0x18) adapter->params.sf_nsec = 64; else return -EINVAL; adapter->params.sf_size = 1 << info; /* * We should reject adapters with FLASHes which are too small. So, emit * a warning. */ if (adapter->params.sf_size < FLASH_MIN_SIZE) { dev_warn(adapter, "WARNING!!! FLASH size %#x < %#x!!!\n", adapter->params.sf_size, FLASH_MIN_SIZE); } return 0; } /** * t4_prep_adapter - prepare SW and HW for operation * @adapter: the adapter * * Initialize adapter SW state for the various HW modules, set initial * values for some adapter tunables, take PHYs out of reset, and * initialize the MDIO interface. */ int t4_prep_adapter(struct adapter *adapter) { int ret, ver; u32 pl_rev; ret = t4_wait_dev_ready(adapter); if (ret < 0) return ret; pl_rev = G_REV(t4_read_reg(adapter, A_PL_REV)); adapter->params.pci.device_id = adapter->pdev->id.device_id; adapter->params.pci.vendor_id = adapter->pdev->id.vendor_id; /* * WE DON'T NEED adapter->params.chip CODE ONCE PL_REV CONTAINS * ADAPTER (VERSION << 4 | REVISION) */ ver = CHELSIO_PCI_ID_VER(adapter->params.pci.device_id); adapter->params.chip = 0; switch (ver) { case CHELSIO_T5: adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev); adapter->params.arch.sge_fl_db = F_DBPRIO | F_DBTYPE; adapter->params.arch.mps_tcam_size = NUM_MPS_T5_CLS_SRAM_L_INSTANCES; adapter->params.arch.mps_rplc_size = 128; adapter->params.arch.nchan = NCHAN; adapter->params.arch.vfcount = 128; break; default: dev_err(adapter, "%s: Device %d is not supported\n", __func__, adapter->params.pci.device_id); return -EINVAL; } ret = t4_get_flash_params(adapter); if (ret < 0) return ret; adapter->params.cim_la_size = CIMLA_SIZE; init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd); /* * Default port and clock for debugging in case we can't reach FW. */ adapter->params.nports = 1; adapter->params.portvec = 1; adapter->params.vpd.cclk = 50000; return 0; } /** * t4_bar2_sge_qregs - return BAR2 SGE Queue register information * @adapter: the adapter * @qid: the Queue ID * @qtype: the Ingress or Egress type for @qid * @pbar2_qoffset: BAR2 Queue Offset * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues * * Returns the BAR2 SGE Queue Registers information associated with the * indicated Absolute Queue ID. These are passed back in return value * pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue * and T4_BAR2_QTYPE_INGRESS for Ingress Queues. * * This may return an error which indicates that BAR2 SGE Queue * registers aren't available. If an error is not returned, then the * following values are returned: * * *@pbar2_qoffset: the BAR2 Offset of the @qid Registers * *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid * * If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which * require the "Inferred Queue ID" ability may be used. E.g. the * Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0, * then these "Inferred Queue ID" register may not be used. */ int t4_bar2_sge_qregs(struct adapter *adapter, unsigned int qid, enum t4_bar2_qtype qtype, u64 *pbar2_qoffset, unsigned int *pbar2_qid) { unsigned int page_shift, page_size, qpp_shift, qpp_mask; u64 bar2_page_offset, bar2_qoffset; unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred; /* * T4 doesn't support BAR2 SGE Queue registers. */ if (is_t4(adapter->params.chip)) return -EINVAL; /* * Get our SGE Page Size parameters. */ page_shift = adapter->params.sge.hps + 10; page_size = 1 << page_shift; /* * Get the right Queues per Page parameters for our Queue. */ qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS ? adapter->params.sge.eq_qpp : adapter->params.sge.iq_qpp); qpp_mask = (1 << qpp_shift) - 1; /* * Calculate the basics of the BAR2 SGE Queue register area: * o The BAR2 page the Queue registers will be in. * o The BAR2 Queue ID. * o The BAR2 Queue ID Offset into the BAR2 page. */ bar2_page_offset = ((qid >> qpp_shift) << page_shift); bar2_qid = qid & qpp_mask; bar2_qid_offset = bar2_qid * SGE_UDB_SIZE; /* * If the BAR2 Queue ID Offset is less than the Page Size, then the * hardware will infer the Absolute Queue ID simply from the writes to * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a * BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply * write to the first BAR2 SGE Queue Area within the BAR2 Page with * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID * from the BAR2 Page and BAR2 Queue ID. * * One important censequence of this is that some BAR2 SGE registers * have a "Queue ID" field and we can write the BAR2 SGE Queue ID * there. But other registers synthesize the SGE Queue ID purely * from the writes to the registers -- the Write Combined Doorbell * Buffer is a good example. These BAR2 SGE Registers are only * available for those BAR2 SGE Register areas where the SGE Absolute * Queue ID can be inferred from simple writes. */ bar2_qoffset = bar2_page_offset; bar2_qinferred = (bar2_qid_offset < page_size); if (bar2_qinferred) { bar2_qoffset += bar2_qid_offset; bar2_qid = 0; } *pbar2_qoffset = bar2_qoffset; *pbar2_qid = bar2_qid; return 0; } /** * t4_init_sge_params - initialize adap->params.sge * @adapter: the adapter * * Initialize various fields of the adapter's SGE Parameters structure. */ int t4_init_sge_params(struct adapter *adapter) { struct sge_params *sge_params = &adapter->params.sge; u32 hps, qpp; unsigned int s_hps, s_qpp; /* * Extract the SGE Page Size for our PF. */ hps = t4_read_reg(adapter, A_SGE_HOST_PAGE_SIZE); s_hps = (S_HOSTPAGESIZEPF0 + (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * adapter->pf); sge_params->hps = ((hps >> s_hps) & M_HOSTPAGESIZEPF0); /* * Extract the SGE Egress and Ingess Queues Per Page for our PF. */ s_qpp = (S_QUEUESPERPAGEPF0 + (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adapter->pf); qpp = t4_read_reg(adapter, A_SGE_EGRESS_QUEUES_PER_PAGE_PF); sge_params->eq_qpp = ((qpp >> s_qpp) & M_QUEUESPERPAGEPF0); qpp = t4_read_reg(adapter, A_SGE_INGRESS_QUEUES_PER_PAGE_PF); sge_params->iq_qpp = ((qpp >> s_qpp) & M_QUEUESPERPAGEPF0); return 0; } /** * t4_init_tp_params - initialize adap->params.tp * @adap: the adapter * * Initialize various fields of the adapter's TP Parameters structure. */ int t4_init_tp_params(struct adapter *adap) { int chan; u32 v; v = t4_read_reg(adap, A_TP_TIMER_RESOLUTION); adap->params.tp.tre = G_TIMERRESOLUTION(v); adap->params.tp.dack_re = G_DELAYEDACKRESOLUTION(v); /* MODQ_REQ_MAP defaults to setting queues 0-3 to chan 0-3 */ for (chan = 0; chan < NCHAN; chan++) adap->params.tp.tx_modq[chan] = chan; /* * Cache the adapter's Compressed Filter Mode and global Incress * Configuration. */ t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, &adap->params.tp.vlan_pri_map, 1, A_TP_VLAN_PRI_MAP); t4_read_indirect(adap, A_TP_PIO_ADDR, A_TP_PIO_DATA, &adap->params.tp.ingress_config, 1, A_TP_INGRESS_CONFIG); /* * Now that we have TP_VLAN_PRI_MAP cached, we can calculate the field * shift positions of several elements of the Compressed Filter Tuple * for this adapter which we need frequently ... */ adap->params.tp.vlan_shift = t4_filter_field_shift(adap, F_VLAN); adap->params.tp.vnic_shift = t4_filter_field_shift(adap, F_VNIC_ID); adap->params.tp.port_shift = t4_filter_field_shift(adap, F_PORT); adap->params.tp.protocol_shift = t4_filter_field_shift(adap, F_PROTOCOL); /* * If TP_INGRESS_CONFIG.VNID == 0, then TP_VLAN_PRI_MAP.VNIC_ID * represents the presense of an Outer VLAN instead of a VNIC ID. */ if ((adap->params.tp.ingress_config & F_VNIC) == 0) adap->params.tp.vnic_shift = -1; return 0; } /** * t4_filter_field_shift - calculate filter field shift * @adap: the adapter * @filter_sel: the desired field (from TP_VLAN_PRI_MAP bits) * * Return the shift position of a filter field within the Compressed * Filter Tuple. The filter field is specified via its selection bit * within TP_VLAN_PRI_MAL (filter mode). E.g. F_VLAN. */ int t4_filter_field_shift(const struct adapter *adap, unsigned int filter_sel) { unsigned int filter_mode = adap->params.tp.vlan_pri_map; unsigned int sel; int field_shift; if ((filter_mode & filter_sel) == 0) return -1; for (sel = 1, field_shift = 0; sel < filter_sel; sel <<= 1) { switch (filter_mode & sel) { case F_FCOE: field_shift += W_FT_FCOE; break; case F_PORT: field_shift += W_FT_PORT; break; case F_VNIC_ID: field_shift += W_FT_VNIC_ID; break; case F_VLAN: field_shift += W_FT_VLAN; break; case F_TOS: field_shift += W_FT_TOS; break; case F_PROTOCOL: field_shift += W_FT_PROTOCOL; break; case F_ETHERTYPE: field_shift += W_FT_ETHERTYPE; break; case F_MACMATCH: field_shift += W_FT_MACMATCH; break; case F_MPSHITTYPE: field_shift += W_FT_MPSHITTYPE; break; case F_FRAGMENTATION: field_shift += W_FT_FRAGMENTATION; break; } } return field_shift; } int t4_init_rss_mode(struct adapter *adap, int mbox) { int i, ret; struct fw_rss_vi_config_cmd rvc; memset(&rvc, 0, sizeof(rvc)); for_each_port(adap, i) { struct port_info *p = adap2pinfo(adap, i); rvc.op_to_viid = htonl(V_FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ | V_FW_RSS_VI_CONFIG_CMD_VIID(p->viid)); rvc.retval_len16 = htonl(FW_LEN16(rvc)); ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc); if (ret) return ret; p->rss_mode = ntohl(rvc.u.basicvirtual.defaultq_to_udpen); } return 0; } int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) { u8 addr[6]; int ret, i, j = 0; struct fw_port_cmd c; memset(&c, 0, sizeof(c)); for_each_port(adap, i) { unsigned int rss_size = 0; struct port_info *p = adap2pinfo(adap, i); while ((adap->params.portvec & (1 << j)) == 0) j++; c.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ | V_FW_PORT_CMD_PORTID(j)); c.action_to_len16 = cpu_to_be32(V_FW_PORT_CMD_ACTION( FW_PORT_ACTION_GET_PORT_INFO) | FW_LEN16(c)); ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret) return ret; ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size); if (ret < 0) return ret; p->viid = ret; p->tx_chan = j; p->rss_size = rss_size; t4_os_set_hw_addr(adap, i, addr); ret = be32_to_cpu(c.u.info.lstatus_to_modtype); p->mdio_addr = (ret & F_FW_PORT_CMD_MDIOCAP) ? G_FW_PORT_CMD_MDIOADDR(ret) : -1; p->port_type = G_FW_PORT_CMD_PTYPE(ret); p->mod_type = FW_PORT_MOD_TYPE_NA; init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap)); j++; } return 0; } ================================================ FILE: drivers/net/cxgbe/base/t4_hw.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __T4_HW_H #define __T4_HW_H enum { NCHAN = 4, /* # of HW channels */ NMTUS = 16, /* size of MTU table */ NCCTRL_WIN = 32, /* # of congestion control windows */ MBOX_LEN = 64, /* mailbox size in bytes */ UDBS_SEG_SIZE = 128, /* segment size for BAR2 user doorbells */ }; enum { CIMLA_SIZE = 2048, /* # of 32-bit words in CIM LA */ }; enum { SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ }; enum { SGE_NTIMERS = 6, /* # of interrupt holdoff timer values */ SGE_NCOUNTERS = 4, /* # of interrupt packet counter values */ }; /* PCI-e memory window access */ enum pcie_memwin { MEMWIN_NIC = 0, }; enum { SGE_MAX_WR_LEN = 512, /* max WR size in bytes */ SGE_EQ_IDXSIZE = 64, /* egress queue pidx/cidx unit size */ /* max no. of desc allowed in WR */ SGE_MAX_WR_NDESC = SGE_MAX_WR_LEN / SGE_EQ_IDXSIZE, }; struct sge_qstat { /* data written to SGE queue status entries */ __be32 qid; __be16 cidx; __be16 pidx; }; /* * Structure for last 128 bits of response descriptors */ struct rsp_ctrl { __be32 hdrbuflen_pidx; __be32 pldbuflen_qid; union { u8 type_gen; __be64 last_flit; } u; }; #define S_RSPD_NEWBUF 31 #define V_RSPD_NEWBUF(x) ((x) << S_RSPD_NEWBUF) #define F_RSPD_NEWBUF V_RSPD_NEWBUF(1U) #define S_RSPD_LEN 0 #define M_RSPD_LEN 0x7fffffff #define V_RSPD_LEN(x) ((x) << S_RSPD_LEN) #define G_RSPD_LEN(x) (((x) >> S_RSPD_LEN) & M_RSPD_LEN) #define S_RSPD_GEN 7 #define V_RSPD_GEN(x) ((x) << S_RSPD_GEN) #define F_RSPD_GEN V_RSPD_GEN(1U) #define S_RSPD_TYPE 4 #define M_RSPD_TYPE 0x3 #define V_RSPD_TYPE(x) ((x) << S_RSPD_TYPE) #define G_RSPD_TYPE(x) (((x) >> S_RSPD_TYPE) & M_RSPD_TYPE) /* Rx queue interrupt deferral field: timer index */ #define S_QINTR_CNT_EN 0 #define V_QINTR_CNT_EN(x) ((x) << S_QINTR_CNT_EN) #define F_QINTR_CNT_EN V_QINTR_CNT_EN(1U) #define S_QINTR_TIMER_IDX 1 #define M_QINTR_TIMER_IDX 0x7 #define V_QINTR_TIMER_IDX(x) ((x) << S_QINTR_TIMER_IDX) #define G_QINTR_TIMER_IDX(x) (((x) >> S_QINTR_TIMER_IDX) & M_QINTR_TIMER_IDX) /* * Flash layout. */ #define FLASH_START(start) ((start) * SF_SEC_SIZE) #define FLASH_MAX_SIZE(nsecs) ((nsecs) * SF_SEC_SIZE) enum { /* * Location of firmware image in FLASH. */ FLASH_FW_START_SEC = 8, FLASH_FW_NSECS = 16, FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC), FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS), /* * Location of Firmware Configuration File in FLASH. */ FLASH_CFG_START_SEC = 31, FLASH_CFG_NSECS = 1, FLASH_CFG_START = FLASH_START(FLASH_CFG_START_SEC), FLASH_CFG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_CFG_NSECS), /* * We don't support FLASH devices which can't support the full * standard set of sections which we need for normal operations. */ FLASH_MIN_SIZE = FLASH_CFG_START + FLASH_CFG_MAX_SIZE, }; #undef FLASH_START #undef FLASH_MAX_SIZE #endif /* __T4_HW_H */ ================================================ FILE: drivers/net/cxgbe/base/t4_msg.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef T4_MSG_H #define T4_MSG_H enum { CPL_SGE_EGR_UPDATE = 0xA5, CPL_FW4_MSG = 0xC0, CPL_FW6_MSG = 0xE0, CPL_TX_PKT_LSO = 0xED, CPL_TX_PKT_XT = 0xEE, }; enum { /* TX_PKT_XT checksum types */ TX_CSUM_TCPIP = 8, TX_CSUM_UDPIP = 9, TX_CSUM_TCPIP6 = 10, }; union opcode_tid { __be32 opcode_tid; __u8 opcode; }; struct rss_header { __u8 opcode; #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN __u8 channel:2; __u8 filter_hit:1; __u8 filter_tid:1; __u8 hash_type:2; __u8 ipv6:1; __u8 send2fw:1; #else __u8 send2fw:1; __u8 ipv6:1; __u8 hash_type:2; __u8 filter_tid:1; __u8 filter_hit:1; __u8 channel:2; #endif __be16 qid; __be32 hash_val; }; #if defined(RSS_HDR_VLD) || defined(CHELSIO_FW) #define RSS_HDR struct rss_header rss_hdr #else #define RSS_HDR #endif #ifndef CHELSIO_FW struct work_request_hdr { __be32 wr_hi; __be32 wr_mid; __be64 wr_lo; }; #define WR_HDR struct work_request_hdr wr #define WR_HDR_SIZE sizeof(struct work_request_hdr) #else #define WR_HDR #define WR_HDR_SIZE 0 #endif struct cpl_tx_data { union opcode_tid ot; __be32 len; __be32 rsvd; __be32 flags; }; struct cpl_tx_pkt_core { __be32 ctrl0; __be16 pack; __be16 len; __be64 ctrl1; }; struct cpl_tx_pkt { WR_HDR; struct cpl_tx_pkt_core c; }; /* cpl_tx_pkt_core.ctrl0 fields */ #define S_TXPKT_PF 8 #define M_TXPKT_PF 0x7 #define V_TXPKT_PF(x) ((x) << S_TXPKT_PF) #define G_TXPKT_PF(x) (((x) >> S_TXPKT_PF) & M_TXPKT_PF) #define S_TXPKT_INTF 16 #define M_TXPKT_INTF 0xF #define V_TXPKT_INTF(x) ((x) << S_TXPKT_INTF) #define G_TXPKT_INTF(x) (((x) >> S_TXPKT_INTF) & M_TXPKT_INTF) #define S_TXPKT_OPCODE 24 #define M_TXPKT_OPCODE 0xFF #define V_TXPKT_OPCODE(x) ((x) << S_TXPKT_OPCODE) #define G_TXPKT_OPCODE(x) (((x) >> S_TXPKT_OPCODE) & M_TXPKT_OPCODE) /* cpl_tx_pkt_core.ctrl1 fields */ #define S_TXPKT_IPHDR_LEN 20 #define M_TXPKT_IPHDR_LEN 0x3FFF #define V_TXPKT_IPHDR_LEN(x) ((__u64)(x) << S_TXPKT_IPHDR_LEN) #define G_TXPKT_IPHDR_LEN(x) (((x) >> S_TXPKT_IPHDR_LEN) & M_TXPKT_IPHDR_LEN) #define S_TXPKT_ETHHDR_LEN 34 #define M_TXPKT_ETHHDR_LEN 0x3F #define V_TXPKT_ETHHDR_LEN(x) ((__u64)(x) << S_TXPKT_ETHHDR_LEN) #define G_TXPKT_ETHHDR_LEN(x) (((x) >> S_TXPKT_ETHHDR_LEN) & M_TXPKT_ETHHDR_LEN) #define S_T6_TXPKT_ETHHDR_LEN 32 #define M_T6_TXPKT_ETHHDR_LEN 0xFF #define V_T6_TXPKT_ETHHDR_LEN(x) ((__u64)(x) << S_T6_TXPKT_ETHHDR_LEN) #define G_T6_TXPKT_ETHHDR_LEN(x) \ (((x) >> S_T6_TXPKT_ETHHDR_LEN) & M_T6_TXPKT_ETHHDR_LEN) #define S_TXPKT_CSUM_TYPE 40 #define M_TXPKT_CSUM_TYPE 0xF #define V_TXPKT_CSUM_TYPE(x) ((__u64)(x) << S_TXPKT_CSUM_TYPE) #define G_TXPKT_CSUM_TYPE(x) (((x) >> S_TXPKT_CSUM_TYPE) & M_TXPKT_CSUM_TYPE) #define S_TXPKT_VLAN 44 #define M_TXPKT_VLAN 0xFFFF #define V_TXPKT_VLAN(x) ((__u64)(x) << S_TXPKT_VLAN) #define G_TXPKT_VLAN(x) (((x) >> S_TXPKT_VLAN) & M_TXPKT_VLAN) #define S_TXPKT_VLAN_VLD 60 #define V_TXPKT_VLAN_VLD(x) ((__u64)(x) << S_TXPKT_VLAN_VLD) #define F_TXPKT_VLAN_VLD V_TXPKT_VLAN_VLD(1ULL) #define S_TXPKT_IPCSUM_DIS 62 #define V_TXPKT_IPCSUM_DIS(x) ((__u64)(x) << S_TXPKT_IPCSUM_DIS) #define F_TXPKT_IPCSUM_DIS V_TXPKT_IPCSUM_DIS(1ULL) #define S_TXPKT_L4CSUM_DIS 63 #define V_TXPKT_L4CSUM_DIS(x) ((__u64)(x) << S_TXPKT_L4CSUM_DIS) #define F_TXPKT_L4CSUM_DIS V_TXPKT_L4CSUM_DIS(1ULL) struct cpl_tx_pkt_lso_core { __be32 lso_ctrl; __be16 ipid_ofst; __be16 mss; __be32 seqno_offset; __be32 len; /* encapsulated CPL (TX_PKT, TX_PKT_XT or TX_DATA) follows here */ }; struct cpl_tx_pkt_lso { WR_HDR; struct cpl_tx_pkt_lso_core c; /* encapsulated CPL (TX_PKT, TX_PKT_XT or TX_DATA) follows here */ }; /* cpl_tx_pkt_lso_core.lso_ctrl fields */ #define S_LSO_TCPHDR_LEN 0 #define M_LSO_TCPHDR_LEN 0xF #define V_LSO_TCPHDR_LEN(x) ((x) << S_LSO_TCPHDR_LEN) #define G_LSO_TCPHDR_LEN(x) (((x) >> S_LSO_TCPHDR_LEN) & M_LSO_TCPHDR_LEN) #define S_LSO_IPHDR_LEN 4 #define M_LSO_IPHDR_LEN 0xFFF #define V_LSO_IPHDR_LEN(x) ((x) << S_LSO_IPHDR_LEN) #define G_LSO_IPHDR_LEN(x) (((x) >> S_LSO_IPHDR_LEN) & M_LSO_IPHDR_LEN) #define S_LSO_ETHHDR_LEN 16 #define M_LSO_ETHHDR_LEN 0xF #define V_LSO_ETHHDR_LEN(x) ((x) << S_LSO_ETHHDR_LEN) #define G_LSO_ETHHDR_LEN(x) (((x) >> S_LSO_ETHHDR_LEN) & M_LSO_ETHHDR_LEN) #define S_LSO_IPV6 20 #define V_LSO_IPV6(x) ((x) << S_LSO_IPV6) #define F_LSO_IPV6 V_LSO_IPV6(1U) #define S_LSO_LAST_SLICE 22 #define V_LSO_LAST_SLICE(x) ((x) << S_LSO_LAST_SLICE) #define F_LSO_LAST_SLICE V_LSO_LAST_SLICE(1U) #define S_LSO_FIRST_SLICE 23 #define V_LSO_FIRST_SLICE(x) ((x) << S_LSO_FIRST_SLICE) #define F_LSO_FIRST_SLICE V_LSO_FIRST_SLICE(1U) #define S_LSO_OPCODE 24 #define M_LSO_OPCODE 0xFF #define V_LSO_OPCODE(x) ((x) << S_LSO_OPCODE) #define G_LSO_OPCODE(x) (((x) >> S_LSO_OPCODE) & M_LSO_OPCODE) #define S_LSO_T5_XFER_SIZE 0 #define M_LSO_T5_XFER_SIZE 0xFFFFFFF #define V_LSO_T5_XFER_SIZE(x) ((x) << S_LSO_T5_XFER_SIZE) #define G_LSO_T5_XFER_SIZE(x) (((x) >> S_LSO_T5_XFER_SIZE) & M_LSO_T5_XFER_SIZE) struct cpl_rx_pkt { RSS_HDR; __u8 opcode; #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN __u8 iff:4; __u8 csum_calc:1; __u8 ipmi_pkt:1; __u8 vlan_ex:1; __u8 ip_frag:1; #else __u8 ip_frag:1; __u8 vlan_ex:1; __u8 ipmi_pkt:1; __u8 csum_calc:1; __u8 iff:4; #endif __be16 csum; __be16 vlan; __be16 len; __be32 l2info; __be16 hdr_len; __be16 err_vec; }; /* rx_pkt.l2info fields */ #define S_RXF_UDP 22 #define V_RXF_UDP(x) ((x) << S_RXF_UDP) #define F_RXF_UDP V_RXF_UDP(1U) #define S_RXF_TCP 23 #define V_RXF_TCP(x) ((x) << S_RXF_TCP) #define F_RXF_TCP V_RXF_TCP(1U) #define S_RXF_IP 24 #define V_RXF_IP(x) ((x) << S_RXF_IP) #define F_RXF_IP V_RXF_IP(1U) #define S_RXF_IP6 25 #define V_RXF_IP6(x) ((x) << S_RXF_IP6) #define F_RXF_IP6 V_RXF_IP6(1U) /* cpl_fw*.type values */ enum { FW_TYPE_RSSCPL = 4, }; struct cpl_fw4_msg { RSS_HDR; u8 opcode; u8 type; __be16 rsvd0; __be32 rsvd1; __be64 data[2]; }; struct cpl_fw6_msg { RSS_HDR; u8 opcode; u8 type; __be16 rsvd0; __be32 rsvd1; __be64 data[4]; }; enum { ULP_TX_SC_IMM = 0x81, ULP_TX_SC_DSGL = 0x82, ULP_TX_SC_ISGL = 0x83 }; #define S_ULPTX_CMD 24 #define M_ULPTX_CMD 0xFF #define V_ULPTX_CMD(x) ((x) << S_ULPTX_CMD) #define S_ULP_TX_SC_MORE 23 #define V_ULP_TX_SC_MORE(x) ((x) << S_ULP_TX_SC_MORE) #define F_ULP_TX_SC_MORE V_ULP_TX_SC_MORE(1U) struct ulptx_sge_pair { __be32 len[2]; __be64 addr[2]; }; struct ulptx_sgl { __be32 cmd_nsge; __be32 len0; __be64 addr0; #if !(defined C99_NOT_SUPPORTED) struct ulptx_sge_pair sge[0]; #endif }; struct ulptx_idata { __be32 cmd_more; __be32 len; }; #define S_ULPTX_NSGE 0 #define M_ULPTX_NSGE 0xFFFF #define V_ULPTX_NSGE(x) ((x) << S_ULPTX_NSGE) struct ulp_txpkt { __be32 cmd_dest; __be32 len; }; /* ulp_txpkt.cmd_dest fields */ #define S_ULP_TXPKT_DEST 16 #define M_ULP_TXPKT_DEST 0x3 #define V_ULP_TXPKT_DEST(x) ((x) << S_ULP_TXPKT_DEST) #define S_ULP_TXPKT_FID 4 #define M_ULP_TXPKT_FID 0x7ff #define V_ULP_TXPKT_FID(x) ((x) << S_ULP_TXPKT_FID) #define S_ULP_TXPKT_RO 3 #define V_ULP_TXPKT_RO(x) ((x) << S_ULP_TXPKT_RO) #define F_ULP_TXPKT_RO V_ULP_TXPKT_RO(1U) #endif /* T4_MSG_H */ ================================================ FILE: drivers/net/cxgbe/base/t4_pci_id_tbl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __T4_PCI_ID_TBL_H__ #define __T4_PCI_ID_TBL_H__ /* * The Os-Dependent code can defined cpp macros for creating a PCI Device ID * Table. This is useful because it allows the PCI ID Table to be maintained * in a single place and all supporting OSes to get new PCI Device IDs * automatically. * * The macros are: * * CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN * -- Used to start the definition of the PCI ID Table. * * CH_PCI_DEVICE_ID_FUNCTION * -- The PCI Function Number to use in the PCI Device ID Table. "0" * -- for drivers attaching to PF0-3, "4" for drivers attaching to PF4, * -- "8" for drivers attaching to SR-IOV Virtual Functions, etc. * * CH_PCI_DEVICE_ID_FUNCTION2 [optional] * -- If defined, create a PCI Device ID Table with both * -- CH_PCI_DEVICE_ID_FUNCTION and CH_PCI_DEVICE_ID_FUNCTION2 populated. * * CH_PCI_ID_TABLE_ENTRY(DeviceID) * -- Used for the individual PCI Device ID entries. Note that we will * -- be adding a trailing comma (",") after all of the entries (and * -- between the pairs of entries if CH_PCI_DEVICE_ID_FUNCTION2 is defined). * * CH_PCI_DEVICE_ID_TABLE_DEFINE_END * -- Used to finish the definition of the PCI ID Table. Note that we * -- will be adding a trailing semi-colon (";") here. * * CH_PCI_DEVICE_ID_BYPASS_SUPPORTED [optional] * -- If defined, indicates that the OS Driver has support for Bypass * -- Adapters. */ #ifdef CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN /* * Some sanity checks ... */ #ifndef CH_PCI_DEVICE_ID_FUNCTION #error CH_PCI_DEVICE_ID_FUNCTION not defined! #endif #ifndef CH_PCI_ID_TABLE_ENTRY #error CH_PCI_ID_TABLE_ENTRY not defined! #endif #ifndef CH_PCI_DEVICE_ID_TABLE_DEFINE_END #error CH_PCI_DEVICE_ID_TABLE_DEFINE_END not defined! #endif /* * T4 and later ASICs use a PCI Device ID scheme of 0xVFPP where: * * V = "4" for T4; "5" for T5, etc. * F = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs * PP = adapter product designation * * We use this consistency in order to create the proper PCI Device IDs * for the specified CH_PCI_DEVICE_ID_FUNCTION. */ #ifndef CH_PCI_DEVICE_ID_FUNCTION2 #define CH_PCI_ID_TABLE_FENTRY(devid) \ CH_PCI_ID_TABLE_ENTRY((devid) | \ ((CH_PCI_DEVICE_ID_FUNCTION) << 8)) #else #define CH_PCI_ID_TABLE_FENTRY(devid) \ CH_PCI_ID_TABLE_ENTRY((devid) | \ ((CH_PCI_DEVICE_ID_FUNCTION) << 8)), \ CH_PCI_ID_TABLE_ENTRY((devid) | \ ((CH_PCI_DEVICE_ID_FUNCTION2) << 8)) #endif CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN /* * T5 adapters: */ CH_PCI_ID_TABLE_FENTRY(0x5000), /* T580-dbg */ CH_PCI_ID_TABLE_FENTRY(0x5001), /* T520-cr */ CH_PCI_ID_TABLE_FENTRY(0x5002), /* T522-cr */ CH_PCI_ID_TABLE_FENTRY(0x5003), /* T540-cr */ CH_PCI_ID_TABLE_FENTRY(0x5004), /* T520-bch */ CH_PCI_ID_TABLE_FENTRY(0x5005), /* T540-bch */ CH_PCI_ID_TABLE_FENTRY(0x5006), /* T540-ch */ CH_PCI_ID_TABLE_FENTRY(0x5007), /* T520-so */ CH_PCI_ID_TABLE_FENTRY(0x5008), /* T520-cx */ CH_PCI_ID_TABLE_FENTRY(0x5009), /* T520-bt */ CH_PCI_ID_TABLE_FENTRY(0x500a), /* T504-bt */ #ifdef CH_PCI_DEVICE_ID_BYPASS_SUPPORTED CH_PCI_ID_TABLE_FENTRY(0x500b), /* B520-sr */ CH_PCI_ID_TABLE_FENTRY(0x500c), /* B504-bt */ #endif CH_PCI_ID_TABLE_FENTRY(0x500d), /* T580-cr */ CH_PCI_ID_TABLE_FENTRY(0x500e), /* T540-LP-cr */ CH_PCI_ID_TABLE_FENTRY(0x5010), /* T580-LP-cr */ CH_PCI_ID_TABLE_FENTRY(0x5011), /* T520-LL-cr */ CH_PCI_ID_TABLE_FENTRY(0x5012), /* T560-cr */ CH_PCI_ID_TABLE_FENTRY(0x5013), /* T580-chr */ CH_PCI_ID_TABLE_FENTRY(0x5014), /* T580-so */ CH_PCI_ID_TABLE_FENTRY(0x5015), /* T502-bt */ CH_PCI_ID_TABLE_FENTRY(0x5080), /* Custom T540-cr */ CH_PCI_ID_TABLE_FENTRY(0x5081), /* Custom T540-LL-cr */ CH_PCI_ID_TABLE_FENTRY(0x5082), /* Custom T504-cr */ CH_PCI_ID_TABLE_FENTRY(0x5083), /* Custom T540-LP-CR */ CH_PCI_ID_TABLE_FENTRY(0x5084), /* Custom T580-cr */ CH_PCI_ID_TABLE_FENTRY(0x5085), /* Custom 3x T580-CR */ CH_PCI_ID_TABLE_FENTRY(0x5086), /* Custom 2x T580-CR */ CH_PCI_ID_TABLE_FENTRY(0x5087), /* Custom T580-CR */ CH_PCI_ID_TABLE_FENTRY(0x5088), /* Custom T570-CR */ CH_PCI_ID_TABLE_FENTRY(0x5089), /* Custom T520-CR */ CH_PCI_ID_TABLE_FENTRY(0x5090), /* Custom T540-CR */ CH_PCI_ID_TABLE_FENTRY(0x5091), /* Custom T522-CR */ CH_PCI_ID_TABLE_FENTRY(0x5092), /* Custom T520-CR */ CH_PCI_DEVICE_ID_TABLE_DEFINE_END; #endif /* CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN */ #endif /* __T4_PCI_ID_TBL_H__ */ ================================================ FILE: drivers/net/cxgbe/base/t4_regs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define MYPF_BASE 0x1b000 #define MYPF_REG(reg_addr) (MYPF_BASE + (reg_addr)) #define PF0_BASE 0x1e000 #define PF0_REG(reg_addr) (PF0_BASE + (reg_addr)) #define PF_STRIDE 0x400 #define PF_BASE(idx) (PF0_BASE + (idx) * PF_STRIDE) #define PF_REG(idx, reg) (PF_BASE(idx) + (reg)) #define MYPORT_BASE 0x1c000 #define MYPORT_REG(reg_addr) (MYPORT_BASE + (reg_addr)) #define PORT0_BASE 0x20000 #define PORT0_REG(reg_addr) (PORT0_BASE + (reg_addr)) #define PORT_STRIDE 0x2000 #define PORT_BASE(idx) (PORT0_BASE + (idx) * PORT_STRIDE) #define PORT_REG(idx, reg) (PORT_BASE(idx) + (reg)) #define PCIE_MEM_ACCESS_REG(reg_addr, idx) ((reg_addr) + (idx) * 8) #define NUM_PCIE_MEM_ACCESS_INSTANCES 8 #define PCIE_FW_REG(reg_addr, idx) ((reg_addr) + (idx) * 4) #define NUM_PCIE_FW_INSTANCES 8 #define T5_MYPORT_BASE 0x2c000 #define T5_MYPORT_REG(reg_addr) (T5_MYPORT_BASE + (reg_addr)) #define T5_PORT0_BASE 0x30000 #define T5_PORT0_REG(reg_addr) (T5_PORT0_BASE + (reg_addr)) #define T5_PORT_STRIDE 0x4000 #define T5_PORT_BASE(idx) (T5_PORT0_BASE + (idx) * T5_PORT_STRIDE) #define T5_PORT_REG(idx, reg) (T5_PORT_BASE(idx) + (reg)) #define MPS_T5_CLS_SRAM_L(idx) (A_MPS_T5_CLS_SRAM_L + (idx) * 8) #define NUM_MPS_T5_CLS_SRAM_L_INSTANCES 512 #define MPS_T5_CLS_SRAM_H(idx) (A_MPS_T5_CLS_SRAM_H + (idx) * 8) #define NUM_MPS_T5_CLS_SRAM_H_INSTANCES 512 /* registers for module SGE */ #define SGE_BASE_ADDR 0x1000 #define A_SGE_PF_KDOORBELL 0x0 #define S_QID 15 #define M_QID 0x1ffffU #define V_QID(x) ((x) << S_QID) #define G_QID(x) (((x) >> S_QID) & M_QID) #define S_DBPRIO 14 #define V_DBPRIO(x) ((x) << S_DBPRIO) #define F_DBPRIO V_DBPRIO(1U) #define S_PIDX 0 #define M_PIDX 0x3fffU #define V_PIDX(x) ((x) << S_PIDX) #define G_PIDX(x) (((x) >> S_PIDX) & M_PIDX) #define S_DBTYPE 13 #define V_DBTYPE(x) ((x) << S_DBTYPE) #define F_DBTYPE V_DBTYPE(1U) #define S_PIDX_T5 0 #define M_PIDX_T5 0x1fffU #define V_PIDX_T5(x) ((x) << S_PIDX_T5) #define G_PIDX_T5(x) (((x) >> S_PIDX_T5) & M_PIDX_T5) #define A_SGE_PF_GTS 0x4 #define S_INGRESSQID 16 #define M_INGRESSQID 0xffffU #define V_INGRESSQID(x) ((x) << S_INGRESSQID) #define G_INGRESSQID(x) (((x) >> S_INGRESSQID) & M_INGRESSQID) #define S_SEINTARM 12 #define V_SEINTARM(x) ((x) << S_SEINTARM) #define F_SEINTARM V_SEINTARM(1U) #define S_CIDXINC 0 #define M_CIDXINC 0xfffU #define V_CIDXINC(x) ((x) << S_CIDXINC) #define G_CIDXINC(x) (((x) >> S_CIDXINC) & M_CIDXINC) #define A_SGE_CONTROL 0x1008 #define S_RXPKTCPLMODE 18 #define V_RXPKTCPLMODE(x) ((x) << S_RXPKTCPLMODE) #define F_RXPKTCPLMODE V_RXPKTCPLMODE(1U) #define S_EGRSTATUSPAGESIZE 17 #define V_EGRSTATUSPAGESIZE(x) ((x) << S_EGRSTATUSPAGESIZE) #define F_EGRSTATUSPAGESIZE V_EGRSTATUSPAGESIZE(1U) #define S_PKTSHIFT 10 #define M_PKTSHIFT 0x7U #define V_PKTSHIFT(x) ((x) << S_PKTSHIFT) #define G_PKTSHIFT(x) (((x) >> S_PKTSHIFT) & M_PKTSHIFT) #define S_INGPADBOUNDARY 4 #define M_INGPADBOUNDARY 0x7U #define V_INGPADBOUNDARY(x) ((x) << S_INGPADBOUNDARY) #define G_INGPADBOUNDARY(x) (((x) >> S_INGPADBOUNDARY) & M_INGPADBOUNDARY) #define A_SGE_HOST_PAGE_SIZE 0x100c #define S_HOSTPAGESIZEPF7 28 #define M_HOSTPAGESIZEPF7 0xfU #define V_HOSTPAGESIZEPF7(x) ((x) << S_HOSTPAGESIZEPF7) #define G_HOSTPAGESIZEPF7(x) (((x) >> S_HOSTPAGESIZEPF7) & M_HOSTPAGESIZEPF7) #define S_HOSTPAGESIZEPF6 24 #define M_HOSTPAGESIZEPF6 0xfU #define V_HOSTPAGESIZEPF6(x) ((x) << S_HOSTPAGESIZEPF6) #define G_HOSTPAGESIZEPF6(x) (((x) >> S_HOSTPAGESIZEPF6) & M_HOSTPAGESIZEPF6) #define S_HOSTPAGESIZEPF5 20 #define M_HOSTPAGESIZEPF5 0xfU #define V_HOSTPAGESIZEPF5(x) ((x) << S_HOSTPAGESIZEPF5) #define G_HOSTPAGESIZEPF5(x) (((x) >> S_HOSTPAGESIZEPF5) & M_HOSTPAGESIZEPF5) #define S_HOSTPAGESIZEPF4 16 #define M_HOSTPAGESIZEPF4 0xfU #define V_HOSTPAGESIZEPF4(x) ((x) << S_HOSTPAGESIZEPF4) #define G_HOSTPAGESIZEPF4(x) (((x) >> S_HOSTPAGESIZEPF4) & M_HOSTPAGESIZEPF4) #define S_HOSTPAGESIZEPF3 12 #define M_HOSTPAGESIZEPF3 0xfU #define V_HOSTPAGESIZEPF3(x) ((x) << S_HOSTPAGESIZEPF3) #define G_HOSTPAGESIZEPF3(x) (((x) >> S_HOSTPAGESIZEPF3) & M_HOSTPAGESIZEPF3) #define S_HOSTPAGESIZEPF2 8 #define M_HOSTPAGESIZEPF2 0xfU #define V_HOSTPAGESIZEPF2(x) ((x) << S_HOSTPAGESIZEPF2) #define G_HOSTPAGESIZEPF2(x) (((x) >> S_HOSTPAGESIZEPF2) & M_HOSTPAGESIZEPF2) #define S_HOSTPAGESIZEPF1 4 #define M_HOSTPAGESIZEPF1 0xfU #define V_HOSTPAGESIZEPF1(x) ((x) << S_HOSTPAGESIZEPF1) #define G_HOSTPAGESIZEPF1(x) (((x) >> S_HOSTPAGESIZEPF1) & M_HOSTPAGESIZEPF1) #define S_HOSTPAGESIZEPF0 0 #define M_HOSTPAGESIZEPF0 0xfU #define V_HOSTPAGESIZEPF0(x) ((x) << S_HOSTPAGESIZEPF0) #define G_HOSTPAGESIZEPF0(x) (((x) >> S_HOSTPAGESIZEPF0) & M_HOSTPAGESIZEPF0) #define A_SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010 #define S_QUEUESPERPAGEPF1 4 #define M_QUEUESPERPAGEPF1 0xfU #define V_QUEUESPERPAGEPF1(x) ((x) << S_QUEUESPERPAGEPF1) #define G_QUEUESPERPAGEPF1(x) (((x) >> S_QUEUESPERPAGEPF1) & M_QUEUESPERPAGEPF1) #define S_QUEUESPERPAGEPF0 0 #define M_QUEUESPERPAGEPF0 0xfU #define V_QUEUESPERPAGEPF0(x) ((x) << S_QUEUESPERPAGEPF0) #define G_QUEUESPERPAGEPF0(x) (((x) >> S_QUEUESPERPAGEPF0) & M_QUEUESPERPAGEPF0) #define S_ERR_CPL_EXCEED_IQE_SIZE 22 #define V_ERR_CPL_EXCEED_IQE_SIZE(x) ((x) << S_ERR_CPL_EXCEED_IQE_SIZE) #define F_ERR_CPL_EXCEED_IQE_SIZE V_ERR_CPL_EXCEED_IQE_SIZE(1U) #define S_ERR_INVALID_CIDX_INC 21 #define V_ERR_INVALID_CIDX_INC(x) ((x) << S_ERR_INVALID_CIDX_INC) #define F_ERR_INVALID_CIDX_INC V_ERR_INVALID_CIDX_INC(1U) #define S_ERR_CPL_OPCODE_0 19 #define V_ERR_CPL_OPCODE_0(x) ((x) << S_ERR_CPL_OPCODE_0) #define F_ERR_CPL_OPCODE_0 V_ERR_CPL_OPCODE_0(1U) #define S_ERR_DROPPED_DB 18 #define V_ERR_DROPPED_DB(x) ((x) << S_ERR_DROPPED_DB) #define F_ERR_DROPPED_DB V_ERR_DROPPED_DB(1U) #define S_ERR_DATA_CPL_ON_HIGH_QID1 17 #define V_ERR_DATA_CPL_ON_HIGH_QID1(x) ((x) << S_ERR_DATA_CPL_ON_HIGH_QID1) #define F_ERR_DATA_CPL_ON_HIGH_QID1 V_ERR_DATA_CPL_ON_HIGH_QID1(1U) #define S_ERR_DATA_CPL_ON_HIGH_QID0 16 #define V_ERR_DATA_CPL_ON_HIGH_QID0(x) ((x) << S_ERR_DATA_CPL_ON_HIGH_QID0) #define F_ERR_DATA_CPL_ON_HIGH_QID0 V_ERR_DATA_CPL_ON_HIGH_QID0(1U) #define S_ERR_BAD_DB_PIDX3 15 #define V_ERR_BAD_DB_PIDX3(x) ((x) << S_ERR_BAD_DB_PIDX3) #define F_ERR_BAD_DB_PIDX3 V_ERR_BAD_DB_PIDX3(1U) #define S_ERR_BAD_DB_PIDX2 14 #define V_ERR_BAD_DB_PIDX2(x) ((x) << S_ERR_BAD_DB_PIDX2) #define F_ERR_BAD_DB_PIDX2 V_ERR_BAD_DB_PIDX2(1U) #define S_ERR_BAD_DB_PIDX1 13 #define V_ERR_BAD_DB_PIDX1(x) ((x) << S_ERR_BAD_DB_PIDX1) #define F_ERR_BAD_DB_PIDX1 V_ERR_BAD_DB_PIDX1(1U) #define S_ERR_BAD_DB_PIDX0 12 #define V_ERR_BAD_DB_PIDX0(x) ((x) << S_ERR_BAD_DB_PIDX0) #define F_ERR_BAD_DB_PIDX0 V_ERR_BAD_DB_PIDX0(1U) #define S_ERR_ING_PCIE_CHAN 11 #define V_ERR_ING_PCIE_CHAN(x) ((x) << S_ERR_ING_PCIE_CHAN) #define F_ERR_ING_PCIE_CHAN V_ERR_ING_PCIE_CHAN(1U) #define S_ERR_ING_CTXT_PRIO 10 #define V_ERR_ING_CTXT_PRIO(x) ((x) << S_ERR_ING_CTXT_PRIO) #define F_ERR_ING_CTXT_PRIO V_ERR_ING_CTXT_PRIO(1U) #define S_ERR_EGR_CTXT_PRIO 9 #define V_ERR_EGR_CTXT_PRIO(x) ((x) << S_ERR_EGR_CTXT_PRIO) #define F_ERR_EGR_CTXT_PRIO V_ERR_EGR_CTXT_PRIO(1U) #define S_DBFIFO_HP_INT 8 #define V_DBFIFO_HP_INT(x) ((x) << S_DBFIFO_HP_INT) #define F_DBFIFO_HP_INT V_DBFIFO_HP_INT(1U) #define S_DBFIFO_LP_INT 7 #define V_DBFIFO_LP_INT(x) ((x) << S_DBFIFO_LP_INT) #define F_DBFIFO_LP_INT V_DBFIFO_LP_INT(1U) #define S_INGRESS_SIZE_ERR 5 #define V_INGRESS_SIZE_ERR(x) ((x) << S_INGRESS_SIZE_ERR) #define F_INGRESS_SIZE_ERR V_INGRESS_SIZE_ERR(1U) #define S_EGRESS_SIZE_ERR 4 #define V_EGRESS_SIZE_ERR(x) ((x) << S_EGRESS_SIZE_ERR) #define F_EGRESS_SIZE_ERR V_EGRESS_SIZE_ERR(1U) #define A_SGE_INT_ENABLE3 0x1040 #define A_SGE_FL_BUFFER_SIZE0 0x1044 #define A_SGE_FL_BUFFER_SIZE1 0x1048 #define A_SGE_FL_BUFFER_SIZE2 0x104c #define A_SGE_FL_BUFFER_SIZE3 0x1050 #define A_SGE_CONM_CTRL 0x1094 #define S_EGRTHRESHOLD 8 #define M_EGRTHRESHOLD 0x3fU #define V_EGRTHRESHOLD(x) ((x) << S_EGRTHRESHOLD) #define G_EGRTHRESHOLD(x) (((x) >> S_EGRTHRESHOLD) & M_EGRTHRESHOLD) #define S_EGRTHRESHOLDPACKING 14 #define M_EGRTHRESHOLDPACKING 0x3fU #define V_EGRTHRESHOLDPACKING(x) ((x) << S_EGRTHRESHOLDPACKING) #define G_EGRTHRESHOLDPACKING(x) (((x) >> S_EGRTHRESHOLDPACKING) & \ M_EGRTHRESHOLDPACKING) #define S_INGTHRESHOLD 2 #define M_INGTHRESHOLD 0x3fU #define V_INGTHRESHOLD(x) ((x) << S_INGTHRESHOLD) #define G_INGTHRESHOLD(x) (((x) >> S_INGTHRESHOLD) & M_INGTHRESHOLD) #define A_SGE_INGRESS_RX_THRESHOLD 0x10a0 #define S_THRESHOLD_0 24 #define M_THRESHOLD_0 0x3fU #define V_THRESHOLD_0(x) ((x) << S_THRESHOLD_0) #define G_THRESHOLD_0(x) (((x) >> S_THRESHOLD_0) & M_THRESHOLD_0) #define S_THRESHOLD_1 16 #define M_THRESHOLD_1 0x3fU #define V_THRESHOLD_1(x) ((x) << S_THRESHOLD_1) #define G_THRESHOLD_1(x) (((x) >> S_THRESHOLD_1) & M_THRESHOLD_1) #define S_THRESHOLD_2 8 #define M_THRESHOLD_2 0x3fU #define V_THRESHOLD_2(x) ((x) << S_THRESHOLD_2) #define G_THRESHOLD_2(x) (((x) >> S_THRESHOLD_2) & M_THRESHOLD_2) #define S_THRESHOLD_3 0 #define M_THRESHOLD_3 0x3fU #define V_THRESHOLD_3(x) ((x) << S_THRESHOLD_3) #define G_THRESHOLD_3(x) (((x) >> S_THRESHOLD_3) & M_THRESHOLD_3) #define A_SGE_TIMER_VALUE_0_AND_1 0x10b8 #define S_TIMERVALUE0 16 #define M_TIMERVALUE0 0xffffU #define V_TIMERVALUE0(x) ((x) << S_TIMERVALUE0) #define G_TIMERVALUE0(x) (((x) >> S_TIMERVALUE0) & M_TIMERVALUE0) #define S_TIMERVALUE1 0 #define M_TIMERVALUE1 0xffffU #define V_TIMERVALUE1(x) ((x) << S_TIMERVALUE1) #define G_TIMERVALUE1(x) (((x) >> S_TIMERVALUE1) & M_TIMERVALUE1) #define A_SGE_TIMER_VALUE_2_AND_3 0x10bc #define S_TIMERVALUE2 16 #define M_TIMERVALUE2 0xffffU #define V_TIMERVALUE2(x) ((x) << S_TIMERVALUE2) #define G_TIMERVALUE2(x) (((x) >> S_TIMERVALUE2) & M_TIMERVALUE2) #define S_TIMERVALUE3 0 #define M_TIMERVALUE3 0xffffU #define V_TIMERVALUE3(x) ((x) << S_TIMERVALUE3) #define G_TIMERVALUE3(x) (((x) >> S_TIMERVALUE3) & M_TIMERVALUE3) #define A_SGE_TIMER_VALUE_4_AND_5 0x10c0 #define S_TIMERVALUE4 16 #define M_TIMERVALUE4 0xffffU #define V_TIMERVALUE4(x) ((x) << S_TIMERVALUE4) #define G_TIMERVALUE4(x) (((x) >> S_TIMERVALUE4) & M_TIMERVALUE4) #define S_TIMERVALUE5 0 #define M_TIMERVALUE5 0xffffU #define V_TIMERVALUE5(x) ((x) << S_TIMERVALUE5) #define G_TIMERVALUE5(x) (((x) >> S_TIMERVALUE5) & M_TIMERVALUE5) #define A_SGE_DEBUG_INDEX 0x10cc #define A_SGE_DEBUG_DATA_HIGH 0x10d0 #define A_SGE_DEBUG_DATA_LOW 0x10d4 #define A_SGE_STAT_CFG 0x10ec #define S_STATMODE 2 #define M_STATMODE 0x3U #define V_STATMODE(x) ((x) << S_STATMODE) #define G_STATMODE(x) (((x) >> S_STATMODE) & M_STATMODE) #define S_STATSOURCE_T5 9 #define M_STATSOURCE_T5 0xfU #define V_STATSOURCE_T5(x) ((x) << S_STATSOURCE_T5) #define G_STATSOURCE_T5(x) (((x) >> S_STATSOURCE_T5) & M_STATSOURCE_T5) #define A_SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4 #define A_SGE_CONTROL2 0x1124 #define S_INGPACKBOUNDARY 16 #define M_INGPACKBOUNDARY 0x7U #define V_INGPACKBOUNDARY(x) ((x) << S_INGPACKBOUNDARY) #define G_INGPACKBOUNDARY(x) (((x) >> S_INGPACKBOUNDARY) & M_INGPACKBOUNDARY) #define S_BUSY 31 #define V_BUSY(x) ((x) << S_BUSY) #define F_BUSY V_BUSY(1U) #define A_SGE_DEBUG_DATA_HIGH_INDEX_10 0x12a8 #define A_SGE_DEBUG_DATA_LOW_INDEX_2 0x12c8 #define A_SGE_DEBUG_DATA_LOW_INDEX_3 0x12cc /* registers for module PCIE */ #define PCIE_BASE_ADDR 0x3000 #define A_PCIE_MEM_ACCESS_BASE_WIN 0x3068 #define S_PCIEOFST 10 #define M_PCIEOFST 0x3fffffU #define V_PCIEOFST(x) ((x) << S_PCIEOFST) #define G_PCIEOFST(x) (((x) >> S_PCIEOFST) & M_PCIEOFST) #define S_BIR 8 #define M_BIR 0x3U #define V_BIR(x) ((x) << S_BIR) #define G_BIR(x) (((x) >> S_BIR) & M_BIR) #define S_WINDOW 0 #define M_WINDOW 0xffU #define V_WINDOW(x) ((x) << S_WINDOW) #define G_WINDOW(x) (((x) >> S_WINDOW) & M_WINDOW) #define A_PCIE_MEM_ACCESS_OFFSET 0x306c #define S_PFNUM 0 #define M_PFNUM 0x7U #define V_PFNUM(x) ((x) << S_PFNUM) #define G_PFNUM(x) (((x) >> S_PFNUM) & M_PFNUM) #define A_PCIE_FW 0x30b8 #define A_PCIE_FW_PF 0x30bc /* registers for module CIM */ #define CIM_BASE_ADDR 0x7b00 #define A_CIM_PF_MAILBOX_DATA 0x240 #define A_CIM_PF_MAILBOX_CTRL 0x280 #define S_MBMSGVALID 3 #define V_MBMSGVALID(x) ((x) << S_MBMSGVALID) #define F_MBMSGVALID V_MBMSGVALID(1U) #define S_MBOWNER 0 #define M_MBOWNER 0x3U #define V_MBOWNER(x) ((x) << S_MBOWNER) #define G_MBOWNER(x) (((x) >> S_MBOWNER) & M_MBOWNER) #define A_CIM_PF_MAILBOX_CTRL_SHADOW_COPY 0x290 #define A_CIM_BOOT_CFG 0x7b00 #define S_UPCRST 0 #define V_UPCRST(x) ((x) << S_UPCRST) #define F_UPCRST V_UPCRST(1U) /* registers for module TP */ #define TP_BASE_ADDR 0x7d00 #define A_TP_TIMER_RESOLUTION 0x7d90 #define S_TIMERRESOLUTION 16 #define M_TIMERRESOLUTION 0xffU #define V_TIMERRESOLUTION(x) ((x) << S_TIMERRESOLUTION) #define G_TIMERRESOLUTION(x) (((x) >> S_TIMERRESOLUTION) & M_TIMERRESOLUTION) #define S_DELAYEDACKRESOLUTION 0 #define M_DELAYEDACKRESOLUTION 0xffU #define V_DELAYEDACKRESOLUTION(x) ((x) << S_DELAYEDACKRESOLUTION) #define G_DELAYEDACKRESOLUTION(x) (((x) >> S_DELAYEDACKRESOLUTION) & \ M_DELAYEDACKRESOLUTION) #define A_TP_CCTRL_TABLE 0x7ddc #define A_TP_MTU_TABLE 0x7de4 #define S_MTUINDEX 24 #define M_MTUINDEX 0xffU #define V_MTUINDEX(x) ((x) << S_MTUINDEX) #define G_MTUINDEX(x) (((x) >> S_MTUINDEX) & M_MTUINDEX) #define S_MTUWIDTH 16 #define M_MTUWIDTH 0xfU #define V_MTUWIDTH(x) ((x) << S_MTUWIDTH) #define G_MTUWIDTH(x) (((x) >> S_MTUWIDTH) & M_MTUWIDTH) #define S_MTUVALUE 0 #define M_MTUVALUE 0x3fffU #define V_MTUVALUE(x) ((x) << S_MTUVALUE) #define G_MTUVALUE(x) (((x) >> S_MTUVALUE) & M_MTUVALUE) #define A_TP_PIO_ADDR 0x7e40 #define A_TP_PIO_DATA 0x7e44 #define A_TP_VLAN_PRI_MAP 0x140 #define S_FRAGMENTATION 9 #define V_FRAGMENTATION(x) ((x) << S_FRAGMENTATION) #define F_FRAGMENTATION V_FRAGMENTATION(1U) #define S_MPSHITTYPE 8 #define V_MPSHITTYPE(x) ((x) << S_MPSHITTYPE) #define F_MPSHITTYPE V_MPSHITTYPE(1U) #define S_MACMATCH 7 #define V_MACMATCH(x) ((x) << S_MACMATCH) #define F_MACMATCH V_MACMATCH(1U) #define S_ETHERTYPE 6 #define V_ETHERTYPE(x) ((x) << S_ETHERTYPE) #define F_ETHERTYPE V_ETHERTYPE(1U) #define S_PROTOCOL 5 #define V_PROTOCOL(x) ((x) << S_PROTOCOL) #define F_PROTOCOL V_PROTOCOL(1U) #define S_TOS 4 #define V_TOS(x) ((x) << S_TOS) #define F_TOS V_TOS(1U) #define S_VLAN 3 #define V_VLAN(x) ((x) << S_VLAN) #define F_VLAN V_VLAN(1U) #define S_VNIC_ID 2 #define V_VNIC_ID(x) ((x) << S_VNIC_ID) #define F_VNIC_ID V_VNIC_ID(1U) #define S_PORT 1 #define V_PORT(x) ((x) << S_PORT) #define F_PORT V_PORT(1U) #define S_FCOE 0 #define V_FCOE(x) ((x) << S_FCOE) #define F_FCOE V_FCOE(1U) #define A_TP_INGRESS_CONFIG 0x141 #define S_VNIC 11 #define V_VNIC(x) ((x) << S_VNIC) #define F_VNIC V_VNIC(1U) #define S_CSUM_HAS_PSEUDO_HDR 10 #define V_CSUM_HAS_PSEUDO_HDR(x) ((x) << S_CSUM_HAS_PSEUDO_HDR) #define F_CSUM_HAS_PSEUDO_HDR V_CSUM_HAS_PSEUDO_HDR(1U) /* registers for module MPS */ #define MPS_BASE_ADDR 0x9000 #define S_REPLICATE 11 #define V_REPLICATE(x) ((x) << S_REPLICATE) #define F_REPLICATE V_REPLICATE(1U) #define S_PF 8 #define M_PF 0x7U #define V_PF(x) ((x) << S_PF) #define G_PF(x) (((x) >> S_PF) & M_PF) #define S_VF_VALID 7 #define V_VF_VALID(x) ((x) << S_VF_VALID) #define F_VF_VALID V_VF_VALID(1U) #define S_VF 0 #define M_VF 0x7fU #define V_VF(x) ((x) << S_VF) #define G_VF(x) (((x) >> S_VF) & M_VF) #define A_MPS_PORT_STAT_TX_PORT_BYTES_L 0x400 #define A_MPS_PORT_STAT_TX_PORT_BYTES_H 0x404 #define A_MPS_PORT_STAT_TX_PORT_FRAMES_L 0x408 #define A_MPS_PORT_STAT_TX_PORT_FRAMES_H 0x40c #define A_MPS_PORT_STAT_TX_PORT_BCAST_L 0x410 #define A_MPS_PORT_STAT_TX_PORT_BCAST_H 0x414 #define A_MPS_PORT_STAT_TX_PORT_MCAST_L 0x418 #define A_MPS_PORT_STAT_TX_PORT_MCAST_H 0x41c #define A_MPS_PORT_STAT_TX_PORT_UCAST_L 0x420 #define A_MPS_PORT_STAT_TX_PORT_UCAST_H 0x424 #define A_MPS_PORT_STAT_TX_PORT_ERROR_L 0x428 #define A_MPS_PORT_STAT_TX_PORT_ERROR_H 0x42c #define A_MPS_PORT_STAT_TX_PORT_64B_L 0x430 #define A_MPS_PORT_STAT_TX_PORT_64B_H 0x434 #define A_MPS_PORT_STAT_TX_PORT_65B_127B_L 0x438 #define A_MPS_PORT_STAT_TX_PORT_65B_127B_H 0x43c #define A_MPS_PORT_STAT_TX_PORT_128B_255B_L 0x440 #define A_MPS_PORT_STAT_TX_PORT_128B_255B_H 0x444 #define A_MPS_PORT_STAT_TX_PORT_256B_511B_L 0x448 #define A_MPS_PORT_STAT_TX_PORT_256B_511B_H 0x44c #define A_MPS_PORT_STAT_TX_PORT_512B_1023B_L 0x450 #define A_MPS_PORT_STAT_TX_PORT_512B_1023B_H 0x454 #define A_MPS_PORT_STAT_TX_PORT_1024B_1518B_L 0x458 #define A_MPS_PORT_STAT_TX_PORT_1024B_1518B_H 0x45c #define A_MPS_PORT_STAT_TX_PORT_1519B_MAX_L 0x460 #define A_MPS_PORT_STAT_TX_PORT_1519B_MAX_H 0x464 #define A_MPS_PORT_STAT_TX_PORT_DROP_L 0x468 #define A_MPS_PORT_STAT_TX_PORT_DROP_H 0x46c #define A_MPS_PORT_STAT_TX_PORT_PAUSE_L 0x470 #define A_MPS_PORT_STAT_TX_PORT_PAUSE_H 0x474 #define A_MPS_PORT_STAT_TX_PORT_PPP0_L 0x478 #define A_MPS_PORT_STAT_TX_PORT_PPP0_H 0x47c #define A_MPS_PORT_STAT_TX_PORT_PPP1_L 0x480 #define A_MPS_PORT_STAT_TX_PORT_PPP1_H 0x484 #define A_MPS_PORT_STAT_TX_PORT_PPP2_L 0x488 #define A_MPS_PORT_STAT_TX_PORT_PPP2_H 0x48c #define A_MPS_PORT_STAT_TX_PORT_PPP3_L 0x490 #define A_MPS_PORT_STAT_TX_PORT_PPP3_H 0x494 #define A_MPS_PORT_STAT_TX_PORT_PPP4_L 0x498 #define A_MPS_PORT_STAT_TX_PORT_PPP4_H 0x49c #define A_MPS_PORT_STAT_TX_PORT_PPP5_L 0x4a0 #define A_MPS_PORT_STAT_TX_PORT_PPP5_H 0x4a4 #define A_MPS_PORT_STAT_TX_PORT_PPP6_L 0x4a8 #define A_MPS_PORT_STAT_TX_PORT_PPP6_H 0x4ac #define A_MPS_PORT_STAT_TX_PORT_PPP7_L 0x4b0 #define A_MPS_PORT_STAT_TX_PORT_PPP7_H 0x4b4 #define A_MPS_PORT_STAT_LB_PORT_BYTES_L 0x4c0 #define A_MPS_PORT_STAT_LB_PORT_BYTES_H 0x4c4 #define A_MPS_PORT_STAT_LB_PORT_FRAMES_L 0x4c8 #define A_MPS_PORT_STAT_LB_PORT_FRAMES_H 0x4cc #define A_MPS_PORT_STAT_LB_PORT_BCAST_L 0x4d0 #define A_MPS_PORT_STAT_LB_PORT_BCAST_H 0x4d4 #define A_MPS_PORT_STAT_LB_PORT_MCAST_L 0x4d8 #define A_MPS_PORT_STAT_LB_PORT_MCAST_H 0x4dc #define A_MPS_PORT_STAT_LB_PORT_UCAST_L 0x4e0 #define A_MPS_PORT_STAT_LB_PORT_UCAST_H 0x4e4 #define A_MPS_PORT_STAT_LB_PORT_ERROR_L 0x4e8 #define A_MPS_PORT_STAT_LB_PORT_ERROR_H 0x4ec #define A_MPS_PORT_STAT_LB_PORT_64B_L 0x4f0 #define A_MPS_PORT_STAT_LB_PORT_64B_H 0x4f4 #define A_MPS_PORT_STAT_LB_PORT_65B_127B_L 0x4f8 #define A_MPS_PORT_STAT_LB_PORT_65B_127B_H 0x4fc #define A_MPS_PORT_STAT_LB_PORT_128B_255B_L 0x500 #define A_MPS_PORT_STAT_LB_PORT_128B_255B_H 0x504 #define A_MPS_PORT_STAT_LB_PORT_256B_511B_L 0x508 #define A_MPS_PORT_STAT_LB_PORT_256B_511B_H 0x50c #define A_MPS_PORT_STAT_LB_PORT_512B_1023B_L 0x510 #define A_MPS_PORT_STAT_LB_PORT_512B_1023B_H 0x514 #define A_MPS_PORT_STAT_LB_PORT_1024B_1518B_L 0x518 #define A_MPS_PORT_STAT_LB_PORT_1024B_1518B_H 0x51c #define A_MPS_PORT_STAT_LB_PORT_1519B_MAX_L 0x520 #define A_MPS_PORT_STAT_LB_PORT_1519B_MAX_H 0x524 #define A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES 0x528 #define A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES_L 0x528 #define A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES_H 0x52c #define A_MPS_PORT_STAT_RX_PORT_BYTES_L 0x540 #define A_MPS_PORT_STAT_RX_PORT_BYTES_H 0x544 #define A_MPS_PORT_STAT_RX_PORT_FRAMES_L 0x548 #define A_MPS_PORT_STAT_RX_PORT_FRAMES_H 0x54c #define A_MPS_PORT_STAT_RX_PORT_BCAST_L 0x550 #define A_MPS_PORT_STAT_RX_PORT_BCAST_H 0x554 #define A_MPS_PORT_STAT_RX_PORT_MCAST_L 0x558 #define A_MPS_PORT_STAT_RX_PORT_MCAST_H 0x55c #define A_MPS_PORT_STAT_RX_PORT_UCAST_L 0x560 #define A_MPS_PORT_STAT_RX_PORT_UCAST_H 0x564 #define A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L 0x568 #define A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_H 0x56c #define A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L 0x570 #define A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_H 0x574 #define A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L 0x578 #define A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_H 0x57c #define A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L 0x580 #define A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_H 0x584 #define A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L 0x588 #define A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_H 0x58c #define A_MPS_PORT_STAT_RX_PORT_64B_L 0x590 #define A_MPS_PORT_STAT_RX_PORT_64B_H 0x594 #define A_MPS_PORT_STAT_RX_PORT_65B_127B_L 0x598 #define A_MPS_PORT_STAT_RX_PORT_65B_127B_H 0x59c #define A_MPS_PORT_STAT_RX_PORT_128B_255B_L 0x5a0 #define A_MPS_PORT_STAT_RX_PORT_128B_255B_H 0x5a4 #define A_MPS_PORT_STAT_RX_PORT_256B_511B_L 0x5a8 #define A_MPS_PORT_STAT_RX_PORT_256B_511B_H 0x5ac #define A_MPS_PORT_STAT_RX_PORT_512B_1023B_L 0x5b0 #define A_MPS_PORT_STAT_RX_PORT_512B_1023B_H 0x5b4 #define A_MPS_PORT_STAT_RX_PORT_1024B_1518B_L 0x5b8 #define A_MPS_PORT_STAT_RX_PORT_1024B_1518B_H 0x5bc #define A_MPS_PORT_STAT_RX_PORT_1519B_MAX_L 0x5c0 #define A_MPS_PORT_STAT_RX_PORT_1519B_MAX_H 0x5c4 #define A_MPS_PORT_STAT_RX_PORT_PAUSE_L 0x5c8 #define A_MPS_PORT_STAT_RX_PORT_PAUSE_H 0x5cc #define A_MPS_PORT_STAT_RX_PORT_PPP0_L 0x5d0 #define A_MPS_PORT_STAT_RX_PORT_PPP0_H 0x5d4 #define A_MPS_PORT_STAT_RX_PORT_PPP1_L 0x5d8 #define A_MPS_PORT_STAT_RX_PORT_PPP1_H 0x5dc #define A_MPS_PORT_STAT_RX_PORT_PPP2_L 0x5e0 #define A_MPS_PORT_STAT_RX_PORT_PPP2_H 0x5e4 #define A_MPS_PORT_STAT_RX_PORT_PPP3_L 0x5e8 #define A_MPS_PORT_STAT_RX_PORT_PPP3_H 0x5ec #define A_MPS_PORT_STAT_RX_PORT_PPP4_L 0x5f0 #define A_MPS_PORT_STAT_RX_PORT_PPP4_H 0x5f4 #define A_MPS_PORT_STAT_RX_PORT_PPP5_L 0x5f8 #define A_MPS_PORT_STAT_RX_PORT_PPP5_H 0x5fc #define A_MPS_PORT_STAT_RX_PORT_PPP6_L 0x600 #define A_MPS_PORT_STAT_RX_PORT_PPP6_H 0x604 #define A_MPS_PORT_STAT_RX_PORT_PPP7_L 0x608 #define A_MPS_PORT_STAT_RX_PORT_PPP7_H 0x60c #define A_MPS_PORT_STAT_RX_PORT_LESS_64B_L 0x610 #define A_MPS_PORT_STAT_RX_PORT_LESS_64B_H 0x614 #define A_MPS_CMN_CTL 0x9000 #define S_NUMPORTS 0 #define M_NUMPORTS 0x3U #define V_NUMPORTS(x) ((x) << S_NUMPORTS) #define G_NUMPORTS(x) (((x) >> S_NUMPORTS) & M_NUMPORTS) #define A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L 0x9640 #define A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_H 0x9644 #define A_MPS_STAT_RX_BG_1_MAC_DROP_FRAME_L 0x9648 #define A_MPS_STAT_RX_BG_1_MAC_DROP_FRAME_H 0x964c #define A_MPS_STAT_RX_BG_2_MAC_DROP_FRAME_L 0x9650 #define A_MPS_STAT_RX_BG_2_MAC_DROP_FRAME_H 0x9654 #define A_MPS_STAT_RX_BG_3_MAC_DROP_FRAME_L 0x9658 #define A_MPS_STAT_RX_BG_3_MAC_DROP_FRAME_H 0x965c #define A_MPS_STAT_RX_BG_0_LB_DROP_FRAME_L 0x9660 #define A_MPS_STAT_RX_BG_0_LB_DROP_FRAME_H 0x9664 #define A_MPS_STAT_RX_BG_1_LB_DROP_FRAME_L 0x9668 #define A_MPS_STAT_RX_BG_1_LB_DROP_FRAME_H 0x966c #define A_MPS_STAT_RX_BG_2_LB_DROP_FRAME_L 0x9670 #define A_MPS_STAT_RX_BG_2_LB_DROP_FRAME_H 0x9674 #define A_MPS_STAT_RX_BG_3_LB_DROP_FRAME_L 0x9678 #define A_MPS_STAT_RX_BG_3_LB_DROP_FRAME_H 0x967c #define A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L 0x9680 #define A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_H 0x9684 #define A_MPS_STAT_RX_BG_1_MAC_TRUNC_FRAME_L 0x9688 #define A_MPS_STAT_RX_BG_1_MAC_TRUNC_FRAME_H 0x968c #define A_MPS_STAT_RX_BG_2_MAC_TRUNC_FRAME_L 0x9690 #define A_MPS_STAT_RX_BG_2_MAC_TRUNC_FRAME_H 0x9694 #define A_MPS_STAT_RX_BG_3_MAC_TRUNC_FRAME_L 0x9698 #define A_MPS_STAT_RX_BG_3_MAC_TRUNC_FRAME_H 0x969c #define A_MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_L 0x96a0 #define A_MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_H 0x96a4 #define A_MPS_STAT_RX_BG_1_LB_TRUNC_FRAME_L 0x96a8 #define A_MPS_STAT_RX_BG_1_LB_TRUNC_FRAME_H 0x96ac #define A_MPS_STAT_RX_BG_2_LB_TRUNC_FRAME_L 0x96b0 #define A_MPS_STAT_RX_BG_2_LB_TRUNC_FRAME_H 0x96b4 #define A_MPS_STAT_RX_BG_3_LB_TRUNC_FRAME_L 0x96b8 #define A_MPS_STAT_RX_BG_3_LB_TRUNC_FRAME_H 0x96bc /* registers for module ULP_RX */ #define ULP_RX_BASE_ADDR 0x19150 #define S_HPZ0 0 #define M_HPZ0 0xfU #define V_HPZ0(x) ((x) << S_HPZ0) #define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0) #define A_ULP_RX_TDDP_PSZ 0x19178 /* registers for module SF */ #define SF_BASE_ADDR 0x193f8 #define A_SF_DATA 0x193f8 #define A_SF_OP 0x193fc #define S_SF_LOCK 4 #define V_SF_LOCK(x) ((x) << S_SF_LOCK) #define F_SF_LOCK V_SF_LOCK(1U) #define S_CONT 3 #define V_CONT(x) ((x) << S_CONT) #define F_CONT V_CONT(1U) #define S_BYTECNT 1 #define M_BYTECNT 0x3U #define V_BYTECNT(x) ((x) << S_BYTECNT) #define G_BYTECNT(x) (((x) >> S_BYTECNT) & M_BYTECNT) #define S_OP 0 #define V_OP(x) ((x) << S_OP) #define F_OP V_OP(1U) /* registers for module PL */ #define PL_BASE_ADDR 0x19400 #define S_SOURCEPF 8 #define M_SOURCEPF 0x7U #define V_SOURCEPF(x) ((x) << S_SOURCEPF) #define G_SOURCEPF(x) (((x) >> S_SOURCEPF) & M_SOURCEPF) #define A_PL_PF_INT_ENABLE 0x3c4 #define S_PFSW 3 #define V_PFSW(x) ((x) << S_PFSW) #define F_PFSW V_PFSW(1U) #define S_PFCIM 1 #define V_PFCIM(x) ((x) << S_PFCIM) #define F_PFCIM V_PFCIM(1U) #define A_PL_WHOAMI 0x19400 #define A_PL_RST 0x19428 #define A_PL_INT_MAP0 0x19414 #define S_PIORST 1 #define V_PIORST(x) ((x) << S_PIORST) #define F_PIORST V_PIORST(1U) #define S_PIORSTMODE 0 #define V_PIORSTMODE(x) ((x) << S_PIORSTMODE) #define F_PIORSTMODE V_PIORSTMODE(1U) #define A_PL_REV 0x1943c #define S_REV 0 #define M_REV 0xfU #define V_REV(x) ((x) << S_REV) #define G_REV(x) (((x) >> S_REV) & M_REV) ================================================ FILE: drivers/net/cxgbe/base/t4_regs_values.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __T4_REGS_VALUES_H__ #define __T4_REGS_VALUES_H__ /* * This file contains definitions for various T4 register value hardware * constants. The types of values encoded here are predominantly those for * register fields which control "modal" behavior. For the most part, we do * not include definitions for register fields which are simple numeric * metrics, etc. */ /* * SGE definitions. * ================ */ /* * SGE register field values. */ /* CONTROL register */ #define X_RXPKTCPLMODE_SPLIT 1 #define X_INGPCIEBOUNDARY_32B 0 #define X_INGPADBOUNDARY_SHIFT 5 /* CONTROL2 register */ #define X_INGPACKBOUNDARY_SHIFT 5 #define X_INGPACKBOUNDARY_16B 0 /* GTS register */ #define X_TIMERREG_RESTART_COUNTER 6 #define X_TIMERREG_UPDATE_CIDX 7 /* * Egress Context field values */ #define X_FETCHBURSTMIN_64B 2 #define X_FETCHBURSTMIN_128B 3 #define X_FETCHBURSTMAX_256B 2 #define X_FETCHBURSTMAX_512B 3 #define X_HOSTFCMODE_NONE 0 /* * Ingress Context field values */ #define X_UPDATEDELIVERY_INTERRUPT 1 #define X_RSPD_TYPE_FLBUF 0 #define X_RSPD_TYPE_CPL 1 /* * Context field definitions. This is by no means a complete list of SGE * Context fields. In the vast majority of cases the firmware initializes * things the way they need to be set up. But in a few small cases, we need * to compute new values and ship them off to the firmware to be applied to * the SGE Conexts ... */ /* * Congestion Manager Definitions. */ #define S_CONMCTXT_CNGTPMODE 19 #define M_CONMCTXT_CNGTPMODE 0x3 #define V_CONMCTXT_CNGTPMODE(x) ((x) << S_CONMCTXT_CNGTPMODE) #define G_CONMCTXT_CNGTPMODE(x) \ (((x) >> S_CONMCTXT_CNGTPMODE) & M_CONMCTXT_CNGTPMODE) #define S_CONMCTXT_CNGCHMAP 0 #define M_CONMCTXT_CNGCHMAP 0xffff #define V_CONMCTXT_CNGCHMAP(x) ((x) << S_CONMCTXT_CNGCHMAP) #define G_CONMCTXT_CNGCHMAP(x) \ (((x) >> S_CONMCTXT_CNGCHMAP) & M_CONMCTXT_CNGCHMAP) #define X_CONMCTXT_CNGTPMODE_QUEUE 1 #define X_CONMCTXT_CNGTPMODE_CHANNEL 2 /* * T5 and later support a new BAR2-based doorbell mechanism for Egress Queues. * The User Doorbells are each 128 bytes in length with a Simple Doorbell at * offsets 8x and a Write Combining single 64-byte Egress Queue Unit * (X_IDXSIZE_UNIT) Gather Buffer interface at offset 64. For Ingress Queues, * we have a Going To Sleep register at offsets 8x+4. * * As noted above, we have many instances of the Simple Doorbell and Going To * Sleep registers at offsets 8x and 8x+4, respectively. We want to use a * non-64-byte aligned offset for the Simple Doorbell in order to attempt to * avoid buffering of the writes to the Simple Doorbell and we want to use a * non-contiguous offset for the Going To Sleep writes in order to avoid * possible combining between them. */ #define SGE_UDB_SIZE 128 #define SGE_UDB_KDOORBELL 8 #define SGE_UDB_GTS 20 /* * CIM definitions. * ================ */ /* * CIM register field values. */ #define X_MBOWNER_NONE 0 #define X_MBOWNER_FW 1 #define X_MBOWNER_PL 2 /* * PCI-E definitions. * ================== */ #define X_WINDOW_SHIFT 10 #define X_PCIEOFST_SHIFT 10 /* * TP definitions. * =============== */ /* * TP_VLAN_PRI_MAP controls which subset of fields will be present in the * Compressed Filter Tuple for LE filters. Each bit set in TP_VLAN_PRI_MAP * selects for a particular field being present. These fields, when present * in the Compressed Filter Tuple, have the following widths in bits. */ #define W_FT_FCOE 1 #define W_FT_PORT 3 #define W_FT_VNIC_ID 17 #define W_FT_VLAN 17 #define W_FT_TOS 8 #define W_FT_PROTOCOL 8 #define W_FT_ETHERTYPE 16 #define W_FT_MACMATCH 9 #define W_FT_MPSHITTYPE 3 #define W_FT_FRAGMENTATION 1 #endif /* __T4_REGS_VALUES_H__ */ ================================================ FILE: drivers/net/cxgbe/base/t4fw_interface.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _T4FW_INTERFACE_H_ #define _T4FW_INTERFACE_H_ /****************************************************************************** * R E T U R N V A L U E S ********************************/ enum fw_retval { FW_SUCCESS = 0, /* completed successfully */ FW_EPERM = 1, /* operation not permitted */ FW_ENOENT = 2, /* no such file or directory */ FW_EIO = 5, /* input/output error; hw bad */ FW_ENOEXEC = 8, /* exec format error; inv microcode */ FW_EAGAIN = 11, /* try again */ FW_ENOMEM = 12, /* out of memory */ FW_EFAULT = 14, /* bad address; fw bad */ FW_EBUSY = 16, /* resource busy */ FW_EEXIST = 17, /* file exists */ FW_ENODEV = 19, /* no such device */ FW_EINVAL = 22, /* invalid argument */ FW_ENOSPC = 28, /* no space left on device */ FW_ENOSYS = 38, /* functionality not implemented */ FW_ENODATA = 61, /* no data available */ FW_EPROTO = 71, /* protocol error */ FW_EADDRINUSE = 98, /* address already in use */ FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ FW_ENETDOWN = 100, /* network is down */ FW_ENETUNREACH = 101, /* network is unreachable */ FW_ENOBUFS = 105, /* no buffer space available */ FW_ETIMEDOUT = 110, /* timeout */ FW_EINPROGRESS = 115, /* fw internal */ }; /****************************************************************************** * M E M O R Y T Y P E s ******************************/ enum fw_memtype { FW_MEMTYPE_EDC0 = 0x0, FW_MEMTYPE_EDC1 = 0x1, FW_MEMTYPE_EXTMEM = 0x2, FW_MEMTYPE_FLASH = 0x4, FW_MEMTYPE_INTERNAL = 0x5, FW_MEMTYPE_EXTMEM1 = 0x6, }; /****************************************************************************** * W O R K R E Q U E S T s ********************************/ enum fw_wr_opcodes { FW_ETH_TX_PKT_WR = 0x08, FW_ETH_TX_PKTS_WR = 0x09, }; /* * Generic work request header flit0 */ struct fw_wr_hdr { __be32 hi; __be32 lo; }; /* work request opcode (hi) */ #define S_FW_WR_OP 24 #define M_FW_WR_OP 0xff #define V_FW_WR_OP(x) ((x) << S_FW_WR_OP) #define G_FW_WR_OP(x) (((x) >> S_FW_WR_OP) & M_FW_WR_OP) /* work request immediate data length (hi) */ #define S_FW_WR_IMMDLEN 0 #define M_FW_WR_IMMDLEN 0xff #define V_FW_WR_IMMDLEN(x) ((x) << S_FW_WR_IMMDLEN) #define G_FW_WR_IMMDLEN(x) \ (((x) >> S_FW_WR_IMMDLEN) & M_FW_WR_IMMDLEN) /* egress queue status update to egress queue status entry (lo) */ #define S_FW_WR_EQUEQ 30 #define M_FW_WR_EQUEQ 0x1 #define V_FW_WR_EQUEQ(x) ((x) << S_FW_WR_EQUEQ) #define G_FW_WR_EQUEQ(x) (((x) >> S_FW_WR_EQUEQ) & M_FW_WR_EQUEQ) #define F_FW_WR_EQUEQ V_FW_WR_EQUEQ(1U) /* length in units of 16-bytes (lo) */ #define S_FW_WR_LEN16 0 #define M_FW_WR_LEN16 0xff #define V_FW_WR_LEN16(x) ((x) << S_FW_WR_LEN16) #define G_FW_WR_LEN16(x) (((x) >> S_FW_WR_LEN16) & M_FW_WR_LEN16) struct fw_eth_tx_pkt_wr { __be32 op_immdlen; __be32 equiq_to_len16; __be64 r3; }; #define S_FW_ETH_TX_PKT_WR_IMMDLEN 0 #define M_FW_ETH_TX_PKT_WR_IMMDLEN 0x1ff #define V_FW_ETH_TX_PKT_WR_IMMDLEN(x) ((x) << S_FW_ETH_TX_PKT_WR_IMMDLEN) #define G_FW_ETH_TX_PKT_WR_IMMDLEN(x) \ (((x) >> S_FW_ETH_TX_PKT_WR_IMMDLEN) & M_FW_ETH_TX_PKT_WR_IMMDLEN) struct fw_eth_tx_pkts_wr { __be32 op_pkd; __be32 equiq_to_len16; __be32 r3; __be16 plen; __u8 npkt; __u8 type; }; /****************************************************************************** * C O M M A N D s *********************/ /* * The maximum length of time, in miliseconds, that we expect any firmware * command to take to execute and return a reply to the host. The RESET * and INITIALIZE commands can take a fair amount of time to execute but * most execute in far less time than this maximum. This constant is used * by host software to determine how long to wait for a firmware command * reply before declaring the firmware as dead/unreachable ... */ #define FW_CMD_MAX_TIMEOUT 10000 /* * If a host driver does a HELLO and discovers that there's already a MASTER * selected, we may have to wait for that MASTER to finish issuing RESET, * configuration and INITIALIZE commands. Also, there's a possibility that * our own HELLO may get lost if it happens right as the MASTER is issuign a * RESET command, so we need to be willing to make a few retries of our HELLO. */ #define FW_CMD_HELLO_TIMEOUT (3 * FW_CMD_MAX_TIMEOUT) #define FW_CMD_HELLO_RETRIES 3 enum fw_cmd_opcodes { FW_RESET_CMD = 0x03, FW_HELLO_CMD = 0x04, FW_BYE_CMD = 0x05, FW_INITIALIZE_CMD = 0x06, FW_CAPS_CONFIG_CMD = 0x07, FW_PARAMS_CMD = 0x08, FW_IQ_CMD = 0x10, FW_EQ_ETH_CMD = 0x12, FW_VI_CMD = 0x14, FW_VI_MAC_CMD = 0x15, FW_VI_RXMODE_CMD = 0x16, FW_VI_ENABLE_CMD = 0x17, FW_PORT_CMD = 0x1b, FW_RSS_IND_TBL_CMD = 0x20, FW_RSS_VI_CONFIG_CMD = 0x23, FW_DEBUG_CMD = 0x81, }; /* * Generic command header flit0 */ struct fw_cmd_hdr { __be32 hi; __be32 lo; }; #define S_FW_CMD_OP 24 #define M_FW_CMD_OP 0xff #define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP) #define G_FW_CMD_OP(x) (((x) >> S_FW_CMD_OP) & M_FW_CMD_OP) #define S_FW_CMD_REQUEST 23 #define M_FW_CMD_REQUEST 0x1 #define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST) #define G_FW_CMD_REQUEST(x) (((x) >> S_FW_CMD_REQUEST) & M_FW_CMD_REQUEST) #define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U) #define S_FW_CMD_READ 22 #define M_FW_CMD_READ 0x1 #define V_FW_CMD_READ(x) ((x) << S_FW_CMD_READ) #define G_FW_CMD_READ(x) (((x) >> S_FW_CMD_READ) & M_FW_CMD_READ) #define F_FW_CMD_READ V_FW_CMD_READ(1U) #define S_FW_CMD_WRITE 21 #define M_FW_CMD_WRITE 0x1 #define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE) #define G_FW_CMD_WRITE(x) (((x) >> S_FW_CMD_WRITE) & M_FW_CMD_WRITE) #define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U) #define S_FW_CMD_EXEC 20 #define M_FW_CMD_EXEC 0x1 #define V_FW_CMD_EXEC(x) ((x) << S_FW_CMD_EXEC) #define G_FW_CMD_EXEC(x) (((x) >> S_FW_CMD_EXEC) & M_FW_CMD_EXEC) #define F_FW_CMD_EXEC V_FW_CMD_EXEC(1U) #define S_FW_CMD_RETVAL 8 #define M_FW_CMD_RETVAL 0xff #define V_FW_CMD_RETVAL(x) ((x) << S_FW_CMD_RETVAL) #define G_FW_CMD_RETVAL(x) (((x) >> S_FW_CMD_RETVAL) & M_FW_CMD_RETVAL) #define S_FW_CMD_LEN16 0 #define M_FW_CMD_LEN16 0xff #define V_FW_CMD_LEN16(x) ((x) << S_FW_CMD_LEN16) #define G_FW_CMD_LEN16(x) (((x) >> S_FW_CMD_LEN16) & M_FW_CMD_LEN16) #define FW_LEN16(fw_struct) V_FW_CMD_LEN16(sizeof(fw_struct) / 16) struct fw_reset_cmd { __be32 op_to_write; __be32 retval_len16; __be32 val; __be32 halt_pkd; }; #define S_FW_RESET_CMD_HALT 31 #define M_FW_RESET_CMD_HALT 0x1 #define V_FW_RESET_CMD_HALT(x) ((x) << S_FW_RESET_CMD_HALT) #define G_FW_RESET_CMD_HALT(x) \ (((x) >> S_FW_RESET_CMD_HALT) & M_FW_RESET_CMD_HALT) #define F_FW_RESET_CMD_HALT V_FW_RESET_CMD_HALT(1U) enum { FW_HELLO_CMD_STAGE_OS = 0, }; struct fw_hello_cmd { __be32 op_to_write; __be32 retval_len16; __be32 err_to_clearinit; __be32 fwrev; }; #define S_FW_HELLO_CMD_ERR 31 #define M_FW_HELLO_CMD_ERR 0x1 #define V_FW_HELLO_CMD_ERR(x) ((x) << S_FW_HELLO_CMD_ERR) #define G_FW_HELLO_CMD_ERR(x) \ (((x) >> S_FW_HELLO_CMD_ERR) & M_FW_HELLO_CMD_ERR) #define F_FW_HELLO_CMD_ERR V_FW_HELLO_CMD_ERR(1U) #define S_FW_HELLO_CMD_INIT 30 #define M_FW_HELLO_CMD_INIT 0x1 #define V_FW_HELLO_CMD_INIT(x) ((x) << S_FW_HELLO_CMD_INIT) #define G_FW_HELLO_CMD_INIT(x) \ (((x) >> S_FW_HELLO_CMD_INIT) & M_FW_HELLO_CMD_INIT) #define F_FW_HELLO_CMD_INIT V_FW_HELLO_CMD_INIT(1U) #define S_FW_HELLO_CMD_MASTERDIS 29 #define M_FW_HELLO_CMD_MASTERDIS 0x1 #define V_FW_HELLO_CMD_MASTERDIS(x) ((x) << S_FW_HELLO_CMD_MASTERDIS) #define G_FW_HELLO_CMD_MASTERDIS(x) \ (((x) >> S_FW_HELLO_CMD_MASTERDIS) & M_FW_HELLO_CMD_MASTERDIS) #define F_FW_HELLO_CMD_MASTERDIS V_FW_HELLO_CMD_MASTERDIS(1U) #define S_FW_HELLO_CMD_MASTERFORCE 28 #define M_FW_HELLO_CMD_MASTERFORCE 0x1 #define V_FW_HELLO_CMD_MASTERFORCE(x) ((x) << S_FW_HELLO_CMD_MASTERFORCE) #define G_FW_HELLO_CMD_MASTERFORCE(x) \ (((x) >> S_FW_HELLO_CMD_MASTERFORCE) & M_FW_HELLO_CMD_MASTERFORCE) #define F_FW_HELLO_CMD_MASTERFORCE V_FW_HELLO_CMD_MASTERFORCE(1U) #define S_FW_HELLO_CMD_MBMASTER 24 #define M_FW_HELLO_CMD_MBMASTER 0xf #define V_FW_HELLO_CMD_MBMASTER(x) ((x) << S_FW_HELLO_CMD_MBMASTER) #define G_FW_HELLO_CMD_MBMASTER(x) \ (((x) >> S_FW_HELLO_CMD_MBMASTER) & M_FW_HELLO_CMD_MBMASTER) #define S_FW_HELLO_CMD_MBASYNCNOT 20 #define M_FW_HELLO_CMD_MBASYNCNOT 0x7 #define V_FW_HELLO_CMD_MBASYNCNOT(x) ((x) << S_FW_HELLO_CMD_MBASYNCNOT) #define G_FW_HELLO_CMD_MBASYNCNOT(x) \ (((x) >> S_FW_HELLO_CMD_MBASYNCNOT) & M_FW_HELLO_CMD_MBASYNCNOT) #define S_FW_HELLO_CMD_STAGE 17 #define M_FW_HELLO_CMD_STAGE 0x7 #define V_FW_HELLO_CMD_STAGE(x) ((x) << S_FW_HELLO_CMD_STAGE) #define G_FW_HELLO_CMD_STAGE(x) \ (((x) >> S_FW_HELLO_CMD_STAGE) & M_FW_HELLO_CMD_STAGE) #define S_FW_HELLO_CMD_CLEARINIT 16 #define M_FW_HELLO_CMD_CLEARINIT 0x1 #define V_FW_HELLO_CMD_CLEARINIT(x) ((x) << S_FW_HELLO_CMD_CLEARINIT) #define G_FW_HELLO_CMD_CLEARINIT(x) \ (((x) >> S_FW_HELLO_CMD_CLEARINIT) & M_FW_HELLO_CMD_CLEARINIT) #define F_FW_HELLO_CMD_CLEARINIT V_FW_HELLO_CMD_CLEARINIT(1U) struct fw_bye_cmd { __be32 op_to_write; __be32 retval_len16; __be64 r3; }; struct fw_initialize_cmd { __be32 op_to_write; __be32 retval_len16; __be64 r3; }; enum fw_caps_config_nic { FW_CAPS_CONFIG_NIC_HASHFILTER = 0x00000020, FW_CAPS_CONFIG_NIC_ETHOFLD = 0x00000040, }; enum fw_memtype_cf { FW_MEMTYPE_CF_FLASH = FW_MEMTYPE_FLASH, }; struct fw_caps_config_cmd { __be32 op_to_write; __be32 cfvalid_to_len16; __be32 r2; __be32 hwmbitmap; __be16 nbmcaps; __be16 linkcaps; __be16 switchcaps; __be16 r3; __be16 niccaps; __be16 toecaps; __be16 rdmacaps; __be16 r4; __be16 iscsicaps; __be16 fcoecaps; __be32 cfcsum; __be32 finiver; __be32 finicsum; }; #define S_FW_CAPS_CONFIG_CMD_CFVALID 27 #define M_FW_CAPS_CONFIG_CMD_CFVALID 0x1 #define V_FW_CAPS_CONFIG_CMD_CFVALID(x) ((x) << S_FW_CAPS_CONFIG_CMD_CFVALID) #define G_FW_CAPS_CONFIG_CMD_CFVALID(x) \ (((x) >> S_FW_CAPS_CONFIG_CMD_CFVALID) & M_FW_CAPS_CONFIG_CMD_CFVALID) #define F_FW_CAPS_CONFIG_CMD_CFVALID V_FW_CAPS_CONFIG_CMD_CFVALID(1U) #define S_FW_CAPS_CONFIG_CMD_MEMTYPE_CF 24 #define M_FW_CAPS_CONFIG_CMD_MEMTYPE_CF 0x7 #define V_FW_CAPS_CONFIG_CMD_MEMTYPE_CF(x) \ ((x) << S_FW_CAPS_CONFIG_CMD_MEMTYPE_CF) #define G_FW_CAPS_CONFIG_CMD_MEMTYPE_CF(x) \ (((x) >> S_FW_CAPS_CONFIG_CMD_MEMTYPE_CF) & \ M_FW_CAPS_CONFIG_CMD_MEMTYPE_CF) #define S_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF 16 #define M_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF 0xff #define V_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(x) \ ((x) << S_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF) #define G_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(x) \ (((x) >> S_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF) & \ M_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF) /* * params command mnemonics */ enum fw_params_mnem { FW_PARAMS_MNEM_DEV = 1, /* device params */ FW_PARAMS_MNEM_PFVF = 2, /* function params */ FW_PARAMS_MNEM_DMAQ = 4, /* dma queue params */ }; /* * device parameters */ enum fw_params_param_dev { FW_PARAMS_PARAM_DEV_CCLK = 0x00, /* chip core clock in khz */ FW_PARAMS_PARAM_DEV_PORTVEC = 0x01, /* the port vector */ FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17, }; /* * physical and virtual function parameters */ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_CPLFW4MSG_ENCAP = 0x31 }; /* * dma queue parameters */ enum fw_params_param_dmaq { FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH = 0x01, FW_PARAMS_PARAM_DMAQ_CONM_CTXT = 0x20, }; #define S_FW_PARAMS_MNEM 24 #define M_FW_PARAMS_MNEM 0xff #define V_FW_PARAMS_MNEM(x) ((x) << S_FW_PARAMS_MNEM) #define G_FW_PARAMS_MNEM(x) \ (((x) >> S_FW_PARAMS_MNEM) & M_FW_PARAMS_MNEM) #define S_FW_PARAMS_PARAM_X 16 #define M_FW_PARAMS_PARAM_X 0xff #define V_FW_PARAMS_PARAM_X(x) ((x) << S_FW_PARAMS_PARAM_X) #define G_FW_PARAMS_PARAM_X(x) \ (((x) >> S_FW_PARAMS_PARAM_X) & M_FW_PARAMS_PARAM_X) #define S_FW_PARAMS_PARAM_Y 8 #define M_FW_PARAMS_PARAM_Y 0xff #define V_FW_PARAMS_PARAM_Y(x) ((x) << S_FW_PARAMS_PARAM_Y) #define G_FW_PARAMS_PARAM_Y(x) \ (((x) >> S_FW_PARAMS_PARAM_Y) & M_FW_PARAMS_PARAM_Y) #define S_FW_PARAMS_PARAM_Z 0 #define M_FW_PARAMS_PARAM_Z 0xff #define V_FW_PARAMS_PARAM_Z(x) ((x) << S_FW_PARAMS_PARAM_Z) #define G_FW_PARAMS_PARAM_Z(x) \ (((x) >> S_FW_PARAMS_PARAM_Z) & M_FW_PARAMS_PARAM_Z) #define S_FW_PARAMS_PARAM_YZ 0 #define M_FW_PARAMS_PARAM_YZ 0xffff #define V_FW_PARAMS_PARAM_YZ(x) ((x) << S_FW_PARAMS_PARAM_YZ) #define G_FW_PARAMS_PARAM_YZ(x) \ (((x) >> S_FW_PARAMS_PARAM_YZ) & M_FW_PARAMS_PARAM_YZ) struct fw_params_cmd { __be32 op_to_vfn; __be32 retval_len16; struct fw_params_param { __be32 mnem; __be32 val; } param[7]; }; #define S_FW_PARAMS_CMD_PFN 8 #define M_FW_PARAMS_CMD_PFN 0x7 #define V_FW_PARAMS_CMD_PFN(x) ((x) << S_FW_PARAMS_CMD_PFN) #define G_FW_PARAMS_CMD_PFN(x) \ (((x) >> S_FW_PARAMS_CMD_PFN) & M_FW_PARAMS_CMD_PFN) #define S_FW_PARAMS_CMD_VFN 0 #define M_FW_PARAMS_CMD_VFN 0xff #define V_FW_PARAMS_CMD_VFN(x) ((x) << S_FW_PARAMS_CMD_VFN) #define G_FW_PARAMS_CMD_VFN(x) \ (((x) >> S_FW_PARAMS_CMD_VFN) & M_FW_PARAMS_CMD_VFN) /* * ingress queue type; the first 1K ingress queues can have associated 0, * 1 or 2 free lists and an interrupt, all other ingress queues lack these * capabilities */ enum fw_iq_type { FW_IQ_TYPE_FL_INT_CAP, }; struct fw_iq_cmd { __be32 op_to_vfn; __be32 alloc_to_len16; __be16 physiqid; __be16 iqid; __be16 fl0id; __be16 fl1id; __be32 type_to_iqandstindex; __be16 iqdroprss_to_iqesize; __be16 iqsize; __be64 iqaddr; __be32 iqns_to_fl0congen; __be16 fl0dcaen_to_fl0cidxfthresh; __be16 fl0size; __be64 fl0addr; __be32 fl1cngchmap_to_fl1congen; __be16 fl1dcaen_to_fl1cidxfthresh; __be16 fl1size; __be64 fl1addr; }; #define S_FW_IQ_CMD_PFN 8 #define M_FW_IQ_CMD_PFN 0x7 #define V_FW_IQ_CMD_PFN(x) ((x) << S_FW_IQ_CMD_PFN) #define G_FW_IQ_CMD_PFN(x) (((x) >> S_FW_IQ_CMD_PFN) & M_FW_IQ_CMD_PFN) #define S_FW_IQ_CMD_VFN 0 #define M_FW_IQ_CMD_VFN 0xff #define V_FW_IQ_CMD_VFN(x) ((x) << S_FW_IQ_CMD_VFN) #define G_FW_IQ_CMD_VFN(x) (((x) >> S_FW_IQ_CMD_VFN) & M_FW_IQ_CMD_VFN) #define S_FW_IQ_CMD_ALLOC 31 #define M_FW_IQ_CMD_ALLOC 0x1 #define V_FW_IQ_CMD_ALLOC(x) ((x) << S_FW_IQ_CMD_ALLOC) #define G_FW_IQ_CMD_ALLOC(x) \ (((x) >> S_FW_IQ_CMD_ALLOC) & M_FW_IQ_CMD_ALLOC) #define F_FW_IQ_CMD_ALLOC V_FW_IQ_CMD_ALLOC(1U) #define S_FW_IQ_CMD_FREE 30 #define M_FW_IQ_CMD_FREE 0x1 #define V_FW_IQ_CMD_FREE(x) ((x) << S_FW_IQ_CMD_FREE) #define G_FW_IQ_CMD_FREE(x) (((x) >> S_FW_IQ_CMD_FREE) & M_FW_IQ_CMD_FREE) #define F_FW_IQ_CMD_FREE V_FW_IQ_CMD_FREE(1U) #define S_FW_IQ_CMD_IQSTART 28 #define M_FW_IQ_CMD_IQSTART 0x1 #define V_FW_IQ_CMD_IQSTART(x) ((x) << S_FW_IQ_CMD_IQSTART) #define G_FW_IQ_CMD_IQSTART(x) \ (((x) >> S_FW_IQ_CMD_IQSTART) & M_FW_IQ_CMD_IQSTART) #define F_FW_IQ_CMD_IQSTART V_FW_IQ_CMD_IQSTART(1U) #define S_FW_IQ_CMD_IQSTOP 27 #define M_FW_IQ_CMD_IQSTOP 0x1 #define V_FW_IQ_CMD_IQSTOP(x) ((x) << S_FW_IQ_CMD_IQSTOP) #define G_FW_IQ_CMD_IQSTOP(x) \ (((x) >> S_FW_IQ_CMD_IQSTOP) & M_FW_IQ_CMD_IQSTOP) #define F_FW_IQ_CMD_IQSTOP V_FW_IQ_CMD_IQSTOP(1U) #define S_FW_IQ_CMD_TYPE 29 #define M_FW_IQ_CMD_TYPE 0x7 #define V_FW_IQ_CMD_TYPE(x) ((x) << S_FW_IQ_CMD_TYPE) #define G_FW_IQ_CMD_TYPE(x) (((x) >> S_FW_IQ_CMD_TYPE) & M_FW_IQ_CMD_TYPE) #define S_FW_IQ_CMD_IQASYNCH 28 #define M_FW_IQ_CMD_IQASYNCH 0x1 #define V_FW_IQ_CMD_IQASYNCH(x) ((x) << S_FW_IQ_CMD_IQASYNCH) #define G_FW_IQ_CMD_IQASYNCH(x) \ (((x) >> S_FW_IQ_CMD_IQASYNCH) & M_FW_IQ_CMD_IQASYNCH) #define F_FW_IQ_CMD_IQASYNCH V_FW_IQ_CMD_IQASYNCH(1U) #define S_FW_IQ_CMD_VIID 16 #define M_FW_IQ_CMD_VIID 0xfff #define V_FW_IQ_CMD_VIID(x) ((x) << S_FW_IQ_CMD_VIID) #define G_FW_IQ_CMD_VIID(x) (((x) >> S_FW_IQ_CMD_VIID) & M_FW_IQ_CMD_VIID) #define S_FW_IQ_CMD_IQANDST 15 #define M_FW_IQ_CMD_IQANDST 0x1 #define V_FW_IQ_CMD_IQANDST(x) ((x) << S_FW_IQ_CMD_IQANDST) #define G_FW_IQ_CMD_IQANDST(x) \ (((x) >> S_FW_IQ_CMD_IQANDST) & M_FW_IQ_CMD_IQANDST) #define F_FW_IQ_CMD_IQANDST V_FW_IQ_CMD_IQANDST(1U) #define S_FW_IQ_CMD_IQANUD 12 #define M_FW_IQ_CMD_IQANUD 0x3 #define V_FW_IQ_CMD_IQANUD(x) ((x) << S_FW_IQ_CMD_IQANUD) #define G_FW_IQ_CMD_IQANUD(x) \ (((x) >> S_FW_IQ_CMD_IQANUD) & M_FW_IQ_CMD_IQANUD) #define S_FW_IQ_CMD_IQANDSTINDEX 0 #define M_FW_IQ_CMD_IQANDSTINDEX 0xfff #define V_FW_IQ_CMD_IQANDSTINDEX(x) ((x) << S_FW_IQ_CMD_IQANDSTINDEX) #define G_FW_IQ_CMD_IQANDSTINDEX(x) \ (((x) >> S_FW_IQ_CMD_IQANDSTINDEX) & M_FW_IQ_CMD_IQANDSTINDEX) #define S_FW_IQ_CMD_IQGTSMODE 14 #define M_FW_IQ_CMD_IQGTSMODE 0x1 #define V_FW_IQ_CMD_IQGTSMODE(x) ((x) << S_FW_IQ_CMD_IQGTSMODE) #define G_FW_IQ_CMD_IQGTSMODE(x) \ (((x) >> S_FW_IQ_CMD_IQGTSMODE) & M_FW_IQ_CMD_IQGTSMODE) #define F_FW_IQ_CMD_IQGTSMODE V_FW_IQ_CMD_IQGTSMODE(1U) #define S_FW_IQ_CMD_IQPCIECH 12 #define M_FW_IQ_CMD_IQPCIECH 0x3 #define V_FW_IQ_CMD_IQPCIECH(x) ((x) << S_FW_IQ_CMD_IQPCIECH) #define G_FW_IQ_CMD_IQPCIECH(x) \ (((x) >> S_FW_IQ_CMD_IQPCIECH) & M_FW_IQ_CMD_IQPCIECH) #define S_FW_IQ_CMD_IQINTCNTTHRESH 4 #define M_FW_IQ_CMD_IQINTCNTTHRESH 0x3 #define V_FW_IQ_CMD_IQINTCNTTHRESH(x) ((x) << S_FW_IQ_CMD_IQINTCNTTHRESH) #define G_FW_IQ_CMD_IQINTCNTTHRESH(x) \ (((x) >> S_FW_IQ_CMD_IQINTCNTTHRESH) & M_FW_IQ_CMD_IQINTCNTTHRESH) #define S_FW_IQ_CMD_IQESIZE 0 #define M_FW_IQ_CMD_IQESIZE 0x3 #define V_FW_IQ_CMD_IQESIZE(x) ((x) << S_FW_IQ_CMD_IQESIZE) #define G_FW_IQ_CMD_IQESIZE(x) \ (((x) >> S_FW_IQ_CMD_IQESIZE) & M_FW_IQ_CMD_IQESIZE) #define S_FW_IQ_CMD_IQFLINTCONGEN 27 #define M_FW_IQ_CMD_IQFLINTCONGEN 0x1 #define V_FW_IQ_CMD_IQFLINTCONGEN(x) ((x) << S_FW_IQ_CMD_IQFLINTCONGEN) #define G_FW_IQ_CMD_IQFLINTCONGEN(x) \ (((x) >> S_FW_IQ_CMD_IQFLINTCONGEN) & M_FW_IQ_CMD_IQFLINTCONGEN) #define F_FW_IQ_CMD_IQFLINTCONGEN V_FW_IQ_CMD_IQFLINTCONGEN(1U) #define S_FW_IQ_CMD_FL0CNGCHMAP 20 #define M_FW_IQ_CMD_FL0CNGCHMAP 0xf #define V_FW_IQ_CMD_FL0CNGCHMAP(x) ((x) << S_FW_IQ_CMD_FL0CNGCHMAP) #define G_FW_IQ_CMD_FL0CNGCHMAP(x) \ (((x) >> S_FW_IQ_CMD_FL0CNGCHMAP) & M_FW_IQ_CMD_FL0CNGCHMAP) #define S_FW_IQ_CMD_FL0DATARO 12 #define M_FW_IQ_CMD_FL0DATARO 0x1 #define V_FW_IQ_CMD_FL0DATARO(x) ((x) << S_FW_IQ_CMD_FL0DATARO) #define G_FW_IQ_CMD_FL0DATARO(x) \ (((x) >> S_FW_IQ_CMD_FL0DATARO) & M_FW_IQ_CMD_FL0DATARO) #define F_FW_IQ_CMD_FL0DATARO V_FW_IQ_CMD_FL0DATARO(1U) #define S_FW_IQ_CMD_FL0CONGCIF 11 #define M_FW_IQ_CMD_FL0CONGCIF 0x1 #define V_FW_IQ_CMD_FL0CONGCIF(x) ((x) << S_FW_IQ_CMD_FL0CONGCIF) #define G_FW_IQ_CMD_FL0CONGCIF(x) \ (((x) >> S_FW_IQ_CMD_FL0CONGCIF) & M_FW_IQ_CMD_FL0CONGCIF) #define F_FW_IQ_CMD_FL0CONGCIF V_FW_IQ_CMD_FL0CONGCIF(1U) #define S_FW_IQ_CMD_FL0FETCHRO 6 #define M_FW_IQ_CMD_FL0FETCHRO 0x1 #define V_FW_IQ_CMD_FL0FETCHRO(x) ((x) << S_FW_IQ_CMD_FL0FETCHRO) #define G_FW_IQ_CMD_FL0FETCHRO(x) \ (((x) >> S_FW_IQ_CMD_FL0FETCHRO) & M_FW_IQ_CMD_FL0FETCHRO) #define F_FW_IQ_CMD_FL0FETCHRO V_FW_IQ_CMD_FL0FETCHRO(1U) #define S_FW_IQ_CMD_FL0HOSTFCMODE 4 #define M_FW_IQ_CMD_FL0HOSTFCMODE 0x3 #define V_FW_IQ_CMD_FL0HOSTFCMODE(x) ((x) << S_FW_IQ_CMD_FL0HOSTFCMODE) #define G_FW_IQ_CMD_FL0HOSTFCMODE(x) \ (((x) >> S_FW_IQ_CMD_FL0HOSTFCMODE) & M_FW_IQ_CMD_FL0HOSTFCMODE) #define S_FW_IQ_CMD_FL0PADEN 2 #define M_FW_IQ_CMD_FL0PADEN 0x1 #define V_FW_IQ_CMD_FL0PADEN(x) ((x) << S_FW_IQ_CMD_FL0PADEN) #define G_FW_IQ_CMD_FL0PADEN(x) \ (((x) >> S_FW_IQ_CMD_FL0PADEN) & M_FW_IQ_CMD_FL0PADEN) #define F_FW_IQ_CMD_FL0PADEN V_FW_IQ_CMD_FL0PADEN(1U) #define S_FW_IQ_CMD_FL0PACKEN 1 #define M_FW_IQ_CMD_FL0PACKEN 0x1 #define V_FW_IQ_CMD_FL0PACKEN(x) ((x) << S_FW_IQ_CMD_FL0PACKEN) #define G_FW_IQ_CMD_FL0PACKEN(x) \ (((x) >> S_FW_IQ_CMD_FL0PACKEN) & M_FW_IQ_CMD_FL0PACKEN) #define F_FW_IQ_CMD_FL0PACKEN V_FW_IQ_CMD_FL0PACKEN(1U) #define S_FW_IQ_CMD_FL0CONGEN 0 #define M_FW_IQ_CMD_FL0CONGEN 0x1 #define V_FW_IQ_CMD_FL0CONGEN(x) ((x) << S_FW_IQ_CMD_FL0CONGEN) #define G_FW_IQ_CMD_FL0CONGEN(x) \ (((x) >> S_FW_IQ_CMD_FL0CONGEN) & M_FW_IQ_CMD_FL0CONGEN) #define F_FW_IQ_CMD_FL0CONGEN V_FW_IQ_CMD_FL0CONGEN(1U) #define S_FW_IQ_CMD_FL0FBMIN 7 #define M_FW_IQ_CMD_FL0FBMIN 0x7 #define V_FW_IQ_CMD_FL0FBMIN(x) ((x) << S_FW_IQ_CMD_FL0FBMIN) #define G_FW_IQ_CMD_FL0FBMIN(x) \ (((x) >> S_FW_IQ_CMD_FL0FBMIN) & M_FW_IQ_CMD_FL0FBMIN) #define S_FW_IQ_CMD_FL0FBMAX 4 #define M_FW_IQ_CMD_FL0FBMAX 0x7 #define V_FW_IQ_CMD_FL0FBMAX(x) ((x) << S_FW_IQ_CMD_FL0FBMAX) #define G_FW_IQ_CMD_FL0FBMAX(x) \ (((x) >> S_FW_IQ_CMD_FL0FBMAX) & M_FW_IQ_CMD_FL0FBMAX) struct fw_eq_eth_cmd { __be32 op_to_vfn; __be32 alloc_to_len16; __be32 eqid_pkd; __be32 physeqid_pkd; __be32 fetchszm_to_iqid; __be32 dcaen_to_eqsize; __be64 eqaddr; __be32 autoequiqe_to_viid; __be32 r8_lo; __be64 r9; }; #define S_FW_EQ_ETH_CMD_PFN 8 #define M_FW_EQ_ETH_CMD_PFN 0x7 #define V_FW_EQ_ETH_CMD_PFN(x) ((x) << S_FW_EQ_ETH_CMD_PFN) #define G_FW_EQ_ETH_CMD_PFN(x) \ (((x) >> S_FW_EQ_ETH_CMD_PFN) & M_FW_EQ_ETH_CMD_PFN) #define S_FW_EQ_ETH_CMD_VFN 0 #define M_FW_EQ_ETH_CMD_VFN 0xff #define V_FW_EQ_ETH_CMD_VFN(x) ((x) << S_FW_EQ_ETH_CMD_VFN) #define G_FW_EQ_ETH_CMD_VFN(x) \ (((x) >> S_FW_EQ_ETH_CMD_VFN) & M_FW_EQ_ETH_CMD_VFN) #define S_FW_EQ_ETH_CMD_ALLOC 31 #define M_FW_EQ_ETH_CMD_ALLOC 0x1 #define V_FW_EQ_ETH_CMD_ALLOC(x) ((x) << S_FW_EQ_ETH_CMD_ALLOC) #define G_FW_EQ_ETH_CMD_ALLOC(x) \ (((x) >> S_FW_EQ_ETH_CMD_ALLOC) & M_FW_EQ_ETH_CMD_ALLOC) #define F_FW_EQ_ETH_CMD_ALLOC V_FW_EQ_ETH_CMD_ALLOC(1U) #define S_FW_EQ_ETH_CMD_FREE 30 #define M_FW_EQ_ETH_CMD_FREE 0x1 #define V_FW_EQ_ETH_CMD_FREE(x) ((x) << S_FW_EQ_ETH_CMD_FREE) #define G_FW_EQ_ETH_CMD_FREE(x) \ (((x) >> S_FW_EQ_ETH_CMD_FREE) & M_FW_EQ_ETH_CMD_FREE) #define F_FW_EQ_ETH_CMD_FREE V_FW_EQ_ETH_CMD_FREE(1U) #define S_FW_EQ_ETH_CMD_EQSTART 28 #define M_FW_EQ_ETH_CMD_EQSTART 0x1 #define V_FW_EQ_ETH_CMD_EQSTART(x) ((x) << S_FW_EQ_ETH_CMD_EQSTART) #define G_FW_EQ_ETH_CMD_EQSTART(x) \ (((x) >> S_FW_EQ_ETH_CMD_EQSTART) & M_FW_EQ_ETH_CMD_EQSTART) #define F_FW_EQ_ETH_CMD_EQSTART V_FW_EQ_ETH_CMD_EQSTART(1U) #define S_FW_EQ_ETH_CMD_EQID 0 #define M_FW_EQ_ETH_CMD_EQID 0xfffff #define V_FW_EQ_ETH_CMD_EQID(x) ((x) << S_FW_EQ_ETH_CMD_EQID) #define G_FW_EQ_ETH_CMD_EQID(x) \ (((x) >> S_FW_EQ_ETH_CMD_EQID) & M_FW_EQ_ETH_CMD_EQID) #define S_FW_EQ_ETH_CMD_FETCHRO 22 #define M_FW_EQ_ETH_CMD_FETCHRO 0x1 #define V_FW_EQ_ETH_CMD_FETCHRO(x) ((x) << S_FW_EQ_ETH_CMD_FETCHRO) #define G_FW_EQ_ETH_CMD_FETCHRO(x) \ (((x) >> S_FW_EQ_ETH_CMD_FETCHRO) & M_FW_EQ_ETH_CMD_FETCHRO) #define F_FW_EQ_ETH_CMD_FETCHRO V_FW_EQ_ETH_CMD_FETCHRO(1U) #define S_FW_EQ_ETH_CMD_HOSTFCMODE 20 #define M_FW_EQ_ETH_CMD_HOSTFCMODE 0x3 #define V_FW_EQ_ETH_CMD_HOSTFCMODE(x) ((x) << S_FW_EQ_ETH_CMD_HOSTFCMODE) #define G_FW_EQ_ETH_CMD_HOSTFCMODE(x) \ (((x) >> S_FW_EQ_ETH_CMD_HOSTFCMODE) & M_FW_EQ_ETH_CMD_HOSTFCMODE) #define S_FW_EQ_ETH_CMD_PCIECHN 16 #define M_FW_EQ_ETH_CMD_PCIECHN 0x3 #define V_FW_EQ_ETH_CMD_PCIECHN(x) ((x) << S_FW_EQ_ETH_CMD_PCIECHN) #define G_FW_EQ_ETH_CMD_PCIECHN(x) \ (((x) >> S_FW_EQ_ETH_CMD_PCIECHN) & M_FW_EQ_ETH_CMD_PCIECHN) #define S_FW_EQ_ETH_CMD_IQID 0 #define M_FW_EQ_ETH_CMD_IQID 0xffff #define V_FW_EQ_ETH_CMD_IQID(x) ((x) << S_FW_EQ_ETH_CMD_IQID) #define G_FW_EQ_ETH_CMD_IQID(x) \ (((x) >> S_FW_EQ_ETH_CMD_IQID) & M_FW_EQ_ETH_CMD_IQID) #define S_FW_EQ_ETH_CMD_FBMIN 23 #define M_FW_EQ_ETH_CMD_FBMIN 0x7 #define V_FW_EQ_ETH_CMD_FBMIN(x) ((x) << S_FW_EQ_ETH_CMD_FBMIN) #define G_FW_EQ_ETH_CMD_FBMIN(x) \ (((x) >> S_FW_EQ_ETH_CMD_FBMIN) & M_FW_EQ_ETH_CMD_FBMIN) #define S_FW_EQ_ETH_CMD_FBMAX 20 #define M_FW_EQ_ETH_CMD_FBMAX 0x7 #define V_FW_EQ_ETH_CMD_FBMAX(x) ((x) << S_FW_EQ_ETH_CMD_FBMAX) #define G_FW_EQ_ETH_CMD_FBMAX(x) \ (((x) >> S_FW_EQ_ETH_CMD_FBMAX) & M_FW_EQ_ETH_CMD_FBMAX) #define S_FW_EQ_ETH_CMD_CIDXFTHRESH 16 #define M_FW_EQ_ETH_CMD_CIDXFTHRESH 0x7 #define V_FW_EQ_ETH_CMD_CIDXFTHRESH(x) ((x) << S_FW_EQ_ETH_CMD_CIDXFTHRESH) #define G_FW_EQ_ETH_CMD_CIDXFTHRESH(x) \ (((x) >> S_FW_EQ_ETH_CMD_CIDXFTHRESH) & M_FW_EQ_ETH_CMD_CIDXFTHRESH) #define S_FW_EQ_ETH_CMD_EQSIZE 0 #define M_FW_EQ_ETH_CMD_EQSIZE 0xffff #define V_FW_EQ_ETH_CMD_EQSIZE(x) ((x) << S_FW_EQ_ETH_CMD_EQSIZE) #define G_FW_EQ_ETH_CMD_EQSIZE(x) \ (((x) >> S_FW_EQ_ETH_CMD_EQSIZE) & M_FW_EQ_ETH_CMD_EQSIZE) #define S_FW_EQ_ETH_CMD_AUTOEQUEQE 30 #define M_FW_EQ_ETH_CMD_AUTOEQUEQE 0x1 #define V_FW_EQ_ETH_CMD_AUTOEQUEQE(x) ((x) << S_FW_EQ_ETH_CMD_AUTOEQUEQE) #define G_FW_EQ_ETH_CMD_AUTOEQUEQE(x) \ (((x) >> S_FW_EQ_ETH_CMD_AUTOEQUEQE) & M_FW_EQ_ETH_CMD_AUTOEQUEQE) #define F_FW_EQ_ETH_CMD_AUTOEQUEQE V_FW_EQ_ETH_CMD_AUTOEQUEQE(1U) #define S_FW_EQ_ETH_CMD_VIID 16 #define M_FW_EQ_ETH_CMD_VIID 0xfff #define V_FW_EQ_ETH_CMD_VIID(x) ((x) << S_FW_EQ_ETH_CMD_VIID) #define G_FW_EQ_ETH_CMD_VIID(x) \ (((x) >> S_FW_EQ_ETH_CMD_VIID) & M_FW_EQ_ETH_CMD_VIID) enum fw_vi_func { FW_VI_FUNC_ETH, }; struct fw_vi_cmd { __be32 op_to_vfn; __be32 alloc_to_len16; __be16 type_to_viid; __u8 mac[6]; __u8 portid_pkd; __u8 nmac; __u8 nmac0[6]; __be16 norss_rsssize; __u8 nmac1[6]; __be16 idsiiq_pkd; __u8 nmac2[6]; __be16 idseiq_pkd; __u8 nmac3[6]; __be64 r9; __be64 r10; }; #define S_FW_VI_CMD_PFN 8 #define M_FW_VI_CMD_PFN 0x7 #define V_FW_VI_CMD_PFN(x) ((x) << S_FW_VI_CMD_PFN) #define G_FW_VI_CMD_PFN(x) (((x) >> S_FW_VI_CMD_PFN) & M_FW_VI_CMD_PFN) #define S_FW_VI_CMD_VFN 0 #define M_FW_VI_CMD_VFN 0xff #define V_FW_VI_CMD_VFN(x) ((x) << S_FW_VI_CMD_VFN) #define G_FW_VI_CMD_VFN(x) (((x) >> S_FW_VI_CMD_VFN) & M_FW_VI_CMD_VFN) #define S_FW_VI_CMD_ALLOC 31 #define M_FW_VI_CMD_ALLOC 0x1 #define V_FW_VI_CMD_ALLOC(x) ((x) << S_FW_VI_CMD_ALLOC) #define G_FW_VI_CMD_ALLOC(x) \ (((x) >> S_FW_VI_CMD_ALLOC) & M_FW_VI_CMD_ALLOC) #define F_FW_VI_CMD_ALLOC V_FW_VI_CMD_ALLOC(1U) #define S_FW_VI_CMD_FREE 30 #define M_FW_VI_CMD_FREE 0x1 #define V_FW_VI_CMD_FREE(x) ((x) << S_FW_VI_CMD_FREE) #define G_FW_VI_CMD_FREE(x) (((x) >> S_FW_VI_CMD_FREE) & M_FW_VI_CMD_FREE) #define F_FW_VI_CMD_FREE V_FW_VI_CMD_FREE(1U) #define S_FW_VI_CMD_TYPE 15 #define M_FW_VI_CMD_TYPE 0x1 #define V_FW_VI_CMD_TYPE(x) ((x) << S_FW_VI_CMD_TYPE) #define G_FW_VI_CMD_TYPE(x) (((x) >> S_FW_VI_CMD_TYPE) & M_FW_VI_CMD_TYPE) #define F_FW_VI_CMD_TYPE V_FW_VI_CMD_TYPE(1U) #define S_FW_VI_CMD_FUNC 12 #define M_FW_VI_CMD_FUNC 0x7 #define V_FW_VI_CMD_FUNC(x) ((x) << S_FW_VI_CMD_FUNC) #define G_FW_VI_CMD_FUNC(x) (((x) >> S_FW_VI_CMD_FUNC) & M_FW_VI_CMD_FUNC) #define S_FW_VI_CMD_VIID 0 #define M_FW_VI_CMD_VIID 0xfff #define V_FW_VI_CMD_VIID(x) ((x) << S_FW_VI_CMD_VIID) #define G_FW_VI_CMD_VIID(x) (((x) >> S_FW_VI_CMD_VIID) & M_FW_VI_CMD_VIID) #define S_FW_VI_CMD_PORTID 4 #define M_FW_VI_CMD_PORTID 0xf #define V_FW_VI_CMD_PORTID(x) ((x) << S_FW_VI_CMD_PORTID) #define G_FW_VI_CMD_PORTID(x) \ (((x) >> S_FW_VI_CMD_PORTID) & M_FW_VI_CMD_PORTID) #define S_FW_VI_CMD_RSSSIZE 0 #define M_FW_VI_CMD_RSSSIZE 0x7ff #define V_FW_VI_CMD_RSSSIZE(x) ((x) << S_FW_VI_CMD_RSSSIZE) #define G_FW_VI_CMD_RSSSIZE(x) \ (((x) >> S_FW_VI_CMD_RSSSIZE) & M_FW_VI_CMD_RSSSIZE) /* Special VI_MAC command index ids */ #define FW_VI_MAC_ADD_MAC 0x3FF #define FW_VI_MAC_ADD_PERSIST_MAC 0x3FE enum fw_vi_mac_smac { FW_VI_MAC_MPS_TCAM_ENTRY, FW_VI_MAC_SMT_AND_MPSTCAM }; struct fw_vi_mac_cmd { __be32 op_to_viid; __be32 freemacs_to_len16; union fw_vi_mac { struct fw_vi_mac_exact { __be16 valid_to_idx; __u8 macaddr[6]; } exact[7]; struct fw_vi_mac_hash { __be64 hashvec; } hash; } u; }; #define S_FW_VI_MAC_CMD_VIID 0 #define M_FW_VI_MAC_CMD_VIID 0xfff #define V_FW_VI_MAC_CMD_VIID(x) ((x) << S_FW_VI_MAC_CMD_VIID) #define G_FW_VI_MAC_CMD_VIID(x) \ (((x) >> S_FW_VI_MAC_CMD_VIID) & M_FW_VI_MAC_CMD_VIID) #define S_FW_VI_MAC_CMD_VALID 15 #define M_FW_VI_MAC_CMD_VALID 0x1 #define V_FW_VI_MAC_CMD_VALID(x) ((x) << S_FW_VI_MAC_CMD_VALID) #define G_FW_VI_MAC_CMD_VALID(x) \ (((x) >> S_FW_VI_MAC_CMD_VALID) & M_FW_VI_MAC_CMD_VALID) #define F_FW_VI_MAC_CMD_VALID V_FW_VI_MAC_CMD_VALID(1U) #define S_FW_VI_MAC_CMD_SMAC_RESULT 10 #define M_FW_VI_MAC_CMD_SMAC_RESULT 0x3 #define V_FW_VI_MAC_CMD_SMAC_RESULT(x) ((x) << S_FW_VI_MAC_CMD_SMAC_RESULT) #define G_FW_VI_MAC_CMD_SMAC_RESULT(x) \ (((x) >> S_FW_VI_MAC_CMD_SMAC_RESULT) & M_FW_VI_MAC_CMD_SMAC_RESULT) #define S_FW_VI_MAC_CMD_IDX 0 #define M_FW_VI_MAC_CMD_IDX 0x3ff #define V_FW_VI_MAC_CMD_IDX(x) ((x) << S_FW_VI_MAC_CMD_IDX) #define G_FW_VI_MAC_CMD_IDX(x) \ (((x) >> S_FW_VI_MAC_CMD_IDX) & M_FW_VI_MAC_CMD_IDX) struct fw_vi_rxmode_cmd { __be32 op_to_viid; __be32 retval_len16; __be32 mtu_to_vlanexen; __be32 r4_lo; }; #define S_FW_VI_RXMODE_CMD_VIID 0 #define M_FW_VI_RXMODE_CMD_VIID 0xfff #define V_FW_VI_RXMODE_CMD_VIID(x) ((x) << S_FW_VI_RXMODE_CMD_VIID) #define G_FW_VI_RXMODE_CMD_VIID(x) \ (((x) >> S_FW_VI_RXMODE_CMD_VIID) & M_FW_VI_RXMODE_CMD_VIID) #define S_FW_VI_RXMODE_CMD_MTU 16 #define M_FW_VI_RXMODE_CMD_MTU 0xffff #define V_FW_VI_RXMODE_CMD_MTU(x) ((x) << S_FW_VI_RXMODE_CMD_MTU) #define G_FW_VI_RXMODE_CMD_MTU(x) \ (((x) >> S_FW_VI_RXMODE_CMD_MTU) & M_FW_VI_RXMODE_CMD_MTU) #define S_FW_VI_RXMODE_CMD_PROMISCEN 14 #define M_FW_VI_RXMODE_CMD_PROMISCEN 0x3 #define V_FW_VI_RXMODE_CMD_PROMISCEN(x) ((x) << S_FW_VI_RXMODE_CMD_PROMISCEN) #define G_FW_VI_RXMODE_CMD_PROMISCEN(x) \ (((x) >> S_FW_VI_RXMODE_CMD_PROMISCEN) & M_FW_VI_RXMODE_CMD_PROMISCEN) #define S_FW_VI_RXMODE_CMD_ALLMULTIEN 12 #define M_FW_VI_RXMODE_CMD_ALLMULTIEN 0x3 #define V_FW_VI_RXMODE_CMD_ALLMULTIEN(x) \ ((x) << S_FW_VI_RXMODE_CMD_ALLMULTIEN) #define G_FW_VI_RXMODE_CMD_ALLMULTIEN(x) \ (((x) >> S_FW_VI_RXMODE_CMD_ALLMULTIEN) & M_FW_VI_RXMODE_CMD_ALLMULTIEN) #define S_FW_VI_RXMODE_CMD_BROADCASTEN 10 #define M_FW_VI_RXMODE_CMD_BROADCASTEN 0x3 #define V_FW_VI_RXMODE_CMD_BROADCASTEN(x) \ ((x) << S_FW_VI_RXMODE_CMD_BROADCASTEN) #define G_FW_VI_RXMODE_CMD_BROADCASTEN(x) \ (((x) >> S_FW_VI_RXMODE_CMD_BROADCASTEN) & \ M_FW_VI_RXMODE_CMD_BROADCASTEN) #define S_FW_VI_RXMODE_CMD_VLANEXEN 8 #define M_FW_VI_RXMODE_CMD_VLANEXEN 0x3 #define V_FW_VI_RXMODE_CMD_VLANEXEN(x) ((x) << S_FW_VI_RXMODE_CMD_VLANEXEN) #define G_FW_VI_RXMODE_CMD_VLANEXEN(x) \ (((x) >> S_FW_VI_RXMODE_CMD_VLANEXEN) & M_FW_VI_RXMODE_CMD_VLANEXEN) struct fw_vi_enable_cmd { __be32 op_to_viid; __be32 ien_to_len16; __be16 blinkdur; __be16 r3; __be32 r4; }; #define S_FW_VI_ENABLE_CMD_VIID 0 #define M_FW_VI_ENABLE_CMD_VIID 0xfff #define V_FW_VI_ENABLE_CMD_VIID(x) ((x) << S_FW_VI_ENABLE_CMD_VIID) #define G_FW_VI_ENABLE_CMD_VIID(x) \ (((x) >> S_FW_VI_ENABLE_CMD_VIID) & M_FW_VI_ENABLE_CMD_VIID) #define S_FW_VI_ENABLE_CMD_IEN 31 #define M_FW_VI_ENABLE_CMD_IEN 0x1 #define V_FW_VI_ENABLE_CMD_IEN(x) ((x) << S_FW_VI_ENABLE_CMD_IEN) #define G_FW_VI_ENABLE_CMD_IEN(x) \ (((x) >> S_FW_VI_ENABLE_CMD_IEN) & M_FW_VI_ENABLE_CMD_IEN) #define F_FW_VI_ENABLE_CMD_IEN V_FW_VI_ENABLE_CMD_IEN(1U) #define S_FW_VI_ENABLE_CMD_EEN 30 #define M_FW_VI_ENABLE_CMD_EEN 0x1 #define V_FW_VI_ENABLE_CMD_EEN(x) ((x) << S_FW_VI_ENABLE_CMD_EEN) #define G_FW_VI_ENABLE_CMD_EEN(x) \ (((x) >> S_FW_VI_ENABLE_CMD_EEN) & M_FW_VI_ENABLE_CMD_EEN) #define F_FW_VI_ENABLE_CMD_EEN V_FW_VI_ENABLE_CMD_EEN(1U) #define S_FW_VI_ENABLE_CMD_DCB_INFO 28 #define M_FW_VI_ENABLE_CMD_DCB_INFO 0x1 #define V_FW_VI_ENABLE_CMD_DCB_INFO(x) ((x) << S_FW_VI_ENABLE_CMD_DCB_INFO) #define G_FW_VI_ENABLE_CMD_DCB_INFO(x) \ (((x) >> S_FW_VI_ENABLE_CMD_DCB_INFO) & M_FW_VI_ENABLE_CMD_DCB_INFO) #define F_FW_VI_ENABLE_CMD_DCB_INFO V_FW_VI_ENABLE_CMD_DCB_INFO(1U) /* VI PF stats offset definitions */ #define VI_PF_NUM_STATS 17 enum fw_vi_stats_pf_index { FW_VI_PF_STAT_TX_BCAST_BYTES_IX, FW_VI_PF_STAT_TX_BCAST_FRAMES_IX, FW_VI_PF_STAT_TX_MCAST_BYTES_IX, FW_VI_PF_STAT_TX_MCAST_FRAMES_IX, FW_VI_PF_STAT_TX_UCAST_BYTES_IX, FW_VI_PF_STAT_TX_UCAST_FRAMES_IX, FW_VI_PF_STAT_TX_OFLD_BYTES_IX, FW_VI_PF_STAT_TX_OFLD_FRAMES_IX, FW_VI_PF_STAT_RX_BYTES_IX, FW_VI_PF_STAT_RX_FRAMES_IX, FW_VI_PF_STAT_RX_BCAST_BYTES_IX, FW_VI_PF_STAT_RX_BCAST_FRAMES_IX, FW_VI_PF_STAT_RX_MCAST_BYTES_IX, FW_VI_PF_STAT_RX_MCAST_FRAMES_IX, FW_VI_PF_STAT_RX_UCAST_BYTES_IX, FW_VI_PF_STAT_RX_UCAST_FRAMES_IX, FW_VI_PF_STAT_RX_ERR_FRAMES_IX }; struct fw_vi_stats_cmd { __be32 op_to_viid; __be32 retval_len16; union fw_vi_stats { struct fw_vi_stats_ctl { __be16 nstats_ix; __be16 r6; __be32 r7; __be64 stat0; __be64 stat1; __be64 stat2; __be64 stat3; __be64 stat4; __be64 stat5; } ctl; struct fw_vi_stats_pf { __be64 tx_bcast_bytes; __be64 tx_bcast_frames; __be64 tx_mcast_bytes; __be64 tx_mcast_frames; __be64 tx_ucast_bytes; __be64 tx_ucast_frames; __be64 tx_offload_bytes; __be64 tx_offload_frames; __be64 rx_pf_bytes; __be64 rx_pf_frames; __be64 rx_bcast_bytes; __be64 rx_bcast_frames; __be64 rx_mcast_bytes; __be64 rx_mcast_frames; __be64 rx_ucast_bytes; __be64 rx_ucast_frames; __be64 rx_err_frames; } pf; struct fw_vi_stats_vf { __be64 tx_bcast_bytes; __be64 tx_bcast_frames; __be64 tx_mcast_bytes; __be64 tx_mcast_frames; __be64 tx_ucast_bytes; __be64 tx_ucast_frames; __be64 tx_drop_frames; __be64 tx_offload_bytes; __be64 tx_offload_frames; __be64 rx_bcast_bytes; __be64 rx_bcast_frames; __be64 rx_mcast_bytes; __be64 rx_mcast_frames; __be64 rx_ucast_bytes; __be64 rx_ucast_frames; __be64 rx_err_frames; } vf; } u; }; /* port capabilities bitmap */ enum fw_port_cap { FW_PORT_CAP_SPEED_100M = 0x0001, FW_PORT_CAP_SPEED_1G = 0x0002, FW_PORT_CAP_SPEED_2_5G = 0x0004, FW_PORT_CAP_SPEED_10G = 0x0008, FW_PORT_CAP_SPEED_40G = 0x0010, FW_PORT_CAP_SPEED_100G = 0x0020, FW_PORT_CAP_FC_RX = 0x0040, FW_PORT_CAP_FC_TX = 0x0080, FW_PORT_CAP_ANEG = 0x0100, FW_PORT_CAP_MDIX = 0x0200, FW_PORT_CAP_MDIAUTO = 0x0400, FW_PORT_CAP_FEC = 0x0800, FW_PORT_CAP_TECHKR = 0x1000, FW_PORT_CAP_TECHKX4 = 0x2000, FW_PORT_CAP_802_3_PAUSE = 0x4000, FW_PORT_CAP_802_3_ASM_DIR = 0x8000, }; enum fw_port_mdi { FW_PORT_CAP_MDI_AUTO, }; #define S_FW_PORT_CAP_MDI 9 #define M_FW_PORT_CAP_MDI 3 #define V_FW_PORT_CAP_MDI(x) ((x) << S_FW_PORT_CAP_MDI) #define G_FW_PORT_CAP_MDI(x) (((x) >> S_FW_PORT_CAP_MDI) & M_FW_PORT_CAP_MDI) enum fw_port_action { FW_PORT_ACTION_L1_CFG = 0x0001, FW_PORT_ACTION_GET_PORT_INFO = 0x0003, }; struct fw_port_cmd { __be32 op_to_portid; __be32 action_to_len16; union fw_port { struct fw_port_l1cfg { __be32 rcap; __be32 r; } l1cfg; struct fw_port_l2cfg { __u8 ctlbf; __u8 ovlan3_to_ivlan0; __be16 ivlantype; __be16 txipg_force_pinfo; __be16 mtu; __be16 ovlan0mask; __be16 ovlan0type; __be16 ovlan1mask; __be16 ovlan1type; __be16 ovlan2mask; __be16 ovlan2type; __be16 ovlan3mask; __be16 ovlan3type; } l2cfg; struct fw_port_info { __be32 lstatus_to_modtype; __be16 pcap; __be16 acap; __be16 mtu; __u8 cbllen; __u8 auxlinfo; __u8 dcbxdis_pkd; __u8 r8_lo; __be16 lpacap; __be64 r9; } info; struct fw_port_diags { __u8 diagop; __u8 r[3]; __be32 diagval; } diags; union fw_port_dcb { struct fw_port_dcb_pgid { __u8 type; __u8 apply_pkd; __u8 r10_lo[2]; __be32 pgid; __be64 r11; } pgid; struct fw_port_dcb_pgrate { __u8 type; __u8 apply_pkd; __u8 r10_lo[5]; __u8 num_tcs_supported; __u8 pgrate[8]; __u8 tsa[8]; } pgrate; struct fw_port_dcb_priorate { __u8 type; __u8 apply_pkd; __u8 r10_lo[6]; __u8 strict_priorate[8]; } priorate; struct fw_port_dcb_pfc { __u8 type; __u8 pfcen; __u8 r10[5]; __u8 max_pfc_tcs; __be64 r11; } pfc; struct fw_port_app_priority { __u8 type; __u8 r10[2]; __u8 idx; __u8 user_prio_map; __u8 sel_field; __be16 protocolid; __be64 r12; } app_priority; struct fw_port_dcb_control { __u8 type; __u8 all_syncd_pkd; __be16 dcb_version_to_app_state; __be32 r11; __be64 r12; } control; } dcb; } u; }; #define S_FW_PORT_CMD_PORTID 0 #define M_FW_PORT_CMD_PORTID 0xf #define V_FW_PORT_CMD_PORTID(x) ((x) << S_FW_PORT_CMD_PORTID) #define G_FW_PORT_CMD_PORTID(x) \ (((x) >> S_FW_PORT_CMD_PORTID) & M_FW_PORT_CMD_PORTID) #define S_FW_PORT_CMD_ACTION 16 #define M_FW_PORT_CMD_ACTION 0xffff #define V_FW_PORT_CMD_ACTION(x) ((x) << S_FW_PORT_CMD_ACTION) #define G_FW_PORT_CMD_ACTION(x) \ (((x) >> S_FW_PORT_CMD_ACTION) & M_FW_PORT_CMD_ACTION) #define S_FW_PORT_CMD_LSTATUS 31 #define M_FW_PORT_CMD_LSTATUS 0x1 #define V_FW_PORT_CMD_LSTATUS(x) ((x) << S_FW_PORT_CMD_LSTATUS) #define G_FW_PORT_CMD_LSTATUS(x) \ (((x) >> S_FW_PORT_CMD_LSTATUS) & M_FW_PORT_CMD_LSTATUS) #define F_FW_PORT_CMD_LSTATUS V_FW_PORT_CMD_LSTATUS(1U) #define S_FW_PORT_CMD_LSPEED 24 #define M_FW_PORT_CMD_LSPEED 0x3f #define V_FW_PORT_CMD_LSPEED(x) ((x) << S_FW_PORT_CMD_LSPEED) #define G_FW_PORT_CMD_LSPEED(x) \ (((x) >> S_FW_PORT_CMD_LSPEED) & M_FW_PORT_CMD_LSPEED) #define S_FW_PORT_CMD_TXPAUSE 23 #define M_FW_PORT_CMD_TXPAUSE 0x1 #define V_FW_PORT_CMD_TXPAUSE(x) ((x) << S_FW_PORT_CMD_TXPAUSE) #define G_FW_PORT_CMD_TXPAUSE(x) \ (((x) >> S_FW_PORT_CMD_TXPAUSE) & M_FW_PORT_CMD_TXPAUSE) #define F_FW_PORT_CMD_TXPAUSE V_FW_PORT_CMD_TXPAUSE(1U) #define S_FW_PORT_CMD_RXPAUSE 22 #define M_FW_PORT_CMD_RXPAUSE 0x1 #define V_FW_PORT_CMD_RXPAUSE(x) ((x) << S_FW_PORT_CMD_RXPAUSE) #define G_FW_PORT_CMD_RXPAUSE(x) \ (((x) >> S_FW_PORT_CMD_RXPAUSE) & M_FW_PORT_CMD_RXPAUSE) #define F_FW_PORT_CMD_RXPAUSE V_FW_PORT_CMD_RXPAUSE(1U) #define S_FW_PORT_CMD_MDIOCAP 21 #define M_FW_PORT_CMD_MDIOCAP 0x1 #define V_FW_PORT_CMD_MDIOCAP(x) ((x) << S_FW_PORT_CMD_MDIOCAP) #define G_FW_PORT_CMD_MDIOCAP(x) \ (((x) >> S_FW_PORT_CMD_MDIOCAP) & M_FW_PORT_CMD_MDIOCAP) #define F_FW_PORT_CMD_MDIOCAP V_FW_PORT_CMD_MDIOCAP(1U) #define S_FW_PORT_CMD_MDIOADDR 16 #define M_FW_PORT_CMD_MDIOADDR 0x1f #define V_FW_PORT_CMD_MDIOADDR(x) ((x) << S_FW_PORT_CMD_MDIOADDR) #define G_FW_PORT_CMD_MDIOADDR(x) \ (((x) >> S_FW_PORT_CMD_MDIOADDR) & M_FW_PORT_CMD_MDIOADDR) #define S_FW_PORT_CMD_PTYPE 8 #define M_FW_PORT_CMD_PTYPE 0x1f #define V_FW_PORT_CMD_PTYPE(x) ((x) << S_FW_PORT_CMD_PTYPE) #define G_FW_PORT_CMD_PTYPE(x) \ (((x) >> S_FW_PORT_CMD_PTYPE) & M_FW_PORT_CMD_PTYPE) #define S_FW_PORT_CMD_LINKDNRC 5 #define M_FW_PORT_CMD_LINKDNRC 0x7 #define V_FW_PORT_CMD_LINKDNRC(x) ((x) << S_FW_PORT_CMD_LINKDNRC) #define G_FW_PORT_CMD_LINKDNRC(x) \ (((x) >> S_FW_PORT_CMD_LINKDNRC) & M_FW_PORT_CMD_LINKDNRC) #define S_FW_PORT_CMD_MODTYPE 0 #define M_FW_PORT_CMD_MODTYPE 0x1f #define V_FW_PORT_CMD_MODTYPE(x) ((x) << S_FW_PORT_CMD_MODTYPE) #define G_FW_PORT_CMD_MODTYPE(x) \ (((x) >> S_FW_PORT_CMD_MODTYPE) & M_FW_PORT_CMD_MODTYPE) /* * These are configured into the VPD and hence tools that generate * VPD may use this enumeration. * extPHY #lanes T4_I2C extI2C BP_Eq BP_ANEG Speed * * REMEMBER: * Update the Common Code t4_hw.c:t4_get_port_type_description() * with any new Firmware Port Technology Types! */ enum fw_port_type { FW_PORT_TYPE_FIBER_XFI = 0, /* Y, 1, N, Y, N, N, 10G */ FW_PORT_TYPE_FIBER_XAUI = 1, /* Y, 4, N, Y, N, N, 10G */ FW_PORT_TYPE_BT_SGMII = 2, /* Y, 1, No, No, No, No, 1G/100M */ FW_PORT_TYPE_BT_XFI = 3, /* Y, 1, No, No, No, No, 10G */ FW_PORT_TYPE_BT_XAUI = 4, /* Y, 4, No, No, No, No, 10G/1G/100M? */ FW_PORT_TYPE_KX4 = 5, /* No, 4, No, No, Yes, Yes, 10G */ FW_PORT_TYPE_CX4 = 6, /* No, 4, No, No, No, No, 10G */ FW_PORT_TYPE_KX = 7, /* No, 1, No, No, Yes, No, 1G */ FW_PORT_TYPE_KR = 8, /* No, 1, No, No, Yes, Yes, 10G */ FW_PORT_TYPE_SFP = 9, /* No, 1, Yes, No, No, No, 10G */ FW_PORT_TYPE_BP_AP = 10, /* No, 1, No, No, Yes, Yes, 10G, BP ANGE */ FW_PORT_TYPE_BP4_AP = 11, /* No, 4, No, No, Yes, Yes, 10G, BP ANGE */ FW_PORT_TYPE_QSFP_10G = 12, /* No, 1, Yes, No, No, No, 10G */ FW_PORT_TYPE_QSA = 13, /* No, 1, Yes, No, No, No, 10G */ FW_PORT_TYPE_QSFP = 14, /* No, 4, Yes, No, No, No, 40G */ FW_PORT_TYPE_BP40_BA = 15, /* No, 4, No, No, Yes, Yes, 40G/10G/1G, BP ANGE */ FW_PORT_TYPE_NONE = M_FW_PORT_CMD_PTYPE }; /* These are read from module's EEPROM and determined once the * module is inserted. */ enum fw_port_module_type { FW_PORT_MOD_TYPE_NA = 0x0, FW_PORT_MOD_TYPE_LR = 0x1, FW_PORT_MOD_TYPE_SR = 0x2, FW_PORT_MOD_TYPE_ER = 0x3, FW_PORT_MOD_TYPE_TWINAX_PASSIVE = 0x4, FW_PORT_MOD_TYPE_TWINAX_ACTIVE = 0x5, FW_PORT_MOD_TYPE_LRM = 0x6, FW_PORT_MOD_TYPE_ERROR = M_FW_PORT_CMD_MODTYPE - 3, FW_PORT_MOD_TYPE_UNKNOWN = M_FW_PORT_CMD_MODTYPE - 2, FW_PORT_MOD_TYPE_NOTSUPPORTED = M_FW_PORT_CMD_MODTYPE - 1, FW_PORT_MOD_TYPE_NONE = M_FW_PORT_CMD_MODTYPE }; /* used by FW and tools may use this to generate VPD */ enum fw_port_mod_sub_type { FW_PORT_MOD_SUB_TYPE_NA, FW_PORT_MOD_SUB_TYPE_MV88E114X = 0x1, FW_PORT_MOD_SUB_TYPE_TN8022 = 0x2, FW_PORT_MOD_SUB_TYPE_AQ1202 = 0x3, FW_PORT_MOD_SUB_TYPE_88x3120 = 0x4, FW_PORT_MOD_SUB_TYPE_BCM84834 = 0x5, FW_PORT_MOD_SUB_TYPE_BCM5482 = 0x6, FW_PORT_MOD_SUB_TYPE_BCM84856 = 0x7, FW_PORT_MOD_SUB_TYPE_BT_VSC8634 = 0x8, /* * The following will never been in the VPD. They are TWINAX cable * lengths decoded from SFP+ module i2c PROMs. These should almost * certainly go somewhere else ... */ FW_PORT_MOD_SUB_TYPE_TWINAX_1 = 0x9, FW_PORT_MOD_SUB_TYPE_TWINAX_3 = 0xA, FW_PORT_MOD_SUB_TYPE_TWINAX_5 = 0xB, FW_PORT_MOD_SUB_TYPE_TWINAX_7 = 0xC, }; /* link down reason codes (3b) */ enum fw_port_link_dn_rc { FW_PORT_LINK_DN_RC_NONE, FW_PORT_LINK_DN_RC_REMFLT, /* Remote fault detected */ FW_PORT_LINK_DN_ANEG_F, /* Auto-negotiation fault */ FW_PORT_LINK_DN_RESERVED3, FW_PORT_LINK_DN_OVERHEAT, /* Port overheated */ FW_PORT_LINK_DN_UNKNOWN, /* Unable to determine reason */ FW_PORT_LINK_DN_RX_LOS, /* No RX signal detected */ FW_PORT_LINK_DN_RESERVED7 }; /* port stats */ #define FW_NUM_PORT_STATS 50 #define FW_NUM_PORT_TX_STATS 23 #define FW_NUM_PORT_RX_STATS 27 enum fw_port_stats_tx_index { FW_STAT_TX_PORT_BYTES_IX, FW_STAT_TX_PORT_FRAMES_IX, FW_STAT_TX_PORT_BCAST_IX, FW_STAT_TX_PORT_MCAST_IX, FW_STAT_TX_PORT_UCAST_IX, FW_STAT_TX_PORT_ERROR_IX, FW_STAT_TX_PORT_64B_IX, FW_STAT_TX_PORT_65B_127B_IX, FW_STAT_TX_PORT_128B_255B_IX, FW_STAT_TX_PORT_256B_511B_IX, FW_STAT_TX_PORT_512B_1023B_IX, FW_STAT_TX_PORT_1024B_1518B_IX, FW_STAT_TX_PORT_1519B_MAX_IX, FW_STAT_TX_PORT_DROP_IX, FW_STAT_TX_PORT_PAUSE_IX, FW_STAT_TX_PORT_PPP0_IX, FW_STAT_TX_PORT_PPP1_IX, FW_STAT_TX_PORT_PPP2_IX, FW_STAT_TX_PORT_PPP3_IX, FW_STAT_TX_PORT_PPP4_IX, FW_STAT_TX_PORT_PPP5_IX, FW_STAT_TX_PORT_PPP6_IX, FW_STAT_TX_PORT_PPP7_IX }; enum fw_port_stat_rx_index { FW_STAT_RX_PORT_BYTES_IX, FW_STAT_RX_PORT_FRAMES_IX, FW_STAT_RX_PORT_BCAST_IX, FW_STAT_RX_PORT_MCAST_IX, FW_STAT_RX_PORT_UCAST_IX, FW_STAT_RX_PORT_MTU_ERROR_IX, FW_STAT_RX_PORT_MTU_CRC_ERROR_IX, FW_STAT_RX_PORT_CRC_ERROR_IX, FW_STAT_RX_PORT_LEN_ERROR_IX, FW_STAT_RX_PORT_SYM_ERROR_IX, FW_STAT_RX_PORT_64B_IX, FW_STAT_RX_PORT_65B_127B_IX, FW_STAT_RX_PORT_128B_255B_IX, FW_STAT_RX_PORT_256B_511B_IX, FW_STAT_RX_PORT_512B_1023B_IX, FW_STAT_RX_PORT_1024B_1518B_IX, FW_STAT_RX_PORT_1519B_MAX_IX, FW_STAT_RX_PORT_PAUSE_IX, FW_STAT_RX_PORT_PPP0_IX, FW_STAT_RX_PORT_PPP1_IX, FW_STAT_RX_PORT_PPP2_IX, FW_STAT_RX_PORT_PPP3_IX, FW_STAT_RX_PORT_PPP4_IX, FW_STAT_RX_PORT_PPP5_IX, FW_STAT_RX_PORT_PPP6_IX, FW_STAT_RX_PORT_PPP7_IX, FW_STAT_RX_PORT_LESS_64B_IX }; struct fw_port_stats_cmd { __be32 op_to_portid; __be32 retval_len16; union fw_port_stats { struct fw_port_stats_ctl { __u8 nstats_bg_bm; __u8 tx_ix; __be16 r6; __be32 r7; __be64 stat0; __be64 stat1; __be64 stat2; __be64 stat3; __be64 stat4; __be64 stat5; } ctl; struct fw_port_stats_all { __be64 tx_bytes; __be64 tx_frames; __be64 tx_bcast; __be64 tx_mcast; __be64 tx_ucast; __be64 tx_error; __be64 tx_64b; __be64 tx_65b_127b; __be64 tx_128b_255b; __be64 tx_256b_511b; __be64 tx_512b_1023b; __be64 tx_1024b_1518b; __be64 tx_1519b_max; __be64 tx_drop; __be64 tx_pause; __be64 tx_ppp0; __be64 tx_ppp1; __be64 tx_ppp2; __be64 tx_ppp3; __be64 tx_ppp4; __be64 tx_ppp5; __be64 tx_ppp6; __be64 tx_ppp7; __be64 rx_bytes; __be64 rx_frames; __be64 rx_bcast; __be64 rx_mcast; __be64 rx_ucast; __be64 rx_mtu_error; __be64 rx_mtu_crc_error; __be64 rx_crc_error; __be64 rx_len_error; __be64 rx_sym_error; __be64 rx_64b; __be64 rx_65b_127b; __be64 rx_128b_255b; __be64 rx_256b_511b; __be64 rx_512b_1023b; __be64 rx_1024b_1518b; __be64 rx_1519b_max; __be64 rx_pause; __be64 rx_ppp0; __be64 rx_ppp1; __be64 rx_ppp2; __be64 rx_ppp3; __be64 rx_ppp4; __be64 rx_ppp5; __be64 rx_ppp6; __be64 rx_ppp7; __be64 rx_less_64b; __be64 rx_bg_drop; __be64 rx_bg_trunc; } all; } u; }; struct fw_rss_ind_tbl_cmd { __be32 op_to_viid; __be32 retval_len16; __be16 niqid; __be16 startidx; __be32 r3; __be32 iq0_to_iq2; __be32 iq3_to_iq5; __be32 iq6_to_iq8; __be32 iq9_to_iq11; __be32 iq12_to_iq14; __be32 iq15_to_iq17; __be32 iq18_to_iq20; __be32 iq21_to_iq23; __be32 iq24_to_iq26; __be32 iq27_to_iq29; __be32 iq30_iq31; __be32 r15_lo; }; #define S_FW_RSS_IND_TBL_CMD_VIID 0 #define M_FW_RSS_IND_TBL_CMD_VIID 0xfff #define V_FW_RSS_IND_TBL_CMD_VIID(x) ((x) << S_FW_RSS_IND_TBL_CMD_VIID) #define G_FW_RSS_IND_TBL_CMD_VIID(x) \ (((x) >> S_FW_RSS_IND_TBL_CMD_VIID) & M_FW_RSS_IND_TBL_CMD_VIID) #define S_FW_RSS_IND_TBL_CMD_IQ0 20 #define M_FW_RSS_IND_TBL_CMD_IQ0 0x3ff #define V_FW_RSS_IND_TBL_CMD_IQ0(x) ((x) << S_FW_RSS_IND_TBL_CMD_IQ0) #define G_FW_RSS_IND_TBL_CMD_IQ0(x) \ (((x) >> S_FW_RSS_IND_TBL_CMD_IQ0) & M_FW_RSS_IND_TBL_CMD_IQ0) #define S_FW_RSS_IND_TBL_CMD_IQ1 10 #define M_FW_RSS_IND_TBL_CMD_IQ1 0x3ff #define V_FW_RSS_IND_TBL_CMD_IQ1(x) ((x) << S_FW_RSS_IND_TBL_CMD_IQ1) #define G_FW_RSS_IND_TBL_CMD_IQ1(x) \ (((x) >> S_FW_RSS_IND_TBL_CMD_IQ1) & M_FW_RSS_IND_TBL_CMD_IQ1) #define S_FW_RSS_IND_TBL_CMD_IQ2 0 #define M_FW_RSS_IND_TBL_CMD_IQ2 0x3ff #define V_FW_RSS_IND_TBL_CMD_IQ2(x) ((x) << S_FW_RSS_IND_TBL_CMD_IQ2) #define G_FW_RSS_IND_TBL_CMD_IQ2(x) \ (((x) >> S_FW_RSS_IND_TBL_CMD_IQ2) & M_FW_RSS_IND_TBL_CMD_IQ2) struct fw_rss_vi_config_cmd { __be32 op_to_viid; __be32 retval_len16; union fw_rss_vi_config { struct fw_rss_vi_config_manual { __be64 r3; __be64 r4; __be64 r5; } manual; struct fw_rss_vi_config_basicvirtual { __be32 r6; __be32 defaultq_to_udpen; __be64 r9; __be64 r10; } basicvirtual; } u; }; #define S_FW_RSS_VI_CONFIG_CMD_VIID 0 #define M_FW_RSS_VI_CONFIG_CMD_VIID 0xfff #define V_FW_RSS_VI_CONFIG_CMD_VIID(x) ((x) << S_FW_RSS_VI_CONFIG_CMD_VIID) #define G_FW_RSS_VI_CONFIG_CMD_VIID(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_VIID) & M_FW_RSS_VI_CONFIG_CMD_VIID) #define S_FW_RSS_VI_CONFIG_CMD_DEFAULTQ 16 #define M_FW_RSS_VI_CONFIG_CMD_DEFAULTQ 0x3ff #define V_FW_RSS_VI_CONFIG_CMD_DEFAULTQ(x) \ ((x) << S_FW_RSS_VI_CONFIG_CMD_DEFAULTQ) #define G_FW_RSS_VI_CONFIG_CMD_DEFAULTQ(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_DEFAULTQ) & \ M_FW_RSS_VI_CONFIG_CMD_DEFAULTQ) #define S_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN 4 #define M_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN 0x1 #define V_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN(x) \ ((x) << S_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) #define G_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) & \ M_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) #define F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN \ V_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN(1U) #define S_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN 3 #define M_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN 0x1 #define V_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN(x) \ ((x) << S_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) #define G_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) & \ M_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) #define F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN \ V_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN(1U) #define S_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN 2 #define M_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN 0x1 #define V_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN(x) \ ((x) << S_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) #define G_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) & \ M_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) #define F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN \ V_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN(1U) #define S_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN 1 #define M_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN 0x1 #define V_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN(x) \ ((x) << S_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) #define G_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) & \ M_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) #define F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN \ V_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN(1U) #define S_FW_RSS_VI_CONFIG_CMD_UDPEN 0 #define M_FW_RSS_VI_CONFIG_CMD_UDPEN 0x1 #define V_FW_RSS_VI_CONFIG_CMD_UDPEN(x) ((x) << S_FW_RSS_VI_CONFIG_CMD_UDPEN) #define G_FW_RSS_VI_CONFIG_CMD_UDPEN(x) \ (((x) >> S_FW_RSS_VI_CONFIG_CMD_UDPEN) & M_FW_RSS_VI_CONFIG_CMD_UDPEN) #define F_FW_RSS_VI_CONFIG_CMD_UDPEN V_FW_RSS_VI_CONFIG_CMD_UDPEN(1U) /****************************************************************************** * D E B U G C O M M A N D s ******************************************************/ struct fw_debug_cmd { __be32 op_type; __be32 len16_pkd; union fw_debug { struct fw_debug_assert { __be32 fcid; __be32 line; __be32 x; __be32 y; __u8 filename_0_7[8]; __u8 filename_8_15[8]; __be64 r3; } assert; struct fw_debug_prt { __be16 dprtstridx; __be16 r3[3]; __be32 dprtstrparam0; __be32 dprtstrparam1; __be32 dprtstrparam2; __be32 dprtstrparam3; } prt; } u; }; #define S_FW_DEBUG_CMD_TYPE 0 #define M_FW_DEBUG_CMD_TYPE 0xff #define V_FW_DEBUG_CMD_TYPE(x) ((x) << S_FW_DEBUG_CMD_TYPE) #define G_FW_DEBUG_CMD_TYPE(x) \ (((x) >> S_FW_DEBUG_CMD_TYPE) & M_FW_DEBUG_CMD_TYPE) /****************************************************************************** * P C I E F W R E G I S T E R **************************************/ /* * Register definitions for the PCIE_FW register which the firmware uses * to retain status across RESETs. This register should be considered * as a READ-ONLY register for Host Software and only to be used to * track firmware initialization/error state, etc. */ #define S_PCIE_FW_ERR 31 #define M_PCIE_FW_ERR 0x1 #define V_PCIE_FW_ERR(x) ((x) << S_PCIE_FW_ERR) #define G_PCIE_FW_ERR(x) (((x) >> S_PCIE_FW_ERR) & M_PCIE_FW_ERR) #define F_PCIE_FW_ERR V_PCIE_FW_ERR(1U) #define S_PCIE_FW_INIT 30 #define M_PCIE_FW_INIT 0x1 #define V_PCIE_FW_INIT(x) ((x) << S_PCIE_FW_INIT) #define G_PCIE_FW_INIT(x) (((x) >> S_PCIE_FW_INIT) & M_PCIE_FW_INIT) #define F_PCIE_FW_INIT V_PCIE_FW_INIT(1U) #define S_PCIE_FW_HALT 29 #define M_PCIE_FW_HALT 0x1 #define V_PCIE_FW_HALT(x) ((x) << S_PCIE_FW_HALT) #define G_PCIE_FW_HALT(x) (((x) >> S_PCIE_FW_HALT) & M_PCIE_FW_HALT) #define F_PCIE_FW_HALT V_PCIE_FW_HALT(1U) #define S_PCIE_FW_EVAL 24 #define M_PCIE_FW_EVAL 0x7 #define V_PCIE_FW_EVAL(x) ((x) << S_PCIE_FW_EVAL) #define G_PCIE_FW_EVAL(x) (((x) >> S_PCIE_FW_EVAL) & M_PCIE_FW_EVAL) #define S_PCIE_FW_MASTER_VLD 15 #define M_PCIE_FW_MASTER_VLD 0x1 #define V_PCIE_FW_MASTER_VLD(x) ((x) << S_PCIE_FW_MASTER_VLD) #define G_PCIE_FW_MASTER_VLD(x) \ (((x) >> S_PCIE_FW_MASTER_VLD) & M_PCIE_FW_MASTER_VLD) #define F_PCIE_FW_MASTER_VLD V_PCIE_FW_MASTER_VLD(1U) #define S_PCIE_FW_MASTER 12 #define M_PCIE_FW_MASTER 0x7 #define V_PCIE_FW_MASTER(x) ((x) << S_PCIE_FW_MASTER) #define G_PCIE_FW_MASTER(x) (((x) >> S_PCIE_FW_MASTER) & M_PCIE_FW_MASTER) /****************************************************************************** * B I N A R Y H E A D E R F O R M A T **********************************************/ /* * firmware binary header format */ struct fw_hdr { __u8 ver; __u8 chip; /* terminator chip family */ __be16 len512; /* bin length in units of 512-bytes */ __be32 fw_ver; /* firmware version */ __be32 tp_microcode_ver; /* tcp processor microcode version */ __u8 intfver_nic; __u8 intfver_vnic; __u8 intfver_ofld; __u8 intfver_ri; __u8 intfver_iscsipdu; __u8 intfver_iscsi; __u8 intfver_fcoepdu; __u8 intfver_fcoe; __u32 reserved2; __u32 reserved3; __u32 magic; /* runtime or bootstrap fw */ __be32 flags; __be32 reserved6[23]; }; #define S_FW_HDR_FW_VER_MAJOR 24 #define M_FW_HDR_FW_VER_MAJOR 0xff #define V_FW_HDR_FW_VER_MAJOR(x) \ ((x) << S_FW_HDR_FW_VER_MAJOR) #define G_FW_HDR_FW_VER_MAJOR(x) \ (((x) >> S_FW_HDR_FW_VER_MAJOR) & M_FW_HDR_FW_VER_MAJOR) #define S_FW_HDR_FW_VER_MINOR 16 #define M_FW_HDR_FW_VER_MINOR 0xff #define V_FW_HDR_FW_VER_MINOR(x) \ ((x) << S_FW_HDR_FW_VER_MINOR) #define G_FW_HDR_FW_VER_MINOR(x) \ (((x) >> S_FW_HDR_FW_VER_MINOR) & M_FW_HDR_FW_VER_MINOR) #define S_FW_HDR_FW_VER_MICRO 8 #define M_FW_HDR_FW_VER_MICRO 0xff #define V_FW_HDR_FW_VER_MICRO(x) \ ((x) << S_FW_HDR_FW_VER_MICRO) #define G_FW_HDR_FW_VER_MICRO(x) \ (((x) >> S_FW_HDR_FW_VER_MICRO) & M_FW_HDR_FW_VER_MICRO) #define S_FW_HDR_FW_VER_BUILD 0 #define M_FW_HDR_FW_VER_BUILD 0xff #define V_FW_HDR_FW_VER_BUILD(x) \ ((x) << S_FW_HDR_FW_VER_BUILD) #define G_FW_HDR_FW_VER_BUILD(x) \ (((x) >> S_FW_HDR_FW_VER_BUILD) & M_FW_HDR_FW_VER_BUILD) #endif /* _T4FW_INTERFACE_H_ */ ================================================ FILE: drivers/net/cxgbe/cxgbe.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CXGBE_H_ #define _CXGBE_H_ #include "common.h" #include "t4_regs.h" #define CXGBE_MIN_RING_DESC_SIZE 1024 /* Min TX/RX descriptor ring size */ #define CXGBE_MAX_RING_DESC_SIZE 4096 /* Max TX/RX descriptor ring size */ #define CXGBE_DEFAULT_TX_DESC_SIZE 1024 /* Default TX ring size */ #define CXGBE_DEFAULT_RX_DESC_SIZE 1024 /* Default RX ring size */ int cxgbe_probe(struct adapter *adapter); int cxgbe_up(struct adapter *adap); int cxgbe_down(struct port_info *pi); void cxgbe_close(struct adapter *adapter); void cxgbe_stats_get(struct port_info *pi, struct port_stats *stats); void cxgbe_stats_reset(struct port_info *pi); int link_start(struct port_info *pi); void init_rspq(struct adapter *adap, struct sge_rspq *q, unsigned int us, unsigned int cnt, unsigned int size, unsigned int iqe_size); int setup_sge_fwevtq(struct adapter *adapter); void cfg_queues(struct rte_eth_dev *eth_dev); int cfg_queue_count(struct rte_eth_dev *eth_dev); int setup_rss(struct port_info *pi); #endif /* _CXGBE_H_ */ ================================================ FILE: drivers/net/cxgbe/cxgbe_compat.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CXGBE_COMPAT_H_ #define _CXGBE_COMPAT_H_ #include #include #include #include #include #include #include #include #include #include #define dev_printf(level, fmt, args...) \ RTE_LOG(level, PMD, "rte_cxgbe_pmd: " fmt, ## args) #define dev_err(x, args...) dev_printf(ERR, args) #define dev_info(x, args...) dev_printf(INFO, args) #define dev_warn(x, args...) dev_printf(WARNING, args) #ifdef RTE_LIBRTE_CXGBE_DEBUG #define dev_debug(x, args...) dev_printf(DEBUG, args) #else #define dev_debug(x, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_CXGBE_DEBUG_REG #define CXGBE_DEBUG_REG(x, args...) dev_printf(DEBUG, "REG:" args) #else #define CXGBE_DEBUG_REG(x, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_CXGBE_DEBUG_MBOX #define CXGBE_DEBUG_MBOX(x, args...) dev_printf(DEBUG, "MBOX:" args) #else #define CXGBE_DEBUG_MBOX(x, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_CXGBE_DEBUG_TX #define CXGBE_DEBUG_TX(x, args...) dev_printf(DEBUG, "TX:" args) #else #define CXGBE_DEBUG_TX(x, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_CXGBE_DEBUG_RX #define CXGBE_DEBUG_RX(x, args...) dev_printf(DEBUG, "RX:" args) #else #define CXGBE_DEBUG_RX(x, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_CXGBE_DEBUG #define CXGBE_FUNC_TRACE() \ RTE_LOG(DEBUG, PMD, "CXGBE trace: %s\n", __func__) #else #define CXGBE_FUNC_TRACE() do { } while (0) #endif #define pr_err(y, args...) dev_err(0, y, ##args) #define pr_warn(y, args...) dev_warn(0, y, ##args) #define pr_info(y, args...) dev_info(0, y, ##args) #define BUG() pr_err("BUG at %s:%d", __func__, __LINE__) #define ASSERT(x) do {\ if (!(x)) \ rte_panic("CXGBE: x"); \ } while (0) #define BUG_ON(x) ASSERT(!(x)) #ifndef WARN_ON #define WARN_ON(x) do { \ int ret = !!(x); \ if (unlikely(ret)) \ pr_warn("WARN_ON: \"" #x "\" at %s:%d\n", __func__, __LINE__); \ } while (0) #endif #define __iomem #ifndef BIT #define BIT(n) (1 << (n)) #endif #define L1_CACHE_SHIFT 6 #define L1_CACHE_BYTES BIT(L1_CACHE_SHIFT) #define PAGE_SHIFT 12 #define CXGBE_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define PTR_ALIGN(p, a) ((typeof(p))CXGBE_ALIGN((unsigned long)(p), (a))) #define VLAN_HLEN 4 #define rmb() rte_rmb() /* dpdk rte provided rmb */ #define wmb() rte_wmb() /* dpdk rte provided wmb */ typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; typedef int bool; typedef uint64_t dma_addr_t; #ifndef __le16 #define __le16 uint16_t #endif #ifndef __le32 #define __le32 uint32_t #endif #ifndef __le64 #define __le64 uint64_t #endif #ifndef __be16 #define __be16 uint16_t #endif #ifndef __be32 #define __be32 uint32_t #endif #ifndef __be64 #define __be64 uint64_t #endif #ifndef __u8 #define __u8 uint8_t #endif #ifndef __u16 #define __u16 uint16_t #endif #ifndef __u32 #define __u32 uint32_t #endif #ifndef __u64 #define __u64 uint64_t #endif #define FALSE 0 #define TRUE 1 #define false 0 #define true 1 #define min(a, b) RTE_MIN(a, b) #define max(a, b) RTE_MAX(a, b) /* * round up val _p to a power of 2 size _s */ #define cxgbe_roundup(_p, _s) (((unsigned long)(_p) + (_s - 1)) & ~(_s - 1)) #undef container_of #define container_of(ptr, type, member) ({ \ typeof(((type *)0)->member)(*__mptr) = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) #define ARRAY_SIZE(arr) RTE_DIM(arr) #define cpu_to_be16(o) rte_cpu_to_be_16(o) #define cpu_to_be32(o) rte_cpu_to_be_32(o) #define cpu_to_be64(o) rte_cpu_to_be_64(o) #define cpu_to_le32(o) rte_cpu_to_le_32(o) #define be16_to_cpu(o) rte_be_to_cpu_16(o) #define be32_to_cpu(o) rte_be_to_cpu_32(o) #define be64_to_cpu(o) rte_be_to_cpu_64(o) #define le32_to_cpu(o) rte_le_to_cpu_32(o) #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) #define DELAY(x) rte_delay_us(x) #define udelay(x) DELAY(x) #define msleep(x) DELAY(1000 * (x)) #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000)) static inline uint8_t hweight32(uint32_t word32) { uint32_t res = word32 - ((word32 >> 1) & 0x55555555); res = (res & 0x33333333) + ((res >> 2) & 0x33333333); res = (res + (res >> 4)) & 0x0F0F0F0F; res = res + (res >> 8); return (res + (res >> 16)) & 0x000000FF; } /* weight32 */ /** * cxgbe_fls - find last (most-significant) bit set * @x: the word to search * * This is defined the same way as ffs. * Note cxgbe_fls(0) = 0, cxgbe_fls(1) = 1, cxgbe_fls(0x80000000) = 32. */ static inline int cxgbe_fls(int x) { return x ? sizeof(x) * 8 - __builtin_clz(x) : 0; } static inline unsigned long ilog2(unsigned long n) { unsigned int e = 0; while (n) { if (n & ~((1 << 8) - 1)) { e += 8; n >>= 8; continue; } if (n & ~((1 << 4) - 1)) { e += 4; n >>= 4; } for (;;) { n >>= 1; if (n == 0) break; e++; } } return e; } static inline void writel(unsigned int val, volatile void __iomem *addr) { *(volatile unsigned int *)addr = val; } static inline void writeq(u64 val, volatile void __iomem *addr) { writel(val, addr); writel(val >> 32, (void *)((uintptr_t)addr + 4)); } #endif /* _CXGBE_COMPAT_H_ */ ================================================ FILE: drivers/net/cxgbe/cxgbe_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cxgbe.h" /* * Macros needed to support the PCI Device ID Table ... */ #define CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN \ static struct rte_pci_id cxgb4_pci_tbl[] = { #define CH_PCI_DEVICE_ID_FUNCTION 0x4 #define PCI_VENDOR_ID_CHELSIO 0x1425 #define CH_PCI_ID_TABLE_ENTRY(devid) \ { RTE_PCI_DEVICE(PCI_VENDOR_ID_CHELSIO, (devid)) } #define CH_PCI_DEVICE_ID_TABLE_DEFINE_END \ { .vendor_id = 0, } \ } /* *... and the PCI ID Table itself ... */ #include "t4_pci_id_tbl.h" static uint16_t cxgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct sge_eth_txq *txq = (struct sge_eth_txq *)tx_queue; uint16_t pkts_sent, pkts_remain; uint16_t total_sent = 0; int ret = 0; CXGBE_DEBUG_TX(adapter, "%s: txq = %p; tx_pkts = %p; nb_pkts = %d\n", __func__, txq, tx_pkts, nb_pkts); t4_os_lock(&txq->txq_lock); /* free up desc from already completed tx */ reclaim_completed_tx(&txq->q); while (total_sent < nb_pkts) { pkts_remain = nb_pkts - total_sent; for (pkts_sent = 0; pkts_sent < pkts_remain; pkts_sent++) { ret = t4_eth_xmit(txq, tx_pkts[total_sent + pkts_sent]); if (ret < 0) break; } if (!pkts_sent) break; total_sent += pkts_sent; /* reclaim as much as possible */ reclaim_completed_tx(&txq->q); } t4_os_unlock(&txq->txq_lock); return total_sent; } static uint16_t cxgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct sge_eth_rxq *rxq = (struct sge_eth_rxq *)rx_queue; unsigned int work_done; CXGBE_DEBUG_RX(adapter, "%s: rxq->rspq.cntxt_id = %u; nb_pkts = %d\n", __func__, rxq->rspq.cntxt_id, nb_pkts); if (cxgbe_poll(&rxq->rspq, rx_pkts, (unsigned int)nb_pkts, &work_done)) dev_err(adapter, "error in cxgbe poll\n"); CXGBE_DEBUG_RX(adapter, "%s: work_done = %u\n", __func__, work_done); return work_done; } static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *device_info) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; int max_queues = adapter->sge.max_ethqsets / adapter->params.nports; device_info->min_rx_bufsize = 68; /* XXX: Smallest pkt size */ device_info->max_rx_pktlen = 1500; /* XXX: For now we support mtu */ device_info->max_rx_queues = max_queues; device_info->max_tx_queues = max_queues; device_info->max_mac_addrs = 1; /* XXX: For now we support one MAC/port */ device_info->max_vfs = adapter->params.arch.vfcount; device_info->max_vmdq_pools = 0; /* XXX: For now no support for VMDQ */ device_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; device_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_TCP_TSO; device_info->reta_size = pi->rss_size; } static void cxgbe_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, 1, -1, 1, -1, false); } static void cxgbe_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, 0, -1, 1, -1, false); } static void cxgbe_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; /* TODO: address filters ?? */ t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, -1, 1, 1, -1, false); } static void cxgbe_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; /* TODO: address filters ?? */ t4_set_rxmode(adapter, adapter->mbox, pi->viid, -1, -1, 0, 1, -1, false); } static int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; struct rte_eth_link *old_link = ð_dev->data->dev_link; unsigned int work_done, budget = 4; cxgbe_poll(&s->fw_evtq, NULL, budget, &work_done); if (old_link->link_status == pi->link_cfg.link_ok) return -1; /* link not changed */ eth_dev->data->dev_link.link_status = pi->link_cfg.link_ok; eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; eth_dev->data->dev_link.link_speed = pi->link_cfg.speed; /* link has changed */ return 0; } static int cxgbe_dev_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id); static int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id); static void cxgbe_dev_tx_queue_release(void *q); static void cxgbe_dev_rx_queue_release(void *q); /* * Stop device. */ static void cxgbe_dev_close(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; int i, dev_down = 0; CXGBE_FUNC_TRACE(); if (!(adapter->flags & FULL_INIT_DONE)) return; cxgbe_down(pi); /* * We clear queues only if both tx and rx path of the port * have been disabled */ t4_sge_eth_clear_queues(pi); /* See if all ports are down */ for_each_port(adapter, i) { pi = adap2pinfo(adapter, i); /* * Skip first port of the adapter since it will be closed * by DPDK */ if (i == 0) continue; dev_down += (pi->eth_dev->data->dev_started == 0) ? 1 : 0; } /* If rest of the ports are stopped, then free up resources */ if (dev_down == (adapter->params.nports - 1)) cxgbe_close(adapter); } /* Start the device. * It returns 0 on success. */ static int cxgbe_dev_start(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; int err = 0, i; CXGBE_FUNC_TRACE(); /* * If we don't have a connection to the firmware there's nothing we * can do. */ if (!(adapter->flags & FW_OK)) { err = -ENXIO; goto out; } if (!(adapter->flags & FULL_INIT_DONE)) { err = cxgbe_up(adapter); if (err < 0) goto out; } err = setup_rss(pi); if (err) goto out; for (i = 0; i < pi->n_tx_qsets; i++) { err = cxgbe_dev_tx_queue_start(eth_dev, i); if (err) goto out; } for (i = 0; i < pi->n_rx_qsets; i++) { err = cxgbe_dev_rx_queue_start(eth_dev, i); if (err) goto out; } err = link_start(pi); if (err) goto out; out: return err; } /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ static void cxgbe_dev_stop(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; CXGBE_FUNC_TRACE(); if (!(adapter->flags & FULL_INIT_DONE)) return; cxgbe_down(pi); /* * We clear queues only if both tx and rx path of the port * have been disabled */ t4_sge_eth_clear_queues(pi); } static int cxgbe_dev_configure(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; int err; CXGBE_FUNC_TRACE(); if (!(adapter->flags & FW_QUEUE_BOUND)) { err = setup_sge_fwevtq(adapter); if (err) return err; adapter->flags |= FW_QUEUE_BOUND; } err = cfg_queue_count(eth_dev); if (err) return err; return 0; } static int cxgbe_dev_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id) { struct sge_eth_txq *txq = (struct sge_eth_txq *) (eth_dev->data->tx_queues[tx_queue_id]); dev_debug(NULL, "%s: tx_queue_id = %d\n", __func__, tx_queue_id); return t4_sge_eth_txq_start(txq); } static int cxgbe_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t tx_queue_id) { struct sge_eth_txq *txq = (struct sge_eth_txq *) (eth_dev->data->tx_queues[tx_queue_id]); dev_debug(NULL, "%s: tx_queue_id = %d\n", __func__, tx_queue_id); return t4_sge_eth_txq_stop(txq); } static int cxgbe_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset + queue_idx]; int err = 0; unsigned int temp_nb_desc; RTE_SET_USED(tx_conf); dev_debug(adapter, "%s: eth_dev->data->nb_tx_queues = %d; queue_idx = %d; nb_desc = %d; socket_id = %d; pi->first_qset = %u\n", __func__, eth_dev->data->nb_tx_queues, queue_idx, nb_desc, socket_id, pi->first_qset); /* Free up the existing queue */ if (eth_dev->data->tx_queues[queue_idx]) { cxgbe_dev_tx_queue_release(eth_dev->data->tx_queues[queue_idx]); eth_dev->data->tx_queues[queue_idx] = NULL; } eth_dev->data->tx_queues[queue_idx] = (void *)txq; /* Sanity Checking * * nb_desc should be > 1023 and <= CXGBE_MAX_RING_DESC_SIZE */ temp_nb_desc = nb_desc; if (nb_desc < CXGBE_MIN_RING_DESC_SIZE) { dev_warn(adapter, "%s: number of descriptors must be >= %d. Using default [%d]\n", __func__, CXGBE_MIN_RING_DESC_SIZE, CXGBE_DEFAULT_TX_DESC_SIZE); temp_nb_desc = CXGBE_DEFAULT_TX_DESC_SIZE; } else if (nb_desc > CXGBE_MAX_RING_DESC_SIZE) { dev_err(adapter, "%s: number of descriptors must be between %d and %d inclusive. Default [%d]\n", __func__, CXGBE_MIN_RING_DESC_SIZE, CXGBE_MAX_RING_DESC_SIZE, CXGBE_DEFAULT_TX_DESC_SIZE); return -(EINVAL); } txq->q.size = temp_nb_desc; err = t4_sge_alloc_eth_txq(adapter, txq, eth_dev, queue_idx, s->fw_evtq.cntxt_id, socket_id); dev_debug(adapter, "%s: txq->q.cntxt_id= %d err = %d\n", __func__, txq->q.cntxt_id, err); return err; } static void cxgbe_dev_tx_queue_release(void *q) { struct sge_eth_txq *txq = (struct sge_eth_txq *)q; if (txq) { struct port_info *pi = (struct port_info *) (txq->eth_dev->data->dev_private); struct adapter *adap = pi->adapter; dev_debug(adapter, "%s: pi->port_id = %d; tx_queue_id = %d\n", __func__, pi->port_id, txq->q.cntxt_id); t4_sge_eth_txq_release(adap, txq); } } static int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adap = pi->adapter; struct sge_rspq *q; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); q = eth_dev->data->rx_queues[rx_queue_id]; return t4_sge_eth_rxq_start(adap, q); } static int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adap = pi->adapter; struct sge_rspq *q; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); q = eth_dev->data->rx_queues[rx_queue_id]; return t4_sge_eth_rxq_stop(adap, q); } static int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset + queue_idx]; int err = 0; int msi_idx = 0; unsigned int temp_nb_desc; RTE_SET_USED(rx_conf); dev_debug(adapter, "%s: eth_dev->data->nb_rx_queues = %d; queue_idx = %d; nb_desc = %d; socket_id = %d; mp = %p\n", __func__, eth_dev->data->nb_rx_queues, queue_idx, nb_desc, socket_id, mp); /* Free up the existing queue */ if (eth_dev->data->rx_queues[queue_idx]) { cxgbe_dev_rx_queue_release(eth_dev->data->rx_queues[queue_idx]); eth_dev->data->rx_queues[queue_idx] = NULL; } eth_dev->data->rx_queues[queue_idx] = (void *)rxq; /* Sanity Checking * * nb_desc should be > 0 and <= CXGBE_MAX_RING_DESC_SIZE */ temp_nb_desc = nb_desc; if (nb_desc < CXGBE_MIN_RING_DESC_SIZE) { dev_warn(adapter, "%s: number of descriptors must be >= %d. Using default [%d]\n", __func__, CXGBE_MIN_RING_DESC_SIZE, CXGBE_DEFAULT_RX_DESC_SIZE); temp_nb_desc = CXGBE_DEFAULT_RX_DESC_SIZE; } else if (nb_desc > CXGBE_MAX_RING_DESC_SIZE) { dev_err(adapter, "%s: number of descriptors must be between %d and %d inclusive. Default [%d]\n", __func__, CXGBE_MIN_RING_DESC_SIZE, CXGBE_MAX_RING_DESC_SIZE, CXGBE_DEFAULT_RX_DESC_SIZE); return -(EINVAL); } rxq->rspq.size = temp_nb_desc; if ((&rxq->fl) != NULL) rxq->fl.size = temp_nb_desc; err = t4_sge_alloc_rxq(adapter, &rxq->rspq, false, eth_dev, msi_idx, &rxq->fl, t4_ethrx_handler, t4_get_mps_bg_map(adapter, pi->tx_chan), mp, queue_idx, socket_id); dev_debug(adapter, "%s: err = %d; port_id = %d; cntxt_id = %u\n", __func__, err, pi->port_id, rxq->rspq.cntxt_id); return err; } static void cxgbe_dev_rx_queue_release(void *q) { struct sge_eth_rxq *rxq = (struct sge_eth_rxq *)q; struct sge_rspq *rq = &rxq->rspq; if (rq) { struct port_info *pi = (struct port_info *) (rq->eth_dev->data->dev_private); struct adapter *adap = pi->adapter; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rxq->rspq.cntxt_id); t4_sge_eth_rxq_release(adap, rxq); } } /* * Get port statistics. */ static void cxgbe_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *eth_stats) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; struct port_stats ps; unsigned int i; cxgbe_stats_get(pi, &ps); /* RX Stats */ eth_stats->ipackets = ps.rx_frames; eth_stats->ibytes = ps.rx_octets; eth_stats->imcasts = ps.rx_mcast_frames; eth_stats->imissed = ps.rx_ovflow0 + ps.rx_ovflow1 + ps.rx_ovflow2 + ps.rx_ovflow3 + ps.rx_trunc0 + ps.rx_trunc1 + ps.rx_trunc2 + ps.rx_trunc3; eth_stats->ibadcrc = ps.rx_fcs_err; eth_stats->ibadlen = ps.rx_jabber + ps.rx_too_long + ps.rx_runt; eth_stats->ierrors = ps.rx_symbol_err + eth_stats->ibadcrc + eth_stats->ibadlen + ps.rx_len_err + eth_stats->imissed; eth_stats->rx_pause_xon = ps.rx_pause; /* TX Stats */ eth_stats->opackets = ps.tx_frames; eth_stats->obytes = ps.tx_octets; eth_stats->oerrors = ps.tx_error_frames; eth_stats->tx_pause_xon = ps.tx_pause; for (i = 0; i < pi->n_rx_qsets; i++) { struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset + i]; eth_stats->q_ipackets[i] = rxq->stats.pkts; eth_stats->q_ibytes[i] = rxq->stats.rx_bytes; } for (i = 0; i < pi->n_tx_qsets; i++) { struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset + i]; eth_stats->q_opackets[i] = txq->stats.pkts; eth_stats->q_obytes[i] = txq->stats.tx_bytes; eth_stats->q_errors[i] = txq->stats.mapping_err; } } /* * Reset port statistics. */ static void cxgbe_dev_stats_reset(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct sge *s = &adapter->sge; unsigned int i; cxgbe_stats_reset(pi); for (i = 0; i < pi->n_rx_qsets; i++) { struct sge_eth_rxq *rxq = &s->ethrxq[pi->first_qset + i]; rxq->stats.pkts = 0; rxq->stats.rx_bytes = 0; } for (i = 0; i < pi->n_tx_qsets; i++) { struct sge_eth_txq *txq = &s->ethtxq[pi->first_qset + i]; txq->stats.pkts = 0; txq->stats.tx_bytes = 0; txq->stats.mapping_err = 0; } } static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev, struct rte_eth_fc_conf *fc_conf) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct link_config *lc = &pi->link_cfg; int rx_pause, tx_pause; fc_conf->autoneg = lc->fc & PAUSE_AUTONEG; rx_pause = lc->fc & PAUSE_RX; tx_pause = lc->fc & PAUSE_TX; if (rx_pause && tx_pause) fc_conf->mode = RTE_FC_FULL; else if (rx_pause) fc_conf->mode = RTE_FC_RX_PAUSE; else if (tx_pause) fc_conf->mode = RTE_FC_TX_PAUSE; else fc_conf->mode = RTE_FC_NONE; return 0; } static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev, struct rte_eth_fc_conf *fc_conf) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = pi->adapter; struct link_config *lc = &pi->link_cfg; if (lc->supported & FW_PORT_CAP_ANEG) { if (fc_conf->autoneg) lc->requested_fc |= PAUSE_AUTONEG; else lc->requested_fc &= ~PAUSE_AUTONEG; } if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || (fc_conf->mode & RTE_FC_RX_PAUSE)) lc->requested_fc |= PAUSE_RX; else lc->requested_fc &= ~PAUSE_RX; if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || (fc_conf->mode & RTE_FC_TX_PAUSE)) lc->requested_fc |= PAUSE_TX; else lc->requested_fc &= ~PAUSE_TX; return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, &pi->link_cfg); } static struct eth_dev_ops cxgbe_eth_dev_ops = { .dev_start = cxgbe_dev_start, .dev_stop = cxgbe_dev_stop, .dev_close = cxgbe_dev_close, .promiscuous_enable = cxgbe_dev_promiscuous_enable, .promiscuous_disable = cxgbe_dev_promiscuous_disable, .allmulticast_enable = cxgbe_dev_allmulticast_enable, .allmulticast_disable = cxgbe_dev_allmulticast_disable, .dev_configure = cxgbe_dev_configure, .dev_infos_get = cxgbe_dev_info_get, .link_update = cxgbe_dev_link_update, .tx_queue_setup = cxgbe_dev_tx_queue_setup, .tx_queue_start = cxgbe_dev_tx_queue_start, .tx_queue_stop = cxgbe_dev_tx_queue_stop, .tx_queue_release = cxgbe_dev_tx_queue_release, .rx_queue_setup = cxgbe_dev_rx_queue_setup, .rx_queue_start = cxgbe_dev_rx_queue_start, .rx_queue_stop = cxgbe_dev_rx_queue_stop, .rx_queue_release = cxgbe_dev_rx_queue_release, .stats_get = cxgbe_dev_stats_get, .stats_reset = cxgbe_dev_stats_reset, .flow_ctrl_get = cxgbe_flow_ctrl_get, .flow_ctrl_set = cxgbe_flow_ctrl_set, }; /* * Initialize driver * It returns 0 on success. */ static int eth_cxgbe_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adapter = NULL; char name[RTE_ETH_NAME_MAX_LEN]; int err = 0; CXGBE_FUNC_TRACE(); eth_dev->dev_ops = &cxgbe_eth_dev_ops; eth_dev->rx_pkt_burst = &cxgbe_recv_pkts; eth_dev->tx_pkt_burst = &cxgbe_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; pci_dev = eth_dev->pci_dev; snprintf(name, sizeof(name), "cxgbeadapter%d", eth_dev->data->port_id); adapter = rte_zmalloc(name, sizeof(*adapter), 0); if (!adapter) return -1; adapter->use_unpacked_mode = 1; adapter->regs = (void *)pci_dev->mem_resource[0].addr; if (!adapter->regs) { dev_err(adapter, "%s: cannot map device registers\n", __func__); err = -ENOMEM; goto out_free_adapter; } adapter->pdev = pci_dev; adapter->eth_dev = eth_dev; pi->adapter = adapter; err = cxgbe_probe(adapter); if (err) dev_err(adapter, "%s: cxgbe probe failed with err %d\n", __func__, err); out_free_adapter: return err; } static struct eth_driver rte_cxgbe_pmd = { { .name = "rte_cxgbe_pmd", .id_table = cxgb4_pci_tbl, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_cxgbe_dev_init, .dev_private_size = sizeof(struct port_info), }; /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of PCI CXGBE devices. */ static int rte_cxgbe_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { CXGBE_FUNC_TRACE(); rte_eth_driver_register(&rte_cxgbe_pmd); return 0; } static struct rte_driver rte_cxgbe_driver = { .name = "cxgbe_driver", .type = PMD_PDEV, .init = rte_cxgbe_pmd_init, }; PMD_REGISTER_DRIVER(rte_cxgbe_driver); ================================================ FILE: drivers/net/cxgbe/cxgbe_main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "t4_regs.h" #include "t4_msg.h" #include "cxgbe.h" /* * Response queue handler for the FW event queue. */ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, __rte_unused const struct pkt_gl *gl) { u8 opcode = ((const struct rss_header *)rsp)->opcode; rsp++; /* skip RSS header */ /* * FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG. */ if (unlikely(opcode == CPL_FW4_MSG && ((const struct cpl_fw4_msg *)rsp)->type == FW_TYPE_RSSCPL)) { rsp++; opcode = ((const struct rss_header *)rsp)->opcode; rsp++; if (opcode != CPL_SGE_EGR_UPDATE) { dev_err(q->adapter, "unexpected FW4/CPL %#x on FW event queue\n", opcode); goto out; } } if (likely(opcode == CPL_SGE_EGR_UPDATE)) { /* do nothing */ } else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) { const struct cpl_fw6_msg *msg = (const void *)rsp; t4_handle_fw_rpl(q->adapter, msg->data); } else { dev_err(adapter, "unexpected CPL %#x on FW event queue\n", opcode); } out: return 0; } int setup_sge_fwevtq(struct adapter *adapter) { struct sge *s = &adapter->sge; int err = 0; int msi_idx = 0; err = t4_sge_alloc_rxq(adapter, &s->fw_evtq, true, adapter->eth_dev, msi_idx, NULL, fwevtq_handler, -1, NULL, 0, rte_socket_id()); return err; } static int closest_timer(const struct sge *s, int time) { unsigned int i, match = 0; int delta, min_delta = INT_MAX; for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) { delta = time - s->timer_val[i]; if (delta < 0) delta = -delta; if (delta < min_delta) { min_delta = delta; match = i; } } return match; } static int closest_thres(const struct sge *s, int thres) { unsigned int i, match = 0; int delta, min_delta = INT_MAX; for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) { delta = thres - s->counter_val[i]; if (delta < 0) delta = -delta; if (delta < min_delta) { min_delta = delta; match = i; } } return match; } /** * cxgb4_set_rspq_intr_params - set a queue's interrupt holdoff parameters * @q: the Rx queue * @us: the hold-off time in us, or 0 to disable timer * @cnt: the hold-off packet count, or 0 to disable counter * * Sets an Rx queue's interrupt hold-off time and packet count. At least * one of the two needs to be enabled for the queue to generate interrupts. */ int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us, unsigned int cnt) { struct adapter *adap = q->adapter; unsigned int timer_val; if (cnt) { int err; u32 v, new_idx; new_idx = closest_thres(&adap->sge, cnt); if (q->desc && q->pktcnt_idx != new_idx) { /* the queue has already been created, update it */ v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | V_FW_PARAMS_PARAM_X( FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) | V_FW_PARAMS_PARAM_YZ(q->cntxt_id); err = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &v, &new_idx); if (err) return err; } q->pktcnt_idx = new_idx; } timer_val = (us == 0) ? X_TIMERREG_RESTART_COUNTER : closest_timer(&adap->sge, us); if ((us | cnt) == 0) q->intr_params = V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX); else q->intr_params = V_QINTR_TIMER_IDX(timer_val) | V_QINTR_CNT_EN(cnt > 0); return 0; } static inline bool is_x_1g_port(const struct link_config *lc) { return ((lc->supported & FW_PORT_CAP_SPEED_1G) != 0); } static inline bool is_x_10g_port(const struct link_config *lc) { return ((lc->supported & FW_PORT_CAP_SPEED_10G) != 0 || (lc->supported & FW_PORT_CAP_SPEED_40G) != 0 || (lc->supported & FW_PORT_CAP_SPEED_100G) != 0); } inline void init_rspq(struct adapter *adap, struct sge_rspq *q, unsigned int us, unsigned int cnt, unsigned int size, unsigned int iqe_size) { q->adapter = adap; cxgb4_set_rspq_intr_params(q, us, cnt); q->iqe_len = iqe_size; q->size = size; } int cfg_queue_count(struct rte_eth_dev *eth_dev) { struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adap = pi->adapter; struct sge *s = &adap->sge; unsigned int max_queues = s->max_ethqsets / adap->params.nports; if ((eth_dev->data->nb_rx_queues < 1) || (eth_dev->data->nb_tx_queues < 1)) return -EINVAL; if ((eth_dev->data->nb_rx_queues > max_queues) || (eth_dev->data->nb_tx_queues > max_queues)) return -EINVAL; if (eth_dev->data->nb_rx_queues > pi->rss_size) return -EINVAL; /* We must configure RSS, since config has changed*/ pi->flags &= ~PORT_RSS_DONE; pi->n_rx_qsets = eth_dev->data->nb_rx_queues; pi->n_tx_qsets = eth_dev->data->nb_tx_queues; return 0; } void cfg_queues(struct rte_eth_dev *eth_dev) { struct rte_config *config = rte_eal_get_configuration(); struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); struct adapter *adap = pi->adapter; struct sge *s = &adap->sge; unsigned int i, nb_ports = 0, qidx = 0; unsigned int q_per_port = 0; if (!(adap->flags & CFG_QUEUES)) { for_each_port(adap, i) { struct port_info *tpi = adap2pinfo(adap, i); nb_ports += (is_x_10g_port(&tpi->link_cfg)) || is_x_1g_port(&tpi->link_cfg) ? 1 : 0; } /* * We default up to # of cores queues per 1G/10G port. */ if (nb_ports) q_per_port = (MAX_ETH_QSETS - (adap->params.nports - nb_ports)) / nb_ports; if (q_per_port > config->lcore_count) q_per_port = config->lcore_count; for_each_port(adap, i) { struct port_info *pi = adap2pinfo(adap, i); pi->first_qset = qidx; /* Initially n_rx_qsets == n_tx_qsets */ pi->n_rx_qsets = (is_x_10g_port(&pi->link_cfg) || is_x_1g_port(&pi->link_cfg)) ? q_per_port : 1; pi->n_tx_qsets = pi->n_rx_qsets; if (pi->n_rx_qsets > pi->rss_size) pi->n_rx_qsets = pi->rss_size; qidx += pi->n_rx_qsets; } s->max_ethqsets = qidx; for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) { struct sge_eth_rxq *r = &s->ethrxq[i]; init_rspq(adap, &r->rspq, 0, 0, 1024, 64); r->usembufs = 1; r->fl.size = (r->usembufs ? 1024 : 72); } for (i = 0; i < ARRAY_SIZE(s->ethtxq); i++) s->ethtxq[i].q.size = 1024; init_rspq(adap, &adap->sge.fw_evtq, 0, 0, 1024, 64); adap->flags |= CFG_QUEUES; } } void cxgbe_stats_get(struct port_info *pi, struct port_stats *stats) { t4_get_port_stats_offset(pi->adapter, pi->tx_chan, stats, &pi->stats_base); } void cxgbe_stats_reset(struct port_info *pi) { t4_clr_port_stats(pi->adapter, pi->tx_chan); } static void setup_memwin(struct adapter *adap) { u32 mem_win0_base; /* For T5, only relative offset inside the PCIe BAR is passed */ mem_win0_base = MEMWIN0_BASE; /* * Set up memory window for accessing adapter memory ranges. (Read * back MA register to ensure that changes propagate before we attempt * to use the new values.) */ t4_write_reg(adap, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, MEMWIN_NIC), mem_win0_base | V_BIR(0) | V_WINDOW(ilog2(MEMWIN0_APERTURE) - X_WINDOW_SHIFT)); t4_read_reg(adap, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, MEMWIN_NIC)); } static int init_rss(struct adapter *adap) { unsigned int i; int err; err = t4_init_rss_mode(adap, adap->mbox); if (err) return err; for_each_port(adap, i) { struct port_info *pi = adap2pinfo(adap, i); pi->rss = rte_zmalloc(NULL, pi->rss_size, 0); if (!pi->rss) return -ENOMEM; } return 0; } static void print_port_info(struct adapter *adap) { int i; char buf[80]; struct rte_pci_addr *loc = &adap->pdev->addr; for_each_port(adap, i) { const struct port_info *pi = &adap->port[i]; char *bufp = buf; if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M) bufp += sprintf(bufp, "100/"); if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G) bufp += sprintf(bufp, "1000/"); if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) bufp += sprintf(bufp, "10G/"); if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G) bufp += sprintf(bufp, "40G/"); if (bufp != buf) --bufp; sprintf(bufp, "BASE-%s", t4_get_port_type_description( (enum fw_port_type)pi->port_type)); dev_info(adap, " " PCI_PRI_FMT " Chelsio rev %d %s %s\n", loc->domain, loc->bus, loc->devid, loc->function, CHELSIO_CHIP_RELEASE(adap->params.chip), buf, (adap->flags & USING_MSIX) ? " MSI-X" : (adap->flags & USING_MSI) ? " MSI" : ""); } } /* * Tweak configuration based on system architecture, etc. Most of these have * defaults assigned to them by Firmware Configuration Files (if we're using * them) but need to be explicitly set if we're using hard-coded * initialization. So these are essentially common tweaks/settings for * Configuration Files and hard-coded initialization ... */ static int adap_init0_tweaks(struct adapter *adapter) { u8 rx_dma_offset; /* * Fix up various Host-Dependent Parameters like Page Size, Cache * Line Size, etc. The firmware default is for a 4KB Page Size and * 64B Cache Line Size ... */ t4_fixup_host_params_compat(adapter, CXGBE_PAGE_SIZE, L1_CACHE_BYTES, T5_LAST_REV); /* * Keep the chip default offset to deliver Ingress packets into our * DMA buffers to zero */ rx_dma_offset = 0; t4_set_reg_field(adapter, A_SGE_CONTROL, V_PKTSHIFT(M_PKTSHIFT), V_PKTSHIFT(rx_dma_offset)); /* * Don't include the "IP Pseudo Header" in CPL_RX_PKT checksums: Linux * adds the pseudo header itself. */ t4_tp_wr_bits_indirect(adapter, A_TP_INGRESS_CONFIG, F_CSUM_HAS_PSEUDO_HDR, 0); return 0; } /* * Attempt to initialize the adapter via a Firmware Configuration File. */ static int adap_init0_config(struct adapter *adapter, int reset) { struct fw_caps_config_cmd caps_cmd; unsigned long mtype = 0, maddr = 0; u32 finiver, finicsum, cfcsum; int ret; int config_issued = 0; int cfg_addr; char config_name[20]; /* * Reset device if necessary. */ if (reset) { ret = t4_fw_reset(adapter, adapter->mbox, F_PIORSTMODE | F_PIORST); if (ret < 0) { dev_warn(adapter, "Firmware reset failed, error %d\n", -ret); goto bye; } } cfg_addr = t4_flash_cfg_addr(adapter); if (cfg_addr < 0) { ret = cfg_addr; dev_warn(adapter, "Finding address for firmware config file in flash failed, error %d\n", -ret); goto bye; } strcpy(config_name, "On Flash"); mtype = FW_MEMTYPE_CF_FLASH; maddr = cfg_addr; /* * Issue a Capability Configuration command to the firmware to get it * to parse the Configuration File. We don't use t4_fw_config_file() * because we want the ability to modify various features after we've * processed the configuration file ... */ memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ); caps_cmd.cfvalid_to_len16 = cpu_to_be32(F_FW_CAPS_CONFIG_CMD_CFVALID | V_FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | V_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) | FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); /* * If the CAPS_CONFIG failed with an ENOENT (for a Firmware * Configuration File in FLASH), our last gasp effort is to use the * Firmware Configuration File which is embedded in the firmware. A * very few early versions of the firmware didn't have one embedded * but we can ignore those. */ if (ret == -ENOENT) { dev_info(adapter, "%s: Going for embedded config in firmware..\n", __func__); memset(&caps_cmd, 0, sizeof(caps_cmd)); caps_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ); caps_cmd.cfvalid_to_len16 = cpu_to_be32(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), &caps_cmd); strcpy(config_name, "Firmware Default"); } config_issued = 1; if (ret < 0) goto bye; finiver = be32_to_cpu(caps_cmd.finiver); finicsum = be32_to_cpu(caps_cmd.finicsum); cfcsum = be32_to_cpu(caps_cmd.cfcsum); if (finicsum != cfcsum) dev_warn(adapter, "Configuration File checksum mismatch: [fini] csum=%#x, computed csum=%#x\n", finicsum, cfcsum); /* * If we're a pure NIC driver then disable all offloading facilities. * This will allow the firmware to optimize aspects of the hardware * configuration which will result in improved performance. */ caps_cmd.niccaps &= cpu_to_be16(~(FW_CAPS_CONFIG_NIC_HASHFILTER | FW_CAPS_CONFIG_NIC_ETHOFLD)); caps_cmd.toecaps = 0; caps_cmd.iscsicaps = 0; caps_cmd.rdmacaps = 0; caps_cmd.fcoecaps = 0; /* * And now tell the firmware to use the configuration we just loaded. */ caps_cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE); caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), NULL); if (ret < 0) { dev_warn(adapter, "Unable to finalize Firmware Capabilities %d\n", -ret); goto bye; } /* * Tweak configuration based on system architecture, etc. */ ret = adap_init0_tweaks(adapter); if (ret < 0) { dev_warn(adapter, "Unable to do init0-tweaks %d\n", -ret); goto bye; } /* * And finally tell the firmware to initialize itself using the * parameters from the Configuration File. */ ret = t4_fw_initialize(adapter, adapter->mbox); if (ret < 0) { dev_warn(adapter, "Initializing Firmware failed, error %d\n", -ret); goto bye; } /* * Return successfully and note that we're operating with parameters * not supplied by the driver, rather than from hard-wired * initialization constants burried in the driver. */ dev_info(adapter, "Successfully configured using Firmware Configuration File \"%s\", version %#x, computed checksum %#x\n", config_name, finiver, cfcsum); return 0; /* * Something bad happened. Return the error ... (If the "error" * is that there's no Configuration File on the adapter we don't * want to issue a warning since this is fairly common.) */ bye: if (config_issued && ret != -ENOENT) dev_warn(adapter, "\"%s\" configuration file error %d\n", config_name, -ret); dev_debug(adapter, "%s: returning ret = %d ..\n", __func__, ret); return ret; } static int adap_init0(struct adapter *adap) { int ret = 0; u32 v, port_vec; enum dev_state state; u32 params[7], val[7]; int reset = 1; int mbox = adap->mbox; /* * Contact FW, advertising Master capability. */ ret = t4_fw_hello(adap, adap->mbox, adap->mbox, MASTER_MAY, &state); if (ret < 0) { dev_err(adap, "%s: could not connect to FW, error %d\n", __func__, -ret); goto bye; } CXGBE_DEBUG_MBOX(adap, "%s: adap->mbox = %d; ret = %d\n", __func__, adap->mbox, ret); if (ret == mbox) adap->flags |= MASTER_PF; if (state == DEV_STATE_INIT) { /* * Force halt and reset FW because a previous instance may have * exited abnormally without properly shutting down */ ret = t4_fw_halt(adap, adap->mbox, reset); if (ret < 0) { dev_err(adap, "Failed to halt. Exit.\n"); goto bye; } ret = t4_fw_restart(adap, adap->mbox, reset); if (ret < 0) { dev_err(adap, "Failed to restart. Exit.\n"); goto bye; } state = (enum dev_state)((unsigned)state & ~DEV_STATE_INIT); } t4_get_fw_version(adap, &adap->params.fw_vers); t4_get_tp_version(adap, &adap->params.tp_vers); dev_info(adap, "fw: %u.%u.%u.%u, TP: %u.%u.%u.%u\n", G_FW_HDR_FW_VER_MAJOR(adap->params.fw_vers), G_FW_HDR_FW_VER_MINOR(adap->params.fw_vers), G_FW_HDR_FW_VER_MICRO(adap->params.fw_vers), G_FW_HDR_FW_VER_BUILD(adap->params.fw_vers), G_FW_HDR_FW_VER_MAJOR(adap->params.tp_vers), G_FW_HDR_FW_VER_MINOR(adap->params.tp_vers), G_FW_HDR_FW_VER_MICRO(adap->params.tp_vers), G_FW_HDR_FW_VER_BUILD(adap->params.tp_vers)); ret = t4_get_core_clock(adap, &adap->params.vpd); if (ret < 0) { dev_err(adap, "%s: could not get core clock, error %d\n", __func__, -ret); goto bye; } /* * Find out what ports are available to us. Note that we need to do * this before calling adap_init0_no_config() since it needs nports * and portvec ... */ v = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC); ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, &v, &port_vec); if (ret < 0) { dev_err(adap, "%s: failure in t4_queury_params; error = %d\n", __func__, ret); goto bye; } adap->params.nports = hweight32(port_vec); adap->params.portvec = port_vec; dev_debug(adap, "%s: adap->params.nports = %u\n", __func__, adap->params.nports); /* * If the firmware is initialized already (and we're not forcing a * master initialization), note that we're living with existing * adapter parameters. Otherwise, it's time to try initializing the * adapter ... */ if (state == DEV_STATE_INIT) { dev_info(adap, "Coming up as %s: Adapter already initialized\n", adap->flags & MASTER_PF ? "MASTER" : "SLAVE"); } else { dev_info(adap, "Coming up as MASTER: Initializing adapter\n"); ret = adap_init0_config(adap, reset); if (ret == -ENOENT) { dev_err(adap, "No Configuration File present on adapter. Using hard-wired configuration parameters.\n"); goto bye; } } if (ret < 0) { dev_err(adap, "could not initialize adapter, error %d\n", -ret); goto bye; } /* * Give the SGE code a chance to pull in anything that it needs ... * Note that this must be called after we retrieve our VPD parameters * in order to know how to convert core ticks to seconds, etc. */ ret = t4_sge_init(adap); if (ret < 0) { dev_err(adap, "t4_sge_init failed with error %d\n", -ret); goto bye; } /* * Grab some of our basic fundamental operating parameters. */ #define FW_PARAM_DEV(param) \ (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) #define FW_PARAM_PFVF(param) \ (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \ V_FW_PARAMS_PARAM_Y(0) | \ V_FW_PARAMS_PARAM_Z(0)) /* If we're running on newer firmware, let it know that we're * prepared to deal with encapsulated CPL messages. Older * firmware won't understand this and we'll just get * unencapsulated messages ... */ params[0] = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); val[0] = 1; (void)t4_set_params(adap, adap->mbox, adap->pf, 0, 1, params, val); /* * Find out whether we're allowed to use the T5+ ULPTX MEMWRITE DSGL * capability. Earlier versions of the firmware didn't have the * ULPTX_MEMWRITE_DSGL so we'll interpret a query failure as no * permission to use ULPTX MEMWRITE DSGL. */ if (is_t4(adap->params.chip)) { adap->params.ulptx_memwrite_dsgl = false; } else { params[0] = FW_PARAM_DEV(ULPTX_MEMWRITE_DSGL); ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, params, val); adap->params.ulptx_memwrite_dsgl = (ret == 0 && val[0] != 0); } /* * The MTU/MSS Table is initialized by now, so load their values. If * we're initializing the adapter, then we'll make any modifications * we want to the MTU/MSS Table and also initialize the congestion * parameters. */ t4_read_mtu_tbl(adap, adap->params.mtus, NULL); if (state != DEV_STATE_INIT) { int i; /* * The default MTU Table contains values 1492 and 1500. * However, for TCP, it's better to have two values which are * a multiple of 8 +/- 4 bytes apart near this popular MTU. * This allows us to have a TCP Data Payload which is a * multiple of 8 regardless of what combination of TCP Options * are in use (always a multiple of 4 bytes) which is * important for performance reasons. For instance, if no * options are in use, then we have a 20-byte IP header and a * 20-byte TCP header. In this case, a 1500-byte MSS would * result in a TCP Data Payload of 1500 - 40 == 1460 bytes * which is not a multiple of 8. So using an MSS of 1488 in * this case results in a TCP Data Payload of 1448 bytes which * is a multiple of 8. On the other hand, if 12-byte TCP Time * Stamps have been negotiated, then an MTU of 1500 bytes * results in a TCP Data Payload of 1448 bytes which, as * above, is a multiple of 8 bytes ... */ for (i = 0; i < NMTUS; i++) if (adap->params.mtus[i] == 1492) { adap->params.mtus[i] = 1488; break; } t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, adap->params.b_wnd); } t4_init_sge_params(adap); t4_init_tp_params(adap); adap->params.drv_memwin = MEMWIN_NIC; adap->flags |= FW_OK; dev_debug(adap, "%s: returning zero..\n", __func__); return 0; /* * Something bad happened. If a command timed out or failed with EIO * FW does not operate within its spec or something catastrophic * happened to HW/FW, stop issuing commands. */ bye: if (ret != -ETIMEDOUT && ret != -EIO) t4_fw_bye(adap, adap->mbox); return ret; } /** * t4_os_portmod_changed - handle port module changes * @adap: the adapter associated with the module change * @port_id: the port index whose module status has changed * * This is the OS-dependent handler for port module changes. It is * invoked when a port module is removed or inserted for any OS-specific * processing. */ void t4_os_portmod_changed(const struct adapter *adap, int port_id) { static const char * const mod_str[] = { NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" }; const struct port_info *pi = &adap->port[port_id]; if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) dev_info(adap, "Port%d: port module unplugged\n", pi->port_id); else if (pi->mod_type < ARRAY_SIZE(mod_str)) dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id, mod_str[pi->mod_type]); else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) dev_info(adap, "Port%d: unsupported optical port module inserted\n", pi->port_id); else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) dev_info(adap, "Port%d: unknown port module inserted, forcing TWINAX\n", pi->port_id); else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR) dev_info(adap, "Port%d: transceiver module error\n", pi->port_id); else dev_info(adap, "Port%d: unknown module type %d inserted\n", pi->port_id, pi->mod_type); } /** * link_start - enable a port * @dev: the port to enable * * Performs the MAC and PHY actions needed to enable a port. */ int link_start(struct port_info *pi) { struct adapter *adapter = pi->adapter; int ret; /* * We do not set address filters and promiscuity here, the stack does * that step explicitly. */ ret = t4_set_rxmode(adapter, adapter->mbox, pi->viid, 1500, -1, -1, -1, 1, true); if (ret == 0) { ret = t4_change_mac(adapter, adapter->mbox, pi->viid, pi->xact_addr_filt, (u8 *)&pi->eth_dev->data->mac_addrs[0], true, true); if (ret >= 0) { pi->xact_addr_filt = ret; ret = 0; } } if (ret == 0) ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan, &pi->link_cfg); if (ret == 0) { /* * Enabling a Virtual Interface can result in an interrupt * during the processing of the VI Enable command and, in some * paths, result in an attempt to issue another command in the * interrupt context. Thus, we disable interrupts during the * course of the VI Enable command ... */ ret = t4_enable_vi_params(adapter, adapter->mbox, pi->viid, true, true, false); } return ret; } /** * cxgb4_write_rss - write the RSS table for a given port * @pi: the port * @queues: array of queue indices for RSS * * Sets up the portion of the HW RSS table for the port's VI to distribute * packets to the Rx queues in @queues. */ int cxgb4_write_rss(const struct port_info *pi, const u16 *queues) { u16 *rss; int i, err; struct adapter *adapter = pi->adapter; const struct sge_eth_rxq *rxq; /* Should never be called before setting up sge eth rx queues */ BUG_ON(!(adapter->flags & FULL_INIT_DONE)); rxq = &adapter->sge.ethrxq[pi->first_qset]; rss = rte_zmalloc(NULL, pi->rss_size * sizeof(u16), 0); if (!rss) return -ENOMEM; /* map the queue indices to queue ids */ for (i = 0; i < pi->rss_size; i++, queues++) rss[i] = rxq[*queues].rspq.abs_id; err = t4_config_rss_range(adapter, adapter->pf, pi->viid, 0, pi->rss_size, rss, pi->rss_size); /* * If Tunnel All Lookup isn't specified in the global RSS * Configuration, then we need to specify a default Ingress * Queue for any ingress packets which aren't hashed. We'll * use our first ingress queue ... */ if (!err) err = t4_config_vi_rss(adapter, adapter->mbox, pi->viid, F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_UDPEN, rss[0]); rte_free(rss); return err; } /** * setup_rss - configure RSS * @adapter: the adapter * * Sets up RSS to distribute packets to multiple receive queues. We * configure the RSS CPU lookup table to distribute to the number of HW * receive queues, and the response queue lookup table to narrow that * down to the response queues actually configured for each port. * We always configure the RSS mapping for all ports since the mapping * table has plenty of entries. */ int setup_rss(struct port_info *pi) { int j, err; struct adapter *adapter = pi->adapter; dev_debug(adapter, "%s: pi->rss_size = %u; pi->n_rx_qsets = %u\n", __func__, pi->rss_size, pi->n_rx_qsets); if (!pi->flags & PORT_RSS_DONE) { if (adapter->flags & FULL_INIT_DONE) { /* Fill default values with equal distribution */ for (j = 0; j < pi->rss_size; j++) pi->rss[j] = j % pi->n_rx_qsets; err = cxgb4_write_rss(pi, pi->rss); if (err) return err; pi->flags |= PORT_RSS_DONE; } } return 0; } /* * Enable NAPI scheduling and interrupt generation for all Rx queues. */ static void enable_rx(struct adapter *adap) { struct sge *s = &adap->sge; struct sge_rspq *q = &s->fw_evtq; int i, j; /* 0-increment GTS to start the timer and enable interrupts */ t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS), V_SEINTARM(q->intr_params) | V_INGRESSQID(q->cntxt_id)); for_each_port(adap, i) { const struct port_info *pi = &adap->port[i]; struct rte_eth_dev *eth_dev = pi->eth_dev; for (j = 0; j < eth_dev->data->nb_rx_queues; j++) { q = eth_dev->data->rx_queues[j]; /* * 0-increment GTS to start the timer and enable * interrupts */ t4_write_reg(adap, MYPF_REG(A_SGE_PF_GTS), V_SEINTARM(q->intr_params) | V_INGRESSQID(q->cntxt_id)); } } } /** * cxgb_up - enable the adapter * @adap: adapter being enabled * * Called when the first port is enabled, this function performs the * actions necessary to make an adapter operational, such as completing * the initialization of HW modules, and enabling interrupts. */ int cxgbe_up(struct adapter *adap) { enable_rx(adap); t4_sge_tx_monitor_start(adap); t4_intr_enable(adap); adap->flags |= FULL_INIT_DONE; /* TODO: deadman watchdog ?? */ return 0; } /* * Close the port */ int cxgbe_down(struct port_info *pi) { struct adapter *adapter = pi->adapter; int err = 0; err = t4_enable_vi(adapter, adapter->mbox, pi->viid, false, false); if (err) { dev_err(adapter, "%s: disable_vi failed: %d\n", __func__, err); return err; } t4_reset_link_config(adapter, pi->port_id); return 0; } /* * Release resources when all the ports have been stopped. */ void cxgbe_close(struct adapter *adapter) { struct port_info *pi; int i; if (adapter->flags & FULL_INIT_DONE) { t4_intr_disable(adapter); t4_sge_tx_monitor_stop(adapter); t4_free_sge_resources(adapter); for_each_port(adapter, i) { pi = adap2pinfo(adapter, i); if (pi->viid != 0) t4_free_vi(adapter, adapter->mbox, adapter->pf, 0, pi->viid); rte_free(pi->eth_dev->data->mac_addrs); } adapter->flags &= ~FULL_INIT_DONE; } if (adapter->flags & FW_OK) t4_fw_bye(adapter, adapter->mbox); } int cxgbe_probe(struct adapter *adapter) { struct port_info *pi; int func, i; int err = 0; func = G_SOURCEPF(t4_read_reg(adapter, A_PL_WHOAMI)); adapter->mbox = func; adapter->pf = func; t4_os_lock_init(&adapter->mbox_lock); TAILQ_INIT(&adapter->mbox_list); err = t4_prep_adapter(adapter); if (err) return err; setup_memwin(adapter); err = adap_init0(adapter); if (err) { dev_err(adapter, "%s: Adapter initialization failed, error %d\n", __func__, err); goto out_free; } if (!is_t4(adapter->params.chip)) { /* * The userspace doorbell BAR is split evenly into doorbell * regions, each associated with an egress queue. If this * per-queue region is large enough (at least UDBS_SEG_SIZE) * then it can be used to submit a tx work request with an * implied doorbell. Enable write combining on the BAR if * there is room for such work requests. */ int s_qpp, qpp, num_seg; s_qpp = (S_QUEUESPERPAGEPF0 + (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * adapter->pf); qpp = 1 << ((t4_read_reg(adapter, A_SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp) & M_QUEUESPERPAGEPF0); num_seg = CXGBE_PAGE_SIZE / UDBS_SEG_SIZE; if (qpp > num_seg) dev_warn(adapter, "Incorrect SGE EGRESS QUEUES_PER_PAGE configuration, continuing in debug mode\n"); adapter->bar2 = (void *)adapter->pdev->mem_resource[2].addr; if (!adapter->bar2) { dev_err(adapter, "cannot map device bar2 region\n"); err = -ENOMEM; goto out_free; } t4_write_reg(adapter, A_SGE_STAT_CFG, V_STATSOURCE_T5(7) | V_STATMODE(0)); } for_each_port(adapter, i) { char name[RTE_ETH_NAME_MAX_LEN]; struct rte_eth_dev_data *data = NULL; const unsigned int numa_node = rte_socket_id(); pi = &adapter->port[i]; pi->adapter = adapter; pi->xact_addr_filt = -1; pi->port_id = i; snprintf(name, sizeof(name), "cxgbe%d", adapter->eth_dev->data->port_id + i); if (i == 0) { /* First port is already allocated by DPDK */ pi->eth_dev = adapter->eth_dev; goto allocate_mac; } /* * now do all data allocation - for eth_dev structure, * and internal (private) data for the remaining ports */ /* reserve an ethdev entry */ pi->eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PCI); if (!pi->eth_dev) goto out_free; data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (!data) goto out_free; data->port_id = adapter->eth_dev->data->port_id + i; pi->eth_dev->data = data; allocate_mac: pi->eth_dev->pci_dev = adapter->pdev; pi->eth_dev->data->dev_private = pi; pi->eth_dev->driver = adapter->eth_dev->driver; pi->eth_dev->dev_ops = adapter->eth_dev->dev_ops; pi->eth_dev->tx_pkt_burst = adapter->eth_dev->tx_pkt_burst; pi->eth_dev->rx_pkt_burst = adapter->eth_dev->rx_pkt_burst; TAILQ_INIT(&pi->eth_dev->link_intr_cbs); pi->eth_dev->data->mac_addrs = rte_zmalloc(name, ETHER_ADDR_LEN, 0); if (!pi->eth_dev->data->mac_addrs) { dev_err(adapter, "%s: Mem allocation failed for storing mac addr, aborting\n", __func__); err = -1; goto out_free; } } if (adapter->flags & FW_OK) { err = t4_port_init(adapter, adapter->mbox, adapter->pf, 0); if (err) { dev_err(adapter, "%s: t4_port_init failed with err %d\n", __func__, err); goto out_free; } } cfg_queues(adapter->eth_dev); print_port_info(adapter); err = init_rss(adapter); if (err) goto out_free; return 0; out_free: for_each_port(adapter, i) { pi = adap2pinfo(adapter, i); if (pi->viid != 0) t4_free_vi(adapter, adapter->mbox, adapter->pf, 0, pi->viid); /* Skip first port since it'll be de-allocated by DPDK */ if (i == 0) continue; if (pi->eth_dev->data) rte_free(pi->eth_dev->data); } if (adapter->flags & FW_OK) t4_fw_bye(adapter, adapter->mbox); return -err; } ================================================ FILE: drivers/net/cxgbe/sge.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2014-2015 Chelsio Communications. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Chelsio Communications nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "t4_regs.h" #include "t4_msg.h" #include "cxgbe.h" static inline void ship_tx_pkt_coalesce_wr(struct adapter *adap, struct sge_eth_txq *txq); /* * Max number of Rx buffers we replenish at a time. */ #define MAX_RX_REFILL 64U #define NOMEM_TMR_IDX (SGE_NTIMERS - 1) /* * Max Tx descriptor space we allow for an Ethernet packet to be inlined * into a WR. */ #define MAX_IMM_TX_PKT_LEN 256 /* * Rx buffer sizes for "usembufs" Free List buffers (one ingress packet * per mbuf buffer). We currently only support two sizes for 1500- and * 9000-byte MTUs. We could easily support more but there doesn't seem to be * much need for that ... */ #define FL_MTU_SMALL 1500 #define FL_MTU_LARGE 9000 static inline unsigned int fl_mtu_bufsize(struct adapter *adapter, unsigned int mtu) { struct sge *s = &adapter->sge; return CXGBE_ALIGN(s->pktshift + ETHER_HDR_LEN + VLAN_HLEN + mtu, s->fl_align); } #define FL_MTU_SMALL_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_SMALL) #define FL_MTU_LARGE_BUFSIZE(adapter) fl_mtu_bufsize(adapter, FL_MTU_LARGE) /* * Bits 0..3 of rx_sw_desc.dma_addr have special meaning. The hardware uses * these to specify the buffer size as an index into the SGE Free List Buffer * Size register array. We also use bit 4, when the buffer has been unmapped * for DMA, but this is of course never sent to the hardware and is only used * to prevent double unmappings. All of the above requires that the Free List * Buffers which we allocate have the bottom 5 bits free (0) -- i.e. are * 32-byte or or a power of 2 greater in alignment. Since the SGE's minimal * Free List Buffer alignment is 32 bytes, this works out for us ... */ enum { RX_BUF_FLAGS = 0x1f, /* bottom five bits are special */ RX_BUF_SIZE = 0x0f, /* bottom three bits are for buf sizes */ RX_UNMAPPED_BUF = 0x10, /* buffer is not mapped */ /* * XXX We shouldn't depend on being able to use these indices. * XXX Especially when some other Master PF has initialized the * XXX adapter or we use the Firmware Configuration File. We * XXX should really search through the Host Buffer Size register * XXX array for the appropriately sized buffer indices. */ RX_SMALL_PG_BUF = 0x0, /* small (PAGE_SIZE) page buffer */ RX_LARGE_PG_BUF = 0x1, /* buffer large page buffer */ RX_SMALL_MTU_BUF = 0x2, /* small MTU buffer */ RX_LARGE_MTU_BUF = 0x3, /* large MTU buffer */ }; /** * txq_avail - return the number of available slots in a Tx queue * @q: the Tx queue * * Returns the number of descriptors in a Tx queue available to write new * packets. */ static inline unsigned int txq_avail(const struct sge_txq *q) { return q->size - 1 - q->in_use; } static int map_mbuf(struct rte_mbuf *mbuf, dma_addr_t *addr) { struct rte_mbuf *m = mbuf; for (; m; m = m->next, addr++) { *addr = m->buf_physaddr + rte_pktmbuf_headroom(m); if (*addr == 0) goto out_err; } return 0; out_err: return -ENOMEM; } /** * free_tx_desc - reclaims Tx descriptors and their buffers * @q: the Tx queue to reclaim descriptors from * @n: the number of descriptors to reclaim * * Reclaims Tx descriptors from an SGE Tx queue and frees the associated * Tx buffers. Called with the Tx queue lock held. */ static void free_tx_desc(struct sge_txq *q, unsigned int n) { struct tx_sw_desc *d; unsigned int cidx = 0; d = &q->sdesc[cidx]; while (n--) { if (d->mbuf) { /* an SGL is present */ rte_pktmbuf_free(d->mbuf); d->mbuf = NULL; } if (d->coalesce.idx) { int i; for (i = 0; i < d->coalesce.idx; i++) { rte_pktmbuf_free(d->coalesce.mbuf[i]); d->coalesce.mbuf[i] = NULL; } d->coalesce.idx = 0; } ++d; if (++cidx == q->size) { cidx = 0; d = q->sdesc; } RTE_MBUF_PREFETCH_TO_FREE(&q->sdesc->mbuf->pool); } } static void reclaim_tx_desc(struct sge_txq *q, unsigned int n) { unsigned int cidx = q->cidx; while (n--) { if (++cidx == q->size) cidx = 0; } q->cidx = cidx; } /** * fl_cap - return the capacity of a free-buffer list * @fl: the FL * * Returns the capacity of a free-buffer list. The capacity is less than * the size because one descriptor needs to be left unpopulated, otherwise * HW will think the FL is empty. */ static inline unsigned int fl_cap(const struct sge_fl *fl) { return fl->size - 8; /* 1 descriptor = 8 buffers */ } /** * fl_starving - return whether a Free List is starving. * @adapter: pointer to the adapter * @fl: the Free List * * Tests specified Free List to see whether the number of buffers * available to the hardware has falled below our "starvation" * threshold. */ static inline bool fl_starving(const struct adapter *adapter, const struct sge_fl *fl) { const struct sge *s = &adapter->sge; return fl->avail - fl->pend_cred <= s->fl_starve_thres; } /** * free_rx_bufs - free the Rx buffers on an SGE free list * @q: the SGE free list to free buffers from * @n: how many buffers to free * * Release the next @n buffers on an SGE free-buffer Rx queue. The * buffers must be made inaccessible to HW before calling this function. */ static void free_rx_bufs(struct sge_fl *q, int n) { unsigned int cidx = q->cidx; struct rx_sw_desc *d; d = &q->sdesc[cidx]; while (n--) { if (d->buf) { rte_pktmbuf_free(d->buf); d->buf = NULL; } ++d; if (++cidx == q->size) { cidx = 0; d = q->sdesc; } q->avail--; } q->cidx = cidx; } /** * unmap_rx_buf - unmap the current Rx buffer on an SGE free list * @q: the SGE free list * * Unmap the current buffer on an SGE free-buffer Rx queue. The * buffer must be made inaccessible to HW before calling this function. * * This is similar to @free_rx_bufs above but does not free the buffer. * Do note that the FL still loses any further access to the buffer. */ static void unmap_rx_buf(struct sge_fl *q) { if (++q->cidx == q->size) q->cidx = 0; q->avail--; } static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) { /* see if we have exceeded q->size / 4 */ if (q->pend_cred >= (q->size / 4)) { u32 val = adap->params.arch.sge_fl_db; if (is_t4(adap->params.chip)) val |= V_PIDX(q->pend_cred / 8); else val |= V_PIDX_T5(q->pend_cred / 8); /* * Make sure all memory writes to the Free List queue are * committed before we tell the hardware about them. */ wmb(); /* * If we don't have access to the new User Doorbell (T5+), use * the old doorbell mechanism; otherwise use the new BAR2 * mechanism. */ if (unlikely(!q->bar2_addr)) { t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL), val | V_QID(q->cntxt_id)); } else { writel(val | V_QID(q->bar2_qid), (void *)((uintptr_t)q->bar2_addr + SGE_UDB_KDOORBELL)); /* * This Write memory Barrier will force the write to * the User Doorbell area to be flushed. */ wmb(); } q->pend_cred &= 7; } } static inline void set_rx_sw_desc(struct rx_sw_desc *sd, void *buf, dma_addr_t mapping) { sd->buf = buf; sd->dma_addr = mapping; /* includes size low bits */ } /** * refill_fl_usembufs - refill an SGE Rx buffer ring with mbufs * @adap: the adapter * @q: the ring to refill * @n: the number of new buffers to allocate * * (Re)populate an SGE free-buffer queue with up to @n new packet buffers, * allocated with the supplied gfp flags. The caller must assure that * @n does not exceed the queue's capacity. If afterwards the queue is * found critically low mark it as starving in the bitmap of starving FLs. * * Returns the number of buffers allocated. */ static unsigned int refill_fl_usembufs(struct adapter *adap, struct sge_fl *q, int n) { struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, fl); unsigned int cred = q->avail; __be64 *d = &q->desc[q->pidx]; struct rx_sw_desc *sd = &q->sdesc[q->pidx]; unsigned int buf_size_idx = RX_SMALL_MTU_BUF; struct rte_mbuf *buf_bulk[n]; int ret, i; ret = rte_mempool_get_bulk(rxq->rspq.mb_pool, (void *)buf_bulk, n); if (unlikely(ret != 0)) { dev_debug(adap, "%s: failed to allocated fl entries in bulk ..\n", __func__); q->alloc_failed++; rxq->rspq.eth_dev->data->rx_mbuf_alloc_failed++; goto out; } for (i = 0; i < n; i++) { struct rte_mbuf *mbuf = buf_bulk[i]; dma_addr_t mapping; if (!mbuf) { dev_debug(adap, "%s: mbuf alloc failed\n", __func__); q->alloc_failed++; rxq->rspq.eth_dev->data->rx_mbuf_alloc_failed++; goto out; } rte_mbuf_refcnt_set(mbuf, 1); mbuf->data_off = RTE_PKTMBUF_HEADROOM; mbuf->next = NULL; mbuf->nb_segs = 1; mbuf->port = rxq->rspq.port_id; mapping = (dma_addr_t)(mbuf->buf_physaddr + mbuf->data_off); mapping |= buf_size_idx; *d++ = cpu_to_be64(mapping); set_rx_sw_desc(sd, mbuf, mapping); sd++; q->avail++; if (++q->pidx == q->size) { q->pidx = 0; sd = q->sdesc; d = q->desc; } } out: cred = q->avail - cred; q->pend_cred += cred; ring_fl_db(adap, q); if (unlikely(fl_starving(adap, q))) { /* * Make sure data has been written to free list */ wmb(); q->low++; } return cred; } /** * refill_fl - refill an SGE Rx buffer ring with mbufs * @adap: the adapter * @q: the ring to refill * @n: the number of new buffers to allocate * * (Re)populate an SGE free-buffer queue with up to @n new packet buffers, * allocated with the supplied gfp flags. The caller must assure that * @n does not exceed the queue's capacity. Returns the number of buffers * allocated. */ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n) { return refill_fl_usembufs(adap, q, n); } static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) { refill_fl(adap, fl, min(MAX_RX_REFILL, fl_cap(fl) - fl->avail)); } /* * Return the number of reclaimable descriptors in a Tx queue. */ static inline int reclaimable(const struct sge_txq *q) { int hw_cidx = ntohs(q->stat->cidx); hw_cidx -= q->cidx; if (hw_cidx < 0) return hw_cidx + q->size; return hw_cidx; } /** * reclaim_completed_tx - reclaims completed Tx descriptors * @q: the Tx queue to reclaim completed descriptors from * * Reclaims Tx descriptors that the SGE has indicated it has processed. */ void reclaim_completed_tx(struct sge_txq *q) { unsigned int avail = reclaimable(q); do { /* reclaim as much as possible */ reclaim_tx_desc(q, avail); q->in_use -= avail; avail = reclaimable(q); } while (avail); } /** * sgl_len - calculates the size of an SGL of the given capacity * @n: the number of SGL entries * * Calculates the number of flits needed for a scatter/gather list that * can hold the given number of entries. */ static inline unsigned int sgl_len(unsigned int n) { /* * A Direct Scatter Gather List uses 32-bit lengths and 64-bit PCI DMA * addresses. The DSGL Work Request starts off with a 32-bit DSGL * ULPTX header, then Length0, then Address0, then, for 1 <= i <= N, * repeated sequences of { Length[i], Length[i+1], Address[i], * Address[i+1] } (this ensures that all addresses are on 64-bit * boundaries). If N is even, then Length[N+1] should be set to 0 and * Address[N+1] is omitted. * * The following calculation incorporates all of the above. It's * somewhat hard to follow but, briefly: the "+2" accounts for the * first two flits which include the DSGL header, Length0 and * Address0; the "(3*(n-1))/2" covers the main body of list entries (3 * flits for every pair of the remaining N) +1 if (n-1) is odd; and * finally the "+((n-1)&1)" adds the one remaining flit needed if * (n-1) is odd ... */ n--; return (3 * n) / 2 + (n & 1) + 2; } /** * flits_to_desc - returns the num of Tx descriptors for the given flits * @n: the number of flits * * Returns the number of Tx descriptors needed for the supplied number * of flits. */ static inline unsigned int flits_to_desc(unsigned int n) { return DIV_ROUND_UP(n, 8); } /** * is_eth_imm - can an Ethernet packet be sent as immediate data? * @m: the packet * * Returns whether an Ethernet packet is small enough to fit as * immediate data. Return value corresponds to the headroom required. */ static inline int is_eth_imm(const struct rte_mbuf *m) { unsigned int hdrlen = (m->ol_flags & PKT_TX_TCP_SEG) ? sizeof(struct cpl_tx_pkt_lso_core) : 0; hdrlen += sizeof(struct cpl_tx_pkt); if (m->pkt_len <= MAX_IMM_TX_PKT_LEN - hdrlen) return hdrlen; return 0; } /** * calc_tx_flits - calculate the number of flits for a packet Tx WR * @m: the packet * * Returns the number of flits needed for a Tx WR for the given Ethernet * packet, including the needed WR and CPL headers. */ static inline unsigned int calc_tx_flits(const struct rte_mbuf *m) { unsigned int flits; int hdrlen; /* * If the mbuf is small enough, we can pump it out as a work request * with only immediate data. In that case we just have to have the * TX Packet header plus the mbuf data in the Work Request. */ hdrlen = is_eth_imm(m); if (hdrlen) return DIV_ROUND_UP(m->pkt_len + hdrlen, sizeof(__be64)); /* * Otherwise, we're going to have to construct a Scatter gather list * of the mbuf body and fragments. We also include the flits necessary * for the TX Packet Work Request and CPL. We always have a firmware * Write Header (incorporated as part of the cpl_tx_pkt_lso and * cpl_tx_pkt structures), followed by either a TX Packet Write CPL * message or, if we're doing a Large Send Offload, an LSO CPL message * with an embeded TX Packet Write CPL message. */ flits = sgl_len(m->nb_segs); if (m->tso_segsz) flits += (sizeof(struct fw_eth_tx_pkt_wr) + sizeof(struct cpl_tx_pkt_lso_core) + sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64); else flits += (sizeof(struct fw_eth_tx_pkt_wr) + sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64); return flits; } /** * write_sgl - populate a scatter/gather list for a packet * @mbuf: the packet * @q: the Tx queue we are writing into * @sgl: starting location for writing the SGL * @end: points right after the end of the SGL * @start: start offset into mbuf main-body data to include in the SGL * @addr: address of mapped region * * Generates a scatter/gather list for the buffers that make up a packet. * The caller must provide adequate space for the SGL that will be written. * The SGL includes all of the packet's page fragments and the data in its * main body except for the first @start bytes. @sgl must be 16-byte * aligned and within a Tx descriptor with available space. @end points * write after the end of the SGL but does not account for any potential * wrap around, i.e., @end > @sgl. */ static void write_sgl(struct rte_mbuf *mbuf, struct sge_txq *q, struct ulptx_sgl *sgl, u64 *end, unsigned int start, const dma_addr_t *addr) { unsigned int i, len; struct ulptx_sge_pair *to; struct rte_mbuf *m = mbuf; unsigned int nfrags = m->nb_segs; struct ulptx_sge_pair buf[nfrags / 2]; len = m->data_len - start; sgl->len0 = htonl(len); sgl->addr0 = rte_cpu_to_be_64(addr[0]); sgl->cmd_nsge = htonl(V_ULPTX_CMD(ULP_TX_SC_DSGL) | V_ULPTX_NSGE(nfrags)); if (likely(--nfrags == 0)) return; /* * Most of the complexity below deals with the possibility we hit the * end of the queue in the middle of writing the SGL. For this case * only we create the SGL in a temporary buffer and then copy it. */ to = (u8 *)end > (u8 *)q->stat ? buf : sgl->sge; for (i = 0; nfrags >= 2; nfrags -= 2, to++) { m = m->next; to->len[0] = rte_cpu_to_be_32(m->data_len); to->addr[0] = rte_cpu_to_be_64(addr[++i]); m = m->next; to->len[1] = rte_cpu_to_be_32(m->data_len); to->addr[1] = rte_cpu_to_be_64(addr[++i]); } if (nfrags) { m = m->next; to->len[0] = rte_cpu_to_be_32(m->data_len); to->len[1] = rte_cpu_to_be_32(0); to->addr[0] = rte_cpu_to_be_64(addr[i + 1]); } if (unlikely((u8 *)end > (u8 *)q->stat)) { unsigned int part0 = RTE_PTR_DIFF((u8 *)q->stat, (u8 *)sgl->sge); unsigned int part1; if (likely(part0)) memcpy(sgl->sge, buf, part0); part1 = RTE_PTR_DIFF((u8 *)end, (u8 *)q->stat); rte_memcpy(q->desc, RTE_PTR_ADD((u8 *)buf, part0), part1); end = RTE_PTR_ADD((void *)q->desc, part1); } if ((uintptr_t)end & 8) /* 0-pad to multiple of 16 */ *(u64 *)end = 0; } #define IDXDIFF(head, tail, wrap) \ ((head) >= (tail) ? (head) - (tail) : (wrap) - (tail) + (head)) #define Q_IDXDIFF(q, idx) IDXDIFF((q)->pidx, (q)->idx, (q)->size) #define R_IDXDIFF(q, idx) IDXDIFF((q)->cidx, (q)->idx, (q)->size) /** * ring_tx_db - ring a Tx queue's doorbell * @adap: the adapter * @q: the Tx queue * @n: number of new descriptors to give to HW * * Ring the doorbel for a Tx queue. */ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q) { int n = Q_IDXDIFF(q, dbidx); /* * Make sure that all writes to the TX Descriptors are committed * before we tell the hardware about them. */ rte_wmb(); /* * If we don't have access to the new User Doorbell (T5+), use the old * doorbell mechanism; otherwise use the new BAR2 mechanism. */ if (unlikely(!q->bar2_addr)) { u32 val = V_PIDX(n); /* * For T4 we need to participate in the Doorbell Recovery * mechanism. */ if (!q->db_disabled) t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL), V_QID(q->cntxt_id) | val); else q->db_pidx_inc += n; q->db_pidx = q->pidx; } else { u32 val = V_PIDX_T5(n); /* * T4 and later chips share the same PIDX field offset within * the doorbell, but T5 and later shrank the field in order to * gain a bit for Doorbell Priority. The field was absurdly * large in the first place (14 bits) so we just use the T5 * and later limits and warn if a Queue ID is too large. */ WARN_ON(val & F_DBPRIO); writel(val | V_QID(q->bar2_qid), (void *)((uintptr_t)q->bar2_addr + SGE_UDB_KDOORBELL)); /* * This Write Memory Barrier will force the write to the User * Doorbell area to be flushed. This is needed to prevent * writes on different CPUs for the same queue from hitting * the adapter out of order. This is required when some Work * Requests take the Write Combine Gather Buffer path (user * doorbell area offset [SGE_UDB_WCDOORBELL..+63]) and some * take the traditional path where we simply increment the * PIDX (User Doorbell area SGE_UDB_KDOORBELL) and have the * hardware DMA read the actual Work Request. */ rte_wmb(); } q->dbidx = q->pidx; } /* * Figure out what HW csum a packet wants and return the appropriate control * bits. */ static u64 hwcsum(enum chip_type chip, const struct rte_mbuf *m) { int csum_type; if (m->ol_flags & PKT_TX_IP_CKSUM) { switch (m->ol_flags & PKT_TX_L4_MASK) { case PKT_TX_TCP_CKSUM: csum_type = TX_CSUM_TCPIP; break; case PKT_TX_UDP_CKSUM: csum_type = TX_CSUM_UDPIP; break; default: goto nocsum; } } else { goto nocsum; } if (likely(csum_type >= TX_CSUM_TCPIP)) { int hdr_len = V_TXPKT_IPHDR_LEN(m->l3_len); int eth_hdr_len = m->l2_len; if (CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5) hdr_len |= V_TXPKT_ETHHDR_LEN(eth_hdr_len); else hdr_len |= V_T6_TXPKT_ETHHDR_LEN(eth_hdr_len); return V_TXPKT_CSUM_TYPE(csum_type) | hdr_len; } nocsum: /* * unknown protocol, disable HW csum * and hope a bad packet is detected */ return F_TXPKT_L4CSUM_DIS; } static inline void txq_advance(struct sge_txq *q, unsigned int n) { q->in_use += n; q->pidx += n; if (q->pidx >= q->size) q->pidx -= q->size; } #define MAX_COALESCE_LEN 64000 static inline int wraps_around(struct sge_txq *q, int ndesc) { return (q->pidx + ndesc) > q->size ? 1 : 0; } static void tx_timer_cb(void *data) { struct adapter *adap = (struct adapter *)data; struct sge_eth_txq *txq = &adap->sge.ethtxq[0]; int i; /* monitor any pending tx */ for (i = 0; i < adap->sge.max_ethqsets; i++, txq++) { t4_os_lock(&txq->txq_lock); if (txq->q.coalesce.idx) { if (txq->q.coalesce.idx == txq->q.last_coal_idx && txq->q.pidx == txq->q.last_pidx) { ship_tx_pkt_coalesce_wr(adap, txq); } else { txq->q.last_coal_idx = txq->q.coalesce.idx; txq->q.last_pidx = txq->q.pidx; } } t4_os_unlock(&txq->txq_lock); } rte_eal_alarm_set(50, tx_timer_cb, (void *)adap); } /** * ship_tx_pkt_coalesce_wr - finalizes and ships a coalesce WR * @ adap: adapter structure * @txq: tx queue * * writes the different fields of the pkts WR and sends it. */ static inline void ship_tx_pkt_coalesce_wr(struct adapter *adap, struct sge_eth_txq *txq) { u32 wr_mid; struct sge_txq *q = &txq->q; struct fw_eth_tx_pkts_wr *wr; unsigned int ndesc; /* fill the pkts WR header */ wr = (void *)&q->desc[q->pidx]; wr->op_pkd = htonl(V_FW_WR_OP(FW_ETH_TX_PKTS_WR)); wr_mid = V_FW_WR_LEN16(DIV_ROUND_UP(q->coalesce.flits, 2)); ndesc = flits_to_desc(q->coalesce.flits); wr->equiq_to_len16 = htonl(wr_mid); wr->plen = cpu_to_be16(q->coalesce.len); wr->npkt = q->coalesce.idx; wr->r3 = 0; wr->type = q->coalesce.type; /* zero out coalesce structure members */ q->coalesce.idx = 0; q->coalesce.flits = 0; q->coalesce.len = 0; txq_advance(q, ndesc); txq->stats.coal_wr++; txq->stats.coal_pkts += wr->npkt; if (Q_IDXDIFF(q, equeidx) >= q->size / 2) { q->equeidx = q->pidx; wr_mid |= F_FW_WR_EQUEQ; wr->equiq_to_len16 = htonl(wr_mid); } ring_tx_db(adap, q); } /** * should_tx_packet_coalesce - decides wether to coalesce an mbuf or not * @txq: tx queue where the mbuf is sent * @mbuf: mbuf to be sent * @nflits: return value for number of flits needed * @adap: adapter structure * * This function decides if a packet should be coalesced or not. */ static inline int should_tx_packet_coalesce(struct sge_eth_txq *txq, struct rte_mbuf *mbuf, unsigned int *nflits, struct adapter *adap) { struct sge_txq *q = &txq->q; unsigned int flits, ndesc; unsigned char type = 0; int credits, hw_cidx = ntohs(q->stat->cidx); int in_use = q->pidx - hw_cidx + flits_to_desc(q->coalesce.flits); /* use coal WR type 1 when no frags are present */ type = (mbuf->nb_segs == 1) ? 1 : 0; if (in_use < 0) in_use += q->size; if (unlikely(type != q->coalesce.type && q->coalesce.idx)) ship_tx_pkt_coalesce_wr(adap, txq); /* calculate the number of flits required for coalescing this packet * without the 2 flits of the WR header. These are added further down * if we are just starting in new PKTS WR. sgl_len doesn't account for * the possible 16 bytes alignment ULP TX commands so we do it here. */ flits = (sgl_len(mbuf->nb_segs) + 1) & ~1U; if (type == 0) flits += (sizeof(struct ulp_txpkt) + sizeof(struct ulptx_idata)) / sizeof(__be64); flits += sizeof(struct cpl_tx_pkt_core) / sizeof(__be64); *nflits = flits; /* If coalescing is on, the mbuf is added to a pkts WR */ if (q->coalesce.idx) { ndesc = DIV_ROUND_UP(q->coalesce.flits + flits, 8); credits = txq_avail(q) - ndesc; /* If we are wrapping or this is last mbuf then, send the * already coalesced mbufs and let the non-coalesce pass * handle the mbuf. */ if (unlikely(credits < 0 || wraps_around(q, ndesc))) { ship_tx_pkt_coalesce_wr(adap, txq); return 0; } /* If the max coalesce len or the max WR len is reached * ship the WR and keep coalescing on. */ if (unlikely((q->coalesce.len + mbuf->pkt_len > MAX_COALESCE_LEN) || (q->coalesce.flits + flits > q->coalesce.max))) { ship_tx_pkt_coalesce_wr(adap, txq); goto new; } return 1; } new: /* start a new pkts WR, the WR header is not filled below */ flits += sizeof(struct fw_eth_tx_pkts_wr) / sizeof(__be64); ndesc = flits_to_desc(q->coalesce.flits + flits); credits = txq_avail(q) - ndesc; if (unlikely(credits < 0 || wraps_around(q, ndesc))) return 0; q->coalesce.flits += 2; q->coalesce.type = type; q->coalesce.ptr = (unsigned char *)&q->desc[q->pidx] + 2 * sizeof(__be64); return 1; } /** * tx_do_packet_coalesce - add an mbuf to a coalesce WR * @txq: sge_eth_txq used send the mbuf * @mbuf: mbuf to be sent * @flits: flits needed for this mbuf * @adap: adapter structure * @pi: port_info structure * @addr: mapped address of the mbuf * * Adds an mbuf to be sent as part of a coalesce WR by filling a * ulp_tx_pkt command, ulp_tx_sc_imm command, cpl message and * ulp_tx_sc_dsgl command. */ static inline int tx_do_packet_coalesce(struct sge_eth_txq *txq, struct rte_mbuf *mbuf, int flits, struct adapter *adap, const struct port_info *pi, dma_addr_t *addr) { u64 cntrl, *end; struct sge_txq *q = &txq->q; struct ulp_txpkt *mc; struct ulptx_idata *sc_imm; struct cpl_tx_pkt_core *cpl; struct tx_sw_desc *sd; unsigned int idx = q->coalesce.idx, len = mbuf->pkt_len; if (q->coalesce.type == 0) { mc = (struct ulp_txpkt *)q->coalesce.ptr; mc->cmd_dest = htonl(V_ULPTX_CMD(4) | V_ULP_TXPKT_DEST(0) | V_ULP_TXPKT_FID(adap->sge.fw_evtq.cntxt_id) | F_ULP_TXPKT_RO); mc->len = htonl(DIV_ROUND_UP(flits, 2)); sc_imm = (struct ulptx_idata *)(mc + 1); sc_imm->cmd_more = htonl(V_ULPTX_CMD(ULP_TX_SC_IMM) | F_ULP_TX_SC_MORE); sc_imm->len = htonl(sizeof(*cpl)); end = (u64 *)mc + flits; cpl = (struct cpl_tx_pkt_core *)(sc_imm + 1); } else { end = (u64 *)q->coalesce.ptr + flits; cpl = (struct cpl_tx_pkt_core *)q->coalesce.ptr; } /* update coalesce structure for this txq */ q->coalesce.flits += flits; q->coalesce.ptr += flits * sizeof(__be64); q->coalesce.len += mbuf->pkt_len; /* fill the cpl message, same as in t4_eth_xmit, this should be kept * similar to t4_eth_xmit */ if (mbuf->ol_flags & PKT_TX_IP_CKSUM) { cntrl = hwcsum(adap->params.chip, mbuf) | F_TXPKT_IPCSUM_DIS; txq->stats.tx_cso++; } else { cntrl = F_TXPKT_L4CSUM_DIS | F_TXPKT_IPCSUM_DIS; } if (mbuf->ol_flags & PKT_TX_VLAN_PKT) { txq->stats.vlan_ins++; cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(mbuf->vlan_tci); } cpl->ctrl0 = htonl(V_TXPKT_OPCODE(CPL_TX_PKT_XT) | V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(adap->pf)); cpl->pack = htons(0); cpl->len = htons(len); cpl->ctrl1 = cpu_to_be64(cntrl); write_sgl(mbuf, q, (struct ulptx_sgl *)(cpl + 1), end, 0, addr); txq->stats.pkts++; txq->stats.tx_bytes += len; sd = &q->sdesc[q->pidx + (idx >> 1)]; if (!(idx & 1)) { if (sd->coalesce.idx) { int i; for (i = 0; i < sd->coalesce.idx; i++) { rte_pktmbuf_free(sd->coalesce.mbuf[i]); sd->coalesce.mbuf[i] = NULL; } } } /* store pointers to the mbuf and the sgl used in free_tx_desc. * each tx desc can hold two pointers corresponding to the value * of ETH_COALESCE_PKT_PER_DESC */ sd->coalesce.mbuf[idx & 1] = mbuf; sd->coalesce.sgl[idx & 1] = (struct ulptx_sgl *)(cpl + 1); sd->coalesce.idx = (idx & 1) + 1; /* send the coaelsced work request if max reached */ if (++q->coalesce.idx == ETH_COALESCE_PKT_NUM) ship_tx_pkt_coalesce_wr(adap, txq); return 0; } /** * t4_eth_xmit - add a packet to an Ethernet Tx queue * @txq: the egress queue * @mbuf: the packet * * Add a packet to an SGE Ethernet Tx queue. Runs with softirqs disabled. */ int t4_eth_xmit(struct sge_eth_txq *txq, struct rte_mbuf *mbuf) { const struct port_info *pi; struct cpl_tx_pkt_lso_core *lso; struct adapter *adap; struct rte_mbuf *m = mbuf; struct fw_eth_tx_pkt_wr *wr; struct cpl_tx_pkt_core *cpl; struct tx_sw_desc *d; dma_addr_t addr[m->nb_segs]; unsigned int flits, ndesc, cflits; int l3hdr_len, l4hdr_len, eth_xtra_len; int len, last_desc; int credits; u32 wr_mid; u64 cntrl, *end; bool v6; /* Reject xmit if queue is stopped */ if (unlikely(txq->flags & EQ_STOPPED)) return -(EBUSY); /* * The chip min packet length is 10 octets but play safe and reject * anything shorter than an Ethernet header. */ if (unlikely(m->pkt_len < ETHER_HDR_LEN)) { out_free: rte_pktmbuf_free(m); return 0; } rte_prefetch0(&((&txq->q)->sdesc->mbuf->pool)); pi = (struct port_info *)txq->eth_dev->data->dev_private; adap = pi->adapter; cntrl = F_TXPKT_L4CSUM_DIS | F_TXPKT_IPCSUM_DIS; /* align the end of coalesce WR to a 512 byte boundary */ txq->q.coalesce.max = (8 - (txq->q.pidx & 7)) * 8; if (!(m->ol_flags & PKT_TX_TCP_SEG)) { if (should_tx_packet_coalesce(txq, mbuf, &cflits, adap)) { if (unlikely(map_mbuf(mbuf, addr) < 0)) { dev_warn(adap, "%s: mapping err for coalesce\n", __func__); txq->stats.mapping_err++; goto out_free; } return tx_do_packet_coalesce(txq, mbuf, cflits, adap, pi, addr); } else { return -EBUSY; } } if (txq->q.coalesce.idx) ship_tx_pkt_coalesce_wr(adap, txq); flits = calc_tx_flits(m); ndesc = flits_to_desc(flits); credits = txq_avail(&txq->q) - ndesc; if (unlikely(credits < 0)) { dev_debug(adap, "%s: Tx ring %u full; credits = %d\n", __func__, txq->q.cntxt_id, credits); return -EBUSY; } if (unlikely(map_mbuf(m, addr) < 0)) { txq->stats.mapping_err++; goto out_free; } wr_mid = V_FW_WR_LEN16(DIV_ROUND_UP(flits, 2)); if (Q_IDXDIFF(&txq->q, equeidx) >= 64) { txq->q.equeidx = txq->q.pidx; wr_mid |= F_FW_WR_EQUEQ; } wr = (void *)&txq->q.desc[txq->q.pidx]; wr->equiq_to_len16 = htonl(wr_mid); wr->r3 = rte_cpu_to_be_64(0); end = (u64 *)wr + flits; len = 0; len += sizeof(*cpl); lso = (void *)(wr + 1); v6 = (m->ol_flags & PKT_TX_IPV6) != 0; l3hdr_len = m->l3_len; l4hdr_len = m->l4_len; eth_xtra_len = m->l2_len - ETHER_HDR_LEN; len += sizeof(*lso); wr->op_immdlen = htonl(V_FW_WR_OP(FW_ETH_TX_PKT_WR) | V_FW_WR_IMMDLEN(len)); lso->lso_ctrl = htonl(V_LSO_OPCODE(CPL_TX_PKT_LSO) | F_LSO_FIRST_SLICE | F_LSO_LAST_SLICE | V_LSO_IPV6(v6) | V_LSO_ETHHDR_LEN(eth_xtra_len / 4) | V_LSO_IPHDR_LEN(l3hdr_len / 4) | V_LSO_TCPHDR_LEN(l4hdr_len / 4)); lso->ipid_ofst = htons(0); lso->mss = htons(m->tso_segsz); lso->seqno_offset = htonl(0); if (is_t4(adap->params.chip)) lso->len = htonl(m->pkt_len); else lso->len = htonl(V_LSO_T5_XFER_SIZE(m->pkt_len)); cpl = (void *)(lso + 1); cntrl = V_TXPKT_CSUM_TYPE(v6 ? TX_CSUM_TCPIP6 : TX_CSUM_TCPIP) | V_TXPKT_IPHDR_LEN(l3hdr_len) | V_TXPKT_ETHHDR_LEN(eth_xtra_len); txq->stats.tso++; txq->stats.tx_cso += m->tso_segsz; if (m->ol_flags & PKT_TX_VLAN_PKT) { txq->stats.vlan_ins++; cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(m->vlan_tci); } cpl->ctrl0 = htonl(V_TXPKT_OPCODE(CPL_TX_PKT_XT) | V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(adap->pf)); cpl->pack = htons(0); cpl->len = htons(m->pkt_len); cpl->ctrl1 = cpu_to_be64(cntrl); txq->stats.pkts++; txq->stats.tx_bytes += m->pkt_len; last_desc = txq->q.pidx + ndesc - 1; if (last_desc >= (int)txq->q.size) last_desc -= txq->q.size; d = &txq->q.sdesc[last_desc]; if (d->mbuf) { rte_pktmbuf_free(d->mbuf); d->mbuf = NULL; } write_sgl(m, &txq->q, (struct ulptx_sgl *)(cpl + 1), end, 0, addr); txq->q.sdesc[last_desc].mbuf = m; txq->q.sdesc[last_desc].sgl = (struct ulptx_sgl *)(cpl + 1); txq_advance(&txq->q, ndesc); ring_tx_db(adap, &txq->q); return 0; } /** * alloc_ring - allocate resources for an SGE descriptor ring * @dev: the PCI device's core device * @nelem: the number of descriptors * @elem_size: the size of each descriptor * @sw_size: the size of the SW state associated with each ring element * @phys: the physical address of the allocated ring * @metadata: address of the array holding the SW state for the ring * @stat_size: extra space in HW ring for status information * @node: preferred node for memory allocations * * Allocates resources for an SGE descriptor ring, such as Tx queues, * free buffer lists, or response queues. Each SGE ring requires * space for its HW descriptors plus, optionally, space for the SW state * associated with each HW entry (the metadata). The function returns * three values: the virtual address for the HW ring (the return value * of the function), the bus address of the HW ring, and the address * of the SW ring. */ static void *alloc_ring(size_t nelem, size_t elem_size, size_t sw_size, dma_addr_t *phys, void *metadata, size_t stat_size, __rte_unused uint16_t queue_id, int socket_id, const char *z_name, const char *z_name_sw) { size_t len = CXGBE_MAX_RING_DESC_SIZE * elem_size + stat_size; const struct rte_memzone *tz; void *s = NULL; dev_debug(adapter, "%s: nelem = %zu; elem_size = %zu; sw_size = %zu; " "stat_size = %zu; queue_id = %u; socket_id = %d; z_name = %s;" " z_name_sw = %s\n", __func__, nelem, elem_size, sw_size, stat_size, queue_id, socket_id, z_name, z_name_sw); tz = rte_memzone_lookup(z_name); if (tz) { dev_debug(adapter, "%s: tz exists...returning existing..\n", __func__); goto alloc_sw_ring; } /* * Allocate TX/RX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ tz = rte_memzone_reserve_aligned(z_name, len, socket_id, 0, 4096); if (!tz) return NULL; alloc_sw_ring: memset(tz->addr, 0, len); if (sw_size) { s = rte_zmalloc_socket(z_name_sw, nelem * sw_size, RTE_CACHE_LINE_SIZE, socket_id); if (!s) { dev_err(adapter, "%s: failed to get sw_ring memory\n", __func__); return NULL; } } if (metadata) *(void **)metadata = s; *phys = (uint64_t)tz->phys_addr; return tz->addr; } /** * t4_pktgl_to_mbuf_usembufs - build an mbuf from a packet gather list * @gl: the gather list * * Builds an mbuf from the given packet gather list. Returns the mbuf or * %NULL if mbuf allocation failed. */ static struct rte_mbuf *t4_pktgl_to_mbuf_usembufs(const struct pkt_gl *gl) { /* * If there's only one mbuf fragment, just return that. */ if (likely(gl->nfrags == 1)) return gl->mbufs[0]; return NULL; } /** * t4_pktgl_to_mbuf - build an mbuf from a packet gather list * @gl: the gather list * * Builds an mbuf from the given packet gather list. Returns the mbuf or * %NULL if mbuf allocation failed. */ static struct rte_mbuf *t4_pktgl_to_mbuf(const struct pkt_gl *gl) { return t4_pktgl_to_mbuf_usembufs(gl); } #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ ((dma_addr_t) ((mb)->buf_physaddr + (mb)->data_off)) /** * t4_ethrx_handler - process an ingress ethernet packet * @q: the response queue that received the packet * @rsp: the response queue descriptor holding the RX_PKT message * @si: the gather list of packet fragments * * Process an ingress ethernet packet and deliver it to the stack. */ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, const struct pkt_gl *si) { struct rte_mbuf *mbuf; const struct cpl_rx_pkt *pkt; const struct rss_header *rss_hdr; bool csum_ok; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); rss_hdr = (const void *)rsp; pkt = (const void *)&rsp[1]; csum_ok = pkt->csum_calc && !pkt->err_vec; mbuf = t4_pktgl_to_mbuf(si); if (unlikely(!mbuf)) { rxq->stats.rx_drops++; return 0; } mbuf->port = pkt->iff; if (pkt->l2info & htonl(F_RXF_IP)) { #ifdef RTE_NEXT_ABI mbuf->packet_type = RTE_PTYPE_L3_IPV4; #else mbuf->ol_flags |= PKT_RX_IPV4_HDR; #endif if (unlikely(!csum_ok)) mbuf->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((pkt->l2info & htonl(F_RXF_UDP | F_RXF_TCP)) && !csum_ok) mbuf->ol_flags |= PKT_RX_L4_CKSUM_BAD; } else if (pkt->l2info & htonl(F_RXF_IP6)) { #ifdef RTE_NEXT_ABI mbuf->packet_type = RTE_PTYPE_L3_IPV6; #else mbuf->ol_flags |= PKT_RX_IPV6_HDR; #endif } mbuf->port = pkt->iff; if (!rss_hdr->filter_tid && rss_hdr->hash_type) { mbuf->ol_flags |= PKT_RX_RSS_HASH; mbuf->hash.rss = ntohl(rss_hdr->hash_val); } if (pkt->vlan_ex) { mbuf->ol_flags |= PKT_RX_VLAN_PKT; mbuf->vlan_tci = ntohs(pkt->vlan); } rxq->stats.pkts++; rxq->stats.rx_bytes += mbuf->pkt_len; return 0; } /** * is_new_response - check if a response is newly written * @r: the response descriptor * @q: the response queue * * Returns true if a response descriptor contains a yet unprocessed * response. */ static inline bool is_new_response(const struct rsp_ctrl *r, const struct sge_rspq *q) { return (r->u.type_gen >> S_RSPD_GEN) == q->gen; } #define CXGB4_MSG_AN ((void *)1) /** * rspq_next - advance to the next entry in a response queue * @q: the queue * * Updates the state of a response queue to advance it to the next entry. */ static inline void rspq_next(struct sge_rspq *q) { q->cur_desc = (const __be64 *)((const char *)q->cur_desc + q->iqe_len); if (unlikely(++q->cidx == q->size)) { q->cidx = 0; q->gen ^= 1; q->cur_desc = q->desc; } } /** * process_responses - process responses from an SGE response queue * @q: the ingress queue to process * @budget: how many responses can be processed in this round * @rx_pkts: mbuf to put the pkts * * Process responses from an SGE response queue up to the supplied budget. * Responses include received packets as well as control messages from FW * or HW. * * Additionally choose the interrupt holdoff time for the next interrupt * on this queue. If the system is under memory shortage use a fairly * long delay to help recovery. */ static int process_responses(struct sge_rspq *q, int budget, struct rte_mbuf **rx_pkts) { int ret = 0, rsp_type; int budget_left = budget; const struct rsp_ctrl *rc; struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq); while (likely(budget_left)) { rc = (const struct rsp_ctrl *) ((const char *)q->cur_desc + (q->iqe_len - sizeof(*rc))); if (!is_new_response(rc, q)) break; /* * Ensure response has been read */ rmb(); rsp_type = G_RSPD_TYPE(rc->u.type_gen); if (likely(rsp_type == X_RSPD_TYPE_FLBUF)) { const struct rx_sw_desc *rsd = &rxq->fl.sdesc[rxq->fl.cidx]; const struct rss_header *rss_hdr = (const void *)q->cur_desc; const struct cpl_rx_pkt *cpl = (const void *)&q->cur_desc[1]; bool csum_ok = cpl->csum_calc && !cpl->err_vec; struct rte_mbuf *pkt; u32 len = ntohl(rc->pldbuflen_qid); BUG_ON(!(len & F_RSPD_NEWBUF)); pkt = rsd->buf; pkt->data_len = G_RSPD_LEN(len); pkt->pkt_len = pkt->data_len; unmap_rx_buf(&rxq->fl); if (cpl->l2info & htonl(F_RXF_IP)) { #ifdef RTE_NEXT_ABI pkt->packet_type = RTE_PTYPE_L3_IPV4; #else pkt->ol_flags |= PKT_RX_IPV4_HDR; #endif if (unlikely(!csum_ok)) pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((cpl->l2info & htonl(F_RXF_UDP | F_RXF_TCP)) && !csum_ok) pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD; } else if (cpl->l2info & htonl(F_RXF_IP6)) { #ifdef RTE_NEXT_ABI pkt->packet_type = RTE_PTYPE_L3_IPV6; #else pkt->ol_flags |= PKT_RX_IPV6_HDR; #endif } if (!rss_hdr->filter_tid && rss_hdr->hash_type) { pkt->ol_flags |= PKT_RX_RSS_HASH; pkt->hash.rss = ntohl(rss_hdr->hash_val); } if (cpl->vlan_ex) { pkt->ol_flags |= PKT_RX_VLAN_PKT; pkt->vlan_tci = ntohs(cpl->vlan); } rxq->stats.pkts++; rxq->stats.rx_bytes += pkt->pkt_len; rx_pkts[budget - budget_left] = pkt; } else if (likely(rsp_type == X_RSPD_TYPE_CPL)) { ret = q->handler(q, q->cur_desc, NULL); } else { ret = q->handler(q, (const __be64 *)rc, CXGB4_MSG_AN); } if (unlikely(ret)) { /* couldn't process descriptor, back off for recovery */ q->next_intr_params = V_QINTR_TIMER_IDX(NOMEM_TMR_IDX); break; } rspq_next(q); budget_left--; if (R_IDXDIFF(q, gts_idx) >= 64) { unsigned int cidx_inc = R_IDXDIFF(q, gts_idx); unsigned int params; u32 val; __refill_fl(q->adapter, &rxq->fl); params = V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX); q->next_intr_params = params; val = V_CIDXINC(cidx_inc) | V_SEINTARM(params); if (unlikely(!q->bar2_addr)) t4_write_reg(q->adapter, MYPF_REG(A_SGE_PF_GTS), val | V_INGRESSQID((u32)q->cntxt_id)); else { writel(val | V_INGRESSQID(q->bar2_qid), (void *)((uintptr_t)q->bar2_addr + SGE_UDB_GTS)); /* * This Write memory Barrier will force the * write to the User Doorbell area to be * flushed. */ wmb(); } q->gts_idx = q->cidx; } } /* * If this is a Response Queue with an associated Free List and * there's room for another chunk of new Free List buffer pointers, * refill the Free List. */ if (q->offset >= 0 && fl_cap(&rxq->fl) - rxq->fl.avail >= 64) __refill_fl(q->adapter, &rxq->fl); return budget - budget_left; } int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts, unsigned int budget, unsigned int *work_done) { int err = 0; *work_done = process_responses(q, budget, rx_pkts); return err; } /** * bar2_address - return the BAR2 address for an SGE Queue's Registers * @adapter: the adapter * @qid: the SGE Queue ID * @qtype: the SGE Queue Type (Egress or Ingress) * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues * * Returns the BAR2 address for the SGE Queue Registers associated with * @qid. If BAR2 SGE Registers aren't available, returns NULL. Also * returns the BAR2 Queue ID to be used with writes to the BAR2 SGE * Queue Registers. If the BAR2 Queue ID is 0, then "Inferred Queue ID" * Registers are supported (e.g. the Write Combining Doorbell Buffer). */ static void __iomem *bar2_address(struct adapter *adapter, unsigned int qid, enum t4_bar2_qtype qtype, unsigned int *pbar2_qid) { u64 bar2_qoffset; int ret; ret = t4_bar2_sge_qregs(adapter, qid, qtype, &bar2_qoffset, pbar2_qid); if (ret) return NULL; return adapter->bar2 + bar2_qoffset; } int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq) { struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq); unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff; return t4_iq_start_stop(adap, adap->mbox, true, adap->pf, 0, rq->cntxt_id, fl_id, 0xffff); } int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq) { struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq); unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff; return t4_iq_start_stop(adap, adap->mbox, false, adap->pf, 0, rq->cntxt_id, fl_id, 0xffff); } /* * @intr_idx: MSI/MSI-X vector if >=0, -(absolute qid + 1) if < 0 * @cong: < 0 -> no congestion feedback, >= 0 -> congestion channel map */ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, struct rte_eth_dev *eth_dev, int intr_idx, struct sge_fl *fl, rspq_handler_t hnd, int cong, struct rte_mempool *mp, int queue_id, int socket_id) { int ret, flsz = 0; struct fw_iq_cmd c; struct sge *s = &adap->sge; struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); char z_name[RTE_MEMZONE_NAMESIZE]; char z_name_sw[RTE_MEMZONE_NAMESIZE]; unsigned int nb_refill; /* Size needs to be multiple of 16, including status entry. */ iq->size = cxgbe_roundup(iq->size, 16); snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", eth_dev->driver->pci_drv.name, fwevtq ? "fwq_ring" : "rx_ring", eth_dev->data->port_id, queue_id); snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name); iq->desc = alloc_ring(iq->size, iq->iqe_len, 0, &iq->phys_addr, NULL, 0, queue_id, socket_id, z_name, z_name_sw); if (!iq->desc) return -ENOMEM; memset(&c, 0, sizeof(c)); c.op_to_vfn = htonl(V_FW_CMD_OP(FW_IQ_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_IQ_CMD_PFN(adap->pf) | V_FW_IQ_CMD_VFN(0)); c.alloc_to_len16 = htonl(F_FW_IQ_CMD_ALLOC | F_FW_IQ_CMD_IQSTART | (sizeof(c) / 16)); c.type_to_iqandstindex = htonl(V_FW_IQ_CMD_TYPE(FW_IQ_TYPE_FL_INT_CAP) | V_FW_IQ_CMD_IQASYNCH(fwevtq) | V_FW_IQ_CMD_VIID(pi->viid) | V_FW_IQ_CMD_IQANDST(intr_idx < 0) | V_FW_IQ_CMD_IQANUD(X_UPDATEDELIVERY_INTERRUPT) | V_FW_IQ_CMD_IQANDSTINDEX(intr_idx >= 0 ? intr_idx : -intr_idx - 1)); c.iqdroprss_to_iqesize = htons(V_FW_IQ_CMD_IQPCIECH(pi->tx_chan) | F_FW_IQ_CMD_IQGTSMODE | V_FW_IQ_CMD_IQINTCNTTHRESH(iq->pktcnt_idx) | V_FW_IQ_CMD_IQESIZE(ilog2(iq->iqe_len) - 4)); c.iqsize = htons(iq->size); c.iqaddr = cpu_to_be64(iq->phys_addr); if (cong >= 0) c.iqns_to_fl0congen = htonl(F_FW_IQ_CMD_IQFLINTCONGEN); if (fl) { struct sge_eth_rxq *rxq = container_of(fl, struct sge_eth_rxq, fl); enum chip_type chip = (enum chip_type)CHELSIO_CHIP_VERSION( adap->params.chip); /* * Allocate the ring for the hardware free list (with space * for its status page) along with the associated software * descriptor ring. The free list size needs to be a multiple * of the Egress Queue Unit and at least 2 Egress Units larger * than the SGE's Egress Congrestion Threshold * (fl_starve_thres - 1). */ if (fl->size < s->fl_starve_thres - 1 + 2 * 8) fl->size = s->fl_starve_thres - 1 + 2 * 8; fl->size = cxgbe_roundup(fl->size, 8); snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", eth_dev->driver->pci_drv.name, fwevtq ? "fwq_ring" : "fl_ring", eth_dev->data->port_id, queue_id); snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name); fl->desc = alloc_ring(fl->size, sizeof(__be64), sizeof(struct rx_sw_desc), &fl->addr, &fl->sdesc, s->stat_len, queue_id, socket_id, z_name, z_name_sw); if (!fl->desc) goto fl_nomem; flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc); c.iqns_to_fl0congen |= htonl(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) | (unlikely(rxq->usembufs) ? 0 : F_FW_IQ_CMD_FL0PACKEN) | F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO | F_FW_IQ_CMD_FL0PADEN); if (cong >= 0) c.iqns_to_fl0congen |= htonl(V_FW_IQ_CMD_FL0CNGCHMAP(cong) | F_FW_IQ_CMD_FL0CONGCIF | F_FW_IQ_CMD_FL0CONGEN); /* In T6, for egress queue type FL there is internal overhead * of 16B for header going into FLM module. * Hence maximum allowed burst size will be 448 bytes. */ c.fl0dcaen_to_fl0cidxfthresh = htons(V_FW_IQ_CMD_FL0FBMIN(X_FETCHBURSTMIN_128B) | V_FW_IQ_CMD_FL0FBMAX((chip <= CHELSIO_T5) ? X_FETCHBURSTMAX_512B : X_FETCHBURSTMAX_256B)); c.fl0size = htons(flsz); c.fl0addr = cpu_to_be64(fl->addr); } ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c); if (ret) goto err; iq->cur_desc = iq->desc; iq->cidx = 0; iq->gts_idx = 0; iq->gen = 1; iq->next_intr_params = iq->intr_params; iq->cntxt_id = ntohs(c.iqid); iq->abs_id = ntohs(c.physiqid); iq->bar2_addr = bar2_address(adap, iq->cntxt_id, T4_BAR2_QTYPE_INGRESS, &iq->bar2_qid); iq->size--; /* subtract status entry */ iq->eth_dev = eth_dev; iq->handler = hnd; iq->port_id = pi->port_id; iq->mb_pool = mp; /* set offset to -1 to distinguish ingress queues without FL */ iq->offset = fl ? 0 : -1; if (fl) { fl->cntxt_id = ntohs(c.fl0id); fl->avail = 0; fl->pend_cred = 0; fl->pidx = 0; fl->cidx = 0; fl->alloc_failed = 0; /* * Note, we must initialize the BAR2 Free List User Doorbell * information before refilling the Free List! */ fl->bar2_addr = bar2_address(adap, fl->cntxt_id, T4_BAR2_QTYPE_EGRESS, &fl->bar2_qid); nb_refill = refill_fl(adap, fl, fl_cap(fl)); if (nb_refill != fl_cap(fl)) { ret = -ENOMEM; dev_err(adap, "%s: mbuf alloc failed with error: %d\n", __func__, ret); goto refill_fl_err; } } /* * For T5 and later we attempt to set up the Congestion Manager values * of the new RX Ethernet Queue. This should really be handled by * firmware because it's more complex than any host driver wants to * get involved with and it's different per chip and this is almost * certainly wrong. Formware would be wrong as well, but it would be * a lot easier to fix in one place ... For now we do something very * simple (and hopefully less wrong). */ if (!is_t4(adap->params.chip) && cong >= 0) { u32 param, val; int i; param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) | V_FW_PARAMS_PARAM_YZ(iq->cntxt_id)); if (cong == 0) { val = V_CONMCTXT_CNGTPMODE(X_CONMCTXT_CNGTPMODE_QUEUE); } else { val = V_CONMCTXT_CNGTPMODE( X_CONMCTXT_CNGTPMODE_CHANNEL); for (i = 0; i < 4; i++) { if (cong & (1 << i)) val |= V_CONMCTXT_CNGCHMAP(1 << (i << 2)); } } ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val); if (ret) dev_warn(adap->pdev_dev, "Failed to set Congestion Manager Context for Ingress Queue %d: %d\n", iq->cntxt_id, -ret); } return 0; refill_fl_err: t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP, iq->cntxt_id, fl ? fl->cntxt_id : 0xffff, 0xffff); fl_nomem: ret = -ENOMEM; err: iq->cntxt_id = 0; iq->abs_id = 0; if (iq->desc) iq->desc = NULL; if (fl && fl->desc) { rte_free(fl->sdesc); fl->cntxt_id = 0; fl->sdesc = NULL; fl->desc = NULL; } return ret; } static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id) { q->cntxt_id = id; q->bar2_addr = bar2_address(adap, q->cntxt_id, T4_BAR2_QTYPE_EGRESS, &q->bar2_qid); q->cidx = 0; q->pidx = 0; q->dbidx = 0; q->in_use = 0; q->equeidx = 0; q->coalesce.idx = 0; q->coalesce.len = 0; q->coalesce.flits = 0; q->last_coal_idx = 0; q->last_pidx = 0; q->stat = (void *)&q->desc[q->size]; } int t4_sge_eth_txq_start(struct sge_eth_txq *txq) { /* * TODO: For flow-control, queue may be stopped waiting to reclaim * credits. * Ensure queue is in EQ_STOPPED state before starting it. */ if (!(txq->flags & EQ_STOPPED)) return -(EBUSY); txq->flags &= ~EQ_STOPPED; return 0; } int t4_sge_eth_txq_stop(struct sge_eth_txq *txq) { txq->flags |= EQ_STOPPED; return 0; } int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, struct rte_eth_dev *eth_dev, uint16_t queue_id, unsigned int iqid, int socket_id) { int ret, nentries; struct fw_eq_eth_cmd c; struct sge *s = &adap->sge; struct port_info *pi = (struct port_info *)(eth_dev->data->dev_private); char z_name[RTE_MEMZONE_NAMESIZE]; char z_name_sw[RTE_MEMZONE_NAMESIZE]; /* Add status entries */ nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", eth_dev->driver->pci_drv.name, "tx_ring", eth_dev->data->port_id, queue_id); snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name); txq->q.desc = alloc_ring(txq->q.size, sizeof(struct tx_desc), sizeof(struct tx_sw_desc), &txq->q.phys_addr, &txq->q.sdesc, s->stat_len, queue_id, socket_id, z_name, z_name_sw); if (!txq->q.desc) return -ENOMEM; memset(&c, 0, sizeof(c)); c.op_to_vfn = htonl(V_FW_CMD_OP(FW_EQ_ETH_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_EQ_ETH_CMD_PFN(adap->pf) | V_FW_EQ_ETH_CMD_VFN(0)); c.alloc_to_len16 = htonl(F_FW_EQ_ETH_CMD_ALLOC | F_FW_EQ_ETH_CMD_EQSTART | (sizeof(c) / 16)); c.autoequiqe_to_viid = htonl(F_FW_EQ_ETH_CMD_AUTOEQUEQE | V_FW_EQ_ETH_CMD_VIID(pi->viid)); c.fetchszm_to_iqid = htonl(V_FW_EQ_ETH_CMD_HOSTFCMODE(X_HOSTFCMODE_NONE) | V_FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) | F_FW_EQ_ETH_CMD_FETCHRO | V_FW_EQ_ETH_CMD_IQID(iqid)); c.dcaen_to_eqsize = htonl(V_FW_EQ_ETH_CMD_FBMIN(X_FETCHBURSTMIN_64B) | V_FW_EQ_ETH_CMD_FBMAX(X_FETCHBURSTMAX_512B) | V_FW_EQ_ETH_CMD_EQSIZE(nentries)); c.eqaddr = rte_cpu_to_be_64(txq->q.phys_addr); ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c); if (ret) { rte_free(txq->q.sdesc); txq->q.sdesc = NULL; txq->q.desc = NULL; return ret; } init_txq(adap, &txq->q, G_FW_EQ_ETH_CMD_EQID(ntohl(c.eqid_pkd))); txq->stats.tso = 0; txq->stats.pkts = 0; txq->stats.tx_cso = 0; txq->stats.coal_wr = 0; txq->stats.vlan_ins = 0; txq->stats.tx_bytes = 0; txq->stats.coal_pkts = 0; txq->stats.mapping_err = 0; txq->flags |= EQ_STOPPED; txq->eth_dev = eth_dev; t4_os_lock_init(&txq->txq_lock); return 0; } static void free_txq(struct sge_txq *q) { q->cntxt_id = 0; q->sdesc = NULL; q->desc = NULL; } static void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl) { unsigned int fl_id = fl ? fl->cntxt_id : 0xffff; t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP, rq->cntxt_id, fl_id, 0xffff); rq->cntxt_id = 0; rq->abs_id = 0; rq->desc = NULL; if (fl) { free_rx_bufs(fl, fl->avail); rte_free(fl->sdesc); fl->sdesc = NULL; fl->cntxt_id = 0; fl->desc = NULL; } } /* * Clear all queues of the port * * Note: This function must only be called after rx and tx path * of the port have been disabled. */ void t4_sge_eth_clear_queues(struct port_info *pi) { int i; struct adapter *adap = pi->adapter; struct sge_eth_rxq *rxq = &adap->sge.ethrxq[pi->first_qset]; struct sge_eth_txq *txq = &adap->sge.ethtxq[pi->first_qset]; for (i = 0; i < pi->n_rx_qsets; i++, rxq++) { if (rxq->rspq.desc) t4_sge_eth_rxq_stop(adap, &rxq->rspq); } for (i = 0; i < pi->n_tx_qsets; i++, txq++) { if (txq->q.desc) { struct sge_txq *q = &txq->q; t4_sge_eth_txq_stop(txq); reclaim_completed_tx(q); free_tx_desc(q, q->size); q->equeidx = q->pidx; } } } void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq) { if (rxq->rspq.desc) { t4_sge_eth_rxq_stop(adap, &rxq->rspq); free_rspq_fl(adap, &rxq->rspq, rxq->fl.size ? &rxq->fl : NULL); } } void t4_sge_eth_txq_release(struct adapter *adap, struct sge_eth_txq *txq) { if (txq->q.desc) { t4_sge_eth_txq_stop(txq); reclaim_completed_tx(&txq->q); t4_eth_eq_free(adap, adap->mbox, adap->pf, 0, txq->q.cntxt_id); free_tx_desc(&txq->q, txq->q.size); rte_free(txq->q.sdesc); free_txq(&txq->q); } } void t4_sge_tx_monitor_start(struct adapter *adap) { rte_eal_alarm_set(50, tx_timer_cb, (void *)adap); } void t4_sge_tx_monitor_stop(struct adapter *adap) { rte_eal_alarm_cancel(tx_timer_cb, (void *)adap); } /** * t4_free_sge_resources - free SGE resources * @adap: the adapter * * Frees resources used by the SGE queue sets. */ void t4_free_sge_resources(struct adapter *adap) { int i; struct sge_eth_rxq *rxq = &adap->sge.ethrxq[0]; struct sge_eth_txq *txq = &adap->sge.ethtxq[0]; /* clean up Ethernet Tx/Rx queues */ for (i = 0; i < adap->sge.max_ethqsets; i++, rxq++, txq++) { /* Free only the queues allocated */ if (rxq->rspq.desc) { t4_sge_eth_rxq_release(adap, rxq); rxq->rspq.eth_dev = NULL; } if (txq->q.desc) { t4_sge_eth_txq_release(adap, txq); txq->eth_dev = NULL; } } if (adap->sge.fw_evtq.desc) free_rspq_fl(adap, &adap->sge.fw_evtq, NULL); } /** * t4_sge_init - initialize SGE * @adap: the adapter * * Performs SGE initialization needed every time after a chip reset. * We do not initialize any of the queues here, instead the driver * top-level must request those individually. * * Called in two different modes: * * 1. Perform actual hardware initialization and record hard-coded * parameters which were used. This gets used when we're the * Master PF and the Firmware Configuration File support didn't * work for some reason. * * 2. We're not the Master PF or initialization was performed with * a Firmware Configuration File. In this case we need to grab * any of the SGE operating parameters that we need to have in * order to do our job and make sure we can live with them ... */ static int t4_sge_init_soft(struct adapter *adap) { struct sge *s = &adap->sge; u32 fl_small_pg, fl_large_pg, fl_small_mtu, fl_large_mtu; u32 timer_value_0_and_1, timer_value_2_and_3, timer_value_4_and_5; u32 ingress_rx_threshold; /* * Verify that CPL messages are going to the Ingress Queue for * process_responses() and that only packet data is going to the * Free Lists. */ if ((t4_read_reg(adap, A_SGE_CONTROL) & F_RXPKTCPLMODE) != V_RXPKTCPLMODE(X_RXPKTCPLMODE_SPLIT)) { dev_err(adap, "bad SGE CPL MODE\n"); return -EINVAL; } /* * Validate the Host Buffer Register Array indices that we want to * use ... * * XXX Note that we should really read through the Host Buffer Size * XXX register array and find the indices of the Buffer Sizes which * XXX meet our needs! */ #define READ_FL_BUF(x) \ t4_read_reg(adap, A_SGE_FL_BUFFER_SIZE0 + (x) * sizeof(u32)) fl_small_pg = READ_FL_BUF(RX_SMALL_PG_BUF); fl_large_pg = READ_FL_BUF(RX_LARGE_PG_BUF); fl_small_mtu = READ_FL_BUF(RX_SMALL_MTU_BUF); fl_large_mtu = READ_FL_BUF(RX_LARGE_MTU_BUF); /* * We only bother using the Large Page logic if the Large Page Buffer * is larger than our Page Size Buffer. */ if (fl_large_pg <= fl_small_pg) fl_large_pg = 0; #undef READ_FL_BUF /* * The Page Size Buffer must be exactly equal to our Page Size and the * Large Page Size Buffer should be 0 (per above) or a power of 2. */ if (fl_small_pg != CXGBE_PAGE_SIZE || (fl_large_pg & (fl_large_pg - 1)) != 0) { dev_err(adap, "bad SGE FL page buffer sizes [%d, %d]\n", fl_small_pg, fl_large_pg); return -EINVAL; } if (fl_large_pg) s->fl_pg_order = ilog2(fl_large_pg) - PAGE_SHIFT; if (adap->use_unpacked_mode) { int err = 0; if (fl_small_mtu < FL_MTU_SMALL_BUFSIZE(adap)) { dev_err(adap, "bad SGE FL small MTU %d\n", fl_small_mtu); err = -EINVAL; } if (fl_large_mtu < FL_MTU_LARGE_BUFSIZE(adap)) { dev_err(adap, "bad SGE FL large MTU %d\n", fl_large_mtu); err = -EINVAL; } if (err) return err; } /* * Retrieve our RX interrupt holdoff timer values and counter * threshold values from the SGE parameters. */ timer_value_0_and_1 = t4_read_reg(adap, A_SGE_TIMER_VALUE_0_AND_1); timer_value_2_and_3 = t4_read_reg(adap, A_SGE_TIMER_VALUE_2_AND_3); timer_value_4_and_5 = t4_read_reg(adap, A_SGE_TIMER_VALUE_4_AND_5); s->timer_val[0] = core_ticks_to_us(adap, G_TIMERVALUE0(timer_value_0_and_1)); s->timer_val[1] = core_ticks_to_us(adap, G_TIMERVALUE1(timer_value_0_and_1)); s->timer_val[2] = core_ticks_to_us(adap, G_TIMERVALUE2(timer_value_2_and_3)); s->timer_val[3] = core_ticks_to_us(adap, G_TIMERVALUE3(timer_value_2_and_3)); s->timer_val[4] = core_ticks_to_us(adap, G_TIMERVALUE4(timer_value_4_and_5)); s->timer_val[5] = core_ticks_to_us(adap, G_TIMERVALUE5(timer_value_4_and_5)); ingress_rx_threshold = t4_read_reg(adap, A_SGE_INGRESS_RX_THRESHOLD); s->counter_val[0] = G_THRESHOLD_0(ingress_rx_threshold); s->counter_val[1] = G_THRESHOLD_1(ingress_rx_threshold); s->counter_val[2] = G_THRESHOLD_2(ingress_rx_threshold); s->counter_val[3] = G_THRESHOLD_3(ingress_rx_threshold); return 0; } int t4_sge_init(struct adapter *adap) { struct sge *s = &adap->sge; u32 sge_control, sge_control2, sge_conm_ctrl; unsigned int ingpadboundary, ingpackboundary; int ret, egress_threshold; /* * Ingress Padding Boundary and Egress Status Page Size are set up by * t4_fixup_host_params(). */ sge_control = t4_read_reg(adap, A_SGE_CONTROL); s->pktshift = G_PKTSHIFT(sge_control); s->stat_len = (sge_control & F_EGRSTATUSPAGESIZE) ? 128 : 64; /* * T4 uses a single control field to specify both the PCIe Padding and * Packing Boundary. T5 introduced the ability to specify these * separately. The actual Ingress Packet Data alignment boundary * within Packed Buffer Mode is the maximum of these two * specifications. */ ingpadboundary = 1 << (G_INGPADBOUNDARY(sge_control) + X_INGPADBOUNDARY_SHIFT); s->fl_align = ingpadboundary; if (!is_t4(adap->params.chip) && !adap->use_unpacked_mode) { /* * T5 has a weird interpretation of one of the PCIe Packing * Boundary values. No idea why ... */ sge_control2 = t4_read_reg(adap, A_SGE_CONTROL2); ingpackboundary = G_INGPACKBOUNDARY(sge_control2); if (ingpackboundary == X_INGPACKBOUNDARY_16B) ingpackboundary = 16; else ingpackboundary = 1 << (ingpackboundary + X_INGPACKBOUNDARY_SHIFT); s->fl_align = max(ingpadboundary, ingpackboundary); } ret = t4_sge_init_soft(adap); if (ret < 0) { dev_err(adap, "%s: t4_sge_init_soft failed, error %d\n", __func__, -ret); return ret; } /* * A FL with <= fl_starve_thres buffers is starving and a periodic * timer will attempt to refill it. This needs to be larger than the * SGE's Egress Congestion Threshold. If it isn't, then we can get * stuck waiting for new packets while the SGE is waiting for us to * give it more Free List entries. (Note that the SGE's Egress * Congestion Threshold is in units of 2 Free List pointers.) For T4, * there was only a single field to control this. For T5 there's the * original field which now only applies to Unpacked Mode Free List * buffers and a new field which only applies to Packed Mode Free List * buffers. */ sge_conm_ctrl = t4_read_reg(adap, A_SGE_CONM_CTRL); if (is_t4(adap->params.chip) || adap->use_unpacked_mode) egress_threshold = G_EGRTHRESHOLD(sge_conm_ctrl); else egress_threshold = G_EGRTHRESHOLDPACKING(sge_conm_ctrl); s->fl_starve_thres = 2 * egress_threshold + 1; return 0; } ================================================ FILE: drivers/net/e1000/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_e1000.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_e1000_version.map LIBABIVER := 1 ifeq ($(CC), icc) # # CFLAGS for icc # CFLAGS_BASE_DRIVER = -wd177 -wd181 -wd188 -wd869 -wd2259 else # # CFLAGS for gcc # CFLAGS_BASE_DRIVER = -Wno-uninitialized -Wno-unused-parameter CFLAGS_BASE_DRIVER += -Wno-unused-variable endif # # Add extra flags for base driver files (also known as shared code) # to disable warnings in them # BASE_DRIVER_OBJS=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(BASE_DRIVER_OBJS), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_80003es2lan.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82540.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82541.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82542.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82543.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82571.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_82575.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_i210.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_api.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_ich8lan.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_mac.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_manage.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_mbx.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_nvm.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_osdep.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_phy.c SRCS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += e1000_vf.c SRCS-$(CONFIG_RTE_LIBRTE_IGB_PMD) += igb_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_IGB_PMD) += igb_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_IGB_PMD) += igb_pf.c SRCS-$(CONFIG_RTE_LIBRTE_EM_PMD) += em_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_EM_PMD) += em_rxtx.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/e1000/base/README ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This directory contains source code of FreeBSD em & igb drivers of version cid-shared-code.2014.04.21 released by LAD. The sub-directory of lad/ contains the original source package. Updating the driver =================== NOTE: The source code in this directory should not be modified apart from the following file(s): e1000_osdep.c e1000_osdep.h ================================================ FILE: drivers/net/e1000/base/e1000_80003es2lan.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* 80003ES2LAN Gigabit Ethernet Controller (Copper) * 80003ES2LAN Gigabit Ethernet Controller (Serdes) */ #include "e1000_api.h" STATIC s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw); STATIC void e1000_release_phy_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw); STATIC void e1000_release_nvm_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data); STATIC s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw); STATIC void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); STATIC s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); STATIC s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); STATIC s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data); STATIC void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); STATIC void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); STATIC s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); /* A table for the GG82563 cable length where the range is defined * with a lower bound at "index" and the upper bound at * "index + 5". */ STATIC const u16 e1000_gg82563_cable_length_table[] = { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF }; #define GG82563_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_gg82563_cable_length_table) / \ sizeof(e1000_gg82563_cable_length_table[0])) /** * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("e1000_init_phy_params_80003es2lan"); if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; return E1000_SUCCESS; } else { phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->type = e1000_phy_gg82563; phy->ops.acquire = e1000_acquire_phy_80003es2lan; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.check_reset_block = e1000_check_reset_block_generic; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.release = e1000_release_phy_80003es2lan; phy->ops.reset = e1000_phy_hw_reset_generic; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan; phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan; phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan; phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan; phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan; /* This can only be done after all function pointers are setup. */ ret_val = e1000_get_phy_id(hw); /* Verify phy id */ if (phy->id != GG82563_E_PHY_ID) return -E1000_ERR_PHY; return ret_val; } /** * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; DEBUGFUNC("e1000_init_nvm_params_80003es2lan"); nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; nvm->word_size = 1 << size; /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_80003es2lan; nvm->ops.read = e1000_read_nvm_eerd; nvm->ops.release = e1000_release_nvm_80003es2lan; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_80003es2lan; return E1000_SUCCESS; } /** * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_params_80003es2lan"); /* Set media type and media-dependent function pointers */ switch (hw->device_id) { case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: hw->phy.media_type = e1000_media_type_internal_serdes; mac->ops.check_for_link = e1000_check_for_serdes_link_generic; mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic; break; default: hw->phy.media_type = e1000_media_type_copper; mac->ops.check_for_link = e1000_check_for_copper_link_generic; mac->ops.setup_physical_interface = e1000_setup_copper_link_80003es2lan; break; } /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* FWSM register */ mac->has_fwsm = true; /* ARC supported; valid only if manageability features are enabled. */ mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); /* Adaptive IFS not supported */ mac->adaptive_ifs = false; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ mac->ops.reset_hw = e1000_reset_hw_80003es2lan; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_80003es2lan; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_generic; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ mac->ops.blink_led = e1000_blink_led_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan; /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); return E1000_SUCCESS; } /** * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_80003es2lan"); hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan; hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan; hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan; } /** * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY * @hw: pointer to the HW structure * * A wrapper to acquire access rights to the correct PHY. **/ STATIC s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) { u16 mask; DEBUGFUNC("e1000_acquire_phy_80003es2lan"); mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; return e1000_acquire_swfw_sync_80003es2lan(hw, mask); } /** * e1000_release_phy_80003es2lan - Release rights to access PHY * @hw: pointer to the HW structure * * A wrapper to release access rights to the correct PHY. **/ STATIC void e1000_release_phy_80003es2lan(struct e1000_hw *hw) { u16 mask; DEBUGFUNC("e1000_release_phy_80003es2lan"); mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; e1000_release_swfw_sync_80003es2lan(hw, mask); } /** * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register * @hw: pointer to the HW structure * * Acquire the semaphore to access the Kumeran interface. * **/ STATIC s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) { u16 mask; DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan"); mask = E1000_SWFW_CSR_SM; return e1000_acquire_swfw_sync_80003es2lan(hw, mask); } /** * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register * @hw: pointer to the HW structure * * Release the semaphore used to access the Kumeran interface **/ STATIC void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw) { u16 mask; DEBUGFUNC("e1000_release_mac_csr_80003es2lan"); mask = E1000_SWFW_CSR_SM; e1000_release_swfw_sync_80003es2lan(hw, mask); } /** * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM * @hw: pointer to the HW structure * * Acquire the semaphore to access the EEPROM. **/ STATIC s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_80003es2lan"); ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); if (ret_val) return ret_val; ret_val = e1000_acquire_nvm_generic(hw); if (ret_val) e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); return ret_val; } /** * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM * @hw: pointer to the HW structure * * Release the semaphore used to access the EEPROM. **/ STATIC void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_80003es2lan"); e1000_release_nvm_generic(hw); e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); } /** * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ STATIC s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 i = 0; s32 timeout = 50; DEBUGFUNC("e1000_acquire_swfw_sync_80003es2lan"); while (i < timeout) { if (e1000_get_hw_semaphore_generic(hw)) return -E1000_ERR_SWFW_SYNC; swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } if (i == timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); return -E1000_ERR_SWFW_SYNC; } swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); return E1000_SUCCESS; } /** * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ STATIC void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; DEBUGFUNC("e1000_release_swfw_sync_80003es2lan"); while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); } /** * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register * @hw: pointer to the HW structure * @offset: offset of the register to read * @data: pointer to the data returned from the operation * * Read the GG82563 PHY register. **/ STATIC s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; u32 page_select; u16 temp; DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan"); ret_val = e1000_acquire_phy_80003es2lan(hw); if (ret_val) return ret_val; /* Select Configuration Page */ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { page_select = GG82563_PHY_PAGE_SELECT; } else { /* Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; } temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); if (ret_val) { e1000_release_phy_80003es2lan(hw); return ret_val; } if (hw->dev_spec._80003es2lan.mdic_wa_enable) { /* The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ usec_delay(200); /* ...and verify the command was successful. */ ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { e1000_release_phy_80003es2lan(hw); return -E1000_ERR_PHY; } usec_delay(200); ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); usec_delay(200); } else { ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); } e1000_release_phy_80003es2lan(hw); return ret_val; } /** * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register * @hw: pointer to the HW structure * @offset: offset of the register to read * @data: value to write to the register * * Write to the GG82563 PHY register. **/ STATIC s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; u32 page_select; u16 temp; DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan"); ret_val = e1000_acquire_phy_80003es2lan(hw); if (ret_val) return ret_val; /* Select Configuration Page */ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { page_select = GG82563_PHY_PAGE_SELECT; } else { /* Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; } temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp); if (ret_val) { e1000_release_phy_80003es2lan(hw); return ret_val; } if (hw->dev_spec._80003es2lan.mdic_wa_enable) { /* The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ usec_delay(200); /* ...and verify the command was successful. */ ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp); if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { e1000_release_phy_80003es2lan(hw); return -E1000_ERR_PHY; } usec_delay(200); ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); usec_delay(200); } else { ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); } e1000_release_phy_80003es2lan(hw); return ret_val; } /** * e1000_write_nvm_80003es2lan - Write to ESB2 NVM * @hw: pointer to the HW structure * @offset: offset of the register to read * @words: number of words to write * @data: buffer of data to write to the NVM * * Write "words" of data to the ESB2 NVM. **/ STATIC s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { DEBUGFUNC("e1000_write_nvm_80003es2lan"); return e1000_write_nvm_spi(hw, offset, words, data); } /** * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete * @hw: pointer to the HW structure * * Wait a specific amount of time for manageability processes to complete. * This is a function pointer entry point called by the phy module. **/ STATIC s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; u32 mask = E1000_NVM_CFG_DONE_PORT_0; DEBUGFUNC("e1000_get_cfg_done_80003es2lan"); if (hw->bus.func == 1) mask = E1000_NVM_CFG_DONE_PORT_1; while (timeout) { if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) break; msec_delay(1); timeout--; } if (!timeout) { DEBUGOUT("MNG configuration cycle has not completed.\n"); return -E1000_ERR_RESET; } return E1000_SUCCESS; } /** * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex * @hw: pointer to the HW structure * * Force the speed and duplex settings onto the PHY. This is a * function pointer entry point called by the phy module. **/ STATIC s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) { s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan"); if (!(hw->phy.ops.read_reg)) return E1000_SUCCESS; /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; DEBUGOUT1("GG82563 PSCR: %X\n", phy_data); ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); /* Reset the phy to commit changes. */ phy_data |= MII_CR_RESET; ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; usec_delay(1); if (hw->phy.autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) { /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = e1000_phy_reset_dsp_generic(hw); if (ret_val) return ret_val; } /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; } ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* Resetting the phy means we need to verify the TX_CLK corresponds * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. */ phy_data &= ~GG82563_MSCR_TX_CLK_MASK; if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; else phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); return ret_val; } /** * e1000_get_cable_length_80003es2lan - Set approximate cable length * @hw: pointer to the HW structure * * Find the approximate cable length as measured by the GG82563 PHY. * This is a function pointer entry point called by the phy module. **/ STATIC s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, index; DEBUGFUNC("e1000_get_cable_length_80003es2lan"); if (!(hw->phy.ops.read_reg)) return E1000_SUCCESS; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); if (ret_val) return ret_val; index = phy_data & GG82563_DSPD_CABLE_LENGTH; if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) return -E1000_ERR_PHY; phy->min_cable_length = e1000_gg82563_cable_length_table[index]; phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; return E1000_SUCCESS; } /** * e1000_get_link_up_info_80003es2lan - Report speed and duplex * @hw: pointer to the HW structure * @speed: pointer to speed buffer * @duplex: pointer to duplex buffer * * Retrieve the current speed and duplex configuration. **/ STATIC s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex) { s32 ret_val; DEBUGFUNC("e1000_get_link_up_info_80003es2lan"); if (hw->phy.media_type == e1000_media_type_copper) { ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); hw->phy.ops.cfg_on_link_up(hw); } else { ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw, speed, duplex); } return ret_val; } /** * e1000_reset_hw_80003es2lan - Reset the ESB2 controller * @hw: pointer to the HW structure * * Perform a global reset to the ESB2 controller. **/ STATIC s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u16 kum_reg_data; DEBUGFUNC("e1000_reset_hw_80003es2lan"); /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); ret_val = e1000_acquire_phy_80003es2lan(hw); if (ret_val) return ret_val; DEBUGOUT("Issuing a global reset to MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); e1000_release_phy_80003es2lan(hw); /* Disable IBIST slave mode (far-end loopback) */ ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data); if (ret_val) return ret_val; kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, kum_reg_data); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) /* We don't want to continue accessing MAC registers. */ return ret_val; /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); return e1000_check_alt_mac_addr_generic(hw); } /** * e1000_init_hw_80003es2lan - Initialize the ESB2 controller * @hw: pointer to the HW structure * * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. **/ STATIC s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 reg_data; s32 ret_val; u16 kum_reg_data; u16 i; DEBUGFUNC("e1000_init_hw_80003es2lan"); e1000_initialize_hw_bits_80003es2lan(hw); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); /* An error is not fatal and we should not stop init due to this */ if (ret_val) DEBUGOUT("Error initializing identification LED\n"); /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); if (ret_val) return ret_val; /* Disable IBIST slave mode (far-end loopback) */ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data); kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, kum_reg_data); /* Set the transmit descriptor write-back policy */ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); /* ...for both queues. */ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); /* Enable retransmit on late collisions */ reg_data = E1000_READ_REG(hw, E1000_TCTL); reg_data |= E1000_TCTL_RTLC; E1000_WRITE_REG(hw, E1000_TCTL, reg_data); /* Configure Gigabit Carry Extend Padding */ reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT); reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data); /* Configure Transmit Inter-Packet Gap */ reg_data = E1000_READ_REG(hw, E1000_TIPG); reg_data &= ~E1000_TIPG_IPGT_MASK; reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TIPG, reg_data); reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); reg_data &= ~0x00100000; E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); /* default to true to enable the MDIC W/A */ hw->dev_spec._80003es2lan.mdic_wa_enable = true; ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >> E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i); if (!ret_val) { if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) hw->dev_spec._80003es2lan.mdic_wa_enable = false; } /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_80003es2lan(hw); return ret_val; } /** * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 * @hw: pointer to the HW structure * * Initializes required hardware-dependent bits needed for normal operation. **/ STATIC void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan"); /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); /* Transmit Descriptor Control 1 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); /* Transmit Arbitration Control 0 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); reg &= ~(0xF << 27); /* 30:27 */ if (hw->phy.media_type != e1000_media_type_copper) reg &= ~(1 << 20); E1000_WRITE_REG(hw, E1000_TARC(0), reg); /* Transmit Arbitration Control 1 */ reg = E1000_READ_REG(hw, E1000_TARC(1)); if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) reg &= ~(1 << 28); else reg |= (1 << 28); E1000_WRITE_REG(hw, E1000_TARC(1), reg); /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ reg = E1000_READ_REG(hw, E1000_RFCTL); reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); E1000_WRITE_REG(hw, E1000_RFCTL, reg); return; } /** * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link * @hw: pointer to the HW structure * * Setup some GG82563 PHY registers for obtaining link **/ STATIC s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u32 reg; u16 data; DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan"); ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); if (ret_val) return ret_val; data |= GG82563_MSCR_ASSERT_CRS_ON_TX; /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ data |= GG82563_MSCR_TX_CLK_1000MBPS_25; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data); if (ret_val) return ret_val; /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data); if (ret_val) return ret_val; data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; switch (phy->mdix) { case 1: data |= GG82563_PSCR_CROSSOVER_MODE_MDI; break; case 2: data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; break; case 0: default: data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; break; } /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; if (phy->disable_polarity_correction) data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data); if (ret_val) return ret_val; /* SW Reset the PHY so all changes take effect */ ret_val = hw->phy.ops.commit(hw); if (ret_val) { DEBUGOUT("Error Resetting the PHY\n"); return ret_val; } /* Bypass Rx and Tx FIFO's */ reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL; data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); if (ret_val) return ret_val; reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE; ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data); if (ret_val) return ret_val; data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data); if (ret_val) return ret_val; data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data); if (ret_val) return ret_val; reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); if (ret_val) return ret_val; /* Do not init these registers when the HW is in IAMT mode, since the * firmware will have already initialized them. We only initialize * them if the HW is not in IAMT mode. */ if (!hw->mac.ops.check_mng_mode(hw)) { /* Enable Electrical Idle on the PHY */ data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, data); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); if (ret_val) return ret_val; data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, data); if (ret_val) return ret_val; } /* Workaround: Disable padding in Kumeran interface in the MAC * and in the PHY to avoid CRC errors. */ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data); if (ret_val) return ret_val; data |= GG82563_ICR_DIS_PADDING; ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data); if (ret_val) return ret_val; return E1000_SUCCESS; } /** * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 * @hw: pointer to the HW structure * * Essentially a wrapper for setting up all things "copper" related. * This is a function pointer entry point called by the mac module. **/ STATIC s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_setup_copper_link_80003es2lan"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Set the mac to wait the maximum time between each * iteration and increase the max iterations when * polling the phy; this fixes erroneous timeouts at 10Mbps. */ ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), 0xFFFF); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), ®_data); if (ret_val) return ret_val; reg_data |= 0x3F; ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), reg_data); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, ®_data); if (ret_val) return ret_val; reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, reg_data); if (ret_val) return ret_val; ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw); if (ret_val) return ret_val; return e1000_setup_copper_link_generic(hw); } /** * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up * @hw: pointer to the HW structure * @duplex: current duplex setting * * Configure the KMRN interface by applying last minute quirks for * 10/100 operation. **/ STATIC s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 speed; u16 duplex; DEBUGFUNC("e1000_configure_on_link_up"); if (hw->phy.media_type == e1000_media_type_copper) { ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex); if (ret_val) return ret_val; if (speed == SPEED_1000) ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); else ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex); } return ret_val; } /** * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation * @hw: pointer to the HW structure * @duplex: current duplex setting * * Configure the KMRN interface by applying last minute quirks for * 10/100 operation. **/ STATIC s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) { s32 ret_val; u32 tipg; u32 i = 0; u16 reg_data, reg_data2; DEBUGFUNC("e1000_configure_kmrn_for_10_100"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) return ret_val; /* Configure Transmit Inter-Packet Gap */ tipg = E1000_READ_REG(hw, E1000_TIPG); tipg &= ~E1000_TIPG_IPGT_MASK; tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TIPG, tipg); do { ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); if (ret_val) return ret_val; i++; } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); if (duplex == HALF_DUPLEX) reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; else reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); } /** * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation * @hw: pointer to the HW structure * * Configure the KMRN interface by applying last minute quirks for * gigabit operation. **/ STATIC s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) { s32 ret_val; u16 reg_data, reg_data2; u32 tipg; u32 i = 0; DEBUGFUNC("e1000_configure_kmrn_for_1000"); reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; ret_val = e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, reg_data); if (ret_val) return ret_val; /* Configure Transmit Inter-Packet Gap */ tipg = E1000_READ_REG(hw, E1000_TIPG); tipg &= ~E1000_TIPG_IPGT_MASK; tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; E1000_WRITE_REG(hw, E1000_TIPG, tipg); do { ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); if (ret_val) return ret_val; i++; } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); } /** * e1000_read_kmrn_reg_80003es2lan - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquire semaphore, then read the PHY register at offset * using the kumeran interface. The information retrieved is stored in data. * Release the semaphore before exiting. **/ STATIC s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) { u32 kmrnctrlsta; s32 ret_val; DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan"); ret_val = e1000_acquire_mac_csr_80003es2lan(hw); if (ret_val) return ret_val; kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); *data = (u16)kmrnctrlsta; e1000_release_mac_csr_80003es2lan(hw); return ret_val; } /** * e1000_write_kmrn_reg_80003es2lan - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquire semaphore, then write the data to PHY register * at the offset using the kumeran interface. Release semaphore * before exiting. **/ STATIC s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) { u32 kmrnctrlsta; s32 ret_val; DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan"); ret_val = e1000_acquire_mac_csr_80003es2lan(hw); if (ret_val) return ret_val; kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | data; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); e1000_release_mac_csr_80003es2lan(hw); return ret_val; } /** * e1000_read_mac_addr_80003es2lan - Read device MAC address * @hw: pointer to the HW structure **/ STATIC s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_read_mac_addr_80003es2lan"); /* If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) return ret_val; return e1000_read_mac_addr_generic(hw); } /** * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) { /* If the management interface is not enabled, then power down */ if (!(hw->mac.ops.check_mng_mode(hw) || hw->phy.ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); E1000_READ_REG(hw, E1000_IAC); E1000_READ_REG(hw, E1000_ICRXOC); E1000_READ_REG(hw, E1000_ICRXPTC); E1000_READ_REG(hw, E1000_ICRXATC); E1000_READ_REG(hw, E1000_ICTXPTC); E1000_READ_REG(hw, E1000_ICTXATC); E1000_READ_REG(hw, E1000_ICTXQEC); E1000_READ_REG(hw, E1000_ICTXQMTC); E1000_READ_REG(hw, E1000_ICRXDMTC); } ================================================ FILE: drivers/net/e1000/base/e1000_80003es2lan.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_80003ES2LAN_H_ #define _E1000_80003ES2LAN_H_ #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 #define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 #define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 #define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 #define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C #define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */ #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 #define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 #define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 /* GG82563 PHY Specific Status Register (Page 0, Register 16 */ #define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Dis */ #define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 #define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ #define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ #define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ /* PHY Specific Control Register 2 (Page 0, Register 26) */ #define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Neg */ /* MAC Specific Control Register (Page 2, Register 21) */ /* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ #define GG82563_MSCR_TX_CLK_MASK 0x0007 #define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 #define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 #define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 #define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ /* DSP Distance Register (Page 5, Register 26) * 0 = <50M * 1 = 50-80M * 2 = 80-100M * 3 = 110-140M * 4 = >140M */ #define GG82563_DSPD_CABLE_LENGTH 0x0007 /* Kumeran Mode Control Register (Page 193, Register 16) */ #define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 /* Max number of times Kumeran read/write should be validated */ #define GG82563_MAX_KMRN_RETRY 0x5 /* Power Management Control Register (Page 193, Register 20) */ /* 1=Enable SERDES Electrical Idle */ #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 /* In-Band Control Register (Page 194, Register 18) */ #define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ #endif ================================================ FILE: drivers/net/e1000/base/e1000_82540.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* * 82540EM Gigabit Ethernet Controller * 82540EP Gigabit Ethernet Controller * 82545EM Gigabit Ethernet Controller (Copper) * 82545EM Gigabit Ethernet Controller (Fiber) * 82545GM Gigabit Ethernet Controller * 82546EB Gigabit Ethernet Controller (Copper) * 82546EB Gigabit Ethernet Controller (Fiber) * 82546GB Gigabit Ethernet Controller */ #include "e1000_api.h" STATIC s32 e1000_init_phy_params_82540(struct e1000_hw *hw); STATIC s32 e1000_init_nvm_params_82540(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_82540(struct e1000_hw *hw); STATIC s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw); STATIC void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw); STATIC s32 e1000_init_hw_82540(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_82540(struct e1000_hw *hw); STATIC s32 e1000_set_phy_mode_82540(struct e1000_hw *hw); STATIC s32 e1000_set_vco_speed_82540(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_82540(struct e1000_hw *hw); STATIC s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_82540(struct e1000_hw *hw); STATIC s32 e1000_read_mac_addr_82540(struct e1000_hw *hw); /** * e1000_init_phy_params_82540 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82540(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 10000; phy->type = e1000_phy_m88; /* Function Pointers */ phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.read_reg = e1000_read_phy_reg_m88; phy->ops.reset = e1000_phy_hw_reset_generic; phy->ops.write_reg = e1000_write_phy_reg_m88; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82540; ret_val = e1000_get_phy_id(hw); if (ret_val) goto out; /* Verify phy id */ switch (hw->mac.type) { case e1000_82540: case e1000_82545: case e1000_82545_rev_3: case e1000_82546: case e1000_82546_rev_3: if (phy->id == M88E1011_I_PHY_ID) break; /* Fall Through */ default: ret_val = -E1000_ERR_PHY; goto out; break; } out: return ret_val; } /** * e1000_init_nvm_params_82540 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_82540(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); DEBUGFUNC("e1000_init_nvm_params_82540"); nvm->type = e1000_nvm_eeprom_microwire; nvm->delay_usec = 50; nvm->opcode_bits = 3; switch (nvm->override) { case e1000_nvm_override_microwire_large: nvm->address_bits = 8; nvm->word_size = 256; break; case e1000_nvm_override_microwire_small: nvm->address_bits = 6; nvm->word_size = 64; break; default: nvm->address_bits = eecd & E1000_EECD_SIZE ? 8 : 6; nvm->word_size = eecd & E1000_EECD_SIZE ? 256 : 64; break; } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_generic; nvm->ops.read = e1000_read_nvm_microwire; nvm->ops.release = e1000_release_nvm_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_microwire; return E1000_SUCCESS; } /** * e1000_init_mac_params_82540 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82540(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_mac_params_82540"); /* Set media type */ switch (hw->device_id) { case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545GM_FIBER: case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546GB_FIBER: hw->phy.media_type = e1000_media_type_fiber; break; case E1000_DEV_ID_82545GM_SERDES: case E1000_DEV_ID_82546GB_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; break; default: hw->phy.media_type = e1000_media_type_copper; break; } /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; /* function id */ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82540; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82540; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; /* physical interface setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82540 : e1000_setup_fiber_serdes_link_82540; /* check for link */ switch (hw->phy.media_type) { case e1000_media_type_copper: mac->ops.check_for_link = e1000_check_for_copper_link_generic; break; case e1000_media_type_fiber: mac->ops.check_for_link = e1000_check_for_fiber_link_generic; break; case e1000_media_type_internal_serdes: mac->ops.check_for_link = e1000_check_for_serdes_link_generic; break; default: ret_val = -E1000_ERR_CONFIG; goto out; break; } /* link info */ mac->ops.get_link_up_info = (hw->phy.media_type == e1000_media_type_copper) ? e1000_get_speed_and_duplex_copper_generic : e1000_get_speed_and_duplex_fiber_serdes_generic; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82540; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82540; out: return ret_val; } /** * e1000_init_function_pointers_82540 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82540(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82540"); hw->mac.ops.init_params = e1000_init_mac_params_82540; hw->nvm.ops.init_params = e1000_init_nvm_params_82540; hw->phy.ops.init_params = e1000_init_phy_params_82540; } /** * e1000_reset_hw_82540 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82540(struct e1000_hw *hw) { u32 ctrl, manc; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82540"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); /* * Delay to allow any outstanding PCI transactions to complete * before resetting the device. */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82540/82545/82546 MAC\n"); switch (hw->mac.type) { case e1000_82545_rev_3: case e1000_82546_rev_3: E1000_WRITE_REG(hw, E1000_CTRL_DUP, ctrl | E1000_CTRL_RST); break; default: /* * These controllers can't ack the 64-bit write when * issuing the reset, so we use IO-mapping as a * workaround to issue the reset. */ E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); break; } /* Wait for EEPROM reload */ msec_delay(5); /* Disable HW ARPs on ASF enabled adapters */ manc = E1000_READ_REG(hw, E1000_MANC); manc &= ~E1000_MANC_ARP_EN; E1000_WRITE_REG(hw, E1000_MANC, manc); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); return ret_val; } /** * e1000_init_hw_82540 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ STATIC s32 e1000_init_hw_82540(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 txdctl, ctrl_ext; s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_82540"); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); if (ret_val) { DEBUGOUT("Error initializing identification LED\n"); /* This is not fatal and we should not stop init due to this */ } /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); if (mac->type < e1000_82545_rev_3) E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) { E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* * Avoid back to back register writes by adding the register * read (flush). This is to protect against some strange * bridge configurations that may issue Memory Write Block * (MWB) to our register space. The *_rev_3 hardware at * least doesn't respond correctly to every other dword in an * MWB to our register space. */ E1000_WRITE_FLUSH(hw); } if (mac->type < e1000_82545_rev_3) e1000_pcix_mmrbc_workaround_generic(hw); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82540(hw); if ((hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER) || (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3)) { ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* * Relaxed ordering must be disabled to avoid a parity * error crash in a PCI slot. */ ctrl_ext |= E1000_CTRL_EXT_RO_DIS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } return ret_val; } /** * e1000_setup_copper_link_82540 - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). **/ STATIC s32 e1000_setup_copper_link_82540(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u16 data; DEBUGFUNC("e1000_setup_copper_link_82540"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = e1000_set_phy_mode_82540(hw); if (ret_val) goto out; if (hw->mac.type == e1000_82545_rev_3 || hw->mac.type == e1000_82546_rev_3) { ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &data); if (ret_val) goto out; data |= 0x00000008; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, data); if (ret_val) goto out; } ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw); out: return ret_val; } /** * e1000_setup_fiber_serdes_link_82540 - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Set the output amplitude to the value in the EEPROM and adjust the VCO * speed to improve Bit Error Rate (BER) performance. Configures collision * distance and flow control for fiber and serdes links. Upon successful * setup, poll for link. **/ STATIC s32 e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_fiber_serdes_link_82540"); switch (mac->type) { case e1000_82545_rev_3: case e1000_82546_rev_3: if (hw->phy.media_type == e1000_media_type_internal_serdes) { /* * If we're on serdes media, adjust the output * amplitude to value set in the EEPROM. */ ret_val = e1000_adjust_serdes_amplitude_82540(hw); if (ret_val) goto out; } /* Adjust VCO speed to improve BER performance */ ret_val = e1000_set_vco_speed_82540(hw); if (ret_val) goto out; default: break; } ret_val = e1000_setup_fiber_serdes_link_generic(hw); out: return ret_val; } /** * e1000_adjust_serdes_amplitude_82540 - Adjust amplitude based on EEPROM * @hw: pointer to the HW structure * * Adjust the SERDES output amplitude based on the EEPROM settings. **/ STATIC s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw) { s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_adjust_serdes_amplitude_82540"); ret_val = hw->nvm.ops.read(hw, NVM_SERDES_AMPLITUDE, 1, &nvm_data); if (ret_val) goto out; if (nvm_data != NVM_RESERVED_WORD) { /* Adjust serdes output amplitude only. */ nvm_data &= NVM_SERDES_AMPLITUDE_MASK; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_EXT_CTRL, nvm_data); if (ret_val) goto out; } out: return ret_val; } /** * e1000_set_vco_speed_82540 - Set VCO speed for better performance * @hw: pointer to the HW structure * * Set the VCO speed to improve Bit Error Rate (BER) performance. **/ STATIC s32 e1000_set_vco_speed_82540(struct e1000_hw *hw) { s32 ret_val; u16 default_page = 0; u16 phy_data; DEBUGFUNC("e1000_set_vco_speed_82540"); /* Set PHY register 30, page 5, bit 8 to 0 */ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); if (ret_val) goto out; ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); if (ret_val) goto out; phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); if (ret_val) goto out; /* Set PHY register 30, page 4, bit 11 to 1 */ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); if (ret_val) goto out; ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); if (ret_val) goto out; phy_data |= M88E1000_PHY_VCO_REG_BIT11; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page); out: return ret_val; } /** * e1000_set_phy_mode_82540 - Set PHY to class A mode * @hw: pointer to the HW structure * * Sets the PHY to class A mode and assumes the following operations will * follow to enable the new class mode: * 1. Do a PHY soft reset. * 2. Restart auto-negotiation or force link. **/ STATIC s32 e1000_set_phy_mode_82540(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 nvm_data; DEBUGFUNC("e1000_set_phy_mode_82540"); if (hw->mac.type != e1000_82545_rev_3) goto out; ret_val = hw->nvm.ops.read(hw, NVM_PHY_CLASS_WORD, 1, &nvm_data); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } if ((nvm_data != NVM_RESERVED_WORD) && (nvm_data & NVM_PHY_CLASS_A)) { ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104); if (ret_val) { ret_val = -E1000_ERR_PHY; goto out; } } out: return ret_val; } /** * e1000_power_down_phy_copper_82540 - Remove link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_82540(struct e1000_hw *hw) { /* If the management interface is not enabled, then power down */ if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_82540 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82540(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82540"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); } /** * e1000_read_mac_addr_82540 - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. * Since devices with two ports use the same EEPROM, we increment the * last bit in the MAC address for the second port. * * This version is being used over generic because of customer issues * with VmWare and Virtual Box when using generic. It seems in * the emulated 82545, RAR[0] does NOT have a valid address after a * reset, this older method works and using this breaks nothing for * these legacy adapters. **/ s32 e1000_read_mac_addr_82540(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 offset, nvm_data, i; DEBUGFUNC("e1000_read_mac_addr"); for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = i >> 1; ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); } /* Flip last bit of mac address if we're on second port */ if (hw->bus.func == E1000_FUNC_1) hw->mac.perm_addr[5] ^= 1; for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; out: return ret_val; } ================================================ FILE: drivers/net/e1000/base/e1000_82541.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* * 82541EI Gigabit Ethernet Controller * 82541ER Gigabit Ethernet Controller * 82541GI Gigabit Ethernet Controller * 82541PI Gigabit Ethernet Controller * 82547EI Gigabit Ethernet Controller * 82547GI Gigabit Ethernet Controller */ #include "e1000_api.h" STATIC s32 e1000_init_phy_params_82541(struct e1000_hw *hw); STATIC s32 e1000_init_nvm_params_82541(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_82541(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_82541(struct e1000_hw *hw); STATIC s32 e1000_init_hw_82541(struct e1000_hw *hw); STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_82541(struct e1000_hw *hw); STATIC s32 e1000_check_for_link_82541(struct e1000_hw *hw); STATIC s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw); STATIC s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active); STATIC s32 e1000_setup_led_82541(struct e1000_hw *hw); STATIC s32 e1000_cleanup_led_82541(struct e1000_hw *hw); STATIC void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw); STATIC s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, bool link_up); STATIC s32 e1000_phy_init_script_82541(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_82541(struct e1000_hw *hw); STATIC const u16 e1000_igp_cable_length_table[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; #define IGP01E1000_AGC_LENGTH_TABLE_SIZE \ (sizeof(e1000_igp_cable_length_table) / \ sizeof(e1000_igp_cable_length_table[0])) /** * e1000_init_phy_params_82541 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("e1000_init_phy_params_82541"); phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 10000; phy->type = e1000_phy_igp; /* Function Pointers */ phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; phy->ops.get_cable_length = e1000_get_cable_length_igp_82541; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.get_info = e1000_get_phy_info_igp; phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.reset = e1000_phy_hw_reset_82541; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541; phy->ops.write_reg = e1000_write_phy_reg_igp; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82541; ret_val = e1000_get_phy_id(hw); if (ret_val) goto out; /* Verify phy id */ if (phy->id != IGP01E1000_I_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } out: return ret_val; } /** * e1000_init_nvm_params_82541 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_82541(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val = E1000_SUCCESS; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; DEBUGFUNC("e1000_init_nvm_params_82541"); switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->type = e1000_nvm_eeprom_spi; eecd |= E1000_EECD_ADDR_BITS; break; case e1000_nvm_override_spi_small: nvm->type = e1000_nvm_eeprom_spi; eecd &= ~E1000_EECD_ADDR_BITS; break; case e1000_nvm_override_microwire_large: nvm->type = e1000_nvm_eeprom_microwire; eecd |= E1000_EECD_SIZE; break; case e1000_nvm_override_microwire_small: nvm->type = e1000_nvm_eeprom_microwire; eecd &= ~E1000_EECD_SIZE; break; default: nvm->type = eecd & E1000_EECD_TYPE ? e1000_nvm_eeprom_spi : e1000_nvm_eeprom_microwire; break; } if (nvm->type == e1000_nvm_eeprom_spi) { nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 16 : 8; nvm->delay_usec = 1; nvm->opcode_bits = 8; nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) ? 32 : 8; /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_generic; nvm->ops.read = e1000_read_nvm_spi; nvm->ops.release = e1000_release_nvm_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_spi; /* * nvm->word_size must be discovered after the pointers * are set so we can verify the size from the nvm image * itself. Temporarily set it to a dummy value so the * read will work. */ nvm->word_size = 64; ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size); if (ret_val) goto out; size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT; /* * if size != 0, it can be added to a constant and become * the left-shift value to set the word_size. Otherwise, * word_size stays at 64. */ if (size) { size += NVM_WORD_SIZE_BASE_SHIFT_82541; nvm->word_size = 1 << size; } } else { nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 8 : 6; nvm->delay_usec = 50; nvm->opcode_bits = 3; nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) ? 256 : 64; /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_generic; nvm->ops.read = e1000_read_nvm_microwire; nvm->ops.release = e1000_release_nvm_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_microwire; } out: return ret_val; } /** * e1000_init_mac_params_82541 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82541(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_params_82541"); /* Set media type */ hw->phy.media_type = e1000_media_type_copper; /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* Function Pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; /* function id */ mac->ops.set_lan_id = e1000_set_lan_id_single_port; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82541; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82541; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; /* physical interface link setup */ mac->ops.setup_physical_interface = e1000_setup_copper_link_82541; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82541; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82541; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_82541; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_82541; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541; return E1000_SUCCESS; } /** * e1000_init_function_pointers_82541 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82541(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82541"); hw->mac.ops.init_params = e1000_init_mac_params_82541; hw->nvm.ops.init_params = e1000_init_nvm_params_82541; hw->phy.ops.init_params = e1000_init_phy_params_82541; } /** * e1000_reset_hw_82541 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82541(struct e1000_hw *hw) { u32 ledctl, ctrl, manc; DEBUGFUNC("e1000_reset_hw_82541"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); /* * Delay to allow any outstanding PCI transactions to complete * before resetting the device. */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Must reset the Phy before resetting the MAC */ if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST)); E1000_WRITE_FLUSH(hw); msec_delay(5); } DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n"); switch (hw->mac.type) { case e1000_82541: case e1000_82541_rev_2: /* * These controllers can't ack the 64-bit write when * issuing the reset, so we use IO-mapping as a * workaround to issue the reset. */ E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); break; default: E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); break; } /* Wait for NVM reload */ msec_delay(20); /* Disable HW ARPs on ASF enabled adapters */ manc = E1000_READ_REG(hw, E1000_MANC); manc &= ~E1000_MANC_ARP_EN; E1000_WRITE_REG(hw, E1000_MANC, manc); if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { e1000_phy_init_script_82541(hw); /* Configure activity LED after Phy reset */ ledctl = E1000_READ_REG(hw, E1000_LEDCTL); ledctl &= IGP_ACTIVITY_LED_MASK; ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); } /* Once again, mask the interrupts */ DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); /* Clear any pending interrupt events. */ E1000_READ_REG(hw, E1000_ICR); return E1000_SUCCESS; } /** * e1000_init_hw_82541 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ STATIC s32 e1000_init_hw_82541(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; u32 i, txdctl; s32 ret_val; DEBUGFUNC("e1000_init_hw_82541"); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); if (ret_val) { DEBUGOUT("Error initializing identification LED\n"); /* This is not fatal and we should not stop init due to this */ } /* Storing the Speed Power Down value for later use */ ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO, &dev_spec->spd_default); if (ret_val) goto out; /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) { E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* * Avoid back to back register writes by adding the register * read (flush). This is to protect against some strange * bridge configurations that may issue Memory Write Block * (MWB) to our register space. */ E1000_WRITE_FLUSH(hw); } /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB; E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82541(hw); out: return ret_val; } /** * e1000_get_link_up_info_82541 - Report speed and duplex * @hw: pointer to the HW structure * @speed: pointer to speed buffer * @duplex: pointer to duplex buffer * * Retrieve the current speed and duplex configuration. **/ STATIC s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed, u16 *duplex) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_get_link_up_info_82541"); ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); if (ret_val) goto out; if (!phy->speed_downgraded) goto out; /* * IGP01 PHY may advertise full duplex operation after speed * downgrade even if it is operating at half duplex. * Here we set the duplex settings to match the duplex in the * link partner's capabilities. */ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data); if (ret_val) goto out; if (!(data & NWAY_ER_LP_NWAY_CAPS)) { *duplex = HALF_DUPLEX; } else { ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data); if (ret_val) goto out; if (*speed == SPEED_100) { if (!(data & NWAY_LPAR_100TX_FD_CAPS)) *duplex = HALF_DUPLEX; } else if (*speed == SPEED_10) { if (!(data & NWAY_LPAR_10T_FD_CAPS)) *duplex = HALF_DUPLEX; } } out: return ret_val; } /** * e1000_phy_hw_reset_82541 - PHY hardware reset * @hw: pointer to the HW structure * * Verify the reset block is not blocking us from resetting. Acquire * semaphore (if necessary) and read/set/write the device control reset * bit in the PHY. Wait the appropriate delay time for the device to * reset and release the semaphore (if necessary). **/ STATIC s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw) { s32 ret_val; u32 ledctl; DEBUGFUNC("e1000_phy_hw_reset_82541"); ret_val = e1000_phy_hw_reset_generic(hw); if (ret_val) goto out; e1000_phy_init_script_82541(hw); if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) { /* Configure activity LED after PHY reset */ ledctl = E1000_READ_REG(hw, E1000_LEDCTL); ledctl &= IGP_ACTIVITY_LED_MASK; ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); } out: return ret_val; } /** * e1000_setup_copper_link_82541 - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). **/ STATIC s32 e1000_setup_copper_link_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; u32 ctrl, ledctl; DEBUGFUNC("e1000_setup_copper_link_82541"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Earlier revs of the IGP phy require us to force MDI. */ if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) { dev_spec->dsp_config = e1000_dsp_config_disabled; phy->mdix = 1; } else { dev_spec->dsp_config = e1000_dsp_config_enabled; } ret_val = e1000_copper_link_setup_igp(hw); if (ret_val) goto out; if (hw->mac.autoneg) { if (dev_spec->ffe_config == e1000_ffe_config_active) dev_spec->ffe_config = e1000_ffe_config_enabled; } /* Configure activity LED after Phy reset */ ledctl = E1000_READ_REG(hw, E1000_LEDCTL); ledctl &= IGP_ACTIVITY_LED_MASK; ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); ret_val = e1000_setup_copper_link_generic(hw); out: return ret_val; } /** * e1000_check_for_link_82541 - Check/Store link connection * @hw: pointer to the HW structure * * This checks the link condition of the adapter and stores the * results in the hw->mac structure. **/ STATIC s32 e1000_check_for_link_82541(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; bool link; DEBUGFUNC("e1000_check_for_link_82541"); /* * We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) { ret_val = E1000_SUCCESS; goto out; } /* * First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) goto out; if (!link) { ret_val = e1000_config_dsp_after_link_change_82541(hw, false); goto out; /* No link detected */ } mac->get_link_status = false; /* * Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); /* * If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) { ret_val = -E1000_ERR_CONFIG; goto out; } ret_val = e1000_config_dsp_after_link_change_82541(hw, true); /* * Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); /* * Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); out: return ret_val; } /** * e1000_config_dsp_after_link_change_82541 - Config DSP after link * @hw: pointer to the HW structure * @link_up: boolean flag for link up status * * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS * at any other case. * * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a * gigabit link is achieved to improve link quality. **/ STATIC s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw, bool link_up) { struct e1000_phy_info *phy = &hw->phy; struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; u32 idle_errs = 0; u16 phy_data, phy_saved_data, speed, duplex, i; u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { IGP01E1000_PHY_AGC_PARAM_A, IGP01E1000_PHY_AGC_PARAM_B, IGP01E1000_PHY_AGC_PARAM_C, IGP01E1000_PHY_AGC_PARAM_D}; DEBUGFUNC("e1000_config_dsp_after_link_change_82541"); if (link_up) { ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); goto out; } if (speed != SPEED_1000) { ret_val = E1000_SUCCESS; goto out; } ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; if ((dev_spec->dsp_config == e1000_dsp_config_enabled) && phy->min_cable_length >= 50) { for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = phy->ops.read_reg(hw, dsp_reg_array[i], &phy_data); if (ret_val) goto out; phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; ret_val = phy->ops.write_reg(hw, dsp_reg_array[i], phy_data); if (ret_val) goto out; } dev_spec->dsp_config = e1000_dsp_config_activated; } if ((dev_spec->ffe_config != e1000_ffe_config_enabled) || (phy->min_cable_length >= 50)) { ret_val = E1000_SUCCESS; goto out; } /* clear previous idle error counts */ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) goto out; for (i = 0; i < ffe_idle_err_timeout; i++) { usec_delay(1000); ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) goto out; idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { dev_spec->ffe_config = e1000_ffe_config_active; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE, IGP01E1000_PHY_DSP_FFE_CM_CP); if (ret_val) goto out; break; } if (idle_errs) ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; } } else { if (dev_spec->dsp_config == e1000_dsp_config_activated) { /* * Save off the current value of register 0x2F5B * to be restored at the end of the routines. */ ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data); if (ret_val) goto out; /* Disable the PHY transmitter */ ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); if (ret_val) goto out; msec_delay_irq(20); ret_val = phy->ops.write_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIG); if (ret_val) goto out; for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = phy->ops.read_reg(hw, dsp_reg_array[i], &phy_data); if (ret_val) goto out; phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; ret_val = phy->ops.write_reg(hw, dsp_reg_array[i], phy_data); if (ret_val) goto out; } ret_val = phy->ops.write_reg(hw, 0x0000, IGP01E1000_IEEE_RESTART_AUTONEG); if (ret_val) goto out; msec_delay_irq(20); /* Now enable the transmitter */ ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data); if (ret_val) goto out; dev_spec->dsp_config = e1000_dsp_config_enabled; } if (dev_spec->ffe_config != e1000_ffe_config_active) { ret_val = E1000_SUCCESS; goto out; } /* * Save off the current value of register 0x2F5B * to be restored at the end of the routines. */ ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data); if (ret_val) goto out; /* Disable the PHY transmitter */ ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003); if (ret_val) goto out; msec_delay_irq(20); ret_val = phy->ops.write_reg(hw, 0x0000, IGP01E1000_IEEE_FORCE_GIG); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE, IGP01E1000_PHY_DSP_FFE_DEFAULT); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, 0x0000, IGP01E1000_IEEE_RESTART_AUTONEG); if (ret_val) goto out; msec_delay_irq(20); /* Now enable the transmitter */ ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data); if (ret_val) goto out; dev_spec->ffe_config = e1000_ffe_config_enabled; } out: return ret_val; } /** * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY * @hw: pointer to the HW structure * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the * cable. By reading the AGC registers, which represent the * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ STATIC s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 i, data; u16 cur_agc_value, agc_value = 0; u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A, IGP01E1000_PHY_AGC_B, IGP01E1000_PHY_AGC_C, IGP01E1000_PHY_AGC_D}; DEBUGFUNC("e1000_get_cable_length_igp_82541"); /* Read the AGC registers for all channels */ for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data); if (ret_val) goto out; cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT; /* Bounds checking */ if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || (cur_agc_value == 0)) { ret_val = -E1000_ERR_PHY; goto out; } agc_value += cur_agc_value; if (min_agc_value > cur_agc_value) min_agc_value = cur_agc_value; } /* Remove the minimal AGC result for length < 50m */ if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) { agc_value -= min_agc_value; /* Average the three remaining channels for the length. */ agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); } else { /* Average the channels for the length. */ agc_value /= IGP01E1000_PHY_CHANNEL_NUM; } phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] > IGP01E1000_AGC_RANGE) ? (e1000_igp_cable_length_table[agc_value] - IGP01E1000_AGC_RANGE) : 0; phy->max_cable_length = e1000_igp_cable_length_table[agc_value] + IGP01E1000_AGC_RANGE; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; out: return ret_val; } /** * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ STATIC s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_set_d3_lplu_state_82541"); switch (hw->mac.type) { case e1000_82541_rev_2: case e1000_82547_rev_2: break; default: ret_val = e1000_set_d3_lplu_state_generic(hw, active); goto out; break; } ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data); if (ret_val) goto out; if (!active) { data &= ~IGP01E1000_GMII_FLEX_SPD; ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); if (ret_val) goto out; /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP01E1000_GMII_FLEX_SPD; ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } out: return ret_val; } /** * e1000_setup_led_82541 - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. **/ STATIC s32 e1000_setup_led_82541(struct e1000_hw *hw) { struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; DEBUGFUNC("e1000_setup_led_82541"); ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO, &dev_spec->spd_default); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO, (u16)(dev_spec->spd_default & ~IGP01E1000_GMII_SPD)); if (ret_val) goto out; E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); out: return ret_val; } /** * e1000_cleanup_led_82541 - Set LED config to default operation * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration * to the default value, saved from the EEPROM. **/ STATIC s32 e1000_cleanup_led_82541(struct e1000_hw *hw) { struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; s32 ret_val; DEBUGFUNC("e1000_cleanup_led_82541"); ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO, dev_spec->spd_default); if (ret_val) goto out; E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); out: return ret_val; } /** * e1000_phy_init_script_82541 - Initialize GbE PHY * @hw: pointer to the HW structure * * Initializes the IGP PHY. **/ STATIC s32 e1000_phy_init_script_82541(struct e1000_hw *hw) { struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; u32 ret_val; u16 phy_saved_data; DEBUGFUNC("e1000_phy_init_script_82541"); if (!dev_spec->phy_init_script) { ret_val = E1000_SUCCESS; goto out; } /* Delay after phy reset to enable NVM configuration to load */ msec_delay(20); /* * Save off the current value of register 0x2F5B to be restored at * the end of this routine. */ ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data); /* Disabled the PHY transmitter */ hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003); msec_delay(20); hw->phy.ops.write_reg(hw, 0x0000, 0x0140); msec_delay(5); switch (hw->mac.type) { case e1000_82541: case e1000_82547: hw->phy.ops.write_reg(hw, 0x1F95, 0x0001); hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21); hw->phy.ops.write_reg(hw, 0x1F79, 0x0018); hw->phy.ops.write_reg(hw, 0x1F30, 0x1600); hw->phy.ops.write_reg(hw, 0x1F31, 0x0014); hw->phy.ops.write_reg(hw, 0x1F32, 0x161C); hw->phy.ops.write_reg(hw, 0x1F94, 0x0003); hw->phy.ops.write_reg(hw, 0x1F96, 0x003F); hw->phy.ops.write_reg(hw, 0x2010, 0x0008); break; case e1000_82541_rev_2: case e1000_82547_rev_2: hw->phy.ops.write_reg(hw, 0x1F73, 0x0099); break; default: break; } hw->phy.ops.write_reg(hw, 0x0000, 0x3300); msec_delay(20); /* Now enable the transmitter */ hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data); if (hw->mac.type == e1000_82547) { u16 fused, fine, coarse; /* Move to analog registers page */ hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused); fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10; fine -= IGP01E1000_ANALOG_FUSE_FINE_1; } else if (coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) fine -= IGP01E1000_ANALOG_FUSE_FINE_10; fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); hw->phy.ops.write_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); hw->phy.ops.write_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); } } out: return ret_val; } /** * e1000_init_script_state_82541 - Enable/Disable PHY init script * @hw: pointer to the HW structure * @state: boolean value used to enable/disable PHY init script * * Allows the driver to enable/disable the PHY init script, if the PHY is an * IGP PHY. **/ void e1000_init_script_state_82541(struct e1000_hw *hw, bool state) { struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; DEBUGFUNC("e1000_init_script_state_82541"); if (hw->phy.type != e1000_phy_igp) { DEBUGOUT("Initialization script not necessary.\n"); goto out; } dev_spec->phy_init_script = state; out: return; } /** * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_82541(struct e1000_hw *hw) { /* If the management interface is not enabled, then power down */ if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN)) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82541"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); } ================================================ FILE: drivers/net/e1000/base/e1000_82541.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_82541_H_ #define _E1000_82541_H_ #define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1) #define IGP01E1000_PHY_CHANNEL_NUM 4 #define IGP01E1000_PHY_AGC_A 0x1172 #define IGP01E1000_PHY_AGC_B 0x1272 #define IGP01E1000_PHY_AGC_C 0x1472 #define IGP01E1000_PHY_AGC_D 0x1872 #define IGP01E1000_PHY_AGC_PARAM_A 0x1171 #define IGP01E1000_PHY_AGC_PARAM_B 0x1271 #define IGP01E1000_PHY_AGC_PARAM_C 0x1471 #define IGP01E1000_PHY_AGC_PARAM_D 0x1871 #define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 #define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 #define IGP01E1000_PHY_DSP_RESET 0x1F33 #define IGP01E1000_PHY_DSP_FFE 0x1F35 #define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 #define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A #define IGP01E1000_IEEE_FORCE_GIG 0x0140 #define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 #define IGP01E1000_AGC_LENGTH_SHIFT 7 #define IGP01E1000_AGC_RANGE 10 #define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 #define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 #define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 #define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 #define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC #define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE #define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 #define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 #define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 #define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 #define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 #define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 #define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 #define IGP01E1000_MSE_CHANNEL_D 0x000F #define IGP01E1000_MSE_CHANNEL_C 0x00F0 #define IGP01E1000_MSE_CHANNEL_B 0x0F00 #define IGP01E1000_MSE_CHANNEL_A 0xF000 void e1000_init_script_state_82541(struct e1000_hw *hw, bool state); #endif ================================================ FILE: drivers/net/e1000/base/e1000_82542.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* * 82542 Gigabit Ethernet Controller */ #include "e1000_api.h" STATIC s32 e1000_init_phy_params_82542(struct e1000_hw *hw); STATIC s32 e1000_init_nvm_params_82542(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_82542(struct e1000_hw *hw); STATIC s32 e1000_get_bus_info_82542(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_82542(struct e1000_hw *hw); STATIC s32 e1000_init_hw_82542(struct e1000_hw *hw); STATIC s32 e1000_setup_link_82542(struct e1000_hw *hw); STATIC s32 e1000_led_on_82542(struct e1000_hw *hw); STATIC s32 e1000_led_off_82542(struct e1000_hw *hw); STATIC void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index); STATIC void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw); STATIC s32 e1000_read_mac_addr_82542(struct e1000_hw *hw); /** * e1000_init_phy_params_82542 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82542(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_phy_params_82542"); phy->type = e1000_phy_none; return ret_val; } /** * e1000_init_nvm_params_82542 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_82542(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_params_82542"); nvm->address_bits = 6; nvm->delay_usec = 50; nvm->opcode_bits = 3; nvm->type = e1000_nvm_eeprom_microwire; nvm->word_size = 64; /* Function Pointers */ nvm->ops.read = e1000_read_nvm_microwire; nvm->ops.release = e1000_stop_nvm; nvm->ops.write = e1000_write_nvm_microwire; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; return E1000_SUCCESS; } /** * e1000_init_mac_params_82542 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_params_82542"); /* Set media type */ hw->phy.media_type = e1000_media_type_fiber; /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_82542; /* function id */ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82542; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82542; /* link setup */ mac->ops.setup_link = e1000_setup_link_82542; /* phy/fiber/serdes setup */ mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic; /* check for link */ mac->ops.check_for_link = e1000_check_for_fiber_link_generic; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82542; /* set RAR */ mac->ops.rar_set = e1000_rar_set_82542; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_82542; mac->ops.led_off = e1000_led_off_82542; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542; /* link info */ mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic; return E1000_SUCCESS; } /** * e1000_init_function_pointers_82542 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82542(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82542"); hw->mac.ops.init_params = e1000_init_mac_params_82542; hw->nvm.ops.init_params = e1000_init_nvm_params_82542; hw->phy.ops.init_params = e1000_init_phy_params_82542; } /** * e1000_get_bus_info_82542 - Obtain bus information for adapter * @hw: pointer to the HW structure * * This will obtain information about the HW bus for which the * adapter is attached and stores it in the hw structure. **/ STATIC s32 e1000_get_bus_info_82542(struct e1000_hw *hw) { DEBUGFUNC("e1000_get_bus_info_82542"); hw->bus.type = e1000_bus_type_pci; hw->bus.speed = e1000_bus_speed_unknown; hw->bus.width = e1000_bus_width_unknown; return E1000_SUCCESS; } /** * e1000_reset_hw_82542 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82542(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; s32 ret_val = E1000_SUCCESS; u32 ctrl; DEBUGFUNC("e1000_reset_hw_82542"); if (hw->revision_id == E1000_REVISION_2) { DEBUGOUT("Disabling MWI on 82542 rev 2\n"); e1000_pci_clear_mwi(hw); } DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); /* * Delay to allow any outstanding PCI transactions to complete before * resetting the device */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82542/82543 MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); hw->nvm.ops.reload(hw); msec_delay(2); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); if (hw->revision_id == E1000_REVISION_2) { if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } return ret_val; } /** * e1000_init_hw_82542 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ STATIC s32 e1000_init_hw_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82542 *dev_spec = &hw->dev_spec._82542; s32 ret_val = E1000_SUCCESS; u32 ctrl; u16 i; DEBUGFUNC("e1000_init_hw_82542"); /* Disabling VLAN filtering */ E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ if (hw->revision_id == E1000_REVISION_2) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); e1000_pci_clear_mwi(hw); E1000_WRITE_REG(hw, E1000_RCTL, E1000_RCTL_RST); E1000_WRITE_FLUSH(hw); msec_delay(5); } /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ if (hw->revision_id == E1000_REVISION_2) { E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_FLUSH(hw); msec_delay(1); if (hw->bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* * Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it * gives equal priority to transmits and receives. */ if (dev_spec->dma_fairness) { ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); } /* Setup link and flow control */ ret_val = e1000_setup_link_82542(hw); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82542(hw); return ret_val; } /** * e1000_setup_link_82542 - Setup flow control and link settings * @hw: pointer to the HW structure * * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ STATIC s32 e1000_setup_link_82542(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; DEBUGFUNC("e1000_setup_link_82542"); ret_val = e1000_set_default_fc_generic(hw); if (ret_val) goto out; hw->fc.requested_mode &= ~e1000_fc_tx_pause; if (mac->report_tx_early) hw->fc.requested_mode &= ~e1000_fc_rx_pause; /* * Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); /* Call the necessary subroutine to configure the link. */ ret_val = mac->ops.setup_physical_interface(hw); if (ret_val) goto out; /* * Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. */ DEBUGOUT("Initializing Flow Control address, type and timer regs\n"); E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); ret_val = e1000_set_fc_watermarks_generic(hw); out: return ret_val; } /** * e1000_led_on_82542 - Turn on SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED on. **/ STATIC s32 e1000_led_on_82542(struct e1000_hw *hw) { u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_on_82542"); ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_led_off_82542 - Turn off SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED off. **/ STATIC s32 e1000_led_off_82542(struct e1000_hw *hw) { u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_off_82542"); ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_rar_set_82542 - Set receive address register * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index: receive address array register * * Sets the receive address array register at index to the address passed * in by addr. **/ STATIC void e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; DEBUGFUNC("e1000_rar_set_82542"); /* * HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) rar_high |= E1000_RAH_AV; E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low); E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high); } /** * e1000_translate_register_82542 - Translate the proper register offset * @reg: e1000 register to be read * * Registers in 82542 are located in different offsets than other adapters * even though they function in the same manner. This function takes in * the name of the register to read and returns the correct offset for * 82542 silicon. **/ u32 e1000_translate_register_82542(u32 reg) { /* * Some of the 82542 registers are located at different * offsets than they are in newer adapters. * Despite the difference in location, the registers * function in the same manner. */ switch (reg) { case E1000_RA: reg = 0x00040; break; case E1000_RDTR: reg = 0x00108; break; case E1000_RDBAL(0): reg = 0x00110; break; case E1000_RDBAH(0): reg = 0x00114; break; case E1000_RDLEN(0): reg = 0x00118; break; case E1000_RDH(0): reg = 0x00120; break; case E1000_RDT(0): reg = 0x00128; break; case E1000_RDBAL(1): reg = 0x00138; break; case E1000_RDBAH(1): reg = 0x0013C; break; case E1000_RDLEN(1): reg = 0x00140; break; case E1000_RDH(1): reg = 0x00148; break; case E1000_RDT(1): reg = 0x00150; break; case E1000_FCRTH: reg = 0x00160; break; case E1000_FCRTL: reg = 0x00168; break; case E1000_MTA: reg = 0x00200; break; case E1000_TDBAL(0): reg = 0x00420; break; case E1000_TDBAH(0): reg = 0x00424; break; case E1000_TDLEN(0): reg = 0x00428; break; case E1000_TDH(0): reg = 0x00430; break; case E1000_TDT(0): reg = 0x00438; break; case E1000_TIDV: reg = 0x00440; break; case E1000_VFTA: reg = 0x00600; break; case E1000_TDFH: reg = 0x08010; break; case E1000_TDFT: reg = 0x08018; break; default: break; } return reg; } /** * e1000_clear_hw_cntrs_82542 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82542"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); } /** * e1000_read_mac_addr_82542 - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. **/ s32 e1000_read_mac_addr_82542(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 offset, nvm_data, i; DEBUGFUNC("e1000_read_mac_addr"); for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = i >> 1; ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); } for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; out: return ret_val; } ================================================ FILE: drivers/net/e1000/base/e1000_82543.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* * 82543GC Gigabit Ethernet Controller (Fiber) * 82543GC Gigabit Ethernet Controller (Copper) * 82544EI Gigabit Ethernet Controller (Copper) * 82544EI Gigabit Ethernet Controller (Fiber) * 82544GC Gigabit Ethernet Controller (Copper) * 82544GC Gigabit Ethernet Controller (LOM) */ #include "e1000_api.h" STATIC s32 e1000_init_phy_params_82543(struct e1000_hw *hw); STATIC s32 e1000_init_nvm_params_82543(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_82543(struct e1000_hw *hw); STATIC s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data); STATIC s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw); STATIC s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_82543(struct e1000_hw *hw); STATIC s32 e1000_init_hw_82543(struct e1000_hw *hw); STATIC s32 e1000_setup_link_82543(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_82543(struct e1000_hw *hw); STATIC s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw); STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw); STATIC s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw); STATIC s32 e1000_led_on_82543(struct e1000_hw *hw); STATIC s32 e1000_led_off_82543(struct e1000_hw *hw); STATIC void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value); STATIC void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw); STATIC s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw); STATIC bool e1000_init_phy_disabled_82543(struct e1000_hw *hw); STATIC void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); STATIC s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw); STATIC void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); STATIC u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw); STATIC void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, u16 count); STATIC bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw); STATIC void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state); /** * e1000_init_phy_params_82543 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82543(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_init_phy_params_82543"); if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } else { phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 10000; phy->type = e1000_phy_m88; /* Function Pointers */ phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.read_reg = (hw->mac.type == e1000_82543) ? e1000_read_phy_reg_82543 : e1000_read_phy_reg_m88; phy->ops.reset = (hw->mac.type == e1000_82543) ? e1000_phy_hw_reset_82543 : e1000_phy_hw_reset_generic; phy->ops.write_reg = (hw->mac.type == e1000_82543) ? e1000_write_phy_reg_82543 : e1000_write_phy_reg_m88; phy->ops.get_info = e1000_get_phy_info_m88; /* * The external PHY of the 82543 can be in a funky state. * Resetting helps us read the PHY registers for acquiring * the PHY ID. */ if (!e1000_init_phy_disabled_82543(hw)) { ret_val = phy->ops.reset(hw); if (ret_val) { DEBUGOUT("Resetting PHY during init failed.\n"); goto out; } msec_delay(20); } ret_val = e1000_get_phy_id(hw); if (ret_val) goto out; /* Verify phy id */ switch (hw->mac.type) { case e1000_82543: if (phy->id != M88E1000_E_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } break; case e1000_82544: if (phy->id != M88E1000_I_PHY_ID) { ret_val = -E1000_ERR_PHY; goto out; } break; default: ret_val = -E1000_ERR_PHY; goto out; break; } out: return ret_val; } /** * e1000_init_nvm_params_82543 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_82543(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_params_82543"); nvm->type = e1000_nvm_eeprom_microwire; nvm->word_size = 64; nvm->delay_usec = 50; nvm->address_bits = 6; nvm->opcode_bits = 3; /* Function Pointers */ nvm->ops.read = e1000_read_nvm_microwire; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_generic; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.write = e1000_write_nvm_microwire; return E1000_SUCCESS; } /** * e1000_init_mac_params_82543 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_params_82543"); /* Set media type */ switch (hw->device_id) { case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82544EI_FIBER: hw->phy.media_type = e1000_media_type_fiber; break; default: hw->phy.media_type = e1000_media_type_copper; break; } /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; /* function id */ mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82543; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82543; /* link setup */ mac->ops.setup_link = e1000_setup_link_82543; /* physical interface setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82543 : e1000_setup_fiber_link_82543; /* check for link */ mac->ops.check_for_link = (hw->phy.media_type == e1000_media_type_copper) ? e1000_check_for_copper_link_82543 : e1000_check_for_fiber_link_82543; /* link info */ mac->ops.get_link_up_info = (hw->phy.media_type == e1000_media_type_copper) ? e1000_get_speed_and_duplex_copper_generic : e1000_get_speed_and_duplex_fiber_serdes_generic; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_82543; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_82543; mac->ops.led_off = e1000_led_off_82543; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543; /* Set tbi compatibility */ if ((hw->mac.type != e1000_82543) || (hw->phy.media_type == e1000_media_type_fiber)) e1000_set_tbi_compatibility_82543(hw, false); return E1000_SUCCESS; } /** * e1000_init_function_pointers_82543 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82543(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82543"); hw->mac.ops.init_params = e1000_init_mac_params_82543; hw->nvm.ops.init_params = e1000_init_nvm_params_82543; hw->phy.ops.init_params = e1000_init_phy_params_82543; } /** * e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status * @hw: pointer to the HW structure * * Returns the current status of 10-bit Interface (TBI) compatibility * (enabled/disabled). **/ STATIC bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw) { struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool state = false; DEBUGFUNC("e1000_tbi_compatibility_enabled_82543"); if (hw->mac.type != e1000_82543) { DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); goto out; } state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED); out: return state; } /** * e1000_set_tbi_compatibility_82543 - Set TBI compatibility * @hw: pointer to the HW structure * @state: enable/disable TBI compatibility * * Enables or disabled 10-bit Interface (TBI) compatibility. **/ void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state) { struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; DEBUGFUNC("e1000_set_tbi_compatibility_82543"); if (hw->mac.type != e1000_82543) { DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); goto out; } if (state) dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED; else dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED; out: return; } /** * e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status * @hw: pointer to the HW structure * * Returns the current status of 10-bit Interface (TBI) store bad packet (SBP) * (enabled/disabled). **/ bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw) { struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool state = false; DEBUGFUNC("e1000_tbi_sbp_enabled_82543"); if (hw->mac.type != e1000_82543) { DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); goto out; } state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED); out: return state; } /** * e1000_set_tbi_sbp_82543 - Set TBI SBP * @hw: pointer to the HW structure * @state: enable/disable TBI store bad packet * * Enables or disabled 10-bit Interface (TBI) store bad packet (SBP). **/ STATIC void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state) { struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; DEBUGFUNC("e1000_set_tbi_sbp_82543"); if (state && e1000_tbi_compatibility_enabled_82543(hw)) dev_spec->tbi_compatibility |= TBI_SBP_ENABLED; else dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED; return; } /** * e1000_init_phy_disabled_82543 - Returns init PHY status * @hw: pointer to the HW structure * * Returns the current status of whether PHY initialization is disabled. * True if PHY initialization is disabled else false. **/ STATIC bool e1000_init_phy_disabled_82543(struct e1000_hw *hw) { struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; bool ret_val; DEBUGFUNC("e1000_init_phy_disabled_82543"); if (hw->mac.type != e1000_82543) { ret_val = false; goto out; } ret_val = dev_spec->init_phy_disabled; out: return ret_val; } /** * e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled * @hw: pointer to the HW structure * @stats: Struct containing statistic register values * @frame_len: The length of the frame in question * @mac_addr: The Ethernet destination address of the frame in question * @max_frame_size: The maximum frame size * * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT **/ void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 *mac_addr, u32 max_frame_size) { if (!(e1000_tbi_sbp_enabled_82543(hw))) goto out; /* First adjust the frame length. */ frame_len--; /* * We need to adjust the statistics counters, since the hardware * counters overcount this packet as a CRC error and undercount * the packet as a good packet */ /* This packet should not be counted as a CRC error. */ stats->crcerrs--; /* This packet does count as a Good Packet Received. */ stats->gprc++; /* Adjust the Good Octets received counters */ stats->gorc += frame_len; /* * Is this a broadcast or multicast? Check broadcast first, * since the test for a multicast frame will test positive on * a broadcast frame. */ if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff)) /* Broadcast packet */ stats->bprc++; else if (*mac_addr & 0x01) /* Multicast packet */ stats->mprc++; /* * In this case, the hardware has over counted the number of * oversize frames. */ if ((frame_len == max_frame_size) && (stats->roc > 0)) stats->roc--; /* * Adjust the bin counters when the extra byte put the frame in the * wrong bin. Remember that the frame_len was adjusted above. */ if (frame_len == 64) { stats->prc64++; stats->prc127--; } else if (frame_len == 127) { stats->prc127++; stats->prc255--; } else if (frame_len == 255) { stats->prc255++; stats->prc511--; } else if (frame_len == 511) { stats->prc511++; stats->prc1023--; } else if (frame_len == 1023) { stats->prc1023++; stats->prc1522--; } else if (frame_len == 1522) { stats->prc1522++; } out: return; } /** * e1000_read_phy_reg_82543 - Read PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY at offset and stores the information read to data. **/ STATIC s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data) { u32 mdic; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_phy_reg_82543"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); ret_val = -E1000_ERR_PARAM; goto out; } /* * We must first send a preamble through the MDIO pin to signal the * beginning of an MII instruction. This is done by sending 32 * consecutive "1" bits. */ e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); /* * Now combine the next few fields that are required for a read * operation. We use this method instead of calling the * e1000_shift_out_mdi_bits routine five different times. The format * of an MII read instruction consists of a shift out of 14 bits and * is defined as follows: * * followed by a shift in of 18 bits. This first two bits shifted in * are TurnAround bits used to avoid contention on the MDIO pin when a * READ operation is performed. These two bits are thrown away * followed by a shift in of 16 bits which contains the desired data. */ mdic = (offset | (hw->phy.addr << 5) | (PHY_OP_READ << 10) | (PHY_SOF << 12)); e1000_shift_out_mdi_bits_82543(hw, mdic, 14); /* * Now that we've shifted out the read command to the MII, we need to * "shift in" the 16-bit value (18 total bits) of the requested PHY * register address. */ *data = e1000_shift_in_mdi_bits_82543(hw); out: return ret_val; } /** * e1000_write_phy_reg_82543 - Write PHY register * @hw: pointer to the HW structure * @offset: register offset to be written * @data: pointer to the data to be written at offset * * Writes data to the PHY at offset. **/ STATIC s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data) { u32 mdic; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_phy_reg_82543"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); ret_val = -E1000_ERR_PARAM; goto out; } /* * We'll need to use the SW defined pins to shift the write command * out to the PHY. We first send a preamble to the PHY to signal the * beginning of the MII instruction. This is done by sending 32 * consecutive "1" bits. */ e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); /* * Now combine the remaining required fields that will indicate a * write operation. We use this method instead of calling the * e1000_shift_out_mdi_bits routine for each field in the command. The * format of a MII write instruction is as follows: * . */ mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) | (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); mdic <<= 16; mdic |= (u32)data; e1000_shift_out_mdi_bits_82543(hw, mdic, 32); out: return ret_val; } /** * e1000_raise_mdi_clk_82543 - Raise Management Data Input clock * @hw: pointer to the HW structure * @ctrl: pointer to the control register * * Raise the management data input clock by setting the MDC bit in the control * register. **/ STATIC void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) { /* * Raise the clock input to the Management Data Clock (by setting the * MDC bit), and then delay a sufficient amount of time. */ E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); usec_delay(10); } /** * e1000_lower_mdi_clk_82543 - Lower Management Data Input clock * @hw: pointer to the HW structure * @ctrl: pointer to the control register * * Lower the management data input clock by clearing the MDC bit in the * control register. **/ STATIC void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) { /* * Lower the clock input to the Management Data Clock (by clearing the * MDC bit), and then delay a sufficient amount of time. */ E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); usec_delay(10); } /** * e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY * @hw: pointer to the HW structure * @data: data to send to the PHY * @count: number of bits to shift out * * We need to shift 'count' bits out to the PHY. So, the value in the * "data" parameter will be shifted out to the PHY one bit at a time. * In order to do this, "data" must be broken down into bits. **/ STATIC void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, u16 count) { u32 ctrl, mask; /* * We need to shift "count" number of bits out to the PHY. So, the * value in the "data" parameter will be shifted out to the PHY one * bit at a time. In order to do this, "data" must be broken down * into bits. */ mask = 0x01; mask <<= (count - 1); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); while (mask) { /* * A "1" is shifted out to the PHY by setting the MDIO bit to * "1" and then raising and lowering the Management Data Clock. * A "0" is shifted out to the PHY by setting the MDIO bit to * "0" and then raising and lowering the clock. */ if (data & mask) ctrl |= E1000_CTRL_MDIO; else ctrl &= ~E1000_CTRL_MDIO; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); usec_delay(10); e1000_raise_mdi_clk_82543(hw, &ctrl); e1000_lower_mdi_clk_82543(hw, &ctrl); mask >>= 1; } } /** * e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY * @hw: pointer to the HW structure * * In order to read a register from the PHY, we need to shift 18 bits * in from the PHY. Bits are "shifted in" by raising the clock input to * the PHY (setting the MDC bit), and then reading the value of the data out * MDIO bit. **/ STATIC u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw) { u32 ctrl; u16 data = 0; u8 i; /* * In order to read a register from the PHY, we need to shift in a * total of 18 bits from the PHY. The first two bit (turnaround) * times are used to avoid contention on the MDIO pin when a read * operation is performed. These two bits are ignored by us and * thrown away. Bits are "shifted in" by raising the input to the * Management Data Clock (setting the MDC bit) and then reading the * value of the MDIO bit. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); /* * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as * input. */ ctrl &= ~E1000_CTRL_MDIO_DIR; ctrl &= ~E1000_CTRL_MDIO; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); /* * Raise and lower the clock before reading in the data. This accounts * for the turnaround bits. The first clock occurred when we clocked * out the last bit of the Register Address. */ e1000_raise_mdi_clk_82543(hw, &ctrl); e1000_lower_mdi_clk_82543(hw, &ctrl); for (data = 0, i = 0; i < 16; i++) { data <<= 1; e1000_raise_mdi_clk_82543(hw, &ctrl); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Check to see if we shifted in a "1". */ if (ctrl & E1000_CTRL_MDIO) data |= 1; e1000_lower_mdi_clk_82543(hw, &ctrl); } e1000_raise_mdi_clk_82543(hw, &ctrl); e1000_lower_mdi_clk_82543(hw, &ctrl); return data; } /** * e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY * @hw: pointer to the HW structure * * Calls the function to force speed and duplex for the m88 PHY, and * if the PHY is not auto-negotiating and the speed is forced to 10Mbit, * then call the function for polarity reversal workaround. **/ STATIC s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_phy_force_speed_duplex_82543"); ret_val = e1000_phy_force_speed_duplex_m88(hw); if (ret_val) goto out; if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)) ret_val = e1000_polarity_reversal_workaround_82543(hw); out: return ret_val; } /** * e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal * @hw: pointer to the HW structure * * When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity * inadvertently. To workaround the issue, we disable the transmitter on * the PHY until we have established the link partner's link parameters. **/ STATIC s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 mii_status_reg; u16 i; bool link; if (!(hw->phy.ops.write_reg)) goto out; /* Polarity reversal workaround for forced 10F/10H links. */ /* Disable the transmitter on the PHY */ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); if (ret_val) goto out; /* * This loop will early-out if the NO link condition has been met. * In other words, DO NOT use e1000_phy_has_link_generic() here. */ for (i = PHY_FORCE_TIME; i > 0; i--) { /* * Read the MII Status Register and wait for Link Status bit * to be clear. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) goto out; if (!(mii_status_reg & ~MII_SR_LINK_STATUS)) break; msec_delay_irq(100); } /* Recommended delay time after link has been lost */ msec_delay_irq(1000); /* Now we will re-enable the transmitter on the PHY */ ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); if (ret_val) goto out; msec_delay_irq(50); ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); if (ret_val) goto out; msec_delay_irq(50); ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); if (ret_val) goto out; msec_delay_irq(50); ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); if (ret_val) goto out; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); if (ret_val) goto out; /* * Read the MII Status Register and wait for Link Status bit * to be set. */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link); if (ret_val) goto out; out: return ret_val; } /** * e1000_phy_hw_reset_82543 - PHY hardware reset * @hw: pointer to the HW structure * * Sets the PHY_RESET_DIR bit in the extended device control register * to put the PHY into a reset and waits for completion. Once the reset * has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out * of reset. **/ STATIC s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) { u32 ctrl_ext; s32 ret_val; DEBUGFUNC("e1000_phy_hw_reset_82543"); /* * Read the Extended Device Control Register, assert the PHY_RESET_DIR * bit to put the PHY into reset... */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); msec_delay(10); /* ...then take it out of reset. */ ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); usec_delay(150); if (!(hw->phy.ops.get_cfg_done)) return E1000_SUCCESS; ret_val = hw->phy.ops.get_cfg_done(hw); return ret_val; } /** * e1000_reset_hw_82543 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_reset_hw_82543"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); e1000_set_tbi_sbp_82543(hw, false); /* * Delay to allow any outstanding PCI transactions to complete before * resetting the device */ msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n"); if (hw->mac.type == e1000_82543) { E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); } else { /* * The 82544 can't ACK the 64-bit write when issuing the * reset, so use IO-mapping as a workaround. */ E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); } /* * After MAC reset, force reload of NVM to restore power-on * settings to device. */ hw->nvm.ops.reload(hw); msec_delay(2); /* Masking off and clearing any pending interrupts */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); return ret_val; } /** * e1000_init_hw_82543 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ STATIC s32 e1000_init_hw_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; u32 ctrl; s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_82543"); /* Disabling VLAN filtering */ E1000_WRITE_REG(hw, E1000_VET, 0); mac->ops.clear_vfta(hw); /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) { E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); E1000_WRITE_FLUSH(hw); } /* * Set the PCI priority bit correctly in the CTRL register. This * determines if the adapter gives priority to receives, or if it * gives equal priority to transmits and receives. */ if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) { ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); } e1000_pcix_mmrbc_workaround_generic(hw); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82543(hw); return ret_val; } /** * e1000_setup_link_82543 - Setup flow control and link settings * @hw: pointer to the HW structure * * Read the EEPROM to determine the initial polarity value and write the * extended device control register with the information before calling * the generic setup link function, which does the following: * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ STATIC s32 e1000_setup_link_82543(struct e1000_hw *hw) { u32 ctrl_ext; s32 ret_val; u16 data; DEBUGFUNC("e1000_setup_link_82543"); /* * Take the 4 bits from NVM word 0xF that determine the initial * polarity value for the SW controlled pins, and setup the * Extended Device Control reg with that info. * This is needed because one of the SW controlled pins is used for * signal detection. So this should be done before phy setup. */ if (hw->mac.type == e1000_82543) { ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); ret_val = -E1000_ERR_NVM; goto out; } ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) << NVM_SWDPIO_EXT_SHIFT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } ret_val = e1000_setup_link_generic(hw); out: return ret_val; } /** * e1000_setup_copper_link_82543 - Configure copper link settings * @hw: pointer to the HW structure * * Configures the link for auto-neg or forced speed and duplex. Then we check * for link, once link is established calls to configure collision distance * and flow control are called. **/ STATIC s32 e1000_setup_copper_link_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; bool link; DEBUGFUNC("e1000_setup_copper_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU; /* * With 82543, we need to force speed and duplex on the MAC * equal to what the PHY speed and duplex configuration is. * In addition, we need to perform a hardware reset on the * PHY to take it out of reset. */ if (hw->mac.type == e1000_82543) { ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = hw->phy.ops.reset(hw); if (ret_val) goto out; } else { ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); } /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */ ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) goto out; if (hw->mac.autoneg) { /* * Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) goto out; } else { /* * PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); ret_val = e1000_phy_force_speed_duplex_82543(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); goto out; } } /* * Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, &link); if (ret_val) goto out; if (link) { DEBUGOUT("Valid link established!!!\n"); /* Config the MAC and PHY after link is up */ if (hw->mac.type == e1000_82544) { hw->mac.ops.config_collision_dist(hw); } else { ret_val = e1000_config_mac_to_phy_82543(hw); if (ret_val) goto out; } ret_val = e1000_config_fc_after_link_up_generic(hw); } else { DEBUGOUT("Unable to establish link!!!\n"); } out: return ret_val; } /** * e1000_setup_fiber_link_82543 - Setup link for fiber * @hw: pointer to the HW structure * * Configures collision distance and flow control for fiber links. Upon * successful setup, poll for link. **/ STATIC s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_fiber_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Take the link out of reset */ ctrl &= ~E1000_CTRL_LRST; hw->mac.ops.config_collision_dist(hw); ret_val = e1000_commit_fc_settings_generic(hw); if (ret_val) goto out; DEBUGOUT("Auto-negotiation enabled\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); msec_delay(1); /* * For these adapters, the SW definable pin 1 is cleared when the * optics detect a signal. If we have a signal, then poll for a * "Link-Up" indication. */ if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) ret_val = e1000_poll_fiber_serdes_link_generic(hw); else DEBUGOUT("No signal detected\n"); out: return ret_val; } /** * e1000_check_for_copper_link_82543 - Check for link (Copper) * @hw: pointer to the HW structure * * Checks the phy for link, if link exists, do the following: * - check for downshift * - do polarity workaround (if necessary) * - configure collision distance * - configure flow control after link up * - configure tbi compatibility **/ STATIC s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 icr, rctl; s32 ret_val; u16 speed, duplex; bool link; DEBUGFUNC("e1000_check_for_copper_link_82543"); if (!mac->get_link_status) { ret_val = E1000_SUCCESS; goto out; } ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) goto out; if (!link) goto out; /* No link detected */ mac->get_link_status = false; e1000_check_downshift_generic(hw); /* * If we are forcing speed/duplex, then we can return since * we have already determined whether we have link or not. */ if (!mac->autoneg) { /* * If speed and duplex are forced to 10H or 10F, then we will * implement the polarity reversal workaround. We disable * interrupts first, and upon returning, place the devices * interrupt state to its previous value except for the link * status change interrupt which will happened due to the * execution of this workaround. */ if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) { E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); ret_val = e1000_polarity_reversal_workaround_82543(hw); icr = E1000_READ_REG(hw, E1000_ICR); E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC)); E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); } ret_val = -E1000_ERR_CONFIG; goto out; } /* * We have a M88E1000 PHY and Auto-Neg is enabled. If we * have Si on board that is 82544 or newer, Auto * Speed Detection takes care of MAC speed/duplex * configuration. So we only need to configure Collision * Distance in the MAC. Otherwise, we need to force * speed/duplex on the MAC to the current PHY speed/duplex * settings. */ if (mac->type == e1000_82544) hw->mac.ops.config_collision_dist(hw); else { ret_val = e1000_config_mac_to_phy_82543(hw); if (ret_val) { DEBUGOUT("Error configuring MAC to PHY settings\n"); goto out; } } /* * Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); /* * At this point we know that we are on copper and we have * auto-negotiated link. These are conditions for checking the link * partner capability register. We use the link speed to determine if * TBI compatibility needs to be turned on or off. If the link is not * at gigabit speed, then TBI compatibility is not needed. If we are * at gigabit speed, we turn on TBI compatibility. */ if (e1000_tbi_compatibility_enabled_82543(hw)) { ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); return ret_val; } if (speed != SPEED_1000) { /* * If link speed is not set to gigabit speed, * we do not need to enable TBI compatibility. */ if (e1000_tbi_sbp_enabled_82543(hw)) { /* * If we previously were in the mode, * turn it off. */ e1000_set_tbi_sbp_82543(hw, false); rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } } else { /* * If TBI compatibility is was previously off, * turn it on. For compatibility with a TBI link * partner, we will store bad packets. Some * frames have an additional byte on the end and * will look like CRC errors to to the hardware. */ if (!e1000_tbi_sbp_enabled_82543(hw)) { e1000_set_tbi_sbp_82543(hw, true); rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_SBP; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } } } out: return ret_val; } /** * e1000_check_for_fiber_link_82543 - Check for link (Fiber) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/ STATIC s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw, ctrl, status; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_check_for_fiber_link_82543"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* * If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also * need to give auto-negotiation time to complete, in case the cable * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */ if ((!(ctrl & E1000_CTRL_SWDPIN1)) && (!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { if (!mac->autoneg_failed) { mac->autoneg_failed = true; ret_val = 0; goto out; } DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); goto out; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* * If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = true; } out: return ret_val; } /** * e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings * @hw: pointer to the HW structure * * For the 82543 silicon, we need to set the MAC to match the settings * of the PHY, even if the PHY is auto-negotiating. **/ STATIC s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw) { u32 ctrl; s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_config_mac_to_phy_82543"); if (!(hw->phy.ops.read_reg)) goto out; /* Set the bits to force speed and duplex */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); /* * Set up duplex in the Device Control and Transmit Control * registers depending on negotiated values. */ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) goto out; ctrl &= ~E1000_CTRL_FD; if (phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; hw->mac.ops.config_collision_dist(hw); /* * Set up speed in the Device Control register depending on * negotiated values. */ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) ctrl |= E1000_CTRL_SPD_1000; else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) ctrl |= E1000_CTRL_SPD_100; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); out: return ret_val; } /** * e1000_write_vfta_82543 - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: the 32-bit offset in which to write the value to. * @value: the 32-bit value to write at location offset. * * This writes a 32-bit value to a 32-bit offset in the VLAN filter * table. **/ STATIC void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value) { u32 temp; DEBUGFUNC("e1000_write_vfta_82543"); if ((hw->mac.type == e1000_82544) && (offset & 1)) { temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp); E1000_WRITE_FLUSH(hw); } else { e1000_write_vfta_generic(hw, offset, value); } } /** * e1000_led_on_82543 - Turn on SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED on. **/ STATIC s32 e1000_led_on_82543(struct e1000_hw *hw) { u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_on_82543"); if (hw->mac.type == e1000_82544 && hw->phy.media_type == e1000_media_type_copper) { /* Clear SW-definable Pin 0 to turn on the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } else { /* Fiber 82544 and all 82543 use this method */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_led_off_82543 - Turn off SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED off. **/ STATIC s32 e1000_led_off_82543(struct e1000_hw *hw) { u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGFUNC("e1000_led_off_82543"); if (hw->mac.type == e1000_82544 && hw->phy.media_type == e1000_media_type_copper) { /* Set SW-definable Pin 0 to turn off the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } else { ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82543"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); } ================================================ FILE: drivers/net/e1000/base/e1000_82543.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_82543_H_ #define _E1000_82543_H_ #define PHY_PREAMBLE 0xFFFFFFFF #define PHY_PREAMBLE_SIZE 32 #define PHY_SOF 0x1 #define PHY_OP_READ 0x2 #define PHY_OP_WRITE 0x1 #define PHY_TURNAROUND 0x2 #define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */ /* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */ #define TBI_SBP_ENABLED 0x2 void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 *mac_addr, u32 max_frame_size); void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state); bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw); #endif ================================================ FILE: drivers/net/e1000/base/e1000_82571.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* 82571EB Gigabit Ethernet Controller * 82571EB Gigabit Ethernet Controller (Copper) * 82571EB Gigabit Ethernet Controller (Fiber) * 82571EB Dual Port Gigabit Mezzanine Adapter * 82571EB Quad Port Gigabit Mezzanine Adapter * 82571PT Gigabit PT Quad Port Server ExpressModule * 82572EI Gigabit Ethernet Controller (Copper) * 82572EI Gigabit Ethernet Controller (Fiber) * 82572EI Gigabit Ethernet Controller * 82573V Gigabit Ethernet Controller (Copper) * 82573E Gigabit Ethernet Controller (Copper) * 82573L Gigabit Ethernet Controller * 82574L Gigabit Network Connection * 82583V Gigabit Network Connection */ #include "e1000_api.h" STATIC s32 e1000_acquire_nvm_82571(struct e1000_hw *hw); STATIC void e1000_release_nvm_82571(struct e1000_hw *hw); STATIC s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw); STATIC s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw); STATIC s32 e1000_get_cfg_done_82571(struct e1000_hw *hw); STATIC s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active); STATIC s32 e1000_reset_hw_82571(struct e1000_hw *hw); STATIC s32 e1000_init_hw_82571(struct e1000_hw *hw); STATIC void e1000_clear_vfta_82571(struct e1000_hw *hw); STATIC bool e1000_check_mng_mode_82574(struct e1000_hw *hw); STATIC s32 e1000_led_on_82574(struct e1000_hw *hw); STATIC s32 e1000_setup_link_82571(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); STATIC s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw); STATIC s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); STATIC s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data); STATIC void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); STATIC s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw); STATIC s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); STATIC s32 e1000_get_phy_id_82571(struct e1000_hw *hw); STATIC void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); STATIC void e1000_put_hw_semaphore_82573(struct e1000_hw *hw); STATIC s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); STATIC void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); STATIC s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active); STATIC s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active); STATIC void e1000_initialize_hw_bits_82571(struct e1000_hw *hw); STATIC s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_read_mac_addr_82571(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); /** * e1000_init_phy_params_82571 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82571(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("e1000_init_phy_params_82571"); if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; return E1000_SUCCESS; } phy->addr = 1; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->ops.check_reset_block = e1000_check_reset_block_generic; phy->ops.reset = e1000_phy_hw_reset_generic; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82571; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82571; switch (hw->mac.type) { case e1000_82571: case e1000_82572: phy->type = e1000_phy_igp_2; phy->ops.get_cfg_done = e1000_get_cfg_done_82571; phy->ops.get_info = e1000_get_phy_info_igp; phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; phy->ops.get_cable_length = e1000_get_cable_length_igp_2; phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.write_reg = e1000_write_phy_reg_igp; phy->ops.acquire = e1000_get_hw_semaphore_82571; phy->ops.release = e1000_put_hw_semaphore_82571; break; case e1000_82573: phy->type = e1000_phy_m88; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.read_reg = e1000_read_phy_reg_m88; phy->ops.write_reg = e1000_write_phy_reg_m88; phy->ops.acquire = e1000_get_hw_semaphore_82571; phy->ops.release = e1000_put_hw_semaphore_82571; break; case e1000_82574: case e1000_82583: E1000_MUTEX_INIT(&hw->dev_spec._82571.swflag_mutex); phy->type = e1000_phy_bm; phy->ops.get_cfg_done = e1000_get_cfg_done_generic; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.read_reg = e1000_read_phy_reg_bm2; phy->ops.write_reg = e1000_write_phy_reg_bm2; phy->ops.acquire = e1000_get_hw_semaphore_82574; phy->ops.release = e1000_put_hw_semaphore_82574; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574; break; default: return -E1000_ERR_PHY; break; } /* This can only be done after all function pointers are setup. */ ret_val = e1000_get_phy_id_82571(hw); if (ret_val) { DEBUGOUT("Error getting PHY ID\n"); return ret_val; } /* Verify phy id */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: if (phy->id != IGP01E1000_I_PHY_ID) ret_val = -E1000_ERR_PHY; break; case e1000_82573: if (phy->id != M88E1111_I_PHY_ID) ret_val = -E1000_ERR_PHY; break; case e1000_82574: case e1000_82583: if (phy->id != BME1000_E_PHY_ID_R2) ret_val = -E1000_ERR_PHY; break; default: ret_val = -E1000_ERR_PHY; break; } if (ret_val) DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); return ret_val; } /** * e1000_init_nvm_params_82571 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; DEBUGFUNC("e1000_init_nvm_params_82571"); nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; nvm->word_size = 2048; /* Autonomous Flash update bit must be cleared due * to Flash update issue. */ eecd &= ~E1000_EECD_AUPDEN; E1000_WRITE_REG(hw, E1000_EECD, eecd); break; } /* Fall Through */ default: nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; nvm->word_size = 1 << size; break; } /* Function Pointers */ switch (hw->mac.type) { case e1000_82574: case e1000_82583: nvm->ops.acquire = e1000_get_hw_semaphore_82574; nvm->ops.release = e1000_put_hw_semaphore_82574; break; default: nvm->ops.acquire = e1000_acquire_nvm_82571; nvm->ops.release = e1000_release_nvm_82571; break; } nvm->ops.read = e1000_read_nvm_eerd; nvm->ops.update = e1000_update_nvm_checksum_82571; nvm->ops.validate = e1000_validate_nvm_checksum_82571; nvm->ops.valid_led_default = e1000_valid_led_default_82571; nvm->ops.write = e1000_write_nvm_82571; return E1000_SUCCESS; } /** * e1000_init_mac_params_82571 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82571(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 swsm = 0; u32 swsm2 = 0; bool force_clear_smbi = false; DEBUGFUNC("e1000_init_mac_params_82571"); /* Set media type and media-dependent function pointers */ switch (hw->device_id) { case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82571EB_QUAD_FIBER: hw->phy.media_type = e1000_media_type_fiber; mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_82571; mac->ops.check_for_link = e1000_check_for_fiber_link_generic; mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic; break; case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82571EB_SERDES_DUAL: case E1000_DEV_ID_82571EB_SERDES_QUAD: case E1000_DEV_ID_82572EI_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_82571; mac->ops.check_for_link = e1000_check_for_serdes_link_82571; mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic; break; default: hw->phy.media_type = e1000_media_type_copper; mac->ops.setup_physical_interface = e1000_setup_copper_link_82571; mac->ops.check_for_link = e1000_check_for_copper_link_generic; mac->ops.get_link_up_info = e1000_get_speed_and_duplex_copper_generic; break; } /* Set mta register count */ mac->mta_reg_count = 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* Adaptive IFS supported */ mac->adaptive_ifs = true; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ mac->ops.reset_hw = e1000_reset_hw_82571; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82571; /* link setup */ mac->ops.setup_link = e1000_setup_link_82571; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_82571; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82571; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn off LED */ mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82571; /* MAC-specific function pointers */ switch (hw->mac.type) { case e1000_82573: mac->ops.set_lan_id = e1000_set_lan_id_single_port; mac->ops.check_mng_mode = e1000_check_mng_mode_generic; mac->ops.led_on = e1000_led_on_generic; mac->ops.blink_led = e1000_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; /* ARC supported; valid only if manageability features are * enabled. */ mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); break; case e1000_82574: case e1000_82583: mac->ops.set_lan_id = e1000_set_lan_id_single_port; mac->ops.check_mng_mode = e1000_check_mng_mode_82574; mac->ops.led_on = e1000_led_on_82574; break; default: mac->ops.check_mng_mode = e1000_check_mng_mode_generic; mac->ops.led_on = e1000_led_on_generic; mac->ops.blink_led = e1000_blink_led_generic; /* FWSM register */ mac->has_fwsm = true; break; } /* Ensure that the inter-port SWSM.SMBI lock bit is clear before * first NVM or PHY access. This should be done for single-port * devices, and for one port only on dual-port devices so that * for those devices we can still use the SMBI lock to synchronize * inter-port accesses to the PHY & NVM. */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: swsm2 = E1000_READ_REG(hw, E1000_SWSM2); if (!(swsm2 & E1000_SWSM2_LOCK)) { /* Only do this for the first interface on this card */ E1000_WRITE_REG(hw, E1000_SWSM2, swsm2 | E1000_SWSM2_LOCK); force_clear_smbi = true; } else { force_clear_smbi = false; } break; default: force_clear_smbi = true; break; } if (force_clear_smbi) { /* Make sure SWSM.SMBI is clear */ swsm = E1000_READ_REG(hw, E1000_SWSM); if (swsm & E1000_SWSM_SMBI) { /* This bit should not be set on a first interface, and * indicates that the bootagent or EFI code has * improperly left this bit enabled */ DEBUGOUT("Please update your 82571 Bootagent\n"); } E1000_WRITE_REG(hw, E1000_SWSM, swsm & ~E1000_SWSM_SMBI); } /* Initialze device specific counter of SMBI acquisition timeouts. */ hw->dev_spec._82571.smb_counter = 0; return E1000_SUCCESS; } /** * e1000_init_function_pointers_82571 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82571"); hw->mac.ops.init_params = e1000_init_mac_params_82571; hw->nvm.ops.init_params = e1000_init_nvm_params_82571; hw->phy.ops.init_params = e1000_init_phy_params_82571; } /** * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision * @hw: pointer to the HW structure * * Reads the PHY registers and stores the PHY ID and possibly the PHY * revision in the hardware structure. **/ STATIC s32 e1000_get_phy_id_82571(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_id = 0; DEBUGFUNC("e1000_get_phy_id_82571"); switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* The 82571 firmware may still be configuring the PHY. * In this case, we cannot access the PHY until the * configuration is done. So we explicitly set the * PHY ID. */ phy->id = IGP01E1000_I_PHY_ID; break; case e1000_82573: return e1000_get_phy_id(hw); break; case e1000_82574: case e1000_82583: ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) return ret_val; phy->id = (u32)(phy_id << 16); usec_delay(20); ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) return ret_val; phy->id |= (u32)(phy_id); phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); break; default: return -E1000_ERR_PHY; break; } return E1000_SUCCESS; } /** * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ STATIC s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) { u32 swsm; s32 sw_timeout = hw->nvm.word_size + 1; s32 fw_timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_82571"); /* If we have timedout 3 times on trying to acquire * the inter-port SMBI semaphore, there is old code * operating on the other port, and it is not * releasing SMBI. Modify the number of times that * we try for the semaphore to interwork with this * older code. */ if (hw->dev_spec._82571.smb_counter > 2) sw_timeout = 1; /* Get the SW semaphore */ while (i < sw_timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == sw_timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); hw->dev_spec._82571.smb_counter++; } /* Get the FW semaphore. */ for (i = 0; i < fw_timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == fw_timeout) { /* Release semaphores */ e1000_put_hw_semaphore_82571(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_put_hw_semaphore_82571 - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/ STATIC void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) { u32 swsm; DEBUGFUNC("e1000_put_hw_semaphore_generic"); swsm = E1000_READ_REG(hw, E1000_SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, E1000_SWSM, swsm); } /** * e1000_get_hw_semaphore_82573 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore during reset. * **/ STATIC s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) { u32 extcnf_ctrl; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_82573"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); do { extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) break; msec_delay(2); i++; } while (i < MDIO_OWNERSHIP_TIMEOUT); if (i == MDIO_OWNERSHIP_TIMEOUT) { /* Release semaphores */ e1000_put_hw_semaphore_82573(hw); DEBUGOUT("Driver can't access the PHY\n"); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_put_hw_semaphore_82573 - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used during reset. * **/ STATIC void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) { u32 extcnf_ctrl; DEBUGFUNC("e1000_put_hw_semaphore_82573"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); } /** * e1000_get_hw_semaphore_82574 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM. * **/ STATIC s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_get_hw_semaphore_82574"); E1000_MUTEX_LOCK(&hw->dev_spec._82571.swflag_mutex); ret_val = e1000_get_hw_semaphore_82573(hw); if (ret_val) E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex); return ret_val; } /** * e1000_put_hw_semaphore_82574 - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM * **/ STATIC void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) { DEBUGFUNC("e1000_put_hw_semaphore_82574"); e1000_put_hw_semaphore_82573(hw); E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex); } /** * e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. * LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ STATIC s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) { u32 data = E1000_READ_REG(hw, E1000_POEMB); DEBUGFUNC("e1000_set_d0_lplu_state_82574"); if (active) data |= E1000_PHY_CTRL_D0A_LPLU; else data &= ~E1000_PHY_CTRL_D0A_LPLU; E1000_WRITE_REG(hw, E1000_POEMB, data); return E1000_SUCCESS; } /** * e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * The low power link up (lplu) state is set to the power management level D3 * when active is true, else clear lplu for D3. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ STATIC s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) { u32 data = E1000_READ_REG(hw, E1000_POEMB); DEBUGFUNC("e1000_set_d3_lplu_state_82574"); if (!active) { data &= ~E1000_PHY_CTRL_NOND0A_LPLU; } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) || (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) { data |= E1000_PHY_CTRL_NOND0A_LPLU; } E1000_WRITE_REG(hw, E1000_POEMB, data); return E1000_SUCCESS; } /** * e1000_acquire_nvm_82571 - Request for access to the EEPROM * @hw: pointer to the HW structure * * To gain access to the EEPROM, first we must obtain a hardware semaphore. * Then for non-82573 hardware, set the EEPROM access request bit and wait * for EEPROM access grant bit. If the access grant bit is not set, release * hardware semaphore. **/ STATIC s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_82571"); ret_val = e1000_get_hw_semaphore_82571(hw); if (ret_val) return ret_val; switch (hw->mac.type) { case e1000_82573: break; default: ret_val = e1000_acquire_nvm_generic(hw); break; } if (ret_val) e1000_put_hw_semaphore_82571(hw); return ret_val; } /** * e1000_release_nvm_82571 - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit. **/ STATIC void e1000_release_nvm_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_82571"); e1000_release_nvm_generic(hw); e1000_put_hw_semaphore_82571(hw); } /** * e1000_write_nvm_82571 - Write to EEPROM using appropriate interface * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * For non-82573 silicon, write data to EEPROM at offset using SPI interface. * * If e1000_update_nvm_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ STATIC s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_write_nvm_82571"); switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); break; case e1000_82571: case e1000_82572: ret_val = e1000_write_nvm_spi(hw, offset, words, data); break; default: ret_val = -E1000_ERR_NVM; break; } return ret_val; } /** * e1000_update_nvm_checksum_82571 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/ STATIC s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) { u32 eecd; s32 ret_val; u16 i; DEBUGFUNC("e1000_update_nvm_checksum_82571"); ret_val = e1000_update_nvm_checksum_generic(hw); if (ret_val) return ret_val; /* If our nvm is an EEPROM, then we're done * otherwise, commit the checksum to the flash NVM. */ if (hw->nvm.type != e1000_nvm_flash_hw) return E1000_SUCCESS; /* Check for pending operations. */ for (i = 0; i < E1000_FLASH_UPDATES; i++) { msec_delay(1); if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD)) break; } if (i == E1000_FLASH_UPDATES) return -E1000_ERR_NVM; /* Reset the firmware if using STM opcode. */ if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) { /* The enabling of and the actual reset must be done * in two write cycles. */ E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET); } /* Commit the write to flash */ eecd = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD; E1000_WRITE_REG(hw, E1000_EECD, eecd); for (i = 0; i < E1000_FLASH_UPDATES; i++) { msec_delay(1); if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD)) break; } if (i == E1000_FLASH_UPDATES) return -E1000_ERR_NVM; return E1000_SUCCESS; } /** * e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ STATIC s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_validate_nvm_checksum_82571"); if (hw->nvm.type == e1000_nvm_flash_hw) e1000_fix_nvm_checksum_82571(hw); return e1000_validate_nvm_checksum_generic(hw); } /** * e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * After checking for invalid values, poll the EEPROM to ensure the previous * command has completed before trying to write the next word. After write * poll for completion. * * If e1000_update_nvm_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ STATIC s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, eewr = 0; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_nvm_eewr_82571"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } for (i = 0; i < words; i++) { eewr = ((data[i] << E1000_NVM_RW_REG_DATA) | ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) | E1000_NVM_RW_REG_START); ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); if (ret_val) break; E1000_WRITE_REG(hw, E1000_EEWR, eewr); ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); if (ret_val) break; } return ret_val; } /** * e1000_get_cfg_done_82571 - Poll for configuration done * @hw: pointer to the HW structure * * Reads the management control register for the config done bit to be set. **/ STATIC s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; DEBUGFUNC("e1000_get_cfg_done_82571"); while (timeout) { if (E1000_READ_REG(hw, E1000_EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) break; msec_delay(1); timeout--; } if (!timeout) { DEBUGOUT("MNG configuration cycle has not completed.\n"); return -E1000_ERR_RESET; } return E1000_SUCCESS; } /** * e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When activating LPLU * this function also disables smart speed and vice versa. LPLU will not be * activated unless the device autonegotiation advertisement meets standards * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function * pointer entry point only called by PHY setup routines. **/ STATIC s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_82571"); if (!(phy->ops.read_reg)) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) return ret_val; if (active) { data |= IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } } return E1000_SUCCESS; } /** * e1000_reset_hw_82571 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82571(struct e1000_hw *hw) { u32 ctrl, ctrl_ext, eecd, tctl; s32 ret_val; DEBUGFUNC("e1000_reset_hw_82571"); /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_EN; E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_FLUSH(hw); msec_delay(10); /* Must acquire the MDIO ownership before MAC reset. * Ownership defaults to firmware after a reset. */ switch (hw->mac.type) { case e1000_82573: ret_val = e1000_get_hw_semaphore_82573(hw); break; case e1000_82574: case e1000_82583: ret_val = e1000_get_hw_semaphore_82574(hw); break; default: break; } ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); /* Must release MDIO ownership and mutex after MAC reset. */ switch (hw->mac.type) { case e1000_82573: /* Release mutex only if the hw semaphore is acquired */ if (!ret_val) e1000_put_hw_semaphore_82573(hw); break; case e1000_82574: case e1000_82583: /* Release mutex only if the hw semaphore is acquired */ if (!ret_val) e1000_put_hw_semaphore_82574(hw); break; default: break; } if (hw->nvm.type == e1000_nvm_flash_hw) { usec_delay(10); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_EE_RST; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); } ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) /* We don't want to continue accessing MAC registers. */ return ret_val; /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. * Need to wait for Phy configuration completion before accessing * NVM and Phy. */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* REQ and GNT bits need to be cleared when using AUTO_RD * to access the EEPROM. */ eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT); E1000_WRITE_REG(hw, E1000_EECD, eecd); break; case e1000_82573: case e1000_82574: case e1000_82583: msec_delay(25); break; default: break; } /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); if (hw->mac.type == e1000_82571) { /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) return ret_val; e1000_set_laa_state_82571(hw, true); } /* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes) hw->mac.serdes_link_state = e1000_serdes_link_down; return E1000_SUCCESS; } /** * e1000_init_hw_82571 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ STATIC s32 e1000_init_hw_82571(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 reg_data; s32 ret_val; u16 i, rar_count = mac->rar_entry_count; DEBUGFUNC("e1000_init_hw_82571"); e1000_initialize_hw_bits_82571(hw); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); /* An error is not fatal and we should not stop init due to this */ if (ret_val) DEBUGOUT("Error initializing identification LED\n"); /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); /* Setup the receive address. * If, however, a locally administered address was assigned to the * 82571, we must reserve a RAR for it to work around an issue where * resetting one port will reload the MAC on the other port. */ if (e1000_get_laa_state_82571(hw)) rar_count--; e1000_init_rx_addrs_generic(hw, rar_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* Set the transmit descriptor write-back policy */ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data); /* ...for both queues. */ switch (mac->type) { case e1000_82573: e1000_enable_tx_pkt_filtering_generic(hw); /* fall through */ case e1000_82574: case e1000_82583: reg_data = E1000_READ_REG(hw, E1000_GCR); reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; E1000_WRITE_REG(hw, E1000_GCR, reg_data); break; default: reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data); break; } /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82571(hw); return ret_val; } /** * e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits * @hw: pointer to the HW structure * * Initializes required hardware-dependent bits needed for normal operation. **/ STATIC void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_initialize_hw_bits_82571"); /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); /* Transmit Descriptor Control 1 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); /* Transmit Arbitration Control 0 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); reg &= ~(0xF << 27); /* 30:27 */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); break; case e1000_82574: case e1000_82583: reg |= (1 << 26); break; default: break; } E1000_WRITE_REG(hw, E1000_TARC(0), reg); /* Transmit Arbitration Control 1 */ reg = E1000_READ_REG(hw, E1000_TARC(1)); switch (hw->mac.type) { case e1000_82571: case e1000_82572: reg &= ~((1 << 29) | (1 << 30)); reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) reg &= ~(1 << 28); else reg |= (1 << 28); E1000_WRITE_REG(hw, E1000_TARC(1), reg); break; default: break; } /* Device Control */ switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: reg = E1000_READ_REG(hw, E1000_CTRL); reg &= ~(1 << 29); E1000_WRITE_REG(hw, E1000_CTRL, reg); break; default: break; } /* Extended Device Control */ switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~(1 << 23); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); break; default: break; } if (hw->mac.type == e1000_82571) { reg = E1000_READ_REG(hw, E1000_PBA_ECC); reg |= E1000_PBA_ECC_CORR_EN; E1000_WRITE_REG(hw, E1000_PBA_ECC, reg); } /* Workaround for hardware errata. * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 */ if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); } /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ if (hw->mac.type <= e1000_82573) { reg = E1000_READ_REG(hw, E1000_RFCTL); reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); E1000_WRITE_REG(hw, E1000_RFCTL, reg); } /* PCI-Ex Control Registers */ switch (hw->mac.type) { case e1000_82574: case e1000_82583: reg = E1000_READ_REG(hw, E1000_GCR); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_GCR, reg); /* Workaround for hardware errata. * apply workaround for hardware errata documented in errata * docs Fixes issue where some error prone or unreliable PCIe * completions are occurring, particularly with ASPM enabled. * Without fix, issue can cause Tx timeouts. */ reg = E1000_READ_REG(hw, E1000_GCR2); reg |= 1; E1000_WRITE_REG(hw, E1000_GCR2, reg); break; default: break; } return; } /** * e1000_clear_vfta_82571 - Clear VLAN filter table * @hw: pointer to the HW structure * * Clears the register array which contains the VLAN filter table by * setting all the values to 0. **/ STATIC void e1000_clear_vfta_82571(struct e1000_hw *hw) { u32 offset; u32 vfta_value = 0; u32 vfta_offset = 0; u32 vfta_bit_in_reg = 0; DEBUGFUNC("e1000_clear_vfta_82571"); switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (hw->mng_cookie.vlan_id != 0) { /* The VFTA is a 4096b bit-field, each identifying * a single VLAN ID. The following operations * determine which 32b entry (i.e. offset) into the * array we want to set the VLAN ID (i.e. bit) of * the manageability unit. */ vfta_offset = (hw->mng_cookie.vlan_id >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); } break; default: break; } for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { /* If the offset we want to clear is the same offset of the * manageability VLAN ID, then clear all bits except that of * the manageability unit. */ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value); E1000_WRITE_FLUSH(hw); } } /** * e1000_check_mng_mode_82574 - Check manageability is enabled * @hw: pointer to the HW structure * * Reads the NVM Initialization Control Word 2 and returns true * (>0) if any manageability is enabled, else false (0). **/ STATIC bool e1000_check_mng_mode_82574(struct e1000_hw *hw) { u16 data; DEBUGFUNC("e1000_check_mng_mode_82574"); hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; } /** * e1000_led_on_82574 - Turn LED on * @hw: pointer to the HW structure * * Turn LED on. **/ STATIC s32 e1000_led_on_82574(struct e1000_hw *hw) { u32 ctrl; u32 i; DEBUGFUNC("e1000_led_on_82574"); ctrl = hw->mac.ledctl_mode2; if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) { /* If no link, then turn LED on by setting the invert bit * for each LED that's "on" (0x0E) in ledctl_mode2. */ for (i = 0; i < 4; i++) if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == E1000_LEDCTL_MODE_LED_ON) ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); } E1000_WRITE_REG(hw, E1000_LEDCTL, ctrl); return E1000_SUCCESS; } /** * e1000_check_phy_82574 - check 82574 phy hung state * @hw: pointer to the HW structure * * Returns whether phy is hung or not **/ bool e1000_check_phy_82574(struct e1000_hw *hw) { u16 status_1kbt = 0; u16 receive_errors = 0; s32 ret_val; DEBUGFUNC("e1000_check_phy_82574"); /* Read PHY Receive Error counter first, if its is max - all F's then * read the Base1000T status register If both are max then PHY is hung. */ ret_val = hw->phy.ops.read_reg(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); if (ret_val) return false; if (receive_errors == E1000_RECEIVE_ERROR_MAX) { ret_val = hw->phy.ops.read_reg(hw, E1000_BASE1000T_STATUS, &status_1kbt); if (ret_val) return false; if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == E1000_IDLE_ERROR_COUNT_MASK) return true; } return false; } /** * e1000_setup_link_82571 - Setup flow control and link settings * @hw: pointer to the HW structure * * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ STATIC s32 e1000_setup_link_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_setup_link_82571"); /* 82573 does not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (hw->fc.requested_mode == e1000_fc_default) hw->fc.requested_mode = e1000_fc_full; break; default: break; } return e1000_setup_link_generic(hw); } /** * e1000_setup_copper_link_82571 - Configure copper link settings * @hw: pointer to the HW structure * * Configures the link for auto-neg or forced speed and duplex. Then we check * for link, once link is established calls to configure collision distance * and flow control are called. **/ STATIC s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_copper_link_82571"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); switch (hw->phy.type) { case e1000_phy_m88: case e1000_phy_bm: ret_val = e1000_copper_link_setup_m88(hw); break; case e1000_phy_igp_2: ret_val = e1000_copper_link_setup_igp(hw); break; default: return -E1000_ERR_PHY; break; } if (ret_val) return ret_val; return e1000_setup_copper_link_generic(hw); } /** * e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Configures collision distance and flow control for fiber and serdes links. * Upon successful setup, poll for link. **/ STATIC s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_setup_fiber_serdes_link_82571"); switch (hw->mac.type) { case e1000_82571: case e1000_82572: /* If SerDes loopback mode is entered, there is no form * of reset to take the adapter out of that mode. So we * have to explicitly take the adapter out of loopback * mode. This prevents drivers from twiddling their thumbs * if another tool failed to take it out of loopback mode. */ E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); break; default: break; } return e1000_setup_fiber_serdes_link_generic(hw); } /** * e1000_check_for_serdes_link_82571 - Check for link (Serdes) * @hw: pointer to the HW structure * * Reports the link state as up or down. * * If autonegotiation is supported by the link partner, the link state is * determined by the result of autonegotiation. This is the most likely case. * If autonegotiation is not supported by the link partner, and the link * has a valid signal, force the link up. * * The link state is represented internally here by 4 states: * * 1) down * 2) autoneg_progress * 3) autoneg_complete (the link successfully autonegotiated) * 4) forced_up (the link has been forced up, it did not autonegotiate) * **/ STATIC s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw; u32 ctrl; u32 status; u32 txcw; u32 i; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_check_for_serdes_link_82571"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); E1000_READ_REG(hw, E1000_RXCW); /* SYNCH bit and IV bit are sticky */ usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { /* Receiver is synchronized with no invalid bits. */ switch (mac->serdes_link_state) { case e1000_serdes_link_autoneg_complete: if (!(status & E1000_STATUS_LU)) { /* We have lost link, retry autoneg before * reporting link failure */ mac->serdes_link_state = e1000_serdes_link_autoneg_progress; mac->serdes_has_link = false; DEBUGOUT("AN_UP -> AN_PROG\n"); } else { mac->serdes_has_link = true; } break; case e1000_serdes_link_forced_up: /* If we are receiving /C/ ordered sets, re-enable * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. */ if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_link_state = e1000_serdes_link_autoneg_progress; mac->serdes_has_link = false; DEBUGOUT("FORCED_UP -> AN_PROG\n"); } else { mac->serdes_has_link = true; } break; case e1000_serdes_link_autoneg_progress: if (rxcw & E1000_RXCW_C) { /* We received /C/ ordered sets, meaning the * link partner has autonegotiated, and we can * trust the Link Up (LU) status bit. */ if (status & E1000_STATUS_LU) { mac->serdes_link_state = e1000_serdes_link_autoneg_complete; DEBUGOUT("AN_PROG -> AN_UP\n"); mac->serdes_has_link = true; } else { /* Autoneg completed, but failed. */ mac->serdes_link_state = e1000_serdes_link_down; DEBUGOUT("AN_PROG -> DOWN\n"); } } else { /* The link partner did not autoneg. * Force link up and full duplex, and change * state to forced. */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error config flow control\n"); break; } mac->serdes_link_state = e1000_serdes_link_forced_up; mac->serdes_has_link = true; DEBUGOUT("AN_PROG -> FORCED_UP\n"); } break; case e1000_serdes_link_down: default: /* The link was down but the receiver has now gained * valid sync, so lets see if we can bring the link * up. */ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_link_state = e1000_serdes_link_autoneg_progress; mac->serdes_has_link = false; DEBUGOUT("DOWN -> AN_PROG\n"); break; } } else { if (!(rxcw & E1000_RXCW_SYNCH)) { mac->serdes_has_link = false; mac->serdes_link_state = e1000_serdes_link_down; DEBUGOUT("ANYSTATE -> DOWN\n"); } else { /* Check several times, if SYNCH bit and CONFIG * bit both are consistently 1 then simply ignore * the IV bit and restart Autoneg */ for (i = 0; i < AN_RETRY_COUNT; i++) { usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if ((rxcw & E1000_RXCW_SYNCH) && (rxcw & E1000_RXCW_C)) continue; if (rxcw & E1000_RXCW_IV) { mac->serdes_has_link = false; mac->serdes_link_state = e1000_serdes_link_down; DEBUGOUT("ANYSTATE -> DOWN\n"); break; } } if (i == AN_RETRY_COUNT) { txcw = E1000_READ_REG(hw, E1000_TXCW); txcw |= E1000_TXCW_ANE; E1000_WRITE_REG(hw, E1000_TXCW, txcw); mac->serdes_link_state = e1000_serdes_link_autoneg_progress; mac->serdes_has_link = false; DEBUGOUT("ANYSTATE -> AN_PROG\n"); } } } return ret_val; } /** * e1000_valid_led_default_82571 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ STATIC s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_82571"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } switch (hw->mac.type) { case e1000_82573: case e1000_82574: case e1000_82583: if (*data == ID_LED_RESERVED_F746) *data = ID_LED_DEFAULT_82573; break; default: if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; break; } return E1000_SUCCESS; } /** * e1000_get_laa_state_82571 - Get locally administered address state * @hw: pointer to the HW structure * * Retrieve and return the current locally administered address state. **/ bool e1000_get_laa_state_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_get_laa_state_82571"); if (hw->mac.type != e1000_82571) return false; return hw->dev_spec._82571.laa_is_present; } /** * e1000_set_laa_state_82571 - Set locally administered address state * @hw: pointer to the HW structure * @state: enable/disable locally administered address * * Enable/Disable the current locally administered address state. **/ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) { DEBUGFUNC("e1000_set_laa_state_82571"); if (hw->mac.type != e1000_82571) return; hw->dev_spec._82571.laa_is_present = state; /* If workaround is activated... */ if (state) /* Hold a copy of the LAA in RAR[14] This is done so that * between the time RAR[0] gets clobbered and the time it * gets fixed, the actual LAA is in one of the RARs and no * incoming packets directed to this port are dropped. * Eventually the LAA will be in RAR[0] and RAR[14]. */ hw->mac.ops.rar_set(hw, hw->mac.addr, hw->mac.rar_entry_count - 1); return; } /** * e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum * @hw: pointer to the HW structure * * Verifies that the EEPROM has completed the update. After updating the * EEPROM, we need to check bit 15 in work 0x23 for the checksum fix. If * the checksum fix is not implemented, we need to set the bit and update * the checksum. Otherwise, if bit 15 is set and the checksum is incorrect, * we need to return bad checksum. **/ STATIC s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val; u16 data; DEBUGFUNC("e1000_fix_nvm_checksum_82571"); if (nvm->type != e1000_nvm_flash_hw) return E1000_SUCCESS; /* Check bit 4 of word 10h. If it is 0, firmware is done updating * 10h-12h. Checksum may need to be fixed. */ ret_val = nvm->ops.read(hw, 0x10, 1, &data); if (ret_val) return ret_val; if (!(data & 0x10)) { /* Read 0x23 and check bit 15. This bit is a 1 * when the checksum has already been fixed. If * the checksum is still wrong and this bit is a * 1, we need to return bad checksum. Otherwise, * we need to set this bit to a 1 and update the * checksum. */ ret_val = nvm->ops.read(hw, 0x23, 1, &data); if (ret_val) return ret_val; if (!(data & 0x8000)) { data |= 0x8000; ret_val = nvm->ops.write(hw, 0x23, 1, &data); if (ret_val) return ret_val; ret_val = nvm->ops.update(hw); if (ret_val) return ret_val; } } return E1000_SUCCESS; } /** * e1000_read_mac_addr_82571 - Read device MAC address * @hw: pointer to the HW structure **/ STATIC s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_read_mac_addr_82571"); if (hw->mac.type == e1000_82571) { s32 ret_val; /* If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) return ret_val; } return e1000_read_mac_addr_generic(hw); } /** * e1000_power_down_phy_copper_82571 - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; struct e1000_mac_info *mac = &hw->mac; if (!phy->ops.check_reset_block) return; /* If the management interface is not enabled, then power down */ if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82571"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); E1000_READ_REG(hw, E1000_IAC); E1000_READ_REG(hw, E1000_ICRXOC); E1000_READ_REG(hw, E1000_ICRXPTC); E1000_READ_REG(hw, E1000_ICRXATC); E1000_READ_REG(hw, E1000_ICTXPTC); E1000_READ_REG(hw, E1000_ICTXATC); E1000_READ_REG(hw, E1000_ICTXQEC); E1000_READ_REG(hw, E1000_ICTXQMTC); E1000_READ_REG(hw, E1000_ICRXDMTC); } ================================================ FILE: drivers/net/e1000/base/e1000_82571.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_82571_H_ #define _E1000_82571_H_ #define ID_LED_RESERVED_F746 0xF746 #define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ (ID_LED_OFF1_ON2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) #define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 #define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */ /* Intr Throttling - RW */ #define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) #define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAC_MASK_82574 0x01F00000 #define E1000_IVAR_INT_ALLOC_VALID 0x8 /* Manageability Operation Mode mask */ #define E1000_NVM_INIT_CTRL2_MNGM 0x6000 #define E1000_BASE1000T_STATUS 10 #define E1000_IDLE_ERROR_COUNT_MASK 0xFF #define E1000_RECEIVE_ERROR_COUNTER 21 #define E1000_RECEIVE_ERROR_MAX 0xFFFF bool e1000_check_phy_82574(struct e1000_hw *hw); bool e1000_get_laa_state_82571(struct e1000_hw *hw); void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state); #endif ================================================ FILE: drivers/net/e1000/base/e1000_82575.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* * 82575EB Gigabit Network Connection * 82575EB Gigabit Backplane Connection * 82575GB Gigabit Network Connection * 82576 Gigabit Network Connection * 82576 Quad Port Gigabit Mezzanine Adapter * 82580 Gigabit Network Connection * I350 Gigabit Network Connection */ #include "e1000_api.h" #include "e1000_i210.h" STATIC s32 e1000_init_phy_params_82575(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw); STATIC s32 e1000_acquire_phy_82575(struct e1000_hw *hw); STATIC void e1000_release_phy_82575(struct e1000_hw *hw); STATIC s32 e1000_acquire_nvm_82575(struct e1000_hw *hw); STATIC void e1000_release_nvm_82575(struct e1000_hw *hw); STATIC s32 e1000_check_for_link_82575(struct e1000_hw *hw); STATIC s32 e1000_check_for_link_media_swap(struct e1000_hw *hw); STATIC s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); STATIC s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_reset_hw_82575(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_82580(struct e1000_hw *hw); STATIC s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data); STATIC s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active); STATIC s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active); STATIC s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active); STATIC s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); STATIC s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); STATIC s32 e1000_get_media_type_82575(struct e1000_hw *hw); STATIC s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw); STATIC s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); STATIC s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data); STATIC void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); STATIC s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); STATIC s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_get_phy_id_82575(struct e1000_hw *hw); STATIC void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask); STATIC bool e1000_sgmii_active_82575(struct e1000_hw *hw); STATIC s32 e1000_reset_init_script_82575(struct e1000_hw *hw); STATIC s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); STATIC void e1000_config_collision_dist_82575(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); STATIC void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); STATIC void e1000_power_up_serdes_link_82575(struct e1000_hw *hw); STATIC s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); STATIC s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw); STATIC s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw); STATIC s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw); STATIC s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset); STATIC s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset); STATIC s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw); STATIC s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw); STATIC void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value); STATIC void e1000_clear_vfta_i350(struct e1000_hw *hw); STATIC void e1000_i2c_start(struct e1000_hw *hw); STATIC void e1000_i2c_stop(struct e1000_hw *hw); STATIC s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data); STATIC s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data); STATIC s32 e1000_get_i2c_ack(struct e1000_hw *hw); STATIC s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data); STATIC s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data); STATIC void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); STATIC void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); STATIC s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data); STATIC bool e1000_get_i2c_data(u32 *i2cctl); STATIC const u16 e1000_82580_rxpbs_table[] = { 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; #define E1000_82580_RXPBS_TABLE_SIZE \ (sizeof(e1000_82580_rxpbs_table) / \ sizeof(e1000_82580_rxpbs_table[0])) /** * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO * @hw: pointer to the HW structure * * Called to determine if the I2C pins are being used for I2C or as an * external MDIO interface since the two options are mutually exclusive. **/ STATIC bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) { u32 reg = 0; bool ext_mdio = false; DEBUGFUNC("e1000_sgmii_uses_mdio_82575"); switch (hw->mac.type) { case e1000_82575: case e1000_82576: reg = E1000_READ_REG(hw, E1000_MDIC); ext_mdio = !!(reg & E1000_MDIC_DEST); break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: reg = E1000_READ_REG(hw, E1000_MDICNFG); ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); break; default: break; } return ext_mdio; } /** * e1000_init_phy_params_82575 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_phy_params_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 ctrl_ext; DEBUGFUNC("e1000_init_phy_params_82575"); phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82575; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->ops.acquire = e1000_acquire_phy_82575; phy->ops.check_reset_block = e1000_check_reset_block_generic; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.get_cfg_done = e1000_get_cfg_done_82575; phy->ops.release = e1000_release_phy_82575; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); if (e1000_sgmii_active_82575(hw)) { phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; ctrl_ext |= E1000_CTRL_I2C_ENA; } else { phy->ops.reset = e1000_phy_hw_reset_generic; ctrl_ext &= ~E1000_CTRL_I2C_ENA; } E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); e1000_reset_mdicnfg_82580(hw); if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; } else { switch (hw->mac.type) { case e1000_82580: case e1000_i350: case e1000_i354: phy->ops.read_reg = e1000_read_phy_reg_82580; phy->ops.write_reg = e1000_write_phy_reg_82580; break; case e1000_i210: case e1000_i211: phy->ops.read_reg = e1000_read_phy_reg_gs40g; phy->ops.write_reg = e1000_write_phy_reg_gs40g; break; default: phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.write_reg = e1000_write_phy_reg_igp; } } /* Set phy->phy_addr and phy->id. */ ret_val = e1000_get_phy_id_82575(hw); /* Verify phy id and set remaining function pointers */ switch (phy->id) { case M88E1543_E_PHY_ID: case M88E1512_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1111_I_PHY_ID: phy->type = e1000_phy_m88; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.get_info = e1000_get_phy_info_m88; if (phy->id == I347AT4_E_PHY_ID || phy->id == M88E1112_E_PHY_ID || phy->id == M88E1340M_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; else if (phy->id == M88E1543_E_PHY_ID || phy->id == M88E1512_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; else phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; /* Check if this PHY is confgured for media swap. */ if (phy->id == M88E1112_E_PHY_ID) { u16 data; ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 2); if (ret_val) goto out; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_MAC_CTRL_1, &data); if (ret_val) goto out; data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; if (data == E1000_M88E1112_AUTO_COPPER_SGMII || data == E1000_M88E1112_AUTO_COPPER_BASEX) hw->mac.ops.check_for_link = e1000_check_for_link_media_swap; } if (phy->id == M88E1512_E_PHY_ID) { ret_val = e1000_initialize_M88E1512_phy(hw); if (ret_val) goto out; } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.get_info = e1000_get_phy_info_igp; phy->ops.get_cable_length = e1000_get_cable_length_igp_2; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; break; case I82580_I_PHY_ID: case I350_I_PHY_ID: phy->type = e1000_phy_82580; phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577; phy->ops.get_cable_length = e1000_get_cable_length_82577; phy->ops.get_info = e1000_get_phy_info_82577; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; break; case I210_I_PHY_ID: phy->type = e1000_phy_i210; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; break; default: ret_val = -E1000_ERR_PHY; goto out; } out: return ret_val; } /** * e1000_init_nvm_params_82575 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; DEBUGFUNC("e1000_init_nvm_params_82575"); size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* * Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* Just in case size is out of range, cap it to the largest * EEPROM size supported */ if (size > 15) size = 15; nvm->word_size = 1 << size; if (hw->mac.type < e1000_i210) { nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } if (nvm->word_size == (1 << 15)) nvm->page_size = 128; nvm->type = e1000_nvm_eeprom_spi; } else { nvm->type = e1000_nvm_flash_hw; } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82575; nvm->ops.release = e1000_release_nvm_82575; if (nvm->word_size < (1 << 15)) nvm->ops.read = e1000_read_nvm_eerd; else nvm->ops.read = e1000_read_nvm_spi; nvm->ops.write = e1000_write_nvm_spi; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_82575; /* override generic family function pointers for specific descendants */ switch (hw->mac.type) { case e1000_82580: nvm->ops.validate = e1000_validate_nvm_checksum_82580; nvm->ops.update = e1000_update_nvm_checksum_82580; break; case e1000_i350: case e1000_i354: nvm->ops.validate = e1000_validate_nvm_checksum_i350; nvm->ops.update = e1000_update_nvm_checksum_i350; break; default: break; } return E1000_SUCCESS; } /** * e1000_init_mac_params_82575 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; DEBUGFUNC("e1000_init_mac_params_82575"); /* Derives media type */ e1000_get_media_type_82575(hw); /* Set mta register count */ mac->mta_reg_count = 128; /* Set uta register count */ mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES_82575; if (mac->type == e1000_82576) mac->rar_entry_count = E1000_RAR_ENTRIES_82576; if (mac->type == e1000_82580) mac->rar_entry_count = E1000_RAR_ENTRIES_82580; if (mac->type == e1000_i350 || mac->type == e1000_i354) mac->rar_entry_count = E1000_RAR_ENTRIES_I350; /* Enable EEE default settings for EEE supported devices */ if (mac->type >= e1000_i350) dev_spec->eee_disable = false; /* Allow a single clear of the SW semaphore on I210 and newer */ if (mac->type >= e1000_i210) dev_spec->clear_semaphore_once = true; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* FWSM register */ mac->has_fwsm = true; /* ARC supported; valid only if manageability features are enabled. */ mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ if (mac->type >= e1000_82580) mac->ops.reset_hw = e1000_reset_hw_82580; else mac->ops.reset_hw = e1000_reset_hw_82575; /* hw initialization */ if ((mac->type == e1000_i210) || (mac->type == e1000_i211)) mac->ops.init_hw = e1000_init_hw_i210; else mac->ops.init_hw = e1000_init_hw_82575; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; /* physical interface link setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575; /* physical interface shutdown */ mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; /* physical interface power up */ mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* configure collision distance */ mac->ops.config_collision_dist = e1000_config_collision_dist_82575; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_i350; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_i350; } else { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; } if (hw->mac.type >= e1000_82580) mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_crossover_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ mac->ops.blink_led = e1000_blink_led_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; /* acquire SW_FW sync */ mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; if (mac->type >= e1000_i210) { mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; } /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); return E1000_SUCCESS; } /** * e1000_init_function_pointers_82575 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82575"); hw->mac.ops.init_params = e1000_init_mac_params_82575; hw->nvm.ops.init_params = e1000_init_nvm_params_82575; hw->phy.ops.init_params = e1000_init_phy_params_82575; hw->mbx.ops.init_params = e1000_init_mbx_params_pf; } /** * e1000_acquire_phy_82575 - Acquire rights to access PHY * @hw: pointer to the HW structure * * Acquire access rights to the correct PHY. **/ STATIC s32 e1000_acquire_phy_82575(struct e1000_hw *hw) { u16 mask = E1000_SWFW_PHY0_SM; DEBUGFUNC("e1000_acquire_phy_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_SWFW_PHY2_SM; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; return hw->mac.ops.acquire_swfw_sync(hw, mask); } /** * e1000_release_phy_82575 - Release rights to access PHY * @hw: pointer to the HW structure * * A wrapper to release access rights to the correct PHY. **/ STATIC void e1000_release_phy_82575(struct e1000_hw *hw) { u16 mask = E1000_SWFW_PHY0_SM; DEBUGFUNC("e1000_release_phy_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_SWFW_PHY2_SM; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; hw->mac.ops.release_swfw_sync(hw, mask); } /** * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the serial gigabit media independent * interface and stores the retrieved information in data. **/ STATIC s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %u is out of range\n", offset); goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_read_phy_reg_i2c(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset using the serial gigabit * media independent interface. **/ STATIC s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %d is out of range\n", offset); goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_write_phy_reg_i2c(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_get_phy_id_82575 - Retrieve PHY addr and id * @hw: pointer to the HW structure * * Retrieves the PHY address and ID for both PHY's which do and do not use * sgmi interface. **/ STATIC s32 e1000_get_phy_id_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id; u32 ctrl_ext; u32 mdic; DEBUGFUNC("e1000_get_phy_id_82575"); /* some i354 devices need an extra read for phy id */ if (hw->mac.type == e1000_i354) e1000_get_phy_id(hw); /* * For SGMII PHYs, we try the list of possible addresses until * we find one that works. For non-SGMII PHYs * (e.g. integrated copper PHYs), an address of 1 should * work. The result of this function should mean phy->phy_addr * and phy->id are set correctly. */ if (!e1000_sgmii_active_82575(hw)) { phy->addr = 1; ret_val = e1000_get_phy_id(hw); goto out; } if (e1000_sgmii_uses_mdio_82575(hw)) { switch (hw->mac.type) { case e1000_82575: case e1000_82576: mdic = E1000_READ_REG(hw, E1000_MDIC); mdic &= E1000_MDIC_PHY_MASK; phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: mdic = E1000_READ_REG(hw, E1000_MDICNFG); mdic &= E1000_MDICNFG_PHY_MASK; phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; break; default: ret_val = -E1000_ERR_PHY; goto out; break; } ret_val = e1000_get_phy_id(hw); goto out; } /* Power on sgmii phy if it is disabled */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); E1000_WRITE_FLUSH(hw); msec_delay(300); /* * The address field in the I2CCMD register is 3 bits and 0 is invalid. * Therefore, we need to test 1-7 */ for (phy->addr = 1; phy->addr < 8; phy->addr++) { ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); if (ret_val == E1000_SUCCESS) { DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", phy_id, phy->addr); /* * At the time of this writing, The M88 part is * the only supported SGMII PHY product. */ if (phy_id == M88_VENDOR) break; } else { DEBUGOUT1("PHY address %u was unreadable\n", phy->addr); } } /* A valid PHY type couldn't be found. */ if (phy->addr == 8) { phy->addr = 0; ret_val = -E1000_ERR_PHY; } else { ret_val = e1000_get_phy_id(hw); } /* restore previous sfp cage power state */ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); out: return ret_val; } /** * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset * @hw: pointer to the HW structure * * Resets the PHY using the serial gigabit media independent interface. **/ STATIC s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; struct e1000_phy_info *phy = &hw->phy; DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); /* * This isn't a true "hard" reset, but is the only reset * available to us at this time. */ DEBUGOUT("Soft resetting SGMII attached PHY...\n"); if (!(hw->phy.ops.write_reg)) goto out; /* * SFP documentation requires the following to configure the SPF module * to work on SGMII. No further documentation is given. */ ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); if (ret_val) goto out; ret_val = hw->phy.ops.commit(hw); if (ret_val) goto out; if (phy->id == M88E1512_E_PHY_ID) ret_val = e1000_initialize_M88E1512_phy(hw); out: return ret_val; } /** * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ STATIC s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_82575"); if (!(hw->phy.ops.read_reg)) goto out; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (active) { data |= IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } } out: return ret_val; } /** * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ STATIC s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); if (active) { data |= E1000_82580_PM_D0_LPLU; /* When LPLU is enabled, we should disable SmartSpeed */ data &= ~E1000_82580_PM_SPD; } else { data &= ~E1000_82580_PM_D0_LPLU; /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) data |= E1000_82580_PM_SPD; else if (phy->smart_speed == e1000_smart_speed_off) data &= ~E1000_82580_PM_SPD; } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); return ret_val; } /** * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); if (!active) { data &= ~E1000_82580_PM_D3_LPLU; /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) data |= E1000_82580_PM_SPD; else if (phy->smart_speed == e1000_smart_speed_off) data &= ~E1000_82580_PM_SPD; } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= E1000_82580_PM_D3_LPLU; /* When LPLU is enabled, we should disable SmartSpeed */ data &= ~E1000_82580_PM_SPD; } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); return ret_val; } /** * e1000_acquire_nvm_82575 - Request for access to EEPROM * @hw: pointer to the HW structure * * Acquire the necessary semaphores for exclusive access to the EEPROM. * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ STATIC s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_82575"); ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); if (ret_val) goto out; /* * Check if there is some access * error this access may hook on */ if (hw->mac.type == e1000_i350) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT | E1000_EECD_TIMEOUT)) { /* Clear all access error flags */ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_ERROR_CLR); DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); } } if (hw->mac.type == e1000_82580) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & E1000_EECD_BLOCKED) { /* Clear access error flag */ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_BLOCKED); DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); } } ret_val = e1000_acquire_nvm_generic(hw); if (ret_val) e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); out: return ret_val; } /** * e1000_release_nvm_82575 - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit, * then release the semaphores acquired. **/ STATIC void e1000_release_nvm_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_82575"); e1000_release_nvm_generic(hw); e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); } /** * e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ STATIC s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ DEBUGFUNC("e1000_acquire_swfw_sync_82575"); while (i < timeout) { if (e1000_get_hw_semaphore_generic(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } if (i == timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); out: return ret_val; } /** * e1000_release_swfw_sync_82575 - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ STATIC void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; DEBUGFUNC("e1000_release_swfw_sync_82575"); while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); } /** * e1000_get_cfg_done_82575 - Read config done bit * @hw: pointer to the HW structure * * Read the management control register for the config done bit for * completion status. NOTE: silicon which is EEPROM-less will fail trying * to read the config done bit, so an error is *ONLY* logged and returns * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon * would not be able to be reset or change link. **/ STATIC s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; s32 ret_val = E1000_SUCCESS; u32 mask = E1000_NVM_CFG_DONE_PORT_0; DEBUGFUNC("e1000_get_cfg_done_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_NVM_CFG_DONE_PORT_1; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_NVM_CFG_DONE_PORT_2; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_NVM_CFG_DONE_PORT_3; while (timeout) { if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) break; msec_delay(1); timeout--; } if (!timeout) DEBUGOUT("MNG configuration cycle has not completed.\n"); /* If EEPROM is not marked present, init the PHY manually */ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); return ret_val; } /** * e1000_get_link_up_info_82575 - Get link speed/duplex info * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * This is a wrapper function, if using the serial gigabit media independent * interface, use PCS to retrieve the link speed and duplex information. * Otherwise, use the generic function to get the link speed and duplex info. **/ STATIC s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex) { s32 ret_val; DEBUGFUNC("e1000_get_link_up_info_82575"); if (hw->phy.media_type != e1000_media_type_copper) ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, duplex); else ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); return ret_val; } /** * e1000_check_for_link_82575 - Check for link * @hw: pointer to the HW structure * * If sgmii is enabled, then use the pcs register to determine link, otherwise * use the generic interface for determining link. **/ STATIC s32 e1000_check_for_link_82575(struct e1000_hw *hw) { s32 ret_val; u16 speed, duplex; DEBUGFUNC("e1000_check_for_link_82575"); if (hw->phy.media_type != e1000_media_type_copper) { ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, &duplex); /* * Use this flag to determine if link needs to be checked or * not. If we have link clear the flag so that we do not * continue to check for link. */ hw->mac.get_link_status = !hw->mac.serdes_has_link; /* * Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); } else { ret_val = e1000_check_for_copper_link_generic(hw); } return ret_val; } /** * e1000_check_for_link_media_swap - Check which M88E1112 interface linked * @hw: pointer to the HW structure * * Poll the M88E1112 interfaces to see which interface achieved link. */ STATIC s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; u8 port = 0; DEBUGFUNC("e1000_check_for_link_media_swap"); /* Check the copper medium. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); if (ret_val) return ret_val; if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_COPPER; /* Check the other medium. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); if (ret_val) return ret_val; /* reset page to 0 */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_OTHER; /* Determine if a swap needs to happen. */ if (port && (hw->dev_spec._82575.media_port != port)) { hw->dev_spec._82575.media_port = port; hw->dev_spec._82575.media_changed = true; } else { ret_val = e1000_check_for_link_82575(hw); } return E1000_SUCCESS; } /** * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown * @hw: pointer to the HW structure **/ STATIC void e1000_power_up_serdes_link_82575(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_power_up_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return; /* Enable PCS to turn on link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg |= E1000_PCS_CFG_PCS_EN; E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); /* Power up the laser */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* flush the write to verify completion */ E1000_WRITE_FLUSH(hw); msec_delay(1); } /** * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Using the physical coding sub-layer (PCS), retrieve the current speed and * duplex, then store the values in the pointers provided. **/ STATIC s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex) { struct e1000_mac_info *mac = &hw->mac; u32 pcs; u32 status; DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); /* * Read the PCS Status register for link state. For non-copper mode, * the status register is not accurate. The PCS status register is * used instead. */ pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); /* * The link up bit determines when link is up on autoneg. */ if (pcs & E1000_PCS_LSTS_LINK_OK) { mac->serdes_has_link = true; /* Detect and store PCS speed */ if (pcs & E1000_PCS_LSTS_SPEED_1000) *speed = SPEED_1000; else if (pcs & E1000_PCS_LSTS_SPEED_100) *speed = SPEED_100; else *speed = SPEED_10; /* Detect and store PCS duplex */ if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) *duplex = FULL_DUPLEX; else *duplex = HALF_DUPLEX; /* Check if it is an I354 2.5Gb backplane connection. */ if (mac->type == e1000_i354) { status = E1000_READ_REG(hw, E1000_STATUS); if ((status & E1000_STATUS_2P5_SKU) && !(status & E1000_STATUS_2P5_SKU_OVER)) { *speed = SPEED_2500; *duplex = FULL_DUPLEX; DEBUGOUT("2500 Mbs, "); DEBUGOUT("Full Duplex\n"); } } } else { mac->serdes_has_link = false; *speed = 0; *duplex = 0; } return E1000_SUCCESS; } /** * e1000_shutdown_serdes_link_82575 - Remove link during power down * @hw: pointer to the HW structure * * In the case of serdes shut down sfp and PCS on driver unload * when management pass thru is not enabled. **/ void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_shutdown_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return; if (!e1000_enable_mng_pass_thru(hw)) { /* Disable PCS to turn off link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg &= ~E1000_PCS_CFG_PCS_EN; E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); /* shutdown the laser */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg |= E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* flush the write to verify completion */ E1000_WRITE_FLUSH(hw); msec_delay(1); } return; } /** * e1000_reset_hw_82575 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ STATIC s32 e1000_reset_hw_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_reset_hw_82575"); /* * Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); /* set the completion timeout for interface */ ret_val = e1000_set_pcie_completion_timeout(hw); if (ret_val) DEBUGOUT("PCI-E Set completion timeout has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { /* * When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ DEBUGOUT("Auto Read Done did not complete\n"); } /* If EEPROM is not present, run manual init scripts */ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); return ret_val; } /** * e1000_init_hw_82575 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ s32 e1000_init_hw_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; u16 i, rar_count = mac->rar_entry_count; DEBUGFUNC("e1000_init_hw_82575"); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); if (ret_val) { DEBUGOUT("Error initializing identification LED\n"); /* This is not fatal and we should not stop init due to this */ } /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); /* Setup the receive address */ e1000_init_rx_addrs_generic(hw, rar_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Zero out the Unicast HASH table */ DEBUGOUT("Zeroing the UTA\n"); for (i = 0; i < mac->uta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* Set the default MTU size */ hw->dev_spec._82575.mtu = 1500; /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82575(hw); return ret_val; } /** * e1000_setup_copper_link_82575 - Configure copper link settings * @hw: pointer to the HW structure * * Configures the link for auto-neg or forced speed and duplex. Then we check * for link, once link is established calls to configure collision distance * and flow control are called. **/ STATIC s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u32 phpm_reg; DEBUGFUNC("e1000_setup_copper_link_82575"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Clear Go Link Disconnect bit on supported devices */ switch (hw->mac.type) { case e1000_82580: case e1000_i350: case e1000_i210: case e1000_i211: phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); phpm_reg &= ~E1000_82580_PM_GO_LINKD; E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); break; default: break; } ret_val = e1000_setup_serdes_link_82575(hw); if (ret_val) goto out; if (e1000_sgmii_active_82575(hw)) { /* allow time for SFP cage time to power up phy */ msec_delay(300); ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); goto out; } } switch (hw->phy.type) { case e1000_phy_i210: case e1000_phy_m88: switch (hw->phy.id) { case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1543_E_PHY_ID: case M88E1512_E_PHY_ID: case I210_I_PHY_ID: ret_val = e1000_copper_link_setup_m88_gen2(hw); break; default: ret_val = e1000_copper_link_setup_m88(hw); break; } break; case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); break; case e1000_phy_82580: ret_val = e1000_copper_link_setup_82577(hw); break; default: ret_val = -E1000_ERR_PHY; break; } if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw); out: return ret_val; } /** * e1000_setup_serdes_link_82575 - Setup link for serdes * @hw: pointer to the HW structure * * Configure the physical coding sub-layer (PCS) link. The PCS link is * used on copper connections where the serialized gigabit media independent * interface (sgmii), or serdes fiber is being used. Configures the link * for auto-negotiation or forces speed/duplex. **/ STATIC s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) { u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_setup_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return ret_val; /* * On the 82575, SerDes loopback mode persists until it is * explicitly turned off or a power cycle is performed. A read to * the register does not indicate its status. Therefore, we ensure * loopback mode is disabled during initialization. */ E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); /* power on the sfp cage if present */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ctrl_reg |= E1000_CTRL_SLU; /* set both sw defined pins on 82575/82576*/ if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; reg = E1000_READ_REG(hw, E1000_PCS_LCTL); /* default pcs_autoneg to the same setting as mac autoneg */ pcs_autoneg = hw->mac.autoneg; switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { case E1000_CTRL_EXT_LINK_MODE_SGMII: /* sgmii mode lets the phy handle forcing speed/duplex */ pcs_autoneg = true; /* autoneg time out should be disabled for SGMII mode */ reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); break; case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: /* disable PCS autoneg and support parallel detect only */ pcs_autoneg = false; /* fall through to default case */ default: if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) pcs_autoneg = false; } /* * non-SGMII modes only supports a speed of 1000/Full for the * link so it is best to just force the MAC and let the pcs * link either autoneg or be forced to 1000/Full */ ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | E1000_CTRL_FD | E1000_CTRL_FRCDPX; /* set speed of 1000/Full if speed/duplex is forced */ reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; break; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); /* * New SerDes mode allows for forcing speed or autonegotiating speed * at 1gb. Autoneg should be default set by most drivers. This is the * mode that will be compatible with older link partners and switches. * However, both are supported by the hardware and some drivers/tools. */ reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ /* Disable force flow control for autoneg */ reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; /* Configure flow control advertisement for autoneg */ anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); switch (hw->fc.requested_mode) { case e1000_fc_full: case e1000_fc_rx_pause: anadv_reg |= E1000_TXCW_ASM_DIR; anadv_reg |= E1000_TXCW_PAUSE; break; case e1000_fc_tx_pause: anadv_reg |= E1000_TXCW_ASM_DIR; break; default: break; } E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ /* Force flow control for forced link */ reg |= E1000_PCS_LCTL_FORCE_FCTRL; DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) e1000_force_mac_fc_generic(hw); return ret_val; } /** * e1000_get_media_type_82575 - derives current media type. * @hw: pointer to the HW structure * * The media type is chosen reflecting few settings. * The following are taken into account: * - link mode set in the current port Init Control Word #3 * - current link mode settings in CSR register * - MDIO vs. I2C PHY control interface chosen * - SFP module media type **/ STATIC s32 e1000_get_media_type_82575(struct e1000_hw *hw) { struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; s32 ret_val = E1000_SUCCESS; u32 ctrl_ext = 0; u32 link_mode = 0; /* Set internal phy as default */ dev_spec->sgmii_active = false; dev_spec->module_plugged = false; /* Get CSR setting */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* extract link mode setting */ link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; switch (link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: hw->phy.media_type = e1000_media_type_internal_serdes; break; case E1000_CTRL_EXT_LINK_MODE_GMII: hw->phy.media_type = e1000_media_type_copper; break; case E1000_CTRL_EXT_LINK_MODE_SGMII: /* Get phy control interface type set (MDIO vs. I2C)*/ if (e1000_sgmii_uses_mdio_82575(hw)) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = true; break; } /* fall through for I2C based SGMII */ case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: /* read media type from SFP EEPROM */ ret_val = e1000_set_sfp_media_type_82575(hw); if ((ret_val != E1000_SUCCESS) || (hw->phy.media_type == e1000_media_type_unknown)) { /* * If media type was not identified then return media * type defined by the CTRL_EXT settings. */ hw->phy.media_type = e1000_media_type_internal_serdes; if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = true; } break; } /* do not change link mode for 100BaseFX */ if (dev_spec->eth_flags.e100_base_fx) break; /* change current link mode setting */ ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; if (hw->phy.media_type == e1000_media_type_copper) ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; else ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); break; } return ret_val; } /** * e1000_set_sfp_media_type_82575 - derives SFP module media type. * @hw: pointer to the HW structure * * The media type is chosen based on SFP module. * compatibility flags retrieved from SFP ID EEPROM. **/ STATIC s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) { s32 ret_val = E1000_ERR_CONFIG; u32 ctrl_ext = 0; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; u8 tranceiver_type = 0; s32 timeout = 3; /* Turn I2C interface ON and power on sfp cage */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); E1000_WRITE_FLUSH(hw); /* Read SFP module data */ while (timeout) { ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), &tranceiver_type); if (ret_val == E1000_SUCCESS) break; msec_delay(100); timeout--; } if (ret_val != E1000_SUCCESS) goto out; ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), (u8 *)eth_flags); if (ret_val != E1000_SUCCESS) goto out; /* Check if there is some SFP module plugged and powered */ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { dev_spec->module_plugged = true; if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { hw->phy.media_type = e1000_media_type_internal_serdes; } else if (eth_flags->e100_base_fx) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_internal_serdes; } else if (eth_flags->e1000_base_t) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_copper; } else { hw->phy.media_type = e1000_media_type_unknown; DEBUGOUT("PHY module has not been recognized\n"); goto out; } } else { hw->phy.media_type = e1000_media_type_unknown; } ret_val = E1000_SUCCESS; out: /* Restore I2C interface setting */ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); return ret_val; } /** * e1000_valid_led_default_82575 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ STATIC s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_82575"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { switch (hw->phy.media_type) { case e1000_media_type_internal_serdes: *data = ID_LED_DEFAULT_82575_SERDES; break; case e1000_media_type_copper: default: *data = ID_LED_DEFAULT; break; } } out: return ret_val; } /** * e1000_sgmii_active_82575 - Return sgmii state * @hw: pointer to the HW structure * * 82575 silicon has a serialized gigabit media independent interface (sgmii) * which can be enabled for use in the embedded applications. Simply * return the current state of the sgmii interface. **/ STATIC bool e1000_sgmii_active_82575(struct e1000_hw *hw) { struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; return dev_spec->sgmii_active; } /** * e1000_reset_init_script_82575 - Inits HW defaults after reset * @hw: pointer to the HW structure * * Inits recommended HW defaults after a reset when there is no EEPROM * detected. This is only for the 82575. **/ STATIC s32 e1000_reset_init_script_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_reset_init_script_82575"); if (hw->mac.type == e1000_82575) { DEBUGOUT("Running reset init script for 82575\n"); /* SerDes configuration via SERDESCTRL */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); /* CCM configuration via CCMCTL register */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); /* PCIe lanes configuration */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); /* PCIe PLL Configuration */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); } return E1000_SUCCESS; } /** * e1000_read_mac_addr_82575 - Read device MAC address * @hw: pointer to the HW structure **/ STATIC s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_read_mac_addr_82575"); /* * If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) goto out; ret_val = e1000_read_mac_addr_generic(hw); out: return ret_val; } /** * e1000_config_collision_dist_82575 - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ STATIC void e1000_config_collision_dist_82575(struct e1000_hw *hw) { u32 tctl_ext; DEBUGFUNC("e1000_config_collision_dist_82575"); tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT); tctl_ext &= ~E1000_TCTL_EXT_COLD; tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT; E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext); E1000_WRITE_FLUSH(hw); } /** * e1000_power_down_phy_copper_82575 - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; if (!(phy->ops.check_reset_block)) return; /* If the management interface is not enabled, then power down */ if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ STATIC void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82575"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); E1000_READ_REG(hw, E1000_IAC); E1000_READ_REG(hw, E1000_ICRXOC); E1000_READ_REG(hw, E1000_ICRXPTC); E1000_READ_REG(hw, E1000_ICRXATC); E1000_READ_REG(hw, E1000_ICTXPTC); E1000_READ_REG(hw, E1000_ICTXATC); E1000_READ_REG(hw, E1000_ICTXQEC); E1000_READ_REG(hw, E1000_ICTXQMTC); E1000_READ_REG(hw, E1000_ICRXDMTC); E1000_READ_REG(hw, E1000_CBTMPC); E1000_READ_REG(hw, E1000_HTDPMC); E1000_READ_REG(hw, E1000_CBRMPC); E1000_READ_REG(hw, E1000_RPTHC); E1000_READ_REG(hw, E1000_HGPTC); E1000_READ_REG(hw, E1000_HTCBDPC); E1000_READ_REG(hw, E1000_HGORCL); E1000_READ_REG(hw, E1000_HGORCH); E1000_READ_REG(hw, E1000_HGOTCL); E1000_READ_REG(hw, E1000_HGOTCH); E1000_READ_REG(hw, E1000_LENERRS); /* This register should not be read in copper configurations */ if ((hw->phy.media_type == e1000_media_type_internal_serdes) || e1000_sgmii_active_82575(hw)) E1000_READ_REG(hw, E1000_SCVPC); } /** * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable * @hw: pointer to the HW structure * * After rx enable if managability is enabled then there is likely some * bad data at the start of the fifo and possibly in the DMA fifo. This * function clears the fifos and flushes any packets that came in as rx was * being enabled. **/ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) { u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; DEBUGFUNC("e1000_rx_fifo_workaround_82575"); if (hw->mac.type != e1000_82575 || !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; /* Disable all Rx queues */ for (i = 0; i < 4; i++) { rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); } /* Poll all queues to verify they have shut down */ for (ms_wait = 0; ms_wait < 10; ms_wait++) { msec_delay(1); rx_enabled = 0; for (i = 0; i < 4; i++) rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) break; } if (ms_wait == 10) DEBUGOUT("Queue disable timed out after 10ms\n"); /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ rfctl = E1000_READ_REG(hw, E1000_RFCTL); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = E1000_READ_REG(hw, E1000_RLPML); E1000_WRITE_REG(hw, E1000_RLPML, 0); rctl = E1000_READ_REG(hw, E1000_RCTL); temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); temp_rctl |= E1000_RCTL_LPE; E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); E1000_WRITE_FLUSH(hw); msec_delay(2); /* Enable Rx queues that were previously enabled and restore our * previous state */ for (i = 0; i < 4; i++) E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RLPML, rlpml); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); /* Flush receive errors generated by workaround */ E1000_READ_REG(hw, E1000_ROC); E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_MPC); } /** * e1000_set_pcie_completion_timeout - set pci-e completion timeout * @hw: pointer to the HW structure * * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, * however the hardware default for these parts is 500us to 1ms which is less * than the 10ms recommended by the pci-e spec. To address this we need to * increase the value to either 10ms to 200ms for capability version 1 config, * or 16ms to 55ms for version 2. **/ STATIC s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) { u32 gcr = E1000_READ_REG(hw, E1000_GCR); s32 ret_val = E1000_SUCCESS; u16 pcie_devctl2; /* only take action if timeout value is defaulted to 0 */ if (gcr & E1000_GCR_CMPL_TMOUT_MASK) goto out; /* * if capababilities version is type 1 we can write the * timeout of 10ms to 200ms through the GCR register */ if (!(gcr & E1000_GCR_CAP_VER2)) { gcr |= E1000_GCR_CMPL_TMOUT_10ms; goto out; } /* * for version 2 capabilities we need to write the config space * directly in order to set the completion timeout value for * 16ms to 55ms */ ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, &pcie_devctl2); if (ret_val) goto out; pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, &pcie_devctl2); out: /* disable completion timeout resend */ gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; E1000_WRITE_REG(hw, E1000_GCR, gcr); return ret_val; } /** * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * @pf: Physical Function pool - do not set anti-spoofing for the PF * * enables/disables L2 switch anti-spoofing functionality. **/ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) { u32 reg_val, reg_offset; switch (hw->mac.type) { case e1000_82576: reg_offset = E1000_DTXSWC; break; case e1000_i350: case e1000_i354: reg_offset = E1000_TXSWC; break; default: return; } reg_val = E1000_READ_REG(hw, reg_offset); if (enable) { reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | E1000_DTXSWC_VLAN_SPOOF_MASK); /* The PF can spoof - it has to in order to * support emulation mode NICs */ reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); } else { reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | E1000_DTXSWC_VLAN_SPOOF_MASK); } E1000_WRITE_REG(hw, reg_offset, reg_val); } /** * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * * enables/disables L2 switch loopback functionality. **/ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) { u32 dtxswc; switch (hw->mac.type) { case e1000_82576: dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); if (enable) dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; else dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); break; case e1000_i350: case e1000_i354: dtxswc = E1000_READ_REG(hw, E1000_TXSWC); if (enable) dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; else dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); break; default: /* Currently no other hardware supports loopback */ break; } } /** * e1000_vmdq_set_replication_pf - enable or disable vmdq replication * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * * enables/disables replication of packets across multiple pools. **/ void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) { u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); if (enable) vt_ctl |= E1000_VT_CTL_VM_REPL_EN; else vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); } /** * e1000_read_phy_reg_82580 - Read 82580 MDI control register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the MDI control register in the PHY at offset and stores the * information read to data. **/ STATIC s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_read_phy_reg_82580"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_read_phy_reg_mdic(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_write_phy_reg_82580 - Write 82580 MDI control register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write to register at offset * * Writes data to MDI control register in the PHY at offset. **/ STATIC s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; DEBUGFUNC("e1000_write_phy_reg_82580"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_write_phy_reg_mdic(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits * @hw: pointer to the HW structure * * This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on * the values found in the EEPROM. This addresses an issue in which these * bits are not restored from EEPROM after reset. **/ STATIC s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 mdicnfg; u16 nvm_data = 0; DEBUGFUNC("e1000_reset_mdicnfg_82580"); if (hw->mac.type != e1000_82580) goto out; if (!e1000_sgmii_active_82575(hw)) goto out; ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); if (nvm_data & NVM_WORD24_EXT_MDIO) mdicnfg |= E1000_MDICNFG_EXT_MDIO; if (nvm_data & NVM_WORD24_COM_MDIO) mdicnfg |= E1000_MDICNFG_COM_MDIO; E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); out: return ret_val; } /** * e1000_reset_hw_82580 - Reset hardware * @hw: pointer to the HW structure * * This resets function or entire device (all ports, etc.) * to a known state. **/ STATIC s32 e1000_reset_hw_82580(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; /* BH SW mailbox bit in SW_FW_SYNC */ u16 swmbsw_mask = E1000_SW_SYNCH_MB; u32 ctrl; bool global_device_reset = hw->dev_spec._82575.global_device_reset; DEBUGFUNC("e1000_reset_hw_82580"); hw->dev_spec._82575.global_device_reset = false; /* 82580 does not reliably do global_device_reset due to hw errata */ if (hw->mac.type == e1000_82580) global_device_reset = false; /* Get current control state. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); /* * Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); /* Determine whether or not a global dev reset is requested */ if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) global_device_reset = false; if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET)) ctrl |= E1000_CTRL_DEV_RST; else ctrl |= E1000_CTRL_RST; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); /* Add delay to insure DEV_RST has time to complete */ if (global_device_reset) msec_delay(5); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { /* * When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ DEBUGOUT("Auto Read Done did not complete\n"); } /* clear global device reset status bit */ E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); ret_val = e1000_reset_mdicnfg_82580(hw); if (ret_val) DEBUGOUT("Could not reset MDICNFG based on EEPROM\n"); /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); /* Release semaphore */ if (global_device_reset) hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); return ret_val; } /** * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size * @data: data received by reading RXPBS register * * The 82580 uses a table based approach for packet buffer allocation sizes. * This function converts the retrieved value into the correct table value * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 * 0x0 36 72 144 1 2 4 8 16 * 0x8 35 70 140 rsv rsv rsv rsv rsv */ u16 e1000_rxpbs_adjust_82580(u32 data) { u16 ret_val = 0; if (data < E1000_82580_RXPBS_TABLE_SIZE) ret_val = e1000_82580_rxpbs_table[data]; return ret_val; } /** * e1000_validate_nvm_checksum_with_offset - Validate EEPROM * checksum * @hw: pointer to the HW structure * @offset: offset in words of the checksum protected region * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) { s32 ret_val = E1000_SUCCESS; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_validate_nvm_checksum_with_offset"); for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); ret_val = -E1000_ERR_NVM; goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_with_offset - Update EEPROM * checksum * @hw: pointer to the HW structure * @offset: offset in words of the checksum protected region * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/ s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum_with_offset"); for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, &checksum); if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); out: return ret_val; } /** * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM section checksum by reading/adding each word of * the EEPROM and then verifies that the sum of the EEPROM is * equal to 0xBABA. **/ STATIC s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) { s32 ret_val; u16 eeprom_regions_count = 1; u16 j, nvm_data; u16 nvm_offset; DEBUGFUNC("e1000_validate_nvm_checksum_82580"); ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { /* if chekcsums compatibility bit is set validate checksums * for all 4 ports. */ eeprom_regions_count = 4; } for (j = 0; j < eeprom_regions_count; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_validate_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_82580 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM section checksums for all 4 ports by reading/adding * each word of the EEPROM up to the checksum. Then calculates the EEPROM * checksum and writes the value to the EEPROM. **/ STATIC s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) { s32 ret_val; u16 j, nvm_data; u16 nvm_offset; DEBUGFUNC("e1000_update_nvm_checksum_82580"); ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n"); goto out; } if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { /* set compatibility bit to validate checksums appropriately */ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n"); goto out; } } for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val) goto out; } out: return ret_val; } /** * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM section checksum by reading/adding each word of * the EEPROM and then verifies that the sum of the EEPROM is * equal to 0xBABA. **/ STATIC s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 j; u16 nvm_offset; DEBUGFUNC("e1000_validate_nvm_checksum_i350"); for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_validate_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_i350 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM section checksums for all 4 ports by reading/adding * each word of the EEPROM up to the checksum. Then calculates the EEPROM * checksum and writes the value to the EEPROM. **/ STATIC s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 j; u16 nvm_offset; DEBUGFUNC("e1000_update_nvm_checksum_i350"); for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * __e1000_access_emi_reg - Read/write EMI register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: pointer to value to read/write from/to the EMI address * @read: boolean flag to indicate read or write **/ STATIC s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, u16 *data, bool read) { s32 ret_val; DEBUGFUNC("__e1000_access_emi_reg"); ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); if (ret_val) return ret_val; if (read) ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); else ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); return ret_val; } /** * e1000_read_emi_reg - Read Extended Management Interface register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: value to be read from the EMI address **/ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) { DEBUGFUNC("e1000_read_emi_reg"); return __e1000_access_emi_reg(hw, addr, data, true); } /** * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY * @hw: pointer to the HW structure * * Initialize Marverl 1512 to work correctly with Avoton. **/ s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_initialize_M88E1512_phy"); /* Check if this is correct PHY. */ if (phy->id != M88E1512_E_PHY_ID) goto out; /* Switch to PHY page 0xFF. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); if (ret_val) goto out; /* Switch to PHY page 0xFB. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); if (ret_val) goto out; ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D); if (ret_val) goto out; /* Switch to PHY page 0x12. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); if (ret_val) goto out; /* Change mode to SGMII-to-Copper */ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); if (ret_val) goto out; /* Return the PHY to page 0. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); if (ret_val) goto out; ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } msec_delay(1000); out: return ret_val; } /** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure * * Enable/disable EEE based on setting in dev_spec structure. * **/ s32 e1000_set_eee_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 ipcnfg, eeer; DEBUGFUNC("e1000_set_eee_i350"); if ((hw->mac.type < e1000_i350) || (hw->phy.media_type != e1000_media_type_copper)) goto out; ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); eeer = E1000_READ_REG(hw, E1000_EEER); /* enable or disable per user setting */ if (!(hw->dev_spec._82575.eee_disable)) { u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); /* This bit should not be set in normal operation. */ if (eee_su & E1000_EEE_SU_LPI_CLK_STP) DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); } E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); E1000_WRITE_REG(hw, E1000_EEER, eeer); E1000_READ_REG(hw, E1000_IPCNFG); E1000_READ_REG(hw, E1000_EEER); out: return ret_val; } /** * e1000_set_eee_i354 - Enable/disable EEE support * @hw: pointer to the HW structure * * Enable/disable EEE legacy mode based on setting in dev_spec structure. * **/ s32 e1000_set_eee_i354(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_set_eee_i354"); if ((hw->phy.media_type != e1000_media_type_copper) || ((phy->id != M88E1543_E_PHY_ID) && (phy->id != M88E1512_E_PHY_ID))) goto out; if (!hw->dev_spec._82575.eee_disable) { /* Switch to PHY page 18. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); if (ret_val) goto out; ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, &phy_data); if (ret_val) goto out; phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, phy_data); if (ret_val) goto out; /* Return the PHY to page 0. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); if (ret_val) goto out; /* Turn on EEE advertisement. */ ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, &phy_data); if (ret_val) goto out; phy_data |= E1000_EEE_ADV_100_SUPPORTED | E1000_EEE_ADV_1000_SUPPORTED; ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); } else { /* Turn off EEE advertisement. */ ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, &phy_data); if (ret_val) goto out; phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | E1000_EEE_ADV_1000_SUPPORTED); ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); } out: return ret_val; } /** * e1000_get_eee_status_i354 - Get EEE status * @hw: pointer to the HW structure * @status: EEE status * * Get EEE status by guessing based on whether Tx or Rx LPI indications have * been received. **/ s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_get_eee_status_i354"); /* Check if EEE is supported on this device. */ if ((hw->phy.media_type != e1000_media_type_copper) || ((phy->id != M88E1543_E_PHY_ID) && (phy->id != M88E1512_E_PHY_ID))) goto out; ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, E1000_PCS_STATUS_DEV_I354, &phy_data); if (ret_val) goto out; *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false; out: return ret_val; } /* Due to a hw errata, if the host tries to configure the VFTA register * while performing queries from the BMC or DMA, then the VFTA in some * cases won't be written. */ /** * e1000_clear_vfta_i350 - Clear VLAN filter table * @hw: pointer to the HW structure * * Clears the register array which contains the VLAN filter table by * setting all the values to 0. **/ void e1000_clear_vfta_i350(struct e1000_hw *hw) { u32 offset; int i; DEBUGFUNC("e1000_clear_vfta_350"); for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { for (i = 0; i < 10; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); E1000_WRITE_FLUSH(hw); } } /** * e1000_write_vfta_i350 - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: register offset in VLAN filter table * @value: register value written to VLAN filter table * * Writes value at the given offset in the register array which stores * the VLAN filter table. **/ void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) { int i; DEBUGFUNC("e1000_write_vfta_350"); for (i = 0; i < 10; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); } /** * e1000_set_i2c_bb - Enable I2C bit-bang * @hw: pointer to the HW structure * * Enable I2C bit-bang interface * **/ s32 e1000_set_i2c_bb(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 ctrl_ext, i2cparams; DEBUGFUNC("e1000_set_i2c_bb"); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_I2C_ENA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS); i2cparams |= E1000_I2CBB_EN; i2cparams |= E1000_I2C_DATA_OE_N; i2cparams |= E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams); E1000_WRITE_FLUSH(hw); return ret_val; } /** * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * * Performs byte read operation over I2C interface at * a specified device address. **/ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { s32 status = E1000_SUCCESS; u32 max_retry = 10; u32 retry = 1; u16 swfw_mask = 0; bool nack = true; DEBUGFUNC("e1000_read_i2c_byte_generic"); swfw_mask = E1000_SWFW_PHY0_SM; do { if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto read_byte_out; } e1000_i2c_start(hw); /* Device Address and write indication */ status = e1000_clock_out_i2c_byte(hw, dev_addr); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, byte_offset); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; e1000_i2c_start(hw); /* Device Address and read indication */ status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1)); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_in_i2c_byte(hw, data); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_bit(hw, nack); if (status != E1000_SUCCESS) goto fail; e1000_i2c_stop(hw); break; fail: hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(100); e1000_i2c_bus_clear(hw); retry++; if (retry < max_retry) DEBUGOUT("I2C byte read error - Retrying.\n"); else DEBUGOUT("I2C byte read error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); read_byte_out: return status; } /** * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * * Performs byte write operation over I2C interface at * a specified device address. **/ s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { s32 status = E1000_SUCCESS; u32 max_retry = 1; u32 retry = 0; u16 swfw_mask = 0; DEBUGFUNC("e1000_write_i2c_byte_generic"); swfw_mask = E1000_SWFW_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto write_byte_out; } do { e1000_i2c_start(hw); status = e1000_clock_out_i2c_byte(hw, dev_addr); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, byte_offset); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, data); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; e1000_i2c_stop(hw); break; fail: e1000_i2c_bus_clear(hw); retry++; if (retry < max_retry) DEBUGOUT("I2C byte write error - Retrying.\n"); else DEBUGOUT("I2C byte write error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); write_byte_out: return status; } /** * e1000_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) **/ STATIC void e1000_i2c_start(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_i2c_start"); /* Start condition must begin with data and clock high */ e1000_set_i2c_data(hw, &i2cctl, 1); e1000_raise_i2c_clk(hw, &i2cctl); /* Setup time for start condition (4.7us) */ usec_delay(E1000_I2C_T_SU_STA); e1000_set_i2c_data(hw, &i2cctl, 0); /* Hold time for start condition (4us) */ usec_delay(E1000_I2C_T_HD_STA); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); } /** * e1000_i2c_stop - Sets I2C stop condition * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) **/ STATIC void e1000_i2c_stop(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_i2c_stop"); /* Stop condition must begin with data low and clock high */ e1000_set_i2c_data(hw, &i2cctl, 0); e1000_raise_i2c_clk(hw, &i2cctl); /* Setup time for stop condition (4us) */ usec_delay(E1000_I2C_T_SU_STO); e1000_set_i2c_data(hw, &i2cctl, 1); /* bus free time between stop and start (4.7us)*/ usec_delay(E1000_I2C_T_BUF); } /** * e1000_clock_in_i2c_byte - Clocks in one byte via I2C * @hw: pointer to hardware structure * @data: data byte to clock in * * Clocks in one byte data via I2C data/clock **/ STATIC s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data) { s32 i; bool bit = 0; DEBUGFUNC("e1000_clock_in_i2c_byte"); *data = 0; for (i = 7; i >= 0; i--) { e1000_clock_in_i2c_bit(hw, &bit); *data |= bit << i; } return E1000_SUCCESS; } /** * e1000_clock_out_i2c_byte - Clocks out one byte via I2C * @hw: pointer to hardware structure * @data: data byte clocked out * * Clocks out one byte data via I2C data/clock **/ STATIC s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data) { s32 status = E1000_SUCCESS; s32 i; u32 i2cctl; bool bit = 0; DEBUGFUNC("e1000_clock_out_i2c_byte"); for (i = 7; i >= 0; i--) { bit = (data >> i) & 0x1; status = e1000_clock_out_i2c_bit(hw, bit); if (status != E1000_SUCCESS) break; } /* Release SDA line (set high) */ i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); i2cctl |= E1000_I2C_DATA_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); E1000_WRITE_FLUSH(hw); return status; } /** * e1000_get_i2c_ack - Polls for I2C ACK * @hw: pointer to hardware structure * * Clocks in/out one bit via I2C data/clock **/ STATIC s32 e1000_get_i2c_ack(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; u32 i = 0; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 timeout = 10; bool ack = true; DEBUGFUNC("e1000_get_i2c_ack"); e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); /* Wait until SCL returns high */ for (i = 0; i < timeout; i++) { usec_delay(1); i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (i2cctl & E1000_I2C_CLK_IN) break; } if (!(i2cctl & E1000_I2C_CLK_IN)) return E1000_ERR_I2C; ack = e1000_get_i2c_data(&i2cctl); if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = E1000_ERR_I2C; } e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); return status; } /** * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock * @hw: pointer to hardware structure * @data: read data value * * Clocks in one bit via I2C data/clock **/ STATIC s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_clock_in_i2c_bit"); e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); *data = e1000_get_i2c_data(&i2cctl); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); return E1000_SUCCESS; } /** * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock * @hw: pointer to hardware structure * @data: data value to write * * Clocks out one bit via I2C data/clock **/ STATIC s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data) { s32 status; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_clock_out_i2c_bit"); status = e1000_set_i2c_data(hw, &i2cctl, data); if (status == E1000_SUCCESS) { e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us. * This also takes care of the data hold time. */ usec_delay(E1000_I2C_T_LOW); } else { status = E1000_ERR_I2C; DEBUGOUT1("I2C data was not set to %X\n", data); } return status; } /** * e1000_raise_i2c_clk - Raises the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' **/ STATIC void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) { DEBUGFUNC("e1000_raise_i2c_clk"); *i2cctl |= E1000_I2C_CLK_OUT; *i2cctl &= ~E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* SCL rise time (1000ns) */ usec_delay(E1000_I2C_T_RISE); } /** * e1000_lower_i2c_clk - Lowers the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' **/ STATIC void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) { DEBUGFUNC("e1000_lower_i2c_clk"); *i2cctl &= ~E1000_I2C_CLK_OUT; *i2cctl &= ~E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* SCL fall time (300ns) */ usec_delay(E1000_I2C_T_FALL); } /** * e1000_set_i2c_data - Sets the I2C data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit **/ STATIC s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data) { s32 status = E1000_SUCCESS; DEBUGFUNC("e1000_set_i2c_data"); if (data) *i2cctl |= E1000_I2C_DATA_OUT; else *i2cctl &= ~E1000_I2C_DATA_OUT; *i2cctl &= ~E1000_I2C_DATA_OE_N; *i2cctl |= E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA); *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (data != e1000_get_i2c_data(i2cctl)) { status = E1000_ERR_I2C; DEBUGOUT1("Error - I2C data was not set to %X.\n", data); } return status; } /** * e1000_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value **/ STATIC bool e1000_get_i2c_data(u32 *i2cctl) { bool data; DEBUGFUNC("e1000_get_i2c_data"); if (*i2cctl & E1000_I2C_DATA_IN) data = 1; else data = 0; return data; } /** * e1000_i2c_bus_clear - Clears the I2C bus * @hw: pointer to hardware structure * * Clears the I2C bus by sending nine clock pulses. * Used when data line is stuck low. **/ void e1000_i2c_bus_clear(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 i; DEBUGFUNC("e1000_i2c_bus_clear"); e1000_i2c_start(hw); e1000_set_i2c_data(hw, &i2cctl, 1); for (i = 0; i < 9; i++) { e1000_raise_i2c_clk(hw, &i2cctl); /* Min high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); e1000_lower_i2c_clk(hw, &i2cctl); /* Min low period of clock is 4.7us*/ usec_delay(E1000_I2C_T_LOW); } e1000_i2c_start(hw); /* Put the i2c bus back to default state */ e1000_i2c_stop(hw); } ================================================ FILE: drivers/net/e1000/base/e1000_82575.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_82575_H_ #define _E1000_82575_H_ #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ (ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_ON2)) /* * Receive Address Register Count * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * These entries are also used for MAC-based filtering. */ /* * For 82576, there are an additional set of RARs that begin at an offset * separate from the first set of RARs. */ #define E1000_RAR_ENTRIES_82575 16 #define E1000_RAR_ENTRIES_82576 24 #define E1000_RAR_ENTRIES_82580 24 #define E1000_RAR_ENTRIES_I350 32 #define E1000_SW_SYNCH_MB 0x00000100 #define E1000_STAT_DEV_RST_SET 0x00100000 #define E1000_CTRL_DEV_RST 0x20000000 #ifdef E1000_BIT_FIELDS struct e1000_adv_data_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { u32 data; struct { u32 datalen:16; /* Data buffer length */ u32 rsvd:4; u32 dtyp:4; /* Descriptor type */ u32 dcmd:8; /* Descriptor command */ } config; } lower; union { u32 data; struct { u32 status:4; /* Descriptor status */ u32 idx:4; u32 popts:6; /* Packet Options */ u32 paylen:18; /* Payload length */ } options; } upper; }; #define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */ #define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */ #define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */ #define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */ #define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */ #define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */ #define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */ #define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */ #define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */ #define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */ #define E1000_ADV_DCMD_RS 0x8 /* Report Status */ #define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */ #define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */ /* Extended Device Control */ #define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */ struct e1000_adv_context_desc { union { u32 ip_config; struct { u32 iplen:9; u32 maclen:7; u32 vlan_tag:16; } fields; } ip_setup; u32 seq_num; union { u64 l4_config; struct { u32 mkrloc:9; u32 tucmd:11; u32 dtyp:4; u32 adv:8; u32 rsvd:4; u32 idx:4; u32 l4len:8; u32 mss:16; } fields; } l4_setup; }; #endif /* SRRCTL bit definitions */ #define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ #define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00 #define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ #define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000 #define E1000_SRRCTL_TIMESTAMP 0x40000000 #define E1000_SRRCTL_DROP_EN 0x80000000 #define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F #define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00 #define E1000_TX_HEAD_WB_ENABLE 0x1 #define E1000_TX_SEQNUM_WB_ENABLE 0x2 #define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 #define E1000_MRQC_ENABLE_VMDQ 0x00000003 #define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 #define E1000_MRQC_ENABLE_RSS_8Q 0x00000002 #define E1000_VMRCTL_MIRROR_PORT_SHIFT 8 #define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << \ E1000_VMRCTL_MIRROR_PORT_SHIFT) #define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0) #define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1) #define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2) #define E1000_EICR_TX_QUEUE ( \ E1000_EICR_TX_QUEUE0 | \ E1000_EICR_TX_QUEUE1 | \ E1000_EICR_TX_QUEUE2 | \ E1000_EICR_TX_QUEUE3) #define E1000_EICR_RX_QUEUE ( \ E1000_EICR_RX_QUEUE0 | \ E1000_EICR_RX_QUEUE1 | \ E1000_EICR_RX_QUEUE2 | \ E1000_EICR_RX_QUEUE3) #define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE #define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE #define EIMS_ENABLE_MASK ( \ E1000_EIMS_RX_QUEUE | \ E1000_EIMS_TX_QUEUE | \ E1000_EIMS_TCP_TIMER | \ E1000_EIMS_OTHER) /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ #define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ #define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ #define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ #define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */ #define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */ #define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */ #define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */ #define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */ #define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */ #define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */ /* Receive Descriptor - Advanced */ union e1000_adv_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { __le32 data; struct { __le16 pkt_info; /*RSS type, Pkt type*/ /* Split Header, header buffer len */ __le16 hdr_info; } hs_rss; } lo_dword; union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; /* Packet length */ __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; #define E1000_RXDADV_RSSTYPE_MASK 0x0000000F #define E1000_RXDADV_RSSTYPE_SHIFT 12 #define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 #define E1000_RXDADV_SPLITHEADER_EN 0x00001000 #define E1000_RXDADV_SPH 0x8000 #define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */ #define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */ #define E1000_RXDADV_ERR_HBO 0x00800000 /* RSS Hash results */ #define E1000_RXDADV_RSSTYPE_NONE 0x00000000 #define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001 #define E1000_RXDADV_RSSTYPE_IPV4 0x00000002 #define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003 #define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004 #define E1000_RXDADV_RSSTYPE_IPV6 0x00000005 #define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006 #define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007 #define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008 #define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 /* RSS Packet Types as indicated in the receive descriptor */ #define E1000_RXDADV_PKTTYPE_ILMASK 0x000000F0 #define E1000_RXDADV_PKTTYPE_TLMASK 0x00000F00 #define E1000_RXDADV_PKTTYPE_NONE 0x00000000 #define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */ #define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */ #define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */ #define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */ #define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ #define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ #define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ #define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ #define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ #define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ #define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ #define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ #define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ /* LinkSec results */ /* Security Processing bit Indication */ #define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000 #define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 #define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 #define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 #define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 #define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000 #define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 #define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 #define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 #define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000 /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { __le64 buffer_addr; /* Address of descriptor's data buf */ __le32 cmd_type_len; __le32 olinfo_status; } read; struct { __le64 rsvd; /* Reserved */ __le32 nxtseq_seed; __le32 status; } wb; }; /* Adv Transmit Descriptor Config Masks */ #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ #define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ #define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ #define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on pkt */ #define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp pkt */ #define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED prsnt in WB */ #define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ #define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ /* 1st & Last TSO-full iSCSI PDU*/ #define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 #define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ /* Context descriptors */ struct e1000_adv_tx_context_desc { __le32 vlan_macip_lens; __le32 seqnum_seed; __le32 type_tucmd_mlhl; __le32 mss_l4len_idx; }; #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ #define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ #define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ #define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ /* IPSec Encrypt Enable for ESP */ #define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000 /* Req requires Markers and CRC */ #define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000 #define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ /* Adv ctxt IPSec SA IDX mask */ #define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF /* Adv ctxt IPSec ESP len mask */ #define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF /* Additional Transmit Descriptor Control definitions */ #define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ #define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wbk flushing */ /* Tx Queue Arbitration Priority 0=low, 1=high */ #define E1000_TXDCTL_PRIORITY 0x08000000 /* Additional Receive Descriptor Control definitions */ #define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */ #define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. wbk flushing */ /* Direct Cache Access (DCA) definitions */ #define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ #define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ #define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ #define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ #define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header ena */ #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload ena */ #define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx Desc Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ #define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ #define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ #define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ #define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */ #define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */ /* Additional interrupt register bit definitions */ #define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ #define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ #define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ /* ETQF register bit definitions */ #define E1000_ETQF_FILTER_ENABLE (1 << 26) #define E1000_ETQF_IMM_INT (1 << 29) #define E1000_ETQF_1588 (1 << 30) #define E1000_ETQF_QUEUE_ENABLE (1 << 31) /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters * here!! * * Current filters: * EAPOL 802.1x (0x888e): Filter 0 */ #define E1000_ETQF_FILTER_EAPOL 0 #define E1000_FTQF_VF_BP 0x00008000 #define E1000_FTQF_1588_TIME_STAMP 0x08000000 #define E1000_FTQF_MASK 0xF0000000 #define E1000_FTQF_MASK_PROTO_BP 0x10000000 #define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000 #define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000 #define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000 #define E1000_NVM_APME_82575 0x0400 #define MAX_NUM_VFS 7 #define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof cntrl */ #define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof cntrl */ #define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ #define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 #define E1000_DTXSWC_LLE_SHIFT 16 #define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ /* Easy defines for setting default pool, would normally be left a zero */ #define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 #define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) /* Other useful VMD_CTL register defines */ #define E1000_VT_CTL_IGNORE_MAC (1 << 28) #define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29) #define E1000_VT_CTL_VM_REPL_EN (1 << 30) /* Per VM Offload register setup */ #define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */ #define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ #define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */ #define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ #define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */ #define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */ #define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ #define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ #define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ #define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */ #define E1000_VMOLR_VPE 0x00800000 /* VLAN promiscuous enable */ #define E1000_VMOLR_UPE 0x20000000 /* Unicast promisuous enable */ #define E1000_DVMOLR_HIDVLAN 0x20000000 /* Vlan hiding enable */ #define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ #define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */ #define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */ #define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */ #define E1000_VLVF_ARRAY_SIZE 32 #define E1000_VLVF_VLANID_MASK 0x00000FFF #define E1000_VLVF_POOLSEL_SHIFT 12 #define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT) #define E1000_VLVF_LVLAN 0x00100000 #define E1000_VLVF_VLANID_ENABLE 0x80000000 #define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */ #define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */ #define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ #define E1000_IOVCTL 0x05BBC #define E1000_IOVCTL_REUSE_VFQ 0x00000001 #define E1000_RPLOLR_STRVLAN 0x40000000 #define E1000_RPLOLR_STRCRC 0x80000000 #define E1000_TCTL_EXT_COLD 0x000FFC00 #define E1000_TCTL_EXT_COLD_SHIFT 10 #define E1000_DTXCTL_8023LL 0x0004 #define E1000_DTXCTL_VLAN_ADDED 0x0008 #define E1000_DTXCTL_OOS_ENABLE 0x0010 #define E1000_DTXCTL_MDP_EN 0x0020 #define E1000_DTXCTL_SPOOF_INT 0x0040 #define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14) #define ALL_QUEUES 0xFFFF /* Rx packet buffer size defines */ #define E1000_RXPBS_SIZE_MASK_82576 0x0000007F void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable); void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf); void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable); s32 e1000_init_nvm_params_82575(struct e1000_hw *hw); s32 e1000_init_hw_82575(struct e1000_hw *hw); enum e1000_promisc_type { e1000_promisc_disabled = 0, /* all promisc modes disabled */ e1000_promisc_unicast = 1, /* unicast promiscuous enabled */ e1000_promisc_multicast = 2, /* multicast promiscuous enabled */ e1000_promisc_enabled = 3, /* both uni and multicast promisc */ e1000_num_promisc_types }; void e1000_vfta_set_vf(struct e1000_hw *, u16, bool); void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); s32 e1000_set_eee_i350(struct e1000_hw *); s32 e1000_set_eee_i354(struct e1000_hw *); s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *); s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw); /* I2C SDA and SCL timing parameters for standard mode */ #define E1000_I2C_T_HD_STA 4 #define E1000_I2C_T_LOW 5 #define E1000_I2C_T_HIGH 4 #define E1000_I2C_T_SU_STA 5 #define E1000_I2C_T_HD_DATA 5 #define E1000_I2C_T_SU_DATA 1 #define E1000_I2C_T_RISE 1 #define E1000_I2C_T_FALL 1 #define E1000_I2C_T_SU_STO 4 #define E1000_I2C_T_BUF 5 s32 e1000_set_i2c_bb(struct e1000_hw *hw); s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); void e1000_i2c_bus_clear(struct e1000_hw *hw); #endif /* _E1000_82575_H_ */ ================================================ FILE: drivers/net/e1000/base/e1000_api.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" /** * e1000_init_mac_params - Initialize MAC function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the MAC * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_mac_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->mac.ops.init_params) { ret_val = hw->mac.ops.init_params(hw); if (ret_val) { DEBUGOUT("MAC Initialization Error\n"); goto out; } } else { DEBUGOUT("mac.init_mac_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_nvm_params - Initialize NVM function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the NVM * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_nvm_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->nvm.ops.init_params) { ret_val = hw->nvm.ops.init_params(hw); if (ret_val) { DEBUGOUT("NVM Initialization Error\n"); goto out; } } else { DEBUGOUT("nvm.init_nvm_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_phy_params - Initialize PHY function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the PHY * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_phy_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->phy.ops.init_params) { ret_val = hw->phy.ops.init_params(hw); if (ret_val) { DEBUGOUT("PHY Initialization Error\n"); goto out; } } else { DEBUGOUT("phy.init_phy_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_mbx_params - Initialize mailbox function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the PHY * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_mbx_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->mbx.ops.init_params) { ret_val = hw->mbx.ops.init_params(hw); if (ret_val) { DEBUGOUT("Mailbox Initialization Error\n"); goto out; } } else { DEBUGOUT("mbx.init_mbx_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * device ID stored in the hw structure. * MUST BE FIRST FUNCTION CALLED (explicitly or through * e1000_setup_init_funcs()). **/ s32 e1000_set_mac_type(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_set_mac_type"); switch (hw->device_id) { case E1000_DEV_ID_82542: mac->type = e1000_82542; break; case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: mac->type = e1000_82543; break; case E1000_DEV_ID_82544EI_COPPER: case E1000_DEV_ID_82544EI_FIBER: case E1000_DEV_ID_82544GC_COPPER: case E1000_DEV_ID_82544GC_LOM: mac->type = e1000_82544; break; case E1000_DEV_ID_82540EM: case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82540EP: case E1000_DEV_ID_82540EP_LOM: case E1000_DEV_ID_82540EP_LP: mac->type = e1000_82540; break; case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_FIBER: mac->type = e1000_82545; break; case E1000_DEV_ID_82545GM_COPPER: case E1000_DEV_ID_82545GM_FIBER: case E1000_DEV_ID_82545GM_SERDES: mac->type = e1000_82545_rev_3; break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_QUAD_COPPER: mac->type = e1000_82546; break; case E1000_DEV_ID_82546GB_COPPER: case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82546GB_SERDES: case E1000_DEV_ID_82546GB_PCIE: case E1000_DEV_ID_82546GB_QUAD_COPPER: case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: mac->type = e1000_82546_rev_3; break; case E1000_DEV_ID_82541EI: case E1000_DEV_ID_82541EI_MOBILE: case E1000_DEV_ID_82541ER_LOM: mac->type = e1000_82541; break; case E1000_DEV_ID_82541ER: case E1000_DEV_ID_82541GI: case E1000_DEV_ID_82541GI_LF: case E1000_DEV_ID_82541GI_MOBILE: mac->type = e1000_82541_rev_2; break; case E1000_DEV_ID_82547EI: case E1000_DEV_ID_82547EI_MOBILE: mac->type = e1000_82547; break; case E1000_DEV_ID_82547GI: mac->type = e1000_82547_rev_2; break; case E1000_DEV_ID_82571EB_COPPER: case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82571EB_SERDES_DUAL: case E1000_DEV_ID_82571EB_SERDES_QUAD: case E1000_DEV_ID_82571EB_QUAD_COPPER: case E1000_DEV_ID_82571PT_QUAD_COPPER: case E1000_DEV_ID_82571EB_QUAD_FIBER: case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: mac->type = e1000_82571; break; case E1000_DEV_ID_82572EI: case E1000_DEV_ID_82572EI_COPPER: case E1000_DEV_ID_82572EI_FIBER: case E1000_DEV_ID_82572EI_SERDES: mac->type = e1000_82572; break; case E1000_DEV_ID_82573E: case E1000_DEV_ID_82573E_IAMT: case E1000_DEV_ID_82573L: mac->type = e1000_82573; break; case E1000_DEV_ID_82574L: case E1000_DEV_ID_82574LA: mac->type = e1000_82574; break; case E1000_DEV_ID_82583V: mac->type = e1000_82583; break; case E1000_DEV_ID_80003ES2LAN_COPPER_DPT: case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: case E1000_DEV_ID_80003ES2LAN_COPPER_SPT: case E1000_DEV_ID_80003ES2LAN_SERDES_SPT: mac->type = e1000_80003es2lan; break; case E1000_DEV_ID_ICH8_IFE: case E1000_DEV_ID_ICH8_IFE_GT: case E1000_DEV_ID_ICH8_IFE_G: case E1000_DEV_ID_ICH8_IGP_M: case E1000_DEV_ID_ICH8_IGP_M_AMT: case E1000_DEV_ID_ICH8_IGP_AMT: case E1000_DEV_ID_ICH8_IGP_C: case E1000_DEV_ID_ICH8_82567V_3: mac->type = e1000_ich8lan; break; case E1000_DEV_ID_ICH9_IFE: case E1000_DEV_ID_ICH9_IFE_GT: case E1000_DEV_ID_ICH9_IFE_G: case E1000_DEV_ID_ICH9_IGP_M: case E1000_DEV_ID_ICH9_IGP_M_AMT: case E1000_DEV_ID_ICH9_IGP_M_V: case E1000_DEV_ID_ICH9_IGP_AMT: case E1000_DEV_ID_ICH9_BM: case E1000_DEV_ID_ICH9_IGP_C: case E1000_DEV_ID_ICH10_R_BM_LM: case E1000_DEV_ID_ICH10_R_BM_LF: case E1000_DEV_ID_ICH10_R_BM_V: mac->type = e1000_ich9lan; break; case E1000_DEV_ID_ICH10_D_BM_LM: case E1000_DEV_ID_ICH10_D_BM_LF: case E1000_DEV_ID_ICH10_D_BM_V: mac->type = e1000_ich10lan; break; case E1000_DEV_ID_PCH_D_HV_DM: case E1000_DEV_ID_PCH_D_HV_DC: case E1000_DEV_ID_PCH_M_HV_LM: case E1000_DEV_ID_PCH_M_HV_LC: mac->type = e1000_pchlan; break; case E1000_DEV_ID_PCH2_LV_LM: case E1000_DEV_ID_PCH2_LV_V: mac->type = e1000_pch2lan; break; case E1000_DEV_ID_PCH_LPT_I217_LM: case E1000_DEV_ID_PCH_LPT_I217_V: case E1000_DEV_ID_PCH_LPTLP_I218_LM: case E1000_DEV_ID_PCH_LPTLP_I218_V: mac->type = e1000_pch_lpt; break; case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: mac->type = e1000_82575; break; case E1000_DEV_ID_82576: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: case E1000_DEV_ID_82576_NS: case E1000_DEV_ID_82576_NS_SERDES: case E1000_DEV_ID_82576_SERDES_QUAD: mac->type = e1000_82576; break; case E1000_DEV_ID_82580_COPPER: case E1000_DEV_ID_82580_FIBER: case E1000_DEV_ID_82580_SERDES: case E1000_DEV_ID_82580_SGMII: case E1000_DEV_ID_82580_COPPER_DUAL: case E1000_DEV_ID_82580_QUAD_FIBER: case E1000_DEV_ID_DH89XXCC_SGMII: case E1000_DEV_ID_DH89XXCC_SERDES: case E1000_DEV_ID_DH89XXCC_BACKPLANE: case E1000_DEV_ID_DH89XXCC_SFP: mac->type = e1000_82580; break; case E1000_DEV_ID_I350_COPPER: case E1000_DEV_ID_I350_FIBER: case E1000_DEV_ID_I350_SERDES: case E1000_DEV_ID_I350_SGMII: case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; case E1000_DEV_ID_I210_COPPER_FLASHLESS: case E1000_DEV_ID_I210_SERDES_FLASHLESS: case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: case E1000_DEV_ID_I210_FIBER: case E1000_DEV_ID_I210_SERDES: case E1000_DEV_ID_I210_SGMII: mac->type = e1000_i210; break; case E1000_DEV_ID_I211_COPPER: mac->type = e1000_i211; break; case E1000_DEV_ID_82576_VF: case E1000_DEV_ID_82576_VF_HV: mac->type = e1000_vfadapt; break; case E1000_DEV_ID_I350_VF: case E1000_DEV_ID_I350_VF_HV: mac->type = e1000_vfadapt_i350; break; case E1000_DEV_ID_I354_BACKPLANE_1GBPS: case E1000_DEV_ID_I354_SGMII: case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS: mac->type = e1000_i354; break; default: /* Should never have loaded on this device */ ret_val = -E1000_ERR_MAC_INIT; break; } return ret_val; } /** * e1000_setup_init_funcs - Initializes function pointers * @hw: pointer to the HW structure * @init_device: true will initialize the rest of the function pointers * getting the device ready for use. false will only set * MAC type and the function pointers for the other init * functions. Passing false will not generate any hardware * reads or writes. * * This function must be called by a driver in order to use the rest * of the 'shared' code files. Called by drivers only. **/ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) { s32 ret_val; /* Can't do much good without knowing the MAC type. */ ret_val = e1000_set_mac_type(hw); if (ret_val) { DEBUGOUT("ERROR: MAC type could not be set properly.\n"); goto out; } if (!hw->hw_addr) { DEBUGOUT("ERROR: Registers not mapped\n"); ret_val = -E1000_ERR_CONFIG; goto out; } /* * Init function pointers to generic implementations. We do this first * allowing a driver module to override it afterward. */ e1000_init_mac_ops_generic(hw); e1000_init_phy_ops_generic(hw); e1000_init_nvm_ops_generic(hw); e1000_init_mbx_ops_generic(hw); /* * Set up the init function pointers. These are functions within the * adapter family file that sets up function pointers for the rest of * the functions in that family. */ switch (hw->mac.type) { case e1000_82542: e1000_init_function_pointers_82542(hw); break; case e1000_82543: case e1000_82544: e1000_init_function_pointers_82543(hw); break; case e1000_82540: case e1000_82545: case e1000_82545_rev_3: case e1000_82546: case e1000_82546_rev_3: e1000_init_function_pointers_82540(hw); break; case e1000_82541: case e1000_82541_rev_2: case e1000_82547: case e1000_82547_rev_2: e1000_init_function_pointers_82541(hw); break; case e1000_82571: case e1000_82572: case e1000_82573: case e1000_82574: case e1000_82583: e1000_init_function_pointers_82571(hw); break; case e1000_80003es2lan: e1000_init_function_pointers_80003es2lan(hw); break; case e1000_ich8lan: case e1000_ich9lan: case e1000_ich10lan: case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: e1000_init_function_pointers_ich8lan(hw); break; case e1000_82575: case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: e1000_init_function_pointers_82575(hw); break; case e1000_i210: case e1000_i211: e1000_init_function_pointers_i210(hw); break; case e1000_vfadapt: e1000_init_function_pointers_vf(hw); break; case e1000_vfadapt_i350: e1000_init_function_pointers_vf(hw); break; default: DEBUGOUT("Hardware not supported\n"); ret_val = -E1000_ERR_CONFIG; break; } /* * Initialize the rest of the function pointers. These require some * register reads/writes in some cases. */ if (!(ret_val) && init_device) { ret_val = e1000_init_mac_params(hw); if (ret_val) goto out; ret_val = e1000_init_nvm_params(hw); if (ret_val) goto out; ret_val = e1000_init_phy_params(hw); if (ret_val) goto out; ret_val = e1000_init_mbx_params(hw); if (ret_val) goto out; } out: return ret_val; } /** * e1000_get_bus_info - Obtain bus information for adapter * @hw: pointer to the HW structure * * This will obtain information about the HW bus for which the * adapter is attached and stores it in the hw structure. This is a * function pointer entry point called by drivers. **/ s32 e1000_get_bus_info(struct e1000_hw *hw) { if (hw->mac.ops.get_bus_info) return hw->mac.ops.get_bus_info(hw); return E1000_SUCCESS; } /** * e1000_clear_vfta - Clear VLAN filter table * @hw: pointer to the HW structure * * This clears the VLAN filter table on the adapter. This is a function * pointer entry point called by drivers. **/ void e1000_clear_vfta(struct e1000_hw *hw) { if (hw->mac.ops.clear_vfta) hw->mac.ops.clear_vfta(hw); } /** * e1000_write_vfta - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: the 32-bit offset in which to write the value to. * @value: the 32-bit value to write at location offset. * * This writes a 32-bit value to a 32-bit offset in the VLAN filter * table. This is a function pointer entry point called by drivers. **/ void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) { if (hw->mac.ops.write_vfta) hw->mac.ops.write_vfta(hw, offset, value); } /** * e1000_update_mc_addr_list - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates the Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. **/ void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { if (hw->mac.ops.update_mc_addr_list) hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count); } /** * e1000_force_mac_fc - Force MAC flow control * @hw: pointer to the HW structure * * Force the MAC's flow control settings. Currently no func pointer exists * and all implementations are handled in the generic version of this * function. **/ s32 e1000_force_mac_fc(struct e1000_hw *hw) { return e1000_force_mac_fc_generic(hw); } /** * e1000_check_for_link - Check/Store link connection * @hw: pointer to the HW structure * * This checks the link condition of the adapter and stores the * results in the hw->mac structure. This is a function pointer entry * point called by drivers. **/ s32 e1000_check_for_link(struct e1000_hw *hw) { if (hw->mac.ops.check_for_link) return hw->mac.ops.check_for_link(hw); return -E1000_ERR_CONFIG; } /** * e1000_check_mng_mode - Check management mode * @hw: pointer to the HW structure * * This checks if the adapter has manageability enabled. * This is a function pointer entry point called by drivers. **/ bool e1000_check_mng_mode(struct e1000_hw *hw) { if (hw->mac.ops.check_mng_mode) return hw->mac.ops.check_mng_mode(hw); return false; } /** * e1000_mng_write_dhcp_info - Writes DHCP info to host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface * @length: size of the buffer * * Writes the DHCP information to the host interface. **/ s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) { return e1000_mng_write_dhcp_info_generic(hw, buffer, length); } /** * e1000_reset_hw - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. This is a function pointer * entry point called by drivers. **/ s32 e1000_reset_hw(struct e1000_hw *hw) { if (hw->mac.ops.reset_hw) return hw->mac.ops.reset_hw(hw); return -E1000_ERR_CONFIG; } /** * e1000_init_hw - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. This is a function * pointer entry point called by drivers. **/ s32 e1000_init_hw(struct e1000_hw *hw) { if (hw->mac.ops.init_hw) return hw->mac.ops.init_hw(hw); return -E1000_ERR_CONFIG; } /** * e1000_setup_link - Configures link and flow control * @hw: pointer to the HW structure * * This configures link and flow control settings for the adapter. This * is a function pointer entry point called by drivers. While modules can * also call this, they probably call their own version of this function. **/ s32 e1000_setup_link(struct e1000_hw *hw) { if (hw->mac.ops.setup_link) return hw->mac.ops.setup_link(hw); return -E1000_ERR_CONFIG; } /** * e1000_get_speed_and_duplex - Returns current speed and duplex * @hw: pointer to the HW structure * @speed: pointer to a 16-bit value to store the speed * @duplex: pointer to a 16-bit value to store the duplex. * * This returns the speed and duplex of the adapter in the two 'out' * variables passed in. This is a function pointer entry point called * by drivers. **/ s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) { if (hw->mac.ops.get_link_up_info) return hw->mac.ops.get_link_up_info(hw, speed, duplex); return -E1000_ERR_CONFIG; } /** * e1000_setup_led - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. This is a function pointer entry * point called by drivers. **/ s32 e1000_setup_led(struct e1000_hw *hw) { if (hw->mac.ops.setup_led) return hw->mac.ops.setup_led(hw); return E1000_SUCCESS; } /** * e1000_cleanup_led - Restores SW controllable LED * @hw: pointer to the HW structure * * This restores the SW controllable LED to the value saved off by * e1000_setup_led. This is a function pointer entry point called by drivers. **/ s32 e1000_cleanup_led(struct e1000_hw *hw) { if (hw->mac.ops.cleanup_led) return hw->mac.ops.cleanup_led(hw); return E1000_SUCCESS; } /** * e1000_blink_led - Blink SW controllable LED * @hw: pointer to the HW structure * * This starts the adapter LED blinking. Request the LED to be setup first * and cleaned up after. This is a function pointer entry point called by * drivers. **/ s32 e1000_blink_led(struct e1000_hw *hw) { if (hw->mac.ops.blink_led) return hw->mac.ops.blink_led(hw); return E1000_SUCCESS; } /** * e1000_id_led_init - store LED configurations in SW * @hw: pointer to the HW structure * * Initializes the LED config in SW. This is a function pointer entry point * called by drivers. **/ s32 e1000_id_led_init(struct e1000_hw *hw) { if (hw->mac.ops.id_led_init) return hw->mac.ops.id_led_init(hw); return E1000_SUCCESS; } /** * e1000_led_on - Turn on SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED on. This is a function pointer entry point * called by drivers. **/ s32 e1000_led_on(struct e1000_hw *hw) { if (hw->mac.ops.led_on) return hw->mac.ops.led_on(hw); return E1000_SUCCESS; } /** * e1000_led_off - Turn off SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED off. This is a function pointer entry point * called by drivers. **/ s32 e1000_led_off(struct e1000_hw *hw) { if (hw->mac.ops.led_off) return hw->mac.ops.led_off(hw); return E1000_SUCCESS; } /** * e1000_reset_adaptive - Reset adaptive IFS * @hw: pointer to the HW structure * * Resets the adaptive IFS. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ void e1000_reset_adaptive(struct e1000_hw *hw) { e1000_reset_adaptive_generic(hw); } /** * e1000_update_adaptive - Update adaptive IFS * @hw: pointer to the HW structure * * Updates adapter IFS. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ void e1000_update_adaptive(struct e1000_hw *hw) { e1000_update_adaptive_generic(hw); } /** * e1000_disable_pcie_master - Disable PCI-Express master access * @hw: pointer to the HW structure * * Disables PCI-Express master access and verifies there are no pending * requests. Currently no func pointer exists and all implementations are * handled in the generic version of this function. **/ s32 e1000_disable_pcie_master(struct e1000_hw *hw) { return e1000_disable_pcie_master_generic(hw); } /** * e1000_config_collision_dist - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ void e1000_config_collision_dist(struct e1000_hw *hw) { if (hw->mac.ops.config_collision_dist) hw->mac.ops.config_collision_dist(hw); } /** * e1000_rar_set - Sets a receive address register * @hw: pointer to the HW structure * @addr: address to set the RAR to * @index: the RAR to set * * Sets a Receive Address Register (RAR) to the specified address. **/ void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) { if (hw->mac.ops.rar_set) hw->mac.ops.rar_set(hw, addr, index); } /** * e1000_validate_mdi_setting - Ensures valid MDI/MDIX SW state * @hw: pointer to the HW structure * * Ensures that the MDI/MDIX SW state is valid. **/ s32 e1000_validate_mdi_setting(struct e1000_hw *hw) { if (hw->mac.ops.validate_mdi_setting) return hw->mac.ops.validate_mdi_setting(hw); return E1000_SUCCESS; } /** * e1000_hash_mc_addr - Determines address location in multicast table * @hw: pointer to the HW structure * @mc_addr: Multicast address to hash. * * This hashes an address to determine its location in the multicast * table. Currently no func pointer exists and all implementations * are handled in the generic version of this function. **/ u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) { return e1000_hash_mc_addr_generic(hw, mc_addr); } /** * e1000_enable_tx_pkt_filtering - Enable packet filtering on TX * @hw: pointer to the HW structure * * Enables packet filtering on transmit packets if manageability is enabled * and host interface is enabled. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw) { return e1000_enable_tx_pkt_filtering_generic(hw); } /** * e1000_mng_host_if_write - Writes to the manageability host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface buffer * @length: size of the buffer * @offset: location in the buffer to write to * @sum: sum of the data (not checksum) * * This function writes the buffer content at the offset given on the host if. * It also does alignment considerations to do the writes in most efficient * way. Also fills up the sum of the buffer in *buffer parameter. **/ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { return e1000_mng_host_if_write_generic(hw, buffer, length, offset, sum); } /** * e1000_mng_write_cmd_header - Writes manageability command header * @hw: pointer to the HW structure * @hdr: pointer to the host interface command header * * Writes the command header after does the checksum calculation. **/ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { return e1000_mng_write_cmd_header_generic(hw, hdr); } /** * e1000_mng_enable_host_if - Checks host interface is enabled * @hw: pointer to the HW structure * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ s32 e1000_mng_enable_host_if(struct e1000_hw *hw) { return e1000_mng_enable_host_if_generic(hw); } /** * e1000_check_reset_block - Verifies PHY can be reset * @hw: pointer to the HW structure * * Checks if the PHY is in a state that can be reset or if manageability * has it tied up. This is a function pointer entry point called by drivers. **/ s32 e1000_check_reset_block(struct e1000_hw *hw) { if (hw->phy.ops.check_reset_block) return hw->phy.ops.check_reset_block(hw); return E1000_SUCCESS; } /** * e1000_read_phy_reg - Reads PHY register * @hw: pointer to the HW structure * @offset: the register to read * @data: the buffer to store the 16-bit read. * * Reads the PHY register and returns the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) { if (hw->phy.ops.read_reg) return hw->phy.ops.read_reg(hw, offset, data); return E1000_SUCCESS; } /** * e1000_write_phy_reg - Writes PHY register * @hw: pointer to the HW structure * @offset: the register to write * @data: the value to write. * * Writes the PHY register at offset with the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) { if (hw->phy.ops.write_reg) return hw->phy.ops.write_reg(hw, offset, data); return E1000_SUCCESS; } /** * e1000_release_phy - Generic release PHY * @hw: pointer to the HW structure * * Return if silicon family does not require a semaphore when accessing the * PHY. **/ void e1000_release_phy(struct e1000_hw *hw) { if (hw->phy.ops.release) hw->phy.ops.release(hw); } /** * e1000_acquire_phy - Generic acquire PHY * @hw: pointer to the HW structure * * Return success if silicon family does not require a semaphore when * accessing the PHY. **/ s32 e1000_acquire_phy(struct e1000_hw *hw) { if (hw->phy.ops.acquire) return hw->phy.ops.acquire(hw); return E1000_SUCCESS; } /** * e1000_cfg_on_link_up - Configure PHY upon link up * @hw: pointer to the HW structure **/ s32 e1000_cfg_on_link_up(struct e1000_hw *hw) { if (hw->phy.ops.cfg_on_link_up) return hw->phy.ops.cfg_on_link_up(hw); return E1000_SUCCESS; } /** * e1000_read_kmrn_reg - Reads register using Kumeran interface * @hw: pointer to the HW structure * @offset: the register to read * @data: the location to store the 16-bit value read. * * Reads a register out of the Kumeran interface. Currently no func pointer * exists and all implementations are handled in the generic version of * this function. **/ s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) { return e1000_read_kmrn_reg_generic(hw, offset, data); } /** * e1000_write_kmrn_reg - Writes register using Kumeran interface * @hw: pointer to the HW structure * @offset: the register to write * @data: the value to write. * * Writes a register to the Kumeran interface. Currently no func pointer * exists and all implementations are handled in the generic version of * this function. **/ s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) { return e1000_write_kmrn_reg_generic(hw, offset, data); } /** * e1000_get_cable_length - Retrieves cable length estimation * @hw: pointer to the HW structure * * This function estimates the cable length and stores them in * hw->phy.min_length and hw->phy.max_length. This is a function pointer * entry point called by drivers. **/ s32 e1000_get_cable_length(struct e1000_hw *hw) { if (hw->phy.ops.get_cable_length) return hw->phy.ops.get_cable_length(hw); return E1000_SUCCESS; } /** * e1000_get_phy_info - Retrieves PHY information from registers * @hw: pointer to the HW structure * * This function gets some information from various PHY registers and * populates hw->phy values with it. This is a function pointer entry * point called by drivers. **/ s32 e1000_get_phy_info(struct e1000_hw *hw) { if (hw->phy.ops.get_info) return hw->phy.ops.get_info(hw); return E1000_SUCCESS; } /** * e1000_phy_hw_reset - Hard PHY reset * @hw: pointer to the HW structure * * Performs a hard PHY reset. This is a function pointer entry point called * by drivers. **/ s32 e1000_phy_hw_reset(struct e1000_hw *hw) { if (hw->phy.ops.reset) return hw->phy.ops.reset(hw); return E1000_SUCCESS; } /** * e1000_phy_commit - Soft PHY reset * @hw: pointer to the HW structure * * Performs a soft PHY reset on those that apply. This is a function pointer * entry point called by drivers. **/ s32 e1000_phy_commit(struct e1000_hw *hw) { if (hw->phy.ops.commit) return hw->phy.ops.commit(hw); return E1000_SUCCESS; } /** * e1000_set_d0_lplu_state - Sets low power link up state for D0 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D0 * and SmartSpeed is disabled when active is true, else clear lplu for D0 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. This is a function pointer entry point called by drivers. **/ s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) { if (hw->phy.ops.set_d0_lplu_state) return hw->phy.ops.set_d0_lplu_state(hw, active); return E1000_SUCCESS; } /** * e1000_set_d3_lplu_state - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. This is a function pointer entry point called by drivers. **/ s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) { if (hw->phy.ops.set_d3_lplu_state) return hw->phy.ops.set_d3_lplu_state(hw, active); return E1000_SUCCESS; } /** * e1000_read_mac_addr - Reads MAC address * @hw: pointer to the HW structure * * Reads the MAC address out of the adapter and stores it in the HW structure. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_mac_addr(struct e1000_hw *hw) { if (hw->mac.ops.read_mac_addr) return hw->mac.ops.read_mac_addr(hw); return e1000_read_mac_addr_generic(hw); } /** * e1000_read_pba_string - Read device part number string * @hw: pointer to the HW structure * @pba_num: pointer to device part number * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size) { return e1000_read_pba_string_generic(hw, pba_num, pba_num_size); } /** * e1000_read_pba_length - Read device part number string length * @hw: pointer to the HW structure * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number length from the EEPROM and * stores the value in pba_num. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size) { return e1000_read_pba_length_generic(hw, pba_num_size); } /** * e1000_read_pba_num - Read device part number * @hw: pointer to the HW structure * @pba_num: pointer to device part number * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num) { return e1000_read_pba_num_generic(hw, pba_num); } /** * e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum * @hw: pointer to the HW structure * * Validates the NVM checksum is correct. This is a function pointer entry * point called by drivers. **/ s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) { if (hw->nvm.ops.validate) return hw->nvm.ops.validate(hw); return -E1000_ERR_CONFIG; } /** * e1000_update_nvm_checksum - Updates NVM (EEPROM) checksum * @hw: pointer to the HW structure * * Updates the NVM checksum. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ s32 e1000_update_nvm_checksum(struct e1000_hw *hw) { if (hw->nvm.ops.update) return hw->nvm.ops.update(hw); return -E1000_ERR_CONFIG; } /** * e1000_reload_nvm - Reloads EEPROM * @hw: pointer to the HW structure * * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the * extended control register. **/ void e1000_reload_nvm(struct e1000_hw *hw) { if (hw->nvm.ops.reload) hw->nvm.ops.reload(hw); } /** * e1000_read_nvm - Reads NVM (EEPROM) * @hw: pointer to the HW structure * @offset: the word offset to read * @words: number of 16-bit words to read * @data: pointer to the properly sized buffer for the data. * * Reads 16-bit chunks of data from the NVM (EEPROM). This is a function * pointer entry point called by drivers. **/ s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { if (hw->nvm.ops.read) return hw->nvm.ops.read(hw, offset, words, data); return -E1000_ERR_CONFIG; } /** * e1000_write_nvm - Writes to NVM (EEPROM) * @hw: pointer to the HW structure * @offset: the word offset to read * @words: number of 16-bit words to write * @data: pointer to the properly sized buffer for the data. * * Writes 16-bit chunks of data to the NVM (EEPROM). This is a function * pointer entry point called by drivers. **/ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { if (hw->nvm.ops.write) return hw->nvm.ops.write(hw, offset, words, data); return E1000_SUCCESS; } /** * e1000_write_8bit_ctrl_reg - Writes 8bit Control register * @hw: pointer to the HW structure * @reg: 32bit register offset * @offset: the register to write * @data: the value to write. * * Writes the PHY register at offset with the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data) { return e1000_write_8bit_ctrl_reg_generic(hw, reg, offset, data); } /** * e1000_power_up_phy - Restores link in case of PHY power down * @hw: pointer to the HW structure * * The phy may be powered down to save power, to turn off link when the * driver is unloaded, or wake on lan is not enabled (among others). **/ void e1000_power_up_phy(struct e1000_hw *hw) { if (hw->phy.ops.power_up) hw->phy.ops.power_up(hw); e1000_setup_link(hw); } /** * e1000_power_down_phy - Power down PHY * @hw: pointer to the HW structure * * The phy may be powered down to save power, to turn off link when the * driver is unloaded, or wake on lan is not enabled (among others). **/ void e1000_power_down_phy(struct e1000_hw *hw) { if (hw->phy.ops.power_down) hw->phy.ops.power_down(hw); } /** * e1000_power_up_fiber_serdes_link - Power up serdes link * @hw: pointer to the HW structure * * Power on the optics and PCS. **/ void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw) { if (hw->mac.ops.power_up_serdes) hw->mac.ops.power_up_serdes(hw); } /** * e1000_shutdown_fiber_serdes_link - Remove link during power down * @hw: pointer to the HW structure * * Shutdown the optics and PCS on driver unload. **/ void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw) { if (hw->mac.ops.shutdown_serdes) hw->mac.ops.shutdown_serdes(hw); } ================================================ FILE: drivers/net/e1000/base/e1000_api.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_API_H_ #define _E1000_API_H_ #include "e1000_hw.h" extern void e1000_init_function_pointers_82542(struct e1000_hw *hw); extern void e1000_init_function_pointers_82543(struct e1000_hw *hw); extern void e1000_init_function_pointers_82540(struct e1000_hw *hw); extern void e1000_init_function_pointers_82571(struct e1000_hw *hw); extern void e1000_init_function_pointers_82541(struct e1000_hw *hw); extern void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw); extern void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw); extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw); extern void e1000_init_function_pointers_vf(struct e1000_hw *hw); extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_init_function_pointers_i210(struct e1000_hw *hw); s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr); s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_init_mac_params(struct e1000_hw *hw); s32 e1000_init_nvm_params(struct e1000_hw *hw); s32 e1000_init_phy_params(struct e1000_hw *hw); s32 e1000_init_mbx_params(struct e1000_hw *hw); s32 e1000_get_bus_info(struct e1000_hw *hw); void e1000_clear_vfta(struct e1000_hw *hw); void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); s32 e1000_force_mac_fc(struct e1000_hw *hw); s32 e1000_check_for_link(struct e1000_hw *hw); s32 e1000_reset_hw(struct e1000_hw *hw); s32 e1000_init_hw(struct e1000_hw *hw); s32 e1000_setup_link(struct e1000_hw *hw); s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_disable_pcie_master(struct e1000_hw *hw); void e1000_config_collision_dist(struct e1000_hw *hw); void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); s32 e1000_setup_led(struct e1000_hw *hw); s32 e1000_cleanup_led(struct e1000_hw *hw); s32 e1000_check_reset_block(struct e1000_hw *hw); s32 e1000_blink_led(struct e1000_hw *hw); s32 e1000_led_on(struct e1000_hw *hw); s32 e1000_led_off(struct e1000_hw *hw); s32 e1000_id_led_init(struct e1000_hw *hw); void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); s32 e1000_get_cable_length(struct e1000_hw *hw); s32 e1000_validate_mdi_setting(struct e1000_hw *hw); s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); s32 e1000_get_phy_info(struct e1000_hw *hw); void e1000_release_phy(struct e1000_hw *hw); s32 e1000_acquire_phy(struct e1000_hw *hw); s32 e1000_cfg_on_link_up(struct e1000_hw *hw); s32 e1000_phy_hw_reset(struct e1000_hw *hw); s32 e1000_phy_commit(struct e1000_hw *hw); void e1000_power_up_phy(struct e1000_hw *hw); void e1000_power_down_phy(struct e1000_hw *hw); s32 e1000_read_mac_addr(struct e1000_hw *hw); s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num); s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size); s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size); void e1000_reload_nvm(struct e1000_hw *hw); s32 e1000_update_nvm_checksum(struct e1000_hw *hw); s32 e1000_validate_nvm_checksum(struct e1000_hw *hw); s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); bool e1000_check_mng_mode(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); s32 e1000_mng_enable_host_if(struct e1000_hw *hw); s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum); s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); u32 e1000_translate_register_82542(u32 reg); /* * TBI_ACCEPT macro definition: * * This macro requires: * adapter = a pointer to struct e1000_hw * status = the 8 bit status field of the Rx descriptor with EOP set * error = the 8 bit error field of the Rx descriptor with EOP set * length = the sum of all the length fields of the Rx descriptors that * make up the current frame * last_byte = the last byte of the frame DMAed by the hardware * max_frame_length = the maximum frame length we want to accept. * min_frame_length = the minimum frame length we want to accept. * * This macro is a conditional that should be used in the interrupt * handler's Rx processing routine when RxErrors have been detected. * * Typical use: * ... * if (TBI_ACCEPT) { * accept_frame = true; * e1000_tbi_adjust_stats(adapter, MacAddress); * frame_length--; * } else { * accept_frame = false; * } * ... */ /* The carrier extension symbol, as received by the NIC. */ #define CARRIER_EXTENSION 0x0F #define TBI_ACCEPT(a, status, errors, length, last_byte, \ min_frame_size, max_frame_size) \ (e1000_tbi_sbp_enabled_82543(a) && \ (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ ((last_byte) == CARRIER_EXTENSION) && \ (((status) & E1000_RXD_STAT_VP) ? \ (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \ ((length) <= (max_frame_size + 1))) : \ (((length) > min_frame_size) && \ ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) #define E1000_MAX(a, b) ((a) > (b) ? (a) : (b)) #define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */ #endif /* _E1000_API_H_ */ ================================================ FILE: drivers/net/e1000/base/e1000_defines.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_DEFINES_H_ #define _E1000_DEFINES_H_ /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 /* Definitions for power management and wakeup registers */ /* Wake Up Control */ #define E1000_WUC_APME 0x00000001 /* APM Enable */ #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ #define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ #define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ /* Wake Up Filter Control */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ #define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ #define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ /* Wake Up Status */ #define E1000_WUS_LNKC E1000_WUFC_LNKC #define E1000_WUS_MAG E1000_WUFC_MAG #define E1000_WUS_EX E1000_WUFC_EX #define E1000_WUS_MC E1000_WUFC_MC #define E1000_WUS_BC E1000_WUFC_BC /* Extended Device Control */ #define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ #define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* SW Definable Pin 4 data */ #define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* SW Definable Pin 6 data */ #define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* SW Definable Pin 3 data */ /* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ #define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ #define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ #define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ #define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ /* Physical Func Reset Done Indication */ #define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_SDLPE 0X00040000 /* SerDes Low Power Enable */ #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clk Gating */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 /* Offset of the link mode field in Ctrl Ext register */ #define E1000_CTRL_EXT_LINK_MODE_OFFSET 22 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 #define E1000_CTRL_EXT_EIAME 0x01000000 #define E1000_CTRL_EXT_IRCA 0x00000001 #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_CTRL_EXT_LSECCK 0x00001000 #define E1000_CTRL_EXT_PHYPDEN 0x00100000 #define E1000_I2CCMD_REG_ADDR_SHIFT 16 #define E1000_I2CCMD_PHY_ADDR_SHIFT 24 #define E1000_I2CCMD_OPCODE_READ 0x08000000 #define E1000_I2CCMD_OPCODE_WRITE 0x00000000 #define E1000_I2CCMD_READY 0x20000000 #define E1000_I2CCMD_ERROR 0x80000000 #define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a)) #define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a)) #define E1000_MAX_SGMII_PHY_REG_ADDR 255 #define E1000_I2CCMD_PHY_TIMEOUT 200 #define E1000_IVAR_VALID 0x80 #define E1000_GPIE_NSICR 0x00000001 #define E1000_GPIE_MSIX_MODE 0x00000010 #define E1000_GPIE_EIAME 0x40000000 #define E1000_GPIE_PBA 0x80000000 /* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ #define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ #define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ #define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ #define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ #define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ #define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ #define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ #define E1000_RXDEXT_STATERR_LB 0x00040000 #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 #define E1000_RXDEXT_STATERR_SEQ 0x04000000 #define E1000_RXDEXT_STATERR_CXE 0x10000000 #define E1000_RXDEXT_STATERR_TCPE 0x20000000 #define E1000_RXDEXT_STATERR_IPE 0x40000000 #define E1000_RXDEXT_STATERR_RXE 0x80000000 /* mask to determine if packets should be dropped due to frame errors */ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ E1000_RXD_ERR_CE | \ E1000_RXD_ERR_SE | \ E1000_RXD_ERR_SEQ | \ E1000_RXD_ERR_CXE | \ E1000_RXD_ERR_RXE) /* Same mask, but for extended and packet split descriptors */ #define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ E1000_RXDEXT_STATERR_CE | \ E1000_RXDEXT_STATERR_SE | \ E1000_RXDEXT_STATERR_SEQ | \ E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) #if !defined(EXTERNAL_RELEASE) || defined(E1000E_MQ) #define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 #endif /* !EXTERNAL_RELEASE || E1000E_MQ */ #define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 #define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 /* Management Control */ #define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ #define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ /* Enable MAC address filtering */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MNG packets to host memory */ #define E1000_MANC_EN_MNG2HOST 0x00200000 #define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */ #define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */ #define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */ #define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ #define E1000_RCTL_EN 0x00000002 /* enable */ #define E1000_RCTL_SBP 0x00000004 /* store bad packet */ #define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */ #define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */ #define E1000_RCTL_LPE 0x00000020 /* long packet enable */ #define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ #define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ #define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */ #define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */ #define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ #define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */ #define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */ #define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */ #define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ #define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ #define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ #define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ #define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ /* Use byte values for the following shift parameters * Usage: * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & * E1000_PSRCTL_BSIZE0_MASK) | * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & * E1000_PSRCTL_BSIZE1_MASK) | * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & * E1000_PSRCTL_BSIZE2_MASK) | * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; * E1000_PSRCTL_BSIZE3_MASK)) * where value0 = [128..16256], default=256 * value1 = [1024..64512], default=4096 * value2 = [0..64512], default=4096 * value3 = [0..64512], default=0 */ #define E1000_PSRCTL_BSIZE0_MASK 0x0000007F #define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 #define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 #define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 #define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ #define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ #define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ #define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ /* SWFW_SYNC Definitions */ #define E1000_SWFW_EEP_SM 0x01 #define E1000_SWFW_PHY0_SM 0x02 #define E1000_SWFW_PHY1_SM 0x04 #define E1000_SWFW_CSR_SM 0x08 #define E1000_SWFW_PHY2_SM 0x20 #define E1000_SWFW_PHY3_SM 0x40 #define E1000_SWFW_SW_MNG_SM 0x400 /* Device Control */ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ #define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ #define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */ #define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ #define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ #define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ #define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ #define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ #define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ #define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ #define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ #define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ #define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ #define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ #define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ #define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ #define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ #define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ #define E1000_CTRL_RST 0x04000000 /* Global reset */ #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ #define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ #define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 #define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 #define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 #define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 #define E1000_CONNSW_ENRGSRC 0x4 #define E1000_CONNSW_PHYSD 0x400 #define E1000_CONNSW_PHY_PDN 0x800 #define E1000_CONNSW_SERDESD 0x200 #define E1000_CONNSW_AUTOSENSE_CONF 0x2 #define E1000_CONNSW_AUTOSENSE_EN 0x1 #define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_100 2 #define E1000_PCS_LCTL_FSV_1000 4 #define E1000_PCS_LCTL_FDV_FULL 8 #define E1000_PCS_LCTL_FSD 0x10 #define E1000_PCS_LCTL_FORCE_LINK 0x20 #define E1000_PCS_LCTL_FORCE_FCTRL 0x80 #define E1000_PCS_LCTL_AN_ENABLE 0x10000 #define E1000_PCS_LCTL_AN_RESTART 0x20000 #define E1000_PCS_LCTL_AN_TIMEOUT 0x40000 #define E1000_ENABLE_SERDES_LOOPBACK 0x0410 #define E1000_PCS_LSTS_LINK_OK 1 #define E1000_PCS_LSTS_SPEED_100 2 #define E1000_PCS_LSTS_SPEED_1000 4 #define E1000_PCS_LSTS_DUPLEX_FULL 8 #define E1000_PCS_LSTS_SYNK_OK 0x10 #define E1000_PCS_LSTS_AN_COMPLETE 0x10000 /* Device Status */ #define E1000_STATUS_FD 0x00000001 /* Duplex 0=half 1=full */ #define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ #define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ #define E1000_STATUS_FUNC_SHIFT 2 #define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ #define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ #define E1000_STATUS_SPEED_MASK 0x000000C0 #define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Compltn by NVM */ #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */ #define E1000_STATUS_2P5_SKU_OVER 0x00002000 /* Val of 2.5GBE SKU Over */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ /* Constants used to interpret the masked PCI-X bus speed. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus spd 50-66MHz */ #define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus spd 66-100MHz */ #define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus spd 100-133MHz*/ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 #define SPEED_2500 2500 #define HALF_DUPLEX 1 #define FULL_DUPLEX 2 #define PHY_FORCE_TIME 20 #define ADVERTISE_10_HALF 0x0001 #define ADVERTISE_10_FULL 0x0002 #define ADVERTISE_100_HALF 0x0004 #define ADVERTISE_100_FULL 0x0008 #define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ #define ADVERTISE_1000_FULL 0x0020 /* 1000/H is not supported, nor spec-compliant. */ #define E1000_ALL_SPEED_DUPLEX ( \ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ADVERTISE_100_FULL | ADVERTISE_1000_FULL) #define E1000_ALL_NOT_GIG ( \ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ADVERTISE_100_FULL) #define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) #define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) #define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX /* LED Control */ #define E1000_PHY_LED0_MODE_MASK 0x00000007 #define E1000_PHY_LED0_IVRT 0x00000008 #define E1000_PHY_LED0_MASK 0x0000001F #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 #define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 #define E1000_LEDCTL_MODE_LINK_UP 0x2 #define E1000_LEDCTL_MODE_LED_ON 0xE #define E1000_LEDCTL_MODE_LED_OFF 0xF /* Transmit Descriptor bit definitions */ #define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ #define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ #define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ #define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ #define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ #define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ #define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ #define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ #define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ #define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ #define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ #define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ #define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ #define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ #define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ #define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ #define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ #define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ /* Transmit Control */ #define E1000_TCTL_EN 0x00000002 /* enable Tx */ #define E1000_TCTL_PSP 0x00000008 /* pad short packets */ #define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ #define E1000_TCTL_COLD 0x003ff000 /* collision distance */ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ /* Transmit Arbitration Count */ #define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */ /* SerDes Control */ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 #define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 /* Receive Checksum Control */ #define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ #define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ #define E1000_RFCTL_NFSW_DIS 0x00000040 #define E1000_RFCTL_NFSR_DIS 0x00000080 #define E1000_RFCTL_ACK_DIS 0x00001000 #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 #define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 #define E1000_RFCTL_LEF 0x00040000 /* Collision related configuration parameters */ #define E1000_COLLISION_THRESHOLD 15 #define E1000_CT_SHIFT 4 #define E1000_COLLISION_DISTANCE 63 #define E1000_COLD_SHIFT 12 /* Default values for the transmit IPG register */ #define DEFAULT_82542_TIPG_IPGT 10 #define DEFAULT_82543_TIPG_IPGT_FIBER 9 #define DEFAULT_82543_TIPG_IPGT_COPPER 8 #define E1000_TIPG_IPGT_MASK 0x000003FF #define DEFAULT_82542_TIPG_IPGR1 2 #define DEFAULT_82543_TIPG_IPGR1 8 #define E1000_TIPG_IPGR1_SHIFT 10 #define DEFAULT_82542_TIPG_IPGR2 10 #define DEFAULT_82543_TIPG_IPGR2 6 #define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 /* Ethertype field values */ #define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ #define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x3F00 /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 #define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 #define E1000_PHY_CTRL_D0A_LPLU 0x00000002 #define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 #define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 #define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 #define E1000_KABGTXD_BGSQLBIAS 0x00050000 /* Low Power IDLE Control */ #define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */ /* PBA constants */ #define E1000_PBA_8K 0x0008 /* 8KB */ #define E1000_PBA_10K 0x000A /* 10KB */ #define E1000_PBA_12K 0x000C /* 12KB */ #define E1000_PBA_14K 0x000E /* 14KB */ #define E1000_PBA_16K 0x0010 /* 16KB */ #define E1000_PBA_18K 0x0012 #define E1000_PBA_20K 0x0014 #define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 #define E1000_PBA_26K 0x001A #define E1000_PBA_30K 0x001E #define E1000_PBA_32K 0x0020 #define E1000_PBA_34K 0x0022 #define E1000_PBA_35K 0x0023 #define E1000_PBA_38K 0x0026 #define E1000_PBA_40K 0x0028 #define E1000_PBA_48K 0x0030 /* 48KB */ #define E1000_PBA_64K 0x0040 /* 64KB */ #define E1000_PBA_RXA_MASK 0xFFFF #define E1000_PBS_16K E1000_PBA_16K /* Uncorrectable/correctable ECC Error counts and enable bits */ #define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF #define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 #define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 #define E1000_PBECCSTS_ECC_ENABLE 0x00010000 #define IFS_MAX 80 #define IFS_MIN 40 #define IFS_RATIO 4 #define IFS_STEP 10 #define MIN_NUM_XMITS 1000 /* SW Semaphore Register */ #define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ #define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ /* Interrupt Cause Read */ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ #define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */ #define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ #define E1000_ICR_RXO 0x00000040 /* Rx overrun */ #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ #define E1000_ICR_VMMB 0x00000100 /* VM MB event */ #define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ #define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ #define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ #define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ #define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ #define E1000_ICR_TXD_LOW 0x00008000 #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ #define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 #define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ #define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ #define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ #define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ #define E1000_ICR_FER 0x00400000 /* Fatal Error */ #define E1000_ICR_THS 0x00800000 /* ICR.THS: Thermal Sensor Event*/ #define E1000_ICR_MDDET 0x10000000 /* Malicious Driver Detect */ /* PBA ECC Register */ #define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ #define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */ #define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */ #define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ #define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */ /* Extended Interrupt Cause Read */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ #define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ #define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ #define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ #define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ #define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ #define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ #define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ #define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ /* TCP Timer */ #define E1000_TCPTIMER_KS 0x00000100 /* KickStart */ #define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */ #define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ #define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ /* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXT0 = Receiver Timer Interrupt (ring 0) * o TXDW = Transmit Descriptor Written Back * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) * o RXSEQ = Receive Sequence Error * o LSC = Link Status Change */ #define IMS_ENABLE_MASK ( \ E1000_IMS_RXT0 | \ E1000_IMS_TXDW | \ E1000_IMS_RXDMT0 | \ E1000_IMS_RXSEQ | \ E1000_IMS_LSC) /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */ #define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ #define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW #define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ #define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ #define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ #define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ #define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ #define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */ #define E1000_IMS_THS E1000_ICR_THS /* ICR.TS: Thermal Sensor Event*/ #define E1000_IMS_MDDET E1000_ICR_MDDET /* Malicious Driver Detect */ /* Extended Interrupt Mask Set */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ #define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ #define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ #define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ #define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ #define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ #define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ #define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ #define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ #define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ /* Extended Interrupt Cause Set */ #define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ #define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ #define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ #define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ #define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ #define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ #define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ #define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ #define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ #define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ #define E1000_EITR_ITR_INT_MASK 0x0000FFFF /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ #define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ #define E1000_EITR_INTERVAL 0x00007FFC /* Transmit Descriptor Control */ #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ #define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ /* Enable the counting of descriptors still to be processed. */ #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Flow Control Constants */ #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 #define FLOW_CONTROL_TYPE 0x8808 /* 802.1q VLAN Packet Size */ #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ /* Receive Address * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * Technically, we have 16 spots. However, we reserve one of these spots * (RAR[15]) for our directed address used by controllers with * manageability enabled, allowing us room for 15 multicast addresses. */ #define E1000_RAR_ENTRIES 15 #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ #define E1000_RAL_MAC_ADDR_LEN 4 #define E1000_RAH_MAC_ADDR_LEN 2 #define E1000_RAH_QUEUE_MASK_82575 0x000C0000 #define E1000_RAH_POOL_1 0x00040000 /* Error Codes */ #define E1000_SUCCESS 0 #define E1000_ERR_NVM 1 #define E1000_ERR_PHY 2 #define E1000_ERR_CONFIG 3 #define E1000_ERR_PARAM 4 #define E1000_ERR_MAC_INIT 5 #define E1000_ERR_PHY_TYPE 6 #define E1000_ERR_RESET 9 #define E1000_ERR_MASTER_REQUESTS_PENDING 10 #define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 #define E1000_ERR_SWFW_SYNC 13 #define E1000_NOT_IMPLEMENTED 14 #define E1000_ERR_MBX 15 #define E1000_ERR_INVALID_ARGUMENT 16 #define E1000_ERR_NO_SPACE 17 #define E1000_ERR_NVM_PBA_SECTION 18 #define E1000_ERR_I2C 19 #define E1000_ERR_INVM_VALUE_NOT_FOUND 20 /* Loop limit on how long we wait for auto-negotiation to complete */ #define FIBER_LINK_UP_LIMIT 50 #define COPPER_LINK_UP_LIMIT 10 #define PHY_AUTO_NEG_LIMIT 45 #define PHY_FORCE_LIMIT 20 /* Number of 100 microseconds we wait for PCI Express master disable */ #define MASTER_DISABLE_TIMEOUT 800 /* Number of milliseconds we wait for PHY configuration done after MAC reset */ #define PHY_CFG_TIMEOUT 100 /* Number of 2 milliseconds we wait for acquiring MDIO ownership. */ #define MDIO_OWNERSHIP_TIMEOUT 10 /* Number of milliseconds for NVM auto read done after MAC reset. */ #define AUTO_READ_DONE_TIMEOUT 10 /* Flow Control */ #define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ #define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ #define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ #define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ #define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ #define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ /* Receive Configuration Word */ #define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ #define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ #define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ #define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 #define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 #define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 #define E1000_TSYNCRXCTL_TYPE_ALL 0x08 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ #define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ #define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000 #define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000 #define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000 #define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000 #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 #define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 #define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02 #define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03 #define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04 #define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00 #define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000 #define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300 #define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800 #define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00 #define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00 #define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00 #define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 #define E1000_TIMINCA_16NS_SHIFT 24 #define E1000_TIMINCA_INCPERIOD_SHIFT 24 #define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF #define E1000_TSICR_TXTS 0x00000002 #define E1000_TSIM_TXTS 0x00000002 /* TUPLE Filtering Configuration */ #define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */ #define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */ #define E1000_TTQF_PROTOCOL_MASK 0xFF /* TTQF Protocol Mask */ /* TTQF TCP Bit, shift with E1000_TTQF_PROTOCOL SHIFT */ #define E1000_TTQF_PROTOCOL_TCP 0x0 /* TTQF UDP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ #define E1000_TTQF_PROTOCOL_UDP 0x1 /* TTQF SCTP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ #define E1000_TTQF_PROTOCOL_SCTP 0x2 #define E1000_TTQF_PROTOCOL_SHIFT 5 /* TTQF Protocol Shift */ #define E1000_TTQF_QUEUE_SHIFT 16 /* TTQF Queue Shfit */ #define E1000_TTQF_RX_QUEUE_MASK 0x70000 /* TTQF Queue Mask */ #define E1000_TTQF_MASK_ENABLE 0x10000000 /* TTQF Mask Enable Bit */ #define E1000_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */ #define E1000_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */ #define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */ #define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */ #define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */ #define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ #define E1000_MDICNFG_PHY_MASK 0x03E00000 #define E1000_MDICNFG_PHY_SHIFT 21 #define E1000_MEDIA_PORT_COPPER 1 #define E1000_MEDIA_PORT_OTHER 2 #define E1000_M88E1112_AUTO_COPPER_SGMII 0x2 #define E1000_M88E1112_AUTO_COPPER_BASEX 0x3 #define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */ #define E1000_M88E1112_MAC_CTRL_1 0x10 #define E1000_M88E1112_MAC_CTRL_1_MODE_MASK 0x0380 /* Mode Select */ #define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT 7 #define E1000_M88E1112_PAGE_ADDR 0x16 #define E1000_M88E1112_STATUS 0x01 #define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */ #define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */ #define E1000_THSTAT_HIGH_EVENT 0x00002000 /* High thermal threshold */ #define E1000_THSTAT_PWR_DOWN 0x00000001 /* Power Down Event */ #define E1000_THSTAT_LINK_THROTTLE 0x00000002 /* Link Spd Throttle Event */ /* I350 EEE defines */ #define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */ #define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */ #define E1000_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */ #define E1000_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */ #define E1000_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */ /* EEE status */ #define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ #define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */ #define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */ #define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */ #define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ #define E1000_M88E1543_EEE_CTRL_1 0x0 #define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ #define E1000_EEE_ADV_DEV_I354 7 #define E1000_EEE_ADV_ADDR_I354 60 #define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ #define E1000_EEE_ADV_1000_SUPPORTED (1 << 2) /* 1000BaseT EEE Supported */ #define E1000_PCS_STATUS_DEV_I354 3 #define E1000_PCS_STATUS_ADDR_I354 1 #define E1000_PCS_STATUS_RX_LPI_RCVD 0x0400 #define E1000_PCS_STATUS_TX_LPI_RCVD 0x0800 #define E1000_M88E1512_CFG_REG_1 0x0010 #define E1000_M88E1512_CFG_REG_2 0x0011 #define E1000_M88E1512_CFG_REG_3 0x0007 #define E1000_M88E1512_MODE 0x0014 #define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ #define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */ #define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */ /* PCI Express Control */ #define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 #define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 #define E1000_GCR_TXD_NO_SNOOP 0x00000008 #define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 #define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 #define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 #define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 #define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 #define E1000_GCR_CAP_VER2 0x00040000 #define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ E1000_GCR_RXDSCW_NO_SNOOP | \ E1000_GCR_RXDSCR_NO_SNOOP | \ E1000_GCR_TXD_NO_SNOOP | \ E1000_GCR_TXDSCW_NO_SNOOP | \ E1000_GCR_TXDSCR_NO_SNOOP) #define E1000_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */ /* mPHY address control and data registers */ #define E1000_MPHY_ADDR_CTL 0x0024 /* Address Control Reg */ #define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000 #define E1000_MPHY_DATA 0x0E10 /* Data Register */ /* AFE CSR Offset for PCS CLK */ #define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004 /* Override for near end digital loopback. */ #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ #define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ #define MII_CR_POWER_DOWN 0x0800 /* Power down */ #define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ #define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ #define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ #define MII_CR_SPEED_1000 0x0040 #define MII_CR_SPEED_100 0x2000 #define MII_CR_SPEED_10 0x0000 /* PHY Status Register */ #define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ #define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ #define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ #define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ #define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ #define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ #define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ #define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ #define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ #define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ #define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ #define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ #define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ #define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ #define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ /* Autoneg Advertisement Register */ #define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ #define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ #define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ #define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ #define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ #define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ #define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ #define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ #define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ #define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ /* Link Partner Ability Register (Base Page) */ #define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ #define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP 10T Half Dplx Capable */ #define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP 10T Full Dplx Capable */ #define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP 100TX Half Dplx Capable */ #define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP 100TX Full Dplx Capable */ #define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ #define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ #define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asym Pause Direction bit */ #define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP detected Remote Fault */ #define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP rx'd link code word */ #define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ /* Autoneg Expansion Register */ #define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ #define NWAY_ER_PAGE_RXD 0x0002 /* LP 10T Half Dplx Capable */ #define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP 10T Full Dplx Capable */ #define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP 100TX Half Dplx Capable */ #define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP 100TX Full Dplx Capable */ /* 1000BASE-T Control Register */ #define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ #define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ #define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ /* 1=Repeater/switch device port 0=DTE device */ #define CR_1000T_REPEATER_DTE 0x0400 /* 1=Configure PHY as Master 0=Configure PHY as Slave */ #define CR_1000T_MS_VALUE 0x0800 /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ #define CR_1000T_MS_ENABLE 0x1000 #define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ #define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ #define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ #define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ #define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ /* 1000BASE-T Status Register */ #define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle err since last rd */ #define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asym pause direction bit */ #define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ #define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ #define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ #define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ #define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx Master, 0=Slave */ #define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ #define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 /* PHY 1000 MII Register/Bit Definitions */ /* PHY Registers defined by IEEE */ #define PHY_CONTROL 0x00 /* Control Register */ #define PHY_STATUS 0x01 /* Status Register */ #define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ #define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ #define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */ #define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ #define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ /* NVM Control */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ #define E1000_EECD_DI 0x00000004 /* NVM Data In */ #define E1000_EECD_DO 0x00000008 /* NVM Data Out */ #define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ #define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ #define E1000_EECD_PRES 0x00000100 /* NVM Present */ #define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */ #define E1000_EECD_BLOCKED 0x00008000 /* Bit banging access blocked flag */ #define E1000_EECD_ABORT 0x00010000 /* NVM operation aborted flag */ #define E1000_EECD_TIMEOUT 0x00020000 /* NVM read operation timeout flag */ #define E1000_EECD_ERROR_CLR 0x00040000 /* NVM error status clear bit */ /* NVM Addressing bits based on type 0=small, 1=large */ #define E1000_EECD_ADDR_BITS 0x00000400 #define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */ #ifndef E1000_NVM_GRANT_ATTEMPTS #define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ #endif #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ #define E1000_EECD_SIZE_EX_SHIFT 11 #define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ #define E1000_EECD_AUPDEN 0x00100000 /* Ena Auto FLASH update */ #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) #define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done */ #define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */ #define E1000_EECD_SEC1VAL_I210 0x02000000 /* Sector One Valid */ #define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ #define E1000_I210_FIFO_SEL_RX 0x00 #define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i)) #define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) #define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 #define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 #define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */ /* Secure FLASH mode requires removing MSb */ #define E1000_I210_FW_PTR_MASK 0x7FFF /* Firmware code revision field word offset*/ #define E1000_I210_FW_VER_OFFSET 328 #define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ #define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ #define E1000_NVM_RW_REG_START 1 /* Start operation */ #define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ #define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ #define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */ #define E1000_FLASH_UPDATES 2000 /* NVM Word Offsets */ #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_VERSION 0x0005 #define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */ #define NVM_PHY_CLASS_WORD 0x0007 #define E1000_I210_NVM_FW_MODULE_PTR 0x0010 #define E1000_I350_NVM_FW_MODULE_PTR 0x0051 #define NVM_FUTURE_INIT_WORD1 0x0019 #define NVM_ETRACK_WORD 0x0042 #define NVM_ETRACK_HIWORD 0x0043 #define NVM_COMB_VER_OFF 0x0083 #define NVM_COMB_VER_PTR 0x003d /* NVM version defines */ #define NVM_MAJOR_MASK 0xF000 #define NVM_MINOR_MASK 0x0FF0 #define NVM_IMAGE_ID_MASK 0x000F #define NVM_COMB_VER_MASK 0x00FF #define NVM_MAJOR_SHIFT 12 #define NVM_MINOR_SHIFT 4 #define NVM_COMB_VER_SHFT 8 #define NVM_VER_INVALID 0xFFFF #define NVM_ETRACK_SHIFT 16 #define NVM_ETRACK_VALID 0x8000 #define NVM_NEW_DEC_MASK 0x0F00 #define NVM_HEX_CONV 16 #define NVM_HEX_TENS 10 /* FW version defines */ /* Offset of "Loader patch ptr" in Firmware Header */ #define E1000_I350_NVM_FW_LOADER_PATCH_PTR_OFFSET 0x01 /* Patch generation hour & minutes */ #define E1000_I350_NVM_FW_VER_WORD1_OFFSET 0x04 /* Patch generation month & day */ #define E1000_I350_NVM_FW_VER_WORD2_OFFSET 0x05 /* Patch generation year */ #define E1000_I350_NVM_FW_VER_WORD3_OFFSET 0x06 /* Patch major & minor numbers */ #define E1000_I350_NVM_FW_VER_WORD4_OFFSET 0x07 #define NVM_MAC_ADDR 0x0000 #define NVM_SUB_DEV_ID 0x000B #define NVM_SUB_VEN_ID 0x000C #define NVM_DEV_ID 0x000D #define NVM_VEN_ID 0x000E #define NVM_INIT_CTRL_2 0x000F #define NVM_INIT_CTRL_4 0x0013 #define NVM_LED_1_CFG 0x001C #define NVM_LED_0_2_CFG 0x001F #define NVM_COMPAT_VALID_CSUM 0x0001 #define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_3GIO_3 0x001A #define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020 #define NVM_INIT_CONTROL3_PORT_A 0x0024 #define NVM_CFG 0x0012 #define NVM_ALT_MAC_ADDR_PTR 0x0037 #define NVM_CHECKSUM_REG 0x003F #define NVM_COMPATIBILITY_REG_3 0x0003 #define NVM_COMPATIBILITY_BIT_MASK 0x8000 #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ #define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */ #define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */ #define NVM_82580_LAN_FUNC_OFFSET(a) ((a) ? (0x40 + (0x40 * (a))) : 0) /* Mask bits for fields in Word 0x24 of the NVM */ #define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */ #define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed extrnl */ /* Offset of Link Mode bits for 82575/82576 */ #define NVM_WORD24_LNK_MODE_OFFSET 8 /* Offset of Link Mode bits for 82580 up */ #define NVM_WORD24_82580_LNK_MODE_OFFSET 4 /* Mask bits for fields in Word 0x0f of the NVM */ #define NVM_WORD0F_PAUSE_MASK 0x3000 #define NVM_WORD0F_PAUSE 0x1000 #define NVM_WORD0F_ASM_DIR 0x2000 #define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0 /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C /* Mask bits for fields in Word 0x03 of the EEPROM */ #define NVM_COMPAT_LOM 0x0800 /* length of string needed to store PBA number */ #define E1000_PBANUM_LENGTH 11 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA /* PBA (printed board assembly) number words */ #define NVM_PBA_OFFSET_0 8 #define NVM_PBA_OFFSET_1 9 #define NVM_PBA_PTR_GUARD 0xFAFA #define NVM_RESERVED_WORD 0xFFFF #define NVM_PHY_CLASS_A 0x8000 #define NVM_SERDES_AMPLITUDE_MASK 0x000F #define NVM_SIZE_MASK 0x1C00 #define NVM_SIZE_SHIFT 10 #define NVM_WORD_SIZE_BASE_SHIFT 6 #define NVM_SWDPIO_EXT_SHIFT 4 /* NVM Commands - Microwire */ #define NVM_READ_OPCODE_MICROWIRE 0x6 /* NVM read opcode */ #define NVM_WRITE_OPCODE_MICROWIRE 0x5 /* NVM write opcode */ #define NVM_ERASE_OPCODE_MICROWIRE 0x7 /* NVM erase opcode */ #define NVM_EWEN_OPCODE_MICROWIRE 0x13 /* NVM erase/write enable */ #define NVM_EWDS_OPCODE_MICROWIRE 0x10 /* NVM erase/write disable */ /* NVM Commands - SPI */ #define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ #define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ #define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ #define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ #define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ #define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ /* SPI NVM Status Register */ #define NVM_STATUS_RDY_SPI 0x01 /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 #define ID_LED_RESERVED_FFFF 0xFFFF #define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ (ID_LED_OFF1_OFF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) #define ID_LED_DEF1_DEF2 0x1 #define ID_LED_DEF1_ON2 0x2 #define ID_LED_DEF1_OFF2 0x3 #define ID_LED_ON1_DEF2 0x4 #define ID_LED_ON1_ON2 0x5 #define ID_LED_ON1_OFF2 0x6 #define ID_LED_OFF1_DEF2 0x7 #define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_OFF2 0x9 #define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF #define IGP_ACTIVITY_LED_ENABLE 0x0300 #define IGP_LED3_MODE 0x07000000 /* PCI/PCI-X/PCI-EX Config space */ #define PCIX_COMMAND_REGISTER 0xE6 #define PCIX_STATUS_REGISTER_LO 0xE8 #define PCIX_STATUS_REGISTER_HI 0xEA #define PCI_HEADER_TYPE_REGISTER 0x0E #define PCIE_LINK_STATUS 0x12 #define PCIE_DEVICE_CONTROL2 0x28 #define PCIX_COMMAND_MMRBC_MASK 0x000C #define PCIX_COMMAND_MMRBC_SHIFT 0x2 #define PCIX_STATUS_HI_MMRBC_MASK 0x0060 #define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 #define PCIX_STATUS_HI_MMRBC_4K 0x3 #define PCIX_STATUS_HI_MMRBC_2K 0x2 #define PCIX_STATUS_LO_FUNC_MASK 0x7 #define PCI_HEADER_TYPE_MULTIFUNC 0x80 #define PCIE_LINK_WIDTH_MASK 0x3F0 #define PCIE_LINK_WIDTH_SHIFT 4 #define PCIE_LINK_SPEED_MASK 0x0F #define PCIE_LINK_SPEED_2500 0x01 #define PCIE_LINK_SPEED_5000 0x02 #define PCIE_DEVICE_CONTROL2_16ms 0x0005 #ifndef ETH_ADDR_LEN #define ETH_ADDR_LEN 6 #endif #define PHY_REVISION_MASK 0xFFFFFFF0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_MULTI_PAGE_REG 0xF /* Bit definitions for valid PHY IDs. * I = Integrated * E = External */ #define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 #define IGP01E1000_I_PHY_ID 0x02A80380 #define M88E1111_I_PHY_ID 0x01410CC0 #define M88E1543_E_PHY_ID 0x01410EA0 #define M88E1512_E_PHY_ID 0x01410DD0 #define M88E1112_E_PHY_ID 0x01410C90 #define I347AT4_E_PHY_ID 0x01410DC0 #define M88E1340M_E_PHY_ID 0x01410DF0 #define GG82563_E_PHY_ID 0x01410CA0 #define IGP03E1000_E_PHY_ID 0x02A80390 #define IFE_E_PHY_ID 0x02A80330 #define IFE_PLUS_E_PHY_ID 0x02A80320 #define IFE_C_E_PHY_ID 0x02A80310 #define BME1000_E_PHY_ID 0x01410CB0 #define BME1000_E_PHY_ID_R2 0x01410CB1 #define I82577_E_PHY_ID 0x01540050 #define I82578_E_PHY_ID 0x004DD040 #define I82579_E_PHY_ID 0x01540090 #define I217_E_PHY_ID 0x015400A0 #define I82580_I_PHY_ID 0x015403A0 #define I350_I_PHY_ID 0x015403B0 #define I210_I_PHY_ID 0x01410C00 #define IGP04E1000_E_PHY_ID 0x02A80391 #define M88_VENDOR 0x0141 /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Reg */ #define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Reg */ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Cntrl */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ #define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ #define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for pg number setting */ #define M88E1000_PHY_GEN_CONTROL 0x1E /* meaning depends on reg 29 */ #define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ #define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ /* M88E1000 PHY Specific Control Register */ #define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */ /* MDI Crossover Mode bits 6:5 Manual MDI configuration */ #define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ #define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* Auto crossover enabled all speeds */ #define M88E1000_PSCR_AUTO_X_MODE 0x0060 #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */ /* M88E1000 PHY Specific Status Register */ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ #define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ /* 0 = <50M * 1 = 50-80M * 2 = 80-110M * 3 = 110-140M * 4 = >140M */ #define M88E1000_PSSR_CABLE_LENGTH 0x0380 #define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ #define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ #define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ #define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ #define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 /* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 /* Number of times we will attempt to autonegotiate before downshifting if we * are the slave */ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ /* Intel I347AT4 Registers */ #define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */ #define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */ #define I347AT4_PAGE_SELECT 0x16 /* I347AT4 Extended PHY Specific Control Register */ /* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800 #define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000 #define I347AT4_PSCR_DOWNSHIFT_1X 0x0000 #define I347AT4_PSCR_DOWNSHIFT_2X 0x1000 #define I347AT4_PSCR_DOWNSHIFT_3X 0x2000 #define I347AT4_PSCR_DOWNSHIFT_4X 0x3000 #define I347AT4_PSCR_DOWNSHIFT_5X 0x4000 #define I347AT4_PSCR_DOWNSHIFT_6X 0x5000 #define I347AT4_PSCR_DOWNSHIFT_7X 0x6000 #define I347AT4_PSCR_DOWNSHIFT_8X 0x7000 /* I347AT4 PHY Cable Diagnostics Control */ #define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */ /* M88E1112 only registers */ #define M88E1112_VCT_DSP_DISTANCE 0x001A /* M88EC018 Rev 2 specific DownShift settings */ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 #define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 #define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C /* BME1000 PHY Specific Control Register */ #define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ /* Bits... * 15-5: page * 4-0: register offset */ #define GG82563_PAGE_SHIFT 5 #define GG82563_REG(page, reg) \ (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) #define GG82563_MIN_ALT_REG 30 /* GG82563 Specific Registers */ #define GG82563_PHY_SPEC_CTRL GG82563_REG(0, 16) /* PHY Spec Cntrl */ #define GG82563_PHY_PAGE_SELECT GG82563_REG(0, 22) /* Page Select */ #define GG82563_PHY_SPEC_CTRL_2 GG82563_REG(0, 26) /* PHY Spec Cntrl2 */ #define GG82563_PHY_PAGE_SELECT_ALT GG82563_REG(0, 29) /* Alt Page Select */ /* MAC Specific Control Register */ #define GG82563_PHY_MAC_SPEC_CTRL GG82563_REG(2, 21) #define GG82563_PHY_DSP_DISTANCE GG82563_REG(5, 26) /* DSP Distance */ /* Page 193 - Port Control Registers */ /* Kumeran Mode Control */ #define GG82563_PHY_KMRN_MODE_CTRL GG82563_REG(193, 16) #define GG82563_PHY_PWR_MGMT_CTRL GG82563_REG(193, 20) /* Pwr Mgt Ctrl */ /* Page 194 - KMRN Registers */ #define GG82563_PHY_INBAND_CTRL GG82563_REG(194, 18) /* Inband Ctrl */ /* MDI Control */ #define E1000_MDIC_REG_MASK 0x001F0000 #define E1000_MDIC_REG_SHIFT 16 #define E1000_MDIC_PHY_MASK 0x03E00000 #define E1000_MDIC_PHY_SHIFT 21 #define E1000_MDIC_OP_WRITE 0x04000000 #define E1000_MDIC_OP_READ 0x08000000 #define E1000_MDIC_READY 0x10000000 #define E1000_MDIC_ERROR 0x40000000 #define E1000_MDIC_DEST 0x80000000 /* SerDes Control */ #define E1000_GEN_CTL_READY 0x80000000 #define E1000_GEN_CTL_ADDRESS_SHIFT 8 #define E1000_GEN_POLL_TIMEOUT 640 /* LinkSec register fields */ #define E1000_LSECTXCAP_SUM_MASK 0x00FF0000 #define E1000_LSECTXCAP_SUM_SHIFT 16 #define E1000_LSECRXCAP_SUM_MASK 0x00FF0000 #define E1000_LSECRXCAP_SUM_SHIFT 16 #define E1000_LSECTXCTRL_EN_MASK 0x00000003 #define E1000_LSECTXCTRL_DISABLE 0x0 #define E1000_LSECTXCTRL_AUTH 0x1 #define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2 #define E1000_LSECTXCTRL_AISCI 0x00000020 #define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 #define E1000_LSECTXCTRL_RSV_MASK 0x000000D8 #define E1000_LSECRXCTRL_EN_MASK 0x0000000C #define E1000_LSECRXCTRL_EN_SHIFT 2 #define E1000_LSECRXCTRL_DISABLE 0x0 #define E1000_LSECRXCTRL_CHECK 0x1 #define E1000_LSECRXCTRL_STRICT 0x2 #define E1000_LSECRXCTRL_DROP 0x3 #define E1000_LSECRXCTRL_PLSH 0x00000040 #define E1000_LSECRXCTRL_RP 0x00000080 #define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 /* Tx Rate-Scheduler Config fields */ #define E1000_RTTBCNRC_RS_ENA 0x80000000 #define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF #define E1000_RTTBCNRC_RF_INT_SHIFT 14 #define E1000_RTTBCNRC_RF_INT_MASK \ (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT) /* DMA Coalescing register fields */ /* DMA Coalescing Watchdog Timer */ #define E1000_DMACR_DMACWT_MASK 0x00003FFF /* DMA Coalescing Rx Threshold */ #define E1000_DMACR_DMACTHR_MASK 0x00FF0000 #define E1000_DMACR_DMACTHR_SHIFT 16 /* Lx when no PCIe transactions */ #define E1000_DMACR_DMAC_LX_MASK 0x30000000 #define E1000_DMACR_DMAC_LX_SHIFT 28 #define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ /* DMA Coalescing BMC-to-OS Watchdog Enable */ #define E1000_DMACR_DC_BMC2OSW_EN 0x00008000 /* DMA Coalescing Transmit Threshold */ #define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF #define E1000_DMCTLX_TTLX_MASK 0x00000FFF /* Time to LX request */ /* Rx Traffic Rate Threshold */ #define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF /* Rx packet rate in current window */ #define E1000_DMCRTRH_LRPRCW 0x80000000 /* DMA Coal Rx Traffic Current Count */ #define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF /* Flow ctrl Rx Threshold High val */ #define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0 #define E1000_FCRTC_RTH_COAL_SHIFT 4 /* Lx power decision based on DMA coal */ #define E1000_PCIEMISC_LX_DECISION 0x00000080 #define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ #define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */ #define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */ /* Proxy Filter Control */ #define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */ #define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */ #define E1000_PROXYFC_MC 0x00000008 /* Directed MC Proxy */ #define E1000_PROXYFC_BC 0x00000010 /* Broadcast Proxy Enable */ #define E1000_PROXYFC_ARP_DIRECTED 0x00000020 /* Directed ARP Proxy Ena */ #define E1000_PROXYFC_IPV4 0x00000040 /* Directed IPv4 Enable */ #define E1000_PROXYFC_IPV6 0x00000080 /* Directed IPv6 Enable */ #define E1000_PROXYFC_NS 0x00000200 /* IPv6 Neighbor Solicitation */ #define E1000_PROXYFC_ARP 0x00000800 /* ARP Request Proxy Ena */ /* Proxy Status */ #define E1000_PROXYS_CLEAR 0xFFFFFFFF /* Clear */ /* Firmware Status */ #define E1000_FWSTS_FWRI 0x80000000 /* FW Reset Indication */ /* VF Control */ #define E1000_VTCTRL_RST 0x04000000 /* Reset VF */ #define E1000_STATUS_LAN_ID_MASK 0x00000000C /* Mask for Lan ID field */ /* Lan ID bit field offset in status register */ #define E1000_STATUS_LAN_ID_OFFSET 2 #define E1000_VFTA_ENTRIES 128 #ifndef E1000_UNUSEDARG #define E1000_UNUSEDARG #endif /* E1000_UNUSEDARG */ #ifndef ERROR_REPORT #define ERROR_REPORT(fmt) do { } while (0) #endif /* ERROR_REPORT */ #endif /* _E1000_DEFINES_H_ */ ================================================ FILE: drivers/net/e1000/base/e1000_hw.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ #include "e1000_osdep.h" #include "e1000_regs.h" #include "e1000_defines.h" struct e1000_hw; #define E1000_DEV_ID_82542 0x1000 #define E1000_DEV_ID_82543GC_FIBER 0x1001 #define E1000_DEV_ID_82543GC_COPPER 0x1004 #define E1000_DEV_ID_82544EI_COPPER 0x1008 #define E1000_DEV_ID_82544EI_FIBER 0x1009 #define E1000_DEV_ID_82544GC_COPPER 0x100C #define E1000_DEV_ID_82544GC_LOM 0x100D #define E1000_DEV_ID_82540EM 0x100E #define E1000_DEV_ID_82540EM_LOM 0x1015 #define E1000_DEV_ID_82540EP_LOM 0x1016 #define E1000_DEV_ID_82540EP 0x1017 #define E1000_DEV_ID_82540EP_LP 0x101E #define E1000_DEV_ID_82545EM_COPPER 0x100F #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82545GM_COPPER 0x1026 #define E1000_DEV_ID_82545GM_FIBER 0x1027 #define E1000_DEV_ID_82545GM_SERDES 0x1028 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82546GB_COPPER 0x1079 #define E1000_DEV_ID_82546GB_FIBER 0x107A #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A #define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EI_MOBILE 0x1018 #define E1000_DEV_ID_82541ER_LOM 0x1014 #define E1000_DEV_ID_82541ER 0x1078 #define E1000_DEV_ID_82541GI 0x1076 #define E1000_DEV_ID_82541GI_LF 0x107C #define E1000_DEV_ID_82541GI_MOBILE 0x1077 #define E1000_DEV_ID_82547EI 0x1019 #define E1000_DEV_ID_82547EI_MOBILE 0x101A #define E1000_DEV_ID_82547GI 0x1075 #define E1000_DEV_ID_82571EB_COPPER 0x105E #define E1000_DEV_ID_82571EB_FIBER 0x105F #define E1000_DEV_ID_82571EB_SERDES 0x1060 #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 #define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 #define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 #define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F #define E1000_DEV_ID_82572EI 0x10B9 #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82574L 0x10D3 #define E1000_DEV_ID_82574LA 0x10F6 #define E1000_DEV_ID_82583V 0x150C #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA #define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB #define E1000_DEV_ID_ICH8_82567V_3 0x1501 #define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 #define E1000_DEV_ID_ICH8_IGP_AMT 0x104A #define E1000_DEV_ID_ICH8_IGP_C 0x104B #define E1000_DEV_ID_ICH8_IFE 0x104C #define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 #define E1000_DEV_ID_ICH8_IFE_G 0x10C5 #define E1000_DEV_ID_ICH8_IGP_M 0x104D #define E1000_DEV_ID_ICH9_IGP_M 0x10BF #define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 #define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB #define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD #define E1000_DEV_ID_ICH9_BM 0x10E5 #define E1000_DEV_ID_ICH9_IGP_C 0x294C #define E1000_DEV_ID_ICH9_IFE 0x10C0 #define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 #define E1000_DEV_ID_ICH9_IFE_G 0x10C2 #define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC #define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD #define E1000_DEV_ID_ICH10_R_BM_V 0x10CE #define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE #define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF #define E1000_DEV_ID_ICH10_D_BM_V 0x1525 #define E1000_DEV_ID_PCH_M_HV_LM 0x10EA #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_DEV_ID_PCH2_LV_LM 0x1502 #define E1000_DEV_ID_PCH2_LV_V 0x1503 #define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A #define E1000_DEV_ID_PCH_LPT_I217_V 0x153B #define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A #define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526 #define E1000_DEV_ID_82576_NS 0x150A #define E1000_DEV_ID_82576_NS_SERDES 0x1518 #define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82576_VF 0x10CA #define E1000_DEV_ID_82576_VF_HV 0x152D #define E1000_DEV_ID_I350_VF 0x1520 #define E1000_DEV_ID_I350_VF_HV 0x152F #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 #define E1000_DEV_ID_82580_COPPER 0x150E #define E1000_DEV_ID_82580_FIBER 0x150F #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 #define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 #define E1000_DEV_ID_I350_COPPER 0x1521 #define E1000_DEV_ID_I350_FIBER 0x1522 #define E1000_DEV_ID_I350_SERDES 0x1523 #define E1000_DEV_ID_I350_SGMII 0x1524 #define E1000_DEV_ID_I350_DA4 0x1546 #define E1000_DEV_ID_I210_COPPER 0x1533 #define E1000_DEV_ID_I210_COPPER_OEM1 0x1534 #define E1000_DEV_ID_I210_COPPER_IT 0x1535 #define E1000_DEV_ID_I210_FIBER 0x1536 #define E1000_DEV_ID_I210_SERDES 0x1537 #define E1000_DEV_ID_I210_SGMII 0x1538 #define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B #define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C #define E1000_DEV_ID_I211_COPPER 0x1539 #define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40 #define E1000_DEV_ID_I354_SGMII 0x1F41 #define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45 #define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C #define E1000_DEV_ID_DH89XXCC_SFP 0x0440 #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 #define E1000_REVISION_3 3 #define E1000_REVISION_4 4 #define E1000_FUNC_0 0 #define E1000_FUNC_1 1 #define E1000_FUNC_2 2 #define E1000_FUNC_3 3 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9 enum e1000_mac_type { e1000_undefined = 0, e1000_82542, e1000_82543, e1000_82544, e1000_82540, e1000_82545, e1000_82545_rev_3, e1000_82546, e1000_82546_rev_3, e1000_82541, e1000_82541_rev_2, e1000_82547, e1000_82547_rev_2, e1000_82571, e1000_82572, e1000_82573, e1000_82574, e1000_82583, e1000_80003es2lan, e1000_ich8lan, e1000_ich9lan, e1000_ich10lan, e1000_pchlan, e1000_pch2lan, e1000_pch_lpt, e1000_82575, e1000_82576, e1000_82580, e1000_i350, e1000_i354, e1000_i210, e1000_i211, e1000_vfadapt, e1000_vfadapt_i350, e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ }; enum e1000_media_type { e1000_media_type_unknown = 0, e1000_media_type_copper = 1, e1000_media_type_fiber = 2, e1000_media_type_internal_serdes = 3, e1000_num_media_types }; enum e1000_nvm_type { e1000_nvm_unknown = 0, e1000_nvm_none, e1000_nvm_eeprom_spi, e1000_nvm_eeprom_microwire, e1000_nvm_flash_hw, e1000_nvm_invm, e1000_nvm_flash_sw }; enum e1000_nvm_override { e1000_nvm_override_none = 0, e1000_nvm_override_spi_small, e1000_nvm_override_spi_large, e1000_nvm_override_microwire_small, e1000_nvm_override_microwire_large }; enum e1000_phy_type { e1000_phy_unknown = 0, e1000_phy_none, e1000_phy_m88, e1000_phy_igp, e1000_phy_igp_2, e1000_phy_gg82563, e1000_phy_igp_3, e1000_phy_ife, e1000_phy_bm, e1000_phy_82578, e1000_phy_82577, e1000_phy_82579, e1000_phy_i217, e1000_phy_82580, e1000_phy_vf, e1000_phy_i210, }; enum e1000_bus_type { e1000_bus_type_unknown = 0, e1000_bus_type_pci, e1000_bus_type_pcix, e1000_bus_type_pci_express, e1000_bus_type_reserved }; enum e1000_bus_speed { e1000_bus_speed_unknown = 0, e1000_bus_speed_33, e1000_bus_speed_66, e1000_bus_speed_100, e1000_bus_speed_120, e1000_bus_speed_133, e1000_bus_speed_2500, e1000_bus_speed_5000, e1000_bus_speed_reserved }; enum e1000_bus_width { e1000_bus_width_unknown = 0, e1000_bus_width_pcie_x1, e1000_bus_width_pcie_x2, e1000_bus_width_pcie_x4 = 4, e1000_bus_width_pcie_x8 = 8, e1000_bus_width_32, e1000_bus_width_64, e1000_bus_width_reserved }; enum e1000_1000t_rx_status { e1000_1000t_rx_status_not_ok = 0, e1000_1000t_rx_status_ok, e1000_1000t_rx_status_undefined = 0xFF }; enum e1000_rev_polarity { e1000_rev_polarity_normal = 0, e1000_rev_polarity_reversed, e1000_rev_polarity_undefined = 0xFF }; enum e1000_fc_mode { e1000_fc_none = 0, e1000_fc_rx_pause, e1000_fc_tx_pause, e1000_fc_full, e1000_fc_default = 0xFF }; enum e1000_ffe_config { e1000_ffe_config_enabled = 0, e1000_ffe_config_active, e1000_ffe_config_blocked }; enum e1000_dsp_config { e1000_dsp_config_disabled = 0, e1000_dsp_config_enabled, e1000_dsp_config_activated, e1000_dsp_config_undefined = 0xFF }; enum e1000_ms_type { e1000_ms_hw_default = 0, e1000_ms_force_master, e1000_ms_force_slave, e1000_ms_auto }; enum e1000_smart_speed { e1000_smart_speed_default = 0, e1000_smart_speed_on, e1000_smart_speed_off }; enum e1000_serdes_link_state { e1000_serdes_link_down = 0, e1000_serdes_link_autoneg_progress, e1000_serdes_link_autoneg_complete, e1000_serdes_link_forced_up }; #define __le16 u16 #define __le32 u32 #define __le64 u64 /* Receive Descriptor */ struct e1000_rx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ __le16 length; /* Length of data DMAed into data buffer */ __le16 csum; /* Packet checksum */ u8 status; /* Descriptor status */ u8 errors; /* Descriptor Errors */ __le16 special; }; /* Receive Descriptor - Extended */ union e1000_rx_desc_extended { struct { __le64 buffer_addr; __le64 reserved; } read; struct { struct { __le32 mrq; /* Multiple Rx Queues */ union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; #define MAX_PS_BUFFERS 4 /* Number of packet split data buffers (not including the header buffer) */ #define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) /* Receive Descriptor - Packet Split */ union e1000_rx_desc_packet_split { struct { /* one buffer for protocol header(s), three data buffers */ __le64 buffer_addr[MAX_PS_BUFFERS]; } read; struct { struct { __le32 mrq; /* Multiple Rx Queues */ union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length0; /* length of buffer 0 */ __le16 vlan; /* VLAN tag */ } middle; struct { __le16 header_status; /* length of buffers 1-3 */ __le16 length[PS_PAGE_BUFFERS]; } upper; __le64 reserved; } wb; /* writeback */ }; /* Transmit Descriptor */ struct e1000_tx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 cso; /* Checksum offset */ u8 cmd; /* Descriptor control */ } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 css; /* Checksum start */ __le16 special; } fields; } upper; }; /* Offload Context Descriptor */ struct e1000_context_desc { union { __le32 ip_config; struct { u8 ipcss; /* IP checksum start */ u8 ipcso; /* IP checksum offset */ __le16 ipcse; /* IP checksum end */ } ip_fields; } lower_setup; union { __le32 tcp_config; struct { u8 tucss; /* TCP checksum start */ u8 tucso; /* TCP checksum offset */ __le16 tucse; /* TCP checksum end */ } tcp_fields; } upper_setup; __le32 cmd_and_length; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 hdr_len; /* Header length */ __le16 mss; /* Maximum segment size */ } fields; } tcp_seg_setup; }; /* Offload data descriptor */ struct e1000_data_desc { __le64 buffer_addr; /* Address of the descriptor's buffer address */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 typ_len_ext; u8 cmd; } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 popts; /* Packet Options */ __le16 special; } fields; } upper; }; /* Statistics counters collected by the MAC */ struct e1000_hw_stats { u64 crcerrs; u64 algnerrc; u64 symerrs; u64 rxerrc; u64 mpc; u64 scc; u64 ecol; u64 mcc; u64 latecol; u64 colc; u64 dc; u64 tncrs; u64 sec; u64 cexterr; u64 rlec; u64 xonrxc; u64 xontxc; u64 xoffrxc; u64 xofftxc; u64 fcruc; u64 prc64; u64 prc127; u64 prc255; u64 prc511; u64 prc1023; u64 prc1522; u64 gprc; u64 bprc; u64 mprc; u64 gptc; u64 gorc; u64 gotc; u64 rnbc; u64 ruc; u64 rfc; u64 roc; u64 rjc; u64 mgprc; u64 mgpdc; u64 mgptc; u64 tor; u64 tot; u64 tpr; u64 tpt; u64 ptc64; u64 ptc127; u64 ptc255; u64 ptc511; u64 ptc1023; u64 ptc1522; u64 mptc; u64 bptc; u64 tsctc; u64 tsctfc; u64 iac; u64 icrxptc; u64 icrxatc; u64 ictxptc; u64 ictxatc; u64 ictxqec; u64 ictxqmtc; u64 icrxdmtc; u64 icrxoc; u64 cbtmpc; u64 htdpmc; u64 cbrdpc; u64 cbrmpc; u64 rpthc; u64 hgptc; u64 htcbdpc; u64 hgorc; u64 hgotc; u64 lenerrs; u64 scvpc; u64 hrmpc; u64 doosync; u64 o2bgptc; u64 o2bspc; u64 b2ospc; u64 b2ogprc; }; struct e1000_vf_stats { u64 base_gprc; u64 base_gptc; u64 base_gorc; u64 base_gotc; u64 base_mprc; u64 base_gotlbc; u64 base_gptlbc; u64 base_gorlbc; u64 base_gprlbc; u32 last_gprc; u32 last_gptc; u32 last_gorc; u32 last_gotc; u32 last_mprc; u32 last_gotlbc; u32 last_gptlbc; u32 last_gorlbc; u32 last_gprlbc; u64 gprc; u64 gptc; u64 gorc; u64 gotc; u64 mprc; u64 gotlbc; u64 gptlbc; u64 gorlbc; u64 gprlbc; }; struct e1000_phy_stats { u32 idle_errors; u32 receive_errors; }; struct e1000_host_mng_dhcp_cookie { u32 signature; u8 status; u8 reserved0; u16 vlan_id; u32 reserved1; u16 reserved2; u8 reserved3; u8 checksum; }; /* Host Interface "Rev 1" */ struct e1000_host_command_header { u8 command_id; u8 command_length; u8 command_options; u8 checksum; }; #define E1000_HI_MAX_DATA_LENGTH 252 struct e1000_host_command_info { struct e1000_host_command_header command_header; u8 command_data[E1000_HI_MAX_DATA_LENGTH]; }; /* Host Interface "Rev 2" */ struct e1000_host_mng_command_header { u8 command_id; u8 checksum; u16 reserved1; u16 reserved2; u16 command_length; }; #define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 struct e1000_host_mng_command_info { struct e1000_host_mng_command_header command_header; u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; }; #include "e1000_mac.h" #include "e1000_phy.h" #include "e1000_nvm.h" #include "e1000_manage.h" #include "e1000_mbx.h" /* Function pointers for the MAC. */ struct e1000_mac_operations { s32 (*init_params)(struct e1000_hw *); s32 (*id_led_init)(struct e1000_hw *); s32 (*blink_led)(struct e1000_hw *); bool (*check_mng_mode)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); s32 (*cleanup_led)(struct e1000_hw *); void (*clear_hw_cntrs)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); s32 (*get_bus_info)(struct e1000_hw *); void (*set_lan_id)(struct e1000_hw *); s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); s32 (*led_on)(struct e1000_hw *); s32 (*led_off)(struct e1000_hw *); void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); void (*shutdown_serdes)(struct e1000_hw *); void (*power_up_serdes)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); s32 (*setup_physical_interface)(struct e1000_hw *); s32 (*setup_led)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); void (*config_collision_dist)(struct e1000_hw *); void (*rar_set)(struct e1000_hw *, u8*, u32); s32 (*read_mac_addr)(struct e1000_hw *); s32 (*validate_mdi_setting)(struct e1000_hw *); s32 (*acquire_swfw_sync)(struct e1000_hw *, u16); void (*release_swfw_sync)(struct e1000_hw *, u16); }; /* When to use various PHY register access functions: * * Func Caller * Function Does Does When to use * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * X_reg L,P,A n/a for simple PHY reg accesses * X_reg_locked P,A L for multiple accesses of different regs * on different pages * X_reg_page A L,P for multiple accesses of different regs * on the same page * * Where X=[read|write], L=locking, P=sets page, A=register access * */ struct e1000_phy_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); s32 (*cfg_on_link_up)(struct e1000_hw *); s32 (*check_polarity)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*commit)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_info)(struct e1000_hw *); s32 (*set_page)(struct e1000_hw *, u16); s32 (*read_reg)(struct e1000_hw *, u32, u16 *); s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *); void (*release)(struct e1000_hw *); s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); s32 (*write_reg)(struct e1000_hw *, u32, u16); s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); s32 (*write_reg_page)(struct e1000_hw *, u32, u16); void (*power_up)(struct e1000_hw *); void (*power_down)(struct e1000_hw *); s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *); s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8); }; /* Function pointers for the NVM. */ struct e1000_nvm_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); s32 (*read)(struct e1000_hw *, u16, u16, u16 *); void (*release)(struct e1000_hw *); void (*reload)(struct e1000_hw *); s32 (*update)(struct e1000_hw *); s32 (*valid_led_default)(struct e1000_hw *, u16 *); s32 (*validate)(struct e1000_hw *); s32 (*write)(struct e1000_hw *, u16, u16, u16 *); }; struct e1000_mac_info { struct e1000_mac_operations ops; u8 addr[ETH_ADDR_LEN]; u8 perm_addr[ETH_ADDR_LEN]; enum e1000_mac_type type; u32 collision_delta; u32 ledctl_default; u32 ledctl_mode1; u32 ledctl_mode2; u32 mc_filter_type; u32 tx_packet_delta; u32 txcw; u16 current_ifs_val; u16 ifs_max_val; u16 ifs_min_val; u16 ifs_ratio; u16 ifs_step_size; u16 mta_reg_count; u16 uta_reg_count; /* Maximum size of the MTA register table in all supported adapters */ #define MAX_MTA_REG 128 u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; u8 forced_speed_duplex; bool adaptive_ifs; bool has_fwsm; bool arc_subsystem_valid; bool asf_firmware_present; bool autoneg; bool autoneg_failed; bool get_link_status; bool in_ifs_mode; bool report_tx_early; enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; }; struct e1000_phy_info { struct e1000_phy_operations ops; enum e1000_phy_type type; enum e1000_1000t_rx_status local_rx; enum e1000_1000t_rx_status remote_rx; enum e1000_ms_type ms_type; enum e1000_ms_type original_ms_type; enum e1000_rev_polarity cable_polarity; enum e1000_smart_speed smart_speed; u32 addr; u32 id; u32 reset_delay_us; /* in usec */ u32 revision; enum e1000_media_type media_type; u16 autoneg_advertised; u16 autoneg_mask; u16 cable_length; u16 max_cable_length; u16 min_cable_length; u8 mdix; bool disable_polarity_correction; bool is_mdix; bool polarity_correction; bool speed_downgraded; bool autoneg_wait_to_complete; }; struct e1000_nvm_info { struct e1000_nvm_operations ops; enum e1000_nvm_type type; enum e1000_nvm_override override; u32 flash_bank_size; u32 flash_base_addr; u16 word_size; u16 delay_usec; u16 address_bits; u16 opcode_bits; u16 page_size; }; struct e1000_bus_info { enum e1000_bus_type type; enum e1000_bus_speed speed; enum e1000_bus_width width; u16 func; u16 pci_cmd_word; }; struct e1000_fc_info { u32 high_water; /* Flow control high-water mark */ u32 low_water; /* Flow control low-water mark */ u16 pause_time; /* Flow control pause timer */ u16 refresh_time; /* Flow control refresh timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ enum e1000_fc_mode current_mode; /* FC mode in effect */ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ }; struct e1000_mbx_operations { s32 (*init_params)(struct e1000_hw *hw); s32 (*read)(struct e1000_hw *, u32 *, u16, u16); s32 (*write)(struct e1000_hw *, u32 *, u16, u16); s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*check_for_msg)(struct e1000_hw *, u16); s32 (*check_for_ack)(struct e1000_hw *, u16); s32 (*check_for_rst)(struct e1000_hw *, u16); }; struct e1000_mbx_stats { u32 msgs_tx; u32 msgs_rx; u32 acks; u32 reqs; u32 rsts; }; struct e1000_mbx_info { struct e1000_mbx_operations ops; struct e1000_mbx_stats stats; u32 timeout; u32 usec_delay; u16 size; }; struct e1000_dev_spec_82541 { enum e1000_dsp_config dsp_config; enum e1000_ffe_config ffe_config; u16 spd_default; bool phy_init_script; }; struct e1000_dev_spec_82542 { bool dma_fairness; }; struct e1000_dev_spec_82543 { u32 tbi_compatibility; bool dma_fairness; bool init_phy_disabled; }; struct e1000_dev_spec_82571 { bool laa_is_present; u32 smb_counter; E1000_MUTEX swflag_mutex; }; struct e1000_dev_spec_80003es2lan { bool mdic_wa_enable; }; struct e1000_shadow_ram { u16 value; bool modified; }; #define E1000_SHADOW_RAM_WORDS 2048 #if defined(NAHUM6LP_HW) && defined(ULP_SUPPORT) /* I218 PHY Ultra Low Power (ULP) states */ enum e1000_ulp_state { e1000_ulp_state_unknown, e1000_ulp_state_off, e1000_ulp_state_on, }; #endif /* NAHUM6LP_HW && ULP_SUPPORT */ struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS]; E1000_MUTEX nvm_mutex; E1000_MUTEX swflag_mutex; bool nvm_k1_enabled; bool eee_disable; u16 eee_lp_ability; #if defined(NAHUM6LP_HW) && defined(ULP_SUPPORT) enum e1000_ulp_state ulp_state; #endif /* NAHUM6LP_HW && ULP_SUPPORT */ u16 lat_enc; u16 max_ltr_enc; bool smbus_disable; }; struct e1000_dev_spec_82575 { bool sgmii_active; bool global_device_reset; bool eee_disable; bool module_plugged; bool clear_semaphore_once; u32 mtu; struct sfp_e1000_flags eth_flags; u8 media_port; bool media_changed; }; struct e1000_dev_spec_vf { u32 vf_number; u32 v2p_mailbox; }; struct e1000_hw { void *back; u8 *hw_addr; u8 *flash_address; unsigned long io_base; struct e1000_mac_info mac; struct e1000_fc_info fc; struct e1000_phy_info phy; struct e1000_nvm_info nvm; struct e1000_bus_info bus; struct e1000_mbx_info mbx; struct e1000_host_mng_dhcp_cookie mng_cookie; union { struct e1000_dev_spec_82541 _82541; struct e1000_dev_spec_82542 _82542; struct e1000_dev_spec_82543 _82543; struct e1000_dev_spec_82571 _82571; struct e1000_dev_spec_80003es2lan _80003es2lan; struct e1000_dev_spec_ich8lan ich8lan; struct e1000_dev_spec_82575 _82575; struct e1000_dev_spec_vf vf; } dev_spec; u16 device_id; u16 subsystem_vendor_id; u16 subsystem_device_id; u16 vendor_id; u8 revision_id; }; #include "e1000_82541.h" #include "e1000_82543.h" #include "e1000_82571.h" #include "e1000_80003es2lan.h" #include "e1000_ich8lan.h" #include "e1000_82575.h" #include "e1000_i210.h" /* These functions must be implemented by drivers */ void e1000_pci_clear_mwi(struct e1000_hw *hw); void e1000_pci_set_mwi(struct e1000_hw *hw); s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); #endif ================================================ FILE: drivers/net/e1000/base/e1000_i210.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" STATIC s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); STATIC void e1000_release_nvm_i210(struct e1000_hw *hw); STATIC s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); STATIC s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); STATIC s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data); /** * e1000_acquire_nvm_i210 - Request for access to EEPROM * @hw: pointer to the HW structure * * Acquire the necessary semaphores for exclusive access to the EEPROM. * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ STATIC s32 e1000_acquire_nvm_i210(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_i210"); ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); return ret_val; } /** * e1000_release_nvm_i210 - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit, * then release the semaphores acquired. **/ STATIC void e1000_release_nvm_i210(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_i210"); e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); } /** * e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ DEBUGFUNC("e1000_acquire_swfw_sync_i210"); while (i < timeout) { if (e1000_get_hw_semaphore_i210(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } if (i == timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); out: return ret_val; } /** * e1000_release_swfw_sync_i210 - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; DEBUGFUNC("e1000_release_swfw_sync_i210"); while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); } /** * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ STATIC s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) { u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_i210"); /* Get the SW semaphore */ while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == timeout) { /* In rare circumstances, the SW semaphore may already be held * unintentionally. Clear the semaphore once before giving up. */ if (hw->dev_spec._82575.clear_semaphore_once) { hw->dev_spec._82575.clear_semaphore_once = false; e1000_put_hw_semaphore_generic(hw); for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); } } /* If we do not have the semaphore here, we have to give up. */ if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the Shadow Ram to read * @words: number of words to read * @data: word read from the Shadow Ram * * Reads a 16 bit word from the Shadow Ram using the EERD register. * Uses necessary synchronization semaphores. **/ s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = E1000_SUCCESS; u16 i, count; DEBUGFUNC("e1000_read_nvm_srrd_i210"); /* We cannot hold synchronization semaphores for too long, * because of forceful takeover procedure. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? E1000_EERD_EEWR_MAX_COUNT : (words - i); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { status = e1000_read_nvm_eerd(hw, offset, count, data + i); hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } if (status != E1000_SUCCESS) break; } return status; } /** * e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR * @hw: pointer to the HW structure * @offset: offset within the Shadow RAM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the Shadow RAM * * Writes data to Shadow RAM at offset using EEWR register. * * If e1000_update_nvm_checksum is not called after this function , the * data will not be committed to FLASH and also Shadow RAM will most likely * contain an invalid checksum. * * If error code is returned, data and Shadow RAM may be inconsistent - buffer * partially written. **/ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = E1000_SUCCESS; u16 i, count; DEBUGFUNC("e1000_write_nvm_srwr_i210"); /* We cannot hold synchronization semaphores for too long, * because of forceful takeover procedure. However it is more efficient * to write in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? E1000_EERD_EEWR_MAX_COUNT : (words - i); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { status = e1000_write_nvm_srwr(hw, offset, count, data + i); hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } if (status != E1000_SUCCESS) break; } return status; } /** * e1000_write_nvm_srwr - Write to Shadow Ram using EEWR * @hw: pointer to the HW structure * @offset: offset within the Shadow Ram to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the Shadow Ram * * Writes data to Shadow Ram at offset using EEWR register. * * If e1000_update_nvm_checksum is not called after this function , the * Shadow Ram will most likely contain an invalid checksum. **/ STATIC s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, k, eewr = 0; u32 attempts = 100000; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_nvm_srwr"); /* * A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } for (i = 0; i < words; i++) { eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | (data[i] << E1000_NVM_RW_REG_DATA) | E1000_NVM_RW_REG_START; E1000_WRITE_REG(hw, E1000_SRWR, eewr); for (k = 0; k < attempts; k++) { if (E1000_NVM_RW_REG_DONE & E1000_READ_REG(hw, E1000_SRWR)) { ret_val = E1000_SUCCESS; break; } usec_delay(5); } if (ret_val != E1000_SUCCESS) { DEBUGOUT("Shadow RAM write EEWR timed out\n"); break; } } out: return ret_val; } /** e1000_read_invm_word_i210 - Reads OTP * @hw: pointer to the HW structure * @address: the word address (aka eeprom offset) to read * @data: pointer to the data read * * Reads 16-bit words from the OTP. Return error when the word is not * stored in OTP. **/ STATIC s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) { s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; u32 invm_dword; u16 i; u8 record_type, word_address; DEBUGFUNC("e1000_read_invm_word_i210"); for (i = 0; i < E1000_INVM_SIZE; i++) { invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); /* Get record type */ record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) break; if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); if (word_address == address) { *data = INVM_DWORD_TO_WORD_DATA(invm_dword); DEBUGOUT2("Read INVM Word 0x%02x = %x", address, *data); status = E1000_SUCCESS; break; } } } if (status != E1000_SUCCESS) DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address); return status; } /** e1000_read_invm_i210 - Read invm wrapper function for I210/I211 * @hw: pointer to the HW structure * @address: the word address (aka eeprom offset) to read * @data: pointer to the data read * * Wrapper function to return data formerly found in the NVM. **/ STATIC s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset, u16 E1000_UNUSEDARG words, u16 *data) { s32 ret_val = E1000_SUCCESS; UNREFERENCED_1PARAMETER(words); DEBUGFUNC("e1000_read_invm_i210"); /* Only the MAC addr is required to be present in the iNVM */ switch (offset) { case NVM_MAC_ADDR: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]); ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1, &data[1]); ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2, &data[2]); if (ret_val != E1000_SUCCESS) DEBUGOUT("MAC Addr not found in iNVM\n"); break; case NVM_INIT_CTRL_2: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_INIT_CTRL_2_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_INIT_CTRL_4: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_INIT_CTRL_4_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_LED_1_CFG: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_LED_1_CFG_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_LED_0_2_CFG: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_LED_0_2_CFG_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_ID_LED_SETTINGS: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = ID_LED_RESERVED_FFFF; ret_val = E1000_SUCCESS; } break; case NVM_SUB_DEV_ID: *data = hw->subsystem_device_id; break; case NVM_SUB_VEN_ID: *data = hw->subsystem_vendor_id; break; case NVM_DEV_ID: *data = hw->device_id; break; case NVM_VEN_ID: *data = hw->vendor_id; break; default: DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset); *data = NVM_RESERVED_WORD; break; } return ret_val; } /** * e1000_read_invm_version - Reads iNVM version and image type * @hw: pointer to the HW structure * @invm_ver: version structure for the version read * * Reads iNVM version and image type. **/ s32 e1000_read_invm_version(struct e1000_hw *hw, struct e1000_fw_version *invm_ver) { u32 *record = NULL; u32 *next_record = NULL; u32 i = 0; u32 invm_dword = 0; u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / E1000_INVM_RECORD_SIZE_IN_BYTES); u32 buffer[E1000_INVM_SIZE]; s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; u16 version = 0; DEBUGFUNC("e1000_read_invm_version"); /* Read iNVM memory */ for (i = 0; i < E1000_INVM_SIZE; i++) { invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); buffer[i] = invm_dword; } /* Read version number */ for (i = 1; i < invm_blocks; i++) { record = &buffer[invm_blocks - i]; next_record = &buffer[invm_blocks - i + 1]; /* Check if we have first version location used */ if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { version = 0; status = E1000_SUCCESS; break; } /* Check if we have second version location used */ else if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; status = E1000_SUCCESS; break; } /* * Check if we have odd version location * used and it is the last one used */ else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && (i != 1))) { version = (*next_record & E1000_INVM_VER_FIELD_TWO) >> 13; status = E1000_SUCCESS; break; } /* * Check if we have even version location * used and it is the last one used */ else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && ((*record & 0x3) == 0)) { version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; status = E1000_SUCCESS; break; } } if (status == E1000_SUCCESS) { invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) >> E1000_INVM_MAJOR_SHIFT; invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; } /* Read Image Type */ for (i = 1; i < invm_blocks; i++) { record = &buffer[invm_blocks - i]; next_record = &buffer[invm_blocks - i + 1]; /* Check if we have image type in first location used */ if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { invm_ver->invm_img_type = 0; status = E1000_SUCCESS; break; } /* Check if we have image type in first location used */ else if ((((*record & 0x3) == 0) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || ((((*record & 0x3) != 0) && (i != 1)))) { invm_ver->invm_img_type = (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; status = E1000_SUCCESS; break; } } return status; } /** * e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); DEBUGFUNC("e1000_validate_nvm_checksum_i210"); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { /* * Replace the read function with semaphore grabbing with * the one that skips this for a while. * We have semaphore taken already here. */ read_op_ptr = hw->nvm.ops.read; hw->nvm.ops.read = e1000_read_nvm_eerd; status = e1000_validate_nvm_checksum_generic(hw); /* Revert original read operation. */ hw->nvm.ops.read = read_op_ptr; hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } return status; } /** * e1000_update_nvm_checksum_i210 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. Next commit EEPROM data onto the Flash. **/ s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum_i210"); /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data); if (ret_val != E1000_SUCCESS) { DEBUGOUT("EEPROM read failed\n"); goto out; } if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { /* * Do not use hw->nvm.ops.write, hw->nvm.ops.read * because we do not want to take the synchronization * semaphores twice here. */ for (i = 0; i < NVM_CHECKSUM_REG; i++) { ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data); if (ret_val) { hw->nvm.ops.release(hw); DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val != E1000_SUCCESS) { hw->nvm.ops.release(hw); DEBUGOUT("NVM Write Error while updating checksum.\n"); goto out; } hw->nvm.ops.release(hw); ret_val = e1000_update_flash_i210(hw); } else { ret_val = E1000_ERR_SWFW_SYNC; } out: return ret_val; } /** * e1000_get_flash_presence_i210 - Check if flash device is detected. * @hw: pointer to the HW structure * **/ bool e1000_get_flash_presence_i210(struct e1000_hw *hw) { u32 eec = 0; bool ret_val = false; DEBUGFUNC("e1000_get_flash_presence_i210"); eec = E1000_READ_REG(hw, E1000_EECD); if (eec & E1000_EECD_FLASH_DETECTED_I210) ret_val = true; return ret_val; } /** * e1000_update_flash_i210 - Commit EEPROM to the flash * @hw: pointer to the HW structure * **/ s32 e1000_update_flash_i210(struct e1000_hw *hw) { s32 ret_val; u32 flup; DEBUGFUNC("e1000_update_flash_i210"); ret_val = e1000_pool_flash_update_done_i210(hw); if (ret_val == -E1000_ERR_NVM) { DEBUGOUT("Flash update time out\n"); goto out; } flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210; E1000_WRITE_REG(hw, E1000_EECD, flup); ret_val = e1000_pool_flash_update_done_i210(hw); if (ret_val == E1000_SUCCESS) DEBUGOUT("Flash update complete\n"); else DEBUGOUT("Flash update time out\n"); out: return ret_val; } /** * e1000_pool_flash_update_done_i210 - Pool FLUDONE status. * @hw: pointer to the HW structure * **/ s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_NVM; u32 i, reg; DEBUGFUNC("e1000_pool_flash_update_done_i210"); for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { reg = E1000_READ_REG(hw, E1000_EECD); if (reg & E1000_EECD_FLUDONE_I210) { ret_val = E1000_SUCCESS; break; } usec_delay(5); } return ret_val; } /** * e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers * @hw: pointer to the HW structure * * Initialize the i210/i211 NVM parameters and function pointers. **/ STATIC s32 e1000_init_nvm_params_i210(struct e1000_hw *hw) { s32 ret_val; struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_params_i210"); ret_val = e1000_init_nvm_params_82575(hw); nvm->ops.acquire = e1000_acquire_nvm_i210; nvm->ops.release = e1000_release_nvm_i210; nvm->ops.valid_led_default = e1000_valid_led_default_i210; if (e1000_get_flash_presence_i210(hw)) { hw->nvm.type = e1000_nvm_flash_hw; nvm->ops.read = e1000_read_nvm_srrd_i210; nvm->ops.write = e1000_write_nvm_srwr_i210; nvm->ops.validate = e1000_validate_nvm_checksum_i210; nvm->ops.update = e1000_update_nvm_checksum_i210; } else { hw->nvm.type = e1000_nvm_invm; nvm->ops.read = e1000_read_invm_i210; nvm->ops.write = e1000_null_write_nvm; nvm->ops.validate = e1000_null_ops_generic; nvm->ops.update = e1000_null_ops_generic; } return ret_val; } /** * e1000_init_function_pointers_i210 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_i210(struct e1000_hw *hw) { e1000_init_function_pointers_82575(hw); hw->nvm.ops.init_params = e1000_init_nvm_params_i210; return; } /** * e1000_valid_led_default_i210 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ STATIC s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_i210"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { switch (hw->phy.media_type) { case e1000_media_type_internal_serdes: *data = ID_LED_DEFAULT_I210_SERDES; break; case e1000_media_type_copper: default: *data = ID_LED_DEFAULT_I210; break; } } out: return ret_val; } /** * __e1000_access_xmdio_reg - Read/write XMDIO register * @hw: pointer to the HW structure * @address: XMDIO address to program * @dev_addr: device address to program * @data: pointer to value to read/write from/to the XMDIO address * @read: boolean flag to indicate read or write **/ STATIC s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address, u8 dev_addr, u16 *data, bool read) { s32 ret_val; DEBUGFUNC("__e1000_access_xmdio_reg"); ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | dev_addr); if (ret_val) return ret_val; if (read) ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); else ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); if (ret_val) return ret_val; /* Recalibrate the device back to 0 */ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); if (ret_val) return ret_val; return ret_val; } /** * e1000_read_xmdio_reg - Read XMDIO register * @hw: pointer to the HW structure * @addr: XMDIO address to program * @dev_addr: device address to program * @data: value to be read from the EMI address **/ s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) { DEBUGFUNC("e1000_read_xmdio_reg"); return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, true); } /** * e1000_write_xmdio_reg - Write XMDIO register * @hw: pointer to the HW structure * @addr: XMDIO address to program * @dev_addr: device address to program * @data: value to be written to the XMDIO address **/ s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) { DEBUGFUNC("e1000_read_xmdio_reg"); return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, false); } /** * e1000_pll_workaround_i210 * @hw: pointer to the HW structure * * Works around an errata in the PLL circuit where it occasionally * provides the wrong clock frequency after power up. **/ STATIC s32 e1000_pll_workaround_i210(struct e1000_hw *hw) { s32 ret_val; u32 wuc, mdicnfg, ctrl_ext, reg_val; u16 nvm_word, phy_word, pci_word, tmp_nvm; int i; /* Get and set needed register values */ wuc = E1000_READ_REG(hw, E1000_WUC); mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); reg_val = mdicnfg & ~E1000_MDICNFG_EXT_MDIO; E1000_WRITE_REG(hw, E1000_MDICNFG, reg_val); /* Get data from NVM, or set default */ ret_val = e1000_read_invm_word_i210(hw, E1000_INVM_AUTOLOAD, &nvm_word); if (ret_val != E1000_SUCCESS) nvm_word = E1000_INVM_DEFAULT_AL; tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL; for (i = 0; i < E1000_MAX_PLL_TRIES; i++) { /* check current state */ hw->phy.ops.read_reg(hw, (E1000_PHY_PLL_FREQ_PAGE | E1000_PHY_PLL_FREQ_REG), &phy_word); if ((phy_word & E1000_PHY_PLL_UNCONF) != E1000_PHY_PLL_UNCONF) { ret_val = E1000_SUCCESS; break; } else { ret_val = -E1000_ERR_PHY; } hw->phy.ops.reset(hw); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= (E1000_CTRL_EXT_PHYPDEN | E1000_CTRL_EXT_SDLPE); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_REG(hw, E1000_WUC, 0); reg_val = (E1000_INVM_AUTOLOAD << 4) | (tmp_nvm << 16); E1000_WRITE_REG(hw, E1000_EEARBC, reg_val); e1000_read_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); pci_word |= E1000_PCI_PMCSR_D3; e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); msec_delay(1); pci_word &= ~E1000_PCI_PMCSR_D3; e1000_write_pci_cfg(hw, E1000_PCI_PMCSR, &pci_word); reg_val = (E1000_INVM_AUTOLOAD << 4) | (nvm_word << 16); E1000_WRITE_REG(hw, E1000_EEARBC, reg_val); /* restore WUC register */ E1000_WRITE_REG(hw, E1000_WUC, wuc); } /* restore MDICNFG setting */ E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); return ret_val; } /** * e1000_init_hw_i210 - Init hw for I210/I211 * @hw: pointer to the HW structure * * Called to initialize hw for i210 hw family. **/ s32 e1000_init_hw_i210(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_init_hw_i210"); if ((hw->mac.type >= e1000_i210) && !(e1000_get_flash_presence_i210(hw))) { ret_val = e1000_pll_workaround_i210(hw); if (ret_val != E1000_SUCCESS) return ret_val; } ret_val = e1000_init_hw_82575(hw); return ret_val; } ================================================ FILE: drivers/net/e1000/base/e1000_i210.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_I210_H_ #define _E1000_I210_H_ bool e1000_get_flash_presence_i210(struct e1000_hw *hw); s32 e1000_update_flash_i210(struct e1000_hw *hw); s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw); s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw); s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_invm_version(struct e1000_hw *hw, struct e1000_fw_version *invm_ver); s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data); s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data); s32 e1000_init_hw_i210(struct e1000_hw *hw); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 #define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \ (u8)((invm_dword) & 0x7) #define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \ (u8)(((invm_dword) & 0x0000FE00) >> 9) #define INVM_DWORD_TO_WORD_DATA(invm_dword) \ (u16)(((invm_dword) & 0xFFFF0000) >> 16) enum E1000_INVM_STRUCTURE_TYPE { E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00, E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01, E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02, E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03, E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04, E1000_INVM_INVALIDATED_STRUCTURE = 0x0F, }; #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 #define E1000_INVM_ULT_BYTES_SIZE 8 #define E1000_INVM_RECORD_SIZE_IN_BYTES 4 #define E1000_INVM_VER_FIELD_ONE 0x1FF8 #define E1000_INVM_VER_FIELD_TWO 0x7FE000 #define E1000_INVM_IMGTYPE_FIELD 0x1F800000 #define E1000_INVM_MAJOR_MASK 0x3F0 #define E1000_INVM_MINOR_MASK 0xF #define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_OFF2)) #define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_ON2)) /* NVM offset defaults for I211 devices */ #define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 #define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 #define NVM_LED_1_CFG_DEFAULT_I211 0x0184 #define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C /* PLL Defines */ #define E1000_PCI_PMCSR 0x44 #define E1000_PCI_PMCSR_D3 0x03 #define E1000_MAX_PLL_TRIES 5 #define E1000_PHY_PLL_UNCONF 0xFF #define E1000_PHY_PLL_FREQ_PAGE 0xFC0000 #define E1000_PHY_PLL_FREQ_REG 0x000E #define E1000_INVM_DEFAULT_AL 0x202F #define E1000_INVM_AUTOLOAD 0x0A #define E1000_INVM_PLL_WO_VAL 0x0010 #endif ================================================ FILE: drivers/net/e1000/base/e1000_ich8lan.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* 82562G 10/100 Network Connection * 82562G-2 10/100 Network Connection * 82562GT 10/100 Network Connection * 82562GT-2 10/100 Network Connection * 82562V 10/100 Network Connection * 82562V-2 10/100 Network Connection * 82566DC-2 Gigabit Network Connection * 82566DC Gigabit Network Connection * 82566DM-2 Gigabit Network Connection * 82566DM Gigabit Network Connection * 82566MC Gigabit Network Connection * 82566MM Gigabit Network Connection * 82567LM Gigabit Network Connection * 82567LF Gigabit Network Connection * 82567V Gigabit Network Connection * 82567LM-2 Gigabit Network Connection * 82567LF-2 Gigabit Network Connection * 82567V-2 Gigabit Network Connection * 82567LF-3 Gigabit Network Connection * 82567LM-3 Gigabit Network Connection * 82567LM-4 Gigabit Network Connection * 82577LM Gigabit Network Connection * 82577LC Gigabit Network Connection * 82578DM Gigabit Network Connection * 82578DC Gigabit Network Connection * 82579LM Gigabit Network Connection * 82579V Gigabit Network Connection * Ethernet Connection I217-LM * Ethernet Connection I217-V * Ethernet Connection I218-V * Ethernet Connection I218-LM */ #include "e1000_api.h" STATIC s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state); STATIC s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); STATIC void e1000_release_swflag_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw); STATIC void e1000_release_nvm_ich8lan(struct e1000_hw *hw); STATIC bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); STATIC bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); STATIC void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); STATIC void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); STATIC s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw); #ifndef NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT STATIC void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); #endif /* NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT */ STATIC s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); STATIC s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active); STATIC s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active); STATIC s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data); STATIC s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); STATIC s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_led_on_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_led_off_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); STATIC s32 e1000_setup_led_pchlan(struct e1000_hw *hw); STATIC s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); STATIC s32 e1000_led_on_pchlan(struct e1000_hw *hw); STATIC s32 e1000_led_off_pchlan(struct e1000_hw *hw); STATIC void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); STATIC void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 *data); STATIC s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 *data); STATIC s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); STATIC s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte); STATIC s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); STATIC void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw); STATIC s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); STATIC s32 e1000_k1_workaround_lv(struct e1000_hw *hw); STATIC void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { struct ich8_hsfsts { u16 flcdone:1; /* bit 0 Flash Cycle Done */ u16 flcerr:1; /* bit 1 Flash Cycle Error */ u16 dael:1; /* bit 2 Direct Access error Log */ u16 berasesz:2; /* bit 4:3 Sector Erase Size */ u16 flcinprog:1; /* bit 5 flash cycle in Progress */ u16 reserved1:2; /* bit 13:6 Reserved */ u16 reserved2:6; /* bit 13:6 Reserved */ u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */ u16 flockdn:1; /* bit 15 Flash Config Lock-Down */ } hsf_status; u16 regval; }; /* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ /* Offset 06h FLCTL */ union ich8_hws_flash_ctrl { struct ich8_hsflctl { u16 flcgo:1; /* 0 Flash Cycle Go */ u16 flcycle:2; /* 2:1 Flash Cycle */ u16 reserved:5; /* 7:3 Reserved */ u16 fldbcount:2; /* 9:8 Flash Data Byte Count */ u16 flockdn:6; /* 15:10 Reserved */ } hsf_ctrl; u16 regval; }; /* ICH Flash Region Access Permissions */ union ich8_hws_flash_regacc { struct ich8_flracc { u32 grra:8; /* 0:7 GbE region Read Access */ u32 grwa:8; /* 8:15 GbE region Write Access */ u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */ u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */ } hsf_flregacc; u16 regval; }; /** * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers * @hw: pointer to the HW structure * * Test access to the PHY registers by reading the PHY ID registers. If * the PHY ID is already known (e.g. resume path) compare it with known ID, * otherwise assume the read PHY ID is correct if it is valid. * * Assumes the sw/fw/hw semaphore is already acquired. **/ STATIC bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) { u16 phy_reg = 0; u32 phy_id = 0; s32 ret_val = 0; u16 retry_count; u32 mac_reg = 0; for (retry_count = 0; retry_count < 2; retry_count++) { ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg); if (ret_val || (phy_reg == 0xFFFF)) continue; phy_id = (u32)(phy_reg << 16); ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_reg); if (ret_val || (phy_reg == 0xFFFF)) { phy_id = 0; continue; } phy_id |= (u32)(phy_reg & PHY_REVISION_MASK); break; } if (hw->phy.id) { if (hw->phy.id == phy_id) goto out; } else if (phy_id) { hw->phy.id = phy_id; hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK); goto out; } /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ if (hw->mac.type < e1000_pch_lpt) { hw->phy.ops.release(hw); ret_val = e1000_set_mdio_slow_mode_hv(hw); if (!ret_val) ret_val = e1000_get_phy_id(hw); hw->phy.ops.acquire(hw); } if (ret_val) return false; out: if (hw->mac.type == e1000_pch_lpt) { /* Unforce SMBus mode in PHY */ hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg); phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg); /* Unforce SMBus mode in MAC */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); } return true; } /** * e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value * @hw: pointer to the HW structure * * Toggling the LANPHYPC pin value fully power-cycles the PHY and is * used to reset the PHY to a quiescent state when necessary. **/ STATIC void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) { u32 mac_reg; DEBUGFUNC("e1000_toggle_lanphypc_pch_lpt"); /* Set Phy Config Counter to 50msec */ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3); mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg); /* Toggle LANPHYPC Value bit */ mac_reg = E1000_READ_REG(hw, E1000_CTRL); mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); usec_delay(10); mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); E1000_WRITE_FLUSH(hw); if (hw->mac.type < e1000_pch_lpt) { msec_delay(50); } else { u16 count = 20; do { msec_delay(5); } while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) & E1000_CTRL_EXT_LPCD) && count--); msec_delay(30); } } /** * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds * @hw: pointer to the HW structure * * Workarounds/flow necessary for PHY initialization during driver load * and resume paths. **/ STATIC s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) { u32 mac_reg, fwsm = E1000_READ_REG(hw, E1000_FWSM); s32 ret_val; DEBUGFUNC("e1000_init_phy_workarounds_pchlan"); /* Gate automatic PHY configuration by hardware on managed and * non-managed 82579 and newer adapters. */ e1000_gate_hw_phy_config_ich8lan(hw, true); #if defined(NAHUM6LP_HW) && defined(ULP_SUPPORT) /* It is not possible to be certain of the current state of ULP * so forcibly disable it. */ hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown; #endif /* NAHUM6LP_HW && ULP_SUPPORT */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) { DEBUGOUT("Failed to initialize PHY flow\n"); goto out; } /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is * inaccessible and resetting the PHY is not blocked, toggle the * LANPHYPC Value bit to force the interconnect to PCIe mode. */ switch (hw->mac.type) { case e1000_pch_lpt: if (e1000_phy_is_accessible_pchlan(hw)) break; /* Before toggling LANPHYPC, see if PHY is accessible by * forcing MAC to SMBus mode first. */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); /* Wait 50 milliseconds for MAC to finish any retries * that it might be trying to perform from previous * attempts to acknowledge any phy read requests. */ msec_delay(50); /* fall-through */ case e1000_pch2lan: if (e1000_phy_is_accessible_pchlan(hw)) break; /* fall-through */ case e1000_pchlan: if ((hw->mac.type == e1000_pchlan) && (fwsm & E1000_ICH_FWSM_FW_VALID)) break; if (hw->phy.ops.check_reset_block(hw)) { DEBUGOUT("Required LANPHYPC toggle blocked by ME\n"); ret_val = -E1000_ERR_PHY; break; } /* Toggle LANPHYPC Value bit */ e1000_toggle_lanphypc_pch_lpt(hw); if (hw->mac.type >= e1000_pch_lpt) { if (e1000_phy_is_accessible_pchlan(hw)) break; /* Toggling LANPHYPC brings the PHY out of SMBus mode * so ensure that the MAC is also out of SMBus mode */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); if (e1000_phy_is_accessible_pchlan(hw)) break; ret_val = -E1000_ERR_PHY; } break; default: break; } hw->phy.ops.release(hw); if (!ret_val) { /* Check to see if able to reset PHY. Print error if not */ if (hw->phy.ops.check_reset_block(hw)) { ERROR_REPORT("Reset blocked by ME\n"); goto out; } /* Reset the PHY before any access to it. Doing so, ensures * that the PHY is in a known good state before we read/write * PHY registers. The generic reset is sufficient here, * because we haven't determined the PHY type yet. */ ret_val = e1000_phy_hw_reset_generic(hw); if (ret_val) goto out; /* On a successful reset, possibly need to wait for the PHY * to quiesce to an accessible state before returning control * to the calling function. If the PHY does not quiesce, then * return E1000E_BLK_PHY_RESET, as this is the condition that * the PHY is in. */ ret_val = hw->phy.ops.check_reset_block(hw); if (ret_val) ERROR_REPORT("ME blocked access to PHY after reset\n"); } out: /* Ungate automatic PHY configuration on non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && !(fwsm & E1000_ICH_FWSM_FW_VALID)) { msec_delay(10); e1000_gate_hw_phy_config_ich8lan(hw, false); } return ret_val; } /** * e1000_init_phy_params_pchlan - Initialize PHY function pointers * @hw: pointer to the HW structure * * Initialize family-specific PHY parameters and function pointers. **/ STATIC s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("e1000_init_phy_params_pchlan"); phy->addr = 1; phy->reset_delay_us = 100; phy->ops.acquire = e1000_acquire_swflag_ich8lan; phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; phy->ops.set_page = e1000_set_page_igp; phy->ops.read_reg = e1000_read_phy_reg_hv; phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; phy->ops.release = e1000_release_swflag_ich8lan; phy->ops.reset = e1000_phy_hw_reset_ich8lan; phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; phy->ops.write_reg = e1000_write_phy_reg_hv; phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->id = e1000_phy_unknown; ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) return ret_val; if (phy->id == e1000_phy_unknown) switch (hw->mac.type) { default: ret_val = e1000_get_phy_id(hw); if (ret_val) return ret_val; if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) break; /* fall-through */ case e1000_pch2lan: case e1000_pch_lpt: /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ ret_val = e1000_set_mdio_slow_mode_hv(hw); if (ret_val) return ret_val; ret_val = e1000_get_phy_id(hw); if (ret_val) return ret_val; break; } phy->type = e1000_get_phy_type_from_id(phy->id); switch (phy->type) { case e1000_phy_82577: case e1000_phy_82579: case e1000_phy_i217: phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577; phy->ops.get_cable_length = e1000_get_cable_length_82577; phy->ops.get_info = e1000_get_phy_info_82577; phy->ops.commit = e1000_phy_sw_reset_generic; break; case e1000_phy_82578: phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.get_info = e1000_get_phy_info_m88; break; default: ret_val = -E1000_ERR_PHY; break; } return ret_val; } /** * e1000_init_phy_params_ich8lan - Initialize PHY function pointers * @hw: pointer to the HW structure * * Initialize family-specific PHY parameters and function pointers. **/ STATIC s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 i = 0; DEBUGFUNC("e1000_init_phy_params_ich8lan"); phy->addr = 1; phy->reset_delay_us = 100; phy->ops.acquire = e1000_acquire_swflag_ich8lan; phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; phy->ops.get_cable_length = e1000_get_cable_length_igp_2; phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.release = e1000_release_swflag_ich8lan; phy->ops.reset = e1000_phy_hw_reset_ich8lan; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; phy->ops.write_reg = e1000_write_phy_reg_igp; phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; /* We may need to do this twice - once for IGP and if that fails, * we'll set BM func pointers and try again */ ret_val = e1000_determine_phy_address(hw); if (ret_val) { phy->ops.write_reg = e1000_write_phy_reg_bm; phy->ops.read_reg = e1000_read_phy_reg_bm; ret_val = e1000_determine_phy_address(hw); if (ret_val) { DEBUGOUT("Cannot determine PHY addr. Erroring out\n"); return ret_val; } } phy->id = 0; while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) && (i++ < 100)) { msec_delay(1); ret_val = e1000_get_phy_id(hw); if (ret_val) return ret_val; } /* Verify phy id */ switch (phy->id) { case IGP03E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->ops.read_reg_locked = e1000_read_phy_reg_igp_locked; phy->ops.write_reg_locked = e1000_write_phy_reg_igp_locked; phy->ops.get_info = e1000_get_phy_info_igp; phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; break; case IFE_E_PHY_ID: case IFE_PLUS_E_PHY_ID: case IFE_C_E_PHY_ID: phy->type = e1000_phy_ife; phy->autoneg_mask = E1000_ALL_NOT_GIG; phy->ops.get_info = e1000_get_phy_info_ife; phy->ops.check_polarity = e1000_check_polarity_ife; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; break; case BME1000_E_PHY_ID: phy->type = e1000_phy_bm; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->ops.read_reg = e1000_read_phy_reg_bm; phy->ops.write_reg = e1000_write_phy_reg_bm; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; break; default: return -E1000_ERR_PHY; break; } return E1000_SUCCESS; } /** * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers * @hw: pointer to the HW structure * * Initialize family-specific NVM parameters and function * pointers. **/ STATIC s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 gfpreg, sector_base_addr, sector_end_addr; u16 i; DEBUGFUNC("e1000_init_nvm_params_ich8lan"); /* Can't read flash registers if the register set isn't mapped. */ nvm->type = e1000_nvm_flash_sw; if (!hw->flash_address) { DEBUGOUT("ERROR: Flash registers not mapped\n"); return -E1000_ERR_CONFIG; } gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); /* sector_X_addr is a "sector"-aligned address (4096 bytes) * Add 1 to sector_end_addr since this sector is included in * the overall size. */ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; /* flash_base_addr is byte-aligned */ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; /* find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. */ nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) << FLASH_SECTOR_ADDR_SHIFT); nvm->flash_bank_size /= 2; /* Adjust to word count */ nvm->flash_bank_size /= sizeof(u16); nvm->word_size = E1000_SHADOW_RAM_WORDS; /* Clear shadow ram */ for (i = 0; i < nvm->word_size; i++) { dev_spec->shadow_ram[i].modified = false; dev_spec->shadow_ram[i].value = 0xFFFF; } E1000_MUTEX_INIT(&dev_spec->nvm_mutex); E1000_MUTEX_INIT(&dev_spec->swflag_mutex); /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_ich8lan; nvm->ops.release = e1000_release_nvm_ich8lan; nvm->ops.read = e1000_read_nvm_ich8lan; nvm->ops.update = e1000_update_nvm_checksum_ich8lan; nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; nvm->ops.write = e1000_write_nvm_ich8lan; return E1000_SUCCESS; } /** * e1000_init_mac_params_ich8lan - Initialize MAC function pointers * @hw: pointer to the HW structure * * Initialize family-specific MAC parameters and function * pointers. **/ STATIC s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; #if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) u16 pci_cfg; #endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ DEBUGFUNC("e1000_init_mac_params_ich8lan"); /* Set media type function pointer */ hw->phy.media_type = e1000_media_type_copper; /* Set mta register count */ mac->mta_reg_count = 32; /* Set rar entry count */ mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; if (mac->type == e1000_ich8lan) mac->rar_entry_count--; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* FWSM register */ mac->has_fwsm = true; /* ARC subsystem not supported */ mac->arc_subsystem_valid = false; /* Adaptive IFS supported */ mac->adaptive_ifs = true; /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; /* function id */ mac->ops.set_lan_id = e1000_set_lan_id_single_port; /* reset */ mac->ops.reset_hw = e1000_reset_hw_ich8lan; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_ich8lan; /* link setup */ mac->ops.setup_link = e1000_setup_link_ich8lan; /* physical interface setup */ mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan; /* check for link */ mac->ops.check_for_link = e1000_check_for_copper_link_ich8lan; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; /* LED and other operations */ switch (mac->type) { case e1000_ich8lan: case e1000_ich9lan: case e1000_ich10lan: /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ mac->ops.blink_led = e1000_blink_led_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_ich8lan; mac->ops.led_off = e1000_led_off_ich8lan; break; case e1000_pch2lan: mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch2lan; /* fall-through */ case e1000_pch_lpt: #ifndef NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; #endif case e1000_pchlan: #if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) /* save PCH revision_id */ e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg); hw->revision_id = (u8)(pci_cfg &= 0x000F); #endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */ /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_pchlan; /* setup LED */ mac->ops.setup_led = e1000_setup_led_pchlan; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_pchlan; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_pchlan; mac->ops.led_off = e1000_led_off_pchlan; break; default: break; } if (mac->type == e1000_pch_lpt) { mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch_lpt; mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt; } /* Enable PCS Lock-loss workaround for ICH8 */ if (mac->type == e1000_ich8lan) e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, true); return E1000_SUCCESS; } /** * __e1000_access_emi_reg_locked - Read/write EMI register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: pointer to value to read/write from/to the EMI address * @read: boolean flag to indicate read or write * * This helper function assumes the SW/FW/HW Semaphore is already acquired. **/ STATIC s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, u16 *data, bool read) { s32 ret_val; DEBUGFUNC("__e1000_access_emi_reg_locked"); ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, address); if (ret_val) return ret_val; if (read) ret_val = hw->phy.ops.read_reg_locked(hw, I82579_EMI_DATA, data); else ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, *data); return ret_val; } /** * e1000_read_emi_reg_locked - Read Extended Management Interface register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: value to be read from the EMI address * * Assumes the SW/FW/HW Semaphore is already acquired. **/ s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) { DEBUGFUNC("e1000_read_emi_reg_locked"); return __e1000_access_emi_reg_locked(hw, addr, data, true); } /** * e1000_write_emi_reg_locked - Write Extended Management Interface register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: value to be written to the EMI address * * Assumes the SW/FW/HW Semaphore is already acquired. **/ s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) { DEBUGFUNC("e1000_read_emi_reg_locked"); return __e1000_access_emi_reg_locked(hw, addr, &data, false); } /** * e1000_set_eee_pchlan - Enable/disable EEE support * @hw: pointer to the HW structure * * Enable/disable EEE based on setting in dev_spec structure, the duplex of * the link and the EEE capabilities of the link partner. The LPI Control * register bits will remain set only if/when link is up. * * EEE LPI must not be asserted earlier than one second after link is up. * On 82579, EEE LPI should not be enabled until such time otherwise there * can be link issues with some switches. Other devices can have EEE LPI * enabled immediately upon link up since they have a timer in hardware which * prevents LPI from being asserted too early. **/ s32 e1000_set_eee_pchlan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; s32 ret_val; u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data; DEBUGFUNC("e1000_set_eee_pchlan"); switch (hw->phy.type) { case e1000_phy_82579: lpa = I82579_EEE_LP_ABILITY; pcs_status = I82579_EEE_PCS_STATUS; adv_addr = I82579_EEE_ADVERTISEMENT; break; case e1000_phy_i217: lpa = I217_EEE_LP_ABILITY; pcs_status = I217_EEE_PCS_STATUS; adv_addr = I217_EEE_ADVERTISEMENT; break; default: return E1000_SUCCESS; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); if (ret_val) goto release; /* Clear bits that enable EEE in various speeds */ lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK; /* Enable EEE if not disabled by user */ if (!dev_spec->eee_disable) { /* Save off link partner's EEE ability */ ret_val = e1000_read_emi_reg_locked(hw, lpa, &dev_spec->eee_lp_ability); if (ret_val) goto release; /* Read EEE advertisement */ ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv); if (ret_val) goto release; /* Enable EEE only for speeds in which the link partner is * EEE capable and for which we advertise EEE. */ if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { hw->phy.ops.read_reg_locked(hw, PHY_LP_ABILITY, &data); if (data & NWAY_LPAR_100TX_FD_CAPS) lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; else /* EEE is not supported in 100Half, so ignore * partner's EEE in 100 ability if full-duplex * is not advertised. */ dev_spec->eee_lp_ability &= ~I82579_EEE_100_SUPPORTED; } } /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); if (ret_val) goto release; ret_val = hw->phy.ops.write_reg_locked(hw, I82579_LPI_CTRL, lpi_ctrl); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP * @hw: pointer to the HW structure * @link: link up bool flag * * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications * preventing further DMA write requests. Workaround the issue by disabling * the de-assertion of the clock request when in 1Gpbs mode. * Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link * speeds in order to avoid Tx hangs. **/ STATIC s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) { u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); u32 status = E1000_READ_REG(hw, E1000_STATUS); s32 ret_val = E1000_SUCCESS; u16 reg; if (link && (status & E1000_STATUS_SPEED_1000)) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, ®); if (ret_val) goto release; ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, reg & ~E1000_KMRNCTRLSTA_K1_ENABLE); if (ret_val) goto release; usec_delay(10); E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, reg); release: hw->phy.ops.release(hw); } else { /* clear FEXTNVM6 bit 8 on link down or 10/100 */ fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; if (!link || ((status & E1000_STATUS_SPEED_100) && (status & E1000_STATUS_FD))) goto update_fextnvm6; ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, ®); if (ret_val) return ret_val; /* Clear link status transmit timeout */ reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK; if (status & E1000_STATUS_SPEED_100) { /* Set inband Tx timeout to 5x10us for 100Half */ reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; /* Do not extend the K1 entry latency for 100Half */ fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; } else { /* Set inband Tx timeout to 50x10us for 10Full/Half */ reg |= 50 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; /* Extend the K1 entry latency for 10 Mbps */ fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; } ret_val = hw->phy.ops.write_reg(hw, I217_INBAND_CTRL, reg); if (ret_val) return ret_val; update_fextnvm6: E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6); } return ret_val; } #if defined(NAHUM6LP_HW) && defined(ULP_SUPPORT) /** * e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP * @hw: pointer to the HW structure * @to_sx: boolean indicating a system power state transition to Sx * * When link is down, configure ULP mode to significantly reduce the power * to the PHY. If on a Manageability Engine (ME) enabled system, tell the * ME firmware to start the ULP configuration. If not on an ME enabled * system, configure the ULP mode by software. */ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) { u32 mac_reg; s32 ret_val = E1000_SUCCESS; u16 phy_reg; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) || (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on)) return 0; if (!to_sx) { int i = 0; /* Poll up to 5 seconds for Cable Disconnected indication */ while (!(E1000_READ_REG(hw, E1000_FEXT) & E1000_FEXT_PHY_CABLE_DISCONNECTED)) { /* Bail if link is re-acquired */ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU) return -E1000_ERR_PHY; if (i++ == 100) break; msec_delay(50); } DEBUGOUT2("CABLE_DISCONNECTED %s set after %dmsec\n", (E1000_READ_REG(hw, E1000_FEXT) & E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not", i * 50); } if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) { /* Request ME configure ULP mode in the PHY */ mac_reg = E1000_READ_REG(hw, E1000_H2ME); mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS; E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; /* During S0 Idle keep the phy in PCI-E mode */ if (hw->dev_spec.ich8lan.smbus_disable) goto skip_smbus; /* Force SMBus mode in PHY */ ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); if (ret_val) goto release; phy_reg |= CV_SMB_CTRL_FORCE_SMBUS; e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); /* Force SMBus mode in MAC */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); skip_smbus: if (!to_sx) { /* Change the 'Link Status Change' interrupt to trigger * on 'Cable Status Change' */ ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES, &phy_reg); if (ret_val) goto release; phy_reg |= E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC; e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES, phy_reg); } /* Set Inband ULP Exit, Reset to SMBus mode and * Disable SMBus Release on PERST# in PHY */ ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); if (ret_val) goto release; phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS | I218_ULP_CONFIG1_DISABLE_SMB_PERST); if (to_sx) { if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC) phy_reg |= I218_ULP_CONFIG1_WOL_HOST; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; } else { phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; } e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); /* Set Disable SMBus Release on PERST# in MAC */ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7); mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST; E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg); /* Commit ULP changes in PHY by starting auto ULP configuration */ phy_reg |= I218_ULP_CONFIG1_START; e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); if (!to_sx) { /* Disable Tx so that the MAC doesn't send any (buffered) * packets to the PHY. */ mac_reg = E1000_READ_REG(hw, E1000_TCTL); mac_reg &= ~E1000_TCTL_EN; E1000_WRITE_REG(hw, E1000_TCTL, mac_reg); } release: hw->phy.ops.release(hw); out: if (ret_val) DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val); else hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on; return ret_val; } /** * e1000_disable_ulp_lpt_lp - unconfigure Ultra Low Power mode for LynxPoint-LP * @hw: pointer to the HW structure * @force: boolean indicating whether or not to force disabling ULP * * Un-configure ULP mode when link is up, the system is transitioned from * Sx or the driver is unloaded. If on a Manageability Engine (ME) enabled * system, poll for an indication from ME that ULP has been un-configured. * If not on an ME enabled system, un-configure the ULP mode by software. * * During nominal operation, this function is called when link is acquired * to disable ULP mode (force=false); otherwise, for example when unloading * the driver or during Sx->S0 transitions, this is called with force=true * to forcibly disable ULP. * When the cable is plugged in while the device is in D0, a Cable Status * Change interrupt is generated which causes this function to be called * to partially disable ULP mode and restart autonegotiation. This function * is then called again due to the resulting Link Status Change interrupt * to finish cleaning up after the ULP flow. */ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) { s32 ret_val = E1000_SUCCESS; u32 mac_reg; u16 phy_reg; int i = 0; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) || (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_off)) return 0; if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) { if (force) { /* Request ME un-configure ULP mode in the PHY */ mac_reg = E1000_READ_REG(hw, E1000_H2ME); mac_reg &= ~E1000_H2ME_ULP; mac_reg |= E1000_H2ME_ENFORCE_SETTINGS; E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); } /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ while (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_ULP_CFG_DONE) { if (i++ == 10) { ret_val = -E1000_ERR_PHY; goto out; } msec_delay(10); } DEBUGOUT1("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10); if (force) { mac_reg = E1000_READ_REG(hw, E1000_H2ME); mac_reg &= ~E1000_H2ME_ENFORCE_SETTINGS; E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); } else { /* Clear H2ME.ULP after ME ULP configuration */ mac_reg = E1000_READ_REG(hw, E1000_H2ME); mac_reg &= ~E1000_H2ME_ULP; E1000_WRITE_REG(hw, E1000_H2ME, mac_reg); /* Restore link speed advertisements and restart * Auto-negotiation */ ret_val = e1000_phy_setup_autoneg(hw); if (ret_val) goto out; ret_val = e1000_oem_bits_config_ich8lan(hw, true); } goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; /* Revert the change to the 'Link Status Change' * interrupt to trigger on 'Cable Status Change' */ ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES, &phy_reg); if (ret_val) goto release; phy_reg &= ~E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC; e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES, phy_reg); if (force) /* Toggle LANPHYPC Value bit */ e1000_toggle_lanphypc_pch_lpt(hw); /* Unforce SMBus mode in PHY */ ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); if (ret_val) { /* The MAC might be in PCIe mode, so temporarily force to * SMBus mode in order to access the PHY. */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); msec_delay(50); ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); if (ret_val) goto release; } phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); /* Unforce SMBus mode in MAC */ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); /* When ULP mode was previously entered, K1 was disabled by the * hardware. Re-Enable K1 in the PHY when exiting ULP. */ ret_val = e1000_read_phy_reg_hv_locked(hw, HV_PM_CTRL, &phy_reg); if (ret_val) goto release; phy_reg |= HV_PM_CTRL_K1_ENABLE; e1000_write_phy_reg_hv_locked(hw, HV_PM_CTRL, phy_reg); /* Clear ULP enabled configuration */ ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); if (ret_val) goto release; /* CSC interrupt received due to ULP Indication */ if ((phy_reg & I218_ULP_CONFIG1_IND) || force) { phy_reg &= ~(I218_ULP_CONFIG1_IND | I218_ULP_CONFIG1_STICKY_ULP | I218_ULP_CONFIG1_RESET_TO_SMBUS | I218_ULP_CONFIG1_WOL_HOST | I218_ULP_CONFIG1_INBAND_EXIT | I218_ULP_CONFIG1_DISABLE_SMB_PERST); e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); /* Commit ULP changes by starting auto ULP configuration */ phy_reg |= I218_ULP_CONFIG1_START; e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); /* Clear Disable SMBus Release on PERST# in MAC */ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7); mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg); if (!force) { hw->phy.ops.release(hw); if (hw->mac.autoneg) e1000_phy_setup_autoneg(hw); e1000_sw_lcd_config_ich8lan(hw); e1000_oem_bits_config_ich8lan(hw, true); /* Set ULP state to unknown and return non-zero to * indicate no link (yet) and re-enter on the next LSC * to finish disabling ULP flow. */ hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown; return 1; } } /* Re-enable Tx */ mac_reg = E1000_READ_REG(hw, E1000_TCTL); mac_reg |= E1000_TCTL_EN; E1000_WRITE_REG(hw, E1000_TCTL, mac_reg); release: hw->phy.ops.release(hw); if (force) { hw->phy.ops.reset(hw); msec_delay(50); } out: if (ret_val) DEBUGOUT1("Error in ULP disable flow: %d\n", ret_val); else hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off; return ret_val; } #endif /* NAHUM6LP_HW && ULP_SUPPORT */ /** * e1000_check_for_copper_link_ich8lan - Check for link (Copper) * @hw: pointer to the HW structure * * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. **/ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; bool link = false; u16 phy_reg; DEBUGFUNC("e1000_check_for_copper_link_ich8lan"); /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) return E1000_SUCCESS; if ((hw->mac.type < e1000_pch_lpt) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) || (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V)) { /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; } else { /* Check the MAC's STATUS register to determine link state * since the PHY could be inaccessible while in ULP mode. */ link = !!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU); if (link) ret_val = e1000_disable_ulp_lpt_lp(hw, false); else ret_val = e1000_enable_ulp_lpt_lp(hw, false); if (ret_val) return ret_val; } if (hw->mac.type == e1000_pchlan) { ret_val = e1000_k1_gig_workaround_hv(hw, link); if (ret_val) return ret_val; } /* When connected at 10Mbps half-duplex, some parts are excessively * aggressive resulting in many collisions. To avoid this, increase * the IPG and reduce Rx latency in the PHY. */ if (((hw->mac.type == e1000_pch2lan) || (hw->mac.type == e1000_pch_lpt)) && link) { u32 reg; reg = E1000_READ_REG(hw, E1000_STATUS); if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { u16 emi_addr; reg = E1000_READ_REG(hw, E1000_TIPG); reg &= ~E1000_TIPG_IPGT_MASK; reg |= 0xFF; E1000_WRITE_REG(hw, E1000_TIPG, reg); /* Reduce Rx latency in analog PHY */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; if (hw->mac.type == e1000_pch2lan) emi_addr = I82579_RX_CONFIG; else emi_addr = I217_RX_CONFIG; ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); hw->phy.ops.release(hw); if (ret_val) return ret_val; } } /* Work-around I218 hang issue */ if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { ret_val = e1000_k1_workaround_lpt_lp(hw, link); if (ret_val) return ret_val; } /* Clear link partner's EEE ability */ hw->dev_spec.ich8lan.eee_lp_ability = 0; if (!link) return E1000_SUCCESS; /* No link detected */ mac->get_link_status = false; switch (hw->mac.type) { case e1000_pch2lan: ret_val = e1000_k1_workaround_lv(hw); if (ret_val) return ret_val; /* fall-thru */ case e1000_pchlan: if (hw->phy.type == e1000_phy_82578) { ret_val = e1000_link_stall_workaround_hv(hw); if (ret_val) return ret_val; } /* Workaround for PCHx parts in half-duplex: * Set the number of preambles removed from the packet * when it is passed from the PHY to the MAC to prevent * the MAC from misinterpreting the packet type. */ hw->phy.ops.read_reg(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg); phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK; if ((E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD) phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT); hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg); break; default: break; } /* Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); /* Enable/Disable EEE after link up */ if (hw->phy.type > e1000_phy_82579) { ret_val = e1000_set_eee_pchlan(hw); if (ret_val) return ret_val; } /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); return ret_val; } /** * e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers * @hw: pointer to the HW structure * * Initialize family-specific function pointers for PHY, MAC, and NVM. **/ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_ich8lan"); hw->mac.ops.init_params = e1000_init_mac_params_ich8lan; hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan; switch (hw->mac.type) { case e1000_ich8lan: case e1000_ich9lan: case e1000_ich10lan: hw->phy.ops.init_params = e1000_init_phy_params_ich8lan; break; case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: hw->phy.ops.init_params = e1000_init_phy_params_pchlan; break; default: break; } } /** * e1000_acquire_nvm_ich8lan - Acquire NVM mutex * @hw: pointer to the HW structure * * Acquires the mutex for performing NVM operations. **/ STATIC s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_acquire_nvm_ich8lan"); E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.nvm_mutex); return E1000_SUCCESS; } /** * e1000_release_nvm_ich8lan - Release NVM mutex * @hw: pointer to the HW structure * * Releases the mutex used while performing NVM operations. **/ STATIC void e1000_release_nvm_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_ich8lan"); E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.nvm_mutex); return; } /** * e1000_acquire_swflag_ich8lan - Acquire software control flag * @hw: pointer to the HW structure * * Acquires the software control flag for performing PHY and select * MAC CSR accesses. **/ STATIC s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) { u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_acquire_swflag_ich8lan"); E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.swflag_mutex); while (timeout) { extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) break; msec_delay_irq(1); timeout--; } if (!timeout) { DEBUGOUT("SW has already locked the resource.\n"); ret_val = -E1000_ERR_CONFIG; goto out; } timeout = SW_FLAG_TIMEOUT; extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); while (timeout) { extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) break; msec_delay_irq(1); timeout--; } if (!timeout) { DEBUGOUT2("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", E1000_READ_REG(hw, E1000_FWSM), extcnf_ctrl); extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); ret_val = -E1000_ERR_CONFIG; goto out; } out: if (ret_val) E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); return ret_val; } /** * e1000_release_swflag_ich8lan - Release software control flag * @hw: pointer to the HW structure * * Releases the software control flag for performing PHY and select * MAC CSR accesses. **/ STATIC void e1000_release_swflag_ich8lan(struct e1000_hw *hw) { u32 extcnf_ctrl; DEBUGFUNC("e1000_release_swflag_ich8lan"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) { extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); } else { DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n"); } E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); return; } /** * e1000_check_mng_mode_ich8lan - Checks management mode * @hw: pointer to the HW structure * * This checks if the adapter has any manageability enabled. * This is a function pointer entry point only called by read/write * routines for the PHY and NVM parts. **/ STATIC bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) { u32 fwsm; DEBUGFUNC("e1000_check_mng_mode_ich8lan"); fwsm = E1000_READ_REG(hw, E1000_FWSM); return (fwsm & E1000_ICH_FWSM_FW_VALID) && ((fwsm & E1000_FWSM_MODE_MASK) == (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); } /** * e1000_check_mng_mode_pchlan - Checks management mode * @hw: pointer to the HW structure * * This checks if the adapter has iAMT enabled. * This is a function pointer entry point only called by read/write * routines for the PHY and NVM parts. **/ STATIC bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) { u32 fwsm; DEBUGFUNC("e1000_check_mng_mode_pchlan"); fwsm = E1000_READ_REG(hw, E1000_FWSM); return (fwsm & E1000_ICH_FWSM_FW_VALID) && (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); } /** * e1000_rar_set_pch2lan - Set receive address register * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index: receive address array register * * Sets the receive address array register at index to the address passed * in by addr. For 82579, RAR[0] is the base address register that is to * contain the MAC address but RAR[1-6] are reserved for manageability (ME). * Use SHRA[0-3] in place of those reserved for ME. **/ STATIC void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; DEBUGFUNC("e1000_rar_set_pch2lan"); /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) rar_high |= E1000_RAH_AV; if (index == 0) { E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); E1000_WRITE_FLUSH(hw); return; } /* RAR[1-6] are owned by manageability. Skip those and program the * next address into the SHRA register array. */ if (index < (u32) (hw->mac.rar_entry_count)) { s32 ret_val; ret_val = e1000_acquire_swflag_ich8lan(hw); if (ret_val) goto out; E1000_WRITE_REG(hw, E1000_SHRAL(index - 1), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_SHRAH(index - 1), rar_high); E1000_WRITE_FLUSH(hw); e1000_release_swflag_ich8lan(hw); /* verify the register updates */ if ((E1000_READ_REG(hw, E1000_SHRAL(index - 1)) == rar_low) && (E1000_READ_REG(hw, E1000_SHRAH(index - 1)) == rar_high)) return; DEBUGOUT2("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n", (index - 1), E1000_READ_REG(hw, E1000_FWSM)); } out: DEBUGOUT1("Failed to write receive address at index %d\n", index); } /** * e1000_rar_set_pch_lpt - Set receive address registers * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index: receive address array register * * Sets the receive address register array at index to the address passed * in by addr. For LPT, RAR[0] is the base address register that is to * contain the MAC address. SHRA[0-10] are the shared receive address * registers that are shared between the Host and manageability engine (ME). **/ STATIC void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; u32 wlock_mac; DEBUGFUNC("e1000_rar_set_pch_lpt"); /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) rar_high |= E1000_RAH_AV; if (index == 0) { E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); E1000_WRITE_FLUSH(hw); return; } /* The manageability engine (ME) can lock certain SHRAR registers that * it is using - those registers are unavailable for use. */ if (index < hw->mac.rar_entry_count) { wlock_mac = E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_WLOCK_MAC_MASK; wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; /* Check if all SHRAR registers are locked */ if (wlock_mac == 1) goto out; if ((wlock_mac == 0) || (index <= wlock_mac)) { s32 ret_val; ret_val = e1000_acquire_swflag_ich8lan(hw); if (ret_val) goto out; E1000_WRITE_REG(hw, E1000_SHRAL_PCH_LPT(index - 1), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_SHRAH_PCH_LPT(index - 1), rar_high); E1000_WRITE_FLUSH(hw); e1000_release_swflag_ich8lan(hw); /* verify the register updates */ if ((E1000_READ_REG(hw, E1000_SHRAL_PCH_LPT(index - 1)) == rar_low) && (E1000_READ_REG(hw, E1000_SHRAH_PCH_LPT(index - 1)) == rar_high)) return; } } out: DEBUGOUT1("Failed to write receive address at index %d\n", index); } #ifndef NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT /** * e1000_update_mc_addr_list_pch2lan - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates entire Multicast Table Array of the PCH2 MAC and PHY. * The caller must have a packed mc_addr_list of multicast addresses. **/ STATIC void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { u16 phy_reg = 0; int i; s32 ret_val; DEBUGFUNC("e1000_update_mc_addr_list_pch2lan"); e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); if (ret_val) goto release; for (i = 0; i < hw->mac.mta_reg_count; i++) { hw->phy.ops.write_reg_page(hw, BM_MTA(i), (u16)(hw->mac.mta_shadow[i] & 0xFFFF)); hw->phy.ops.write_reg_page(hw, (BM_MTA(i) + 1), (u16)((hw->mac.mta_shadow[i] >> 16) & 0xFFFF)); } e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); release: hw->phy.ops.release(hw); } #endif /* NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT */ /** * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked * @hw: pointer to the HW structure * * Checks if firmware is blocking the reset of the PHY. * This is a function pointer entry point only called by * reset routines. **/ STATIC s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) { u32 fwsm; bool blocked = false; int i = 0; DEBUGFUNC("e1000_check_reset_block_ich8lan"); do { fwsm = E1000_READ_REG(hw, E1000_FWSM); if (!(fwsm & E1000_ICH_FWSM_RSPCIPHY)) { blocked = true; msec_delay(10); continue; } blocked = false; } while (blocked && (i++ < 10)); return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } /** * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states * @hw: pointer to the HW structure * * Assumes semaphore already acquired. * **/ STATIC s32 e1000_write_smbus_addr(struct e1000_hw *hw) { u16 phy_data; u32 strap = E1000_READ_REG(hw, E1000_STRAP); u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >> E1000_STRAP_SMT_FREQ_SHIFT; s32 ret_val; strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); if (ret_val) return ret_val; phy_data &= ~HV_SMB_ADDR_MASK; phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; if (hw->phy.type == e1000_phy_i217) { /* Restore SMBus frequency */ if (freq--) { phy_data &= ~HV_SMB_ADDR_FREQ_MASK; phy_data |= (freq & (1 << 0)) << HV_SMB_ADDR_FREQ_LOW_SHIFT; phy_data |= (freq & (1 << 1)) << (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1); } else { DEBUGOUT("Unsupported SMB frequency in PHY\n"); } } return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); } /** * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure * * SW should configure the LCD from the NVM extended configuration region * as a workaround for certain parts. **/ STATIC s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val = E1000_SUCCESS; u16 word_addr, reg_data, reg_addr, phy_page = 0; DEBUGFUNC("e1000_sw_lcd_config_ich8lan"); /* Initialize the PHY from the NVM on ICH platforms. This * is needed due to an issue where the NVM configuration is * not properly autoloaded after power transitions. * Therefore, after each PHY reset, we will load the * configuration data out of the NVM manually. */ switch (hw->mac.type) { case e1000_ich8lan: if (phy->type != e1000_phy_igp_3) return ret_val; if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_AMT) || (hw->device_id == E1000_DEV_ID_ICH8_IGP_C)) { sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; break; } /* Fall-thru */ case e1000_pchlan: case e1000_pch2lan: case e1000_pch_lpt: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: return ret_val; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; data = E1000_READ_REG(hw, E1000_FEXTNVM); if (!(data & sw_cfg_mask)) goto release; /* Make sure HW does not configure LCD from PHY * extended configuration before SW configuration */ data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if ((hw->mac.type < e1000_pch2lan) && (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)) goto release; cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE); cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; if (!cnf_size) goto release; cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; if (((hw->mac.type == e1000_pchlan) && !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || (hw->mac.type > e1000_pchlan)) { /* HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. * When both NVM bits are cleared, SW will configure * them instead. */ ret_val = e1000_write_smbus_addr(hw); if (ret_val) goto release; data = E1000_READ_REG(hw, E1000_LEDCTL); ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, (u16)data); if (ret_val) goto release; } /* Configure LCD from extended configuration region. */ /* cnf_base_addr is in DWORD */ word_addr = (u16)(cnf_base_addr << 1); for (i = 0; i < cnf_size; i++) { ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1, ®_data); if (ret_val) goto release; ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1), 1, ®_addr); if (ret_val) goto release; /* Save off the PHY page for future writes. */ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { phy_page = reg_data; continue; } reg_addr &= PHY_REG_MASK; reg_addr |= phy_page; ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr, reg_data); if (ret_val) goto release; } release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_k1_gig_workaround_hv - K1 Si workaround * @hw: pointer to the HW structure * @link: link up bool flag * * If K1 is enabled for 1Gbps, the MAC might stall when transitioning * from a lower speed. This workaround disables K1 whenever link is at 1Gig * If link is down, the function will restore the default K1 setting located * in the NVM. **/ STATIC s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) { s32 ret_val = E1000_SUCCESS; u16 status_reg = 0; bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; DEBUGFUNC("e1000_k1_gig_workaround_hv"); if (hw->mac.type != e1000_pchlan) return E1000_SUCCESS; /* Wrap the whole flow with the sw flag */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ if (link) { if (hw->phy.type == e1000_phy_82578) { ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS, &status_reg); if (ret_val) goto release; status_reg &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | BM_CS_STATUS_SPEED_MASK); if (status_reg == (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | BM_CS_STATUS_SPEED_1000)) k1_enable = false; } if (hw->phy.type == e1000_phy_82577) { ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS, &status_reg); if (ret_val) goto release; status_reg &= (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE | HV_M_STATUS_SPEED_MASK); if (status_reg == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE | HV_M_STATUS_SPEED_1000)) k1_enable = false; } /* Link stall fix for link up */ ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), 0x0100); if (ret_val) goto release; } else { /* Link stall fix for link down */ ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), 0x4100); if (ret_val) goto release; } ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_configure_k1_ich8lan - Configure K1 power state * @hw: pointer to the HW structure * @enable: K1 state to configure * * Configure the K1 power state based on the provided parameter. * Assumes semaphore already acquired. * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) **/ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) { s32 ret_val; u32 ctrl_reg = 0; u32 ctrl_ext = 0; u32 reg = 0; u16 kmrn_reg = 0; DEBUGFUNC("e1000_configure_k1_ich8lan"); ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, &kmrn_reg); if (ret_val) return ret_val; if (k1_enable) kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; else kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, kmrn_reg); if (ret_val) return ret_val; usec_delay(20); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); reg |= E1000_CTRL_FRCSPD; E1000_WRITE_REG(hw, E1000_CTRL, reg); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); E1000_WRITE_FLUSH(hw); usec_delay(20); E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); usec_delay(20); return E1000_SUCCESS; } /** * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure * @d0_state: boolean if entering d0 or d3 device state * * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are * collectively called OEM bits. The OEM Write Enable bit and SW Config bit * in NVM determines whether HW should configure LPLU and Gbe Disable. **/ STATIC s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) { s32 ret_val = 0; u32 mac_reg; u16 oem_reg; DEBUGFUNC("e1000_oem_bits_config_ich8lan"); if (hw->mac.type < e1000_pchlan) return ret_val; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; if (hw->mac.type == e1000_pchlan) { mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) goto release; } mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM); if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) goto release; mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL); ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg); if (ret_val) goto release; oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); if (d0_state) { if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) oem_reg |= HV_OEM_BITS_GBE_DIS; if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) oem_reg |= HV_OEM_BITS_LPLU; } else { if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) oem_reg |= HV_OEM_BITS_GBE_DIS; if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_NOND0A_LPLU)) oem_reg |= HV_OEM_BITS_LPLU; } /* Set Restart auto-neg to activate the bits */ if ((d0_state || (hw->mac.type != e1000_pchlan)) && !hw->phy.ops.check_reset_block(hw)) oem_reg |= HV_OEM_BITS_RESTART_AN; ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode * @hw: pointer to the HW structure **/ STATIC s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) { s32 ret_val; u16 data; DEBUGFUNC("e1000_set_mdio_slow_mode_hv"); ret_val = hw->phy.ops.read_reg(hw, HV_KMRN_MODE_CTRL, &data); if (ret_val) return ret_val; data |= HV_KMRN_MDIO_SLOW; ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_MODE_CTRL, data); return ret_val; } /** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. **/ STATIC s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_hv_phy_workarounds_ich8lan"); if (hw->mac.type != e1000_pchlan) return E1000_SUCCESS; /* Set MDIO slow mode before any other MDIO access */ if (hw->phy.type == e1000_phy_82577) { ret_val = e1000_set_mdio_slow_mode_hv(hw); if (ret_val) return ret_val; } if (((hw->phy.type == e1000_phy_82577) && ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { /* Disable generation of early preamble */ ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431); if (ret_val) return ret_val; /* Preamble tuning for SSC */ ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204); if (ret_val) return ret_val; } if (hw->phy.type == e1000_phy_82578) { /* Return registers to default by doing a soft reset then * writing 0x3140 to the control register. */ if (hw->phy.revision < 2) { e1000_phy_sw_reset_generic(hw); ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x3140); } } /* Select page 0 */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; hw->phy.addr = 1; ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); hw->phy.ops.release(hw); if (ret_val) return ret_val; /* Configure the K1 Si workaround during phy reset assuming there is * link so that it disables K1 if link is in 1Gbps. */ ret_val = e1000_k1_gig_workaround_hv(hw, true); if (ret_val) return ret_val; /* Workaround for link disconnects on a busy hub in half duplex */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data); if (ret_val) goto release; ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF); if (ret_val) goto release; /* set MSE higher to enable link to stay up when noise is high */ ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY * @hw: pointer to the HW structure **/ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) { u32 mac_reg; u16 i, phy_reg = 0; s32 ret_val; DEBUGFUNC("e1000_copy_rx_addrs_to_phy_ich8lan"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); if (ret_val) goto release; /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */ for (i = 0; i < (hw->mac.rar_entry_count); i++) { mac_reg = E1000_READ_REG(hw, E1000_RAL(i)); hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF)); mac_reg = E1000_READ_REG(hw, E1000_RAH(i)); hw->phy.ops.write_reg_page(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF)); hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i), (u16)((mac_reg & E1000_RAH_AV) >> 16)); } e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); release: hw->phy.ops.release(hw); } #ifndef CRC32_OS_SUPPORT STATIC u32 e1000_calc_rx_da_crc(u8 mac[]) { u32 poly = 0xEDB88320; /* Polynomial for 802.3 CRC calculation */ u32 i, j, mask, crc; DEBUGFUNC("e1000_calc_rx_da_crc"); crc = 0xffffffff; for (i = 0; i < 6; i++) { crc = crc ^ mac[i]; for (j = 8; j > 0; j--) { mask = (crc & 1) * (-1); crc = (crc >> 1) ^ (poly & mask); } } return ~crc; } #endif /* CRC32_OS_SUPPORT */ /** * e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation * with 82579 PHY * @hw: pointer to the HW structure * @enable: flag to enable/disable workaround when enabling/disabling jumbos **/ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) { s32 ret_val = E1000_SUCCESS; u16 phy_reg, data; u32 mac_reg; u16 i; DEBUGFUNC("e1000_lv_jumbo_workaround_ich8lan"); if (hw->mac.type < e1000_pch2lan) return E1000_SUCCESS; /* disable Rx path while enabling/disabling workaround */ hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); if (ret_val) return ret_val; if (enable) { /* Write Rx addresses (rar_entry_count for RAL/H, and * SHRAL/H) and initial CRC values to the MAC */ for (i = 0; i < hw->mac.rar_entry_count; i++) { u8 mac_addr[ETH_ADDR_LEN] = {0}; u32 addr_high, addr_low; addr_high = E1000_READ_REG(hw, E1000_RAH(i)); if (!(addr_high & E1000_RAH_AV)) continue; addr_low = E1000_READ_REG(hw, E1000_RAL(i)); mac_addr[0] = (addr_low & 0xFF); mac_addr[1] = ((addr_low >> 8) & 0xFF); mac_addr[2] = ((addr_low >> 16) & 0xFF); mac_addr[3] = ((addr_low >> 24) & 0xFF); mac_addr[4] = (addr_high & 0xFF); mac_addr[5] = ((addr_high >> 8) & 0xFF); #ifndef CRC32_OS_SUPPORT E1000_WRITE_REG(hw, E1000_PCH_RAICC(i), e1000_calc_rx_da_crc(mac_addr)); #else /* CRC32_OS_SUPPORT */ E1000_WRITE_REG(hw, E1000_PCH_RAICC(i), E1000_CRC32(ETH_ADDR_LEN, mac_addr)); #endif /* CRC32_OS_SUPPORT */ } /* Write Rx addresses to the PHY */ e1000_copy_rx_addrs_to_phy_ich8lan(hw); /* Enable jumbo frame workaround in the MAC */ mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG); mac_reg &= ~(1 << 14); mac_reg |= (7 << 15); E1000_WRITE_REG(hw, E1000_FFLT_DBG, mac_reg); mac_reg = E1000_READ_REG(hw, E1000_RCTL); mac_reg |= E1000_RCTL_SECRC; E1000_WRITE_REG(hw, E1000_RCTL, mac_reg); ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, &data); if (ret_val) return ret_val; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, data | (1 << 0)); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, &data); if (ret_val) return ret_val; data &= ~(0xF << 8); data |= (0xB << 8); ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, data); if (ret_val) return ret_val; /* Enable jumbo frame workaround in the PHY */ hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); data |= (0x37 << 5); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data); data &= ~(1 << 13); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data); data &= ~(0x3FF << 2); data |= (0x1A << 2); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0xF100); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data); ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data | (1 << 10)); if (ret_val) return ret_val; } else { /* Write MAC register values back to h/w defaults */ mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG); mac_reg &= ~(0xF << 14); E1000_WRITE_REG(hw, E1000_FFLT_DBG, mac_reg); mac_reg = E1000_READ_REG(hw, E1000_RCTL); mac_reg &= ~E1000_RCTL_SECRC; E1000_WRITE_REG(hw, E1000_RCTL, mac_reg); ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, &data); if (ret_val) return ret_val; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, data & ~(1 << 0)); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, &data); if (ret_val) return ret_val; data &= ~(0xF << 8); data |= (0xB << 8); ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, data); if (ret_val) return ret_val; /* Write PHY register values back to h/w defaults */ hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data); data |= (1 << 13); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data); data &= ~(0x3FF << 2); data |= (0x8 << 2); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0x7E00); if (ret_val) return ret_val; hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data); ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data & ~(1 << 10)); if (ret_val) return ret_val; } /* re-enable Rx path after enabling/disabling workaround */ return hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); } /** * e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. **/ STATIC s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_lv_phy_workarounds_ich8lan"); if (hw->mac.type != e1000_pch2lan) return E1000_SUCCESS; /* Set MDIO slow mode before any other MDIO access */ ret_val = e1000_set_mdio_slow_mode_hv(hw); if (ret_val) return ret_val; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* set MSE higher to enable link to stay up when noise is high */ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034); if (ret_val) goto release; /* drop link after 5 times MSE threshold was reached */ ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_k1_gig_workaround_lv - K1 Si workaround * @hw: pointer to the HW structure * * Workaround to set the K1 beacon duration for 82579 parts in 10Mbps * Disable K1 for 1000 and 100 speeds **/ STATIC s32 e1000_k1_workaround_lv(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 status_reg = 0; DEBUGFUNC("e1000_k1_workaround_lv"); if (hw->mac.type != e1000_pch2lan) return E1000_SUCCESS; /* Set K1 beacon duration based on 10Mbs speed */ ret_val = hw->phy.ops.read_reg(hw, HV_M_STATUS, &status_reg); if (ret_val) return ret_val; if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { if (status_reg & (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) { u16 pm_phy_reg; /* LV 1G/100 Packet drop issue wa */ ret_val = hw->phy.ops.read_reg(hw, HV_PM_CTRL, &pm_phy_reg); if (ret_val) return ret_val; pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE; ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, pm_phy_reg); if (ret_val) return ret_val; } else { u32 mac_reg; mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4); mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg); } } return ret_val; } /** * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware * @hw: pointer to the HW structure * @gate: boolean set to true to gate, false to ungate * * Gate/ungate the automatic PHY configuration via hardware; perform * the configuration via software instead. **/ STATIC void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) { u32 extcnf_ctrl; DEBUGFUNC("e1000_gate_hw_phy_config_ich8lan"); if (hw->mac.type < e1000_pch2lan) return; extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (gate) extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; else extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); } /** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure * * Check the appropriate indication the MAC has finished configuring the * PHY after a software reset. **/ STATIC void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) { u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; DEBUGFUNC("e1000_lan_init_done_ich8lan"); /* Wait for basic configuration completes before proceeding */ do { data = E1000_READ_REG(hw, E1000_STATUS); data &= E1000_STATUS_LAN_INIT_DONE; usec_delay(100); } while ((!data) && --loop); /* If basic configuration is incomplete before the above loop * count reaches 0, loading the configuration from NVM will * leave the PHY in a bad state possibly resulting in no link. */ if (loop == 0) DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n"); /* Clear the Init Done bit for the next init event */ data = E1000_READ_REG(hw, E1000_STATUS); data &= ~E1000_STATUS_LAN_INIT_DONE; E1000_WRITE_REG(hw, E1000_STATUS, data); } /** * e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset * @hw: pointer to the HW structure **/ STATIC s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 reg; DEBUGFUNC("e1000_post_phy_reset_ich8lan"); if (hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; /* Allow time for h/w to get to quiescent state after reset */ msec_delay(10); /* Perform any necessary post-reset workarounds */ switch (hw->mac.type) { case e1000_pchlan: ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) return ret_val; break; case e1000_pch2lan: ret_val = e1000_lv_phy_workarounds_ich8lan(hw); if (ret_val) return ret_val; break; default: break; } /* Clear the host wakeup bit after lcd reset */ if (hw->mac.type >= e1000_pchlan) { hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, ®); reg &= ~BM_WUC_HOST_WU_BIT; hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, reg); } /* Configure the LCD with the extended configuration region in NVM */ ret_val = e1000_sw_lcd_config_ich8lan(hw); if (ret_val) return ret_val; /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, true); if (hw->mac.type == e1000_pch2lan) { /* Ungate automatic PHY configuration on non-managed 82579 */ if (!(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) { msec_delay(10); e1000_gate_hw_phy_config_ich8lan(hw, false); } /* Set EEE LPI Update Timer to 200usec */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_UPDATE_TIMER, 0x1387); hw->phy.ops.release(hw); } return ret_val; } /** * e1000_phy_hw_reset_ich8lan - Performs a PHY reset * @hw: pointer to the HW structure * * Resets the PHY * This is a function pointer entry point called by drivers * or other shared routines. **/ STATIC s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_phy_hw_reset_ich8lan"); /* Gate automatic PHY configuration by hardware on non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) e1000_gate_hw_phy_config_ich8lan(hw, true); ret_val = e1000_phy_hw_reset_generic(hw); if (ret_val) return ret_val; return e1000_post_phy_reset_ich8lan(hw); } /** * e1000_set_lplu_state_pchlan - Set Low Power Link Up state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU state according to the active flag. For PCH, if OEM write * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set * the phy speed. This function will manually set the LPLU bit and restart * auto-neg as hw would do. D3 and D0 LPLU will call the same function * since it configures the same bit. **/ STATIC s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) { s32 ret_val; u16 oem_reg; DEBUGFUNC("e1000_set_lplu_state_pchlan"); ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg); if (ret_val) return ret_val; if (active) oem_reg |= HV_OEM_BITS_LPLU; else oem_reg &= ~HV_OEM_BITS_LPLU; if (!hw->phy.ops.check_reset_block(hw)) oem_reg |= HV_OEM_BITS_RESTART_AN; return hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg); } /** * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ STATIC s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; u32 phy_ctrl; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan"); if (phy->type == e1000_phy_ife) return E1000_SUCCESS; phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); if (active) { phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) return E1000_SUCCESS; /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) e1000_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else { phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) return E1000_SUCCESS; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } } return E1000_SUCCESS; } /** * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D3 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ STATIC s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; u32 phy_ctrl; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d3_lplu_state_ich8lan"); phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); if (!active) { phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) return E1000_SUCCESS; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) return E1000_SUCCESS; /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) e1000_gig_downshift_workaround_ich8lan(hw); /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } return ret_val; } /** * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 * @hw: pointer to the HW structure * @bank: pointer to the variable that returns the active bank * * Reads signature byte from the NVM using the flash access registers. * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. **/ STATIC s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) { u32 eecd; struct e1000_nvm_info *nvm = &hw->nvm; u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; u8 sig_byte = 0; s32 ret_val; DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan"); switch (hw->mac.type) { case e1000_ich8lan: case e1000_ich9lan: eecd = E1000_READ_REG(hw, E1000_EECD); if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == E1000_EECD_SEC1VAL_VALID_MASK) { if (eecd & E1000_EECD_SEC1VAL) *bank = 1; else *bank = 0; return E1000_SUCCESS; } DEBUGOUT("Unable to determine valid NVM bank via EEC - reading flash signature\n"); /* fall-thru */ default: /* set bank to 0 in case flash read fails */ *bank = 0; /* Check bank 0 */ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, &sig_byte); if (ret_val) return ret_val; if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == E1000_ICH_NVM_SIG_VALUE) { *bank = 0; return E1000_SUCCESS; } /* Check bank 1 */ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + bank1_offset, &sig_byte); if (ret_val) return ret_val; if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == E1000_ICH_NVM_SIG_VALUE) { *bank = 1; return E1000_SUCCESS; } DEBUGOUT("ERROR: No valid NVM bank present\n"); return -E1000_ERR_NVM; } } /** * e1000_read_nvm_ich8lan - Read word(s) from the NVM * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the word(s) to read. * @words: Size of data to read in words * @data: Pointer to the word(s) to read at offset. * * Reads a word(s) from the NVM using the flash access registers. **/ STATIC s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 act_offset; s32 ret_val = E1000_SUCCESS; u32 bank = 0; u16 i, word; DEBUGFUNC("e1000_read_nvm_ich8lan"); if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } nvm->ops.acquire(hw); ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); if (ret_val != E1000_SUCCESS) { DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); bank = 0; } act_offset = (bank) ? nvm->flash_bank_size : 0; act_offset += offset; ret_val = E1000_SUCCESS; for (i = 0; i < words; i++) { if (dev_spec->shadow_ram[offset+i].modified) { data[i] = dev_spec->shadow_ram[offset+i].value; } else { ret_val = e1000_read_flash_word_ich8lan(hw, act_offset + i, &word); if (ret_val) break; data[i] = word; } } nvm->ops.release(hw); out: if (ret_val) DEBUGOUT1("NVM read error: %d\n", ret_val); return ret_val; } /** * e1000_flash_cycle_init_ich8lan - Initialize flash * @hw: pointer to the HW structure * * This function does initial flash setup so that a new read/write/erase cycle * can be started. **/ STATIC s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) { union ich8_hws_flash_status hsfsts; s32 ret_val = -E1000_ERR_NVM; DEBUGFUNC("e1000_flash_cycle_init_ich8lan"); hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* Check if the flash descriptor is valid */ if (!hsfsts.hsf_status.fldesvalid) { DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used.\n"); return -E1000_ERR_NVM; } /* Clear FCERR and DAEL in hw status by writing 1 */ hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or * FDONE bit should be changed in the hardware so that it * is 1 after hardware reset, which can then be used as an * indication whether a cycle is in progress or has been * completed. */ if (!hsfsts.hsf_status.flcinprog) { /* There is no cycle running at present, * so we can start a cycle. * Begin by setting Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); ret_val = E1000_SUCCESS; } else { s32 i; /* Otherwise poll for sometime so the current * cycle has a chance to end before giving up. */ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (!hsfsts.hsf_status.flcinprog) { ret_val = E1000_SUCCESS; break; } usec_delay(1); } if (ret_val == E1000_SUCCESS) { /* Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access\n"); } } return ret_val; } /** * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) * @hw: pointer to the HW structure * @timeout: maximum time to wait for completion * * This function starts a flash cycle and waits for its completion. **/ STATIC s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) { union ich8_hws_flash_ctrl hsflctl; union ich8_hws_flash_status hsfsts; u32 i = 0; DEBUGFUNC("e1000_flash_cycle_ich8lan"); /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* wait till FDONE bit is set to 1 */ do { hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcdone) break; usec_delay(1); } while (i++ < timeout); if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr) return E1000_SUCCESS; return -E1000_ERR_NVM; } /** * e1000_read_flash_word_ich8lan - Read word from flash * @hw: pointer to the HW structure * @offset: offset to data location * @data: pointer to the location for storing the data * * Reads the flash word at offset into data. Offset is converted * to bytes before read. **/ STATIC s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data) { DEBUGFUNC("e1000_read_flash_word_ich8lan"); if (!data) return -E1000_ERR_NVM; /* Must convert offset into bytes. */ offset <<= 1; return e1000_read_flash_data_ich8lan(hw, offset, 2, data); } /** * e1000_read_flash_byte_ich8lan - Read byte from flash * @hw: pointer to the HW structure * @offset: The offset of the byte to read. * @data: Pointer to a byte to store the value read. * * Reads a single byte from the NVM using the flash access registers. **/ STATIC s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 *data) { s32 ret_val; u16 word = 0; ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); if (ret_val) return ret_val; *data = (u8)word; return E1000_SUCCESS; } /** * e1000_read_flash_data_ich8lan - Read byte or word from NVM * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the byte or word to read. * @size: Size of data to read, 1=byte 2=word * @data: Pointer to the word to store the value read. * * Reads a byte or word from the NVM using the flash access registers. **/ STATIC s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 *data) { union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; u32 flash_linear_addr; u32 flash_data = 0; s32 ret_val = -E1000_ERR_NVM; u8 count = 0; DEBUGFUNC("e1000_read_flash_data_ich8lan"); if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) return -E1000_ERR_NVM; flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); do { usec_delay(1); /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_READ_COMMAND_TIMEOUT); /* Check if FCERR is set to 1, if set to 1, clear it * and try the whole sequence a few more times, else * read in (shift in) the Flash Data0, the order is * least significant byte first msb to lsb */ if (ret_val == E1000_SUCCESS) { flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); if (size == 1) *data = (u8)(flash_data & 0x000000FF); else if (size == 2) *data = (u16)(flash_data & 0x0000FFFF); break; } else { /* If we've gotten here, then things are probably * completely hosed, but if the error condition is * detected, it won't hurt to give it another try... * ICH_FLASH_CYCLE_REPEAT_COUNT times. */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr) { /* Repeat for some time before giving up. */ continue; } else if (!hsfsts.hsf_status.flcdone) { DEBUGOUT("Timeout error - flash cycle did not complete.\n"); break; } } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return ret_val; } /** * e1000_write_nvm_ich8lan - Write word(s) to the NVM * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the word(s) to write. * @words: Size of data to write in words * @data: Pointer to the word(s) to write at offset. * * Writes a byte or word to the NVM using the flash access registers. **/ STATIC s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u16 i; DEBUGFUNC("e1000_write_nvm_ich8lan"); if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } nvm->ops.acquire(hw); for (i = 0; i < words; i++) { dev_spec->shadow_ram[offset+i].modified = true; dev_spec->shadow_ram[offset+i].value = data[i]; } nvm->ops.release(hw); return E1000_SUCCESS; } /** * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM * @hw: pointer to the HW structure * * The NVM checksum is updated by calling the generic update_nvm_checksum, * which writes the checksum to the shadow ram. The changes in the shadow * ram are then committed to the EEPROM by processing each bank at a time * checking for the modified bit and writing only the pending changes. * After a successful commit, the shadow ram is cleared and is ready for * future writes. **/ STATIC s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 i, act_offset, new_bank_offset, old_bank_offset, bank; s32 ret_val; u16 data; DEBUGFUNC("e1000_update_nvm_checksum_ich8lan"); ret_val = e1000_update_nvm_checksum_generic(hw); if (ret_val) goto out; if (nvm->type != e1000_nvm_flash_sw) goto out; nvm->ops.acquire(hw); /* We're writing to the opposite bank so if we're on bank 1, * write to bank 0 etc. We also need to erase the segment that * is going to be written */ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); if (ret_val != E1000_SUCCESS) { DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); bank = 0; } if (bank == 0) { new_bank_offset = nvm->flash_bank_size; old_bank_offset = 0; ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); if (ret_val) goto release; } else { old_bank_offset = nvm->flash_bank_size; new_bank_offset = 0; ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); if (ret_val) goto release; } for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { /* Determine whether to write the value stored * in the other NVM bank or a modified value stored * in the shadow RAM */ if (dev_spec->shadow_ram[i].modified) { data = dev_spec->shadow_ram[i].value; } else { ret_val = e1000_read_flash_word_ich8lan(hw, i + old_bank_offset, &data); if (ret_val) break; } /* If the word is 0x13, then make sure the signature bits * (15:14) are 11b until the commit has completed. * This will allow us to write 10b which indicates the * signature is valid. We want to do this after the write * has completed so that we don't mark the segment valid * while the write is still in progress */ if (i == E1000_ICH_NVM_SIG_WORD) data |= E1000_ICH_NVM_SIG_MASK; /* Convert offset to bytes. */ act_offset = (i + new_bank_offset) << 1; usec_delay(100); /* Write the bytes to the new bank. */ ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, (u8)data); if (ret_val) break; usec_delay(100); ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset + 1, (u8)(data >> 8)); if (ret_val) break; } /* Don't bother writing the segment valid bits if sector * programming failed. */ if (ret_val) { DEBUGOUT("Flash commit failed.\n"); goto release; } /* Finally validate the new segment by setting bit 15:14 * to 10b in word 0x13 , this can be done without an * erase as well since these bits are 11 to start with * and we need to change bit 14 to 0b */ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); if (ret_val) goto release; data &= 0xBFFF; ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset * 2 + 1, (u8)(data >> 8)); if (ret_val) goto release; /* And invalidate the previously valid segment by setting * its signature word (0x13) high_byte to 0b. This can be * done without an erase because flash erase sets all bits * to 1's. We can write 1's to 0's without an erase */ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); if (ret_val) goto release; /* Great! Everything worked, we can now clear the cached entries. */ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { dev_spec->shadow_ram[i].modified = false; dev_spec->shadow_ram[i].value = 0xFFFF; } release: nvm->ops.release(hw); /* Reload the EEPROM, or else modifications will not appear * until after the next adapter reset. */ if (!ret_val) { nvm->ops.reload(hw); msec_delay(10); } out: if (ret_val) DEBUGOUT1("NVM update error: %d\n", ret_val); return ret_val; } /** * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum * @hw: pointer to the HW structure * * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. * If the bit is 0, that the EEPROM had been modified, but the checksum was not * calculated, in which case we need to calculate the checksum and set bit 6. **/ STATIC s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) { s32 ret_val; u16 data; u16 word; u16 valid_csum_mask; DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan"); /* Read NVM and check Invalid Image CSUM bit. If this bit is 0, * the checksum needs to be fixed. This bit is an indication that * the NVM was prepared by OEM software and did not calculate * the checksum...a likely scenario. */ switch (hw->mac.type) { case e1000_pch_lpt: word = NVM_COMPAT; valid_csum_mask = NVM_COMPAT_VALID_CSUM; break; default: word = NVM_FUTURE_INIT_WORD1; valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM; break; } ret_val = hw->nvm.ops.read(hw, word, 1, &data); if (ret_val) return ret_val; if (!(data & valid_csum_mask)) { data |= valid_csum_mask; ret_val = hw->nvm.ops.write(hw, word, 1, &data); if (ret_val) return ret_val; ret_val = hw->nvm.ops.update(hw); if (ret_val) return ret_val; } return e1000_validate_nvm_checksum_generic(hw); } /** * e1000_write_flash_data_ich8lan - Writes bytes to the NVM * @hw: pointer to the HW structure * @offset: The offset (in bytes) of the byte/word to read. * @size: Size of data to read, 1=byte 2=word * @data: The byte(s) to write to the NVM. * * Writes one/two bytes to the NVM using the flash access registers. **/ STATIC s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, u8 size, u16 data) { union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; u32 flash_linear_addr; u32 flash_data = 0; s32 ret_val; u8 count = 0; DEBUGFUNC("e1000_write_ich8_data"); if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) return -E1000_ERR_NVM; flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr); do { usec_delay(1); /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val != E1000_SUCCESS) break; hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); if (size == 1) flash_data = (u32)data & 0x00FF; else flash_data = (u32)data; E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); /* check if FCERR is set to 1 , if set to 1, clear it * and try the whole sequence a few more times else done */ ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_WRITE_COMMAND_TIMEOUT); if (ret_val == E1000_SUCCESS) break; /* If we're here, then things are most likely * completely hosed, but if the error condition * is detected, it won't hurt to give it another * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr) /* Repeat for some time before giving up. */ continue; if (!hsfsts.hsf_status.flcdone) { DEBUGOUT("Timeout error - flash cycle did not complete.\n"); break; } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return ret_val; } /** * e1000_write_flash_byte_ich8lan - Write a single byte to NVM * @hw: pointer to the HW structure * @offset: The index of the byte to read. * @data: The byte to write to the NVM. * * Writes a single byte to the NVM using the flash access registers. **/ STATIC s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 data) { u16 word = (u16)data; DEBUGFUNC("e1000_write_flash_byte_ich8lan"); return e1000_write_flash_data_ich8lan(hw, offset, 1, word); } /** * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM * @hw: pointer to the HW structure * @offset: The offset of the byte to write. * @byte: The byte to write to the NVM. * * Writes a single byte to the NVM using the flash access registers. * Goes through a retry algorithm before giving up. **/ STATIC s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte) { s32 ret_val; u16 program_retries; DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); if (!ret_val) return ret_val; for (program_retries = 0; program_retries < 100; program_retries++) { DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); usec_delay(100); ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); if (ret_val == E1000_SUCCESS) break; } if (program_retries == 100) return -E1000_ERR_NVM; return E1000_SUCCESS; } /** * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM * @hw: pointer to the HW structure * @bank: 0 for first bank, 1 for second bank, etc. * * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. * bank N is 4096 * N + flash_reg_addr. **/ STATIC s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) { struct e1000_nvm_info *nvm = &hw->nvm; union ich8_hws_flash_status hsfsts; union ich8_hws_flash_ctrl hsflctl; u32 flash_linear_addr; /* bank size is in 16bit words - adjust to bytes */ u32 flash_bank_size = nvm->flash_bank_size * 2; s32 ret_val; s32 count = 0; s32 j, iteration, sector_size; DEBUGFUNC("e1000_erase_flash_bank_ich8lan"); hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* Determine HW Sector size: Read BERASE bits of hw flash status * register * 00: The Hw sector is 256 bytes, hence we need to erase 16 * consecutive sectors. The start index for the nth Hw sector * can be calculated as = bank * 4096 + n * 256 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. * The start index for the nth Hw sector can be calculated * as = bank * 4096 * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 * (ich9 only, otherwise error condition) * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 */ switch (hsfsts.hsf_status.berasesz) { case 0: /* Hw sector size 256 */ sector_size = ICH_FLASH_SEG_SIZE_256; iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; break; case 1: sector_size = ICH_FLASH_SEG_SIZE_4K; iteration = 1; break; case 2: sector_size = ICH_FLASH_SEG_SIZE_8K; iteration = 1; break; case 3: sector_size = ICH_FLASH_SEG_SIZE_64K; iteration = 1; break; default: return -E1000_ERR_NVM; } /* Start with the base address, then add the sector offset. */ flash_linear_addr = hw->nvm.flash_base_addr; flash_linear_addr += (bank) ? flash_bank_size : 0; for (j = 0; j < iteration; j++) { do { u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT; /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val) return ret_val; /* Write a value 11 (block Erase) in Flash * Cycle field in hw flash control */ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of an index within the * block into Flash Linear address field in Flash * Address. */ flash_linear_addr += (j * sector_size); E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); ret_val = e1000_flash_cycle_ich8lan(hw, timeout); if (ret_val == E1000_SUCCESS) break; /* Check if FCERR is set to 1. If 1, * clear it and try the whole sequence * a few more times else Done */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr) /* repeat for some time before giving up */ continue; else if (!hsfsts.hsf_status.flcdone) return ret_val; } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); } return E1000_SUCCESS; } /** * e1000_valid_led_default_ich8lan - Set the default LED settings * @hw: pointer to the HW structure * @data: Pointer to the LED settings * * Reads the LED default settings from the NVM to data. If the NVM LED * settings is all 0's or F's, set the LED default to a valid LED default * setting. **/ STATIC s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_ich8lan"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT_ICH8LAN; return E1000_SUCCESS; } /** * e1000_id_led_init_pchlan - store LED configurations * @hw: pointer to the HW structure * * PCH does not control LEDs via the LEDCTL register, rather it uses * the PHY LED configuration register. * * PCH also does not have an "always on" or "always off" mode which * complicates the ID feature. Instead of using the "on" mode to indicate * in ledctl_mode2 the LEDs to use for ID (see e1000_id_led_init_generic()), * use "link_up" mode. The LEDs will still ID on request if there is no * link based on logic in e1000_led_[on|off]_pchlan(). **/ STATIC s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; u16 data, i, temp, shift; DEBUGFUNC("e1000_id_led_init_pchlan"); /* Get default ID LED modes */ ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) return ret_val; mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; mac->ledctl_mode2 = mac->ledctl_default; for (i = 0; i < 4; i++) { temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; shift = (i * 5); switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); mac->ledctl_mode1 |= (ledctl_on << shift); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2: mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); mac->ledctl_mode1 |= (ledctl_off << shift); break; default: /* Do nothing */ break; } switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); mac->ledctl_mode2 |= (ledctl_on << shift); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2: mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); mac->ledctl_mode2 |= (ledctl_off << shift); break; default: /* Do nothing */ break; } } return E1000_SUCCESS; } /** * e1000_get_bus_info_ich8lan - Get/Set the bus type and width * @hw: pointer to the HW structure * * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability * register, so the the bus width is hard coded. **/ STATIC s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; s32 ret_val; DEBUGFUNC("e1000_get_bus_info_ich8lan"); ret_val = e1000_get_bus_info_pcie_generic(hw); /* ICH devices are "PCI Express"-ish. They have * a configuration space, but do not contain * PCI Express Capability registers, so bus width * must be hardcoded. */ if (bus->width == e1000_bus_width_unknown) bus->width = e1000_bus_width_pcie_x1; return ret_val; } /** * e1000_reset_hw_ich8lan - Reset the hardware * @hw: pointer to the HW structure * * Does a full reset of the hardware which includes a reset of the PHY and * MAC. **/ STATIC s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u16 kum_cfg; u32 ctrl, reg; s32 ret_val; DEBUGFUNC("e1000_reset_hw_ich8lan"); /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); /* Disable the Transmit and Receive units. Then delay to allow * any pending transactions to complete before we hit the MAC * with the global reset. */ E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); /* Workaround for ICH8 bit corruption issue in FIFO memory */ if (hw->mac.type == e1000_ich8lan) { /* Set Tx and Rx buffer allocation to 8k apiece. */ E1000_WRITE_REG(hw, E1000_PBA, E1000_PBA_8K); /* Set Packet Buffer Size to 16k. */ E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K); } if (hw->mac.type == e1000_pchlan) { /* Save the NVM K1 bit setting*/ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg); if (ret_val) return ret_val; if (kum_cfg & E1000_NVM_K1_ENABLE) dev_spec->nvm_k1_enabled = true; else dev_spec->nvm_k1_enabled = false; } ctrl = E1000_READ_REG(hw, E1000_CTRL); if (!hw->phy.ops.check_reset_block(hw)) { /* Full-chip reset requires MAC and PHY reset at the same * time to make sure the interface between MAC and the * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; /* Gate automatic PHY configuration by hardware on * non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) e1000_gate_hw_phy_config_ich8lan(hw, true); } ret_val = e1000_acquire_swflag_ich8lan(hw); DEBUGOUT("Issuing a global reset to ich8lan\n"); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST)); /* cannot issue a flush here because it hangs the hardware */ msec_delay(20); /* Set Phy Config Counter to 50msec */ if (hw->mac.type == e1000_pch2lan) { reg = E1000_READ_REG(hw, E1000_FEXTNVM3); reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; E1000_WRITE_REG(hw, E1000_FEXTNVM3, reg); } if (!ret_val) E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); if (ctrl & E1000_CTRL_PHY_RST) { ret_val = hw->phy.ops.get_cfg_done(hw); if (ret_val) return ret_val; ret_val = e1000_post_phy_reset_ich8lan(hw); if (ret_val) return ret_val; } /* For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up * as a bad packet to the DMA engine. */ if (hw->mac.type == e1000_pchlan) E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); reg = E1000_READ_REG(hw, E1000_KABGTXD); reg |= E1000_KABGTXD_BGSQLBIAS; E1000_WRITE_REG(hw, E1000_KABGTXD, reg); return E1000_SUCCESS; } /** * e1000_init_hw_ich8lan - Initialize the hardware * @hw: pointer to the HW structure * * Prepares the hardware for transmit and receive by doing the following: * - initialize hardware bits * - initialize LED identification * - setup receive address registers * - setup flow control * - setup transmit descriptors * - clear statistics **/ STATIC s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 ctrl_ext, txdctl, snoop; s32 ret_val; u16 i; DEBUGFUNC("e1000_init_hw_ich8lan"); e1000_initialize_hw_bits_ich8lan(hw); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); /* An error is not fatal and we should not stop init due to this */ if (ret_val) DEBUGOUT("Error initializing identification LED\n"); /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* The 82578 Rx buffer will stall if wakeup is enabled in host and * the ME. Disable wakeup by clearing the host wakeup bit. * Reset the phy after disabling host wakeup to reset the Rx buffer. */ if (hw->phy.type == e1000_phy_82578) { hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &i); i &= ~BM_WUC_HOST_WU_BIT; hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, i); ret_val = e1000_phy_hw_reset_ich8lan(hw); if (ret_val) return ret_val; } /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* Set the transmit descriptor write-back policy for both queues */ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB); txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | E1000_TXDCTL_MAX_TX_DESC_PREFETCH); E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1)); txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB); txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | E1000_TXDCTL_MAX_TX_DESC_PREFETCH); E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl); /* ICH8 has opposite polarity of no_snoop bits. * By default, we should use snoop behavior. */ if (mac->type == e1000_ich8lan) snoop = PCIE_ICH8_SNOOP_ALL; else snoop = (u32) ~(PCIE_NO_SNOOP_ALL); e1000_set_pcie_no_snoop_generic(hw, snoop); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_RO_DIS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_ich8lan(hw); return ret_val; } /** * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits * @hw: pointer to the HW structure * * Sets/Clears required hardware bits necessary for correctly setting up the * hardware for transmit and receive. **/ STATIC void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_initialize_hw_bits_ich8lan"); /* Extended Device Control */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg |= (1 << 22); /* Enable PHY low-power state when MAC is at D3 w/o WoL */ if (hw->mac.type >= e1000_pchlan) reg |= E1000_CTRL_EXT_PHYPDEN; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* Transmit Descriptor Control 0 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); /* Transmit Descriptor Control 1 */ reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); /* Transmit Arbitration Control 0 */ reg = E1000_READ_REG(hw, E1000_TARC(0)); if (hw->mac.type == e1000_ich8lan) reg |= (1 << 28) | (1 << 29); reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); E1000_WRITE_REG(hw, E1000_TARC(0), reg); /* Transmit Arbitration Control 1 */ reg = E1000_READ_REG(hw, E1000_TARC(1)); if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) reg &= ~(1 << 28); else reg |= (1 << 28); reg |= (1 << 24) | (1 << 26) | (1 << 30); E1000_WRITE_REG(hw, E1000_TARC(1), reg); /* Device Status */ if (hw->mac.type == e1000_ich8lan) { reg = E1000_READ_REG(hw, E1000_STATUS); reg &= ~(1 << 31); E1000_WRITE_REG(hw, E1000_STATUS, reg); } /* work-around descriptor data corruption issue during nfs v2 udp * traffic, just disable the nfs filtering capability */ reg = E1000_READ_REG(hw, E1000_RFCTL); reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); /* Disable IPv6 extension header parsing because some malformed * IPv6 headers can hang the Rx. */ if (hw->mac.type == e1000_ich8lan) reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); E1000_WRITE_REG(hw, E1000_RFCTL, reg); /* Enable ECC on Lynxpoint */ if (hw->mac.type == e1000_pch_lpt) { reg = E1000_READ_REG(hw, E1000_PBECCSTS); reg |= E1000_PBECCSTS_ECC_ENABLE; E1000_WRITE_REG(hw, E1000_PBECCSTS, reg); reg = E1000_READ_REG(hw, E1000_CTRL); reg |= E1000_CTRL_MEHE; E1000_WRITE_REG(hw, E1000_CTRL, reg); } return; } /** * e1000_setup_link_ich8lan - Setup flow control and link settings * @hw: pointer to the HW structure * * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ STATIC s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_setup_link_ich8lan"); if (hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; /* ICH parts do not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ if (hw->fc.requested_mode == e1000_fc_default) hw->fc.requested_mode = e1000_fc_full; /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); /* Continue to configure the copper link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) return ret_val; E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); if ((hw->phy.type == e1000_phy_82578) || (hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_i217) || (hw->phy.type == e1000_phy_82577)) { E1000_WRITE_REG(hw, E1000_FCRTV_PCH, hw->fc.refresh_time); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), hw->fc.pause_time); if (ret_val) return ret_val; } return e1000_set_fc_watermarks_generic(hw); } /** * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface * @hw: pointer to the HW structure * * Configures the kumeran interface to the PHY to wait the appropriate time * when polling the PHY, then call the generic setup_copper_link to finish * configuring the copper link. **/ STATIC s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_setup_copper_link_ich8lan"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Set the mac to wait the maximum time between each iteration * and increase the max iterations when polling the phy; * this fixes erroneous timeouts at 10Mbps. */ ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF); if (ret_val) return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, ®_data); if (ret_val) return ret_val; reg_data |= 0x3F; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, reg_data); if (ret_val) return ret_val; switch (hw->phy.type) { case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); if (ret_val) return ret_val; break; case e1000_phy_bm: case e1000_phy_82578: ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) return ret_val; break; case e1000_phy_82577: case e1000_phy_82579: ret_val = e1000_copper_link_setup_82577(hw); if (ret_val) return ret_val; break; case e1000_phy_ife: ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, ®_data); if (ret_val) return ret_val; reg_data &= ~IFE_PMC_AUTO_MDIX; switch (hw->phy.mdix) { case 1: reg_data &= ~IFE_PMC_FORCE_MDIX; break; case 2: reg_data |= IFE_PMC_FORCE_MDIX; break; case 0: default: reg_data |= IFE_PMC_AUTO_MDIX; break; } ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, reg_data); if (ret_val) return ret_val; break; default: break; } return e1000_setup_copper_link_generic(hw); } /** * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface * @hw: pointer to the HW structure * * Calls the PHY specific link setup function and then calls the * generic setup_copper_link to finish configuring the link for * Lynxpoint PCH devices **/ STATIC s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_copper_link_pch_lpt"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); ret_val = e1000_copper_link_setup_82577(hw); if (ret_val) return ret_val; return e1000_setup_copper_link_generic(hw); } /** * e1000_get_link_up_info_ich8lan - Get current link speed and duplex * @hw: pointer to the HW structure * @speed: pointer to store current link speed * @duplex: pointer to store the current link duplex * * Calls the generic get_speed_and_duplex to retrieve the current link * information and then calls the Kumeran lock loss workaround for links at * gigabit speeds. **/ STATIC s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex) { s32 ret_val; DEBUGFUNC("e1000_get_link_up_info_ich8lan"); ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); if (ret_val) return ret_val; if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); } return ret_val; } /** * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround * @hw: pointer to the HW structure * * Work-around for 82566 Kumeran PCS lock loss: * On link status change (i.e. PCI reset, speed change) and link is up and * speed is gigabit- * 0) if workaround is optionally disabled do nothing * 1) wait 1ms for Kumeran link to come up * 2) check Kumeran Diagnostic register PCS lock loss bit * 3) if not set the link is locked (all is good), otherwise... * 4) reset the PHY * 5) repeat up to 10 times * Note: this is only called for IGP3 copper when speed is 1gb. **/ STATIC s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 phy_ctrl; s32 ret_val; u16 i, data; bool link; DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); if (!dev_spec->kmrn_lock_loss_workaround_enabled) return E1000_SUCCESS; /* Make sure link is up before proceeding. If not just return. * Attempting this while link is negotiating fouled up link * stability */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (!link) return E1000_SUCCESS; for (i = 0; i < 10; i++) { /* read once to clear */ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); if (ret_val) return ret_val; /* and again to get new status */ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); if (ret_val) return ret_val; /* check for PCS lock */ if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) return E1000_SUCCESS; /* Issue PHY reset */ hw->phy.ops.reset(hw); msec_delay_irq(5); } /* Disable GigE link negotiation */ phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE); E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); /* Call gig speed drop workaround on Gig disable before accessing * any PHY registers */ e1000_gig_downshift_workaround_ich8lan(hw); /* unable to acquire PCS lock */ return -E1000_ERR_PHY; } /** * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state * @hw: pointer to the HW structure * @state: boolean value used to set the current Kumeran workaround state * * If ICH8, set the current Kumeran workaround state (enabled - true * /disabled - false). **/ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan"); if (hw->mac.type != e1000_ich8lan) { DEBUGOUT("Workaround applies to ICH8 only.\n"); return; } dev_spec->kmrn_lock_loss_workaround_enabled = state; return; } /** * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 * @hw: pointer to the HW structure * * Workaround for 82566 power-down on D3 entry: * 1) disable gigabit link * 2) write VR power-down enable * 3) read it back * Continue if successful, else issue LCD reset and repeat **/ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) { u32 reg; u16 data; u8 retry = 0; DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan"); if (hw->phy.type != e1000_phy_igp_3) return; /* Try the workaround twice (if needed) */ do { /* Disable link */ reg = E1000_READ_REG(hw, E1000_PHY_CTRL); reg |= (E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE); E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg); /* Call gig speed drop workaround on Gig disable before * accessing any PHY registers */ if (hw->mac.type == e1000_ich8lan) e1000_gig_downshift_workaround_ich8lan(hw); /* Write VR power-down enable */ hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; hw->phy.ops.write_reg(hw, IGP3_VR_CTRL, data | IGP3_VR_CTRL_MODE_SHUTDOWN); /* Read it back and test */ hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) break; /* Issue PHY reset and repeat at most one more time */ reg = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST); retry++; } while (retry); } /** * e1000_gig_downshift_workaround_ich8lan - WoL from S5 stops working * @hw: pointer to the HW structure * * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), * LPLU, Gig disable, MDIC PHY reset): * 1) Set Kumeran Near-end loopback * 2) Clear Kumeran Near-end loopback * Should only be called for ICH8[m] devices with any 1G Phy. **/ void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) { s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan"); if ((hw->mac.type != e1000_ich8lan) || (hw->phy.type == e1000_phy_ife)) return; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, ®_data); if (ret_val) return; reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); if (ret_val) return; reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); } /** * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx * @hw: pointer to the HW structure * * During S0 to Sx transition, it is possible the link remains at gig * instead of negotiating to a lower speed. Before going to Sx, set * 'Gig Disable' to force link speed negotiation to a lower speed based on * the LPLU setting in the NVM or custom setting. For PCH and newer parts, * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also * needs to be written. * Parts that support (and are linked to a partner which support) EEE in * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power * than 10Mbps w/o EEE. **/ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 phy_ctrl; s32 ret_val; DEBUGFUNC("e1000_suspend_workarounds_ich8lan"); phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; if (hw->phy.type == e1000_phy_i217) { u16 phy_reg, device_id = hw->device_id; if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; if (!dev_spec->eee_disable) { u16 eee_advert; ret_val = e1000_read_emi_reg_locked(hw, I217_EEE_ADVERTISEMENT, &eee_advert); if (ret_val) goto release; /* Disable LPLU if both link partners support 100BaseT * EEE and 100Full is advertised on both ends of the * link, and enable Auto Enable LPI since there will * be no driver to enable LPI while in Sx. */ if ((eee_advert & I82579_EEE_100_SUPPORTED) && (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) && (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) { phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_NOND0A_LPLU); /* Set Auto Enable LPI after link up */ hw->phy.ops.read_reg_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg); phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI; hw->phy.ops.write_reg_locked(hw, I217_LPI_GPIO_CTRL, phy_reg); } } /* For i217 Intel Rapid Start Technology support, * when the system is going into Sx and no manageability engine * is present, the driver must configure proxy to reset only on * power good. LPI (Low Power Idle) state must also reset only * on power good, as well as the MTA (Multicast table array). * The SMBus release must also be disabled on LCD reset. */ if (!(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) { /* Enable proxy to reset only on power good. */ hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL, &phy_reg); phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, phy_reg); /* Set bit enable LPI (EEE) to reset only on * power good. */ hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg); phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg); /* Disable the SMB release on LCD reset. */ hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg); phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg); } /* Enable MTA to reset for Intel Rapid Start Technology * Support */ hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg); phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg); release: hw->phy.ops.release(hw); } out: E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (hw->mac.type == e1000_ich8lan) e1000_gig_downshift_workaround_ich8lan(hw); if (hw->mac.type >= e1000_pchlan) { e1000_oem_bits_config_ich8lan(hw, false); /* Reset PHY to activate OEM bits on 82577/8 */ if (hw->mac.type == e1000_pchlan) e1000_phy_hw_reset_generic(hw); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; e1000_write_smbus_addr(hw); hw->phy.ops.release(hw); } return; } /** * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0 * @hw: pointer to the HW structure * * During Sx to S0 transitions on non-managed devices or managed devices * on which PHY resets are not blocked, if the PHY registers cannot be * accessed properly by the s/w toggle the LANPHYPC value to power cycle * the PHY. * On i217, setup Intel Rapid Start Technology. **/ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_resume_workarounds_pchlan"); if (hw->mac.type < e1000_pch2lan) return; ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) { DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val); return; } /* For i217 Intel Rapid Start Technology support when the system * is transitioning from Sx and no manageability engine is present * configure SMBus to restore on reset, disable proxy, and enable * the reset on MTA (Multicast table array). */ if (hw->phy.type == e1000_phy_i217) { u16 phy_reg; ret_val = hw->phy.ops.acquire(hw); if (ret_val) { DEBUGOUT("Failed to setup iRST\n"); return; } /* Clear Auto Enable LPI after link up */ hw->phy.ops.read_reg_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg); phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI; hw->phy.ops.write_reg_locked(hw, I217_LPI_GPIO_CTRL, phy_reg); if (!(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) { /* Restore clear on SMB if no manageability engine * is present */ ret_val = hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg); if (ret_val) goto release; phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg); /* Disable Proxy */ hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, 0); } /* Enable reset on MTA */ ret_val = hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg); if (ret_val) goto release; phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg); release: if (ret_val) DEBUGOUT1("Error %d in resume workarounds\n", ret_val); hw->phy.ops.release(hw); } } /** * e1000_cleanup_led_ich8lan - Restore the default LED operation * @hw: pointer to the HW structure * * Return the LED back to the default configuration. **/ STATIC s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_cleanup_led_ich8lan"); if (hw->phy.type == e1000_phy_ife) return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); return E1000_SUCCESS; } /** * e1000_led_on_ich8lan - Turn LEDs on * @hw: pointer to the HW structure * * Turn on the LEDs. **/ STATIC s32 e1000_led_on_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_led_on_ich8lan"); if (hw->phy.type == e1000_phy_ife) return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); return E1000_SUCCESS; } /** * e1000_led_off_ich8lan - Turn LEDs off * @hw: pointer to the HW structure * * Turn off the LEDs. **/ STATIC s32 e1000_led_off_ich8lan(struct e1000_hw *hw) { DEBUGFUNC("e1000_led_off_ich8lan"); if (hw->phy.type == e1000_phy_ife) return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); return E1000_SUCCESS; } /** * e1000_setup_led_pchlan - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use. **/ STATIC s32 e1000_setup_led_pchlan(struct e1000_hw *hw) { DEBUGFUNC("e1000_setup_led_pchlan"); return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_mode1); } /** * e1000_cleanup_led_pchlan - Restore the default LED operation * @hw: pointer to the HW structure * * Return the LED back to the default configuration. **/ STATIC s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) { DEBUGFUNC("e1000_cleanup_led_pchlan"); return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_default); } /** * e1000_led_on_pchlan - Turn LEDs on * @hw: pointer to the HW structure * * Turn on the LEDs. **/ STATIC s32 e1000_led_on_pchlan(struct e1000_hw *hw) { u16 data = (u16)hw->mac.ledctl_mode2; u32 i, led; DEBUGFUNC("e1000_led_on_pchlan"); /* If no link, then turn LED on by setting the invert bit * for each LED that's mode is "link_up" in ledctl_mode2. */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { for (i = 0; i < 3; i++) { led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; if ((led & E1000_PHY_LED0_MODE_MASK) != E1000_LEDCTL_MODE_LINK_UP) continue; if (led & E1000_PHY_LED0_IVRT) data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); else data |= (E1000_PHY_LED0_IVRT << (i * 5)); } } return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data); } /** * e1000_led_off_pchlan - Turn LEDs off * @hw: pointer to the HW structure * * Turn off the LEDs. **/ STATIC s32 e1000_led_off_pchlan(struct e1000_hw *hw) { u16 data = (u16)hw->mac.ledctl_mode1; u32 i, led; DEBUGFUNC("e1000_led_off_pchlan"); /* If no link, then turn LED off by clearing the invert bit * for each LED that's mode is "link_up" in ledctl_mode1. */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { for (i = 0; i < 3; i++) { led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; if ((led & E1000_PHY_LED0_MODE_MASK) != E1000_LEDCTL_MODE_LINK_UP) continue; if (led & E1000_PHY_LED0_IVRT) data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); else data |= (E1000_PHY_LED0_IVRT << (i * 5)); } } return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data); } /** * e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset * @hw: pointer to the HW structure * * Read appropriate register for the config done bit for completion status * and configure the PHY through s/w for EEPROM-less parts. * * NOTE: some silicon which is EEPROM-less will fail trying to read the * config done bit, so only an error is logged and continues. If we were * to return with error, EEPROM-less silicon would not be able to be reset * or change link. **/ STATIC s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 bank = 0; u32 status; DEBUGFUNC("e1000_get_cfg_done_ich8lan"); e1000_get_cfg_done_generic(hw); /* Wait for indication from h/w that it has completed basic config */ if (hw->mac.type >= e1000_ich10lan) { e1000_lan_init_done_ich8lan(hw); } else { ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { /* When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ DEBUGOUT("Auto Read Done did not complete\n"); ret_val = E1000_SUCCESS; } } /* Clear PHY Reset Asserted bit */ status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_PHYRA) E1000_WRITE_REG(hw, E1000_STATUS, status & ~E1000_STATUS_PHYRA); else DEBUGOUT("PHY Reset Asserted not set - needs delay\n"); /* If EEPROM is not marked present, init the IGP 3 PHY manually */ if (hw->mac.type <= e1000_ich9lan) { if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) { e1000_phy_init_script_igp3(hw); } } else { if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { /* Maybe we should do a basic PHY config */ DEBUGOUT("EEPROM not present\n"); ret_val = -E1000_ERR_CONFIG; } } return ret_val; } /** * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ STATIC void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) { /* If the management interface is not enabled, then power down */ if (!(hw->mac.ops.check_mng_mode(hw) || hw->phy.ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters * @hw: pointer to the HW structure * * Clears hardware counters specific to the silicon family and calls * clear_hw_cntrs_generic to clear all general purpose counters. **/ STATIC void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) { u16 phy_data; s32 ret_val; DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); E1000_READ_REG(hw, E1000_IAC); E1000_READ_REG(hw, E1000_ICRXOC); /* Clear PHY statistics registers */ if ((hw->phy.type == e1000_phy_82578) || (hw->phy.type == e1000_phy_82579) || (hw->phy.type == e1000_phy_i217) || (hw->phy.type == e1000_phy_82577)) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; ret_val = hw->phy.ops.set_page(hw, HV_STATS_PAGE << IGP_PAGE_SHIFT); if (ret_val) goto release; hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); release: hw->phy.ops.release(hw); } } ================================================ FILE: drivers/net/e1000/base/e1000_ich8lan.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_ICH8LAN_H_ #define _E1000_ICH8LAN_H_ #define ICH_FLASH_GFPREG 0x0000 #define ICH_FLASH_HSFSTS 0x0004 #define ICH_FLASH_HSFCTL 0x0006 #define ICH_FLASH_FADDR 0x0008 #define ICH_FLASH_FDATA0 0x0010 /* Requires up to 10 seconds when MNG might be accessing part. */ #define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 #define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 #define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 #define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF #define ICH_FLASH_CYCLE_REPEAT_COUNT 10 #define ICH_CYCLE_READ 0 #define ICH_CYCLE_WRITE 2 #define ICH_CYCLE_ERASE 3 #define FLASH_GFPREG_BASE_MASK 0x1FFF #define FLASH_SECTOR_ADDR_SHIFT 12 #define ICH_FLASH_SEG_SIZE_256 256 #define ICH_FLASH_SEG_SIZE_4K 4096 #define ICH_FLASH_SEG_SIZE_8K 8192 #define ICH_FLASH_SEG_SIZE_64K 65536 #define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ /* FW established a valid mode */ #define E1000_ICH_FWSM_FW_VALID 0x00008000 #define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ #define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000 #define E1000_ICH_MNG_IAMT_MODE 0x2 #define E1000_FWSM_WLOCK_MAC_MASK 0x0380 #define E1000_FWSM_WLOCK_MAC_SHIFT 7 #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) #define E1000_FWSM_ULP_CFG_DONE 0x00000400 /* Low power cfg done */ #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ /* Shared Receive Address Registers */ #define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) #define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) #define E1000_H2ME 0x05B50 /* Host to ME */ #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) #define E1000_H2ME_ULP 0x00000800 /* ULP Indication Bit */ #define E1000_H2ME_ENFORCE_SETTINGS 0x00001000 /* Enforce Settings */ #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ #define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ (ID_LED_OFF1_OFF2 << 8) | \ (ID_LED_OFF1_ON2 << 4) | \ (ID_LED_DEF1_DEF2)) #define E1000_ICH_NVM_SIG_WORD 0x13 #define E1000_ICH_NVM_SIG_MASK 0xC000 #define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 #define E1000_ICH_NVM_SIG_VALUE 0x80 #define E1000_ICH8_LAN_INIT_TIMEOUT 1500 #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) /* FEXT register bit definition */ #define E1000_FEXT_PHY_CABLE_DISCONNECTED 0x00000004 #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ #define E1000_FEXTNVM_SW_CONFIG 1 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */ #define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000 #define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000 #define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) #define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 #define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */ #define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ #define PHY_PAGE_SHIFT 5 #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ ((reg) & MAX_PHY_REG_ADDRESS)) #define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ #define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ #define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 #define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 #define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 /* PHY Wakeup Registers and defines */ #define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) #define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) #define BM_WUC PHY_REG(BM_WUC_PAGE, 1) #define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) #define BM_WUS PHY_REG(BM_WUC_PAGE, 3) #define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) #define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) #define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) #define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) #define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) #define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ #define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ #define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ #define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ #define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ #define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ #define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ #define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ #define HV_MUX_DATA_CTRL PHY_REG(776, 16) #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 #define HV_STATS_PAGE 778 /* Half-duplex collision counts */ #define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision */ #define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) #define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. */ #define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) #define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Collision */ #define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) #define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision */ #define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) #define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision */ #define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) #define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ #define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) #define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Tx with no CRS */ #define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30) #define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ /* SMBus Control Phy Register */ #define CV_SMB_CTRL PHY_REG(769, 23) #define CV_SMB_CTRL_FORCE_SMBUS 0x0001 #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) /* I218 Ultra Low Power Configuration 1 Register */ #define I218_ULP_CONFIG1 PHY_REG(779, 16) #define I218_ULP_CONFIG1_START 0x0001 /* Start auto ULP config */ #define I218_ULP_CONFIG1_IND 0x0004 /* Pwr up from ULP indication */ #define I218_ULP_CONFIG1_STICKY_ULP 0x0010 /* Set sticky ULP mode */ #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ /* SMBus Address Phy Register */ #define HV_SMB_ADDR PHY_REG(768, 26) #define HV_SMB_ADDR_MASK 0x007F #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 #define HV_SMB_ADDR_FREQ_MASK 0x1100 #define HV_SMB_ADDR_FREQ_LOW_SHIFT 8 #define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12 /* Strapping Option Register - RO */ #define E1000_STRAP 0x0000C #define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 #define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 #define E1000_STRAP_SMT_FREQ_MASK 0x00003000 #define E1000_STRAP_SMT_FREQ_SHIFT 12 /* OEM Bits Phy Register */ #define HV_OEM_BITS PHY_REG(768, 25) #define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ #define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ /* KMRN Mode Control */ #define HV_KMRN_MODE_CTRL PHY_REG(769, 16) #define HV_KMRN_MDIO_SLOW 0x0400 /* KMRN FIFO Control and Status */ #define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16) #define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000 #define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12 /* PHY Power Management Control */ #define HV_PM_CTRL PHY_REG(770, 17) #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define HV_PM_CTRL_K1_ENABLE 0x4000 #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* Inband Control */ #define I217_INBAND_CTRL PHY_REG(770, 18) #define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK 0x3F00 #define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT 8 /* Low Power Idle GPIO Control */ #define I217_LPI_GPIO_CTRL PHY_REG(772, 18) #define I217_LPI_GPIO_CTRL_AUTO_EN_LPI 0x0800 /* PHY Low Power Idle Control */ #define I82579_LPI_CTRL PHY_REG(772, 20) #define I82579_LPI_CTRL_100_ENABLE 0x2000 #define I82579_LPI_CTRL_1000_ENABLE 0x4000 #define I82579_LPI_CTRL_ENABLE_MASK 0x6000 /* 82579 DFT Control */ #define I82579_DFT_CTRL PHY_REG(769, 20) #define I82579_DFT_CTRL_GATE_PHY_RESET 0x0040 /* Gate PHY Reset on MAC Reset */ /* Extended Management Interface (EMI) Registers */ #define I82579_EMI_ADDR 0x10 #define I82579_EMI_DATA 0x11 #define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ #define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */ #define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ #define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ #define I82579_RX_CONFIG 0x3412 /* Receive configuration */ #define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ #define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ #define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ #define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ #define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ #define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ #define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ #define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ #define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ #define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ #define I217_RX_CONFIG 0xB20C /* Receive configuration */ #define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ #define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ /* Intel Rapid Start Technology Support */ #define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) #define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 #define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) #define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 #define I217_CGFREG PHY_REG(772, 29) #define I217_CGFREG_ENABLE_MTA_RESET 0x0002 #define I217_MEMPWR PHY_REG(772, 26) #define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 /* Receive Address Initial CRC Calculation */ #define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) #if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) #define E1000_PCI_REVISION_ID_REG 0x08 #endif /* defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT) */ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data); s32 e1000_set_eee_pchlan(struct e1000_hw *hw); #if defined(NAHUM6LP_HW) && defined(ULP_SUPPORT) s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx); s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force); #endif /* NAHUM6LP_HW && ULP_SUPPORT */ #endif /* _E1000_ICH8LAN_H_ */ void e1000_demote_ltr(struct e1000_hw *hw, bool demote, bool link); ================================================ FILE: drivers/net/e1000/base/e1000_mac.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); STATIC void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw); STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); /** * e1000_init_mac_ops_generic - Initialize MAC function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_mac_ops_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_ops_generic"); /* General Setup */ mac->ops.init_params = e1000_null_ops_generic; mac->ops.init_hw = e1000_null_ops_generic; mac->ops.reset_hw = e1000_null_ops_generic; mac->ops.setup_physical_interface = e1000_null_ops_generic; mac->ops.get_bus_info = e1000_null_ops_generic; mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; mac->ops.read_mac_addr = e1000_read_mac_addr_generic; mac->ops.config_collision_dist = e1000_config_collision_dist_generic; mac->ops.clear_hw_cntrs = e1000_null_mac_generic; /* LED */ mac->ops.cleanup_led = e1000_null_ops_generic; mac->ops.setup_led = e1000_null_ops_generic; mac->ops.blink_led = e1000_null_ops_generic; mac->ops.led_on = e1000_null_ops_generic; mac->ops.led_off = e1000_null_ops_generic; /* LINK */ mac->ops.setup_link = e1000_null_ops_generic; mac->ops.get_link_up_info = e1000_null_link_info; mac->ops.check_for_link = e1000_null_ops_generic; /* Management */ mac->ops.check_mng_mode = e1000_null_mng_mode; /* VLAN, MC, etc. */ mac->ops.update_mc_addr_list = e1000_null_update_mc; mac->ops.clear_vfta = e1000_null_mac_generic; mac->ops.write_vfta = e1000_null_write_vfta; mac->ops.rar_set = e1000_rar_set_generic; mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; } /** * e1000_null_ops_generic - No-op function, returns 0 * @hw: pointer to the HW structure **/ s32 e1000_null_ops_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_ops_generic"); UNREFERENCED_1PARAMETER(hw); return E1000_SUCCESS; } /** * e1000_null_mac_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_mac_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_mac_generic"); UNREFERENCED_1PARAMETER(hw); return; } /** * e1000_null_link_info - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_link_info(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d) { DEBUGFUNC("e1000_null_link_info"); UNREFERENCED_3PARAMETER(hw, s, d); return E1000_SUCCESS; } /** * e1000_null_mng_mode - No-op function, return false * @hw: pointer to the HW structure **/ bool e1000_null_mng_mode(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_mng_mode"); UNREFERENCED_1PARAMETER(hw); return false; } /** * e1000_null_update_mc - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_update_mc(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a) { DEBUGFUNC("e1000_null_update_mc"); UNREFERENCED_3PARAMETER(hw, h, a); return; } /** * e1000_null_write_vfta - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_write_vfta(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG a, u32 E1000_UNUSEDARG b) { DEBUGFUNC("e1000_null_write_vfta"); UNREFERENCED_3PARAMETER(hw, a, b); return; } /** * e1000_null_rar_set - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_rar_set(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a) { DEBUGFUNC("e1000_null_rar_set"); UNREFERENCED_3PARAMETER(hw, h, a); return; } /** * e1000_get_bus_info_pci_generic - Get PCI(x) bus information * @hw: pointer to the HW structure * * Determines and stores the system bus information for a particular * network interface. The following bus information is determined and stored: * bus speed, bus width, type (PCI/PCIx), and PCI(-x) function. **/ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; u32 status = E1000_READ_REG(hw, E1000_STATUS); s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_get_bus_info_pci_generic"); /* PCI or PCI-X? */ bus->type = (status & E1000_STATUS_PCIX_MODE) ? e1000_bus_type_pcix : e1000_bus_type_pci; /* Bus speed */ if (bus->type == e1000_bus_type_pci) { bus->speed = (status & E1000_STATUS_PCI66) ? e1000_bus_speed_66 : e1000_bus_speed_33; } else { switch (status & E1000_STATUS_PCIX_SPEED) { case E1000_STATUS_PCIX_SPEED_66: bus->speed = e1000_bus_speed_66; break; case E1000_STATUS_PCIX_SPEED_100: bus->speed = e1000_bus_speed_100; break; case E1000_STATUS_PCIX_SPEED_133: bus->speed = e1000_bus_speed_133; break; default: bus->speed = e1000_bus_speed_reserved; break; } } /* Bus width */ bus->width = (status & E1000_STATUS_BUS64) ? e1000_bus_width_64 : e1000_bus_width_32; /* Which PCI(-X) function? */ mac->ops.set_lan_id(hw); return ret_val; } /** * e1000_get_bus_info_pcie_generic - Get PCIe bus information * @hw: pointer to the HW structure * * Determines and stores the system bus information for a particular * network interface. The following bus information is determined and stored: * bus speed, bus width, type (PCIe), and PCIe function. **/ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; s32 ret_val; u16 pcie_link_status; DEBUGFUNC("e1000_get_bus_info_pcie_generic"); bus->type = e1000_bus_type_pci_express; ret_val = e1000_read_pcie_cap_reg(hw, PCIE_LINK_STATUS, &pcie_link_status); if (ret_val) { bus->width = e1000_bus_width_unknown; bus->speed = e1000_bus_speed_unknown; } else { switch (pcie_link_status & PCIE_LINK_SPEED_MASK) { case PCIE_LINK_SPEED_2500: bus->speed = e1000_bus_speed_2500; break; case PCIE_LINK_SPEED_5000: bus->speed = e1000_bus_speed_5000; break; default: bus->speed = e1000_bus_speed_unknown; break; } bus->width = (enum e1000_bus_width)((pcie_link_status & PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT); } mac->ops.set_lan_id(hw); return E1000_SUCCESS; } /** * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices * * @hw: pointer to the HW structure * * Determines the LAN function id by reading memory-mapped registers * and swaps the port value if requested. **/ STATIC void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; u32 reg; /* The status register reports the correct function number * for the device regardless of function swap state. */ reg = E1000_READ_REG(hw, E1000_STATUS); bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; } /** * e1000_set_lan_id_multi_port_pci - Set LAN id for PCI multiple port devices * @hw: pointer to the HW structure * * Determines the LAN function id by reading PCI config space. **/ void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; u16 pci_header_type; u32 status; e1000_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type); if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { status = E1000_READ_REG(hw, E1000_STATUS); bus->func = (status & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; } else { bus->func = 0; } } /** * e1000_set_lan_id_single_port - Set LAN id for a single port device * @hw: pointer to the HW structure * * Sets the LAN function id to zero for a single port device. **/ void e1000_set_lan_id_single_port(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; bus->func = 0; } /** * e1000_clear_vfta_generic - Clear VLAN filter table * @hw: pointer to the HW structure * * Clears the register array which contains the VLAN filter table by * setting all the values to 0. **/ void e1000_clear_vfta_generic(struct e1000_hw *hw) { u32 offset; DEBUGFUNC("e1000_clear_vfta_generic"); for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); E1000_WRITE_FLUSH(hw); } } /** * e1000_write_vfta_generic - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: register offset in VLAN filter table * @value: register value written to VLAN filter table * * Writes value at the given offset in the register array which stores * the VLAN filter table. **/ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) { DEBUGFUNC("e1000_write_vfta_generic"); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); } /** * e1000_init_rx_addrs_generic - Initialize receive address's * @hw: pointer to the HW structure * @rar_count: receive address registers * * Setup the receive address registers by setting the base receive address * register to the devices MAC address and clearing all the other receive * address registers to 0. **/ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) { u32 i; u8 mac_addr[ETH_ADDR_LEN] = {0}; DEBUGFUNC("e1000_init_rx_addrs_generic"); /* Setup the receive address */ DEBUGOUT("Programming MAC Address into RAR[0]\n"); hw->mac.ops.rar_set(hw, hw->mac.addr, 0); /* Zero out the other (rar_entry_count - 1) receive addresses */ DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); for (i = 1; i < rar_count; i++) hw->mac.ops.rar_set(hw, mac_addr, i); } /** * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr * @hw: pointer to the HW structure * * Checks the nvm for an alternate MAC address. An alternate MAC address * can be setup by pre-boot software and must be treated like a permanent * address and must override the actual permanent MAC address. If an * alternate MAC address is found it is programmed into RAR0, replacing * the permanent address that was installed into RAR0 by the Si on reset. * This function will return SUCCESS unless it encounters an error while * reading the EEPROM. **/ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) { u32 i; s32 ret_val; u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ADDR_LEN]; DEBUGFUNC("e1000_check_alt_mac_addr_generic"); ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data); if (ret_val) return ret_val; /* not supported on older hardware or 82573 */ if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573)) return E1000_SUCCESS; /* Alternate MAC address is handled by the option ROM for 82580 * and newer. SW support not required. */ if (hw->mac.type >= e1000_82580) return E1000_SUCCESS; ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if ((nvm_alt_mac_addr_offset == 0xFFFF) || (nvm_alt_mac_addr_offset == 0x0000)) /* There is no Alternate MAC Address */ return E1000_SUCCESS; if (hw->bus.func == E1000_FUNC_1) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; if (hw->bus.func == E1000_FUNC_2) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN2; if (hw->bus.func == E1000_FUNC_3) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN3; for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = nvm_alt_mac_addr_offset + (i >> 1); ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } alt_mac_addr[i] = (u8)(nvm_data & 0xFF); alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); } /* if multicast bit is set, the alternate address will not be used */ if (alt_mac_addr[0] & 0x01) { DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); return E1000_SUCCESS; } /* We have a valid alternate MAC address, and we want to treat it the * same as the normal permanent MAC address stored by the HW into the * RAR. Do this by mapping this address into RAR0. */ hw->mac.ops.rar_set(hw, alt_mac_addr, 0); return E1000_SUCCESS; } /** * e1000_rar_set_generic - Set receive address register * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index: receive address array register * * Sets the receive address array register at index to the address passed * in by addr. **/ STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; DEBUGFUNC("e1000_rar_set_generic"); /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) rar_high |= E1000_RAH_AV; /* Some bridges will combine consecutive 32-bit writes into * a single burst write, which will malfunction on some parts. * The flushes avoid this. */ E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); E1000_WRITE_FLUSH(hw); } /** * e1000_hash_mc_addr_generic - Generate a multicast hash value * @hw: pointer to the HW structure * @mc_addr: pointer to a multicast address * * Generates a multicast address hash value which is used to determine * the multicast filter table array address and new table value. **/ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) { u32 hash_value, hash_mask; u8 bit_shift = 0; DEBUGFUNC("e1000_hash_mc_addr_generic"); /* Register count multiplied by bits per register */ hash_mask = (hw->mac.mta_reg_count * 32) - 1; /* For a mc_filter_type of 0, bit_shift is the number of left-shifts * where 0xFF would still fall within the hash mask. */ while (hash_mask >> bit_shift != 0xFF) bit_shift++; /* The portion of the address that is used for the hash table * is determined by the mc_filter_type setting. * The algorithm is such that there is a total of 8 bits of shifting. * The bit_shift for a mc_filter_type of 0 represents the number of * left-shifts where the MSB of mc_addr[5] would still fall within * the hash_mask. Case 0 does this exactly. Since there are a total * of 8 bits of shifting, then mc_addr[4] will shift right the * remaining number of bits. Thus 8 - bit_shift. The rest of the * cases are a variation of this algorithm...essentially raising the * number of bits to shift mc_addr[5] left, while still keeping the * 8-bit shifting total. * * For example, given the following Destination MAC Address and an * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), * we can see that the bit_shift for case 0 is 4. These are the hash * values resulting from each mc_filter_type... * [0] [1] [2] [3] [4] [5] * 01 AA 00 12 34 56 * LSB MSB * * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 */ switch (hw->mac.mc_filter_type) { default: case 0: break; case 1: bit_shift += 1; break; case 2: bit_shift += 2; break; case 3: bit_shift += 4; break; } hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | (((u16) mc_addr[5]) << bit_shift))); return hash_value; } /** * e1000_update_mc_addr_list_generic - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates entire Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. **/ void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { u32 hash_value, hash_bit, hash_reg; int i; DEBUGFUNC("e1000_update_mc_addr_list_generic"); /* clear mta_shadow */ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); /* update mta_shadow from mc_addr_list */ for (i = 0; (u32) i < mc_addr_count; i++) { hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); hash_bit = hash_value & 0x1F; hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); mc_addr_list += (ETH_ADDR_LEN); } /* replace the entire MTA table */ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); E1000_WRITE_FLUSH(hw); } /** * e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value * @hw: pointer to the HW structure * * In certain situations, a system BIOS may report that the PCIx maximum * memory read byte count (MMRBC) value is higher than than the actual * value. We check the PCIx command register with the current PCIx status * register. **/ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw) { u16 cmd_mmrbc; u16 pcix_cmd; u16 pcix_stat_hi_word; u16 stat_mmrbc; DEBUGFUNC("e1000_pcix_mmrbc_workaround_generic"); /* Workaround for PCI-X issue when BIOS sets MMRBC incorrectly */ if (hw->bus.type != e1000_bus_type_pcix) return; e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd); e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >> PCIX_COMMAND_MMRBC_SHIFT; stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> PCIX_STATUS_HI_MMRBC_SHIFT; if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; if (cmd_mmrbc > stat_mmrbc) { pcix_cmd &= ~PCIX_COMMAND_MMRBC_MASK; pcix_cmd |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd); } } /** * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters * @hw: pointer to the HW structure * * Clears the base hardware counters by reading the counter registers. **/ void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); E1000_READ_REG(hw, E1000_CRCERRS); E1000_READ_REG(hw, E1000_SYMERRS); E1000_READ_REG(hw, E1000_MPC); E1000_READ_REG(hw, E1000_SCC); E1000_READ_REG(hw, E1000_ECOL); E1000_READ_REG(hw, E1000_MCC); E1000_READ_REG(hw, E1000_LATECOL); E1000_READ_REG(hw, E1000_COLC); E1000_READ_REG(hw, E1000_DC); E1000_READ_REG(hw, E1000_SEC); E1000_READ_REG(hw, E1000_RLEC); E1000_READ_REG(hw, E1000_XONRXC); E1000_READ_REG(hw, E1000_XONTXC); E1000_READ_REG(hw, E1000_XOFFRXC); E1000_READ_REG(hw, E1000_XOFFTXC); E1000_READ_REG(hw, E1000_FCRUC); E1000_READ_REG(hw, E1000_GPRC); E1000_READ_REG(hw, E1000_BPRC); E1000_READ_REG(hw, E1000_MPRC); E1000_READ_REG(hw, E1000_GPTC); E1000_READ_REG(hw, E1000_GORCL); E1000_READ_REG(hw, E1000_GORCH); E1000_READ_REG(hw, E1000_GOTCL); E1000_READ_REG(hw, E1000_GOTCH); E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_RUC); E1000_READ_REG(hw, E1000_RFC); E1000_READ_REG(hw, E1000_ROC); E1000_READ_REG(hw, E1000_RJC); E1000_READ_REG(hw, E1000_TORL); E1000_READ_REG(hw, E1000_TORH); E1000_READ_REG(hw, E1000_TOTL); E1000_READ_REG(hw, E1000_TOTH); E1000_READ_REG(hw, E1000_TPR); E1000_READ_REG(hw, E1000_TPT); E1000_READ_REG(hw, E1000_MPTC); E1000_READ_REG(hw, E1000_BPTC); } /** * e1000_check_for_copper_link_generic - Check for link (Copper) * @hw: pointer to the HW structure * * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. **/ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; bool link; DEBUGFUNC("e1000_check_for_copper_link"); /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) return E1000_SUCCESS; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) return E1000_SUCCESS; /* No link detected */ mac->get_link_status = false; /* Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); return ret_val; } /** * e1000_check_for_fiber_link_generic - Check for link (Fiber) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw; u32 ctrl; u32 status; s32 ret_val; DEBUGFUNC("e1000_check_for_fiber_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also * need to give auto-negotiation time to complete, in case the cable * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) { mac->autoneg_failed = true; return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = true; } return E1000_SUCCESS; } /** * e1000_check_for_serdes_link_generic - Check for link (Serdes) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw; u32 ctrl; u32 status; s32 ret_val; DEBUGFUNC("e1000_check_for_serdes_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), and our link partner is not trying to * auto-negotiate with us (we are receiving idles or data), * we need to force link up. We also need to give auto-negotiation * time to complete. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) { mac->autoneg_failed = true; return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = true; } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { /* If we force link for non-auto-negotiation switch, check * link status based on MAC synchronization for internal * serdes media type. */ /* SYNCH bit and IV bit are sticky. */ usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; DEBUGOUT("SERDES: Link up - forced.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - force failed.\n"); } } if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) { /* SYNCH bit and IV bit are sticky, so reread rxcw. */ usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; DEBUGOUT("SERDES: Link up - autoneg completed successfully.\n"); } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - invalid codewords detected in autoneg.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - no sync.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - autoneg failed\n"); } } return E1000_SUCCESS; } /** * e1000_set_default_fc_generic - Set flow control default values * @hw: pointer to the HW structure * * Read the EEPROM for the default values for flow control and store the * values. **/ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) { s32 ret_val; u16 nvm_data; u16 nvm_offset = 0; DEBUGFUNC("e1000_set_default_fc_generic"); /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or * disabling auto-negotiation, and the direction of the * SW defined pins. If there is no SW over-ride of the flow * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ if (hw->mac.type == e1000_i350) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func); ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG + nvm_offset, 1, &nvm_data); } else { ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); } if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) hw->fc.requested_mode = e1000_fc_none; else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) hw->fc.requested_mode = e1000_fc_tx_pause; else hw->fc.requested_mode = e1000_fc_full; return E1000_SUCCESS; } /** * e1000_setup_link_generic - Setup flow control and link settings * @hw: pointer to the HW structure * * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ s32 e1000_setup_link_generic(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_setup_link_generic"); /* In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; /* If requested flow control is set to default, set flow control * based on the EEPROM flow control settings. */ if (hw->fc.requested_mode == e1000_fc_default) { ret_val = e1000_set_default_fc_generic(hw); if (ret_val) return ret_val; } /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) return ret_val; /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. */ DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); return e1000_set_fc_watermarks_generic(hw); } /** * e1000_commit_fc_settings_generic - Configure flow control * @hw: pointer to the HW structure * * Write the flow control settings to the Transmit Config Word Register (TXCW) * base on the flow control settings in e1000_mac_info. **/ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 txcw; DEBUGFUNC("e1000_commit_fc_settings_generic"); /* Check for a software override of the flow control settings, and * setup the device accordingly. If auto-negotiation is enabled, then * software will have to set the "PAUSE" bits to the correct value in * the Transmit Config Word Register (TXCW) and re-start auto- * negotiation. However, if auto-negotiation is disabled, then * software will have to manually configure the two flow control enable * bits in the CTRL register. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we * do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. */ switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control completely disabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: /* Rx Flow control is enabled and Tx Flow control is disabled * by a software over-ride. Since there really isn't a way to * advertise that we are capable of Rx Pause ONLY, we will * advertise that we support both symmetric and asymmetric Rx * PAUSE. Later, we will disable the adapter's ability to send * PAUSE frames. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is disabled, * by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; break; } E1000_WRITE_REG(hw, E1000_TXCW, txcw); mac->txcw = txcw; return E1000_SUCCESS; } /** * e1000_poll_fiber_serdes_link_generic - Poll for link up * @hw: pointer to the HW structure * * Polls for link up by reading the status register, if link fails to come * up with auto-negotiation, then the link is forced if a signal is detected. **/ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 i, status; s32 ret_val; DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); /* If we have a signal (the cable is plugged in, or assumed true for * serdes media) then poll for a "Link-Up" indication in the Device * Status Register. Time-out if a link isn't seen in 500 milliseconds * seconds (Auto-negotiation should complete in less than 500 * milliseconds even if the other end is doing it in SW). */ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { msec_delay(10); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) break; } if (i == FIBER_LINK_UP_LIMIT) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); mac->autoneg_failed = true; /* AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the * link up if we detect a signal. This will allow us to * communicate with non-autonegotiating link partners. */ ret_val = mac->ops.check_for_link(hw); if (ret_val) { DEBUGOUT("Error while checking for link\n"); return ret_val; } mac->autoneg_failed = false; } else { mac->autoneg_failed = false; DEBUGOUT("Valid Link Found\n"); } return E1000_SUCCESS; } /** * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Configures collision distance and flow control for fiber and serdes * links. Upon successful setup, poll for link. **/ s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Take the link out of reset */ ctrl &= ~E1000_CTRL_LRST; hw->mac.ops.config_collision_dist(hw); ret_val = e1000_commit_fc_settings_generic(hw); if (ret_val) return ret_val; /* Since auto-negotiation is enabled, take the link out of reset (the * link will be in reset, because we previously reset the chip). This * will restart auto-negotiation. If auto-negotiation is successful * then the link-up status bit will be set and the flow control enable * bits (RFCE and TFCE) will be set according to their negotiated value. */ DEBUGOUT("Auto-negotiation enabled\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); msec_delay(1); /* For these adapters, the SW definable pin 1 is set when the optics * detect a signal. If we have a signal, then poll for a "Link-Up" * indication. */ if (hw->phy.media_type == e1000_media_type_internal_serdes || (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { ret_val = e1000_poll_fiber_serdes_link_generic(hw); } else { DEBUGOUT("No signal detected\n"); } return ret_val; } /** * e1000_config_collision_dist_generic - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw) { u32 tctl; DEBUGFUNC("e1000_config_collision_dist_generic"); tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_COLD; tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_FLUSH(hw); } /** * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks * @hw: pointer to the HW structure * * Sets the flow control high/low threshold (watermark) registers. If * flow control XON frame transmission is enabled, then set XON frame * transmission as well. **/ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) { u32 fcrtl = 0, fcrth = 0; DEBUGFUNC("e1000_set_fc_watermarks_generic"); /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ if (hw->fc.current_mode & e1000_fc_tx_pause) { /* We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of * XON frames. */ fcrtl = hw->fc.low_water; if (hw->fc.send_xon) fcrtl |= E1000_FCRTL_XONE; fcrth = hw->fc.high_water; } E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); return E1000_SUCCESS; } /** * e1000_force_mac_fc_generic - Force the MAC's flow control settings * @hw: pointer to the HW structure * * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the * device control register to reflect the adapter settings. TFCE and RFCE * need to be explicitly set by software when a copper PHY is used because * autonegotiation is managed by the PHY rather than the MAC. Software must * also configure these bits when link is forced on a fiber connection. **/ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_force_mac_fc_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Because we didn't get link via the internal auto-negotiation * mechanism (we either forced link or we got link via PHY * auto-neg), we have to manually enable/disable transmit an * receive flow control. * * The "Case" statement below enables/disable flow control * according to the "hw->fc.current_mode" parameter. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause * frames but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames * frames but we do not receive pause frames). * 3: Both Rx and Tx flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); switch (hw->fc.current_mode) { case e1000_fc_none: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; case e1000_fc_rx_pause: ctrl &= (~E1000_CTRL_TFCE); ctrl |= E1000_CTRL_RFCE; break; case e1000_fc_tx_pause: ctrl &= (~E1000_CTRL_RFCE); ctrl |= E1000_CTRL_TFCE; break; case e1000_fc_full: ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_config_fc_after_link_up_generic - Configures flow control after link * @hw: pointer to the HW structure * * Checks the status of auto-negotiation after link up to ensure that the * speed and duplex were not forced. If the link needed to be forced, then * flow control needs to be forced also. If auto-negotiation is enabled * and did not fail, then we configure flow control based on our link * partner. **/ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; DEBUGFUNC("e1000_config_fc_after_link_up_generic"); /* Check for the case where we have fiber media and auto-neg failed * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ if (mac->autoneg_failed) { if (hw->phy.media_type == e1000_media_type_fiber || hw->phy.media_type == e1000_media_type_internal_serdes) ret_val = e1000_force_mac_fc_generic(hw); } else { if (hw->phy.media_type == e1000_media_type_copper) ret_val = e1000_force_mac_fc_generic(hw); } if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } /* Check for the case where we have copper media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); return ret_val; } /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (Address 4) and the Auto_Negotiation Base * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base * Page Ability Register (Address 5) determine flow control * for both the PHY and the link partner. The following * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, * 1999, describes these PAUSE resolution bits and how flow * control is determined based upon these settings. * NOTE: DC = Don't Care * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution *-------|---------|-------|---------|-------------------- * 0 | 0 | DC | DC | e1000_fc_none * 0 | 1 | 0 | DC | e1000_fc_none * 0 | 1 | 1 | 0 | e1000_fc_none * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * 1 | 0 | 0 | DC | e1000_fc_none * 1 | DC | 1 | DC | e1000_fc_full * 1 | 1 | 0 | 0 | e1000_fc_none * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * * Are both PAUSE bits set to 1? If so, this implies * Symmetric Flow Control is enabled at both ends. The * ASM_DIR bits are irrelevant per the spec. * * For Symmetric Flow Control: * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | DC | 1 | DC | E1000_fc_full * */ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause */ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause */ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } else { /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } /* Now we need to do one last check... If we auto- * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); return ret_val; } if (duplex == HALF_DUPLEX) hw->fc.current_mode = e1000_fc_none; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000_force_mac_fc_generic(hw); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } } /* Check for the case where we have SerDes media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_internal_serdes) && mac->autoneg) { /* Read the PCS_LSTS and check to see if AutoNeg * has completed. */ pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT); if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { DEBUGOUT("PCS Auto Neg has not completed.\n"); return ret_val; } /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (PCS_ANADV) and the Auto_Negotiation Base * Page Ability Register (PCS_LPAB) to determine how * flow control was negotiated. */ pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB); /* Two bits in the Auto Negotiation Advertisement Register * (PCS_ANADV) and two bits in the Auto Negotiation Base * Page Ability Register (PCS_LPAB) determine flow control * for both the PHY and the link partner. The following * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, * 1999, describes these PAUSE resolution bits and how flow * control is determined based upon these settings. * NOTE: DC = Don't Care * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution *-------|---------|-------|---------|-------------------- * 0 | 0 | DC | DC | e1000_fc_none * 0 | 1 | 0 | DC | e1000_fc_none * 0 | 1 | 1 | 0 | e1000_fc_none * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * 1 | 0 | 0 | DC | e1000_fc_none * 1 | DC | 1 | DC | e1000_fc_full * 1 | 1 | 0 | 0 | e1000_fc_none * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * * Are both PAUSE bits set to 1? If so, this implies * Symmetric Flow Control is enabled at both ends. The * ASM_DIR bits are irrelevant per the spec. * * For Symmetric Flow Control: * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | DC | 1 | DC | e1000_fc_full * */ if ((pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause */ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_adv_reg & E1000_TXCW_ASM_DIR) && (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause */ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_adv_reg & E1000_TXCW_ASM_DIR) && !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } else { /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL); pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg); ret_val = e1000_force_mac_fc_generic(hw); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } } return E1000_SUCCESS; } /** * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Read the status register for the current speed/duplex and store the current * speed and duplex for copper connections. **/ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex) { u32 status; DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic"); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; DEBUGOUT("1000 Mbs, "); } else if (status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; DEBUGOUT("100 Mbs, "); } else { *speed = SPEED_10; DEBUGOUT("10 Mbs, "); } if (status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; DEBUGOUT("Half Duplex\n"); } return E1000_SUCCESS; } /** * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Sets the speed and duplex to gigabit full duplex (the only possible option) * for fiber/serdes links. **/ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw, u16 *speed, u16 *duplex) { DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); UNREFERENCED_1PARAMETER(hw); *speed = SPEED_1000; *duplex = FULL_DUPLEX; return E1000_SUCCESS; } /** * e1000_get_hw_semaphore_generic - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_generic"); /* Get the SW semaphore */ while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_put_hw_semaphore_generic - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; DEBUGFUNC("e1000_put_hw_semaphore_generic"); swsm = E1000_READ_REG(hw, E1000_SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, E1000_SWSM, swsm); } /** * e1000_get_auto_rd_done_generic - Check for auto read completion * @hw: pointer to the HW structure * * Check EEPROM for Auto Read done bit. **/ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) { s32 i = 0; DEBUGFUNC("e1000_get_auto_rd_done_generic"); while (i < AUTO_READ_DONE_TIMEOUT) { if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) break; msec_delay(1); i++; } if (i == AUTO_READ_DONE_TIMEOUT) { DEBUGOUT("Auto read by HW from NVM has not completed.\n"); return -E1000_ERR_RESET; } return E1000_SUCCESS; } /** * e1000_valid_led_default_generic - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_generic"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; return E1000_SUCCESS; } /** * e1000_id_led_init_generic - * @hw: pointer to the HW structure * **/ s32 e1000_id_led_init_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; const u32 ledctl_mask = 0x000000FF; const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; u16 data, i, temp; const u16 led_mask = 0x0F; DEBUGFUNC("e1000_id_led_init_generic"); ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) return ret_val; mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; mac->ledctl_mode2 = mac->ledctl_default; for (i = 0; i < 4; i++) { temp = (data >> (i << 2)) & led_mask; switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_on << (i << 3); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_on << (i << 3); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } } return E1000_SUCCESS; } /** * e1000_setup_led_generic - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. **/ s32 e1000_setup_led_generic(struct e1000_hw *hw) { u32 ledctl; DEBUGFUNC("e1000_setup_led_generic"); if (hw->mac.ops.setup_led != e1000_setup_led_generic) return -E1000_ERR_CONFIG; if (hw->phy.media_type == e1000_media_type_fiber) { ledctl = E1000_READ_REG(hw, E1000_LEDCTL); hw->mac.ledctl_default = ledctl; /* Turn off LED0 */ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED0_MODE_MASK); ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); } else if (hw->phy.media_type == e1000_media_type_copper) { E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); } return E1000_SUCCESS; } /** * e1000_cleanup_led_generic - Set LED config to default operation * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration * to the default value, saved from the EEPROM. **/ s32 e1000_cleanup_led_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_cleanup_led_generic"); E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); return E1000_SUCCESS; } /** * e1000_blink_led_generic - Blink LED * @hw: pointer to the HW structure * * Blink the LEDs which are set to be on. **/ s32 e1000_blink_led_generic(struct e1000_hw *hw) { u32 ledctl_blink = 0; u32 i; DEBUGFUNC("e1000_blink_led_generic"); if (hw->phy.media_type == e1000_media_type_fiber) { /* always blink LED0 for PCI-E fiber */ ledctl_blink = E1000_LEDCTL_LED0_BLINK | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { /* Set the blink bit for each LED that's "on" (0x0E) * (or "off" if inverted) in ledctl_mode2. The blink * logic in hardware only works when mode is set to "on" * so it must be changed accordingly when the mode is * "off" and inverted. */ ledctl_blink = hw->mac.ledctl_mode2; for (i = 0; i < 32; i += 8) { u32 mode = (hw->mac.ledctl_mode2 >> i) & E1000_LEDCTL_LED0_MODE_MASK; u32 led_default = hw->mac.ledctl_default >> i; if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && (mode == E1000_LEDCTL_MODE_LED_ON)) || ((led_default & E1000_LEDCTL_LED0_IVRT) && (mode == E1000_LEDCTL_MODE_LED_OFF))) { ledctl_blink &= ~(E1000_LEDCTL_LED0_MODE_MASK << i); ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_MODE_LED_ON) << i; } } } E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); return E1000_SUCCESS; } /** * e1000_led_on_generic - Turn LED on * @hw: pointer to the HW structure * * Turn LED on. **/ s32 e1000_led_on_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_led_on_generic"); switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); break; case e1000_media_type_copper: E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); break; default: break; } return E1000_SUCCESS; } /** * e1000_led_off_generic - Turn LED off * @hw: pointer to the HW structure * * Turn LED off. **/ s32 e1000_led_off_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_led_off_generic"); switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); break; case e1000_media_type_copper: E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); break; default: break; } return E1000_SUCCESS; } /** * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities * @hw: pointer to the HW structure * @no_snoop: bitmap of snoop events * * Set the PCI-express register to snoop for events enabled in 'no_snoop'. **/ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) { u32 gcr; DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); if (hw->bus.type != e1000_bus_type_pci_express) return; if (no_snoop) { gcr = E1000_READ_REG(hw, E1000_GCR); gcr &= ~(PCIE_NO_SNOOP_ALL); gcr |= no_snoop; E1000_WRITE_REG(hw, E1000_GCR, gcr); } } /** * e1000_disable_pcie_master_generic - Disables PCI-express master access * @hw: pointer to the HW structure * * Returns E1000_SUCCESS if successful, else returns -10 * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused * the master requests to be disabled. * * Disables PCI-Express master access and verifies there are no pending * requests. **/ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) { u32 ctrl; s32 timeout = MASTER_DISABLE_TIMEOUT; DEBUGFUNC("e1000_disable_pcie_master_generic"); if (hw->bus.type != e1000_bus_type_pci_express) return E1000_SUCCESS; ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); while (timeout) { if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_GIO_MASTER_ENABLE) || E1000_REMOVED(hw->hw_addr)) break; usec_delay(100); timeout--; } if (!timeout) { DEBUGOUT("Master requests are pending.\n"); return -E1000_ERR_MASTER_REQUESTS_PENDING; } return E1000_SUCCESS; } /** * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Reset the Adaptive Interframe Spacing throttle to default values. **/ void e1000_reset_adaptive_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_reset_adaptive_generic"); if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); return; } mac->current_ifs_val = 0; mac->ifs_min_val = IFS_MIN; mac->ifs_max_val = IFS_MAX; mac->ifs_step_size = IFS_STEP; mac->ifs_ratio = IFS_RATIO; mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } /** * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Update the Adaptive Interframe Spacing Throttle value based on the * time between transmitted packets and time between collisions. **/ void e1000_update_adaptive_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_update_adaptive_generic"); if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); return; } if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { if (mac->tx_packet_delta > MIN_NUM_XMITS) { mac->in_ifs_mode = true; if (mac->current_ifs_val < mac->ifs_max_val) { if (!mac->current_ifs_val) mac->current_ifs_val = mac->ifs_min_val; else mac->current_ifs_val += mac->ifs_step_size; E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); } } } else { if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { mac->current_ifs_val = 0; mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } } } /** * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * * Verify that when not using auto-negotiation that MDI/MDIx is correctly * set, which is forced to MDI mode only. **/ STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_validate_mdi_setting_generic"); if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { DEBUGOUT("Invalid MDI setting detected\n"); hw->phy.mdix = 1; return -E1000_ERR_CONFIG; } return E1000_SUCCESS; } /** * e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * * Validate the MDI/MDIx setting, allowing for auto-crossover during forced * operation. **/ s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic"); UNREFERENCED_1PARAMETER(hw); return E1000_SUCCESS; } /** * e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register * @hw: pointer to the HW structure * @reg: 32bit register offset such as E1000_SCTL * @offset: register offset to write to * @data: data to write at register offset * * Writes an address/data control type register. There are several of these * and they all have the format address << 8 | data and bit 31 is polled for * completion. **/ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data) { u32 i, regvalue = 0; DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic"); /* Set up the address and data */ regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT); E1000_WRITE_REG(hw, reg, regvalue); /* Poll the ready bit to see if the MDI read completed */ for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { usec_delay(5); regvalue = E1000_READ_REG(hw, reg); if (regvalue & E1000_GEN_CTL_READY) break; } if (!(regvalue & E1000_GEN_CTL_READY)) { DEBUGOUT1("Reg %08x did not indicate ready\n", reg); return -E1000_ERR_PHY; } return E1000_SUCCESS; } ================================================ FILE: drivers/net/e1000/base/e1000_mac.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_MAC_H_ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); #ifndef E1000_REMOVED #define E1000_REMOVED(a) (0) #endif /* E1000_REMOVED */ void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); bool e1000_null_mng_mode(struct e1000_hw *hw); void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a); void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b); void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a); s32 e1000_blink_led_generic(struct e1000_hw *hw); s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); s32 e1000_cleanup_led_generic(struct e1000_hw *hw); s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw); s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw); s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); void e1000_set_lan_id_single_port(struct e1000_hw *hw); void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw); s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_id_led_init_generic(struct e1000_hw *hw); s32 e1000_led_on_generic(struct e1000_hw *hw); s32 e1000_led_off_generic(struct e1000_hw *hw); void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); s32 e1000_set_default_fc_generic(struct e1000_hw *hw); s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_setup_led_generic(struct e1000_hw *hw); s32 e1000_setup_link_generic(struct e1000_hw *hw); s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw); void e1000_clear_vfta_generic(struct e1000_hw *hw); void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw); void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); void e1000_reset_adaptive_generic(struct e1000_hw *hw); void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); void e1000_update_adaptive_generic(struct e1000_hw *hw); void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); #endif ================================================ FILE: drivers/net/e1000/base/e1000_manage.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" /** * e1000_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM * @length: size of EEPROM to calculate a checksum for * * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ u8 e1000_calculate_checksum(u8 *buffer, u32 length) { u32 i; u8 sum = 0; DEBUGFUNC("e1000_calculate_checksum"); if (!buffer) return 0; for (i = 0; i < length; i++) sum += buffer[i]; return (u8) (0 - sum); } /** * e1000_mng_enable_host_if_generic - Checks host interface is enabled * @hw: pointer to the HW structure * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) { u32 hicr; u8 i; DEBUGFUNC("e1000_mng_enable_host_if_generic"); if (!hw->mac.arc_subsystem_valid) { DEBUGOUT("ARC subsystem not valid.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* check the previous command is completed */ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay_irq(1); } if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { DEBUGOUT("Previous command timeout failed .\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } return E1000_SUCCESS; } /** * e1000_check_mng_mode_generic - Generic check management mode * @hw: pointer to the HW structure * * Reads the firmware semaphore register and returns true (>0) if * manageability is enabled, else false (0). **/ bool e1000_check_mng_mode_generic(struct e1000_hw *hw) { u32 fwsm = E1000_READ_REG(hw, E1000_FWSM); DEBUGFUNC("e1000_check_mng_mode_generic"); return (fwsm & E1000_FWSM_MODE_MASK) == (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); } /** * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx * @hw: pointer to the HW structure * * Enables packet filtering on transmit packets if manageability is enabled * and host interface is enabled. **/ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) { struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; u32 *buffer = (u32 *)&hw->mng_cookie; u32 offset; s32 ret_val, hdr_csum, csum; u8 i, len; DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); hw->mac.tx_pkt_filtering = true; /* No manageability, no filtering */ if (!hw->mac.ops.check_mng_mode(hw)) { hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /* If we can't read from the host interface for whatever * reason, disable filtering. */ ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val != E1000_SUCCESS) { hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /* Read in the header. Length and offset are in dwords. */ len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; for (i = 0; i < len; i++) *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i); hdr_csum = hdr->checksum; hdr->checksum = 0; csum = e1000_calculate_checksum((u8 *)hdr, E1000_MNG_DHCP_COOKIE_LENGTH); /* If either the checksums or signature don't match, then * the cookie area isn't considered valid, in which case we * take the safe route of assuming Tx filtering is enabled. */ if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { hw->mac.tx_pkt_filtering = true; return hw->mac.tx_pkt_filtering; } /* Cookie area is valid, make the final check for filtering. */ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /** * e1000_mng_write_cmd_header_generic - Writes manageability command header * @hw: pointer to the HW structure * @hdr: pointer to the host interface command header * * Writes the command header after does the checksum calculation. **/ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { u16 i, length = sizeof(struct e1000_host_mng_command_header); DEBUGFUNC("e1000_mng_write_cmd_header_generic"); /* Write the whole command header structure with new checksum. */ hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); length >>= 2; /* Write the relevant command block into the ram area. */ for (i = 0; i < length; i++) { E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *) hdr + i)); E1000_WRITE_FLUSH(hw); } return E1000_SUCCESS; } /** * e1000_mng_host_if_write_generic - Write to the manageability host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface buffer * @length: size of the buffer * @offset: location in the buffer to write to * @sum: sum of the data (not checksum) * * This function writes the buffer content at the offset given on the host if. * It also does alignment considerations to do the writes in most efficient * way. Also fills up the sum of the buffer in *buffer parameter. **/ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { u8 *tmp; u8 *bufptr = buffer; u32 data = 0; u16 remaining, i, j, prev_bytes; DEBUGFUNC("e1000_mng_host_if_write_generic"); /* sum = only sum of the data and it is not checksum */ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) return -E1000_ERR_PARAM; tmp = (u8 *)&data; prev_bytes = offset & 0x3; offset >>= 2; if (prev_bytes) { data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); for (j = prev_bytes; j < sizeof(u32); j++) { *(tmp + j) = *bufptr++; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); length -= j - prev_bytes; offset++; } remaining = length & 0x3; length -= remaining; /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant command block into the * ram area. */ for (i = 0; i < length; i++) { for (j = 0; j < sizeof(u32); j++) { *(tmp + j) = *bufptr++; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); } if (remaining) { for (j = 0; j < sizeof(u32); j++) { if (j < remaining) *(tmp + j) = *bufptr++; else *(tmp + j) = 0; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); } return E1000_SUCCESS; } /** * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface * @length: size of the buffer * * Writes the DHCP information to the host interface. **/ s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length) { struct e1000_host_mng_command_header hdr; s32 ret_val; u32 hicr; DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; hdr.command_length = length; hdr.reserved1 = 0; hdr.reserved2 = 0; hdr.checksum = 0; /* Enable the host interface */ ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val) return ret_val; /* Populate the host interface with the contents of "buffer". */ ret_val = e1000_mng_host_if_write_generic(hw, buffer, length, sizeof(hdr), &(hdr.checksum)); if (ret_val) return ret_val; /* Write the manageability command header */ ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr); if (ret_val) return ret_val; /* Tell the ARC a new command is pending. */ hicr = E1000_READ_REG(hw, E1000_HICR); E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); return E1000_SUCCESS; } /** * e1000_enable_mng_pass_thru - Check if management passthrough is needed * @hw: pointer to the HW structure * * Verifies the hardware needs to leave interface enabled so that frames can * be directed to and from the management interface. **/ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) { u32 manc; u32 fwsm, factps; DEBUGFUNC("e1000_enable_mng_pass_thru"); if (!hw->mac.asf_firmware_present) return false; manc = E1000_READ_REG(hw, E1000_MANC); if (!(manc & E1000_MANC_RCV_TCO_EN)) return false; if (hw->mac.has_fwsm) { fwsm = E1000_READ_REG(hw, E1000_FWSM); factps = E1000_READ_REG(hw, E1000_FACTPS); if (!(factps & E1000_FACTPS_MNGCG) && ((fwsm & E1000_FWSM_MODE_MASK) == (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) return true; } else if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) { u16 data; factps = E1000_READ_REG(hw, E1000_FACTPS); e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); if (!(factps & E1000_FACTPS_MNGCG) && ((data & E1000_NVM_INIT_CTRL2_MNGM) == (e1000_mng_mode_pt << 13))) return true; } else if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) { return true; } return false; } /** * e1000_host_interface_command - Writes buffer to host interface * @hw: pointer to the HW structure * @buffer: contains a command to write * @length: the byte length of the buffer, must be multiple of 4 bytes * * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS * else returns E1000_ERR_HOST_INTERFACE_COMMAND. **/ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) { u32 hicr, i; DEBUGFUNC("e1000_host_interface_command"); if (!(hw->mac.arc_subsystem_valid)) { DEBUGOUT("Hardware doesn't support host interface command.\n"); return E1000_SUCCESS; } if (!hw->mac.asf_firmware_present) { DEBUGOUT("Firmware is not present.\n"); return E1000_SUCCESS; } if (length == 0 || length & 0x3 || length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) { DEBUGOUT("Buffer length failure.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < length; i++) E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *)buffer + i)); /* Setting this bit tells the ARC that a new command is pending. */ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay(1); } /* Check command successful completion. */ if (i == E1000_HI_COMMAND_TIMEOUT || (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) { DEBUGOUT("Command has failed with no status valid.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } for (i = 0; i < length; i++) *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i); return E1000_SUCCESS; } /** * e1000_load_firmware - Writes proxy FW code buffer to host interface * and execute. * @hw: pointer to the HW structure * @buffer: contains a firmware to write * @length: the byte length of the buffer, must be multiple of 4 bytes * * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND. **/ s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length) { u32 hicr, hibba, fwsm, icr, i; DEBUGFUNC("e1000_load_firmware"); if (hw->mac.type < e1000_i210) { DEBUGOUT("Hardware doesn't support loading FW by the driver\n"); return -E1000_ERR_CONFIG; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) { DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) { DEBUGOUT("Buffer length failure.\n"); return -E1000_ERR_INVALID_ARGUMENT; } /* Clear notification from ROM-FW by reading ICR register */ icr = E1000_READ_REG(hw, E1000_ICR_V2); /* Reset ROM-FW */ hicr = E1000_READ_REG(hw, E1000_HICR); hicr |= E1000_HICR_FW_RESET_ENABLE; E1000_WRITE_REG(hw, E1000_HICR, hicr); hicr |= E1000_HICR_FW_RESET; E1000_WRITE_REG(hw, E1000_HICR, hicr); E1000_WRITE_FLUSH(hw); /* Wait till MAC notifies about its readiness after ROM-FW reset */ for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) { icr = E1000_READ_REG(hw, E1000_ICR_V2); if (icr & E1000_ICR_MNG) break; msec_delay(1); } /* Check for timeout */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("FW reset failed.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Wait till MAC is ready to accept new FW code */ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { fwsm = E1000_READ_REG(hw, E1000_FWSM); if ((fwsm & E1000_FWSM_FW_VALID) && ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT == E1000_FWSM_HI_EN_ONLY_MODE)) break; msec_delay(1); } /* Check for timeout */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("FW reset failed.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant FW code block * into the ram area in DWORDs via 1kB ram addressing window. */ for (i = 0; i < length; i++) { if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) { /* Point to correct 1kB ram window */ hibba = E1000_HI_FW_BASE_ADDRESS + ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) * (i / E1000_HI_FW_BLOCK_DWORD_LENGTH)); E1000_WRITE_REG(hw, E1000_HIBBA, hibba); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i % E1000_HI_FW_BLOCK_DWORD_LENGTH, *((u32 *)buffer + i)); } /* Setting this bit tells the ARC that a new FW is ready to execute. */ hicr = E1000_READ_REG(hw, E1000_HICR); E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay(1); } /* Check for successful FW start. */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("New FW did not start within timeout period.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } return E1000_SUCCESS; } ================================================ FILE: drivers/net/e1000/base/e1000_manage.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_MANAGE_H_ #define _E1000_MANAGE_H_ bool e1000_check_mng_mode_generic(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum); s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length); bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); u8 e1000_calculate_checksum(u8 *buffer, u32 length); s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length); s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length); enum e1000_mng_mode { e1000_mng_mode_none = 0, e1000_mng_mode_asf, e1000_mng_mode_pt, e1000_mng_mode_ipmi, e1000_mng_mode_host_if_only }; #define E1000_FACTPS_MNGCG 0x20000000 #define E1000_FWSM_MODE_MASK 0xE #define E1000_FWSM_MODE_SHIFT 1 #define E1000_FWSM_FW_VALID 0x00008000 #define E1000_FWSM_HI_EN_ONLY_MODE 0x4 #define E1000_MNG_IAMT_MODE 0x3 #define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 #define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 #define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 #define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 #define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 #define E1000_VFTA_ENTRY_SHIFT 5 #define E1000_VFTA_ENTRY_MASK 0x7F #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F #define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ #define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ #define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI cmd limit */ #define E1000_HI_FW_BASE_ADDRESS 0x10000 #define E1000_HI_FW_MAX_LENGTH (64 * 1024) /* Num of bytes */ #define E1000_HI_FW_BLOCK_DWORD_LENGTH 256 /* Num of DWORDs per page */ #define E1000_HICR_MEMORY_BASE_EN 0x200 /* MB Enable bit - RO */ #define E1000_HICR_EN 0x01 /* Enable bit - RO */ /* Driver sets this bit when done to put command in RAM */ #define E1000_HICR_C 0x02 #define E1000_HICR_SV 0x04 /* Status Validity */ #define E1000_HICR_FW_RESET_ENABLE 0x40 #define E1000_HICR_FW_RESET 0x80 /* Intel(R) Active Management Technology signature */ #define E1000_IAMT_SIGNATURE 0x544D4149 #endif ================================================ FILE: drivers/net/e1000/base/e1000_mbx.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_mbx.h" /** * e1000_null_mbx_check_for_flag - No-op function, return 0 * @hw: pointer to the HW structure **/ STATIC s32 e1000_null_mbx_check_for_flag(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG mbx_id) { DEBUGFUNC("e1000_null_mbx_check_flag"); UNREFERENCED_2PARAMETER(hw, mbx_id); return E1000_SUCCESS; } /** * e1000_null_mbx_transact - No-op function, return 0 * @hw: pointer to the HW structure **/ STATIC s32 e1000_null_mbx_transact(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG *msg, u16 E1000_UNUSEDARG size, u16 E1000_UNUSEDARG mbx_id) { DEBUGFUNC("e1000_null_mbx_rw_msg"); UNREFERENCED_4PARAMETER(hw, msg, size, mbx_id); return E1000_SUCCESS; } /** * e1000_read_mbx - Reads a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to read * * returns SUCCESS if it successfully read message from buffer **/ s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_read_mbx"); /* limit read to size of mailbox */ if (size > mbx->size) size = mbx->size; if (mbx->ops.read) ret_val = mbx->ops.read(hw, msg, size, mbx_id); return ret_val; } /** * e1000_write_mbx - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer **/ s32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_mbx"); if (size > mbx->size) ret_val = -E1000_ERR_MBX; else if (mbx->ops.write) ret_val = mbx->ops.write(hw, msg, size, mbx_id); return ret_val; } /** * e1000_check_for_msg - checks to see if someone sent us mail * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_msg"); if (mbx->ops.check_for_msg) ret_val = mbx->ops.check_for_msg(hw, mbx_id); return ret_val; } /** * e1000_check_for_ack - checks to see if someone sent us ACK * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_ack"); if (mbx->ops.check_for_ack) ret_val = mbx->ops.check_for_ack(hw, mbx_id); return ret_val; } /** * e1000_check_for_rst - checks to see if other side has reset * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_rst"); if (mbx->ops.check_for_rst) ret_val = mbx->ops.check_for_rst(hw, mbx_id); return ret_val; } /** * e1000_poll_for_msg - Wait for message notification * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification **/ STATIC s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("e1000_poll_for_msg"); if (!countdown || !mbx->ops.check_for_msg) goto out; while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } /* if we failed, all future posted messages fail until reset */ if (!countdown) mbx->timeout = 0; out: return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; } /** * e1000_poll_for_ack - Wait for message acknowledgement * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message acknowledgement **/ STATIC s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("e1000_poll_for_ack"); if (!countdown || !mbx->ops.check_for_ack) goto out; while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } /* if we failed, all future posted messages fail until reset */ if (!countdown) mbx->timeout = 0; out: return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; } /** * e1000_read_posted_mbx - Wait for message notification and receive message * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification and * copied it into the receive buffer. **/ s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_read_posted_mbx"); if (!mbx->ops.read) goto out; ret_val = e1000_poll_for_msg(hw, mbx_id); /* if ack received read message, otherwise we timed out */ if (!ret_val) ret_val = mbx->ops.read(hw, msg, size, mbx_id); out: return ret_val; } /** * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer and * received an ack to that message within delay * timeout period **/ s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_write_posted_mbx"); /* exit if either we can't write or there isn't a defined timeout */ if (!mbx->ops.write || !mbx->timeout) goto out; /* send msg */ ret_val = mbx->ops.write(hw, msg, size, mbx_id); /* if msg sent wait until we receive an ack */ if (!ret_val) ret_val = e1000_poll_for_ack(hw, mbx_id); out: return ret_val; } /** * e1000_init_mbx_ops_generic - Initialize mbx function pointers * @hw: pointer to the HW structure * * Sets the function pointers to no-op functions **/ void e1000_init_mbx_ops_generic(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; mbx->ops.init_params = e1000_null_ops_generic; mbx->ops.read = e1000_null_mbx_transact; mbx->ops.write = e1000_null_mbx_transact; mbx->ops.check_for_msg = e1000_null_mbx_check_for_flag; mbx->ops.check_for_ack = e1000_null_mbx_check_for_flag; mbx->ops.check_for_rst = e1000_null_mbx_check_for_flag; mbx->ops.read_posted = e1000_read_posted_mbx; mbx->ops.write_posted = e1000_write_posted_mbx; } /** * e1000_read_v2p_mailbox - read v2p mailbox * @hw: pointer to the HW structure * * This function is used to read the v2p mailbox without losing the read to * clear status bits. **/ STATIC u32 e1000_read_v2p_mailbox(struct e1000_hw *hw) { u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0)); v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox; hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS; return v2p_mailbox; } /** * e1000_check_for_bit_vf - Determine if a status bit was set * @hw: pointer to the HW structure * @mask: bitmask for bits to be tested and cleared * * This function is used to check for the read to clear bits within * the V2P mailbox. **/ STATIC s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask) { u32 v2p_mailbox = e1000_read_v2p_mailbox(hw); s32 ret_val = -E1000_ERR_MBX; if (v2p_mailbox & mask) ret_val = E1000_SUCCESS; hw->dev_spec.vf.v2p_mailbox &= ~mask; return ret_val; } /** * e1000_check_for_msg_vf - checks to see if the PF has sent mail * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the PF has set the Status bit or else ERR_MBX **/ STATIC s32 e1000_check_for_msg_vf(struct e1000_hw *hw, u16 E1000_UNUSEDARG mbx_id) { s32 ret_val = -E1000_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("e1000_check_for_msg_vf"); if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) { ret_val = E1000_SUCCESS; hw->mbx.stats.reqs++; } return ret_val; } /** * e1000_check_for_ack_vf - checks to see if the PF has ACK'd * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX **/ STATIC s32 e1000_check_for_ack_vf(struct e1000_hw *hw, u16 E1000_UNUSEDARG mbx_id) { s32 ret_val = -E1000_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("e1000_check_for_ack_vf"); if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) { ret_val = E1000_SUCCESS; hw->mbx.stats.acks++; } return ret_val; } /** * e1000_check_for_rst_vf - checks to see if the PF has reset * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns true if the PF has set the reset done bit or else false **/ STATIC s32 e1000_check_for_rst_vf(struct e1000_hw *hw, u16 E1000_UNUSEDARG mbx_id) { s32 ret_val = -E1000_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("e1000_check_for_rst_vf"); if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD | E1000_V2PMAILBOX_RSTI))) { ret_val = E1000_SUCCESS; hw->mbx.stats.rsts++; } return ret_val; } /** * e1000_obtain_mbx_lock_vf - obtain mailbox lock * @hw: pointer to the HW structure * * return SUCCESS if we obtained the mailbox lock **/ STATIC s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_obtain_mbx_lock_vf"); /* Take ownership of the buffer */ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); /* reserve mailbox for vf use */ if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) ret_val = E1000_SUCCESS; return ret_val; } /** * e1000_write_mbx_vf - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer **/ STATIC s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size, u16 E1000_UNUSEDARG mbx_id) { s32 ret_val; u16 i; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("e1000_write_mbx_vf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_vf(hw); if (ret_val) goto out_no_write; /* flush msg and acks as we are overwriting the message buffer */ e1000_check_for_msg_vf(hw, 0); e1000_check_for_ack_vf(hw, 0); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]); /* update stats */ hw->mbx.stats.msgs_tx++; /* Drop VFU and interrupt the PF to tell it a message has been sent */ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ); out_no_write: return ret_val; } /** * e1000_read_mbx_vf - Reads a message from the inbox intended for vf * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to read * * returns SUCCESS if it successfully read message from buffer **/ STATIC s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size, u16 E1000_UNUSEDARG mbx_id) { s32 ret_val = E1000_SUCCESS; u16 i; DEBUGFUNC("e1000_read_mbx_vf"); UNREFERENCED_1PARAMETER(mbx_id); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_vf(hw); if (ret_val) goto out_no_read; /* copy the message from the mailbox memory buffer */ for (i = 0; i < size; i++) msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i); /* Acknowledge receipt and release mailbox, then we're done */ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK); /* update stats */ hw->mbx.stats.msgs_rx++; out_no_read: return ret_val; } /** * e1000_init_mbx_params_vf - set initial values for vf mailbox * @hw: pointer to the HW structure * * Initializes the hw->mbx struct to correct values for vf mailbox */ s32 e1000_init_mbx_params_vf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; /* start mailbox as timed out and let the reset_hw call set the timeout * value to begin communications */ mbx->timeout = 0; mbx->usec_delay = E1000_VF_MBX_INIT_DELAY; mbx->size = E1000_VFMAILBOX_SIZE; mbx->ops.read = e1000_read_mbx_vf; mbx->ops.write = e1000_write_mbx_vf; mbx->ops.read_posted = e1000_read_posted_mbx; mbx->ops.write_posted = e1000_write_posted_mbx; mbx->ops.check_for_msg = e1000_check_for_msg_vf; mbx->ops.check_for_ack = e1000_check_for_ack_vf; mbx->ops.check_for_rst = e1000_check_for_rst_vf; mbx->stats.msgs_tx = 0; mbx->stats.msgs_rx = 0; mbx->stats.reqs = 0; mbx->stats.acks = 0; mbx->stats.rsts = 0; return E1000_SUCCESS; } STATIC s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask) { u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR); s32 ret_val = -E1000_ERR_MBX; if (mbvficr & mask) { ret_val = E1000_SUCCESS; E1000_WRITE_REG(hw, E1000_MBVFICR, mask); } return ret_val; } /** * e1000_check_for_msg_pf - checks to see if the VF has sent mail * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_msg_pf"); if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { ret_val = E1000_SUCCESS; hw->mbx.stats.reqs++; } return ret_val; } /** * e1000_check_for_ack_pf - checks to see if the VF has ACKed * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_ack_pf"); if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { ret_val = E1000_SUCCESS; hw->mbx.stats.acks++; } return ret_val; } /** * e1000_check_for_rst_pf - checks to see if the VF has reset * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) { u32 vflre = E1000_READ_REG(hw, E1000_VFLRE); s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_rst_pf"); if (vflre & (1 << vf_number)) { ret_val = E1000_SUCCESS; E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number)); hw->mbx.stats.rsts++; } return ret_val; } /** * e1000_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ STATIC s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; u32 p2v_mailbox; DEBUGFUNC("e1000_obtain_mbx_lock_pf"); /* Take ownership of the buffer */ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); if (p2v_mailbox & E1000_P2VMAILBOX_PFU) ret_val = E1000_SUCCESS; return ret_val; } /** * e1000_write_mbx_pf - Places a message in the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * returns SUCCESS if it successfully copied message into the buffer **/ STATIC s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("e1000_write_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_write; /* flush msg and acks as we are overwriting the message buffer */ e1000_check_for_msg_pf(hw, vf_number); e1000_check_for_ack_pf(hw, vf_number); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]); /* Interrupt VF to tell it a message has been sent and release buffer*/ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); /* update stats */ hw->mbx.stats.msgs_tx++; out_no_write: return ret_val; } /** * e1000_read_mbx_pf - Read a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * This function copies a message from the mailbox buffer to the caller's * memory buffer. The presumption is that the caller knows that there was * a message due to a VF request so no polling for message is needed. **/ STATIC s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("e1000_read_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_read; /* copy the message to the mailbox memory buffer */ for (i = 0; i < size; i++) msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i); /* Acknowledge the message and release buffer */ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); /* update stats */ hw->mbx.stats.msgs_rx++; out_no_read: return ret_val; } /** * e1000_init_mbx_params_pf - set initial values for pf mailbox * @hw: pointer to the HW structure * * Initializes the hw->mbx struct to correct values for pf mailbox */ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; switch (hw->mac.type) { case e1000_82576: case e1000_i350: case e1000_i354: mbx->timeout = 0; mbx->usec_delay = 0; mbx->size = E1000_VFMAILBOX_SIZE; mbx->ops.read = e1000_read_mbx_pf; mbx->ops.write = e1000_write_mbx_pf; mbx->ops.read_posted = e1000_read_posted_mbx; mbx->ops.write_posted = e1000_write_posted_mbx; mbx->ops.check_for_msg = e1000_check_for_msg_pf; mbx->ops.check_for_ack = e1000_check_for_ack_pf; mbx->ops.check_for_rst = e1000_check_for_rst_pf; mbx->stats.msgs_tx = 0; mbx->stats.msgs_rx = 0; mbx->stats.reqs = 0; mbx->stats.acks = 0; mbx->stats.rsts = 0; default: return E1000_SUCCESS; } } ================================================ FILE: drivers/net/e1000/base/e1000_mbx.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_MBX_H_ #define _E1000_MBX_H_ #include "e1000_api.h" /* Define mailbox register bits */ #define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ #define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */ #define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ #define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ #define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */ #define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */ #define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */ #define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ #define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ #define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ #define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ #define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ #define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ #define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ #define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ /* If it's a E1000_VF_* msg then it originates in the VF and is sent to the * PF. The reverse is true if it is E1000_PF_*. * Message ACK's are the value or'd with 0xF0000000 */ /* Msgs below or'd with this are the ACK */ #define E1000_VT_MSGTYPE_ACK 0x80000000 /* Msgs below or'd with this are the NACK */ #define E1000_VT_MSGTYPE_NACK 0x40000000 /* Indicates that VF is still clear to send requests */ #define E1000_VT_MSGTYPE_CTS 0x20000000 #define E1000_VT_MSGINFO_SHIFT 16 /* bits 23:16 are used for extra info for certain messages */ #define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_RESET 0x01 /* VF requests reset */ #define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */ #define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */ #define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */ #define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_LPE 0x05 /* reqs to set VMOLR.LPE */ #define E1000_VF_SET_PROMISC 0x06 /* reqs to clear VMOLR.ROPE/MPME*/ #define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT) #define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ #define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ s32 e1000_read_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_write_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_check_for_msg(struct e1000_hw *, u16); s32 e1000_check_for_ack(struct e1000_hw *, u16); s32 e1000_check_for_rst(struct e1000_hw *, u16); void e1000_init_mbx_ops_generic(struct e1000_hw *hw); s32 e1000_init_mbx_params_vf(struct e1000_hw *); s32 e1000_init_mbx_params_pf(struct e1000_hw *); #endif /* _E1000_MBX_H_ */ ================================================ FILE: drivers/net/e1000/base/e1000_nvm.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" STATIC void e1000_reload_nvm_generic(struct e1000_hw *hw); /** * e1000_init_nvm_ops_generic - Initialize NVM function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_nvm_ops_generic(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_ops_generic"); /* Initialize function pointers */ nvm->ops.init_params = e1000_null_ops_generic; nvm->ops.acquire = e1000_null_ops_generic; nvm->ops.read = e1000_null_read_nvm; nvm->ops.release = e1000_null_nvm_generic; nvm->ops.reload = e1000_reload_nvm_generic; nvm->ops.update = e1000_null_ops_generic; nvm->ops.valid_led_default = e1000_null_led_default; nvm->ops.validate = e1000_null_ops_generic; nvm->ops.write = e1000_null_write_nvm; } /** * e1000_null_nvm_read - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b, u16 E1000_UNUSEDARG *c) { DEBUGFUNC("e1000_null_read_nvm"); UNREFERENCED_4PARAMETER(hw, a, b, c); return E1000_SUCCESS; } /** * e1000_null_nvm_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_nvm_generic"); UNREFERENCED_1PARAMETER(hw); return; } /** * e1000_null_led_default - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_null_led_default"); UNREFERENCED_2PARAMETER(hw, data); return E1000_SUCCESS; } /** * e1000_null_write_nvm - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b, u16 E1000_UNUSEDARG *c) { DEBUGFUNC("e1000_null_write_nvm"); UNREFERENCED_4PARAMETER(hw, a, b, c); return E1000_SUCCESS; } /** * e1000_raise_eec_clk - Raise EEPROM clock * @hw: pointer to the HW structure * @eecd: pointer to the EEPROM * * Enable/Raise the EEPROM clock bit. **/ STATIC void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) { *eecd = *eecd | E1000_EECD_SK; E1000_WRITE_REG(hw, E1000_EECD, *eecd); E1000_WRITE_FLUSH(hw); usec_delay(hw->nvm.delay_usec); } /** * e1000_lower_eec_clk - Lower EEPROM clock * @hw: pointer to the HW structure * @eecd: pointer to the EEPROM * * Clear/Lower the EEPROM clock bit. **/ STATIC void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) { *eecd = *eecd & ~E1000_EECD_SK; E1000_WRITE_REG(hw, E1000_EECD, *eecd); E1000_WRITE_FLUSH(hw); usec_delay(hw->nvm.delay_usec); } /** * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM * @hw: pointer to the HW structure * @data: data to send to the EEPROM * @count: number of bits to shift out * * We need to shift 'count' bits out to the EEPROM. So, the value in the * "data" parameter will be shifted out to the EEPROM one bit at a time. * In order to do this, "data" must be broken down into bits. **/ STATIC void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u32 mask; DEBUGFUNC("e1000_shift_out_eec_bits"); mask = 0x01 << (count - 1); if (nvm->type == e1000_nvm_eeprom_microwire) eecd &= ~E1000_EECD_DO; else if (nvm->type == e1000_nvm_eeprom_spi) eecd |= E1000_EECD_DO; do { eecd &= ~E1000_EECD_DI; if (data & mask) eecd |= E1000_EECD_DI; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); e1000_raise_eec_clk(hw, &eecd); e1000_lower_eec_clk(hw, &eecd); mask >>= 1; } while (mask); eecd &= ~E1000_EECD_DI; E1000_WRITE_REG(hw, E1000_EECD, eecd); } /** * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM * @hw: pointer to the HW structure * @count: number of bits to shift in * * In order to read a register from the EEPROM, we need to shift 'count' bits * in from the EEPROM. Bits are "shifted in" by raising the clock input to * the EEPROM (setting the SK bit), and then reading the value of the data out * "DO" bit. During this "shifting in" process the data in "DI" bit should * always be clear. **/ STATIC u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) { u32 eecd; u32 i; u16 data; DEBUGFUNC("e1000_shift_in_eec_bits"); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); data = 0; for (i = 0; i < count; i++) { data <<= 1; e1000_raise_eec_clk(hw, &eecd); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~E1000_EECD_DI; if (eecd & E1000_EECD_DO) data |= 1; e1000_lower_eec_clk(hw, &eecd); } return data; } /** * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion * @hw: pointer to the HW structure * @ee_reg: EEPROM flag for polling * * Polls the EEPROM status bit for either read or write completion based * upon the value of 'ee_reg'. **/ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) { u32 attempts = 100000; u32 i, reg = 0; DEBUGFUNC("e1000_poll_eerd_eewr_done"); for (i = 0; i < attempts; i++) { if (ee_reg == E1000_NVM_POLL_READ) reg = E1000_READ_REG(hw, E1000_EERD); else reg = E1000_READ_REG(hw, E1000_EEWR); if (reg & E1000_NVM_RW_REG_DONE) return E1000_SUCCESS; usec_delay(5); } return -E1000_ERR_NVM; } /** * e1000_acquire_nvm_generic - Generic request for access to EEPROM * @hw: pointer to the HW structure * * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); s32 timeout = E1000_NVM_GRANT_ATTEMPTS; DEBUGFUNC("e1000_acquire_nvm_generic"); E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); eecd = E1000_READ_REG(hw, E1000_EECD); while (timeout) { if (eecd & E1000_EECD_GNT) break; usec_delay(5); eecd = E1000_READ_REG(hw, E1000_EECD); timeout--; } if (!timeout) { eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, E1000_EECD, eecd); DEBUGOUT("Could not acquire NVM grant\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_standby_nvm - Return EEPROM to standby state * @hw: pointer to the HW structure * * Return the EEPROM to a standby state. **/ STATIC void e1000_standby_nvm(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); DEBUGFUNC("e1000_standby_nvm"); if (nvm->type == e1000_nvm_eeprom_microwire) { eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); e1000_raise_eec_clk(hw, &eecd); /* Select EEPROM */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); e1000_lower_eec_clk(hw, &eecd); } else if (nvm->type == e1000_nvm_eeprom_spi) { /* Toggle CS to flush commands */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); eecd &= ~E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); } } /** * e1000_stop_nvm - Terminate EEPROM command * @hw: pointer to the HW structure * * Terminates the current command by inverting the EEPROM's chip select pin. **/ void e1000_stop_nvm(struct e1000_hw *hw) { u32 eecd; DEBUGFUNC("e1000_stop_nvm"); eecd = E1000_READ_REG(hw, E1000_EECD); if (hw->nvm.type == e1000_nvm_eeprom_spi) { /* Pull CS high */ eecd |= E1000_EECD_CS; e1000_lower_eec_clk(hw, &eecd); } else if (hw->nvm.type == e1000_nvm_eeprom_microwire) { /* CS on Microwire is active-high */ eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); E1000_WRITE_REG(hw, E1000_EECD, eecd); e1000_raise_eec_clk(hw, &eecd); e1000_lower_eec_clk(hw, &eecd); } } /** * e1000_release_nvm_generic - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit. **/ void e1000_release_nvm_generic(struct e1000_hw *hw) { u32 eecd; DEBUGFUNC("e1000_release_nvm_generic"); e1000_stop_nvm(hw); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, E1000_EECD, eecd); } /** * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write * @hw: pointer to the HW structure * * Setups the EEPROM for reading and writing. **/ STATIC s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u8 spi_stat_reg; DEBUGFUNC("e1000_ready_nvm_eeprom"); if (nvm->type == e1000_nvm_eeprom_microwire) { /* Clear SK and DI */ eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); E1000_WRITE_REG(hw, E1000_EECD, eecd); /* Set CS */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); } else if (nvm->type == e1000_nvm_eeprom_spi) { u16 timeout = NVM_MAX_RETRY_SPI; /* Clear SK and CS */ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(1); /* Read "Status Register" repeatedly until the LSB is cleared. * The EEPROM will signal that the command has been completed * by clearing bit 0 of the internal status register. If it's * not cleared within 'timeout', then error out. */ while (timeout) { e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, hw->nvm.opcode_bits); spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) break; usec_delay(5); e1000_standby_nvm(hw); timeout--; } if (!timeout) { DEBUGOUT("SPI NVM Status error\n"); return -E1000_ERR_NVM; } } return E1000_SUCCESS; } /** * e1000_read_nvm_spi - Read EEPROM's using SPI * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM. **/ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i = 0; s32 ret_val; u16 word_in; u8 read_opcode = NVM_READ_OPCODE_SPI; DEBUGFUNC("e1000_read_nvm_spi"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; e1000_standby_nvm(hw); if ((nvm->address_bits == 8) && (offset >= 128)) read_opcode |= NVM_A8_OPCODE_SPI; /* Send the READ command (opcode + addr) */ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); /* Read the data. SPI NVMs increment the address with each byte * read and will roll over if reading beyond the end. This allows * us to read the whole NVM from any offset */ for (i = 0; i < words; i++) { word_in = e1000_shift_in_eec_bits(hw, 16); data[i] = (word_in >> 8) | (word_in << 8); } release: nvm->ops.release(hw); return ret_val; } /** * e1000_read_nvm_microwire - Reads EEPROM's using microwire * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM. **/ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i = 0; s32 ret_val; u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; DEBUGFUNC("e1000_read_nvm_microwire"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; for (i = 0; i < words; i++) { /* Send the READ command (opcode + addr) */ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset + i), nvm->address_bits); /* Read the data. For microwire, each word requires the * overhead of setup and tear-down. */ data[i] = e1000_shift_in_eec_bits(hw, 16); e1000_standby_nvm(hw); } release: nvm->ops.release(hw); return ret_val; } /** * e1000_read_nvm_eerd - Reads EEPROM using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, eerd = 0; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_nvm_eerd"); /* A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } for (i = 0; i < words; i++) { eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + E1000_NVM_RW_REG_START; E1000_WRITE_REG(hw, E1000_EERD, eerd); ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); if (ret_val) break; data[i] = (E1000_READ_REG(hw, E1000_EERD) >> E1000_NVM_RW_REG_DATA); } return ret_val; } /** * e1000_write_nvm_spi - Write to EEPROM using SPI * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * Writes data to EEPROM at offset using SPI interface. * * If e1000_update_nvm_checksum is not called after this function , the * EEPROM will most likely contain an invalid checksum. **/ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val = -E1000_ERR_NVM; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_spi"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) { nvm->ops.release(hw); return ret_val; } e1000_standby_nvm(hw); /* Send the WRITE ENABLE command (8 bit opcode) */ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, nvm->opcode_bits); e1000_standby_nvm(hw); /* Some SPI eeproms use the 8th address bit embedded in the * opcode */ if ((nvm->address_bits == 8) && (offset >= 128)) write_opcode |= NVM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), nvm->address_bits); /* Loop to allow for up to whole page write of eeprom */ while (widx < words) { u16 word_out = data[widx]; word_out = (word_out >> 8) | (word_out << 8); e1000_shift_out_eec_bits(hw, word_out, 16); widx++; if ((((offset + widx) * 2) % nvm->page_size) == 0) { e1000_standby_nvm(hw); break; } } msec_delay(10); nvm->ops.release(hw); } return ret_val; } /** * e1000_write_nvm_microwire - Writes EEPROM using microwire * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * Writes data to EEPROM at offset using microwire interface. * * If e1000_update_nvm_checksum is not called after this function , the * EEPROM will most likely contain an invalid checksum. **/ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val; u32 eecd; u16 words_written = 0; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_microwire"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, (u16)(nvm->opcode_bits + 2)); e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); e1000_standby_nvm(hw); while (words_written < words) { e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), nvm->address_bits); e1000_shift_out_eec_bits(hw, data[words_written], 16); e1000_standby_nvm(hw); for (widx = 0; widx < 200; widx++) { eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & E1000_EECD_DO) break; usec_delay(50); } if (widx == 200) { DEBUGOUT("NVM Write did not complete\n"); ret_val = -E1000_ERR_NVM; goto release; } e1000_standby_nvm(hw); words_written++; } e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, (u16)(nvm->opcode_bits + 2)); e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); release: nvm->ops.release(hw); return ret_val; } /** * e1000_read_pba_string_generic - Read device part number * @hw: pointer to the HW structure * @pba_num: pointer to device part number * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. **/ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size) { s32 ret_val; u16 nvm_data; u16 pba_ptr; u16 offset; u16 length; DEBUGFUNC("e1000_read_pba_string_generic"); if ((hw->mac.type >= e1000_i210) && !e1000_get_flash_presence_i210(hw)) { DEBUGOUT("Flashless no PBA string\n"); return -E1000_ERR_NVM_PBA_SECTION; } if (pba_num == NULL) { DEBUGOUT("PBA string buffer was null\n"); return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } /* if nvm_data is not ptr guard the PBA must be in legacy format which * means pba_ptr is actually our second data word for the PBA number * and we can decode it into an ascii string */ if (nvm_data != NVM_PBA_PTR_GUARD) { DEBUGOUT("NVM PBA number is not stored as string\n"); /* make sure callers buffer is big enough to store the PBA */ if (pba_num_size < E1000_PBANUM_LENGTH) { DEBUGOUT("PBA string buffer too small\n"); return E1000_ERR_NO_SPACE; } /* extract hex string from data and pba_ptr */ pba_num[0] = (nvm_data >> 12) & 0xF; pba_num[1] = (nvm_data >> 8) & 0xF; pba_num[2] = (nvm_data >> 4) & 0xF; pba_num[3] = nvm_data & 0xF; pba_num[4] = (pba_ptr >> 12) & 0xF; pba_num[5] = (pba_ptr >> 8) & 0xF; pba_num[6] = '-'; pba_num[7] = 0; pba_num[8] = (pba_ptr >> 4) & 0xF; pba_num[9] = pba_ptr & 0xF; /* put a null character on the end of our string */ pba_num[10] = '\0'; /* switch all the data but the '-' to hex char */ for (offset = 0; offset < 10; offset++) { if (pba_num[offset] < 0xA) pba_num[offset] += '0'; else if (pba_num[offset] < 0x10) pba_num[offset] += 'A' - 0xA; } return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); return -E1000_ERR_NVM_PBA_SECTION; } /* check if pba_num buffer is big enough */ if (pba_num_size < (((u32)length * 2) - 1)) { DEBUGOUT("PBA string buffer too small\n"); return -E1000_ERR_NO_SPACE; } /* trim pba length from start of string */ pba_ptr++; length--; for (offset = 0; offset < length; offset++) { ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } pba_num[offset * 2] = (u8)(nvm_data >> 8); pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); } pba_num[offset * 2] = '\0'; return E1000_SUCCESS; } /** * e1000_read_pba_length_generic - Read device part number length * @hw: pointer to the HW structure * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number length from the EEPROM and * stores the value in pba_num_size. **/ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size) { s32 ret_val; u16 nvm_data; u16 pba_ptr; u16 length; DEBUGFUNC("e1000_read_pba_length_generic"); if (pba_num_size == NULL) { DEBUGOUT("PBA buffer size was null\n"); return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } /* if data is not ptr guard the PBA must be in legacy format */ if (nvm_data != NVM_PBA_PTR_GUARD) { *pba_num_size = E1000_PBANUM_LENGTH; return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); return -E1000_ERR_NVM_PBA_SECTION; } /* Convert from length in u16 values to u8 chars, add 1 for NULL, * and subtract 2 because length field is included in length. */ *pba_num_size = ((u32)length * 2) - 1; return E1000_SUCCESS; } /** * e1000_read_pba_num_generic - Read device part number * @hw: pointer to the HW structure * @pba_num: pointer to device part number * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. **/ s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num) { s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_read_pba_num_generic"); ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } else if (nvm_data == NVM_PBA_PTR_GUARD) { DEBUGOUT("NVM Not Supported\n"); return -E1000_NOT_IMPLEMENTED; } *pba_num = (u32)(nvm_data << 16); ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } *pba_num |= nvm_data; return E1000_SUCCESS; } /** * e1000_read_pba_raw * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @max_pba_block_size: PBA block size limit * @pba: pointer to output PBA structure * * Reads PBA from EEPROM image when eeprom_buf is not NULL. * Reads PBA from physical EEPROM device when eeprom_buf is NULL. * **/ s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 max_pba_block_size, struct e1000_pba *pba) { s32 ret_val; u16 pba_block_size; if (pba == NULL) return -E1000_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba->word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > NVM_PBA_OFFSET_1) { pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0]; pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1]; } else { return -E1000_ERR_PARAM; } } if (pba->word[0] == NVM_PBA_PTR_GUARD) { if (pba->pba_block == NULL) return -E1000_ERR_PARAM; ret_val = e1000_get_pba_block_size(hw, eeprom_buf, eeprom_buf_size, &pba_block_size); if (ret_val) return ret_val; if (pba_block_size > max_pba_block_size) return -E1000_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = e1000_read_nvm(hw, pba->word[1], pba_block_size, pba->pba_block); if (ret_val) return ret_val; } else { if (eeprom_buf_size > (u32)(pba->word[1] + pba_block_size)) { memcpy(pba->pba_block, &eeprom_buf[pba->word[1]], pba_block_size * sizeof(u16)); } else { return -E1000_ERR_PARAM; } } } return E1000_SUCCESS; } /** * e1000_write_pba_raw * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @pba: pointer to PBA structure * * Writes PBA to EEPROM image when eeprom_buf is not NULL. * Writes PBA to physical EEPROM device when eeprom_buf is NULL. * **/ s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, struct e1000_pba *pba) { s32 ret_val; if (pba == NULL) return -E1000_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba->word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > NVM_PBA_OFFSET_1) { eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0]; eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1]; } else { return -E1000_ERR_PARAM; } } if (pba->word[0] == NVM_PBA_PTR_GUARD) { if (pba->pba_block == NULL) return -E1000_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = e1000_write_nvm(hw, pba->word[1], pba->pba_block[0], pba->pba_block); if (ret_val) return ret_val; } else { if (eeprom_buf_size > (u32)(pba->word[1] + pba->pba_block[0])) { memcpy(&eeprom_buf[pba->word[1]], pba->pba_block, pba->pba_block[0] * sizeof(u16)); } else { return -E1000_ERR_PARAM; } } } return E1000_SUCCESS; } /** * e1000_get_pba_block_size * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @pba_data_size: pointer to output variable * * Returns the size of the PBA block in words. Function operates on EEPROM * image if the eeprom_buf pointer is not NULL otherwise it accesses physical * EEPROM device. * **/ s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 *pba_block_size) { s32 ret_val; u16 pba_word[2]; u16 length; DEBUGFUNC("e1000_get_pba_block_size"); if (eeprom_buf == NULL) { ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > NVM_PBA_OFFSET_1) { pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0]; pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1]; } else { return -E1000_ERR_PARAM; } } if (pba_word[0] == NVM_PBA_PTR_GUARD) { if (eeprom_buf == NULL) { ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1, &length); if (ret_val) return ret_val; } else { if (eeprom_buf_size > pba_word[1]) length = eeprom_buf[pba_word[1] + 0]; else return -E1000_ERR_PARAM; } if (length == 0xFFFF || length == 0) return -E1000_ERR_NVM_PBA_SECTION; } else { /* PBA number in legacy format, there is no PBA Block. */ length = 0; } if (pba_block_size != NULL) *pba_block_size = length; return E1000_SUCCESS; } /** * e1000_read_mac_addr_generic - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. * Since devices with two ports use the same EEPROM, we increment the * last bit in the MAC address for the second port. **/ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) { u32 rar_high; u32 rar_low; u16 i; rar_high = E1000_READ_REG(hw, E1000_RAH(0)); rar_low = E1000_READ_REG(hw, E1000_RAL(0)); for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; return E1000_SUCCESS; } /** * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_validate_nvm_checksum_generic"); for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_update_nvm_checksum_generic - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum"); for (i = 0; i < NVM_CHECKSUM_REG; i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); return ret_val; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); return ret_val; } /** * e1000_reload_nvm_generic - Reloads EEPROM * @hw: pointer to the HW structure * * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the * extended control register. **/ STATIC void e1000_reload_nvm_generic(struct e1000_hw *hw) { u32 ctrl_ext; DEBUGFUNC("e1000_reload_nvm_generic"); usec_delay(10); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_EE_RST; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); } /** * e1000_get_fw_version - Get firmware version information * @hw: pointer to the HW structure * @fw_vers: pointer to output version structure * * unsupported/not present features return 0 in version structure **/ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) { u16 eeprom_verh, eeprom_verl, etrack_test, fw_version; u8 q, hval, rem, result; u16 comb_verh, comb_verl, comb_offset; memset(fw_vers, 0, sizeof(struct e1000_fw_version)); /* basic eeprom version numbers, bits used vary by part and by tool * used to create the nvm images */ /* Check which data format we have */ switch (hw->mac.type) { case e1000_i211: e1000_read_invm_version(hw, fw_vers); return; case e1000_82575: case e1000_82576: case e1000_82580: hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); /* Use this format, unless EETRACK ID exists, * then use alternate format */ if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) { hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK) >> NVM_MINOR_SHIFT; fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK); goto etrack_id; } break; case e1000_i210: if (!(e1000_get_flash_presence_i210(hw))) { e1000_read_invm_version(hw, fw_vers); return; } /* fall through */ case e1000_i350: hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); /* find combo image version */ hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) { hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset + 1), 1, &comb_verh); hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), 1, &comb_verl); /* get Option Rom version if it exists and is valid */ if ((comb_verh && comb_verl) && ((comb_verh != NVM_VER_INVALID) && (comb_verl != NVM_VER_INVALID))) { fw_vers->or_valid = true; fw_vers->or_major = comb_verl >> NVM_COMB_VER_SHFT; fw_vers->or_build = (comb_verl << NVM_COMB_VER_SHFT) | (comb_verh >> NVM_COMB_VER_SHFT); fw_vers->or_patch = comb_verh & NVM_COMB_VER_MASK; } } break; default: hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); return; } hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; /* check for old style version format in newer images*/ if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) { eeprom_verl = (fw_version & NVM_COMB_VER_MASK); } else { eeprom_verl = (fw_version & NVM_MINOR_MASK) >> NVM_MINOR_SHIFT; } /* Convert minor value to hex before assigning to output struct * Val to be converted will not be higher than 99, per tool output */ q = eeprom_verl / NVM_HEX_CONV; hval = q * NVM_HEX_TENS; rem = eeprom_verl % NVM_HEX_CONV; result = hval + rem; fw_vers->eep_minor = result; etrack_id: if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) { hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl; } return; } ================================================ FILE: drivers/net/e1000/base/e1000_nvm.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ struct e1000_pba { u16 word[2]; u16 *pba_block; }; struct e1000_fw_version { u32 etrack_id; u16 eep_major; u16 eep_minor; u16 eep_build; u8 invm_major; u8 invm_minor; u8 invm_img_type; bool or_valid; u16 or_major; u16 or_build; u16 or_patch; }; void e1000_init_nvm_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); void e1000_null_nvm_generic(struct e1000_hw *hw); s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data); s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num); s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size); s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size); s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 max_pba_block_size, struct e1000_pba *pba); s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, struct e1000_pba *pba); s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 *pba_block_size); s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); void e1000_stop_nvm(struct e1000_hw *hw); void e1000_release_nvm_generic(struct e1000_hw *hw); void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers); #define E1000_STM_OPCODE 0xDB00 #endif ================================================ FILE: drivers/net/e1000/base/e1000_osdep.c ================================================ /****************************************************************************** Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ /*$FreeBSD$*/ #include "e1000_api.h" /* * NOTE: the following routines using the e1000 * naming style are provided to the shared * code but are OS specific */ void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) { return; } void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value) { *value = 0; return; } void e1000_pci_set_mwi(struct e1000_hw *hw) { } void e1000_pci_clear_mwi(struct e1000_hw *hw) { } /* * Read the PCI Express capabilities */ int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { return E1000_NOT_IMPLEMENTED; } /* * Write the PCI Express capabilities */ int32_t e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { return E1000_NOT_IMPLEMENTED; } ================================================ FILE: drivers/net/e1000/base/e1000_osdep.h ================================================ /****************************************************************************** Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ /*$FreeBSD$*/ #ifndef _E1000_OSDEP_H_ #define _E1000_OSDEP_H_ #include #include #include #include #include #include #include #include #include #include "../e1000_logs.h" #define DELAY(x) rte_delay_us(x) #define usec_delay(x) DELAY(x) #define usec_delay_irq(x) DELAY(x) #define msec_delay(x) DELAY(1000*(x)) #define msec_delay_irq(x) DELAY(1000*(x)) #define DEBUGFUNC(F) DEBUGOUT(F "\n"); #define DEBUGOUT(S, args...) PMD_DRV_LOG_RAW(DEBUG, S, ##args) #define DEBUGOUT1(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT2(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT3(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT6(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT7(S, args...) DEBUGOUT(S, ##args) #define UNREFERENCED_PARAMETER(_p) #define UNREFERENCED_1PARAMETER(_p) #define UNREFERENCED_2PARAMETER(_p, _q) #define UNREFERENCED_3PARAMETER(_p, _q, _r) #define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) #define FALSE 0 #define TRUE 1 #define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ /* Mutex used in the shared code */ #define E1000_MUTEX uintptr_t #define E1000_MUTEX_INIT(mutex) (*(mutex) = 0) #define E1000_MUTEX_LOCK(mutex) (*(mutex) = 1) #define E1000_MUTEX_UNLOCK(mutex) (*(mutex) = 0) typedef uint64_t u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; typedef int64_t s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; typedef int bool; #define __le16 u16 #define __le32 u32 #define __le64 u64 #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) #define E1000_PCI_REG(reg) (*((volatile uint32_t *)(reg))) #define E1000_PCI_REG_WRITE(reg, value) do { \ E1000_PCI_REG((reg)) = (rte_cpu_to_le_32(value)); \ } while (0) #define E1000_PCI_REG_ADDR(hw, reg) \ ((volatile uint32_t *)((char *)(hw)->hw_addr + (reg))) #define E1000_PCI_REG_ARRAY_ADDR(hw, reg, index) \ E1000_PCI_REG_ADDR((hw), (reg) + ((index) << 2)) static inline uint32_t e1000_read_addr(volatile void* addr) { return rte_le_to_cpu_32(E1000_PCI_REG(addr)); } /* Necessary defines */ #define E1000_MRQC_ENABLE_MASK 0x00000007 #define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 #define E1000_ALL_FULL_DUPLEX ( \ ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL) #define M88E1543_E_PHY_ID 0x01410EA0 #define NAHUM6LP_HW #define ULP_SUPPORT #define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ #define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 /* Register READ/WRITE macros */ #define E1000_READ_REG(hw, reg) \ e1000_read_addr(E1000_PCI_REG_ADDR((hw), (reg))) #define E1000_WRITE_REG(hw, reg, value) \ E1000_PCI_REG_WRITE(E1000_PCI_REG_ADDR((hw), (reg)), (value)) #define E1000_READ_REG_ARRAY(hw, reg, index) \ E1000_PCI_REG(E1000_PCI_REG_ARRAY_ADDR((hw), (reg), (index))) #define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \ E1000_PCI_REG_WRITE(E1000_PCI_REG_ARRAY_ADDR((hw), (reg), (index)), (value)) #define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY #define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY #define E1000_ACCESS_PANIC(x, hw, reg, value) \ rte_panic("%s:%u\t" RTE_STR(x) "(%p, 0x%x, 0x%x)", \ __FILE__, __LINE__, (hw), (reg), (unsigned int)(value)) /* * To be able to do IO write, we need to map IO BAR * (bar 2/4 depending on device). * Right now mapping multiple BARs is not supported by DPDK. * Fortunatelly we need it only for legacy hw support. */ #define E1000_WRITE_REG_IO(hw, reg, value) \ E1000_WRITE_REG(hw, reg, value) /* * Not implemented. */ #define E1000_READ_FLASH_REG(hw, reg) \ (E1000_ACCESS_PANIC(E1000_READ_FLASH_REG, hw, reg, 0), 0) #define E1000_READ_FLASH_REG16(hw, reg) \ (E1000_ACCESS_PANIC(E1000_READ_FLASH_REG16, hw, reg, 0), 0) #define E1000_WRITE_FLASH_REG(hw, reg, value) \ E1000_ACCESS_PANIC(E1000_WRITE_FLASH_REG, hw, reg, value) #define E1000_WRITE_FLASH_REG16(hw, reg, value) \ E1000_ACCESS_PANIC(E1000_WRITE_FLASH_REG16, hw, reg, value) #define STATIC static #ifndef ETH_ADDR_LEN #define ETH_ADDR_LEN 6 #endif #define false FALSE #define true TRUE #endif /* _E1000_OSDEP_H_ */ ================================================ FILE: drivers/net/e1000/base/e1000_phy.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" STATIC s32 e1000_wait_autoneg(struct e1000_hw *hw); STATIC s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set); STATIC u32 e1000_get_phy_addr_for_hv_page(u32 page); STATIC s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read); /* Cable length tables */ STATIC const u16 e1000_m88_cable_length_table[] = { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_m88_cable_length_table) / \ sizeof(e1000_m88_cable_length_table[0])) STATIC const u16 e1000_igp_2_cable_length_table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, 124}; #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_igp_2_cable_length_table) / \ sizeof(e1000_igp_2_cable_length_table[0])) /** * e1000_init_phy_ops_generic - Initialize PHY function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_phy_ops_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; DEBUGFUNC("e1000_init_phy_ops_generic"); /* Initialize function pointers */ phy->ops.init_params = e1000_null_ops_generic; phy->ops.acquire = e1000_null_ops_generic; phy->ops.check_polarity = e1000_null_ops_generic; phy->ops.check_reset_block = e1000_null_ops_generic; phy->ops.commit = e1000_null_ops_generic; phy->ops.force_speed_duplex = e1000_null_ops_generic; phy->ops.get_cfg_done = e1000_null_ops_generic; phy->ops.get_cable_length = e1000_null_ops_generic; phy->ops.get_info = e1000_null_ops_generic; phy->ops.set_page = e1000_null_set_page; phy->ops.read_reg = e1000_null_read_reg; phy->ops.read_reg_locked = e1000_null_read_reg; phy->ops.read_reg_page = e1000_null_read_reg; phy->ops.release = e1000_null_phy_generic; phy->ops.reset = e1000_null_ops_generic; phy->ops.set_d0_lplu_state = e1000_null_lplu_state; phy->ops.set_d3_lplu_state = e1000_null_lplu_state; phy->ops.write_reg = e1000_null_write_reg; phy->ops.write_reg_locked = e1000_null_write_reg; phy->ops.write_reg_page = e1000_null_write_reg; phy->ops.power_up = e1000_null_phy_generic; phy->ops.power_down = e1000_null_phy_generic; phy->ops.read_i2c_byte = e1000_read_i2c_byte_null; phy->ops.write_i2c_byte = e1000_write_i2c_byte_null; phy->ops.cfg_on_link_up = e1000_null_ops_generic; } /** * e1000_null_set_page - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_null_set_page"); UNREFERENCED_2PARAMETER(hw, data); return E1000_SUCCESS; } /** * e1000_null_read_reg - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_null_read_reg"); UNREFERENCED_3PARAMETER(hw, offset, data); return E1000_SUCCESS; } /** * e1000_null_phy_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_phy_generic"); UNREFERENCED_1PARAMETER(hw); return; } /** * e1000_null_lplu_state - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw, bool E1000_UNUSEDARG active) { DEBUGFUNC("e1000_null_lplu_state"); UNREFERENCED_2PARAMETER(hw, active); return E1000_SUCCESS; } /** * e1000_null_write_reg - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_null_write_reg"); UNREFERENCED_3PARAMETER(hw, offset, data); return E1000_SUCCESS; } /** * e1000_read_i2c_byte_null - No-op function, return 0 * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: data value read * **/ s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG byte_offset, u8 E1000_UNUSEDARG dev_addr, u8 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_read_i2c_byte_null"); UNREFERENCED_4PARAMETER(hw, byte_offset, dev_addr, data); return E1000_SUCCESS; } /** * e1000_write_i2c_byte_null - No-op function, return 0 * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: data value to write * **/ s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG byte_offset, u8 E1000_UNUSEDARG dev_addr, u8 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_write_i2c_byte_null"); UNREFERENCED_4PARAMETER(hw, byte_offset, dev_addr, data); return E1000_SUCCESS; } /** * e1000_check_reset_block_generic - Check if PHY reset is blocked * @hw: pointer to the HW structure * * Read the PHY management control register and check whether a PHY reset * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise * return E1000_BLK_PHY_RESET (12). **/ s32 e1000_check_reset_block_generic(struct e1000_hw *hw) { u32 manc; DEBUGFUNC("e1000_check_reset_block"); manc = E1000_READ_REG(hw, E1000_MANC); return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } /** * e1000_get_phy_id - Retrieve the PHY ID and revision * @hw: pointer to the HW structure * * Reads the PHY registers and stores the PHY ID and possibly the PHY * revision in the hardware structure. **/ s32 e1000_get_phy_id(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id; u16 retry_count = 0; DEBUGFUNC("e1000_get_phy_id"); if (!phy->ops.read_reg) return E1000_SUCCESS; while (retry_count < 2) { ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) return ret_val; phy->id = (u32)(phy_id << 16); usec_delay(20); ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) return ret_val; phy->id |= (u32)(phy_id & PHY_REVISION_MASK); phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); if (phy->id != 0 && phy->id != PHY_REVISION_MASK) return E1000_SUCCESS; retry_count++; } return E1000_SUCCESS; } /** * e1000_phy_reset_dsp_generic - Reset PHY DSP * @hw: pointer to the HW structure * * Reset the digital signal processor. **/ s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_phy_reset_dsp_generic"); if (!hw->phy.ops.write_reg) return E1000_SUCCESS; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); if (ret_val) return ret_val; return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); } /** * e1000_read_phy_reg_mdic - Read MDI control register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the MDI control register in the PHY at offset and stores the * information read to data. **/ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) { struct e1000_phy_info *phy = &hw->phy; u32 i, mdic = 0; DEBUGFUNC("e1000_read_phy_reg_mdic"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); return -E1000_ERR_PARAM; } /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ mdic = ((offset << E1000_MDIC_REG_SHIFT) | (phy->addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_READ)); E1000_WRITE_REG(hw, E1000_MDIC, mdic); /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { usec_delay_irq(50); mdic = E1000_READ_REG(hw, E1000_MDIC); if (mdic & E1000_MDIC_READY) break; } if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Read did not complete\n"); return -E1000_ERR_PHY; } if (mdic & E1000_MDIC_ERROR) { DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n", offset, (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); return -E1000_ERR_PHY; } *data = (u16) mdic; /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) usec_delay_irq(100); return E1000_SUCCESS; } /** * e1000_write_phy_reg_mdic - Write MDI control register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write to register at offset * * Writes data to MDI control register in the PHY at offset. **/ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) { struct e1000_phy_info *phy = &hw->phy; u32 i, mdic = 0; DEBUGFUNC("e1000_write_phy_reg_mdic"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); return -E1000_ERR_PARAM; } /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ mdic = (((u32)data) | (offset << E1000_MDIC_REG_SHIFT) | (phy->addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_WRITE)); E1000_WRITE_REG(hw, E1000_MDIC, mdic); /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { usec_delay_irq(50); mdic = E1000_READ_REG(hw, E1000_MDIC); if (mdic & E1000_MDIC_READY) break; } if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Write did not complete\n"); return -E1000_ERR_PHY; } if (mdic & E1000_MDIC_ERROR) { DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n", offset, (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); return -E1000_ERR_PHY; } /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) usec_delay_irq(100); return E1000_SUCCESS; } /** * e1000_read_phy_reg_i2c - Read PHY register using i2c * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the i2c interface and stores the * retrieved information in data. **/ s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) { struct e1000_phy_info *phy = &hw->phy; u32 i, i2ccmd = 0; DEBUGFUNC("e1000_read_phy_reg_i2c"); /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | (E1000_I2CCMD_OPCODE_READ)); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) break; } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Read did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } /* Need to byte-swap the 16-bit value. */ *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); return E1000_SUCCESS; } /** * e1000_write_phy_reg_i2c - Write PHY register using i2c * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset using the i2c interface. **/ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) { struct e1000_phy_info *phy = &hw->phy; u32 i, i2ccmd = 0; u16 phy_data_swapped; DEBUGFUNC("e1000_write_phy_reg_i2c"); /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/ if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) { DEBUGOUT1("PHY I2C Address %d is out of range.\n", hw->phy.addr); return -E1000_ERR_CONFIG; } /* Swap the data bytes for the I2C interface */ phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_WRITE | phy_data_swapped); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) break; } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Write did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_read_sfp_data_byte - Reads SFP module data. * @hw: pointer to the HW structure * @offset: byte location offset to be read * @data: read data buffer pointer * * Reads one byte from SFP module data stored * in SFP resided EEPROM memory or SFP diagnostic area. * Function should be called with * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters * access **/ s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data) { u32 i = 0; u32 i2ccmd = 0; u32 data_local = 0; DEBUGFUNC("e1000_read_sfp_data_byte"); if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { DEBUGOUT("I2CCMD command address exceeds upper limit\n"); return -E1000_ERR_PHY; } /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing with the * EEPROM to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_READ); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); data_local = E1000_READ_REG(hw, E1000_I2CCMD); if (data_local & E1000_I2CCMD_READY) break; } if (!(data_local & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Read did not complete\n"); return -E1000_ERR_PHY; } if (data_local & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } *data = (u8) data_local & 0xFF; return E1000_SUCCESS; } /** * e1000_write_sfp_data_byte - Writes SFP module data. * @hw: pointer to the HW structure * @offset: byte location offset to write to * @data: data to write * * Writes one byte to SFP module data stored * in SFP resided EEPROM memory or SFP diagnostic area. * Function should be called with * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters * access **/ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) { u32 i = 0; u32 i2ccmd = 0; u32 data_local = 0; DEBUGFUNC("e1000_write_sfp_data_byte"); if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { DEBUGOUT("I2CCMD command address exceeds upper limit\n"); return -E1000_ERR_PHY; } /* The programming interface is 16 bits wide * so we need to read the whole word first * then update appropriate byte lane and write * the updated word back. */ /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing * with an EEPROM to write the data given. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_READ); /* Set a command to read single word */ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); /* Poll the ready bit to see if lastly * launched I2C operation completed */ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) { /* Check if this is READ or WRITE phase */ if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) == E1000_I2CCMD_OPCODE_READ) { /* Write the selected byte * lane and update whole word */ data_local = i2ccmd & 0xFF00; data_local |= data; i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_WRITE | data_local); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); } else { break; } } } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Write did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_read_phy_reg_m88 - Read m88 PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore, if necessary, then reads the PHY register at offset * and storing the retrieved information in data. Release any acquired * semaphores before exiting. **/ s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_read_phy_reg_m88"); if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_m88 - Write m88 PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; DEBUGFUNC("e1000_write_phy_reg_m88"); if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); return ret_val; } /** * e1000_set_page_igp - Set page as on IGP-like PHY(s) * @hw: pointer to the HW structure * @page: page to set (shifted left when necessary) * * Sets PHY page required for PHY register access. Assumes semaphore is * already acquired. Note, this function sets phy.addr to 1 so the caller * must set it appropriately (if necessary) after this function returns. **/ s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) { DEBUGFUNC("e1000_set_page_igp"); DEBUGOUT1("Setting page 0x%x\n", page); hw->phy.addr = 1; return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); } /** * __e1000_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then reads the PHY register at offset * and stores the retrieved information in data. Release any acquired * semaphores before exiting. **/ STATIC s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, bool locked) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("__e1000_read_phy_reg_igp"); if (!locked) { if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } if (offset > MAX_PHY_MULTI_PAGE_REG) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (!ret_val) ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore then reads the PHY register at offset and stores the * retrieved information in data. * Release the acquired semaphore before exiting. **/ s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_igp(hw, offset, data, false); } /** * e1000_read_phy_reg_igp_locked - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset and stores the retrieved information * in data. Assumes semaphore already acquired. **/ s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_igp(hw, offset, data, true); } /** * e1000_write_phy_reg_igp - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ STATIC s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, bool locked) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_phy_reg_igp"); if (!locked) { if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } if (offset > MAX_PHY_MULTI_PAGE_REG) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (!ret_val) ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_igp - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_igp(hw, offset, data, false); } /** * e1000_write_phy_reg_igp_locked - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset. * Assumes semaphore already acquired. **/ s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_igp(hw, offset, data, true); } /** * __e1000_read_kmrn_reg - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then reads the PHY register at offset * using the kumeran interface. The information retrieved is stored in data. * Release any acquired semaphores before exiting. **/ STATIC s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, bool locked) { u32 kmrnctrlsta; DEBUGFUNC("__e1000_read_kmrn_reg"); if (!locked) { s32 ret_val = E1000_SUCCESS; if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); *data = (u16)kmrnctrlsta; if (!locked) hw->phy.ops.release(hw); return E1000_SUCCESS; } /** * e1000_read_kmrn_reg_generic - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore then reads the PHY register at offset using the * kumeran interface. The information retrieved is stored in data. * Release the acquired semaphore before exiting. **/ s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, false); } /** * e1000_read_kmrn_reg_locked - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the kumeran interface. The * information retrieved is stored in data. * Assumes semaphore already acquired. **/ s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, true); } /** * __e1000_write_kmrn_reg - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then write the data to PHY register * at the offset using the kumeran interface. Release any acquired semaphores * before exiting. **/ STATIC s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, bool locked) { u32 kmrnctrlsta; DEBUGFUNC("e1000_write_kmrn_reg_generic"); if (!locked) { s32 ret_val = E1000_SUCCESS; if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | data; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); if (!locked) hw->phy.ops.release(hw); return E1000_SUCCESS; } /** * e1000_write_kmrn_reg_generic - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore then writes the data to the PHY register at the offset * using the kumeran interface. Release the acquired semaphore before exiting. **/ s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, false); } /** * e1000_write_kmrn_reg_locked - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Write the data to PHY register at the offset using the kumeran interface. * Assumes semaphore already acquired. **/ s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, true); } /** * e1000_set_master_slave_mode - Setup PHY for Master/slave mode * @hw: pointer to the HW structure * * Sets up Master/slave mode **/ STATIC s32 e1000_set_master_slave_mode(struct e1000_hw *hw) { s32 ret_val; u16 phy_data; /* Resolve Master/Slave mode */ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data); if (ret_val) return ret_val; /* load defaults for future use */ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ? ((phy_data & CR_1000T_MS_VALUE) ? e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; switch (hw->phy.ms_type) { case e1000_ms_force_master: phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); break; case e1000_ms_force_slave: phy_data |= CR_1000T_MS_ENABLE; phy_data &= ~(CR_1000T_MS_VALUE); break; case e1000_ms_auto: phy_data &= ~CR_1000T_MS_ENABLE; /* fall-through */ default: break; } return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data); } /** * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link * @hw: pointer to the HW structure * * Sets up Carrier-sense on Transmit and downshift values. **/ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) { s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_82577"); if (hw->phy.type == e1000_phy_82580) { ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); return ret_val; } } /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data); if (ret_val) return ret_val; phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; /* Enable downshift */ phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data); if (ret_val) return ret_val; /* Set MDI/MDIX mode */ ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data); if (ret_val) return ret_val; phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; /* Options: * 0 - Auto (default) * 1 - MDI mode * 2 - MDI-X mode */ switch (hw->phy.mdix) { case 1: break; case 2: phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; break; case 0: default: phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; break; } ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data); if (ret_val) return ret_val; return e1000_set_master_slave_mode(hw); } /** * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link * @hw: pointer to the HW structure * * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock * and downshift values are set also. **/ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_m88"); /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* For BM PHY this bit is downshift enable */ if (phy->type != e1000_phy_bm) phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (phy->mdix) { case 1: phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; break; case 2: phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; break; case 3: phy_data |= M88E1000_PSCR_AUTO_X_1000T; break; case 0: default: phy_data |= M88E1000_PSCR_AUTO_X_MODE; break; } /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; /* Enable downshift on BM (disabled by default) */ if (phy->type == e1000_phy_bm) { /* For 82574/82583, first disable then enable downshift */ if (phy->id == BME1000_E_PHY_ID_R2) { phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; /* Commit the changes. */ ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } } phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; } ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; if ((phy->type == e1000_phy_m88) && (phy->revision < E1000_REVISION_4) && (phy->id != BME1000_E_PHY_ID_R2)) { /* Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data |= M88E1000_EPSCR_TX_CLK_25; if ((phy->revision == E1000_REVISION_2) && (phy->id == M88E1111_I_PHY_ID)) { /* 82573L PHY - set the downshift counter to 5x. */ phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; } else { /* Configure Master and Slave downshift values */ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; } if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { /* Set PHY page 0, register 29 to 0x0003 */ ret_val = phy->ops.write_reg(hw, 29, 0x0003); if (ret_val) return ret_val; /* Set PHY page 0, register 30 to 0x0000 */ ret_val = phy->ops.write_reg(hw, 30, 0x0000); if (ret_val) return ret_val; } /* Commit the changes. */ ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } if (phy->type == e1000_phy_82578) { ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* 82578 PHY - set the downshift count to 1x. */ phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; } return E1000_SUCCESS; } /** * e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link * @hw: pointer to the HW structure * * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's. * Also enables and sets the downshift parameters. **/ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_m88_gen2"); /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (phy->mdix) { case 1: phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; break; case 2: phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; break; case 3: /* M88E1112 does not support this mode) */ if (phy->id != M88E1112_E_PHY_ID) { phy_data |= M88E1000_PSCR_AUTO_X_1000T; break; } case 0: default: phy_data |= M88E1000_PSCR_AUTO_X_MODE; break; } /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; /* Enable downshift and setting it to X6 */ if (phy->id == M88E1543_E_PHY_ID) { phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } } phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK; phy_data |= I347AT4_PSCR_DOWNSHIFT_6X; phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; /* Commit the changes. */ ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } ret_val = e1000_set_master_slave_mode(hw); if (ret_val) return ret_val; return E1000_SUCCESS; } /** * e1000_copper_link_setup_igp - Setup igp PHY's for copper link * @hw: pointer to the HW structure * * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for * igp PHY's. **/ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_copper_link_setup_igp"); ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); return ret_val; } /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid * timeout issues when LFS is enabled. */ msec_delay(100); /* The NVM settings will configure LPLU in D3 for * non-IGP1 PHYs. */ if (phy->type == e1000_phy_igp) { /* disable lplu d3 during driver init */ ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D3\n"); return ret_val; } } /* disable lplu d0 during driver init */ if (hw->phy.ops.set_d0_lplu_state) { ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D0\n"); return ret_val; } } /* Configure mdi-mdix settings */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCR_AUTO_MDIX; switch (phy->mdix) { case 1: data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 2: data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 0: default: data |= IGP01E1000_PSCR_AUTO_MDIX; break; } ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); if (ret_val) return ret_val; /* set auto-master slave resolution settings */ if (hw->mac.autoneg) { /* when autonegotiation advertisement is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; /* Set auto Master/Slave resolution process */ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) return ret_val; data &= ~CR_1000T_MS_ENABLE; ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) return ret_val; } ret_val = e1000_set_master_slave_mode(hw); } return ret_val; } /** * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation * @hw: pointer to the HW structure * * Reads the MII auto-neg advertisement register and/or the 1000T control * register and if the PHY is already setup for auto-negotiation, then * return successful. Otherwise, setup advertisement and flow control to * the appropriate values for the wanted auto-negotiation. **/ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 mii_autoneg_adv_reg; u16 mii_1000t_ctrl_reg = 0; DEBUGFUNC("e1000_phy_setup_autoneg"); phy->autoneg_advertised &= phy->autoneg_mask; /* Read the MII Auto-Neg Advertisement Register (Address 4). */ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) return ret_val; if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); if (ret_val) return ret_val; } /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for * autoneg_advertised software override. Since we can advertise * a plethora of combinations, we need to check each bit * individually. */ /* First we clear all the 10/100 mb speed bits in the Auto-Neg * Advertisement Register (Address 4) and the 1000 mb speed bits in * the 1000Base-T Control Register (Address 9). */ mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_10T_HD_CAPS); mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); /* Do we want to advertise 10 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_HALF) { DEBUGOUT("Advertise 10mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; } /* Do we want to advertise 10 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_FULL) { DEBUGOUT("Advertise 10mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; } /* Do we want to advertise 100 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_HALF) { DEBUGOUT("Advertise 100mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; } /* Do we want to advertise 100 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_FULL) { DEBUGOUT("Advertise 100mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; } /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ if (phy->autoneg_advertised & ADVERTISE_1000_HALF) DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); /* Do we want to advertise 1000 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { DEBUGOUT("Advertise 1000mb Full duplex\n"); mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; } /* Check for a software override of the flow control settings, and * setup the PHY advertisement registers accordingly. If * auto-negotiation is enabled, then software will have to set the * "PAUSE" bits to the correct value in the Auto-Negotiation * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- * negotiation. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames * but we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: No software override. The flow control configuration * in the EEPROM is used. */ switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control (Rx & Tx) is completely disabled by a * software over-ride. */ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_rx_pause: /* Rx Flow control is enabled, and Tx Flow control is * disabled, by a software over-ride. * * Since there really isn't a way to advertise that we are * capable of Rx Pause ONLY, we will advertise that we * support both symmetric and asymmetric Rx PAUSE. Later * (in e1000_config_fc_after_link_up) we will disable the * hw's ability to send PAUSE frames. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is * disabled, by a software over-ride. */ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; case e1000_fc_full: /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); if (phy->autoneg_mask & ADVERTISE_1000_FULL) ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); return ret_val; } /** * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link * @hw: pointer to the HW structure * * Performs initial bounds checking on autoneg advertisement parameter, then * configure to advertise the full capability. Setup the PHY to autoneg * and restart the negotiation process between the link partner. If * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. **/ s32 e1000_copper_link_autoneg(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_ctrl; DEBUGFUNC("e1000_copper_link_autoneg"); /* Perform some bounds checking on the autoneg advertisement * parameter. */ phy->autoneg_advertised &= phy->autoneg_mask; /* If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ if (!phy->autoneg_advertised) phy->autoneg_advertised = phy->autoneg_mask; DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); ret_val = e1000_phy_setup_autoneg(hw); if (ret_val) { DEBUGOUT("Error Setting up Auto-Negotiation\n"); return ret_val; } DEBUGOUT("Restarting Auto-Neg\n"); /* Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) return ret_val; phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) return ret_val; /* Does the user want to wait for Auto-Neg to complete here, or * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { ret_val = e1000_wait_autoneg(hw); if (ret_val) { DEBUGOUT("Error while waiting for autoneg to complete\n"); return ret_val; } } hw->mac.get_link_status = true; return ret_val; } /** * e1000_setup_copper_link_generic - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). **/ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) { s32 ret_val; bool link; DEBUGFUNC("e1000_setup_copper_link_generic"); if (hw->mac.autoneg) { /* Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) return ret_val; } else { /* PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } } /* Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, &link); if (ret_val) return ret_val; if (link) { DEBUGOUT("Valid link established!!!\n"); hw->mac.ops.config_collision_dist(hw); ret_val = e1000_config_fc_after_link_up_generic(hw); } else { DEBUGOUT("Unable to establish link!!!\n"); } return ret_val; } /** * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. Clears the * auto-crossover to force MDI manually. Waits for link and returns * successful if link up is successful, else -E1000_ERR_PHY (-2). **/ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); if (ret_val) return ret_val; DEBUGOUT1("IGP PSCR: %X\n", phy_data); usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); } return ret_val; } /** * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. Clears the * auto-crossover to force MDI manually. Resets the PHY to commit the * changes. If time expires while waiting for link up, we reset the DSP. * After reset, TX_CLK and CRS on Tx must be set. Return successful upon * successful completion, else return corresponding error code. **/ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); /* I210 and I211 devices support Auto-Crossover in forced operation. */ if (phy->type != e1000_phy_i210) { /* Clear Auto-Crossover to force MDI manually. M88E1000 * requires MDI forced whenever speed and duplex are forced. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; } DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; /* Reset the phy to commit changes. */ ret_val = hw->phy.ops.commit(hw); if (ret_val) return ret_val; if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) { bool reset_dsp = true; switch (hw->phy.id) { case I347AT4_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1543_E_PHY_ID: case M88E1512_E_PHY_ID: case I210_I_PHY_ID: reset_dsp = false; break; default: if (hw->phy.type != e1000_phy_m88) reset_dsp = false; break; } if (!reset_dsp) { DEBUGOUT("Link taking longer than expected.\n"); } else { /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x001d); if (ret_val) return ret_val; ret_val = e1000_phy_reset_dsp_generic(hw); if (ret_val) return ret_val; } } /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; } if (hw->phy.type != e1000_phy_m88) return E1000_SUCCESS; if (hw->phy.id == I347AT4_E_PHY_ID || hw->phy.id == M88E1340M_E_PHY_ID || hw->phy.id == M88E1112_E_PHY_ID) return E1000_SUCCESS; if (hw->phy.id == I210_I_PHY_ID) return E1000_SUCCESS; if ((hw->phy.id == M88E1543_E_PHY_ID) || (hw->phy.id == M88E1512_E_PHY_ID)) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* Resetting the phy means we need to re-force TX_CLK in the * Extended PHY Specific Control Register to 25MHz clock from * the reset value of 2.5MHz. */ phy_data |= M88E1000_EPSCR_TX_CLK_25; ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); return ret_val; } /** * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex * @hw: pointer to the HW structure * * Forces the speed and duplex settings of the PHY. * This is a function pointer entry point only called by * PHY setup routines. **/ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_ife"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); if (ret_val) return ret_val; /* Disable MDI-X support for 10/100 */ ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); if (ret_val) return ret_val; data &= ~IFE_PMC_AUTO_MDIX; data &= ~IFE_PMC_FORCE_MDIX; ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); if (ret_val) return ret_val; DEBUGOUT1("IFE PMC: %X\n", data); usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; } return E1000_SUCCESS; } /** * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex * @hw: pointer to the HW structure * @phy_ctrl: pointer to current value of PHY_CONTROL * * Forces speed and duplex on the PHY by doing the following: disable flow * control, force speed/duplex on the MAC, disable auto speed detection, * disable auto-negotiation, configure duplex, configure speed, configure * the collision distance, write configuration to CTRL register. The * caller must write to the PHY_CONTROL register for these settings to * take affect. **/ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) { struct e1000_mac_info *mac = &hw->mac; u32 ctrl; DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); /* Turn off flow control when forcing speed/duplex */ hw->fc.current_mode = e1000_fc_none; /* Force speed/duplex on the mac */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ctrl &= ~E1000_CTRL_SPD_SEL; /* Disable Auto Speed Detection */ ctrl &= ~E1000_CTRL_ASDE; /* Disable autoneg on the phy */ *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; /* Forcing Full or Half Duplex? */ if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { ctrl &= ~E1000_CTRL_FD; *phy_ctrl &= ~MII_CR_FULL_DUPLEX; DEBUGOUT("Half Duplex\n"); } else { ctrl |= E1000_CTRL_FD; *phy_ctrl |= MII_CR_FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } /* Forcing 10mb or 100mb? */ if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { ctrl |= E1000_CTRL_SPD_100; *phy_ctrl |= MII_CR_SPEED_100; *phy_ctrl &= ~MII_CR_SPEED_1000; DEBUGOUT("Forcing 100mb\n"); } else { ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); DEBUGOUT("Forcing 10mb\n"); } hw->mac.ops.config_collision_dist(hw); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); } /** * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_set_d3_lplu_state_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) return ret_val; if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP02E1000_PM_D3_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } return ret_val; } /** * e1000_check_downshift_generic - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 * * A downshift is detected by querying the PHY link health. **/ s32 e1000_check_downshift_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, offset, mask; DEBUGFUNC("e1000_check_downshift_generic"); switch (phy->type) { case e1000_phy_i210: case e1000_phy_m88: case e1000_phy_gg82563: case e1000_phy_bm: case e1000_phy_82578: offset = M88E1000_PHY_SPEC_STATUS; mask = M88E1000_PSSR_DOWNSHIFT; break; case e1000_phy_igp: case e1000_phy_igp_2: case e1000_phy_igp_3: offset = IGP01E1000_PHY_LINK_HEALTH; mask = IGP01E1000_PLHR_SS_DOWNGRADE; break; default: /* speed downshift not supported */ phy->speed_downgraded = false; return E1000_SUCCESS; } ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->speed_downgraded = !!(phy_data & mask); return ret_val; } /** * e1000_check_polarity_m88 - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY specific status register. **/ s32 e1000_check_polarity_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_check_polarity_m88"); ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); if (!ret_val) phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_check_polarity_igp - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY port status register, and the * current speed (since there is no polarity at 100Mbps). **/ s32 e1000_check_polarity_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data, offset, mask; DEBUGFUNC("e1000_check_polarity_igp"); /* Polarity is determined based on the speed of * our connection. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) return ret_val; if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { offset = IGP01E1000_PHY_PCS_INIT_REG; mask = IGP01E1000_PHY_POLARITY_MASK; } else { /* This really only applies to 10Mbps since * there is no polarity for 100Mbps (always 0). */ offset = IGP01E1000_PHY_PORT_STATUS; mask = IGP01E1000_PSSR_POLARITY_REVERSED; } ret_val = phy->ops.read_reg(hw, offset, &data); if (!ret_val) phy->cable_polarity = ((data & mask) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_check_polarity_ife - Check cable polarity for IFE PHY * @hw: pointer to the HW structure * * Polarity is determined on the polarity reversal feature being enabled. **/ s32 e1000_check_polarity_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, offset, mask; DEBUGFUNC("e1000_check_polarity_ife"); /* Polarity is determined based on the reversal feature being enabled. */ if (phy->polarity_correction) { offset = IFE_PHY_EXTENDED_STATUS_CONTROL; mask = IFE_PESC_POLARITY_REVERSED; } else { offset = IFE_PHY_SPECIAL_CONTROL; mask = IFE_PSC_FORCE_POLARITY; } ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->cable_polarity = ((phy_data & mask) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_wait_autoneg - Wait for auto-neg completion * @hw: pointer to the HW structure * * Waits for auto-negotiation to complete or for the auto-negotiation time * limit to expire, which ever happens first. **/ STATIC s32 e1000_wait_autoneg(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 i, phy_status; DEBUGFUNC("e1000_wait_autoneg"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_AUTONEG_COMPLETE) break; msec_delay(100); } /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation * has completed. */ return ret_val; } /** * e1000_phy_has_link_generic - Polls PHY for link * @hw: pointer to the HW structure * @iterations: number of times to poll for link * @usec_interval: delay between polling attempts * @success: pointer to whether polling was successful or not * * Polls the PHY status register for link, 'iterations' number of times. **/ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success) { s32 ret_val = E1000_SUCCESS; u16 i, phy_status; DEBUGFUNC("e1000_phy_has_link_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; for (i = 0; i < iterations; i++) { /* Some PHYs require the PHY_STATUS register to be read * twice due to the link bit being sticky. No harm doing * it across the board. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) { /* If the first read fails, another entity may have * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ if (usec_interval >= 1000) msec_delay(usec_interval/1000); else usec_delay(usec_interval); } ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) break; if (usec_interval >= 1000) msec_delay(usec_interval/1000); else usec_delay(usec_interval); } *success = (i < iterations); return ret_val; } /** * e1000_get_cable_length_m88 - Determine cable length for m88 PHY * @hw: pointer to the HW structure * * Reads the PHY specific status register to retrieve the cable length * information. The cable length is determined by averaging the minimum and * maximum values to get the "average" cable length. The m88 PHY has four * possible cable length values, which are: * Register Value Cable Length * 0 < 50 meters * 1 50 - 80 meters * 2 80 - 110 meters * 3 110 - 140 meters * 4 > 140 meters **/ s32 e1000_get_cable_length_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, index; DEBUGFUNC("e1000_get_cable_length_m88"); ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) return ret_val; index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) return -E1000_ERR_PHY; phy->min_cable_length = e1000_m88_cable_length_table[index]; phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; return E1000_SUCCESS; } s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, phy_data2, is_cm; u16 index, default_page; DEBUGFUNC("e1000_get_cable_length_m88_gen2"); switch (hw->phy.id) { case I210_I_PHY_ID: /* Get cable length from PHY Cable Diagnostics Control Reg */ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + (I347AT4_PCDL + phy->addr), &phy_data); if (ret_val) return ret_val; /* Check if the unit of cable length is meters or cm */ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + I347AT4_PCDC, &phy_data2); if (ret_val) return ret_val; is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); /* Populate the phy structure with cable length in meters */ phy->min_cable_length = phy_data / (is_cm ? 100 : 1); phy->max_cable_length = phy_data / (is_cm ? 100 : 1); phy->cable_length = phy_data / (is_cm ? 100 : 1); break; case M88E1543_E_PHY_ID: case M88E1512_E_PHY_ID: case M88E1340M_E_PHY_ID: case I347AT4_E_PHY_ID: /* Remember the original page select and set it to 7 */ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, &default_page); if (ret_val) return ret_val; ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07); if (ret_val) return ret_val; /* Get cable length from PHY Cable Diagnostics Control Reg */ ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr), &phy_data); if (ret_val) return ret_val; /* Check if the unit of cable length is meters or cm */ ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2); if (ret_val) return ret_val; is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); /* Populate the phy structure with cable length in meters */ phy->min_cable_length = phy_data / (is_cm ? 100 : 1); phy->max_cable_length = phy_data / (is_cm ? 100 : 1); phy->cable_length = phy_data / (is_cm ? 100 : 1); /* Reset the page select to its original value */ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, default_page); if (ret_val) return ret_val; break; case M88E1112_E_PHY_ID: /* Remember the original page select and set it to 5 */ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, &default_page); if (ret_val) return ret_val; ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE, &phy_data); if (ret_val) return ret_val; index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) return -E1000_ERR_PHY; phy->min_cable_length = e1000_m88_cable_length_table[index]; phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; /* Reset the page select to its original value */ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, default_page); if (ret_val) return ret_val; break; default: return -E1000_ERR_PHY; } return ret_val; } /** * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY * @hw: pointer to the HW structure * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the * cable. By reading the AGC registers, which represent the * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, i, agc_value = 0; u16 cur_agc_index, max_agc_index = 0; u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { IGP02E1000_PHY_AGC_A, IGP02E1000_PHY_AGC_B, IGP02E1000_PHY_AGC_C, IGP02E1000_PHY_AGC_D }; DEBUGFUNC("e1000_get_cable_length_igp_2"); /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); if (ret_val) return ret_val; /* Getting bits 15:9, which represent the combination of * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. */ cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & IGP02E1000_AGC_LENGTH_MASK); /* Array index bound check. */ if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || (cur_agc_index == 0)) return -E1000_ERR_PHY; /* Remove min & max AGC values from calculation. */ if (e1000_igp_2_cable_length_table[min_agc_index] > e1000_igp_2_cable_length_table[cur_agc_index]) min_agc_index = cur_agc_index; if (e1000_igp_2_cable_length_table[max_agc_index] < e1000_igp_2_cable_length_table[cur_agc_index]) max_agc_index = cur_agc_index; agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; } agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + e1000_igp_2_cable_length_table[max_agc_index]); agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); /* Calculate cable length with the error range of +/- 10 meters. */ phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ? (agc_value - IGP02E1000_AGC_RANGE) : 0); phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; return E1000_SUCCESS; } /** * e1000_get_phy_info_m88 - Retrieve PHY information * @hw: pointer to the HW structure * * Valid for only copper links. Read the PHY status register (sticky read) * to verify that link is up. Read the PHY special control register to * determine the polarity and 10base-T extended distance. Read the PHY * special status register to determine MDI/MDIx and current speed. If * speed is 1000, then determine cable length, local and remote receiver. **/ s32 e1000_get_phy_info_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_get_phy_info_m88"); if (phy->media_type != e1000_media_type_copper) { DEBUGOUT("Phy info is only valid for copper media\n"); return -E1000_ERR_CONFIG; } ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy->polarity_correction = !!(phy_data & M88E1000_PSCR_POLARITY_REVERSAL); ret_val = e1000_check_polarity_m88(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) return ret_val; phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX); if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) return ret_val; phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { /* Set values to "undefined" */ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return ret_val; } /** * e1000_get_phy_info_igp - Retrieve igp PHY information * @hw: pointer to the HW structure * * Read PHY status to determine if link is up. If link is up, then * set/determine 10base-T extended distance and polarity correction. Read * PHY port status to determine MDI/MDIx and speed. Based on the speed, * determine on the cable length, local and remote receiver. **/ s32 e1000_get_phy_info_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_igp"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } phy->polarity_correction = true; ret_val = e1000_check_polarity_igp(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX); if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { ret_val = phy->ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) return ret_val; phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return ret_val; } /** * e1000_get_phy_info_ife - Retrieves various IFE PHY states * @hw: pointer to the HW structure * * Populates "phy" structure with various feature states. **/ s32 e1000_get_phy_info_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_ife"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data); if (ret_val) return ret_val; phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE); if (phy->polarity_correction) { ret_val = e1000_check_polarity_ife(hw); if (ret_val) return ret_val; } else { /* Polarity is forced */ phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); } ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS); /* The following parameters are undefined for 10/100 operation. */ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; return E1000_SUCCESS; } /** * e1000_phy_sw_reset_generic - PHY software reset * @hw: pointer to the HW structure * * Does a software reset of the PHY by reading the PHY control register and * setting/write the control register reset bit to the PHY. **/ s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) { s32 ret_val; u16 phy_ctrl; DEBUGFUNC("e1000_phy_sw_reset_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) return ret_val; phy_ctrl |= MII_CR_RESET; ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) return ret_val; usec_delay(1); return ret_val; } /** * e1000_phy_hw_reset_generic - PHY hardware reset * @hw: pointer to the HW structure * * Verify the reset block is not blocking us from resetting. Acquire * semaphore (if necessary) and read/set/write the device control reset * bit in the PHY. Wait the appropriate delay time for the device to * reset and release the semaphore (if necessary). **/ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u32 ctrl; DEBUGFUNC("e1000_phy_hw_reset_generic"); if (phy->ops.check_reset_block) { ret_val = phy->ops.check_reset_block(hw); if (ret_val) return E1000_SUCCESS; } ret_val = phy->ops.acquire(hw); if (ret_val) return ret_val; ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); E1000_WRITE_FLUSH(hw); usec_delay(phy->reset_delay_us); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); usec_delay(150); phy->ops.release(hw); return phy->ops.get_cfg_done(hw); } /** * e1000_get_cfg_done_generic - Generic configuration done * @hw: pointer to the HW structure * * Generic function to wait 10 milli-seconds for configuration to complete * and return success. **/ s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_get_cfg_done_generic"); UNREFERENCED_1PARAMETER(hw); msec_delay_irq(10); return E1000_SUCCESS; } /** * e1000_phy_init_script_igp3 - Inits the IGP3 PHY * @hw: pointer to the HW structure * * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. **/ s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) { DEBUGOUT("Running IGP 3 PHY init script\n"); /* PHY init IGP 3 */ /* Enable rise/fall, 10-mode work in class-A */ hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); /* Remove all caps from Replica path filter */ hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); /* Bias trimming for ADC, AFE and Driver (Default) */ hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); /* Increase Hybrid poly bias */ hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); /* Add 4% to Tx amplitude in Gig mode */ hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); /* Disable trimming (TTT) */ hw->phy.ops.write_reg(hw, 0x2011, 0x0000); /* Poly DC correction to 94.6% + 2% for all channels */ hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); /* ABS DC correction to 95.9% */ hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); /* BG temp curve trim */ hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); /* Increasing ADC OPAMP stage 1 currents to max */ hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); /* Force 1000 ( required for enabling PHY regs configuration) */ hw->phy.ops.write_reg(hw, 0x0000, 0x0140); /* Set upd_freq to 6 */ hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); /* Disable NPDFE */ hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); /* Disable adaptive fixed FFE (Default) */ hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); /* Enable FFE hysteresis */ hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); /* Fixed FFE for short cable lengths */ hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); /* Fixed FFE for medium cable lengths */ hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); /* Fixed FFE for long cable lengths */ hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); /* Enable Adaptive Clip Threshold */ hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); /* AHT reset limit to 1 */ hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); /* Set AHT master delay to 127 msec */ hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); /* Set scan bits for AHT */ hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); /* Set AHT Preset bits */ hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); /* Change integ_factor of channel A to 3 */ hw->phy.ops.write_reg(hw, 0x1895, 0x0003); /* Change prop_factor of channels BCD to 8 */ hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); /* Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); /* Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ hw->phy.ops.write_reg(hw, 0x0019, 0x008D); /* Enable restart AN on an1000_dis change */ hw->phy.ops.write_reg(hw, 0x001B, 0x2080); /* Enable wh_fifo read clock in 10/100 modes */ hw->phy.ops.write_reg(hw, 0x0014, 0x0045); /* Restart AN, Speed selection is 1000 */ hw->phy.ops.write_reg(hw, 0x0000, 0x1340); return E1000_SUCCESS; } /** * e1000_get_phy_type_from_id - Get PHY type from id * @phy_id: phy_id read from the phy * * Returns the phy type from the id. **/ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) { enum e1000_phy_type phy_type = e1000_phy_unknown; switch (phy_id) { case M88E1000_I_PHY_ID: case M88E1000_E_PHY_ID: case M88E1111_I_PHY_ID: case M88E1011_I_PHY_ID: case M88E1543_E_PHY_ID: case M88E1512_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: phy_type = e1000_phy_m88; break; case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ phy_type = e1000_phy_igp_2; break; case GG82563_E_PHY_ID: phy_type = e1000_phy_gg82563; break; case IGP03E1000_E_PHY_ID: phy_type = e1000_phy_igp_3; break; case IFE_E_PHY_ID: case IFE_PLUS_E_PHY_ID: case IFE_C_E_PHY_ID: phy_type = e1000_phy_ife; break; case BME1000_E_PHY_ID: case BME1000_E_PHY_ID_R2: phy_type = e1000_phy_bm; break; case I82578_E_PHY_ID: phy_type = e1000_phy_82578; break; case I82577_E_PHY_ID: phy_type = e1000_phy_82577; break; case I82579_E_PHY_ID: phy_type = e1000_phy_82579; break; case I217_E_PHY_ID: phy_type = e1000_phy_i217; break; case I82580_I_PHY_ID: phy_type = e1000_phy_82580; break; case I210_I_PHY_ID: phy_type = e1000_phy_i210; break; default: phy_type = e1000_phy_unknown; break; } return phy_type; } /** * e1000_determine_phy_address - Determines PHY address. * @hw: pointer to the HW structure * * This uses a trial and error method to loop through possible PHY * addresses. It tests each by reading the PHY ID registers and * checking for a match. **/ s32 e1000_determine_phy_address(struct e1000_hw *hw) { u32 phy_addr = 0; u32 i; enum e1000_phy_type phy_type = e1000_phy_unknown; hw->phy.id = phy_type; for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { hw->phy.addr = phy_addr; i = 0; do { e1000_get_phy_id(hw); phy_type = e1000_get_phy_type_from_id(hw->phy.id); /* If phy_type is valid, break - we found our * PHY address */ if (phy_type != e1000_phy_unknown) return E1000_SUCCESS; msec_delay(1); i++; } while (i < 10); } return -E1000_ERR_PHY_TYPE; } /** * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address * @page: page to access * * Returns the phy address for the page requested. **/ STATIC u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) { u32 phy_addr = 2; if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) phy_addr = 1; return phy_addr; } /** * e1000_write_phy_reg_bm - Write BM PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; u32 page = offset >> IGP_PAGE_SHIFT; DEBUGFUNC("e1000_write_phy_reg_bm"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, false, false); goto release; } hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ if (hw->phy.addr == 1) { page_shift = IGP_PAGE_SHIFT; page_select = IGP01E1000_PHY_PAGE_SELECT; } else { page_shift = 0; page_select = BM_PHY_PAGE_SELECT; } /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_write_phy_reg_mdic(hw, page_select, (page << page_shift)); if (ret_val) goto release; } ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_bm - Read BM PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore, if necessary, then reads the PHY register at offset * and storing the retrieved information in data. Release any acquired * semaphores before exiting. **/ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; u32 page = offset >> IGP_PAGE_SHIFT; DEBUGFUNC("e1000_read_phy_reg_bm"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, true, false); goto release; } hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ if (hw->phy.addr == 1) { page_shift = IGP_PAGE_SHIFT; page_select = IGP01E1000_PHY_PAGE_SELECT; } else { page_shift = 0; page_select = BM_PHY_PAGE_SELECT; } /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_write_phy_reg_mdic(hw, page_select, (page << page_shift)); if (ret_val) goto release; } ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_bm2 - Read BM PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore, if necessary, then reads the PHY register at offset * and storing the retrieved information in data. Release any acquired * semaphores before exiting. **/ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; u16 page = (u16)(offset >> IGP_PAGE_SHIFT); DEBUGFUNC("e1000_read_phy_reg_bm2"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, true, false); goto release; } hw->phy.addr = 1; if (offset > MAX_PHY_MULTI_PAGE_REG) { /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, page); if (ret_val) goto release; } ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_bm2 - Write BM PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; u16 page = (u16)(offset >> IGP_PAGE_SHIFT); DEBUGFUNC("e1000_write_phy_reg_bm2"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, false, false); goto release; } hw->phy.addr = 1; if (offset > MAX_PHY_MULTI_PAGE_REG) { /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, page); if (ret_val) goto release; } ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers * @hw: pointer to the HW structure * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG * * Assumes semaphore already acquired and phy_reg points to a valid memory * address to store contents of the BM_WUC_ENABLE_REG register. **/ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) { s32 ret_val; u16 temp; DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm"); if (!phy_reg) return -E1000_ERR_PARAM; /* All page select, port ctrl and wakeup registers use phy address 1 */ hw->phy.addr = 1; /* Select Port Control Registers page */ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); if (ret_val) { DEBUGOUT("Could not set Port Control page\n"); return ret_val; } ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); if (ret_val) { DEBUGOUT2("Could not read PHY register %d.%d\n", BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); return ret_val; } /* Enable both PHY wakeup mode and Wakeup register page writes. * Prevent a power state change by disabling ME and Host PHY wakeup. */ temp = *phy_reg; temp |= BM_WUC_ENABLE_BIT; temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT); ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp); if (ret_val) { DEBUGOUT2("Could not write PHY register %d.%d\n", BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); return ret_val; } /* Select Host Wakeup Registers page - caller now able to write * registers on the Wakeup registers page */ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); } /** * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs * @hw: pointer to the HW structure * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG * * Restore BM_WUC_ENABLE_REG to its original value. * * Assumes semaphore already acquired and *phy_reg is the contents of the * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by * caller. **/ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) { s32 ret_val; DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm"); if (!phy_reg) return -E1000_ERR_PARAM; /* Select Port Control Registers page */ ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); if (ret_val) { DEBUGOUT("Could not set Port Control page\n"); return ret_val; } /* Restore 769.17 to its original value */ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg); if (ret_val) DEBUGOUT2("Could not restore PHY register %d.%d\n", BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); return ret_val; } /** * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register * @hw: pointer to the HW structure * @offset: register offset to be read or written * @data: pointer to the data to read or write * @read: determines if operation is read or write * @page_set: BM_WUC_PAGE already set and access enabled * * Read the PHY register at offset and store the retrieved information in * data, or write data to PHY register at offset. Note the procedure to * access the PHY wakeup registers is different than reading the other PHY * registers. It works as such: * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1 * 2) Set page to 800 for host (801 if we were manageability) * 3) Write the address using the address opcode (0x11) * 4) Read or write the data using the data opcode (0x12) * 5) Restore 769.17.2 to its original value * * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm(). * * Assumes semaphore is already acquired. When page_set==true, assumes * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()). **/ STATIC s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set) { s32 ret_val; u16 reg = BM_PHY_REG_NUM(offset); u16 page = BM_PHY_REG_PAGE(offset); u16 phy_reg = 0; DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ if ((hw->mac.type == e1000_pchlan) && (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) DEBUGOUT1("Attempting to access page %d while gig enabled.\n", page); if (!page_set) { /* Enable access to PHY wakeup registers */ ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); if (ret_val) { DEBUGOUT("Could not enable PHY wakeup reg access\n"); return ret_val; } } DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg); /* Write the Wakeup register page offset value using opcode 0x11 */ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); if (ret_val) { DEBUGOUT1("Could not write address opcode to page %d\n", page); return ret_val; } if (read) { /* Read the Wakeup register page value using opcode 0x12 */ ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, data); } else { /* Write the Wakeup register page value using opcode 0x12 */ ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, *data); } if (ret_val) { DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg); return ret_val; } if (!page_set) ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); return ret_val; } /** * e1000_power_up_phy_copper - Restore copper link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, restore the link to previous * settings. **/ void e1000_power_up_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg &= ~MII_CR_POWER_DOWN; if (hw->phy.type == e1000_phy_i210) { hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); power_reg &= ~GS40G_CS_POWER_DOWN; hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); } /** * e1000_power_down_phy_copper - Restore copper link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, restore the link to previous * settings. **/ void e1000_power_down_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; /* i210 Phy requires an additional bit for power up/down */ if (hw->phy.type == e1000_phy_i210) { hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); power_reg |= GS40G_CS_POWER_DOWN; hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); msec_delay(1); } /** * __e1000_read_phy_reg_hv - Read HV PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then reads the PHY register at offset * and stores the retrieved information in data. Release any acquired * semaphore before exiting. **/ STATIC s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool locked, bool page_set) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); DEBUGFUNC("__e1000_read_phy_reg_hv"); if (!locked) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, true, page_set); goto out; } if (page > 0 && page < HV_INTC_FC_PAGE_START) { ret_val = e1000_access_phy_debug_regs_hv(hw, offset, data, true); goto out; } if (!page_set) { if (page == HV_INTC_FC_PAGE_START) page = 0; if (reg > MAX_PHY_MULTI_PAGE_REG) { /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_set_page_igp(hw, (page << IGP_PAGE_SHIFT)); hw->phy.addr = phy_addr; if (ret_val) goto out; } } DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, page << IGP_PAGE_SHIFT, reg); ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); out: if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_hv - Read HV PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore then reads the PHY register at offset and stores * the retrieved information in data. Release the acquired semaphore * before exiting. **/ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_hv(hw, offset, data, false, false); } /** * e1000_read_phy_reg_hv_locked - Read HV PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset and stores the retrieved information * in data. Assumes semaphore already acquired. **/ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_hv(hw, offset, data, true, false); } /** * e1000_read_phy_reg_page_hv - Read HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Reads the PHY register at offset and stores the retrieved information * in data. Assumes semaphore already acquired and page already set. **/ s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_hv(hw, offset, data, true, true); } /** * __e1000_write_phy_reg_hv - Write HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ STATIC s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, bool locked, bool page_set) { s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); DEBUGFUNC("__e1000_write_phy_reg_hv"); if (!locked) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, false, page_set); goto out; } if (page > 0 && page < HV_INTC_FC_PAGE_START) { ret_val = e1000_access_phy_debug_regs_hv(hw, offset, &data, false); goto out; } if (!page_set) { if (page == HV_INTC_FC_PAGE_START) page = 0; /* Workaround MDIO accesses being disabled after entering IEEE * Power Down (when bit 11 of the PHY Control register is set) */ if ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision >= 1) && (hw->phy.addr == 2) && !(MAX_PHY_REG_ADDRESS & reg) && (data & (1 << 11))) { u16 data2 = 0x7EFF; ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, &data2, false); if (ret_val) goto out; } if (reg > MAX_PHY_MULTI_PAGE_REG) { /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_set_page_igp(hw, (page << IGP_PAGE_SHIFT)); hw->phy.addr = phy_addr; if (ret_val) goto out; } } DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page, page << IGP_PAGE_SHIFT, reg); ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); out: if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_hv - Write HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore then writes the data to PHY register at the offset. * Release the acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_hv(hw, offset, data, false, false); } /** * e1000_write_phy_reg_hv_locked - Write HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset. Assumes semaphore * already acquired. **/ s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_hv(hw, offset, data, true, false); } /** * e1000_write_phy_reg_page_hv - Write HV PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset. Assumes semaphore * already acquired and page already set. **/ s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_hv(hw, offset, data, true, true); } /** * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page * @page: page to be accessed **/ STATIC u32 e1000_get_phy_addr_for_hv_page(u32 page) { u32 phy_addr = 2; if (page >= HV_INTC_FC_PAGE_START) phy_addr = 1; return phy_addr; } /** * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers * @hw: pointer to the HW structure * @offset: register offset to be read or written * @data: pointer to the data to be read or written * @read: determines if operation is read or write * * Reads the PHY register at offset and stores the retreived information * in data. Assumes semaphore already acquired. Note that the procedure * to access these regs uses the address port and data port to read/write. * These accesses done with PHY address 2 and without using pages. **/ STATIC s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read) { s32 ret_val; u32 addr_reg; u32 data_reg; DEBUGFUNC("e1000_access_phy_debug_regs_hv"); /* This takes care of the difference with desktop vs mobile phy */ addr_reg = ((hw->phy.type == e1000_phy_82578) ? I82578_ADDR_REG : I82577_ADDR_REG); data_reg = addr_reg + 1; /* All operations in this function are phy address 2 */ hw->phy.addr = 2; /* masking with 0x3F to remove the page from offset */ ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); if (ret_val) { DEBUGOUT("Could not write the Address Offset port register\n"); return ret_val; } /* Read or write the data value next */ if (read) ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data); else ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data); if (ret_val) DEBUGOUT("Could not access the Data port register\n"); return ret_val; } /** * e1000_link_stall_workaround_hv - Si workaround * @hw: pointer to the HW structure * * This function works around a Si bug where the link partner can get * a link up indication before the PHY does. If small packets are sent * by the link partner they can be placed in the packet buffer without * being properly accounted for by the PHY and will stall preventing * further packets from being received. The workaround is to clear the * packet buffer after the PHY detects link up. **/ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_link_stall_workaround_hv"); if (hw->phy.type != e1000_phy_82578) return E1000_SUCCESS; /* Do not apply workaround if in PHY loopback bit 14 set */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &data); if (data & PHY_CONTROL_LB) return E1000_SUCCESS; /* check if link is up and at 1Gbps */ ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data); if (ret_val) return ret_val; data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | BM_CS_STATUS_SPEED_MASK); if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | BM_CS_STATUS_SPEED_1000)) return E1000_SUCCESS; msec_delay(200); /* flush the packets in the fifo buffer */ ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL, (HV_MUX_DATA_CTRL_GEN_TO_MAC | HV_MUX_DATA_CTRL_FORCE_SPEED)); if (ret_val) return ret_val; return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC); } /** * e1000_check_polarity_82577 - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY specific status register. **/ s32 e1000_check_polarity_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_check_polarity_82577"); ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); if (!ret_val) phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. **/ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_82577"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); } return ret_val; } /** * e1000_get_phy_info_82577 - Retrieve I82577 PHY information * @hw: pointer to the HW structure * * Read PHY status to determine if link is up. If link is up, then * set/determine 10base-T extended distance and polarity correction. Read * PHY port status to determine MDI/MDIx and speed. Based on the speed, * determine on the cable length, local and remote receiver. **/ s32 e1000_get_phy_info_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_82577"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } phy->polarity_correction = true; ret_val = e1000_check_polarity_82577(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX); if ((data & I82577_PHY_STATUS2_SPEED_MASK) == I82577_PHY_STATUS2_SPEED_1000MBPS) { ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) return ret_val; phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return E1000_SUCCESS; } /** * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY * @hw: pointer to the HW structure * * Reads the diagnostic status register and verifies result is valid before * placing it in the phy_cable_length field. **/ s32 e1000_get_cable_length_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, length; DEBUGFUNC("e1000_get_cable_length_82577"); ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data); if (ret_val) return ret_val; length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >> I82577_DSTATUS_CABLE_LENGTH_SHIFT); if (length == E1000_CABLE_LENGTH_UNDEFINED) return -E1000_ERR_PHY; phy->cable_length = length; return E1000_SUCCESS; } /** * e1000_write_phy_reg_gs40g - Write GS40G PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; u16 page = offset >> GS40G_PAGE_SHIFT; DEBUGFUNC("e1000_write_phy_reg_gs40g"); offset = offset & GS40G_OFFSET_MASK; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); if (ret_val) goto release; ret_val = e1000_write_phy_reg_mdic(hw, offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_gs40g - Read GS40G PHY register * @hw: pointer to the HW structure * @offset: lower half is register offset to read to * upper half is page to use. * @data: data to read at register offset * * Acquires semaphore, if necessary, then reads the data in the PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; u16 page = offset >> GS40G_PAGE_SHIFT; DEBUGFUNC("e1000_read_phy_reg_gs40g"); offset = offset & GS40G_OFFSET_MASK; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); if (ret_val) goto release; ret_val = e1000_read_phy_reg_mdic(hw, offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_mphy - Read mPHY control register * @hw: pointer to the HW structure * @address: address to be read * @data: pointer to the read data * * Reads the mPHY control register in the PHY at offset and stores the * information read to data. **/ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) { u32 mphy_ctrl = 0; bool locked = false; bool ready; DEBUGFUNC("e1000_read_phy_reg_mphy"); /* Check if mPHY is ready to read/write operations */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* Check if mPHY access is disabled and enable it if so */ mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) { locked = true; ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; mphy_ctrl |= E1000_MPHY_ENA_ACCESS; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); } /* Set the address that we want to read */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* We mask address, because we want to use only current lane */ mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK & ~E1000_MPHY_ADDRESS_FNC_OVERRIDE) | (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; *data = E1000_READ_REG(hw, E1000_MPHY_DATA); /* Disable access to mPHY if it was originally disabled */ if (locked) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); return E1000_SUCCESS; } /** * e1000_write_phy_reg_mphy - Write mPHY control register * @hw: pointer to the HW structure * @address: address to write to * @data: data to write to register at offset * @line_override: used when we want to use different line than default one * * Writes data to mPHY control register. **/ s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, bool line_override) { u32 mphy_ctrl = 0; bool locked = false; bool ready; DEBUGFUNC("e1000_write_phy_reg_mphy"); /* Check if mPHY is ready to read/write operations */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* Check if mPHY access is disabled and enable it if so */ mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) { locked = true; ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; mphy_ctrl |= E1000_MPHY_ENA_ACCESS; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); } /* Set the address that we want to read */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* We mask address, because we want to use only current lane */ if (line_override) mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE; else mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE; mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) | (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_DATA, data); /* Disable access to mPHY if it was originally disabled */ if (locked) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); return E1000_SUCCESS; } /** * e1000_is_mphy_ready - Check if mPHY control register is not busy * @hw: pointer to the HW structure * * Returns mPHY control register status. **/ bool e1000_is_mphy_ready(struct e1000_hw *hw) { u16 retry_count = 0; u32 mphy_ctrl = 0; bool ready = false; while (retry_count < 2) { mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_BUSY) { usec_delay(20); retry_count++; continue; } ready = true; break; } if (!ready) DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n"); return ready; } ================================================ FILE: drivers/net/e1000/base/e1000_phy.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_PHY_H_ #define _E1000_PHY_H_ void e1000_init_phy_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data); void e1000_null_phy_generic(struct e1000_hw *hw); s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_null_set_page(struct e1000_hw *hw, u16 data); s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 e1000_check_downshift_generic(struct e1000_hw *hw); s32 e1000_check_polarity_m88(struct e1000_hw *hw); s32 e1000_check_polarity_igp(struct e1000_hw *hw); s32 e1000_check_polarity_ife(struct e1000_hw *hw); s32 e1000_check_reset_block_generic(struct e1000_hw *hw); s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); s32 e1000_copper_link_autoneg(struct e1000_hw *hw); s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); s32 e1000_get_cable_length_m88(struct e1000_hw *hw); s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw); s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); s32 e1000_get_phy_id(struct e1000_hw *hw); s32 e1000_get_phy_info_igp(struct e1000_hw *hw); s32 e1000_get_phy_info_m88(struct e1000_hw *hw); s32 e1000_get_phy_info_ife(struct e1000_hw *hw); s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); s32 e1000_determine_phy_address(struct e1000_hw *hw); s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); void e1000_power_up_phy_copper(struct e1000_hw *hw); void e1000_power_down_phy_copper(struct e1000_hw *hw); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data); s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data); s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); s32 e1000_check_polarity_82577(struct e1000_hw *hw); s32 e1000_get_phy_info_82577(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); s32 e1000_get_cable_length_82577(struct e1000_hw *hw); s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data); s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, bool line_override); bool e1000_is_mphy_ready(struct e1000_hw *hw); #define E1000_MAX_PHY_ADDR 8 /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ #define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ #define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ #define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ #define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ #define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ #define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ #define IGP_PAGE_SHIFT 5 #define PHY_REG_MASK 0x1F /* GS40G - I210 PHY defines */ #define GS40G_PAGE_SELECT 0x16 #define GS40G_PAGE_SHIFT 16 #define GS40G_OFFSET_MASK 0xFFFF #define GS40G_PAGE_2 0x20000 #define GS40G_MAC_REG2 0x15 #define GS40G_MAC_LB 0x4140 #define GS40G_MAC_SPEED_1G 0X0006 #define GS40G_COPPER_SPEC 0x0010 #define GS40G_CS_POWER_DOWN 0x0002 /* BM/HV Specific Registers */ #define BM_PORT_CTRL_PAGE 769 #define BM_WUC_PAGE 800 #define BM_WUC_ADDRESS_OPCODE 0x11 #define BM_WUC_DATA_OPCODE 0x12 #define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE #define BM_WUC_ENABLE_REG 17 #define BM_WUC_ENABLE_BIT (1 << 2) #define BM_WUC_HOST_WU_BIT (1 << 4) #define BM_WUC_ME_WU_BIT (1 << 5) #define PHY_UPPER_SHIFT 21 #define BM_PHY_REG(page, reg) \ (((reg) & MAX_PHY_REG_ADDRESS) |\ (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) #define BM_PHY_REG_PAGE(offset) \ ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) #define BM_PHY_REG_NUM(offset) \ ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ ~MAX_PHY_REG_ADDRESS))) #define HV_INTC_FC_PAGE_START 768 #define I82578_ADDR_REG 29 #define I82577_ADDR_REG 16 #define I82577_CFG_REG 22 #define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) #define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */ #define I82577_CTRL_REG 23 /* 82577 specific PHY registers */ #define I82577_PHY_CTRL_2 18 #define I82577_PHY_LBK_CTRL 19 #define I82577_PHY_STATUS_2 26 #define I82577_PHY_DIAG_STATUS 31 /* I82577 PHY Status 2 */ #define I82577_PHY_STATUS2_REV_POLARITY 0x0400 #define I82577_PHY_STATUS2_MDIX 0x0800 #define I82577_PHY_STATUS2_SPEED_MASK 0x0300 #define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 /* I82577 PHY Control 2 */ #define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 #define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 #define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 /* I82577 PHY Diagnostics Status */ #define I82577_DSTATUS_CABLE_LENGTH 0x03FC #define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 /* 82580 PHY Power Management */ #define E1000_82580_PHY_POWER_MGMT 0xE14 #define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ #define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ #define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ #define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ #define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */ #define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */ #define E1000_MPHY_BUSY 0x00010000 /* busy bit */ #define E1000_MPHY_ADDRESS_FNC_OVERRIDE 0x20000000 /* fnc_override bit */ #define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address mask */ /* BM PHY Copper Specific Control 1 */ #define BM_CS_CTRL1 16 /* BM PHY Copper Specific Status */ #define BM_CS_STATUS 17 #define BM_CS_STATUS_LINK_UP 0x0400 #define BM_CS_STATUS_RESOLVED 0x0800 #define BM_CS_STATUS_SPEED_MASK 0xC000 #define BM_CS_STATUS_SPEED_1000 0x8000 /* 82577 Mobile Phy Status Register */ #define HV_M_STATUS 26 #define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 #define HV_M_STATUS_SPEED_MASK 0x0300 #define HV_M_STATUS_SPEED_1000 0x0200 #define HV_M_STATUS_SPEED_100 0x0100 #define HV_M_STATUS_LINK_UP 0x0040 #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078 #define IGP01E1000_PSCR_AUTO_MDIX 0x1000 #define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ #define IGP01E1000_PSCFR_SMART_SPEED 0x0080 /* Enable flexible speed on link-up */ #define IGP01E1000_GMII_FLEX_SPD 0x0010 #define IGP01E1000_GMII_SPD 0x0020 /* Enable SPD */ #define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ #define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ #define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ #define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 #define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 #define IGP01E1000_PSSR_MDIX 0x0800 #define IGP01E1000_PSSR_SPEED_MASK 0xC000 #define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 #define IGP02E1000_PHY_CHANNEL_NUM 4 #define IGP02E1000_PHY_AGC_A 0x11B1 #define IGP02E1000_PHY_AGC_B 0x12B1 #define IGP02E1000_PHY_AGC_C 0x14B1 #define IGP02E1000_PHY_AGC_D 0x18B1 #define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */ #define IGP02E1000_AGC_LENGTH_MASK 0x7F #define IGP02E1000_AGC_RANGE 15 #define E1000_CABLE_LENGTH_UNDEFINED 0xFF #define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 #define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 #define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ #define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ #define E1000_KMRNCTRLSTA_OP_MODES 0x1F /* Kumeran Modes of Operation */ #define E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC 0x0002 /* change LSC to CSC */ #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ #define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */ #define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ /* IFE PHY Extended Status Control */ #define IFE_PESC_POLARITY_REVERSED 0x0100 /* IFE PHY Special Control */ #define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 #define IFE_PSC_FORCE_POLARITY 0x0020 /* IFE PHY Special Control and LED Control */ #define IFE_PSCL_PROBE_MODE 0x0020 #define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ #define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ /* IFE PHY MDIX Control */ #define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ #define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ #define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */ /* SFP modules ID memory locations */ #define E1000_SFF_IDENTIFIER_OFFSET 0x00 #define E1000_SFF_IDENTIFIER_SFF 0x02 #define E1000_SFF_IDENTIFIER_SFP 0x03 #define E1000_SFF_ETH_FLAGS_OFFSET 0x06 /* Flags for SFP modules compatible with ETH up to 1Gb */ struct sfp_e1000_flags { u8 e1000_base_sx:1; u8 e1000_base_lx:1; u8 e1000_base_cx:1; u8 e1000_base_t:1; u8 e100_base_lx:1; u8 e100_base_fx:1; u8 e10_base_bx10:1; u8 e10_base_px:1; }; /* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */ #define E1000_SFF_VENDOR_OUI_TYCO 0x00407600 #define E1000_SFF_VENDOR_OUI_FTL 0x00906500 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100 #endif ================================================ FILE: drivers/net/e1000/base/e1000_regs.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_REGS_H_ #define _E1000_REGS_H_ #define E1000_CTRL 0x00000 /* Device Control - RW */ #define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ #define E1000_STATUS 0x00008 /* Device Status - RO */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_MDICNFG 0x00E04 /* MDI Config - RW */ #define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */ #define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */ #define E1000_EEPROM_PCIE_CTRL_WORD_2 0x28 /* EEPROM PCIe Ctrl Word 2 */ #define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */ #define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */ #define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */ #define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */ #define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */ #define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */ #define E1000_PPHY_CTRL 0x5b48 /* PCIe PHY Control */ #define E1000_I350_BARCTRL 0x5BFC /* BAR ctrl reg */ #define E1000_I350_DTXMXPKTSZ 0x355C /* Maximum sent packet size reg*/ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #if !defined(EXTERNAL_RELEASE) || (defined(NAHUM6LP_HW) && defined(ULP_SUPPORT)) #define E1000_FEXT 0x0002C /* Future Extended - RW */ #endif /* !EXTERNAL_RELEASE || (NAHUM6LP_HW && ULP_SUPPORT) */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ #define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ #define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ #define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ #define E1000_SVCR 0x000F0 #define E1000_SVT 0x000F4 #define E1000_LPIC 0x000FC /* Low Power IDLE control */ #define E1000_RCTL 0x00100 /* Rx Control - RW */ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ #define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ #define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ #define E1000_PBA_ECC 0x01100 /* PBA ECC Register */ #define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ #define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) #define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ #define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ #define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ #define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ #define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ #define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ #define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ #define E1000_TCTL 0x00400 /* Tx Control - RW */ #define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ #define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ #define E1000_TBT 0x00448 /* Tx Burst Timer - RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ #define E1000_LEDCTL 0x00E00 /* LED Control - RW */ #define E1000_LEDMUX 0x08130 /* LED MUX Control */ #define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ #define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ #define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ #define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ #define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ #define E1000_FLSWCTL 0x01030 /* FLASH control register */ #define E1000_FLSWDATA 0x01034 /* FLASH data register */ #define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ #define E1000_FLOP 0x0103C /* FLASH Opcode Register */ #define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ #define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ #define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */ #define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */ #define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */ #define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */ #define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */ #define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */ #define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */ #define E1000_I2C_CLK_STRETCH_DIS 0x00008000 /* I2C- Dis Clk Stretching */ #define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ #define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ #define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ #define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ #define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ #define E1000_ICR_V2 0x01500 /* Intr Cause - new location - RC */ #define E1000_ICS_V2 0x01504 /* Intr Cause Set - new location - WO */ #define E1000_IMS_V2 0x01508 /* Intr Mask Set/Read - new location - RW */ #define E1000_IMC_V2 0x0150C /* Intr Mask Clear - new location - WO */ #define E1000_IAM_V2 0x01510 /* Intr Ack Auto Mask - new location - RW */ #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ #define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ #define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ #define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ #define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ #define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ #define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ /* Split and Replication Rx Control - RW */ #define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */ #define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */ #define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ #define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ #define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ #define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ #define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer Si - RW */ #define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */ #define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ #define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ #define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */ #define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */ #define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */ #define E1000_I210_FLMNGCTL 0x12038 #define E1000_I210_FLMNGDATA 0x1203C #define E1000_I210_FLMNGCNT 0x12040 #define E1000_I210_FLSWCTL 0x12048 #define E1000_I210_FLSWDATA 0x1204C #define E1000_I210_FLSWCNT 0x12050 #define E1000_I210_FLA 0x1201C #define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n)) #define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */ /* QAV Tx mode control register */ #define E1000_I210_TQAVCTRL 0x3570 /* QAV Tx mode control register bitfields masks */ /* QAV enable */ #define E1000_TQAVCTRL_MODE (1 << 0) /* Fetching arbitration type */ #define E1000_TQAVCTRL_FETCH_ARB (1 << 4) /* Fetching timer enable */ #define E1000_TQAVCTRL_FETCH_TIMER_ENABLE (1 << 5) /* Launch arbitration type */ #define E1000_TQAVCTRL_LAUNCH_ARB (1 << 8) /* Launch timer enable */ #define E1000_TQAVCTRL_LAUNCH_TIMER_ENABLE (1 << 9) /* SP waits for SR enable */ #define E1000_TQAVCTRL_SP_WAIT_SR (1 << 10) /* Fetching timer correction */ #define E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET 16 #define E1000_TQAVCTRL_FETCH_TIMER_DELTA \ (0xFFFF << E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET) /* High credit registers where _n can be 0 or 1. */ #define E1000_I210_TQAVHC(_n) (0x300C + 0x40 * (_n)) /* Queues fetch arbitration priority control register */ #define E1000_I210_TQAVARBCTRL 0x3574 /* Queues priority masks where _n and _p can be 0-3. */ #define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n)) /* QAV Tx mode control registers where _n can be 0 or 1. */ #define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n)) /* QAV Tx mode control register bitfields masks */ #define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */ #define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */ #define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */ /* Good transmitted packets counter registers */ #define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) /* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */ #define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n)) #define E1000_MMDAC 13 /* MMD Access Control */ #define E1000_MMDAAD 14 /* MMD Access Address/Data */ /* Convenience macros * * Note: "_n" is the queue number of the register to be written to. * * Example usage: * E1000_RDBAL_REG(current_rx_queue) */ #define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ (0x0C000 + ((_n) * 0x40))) #define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ (0x0C004 + ((_n) * 0x40))) #define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ (0x0C008 + ((_n) * 0x40))) #define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \ (0x0C00C + ((_n) * 0x40))) #define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ (0x0C010 + ((_n) * 0x40))) #define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ (0x0C014 + ((_n) * 0x40))) #define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) #define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ (0x0C018 + ((_n) * 0x40))) #define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ (0x0C028 + ((_n) * 0x40))) #define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \ (0x0C030 + ((_n) * 0x40))) #define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ (0x0E000 + ((_n) * 0x40))) #define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ (0x0E004 + ((_n) * 0x40))) #define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ (0x0E008 + ((_n) * 0x40))) #define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ (0x0E010 + ((_n) * 0x40))) #define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ (0x0E014 + ((_n) * 0x40))) #define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) #define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ (0x0E028 + ((_n) * 0x40))) #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ (0x0E038 + ((_n) * 0x40))) #define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ (0x0E03C + ((_n) * 0x40))) #define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) #define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ #define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ #define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ #define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) #define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ (0x054E0 + ((_i - 16) * 8))) #define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ (0x054E4 + ((_i - 16) * 8))) #define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) #define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) #define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) #define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) #define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) #define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) #define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) #define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) #define E1000_PBSLAC 0x03100 /* Pkt Buffer Slave Access Control */ #define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Pkt Buffer DWORD */ #define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ /* Same as TXPBS, renamed for newer Si - RW */ #define E1000_ITPBS 0x03404 #define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ #define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ #define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ #define E1000_TDPUMB 0x0357C /* DMA Tx Desc uC Mail Box - RW */ #define E1000_TDPUAD 0x03580 /* DMA Tx Desc uC Addr Command - RW */ #define E1000_TDPUWD 0x03584 /* DMA Tx Desc uC Data Write - RW */ #define E1000_TDPURD 0x03588 /* DMA Tx Desc uC Data Read - RW */ #define E1000_TDPUCTL 0x0358C /* DMA Tx Desc uC Control - RW */ #define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ #define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ #define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ /* DMA Tx Max Total Allow Size Reqs - RW */ #define E1000_DTXMXSZRQ 0x03540 #define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ #define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ #define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ #define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ #define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ #define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ #define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ #define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ #define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ #define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ #define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ #define E1000_COLC 0x04028 /* Collision Count - R/clr */ #define E1000_DC 0x04030 /* Defer Count - R/clr */ #define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ #define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ #define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ #define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ #define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ #define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ #define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ #define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ #define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ #define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ #define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ #define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ #define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ #define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ #define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ #define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ #define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ #define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ #define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ #define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ #define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ #define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ #define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ #define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ #define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ #define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ #define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ #define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ #define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ #define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ #define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ #define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ #define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ #define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ #define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ #define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ #define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ #define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ #define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ #define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ #define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ #define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ #define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ #define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ #define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ #define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ #define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ #define E1000_IAC 0x04100 /* Interrupt Assertion Count */ #define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ #define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ #define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ #define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ #define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ #define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ #define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ #define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ #define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */ #define E1000_VFGPRC 0x00F10 #define E1000_VFGORC 0x00F18 #define E1000_VFMPRC 0x00F3C #define E1000_VFGPTC 0x00F14 #define E1000_VFGOTC 0x00F34 #define E1000_VFGOTLBC 0x00F50 #define E1000_VFGPTLBC 0x00F44 #define E1000_VFGORLBC 0x00F48 #define E1000_VFGPRLBC 0x00F40 /* Virtualization statistical counters */ #define E1000_PFVFGPRC(_n) (0x010010 + (0x100 * (_n))) #define E1000_PFVFGPTC(_n) (0x010014 + (0x100 * (_n))) #define E1000_PFVFGORC(_n) (0x010018 + (0x100 * (_n))) #define E1000_PFVFGOTC(_n) (0x010034 + (0x100 * (_n))) #define E1000_PFVFMPRC(_n) (0x010038 + (0x100 * (_n))) #define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n))) #define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n))) #define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n))) #define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n))) /* LinkSec */ #define E1000_LSECTXUT 0x04300 /* Tx Untagged Pkt Cnt */ #define E1000_LSECTXPKTE 0x04304 /* Encrypted Tx Pkts Cnt */ #define E1000_LSECTXPKTP 0x04308 /* Protected Tx Pkt Cnt */ #define E1000_LSECTXOCTE 0x0430C /* Encrypted Tx Octets Cnt */ #define E1000_LSECTXOCTP 0x04310 /* Protected Tx Octets Cnt */ #define E1000_LSECRXUT 0x04314 /* Untagged non-Strict Rx Pkt Cnt */ #define E1000_LSECRXOCTD 0x0431C /* Rx Octets Decrypted Count */ #define E1000_LSECRXOCTV 0x04320 /* Rx Octets Validated */ #define E1000_LSECRXBAD 0x04324 /* Rx Bad Tag */ #define E1000_LSECRXNOSCI 0x04328 /* Rx Packet No SCI Count */ #define E1000_LSECRXUNSCI 0x0432C /* Rx Packet Unknown SCI Count */ #define E1000_LSECRXUNCH 0x04330 /* Rx Unchecked Packets Count */ #define E1000_LSECRXDELAY 0x04340 /* Rx Delayed Packet Count */ #define E1000_LSECRXLATE 0x04350 /* Rx Late Packets Count */ #define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* Rx Pkt OK Cnt */ #define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* Rx Invalid Cnt */ #define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* Rx Not Valid Cnt */ #define E1000_LSECRXUNSA 0x043C0 /* Rx Unused SA Count */ #define E1000_LSECRXNUSA 0x043D0 /* Rx Not Using SA Count */ #define E1000_LSECTXCAP 0x0B000 /* Tx Capabilities Register - RO */ #define E1000_LSECRXCAP 0x0B300 /* Rx Capabilities Register - RO */ #define E1000_LSECTXCTRL 0x0B004 /* Tx Control - RW */ #define E1000_LSECRXCTRL 0x0B304 /* Rx Control - RW */ #define E1000_LSECTXSCL 0x0B008 /* Tx SCI Low - RW */ #define E1000_LSECTXSCH 0x0B00C /* Tx SCI High - RW */ #define E1000_LSECTXSA 0x0B010 /* Tx SA0 - RW */ #define E1000_LSECTXPN0 0x0B018 /* Tx SA PN 0 - RW */ #define E1000_LSECTXPN1 0x0B01C /* Tx SA PN 1 - RW */ #define E1000_LSECRXSCL 0x0B3D0 /* Rx SCI Low - RW */ #define E1000_LSECRXSCH 0x0B3E0 /* Rx SCI High - RW */ /* LinkSec Tx 128-bit Key 0 - WO */ #define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */ #define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) #define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* Rx SAs - RW */ #define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* Rx SAs - RW */ /* LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit * key - RW. */ #define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) #define E1000_SSVPC 0x041A0 /* Switch Security Violation Pkt Cnt */ #define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ #define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ #define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ /* IPSec Rx IPv4/v6 Address - RW */ #define E1000_IPSRXIPADDR(_n) (0x0B420 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */ #define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) #define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ #define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ /* IPSec Tx 128-bit Key - RW */ #define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) #define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ #define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ #define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ #define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ #define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ #define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */ #define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ #define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */ #define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */ #define E1000_RPTHC 0x04104 /* Rx Packets To Host */ #define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */ #define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */ #define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */ #define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */ #define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ #define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ #define E1000_LENERRS 0x04138 /* Length Errors Count */ #define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ #define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ #define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ #define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ #define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ #define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Pg - RW */ #define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ #define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ #define E1000_RFCTL 0x05008 /* Receive Filter Control*/ #define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ #define E1000_RA 0x05400 /* Receive Address - RW Array */ #define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */ #define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ #define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ #define E1000_CIAA 0x05B88 /* Config Indirect Access Address - RW */ #define E1000_CIAD 0x05B8C /* Config Indirect Access Data - RW */ #define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ #define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ #define E1000_WUC 0x05800 /* Wakeup Control - RW */ #define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ #define E1000_WUS 0x05810 /* Wakeup Status - RO */ #define E1000_MANC 0x05820 /* Management Control - RW */ #define E1000_IPAV 0x05838 /* IP Address Valid - RW */ #define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ #define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ #define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ #define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ #define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */ #define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ #define E1000_HOST_IF 0x08800 /* Host Interface */ #define E1000_HIBBA 0x8F40 /* Host Interface Buffer Base Address */ /* Flexible Host Filter Table */ #define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Ext Flexible Host Filter Table */ #define E1000_FHFT_EXT(_n) (0x09A00 + ((_n) * 0x100)) #define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ #define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ /* Management Decision Filters */ #define E1000_MDEF(_n) (0x05890 + (4 * (_n))) #define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ #define E1000_CCMCTL 0x05B48 /* CCM Control Register */ #define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ #define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ #define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ #define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ #define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ #define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ #define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ #define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ #define E1000_SWSM 0x05B50 /* SW Semaphore */ #define E1000_FWSM 0x05B54 /* FW Semaphore */ /* Driver-only SW semaphore (not used by BOOT agents) */ #define E1000_SWSM2 0x05B58 #define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ #define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ #define E1000_UFUSE 0x05B78 /* UFUSE - RO */ #define E1000_FFLT_DBG 0x05F04 /* Debug Register */ #define E1000_HICR 0x08F00 /* Host Interface Control */ #define E1000_FWSTS 0x08F0C /* FW Status */ /* RSS registers */ #define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ #define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ #define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ #define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/ #define E1000_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */ #define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */ #define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ #define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ #define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ /* VT Registers */ #define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ #define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ #define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ #define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ #define E1000_VFRE 0x00C8C /* VF Receive Enables */ #define E1000_VFTE 0x00C90 /* VF Transmit Enables */ #define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ #define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ #define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */ #define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ #define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ #define E1000_IOVTCL 0x05BBC /* IOV Control Register */ #define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ #define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */ #define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */ #define E1000_MDFB 0x03558 /* Malicious Driver free block */ #define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */ #define E1000_TXSWC 0x05ACC /* Tx Switch Control */ #define E1000_SCCRL 0x05DB0 /* Storm Control Control */ #define E1000_BSCTRH 0x05DB8 /* Broadcast Storm Control Threshold */ #define E1000_MSCTRH 0x05DBC /* Multicast Storm Control Threshold */ /* These act per VF so an array friendly macro is used */ #define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) #define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) #define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) #define E1000_VFVMBMEM(_n) (0x00800 + (_n)) #define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) /* VLAN Virtual Machine Filter - RW */ #define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) #define E1000_VMVIR(_n) (0x03700 + (4 * (_n))) #define E1000_DVMOLR(_n) (0x0C038 + (0x40 * (_n))) /* DMA VM offload */ #define E1000_VTCTRL(_n) (0x10000 + (0x100 * (_n))) /* VT Control */ #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ #define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ #define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ #define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ #define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ #define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */ #define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */ #define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ #define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ #define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ #define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ #define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ #define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ /* Filtering Registers */ #define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ #define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ #define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ #define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ #define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */ #define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ #define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ #define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ #define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ #define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ #define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ #define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ /* Tx Desc plane TC Rate-scheduler config */ #define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */ #define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */ #define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */ #define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */ #define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */ #define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */ #define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */ #define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */ #define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/ #define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */ #define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) #define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ #define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ #define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ #define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ #define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ #define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ #define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ #define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ #define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ #define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ #define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ #define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ #define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ #define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ /* DMA Coalescing registers */ #define E1000_DMACR 0x02508 /* Control Register */ #define E1000_DMCTXTH 0x03550 /* Transmit Threshold */ #define E1000_DMCTLX 0x02514 /* Time to Lx Request */ #define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */ #define E1000_DMCCNT 0x05DD4 /* Current Rx Count */ #define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ #define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ /* PCIe Parity Status Register */ #define E1000_PCIEERRSTS 0x05BA8 #define E1000_PROXYS 0x5F64 /* Proxying Status */ #define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */ /* Thermal sensor configuration and status registers */ #define E1000_THMJT 0x08100 /* Junction Temperature */ #define E1000_THLOWTC 0x08104 /* Low Threshold Control */ #define E1000_THMIDTC 0x08108 /* Mid Threshold Control */ #define E1000_THHIGHTC 0x0810C /* High Threshold Control */ #define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ /* Energy Efficient Ethernet "EEE" registers */ #define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ #define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */ #define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/ #define E1000_EEE_SU 0x0E34 /* EEE Setup */ #define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */ #define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */ /* OS2BMC Registers */ #define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ #define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ #define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ #define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ #endif ================================================ FILE: drivers/net/e1000/base/e1000_vf.c ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "e1000_api.h" STATIC s32 e1000_init_phy_params_vf(struct e1000_hw *hw); STATIC s32 e1000_init_nvm_params_vf(struct e1000_hw *hw); STATIC void e1000_release_vf(struct e1000_hw *hw); STATIC s32 e1000_acquire_vf(struct e1000_hw *hw); STATIC s32 e1000_setup_link_vf(struct e1000_hw *hw); STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw); STATIC s32 e1000_init_mac_params_vf(struct e1000_hw *hw); STATIC s32 e1000_check_for_link_vf(struct e1000_hw *hw); STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed, u16 *duplex); STATIC s32 e1000_init_hw_vf(struct e1000_hw *hw); STATIC s32 e1000_reset_hw_vf(struct e1000_hw *hw); STATIC void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *, u32); STATIC void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32); STATIC s32 e1000_read_mac_addr_vf(struct e1000_hw *); /** * e1000_init_phy_params_vf - Inits PHY params * @hw: pointer to the HW structure * * Doesn't do much - there's no PHY available to the VF. **/ STATIC s32 e1000_init_phy_params_vf(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_phy_params_vf"); hw->phy.type = e1000_phy_vf; hw->phy.ops.acquire = e1000_acquire_vf; hw->phy.ops.release = e1000_release_vf; return E1000_SUCCESS; } /** * e1000_init_nvm_params_vf - Inits NVM params * @hw: pointer to the HW structure * * Doesn't do much - there's no NVM available to the VF. **/ STATIC s32 e1000_init_nvm_params_vf(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_nvm_params_vf"); hw->nvm.type = e1000_nvm_none; hw->nvm.ops.acquire = e1000_acquire_vf; hw->nvm.ops.release = e1000_release_vf; return E1000_SUCCESS; } /** * e1000_init_mac_params_vf - Inits MAC params * @hw: pointer to the HW structure **/ STATIC s32 e1000_init_mac_params_vf(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_params_vf"); /* Set media type */ /* * Virtual functions don't care what they're media type is as they * have no direct access to the PHY, or the media. That is handled * by the physical function driver. */ hw->phy.media_type = e1000_media_type_unknown; /* No ASF features for the VF driver */ mac->asf_firmware_present = false; /* ARC subsystem not supported */ mac->arc_subsystem_valid = false; /* Disable adaptive IFS mode so the generic funcs don't do anything */ mac->adaptive_ifs = false; /* VF's have no MTA Registers - PF feature only */ mac->mta_reg_count = 128; /* VF's have no access to RAR entries */ mac->rar_entry_count = 1; /* Function pointers */ /* link setup */ mac->ops.setup_link = e1000_setup_link_vf; /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_vf; /* reset */ mac->ops.reset_hw = e1000_reset_hw_vf; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_vf; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_vf; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_vf; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf; /* set mac address */ mac->ops.rar_set = e1000_rar_set_vf; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_vf; return E1000_SUCCESS; } /** * e1000_init_function_pointers_vf - Inits function pointers * @hw: pointer to the HW structure **/ void e1000_init_function_pointers_vf(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_vf"); hw->mac.ops.init_params = e1000_init_mac_params_vf; hw->nvm.ops.init_params = e1000_init_nvm_params_vf; hw->phy.ops.init_params = e1000_init_phy_params_vf; hw->mbx.ops.init_params = e1000_init_mbx_params_vf; } /** * e1000_acquire_vf - Acquire rights to access PHY or NVM. * @hw: pointer to the HW structure * * There is no PHY or NVM so we want all attempts to acquire these to fail. * In addition, the MAC registers to access PHY/NVM don't exist so we don't * even want any SW to attempt to use them. **/ STATIC s32 e1000_acquire_vf(struct e1000_hw E1000_UNUSEDARG *hw) { UNREFERENCED_1PARAMETER(hw); return -E1000_ERR_PHY; } /** * e1000_release_vf - Release PHY or NVM * @hw: pointer to the HW structure * * There is no PHY or NVM so we want all attempts to acquire these to fail. * In addition, the MAC registers to access PHY/NVM don't exist so we don't * even want any SW to attempt to use them. **/ STATIC void e1000_release_vf(struct e1000_hw E1000_UNUSEDARG *hw) { UNREFERENCED_1PARAMETER(hw); return; } /** * e1000_setup_link_vf - Sets up link. * @hw: pointer to the HW structure * * Virtual functions cannot change link. **/ STATIC s32 e1000_setup_link_vf(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_setup_link_vf"); UNREFERENCED_1PARAMETER(hw); return E1000_SUCCESS; } /** * e1000_get_bus_info_pcie_vf - Gets the bus info. * @hw: pointer to the HW structure * * Virtual functions are not really on their own bus. **/ STATIC s32 e1000_get_bus_info_pcie_vf(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; DEBUGFUNC("e1000_get_bus_info_pcie_vf"); /* Do not set type PCI-E because we don't want disable master to run */ bus->type = e1000_bus_type_reserved; bus->speed = e1000_bus_speed_2500; return 0; } /** * e1000_get_link_up_info_vf - Gets link info. * @hw: pointer to the HW structure * @speed: pointer to 16 bit value to store link speed. * @duplex: pointer to 16 bit value to store duplex. * * Since we cannot read the PHY and get accurate link info, we must rely upon * the status register's data which is often stale and inaccurate. **/ STATIC s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed, u16 *duplex) { s32 status; DEBUGFUNC("e1000_get_link_up_info_vf"); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; DEBUGOUT("1000 Mbs, "); } else if (status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; DEBUGOUT("100 Mbs, "); } else { *speed = SPEED_10; DEBUGOUT("10 Mbs, "); } if (status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; DEBUGOUT("Half Duplex\n"); } return E1000_SUCCESS; } /** * e1000_reset_hw_vf - Resets the HW * @hw: pointer to the HW structure * * VF's provide a function level reset. This is done using bit 26 of ctrl_reg. * This is all the reset we can perform on a VF. **/ STATIC s32 e1000_reset_hw_vf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; u32 timeout = E1000_VF_INIT_TIMEOUT; s32 ret_val = -E1000_ERR_MAC_INIT; u32 ctrl, msgbuf[3]; u8 *addr = (u8 *)(&msgbuf[1]); DEBUGFUNC("e1000_reset_hw_vf"); DEBUGOUT("Issuing a function level reset to MAC\n"); ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); /* we cannot reset while the RSTI / RSTD bits are asserted */ while (!mbx->ops.check_for_rst(hw, 0) && timeout) { timeout--; usec_delay(5); } if (timeout) { /* mailbox timeout can now become active */ mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT; msgbuf[0] = E1000_VF_RESET; mbx->ops.write_posted(hw, msgbuf, 1, 0); msec_delay(10); /* set our "perm_addr" based on info provided by PF */ ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0); if (!ret_val) { if (msgbuf[0] == (E1000_VF_RESET | E1000_VT_MSGTYPE_ACK)) memcpy(hw->mac.perm_addr, addr, 6); else ret_val = -E1000_ERR_MAC_INIT; } } return ret_val; } /** * e1000_init_hw_vf - Inits the HW * @hw: pointer to the HW structure * * Not much to do here except clear the PF Reset indication if there is one. **/ STATIC s32 e1000_init_hw_vf(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_hw_vf"); /* attempt to set and restore our mac address */ e1000_rar_set_vf(hw, hw->mac.addr, 0); return E1000_SUCCESS; } /** * e1000_rar_set_vf - set device MAC address * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index receive address array register **/ STATIC void e1000_rar_set_vf(struct e1000_hw *hw, u8 *addr, u32 E1000_UNUSEDARG index) { struct e1000_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val; UNREFERENCED_1PARAMETER(index); memset(msgbuf, 0, 12); msgbuf[0] = E1000_VF_SET_MAC_ADDR; memcpy(msg_addr, addr, 6); ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0); msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK))) e1000_read_mac_addr_vf(hw); } /** * e1000_hash_mc_addr_vf - Generate a multicast hash value * @hw: pointer to the HW structure * @mc_addr: pointer to a multicast address * * Generates a multicast address hash value which is used to determine * the multicast filter table array address and new table value. **/ STATIC u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr) { u32 hash_value, hash_mask; u8 bit_shift = 0; DEBUGFUNC("e1000_hash_mc_addr_generic"); /* Register count multiplied by bits per register */ hash_mask = (hw->mac.mta_reg_count * 32) - 1; /* * The bit_shift is the number of left-shifts * where 0xFF would still fall within the hash mask. */ while (hash_mask >> bit_shift != 0xFF) bit_shift++; hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | (((u16) mc_addr[5]) << bit_shift))); return hash_value; } STATIC void e1000_write_msg_read_ack(struct e1000_hw *hw, u32 *msg, u16 size) { struct e1000_mbx_info *mbx = &hw->mbx; u32 retmsg[E1000_VFMAILBOX_SIZE]; s32 retval = mbx->ops.write_posted(hw, msg, size, 0); if (!retval) mbx->ops.read_posted(hw, retmsg, E1000_VFMAILBOX_SIZE, 0); } /** * e1000_update_mc_addr_list_vf - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates the Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. **/ void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { u32 msgbuf[E1000_VFMAILBOX_SIZE]; u16 *hash_list = (u16 *)&msgbuf[1]; u32 hash_value; u32 i; DEBUGFUNC("e1000_update_mc_addr_list_vf"); /* Each entry in the list uses 1 16 bit word. We have 30 * 16 bit words available in our HW msg buffer (minus 1 for the * msg type). That's 30 hash values if we pack 'em right. If * there are more than 30 MC addresses to add then punt the * extras for now and then add code to handle more than 30 later. * It would be unusual for a server to request that many multi-cast * addresses except for in large enterprise network environments. */ DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count); if (mc_addr_count > 30) { msgbuf[0] |= E1000_VF_SET_MULTICAST_OVERFLOW; mc_addr_count = 30; } msgbuf[0] = E1000_VF_SET_MULTICAST; msgbuf[0] |= mc_addr_count << E1000_VT_MSGINFO_SHIFT; for (i = 0; i < mc_addr_count; i++) { hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list); DEBUGOUT1("Hash value = 0x%03X\n", hash_value); hash_list[i] = hash_value & 0x0FFF; mc_addr_list += ETH_ADDR_LEN; } e1000_write_msg_read_ack(hw, msgbuf, E1000_VFMAILBOX_SIZE); } /** * e1000_vfta_set_vf - Set/Unset vlan filter table address * @hw: pointer to the HW structure * @vid: determines the vfta register and bit to set/unset * @set: if true then set bit, else clear bit **/ void e1000_vfta_set_vf(struct e1000_hw *hw, u16 vid, bool set) { u32 msgbuf[2]; msgbuf[0] = E1000_VF_SET_VLAN; msgbuf[1] = vid; /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ if (set) msgbuf[0] |= E1000_VF_SET_VLAN_ADD; e1000_write_msg_read_ack(hw, msgbuf, 2); } /** e1000_rlpml_set_vf - Set the maximum receive packet length * @hw: pointer to the HW structure * @max_size: value to assign to max frame size **/ void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size) { u32 msgbuf[2]; msgbuf[0] = E1000_VF_SET_LPE; msgbuf[1] = max_size; e1000_write_msg_read_ack(hw, msgbuf, 2); } /** * e1000_promisc_set_vf - Set flags for Unicast or Multicast promisc * @hw: pointer to the HW structure * @uni: boolean indicating unicast promisc status * @multi: boolean indicating multicast promisc status **/ s32 e1000_promisc_set_vf(struct e1000_hw *hw, enum e1000_promisc_type type) { struct e1000_mbx_info *mbx = &hw->mbx; u32 msgbuf = E1000_VF_SET_PROMISC; s32 ret_val; switch (type) { case e1000_promisc_multicast: msgbuf |= E1000_VF_SET_PROMISC_MULTICAST; break; case e1000_promisc_enabled: msgbuf |= E1000_VF_SET_PROMISC_MULTICAST; case e1000_promisc_unicast: msgbuf |= E1000_VF_SET_PROMISC_UNICAST; case e1000_promisc_disabled: break; default: return -E1000_ERR_MAC_INIT; } ret_val = mbx->ops.write_posted(hw, &msgbuf, 1, 0); if (!ret_val) ret_val = mbx->ops.read_posted(hw, &msgbuf, 1, 0); if (!ret_val && !(msgbuf & E1000_VT_MSGTYPE_ACK)) ret_val = -E1000_ERR_MAC_INIT; return ret_val; } /** * e1000_read_mac_addr_vf - Read device MAC address * @hw: pointer to the HW structure **/ STATIC s32 e1000_read_mac_addr_vf(struct e1000_hw *hw) { int i; for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; return E1000_SUCCESS; } /** * e1000_check_for_link_vf - Check for link for a virtual interface * @hw: pointer to the HW structure * * Checks to see if the underlying PF is still talking to the VF and * if it is then it reports the link state to the hardware, otherwise * it reports link down and returns an error. **/ STATIC s32 e1000_check_for_link_vf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; u32 in_msg = 0; DEBUGFUNC("e1000_check_for_link_vf"); /* * We only want to run this if there has been a rst asserted. * in this case that could mean a link change, device reset, * or a virtual function reset */ /* If we were hit with a reset or timeout drop the link */ if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout) mac->get_link_status = true; if (!mac->get_link_status) goto out; /* if link status is down no point in checking to see if pf is up */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) goto out; /* if the read failed it could just be a mailbox collision, best wait * until we are called again and don't report an error */ if (mbx->ops.read(hw, &in_msg, 1, 0)) goto out; /* if incoming message isn't clear to send we are waiting on response */ if (!(in_msg & E1000_VT_MSGTYPE_CTS)) { /* message is not CTS and is NACK we have lost CTS status */ if (in_msg & E1000_VT_MSGTYPE_NACK) ret_val = -E1000_ERR_MAC_INIT; goto out; } /* at this point we know the PF is talking to us, check and see if * we are still accepting timeout or if we had a timeout failure. * if we failed then we will need to reinit */ if (!mbx->timeout) { ret_val = -E1000_ERR_MAC_INIT; goto out; } /* if we passed all the tests above then the link is up and we no * longer need to check for link */ mac->get_link_status = false; out: return ret_val; } ================================================ FILE: drivers/net/e1000/base/e1000_vf.h ================================================ /******************************************************************************* Copyright (c) 2001-2014, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _E1000_VF_H_ #define _E1000_VF_H_ #include "e1000_osdep.h" #include "e1000_regs.h" #include "e1000_defines.h" struct e1000_hw; #define E1000_DEV_ID_82576_VF 0x10CA #define E1000_DEV_ID_I350_VF 0x1520 #define E1000_VF_INIT_TIMEOUT 200 /* Num of retries to clear RSTI */ /* Additional Descriptor Control definitions */ #define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ #define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */ /* SRRCTL bit definitions */ #define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \ (0x0C00C + ((_n) * 0x40))) #define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ #define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00 #define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ #define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000 #define E1000_SRRCTL_DROP_EN 0x80000000 #define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F #define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00 /* Interrupt Defines */ #define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ #define E1000_EITR(_n) (0x01680 + ((_n) << 2)) #define E1000_EICS 0x01520 /* Ext. Intr Cause Set -W0 */ #define E1000_EIMS 0x01524 /* Ext. Intr Mask Set/Read -RW */ #define E1000_EIMC 0x01528 /* Ext. Intr Mask Clear -WO */ #define E1000_EIAC 0x0152C /* Ext. Intr Auto Clear -RW */ #define E1000_EIAM 0x01530 /* Ext. Intr Ack Auto Clear Mask -RW */ #define E1000_IVAR0 0x01700 /* Intr Vector Alloc (array) -RW */ #define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes -RW */ #define E1000_IVAR_VALID 0x80 /* Receive Descriptor - Advanced */ union e1000_adv_rx_desc { struct { u64 pkt_addr; /* Packet buffer address */ u64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { u32 data; struct { /* RSS type, Packet type */ u16 pkt_info; /* Split Header, header buffer len */ u16 hdr_info; } hs_rss; } lo_dword; union { u32 rss; /* RSS Hash */ struct { u16 ip_id; /* IP id */ u16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { u32 status_error; /* ext status/error */ u16 length; /* Packet length */ u16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; #define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { u64 buffer_addr; /* Address of descriptor's data buf */ u32 cmd_type_len; u32 olinfo_status; } read; struct { u64 rsvd; /* Reserved */ u32 nxtseq_seed; u32 status; } wb; }; /* Adv Transmit Descriptor Config Masks */ #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ #define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ #define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ #define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ /* Context descriptors */ struct e1000_adv_tx_context_desc { u32 vlan_macip_lens; u32 seqnum_seed; u32 type_tucmd_mlhl; u32 mss_l4len_idx; }; #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ #define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ enum e1000_mac_type { e1000_undefined = 0, e1000_vfadapt, e1000_vfadapt_i350, e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ }; struct e1000_vf_stats { u64 base_gprc; u64 base_gptc; u64 base_gorc; u64 base_gotc; u64 base_mprc; u64 base_gotlbc; u64 base_gptlbc; u64 base_gorlbc; u64 base_gprlbc; u32 last_gprc; u32 last_gptc; u32 last_gorc; u32 last_gotc; u32 last_mprc; u32 last_gotlbc; u32 last_gptlbc; u32 last_gorlbc; u32 last_gprlbc; u64 gprc; u64 gptc; u64 gorc; u64 gotc; u64 mprc; u64 gotlbc; u64 gptlbc; u64 gorlbc; u64 gprlbc; }; #include "e1000_mbx.h" struct e1000_mac_operations { /* Function pointers for the MAC. */ s32 (*init_params)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); s32 (*get_bus_info)(struct e1000_hw *); s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); void (*rar_set)(struct e1000_hw *, u8*, u32); s32 (*read_mac_addr)(struct e1000_hw *); }; struct e1000_mac_info { struct e1000_mac_operations ops; u8 addr[6]; u8 perm_addr[6]; enum e1000_mac_type type; u16 mta_reg_count; u16 rar_entry_count; bool get_link_status; }; struct e1000_mbx_operations { s32 (*init_params)(struct e1000_hw *hw); s32 (*read)(struct e1000_hw *, u32 *, u16, u16); s32 (*write)(struct e1000_hw *, u32 *, u16, u16); s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*check_for_msg)(struct e1000_hw *, u16); s32 (*check_for_ack)(struct e1000_hw *, u16); s32 (*check_for_rst)(struct e1000_hw *, u16); }; struct e1000_mbx_stats { u32 msgs_tx; u32 msgs_rx; u32 acks; u32 reqs; u32 rsts; }; struct e1000_mbx_info { struct e1000_mbx_operations ops; struct e1000_mbx_stats stats; u32 timeout; u32 usec_delay; u16 size; }; struct e1000_dev_spec_vf { u32 vf_number; u32 v2p_mailbox; }; struct e1000_hw { void *back; u8 *hw_addr; u8 *flash_address; unsigned long io_base; struct e1000_mac_info mac; struct e1000_mbx_info mbx; union { struct e1000_dev_spec_vf vf; } dev_spec; u16 device_id; u16 subsystem_vendor_id; u16 subsystem_device_id; u16 vendor_id; u8 revision_id; }; enum e1000_promisc_type { e1000_promisc_disabled = 0, /* all promisc modes disabled */ e1000_promisc_unicast = 1, /* unicast promiscuous enabled */ e1000_promisc_multicast = 2, /* multicast promiscuous enabled */ e1000_promisc_enabled = 3, /* both uni and multicast promisc */ e1000_num_promisc_types }; /* These functions must be implemented by drivers */ s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); void e1000_vfta_set_vf(struct e1000_hw *, u16, bool); void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type); #endif /* _E1000_VF_H_ */ ================================================ FILE: drivers/net/e1000/e1000_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _E1000_ETHDEV_H_ #define _E1000_ETHDEV_H_ /* need update link, bit flag */ #define E1000_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) #define E1000_FLAG_MAILBOX (uint32_t)(1 << 1) /* * Defines that were not part of e1000_hw.h as they are not used by the FreeBSD * driver. */ #define E1000_ADVTXD_POPTS_TXSM 0x00000200 /* L4 Checksum offload request */ #define E1000_ADVTXD_POPTS_IXSM 0x00000100 /* IP Checksum offload request */ #define E1000_ADVTXD_TUCMD_L4T_RSV 0x00001800 /* L4 Packet TYPE of Reserved */ #define E1000_RXD_STAT_TMST 0x10000 /* Timestamped Packet indication */ #define E1000_RXD_ERR_CKSUM_BIT 29 #define E1000_RXD_ERR_CKSUM_MSK 3 #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Bit shift for l2_len */ #define E1000_CTRL_EXT_EXTEND_VLAN (1<<26) /* EXTENDED VLAN */ #define IGB_VFTA_SIZE 128 #define IGB_MAX_RX_QUEUE_NUM 8 #define IGB_MAX_RX_QUEUE_NUM_82576 16 #define E1000_SYN_FILTER_ENABLE 0x00000001 /* syn filter enable field */ #define E1000_SYN_FILTER_QUEUE 0x0000000E /* syn filter queue field */ #define E1000_SYN_FILTER_QUEUE_SHIFT 1 /* syn filter queue field */ #define E1000_RFCTL_SYNQFP 0x00080000 /* SYNQFP in RFCTL register */ #define E1000_ETQF_ETHERTYPE 0x0000FFFF #define E1000_ETQF_QUEUE 0x00070000 #define E1000_ETQF_QUEUE_SHIFT 16 #define E1000_MAX_ETQF_FILTERS 8 #define E1000_IMIR_DSTPORT 0x0000FFFF #define E1000_IMIR_PRIORITY 0xE0000000 #define E1000_MAX_TTQF_FILTERS 8 #define E1000_2TUPLE_MAX_PRI 7 #define E1000_MAX_FLEX_FILTERS 8 #define E1000_MAX_FHFT 4 #define E1000_MAX_FHFT_EXT 4 #define E1000_FHFT_SIZE_IN_DWD 64 #define E1000_MAX_FLEX_FILTER_PRI 7 #define E1000_MAX_FLEX_FILTER_LEN 128 #define E1000_MAX_FLEX_FILTER_DWDS \ (E1000_MAX_FLEX_FILTER_LEN / sizeof(uint32_t)) #define E1000_FLEX_FILTERS_MASK_SIZE \ (E1000_MAX_FLEX_FILTER_DWDS / 4) #define E1000_FHFT_QUEUEING_LEN 0x0000007F #define E1000_FHFT_QUEUEING_QUEUE 0x00000700 #define E1000_FHFT_QUEUEING_PRIO 0x00070000 #define E1000_FHFT_QUEUEING_OFFSET 0xFC #define E1000_FHFT_QUEUEING_QUEUE_SHIFT 8 #define E1000_FHFT_QUEUEING_PRIO_SHIFT 16 #define E1000_WUFC_FLEX_HQ 0x00004000 #define E1000_SPQF_SRCPORT 0x0000FFFF #define E1000_MAX_FTQF_FILTERS 8 #define E1000_FTQF_PROTOCOL_MASK 0x000000FF #define E1000_FTQF_5TUPLE_MASK_SHIFT 28 #define E1000_FTQF_QUEUE_MASK 0x03ff0000 #define E1000_FTQF_QUEUE_SHIFT 16 #define E1000_FTQF_QUEUE_ENABLE 0x00000100 #define IGB_RSS_OFFLOAD_ALL ( \ ETH_RSS_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_NONFRAG_IPV4_UDP | \ ETH_RSS_IPV6 | \ ETH_RSS_NONFRAG_IPV6_TCP | \ ETH_RSS_NONFRAG_IPV6_UDP | \ ETH_RSS_IPV6_EX | \ ETH_RSS_IPV6_TCP_EX | \ ETH_RSS_IPV6_UDP_EX) /* structure for interrupt relative data */ struct e1000_interrupt { uint32_t flags; uint32_t mask; }; /* local vfta copy */ struct e1000_vfta { uint32_t vfta[IGB_VFTA_SIZE]; }; /* * VF data which used by PF host only */ #define E1000_MAX_VF_MC_ENTRIES 30 struct e1000_vf_info { uint8_t vf_mac_addresses[ETHER_ADDR_LEN]; uint16_t vf_mc_hashes[E1000_MAX_VF_MC_ENTRIES]; uint16_t num_vf_mc_hashes; uint16_t default_vf_vlan_id; uint16_t vlans_enabled; uint16_t pf_qos; uint16_t vlan_count; uint16_t tx_rate; }; TAILQ_HEAD(e1000_flex_filter_list, e1000_flex_filter); struct e1000_flex_filter_info { uint16_t len; uint32_t dwords[E1000_MAX_FLEX_FILTER_DWDS]; /* flex bytes in dword. */ /* if mask bit is 1b, do not compare corresponding byte in dwords. */ uint8_t mask[E1000_FLEX_FILTERS_MASK_SIZE]; uint8_t priority; }; /* Flex filter structure */ struct e1000_flex_filter { TAILQ_ENTRY(e1000_flex_filter) entries; uint16_t index; /* index of flex filter */ struct e1000_flex_filter_info filter_info; uint16_t queue; /* rx queue assigned to */ }; TAILQ_HEAD(e1000_5tuple_filter_list, e1000_5tuple_filter); TAILQ_HEAD(e1000_2tuple_filter_list, e1000_2tuple_filter); struct e1000_5tuple_filter_info { uint32_t dst_ip; uint32_t src_ip; uint16_t dst_port; uint16_t src_port; uint8_t proto; /* l4 protocol. */ /* the packet matched above 5tuple and contain any set bit will hit this filter. */ uint8_t tcp_flags; uint8_t priority; /* seven levels (001b-111b), 111b is highest, used when more than one filter matches. */ uint8_t dst_ip_mask:1, /* if mask is 1b, do not compare dst ip. */ src_ip_mask:1, /* if mask is 1b, do not compare src ip. */ dst_port_mask:1, /* if mask is 1b, do not compare dst port. */ src_port_mask:1, /* if mask is 1b, do not compare src port. */ proto_mask:1; /* if mask is 1b, do not compare protocol. */ }; struct e1000_2tuple_filter_info { uint16_t dst_port; uint8_t proto; /* l4 protocol. */ /* the packet matched above 2tuple and contain any set bit will hit this filter. */ uint8_t tcp_flags; uint8_t priority; /* seven levels (001b-111b), 111b is highest, used when more than one filter matches. */ uint8_t dst_ip_mask:1, /* if mask is 1b, do not compare dst ip. */ src_ip_mask:1, /* if mask is 1b, do not compare src ip. */ dst_port_mask:1, /* if mask is 1b, do not compare dst port. */ src_port_mask:1, /* if mask is 1b, do not compare src port. */ proto_mask:1; /* if mask is 1b, do not compare protocol. */ }; /* 5tuple filter structure */ struct e1000_5tuple_filter { TAILQ_ENTRY(e1000_5tuple_filter) entries; uint16_t index; /* the index of 5tuple filter */ struct e1000_5tuple_filter_info filter_info; uint16_t queue; /* rx queue assigned to */ }; /* 2tuple filter structure */ struct e1000_2tuple_filter { TAILQ_ENTRY(e1000_2tuple_filter) entries; uint16_t index; /* the index of 2tuple filter */ struct e1000_2tuple_filter_info filter_info; uint16_t queue; /* rx queue assigned to */ }; /* * Structure to store filters' info. */ struct e1000_filter_info { uint8_t ethertype_mask; /* Bit mask for every used ethertype filter */ /* store used ethertype filters*/ uint16_t ethertype_filters[E1000_MAX_ETQF_FILTERS]; uint8_t flex_mask; /* Bit mask for every used flex filter */ struct e1000_flex_filter_list flex_list; /* Bit mask for every used 5tuple filter */ uint8_t fivetuple_mask; struct e1000_5tuple_filter_list fivetuple_list; /* Bit mask for every used 2tuple filter */ uint8_t twotuple_mask; struct e1000_2tuple_filter_list twotuple_list; }; /* * Structure to store private data for each driver instance (for each port). */ struct e1000_adapter { struct e1000_hw hw; struct e1000_hw_stats stats; struct e1000_interrupt intr; struct e1000_vfta shadow_vfta; struct e1000_vf_info *vfdata; struct e1000_filter_info filter; bool stopped; }; #define E1000_DEV_PRIVATE(adapter) \ ((struct e1000_adapter *)adapter) #define E1000_DEV_PRIVATE_TO_HW(adapter) \ (&((struct e1000_adapter *)adapter)->hw) #define E1000_DEV_PRIVATE_TO_STATS(adapter) \ (&((struct e1000_adapter *)adapter)->stats) #define E1000_DEV_PRIVATE_TO_INTR(adapter) \ (&((struct e1000_adapter *)adapter)->intr) #define E1000_DEV_PRIVATE_TO_VFTA(adapter) \ (&((struct e1000_adapter *)adapter)->shadow_vfta) #define E1000_DEV_PRIVATE_TO_P_VFDATA(adapter) \ (&((struct e1000_adapter *)adapter)->vfdata) #define E1000_DEV_PRIVATE_TO_FILTER_INFO(adapter) \ (&((struct e1000_adapter *)adapter)->filter) /* * RX/TX IGB function prototypes */ void eth_igb_tx_queue_release(void *txq); void eth_igb_rx_queue_release(void *rxq); void igb_dev_clear_queues(struct rte_eth_dev *dev); void igb_dev_free_queues(struct rte_eth_dev *dev); int eth_igb_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); uint32_t eth_igb_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id); int eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset); int eth_igb_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); int eth_igb_rx_init(struct rte_eth_dev *dev); void eth_igb_tx_init(struct rte_eth_dev *dev); uint16_t eth_igb_xmit_pkts(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); uint16_t eth_igb_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t eth_igb_recv_scattered_pkts(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); int eth_igb_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); int eth_igb_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); int eth_igbvf_rx_init(struct rte_eth_dev *dev); void eth_igbvf_tx_init(struct rte_eth_dev *dev); /* * misc function prototypes */ void igb_pf_host_init(struct rte_eth_dev *eth_dev); void igb_pf_mbx_process(struct rte_eth_dev *eth_dev); int igb_pf_host_configure(struct rte_eth_dev *eth_dev); /* * RX/TX EM function prototypes */ void eth_em_tx_queue_release(void *txq); void eth_em_rx_queue_release(void *rxq); void em_dev_clear_queues(struct rte_eth_dev *dev); void em_dev_free_queues(struct rte_eth_dev *dev); int eth_em_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); uint32_t eth_em_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id); int eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset); int eth_em_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); int eth_em_rx_init(struct rte_eth_dev *dev); void eth_em_tx_init(struct rte_eth_dev *dev); uint16_t eth_em_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); uint16_t eth_em_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t eth_em_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); void igb_pf_host_uninit(struct rte_eth_dev *dev); #endif /* _E1000_ETHDEV_H_ */ ================================================ FILE: drivers/net/e1000/e1000_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _E1000_LOGS_H_ #define _E1000_LOGS_H_ #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) #ifdef RTE_LIBRTE_E1000_DEBUG_INIT #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_FUNC_TRACE() do { } while (0) #endif #ifdef RTE_LIBRTE_E1000_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_E1000_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_E1000_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_E1000_DEBUG_DRIVER #define PMD_DRV_LOG_RAW(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) #else #define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) #endif #define PMD_DRV_LOG(level, fmt, args...) \ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) #endif /* _E1000_LOGS_H_ */ ================================================ FILE: drivers/net/e1000/em_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e1000_logs.h" #include "base/e1000_api.h" #include "e1000_ethdev.h" #define EM_EIAC 0x000DC #define PMD_ROUNDUP(x,y) (((x) + (y) - 1)/(y) * (y)) static int eth_em_configure(struct rte_eth_dev *dev); static int eth_em_start(struct rte_eth_dev *dev); static void eth_em_stop(struct rte_eth_dev *dev); static void eth_em_close(struct rte_eth_dev *dev); static void eth_em_promiscuous_enable(struct rte_eth_dev *dev); static void eth_em_promiscuous_disable(struct rte_eth_dev *dev); static void eth_em_allmulticast_enable(struct rte_eth_dev *dev); static void eth_em_allmulticast_disable(struct rte_eth_dev *dev); static int eth_em_link_update(struct rte_eth_dev *dev, int wait_to_complete); static void eth_em_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static void eth_em_stats_reset(struct rte_eth_dev *dev); static void eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int eth_em_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int eth_em_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int eth_em_interrupt_setup(struct rte_eth_dev *dev); static int eth_em_interrupt_get_status(struct rte_eth_dev *dev); static int eth_em_interrupt_action(struct rte_eth_dev *dev); static void eth_em_interrupt_handler(struct rte_intr_handle *handle, void *param); static int em_hw_init(struct e1000_hw *hw); static int em_hardware_init(struct e1000_hw *hw); static void em_hw_control_acquire(struct e1000_hw *hw); static void em_hw_control_release(struct e1000_hw *hw); static void em_init_manageability(struct e1000_hw *hw); static void em_release_manageability(struct e1000_hw *hw); static int eth_em_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int eth_em_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev); static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev); static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev); static void em_vlan_hw_strip_disable(struct rte_eth_dev *dev); /* static void eth_em_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); */ static int eth_em_led_on(struct rte_eth_dev *dev); static int eth_em_led_off(struct rte_eth_dev *dev); static void em_intr_disable(struct e1000_hw *hw); static int em_get_rx_buffer_size(struct e1000_hw *hw); static void eth_em_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void eth_em_rar_clear(struct rte_eth_dev *dev, uint32_t index); static int eth_em_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); #define EM_FC_PAUSE_TIME 0x0680 #define EM_LINK_UPDATE_CHECK_TIMEOUT 90 /* 9s */ #define EM_LINK_UPDATE_CHECK_INTERVAL 100 /* ms */ static enum e1000_fc_mode em_fc_setting = e1000_fc_full; /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_em_map[] = { #define RTE_PCI_DEV_ID_DECL_EM(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" {0}, }; static const struct eth_dev_ops eth_em_ops = { .dev_configure = eth_em_configure, .dev_start = eth_em_start, .dev_stop = eth_em_stop, .dev_close = eth_em_close, .promiscuous_enable = eth_em_promiscuous_enable, .promiscuous_disable = eth_em_promiscuous_disable, .allmulticast_enable = eth_em_allmulticast_enable, .allmulticast_disable = eth_em_allmulticast_disable, .link_update = eth_em_link_update, .stats_get = eth_em_stats_get, .stats_reset = eth_em_stats_reset, .dev_infos_get = eth_em_infos_get, .mtu_set = eth_em_mtu_set, .vlan_filter_set = eth_em_vlan_filter_set, .vlan_offload_set = eth_em_vlan_offload_set, .rx_queue_setup = eth_em_rx_queue_setup, .rx_queue_release = eth_em_rx_queue_release, .rx_queue_count = eth_em_rx_queue_count, .rx_descriptor_done = eth_em_rx_descriptor_done, .tx_queue_setup = eth_em_tx_queue_setup, .tx_queue_release = eth_em_tx_queue_release, .dev_led_on = eth_em_led_on, .dev_led_off = eth_em_led_off, .flow_ctrl_get = eth_em_flow_ctrl_get, .flow_ctrl_set = eth_em_flow_ctrl_set, .mac_addr_add = eth_em_rar_set, .mac_addr_remove = eth_em_rar_clear, .set_mc_addr_list = eth_em_set_mc_addr_list, }; /** * Atomically reads the link status information from global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_em_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /** * Atomically writes the link status information into global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_em_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static int eth_em_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); pci_dev = eth_dev->pci_dev; eth_dev->dev_ops = ð_em_ops; eth_dev->rx_pkt_burst = (eth_rx_burst_t)ð_em_recv_pkts; eth_dev->tx_pkt_burst = (eth_tx_burst_t)ð_em_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX function */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (eth_dev->data->scattered_rx) eth_dev->rx_pkt_burst = (eth_rx_burst_t)ð_em_recv_scattered_pkts; return 0; } hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; hw->device_id = pci_dev->id.device_id; adapter->stopped = 0; /* For ICH8 support we'll need to map the flash memory BAR */ if (e1000_setup_init_funcs(hw, TRUE) != E1000_SUCCESS || em_hw_init(hw) != 0) { PMD_INIT_LOG(ERR, "port_id %d vendorID=0x%x deviceID=0x%x: " "failed to init HW", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); return -(ENODEV); } /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("e1000", ETHER_ADDR_LEN * hw->mac.rar_entry_count, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to " "store MAC addresses", ETHER_ADDR_LEN * hw->mac.rar_entry_count); return -(ENOMEM); } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *) hw->mac.addr, eth_dev->data->mac_addrs); /* initialize the vfta */ memset(shadow_vfta, 0, sizeof(*shadow_vfta)); PMD_INIT_LOG(DEBUG, "port_id %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); rte_intr_callback_register(&(pci_dev->intr_handle), eth_em_interrupt_handler, (void *)eth_dev); return (0); } static int eth_em_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; pci_dev = eth_dev->pci_dev; if (adapter->stopped == 0) eth_em_close(eth_dev); eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; /* disable uio intr before callback unregister */ rte_intr_disable(&(pci_dev->intr_handle)); rte_intr_callback_unregister(&(pci_dev->intr_handle), eth_em_interrupt_handler, (void *)eth_dev); return 0; } static struct eth_driver rte_em_pmd = { .pci_drv = { .name = "rte_em_pmd", .id_table = pci_id_em_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_em_dev_init, .eth_dev_uninit = eth_em_dev_uninit, .dev_private_size = sizeof(struct e1000_adapter), }; static int rte_em_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { rte_eth_driver_register(&rte_em_pmd); return 0; } static int em_hw_init(struct e1000_hw *hw) { int diag; diag = hw->mac.ops.init_params(hw); if (diag != 0) { PMD_INIT_LOG(ERR, "MAC Initialization Error"); return diag; } diag = hw->nvm.ops.init_params(hw); if (diag != 0) { PMD_INIT_LOG(ERR, "NVM Initialization Error"); return diag; } diag = hw->phy.ops.init_params(hw); if (diag != 0) { PMD_INIT_LOG(ERR, "PHY Initialization Error"); return diag; } (void) e1000_get_bus_info(hw); hw->mac.autoneg = 1; hw->phy.autoneg_wait_to_complete = 0; hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; e1000_init_script_state_82541(hw, TRUE); e1000_set_tbi_compatibility_82543(hw, TRUE); /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { hw->phy.mdix = 0; /* AUTO_ALL_MODES */ hw->phy.disable_polarity_correction = 0; hw->phy.ms_type = e1000_ms_hw_default; } /* * Start from a known state, this is important in reading the nvm * and mac from that. */ e1000_reset_hw(hw); /* Make sure we have a good EEPROM before we read from it */ if (e1000_validate_nvm_checksum(hw) < 0) { /* * Some PCI-E parts fail the first check due to * the link being in sleep state, call it again, * if it fails a second time its a real issue. */ diag = e1000_validate_nvm_checksum(hw); if (diag < 0) { PMD_INIT_LOG(ERR, "EEPROM checksum invalid"); goto error; } } /* Read the permanent MAC address out of the EEPROM */ diag = e1000_read_mac_addr(hw); if (diag != 0) { PMD_INIT_LOG(ERR, "EEPROM error while reading MAC address"); goto error; } /* Now initialize the hardware */ diag = em_hardware_init(hw); if (diag != 0) { PMD_INIT_LOG(ERR, "Hardware initialization failed"); goto error; } hw->mac.get_link_status = 1; /* Indicate SOL/IDER usage */ diag = e1000_check_reset_block(hw); if (diag < 0) { PMD_INIT_LOG(ERR, "PHY reset is blocked due to " "SOL/IDER session"); } return (0); error: em_hw_control_release(hw); return (diag); } static int eth_em_configure(struct rte_eth_dev *dev) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); intr->flags |= E1000_FLAG_NEED_LINK_UPDATE; PMD_INIT_FUNC_TRACE(); return (0); } static void em_set_pba(struct e1000_hw *hw) { uint32_t pba; /* * Packet Buffer Allocation (PBA) * Writing PBA sets the receive portion of the buffer * the remainder is used for the transmit buffer. * Devices before the 82547 had a Packet Buffer of 64K. * After the 82547 the buffer was reduced to 40K. */ switch (hw->mac.type) { case e1000_82547: case e1000_82547_rev_2: /* 82547: Total Packet Buffer is 40K */ pba = E1000_PBA_22K; /* 22K for Rx, 18K for Tx */ break; case e1000_82571: case e1000_82572: case e1000_80003es2lan: pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ break; case e1000_82573: /* 82573: Total Packet Buffer is 32K */ pba = E1000_PBA_12K; /* 12K for Rx, 20K for Tx */ break; case e1000_82574: case e1000_82583: pba = E1000_PBA_20K; /* 20K for Rx, 20K for Tx */ break; case e1000_ich8lan: pba = E1000_PBA_8K; break; case e1000_ich9lan: case e1000_ich10lan: pba = E1000_PBA_10K; break; case e1000_pchlan: case e1000_pch2lan: pba = E1000_PBA_26K; break; default: pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ } E1000_WRITE_REG(hw, E1000_PBA, pba); } static int eth_em_start(struct rte_eth_dev *dev) { struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret, mask; PMD_INIT_FUNC_TRACE(); eth_em_stop(dev); e1000_power_up_phy(hw); /* Set default PBA value */ em_set_pba(hw); /* Put the address into the Receive Address Array */ e1000_rar_set(hw, hw->mac.addr, 0); /* * With the 82571 adapter, RAR[0] may be overwritten * when the other port is reset, we make a duplicate * in RAR[14] for that eventuality, this assures * the interface continues to function. */ if (hw->mac.type == e1000_82571) { e1000_set_laa_state_82571(hw, TRUE); e1000_rar_set(hw, hw->mac.addr, E1000_RAR_ENTRIES - 1); } /* Initialize the hardware */ if (em_hardware_init(hw)) { PMD_INIT_LOG(ERR, "Unable to initialize the hardware"); return (-EIO); } E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN); /* Configure for OS presence */ em_init_manageability(hw); eth_em_tx_init(dev); ret = eth_em_rx_init(dev); if (ret) { PMD_INIT_LOG(ERR, "Unable to initialize RX hardware"); em_dev_clear_queues(dev); return ret; } e1000_clear_hw_cntrs_base_generic(hw); mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \ ETH_VLAN_EXTEND_MASK; eth_em_vlan_offload_set(dev, mask); /* Set Interrupt Throttling Rate to maximum allowed value. */ E1000_WRITE_REG(hw, E1000_ITR, UINT16_MAX); /* Setup link speed and duplex */ switch (dev->data->dev_conf.link_speed) { case ETH_LINK_SPEED_AUTONEG: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX; else goto error_invalid_config; break; case ETH_LINK_SPEED_10: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_10_SPEED; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_10_HALF; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_10_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_100: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_100_SPEED; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_100_HALF; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_100_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_1000: if ((dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) || (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX)) hw->phy.autoneg_advertised = ADVERTISE_1000_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_10000: default: goto error_invalid_config; } e1000_setup_link(hw); /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc != 0) { ret = eth_em_interrupt_setup(dev); if (ret) { PMD_INIT_LOG(ERR, "Unable to setup interrupts"); em_dev_clear_queues(dev); return ret; } } adapter->stopped = 0; PMD_INIT_LOG(DEBUG, "<<"); return (0); error_invalid_config: PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u", dev->data->dev_conf.link_speed, dev->data->dev_conf.link_duplex, dev->data->port_id); em_dev_clear_queues(dev); return (-EINVAL); } /********************************************************************* * * This routine disables all traffic on the adapter by issuing a * global reset on the MAC. * **********************************************************************/ static void eth_em_stop(struct rte_eth_dev *dev) { struct rte_eth_link link; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); em_intr_disable(hw); e1000_reset_hw(hw); if (hw->mac.type >= e1000_82544) E1000_WRITE_REG(hw, E1000_WUC, 0); /* Power down the phy. Needed to make the link go down */ e1000_power_down_phy(hw); em_dev_clear_queues(dev); /* clear the recorded link status */ memset(&link, 0, sizeof(link)); rte_em_dev_atomic_write_link_status(dev, &link); } static void eth_em_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); eth_em_stop(dev); adapter->stopped = 1; em_dev_free_queues(dev); e1000_phy_hw_reset(hw); em_release_manageability(hw); em_hw_control_release(hw); } static int em_get_rx_buffer_size(struct e1000_hw *hw) { uint32_t rx_buf_size; rx_buf_size = ((E1000_READ_REG(hw, E1000_PBA) & UINT16_MAX) << 10); return rx_buf_size; } /********************************************************************* * * Initialize the hardware * **********************************************************************/ static int em_hardware_init(struct e1000_hw *hw) { uint32_t rx_buf_size; int diag; /* Issue a global reset */ e1000_reset_hw(hw); /* Let the firmware know the OS is in control */ em_hw_control_acquire(hw); /* * These parameters control the automatic generation (Tx) and * response (Rx) to Ethernet PAUSE frames. * - High water mark should allow for at least two standard size (1518) * frames to be received after sending an XOFF. * - Low water mark works best when it is very near the high water mark. * This allows the receiver to restart by sending XON when it has * drained a bit. Here we use an arbitrary value of 1500 which will * restart after one full frame is pulled from the buffer. There * could be several smaller frames in the buffer and if so they will * not trigger the XON until their total number reduces the buffer * by 1500. * - The pause time is fairly large at 1000 x 512ns = 512 usec. */ rx_buf_size = em_get_rx_buffer_size(hw); hw->fc.high_water = rx_buf_size - PMD_ROUNDUP(ETHER_MAX_LEN * 2, 1024); hw->fc.low_water = hw->fc.high_water - 1500; if (hw->mac.type == e1000_80003es2lan) hw->fc.pause_time = UINT16_MAX; else hw->fc.pause_time = EM_FC_PAUSE_TIME; hw->fc.send_xon = 1; /* Set Flow control, use the tunable location if sane */ if (em_fc_setting <= e1000_fc_full) hw->fc.requested_mode = em_fc_setting; else hw->fc.requested_mode = e1000_fc_none; /* Workaround: no TX flow ctrl for PCH */ if (hw->mac.type == e1000_pchlan) hw->fc.requested_mode = e1000_fc_rx_pause; /* Override - settings for PCH2LAN, ya its magic :) */ if (hw->mac.type == e1000_pch2lan) { hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; hw->fc.pause_time = 0x0650; hw->fc.refresh_time = 0x0400; } diag = e1000_init_hw(hw); if (diag < 0) return (diag); e1000_check_for_link(hw); return (0); } /* This function is based on em_update_stats_counters() in e1000/if_em.c */ static void eth_em_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_hw_stats *stats = E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); int pause_frames; if(hw->phy.media_type == e1000_media_type_copper || (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { stats->symerrs += E1000_READ_REG(hw,E1000_SYMERRS); stats->sec += E1000_READ_REG(hw, E1000_SEC); } stats->crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); stats->mpc += E1000_READ_REG(hw, E1000_MPC); stats->scc += E1000_READ_REG(hw, E1000_SCC); stats->ecol += E1000_READ_REG(hw, E1000_ECOL); stats->mcc += E1000_READ_REG(hw, E1000_MCC); stats->latecol += E1000_READ_REG(hw, E1000_LATECOL); stats->colc += E1000_READ_REG(hw, E1000_COLC); stats->dc += E1000_READ_REG(hw, E1000_DC); stats->rlec += E1000_READ_REG(hw, E1000_RLEC); stats->xonrxc += E1000_READ_REG(hw, E1000_XONRXC); stats->xontxc += E1000_READ_REG(hw, E1000_XONTXC); /* * For watchdog management we need to know if we have been * paused during the last interval, so capture that here. */ pause_frames = E1000_READ_REG(hw, E1000_XOFFRXC); stats->xoffrxc += pause_frames; stats->xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC); stats->fcruc += E1000_READ_REG(hw, E1000_FCRUC); stats->prc64 += E1000_READ_REG(hw, E1000_PRC64); stats->prc127 += E1000_READ_REG(hw, E1000_PRC127); stats->prc255 += E1000_READ_REG(hw, E1000_PRC255); stats->prc511 += E1000_READ_REG(hw, E1000_PRC511); stats->prc1023 += E1000_READ_REG(hw, E1000_PRC1023); stats->prc1522 += E1000_READ_REG(hw, E1000_PRC1522); stats->gprc += E1000_READ_REG(hw, E1000_GPRC); stats->bprc += E1000_READ_REG(hw, E1000_BPRC); stats->mprc += E1000_READ_REG(hw, E1000_MPRC); stats->gptc += E1000_READ_REG(hw, E1000_GPTC); /* * For the 64-bit byte counters the low dword must be read first. * Both registers clear on the read of the high dword. */ stats->gorc += E1000_READ_REG(hw, E1000_GORCL); stats->gorc += ((uint64_t)E1000_READ_REG(hw, E1000_GORCH) << 32); stats->gotc += E1000_READ_REG(hw, E1000_GOTCL); stats->gotc += ((uint64_t)E1000_READ_REG(hw, E1000_GOTCH) << 32); stats->rnbc += E1000_READ_REG(hw, E1000_RNBC); stats->ruc += E1000_READ_REG(hw, E1000_RUC); stats->rfc += E1000_READ_REG(hw, E1000_RFC); stats->roc += E1000_READ_REG(hw, E1000_ROC); stats->rjc += E1000_READ_REG(hw, E1000_RJC); stats->tor += E1000_READ_REG(hw, E1000_TORH); stats->tot += E1000_READ_REG(hw, E1000_TOTH); stats->tpr += E1000_READ_REG(hw, E1000_TPR); stats->tpt += E1000_READ_REG(hw, E1000_TPT); stats->ptc64 += E1000_READ_REG(hw, E1000_PTC64); stats->ptc127 += E1000_READ_REG(hw, E1000_PTC127); stats->ptc255 += E1000_READ_REG(hw, E1000_PTC255); stats->ptc511 += E1000_READ_REG(hw, E1000_PTC511); stats->ptc1023 += E1000_READ_REG(hw, E1000_PTC1023); stats->ptc1522 += E1000_READ_REG(hw, E1000_PTC1522); stats->mptc += E1000_READ_REG(hw, E1000_MPTC); stats->bptc += E1000_READ_REG(hw, E1000_BPTC); /* Interrupt Counts */ if (hw->mac.type >= e1000_82571) { stats->iac += E1000_READ_REG(hw, E1000_IAC); stats->icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC); stats->icrxatc += E1000_READ_REG(hw, E1000_ICRXATC); stats->ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC); stats->ictxatc += E1000_READ_REG(hw, E1000_ICTXATC); stats->ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC); stats->ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC); stats->icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC); stats->icrxoc += E1000_READ_REG(hw, E1000_ICRXOC); } if (hw->mac.type >= e1000_82543) { stats->algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC); stats->rxerrc += E1000_READ_REG(hw, E1000_RXERRC); stats->tncrs += E1000_READ_REG(hw, E1000_TNCRS); stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR); stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC); stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC); } if (rte_stats == NULL) return; /* Rx Errors */ rte_stats->ibadcrc = stats->crcerrs; rte_stats->ibadlen = stats->rlec + stats->ruc + stats->roc; rte_stats->imissed = stats->mpc; rte_stats->ierrors = rte_stats->ibadcrc + rte_stats->ibadlen + rte_stats->imissed + stats->rxerrc + stats->algnerrc + stats->cexterr; /* Tx Errors */ rte_stats->oerrors = stats->ecol + stats->latecol; rte_stats->ipackets = stats->gprc; rte_stats->opackets = stats->gptc; rte_stats->ibytes = stats->gorc; rte_stats->obytes = stats->gotc; /* XON/XOFF pause frames stats registers */ rte_stats->tx_pause_xon = stats->xontxc; rte_stats->rx_pause_xon = stats->xonrxc; rte_stats->tx_pause_xoff = stats->xofftxc; rte_stats->rx_pause_xoff = stats->xoffrxc; } static void eth_em_stats_reset(struct rte_eth_dev *dev) { struct e1000_hw_stats *hw_stats = E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* HW registers are cleared on read */ eth_em_stats_get(dev, NULL); /* Reset software totals */ memset(hw_stats, 0, sizeof(*hw_stats)); } static uint32_t em_get_max_pktlen(const struct e1000_hw *hw) { switch (hw->mac.type) { case e1000_82571: case e1000_82572: case e1000_ich9lan: case e1000_ich10lan: case e1000_pch2lan: case e1000_82574: case e1000_80003es2lan: /* 9K Jumbo Frame size */ case e1000_82583: return (0x2412); case e1000_pchlan: return (0x1000); /* Adapters that do not support jumbo frames */ case e1000_ich8lan: return (ETHER_MAX_LEN); default: return (MAX_JUMBO_FRAME_SIZE); } } static void eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */ dev_info->max_rx_pktlen = em_get_max_pktlen(hw); dev_info->max_mac_addrs = hw->mac.rar_entry_count; /* * Starting with 631xESB hw supports 2 TX/RX queues per port. * Unfortunatelly, all these nics have just one TX context. * So we have few choises for TX: * - Use just one TX queue. * - Allow cksum offload only for one TX queue. * - Don't allow TX cksum offload at all. * For now, option #1 was chosen. * To use second RX queue we have to use extended RX descriptor * (Multiple Receive Queues are mutually exclusive with UDP * fragmentation and are not supported when a legacy receive * descriptor format is used). * Which means separate RX routinies - as legacy nics (82540, 82545) * don't support extended RXD. * To avoid it we support just one RX queue for now (no RSS). */ dev_info->max_rx_queues = 1; dev_info->max_tx_queues = 1; } /* return 0 means link status changed, -1 means not changed */ static int eth_em_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_link link, old; int link_check, count; link_check = 0; hw->mac.get_link_status = 1; /* possible wait-to-complete in up to 9 seconds */ for (count = 0; count < EM_LINK_UPDATE_CHECK_TIMEOUT; count ++) { /* Read the real link status */ switch (hw->phy.media_type) { case e1000_media_type_copper: /* Do the work to read phy */ e1000_check_for_link(hw); link_check = !hw->mac.get_link_status; break; case e1000_media_type_fiber: e1000_check_for_link(hw); link_check = (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU); break; case e1000_media_type_internal_serdes: e1000_check_for_link(hw); link_check = hw->mac.serdes_has_link; break; default: break; } if (link_check || wait_to_complete == 0) break; rte_delay_ms(EM_LINK_UPDATE_CHECK_INTERVAL); } memset(&link, 0, sizeof(link)); rte_em_dev_atomic_read_link_status(dev, &link); old = link; /* Now we check if a transition has happened */ if (link_check && (link.link_status == 0)) { hw->mac.ops.get_link_up_info(hw, &link.link_speed, &link.link_duplex); link.link_status = 1; } else if (!link_check && (link.link_status == 1)) { link.link_speed = 0; link.link_duplex = 0; link.link_status = 0; } rte_em_dev_atomic_write_link_status(dev, &link); /* not changed */ if (old.link_status == link.link_status) return -1; /* changed */ return 0; } /* * em_hw_control_acquire sets {CTRL_EXT|FWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means * that the driver is loaded. For AMT version type f/w * this means that the network i/f is open. */ static void em_hw_control_acquire(struct e1000_hw *hw) { uint32_t ctrl_ext, swsm; /* Let firmware know the driver has taken over */ if (hw->mac.type == e1000_82573) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_DRV_LOAD); } else { ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); } } /* * em_hw_control_release resets {CTRL_EXTT|FWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. For AMT versions of the * f/w this means that the network i/f is closed. */ static void em_hw_control_release(struct e1000_hw *hw) { uint32_t ctrl_ext, swsm; /* Let firmware taken over control of h/w */ if (hw->mac.type == e1000_82573) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm & ~E1000_SWSM_DRV_LOAD); } else { ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); } } /* * Bit of a misnomer, what this really means is * to enable OS management of the system... aka * to disable special hardware management features. */ static void em_init_manageability(struct e1000_hw *hw) { if (e1000_enable_mng_pass_thru(hw)) { uint32_t manc2h = E1000_READ_REG(hw, E1000_MANC2H); uint32_t manc = E1000_READ_REG(hw, E1000_MANC); /* disable hardware interception of ARP */ manc &= ~(E1000_MANC_ARP_EN); /* enable receiving management packets to the host */ manc |= E1000_MANC_EN_MNG2HOST; manc2h |= 1 << 5; /* Mng Port 623 */ manc2h |= 1 << 6; /* Mng Port 664 */ E1000_WRITE_REG(hw, E1000_MANC2H, manc2h); E1000_WRITE_REG(hw, E1000_MANC, manc); } } /* * Give control back to hardware management * controller if there is one. */ static void em_release_manageability(struct e1000_hw *hw) { uint32_t manc; if (e1000_enable_mng_pass_thru(hw)) { manc = E1000_READ_REG(hw, E1000_MANC); /* re-enable hardware interception of ARP */ manc |= E1000_MANC_ARP_EN; manc &= ~E1000_MANC_EN_MNG2HOST; E1000_WRITE_REG(hw, E1000_MANC, manc); } } static void eth_em_promiscuous_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_em_promiscuous_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_SBP); if (dev->data->all_multicast == 1) rctl |= E1000_RCTL_MPE; else rctl &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_em_allmulticast_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_MPE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_em_allmulticast_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; if (dev->data->promiscuous == 1) return; /* must remain in all_multicast mode */ rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static int eth_em_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vfta; uint32_t vid_idx; uint32_t vid_bit; vid_idx = (uint32_t) ((vlan_id >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK); vid_bit = (uint32_t) (1 << (vlan_id & E1000_VFTA_ENTRY_BIT_SHIFT_MASK)); vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, vid_idx); if (on) vfta |= vid_bit; else vfta &= ~vid_bit; E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, vid_idx, vfta); /* update local VFTA copy */ shadow_vfta->vfta[vid_idx] = vfta; return 0; } static void em_vlan_hw_filter_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* Filter Table Disable */ reg = E1000_READ_REG(hw, E1000_RCTL); reg &= ~E1000_RCTL_CFIEN; reg &= ~E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); } static void em_vlan_hw_filter_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t reg; int i; /* Filter Table Enable, CFI not used for packet acceptance */ reg = E1000_READ_REG(hw, E1000_RCTL); reg &= ~E1000_RCTL_CFIEN; reg |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); /* restore vfta from local copy */ for (i = 0; i < IGB_VFTA_SIZE; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, i, shadow_vfta->vfta[i]); } static void em_vlan_hw_strip_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* VLAN Mode Disable */ reg = E1000_READ_REG(hw, E1000_CTRL); reg &= ~E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, reg); } static void em_vlan_hw_strip_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* VLAN Mode Enable */ reg = E1000_READ_REG(hw, E1000_CTRL); reg |= E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, reg); } static void eth_em_vlan_offload_set(struct rte_eth_dev *dev, int mask) { if(mask & ETH_VLAN_STRIP_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_strip) em_vlan_hw_strip_enable(dev); else em_vlan_hw_strip_disable(dev); } if(mask & ETH_VLAN_FILTER_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_filter) em_vlan_hw_filter_enable(dev); else em_vlan_hw_filter_disable(dev); } } static void em_intr_disable(struct e1000_hw *hw) { E1000_WRITE_REG(hw, E1000_IMC, ~0); } /** * It enables the interrupt mask and then enable the interrupt. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_em_interrupt_setup(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); E1000_WRITE_REG(hw, E1000_IMS, E1000_ICR_LSC); rte_intr_enable(&(dev->pci_dev->intr_handle)); return (0); } /* * It reads ICR and gets interrupt causes, check it and set a bit flag * to update link status. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_em_interrupt_get_status(struct rte_eth_dev *dev) { uint32_t icr; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); /* read-on-clear nic registers here */ icr = E1000_READ_REG(hw, E1000_ICR); if (icr & E1000_ICR_LSC) { intr->flags |= E1000_FLAG_NEED_LINK_UPDATE; } return 0; } /* * It executes link_update after knowing an interrupt is prsent. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_em_interrupt_action(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); uint32_t tctl, rctl; struct rte_eth_link link; int ret; if (!(intr->flags & E1000_FLAG_NEED_LINK_UPDATE)) return -1; intr->flags &= ~E1000_FLAG_NEED_LINK_UPDATE; rte_intr_enable(&(dev->pci_dev->intr_handle)); /* set get_link_status to check register later */ hw->mac.get_link_status = 1; ret = eth_em_link_update(dev, 0); /* check if link has changed */ if (ret < 0) return 0; memset(&link, 0, sizeof(link)); rte_em_dev_atomic_read_link_status(dev, &link); if (link.link_status) { PMD_INIT_LOG(INFO, " Port %d: Link Up - speed %u Mbps - %s", dev->data->port_id, (unsigned)link.link_speed, link.link_duplex == ETH_LINK_FULL_DUPLEX ? "full-duplex" : "half-duplex"); } else { PMD_INIT_LOG(INFO, " Port %d: Link Down", dev->data->port_id); } PMD_INIT_LOG(DEBUG, "PCI Address: %04d:%02d:%02d:%d", dev->pci_dev->addr.domain, dev->pci_dev->addr.bus, dev->pci_dev->addr.devid, dev->pci_dev->addr.function); tctl = E1000_READ_REG(hw, E1000_TCTL); rctl = E1000_READ_REG(hw, E1000_RCTL); if (link.link_status) { /* enable Tx/Rx */ tctl |= E1000_TCTL_EN; rctl |= E1000_RCTL_EN; } else { /* disable Tx/Rx */ tctl &= ~E1000_TCTL_EN; rctl &= ~E1000_RCTL_EN; } E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); return 0; } /** * Interrupt handler which shall be registered at first. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void eth_em_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; eth_em_interrupt_get_status(dev); eth_em_interrupt_action(dev); _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); } static int eth_em_led_on(struct rte_eth_dev *dev) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP); } static int eth_em_led_off(struct rte_eth_dev *dev) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP); } static int eth_em_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct e1000_hw *hw; uint32_t ctrl; int tx_pause; int rx_pause; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); fc_conf->pause_time = hw->fc.pause_time; fc_conf->high_water = hw->fc.high_water; fc_conf->low_water = hw->fc.low_water; fc_conf->send_xon = hw->fc.send_xon; fc_conf->autoneg = hw->mac.autoneg; /* * Return rx_pause and tx_pause status according to actual setting of * the TFCE and RFCE bits in the CTRL register. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); if (ctrl & E1000_CTRL_TFCE) tx_pause = 1; else tx_pause = 0; if (ctrl & E1000_CTRL_RFCE) rx_pause = 1; else rx_pause = 0; if (rx_pause && tx_pause) fc_conf->mode = RTE_FC_FULL; else if (rx_pause) fc_conf->mode = RTE_FC_RX_PAUSE; else if (tx_pause) fc_conf->mode = RTE_FC_TX_PAUSE; else fc_conf->mode = RTE_FC_NONE; return 0; } static int eth_em_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct e1000_hw *hw; int err; enum e1000_fc_mode rte_fcmode_2_e1000_fcmode[] = { e1000_fc_none, e1000_fc_rx_pause, e1000_fc_tx_pause, e1000_fc_full }; uint32_t rx_buf_size; uint32_t max_high_water; uint32_t rctl; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (fc_conf->autoneg != hw->mac.autoneg) return -ENOTSUP; rx_buf_size = em_get_rx_buffer_size(hw); PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); /* At least reserve one Ethernet frame for watermark */ max_high_water = rx_buf_size - ETHER_MAX_LEN; if ((fc_conf->high_water > max_high_water) || (fc_conf->high_water < fc_conf->low_water)) { PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value"); PMD_INIT_LOG(ERR, "high water must <= 0x%x", max_high_water); return (-EINVAL); } hw->fc.requested_mode = rte_fcmode_2_e1000_fcmode[fc_conf->mode]; hw->fc.pause_time = fc_conf->pause_time; hw->fc.high_water = fc_conf->high_water; hw->fc.low_water = fc_conf->low_water; hw->fc.send_xon = fc_conf->send_xon; err = e1000_setup_link_generic(hw); if (err == E1000_SUCCESS) { /* check if we want to forward MAC frames - driver doesn't have native * capability to do that, so we'll write the registers ourselves */ rctl = E1000_READ_REG(hw, E1000_RCTL); /* set or clear MFLCN.PMCF bit depending on configuration */ if (fc_conf->mac_ctrl_frame_fwd != 0) rctl |= E1000_RCTL_PMCF; else rctl &= ~E1000_RCTL_PMCF; E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); return 0; } PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err); return (-EIO); } static void eth_em_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, __rte_unused uint32_t pool) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); e1000_rar_set(hw, mac_addr->addr_bytes, index); } static void eth_em_rar_clear(struct rte_eth_dev *dev, uint32_t index) { uint8_t addr[ETHER_ADDR_LEN]; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); memset(addr, 0, sizeof(addr)); e1000_rar_set(hw, addr, index); } static int eth_em_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { struct rte_eth_dev_info dev_info; struct e1000_hw *hw; uint32_t frame_size; uint32_t rctl; eth_em_infos_get(dev, &dev_info); frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + VLAN_TAG_SIZE; /* check that mtu is within the allowed range */ if ((mtu < ETHER_MIN_MTU) || (frame_size > dev_info.max_rx_pktlen)) return -EINVAL; /* refuse mtu that requires the support of scattered packets when this * feature has not been enabled before. */ if (!dev->data->scattered_rx && frame_size > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) return -EINVAL; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); rctl = E1000_READ_REG(hw, E1000_RCTL); /* switch to jumbo mode if needed */ if (frame_size > ETHER_MAX_LEN) { dev->data->dev_conf.rxmode.jumbo_frame = 1; rctl |= E1000_RCTL_LPE; } else { dev->data->dev_conf.rxmode.jumbo_frame = 0; rctl &= ~E1000_RCTL_LPE; } E1000_WRITE_REG(hw, E1000_RCTL, rctl); /* update max frame size */ dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; return 0; } static int eth_em_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); e1000_update_mc_addr_list(hw, (u8 *)mc_addr_set, nb_mc_addr); return 0; } struct rte_driver em_pmd_drv = { .type = PMD_PDEV, .init = rte_em_pmd_init, }; PMD_REGISTER_DRIVER(em_pmd_drv); ================================================ FILE: drivers/net/e1000/em_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e1000_logs.h" #include "base/e1000_api.h" #include "e1000_ethdev.h" #include "base/e1000_osdep.h" #define E1000_TXD_VLAN_SHIFT 16 #define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return (m); } #define RTE_MBUF_DATA_DMA_ADDR(mb) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) /** * Structure associated with each descriptor of the RX ring of a RX queue. */ struct em_rx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ }; /** * Structure associated with each descriptor of the TX ring of a TX queue. */ struct em_tx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ uint16_t next_id; /**< Index of next descriptor in ring. */ uint16_t last_id; /**< Index of last scattered descriptor. */ }; /** * Structure associated with each RX queue. */ struct em_rx_queue { struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ volatile struct e1000_rx_desc *rx_ring; /**< RX ring virtual address. */ uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ volatile uint32_t *rdt_reg_addr; /**< RDT register address. */ volatile uint32_t *rdh_reg_addr; /**< RDH register address. */ struct em_rx_entry *sw_ring; /**< address of RX software ring. */ struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ uint16_t nb_rx_desc; /**< number of RX descriptors. */ uint16_t rx_tail; /**< current value of RDT register. */ uint16_t nb_rx_hold; /**< number of held free RX desc. */ uint16_t rx_free_thresh; /**< max free RX desc to hold. */ uint16_t queue_id; /**< RX queue index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold register. */ uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ }; /** * Hardware context number */ enum { EM_CTX_0 = 0, /**< CTX0 */ EM_CTX_NUM = 1, /**< CTX NUM */ }; /** Offload features */ union em_vlan_macip { uint32_t data; struct { uint16_t l3_len:9; /**< L3 (IP) Header Length. */ uint16_t l2_len:7; /**< L2 (MAC) Header Length. */ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order). */ } f; }; /* * Compare mask for vlan_macip_len.data, * should be in sync with em_vlan_macip.f layout. * */ #define TX_VLAN_CMP_MASK 0xFFFF0000 /**< VLAN length - 16-bits. */ #define TX_MAC_LEN_CMP_MASK 0x0000FE00 /**< MAC length - 7-bits. */ #define TX_IP_LEN_CMP_MASK 0x000001FF /**< IP length - 9-bits. */ /** MAC+IP length. */ #define TX_MACIP_LEN_CMP_MASK (TX_MAC_LEN_CMP_MASK | TX_IP_LEN_CMP_MASK) /** * Structure to check if new context need be built */ struct em_ctx_info { uint64_t flags; /**< ol_flags related to context build. */ uint32_t cmp_mask; /**< compare mask */ union em_vlan_macip hdrlen; /**< L2 and L3 header lenghts */ }; /** * Structure associated with each TX queue. */ struct em_tx_queue { volatile struct e1000_data_desc *tx_ring; /**< TX ring address */ uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ struct em_tx_entry *sw_ring; /**< virtual address of SW ring. */ volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ uint16_t nb_tx_desc; /**< number of TX descriptors. */ uint16_t tx_tail; /**< Current value of TDT register. */ /**< Start freeing TX buffers if there are less free descriptors than this value. */ uint16_t tx_free_thresh; /**< Number of TX descriptors to use before RS bit is set. */ uint16_t tx_rs_thresh; /** Number of TX descriptors used since RS bit was set. */ uint16_t nb_tx_used; /** Index to last TX descriptor to have been cleaned. */ uint16_t last_desc_cleaned; /** Total number of TX descriptors ready to be allocated. */ uint16_t nb_tx_free; uint16_t queue_id; /**< TX queue index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold register. */ struct em_ctx_info ctx_cache; /**< Hardware context history.*/ }; #if 1 #define RTE_PMD_USE_PREFETCH #endif #ifdef RTE_PMD_USE_PREFETCH #define rte_em_prefetch(p) rte_prefetch0(p) #else #define rte_em_prefetch(p) do {} while(0) #endif #ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch(p) rte_prefetch1(p) #else #define rte_packet_prefetch(p) do {} while(0) #endif #ifndef DEFAULT_TX_FREE_THRESH #define DEFAULT_TX_FREE_THRESH 32 #endif /* DEFAULT_TX_FREE_THRESH */ #ifndef DEFAULT_TX_RS_THRESH #define DEFAULT_TX_RS_THRESH 32 #endif /* DEFAULT_TX_RS_THRESH */ /********************************************************************* * * TX function * **********************************************************************/ /* * Populates TX context descriptor. */ static inline void em_set_xmit_ctx(struct em_tx_queue* txq, volatile struct e1000_context_desc *ctx_txd, uint64_t flags, union em_vlan_macip hdrlen) { uint32_t cmp_mask, cmd_len; uint16_t ipcse, l2len; struct e1000_context_desc ctx; cmp_mask = 0; cmd_len = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_C; l2len = hdrlen.f.l2_len; ipcse = (uint16_t)(l2len + hdrlen.f.l3_len); /* setup IPCS* fields */ ctx.lower_setup.ip_fields.ipcss = (uint8_t)l2len; ctx.lower_setup.ip_fields.ipcso = (uint8_t)(l2len + offsetof(struct ipv4_hdr, hdr_checksum)); /* * When doing checksum or TCP segmentation with IPv6 headers, * IPCSE field should be set t0 0. */ if (flags & PKT_TX_IP_CKSUM) { ctx.lower_setup.ip_fields.ipcse = (uint16_t)rte_cpu_to_le_16(ipcse - 1); cmd_len |= E1000_TXD_CMD_IP; cmp_mask |= TX_MACIP_LEN_CMP_MASK; } else { ctx.lower_setup.ip_fields.ipcse = 0; } /* setup TUCS* fields */ ctx.upper_setup.tcp_fields.tucss = (uint8_t)ipcse; ctx.upper_setup.tcp_fields.tucse = 0; switch (flags & PKT_TX_L4_MASK) { case PKT_TX_UDP_CKSUM: ctx.upper_setup.tcp_fields.tucso = (uint8_t)(ipcse + offsetof(struct udp_hdr, dgram_cksum)); cmp_mask |= TX_MACIP_LEN_CMP_MASK; break; case PKT_TX_TCP_CKSUM: ctx.upper_setup.tcp_fields.tucso = (uint8_t)(ipcse + offsetof(struct tcp_hdr, cksum)); cmd_len |= E1000_TXD_CMD_TCP; cmp_mask |= TX_MACIP_LEN_CMP_MASK; break; default: ctx.upper_setup.tcp_fields.tucso = 0; } ctx.cmd_and_length = rte_cpu_to_le_32(cmd_len); ctx.tcp_seg_setup.data = 0; *ctx_txd = ctx; txq->ctx_cache.flags = flags; txq->ctx_cache.cmp_mask = cmp_mask; txq->ctx_cache.hdrlen = hdrlen; } /* * Check which hardware context can be used. Use the existing match * or create a new context descriptor. */ static inline uint32_t what_ctx_update(struct em_tx_queue *txq, uint64_t flags, union em_vlan_macip hdrlen) { /* If match with the current context */ if (likely (txq->ctx_cache.flags == flags && ((txq->ctx_cache.hdrlen.data ^ hdrlen.data) & txq->ctx_cache.cmp_mask) == 0)) return (EM_CTX_0); /* Mismatch */ return (EM_CTX_NUM); } /* Reset transmit descriptors after they have been used */ static inline int em_xmit_cleanup(struct em_tx_queue *txq) { struct em_tx_entry *sw_ring = txq->sw_ring; volatile struct e1000_data_desc *txr = txq->tx_ring; uint16_t last_desc_cleaned = txq->last_desc_cleaned; uint16_t nb_tx_desc = txq->nb_tx_desc; uint16_t desc_to_clean_to; uint16_t nb_tx_to_clean; /* Determine the last descriptor needing to be cleaned */ desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_rs_thresh); if (desc_to_clean_to >= nb_tx_desc) desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc); /* Check to make sure the last descriptor to clean is done */ desc_to_clean_to = sw_ring[desc_to_clean_to].last_id; if (! (txr[desc_to_clean_to].upper.fields.status & E1000_TXD_STAT_DD)) { PMD_TX_FREE_LOG(DEBUG, "TX descriptor %4u is not done" "(port=%d queue=%d)", desc_to_clean_to, txq->port_id, txq->queue_id); /* Failed to clean any descriptors, better luck next time */ return -(1); } /* Figure out how many descriptors will be cleaned */ if (last_desc_cleaned > desc_to_clean_to) nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) + desc_to_clean_to); else nb_tx_to_clean = (uint16_t)(desc_to_clean_to - last_desc_cleaned); PMD_TX_FREE_LOG(DEBUG, "Cleaning %4u TX descriptors: %4u to %4u " "(port=%d queue=%d)", nb_tx_to_clean, last_desc_cleaned, desc_to_clean_to, txq->port_id, txq->queue_id); /* * The last descriptor to clean is done, so that means all the * descriptors from the last descriptor that was cleaned * up to the last descriptor with the RS bit set * are done. Only reset the threshold descriptor. */ txr[desc_to_clean_to].upper.fields.status = 0; /* Update the txq to reflect the last descriptor that was cleaned */ txq->last_desc_cleaned = desc_to_clean_to; txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean); /* No Error */ return (0); } static inline uint32_t tx_desc_cksum_flags_to_upper(uint64_t ol_flags) { static const uint32_t l4_olinfo[2] = {0, E1000_TXD_POPTS_TXSM << 8}; static const uint32_t l3_olinfo[2] = {0, E1000_TXD_POPTS_IXSM << 8}; uint32_t tmp; tmp = l4_olinfo[(ol_flags & PKT_TX_L4_MASK) != PKT_TX_L4_NO_CKSUM]; tmp |= l3_olinfo[(ol_flags & PKT_TX_IP_CKSUM) != 0]; return (tmp); } uint16_t eth_em_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct em_tx_queue *txq; struct em_tx_entry *sw_ring; struct em_tx_entry *txe, *txn; volatile struct e1000_data_desc *txr; volatile struct e1000_data_desc *txd; struct rte_mbuf *tx_pkt; struct rte_mbuf *m_seg; uint64_t buf_dma_addr; uint32_t popts_spec; uint32_t cmd_type_len; uint16_t slen; uint64_t ol_flags; uint16_t tx_id; uint16_t tx_last; uint16_t nb_tx; uint16_t nb_used; uint64_t tx_ol_req; uint32_t ctx; uint32_t new_ctx; union em_vlan_macip hdrlen; txq = tx_queue; sw_ring = txq->sw_ring; txr = txq->tx_ring; tx_id = txq->tx_tail; txe = &sw_ring[tx_id]; /* Determine if the descriptor ring needs to be cleaned. */ if (txq->nb_tx_free < txq->tx_free_thresh) em_xmit_cleanup(txq); /* TX loop */ for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { new_ctx = 0; tx_pkt = *tx_pkts++; RTE_MBUF_PREFETCH_TO_FREE(txe->mbuf); /* * Determine how many (if any) context descriptors * are needed for offload functionality. */ ol_flags = tx_pkt->ol_flags; /* If hardware offload required */ tx_ol_req = (ol_flags & (PKT_TX_IP_CKSUM | PKT_TX_L4_MASK)); if (tx_ol_req) { hdrlen.f.vlan_tci = tx_pkt->vlan_tci; hdrlen.f.l2_len = tx_pkt->l2_len; hdrlen.f.l3_len = tx_pkt->l3_len; /* If new context to be built or reuse the exist ctx. */ ctx = what_ctx_update(txq, tx_ol_req, hdrlen); /* Only allocate context descriptor if required*/ new_ctx = (ctx == EM_CTX_NUM); } /* * Keep track of how many descriptors are used this loop * This will always be the number of segments + the number of * Context descriptors required to transmit the packet */ nb_used = (uint16_t)(tx_pkt->nb_segs + new_ctx); /* * The number of descriptors that must be allocated for a * packet is the number of segments of that packet, plus 1 * Context Descriptor for the hardware offload, if any. * Determine the last TX descriptor to allocate in the TX ring * for the packet, starting from the current position (tx_id) * in the ring. */ tx_last = (uint16_t) (tx_id + nb_used - 1); /* Circular ring */ if (tx_last >= txq->nb_tx_desc) tx_last = (uint16_t) (tx_last - txq->nb_tx_desc); PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u" " tx_first=%u tx_last=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) tx_pkt->pkt_len, (unsigned) tx_id, (unsigned) tx_last); /* * Make sure there are enough TX descriptors available to * transmit the entire packet. * nb_used better be less than or equal to txq->tx_rs_thresh */ while (unlikely (nb_used > txq->nb_tx_free)) { PMD_TX_FREE_LOG(DEBUG, "Not enough free TX descriptors " "nb_used=%4u nb_free=%4u " "(port=%d queue=%d)", nb_used, txq->nb_tx_free, txq->port_id, txq->queue_id); if (em_xmit_cleanup(txq) != 0) { /* Could not clean any descriptors */ if (nb_tx == 0) return (0); goto end_of_tx; } } /* * By now there are enough free TX descriptors to transmit * the packet. */ /* * Set common flags of all TX Data Descriptors. * * The following bits must be set in all Data Descriptors: * - E1000_TXD_DTYP_DATA * - E1000_TXD_DTYP_DEXT * * The following bits must be set in the first Data Descriptor * and are ignored in the other ones: * - E1000_TXD_POPTS_IXSM * - E1000_TXD_POPTS_TXSM * * The following bits must be set in the last Data Descriptor * and are ignored in the other ones: * - E1000_TXD_CMD_VLE * - E1000_TXD_CMD_IFCS * * The following bits must only be set in the last Data * Descriptor: * - E1000_TXD_CMD_EOP * * The following bits can be set in any Data Descriptor, but * are only set in the last Data Descriptor: * - E1000_TXD_CMD_RS */ cmd_type_len = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | E1000_TXD_CMD_IFCS; popts_spec = 0; /* Set VLAN Tag offload fields. */ if (ol_flags & PKT_TX_VLAN_PKT) { cmd_type_len |= E1000_TXD_CMD_VLE; popts_spec = tx_pkt->vlan_tci << E1000_TXD_VLAN_SHIFT; } if (tx_ol_req) { /* * Setup the TX Context Descriptor if required */ if (new_ctx) { volatile struct e1000_context_desc *ctx_txd; ctx_txd = (volatile struct e1000_context_desc *) &txr[tx_id]; txn = &sw_ring[txe->next_id]; RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf); if (txe->mbuf != NULL) { rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = NULL; } em_set_xmit_ctx(txq, ctx_txd, tx_ol_req, hdrlen); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; } /* * Setup the TX Data Descriptor, * This path will go through * whatever new/reuse the context descriptor */ popts_spec |= tx_desc_cksum_flags_to_upper(ol_flags); } m_seg = tx_pkt; do { txd = &txr[tx_id]; txn = &sw_ring[txe->next_id]; if (txe->mbuf != NULL) rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = m_seg; /* * Set up Transmit Data Descriptor. */ slen = m_seg->data_len; buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(m_seg); txd->buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txd->lower.data = rte_cpu_to_le_32(cmd_type_len | slen); txd->upper.data = rte_cpu_to_le_32(popts_spec); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; m_seg = m_seg->next; } while (m_seg != NULL); /* * The last packet data descriptor needs End Of Packet (EOP) */ cmd_type_len |= E1000_TXD_CMD_EOP; txq->nb_tx_used = (uint16_t)(txq->nb_tx_used + nb_used); txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used); /* Set RS bit only on threshold packets' last descriptor */ if (txq->nb_tx_used >= txq->tx_rs_thresh) { PMD_TX_FREE_LOG(DEBUG, "Setting RS bit on TXD id=%4u " "(port=%d queue=%d)", tx_last, txq->port_id, txq->queue_id); cmd_type_len |= E1000_TXD_CMD_RS; /* Update txq RS bit counters */ txq->nb_tx_used = 0; } txd->lower.data |= rte_cpu_to_le_32(cmd_type_len); } end_of_tx: rte_wmb(); /* * Set the Transmit Descriptor Tail (TDT) */ PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) tx_id, (unsigned) nb_tx); E1000_PCI_REG_WRITE(txq->tdt_reg_addr, tx_id); txq->tx_tail = tx_id; return (nb_tx); } /********************************************************************* * * RX functions * **********************************************************************/ static inline uint64_t rx_desc_status_to_pkt_flags(uint32_t rx_status) { uint64_t pkt_flags; /* Check if VLAN present */ pkt_flags = ((rx_status & E1000_RXD_STAT_VP) ? PKT_RX_VLAN_PKT : 0); return pkt_flags; } static inline uint64_t rx_desc_error_to_pkt_flags(uint32_t rx_error) { uint64_t pkt_flags = 0; if (rx_error & E1000_RXD_ERR_IPE) pkt_flags |= PKT_RX_IP_CKSUM_BAD; if (rx_error & E1000_RXD_ERR_TCPE) pkt_flags |= PKT_RX_L4_CKSUM_BAD; return (pkt_flags); } uint16_t eth_em_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { volatile struct e1000_rx_desc *rx_ring; volatile struct e1000_rx_desc *rxdp; struct em_rx_queue *rxq; struct em_rx_entry *sw_ring; struct em_rx_entry *rxe; struct rte_mbuf *rxm; struct rte_mbuf *nmb; struct e1000_rx_desc rxd; uint64_t dma_addr; uint16_t pkt_len; uint16_t rx_id; uint16_t nb_rx; uint16_t nb_hold; uint8_t status; rxq = rx_queue; nb_rx = 0; nb_hold = 0; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; while (nb_rx < nb_pkts) { /* * The order of operations here is important as the DD status * bit must not be read after any other descriptor fields. * rx_ring and rxdp are pointing to volatile data so the order * of accesses cannot be reordered by the compiler. If they were * not volatile, they could be reordered which could lead to * using invalid descriptor fields when read from rxd. */ rxdp = &rx_ring[rx_id]; status = rxdp->status; if (! (status & E1000_RXD_STAT_DD)) break; rxd = *rxdp; /* * End of packet. * * If the E1000_RXD_STAT_EOP flag is not set, the RX packet is * likely to be invalid and to be dropped by the various * validation checks performed by the network stack. * * Allocate a new mbuf to replenish the RX ring descriptor. * If the allocation fails: * - arrange for that RX descriptor to be the first one * being parsed the next time the receive function is * invoked [on the same queue]. * * - Stop parsing the RX ring and return immediately. * * This policy do not drop the packet received in the RX * descriptor for which the allocation of a new mbuf failed. * Thus, it allows that packet to be later retrieved if * mbuf have been freed in the mean time. * As a side effect, holding RX descriptors instead of * systematically giving them back to the NIC may lead to * RX ring exhaustion situations. * However, the NIC can gracefully prevent such situations * to happen by sending specific "back-pressure" flow control * frames to its peer(s). */ PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "status=0x%x pkt_len=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) status, (unsigned) rte_le_to_cpu_16(rxd.length)); nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++; break; } nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf while processing current one. */ rte_em_prefetch(sw_ring[rx_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_em_prefetch(&rx_ring[rx_id]); rte_em_prefetch(&sw_ring[rx_id]); } /* Rearm RXD: attach new mbuf and reset status to zero. */ rxm = rxe->mbuf; rxe->mbuf = nmb; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->buffer_addr = dma_addr; rxdp->status = 0; /* * Initialize the returned mbuf. * 1) setup generic mbuf fields: * - number of segments, * - next segment, * - packet length, * - RX port identifier. * 2) integrate hardware offload data, if any: * - RSS flag & hash, * - IP checksum flag, * - VLAN TCI, if any, * - error flags. */ pkt_len = (uint16_t) (rte_le_to_cpu_16(rxd.length) - rxq->crc_len); rxm->data_off = RTE_PKTMBUF_HEADROOM; rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off); rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = pkt_len; rxm->data_len = pkt_len; rxm->port = rxq->port_id; rxm->ol_flags = rx_desc_status_to_pkt_flags(status); rxm->ol_flags = rxm->ol_flags | rx_desc_error_to_pkt_flags(rxd.errors); /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */ rxm->vlan_tci = rte_le_to_cpu_16(rxd.special); /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = rxm; } rxq->rx_tail = rx_id; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ nb_hold = (uint16_t) (nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) nb_hold, (unsigned) nb_rx); rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); E1000_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return (nb_rx); } uint16_t eth_em_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct em_rx_queue *rxq; volatile struct e1000_rx_desc *rx_ring; volatile struct e1000_rx_desc *rxdp; struct em_rx_entry *sw_ring; struct em_rx_entry *rxe; struct rte_mbuf *first_seg; struct rte_mbuf *last_seg; struct rte_mbuf *rxm; struct rte_mbuf *nmb; struct e1000_rx_desc rxd; uint64_t dma; /* Physical address of mbuf data buffer */ uint16_t rx_id; uint16_t nb_rx; uint16_t nb_hold; uint16_t data_len; uint8_t status; rxq = rx_queue; nb_rx = 0; nb_hold = 0; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; /* * Retrieve RX context of current packet, if any. */ first_seg = rxq->pkt_first_seg; last_seg = rxq->pkt_last_seg; while (nb_rx < nb_pkts) { next_desc: /* * The order of operations here is important as the DD status * bit must not be read after any other descriptor fields. * rx_ring and rxdp are pointing to volatile data so the order * of accesses cannot be reordered by the compiler. If they were * not volatile, they could be reordered which could lead to * using invalid descriptor fields when read from rxd. */ rxdp = &rx_ring[rx_id]; status = rxdp->status; if (! (status & E1000_RXD_STAT_DD)) break; rxd = *rxdp; /* * Descriptor done. * * Allocate a new mbuf to replenish the RX ring descriptor. * If the allocation fails: * - arrange for that RX descriptor to be the first one * being parsed the next time the receive function is * invoked [on the same queue]. * * - Stop parsing the RX ring and return immediately. * * This policy does not drop the packet received in the RX * descriptor for which the allocation of a new mbuf failed. * Thus, it allows that packet to be later retrieved if * mbuf have been freed in the mean time. * As a side effect, holding RX descriptors instead of * systematically giving them back to the NIC may lead to * RX ring exhaustion situations. * However, the NIC can gracefully prevent such situations * to happen by sending specific "back-pressure" flow control * frames to its peer(s). */ PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "status=0x%x data_len=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) status, (unsigned) rte_le_to_cpu_16(rxd.length)); nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++; break; } nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf while processing current one. */ rte_em_prefetch(sw_ring[rx_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_em_prefetch(&rx_ring[rx_id]); rte_em_prefetch(&sw_ring[rx_id]); } /* * Update RX descriptor with the physical address of the new * data buffer of the new allocated mbuf. */ rxm = rxe->mbuf; rxe->mbuf = nmb; dma = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->buffer_addr = dma; rxdp->status = 0; /* * Set data length & data buffer address of mbuf. */ data_len = rte_le_to_cpu_16(rxd.length); rxm->data_len = data_len; rxm->data_off = RTE_PKTMBUF_HEADROOM; /* * If this is the first buffer of the received packet, * set the pointer to the first mbuf of the packet and * initialize its context. * Otherwise, update the total length and the number of segments * of the current scattered packet, and update the pointer to * the last mbuf of the current packet. */ if (first_seg == NULL) { first_seg = rxm; first_seg->pkt_len = data_len; first_seg->nb_segs = 1; } else { first_seg->pkt_len += data_len; first_seg->nb_segs++; last_seg->next = rxm; } /* * If this is not the last buffer of the received packet, * update the pointer to the last mbuf of the current scattered * packet and continue to parse the RX ring. */ if (! (status & E1000_RXD_STAT_EOP)) { last_seg = rxm; goto next_desc; } /* * This is the last buffer of the received packet. * If the CRC is not stripped by the hardware: * - Subtract the CRC length from the total packet length. * - If the last buffer only contains the whole CRC or a part * of it, free the mbuf associated to the last buffer. * If part of the CRC is also contained in the previous * mbuf, subtract the length of that CRC part from the * data length of the previous mbuf. */ rxm->next = NULL; if (unlikely(rxq->crc_len > 0)) { first_seg->pkt_len -= ETHER_CRC_LEN; if (data_len <= ETHER_CRC_LEN) { rte_pktmbuf_free_seg(rxm); first_seg->nb_segs--; last_seg->data_len = (uint16_t) (last_seg->data_len - (ETHER_CRC_LEN - data_len)); last_seg->next = NULL; } else rxm->data_len = (uint16_t) (data_len - ETHER_CRC_LEN); } /* * Initialize the first mbuf of the returned packet: * - RX port identifier, * - hardware offload data, if any: * - IP checksum flag, * - error flags. */ first_seg->port = rxq->port_id; first_seg->ol_flags = rx_desc_status_to_pkt_flags(status); first_seg->ol_flags = first_seg->ol_flags | rx_desc_error_to_pkt_flags(rxd.errors); /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */ rxm->vlan_tci = rte_le_to_cpu_16(rxd.special); /* Prefetch data of first segment, if configured to do so. */ rte_packet_prefetch((char *)first_seg->buf_addr + first_seg->data_off); /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = first_seg; /* * Setup receipt context for a new packet. */ first_seg = NULL; } /* * Record index of the next RX descriptor to probe. */ rxq->rx_tail = rx_id; /* * Save receive context. */ rxq->pkt_first_seg = first_seg; rxq->pkt_last_seg = last_seg; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ nb_hold = (uint16_t) (nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) nb_hold, (unsigned) nb_rx); rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); E1000_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return (nb_rx); } /* * Rings setup and release. * * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. * This will also optimize cache line size effect. * H/W supports up to cache line size 128. */ #define EM_ALIGN 128 /* * Maximum number of Ring Descriptors. * * Since RDLEN/TDLEN should be multiple of 128 bytes, the number of ring * desscriptors should meet the following condition: * (num_ring_desc * sizeof(struct e1000_rx/tx_desc)) % 128 == 0 */ #define EM_MIN_RING_DESC 32 #define EM_MAX_RING_DESC 4096 #define EM_MAX_BUF_SIZE 16384 #define EM_RCTL_FLXBUF_STEP 1024 static const struct rte_memzone * ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { const struct rte_memzone *mz; char z_name[RTE_MEMZONE_NAMESIZE]; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); if ((mz = rte_memzone_lookup(z_name)) != 0) return (mz); #ifdef RTE_LIBRTE_XEN_DOM0 return rte_memzone_reserve_bounded(z_name, ring_size, socket_id, 0, RTE_CACHE_LINE_SIZE, RTE_PGSIZE_2M); #else return rte_memzone_reserve(z_name, ring_size, socket_id, 0); #endif } static void em_tx_queue_release_mbufs(struct em_tx_queue *txq) { unsigned i; if (txq->sw_ring != NULL) { for (i = 0; i != txq->nb_tx_desc; i++) { if (txq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); txq->sw_ring[i].mbuf = NULL; } } } } static void em_tx_queue_release(struct em_tx_queue *txq) { if (txq != NULL) { em_tx_queue_release_mbufs(txq); rte_free(txq->sw_ring); rte_free(txq); } } void eth_em_tx_queue_release(void *txq) { em_tx_queue_release(txq); } /* (Re)set dynamic em_tx_queue fields to defaults */ static void em_reset_tx_queue(struct em_tx_queue *txq) { uint16_t i, nb_desc, prev; static const struct e1000_data_desc txd_init = { .upper.fields = {.status = E1000_TXD_STAT_DD}, }; nb_desc = txq->nb_tx_desc; /* Initialize ring entries */ prev = (uint16_t) (nb_desc - 1); for (i = 0; i < nb_desc; i++) { txq->tx_ring[i] = txd_init; txq->sw_ring[i].mbuf = NULL; txq->sw_ring[i].last_id = i; txq->sw_ring[prev].next_id = i; prev = i; } /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition */ txq->nb_tx_free = (uint16_t)(nb_desc - 1); txq->last_desc_cleaned = (uint16_t)(nb_desc - 1); txq->nb_tx_used = 0; txq->tx_tail = 0; memset((void*)&txq->ctx_cache, 0, sizeof (txq->ctx_cache)); } int eth_em_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { const struct rte_memzone *tz; struct em_tx_queue *txq; struct e1000_hw *hw; uint32_t tsize; uint16_t tx_rs_thresh, tx_free_thresh; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Validate number of transmit descriptors. * It must not exceed hardware maximum, and must be multiple * of EM_ALIGN. */ if (((nb_desc * sizeof(*txq->tx_ring)) % EM_ALIGN) != 0 || (nb_desc > EM_MAX_RING_DESC) || (nb_desc < EM_MIN_RING_DESC)) { return -(EINVAL); } tx_free_thresh = tx_conf->tx_free_thresh; if (tx_free_thresh == 0) tx_free_thresh = (uint16_t)RTE_MIN(nb_desc / 4, DEFAULT_TX_FREE_THRESH); tx_rs_thresh = tx_conf->tx_rs_thresh; if (tx_rs_thresh == 0) tx_rs_thresh = (uint16_t)RTE_MIN(tx_free_thresh, DEFAULT_TX_RS_THRESH); if (tx_free_thresh >= (nb_desc - 3)) { PMD_INIT_LOG(ERR, "tx_free_thresh must be less than the " "number of TX descriptors minus 3. " "(tx_free_thresh=%u port=%d queue=%d)", (unsigned int)tx_free_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } if (tx_rs_thresh > tx_free_thresh) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than or equal to " "tx_free_thresh. (tx_free_thresh=%u " "tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_free_thresh, (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } /* * If rs_bit_thresh is greater than 1, then TX WTHRESH should be * set to 0. If WTHRESH is greater than zero, the RS bit is ignored * by the NIC and all descriptors are written back after the NIC * accumulates WTHRESH descriptors. */ if (tx_conf->tx_thresh.wthresh != 0 && tx_rs_thresh != 1) { PMD_INIT_LOG(ERR, "TX WTHRESH must be set to 0 if " "tx_rs_thresh is greater than 1. (tx_rs_thresh=%u " "port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } /* Free memory prior to re-allocation if needed... */ if (dev->data->tx_queues[queue_idx] != NULL) { em_tx_queue_release(dev->data->tx_queues[queue_idx]); dev->data->tx_queues[queue_idx] = NULL; } /* * Allocate TX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ tsize = sizeof (txq->tx_ring[0]) * EM_MAX_RING_DESC; if ((tz = ring_dma_zone_reserve(dev, "tx_ring", queue_idx, tsize, socket_id)) == NULL) return (-ENOMEM); /* Allocate the tx queue data structure. */ if ((txq = rte_zmalloc("ethdev TX queue", sizeof(*txq), RTE_CACHE_LINE_SIZE)) == NULL) return (-ENOMEM); /* Allocate software ring */ if ((txq->sw_ring = rte_zmalloc("txq->sw_ring", sizeof(txq->sw_ring[0]) * nb_desc, RTE_CACHE_LINE_SIZE)) == NULL) { em_tx_queue_release(txq); return (-ENOMEM); } txq->nb_tx_desc = nb_desc; txq->tx_free_thresh = tx_free_thresh; txq->tx_rs_thresh = tx_rs_thresh; txq->pthresh = tx_conf->tx_thresh.pthresh; txq->hthresh = tx_conf->tx_thresh.hthresh; txq->wthresh = tx_conf->tx_thresh.wthresh; txq->queue_id = queue_idx; txq->port_id = dev->data->port_id; txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(queue_idx)); #ifndef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = (uint64_t) tz->phys_addr; #else txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); #endif txq->tx_ring = (struct e1000_data_desc *) tz->addr; PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); em_reset_tx_queue(txq); dev->data->tx_queues[queue_idx] = txq; return (0); } static void em_rx_queue_release_mbufs(struct em_rx_queue *rxq) { unsigned i; if (rxq->sw_ring != NULL) { for (i = 0; i != rxq->nb_rx_desc; i++) { if (rxq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); rxq->sw_ring[i].mbuf = NULL; } } } } static void em_rx_queue_release(struct em_rx_queue *rxq) { if (rxq != NULL) { em_rx_queue_release_mbufs(rxq); rte_free(rxq->sw_ring); rte_free(rxq); } } void eth_em_rx_queue_release(void *rxq) { em_rx_queue_release(rxq); } /* Reset dynamic em_rx_queue fields back to defaults */ static void em_reset_rx_queue(struct em_rx_queue *rxq) { rxq->rx_tail = 0; rxq->nb_rx_hold = 0; rxq->pkt_first_seg = NULL; rxq->pkt_last_seg = NULL; } int eth_em_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { const struct rte_memzone *rz; struct em_rx_queue *rxq; struct e1000_hw *hw; uint32_t rsize; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Validate number of receive descriptors. * It must not exceed hardware maximum, and must be multiple * of EM_ALIGN. */ if (((nb_desc * sizeof(rxq->rx_ring[0])) % EM_ALIGN) != 0 || (nb_desc > EM_MAX_RING_DESC) || (nb_desc < EM_MIN_RING_DESC)) { return (-EINVAL); } /* * EM devices don't support drop_en functionality */ if (rx_conf->rx_drop_en) { PMD_INIT_LOG(ERR, "drop_en functionality not supported by " "device"); return (-EINVAL); } /* Free memory prior to re-allocation if needed. */ if (dev->data->rx_queues[queue_idx] != NULL) { em_rx_queue_release(dev->data->rx_queues[queue_idx]); dev->data->rx_queues[queue_idx] = NULL; } /* Allocate RX ring for max possible mumber of hardware descriptors. */ rsize = sizeof (rxq->rx_ring[0]) * EM_MAX_RING_DESC; if ((rz = ring_dma_zone_reserve(dev, "rx_ring", queue_idx, rsize, socket_id)) == NULL) return (-ENOMEM); /* Allocate the RX queue data structure. */ if ((rxq = rte_zmalloc("ethdev RX queue", sizeof(*rxq), RTE_CACHE_LINE_SIZE)) == NULL) return (-ENOMEM); /* Allocate software ring. */ if ((rxq->sw_ring = rte_zmalloc("rxq->sw_ring", sizeof (rxq->sw_ring[0]) * nb_desc, RTE_CACHE_LINE_SIZE)) == NULL) { em_rx_queue_release(rxq); return (-ENOMEM); } rxq->mb_pool = mp; rxq->nb_rx_desc = nb_desc; rxq->pthresh = rx_conf->rx_thresh.pthresh; rxq->hthresh = rx_conf->rx_thresh.hthresh; rxq->wthresh = rx_conf->rx_thresh.wthresh; rxq->rx_free_thresh = rx_conf->rx_free_thresh; rxq->queue_id = queue_idx; rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(queue_idx)); rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(queue_idx)); #ifndef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = (uint64_t) rz->phys_addr; #else rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); #endif rxq->rx_ring = (struct e1000_rx_desc *) rz->addr; PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, rxq->sw_ring, rxq->rx_ring, rxq->rx_ring_phys_addr); dev->data->rx_queues[queue_idx] = rxq; em_reset_rx_queue(rxq); return (0); } uint32_t eth_em_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { #define EM_RXQ_SCAN_INTERVAL 4 volatile struct e1000_rx_desc *rxdp; struct em_rx_queue *rxq; uint32_t desc = 0; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_RX_LOG(DEBUG, "Invalid RX queue_id=%d", rx_queue_id); return 0; } rxq = dev->data->rx_queues[rx_queue_id]; rxdp = &(rxq->rx_ring[rxq->rx_tail]); while ((desc < rxq->nb_rx_desc) && (rxdp->status & E1000_RXD_STAT_DD)) { desc += EM_RXQ_SCAN_INTERVAL; rxdp += EM_RXQ_SCAN_INTERVAL; if (rxq->rx_tail + desc >= rxq->nb_rx_desc) rxdp = &(rxq->rx_ring[rxq->rx_tail + desc - rxq->nb_rx_desc]); } return desc; } int eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset) { volatile struct e1000_rx_desc *rxdp; struct em_rx_queue *rxq = rx_queue; uint32_t desc; if (unlikely(offset >= rxq->nb_rx_desc)) return 0; desc = rxq->rx_tail + offset; if (desc >= rxq->nb_rx_desc) desc -= rxq->nb_rx_desc; rxdp = &rxq->rx_ring[desc]; return !!(rxdp->status & E1000_RXD_STAT_DD); } void em_dev_clear_queues(struct rte_eth_dev *dev) { uint16_t i; struct em_tx_queue *txq; struct em_rx_queue *rxq; for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; if (txq != NULL) { em_tx_queue_release_mbufs(txq); em_reset_tx_queue(txq); } } for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; if (rxq != NULL) { em_rx_queue_release_mbufs(rxq); em_reset_rx_queue(rxq); } } } void em_dev_free_queues(struct rte_eth_dev *dev) { uint16_t i; for (i = 0; i < dev->data->nb_rx_queues; i++) { eth_em_rx_queue_release(dev->data->rx_queues[i]); dev->data->rx_queues[i] = NULL; } dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) { eth_em_tx_queue_release(dev->data->tx_queues[i]); dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; } /* * Takes as input/output parameter RX buffer size. * Returns (BSIZE | BSEX | FLXBUF) fields of RCTL register. */ static uint32_t em_rctl_bsize(__rte_unused enum e1000_mac_type hwtyp, uint32_t *bufsz) { /* * For BSIZE & BSEX all configurable sizes are: * 16384: rctl |= (E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX); * 8192: rctl |= (E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX); * 4096: rctl |= (E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX); * 2048: rctl |= E1000_RCTL_SZ_2048; * 1024: rctl |= E1000_RCTL_SZ_1024; * 512: rctl |= E1000_RCTL_SZ_512; * 256: rctl |= E1000_RCTL_SZ_256; */ static const struct { uint32_t bufsz; uint32_t rctl; } bufsz_to_rctl[] = { {16384, (E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX)}, {8192, (E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX)}, {4096, (E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX)}, {2048, E1000_RCTL_SZ_2048}, {1024, E1000_RCTL_SZ_1024}, {512, E1000_RCTL_SZ_512}, {256, E1000_RCTL_SZ_256}, }; int i; uint32_t rctl_bsize; rctl_bsize = *bufsz; /* * Starting from 82571 it is possible to specify RX buffer size * by RCTL.FLXBUF. When this field is different from zero, the * RX buffer size = RCTL.FLXBUF * 1K * (e.g. t is possible to specify RX buffer size 1,2,...,15KB). * It is working ok on real HW, but by some reason doesn't work * on VMware emulated 82574L. * So for now, always use BSIZE/BSEX to setup RX buffer size. * If you don't plan to use it on VMware emulated 82574L and * would like to specify RX buffer size in 1K granularity, * uncomment the following lines: * *************************************************************** * if (hwtyp >= e1000_82571 && hwtyp <= e1000_82574 && * rctl_bsize >= EM_RCTL_FLXBUF_STEP) { * rctl_bsize /= EM_RCTL_FLXBUF_STEP; * *bufsz = rctl_bsize; * return (rctl_bsize << E1000_RCTL_FLXBUF_SHIFT & * E1000_RCTL_FLXBUF_MASK); * } * *************************************************************** */ for (i = 0; i != sizeof(bufsz_to_rctl) / sizeof(bufsz_to_rctl[0]); i++) { if (rctl_bsize >= bufsz_to_rctl[i].bufsz) { *bufsz = bufsz_to_rctl[i].bufsz; return (bufsz_to_rctl[i].rctl); } } /* Should never happen. */ return (-EINVAL); } static int em_alloc_rx_queue_mbufs(struct em_rx_queue *rxq) { struct em_rx_entry *rxe = rxq->sw_ring; uint64_t dma_addr; unsigned i; static const struct e1000_rx_desc rxd_init = { .buffer_addr = 0, }; /* Initialize software ring entries */ for (i = 0; i < rxq->nb_rx_desc; i++) { volatile struct e1000_rx_desc *rxd; struct rte_mbuf *mbuf = rte_rxmbuf_alloc(rxq->mb_pool); if (mbuf == NULL) { PMD_INIT_LOG(ERR, "RX mbuf alloc failed " "queue_id=%hu", rxq->queue_id); return (-ENOMEM); } dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf)); /* Clear HW ring memory */ rxq->rx_ring[i] = rxd_init; rxd = &rxq->rx_ring[i]; rxd->buffer_addr = dma_addr; rxe[i].mbuf = mbuf; } return 0; } /********************************************************************* * * Enable receive unit. * **********************************************************************/ int eth_em_rx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct em_rx_queue *rxq; uint32_t rctl; uint32_t rfctl; uint32_t rxcsum; uint32_t rctl_bsize; uint16_t i; int ret; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Make sure receives are disabled while setting * up the descriptor ring. */ rctl = E1000_READ_REG(hw, E1000_RCTL); E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); rfctl = E1000_READ_REG(hw, E1000_RFCTL); /* Disable extended descriptor type. */ rfctl &= ~E1000_RFCTL_EXTEN; /* Disable accelerated acknowledge */ if (hw->mac.type == e1000_82574) rfctl |= E1000_RFCTL_ACK_DIS; E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); /* * XXX TEMPORARY WORKAROUND: on some systems with 82573 * long latencies are observed, like Lenovo X60. This * change eliminates the problem, but since having positive * values in RDTR is a known source of problems on other * platforms another solution is being sought. */ if (hw->mac.type == e1000_82573) E1000_WRITE_REG(hw, E1000_RDTR, 0x20); dev->rx_pkt_burst = (eth_rx_burst_t)eth_em_recv_pkts; /* Determine RX bufsize. */ rctl_bsize = EM_MAX_BUF_SIZE; for (i = 0; i < dev->data->nb_rx_queues; i++) { uint32_t buf_size; rxq = dev->data->rx_queues[i]; buf_size = rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM; rctl_bsize = RTE_MIN(rctl_bsize, buf_size); } rctl |= em_rctl_bsize(hw->mac.type, &rctl_bsize); /* Configure and enable each RX queue. */ for (i = 0; i < dev->data->nb_rx_queues; i++) { uint64_t bus_addr; uint32_t rxdctl; rxq = dev->data->rx_queues[i]; /* Allocate buffers for descriptor rings and setup queue */ ret = em_alloc_rx_queue_mbufs(rxq); if (ret) return ret; /* * Reset crc_len in case it was changed after queue setup by a * call to configure */ rxq->crc_len = (uint8_t)(dev->data->dev_conf.rxmode.hw_strip_crc ? 0 : ETHER_CRC_LEN); bus_addr = rxq->rx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_RDLEN(i), rxq->nb_rx_desc * sizeof(*rxq->rx_ring)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), (uint32_t)bus_addr); E1000_WRITE_REG(hw, E1000_RDH(i), 0); E1000_WRITE_REG(hw, E1000_RDT(i), rxq->nb_rx_desc - 1); rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); rxdctl &= 0xFE000000; rxdctl |= rxq->pthresh & 0x3F; rxdctl |= (rxq->hthresh & 0x3F) << 8; rxdctl |= (rxq->wthresh & 0x3F) << 16; rxdctl |= E1000_RXDCTL_GRAN; E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); /* * Due to EM devices not having any sort of hardware * limit for packet length, jumbo frame of any size * can be accepted, thus we have to enable scattered * rx if jumbo frames are enabled (or if buffer size * is too small to accommodate non-jumbo packets) * to avoid splitting packets that don't fit into * one buffer. */ if (dev->data->dev_conf.rxmode.jumbo_frame || rctl_bsize < ETHER_MAX_LEN) { if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = (eth_rx_burst_t)eth_em_recv_scattered_pkts; dev->data->scattered_rx = 1; } } if (dev->data->dev_conf.rxmode.enable_scatter) { if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_em_recv_scattered_pkts; dev->data->scattered_rx = 1; } /* * Setup the Checksum Register. * Receive Full-Packet Checksum Offload is mutually exclusive with RSS. */ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); if (dev->data->dev_conf.rxmode.hw_ip_checksum) rxcsum |= E1000_RXCSUM_IPOFL; else rxcsum &= ~E1000_RXCSUM_IPOFL; E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* No MRQ or RSS support for now */ /* Set early receive threshold on appropriate hw */ if ((hw->mac.type == e1000_ich9lan || hw->mac.type == e1000_pch2lan || hw->mac.type == e1000_ich10lan) && dev->data->dev_conf.rxmode.jumbo_frame == 1) { u32 rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0)); E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); E1000_WRITE_REG(hw, E1000_ERT, 0x100 | (1 << 13)); } if (hw->mac.type == e1000_pch2lan) { if (dev->data->dev_conf.rxmode.jumbo_frame == 1) e1000_lv_jumbo_workaround_ich8lan(hw, TRUE); else e1000_lv_jumbo_workaround_ich8lan(hw, FALSE); } /* Setup the Receive Control Register. */ if (dev->data->dev_conf.rxmode.hw_strip_crc) rctl |= E1000_RCTL_SECRC; /* Strip Ethernet CRC. */ else rctl &= ~E1000_RCTL_SECRC; /* Do not Strip Ethernet CRC. */ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); /* Make sure VLAN Filters are off. */ rctl &= ~E1000_RCTL_VFE; /* Don't store bad packets. */ rctl &= ~E1000_RCTL_SBP; /* Legacy descriptor type. */ rctl &= ~E1000_RCTL_DTYP_MASK; /* * Configure support of jumbo frames, if any. */ if (dev->data->dev_conf.rxmode.jumbo_frame == 1) rctl |= E1000_RCTL_LPE; else rctl &= ~E1000_RCTL_LPE; /* Enable Receives. */ E1000_WRITE_REG(hw, E1000_RCTL, rctl); return 0; } /********************************************************************* * * Enable transmit unit. * **********************************************************************/ void eth_em_tx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct em_tx_queue *txq; uint32_t tctl; uint32_t txdctl; uint16_t i; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Setup the Base and Length of the Tx Descriptor Rings. */ for (i = 0; i < dev->data->nb_tx_queues; i++) { uint64_t bus_addr; txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_TDLEN(i), txq->nb_tx_desc * sizeof(*txq->tx_ring)); E1000_WRITE_REG(hw, E1000_TDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_TDBAL(i), (uint32_t)bus_addr); /* Setup the HW Tx Head and Tail descriptor pointers. */ E1000_WRITE_REG(hw, E1000_TDT(i), 0); E1000_WRITE_REG(hw, E1000_TDH(i), 0); /* Setup Transmit threshold registers. */ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(i)); /* * bit 22 is reserved, on some models should always be 0, * on others - always 1. */ txdctl &= E1000_TXDCTL_COUNT_DESC; txdctl |= txq->pthresh & 0x3F; txdctl |= (txq->hthresh & 0x3F) << 8; txdctl |= (txq->wthresh & 0x3F) << 16; txdctl |= E1000_TXDCTL_GRAN; E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); } /* Program the Transmit Control Register. */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(hw, E1000_TCTL, tctl); } ================================================ FILE: drivers/net/e1000/igb_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e1000_logs.h" #include "base/e1000_api.h" #include "e1000_ethdev.h" #include "igb_regs.h" /* * Default values for port configuration */ #define IGB_DEFAULT_RX_FREE_THRESH 32 #define IGB_DEFAULT_RX_PTHRESH 8 #define IGB_DEFAULT_RX_HTHRESH 8 #define IGB_DEFAULT_RX_WTHRESH 0 #define IGB_DEFAULT_TX_PTHRESH 32 #define IGB_DEFAULT_TX_HTHRESH 0 #define IGB_DEFAULT_TX_WTHRESH 0 #define IGB_HKEY_MAX_INDEX 10 /* Bit shift and mask */ #define IGB_4_BIT_WIDTH (CHAR_BIT / 2) #define IGB_4_BIT_MASK RTE_LEN2MASK(IGB_4_BIT_WIDTH, uint8_t) #define IGB_8_BIT_WIDTH CHAR_BIT #define IGB_8_BIT_MASK UINT8_MAX /* Additional timesync values. */ #define E1000_ETQF_FILTER_1588 3 #define E1000_TIMINCA_INCVALUE 16000000 #define E1000_TIMINCA_INIT ((0x02 << E1000_TIMINCA_16NS_SHIFT) \ | E1000_TIMINCA_INCVALUE) #define E1000_TSAUXC_DISABLE_SYSTIME 0x80000000 static int eth_igb_configure(struct rte_eth_dev *dev); static int eth_igb_start(struct rte_eth_dev *dev); static void eth_igb_stop(struct rte_eth_dev *dev); static void eth_igb_close(struct rte_eth_dev *dev); static void eth_igb_promiscuous_enable(struct rte_eth_dev *dev); static void eth_igb_promiscuous_disable(struct rte_eth_dev *dev); static void eth_igb_allmulticast_enable(struct rte_eth_dev *dev); static void eth_igb_allmulticast_disable(struct rte_eth_dev *dev); static int eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete); static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static void eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev); #ifdef RTE_NEXT_ABI static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev); #endif static int eth_igb_interrupt_get_status(struct rte_eth_dev *dev); static int eth_igb_interrupt_action(struct rte_eth_dev *dev); static void eth_igb_interrupt_handler(struct rte_intr_handle *handle, void *param); static int igb_hardware_init(struct e1000_hw *hw); static void igb_hw_control_acquire(struct e1000_hw *hw); static void igb_hw_control_release(struct e1000_hw *hw); static void igb_init_manageability(struct e1000_hw *hw); static void igb_release_manageability(struct e1000_hw *hw); static int eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev); static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev); static void igb_vlan_hw_strip_enable(struct rte_eth_dev *dev); static void igb_vlan_hw_strip_disable(struct rte_eth_dev *dev); static void igb_vlan_hw_extend_enable(struct rte_eth_dev *dev); static void igb_vlan_hw_extend_disable(struct rte_eth_dev *dev); static int eth_igb_led_on(struct rte_eth_dev *dev); static int eth_igb_led_off(struct rte_eth_dev *dev); static void igb_intr_disable(struct e1000_hw *hw); static int igb_get_rx_buffer_size(struct e1000_hw *hw); static void eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index); static void eth_igb_default_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *addr); static void igbvf_intr_disable(struct e1000_hw *hw); static int igbvf_dev_configure(struct rte_eth_dev *dev); static int igbvf_dev_start(struct rte_eth_dev *dev); static void igbvf_dev_stop(struct rte_eth_dev *dev); static void igbvf_dev_close(struct rte_eth_dev *dev); static int eth_igbvf_link_update(struct e1000_hw *hw); static void eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static void eth_igbvf_stats_reset(struct rte_eth_dev *dev); static int igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on); static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on); static void igbvf_default_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *addr); static int igbvf_get_reg_length(struct rte_eth_dev *dev); static int igbvf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); static int eth_igb_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int eth_igb_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int eth_igb_syn_filter_set(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter, bool add); static int eth_igb_syn_filter_get(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter); static int eth_igb_syn_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int igb_add_2tuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter); static int igb_remove_2tuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter); static int eth_igb_add_del_flex_filter(struct rte_eth_dev *dev, struct rte_eth_flex_filter *filter, bool add); static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, struct rte_eth_flex_filter *filter); static int eth_igb_flex_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter); static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter); static int igb_add_del_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *filter, bool add); static int igb_get_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *filter); static int igb_ntuple_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int igb_add_del_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter, bool add); static int igb_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int igb_get_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter); static int eth_igb_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); static int eth_igb_get_reg_length(struct rte_eth_dev *dev); static int eth_igb_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); static int eth_igb_get_eeprom_length(struct rte_eth_dev *dev); static int eth_igb_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); static int eth_igb_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); static int igb_timesync_enable(struct rte_eth_dev *dev); static int igb_timesync_disable(struct rte_eth_dev *dev); static int igb_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags); static int igb_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp); #ifdef RTE_NEXT_ABI static int eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id); static int eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); static void eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector); static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector, uint8_t index, uint8_t offset); #endif static void eth_igb_configure_msix_intr(struct rte_eth_dev *dev); /* * Define VF Stats MACRO for Non "cleared on read" register */ #define UPDATE_VF_STAT(reg, last, cur) \ { \ u32 latest = E1000_READ_REG(hw, reg); \ cur += latest - last; \ last = latest; \ } #define IGB_FC_PAUSE_TIME 0x0680 #define IGB_LINK_UPDATE_CHECK_TIMEOUT 90 /* 9s */ #define IGB_LINK_UPDATE_CHECK_INTERVAL 100 /* ms */ #define IGBVF_PMD_NAME "rte_igbvf_pmd" /* PMD name */ static enum e1000_fc_mode igb_fc_setting = e1000_fc_full; /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_igb_map[] = { #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" {0}, }; /* * The set of PCI devices this driver supports (for 82576&I350 VF) */ static const struct rte_pci_id pci_id_igbvf_map[] = { #define RTE_PCI_DEV_ID_DECL_IGBVF(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" {0}, }; static const struct eth_dev_ops eth_igb_ops = { .dev_configure = eth_igb_configure, .dev_start = eth_igb_start, .dev_stop = eth_igb_stop, .dev_close = eth_igb_close, .promiscuous_enable = eth_igb_promiscuous_enable, .promiscuous_disable = eth_igb_promiscuous_disable, .allmulticast_enable = eth_igb_allmulticast_enable, .allmulticast_disable = eth_igb_allmulticast_disable, .link_update = eth_igb_link_update, .stats_get = eth_igb_stats_get, .stats_reset = eth_igb_stats_reset, .dev_infos_get = eth_igb_infos_get, .mtu_set = eth_igb_mtu_set, .vlan_filter_set = eth_igb_vlan_filter_set, .vlan_tpid_set = eth_igb_vlan_tpid_set, .vlan_offload_set = eth_igb_vlan_offload_set, .rx_queue_setup = eth_igb_rx_queue_setup, #ifdef RTE_NEXT_ABI .rx_queue_intr_enable = eth_igb_rx_queue_intr_enable, .rx_queue_intr_disable = eth_igb_rx_queue_intr_disable, #endif .rx_queue_release = eth_igb_rx_queue_release, .rx_queue_count = eth_igb_rx_queue_count, .rx_descriptor_done = eth_igb_rx_descriptor_done, .tx_queue_setup = eth_igb_tx_queue_setup, .tx_queue_release = eth_igb_tx_queue_release, .dev_led_on = eth_igb_led_on, .dev_led_off = eth_igb_led_off, .flow_ctrl_get = eth_igb_flow_ctrl_get, .flow_ctrl_set = eth_igb_flow_ctrl_set, .mac_addr_add = eth_igb_rar_set, .mac_addr_remove = eth_igb_rar_clear, .mac_addr_set = eth_igb_default_mac_addr_set, .reta_update = eth_igb_rss_reta_update, .reta_query = eth_igb_rss_reta_query, .rss_hash_update = eth_igb_rss_hash_update, .rss_hash_conf_get = eth_igb_rss_hash_conf_get, .filter_ctrl = eth_igb_filter_ctrl, .set_mc_addr_list = eth_igb_set_mc_addr_list, .timesync_enable = igb_timesync_enable, .timesync_disable = igb_timesync_disable, .timesync_read_rx_timestamp = igb_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = igb_timesync_read_tx_timestamp, .get_reg_length = eth_igb_get_reg_length, .get_reg = eth_igb_get_regs, .get_eeprom_length = eth_igb_get_eeprom_length, .get_eeprom = eth_igb_get_eeprom, .set_eeprom = eth_igb_set_eeprom, }; /* * dev_ops for virtual function, bare necessities for basic vf * operation have been implemented */ static const struct eth_dev_ops igbvf_eth_dev_ops = { .dev_configure = igbvf_dev_configure, .dev_start = igbvf_dev_start, .dev_stop = igbvf_dev_stop, .dev_close = igbvf_dev_close, .link_update = eth_igb_link_update, .stats_get = eth_igbvf_stats_get, .stats_reset = eth_igbvf_stats_reset, .vlan_filter_set = igbvf_vlan_filter_set, .dev_infos_get = eth_igbvf_infos_get, .rx_queue_setup = eth_igb_rx_queue_setup, .rx_queue_release = eth_igb_rx_queue_release, .tx_queue_setup = eth_igb_tx_queue_setup, .tx_queue_release = eth_igb_tx_queue_release, .set_mc_addr_list = eth_igb_set_mc_addr_list, .mac_addr_set = igbvf_default_mac_addr_set, .get_reg_length = igbvf_get_reg_length, .get_reg = igbvf_get_regs, }; /** * Atomically reads the link status information from global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_igb_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /** * Atomically writes the link status information into global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_igb_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static inline void igb_intr_enable(struct rte_eth_dev *dev) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); E1000_WRITE_REG(hw, E1000_IMS, intr->mask); E1000_WRITE_FLUSH(hw); } static void igb_intr_disable(struct e1000_hw *hw) { E1000_WRITE_REG(hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(hw); } static inline int32_t igb_pf_reset_hw(struct e1000_hw *hw) { uint32_t ctrl_ext; int32_t status; status = e1000_reset_hw(hw); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext |= E1000_CTRL_EXT_PFRSTD; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); return status; } static void igb_identify_hardware(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); hw->vendor_id = dev->pci_dev->id.vendor_id; hw->device_id = dev->pci_dev->id.device_id; hw->subsystem_vendor_id = dev->pci_dev->id.subsystem_vendor_id; hw->subsystem_device_id = dev->pci_dev->id.subsystem_device_id; e1000_set_mac_type(hw); /* need to check if it is a vf device below */ } static int igb_reset_swfw_lock(struct e1000_hw *hw) { int ret_val; /* * Do mac ops initialization manually here, since we will need * some function pointers set by this call. */ ret_val = e1000_init_mac_params(hw); if (ret_val) return ret_val; /* * SMBI lock should not fail in this early stage. If this is the case, * it is due to an improper exit of the application. * So force the release of the faulty lock. */ if (e1000_get_hw_semaphore_generic(hw) < 0) { PMD_DRV_LOG(DEBUG, "SMBI lock released"); } e1000_put_hw_semaphore_generic(hw); if (hw->mac.ops.acquire_swfw_sync != NULL) { uint16_t mask; /* * Phy lock should not fail in this early stage. If this is the case, * it is due to an improper exit of the application. * So force the release of the faulty lock. */ mask = E1000_SWFW_PHY0_SM << hw->bus.func; if (hw->bus.func > E1000_FUNC_1) mask <<= 2; if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) { PMD_DRV_LOG(DEBUG, "SWFW phy%d lock released", hw->bus.func); } hw->mac.ops.release_swfw_sync(hw, mask); /* * This one is more tricky since it is common to all ports; but * swfw_sync retries last long enough (1s) to be almost sure that if * lock can not be taken it is due to an improper lock of the * semaphore. */ mask = E1000_SWFW_EEP_SM; if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) { PMD_DRV_LOG(DEBUG, "SWFW common locks released"); } hw->mac.ops.release_swfw_sync(hw, mask); } return E1000_SUCCESS; } static int eth_igb_dev_init(struct rte_eth_dev *eth_dev) { int error = 0; struct rte_pci_device *pci_dev; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); uint32_t ctrl_ext; pci_dev = eth_dev->pci_dev; eth_dev->dev_ops = ð_igb_ops; eth_dev->rx_pkt_burst = ð_igb_recv_pkts; eth_dev->tx_pkt_burst = ð_igb_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX function */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (eth_dev->data->scattered_rx) eth_dev->rx_pkt_burst = ð_igb_recv_scattered_pkts; return 0; } hw->hw_addr= (void *)pci_dev->mem_resource[0].addr; igb_identify_hardware(eth_dev); if (e1000_setup_init_funcs(hw, FALSE) != E1000_SUCCESS) { error = -EIO; goto err_late; } e1000_get_bus_info(hw); /* Reset any pending lock */ if (igb_reset_swfw_lock(hw) != E1000_SUCCESS) { error = -EIO; goto err_late; } /* Finish initialization */ if (e1000_setup_init_funcs(hw, TRUE) != E1000_SUCCESS) { error = -EIO; goto err_late; } hw->mac.autoneg = 1; hw->phy.autoneg_wait_to_complete = 0; hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { hw->phy.mdix = 0; /* AUTO_ALL_MODES */ hw->phy.disable_polarity_correction = 0; hw->phy.ms_type = e1000_ms_hw_default; } /* * Start from a known state, this is important in reading the nvm * and mac from that. */ igb_pf_reset_hw(hw); /* Make sure we have a good EEPROM before we read from it */ if (e1000_validate_nvm_checksum(hw) < 0) { /* * Some PCI-E parts fail the first check due to * the link being in sleep state, call it again, * if it fails a second time its a real issue. */ if (e1000_validate_nvm_checksum(hw) < 0) { PMD_INIT_LOG(ERR, "EEPROM checksum invalid"); error = -EIO; goto err_late; } } /* Read the permanent MAC address out of the EEPROM */ if (e1000_read_mac_addr(hw) != 0) { PMD_INIT_LOG(ERR, "EEPROM error while reading MAC address"); error = -EIO; goto err_late; } /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("e1000", ETHER_ADDR_LEN * hw->mac.rar_entry_count, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to " "store MAC addresses", ETHER_ADDR_LEN * hw->mac.rar_entry_count); error = -ENOMEM; goto err_late; } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *)hw->mac.addr, ð_dev->data->mac_addrs[0]); /* initialize the vfta */ memset(shadow_vfta, 0, sizeof(*shadow_vfta)); /* Now initialize the hardware */ if (igb_hardware_init(hw) != 0) { PMD_INIT_LOG(ERR, "Hardware initialization failed"); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; error = -ENODEV; goto err_late; } hw->mac.get_link_status = 1; adapter->stopped = 0; /* Indicate SOL/IDER usage */ if (e1000_check_reset_block(hw) < 0) { PMD_INIT_LOG(ERR, "PHY reset is blocked due to" "SOL/IDER session"); } /* initialize PF if max_vfs not zero */ igb_pf_host_init(eth_dev); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext |= E1000_CTRL_EXT_PFRSTD; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); PMD_INIT_LOG(DEBUG, "port_id %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); /* enable support intr */ igb_intr_enable(eth_dev); TAILQ_INIT(&filter_info->flex_list); filter_info->flex_mask = 0; TAILQ_INIT(&filter_info->twotuple_list); filter_info->twotuple_mask = 0; TAILQ_INIT(&filter_info->fivetuple_list); filter_info->fivetuple_mask = 0; return 0; err_late: igb_hw_control_release(hw); return (error); } static int eth_igb_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct e1000_hw *hw; struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); pci_dev = eth_dev->pci_dev; if (adapter->stopped == 0) eth_igb_close(eth_dev); eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; /* Reset any pending lock */ igb_reset_swfw_lock(hw); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; /* uninitialize PF if max_vfs not zero */ igb_pf_host_uninit(eth_dev); /* disable uio intr before callback unregister */ rte_intr_disable(&(pci_dev->intr_handle)); rte_intr_callback_unregister(&(pci_dev->intr_handle), eth_igb_interrupt_handler, (void *)eth_dev); return 0; } /* * Virtual Function device init */ static int eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); int diag; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &igbvf_eth_dev_ops; eth_dev->rx_pkt_burst = ð_igb_recv_pkts; eth_dev->tx_pkt_burst = ð_igb_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX function */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (eth_dev->data->scattered_rx) eth_dev->rx_pkt_burst = ð_igb_recv_scattered_pkts; return 0; } pci_dev = eth_dev->pci_dev; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; adapter->stopped = 0; /* Initialize the shared code (base driver) */ diag = e1000_setup_init_funcs(hw, TRUE); if (diag != 0) { PMD_INIT_LOG(ERR, "Shared code init failed for igbvf: %d", diag); return -EIO; } /* init_mailbox_params */ hw->mbx.ops.init_params(hw); /* Disable the interrupts for VF */ igbvf_intr_disable(hw); diag = hw->mac.ops.reset_hw(hw); /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("igbvf", ETHER_ADDR_LEN * hw->mac.rar_entry_count, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to store MAC " "addresses", ETHER_ADDR_LEN * hw->mac.rar_entry_count); return -ENOMEM; } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *) hw->mac.perm_addr, ð_dev->data->mac_addrs[0]); PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x " "mac.type=%s", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id, "igb_mac_82576_vf"); return 0; } static int eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev) { struct e1000_adapter *adapter = E1000_DEV_PRIVATE(eth_dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; if (adapter->stopped == 0) igbvf_dev_close(eth_dev); eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; return 0; } static struct eth_driver rte_igb_pmd = { .pci_drv = { .name = "rte_igb_pmd", .id_table = pci_id_igb_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_igb_dev_init, .eth_dev_uninit = eth_igb_dev_uninit, .dev_private_size = sizeof(struct e1000_adapter), }; /* * virtual function driver struct */ static struct eth_driver rte_igbvf_pmd = { .pci_drv = { .name = "rte_igbvf_pmd", .id_table = pci_id_igbvf_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_igbvf_dev_init, .eth_dev_uninit = eth_igbvf_dev_uninit, .dev_private_size = sizeof(struct e1000_adapter), }; static int rte_igb_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { rte_eth_driver_register(&rte_igb_pmd); return 0; } static void igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* RCTL: enable VLAN filter since VMDq always use VLAN filter */ uint32_t rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } /* * VF Driver initialization routine. * Invoked one at EAL init time. * Register itself as the [Virtual Poll Mode] Driver of PCI IGB devices. */ static int rte_igbvf_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_igbvf_pmd); return (0); } static int eth_igb_configure(struct rte_eth_dev *dev) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); intr->flags |= E1000_FLAG_NEED_LINK_UPDATE; PMD_INIT_FUNC_TRACE(); return (0); } static int eth_igb_start(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; int ret, mask; #ifdef RTE_NEXT_ABI uint32_t intr_vector = 0; #endif uint32_t ctrl_ext; PMD_INIT_FUNC_TRACE(); /* Power up the phy. Needed to make the link go Up */ e1000_power_up_phy(hw); /* * Packet Buffer Allocation (PBA) * Writing PBA sets the receive portion of the buffer * the remainder is used for the transmit buffer. */ if (hw->mac.type == e1000_82575) { uint32_t pba; pba = E1000_PBA_32K; /* 32K for Rx, 16K for Tx */ E1000_WRITE_REG(hw, E1000_PBA, pba); } /* Put the address into the Receive Address Array */ e1000_rar_set(hw, hw->mac.addr, 0); /* Initialize the hardware */ if (igb_hardware_init(hw)) { PMD_INIT_LOG(ERR, "Unable to initialize the hardware"); return (-EIO); } adapter->stopped = 0; E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN << 16 | ETHER_TYPE_VLAN); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext |= E1000_CTRL_EXT_PFRSTD; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); /* configure PF module if SRIOV enabled */ igb_pf_host_configure(dev); #ifdef RTE_NEXT_ABI /* check and configure queue intr-vector mapping */ if (dev->data->dev_conf.intr_conf.rxq != 0) intr_vector = dev->data->nb_rx_queues; if (rte_intr_efd_enable(intr_handle, intr_vector)) return -1; if (rte_intr_dp_is_en(intr_handle)) { intr_handle->intr_vec = rte_zmalloc("intr_vec", dev->data->nb_rx_queues * sizeof(int), 0); if (intr_handle->intr_vec == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" " intr_vec\n", dev->data->nb_rx_queues); return -ENOMEM; } } #endif /* confiugre msix for rx interrupt */ eth_igb_configure_msix_intr(dev); /* Configure for OS presence */ igb_init_manageability(hw); eth_igb_tx_init(dev); /* This can fail when allocating mbufs for descriptor rings */ ret = eth_igb_rx_init(dev); if (ret) { PMD_INIT_LOG(ERR, "Unable to initialize RX hardware"); igb_dev_clear_queues(dev); return ret; } e1000_clear_hw_cntrs_base_generic(hw); /* * VLAN Offload Settings */ mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \ ETH_VLAN_EXTEND_MASK; eth_igb_vlan_offload_set(dev, mask); if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) { /* Enable VLAN filter since VMDq always use VLAN filter */ igb_vmdq_vlan_hw_filter_enable(dev); } if ((hw->mac.type == e1000_82576) || (hw->mac.type == e1000_82580) || (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { /* Configure EITR with the maximum possible value (0xFFFF) */ E1000_WRITE_REG(hw, E1000_EITR(0), 0xFFFF); } /* Setup link speed and duplex */ switch (dev->data->dev_conf.link_speed) { case ETH_LINK_SPEED_AUTONEG: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_HALF_DUPLEX; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_FULL_DUPLEX; else goto error_invalid_config; break; case ETH_LINK_SPEED_10: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_10_SPEED; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_10_HALF; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_10_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_100: if (dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) hw->phy.autoneg_advertised = E1000_ALL_100_SPEED; else if (dev->data->dev_conf.link_duplex == ETH_LINK_HALF_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_100_HALF; else if (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX) hw->phy.autoneg_advertised = ADVERTISE_100_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_1000: if ((dev->data->dev_conf.link_duplex == ETH_LINK_AUTONEG_DUPLEX) || (dev->data->dev_conf.link_duplex == ETH_LINK_FULL_DUPLEX)) hw->phy.autoneg_advertised = ADVERTISE_1000_FULL; else goto error_invalid_config; break; case ETH_LINK_SPEED_10000: default: goto error_invalid_config; } e1000_setup_link(hw); /* check if lsc interrupt feature is enabled */ if (dev->data->dev_conf.intr_conf.lsc != 0) { if (rte_intr_allow_others(intr_handle)) { rte_intr_callback_register(intr_handle, eth_igb_interrupt_handler, (void *)dev); eth_igb_lsc_interrupt_setup(dev); } else PMD_INIT_LOG(INFO, "lsc won't enable because of" " no intr multiplex\n"); } #ifdef RTE_NEXT_ABI /* check if rxq interrupt is enabled */ if (dev->data->dev_conf.intr_conf.rxq != 0) eth_igb_rxq_interrupt_setup(dev); #endif /* enable uio/vfio intr/eventfd mapping */ rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ igb_intr_enable(dev); PMD_INIT_LOG(DEBUG, "<<"); return (0); error_invalid_config: PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u", dev->data->dev_conf.link_speed, dev->data->dev_conf.link_duplex, dev->data->port_id); igb_dev_clear_queues(dev); return (-EINVAL); } /********************************************************************* * * This routine disables all traffic on the adapter by issuing a * global reset on the MAC. * **********************************************************************/ static void eth_igb_stop(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct rte_eth_link link; struct e1000_flex_filter *p_flex; struct e1000_5tuple_filter *p_5tuple, *p_5tuple_next; struct e1000_2tuple_filter *p_2tuple, *p_2tuple_next; struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; igb_intr_disable(hw); /* disable intr eventfd mapping */ rte_intr_disable(intr_handle); igb_pf_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); /* Set bit for Go Link disconnect */ if (hw->mac.type >= e1000_82580) { uint32_t phpm_reg; phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); phpm_reg |= E1000_82580_PM_GO_LINKD; E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); } /* Power down the phy. Needed to make the link go Down */ if (hw->phy.media_type == e1000_media_type_copper) e1000_power_down_phy(hw); else e1000_shutdown_fiber_serdes_link(hw); igb_dev_clear_queues(dev); /* clear the recorded link status */ memset(&link, 0, sizeof(link)); rte_igb_dev_atomic_write_link_status(dev, &link); /* Remove all flex filters of the device */ while ((p_flex = TAILQ_FIRST(&filter_info->flex_list))) { TAILQ_REMOVE(&filter_info->flex_list, p_flex, entries); rte_free(p_flex); } filter_info->flex_mask = 0; /* Remove all ntuple filters of the device */ for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list); p_5tuple != NULL; p_5tuple = p_5tuple_next) { p_5tuple_next = TAILQ_NEXT(p_5tuple, entries); TAILQ_REMOVE(&filter_info->fivetuple_list, p_5tuple, entries); rte_free(p_5tuple); } filter_info->fivetuple_mask = 0; for (p_2tuple = TAILQ_FIRST(&filter_info->twotuple_list); p_2tuple != NULL; p_2tuple = p_2tuple_next) { p_2tuple_next = TAILQ_NEXT(p_2tuple, entries); TAILQ_REMOVE(&filter_info->twotuple_list, p_2tuple, entries); rte_free(p_2tuple); } filter_info->twotuple_mask = 0; #ifdef RTE_NEXT_ABI /* Clean datapath event and queue/vec mapping */ rte_intr_efd_disable(intr_handle); if (intr_handle->intr_vec != NULL) { rte_free(intr_handle->intr_vec); intr_handle->intr_vec = NULL; } #endif } static void eth_igb_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); struct rte_eth_link link; #ifdef RTE_NEXT_ABI struct rte_pci_device *pci_dev; #endif eth_igb_stop(dev); adapter->stopped = 1; e1000_phy_hw_reset(hw); igb_release_manageability(hw); igb_hw_control_release(hw); /* Clear bit for Go Link disconnect */ if (hw->mac.type >= e1000_82580) { uint32_t phpm_reg; phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); phpm_reg &= ~E1000_82580_PM_GO_LINKD; E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); } igb_dev_free_queues(dev); #ifdef RTE_NEXT_ABI pci_dev = dev->pci_dev; if (pci_dev->intr_handle.intr_vec) { rte_free(pci_dev->intr_handle.intr_vec); pci_dev->intr_handle.intr_vec = NULL; } #endif memset(&link, 0, sizeof(link)); rte_igb_dev_atomic_write_link_status(dev, &link); } static int igb_get_rx_buffer_size(struct e1000_hw *hw) { uint32_t rx_buf_size; if (hw->mac.type == e1000_82576) { rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0xffff) << 10; } else if (hw->mac.type == e1000_82580 || hw->mac.type == e1000_i350) { /* PBS needs to be translated according to a lookup table */ rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0xf); rx_buf_size = (uint32_t) e1000_rxpbs_adjust_82580(rx_buf_size); rx_buf_size = (rx_buf_size << 10); } else if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) { rx_buf_size = (E1000_READ_REG(hw, E1000_RXPBS) & 0x3f) << 10; } else { rx_buf_size = (E1000_READ_REG(hw, E1000_PBA) & 0xffff) << 10; } return rx_buf_size; } /********************************************************************* * * Initialize the hardware * **********************************************************************/ static int igb_hardware_init(struct e1000_hw *hw) { uint32_t rx_buf_size; int diag; /* Let the firmware know the OS is in control */ igb_hw_control_acquire(hw); /* * These parameters control the automatic generation (Tx) and * response (Rx) to Ethernet PAUSE frames. * - High water mark should allow for at least two standard size (1518) * frames to be received after sending an XOFF. * - Low water mark works best when it is very near the high water mark. * This allows the receiver to restart by sending XON when it has * drained a bit. Here we use an arbitrary value of 1500 which will * restart after one full frame is pulled from the buffer. There * could be several smaller frames in the buffer and if so they will * not trigger the XON until their total number reduces the buffer * by 1500. * - The pause time is fairly large at 1000 x 512ns = 512 usec. */ rx_buf_size = igb_get_rx_buffer_size(hw); hw->fc.high_water = rx_buf_size - (ETHER_MAX_LEN * 2); hw->fc.low_water = hw->fc.high_water - 1500; hw->fc.pause_time = IGB_FC_PAUSE_TIME; hw->fc.send_xon = 1; /* Set Flow control, use the tunable location if sane */ if ((igb_fc_setting != e1000_fc_none) && (igb_fc_setting < 4)) hw->fc.requested_mode = igb_fc_setting; else hw->fc.requested_mode = e1000_fc_none; /* Issue a global reset */ igb_pf_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); diag = e1000_init_hw(hw); if (diag < 0) return (diag); E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN << 16 | ETHER_TYPE_VLAN); e1000_get_phy_info(hw); e1000_check_for_link(hw); return (0); } /* This function is based on igb_update_stats_counters() in igb/if_igb.c */ static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_hw_stats *stats = E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); int pause_frames; if(hw->phy.media_type == e1000_media_type_copper || (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { stats->symerrs += E1000_READ_REG(hw,E1000_SYMERRS); stats->sec += E1000_READ_REG(hw, E1000_SEC); } stats->crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); stats->mpc += E1000_READ_REG(hw, E1000_MPC); stats->scc += E1000_READ_REG(hw, E1000_SCC); stats->ecol += E1000_READ_REG(hw, E1000_ECOL); stats->mcc += E1000_READ_REG(hw, E1000_MCC); stats->latecol += E1000_READ_REG(hw, E1000_LATECOL); stats->colc += E1000_READ_REG(hw, E1000_COLC); stats->dc += E1000_READ_REG(hw, E1000_DC); stats->rlec += E1000_READ_REG(hw, E1000_RLEC); stats->xonrxc += E1000_READ_REG(hw, E1000_XONRXC); stats->xontxc += E1000_READ_REG(hw, E1000_XONTXC); /* ** For watchdog management we need to know if we have been ** paused during the last interval, so capture that here. */ pause_frames = E1000_READ_REG(hw, E1000_XOFFRXC); stats->xoffrxc += pause_frames; stats->xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC); stats->fcruc += E1000_READ_REG(hw, E1000_FCRUC); stats->prc64 += E1000_READ_REG(hw, E1000_PRC64); stats->prc127 += E1000_READ_REG(hw, E1000_PRC127); stats->prc255 += E1000_READ_REG(hw, E1000_PRC255); stats->prc511 += E1000_READ_REG(hw, E1000_PRC511); stats->prc1023 += E1000_READ_REG(hw, E1000_PRC1023); stats->prc1522 += E1000_READ_REG(hw, E1000_PRC1522); stats->gprc += E1000_READ_REG(hw, E1000_GPRC); stats->bprc += E1000_READ_REG(hw, E1000_BPRC); stats->mprc += E1000_READ_REG(hw, E1000_MPRC); stats->gptc += E1000_READ_REG(hw, E1000_GPTC); /* For the 64-bit byte counters the low dword must be read first. */ /* Both registers clear on the read of the high dword */ stats->gorc += E1000_READ_REG(hw, E1000_GORCL); stats->gorc += ((uint64_t)E1000_READ_REG(hw, E1000_GORCH) << 32); stats->gotc += E1000_READ_REG(hw, E1000_GOTCL); stats->gotc += ((uint64_t)E1000_READ_REG(hw, E1000_GOTCH) << 32); stats->rnbc += E1000_READ_REG(hw, E1000_RNBC); stats->ruc += E1000_READ_REG(hw, E1000_RUC); stats->rfc += E1000_READ_REG(hw, E1000_RFC); stats->roc += E1000_READ_REG(hw, E1000_ROC); stats->rjc += E1000_READ_REG(hw, E1000_RJC); stats->tor += E1000_READ_REG(hw, E1000_TORH); stats->tot += E1000_READ_REG(hw, E1000_TOTH); stats->tpr += E1000_READ_REG(hw, E1000_TPR); stats->tpt += E1000_READ_REG(hw, E1000_TPT); stats->ptc64 += E1000_READ_REG(hw, E1000_PTC64); stats->ptc127 += E1000_READ_REG(hw, E1000_PTC127); stats->ptc255 += E1000_READ_REG(hw, E1000_PTC255); stats->ptc511 += E1000_READ_REG(hw, E1000_PTC511); stats->ptc1023 += E1000_READ_REG(hw, E1000_PTC1023); stats->ptc1522 += E1000_READ_REG(hw, E1000_PTC1522); stats->mptc += E1000_READ_REG(hw, E1000_MPTC); stats->bptc += E1000_READ_REG(hw, E1000_BPTC); /* Interrupt Counts */ stats->iac += E1000_READ_REG(hw, E1000_IAC); stats->icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC); stats->icrxatc += E1000_READ_REG(hw, E1000_ICRXATC); stats->ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC); stats->ictxatc += E1000_READ_REG(hw, E1000_ICTXATC); stats->ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC); stats->ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC); stats->icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC); stats->icrxoc += E1000_READ_REG(hw, E1000_ICRXOC); /* Host to Card Statistics */ stats->cbtmpc += E1000_READ_REG(hw, E1000_CBTMPC); stats->htdpmc += E1000_READ_REG(hw, E1000_HTDPMC); stats->cbrdpc += E1000_READ_REG(hw, E1000_CBRDPC); stats->cbrmpc += E1000_READ_REG(hw, E1000_CBRMPC); stats->rpthc += E1000_READ_REG(hw, E1000_RPTHC); stats->hgptc += E1000_READ_REG(hw, E1000_HGPTC); stats->htcbdpc += E1000_READ_REG(hw, E1000_HTCBDPC); stats->hgorc += E1000_READ_REG(hw, E1000_HGORCL); stats->hgorc += ((uint64_t)E1000_READ_REG(hw, E1000_HGORCH) << 32); stats->hgotc += E1000_READ_REG(hw, E1000_HGOTCL); stats->hgotc += ((uint64_t)E1000_READ_REG(hw, E1000_HGOTCH) << 32); stats->lenerrs += E1000_READ_REG(hw, E1000_LENERRS); stats->scvpc += E1000_READ_REG(hw, E1000_SCVPC); stats->hrmpc += E1000_READ_REG(hw, E1000_HRMPC); stats->algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC); stats->rxerrc += E1000_READ_REG(hw, E1000_RXERRC); stats->tncrs += E1000_READ_REG(hw, E1000_TNCRS); stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR); stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC); stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC); if (rte_stats == NULL) return; /* Rx Errors */ rte_stats->ibadcrc = stats->crcerrs; rte_stats->ibadlen = stats->rlec + stats->ruc + stats->roc; rte_stats->imissed = stats->mpc; rte_stats->ierrors = rte_stats->ibadcrc + rte_stats->ibadlen + rte_stats->imissed + stats->rxerrc + stats->algnerrc + stats->cexterr; /* Tx Errors */ rte_stats->oerrors = stats->ecol + stats->latecol; /* XON/XOFF pause frames */ rte_stats->tx_pause_xon = stats->xontxc; rte_stats->rx_pause_xon = stats->xonrxc; rte_stats->tx_pause_xoff = stats->xofftxc; rte_stats->rx_pause_xoff = stats->xoffrxc; rte_stats->ipackets = stats->gprc; rte_stats->opackets = stats->gptc; rte_stats->ibytes = stats->gorc; rte_stats->obytes = stats->gotc; } static void eth_igb_stats_reset(struct rte_eth_dev *dev) { struct e1000_hw_stats *hw_stats = E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* HW registers are cleared on read */ eth_igb_stats_get(dev, NULL); /* Reset software totals */ memset(hw_stats, 0, sizeof(*hw_stats)); } static void eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*) E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* Good Rx packets, include VF loopback */ UPDATE_VF_STAT(E1000_VFGPRC, hw_stats->last_gprc, hw_stats->gprc); /* Good Rx octets, include VF loopback */ UPDATE_VF_STAT(E1000_VFGORC, hw_stats->last_gorc, hw_stats->gorc); /* Good Tx packets, include VF loopback */ UPDATE_VF_STAT(E1000_VFGPTC, hw_stats->last_gptc, hw_stats->gptc); /* Good Tx octets, include VF loopback */ UPDATE_VF_STAT(E1000_VFGOTC, hw_stats->last_gotc, hw_stats->gotc); /* Rx Multicst packets */ UPDATE_VF_STAT(E1000_VFMPRC, hw_stats->last_mprc, hw_stats->mprc); /* Good Rx loopback packets */ UPDATE_VF_STAT(E1000_VFGPRLBC, hw_stats->last_gprlbc, hw_stats->gprlbc); /* Good Rx loopback octets */ UPDATE_VF_STAT(E1000_VFGORLBC, hw_stats->last_gorlbc, hw_stats->gorlbc); /* Good Tx loopback packets */ UPDATE_VF_STAT(E1000_VFGPTLBC, hw_stats->last_gptlbc, hw_stats->gptlbc); /* Good Tx loopback octets */ UPDATE_VF_STAT(E1000_VFGOTLBC, hw_stats->last_gotlbc, hw_stats->gotlbc); if (rte_stats == NULL) return; rte_stats->ipackets = hw_stats->gprc; rte_stats->ibytes = hw_stats->gorc; rte_stats->opackets = hw_stats->gptc; rte_stats->obytes = hw_stats->gotc; rte_stats->imcasts = hw_stats->mprc; rte_stats->ilbpackets = hw_stats->gprlbc; rte_stats->ilbbytes = hw_stats->gorlbc; rte_stats->olbpackets = hw_stats->gptlbc; rte_stats->olbbytes = hw_stats->gotlbc; } static void eth_igbvf_stats_reset(struct rte_eth_dev *dev) { struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*) E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* Sync HW register to the last stats */ eth_igbvf_stats_get(dev, NULL); /* reset HW current stats*/ memset(&hw_stats->gprc, 0, sizeof(*hw_stats) - offsetof(struct e1000_vf_stats, gprc)); } static void eth_igb_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */ dev_info->max_rx_pktlen = 0x3FFF; /* See RLPML register. */ dev_info->max_mac_addrs = hw->mac.rar_entry_count; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM; switch (hw->mac.type) { case e1000_82575: dev_info->max_rx_queues = 4; dev_info->max_tx_queues = 4; dev_info->max_vmdq_pools = 0; break; case e1000_82576: dev_info->max_rx_queues = 16; dev_info->max_tx_queues = 16; dev_info->max_vmdq_pools = ETH_8_POOLS; dev_info->vmdq_queue_num = 16; break; case e1000_82580: dev_info->max_rx_queues = 8; dev_info->max_tx_queues = 8; dev_info->max_vmdq_pools = ETH_8_POOLS; dev_info->vmdq_queue_num = 8; break; case e1000_i350: dev_info->max_rx_queues = 8; dev_info->max_tx_queues = 8; dev_info->max_vmdq_pools = ETH_8_POOLS; dev_info->vmdq_queue_num = 8; break; case e1000_i354: dev_info->max_rx_queues = 8; dev_info->max_tx_queues = 8; break; case e1000_i210: dev_info->max_rx_queues = 4; dev_info->max_tx_queues = 4; dev_info->max_vmdq_pools = 0; break; case e1000_i211: dev_info->max_rx_queues = 2; dev_info->max_tx_queues = 2; dev_info->max_vmdq_pools = 0; break; default: /* Should not happen */ break; } dev_info->hash_key_size = IGB_HKEY_MAX_INDEX * sizeof(uint32_t); dev_info->reta_size = ETH_RSS_RETA_SIZE_128; dev_info->flow_type_rss_offloads = IGB_RSS_OFFLOAD_ALL; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = IGB_DEFAULT_RX_PTHRESH, .hthresh = IGB_DEFAULT_RX_HTHRESH, .wthresh = IGB_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = IGB_DEFAULT_TX_PTHRESH, .hthresh = IGB_DEFAULT_TX_HTHRESH, .wthresh = IGB_DEFAULT_TX_WTHRESH, }, .txq_flags = 0, }; } static void eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */ dev_info->max_rx_pktlen = 0x3FFF; /* See RLPML register. */ dev_info->max_mac_addrs = hw->mac.rar_entry_count; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM; switch (hw->mac.type) { case e1000_vfadapt: dev_info->max_rx_queues = 2; dev_info->max_tx_queues = 2; break; case e1000_vfadapt_i350: dev_info->max_rx_queues = 1; dev_info->max_tx_queues = 1; break; default: /* Should not happen */ break; } dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = IGB_DEFAULT_RX_PTHRESH, .hthresh = IGB_DEFAULT_RX_HTHRESH, .wthresh = IGB_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = IGB_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = IGB_DEFAULT_TX_PTHRESH, .hthresh = IGB_DEFAULT_TX_HTHRESH, .wthresh = IGB_DEFAULT_TX_WTHRESH, }, .txq_flags = 0, }; } /* return 0 means link status changed, -1 means not changed */ static int eth_igb_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_link link, old; int link_check, count; link_check = 0; hw->mac.get_link_status = 1; /* possible wait-to-complete in up to 9 seconds */ for (count = 0; count < IGB_LINK_UPDATE_CHECK_TIMEOUT; count ++) { /* Read the real link status */ switch (hw->phy.media_type) { case e1000_media_type_copper: /* Do the work to read phy */ e1000_check_for_link(hw); link_check = !hw->mac.get_link_status; break; case e1000_media_type_fiber: e1000_check_for_link(hw); link_check = (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU); break; case e1000_media_type_internal_serdes: e1000_check_for_link(hw); link_check = hw->mac.serdes_has_link; break; /* VF device is type_unknown */ case e1000_media_type_unknown: eth_igbvf_link_update(hw); link_check = !hw->mac.get_link_status; break; default: break; } if (link_check || wait_to_complete == 0) break; rte_delay_ms(IGB_LINK_UPDATE_CHECK_INTERVAL); } memset(&link, 0, sizeof(link)); rte_igb_dev_atomic_read_link_status(dev, &link); old = link; /* Now we check if a transition has happened */ if (link_check) { hw->mac.ops.get_link_up_info(hw, &link.link_speed, &link.link_duplex); link.link_status = 1; } else if (!link_check) { link.link_speed = 0; link.link_duplex = 0; link.link_status = 0; } rte_igb_dev_atomic_write_link_status(dev, &link); /* not changed */ if (old.link_status == link.link_status) return -1; /* changed */ return 0; } /* * igb_hw_control_acquire sets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means * that the driver is loaded. */ static void igb_hw_control_acquire(struct e1000_hw *hw) { uint32_t ctrl_ext; /* Let firmware know the driver has taken over */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); } /* * igb_hw_control_release resets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. */ static void igb_hw_control_release(struct e1000_hw *hw) { uint32_t ctrl_ext; /* Let firmware taken over control of h/w */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); } /* * Bit of a misnomer, what this really means is * to enable OS management of the system... aka * to disable special hardware management features. */ static void igb_init_manageability(struct e1000_hw *hw) { if (e1000_enable_mng_pass_thru(hw)) { uint32_t manc2h = E1000_READ_REG(hw, E1000_MANC2H); uint32_t manc = E1000_READ_REG(hw, E1000_MANC); /* disable hardware interception of ARP */ manc &= ~(E1000_MANC_ARP_EN); /* enable receiving management packets to the host */ manc |= E1000_MANC_EN_MNG2HOST; manc2h |= 1 << 5; /* Mng Port 623 */ manc2h |= 1 << 6; /* Mng Port 664 */ E1000_WRITE_REG(hw, E1000_MANC2H, manc2h); E1000_WRITE_REG(hw, E1000_MANC, manc); } } static void igb_release_manageability(struct e1000_hw *hw) { if (e1000_enable_mng_pass_thru(hw)) { uint32_t manc = E1000_READ_REG(hw, E1000_MANC); manc |= E1000_MANC_ARP_EN; manc &= ~E1000_MANC_EN_MNG2HOST; E1000_WRITE_REG(hw, E1000_MANC, manc); } } static void eth_igb_promiscuous_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_igb_promiscuous_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= (~E1000_RCTL_UPE); if (dev->data->all_multicast == 1) rctl |= E1000_RCTL_MPE; else rctl &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_igb_allmulticast_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_MPE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static void eth_igb_allmulticast_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rctl; if (dev->data->promiscuous == 1) return; /* must remain in all_multicast mode */ rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= (~E1000_RCTL_MPE); E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vfta; uint32_t vid_idx; uint32_t vid_bit; vid_idx = (uint32_t) ((vlan_id >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK); vid_bit = (uint32_t) (1 << (vlan_id & E1000_VFTA_ENTRY_BIT_SHIFT_MASK)); vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, vid_idx); if (on) vfta |= vid_bit; else vfta &= ~vid_bit; E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, vid_idx, vfta); /* update local VFTA copy */ shadow_vfta->vfta[vid_idx] = vfta; return 0; } static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg = ETHER_TYPE_VLAN ; reg |= (tpid << 16); E1000_WRITE_REG(hw, E1000_VET, reg); } static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* Filter Table Disable */ reg = E1000_READ_REG(hw, E1000_RCTL); reg &= ~E1000_RCTL_CFIEN; reg &= ~E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); } static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t reg; int i; /* Filter Table Enable, CFI not used for packet acceptance */ reg = E1000_READ_REG(hw, E1000_RCTL); reg &= ~E1000_RCTL_CFIEN; reg |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); /* restore VFTA table */ for (i = 0; i < IGB_VFTA_SIZE; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, i, shadow_vfta->vfta[i]); } static void igb_vlan_hw_strip_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* VLAN Mode Disable */ reg = E1000_READ_REG(hw, E1000_CTRL); reg &= ~E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, reg); } static void igb_vlan_hw_strip_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* VLAN Mode Enable */ reg = E1000_READ_REG(hw, E1000_CTRL); reg |= E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, reg); } static void igb_vlan_hw_extend_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* CTRL_EXT: Extended VLAN */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~E1000_CTRL_EXT_EXTEND_VLAN; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* Update maximum packet length */ if (dev->data->dev_conf.rxmode.jumbo_frame == 1) E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE); } static void igb_vlan_hw_extend_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* CTRL_EXT: Extended VLAN */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg |= E1000_CTRL_EXT_EXTEND_VLAN; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* Update maximum packet length */ if (dev->data->dev_conf.rxmode.jumbo_frame == 1) E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * VLAN_TAG_SIZE); } static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask) { if(mask & ETH_VLAN_STRIP_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_strip) igb_vlan_hw_strip_enable(dev); else igb_vlan_hw_strip_disable(dev); } if(mask & ETH_VLAN_FILTER_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_filter) igb_vlan_hw_filter_enable(dev); else igb_vlan_hw_filter_disable(dev); } if(mask & ETH_VLAN_EXTEND_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_extend) igb_vlan_hw_extend_enable(dev); else igb_vlan_hw_extend_disable(dev); } } /** * It enables the interrupt mask and then enable the interrupt. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_igb_lsc_interrupt_setup(struct rte_eth_dev *dev) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); intr->mask |= E1000_ICR_LSC; return 0; } #ifdef RTE_NEXT_ABI /* It clears the interrupt causes and enables the interrupt. * It will be called once only during nic initialized. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_igb_rxq_interrupt_setup(struct rte_eth_dev *dev) { uint32_t mask, regval; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); eth_igb_infos_get(dev, &dev_info); mask = 0xFFFFFFFF >> (32 - dev_info.max_rx_queues); regval = E1000_READ_REG(hw, E1000_EIMS); E1000_WRITE_REG(hw, E1000_EIMS, regval | mask); return 0; } #endif /* * It reads ICR and gets interrupt causes, check it and set a bit flag * to update link status. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_igb_interrupt_get_status(struct rte_eth_dev *dev) { uint32_t icr; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); igb_intr_disable(hw); /* read-on-clear nic registers here */ icr = E1000_READ_REG(hw, E1000_ICR); intr->flags = 0; if (icr & E1000_ICR_LSC) { intr->flags |= E1000_FLAG_NEED_LINK_UPDATE; } if (icr & E1000_ICR_VMMB) intr->flags |= E1000_FLAG_MAILBOX; return 0; } /* * It executes link_update after knowing an interrupt is prsent. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int eth_igb_interrupt_action(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); uint32_t tctl, rctl; struct rte_eth_link link; int ret; if (intr->flags & E1000_FLAG_MAILBOX) { igb_pf_mbx_process(dev); intr->flags &= ~E1000_FLAG_MAILBOX; } igb_intr_enable(dev); rte_intr_enable(&(dev->pci_dev->intr_handle)); if (intr->flags & E1000_FLAG_NEED_LINK_UPDATE) { intr->flags &= ~E1000_FLAG_NEED_LINK_UPDATE; /* set get_link_status to check register later */ hw->mac.get_link_status = 1; ret = eth_igb_link_update(dev, 0); /* check if link has changed */ if (ret < 0) return 0; memset(&link, 0, sizeof(link)); rte_igb_dev_atomic_read_link_status(dev, &link); if (link.link_status) { PMD_INIT_LOG(INFO, " Port %d: Link Up - speed %u Mbps - %s", dev->data->port_id, (unsigned)link.link_speed, link.link_duplex == ETH_LINK_FULL_DUPLEX ? "full-duplex" : "half-duplex"); } else { PMD_INIT_LOG(INFO, " Port %d: Link Down", dev->data->port_id); } PMD_INIT_LOG(DEBUG, "PCI Address: %04d:%02d:%02d:%d", dev->pci_dev->addr.domain, dev->pci_dev->addr.bus, dev->pci_dev->addr.devid, dev->pci_dev->addr.function); tctl = E1000_READ_REG(hw, E1000_TCTL); rctl = E1000_READ_REG(hw, E1000_RCTL); if (link.link_status) { /* enable Tx/Rx */ tctl |= E1000_TCTL_EN; rctl |= E1000_RCTL_EN; } else { /* disable Tx/Rx */ tctl &= ~E1000_TCTL_EN; rctl &= ~E1000_RCTL_EN; } E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); } return 0; } /** * Interrupt handler which shall be registered at first. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void eth_igb_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; eth_igb_interrupt_get_status(dev); eth_igb_interrupt_action(dev); } static int eth_igb_led_on(struct rte_eth_dev *dev) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP); } static int eth_igb_led_off(struct rte_eth_dev *dev) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP); } static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct e1000_hw *hw; uint32_t ctrl; int tx_pause; int rx_pause; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); fc_conf->pause_time = hw->fc.pause_time; fc_conf->high_water = hw->fc.high_water; fc_conf->low_water = hw->fc.low_water; fc_conf->send_xon = hw->fc.send_xon; fc_conf->autoneg = hw->mac.autoneg; /* * Return rx_pause and tx_pause status according to actual setting of * the TFCE and RFCE bits in the CTRL register. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); if (ctrl & E1000_CTRL_TFCE) tx_pause = 1; else tx_pause = 0; if (ctrl & E1000_CTRL_RFCE) rx_pause = 1; else rx_pause = 0; if (rx_pause && tx_pause) fc_conf->mode = RTE_FC_FULL; else if (rx_pause) fc_conf->mode = RTE_FC_RX_PAUSE; else if (tx_pause) fc_conf->mode = RTE_FC_TX_PAUSE; else fc_conf->mode = RTE_FC_NONE; return 0; } static int eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct e1000_hw *hw; int err; enum e1000_fc_mode rte_fcmode_2_e1000_fcmode[] = { e1000_fc_none, e1000_fc_rx_pause, e1000_fc_tx_pause, e1000_fc_full }; uint32_t rx_buf_size; uint32_t max_high_water; uint32_t rctl; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (fc_conf->autoneg != hw->mac.autoneg) return -ENOTSUP; rx_buf_size = igb_get_rx_buffer_size(hw); PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); /* At least reserve one Ethernet frame for watermark */ max_high_water = rx_buf_size - ETHER_MAX_LEN; if ((fc_conf->high_water > max_high_water) || (fc_conf->high_water < fc_conf->low_water)) { PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value"); PMD_INIT_LOG(ERR, "high water must <= 0x%x", max_high_water); return (-EINVAL); } hw->fc.requested_mode = rte_fcmode_2_e1000_fcmode[fc_conf->mode]; hw->fc.pause_time = fc_conf->pause_time; hw->fc.high_water = fc_conf->high_water; hw->fc.low_water = fc_conf->low_water; hw->fc.send_xon = fc_conf->send_xon; err = e1000_setup_link_generic(hw); if (err == E1000_SUCCESS) { /* check if we want to forward MAC frames - driver doesn't have native * capability to do that, so we'll write the registers ourselves */ rctl = E1000_READ_REG(hw, E1000_RCTL); /* set or clear MFLCN.PMCF bit depending on configuration */ if (fc_conf->mac_ctrl_frame_fwd != 0) rctl |= E1000_RCTL_PMCF; else rctl &= ~E1000_RCTL_PMCF; E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); return 0; } PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err); return (-EIO); } #define E1000_RAH_POOLSEL_SHIFT (18) static void eth_igb_rar_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, __rte_unused uint32_t pool) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rah; e1000_rar_set(hw, mac_addr->addr_bytes, index); rah = E1000_READ_REG(hw, E1000_RAH(index)); rah |= (0x1 << (E1000_RAH_POOLSEL_SHIFT + pool)); E1000_WRITE_REG(hw, E1000_RAH(index), rah); } static void eth_igb_rar_clear(struct rte_eth_dev *dev, uint32_t index) { uint8_t addr[ETHER_ADDR_LEN]; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); memset(addr, 0, sizeof(addr)); e1000_rar_set(hw, addr, index); } static void eth_igb_default_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *addr) { eth_igb_rar_clear(dev, 0); eth_igb_rar_set(dev, (void *)addr, 0, 0); } /* * Virtual Function operations */ static void igbvf_intr_disable(struct e1000_hw *hw) { PMD_INIT_FUNC_TRACE(); /* Clear interrupt mask to stop from interrupts being generated */ E1000_WRITE_REG(hw, E1000_EIMC, 0xFFFF); E1000_WRITE_FLUSH(hw); } static void igbvf_stop_adapter(struct rte_eth_dev *dev) { u32 reg_val; u16 i; struct rte_eth_dev_info dev_info; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); memset(&dev_info, 0, sizeof(dev_info)); eth_igbvf_infos_get(dev, &dev_info); /* Clear interrupt mask to stop from interrupts being generated */ igbvf_intr_disable(hw); /* Clear any pending interrupts, flush previous writes */ E1000_READ_REG(hw, E1000_EICR); /* Disable the transmit unit. Each queue must be disabled. */ for (i = 0; i < dev_info.max_tx_queues; i++) E1000_WRITE_REG(hw, E1000_TXDCTL(i), E1000_TXDCTL_SWFLSH); /* Disable the receive unit by stopping each queue */ for (i = 0; i < dev_info.max_rx_queues; i++) { reg_val = E1000_READ_REG(hw, E1000_RXDCTL(i)); reg_val &= ~E1000_RXDCTL_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_RXDCTL(i), reg_val); while (E1000_READ_REG(hw, E1000_RXDCTL(i)) & E1000_RXDCTL_QUEUE_ENABLE) ; } /* flush all queues disables */ E1000_WRITE_FLUSH(hw); msec_delay(2); } static int eth_igbvf_link_update(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; struct e1000_mac_info *mac = &hw->mac; int ret_val = E1000_SUCCESS; PMD_INIT_LOG(DEBUG, "e1000_check_for_link_vf"); /* * We only want to run this if there has been a rst asserted. * in this case that could mean a link change, device reset, * or a virtual function reset */ /* If we were hit with a reset or timeout drop the link */ if (!e1000_check_for_rst(hw, 0) || !mbx->timeout) mac->get_link_status = TRUE; if (!mac->get_link_status) goto out; /* if link status is down no point in checking to see if pf is up */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) goto out; /* if we passed all the tests above then the link is up and we no * longer need to check for link */ mac->get_link_status = FALSE; out: return ret_val; } static int igbvf_dev_configure(struct rte_eth_dev *dev) { struct rte_eth_conf* conf = &dev->data->dev_conf; PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d", dev->data->port_id); /* * VF has no ability to enable/disable HW CRC * Keep the persistent behavior the same as Host PF */ #ifndef RTE_LIBRTE_E1000_PF_DISABLE_STRIP_CRC if (!conf->rxmode.hw_strip_crc) { PMD_INIT_LOG(NOTICE, "VF can't disable HW CRC Strip"); conf->rxmode.hw_strip_crc = 1; } #else if (conf->rxmode.hw_strip_crc) { PMD_INIT_LOG(NOTICE, "VF can't enable HW CRC Strip"); conf->rxmode.hw_strip_crc = 0; } #endif return 0; } static int igbvf_dev_start(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); int ret; PMD_INIT_FUNC_TRACE(); hw->mac.ops.reset_hw(hw); adapter->stopped = 0; /* Set all vfta */ igbvf_set_vfta_all(dev,1); eth_igbvf_tx_init(dev); /* This can fail when allocating mbufs for descriptor rings */ ret = eth_igbvf_rx_init(dev); if (ret) { PMD_INIT_LOG(ERR, "Unable to initialize RX hardware"); igb_dev_clear_queues(dev); return ret; } return 0; } static void igbvf_dev_stop(struct rte_eth_dev *dev) { PMD_INIT_FUNC_TRACE(); igbvf_stop_adapter(dev); /* * Clear what we set, but we still keep shadow_vfta to * restore after device starts */ igbvf_set_vfta_all(dev,0); igb_dev_clear_queues(dev); } static void igbvf_dev_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_adapter *adapter = E1000_DEV_PRIVATE(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); e1000_reset_hw(hw); igbvf_dev_stop(dev); adapter->stopped = 1; igb_dev_free_queues(dev); } static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on) { struct e1000_mbx_info *mbx = &hw->mbx; uint32_t msgbuf[2]; /* After set vlan, vlan strip will also be enabled in igb driver*/ msgbuf[0] = E1000_VF_SET_VLAN; msgbuf[1] = vid; /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ if (on) msgbuf[0] |= E1000_VF_SET_VLAN_ADD; return (mbx->ops.write_posted(hw, msgbuf, 2, 0)); } static void igbvf_set_vfta_all(struct rte_eth_dev *dev, bool on) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); int i = 0, j = 0, vfta = 0, mask = 1; for (i = 0; i < IGB_VFTA_SIZE; i++){ vfta = shadow_vfta->vfta[i]; if(vfta){ mask = 1; for (j = 0; j < 32; j++){ if(vfta & mask) igbvf_set_vfta(hw, (uint16_t)((i<<5)+j), on); mask<<=1; } } } } static int igbvf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vfta * shadow_vfta = E1000_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vid_idx = 0; uint32_t vid_bit = 0; int ret = 0; PMD_INIT_FUNC_TRACE(); /*vind is not used in VF driver, set to 0, check ixgbe_set_vfta_vf*/ ret = igbvf_set_vfta(hw, vlan_id, !!on); if(ret){ PMD_INIT_LOG(ERR, "Unable to set VF vlan"); return ret; } vid_idx = (uint32_t) ((vlan_id >> 5) & 0x7F); vid_bit = (uint32_t) (1 << (vlan_id & 0x1F)); /*Save what we set and retore it after device reset*/ if (on) shadow_vfta->vfta[vid_idx] |= vid_bit; else shadow_vfta->vfta[vid_idx] &= ~vid_bit; return 0; } static void igbvf_default_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *addr) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* index is not used by rar_set() */ hw->mac.ops.rar_set(hw, (void *)addr, 0); } static int eth_igb_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { uint8_t i, j, mask; uint32_t reta, r; uint16_t idx, shift; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (reta_size != ETH_RSS_RETA_SIZE_128) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128); return -EINVAL; } for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & IGB_4_BIT_MASK); if (!mask) continue; if (mask == IGB_4_BIT_MASK) r = 0; else r = E1000_READ_REG(hw, E1000_RETA(i >> 2)); for (j = 0, reta = 0; j < IGB_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta |= reta_conf[idx].reta[shift + j] << (CHAR_BIT * j); else reta |= r & (IGB_8_BIT_MASK << (CHAR_BIT * j)); } E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta); } return 0; } static int eth_igb_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { uint8_t i, j, mask; uint32_t reta; uint16_t idx, shift; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (reta_size != ETH_RSS_RETA_SIZE_128) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128); return -EINVAL; } for (i = 0; i < reta_size; i += IGB_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & IGB_4_BIT_MASK); if (!mask) continue; reta = E1000_READ_REG(hw, E1000_RETA(i >> 2)); for (j = 0; j < IGB_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta_conf[idx].reta[shift + j] = ((reta >> (CHAR_BIT * j)) & IGB_8_BIT_MASK); } } return 0; } #define MAC_TYPE_FILTER_SUP(type) do {\ if ((type) != e1000_82580 && (type) != e1000_i350 &&\ (type) != e1000_82576)\ return -ENOTSUP;\ } while (0) static int eth_igb_syn_filter_set(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter, bool add) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t synqf, rfctl; if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) return -EINVAL; synqf = E1000_READ_REG(hw, E1000_SYNQF(0)); if (add) { if (synqf & E1000_SYN_FILTER_ENABLE) return -EINVAL; synqf = (uint32_t)(((filter->queue << E1000_SYN_FILTER_QUEUE_SHIFT) & E1000_SYN_FILTER_QUEUE) | E1000_SYN_FILTER_ENABLE); rfctl = E1000_READ_REG(hw, E1000_RFCTL); if (filter->hig_pri) rfctl |= E1000_RFCTL_SYNQFP; else rfctl &= ~E1000_RFCTL_SYNQFP; E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); } else { if (!(synqf & E1000_SYN_FILTER_ENABLE)) return -ENOENT; synqf = 0; } E1000_WRITE_REG(hw, E1000_SYNQF(0), synqf); E1000_WRITE_FLUSH(hw); return 0; } static int eth_igb_syn_filter_get(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t synqf, rfctl; synqf = E1000_READ_REG(hw, E1000_SYNQF(0)); if (synqf & E1000_SYN_FILTER_ENABLE) { rfctl = E1000_READ_REG(hw, E1000_RFCTL); filter->hig_pri = (rfctl & E1000_RFCTL_SYNQFP) ? 1 : 0; filter->queue = (uint8_t)((synqf & E1000_SYN_FILTER_QUEUE) >> E1000_SYN_FILTER_QUEUE_SHIFT); return 0; } return -ENOENT; } static int eth_igb_syn_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = eth_igb_syn_filter_set(dev, (struct rte_eth_syn_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = eth_igb_syn_filter_set(dev, (struct rte_eth_syn_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = eth_igb_syn_filter_get(dev, (struct rte_eth_syn_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op); ret = -EINVAL; break; } return ret; } #define MAC_TYPE_FILTER_SUP_EXT(type) do {\ if ((type) != e1000_82580 && (type) != e1000_i350)\ return -ENOSYS; \ } while (0) /* translate elements in struct rte_eth_ntuple_filter to struct e1000_2tuple_filter_info*/ static inline int ntuple_filter_to_2tuple(struct rte_eth_ntuple_filter *filter, struct e1000_2tuple_filter_info *filter_info) { if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) return -EINVAL; if (filter->priority > E1000_2TUPLE_MAX_PRI) return -EINVAL; /* filter index is out of range. */ if (filter->tcp_flags > TCP_FLAG_ALL) return -EINVAL; /* flags is invalid. */ switch (filter->dst_port_mask) { case UINT16_MAX: filter_info->dst_port_mask = 0; filter_info->dst_port = filter->dst_port; break; case 0: filter_info->dst_port_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid dst_port mask."); return -EINVAL; } switch (filter->proto_mask) { case UINT8_MAX: filter_info->proto_mask = 0; filter_info->proto = filter->proto; break; case 0: filter_info->proto_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid protocol mask."); return -EINVAL; } filter_info->priority = (uint8_t)filter->priority; if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG) filter_info->tcp_flags = filter->tcp_flags; else filter_info->tcp_flags = 0; return 0; } static inline struct e1000_2tuple_filter * igb_2tuple_filter_lookup(struct e1000_2tuple_filter_list *filter_list, struct e1000_2tuple_filter_info *key) { struct e1000_2tuple_filter *it; TAILQ_FOREACH(it, filter_list, entries) { if (memcmp(key, &it->filter_info, sizeof(struct e1000_2tuple_filter_info)) == 0) { return it; } } return NULL; } /* * igb_add_2tuple_filter - add a 2tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: ponter to the filter that will be added. * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_add_2tuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_2tuple_filter *filter; uint32_t ttqf = E1000_TTQF_DISABLE_MASK; uint32_t imir, imir_ext = E1000_IMIREXT_SIZE_BP; int i, ret; filter = rte_zmalloc("e1000_2tuple_filter", sizeof(struct e1000_2tuple_filter), 0); if (filter == NULL) return -ENOMEM; ret = ntuple_filter_to_2tuple(ntuple_filter, &filter->filter_info); if (ret < 0) { rte_free(filter); return ret; } if (igb_2tuple_filter_lookup(&filter_info->twotuple_list, &filter->filter_info) != NULL) { PMD_DRV_LOG(ERR, "filter exists."); rte_free(filter); return -EEXIST; } filter->queue = ntuple_filter->queue; /* * look for an unused 2tuple filter index, * and insert the filter to list. */ for (i = 0; i < E1000_MAX_TTQF_FILTERS; i++) { if (!(filter_info->twotuple_mask & (1 << i))) { filter_info->twotuple_mask |= 1 << i; filter->index = i; TAILQ_INSERT_TAIL(&filter_info->twotuple_list, filter, entries); break; } } if (i >= E1000_MAX_TTQF_FILTERS) { PMD_DRV_LOG(ERR, "2tuple filters are full."); rte_free(filter); return -ENOSYS; } imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT); if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */ imir |= E1000_IMIR_PORT_BP; else imir &= ~E1000_IMIR_PORT_BP; imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT; ttqf |= E1000_TTQF_QUEUE_ENABLE; ttqf |= (uint32_t)(filter->queue << E1000_TTQF_QUEUE_SHIFT); ttqf |= (uint32_t)(filter->filter_info.proto & E1000_TTQF_PROTOCOL_MASK); if (filter->filter_info.proto_mask == 0) ttqf &= ~E1000_TTQF_MASK_ENABLE; /* tcp flags bits setting. */ if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) { if (filter->filter_info.tcp_flags & TCP_URG_FLAG) imir_ext |= E1000_IMIREXT_CTRL_URG; if (filter->filter_info.tcp_flags & TCP_ACK_FLAG) imir_ext |= E1000_IMIREXT_CTRL_ACK; if (filter->filter_info.tcp_flags & TCP_PSH_FLAG) imir_ext |= E1000_IMIREXT_CTRL_PSH; if (filter->filter_info.tcp_flags & TCP_RST_FLAG) imir_ext |= E1000_IMIREXT_CTRL_RST; if (filter->filter_info.tcp_flags & TCP_SYN_FLAG) imir_ext |= E1000_IMIREXT_CTRL_SYN; if (filter->filter_info.tcp_flags & TCP_FIN_FLAG) imir_ext |= E1000_IMIREXT_CTRL_FIN; } else imir_ext |= E1000_IMIREXT_CTRL_BP; E1000_WRITE_REG(hw, E1000_IMIR(i), imir); E1000_WRITE_REG(hw, E1000_TTQF(i), ttqf); E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext); return 0; } /* * igb_remove_2tuple_filter - remove a 2tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: ponter to the filter that will be removed. * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_remove_2tuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_2tuple_filter_info filter_2tuple; struct e1000_2tuple_filter *filter; int ret; memset(&filter_2tuple, 0, sizeof(struct e1000_2tuple_filter_info)); ret = ntuple_filter_to_2tuple(ntuple_filter, &filter_2tuple); if (ret < 0) return ret; filter = igb_2tuple_filter_lookup(&filter_info->twotuple_list, &filter_2tuple); if (filter == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } filter_info->twotuple_mask &= ~(1 << filter->index); TAILQ_REMOVE(&filter_info->twotuple_list, filter, entries); rte_free(filter); E1000_WRITE_REG(hw, E1000_TTQF(filter->index), E1000_TTQF_DISABLE_MASK); E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0); E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0); return 0; } static inline struct e1000_flex_filter * eth_igb_flex_filter_lookup(struct e1000_flex_filter_list *filter_list, struct e1000_flex_filter_info *key) { struct e1000_flex_filter *it; TAILQ_FOREACH(it, filter_list, entries) { if (memcmp(key, &it->filter_info, sizeof(struct e1000_flex_filter_info)) == 0) return it; } return NULL; } static int eth_igb_add_del_flex_filter(struct rte_eth_dev *dev, struct rte_eth_flex_filter *filter, bool add) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_flex_filter *flex_filter, *it; uint32_t wufc, queueing, mask; uint32_t reg_off; uint8_t shift, i, j = 0; flex_filter = rte_zmalloc("e1000_flex_filter", sizeof(struct e1000_flex_filter), 0); if (flex_filter == NULL) return -ENOMEM; flex_filter->filter_info.len = filter->len; flex_filter->filter_info.priority = filter->priority; memcpy(flex_filter->filter_info.dwords, filter->bytes, filter->len); for (i = 0; i < RTE_ALIGN(filter->len, CHAR_BIT) / CHAR_BIT; i++) { mask = 0; /* reverse bits in flex filter's mask*/ for (shift = 0; shift < CHAR_BIT; shift++) { if (filter->mask[i] & (0x01 << shift)) mask |= (0x80 >> shift); } flex_filter->filter_info.mask[i] = mask; } wufc = E1000_READ_REG(hw, E1000_WUFC); if (flex_filter->index < E1000_MAX_FHFT) reg_off = E1000_FHFT(flex_filter->index); else reg_off = E1000_FHFT_EXT(flex_filter->index - E1000_MAX_FHFT); if (add) { if (eth_igb_flex_filter_lookup(&filter_info->flex_list, &flex_filter->filter_info) != NULL) { PMD_DRV_LOG(ERR, "filter exists."); rte_free(flex_filter); return -EEXIST; } flex_filter->queue = filter->queue; /* * look for an unused flex filter index * and insert the filter into the list. */ for (i = 0; i < E1000_MAX_FLEX_FILTERS; i++) { if (!(filter_info->flex_mask & (1 << i))) { filter_info->flex_mask |= 1 << i; flex_filter->index = i; TAILQ_INSERT_TAIL(&filter_info->flex_list, flex_filter, entries); break; } } if (i >= E1000_MAX_FLEX_FILTERS) { PMD_DRV_LOG(ERR, "flex filters are full."); rte_free(flex_filter); return -ENOSYS; } E1000_WRITE_REG(hw, E1000_WUFC, wufc | E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << flex_filter->index)); queueing = filter->len | (filter->queue << E1000_FHFT_QUEUEING_QUEUE_SHIFT) | (filter->priority << E1000_FHFT_QUEUEING_PRIO_SHIFT); E1000_WRITE_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET, queueing); for (i = 0; i < E1000_FLEX_FILTERS_MASK_SIZE; i++) { E1000_WRITE_REG(hw, reg_off, flex_filter->filter_info.dwords[j]); reg_off += sizeof(uint32_t); E1000_WRITE_REG(hw, reg_off, flex_filter->filter_info.dwords[++j]); reg_off += sizeof(uint32_t); E1000_WRITE_REG(hw, reg_off, (uint32_t)flex_filter->filter_info.mask[i]); reg_off += sizeof(uint32_t) * 2; ++j; } } else { it = eth_igb_flex_filter_lookup(&filter_info->flex_list, &flex_filter->filter_info); if (it == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); rte_free(flex_filter); return -ENOENT; } for (i = 0; i < E1000_FHFT_SIZE_IN_DWD; i++) E1000_WRITE_REG(hw, reg_off + i * sizeof(uint32_t), 0); E1000_WRITE_REG(hw, E1000_WUFC, wufc & (~(E1000_WUFC_FLX0 << it->index))); filter_info->flex_mask &= ~(1 << it->index); TAILQ_REMOVE(&filter_info->flex_list, it, entries); rte_free(it); rte_free(flex_filter); } return 0; } static int eth_igb_get_flex_filter(struct rte_eth_dev *dev, struct rte_eth_flex_filter *filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_flex_filter flex_filter, *it; uint32_t wufc, queueing, wufc_en = 0; memset(&flex_filter, 0, sizeof(struct e1000_flex_filter)); flex_filter.filter_info.len = filter->len; flex_filter.filter_info.priority = filter->priority; memcpy(flex_filter.filter_info.dwords, filter->bytes, filter->len); memcpy(flex_filter.filter_info.mask, filter->mask, RTE_ALIGN(filter->len, sizeof(char)) / sizeof(char)); it = eth_igb_flex_filter_lookup(&filter_info->flex_list, &flex_filter.filter_info); if (it == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } wufc = E1000_READ_REG(hw, E1000_WUFC); wufc_en = E1000_WUFC_FLEX_HQ | (E1000_WUFC_FLX0 << it->index); if ((wufc & wufc_en) == wufc_en) { uint32_t reg_off = 0; if (it->index < E1000_MAX_FHFT) reg_off = E1000_FHFT(it->index); else reg_off = E1000_FHFT_EXT(it->index - E1000_MAX_FHFT); queueing = E1000_READ_REG(hw, reg_off + E1000_FHFT_QUEUEING_OFFSET); filter->len = queueing & E1000_FHFT_QUEUEING_LEN; filter->priority = (queueing & E1000_FHFT_QUEUEING_PRIO) >> E1000_FHFT_QUEUEING_PRIO_SHIFT; filter->queue = (queueing & E1000_FHFT_QUEUEING_QUEUE) >> E1000_FHFT_QUEUEING_QUEUE_SHIFT; return 0; } return -ENOENT; } static int eth_igb_flex_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_flex_filter *filter; int ret = 0; MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return ret; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", filter_op); return -EINVAL; } filter = (struct rte_eth_flex_filter *)arg; if (filter->len == 0 || filter->len > E1000_MAX_FLEX_FILTER_LEN || filter->len % sizeof(uint64_t) != 0) { PMD_DRV_LOG(ERR, "filter's length is out of range"); return -EINVAL; } if (filter->priority > E1000_MAX_FLEX_FILTER_PRI) { PMD_DRV_LOG(ERR, "filter's priority is out of range"); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = eth_igb_add_del_flex_filter(dev, filter, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = eth_igb_add_del_flex_filter(dev, filter, FALSE); break; case RTE_ETH_FILTER_GET: ret = eth_igb_get_flex_filter(dev, filter); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u", filter_op); ret = -EINVAL; break; } return ret; } /* translate elements in struct rte_eth_ntuple_filter to struct e1000_5tuple_filter_info*/ static inline int ntuple_filter_to_5tuple_82576(struct rte_eth_ntuple_filter *filter, struct e1000_5tuple_filter_info *filter_info) { if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576) return -EINVAL; if (filter->priority > E1000_2TUPLE_MAX_PRI) return -EINVAL; /* filter index is out of range. */ if (filter->tcp_flags > TCP_FLAG_ALL) return -EINVAL; /* flags is invalid. */ switch (filter->dst_ip_mask) { case UINT32_MAX: filter_info->dst_ip_mask = 0; filter_info->dst_ip = filter->dst_ip; break; case 0: filter_info->dst_ip_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid dst_ip mask."); return -EINVAL; } switch (filter->src_ip_mask) { case UINT32_MAX: filter_info->src_ip_mask = 0; filter_info->src_ip = filter->src_ip; break; case 0: filter_info->src_ip_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid src_ip mask."); return -EINVAL; } switch (filter->dst_port_mask) { case UINT16_MAX: filter_info->dst_port_mask = 0; filter_info->dst_port = filter->dst_port; break; case 0: filter_info->dst_port_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid dst_port mask."); return -EINVAL; } switch (filter->src_port_mask) { case UINT16_MAX: filter_info->src_port_mask = 0; filter_info->src_port = filter->src_port; break; case 0: filter_info->src_port_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid src_port mask."); return -EINVAL; } switch (filter->proto_mask) { case UINT8_MAX: filter_info->proto_mask = 0; filter_info->proto = filter->proto; break; case 0: filter_info->proto_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid protocol mask."); return -EINVAL; } filter_info->priority = (uint8_t)filter->priority; if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG) filter_info->tcp_flags = filter->tcp_flags; else filter_info->tcp_flags = 0; return 0; } static inline struct e1000_5tuple_filter * igb_5tuple_filter_lookup_82576(struct e1000_5tuple_filter_list *filter_list, struct e1000_5tuple_filter_info *key) { struct e1000_5tuple_filter *it; TAILQ_FOREACH(it, filter_list, entries) { if (memcmp(key, &it->filter_info, sizeof(struct e1000_5tuple_filter_info)) == 0) { return it; } } return NULL; } /* * igb_add_5tuple_filter_82576 - add a 5tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: ponter to the filter that will be added. * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_add_5tuple_filter_82576(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_5tuple_filter *filter; uint32_t ftqf = E1000_FTQF_VF_BP | E1000_FTQF_MASK; uint32_t spqf, imir, imir_ext = E1000_IMIREXT_SIZE_BP; uint8_t i; int ret; filter = rte_zmalloc("e1000_5tuple_filter", sizeof(struct e1000_5tuple_filter), 0); if (filter == NULL) return -ENOMEM; ret = ntuple_filter_to_5tuple_82576(ntuple_filter, &filter->filter_info); if (ret < 0) { rte_free(filter); return ret; } if (igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list, &filter->filter_info) != NULL) { PMD_DRV_LOG(ERR, "filter exists."); rte_free(filter); return -EEXIST; } filter->queue = ntuple_filter->queue; /* * look for an unused 5tuple filter index, * and insert the filter to list. */ for (i = 0; i < E1000_MAX_FTQF_FILTERS; i++) { if (!(filter_info->fivetuple_mask & (1 << i))) { filter_info->fivetuple_mask |= 1 << i; filter->index = i; TAILQ_INSERT_TAIL(&filter_info->fivetuple_list, filter, entries); break; } } if (i >= E1000_MAX_FTQF_FILTERS) { PMD_DRV_LOG(ERR, "5tuple filters are full."); rte_free(filter); return -ENOSYS; } ftqf |= filter->filter_info.proto & E1000_FTQF_PROTOCOL_MASK; if (filter->filter_info.src_ip_mask == 0) /* 0b means compare. */ ftqf &= ~E1000_FTQF_MASK_SOURCE_ADDR_BP; if (filter->filter_info.dst_ip_mask == 0) ftqf &= ~E1000_FTQF_MASK_DEST_ADDR_BP; if (filter->filter_info.src_port_mask == 0) ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; if (filter->filter_info.proto_mask == 0) ftqf &= ~E1000_FTQF_MASK_PROTO_BP; ftqf |= (filter->queue << E1000_FTQF_QUEUE_SHIFT) & E1000_FTQF_QUEUE_MASK; ftqf |= E1000_FTQF_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_FTQF(i), ftqf); E1000_WRITE_REG(hw, E1000_DAQF(i), filter->filter_info.dst_ip); E1000_WRITE_REG(hw, E1000_SAQF(i), filter->filter_info.src_ip); spqf = filter->filter_info.src_port & E1000_SPQF_SRCPORT; E1000_WRITE_REG(hw, E1000_SPQF(i), spqf); imir = (uint32_t)(filter->filter_info.dst_port & E1000_IMIR_DSTPORT); if (filter->filter_info.dst_port_mask == 1) /* 1b means not compare. */ imir |= E1000_IMIR_PORT_BP; else imir &= ~E1000_IMIR_PORT_BP; imir |= filter->filter_info.priority << E1000_IMIR_PRIORITY_SHIFT; /* tcp flags bits setting. */ if (filter->filter_info.tcp_flags & TCP_FLAG_ALL) { if (filter->filter_info.tcp_flags & TCP_URG_FLAG) imir_ext |= E1000_IMIREXT_CTRL_URG; if (filter->filter_info.tcp_flags & TCP_ACK_FLAG) imir_ext |= E1000_IMIREXT_CTRL_ACK; if (filter->filter_info.tcp_flags & TCP_PSH_FLAG) imir_ext |= E1000_IMIREXT_CTRL_PSH; if (filter->filter_info.tcp_flags & TCP_RST_FLAG) imir_ext |= E1000_IMIREXT_CTRL_RST; if (filter->filter_info.tcp_flags & TCP_SYN_FLAG) imir_ext |= E1000_IMIREXT_CTRL_SYN; if (filter->filter_info.tcp_flags & TCP_FIN_FLAG) imir_ext |= E1000_IMIREXT_CTRL_FIN; } else imir_ext |= E1000_IMIREXT_CTRL_BP; E1000_WRITE_REG(hw, E1000_IMIR(i), imir); E1000_WRITE_REG(hw, E1000_IMIREXT(i), imir_ext); return 0; } /* * igb_remove_5tuple_filter_82576 - remove a 5tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: ponter to the filter that will be removed. * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_remove_5tuple_filter_82576(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_5tuple_filter_info filter_5tuple; struct e1000_5tuple_filter *filter; int ret; memset(&filter_5tuple, 0, sizeof(struct e1000_5tuple_filter_info)); ret = ntuple_filter_to_5tuple_82576(ntuple_filter, &filter_5tuple); if (ret < 0) return ret; filter = igb_5tuple_filter_lookup_82576(&filter_info->fivetuple_list, &filter_5tuple); if (filter == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } filter_info->fivetuple_mask &= ~(1 << filter->index); TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries); rte_free(filter); E1000_WRITE_REG(hw, E1000_FTQF(filter->index), E1000_FTQF_VF_BP | E1000_FTQF_MASK); E1000_WRITE_REG(hw, E1000_DAQF(filter->index), 0); E1000_WRITE_REG(hw, E1000_SAQF(filter->index), 0); E1000_WRITE_REG(hw, E1000_SPQF(filter->index), 0); E1000_WRITE_REG(hw, E1000_IMIR(filter->index), 0); E1000_WRITE_REG(hw, E1000_IMIREXT(filter->index), 0); return 0; } static int eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { uint32_t rctl; struct e1000_hw *hw; struct rte_eth_dev_info dev_info; uint32_t frame_size = mtu + (ETHER_HDR_LEN + ETHER_CRC_LEN + VLAN_TAG_SIZE); hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); #ifdef RTE_LIBRTE_82571_SUPPORT /* XXX: not bigger than max_rx_pktlen */ if (hw->mac.type == e1000_82571) return -ENOTSUP; #endif eth_igb_infos_get(dev, &dev_info); /* check that mtu is within the allowed range */ if ((mtu < ETHER_MIN_MTU) || (frame_size > dev_info.max_rx_pktlen)) return -EINVAL; /* refuse mtu that requires the support of scattered packets when this * feature has not been enabled before. */ if (!dev->data->scattered_rx && frame_size > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM) return -EINVAL; rctl = E1000_READ_REG(hw, E1000_RCTL); /* switch to jumbo mode if needed */ if (frame_size > ETHER_MAX_LEN) { dev->data->dev_conf.rxmode.jumbo_frame = 1; rctl |= E1000_RCTL_LPE; } else { dev->data->dev_conf.rxmode.jumbo_frame = 0; rctl &= ~E1000_RCTL_LPE; } E1000_WRITE_REG(hw, E1000_RCTL, rctl); /* update max frame size */ dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len); return 0; } /* * igb_add_del_ntuple_filter - add or delete a ntuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: Pointer to struct rte_eth_ntuple_filter * add: if true, add filter, if false, remove filter * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_add_del_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter, bool add) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; switch (ntuple_filter->flags) { case RTE_5TUPLE_FLAGS: case (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG): if (hw->mac.type != e1000_82576) return -ENOTSUP; if (add) ret = igb_add_5tuple_filter_82576(dev, ntuple_filter); else ret = igb_remove_5tuple_filter_82576(dev, ntuple_filter); break; case RTE_2TUPLE_FLAGS: case (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG): if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350) return -ENOTSUP; if (add) ret = igb_add_2tuple_filter(dev, ntuple_filter); else ret = igb_remove_2tuple_filter(dev, ntuple_filter); break; default: ret = -EINVAL; break; } return ret; } /* * igb_get_ntuple_filter - get a ntuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: Pointer to struct rte_eth_ntuple_filter * * @return * - On success, zero. * - On failure, a negative value. */ static int igb_get_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct e1000_5tuple_filter_info filter_5tuple; struct e1000_2tuple_filter_info filter_2tuple; struct e1000_5tuple_filter *p_5tuple_filter; struct e1000_2tuple_filter *p_2tuple_filter; int ret; switch (ntuple_filter->flags) { case RTE_5TUPLE_FLAGS: case (RTE_5TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG): if (hw->mac.type != e1000_82576) return -ENOTSUP; memset(&filter_5tuple, 0, sizeof(struct e1000_5tuple_filter_info)); ret = ntuple_filter_to_5tuple_82576(ntuple_filter, &filter_5tuple); if (ret < 0) return ret; p_5tuple_filter = igb_5tuple_filter_lookup_82576( &filter_info->fivetuple_list, &filter_5tuple); if (p_5tuple_filter == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } ntuple_filter->queue = p_5tuple_filter->queue; break; case RTE_2TUPLE_FLAGS: case (RTE_2TUPLE_FLAGS | RTE_NTUPLE_FLAGS_TCP_FLAG): if (hw->mac.type != e1000_82580 && hw->mac.type != e1000_i350) return -ENOTSUP; memset(&filter_2tuple, 0, sizeof(struct e1000_2tuple_filter_info)); ret = ntuple_filter_to_2tuple(ntuple_filter, &filter_2tuple); if (ret < 0) return ret; p_2tuple_filter = igb_2tuple_filter_lookup( &filter_info->twotuple_list, &filter_2tuple); if (p_2tuple_filter == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } ntuple_filter->queue = p_2tuple_filter->queue; break; default: ret = -EINVAL; break; } return 0; } /* * igb_ntuple_filter_handle - Handle operations for ntuple filter. * @dev: pointer to rte_eth_dev structure * @filter_op:operation will be taken. * @arg: a pointer to specific structure corresponding to the filter_op */ static int igb_ntuple_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = igb_add_del_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = igb_add_del_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = igb_get_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); ret = -EINVAL; break; } return ret; } static inline int igb_ethertype_filter_lookup(struct e1000_filter_info *filter_info, uint16_t ethertype) { int i; for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) { if (filter_info->ethertype_filters[i] == ethertype && (filter_info->ethertype_mask & (1 << i))) return i; } return -1; } static inline int igb_ethertype_filter_insert(struct e1000_filter_info *filter_info, uint16_t ethertype) { int i; for (i = 0; i < E1000_MAX_ETQF_FILTERS; i++) { if (!(filter_info->ethertype_mask & (1 << i))) { filter_info->ethertype_mask |= 1 << i; filter_info->ethertype_filters[i] = ethertype; return i; } } return -1; } static inline int igb_ethertype_filter_remove(struct e1000_filter_info *filter_info, uint8_t idx) { if (idx >= E1000_MAX_ETQF_FILTERS) return -1; filter_info->ethertype_mask &= ~(1 << idx); filter_info->ethertype_filters[idx] = 0; return idx; } static int igb_add_del_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter, bool add) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); uint32_t etqf = 0; int ret; if (filter->ether_type == ETHER_TYPE_IPv4 || filter->ether_type == ETHER_TYPE_IPv6) { PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in" " ethertype filter.", filter->ether_type); return -EINVAL; } if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { PMD_DRV_LOG(ERR, "mac compare is unsupported."); return -EINVAL; } if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { PMD_DRV_LOG(ERR, "drop option is unsupported."); return -EINVAL; } ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type); if (ret >= 0 && add) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.", filter->ether_type); return -EEXIST; } if (ret < 0 && !add) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", filter->ether_type); return -ENOENT; } if (add) { ret = igb_ethertype_filter_insert(filter_info, filter->ether_type); if (ret < 0) { PMD_DRV_LOG(ERR, "ethertype filters are full."); return -ENOSYS; } etqf |= E1000_ETQF_FILTER_ENABLE | E1000_ETQF_QUEUE_ENABLE; etqf |= (uint32_t)(filter->ether_type & E1000_ETQF_ETHERTYPE); etqf |= filter->queue << E1000_ETQF_QUEUE_SHIFT; } else { ret = igb_ethertype_filter_remove(filter_info, (uint8_t)ret); if (ret < 0) return -ENOSYS; } E1000_WRITE_REG(hw, E1000_ETQF(ret), etqf); E1000_WRITE_FLUSH(hw); return 0; } static int igb_get_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); uint32_t etqf; int ret; ret = igb_ethertype_filter_lookup(filter_info, filter->ether_type); if (ret < 0) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", filter->ether_type); return -ENOENT; } etqf = E1000_READ_REG(hw, E1000_ETQF(ret)); if (etqf & E1000_ETQF_FILTER_ENABLE) { filter->ether_type = etqf & E1000_ETQF_ETHERTYPE; filter->flags = 0; filter->queue = (etqf & E1000_ETQF_QUEUE) >> E1000_ETQF_QUEUE_SHIFT; return 0; } return -ENOENT; } /* * igb_ethertype_filter_handle - Handle operations for ethertype filter. * @dev: pointer to rte_eth_dev structure * @filter_op:operation will be taken. * @arg: a pointer to specific structure corresponding to the filter_op */ static int igb_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = igb_add_del_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = igb_add_del_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = igb_get_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); ret = -EINVAL; break; } return ret; } static int eth_igb_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg) { int ret = -EINVAL; switch (filter_type) { case RTE_ETH_FILTER_NTUPLE: ret = igb_ntuple_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_ETHERTYPE: ret = igb_ethertype_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_SYN: ret = eth_igb_syn_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_FLEXIBLE: ret = eth_igb_flex_filter_handle(dev, filter_op, arg); break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type); break; } return ret; } static int eth_igb_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); e1000_update_mc_addr_list(hw, (u8 *)mc_addr_set, nb_mc_addr); return 0; } static int igb_timesync_enable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_ctl; uint32_t tsauxc; /* Enable system time for it isn't on by default. */ tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); tsauxc &= ~E1000_TSAUXC_DISABLE_SYSTIME; E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); /* Start incrementing the register used to timestamp PTP packets. */ E1000_WRITE_REG(hw, E1000_TIMINCA, E1000_TIMINCA_INIT); /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ E1000_WRITE_REG(hw, E1000_ETQF(E1000_ETQF_FILTER_1588), (ETHER_TYPE_1588 | E1000_ETQF_FILTER_ENABLE | E1000_ETQF_1588)); /* Enable timestamping of received PTP packets. */ tsync_ctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL); tsync_ctl |= E1000_TSYNCRXCTL_ENABLED; E1000_WRITE_REG(hw, E1000_TSYNCRXCTL, tsync_ctl); /* Enable Timestamping of transmitted PTP packets. */ tsync_ctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL); tsync_ctl |= E1000_TSYNCTXCTL_ENABLED; E1000_WRITE_REG(hw, E1000_TSYNCTXCTL, tsync_ctl); return 0; } static int igb_timesync_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_ctl; /* Disable timestamping of transmitted PTP packets. */ tsync_ctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL); tsync_ctl &= ~E1000_TSYNCTXCTL_ENABLED; E1000_WRITE_REG(hw, E1000_TSYNCTXCTL, tsync_ctl); /* Disable timestamping of received PTP packets. */ tsync_ctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL); tsync_ctl &= ~E1000_TSYNCRXCTL_ENABLED; E1000_WRITE_REG(hw, E1000_TSYNCRXCTL, tsync_ctl); /* Disable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ E1000_WRITE_REG(hw, E1000_ETQF(E1000_ETQF_FILTER_1588), 0); /* Stop incrementating the System Time registers. */ E1000_WRITE_REG(hw, E1000_TIMINCA, 0); return 0; } static int igb_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags __rte_unused) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_rxctl; uint32_t rx_stmpl; uint32_t rx_stmph; tsync_rxctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL); if ((tsync_rxctl & E1000_TSYNCRXCTL_VALID) == 0) return -EINVAL; rx_stmpl = E1000_READ_REG(hw, E1000_RXSTMPL); rx_stmph = E1000_READ_REG(hw, E1000_RXSTMPH); timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); timestamp->tv_nsec = 0; return 0; } static int igb_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_txctl; uint32_t tx_stmpl; uint32_t tx_stmph; tsync_txctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL); if ((tsync_txctl & E1000_TSYNCTXCTL_VALID) == 0) return -EINVAL; tx_stmpl = E1000_READ_REG(hw, E1000_TXSTMPL); tx_stmph = E1000_READ_REG(hw, E1000_TXSTMPH); timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); timestamp->tv_nsec = 0; return 0; } static int eth_igb_get_reg_length(struct rte_eth_dev *dev __rte_unused) { int count = 0; int g_ind = 0; const struct reg_info *reg_group; while ((reg_group = igb_regs[g_ind++])) count += igb_reg_group_count(reg_group); return count; } static int igbvf_get_reg_length(struct rte_eth_dev *dev __rte_unused) { int count = 0; int g_ind = 0; const struct reg_info *reg_group; while ((reg_group = igbvf_regs[g_ind++])) count += igb_reg_group_count(reg_group); return count; } static int eth_igb_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *data = regs->data; int g_ind = 0; int count = 0; const struct reg_info *reg_group; /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)eth_igb_get_reg_length(dev))) { regs->version = hw->mac.type << 24 | hw->revision_id << 16 | hw->device_id; while ((reg_group = igb_regs[g_ind++])) count += igb_read_regs_group(dev, &data[count], reg_group); return 0; } return -ENOTSUP; } static int igbvf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *data = regs->data; int g_ind = 0; int count = 0; const struct reg_info *reg_group; /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)igbvf_get_reg_length(dev))) { regs->version = hw->mac.type << 24 | hw->revision_id << 16 | hw->device_id; while ((reg_group = igbvf_regs[g_ind++])) count += igb_read_regs_group(dev, &data[count], reg_group); return 0; } return -ENOTSUP; } static int eth_igb_get_eeprom_length(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Return unit is byte count */ return hw->nvm.word_size * 2; } static int eth_igb_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *in_eeprom) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_nvm_info *nvm = &hw->nvm; uint16_t *data = in_eeprom->data; int first, length; first = in_eeprom->offset >> 1; length = in_eeprom->length >> 1; if ((first >= hw->nvm.word_size) || ((first + length) >= hw->nvm.word_size)) return -EINVAL; in_eeprom->magic = hw->vendor_id | ((uint32_t)hw->device_id << 16); if ((nvm->ops.read) == NULL) return -ENOTSUP; return nvm->ops.read(hw, first, length, data); } static int eth_igb_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *in_eeprom) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_nvm_info *nvm = &hw->nvm; uint16_t *data = in_eeprom->data; int first, length; first = in_eeprom->offset >> 1; length = in_eeprom->length >> 1; if ((first >= hw->nvm.word_size) || ((first + length) >= hw->nvm.word_size)) return -EINVAL; in_eeprom->magic = (uint32_t)hw->vendor_id | ((uint32_t)hw->device_id << 16); if ((nvm->ops.write) == NULL) return -ENOTSUP; return nvm->ops.write(hw, first, length, data); } static struct rte_driver pmd_igb_drv = { .type = PMD_PDEV, .init = rte_igb_pmd_init, }; static struct rte_driver pmd_igbvf_drv = { .type = PMD_PDEV, .init = rte_igbvf_pmd_init, }; #ifdef RTE_NEXT_ABI static int eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mask = 1 << queue_id; E1000_WRITE_REG(hw, E1000_EIMC, mask); E1000_WRITE_FLUSH(hw); return 0; } static int eth_igb_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mask = 1 << queue_id; uint32_t regval; regval = E1000_READ_REG(hw, E1000_EIMS); E1000_WRITE_REG(hw, E1000_EIMS, regval | mask); E1000_WRITE_FLUSH(hw); rte_intr_enable(&dev->pci_dev->intr_handle); return 0; } static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector, uint8_t index, uint8_t offset) { uint32_t val = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); /* clear bits */ val &= ~((uint32_t)0xFF << offset); /* write vector and valid bit */ val |= (msix_vector | E1000_IVAR_VALID) << offset; E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, val); } static void eth_igb_assign_msix_vector(struct e1000_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector) { uint32_t tmp = 0; if (hw->mac.type == e1000_82575) { if (direction == 0) tmp = E1000_EICR_RX_QUEUE0 << queue; else if (direction == 1) tmp = E1000_EICR_TX_QUEUE0 << queue; E1000_WRITE_REG(hw, E1000_MSIXBM(msix_vector), tmp); } else if (hw->mac.type == e1000_82576) { if ((direction == 0) || (direction == 1)) eth_igb_write_ivar(hw, msix_vector, queue & 0x7, ((queue & 0x8) << 1) + 8 * direction); } else if ((hw->mac.type == e1000_82580) || (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354) || (hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { if ((direction == 0) || (direction == 1)) eth_igb_write_ivar(hw, msix_vector, queue >> 1, ((queue & 0x1) << 4) + 8 * direction); } } #endif /* Sets up the hardware to generate MSI-X interrupts properly * @hw * board private structure */ static void eth_igb_configure_msix_intr(struct rte_eth_dev *dev) { #ifdef RTE_NEXT_ABI int queue_id; uint32_t tmpval, regval, intr_mask; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t vec = 0; #endif struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; /* won't configure msix register if no mapping is done * between intr vector and event fd */ if (!rte_intr_dp_is_en(intr_handle)) return; #ifdef RTE_NEXT_ABI /* set interrupt vector for other causes */ if (hw->mac.type == e1000_82575) { tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT); /* enable MSI-X PBA support */ tmpval |= E1000_CTRL_EXT_PBA_CLR; /* Auto-Mask interrupts upon ICR read */ tmpval |= E1000_CTRL_EXT_EIAME; tmpval |= E1000_CTRL_EXT_IRCA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmpval); /* enable msix_other interrupt */ E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), 0, E1000_EIMS_OTHER); regval = E1000_READ_REG(hw, E1000_EIAC); E1000_WRITE_REG(hw, E1000_EIAC, regval | E1000_EIMS_OTHER); regval = E1000_READ_REG(hw, E1000_EIAM); E1000_WRITE_REG(hw, E1000_EIMS, regval | E1000_EIMS_OTHER); } else if ((hw->mac.type == e1000_82576) || (hw->mac.type == e1000_82580) || (hw->mac.type == e1000_i350) || (hw->mac.type == e1000_i354) || (hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { /* turn on MSI-X capability first */ E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE | E1000_GPIE_PBA | E1000_GPIE_EIAME | E1000_GPIE_NSICR); intr_mask = (1 << intr_handle->max_intr) - 1; regval = E1000_READ_REG(hw, E1000_EIAC); E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask); /* enable msix_other interrupt */ regval = E1000_READ_REG(hw, E1000_EIMS); E1000_WRITE_REG(hw, E1000_EIMS, regval | intr_mask); tmpval = (dev->data->nb_rx_queues | E1000_IVAR_VALID) << 8; E1000_WRITE_REG(hw, E1000_IVAR_MISC, tmpval); } /* use EIAM to auto-mask when MSI-X interrupt * is asserted, this saves a register write for every interrupt */ intr_mask = (1 << intr_handle->nb_efd) - 1; regval = E1000_READ_REG(hw, E1000_EIAM); E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask); for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) { eth_igb_assign_msix_vector(hw, 0, queue_id, vec); intr_handle->intr_vec[queue_id] = vec; if (vec < intr_handle->nb_efd - 1) vec++; } E1000_WRITE_FLUSH(hw); #endif } PMD_REGISTER_DRIVER(pmd_igb_drv); PMD_REGISTER_DRIVER(pmd_igbvf_drv); ================================================ FILE: drivers/net/e1000/igb_pf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/e1000_defines.h" #include "base/e1000_regs.h" #include "base/e1000_hw.h" #include "e1000_ethdev.h" static inline uint16_t dev_num_vf(struct rte_eth_dev *eth_dev) { return eth_dev->pci_dev->max_vfs; } static inline int igb_vf_perm_addr_gen(struct rte_eth_dev *dev, uint16_t vf_num) { unsigned char vf_mac_addr[ETHER_ADDR_LEN]; struct e1000_vf_info *vfinfo = *E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); uint16_t vfn; for (vfn = 0; vfn < vf_num; vfn++) { eth_random_addr(vf_mac_addr); /* keep the random address as default */ memcpy(vfinfo[vfn].vf_mac_addresses, vf_mac_addr, ETHER_ADDR_LEN); } return 0; } static inline int igb_mb_intr_setup(struct rte_eth_dev *dev) { struct e1000_interrupt *intr = E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); intr->mask |= E1000_ICR_VMMB; return 0; } void igb_pf_host_init(struct rte_eth_dev *eth_dev) { struct e1000_vf_info **vfinfo = E1000_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); uint16_t vf_num; uint8_t nb_queue; RTE_ETH_DEV_SRIOV(eth_dev).active = 0; if (0 == (vf_num = dev_num_vf(eth_dev))) return; if (hw->mac.type == e1000_i350) nb_queue = 1; else if(hw->mac.type == e1000_82576) /* per datasheet, it should be 2, but 1 seems correct */ nb_queue = 1; else return; *vfinfo = rte_zmalloc("vf_info", sizeof(struct e1000_vf_info) * vf_num, 0); if (*vfinfo == NULL) rte_panic("Cannot allocate memory for private VF data\n"); RTE_ETH_DEV_SRIOV(eth_dev).active = ETH_8_POOLS; RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = nb_queue; RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = vf_num; RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = (uint16_t)(vf_num * nb_queue); igb_vf_perm_addr_gen(eth_dev, vf_num); /* set mb interrupt mask */ igb_mb_intr_setup(eth_dev); return; } void igb_pf_host_uninit(struct rte_eth_dev *dev) { struct e1000_vf_info **vfinfo; uint16_t vf_num; PMD_INIT_FUNC_TRACE(); vfinfo = E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); RTE_ETH_DEV_SRIOV(dev).active = 0; RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 0; RTE_ETH_DEV_SRIOV(dev).def_vmdq_idx = 0; RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = 0; vf_num = dev_num_vf(dev); if (vf_num == 0) return; rte_free(*vfinfo); *vfinfo = NULL; } #define E1000_RAH_POOLSEL_SHIFT (18) int igb_pf_host_configure(struct rte_eth_dev *eth_dev) { uint32_t vtctl; uint16_t vf_num; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); uint32_t vlanctrl; int i; uint32_t rah; if (0 == (vf_num = dev_num_vf(eth_dev))) return -1; /* enable VMDq and set the default pool for PF */ vtctl = E1000_READ_REG(hw, E1000_VT_CTL); vtctl &= ~E1000_VT_CTL_DEFAULT_POOL_MASK; vtctl |= RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx << E1000_VT_CTL_DEFAULT_POOL_SHIFT; vtctl |= E1000_VT_CTL_VM_REPL_EN; E1000_WRITE_REG(hw, E1000_VT_CTL, vtctl); /* Enable pools reserved to PF only */ E1000_WRITE_REG(hw, E1000_VFRE, (~0) << vf_num); E1000_WRITE_REG(hw, E1000_VFTE, (~0) << vf_num); /* PFDMA Tx General Switch Control Enables VMDQ loopback */ if (hw->mac.type == e1000_i350) E1000_WRITE_REG(hw, E1000_TXSWC, E1000_DTXSWC_VMDQ_LOOPBACK_EN); else E1000_WRITE_REG(hw, E1000_DTXSWC, E1000_DTXSWC_VMDQ_LOOPBACK_EN); /* clear VMDq map to perment rar 0 */ rah = E1000_READ_REG(hw, E1000_RAH(0)); rah &= ~ (0xFF << E1000_RAH_POOLSEL_SHIFT); E1000_WRITE_REG(hw, E1000_RAH(0), rah); /* clear VMDq map to scan rar 32 */ rah = E1000_READ_REG(hw, E1000_RAH(hw->mac.rar_entry_count)); rah &= ~ (0xFF << E1000_RAH_POOLSEL_SHIFT); E1000_WRITE_REG(hw, E1000_RAH(hw->mac.rar_entry_count), rah); /* set VMDq map to default PF pool */ rah = E1000_READ_REG(hw, E1000_RAH(0)); rah |= (0x1 << (RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx + E1000_RAH_POOLSEL_SHIFT)); E1000_WRITE_REG(hw, E1000_RAH(0), rah); /* * enable vlan filtering and allow all vlan tags through */ vlanctrl = E1000_READ_REG(hw, E1000_RCTL); vlanctrl |= E1000_RCTL_VFE ; /* enable vlan filters */ E1000_WRITE_REG(hw, E1000_RCTL, vlanctrl); /* VFTA - enable all vlan filters */ for (i = 0; i < IGB_VFTA_SIZE; i++) { E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, i, 0xFFFFFFFF); } /* Enable/Disable MAC Anti-Spoofing */ e1000_vmdq_set_anti_spoofing_pf(hw, FALSE, vf_num); return 0; } static void set_rx_mode(struct rte_eth_dev *dev) { struct rte_eth_dev_data *dev_data = (struct rte_eth_dev_data*)dev->data->dev_private; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fctrl, vmolr = E1000_VMOLR_BAM | E1000_VMOLR_AUPE; uint16_t vfn = dev_num_vf(dev); /* Check for Promiscuous and All Multicast modes */ fctrl = E1000_READ_REG(hw, E1000_RCTL); /* set all bits that we expect to always be set */ fctrl &= ~E1000_RCTL_SBP; /* disable store-bad-packets */ fctrl |= E1000_RCTL_BAM;; /* clear the bits we are changing the status of */ fctrl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); if (dev_data->promiscuous) { fctrl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); } else { if (dev_data->all_multicast) { fctrl |= E1000_RCTL_MPE; vmolr |= E1000_VMOLR_MPME; } else { vmolr |= E1000_VMOLR_ROMPE; } } if ((hw->mac.type == e1000_82576) || (hw->mac.type == e1000_i350)) { vmolr |= E1000_READ_REG(hw, E1000_VMOLR(vfn)) & ~(E1000_VMOLR_MPME | E1000_VMOLR_ROMPE | E1000_VMOLR_ROPE); E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); } E1000_WRITE_REG(hw, E1000_RCTL, fctrl); } static inline void igb_vf_reset_event(struct rte_eth_dev *dev, uint16_t vf) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_info *vfinfo = *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); uint32_t vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_BAM | E1000_VMOLR_AUPE); E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); E1000_WRITE_REG(hw, E1000_VMVIR(vf), 0); /* reset multicast table array for vf */ vfinfo[vf].num_vf_mc_hashes = 0; /* reset rx mode */ set_rx_mode(dev); } static inline void igb_vf_reset_msg(struct rte_eth_dev *dev, uint16_t vf) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; /* enable transmit and receive for vf */ reg = E1000_READ_REG(hw, E1000_VFTE); reg |= (reg | (1 << vf)); E1000_WRITE_REG(hw, E1000_VFTE, reg); reg = E1000_READ_REG(hw, E1000_VFRE); reg |= (reg | (1 << vf)); E1000_WRITE_REG(hw, E1000_VFRE, reg); igb_vf_reset_event(dev, vf); } static int igb_vf_reset(struct rte_eth_dev *dev, uint16_t vf, uint32_t *msgbuf) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_info *vfinfo = *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); unsigned char *vf_mac = vfinfo[vf].vf_mac_addresses; int rar_entry = hw->mac.rar_entry_count - (vf + 1); uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); uint32_t rah; igb_vf_reset_msg(dev, vf); hw->mac.ops.rar_set(hw, vf_mac, rar_entry); rah = E1000_READ_REG(hw, E1000_RAH(rar_entry)); rah |= (0x1 << (vf + E1000_RAH_POOLSEL_SHIFT)); E1000_WRITE_REG(hw, E1000_RAH(rar_entry), rah); /* reply to reset with ack and vf mac address */ msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; rte_memcpy(new_mac, vf_mac, ETHER_ADDR_LEN); e1000_write_mbx(hw, msgbuf, 3, vf); return 0; } static int igb_vf_set_mac_addr(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_info *vfinfo = *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); int rar_entry = hw->mac.rar_entry_count - (vf + 1); uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); if (is_valid_assigned_ether_addr((struct ether_addr*)new_mac)) { rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, 6); hw->mac.ops.rar_set(hw, new_mac, rar_entry); return 0; } return -1; } static int igb_vf_set_multicast(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *msgbuf) { int i; uint32_t vector_bit; uint32_t vector_reg; uint32_t mta_reg; int entries = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; uint16_t *hash_list = (uint16_t *)&msgbuf[1]; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_info *vfinfo = *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); /* only so many hash values supported */ entries = RTE_MIN(entries, E1000_MAX_VF_MC_ENTRIES); /* * salt away the number of multi cast addresses assigned * to this VF for later use to restore when the PF multi cast * list changes */ vfinfo->num_vf_mc_hashes = (uint16_t)entries; /* * VFs are limited to using the MTA hash table for their multicast * addresses */ for (i = 0; i < entries; i++) { vfinfo->vf_mc_hashes[i] = hash_list[i]; } for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; mta_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, vector_reg); mta_reg |= (1 << vector_bit); E1000_WRITE_REG_ARRAY(hw, E1000_MTA, vector_reg, mta_reg); } return 0; } static int igb_vf_set_vlan(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { int add, vid; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct e1000_vf_info *vfinfo = *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); uint32_t vid_idx, vid_bit, vfta; add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); if (add) vfinfo[vf].vlan_count++; else if (vfinfo[vf].vlan_count) vfinfo[vf].vlan_count--; vid_idx = (uint32_t)((vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK); vid_bit = (uint32_t)(1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK)); vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, vid_idx); if (add) vfta |= vid_bit; else vfta &= ~vid_bit; E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, vid_idx, vfta); E1000_WRITE_FLUSH(hw); return 0; } static int igb_vf_set_rlpml(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint16_t rlpml = msgbuf[1] & E1000_VMOLR_RLPML_MASK; uint32_t max_frame = rlpml + ETHER_HDR_LEN + ETHER_CRC_LEN; uint32_t vmolr; if ((max_frame < ETHER_MIN_LEN) || (max_frame > ETHER_MAX_JUMBO_FRAME_LEN)) return -1; vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); vmolr &= ~E1000_VMOLR_RLPML_MASK; vmolr |= rlpml; /* Enable Long Packet support */ vmolr |= E1000_VMOLR_LPE; E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); E1000_WRITE_FLUSH(hw); return 0; } static int igb_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf) { uint16_t mbx_size = E1000_VFMAILBOX_SIZE; uint32_t msgbuf[E1000_VFMAILBOX_SIZE]; int32_t retval; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); retval = e1000_read_mbx(hw, msgbuf, mbx_size, vf); if (retval) { PMD_INIT_LOG(ERR, "Error mbx recv msg from VF %d", vf); return retval; } /* do nothing with the message already processed */ if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) return retval; /* flush the ack before we write any messages back */ E1000_WRITE_FLUSH(hw); /* perform VF reset */ if (msgbuf[0] == E1000_VF_RESET) { return igb_vf_reset(dev, vf, msgbuf); } /* check & process VF to PF mailbox message */ switch ((msgbuf[0] & 0xFFFF)) { case E1000_VF_SET_MAC_ADDR: retval = igb_vf_set_mac_addr(dev, vf, msgbuf); break; case E1000_VF_SET_MULTICAST: retval = igb_vf_set_multicast(dev, vf, msgbuf); break; case E1000_VF_SET_LPE: retval = igb_vf_set_rlpml(dev, vf, msgbuf); break; case E1000_VF_SET_VLAN: retval = igb_vf_set_vlan(dev, vf, msgbuf); break; default: PMD_INIT_LOG(DEBUG, "Unhandled Msg %8.8x", (unsigned) msgbuf[0]); retval = E1000_ERR_MBX; break; } /* response the VF according to the message process result */ if (retval) msgbuf[0] |= E1000_VT_MSGTYPE_NACK; else msgbuf[0] |= E1000_VT_MSGTYPE_ACK; msgbuf[0] |= E1000_VT_MSGTYPE_CTS; e1000_write_mbx(hw, msgbuf, 1, vf); return retval; } static inline void igb_rcv_ack_from_vf(struct rte_eth_dev *dev, uint16_t vf) { uint32_t msg = E1000_VT_MSGTYPE_NACK; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); e1000_write_mbx(hw, &msg, 1, vf); } void igb_pf_mbx_process(struct rte_eth_dev *eth_dev) { uint16_t vf; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); for (vf = 0; vf < dev_num_vf(eth_dev); vf++) { /* check & process vf function level reset */ if (!e1000_check_for_rst(hw, vf)) igb_vf_reset_event(eth_dev, vf); /* check & process vf mailbox messages */ if (!e1000_check_for_msg(hw, vf)) igb_rcv_msg_from_vf(eth_dev, vf); /* check & process acks from vf */ if (!e1000_check_for_ack(hw, vf)) igb_rcv_ack_from_vf(eth_dev, vf); } } ================================================ FILE: drivers/net/e1000/igb_regs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IGB_REGS_H_ #define _IGB_REGS_H_ #include "e1000_ethdev.h" struct reg_info { uint32_t base_addr; uint32_t count; uint32_t stride; const char *name; }; static const struct reg_info igb_regs_general[] = { {E1000_CTRL, 1, 1, "E1000_CTRL"}, {E1000_STATUS, 1, 1, "E1000_STATUS"}, {E1000_CTRL_EXT, 1, 1, "E1000_CTRL_EXT"}, {E1000_MDIC, 1, 1, "E1000_MDIC"}, {E1000_SCTL, 1, 1, "E1000_SCTL"}, {E1000_CONNSW, 1, 1, "E1000_CONNSW"}, {E1000_VET, 1, 1, "E1000_VET"}, {E1000_LEDCTL, 1, 1, "E1000_LEDCTL"}, {E1000_PBA, 1, 1, "E1000_PBA"}, {E1000_PBS, 1, 1, "E1000_PBS"}, {E1000_FRTIMER, 1, 1, "E1000_FRTIMER"}, {E1000_TCPTIMER, 1, 1, "E1000_TCPTIMER"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_nvm[] = { {E1000_EECD, 1, 1, "E1000_EECD"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_interrupt[] = { {E1000_EICS, 1, 1, "E1000_EICS"}, {E1000_EIMS, 1, 1, "E1000_EIMS"}, {E1000_EIMC, 1, 1, "E1000_EIMC"}, {E1000_EIAC, 1, 1, "E1000_EIAC"}, {E1000_EIAM, 1, 1, "E1000_EIAM"}, {E1000_ICS, 1, 1, "E1000_ICS"}, {E1000_IMS, 1, 1, "E1000_IMS"}, {E1000_IMC, 1, 1, "E1000_IMC"}, {E1000_IAC, 1, 1, "E1000_IAC"}, {E1000_IAM, 1, 1, "E1000_IAM"}, {E1000_IMIRVP, 1, 1, "E1000_IMIRVP"}, {E1000_EITR(0), 10, 4, "E1000_EITR"}, {E1000_IMIR(0), 8, 4, "E1000_IMIR"}, {E1000_IMIREXT(0), 8, 4, "E1000_IMIREXT"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_fctl[] = { {E1000_FCAL, 1, 1, "E1000_FCAL"}, {E1000_FCAH, 1, 1, "E1000_FCAH"}, {E1000_FCTTV, 1, 1, "E1000_FCTTV"}, {E1000_FCRTL, 1, 1, "E1000_FCRTL"}, {E1000_FCRTH, 1, 1, "E1000_FCRTH"}, {E1000_FCRTV, 1, 1, "E1000_FCRTV"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_rxdma[] = { {E1000_RDBAL(0), 4, 0x100, "E1000_RDBAL"}, {E1000_RDBAH(0), 4, 0x100, "E1000_RDBAH"}, {E1000_RDLEN(0), 4, 0x100, "E1000_RDLEN"}, {E1000_RDH(0), 4, 0x100, "E1000_RDH"}, {E1000_RDT(0), 4, 0x100, "E1000_RDT"}, {E1000_RXCTL(0), 4, 0x100, "E1000_RXCTL"}, {E1000_SRRCTL(0), 4, 0x100, "E1000_SRRCTL"}, {E1000_DCA_RXCTRL(0), 4, 0x100, "E1000_DCA_RXCTRL"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_rx[] = { {E1000_RCTL, 1, 1, "E1000_RCTL"}, {E1000_RXCSUM, 1, 1, "E1000_RXCSUM"}, {E1000_RLPML, 1, 1, "E1000_RLPML"}, {E1000_RFCTL, 1, 1, "E1000_RFCTL"}, {E1000_MRQC, 1, 1, "E1000_MRQC"}, {E1000_VT_CTL, 1, 1, "E1000_VT_CTL"}, {E1000_RAL(0), 16, 8, "E1000_RAL"}, {E1000_RAH(0), 16, 8, "E1000_RAH"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_tx[] = { {E1000_TCTL, 1, 1, "E1000_TCTL"}, {E1000_TCTL_EXT, 1, 1, "E1000_TCTL_EXT"}, {E1000_TIPG, 1, 1, "E1000_TIPG"}, {E1000_DTXCTL, 1, 1, "E1000_DTXCTL"}, {E1000_TDBAL(0), 4, 0x100, "E1000_TDBAL"}, {E1000_TDBAH(0), 4, 0x100, "E1000_TDBAH"}, {E1000_TDLEN(0), 4, 0x100, "E1000_TDLEN"}, {E1000_TDH(0), 4, 0x100, "E1000_TDLEN"}, {E1000_TDT(0), 4, 0x100, "E1000_TDT"}, {E1000_TXDCTL(0), 4, 0x100, "E1000_TXDCTL"}, {E1000_TDWBAL(0), 4, 0x100, "E1000_TDWBAL"}, {E1000_TDWBAH(0), 4, 0x100, "E1000_TDWBAH"}, {E1000_DCA_TXCTRL(0), 4, 0x100, "E1000_DCA_TXCTRL"}, {E1000_TDFH, 1, 1, "E1000_TDFH"}, {E1000_TDFT, 1, 1, "E1000_TDFT"}, {E1000_TDFHS, 1, 1, "E1000_TDFHS"}, {E1000_TDFPC, 1, 1, "E1000_TDFPC"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_wakeup[] = { {E1000_WUC, 1, 1, "E1000_WUC"}, {E1000_WUFC, 1, 1, "E1000_WUFC"}, {E1000_WUS, 1, 1, "E1000_WUS"}, {E1000_IPAV, 1, 1, "E1000_IPAV"}, {E1000_WUPL, 1, 1, "E1000_WUPL"}, {E1000_IP4AT_REG(0), 4, 8, "E1000_IP4AT_REG"}, {E1000_IP6AT_REG(0), 4, 4, "E1000_IP6AT_REG"}, {E1000_WUPM_REG(0), 4, 4, "E1000_WUPM_REG"}, {E1000_FFMT_REG(0), 4, 8, "E1000_FFMT_REG"}, {E1000_FFVT_REG(0), 4, 8, "E1000_FFVT_REG"}, {E1000_FFLT_REG(0), 4, 8, "E1000_FFLT_REG"}, {0, 0, 0, ""} }; static const struct reg_info igb_regs_mac[] = { {E1000_PCS_CFG0, 1, 1, "E1000_PCS_CFG0"}, {E1000_PCS_LCTL, 1, 1, "E1000_PCS_LCTL"}, {E1000_PCS_LSTAT, 1, 1, "E1000_PCS_LSTAT"}, {E1000_PCS_ANADV, 1, 1, "E1000_PCS_ANADV"}, {E1000_PCS_LPAB, 1, 1, "E1000_PCS_LPAB"}, {E1000_PCS_NPTX, 1, 1, "E1000_PCS_NPTX"}, {E1000_PCS_LPABNP, 1, 1, "E1000_PCS_LPABNP"}, {0, 0, 0, ""} }; static const struct reg_info *igb_regs[] = { igb_regs_general, igb_regs_nvm, igb_regs_interrupt, igb_regs_fctl, igb_regs_rxdma, igb_regs_rx, igb_regs_tx, igb_regs_wakeup, igb_regs_mac, NULL}; /* FIXME: reading igb_regs_interrupt results side-effect which doesn't * work with VFIO; re-install igb_regs_interrupt once issue is resolved. */ static const struct reg_info *igbvf_regs[] = { igb_regs_general, igb_regs_rxdma, igb_regs_tx, NULL}; static inline int igb_read_regs(struct e1000_hw *hw, const struct reg_info *reg, uint32_t *reg_buf) { unsigned int i; for (i = 0; i < reg->count; i++) { reg_buf[i] = E1000_READ_REG(hw, reg->base_addr + i * reg->stride); } return reg->count; }; static inline int igb_reg_group_count(const struct reg_info *regs) { int count = 0; int i = 0; while (regs[i].count) count += regs[i++].count; return count; }; static inline int igb_read_regs_group(struct rte_eth_dev *dev, uint32_t *reg_buf, const struct reg_info *regs) { int count = 0; int i = 0; struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); while (regs[i].count) count += igb_read_regs(hw, ®s[i++], ®_buf[count]); return count; }; #endif /* _IGB_REGS_H_ */ ================================================ FILE: drivers/net/e1000/igb_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "e1000_logs.h" #include "base/e1000_api.h" #include "e1000_ethdev.h" /* Bit Mask to indicate what bits required for building TX context */ #define IGB_TX_OFFLOAD_MASK ( \ PKT_TX_VLAN_PKT | \ PKT_TX_IP_CKSUM | \ PKT_TX_L4_MASK) static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return (m); } #define RTE_MBUF_DATA_DMA_ADDR(mb) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) /** * Structure associated with each descriptor of the RX ring of a RX queue. */ struct igb_rx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ }; /** * Structure associated with each descriptor of the TX ring of a TX queue. */ struct igb_tx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ uint16_t next_id; /**< Index of next descriptor in ring. */ uint16_t last_id; /**< Index of last scattered descriptor. */ }; /** * Structure associated with each RX queue. */ struct igb_rx_queue { struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ volatile union e1000_adv_rx_desc *rx_ring; /**< RX ring virtual address. */ uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ volatile uint32_t *rdt_reg_addr; /**< RDT register address. */ volatile uint32_t *rdh_reg_addr; /**< RDH register address. */ struct igb_rx_entry *sw_ring; /**< address of RX software ring. */ struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ uint16_t nb_rx_desc; /**< number of RX descriptors. */ uint16_t rx_tail; /**< current value of RDT register. */ uint16_t nb_rx_hold; /**< number of held free RX desc. */ uint16_t rx_free_thresh; /**< max free RX desc to hold. */ uint16_t queue_id; /**< RX queue index. */ uint16_t reg_idx; /**< RX queue register index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold register. */ uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ }; /** * Hardware context number */ enum igb_advctx_num { IGB_CTX_0 = 0, /**< CTX0 */ IGB_CTX_1 = 1, /**< CTX1 */ IGB_CTX_NUM = 2, /**< CTX_NUM */ }; /** Offload features */ union igb_vlan_macip { uint32_t data; struct { uint16_t l2_l3_len; /**< 7bit L2 and 9b L3 lengths combined */ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order). */ } f; }; /* * Compare mask for vlan_macip_len.data, * should be in sync with igb_vlan_macip.f layout. * */ #define TX_VLAN_CMP_MASK 0xFFFF0000 /**< VLAN length - 16-bits. */ #define TX_MAC_LEN_CMP_MASK 0x0000FE00 /**< MAC length - 7-bits. */ #define TX_IP_LEN_CMP_MASK 0x000001FF /**< IP length - 9-bits. */ /** MAC+IP length. */ #define TX_MACIP_LEN_CMP_MASK (TX_MAC_LEN_CMP_MASK | TX_IP_LEN_CMP_MASK) /** * Strucutre to check if new context need be built */ struct igb_advctx_info { uint64_t flags; /**< ol_flags related to context build. */ uint32_t cmp_mask; /**< compare mask for vlan_macip_lens */ union igb_vlan_macip vlan_macip_lens; /**< vlan, mac & ip length. */ }; /** * Structure associated with each TX queue. */ struct igb_tx_queue { volatile union e1000_adv_tx_desc *tx_ring; /**< TX ring address */ uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ struct igb_tx_entry *sw_ring; /**< virtual address of SW ring. */ volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ uint32_t txd_type; /**< Device-specific TXD type */ uint16_t nb_tx_desc; /**< number of TX descriptors. */ uint16_t tx_tail; /**< Current value of TDT register. */ uint16_t tx_head; /**< Index of first used TX descriptor. */ uint16_t queue_id; /**< TX queue index. */ uint16_t reg_idx; /**< TX queue register index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold register. */ uint32_t ctx_curr; /**< Current used hardware descriptor. */ uint32_t ctx_start; /**< Start context position for transmit queue. */ struct igb_advctx_info ctx_cache[IGB_CTX_NUM]; /**< Hardware context history.*/ }; #if 1 #define RTE_PMD_USE_PREFETCH #endif #ifdef RTE_PMD_USE_PREFETCH #define rte_igb_prefetch(p) rte_prefetch0(p) #else #define rte_igb_prefetch(p) do {} while(0) #endif #ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch(p) rte_prefetch1(p) #else #define rte_packet_prefetch(p) do {} while(0) #endif /* * Macro for VMDq feature for 1 GbE NIC. */ #define E1000_VMOLR_SIZE (8) /********************************************************************* * * TX function * **********************************************************************/ /* * Advanced context descriptor are almost same between igb/ixgbe * This is a separate function, looking for optimization opportunity here * Rework required to go with the pre-defined values. */ static inline void igbe_set_xmit_ctx(struct igb_tx_queue* txq, volatile struct e1000_adv_tx_context_desc *ctx_txd, uint64_t ol_flags, uint32_t vlan_macip_lens) { uint32_t type_tucmd_mlhl; uint32_t mss_l4len_idx; uint32_t ctx_idx, ctx_curr; uint32_t cmp_mask; ctx_curr = txq->ctx_curr; ctx_idx = ctx_curr + txq->ctx_start; cmp_mask = 0; type_tucmd_mlhl = 0; if (ol_flags & PKT_TX_VLAN_PKT) { cmp_mask |= TX_VLAN_CMP_MASK; } if (ol_flags & PKT_TX_IP_CKSUM) { type_tucmd_mlhl = E1000_ADVTXD_TUCMD_IPV4; cmp_mask |= TX_MACIP_LEN_CMP_MASK; } /* Specify which HW CTX to upload. */ mss_l4len_idx = (ctx_idx << E1000_ADVTXD_IDX_SHIFT); switch (ol_flags & PKT_TX_L4_MASK) { case PKT_TX_UDP_CKSUM: type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP | E1000_ADVTXD_DTYP_CTXT | E1000_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct udp_hdr) << E1000_ADVTXD_L4LEN_SHIFT; cmp_mask |= TX_MACIP_LEN_CMP_MASK; break; case PKT_TX_TCP_CKSUM: type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP | E1000_ADVTXD_DTYP_CTXT | E1000_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct tcp_hdr) << E1000_ADVTXD_L4LEN_SHIFT; cmp_mask |= TX_MACIP_LEN_CMP_MASK; break; case PKT_TX_SCTP_CKSUM: type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_SCTP | E1000_ADVTXD_DTYP_CTXT | E1000_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct sctp_hdr) << E1000_ADVTXD_L4LEN_SHIFT; cmp_mask |= TX_MACIP_LEN_CMP_MASK; break; default: type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_RSV | E1000_ADVTXD_DTYP_CTXT | E1000_ADVTXD_DCMD_DEXT; break; } txq->ctx_cache[ctx_curr].flags = ol_flags; txq->ctx_cache[ctx_curr].cmp_mask = cmp_mask; txq->ctx_cache[ctx_curr].vlan_macip_lens.data = vlan_macip_lens & cmp_mask; ctx_txd->type_tucmd_mlhl = rte_cpu_to_le_32(type_tucmd_mlhl); ctx_txd->vlan_macip_lens = rte_cpu_to_le_32(vlan_macip_lens); ctx_txd->mss_l4len_idx = rte_cpu_to_le_32(mss_l4len_idx); ctx_txd->seqnum_seed = 0; } /* * Check which hardware context can be used. Use the existing match * or create a new context descriptor. */ static inline uint32_t what_advctx_update(struct igb_tx_queue *txq, uint64_t flags, uint32_t vlan_macip_lens) { /* If match with the current context */ if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) && (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens.data == (txq->ctx_cache[txq->ctx_curr].cmp_mask & vlan_macip_lens)))) { return txq->ctx_curr; } /* If match with the second context */ txq->ctx_curr ^= 1; if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) && (txq->ctx_cache[txq->ctx_curr].vlan_macip_lens.data == (txq->ctx_cache[txq->ctx_curr].cmp_mask & vlan_macip_lens)))) { return txq->ctx_curr; } /* Mismatch, use the previous context */ return (IGB_CTX_NUM); } static inline uint32_t tx_desc_cksum_flags_to_olinfo(uint64_t ol_flags) { static const uint32_t l4_olinfo[2] = {0, E1000_ADVTXD_POPTS_TXSM}; static const uint32_t l3_olinfo[2] = {0, E1000_ADVTXD_POPTS_IXSM}; uint32_t tmp; tmp = l4_olinfo[(ol_flags & PKT_TX_L4_MASK) != PKT_TX_L4_NO_CKSUM]; tmp |= l3_olinfo[(ol_flags & PKT_TX_IP_CKSUM) != 0]; return tmp; } static inline uint32_t tx_desc_vlan_flags_to_cmdtype(uint64_t ol_flags) { static uint32_t vlan_cmd[2] = {0, E1000_ADVTXD_DCMD_VLE}; return vlan_cmd[(ol_flags & PKT_TX_VLAN_PKT) != 0]; } uint16_t eth_igb_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct igb_tx_queue *txq; struct igb_tx_entry *sw_ring; struct igb_tx_entry *txe, *txn; volatile union e1000_adv_tx_desc *txr; volatile union e1000_adv_tx_desc *txd; struct rte_mbuf *tx_pkt; struct rte_mbuf *m_seg; union igb_vlan_macip vlan_macip_lens; union { uint16_t u16; struct { uint16_t l3_len:9; uint16_t l2_len:7; }; } l2_l3_len; uint64_t buf_dma_addr; uint32_t olinfo_status; uint32_t cmd_type_len; uint32_t pkt_len; uint16_t slen; uint64_t ol_flags; uint16_t tx_end; uint16_t tx_id; uint16_t tx_last; uint16_t nb_tx; uint64_t tx_ol_req; uint32_t new_ctx = 0; uint32_t ctx = 0; txq = tx_queue; sw_ring = txq->sw_ring; txr = txq->tx_ring; tx_id = txq->tx_tail; txe = &sw_ring[tx_id]; for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { tx_pkt = *tx_pkts++; pkt_len = tx_pkt->pkt_len; RTE_MBUF_PREFETCH_TO_FREE(txe->mbuf); /* * The number of descriptors that must be allocated for a * packet is the number of segments of that packet, plus 1 * Context Descriptor for the VLAN Tag Identifier, if any. * Determine the last TX descriptor to allocate in the TX ring * for the packet, starting from the current position (tx_id) * in the ring. */ tx_last = (uint16_t) (tx_id + tx_pkt->nb_segs - 1); ol_flags = tx_pkt->ol_flags; l2_l3_len.l2_len = tx_pkt->l2_len; l2_l3_len.l3_len = tx_pkt->l3_len; vlan_macip_lens.f.vlan_tci = tx_pkt->vlan_tci; vlan_macip_lens.f.l2_l3_len = l2_l3_len.u16; tx_ol_req = ol_flags & IGB_TX_OFFLOAD_MASK; /* If a Context Descriptor need be built . */ if (tx_ol_req) { ctx = what_advctx_update(txq, tx_ol_req, vlan_macip_lens.data); /* Only allocate context descriptor if required*/ new_ctx = (ctx == IGB_CTX_NUM); ctx = txq->ctx_curr; tx_last = (uint16_t) (tx_last + new_ctx); } if (tx_last >= txq->nb_tx_desc) tx_last = (uint16_t) (tx_last - txq->nb_tx_desc); PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u" " tx_first=%u tx_last=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) pkt_len, (unsigned) tx_id, (unsigned) tx_last); /* * Check if there are enough free descriptors in the TX ring * to transmit the next packet. * This operation is based on the two following rules: * * 1- Only check that the last needed TX descriptor can be * allocated (by construction, if that descriptor is free, * all intermediate ones are also free). * * For this purpose, the index of the last TX descriptor * used for a packet (the "last descriptor" of a packet) * is recorded in the TX entries (the last one included) * that are associated with all TX descriptors allocated * for that packet. * * 2- Avoid to allocate the last free TX descriptor of the * ring, in order to never set the TDT register with the * same value stored in parallel by the NIC in the TDH * register, which makes the TX engine of the NIC enter * in a deadlock situation. * * By extension, avoid to allocate a free descriptor that * belongs to the last set of free descriptors allocated * to the same packet previously transmitted. */ /* * The "last descriptor" of the previously sent packet, if any, * which used the last descriptor to allocate. */ tx_end = sw_ring[tx_last].last_id; /* * The next descriptor following that "last descriptor" in the * ring. */ tx_end = sw_ring[tx_end].next_id; /* * The "last descriptor" associated with that next descriptor. */ tx_end = sw_ring[tx_end].last_id; /* * Check that this descriptor is free. */ if (! (txr[tx_end].wb.status & E1000_TXD_STAT_DD)) { if (nb_tx == 0) return (0); goto end_of_tx; } /* * Set common flags of all TX Data Descriptors. * * The following bits must be set in all Data Descriptors: * - E1000_ADVTXD_DTYP_DATA * - E1000_ADVTXD_DCMD_DEXT * * The following bits must be set in the first Data Descriptor * and are ignored in the other ones: * - E1000_ADVTXD_DCMD_IFCS * - E1000_ADVTXD_MAC_1588 * - E1000_ADVTXD_DCMD_VLE * * The following bits must only be set in the last Data * Descriptor: * - E1000_TXD_CMD_EOP * * The following bits can be set in any Data Descriptor, but * are only set in the last Data Descriptor: * - E1000_TXD_CMD_RS */ cmd_type_len = txq->txd_type | E1000_ADVTXD_DCMD_IFCS | E1000_ADVTXD_DCMD_DEXT; olinfo_status = (pkt_len << E1000_ADVTXD_PAYLEN_SHIFT); #if defined(RTE_LIBRTE_IEEE1588) if (ol_flags & PKT_TX_IEEE1588_TMST) cmd_type_len |= E1000_ADVTXD_MAC_TSTAMP; #endif if (tx_ol_req) { /* Setup TX Advanced context descriptor if required */ if (new_ctx) { volatile struct e1000_adv_tx_context_desc * ctx_txd; ctx_txd = (volatile struct e1000_adv_tx_context_desc *) &txr[tx_id]; txn = &sw_ring[txe->next_id]; RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf); if (txe->mbuf != NULL) { rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = NULL; } igbe_set_xmit_ctx(txq, ctx_txd, tx_ol_req, vlan_macip_lens.data); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; } /* Setup the TX Advanced Data Descriptor */ cmd_type_len |= tx_desc_vlan_flags_to_cmdtype(ol_flags); olinfo_status |= tx_desc_cksum_flags_to_olinfo(ol_flags); olinfo_status |= (ctx << E1000_ADVTXD_IDX_SHIFT); } m_seg = tx_pkt; do { txn = &sw_ring[txe->next_id]; txd = &txr[tx_id]; if (txe->mbuf != NULL) rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = m_seg; /* * Set up transmit descriptor. */ slen = (uint16_t) m_seg->data_len; buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(m_seg); txd->read.buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txd->read.cmd_type_len = rte_cpu_to_le_32(cmd_type_len | slen); txd->read.olinfo_status = rte_cpu_to_le_32(olinfo_status); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; m_seg = m_seg->next; } while (m_seg != NULL); /* * The last packet data descriptor needs End Of Packet (EOP) * and Report Status (RS). */ txd->read.cmd_type_len |= rte_cpu_to_le_32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS); } end_of_tx: rte_wmb(); /* * Set the Transmit Descriptor Tail (TDT). */ E1000_PCI_REG_WRITE(txq->tdt_reg_addr, tx_id); PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) tx_id, (unsigned) nb_tx); txq->tx_tail = tx_id; return (nb_tx); } /********************************************************************* * * RX functions * **********************************************************************/ #ifdef RTE_NEXT_ABI #define IGB_PACKET_TYPE_IPV4 0X01 #define IGB_PACKET_TYPE_IPV4_TCP 0X11 #define IGB_PACKET_TYPE_IPV4_UDP 0X21 #define IGB_PACKET_TYPE_IPV4_SCTP 0X41 #define IGB_PACKET_TYPE_IPV4_EXT 0X03 #define IGB_PACKET_TYPE_IPV4_EXT_SCTP 0X43 #define IGB_PACKET_TYPE_IPV6 0X04 #define IGB_PACKET_TYPE_IPV6_TCP 0X14 #define IGB_PACKET_TYPE_IPV6_UDP 0X24 #define IGB_PACKET_TYPE_IPV6_EXT 0X0C #define IGB_PACKET_TYPE_IPV6_EXT_TCP 0X1C #define IGB_PACKET_TYPE_IPV6_EXT_UDP 0X2C #define IGB_PACKET_TYPE_IPV4_IPV6 0X05 #define IGB_PACKET_TYPE_IPV4_IPV6_TCP 0X15 #define IGB_PACKET_TYPE_IPV4_IPV6_UDP 0X25 #define IGB_PACKET_TYPE_IPV4_IPV6_EXT 0X0D #define IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D #define IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D #define IGB_PACKET_TYPE_MAX 0X80 #define IGB_PACKET_TYPE_MASK 0X7F #define IGB_PACKET_TYPE_SHIFT 0X04 static inline uint32_t igb_rxd_pkt_info_to_pkt_type(uint16_t pkt_info) { static const uint32_t ptype_table[IGB_PACKET_TYPE_MAX] __rte_cache_aligned = { [IGB_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4, [IGB_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT, [IGB_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6, [IGB_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6, [IGB_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT, [IGB_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT, [IGB_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP, [IGB_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP, [IGB_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP, [IGB_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP, [IGB_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP, [IGB_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP, [IGB_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP, [IGB_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP, [IGB_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP, [IGB_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP, [IGB_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP, [IGB_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP, }; if (unlikely(pkt_info & E1000_RXDADV_PKTTYPE_ETQF)) return RTE_PTYPE_UNKNOWN; pkt_info = (pkt_info >> IGB_PACKET_TYPE_SHIFT) & IGB_PACKET_TYPE_MASK; return ptype_table[pkt_info]; } static inline uint64_t rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs) { uint64_t pkt_flags = ((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH; #if defined(RTE_LIBRTE_IEEE1588) static uint32_t ip_pkt_etqf_map[8] = { 0, 0, 0, PKT_RX_IEEE1588_PTP, 0, 0, 0, 0, }; pkt_flags |= ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07]; #endif return pkt_flags; } #else /* RTE_NEXT_ABI */ static inline uint64_t rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs) { uint64_t pkt_flags; static uint64_t ip_pkt_types_map[16] = { 0, PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT, PKT_RX_IPV4_HDR_EXT, PKT_RX_IPV6_HDR, 0, 0, 0, PKT_RX_IPV6_HDR_EXT, 0, 0, 0, PKT_RX_IPV6_HDR_EXT, 0, 0, 0, }; #if defined(RTE_LIBRTE_IEEE1588) static uint32_t ip_pkt_etqf_map[8] = { 0, 0, 0, PKT_RX_IEEE1588_PTP, 0, 0, 0, 0, }; pkt_flags = (hl_tp_rs & E1000_RXDADV_PKTTYPE_ETQF) ? ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07] : ip_pkt_types_map[(hl_tp_rs >> 4) & 0x0F]; #else pkt_flags = (hl_tp_rs & E1000_RXDADV_PKTTYPE_ETQF) ? 0 : ip_pkt_types_map[(hl_tp_rs >> 4) & 0x0F]; #endif return pkt_flags | (((hl_tp_rs & 0x0F) == 0) ? 0 : PKT_RX_RSS_HASH); } #endif /* RTE_NEXT_ABI */ static inline uint64_t rx_desc_status_to_pkt_flags(uint32_t rx_status) { uint64_t pkt_flags; /* Check if VLAN present */ pkt_flags = (rx_status & E1000_RXD_STAT_VP) ? PKT_RX_VLAN_PKT : 0; #if defined(RTE_LIBRTE_IEEE1588) if (rx_status & E1000_RXD_STAT_TMST) pkt_flags = pkt_flags | PKT_RX_IEEE1588_TMST; #endif return pkt_flags; } static inline uint64_t rx_desc_error_to_pkt_flags(uint32_t rx_status) { /* * Bit 30: IPE, IPv4 checksum error * Bit 29: L4I, L4I integrity error */ static uint64_t error_to_pkt_flags_map[4] = { 0, PKT_RX_L4_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD }; return error_to_pkt_flags_map[(rx_status >> E1000_RXD_ERR_CKSUM_BIT) & E1000_RXD_ERR_CKSUM_MSK]; } uint16_t eth_igb_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct igb_rx_queue *rxq; volatile union e1000_adv_rx_desc *rx_ring; volatile union e1000_adv_rx_desc *rxdp; struct igb_rx_entry *sw_ring; struct igb_rx_entry *rxe; struct rte_mbuf *rxm; struct rte_mbuf *nmb; union e1000_adv_rx_desc rxd; uint64_t dma_addr; uint32_t staterr; uint32_t hlen_type_rss; uint16_t pkt_len; uint16_t rx_id; uint16_t nb_rx; uint16_t nb_hold; uint64_t pkt_flags; nb_rx = 0; nb_hold = 0; rxq = rx_queue; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; while (nb_rx < nb_pkts) { /* * The order of operations here is important as the DD status * bit must not be read after any other descriptor fields. * rx_ring and rxdp are pointing to volatile data so the order * of accesses cannot be reordered by the compiler. If they were * not volatile, they could be reordered which could lead to * using invalid descriptor fields when read from rxd. */ rxdp = &rx_ring[rx_id]; staterr = rxdp->wb.upper.status_error; if (! (staterr & rte_cpu_to_le_32(E1000_RXD_STAT_DD))) break; rxd = *rxdp; /* * End of packet. * * If the E1000_RXD_STAT_EOP flag is not set, the RX packet is * likely to be invalid and to be dropped by the various * validation checks performed by the network stack. * * Allocate a new mbuf to replenish the RX ring descriptor. * If the allocation fails: * - arrange for that RX descriptor to be the first one * being parsed the next time the receive function is * invoked [on the same queue]. * * - Stop parsing the RX ring and return immediately. * * This policy do not drop the packet received in the RX * descriptor for which the allocation of a new mbuf failed. * Thus, it allows that packet to be later retrieved if * mbuf have been freed in the mean time. * As a side effect, holding RX descriptors instead of * systematically giving them back to the NIC may lead to * RX ring exhaustion situations. * However, the NIC can gracefully prevent such situations * to happen by sending specific "back-pressure" flow control * frames to its peer(s). */ PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "staterr=0x%x pkt_len=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) staterr, (unsigned) rte_le_to_cpu_16(rxd.wb.upper.length)); nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++; break; } nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf while processing current one. */ rte_igb_prefetch(sw_ring[rx_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_igb_prefetch(&rx_ring[rx_id]); rte_igb_prefetch(&sw_ring[rx_id]); } rxm = rxe->mbuf; rxe->mbuf = nmb; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->read.hdr_addr = 0; rxdp->read.pkt_addr = dma_addr; /* * Initialize the returned mbuf. * 1) setup generic mbuf fields: * - number of segments, * - next segment, * - packet length, * - RX port identifier. * 2) integrate hardware offload data, if any: * - RSS flag & hash, * - IP checksum flag, * - VLAN TCI, if any, * - error flags. */ pkt_len = (uint16_t) (rte_le_to_cpu_16(rxd.wb.upper.length) - rxq->crc_len); rxm->data_off = RTE_PKTMBUF_HEADROOM; rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off); rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = pkt_len; rxm->data_len = pkt_len; rxm->port = rxq->port_id; rxm->hash.rss = rxd.wb.lower.hi_dword.rss; hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data); /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan); pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss); pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr); pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr); rxm->ol_flags = pkt_flags; #ifdef RTE_NEXT_ABI rxm->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb.lower. lo_dword.hs_rss.pkt_info); #endif /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = rxm; } rxq->rx_tail = rx_id; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ nb_hold = (uint16_t) (nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) nb_hold, (unsigned) nb_rx); rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); E1000_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return (nb_rx); } uint16_t eth_igb_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct igb_rx_queue *rxq; volatile union e1000_adv_rx_desc *rx_ring; volatile union e1000_adv_rx_desc *rxdp; struct igb_rx_entry *sw_ring; struct igb_rx_entry *rxe; struct rte_mbuf *first_seg; struct rte_mbuf *last_seg; struct rte_mbuf *rxm; struct rte_mbuf *nmb; union e1000_adv_rx_desc rxd; uint64_t dma; /* Physical address of mbuf data buffer */ uint32_t staterr; uint32_t hlen_type_rss; uint16_t rx_id; uint16_t nb_rx; uint16_t nb_hold; uint16_t data_len; uint64_t pkt_flags; nb_rx = 0; nb_hold = 0; rxq = rx_queue; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; /* * Retrieve RX context of current packet, if any. */ first_seg = rxq->pkt_first_seg; last_seg = rxq->pkt_last_seg; while (nb_rx < nb_pkts) { next_desc: /* * The order of operations here is important as the DD status * bit must not be read after any other descriptor fields. * rx_ring and rxdp are pointing to volatile data so the order * of accesses cannot be reordered by the compiler. If they were * not volatile, they could be reordered which could lead to * using invalid descriptor fields when read from rxd. */ rxdp = &rx_ring[rx_id]; staterr = rxdp->wb.upper.status_error; if (! (staterr & rte_cpu_to_le_32(E1000_RXD_STAT_DD))) break; rxd = *rxdp; /* * Descriptor done. * * Allocate a new mbuf to replenish the RX ring descriptor. * If the allocation fails: * - arrange for that RX descriptor to be the first one * being parsed the next time the receive function is * invoked [on the same queue]. * * - Stop parsing the RX ring and return immediately. * * This policy does not drop the packet received in the RX * descriptor for which the allocation of a new mbuf failed. * Thus, it allows that packet to be later retrieved if * mbuf have been freed in the mean time. * As a side effect, holding RX descriptors instead of * systematically giving them back to the NIC may lead to * RX ring exhaustion situations. * However, the NIC can gracefully prevent such situations * to happen by sending specific "back-pressure" flow control * frames to its peer(s). */ PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "staterr=0x%x data_len=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) staterr, (unsigned) rte_le_to_cpu_16(rxd.wb.upper.length)); nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++; break; } nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf while processing current one. */ rte_igb_prefetch(sw_ring[rx_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_igb_prefetch(&rx_ring[rx_id]); rte_igb_prefetch(&sw_ring[rx_id]); } /* * Update RX descriptor with the physical address of the new * data buffer of the new allocated mbuf. */ rxm = rxe->mbuf; rxe->mbuf = nmb; dma = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->read.pkt_addr = dma; rxdp->read.hdr_addr = 0; /* * Set data length & data buffer address of mbuf. */ data_len = rte_le_to_cpu_16(rxd.wb.upper.length); rxm->data_len = data_len; rxm->data_off = RTE_PKTMBUF_HEADROOM; /* * If this is the first buffer of the received packet, * set the pointer to the first mbuf of the packet and * initialize its context. * Otherwise, update the total length and the number of segments * of the current scattered packet, and update the pointer to * the last mbuf of the current packet. */ if (first_seg == NULL) { first_seg = rxm; first_seg->pkt_len = data_len; first_seg->nb_segs = 1; } else { first_seg->pkt_len += data_len; first_seg->nb_segs++; last_seg->next = rxm; } /* * If this is not the last buffer of the received packet, * update the pointer to the last mbuf of the current scattered * packet and continue to parse the RX ring. */ if (! (staterr & E1000_RXD_STAT_EOP)) { last_seg = rxm; goto next_desc; } /* * This is the last buffer of the received packet. * If the CRC is not stripped by the hardware: * - Subtract the CRC length from the total packet length. * - If the last buffer only contains the whole CRC or a part * of it, free the mbuf associated to the last buffer. * If part of the CRC is also contained in the previous * mbuf, subtract the length of that CRC part from the * data length of the previous mbuf. */ rxm->next = NULL; if (unlikely(rxq->crc_len > 0)) { first_seg->pkt_len -= ETHER_CRC_LEN; if (data_len <= ETHER_CRC_LEN) { rte_pktmbuf_free_seg(rxm); first_seg->nb_segs--; last_seg->data_len = (uint16_t) (last_seg->data_len - (ETHER_CRC_LEN - data_len)); last_seg->next = NULL; } else rxm->data_len = (uint16_t) (data_len - ETHER_CRC_LEN); } /* * Initialize the first mbuf of the returned packet: * - RX port identifier, * - hardware offload data, if any: * - RSS flag & hash, * - IP checksum flag, * - VLAN TCI, if any, * - error flags. */ first_seg->port = rxq->port_id; first_seg->hash.rss = rxd.wb.lower.hi_dword.rss; /* * The vlan_tci field is only valid when PKT_RX_VLAN_PKT is * set in the pkt_flags field. */ first_seg->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan); hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data); pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss); pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr); pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr); first_seg->ol_flags = pkt_flags; #ifdef RTE_NEXT_ABI first_seg->packet_type = igb_rxd_pkt_info_to_pkt_type(rxd.wb. lower.lo_dword.hs_rss.pkt_info); #endif /* Prefetch data of first segment, if configured to do so. */ rte_packet_prefetch((char *)first_seg->buf_addr + first_seg->data_off); /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = first_seg; /* * Setup receipt context for a new packet. */ first_seg = NULL; } /* * Record index of the next RX descriptor to probe. */ rxq->rx_tail = rx_id; /* * Save receive context. */ rxq->pkt_first_seg = first_seg; rxq->pkt_last_seg = last_seg; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ nb_hold = (uint16_t) (nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) nb_hold, (unsigned) nb_rx); rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); E1000_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return (nb_rx); } /* * Rings setup and release. * * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. * This will also optimize cache line size effect. * H/W supports up to cache line size 128. */ #define IGB_ALIGN 128 /* * Maximum number of Ring Descriptors. * * Since RDLEN/TDLEN should be multiple of 128bytes, the number of ring * desscriptors should meet the following condition: * (num_ring_desc * sizeof(struct e1000_rx/tx_desc)) % 128 == 0 */ #define IGB_MIN_RING_DESC 32 #define IGB_MAX_RING_DESC 4096 static const struct rte_memzone * ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); mz = rte_memzone_lookup(z_name); if (mz) return mz; #ifdef RTE_LIBRTE_XEN_DOM0 return rte_memzone_reserve_bounded(z_name, ring_size, socket_id, 0, IGB_ALIGN, RTE_PGSIZE_2M); #else return rte_memzone_reserve_aligned(z_name, ring_size, socket_id, 0, IGB_ALIGN); #endif } static void igb_tx_queue_release_mbufs(struct igb_tx_queue *txq) { unsigned i; if (txq->sw_ring != NULL) { for (i = 0; i < txq->nb_tx_desc; i++) { if (txq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); txq->sw_ring[i].mbuf = NULL; } } } } static void igb_tx_queue_release(struct igb_tx_queue *txq) { if (txq != NULL) { igb_tx_queue_release_mbufs(txq); rte_free(txq->sw_ring); rte_free(txq); } } void eth_igb_tx_queue_release(void *txq) { igb_tx_queue_release(txq); } static void igb_reset_tx_queue_stat(struct igb_tx_queue *txq) { txq->tx_head = 0; txq->tx_tail = 0; txq->ctx_curr = 0; memset((void*)&txq->ctx_cache, 0, IGB_CTX_NUM * sizeof(struct igb_advctx_info)); } static void igb_reset_tx_queue(struct igb_tx_queue *txq, struct rte_eth_dev *dev) { static const union e1000_adv_tx_desc zeroed_desc = {{0}}; struct igb_tx_entry *txe = txq->sw_ring; uint16_t i, prev; struct e1000_hw *hw; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Zero out HW ring memory */ for (i = 0; i < txq->nb_tx_desc; i++) { txq->tx_ring[i] = zeroed_desc; } /* Initialize ring entries */ prev = (uint16_t)(txq->nb_tx_desc - 1); for (i = 0; i < txq->nb_tx_desc; i++) { volatile union e1000_adv_tx_desc *txd = &(txq->tx_ring[i]); txd->wb.status = E1000_TXD_STAT_DD; txe[i].mbuf = NULL; txe[i].last_id = i; txe[prev].next_id = i; prev = i; } txq->txd_type = E1000_ADVTXD_DTYP_DATA; /* 82575 specific, each tx queue will use 2 hw contexts */ if (hw->mac.type == e1000_82575) txq->ctx_start = txq->queue_id * IGB_CTX_NUM; igb_reset_tx_queue_stat(txq); } int eth_igb_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { const struct rte_memzone *tz; struct igb_tx_queue *txq; struct e1000_hw *hw; uint32_t size; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Validate number of transmit descriptors. * It must not exceed hardware maximum, and must be multiple * of IGB_ALIGN. */ if (((nb_desc * sizeof(union e1000_adv_tx_desc)) % IGB_ALIGN) != 0 || (nb_desc > IGB_MAX_RING_DESC) || (nb_desc < IGB_MIN_RING_DESC)) { return -EINVAL; } /* * The tx_free_thresh and tx_rs_thresh values are not used in the 1G * driver. */ if (tx_conf->tx_free_thresh != 0) PMD_INIT_LOG(WARNING, "The tx_free_thresh parameter is not " "used for the 1G driver."); if (tx_conf->tx_rs_thresh != 0) PMD_INIT_LOG(WARNING, "The tx_rs_thresh parameter is not " "used for the 1G driver."); if (tx_conf->tx_thresh.wthresh == 0) PMD_INIT_LOG(WARNING, "To improve 1G driver performance, " "consider setting the TX WTHRESH value to 4, 8, " "or 16."); /* Free memory prior to re-allocation if needed */ if (dev->data->tx_queues[queue_idx] != NULL) { igb_tx_queue_release(dev->data->tx_queues[queue_idx]); dev->data->tx_queues[queue_idx] = NULL; } /* First allocate the tx queue data structure */ txq = rte_zmalloc("ethdev TX queue", sizeof(struct igb_tx_queue), RTE_CACHE_LINE_SIZE); if (txq == NULL) return (-ENOMEM); /* * Allocate TX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ size = sizeof(union e1000_adv_tx_desc) * IGB_MAX_RING_DESC; tz = ring_dma_zone_reserve(dev, "tx_ring", queue_idx, size, socket_id); if (tz == NULL) { igb_tx_queue_release(txq); return (-ENOMEM); } txq->nb_tx_desc = nb_desc; txq->pthresh = tx_conf->tx_thresh.pthresh; txq->hthresh = tx_conf->tx_thresh.hthresh; txq->wthresh = tx_conf->tx_thresh.wthresh; if (txq->wthresh > 0 && hw->mac.type == e1000_82576) txq->wthresh = 1; txq->queue_id = queue_idx; txq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); txq->port_id = dev->data->port_id; txq->tdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_TDT(txq->reg_idx)); #ifndef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = (uint64_t) tz->phys_addr; #else txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); #endif txq->tx_ring = (union e1000_adv_tx_desc *) tz->addr; /* Allocate software ring */ txq->sw_ring = rte_zmalloc("txq->sw_ring", sizeof(struct igb_tx_entry) * nb_desc, RTE_CACHE_LINE_SIZE); if (txq->sw_ring == NULL) { igb_tx_queue_release(txq); return (-ENOMEM); } PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); igb_reset_tx_queue(txq, dev); dev->tx_pkt_burst = eth_igb_xmit_pkts; dev->data->tx_queues[queue_idx] = txq; return (0); } static void igb_rx_queue_release_mbufs(struct igb_rx_queue *rxq) { unsigned i; if (rxq->sw_ring != NULL) { for (i = 0; i < rxq->nb_rx_desc; i++) { if (rxq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); rxq->sw_ring[i].mbuf = NULL; } } } } static void igb_rx_queue_release(struct igb_rx_queue *rxq) { if (rxq != NULL) { igb_rx_queue_release_mbufs(rxq); rte_free(rxq->sw_ring); rte_free(rxq); } } void eth_igb_rx_queue_release(void *rxq) { igb_rx_queue_release(rxq); } static void igb_reset_rx_queue(struct igb_rx_queue *rxq) { static const union e1000_adv_rx_desc zeroed_desc = {{0}}; unsigned i; /* Zero out HW ring memory */ for (i = 0; i < rxq->nb_rx_desc; i++) { rxq->rx_ring[i] = zeroed_desc; } rxq->rx_tail = 0; rxq->pkt_first_seg = NULL; rxq->pkt_last_seg = NULL; } int eth_igb_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { const struct rte_memzone *rz; struct igb_rx_queue *rxq; struct e1000_hw *hw; unsigned int size; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Validate number of receive descriptors. * It must not exceed hardware maximum, and must be multiple * of IGB_ALIGN. */ if (((nb_desc * sizeof(union e1000_adv_rx_desc)) % IGB_ALIGN) != 0 || (nb_desc > IGB_MAX_RING_DESC) || (nb_desc < IGB_MIN_RING_DESC)) { return (-EINVAL); } /* Free memory prior to re-allocation if needed */ if (dev->data->rx_queues[queue_idx] != NULL) { igb_rx_queue_release(dev->data->rx_queues[queue_idx]); dev->data->rx_queues[queue_idx] = NULL; } /* First allocate the RX queue data structure. */ rxq = rte_zmalloc("ethdev RX queue", sizeof(struct igb_rx_queue), RTE_CACHE_LINE_SIZE); if (rxq == NULL) return (-ENOMEM); rxq->mb_pool = mp; rxq->nb_rx_desc = nb_desc; rxq->pthresh = rx_conf->rx_thresh.pthresh; rxq->hthresh = rx_conf->rx_thresh.hthresh; rxq->wthresh = rx_conf->rx_thresh.wthresh; if (rxq->wthresh > 0 && hw->mac.type == e1000_82576) rxq->wthresh = 1; rxq->drop_en = rx_conf->rx_drop_en; rxq->rx_free_thresh = rx_conf->rx_free_thresh; rxq->queue_id = queue_idx; rxq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); /* * Allocate RX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ size = sizeof(union e1000_adv_rx_desc) * IGB_MAX_RING_DESC; rz = ring_dma_zone_reserve(dev, "rx_ring", queue_idx, size, socket_id); if (rz == NULL) { igb_rx_queue_release(rxq); return (-ENOMEM); } rxq->rdt_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDT(rxq->reg_idx)); rxq->rdh_reg_addr = E1000_PCI_REG_ADDR(hw, E1000_RDH(rxq->reg_idx)); #ifndef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = (uint64_t) rz->phys_addr; #else rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); #endif rxq->rx_ring = (union e1000_adv_rx_desc *) rz->addr; /* Allocate software ring. */ rxq->sw_ring = rte_zmalloc("rxq->sw_ring", sizeof(struct igb_rx_entry) * nb_desc, RTE_CACHE_LINE_SIZE); if (rxq->sw_ring == NULL) { igb_rx_queue_release(rxq); return (-ENOMEM); } PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, rxq->sw_ring, rxq->rx_ring, rxq->rx_ring_phys_addr); dev->data->rx_queues[queue_idx] = rxq; igb_reset_rx_queue(rxq); return 0; } uint32_t eth_igb_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { #define IGB_RXQ_SCAN_INTERVAL 4 volatile union e1000_adv_rx_desc *rxdp; struct igb_rx_queue *rxq; uint32_t desc = 0; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_RX_LOG(ERR, "Invalid RX queue id=%d", rx_queue_id); return 0; } rxq = dev->data->rx_queues[rx_queue_id]; rxdp = &(rxq->rx_ring[rxq->rx_tail]); while ((desc < rxq->nb_rx_desc) && (rxdp->wb.upper.status_error & E1000_RXD_STAT_DD)) { desc += IGB_RXQ_SCAN_INTERVAL; rxdp += IGB_RXQ_SCAN_INTERVAL; if (rxq->rx_tail + desc >= rxq->nb_rx_desc) rxdp = &(rxq->rx_ring[rxq->rx_tail + desc - rxq->nb_rx_desc]); } return 0; } int eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset) { volatile union e1000_adv_rx_desc *rxdp; struct igb_rx_queue *rxq = rx_queue; uint32_t desc; if (unlikely(offset >= rxq->nb_rx_desc)) return 0; desc = rxq->rx_tail + offset; if (desc >= rxq->nb_rx_desc) desc -= rxq->nb_rx_desc; rxdp = &rxq->rx_ring[desc]; return !!(rxdp->wb.upper.status_error & E1000_RXD_STAT_DD); } void igb_dev_clear_queues(struct rte_eth_dev *dev) { uint16_t i; struct igb_tx_queue *txq; struct igb_rx_queue *rxq; for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; if (txq != NULL) { igb_tx_queue_release_mbufs(txq); igb_reset_tx_queue(txq, dev); } } for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; if (rxq != NULL) { igb_rx_queue_release_mbufs(rxq); igb_reset_rx_queue(rxq); } } } void igb_dev_free_queues(struct rte_eth_dev *dev) { uint16_t i; for (i = 0; i < dev->data->nb_rx_queues; i++) { eth_igb_rx_queue_release(dev->data->rx_queues[i]); dev->data->rx_queues[i] = NULL; } dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) { eth_igb_tx_queue_release(dev->data->tx_queues[i]); dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; } /** * Receive Side Scaling (RSS). * See section 7.1.1.7 in the following document: * "Intel 82576 GbE Controller Datasheet" - Revision 2.45 October 2009 * * Principles: * The source and destination IP addresses of the IP header and the source and * destination ports of TCP/UDP headers, if any, of received packets are hashed * against a configurable random key to compute a 32-bit RSS hash result. * The seven (7) LSBs of the 32-bit hash result are used as an index into a * 128-entry redirection table (RETA). Each entry of the RETA provides a 3-bit * RSS output index which is used as the RX queue index where to store the * received packets. * The following output is supplied in the RX write-back descriptor: * - 32-bit result of the Microsoft RSS hash function, * - 4-bit RSS type field. */ /* * RSS random key supplied in section 7.1.1.7.3 of the Intel 82576 datasheet. * Used as the default key. */ static uint8_t rss_intel_key[40] = { 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; static void igb_rss_disable(struct rte_eth_dev *dev) { struct e1000_hw *hw; uint32_t mrqc; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); mrqc = E1000_READ_REG(hw, E1000_MRQC); mrqc &= ~E1000_MRQC_ENABLE_MASK; E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } static void igb_hw_rss_hash_set(struct e1000_hw *hw, struct rte_eth_rss_conf *rss_conf) { uint8_t *hash_key; uint32_t rss_key; uint32_t mrqc; uint64_t rss_hf; uint16_t i; hash_key = rss_conf->rss_key; if (hash_key != NULL) { /* Fill in RSS hash key */ for (i = 0; i < 10; i++) { rss_key = hash_key[(i * 4)]; rss_key |= hash_key[(i * 4) + 1] << 8; rss_key |= hash_key[(i * 4) + 2] << 16; rss_key |= hash_key[(i * 4) + 3] << 24; E1000_WRITE_REG_ARRAY(hw, E1000_RSSRK(0), i, rss_key); } } /* Set configured hashing protocols in MRQC register */ rss_hf = rss_conf->rss_hf; mrqc = E1000_MRQC_ENABLE_RSS_4Q; /* RSS enabled. */ if (rss_hf & ETH_RSS_IPV4) mrqc |= E1000_MRQC_RSS_FIELD_IPV4; if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) mrqc |= E1000_MRQC_RSS_FIELD_IPV4_TCP; if (rss_hf & ETH_RSS_IPV6) mrqc |= E1000_MRQC_RSS_FIELD_IPV6; if (rss_hf & ETH_RSS_IPV6_EX) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_EX; if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_TCP; if (rss_hf & ETH_RSS_IPV6_TCP_EX) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; if (rss_hf & ETH_RSS_IPV6_UDP_EX) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP_EX; E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } int eth_igb_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct e1000_hw *hw; uint32_t mrqc; uint64_t rss_hf; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Before changing anything, first check that the update RSS operation * does not attempt to disable RSS, if RSS was enabled at * initialization time, or does not attempt to enable RSS, if RSS was * disabled at initialization time. */ rss_hf = rss_conf->rss_hf & IGB_RSS_OFFLOAD_ALL; mrqc = E1000_READ_REG(hw, E1000_MRQC); if (!(mrqc & E1000_MRQC_ENABLE_MASK)) { /* RSS disabled */ if (rss_hf != 0) /* Enable RSS */ return -(EINVAL); return 0; /* Nothing to do */ } /* RSS enabled */ if (rss_hf == 0) /* Disable RSS */ return -(EINVAL); igb_hw_rss_hash_set(hw, rss_conf); return 0; } int eth_igb_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct e1000_hw *hw; uint8_t *hash_key; uint32_t rss_key; uint32_t mrqc; uint64_t rss_hf; uint16_t i; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); hash_key = rss_conf->rss_key; if (hash_key != NULL) { /* Return RSS hash key */ for (i = 0; i < 10; i++) { rss_key = E1000_READ_REG_ARRAY(hw, E1000_RSSRK(0), i); hash_key[(i * 4)] = rss_key & 0x000000FF; hash_key[(i * 4) + 1] = (rss_key >> 8) & 0x000000FF; hash_key[(i * 4) + 2] = (rss_key >> 16) & 0x000000FF; hash_key[(i * 4) + 3] = (rss_key >> 24) & 0x000000FF; } } /* Get RSS functions configured in MRQC register */ mrqc = E1000_READ_REG(hw, E1000_MRQC); if ((mrqc & E1000_MRQC_ENABLE_RSS_4Q) == 0) { /* RSS is disabled */ rss_conf->rss_hf = 0; return 0; } rss_hf = 0; if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) rss_hf |= ETH_RSS_IPV4; if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) rss_hf |= ETH_RSS_IPV6; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_EX) rss_hf |= ETH_RSS_IPV6_EX; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP_EX) rss_hf |= ETH_RSS_IPV6_TCP_EX; if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_UDP) rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_UDP) rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP; if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_UDP_EX) rss_hf |= ETH_RSS_IPV6_UDP_EX; rss_conf->rss_hf = rss_hf; return 0; } static void igb_rss_configure(struct rte_eth_dev *dev) { struct rte_eth_rss_conf rss_conf; struct e1000_hw *hw; uint32_t shift; uint16_t i; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Fill in redirection table. */ shift = (hw->mac.type == e1000_82575) ? 6 : 0; for (i = 0; i < 128; i++) { union e1000_reta { uint32_t dword; uint8_t bytes[4]; } reta; uint8_t q_idx; q_idx = (uint8_t) ((dev->data->nb_rx_queues > 1) ? i % dev->data->nb_rx_queues : 0); reta.bytes[i & 3] = (uint8_t) (q_idx << shift); if ((i & 3) == 3) E1000_WRITE_REG(hw, E1000_RETA(i >> 2), reta.dword); } /* * Configure the RSS key and the RSS protocols used to compute * the RSS hash of input packets. */ rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf; if ((rss_conf.rss_hf & IGB_RSS_OFFLOAD_ALL) == 0) { igb_rss_disable(dev); return; } if (rss_conf.rss_key == NULL) rss_conf.rss_key = rss_intel_key; /* Default hash key */ igb_hw_rss_hash_set(hw, &rss_conf); } /* * Check if the mac type support VMDq or not. * Return 1 if it supports, otherwise, return 0. */ static int igb_is_vmdq_supported(const struct rte_eth_dev *dev) { const struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); switch (hw->mac.type) { case e1000_82576: case e1000_82580: case e1000_i350: return 1; case e1000_82540: case e1000_82541: case e1000_82542: case e1000_82543: case e1000_82544: case e1000_82545: case e1000_82546: case e1000_82547: case e1000_82571: case e1000_82572: case e1000_82573: case e1000_82574: case e1000_82583: case e1000_i210: case e1000_i211: default: PMD_INIT_LOG(ERR, "Cannot support VMDq feature"); return 0; } } static int igb_vmdq_rx_hw_configure(struct rte_eth_dev *dev) { struct rte_eth_vmdq_rx_conf *cfg; struct e1000_hw *hw; uint32_t mrqc, vt_ctl, vmolr, rctl; int i; PMD_INIT_FUNC_TRACE(); hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; /* Check if mac type can support VMDq, return value of 0 means NOT support */ if (igb_is_vmdq_supported(dev) == 0) return -1; igb_rss_disable(dev); /* RCTL: eanble VLAN filter */ rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); /* MRQC: enable vmdq */ mrqc = E1000_READ_REG(hw, E1000_MRQC); mrqc |= E1000_MRQC_ENABLE_VMDQ; E1000_WRITE_REG(hw, E1000_MRQC, mrqc); /* VTCTL: pool selection according to VLAN tag */ vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); if (cfg->enable_default_pool) vt_ctl |= (cfg->default_pool << E1000_VT_CTL_DEFAULT_POOL_SHIFT); vt_ctl |= E1000_VT_CTL_IGNORE_MAC; E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); for (i = 0; i < E1000_VMOLR_SIZE; i++) { vmolr = E1000_READ_REG(hw, E1000_VMOLR(i)); vmolr &= ~(E1000_VMOLR_AUPE | E1000_VMOLR_ROMPE | E1000_VMOLR_ROPE | E1000_VMOLR_BAM | E1000_VMOLR_MPME); if (cfg->rx_mode & ETH_VMDQ_ACCEPT_UNTAG) vmolr |= E1000_VMOLR_AUPE; if (cfg->rx_mode & ETH_VMDQ_ACCEPT_HASH_MC) vmolr |= E1000_VMOLR_ROMPE; if (cfg->rx_mode & ETH_VMDQ_ACCEPT_HASH_UC) vmolr |= E1000_VMOLR_ROPE; if (cfg->rx_mode & ETH_VMDQ_ACCEPT_BROADCAST) vmolr |= E1000_VMOLR_BAM; if (cfg->rx_mode & ETH_VMDQ_ACCEPT_MULTICAST) vmolr |= E1000_VMOLR_MPME; E1000_WRITE_REG(hw, E1000_VMOLR(i), vmolr); } /* * VMOLR: set STRVLAN as 1 if IGMAC in VTCTL is set as 1 * Both 82576 and 82580 support it */ if (hw->mac.type != e1000_i350) { for (i = 0; i < E1000_VMOLR_SIZE; i++) { vmolr = E1000_READ_REG(hw, E1000_VMOLR(i)); vmolr |= E1000_VMOLR_STRVLAN; E1000_WRITE_REG(hw, E1000_VMOLR(i), vmolr); } } /* VFTA - enable all vlan filters */ for (i = 0; i < IGB_VFTA_SIZE; i++) E1000_WRITE_REG(hw, (E1000_VFTA+(i*4)), UINT32_MAX); /* VFRE: 8 pools enabling for rx, both 82576 and i350 support it */ if (hw->mac.type != e1000_82580) E1000_WRITE_REG(hw, E1000_VFRE, E1000_MBVFICR_VFREQ_MASK); /* * RAH/RAL - allow pools to read specific mac addresses * In this case, all pools should be able to read from mac addr 0 */ E1000_WRITE_REG(hw, E1000_RAH(0), (E1000_RAH_AV | UINT16_MAX)); E1000_WRITE_REG(hw, E1000_RAL(0), UINT32_MAX); /* VLVF: set up filters for vlan tags as configured */ for (i = 0; i < cfg->nb_pool_maps; i++) { /* set vlan id in VF register and set the valid bit */ E1000_WRITE_REG(hw, E1000_VLVF(i), (E1000_VLVF_VLANID_ENABLE | \ (cfg->pool_map[i].vlan_id & ETH_VLAN_ID_MAX) | \ ((cfg->pool_map[i].pools << E1000_VLVF_POOLSEL_SHIFT ) & \ E1000_VLVF_POOLSEL_MASK))); } E1000_WRITE_FLUSH(hw); return 0; } /********************************************************************* * * Enable receive unit. * **********************************************************************/ static int igb_alloc_rx_queue_mbufs(struct igb_rx_queue *rxq) { struct igb_rx_entry *rxe = rxq->sw_ring; uint64_t dma_addr; unsigned i; /* Initialize software ring entries. */ for (i = 0; i < rxq->nb_rx_desc; i++) { volatile union e1000_adv_rx_desc *rxd; struct rte_mbuf *mbuf = rte_rxmbuf_alloc(rxq->mb_pool); if (mbuf == NULL) { PMD_INIT_LOG(ERR, "RX mbuf alloc failed " "queue_id=%hu", rxq->queue_id); return (-ENOMEM); } dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf)); rxd = &rxq->rx_ring[i]; rxd->read.hdr_addr = 0; rxd->read.pkt_addr = dma_addr; rxe[i].mbuf = mbuf; } return 0; } #define E1000_MRQC_DEF_Q_SHIFT (3) static int igb_dev_mq_rx_configure(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mrqc; if (RTE_ETH_DEV_SRIOV(dev).active == ETH_8_POOLS) { /* * SRIOV active scheme * FIXME if support RSS together with VMDq & SRIOV */ mrqc = E1000_MRQC_ENABLE_VMDQ; /* 011b Def_Q ignore, according to VT_CTL.DEF_PL */ mrqc |= 0x3 << E1000_MRQC_DEF_Q_SHIFT; E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } else if(RTE_ETH_DEV_SRIOV(dev).active == 0) { /* * SRIOV inactive scheme */ switch (dev->data->dev_conf.rxmode.mq_mode) { case ETH_MQ_RX_RSS: igb_rss_configure(dev); break; case ETH_MQ_RX_VMDQ_ONLY: /*Configure general VMDQ only RX parameters*/ igb_vmdq_rx_hw_configure(dev); break; case ETH_MQ_RX_NONE: /* if mq_mode is none, disable rss mode.*/ default: igb_rss_disable(dev); break; } } return 0; } int eth_igb_rx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct igb_rx_queue *rxq; uint32_t rctl; uint32_t rxcsum; uint32_t srrctl; uint16_t buf_size; uint16_t rctl_bsize; uint16_t i; int ret; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); srrctl = 0; /* * Make sure receives are disabled while setting * up the descriptor ring. */ rctl = E1000_READ_REG(hw, E1000_RCTL); E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); /* * Configure support of jumbo frames, if any. */ if (dev->data->dev_conf.rxmode.jumbo_frame == 1) { rctl |= E1000_RCTL_LPE; /* * Set maximum packet length by default, and might be updated * together with enabling/disabling dual VLAN. */ E1000_WRITE_REG(hw, E1000_RLPML, dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE); } else rctl &= ~E1000_RCTL_LPE; /* Configure and enable each RX queue. */ rctl_bsize = 0; dev->rx_pkt_burst = eth_igb_recv_pkts; for (i = 0; i < dev->data->nb_rx_queues; i++) { uint64_t bus_addr; uint32_t rxdctl; rxq = dev->data->rx_queues[i]; /* Allocate buffers for descriptor rings and set up queue */ ret = igb_alloc_rx_queue_mbufs(rxq); if (ret) return ret; /* * Reset crc_len in case it was changed after queue setup by a * call to configure */ rxq->crc_len = (uint8_t)(dev->data->dev_conf.rxmode.hw_strip_crc ? 0 : ETHER_CRC_LEN); bus_addr = rxq->rx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_RDLEN(rxq->reg_idx), rxq->nb_rx_desc * sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(rxq->reg_idx), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(rxq->reg_idx), (uint32_t)bus_addr); srrctl = E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; /* * Configure RX buffer size. */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM); if (buf_size >= 1024) { /* * Configure the BSIZEPACKET field of the SRRCTL * register of the queue. * Value is in 1 KB resolution, from 1 KB to 127 KB. * If this field is equal to 0b, then RCTL.BSIZE * determines the RX packet buffer size. */ srrctl |= ((buf_size >> E1000_SRRCTL_BSIZEPKT_SHIFT) & E1000_SRRCTL_BSIZEPKT_MASK); buf_size = (uint16_t) ((srrctl & E1000_SRRCTL_BSIZEPKT_MASK) << E1000_SRRCTL_BSIZEPKT_SHIFT); /* It adds dual VLAN length for supporting dual VLAN */ if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * VLAN_TAG_SIZE) > buf_size){ if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } } else { /* * Use BSIZE field of the device RCTL register. */ if ((rctl_bsize == 0) || (rctl_bsize > buf_size)) rctl_bsize = buf_size; if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } /* Set if packets are dropped when no descriptors available */ if (rxq->drop_en) srrctl |= E1000_SRRCTL_DROP_EN; E1000_WRITE_REG(hw, E1000_SRRCTL(rxq->reg_idx), srrctl); /* Enable this RX queue. */ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(rxq->reg_idx)); rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; rxdctl &= 0xFFF00000; rxdctl |= (rxq->pthresh & 0x1F); rxdctl |= ((rxq->hthresh & 0x1F) << 8); rxdctl |= ((rxq->wthresh & 0x1F) << 16); E1000_WRITE_REG(hw, E1000_RXDCTL(rxq->reg_idx), rxdctl); } if (dev->data->dev_conf.rxmode.enable_scatter) { if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } /* * Setup BSIZE field of RCTL register, if needed. * Buffer sizes >= 1024 are not [supposed to be] setup in the RCTL * register, since the code above configures the SRRCTL register of * the RX queue in such a case. * All configurable sizes are: * 16384: rctl |= (E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX); * 8192: rctl |= (E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX); * 4096: rctl |= (E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX); * 2048: rctl |= E1000_RCTL_SZ_2048; * 1024: rctl |= E1000_RCTL_SZ_1024; * 512: rctl |= E1000_RCTL_SZ_512; * 256: rctl |= E1000_RCTL_SZ_256; */ if (rctl_bsize > 0) { if (rctl_bsize >= 512) /* 512 <= buf_size < 1024 - use 512 */ rctl |= E1000_RCTL_SZ_512; else /* 256 <= buf_size < 512 - use 256 */ rctl |= E1000_RCTL_SZ_256; } /* * Configure RSS if device configured with multiple RX queues. */ igb_dev_mq_rx_configure(dev); /* Update the rctl since igb_dev_mq_rx_configure may change its value */ rctl |= E1000_READ_REG(hw, E1000_RCTL); /* * Setup the Checksum Register. * Receive Full-Packet Checksum Offload is mutually exclusive with RSS. */ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); rxcsum |= E1000_RXCSUM_PCSD; /* Enable both L3/L4 rx checksum offload */ if (dev->data->dev_conf.rxmode.hw_ip_checksum) rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); else rxcsum &= ~(E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* Setup the Receive Control Register. */ if (dev->data->dev_conf.rxmode.hw_strip_crc) { rctl |= E1000_RCTL_SECRC; /* Strip Ethernet CRC. */ /* set STRCRC bit in all queues */ if (hw->mac.type == e1000_i350 || hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211 || hw->mac.type == e1000_i354) { for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; uint32_t dvmolr = E1000_READ_REG(hw, E1000_DVMOLR(rxq->reg_idx)); dvmolr |= E1000_DVMOLR_STRCRC; E1000_WRITE_REG(hw, E1000_DVMOLR(rxq->reg_idx), dvmolr); } } } else { rctl &= ~E1000_RCTL_SECRC; /* Do not Strip Ethernet CRC. */ /* clear STRCRC bit in all queues */ if (hw->mac.type == e1000_i350 || hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211 || hw->mac.type == e1000_i354) { for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; uint32_t dvmolr = E1000_READ_REG(hw, E1000_DVMOLR(rxq->reg_idx)); dvmolr &= ~E1000_DVMOLR_STRCRC; E1000_WRITE_REG(hw, E1000_DVMOLR(rxq->reg_idx), dvmolr); } } } rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); /* Make sure VLAN Filters are off. */ if (dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_VMDQ_ONLY) rctl &= ~E1000_RCTL_VFE; /* Don't store bad packets. */ rctl &= ~E1000_RCTL_SBP; /* Enable Receives. */ E1000_WRITE_REG(hw, E1000_RCTL, rctl); /* * Setup the HW Rx Head and Tail Descriptor Pointers. * This needs to be done after enable. */ for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; E1000_WRITE_REG(hw, E1000_RDH(rxq->reg_idx), 0); E1000_WRITE_REG(hw, E1000_RDT(rxq->reg_idx), rxq->nb_rx_desc - 1); } return 0; } /********************************************************************* * * Enable transmit unit. * **********************************************************************/ void eth_igb_tx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct igb_tx_queue *txq; uint32_t tctl; uint32_t txdctl; uint16_t i; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Setup the Base and Length of the Tx Descriptor Rings. */ for (i = 0; i < dev->data->nb_tx_queues; i++) { uint64_t bus_addr; txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_TDLEN(txq->reg_idx), txq->nb_tx_desc * sizeof(union e1000_adv_tx_desc)); E1000_WRITE_REG(hw, E1000_TDBAH(txq->reg_idx), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_TDBAL(txq->reg_idx), (uint32_t)bus_addr); /* Setup the HW Tx Head and Tail descriptor pointers. */ E1000_WRITE_REG(hw, E1000_TDT(txq->reg_idx), 0); E1000_WRITE_REG(hw, E1000_TDH(txq->reg_idx), 0); /* Setup Transmit threshold registers. */ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(txq->reg_idx)); txdctl |= txq->pthresh & 0x1F; txdctl |= ((txq->hthresh & 0x1F) << 8); txdctl |= ((txq->wthresh & 0x1F) << 16); txdctl |= E1000_TXDCTL_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_TXDCTL(txq->reg_idx), txdctl); } /* Program the Transmit Control Register. */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); e1000_config_collision_dist(hw); /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(hw, E1000_TCTL, tctl); } /********************************************************************* * * Enable VF receive unit. * **********************************************************************/ int eth_igbvf_rx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct igb_rx_queue *rxq; uint32_t srrctl; uint16_t buf_size; uint16_t rctl_bsize; uint16_t i; int ret; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* setup MTU */ e1000_rlpml_set_vf(hw, (uint16_t)(dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE)); /* Configure and enable each RX queue. */ rctl_bsize = 0; dev->rx_pkt_burst = eth_igb_recv_pkts; for (i = 0; i < dev->data->nb_rx_queues; i++) { uint64_t bus_addr; uint32_t rxdctl; rxq = dev->data->rx_queues[i]; /* Allocate buffers for descriptor rings and set up queue */ ret = igb_alloc_rx_queue_mbufs(rxq); if (ret) return ret; bus_addr = rxq->rx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_RDLEN(i), rxq->nb_rx_desc * sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), (uint32_t)bus_addr); srrctl = E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; /* * Configure RX buffer size. */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM); if (buf_size >= 1024) { /* * Configure the BSIZEPACKET field of the SRRCTL * register of the queue. * Value is in 1 KB resolution, from 1 KB to 127 KB. * If this field is equal to 0b, then RCTL.BSIZE * determines the RX packet buffer size. */ srrctl |= ((buf_size >> E1000_SRRCTL_BSIZEPKT_SHIFT) & E1000_SRRCTL_BSIZEPKT_MASK); buf_size = (uint16_t) ((srrctl & E1000_SRRCTL_BSIZEPKT_MASK) << E1000_SRRCTL_BSIZEPKT_SHIFT); /* It adds dual VLAN length for supporting dual VLAN */ if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * VLAN_TAG_SIZE) > buf_size){ if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } } else { /* * Use BSIZE field of the device RCTL register. */ if ((rctl_bsize == 0) || (rctl_bsize > buf_size)) rctl_bsize = buf_size; if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } /* Set if packets are dropped when no descriptors available */ if (rxq->drop_en) srrctl |= E1000_SRRCTL_DROP_EN; E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); /* Enable this RX queue. */ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; rxdctl &= 0xFFF00000; rxdctl |= (rxq->pthresh & 0x1F); rxdctl |= ((rxq->hthresh & 0x1F) << 8); if (hw->mac.type == e1000_vfadapt) { /* * Workaround of 82576 VF Erratum * force set WTHRESH to 1 * to avoid Write-Back not triggered sometimes */ rxdctl |= 0x10000; PMD_INIT_LOG(DEBUG, "Force set RX WTHRESH to 1 !"); } else rxdctl |= ((rxq->wthresh & 0x1F) << 16); E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); } if (dev->data->dev_conf.rxmode.enable_scatter) { if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->rx_pkt_burst = eth_igb_recv_scattered_pkts; dev->data->scattered_rx = 1; } /* * Setup the HW Rx Head and Tail Descriptor Pointers. * This needs to be done after enable. */ for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; E1000_WRITE_REG(hw, E1000_RDH(i), 0); E1000_WRITE_REG(hw, E1000_RDT(i), rxq->nb_rx_desc - 1); } return 0; } /********************************************************************* * * Enable VF transmit unit. * **********************************************************************/ void eth_igbvf_tx_init(struct rte_eth_dev *dev) { struct e1000_hw *hw; struct igb_tx_queue *txq; uint32_t txdctl; uint16_t i; hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Setup the Base and Length of the Tx Descriptor Rings. */ for (i = 0; i < dev->data->nb_tx_queues; i++) { uint64_t bus_addr; txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; E1000_WRITE_REG(hw, E1000_TDLEN(i), txq->nb_tx_desc * sizeof(union e1000_adv_tx_desc)); E1000_WRITE_REG(hw, E1000_TDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_TDBAL(i), (uint32_t)bus_addr); /* Setup the HW Tx Head and Tail descriptor pointers. */ E1000_WRITE_REG(hw, E1000_TDT(i), 0); E1000_WRITE_REG(hw, E1000_TDH(i), 0); /* Setup Transmit threshold registers. */ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(i)); txdctl |= txq->pthresh & 0x1F; txdctl |= ((txq->hthresh & 0x1F) << 8); if (hw->mac.type == e1000_82576) { /* * Workaround of 82576 VF Erratum * force set WTHRESH to 1 * to avoid Write-Back not triggered sometimes */ txdctl |= 0x10000; PMD_INIT_LOG(DEBUG, "Force set TX WTHRESH to 1 !"); } else txdctl |= ((txq->wthresh & 0x1F) << 16); txdctl |= E1000_TXDCTL_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); } } ================================================ FILE: drivers/net/enic/LICENSE ================================================ * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: drivers/net/enic/Makefile ================================================ # # Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. # Copyright 2007 Nuova Systems, Inc. All rights reserved. # # Copyright (c) 2014, Cisco Systems, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_enic.a EXPORT_MAP := rte_pmd_enic_version.map LIBABIVER := 1 CFLAGS += -I$(SRCDIR)/base/ CFLAGS += -I$(SRCDIR) CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -Wno-strict-aliasing VPATH += $(SRCDIR)/src # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_main.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_clsf.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_res.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_cq.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_wq.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_dev.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_intr.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_rq.c SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_rss.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += lib/librte_net DEPDIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += lib/librte_hash include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/enic/base/cq_desc.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: cq_desc.h 129574 2013-04-26 22:11:14Z rfaucett $" #ifndef _CQ_DESC_H_ #define _CQ_DESC_H_ /* * Completion queue descriptor types */ enum cq_desc_types { CQ_DESC_TYPE_WQ_ENET = 0, CQ_DESC_TYPE_DESC_COPY = 1, CQ_DESC_TYPE_WQ_EXCH = 2, CQ_DESC_TYPE_RQ_ENET = 3, CQ_DESC_TYPE_RQ_FCP = 4, CQ_DESC_TYPE_IOMMU_MISS = 5, CQ_DESC_TYPE_SGL = 6, CQ_DESC_TYPE_CLASSIFIER = 7, CQ_DESC_TYPE_TEST = 127, }; /* Completion queue descriptor: 16B * * All completion queues have this basic layout. The * type_specfic area is unique for each completion * queue type. */ struct cq_desc { __le16 completed_index; __le16 q_number; u8 type_specfic[11]; u8 type_color; }; #define CQ_DESC_TYPE_BITS 4 #define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1) #define CQ_DESC_COLOR_MASK 1 #define CQ_DESC_COLOR_SHIFT 7 #define CQ_DESC_Q_NUM_BITS 10 #define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1) #define CQ_DESC_COMP_NDX_BITS 12 #define CQ_DESC_COMP_NDX_MASK ((1 << CQ_DESC_COMP_NDX_BITS) - 1) static inline void cq_color_enc(struct cq_desc *desc, const u8 color) { if (color) desc->type_color |= (1 << CQ_DESC_COLOR_SHIFT); else desc->type_color &= ~(1 << CQ_DESC_COLOR_SHIFT); } static inline void cq_desc_enc(struct cq_desc *desc, const u8 type, const u8 color, const u16 q_number, const u16 completed_index) { desc->type_color = (type & CQ_DESC_TYPE_MASK) | ((color & CQ_DESC_COLOR_MASK) << CQ_DESC_COLOR_SHIFT); desc->q_number = cpu_to_le16(q_number & CQ_DESC_Q_NUM_MASK); desc->completed_index = cpu_to_le16(completed_index & CQ_DESC_COMP_NDX_MASK); } static inline void cq_desc_dec(const struct cq_desc *desc_arg, u8 *type, u8 *color, u16 *q_number, u16 *completed_index) { const struct cq_desc *desc = desc_arg; const u8 type_color = desc->type_color; *color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; /* * Make sure color bit is read from desc *before* other fields * are read from desc. Hardware guarantees color bit is last * bit (byte) written. Adding the rmb() prevents the compiler * and/or CPU from reordering the reads which would potentially * result in reading stale values. */ rmb(); *type = type_color & CQ_DESC_TYPE_MASK; *q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK; *completed_index = le16_to_cpu(desc->completed_index) & CQ_DESC_COMP_NDX_MASK; } static inline void cq_color_dec(const struct cq_desc *desc_arg, u8 *color) { volatile const struct cq_desc *desc = desc_arg; *color = (desc->type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; } #endif /* _CQ_DESC_H_ */ ================================================ FILE: drivers/net/enic/base/cq_enet_desc.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: cq_enet_desc.h 160468 2014-02-18 09:50:15Z gvaradar $" #ifndef _CQ_ENET_DESC_H_ #define _CQ_ENET_DESC_H_ #include "cq_desc.h" /* Ethernet completion queue descriptor: 16B */ struct cq_enet_wq_desc { __le16 completed_index; __le16 q_number; u8 reserved[11]; u8 type_color; }; static inline void cq_enet_wq_desc_enc(struct cq_enet_wq_desc *desc, u8 type, u8 color, u16 q_number, u16 completed_index) { cq_desc_enc((struct cq_desc *)desc, type, color, q_number, completed_index); } static inline void cq_enet_wq_desc_dec(struct cq_enet_wq_desc *desc, u8 *type, u8 *color, u16 *q_number, u16 *completed_index) { cq_desc_dec((struct cq_desc *)desc, type, color, q_number, completed_index); } /* Completion queue descriptor: Ethernet receive queue, 16B */ struct cq_enet_rq_desc { __le16 completed_index_flags; __le16 q_number_rss_type_flags; __le32 rss_hash; __le16 bytes_written_flags; __le16 vlan; __le16 checksum_fcoe; u8 flags; u8 type_color; }; #define CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT (0x1 << 12) #define CQ_ENET_RQ_DESC_FLAGS_FCOE (0x1 << 13) #define CQ_ENET_RQ_DESC_FLAGS_EOP (0x1 << 14) #define CQ_ENET_RQ_DESC_FLAGS_SOP (0x1 << 15) #define CQ_ENET_RQ_DESC_RSS_TYPE_BITS 4 #define CQ_ENET_RQ_DESC_RSS_TYPE_MASK \ ((1 << CQ_ENET_RQ_DESC_RSS_TYPE_BITS) - 1) #define CQ_ENET_RQ_DESC_RSS_TYPE_NONE 0 #define CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 1 #define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 2 #define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 3 #define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 4 #define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX 5 #define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX 6 #define CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC (0x1 << 14) #define CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS 14 #define CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK \ ((1 << CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS) - 1) #define CQ_ENET_RQ_DESC_FLAGS_TRUNCATED (0x1 << 14) #define CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED (0x1 << 15) #define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS 12 #define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK \ ((1 << CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS) - 1) #define CQ_ENET_RQ_DESC_VLAN_TCI_CFI_MASK (0x1 << 12) #define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS 3 #define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_MASK \ ((1 << CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS) - 1) #define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_SHIFT 13 #define CQ_ENET_RQ_DESC_FCOE_SOF_BITS 8 #define CQ_ENET_RQ_DESC_FCOE_SOF_MASK \ ((1 << CQ_ENET_RQ_DESC_FCOE_SOF_BITS) - 1) #define CQ_ENET_RQ_DESC_FCOE_EOF_BITS 8 #define CQ_ENET_RQ_DESC_FCOE_EOF_MASK \ ((1 << CQ_ENET_RQ_DESC_FCOE_EOF_BITS) - 1) #define CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT 8 #define CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK (0x1 << 0) #define CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK (0x1 << 0) #define CQ_ENET_RQ_DESC_FLAGS_UDP (0x1 << 1) #define CQ_ENET_RQ_DESC_FCOE_ENC_ERROR (0x1 << 1) #define CQ_ENET_RQ_DESC_FLAGS_TCP (0x1 << 2) #define CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK (0x1 << 3) #define CQ_ENET_RQ_DESC_FLAGS_IPV6 (0x1 << 4) #define CQ_ENET_RQ_DESC_FLAGS_IPV4 (0x1 << 5) #define CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT (0x1 << 6) #define CQ_ENET_RQ_DESC_FLAGS_FCS_OK (0x1 << 7) static inline void cq_enet_rq_desc_enc(struct cq_enet_rq_desc *desc, u8 type, u8 color, u16 q_number, u16 completed_index, u8 ingress_port, u8 fcoe, u8 eop, u8 sop, u8 rss_type, u8 csum_not_calc, u32 rss_hash, u16 bytes_written, u8 packet_error, u8 vlan_stripped, u16 vlan, u16 checksum, u8 fcoe_sof, u8 fcoe_fc_crc_ok, u8 fcoe_enc_error, u8 fcoe_eof, u8 tcp_udp_csum_ok, u8 udp, u8 tcp, u8 ipv4_csum_ok, u8 ipv6, u8 ipv4, u8 ipv4_fragment, u8 fcs_ok) { cq_desc_enc((struct cq_desc *)desc, type, color, q_number, completed_index); desc->completed_index_flags |= cpu_to_le16( (ingress_port ? CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT : 0) | (fcoe ? CQ_ENET_RQ_DESC_FLAGS_FCOE : 0) | (eop ? CQ_ENET_RQ_DESC_FLAGS_EOP : 0) | (sop ? CQ_ENET_RQ_DESC_FLAGS_SOP : 0)); desc->q_number_rss_type_flags |= cpu_to_le16( ((rss_type & CQ_ENET_RQ_DESC_RSS_TYPE_MASK) << CQ_DESC_Q_NUM_BITS) | (csum_not_calc ? CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC : 0)); desc->rss_hash = cpu_to_le32(rss_hash); desc->bytes_written_flags = cpu_to_le16( (bytes_written & CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK) | (packet_error ? CQ_ENET_RQ_DESC_FLAGS_TRUNCATED : 0) | (vlan_stripped ? CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED : 0)); desc->vlan = cpu_to_le16(vlan); if (fcoe) { desc->checksum_fcoe = cpu_to_le16( (fcoe_sof & CQ_ENET_RQ_DESC_FCOE_SOF_MASK) | ((fcoe_eof & CQ_ENET_RQ_DESC_FCOE_EOF_MASK) << CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT)); } else { desc->checksum_fcoe = cpu_to_le16(checksum); } desc->flags = (tcp_udp_csum_ok ? CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK : 0) | (udp ? CQ_ENET_RQ_DESC_FLAGS_UDP : 0) | (tcp ? CQ_ENET_RQ_DESC_FLAGS_TCP : 0) | (ipv4_csum_ok ? CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK : 0) | (ipv6 ? CQ_ENET_RQ_DESC_FLAGS_IPV6 : 0) | (ipv4 ? CQ_ENET_RQ_DESC_FLAGS_IPV4 : 0) | (ipv4_fragment ? CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT : 0) | (fcs_ok ? CQ_ENET_RQ_DESC_FLAGS_FCS_OK : 0) | (fcoe_fc_crc_ok ? CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK : 0) | (fcoe_enc_error ? CQ_ENET_RQ_DESC_FCOE_ENC_ERROR : 0); } static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, u8 *type, u8 *color, u16 *q_number, u16 *completed_index, u8 *ingress_port, u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type, u8 *csum_not_calc, u32 *rss_hash, u16 *bytes_written, u8 *packet_error, u8 *vlan_stripped, u16 *vlan_tci, u16 *checksum, u8 *fcoe_sof, u8 *fcoe_fc_crc_ok, u8 *fcoe_enc_error, u8 *fcoe_eof, u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok, u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok) { u16 completed_index_flags; u16 q_number_rss_type_flags; u16 bytes_written_flags; cq_desc_dec((struct cq_desc *)desc, type, color, q_number, completed_index); completed_index_flags = le16_to_cpu(desc->completed_index_flags); q_number_rss_type_flags = le16_to_cpu(desc->q_number_rss_type_flags); bytes_written_flags = le16_to_cpu(desc->bytes_written_flags); *ingress_port = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0; *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ? 1 : 0; *eop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_EOP) ? 1 : 0; *sop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_SOP) ? 1 : 0; *rss_type = (u8)((q_number_rss_type_flags >> CQ_DESC_Q_NUM_BITS) & CQ_ENET_RQ_DESC_RSS_TYPE_MASK); *csum_not_calc = (q_number_rss_type_flags & CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ? 1 : 0; *rss_hash = le32_to_cpu(desc->rss_hash); *bytes_written = bytes_written_flags & CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; *packet_error = (bytes_written_flags & CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ? 1 : 0; *vlan_stripped = (bytes_written_flags & CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) ? 1 : 0; /* * Tag Control Information(16) = user_priority(3) + cfi(1) + vlan(12) */ *vlan_tci = le16_to_cpu(desc->vlan); if (*fcoe) { *fcoe_sof = (u8)(le16_to_cpu(desc->checksum_fcoe) & CQ_ENET_RQ_DESC_FCOE_SOF_MASK); *fcoe_fc_crc_ok = (desc->flags & CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK) ? 1 : 0; *fcoe_enc_error = (desc->flags & CQ_ENET_RQ_DESC_FCOE_ENC_ERROR) ? 1 : 0; *fcoe_eof = (u8)((le16_to_cpu(desc->checksum_fcoe) >> CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT) & CQ_ENET_RQ_DESC_FCOE_EOF_MASK); *checksum = 0; } else { *fcoe_sof = 0; *fcoe_fc_crc_ok = 0; *fcoe_enc_error = 0; *fcoe_eof = 0; *checksum = le16_to_cpu(desc->checksum_fcoe); } *tcp_udp_csum_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ? 1 : 0; *udp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_UDP) ? 1 : 0; *tcp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP) ? 1 : 0; *ipv4_csum_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ? 1 : 0; *ipv6 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV6) ? 1 : 0; *ipv4 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4) ? 1 : 0; *ipv4_fragment = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT) ? 1 : 0; *fcs_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ? 1 : 0; } #endif /* _CQ_ENET_DESC_H_ */ ================================================ FILE: drivers/net/enic/base/rq_enet_desc.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: rq_enet_desc.h 59839 2010-09-27 20:36:31Z roprabhu $" #ifndef _RQ_ENET_DESC_H_ #define _RQ_ENET_DESC_H_ /* Ethernet receive queue descriptor: 16B */ struct rq_enet_desc { __le64 address; __le16 length_type; u8 reserved[6]; }; enum rq_enet_type_types { RQ_ENET_TYPE_ONLY_SOP = 0, RQ_ENET_TYPE_NOT_SOP = 1, RQ_ENET_TYPE_RESV2 = 2, RQ_ENET_TYPE_RESV3 = 3, }; #define RQ_ENET_ADDR_BITS 64 #define RQ_ENET_LEN_BITS 14 #define RQ_ENET_LEN_MASK ((1 << RQ_ENET_LEN_BITS) - 1) #define RQ_ENET_TYPE_BITS 2 #define RQ_ENET_TYPE_MASK ((1 << RQ_ENET_TYPE_BITS) - 1) static inline void rq_enet_desc_enc(struct rq_enet_desc *desc, u64 address, u8 type, u16 length) { desc->address = cpu_to_le64(address); desc->length_type = cpu_to_le16((length & RQ_ENET_LEN_MASK) | ((type & RQ_ENET_TYPE_MASK) << RQ_ENET_LEN_BITS)); } static inline void rq_enet_desc_dec(struct rq_enet_desc *desc, u64 *address, u8 *type, u16 *length) { *address = le64_to_cpu(desc->address); *length = le16_to_cpu(desc->length_type) & RQ_ENET_LEN_MASK; *type = (u8)((le16_to_cpu(desc->length_type) >> RQ_ENET_LEN_BITS) & RQ_ENET_TYPE_MASK); } #endif /* _RQ_ENET_DESC_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_cq.c ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_cq.c 171146 2014-05-02 07:08:20Z ssujith $" #include "vnic_dev.h" #include "vnic_cq.h" int vnic_cq_mem_size(struct vnic_cq *cq, unsigned int desc_count, unsigned int desc_size) { int mem_size; mem_size = vnic_dev_desc_ring_size(&cq->ring, desc_count, desc_size); return mem_size; } void vnic_cq_free(struct vnic_cq *cq) { vnic_dev_free_desc_ring(cq->vdev, &cq->ring); cq->ctrl = NULL; } int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, unsigned int socket_id, unsigned int desc_count, unsigned int desc_size) { int err; char res_name[NAME_MAX]; static int instance; cq->index = index; cq->vdev = vdev; cq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_CQ, index); if (!cq->ctrl) { pr_err("Failed to hook CQ[%d] resource\n", index); return -EINVAL; } snprintf(res_name, sizeof(res_name), "%d-cq-%d", instance++, index); err = vnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size, socket_id, res_name); if (err) return err; return 0; } void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, unsigned int cq_tail_color, unsigned int interrupt_enable, unsigned int cq_entry_enable, unsigned int cq_message_enable, unsigned int interrupt_offset, u64 cq_message_addr) { u64 paddr; paddr = (u64)cq->ring.base_addr | VNIC_PADDR_TARGET; writeq(paddr, &cq->ctrl->ring_base); iowrite32(cq->ring.desc_count, &cq->ctrl->ring_size); iowrite32(flow_control_enable, &cq->ctrl->flow_control_enable); iowrite32(color_enable, &cq->ctrl->color_enable); iowrite32(cq_head, &cq->ctrl->cq_head); iowrite32(cq_tail, &cq->ctrl->cq_tail); iowrite32(cq_tail_color, &cq->ctrl->cq_tail_color); iowrite32(interrupt_enable, &cq->ctrl->interrupt_enable); iowrite32(cq_entry_enable, &cq->ctrl->cq_entry_enable); iowrite32(cq_message_enable, &cq->ctrl->cq_message_enable); iowrite32(interrupt_offset, &cq->ctrl->interrupt_offset); writeq(cq_message_addr, &cq->ctrl->cq_message_addr); cq->interrupt_offset = interrupt_offset; } void vnic_cq_clean(struct vnic_cq *cq) { cq->to_clean = 0; cq->last_color = 0; iowrite32(0, &cq->ctrl->cq_head); iowrite32(0, &cq->ctrl->cq_tail); iowrite32(1, &cq->ctrl->cq_tail_color); vnic_dev_clear_desc_ring(&cq->ring); } ================================================ FILE: drivers/net/enic/base/vnic_cq.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_cq.h 173398 2014-05-19 09:17:02Z gvaradar $" #ifndef _VNIC_CQ_H_ #define _VNIC_CQ_H_ #include #include "cq_desc.h" #include "vnic_dev.h" /* Completion queue control */ struct vnic_cq_ctrl { u64 ring_base; /* 0x00 */ u32 ring_size; /* 0x08 */ u32 pad0; u32 flow_control_enable; /* 0x10 */ u32 pad1; u32 color_enable; /* 0x18 */ u32 pad2; u32 cq_head; /* 0x20 */ u32 pad3; u32 cq_tail; /* 0x28 */ u32 pad4; u32 cq_tail_color; /* 0x30 */ u32 pad5; u32 interrupt_enable; /* 0x38 */ u32 pad6; u32 cq_entry_enable; /* 0x40 */ u32 pad7; u32 cq_message_enable; /* 0x48 */ u32 pad8; u32 interrupt_offset; /* 0x50 */ u32 pad9; u64 cq_message_addr; /* 0x58 */ u32 pad10; }; #ifdef ENIC_AIC struct vnic_rx_bytes_counter { unsigned int small_pkt_bytes_cnt; unsigned int large_pkt_bytes_cnt; }; #endif struct vnic_cq { unsigned int index; struct vnic_dev *vdev; struct vnic_cq_ctrl __iomem *ctrl; /* memory-mapped */ struct vnic_dev_ring ring; unsigned int to_clean; unsigned int last_color; unsigned int interrupt_offset; #ifdef ENIC_AIC struct vnic_rx_bytes_counter pkt_size_counter; unsigned int cur_rx_coal_timeval; unsigned int tobe_rx_coal_timeval; ktime_t prev_ts; #endif }; static inline unsigned int vnic_cq_service(struct vnic_cq *cq, unsigned int work_to_do, int (*q_service)(struct vnic_dev *vdev, struct cq_desc *cq_desc, u8 type, u16 q_number, u16 completed_index, void *opaque), void *opaque) { struct cq_desc *cq_desc; unsigned int work_done = 0; u16 q_number, completed_index; u8 type, color; struct rte_mbuf **rx_pkts = opaque; unsigned int ret; cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + cq->ring.desc_size * cq->to_clean); cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index); while (color != cq->last_color) { if (opaque) opaque = (void *)&(rx_pkts[work_done]); ret = (*q_service)(cq->vdev, cq_desc, type, q_number, completed_index, opaque); cq->to_clean++; if (cq->to_clean == cq->ring.desc_count) { cq->to_clean = 0; cq->last_color = cq->last_color ? 0 : 1; } cq_desc = (struct cq_desc *)((u8 *)cq->ring.descs + cq->ring.desc_size * cq->to_clean); cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index); if (ret) work_done++; if (work_done >= work_to_do) break; } return work_done; } void vnic_cq_free(struct vnic_cq *cq); int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, unsigned int socket_id, unsigned int desc_count, unsigned int desc_size); void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, unsigned int cq_tail_color, unsigned int interrupt_enable, unsigned int cq_entry_enable, unsigned int message_enable, unsigned int interrupt_offset, u64 message_addr); void vnic_cq_clean(struct vnic_cq *cq); int vnic_cq_mem_size(struct vnic_cq *cq, unsigned int desc_count, unsigned int desc_size); #endif /* _VNIC_CQ_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_dev.c ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #include #include #include #include "vnic_dev.h" #include "vnic_resource.h" #include "vnic_devcmd.h" #include "vnic_stats.h" enum vnic_proxy_type { PROXY_NONE, PROXY_BY_BDF, PROXY_BY_INDEX, }; struct vnic_res { void __iomem *vaddr; dma_addr_t bus_addr; unsigned int count; }; struct vnic_intr_coal_timer_info { u32 mul; u32 div; u32 max_usec; }; struct vnic_dev { void *priv; struct rte_pci_device *pdev; struct vnic_res res[RES_TYPE_MAX]; enum vnic_dev_intr_mode intr_mode; struct vnic_devcmd __iomem *devcmd; struct vnic_devcmd_notify *notify; struct vnic_devcmd_notify notify_copy; dma_addr_t notify_pa; u32 notify_sz; dma_addr_t linkstatus_pa; struct vnic_stats *stats; dma_addr_t stats_pa; struct vnic_devcmd_fw_info *fw_info; dma_addr_t fw_info_pa; enum vnic_proxy_type proxy; u32 proxy_index; u64 args[VNIC_DEVCMD_NARGS]; u16 split_hdr_size; int in_reset; struct vnic_intr_coal_timer_info intr_coal_timer_info; void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name); void (*free_consistent)(struct rte_pci_device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle); }; #define VNIC_MAX_RES_HDR_SIZE \ (sizeof(struct vnic_resource_header) + \ sizeof(struct vnic_resource) * RES_TYPE_MAX) #define VNIC_RES_STRIDE 128 void *vnic_dev_priv(struct vnic_dev *vdev) { return vdev->priv; } void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), void (*free_consistent)(struct rte_pci_device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)) { vdev->alloc_consistent = alloc_consistent; vdev->free_consistent = free_consistent; } static int vnic_dev_discover_res(struct vnic_dev *vdev, struct vnic_dev_bar *bar, unsigned int num_bars) { struct vnic_resource_header __iomem *rh; struct mgmt_barmap_hdr __iomem *mrh; struct vnic_resource __iomem *r; u8 type; if (num_bars == 0) return -EINVAL; if (bar->len < VNIC_MAX_RES_HDR_SIZE) { pr_err("vNIC BAR0 res hdr length error\n"); return -EINVAL; } rh = bar->vaddr; mrh = bar->vaddr; if (!rh) { pr_err("vNIC BAR0 res hdr not mem-mapped\n"); return -EINVAL; } /* Check for mgmt vnic in addition to normal vnic */ if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) || (ioread32(&rh->version) != VNIC_RES_VERSION)) { if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) || (ioread32(&mrh->version) != MGMTVNIC_VERSION)) { pr_err("vNIC BAR0 res magic/version error " \ "exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n", VNIC_RES_MAGIC, VNIC_RES_VERSION, MGMTVNIC_MAGIC, MGMTVNIC_VERSION, ioread32(&rh->magic), ioread32(&rh->version)); return -EINVAL; } } if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC) r = (struct vnic_resource __iomem *)(mrh + 1); else r = (struct vnic_resource __iomem *)(rh + 1); while ((type = ioread8(&r->type)) != RES_TYPE_EOL) { u8 bar_num = ioread8(&r->bar); u32 bar_offset = ioread32(&r->bar_offset); u32 count = ioread32(&r->count); u32 len; r++; if (bar_num >= num_bars) continue; if (!bar[bar_num].len || !bar[bar_num].vaddr) continue; switch (type) { case RES_TYPE_WQ: case RES_TYPE_RQ: case RES_TYPE_CQ: case RES_TYPE_INTR_CTRL: /* each count is stride bytes long */ len = count * VNIC_RES_STRIDE; if (len + bar_offset > bar[bar_num].len) { pr_err("vNIC BAR0 resource %d " \ "out-of-bounds, offset 0x%x + " \ "size 0x%x > bar len 0x%lx\n", type, bar_offset, len, bar[bar_num].len); return -EINVAL; } break; case RES_TYPE_INTR_PBA_LEGACY: case RES_TYPE_DEVCMD: len = count; break; default: continue; } vdev->res[type].count = count; vdev->res[type].vaddr = (char __iomem *)bar[bar_num].vaddr + bar_offset; vdev->res[type].bus_addr = bar[bar_num].bus_addr + bar_offset; } return 0; } unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, enum vnic_res_type type) { return vdev->res[type].count; } void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index) { if (!vdev->res[type].vaddr) return NULL; switch (type) { case RES_TYPE_WQ: case RES_TYPE_RQ: case RES_TYPE_CQ: case RES_TYPE_INTR_CTRL: return (char __iomem *)vdev->res[type].vaddr + index * VNIC_RES_STRIDE; default: return (char __iomem *)vdev->res[type].vaddr; } } unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size) { /* The base address of the desc rings must be 512 byte aligned. * Descriptor count is aligned to groups of 32 descriptors. A * count of 0 means the maximum 4096 descriptors. Descriptor * size is aligned to 16 bytes. */ unsigned int count_align = 32; unsigned int desc_align = 16; ring->base_align = 512; if (desc_count == 0) desc_count = 4096; ring->desc_count = VNIC_ALIGN(desc_count, count_align); ring->desc_size = VNIC_ALIGN(desc_size, desc_align); ring->size = ring->desc_count * ring->desc_size; ring->size_unaligned = ring->size + ring->base_align; return ring->size_unaligned; } void vnic_set_hdr_split_size(struct vnic_dev *vdev, u16 size) { vdev->split_hdr_size = size; } u16 vnic_get_hdr_split_size(struct vnic_dev *vdev) { return vdev->split_hdr_size; } void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring) { memset(ring->descs, 0, ring->size); } int vnic_dev_alloc_desc_ring(__attribute__((unused)) struct vnic_dev *vdev, struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size, unsigned int socket_id, char *z_name) { const struct rte_memzone *rz; vnic_dev_desc_ring_size(ring, desc_count, desc_size); rz = rte_memzone_reserve_aligned(z_name, ring->size_unaligned, socket_id, 0, ENIC_ALIGN); if (!rz) { pr_err("Failed to allocate ring (size=%d), aborting\n", (int)ring->size); return -ENOMEM; } ring->descs_unaligned = rz->addr; if (!ring->descs_unaligned) { pr_err("Failed to map allocated ring (size=%d), aborting\n", (int)ring->size); return -ENOMEM; } ring->base_addr_unaligned = (dma_addr_t)rz->phys_addr; ring->base_addr = VNIC_ALIGN(ring->base_addr_unaligned, ring->base_align); ring->descs = (u8 *)ring->descs_unaligned + (ring->base_addr - ring->base_addr_unaligned); vnic_dev_clear_desc_ring(ring); ring->desc_avail = ring->desc_count - 1; return 0; } void vnic_dev_free_desc_ring(__attribute__((unused)) struct vnic_dev *vdev, struct vnic_dev_ring *ring) { if (ring->descs) ring->descs = NULL; } static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait) { struct vnic_devcmd __iomem *devcmd = vdev->devcmd; unsigned int i; int delay; u32 status; int err; status = ioread32(&devcmd->status); if (status == 0xFFFFFFFF) { /* PCI-e target device is gone */ return -ENODEV; } if (status & STAT_BUSY) { pr_err("Busy devcmd %d\n", _CMD_N(cmd)); return -EBUSY; } if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) { for (i = 0; i < VNIC_DEVCMD_NARGS; i++) writeq(vdev->args[i], &devcmd->args[i]); wmb(); /* complete all writes initiated till now */ } iowrite32(cmd, &devcmd->cmd); if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT)) return 0; for (delay = 0; delay < wait; delay++) { udelay(100); status = ioread32(&devcmd->status); if (status == 0xFFFFFFFF) { /* PCI-e target device is gone */ return -ENODEV; } if (!(status & STAT_BUSY)) { if (status & STAT_ERROR) { err = -(int)readq(&devcmd->args[0]); if (cmd != CMD_CAPABILITY) pr_err("Devcmd %d failed " \ "with error code %d\n", _CMD_N(cmd), err); return err; } if (_CMD_DIR(cmd) & _CMD_DIR_READ) { rmb();/* finish all reads initiated till now */ for (i = 0; i < VNIC_DEVCMD_NARGS; i++) vdev->args[i] = readq(&devcmd->args[i]); } return 0; } } pr_err("Timedout devcmd %d\n", _CMD_N(cmd)); return -ETIMEDOUT; } static int vnic_dev_cmd_proxy(struct vnic_dev *vdev, enum vnic_devcmd_cmd proxy_cmd, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait) { u32 status; int err; memset(vdev->args, 0, sizeof(vdev->args)); vdev->args[0] = vdev->proxy_index; vdev->args[1] = cmd; vdev->args[2] = *a0; vdev->args[3] = *a1; err = _vnic_dev_cmd(vdev, proxy_cmd, wait); if (err) return err; status = (u32)vdev->args[0]; if (status & STAT_ERROR) { err = (int)vdev->args[1]; if (err != ERR_ECMDUNKNOWN || cmd != CMD_CAPABILITY) pr_err("Error %d proxy devcmd %d\n", err, _CMD_N(cmd)); return err; } *a0 = vdev->args[1]; *a1 = vdev->args[2]; return 0; } static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait) { int err; vdev->args[0] = *a0; vdev->args[1] = *a1; err = _vnic_dev_cmd(vdev, cmd, wait); *a0 = vdev->args[0]; *a1 = vdev->args[1]; return err; } void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, u16 index) { vdev->proxy = PROXY_BY_INDEX; vdev->proxy_index = index; } void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf) { vdev->proxy = PROXY_BY_BDF; vdev->proxy_index = bdf; } void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) { vdev->proxy = PROXY_NONE; vdev->proxy_index = 0; } int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait) { memset(vdev->args, 0, sizeof(vdev->args)); switch (vdev->proxy) { case PROXY_BY_INDEX: return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd, a0, a1, wait); case PROXY_BY_BDF: return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd, a0, a1, wait); case PROXY_NONE: default: return vnic_dev_cmd_no_proxy(vdev, cmd, a0, a1, wait); } } static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) { u64 a0 = (u32)cmd, a1 = 0; int wait = 1000; int err; err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait); return !(err || a0); } int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size, void *value) { u64 a0, a1; int wait = 1000; int err; a0 = offset; a1 = size; err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait); switch (size) { case 1: *(u8 *)value = (u8)a0; break; case 2: *(u16 *)value = (u16)a0; break; case 4: *(u32 *)value = (u32)a0; break; case 8: *(u64 *)value = a0; break; default: BUG(); break; } return err; } int vnic_dev_stats_clear(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait); } int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats) { u64 a0, a1; int wait = 1000; static u32 instance; char name[NAME_MAX]; if (!vdev->stats) { snprintf((char *)name, sizeof(name), "vnic_stats-%d", instance++); vdev->stats = vdev->alloc_consistent(vdev->priv, sizeof(struct vnic_stats), &vdev->stats_pa, (u8 *)name); if (!vdev->stats) return -ENOMEM; } *stats = vdev->stats; a0 = vdev->stats_pa; a1 = sizeof(struct vnic_stats); return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait); } int vnic_dev_close(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait); } /** Deprecated. @see vnic_dev_enable_wait */ int vnic_dev_enable(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); } int vnic_dev_enable_wait(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT)) return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait); else return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); } int vnic_dev_disable(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait); } int vnic_dev_open(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait); } int vnic_dev_open_done(struct vnic_dev *vdev, int *done) { u64 a0 = 0, a1 = 0; int wait = 1000; int err; *done = 0; err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait); if (err) return err; *done = (a0 == 0); return 0; } int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait); } int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) { u64 a0 = 0, a1 = 0; int wait = 1000; int err; *done = 0; err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait); if (err) return err; *done = (a0 == 0); return 0; } int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) { u64 a0, a1 = 0; int wait = 1000; int err, i; for (i = 0; i < ETH_ALEN; i++) mac_addr[i] = 0; err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait); if (err) return err; for (i = 0; i < ETH_ALEN; i++) mac_addr[i] = ((u8 *)&a0)[i]; return 0; } int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, int broadcast, int promisc, int allmulti) { u64 a0, a1 = 0; int wait = 1000; int err; a0 = (directed ? CMD_PFILTER_DIRECTED : 0) | (multicast ? CMD_PFILTER_MULTICAST : 0) | (broadcast ? CMD_PFILTER_BROADCAST : 0) | (promisc ? CMD_PFILTER_PROMISCUOUS : 0) | (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0); err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait); if (err) pr_err("Can't set packet filter\n"); return err; } int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) { u64 a0 = 0, a1 = 0; int wait = 1000; int err; int i; for (i = 0; i < ETH_ALEN; i++) ((u8 *)&a0)[i] = addr[i]; err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); if (err) pr_err("Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], err); return err; } int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) { u64 a0 = 0, a1 = 0; int wait = 1000; int err; int i; for (i = 0; i < ETH_ALEN; i++) ((u8 *)&a0)[i] = addr[i]; err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); if (err) pr_err("Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], err); return err; } int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, u8 ig_vlan_rewrite_mode) { u64 a0 = ig_vlan_rewrite_mode, a1 = 0; int wait = 1000; if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE)) return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE, &a0, &a1, wait); else return 0; } int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) { u64 a0 = intr, a1 = 0; int wait = 1000; int err; err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait); if (err) pr_err("Failed to raise INTR[%d], err %d\n", intr, err); return err; } void vnic_dev_set_reset_flag(struct vnic_dev *vdev, int state) { vdev->in_reset = state; } static inline int vnic_dev_in_reset(struct vnic_dev *vdev) { return vdev->in_reset; } int vnic_dev_notify_setcmd(struct vnic_dev *vdev, void *notify_addr, dma_addr_t notify_pa, u16 intr) { u64 a0, a1; int wait = 1000; int r; memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify)); if (!vnic_dev_in_reset(vdev)) { vdev->notify = notify_addr; vdev->notify_pa = notify_pa; } a0 = (u64)notify_pa; a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; a1 += sizeof(struct vnic_devcmd_notify); r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); if (!vnic_dev_in_reset(vdev)) vdev->notify_sz = (r == 0) ? (u32)a1 : 0; return r; } int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) { void *notify_addr = NULL; dma_addr_t notify_pa = 0; char name[NAME_MAX]; static u32 instance; if (vdev->notify || vdev->notify_pa) { pr_warn("notify block %p still allocated.\n" \ "Ignore if restarting port\n", vdev->notify); return -EINVAL; } if (!vnic_dev_in_reset(vdev)) { snprintf((char *)name, sizeof(name), "vnic_notify-%d", instance++); notify_addr = vdev->alloc_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), ¬ify_pa, (u8 *)name); if (!notify_addr) return -ENOMEM; } return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr); } int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) { u64 a0, a1; int wait = 1000; int err; a0 = 0; /* paddr = 0 to unset notify buffer */ a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */ a1 += sizeof(struct vnic_devcmd_notify); err = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); if (!vnic_dev_in_reset(vdev)) { vdev->notify = NULL; vdev->notify_pa = 0; vdev->notify_sz = 0; } return err; } int vnic_dev_notify_unset(struct vnic_dev *vdev) { if (vdev->notify && !vnic_dev_in_reset(vdev)) { vdev->free_consistent(vdev->pdev, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); } return vnic_dev_notify_unsetcmd(vdev); } static int vnic_dev_notify_ready(struct vnic_dev *vdev) { u32 *words; unsigned int nwords = vdev->notify_sz / 4; unsigned int i; u32 csum; if (!vdev->notify || !vdev->notify_sz) return 0; do { csum = 0; rte_memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz); words = (u32 *)&vdev->notify_copy; for (i = 1; i < nwords; i++) csum += words[i]; } while (csum != words[0]); return 1; } int vnic_dev_init(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; int r = 0; if (vnic_dev_capable(vdev, CMD_INIT)) r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); else { vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); if (a0 & CMD_INITF_DEFAULT_MAC) { /* Emulate these for old CMD_INIT_v1 which * didn't pass a0 so no CMD_INITF_*. */ vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait); vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); } } return r; } int vnic_dev_deinit(struct vnic_dev *vdev) { u64 a0 = 0, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait); } void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev) { /* Default: hardware intr coal timer is in units of 1.5 usecs */ vdev->intr_coal_timer_info.mul = 2; vdev->intr_coal_timer_info.div = 3; vdev->intr_coal_timer_info.max_usec = vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff); } int vnic_dev_link_status(struct vnic_dev *vdev) { if (!vnic_dev_notify_ready(vdev)) return 0; return vdev->notify_copy.link_state; } u32 vnic_dev_port_speed(struct vnic_dev *vdev) { if (!vnic_dev_notify_ready(vdev)) return 0; return vdev->notify_copy.port_speed; } void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode) { vdev->intr_mode = intr_mode; } enum vnic_dev_intr_mode vnic_dev_get_intr_mode( struct vnic_dev *vdev) { return vdev->intr_mode; } u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec) { return (usec * vdev->intr_coal_timer_info.mul) / vdev->intr_coal_timer_info.div; } u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles) { return (hw_cycles * vdev->intr_coal_timer_info.div) / vdev->intr_coal_timer_info.mul; } u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev) { return vdev->intr_coal_timer_info.max_usec; } void vnic_dev_unregister(struct vnic_dev *vdev) { if (vdev) { if (vdev->notify) vdev->free_consistent(vdev->pdev, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); if (vdev->stats) vdev->free_consistent(vdev->pdev, sizeof(struct vnic_stats), vdev->stats, vdev->stats_pa); if (vdev->fw_info) vdev->free_consistent(vdev->pdev, sizeof(struct vnic_devcmd_fw_info), vdev->fw_info, vdev->fw_info_pa); kfree(vdev); } } struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, void *priv, struct rte_pci_device *pdev, struct vnic_dev_bar *bar, unsigned int num_bars) { if (!vdev) { vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC); if (!vdev) return NULL; } vdev->priv = priv; vdev->pdev = pdev; if (vnic_dev_discover_res(vdev, bar, num_bars)) goto err_out; vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0); if (!vdev->devcmd) goto err_out; return vdev; err_out: vnic_dev_unregister(vdev); return NULL; } struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev) { return vdev->pdev; } int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr) { u64 a0, a1 = 0; int wait = 1000; int i; for (i = 0; i < ETH_ALEN; i++) ((u8 *)&a0)[i] = mac_addr[i]; return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait); } /* * vnic_dev_classifier: Add/Delete classifier entries * @vdev: vdev of the device * @cmd: CLSF_ADD for Add filter * CLSF_DEL for Delete filter * @entry: In case of ADD filter, the caller passes the RQ number in this * variable. * This function stores the filter_id returned by the * firmware in the same variable before return; * * In case of DEL filter, the caller passes the RQ number. Return * value is irrelevant. * @data: filter data */ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, struct filter *data) { u64 a0, a1; int wait = 1000; dma_addr_t tlv_pa; int ret = -EINVAL; struct filter_tlv *tlv, *tlv_va; struct filter_action *action; u64 tlv_size; static unsigned int unique_id; char z_name[RTE_MEMZONE_NAMESIZE]; if (cmd == CLSF_ADD) { tlv_size = sizeof(struct filter) + sizeof(struct filter_action) + 2*sizeof(struct filter_tlv); snprintf((char *)z_name, sizeof(z_name), "vnic_clsf_%d", unique_id++); tlv_va = vdev->alloc_consistent(vdev->priv, tlv_size, &tlv_pa, (u8 *)z_name); if (!tlv_va) return -ENOMEM; tlv = tlv_va; a0 = tlv_pa; a1 = tlv_size; memset(tlv, 0, tlv_size); tlv->type = CLSF_TLV_FILTER; tlv->length = sizeof(struct filter); *(struct filter *)&tlv->val = *data; tlv = (struct filter_tlv *)((char *)tlv + sizeof(struct filter_tlv) + sizeof(struct filter)); tlv->type = CLSF_TLV_ACTION; tlv->length = sizeof(struct filter_action); action = (struct filter_action *)&tlv->val; action->type = FILTER_ACTION_RQ_STEERING; action->u.rq_idx = *entry; ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait); *entry = (u16)a0; vdev->free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa); } else if (cmd == CLSF_DEL) { a0 = *entry; ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait); } return ret; } ================================================ FILE: drivers/net/enic/base/vnic_dev.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_dev.h 196958 2014-11-04 18:23:37Z xuywang $" #ifndef _VNIC_DEV_H_ #define _VNIC_DEV_H_ #include "enic_compat.h" #include "rte_pci.h" #include "vnic_resource.h" #include "vnic_devcmd.h" #ifndef VNIC_PADDR_TARGET #define VNIC_PADDR_TARGET 0x0000000000000000ULL #endif #ifndef readq static inline u64 readq(void __iomem *reg) { return ((u64)readl((char *)reg + 0x4UL) << 32) | (u64)readl(reg); } static inline void writeq(u64 val, void __iomem *reg) { writel(val & 0xffffffff, reg); writel((u32)(val >> 32), (char *)reg + 0x4UL); } #endif #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt enum vnic_dev_intr_mode { VNIC_DEV_INTR_MODE_UNKNOWN, VNIC_DEV_INTR_MODE_INTX, VNIC_DEV_INTR_MODE_MSI, VNIC_DEV_INTR_MODE_MSIX, }; struct vnic_dev_bar { void __iomem *vaddr; dma_addr_t bus_addr; unsigned long len; }; struct vnic_dev_ring { void *descs; size_t size; dma_addr_t base_addr; size_t base_align; void *descs_unaligned; size_t size_unaligned; dma_addr_t base_addr_unaligned; unsigned int desc_size; unsigned int desc_count; unsigned int desc_avail; }; struct vnic_dev_iomap_info { dma_addr_t bus_addr; unsigned long len; void __iomem *vaddr; }; struct vnic_dev; struct vnic_stats; void *vnic_dev_priv(struct vnic_dev *vdev); unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, enum vnic_res_type type); void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), void (*free_consistent)(struct rte_pci_device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)); void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index); dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index); uint8_t vnic_dev_get_res_bar(struct vnic_dev *vdev, enum vnic_res_type type); uint32_t vnic_dev_get_res_offset(struct vnic_dev *vdev, enum vnic_res_type type, unsigned int index); unsigned long vnic_dev_get_res_type_len(struct vnic_dev *vdev, enum vnic_res_type type); unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size); void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring); void vnic_set_hdr_split_size(struct vnic_dev *vdev, u16 size); u16 vnic_get_hdr_split_size(struct vnic_dev *vdev); int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring, unsigned int desc_count, unsigned int desc_size, unsigned int socket_id, char *z_name); void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring); int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait); int vnic_dev_cmd_args(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, u64 *args, int nargs, int wait); void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, u16 index); void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf); void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev); int vnic_dev_fw_info(struct vnic_dev *vdev, struct vnic_devcmd_fw_info **fw_info); int vnic_dev_asic_info(struct vnic_dev *vdev, u16 *asic_type, u16 *asic_rev); int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size, void *value); int vnic_dev_stats_clear(struct vnic_dev *vdev); int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats); int vnic_dev_hang_notify(struct vnic_dev *vdev); int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, int broadcast, int promisc, int allmulti); int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed, int multicast, int broadcast, int promisc, int allmulti); int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr); int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr); void vnic_dev_set_reset_flag(struct vnic_dev *vdev, int state); int vnic_dev_notify_unset(struct vnic_dev *vdev); int vnic_dev_notify_setcmd(struct vnic_dev *vdev, void *notify_addr, dma_addr_t notify_pa, u16 intr); int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev); int vnic_dev_link_status(struct vnic_dev *vdev); u32 vnic_dev_port_speed(struct vnic_dev *vdev); u32 vnic_dev_msg_lvl(struct vnic_dev *vdev); u32 vnic_dev_mtu(struct vnic_dev *vdev); u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev); u32 vnic_dev_notify_status(struct vnic_dev *vdev); u32 vnic_dev_uif(struct vnic_dev *vdev); int vnic_dev_close(struct vnic_dev *vdev); int vnic_dev_enable(struct vnic_dev *vdev); int vnic_dev_enable_wait(struct vnic_dev *vdev); int vnic_dev_disable(struct vnic_dev *vdev); int vnic_dev_open(struct vnic_dev *vdev, int arg); int vnic_dev_open_done(struct vnic_dev *vdev, int *done); int vnic_dev_init(struct vnic_dev *vdev, int arg); int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err); int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len); int vnic_dev_deinit(struct vnic_dev *vdev); void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev); int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev); int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode); enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec); u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles); u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev); void vnic_dev_unregister(struct vnic_dev *vdev); int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, u8 ig_vlan_rewrite_mode); struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, void *priv, struct rte_pci_device *pdev, struct vnic_dev_bar *bar, unsigned int num_bars); struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev); int vnic_dev_cmd_init(struct vnic_dev *vdev, int fallback); int vnic_dev_get_size(void); int vnic_dev_int13(struct vnic_dev *vdev, u64 arg, u32 op); int vnic_dev_perbi(struct vnic_dev *vdev, u64 arg, u32 op); u32 vnic_dev_perbi_rebuild_cnt(struct vnic_dev *vdev); int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len); int vnic_dev_enable2(struct vnic_dev *vdev, int active); int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status); int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status); int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, struct filter *data); #ifdef ENIC_VXLAN int vnic_dev_overlay_offload_enable_disable(struct vnic_dev *vdev, u8 overlay, u8 config); int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay, u16 vxlan_udp_port_number); #endif #endif /* _VNIC_DEV_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_devcmd.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_devcmd.h 173135 2014-05-16 03:14:07Z sanpilla $" #ifndef _VNIC_DEVCMD_H_ #define _VNIC_DEVCMD_H_ #define _CMD_NBITS 14 #define _CMD_VTYPEBITS 10 #define _CMD_FLAGSBITS 6 #define _CMD_DIRBITS 2 #define _CMD_NMASK ((1 << _CMD_NBITS)-1) #define _CMD_VTYPEMASK ((1 << _CMD_VTYPEBITS)-1) #define _CMD_FLAGSMASK ((1 << _CMD_FLAGSBITS)-1) #define _CMD_DIRMASK ((1 << _CMD_DIRBITS)-1) #define _CMD_NSHIFT 0 #define _CMD_VTYPESHIFT (_CMD_NSHIFT+_CMD_NBITS) #define _CMD_FLAGSSHIFT (_CMD_VTYPESHIFT+_CMD_VTYPEBITS) #define _CMD_DIRSHIFT (_CMD_FLAGSSHIFT+_CMD_FLAGSBITS) /* * Direction bits (from host perspective). */ #define _CMD_DIR_NONE 0U #define _CMD_DIR_WRITE 1U #define _CMD_DIR_READ 2U #define _CMD_DIR_RW (_CMD_DIR_WRITE | _CMD_DIR_READ) /* * Flag bits. */ #define _CMD_FLAGS_NONE 0U #define _CMD_FLAGS_NOWAIT 1U /* * vNIC type bits. */ #define _CMD_VTYPE_NONE 0U #define _CMD_VTYPE_ENET 1U #define _CMD_VTYPE_FC 2U #define _CMD_VTYPE_SCSI 4U #define _CMD_VTYPE_ALL (_CMD_VTYPE_ENET | _CMD_VTYPE_FC | _CMD_VTYPE_SCSI) /* * Used to create cmds.. */ #define _CMDCF(dir, flags, vtype, nr) \ (((dir) << _CMD_DIRSHIFT) | \ ((flags) << _CMD_FLAGSSHIFT) | \ ((vtype) << _CMD_VTYPESHIFT) | \ ((nr) << _CMD_NSHIFT)) #define _CMDC(dir, vtype, nr) _CMDCF(dir, 0, vtype, nr) #define _CMDCNW(dir, vtype, nr) _CMDCF(dir, _CMD_FLAGS_NOWAIT, vtype, nr) /* * Used to decode cmds.. */ #define _CMD_DIR(cmd) (((cmd) >> _CMD_DIRSHIFT) & _CMD_DIRMASK) #define _CMD_FLAGS(cmd) (((cmd) >> _CMD_FLAGSSHIFT) & _CMD_FLAGSMASK) #define _CMD_VTYPE(cmd) (((cmd) >> _CMD_VTYPESHIFT) & _CMD_VTYPEMASK) #define _CMD_N(cmd) (((cmd) >> _CMD_NSHIFT) & _CMD_NMASK) enum vnic_devcmd_cmd { CMD_NONE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0), /* * mcpu fw info in mem: * in: * (u64)a0=paddr to struct vnic_devcmd_fw_info * action: * Fills in struct vnic_devcmd_fw_info (128 bytes) * note: * An old definition of CMD_MCPU_FW_INFO */ CMD_MCPU_FW_INFO_OLD = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1), /* * mcpu fw info in mem: * in: * (u64)a0=paddr to struct vnic_devcmd_fw_info * (u16)a1=size of the structure * out: * (u16)a1=0 for in:a1 = 0, * data size actually written for other values. * action: * Fills in first 128 bytes of vnic_devcmd_fw_info for in:a1 = 0, * first in:a1 bytes for 0 < in:a1 <= 132, * 132 bytes for other values of in:a1. * note: * CMD_MCPU_FW_INFO and CMD_MCPU_FW_INFO_OLD have the same enum 1 * for source compatibility. */ CMD_MCPU_FW_INFO = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 1), /* dev-specific block member: * in: (u16)a0=offset,(u8)a1=size * out: a0=value */ CMD_DEV_SPEC = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 2), /* stats clear */ CMD_STATS_CLEAR = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 3), /* stats dump in mem: (u64)a0=paddr to stats area, * (u16)a1=sizeof stats area */ CMD_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 4), /* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */ CMD_PACKET_FILTER = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7), /* set Rx packet filter for all: (u32)a0=filters (see CMD_PFILTER_*) */ CMD_PACKET_FILTER_ALL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 7), /* hang detection notification */ CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8), /* MAC address in (u48)a0 */ CMD_GET_MAC_ADDR = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9), /* add addr from (u48)a0 */ CMD_ADDR_ADD = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 12), /* del addr from (u48)a0 */ CMD_ADDR_DEL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET | _CMD_VTYPE_FC, 13), /* add VLAN id in (u16)a0 */ CMD_VLAN_ADD = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 14), /* del VLAN id in (u16)a0 */ CMD_VLAN_DEL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 15), /* nic_cfg in (u32)a0 */ CMD_NIC_CFG = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 16), /* union vnic_rss_key in mem: (u64)a0=paddr, (u16)a1=len */ CMD_RSS_KEY = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 17), /* union vnic_rss_cpu in mem: (u64)a0=paddr, (u16)a1=len */ CMD_RSS_CPU = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 18), /* initiate softreset */ CMD_SOFT_RESET = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 19), /* softreset status: * out: a0=0 reset complete, a0=1 reset in progress */ CMD_SOFT_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 20), /* set struct vnic_devcmd_notify buffer in mem: * in: * (u64)a0=paddr to notify (set paddr=0 to unset) * (u32)a1 & 0x00000000ffffffff=sizeof(struct vnic_devcmd_notify) * (u16)a1 & 0x0000ffff00000000=intr num (-1 for no intr) * out: * (u32)a1 = effective size */ CMD_NOTIFY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 21), /* UNDI API: (u64)a0=paddr to s_PXENV_UNDI_ struct, * (u8)a1=PXENV_UNDI_xxx */ CMD_UNDI = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 22), /* initiate open sequence (u32)a0=flags (see CMD_OPENF_*) */ CMD_OPEN = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 23), /* open status: * out: a0=0 open complete, a0=1 open in progress */ CMD_OPEN_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 24), /* close vnic */ CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25), /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ /***** Replaced by CMD_INIT *****/ CMD_INIT_v1 = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26), /* variant of CMD_INIT, with provisioning info * (u64)a0=paddr of vnic_devcmd_provinfo * (u32)a1=sizeof provision info */ CMD_INIT_PROV_INFO = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 27), /* enable virtual link */ CMD_ENABLE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28), /* enable virtual link, waiting variant. */ CMD_ENABLE_WAIT = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28), /* disable virtual link */ CMD_DISABLE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29), /* stats dump sum of all vnic stats on same uplink in mem: * (u64)a0=paddr * (u16)a1=sizeof stats area */ CMD_STATS_DUMP_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 30), /* init status: * out: a0=0 init complete, a0=1 init in progress * if a0=0, a1=errno */ CMD_INIT_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31), /* INT13 API: (u64)a0=paddr to vnic_int13_params struct * (u32)a1=INT13_CMD_xxx */ CMD_INT13 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32), /* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */ CMD_LOGICAL_UPLINK = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 33), /* undo initialize of virtual link */ CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */ CMD_INIT = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35), /* check fw capability of a cmd: * in: (u32)a0=cmd * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), /* persistent binding info * in: (u64)a0=paddr of arg * (u32)a1=CMD_PERBI_XXX */ CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37), /* Interrupt Assert Register functionality * in: (u16)a0=interrupt number to assert */ CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38), /* initiate hangreset, like softreset after hang detected */ CMD_HANG_RESET = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39), /* hangreset status: * out: a0=0 reset complete, a0=1 reset in progress */ CMD_HANG_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40), /* * Set hw ingress packet vlan rewrite mode: * in: (u32)a0=new vlan rewrite mode * out: (u32)a0=old vlan rewrite mode */ CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41), /* * in: (u16)a0=bdf of target vnic * (u32)a1=cmd to proxy * a2-a15=args to cmd in a1 * out: (u32)a0=status of proxied cmd * a1-a15=out args of proxied cmd */ CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42), /* * As for BY_BDF except a0 is index of hvnlink subordinate vnic * or SR-IOV virtual vnic */ CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), /* * For HPP toggle: * adapter-info-get * in: (u64)a0=phsical address of buffer passed in from caller. * (u16)a1=size of buffer specified in a0. * out: (u64)a0=phsical address of buffer passed in from caller. * (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or * 0 if no VIF-CONFIG-INFO TLV was ever received. */ CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), /* * INT13 API: (u64)a0=paddr to vnic_int13_params struct * (u32)a1=INT13_CMD_xxx */ CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45), /* * Set default vlan: * in: (u16)a0=new default vlan * (u16)a1=zero for overriding vlan with param a0, * non-zero for resetting vlan to the default * out: (u16)a0=old default vlan */ CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46), /* init_prov_info2: * Variant of CMD_INIT_PROV_INFO, where it will not try to enable * the vnic until CMD_ENABLE2 is issued. * (u64)a0=paddr of vnic_devcmd_provinfo * (u32)a1=sizeof provision info */ CMD_INIT_PROV_INFO2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47), /* enable2: * (u32)a0=0 ==> standby * =CMD_ENABLE2_ACTIVE ==> active */ CMD_ENABLE2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 48), /* * cmd_status: * Returns the status of the specified command * Input: * a0 = command for which status is being queried. * Possible values are: * CMD_SOFT_RESET * CMD_HANG_RESET * CMD_OPEN * CMD_INIT * CMD_INIT_PROV_INFO * CMD_DEINIT * CMD_INIT_PROV_INFO2 * CMD_ENABLE2 * Output: * if status == STAT_ERROR * a0 = ERR_ENOTSUPPORTED - status for command in a0 is * not supported * if status == STAT_NONE * a0 = status of the devcmd specified in a0 as follows. * ERR_SUCCESS - command in a0 completed successfully * ERR_EINPROGRESS - command in a0 is still in progress */ CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49), /* * Returns interrupt coalescing timer conversion factors. * After calling this devcmd, ENIC driver can convert * interrupt coalescing timer in usec into CPU cycles as follows: * * intr_timer_cycles = intr_timer_usec * multiplier / divisor * * Interrupt coalescing timer in usecs can be be converted/obtained * from CPU cycles as follows: * * intr_timer_usec = intr_timer_cycles * divisor / multiplier * * in: none * out: (u32)a0 = multiplier * (u32)a1 = divisor * (u32)a2 = maximum timer value in usec */ CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50), /* * ISCSI DUMP API: * in: (u64)a0=paddr of the param or param itself * (u32)a1=ISCSI_CMD_xxx */ CMD_ISCSI_DUMP_REQ = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 51), /* * ISCSI DUMP STATUS API: * in: (u32)a0=cmd tag * in: (u32)a1=ISCSI_CMD_xxx * out: (u32)a0=cmd status */ CMD_ISCSI_DUMP_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 52), /* * Subvnic migration from MQ <--> VF. * Enable the LIF migration from MQ to VF and vice versa. MQ and VF * indexes are statically bound at the time of initialization. * Based on the * direction of migration, the resources of either MQ or the VF shall * be attached to the LIF. * in: (u32)a0=Direction of Migration * 0=> Migrate to VF * 1=> Migrate to MQ * (u32)a1=VF index (MQ index) */ CMD_MIGRATE_SUBVNIC = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 53), /* * Register / Deregister the notification block for MQ subvnics * in: * (u64)a0=paddr to notify (set paddr=0 to unset) * (u32)a1 & 0x00000000ffffffff=sizeof(struct vnic_devcmd_notify) * (u16)a1 & 0x0000ffff00000000=intr num (-1 for no intr) * out: * (u32)a1 = effective size */ CMD_SUBVNIC_NOTIFY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 54), /* * Set the predefined mac address as default * in: * (u48)a0=mac addr */ CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55), /* Update the provisioning info of the given VIF * (u64)a0=paddr of vnic_devcmd_provinfo * (u32)a1=sizeof provision info */ CMD_PROV_INFO_UPDATE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 56), /* * Initialization for the devcmd2 interface. * in: (u64) a0=host result buffer physical address * in: (u16) a1=number of entries in result buffer */ CMD_INITIALIZE_DEVCMD2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 57), /* * Add a filter. * in: (u64) a0= filter address * (u32) a1= size of filter * out: (u32) a0=filter identifier */ CMD_ADD_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 58), /* * Delete a filter. * in: (u32) a0=filter identifier */ CMD_DEL_FILTER = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 59), /* * Enable a Queue Pair in User space NIC * in: (u32) a0=Queue Pair number * (u32) a1= command */ CMD_QP_ENABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 60), /* * Disable a Queue Pair in User space NIC * in: (u32) a0=Queue Pair number * (u32) a1= command */ CMD_QP_DISABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 61), /* * Stats dump Queue Pair in User space NIC * in: (u32) a0=Queue Pair number * (u64) a1=host buffer addr for status dump * (u32) a2=length of the buffer */ CMD_QP_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 62), /* * Clear stats for Queue Pair in User space NIC * in: (u32) a0=Queue Pair number */ CMD_QP_STATS_CLEAR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 63), /* * Enable/Disable overlay offloads on the given vnic * in: (u8) a0 = OVERLAY_FEATURE_NVGRE : NVGRE * a0 = OVERLAY_FEATURE_VXLAN : VxLAN * in: (u8) a1 = OVERLAY_OFFLOAD_ENABLE : Enable * a1 = OVERLAY_OFFLOAD_DISABLE : Disable */ CMD_OVERLAY_OFFLOAD_ENABLE_DISABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 72), /* * Configuration of overlay offloads feature on a given vNIC * in: (u8) a0 = DEVCMD_OVERLAY_NVGRE : NVGRE * a0 = DEVCMD_OVERLAY_VXLAN : VxLAN * in: (u8) a1 = VXLAN_PORT_UPDATE : VxLAN * in: (u16) a2 = unsigned short int port information */ CMD_OVERLAY_OFFLOAD_CFG = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 73), }; /* CMD_ENABLE2 flags */ #define CMD_ENABLE2_STANDBY 0x0 #define CMD_ENABLE2_ACTIVE 0x1 /* flags for CMD_OPEN */ #define CMD_OPENF_OPROM 0x1 /* open coming from option rom */ /* flags for CMD_INIT */ #define CMD_INITF_DEFAULT_MAC 0x1 /* init with default mac addr */ /* flags for CMD_PACKET_FILTER */ #define CMD_PFILTER_DIRECTED 0x01 #define CMD_PFILTER_MULTICAST 0x02 #define CMD_PFILTER_BROADCAST 0x04 #define CMD_PFILTER_PROMISCUOUS 0x08 #define CMD_PFILTER_ALL_MULTICAST 0x10 /* Commands for CMD_QP_ENABLE/CM_QP_DISABLE */ #define CMD_QP_RQWQ 0x0 /* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */ #define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK 0 #define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN 1 #define IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN 2 #define IG_VLAN_REWRITE_MODE_PASS_THRU 3 enum vnic_devcmd_status { STAT_NONE = 0, STAT_BUSY = 1 << 0, /* cmd in progress */ STAT_ERROR = 1 << 1, /* last cmd caused error (code in a0) */ }; enum vnic_devcmd_error { ERR_SUCCESS = 0, ERR_EINVAL = 1, ERR_EFAULT = 2, ERR_EPERM = 3, ERR_EBUSY = 4, ERR_ECMDUNKNOWN = 5, ERR_EBADSTATE = 6, ERR_ENOMEM = 7, ERR_ETIMEDOUT = 8, ERR_ELINKDOWN = 9, ERR_EMAXRES = 10, ERR_ENOTSUPPORTED = 11, ERR_EINPROGRESS = 12, ERR_MAX }; /* * note: hw_version and asic_rev refer to the same thing, * but have different formats. hw_version is * a 32-byte string (e.g. "A2") and asic_rev is * a 16-bit integer (e.g. 0xA2). */ struct vnic_devcmd_fw_info { char fw_version[32]; char fw_build[32]; char hw_version[32]; char hw_serial_number[32]; u16 asic_type; u16 asic_rev; }; enum fwinfo_asic_type { FWINFO_ASIC_TYPE_UNKNOWN, FWINFO_ASIC_TYPE_PALO, FWINFO_ASIC_TYPE_SERENO, }; struct vnic_devcmd_notify { u32 csum; /* checksum over following words */ u32 link_state; /* link up == 1 */ u32 port_speed; /* effective port speed (rate limit) */ u32 mtu; /* MTU */ u32 msglvl; /* requested driver msg lvl */ u32 uif; /* uplink interface */ u32 status; /* status bits (see VNIC_STF_*) */ u32 error; /* error code (see ERR_*) for first ERR */ u32 link_down_cnt; /* running count of link down transitions */ u32 perbi_rebuild_cnt; /* running count of perbi rebuilds */ }; #define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ #define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */ #define VNIC_STF_PFC_PAUSE 0x0004 /* priority flow control pause on */ /* all supported status flags */ #define VNIC_STF_ALL (VNIC_STF_FATAL_ERR |\ VNIC_STF_STD_PAUSE |\ VNIC_STF_PFC_PAUSE |\ 0) struct vnic_devcmd_provinfo { u8 oui[3]; u8 type; u8 data[0]; }; /* * These are used in flags field of different filters to denote * valid fields used. */ #define FILTER_FIELD_VALID(fld) (1 << (fld - 1)) #define FILTER_FIELDS_USNIC (FILTER_FIELD_VALID(1) | \ FILTER_FIELD_VALID(2) | \ FILTER_FIELD_VALID(3) | \ FILTER_FIELD_VALID(4)) #define FILTER_FIELDS_IPV4_5TUPLE (FILTER_FIELD_VALID(1) | \ FILTER_FIELD_VALID(2) | \ FILTER_FIELD_VALID(3) | \ FILTER_FIELD_VALID(4) | \ FILTER_FIELD_VALID(5)) #define FILTER_FIELDS_MAC_VLAN (FILTER_FIELD_VALID(1) | \ FILTER_FIELD_VALID(2)) #define FILTER_FIELD_USNIC_VLAN FILTER_FIELD_VALID(1) #define FILTER_FIELD_USNIC_ETHTYPE FILTER_FIELD_VALID(2) #define FILTER_FIELD_USNIC_PROTO FILTER_FIELD_VALID(3) #define FILTER_FIELD_USNIC_ID FILTER_FIELD_VALID(4) struct filter_usnic_id { u32 flags; u16 vlan; u16 ethtype; u8 proto_version; u32 usnic_id; } __attribute__((packed)); #define FILTER_FIELD_5TUP_PROTO FILTER_FIELD_VALID(1) #define FILTER_FIELD_5TUP_SRC_AD FILTER_FIELD_VALID(2) #define FILTER_FIELD_5TUP_DST_AD FILTER_FIELD_VALID(3) #define FILTER_FIELD_5TUP_SRC_PT FILTER_FIELD_VALID(4) #define FILTER_FIELD_5TUP_DST_PT FILTER_FIELD_VALID(5) /* Enums for the protocol field. */ enum protocol_e { PROTO_UDP = 0, PROTO_TCP = 1, }; struct filter_ipv4_5tuple { u32 flags; u32 protocol; u32 src_addr; u32 dst_addr; u16 src_port; u16 dst_port; } __attribute__((packed)); #define FILTER_FIELD_VMQ_VLAN FILTER_FIELD_VALID(1) #define FILTER_FIELD_VMQ_MAC FILTER_FIELD_VALID(2) struct filter_mac_vlan { u32 flags; u16 vlan; u8 mac_addr[6]; } __attribute__((packed)); /* Specifies the filter_action type. */ enum { FILTER_ACTION_RQ_STEERING = 0, FILTER_ACTION_MAX }; struct filter_action { u32 type; union { u32 rq_idx; } u; } __attribute__((packed)); /* Specifies the filter type. */ enum filter_type { FILTER_USNIC_ID = 0, FILTER_IPV4_5TUPLE = 1, FILTER_MAC_VLAN = 2, FILTER_MAX }; struct filter { u32 type; union { struct filter_usnic_id usnic; struct filter_ipv4_5tuple ipv4; struct filter_mac_vlan mac_vlan; } u; } __attribute__((packed)); enum { CLSF_TLV_FILTER = 0, CLSF_TLV_ACTION = 1, }; #define FILTER_MAX_BUF_SIZE 100 /* Maximum size of buffer to CMD_ADD_FILTER */ struct filter_tlv { uint32_t type; uint32_t length; uint32_t val[0]; }; enum { CLSF_ADD = 0, CLSF_DEL = 1, }; /* * Writing cmd register causes STAT_BUSY to get set in status register. * When cmd completes, STAT_BUSY will be cleared. * * If cmd completed successfully STAT_ERROR will be clear * and args registers contain cmd-specific results. * * If cmd error, STAT_ERROR will be set and args[0] contains error code. * * status register is read-only. While STAT_BUSY is set, * all other register contents are read-only. */ /* Make sizeof(vnic_devcmd) a power-of-2 for I/O BAR. */ #define VNIC_DEVCMD_NARGS 15 struct vnic_devcmd { u32 status; /* RO */ u32 cmd; /* RW */ u64 args[VNIC_DEVCMD_NARGS]; /* RW cmd args (little-endian) */ }; /* * Version 2 of the interface. * * Some things are carried over, notably the vnic_devcmd_cmd enum. */ /* * Flags for vnic_devcmd2.flags */ #define DEVCMD2_FNORESULT 0x1 /* Don't copy result to host */ #define VNIC_DEVCMD2_NARGS VNIC_DEVCMD_NARGS struct vnic_devcmd2 { u16 pad; u16 flags; u32 cmd; /* same command #defines as original */ u64 args[VNIC_DEVCMD2_NARGS]; }; #define VNIC_DEVCMD2_NRESULTS VNIC_DEVCMD_NARGS struct devcmd2_result { u64 results[VNIC_DEVCMD2_NRESULTS]; u32 pad; u16 completed_index; /* into copy WQ */ u8 error; /* same error codes as original */ u8 color; /* 0 or 1 as with completion queues */ }; #define DEVCMD2_RING_SIZE 32 #define DEVCMD2_DESC_SIZE 128 #define DEVCMD2_RESULTS_SIZE_MAX ((1 << 16) - 1) /* Overlay related definitions */ /* * This enum lists the flag associated with each of the overlay features */ typedef enum { OVERLAY_FEATURE_NVGRE = 1, OVERLAY_FEATURE_VXLAN, OVERLAY_FEATURE_MAX, } overlay_feature_t; #define OVERLAY_OFFLOAD_ENABLE 0 #define OVERLAY_OFFLOAD_DISABLE 1 #define OVERLAY_CFG_VXLAN_PORT_UPDATE 0 #endif /* _VNIC_DEVCMD_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_enet.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_enet.h 175806 2014-06-04 19:31:17Z rfaucett $" #ifndef _VNIC_ENIC_H_ #define _VNIC_ENIC_H_ /* Device-specific region: enet configuration */ struct vnic_enet_config { u32 flags; u32 wq_desc_count; u32 rq_desc_count; u16 mtu; u16 intr_timer_deprecated; u8 intr_timer_type; u8 intr_mode; char devname[16]; u32 intr_timer_usec; u16 loop_tag; u16 vf_rq_count; u16 num_arfs; u64 mem_paddr; }; #define VENETF_TSO 0x1 /* TSO enabled */ #define VENETF_LRO 0x2 /* LRO enabled */ #define VENETF_RXCSUM 0x4 /* RX csum enabled */ #define VENETF_TXCSUM 0x8 /* TX csum enabled */ #define VENETF_RSS 0x10 /* RSS enabled */ #define VENETF_RSSHASH_IPV4 0x20 /* Hash on IPv4 fields */ #define VENETF_RSSHASH_TCPIPV4 0x40 /* Hash on TCP + IPv4 fields */ #define VENETF_RSSHASH_IPV6 0x80 /* Hash on IPv6 fields */ #define VENETF_RSSHASH_TCPIPV6 0x100 /* Hash on TCP + IPv6 fields */ #define VENETF_RSSHASH_IPV6_EX 0x200 /* Hash on IPv6 extended fields */ #define VENETF_RSSHASH_TCPIPV6_EX 0x400 /* Hash on TCP + IPv6 ext. fields */ #define VENETF_LOOP 0x800 /* Loopback enabled */ #define VENETF_VMQ 0x4000 /* using VMQ flag for VMware NETQ */ #define VENETF_VXLAN 0x10000 /* VxLAN offload */ #define VENETF_NVGRE 0x20000 /* NVGRE offload */ #define VENET_INTR_TYPE_MIN 0 /* Timer specs min interrupt spacing */ #define VENET_INTR_TYPE_IDLE 1 /* Timer specs idle time before irq */ #define VENET_INTR_MODE_ANY 0 /* Try MSI-X, then MSI, then INTx */ #define VENET_INTR_MODE_MSI 1 /* Try MSI then INTx */ #define VENET_INTR_MODE_INTX 2 /* Try INTx only */ #endif /* _VNIC_ENIC_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_intr.c ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_intr.c 171146 2014-05-02 07:08:20Z ssujith $" #include "vnic_dev.h" #include "vnic_intr.h" void vnic_intr_free(struct vnic_intr *intr) { intr->ctrl = NULL; } int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, unsigned int index) { intr->index = index; intr->vdev = vdev; intr->ctrl = vnic_dev_get_res(vdev, RES_TYPE_INTR_CTRL, index); if (!intr->ctrl) { pr_err("Failed to hook INTR[%d].ctrl resource\n", index); return -EINVAL; } return 0; } void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion) { vnic_intr_coalescing_timer_set(intr, coalescing_timer); iowrite32(coalescing_type, &intr->ctrl->coalescing_type); iowrite32(mask_on_assertion, &intr->ctrl->mask_on_assertion); iowrite32(0, &intr->ctrl->int_credits); } void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, u32 coalescing_timer) { iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev, coalescing_timer), &intr->ctrl->coalescing_timer); } void vnic_intr_clean(struct vnic_intr *intr) { iowrite32(0, &intr->ctrl->int_credits); } ================================================ FILE: drivers/net/enic/base/vnic_intr.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_intr.h 171146 2014-05-02 07:08:20Z ssujith $" #ifndef _VNIC_INTR_H_ #define _VNIC_INTR_H_ #include "vnic_dev.h" #define VNIC_INTR_TIMER_TYPE_ABS 0 #define VNIC_INTR_TIMER_TYPE_QUIET 1 /* Interrupt control */ struct vnic_intr_ctrl { u32 coalescing_timer; /* 0x00 */ u32 pad0; u32 coalescing_value; /* 0x08 */ u32 pad1; u32 coalescing_type; /* 0x10 */ u32 pad2; u32 mask_on_assertion; /* 0x18 */ u32 pad3; u32 mask; /* 0x20 */ u32 pad4; u32 int_credits; /* 0x28 */ u32 pad5; u32 int_credit_return; /* 0x30 */ u32 pad6; }; struct vnic_intr { unsigned int index; struct vnic_dev *vdev; struct vnic_intr_ctrl __iomem *ctrl; /* memory-mapped */ }; static inline void vnic_intr_unmask(struct vnic_intr *intr) { iowrite32(0, &intr->ctrl->mask); } static inline void vnic_intr_mask(struct vnic_intr *intr) { iowrite32(1, &intr->ctrl->mask); } static inline int vnic_intr_masked(struct vnic_intr *intr) { return ioread32(&intr->ctrl->mask); } static inline void vnic_intr_return_credits(struct vnic_intr *intr, unsigned int credits, int unmask, int reset_timer) { #define VNIC_INTR_UNMASK_SHIFT 16 #define VNIC_INTR_RESET_TIMER_SHIFT 17 u32 int_credit_return = (credits & 0xffff) | (unmask ? (1 << VNIC_INTR_UNMASK_SHIFT) : 0) | (reset_timer ? (1 << VNIC_INTR_RESET_TIMER_SHIFT) : 0); iowrite32(int_credit_return, &intr->ctrl->int_credit_return); } static inline unsigned int vnic_intr_credits(struct vnic_intr *intr) { return ioread32(&intr->ctrl->int_credits); } static inline void vnic_intr_return_all_credits(struct vnic_intr *intr) { unsigned int credits = vnic_intr_credits(intr); int unmask = 1; int reset_timer = 1; vnic_intr_return_credits(intr, credits, unmask, reset_timer); } static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) { /* read PBA without clearing */ return ioread32(legacy_pba); } void vnic_intr_free(struct vnic_intr *intr); int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, unsigned int index); void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion); void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, u32 coalescing_timer); void vnic_intr_clean(struct vnic_intr *intr); #endif /* _VNIC_INTR_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_nic.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_nic.h 59839 2010-09-27 20:36:31Z roprabhu $" #ifndef _VNIC_NIC_H_ #define _VNIC_NIC_H_ #define NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD 0xffUL #define NIC_CFG_RSS_DEFAULT_CPU_SHIFT 0 #define NIC_CFG_RSS_HASH_TYPE (0xffUL << 8) #define NIC_CFG_RSS_HASH_TYPE_MASK_FIELD 0xffUL #define NIC_CFG_RSS_HASH_TYPE_SHIFT 8 #define NIC_CFG_RSS_HASH_BITS (7UL << 16) #define NIC_CFG_RSS_HASH_BITS_MASK_FIELD 7UL #define NIC_CFG_RSS_HASH_BITS_SHIFT 16 #define NIC_CFG_RSS_BASE_CPU (7UL << 19) #define NIC_CFG_RSS_BASE_CPU_MASK_FIELD 7UL #define NIC_CFG_RSS_BASE_CPU_SHIFT 19 #define NIC_CFG_RSS_ENABLE (1UL << 22) #define NIC_CFG_RSS_ENABLE_MASK_FIELD 1UL #define NIC_CFG_RSS_ENABLE_SHIFT 22 #define NIC_CFG_TSO_IPID_SPLIT_EN (1UL << 23) #define NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD 1UL #define NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT 23 #define NIC_CFG_IG_VLAN_STRIP_EN (1UL << 24) #define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD 1UL #define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT 24 #define NIC_CFG_RSS_HASH_TYPE_IPV4 (1 << 1) #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 (1 << 2) #define NIC_CFG_RSS_HASH_TYPE_IPV6 (1 << 3) #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 (1 << 4) #define NIC_CFG_RSS_HASH_TYPE_IPV6_EX (1 << 5) #define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX (1 << 6) static inline void vnic_set_nic_cfg(u32 *nic_cfg, u8 rss_default_cpu, u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, u8 ig_vlan_strip_en) { *nic_cfg = (rss_default_cpu & NIC_CFG_RSS_DEFAULT_CPU_MASK_FIELD) | ((rss_hash_type & NIC_CFG_RSS_HASH_TYPE_MASK_FIELD) << NIC_CFG_RSS_HASH_TYPE_SHIFT) | ((rss_hash_bits & NIC_CFG_RSS_HASH_BITS_MASK_FIELD) << NIC_CFG_RSS_HASH_BITS_SHIFT) | ((rss_base_cpu & NIC_CFG_RSS_BASE_CPU_MASK_FIELD) << NIC_CFG_RSS_BASE_CPU_SHIFT) | ((rss_enable & NIC_CFG_RSS_ENABLE_MASK_FIELD) << NIC_CFG_RSS_ENABLE_SHIFT) | ((tso_ipid_split_en & NIC_CFG_TSO_IPID_SPLIT_EN_MASK_FIELD) << NIC_CFG_TSO_IPID_SPLIT_EN_SHIFT) | ((ig_vlan_strip_en & NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD) << NIC_CFG_IG_VLAN_STRIP_EN_SHIFT); } #endif /* _VNIC_NIC_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_resource.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_resource.h 196958 2014-11-04 18:23:37Z xuywang $" #ifndef _VNIC_RESOURCE_H_ #define _VNIC_RESOURCE_H_ #define VNIC_RES_MAGIC 0x766E6963L /* 'vnic' */ #define VNIC_RES_VERSION 0x00000000L #define MGMTVNIC_MAGIC 0x544d474dL /* 'MGMT' */ #define MGMTVNIC_VERSION 0x00000000L /* The MAC address assigned to the CFG vNIC is fixed. */ #define MGMTVNIC_MAC { 0x02, 0x00, 0x54, 0x4d, 0x47, 0x4d } /* vNIC resource types */ enum vnic_res_type { RES_TYPE_EOL, /* End-of-list */ RES_TYPE_WQ, /* Work queues */ RES_TYPE_RQ, /* Receive queues */ RES_TYPE_CQ, /* Completion queues */ RES_TYPE_MEM, /* Window to dev memory */ RES_TYPE_NIC_CFG, /* Enet NIC config registers */ RES_TYPE_RSS_KEY, /* Enet RSS secret key */ RES_TYPE_RSS_CPU, /* Enet RSS indirection table */ RES_TYPE_TX_STATS, /* Netblock Tx statistic regs */ RES_TYPE_RX_STATS, /* Netblock Rx statistic regs */ RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */ RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */ RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */ RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status */ RES_TYPE_DEBUG, /* Debug-only info */ RES_TYPE_DEV, /* Device-specific region */ RES_TYPE_DEVCMD, /* Device command region */ RES_TYPE_PASS_THRU_PAGE, /* Pass-thru page */ RES_TYPE_SUBVNIC, /* subvnic resource type */ RES_TYPE_MQ_WQ, /* MQ Work queues */ RES_TYPE_MQ_RQ, /* MQ Receive queues */ RES_TYPE_MQ_CQ, /* MQ Completion queues */ RES_TYPE_DEPRECATED1, /* Old version of devcmd 2 */ RES_TYPE_DEVCMD2, /* Device control region */ RES_TYPE_MAX, /* Count of resource types */ }; struct vnic_resource_header { u32 magic; u32 version; }; struct mgmt_barmap_hdr { u32 magic; /* magic number */ u32 version; /* header format version */ u16 lif; /* loopback lif for mgmt frames */ u16 pci_slot; /* installed pci slot */ char serial[16]; /* card serial number */ }; struct vnic_resource { u8 type; u8 bar; u8 pad[2]; u32 bar_offset; u32 count; }; #endif /* _VNIC_RESOURCE_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_rq.c ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_rq.c 171146 2014-05-02 07:08:20Z ssujith $" #include "vnic_dev.h" #include "vnic_rq.h" static int vnic_rq_alloc_bufs(struct vnic_rq *rq) { struct vnic_rq_buf *buf; unsigned int i, j, count = rq->ring.desc_count; unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count); for (i = 0; i < blks; i++) { rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC); if (!rq->bufs[i]) return -ENOMEM; } for (i = 0; i < blks; i++) { buf = rq->bufs[i]; for (j = 0; j < VNIC_RQ_BUF_BLK_ENTRIES(count); j++) { buf->index = i * VNIC_RQ_BUF_BLK_ENTRIES(count) + j; buf->desc = (u8 *)rq->ring.descs + rq->ring.desc_size * buf->index; if (buf->index + 1 == count) { buf->next = rq->bufs[0]; break; } else if (j + 1 == VNIC_RQ_BUF_BLK_ENTRIES(count)) { buf->next = rq->bufs[i + 1]; } else { buf->next = buf + 1; buf++; } } } rq->to_use = rq->to_clean = rq->bufs[0]; return 0; } int vnic_rq_mem_size(struct vnic_rq *rq, unsigned int desc_count, unsigned int desc_size) { int mem_size = 0; mem_size += vnic_dev_desc_ring_size(&rq->ring, desc_count, desc_size); mem_size += VNIC_RQ_BUF_BLKS_NEEDED(rq->ring.desc_count) * VNIC_RQ_BUF_BLK_SZ(rq->ring.desc_count); return mem_size; } void vnic_rq_free(struct vnic_rq *rq) { struct vnic_dev *vdev; unsigned int i; vdev = rq->vdev; vnic_dev_free_desc_ring(vdev, &rq->ring); for (i = 0; i < VNIC_RQ_BUF_BLKS_MAX; i++) { if (rq->bufs[i]) { kfree(rq->bufs[i]); rq->bufs[i] = NULL; } } rq->ctrl = NULL; } int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, unsigned int desc_count, unsigned int desc_size) { int err; char res_name[NAME_MAX]; static int instance; rq->index = index; rq->vdev = vdev; rq->ctrl = vnic_dev_get_res(vdev, RES_TYPE_RQ, index); if (!rq->ctrl) { pr_err("Failed to hook RQ[%d] resource\n", index); return -EINVAL; } vnic_rq_disable(rq); snprintf(res_name, sizeof(res_name), "%d-rq-%d", instance++, index); err = vnic_dev_alloc_desc_ring(vdev, &rq->ring, desc_count, desc_size, rq->socket_id, res_name); if (err) return err; err = vnic_rq_alloc_bufs(rq); if (err) { vnic_rq_free(rq); return err; } return 0; } void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) { u64 paddr; unsigned int count = rq->ring.desc_count; paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET; writeq(paddr, &rq->ctrl->ring_base); iowrite32(count, &rq->ctrl->ring_size); iowrite32(cq_index, &rq->ctrl->cq_index); iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable); iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset); iowrite32(0, &rq->ctrl->dropped_packet_count); iowrite32(0, &rq->ctrl->error_status); iowrite32(fetch_index, &rq->ctrl->fetch_index); iowrite32(posted_index, &rq->ctrl->posted_index); rq->to_use = rq->to_clean = &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)] [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)]; } void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) { u32 fetch_index = 0; /* Use current fetch_index as the ring starting point */ fetch_index = ioread32(&rq->ctrl->fetch_index); if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */ /* Hardware surprise removal: reset fetch_index */ fetch_index = 0; } vnic_rq_init_start(rq, cq_index, fetch_index, fetch_index, error_interrupt_enable, error_interrupt_offset); } void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error) { iowrite32(error, &rq->ctrl->error_status); } unsigned int vnic_rq_error_status(struct vnic_rq *rq) { return ioread32(&rq->ctrl->error_status); } void vnic_rq_enable(struct vnic_rq *rq) { iowrite32(1, &rq->ctrl->enable); } int vnic_rq_disable(struct vnic_rq *rq) { unsigned int wait; iowrite32(0, &rq->ctrl->enable); /* Wait for HW to ACK disable request */ for (wait = 0; wait < 1000; wait++) { if (!(ioread32(&rq->ctrl->running))) return 0; udelay(10); } pr_err("Failed to disable RQ[%d]\n", rq->index); return -ETIMEDOUT; } void vnic_rq_clean(struct vnic_rq *rq, void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf)) { struct vnic_rq_buf *buf; u32 fetch_index; unsigned int count = rq->ring.desc_count; buf = rq->to_clean; while (vnic_rq_desc_used(rq) > 0) { (*buf_clean)(rq, buf); buf = rq->to_clean = buf->next; rq->ring.desc_avail++; } /* Use current fetch_index as the ring starting point */ fetch_index = ioread32(&rq->ctrl->fetch_index); if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone */ /* Hardware surprise removal: reset fetch_index */ fetch_index = 0; } rq->to_use = rq->to_clean = &rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES(count)] [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)]; iowrite32(fetch_index, &rq->ctrl->posted_index); vnic_dev_clear_desc_ring(&rq->ring); } ================================================ FILE: drivers/net/enic/base/vnic_rq.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_rq.h 180262 2014-07-02 07:57:43Z gvaradar $" #ifndef _VNIC_RQ_H_ #define _VNIC_RQ_H_ #include "vnic_dev.h" #include "vnic_cq.h" /* Receive queue control */ struct vnic_rq_ctrl { u64 ring_base; /* 0x00 */ u32 ring_size; /* 0x08 */ u32 pad0; u32 posted_index; /* 0x10 */ u32 pad1; u32 cq_index; /* 0x18 */ u32 pad2; u32 enable; /* 0x20 */ u32 pad3; u32 running; /* 0x28 */ u32 pad4; u32 fetch_index; /* 0x30 */ u32 pad5; u32 error_interrupt_enable; /* 0x38 */ u32 pad6; u32 error_interrupt_offset; /* 0x40 */ u32 pad7; u32 error_status; /* 0x48 */ u32 pad8; u32 dropped_packet_count; /* 0x50 */ u32 pad9; u32 dropped_packet_count_rc; /* 0x58 */ u32 pad10; }; /* Break the vnic_rq_buf allocations into blocks of 32/64 entries */ #define VNIC_RQ_BUF_MIN_BLK_ENTRIES 32 #define VNIC_RQ_BUF_DFLT_BLK_ENTRIES 64 #define VNIC_RQ_BUF_BLK_ENTRIES(entries) \ ((unsigned int)((entries < VNIC_RQ_BUF_DFLT_BLK_ENTRIES) ? \ VNIC_RQ_BUF_MIN_BLK_ENTRIES : VNIC_RQ_BUF_DFLT_BLK_ENTRIES)) #define VNIC_RQ_BUF_BLK_SZ(entries) \ (VNIC_RQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_rq_buf)) #define VNIC_RQ_BUF_BLKS_NEEDED(entries) \ DIV_ROUND_UP(entries, VNIC_RQ_BUF_BLK_ENTRIES(entries)) #define VNIC_RQ_BUF_BLKS_MAX VNIC_RQ_BUF_BLKS_NEEDED(4096) struct vnic_rq_buf { struct vnic_rq_buf *next; dma_addr_t dma_addr; void *os_buf; unsigned int os_buf_index; unsigned int len; unsigned int index; void *desc; uint64_t wr_id; }; struct vnic_rq { unsigned int index; struct vnic_dev *vdev; struct vnic_rq_ctrl __iomem *ctrl; /* memory-mapped */ struct vnic_dev_ring ring; struct vnic_rq_buf *bufs[VNIC_RQ_BUF_BLKS_MAX]; struct vnic_rq_buf *to_use; struct vnic_rq_buf *to_clean; void *os_buf_head; unsigned int pkts_outstanding; unsigned int socket_id; struct rte_mempool *mp; }; static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq) { /* how many does SW own? */ return rq->ring.desc_avail; } static inline unsigned int vnic_rq_desc_used(struct vnic_rq *rq) { /* how many does HW own? */ return rq->ring.desc_count - rq->ring.desc_avail - 1; } static inline void *vnic_rq_next_desc(struct vnic_rq *rq) { return rq->to_use->desc; } static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq) { return rq->to_use->index; } static inline void vnic_rq_post(struct vnic_rq *rq, void *os_buf, unsigned int os_buf_index, dma_addr_t dma_addr, unsigned int len, uint64_t wrid) { struct vnic_rq_buf *buf = rq->to_use; buf->os_buf = os_buf; buf->os_buf_index = os_buf_index; buf->dma_addr = dma_addr; buf->len = len; buf->wr_id = wrid; buf = buf->next; rq->to_use = buf; rq->ring.desc_avail--; /* Move the posted_index every nth descriptor */ #ifndef VNIC_RQ_RETURN_RATE #define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */ #endif if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) { /* Adding write memory barrier prevents compiler and/or CPU * reordering, thus avoiding descriptor posting before * descriptor is initialized. Otherwise, hardware can read * stale descriptor fields. */ wmb(); iowrite32(buf->index, &rq->ctrl->posted_index); } } static inline void vnic_rq_post_commit(struct vnic_rq *rq, void *os_buf, unsigned int os_buf_index, dma_addr_t dma_addr, unsigned int len) { struct vnic_rq_buf *buf = rq->to_use; buf->os_buf = os_buf; buf->os_buf_index = os_buf_index; buf->dma_addr = dma_addr; buf->len = len; buf = buf->next; rq->to_use = buf; rq->ring.desc_avail--; /* Move the posted_index every descriptor */ /* Adding write memory barrier prevents compiler and/or CPU * reordering, thus avoiding descriptor posting before * descriptor is initialized. Otherwise, hardware can read * stale descriptor fields. */ wmb(); iowrite32(buf->index, &rq->ctrl->posted_index); } static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count) { rq->ring.desc_avail += count; } enum desc_return_options { VNIC_RQ_RETURN_DESC, VNIC_RQ_DEFER_RETURN_DESC, }; static inline int vnic_rq_service(struct vnic_rq *rq, struct cq_desc *cq_desc, u16 completed_index, int desc_return, int (*buf_service)(struct vnic_rq *rq, struct cq_desc *cq_desc, struct vnic_rq_buf *buf, int skipped, void *opaque), void *opaque) { struct vnic_rq_buf *buf; int skipped; int eop = 0; buf = rq->to_clean; while (1) { skipped = (buf->index != completed_index); if ((*buf_service)(rq, cq_desc, buf, skipped, opaque)) eop++; if (desc_return == VNIC_RQ_RETURN_DESC) rq->ring.desc_avail++; rq->to_clean = buf->next; if (!skipped) break; buf = rq->to_clean; } return eop; } static inline int vnic_rq_fill(struct vnic_rq *rq, int (*buf_fill)(struct vnic_rq *rq)) { int err; while (vnic_rq_desc_avail(rq) > 0) { err = (*buf_fill)(rq); if (err) return err; } return 0; } static inline int vnic_rq_fill_count(struct vnic_rq *rq, int (*buf_fill)(struct vnic_rq *rq), unsigned int count) { int err; while ((vnic_rq_desc_avail(rq) > 0) && (count--)) { err = (*buf_fill)(rq); if (err) return err; } return 0; } void vnic_rq_free(struct vnic_rq *rq); int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index, unsigned int desc_count, unsigned int desc_size); void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error); unsigned int vnic_rq_error_status(struct vnic_rq *rq); void vnic_rq_enable(struct vnic_rq *rq); int vnic_rq_disable(struct vnic_rq *rq); void vnic_rq_clean(struct vnic_rq *rq, void (*buf_clean)(struct vnic_rq *rq, struct vnic_rq_buf *buf)); int vnic_rq_mem_size(struct vnic_rq *rq, unsigned int desc_count, unsigned int desc_size); #endif /* _VNIC_RQ_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_rss.c ================================================ /* * Copyright 2008 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #include "enic_compat.h" #include "vnic_rss.h" void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key) { u32 i; u32 *p; u16 *q; for (i = 0; i < 4; ++i) { p = (u32 *)(key + (10 * i)); iowrite32(*p++, &rss_key->key[i].b[0]); iowrite32(*p++, &rss_key->key[i].b[4]); q = (u16 *)p; iowrite32(*q, &rss_key->key[i].b[8]); } } void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu) { u32 i; u32 *p = (u32 *)cpu; for (i = 0; i < 32; ++i) iowrite32(*p++, &rss_cpu->cpu[i].b[0]); } void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key) { u32 i; u32 *p; u16 *q; for (i = 0; i < 4; ++i) { p = (u32 *)(key + (10 * i)); *p++ = ioread32(&rss_key->key[i].b[0]); *p++ = ioread32(&rss_key->key[i].b[4]); q = (u16 *)p; *q = (u16)ioread32(&rss_key->key[i].b[8]); } } void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu) { u32 i; u32 *p = (u32 *)cpu; for (i = 0; i < 32; ++i) *p++ = ioread32(&rss_cpu->cpu[i].b[0]); } ================================================ FILE: drivers/net/enic/base/vnic_rss.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ident "$Id: vnic_rss.h 64224 2010-11-09 19:43:13Z vkolluri $" #ifndef _VNIC_RSS_H_ #define _VNIC_RSS_H_ /* RSS key array */ union vnic_rss_key { struct { u8 b[10]; u8 b_pad[6]; } key[4]; u64 raw[8]; }; /* RSS cpu array */ union vnic_rss_cpu { struct { u8 b[4]; u8 b_pad[4]; } cpu[32]; u64 raw[32]; }; void vnic_set_rss_key(union vnic_rss_key *rss_key, u8 *key); void vnic_set_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); void vnic_get_rss_key(union vnic_rss_key *rss_key, u8 *key); void vnic_get_rss_cpu(union vnic_rss_cpu *rss_cpu, u8 *cpu); #endif /* _VNIC_RSS_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_stats.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_stats.h 84040 2011-08-09 23:38:43Z dwang2 $" #ifndef _VNIC_STATS_H_ #define _VNIC_STATS_H_ /* Tx statistics */ struct vnic_tx_stats { u64 tx_frames_ok; u64 tx_unicast_frames_ok; u64 tx_multicast_frames_ok; u64 tx_broadcast_frames_ok; u64 tx_bytes_ok; u64 tx_unicast_bytes_ok; u64 tx_multicast_bytes_ok; u64 tx_broadcast_bytes_ok; u64 tx_drops; u64 tx_errors; u64 tx_tso; u64 rsvd[16]; }; /* Rx statistics */ struct vnic_rx_stats { u64 rx_frames_ok; u64 rx_frames_total; u64 rx_unicast_frames_ok; u64 rx_multicast_frames_ok; u64 rx_broadcast_frames_ok; u64 rx_bytes_ok; u64 rx_unicast_bytes_ok; u64 rx_multicast_bytes_ok; u64 rx_broadcast_bytes_ok; u64 rx_drop; u64 rx_no_bufs; u64 rx_errors; u64 rx_rss; u64 rx_crc_errors; u64 rx_frames_64; u64 rx_frames_127; u64 rx_frames_255; u64 rx_frames_511; u64 rx_frames_1023; u64 rx_frames_1518; u64 rx_frames_to_max; u64 rsvd[16]; }; struct vnic_stats { struct vnic_tx_stats tx; struct vnic_rx_stats rx; }; #endif /* _VNIC_STATS_H_ */ ================================================ FILE: drivers/net/enic/base/vnic_wq.c ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_wq.c 183023 2014-07-22 23:47:25Z xuywang $" #include "vnic_dev.h" #include "vnic_wq.h" static inline int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, enum vnic_res_type res_type) { wq->ctrl = vnic_dev_get_res(vdev, res_type, index); if (!wq->ctrl) return -EINVAL; return 0; } static inline int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int desc_count, unsigned int desc_size) { char res_name[NAME_MAX]; static int instance; snprintf(res_name, sizeof(res_name), "%d-wq-%d", instance++, wq->index); return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size, wq->socket_id, res_name); } static int vnic_wq_alloc_bufs(struct vnic_wq *wq) { struct vnic_wq_buf *buf; unsigned int i, j, count = wq->ring.desc_count; unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count); for (i = 0; i < blks; i++) { wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC); if (!wq->bufs[i]) return -ENOMEM; } for (i = 0; i < blks; i++) { buf = wq->bufs[i]; for (j = 0; j < VNIC_WQ_BUF_BLK_ENTRIES(count); j++) { buf->index = i * VNIC_WQ_BUF_BLK_ENTRIES(count) + j; buf->desc = (u8 *)wq->ring.descs + wq->ring.desc_size * buf->index; if (buf->index + 1 == count) { buf->next = wq->bufs[0]; break; } else if (j + 1 == VNIC_WQ_BUF_BLK_ENTRIES(count)) { buf->next = wq->bufs[i + 1]; } else { buf->next = buf + 1; buf++; } } } wq->to_use = wq->to_clean = wq->bufs[0]; return 0; } void vnic_wq_free(struct vnic_wq *wq) { struct vnic_dev *vdev; unsigned int i; vdev = wq->vdev; vnic_dev_free_desc_ring(vdev, &wq->ring); for (i = 0; i < VNIC_WQ_BUF_BLKS_MAX; i++) { if (wq->bufs[i]) { kfree(wq->bufs[i]); wq->bufs[i] = NULL; } } wq->ctrl = NULL; } int vnic_wq_mem_size(struct vnic_wq *wq, unsigned int desc_count, unsigned int desc_size) { int mem_size = 0; mem_size += vnic_dev_desc_ring_size(&wq->ring, desc_count, desc_size); mem_size += VNIC_WQ_BUF_BLKS_NEEDED(wq->ring.desc_count) * VNIC_WQ_BUF_BLK_SZ(wq->ring.desc_count); return mem_size; } int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, unsigned int desc_count, unsigned int desc_size) { int err; wq->index = index; wq->vdev = vdev; err = vnic_wq_get_ctrl(vdev, wq, index, RES_TYPE_WQ); if (err) { pr_err("Failed to hook WQ[%d] resource, err %d\n", index, err); return err; } vnic_wq_disable(wq); err = vnic_wq_alloc_ring(vdev, wq, desc_count, desc_size); if (err) return err; err = vnic_wq_alloc_bufs(wq); if (err) { vnic_wq_free(wq); return err; } return 0; } void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) { u64 paddr; unsigned int count = wq->ring.desc_count; paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET; writeq(paddr, &wq->ctrl->ring_base); iowrite32(count, &wq->ctrl->ring_size); iowrite32(fetch_index, &wq->ctrl->fetch_index); iowrite32(posted_index, &wq->ctrl->posted_index); iowrite32(cq_index, &wq->ctrl->cq_index); iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable); iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset); iowrite32(0, &wq->ctrl->error_status); wq->to_use = wq->to_clean = &wq->bufs[fetch_index / VNIC_WQ_BUF_BLK_ENTRIES(count)] [fetch_index % VNIC_WQ_BUF_BLK_ENTRIES(count)]; } void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset) { vnic_wq_init_start(wq, cq_index, 0, 0, error_interrupt_enable, error_interrupt_offset); } void vnic_wq_error_out(struct vnic_wq *wq, unsigned int error) { iowrite32(error, &wq->ctrl->error_status); } unsigned int vnic_wq_error_status(struct vnic_wq *wq) { return ioread32(&wq->ctrl->error_status); } void vnic_wq_enable(struct vnic_wq *wq) { iowrite32(1, &wq->ctrl->enable); } int vnic_wq_disable(struct vnic_wq *wq) { unsigned int wait; iowrite32(0, &wq->ctrl->enable); /* Wait for HW to ACK disable request */ for (wait = 0; wait < 1000; wait++) { if (!(ioread32(&wq->ctrl->running))) return 0; udelay(10); } pr_err("Failed to disable WQ[%d]\n", wq->index); return -ETIMEDOUT; } void vnic_wq_clean(struct vnic_wq *wq, void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)) { struct vnic_wq_buf *buf; buf = wq->to_clean; while (vnic_wq_desc_used(wq) > 0) { (*buf_clean)(wq, buf); buf = wq->to_clean = buf->next; wq->ring.desc_avail++; } wq->to_use = wq->to_clean = wq->bufs[0]; iowrite32(0, &wq->ctrl->fetch_index); iowrite32(0, &wq->ctrl->posted_index); iowrite32(0, &wq->ctrl->error_status); vnic_dev_clear_desc_ring(&wq->ring); } ================================================ FILE: drivers/net/enic/base/vnic_wq.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: vnic_wq.h 183023 2014-07-22 23:47:25Z xuywang $" #ifndef _VNIC_WQ_H_ #define _VNIC_WQ_H_ #include "vnic_dev.h" #include "vnic_cq.h" /* Work queue control */ struct vnic_wq_ctrl { u64 ring_base; /* 0x00 */ u32 ring_size; /* 0x08 */ u32 pad0; u32 posted_index; /* 0x10 */ u32 pad1; u32 cq_index; /* 0x18 */ u32 pad2; u32 enable; /* 0x20 */ u32 pad3; u32 running; /* 0x28 */ u32 pad4; u32 fetch_index; /* 0x30 */ u32 pad5; u32 dca_value; /* 0x38 */ u32 pad6; u32 error_interrupt_enable; /* 0x40 */ u32 pad7; u32 error_interrupt_offset; /* 0x48 */ u32 pad8; u32 error_status; /* 0x50 */ u32 pad9; }; struct vnic_wq_buf { struct vnic_wq_buf *next; dma_addr_t dma_addr; void *os_buf; unsigned int len; unsigned int index; int sop; void *desc; uint64_t wr_id; /* Cookie */ uint8_t cq_entry; /* Gets completion event from hw */ uint8_t desc_skip_cnt; /* Num descs to occupy */ uint8_t compressed_send; /* Both hdr and payload in one desc */ }; /* Break the vnic_wq_buf allocations into blocks of 32/64 entries */ #define VNIC_WQ_BUF_MIN_BLK_ENTRIES 32 #define VNIC_WQ_BUF_DFLT_BLK_ENTRIES 64 #define VNIC_WQ_BUF_BLK_ENTRIES(entries) \ ((unsigned int)((entries < VNIC_WQ_BUF_DFLT_BLK_ENTRIES) ? \ VNIC_WQ_BUF_MIN_BLK_ENTRIES : VNIC_WQ_BUF_DFLT_BLK_ENTRIES)) #define VNIC_WQ_BUF_BLK_SZ(entries) \ (VNIC_WQ_BUF_BLK_ENTRIES(entries) * sizeof(struct vnic_wq_buf)) #define VNIC_WQ_BUF_BLKS_NEEDED(entries) \ DIV_ROUND_UP(entries, VNIC_WQ_BUF_BLK_ENTRIES(entries)) #define VNIC_WQ_BUF_BLKS_MAX VNIC_WQ_BUF_BLKS_NEEDED(4096) struct vnic_wq { unsigned int index; struct vnic_dev *vdev; struct vnic_wq_ctrl __iomem *ctrl; /* memory-mapped */ struct vnic_dev_ring ring; struct vnic_wq_buf *bufs[VNIC_WQ_BUF_BLKS_MAX]; struct vnic_wq_buf *to_use; struct vnic_wq_buf *to_clean; unsigned int pkts_outstanding; unsigned int socket_id; }; static inline unsigned int vnic_wq_desc_avail(struct vnic_wq *wq) { /* how many does SW own? */ return wq->ring.desc_avail; } static inline unsigned int vnic_wq_desc_used(struct vnic_wq *wq) { /* how many does HW own? */ return wq->ring.desc_count - wq->ring.desc_avail - 1; } static inline void *vnic_wq_next_desc(struct vnic_wq *wq) { return wq->to_use->desc; } #define PI_LOG2_CACHE_LINE_SIZE 5 #define PI_INDEX_BITS 12 #define PI_INDEX_MASK ((1U << PI_INDEX_BITS) - 1) #define PI_PREFETCH_LEN_MASK ((1U << PI_LOG2_CACHE_LINE_SIZE) - 1) #define PI_PREFETCH_LEN_OFF 16 #define PI_PREFETCH_ADDR_BITS 43 #define PI_PREFETCH_ADDR_MASK ((1ULL << PI_PREFETCH_ADDR_BITS) - 1) #define PI_PREFETCH_ADDR_OFF 21 /** How many cache lines are touched by buffer (addr, len). */ static inline unsigned int num_cache_lines_touched(dma_addr_t addr, unsigned int len) { const unsigned long mask = PI_PREFETCH_LEN_MASK; const unsigned long laddr = (unsigned long)addr; unsigned long lines, equiv_len; /* A. If addr is aligned, our solution is just to round up len to the next boundary. e.g. addr = 0, len = 48 +--------------------+ |XXXXXXXXXXXXXXXXXXXX| 32-byte cacheline a +--------------------+ |XXXXXXXXXX | cacheline b +--------------------+ B. If addr is not aligned, however, we may use an extra cacheline. e.g. addr = 12, len = 22 +--------------------+ | XXXXXXXXXXXXX| +--------------------+ |XX | +--------------------+ Our solution is to make the problem equivalent to case A above by adding the empty space in the first cacheline to the length: unsigned long len; +--------------------+ |eeeeeeeXXXXXXXXXXXXX| "e" is empty space, which we add to len +--------------------+ |XX | +--------------------+ */ equiv_len = len + (laddr & mask); /* Now we can just round up this len to the next 32-byte boundary. */ lines = (equiv_len + mask) & (~mask); /* Scale bytes -> cachelines. */ return lines >> PI_LOG2_CACHE_LINE_SIZE; } static inline u64 vnic_cached_posted_index(dma_addr_t addr, unsigned int len, unsigned int index) { unsigned int num_cache_lines = num_cache_lines_touched(addr, len); /* Wish we could avoid a branch here. We could have separate * vnic_wq_post() and vinc_wq_post_inline(), the latter * only supporting < 1k (2^5 * 2^5) sends, I suppose. This would * eliminate the if (eop) branch as well. */ if (num_cache_lines > PI_PREFETCH_LEN_MASK) num_cache_lines = 0; return (index & PI_INDEX_MASK) | ((num_cache_lines & PI_PREFETCH_LEN_MASK) << PI_PREFETCH_LEN_OFF) | (((addr >> PI_LOG2_CACHE_LINE_SIZE) & PI_PREFETCH_ADDR_MASK) << PI_PREFETCH_ADDR_OFF); } static inline void vnic_wq_post(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, int sop, int eop, uint8_t desc_skip_cnt, uint8_t cq_entry, uint8_t compressed_send, uint64_t wrid) { struct vnic_wq_buf *buf = wq->to_use; buf->sop = sop; buf->cq_entry = cq_entry; buf->compressed_send = compressed_send; buf->desc_skip_cnt = desc_skip_cnt; buf->os_buf = os_buf; buf->dma_addr = dma_addr; buf->len = len; buf->wr_id = wrid; buf = buf->next; if (eop) { #ifdef DO_PREFETCH uint64_t wr = vnic_cached_posted_index(dma_addr, len, buf->index); #endif /* Adding write memory barrier prevents compiler and/or CPU * reordering, thus avoiding descriptor posting before * descriptor is initialized. Otherwise, hardware can read * stale descriptor fields. */ wmb(); #ifdef DO_PREFETCH /* Intel chipsets seem to limit the rate of PIOs that we can * push on the bus. Thus, it is very important to do a single * 64 bit write here. With two 32-bit writes, my maximum * pkt/sec rate was cut almost in half. -AJF */ iowrite64((uint64_t)wr, &wq->ctrl->posted_index); #else iowrite32(buf->index, &wq->ctrl->posted_index); #endif } wq->to_use = buf; wq->ring.desc_avail -= desc_skip_cnt; } static inline void vnic_wq_service(struct vnic_wq *wq, struct cq_desc *cq_desc, u16 completed_index, void (*buf_service)(struct vnic_wq *wq, struct cq_desc *cq_desc, struct vnic_wq_buf *buf, void *opaque), void *opaque) { struct vnic_wq_buf *buf; buf = wq->to_clean; while (1) { (*buf_service)(wq, cq_desc, buf, opaque); wq->ring.desc_avail++; wq->to_clean = buf->next; if (buf->index == completed_index) break; buf = wq->to_clean; } } void vnic_wq_free(struct vnic_wq *wq); int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index, unsigned int desc_count, unsigned int desc_size); void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index, unsigned int fetch_index, unsigned int posted_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index, unsigned int error_interrupt_enable, unsigned int error_interrupt_offset); void vnic_wq_error_out(struct vnic_wq *wq, unsigned int error); unsigned int vnic_wq_error_status(struct vnic_wq *wq); void vnic_wq_enable(struct vnic_wq *wq); int vnic_wq_disable(struct vnic_wq *wq); void vnic_wq_clean(struct vnic_wq *wq, void (*buf_clean)(struct vnic_wq *wq, struct vnic_wq_buf *buf)); int vnic_wq_mem_size(struct vnic_wq *wq, unsigned int desc_count, unsigned int desc_size); #endif /* _VNIC_WQ_H_ */ ================================================ FILE: drivers/net/enic/base/wq_enet_desc.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: wq_enet_desc.h 59839 2010-09-27 20:36:31Z roprabhu $" #ifndef _WQ_ENET_DESC_H_ #define _WQ_ENET_DESC_H_ /* Ethernet work queue descriptor: 16B */ struct wq_enet_desc { __le64 address; __le16 length; __le16 mss_loopback; __le16 header_length_flags; __le16 vlan_tag; }; #define WQ_ENET_ADDR_BITS 64 #define WQ_ENET_LEN_BITS 14 #define WQ_ENET_LEN_MASK ((1 << WQ_ENET_LEN_BITS) - 1) #define WQ_ENET_MSS_BITS 14 #define WQ_ENET_MSS_MASK ((1 << WQ_ENET_MSS_BITS) - 1) #define WQ_ENET_MSS_SHIFT 2 #define WQ_ENET_LOOPBACK_SHIFT 1 #define WQ_ENET_HDRLEN_BITS 10 #define WQ_ENET_HDRLEN_MASK ((1 << WQ_ENET_HDRLEN_BITS) - 1) #define WQ_ENET_FLAGS_OM_BITS 2 #define WQ_ENET_FLAGS_OM_MASK ((1 << WQ_ENET_FLAGS_OM_BITS) - 1) #define WQ_ENET_FLAGS_EOP_SHIFT 12 #define WQ_ENET_FLAGS_CQ_ENTRY_SHIFT 13 #define WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT 14 #define WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT 15 #define WQ_ENET_OFFLOAD_MODE_CSUM 0 #define WQ_ENET_OFFLOAD_MODE_RESERVED 1 #define WQ_ENET_OFFLOAD_MODE_CSUM_L4 2 #define WQ_ENET_OFFLOAD_MODE_TSO 3 static inline void wq_enet_desc_enc(struct wq_enet_desc *desc, u64 address, u16 length, u16 mss, u16 header_length, u8 offload_mode, u8 eop, u8 cq_entry, u8 fcoe_encap, u8 vlan_tag_insert, u16 vlan_tag, u8 loopback) { desc->address = cpu_to_le64(address); desc->length = cpu_to_le16(length & WQ_ENET_LEN_MASK); desc->mss_loopback = cpu_to_le16((mss & WQ_ENET_MSS_MASK) << WQ_ENET_MSS_SHIFT | (loopback & 1) << WQ_ENET_LOOPBACK_SHIFT); desc->header_length_flags = cpu_to_le16( (header_length & WQ_ENET_HDRLEN_MASK) | (offload_mode & WQ_ENET_FLAGS_OM_MASK) << WQ_ENET_HDRLEN_BITS | (eop & 1) << WQ_ENET_FLAGS_EOP_SHIFT | (cq_entry & 1) << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT | (fcoe_encap & 1) << WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT | (vlan_tag_insert & 1) << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT); desc->vlan_tag = cpu_to_le16(vlan_tag); } static inline void wq_enet_desc_dec(struct wq_enet_desc *desc, u64 *address, u16 *length, u16 *mss, u16 *header_length, u8 *offload_mode, u8 *eop, u8 *cq_entry, u8 *fcoe_encap, u8 *vlan_tag_insert, u16 *vlan_tag, u8 *loopback) { *address = le64_to_cpu(desc->address); *length = le16_to_cpu(desc->length) & WQ_ENET_LEN_MASK; *mss = (le16_to_cpu(desc->mss_loopback) >> WQ_ENET_MSS_SHIFT) & WQ_ENET_MSS_MASK; *loopback = (u8)((le16_to_cpu(desc->mss_loopback) >> WQ_ENET_LOOPBACK_SHIFT) & 1); *header_length = le16_to_cpu(desc->header_length_flags) & WQ_ENET_HDRLEN_MASK; *offload_mode = (u8)((le16_to_cpu(desc->header_length_flags) >> WQ_ENET_HDRLEN_BITS) & WQ_ENET_FLAGS_OM_MASK); *eop = (u8)((le16_to_cpu(desc->header_length_flags) >> WQ_ENET_FLAGS_EOP_SHIFT) & 1); *cq_entry = (u8)((le16_to_cpu(desc->header_length_flags) >> WQ_ENET_FLAGS_CQ_ENTRY_SHIFT) & 1); *fcoe_encap = (u8)((le16_to_cpu(desc->header_length_flags) >> WQ_ENET_FLAGS_FCOE_ENCAP_SHIFT) & 1); *vlan_tag_insert = (u8)((le16_to_cpu(desc->header_length_flags) >> WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT) & 1); *vlan_tag = le16_to_cpu(desc->vlan_tag); } #endif /* _WQ_ENET_DESC_H_ */ ================================================ FILE: drivers/net/enic/enic.h ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #ifndef _ENIC_H_ #define _ENIC_H_ #include "vnic_enet.h" #include "vnic_dev.h" #include "vnic_wq.h" #include "vnic_rq.h" #include "vnic_cq.h" #include "vnic_intr.h" #include "vnic_stats.h" #include "vnic_nic.h" #include "vnic_rss.h" #include "enic_res.h" #define DRV_NAME "enic_pmd" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Poll-mode Driver" #define DRV_VERSION "1.0.0.5" #define DRV_COPYRIGHT "Copyright 2008-2015 Cisco Systems, Inc" #define ENIC_WQ_MAX 8 #define ENIC_RQ_MAX 8 #define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) #define VLAN_ETH_HLEN 18 #define ENICPMD_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) #define ENICPMD_BDF_LENGTH 13 /* 0000:00:00.0'\0' */ #define PKT_TX_TCP_UDP_CKSUM 0x6000 #define ENIC_CALC_IP_CKSUM 1 #define ENIC_CALC_TCP_UDP_CKSUM 2 #define ENIC_MAX_MTU 9000 #define ENIC_PAGE_SIZE 4096 #define PAGE_ROUND_UP(x) \ ((((unsigned long)(x)) + ENIC_PAGE_SIZE-1) & (~(ENIC_PAGE_SIZE-1))) #define ENICPMD_VFIO_PATH "/dev/vfio/vfio" /*#define ENIC_DESC_COUNT_MAKE_ODD (x) do{if ((~(x)) & 1) { (x)--; } }while(0)*/ #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ #define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ #define ENICPMD_FDIR_MAX 64 struct enic_fdir_node { struct rte_eth_fdir_filter filter; u16 fltr_id; u16 rq_index; }; struct enic_fdir { struct rte_eth_fdir_stats stats; struct rte_hash *hash; struct enic_fdir_node *nodes[ENICPMD_FDIR_MAX]; }; /* Per-instance private data structure */ struct enic { struct enic *next; struct rte_pci_device *pdev; struct vnic_enet_config config; struct vnic_dev_bar bar0; struct vnic_dev *vdev; unsigned int port_id; struct rte_eth_dev *rte_dev; struct enic_fdir fdir; char bdf_name[ENICPMD_BDF_LENGTH]; int dev_fd; int iommu_group_fd; int iommu_groupid; int eventfd; uint8_t mac_addr[ETH_ALEN]; pthread_t err_intr_thread; int promisc; int allmulti; u8 ig_vlan_strip_en; int link_status; u8 hw_ip_checksum; unsigned int flags; unsigned int priv_flags; /* work queue */ struct vnic_wq wq[ENIC_WQ_MAX]; unsigned int wq_count; /* receive queue */ struct vnic_rq rq[ENIC_RQ_MAX]; unsigned int rq_count; /* completion queue */ struct vnic_cq cq[ENIC_CQ_MAX]; unsigned int cq_count; /* interrupt resource */ struct vnic_intr intr; unsigned int intr_count; }; static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq) { return rq; } static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) { return enic->rq_count + wq; } static inline unsigned int enic_msix_err_intr(__rte_unused struct enic *enic) { return 0; } static inline struct enic *pmd_priv(struct rte_eth_dev *eth_dev) { return (struct enic *)eth_dev->data->dev_private; } extern void enic_fdir_stats_get(struct enic *enic, struct rte_eth_fdir_stats *stats); extern int enic_fdir_add_fltr(struct enic *enic, struct rte_eth_fdir_filter *params); extern int enic_fdir_del_fltr(struct enic *enic, struct rte_eth_fdir_filter *params); extern void enic_free_wq(void *txq); extern int enic_alloc_intr_resources(struct enic *enic); extern int enic_setup_finish(struct enic *enic); extern int enic_alloc_wq(struct enic *enic, uint16_t queue_idx, unsigned int socket_id, uint16_t nb_desc); extern void enic_start_wq(struct enic *enic, uint16_t queue_idx); extern int enic_stop_wq(struct enic *enic, uint16_t queue_idx); extern void enic_start_rq(struct enic *enic, uint16_t queue_idx); extern int enic_stop_rq(struct enic *enic, uint16_t queue_idx); extern void enic_free_rq(void *rxq); extern int enic_alloc_rq(struct enic *enic, uint16_t queue_idx, unsigned int socket_id, struct rte_mempool *mp, uint16_t nb_desc); extern int enic_set_rss_nic_cfg(struct enic *enic); extern int enic_set_vnic_res(struct enic *enic); extern void enic_set_hdr_split_size(struct enic *enic, u16 split_hdr_size); extern int enic_enable(struct enic *enic); extern int enic_disable(struct enic *enic); extern void enic_remove(struct enic *enic); extern int enic_get_link_status(struct enic *enic); extern void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats); extern void enic_dev_stats_clear(struct enic *enic); extern void enic_add_packet_filter(struct enic *enic); extern void enic_set_mac_address(struct enic *enic, uint8_t *mac_addr); extern void enic_del_mac_address(struct enic *enic); extern unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq); extern int enic_send_pkt(struct enic *enic, struct vnic_wq *wq, struct rte_mbuf *tx_pkt, unsigned short len, uint8_t sop, uint8_t eop, uint16_t ol_flags, uint16_t vlan_tag); extern int enic_poll(struct vnic_rq *rq, struct rte_mbuf **rx_pkts, unsigned int budget, unsigned int *work_done); extern int enic_probe(struct enic *enic); extern int enic_clsf_init(struct enic *enic); extern void enic_clsf_destroy(struct enic *enic); #endif /* _ENIC_H_ */ ================================================ FILE: drivers/net/enic/enic_clsf.c ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #include #include #include #include #include #include "enic_compat.h" #include "enic.h" #include "wq_enet_desc.h" #include "rq_enet_desc.h" #include "cq_enet_desc.h" #include "vnic_enet.h" #include "vnic_dev.h" #include "vnic_wq.h" #include "vnic_rq.h" #include "vnic_cq.h" #include "vnic_intr.h" #include "vnic_nic.h" #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #define DEFAULT_HASH_FUNC rte_hash_crc #else #include #define DEFAULT_HASH_FUNC rte_jhash #endif #define SOCKET_0 0 #define ENICPMD_CLSF_HASH_ENTRIES ENICPMD_FDIR_MAX void enic_fdir_stats_get(struct enic *enic, struct rte_eth_fdir_stats *stats) { *stats = enic->fdir.stats; } int enic_fdir_del_fltr(struct enic *enic, struct rte_eth_fdir_filter *params) { int32_t pos; struct enic_fdir_node *key; /* See if the key is in the table */ pos = rte_hash_del_key(enic->fdir.hash, params); switch (pos) { case -EINVAL: case -ENOENT: enic->fdir.stats.f_remove++; return -EINVAL; default: /* The entry is present in the table */ key = enic->fdir.nodes[pos]; /* Delete the filter */ vnic_dev_classifier(enic->vdev, CLSF_DEL, &key->fltr_id, NULL); rte_free(key); enic->fdir.nodes[pos] = NULL; enic->fdir.stats.free++; enic->fdir.stats.remove++; break; } return 0; } int enic_fdir_add_fltr(struct enic *enic, struct rte_eth_fdir_filter *params) { struct enic_fdir_node *key; struct filter fltr = {0}; int32_t pos; u8 do_free = 0; u16 old_fltr_id = 0; u32 flowtype_supported; u16 flex_bytes; u16 queue; flowtype_supported = ( (RTE_ETH_FLOW_NONFRAG_IPV4_TCP == params->input.flow_type) || (RTE_ETH_FLOW_NONFRAG_IPV4_UDP == params->input.flow_type)); flex_bytes = ((params->input.flow_ext.flexbytes[1] << 8 & 0xFF00) | (params->input.flow_ext.flexbytes[0] & 0xFF)); if (!enic->fdir.hash || (params->input.flow_ext.vlan_tci & 0xFFF) || !flowtype_supported || flex_bytes || params->action.behavior /* drop */) { enic->fdir.stats.f_add++; return -ENOTSUP; } queue = params->action.rx_queue; /* See if the key is already there in the table */ pos = rte_hash_del_key(enic->fdir.hash, params); switch (pos) { case -EINVAL: enic->fdir.stats.f_add++; return -EINVAL; case -ENOENT: /* Add a new classifier entry */ if (!enic->fdir.stats.free) { enic->fdir.stats.f_add++; return -ENOSPC; } key = rte_zmalloc("enic_fdir_node", sizeof(struct enic_fdir_node), 0); if (!key) { enic->fdir.stats.f_add++; return -ENOMEM; } break; default: /* The entry is already present in the table. * Check if there is a change in queue */ key = enic->fdir.nodes[pos]; enic->fdir.nodes[pos] = NULL; if (unlikely(key->rq_index == queue)) { /* Nothing to be done */ pos = rte_hash_add_key(enic->fdir.hash, params); enic->fdir.nodes[pos] = key; enic->fdir.stats.f_add++; dev_warning(enic, "FDIR rule is already present\n"); return 0; } if (likely(enic->fdir.stats.free)) { /* Add the filter and then delete the old one. * This is to avoid packets from going into the * default queue during the window between * delete and add */ do_free = 1; old_fltr_id = key->fltr_id; } else { /* No free slots in the classifier. * Delete the filter and add the modified one later */ vnic_dev_classifier(enic->vdev, CLSF_DEL, &key->fltr_id, NULL); enic->fdir.stats.free++; } break; } key->filter = *params; key->rq_index = queue; fltr.type = FILTER_IPV4_5TUPLE; fltr.u.ipv4.src_addr = rte_be_to_cpu_32( params->input.flow.ip4_flow.src_ip); fltr.u.ipv4.dst_addr = rte_be_to_cpu_32( params->input.flow.ip4_flow.dst_ip); fltr.u.ipv4.src_port = rte_be_to_cpu_16( params->input.flow.udp4_flow.src_port); fltr.u.ipv4.dst_port = rte_be_to_cpu_16( params->input.flow.udp4_flow.dst_port); if (RTE_ETH_FLOW_NONFRAG_IPV4_TCP == params->input.flow_type) fltr.u.ipv4.protocol = PROTO_TCP; else fltr.u.ipv4.protocol = PROTO_UDP; fltr.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; if (!vnic_dev_classifier(enic->vdev, CLSF_ADD, &queue, &fltr)) { key->fltr_id = queue; } else { dev_err(enic, "Add classifier entry failed\n"); enic->fdir.stats.f_add++; rte_free(key); return -1; } if (do_free) vnic_dev_classifier(enic->vdev, CLSF_DEL, &old_fltr_id, NULL); else{ enic->fdir.stats.free--; enic->fdir.stats.add++; } pos = rte_hash_add_key(enic->fdir.hash, (void *)key); enic->fdir.nodes[pos] = key; return 0; } void enic_clsf_destroy(struct enic *enic) { u32 index; struct enic_fdir_node *key; /* delete classifier entries */ for (index = 0; index < ENICPMD_FDIR_MAX; index++) { key = enic->fdir.nodes[index]; if (key) { vnic_dev_classifier(enic->vdev, CLSF_DEL, &key->fltr_id, NULL); rte_free(key); } } if (enic->fdir.hash) { rte_hash_free(enic->fdir.hash); enic->fdir.hash = NULL; } } int enic_clsf_init(struct enic *enic) { struct rte_hash_parameters hash_params = { .name = "enicpmd_clsf_hash", .entries = ENICPMD_CLSF_HASH_ENTRIES, .key_len = RTE_HASH_KEY_LENGTH_MAX, .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, .socket_id = SOCKET_0, }; enic->fdir.hash = rte_hash_create(&hash_params); memset(&enic->fdir.stats, 0, sizeof(enic->fdir.stats)); enic->fdir.stats.free = ENICPMD_FDIR_MAX; return (NULL == enic->fdir.hash); } ================================================ FILE: drivers/net/enic/enic_compat.h ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #ifndef _ENIC_COMPAT_H_ #define _ENIC_COMPAT_H_ #include #include #include #include #include #define ENIC_PAGE_ALIGN 4096UL #define ENIC_ALIGN ENIC_PAGE_ALIGN #define NAME_MAX 255 #define ETH_ALEN 6 #define __iomem #define rmb() rte_rmb() /* dpdk rte provided rmb */ #define wmb() rte_wmb() /* dpdk rte provided wmb */ #define le16_to_cpu #define le32_to_cpu #define le64_to_cpu #define cpu_to_le16 #define cpu_to_le32 #define cpu_to_le64 #ifndef offsetof #define offsetof(t, m) ((size_t) &((t *)0)->m) #endif #define pr_err(y, args...) dev_err(0, y, ##args) #define pr_warn(y, args...) dev_warning(0, y, ##args) #define BUG() pr_err("BUG at %s:%d", __func__, __LINE__) #define VNIC_ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) #define udelay usleep #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) #define kzalloc(size, flags) calloc(1, size) #define kfree(x) free(x) #define dev_printk(level, fmt, args...) \ RTE_LOG(level, PMD, "rte_enic_pmd: " fmt, ## args) #define dev_err(x, args...) dev_printk(ERR, args) #define dev_info(x, args...) dev_printk(INFO, args) #define dev_warning(x, args...) dev_printk(WARNING, args) #define dev_debug(x, args...) dev_printk(DEBUG, args) #define __le16 u16 #define __le32 u32 #define __le64 u64 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef unsigned long long dma_addr_t; static inline uint32_t ioread32(volatile void *addr) { return *(volatile uint32_t *)addr; } static inline uint16_t ioread16(volatile void *addr) { return *(volatile uint16_t *)addr; } static inline uint8_t ioread8(volatile void *addr) { return *(volatile uint8_t *)addr; } static inline void iowrite32(uint32_t val, volatile void *addr) { *(volatile uint32_t *)addr = val; } static inline void iowrite16(uint16_t val, volatile void *addr) { *(volatile uint16_t *)addr = val; } static inline void iowrite8(uint8_t val, volatile void *addr) { *(volatile uint8_t *)addr = val; } static inline unsigned int readl(volatile void __iomem *addr) { return *(volatile unsigned int *)addr; } static inline void writel(unsigned int val, volatile void __iomem *addr) { *(volatile unsigned int *)addr = val; } #define min_t(type, x, y) ({ \ type __min1 = (x); \ type __min2 = (y); \ __min1 < __min2 ? __min1 : __min2; }) #define max_t(type, x, y) ({ \ type __max1 = (x); \ type __max2 = (y); \ __max1 > __max2 ? __max1 : __max2; }) #endif /* _ENIC_COMPAT_H_ */ ================================================ FILE: drivers/net/enic/enic_ethdev.c ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #include #include #include #include #include #include #include "vnic_intr.h" #include "vnic_cq.h" #include "vnic_wq.h" #include "vnic_rq.h" #include "vnic_enet.h" #include "enic.h" #ifdef RTE_LIBRTE_ENIC_DEBUG #define ENICPMD_FUNC_TRACE() \ RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__) #else #define ENICPMD_FUNC_TRACE() (void)0 #endif /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_enic_map[] = { #define RTE_PCI_DEV_ID_DECL_ENIC(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #ifndef PCI_VENDOR_ID_CISCO #define PCI_VENDOR_ID_CISCO 0x1137 #endif #include "rte_pci_dev_ids.h" RTE_PCI_DEV_ID_DECL_ENIC(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) RTE_PCI_DEV_ID_DECL_ENIC(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) {.vendor_id = 0, /* Sentinal */}, }; static int enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev, enum rte_filter_op filter_op, void *arg) { struct enic *enic = pmd_priv(eth_dev); int ret = 0; ENICPMD_FUNC_TRACE(); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) return -EINVAL; switch (filter_op) { case RTE_ETH_FILTER_ADD: case RTE_ETH_FILTER_UPDATE: ret = enic_fdir_add_fltr(enic, (struct rte_eth_fdir_filter *)arg); break; case RTE_ETH_FILTER_DELETE: ret = enic_fdir_del_fltr(enic, (struct rte_eth_fdir_filter *)arg); break; case RTE_ETH_FILTER_STATS: enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg); break; case RTE_ETH_FILTER_FLUSH: case RTE_ETH_FILTER_INFO: dev_warning(enic, "unsupported operation %u", filter_op); ret = -ENOTSUP; break; default: dev_err(enic, "unknown operation %u", filter_op); ret = -EINVAL; break; } return ret; } static int enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg) { int ret = -EINVAL; if (RTE_ETH_FILTER_FDIR == filter_type) ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg); else dev_warning(enic, "Filter type (%d) not supported", filter_type); return ret; } static void enicpmd_dev_tx_queue_release(void *txq) { ENICPMD_FUNC_TRACE(); enic_free_wq(txq); } static int enicpmd_dev_setup_intr(struct enic *enic) { int ret; unsigned int index; ENICPMD_FUNC_TRACE(); /* Are we done with the init of all the queues? */ for (index = 0; index < enic->cq_count; index++) { if (!enic->cq[index].ctrl) break; } if (enic->cq_count != index) return 0; ret = enic_alloc_intr_resources(enic); if (ret) { dev_err(enic, "alloc intr failed\n"); return ret; } enic_init_vnic_resources(enic); ret = enic_setup_finish(enic); if (ret) dev_err(enic, "setup could not be finished\n"); return ret; } static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, __rte_unused const struct rte_eth_txconf *tx_conf) { int ret; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx]; ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc); if (ret) { dev_err(enic, "error in allocating wq\n"); return ret; } return enicpmd_dev_setup_intr(enic); } static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev, uint16_t queue_idx) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_start_wq(enic, queue_idx); return 0; } static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t queue_idx) { int ret; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); ret = enic_stop_wq(enic, queue_idx); if (ret) dev_err(enic, "error in stopping wq %d\n", queue_idx); return ret; } static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t queue_idx) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_start_rq(enic, queue_idx); return 0; } static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t queue_idx) { int ret; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); ret = enic_stop_rq(enic, queue_idx); if (ret) dev_err(enic, "error in stopping rq %d\n", queue_idx); return ret; } static void enicpmd_dev_rx_queue_release(void *rxq) { ENICPMD_FUNC_TRACE(); enic_free_rq(rxq); } static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, __rte_unused const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { int ret; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); eth_dev->data->rx_queues[queue_idx] = (void *)&enic->rq[queue_idx]; ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc); if (ret) { dev_err(enic, "error in allocating rq\n"); return ret; } return enicpmd_dev_setup_intr(enic); } static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id, int on) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); if (on) enic_add_vlan(enic, vlan_id); else enic_del_vlan(enic, vlan_id); return 0; } static void enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); if (mask & ETH_VLAN_STRIP_MASK) { if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip) enic->ig_vlan_strip_en = 1; else enic->ig_vlan_strip_en = 0; } enic_set_rss_nic_cfg(enic); if (mask & ETH_VLAN_FILTER_MASK) { dev_warning(enic, "Configuration of VLAN filter is not supported\n"); } if (mask & ETH_VLAN_EXTEND_MASK) { dev_warning(enic, "Configuration of extended VLAN is not supported\n"); } } static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev) { int ret; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); ret = enic_set_vnic_res(enic); if (ret) { dev_err(enic, "Set vNIC resource num failed, aborting\n"); return ret; } if (eth_dev->data->dev_conf.rxmode.split_hdr_size && eth_dev->data->dev_conf.rxmode.header_split) { /* Enable header-data-split */ enic_set_hdr_split_size(enic, eth_dev->data->dev_conf.rxmode.split_hdr_size); } enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum; return 0; } /* Start the device. * It returns 0 on success. */ static int enicpmd_dev_start(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); return enic_enable(enic); } /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev) { struct rte_eth_link link; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_disable(enic); memset(&link, 0, sizeof(link)); rte_atomic64_cmpset((uint64_t *)ð_dev->data->dev_link, *(uint64_t *)ð_dev->data->dev_link, *(uint64_t *)&link); } /* * Stop device. */ static void enicpmd_dev_close(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_remove(enic); } static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete) { struct enic *enic = pmd_priv(eth_dev); int ret; int link_status = 0; ENICPMD_FUNC_TRACE(); link_status = enic_get_link_status(enic); ret = (link_status == enic->link_status); enic->link_status = link_status; eth_dev->data->dev_link.link_status = link_status; eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); return ret; } static void enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_dev_stats_get(enic, stats); } static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_dev_stats_clear(enic); } static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *device_info) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); device_info->max_rx_queues = enic->rq_count; device_info->max_tx_queues = enic->wq_count; device_info->min_rx_bufsize = ENIC_MIN_MTU; device_info->max_rx_pktlen = enic->config.mtu; device_info->max_mac_addrs = 1; device_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; device_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM; } static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic->promisc = 1; enic_add_packet_filter(enic); } static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic->promisc = 0; enic_add_packet_filter(enic); } static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic->allmulti = 1; enic_add_packet_filter(enic); } static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic->allmulti = 0; enic_add_packet_filter(enic); } static void enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev, struct ether_addr *mac_addr, __rte_unused uint32_t index, __rte_unused uint32_t pool) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_set_mac_address(enic, mac_addr->addr_bytes); } static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, __rte_unused uint32_t index) { struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic_del_mac_address(enic); } static uint16_t enicpmd_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { unsigned int index; unsigned int frags; unsigned int pkt_len; unsigned int seg_len; unsigned int inc_len; unsigned int nb_segs; struct rte_mbuf *tx_pkt; struct vnic_wq *wq = (struct vnic_wq *)tx_queue; struct enic *enic = vnic_dev_priv(wq->vdev); unsigned short vlan_id; unsigned short ol_flags; for (index = 0; index < nb_pkts; index++) { tx_pkt = *tx_pkts++; inc_len = 0; nb_segs = tx_pkt->nb_segs; if (nb_segs > vnic_wq_desc_avail(wq)) { /* wq cleanup and try again */ if (!enic_cleanup_wq(enic, wq) || (nb_segs > vnic_wq_desc_avail(wq))) return index; } pkt_len = tx_pkt->pkt_len; vlan_id = tx_pkt->vlan_tci; ol_flags = tx_pkt->ol_flags; for (frags = 0; inc_len < pkt_len; frags++) { if (!tx_pkt) break; seg_len = tx_pkt->data_len; inc_len += seg_len; if (enic_send_pkt(enic, wq, tx_pkt, (unsigned short)seg_len, !frags, (pkt_len == inc_len), ol_flags, vlan_id)) { break; } tx_pkt = tx_pkt->next; } } enic_cleanup_wq(enic, wq); return index; } static uint16_t enicpmd_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct vnic_rq *rq = (struct vnic_rq *)rx_queue; unsigned int work_done; if (enic_poll(rq, rx_pkts, (unsigned int)nb_pkts, &work_done)) dev_err(enic, "error in enicpmd poll\n"); return work_done; } static const struct eth_dev_ops enicpmd_eth_dev_ops = { .dev_configure = enicpmd_dev_configure, .dev_start = enicpmd_dev_start, .dev_stop = enicpmd_dev_stop, .dev_set_link_up = NULL, .dev_set_link_down = NULL, .dev_close = enicpmd_dev_close, .promiscuous_enable = enicpmd_dev_promiscuous_enable, .promiscuous_disable = enicpmd_dev_promiscuous_disable, .allmulticast_enable = enicpmd_dev_allmulticast_enable, .allmulticast_disable = enicpmd_dev_allmulticast_disable, .link_update = enicpmd_dev_link_update, .stats_get = enicpmd_dev_stats_get, .stats_reset = enicpmd_dev_stats_reset, .queue_stats_mapping_set = NULL, .dev_infos_get = enicpmd_dev_info_get, .mtu_set = NULL, .vlan_filter_set = enicpmd_vlan_filter_set, .vlan_tpid_set = NULL, .vlan_offload_set = enicpmd_vlan_offload_set, .vlan_strip_queue_set = NULL, .rx_queue_start = enicpmd_dev_rx_queue_start, .rx_queue_stop = enicpmd_dev_rx_queue_stop, .tx_queue_start = enicpmd_dev_tx_queue_start, .tx_queue_stop = enicpmd_dev_tx_queue_stop, .rx_queue_setup = enicpmd_dev_rx_queue_setup, .rx_queue_release = enicpmd_dev_rx_queue_release, .rx_queue_count = NULL, .rx_descriptor_done = NULL, .tx_queue_setup = enicpmd_dev_tx_queue_setup, .tx_queue_release = enicpmd_dev_tx_queue_release, .dev_led_on = NULL, .dev_led_off = NULL, .flow_ctrl_get = NULL, .flow_ctrl_set = NULL, .priority_flow_ctrl_set = NULL, .mac_addr_add = enicpmd_add_mac_addr, .mac_addr_remove = enicpmd_remove_mac_addr, .fdir_set_masks = NULL, .filter_ctrl = enicpmd_dev_filter_ctrl, }; struct enic *enicpmd_list_head = NULL; /* Initialize the driver * It returns 0 on success. */ static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pdev; struct rte_pci_addr *addr; struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); enic->port_id = eth_dev->data->port_id; enic->rte_dev = eth_dev; eth_dev->dev_ops = &enicpmd_eth_dev_ops; eth_dev->rx_pkt_burst = &enicpmd_recv_pkts; eth_dev->tx_pkt_burst = &enicpmd_xmit_pkts; pdev = eth_dev->pci_dev; enic->pdev = pdev; addr = &pdev->addr; snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x", addr->domain, addr->bus, addr->devid, addr->function); return enic_probe(enic); } static struct eth_driver rte_enic_pmd = { .pci_drv = { .name = "rte_enic_pmd", .id_table = pci_id_enic_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING, }, .eth_dev_init = eth_enicpmd_dev_init, .dev_private_size = sizeof(struct enic), }; /* Driver initialization routine. * Invoked once at EAL init time. * Register as the [Poll Mode] Driver of Cisco ENIC device. */ static int rte_enic_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { ENICPMD_FUNC_TRACE(); rte_eth_driver_register(&rte_enic_pmd); return 0; } static struct rte_driver rte_enic_driver = { .type = PMD_PDEV, .init = rte_enic_pmd_init, }; PMD_REGISTER_DRIVER(rte_enic_driver); ================================================ FILE: drivers/net/enic/enic_main.c ================================================ /* * Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id$" #include #include #include #include #include #include #include #include #include #include #include #include "enic_compat.h" #include "enic.h" #include "wq_enet_desc.h" #include "rq_enet_desc.h" #include "cq_enet_desc.h" #include "vnic_enet.h" #include "vnic_dev.h" #include "vnic_wq.h" #include "vnic_rq.h" #include "vnic_cq.h" #include "vnic_intr.h" #include "vnic_nic.h" static inline int enic_is_sriov_vf(struct enic *enic) { return enic->pdev->id.device_id == PCI_DEVICE_ID_CISCO_VIC_ENET_VF; } static int is_zero_addr(uint8_t *addr) { return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); } static int is_mcast_addr(uint8_t *addr) { return addr[0] & 1; } static int is_eth_addr_valid(uint8_t *addr) { return !is_mcast_addr(addr) && !is_zero_addr(addr); } static inline struct rte_mbuf * enic_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return m; } void enic_set_hdr_split_size(struct enic *enic, u16 split_hdr_size) { vnic_set_hdr_split_size(enic->vdev, split_hdr_size); } static void enic_free_wq_buf(__rte_unused struct vnic_wq *wq, struct vnic_wq_buf *buf) { struct rte_mbuf *mbuf = (struct rte_mbuf *)buf->os_buf; rte_mempool_put(mbuf->pool, mbuf); buf->os_buf = NULL; } static void enic_wq_free_buf(struct vnic_wq *wq, __rte_unused struct cq_desc *cq_desc, struct vnic_wq_buf *buf, __rte_unused void *opaque) { enic_free_wq_buf(wq, buf); } static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, __rte_unused u8 type, u16 q_number, u16 completed_index, void *opaque) { struct enic *enic = vnic_dev_priv(vdev); vnic_wq_service(&enic->wq[q_number], cq_desc, completed_index, enic_wq_free_buf, opaque); return 0; } static void enic_log_q_error(struct enic *enic) { unsigned int i; u32 error_status; for (i = 0; i < enic->wq_count; i++) { error_status = vnic_wq_error_status(&enic->wq[i]); if (error_status) dev_err(enic, "WQ[%d] error_status %d\n", i, error_status); } for (i = 0; i < enic->rq_count; i++) { error_status = vnic_rq_error_status(&enic->rq[i]); if (error_status) dev_err(enic, "RQ[%d] error_status %d\n", i, error_status); } } unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq) { unsigned int cq = enic_cq_wq(enic, wq->index); /* Return the work done */ return vnic_cq_service(&enic->cq[cq], -1 /*wq_work_to_do*/, enic_wq_service, NULL); } int enic_send_pkt(struct enic *enic, struct vnic_wq *wq, struct rte_mbuf *tx_pkt, unsigned short len, uint8_t sop, uint8_t eop, uint16_t ol_flags, uint16_t vlan_tag) { struct wq_enet_desc *desc = vnic_wq_next_desc(wq); uint16_t mss = 0; uint8_t cq_entry = eop; uint8_t vlan_tag_insert = 0; uint64_t bus_addr = (dma_addr_t) (tx_pkt->buf_physaddr + RTE_PKTMBUF_HEADROOM); if (sop) { if (ol_flags & PKT_TX_VLAN_PKT) vlan_tag_insert = 1; if (enic->hw_ip_checksum) { if (ol_flags & PKT_TX_IP_CKSUM) mss |= ENIC_CALC_IP_CKSUM; if (ol_flags & PKT_TX_TCP_UDP_CKSUM) mss |= ENIC_CALC_TCP_UDP_CKSUM; } } wq_enet_desc_enc(desc, bus_addr, len, mss, 0 /* header_length */, 0 /* offload_mode WQ_ENET_OFFLOAD_MODE_CSUM */, eop, cq_entry, 0 /* fcoe_encap */, vlan_tag_insert, vlan_tag, 0 /* loopback */); vnic_wq_post(wq, (void *)tx_pkt, bus_addr, len, sop, eop, 1 /*desc_skip_cnt*/, cq_entry, 0 /*compressed send*/, 0 /*wrid*/); return 0; } void enic_dev_stats_clear(struct enic *enic) { if (vnic_dev_stats_clear(enic->vdev)) dev_err(enic, "Error in clearing stats\n"); } void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats) { struct vnic_stats *stats; if (vnic_dev_stats_dump(enic->vdev, &stats)) { dev_err(enic, "Error in getting stats\n"); return; } r_stats->ipackets = stats->rx.rx_frames_ok; r_stats->opackets = stats->tx.tx_frames_ok; r_stats->ibytes = stats->rx.rx_bytes_ok; r_stats->obytes = stats->tx.tx_bytes_ok; r_stats->ierrors = stats->rx.rx_errors; r_stats->oerrors = stats->tx.tx_errors; r_stats->imcasts = stats->rx.rx_multicast_frames_ok; r_stats->rx_nombuf = stats->rx.rx_no_bufs; } void enic_del_mac_address(struct enic *enic) { if (vnic_dev_del_addr(enic->vdev, enic->mac_addr)) dev_err(enic, "del mac addr failed\n"); } void enic_set_mac_address(struct enic *enic, uint8_t *mac_addr) { int err; if (!is_eth_addr_valid(mac_addr)) { dev_err(enic, "invalid mac address\n"); return; } err = vnic_dev_del_addr(enic->vdev, mac_addr); if (err) { dev_err(enic, "del mac addr failed\n"); return; } ether_addr_copy((struct ether_addr *)mac_addr, (struct ether_addr *)enic->mac_addr); err = vnic_dev_add_addr(enic->vdev, mac_addr); if (err) { dev_err(enic, "add mac addr failed\n"); return; } } static void enic_free_rq_buf(__rte_unused struct vnic_rq *rq, struct vnic_rq_buf *buf) { if (!buf->os_buf) return; rte_pktmbuf_free((struct rte_mbuf *)buf->os_buf); buf->os_buf = NULL; } void enic_init_vnic_resources(struct enic *enic) { unsigned int error_interrupt_enable = 1; unsigned int error_interrupt_offset = 0; unsigned int index = 0; for (index = 0; index < enic->rq_count; index++) { vnic_rq_init(&enic->rq[index], enic_cq_rq(enic, index), error_interrupt_enable, error_interrupt_offset); } for (index = 0; index < enic->wq_count; index++) { vnic_wq_init(&enic->wq[index], enic_cq_wq(enic, index), error_interrupt_enable, error_interrupt_offset); } vnic_dev_stats_clear(enic->vdev); for (index = 0; index < enic->cq_count; index++) { vnic_cq_init(&enic->cq[index], 0 /* flow_control_enable */, 1 /* color_enable */, 0 /* cq_head */, 0 /* cq_tail */, 1 /* cq_tail_color */, 0 /* interrupt_enable */, 1 /* cq_entry_enable */, 0 /* cq_message_enable */, 0 /* interrupt offset */, 0 /* cq_message_addr */); } vnic_intr_init(&enic->intr, enic->config.intr_timer_usec, enic->config.intr_timer_type, /*mask_on_assertion*/1); } static int enic_rq_alloc_buf(struct vnic_rq *rq) { struct enic *enic = vnic_dev_priv(rq->vdev); dma_addr_t dma_addr; struct rq_enet_desc *desc = vnic_rq_next_desc(rq); uint8_t type = RQ_ENET_TYPE_ONLY_SOP; u16 split_hdr_size = vnic_get_hdr_split_size(enic->vdev); struct rte_mbuf *mbuf = enic_rxmbuf_alloc(rq->mp); struct rte_mbuf *hdr_mbuf = NULL; if (!mbuf) { dev_err(enic, "mbuf alloc in enic_rq_alloc_buf failed\n"); return -1; } if (unlikely(split_hdr_size)) { if (vnic_rq_desc_avail(rq) < 2) { rte_mempool_put(mbuf->pool, mbuf); return -1; } hdr_mbuf = enic_rxmbuf_alloc(rq->mp); if (!hdr_mbuf) { rte_mempool_put(mbuf->pool, mbuf); dev_err(enic, "hdr_mbuf alloc in enic_rq_alloc_buf failed\n"); return -1; } hdr_mbuf->data_off = RTE_PKTMBUF_HEADROOM; hdr_mbuf->nb_segs = 2; hdr_mbuf->port = enic->port_id; hdr_mbuf->next = mbuf; dma_addr = (dma_addr_t) (hdr_mbuf->buf_physaddr + hdr_mbuf->data_off); rq_enet_desc_enc(desc, dma_addr, type, split_hdr_size); vnic_rq_post(rq, (void *)hdr_mbuf, 0 /*os_buf_index*/, dma_addr, (unsigned int)split_hdr_size, 0 /*wrid*/); desc = vnic_rq_next_desc(rq); type = RQ_ENET_TYPE_NOT_SOP; } else { mbuf->nb_segs = 1; mbuf->port = enic->port_id; } mbuf->data_off = RTE_PKTMBUF_HEADROOM; mbuf->next = NULL; dma_addr = (dma_addr_t) (mbuf->buf_physaddr + mbuf->data_off); rq_enet_desc_enc(desc, dma_addr, type, mbuf->buf_len); vnic_rq_post(rq, (void *)mbuf, 0 /*os_buf_index*/, dma_addr, (unsigned int)mbuf->buf_len, 0 /*wrid*/); return 0; } static int enic_rq_indicate_buf(struct vnic_rq *rq, struct cq_desc *cq_desc, struct vnic_rq_buf *buf, int skipped, void *opaque) { struct enic *enic = vnic_dev_priv(rq->vdev); struct rte_mbuf **rx_pkt_bucket = (struct rte_mbuf **)opaque; struct rte_mbuf *rx_pkt = NULL; struct rte_mbuf *hdr_rx_pkt = NULL; u8 type, color, eop, sop, ingress_port, vlan_stripped; u8 fcoe, fcoe_sof, fcoe_fc_crc_ok, fcoe_enc_error, fcoe_eof; u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok; u8 ipv6, ipv4, ipv4_fragment, fcs_ok, rss_type, csum_not_calc; u8 packet_error; u16 q_number, completed_index, bytes_written, vlan_tci, checksum; u32 rss_hash; cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc, &type, &color, &q_number, &completed_index, &ingress_port, &fcoe, &eop, &sop, &rss_type, &csum_not_calc, &rss_hash, &bytes_written, &packet_error, &vlan_stripped, &vlan_tci, &checksum, &fcoe_sof, &fcoe_fc_crc_ok, &fcoe_enc_error, &fcoe_eof, &tcp_udp_csum_ok, &udp, &tcp, &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment, &fcs_ok); rx_pkt = (struct rte_mbuf *)buf->os_buf; buf->os_buf = NULL; if (unlikely(packet_error)) { dev_err(enic, "packet error\n"); rx_pkt->data_len = 0; return 0; } if (unlikely(skipped)) { rx_pkt->data_len = 0; return 0; } if (likely(!vnic_get_hdr_split_size(enic->vdev))) { /* No header split configured */ *rx_pkt_bucket = rx_pkt; rx_pkt->pkt_len = bytes_written; if (ipv4) { #ifdef RTE_NEXT_ABI rx_pkt->packet_type = RTE_PTYPE_L3_IPV4; #else rx_pkt->ol_flags |= PKT_RX_IPV4_HDR; #endif if (!csum_not_calc) { if (unlikely(!ipv4_csum_ok)) rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((tcp || udp) && (!tcp_udp_csum_ok)) rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD; } } else if (ipv6) #ifdef RTE_NEXT_ABI rx_pkt->packet_type = RTE_PTYPE_L3_IPV6; #else rx_pkt->ol_flags |= PKT_RX_IPV6_HDR; #endif } else { /* Header split */ if (sop && !eop) { /* This piece is header */ *rx_pkt_bucket = rx_pkt; rx_pkt->pkt_len = bytes_written; } else { if (sop && eop) { /* The packet is smaller than split_hdr_size */ *rx_pkt_bucket = rx_pkt; rx_pkt->pkt_len = bytes_written; if (ipv4) { #ifdef RTE_NEXT_ABI rx_pkt->packet_type = RTE_PTYPE_L3_IPV4; #else rx_pkt->ol_flags |= PKT_RX_IPV4_HDR; #endif if (!csum_not_calc) { if (unlikely(!ipv4_csum_ok)) rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((tcp || udp) && (!tcp_udp_csum_ok)) rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD; } } else if (ipv6) #ifdef RTE_NEXT_ABI rx_pkt->packet_type = RTE_PTYPE_L3_IPV6; #else rx_pkt->ol_flags |= PKT_RX_IPV6_HDR; #endif } else { /* Payload */ hdr_rx_pkt = *rx_pkt_bucket; hdr_rx_pkt->pkt_len += bytes_written; if (ipv4) { #ifdef RTE_NEXT_ABI hdr_rx_pkt->packet_type = RTE_PTYPE_L3_IPV4; #else hdr_rx_pkt->ol_flags |= PKT_RX_IPV4_HDR; #endif if (!csum_not_calc) { if (unlikely(!ipv4_csum_ok)) hdr_rx_pkt->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((tcp || udp) && (!tcp_udp_csum_ok)) hdr_rx_pkt->ol_flags |= PKT_RX_L4_CKSUM_BAD; } } else if (ipv6) #ifdef RTE_NEXT_ABI hdr_rx_pkt->packet_type = RTE_PTYPE_L3_IPV6; #else hdr_rx_pkt->ol_flags |= PKT_RX_IPV6_HDR; #endif } } } rx_pkt->data_len = bytes_written; if (rss_hash) { rx_pkt->ol_flags |= PKT_RX_RSS_HASH; rx_pkt->hash.rss = rss_hash; } if (vlan_tci) { rx_pkt->ol_flags |= PKT_RX_VLAN_PKT; rx_pkt->vlan_tci = vlan_tci; } return eop; } static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, __rte_unused u8 type, u16 q_number, u16 completed_index, void *opaque) { struct enic *enic = vnic_dev_priv(vdev); return vnic_rq_service(&enic->rq[q_number], cq_desc, completed_index, VNIC_RQ_RETURN_DESC, enic_rq_indicate_buf, opaque); } int enic_poll(struct vnic_rq *rq, struct rte_mbuf **rx_pkts, unsigned int budget, unsigned int *work_done) { struct enic *enic = vnic_dev_priv(rq->vdev); unsigned int cq = enic_cq_rq(enic, rq->index); int err = 0; *work_done = vnic_cq_service(&enic->cq[cq], budget, enic_rq_service, (void *)rx_pkts); if (*work_done) { vnic_rq_fill(rq, enic_rq_alloc_buf); /* Need at least one buffer on ring to get going */ if (vnic_rq_desc_used(rq) == 0) { dev_err(enic, "Unable to alloc receive buffers\n"); err = -1; } } return err; } static void * enic_alloc_consistent(__rte_unused void *priv, size_t size, dma_addr_t *dma_handle, u8 *name) { void *vaddr; const struct rte_memzone *rz; *dma_handle = 0; rz = rte_memzone_reserve_aligned((const char *)name, size, 0, 0, ENIC_ALIGN); if (!rz) { pr_err("%s : Failed to allocate memory requested for %s", __func__, name); return NULL; } vaddr = rz->addr; *dma_handle = (dma_addr_t)rz->phys_addr; return vaddr; } static void enic_free_consistent(__rte_unused struct rte_pci_device *hwdev, __rte_unused size_t size, __rte_unused void *vaddr, __rte_unused dma_addr_t dma_handle) { /* Nothing to be done */ } static void enic_intr_handler(__rte_unused struct rte_intr_handle *handle, void *arg) { struct enic *enic = pmd_priv((struct rte_eth_dev *)arg); vnic_intr_return_all_credits(&enic->intr); enic_log_q_error(enic); } int enic_enable(struct enic *enic) { unsigned int index; struct rte_eth_dev *eth_dev = enic->rte_dev; eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */ if (enic_clsf_init(enic)) dev_warning(enic, "Init of hash table for clsf failed."\ "Flow director feature will not work\n"); /* Fill RQ bufs */ for (index = 0; index < enic->rq_count; index++) { vnic_rq_fill(&enic->rq[index], enic_rq_alloc_buf); /* Need at least one buffer on ring to get going */ if (vnic_rq_desc_used(&enic->rq[index]) == 0) { dev_err(enic, "Unable to alloc receive buffers\n"); return -1; } } for (index = 0; index < enic->wq_count; index++) vnic_wq_enable(&enic->wq[index]); for (index = 0; index < enic->rq_count; index++) vnic_rq_enable(&enic->rq[index]); vnic_dev_enable_wait(enic->vdev); /* Register and enable error interrupt */ rte_intr_callback_register(&(enic->pdev->intr_handle), enic_intr_handler, (void *)enic->rte_dev); rte_intr_enable(&(enic->pdev->intr_handle)); vnic_intr_unmask(&enic->intr); return 0; } int enic_alloc_intr_resources(struct enic *enic) { int err; dev_info(enic, "vNIC resources used: "\ "wq %d rq %d cq %d intr %d\n", enic->wq_count, enic->rq_count, enic->cq_count, enic->intr_count); err = vnic_intr_alloc(enic->vdev, &enic->intr, 0); if (err) enic_free_vnic_resources(enic); return err; } void enic_free_rq(void *rxq) { struct vnic_rq *rq = (struct vnic_rq *)rxq; struct enic *enic = vnic_dev_priv(rq->vdev); vnic_rq_free(rq); vnic_cq_free(&enic->cq[rq->index]); } void enic_start_wq(struct enic *enic, uint16_t queue_idx) { vnic_wq_enable(&enic->wq[queue_idx]); } int enic_stop_wq(struct enic *enic, uint16_t queue_idx) { return vnic_wq_disable(&enic->wq[queue_idx]); } void enic_start_rq(struct enic *enic, uint16_t queue_idx) { vnic_rq_enable(&enic->rq[queue_idx]); } int enic_stop_rq(struct enic *enic, uint16_t queue_idx) { return vnic_rq_disable(&enic->rq[queue_idx]); } int enic_alloc_rq(struct enic *enic, uint16_t queue_idx, unsigned int socket_id, struct rte_mempool *mp, uint16_t nb_desc) { int err; struct vnic_rq *rq = &enic->rq[queue_idx]; rq->socket_id = socket_id; rq->mp = mp; if (nb_desc) { if (nb_desc > enic->config.rq_desc_count) { dev_warning(enic, "RQ %d - number of rx desc in cmd line (%d)"\ "is greater than that in the UCSM/CIMC adapter"\ "policy. Applying the value in the adapter "\ "policy (%d).\n", queue_idx, nb_desc, enic->config.rq_desc_count); } else if (nb_desc != enic->config.rq_desc_count) { enic->config.rq_desc_count = nb_desc; dev_info(enic, "RX Queues - effective number of descs:%d\n", nb_desc); } } /* Allocate queue resources */ err = vnic_rq_alloc(enic->vdev, &enic->rq[queue_idx], queue_idx, enic->config.rq_desc_count, sizeof(struct rq_enet_desc)); if (err) { dev_err(enic, "error in allocation of rq\n"); return err; } err = vnic_cq_alloc(enic->vdev, &enic->cq[queue_idx], queue_idx, socket_id, enic->config.rq_desc_count, sizeof(struct cq_enet_rq_desc)); if (err) { vnic_rq_free(rq); dev_err(enic, "error in allocation of cq for rq\n"); } return err; } void enic_free_wq(void *txq) { struct vnic_wq *wq = (struct vnic_wq *)txq; struct enic *enic = vnic_dev_priv(wq->vdev); vnic_wq_free(wq); vnic_cq_free(&enic->cq[enic->rq_count + wq->index]); } int enic_alloc_wq(struct enic *enic, uint16_t queue_idx, unsigned int socket_id, uint16_t nb_desc) { int err; struct vnic_wq *wq = &enic->wq[queue_idx]; unsigned int cq_index = enic_cq_wq(enic, queue_idx); wq->socket_id = socket_id; if (nb_desc) { if (nb_desc > enic->config.wq_desc_count) { dev_warning(enic, "WQ %d - number of tx desc in cmd line (%d)"\ "is greater than that in the UCSM/CIMC adapter"\ "policy. Applying the value in the adapter "\ "policy (%d)\n", queue_idx, nb_desc, enic->config.wq_desc_count); } else if (nb_desc != enic->config.wq_desc_count) { enic->config.wq_desc_count = nb_desc; dev_info(enic, "TX Queues - effective number of descs:%d\n", nb_desc); } } /* Allocate queue resources */ err = vnic_wq_alloc(enic->vdev, &enic->wq[queue_idx], queue_idx, enic->config.wq_desc_count, sizeof(struct wq_enet_desc)); if (err) { dev_err(enic, "error in allocation of wq\n"); return err; } err = vnic_cq_alloc(enic->vdev, &enic->cq[cq_index], cq_index, socket_id, enic->config.wq_desc_count, sizeof(struct cq_enet_wq_desc)); if (err) { vnic_wq_free(wq); dev_err(enic, "error in allocation of cq for wq\n"); } return err; } int enic_disable(struct enic *enic) { unsigned int i; int err; vnic_intr_mask(&enic->intr); (void)vnic_intr_masked(&enic->intr); /* flush write */ vnic_dev_disable(enic->vdev); enic_clsf_destroy(enic); if (!enic_is_sriov_vf(enic)) vnic_dev_del_addr(enic->vdev, enic->mac_addr); for (i = 0; i < enic->wq_count; i++) { err = vnic_wq_disable(&enic->wq[i]); if (err) return err; } for (i = 0; i < enic->rq_count; i++) { err = vnic_rq_disable(&enic->rq[i]); if (err) return err; } vnic_dev_set_reset_flag(enic->vdev, 1); vnic_dev_notify_unset(enic->vdev); for (i = 0; i < enic->wq_count; i++) vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); for (i = 0; i < enic->rq_count; i++) vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); for (i = 0; i < enic->cq_count; i++) vnic_cq_clean(&enic->cq[i]); vnic_intr_clean(&enic->intr); return 0; } static int enic_dev_wait(struct vnic_dev *vdev, int (*start)(struct vnic_dev *, int), int (*finished)(struct vnic_dev *, int *), int arg) { int done; int err; int i; err = start(vdev, arg); if (err) return err; /* Wait for func to complete...2 seconds max */ for (i = 0; i < 2000; i++) { err = finished(vdev, &done); if (err) return err; if (done) return 0; usleep(1000); } return -ETIMEDOUT; } static int enic_dev_open(struct enic *enic) { int err; err = enic_dev_wait(enic->vdev, vnic_dev_open, vnic_dev_open_done, 0); if (err) dev_err(enic_get_dev(enic), "vNIC device open failed, err %d\n", err); return err; } static int enic_set_rsskey(struct enic *enic) { dma_addr_t rss_key_buf_pa; union vnic_rss_key *rss_key_buf_va = NULL; static union vnic_rss_key rss_key = { .key = { [0] = {.b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}}, [1] = {.b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101}}, [2] = {.b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115}}, [3] = {.b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108}}, } }; int err; u8 name[NAME_MAX]; snprintf((char *)name, NAME_MAX, "rss_key-%s", enic->bdf_name); rss_key_buf_va = enic_alloc_consistent(enic, sizeof(union vnic_rss_key), &rss_key_buf_pa, name); if (!rss_key_buf_va) return -ENOMEM; rte_memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key)); err = enic_set_rss_key(enic, rss_key_buf_pa, sizeof(union vnic_rss_key)); enic_free_consistent(enic->pdev, sizeof(union vnic_rss_key), rss_key_buf_va, rss_key_buf_pa); return err; } static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) { dma_addr_t rss_cpu_buf_pa; union vnic_rss_cpu *rss_cpu_buf_va = NULL; int i; int err; u8 name[NAME_MAX]; snprintf((char *)name, NAME_MAX, "rss_cpu-%s", enic->bdf_name); rss_cpu_buf_va = enic_alloc_consistent(enic, sizeof(union vnic_rss_cpu), &rss_cpu_buf_pa, name); if (!rss_cpu_buf_va) return -ENOMEM; for (i = 0; i < (1 << rss_hash_bits); i++) (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; err = enic_set_rss_cpu(enic, rss_cpu_buf_pa, sizeof(union vnic_rss_cpu)); enic_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu), rss_cpu_buf_va, rss_cpu_buf_pa); return err; } static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable) { const u8 tso_ipid_split_en = 0; int err; /* Enable VLAN tag stripping */ err = enic_set_nic_cfg(enic, rss_default_cpu, rss_hash_type, rss_hash_bits, rss_base_cpu, rss_enable, tso_ipid_split_en, enic->ig_vlan_strip_en); return err; } int enic_set_rss_nic_cfg(struct enic *enic) { const u8 rss_default_cpu = 0; const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 | NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 | NIC_CFG_RSS_HASH_TYPE_IPV6 | NIC_CFG_RSS_HASH_TYPE_TCP_IPV6; const u8 rss_hash_bits = 7; const u8 rss_base_cpu = 0; u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1); if (rss_enable) { if (!enic_set_rsskey(enic)) { if (enic_set_rsscpu(enic, rss_hash_bits)) { rss_enable = 0; dev_warning(enic, "RSS disabled, "\ "Failed to set RSS cpu indirection table."); } } else { rss_enable = 0; dev_warning(enic, "RSS disabled, Failed to set RSS key.\n"); } } return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type, rss_hash_bits, rss_base_cpu, rss_enable); } int enic_setup_finish(struct enic *enic) { int ret; ret = enic_set_rss_nic_cfg(enic); if (ret) { dev_err(enic, "Failed to config nic, aborting.\n"); return -1; } vnic_dev_add_addr(enic->vdev, enic->mac_addr); /* Default conf */ vnic_dev_packet_filter(enic->vdev, 1 /* directed */, 1 /* multicast */, 1 /* broadcast */, 0 /* promisc */, 1 /* allmulti */); enic->promisc = 0; enic->allmulti = 1; return 0; } void enic_add_packet_filter(struct enic *enic) { /* Args -> directed, multicast, broadcast, promisc, allmulti */ vnic_dev_packet_filter(enic->vdev, 1, 1, 1, enic->promisc, enic->allmulti); } int enic_get_link_status(struct enic *enic) { return vnic_dev_link_status(enic->vdev); } static void enic_dev_deinit(struct enic *enic) { struct rte_eth_dev *eth_dev = enic->rte_dev; rte_free(eth_dev->data->mac_addrs); } int enic_set_vnic_res(struct enic *enic) { struct rte_eth_dev *eth_dev = enic->rte_dev; if ((enic->rq_count < eth_dev->data->nb_rx_queues) || (enic->wq_count < eth_dev->data->nb_tx_queues)) { dev_err(dev, "Not enough resources configured, aborting\n"); return -1; } enic->rq_count = eth_dev->data->nb_rx_queues; enic->wq_count = eth_dev->data->nb_tx_queues; if (enic->cq_count < (enic->rq_count + enic->wq_count)) { dev_err(dev, "Not enough resources configured, aborting\n"); return -1; } enic->cq_count = enic->rq_count + enic->wq_count; return 0; } static int enic_dev_init(struct enic *enic) { int err; struct rte_eth_dev *eth_dev = enic->rte_dev; vnic_dev_intr_coal_timer_info_default(enic->vdev); /* Get vNIC configuration */ err = enic_get_vnic_config(enic); if (err) { dev_err(dev, "Get vNIC configuration failed, aborting\n"); return err; } eth_dev->data->mac_addrs = rte_zmalloc("enic_mac_addr", ETH_ALEN, 0); if (!eth_dev->data->mac_addrs) { dev_err(enic, "mac addr storage alloc failed, aborting.\n"); return -1; } ether_addr_copy((struct ether_addr *) enic->mac_addr, ð_dev->data->mac_addrs[0]); /* Get available resource counts */ enic_get_res_counts(enic); vnic_dev_set_reset_flag(enic->vdev, 0); return 0; } int enic_probe(struct enic *enic) { struct rte_pci_device *pdev = enic->pdev; int err = -1; dev_debug(enic, " Initializing ENIC PMD version %s\n", DRV_VERSION); enic->bar0.vaddr = (void *)pdev->mem_resource[0].addr; enic->bar0.len = pdev->mem_resource[0].len; /* Register vNIC device */ enic->vdev = vnic_dev_register(NULL, enic, enic->pdev, &enic->bar0, 1); if (!enic->vdev) { dev_err(enic, "vNIC registration failed, aborting\n"); goto err_out; } vnic_register_cbacks(enic->vdev, enic_alloc_consistent, enic_free_consistent); /* Issue device open to get device in known state */ err = enic_dev_open(enic); if (err) { dev_err(enic, "vNIC dev open failed, aborting\n"); goto err_out_unregister; } /* Set ingress vlan rewrite mode before vnic initialization */ err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev, IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN); if (err) { dev_err(enic, "Failed to set ingress vlan rewrite mode, aborting.\n"); goto err_out_dev_close; } /* Issue device init to initialize the vnic-to-switch link. * We'll start with carrier off and wait for link UP * notification later to turn on carrier. We don't need * to wait here for the vnic-to-switch link initialization * to complete; link UP notification is the indication that * the process is complete. */ err = vnic_dev_init(enic->vdev, 0); if (err) { dev_err(enic, "vNIC dev init failed, aborting\n"); goto err_out_dev_close; } err = enic_dev_init(enic); if (err) { dev_err(enic, "Device initialization failed, aborting\n"); goto err_out_dev_close; } return 0; err_out_dev_close: vnic_dev_close(enic->vdev); err_out_unregister: vnic_dev_unregister(enic->vdev); err_out: return err; } void enic_remove(struct enic *enic) { enic_dev_deinit(enic); vnic_dev_close(enic->vdev); vnic_dev_unregister(enic->vdev); } ================================================ FILE: drivers/net/enic/enic_res.c ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: enic_res.c 171146 2014-05-02 07:08:20Z ssujith $" #include "enic_compat.h" #include "rte_ethdev.h" #include "wq_enet_desc.h" #include "rq_enet_desc.h" #include "cq_enet_desc.h" #include "vnic_resource.h" #include "vnic_enet.h" #include "vnic_dev.h" #include "vnic_wq.h" #include "vnic_rq.h" #include "vnic_cq.h" #include "vnic_intr.h" #include "vnic_stats.h" #include "vnic_nic.h" #include "vnic_rss.h" #include "enic_res.h" #include "enic.h" int enic_get_vnic_config(struct enic *enic) { struct vnic_enet_config *c = &enic->config; int err; err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr); if (err) { dev_err(enic_get_dev(enic), "Error getting MAC addr, %d\n", err); return err; } #define GET_CONFIG(m) \ do { \ err = vnic_dev_spec(enic->vdev, \ offsetof(struct vnic_enet_config, m), \ sizeof(c->m), &c->m); \ if (err) { \ dev_err(enic_get_dev(enic), \ "Error getting %s, %d\n", #m, err); \ return err; \ } \ } while (0) GET_CONFIG(flags); GET_CONFIG(wq_desc_count); GET_CONFIG(rq_desc_count); GET_CONFIG(mtu); GET_CONFIG(intr_timer_type); GET_CONFIG(intr_mode); GET_CONFIG(intr_timer_usec); GET_CONFIG(loop_tag); GET_CONFIG(num_arfs); c->wq_desc_count = min_t(u32, ENIC_MAX_WQ_DESCS, max_t(u32, ENIC_MIN_WQ_DESCS, c->wq_desc_count)); c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ c->rq_desc_count = min_t(u32, ENIC_MAX_RQ_DESCS, max_t(u32, ENIC_MIN_RQ_DESCS, c->rq_desc_count)); c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ if (c->mtu == 0) c->mtu = 1500; c->mtu = min_t(u16, ENIC_MAX_MTU, max_t(u16, ENIC_MIN_MTU, c->mtu)); c->intr_timer_usec = min_t(u32, c->intr_timer_usec, vnic_dev_get_intr_coal_timer_max(enic->vdev)); dev_info(enic_get_dev(enic), "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x " "wq/rq %d/%d mtu %d\n", enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2], enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5], c->wq_desc_count, c->rq_desc_count, c->mtu); dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s " "rss %s intr mode %s type %s timer %d usec " "loopback tag 0x%04x\n", ENIC_SETTING(enic, TXCSUM) ? "yes" : "no", ENIC_SETTING(enic, RXCSUM) ? "yes" : "no", ENIC_SETTING(enic, RSS) ? "yes" : "no", c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" : c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" : c->intr_mode == VENET_INTR_MODE_ANY ? "any" : "unknown", c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" : c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" : "unknown", c->intr_timer_usec, c->loop_tag); return 0; } int enic_add_vlan(struct enic *enic, u16 vlanid) { u64 a0 = vlanid, a1 = 0; int wait = 1000; int err; err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait); if (err) dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err); return err; } int enic_del_vlan(struct enic *enic, u16 vlanid) { u64 a0 = vlanid, a1 = 0; int wait = 1000; int err; err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait); if (err) dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err); return err; } int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, u8 ig_vlan_strip_en) { u64 a0, a1; u32 nic_cfg; int wait = 1000; vnic_set_nic_cfg(&nic_cfg, rss_default_cpu, rss_hash_type, rss_hash_bits, rss_base_cpu, rss_enable, tso_ipid_split_en, ig_vlan_strip_en); a0 = nic_cfg; a1 = 0; return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait); } int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len) { u64 a0 = (u64)key_pa, a1 = len; int wait = 1000; return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait); } int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len) { u64 a0 = (u64)cpu_pa, a1 = len; int wait = 1000; return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait); } void enic_free_vnic_resources(struct enic *enic) { unsigned int i; for (i = 0; i < enic->wq_count; i++) vnic_wq_free(&enic->wq[i]); for (i = 0; i < enic->rq_count; i++) vnic_rq_free(&enic->rq[i]); for (i = 0; i < enic->cq_count; i++) vnic_cq_free(&enic->cq[i]); vnic_intr_free(&enic->intr); } void enic_get_res_counts(struct enic *enic) { enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); enic->intr_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL); dev_info(enic_get_dev(enic), "vNIC resources avail: wq %d rq %d cq %d intr %d\n", enic->wq_count, enic->rq_count, enic->cq_count, enic->intr_count); } ================================================ FILE: drivers/net/enic/enic_res.h ================================================ /* * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. * Copyright 2007 Nuova Systems, Inc. All rights reserved. * * Copyright (c) 2014, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ident "$Id: enic_res.h 173137 2014-05-16 03:27:22Z sanpilla $" #ifndef _ENIC_RES_H_ #define _ENIC_RES_H_ #include "wq_enet_desc.h" #include "rq_enet_desc.h" #include "vnic_wq.h" #include "vnic_rq.h" #define ENIC_MIN_WQ_DESCS 64 #define ENIC_MAX_WQ_DESCS 4096 #define ENIC_MIN_RQ_DESCS 64 #define ENIC_MAX_RQ_DESCS 4096 #define ENIC_MIN_MTU 68 #define ENIC_MAX_MTU 9000 #define ENIC_MULTICAST_PERFECT_FILTERS 32 #define ENIC_UNICAST_PERFECT_FILTERS 32 #define ENIC_NON_TSO_MAX_DESC 16 #define ENIC_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, unsigned int mss_or_csum_offset, unsigned int hdr_len, int vlan_tag_insert, unsigned int vlan_tag, int offload_mode, int cq_entry, int sop, int eop, int loopback) { struct wq_enet_desc *desc = vnic_wq_next_desc(wq); u8 desc_skip_cnt = 1; u8 compressed_send = 0; u64 wrid = 0; wq_enet_desc_enc(desc, (u64)dma_addr | VNIC_PADDR_TARGET, (u16)len, (u16)mss_or_csum_offset, (u16)hdr_len, (u8)offload_mode, (u8)eop, (u8)cq_entry, 0, /* fcoe_encap */ (u8)vlan_tag_insert, (u16)vlan_tag, (u8)loopback); vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop, desc_skip_cnt, (u8)cq_entry, compressed_send, wrid); } static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, int eop, int loopback) { enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, 0, 0, 0, 0, 0, eop, 0 /* !SOP */, eop, loopback); } static inline void enic_queue_wq_desc(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, int vlan_tag_insert, unsigned int vlan_tag, int eop, int loopback) { enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, 0, 0, vlan_tag_insert, vlan_tag, WQ_ENET_OFFLOAD_MODE_CSUM, eop, 1 /* SOP */, eop, loopback); } static inline void enic_queue_wq_desc_csum(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, int ip_csum, int tcpudp_csum, int vlan_tag_insert, unsigned int vlan_tag, int eop, int loopback) { enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, (ip_csum ? 1 : 0) + (tcpudp_csum ? 2 : 0), 0, vlan_tag_insert, vlan_tag, WQ_ENET_OFFLOAD_MODE_CSUM, eop, 1 /* SOP */, eop, loopback); } static inline void enic_queue_wq_desc_csum_l4(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, unsigned int csum_offset, unsigned int hdr_len, int vlan_tag_insert, unsigned int vlan_tag, int eop, int loopback) { enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, csum_offset, hdr_len, vlan_tag_insert, vlan_tag, WQ_ENET_OFFLOAD_MODE_CSUM_L4, eop, 1 /* SOP */, eop, loopback); } static inline void enic_queue_wq_desc_tso(struct vnic_wq *wq, void *os_buf, dma_addr_t dma_addr, unsigned int len, unsigned int mss, unsigned int hdr_len, int vlan_tag_insert, unsigned int vlan_tag, int eop, int loopback) { enic_queue_wq_desc_ex(wq, os_buf, dma_addr, len, mss, hdr_len, vlan_tag_insert, vlan_tag, WQ_ENET_OFFLOAD_MODE_TSO, eop, 1 /* SOP */, eop, loopback); } static inline void enic_queue_rq_desc(struct vnic_rq *rq, void *os_buf, unsigned int os_buf_index, dma_addr_t dma_addr, unsigned int len) { struct rq_enet_desc *desc = vnic_rq_next_desc(rq); u64 wrid = 0; u8 type = os_buf_index ? RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP; rq_enet_desc_enc(desc, (u64)dma_addr | VNIC_PADDR_TARGET, type, (u16)len); vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len, wrid); } struct enic; int enic_get_vnic_config(struct enic *); int enic_add_vlan(struct enic *enic, u16 vlanid); int enic_del_vlan(struct enic *enic, u16 vlanid); int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, u8 ig_vlan_strip_en); int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len); int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len); void enic_get_res_counts(struct enic *enic); void enic_init_vnic_resources(struct enic *enic); int enic_alloc_vnic_resources(struct enic *); void enic_free_vnic_resources(struct enic *); #endif /* _ENIC_RES_H_ */ ================================================ FILE: drivers/net/fm10k/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2013-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_fm10k.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_fm10k_version.map LIBABIVER := 1 ifeq ($(CC), icc) # # CFLAGS for icc # CFLAGS_BASE_DRIVER = -wd174 -wd593 -wd869 -wd981 -wd2259 else ifeq ($(CC), clang) # ## CFLAGS for clang # CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args CFLAGS_BASE_DRIVER += -Wno-unused-variable CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers else # # CFLAGS for gcc # CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args CFLAGS_BASE_DRIVER += -Wno-unused-variable CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS += -Wno-deprecated CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable endif endif # # Add extra flags for base driver source files to disable warnings in them # BASE_DRIVER_OBJS=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(BASE_DRIVER_OBJS), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_pf.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_tlv.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_common.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_mbx.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_vf.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_api.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/fm10k/base/fm10k_api.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_api.h" #include "fm10k_common.h" /** * fm10k_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * vendor ID and device ID stored in the hw structure. **/ s32 fm10k_set_mac_type(struct fm10k_hw *hw) { s32 ret_val = FM10K_SUCCESS; DEBUGFUNC("fm10k_set_mac_type"); if (hw->vendor_id != FM10K_INTEL_VENDOR_ID) { ERROR_REPORT2(FM10K_ERROR_UNSUPPORTED, "Unsupported vendor id: %x\n", hw->vendor_id); return FM10K_ERR_DEVICE_NOT_SUPPORTED; } switch (hw->device_id) { case FM10K_DEV_ID_PF: hw->mac.type = fm10k_mac_pf; break; case FM10K_DEV_ID_VF: hw->mac.type = fm10k_mac_vf; break; default: ret_val = FM10K_ERR_DEVICE_NOT_SUPPORTED; ERROR_REPORT2(FM10K_ERROR_UNSUPPORTED, "Unsupported device id: %x\n", hw->device_id); break; } DEBUGOUT2("fm10k_set_mac_type found mac: %d, returns: %d\n", hw->mac.type, ret_val); return ret_val; } /** * fm10k_init_shared_code - Initialize the shared code * @hw: pointer to hardware structure * * This will assign function pointers and assign the MAC type and PHY code. * Does not touch the hardware. This function must be called prior to any * other function in the shared code. The fm10k_hw structure should be * memset to 0 prior to calling this function. The following fields in * hw structure should be filled in prior to calling this function: * hw_addr, back, device_id, vendor_id, subsystem_device_id, * subsystem_vendor_id, and revision_id **/ s32 fm10k_init_shared_code(struct fm10k_hw *hw) { s32 status; DEBUGFUNC("fm10k_init_shared_code"); /* Set the mac type */ fm10k_set_mac_type(hw); switch (hw->mac.type) { case fm10k_mac_pf: status = fm10k_init_ops_pf(hw); break; case fm10k_mac_vf: status = fm10k_init_ops_vf(hw); break; default: status = FM10K_ERR_DEVICE_NOT_SUPPORTED; break; } return status; } #define fm10k_call_func(hw, func, params, error) \ ((func) ? (func params) : (error)) /** * fm10k_reset_hw - Reset the hardware to known good state * @hw: pointer to hardware structure * * This function should return the hardware to a state similar to the * one it is in after being powered on. **/ s32 fm10k_reset_hw(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.reset_hw, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_init_hw - Initialize the hardware * @hw: pointer to hardware structure * * Initialize the hardware by resetting and then starting the hardware **/ s32 fm10k_init_hw(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.init_hw, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_stop_hw - Prepares hardware to shutdown Rx/Tx * @hw: pointer to hardware structure * * Disables Rx/Tx queues and disables the DMA engine. **/ s32 fm10k_stop_hw(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.stop_hw, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_start_hw - Prepares hardware for Rx/Tx * @hw: pointer to hardware structure * * This function sets the flags indicating that the hardware is ready to * begin operation. **/ s32 fm10k_start_hw(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.start_hw, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_get_bus_info - Set PCI bus info * @hw: pointer to hardware structure * * Sets the PCI bus info (speed, width, type) within the fm10k_hw structure **/ s32 fm10k_get_bus_info(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.get_bus_info, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_is_slot_appropriate - Indicate appropriate slot for this SKU * @hw: pointer to hardware structure * * Looks at the PCIe bus info to confirm whether or not this slot can support * the necessary bandwidth for this device. **/ bool fm10k_is_slot_appropriate(struct fm10k_hw *hw) { if (hw->mac.ops.is_slot_appropriate) return hw->mac.ops.is_slot_appropriate(hw); return true; } /** * fm10k_update_vlan - Clear VLAN ID to VLAN filter table * @hw: pointer to hardware structure * @vid: VLAN ID to add to table * @idx: Index indicating VF ID or PF ID in table * @set: Indicates if this is a set or clear operation * * This function adds or removes the corresponding VLAN ID from the VLAN * filter table for the corresponding function. **/ s32 fm10k_update_vlan(struct fm10k_hw *hw, u32 vid, u8 idx, bool set) { return fm10k_call_func(hw, hw->mac.ops.update_vlan, (hw, vid, idx, set), FM10K_NOT_IMPLEMENTED); } /** * fm10k_read_mac_addr - Reads MAC address * @hw: pointer to hardware structure * * Reads the MAC address out of the interface and stores it in the HW * structures. **/ s32 fm10k_read_mac_addr(struct fm10k_hw *hw) { return fm10k_call_func(hw, hw->mac.ops.read_mac_addr, (hw), FM10K_NOT_IMPLEMENTED); } /** * fm10k_update_hw_stats - Update hw statistics * @hw: pointer to hardware structure * * This function updates statistics that are related to hardware. * */ void fm10k_update_hw_stats(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { if (hw->mac.ops.update_hw_stats) hw->mac.ops.update_hw_stats(hw, stats); } /** * fm10k_rebind_hw_stats - Reset base for hw statistics * @hw: pointer to hardware structure * * This function resets the base for statistics that are related to hardware. * */ void fm10k_rebind_hw_stats(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { if (hw->mac.ops.rebind_hw_stats) hw->mac.ops.rebind_hw_stats(hw, stats); } /** * fm10k_configure_dglort_map - Configures GLORT entry and queues * @hw: pointer to hardware structure * @dglort: pointer to dglort configuration structure * * Reads the configuration structure contained in dglort_cfg and uses * that information to then populate a DGLORTMAP/DEC entry and the queues * to which it has been assigned. **/ s32 fm10k_configure_dglort_map(struct fm10k_hw *hw, struct fm10k_dglort_cfg *dglort) { return fm10k_call_func(hw, hw->mac.ops.configure_dglort_map, (hw, dglort), FM10K_NOT_IMPLEMENTED); } /** * fm10k_set_dma_mask - Configures PhyAddrSpace to limit DMA to system * @hw: pointer to hardware structure * @dma_mask: 64 bit DMA mask required for platform * * This function configures the endpoint to limit the access to memory * beyond what is physically in the system. **/ void fm10k_set_dma_mask(struct fm10k_hw *hw, u64 dma_mask) { if (hw->mac.ops.set_dma_mask) hw->mac.ops.set_dma_mask(hw, dma_mask); } /** * fm10k_get_fault - Record a fault in one of the interface units * @hw: pointer to hardware structure * @type: pointer to fault type register offset * @fault: pointer to memory location to record the fault * * Record the fault register contents to the fault data structure and * clear the entry from the register. * * Returns ERR_PARAM if invalid register is specified or no error is present. **/ s32 fm10k_get_fault(struct fm10k_hw *hw, int type, struct fm10k_fault *fault) { return fm10k_call_func(hw, hw->mac.ops.get_fault, (hw, type, fault), FM10K_NOT_IMPLEMENTED); } /** * fm10k_update_uc_addr - Update device unicast address * @hw: pointer to the HW structure * @lport: logical port ID to update - unused * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * @flags: flags field to indicate add and secure - unused * * This function is used to add or remove unicast MAC addresses **/ s32 fm10k_update_uc_addr(struct fm10k_hw *hw, u16 lport, const u8 *mac, u16 vid, bool add, u8 flags) { return fm10k_call_func(hw, hw->mac.ops.update_uc_addr, (hw, lport, mac, vid, add, flags), FM10K_NOT_IMPLEMENTED); } /** * fm10k_update_mc_addr - Update device multicast address * @hw: pointer to the HW structure * @lport: logical port ID to update - unused * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * * This function is used to add or remove multicast MAC addresses **/ s32 fm10k_update_mc_addr(struct fm10k_hw *hw, u16 lport, const u8 *mac, u16 vid, bool add) { return fm10k_call_func(hw, hw->mac.ops.update_mc_addr, (hw, lport, mac, vid, add), FM10K_NOT_IMPLEMENTED); } /** * fm10k_adjust_systime - Adjust systime frequency * @hw: pointer to hardware structure * @ppb: adjustment rate in parts per billion * * This function is meant to update the frequency of the clock represented * by the SYSTIME register. **/ s32 fm10k_adjust_systime(struct fm10k_hw *hw, s32 ppb) { return fm10k_call_func(hw, hw->mac.ops.adjust_systime, (hw, ppb), FM10K_NOT_IMPLEMENTED); } ================================================ FILE: drivers/net/fm10k/base/fm10k_api.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_API_H_ #define _FM10K_API_H_ #include "fm10k_pf.h" #include "fm10k_vf.h" s32 fm10k_set_mac_type(struct fm10k_hw *hw); s32 fm10k_reset_hw(struct fm10k_hw *hw); s32 fm10k_init_hw(struct fm10k_hw *hw); s32 fm10k_stop_hw(struct fm10k_hw *hw); s32 fm10k_start_hw(struct fm10k_hw *hw); s32 fm10k_init_shared_code(struct fm10k_hw *hw); s32 fm10k_get_bus_info(struct fm10k_hw *hw); bool fm10k_is_slot_appropriate(struct fm10k_hw *hw); s32 fm10k_update_vlan(struct fm10k_hw *hw, u32 vid, u8 idx, bool set); s32 fm10k_read_mac_addr(struct fm10k_hw *hw); void fm10k_update_hw_stats(struct fm10k_hw *hw, struct fm10k_hw_stats *stats); void fm10k_rebind_hw_stats(struct fm10k_hw *hw, struct fm10k_hw_stats *stats); s32 fm10k_configure_dglort_map(struct fm10k_hw *hw, struct fm10k_dglort_cfg *dglort); void fm10k_set_dma_mask(struct fm10k_hw *hw, u64 dma_mask); s32 fm10k_get_fault(struct fm10k_hw *hw, int type, struct fm10k_fault *fault); s32 fm10k_update_uc_addr(struct fm10k_hw *hw, u16 lport, const u8 *mac, u16 vid, bool add, u8 flags); s32 fm10k_update_mc_addr(struct fm10k_hw *hw, u16 lport, const u8 *mac, u16 vid, bool add); s32 fm10k_adjust_systime(struct fm10k_hw *hw, s32 ppb); #endif /* _FM10K_API_H_ */ ================================================ FILE: drivers/net/fm10k/base/fm10k_common.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_common.h" /** * fm10k_get_bus_info_generic - Generic set PCI bus info * @hw: pointer to hardware structure * * Gets the PCI bus info (speed, width, type) then calls helper function to * store this data within the fm10k_hw structure. **/ STATIC s32 fm10k_get_bus_info_generic(struct fm10k_hw *hw) { u16 link_cap, link_status, device_cap, device_control; DEBUGFUNC("fm10k_get_bus_info_generic"); /* Get the maximum link width and speed from PCIe config space */ link_cap = FM10K_READ_PCI_WORD(hw, FM10K_PCIE_LINK_CAP); switch (link_cap & FM10K_PCIE_LINK_WIDTH) { case FM10K_PCIE_LINK_WIDTH_1: hw->bus_caps.width = fm10k_bus_width_pcie_x1; break; case FM10K_PCIE_LINK_WIDTH_2: hw->bus_caps.width = fm10k_bus_width_pcie_x2; break; case FM10K_PCIE_LINK_WIDTH_4: hw->bus_caps.width = fm10k_bus_width_pcie_x4; break; case FM10K_PCIE_LINK_WIDTH_8: hw->bus_caps.width = fm10k_bus_width_pcie_x8; break; default: hw->bus_caps.width = fm10k_bus_width_unknown; break; } switch (link_cap & FM10K_PCIE_LINK_SPEED) { case FM10K_PCIE_LINK_SPEED_2500: hw->bus_caps.speed = fm10k_bus_speed_2500; break; case FM10K_PCIE_LINK_SPEED_5000: hw->bus_caps.speed = fm10k_bus_speed_5000; break; case FM10K_PCIE_LINK_SPEED_8000: hw->bus_caps.speed = fm10k_bus_speed_8000; break; default: hw->bus_caps.speed = fm10k_bus_speed_unknown; break; } /* Get the PCIe maximum payload size for the PCIe function */ device_cap = FM10K_READ_PCI_WORD(hw, FM10K_PCIE_DEV_CAP); switch (device_cap & FM10K_PCIE_DEV_CAP_PAYLOAD) { case FM10K_PCIE_DEV_CAP_PAYLOAD_128: hw->bus_caps.payload = fm10k_bus_payload_128; break; case FM10K_PCIE_DEV_CAP_PAYLOAD_256: hw->bus_caps.payload = fm10k_bus_payload_256; break; case FM10K_PCIE_DEV_CAP_PAYLOAD_512: hw->bus_caps.payload = fm10k_bus_payload_512; break; default: hw->bus_caps.payload = fm10k_bus_payload_unknown; break; } /* Get the negotiated link width and speed from PCIe config space */ link_status = FM10K_READ_PCI_WORD(hw, FM10K_PCIE_LINK_STATUS); switch (link_status & FM10K_PCIE_LINK_WIDTH) { case FM10K_PCIE_LINK_WIDTH_1: hw->bus.width = fm10k_bus_width_pcie_x1; break; case FM10K_PCIE_LINK_WIDTH_2: hw->bus.width = fm10k_bus_width_pcie_x2; break; case FM10K_PCIE_LINK_WIDTH_4: hw->bus.width = fm10k_bus_width_pcie_x4; break; case FM10K_PCIE_LINK_WIDTH_8: hw->bus.width = fm10k_bus_width_pcie_x8; break; default: hw->bus.width = fm10k_bus_width_unknown; break; } switch (link_status & FM10K_PCIE_LINK_SPEED) { case FM10K_PCIE_LINK_SPEED_2500: hw->bus.speed = fm10k_bus_speed_2500; break; case FM10K_PCIE_LINK_SPEED_5000: hw->bus.speed = fm10k_bus_speed_5000; break; case FM10K_PCIE_LINK_SPEED_8000: hw->bus.speed = fm10k_bus_speed_8000; break; default: hw->bus.speed = fm10k_bus_speed_unknown; break; } /* Get the negotiated PCIe maximum payload size for the PCIe function */ device_control = FM10K_READ_PCI_WORD(hw, FM10K_PCIE_DEV_CTRL); switch (device_control & FM10K_PCIE_DEV_CTRL_PAYLOAD) { case FM10K_PCIE_DEV_CTRL_PAYLOAD_128: hw->bus.payload = fm10k_bus_payload_128; break; case FM10K_PCIE_DEV_CTRL_PAYLOAD_256: hw->bus.payload = fm10k_bus_payload_256; break; case FM10K_PCIE_DEV_CTRL_PAYLOAD_512: hw->bus.payload = fm10k_bus_payload_512; break; default: hw->bus.payload = fm10k_bus_payload_unknown; break; } return FM10K_SUCCESS; } u16 fm10k_get_pcie_msix_count_generic(struct fm10k_hw *hw) { u16 msix_count; DEBUGFUNC("fm10k_get_pcie_msix_count_generic"); /* read in value from MSI-X capability register */ msix_count = FM10K_READ_PCI_WORD(hw, FM10K_PCI_MSIX_MSG_CTRL); msix_count &= FM10K_PCI_MSIX_MSG_CTRL_TBL_SZ_MASK; /* MSI-X count is zero-based in HW */ msix_count++; if (msix_count > FM10K_MAX_MSIX_VECTORS) msix_count = FM10K_MAX_MSIX_VECTORS; return msix_count; } /** * fm10k_init_ops_generic - Inits function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 fm10k_init_ops_generic(struct fm10k_hw *hw) { struct fm10k_mac_info *mac = &hw->mac; DEBUGFUNC("fm10k_init_ops_generic"); /* MAC */ mac->ops.get_bus_info = &fm10k_get_bus_info_generic; /* initialize GLORT state to avoid any false hits */ mac->dglort_map = FM10K_DGLORTMAP_NONE; return FM10K_SUCCESS; } /** * fm10k_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * This function sets the Tx ready flag to indicate that the Tx path has * been initialized. **/ s32 fm10k_start_hw_generic(struct fm10k_hw *hw) { DEBUGFUNC("fm10k_start_hw_generic"); /* set flag indicating we are beginning Tx */ hw->mac.tx_ready = true; return FM10K_SUCCESS; } /** * fm10k_disable_queues_generic - Stop Tx/Rx queues * @hw: pointer to hardware structure * @q_cnt: number of queues to be disabled * **/ s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt) { u32 reg; u16 i, time; DEBUGFUNC("fm10k_disable_queues_generic"); /* clear tx_ready to prevent any false hits for reset */ hw->mac.tx_ready = false; /* clear the enable bit for all rings */ for (i = 0; i < q_cnt; i++) { reg = FM10K_READ_REG(hw, FM10K_TXDCTL(i)); FM10K_WRITE_REG(hw, FM10K_TXDCTL(i), reg & ~FM10K_TXDCTL_ENABLE); reg = FM10K_READ_REG(hw, FM10K_RXQCTL(i)); FM10K_WRITE_REG(hw, FM10K_RXQCTL(i), reg & ~FM10K_RXQCTL_ENABLE); } FM10K_WRITE_FLUSH(hw); usec_delay(1); /* loop through all queues to verify that they are all disabled */ for (i = 0, time = FM10K_QUEUE_DISABLE_TIMEOUT; time;) { /* if we are at end of rings all rings are disabled */ if (i == q_cnt) return FM10K_SUCCESS; /* if queue enables cleared, then move to next ring pair */ reg = FM10K_READ_REG(hw, FM10K_TXDCTL(i)); if (!~reg || !(reg & FM10K_TXDCTL_ENABLE)) { reg = FM10K_READ_REG(hw, FM10K_RXQCTL(i)); if (!~reg || !(reg & FM10K_RXQCTL_ENABLE)) { i++; continue; } } /* decrement time and wait 1 usec */ time--; if (time) usec_delay(1); } return FM10K_ERR_REQUESTS_PENDING; } /** * fm10k_stop_hw_generic - Stop Tx/Rx units * @hw: pointer to hardware structure * **/ s32 fm10k_stop_hw_generic(struct fm10k_hw *hw) { DEBUGFUNC("fm10k_stop_hw_generic"); return fm10k_disable_queues_generic(hw, hw->mac.max_queues); } /** * fm10k_read_hw_stats_32b - Reads value of 32-bit registers * @hw: pointer to the hardware structure * @addr: address of register containing a 32-bit value * * Function reads the content of the register and returns the delta * between the base and the current value. * **/ u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr, struct fm10k_hw_stat *stat) { u32 delta = FM10K_READ_REG(hw, addr) - stat->base_l; DEBUGFUNC("fm10k_read_hw_stats_32b"); if (FM10K_REMOVED(hw->hw_addr)) stat->base_h = 0; return delta; } /** * fm10k_read_hw_stats_48b - Reads value of 48-bit registers * @hw: pointer to the hardware structure * @addr: address of register containing the lower 32-bit value * * Function reads the content of 2 registers, combined to represent a 48-bit * statistical value. Extra processing is required to handle overflowing. * Finally, a delta value is returned representing the difference between the * values stored in registers and values stored in the statistic counters. * **/ STATIC u64 fm10k_read_hw_stats_48b(struct fm10k_hw *hw, u32 addr, struct fm10k_hw_stat *stat) { u32 count_l; u32 count_h; u32 count_tmp; u64 delta; DEBUGFUNC("fm10k_read_hw_stats_48b"); count_h = FM10K_READ_REG(hw, addr + 1); /* Check for overflow */ do { count_tmp = count_h; count_l = FM10K_READ_REG(hw, addr); count_h = FM10K_READ_REG(hw, addr + 1); } while (count_h != count_tmp); delta = ((u64)(count_h - stat->base_h) << 32) + count_l; delta -= stat->base_l; return delta & FM10K_48_BIT_MASK; } /** * fm10k_update_hw_base_48b - Updates 48-bit statistic base value * @stat: pointer to the hardware statistic structure * @delta: value to be updated into the hardware statistic structure * * Function receives a value and determines if an update is required based on * a delta calculation. Only the base value will be updated. **/ STATIC void fm10k_update_hw_base_48b(struct fm10k_hw_stat *stat, u64 delta) { DEBUGFUNC("fm10k_update_hw_base_48b"); if (!delta) return; /* update lower 32 bits */ delta += stat->base_l; stat->base_l = (u32)delta; /* update upper 32 bits */ stat->base_h += (u32)(delta >> 32); } /** * fm10k_update_hw_stats_tx_q - Updates TX queue statistics counters * @hw: pointer to the hardware structure * @q: pointer to the ring of hardware statistics queue * @idx: index pointing to the start of the ring iteration * * Function updates the TX queue statistics counters that are related to the * hardware. **/ STATIC void fm10k_update_hw_stats_tx_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q, u32 idx) { u32 id_tx, id_tx_prev, tx_packets; u64 tx_bytes = 0; DEBUGFUNC("fm10k_update_hw_stats_tx_q"); /* Retrieve TX Owner Data */ id_tx = FM10K_READ_REG(hw, FM10K_TXQCTL(idx)); /* Process TX Ring */ do { tx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPTC(idx), &q->tx_packets); if (tx_packets) tx_bytes = fm10k_read_hw_stats_48b(hw, FM10K_QBTC_L(idx), &q->tx_bytes); /* Re-Check Owner Data */ id_tx_prev = id_tx; id_tx = FM10K_READ_REG(hw, FM10K_TXQCTL(idx)); } while ((id_tx ^ id_tx_prev) & FM10K_TXQCTL_ID_MASK); /* drop non-ID bits and set VALID ID bit */ id_tx &= FM10K_TXQCTL_ID_MASK; id_tx |= FM10K_STAT_VALID; /* update packet counts */ if (q->tx_stats_idx == id_tx) { q->tx_packets.count += tx_packets; q->tx_bytes.count += tx_bytes; } /* update bases and record ID */ fm10k_update_hw_base_32b(&q->tx_packets, tx_packets); fm10k_update_hw_base_48b(&q->tx_bytes, tx_bytes); q->tx_stats_idx = id_tx; } /** * fm10k_update_hw_stats_rx_q - Updates RX queue statistics counters * @hw: pointer to the hardware structure * @q: pointer to the ring of hardware statistics queue * @idx: index pointing to the start of the ring iteration * * Function updates the RX queue statistics counters that are related to the * hardware. **/ STATIC void fm10k_update_hw_stats_rx_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q, u32 idx) { u32 id_rx, id_rx_prev, rx_packets, rx_drops; u64 rx_bytes = 0; DEBUGFUNC("fm10k_update_hw_stats_rx_q"); /* Retrieve RX Owner Data */ id_rx = FM10K_READ_REG(hw, FM10K_RXQCTL(idx)); /* Process RX Ring */ do { rx_drops = fm10k_read_hw_stats_32b(hw, FM10K_QPRDC(idx), &q->rx_drops); rx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPRC(idx), &q->rx_packets); if (rx_packets) rx_bytes = fm10k_read_hw_stats_48b(hw, FM10K_QBRC_L(idx), &q->rx_bytes); /* Re-Check Owner Data */ id_rx_prev = id_rx; id_rx = FM10K_READ_REG(hw, FM10K_RXQCTL(idx)); } while ((id_rx ^ id_rx_prev) & FM10K_RXQCTL_ID_MASK); /* drop non-ID bits and set VALID ID bit */ id_rx &= FM10K_RXQCTL_ID_MASK; id_rx |= FM10K_STAT_VALID; /* update packet counts */ if (q->rx_stats_idx == id_rx) { q->rx_drops.count += rx_drops; q->rx_packets.count += rx_packets; q->rx_bytes.count += rx_bytes; } /* update bases and record ID */ fm10k_update_hw_base_32b(&q->rx_drops, rx_drops); fm10k_update_hw_base_32b(&q->rx_packets, rx_packets); fm10k_update_hw_base_48b(&q->rx_bytes, rx_bytes); q->rx_stats_idx = id_rx; } /** * fm10k_update_hw_stats_q - Updates queue statistics counters * @hw: pointer to the hardware structure * @q: pointer to the ring of hardware statistics queue * @idx: index pointing to the start of the ring iteration * @count: number of queues to iterate over * * Function updates the queue statistics counters that are related to the * hardware. **/ void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q, u32 idx, u32 count) { u32 i; DEBUGFUNC("fm10k_update_hw_stats_q"); for (i = 0; i < count; i++, idx++, q++) { fm10k_update_hw_stats_tx_q(hw, q, idx); fm10k_update_hw_stats_rx_q(hw, q, idx); } } /** * fm10k_unbind_hw_stats_q - Unbind the queue counters from their queues * @hw: pointer to the hardware structure * @q: pointer to the ring of hardware statistics queue * @idx: index pointing to the start of the ring iteration * @count: number of queues to iterate over * * Function invalidates the index values for the queues so any updates that * may have happened are ignored and the base for the queue stats is reset. **/ void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count) { u32 i; for (i = 0; i < count; i++, idx++, q++) { q->rx_stats_idx = 0; q->tx_stats_idx = 0; } } /** * fm10k_get_host_state_generic - Returns the state of the host * @hw: pointer to hardware structure * @host_ready: pointer to boolean value that will record host state * * This function will check the health of the mailbox and Tx queue 0 * in order to determine if we should report that the link is up or not. **/ s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready) { struct fm10k_mbx_info *mbx = &hw->mbx; struct fm10k_mac_info *mac = &hw->mac; s32 ret_val = FM10K_SUCCESS; u32 txdctl = FM10K_READ_REG(hw, FM10K_TXDCTL(0)); DEBUGFUNC("fm10k_get_host_state_generic"); /* process upstream mailbox in case interrupts were disabled */ mbx->ops.process(hw, mbx); /* If Tx is no longer enabled link should come down */ if (!(~txdctl) || !(txdctl & FM10K_TXDCTL_ENABLE)) mac->get_host_state = true; /* exit if not checking for link, or link cannot be changed */ if (!mac->get_host_state || !(~txdctl)) goto out; /* if we somehow dropped the Tx enable we should reset */ if (hw->mac.tx_ready && !(txdctl & FM10K_TXDCTL_ENABLE)) { ret_val = FM10K_ERR_RESET_REQUESTED; goto out; } /* if Mailbox timed out we should request reset */ if (!mbx->timeout) { ret_val = FM10K_ERR_RESET_REQUESTED; goto out; } /* verify Mailbox is still valid */ if (!mbx->ops.tx_ready(mbx, FM10K_VFMBX_MSG_MTU)) goto out; /* interface cannot receive traffic without logical ports */ if (mac->dglort_map == FM10K_DGLORTMAP_NONE) goto out; /* if we passed all the tests above then the switch is ready and we no * longer need to check for link */ mac->get_host_state = false; out: *host_ready = !mac->get_host_state; return ret_val; } ================================================ FILE: drivers/net/fm10k/base/fm10k_common.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_COMMON_H_ #define _FM10K_COMMON_H_ #include "fm10k_type.h" u16 fm10k_get_pcie_msix_count_generic(struct fm10k_hw *hw); s32 fm10k_init_ops_generic(struct fm10k_hw *hw); s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt); s32 fm10k_start_hw_generic(struct fm10k_hw *hw); s32 fm10k_stop_hw_generic(struct fm10k_hw *hw); u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr, struct fm10k_hw_stat *stat); #define fm10k_update_hw_base_32b(stat, delta) ((stat)->base_l += (delta)) void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q, u32 idx, u32 count); #define fm10k_unbind_hw_stats_32b(s) ((s)->base_h = 0) void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count); s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready); #endif /* _FM10K_COMMON_H_ */ ================================================ FILE: drivers/net/fm10k/base/fm10k_mbx.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_common.h" /** * fm10k_fifo_init - Initialize a message FIFO * @fifo: pointer to FIFO * @buffer: pointer to memory to be used to store FIFO * @size: maximum message size to store in FIFO, must be 2^n - 1 **/ STATIC void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size) { fifo->buffer = buffer; fifo->size = size; fifo->head = 0; fifo->tail = 0; } /** * fm10k_fifo_used - Retrieve used space in FIFO * @fifo: pointer to FIFO * * This function returns the number of DWORDs used in the FIFO **/ STATIC u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo) { return fifo->tail - fifo->head; } /** * fm10k_fifo_unused - Retrieve unused space in FIFO * @fifo: pointer to FIFO * * This function returns the number of unused DWORDs in the FIFO **/ STATIC u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo) { return fifo->size + fifo->head - fifo->tail; } /** * fm10k_fifo_empty - Test to verify if fifo is empty * @fifo: pointer to FIFO * * This function returns true if the FIFO is empty, else false **/ STATIC bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo) { return fifo->head == fifo->tail; } /** * fm10k_fifo_head_offset - returns indices of head with given offset * @fifo: pointer to FIFO * @offset: offset to add to head * * This function returns the indices into the fifo based on head + offset **/ STATIC u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset) { return (fifo->head + offset) & (fifo->size - 1); } /** * fm10k_fifo_tail_offset - returns indices of tail with given offset * @fifo: pointer to FIFO * @offset: offset to add to tail * * This function returns the indices into the fifo based on tail + offset **/ STATIC u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset) { return (fifo->tail + offset) & (fifo->size - 1); } /** * fm10k_fifo_head_len - Retrieve length of first message in FIFO * @fifo: pointer to FIFO * * This function returns the size of the first message in the FIFO **/ STATIC u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo) { u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0); /* verify there is at least 1 DWORD in the fifo so *head is valid */ if (fm10k_fifo_empty(fifo)) return 0; /* retieve the message length */ return FM10K_TLV_DWORD_LEN(*head); } /** * fm10k_fifo_head_drop - Drop the first message in FIFO * @fifo: pointer to FIFO * * This function returns the size of the message dropped from the FIFO **/ STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo) { u16 len = fm10k_fifo_head_len(fifo); /* update head so it is at the start of next frame */ fifo->head += len; return len; } /** * fm10k_mbx_index_len - Convert a head/tail index into a length value * @mbx: pointer to mailbox * @head: head index * @tail: head index * * This function takes the head and tail index and determines the length * of the data indicated by this pair. **/ STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail) { u16 len = tail - head; /* we wrapped so subtract 2, one for index 0, one for all 1s index */ if (len > tail) len -= 2; return len & ((mbx->mbmem_len << 1) - 1); } /** * fm10k_mbx_tail_add - Determine new tail value with added offset * @mbx: pointer to mailbox * @offset: length to add to head offset * * This function takes the local tail index and recomputes it for * a given length added as an offset. **/ STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset) { u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1); /* add/sub 1 because we cannot have offset 0 or all 1s */ return (tail > mbx->tail) ? --tail : ++tail; } /** * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset * @mbx: pointer to mailbox * @offset: length to add to head offset * * This function takes the local tail index and recomputes it for * a given length added as an offset. **/ STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset) { u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1); /* sub/add 1 because we cannot have offset 0 or all 1s */ return (tail < mbx->tail) ? ++tail : --tail; } /** * fm10k_mbx_head_add - Determine new head value with added offset * @mbx: pointer to mailbox * @offset: length to add to head offset * * This function takes the local head index and recomputes it for * a given length added as an offset. **/ STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset) { u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1); /* add/sub 1 because we cannot have offset 0 or all 1s */ return (head > mbx->head) ? --head : ++head; } /** * fm10k_mbx_head_sub - Determine new head value with subtracted offset * @mbx: pointer to mailbox * @offset: length to add to head offset * * This function takes the local head index and recomputes it for * a given length added as an offset. **/ STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset) { u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1); /* sub/add 1 because we cannot have offset 0 or all 1s */ return (head < mbx->head) ? ++head : --head; } /** * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed * @mbx: pointer to mailbox * * This function will return the length of the message currently being * pushed onto the tail of the Rx queue. **/ STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx) { u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0); /* pushed tail is only valid if pushed is set */ if (!mbx->pushed) return 0; return FM10K_TLV_DWORD_LEN(*tail); } /** * fm10k_fifo_write_copy - pulls data off of msg and places it in fifo * @fifo: pointer to FIFO * @msg: message array to populate * @tail_offset: additional offset to add to tail pointer * @len: length of FIFO to copy into message header * * This function will take a message and copy it into a section of the * FIFO. In order to get something into a location other than just * the tail you can use tail_offset to adjust the pointer. **/ STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo, const u32 *msg, u16 tail_offset, u16 len) { u16 end = fm10k_fifo_tail_offset(fifo, tail_offset); u32 *tail = fifo->buffer + end; /* track when we should cross the end of the FIFO */ end = fifo->size - end; /* copy end of message before start of message */ if (end < len) memcpy(fifo->buffer, msg + end, (len - end) << 2); else end = len; /* Copy remaining message into Tx FIFO */ memcpy(tail, msg, end << 2); } /** * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO * @fifo: pointer to FIFO * @msg: message array to read * * This function enqueues a message up to the size specified by the length * contained in the first DWORD of the message and will place at the tail * of the FIFO. It will return 0 on success, or a negative value on error. **/ STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg) { u16 len = FM10K_TLV_DWORD_LEN(*msg); DEBUGFUNC("fm10k_fifo_enqueue"); /* verify parameters */ if (len > fifo->size) return FM10K_MBX_ERR_SIZE; /* verify there is room for the message */ if (len > fm10k_fifo_unused(fifo)) return FM10K_MBX_ERR_NO_SPACE; /* Copy message into FIFO */ fm10k_fifo_write_copy(fifo, msg, 0, len); /* memory barrier to guarantee FIFO is written before tail update */ FM10K_WMB(); /* Update Tx FIFO tail */ fifo->tail += len; return FM10K_SUCCESS; } /** * fm10k_mbx_validate_msg_size - Validate incoming message based on size * @mbx: pointer to mailbox * @len: length of data pushed onto buffer * * This function analyzes the frame and will return a non-zero value when * the start of a message larger than the mailbox is detected. **/ STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len) { struct fm10k_mbx_fifo *fifo = &mbx->rx; u16 total_len = 0, msg_len; u32 *msg; DEBUGFUNC("fm10k_mbx_validate_msg"); /* length should include previous amounts pushed */ len += mbx->pushed; /* offset in message is based off of current message size */ do { msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len); msg_len = FM10K_TLV_DWORD_LEN(*msg); total_len += msg_len; } while (total_len < len); /* message extends out of pushed section, but fits in FIFO */ if ((len < total_len) && (msg_len <= mbx->rx.size)) return 0; /* return length of invalid section */ return (len < total_len) ? len : (len - total_len); } /** * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem * @mbx: pointer to mailbox * * This function will take a section of the Rx FIFO and copy it into the mbx->tail--; * mailbox memory. The offset in mbmem is based on the lower bits of the * tail and len determines the length to copy. **/ STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { struct fm10k_mbx_fifo *fifo = &mbx->tx; u32 mbmem = mbx->mbmem_reg; u32 *head = fifo->buffer; u16 end, len, tail, mask; DEBUGFUNC("fm10k_mbx_write_copy"); if (!mbx->tail_len) return; /* determine data length and mbmem tail index */ mask = mbx->mbmem_len - 1; len = mbx->tail_len; tail = fm10k_mbx_tail_sub(mbx, len); if (tail > mask) tail++; /* determine offset in the ring */ end = fm10k_fifo_head_offset(fifo, mbx->pulled); head += end; /* memory barrier to guarantee data is ready to be read */ FM10K_RMB(); /* Copy message from Tx FIFO */ for (end = fifo->size - end; len; head = fifo->buffer) { do { /* adjust tail to match offset for FIFO */ tail &= mask; if (!tail) tail++; /* write message to hardware FIFO */ FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++)); } while (--len && --end); } } /** * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * @head: acknowledgement number last received * * This function will push the tail index forward based on the remote * head index. It will then pull up to mbmem_len DWORDs off of the * head of the FIFO and will place it in the MBMEM registers * associated with the mailbox. **/ STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 head) { u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail); struct fm10k_mbx_fifo *fifo = &mbx->tx; /* update number of bytes pulled and update bytes in transit */ mbx->pulled += mbx->tail_len - ack; /* determine length of data to pull, reserve space for mbmem header */ mbmem_len = mbx->mbmem_len - 1; len = fm10k_fifo_used(fifo) - mbx->pulled; if (len > mbmem_len) len = mbmem_len; /* update tail and record number of bytes in transit */ mbx->tail = fm10k_mbx_tail_add(mbx, len - ack); mbx->tail_len = len; /* drop pulled messages from the FIFO */ for (len = fm10k_fifo_head_len(fifo); len && (mbx->pulled >= len); len = fm10k_fifo_head_len(fifo)) { mbx->pulled -= fm10k_fifo_head_drop(fifo); mbx->tx_messages++; mbx->tx_dwords += len; } /* Copy message out from the Tx FIFO */ fm10k_mbx_write_copy(hw, mbx); } /** * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will take a section of the mailbox memory and copy it * into the Rx FIFO. The offset is based on the lower bits of the * head and len determines the length to copy. **/ STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { struct fm10k_mbx_fifo *fifo = &mbx->rx; u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len; u32 *tail = fifo->buffer; u16 end, len, head; DEBUGFUNC("fm10k_mbx_read_copy"); /* determine data length and mbmem head index */ len = mbx->head_len; head = fm10k_mbx_head_sub(mbx, len); if (head >= mbx->mbmem_len) head++; /* determine offset in the ring */ end = fm10k_fifo_tail_offset(fifo, mbx->pushed); tail += end; /* Copy message into Rx FIFO */ for (end = fifo->size - end; len; tail = fifo->buffer) { do { /* adjust head to match offset for FIFO */ head &= mbx->mbmem_len - 1; if (!head) head++; /* read message from hardware FIFO */ *(tail++) = FM10K_READ_MBX(hw, mbmem + head++); } while (--len && --end); } /* memory barrier to guarantee FIFO is written before tail update */ FM10K_WMB(); } /** * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * @tail: tail index of message * * This function will first validate the tail index and size for the * incoming message. It then updates the acknowledgment number and * copies the data into the FIFO. It will return the number of messages * dequeued on success and a negative value on error. **/ STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 tail) { struct fm10k_mbx_fifo *fifo = &mbx->rx; u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail); DEBUGFUNC("fm10k_mbx_push_tail"); /* determine length of data to push */ len = fm10k_fifo_unused(fifo) - mbx->pushed; if (len > seq) len = seq; /* update head and record bytes received */ mbx->head = fm10k_mbx_head_add(mbx, len); mbx->head_len = len; /* nothing to do if there is no data */ if (!len) return FM10K_SUCCESS; /* Copy msg into Rx FIFO */ fm10k_mbx_read_copy(hw, mbx); /* determine if there are any invalid lengths in message */ if (fm10k_mbx_validate_msg_size(mbx, len)) return FM10K_MBX_ERR_SIZE; /* Update pushed */ mbx->pushed += len; /* flush any completed messages */ for (len = fm10k_mbx_pushed_tail_len(mbx); len && (mbx->pushed >= len); len = fm10k_mbx_pushed_tail_len(mbx)) { fifo->tail += len; mbx->pushed -= len; mbx->rx_messages++; mbx->rx_dwords += len; } return FM10K_SUCCESS; } /* pre-generated data for generating the CRC based on the poly 0xAC9A. */ static const u16 fm10k_crc_16b_table[256] = { 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797, 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678, 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449, 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6, 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B, 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4, 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5, 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A, 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA, 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035, 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204, 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB, 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666, 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789, 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8, 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457, 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D, 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2, 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3, 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C, 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1, 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E, 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F, 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80, 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40, 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF, 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E, 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71, 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC, 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13, 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922, 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD }; /** * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data * @data: pointer to data to process * @seed: seed value for CRC * @len: length measured in 16 bits words * * This function will generate a CRC based on the polynomial 0xAC9A and * whatever value is stored in the seed variable. Note that this * value inverts the local seed and the result in order to capture all * leading and trailing zeros. */ STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len) { u32 result = seed; while (len--) { result ^= *(data++); result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF]; result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF]; if (!(len--)) break; result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF]; result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF]; } return (u16)result; } /** * fm10k_fifo_crc - generate a CRC based off of FIFO data * @fifo: pointer to FIFO * @offset: offset point for start of FIFO * @len: number of DWORDS words to process * @seed: seed value for CRC * * This function generates a CRC for some region of the FIFO **/ STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset, u16 len, u16 seed) { u32 *data = fifo->buffer + offset; /* track when we should cross the end of the FIFO */ offset = fifo->size - offset; /* if we are in 2 blocks process the end of the FIFO first */ if (offset < len) { seed = fm10k_crc_16b(data, seed, offset * 2); data = fifo->buffer; len -= offset; } /* process any remaining bits */ return fm10k_crc_16b(data, seed, len * 2); } /** * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data * @mbx: pointer to mailbox * @head: head index provided by remote mailbox * * This function will generate the CRC for all data from the end of the * last head update to the current one. It uses the result of the * previous CRC as the seed for this update. The result is stored in * mbx->local. **/ STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head) { u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail); /* determine the offset for the start of the region to be pulled */ head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled); /* update local CRC to include all of the pulled data */ mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local); } /** * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data * @mbx: pointer to mailbox * * This function will take all data that has been provided from the remote * end and generate a CRC for it. This is stored in mbx->remote. The * CRC for the header is then computed and if the result is non-zero this * is an error and we signal an error dropping all data and resetting the * connection. */ STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx) { struct fm10k_mbx_fifo *fifo = &mbx->rx; u16 len = mbx->head_len; u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len; u16 crc; /* update the remote CRC if new data has been received */ if (len) mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote); /* process the full header as we have to validate the CRC */ crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1); /* notify other end if we have a problem */ return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS; } /** * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO * @mbx: pointer to mailbox * * This function returns true if there is a message in the Rx FIFO to dequeue. **/ STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx) { u16 msg_size = fm10k_fifo_head_len(&mbx->rx); return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size); } /** * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx * @mbx: pointer to mailbox * @len: verify free space is >= this value * * This function returns true if the mailbox is in a state ready to transmit. **/ STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len) { u16 fifo_unused = fm10k_fifo_unused(&mbx->tx); return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len); } /** * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied * @mbx: pointer to mailbox * * This function returns true if the Tx FIFO is empty. **/ STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx) { return fm10k_fifo_empty(&mbx->tx); } /** * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function dequeues messages and hands them off to the tlv parser. * It will return the number of messages processed when called. **/ STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { struct fm10k_mbx_fifo *fifo = &mbx->rx; s32 err; u16 cnt; /* parse Rx messages out of the Rx FIFO to empty it */ for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) { err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head, mbx, mbx->msg_data); if (err < 0) mbx->rx_parse_err++; fm10k_fifo_head_drop(fifo); } /* shift remaining bytes back to start of FIFO */ memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2); /* shift head and tail based on the memory we moved */ fifo->tail -= fifo->head; fifo->head = 0; return cnt; } /** * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * @msg: message array to read * * This function enqueues a message up to the size specified by the length * contained in the first DWORD of the message and will place at the tail * of the FIFO. It will return 0 on success, or a negative value on error. **/ STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, const u32 *msg) { u32 countdown = mbx->timeout; s32 err; switch (mbx->state) { case FM10K_STATE_CLOSED: case FM10K_STATE_DISCONNECT: return FM10K_MBX_ERR_NO_MBX; default: break; } /* enqueue the message on the Tx FIFO */ err = fm10k_fifo_enqueue(&mbx->tx, msg); /* if it failed give the FIFO a chance to drain */ while (err && countdown) { countdown--; usec_delay(mbx->usec_delay); mbx->ops.process(hw, mbx); err = fm10k_fifo_enqueue(&mbx->tx, msg); } /* if we failed treat the error */ if (err) { mbx->timeout = 0; mbx->tx_busy++; } /* begin processing message, ignore errors as this is just meant * to start the mailbox flow so we are not concerned if there * is a bad error, or the mailbox is already busy with a request */ if (!mbx->tail_len) mbx->ops.process(hw, mbx); return FM10K_SUCCESS; } /** * fm10k_mbx_read - Copies the mbmem to local message buffer * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function copies the message from the mbmem to the message array **/ STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { DEBUGFUNC("fm10k_mbx_read"); /* only allow one reader in here at a time */ if (mbx->mbx_hdr) return FM10K_MBX_ERR_BUSY; /* read to capture initial interrupt bits */ if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT) mbx->mbx_lock = FM10K_MBX_ACK; /* write back interrupt bits to clear */ FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT); /* read remote header */ mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len); return FM10K_SUCCESS; } /** * fm10k_mbx_write - Copies the local message buffer to mbmem * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function copies the message from the the message array to mbmem **/ STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { u32 mbmem = mbx->mbmem_reg; DEBUGFUNC("fm10k_mbx_write"); /* write new msg header to notify recipient of change */ FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr); /* write mailbox to send interrupt */ if (mbx->mbx_lock) FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock); /* we no longer are using the header so free it */ mbx->mbx_hdr = 0; mbx->mbx_lock = 0; } /** * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header * @mbx: pointer to mailbox * * This function returns a connection mailbox header **/ STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx) { mbx->mbx_lock |= FM10K_MBX_REQ; mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) | FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) | FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE); } /** * fm10k_mbx_create_data_hdr - Generate a data mailbox header * @mbx: pointer to mailbox * * This function returns a data mailbox header **/ STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx) { u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) | FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) | FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD); struct fm10k_mbx_fifo *fifo = &mbx->tx; u16 crc; if (mbx->tail_len) mbx->mbx_lock |= FM10K_MBX_REQ; /* generate CRC for data in flight and header */ crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled), mbx->tail_len, mbx->local); crc = fm10k_crc_16b(&hdr, crc, 1); /* load header to memory to be written */ mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC); } /** * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header * @mbx: pointer to mailbox * * This function returns a disconnect mailbox header **/ STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx) { u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) | FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) | FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD); u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1); mbx->mbx_lock |= FM10K_MBX_ACK; /* load header to memory to be written */ mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC); } /** * fm10k_mbx_create_error_msg - Generate a error message * @mbx: pointer to mailbox * @err: local error encountered * * This function will interpret the error provided by err, and based on * that it may shift the message by 1 DWORD and then place an error header * at the start of the message. **/ STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err) { /* only generate an error message for these types */ switch (err) { case FM10K_MBX_ERR_TAIL: case FM10K_MBX_ERR_HEAD: case FM10K_MBX_ERR_TYPE: case FM10K_MBX_ERR_SIZE: case FM10K_MBX_ERR_RSVD0: case FM10K_MBX_ERR_CRC: break; default: return; } mbx->mbx_lock |= FM10K_MBX_REQ; mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) | FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) | FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD); } /** * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header * @mbx: pointer to mailbox * @msg: message array to read * * This function will parse up the fields in the mailbox header and return * an error if the header contains any of a number of invalid configurations * including unrecognized type, invalid route, or a malformed message. **/ STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx) { u16 type, rsvd0, head, tail, size; const u32 *hdr = &mbx->mbx_hdr; DEBUGFUNC("fm10k_mbx_validate_msg_hdr"); type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE); rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0); tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL); head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE); if (rsvd0) return FM10K_MBX_ERR_RSVD0; switch (type) { case FM10K_MSG_DISCONNECT: /* validate that all data has been received */ if (tail != mbx->head) return FM10K_MBX_ERR_TAIL; /* fall through */ case FM10K_MSG_DATA: /* validate that head is moving correctly */ if (!head || (head == FM10K_MSG_HDR_MASK(HEAD))) return FM10K_MBX_ERR_HEAD; if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len) return FM10K_MBX_ERR_HEAD; /* validate that tail is moving correctly */ if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL))) return FM10K_MBX_ERR_TAIL; if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len) break; return FM10K_MBX_ERR_TAIL; case FM10K_MSG_CONNECT: /* validate size is in range and is power of 2 mask */ if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1))) return FM10K_MBX_ERR_SIZE; /* fall through */ case FM10K_MSG_ERROR: if (!head || (head == FM10K_MSG_HDR_MASK(HEAD))) return FM10K_MBX_ERR_HEAD; /* neither create nor error include a tail offset */ if (tail) return FM10K_MBX_ERR_TAIL; break; default: return FM10K_MBX_ERR_TYPE; } return FM10K_SUCCESS; } /** * fm10k_mbx_create_reply - Generate reply based on state and remote head * @mbx: pointer to mailbox * @head: acknowledgement number * * This function will generate an outgoing message based on the current * mailbox state and the remote fifo head. It will return the length * of the outgoing message excluding header on success, and a negative value * on error. **/ STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 head) { switch (mbx->state) { case FM10K_STATE_OPEN: case FM10K_STATE_DISCONNECT: /* update our checksum for the outgoing data */ fm10k_mbx_update_local_crc(mbx, head); /* as long as other end recognizes us keep sending data */ fm10k_mbx_pull_head(hw, mbx, head); /* generate new header based on data */ if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) fm10k_mbx_create_data_hdr(mbx); else fm10k_mbx_create_disconnect_hdr(mbx); break; case FM10K_STATE_CONNECT: /* send disconnect even if we aren't connected */ fm10k_mbx_create_connect_hdr(mbx); break; case FM10K_STATE_CLOSED: /* generate new header based on data */ fm10k_mbx_create_disconnect_hdr(mbx); default: break; } return FM10K_SUCCESS; } /** * fm10k_mbx_reset_work- Reset internal pointers for any pending work * @mbx: pointer to mailbox * * This function will reset all internal pointers so any work in progress * is dropped. This call should occur every time we transition from the * open state to the connect state. **/ STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx) { /* reset our outgoing max size back to Rx limits */ mbx->max_size = mbx->rx.size - 1; /* just do a quick resysnc to start of message */ mbx->pushed = 0; mbx->pulled = 0; mbx->tail_len = 0; mbx->head_len = 0; mbx->rx.tail = 0; mbx->rx.head = 0; } /** * fm10k_mbx_update_max_size - Update the max_size and drop any large messages * @mbx: pointer to mailbox * @size: new value for max_size * * This function will update the max_size value and drop any outgoing messages * from the head of the Tx FIFO that are larger than max_size. **/ STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size) { u16 len; DEBUGFUNC("fm10k_mbx_update_max_size_hdr"); mbx->max_size = size; /* flush any oversized messages from the queue */ for (len = fm10k_fifo_head_len(&mbx->tx); len > size; len = fm10k_fifo_head_len(&mbx->tx)) { fm10k_fifo_head_drop(&mbx->tx); mbx->tx_dropped++; } } /** * fm10k_mbx_connect_reset - Reset following request for reset * @mbx: pointer to mailbox * * This function resets the mailbox to either a disconnected state * or a connect state depending on the current mailbox state **/ STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx) { /* just do a quick resysnc to start of frame */ fm10k_mbx_reset_work(mbx); /* reset CRC seeds */ mbx->local = FM10K_MBX_CRC_SEED; mbx->remote = FM10K_MBX_CRC_SEED; /* we cannot exit connect until the size is good */ if (mbx->state == FM10K_STATE_OPEN) mbx->state = FM10K_STATE_CONNECT; else mbx->state = FM10K_STATE_CLOSED; } /** * fm10k_mbx_process_connect - Process connect header * @mbx: pointer to mailbox * @msg: message array to process * * This function will read an incoming connect header and reply with the * appropriate message. It will return a value indicating the number of * data DWORDs on success, or will return a negative value on failure. **/ STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const enum fm10k_mbx_state state = mbx->state; const u32 *hdr = &mbx->mbx_hdr; u16 size, head; /* we will need to pull all of the fields for verification */ size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE); head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); switch (state) { case FM10K_STATE_DISCONNECT: case FM10K_STATE_OPEN: /* reset any in-progress work */ fm10k_mbx_connect_reset(mbx); break; case FM10K_STATE_CONNECT: /* we cannot exit connect until the size is good */ if (size > mbx->rx.size) { mbx->max_size = mbx->rx.size - 1; } else { /* record the remote system requesting connection */ mbx->state = FM10K_STATE_OPEN; fm10k_mbx_update_max_size(mbx, size); } break; default: break; } /* align our tail index to remote head index */ mbx->tail = head; return fm10k_mbx_create_reply(hw, mbx, head); } /** * fm10k_mbx_process_data - Process data header * @mbx: pointer to mailbox * * This function will read an incoming data header and reply with the * appropriate message. It will return a value indicating the number of * data DWORDs on success, or will return a negative value on failure. **/ STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const u32 *hdr = &mbx->mbx_hdr; u16 head, tail; s32 err; DEBUGFUNC("fm10k_mbx_process_data"); /* we will need to pull all of the fields for verification */ head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL); /* if we are in connect just update our data and go */ if (mbx->state == FM10K_STATE_CONNECT) { mbx->tail = head; mbx->state = FM10K_STATE_OPEN; } /* abort on message size errors */ err = fm10k_mbx_push_tail(hw, mbx, tail); if (err < 0) return err; /* verify the checksum on the incoming data */ err = fm10k_mbx_verify_remote_crc(mbx); if (err) return err; /* process messages if we have received any */ fm10k_mbx_dequeue_rx(hw, mbx); return fm10k_mbx_create_reply(hw, mbx, head); } /** * fm10k_mbx_process_disconnect - Process disconnect header * @mbx: pointer to mailbox * * This function will read an incoming disconnect header and reply with the * appropriate message. It will return a value indicating the number of * data DWORDs on success, or will return a negative value on failure. **/ STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const enum fm10k_mbx_state state = mbx->state; const u32 *hdr = &mbx->mbx_hdr; u16 head; s32 err; /* we will need to pull the header field for verification */ head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); /* We should not be receiving disconnect if Rx is incomplete */ if (mbx->pushed) return FM10K_MBX_ERR_TAIL; /* we have already verified mbx->head == tail so we know this is 0 */ mbx->head_len = 0; /* verify the checksum on the incoming header is correct */ err = fm10k_mbx_verify_remote_crc(mbx); if (err) return err; switch (state) { case FM10K_STATE_DISCONNECT: case FM10K_STATE_OPEN: /* state doesn't change if we still have work to do */ if (!fm10k_mbx_tx_complete(mbx)) break; /* verify the head indicates we completed all transmits */ if (head != mbx->tail) return FM10K_MBX_ERR_HEAD; /* reset any in-progress work */ fm10k_mbx_connect_reset(mbx); break; default: break; } return fm10k_mbx_create_reply(hw, mbx, head); } /** * fm10k_mbx_process_error - Process error header * @mbx: pointer to mailbox * * This function will read an incoming error header and reply with the * appropriate message. It will return a value indicating the number of * data DWORDs on success, or will return a negative value on failure. **/ STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const u32 *hdr = &mbx->mbx_hdr; s32 err_no; u16 head; /* we will need to pull all of the fields for verification */ head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD); /* we only have lower 10 bits of error number so add upper bits */ err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO); err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO); switch (mbx->state) { case FM10K_STATE_OPEN: case FM10K_STATE_DISCONNECT: /* flush any uncompleted work */ fm10k_mbx_reset_work(mbx); /* reset CRC seeds */ mbx->local = FM10K_MBX_CRC_SEED; mbx->remote = FM10K_MBX_CRC_SEED; /* reset tail index and size to prepare for reconnect */ mbx->tail = head; /* if open then reset max_size and go back to connect */ if (mbx->state == FM10K_STATE_OPEN) { mbx->state = FM10K_STATE_CONNECT; break; } /* send a connect message to get data flowing again */ fm10k_mbx_create_connect_hdr(mbx); return FM10K_SUCCESS; default: break; } return fm10k_mbx_create_reply(hw, mbx, mbx->tail); } /** * fm10k_mbx_process - Process mailbox interrupt * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will process incoming mailbox events and generate mailbox * replies. It will return a value indicating the number of DWORDs * transmitted excluding header on success or a negative value on error. **/ STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { s32 err; DEBUGFUNC("fm10k_mbx_process"); /* we do not read mailbox if closed */ if (mbx->state == FM10K_STATE_CLOSED) return FM10K_SUCCESS; /* copy data from mailbox */ err = fm10k_mbx_read(hw, mbx); if (err) return err; /* validate type, source, and destination */ err = fm10k_mbx_validate_msg_hdr(mbx); if (err < 0) goto msg_err; switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) { case FM10K_MSG_CONNECT: err = fm10k_mbx_process_connect(hw, mbx); break; case FM10K_MSG_DATA: err = fm10k_mbx_process_data(hw, mbx); break; case FM10K_MSG_DISCONNECT: err = fm10k_mbx_process_disconnect(hw, mbx); break; case FM10K_MSG_ERROR: err = fm10k_mbx_process_error(hw, mbx); break; default: err = FM10K_MBX_ERR_TYPE; break; } msg_err: /* notify partner of errors on our end */ if (err < 0) fm10k_mbx_create_error_msg(mbx, err); /* copy data from mailbox */ fm10k_mbx_write(hw, mbx); return err; } /** * fm10k_mbx_disconnect - Shutdown mailbox connection * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will shut down the mailbox. It places the mailbox first * in the disconnect state, it then allows up to a predefined timeout for * the mailbox to transition to close on its own. If this does not occur * then the mailbox will be forced into the closed state. * * Any mailbox transactions not completed before calling this function * are not guaranteed to complete and may be dropped. **/ STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0; DEBUGFUNC("fm10k_mbx_disconnect"); /* Place mbx in ready to disconnect state */ mbx->state = FM10K_STATE_DISCONNECT; /* trigger interrupt to start shutdown process */ FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ | FM10K_MBX_INTERRUPT_DISABLE); do { usec_delay(FM10K_MBX_POLL_DELAY); mbx->ops.process(hw, mbx); timeout -= FM10K_MBX_POLL_DELAY; } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED)); /* in case we didn't close just force the mailbox into shutdown */ fm10k_mbx_connect_reset(mbx); fm10k_mbx_update_max_size(mbx, 0); FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0); } /** * fm10k_mbx_connect - Start mailbox connection * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will initiate a mailbox connection. It will populate the * mailbox with a broadcast connect message and then initialize the lock. * This is safe since the connect message is a single DWORD so the mailbox * transaction is guaranteed to be atomic. * * This function will return an error if the mailbox has not been initiated * or is currently in use. **/ STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { DEBUGFUNC("fm10k_mbx_connect"); /* we cannot connect an uninitialized mailbox */ if (!mbx->rx.buffer) return FM10K_MBX_ERR_NO_SPACE; /* we cannot connect an already connected mailbox */ if (mbx->state != FM10K_STATE_CLOSED) return FM10K_MBX_ERR_BUSY; /* mailbox timeout can now become active */ mbx->timeout = FM10K_MBX_INIT_TIMEOUT; /* Place mbx in ready to connect state */ mbx->state = FM10K_STATE_CONNECT; /* initialize header of remote mailbox */ fm10k_mbx_create_disconnect_hdr(mbx); FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr); /* enable interrupt and notify other party of new message */ mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT | FM10K_MBX_INTERRUPT_ENABLE; /* generate and load connect header into mailbox */ fm10k_mbx_create_connect_hdr(mbx); fm10k_mbx_write(hw, mbx); return FM10K_SUCCESS; } /** * fm10k_mbx_validate_handlers - Validate layout of message parsing data * @msg_data: handlers for mailbox events * * This function validates the layout of the message parsing data. This * should be mostly static, but it is important to catch any errors that * are made when constructing the parsers. **/ STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data) { const struct fm10k_tlv_attr *attr; unsigned int id; DEBUGFUNC("fm10k_mbx_validate_handlers"); /* Allow NULL mailboxes that transmit but don't receive */ if (!msg_data) return FM10K_SUCCESS; while (msg_data->id != FM10K_TLV_ERROR) { /* all messages should have a function handler */ if (!msg_data->func) return FM10K_ERR_PARAM; /* parser is optional */ attr = msg_data->attr; if (attr) { while (attr->id != FM10K_TLV_ERROR) { id = attr->id; attr++; /* ID should always be increasing */ if (id >= attr->id) return FM10K_ERR_PARAM; /* ID should fit in results array */ if (id >= FM10K_TLV_RESULTS_MAX) return FM10K_ERR_PARAM; } /* verify terminator is in the list */ if (attr->id != FM10K_TLV_ERROR) return FM10K_ERR_PARAM; } id = msg_data->id; msg_data++; /* ID should always be increasing */ if (id >= msg_data->id) return FM10K_ERR_PARAM; } /* verify terminator is in the list */ if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func) return FM10K_ERR_PARAM; return FM10K_SUCCESS; } /** * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox * @mbx: pointer to mailbox * @msg_data: handlers for mailbox events * * This function associates a set of message handling ops with a mailbox. **/ STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx, const struct fm10k_msg_data *msg_data) { DEBUGFUNC("fm10k_mbx_register_handlers"); /* validate layout of handlers before assigning them */ if (fm10k_mbx_validate_handlers(msg_data)) return FM10K_ERR_PARAM; /* initialize the message handlers */ mbx->msg_data = msg_data; return FM10K_SUCCESS; } /** * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox * @hw: pointer to hardware structure * @mbx: pointer to mailbox * @msg_data: handlers for mailbox events * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes * * This function initializes the mailbox for use. It will split the * buffer provided an use that th populate both the Tx and Rx FIFO by * evenly splitting it. In order to allow for easy masking of head/tail * the value reported in size must be a power of 2 and is reported in * DWORDs, not bytes. Any invalid values will cause the mailbox to return * error. **/ s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, const struct fm10k_msg_data *msg_data, u8 id) { DEBUGFUNC("fm10k_pfvf_mbx_init"); /* initialize registers */ switch (hw->mac.type) { case fm10k_mac_vf: mbx->mbx_reg = FM10K_VFMBX; mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR); break; case fm10k_mac_pf: /* there are only 64 VF <-> PF mailboxes */ if (id < 64) { mbx->mbx_reg = FM10K_MBX(id); mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0); break; } /* fallthough */ default: return FM10K_MBX_ERR_NO_MBX; } /* start out in closed state */ mbx->state = FM10K_STATE_CLOSED; /* validate layout of handlers before assigning them */ if (fm10k_mbx_validate_handlers(msg_data)) return FM10K_ERR_PARAM; /* initialize the message handlers */ mbx->msg_data = msg_data; /* start mailbox as timed out and let the reset_hw call * set the timeout value to begin communications */ mbx->timeout = 0; mbx->usec_delay = FM10K_MBX_INIT_DELAY; /* initialize tail and head */ mbx->tail = 1; mbx->head = 1; /* initialize CRC seeds */ mbx->local = FM10K_MBX_CRC_SEED; mbx->remote = FM10K_MBX_CRC_SEED; /* Split buffer for use by Tx/Rx FIFOs */ mbx->max_size = FM10K_MBX_MSG_MAX_SIZE; mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR; /* initialize the FIFOs, sizes are in 4 byte increments */ fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE); fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE], FM10K_MBX_RX_BUFFER_SIZE); /* initialize function pointers */ mbx->ops.connect = fm10k_mbx_connect; mbx->ops.disconnect = fm10k_mbx_disconnect; mbx->ops.rx_ready = fm10k_mbx_rx_ready; mbx->ops.tx_ready = fm10k_mbx_tx_ready; mbx->ops.tx_complete = fm10k_mbx_tx_complete; mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx; mbx->ops.process = fm10k_mbx_process; mbx->ops.register_handlers = fm10k_mbx_register_handlers; return FM10K_SUCCESS; } /** * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO * @mbx: pointer to mailbox * * This function returns a connection mailbox header **/ STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx) { if (mbx->tail_len) mbx->mbx_lock |= FM10K_MBX_REQ; mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) | FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) | FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD); } /** * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO * @mbx: pointer to mailbox * @err: error flags to report if any * * This function returns a connection mailbox header **/ STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err) { if (mbx->local) mbx->mbx_lock |= FM10K_MBX_REQ; mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) | FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) | FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) | FM10K_MSG_HDR_FIELD_SET(err, SM_ERR); } /** * fm10k_sm_mbx_connect_reset - Reset following request for reset * @mbx: pointer to mailbox * * This function resets the mailbox to a just connected state **/ STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx) { /* flush any uncompleted work */ fm10k_mbx_reset_work(mbx); /* set local version to max and remote version to 0 */ mbx->local = FM10K_SM_MBX_VERSION; mbx->remote = 0; /* initialize tail and head */ mbx->tail = 1; mbx->head = 1; /* reset state back to connect */ mbx->state = FM10K_STATE_CONNECT; } /** * fm10k_sm_mbx_connect - Start switch manager mailbox connection * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will initiate a mailbox connection with the switch * manager. To do this it will first disconnect the mailbox, and then * reconnect it in order to complete a reset of the mailbox. * * This function will return an error if the mailbox has not been initiated * or is currently in use. **/ STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { DEBUGFUNC("fm10k_mbx_connect"); /* we cannot connect an uninitialized mailbox */ if (!mbx->rx.buffer) return FM10K_MBX_ERR_NO_SPACE; /* we cannot connect an already connected mailbox */ if (mbx->state != FM10K_STATE_CLOSED) return FM10K_MBX_ERR_BUSY; /* mailbox timeout can now become active */ mbx->timeout = FM10K_MBX_INIT_TIMEOUT; /* Place mbx in ready to connect state */ mbx->state = FM10K_STATE_CONNECT; mbx->max_size = FM10K_MBX_MSG_MAX_SIZE; /* reset interface back to connect */ fm10k_sm_mbx_connect_reset(mbx); /* enable interrupt and notify other party of new message */ mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT | FM10K_MBX_INTERRUPT_ENABLE; /* generate and load connect header into mailbox */ fm10k_sm_mbx_create_connect_hdr(mbx, 0); fm10k_mbx_write(hw, mbx); /* enable interrupt and notify other party of new message */ return FM10K_SUCCESS; } /** * fm10k_sm_mbx_disconnect - Shutdown mailbox connection * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will shut down the mailbox. It places the mailbox first * in the disconnect state, it then allows up to a predefined timeout for * the mailbox to transition to close on its own. If this does not occur * then the mailbox will be forced into the closed state. * * Any mailbox transactions not completed before calling this function * are not guaranteed to complete and may be dropped. **/ STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0; DEBUGFUNC("fm10k_sm_mbx_disconnect"); /* Place mbx in ready to disconnect state */ mbx->state = FM10K_STATE_DISCONNECT; /* trigger interrupt to start shutdown process */ FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ | FM10K_MBX_INTERRUPT_DISABLE); do { usec_delay(FM10K_MBX_POLL_DELAY); mbx->ops.process(hw, mbx); timeout -= FM10K_MBX_POLL_DELAY; } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED)); /* in case we didn't close just force the mailbox into shutdown */ mbx->state = FM10K_STATE_CLOSED; mbx->remote = 0; fm10k_mbx_reset_work(mbx); fm10k_mbx_update_max_size(mbx, 0); FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0); } /** * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header * @mbx: pointer to mailbox * * This function will parse up the fields in the mailbox header and return * an error if the header contains any of a number of invalid configurations * including unrecognized offsets or version numbers. **/ STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx) { const u32 *hdr = &mbx->mbx_hdr; u16 tail, head, ver; DEBUGFUNC("fm10k_mbx_validate_msg_hdr"); tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL); ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER); head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD); switch (ver) { case 0: break; case FM10K_SM_MBX_VERSION: if (!head || head > FM10K_SM_MBX_FIFO_LEN) return FM10K_MBX_ERR_HEAD; if (!tail || tail > FM10K_SM_MBX_FIFO_LEN) return FM10K_MBX_ERR_TAIL; if (mbx->tail < head) head += mbx->mbmem_len - 1; if (tail < mbx->head) tail += mbx->mbmem_len - 1; if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len) return FM10K_MBX_ERR_HEAD; if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len) break; return FM10K_MBX_ERR_TAIL; default: return FM10K_MBX_ERR_SRC; } return FM10K_SUCCESS; } /** * fm10k_sm_mbx_process_error - Process header with error flag set * @mbx: pointer to mailbox * * This function is meant to respond to a request where the error flag * is set. As a result we will terminate a connection if one is present * and fall back into the reset state with a connection header of version * 0 (RESET). **/ STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx) { const enum fm10k_mbx_state state = mbx->state; switch (state) { case FM10K_STATE_DISCONNECT: /* if there is an error just disconnect */ mbx->remote = 0; break; case FM10K_STATE_OPEN: /* flush any uncompleted work */ fm10k_sm_mbx_connect_reset(mbx); break; case FM10K_STATE_CONNECT: /* try connnecting at lower version */ if (mbx->remote) { while (mbx->local > 1) mbx->local--; mbx->remote = 0; } break; default: break; } fm10k_sm_mbx_create_connect_hdr(mbx, 0); } /** * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr * @mbx: pointer to mailbox * @err: local error encountered * * This function will interpret the error provided by err, and based on * that it may set the error bit in the local message header **/ STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err) { /* only generate an error message for these types */ switch (err) { case FM10K_MBX_ERR_TAIL: case FM10K_MBX_ERR_HEAD: case FM10K_MBX_ERR_SRC: case FM10K_MBX_ERR_SIZE: case FM10K_MBX_ERR_RSVD0: break; default: return; } /* process it as though we received an error, and send error reply */ fm10k_sm_mbx_process_error(mbx); fm10k_sm_mbx_create_connect_hdr(mbx, 1); } /** * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will dequeue one message from the Rx switch manager mailbox * FIFO and place it in the Rx mailbox FIFO for processing by software. **/ STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 tail) { /* reduce length by 1 to convert to a mask */ u16 mbmem_len = mbx->mbmem_len - 1; s32 err; DEBUGFUNC("fm10k_sm_mbx_receive"); /* push tail in front of head */ if (tail < mbx->head) tail += mbmem_len; /* copy data to the Rx FIFO */ err = fm10k_mbx_push_tail(hw, mbx, tail); if (err < 0) return err; /* process messages if we have received any */ fm10k_mbx_dequeue_rx(hw, mbx); /* guarantee head aligns with the end of the last message */ mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed); mbx->pushed = 0; /* clear any extra bits left over since index adds 1 extra bit */ if (mbx->head > mbmem_len) mbx->head -= mbmem_len; return err; } /** * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will dequeue one message from the Tx mailbox FIFO and place * it in the Tx switch manager mailbox FIFO for processing by hardware. **/ STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 head) { struct fm10k_mbx_fifo *fifo = &mbx->tx; /* reduce length by 1 to convert to a mask */ u16 mbmem_len = mbx->mbmem_len - 1; u16 tail_len, len = 0; u32 *msg; DEBUGFUNC("fm10k_sm_mbx_transmit"); /* push head behind tail */ if (mbx->tail < head) head += mbmem_len; fm10k_mbx_pull_head(hw, mbx, head); /* determine msg aligned offset for end of buffer */ do { msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len); tail_len = len; len += FM10K_TLV_DWORD_LEN(*msg); } while ((len <= mbx->tail_len) && (len < mbmem_len)); /* guarantee we stop on a message boundary */ if (mbx->tail_len > tail_len) { mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len); mbx->tail_len = tail_len; } /* clear any extra bits left over since index adds 1 extra bit */ if (mbx->tail > mbmem_len) mbx->tail -= mbmem_len; } /** * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head * @mbx: pointer to mailbox * @head: acknowledgement number * * This function will generate an outgoing message based on the current * mailbox state and the remote fifo head. It will return the length * of the outgoing message excluding header on success, and a negative value * on error. **/ STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, u16 head) { switch (mbx->state) { case FM10K_STATE_OPEN: case FM10K_STATE_DISCONNECT: /* flush out Tx data */ fm10k_sm_mbx_transmit(hw, mbx, head); /* generate new header based on data */ if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) { fm10k_sm_mbx_create_data_hdr(mbx); } else { mbx->remote = 0; fm10k_sm_mbx_create_connect_hdr(mbx, 0); } break; case FM10K_STATE_CONNECT: case FM10K_STATE_CLOSED: fm10k_sm_mbx_create_connect_hdr(mbx, 0); break; default: break; } } /** * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET) * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function is meant to respond to a request where the version data * is set to 0. As such we will either terminate the connection or go * into the connect state in order to re-establish the connection. This * function can also be used to respond to an error as the connection * resetting would also be a means of dealing with errors. **/ STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const enum fm10k_mbx_state state = mbx->state; switch (state) { case FM10K_STATE_DISCONNECT: /* drop remote connections and disconnect */ mbx->state = FM10K_STATE_CLOSED; mbx->remote = 0; mbx->local = 0; break; case FM10K_STATE_OPEN: /* flush any incomplete work */ fm10k_sm_mbx_connect_reset(mbx); break; case FM10K_STATE_CONNECT: /* Update remote value to match local value */ mbx->remote = mbx->local; default: break; } fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail); } /** * fm10k_sm_mbx_process_version_1 - Process header with version == 1 * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function is meant to process messages received when the remote * mailbox is active. **/ STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { const u32 *hdr = &mbx->mbx_hdr; u16 head, tail; s32 len; /* pull all fields needed for verification */ tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL); head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD); /* if we are in connect and wanting version 1 then start up and go */ if (mbx->state == FM10K_STATE_CONNECT) { if (!mbx->remote) goto send_reply; if (mbx->remote != 1) return FM10K_MBX_ERR_SRC; mbx->state = FM10K_STATE_OPEN; } do { /* abort on message size errors */ len = fm10k_sm_mbx_receive(hw, mbx, tail); if (len < 0) return len; /* continue until we have flushed the Rx FIFO */ } while (len); send_reply: fm10k_sm_mbx_create_reply(hw, mbx, head); return FM10K_SUCCESS; } /** * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt * @hw: pointer to hardware structure * @mbx: pointer to mailbox * * This function will process incoming mailbox events and generate mailbox * replies. It will return a value indicating the number of DWORDs * transmitted excluding header on success or a negative value on error. **/ STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) { s32 err; DEBUGFUNC("fm10k_sm_mbx_process"); /* we do not read mailbox if closed */ if (mbx->state == FM10K_STATE_CLOSED) return FM10K_SUCCESS; /* retrieve data from switch manager */ err = fm10k_mbx_read(hw, mbx); if (err) return err; err = fm10k_sm_mbx_validate_fifo_hdr(mbx); if (err < 0) goto fifo_err; if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) { fm10k_sm_mbx_process_error(mbx); goto fifo_err; } switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) { case 0: fm10k_sm_mbx_process_reset(hw, mbx); break; case FM10K_SM_MBX_VERSION: err = fm10k_sm_mbx_process_version_1(hw, mbx); break; } fifo_err: if (err < 0) fm10k_sm_mbx_create_error_msg(mbx, err); /* report data to switch manager */ fm10k_mbx_write(hw, mbx); return err; } /** * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox * @hw: pointer to hardware structure * @mbx: pointer to mailbox * @msg_data: handlers for mailbox events * * This function for now is used to stub out the PF/SM mailbox **/ s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx, const struct fm10k_msg_data *msg_data) { DEBUGFUNC("fm10k_sm_mbx_init"); UNREFERENCED_1PARAMETER(hw); mbx->mbx_reg = FM10K_GMBX; mbx->mbmem_reg = FM10K_MBMEM_PF(0); /* start out in closed state */ mbx->state = FM10K_STATE_CLOSED; /* validate layout of handlers before assigning them */ if (fm10k_mbx_validate_handlers(msg_data)) return FM10K_ERR_PARAM; /* initialize the message handlers */ mbx->msg_data = msg_data; /* start mailbox as timed out and let the reset_hw call * set the timeout value to begin communications */ mbx->timeout = 0; mbx->usec_delay = FM10K_MBX_INIT_DELAY; /* Split buffer for use by Tx/Rx FIFOs */ mbx->max_size = FM10K_MBX_MSG_MAX_SIZE; mbx->mbmem_len = FM10K_MBMEM_PF_XOR; /* initialize the FIFOs, sizes are in 4 byte increments */ fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE); fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE], FM10K_MBX_RX_BUFFER_SIZE); /* initialize function pointers */ mbx->ops.connect = fm10k_sm_mbx_connect; mbx->ops.disconnect = fm10k_sm_mbx_disconnect; mbx->ops.rx_ready = fm10k_mbx_rx_ready; mbx->ops.tx_ready = fm10k_mbx_tx_ready; mbx->ops.tx_complete = fm10k_mbx_tx_complete; mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx; mbx->ops.process = fm10k_sm_mbx_process; mbx->ops.register_handlers = fm10k_mbx_register_handlers; return FM10K_SUCCESS; } ================================================ FILE: drivers/net/fm10k/base/fm10k_mbx.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_MBX_H_ #define _FM10K_MBX_H_ /* forward declaration */ struct fm10k_mbx_info; #include "fm10k_type.h" #include "fm10k_tlv.h" /* PF Mailbox Registers */ #define FM10K_MBMEM(_n) ((_n) + 0x18000) #define FM10K_MBMEM_VF(_n, _m) (((_n) * 0x10) + (_m) + 0x18000) #define FM10K_MBMEM_SM(_n) ((_n) + 0x18400) #define FM10K_MBMEM_PF(_n) ((_n) + 0x18600) /* XOR provides means of switching from Tx to Rx FIFO */ #define FM10K_MBMEM_PF_XOR (FM10K_MBMEM_SM(0) ^ FM10K_MBMEM_PF(0)) #define FM10K_MBX(_n) ((_n) + 0x18800) #define FM10K_MBX_OWNER 0x00000001 #define FM10K_MBX_REQ 0x00000002 #define FM10K_MBX_ACK 0x00000004 #define FM10K_MBX_REQ_INTERRUPT 0x00000008 #define FM10K_MBX_ACK_INTERRUPT 0x00000010 #define FM10K_MBX_INTERRUPT_ENABLE 0x00000020 #define FM10K_MBX_INTERRUPT_DISABLE 0x00000040 #define FM10K_MBICR(_n) ((_n) + 0x18840) #define FM10K_GMBX 0x18842 /* VF Mailbox Registers */ #define FM10K_VFMBX 0x00010 #define FM10K_VFMBMEM(_n) ((_n) + 0x00020) #define FM10K_VFMBMEM_LEN 16 #define FM10K_VFMBMEM_VF_XOR (FM10K_VFMBMEM_LEN / 2) /* Delays/timeouts */ #define FM10K_MBX_DISCONNECT_TIMEOUT 500 #define FM10K_MBX_POLL_DELAY 19 #define FM10K_MBX_INT_DELAY 20 #define FM10K_WRITE_MBX(hw, reg, value) FM10K_WRITE_REG(hw, reg, value) /* PF/VF Mailbox state machine * * +----------+ connect() +----------+ * | CLOSED | --------------> | CONNECT | * +----------+ +----------+ * ^ ^ | * | rcv: rcv: | | rcv: * | Connect Disconnect | | Connect * | Disconnect Error | | Data * | | | * | | V * +----------+ disconnect() +----------+ * |DISCONNECT| <-------------- | OPEN | * +----------+ +----------+ * * The diagram above describes the PF/VF mailbox state machine. There * are four main states to this machine. * Closed: This state represents a mailbox that is in a standby state * with interrupts disabled. In this state the mailbox should not * read the mailbox or write any data. The only means of exiting * this state is for the system to make the connect() call for the * mailbox, it will then transition to the connect state. * Connect: In this state the mailbox is seeking a connection. It will * post a connect message with no specified destination and will * wait for a reply from the other side of the mailbox. This state * is exited when either a connect with the local mailbox as the * destination is received or when a data message is received with * a valid sequence number. * Open: In this state the mailbox is able to transfer data between the local * entity and the remote. It will fall back to connect in the event of * receiving either an error message, or a disconnect message. It will * transition to disconnect on a call to disconnect(); * Disconnect: In this state the mailbox is attempting to gracefully terminate * the connection. It will do so at the first point where it knows * that the remote endpoint is either done sending, or when the * remote endpoint has fallen back into connect. */ enum fm10k_mbx_state { FM10K_STATE_CLOSED, FM10K_STATE_CONNECT, FM10K_STATE_OPEN, FM10K_STATE_DISCONNECT, }; /* PF/VF Mailbox header format * 3 2 1 0 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Size/Err_no/CRC | Rsvd0 | Head | Tail | Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * The layout above describes the format for the header used in the PF/VF * mailbox. The header is broken out into the following fields: * Type: There are 4 supported message types * 0x8: Data header - used to transport message data * 0xC: Connect header - used to establish connection * 0xD: Disconnect header - used to tear down a connection * 0xE: Error header - used to address message exceptions * Tail: Tail index for local FIFO * Tail index actually consists of two parts. The MSB of * the head is a loop tracker, it is 0 on an even numbered * loop through the FIFO, and 1 on the odd numbered loops. * To get the actual mailbox offset based on the tail it * is necessary to add bit 3 to bit 0 and clear bit 3. This * gives us a valid range of 0x1 - 0xE. * Head: Head index for remote FIFO * Head index follows the same format as the tail index. * Rsvd0: Reserved 0 portion of the mailbox header * CRC: Running CRC for all data since connect plus current message header * Size: Maximum message size - Applies only to connect headers * The maximum message size is provided during connect to avoid * jamming the mailbox with messages that do not fit. * Err_no: Error number - Applies only to error headers * The error number provides a indication of the type of error * experienced. */ /* macros for retriving and setting header values */ #define FM10K_MSG_HDR_MASK(name) \ ((0x1u << FM10K_MSG_##name##_SIZE) - 1) #define FM10K_MSG_HDR_FIELD_SET(value, name) \ (((u32)(value) & FM10K_MSG_HDR_MASK(name)) << FM10K_MSG_##name##_SHIFT) #define FM10K_MSG_HDR_FIELD_GET(value, name) \ ((u16)((value) >> FM10K_MSG_##name##_SHIFT) & FM10K_MSG_HDR_MASK(name)) /* offsets shared between all headers */ #define FM10K_MSG_TYPE_SHIFT 0 #define FM10K_MSG_TYPE_SIZE 4 #define FM10K_MSG_TAIL_SHIFT 4 #define FM10K_MSG_TAIL_SIZE 4 #define FM10K_MSG_HEAD_SHIFT 8 #define FM10K_MSG_HEAD_SIZE 4 #define FM10K_MSG_RSVD0_SHIFT 12 #define FM10K_MSG_RSVD0_SIZE 4 /* offsets for data/disconnect headers */ #define FM10K_MSG_CRC_SHIFT 16 #define FM10K_MSG_CRC_SIZE 16 /* offsets for connect headers */ #define FM10K_MSG_CONNECT_SIZE_SHIFT 16 #define FM10K_MSG_CONNECT_SIZE_SIZE 16 /* offsets for error headers */ #define FM10K_MSG_ERR_NO_SHIFT 16 #define FM10K_MSG_ERR_NO_SIZE 16 enum fm10k_msg_type { FM10K_MSG_DATA = 0x8, FM10K_MSG_CONNECT = 0xC, FM10K_MSG_DISCONNECT = 0xD, FM10K_MSG_ERROR = 0xE, }; /* HNI/SM Mailbox FIFO format * 3 2 1 0 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-------+-----------------------+-------+-----------------------+ * | Error | Remote Head |Version| Local Tail | * +-------+-----------------------+-------+-----------------------+ * | | * . Local FIFO Data . * . . * +-------+-----------------------+-------+-----------------------+ * * The layout above describes the format for the FIFOs used by the host * network interface and the switch manager to communicate messages back * and forth. Both the HNI and the switch maintain one such FIFO. The * layout in memory has the switch manager FIFO followed immediately by * the HNI FIFO. For this reason I am using just the pointer to the * HNI FIFO in the mailbox ops as the offset between the two is fixed. * * The header for the FIFO is broken out into the following fields: * Local Tail: Offset into FIFO region for next DWORD to write. * Version: Version info for mailbox, only values of 0/1 are supported. * Remote Head: Offset into remote FIFO to indicate how much we have read. * Error: Error indication, values TBD. */ /* version number for switch manager mailboxes */ #define FM10K_SM_MBX_VERSION 1 #define FM10K_SM_MBX_FIFO_LEN (FM10K_MBMEM_PF_XOR - 1) #define FM10K_SM_MBX_FIFO_HDR_LEN 1 /* offsets shared between all SM FIFO headers */ #define FM10K_MSG_SM_TAIL_SHIFT 0 #define FM10K_MSG_SM_TAIL_SIZE 12 #define FM10K_MSG_SM_VER_SHIFT 12 #define FM10K_MSG_SM_VER_SIZE 4 #define FM10K_MSG_SM_HEAD_SHIFT 16 #define FM10K_MSG_SM_HEAD_SIZE 12 #define FM10K_MSG_SM_ERR_SHIFT 28 #define FM10K_MSG_SM_ERR_SIZE 4 /* All error messages returned by mailbox functions * The value -511 is 0xFE01 in hex. The idea is to order the errors * from 0xFE01 - 0xFEFF so error codes are easily visible in the mailbox * messages. This also helps to avoid error number collisions as Linux * doesn't appear to use error numbers 256 - 511. */ #define FM10K_MBX_ERR(_n) ((_n) - 512) #define FM10K_MBX_ERR_NO_MBX FM10K_MBX_ERR(0x01) #define FM10K_MBX_ERR_NO_MSG FM10K_MBX_ERR(0x02) #define FM10K_MBX_ERR_NO_SPACE FM10K_MBX_ERR(0x03) #define FM10K_MBX_ERR_LOCK FM10K_MBX_ERR(0x04) #define FM10K_MBX_ERR_TAIL FM10K_MBX_ERR(0x05) #define FM10K_MBX_ERR_HEAD FM10K_MBX_ERR(0x06) #define FM10K_MBX_ERR_DST FM10K_MBX_ERR(0x07) #define FM10K_MBX_ERR_SRC FM10K_MBX_ERR(0x08) #define FM10K_MBX_ERR_TYPE FM10K_MBX_ERR(0x09) #define FM10K_MBX_ERR_LEN FM10K_MBX_ERR(0x0A) #define FM10K_MBX_ERR_SIZE FM10K_MBX_ERR(0x0B) #define FM10K_MBX_ERR_BUSY FM10K_MBX_ERR(0x0C) #define FM10K_MBX_ERR_VALUE FM10K_MBX_ERR(0x0D) #define FM10K_MBX_ERR_RSVD0 FM10K_MBX_ERR(0x0E) #define FM10K_MBX_ERR_CRC FM10K_MBX_ERR(0x0F) #define FM10K_MBX_CRC_SEED 0xFFFF struct fm10k_mbx_ops { s32 (*connect)(struct fm10k_hw *, struct fm10k_mbx_info *); void (*disconnect)(struct fm10k_hw *, struct fm10k_mbx_info *); bool (*rx_ready)(struct fm10k_mbx_info *); bool (*tx_ready)(struct fm10k_mbx_info *, u16); bool (*tx_complete)(struct fm10k_mbx_info *); s32 (*enqueue_tx)(struct fm10k_hw *, struct fm10k_mbx_info *, const u32 *); s32 (*process)(struct fm10k_hw *, struct fm10k_mbx_info *); s32 (*register_handlers)(struct fm10k_mbx_info *, const struct fm10k_msg_data *); }; struct fm10k_mbx_fifo { u32 *buffer; u16 head; u16 tail; u16 size; }; /* size of buffer to be stored in mailbox for FIFOs */ #define FM10K_MBX_TX_BUFFER_SIZE 512 #define FM10K_MBX_RX_BUFFER_SIZE 128 #define FM10K_MBX_BUFFER_SIZE \ (FM10K_MBX_TX_BUFFER_SIZE + FM10K_MBX_RX_BUFFER_SIZE) /* minimum and maximum message size in dwords */ #define FM10K_MBX_MSG_MAX_SIZE \ ((FM10K_MBX_TX_BUFFER_SIZE - 1) & (FM10K_MBX_RX_BUFFER_SIZE - 1)) #define FM10K_VFMBX_MSG_MTU ((FM10K_VFMBMEM_LEN / 2) - 1) #define FM10K_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define FM10K_MBX_INIT_DELAY 500 /* microseconds between retries */ struct fm10k_mbx_info { /* function pointers for mailbox operations */ struct fm10k_mbx_ops ops; const struct fm10k_msg_data *msg_data; /* message FIFOs */ struct fm10k_mbx_fifo rx; struct fm10k_mbx_fifo tx; /* delay for handling timeouts */ u32 timeout; u32 usec_delay; /* mailbox state info */ u32 mbx_reg, mbmem_reg, mbx_lock, mbx_hdr; u16 max_size, mbmem_len; u16 tail, tail_len, pulled; u16 head, head_len, pushed; u16 local, remote; enum fm10k_mbx_state state; /* result of last mailbox test */ s32 test_result; /* statistics */ u64 tx_busy; u64 tx_dropped; u64 tx_messages; u64 tx_dwords; u64 rx_messages; u64 rx_dwords; u64 rx_parse_err; /* Buffer to store messages */ u32 buffer[FM10K_MBX_BUFFER_SIZE]; }; s32 fm10k_pfvf_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *, const struct fm10k_msg_data *, u8); s32 fm10k_sm_mbx_init(struct fm10k_hw *, struct fm10k_mbx_info *, const struct fm10k_msg_data *); #endif /* _FM10K_MBX_H_ */ ================================================ FILE: drivers/net/fm10k/base/fm10k_osdep.h ================================================ /******************************************************************************* Copyright (c) 2013-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_OSDEP_H_ #define _FM10K_OSDEP_H_ #include #include #include #include #include #include "../fm10k_logs.h" /* TODO: this does not look like it should be used... */ #define ERROR_REPORT2(v1, v2, v3) do { } while (0) #define STATIC static #define DEBUGFUNC(F) DEBUGOUT(F "\n"); #define DEBUGOUT(S, args...) PMD_DRV_LOG_RAW(DEBUG, S, ##args) #define DEBUGOUT1(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT2(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT3(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT6(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT7(S, args...) DEBUGOUT(S, ##args) #define FALSE 0 #define TRUE 1 #ifndef false #define false FALSE #endif #ifndef true #define true TRUE #endif typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef int16_t s16; typedef uint32_t u32; typedef int32_t s32; typedef int64_t s64; typedef uint64_t u64; typedef int bool; #ifndef __le16 #define __le16 u16 #define __le32 u32 #define __le64 u64 #endif #ifndef __be16 #define __be16 u16 #define __be32 u32 #define __be64 u64 #endif /* offsets are WORD offsets, not BYTE offsets */ #define FM10K_WRITE_REG(hw, reg, val) \ ((((volatile uint32_t *)(hw)->hw_addr)[(reg)]) = ((uint32_t)(val))) #define FM10K_READ_REG(hw, reg) \ (((volatile uint32_t *)(hw)->hw_addr)[(reg)]) #define FM10K_WRITE_FLUSH(a) FM10K_READ_REG(a, FM10K_CTRL) #define FM10K_PCI_REG(reg) (*((volatile uint32_t *)(reg))) #define FM10K_PCI_REG_WRITE(reg, value) do { \ FM10K_PCI_REG((reg)) = (value); \ } while (0) /* not implemented */ #define FM10K_READ_PCI_WORD(hw, reg) 0 #define FM10K_WRITE_MBX(hw, reg, value) FM10K_WRITE_REG(hw, reg, value) #define FM10K_READ_MBX(hw, reg) FM10K_READ_REG(hw, reg) #define FM10K_LE16_TO_CPU rte_le_to_cpu_16 #define FM10K_LE32_TO_CPU rte_le_to_cpu_32 #define FM10K_CPU_TO_LE32 rte_cpu_to_le_32 #define FM10K_CPU_TO_LE16 rte_cpu_to_le_16 #define FM10K_RMB rte_rmb #define FM10K_WMB rte_wmb #define usec_delay rte_delay_us #define FM10K_REMOVED(hw_addr) (!(hw_addr)) #ifndef FM10K_IS_ZERO_ETHER_ADDR /* make certain address is not 0 */ #define FM10K_IS_ZERO_ETHER_ADDR(addr) \ (!((addr)[0] | (addr)[1] | (addr)[2] | (addr)[3] | (addr)[4] | (addr)[5])) #endif #ifndef FM10K_IS_MULTICAST_ETHER_ADDR #define FM10K_IS_MULTICAST_ETHER_ADDR(addr) ((addr)[0] & 0x1) #endif #ifndef FM10K_IS_VALID_ETHER_ADDR /* make certain address is not multicast or 0 */ #define FM10K_IS_VALID_ETHER_ADDR(addr) \ (!FM10K_IS_MULTICAST_ETHER_ADDR(addr) && !FM10K_IS_ZERO_ETHER_ADDR(addr)) #endif #ifndef do_div #define do_div(n, base) ({\ (n) = (n) / (base);\ }) #endif /* do_div */ /* DPDK can't access IOMEM directly */ #ifndef FM10K_WRITE_SW_REG #define FM10K_WRITE_SW_REG(v1, v2, v3) do { } while (0) #endif #ifndef fm10k_read_reg #define fm10k_read_reg FM10K_READ_REG #endif #endif /* _FM10K_OSDEP_H_ */ ================================================ FILE: drivers/net/fm10k/base/fm10k_pf.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_pf.h" #include "fm10k_vf.h" /** * fm10k_reset_hw_pf - PF hardware reset * @hw: pointer to hardware structure * * This function should return the hardware to a state similar to the * one it is in after being powered on. **/ STATIC s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) { s32 err; u32 reg; u16 i; DEBUGFUNC("fm10k_reset_hw_pf"); /* Disable interrupts */ FM10K_WRITE_REG(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(ALL)); /* Lock ITR2 reg 0 into itself and disable interrupt moderation */ FM10K_WRITE_REG(hw, FM10K_ITR2(0), 0); FM10K_WRITE_REG(hw, FM10K_INT_CTRL, 0); /* We assume here Tx and Rx queue 0 are owned by the PF */ /* Shut off VF access to their queues forcing them to queue 0 */ for (i = 0; i < FM10K_TQMAP_TABLE_SIZE; i++) { FM10K_WRITE_REG(hw, FM10K_TQMAP(i), 0); FM10K_WRITE_REG(hw, FM10K_RQMAP(i), 0); } /* shut down all rings */ err = fm10k_disable_queues_generic(hw, FM10K_MAX_QUEUES); if (err) return err; /* Verify that DMA is no longer active */ reg = FM10K_READ_REG(hw, FM10K_DMA_CTRL); if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE)) return FM10K_ERR_DMA_PENDING; /* verify the switch is ready for reset */ reg = FM10K_READ_REG(hw, FM10K_DMA_CTRL2); if (!(reg & FM10K_DMA_CTRL2_SWITCH_READY)) goto out; /* Inititate data path reset */ reg |= FM10K_DMA_CTRL_DATAPATH_RESET; FM10K_WRITE_REG(hw, FM10K_DMA_CTRL, reg); /* Flush write and allow 100us for reset to complete */ FM10K_WRITE_FLUSH(hw); usec_delay(FM10K_RESET_TIMEOUT); /* Verify we made it out of reset */ reg = FM10K_READ_REG(hw, FM10K_IP); if (!(reg & FM10K_IP_NOTINRESET)) err = FM10K_ERR_RESET_FAILED; out: return err; } /** * fm10k_is_ari_hierarchy_pf - Indicate ARI hierarchy support * @hw: pointer to hardware structure * * Looks at the ARI hierarchy bit to determine whether ARI is supported or not. **/ STATIC bool fm10k_is_ari_hierarchy_pf(struct fm10k_hw *hw) { u16 sriov_ctrl = FM10K_READ_PCI_WORD(hw, FM10K_PCIE_SRIOV_CTRL); DEBUGFUNC("fm10k_is_ari_hierarchy_pf"); return !!(sriov_ctrl & FM10K_PCIE_SRIOV_CTRL_VFARI); } /** * fm10k_init_hw_pf - PF hardware initialization * @hw: pointer to hardware structure * **/ STATIC s32 fm10k_init_hw_pf(struct fm10k_hw *hw) { u32 dma_ctrl, txqctl; u16 i; DEBUGFUNC("fm10k_init_hw_pf"); /* Establish default VSI as valid */ FM10K_WRITE_REG(hw, FM10K_DGLORTDEC(fm10k_dglort_default), 0); FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(fm10k_dglort_default), FM10K_DGLORTMAP_ANY); /* Invalidate all other GLORT entries */ for (i = 1; i < FM10K_DGLORT_COUNT; i++) FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(i), FM10K_DGLORTMAP_NONE); /* reset ITR2(0) to point to itself */ FM10K_WRITE_REG(hw, FM10K_ITR2(0), 0); /* reset VF ITR2(0) to point to 0 avoid PF registers */ FM10K_WRITE_REG(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), 0); /* loop through all PF ITR2 registers pointing them to the previous */ for (i = 1; i < FM10K_ITR_REG_COUNT_PF; i++) FM10K_WRITE_REG(hw, FM10K_ITR2(i), i - 1); /* Enable interrupt moderator if not already enabled */ FM10K_WRITE_REG(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR); /* compute the default txqctl configuration */ txqctl = FM10K_TXQCTL_PF | FM10K_TXQCTL_UNLIMITED_BW | (hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT); for (i = 0; i < FM10K_MAX_QUEUES; i++) { /* configure rings for 256 Queue / 32 Descriptor cache mode */ FM10K_WRITE_REG(hw, FM10K_TQDLOC(i), (i * FM10K_TQDLOC_BASE_32_DESC) | FM10K_TQDLOC_SIZE_32_DESC); FM10K_WRITE_REG(hw, FM10K_TXQCTL(i), txqctl); /* configure rings to provide TPH processing hints */ FM10K_WRITE_REG(hw, FM10K_TPH_TXCTRL(i), FM10K_TPH_TXCTRL_DESC_TPHEN | FM10K_TPH_TXCTRL_DESC_RROEN | FM10K_TPH_TXCTRL_DESC_WROEN | FM10K_TPH_TXCTRL_DATA_RROEN); FM10K_WRITE_REG(hw, FM10K_TPH_RXCTRL(i), FM10K_TPH_RXCTRL_DESC_TPHEN | FM10K_TPH_RXCTRL_DESC_RROEN | FM10K_TPH_RXCTRL_DATA_WROEN | FM10K_TPH_RXCTRL_HDR_WROEN); } /* set max hold interval to align with 1.024 usec in all modes */ switch (hw->bus.speed) { case fm10k_bus_speed_2500: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1; break; case fm10k_bus_speed_5000: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2; break; case fm10k_bus_speed_8000: dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3; break; default: dma_ctrl = 0; break; } /* Configure TSO flags */ FM10K_WRITE_REG(hw, FM10K_DTXTCPFLGL, FM10K_TSO_FLAGS_LOW); FM10K_WRITE_REG(hw, FM10K_DTXTCPFLGH, FM10K_TSO_FLAGS_HI); /* Enable DMA engine * Set Rx Descriptor size to 32 * Set Minimum MSS to 64 * Set Maximum number of Rx queues to 256 / 32 Descriptor */ dma_ctrl |= FM10K_DMA_CTRL_TX_ENABLE | FM10K_DMA_CTRL_RX_ENABLE | FM10K_DMA_CTRL_RX_DESC_SIZE | FM10K_DMA_CTRL_MINMSS_64 | FM10K_DMA_CTRL_32_DESC; FM10K_WRITE_REG(hw, FM10K_DMA_CTRL, dma_ctrl); /* record maximum queue count, we limit ourselves to 128 */ hw->mac.max_queues = FM10K_MAX_QUEUES_PF; /* We support either 64 VFs or 7 VFs depending on if we have ARI */ hw->iov.total_vfs = fm10k_is_ari_hierarchy_pf(hw) ? 64 : 7; return FM10K_SUCCESS; } /** * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU * @hw: pointer to hardware structure * * Looks at the PCIe bus info to confirm whether or not this slot can support * the necessary bandwidth for this device. **/ STATIC bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw) { DEBUGFUNC("fm10k_is_slot_appropriate_pf"); return (hw->bus.speed == hw->bus_caps.speed) && (hw->bus.width == hw->bus_caps.width); } /** * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table * @hw: pointer to hardware structure * @vid: VLAN ID to add to table * @vsi: Index indicating VF ID or PF ID in table * @set: Indicates if this is a set or clear operation * * This function adds or removes the corresponding VLAN ID from the VLAN * filter table for the corresponding function. In addition to the * standard set/clear that supports one bit a multi-bit write is * supported to set 64 bits at a time. **/ STATIC s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) { u32 vlan_table, reg, mask, bit, len; /* verify the VSI index is valid */ if (vsi > FM10K_VLAN_TABLE_VSI_MAX) return FM10K_ERR_PARAM; /* VLAN multi-bit write: * The multi-bit write has several parts to it. * 3 2 1 0 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | RSVD0 | Length |C|RSVD0| VLAN ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * VLAN ID: Vlan Starting value * RSVD0: Reserved section, must be 0 * C: Flag field, 0 is set, 1 is clear (Used in VF VLAN message) * Length: Number of times to repeat the bit being set */ len = vid >> 16; vid = (vid << 17) >> 17; /* verify the reserved 0 fields are 0 */ if (len >= FM10K_VLAN_TABLE_VID_MAX || vid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; /* Loop through the table updating all required VLANs */ for (reg = FM10K_VLAN_TABLE(vsi, vid / 32), bit = vid % 32; len < FM10K_VLAN_TABLE_VID_MAX; len -= 32 - bit, reg++, bit = 0) { /* record the initial state of the register */ vlan_table = FM10K_READ_REG(hw, reg); /* truncate mask if we are at the start or end of the run */ mask = (~(u32)0 >> ((len < 31) ? 31 - len : 0)) << bit; /* make necessary modifications to the register */ mask &= set ? ~vlan_table : vlan_table; if (mask) FM10K_WRITE_REG(hw, reg, vlan_table ^ mask); } return FM10K_SUCCESS; } /** * fm10k_read_mac_addr_pf - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the SM_AREA and stores the value. **/ STATIC s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw) { u8 perm_addr[ETH_ALEN]; u32 serial_num; int i; DEBUGFUNC("fm10k_read_mac_addr_pf"); serial_num = FM10K_READ_REG(hw, FM10K_SM_AREA(1)); /* last byte should be all 1's */ if ((~serial_num) << 24) return FM10K_ERR_INVALID_MAC_ADDR; perm_addr[0] = (u8)(serial_num >> 24); perm_addr[1] = (u8)(serial_num >> 16); perm_addr[2] = (u8)(serial_num >> 8); serial_num = FM10K_READ_REG(hw, FM10K_SM_AREA(0)); /* first byte should be all 1's */ if ((~serial_num) >> 24) return FM10K_ERR_INVALID_MAC_ADDR; perm_addr[3] = (u8)(serial_num >> 16); perm_addr[4] = (u8)(serial_num >> 8); perm_addr[5] = (u8)(serial_num); for (i = 0; i < ETH_ALEN; i++) { hw->mac.perm_addr[i] = perm_addr[i]; hw->mac.addr[i] = perm_addr[i]; } return FM10K_SUCCESS; } /** * fm10k_glort_valid_pf - Validate that the provided glort is valid * @hw: pointer to the HW structure * @glort: base glort to be validated * * This function will return an error if the provided glort is invalid **/ bool fm10k_glort_valid_pf(struct fm10k_hw *hw, u16 glort) { glort &= hw->mac.dglort_map >> FM10K_DGLORTMAP_MASK_SHIFT; return glort == (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE); } /** * fm10k_update_xc_addr_pf - Update device addresses * @hw: pointer to the HW structure * @glort: base resource tag for this request * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * @flags: flags field to indicate add and secure * * This function generates a message to the Switch API requesting * that the given logical port add/remove the given L2 MAC/VLAN address. **/ STATIC s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, const u8 *mac, u16 vid, bool add, u8 flags) { struct fm10k_mbx_info *mbx = &hw->mbx; struct fm10k_mac_update mac_update; u32 msg[5]; DEBUGFUNC("fm10k_update_xc_addr_pf"); /* if glort or VLAN are not valid return error */ if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; /* record fields */ mac_update.mac_lower = FM10K_CPU_TO_LE32(((u32)mac[2] << 24) | ((u32)mac[3] << 16) | ((u32)mac[4] << 8) | ((u32)mac[5])); mac_update.mac_upper = FM10K_CPU_TO_LE16(((u32)mac[0] << 8) | ((u32)mac[1])); mac_update.vlan = FM10K_CPU_TO_LE16(vid); mac_update.glort = FM10K_CPU_TO_LE16(glort); mac_update.action = add ? 0 : 1; mac_update.flags = flags; /* populate mac_update fields */ fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_UPDATE_MAC_FWD_RULE); fm10k_tlv_attr_put_le_struct(msg, FM10K_PF_ATTR_ID_MAC_UPDATE, &mac_update, sizeof(mac_update)); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_update_uc_addr_pf - Update device unicast addresses * @hw: pointer to the HW structure * @glort: base resource tag for this request * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * @flags: flags field to indicate add and secure * * This function is used to add or remove unicast addresses for * the PF. **/ STATIC s32 fm10k_update_uc_addr_pf(struct fm10k_hw *hw, u16 glort, const u8 *mac, u16 vid, bool add, u8 flags) { DEBUGFUNC("fm10k_update_uc_addr_pf"); /* verify MAC address is valid */ if (!FM10K_IS_VALID_ETHER_ADDR(mac)) return FM10K_ERR_PARAM; return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, flags); } /** * fm10k_update_mc_addr_pf - Update device multicast addresses * @hw: pointer to the HW structure * @glort: base resource tag for this request * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * * This function is used to add or remove multicast MAC addresses for * the PF. **/ STATIC s32 fm10k_update_mc_addr_pf(struct fm10k_hw *hw, u16 glort, const u8 *mac, u16 vid, bool add) { DEBUGFUNC("fm10k_update_mc_addr_pf"); /* verify multicast address is valid */ if (!FM10K_IS_MULTICAST_ETHER_ADDR(mac)) return FM10K_ERR_PARAM; return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, 0); } /** * fm10k_update_xcast_mode_pf - Request update of multicast mode * @hw: pointer to hardware structure * @glort: base resource tag for this request * @mode: integer value indicating mode being requested * * This function will attempt to request a higher mode for the port * so that it can enable either multicast, multicast promiscuous, or * promiscuous mode of operation. **/ STATIC s32 fm10k_update_xcast_mode_pf(struct fm10k_hw *hw, u16 glort, u8 mode) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[3], xcast_mode; DEBUGFUNC("fm10k_update_xcast_mode_pf"); if (mode > FM10K_XCAST_MODE_NONE) return FM10K_ERR_PARAM; /* if glort is not valid return error */ if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; /* write xcast mode as a single u32 value, * lower 16 bits: glort * upper 16 bits: mode */ xcast_mode = ((u32)mode << 16) | glort; /* generate message requesting to change xcast mode */ fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_XCAST_MODES); fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_XCAST_MODE, xcast_mode); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_update_int_moderator_pf - Update interrupt moderator linked list * @hw: pointer to hardware structure * * This function walks through the MSI-X vector table to determine the * number of active interrupts and based on that information updates the * interrupt moderator linked list. **/ STATIC void fm10k_update_int_moderator_pf(struct fm10k_hw *hw) { u32 i; /* Disable interrupt moderator */ FM10K_WRITE_REG(hw, FM10K_INT_CTRL, 0); /* loop through PF from last to first looking enabled vectors */ for (i = FM10K_ITR_REG_COUNT_PF - 1; i; i--) { if (!FM10K_READ_REG(hw, FM10K_MSIX_VECTOR_MASK(i))) break; } /* always reset VFITR2[0] to point to last enabled PF vector */ FM10K_WRITE_REG(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), i); /* reset ITR2[0] to point to last enabled PF vector */ if (!hw->iov.num_vfs) FM10K_WRITE_REG(hw, FM10K_ITR2(0), i); /* Enable interrupt moderator */ FM10K_WRITE_REG(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR); } /** * fm10k_update_lport_state_pf - Notify the switch of a change in port state * @hw: pointer to the HW structure * @glort: base resource tag for this request * @count: number of logical ports being updated * @enable: boolean value indicating enable or disable * * This function is used to add/remove a logical port from the switch. **/ STATIC s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort, u16 count, bool enable) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[3], lport_msg; DEBUGFUNC("fm10k_lport_state_pf"); /* do nothing if we are being asked to create or destroy 0 ports */ if (!count) return FM10K_SUCCESS; /* if glort is not valid return error */ if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; /* construct the lport message from the 2 pieces of data we have */ lport_msg = ((u32)count << 16) | glort; /* generate lport create/delete message */ fm10k_tlv_msg_init(msg, enable ? FM10K_PF_MSG_ID_LPORT_CREATE : FM10K_PF_MSG_ID_LPORT_DELETE); fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_PORT, lport_msg); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_configure_dglort_map_pf - Configures GLORT entry and queues * @hw: pointer to hardware structure * @dglort: pointer to dglort configuration structure * * Reads the configuration structure contained in dglort_cfg and uses * that information to then populate a DGLORTMAP/DEC entry and the queues * to which it has been assigned. **/ STATIC s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, struct fm10k_dglort_cfg *dglort) { u16 glort, queue_count, vsi_count, pc_count; u16 vsi, queue, pc, q_idx; u32 txqctl, dglortdec, dglortmap; /* verify the dglort pointer */ if (!dglort) return FM10K_ERR_PARAM; /* verify the dglort values */ if ((dglort->idx > 7) || (dglort->rss_l > 7) || (dglort->pc_l > 3) || (dglort->vsi_l > 6) || (dglort->vsi_b > 64) || (dglort->queue_l > 8) || (dglort->queue_b >= 256)) return FM10K_ERR_PARAM; /* determine count of VSIs and queues */ queue_count = 1 << (dglort->rss_l + dglort->pc_l); vsi_count = 1 << (dglort->vsi_l + dglort->queue_l); glort = dglort->glort; q_idx = dglort->queue_b; /* configure SGLORT for queues */ for (vsi = 0; vsi < vsi_count; vsi++, glort++) { for (queue = 0; queue < queue_count; queue++, q_idx++) { if (q_idx >= FM10K_MAX_QUEUES) break; FM10K_WRITE_REG(hw, FM10K_TX_SGLORT(q_idx), glort); FM10K_WRITE_REG(hw, FM10K_RX_SGLORT(q_idx), glort); } } /* determine count of PCs and queues */ queue_count = 1 << (dglort->queue_l + dglort->rss_l + dglort->vsi_l); pc_count = 1 << dglort->pc_l; /* configure PC for Tx queues */ for (pc = 0; pc < pc_count; pc++) { q_idx = pc + dglort->queue_b; for (queue = 0; queue < queue_count; queue++) { if (q_idx >= FM10K_MAX_QUEUES) break; txqctl = FM10K_READ_REG(hw, FM10K_TXQCTL(q_idx)); txqctl &= ~FM10K_TXQCTL_PC_MASK; txqctl |= pc << FM10K_TXQCTL_PC_SHIFT; FM10K_WRITE_REG(hw, FM10K_TXQCTL(q_idx), txqctl); q_idx += pc_count; } } /* configure DGLORTDEC */ dglortdec = ((u32)(dglort->rss_l) << FM10K_DGLORTDEC_RSSLENGTH_SHIFT) | ((u32)(dglort->queue_b) << FM10K_DGLORTDEC_QBASE_SHIFT) | ((u32)(dglort->pc_l) << FM10K_DGLORTDEC_PCLENGTH_SHIFT) | ((u32)(dglort->vsi_b) << FM10K_DGLORTDEC_VSIBASE_SHIFT) | ((u32)(dglort->vsi_l) << FM10K_DGLORTDEC_VSILENGTH_SHIFT) | ((u32)(dglort->queue_l)); if (dglort->inner_rss) dglortdec |= FM10K_DGLORTDEC_INNERRSS_ENABLE; /* configure DGLORTMAP */ dglortmap = (dglort->idx == fm10k_dglort_default) ? FM10K_DGLORTMAP_ANY : FM10K_DGLORTMAP_ZERO; dglortmap <<= dglort->vsi_l + dglort->queue_l + dglort->shared_l; dglortmap |= dglort->glort; /* write values to hardware */ FM10K_WRITE_REG(hw, FM10K_DGLORTDEC(dglort->idx), dglortdec); FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(dglort->idx), dglortmap); return FM10K_SUCCESS; } u16 fm10k_queues_per_pool(struct fm10k_hw *hw) { u16 num_pools = hw->iov.num_pools; return (num_pools > 32) ? 2 : (num_pools > 16) ? 4 : (num_pools > 8) ? 8 : FM10K_MAX_QUEUES_POOL; } u16 fm10k_vf_queue_index(struct fm10k_hw *hw, u16 vf_idx) { u16 num_vfs = hw->iov.num_vfs; u16 vf_q_idx = FM10K_MAX_QUEUES; vf_q_idx -= fm10k_queues_per_pool(hw) * (num_vfs - vf_idx); return vf_q_idx; } STATIC u16 fm10k_vectors_per_pool(struct fm10k_hw *hw) { u16 num_pools = hw->iov.num_pools; return (num_pools > 32) ? 8 : (num_pools > 16) ? 16 : FM10K_MAX_VECTORS_POOL; } STATIC u16 fm10k_vf_vector_index(struct fm10k_hw *hw, u16 vf_idx) { u16 vf_v_idx = FM10K_MAX_VECTORS_PF; vf_v_idx += fm10k_vectors_per_pool(hw) * vf_idx; return vf_v_idx; } /** * fm10k_iov_assign_resources_pf - Assign pool resources for virtualization * @hw: pointer to the HW structure * @num_vfs: number of VFs to be allocated * @num_pools: number of virtualization pools to be allocated * * Allocates queues and traffic classes to virtualization entities to prepare * the PF for SR-IOV and VMDq **/ STATIC s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, u16 num_pools) { u16 qmap_stride, qpp, vpp, vf_q_idx, vf_q_idx0, qmap_idx; u32 vid = hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT; int i, j; /* hardware only supports up to 64 pools */ if (num_pools > 64) return FM10K_ERR_PARAM; /* the number of VFs cannot exceed the number of pools */ if ((num_vfs > num_pools) || (num_vfs > hw->iov.total_vfs)) return FM10K_ERR_PARAM; /* record number of virtualization entities */ hw->iov.num_vfs = num_vfs; hw->iov.num_pools = num_pools; /* determine qmap offsets and counts */ qmap_stride = (num_vfs > 8) ? 32 : 256; qpp = fm10k_queues_per_pool(hw); vpp = fm10k_vectors_per_pool(hw); /* calculate starting index for queues */ vf_q_idx = fm10k_vf_queue_index(hw, 0); qmap_idx = 0; /* establish TCs with -1 credits and no quanta to prevent transmit */ for (i = 0; i < num_vfs; i++) { FM10K_WRITE_REG(hw, FM10K_TC_MAXCREDIT(i), 0); FM10K_WRITE_REG(hw, FM10K_TC_RATE(i), 0); FM10K_WRITE_REG(hw, FM10K_TC_CREDIT(i), FM10K_TC_CREDIT_CREDIT_MASK); } /* zero out all mbmem registers */ for (i = FM10K_VFMBMEM_LEN * num_vfs; i--;) FM10K_WRITE_REG(hw, FM10K_MBMEM(i), 0); /* clear event notification of VF FLR */ FM10K_WRITE_REG(hw, FM10K_PFVFLREC(0), ~0); FM10K_WRITE_REG(hw, FM10K_PFVFLREC(1), ~0); /* loop through unallocated rings assigning them back to PF */ for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) { FM10K_WRITE_REG(hw, FM10K_TXDCTL(i), 0); FM10K_WRITE_REG(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF | vid); FM10K_WRITE_REG(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF); } /* PF should have already updated VFITR2[0] */ /* update all ITR registers to flow to VFITR2[0] */ for (i = FM10K_ITR_REG_COUNT_PF + 1; i < FM10K_ITR_REG_COUNT; i++) { if (!(i & (vpp - 1))) FM10K_WRITE_REG(hw, FM10K_ITR2(i), i - vpp); else FM10K_WRITE_REG(hw, FM10K_ITR2(i), i - 1); } /* update PF ITR2[0] to reference the last vector */ FM10K_WRITE_REG(hw, FM10K_ITR2(0), fm10k_vf_vector_index(hw, num_vfs - 1)); /* loop through rings populating rings and TCs */ for (i = 0; i < num_vfs; i++) { /* record index for VF queue 0 for use in end of loop */ vf_q_idx0 = vf_q_idx; for (j = 0; j < qpp; j++, qmap_idx++, vf_q_idx++) { /* assign VF and locked TC to queues */ FM10K_WRITE_REG(hw, FM10K_TXDCTL(vf_q_idx), 0); FM10K_WRITE_REG(hw, FM10K_TXQCTL(vf_q_idx), (i << FM10K_TXQCTL_TC_SHIFT) | i | FM10K_TXQCTL_VF | vid); FM10K_WRITE_REG(hw, FM10K_RXDCTL(vf_q_idx), FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | FM10K_RXDCTL_DROP_ON_EMPTY); FM10K_WRITE_REG(hw, FM10K_RXQCTL(vf_q_idx), FM10K_RXQCTL_VF | (i << FM10K_RXQCTL_VF_SHIFT)); /* map queue pair to VF */ FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx), vf_q_idx); } /* repeat the first ring for all of the remaining VF rings */ for (; j < qmap_stride; j++, qmap_idx++) { FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), vf_q_idx0); FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx), vf_q_idx0); } } /* loop through remaining indexes assigning all to queue 0 */ while (qmap_idx < FM10K_TQMAP_TABLE_SIZE) { FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), 0); FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx), 0); qmap_idx++; } return FM10K_SUCCESS; } /** * fm10k_iov_configure_tc_pf - Configure the shaping group for VF * @hw: pointer to the HW structure * @vf_idx: index of VF receiving GLORT * @rate: Rate indicated in Mb/s * * Configured the TC for a given VF to allow only up to a given number * of Mb/s of outgoing Tx throughput. **/ STATIC s32 fm10k_iov_configure_tc_pf(struct fm10k_hw *hw, u16 vf_idx, int rate) { /* configure defaults */ u32 interval = FM10K_TC_RATE_INTERVAL_4US_GEN3; u32 tc_rate = FM10K_TC_RATE_QUANTA_MASK; /* verify vf is in range */ if (vf_idx >= hw->iov.num_vfs) return FM10K_ERR_PARAM; /* set interval to align with 4.096 usec in all modes */ switch (hw->bus.speed) { case fm10k_bus_speed_2500: interval = FM10K_TC_RATE_INTERVAL_4US_GEN1; break; case fm10k_bus_speed_5000: interval = FM10K_TC_RATE_INTERVAL_4US_GEN2; break; default: break; } if (rate) { if (rate > FM10K_VF_TC_MAX || rate < FM10K_VF_TC_MIN) return FM10K_ERR_PARAM; /* The quanta is measured in Bytes per 4.096 or 8.192 usec * The rate is provided in Mbits per second * To tralslate from rate to quanta we need to multiply the * rate by 8.192 usec and divide by 8 bits/byte. To avoid * dealing with floating point we can round the values up * to the nearest whole number ratio which gives us 128 / 125. */ tc_rate = (rate * 128) / 125; /* try to keep the rate limiting accurate by increasing * the number of credits and interval for rates less than 4Gb/s */ if (rate < 4000) interval <<= 1; else tc_rate >>= 1; } /* update rate limiter with new values */ FM10K_WRITE_REG(hw, FM10K_TC_RATE(vf_idx), tc_rate | interval); FM10K_WRITE_REG(hw, FM10K_TC_MAXCREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K); FM10K_WRITE_REG(hw, FM10K_TC_CREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K); return FM10K_SUCCESS; } /** * fm10k_iov_assign_int_moderator_pf - Add VF interrupts to moderator list * @hw: pointer to the HW structure * @vf_idx: index of VF receiving GLORT * * Update the interrupt moderator linked list to include any MSI-X * interrupts which the VF has enabled in the MSI-X vector table. **/ STATIC s32 fm10k_iov_assign_int_moderator_pf(struct fm10k_hw *hw, u16 vf_idx) { u16 vf_v_idx, vf_v_limit, i; /* verify vf is in range */ if (vf_idx >= hw->iov.num_vfs) return FM10K_ERR_PARAM; /* determine vector offset and count */ vf_v_idx = fm10k_vf_vector_index(hw, vf_idx); vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw); /* search for first vector that is not masked */ for (i = vf_v_limit - 1; i > vf_v_idx; i--) { if (!FM10K_READ_REG(hw, FM10K_MSIX_VECTOR_MASK(i))) break; } /* reset linked list so it now includes our active vectors */ if (vf_idx == (hw->iov.num_vfs - 1)) FM10K_WRITE_REG(hw, FM10K_ITR2(0), i); else FM10K_WRITE_REG(hw, FM10K_ITR2(vf_v_limit), i); return FM10K_SUCCESS; } /** * fm10k_iov_assign_default_mac_vlan_pf - Assign a MAC and VLAN to VF * @hw: pointer to the HW structure * @vf_info: pointer to VF information structure * * Assign a MAC address and default VLAN to a VF and notify it of the update **/ STATIC s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, struct fm10k_vf_info *vf_info) { u16 qmap_stride, queues_per_pool, vf_q_idx, timeout, qmap_idx, i; u32 msg[4], txdctl, txqctl, tdbal = 0, tdbah = 0; s32 err = FM10K_SUCCESS; u16 vf_idx, vf_vid; /* verify vf is in range */ if (!vf_info || vf_info->vf_idx >= hw->iov.num_vfs) return FM10K_ERR_PARAM; /* determine qmap offsets and counts */ qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256; queues_per_pool = fm10k_queues_per_pool(hw); /* calculate starting index for queues */ vf_idx = vf_info->vf_idx; vf_q_idx = fm10k_vf_queue_index(hw, vf_idx); qmap_idx = qmap_stride * vf_idx; /* MAP Tx queue back to 0 temporarily, and disable it */ FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), 0); FM10K_WRITE_REG(hw, FM10K_TXDCTL(vf_q_idx), 0); /* determine correct default VLAN ID */ if (vf_info->pf_vid) vf_vid = vf_info->pf_vid | FM10K_VLAN_CLEAR; else vf_vid = vf_info->sw_vid; /* generate MAC_ADDR request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_DEFAULT_MAC, vf_info->mac, vf_vid); /* load onto outgoing mailbox, ignore any errors on enqueue */ if (vf_info->mbx.ops.enqueue_tx) vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); /* verify ring has disabled before modifying base address registers */ txdctl = FM10K_READ_REG(hw, FM10K_TXDCTL(vf_q_idx)); for (timeout = 0; txdctl & FM10K_TXDCTL_ENABLE; timeout++) { /* limit ourselves to a 1ms timeout */ if (timeout == 10) { err = FM10K_ERR_DMA_PENDING; goto err_out; } usec_delay(100); txdctl = FM10K_READ_REG(hw, FM10K_TXDCTL(vf_q_idx)); } /* Update base address registers to contain MAC address */ if (FM10K_IS_VALID_ETHER_ADDR(vf_info->mac)) { tdbal = (((u32)vf_info->mac[3]) << 24) | (((u32)vf_info->mac[4]) << 16) | (((u32)vf_info->mac[5]) << 8); tdbah = (((u32)0xFF) << 24) | (((u32)vf_info->mac[0]) << 16) | (((u32)vf_info->mac[1]) << 8) | ((u32)vf_info->mac[2]); } /* Record the base address into queue 0 */ FM10K_WRITE_REG(hw, FM10K_TDBAL(vf_q_idx), tdbal); FM10K_WRITE_REG(hw, FM10K_TDBAH(vf_q_idx), tdbah); err_out: /* configure Queue control register */ txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) & FM10K_TXQCTL_VID_MASK; txqctl |= (vf_idx << FM10K_TXQCTL_TC_SHIFT) | FM10K_TXQCTL_VF | vf_idx; /* assign VID */ for (i = 0; i < queues_per_pool; i++) FM10K_WRITE_REG(hw, FM10K_TXQCTL(vf_q_idx + i), txqctl); /* restore the queue back to VF ownership */ FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); return err; } /** * fm10k_iov_reset_resources_pf - Reassign queues and interrupts to a VF * @hw: pointer to the HW structure * @vf_info: pointer to VF information structure * * Reassign the interrupts and queues to a VF following an FLR **/ STATIC s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, struct fm10k_vf_info *vf_info) { u16 qmap_stride, queues_per_pool, vf_q_idx, qmap_idx; u32 tdbal = 0, tdbah = 0, txqctl, rxqctl; u16 vf_v_idx, vf_v_limit, vf_vid; u8 vf_idx = vf_info->vf_idx; int i; /* verify vf is in range */ if (vf_idx >= hw->iov.num_vfs) return FM10K_ERR_PARAM; /* clear event notification of VF FLR */ FM10K_WRITE_REG(hw, FM10K_PFVFLREC(vf_idx / 32), 1 << (vf_idx % 32)); /* force timeout and then disconnect the mailbox */ vf_info->mbx.timeout = 0; if (vf_info->mbx.ops.disconnect) vf_info->mbx.ops.disconnect(hw, &vf_info->mbx); /* determine vector offset and count */ vf_v_idx = fm10k_vf_vector_index(hw, vf_idx); vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw); /* determine qmap offsets and counts */ qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256; queues_per_pool = fm10k_queues_per_pool(hw); qmap_idx = qmap_stride * vf_idx; /* make all the queues inaccessible to the VF */ for (i = qmap_idx; i < (qmap_idx + qmap_stride); i++) { FM10K_WRITE_REG(hw, FM10K_TQMAP(i), 0); FM10K_WRITE_REG(hw, FM10K_RQMAP(i), 0); } /* calculate starting index for queues */ vf_q_idx = fm10k_vf_queue_index(hw, vf_idx); /* determine correct default VLAN ID */ if (vf_info->pf_vid) vf_vid = vf_info->pf_vid; else vf_vid = vf_info->sw_vid; /* configure Queue control register */ txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) | (vf_idx << FM10K_TXQCTL_TC_SHIFT) | FM10K_TXQCTL_VF | vf_idx; rxqctl = FM10K_RXQCTL_VF | (vf_idx << FM10K_RXQCTL_VF_SHIFT); /* stop further DMA and reset queue ownership back to VF */ for (i = vf_q_idx; i < (queues_per_pool + vf_q_idx); i++) { FM10K_WRITE_REG(hw, FM10K_TXDCTL(i), 0); FM10K_WRITE_REG(hw, FM10K_TXQCTL(i), txqctl); FM10K_WRITE_REG(hw, FM10K_RXDCTL(i), FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | FM10K_RXDCTL_DROP_ON_EMPTY); FM10K_WRITE_REG(hw, FM10K_RXQCTL(i), rxqctl); } /* reset TC with -1 credits and no quanta to prevent transmit */ FM10K_WRITE_REG(hw, FM10K_TC_MAXCREDIT(vf_idx), 0); FM10K_WRITE_REG(hw, FM10K_TC_RATE(vf_idx), 0); FM10K_WRITE_REG(hw, FM10K_TC_CREDIT(vf_idx), FM10K_TC_CREDIT_CREDIT_MASK); /* update our first entry in the table based on previous VF */ if (!vf_idx) hw->mac.ops.update_int_moderator(hw); else hw->iov.ops.assign_int_moderator(hw, vf_idx - 1); /* reset linked list so it now includes our active vectors */ if (vf_idx == (hw->iov.num_vfs - 1)) FM10K_WRITE_REG(hw, FM10K_ITR2(0), vf_v_idx); else FM10K_WRITE_REG(hw, FM10K_ITR2(vf_v_limit), vf_v_idx); /* link remaining vectors so that next points to previous */ for (vf_v_idx++; vf_v_idx < vf_v_limit; vf_v_idx++) FM10K_WRITE_REG(hw, FM10K_ITR2(vf_v_idx), vf_v_idx - 1); /* zero out MBMEM, VLAN_TABLE, RETA, RSSRK, and MRQC registers */ for (i = FM10K_VFMBMEM_LEN; i--;) FM10K_WRITE_REG(hw, FM10K_MBMEM_VF(vf_idx, i), 0); for (i = FM10K_VLAN_TABLE_SIZE; i--;) FM10K_WRITE_REG(hw, FM10K_VLAN_TABLE(vf_info->vsi, i), 0); for (i = FM10K_RETA_SIZE; i--;) FM10K_WRITE_REG(hw, FM10K_RETA(vf_info->vsi, i), 0); for (i = FM10K_RSSRK_SIZE; i--;) FM10K_WRITE_REG(hw, FM10K_RSSRK(vf_info->vsi, i), 0); FM10K_WRITE_REG(hw, FM10K_MRQC(vf_info->vsi), 0); /* Update base address registers to contain MAC address */ if (FM10K_IS_VALID_ETHER_ADDR(vf_info->mac)) { tdbal = (((u32)vf_info->mac[3]) << 24) | (((u32)vf_info->mac[4]) << 16) | (((u32)vf_info->mac[5]) << 8); tdbah = (((u32)0xFF) << 24) | (((u32)vf_info->mac[0]) << 16) | (((u32)vf_info->mac[1]) << 8) | ((u32)vf_info->mac[2]); } /* map queue pairs back to VF from last to first */ for (i = queues_per_pool; i--;) { FM10K_WRITE_REG(hw, FM10K_TDBAL(vf_q_idx + i), tdbal); FM10K_WRITE_REG(hw, FM10K_TDBAH(vf_q_idx + i), tdbah); FM10K_WRITE_REG(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i); FM10K_WRITE_REG(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i); } return FM10K_SUCCESS; } /** * fm10k_iov_set_lport_pf - Assign and enable a logical port for a given VF * @hw: pointer to hardware structure * @vf_info: pointer to VF information structure * @lport_idx: Logical port offset from the hardware glort * @flags: Set of capability flags to extend port beyond basic functionality * * This function allows enabling a VF port by assigning it a GLORT and * setting the flags so that it can enable an Rx mode. **/ STATIC s32 fm10k_iov_set_lport_pf(struct fm10k_hw *hw, struct fm10k_vf_info *vf_info, u16 lport_idx, u8 flags) { u16 glort = (hw->mac.dglort_map + lport_idx) & FM10K_DGLORTMAP_NONE; DEBUGFUNC("fm10k_iov_set_lport_state_pf"); /* if glort is not valid return error */ if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; vf_info->vf_flags = flags | FM10K_VF_FLAG_NONE_CAPABLE; vf_info->glort = glort; return FM10K_SUCCESS; } /** * fm10k_iov_reset_lport_pf - Disable a logical port for a given VF * @hw: pointer to hardware structure * @vf_info: pointer to VF information structure * * This function disables a VF port by stripping it of a GLORT and * setting the flags so that it cannot enable any Rx mode. **/ STATIC void fm10k_iov_reset_lport_pf(struct fm10k_hw *hw, struct fm10k_vf_info *vf_info) { u32 msg[1]; DEBUGFUNC("fm10k_iov_reset_lport_state_pf"); /* need to disable the port if it is already enabled */ if (FM10K_VF_FLAG_ENABLED(vf_info)) { /* notify switch that this port has been disabled */ fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false); /* generate port state response to notify VF it is not ready */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); } /* clear flags and glort if it exists */ vf_info->vf_flags = 0; vf_info->glort = 0; } /** * fm10k_iov_update_stats_pf - Updates hardware related statistics for VFs * @hw: pointer to hardware structure * @q: stats for all queues of a VF * @vf_idx: index of VF * * This function collects queue stats for VFs. **/ STATIC void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q, u16 vf_idx) { u32 idx, qpp; /* get stats for all of the queues */ qpp = fm10k_queues_per_pool(hw); idx = fm10k_vf_queue_index(hw, vf_idx); fm10k_update_hw_stats_q(hw, q, idx, qpp); } STATIC s32 fm10k_iov_report_timestamp_pf(struct fm10k_hw *hw, struct fm10k_vf_info *vf_info, u64 timestamp) { u32 msg[4]; /* generate port state response to notify VF it is not ready */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588); fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_TIMESTAMP, timestamp); return vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); } /** * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF * @hw: Pointer to hardware structure * @results: Pointer array to message, results[0] is pointer to message * @mbx: Pointer to mailbox information structure * * This function is a default handler for MSI-X requests from the VF. The * assumption is that in this case it is acceptable to just directly * hand off the message from the VF to the underlying shared code. **/ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; u8 vf_idx = vf_info->vf_idx; UNREFERENCED_1PARAMETER(results); DEBUGFUNC("fm10k_iov_msg_msix_pf"); return hw->iov.ops.assign_int_moderator(hw, vf_idx); } /** * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF * @hw: Pointer to hardware structure * @results: Pointer array to message, results[0] is pointer to message * @mbx: Pointer to mailbox information structure * * This function is a default handler for MAC/VLAN requests from the VF. * The assumption is that in this case it is acceptable to just directly * hand off the message from the VF to the underlying shared code. **/ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; int err = FM10K_SUCCESS; u8 mac[ETH_ALEN]; u32 *result; u16 vlan; u32 vid; DEBUGFUNC("fm10k_iov_msg_mac_vlan_pf"); /* we shouldn't be updating rules on a disabled interface */ if (!FM10K_VF_FLAG_ENABLED(vf_info)) err = FM10K_ERR_PARAM; if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) { result = results[FM10K_MAC_VLAN_MSG_VLAN]; /* record VLAN id requested */ err = fm10k_tlv_attr_get_u32(result, &vid); if (err) return err; /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ if (!vid || (vid == FM10K_VLAN_CLEAR)) { if (vf_info->pf_vid) vid |= vf_info->pf_vid; else vid |= vf_info->sw_vid; } else if (vid != vf_info->pf_vid) { return FM10K_ERR_PARAM; } /* update VSI info for VF in regards to VLAN table */ err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, !(vid & FM10K_VLAN_CLEAR)); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) { result = results[FM10K_MAC_VLAN_MSG_MAC]; /* record unicast MAC address requested */ err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan); if (err) return err; /* block attempts to set MAC for a locked device */ if (FM10K_IS_VALID_ETHER_ADDR(vf_info->mac) && memcmp(mac, vf_info->mac, ETH_ALEN)) return FM10K_ERR_PARAM; /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { if (vf_info->pf_vid) vlan |= vf_info->pf_vid; else vlan |= vf_info->sw_vid; } else if (vf_info->pf_vid) { return FM10K_ERR_PARAM; } /* notify switch of request for new unicast address */ err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, mac, vlan, !(vlan & FM10K_VLAN_CLEAR), 0); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) { result = results[FM10K_MAC_VLAN_MSG_MULTICAST]; /* record multicast MAC address requested */ err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan); if (err) return err; /* verify that the VF is allowed to request multicast */ if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED)) return FM10K_ERR_PARAM; /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { if (vf_info->pf_vid) vlan |= vf_info->pf_vid; else vlan |= vf_info->sw_vid; } else if (vf_info->pf_vid) { return FM10K_ERR_PARAM; } /* notify switch of request for new multicast address */ err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, !(vlan & FM10K_VLAN_CLEAR), 0); } return err; } /** * fm10k_iov_supported_xcast_mode_pf - Determine best match for xcast mode * @vf_info: VF info structure containing capability flags * @mode: Requested xcast mode * * This function outputs the mode that most closely matches the requested * mode. If not modes match it will request we disable the port **/ STATIC u8 fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info *vf_info, u8 mode) { u8 vf_flags = vf_info->vf_flags; /* match up mode to capabilities as best as possible */ switch (mode) { case FM10K_XCAST_MODE_PROMISC: if (vf_flags & FM10K_VF_FLAG_PROMISC_CAPABLE) return FM10K_XCAST_MODE_PROMISC; /* fallthough */ case FM10K_XCAST_MODE_ALLMULTI: if (vf_flags & FM10K_VF_FLAG_ALLMULTI_CAPABLE) return FM10K_XCAST_MODE_ALLMULTI; /* fallthough */ case FM10K_XCAST_MODE_MULTI: if (vf_flags & FM10K_VF_FLAG_MULTI_CAPABLE) return FM10K_XCAST_MODE_MULTI; /* fallthough */ case FM10K_XCAST_MODE_NONE: if (vf_flags & FM10K_VF_FLAG_NONE_CAPABLE) return FM10K_XCAST_MODE_NONE; /* fallthough */ default: break; } /* disable interface as it should not be able to request any */ return FM10K_XCAST_MODE_DISABLE; } /** * fm10k_iov_msg_lport_state_pf - Message handler for port state requests * @hw: Pointer to hardware structure * @results: Pointer array to message, results[0] is pointer to message * @mbx: Pointer to mailbox information structure * * This function is a default handler for port state requests. The port * state requests for now are basic and consist of enabling or disabling * the port. **/ s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; u32 *result; s32 err = FM10K_SUCCESS; u32 msg[2]; u8 mode = 0; DEBUGFUNC("fm10k_iov_msg_lport_state_pf"); /* verify VF is allowed to enable even minimal mode */ if (!(vf_info->vf_flags & FM10K_VF_FLAG_NONE_CAPABLE)) return FM10K_ERR_PARAM; if (!!results[FM10K_LPORT_STATE_MSG_XCAST_MODE]) { result = results[FM10K_LPORT_STATE_MSG_XCAST_MODE]; /* XCAST mode update requested */ err = fm10k_tlv_attr_get_u8(result, &mode); if (err) return FM10K_ERR_PARAM; /* prep for possible demotion depending on capabilities */ mode = fm10k_iov_supported_xcast_mode_pf(vf_info, mode); /* if mode is not currently enabled, enable it */ if (!(FM10K_VF_FLAG_ENABLED(vf_info) & (1 << mode))) fm10k_update_xcast_mode_pf(hw, vf_info->glort, mode); /* swap mode back to a bit flag */ mode = FM10K_VF_FLAG_SET_MODE(mode); } else if (!results[FM10K_LPORT_STATE_MSG_DISABLE]) { /* need to disable the port if it is already enabled */ if (FM10K_VF_FLAG_ENABLED(vf_info)) err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false); /* when enabling the port we should reset the rate limiters */ hw->iov.ops.configure_tc(hw, vf_info->vf_idx, vf_info->rate); /* set mode for minimal functionality */ mode = FM10K_VF_FLAG_SET_MODE_NONE; /* generate port state response to notify VF it is ready */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_READY); mbx->ops.enqueue_tx(hw, mbx, msg); } /* if enable state toggled note the update */ if (!err && (!FM10K_VF_FLAG_ENABLED(vf_info) != !mode)) err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1, !!mode); /* if state change succeeded, then update our stored state */ mode |= FM10K_VF_FLAG_CAPABLE(vf_info); if (!err) vf_info->vf_flags = mode; return err; } const struct fm10k_msg_data fm10k_iov_msg_data_pf[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MSIX_HANDLER(fm10k_iov_msg_msix_pf), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_iov_msg_mac_vlan_pf), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_iov_msg_lport_state_pf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; /** * fm10k_update_stats_hw_pf - Updates hardware related statistics of PF * @hw: pointer to hardware structure * @stats: pointer to the stats structure to update * * This function collects and aggregates global and per queue hardware * statistics. **/ STATIC void fm10k_update_hw_stats_pf(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { u32 timeout, ur, ca, um, xec, vlan_drop, loopback_drop, nodesc_drop; u32 id, id_prev; DEBUGFUNC("fm10k_update_hw_stats_pf"); /* Use Tx queue 0 as a canary to detect a reset */ id = FM10K_READ_REG(hw, FM10K_TXQCTL(0)); /* Read Global Statistics */ do { timeout = fm10k_read_hw_stats_32b(hw, FM10K_STATS_TIMEOUT, &stats->timeout); ur = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UR, &stats->ur); ca = fm10k_read_hw_stats_32b(hw, FM10K_STATS_CA, &stats->ca); um = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UM, &stats->um); xec = fm10k_read_hw_stats_32b(hw, FM10K_STATS_XEC, &stats->xec); vlan_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_VLAN_DROP, &stats->vlan_drop); loopback_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_LOOPBACK_DROP, &stats->loopback_drop); nodesc_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_NODESC_DROP, &stats->nodesc_drop); /* if value has not changed then we have consistent data */ id_prev = id; id = FM10K_READ_REG(hw, FM10K_TXQCTL(0)); } while ((id ^ id_prev) & FM10K_TXQCTL_ID_MASK); /* drop non-ID bits and set VALID ID bit */ id &= FM10K_TXQCTL_ID_MASK; id |= FM10K_STAT_VALID; /* Update Global Statistics */ if (stats->stats_idx == id) { stats->timeout.count += timeout; stats->ur.count += ur; stats->ca.count += ca; stats->um.count += um; stats->xec.count += xec; stats->vlan_drop.count += vlan_drop; stats->loopback_drop.count += loopback_drop; stats->nodesc_drop.count += nodesc_drop; } /* Update bases and record current PF id */ fm10k_update_hw_base_32b(&stats->timeout, timeout); fm10k_update_hw_base_32b(&stats->ur, ur); fm10k_update_hw_base_32b(&stats->ca, ca); fm10k_update_hw_base_32b(&stats->um, um); fm10k_update_hw_base_32b(&stats->xec, xec); fm10k_update_hw_base_32b(&stats->vlan_drop, vlan_drop); fm10k_update_hw_base_32b(&stats->loopback_drop, loopback_drop); fm10k_update_hw_base_32b(&stats->nodesc_drop, nodesc_drop); stats->stats_idx = id; /* Update Queue Statistics */ fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues); } /** * fm10k_rebind_hw_stats_pf - Resets base for hardware statistics of PF * @hw: pointer to hardware structure * @stats: pointer to the stats structure to update * * This function resets the base for global and per queue hardware * statistics. **/ STATIC void fm10k_rebind_hw_stats_pf(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { DEBUGFUNC("fm10k_rebind_hw_stats_pf"); /* Unbind Global Statistics */ fm10k_unbind_hw_stats_32b(&stats->timeout); fm10k_unbind_hw_stats_32b(&stats->ur); fm10k_unbind_hw_stats_32b(&stats->ca); fm10k_unbind_hw_stats_32b(&stats->um); fm10k_unbind_hw_stats_32b(&stats->xec); fm10k_unbind_hw_stats_32b(&stats->vlan_drop); fm10k_unbind_hw_stats_32b(&stats->loopback_drop); fm10k_unbind_hw_stats_32b(&stats->nodesc_drop); /* Unbind Queue Statistics */ fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues); /* Reinitialize bases for all stats */ fm10k_update_hw_stats_pf(hw, stats); } /** * fm10k_set_dma_mask_pf - Configures PhyAddrSpace to limit DMA to system * @hw: pointer to hardware structure * @dma_mask: 64 bit DMA mask required for platform * * This function sets the PHYADDR.PhyAddrSpace bits for the endpoint in order * to limit the access to memory beyond what is physically in the system. **/ STATIC void fm10k_set_dma_mask_pf(struct fm10k_hw *hw, u64 dma_mask) { /* we need to write the upper 32 bits of DMA mask to PhyAddrSpace */ u32 phyaddr = (u32)(dma_mask >> 32); DEBUGFUNC("fm10k_set_dma_mask_pf"); FM10K_WRITE_REG(hw, FM10K_PHYADDR, phyaddr); } /** * fm10k_get_fault_pf - Record a fault in one of the interface units * @hw: pointer to hardware structure * @type: pointer to fault type register offset * @fault: pointer to memory location to record the fault * * Record the fault register contents to the fault data structure and * clear the entry from the register. * * Returns ERR_PARAM if invalid register is specified or no error is present. **/ STATIC s32 fm10k_get_fault_pf(struct fm10k_hw *hw, int type, struct fm10k_fault *fault) { u32 func; DEBUGFUNC("fm10k_get_fault_pf"); /* verify the fault register is in range and is aligned */ switch (type) { case FM10K_PCA_FAULT: case FM10K_THI_FAULT: case FM10K_FUM_FAULT: break; default: return FM10K_ERR_PARAM; } /* only service faults that are valid */ func = FM10K_READ_REG(hw, type + FM10K_FAULT_FUNC); if (!(func & FM10K_FAULT_FUNC_VALID)) return FM10K_ERR_PARAM; /* read remaining fields */ fault->address = FM10K_READ_REG(hw, type + FM10K_FAULT_ADDR_HI); fault->address <<= 32; fault->address = FM10K_READ_REG(hw, type + FM10K_FAULT_ADDR_LO); fault->specinfo = FM10K_READ_REG(hw, type + FM10K_FAULT_SPECINFO); /* clear valid bit to allow for next error */ FM10K_WRITE_REG(hw, type + FM10K_FAULT_FUNC, FM10K_FAULT_FUNC_VALID); /* Record which function triggered the error */ if (func & FM10K_FAULT_FUNC_PF) fault->func = 0; else fault->func = 1 + ((func & FM10K_FAULT_FUNC_VF_MASK) >> FM10K_FAULT_FUNC_VF_SHIFT); /* record fault type */ fault->type = func & FM10K_FAULT_FUNC_TYPE_MASK; return FM10K_SUCCESS; } /** * fm10k_request_lport_map_pf - Request LPORT map from the switch API * @hw: pointer to hardware structure * **/ STATIC s32 fm10k_request_lport_map_pf(struct fm10k_hw *hw) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[1]; DEBUGFUNC("fm10k_request_lport_pf"); /* issue request asking for LPORT map */ fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_LPORT_MAP); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_get_host_state_pf - Returns the state of the switch and mailbox * @hw: pointer to hardware structure * @switch_ready: pointer to boolean value that will record switch state * * This funciton will check the DMA_CTRL2 register and mailbox in order * to determine if the switch is ready for the PF to begin requesting * addresses and mapping traffic to the local interface. **/ STATIC s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready) { s32 ret_val = FM10K_SUCCESS; u32 dma_ctrl2; DEBUGFUNC("fm10k_get_host_state_pf"); /* verify the switch is ready for interaction */ dma_ctrl2 = FM10K_READ_REG(hw, FM10K_DMA_CTRL2); if (!(dma_ctrl2 & FM10K_DMA_CTRL2_SWITCH_READY)) goto out; /* retrieve generic host state info */ ret_val = fm10k_get_host_state_generic(hw, switch_ready); if (ret_val) goto out; /* interface cannot receive traffic without logical ports */ if (hw->mac.dglort_map == FM10K_DGLORTMAP_NONE) ret_val = fm10k_request_lport_map_pf(hw); out: return ret_val; } /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = { FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP), FM10K_TLV_ATTR_LAST }; /** * fm10k_msg_lport_map_pf - Message handler for lport_map message from SM * @hw: Pointer to hardware structure * @results: pointer array containing parsed data * @mbx: Pointer to mailbox information structure * * This handler configures the lport mapping based on the reply from the * switch API. **/ s32 fm10k_msg_lport_map_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { u16 glort, mask; u32 dglort_map; s32 err; UNREFERENCED_1PARAMETER(mbx); DEBUGFUNC("fm10k_msg_lport_map_pf"); err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_LPORT_MAP], &dglort_map); if (err) return err; /* extract values out of the header */ glort = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_GLORT); mask = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_MASK); /* verify mask is set and none of the masked bits in glort are set */ if (!mask || (glort & ~mask)) return FM10K_ERR_PARAM; /* verify the mask is contiguous, and that it is 1's followed by 0's */ if (((~(mask - 1) & mask) + mask) & FM10K_DGLORTMAP_NONE) return FM10K_ERR_PARAM; /* record the glort, mask, and port count */ hw->mac.dglort_map = dglort_map; return FM10K_SUCCESS; } const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = { FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_UPDATE_PVID), FM10K_TLV_ATTR_LAST }; /** * fm10k_msg_update_pvid_pf - Message handler for port VLAN message from SM * @hw: Pointer to hardware structure * @results: pointer array containing parsed data * @mbx: Pointer to mailbox information structure * * This handler configures the default VLAN for the PF **/ s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { u16 glort, pvid; u32 pvid_update; s32 err; UNREFERENCED_1PARAMETER(mbx); DEBUGFUNC("fm10k_msg_update_pvid_pf"); err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_UPDATE_PVID], &pvid_update); if (err) return err; /* extract values from the pvid update */ glort = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_GLORT); pvid = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_PVID); /* if glort is not valid return error */ if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; /* verify VID is valid */ if (pvid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; /* record the port VLAN ID value */ hw->mac.default_vid = pvid; return FM10K_SUCCESS; } /** * fm10k_record_global_table_data - Move global table data to swapi table info * @from: pointer to source table data structure * @to: pointer to destination table info structure * * This function is will copy table_data to the table_info contained in * the hw struct. **/ static void fm10k_record_global_table_data(struct fm10k_global_table_data *from, struct fm10k_swapi_table_info *to) { /* convert from le32 struct to CPU byte ordered values */ to->used = FM10K_LE32_TO_CPU(from->used); to->avail = FM10K_LE32_TO_CPU(from->avail); } const struct fm10k_tlv_attr fm10k_err_msg_attr[] = { FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR, sizeof(struct fm10k_swapi_error)), FM10K_TLV_ATTR_LAST }; /** * fm10k_msg_err_pf - Message handler for error reply * @hw: Pointer to hardware structure * @results: pointer array containing parsed data * @mbx: Pointer to mailbox information structure * * This handler will capture the data for any error replies to previous * messages that the PF has sent. **/ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_swapi_error err_msg; s32 err; UNREFERENCED_1PARAMETER(mbx); DEBUGFUNC("fm10k_msg_err_pf"); /* extract structure from message */ err = fm10k_tlv_attr_get_le_struct(results[FM10K_PF_ATTR_ID_ERR], &err_msg, sizeof(err_msg)); if (err) return err; /* record table status */ fm10k_record_global_table_data(&err_msg.mac, &hw->swapi.mac); fm10k_record_global_table_data(&err_msg.nexthop, &hw->swapi.nexthop); fm10k_record_global_table_data(&err_msg.ffu, &hw->swapi.ffu); /* record SW API status value */ hw->swapi.status = FM10K_LE32_TO_CPU(err_msg.status); return FM10K_SUCCESS; } const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[] = { FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_TIMESTAMP, sizeof(struct fm10k_swapi_1588_timestamp)), FM10K_TLV_ATTR_LAST }; /* currently there is no shared 1588 timestamp handler */ /** * fm10k_request_tx_timestamp_mode_pf - Request a specific Tx timestamping mode * @hw: pointer to hardware structure * @glort: base resource tag for this request * @mode: integer value indicating the requested mode * * This function will attempt to request a specific timestamp mode for the * port so that it can receive Tx timestamp messages. **/ STATIC s32 fm10k_request_tx_timestamp_mode_pf(struct fm10k_hw *hw, u16 glort, u8 mode) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[3], timestamp_mode; DEBUGFUNC("fm10k_request_timestamp_mode_pf"); if (mode > FM10K_TIMESTAMP_MODE_PEP_TO_ANY) return FM10K_ERR_PARAM; /* if glort is not valid return error */ if (!fm10k_glort_valid_pf(hw, glort)) return FM10K_ERR_PARAM; /* write timestamp mode as a single u32 value, * lower 16 bits: glort * upper 16 bits: mode */ timestamp_mode = ((u32)mode << 16) | glort; /* generate message requesting change to xcast mode */ fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_TX_TIMESTAMP_MODE); fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_TIMESTAMP_MODE_REQ, timestamp_mode); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_adjust_systime_pf - Adjust systime frequency * @hw: pointer to hardware structure * @ppb: adjustment rate in parts per billion * * This function will adjust the SYSTIME_CFG register contained in BAR 4 * if this function is supported for BAR 4 access. The adjustment amount * is based on the parts per billion value provided and adjusted to a * value based on parts per 2^48 clock cycles. * * If adjustment is not supported or the requested value is too large * we will return an error. **/ STATIC s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb) { u64 systime_adjust; DEBUGFUNC("fm10k_adjust_systime_vf"); /* if sw_addr is not set we don't have switch register access */ if (!hw->sw_addr) return ppb ? FM10K_ERR_PARAM : FM10K_SUCCESS; /* we must convert the value from parts per billion to parts per * 2^48 cycles. In addition I have opted to only use the 30 most * significant bits of the adjustment value as the 8 least * significant bits are located in another register and represent * a value significantly less than a part per billion, the result * of dropping the 8 least significant bits is that the adjustment * value is effectively multiplied by 2^8 when we write it. * * As a result of all this the math for this breaks down as follows: * ppb / 10^9 == adjust * 2^8 / 2^48 * If we solve this for adjust, and simplify it comes out as: * ppb * 2^31 / 5^9 == adjust */ systime_adjust = (ppb < 0) ? -ppb : ppb; systime_adjust <<= 31; do_div(systime_adjust, 1953125); /* verify the requested adjustment value is in range */ if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK) return FM10K_ERR_PARAM; if (ppb < 0) systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE; FM10K_WRITE_SW_REG(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust); return FM10K_SUCCESS; } /** * fm10k_read_systime_pf - Reads value of systime registers * @hw: pointer to the hardware structure * * Function reads the content of 2 registers, combined to represent a 64 bit * value measured in nanosecods. In order to guarantee the value is accurate * we check the 32 most significant bits both before and after reading the * 32 least significant bits to verify they didn't change as we were reading * the registers. **/ static u64 fm10k_read_systime_pf(struct fm10k_hw *hw) { u32 systime_l, systime_h, systime_tmp; systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1); do { systime_tmp = systime_h; systime_l = fm10k_read_reg(hw, FM10K_SYSTIME); systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1); } while (systime_tmp != systime_h); return ((u64)systime_h << 32) | systime_l; } static const struct fm10k_msg_data fm10k_msg_data_pf[] = { FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; /** * fm10k_init_ops_pf - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for PF. * Does not touch the hardware. **/ s32 fm10k_init_ops_pf(struct fm10k_hw *hw) { struct fm10k_mac_info *mac = &hw->mac; struct fm10k_iov_info *iov = &hw->iov; DEBUGFUNC("fm10k_init_ops_pf"); fm10k_init_ops_generic(hw); mac->ops.reset_hw = &fm10k_reset_hw_pf; mac->ops.init_hw = &fm10k_init_hw_pf; mac->ops.start_hw = &fm10k_start_hw_generic; mac->ops.stop_hw = &fm10k_stop_hw_generic; mac->ops.is_slot_appropriate = &fm10k_is_slot_appropriate_pf; mac->ops.update_vlan = &fm10k_update_vlan_pf; mac->ops.read_mac_addr = &fm10k_read_mac_addr_pf; mac->ops.update_uc_addr = &fm10k_update_uc_addr_pf; mac->ops.update_mc_addr = &fm10k_update_mc_addr_pf; mac->ops.update_xcast_mode = &fm10k_update_xcast_mode_pf; mac->ops.update_int_moderator = &fm10k_update_int_moderator_pf; mac->ops.update_lport_state = &fm10k_update_lport_state_pf; mac->ops.update_hw_stats = &fm10k_update_hw_stats_pf; mac->ops.rebind_hw_stats = &fm10k_rebind_hw_stats_pf; mac->ops.configure_dglort_map = &fm10k_configure_dglort_map_pf; mac->ops.set_dma_mask = &fm10k_set_dma_mask_pf; mac->ops.get_fault = &fm10k_get_fault_pf; mac->ops.get_host_state = &fm10k_get_host_state_pf; mac->ops.adjust_systime = &fm10k_adjust_systime_pf; mac->ops.read_systime = &fm10k_read_systime_pf; mac->ops.request_tx_timestamp_mode = &fm10k_request_tx_timestamp_mode_pf; mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw); iov->ops.assign_resources = &fm10k_iov_assign_resources_pf; iov->ops.configure_tc = &fm10k_iov_configure_tc_pf; iov->ops.assign_int_moderator = &fm10k_iov_assign_int_moderator_pf; iov->ops.assign_default_mac_vlan = fm10k_iov_assign_default_mac_vlan_pf; iov->ops.reset_resources = &fm10k_iov_reset_resources_pf; iov->ops.set_lport = &fm10k_iov_set_lport_pf; iov->ops.reset_lport = &fm10k_iov_reset_lport_pf; iov->ops.update_stats = &fm10k_iov_update_stats_pf; iov->ops.report_timestamp = &fm10k_iov_report_timestamp_pf; return fm10k_sm_mbx_init(hw, &hw->mbx, fm10k_msg_data_pf); } ================================================ FILE: drivers/net/fm10k/base/fm10k_pf.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_PF_H_ #define _FM10K_PF_H_ #include "fm10k_type.h" #include "fm10k_common.h" bool fm10k_glort_valid_pf(struct fm10k_hw *hw, u16 glort); u16 fm10k_queues_per_pool(struct fm10k_hw *hw); u16 fm10k_vf_queue_index(struct fm10k_hw *hw, u16 vf_idx); enum fm10k_pf_tlv_msg_id_v1 { FM10K_PF_MSG_ID_TEST = 0x000, /* msg ID reserved */ FM10K_PF_MSG_ID_XCAST_MODES = 0x001, FM10K_PF_MSG_ID_UPDATE_MAC_FWD_RULE = 0x002, FM10K_PF_MSG_ID_LPORT_MAP = 0x100, FM10K_PF_MSG_ID_LPORT_CREATE = 0x200, FM10K_PF_MSG_ID_LPORT_DELETE = 0x201, FM10K_PF_MSG_ID_CONFIG = 0x300, FM10K_PF_MSG_ID_UPDATE_PVID = 0x400, FM10K_PF_MSG_ID_CREATE_FLOW_TABLE = 0x501, FM10K_PF_MSG_ID_DELETE_FLOW_TABLE = 0x502, FM10K_PF_MSG_ID_UPDATE_FLOW = 0x503, FM10K_PF_MSG_ID_DELETE_FLOW = 0x504, FM10K_PF_MSG_ID_SET_FLOW_STATE = 0x505, FM10K_PF_MSG_ID_GET_1588_INFO = 0x506, FM10K_PF_MSG_ID_1588_TIMESTAMP = 0x701, FM10K_PF_MSG_ID_TX_TIMESTAMP_MODE = 0x702, }; enum fm10k_pf_tlv_attr_id_v1 { FM10K_PF_ATTR_ID_ERR = 0x00, FM10K_PF_ATTR_ID_LPORT_MAP = 0x01, FM10K_PF_ATTR_ID_XCAST_MODE = 0x02, FM10K_PF_ATTR_ID_MAC_UPDATE = 0x03, FM10K_PF_ATTR_ID_VLAN_UPDATE = 0x04, FM10K_PF_ATTR_ID_CONFIG = 0x05, FM10K_PF_ATTR_ID_CREATE_FLOW_TABLE = 0x06, FM10K_PF_ATTR_ID_DELETE_FLOW_TABLE = 0x07, FM10K_PF_ATTR_ID_UPDATE_FLOW = 0x08, FM10K_PF_ATTR_ID_FLOW_STATE = 0x09, FM10K_PF_ATTR_ID_FLOW_HANDLE = 0x0A, FM10K_PF_ATTR_ID_DELETE_FLOW = 0x0B, FM10K_PF_ATTR_ID_PORT = 0x0C, FM10K_PF_ATTR_ID_UPDATE_PVID = 0x0D, FM10K_PF_ATTR_ID_1588_TIMESTAMP = 0x10, FM10K_PF_ATTR_ID_TIMESTAMP_MODE_REQ = 0x11, FM10K_PF_ATTR_ID_TIMESTAMP_MODE_RESP = 0x12, }; #define FM10K_MSG_LPORT_MAP_GLORT_SHIFT 0 #define FM10K_MSG_LPORT_MAP_GLORT_SIZE 16 #define FM10K_MSG_LPORT_MAP_MASK_SHIFT 16 #define FM10K_MSG_LPORT_MAP_MASK_SIZE 16 #define FM10K_MSG_UPDATE_PVID_GLORT_SHIFT 0 #define FM10K_MSG_UPDATE_PVID_GLORT_SIZE 16 #define FM10K_MSG_UPDATE_PVID_PVID_SHIFT 16 #define FM10K_MSG_UPDATE_PVID_PVID_SIZE 16 struct fm10k_mac_update { __le32 mac_lower; __le16 mac_upper; __le16 vlan; __le16 glort; u8 flags; u8 action; }; struct fm10k_global_table_data { __le32 used; __le32 avail; }; struct fm10k_swapi_error { __le32 status; struct fm10k_global_table_data mac; struct fm10k_global_table_data nexthop; struct fm10k_global_table_data ffu; }; struct fm10k_swapi_1588_timestamp { __le64 egress; __le64 ingress; __le16 dglort; __le16 sglort; }; #define FM10K_PF_MSG_LPORT_CREATE_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_LPORT_CREATE, NULL, func) #define FM10K_PF_MSG_LPORT_DELETE_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_LPORT_DELETE, NULL, func) s32 fm10k_msg_lport_map_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[]; #define FM10K_PF_MSG_LPORT_MAP_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_LPORT_MAP, \ fm10k_lport_map_msg_attr, func) s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[]; #define FM10K_PF_MSG_UPDATE_PVID_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_UPDATE_PVID, \ fm10k_update_pvid_msg_attr, func) s32 fm10k_msg_err_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_err_msg_attr[]; #define FM10K_PF_MSG_ERR_HANDLER(msg, func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_##msg, fm10k_err_msg_attr, func) extern const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[]; #define FM10K_PF_MSG_1588_TIMESTAMP_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_PF_MSG_ID_1588_TIMESTAMP, \ fm10k_1588_timestamp_msg_attr, func) s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_msg_data fm10k_iov_msg_data_pf[]; s32 fm10k_init_ops_pf(struct fm10k_hw *hw); #endif /* _FM10K_PF_H */ ================================================ FILE: drivers/net/fm10k/base/fm10k_tlv.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_tlv.h" /** * fm10k_tlv_msg_init - Initialize message block for TLV data storage * @msg: Pointer to message block * @msg_id: Message ID indicating message type * * This function return success if provided with a valid message pointer **/ s32 fm10k_tlv_msg_init(u32 *msg, u16 msg_id) { DEBUGFUNC("fm10k_tlv_msg_init"); /* verify pointer is not NULL */ if (!msg) return FM10K_ERR_PARAM; *msg = (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT) | msg_id; return FM10K_SUCCESS; } /** * fm10k_tlv_attr_put_null_string - Place null terminated string on message * @msg: Pointer to message block * @attr_id: Attribute ID * @string: Pointer to string to be stored in attribute * * This function will reorder a string to be CPU endian and store it in * the attribute buffer. It will return success if provided with a valid * pointers. **/ s32 fm10k_tlv_attr_put_null_string(u32 *msg, u16 attr_id, const unsigned char *string) { u32 attr_data = 0, len = 0; u32 *attr; DEBUGFUNC("fm10k_tlv_attr_put_null_string"); /* verify pointers are not NULL */ if (!string || !msg) return FM10K_ERR_PARAM; attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; /* copy string into local variable and then write to msg */ do { /* write data to message */ if (len && !(len % 4)) { attr[len / 4] = attr_data; attr_data = 0; } /* record character to offset location */ attr_data |= (u32)(*string) << (8 * (len % 4)); len++; /* test for NULL and then increment */ } while (*(string++)); /* write last piece of data to message */ attr[(len + 3) / 4] = attr_data; /* record attribute header, update message length */ len <<= FM10K_TLV_LEN_SHIFT; attr[0] = len | attr_id; /* add header length to length */ len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; *msg += FM10K_TLV_LEN_ALIGN(len); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_get_null_string - Get null terminated string from attribute * @attr: Pointer to attribute * @string: Pointer to location of destination string * * This function pulls the string back out of the attribute and will place * it in the array pointed by by string. It will return success if provided * with a valid pointers. **/ s32 fm10k_tlv_attr_get_null_string(u32 *attr, unsigned char *string) { u32 len; DEBUGFUNC("fm10k_tlv_attr_get_null_string"); /* verify pointers are not NULL */ if (!string || !attr) return FM10K_ERR_PARAM; len = *attr >> FM10K_TLV_LEN_SHIFT; attr++; while (len--) string[len] = (u8)(attr[len / 4] >> (8 * (len % 4))); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_put_mac_vlan - Store MAC/VLAN attribute in message * @msg: Pointer to message block * @attr_id: Attribute ID * @mac_addr: MAC address to be stored * * This function will reorder a MAC address to be CPU endian and store it * in the attribute buffer. It will return success if provided with a * valid pointers. **/ s32 fm10k_tlv_attr_put_mac_vlan(u32 *msg, u16 attr_id, const u8 *mac_addr, u16 vlan) { u32 len = ETH_ALEN << FM10K_TLV_LEN_SHIFT; u32 *attr; DEBUGFUNC("fm10k_tlv_attr_put_mac_vlan"); /* verify pointers are not NULL */ if (!msg || !mac_addr) return FM10K_ERR_PARAM; attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; /* record attribute header, update message length */ attr[0] = len | attr_id; /* copy value into local variable and then write to msg */ attr[1] = FM10K_LE32_TO_CPU(*(const __le32 *)&mac_addr[0]); attr[2] = FM10K_LE16_TO_CPU(*(const __le16 *)&mac_addr[4]); attr[2] |= (u32)vlan << 16; /* add header length to length */ len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; *msg += FM10K_TLV_LEN_ALIGN(len); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_get_mac_vlan - Get MAC/VLAN stored in attribute * @attr: Pointer to attribute * @attr_id: Attribute ID * @mac_addr: location of buffer to store MAC address * * This function pulls the MAC address back out of the attribute and will * place it in the array pointed by by mac_addr. It will return success * if provided with a valid pointers. **/ s32 fm10k_tlv_attr_get_mac_vlan(u32 *attr, u8 *mac_addr, u16 *vlan) { DEBUGFUNC("fm10k_tlv_attr_get_mac_vlan"); /* verify pointers are not NULL */ if (!mac_addr || !attr) return FM10K_ERR_PARAM; *(__le32 *)&mac_addr[0] = FM10K_CPU_TO_LE32(attr[1]); *(__le16 *)&mac_addr[4] = FM10K_CPU_TO_LE16((u16)(attr[2])); *vlan = (u16)(attr[2] >> 16); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_put_bool - Add header indicating value "true" * @msg: Pointer to message block * @attr_id: Attribute ID * * This function will simply add an attribute header, the fact * that the header is here means the attribute value is true, else * it is false. The function will return success if provided with a * valid pointers. **/ s32 fm10k_tlv_attr_put_bool(u32 *msg, u16 attr_id) { DEBUGFUNC("fm10k_tlv_attr_put_bool"); /* verify pointers are not NULL */ if (!msg) return FM10K_ERR_PARAM; /* record attribute header */ msg[FM10K_TLV_DWORD_LEN(*msg)] = attr_id; /* add header length to length */ *msg += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; return FM10K_SUCCESS; } /** * fm10k_tlv_attr_put_value - Store integer value attribute in message * @msg: Pointer to message block * @attr_id: Attribute ID * @value: Value to be written * @len: Size of value * * This function will place an integer value of up to 8 bytes in size * in a message attribute. The function will return success provided * that msg is a valid pointer, and len is 1, 2, 4, or 8. **/ s32 fm10k_tlv_attr_put_value(u32 *msg, u16 attr_id, s64 value, u32 len) { u32 *attr; DEBUGFUNC("fm10k_tlv_attr_put_value"); /* verify non-null msg and len is 1, 2, 4, or 8 */ if (!msg || !len || len > 8 || (len & (len - 1))) return FM10K_ERR_PARAM; attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; if (len < 4) { attr[1] = (u32)value & ((0x1ul << (8 * len)) - 1); } else { attr[1] = (u32)value; if (len > 4) attr[2] = (u32)(value >> 32); } /* record attribute header, update message length */ len <<= FM10K_TLV_LEN_SHIFT; attr[0] = len | attr_id; /* add header length to length */ len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; *msg += FM10K_TLV_LEN_ALIGN(len); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_get_value - Get integer value stored in attribute * @attr: Pointer to attribute * @value: Pointer to destination buffer * @len: Size of value * * This function will place an integer value of up to 8 bytes in size * in the offset pointed to by value. The function will return success * provided that pointers are valid and the len value matches the * attribute length. **/ s32 fm10k_tlv_attr_get_value(u32 *attr, void *value, u32 len) { DEBUGFUNC("fm10k_tlv_attr_get_value"); /* verify pointers are not NULL */ if (!attr || !value) return FM10K_ERR_PARAM; if ((*attr >> FM10K_TLV_LEN_SHIFT) != len) return FM10K_ERR_PARAM; if (len == 8) *(u64 *)value = ((u64)attr[2] << 32) | attr[1]; else if (len == 4) *(u32 *)value = attr[1]; else if (len == 2) *(u16 *)value = (u16)attr[1]; else *(u8 *)value = (u8)attr[1]; return FM10K_SUCCESS; } /** * fm10k_tlv_attr_put_le_struct - Store little endian structure in message * @msg: Pointer to message block * @attr_id: Attribute ID * @le_struct: Pointer to structure to be written * @len: Size of le_struct * * This function will place a little endian structure value in a message * attribute. The function will return success provided that all pointers * are valid and length is a non-zero multiple of 4. **/ s32 fm10k_tlv_attr_put_le_struct(u32 *msg, u16 attr_id, const void *le_struct, u32 len) { const __le32 *le32_ptr = (const __le32 *)le_struct; u32 *attr; u32 i; DEBUGFUNC("fm10k_tlv_attr_put_le_struct"); /* verify non-null msg and len is in 32 bit words */ if (!msg || !len || (len % 4)) return FM10K_ERR_PARAM; attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; /* copy le32 structure into host byte order at 32b boundaries */ for (i = 0; i < (len / 4); i++) attr[i + 1] = FM10K_LE32_TO_CPU(le32_ptr[i]); /* record attribute header, update message length */ len <<= FM10K_TLV_LEN_SHIFT; attr[0] = len | attr_id; /* add header length to length */ len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; *msg += FM10K_TLV_LEN_ALIGN(len); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_get_le_struct - Get little endian struct form attribute * @attr: Pointer to attribute * @le_struct: Pointer to structure to be written * @len: Size of structure * * This function will place a little endian structure in the buffer * pointed to by le_struct. The function will return success * provided that pointers are valid and the len value matches the * attribute length. **/ s32 fm10k_tlv_attr_get_le_struct(u32 *attr, void *le_struct, u32 len) { __le32 *le32_ptr = (__le32 *)le_struct; u32 i; DEBUGFUNC("fm10k_tlv_attr_get_le_struct"); /* verify pointers are not NULL */ if (!le_struct || !attr) return FM10K_ERR_PARAM; if ((*attr >> FM10K_TLV_LEN_SHIFT) != len) return FM10K_ERR_PARAM; attr++; for (i = 0; len; i++, len -= 4) le32_ptr[i] = FM10K_CPU_TO_LE32(attr[i]); return FM10K_SUCCESS; } /** * fm10k_tlv_attr_nest_start - Start a set of nested attributes * @msg: Pointer to message block * @attr_id: Attribute ID * * This function will mark off a new nested region for encapsulating * a given set of attributes. The idea is if you wish to place a secondary * structure within the message this mechanism allows for that. The * function will return NULL on failure, and a pointer to the start * of the nested attributes on success. **/ u32 *fm10k_tlv_attr_nest_start(u32 *msg, u16 attr_id) { u32 *attr; DEBUGFUNC("fm10k_tlv_attr_nest_start"); /* verify pointer is not NULL */ if (!msg) return NULL; attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; attr[0] = attr_id; /* return pointer to nest header */ return attr; } /** * fm10k_tlv_attr_nest_start - Start a set of nested attributes * @msg: Pointer to message block * * This function closes off an existing set of nested attributes. The * message pointer should be pointing to the parent of the nest. So in * the case of a nest within the nest this would be the outer nest pointer. * This function will return success provided all pointers are valid. **/ s32 fm10k_tlv_attr_nest_stop(u32 *msg) { u32 *attr; u32 len; DEBUGFUNC("fm10k_tlv_attr_nest_stop"); /* verify pointer is not NULL */ if (!msg) return FM10K_ERR_PARAM; /* locate the nested header and retrieve its length */ attr = &msg[FM10K_TLV_DWORD_LEN(*msg)]; len = (attr[0] >> FM10K_TLV_LEN_SHIFT) << FM10K_TLV_LEN_SHIFT; /* only include nest if data was added to it */ if (len) { len += FM10K_TLV_HDR_LEN << FM10K_TLV_LEN_SHIFT; *msg += len; } return FM10K_SUCCESS; } /** * fm10k_tlv_attr_validate - Validate attribute metadata * @attr: Pointer to attribute * @tlv_attr: Type and length info for attribute * * This function does some basic validation of the input TLV. It * verifies the length, and in the case of null terminated strings * it verifies that the last byte is null. The function will * return FM10K_ERR_PARAM if any attribute is malformed, otherwise * it returns 0. **/ STATIC s32 fm10k_tlv_attr_validate(u32 *attr, const struct fm10k_tlv_attr *tlv_attr) { u32 attr_id = *attr & FM10K_TLV_ID_MASK; u16 len = *attr >> FM10K_TLV_LEN_SHIFT; DEBUGFUNC("fm10k_tlv_attr_validate"); /* verify this is an attribute and not a message */ if (*attr & (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT)) return FM10K_ERR_PARAM; /* search through the list of attributes to find a matching ID */ while (tlv_attr->id < attr_id) tlv_attr++; /* if didn't find a match then we should exit */ if (tlv_attr->id != attr_id) return FM10K_NOT_IMPLEMENTED; /* move to start of attribute data */ attr++; switch (tlv_attr->type) { case FM10K_TLV_NULL_STRING: if (!len || (attr[(len - 1) / 4] & (0xFF << (8 * ((len - 1) % 4))))) return FM10K_ERR_PARAM; if (len > tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_MAC_ADDR: if (len != ETH_ALEN) return FM10K_ERR_PARAM; break; case FM10K_TLV_BOOL: if (len) return FM10K_ERR_PARAM; break; case FM10K_TLV_UNSIGNED: case FM10K_TLV_SIGNED: if (len != tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_LE_STRUCT: /* struct must be 4 byte aligned */ if ((len % 4) || len != tlv_attr->len) return FM10K_ERR_PARAM; break; case FM10K_TLV_NESTED: /* nested attributes must be 4 byte aligned */ if (len % 4) return FM10K_ERR_PARAM; break; default: /* attribute id is mapped to bad value */ return FM10K_ERR_PARAM; } return FM10K_SUCCESS; } /** * fm10k_tlv_attr_parse - Parses stream of attribute data * @attr: Pointer to attribute list * @results: Pointer array to store pointers to attributes * @tlv_attr: Type and length info for attributes * * This function validates a stream of attributes and parses them * up into an array of pointers stored in results. The function will * return FM10K_ERR_PARAM on any input or message error, * FM10K_NOT_IMPLEMENTED for any attribute that is outside of the array * and 0 on success. **/ s32 fm10k_tlv_attr_parse(u32 *attr, u32 **results, const struct fm10k_tlv_attr *tlv_attr) { u32 i, attr_id, offset = 0; s32 err = 0; u16 len; DEBUGFUNC("fm10k_tlv_attr_parse"); /* verify pointers are not NULL */ if (!attr || !results) return FM10K_ERR_PARAM; /* initialize results to NULL */ for (i = 0; i < FM10K_TLV_RESULTS_MAX; i++) results[i] = NULL; /* pull length from the message header */ len = *attr >> FM10K_TLV_LEN_SHIFT; /* no attributes to parse if there is no length */ if (!len) return FM10K_SUCCESS; /* no attributes to parse, just raw data, message becomes attribute */ if (!tlv_attr) { results[0] = attr; return FM10K_SUCCESS; } /* move to start of attribute data */ attr++; /* run through list parsing all attributes */ while (offset < len) { attr_id = *attr & FM10K_TLV_ID_MASK; if (attr_id < FM10K_TLV_RESULTS_MAX) err = fm10k_tlv_attr_validate(attr, tlv_attr); else err = FM10K_NOT_IMPLEMENTED; if (err < 0) return err; if (!err) results[attr_id] = attr; /* update offset */ offset += FM10K_TLV_DWORD_LEN(*attr) * 4; /* move to next attribute */ attr = &attr[FM10K_TLV_DWORD_LEN(*attr)]; } /* we should find ourselves at the end of the list */ if (offset != len) return FM10K_ERR_PARAM; return FM10K_SUCCESS; } /** * fm10k_tlv_msg_parse - Parses message header and calls function handler * @hw: Pointer to hardware structure * @msg: Pointer to message * @mbx: Pointer to mailbox information structure * @func: Function array containing list of message handling functions * * This function should be the first function called upon receiving a * message. The handler will identify the message type and call the correct * handler for the given message. It will return the value from the function * call on a recognized message type, otherwise it will return * FM10K_NOT_IMPLEMENTED on an unrecognized type. **/ s32 fm10k_tlv_msg_parse(struct fm10k_hw *hw, u32 *msg, struct fm10k_mbx_info *mbx, const struct fm10k_msg_data *data) { u32 *results[FM10K_TLV_RESULTS_MAX]; u32 msg_id; s32 err; DEBUGFUNC("fm10k_tlv_msg_parse"); /* verify pointer is not NULL */ if (!msg || !data) return FM10K_ERR_PARAM; /* verify this is a message and not an attribute */ if (!(*msg & (FM10K_TLV_FLAGS_MSG << FM10K_TLV_FLAGS_SHIFT))) return FM10K_ERR_PARAM; /* grab message ID */ msg_id = *msg & FM10K_TLV_ID_MASK; while (data->id < msg_id) data++; /* if we didn't find it then pass it up as an error */ if (data->id != msg_id) { while (data->id != FM10K_TLV_ERROR) data++; } /* parse the attributes into the results list */ err = fm10k_tlv_attr_parse(msg, results, data->attr); if (err < 0) return err; return data->func(hw, results, mbx); } /** * fm10k_tlv_msg_error - Default handler for unrecognized TLV message IDs * @hw: Pointer to hardware structure * @results: Pointer array to message, results[0] is pointer to message * @mbx: Unused mailbox pointer * * This function is a default handler for unrecognized messages. At a * a minimum it just indicates that the message requested was * unimplemented. **/ s32 fm10k_tlv_msg_error(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { UNREFERENCED_3PARAMETER(hw, results, mbx); DEBUGOUT1("Unknown message ID %u\n", **results & FM10K_TLV_ID_MASK); return FM10K_NOT_IMPLEMENTED; } STATIC const unsigned char test_str[] = "fm10k"; STATIC const unsigned char test_mac[ETH_ALEN] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc }; STATIC const u16 test_vlan = 0x0FED; STATIC const u64 test_u64 = 0xfedcba9876543210ull; STATIC const u32 test_u32 = 0x87654321; STATIC const u16 test_u16 = 0x8765; STATIC const u8 test_u8 = 0x87; STATIC const s64 test_s64 = -0x123456789abcdef0ll; STATIC const s32 test_s32 = -0x1235678; STATIC const s16 test_s16 = -0x1234; STATIC const s8 test_s8 = -0x12; STATIC const __le32 test_le[2] = { FM10K_CPU_TO_LE32(0x12345678), FM10K_CPU_TO_LE32(0x9abcdef0)}; /* The message below is meant to be used as a test message to demonstrate * how to use the TLV interface and to test the types. Normally this code * be compiled out by stripping the code wrapped in FM10K_TLV_TEST_MSG */ const struct fm10k_tlv_attr fm10k_tlv_msg_test_attr[] = { FM10K_TLV_ATTR_NULL_STRING(FM10K_TEST_MSG_STRING, 80), FM10K_TLV_ATTR_MAC_ADDR(FM10K_TEST_MSG_MAC_ADDR), FM10K_TLV_ATTR_U8(FM10K_TEST_MSG_U8), FM10K_TLV_ATTR_U16(FM10K_TEST_MSG_U16), FM10K_TLV_ATTR_U32(FM10K_TEST_MSG_U32), FM10K_TLV_ATTR_U64(FM10K_TEST_MSG_U64), FM10K_TLV_ATTR_S8(FM10K_TEST_MSG_S8), FM10K_TLV_ATTR_S16(FM10K_TEST_MSG_S16), FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_S32), FM10K_TLV_ATTR_S64(FM10K_TEST_MSG_S64), FM10K_TLV_ATTR_LE_STRUCT(FM10K_TEST_MSG_LE_STRUCT, 8), FM10K_TLV_ATTR_NESTED(FM10K_TEST_MSG_NESTED), FM10K_TLV_ATTR_S32(FM10K_TEST_MSG_RESULT), FM10K_TLV_ATTR_LAST }; /** * fm10k_tlv_msg_test_generate_data - Stuff message with data * @msg: Pointer to message * @attr_flags: List of flags indicating what attributes to add * * This function is meant to load a message buffer with attribute data **/ STATIC void fm10k_tlv_msg_test_generate_data(u32 *msg, u32 attr_flags) { DEBUGFUNC("fm10k_tlv_msg_test_generate_data"); if (attr_flags & (1 << FM10K_TEST_MSG_STRING)) fm10k_tlv_attr_put_null_string(msg, FM10K_TEST_MSG_STRING, test_str); if (attr_flags & (1 << FM10K_TEST_MSG_MAC_ADDR)) fm10k_tlv_attr_put_mac_vlan(msg, FM10K_TEST_MSG_MAC_ADDR, test_mac, test_vlan); if (attr_flags & (1 << FM10K_TEST_MSG_U8)) fm10k_tlv_attr_put_u8(msg, FM10K_TEST_MSG_U8, test_u8); if (attr_flags & (1 << FM10K_TEST_MSG_U16)) fm10k_tlv_attr_put_u16(msg, FM10K_TEST_MSG_U16, test_u16); if (attr_flags & (1 << FM10K_TEST_MSG_U32)) fm10k_tlv_attr_put_u32(msg, FM10K_TEST_MSG_U32, test_u32); if (attr_flags & (1 << FM10K_TEST_MSG_U64)) fm10k_tlv_attr_put_u64(msg, FM10K_TEST_MSG_U64, test_u64); if (attr_flags & (1 << FM10K_TEST_MSG_S8)) fm10k_tlv_attr_put_s8(msg, FM10K_TEST_MSG_S8, test_s8); if (attr_flags & (1 << FM10K_TEST_MSG_S16)) fm10k_tlv_attr_put_s16(msg, FM10K_TEST_MSG_S16, test_s16); if (attr_flags & (1 << FM10K_TEST_MSG_S32)) fm10k_tlv_attr_put_s32(msg, FM10K_TEST_MSG_S32, test_s32); if (attr_flags & (1 << FM10K_TEST_MSG_S64)) fm10k_tlv_attr_put_s64(msg, FM10K_TEST_MSG_S64, test_s64); if (attr_flags & (1 << FM10K_TEST_MSG_LE_STRUCT)) fm10k_tlv_attr_put_le_struct(msg, FM10K_TEST_MSG_LE_STRUCT, test_le, 8); } /** * fm10k_tlv_msg_test_create - Create a test message testing all attributes * @msg: Pointer to message * @attr_flags: List of flags indicating what attributes to add * * This function is meant to load a message buffer with all attribute types * including a nested attribute. **/ void fm10k_tlv_msg_test_create(u32 *msg, u32 attr_flags) { u32 *nest = NULL; DEBUGFUNC("fm10k_tlv_msg_test_create"); fm10k_tlv_msg_init(msg, FM10K_TLV_MSG_ID_TEST); fm10k_tlv_msg_test_generate_data(msg, attr_flags); /* check for nested attributes */ attr_flags >>= FM10K_TEST_MSG_NESTED; if (attr_flags) { nest = fm10k_tlv_attr_nest_start(msg, FM10K_TEST_MSG_NESTED); fm10k_tlv_msg_test_generate_data(nest, attr_flags); fm10k_tlv_attr_nest_stop(msg); } } /** * fm10k_tlv_msg_test - Validate all results on test message receive * @hw: Pointer to hardware structure * @results: Pointer array to attributes in the message * @mbx: Pointer to mailbox information structure * * This function does a check to verify all attributes match what the test * message placed in the message buffer. It is the default handler * for TLV test messages. **/ s32 fm10k_tlv_msg_test(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { u32 *nest_results[FM10K_TLV_RESULTS_MAX]; unsigned char result_str[80]; unsigned char result_mac[ETH_ALEN]; s32 err = FM10K_SUCCESS; __le32 result_le[2]; u16 result_vlan; u64 result_u64; u32 result_u32; u16 result_u16; u8 result_u8; s64 result_s64; s32 result_s32; s16 result_s16; s8 result_s8; u32 reply[3]; DEBUGFUNC("fm10k_tlv_msg_test"); /* retrieve results of a previous test */ if (!!results[FM10K_TEST_MSG_RESULT]) return fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_RESULT], &mbx->test_result); parse_nested: if (!!results[FM10K_TEST_MSG_STRING]) { err = fm10k_tlv_attr_get_null_string( results[FM10K_TEST_MSG_STRING], result_str); if (!err && memcmp(test_str, result_str, sizeof(test_str))) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_MAC_ADDR]) { err = fm10k_tlv_attr_get_mac_vlan( results[FM10K_TEST_MSG_MAC_ADDR], result_mac, &result_vlan); if (!err && memcmp(test_mac, result_mac, ETH_ALEN)) err = FM10K_ERR_INVALID_VALUE; if (!err && test_vlan != result_vlan) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_U8]) { err = fm10k_tlv_attr_get_u8(results[FM10K_TEST_MSG_U8], &result_u8); if (!err && test_u8 != result_u8) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_U16]) { err = fm10k_tlv_attr_get_u16(results[FM10K_TEST_MSG_U16], &result_u16); if (!err && test_u16 != result_u16) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_U32]) { err = fm10k_tlv_attr_get_u32(results[FM10K_TEST_MSG_U32], &result_u32); if (!err && test_u32 != result_u32) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_U64]) { err = fm10k_tlv_attr_get_u64(results[FM10K_TEST_MSG_U64], &result_u64); if (!err && test_u64 != result_u64) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_S8]) { err = fm10k_tlv_attr_get_s8(results[FM10K_TEST_MSG_S8], &result_s8); if (!err && test_s8 != result_s8) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_S16]) { err = fm10k_tlv_attr_get_s16(results[FM10K_TEST_MSG_S16], &result_s16); if (!err && test_s16 != result_s16) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_S32]) { err = fm10k_tlv_attr_get_s32(results[FM10K_TEST_MSG_S32], &result_s32); if (!err && test_s32 != result_s32) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_S64]) { err = fm10k_tlv_attr_get_s64(results[FM10K_TEST_MSG_S64], &result_s64); if (!err && test_s64 != result_s64) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_LE_STRUCT]) { err = fm10k_tlv_attr_get_le_struct( results[FM10K_TEST_MSG_LE_STRUCT], result_le, sizeof(result_le)); if (!err && memcmp(test_le, result_le, sizeof(test_le))) err = FM10K_ERR_INVALID_VALUE; if (err) goto report_result; } if (!!results[FM10K_TEST_MSG_NESTED]) { /* clear any pointers */ memset(nest_results, 0, sizeof(nest_results)); /* parse the nested attributes into the nest results list */ err = fm10k_tlv_attr_parse(results[FM10K_TEST_MSG_NESTED], nest_results, fm10k_tlv_msg_test_attr); if (err) goto report_result; /* loop back through to the start */ results = nest_results; goto parse_nested; } report_result: /* generate reply with test result */ fm10k_tlv_msg_init(reply, FM10K_TLV_MSG_ID_TEST); fm10k_tlv_attr_put_s32(reply, FM10K_TEST_MSG_RESULT, err); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, reply); } ================================================ FILE: drivers/net/fm10k/base/fm10k_tlv.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_TLV_H_ #define _FM10K_TLV_H_ /* forward declaration */ struct fm10k_msg_data; #include "fm10k_type.h" /* Message / Argument header format * 3 2 1 0 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Length | Flags | Type / ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * The message header format described here is used for messages that are * passed between the PF and the VF. To allow for messages larger then * mailbox size we will provide a message with the above header and it * will be segmented and transported to the mailbox to the other side where * it is reassembled. It contains the following fields: * Len: Length of the message in bytes excluding the message header * Flags: TBD * Rule: These will be the message/argument types we pass */ /* message data header */ #define FM10K_TLV_ID_SHIFT 0 #define FM10K_TLV_ID_SIZE 16 #define FM10K_TLV_ID_MASK ((1u << FM10K_TLV_ID_SIZE) - 1) #define FM10K_TLV_FLAGS_SHIFT 16 #define FM10K_TLV_FLAGS_MSG 0x1 #define FM10K_TLV_FLAGS_SIZE 4 #define FM10K_TLV_LEN_SHIFT 20 #define FM10K_TLV_LEN_SIZE 12 #define FM10K_TLV_HDR_LEN 4ul #define FM10K_TLV_LEN_ALIGN_MASK \ ((FM10K_TLV_HDR_LEN - 1) << FM10K_TLV_LEN_SHIFT) #define FM10K_TLV_LEN_ALIGN(tlv) \ (((tlv) + FM10K_TLV_LEN_ALIGN_MASK) & ~FM10K_TLV_LEN_ALIGN_MASK) #define FM10K_TLV_DWORD_LEN(tlv) \ ((u16)((FM10K_TLV_LEN_ALIGN(tlv)) >> (FM10K_TLV_LEN_SHIFT + 2)) + 1) #define FM10K_TLV_RESULTS_MAX 32 enum fm10k_tlv_type { FM10K_TLV_NULL_STRING, FM10K_TLV_MAC_ADDR, FM10K_TLV_BOOL, FM10K_TLV_UNSIGNED, FM10K_TLV_SIGNED, FM10K_TLV_LE_STRUCT, FM10K_TLV_NESTED, FM10K_TLV_MAX_TYPE }; #define FM10K_TLV_ERROR (~0u) struct fm10k_tlv_attr { unsigned int id; enum fm10k_tlv_type type; u16 len; }; #define FM10K_TLV_ATTR_NULL_STRING(id, len) { id, FM10K_TLV_NULL_STRING, len } #define FM10K_TLV_ATTR_MAC_ADDR(id) { id, FM10K_TLV_MAC_ADDR, 6 } #define FM10K_TLV_ATTR_BOOL(id) { id, FM10K_TLV_BOOL, 0 } #define FM10K_TLV_ATTR_U8(id) { id, FM10K_TLV_UNSIGNED, 1 } #define FM10K_TLV_ATTR_U16(id) { id, FM10K_TLV_UNSIGNED, 2 } #define FM10K_TLV_ATTR_U32(id) { id, FM10K_TLV_UNSIGNED, 4 } #define FM10K_TLV_ATTR_U64(id) { id, FM10K_TLV_UNSIGNED, 8 } #define FM10K_TLV_ATTR_S8(id) { id, FM10K_TLV_SIGNED, 1 } #define FM10K_TLV_ATTR_S16(id) { id, FM10K_TLV_SIGNED, 2 } #define FM10K_TLV_ATTR_S32(id) { id, FM10K_TLV_SIGNED, 4 } #define FM10K_TLV_ATTR_S64(id) { id, FM10K_TLV_SIGNED, 8 } #define FM10K_TLV_ATTR_LE_STRUCT(id, len) { id, FM10K_TLV_LE_STRUCT, len } #define FM10K_TLV_ATTR_NESTED(id) { id, FM10K_TLV_NESTED } #define FM10K_TLV_ATTR_LAST { FM10K_TLV_ERROR } struct fm10k_msg_data { unsigned int id; const struct fm10k_tlv_attr *attr; s32 (*func)(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); }; #define FM10K_MSG_HANDLER(id, attr, func) { id, attr, func } s32 fm10k_tlv_msg_init(u32 *, u16); s32 fm10k_tlv_attr_put_null_string(u32 *, u16, const unsigned char *); s32 fm10k_tlv_attr_get_null_string(u32 *, unsigned char *); s32 fm10k_tlv_attr_put_mac_vlan(u32 *, u16, const u8 *, u16); s32 fm10k_tlv_attr_get_mac_vlan(u32 *, u8 *, u16 *); s32 fm10k_tlv_attr_put_bool(u32 *, u16); s32 fm10k_tlv_attr_put_value(u32 *, u16, s64, u32); #define fm10k_tlv_attr_put_u8(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 1) #define fm10k_tlv_attr_put_u16(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 2) #define fm10k_tlv_attr_put_u32(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 4) #define fm10k_tlv_attr_put_u64(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 8) #define fm10k_tlv_attr_put_s8(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 1) #define fm10k_tlv_attr_put_s16(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 2) #define fm10k_tlv_attr_put_s32(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 4) #define fm10k_tlv_attr_put_s64(msg, attr_id, val) \ fm10k_tlv_attr_put_value(msg, attr_id, val, 8) s32 fm10k_tlv_attr_get_value(u32 *, void *, u32); #define fm10k_tlv_attr_get_u8(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(u8)) #define fm10k_tlv_attr_get_u16(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(u16)) #define fm10k_tlv_attr_get_u32(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(u32)) #define fm10k_tlv_attr_get_u64(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(u64)) #define fm10k_tlv_attr_get_s8(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(s8)) #define fm10k_tlv_attr_get_s16(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(s16)) #define fm10k_tlv_attr_get_s32(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(s32)) #define fm10k_tlv_attr_get_s64(attr, ptr) \ fm10k_tlv_attr_get_value(attr, ptr, sizeof(s64)) s32 fm10k_tlv_attr_put_le_struct(u32 *, u16, const void *, u32); s32 fm10k_tlv_attr_get_le_struct(u32 *, void *, u32); u32 *fm10k_tlv_attr_nest_start(u32 *, u16); s32 fm10k_tlv_attr_nest_stop(u32 *); s32 fm10k_tlv_attr_parse(u32 *, u32 **, const struct fm10k_tlv_attr *); s32 fm10k_tlv_msg_parse(struct fm10k_hw *, u32 *, struct fm10k_mbx_info *, const struct fm10k_msg_data *); s32 fm10k_tlv_msg_error(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *); #define FM10K_TLV_MSG_ID_TEST 0 enum fm10k_tlv_test_attr_id { FM10K_TEST_MSG_UNSET, FM10K_TEST_MSG_STRING, FM10K_TEST_MSG_MAC_ADDR, FM10K_TEST_MSG_U8, FM10K_TEST_MSG_U16, FM10K_TEST_MSG_U32, FM10K_TEST_MSG_U64, FM10K_TEST_MSG_S8, FM10K_TEST_MSG_S16, FM10K_TEST_MSG_S32, FM10K_TEST_MSG_S64, FM10K_TEST_MSG_LE_STRUCT, FM10K_TEST_MSG_NESTED, FM10K_TEST_MSG_RESULT, FM10K_TEST_MSG_MAX }; extern const struct fm10k_tlv_attr fm10k_tlv_msg_test_attr[]; void fm10k_tlv_msg_test_create(u32 *, u32); s32 fm10k_tlv_msg_test(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); #define FM10K_TLV_MSG_TEST_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_TLV_MSG_ID_TEST, fm10k_tlv_msg_test_attr, func) #define FM10K_TLV_MSG_ERROR_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_TLV_ERROR, NULL, func) #endif /* _FM10K_MSG_H_ */ ================================================ FILE: drivers/net/fm10k/base/fm10k_type.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_TYPE_H_ #define _FM10K_TYPE_H_ /* forward declaration */ struct fm10k_hw; #include "fm10k_osdep.h" #include "fm10k_mbx.h" #define FM10K_INTEL_VENDOR_ID 0x8086 #define FM10K_DEV_ID_PF 0x15A4 #define FM10K_DEV_ID_VF 0x15A5 #define FM10K_MAX_QUEUES 256 #define FM10K_MAX_QUEUES_PF 128 #define FM10K_MAX_QUEUES_POOL 16 #define FM10K_48_BIT_MASK 0x0000FFFFFFFFFFFFull #define FM10K_STAT_VALID 0x80000000 /* PCI Bus Info */ #define FM10K_PCIE_LINK_CAP 0x7C #define FM10K_PCIE_LINK_STATUS 0x82 #define FM10K_PCIE_LINK_WIDTH 0x3F0 #define FM10K_PCIE_LINK_WIDTH_1 0x10 #define FM10K_PCIE_LINK_WIDTH_2 0x20 #define FM10K_PCIE_LINK_WIDTH_4 0x40 #define FM10K_PCIE_LINK_WIDTH_8 0x80 #define FM10K_PCIE_LINK_SPEED 0xF #define FM10K_PCIE_LINK_SPEED_2500 0x1 #define FM10K_PCIE_LINK_SPEED_5000 0x2 #define FM10K_PCIE_LINK_SPEED_8000 0x3 /* PCIe payload size */ #define FM10K_PCIE_DEV_CAP 0x74 #define FM10K_PCIE_DEV_CAP_PAYLOAD 0x07 #define FM10K_PCIE_DEV_CAP_PAYLOAD_128 0x00 #define FM10K_PCIE_DEV_CAP_PAYLOAD_256 0x01 #define FM10K_PCIE_DEV_CAP_PAYLOAD_512 0x02 #define FM10K_PCIE_DEV_CTRL 0x78 #define FM10K_PCIE_DEV_CTRL_PAYLOAD 0xE0 #define FM10K_PCIE_DEV_CTRL_PAYLOAD_128 0x00 #define FM10K_PCIE_DEV_CTRL_PAYLOAD_256 0x20 #define FM10K_PCIE_DEV_CTRL_PAYLOAD_512 0x40 /* PCIe MSI-X Capability info */ #define FM10K_PCI_MSIX_MSG_CTRL 0xB2 #define FM10K_PCI_MSIX_MSG_CTRL_TBL_SZ_MASK 0x7FF #define FM10K_MAX_MSIX_VECTORS 256 #define FM10K_MAX_VECTORS_PF 256 #define FM10K_MAX_VECTORS_POOL 32 /* PCIe SR-IOV Info */ #define FM10K_PCIE_SRIOV_CTRL 0x190 #define FM10K_PCIE_SRIOV_CTRL_VFARI 0x10 #define FM10K_SUCCESS 0 #define FM10K_ERR_DEVICE_NOT_SUPPORTED -1 #define FM10K_ERR_PARAM -2 #define FM10K_ERR_NO_RESOURCES -3 #define FM10K_ERR_REQUESTS_PENDING -4 #define FM10K_ERR_RESET_REQUESTED -5 #define FM10K_ERR_DMA_PENDING -6 #define FM10K_ERR_RESET_FAILED -7 #define FM10K_ERR_INVALID_MAC_ADDR -8 #define FM10K_ERR_INVALID_VALUE -9 #define FM10K_NOT_IMPLEMENTED 0x7FFFFFFF #define UNREFERENCED_XPARAMETER #define UNREFERENCED_1PARAMETER(_p) (_p) #define UNREFERENCED_2PARAMETER(_p, _q) do { (_p); (_q); } while (0) #define UNREFERENCED_3PARAMETER(_p, _q, _r) do { (_p); (_q); (_r); } while (0) /* Start of PF registers */ #define FM10K_CTRL 0x0000 #define FM10K_CTRL_BAR4_ALLOWED 0x00000004 #define FM10K_CTRL_EXT 0x0001 #define FM10K_CTRL_EXT_NS_DIS 0x00000001 #define FM10K_CTRL_EXT_RO_DIS 0x00000002 #define FM10K_CTRL_EXT_SWITCH_LOOPBACK 0x00000004 #define FM10K_EXVET 0x0002 #define FM10K_EXVET_ETHERTYPE_MASK 0x000000FF #define FM10K_EXVET_TAG_SIZE_SHIFT 16 #define FM10K_EXVET_AFTER_VLAN 0x00040000 #define FM10K_GCR 0x0003 #define FM10K_FACTPS 0x0004 #define FM10K_GCR_EXT 0x0005 /* Interrupt control registers */ #define FM10K_EICR 0x0006 #define FM10K_EICR_PCA_FAULT 0x00000001 #define FM10K_EICR_THI_FAULT 0x00000004 #define FM10K_EICR_FUM_FAULT 0x00000020 #define FM10K_EICR_FAULT_MASK 0x0000003F #define FM10K_EICR_MAILBOX 0x00000040 #define FM10K_EICR_SWITCHREADY 0x00000080 #define FM10K_EICR_SWITCHNOTREADY 0x00000100 #define FM10K_EICR_SWITCHINTERRUPT 0x00000200 #define FM10K_EICR_SRAMERROR 0x00000400 #define FM10K_EICR_VFLR 0x00000800 #define FM10K_EICR_MAXHOLDTIME 0x00001000 #define FM10K_EIMR 0x0007 #define FM10K_EIMR_PCA_FAULT 0x00000001 #define FM10K_EIMR_THI_FAULT 0x00000010 #define FM10K_EIMR_FUM_FAULT 0x00000400 #define FM10K_EIMR_MAILBOX 0x00001000 #define FM10K_EIMR_SWITCHREADY 0x00004000 #define FM10K_EIMR_SWITCHNOTREADY 0x00010000 #define FM10K_EIMR_SWITCHINTERRUPT 0x00040000 #define FM10K_EIMR_SRAMERROR 0x00100000 #define FM10K_EIMR_VFLR 0x00400000 #define FM10K_EIMR_MAXHOLDTIME 0x01000000 #define FM10K_EIMR_ALL 0x55555555 #define FM10K_EIMR_DISABLE(NAME) ((FM10K_EIMR_ ## NAME) << 0) #define FM10K_EIMR_ENABLE(NAME) ((FM10K_EIMR_ ## NAME) << 1) #define FM10K_FAULT_ADDR_LO 0x0 #define FM10K_FAULT_ADDR_HI 0x1 #define FM10K_FAULT_SPECINFO 0x2 #define FM10K_FAULT_FUNC 0x3 #define FM10K_FAULT_SIZE 0x4 #define FM10K_FAULT_FUNC_VALID 0x00008000 #define FM10K_FAULT_FUNC_PF 0x00004000 #define FM10K_FAULT_FUNC_VF_MASK 0x00003F00 #define FM10K_FAULT_FUNC_VF_SHIFT 8 #define FM10K_FAULT_FUNC_TYPE_MASK 0x000000FF #define FM10K_PCA_FAULT 0x0008 #define FM10K_THI_FAULT 0x0010 #define FM10K_FUM_FAULT 0x001C /* Rx queue timeout indicator */ #define FM10K_MAXHOLDQ(_n) ((_n) + 0x0020) /* Switch Manager info */ #define FM10K_SM_AREA(_n) ((_n) + 0x0028) /* GLORT mapping registers */ #define FM10K_DGLORTMAP(_n) ((_n) + 0x0030) #define FM10K_DGLORT_COUNT 8 #define FM10K_DGLORTMAP_MASK_SHIFT 16 #define FM10K_DGLORTMAP_ANY 0x00000000 #define FM10K_DGLORTMAP_NONE 0x0000FFFF #define FM10K_DGLORTMAP_ZERO 0xFFFF0000 #define FM10K_DGLORTDEC(_n) ((_n) + 0x0038) #define FM10K_DGLORTDEC_VSILENGTH_SHIFT 4 #define FM10K_DGLORTDEC_VSIBASE_SHIFT 7 #define FM10K_DGLORTDEC_PCLENGTH_SHIFT 14 #define FM10K_DGLORTDEC_QBASE_SHIFT 16 #define FM10K_DGLORTDEC_RSSLENGTH_SHIFT 24 #define FM10K_DGLORTDEC_INNERRSS_ENABLE 0x08000000 #define FM10K_TUNNEL_CFG 0x0040 #define FM10K_TUNNEL_CFG_NVGRE_SHIFT 16 #define FM10K_TUNNEL_CFG_GENEVE 0x0041 #define FM10K_SWPRI_MAP(_n) ((_n) + 0x0050) #define FM10K_SWPRI_MAX 16 #define FM10K_RSSRK(_n, _m) (((_n) * 0x10) + (_m) + 0x0800) #define FM10K_RSSRK_SIZE 10 #define FM10K_RSSRK_ENTRIES_PER_REG 4 #define FM10K_RETA(_n, _m) (((_n) * 0x20) + (_m) + 0x1000) #define FM10K_RETA_SIZE 32 #define FM10K_RETA_ENTRIES_PER_REG 4 #define FM10K_MAX_RSS_INDICES 128 /* Rate limiting registers */ #define FM10K_TC_CREDIT(_n) ((_n) + 0x2000) #define FM10K_TC_CREDIT_CREDIT_MASK 0x001FFFFF #define FM10K_TC_MAXCREDIT(_n) ((_n) + 0x2040) #define FM10K_TC_MAXCREDIT_64K 0x00010000 #define FM10K_TC_RATE(_n) ((_n) + 0x2080) #define FM10K_TC_RATE_QUANTA_MASK 0x0000FFFF #define FM10K_TC_RATE_INTERVAL_4US_GEN1 0x00020000 #define FM10K_TC_RATE_INTERVAL_4US_GEN2 0x00040000 #define FM10K_TC_RATE_INTERVAL_4US_GEN3 0x00080000 #define FM10K_TC_RATE_STATUS 0x20C0 #define FM10K_PAUSE 0x20C2 /* DMA control registers */ #define FM10K_DMA_CTRL 0x20C3 #define FM10K_DMA_CTRL_TX_ENABLE 0x00000001 #define FM10K_DMA_CTRL_TX_HOST_PENDING 0x00000002 #define FM10K_DMA_CTRL_TX_DATA 0x00000004 #define FM10K_DMA_CTRL_TX_ACTIVE 0x00000008 #define FM10K_DMA_CTRL_RX_ENABLE 0x00000010 #define FM10K_DMA_CTRL_RX_HOST_PENDING 0x00000020 #define FM10K_DMA_CTRL_RX_DATA 0x00000040 #define FM10K_DMA_CTRL_RX_ACTIVE 0x00000080 #define FM10K_DMA_CTRL_RX_DESC_SIZE 0x00000100 #define FM10K_DMA_CTRL_MINMSS_SHIFT 9 #define FM10K_DMA_CTRL_MINMSS_64 0x00008000 #define FM10K_DMA_CTRL_MAX_HOLD_TIME_SHIFT 23 #define FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3 0x04800000 #define FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2 0x04000000 #define FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1 0x03800000 #define FM10K_DMA_CTRL_DATAPATH_RESET 0x20000000 #define FM10K_DMA_CTRL_MAXNUMOFQ_MASK 0xC0000000 #define FM10K_DMA_CTRL_32_DESC 0x00000000 #define FM10K_DMA_CTRL_64_DESC 0x40000000 #define FM10K_DMA_CTRL_128_DESC 0x80000000 #define FM10K_DMA_CTRL2 0x20C4 #define FM10K_DMA_CTRL2_TX_FRAME_SPACING_SHIFT 5 #define FM10K_DMA_CTRL2_SWITCH_READY 0x00002000 #define FM10K_DMA_CTRL2_RX_DESC_READ_PRIO_SHIFT 14 #define FM10K_DMA_CTRL2_TX_DESC_READ_PRIO_SHIFT 17 #define FM10K_DMA_CTRL2_TX_DATA_READ_PRIO_SHIFT 20 /* TSO flags configuration * First packet contains all flags except for fin and psh * Middle packet contains only urg and ack * Last packet contains urg, ack, fin, and psh */ #define FM10K_TSO_FLAGS_LOW 0x00300FF6 #define FM10K_TSO_FLAGS_HI 0x00000039 #define FM10K_DTXTCPFLGL 0x20C5 #define FM10K_DTXTCPFLGH 0x20C6 #define FM10K_TPH_CTRL 0x20C7 #define FM10K_TPH_CTRL_DISABLE_READ_HINT 0x00000080 #define FM10K_MRQC(_n) ((_n) + 0x2100) #define FM10K_MRQC_TCP_IPV4 0x00000001 #define FM10K_MRQC_IPV4 0x00000002 #define FM10K_MRQC_IPV6 0x00000010 #define FM10K_MRQC_TCP_IPV6 0x00000020 #define FM10K_MRQC_UDP_IPV4 0x00000040 #define FM10K_MRQC_UDP_IPV6 0x00000080 #define FM10K_TQMAP(_n) ((_n) + 0x2800) #define FM10K_TQMAP_TABLE_SIZE 2048 #define FM10K_RQMAP(_n) ((_n) + 0x3000) #define FM10K_RQMAP_TABLE_SIZE 2048 /* Hardware Statistics */ #define FM10K_STATS_TIMEOUT 0x3800 #define FM10K_STATS_UR 0x3801 #define FM10K_STATS_CA 0x3802 #define FM10K_STATS_UM 0x3803 #define FM10K_STATS_XEC 0x3804 #define FM10K_STATS_VLAN_DROP 0x3805 #define FM10K_STATS_LOOPBACK_DROP 0x3806 #define FM10K_STATS_NODESC_DROP 0x3807 /* Timesync registers */ #define FM10K_RRTIME_CFG 0x3808 #define FM10K_RRTIME_LIMIT(_n) ((_n) + 0x380C) #define FM10K_RRTIME_COUNT(_n) ((_n) + 0x3810) #define FM10K_SYSTIME 0x3814 #define FM10K_SYSTIME0 0x3816 #define FM10K_SYSTIME_CFG 0x3818 #define FM10K_SYSTIME_CFG_STEP_MASK 0x0000000F /* PCIe state registers */ #define FM10K_PFVFBME(_n) ((_n) + 0x381A) #define FM10K_PHYADDR 0x381C /* Rx ring registers */ #define FM10K_RDBAL(_n) ((0x40 * (_n)) + 0x4000) #define FM10K_RDBAH(_n) ((0x40 * (_n)) + 0x4001) #define FM10K_RDLEN(_n) ((0x40 * (_n)) + 0x4002) #define FM10K_TPH_RXCTRL(_n) ((0x40 * (_n)) + 0x4003) #define FM10K_TPH_RXCTRL_DESC_TPHEN 0x00000020 #define FM10K_TPH_RXCTRL_HDR_TPHEN 0x00000040 #define FM10K_TPH_RXCTRL_DATA_TPHEN 0x00000080 #define FM10K_TPH_RXCTRL_DESC_RROEN 0x00000200 #define FM10K_TPH_RXCTRL_DATA_WROEN 0x00002000 #define FM10K_TPH_RXCTRL_HDR_WROEN 0x00008000 #define FM10K_RDH(_n) ((0x40 * (_n)) + 0x4004) #define FM10K_RDT(_n) ((0x40 * (_n)) + 0x4005) #define FM10K_RXQCTL(_n) ((0x40 * (_n)) + 0x4006) #define FM10K_RXQCTL_ENABLE 0x00000001 #define FM10K_RXQCTL_PF 0x000000FC #define FM10K_RXQCTL_VF_SHIFT 2 #define FM10K_RXQCTL_VF 0x00000100 #define FM10K_RXQCTL_ID_MASK (FM10K_RXQCTL_PF | FM10K_RXQCTL_VF) #define FM10K_RXDCTL(_n) ((0x40 * (_n)) + 0x4007) #define FM10K_RXDCTL_WRITE_BACK_MIN_DELAY 0x00000001 #define FM10K_RXDCTL_WRITE_BACK_IMM 0x00000100 #define FM10K_RXDCTL_DROP_ON_EMPTY 0x00000200 #define FM10K_RXINT(_n) ((0x40 * (_n)) + 0x4008) #define FM10K_RXINT_TIMER_SHIFT 8 #define FM10K_SRRCTL(_n) ((0x40 * (_n)) + 0x4009) #define FM10K_SRRCTL_BSIZEPKT_SHIFT 8 /* shift _right_ */ #define FM10K_SRRCTL_BSIZEHDR_SHIFT 2 /* shift _left_ */ #define FM10K_SRRCTL_BSIZEHDR_MASK 0x00003F00 #define FM10K_SRRCTL_DESCTYPE_HDR_SPLIT 0x00004000 #define FM10K_SRRCTL_DESCTYPE_SIZE_SPLIT 0x00008000 #define FM10K_SRRCTL_PSRTYPE_INNER_TCPHDR 0x00010000 #define FM10K_SRRCTL_PSRTYPE_INNER_UDPHDR 0x00020000 #define FM10K_SRRCTL_PSRTYPE_INNER_IPV4HDR 0x00040000 #define FM10K_SRRCTL_PSRTYPE_INNER_IPV6HDR 0x00080000 #define FM10K_SRRCTL_PSRTYPE_INNER_L2HDR 0x00100000 #define FM10K_SRRCTL_PSRTYPE_ENCAPHDR 0x00200000 #define FM10K_SRRCTL_PSRTYPE_TCPHDR 0x00400000 #define FM10K_SRRCTL_PSRTYPE_UDPHDR 0x00800000 #define FM10K_SRRCTL_PSRTYPE_IPV4HDR 0x01000000 #define FM10K_SRRCTL_PSRTYPE_IPV6HDR 0x02000000 #define FM10K_SRRCTL_PSRTYPE_L2HDR 0x04000000 #define FM10K_SRRCTL_LOOPBACK_SUPPRESS 0x40000000 #define FM10K_SRRCTL_BUFFER_CHAINING_EN 0x80000000 /* Rx Statistics */ #define FM10K_QPRC(_n) ((0x40 * (_n)) + 0x400A) #define FM10K_QPRDC(_n) ((0x40 * (_n)) + 0x400B) #define FM10K_QBRC_L(_n) ((0x40 * (_n)) + 0x400C) #define FM10K_QBRC_H(_n) ((0x40 * (_n)) + 0x400D) /* Rx GLORT register */ #define FM10K_RX_SGLORT(_n) ((0x40 * (_n)) + 0x400E) /* Tx ring registers */ #define FM10K_TDBAL(_n) ((0x40 * (_n)) + 0x8000) #define FM10K_TDBAH(_n) ((0x40 * (_n)) + 0x8001) #define FM10K_TDLEN(_n) ((0x40 * (_n)) + 0x8002) #define FM10K_TPH_TXCTRL(_n) ((0x40 * (_n)) + 0x8003) #define FM10K_TPH_TXCTRL_DESC_TPHEN 0x00000020 #define FM10K_TPH_TXCTRL_DESC_RROEN 0x00000200 #define FM10K_TPH_TXCTRL_DESC_WROEN 0x00000800 #define FM10K_TPH_TXCTRL_DATA_RROEN 0x00002000 #define FM10K_TDH(_n) ((0x40 * (_n)) + 0x8004) #define FM10K_TDT(_n) ((0x40 * (_n)) + 0x8005) #define FM10K_TXDCTL(_n) ((0x40 * (_n)) + 0x8006) #define FM10K_TXDCTL_ENABLE 0x00004000 #define FM10K_TXDCTL_MAX_TIME_SHIFT 16 #define FM10K_TXDCTL_PUSH_DESC 0x10000000 #define FM10K_TXQCTL(_n) ((0x40 * (_n)) + 0x8007) #define FM10K_TXQCTL_PF 0x0000003F #define FM10K_TXQCTL_VF 0x00000040 #define FM10K_TXQCTL_ID_MASK (FM10K_TXQCTL_PF | FM10K_TXQCTL_VF) #define FM10K_TXQCTL_PC_SHIFT 7 #define FM10K_TXQCTL_PC_MASK 0x00000380 #define FM10K_TXQCTL_TC_SHIFT 10 #define FM10K_TXQCTL_TC_MASK 0x0000FC00 #define FM10K_TXQCTL_VID_SHIFT 16 #define FM10K_TXQCTL_VID_MASK 0x0FFF0000 #define FM10K_TXQCTL_UNLIMITED_BW 0x10000000 #define FM10K_TXQCTL_PUSHMODEDIS 0x20000000 #define FM10K_TXINT(_n) ((0x40 * (_n)) + 0x8008) #define FM10K_TXINT_TIMER_SHIFT 8 /* Tx Statistics */ #define FM10K_QPTC(_n) ((0x40 * (_n)) + 0x8009) #define FM10K_QBTC_L(_n) ((0x40 * (_n)) + 0x800A) #define FM10K_QBTC_H(_n) ((0x40 * (_n)) + 0x800B) /* Tx Push registers */ #define FM10K_TQDLOC(_n) ((0x40 * (_n)) + 0x800C) #define FM10K_TQDLOC_BASE_32_DESC 0x08 #define FM10K_TQDLOC_BASE_64_DESC 0x10 #define FM10K_TQDLOC_BASE_128_DESC 0x20 #define FM10K_TQDLOC_SIZE_32_DESC 0x00050000 #define FM10K_TQDLOC_SIZE_64_DESC 0x00060000 #define FM10K_TQDLOC_SIZE_128_DESC 0x00070000 #define FM10K_TQDLOC_SIZE_SHIFT 16 #define FM10K_TX_DCACHE(_n, _m) ((0x400 * (_n)) + (0x4 * (_m)) + 0x40000) /* Tx GLORT registers */ #define FM10K_TX_SGLORT(_n) ((0x40 * (_n)) + 0x800D) #define FM10K_PFVTCTL(_n) ((0x40 * (_n)) + 0x800E) #define FM10K_PFVTCTL_FTAG_DESC_ENABLE 0x00000001 /* Interrupt moderation and control registers */ #define FM10K_PBACL(_n) ((_n) + 0x10000) #define FM10K_INT_MAP(_n) ((_n) + 0x10080) #define FM10K_INT_MAP_TIMER0 0x00000000 #define FM10K_INT_MAP_TIMER1 0x00000100 #define FM10K_INT_MAP_IMMEDIATE 0x00000200 #define FM10K_INT_MAP_DISABLE 0x00000300 #define FM10K_MSIX_VECTOR_ADDR_LO(_n) ((0x4 * (_n)) + 0x11000) #define FM10K_MSIX_VECTOR_ADDR_HI(_n) ((0x4 * (_n)) + 0x11001) #define FM10K_MSIX_VECTOR_DATA(_n) ((0x4 * (_n)) + 0x11002) #define FM10K_MSIX_VECTOR_MASK(_n) ((0x4 * (_n)) + 0x11003) #define FM10K_INT_CTRL 0x12000 #define FM10K_INT_CTRL_ENABLEMODERATOR 0x00000400 #define FM10K_ITR(_n) ((_n) + 0x12400) #define FM10K_ITR_INTERVAL1_SHIFT 12 #define FM10K_ITR_TIMER0_EXPIRED 0x01000000 #define FM10K_ITR_TIMER1_EXPIRED 0x02000000 #define FM10K_ITR_PENDING0 0x04000000 #define FM10K_ITR_PENDING1 0x08000000 #define FM10K_ITR_PENDING2 0x10000000 #define FM10K_ITR_AUTOMASK 0x20000000 #define FM10K_ITR_MASK_SET 0x40000000 #define FM10K_ITR_MASK_CLEAR 0x80000000 #define FM10K_ITR2(_n) ((0x2 * (_n)) + 0x12800) #define FM10K_ITR2_LP(_n) ((0x2 * (_n)) + 0x12801) #define FM10K_ITR_REG_COUNT 768 #define FM10K_ITR_REG_COUNT_PF 256 /* Switch manager interrupt registers */ #define FM10K_IP 0x13000 #define FM10K_IP_HOT_RESET 0x00000001 #define FM10K_IP_DEVICE_STATE_CHANGE 0x00000002 #define FM10K_IP_MAILBOX 0x00000004 #define FM10K_IP_VPD_REQUEST 0x00000008 #define FM10K_IP_SRAMERROR 0x00000010 #define FM10K_IP_PFLR 0x00000020 #define FM10K_IP_DATAPATHRESET 0x00000040 #define FM10K_IP_OUTOFRESET 0x00000080 #define FM10K_IP_NOTINRESET 0x00000100 #define FM10K_IP_TIMEOUT 0x00000200 #define FM10K_IP_VFLR 0x00000400 #define FM10K_IM 0x13001 #define FM10K_IB 0x13002 #define FM10K_SRAM_IP 0x13003 #define FM10K_SRAM_IM 0x13004 /* VLAN registers */ #define FM10K_VLAN_TABLE(_n, _m) ((0x80 * (_n)) + (_m) + 0x14000) #define FM10K_VLAN_TABLE_SIZE 128 /* VLAN specific message offsets */ #define FM10K_VLAN_TABLE_VID_MAX 4096 #define FM10K_VLAN_TABLE_VSI_MAX 64 #define FM10K_VLAN_LENGTH_SHIFT 16 #define FM10K_VLAN_CLEAR (1 << 15) #define FM10K_VLAN_ALL \ ((FM10K_VLAN_TABLE_VID_MAX - 1) << FM10K_VLAN_LENGTH_SHIFT) /* VF FLR event notification registers */ #define FM10K_PFVFLRE(_n) ((0x1 * (_n)) + 0x18844) #define FM10K_PFVFLREC(_n) ((0x1 * (_n)) + 0x18846) /* Defines for size of uncacheable and write-combining memories */ #define FM10K_UC_ADDR_START 0x000000 /* start of standard regs */ #define FM10K_WC_ADDR_START 0x100000 /* start of Tx Desc Cache */ #define FM10K_DBI_ADDR_START 0x200000 /* start of debug registers */ #define FM10K_UC_ADDR_SIZE (FM10K_WC_ADDR_START - FM10K_UC_ADDR_START) #define FM10K_WC_ADDR_SIZE (FM10K_DBI_ADDR_START - FM10K_WC_ADDR_START) /* Define timeouts for resets and disables */ #define FM10K_QUEUE_DISABLE_TIMEOUT 100 #define FM10K_RESET_TIMEOUT 150 /* Maximum supported combined inner and outer header length for encapsulation */ #define FM10K_TUNNEL_HEADER_LENGTH 184 /* VF registers */ #define FM10K_VFCTRL 0x00000 #define FM10K_VFCTRL_RST 0x00000008 #define FM10K_VFINT_MAP 0x00030 #define FM10K_VFSYSTIME 0x00040 #define FM10K_VFITR(_n) ((_n) + 0x00060) #define FM10K_VFPBACL(_n) ((_n) + 0x00008) /* Registers contained in BAR 4 for Switch management */ #define FM10K_SW_SYSTIME_CFG 0x0224C #define FM10K_SW_SYSTIME_CFG_STEP_SHIFT 4 #define FM10K_SW_SYSTIME_CFG_ADJUST_MASK 0xFF000000 #define FM10K_SW_SYSTIME_ADJUST 0x0224D #define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF #define FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE 0x80000000 #define FM10K_SW_SYSTIME_PULSE(_n) ((_n) + 0x02252) #ifndef ETH_ALEN #define ETH_ALEN 6 #endif /* ETH_ALEN */ enum fm10k_int_source { fm10k_int_Mailbox = 0, fm10k_int_PCIeFault = 1, fm10k_int_SwitchUpDown = 2, fm10k_int_SwitchEvent = 3, fm10k_int_SRAM = 4, fm10k_int_VFLR = 5, fm10k_int_MaxHoldTime = 6, fm10k_int_sources_max_pf }; /* PCIe bus speeds */ enum fm10k_bus_speed { fm10k_bus_speed_unknown = 0, fm10k_bus_speed_2500 = 2500, fm10k_bus_speed_5000 = 5000, fm10k_bus_speed_8000 = 8000, fm10k_bus_speed_reserved }; /* PCIe bus widths */ enum fm10k_bus_width { fm10k_bus_width_unknown = 0, fm10k_bus_width_pcie_x1 = 1, fm10k_bus_width_pcie_x2 = 2, fm10k_bus_width_pcie_x4 = 4, fm10k_bus_width_pcie_x8 = 8, fm10k_bus_width_reserved }; /* PCIe payload sizes */ enum fm10k_bus_payload { fm10k_bus_payload_unknown = 0, fm10k_bus_payload_128 = 1, fm10k_bus_payload_256 = 2, fm10k_bus_payload_512 = 3, fm10k_bus_payload_reserved }; /* Bus parameters */ struct fm10k_bus_info { enum fm10k_bus_speed speed; enum fm10k_bus_width width; enum fm10k_bus_payload payload; }; /* Statistics related declarations */ struct fm10k_hw_stat { u64 count; u32 base_l; u32 base_h; }; struct fm10k_hw_stats_q { struct fm10k_hw_stat tx_bytes; struct fm10k_hw_stat tx_packets; #define tx_stats_idx tx_packets.base_h struct fm10k_hw_stat rx_bytes; struct fm10k_hw_stat rx_packets; #define rx_stats_idx rx_packets.base_h struct fm10k_hw_stat rx_drops; }; struct fm10k_hw_stats { struct fm10k_hw_stat timeout; #define stats_idx timeout.base_h struct fm10k_hw_stat ur; struct fm10k_hw_stat ca; struct fm10k_hw_stat um; struct fm10k_hw_stat xec; struct fm10k_hw_stat vlan_drop; struct fm10k_hw_stat loopback_drop; struct fm10k_hw_stat nodesc_drop; struct fm10k_hw_stats_q q[FM10K_MAX_QUEUES_PF]; }; /* Establish DGLORT feature priority */ enum fm10k_dglortdec_idx { fm10k_dglort_default = 0, fm10k_dglort_vf_rsvd0 = 1, fm10k_dglort_vf_rss = 2, fm10k_dglort_pf_rsvd0 = 3, fm10k_dglort_pf_queue = 4, fm10k_dglort_pf_vsi = 5, fm10k_dglort_pf_rsvd1 = 6, fm10k_dglort_pf_rss = 7 }; struct fm10k_dglort_cfg { u16 glort; /* GLORT base */ u16 queue_b; /* Base value for queue */ u8 vsi_b; /* Base value for VSI */ u8 idx; /* index of DGLORTDEC entry */ u8 rss_l; /* RSS indices */ u8 pc_l; /* Priority Class indices */ u8 vsi_l; /* Number of bits from GLORT used to determine VSI */ u8 queue_l; /* Number of bits from GLORT used to determine queue */ u8 shared_l; /* Ignored bits from GLORT resulting in shared VSI */ u8 inner_rss; /* Boolean value if inner header is used for RSS */ }; enum fm10k_pca_fault { PCA_NO_FAULT, PCA_UNMAPPED_ADDR, PCA_BAD_QACCESS_PF, PCA_BAD_QACCESS_VF, PCA_MALICIOUS_REQ, PCA_POISONED_TLP, PCA_TLP_ABORT, __PCA_MAX }; enum fm10k_thi_fault { THI_NO_FAULT, THI_MAL_DIS_Q_FAULT, __THI_MAX }; enum fm10k_fum_fault { FUM_NO_FAULT, FUM_UNMAPPED_ADDR, FUM_POISONED_TLP, FUM_BAD_VF_QACCESS, FUM_ADD_DECODE_ERR, FUM_RO_ERROR, FUM_QPRC_CRC_ERROR, FUM_CSR_TIMEOUT, FUM_INVALID_TYPE, FUM_INVALID_LENGTH, FUM_INVALID_BE, FUM_INVALID_ALIGN, __FUM_MAX }; struct fm10k_fault { u64 address; /* Address at the time fault was detected */ u32 specinfo; /* Extra info on this fault (fault dependent) */ u8 type; /* Fault value dependent on subunit */ u8 func; /* Function number of the fault */ }; struct fm10k_mac_ops { /* basic bring-up and tear-down */ s32 (*reset_hw)(struct fm10k_hw *); s32 (*init_hw)(struct fm10k_hw *); s32 (*start_hw)(struct fm10k_hw *); s32 (*stop_hw)(struct fm10k_hw *); s32 (*get_bus_info)(struct fm10k_hw *); s32 (*get_host_state)(struct fm10k_hw *, bool *); bool (*is_slot_appropriate)(struct fm10k_hw *); s32 (*update_vlan)(struct fm10k_hw *, u32, u8, bool); s32 (*read_mac_addr)(struct fm10k_hw *); s32 (*update_uc_addr)(struct fm10k_hw *, u16, const u8 *, u16, bool, u8); s32 (*update_mc_addr)(struct fm10k_hw *, u16, const u8 *, u16, bool); s32 (*update_xcast_mode)(struct fm10k_hw *, u16, u8); void (*update_int_moderator)(struct fm10k_hw *); s32 (*update_lport_state)(struct fm10k_hw *, u16, u16, bool); void (*update_hw_stats)(struct fm10k_hw *, struct fm10k_hw_stats *); void (*rebind_hw_stats)(struct fm10k_hw *, struct fm10k_hw_stats *); s32 (*configure_dglort_map)(struct fm10k_hw *, struct fm10k_dglort_cfg *); void (*set_dma_mask)(struct fm10k_hw *, u64); s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *); void (*request_lport_map)(struct fm10k_hw *); s32 (*adjust_systime)(struct fm10k_hw *, s32 ppb); u64 (*read_systime)(struct fm10k_hw *); s32 (*request_tx_timestamp_mode)(struct fm10k_hw *, u16, u8); }; enum fm10k_mac_type { fm10k_mac_unknown = 0, fm10k_mac_pf, fm10k_mac_vf, fm10k_num_macs }; struct fm10k_mac_info { struct fm10k_mac_ops ops; enum fm10k_mac_type type; u8 addr[ETH_ALEN]; u8 perm_addr[ETH_ALEN]; u16 default_vid; u16 max_msix_vectors; u16 max_queues; bool vlan_override; bool get_host_state; bool tx_ready; u32 dglort_map; }; struct fm10k_swapi_table_info { u32 used; u32 avail; }; struct fm10k_swapi_info { u32 status; struct fm10k_swapi_table_info mac; struct fm10k_swapi_table_info nexthop; struct fm10k_swapi_table_info ffu; }; enum fm10k_xcast_modes { FM10K_XCAST_MODE_ALLMULTI = 0, FM10K_XCAST_MODE_MULTI = 1, FM10K_XCAST_MODE_PROMISC = 2, FM10K_XCAST_MODE_NONE = 3, FM10K_XCAST_MODE_DISABLE = 4 }; enum fm10k_timestamp_modes { FM10K_TIMESTAMP_MODE_NONE = 0, FM10K_TIMESTAMP_MODE_PEP_TO_PEP = 1, FM10K_TIMESTAMP_MODE_PEP_TO_ANY = 2, }; #define FM10K_VF_TC_MAX 100000 /* 100,000 Mb/s aka 100Gb/s */ #define FM10K_VF_TC_MIN 1 /* 1 Mb/s is the slowest rate */ struct fm10k_vf_info { /* mbx must be first field in struct unless all default IOV message * handlers are redone as the assumption is that vf_info starts * at the same offset as the mailbox */ struct fm10k_mbx_info mbx; /* PF side of VF mailbox */ int rate; /* Tx BW cap as defined by OS */ u16 glort; /* resource tag for this VF */ u16 sw_vid; /* Switch API assigned VLAN */ u16 pf_vid; /* PF assigned Default VLAN */ u8 mac[ETH_ALEN]; /* PF Default MAC address */ u8 vsi; /* VSI identifier */ u8 vf_idx; /* which VF this is */ u8 vf_flags; /* flags indicating what modes * are supported for the port */ }; #define FM10K_VF_FLAG_ALLMULTI_CAPABLE ((u8)1 << FM10K_XCAST_MODE_ALLMULTI) #define FM10K_VF_FLAG_MULTI_CAPABLE ((u8)1 << FM10K_XCAST_MODE_MULTI) #define FM10K_VF_FLAG_PROMISC_CAPABLE ((u8)1 << FM10K_XCAST_MODE_PROMISC) #define FM10K_VF_FLAG_NONE_CAPABLE ((u8)1 << FM10K_XCAST_MODE_NONE) #define FM10K_VF_FLAG_CAPABLE(vf_info) ((vf_info)->vf_flags & (u8)0xF) #define FM10K_VF_FLAG_ENABLED(vf_info) ((vf_info)->vf_flags >> 4) #define FM10K_VF_FLAG_SET_MODE(mode) ((u8)0x10 << (mode)) #define FM10K_VF_FLAG_ENABLED_MODE_SHIFT 4 #define FM10K_VF_FLAG_SET_MODE_MASK ((u8)0xF0) #define FM10K_VF_FLAG_SET_MODE_NONE \ FM10K_VF_FLAG_SET_MODE(FM10K_XCAST_MODE_NONE) #define FM10K_VF_FLAG_MULTI_ENABLED \ (FM10K_VF_FLAG_SET_MODE(FM10K_XCAST_MODE_ALLMULTI) | \ FM10K_VF_FLAG_SET_MODE(FM10K_XCAST_MODE_MULTI) | \ FM10K_VF_FLAG_SET_MODE(FM10K_XCAST_MODE_PROMISC)) struct fm10k_iov_ops { /* IOV related bring-up and tear-down */ s32 (*assign_resources)(struct fm10k_hw *, u16, u16); s32 (*configure_tc)(struct fm10k_hw *, u16, int); s32 (*assign_int_moderator)(struct fm10k_hw *, u16); s32 (*assign_default_mac_vlan)(struct fm10k_hw *, struct fm10k_vf_info *); s32 (*reset_resources)(struct fm10k_hw *, struct fm10k_vf_info *); s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8); void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *); void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16); s32 (*report_timestamp)(struct fm10k_hw *, struct fm10k_vf_info *, u64); }; struct fm10k_iov_info { struct fm10k_iov_ops ops; u16 total_vfs; u16 num_vfs; u16 num_pools; }; struct fm10k_hw { u32 *hw_addr; u32 *sw_addr; void *back; struct fm10k_mac_info mac; struct fm10k_bus_info bus; struct fm10k_bus_info bus_caps; struct fm10k_iov_info iov; struct fm10k_mbx_info mbx; struct fm10k_swapi_info swapi; u16 device_id; u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; u8 revision_id; }; /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define FM10K_REQ_TX_DESCRIPTOR_MULTIPLE 8 #define FM10K_REQ_RX_DESCRIPTOR_MULTIPLE 8 /* Transmit Descriptor */ struct fm10k_tx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ __le16 buflen; /* Length of data to be DMAed */ __le16 vlan; /* VLAN_ID and VPRI to be inserted in FTAG */ __le16 mss; /* MSS for segmentation offload */ u8 hdrlen; /* Header size for segmentation offload */ u8 flags; /* Status and offload request flags */ }; /* Transmit Descriptor Cache Structure */ struct fm10k_tx_desc_cache { struct fm10k_tx_desc tx_desc[256]; }; #define FM10K_TXD_FLAG_INT 0x01 #define FM10K_TXD_FLAG_TIME 0x02 #define FM10K_TXD_FLAG_CSUM 0x04 #define FM10K_TXD_FLAG_CSUM2 0x08 #define FM10K_TXD_FLAG_FTAG 0x10 #define FM10K_TXD_FLAG_RS 0x20 #define FM10K_TXD_FLAG_LAST 0x40 #define FM10K_TXD_FLAG_DONE 0x80 #define FM10K_TXD_VLAN_PRI_SHIFT 12 /* These macros are meant to enable optimal placement of the RS and INT * bits. It will point us to the last descriptor in the cache for either the * start of the packet, or the end of the packet. If the index is actually * at the start of the FIFO it will point to the offset for the last index * in the FIFO to prevent an unnecessary write. */ #define FM10K_TXD_WB_FIFO_SIZE 4 #define FM10K_TXD_WB_IDX(idx) \ (((idx) - 1) | (FM10K_TXD_WB_FIFO_SIZE - 1)) /* Receive Descriptor - 32B */ union fm10k_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ __le64 reserved; /* Empty space, RSS hash */ __le64 timestamp; } q; /* Read, Writeback, 64b quad-words */ struct { __le32 data; /* RSS and header data */ __le32 rss; /* RSS Hash */ __le32 staterr; __le32 vlan_len; __le32 glort; /* sglort/dglort */ } d; /* Writeback, 32b double-words */ struct { __le16 pkt_info; /* RSS, Pkt type */ __le16 hdr_info; /* Splithdr, hdrlen, xC */ __le16 rss_lower; __le16 rss_upper; __le16 status; /* status/error */ __le16 csum_err; /* checksum or extended error value */ __le16 length; /* Packet length */ __le16 vlan; /* VLAN tag */ __le16 dglort; __le16 sglort; } w; /* Writeback, 16b words */ }; #define FM10K_RXD_RSSTYPE_MASK 0x000F enum fm10k_rdesc_rss_type { FM10K_RSSTYPE_NONE = 0x0, FM10K_RSSTYPE_IPV4_TCP = 0x1, FM10K_RSSTYPE_IPV4 = 0x2, FM10K_RSSTYPE_IPV6_TCP = 0x3, /* Reserved 0x4 */ FM10K_RSSTYPE_IPV6 = 0x5, /* Reserved 0x6 */ FM10K_RSSTYPE_IPV4_UDP = 0x7, FM10K_RSSTYPE_IPV6_UDP = 0x8 /* Reserved 0x9 - 0xF */ }; #define FM10K_RXD_PKTTYPE_MASK 0x03F0 #define FM10K_RXD_PKTTYPE_MASK_L3 0x0070 #define FM10K_RXD_PKTTYPE_MASK_L4 0x0380 #define FM10K_RXD_PKTTYPE_SHIFT 4 #define FM10K_RXD_PKTTYPE_INNER_MASK_L3 0x1C00 #define FM10K_RXD_PKTTYPE_INNER_MASK_L4 0xE000 #define FM10K_RXD_PKTTYPE_INNER_SHIFT 10 enum fm10k_rdesc_pkt_type { /* L3 type */ FM10K_PKTTYPE_OTHER = 0x00, FM10K_PKTTYPE_IPV4 = 0x01, FM10K_PKTTYPE_IPV4_EX = 0x02, FM10K_PKTTYPE_IPV6 = 0x03, FM10K_PKTTYPE_IPV6_EX = 0x04, /* L4 type */ FM10K_PKTTYPE_TCP = 0x08, FM10K_PKTTYPE_UDP = 0x10, FM10K_PKTTYPE_GRE = 0x18, FM10K_PKTTYPE_VXLAN = 0x20, FM10K_PKTTYPE_NVGRE = 0x28, FM10K_PKTTYPE_GENEVE = 0x30 }; #define FM10K_RXD_HDR_INFO_XC_MASK 0x0006 enum fm10k_rxdesc_xc { FM10K_XC_UNICAST = 0x0, FM10K_XC_MULTICAST = 0x4, FM10K_XC_BROADCAST = 0x6 }; #define FM10K_RXD_HDR_INFO_LEN_SHIFT 5 #define FM10K_RXD_HDR_INFO_SPH 0x8000 #define FM10K_RXD_STATUS_DD 0x0001 /* Descriptor done */ #define FM10K_RXD_STATUS_EOP 0x0002 /* End of packet */ #define FM10K_RXD_STATUS_VEXT 0x0004 /* A VLAN tag is present */ #define FM10K_RXD_STATUS_IPCS 0x0008 /* Indicates IPv4 csum */ #define FM10K_RXD_STATUS_L4CS 0x0010 /* Indicates an L4 csum */ #define FM10K_RXD_STATUS_IPCS2 0x0020 /* Inner header IPv4 csum */ #define FM10K_RXD_STATUS_L4CS2 0x0040 /* Inner header L4 csum */ #define FM10K_RXD_STATUS_IPFRAG_MASK 0x0180 /* Fragment mask */ #define FM10K_RXD_STATUS_IPFRAG_CSUM 0x0100 /* Fragment w/ CSUM field */ #define FM10K_RXD_STATUS_VEXT2 0x0200 /* A custom tag is present */ #define FM10K_RXD_STATUS_HBO 0x0400 /* header buffer overrun */ #define FM10K_RXD_STATUS_L4E2 0x0800 /* Inner header L4 csum err */ #define FM10K_RXD_STATUS_IPE2 0x1000 /* Inner header IPv4 csum err */ #define FM10K_RXD_STATUS_RXE 0x2000 /* Generic Rx error */ #define FM10K_RXD_STATUS_L4E 0x4000 /* L4 csum error */ #define FM10K_RXD_STATUS_IPE 0x8000 /* IPv4 csum error */ #define FM10K_RXD_ERR_SWITCH_ERROR 0x0001 /* Switch found bad packet */ #define FM10K_RXD_ERR_NO_DESCRIPTOR 0x0002 /* No descriptor available */ #define FM10K_RXD_ERR_PP_ERROR 0x0004 /* RAM error during processing */ #define FM10K_RXD_ERR_SWITCH_READY 0x0008 /* Link transition mid-packet */ #define FM10K_RXD_ERR_TOO_BIG 0x0010 /* Pkt too big for single buf */ #define FM10K_RXD_VLAN_ID_MASK 0x0FFF #define FM10K_RXD_VLAN_PRI_SHIFT FM10K_TXD_VLAN_PRI_SHIFT struct fm10k_ftag { __be16 swpri_type_user; __be16 vlan; __be16 sglort; __be16 dglort; }; #endif /* _FM10K_TYPE_H */ ================================================ FILE: drivers/net/fm10k/base/fm10k_vf.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "fm10k_vf.h" /** * fm10k_stop_hw_vf - Stop Tx/Rx units * @hw: pointer to hardware structure * **/ STATIC s32 fm10k_stop_hw_vf(struct fm10k_hw *hw) { u8 *perm_addr = hw->mac.perm_addr; u32 bal = 0, bah = 0; s32 err; u16 i; DEBUGFUNC("fm10k_stop_hw_vf"); /* we need to disable the queues before taking further steps */ err = fm10k_stop_hw_generic(hw); if (err) return err; /* If permanent address is set then we need to restore it */ if (FM10K_IS_VALID_ETHER_ADDR(perm_addr)) { bal = (((u32)perm_addr[3]) << 24) | (((u32)perm_addr[4]) << 16) | (((u32)perm_addr[5]) << 8); bah = (((u32)0xFF) << 24) | (((u32)perm_addr[0]) << 16) | (((u32)perm_addr[1]) << 8) | ((u32)perm_addr[2]); } /* The queues have already been disabled so we just need to * update their base address registers */ for (i = 0; i < hw->mac.max_queues; i++) { FM10K_WRITE_REG(hw, FM10K_TDBAL(i), bal); FM10K_WRITE_REG(hw, FM10K_TDBAH(i), bah); FM10K_WRITE_REG(hw, FM10K_RDBAL(i), bal); FM10K_WRITE_REG(hw, FM10K_RDBAH(i), bah); } return FM10K_SUCCESS; } /** * fm10k_reset_hw_vf - VF hardware reset * @hw: pointer to hardware structure * * This function should return the hardware to a state similar to the * one it is in after just being initialized. **/ STATIC s32 fm10k_reset_hw_vf(struct fm10k_hw *hw) { s32 err; DEBUGFUNC("fm10k_reset_hw_vf"); /* shut down queues we own and reset DMA configuration */ err = fm10k_stop_hw_vf(hw); if (err) return err; /* Inititate VF reset */ FM10K_WRITE_REG(hw, FM10K_VFCTRL, FM10K_VFCTRL_RST); /* Flush write and allow 100us for reset to complete */ FM10K_WRITE_FLUSH(hw); usec_delay(FM10K_RESET_TIMEOUT); /* Clear reset bit and verify it was cleared */ FM10K_WRITE_REG(hw, FM10K_VFCTRL, 0); if (FM10K_READ_REG(hw, FM10K_VFCTRL) & FM10K_VFCTRL_RST) err = FM10K_ERR_RESET_FAILED; return err; } /** * fm10k_init_hw_vf - VF hardware initialization * @hw: pointer to hardware structure * **/ STATIC s32 fm10k_init_hw_vf(struct fm10k_hw *hw) { u32 tqdloc, tqdloc0 = ~FM10K_READ_REG(hw, FM10K_TQDLOC(0)); s32 err; u16 i; DEBUGFUNC("fm10k_init_hw_vf"); /* assume we always have at least 1 queue */ for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) { /* verify the Descriptor cache offsets are increasing */ tqdloc = ~FM10K_READ_REG(hw, FM10K_TQDLOC(i)); if (!tqdloc || (tqdloc == tqdloc0)) break; /* check to verify the PF doesn't own any of our queues */ if (!~FM10K_READ_REG(hw, FM10K_TXQCTL(i)) || !~FM10K_READ_REG(hw, FM10K_RXQCTL(i))) break; } /* shut down queues we own and reset DMA configuration */ err = fm10k_disable_queues_generic(hw, i); if (err) return err; /* record maximum queue count */ hw->mac.max_queues = i; /* fetch default VLAN */ hw->mac.default_vid = (FM10K_READ_REG(hw, FM10K_TXQCTL(0)) & FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT; return FM10K_SUCCESS; } /** * fm10k_is_slot_appropriate_vf - Indicate appropriate slot for this SKU * @hw: pointer to hardware structure * * Looks at the PCIe bus info to confirm whether or not this slot can support * the necessary bandwidth for this device. Since the VF has no control over * the "slot" it is in, always indicate that the slot is appropriate. **/ STATIC bool fm10k_is_slot_appropriate_vf(struct fm10k_hw *hw) { UNREFERENCED_1PARAMETER(hw); DEBUGFUNC("fm10k_is_slot_appropriate_vf"); return TRUE; } /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = { FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN), FM10K_TLV_ATTR_BOOL(FM10K_MAC_VLAN_MSG_SET), FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MAC), FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_DEFAULT_MAC), FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MULTICAST), FM10K_TLV_ATTR_LAST }; /** * fm10k_update_vlan_vf - Update status of VLAN ID in VLAN filter table * @hw: pointer to hardware structure * @vid: VLAN ID to add to table * @vsi: Reserved, should always be 0 * @set: Indicates if this is a set or clear operation * * This function adds or removes the corresponding VLAN ID from the VLAN * filter table for this VF. **/ STATIC s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[4]; /* verify the index is not set */ if (vsi) return FM10K_ERR_PARAM; /* verify upper 4 bits of vid and length are 0 */ if ((vid << 16 | vid) >> 28) return FM10K_ERR_PARAM; /* encode set bit into the VLAN ID */ if (!set) vid |= FM10K_VLAN_CLEAR; /* generate VLAN request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); fm10k_tlv_attr_put_u32(msg, FM10K_MAC_VLAN_MSG_VLAN, vid); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_msg_mac_vlan_vf - Read device MAC address from mailbox message * @hw: pointer to the HW structure * @results: Attributes for message * @mbx: unused mailbox data * * This function should determine the MAC address for the VF **/ s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { u8 perm_addr[ETH_ALEN]; u16 vid; s32 err; UNREFERENCED_1PARAMETER(mbx); DEBUGFUNC("fm10k_msg_mac_vlan_vf"); /* record MAC address requested */ err = fm10k_tlv_attr_get_mac_vlan( results[FM10K_MAC_VLAN_MSG_DEFAULT_MAC], perm_addr, &vid); if (err) return err; memcpy(hw->mac.perm_addr, perm_addr, ETH_ALEN); hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1); hw->mac.vlan_override = !!(vid & FM10K_VLAN_CLEAR); return FM10K_SUCCESS; } /** * fm10k_read_mac_addr_vf - Read device MAC address * @hw: pointer to the HW structure * * This function should determine the MAC address for the VF **/ STATIC s32 fm10k_read_mac_addr_vf(struct fm10k_hw *hw) { u8 perm_addr[ETH_ALEN]; u32 base_addr; DEBUGFUNC("fm10k_read_mac_addr_vf"); base_addr = FM10K_READ_REG(hw, FM10K_TDBAL(0)); /* last byte should be 0 */ if (base_addr << 24) return FM10K_ERR_INVALID_MAC_ADDR; perm_addr[3] = (u8)(base_addr >> 24); perm_addr[4] = (u8)(base_addr >> 16); perm_addr[5] = (u8)(base_addr >> 8); base_addr = FM10K_READ_REG(hw, FM10K_TDBAH(0)); /* first byte should be all 1's */ if ((~base_addr) >> 24) return FM10K_ERR_INVALID_MAC_ADDR; perm_addr[0] = (u8)(base_addr >> 16); perm_addr[1] = (u8)(base_addr >> 8); perm_addr[2] = (u8)(base_addr); memcpy(hw->mac.perm_addr, perm_addr, ETH_ALEN); memcpy(hw->mac.addr, perm_addr, ETH_ALEN); return FM10K_SUCCESS; } /** * fm10k_update_uc_addr_vf - Update device unicast addresses * @hw: pointer to the HW structure * @glort: unused * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * @flags: flags field to indicate add and secure - unused * * This function is used to add or remove unicast MAC addresses for * the VF. **/ STATIC s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, u16 glort, const u8 *mac, u16 vid, bool add, u8 flags) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[7]; DEBUGFUNC("fm10k_update_uc_addr_vf"); UNREFERENCED_2PARAMETER(glort, flags); /* verify VLAN ID is valid */ if (vid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; /* verify MAC address is valid */ if (!FM10K_IS_VALID_ETHER_ADDR(mac)) return FM10K_ERR_PARAM; /* verify we are not locked down on the MAC address */ if (FM10K_IS_VALID_ETHER_ADDR(hw->mac.perm_addr) && memcmp(hw->mac.perm_addr, mac, ETH_ALEN)) return FM10K_ERR_PARAM; /* add bit to notify us if this is a set or clear operation */ if (!add) vid |= FM10K_VLAN_CLEAR; /* generate VLAN request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MAC, mac, vid); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_update_mc_addr_vf - Update device multicast addresses * @hw: pointer to the HW structure * @glort: unused * @mac: MAC address to add/remove from table * @vid: VLAN ID to add/remove from table * @add: Indicates if this is an add or remove operation * * This function is used to add or remove multicast MAC addresses for * the VF. **/ STATIC s32 fm10k_update_mc_addr_vf(struct fm10k_hw *hw, u16 glort, const u8 *mac, u16 vid, bool add) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[7]; DEBUGFUNC("fm10k_update_uc_addr_vf"); UNREFERENCED_1PARAMETER(glort); /* verify VLAN ID is valid */ if (vid >= FM10K_VLAN_TABLE_VID_MAX) return FM10K_ERR_PARAM; /* verify multicast address is valid */ if (!FM10K_IS_MULTICAST_ETHER_ADDR(mac)) return FM10K_ERR_PARAM; /* add bit to notify us if this is a set or clear operation */ if (!add) vid |= FM10K_VLAN_CLEAR; /* generate VLAN request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MULTICAST, mac, vid); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_update_int_moderator_vf - Request update of interrupt moderator list * @hw: pointer to hardware structure * * This function will issue a request to the PF to rescan our MSI-X table * and to update the interrupt moderator linked list. **/ STATIC void fm10k_update_int_moderator_vf(struct fm10k_hw *hw) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[1]; /* generate MSI-X request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MSIX); /* load onto outgoing mailbox */ mbx->ops.enqueue_tx(hw, mbx, msg); } /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[] = { FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_DISABLE), FM10K_TLV_ATTR_U8(FM10K_LPORT_STATE_MSG_XCAST_MODE), FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_READY), FM10K_TLV_ATTR_LAST }; /** * fm10k_msg_lport_state_vf - Message handler for lport_state message from PF * @hw: Pointer to hardware structure * @results: pointer array containing parsed data * @mbx: Pointer to mailbox information structure * * This handler is meant to capture the indication from the PF that we * are ready to bring up the interface. **/ s32 fm10k_msg_lport_state_vf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { UNREFERENCED_1PARAMETER(mbx); DEBUGFUNC("fm10k_msg_lport_state_vf"); hw->mac.dglort_map = !results[FM10K_LPORT_STATE_MSG_READY] ? FM10K_DGLORTMAP_NONE : FM10K_DGLORTMAP_ZERO; return FM10K_SUCCESS; } /** * fm10k_update_lport_state_vf - Update device state in lower device * @hw: pointer to the HW structure * @glort: unused * @count: number of logical ports to enable - unused (always 1) * @enable: boolean value indicating if this is an enable or disable request * * Notify the lower device of a state change. If the lower device is * enabled we can add filters, if it is disabled all filters for this * logical port are flushed. **/ STATIC s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, u16 glort, u16 count, bool enable) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[2]; UNREFERENCED_2PARAMETER(glort, count); DEBUGFUNC("fm10k_update_lport_state_vf"); /* reset glort mask 0 as we have to wait to be enabled */ hw->mac.dglort_map = FM10K_DGLORTMAP_NONE; /* generate port state request */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); if (!enable) fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_DISABLE); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } /** * fm10k_update_xcast_mode_vf - Request update of multicast mode * @hw: pointer to hardware structure * @glort: unused * @mode: integer value indicating mode being requested * * This function will attempt to request a higher mode for the port * so that it can enable either multicast, multicast promiscuous, or * promiscuous mode of operation. **/ STATIC s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode) { struct fm10k_mbx_info *mbx = &hw->mbx; u32 msg[3]; UNREFERENCED_1PARAMETER(glort); DEBUGFUNC("fm10k_update_xcast_mode_vf"); if (mode > FM10K_XCAST_MODE_NONE) return FM10K_ERR_PARAM; /* generate message requesting to change xcast mode */ fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); fm10k_tlv_attr_put_u8(msg, FM10K_LPORT_STATE_MSG_XCAST_MODE, mode); /* load onto outgoing mailbox */ return mbx->ops.enqueue_tx(hw, mbx, msg); } const struct fm10k_tlv_attr fm10k_1588_msg_attr[] = { FM10K_TLV_ATTR_U64(FM10K_1588_MSG_TIMESTAMP), FM10K_TLV_ATTR_LAST }; /* currently there is no shared 1588 timestamp handler */ /** * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF * @hw: pointer to hardware structure * @stats: pointer to statistics structure * * This function collects and aggregates per queue hardware statistics. **/ STATIC void fm10k_update_hw_stats_vf(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { DEBUGFUNC("fm10k_update_hw_stats_vf"); fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues); } /** * fm10k_rebind_hw_stats_vf - Resets base for hardware statistics of VF * @hw: pointer to hardware structure * @stats: pointer to the stats structure to update * * This function resets the base for queue hardware statistics. **/ STATIC void fm10k_rebind_hw_stats_vf(struct fm10k_hw *hw, struct fm10k_hw_stats *stats) { DEBUGFUNC("fm10k_rebind_hw_stats_vf"); /* Unbind Queue Statistics */ fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues); /* Reinitialize bases for all stats */ fm10k_update_hw_stats_vf(hw, stats); } /** * fm10k_configure_dglort_map_vf - Configures GLORT entry and queues * @hw: pointer to hardware structure * @dglort: pointer to dglort configuration structure * * Reads the configuration structure contained in dglort_cfg and uses * that information to then populate a DGLORTMAP/DEC entry and the queues * to which it has been assigned. **/ STATIC s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw, struct fm10k_dglort_cfg *dglort) { UNREFERENCED_1PARAMETER(hw); DEBUGFUNC("fm10k_configure_dglort_map_vf"); /* verify the dglort pointer */ if (!dglort) return FM10K_ERR_PARAM; /* stub for now until we determine correct message for this */ return FM10K_SUCCESS; } /** * fm10k_adjust_systime_vf - Adjust systime frequency * @hw: pointer to hardware structure * @ppb: adjustment rate in parts per billion * * This function takes an adjustment rate in parts per billion and will * verify that this value is 0 as the VF cannot support adjusting the * systime clock. * * If the ppb value is non-zero the return is ERR_PARAM else success **/ STATIC s32 fm10k_adjust_systime_vf(struct fm10k_hw *hw, s32 ppb) { UNREFERENCED_1PARAMETER(hw); DEBUGFUNC("fm10k_adjust_systime_vf"); /* The VF cannot adjust the clock frequency, however it should * already have a syntonic clock with whichever host interface is * running as the master for the host interface clock domain so * there should be not frequency adjustment necessary. */ return ppb ? FM10K_ERR_PARAM : FM10K_SUCCESS; } /** * fm10k_read_systime_vf - Reads value of systime registers * @hw: pointer to the hardware structure * * Function reads the content of 2 registers, combined to represent a 64 bit * value measured in nanoseconds. In order to guarantee the value is accurate * we check the 32 most significant bits both before and after reading the * 32 least significant bits to verify they didn't change as we were reading * the registers. **/ static u64 fm10k_read_systime_vf(struct fm10k_hw *hw) { u32 systime_l, systime_h, systime_tmp; systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1); do { systime_tmp = systime_h; systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME); systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1); } while (systime_tmp != systime_h); return ((u64)systime_h << 32) | systime_l; } static const struct fm10k_msg_data fm10k_msg_data_vf[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; /** * fm10k_init_ops_vf - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for VF. * Does not touch the hardware. **/ s32 fm10k_init_ops_vf(struct fm10k_hw *hw) { struct fm10k_mac_info *mac = &hw->mac; DEBUGFUNC("fm10k_init_ops_vf"); fm10k_init_ops_generic(hw); mac->ops.reset_hw = &fm10k_reset_hw_vf; mac->ops.init_hw = &fm10k_init_hw_vf; mac->ops.start_hw = &fm10k_start_hw_generic; mac->ops.stop_hw = &fm10k_stop_hw_vf; mac->ops.is_slot_appropriate = &fm10k_is_slot_appropriate_vf; mac->ops.update_vlan = &fm10k_update_vlan_vf; mac->ops.read_mac_addr = &fm10k_read_mac_addr_vf; mac->ops.update_uc_addr = &fm10k_update_uc_addr_vf; mac->ops.update_mc_addr = &fm10k_update_mc_addr_vf; mac->ops.update_xcast_mode = &fm10k_update_xcast_mode_vf; mac->ops.update_int_moderator = &fm10k_update_int_moderator_vf; mac->ops.update_lport_state = &fm10k_update_lport_state_vf; mac->ops.update_hw_stats = &fm10k_update_hw_stats_vf; mac->ops.rebind_hw_stats = &fm10k_rebind_hw_stats_vf; mac->ops.configure_dglort_map = &fm10k_configure_dglort_map_vf; mac->ops.get_host_state = &fm10k_get_host_state_generic; mac->ops.adjust_systime = &fm10k_adjust_systime_vf; mac->ops.read_systime = &fm10k_read_systime_vf, mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw); return fm10k_pfvf_mbx_init(hw, &hw->mbx, fm10k_msg_data_vf, 0); } ================================================ FILE: drivers/net/fm10k/base/fm10k_vf.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _FM10K_VF_H_ #define _FM10K_VF_H_ #include "fm10k_type.h" #include "fm10k_common.h" enum fm10k_vf_tlv_msg_id { FM10K_VF_MSG_ID_TEST = 0, /* msg ID reserved for testing */ FM10K_VF_MSG_ID_MSIX, FM10K_VF_MSG_ID_MAC_VLAN, FM10K_VF_MSG_ID_LPORT_STATE, FM10K_VF_MSG_ID_1588, FM10K_VF_MSG_ID_MAX, }; enum fm10k_tlv_mac_vlan_attr_id { FM10K_MAC_VLAN_MSG_VLAN, FM10K_MAC_VLAN_MSG_SET, FM10K_MAC_VLAN_MSG_MAC, FM10K_MAC_VLAN_MSG_DEFAULT_MAC, FM10K_MAC_VLAN_MSG_MULTICAST, FM10K_MAC_VLAN_MSG_ID_MAX }; enum fm10k_tlv_lport_state_attr_id { FM10K_LPORT_STATE_MSG_DISABLE, FM10K_LPORT_STATE_MSG_XCAST_MODE, FM10K_LPORT_STATE_MSG_READY, FM10K_LPORT_STATE_MSG_MAX }; enum fm10k_tlv_1588_attr_id { FM10K_1588_MSG_TIMESTAMP, FM10K_1588_MSG_MAX }; #define FM10K_VF_MSG_MSIX_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func) s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[]; #define FM10K_VF_MSG_MAC_VLAN_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MAC_VLAN, \ fm10k_mac_vlan_msg_attr, func) s32 fm10k_msg_lport_state_vf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *); extern const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[]; #define FM10K_VF_MSG_LPORT_STATE_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \ fm10k_lport_state_msg_attr, func) extern const struct fm10k_tlv_attr fm10k_1588_msg_attr[]; #define FM10K_VF_MSG_1588_HANDLER(func) \ FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_1588, fm10k_1588_msg_attr, func) s32 fm10k_init_ops_vf(struct fm10k_hw *hw); #endif /* _FM10K_VF_H */ ================================================ FILE: drivers/net/fm10k/fm10k.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _FM10K_H_ #define _FM10K_H_ #include #include #include #include #include #include "fm10k_logs.h" #include "base/fm10k_type.h" /* descriptor ring base addresses must be aligned to the following */ #define FM10K_ALIGN_RX_DESC 128 #define FM10K_ALIGN_TX_DESC 128 /* The maximum packet size that FM10K supports */ #define FM10K_MAX_PKT_SIZE (15 * 1024) /* Minimum size of RX buffer FM10K supported */ #define FM10K_MIN_RX_BUF_SIZE 256 /* The maximum of SRIOV VFs per port supported */ #define FM10K_MAX_VF_NUM 64 /* number of descriptors must be a multiple of the following */ #define FM10K_MULT_RX_DESC FM10K_REQ_RX_DESCRIPTOR_MULTIPLE #define FM10K_MULT_TX_DESC FM10K_REQ_TX_DESCRIPTOR_MULTIPLE /* maximum size of descriptor rings */ #define FM10K_MAX_RX_RING_SZ (512 * 1024) #define FM10K_MAX_TX_RING_SZ (512 * 1024) /* minimum and maximum number of descriptors in a ring */ #define FM10K_MIN_RX_DESC 32 #define FM10K_MIN_TX_DESC 32 #define FM10K_MAX_RX_DESC (FM10K_MAX_RX_RING_SZ / sizeof(union fm10k_rx_desc)) #define FM10K_MAX_TX_DESC (FM10K_MAX_TX_RING_SZ / sizeof(struct fm10k_tx_desc)) /* * byte aligment for HW RX data buffer * Datasheet requires RX buffer addresses shall either be 512-byte aligned or * be 8-byte aligned but without crossing host memory pages (4KB alignment * boundaries). Satisfy first option. */ #define FM10K_RX_DATABUF_ALIGN 512 /* * threshold default, min, max, and divisor constraints * the configured values must satisfy the following: * MIN <= value <= MAX * DIV % value == 0 */ #define FM10K_RX_FREE_THRESH_DEFAULT(rxq) 32 #define FM10K_RX_FREE_THRESH_MIN(rxq) 1 #define FM10K_RX_FREE_THRESH_MAX(rxq) ((rxq)->nb_desc - 1) #define FM10K_RX_FREE_THRESH_DIV(rxq) ((rxq)->nb_desc) #define FM10K_TX_FREE_THRESH_DEFAULT(txq) 32 #define FM10K_TX_FREE_THRESH_MIN(txq) 1 #define FM10K_TX_FREE_THRESH_MAX(txq) ((txq)->nb_desc - 3) #define FM10K_TX_FREE_THRESH_DIV(txq) 0 #define FM10K_DEFAULT_RX_PTHRESH 8 #define FM10K_DEFAULT_RX_HTHRESH 8 #define FM10K_DEFAULT_RX_WTHRESH 0 #define FM10K_DEFAULT_TX_PTHRESH 32 #define FM10K_DEFAULT_TX_HTHRESH 0 #define FM10K_DEFAULT_TX_WTHRESH 0 #define FM10K_TX_RS_THRESH_DEFAULT(txq) 32 #define FM10K_TX_RS_THRESH_MIN(txq) 1 #define FM10K_TX_RS_THRESH_MAX(txq) \ RTE_MIN(((txq)->nb_desc - 2), (txq)->free_thresh) #define FM10K_TX_RS_THRESH_DIV(txq) ((txq)->nb_desc) #define FM10K_VLAN_TAG_SIZE 4 /* Maximum number of MAC addresses per PF/VF */ #define FM10K_MAX_MACADDR_NUM 64 #define FM10K_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t)) #define FM10K_VFTA_SIZE (4096 / FM10K_UINT32_BIT_SIZE) /* vlan_id is a 12 bit number. * The VFTA array is actually a 4096 bit array, 128 of 32bit elements. * 2^5 = 32. The val of lower 5 bits specifies the bit in the 32bit element. * The higher 7 bit val specifies VFTA array index. */ #define FM10K_VFTA_BIT(vlan_id) (1 << ((vlan_id) & 0x1F)) #define FM10K_VFTA_IDX(vlan_id) ((vlan_id) >> 5) struct fm10k_macvlan_filter_info { uint16_t vlan_num; /* Total VLAN number */ uint16_t mac_num; /* Total mac number */ uint32_t vfta[FM10K_VFTA_SIZE]; /* VLAN bitmap */ }; struct fm10k_dev_info { volatile uint32_t enable; volatile uint32_t glort; /* Protect the mailbox to avoid race condition */ rte_spinlock_t mbx_lock; struct fm10k_macvlan_filter_info macvlan; }; /* * Structure to store private data for each driver instance. */ struct fm10k_adapter { struct fm10k_hw hw; struct fm10k_hw_stats stats; struct fm10k_dev_info info; }; #define FM10K_DEV_PRIVATE_TO_HW(adapter) \ (&((struct fm10k_adapter *)adapter)->hw) #define FM10K_DEV_PRIVATE_TO_STATS(adapter) \ (&((struct fm10k_adapter *)adapter)->stats) #define FM10K_DEV_PRIVATE_TO_INFO(adapter) \ (&((struct fm10k_adapter *)adapter)->info) #define FM10K_DEV_PRIVATE_TO_MBXLOCK(adapter) \ (&(((struct fm10k_adapter *)adapter)->info.mbx_lock)) #define FM10K_DEV_PRIVATE_TO_MACVLAN(adapter) \ (&(((struct fm10k_adapter *)adapter)->info.macvlan)) struct fm10k_rx_queue { struct rte_mempool *mp; struct rte_mbuf **sw_ring; volatile union fm10k_rx_desc *hw_ring; struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ uint64_t hw_ring_phys_addr; uint16_t next_dd; uint16_t next_alloc; uint16_t next_trigger; uint16_t alloc_thresh; volatile uint32_t *tail_ptr; uint16_t nb_desc; uint16_t queue_id; uint8_t port_id; uint8_t drop_en; uint8_t rx_deferred_start; /**< don't start this queue in dev start. */ }; /* * a FIFO is used to track which descriptors have their RS bit set for Tx * queues which are configured to allow multiple descriptors per packet */ struct fifo { uint16_t *list; uint16_t *head; uint16_t *tail; uint16_t *endp; }; struct fm10k_tx_queue { struct rte_mbuf **sw_ring; struct fm10k_tx_desc *hw_ring; uint64_t hw_ring_phys_addr; struct fifo rs_tracker; uint16_t last_free; uint16_t next_free; uint16_t nb_free; uint16_t nb_used; uint16_t free_thresh; uint16_t rs_thresh; volatile uint32_t *tail_ptr; uint16_t nb_desc; uint8_t port_id; uint8_t tx_deferred_start; /** < don't start this queue in dev start. */ uint16_t queue_id; }; #define MBUF_DMA_ADDR(mb) \ ((uint64_t) ((mb)->buf_physaddr + (mb)->data_off)) /* enforce 512B alignment on default Rx DMA addresses */ #define MBUF_DMA_ADDR_DEFAULT(mb) \ ((uint64_t) RTE_ALIGN(((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM),\ FM10K_RX_DATABUF_ALIGN)) static inline void fifo_reset(struct fifo *fifo, uint32_t len) { fifo->head = fifo->tail = fifo->list; fifo->endp = fifo->list + len; } static inline void fifo_insert(struct fifo *fifo, uint16_t val) { *fifo->head = val; if (++fifo->head == fifo->endp) fifo->head = fifo->list; } /* do not worry about list being empty since we only check it once we know * we have used enough descriptors to set the RS bit at least once */ static inline uint16_t fifo_peek(struct fifo *fifo) { return *fifo->tail; } static inline uint16_t fifo_remove(struct fifo *fifo) { uint16_t val; val = *fifo->tail; if (++fifo->tail == fifo->endp) fifo->tail = fifo->list; return val; } static inline void fm10k_pktmbuf_reset(struct rte_mbuf *mb, uint8_t in_port) { rte_mbuf_refcnt_set(mb, 1); mb->next = NULL; mb->nb_segs = 1; /* enforce 512B alignment on default Rx virtual addresses */ mb->data_off = (uint16_t)(RTE_PTR_ALIGN((char *)mb->buf_addr + RTE_PKTMBUF_HEADROOM, FM10K_RX_DATABUF_ALIGN) - (char *)mb->buf_addr); mb->port = in_port; } /* * Verify Rx packet buffer alignment is valid. * * Hardware requires specific alignment for Rx packet buffers. At * least one of the following two conditions must be satisfied. * 1. Address is 512B aligned * 2. Address is 8B aligned and buffer does not cross 4K boundary. * * Return 1 if buffer alignment satisfies at least one condition, * otherwise return 0. * * Note: Alignment is checked by the driver when the Rx queue is reset. It * is assumed that if an entire descriptor ring can be filled with * buffers containing valid alignment, then all buffers in that mempool * have valid address alignment. It is the responsibility of the user * to ensure all buffers have valid alignment, as it is the user who * creates the mempool. * Note: It is assumed the buffer needs only to store a maximum size Ethernet * frame. */ static inline int fm10k_addr_alignment_valid(struct rte_mbuf *mb) { uint64_t addr = MBUF_DMA_ADDR_DEFAULT(mb); uint64_t boundary1, boundary2; /* 512B aligned? */ if (RTE_ALIGN(addr, FM10K_RX_DATABUF_ALIGN) == addr) return 1; /* 8B aligned, and max Ethernet frame would not cross a 4KB boundary? */ if (RTE_ALIGN(addr, 8) == addr) { boundary1 = RTE_ALIGN_FLOOR(addr, 4096); boundary2 = RTE_ALIGN_FLOOR(addr + ETHER_MAX_VLAN_FRAME_LEN, 4096); if (boundary1 == boundary2) return 1; } PMD_INIT_LOG(ERR, "Error: Invalid buffer alignment!"); return 0; } /* Rx and Tx prototypes */ uint16_t fm10k_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t fm10k_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); #endif ================================================ FILE: drivers/net/fm10k/fm10k_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "fm10k.h" #include "base/fm10k_api.h" /* Default delay to acquire mailbox lock */ #define FM10K_MBXLOCK_DELAY_US 20 #define UINT64_LOWER_32BITS_MASK 0x00000000ffffffffULL /* Max try times to acquire switch status */ #define MAX_QUERY_SWITCH_STATE_TIMES 10 /* Wait interval to get switch status */ #define WAIT_SWITCH_MSG_US 100000 /* Number of chars per uint32 type */ #define CHARS_PER_UINT32 (sizeof(uint32_t)) #define BIT_MASK_PER_UINT32 ((1 << CHARS_PER_UINT32) - 1) static void fm10k_close_mbx_service(struct fm10k_hw *hw); static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev); static void fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev); static void fm10k_dev_allmulticast_enable(struct rte_eth_dev *dev); static void fm10k_dev_allmulticast_disable(struct rte_eth_dev *dev); static inline int fm10k_glort_valid(struct fm10k_hw *hw); static int fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void fm10k_MAC_filter_set(struct rte_eth_dev *dev, const u8 *mac, bool add); static void fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev); static void fm10k_tx_queue_release(void *queue); static void fm10k_rx_queue_release(void *queue); static void fm10k_mbx_initlock(struct fm10k_hw *hw) { rte_spinlock_init(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back)); } static void fm10k_mbx_lock(struct fm10k_hw *hw) { while (!rte_spinlock_trylock(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back))) rte_delay_us(FM10K_MBXLOCK_DELAY_US); } static void fm10k_mbx_unlock(struct fm10k_hw *hw) { rte_spinlock_unlock(FM10K_DEV_PRIVATE_TO_MBXLOCK(hw->back)); } /* * reset queue to initial state, allocate software buffers used when starting * device. * return 0 on success * return -ENOMEM if buffers cannot be allocated * return -EINVAL if buffers do not satisfy alignment condition */ static inline int rx_queue_reset(struct fm10k_rx_queue *q) { uint64_t dma_addr; int i, diag; PMD_INIT_FUNC_TRACE(); diag = rte_mempool_get_bulk(q->mp, (void **)q->sw_ring, q->nb_desc); if (diag != 0) return -ENOMEM; for (i = 0; i < q->nb_desc; ++i) { fm10k_pktmbuf_reset(q->sw_ring[i], q->port_id); if (!fm10k_addr_alignment_valid(q->sw_ring[i])) { rte_mempool_put_bulk(q->mp, (void **)q->sw_ring, q->nb_desc); return -EINVAL; } dma_addr = MBUF_DMA_ADDR_DEFAULT(q->sw_ring[i]); q->hw_ring[i].q.pkt_addr = dma_addr; q->hw_ring[i].q.hdr_addr = dma_addr; } q->next_dd = 0; q->next_alloc = 0; q->next_trigger = q->alloc_thresh - 1; FM10K_PCI_REG_WRITE(q->tail_ptr, q->nb_desc - 1); return 0; } /* * clean queue, descriptor rings, free software buffers used when stopping * device. */ static inline void rx_queue_clean(struct fm10k_rx_queue *q) { union fm10k_rx_desc zero = {.q = {0, 0, 0, 0} }; uint32_t i; PMD_INIT_FUNC_TRACE(); /* zero descriptor rings */ for (i = 0; i < q->nb_desc; ++i) q->hw_ring[i] = zero; /* free software buffers */ for (i = 0; i < q->nb_desc; ++i) { if (q->sw_ring[i]) { rte_pktmbuf_free_seg(q->sw_ring[i]); q->sw_ring[i] = NULL; } } } /* * free all queue memory used when releasing the queue (i.e. configure) */ static inline void rx_queue_free(struct fm10k_rx_queue *q) { PMD_INIT_FUNC_TRACE(); if (q) { PMD_INIT_LOG(DEBUG, "Freeing rx queue %p", q); rx_queue_clean(q); if (q->sw_ring) { rte_free(q->sw_ring); q->sw_ring = NULL; } rte_free(q); q = NULL; } } /* * disable RX queue, wait unitl HW finished necessary flush operation */ static inline int rx_queue_disable(struct fm10k_hw *hw, uint16_t qnum) { uint32_t reg, i; reg = FM10K_READ_REG(hw, FM10K_RXQCTL(qnum)); FM10K_WRITE_REG(hw, FM10K_RXQCTL(qnum), reg & ~FM10K_RXQCTL_ENABLE); /* Wait 100us at most */ for (i = 0; i < FM10K_QUEUE_DISABLE_TIMEOUT; i++) { rte_delay_us(1); reg = FM10K_READ_REG(hw, FM10K_RXQCTL(qnum)); if (!(reg & FM10K_RXQCTL_ENABLE)) break; } if (i == FM10K_QUEUE_DISABLE_TIMEOUT) return -1; return 0; } /* * reset queue to initial state, allocate software buffers used when starting * device */ static inline void tx_queue_reset(struct fm10k_tx_queue *q) { PMD_INIT_FUNC_TRACE(); q->last_free = 0; q->next_free = 0; q->nb_used = 0; q->nb_free = q->nb_desc - 1; fifo_reset(&q->rs_tracker, (q->nb_desc + 1) / q->rs_thresh); FM10K_PCI_REG_WRITE(q->tail_ptr, 0); } /* * clean queue, descriptor rings, free software buffers used when stopping * device */ static inline void tx_queue_clean(struct fm10k_tx_queue *q) { struct fm10k_tx_desc zero = {0, 0, 0, 0, 0, 0}; uint32_t i; PMD_INIT_FUNC_TRACE(); /* zero descriptor rings */ for (i = 0; i < q->nb_desc; ++i) q->hw_ring[i] = zero; /* free software buffers */ for (i = 0; i < q->nb_desc; ++i) { if (q->sw_ring[i]) { rte_pktmbuf_free_seg(q->sw_ring[i]); q->sw_ring[i] = NULL; } } } /* * free all queue memory used when releasing the queue (i.e. configure) */ static inline void tx_queue_free(struct fm10k_tx_queue *q) { PMD_INIT_FUNC_TRACE(); if (q) { PMD_INIT_LOG(DEBUG, "Freeing tx queue %p", q); tx_queue_clean(q); if (q->rs_tracker.list) { rte_free(q->rs_tracker.list); q->rs_tracker.list = NULL; } if (q->sw_ring) { rte_free(q->sw_ring); q->sw_ring = NULL; } rte_free(q); q = NULL; } } /* * disable TX queue, wait unitl HW finished necessary flush operation */ static inline int tx_queue_disable(struct fm10k_hw *hw, uint16_t qnum) { uint32_t reg, i; reg = FM10K_READ_REG(hw, FM10K_TXDCTL(qnum)); FM10K_WRITE_REG(hw, FM10K_TXDCTL(qnum), reg & ~FM10K_TXDCTL_ENABLE); /* Wait 100us at most */ for (i = 0; i < FM10K_QUEUE_DISABLE_TIMEOUT; i++) { rte_delay_us(1); reg = FM10K_READ_REG(hw, FM10K_TXDCTL(qnum)); if (!(reg & FM10K_TXDCTL_ENABLE)) break; } if (i == FM10K_QUEUE_DISABLE_TIMEOUT) return -1; return 0; } static int fm10k_dev_configure(struct rte_eth_dev *dev) { PMD_INIT_FUNC_TRACE(); if (dev->data->dev_conf.rxmode.hw_strip_crc == 0) PMD_INIT_LOG(WARNING, "fm10k always strip CRC"); return 0; } static void fm10k_dev_mq_rx_configure(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_conf *dev_conf = &dev->data->dev_conf; uint32_t mrqc, *key, i, reta, j; uint64_t hf; #define RSS_KEY_SIZE 40 static uint8_t rss_intel_key[RSS_KEY_SIZE] = { 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; if (dev->data->nb_rx_queues == 1 || dev_conf->rxmode.mq_mode != ETH_MQ_RX_RSS || dev_conf->rx_adv_conf.rss_conf.rss_hf == 0) return; /* random key is rss_intel_key (default) or user provided (rss_key) */ if (dev_conf->rx_adv_conf.rss_conf.rss_key == NULL) key = (uint32_t *)rss_intel_key; else key = (uint32_t *)dev_conf->rx_adv_conf.rss_conf.rss_key; /* Now fill our hash function seeds, 4 bytes at a time */ for (i = 0; i < RSS_KEY_SIZE / sizeof(*key); ++i) FM10K_WRITE_REG(hw, FM10K_RSSRK(0, i), key[i]); /* * Fill in redirection table * The byte-swap is needed because NIC registers are in * little-endian order. */ reta = 0; for (i = 0, j = 0; i < FM10K_MAX_RSS_INDICES; i++, j++) { if (j == dev->data->nb_rx_queues) j = 0; reta = (reta << CHAR_BIT) | j; if ((i & 3) == 3) FM10K_WRITE_REG(hw, FM10K_RETA(0, i >> 2), rte_bswap32(reta)); } /* * Generate RSS hash based on packet types, TCP/UDP * port numbers and/or IPv4/v6 src and dst addresses */ hf = dev_conf->rx_adv_conf.rss_conf.rss_hf; mrqc = 0; mrqc |= (hf & ETH_RSS_IPV4) ? FM10K_MRQC_IPV4 : 0; mrqc |= (hf & ETH_RSS_IPV6) ? FM10K_MRQC_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_EX) ? FM10K_MRQC_IPV6 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_TCP) ? FM10K_MRQC_TCP_IPV4 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_TCP) ? FM10K_MRQC_TCP_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_TCP_EX) ? FM10K_MRQC_TCP_IPV6 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_UDP) ? FM10K_MRQC_UDP_IPV4 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_UDP) ? FM10K_MRQC_UDP_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_UDP_EX) ? FM10K_MRQC_UDP_IPV6 : 0; if (mrqc == 0) { PMD_INIT_LOG(ERR, "Specified RSS mode 0x%"PRIx64"is not" "supported", hf); return; } FM10K_WRITE_REG(hw, FM10K_MRQC(0), mrqc); } static int fm10k_dev_tx_init(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int i, ret; struct fm10k_tx_queue *txq; uint64_t base_addr; uint32_t size; /* Disable TXINT to avoid possible interrupt */ for (i = 0; i < hw->mac.max_queues; i++) FM10K_WRITE_REG(hw, FM10K_TXINT(i), 3 << FM10K_TXINT_TIMER_SHIFT); /* Setup TX queue */ for (i = 0; i < dev->data->nb_tx_queues; ++i) { txq = dev->data->tx_queues[i]; base_addr = txq->hw_ring_phys_addr; size = txq->nb_desc * sizeof(struct fm10k_tx_desc); /* disable queue to avoid issues while updating state */ ret = tx_queue_disable(hw, i); if (ret) { PMD_INIT_LOG(ERR, "failed to disable queue %d", i); return -1; } /* set location and size for descriptor ring */ FM10K_WRITE_REG(hw, FM10K_TDBAL(i), base_addr & UINT64_LOWER_32BITS_MASK); FM10K_WRITE_REG(hw, FM10K_TDBAH(i), base_addr >> (CHAR_BIT * sizeof(uint32_t))); FM10K_WRITE_REG(hw, FM10K_TDLEN(i), size); } return 0; } static int fm10k_dev_rx_init(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int i, ret; struct fm10k_rx_queue *rxq; uint64_t base_addr; uint32_t size; uint32_t rxdctl = FM10K_RXDCTL_WRITE_BACK_MIN_DELAY; uint16_t buf_size; /* Disable RXINT to avoid possible interrupt */ for (i = 0; i < hw->mac.max_queues; i++) FM10K_WRITE_REG(hw, FM10K_RXINT(i), 3 << FM10K_RXINT_TIMER_SHIFT); /* Setup RX queues */ for (i = 0; i < dev->data->nb_rx_queues; ++i) { rxq = dev->data->rx_queues[i]; base_addr = rxq->hw_ring_phys_addr; size = rxq->nb_desc * sizeof(union fm10k_rx_desc); /* disable queue to avoid issues while updating state */ ret = rx_queue_disable(hw, i); if (ret) { PMD_INIT_LOG(ERR, "failed to disable queue %d", i); return -1; } /* Setup the Base and Length of the Rx Descriptor Ring */ FM10K_WRITE_REG(hw, FM10K_RDBAL(i), base_addr & UINT64_LOWER_32BITS_MASK); FM10K_WRITE_REG(hw, FM10K_RDBAH(i), base_addr >> (CHAR_BIT * sizeof(uint32_t))); FM10K_WRITE_REG(hw, FM10K_RDLEN(i), size); /* Configure the Rx buffer size for one buff without split */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM); /* As RX buffer is aligned to 512B within mbuf, some bytes are * reserved for this purpose, and the worst case could be 511B. * But SRR reg assumes all buffers have the same size. In order * to fill the gap, we'll have to consider the worst case and * assume 512B is reserved. If we don't do so, it's possible * for HW to overwrite data to next mbuf. */ buf_size -= FM10K_RX_DATABUF_ALIGN; FM10K_WRITE_REG(hw, FM10K_SRRCTL(i), buf_size >> FM10K_SRRCTL_BSIZEPKT_SHIFT); /* It adds dual VLAN length for supporting dual VLAN */ if ((dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * FM10K_VLAN_TAG_SIZE) > buf_size || dev->data->dev_conf.rxmode.enable_scatter) { uint32_t reg; dev->data->scattered_rx = 1; dev->rx_pkt_burst = fm10k_recv_scattered_pkts; reg = FM10K_READ_REG(hw, FM10K_SRRCTL(i)); reg |= FM10K_SRRCTL_BUFFER_CHAINING_EN; FM10K_WRITE_REG(hw, FM10K_SRRCTL(i), reg); } /* Enable drop on empty, it's RO for VF */ if (hw->mac.type == fm10k_mac_pf && rxq->drop_en) rxdctl |= FM10K_RXDCTL_DROP_ON_EMPTY; FM10K_WRITE_REG(hw, FM10K_RXDCTL(i), rxdctl); FM10K_WRITE_FLUSH(hw); } /* Configure RSS if applicable */ fm10k_dev_mq_rx_configure(dev); return 0; } static int fm10k_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int err = -1; uint32_t reg; struct fm10k_rx_queue *rxq; PMD_INIT_FUNC_TRACE(); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; err = rx_queue_reset(rxq); if (err == -ENOMEM) { PMD_INIT_LOG(ERR, "Failed to alloc memory : %d", err); return err; } else if (err == -EINVAL) { PMD_INIT_LOG(ERR, "Invalid buffer address alignment :" " %d", err); return err; } /* Setup the HW Rx Head and Tail Descriptor Pointers * Note: this must be done AFTER the queue is enabled on real * hardware, but BEFORE the queue is enabled when using the * emulation platform. Do it in both places for now and remove * this comment and the following two register writes when the * emulation platform is no longer being used. */ FM10K_WRITE_REG(hw, FM10K_RDH(rx_queue_id), 0); FM10K_WRITE_REG(hw, FM10K_RDT(rx_queue_id), rxq->nb_desc - 1); /* Set PF ownership flag for PF devices */ reg = FM10K_READ_REG(hw, FM10K_RXQCTL(rx_queue_id)); if (hw->mac.type == fm10k_mac_pf) reg |= FM10K_RXQCTL_PF; reg |= FM10K_RXQCTL_ENABLE; /* enable RX queue */ FM10K_WRITE_REG(hw, FM10K_RXQCTL(rx_queue_id), reg); FM10K_WRITE_FLUSH(hw); /* Setup the HW Rx Head and Tail Descriptor Pointers * Note: this must be done AFTER the queue is enabled */ FM10K_WRITE_REG(hw, FM10K_RDH(rx_queue_id), 0); FM10K_WRITE_REG(hw, FM10K_RDT(rx_queue_id), rxq->nb_desc - 1); } return err; } static int fm10k_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rx_queue_id < dev->data->nb_rx_queues) { /* Disable RX queue */ rx_queue_disable(hw, rx_queue_id); /* Free mbuf and clean HW ring */ rx_queue_clean(dev->data->rx_queues[rx_queue_id]); } return 0; } static int fm10k_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); /** @todo - this should be defined in the shared code */ #define FM10K_TXDCTL_WRITE_BACK_MIN_DELAY 0x00010000 uint32_t txdctl = FM10K_TXDCTL_WRITE_BACK_MIN_DELAY; int err = 0; PMD_INIT_FUNC_TRACE(); if (tx_queue_id < dev->data->nb_tx_queues) { tx_queue_reset(dev->data->tx_queues[tx_queue_id]); /* reset head and tail pointers */ FM10K_WRITE_REG(hw, FM10K_TDH(tx_queue_id), 0); FM10K_WRITE_REG(hw, FM10K_TDT(tx_queue_id), 0); /* enable TX queue */ FM10K_WRITE_REG(hw, FM10K_TXDCTL(tx_queue_id), FM10K_TXDCTL_ENABLE | txdctl); FM10K_WRITE_FLUSH(hw); } else err = -1; return err; } static int fm10k_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (tx_queue_id < dev->data->nb_tx_queues) { tx_queue_disable(hw, tx_queue_id); tx_queue_clean(dev->data->tx_queues[tx_queue_id]); } return 0; } static inline int fm10k_glort_valid(struct fm10k_hw *hw) { return ((hw->mac.dglort_map & FM10K_DGLORTMAP_NONE) != FM10K_DGLORTMAP_NONE); } static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int status; PMD_INIT_FUNC_TRACE(); /* Return if it didn't acquire valid glort range */ if (!fm10k_glort_valid(hw)) return; fm10k_mbx_lock(hw); status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, FM10K_XCAST_MODE_PROMISC); fm10k_mbx_unlock(hw); if (status != FM10K_SUCCESS) PMD_INIT_LOG(ERR, "Failed to enable promiscuous mode"); } static void fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint8_t mode; int status; PMD_INIT_FUNC_TRACE(); /* Return if it didn't acquire valid glort range */ if (!fm10k_glort_valid(hw)) return; if (dev->data->all_multicast == 1) mode = FM10K_XCAST_MODE_ALLMULTI; else mode = FM10K_XCAST_MODE_NONE; fm10k_mbx_lock(hw); status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, mode); fm10k_mbx_unlock(hw); if (status != FM10K_SUCCESS) PMD_INIT_LOG(ERR, "Failed to disable promiscuous mode"); } static void fm10k_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int status; PMD_INIT_FUNC_TRACE(); /* Return if it didn't acquire valid glort range */ if (!fm10k_glort_valid(hw)) return; /* If promiscuous mode is enabled, it doesn't make sense to enable * allmulticast and disable promiscuous since fm10k only can select * one of the modes. */ if (dev->data->promiscuous) { PMD_INIT_LOG(INFO, "Promiscuous mode is enabled, "\ "needn't enable allmulticast"); return; } fm10k_mbx_lock(hw); status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, FM10K_XCAST_MODE_ALLMULTI); fm10k_mbx_unlock(hw); if (status != FM10K_SUCCESS) PMD_INIT_LOG(ERR, "Failed to enable allmulticast mode"); } static void fm10k_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int status; PMD_INIT_FUNC_TRACE(); /* Return if it didn't acquire valid glort range */ if (!fm10k_glort_valid(hw)) return; if (dev->data->promiscuous) { PMD_INIT_LOG(ERR, "Failed to disable allmulticast mode "\ "since promisc mode is enabled"); return; } fm10k_mbx_lock(hw); /* Change mode to unicast mode */ status = hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, FM10K_XCAST_MODE_NONE); fm10k_mbx_unlock(hw); if (status != FM10K_SUCCESS) PMD_INIT_LOG(ERR, "Failed to disable allmulticast mode"); } /* fls = find last set bit = 32 minus the number of leading zeros */ #ifndef fls #define fls(x) (((x) == 0) ? 0 : (32 - __builtin_clz((x)))) #endif #define BSIZEPKT_ROUNDUP ((1 << FM10K_SRRCTL_BSIZEPKT_SHIFT) - 1) static int fm10k_dev_start(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int i, diag; PMD_INIT_FUNC_TRACE(); /* stop, init, then start the hw */ diag = fm10k_stop_hw(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Hardware stop failed: %d", diag); return -EIO; } diag = fm10k_init_hw(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Hardware init failed: %d", diag); return -EIO; } diag = fm10k_start_hw(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Hardware start failed: %d", diag); return -EIO; } diag = fm10k_dev_tx_init(dev); if (diag) { PMD_INIT_LOG(ERR, "TX init failed: %d", diag); return diag; } diag = fm10k_dev_rx_init(dev); if (diag) { PMD_INIT_LOG(ERR, "RX init failed: %d", diag); return diag; } if (hw->mac.type == fm10k_mac_pf) { /* Establish only VSI 0 as valid */ FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(0), FM10K_DGLORTMAP_ANY); /* Configure RSS bits used in RETA table */ FM10K_WRITE_REG(hw, FM10K_DGLORTDEC(0), fls(dev->data->nb_rx_queues - 1) << FM10K_DGLORTDEC_RSSLENGTH_SHIFT); /* Invalidate all other GLORT entries */ for (i = 1; i < FM10K_DGLORT_COUNT; i++) FM10K_WRITE_REG(hw, FM10K_DGLORTMAP(i), FM10K_DGLORTMAP_NONE); } for (i = 0; i < dev->data->nb_rx_queues; i++) { struct fm10k_rx_queue *rxq; rxq = dev->data->rx_queues[i]; if (rxq->rx_deferred_start) continue; diag = fm10k_dev_rx_queue_start(dev, i); if (diag != 0) { int j; for (j = 0; j < i; ++j) rx_queue_clean(dev->data->rx_queues[j]); return diag; } } for (i = 0; i < dev->data->nb_tx_queues; i++) { struct fm10k_tx_queue *txq; txq = dev->data->tx_queues[i]; if (txq->tx_deferred_start) continue; diag = fm10k_dev_tx_queue_start(dev, i); if (diag != 0) { int j; for (j = 0; j < i; ++j) tx_queue_clean(dev->data->tx_queues[j]); for (j = 0; j < dev->data->nb_rx_queues; ++j) rx_queue_clean(dev->data->rx_queues[j]); return diag; } } /* Update default vlan */ if (hw->mac.default_vid && hw->mac.default_vid <= ETHER_MAX_VLAN_ID) fm10k_vlan_filter_set(dev, hw->mac.default_vid, true); return 0; } static void fm10k_dev_stop(struct rte_eth_dev *dev) { int i; PMD_INIT_FUNC_TRACE(); if (dev->data->tx_queues) for (i = 0; i < dev->data->nb_tx_queues; i++) fm10k_dev_tx_queue_stop(dev, i); if (dev->data->rx_queues) for (i = 0; i < dev->data->nb_rx_queues; i++) fm10k_dev_rx_queue_stop(dev, i); } static void fm10k_dev_queue_release(struct rte_eth_dev *dev) { int i; PMD_INIT_FUNC_TRACE(); if (dev->data->tx_queues) { for (i = 0; i < dev->data->nb_tx_queues; i++) fm10k_tx_queue_release(dev->data->tx_queues[i]); } if (dev->data->rx_queues) { for (i = 0; i < dev->data->nb_rx_queues; i++) fm10k_rx_queue_release(dev->data->rx_queues[i]); } } static void fm10k_dev_close(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); fm10k_MACVLAN_remove_all(dev); /* Stop mailbox service first */ fm10k_close_mbx_service(hw); fm10k_dev_stop(dev); fm10k_dev_queue_release(dev); fm10k_stop_hw(hw); } static int fm10k_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) { PMD_INIT_FUNC_TRACE(); /* The host-interface link is always up. The speed is ~50Gbps per Gen3 * x8 PCIe interface. For now, we leave the speed undefined since there * is no 50Gbps Ethernet. */ dev->data->dev_link.link_speed = 0; dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; dev->data->dev_link.link_status = 1; return 0; } static void fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { uint64_t ipackets, opackets, ibytes, obytes; struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct fm10k_hw_stats *hw_stats = FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private); int i; PMD_INIT_FUNC_TRACE(); fm10k_update_hw_stats(hw, hw_stats); ipackets = opackets = ibytes = obytes = 0; for (i = 0; (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) && (i < hw->mac.max_queues); ++i) { stats->q_ipackets[i] = hw_stats->q[i].rx_packets.count; stats->q_opackets[i] = hw_stats->q[i].tx_packets.count; stats->q_ibytes[i] = hw_stats->q[i].rx_bytes.count; stats->q_obytes[i] = hw_stats->q[i].tx_bytes.count; ipackets += stats->q_ipackets[i]; opackets += stats->q_opackets[i]; ibytes += stats->q_ibytes[i]; obytes += stats->q_obytes[i]; } stats->ipackets = ipackets; stats->opackets = opackets; stats->ibytes = ibytes; stats->obytes = obytes; } static void fm10k_stats_reset(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct fm10k_hw_stats *hw_stats = FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); memset(hw_stats, 0, sizeof(*hw_stats)); fm10k_rebind_hw_stats(hw, hw_stats); } static void fm10k_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); dev_info->min_rx_bufsize = FM10K_MIN_RX_BUF_SIZE; dev_info->max_rx_pktlen = FM10K_MAX_PKT_SIZE; dev_info->max_rx_queues = hw->mac.max_queues; dev_info->max_tx_queues = hw->mac.max_queues; dev_info->max_mac_addrs = FM10K_MAX_MACADDR_NUM; dev_info->max_hash_mac_addrs = 0; dev_info->max_vfs = dev->pci_dev->max_vfs; dev_info->max_vmdq_pools = ETH_64_POOLS; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM; dev_info->hash_key_size = FM10K_RSSRK_SIZE * sizeof(uint32_t); dev_info->reta_size = FM10K_MAX_RSS_INDICES; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = FM10K_DEFAULT_RX_PTHRESH, .hthresh = FM10K_DEFAULT_RX_HTHRESH, .wthresh = FM10K_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = FM10K_RX_FREE_THRESH_DEFAULT(0), .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = FM10K_DEFAULT_TX_PTHRESH, .hthresh = FM10K_DEFAULT_TX_HTHRESH, .wthresh = FM10K_DEFAULT_TX_WTHRESH, }, .tx_free_thresh = FM10K_TX_FREE_THRESH_DEFAULT(0), .tx_rs_thresh = FM10K_TX_RS_THRESH_DEFAULT(0), .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; } static int fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { s32 result; uint16_t mac_num = 0; uint32_t vid_idx, vid_bit, mac_index; struct fm10k_hw *hw; struct fm10k_macvlan_filter_info *macvlan; struct rte_eth_dev_data *data = dev->data; hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); if (vlan_id > ETH_VLAN_ID_MAX) { PMD_INIT_LOG(ERR, "Invalid vlan_id: must be < 4096"); return (-EINVAL); } vid_idx = FM10K_VFTA_IDX(vlan_id); vid_bit = FM10K_VFTA_BIT(vlan_id); /* this VLAN ID is already in the VLAN filter table, return SUCCESS */ if (on && (macvlan->vfta[vid_idx] & vid_bit)) return 0; /* this VLAN ID is NOT in the VLAN filter table, cannot remove */ if (!on && !(macvlan->vfta[vid_idx] & vid_bit)) { PMD_INIT_LOG(ERR, "Invalid vlan_id: not existing " "in the VLAN filter table"); return (-EINVAL); } fm10k_mbx_lock(hw); result = fm10k_update_vlan(hw, vlan_id, 0, on); fm10k_mbx_unlock(hw); if (result != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "VLAN update failed: %d", result); return (-EIO); } for (mac_index = 0; (mac_index < FM10K_MAX_MACADDR_NUM) && (result == FM10K_SUCCESS); mac_index++) { if (is_zero_ether_addr(&data->mac_addrs[mac_index])) continue; if (mac_num > macvlan->mac_num - 1) { PMD_INIT_LOG(ERR, "MAC address number " "not match"); break; } fm10k_mbx_lock(hw); result = fm10k_update_uc_addr(hw, hw->mac.dglort_map, data->mac_addrs[mac_index].addr_bytes, vlan_id, on, 0); fm10k_mbx_unlock(hw); mac_num++; } if (result != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "MAC address update failed: %d", result); return (-EIO); } if (on) { macvlan->vlan_num++; macvlan->vfta[vid_idx] |= vid_bit; } else { macvlan->vlan_num--; macvlan->vfta[vid_idx] &= ~vid_bit; } return 0; } static void fm10k_vlan_offload_set(__rte_unused struct rte_eth_dev *dev, int mask) { if (mask & ETH_VLAN_STRIP_MASK) { if (!dev->data->dev_conf.rxmode.hw_vlan_strip) PMD_INIT_LOG(ERR, "VLAN stripping is " "always on in fm10k"); } if (mask & ETH_VLAN_EXTEND_MASK) { if (dev->data->dev_conf.rxmode.hw_vlan_extend) PMD_INIT_LOG(ERR, "VLAN QinQ is not " "supported in fm10k"); } if (mask & ETH_VLAN_FILTER_MASK) { if (!dev->data->dev_conf.rxmode.hw_vlan_filter) PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k"); } } /* Add/Remove a MAC address, and update filters */ static void fm10k_MAC_filter_set(struct rte_eth_dev *dev, const u8 *mac, bool add) { uint32_t i, j, k; struct fm10k_hw *hw; struct fm10k_macvlan_filter_info *macvlan; hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); i = 0; for (j = 0; j < FM10K_VFTA_SIZE; j++) { if (macvlan->vfta[j]) { for (k = 0; k < FM10K_UINT32_BIT_SIZE; k++) { if (macvlan->vfta[j] & (1 << k)) { if (i + 1 > macvlan->vlan_num) { PMD_INIT_LOG(ERR, "vlan number " "not match"); return; } fm10k_mbx_lock(hw); fm10k_update_uc_addr(hw, hw->mac.dglort_map, mac, j * FM10K_UINT32_BIT_SIZE + k, add, 0); fm10k_mbx_unlock(hw); i++; } } } } if (add) macvlan->mac_num++; else macvlan->mac_num--; } /* Add a MAC address, and update filters */ static void fm10k_macaddr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, __rte_unused uint32_t index, __rte_unused uint32_t pool) { fm10k_MAC_filter_set(dev, mac_addr->addr_bytes, TRUE); } /* Remove a MAC address, and update filters */ static void fm10k_macaddr_remove(struct rte_eth_dev *dev, uint32_t index) { struct rte_eth_dev_data *data = dev->data; if (index < FM10K_MAX_MACADDR_NUM) fm10k_MAC_filter_set(dev, data->mac_addrs[index].addr_bytes, FALSE); } /* Remove all VLAN and MAC address table entries */ static void fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev) { uint32_t j, k; struct fm10k_macvlan_filter_info *macvlan; macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); for (j = 0; j < FM10K_VFTA_SIZE; j++) { if (macvlan->vfta[j]) { for (k = 0; k < FM10K_UINT32_BIT_SIZE; k++) { if (macvlan->vfta[j] & (1 << k)) fm10k_vlan_filter_set(dev, j * FM10K_UINT32_BIT_SIZE + k, false); } } } } static inline int check_nb_desc(uint16_t min, uint16_t max, uint16_t mult, uint16_t request) { if ((request < min) || (request > max) || ((request % mult) != 0)) return -1; else return 0; } /* * Create a memzone for hardware descriptor rings. Malloc cannot be used since * the physical address is required. If the memzone is already created, then * this function returns a pointer to the existing memzone. */ static inline const struct rte_memzone * allocate_hw_ring(const char *driver_name, const char *ring_name, uint8_t port_id, uint16_t queue_id, int socket_id, uint32_t size, uint32_t align) { char name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(name, sizeof(name), "%s_%s_%d_%d_%d", driver_name, ring_name, port_id, queue_id, socket_id); /* return the memzone if it already exists */ mz = rte_memzone_lookup(name); if (mz) return mz; #ifdef RTE_LIBRTE_XEN_DOM0 return rte_memzone_reserve_bounded(name, size, socket_id, 0, align, RTE_PGSIZE_2M); #else return rte_memzone_reserve_aligned(name, size, socket_id, 0, align); #endif } static inline int check_thresh(uint16_t min, uint16_t max, uint16_t div, uint16_t request) { if ((request < min) || (request > max) || ((div % request) != 0)) return -1; else return 0; } static inline int handle_rxconf(struct fm10k_rx_queue *q, const struct rte_eth_rxconf *conf) { uint16_t rx_free_thresh; if (conf->rx_free_thresh == 0) rx_free_thresh = FM10K_RX_FREE_THRESH_DEFAULT(q); else rx_free_thresh = conf->rx_free_thresh; /* make sure the requested threshold satisfies the constraints */ if (check_thresh(FM10K_RX_FREE_THRESH_MIN(q), FM10K_RX_FREE_THRESH_MAX(q), FM10K_RX_FREE_THRESH_DIV(q), rx_free_thresh)) { PMD_INIT_LOG(ERR, "rx_free_thresh (%u) must be " "less than or equal to %u, " "greater than or equal to %u, " "and a divisor of %u", rx_free_thresh, FM10K_RX_FREE_THRESH_MAX(q), FM10K_RX_FREE_THRESH_MIN(q), FM10K_RX_FREE_THRESH_DIV(q)); return (-EINVAL); } q->alloc_thresh = rx_free_thresh; q->drop_en = conf->rx_drop_en; q->rx_deferred_start = conf->rx_deferred_start; return 0; } /* * Hardware requires specific alignment for Rx packet buffers. At * least one of the following two conditions must be satisfied. * 1. Address is 512B aligned * 2. Address is 8B aligned and buffer does not cross 4K boundary. * * As such, the driver may need to adjust the DMA address within the * buffer by up to 512B. * * return 1 if the element size is valid, otherwise return 0. */ static int mempool_element_size_valid(struct rte_mempool *mp) { uint32_t min_size; /* elt_size includes mbuf header and headroom */ min_size = mp->elt_size - sizeof(struct rte_mbuf) - RTE_PKTMBUF_HEADROOM; /* account for up to 512B of alignment */ min_size -= FM10K_RX_DATABUF_ALIGN; /* sanity check for overflow */ if (min_size > mp->elt_size) return 0; /* size is valid */ return 1; } static int fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *conf, struct rte_mempool *mp) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct fm10k_rx_queue *q; const struct rte_memzone *mz; PMD_INIT_FUNC_TRACE(); /* make sure the mempool element size can account for alignment. */ if (!mempool_element_size_valid(mp)) { PMD_INIT_LOG(ERR, "Error : Mempool element size is too small"); return (-EINVAL); } /* make sure a valid number of descriptors have been requested */ if (check_nb_desc(FM10K_MIN_RX_DESC, FM10K_MAX_RX_DESC, FM10K_MULT_RX_DESC, nb_desc)) { PMD_INIT_LOG(ERR, "Number of Rx descriptors (%u) must be " "less than or equal to %"PRIu32", " "greater than or equal to %u, " "and a multiple of %u", nb_desc, (uint32_t)FM10K_MAX_RX_DESC, FM10K_MIN_RX_DESC, FM10K_MULT_RX_DESC); return (-EINVAL); } /* * if this queue existed already, free the associated memory. The * queue cannot be reused in case we need to allocate memory on * different socket than was previously used. */ if (dev->data->rx_queues[queue_id] != NULL) { rx_queue_free(dev->data->rx_queues[queue_id]); dev->data->rx_queues[queue_id] = NULL; } /* allocate memory for the queue structure */ q = rte_zmalloc_socket("fm10k", sizeof(*q), RTE_CACHE_LINE_SIZE, socket_id); if (q == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate queue structure"); return (-ENOMEM); } /* setup queue */ q->mp = mp; q->nb_desc = nb_desc; q->port_id = dev->data->port_id; q->queue_id = queue_id; q->tail_ptr = (volatile uint32_t *) &((uint32_t *)hw->hw_addr)[FM10K_RDT(queue_id)]; if (handle_rxconf(q, conf)) return (-EINVAL); /* allocate memory for the software ring */ q->sw_ring = rte_zmalloc_socket("fm10k sw ring", nb_desc * sizeof(struct rte_mbuf *), RTE_CACHE_LINE_SIZE, socket_id); if (q->sw_ring == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate software ring"); rte_free(q); return (-ENOMEM); } /* * allocate memory for the hardware descriptor ring. A memzone large * enough to hold the maximum ring size is requested to allow for * resizing in later calls to the queue setup function. */ mz = allocate_hw_ring(dev->driver->pci_drv.name, "rx_ring", dev->data->port_id, queue_id, socket_id, FM10K_MAX_RX_RING_SZ, FM10K_ALIGN_RX_DESC); if (mz == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate hardware ring"); rte_free(q->sw_ring); rte_free(q); return (-ENOMEM); } q->hw_ring = mz->addr; #ifdef RTE_LIBRTE_XEN_DOM0 q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); #else q->hw_ring_phys_addr = mz->phys_addr; #endif dev->data->rx_queues[queue_id] = q; return 0; } static void fm10k_rx_queue_release(void *queue) { PMD_INIT_FUNC_TRACE(); rx_queue_free(queue); } static inline int handle_txconf(struct fm10k_tx_queue *q, const struct rte_eth_txconf *conf) { uint16_t tx_free_thresh; uint16_t tx_rs_thresh; /* constraint MACROs require that tx_free_thresh is configured * before tx_rs_thresh */ if (conf->tx_free_thresh == 0) tx_free_thresh = FM10K_TX_FREE_THRESH_DEFAULT(q); else tx_free_thresh = conf->tx_free_thresh; /* make sure the requested threshold satisfies the constraints */ if (check_thresh(FM10K_TX_FREE_THRESH_MIN(q), FM10K_TX_FREE_THRESH_MAX(q), FM10K_TX_FREE_THRESH_DIV(q), tx_free_thresh)) { PMD_INIT_LOG(ERR, "tx_free_thresh (%u) must be " "less than or equal to %u, " "greater than or equal to %u, " "and a divisor of %u", tx_free_thresh, FM10K_TX_FREE_THRESH_MAX(q), FM10K_TX_FREE_THRESH_MIN(q), FM10K_TX_FREE_THRESH_DIV(q)); return (-EINVAL); } q->free_thresh = tx_free_thresh; if (conf->tx_rs_thresh == 0) tx_rs_thresh = FM10K_TX_RS_THRESH_DEFAULT(q); else tx_rs_thresh = conf->tx_rs_thresh; q->tx_deferred_start = conf->tx_deferred_start; /* make sure the requested threshold satisfies the constraints */ if (check_thresh(FM10K_TX_RS_THRESH_MIN(q), FM10K_TX_RS_THRESH_MAX(q), FM10K_TX_RS_THRESH_DIV(q), tx_rs_thresh)) { PMD_INIT_LOG(ERR, "tx_rs_thresh (%u) must be " "less than or equal to %u, " "greater than or equal to %u, " "and a divisor of %u", tx_rs_thresh, FM10K_TX_RS_THRESH_MAX(q), FM10K_TX_RS_THRESH_MIN(q), FM10K_TX_RS_THRESH_DIV(q)); return (-EINVAL); } q->rs_thresh = tx_rs_thresh; return 0; } static int fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *conf) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct fm10k_tx_queue *q; const struct rte_memzone *mz; PMD_INIT_FUNC_TRACE(); /* make sure a valid number of descriptors have been requested */ if (check_nb_desc(FM10K_MIN_TX_DESC, FM10K_MAX_TX_DESC, FM10K_MULT_TX_DESC, nb_desc)) { PMD_INIT_LOG(ERR, "Number of Tx descriptors (%u) must be " "less than or equal to %"PRIu32", " "greater than or equal to %u, " "and a multiple of %u", nb_desc, (uint32_t)FM10K_MAX_TX_DESC, FM10K_MIN_TX_DESC, FM10K_MULT_TX_DESC); return (-EINVAL); } /* * if this queue existed already, free the associated memory. The * queue cannot be reused in case we need to allocate memory on * different socket than was previously used. */ if (dev->data->tx_queues[queue_id] != NULL) { tx_queue_free(dev->data->tx_queues[queue_id]); dev->data->tx_queues[queue_id] = NULL; } /* allocate memory for the queue structure */ q = rte_zmalloc_socket("fm10k", sizeof(*q), RTE_CACHE_LINE_SIZE, socket_id); if (q == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate queue structure"); return (-ENOMEM); } /* setup queue */ q->nb_desc = nb_desc; q->port_id = dev->data->port_id; q->queue_id = queue_id; q->tail_ptr = (volatile uint32_t *) &((uint32_t *)hw->hw_addr)[FM10K_TDT(queue_id)]; if (handle_txconf(q, conf)) return (-EINVAL); /* allocate memory for the software ring */ q->sw_ring = rte_zmalloc_socket("fm10k sw ring", nb_desc * sizeof(struct rte_mbuf *), RTE_CACHE_LINE_SIZE, socket_id); if (q->sw_ring == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate software ring"); rte_free(q); return (-ENOMEM); } /* * allocate memory for the hardware descriptor ring. A memzone large * enough to hold the maximum ring size is requested to allow for * resizing in later calls to the queue setup function. */ mz = allocate_hw_ring(dev->driver->pci_drv.name, "tx_ring", dev->data->port_id, queue_id, socket_id, FM10K_MAX_TX_RING_SZ, FM10K_ALIGN_TX_DESC); if (mz == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate hardware ring"); rte_free(q->sw_ring); rte_free(q); return (-ENOMEM); } q->hw_ring = mz->addr; #ifdef RTE_LIBRTE_XEN_DOM0 q->hw_ring_phys_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); #else q->hw_ring_phys_addr = mz->phys_addr; #endif /* * allocate memory for the RS bit tracker. Enough slots to hold the * descriptor index for each RS bit needing to be set are required. */ q->rs_tracker.list = rte_zmalloc_socket("fm10k rs tracker", ((nb_desc + 1) / q->rs_thresh) * sizeof(uint16_t), RTE_CACHE_LINE_SIZE, socket_id); if (q->rs_tracker.list == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate RS bit tracker"); rte_free(q->sw_ring); rte_free(q); return (-ENOMEM); } dev->data->tx_queues[queue_id] = q; return 0; } static void fm10k_tx_queue_release(void *queue) { PMD_INIT_FUNC_TRACE(); tx_queue_free(queue); } static int fm10k_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint16_t i, j, idx, shift; uint8_t mask; uint32_t reta; PMD_INIT_FUNC_TRACE(); if (reta_size > FM10K_MAX_RSS_INDICES) { PMD_INIT_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)", reta_size, FM10K_MAX_RSS_INDICES); return -EINVAL; } /* * Update Redirection Table RETA[n], n=0..31. The redirection table has * 128-entries in 32 registers */ for (i = 0; i < FM10K_MAX_RSS_INDICES; i += CHARS_PER_UINT32) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & BIT_MASK_PER_UINT32); if (mask == 0) continue; reta = 0; if (mask != BIT_MASK_PER_UINT32) reta = FM10K_READ_REG(hw, FM10K_RETA(0, i >> 2)); for (j = 0; j < CHARS_PER_UINT32; j++) { if (mask & (0x1 << j)) { if (mask != 0xF) reta &= ~(UINT8_MAX << CHAR_BIT * j); reta |= reta_conf[idx].reta[shift + j] << (CHAR_BIT * j); } } FM10K_WRITE_REG(hw, FM10K_RETA(0, i >> 2), reta); } return 0; } static int fm10k_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint16_t i, j, idx, shift; uint8_t mask; uint32_t reta; PMD_INIT_FUNC_TRACE(); if (reta_size < FM10K_MAX_RSS_INDICES) { PMD_INIT_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)", reta_size, FM10K_MAX_RSS_INDICES); return -EINVAL; } /* * Read Redirection Table RETA[n], n=0..31. The redirection table has * 128-entries in 32 registers */ for (i = 0; i < FM10K_MAX_RSS_INDICES; i += CHARS_PER_UINT32) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & BIT_MASK_PER_UINT32); if (mask == 0) continue; reta = FM10K_READ_REG(hw, FM10K_RETA(0, i >> 2)); for (j = 0; j < CHARS_PER_UINT32; j++) { if (mask & (0x1 << j)) reta_conf[idx].reta[shift + j] = ((reta >> CHAR_BIT * j) & UINT8_MAX); } } return 0; } static int fm10k_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *key = (uint32_t *)rss_conf->rss_key; uint32_t mrqc; uint64_t hf = rss_conf->rss_hf; int i; PMD_INIT_FUNC_TRACE(); if (rss_conf->rss_key_len < FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG) return -EINVAL; if (hf == 0) return -EINVAL; mrqc = 0; mrqc |= (hf & ETH_RSS_IPV4) ? FM10K_MRQC_IPV4 : 0; mrqc |= (hf & ETH_RSS_IPV6) ? FM10K_MRQC_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_EX) ? FM10K_MRQC_IPV6 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_TCP) ? FM10K_MRQC_TCP_IPV4 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_TCP) ? FM10K_MRQC_TCP_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_TCP_EX) ? FM10K_MRQC_TCP_IPV6 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV4_UDP) ? FM10K_MRQC_UDP_IPV4 : 0; mrqc |= (hf & ETH_RSS_NONFRAG_IPV6_UDP) ? FM10K_MRQC_UDP_IPV6 : 0; mrqc |= (hf & ETH_RSS_IPV6_UDP_EX) ? FM10K_MRQC_UDP_IPV6 : 0; /* If the mapping doesn't fit any supported, return */ if (mrqc == 0) return -EINVAL; if (key != NULL) for (i = 0; i < FM10K_RSSRK_SIZE; ++i) FM10K_WRITE_REG(hw, FM10K_RSSRK(0, i), key[i]); FM10K_WRITE_REG(hw, FM10K_MRQC(0), mrqc); return 0; } static int fm10k_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *key = (uint32_t *)rss_conf->rss_key; uint32_t mrqc; uint64_t hf; int i; PMD_INIT_FUNC_TRACE(); if (rss_conf->rss_key_len < FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG) return -EINVAL; if (key != NULL) for (i = 0; i < FM10K_RSSRK_SIZE; ++i) key[i] = FM10K_READ_REG(hw, FM10K_RSSRK(0, i)); mrqc = FM10K_READ_REG(hw, FM10K_MRQC(0)); hf = 0; hf |= (mrqc & FM10K_MRQC_IPV4) ? ETH_RSS_IPV4 : 0; hf |= (mrqc & FM10K_MRQC_IPV6) ? ETH_RSS_IPV6 : 0; hf |= (mrqc & FM10K_MRQC_IPV6) ? ETH_RSS_IPV6_EX : 0; hf |= (mrqc & FM10K_MRQC_TCP_IPV4) ? ETH_RSS_NONFRAG_IPV4_TCP : 0; hf |= (mrqc & FM10K_MRQC_TCP_IPV6) ? ETH_RSS_NONFRAG_IPV6_TCP : 0; hf |= (mrqc & FM10K_MRQC_TCP_IPV6) ? ETH_RSS_IPV6_TCP_EX : 0; hf |= (mrqc & FM10K_MRQC_UDP_IPV4) ? ETH_RSS_NONFRAG_IPV4_UDP : 0; hf |= (mrqc & FM10K_MRQC_UDP_IPV6) ? ETH_RSS_NONFRAG_IPV6_UDP : 0; hf |= (mrqc & FM10K_MRQC_UDP_IPV6) ? ETH_RSS_IPV6_UDP_EX : 0; rss_conf->rss_hf = hf; return 0; } static void fm10k_dev_enable_intr_pf(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; /* Bind all local non-queue interrupt to vector 0 */ int_map |= 0; FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchUpDown), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchEvent), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SRAM), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_VFLR), int_map); /* Enable misc causes */ FM10K_WRITE_REG(hw, FM10K_EIMR, FM10K_EIMR_ENABLE(PCA_FAULT) | FM10K_EIMR_ENABLE(THI_FAULT) | FM10K_EIMR_ENABLE(FUM_FAULT) | FM10K_EIMR_ENABLE(MAILBOX) | FM10K_EIMR_ENABLE(SWITCHREADY) | FM10K_EIMR_ENABLE(SWITCHNOTREADY) | FM10K_EIMR_ENABLE(SRAMERROR) | FM10K_EIMR_ENABLE(VFLR)); /* Enable ITR 0 */ FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR); FM10K_WRITE_FLUSH(hw); } static void fm10k_dev_disable_intr_pf(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_DISABLE; int_map |= 0; FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_Mailbox), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_PCIeFault), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchUpDown), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SwitchEvent), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_SRAM), int_map); FM10K_WRITE_REG(hw, FM10K_INT_MAP(fm10k_int_VFLR), int_map); /* Disable misc causes */ FM10K_WRITE_REG(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(PCA_FAULT) | FM10K_EIMR_DISABLE(THI_FAULT) | FM10K_EIMR_DISABLE(FUM_FAULT) | FM10K_EIMR_DISABLE(MAILBOX) | FM10K_EIMR_DISABLE(SWITCHREADY) | FM10K_EIMR_DISABLE(SWITCHNOTREADY) | FM10K_EIMR_DISABLE(SRAMERROR) | FM10K_EIMR_DISABLE(VFLR)); /* Disable ITR 0 */ FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_MASK_SET); FM10K_WRITE_FLUSH(hw); } static void fm10k_dev_enable_intr_vf(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_IMMEDIATE; /* Bind all local non-queue interrupt to vector 0 */ int_map |= 0; /* Only INT 0 available, other 15 are reserved. */ FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); /* Enable ITR 0 */ FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR); FM10K_WRITE_FLUSH(hw); } static void fm10k_dev_disable_intr_vf(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t int_map = FM10K_INT_MAP_DISABLE; int_map |= 0; /* Only INT 0 available, other 15 are reserved. */ FM10K_WRITE_REG(hw, FM10K_VFINT_MAP, int_map); /* Disable ITR 0 */ FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_MASK_SET); FM10K_WRITE_FLUSH(hw); } static int fm10k_dev_handle_fault(struct fm10k_hw *hw, uint32_t eicr) { struct fm10k_fault fault; int err; const char *estr = "Unknown error"; /* Process PCA fault */ if (eicr & FM10K_EICR_PCA_FAULT) { err = fm10k_get_fault(hw, FM10K_PCA_FAULT, &fault); if (err) goto error; switch (fault.type) { case PCA_NO_FAULT: estr = "PCA_NO_FAULT"; break; case PCA_UNMAPPED_ADDR: estr = "PCA_UNMAPPED_ADDR"; break; case PCA_BAD_QACCESS_PF: estr = "PCA_BAD_QACCESS_PF"; break; case PCA_BAD_QACCESS_VF: estr = "PCA_BAD_QACCESS_VF"; break; case PCA_MALICIOUS_REQ: estr = "PCA_MALICIOUS_REQ"; break; case PCA_POISONED_TLP: estr = "PCA_POISONED_TLP"; break; case PCA_TLP_ABORT: estr = "PCA_TLP_ABORT"; break; default: goto error; } PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", estr, fault.func ? "VF" : "PF", fault.func, fault.address, fault.specinfo); } /* Process THI fault */ if (eicr & FM10K_EICR_THI_FAULT) { err = fm10k_get_fault(hw, FM10K_THI_FAULT, &fault); if (err) goto error; switch (fault.type) { case THI_NO_FAULT: estr = "THI_NO_FAULT"; break; case THI_MAL_DIS_Q_FAULT: estr = "THI_MAL_DIS_Q_FAULT"; break; default: goto error; } PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", estr, fault.func ? "VF" : "PF", fault.func, fault.address, fault.specinfo); } /* Process FUM fault */ if (eicr & FM10K_EICR_FUM_FAULT) { err = fm10k_get_fault(hw, FM10K_FUM_FAULT, &fault); if (err) goto error; switch (fault.type) { case FUM_NO_FAULT: estr = "FUM_NO_FAULT"; break; case FUM_UNMAPPED_ADDR: estr = "FUM_UNMAPPED_ADDR"; break; case FUM_POISONED_TLP: estr = "FUM_POISONED_TLP"; break; case FUM_BAD_VF_QACCESS: estr = "FUM_BAD_VF_QACCESS"; break; case FUM_ADD_DECODE_ERR: estr = "FUM_ADD_DECODE_ERR"; break; case FUM_RO_ERROR: estr = "FUM_RO_ERROR"; break; case FUM_QPRC_CRC_ERROR: estr = "FUM_QPRC_CRC_ERROR"; break; case FUM_CSR_TIMEOUT: estr = "FUM_CSR_TIMEOUT"; break; case FUM_INVALID_TYPE: estr = "FUM_INVALID_TYPE"; break; case FUM_INVALID_LENGTH: estr = "FUM_INVALID_LENGTH"; break; case FUM_INVALID_BE: estr = "FUM_INVALID_BE"; break; case FUM_INVALID_ALIGN: estr = "FUM_INVALID_ALIGN"; break; default: goto error; } PMD_INIT_LOG(ERR, "%s: %s(%d) Addr:0x%"PRIx64" Spec: 0x%x", estr, fault.func ? "VF" : "PF", fault.func, fault.address, fault.specinfo); } return 0; error: PMD_INIT_LOG(ERR, "Failed to handle fault event."); return err; } /** * PF interrupt handler triggered by NIC for handling specific interrupt. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void fm10k_dev_interrupt_handler_pf( __rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t cause, status; if (hw->mac.type != fm10k_mac_pf) return; cause = FM10K_READ_REG(hw, FM10K_EICR); /* Handle PCI fault cases */ if (cause & FM10K_EICR_FAULT_MASK) { PMD_INIT_LOG(ERR, "INT: find fault!"); fm10k_dev_handle_fault(hw, cause); } /* Handle switch up/down */ if (cause & FM10K_EICR_SWITCHNOTREADY) PMD_INIT_LOG(ERR, "INT: Switch is not ready"); if (cause & FM10K_EICR_SWITCHREADY) PMD_INIT_LOG(INFO, "INT: Switch is ready"); /* Handle mailbox message */ fm10k_mbx_lock(hw); hw->mbx.ops.process(hw, &hw->mbx); fm10k_mbx_unlock(hw); /* Handle SRAM error */ if (cause & FM10K_EICR_SRAMERROR) { PMD_INIT_LOG(ERR, "INT: SRAM error on PEP"); status = FM10K_READ_REG(hw, FM10K_SRAM_IP); /* Write to clear pending bits */ FM10K_WRITE_REG(hw, FM10K_SRAM_IP, status); /* Todo: print out error message after shared code updates */ } /* Clear these 3 events if having any */ cause &= FM10K_EICR_SWITCHNOTREADY | FM10K_EICR_MAILBOX | FM10K_EICR_SWITCHREADY; if (cause) FM10K_WRITE_REG(hw, FM10K_EICR, cause); /* Re-enable interrupt from device side */ FM10K_WRITE_REG(hw, FM10K_ITR(0), FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR); /* Re-enable interrupt from host side */ rte_intr_enable(&(dev->pci_dev->intr_handle)); } /** * VF interrupt handler triggered by NIC for handling specific interrupt. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void fm10k_dev_interrupt_handler_vf( __rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (hw->mac.type != fm10k_mac_vf) return; /* Handle mailbox message if lock is acquired */ fm10k_mbx_lock(hw); hw->mbx.ops.process(hw, &hw->mbx); fm10k_mbx_unlock(hw); /* Re-enable interrupt from device side */ FM10K_WRITE_REG(hw, FM10K_VFITR(0), FM10K_ITR_AUTOMASK | FM10K_ITR_MASK_CLEAR); /* Re-enable interrupt from host side */ rte_intr_enable(&(dev->pci_dev->intr_handle)); } /* Mailbox message handler in VF */ static const struct fm10k_msg_data fm10k_msgdata_vf[] = { FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; /* Mailbox message handler in PF */ static const struct fm10k_msg_data fm10k_msgdata_pf[] = { FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf), FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), }; static int fm10k_setup_mbx_service(struct fm10k_hw *hw) { int err; /* Initialize mailbox lock */ fm10k_mbx_initlock(hw); /* Replace default message handler with new ones */ if (hw->mac.type == fm10k_mac_pf) err = hw->mbx.ops.register_handlers(&hw->mbx, fm10k_msgdata_pf); else err = hw->mbx.ops.register_handlers(&hw->mbx, fm10k_msgdata_vf); if (err) { PMD_INIT_LOG(ERR, "Failed to register mailbox handler.err:%d", err); return err; } /* Connect to SM for PF device or PF for VF device */ return hw->mbx.ops.connect(hw, &hw->mbx); } static void fm10k_close_mbx_service(struct fm10k_hw *hw) { /* Disconnect from SM for PF device or PF for VF device */ hw->mbx.ops.disconnect(hw, &hw->mbx); } static const struct eth_dev_ops fm10k_eth_dev_ops = { .dev_configure = fm10k_dev_configure, .dev_start = fm10k_dev_start, .dev_stop = fm10k_dev_stop, .dev_close = fm10k_dev_close, .promiscuous_enable = fm10k_dev_promiscuous_enable, .promiscuous_disable = fm10k_dev_promiscuous_disable, .allmulticast_enable = fm10k_dev_allmulticast_enable, .allmulticast_disable = fm10k_dev_allmulticast_disable, .stats_get = fm10k_stats_get, .stats_reset = fm10k_stats_reset, .link_update = fm10k_link_update, .dev_infos_get = fm10k_dev_infos_get, .vlan_filter_set = fm10k_vlan_filter_set, .vlan_offload_set = fm10k_vlan_offload_set, .mac_addr_add = fm10k_macaddr_add, .mac_addr_remove = fm10k_macaddr_remove, .rx_queue_start = fm10k_dev_rx_queue_start, .rx_queue_stop = fm10k_dev_rx_queue_stop, .tx_queue_start = fm10k_dev_tx_queue_start, .tx_queue_stop = fm10k_dev_tx_queue_stop, .rx_queue_setup = fm10k_rx_queue_setup, .rx_queue_release = fm10k_rx_queue_release, .tx_queue_setup = fm10k_tx_queue_setup, .tx_queue_release = fm10k_tx_queue_release, .reta_update = fm10k_reta_update, .reta_query = fm10k_reta_query, .rss_hash_update = fm10k_rss_hash_update, .rss_hash_conf_get = fm10k_rss_hash_conf_get, }; static int eth_fm10k_dev_init(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); int diag; struct fm10k_macvlan_filter_info *macvlan; PMD_INIT_FUNC_TRACE(); dev->dev_ops = &fm10k_eth_dev_ops; dev->rx_pkt_burst = &fm10k_recv_pkts; dev->tx_pkt_burst = &fm10k_xmit_pkts; if (dev->data->scattered_rx) dev->rx_pkt_burst = &fm10k_recv_scattered_pkts; /* only initialize in the primary process */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; macvlan = FM10K_DEV_PRIVATE_TO_MACVLAN(dev->data->dev_private); memset(macvlan, 0, sizeof(*macvlan)); /* Vendor and Device ID need to be set before init of shared code */ memset(hw, 0, sizeof(*hw)); hw->device_id = dev->pci_dev->id.device_id; hw->vendor_id = dev->pci_dev->id.vendor_id; hw->subsystem_device_id = dev->pci_dev->id.subsystem_device_id; hw->subsystem_vendor_id = dev->pci_dev->id.subsystem_vendor_id; hw->revision_id = 0; hw->hw_addr = (void *)dev->pci_dev->mem_resource[0].addr; if (hw->hw_addr == NULL) { PMD_INIT_LOG(ERR, "Bad mem resource." " Try to blacklist unused devices."); return -EIO; } /* Store fm10k_adapter pointer */ hw->back = dev->data->dev_private; /* Initialize the shared code */ diag = fm10k_init_shared_code(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Shared code init failed: %d", diag); return -EIO; } /* * Inialize bus info. Normally we would call fm10k_get_bus_info(), but * there is no way to get link status without reading BAR4. Until this * works, assume we have maximum bandwidth. * @todo - fix bus info */ hw->bus_caps.speed = fm10k_bus_speed_8000; hw->bus_caps.width = fm10k_bus_width_pcie_x8; hw->bus_caps.payload = fm10k_bus_payload_512; hw->bus.speed = fm10k_bus_speed_8000; hw->bus.width = fm10k_bus_width_pcie_x8; hw->bus.payload = fm10k_bus_payload_256; /* Initialize the hw */ diag = fm10k_init_hw(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Hardware init failed: %d", diag); return -EIO; } /* Initialize MAC address(es) */ dev->data->mac_addrs = rte_zmalloc("fm10k", ETHER_ADDR_LEN * FM10K_MAX_MACADDR_NUM, 0); if (dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate memory for MAC addresses"); return -ENOMEM; } diag = fm10k_read_mac_addr(hw); ether_addr_copy((const struct ether_addr *)hw->mac.addr, &dev->data->mac_addrs[0]); if (diag != FM10K_SUCCESS || !is_valid_assigned_ether_addr(dev->data->mac_addrs)) { /* Generate a random addr */ eth_random_addr(hw->mac.addr); memcpy(hw->mac.perm_addr, hw->mac.addr, ETH_ALEN); ether_addr_copy((const struct ether_addr *)hw->mac.addr, &dev->data->mac_addrs[0]); } /* Reset the hw statistics */ fm10k_stats_reset(dev); /* Reset the hw */ diag = fm10k_reset_hw(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Hardware reset failed: %d", diag); return -EIO; } /* Setup mailbox service */ diag = fm10k_setup_mbx_service(hw); if (diag != FM10K_SUCCESS) { PMD_INIT_LOG(ERR, "Failed to setup mailbox: %d", diag); return -EIO; } /*PF/VF has different interrupt handling mechanism */ if (hw->mac.type == fm10k_mac_pf) { /* register callback func to eal lib */ rte_intr_callback_register(&(dev->pci_dev->intr_handle), fm10k_dev_interrupt_handler_pf, (void *)dev); /* enable MISC interrupt */ fm10k_dev_enable_intr_pf(dev); } else { /* VF */ rte_intr_callback_register(&(dev->pci_dev->intr_handle), fm10k_dev_interrupt_handler_vf, (void *)dev); fm10k_dev_enable_intr_vf(dev); } /* Enable uio intr after callback registered */ rte_intr_enable(&(dev->pci_dev->intr_handle)); hw->mac.ops.update_int_moderator(hw); /* Make sure Switch Manager is ready before going forward. */ if (hw->mac.type == fm10k_mac_pf) { int switch_ready = 0; int i; for (i = 0; i < MAX_QUERY_SWITCH_STATE_TIMES; i++) { fm10k_mbx_lock(hw); hw->mac.ops.get_host_state(hw, &switch_ready); fm10k_mbx_unlock(hw); if (switch_ready) break; /* Delay some time to acquire async LPORT_MAP info. */ rte_delay_us(WAIT_SWITCH_MSG_US); } if (switch_ready == 0) { PMD_INIT_LOG(ERR, "switch is not ready"); return -1; } } /* * Below function will trigger operations on mailbox, acquire lock to * avoid race condition from interrupt handler. Operations on mailbox * FIFO will trigger interrupt to PF/SM, in which interrupt handler * will handle and generate an interrupt to our side. Then, FIFO in * mailbox will be touched. */ fm10k_mbx_lock(hw); /* Enable port first */ hw->mac.ops.update_lport_state(hw, hw->mac.dglort_map, 1, 1); /* Set unicast mode by default. App can change to other mode in other * API func. */ hw->mac.ops.update_xcast_mode(hw, hw->mac.dglort_map, FM10K_XCAST_MODE_NONE); fm10k_mbx_unlock(hw); /* Add default mac address */ fm10k_MAC_filter_set(dev, hw->mac.addr, true); return 0; } static int eth_fm10k_dev_uninit(struct rte_eth_dev *dev) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); /* only uninitialize in the primary process */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; /* safe to close dev here */ fm10k_dev_close(dev); dev->dev_ops = NULL; dev->rx_pkt_burst = NULL; dev->tx_pkt_burst = NULL; /* disable uio/vfio intr */ rte_intr_disable(&(dev->pci_dev->intr_handle)); /*PF/VF has different interrupt handling mechanism */ if (hw->mac.type == fm10k_mac_pf) { /* disable interrupt */ fm10k_dev_disable_intr_pf(dev); /* unregister callback func to eal lib */ rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), fm10k_dev_interrupt_handler_pf, (void *)dev); } else { /* disable interrupt */ fm10k_dev_disable_intr_vf(dev); rte_intr_callback_unregister(&(dev->pci_dev->intr_handle), fm10k_dev_interrupt_handler_vf, (void *)dev); } /* free mac memory */ if (dev->data->mac_addrs) { rte_free(dev->data->mac_addrs); dev->data->mac_addrs = NULL; } memset(hw, 0, sizeof(*hw)); return 0; } /* * The set of PCI devices this driver supports. This driver will enable both PF * and SRIOV-VF devices. */ static const struct rte_pci_id pci_id_fm10k_map[] = { #define RTE_PCI_DEV_ID_DECL_FM10K(vend, dev) { RTE_PCI_DEVICE(vend, dev) }, #define RTE_PCI_DEV_ID_DECL_FM10KVF(vend, dev) { RTE_PCI_DEVICE(vend, dev) }, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static struct eth_driver rte_pmd_fm10k = { .pci_drv = { .name = "rte_pmd_fm10k", .id_table = pci_id_fm10k_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_fm10k_dev_init, .eth_dev_uninit = eth_fm10k_dev_uninit, .dev_private_size = sizeof(struct fm10k_adapter), }; /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of PCI FM10K devices. */ static int rte_pmd_fm10k_init(__rte_unused const char *name, __rte_unused const char *params) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_pmd_fm10k); return 0; } static struct rte_driver rte_fm10k_driver = { .type = PMD_PDEV, .init = rte_pmd_fm10k_init, }; PMD_REGISTER_DRIVER(rte_fm10k_driver); ================================================ FILE: drivers/net/fm10k/fm10k_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _FM10K_LOGS_H_ #define _FM10K_LOGS_H_ #include #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) #ifdef RTE_LIBRTE_FM10K_DEBUG_INIT #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_FUNC_TRACE() do { } while (0) #endif #ifdef RTE_LIBRTE_FM10K_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_FM10K_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_FM10K_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while (0) #endif #ifdef RTE_LIBRTE_FM10K_DEBUG_DRIVER #define PMD_DRV_LOG_RAW(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) #else #define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) #endif #define PMD_DRV_LOG(level, fmt, args...) \ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) #endif /* _FM10K_LOGS_H_ */ ================================================ FILE: drivers/net/fm10k/fm10k_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "fm10k.h" #include "base/fm10k_type.h" #ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch(p) rte_prefetch1(p) #else #define rte_packet_prefetch(p) do {} while (0) #endif #ifdef RTE_LIBRTE_FM10K_DEBUG_RX static inline void dump_rxd(union fm10k_rx_desc *rxd) { PMD_RX_LOG(DEBUG, "+----------------|----------------+"); PMD_RX_LOG(DEBUG, "| GLORT | PKT HDR & TYPE |"); PMD_RX_LOG(DEBUG, "| 0x%08x | 0x%08x |", rxd->d.glort, rxd->d.data); PMD_RX_LOG(DEBUG, "+----------------|----------------+"); PMD_RX_LOG(DEBUG, "| VLAN & LEN | STATUS |"); PMD_RX_LOG(DEBUG, "| 0x%08x | 0x%08x |", rxd->d.vlan_len, rxd->d.staterr); PMD_RX_LOG(DEBUG, "+----------------|----------------+"); PMD_RX_LOG(DEBUG, "| RESERVED | RSS_HASH |"); PMD_RX_LOG(DEBUG, "| 0x%08x | 0x%08x |", 0, rxd->d.rss); PMD_RX_LOG(DEBUG, "+----------------|----------------+"); PMD_RX_LOG(DEBUG, "| TIME TAG |"); PMD_RX_LOG(DEBUG, "| 0x%016"PRIx64" |", rxd->q.timestamp); PMD_RX_LOG(DEBUG, "+----------------|----------------+"); } #endif static inline void rx_desc_to_ol_flags(struct rte_mbuf *m, const union fm10k_rx_desc *d) { #ifdef RTE_NEXT_ABI static const uint32_t ptype_table[FM10K_RXD_PKTTYPE_MASK >> FM10K_RXD_PKTTYPE_SHIFT] __rte_cache_aligned = { [FM10K_PKTTYPE_OTHER] = RTE_PTYPE_L2_ETHER, [FM10K_PKTTYPE_IPV4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4, [FM10K_PKTTYPE_IPV4_EX] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT, [FM10K_PKTTYPE_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6, [FM10K_PKTTYPE_IPV6_EX] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT, [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP, [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP, [FM10K_PKTTYPE_IPV4 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP, [FM10K_PKTTYPE_IPV6 | FM10K_PKTTYPE_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP, }; m->packet_type = ptype_table[(d->w.pkt_info & FM10K_RXD_PKTTYPE_MASK) >> FM10K_RXD_PKTTYPE_SHIFT]; #else /* RTE_NEXT_ABI */ uint16_t ptype; static const uint16_t pt_lut[] = { 0, PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT, PKT_RX_IPV6_HDR, PKT_RX_IPV6_HDR_EXT, 0, 0, 0 }; #endif /* RTE_NEXT_ABI */ if (d->w.pkt_info & FM10K_RXD_RSSTYPE_MASK) m->ol_flags |= PKT_RX_RSS_HASH; if (unlikely((d->d.staterr & (FM10K_RXD_STATUS_IPCS | FM10K_RXD_STATUS_IPE)) == (FM10K_RXD_STATUS_IPCS | FM10K_RXD_STATUS_IPE))) m->ol_flags |= PKT_RX_IP_CKSUM_BAD; if (unlikely((d->d.staterr & (FM10K_RXD_STATUS_L4CS | FM10K_RXD_STATUS_L4E)) == (FM10K_RXD_STATUS_L4CS | FM10K_RXD_STATUS_L4E))) m->ol_flags |= PKT_RX_L4_CKSUM_BAD; if (d->d.staterr & FM10K_RXD_STATUS_VEXT) m->ol_flags |= PKT_RX_VLAN_PKT; if (unlikely(d->d.staterr & FM10K_RXD_STATUS_HBO)) m->ol_flags |= PKT_RX_HBUF_OVERFLOW; if (unlikely(d->d.staterr & FM10K_RXD_STATUS_RXE)) m->ol_flags |= PKT_RX_RECIP_ERR; #ifndef RTE_NEXT_ABI ptype = (d->d.data & FM10K_RXD_PKTTYPE_MASK_L3) >> FM10K_RXD_PKTTYPE_SHIFT; m->ol_flags |= pt_lut[(uint8_t)ptype]; #endif } uint16_t fm10k_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct rte_mbuf *mbuf; union fm10k_rx_desc desc; struct fm10k_rx_queue *q = rx_queue; uint16_t count = 0; int alloc = 0; uint16_t next_dd; int ret; next_dd = q->next_dd; nb_pkts = RTE_MIN(nb_pkts, q->alloc_thresh); for (count = 0; count < nb_pkts; ++count) { mbuf = q->sw_ring[next_dd]; desc = q->hw_ring[next_dd]; if (!(desc.d.staterr & FM10K_RXD_STATUS_DD)) break; #ifdef RTE_LIBRTE_FM10K_DEBUG_RX dump_rxd(&desc); #endif rte_pktmbuf_pkt_len(mbuf) = desc.w.length; rte_pktmbuf_data_len(mbuf) = desc.w.length; mbuf->ol_flags = 0; #ifdef RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE rx_desc_to_ol_flags(mbuf, &desc); #endif mbuf->hash.rss = desc.d.rss; rx_pkts[count] = mbuf; if (++next_dd == q->nb_desc) { next_dd = 0; alloc = 1; } /* Prefetch next mbuf while processing current one. */ rte_prefetch0(q->sw_ring[next_dd]); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((next_dd & 0x3) == 0) { rte_prefetch0(&q->hw_ring[next_dd]); rte_prefetch0(&q->sw_ring[next_dd]); } } q->next_dd = next_dd; if ((q->next_dd > q->next_trigger) || (alloc == 1)) { ret = rte_mempool_get_bulk(q->mp, (void **)&q->sw_ring[q->next_alloc], q->alloc_thresh); if (unlikely(ret != 0)) { uint8_t port = q->port_id; PMD_RX_LOG(ERR, "Failed to alloc mbuf"); /* * Need to restore next_dd if we cannot allocate new * buffers to replenish the old ones. */ q->next_dd = (q->next_dd + q->nb_desc - count) % q->nb_desc; rte_eth_devices[port].data->rx_mbuf_alloc_failed++; return 0; } for (; q->next_alloc <= q->next_trigger; ++q->next_alloc) { mbuf = q->sw_ring[q->next_alloc]; /* setup static mbuf fields */ fm10k_pktmbuf_reset(mbuf, q->port_id); /* write descriptor */ desc.q.pkt_addr = MBUF_DMA_ADDR_DEFAULT(mbuf); desc.q.hdr_addr = MBUF_DMA_ADDR_DEFAULT(mbuf); q->hw_ring[q->next_alloc] = desc; } FM10K_PCI_REG_WRITE(q->tail_ptr, q->next_trigger); q->next_trigger += q->alloc_thresh; if (q->next_trigger >= q->nb_desc) { q->next_trigger = q->alloc_thresh - 1; q->next_alloc = 0; } } return count; } uint16_t fm10k_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct rte_mbuf *mbuf; union fm10k_rx_desc desc; struct fm10k_rx_queue *q = rx_queue; uint16_t count = 0; uint16_t nb_rcv, nb_seg; int alloc = 0; uint16_t next_dd; struct rte_mbuf *first_seg = q->pkt_first_seg; struct rte_mbuf *last_seg = q->pkt_last_seg; int ret; next_dd = q->next_dd; nb_rcv = 0; nb_seg = RTE_MIN(nb_pkts, q->alloc_thresh); for (count = 0; count < nb_seg; count++) { mbuf = q->sw_ring[next_dd]; desc = q->hw_ring[next_dd]; if (!(desc.d.staterr & FM10K_RXD_STATUS_DD)) break; #ifdef RTE_LIBRTE_FM10K_DEBUG_RX dump_rxd(&desc); #endif if (++next_dd == q->nb_desc) { next_dd = 0; alloc = 1; } /* Prefetch next mbuf while processing current one. */ rte_prefetch0(q->sw_ring[next_dd]); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((next_dd & 0x3) == 0) { rte_prefetch0(&q->hw_ring[next_dd]); rte_prefetch0(&q->sw_ring[next_dd]); } /* Fill data length */ rte_pktmbuf_data_len(mbuf) = desc.w.length; /* * If this is the first buffer of the received packet, * set the pointer to the first mbuf of the packet and * initialize its context. * Otherwise, update the total length and the number of segments * of the current scattered packet, and update the pointer to * the last mbuf of the current packet. */ if (!first_seg) { first_seg = mbuf; first_seg->pkt_len = desc.w.length; } else { first_seg->pkt_len = (uint16_t)(first_seg->pkt_len + rte_pktmbuf_data_len(mbuf)); first_seg->nb_segs++; last_seg->next = mbuf; } /* * If this is not the last buffer of the received packet, * update the pointer to the last mbuf of the current scattered * packet and continue to parse the RX ring. */ if (!(desc.d.staterr & FM10K_RXD_STATUS_EOP)) { last_seg = mbuf; continue; } first_seg->ol_flags = 0; #ifdef RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE rx_desc_to_ol_flags(first_seg, &desc); #endif first_seg->hash.rss = desc.d.rss; /* Prefetch data of first segment, if configured to do so. */ rte_packet_prefetch((char *)first_seg->buf_addr + first_seg->data_off); /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rcv++] = first_seg; /* * Setup receipt context for a new packet. */ first_seg = NULL; } q->next_dd = next_dd; if ((q->next_dd > q->next_trigger) || (alloc == 1)) { ret = rte_mempool_get_bulk(q->mp, (void **)&q->sw_ring[q->next_alloc], q->alloc_thresh); if (unlikely(ret != 0)) { uint8_t port = q->port_id; PMD_RX_LOG(ERR, "Failed to alloc mbuf"); /* * Need to restore next_dd if we cannot allocate new * buffers to replenish the old ones. */ q->next_dd = (q->next_dd + q->nb_desc - count) % q->nb_desc; rte_eth_devices[port].data->rx_mbuf_alloc_failed++; return 0; } for (; q->next_alloc <= q->next_trigger; ++q->next_alloc) { mbuf = q->sw_ring[q->next_alloc]; /* setup static mbuf fields */ fm10k_pktmbuf_reset(mbuf, q->port_id); /* write descriptor */ desc.q.pkt_addr = MBUF_DMA_ADDR_DEFAULT(mbuf); desc.q.hdr_addr = MBUF_DMA_ADDR_DEFAULT(mbuf); q->hw_ring[q->next_alloc] = desc; } FM10K_PCI_REG_WRITE(q->tail_ptr, q->next_trigger); q->next_trigger += q->alloc_thresh; if (q->next_trigger >= q->nb_desc) { q->next_trigger = q->alloc_thresh - 1; q->next_alloc = 0; } } q->pkt_first_seg = first_seg; q->pkt_last_seg = last_seg; return nb_rcv; } static inline void tx_free_descriptors(struct fm10k_tx_queue *q) { uint16_t next_rs, count = 0; next_rs = fifo_peek(&q->rs_tracker); if (!(q->hw_ring[next_rs].flags & FM10K_TXD_FLAG_DONE)) return; /* the DONE flag is set on this descriptor so remove the ID * from the RS bit tracker and free the buffers */ fifo_remove(&q->rs_tracker); /* wrap around? if so, free buffers from last_free up to but NOT * including nb_desc */ if (q->last_free > next_rs) { count = q->nb_desc - q->last_free; while (q->last_free < q->nb_desc) { rte_pktmbuf_free_seg(q->sw_ring[q->last_free]); q->sw_ring[q->last_free] = NULL; ++q->last_free; } q->last_free = 0; } /* adjust free descriptor count before the next loop */ q->nb_free += count + (next_rs + 1 - q->last_free); /* free buffers from last_free, up to and including next_rs */ while (q->last_free <= next_rs) { rte_pktmbuf_free_seg(q->sw_ring[q->last_free]); q->sw_ring[q->last_free] = NULL; ++q->last_free; } if (q->last_free == q->nb_desc) q->last_free = 0; } static inline void tx_xmit_pkt(struct fm10k_tx_queue *q, struct rte_mbuf *mb) { uint16_t last_id; uint8_t flags; /* always set the LAST flag on the last descriptor used to * transmit the packet */ flags = FM10K_TXD_FLAG_LAST; last_id = q->next_free + mb->nb_segs - 1; if (last_id >= q->nb_desc) last_id = last_id - q->nb_desc; /* but only set the RS flag on the last descriptor if rs_thresh * descriptors will be used since the RS flag was last set */ if ((q->nb_used + mb->nb_segs) >= q->rs_thresh) { flags |= FM10K_TXD_FLAG_RS; fifo_insert(&q->rs_tracker, last_id); q->nb_used = 0; } else { q->nb_used = q->nb_used + mb->nb_segs; } q->nb_free -= mb->nb_segs; q->hw_ring[q->next_free].flags = 0; /* set checksum flags on first descriptor of packet. SCTP checksum * offload is not supported, but we do not explicitly check for this * case in favor of greatly simplified processing. */ if (mb->ol_flags & (PKT_TX_IP_CKSUM | PKT_TX_L4_MASK)) q->hw_ring[q->next_free].flags |= FM10K_TXD_FLAG_CSUM; /* set vlan if requested */ if (mb->ol_flags & PKT_TX_VLAN_PKT) q->hw_ring[q->next_free].vlan = mb->vlan_tci; q->sw_ring[q->next_free] = mb; q->hw_ring[q->next_free].buffer_addr = rte_cpu_to_le_64(MBUF_DMA_ADDR(mb)); q->hw_ring[q->next_free].buflen = rte_cpu_to_le_16(rte_pktmbuf_data_len(mb)); if (++q->next_free == q->nb_desc) q->next_free = 0; /* fill up the rings */ for (mb = mb->next; mb != NULL; mb = mb->next) { q->sw_ring[q->next_free] = mb; q->hw_ring[q->next_free].buffer_addr = rte_cpu_to_le_64(MBUF_DMA_ADDR(mb)); q->hw_ring[q->next_free].buflen = rte_cpu_to_le_16(rte_pktmbuf_data_len(mb)); q->hw_ring[q->next_free].flags = 0; if (++q->next_free == q->nb_desc) q->next_free = 0; } q->hw_ring[last_id].flags = flags; } uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct fm10k_tx_queue *q = tx_queue; struct rte_mbuf *mb; uint16_t count; for (count = 0; count < nb_pkts; ++count) { mb = tx_pkts[count]; /* running low on descriptors? try to free some... */ if (q->nb_free < q->free_thresh) tx_free_descriptors(q); /* make sure there are enough free descriptors to transmit the * entire packet before doing anything */ if (q->nb_free < mb->nb_segs) break; /* sanity check to make sure the mbuf is valid */ if ((mb->nb_segs == 0) || ((mb->nb_segs > 1) && (mb->next == NULL))) break; /* process the packet */ tx_xmit_pkt(q, mb); } /* update the tail pointer if any packets were processed */ if (likely(count > 0)) FM10K_PCI_REG_WRITE(q->tail_ptr, q->next_free); return count; } ================================================ FILE: drivers/net/i40e/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_i40e.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -DPF_DRIVER -DVF_DRIVER -DINTEGRATED_VF EXPORT_MAP := rte_pmd_i40e_version.map LIBABIVER := 1 # # Add extra flags for base driver files (also known as shared code) # to disable warnings # ifeq ($(CC), icc) CFLAGS_BASE_DRIVER = -wd593 -wd188 else ifeq ($(CC), clang) CFLAGS_BASE_DRIVER += -Wno-sign-compare CFLAGS_BASE_DRIVER += -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-unused-parameter CFLAGS_BASE_DRIVER += -Wno-strict-aliasing CFLAGS_BASE_DRIVER += -Wno-format CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers CFLAGS_BASE_DRIVER += -Wno-pointer-to-int-cast CFLAGS_BASE_DRIVER += -Wno-format-nonliteral CFLAGS_BASE_DRIVER += -Wno-unused-variable else CFLAGS_BASE_DRIVER = -Wno-sign-compare CFLAGS_BASE_DRIVER += -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-unused-parameter CFLAGS_BASE_DRIVER += -Wno-strict-aliasing CFLAGS_BASE_DRIVER += -Wno-format CFLAGS_BASE_DRIVER += -Wno-missing-field-initializers CFLAGS_BASE_DRIVER += -Wno-pointer-to-int-cast CFLAGS_BASE_DRIVER += -Wno-format-nonliteral CFLAGS_BASE_DRIVER += -Wno-format-security CFLAGS_BASE_DRIVER += -Wno-unused-variable ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS_BASE_DRIVER += -Wno-unused-but-set-variable endif CFLAGS_i40e_lan_hmc.o += -Wno-error endif OBJS_BASE_DRIVER=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(OBJS_BASE_DRIVER), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_adminq.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_common.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_diag.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_hmc.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_lan_hmc.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_nvm.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_dcb.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/i40e/base/i40e_adminq.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_status.h" #include "i40e_type.h" #include "i40e_register.h" #include "i40e_adminq.h" #include "i40e_prototype.h" #ifdef PF_DRIVER /** * i40e_is_nvm_update_op - return true if this is an NVM update operation * @desc: API request descriptor **/ STATIC INLINE bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc) { return (desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_erase) || desc->opcode == CPU_TO_LE16(i40e_aqc_opc_nvm_update)); } #endif /* PF_DRIVER */ /** * i40e_adminq_init_regs - Initialize AdminQ registers * @hw: pointer to the hardware structure * * This assumes the alloc_asq and alloc_arq functions have already been called **/ STATIC void i40e_adminq_init_regs(struct i40e_hw *hw) { /* set head and tail registers in our local struct */ if (i40e_is_vf(hw)) { hw->aq.asq.tail = I40E_VF_ATQT1; hw->aq.asq.head = I40E_VF_ATQH1; hw->aq.asq.len = I40E_VF_ATQLEN1; hw->aq.asq.bal = I40E_VF_ATQBAL1; hw->aq.asq.bah = I40E_VF_ATQBAH1; hw->aq.arq.tail = I40E_VF_ARQT1; hw->aq.arq.head = I40E_VF_ARQH1; hw->aq.arq.len = I40E_VF_ARQLEN1; hw->aq.arq.bal = I40E_VF_ARQBAL1; hw->aq.arq.bah = I40E_VF_ARQBAH1; } else { hw->aq.asq.tail = I40E_PF_ATQT; hw->aq.asq.head = I40E_PF_ATQH; hw->aq.asq.len = I40E_PF_ATQLEN; hw->aq.asq.bal = I40E_PF_ATQBAL; hw->aq.asq.bah = I40E_PF_ATQBAH; hw->aq.arq.tail = I40E_PF_ARQT; hw->aq.arq.head = I40E_PF_ARQH; hw->aq.arq.len = I40E_PF_ARQLEN; hw->aq.arq.bal = I40E_PF_ARQBAL; hw->aq.arq.bah = I40E_PF_ARQBAH; } } /** * i40e_alloc_adminq_asq_ring - Allocate Admin Queue send rings * @hw: pointer to the hardware structure **/ enum i40e_status_code i40e_alloc_adminq_asq_ring(struct i40e_hw *hw) { enum i40e_status_code ret_code; ret_code = i40e_allocate_dma_mem(hw, &hw->aq.asq.desc_buf, i40e_mem_atq_ring, (hw->aq.num_asq_entries * sizeof(struct i40e_aq_desc)), I40E_ADMINQ_DESC_ALIGNMENT); if (ret_code) return ret_code; ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.cmd_buf, (hw->aq.num_asq_entries * sizeof(struct i40e_asq_cmd_details))); if (ret_code) { i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf); return ret_code; } return ret_code; } /** * i40e_alloc_adminq_arq_ring - Allocate Admin Queue receive rings * @hw: pointer to the hardware structure **/ enum i40e_status_code i40e_alloc_adminq_arq_ring(struct i40e_hw *hw) { enum i40e_status_code ret_code; ret_code = i40e_allocate_dma_mem(hw, &hw->aq.arq.desc_buf, i40e_mem_arq_ring, (hw->aq.num_arq_entries * sizeof(struct i40e_aq_desc)), I40E_ADMINQ_DESC_ALIGNMENT); return ret_code; } /** * i40e_free_adminq_asq - Free Admin Queue send rings * @hw: pointer to the hardware structure * * This assumes the posted send buffers have already been cleaned * and de-allocated **/ void i40e_free_adminq_asq(struct i40e_hw *hw) { i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf); } /** * i40e_free_adminq_arq - Free Admin Queue receive rings * @hw: pointer to the hardware structure * * This assumes the posted receive buffers have already been cleaned * and de-allocated **/ void i40e_free_adminq_arq(struct i40e_hw *hw) { i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf); } /** * i40e_alloc_arq_bufs - Allocate pre-posted buffers for the receive queue * @hw: pointer to the hardware structure **/ STATIC enum i40e_status_code i40e_alloc_arq_bufs(struct i40e_hw *hw) { enum i40e_status_code ret_code; struct i40e_aq_desc *desc; struct i40e_dma_mem *bi; int i; /* We'll be allocating the buffer info memory first, then we can * allocate the mapped buffers for the event processing */ /* buffer_info structures do not need alignment */ ret_code = i40e_allocate_virt_mem(hw, &hw->aq.arq.dma_head, (hw->aq.num_arq_entries * sizeof(struct i40e_dma_mem))); if (ret_code) goto alloc_arq_bufs; hw->aq.arq.r.arq_bi = (struct i40e_dma_mem *)hw->aq.arq.dma_head.va; /* allocate the mapped buffers */ for (i = 0; i < hw->aq.num_arq_entries; i++) { bi = &hw->aq.arq.r.arq_bi[i]; ret_code = i40e_allocate_dma_mem(hw, bi, i40e_mem_arq_buf, hw->aq.arq_buf_size, I40E_ADMINQ_DESC_ALIGNMENT); if (ret_code) goto unwind_alloc_arq_bufs; /* now configure the descriptors for use */ desc = I40E_ADMINQ_DESC(hw->aq.arq, i); desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_BUF); if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF) desc->flags |= CPU_TO_LE16(I40E_AQ_FLAG_LB); desc->opcode = 0; /* This is in accordance with Admin queue design, there is no * register for buffer size configuration */ desc->datalen = CPU_TO_LE16((u16)bi->size); desc->retval = 0; desc->cookie_high = 0; desc->cookie_low = 0; desc->params.external.addr_high = CPU_TO_LE32(I40E_HI_DWORD(bi->pa)); desc->params.external.addr_low = CPU_TO_LE32(I40E_LO_DWORD(bi->pa)); desc->params.external.param0 = 0; desc->params.external.param1 = 0; } alloc_arq_bufs: return ret_code; unwind_alloc_arq_bufs: /* don't try to free the one that failed... */ i--; for (; i >= 0; i--) i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]); i40e_free_virt_mem(hw, &hw->aq.arq.dma_head); return ret_code; } /** * i40e_alloc_asq_bufs - Allocate empty buffer structs for the send queue * @hw: pointer to the hardware structure **/ STATIC enum i40e_status_code i40e_alloc_asq_bufs(struct i40e_hw *hw) { enum i40e_status_code ret_code; struct i40e_dma_mem *bi; int i; /* No mapped memory needed yet, just the buffer info structures */ ret_code = i40e_allocate_virt_mem(hw, &hw->aq.asq.dma_head, (hw->aq.num_asq_entries * sizeof(struct i40e_dma_mem))); if (ret_code) goto alloc_asq_bufs; hw->aq.asq.r.asq_bi = (struct i40e_dma_mem *)hw->aq.asq.dma_head.va; /* allocate the mapped buffers */ for (i = 0; i < hw->aq.num_asq_entries; i++) { bi = &hw->aq.asq.r.asq_bi[i]; ret_code = i40e_allocate_dma_mem(hw, bi, i40e_mem_asq_buf, hw->aq.asq_buf_size, I40E_ADMINQ_DESC_ALIGNMENT); if (ret_code) goto unwind_alloc_asq_bufs; } alloc_asq_bufs: return ret_code; unwind_alloc_asq_bufs: /* don't try to free the one that failed... */ i--; for (; i >= 0; i--) i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]); i40e_free_virt_mem(hw, &hw->aq.asq.dma_head); return ret_code; } /** * i40e_free_arq_bufs - Free receive queue buffer info elements * @hw: pointer to the hardware structure **/ STATIC void i40e_free_arq_bufs(struct i40e_hw *hw) { int i; /* free descriptors */ for (i = 0; i < hw->aq.num_arq_entries; i++) i40e_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]); /* free the descriptor memory */ i40e_free_dma_mem(hw, &hw->aq.arq.desc_buf); /* free the dma header */ i40e_free_virt_mem(hw, &hw->aq.arq.dma_head); } /** * i40e_free_asq_bufs - Free send queue buffer info elements * @hw: pointer to the hardware structure **/ STATIC void i40e_free_asq_bufs(struct i40e_hw *hw) { int i; /* only unmap if the address is non-NULL */ for (i = 0; i < hw->aq.num_asq_entries; i++) if (hw->aq.asq.r.asq_bi[i].pa) i40e_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]); /* free the buffer info list */ i40e_free_virt_mem(hw, &hw->aq.asq.cmd_buf); /* free the descriptor memory */ i40e_free_dma_mem(hw, &hw->aq.asq.desc_buf); /* free the dma header */ i40e_free_virt_mem(hw, &hw->aq.asq.dma_head); } /** * i40e_config_asq_regs - configure ASQ registers * @hw: pointer to the hardware structure * * Configure base address and length registers for the transmit queue **/ STATIC enum i40e_status_code i40e_config_asq_regs(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; u32 reg = 0; /* Clear Head and Tail */ wr32(hw, hw->aq.asq.head, 0); wr32(hw, hw->aq.asq.tail, 0); /* set starting point */ wr32(hw, hw->aq.asq.len, (hw->aq.num_asq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK)); wr32(hw, hw->aq.asq.bal, I40E_LO_DWORD(hw->aq.asq.desc_buf.pa)); wr32(hw, hw->aq.asq.bah, I40E_HI_DWORD(hw->aq.asq.desc_buf.pa)); /* Check one register to verify that config was applied */ reg = rd32(hw, hw->aq.asq.bal); if (reg != I40E_LO_DWORD(hw->aq.asq.desc_buf.pa)) ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; return ret_code; } /** * i40e_config_arq_regs - ARQ register configuration * @hw: pointer to the hardware structure * * Configure base address and length registers for the receive (event queue) **/ STATIC enum i40e_status_code i40e_config_arq_regs(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; u32 reg = 0; /* Clear Head and Tail */ wr32(hw, hw->aq.arq.head, 0); wr32(hw, hw->aq.arq.tail, 0); /* set starting point */ wr32(hw, hw->aq.arq.len, (hw->aq.num_arq_entries | I40E_PF_ARQLEN_ARQENABLE_MASK)); wr32(hw, hw->aq.arq.bal, I40E_LO_DWORD(hw->aq.arq.desc_buf.pa)); wr32(hw, hw->aq.arq.bah, I40E_HI_DWORD(hw->aq.arq.desc_buf.pa)); /* Update tail in the HW to post pre-allocated buffers */ wr32(hw, hw->aq.arq.tail, hw->aq.num_arq_entries - 1); /* Check one register to verify that config was applied */ reg = rd32(hw, hw->aq.arq.bal); if (reg != I40E_LO_DWORD(hw->aq.arq.desc_buf.pa)) ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; return ret_code; } /** * i40e_init_asq - main initialization routine for ASQ * @hw: pointer to the hardware structure * * This is the main initialization routine for the Admin Send Queue * Prior to calling this function, drivers *MUST* set the following fields * in the hw->aq structure: * - hw->aq.num_asq_entries * - hw->aq.arq_buf_size * * Do *NOT* hold the lock when calling this as the memory allocation routines * called are not going to be atomic context safe **/ enum i40e_status_code i40e_init_asq(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; if (hw->aq.asq.count > 0) { /* queue already initialized */ ret_code = I40E_ERR_NOT_READY; goto init_adminq_exit; } /* verify input for valid configuration */ if ((hw->aq.num_asq_entries == 0) || (hw->aq.asq_buf_size == 0)) { ret_code = I40E_ERR_CONFIG; goto init_adminq_exit; } hw->aq.asq.next_to_use = 0; hw->aq.asq.next_to_clean = 0; hw->aq.asq.count = hw->aq.num_asq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_asq_ring(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_exit; /* allocate buffers in the rings */ ret_code = i40e_alloc_asq_bufs(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_free_rings; /* initialize base registers */ ret_code = i40e_config_asq_regs(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_free_rings; /* success! */ goto init_adminq_exit; init_adminq_free_rings: i40e_free_adminq_asq(hw); init_adminq_exit: return ret_code; } /** * i40e_init_arq - initialize ARQ * @hw: pointer to the hardware structure * * The main initialization routine for the Admin Receive (Event) Queue. * Prior to calling this function, drivers *MUST* set the following fields * in the hw->aq structure: * - hw->aq.num_asq_entries * - hw->aq.arq_buf_size * * Do *NOT* hold the lock when calling this as the memory allocation routines * called are not going to be atomic context safe **/ enum i40e_status_code i40e_init_arq(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; if (hw->aq.arq.count > 0) { /* queue already initialized */ ret_code = I40E_ERR_NOT_READY; goto init_adminq_exit; } /* verify input for valid configuration */ if ((hw->aq.num_arq_entries == 0) || (hw->aq.arq_buf_size == 0)) { ret_code = I40E_ERR_CONFIG; goto init_adminq_exit; } hw->aq.arq.next_to_use = 0; hw->aq.arq.next_to_clean = 0; hw->aq.arq.count = hw->aq.num_arq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_arq_ring(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_exit; /* allocate buffers in the rings */ ret_code = i40e_alloc_arq_bufs(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_free_rings; /* initialize base registers */ ret_code = i40e_config_arq_regs(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_free_rings; /* success! */ goto init_adminq_exit; init_adminq_free_rings: i40e_free_adminq_arq(hw); init_adminq_exit: return ret_code; } /** * i40e_shutdown_asq - shutdown the ASQ * @hw: pointer to the hardware structure * * The main shutdown routine for the Admin Send Queue **/ enum i40e_status_code i40e_shutdown_asq(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; if (hw->aq.asq.count == 0) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.asq.head, 0); wr32(hw, hw->aq.asq.tail, 0); wr32(hw, hw->aq.asq.len, 0); wr32(hw, hw->aq.asq.bal, 0); wr32(hw, hw->aq.asq.bah, 0); /* make sure spinlock is available */ i40e_acquire_spinlock(&hw->aq.asq_spinlock); hw->aq.asq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_asq_bufs(hw); i40e_release_spinlock(&hw->aq.asq_spinlock); return ret_code; } /** * i40e_shutdown_arq - shutdown ARQ * @hw: pointer to the hardware structure * * The main shutdown routine for the Admin Receive Queue **/ enum i40e_status_code i40e_shutdown_arq(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; if (hw->aq.arq.count == 0) return I40E_ERR_NOT_READY; /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.arq.head, 0); wr32(hw, hw->aq.arq.tail, 0); wr32(hw, hw->aq.arq.len, 0); wr32(hw, hw->aq.arq.bal, 0); wr32(hw, hw->aq.arq.bah, 0); /* make sure spinlock is available */ i40e_acquire_spinlock(&hw->aq.arq_spinlock); hw->aq.arq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_arq_bufs(hw); i40e_release_spinlock(&hw->aq.arq_spinlock); return ret_code; } /** * i40e_init_adminq - main initialization routine for Admin Queue * @hw: pointer to the hardware structure * * Prior to calling this function, drivers *MUST* set the following fields * in the hw->aq structure: * - hw->aq.num_asq_entries * - hw->aq.num_arq_entries * - hw->aq.arq_buf_size * - hw->aq.asq_buf_size **/ enum i40e_status_code i40e_init_adminq(struct i40e_hw *hw) { enum i40e_status_code ret_code; #ifdef PF_DRIVER u16 eetrack_lo, eetrack_hi; int retry = 0; #endif /* verify input for valid configuration */ if ((hw->aq.num_arq_entries == 0) || (hw->aq.num_asq_entries == 0) || (hw->aq.arq_buf_size == 0) || (hw->aq.asq_buf_size == 0)) { ret_code = I40E_ERR_CONFIG; goto init_adminq_exit; } /* initialize spin locks */ i40e_init_spinlock(&hw->aq.asq_spinlock); i40e_init_spinlock(&hw->aq.arq_spinlock); /* Set up register offsets */ i40e_adminq_init_regs(hw); /* setup ASQ command write back timeout */ hw->aq.asq_cmd_timeout = I40E_ASQ_CMD_TIMEOUT; /* allocate the ASQ */ ret_code = i40e_init_asq(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_destroy_spinlocks; /* allocate the ARQ */ ret_code = i40e_init_arq(hw); if (ret_code != I40E_SUCCESS) goto init_adminq_free_asq; #ifdef PF_DRIVER #ifdef INTEGRATED_VF /* VF has no need of firmware */ if (i40e_is_vf(hw)) goto init_adminq_exit; #endif /* There are some cases where the firmware may not be quite ready * for AdminQ operations, so we retry the AdminQ setup a few times * if we see timeouts in this first AQ call. */ do { ret_code = i40e_aq_get_firmware_version(hw, &hw->aq.fw_maj_ver, &hw->aq.fw_min_ver, &hw->aq.fw_build, &hw->aq.api_maj_ver, &hw->aq.api_min_ver, NULL); if (ret_code != I40E_ERR_ADMIN_QUEUE_TIMEOUT) break; retry++; i40e_msec_delay(100); i40e_resume_aq(hw); } while (retry < 10); if (ret_code != I40E_SUCCESS) goto init_adminq_free_arq; /* get the NVM version info */ i40e_read_nvm_word(hw, I40E_SR_NVM_DEV_STARTER_VERSION, &hw->nvm.version); i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo); i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi); hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo; if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) { ret_code = I40E_ERR_FIRMWARE_API_VERSION; goto init_adminq_free_arq; } /* pre-emptive resource lock release */ i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); hw->aq.nvm_release_on_done = false; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; ret_code = i40e_aq_set_hmc_resource_profile(hw, I40E_HMC_PROFILE_DEFAULT, 0, NULL); #endif /* PF_DRIVER */ ret_code = I40E_SUCCESS; /* success! */ goto init_adminq_exit; #ifdef PF_DRIVER init_adminq_free_arq: i40e_shutdown_arq(hw); #endif init_adminq_free_asq: i40e_shutdown_asq(hw); init_adminq_destroy_spinlocks: i40e_destroy_spinlock(&hw->aq.asq_spinlock); i40e_destroy_spinlock(&hw->aq.arq_spinlock); init_adminq_exit: return ret_code; } /** * i40e_shutdown_adminq - shutdown routine for the Admin Queue * @hw: pointer to the hardware structure **/ enum i40e_status_code i40e_shutdown_adminq(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; if (i40e_check_asq_alive(hw)) i40e_aq_queue_shutdown(hw, true); i40e_shutdown_asq(hw); i40e_shutdown_arq(hw); /* destroy the spinlocks */ i40e_destroy_spinlock(&hw->aq.asq_spinlock); i40e_destroy_spinlock(&hw->aq.arq_spinlock); return ret_code; } /** * i40e_clean_asq - cleans Admin send queue * @hw: pointer to the hardware structure * * returns the number of free desc **/ u16 i40e_clean_asq(struct i40e_hw *hw) { struct i40e_adminq_ring *asq = &(hw->aq.asq); struct i40e_asq_cmd_details *details; u16 ntc = asq->next_to_clean; struct i40e_aq_desc desc_cb; struct i40e_aq_desc *desc; desc = I40E_ADMINQ_DESC(*asq, ntc); details = I40E_ADMINQ_DETAILS(*asq, ntc); while (rd32(hw, hw->aq.asq.head) != ntc) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "%s: ntc %d head %d.\n", __FUNCTION__, ntc, rd32(hw, hw->aq.asq.head)); if (details->callback) { I40E_ADMINQ_CALLBACK cb_func = (I40E_ADMINQ_CALLBACK)details->callback; i40e_memcpy(&desc_cb, desc, sizeof(struct i40e_aq_desc), I40E_DMA_TO_DMA); cb_func(hw, &desc_cb); } i40e_memset(desc, 0, sizeof(*desc), I40E_DMA_MEM); i40e_memset(details, 0, sizeof(*details), I40E_NONDMA_MEM); ntc++; if (ntc == asq->count) ntc = 0; desc = I40E_ADMINQ_DESC(*asq, ntc); details = I40E_ADMINQ_DETAILS(*asq, ntc); } asq->next_to_clean = ntc; return I40E_DESC_UNUSED(asq); } /** * i40e_asq_done - check if FW has processed the Admin Send Queue * @hw: pointer to the hw struct * * Returns true if the firmware has processed all descriptors on the * admin send queue. Returns false if there are still requests pending. **/ bool i40e_asq_done(struct i40e_hw *hw) { /* AQ designers suggest use of head for better * timing reliability than DD bit */ return rd32(hw, hw->aq.asq.head) == hw->aq.asq.next_to_use; } /** * i40e_asq_send_command - send command to Admin Queue * @hw: pointer to the hw struct * @desc: prefilled descriptor describing the command (non DMA mem) * @buff: buffer to use for indirect commands * @buff_size: size of buffer for indirect commands * @cmd_details: pointer to command details structure * * This is the main send command driver routine for the Admin Queue send * queue. It runs the queue, cleans the queue, etc **/ enum i40e_status_code i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc, void *buff, /* can be NULL */ u16 buff_size, struct i40e_asq_cmd_details *cmd_details) { enum i40e_status_code status = I40E_SUCCESS; struct i40e_dma_mem *dma_buff = NULL; struct i40e_asq_cmd_details *details; struct i40e_aq_desc *desc_on_ring; bool cmd_completed = false; u16 retval = 0; u32 val = 0; val = rd32(hw, hw->aq.asq.head); if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: head overrun at %d\n", val); status = I40E_ERR_QUEUE_EMPTY; goto asq_send_command_exit; } if (hw->aq.asq.count == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Admin queue not initialized.\n"); status = I40E_ERR_QUEUE_EMPTY; goto asq_send_command_exit; } details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); if (cmd_details) { i40e_memcpy(details, cmd_details, sizeof(struct i40e_asq_cmd_details), I40E_NONDMA_TO_NONDMA); /* If the cmd_details are defined copy the cookie. The * CPU_TO_LE32 is not needed here because the data is ignored * by the FW, only used by the driver */ if (details->cookie) { desc->cookie_high = CPU_TO_LE32(I40E_HI_DWORD(details->cookie)); desc->cookie_low = CPU_TO_LE32(I40E_LO_DWORD(details->cookie)); } } else { i40e_memset(details, 0, sizeof(struct i40e_asq_cmd_details), I40E_NONDMA_MEM); } /* clear requested flags and then set additional flags if defined */ desc->flags &= ~CPU_TO_LE16(details->flags_dis); desc->flags |= CPU_TO_LE16(details->flags_ena); i40e_acquire_spinlock(&hw->aq.asq_spinlock); if (buff_size > hw->aq.asq_buf_size) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Invalid buffer size: %d.\n", buff_size); status = I40E_ERR_INVALID_SIZE; goto asq_send_command_error; } if (details->postpone && !details->async) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Async flag not set along with postpone flag"); status = I40E_ERR_PARAM; goto asq_send_command_error; } /* call clean and check queue available function to reclaim the * descriptors that were processed by FW, the function returns the * number of desc available */ /* the clean function called here could be called in a separate thread * in case of asynchronous completions */ if (i40e_clean_asq(hw) == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Error queue is full.\n"); status = I40E_ERR_ADMIN_QUEUE_FULL; goto asq_send_command_error; } /* initialize the temp desc pointer with the right desc */ desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use); /* if the desc is available copy the temp desc to the right place */ i40e_memcpy(desc_on_ring, desc, sizeof(struct i40e_aq_desc), I40E_NONDMA_TO_DMA); /* if buff is not NULL assume indirect command */ if (buff != NULL) { dma_buff = &(hw->aq.asq.r.asq_bi[hw->aq.asq.next_to_use]); /* copy the user buff into the respective DMA buff */ i40e_memcpy(dma_buff->va, buff, buff_size, I40E_NONDMA_TO_DMA); desc_on_ring->datalen = CPU_TO_LE16(buff_size); /* Update the address values in the desc with the pa value * for respective buffer */ desc_on_ring->params.external.addr_high = CPU_TO_LE32(I40E_HI_DWORD(dma_buff->pa)); desc_on_ring->params.external.addr_low = CPU_TO_LE32(I40E_LO_DWORD(dma_buff->pa)); } /* bump the tail */ i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer:\n"); i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc_on_ring, buff, buff_size); (hw->aq.asq.next_to_use)++; if (hw->aq.asq.next_to_use == hw->aq.asq.count) hw->aq.asq.next_to_use = 0; if (!details->postpone) wr32(hw, hw->aq.asq.tail, hw->aq.asq.next_to_use); /* if cmd_details are not defined or async flag is not set, * we need to wait for desc write back */ if (!details->async && !details->postpone) { u32 total_delay = 0; do { /* AQ designers suggest use of head for better * timing reliability than DD bit */ if (i40e_asq_done(hw)) break; /* ugh! delay while spin_lock */ i40e_msec_delay(1); total_delay++; } while (total_delay < hw->aq.asq_cmd_timeout); } /* if ready, copy the desc back to temp */ if (i40e_asq_done(hw)) { i40e_memcpy(desc, desc_on_ring, sizeof(struct i40e_aq_desc), I40E_DMA_TO_NONDMA); if (buff != NULL) i40e_memcpy(buff, dma_buff->va, buff_size, I40E_DMA_TO_NONDMA); retval = LE16_TO_CPU(desc->retval); if (retval != 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Command completed with error 0x%X.\n", retval); /* strip off FW internal code */ retval &= 0xff; } cmd_completed = true; if ((enum i40e_admin_queue_err)retval == I40E_AQ_RC_OK) status = I40E_SUCCESS; else status = I40E_ERR_ADMIN_QUEUE_ERROR; hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; } i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: desc and buffer writeback:\n"); i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size); /* update the error if time out occurred */ if ((!cmd_completed) && (!details->async && !details->postpone)) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: Writeback timeout.\n"); status = I40E_ERR_ADMIN_QUEUE_TIMEOUT; } asq_send_command_error: i40e_release_spinlock(&hw->aq.asq_spinlock); asq_send_command_exit: return status; } /** * i40e_fill_default_direct_cmd_desc - AQ descriptor helper function * @desc: pointer to the temp descriptor (non DMA mem) * @opcode: the opcode can be used to decide which flags to turn off or on * * Fill the desc with default values **/ void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc, u16 opcode) { /* zero out the desc */ i40e_memset((void *)desc, 0, sizeof(struct i40e_aq_desc), I40E_NONDMA_MEM); desc->opcode = CPU_TO_LE16(opcode); desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_SI); } /** * i40e_clean_arq_element * @hw: pointer to the hw struct * @e: event info from the receive descriptor, includes any buffers * @pending: number of events that could be left to process * * This function cleans one Admin Receive Queue element and returns * the contents through e. It can also return how many events are * left to process through 'pending' **/ enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw, struct i40e_arq_event_info *e, u16 *pending) { enum i40e_status_code ret_code = I40E_SUCCESS; u16 ntc = hw->aq.arq.next_to_clean; struct i40e_aq_desc *desc; struct i40e_dma_mem *bi; u16 desc_idx; u16 datalen; u16 flags; u16 ntu; /* take the lock before we start messing with the ring */ i40e_acquire_spinlock(&hw->aq.arq_spinlock); /* set next_to_use to head */ ntu = (rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK); if (ntu == ntc) { /* nothing to do - shouldn't need to update ring's values */ ret_code = I40E_ERR_ADMIN_QUEUE_NO_WORK; goto clean_arq_element_out; } /* now clean the next descriptor */ desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc); desc_idx = ntc; flags = LE16_TO_CPU(desc->flags); if (flags & I40E_AQ_FLAG_ERR) { ret_code = I40E_ERR_ADMIN_QUEUE_ERROR; hw->aq.arq_last_status = (enum i40e_admin_queue_err)LE16_TO_CPU(desc->retval); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: Event received with error 0x%X.\n", hw->aq.arq_last_status); } i40e_memcpy(&e->desc, desc, sizeof(struct i40e_aq_desc), I40E_DMA_TO_NONDMA); datalen = LE16_TO_CPU(desc->datalen); e->msg_len = min(datalen, e->buf_len); if (e->msg_buf != NULL && (e->msg_len != 0)) i40e_memcpy(e->msg_buf, hw->aq.arq.r.arq_bi[desc_idx].va, e->msg_len, I40E_DMA_TO_NONDMA); i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQRX: desc and buffer:\n"); i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, e->msg_buf, hw->aq.arq_buf_size); /* Restore the original datalen and buffer address in the desc, * FW updates datalen to indicate the event message * size */ bi = &hw->aq.arq.r.arq_bi[ntc]; i40e_memset((void *)desc, 0, sizeof(struct i40e_aq_desc), I40E_DMA_MEM); desc->flags = CPU_TO_LE16(I40E_AQ_FLAG_BUF); if (hw->aq.arq_buf_size > I40E_AQ_LARGE_BUF) desc->flags |= CPU_TO_LE16(I40E_AQ_FLAG_LB); desc->datalen = CPU_TO_LE16((u16)bi->size); desc->params.external.addr_high = CPU_TO_LE32(I40E_HI_DWORD(bi->pa)); desc->params.external.addr_low = CPU_TO_LE32(I40E_LO_DWORD(bi->pa)); /* set tail = the last cleaned desc index. */ wr32(hw, hw->aq.arq.tail, ntc); /* ntc is updated to tail + 1 */ ntc++; if (ntc == hw->aq.num_arq_entries) ntc = 0; hw->aq.arq.next_to_clean = ntc; hw->aq.arq.next_to_use = ntu; clean_arq_element_out: /* Set pending if needed, unlock and return */ if (pending != NULL) *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc); i40e_release_spinlock(&hw->aq.arq_spinlock); #ifdef PF_DRIVER if (i40e_is_nvm_update_op(&e->desc)) { if (hw->aq.nvm_release_on_done) { i40e_release_nvm(hw); hw->aq.nvm_release_on_done = false; } } #endif return ret_code; } void i40e_resume_aq(struct i40e_hw *hw) { /* Registers are reset after PF reset */ hw->aq.asq.next_to_use = 0; hw->aq.asq.next_to_clean = 0; #if (I40E_VF_ATQLEN_ATQENABLE_MASK != I40E_PF_ATQLEN_ATQENABLE_MASK) #error I40E_VF_ATQLEN_ATQENABLE_MASK != I40E_PF_ATQLEN_ATQENABLE_MASK #endif i40e_config_asq_regs(hw); hw->aq.arq.next_to_use = 0; hw->aq.arq.next_to_clean = 0; i40e_config_arq_regs(hw); } ================================================ FILE: drivers/net/i40e/base/i40e_adminq.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_ADMINQ_H_ #define _I40E_ADMINQ_H_ #include "i40e_osdep.h" #include "i40e_status.h" #include "i40e_adminq_cmd.h" #define I40E_ADMINQ_DESC(R, i) \ (&(((struct i40e_aq_desc *)((R).desc_buf.va))[i])) #define I40E_ADMINQ_DESC_ALIGNMENT 4096 struct i40e_adminq_ring { struct i40e_virt_mem dma_head; /* space for dma structures */ struct i40e_dma_mem desc_buf; /* descriptor ring memory */ struct i40e_virt_mem cmd_buf; /* command buffer memory */ union { struct i40e_dma_mem *asq_bi; struct i40e_dma_mem *arq_bi; } r; u16 count; /* Number of descriptors */ u16 rx_buf_len; /* Admin Receive Queue buffer length */ /* used for interrupt processing */ u16 next_to_use; u16 next_to_clean; /* used for queue tracking */ u32 head; u32 tail; u32 len; u32 bah; u32 bal; }; /* ASQ transaction details */ struct i40e_asq_cmd_details { void *callback; /* cast from type I40E_ADMINQ_CALLBACK */ u64 cookie; u16 flags_ena; u16 flags_dis; bool async; bool postpone; }; #define I40E_ADMINQ_DETAILS(R, i) \ (&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i])) /* ARQ event information */ struct i40e_arq_event_info { struct i40e_aq_desc desc; u16 msg_len; u16 buf_len; u8 *msg_buf; }; /* Admin Queue information */ struct i40e_adminq_info { struct i40e_adminq_ring arq; /* receive queue */ struct i40e_adminq_ring asq; /* send queue */ u32 asq_cmd_timeout; /* send queue cmd write back timeout*/ u16 num_arq_entries; /* receive queue depth */ u16 num_asq_entries; /* send queue depth */ u16 arq_buf_size; /* receive queue buffer size */ u16 asq_buf_size; /* send queue buffer size */ u16 fw_maj_ver; /* firmware major version */ u16 fw_min_ver; /* firmware minor version */ u32 fw_build; /* firmware build number */ u16 api_maj_ver; /* api major version */ u16 api_min_ver; /* api minor version */ bool nvm_release_on_done; struct i40e_spinlock asq_spinlock; /* Send queue spinlock */ struct i40e_spinlock arq_spinlock; /* Receive queue spinlock */ /* last status values on send and receive queues */ enum i40e_admin_queue_err asq_last_status; enum i40e_admin_queue_err arq_last_status; }; /** * i40e_aq_rc_to_posix - convert errors to user-land codes * aq_rc: AdminQ error code to convert **/ STATIC inline int i40e_aq_rc_to_posix(int aq_ret, u16 aq_rc) { int aq_to_posix[] = { 0, /* I40E_AQ_RC_OK */ -EPERM, /* I40E_AQ_RC_EPERM */ -ENOENT, /* I40E_AQ_RC_ENOENT */ -ESRCH, /* I40E_AQ_RC_ESRCH */ -EINTR, /* I40E_AQ_RC_EINTR */ -EIO, /* I40E_AQ_RC_EIO */ -ENXIO, /* I40E_AQ_RC_ENXIO */ -E2BIG, /* I40E_AQ_RC_E2BIG */ -EAGAIN, /* I40E_AQ_RC_EAGAIN */ -ENOMEM, /* I40E_AQ_RC_ENOMEM */ -EACCES, /* I40E_AQ_RC_EACCES */ -EFAULT, /* I40E_AQ_RC_EFAULT */ -EBUSY, /* I40E_AQ_RC_EBUSY */ -EEXIST, /* I40E_AQ_RC_EEXIST */ -EINVAL, /* I40E_AQ_RC_EINVAL */ -ENOTTY, /* I40E_AQ_RC_ENOTTY */ -ENOSPC, /* I40E_AQ_RC_ENOSPC */ -ENOSYS, /* I40E_AQ_RC_ENOSYS */ -ERANGE, /* I40E_AQ_RC_ERANGE */ -EPIPE, /* I40E_AQ_RC_EFLUSHED */ -ESPIPE, /* I40E_AQ_RC_BAD_ADDR */ -EROFS, /* I40E_AQ_RC_EMODE */ -EFBIG, /* I40E_AQ_RC_EFBIG */ }; /* aq_rc is invalid if AQ timed out */ if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) return -EAGAIN; if (aq_rc >= (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0]))) return -ERANGE; return aq_to_posix[aq_rc]; } /* general information */ #define I40E_AQ_LARGE_BUF 512 #define I40E_ASQ_CMD_TIMEOUT 250 /* msecs */ void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc, u16 opcode); #endif /* _I40E_ADMINQ_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_adminq_cmd.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_ADMINQ_CMD_H_ #define _I40E_ADMINQ_CMD_H_ /* This header file defines the i40e Admin Queue commands and is shared between * i40e Firmware and Software. * * This file needs to comply with the Linux Kernel coding style. */ #define I40E_FW_API_VERSION_MAJOR 0x0001 #define I40E_FW_API_VERSION_MINOR 0x0002 struct i40e_aq_desc { __le16 flags; __le16 opcode; __le16 datalen; __le16 retval; __le32 cookie_high; __le32 cookie_low; union { struct { __le32 param0; __le32 param1; __le32 param2; __le32 param3; } internal; struct { __le32 param0; __le32 param1; __le32 addr_high; __le32 addr_low; } external; u8 raw[16]; } params; }; /* Flags sub-structure * |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 | * |DD |CMP|ERR|VFE| * * RESERVED * * |LB |RD |VFC|BUF|SI |EI |FE | */ /* command flags and offsets*/ #define I40E_AQ_FLAG_DD_SHIFT 0 #define I40E_AQ_FLAG_CMP_SHIFT 1 #define I40E_AQ_FLAG_ERR_SHIFT 2 #define I40E_AQ_FLAG_VFE_SHIFT 3 #define I40E_AQ_FLAG_LB_SHIFT 9 #define I40E_AQ_FLAG_RD_SHIFT 10 #define I40E_AQ_FLAG_VFC_SHIFT 11 #define I40E_AQ_FLAG_BUF_SHIFT 12 #define I40E_AQ_FLAG_SI_SHIFT 13 #define I40E_AQ_FLAG_EI_SHIFT 14 #define I40E_AQ_FLAG_FE_SHIFT 15 #define I40E_AQ_FLAG_DD (1 << I40E_AQ_FLAG_DD_SHIFT) /* 0x1 */ #define I40E_AQ_FLAG_CMP (1 << I40E_AQ_FLAG_CMP_SHIFT) /* 0x2 */ #define I40E_AQ_FLAG_ERR (1 << I40E_AQ_FLAG_ERR_SHIFT) /* 0x4 */ #define I40E_AQ_FLAG_VFE (1 << I40E_AQ_FLAG_VFE_SHIFT) /* 0x8 */ #define I40E_AQ_FLAG_LB (1 << I40E_AQ_FLAG_LB_SHIFT) /* 0x200 */ #define I40E_AQ_FLAG_RD (1 << I40E_AQ_FLAG_RD_SHIFT) /* 0x400 */ #define I40E_AQ_FLAG_VFC (1 << I40E_AQ_FLAG_VFC_SHIFT) /* 0x800 */ #define I40E_AQ_FLAG_BUF (1 << I40E_AQ_FLAG_BUF_SHIFT) /* 0x1000 */ #define I40E_AQ_FLAG_SI (1 << I40E_AQ_FLAG_SI_SHIFT) /* 0x2000 */ #define I40E_AQ_FLAG_EI (1 << I40E_AQ_FLAG_EI_SHIFT) /* 0x4000 */ #define I40E_AQ_FLAG_FE (1 << I40E_AQ_FLAG_FE_SHIFT) /* 0x8000 */ /* error codes */ enum i40e_admin_queue_err { I40E_AQ_RC_OK = 0, /* success */ I40E_AQ_RC_EPERM = 1, /* Operation not permitted */ I40E_AQ_RC_ENOENT = 2, /* No such element */ I40E_AQ_RC_ESRCH = 3, /* Bad opcode */ I40E_AQ_RC_EINTR = 4, /* operation interrupted */ I40E_AQ_RC_EIO = 5, /* I/O error */ I40E_AQ_RC_ENXIO = 6, /* No such resource */ I40E_AQ_RC_E2BIG = 7, /* Arg too long */ I40E_AQ_RC_EAGAIN = 8, /* Try again */ I40E_AQ_RC_ENOMEM = 9, /* Out of memory */ I40E_AQ_RC_EACCES = 10, /* Permission denied */ I40E_AQ_RC_EFAULT = 11, /* Bad address */ I40E_AQ_RC_EBUSY = 12, /* Device or resource busy */ I40E_AQ_RC_EEXIST = 13, /* object already exists */ I40E_AQ_RC_EINVAL = 14, /* Invalid argument */ I40E_AQ_RC_ENOTTY = 15, /* Not a typewriter */ I40E_AQ_RC_ENOSPC = 16, /* No space left or alloc failure */ I40E_AQ_RC_ENOSYS = 17, /* Function not implemented */ I40E_AQ_RC_ERANGE = 18, /* Parameter out of range */ I40E_AQ_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */ I40E_AQ_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */ I40E_AQ_RC_EMODE = 21, /* Op not allowed in current dev mode */ I40E_AQ_RC_EFBIG = 22, /* File too large */ }; /* Admin Queue command opcodes */ enum i40e_admin_queue_opc { /* aq commands */ i40e_aqc_opc_get_version = 0x0001, i40e_aqc_opc_driver_version = 0x0002, i40e_aqc_opc_queue_shutdown = 0x0003, i40e_aqc_opc_set_pf_context = 0x0004, /* resource ownership */ i40e_aqc_opc_request_resource = 0x0008, i40e_aqc_opc_release_resource = 0x0009, i40e_aqc_opc_list_func_capabilities = 0x000A, i40e_aqc_opc_list_dev_capabilities = 0x000B, i40e_aqc_opc_set_cppm_configuration = 0x0103, i40e_aqc_opc_set_arp_proxy_entry = 0x0104, i40e_aqc_opc_set_ns_proxy_entry = 0x0105, /* LAA */ i40e_aqc_opc_mng_laa = 0x0106, /* AQ obsolete */ i40e_aqc_opc_mac_address_read = 0x0107, i40e_aqc_opc_mac_address_write = 0x0108, /* PXE */ i40e_aqc_opc_clear_pxe_mode = 0x0110, /* internal switch commands */ i40e_aqc_opc_get_switch_config = 0x0200, i40e_aqc_opc_add_statistics = 0x0201, i40e_aqc_opc_remove_statistics = 0x0202, i40e_aqc_opc_set_port_parameters = 0x0203, i40e_aqc_opc_get_switch_resource_alloc = 0x0204, i40e_aqc_opc_add_vsi = 0x0210, i40e_aqc_opc_update_vsi_parameters = 0x0211, i40e_aqc_opc_get_vsi_parameters = 0x0212, i40e_aqc_opc_add_pv = 0x0220, i40e_aqc_opc_update_pv_parameters = 0x0221, i40e_aqc_opc_get_pv_parameters = 0x0222, i40e_aqc_opc_add_veb = 0x0230, i40e_aqc_opc_update_veb_parameters = 0x0231, i40e_aqc_opc_get_veb_parameters = 0x0232, i40e_aqc_opc_delete_element = 0x0243, i40e_aqc_opc_add_macvlan = 0x0250, i40e_aqc_opc_remove_macvlan = 0x0251, i40e_aqc_opc_add_vlan = 0x0252, i40e_aqc_opc_remove_vlan = 0x0253, i40e_aqc_opc_set_vsi_promiscuous_modes = 0x0254, i40e_aqc_opc_add_tag = 0x0255, i40e_aqc_opc_remove_tag = 0x0256, i40e_aqc_opc_add_multicast_etag = 0x0257, i40e_aqc_opc_remove_multicast_etag = 0x0258, i40e_aqc_opc_update_tag = 0x0259, i40e_aqc_opc_add_control_packet_filter = 0x025A, i40e_aqc_opc_remove_control_packet_filter = 0x025B, i40e_aqc_opc_add_cloud_filters = 0x025C, i40e_aqc_opc_remove_cloud_filters = 0x025D, i40e_aqc_opc_add_mirror_rule = 0x0260, i40e_aqc_opc_delete_mirror_rule = 0x0261, /* DCB commands */ i40e_aqc_opc_dcb_ignore_pfc = 0x0301, i40e_aqc_opc_dcb_updated = 0x0302, /* TX scheduler */ i40e_aqc_opc_configure_vsi_bw_limit = 0x0400, i40e_aqc_opc_configure_vsi_ets_sla_bw_limit = 0x0406, i40e_aqc_opc_configure_vsi_tc_bw = 0x0407, i40e_aqc_opc_query_vsi_bw_config = 0x0408, i40e_aqc_opc_query_vsi_ets_sla_config = 0x040A, i40e_aqc_opc_configure_switching_comp_bw_limit = 0x0410, i40e_aqc_opc_enable_switching_comp_ets = 0x0413, i40e_aqc_opc_modify_switching_comp_ets = 0x0414, i40e_aqc_opc_disable_switching_comp_ets = 0x0415, i40e_aqc_opc_configure_switching_comp_ets_bw_limit = 0x0416, i40e_aqc_opc_configure_switching_comp_bw_config = 0x0417, i40e_aqc_opc_query_switching_comp_ets_config = 0x0418, i40e_aqc_opc_query_port_ets_config = 0x0419, i40e_aqc_opc_query_switching_comp_bw_config = 0x041A, i40e_aqc_opc_suspend_port_tx = 0x041B, i40e_aqc_opc_resume_port_tx = 0x041C, i40e_aqc_opc_configure_partition_bw = 0x041D, /* hmc */ i40e_aqc_opc_query_hmc_resource_profile = 0x0500, i40e_aqc_opc_set_hmc_resource_profile = 0x0501, /* phy commands*/ i40e_aqc_opc_get_phy_abilities = 0x0600, i40e_aqc_opc_set_phy_config = 0x0601, i40e_aqc_opc_set_mac_config = 0x0603, i40e_aqc_opc_set_link_restart_an = 0x0605, i40e_aqc_opc_get_link_status = 0x0607, i40e_aqc_opc_set_phy_int_mask = 0x0613, i40e_aqc_opc_get_local_advt_reg = 0x0614, i40e_aqc_opc_set_local_advt_reg = 0x0615, i40e_aqc_opc_get_partner_advt = 0x0616, i40e_aqc_opc_set_lb_modes = 0x0618, i40e_aqc_opc_get_phy_wol_caps = 0x0621, i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_upload_ext_phy_fm = 0x0625, /* NVM commands */ i40e_aqc_opc_nvm_read = 0x0701, i40e_aqc_opc_nvm_erase = 0x0702, i40e_aqc_opc_nvm_update = 0x0703, i40e_aqc_opc_nvm_config_read = 0x0704, i40e_aqc_opc_nvm_config_write = 0x0705, /* virtualization commands */ i40e_aqc_opc_send_msg_to_pf = 0x0801, i40e_aqc_opc_send_msg_to_vf = 0x0802, i40e_aqc_opc_send_msg_to_peer = 0x0803, /* alternate structure */ i40e_aqc_opc_alternate_write = 0x0900, i40e_aqc_opc_alternate_write_indirect = 0x0901, i40e_aqc_opc_alternate_read = 0x0902, i40e_aqc_opc_alternate_read_indirect = 0x0903, i40e_aqc_opc_alternate_write_done = 0x0904, i40e_aqc_opc_alternate_set_mode = 0x0905, i40e_aqc_opc_alternate_clear_port = 0x0906, /* LLDP commands */ i40e_aqc_opc_lldp_get_mib = 0x0A00, i40e_aqc_opc_lldp_update_mib = 0x0A01, i40e_aqc_opc_lldp_add_tlv = 0x0A02, i40e_aqc_opc_lldp_update_tlv = 0x0A03, i40e_aqc_opc_lldp_delete_tlv = 0x0A04, i40e_aqc_opc_lldp_stop = 0x0A05, i40e_aqc_opc_lldp_start = 0x0A06, i40e_aqc_opc_get_cee_dcb_cfg = 0x0A07, i40e_aqc_opc_lldp_set_local_mib = 0x0A08, i40e_aqc_opc_lldp_stop_start_spec_agent = 0x0A09, /* Tunnel commands */ i40e_aqc_opc_add_udp_tunnel = 0x0B00, i40e_aqc_opc_del_udp_tunnel = 0x0B01, i40e_aqc_opc_tunnel_key_structure = 0x0B10, /* Async Events */ i40e_aqc_opc_event_lan_overflow = 0x1001, /* OEM commands */ i40e_aqc_opc_oem_parameter_change = 0xFE00, i40e_aqc_opc_oem_device_status_change = 0xFE01, i40e_aqc_opc_oem_ocsd_initialize = 0xFE02, i40e_aqc_opc_oem_ocbb_initialize = 0xFE03, /* debug commands */ i40e_aqc_opc_debug_get_deviceid = 0xFF00, i40e_aqc_opc_debug_set_mode = 0xFF01, i40e_aqc_opc_debug_read_reg = 0xFF03, i40e_aqc_opc_debug_write_reg = 0xFF04, i40e_aqc_opc_debug_modify_reg = 0xFF07, i40e_aqc_opc_debug_dump_internals = 0xFF08, }; /* command structures and indirect data structures */ /* Structure naming conventions: * - no suffix for direct command descriptor structures * - _data for indirect sent data * - _resp for indirect return data (data which is both will use _data) * - _completion for direct return data * - _element_ for repeated elements (may also be _data or _resp) * * Command structures are expected to overlay the params.raw member of the basic * descriptor, and as such cannot exceed 16 bytes in length. */ /* This macro is used to generate a compilation error if a structure * is not exactly the correct length. It gives a divide by zero error if the * structure is not of the correct size, otherwise it creates an enum that is * never used. */ #define I40E_CHECK_STRUCT_LEN(n, X) enum i40e_static_assert_enum_##X \ { i40e_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) } /* This macro is used extensively to ensure that command structures are 16 * bytes in length as they have to map to the raw array of that size. */ #define I40E_CHECK_CMD_LENGTH(X) I40E_CHECK_STRUCT_LEN(16, X) /* internal (0x00XX) commands */ /* Get version (direct 0x0001) */ struct i40e_aqc_get_version { __le32 rom_ver; __le32 fw_build; __le16 fw_major; __le16 fw_minor; __le16 api_major; __le16 api_minor; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_version); /* Send driver version (indirect 0x0002) */ struct i40e_aqc_driver_version { u8 driver_major_ver; u8 driver_minor_ver; u8 driver_build_ver; u8 driver_subbuild_ver; u8 reserved[4]; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_driver_version); /* Queue Shutdown (direct 0x0003) */ struct i40e_aqc_queue_shutdown { __le32 driver_unloading; #define I40E_AQ_DRIVER_UNLOADING 0x1 u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_queue_shutdown); /* Set PF context (0x0004, direct) */ struct i40e_aqc_set_pf_context { u8 pf_id; u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_pf_context); /* Request resource ownership (direct 0x0008) * Release resource ownership (direct 0x0009) */ #define I40E_AQ_RESOURCE_NVM 1 #define I40E_AQ_RESOURCE_SDP 2 #define I40E_AQ_RESOURCE_ACCESS_READ 1 #define I40E_AQ_RESOURCE_ACCESS_WRITE 2 #define I40E_AQ_RESOURCE_NVM_READ_TIMEOUT 3000 #define I40E_AQ_RESOURCE_NVM_WRITE_TIMEOUT 180000 struct i40e_aqc_request_resource { __le16 resource_id; __le16 access_type; __le32 timeout; __le32 resource_number; u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_request_resource); /* Get function capabilities (indirect 0x000A) * Get device capabilities (indirect 0x000B) */ struct i40e_aqc_list_capabilites { u8 command_flags; #define I40E_AQ_LIST_CAP_PF_INDEX_EN 1 u8 pf_index; u8 reserved[2]; __le32 count; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_list_capabilites); struct i40e_aqc_list_capabilities_element_resp { __le16 id; u8 major_rev; u8 minor_rev; __le32 number; __le32 logical_id; __le32 phys_id; u8 reserved[16]; }; /* list of caps */ #define I40E_AQ_CAP_ID_SWITCH_MODE 0x0001 #define I40E_AQ_CAP_ID_MNG_MODE 0x0002 #define I40E_AQ_CAP_ID_NPAR_ACTIVE 0x0003 #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 #define I40E_AQ_CAP_ID_SRIOV 0x0012 #define I40E_AQ_CAP_ID_VF 0x0013 #define I40E_AQ_CAP_ID_VMDQ 0x0014 #define I40E_AQ_CAP_ID_8021QBG 0x0015 #define I40E_AQ_CAP_ID_8021QBR 0x0016 #define I40E_AQ_CAP_ID_VSI 0x0017 #define I40E_AQ_CAP_ID_DCB 0x0018 #define I40E_AQ_CAP_ID_FCOE 0x0021 #define I40E_AQ_CAP_ID_ISCSI 0x0022 #define I40E_AQ_CAP_ID_RSS 0x0040 #define I40E_AQ_CAP_ID_RXQ 0x0041 #define I40E_AQ_CAP_ID_TXQ 0x0042 #define I40E_AQ_CAP_ID_MSIX 0x0043 #define I40E_AQ_CAP_ID_VF_MSIX 0x0044 #define I40E_AQ_CAP_ID_FLOW_DIRECTOR 0x0045 #define I40E_AQ_CAP_ID_1588 0x0046 #define I40E_AQ_CAP_ID_IWARP 0x0051 #define I40E_AQ_CAP_ID_LED 0x0061 #define I40E_AQ_CAP_ID_SDP 0x0062 #define I40E_AQ_CAP_ID_MDIO 0x0063 #define I40E_AQ_CAP_ID_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 /* Set CPPM Configuration (direct 0x0103) */ struct i40e_aqc_cppm_configuration { __le16 command_flags; #define I40E_AQ_CPPM_EN_LTRC 0x0800 #define I40E_AQ_CPPM_EN_DMCTH 0x1000 #define I40E_AQ_CPPM_EN_DMCTLX 0x2000 #define I40E_AQ_CPPM_EN_HPTC 0x4000 #define I40E_AQ_CPPM_EN_DMARC 0x8000 __le16 ttlx; __le32 dmacr; __le16 dmcth; u8 hptc; u8 reserved; __le32 pfltrc; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_cppm_configuration); /* Set ARP Proxy command / response (indirect 0x0104) */ struct i40e_aqc_arp_proxy_data { __le16 command_flags; #define I40E_AQ_ARP_INIT_IPV4 0x0008 #define I40E_AQ_ARP_UNSUP_CTL 0x0010 #define I40E_AQ_ARP_ENA 0x0020 #define I40E_AQ_ARP_ADD_IPV4 0x0040 #define I40E_AQ_ARP_DEL_IPV4 0x0080 __le16 table_id; __le32 pfpm_proxyfc; __le32 ip_addr; u8 mac_addr[6]; u8 reserved[2]; }; I40E_CHECK_STRUCT_LEN(0x14, i40e_aqc_arp_proxy_data); /* Set NS Proxy Table Entry Command (indirect 0x0105) */ struct i40e_aqc_ns_proxy_data { __le16 table_idx_mac_addr_0; __le16 table_idx_mac_addr_1; __le16 table_idx_ipv6_0; __le16 table_idx_ipv6_1; __le16 control; #define I40E_AQ_NS_PROXY_ADD_0 0x0100 #define I40E_AQ_NS_PROXY_DEL_0 0x0200 #define I40E_AQ_NS_PROXY_ADD_1 0x0400 #define I40E_AQ_NS_PROXY_DEL_1 0x0800 #define I40E_AQ_NS_PROXY_ADD_IPV6_0 0x1000 #define I40E_AQ_NS_PROXY_DEL_IPV6_0 0x2000 #define I40E_AQ_NS_PROXY_ADD_IPV6_1 0x4000 #define I40E_AQ_NS_PROXY_DEL_IPV6_1 0x8000 #define I40E_AQ_NS_PROXY_COMMAND_SEQ 0x0001 #define I40E_AQ_NS_PROXY_INIT_IPV6_TBL 0x0002 #define I40E_AQ_NS_PROXY_INIT_MAC_TBL 0x0004 u8 mac_addr_0[6]; u8 mac_addr_1[6]; u8 local_mac_addr[6]; u8 ipv6_addr_0[16]; /* Warning! spec specifies BE byte order */ u8 ipv6_addr_1[16]; }; I40E_CHECK_STRUCT_LEN(0x3c, i40e_aqc_ns_proxy_data); /* Manage LAA Command (0x0106) - obsolete */ struct i40e_aqc_mng_laa { __le16 command_flags; #define I40E_AQ_LAA_FLAG_WR 0x8000 u8 reserved[2]; __le32 sal; __le16 sah; u8 reserved2[6]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mng_laa); /* Manage MAC Address Read Command (indirect 0x0107) */ struct i40e_aqc_mac_address_read { __le16 command_flags; #define I40E_AQC_LAN_ADDR_VALID 0x10 #define I40E_AQC_SAN_ADDR_VALID 0x20 #define I40E_AQC_PORT_ADDR_VALID 0x40 #define I40E_AQC_WOL_ADDR_VALID 0x80 #define I40E_AQC_ADDR_VALID_MASK 0xf0 u8 reserved[6]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_read); struct i40e_aqc_mac_address_read_data { u8 pf_lan_mac[6]; u8 pf_san_mac[6]; u8 port_mac[6]; u8 pf_wol_mac[6]; }; I40E_CHECK_STRUCT_LEN(24, i40e_aqc_mac_address_read_data); /* Manage MAC Address Write Command (0x0108) */ struct i40e_aqc_mac_address_write { __le16 command_flags; #define I40E_AQC_WRITE_TYPE_LAA_ONLY 0x0000 #define I40E_AQC_WRITE_TYPE_LAA_WOL 0x4000 #define I40E_AQC_WRITE_TYPE_PORT 0x8000 #define I40E_AQC_WRITE_TYPE_MASK 0xc000 __le16 mac_sah; __le32 mac_sal; u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_mac_address_write); /* PXE commands (0x011x) */ /* Clear PXE Command and response (direct 0x0110) */ struct i40e_aqc_clear_pxe { u8 rx_cnt; u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_clear_pxe); /* Switch configuration commands (0x02xx) */ /* Used by many indirect commands that only pass an seid and a buffer in the * command */ struct i40e_aqc_switch_seid { __le16 seid; u8 reserved[6]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_switch_seid); /* Get Switch Configuration command (indirect 0x0200) * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_switch_config_header_resp { __le16 num_reported; __le16 num_total; u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_config_header_resp); struct i40e_aqc_switch_config_element_resp { u8 element_type; #define I40E_AQ_SW_ELEM_TYPE_MAC 1 #define I40E_AQ_SW_ELEM_TYPE_PF 2 #define I40E_AQ_SW_ELEM_TYPE_VF 3 #define I40E_AQ_SW_ELEM_TYPE_EMP 4 #define I40E_AQ_SW_ELEM_TYPE_BMC 5 #define I40E_AQ_SW_ELEM_TYPE_PV 16 #define I40E_AQ_SW_ELEM_TYPE_VEB 17 #define I40E_AQ_SW_ELEM_TYPE_PA 18 #define I40E_AQ_SW_ELEM_TYPE_VSI 19 u8 revision; #define I40E_AQ_SW_ELEM_REV_1 1 __le16 seid; __le16 uplink_seid; __le16 downlink_seid; u8 reserved[3]; u8 connection_type; #define I40E_AQ_CONN_TYPE_REGULAR 0x1 #define I40E_AQ_CONN_TYPE_DEFAULT 0x2 #define I40E_AQ_CONN_TYPE_CASCADED 0x3 __le16 scheduler_id; __le16 element_info; }; I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_config_element_resp); /* Get Switch Configuration (indirect 0x0200) * an array of elements are returned in the response buffer * the first in the array is the header, remainder are elements */ struct i40e_aqc_get_switch_config_resp { struct i40e_aqc_get_switch_config_header_resp header; struct i40e_aqc_switch_config_element_resp element[1]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_switch_config_resp); /* Add Statistics (direct 0x0201) * Remove Statistics (direct 0x0202) */ struct i40e_aqc_add_remove_statistics { __le16 seid; __le16 vlan; __le16 stat_index; u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_statistics); /* Set Port Parameters command (direct 0x0203) */ struct i40e_aqc_set_port_parameters { __le16 command_flags; #define I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS 1 #define I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS 2 /* must set! */ #define I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA 4 __le16 bad_frame_vsi; __le16 default_seid; /* reserved for command */ u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_port_parameters); /* Get Switch Resource Allocation (indirect 0x0204) */ struct i40e_aqc_get_switch_resource_alloc { u8 num_entries; /* reserved for command */ u8 reserved[7]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_switch_resource_alloc); /* expect an array of these structs in the response buffer */ struct i40e_aqc_switch_resource_alloc_element_resp { u8 resource_type; #define I40E_AQ_RESOURCE_TYPE_VEB 0x0 #define I40E_AQ_RESOURCE_TYPE_VSI 0x1 #define I40E_AQ_RESOURCE_TYPE_MACADDR 0x2 #define I40E_AQ_RESOURCE_TYPE_STAG 0x3 #define I40E_AQ_RESOURCE_TYPE_ETAG 0x4 #define I40E_AQ_RESOURCE_TYPE_MULTICAST_HASH 0x5 #define I40E_AQ_RESOURCE_TYPE_UNICAST_HASH 0x6 #define I40E_AQ_RESOURCE_TYPE_VLAN 0x7 #define I40E_AQ_RESOURCE_TYPE_VSI_LIST_ENTRY 0x8 #define I40E_AQ_RESOURCE_TYPE_ETAG_LIST_ENTRY 0x9 #define I40E_AQ_RESOURCE_TYPE_VLAN_STAT_POOL 0xA #define I40E_AQ_RESOURCE_TYPE_MIRROR_RULE 0xB #define I40E_AQ_RESOURCE_TYPE_QUEUE_SETS 0xC #define I40E_AQ_RESOURCE_TYPE_VLAN_FILTERS 0xD #define I40E_AQ_RESOURCE_TYPE_INNER_MAC_FILTERS 0xF #define I40E_AQ_RESOURCE_TYPE_IP_FILTERS 0x10 #define I40E_AQ_RESOURCE_TYPE_GRE_VN_KEYS 0x11 #define I40E_AQ_RESOURCE_TYPE_VN2_KEYS 0x12 #define I40E_AQ_RESOURCE_TYPE_TUNNEL_PORTS 0x13 u8 reserved1; __le16 guaranteed; __le16 total; __le16 used; __le16 total_unalloced; u8 reserved2[6]; }; I40E_CHECK_STRUCT_LEN(0x10, i40e_aqc_switch_resource_alloc_element_resp); /* Add VSI (indirect 0x0210) * this indirect command uses struct i40e_aqc_vsi_properties_data * as the indirect buffer (128 bytes) * * Update VSI (indirect 0x211) * uses the same data structure as Add VSI * * Get VSI (indirect 0x0212) * uses the same completion and data structure as Add VSI */ struct i40e_aqc_add_get_update_vsi { __le16 uplink_seid; u8 connection_type; #define I40E_AQ_VSI_CONN_TYPE_NORMAL 0x1 #define I40E_AQ_VSI_CONN_TYPE_DEFAULT 0x2 #define I40E_AQ_VSI_CONN_TYPE_CASCADED 0x3 u8 reserved1; u8 vf_id; u8 reserved2; __le16 vsi_flags; #define I40E_AQ_VSI_TYPE_SHIFT 0x0 #define I40E_AQ_VSI_TYPE_MASK (0x3 << I40E_AQ_VSI_TYPE_SHIFT) #define I40E_AQ_VSI_TYPE_VF 0x0 #define I40E_AQ_VSI_TYPE_VMDQ2 0x1 #define I40E_AQ_VSI_TYPE_PF 0x2 #define I40E_AQ_VSI_TYPE_EMP_MNG 0x3 #define I40E_AQ_VSI_FLAG_CASCADED_PV 0x4 __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi); struct i40e_aqc_add_get_update_vsi_completion { __le16 seid; __le16 vsi_number; __le16 vsi_used; __le16 vsi_free; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_get_update_vsi_completion); struct i40e_aqc_vsi_properties_data { /* first 96 byte are written by SW */ __le16 valid_sections; #define I40E_AQ_VSI_PROP_SWITCH_VALID 0x0001 #define I40E_AQ_VSI_PROP_SECURITY_VALID 0x0002 #define I40E_AQ_VSI_PROP_VLAN_VALID 0x0004 #define I40E_AQ_VSI_PROP_CAS_PV_VALID 0x0008 #define I40E_AQ_VSI_PROP_INGRESS_UP_VALID 0x0010 #define I40E_AQ_VSI_PROP_EGRESS_UP_VALID 0x0020 #define I40E_AQ_VSI_PROP_QUEUE_MAP_VALID 0x0040 #define I40E_AQ_VSI_PROP_QUEUE_OPT_VALID 0x0080 #define I40E_AQ_VSI_PROP_OUTER_UP_VALID 0x0100 #define I40E_AQ_VSI_PROP_SCHED_VALID 0x0200 /* switch section */ __le16 switch_id; /* 12bit id combined with flags below */ #define I40E_AQ_VSI_SW_ID_SHIFT 0x0000 #define I40E_AQ_VSI_SW_ID_MASK (0xFFF << I40E_AQ_VSI_SW_ID_SHIFT) #define I40E_AQ_VSI_SW_ID_FLAG_NOT_STAG 0x1000 #define I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB 0x2000 #define I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB 0x4000 u8 sw_reserved[2]; /* security section */ u8 sec_flags; #define I40E_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD 0x01 #define I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK 0x02 #define I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK 0x04 u8 sec_reserved; /* VLAN section */ __le16 pvid; /* VLANS include priority bits */ __le16 fcoe_pvid; u8 port_vlan_flags; #define I40E_AQ_VSI_PVLAN_MODE_SHIFT 0x00 #define I40E_AQ_VSI_PVLAN_MODE_MASK (0x03 << \ I40E_AQ_VSI_PVLAN_MODE_SHIFT) #define I40E_AQ_VSI_PVLAN_MODE_TAGGED 0x01 #define I40E_AQ_VSI_PVLAN_MODE_UNTAGGED 0x02 #define I40E_AQ_VSI_PVLAN_MODE_ALL 0x03 #define I40E_AQ_VSI_PVLAN_INSERT_PVID 0x04 #define I40E_AQ_VSI_PVLAN_EMOD_SHIFT 0x03 #define I40E_AQ_VSI_PVLAN_EMOD_MASK (0x3 << \ I40E_AQ_VSI_PVLAN_EMOD_SHIFT) #define I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH 0x0 #define I40E_AQ_VSI_PVLAN_EMOD_STR_UP 0x08 #define I40E_AQ_VSI_PVLAN_EMOD_STR 0x10 #define I40E_AQ_VSI_PVLAN_EMOD_NOTHING 0x18 u8 pvlan_reserved[3]; /* ingress egress up sections */ __le32 ingress_table; /* bitmap, 3 bits per up */ #define I40E_AQ_VSI_UP_TABLE_UP0_SHIFT 0 #define I40E_AQ_VSI_UP_TABLE_UP0_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP0_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP1_SHIFT 3 #define I40E_AQ_VSI_UP_TABLE_UP1_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP1_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP2_SHIFT 6 #define I40E_AQ_VSI_UP_TABLE_UP2_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP2_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP3_SHIFT 9 #define I40E_AQ_VSI_UP_TABLE_UP3_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP3_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP4_SHIFT 12 #define I40E_AQ_VSI_UP_TABLE_UP4_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP4_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP5_SHIFT 15 #define I40E_AQ_VSI_UP_TABLE_UP5_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP5_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP6_SHIFT 18 #define I40E_AQ_VSI_UP_TABLE_UP6_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP6_SHIFT) #define I40E_AQ_VSI_UP_TABLE_UP7_SHIFT 21 #define I40E_AQ_VSI_UP_TABLE_UP7_MASK (0x7 << \ I40E_AQ_VSI_UP_TABLE_UP7_SHIFT) __le32 egress_table; /* same defines as for ingress table */ /* cascaded PV section */ __le16 cas_pv_tag; u8 cas_pv_flags; #define I40E_AQ_VSI_CAS_PV_TAGX_SHIFT 0x00 #define I40E_AQ_VSI_CAS_PV_TAGX_MASK (0x03 << \ I40E_AQ_VSI_CAS_PV_TAGX_SHIFT) #define I40E_AQ_VSI_CAS_PV_TAGX_LEAVE 0x00 #define I40E_AQ_VSI_CAS_PV_TAGX_REMOVE 0x01 #define I40E_AQ_VSI_CAS_PV_TAGX_COPY 0x02 #define I40E_AQ_VSI_CAS_PV_INSERT_TAG 0x10 #define I40E_AQ_VSI_CAS_PV_ETAG_PRUNE 0x20 #define I40E_AQ_VSI_CAS_PV_ACCEPT_HOST_TAG 0x40 u8 cas_pv_reserved; /* queue mapping section */ __le16 mapping_flags; #define I40E_AQ_VSI_QUE_MAP_CONTIG 0x0 #define I40E_AQ_VSI_QUE_MAP_NONCONTIG 0x1 __le16 queue_mapping[16]; #define I40E_AQ_VSI_QUEUE_SHIFT 0x0 #define I40E_AQ_VSI_QUEUE_MASK (0x7FF << I40E_AQ_VSI_QUEUE_SHIFT) __le16 tc_mapping[8]; #define I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT 0 #define I40E_AQ_VSI_TC_QUE_OFFSET_MASK (0x1FF << \ I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) #define I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT 9 #define I40E_AQ_VSI_TC_QUE_NUMBER_MASK (0x7 << \ I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT) /* queueing option section */ u8 queueing_opt_flags; #define I40E_AQ_VSI_QUE_OPT_TCP_ENA 0x10 #define I40E_AQ_VSI_QUE_OPT_FCOE_ENA 0x20 u8 queueing_opt_reserved[3]; /* scheduler section */ u8 up_enable_bits; u8 sched_reserved; /* outer up section */ __le32 outer_up_table; /* same structure and defines as ingress table */ u8 cmd_reserved[8]; /* last 32 bytes are written by FW */ __le16 qs_handle[8]; #define I40E_AQ_VSI_QS_HANDLE_INVALID 0xFFFF __le16 stat_counter_idx; __le16 sched_id; u8 resp_reserved[12]; }; I40E_CHECK_STRUCT_LEN(128, i40e_aqc_vsi_properties_data); /* Add Port Virtualizer (direct 0x0220) * also used for update PV (direct 0x0221) but only flags are used * (IS_CTRL_PORT only works on add PV) */ struct i40e_aqc_add_update_pv { __le16 command_flags; #define I40E_AQC_PV_FLAG_PV_TYPE 0x1 #define I40E_AQC_PV_FLAG_FWD_UNKNOWN_STAG_EN 0x2 #define I40E_AQC_PV_FLAG_FWD_UNKNOWN_ETAG_EN 0x4 #define I40E_AQC_PV_FLAG_IS_CTRL_PORT 0x8 __le16 uplink_seid; __le16 connected_seid; u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv); struct i40e_aqc_add_update_pv_completion { /* reserved for update; for add also encodes error if rc == ENOSPC */ __le16 pv_seid; #define I40E_AQC_PV_ERR_FLAG_NO_PV 0x1 #define I40E_AQC_PV_ERR_FLAG_NO_SCHED 0x2 #define I40E_AQC_PV_ERR_FLAG_NO_COUNTER 0x4 #define I40E_AQC_PV_ERR_FLAG_NO_ENTRY 0x8 u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_update_pv_completion); /* Get PV Params (direct 0x0222) * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_pv_params_completion { __le16 seid; __le16 default_stag; __le16 pv_flags; /* same flags as add_pv */ #define I40E_AQC_GET_PV_PV_TYPE 0x1 #define I40E_AQC_GET_PV_FRWD_UNKNOWN_STAG 0x2 #define I40E_AQC_GET_PV_FRWD_UNKNOWN_ETAG 0x4 u8 reserved[8]; __le16 default_port_seid; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_pv_params_completion); /* Add VEB (direct 0x0230) */ struct i40e_aqc_add_veb { __le16 uplink_seid; __le16 downlink_seid; __le16 veb_flags; #define I40E_AQC_ADD_VEB_FLOATING 0x1 #define I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT 1 #define I40E_AQC_ADD_VEB_PORT_TYPE_MASK (0x3 << \ I40E_AQC_ADD_VEB_PORT_TYPE_SHIFT) #define I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT 0x2 #define I40E_AQC_ADD_VEB_PORT_TYPE_DATA 0x4 #define I40E_AQC_ADD_VEB_ENABLE_L2_FILTER 0x8 u8 enable_tcs; u8 reserved[9]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb); struct i40e_aqc_add_veb_completion { u8 reserved[6]; __le16 switch_seid; /* also encodes error if rc == ENOSPC; codes are the same as add_pv */ __le16 veb_seid; #define I40E_AQC_VEB_ERR_FLAG_NO_VEB 0x1 #define I40E_AQC_VEB_ERR_FLAG_NO_SCHED 0x2 #define I40E_AQC_VEB_ERR_FLAG_NO_COUNTER 0x4 #define I40E_AQC_VEB_ERR_FLAG_NO_ENTRY 0x8 __le16 statistic_index; __le16 vebs_used; __le16 vebs_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_veb_completion); /* Get VEB Parameters (direct 0x0232) * uses i40e_aqc_switch_seid for the descriptor */ struct i40e_aqc_get_veb_parameters_completion { __le16 seid; __le16 switch_id; __le16 veb_flags; /* only the first/last flags from 0x0230 is valid */ __le16 statistic_index; __le16 vebs_used; __le16 vebs_free; u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_veb_parameters_completion); /* Delete Element (direct 0x0243) * uses the generic i40e_aqc_switch_seid */ /* Add MAC-VLAN (indirect 0x0250) */ /* used for the command for most vlan commands */ struct i40e_aqc_macvlan { __le16 num_addresses; __le16 seid[3]; #define I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_MACVLAN_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) #define I40E_AQC_MACVLAN_CMD_SEID_VALID 0x8000 __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_macvlan); /* indirect data for command and response */ struct i40e_aqc_add_macvlan_element_data { u8 mac_addr[6]; __le16 vlan_tag; __le16 flags; #define I40E_AQC_MACVLAN_ADD_PERFECT_MATCH 0x0001 #define I40E_AQC_MACVLAN_ADD_HASH_MATCH 0x0002 #define I40E_AQC_MACVLAN_ADD_IGNORE_VLAN 0x0004 #define I40E_AQC_MACVLAN_ADD_TO_QUEUE 0x0008 __le16 queue_number; #define I40E_AQC_MACVLAN_CMD_QUEUE_SHIFT 0 #define I40E_AQC_MACVLAN_CMD_QUEUE_MASK (0x7FF << \ I40E_AQC_MACVLAN_CMD_SEID_NUM_SHIFT) /* response section */ u8 match_method; #define I40E_AQC_MM_PERFECT_MATCH 0x01 #define I40E_AQC_MM_HASH_MATCH 0x02 #define I40E_AQC_MM_ERR_NO_RES 0xFF u8 reserved1[3]; }; struct i40e_aqc_add_remove_macvlan_completion { __le16 perfect_mac_used; __le16 perfect_mac_free; __le16 unicast_hash_free; __le16 multicast_hash_free; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_macvlan_completion); /* Remove MAC-VLAN (indirect 0x0251) * uses i40e_aqc_macvlan for the descriptor * data points to an array of num_addresses of elements */ struct i40e_aqc_remove_macvlan_element_data { u8 mac_addr[6]; __le16 vlan_tag; u8 flags; #define I40E_AQC_MACVLAN_DEL_PERFECT_MATCH 0x01 #define I40E_AQC_MACVLAN_DEL_HASH_MATCH 0x02 #define I40E_AQC_MACVLAN_DEL_IGNORE_VLAN 0x08 #define I40E_AQC_MACVLAN_DEL_ALL_VSIS 0x10 u8 reserved[3]; /* reply section */ u8 error_code; #define I40E_AQC_REMOVE_MACVLAN_SUCCESS 0x0 #define I40E_AQC_REMOVE_MACVLAN_FAIL 0xFF u8 reply_reserved[3]; }; /* Add VLAN (indirect 0x0252) * Remove VLAN (indirect 0x0253) * use the generic i40e_aqc_macvlan for the command */ struct i40e_aqc_add_remove_vlan_element_data { __le16 vlan_tag; u8 vlan_flags; /* flags for add VLAN */ #define I40E_AQC_ADD_VLAN_LOCAL 0x1 #define I40E_AQC_ADD_PVLAN_TYPE_SHIFT 1 #define I40E_AQC_ADD_PVLAN_TYPE_MASK (0x3 << I40E_AQC_ADD_PVLAN_TYPE_SHIFT) #define I40E_AQC_ADD_PVLAN_TYPE_REGULAR 0x0 #define I40E_AQC_ADD_PVLAN_TYPE_PRIMARY 0x2 #define I40E_AQC_ADD_PVLAN_TYPE_SECONDARY 0x4 #define I40E_AQC_VLAN_PTYPE_SHIFT 3 #define I40E_AQC_VLAN_PTYPE_MASK (0x3 << I40E_AQC_VLAN_PTYPE_SHIFT) #define I40E_AQC_VLAN_PTYPE_REGULAR_VSI 0x0 #define I40E_AQC_VLAN_PTYPE_PROMISC_VSI 0x8 #define I40E_AQC_VLAN_PTYPE_COMMUNITY_VSI 0x10 #define I40E_AQC_VLAN_PTYPE_ISOLATED_VSI 0x18 /* flags for remove VLAN */ #define I40E_AQC_REMOVE_VLAN_ALL 0x1 u8 reserved; u8 result; /* flags for add VLAN */ #define I40E_AQC_ADD_VLAN_SUCCESS 0x0 #define I40E_AQC_ADD_VLAN_FAIL_REQUEST 0xFE #define I40E_AQC_ADD_VLAN_FAIL_RESOURCE 0xFF /* flags for remove VLAN */ #define I40E_AQC_REMOVE_VLAN_SUCCESS 0x0 #define I40E_AQC_REMOVE_VLAN_FAIL 0xFF u8 reserved1[3]; }; struct i40e_aqc_add_remove_vlan_completion { u8 reserved[4]; __le16 vlans_used; __le16 vlans_free; __le32 addr_high; __le32 addr_low; }; /* Set VSI Promiscuous Modes (direct 0x0254) */ struct i40e_aqc_set_vsi_promiscuous_modes { __le16 promiscuous_flags; __le16 valid_flags; /* flags used for both fields above */ #define I40E_AQC_SET_VSI_PROMISC_UNICAST 0x01 #define I40E_AQC_SET_VSI_PROMISC_MULTICAST 0x02 #define I40E_AQC_SET_VSI_PROMISC_BROADCAST 0x04 #define I40E_AQC_SET_VSI_DEFAULT 0x08 #define I40E_AQC_SET_VSI_PROMISC_VLAN 0x10 __le16 seid; #define I40E_AQC_VSI_PROM_CMD_SEID_MASK 0x3FF __le16 vlan_tag; #define I40E_AQC_SET_VSI_VLAN_VALID 0x8000 u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_vsi_promiscuous_modes); /* Add S/E-tag command (direct 0x0255) * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_add_tag { __le16 flags; #define I40E_AQC_ADD_TAG_FLAG_TO_QUEUE 0x0001 __le16 seid; #define I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_ADD_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_TAG_CMD_SEID_NUM_SHIFT) __le16 tag; __le16 queue_number; u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_tag); struct i40e_aqc_add_remove_tag_completion { u8 reserved[12]; __le16 tags_used; __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_tag_completion); /* Remove S/E-tag command (direct 0x0256) * Uses generic i40e_aqc_add_remove_tag_completion for completion */ struct i40e_aqc_remove_tag { __le16 seid; #define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_REMOVE_TAG_CMD_SEID_NUM_SHIFT) __le16 tag; u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_tag); /* Add multicast E-Tag (direct 0x0257) * del multicast E-Tag (direct 0x0258) only uses pv_seid and etag fields * and no external data */ struct i40e_aqc_add_remove_mcast_etag { __le16 pv_seid; __le16 etag; u8 num_unicast_etags; u8 reserved[3]; __le32 addr_high; /* address of array of 2-byte s-tags */ __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag); struct i40e_aqc_add_remove_mcast_etag_completion { u8 reserved[4]; __le16 mcast_etags_used; __le16 mcast_etags_free; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_mcast_etag_completion); /* Update S/E-Tag (direct 0x0259) */ struct i40e_aqc_update_tag { __le16 seid; #define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_UPDATE_TAG_CMD_SEID_NUM_SHIFT) __le16 old_tag; __le16 new_tag; u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag); struct i40e_aqc_update_tag_completion { u8 reserved[12]; __le16 tags_used; __le16 tags_free; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_update_tag_completion); /* Add Control Packet filter (direct 0x025A) * Remove Control Packet filter (direct 0x025B) * uses the i40e_aqc_add_oveb_cloud, * and the generic direct completion structure */ struct i40e_aqc_add_remove_control_packet_filter { u8 mac[6]; __le16 etype; __le16 flags; #define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC 0x0001 #define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP 0x0002 #define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE 0x0004 #define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX 0x0008 #define I40E_AQC_ADD_CONTROL_PACKET_FLAGS_RX 0x0000 __le16 seid; #define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CONTROL_PACKET_CMD_SEID_NUM_SHIFT) __le16 queue; u8 reserved[2]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter); struct i40e_aqc_add_remove_control_packet_filter_completion { __le16 mac_etype_used; __le16 etype_used; __le16 mac_etype_free; __le16 etype_free; u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_control_packet_filter_completion); /* Add Cloud filters (indirect 0x025C) * Remove Cloud filters (indirect 0x025D) * uses the i40e_aqc_add_remove_cloud_filters, * and the generic indirect completion structure */ struct i40e_aqc_add_remove_cloud_filters { u8 num_filters; u8 reserved; __le16 seid; #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT 0 #define I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_MASK (0x3FF << \ I40E_AQC_ADD_CLOUD_CMD_SEID_NUM_SHIFT) u8 reserved2[4]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_remove_cloud_filters); struct i40e_aqc_add_remove_cloud_filters_element_data { u8 outer_mac[6]; u8 inner_mac[6]; __le16 inner_vlan; union { struct { u8 reserved[12]; u8 data[4]; } v4; struct { u8 data[16]; } v6; } ipaddr; __le16 flags; #define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0 #define I40E_AQC_ADD_CLOUD_FILTER_MASK (0x3F << \ I40E_AQC_ADD_CLOUD_FILTER_SHIFT) /* 0x0000 reserved */ #define I40E_AQC_ADD_CLOUD_FILTER_OIP 0x0001 /* 0x0002 reserved */ #define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN 0x0003 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID 0x0004 /* 0x0005 reserved */ #define I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID 0x0006 /* 0x0007 reserved */ /* 0x0008 reserved */ #define I40E_AQC_ADD_CLOUD_FILTER_OMAC 0x0009 #define I40E_AQC_ADD_CLOUD_FILTER_IMAC 0x000A #define I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC 0x000B #define I40E_AQC_ADD_CLOUD_FILTER_IIP 0x000C #define I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE 0x0080 #define I40E_AQC_ADD_CLOUD_VNK_SHIFT 6 #define I40E_AQC_ADD_CLOUD_VNK_MASK 0x00C0 #define I40E_AQC_ADD_CLOUD_FLAGS_IPV4 0 #define I40E_AQC_ADD_CLOUD_FLAGS_IPV6 0x0100 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 __le32 tenant_id; u8 reserved[4]; __le16 queue_number; #define I40E_AQC_ADD_CLOUD_QUEUE_SHIFT 0 #define I40E_AQC_ADD_CLOUD_QUEUE_MASK (0x7FF << \ I40E_AQC_ADD_CLOUD_QUEUE_SHIFT) u8 reserved2[14]; /* response section */ u8 allocation_result; #define I40E_AQC_ADD_CLOUD_FILTER_SUCCESS 0x0 #define I40E_AQC_ADD_CLOUD_FILTER_FAIL 0xFF u8 response_reserved[7]; }; struct i40e_aqc_remove_cloud_filters_completion { __le16 perfect_ovlan_used; __le16 perfect_ovlan_free; __le16 vlan_used; __le16 vlan_free; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_cloud_filters_completion); /* Add Mirror Rule (indirect or direct 0x0260) * Delete Mirror Rule (indirect or direct 0x0261) * note: some rule types (4,5) do not use an external buffer. * take care to set the flags correctly. */ struct i40e_aqc_add_delete_mirror_rule { __le16 seid; __le16 rule_type; #define I40E_AQC_MIRROR_RULE_TYPE_SHIFT 0 #define I40E_AQC_MIRROR_RULE_TYPE_MASK (0x7 << \ I40E_AQC_MIRROR_RULE_TYPE_SHIFT) #define I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS 1 #define I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS 2 #define I40E_AQC_MIRROR_RULE_TYPE_VLAN 3 #define I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS 4 #define I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS 5 __le16 num_entries; __le16 destination; /* VSI for add, rule id for delete */ __le32 addr_high; /* address of array of 2-byte VSI or VLAN ids */ __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule); struct i40e_aqc_add_delete_mirror_rule_completion { u8 reserved[2]; __le16 rule_id; /* only used on add */ __le16 mirror_rules_used; __le16 mirror_rules_free; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_delete_mirror_rule_completion); /* DCB 0x03xx*/ /* PFC Ignore (direct 0x0301) * the command and response use the same descriptor structure */ struct i40e_aqc_pfc_ignore { u8 tc_bitmap; u8 command_flags; /* unused on response */ #define I40E_AQC_PFC_IGNORE_SET 0x80 #define I40E_AQC_PFC_IGNORE_CLEAR 0x0 u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pfc_ignore); /* DCB Update (direct 0x0302) uses the i40e_aq_desc structure * with no parameters */ /* TX scheduler 0x04xx */ /* Almost all the indirect commands use * this generic struct to pass the SEID in param0 */ struct i40e_aqc_tx_sched_ind { __le16 vsi_seid; u8 reserved[6]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_tx_sched_ind); /* Several commands respond with a set of queue set handles */ struct i40e_aqc_qs_handles_resp { __le16 qs_handles[8]; }; /* Configure VSI BW limits (direct 0x0400) */ struct i40e_aqc_configure_vsi_bw_limit { __le16 vsi_seid; u8 reserved[2]; __le16 credit; u8 reserved1[2]; u8 max_credit; /* 0-3, limit = 2^max */ u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_vsi_bw_limit); /* Configure VSI Bandwidth Limit per Traffic Type (indirect 0x0406) * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_ets_sla_bw_data { u8 tc_valid_bits; u8 reserved[15]; __le16 tc_bw_credits[8]; /* FW writesback QS handles here */ /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ __le16 tc_bw_max[2]; u8 reserved1[28]; }; I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_configure_vsi_ets_sla_bw_data); /* Configure VSI Bandwidth Allocation per Traffic Type (indirect 0x0407) * responds with i40e_aqc_qs_handles_resp */ struct i40e_aqc_configure_vsi_tc_bw_data { u8 tc_valid_bits; u8 reserved[3]; u8 tc_bw_credits[8]; u8 reserved1[4]; __le16 qs_handles[8]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_configure_vsi_tc_bw_data); /* Query vsi bw configuration (indirect 0x0408) */ struct i40e_aqc_query_vsi_bw_config_resp { u8 tc_valid_bits; u8 tc_suspended_bits; u8 reserved[14]; __le16 qs_handles[8]; u8 reserved1[4]; __le16 port_bw_limit; u8 reserved2[2]; u8 max_bw; /* 0-3, limit = 2^max */ u8 reserved3[23]; }; I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_query_vsi_bw_config_resp); /* Query VSI Bandwidth Allocation per Traffic Type (indirect 0x040A) */ struct i40e_aqc_query_vsi_ets_sla_config_resp { u8 tc_valid_bits; u8 reserved[3]; u8 share_credits[8]; __le16 credits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ __le16 tc_bw_max[2]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_query_vsi_ets_sla_config_resp); /* Configure Switching Component Bandwidth Limit (direct 0x0410) */ struct i40e_aqc_configure_switching_comp_bw_limit { __le16 seid; u8 reserved[2]; __le16 credit; u8 reserved1[2]; u8 max_bw; /* 0-3, limit = 2^max */ u8 reserved2[7]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_configure_switching_comp_bw_limit); /* Enable Physical Port ETS (indirect 0x0413) * Modify Physical Port ETS (indirect 0x0414) * Disable Physical Port ETS (indirect 0x0415) */ struct i40e_aqc_configure_switching_comp_ets_data { u8 reserved[4]; u8 tc_valid_bits; u8 seepage; #define I40E_AQ_ETS_SEEPAGE_EN_MASK 0x1 u8 tc_strict_priority_flags; u8 reserved1[17]; u8 tc_bw_share_credits[8]; u8 reserved2[96]; }; I40E_CHECK_STRUCT_LEN(0x80, i40e_aqc_configure_switching_comp_ets_data); /* Configure Switching Component Bandwidth Limits per Tc (indirect 0x0416) */ struct i40e_aqc_configure_switching_comp_ets_bw_limit_data { u8 tc_valid_bits; u8 reserved[15]; __le16 tc_bw_credit[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ __le16 tc_bw_max[2]; u8 reserved1[28]; }; I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_configure_switching_comp_ets_bw_limit_data); /* Configure Switching Component Bandwidth Allocation per Tc * (indirect 0x0417) */ struct i40e_aqc_configure_switching_comp_bw_config_data { u8 tc_valid_bits; u8 reserved[2]; u8 absolute_credits; /* bool */ u8 tc_bw_share_credits[8]; u8 reserved1[20]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_configure_switching_comp_bw_config_data); /* Query Switching Component Configuration (indirect 0x0418) */ struct i40e_aqc_query_switching_comp_ets_config_resp { u8 tc_valid_bits; u8 reserved[35]; __le16 port_bw_limit; u8 reserved1[2]; u8 tc_bw_max; /* 0-3, limit = 2^max */ u8 reserved2[23]; }; I40E_CHECK_STRUCT_LEN(0x40, i40e_aqc_query_switching_comp_ets_config_resp); /* Query PhysicalPort ETS Configuration (indirect 0x0419) */ struct i40e_aqc_query_port_ets_config_resp { u8 reserved[4]; u8 tc_valid_bits; u8 reserved1; u8 tc_strict_priority_bits; u8 reserved2; u8 tc_bw_share_credits[8]; __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit reserved, limit = 2^max */ __le16 tc_bw_max[2]; u8 reserved3[32]; }; I40E_CHECK_STRUCT_LEN(0x44, i40e_aqc_query_port_ets_config_resp); /* Query Switching Component Bandwidth Allocation per Traffic Type * (indirect 0x041A) */ struct i40e_aqc_query_switching_comp_bw_config_resp { u8 tc_valid_bits; u8 reserved[2]; u8 absolute_credits_enable; /* bool */ u8 tc_bw_share_credits[8]; __le16 tc_bw_limits[8]; /* 4 bits per tc 0-7, 4th bit is reserved, limit = 2^max */ __le16 tc_bw_max[2]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_query_switching_comp_bw_config_resp); /* Suspend/resume port TX traffic * (direct 0x041B and 0x041C) uses the generic SEID struct */ /* Configure partition BW * (indirect 0x041D) */ struct i40e_aqc_configure_partition_bw_data { __le16 pf_valid_bits; u8 min_bw[16]; /* guaranteed bandwidth */ u8 max_bw[16]; /* bandwidth limit */ }; I40E_CHECK_STRUCT_LEN(0x22, i40e_aqc_configure_partition_bw_data); /* Get and set the active HMC resource profile and status. * (direct 0x0500) and (direct 0x0501) */ struct i40e_aq_get_set_hmc_resource_profile { u8 pm_profile; u8 pe_vf_enabled; u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_get_set_hmc_resource_profile); enum i40e_aq_hmc_profile { /* I40E_HMC_PROFILE_NO_CHANGE = 0, reserved */ I40E_HMC_PROFILE_DEFAULT = 1, I40E_HMC_PROFILE_FAVOR_VF = 2, I40E_HMC_PROFILE_EQUAL = 3, }; #define I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK 0xF #define I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK 0x3F /* Get PHY Abilities (indirect 0x0600) uses the generic indirect struct */ /* set in param0 for get phy abilities to report qualified modules */ #define I40E_AQ_PHY_REPORT_QUALIFIED_MODULES 0x0001 #define I40E_AQ_PHY_REPORT_INITIAL_VALUES 0x0002 enum i40e_aq_phy_type { I40E_PHY_TYPE_SGMII = 0x0, I40E_PHY_TYPE_1000BASE_KX = 0x1, I40E_PHY_TYPE_10GBASE_KX4 = 0x2, I40E_PHY_TYPE_10GBASE_KR = 0x3, I40E_PHY_TYPE_40GBASE_KR4 = 0x4, I40E_PHY_TYPE_XAUI = 0x5, I40E_PHY_TYPE_XFI = 0x6, I40E_PHY_TYPE_SFI = 0x7, I40E_PHY_TYPE_XLAUI = 0x8, I40E_PHY_TYPE_XLPPI = 0x9, I40E_PHY_TYPE_40GBASE_CR4_CU = 0xA, I40E_PHY_TYPE_10GBASE_CR1_CU = 0xB, I40E_PHY_TYPE_10GBASE_AOC = 0xC, I40E_PHY_TYPE_40GBASE_AOC = 0xD, I40E_PHY_TYPE_100BASE_TX = 0x11, I40E_PHY_TYPE_1000BASE_T = 0x12, I40E_PHY_TYPE_10GBASE_T = 0x13, I40E_PHY_TYPE_10GBASE_SR = 0x14, I40E_PHY_TYPE_10GBASE_LR = 0x15, I40E_PHY_TYPE_10GBASE_SFPP_CU = 0x16, I40E_PHY_TYPE_10GBASE_CR1 = 0x17, I40E_PHY_TYPE_40GBASE_CR4 = 0x18, I40E_PHY_TYPE_40GBASE_SR4 = 0x19, I40E_PHY_TYPE_40GBASE_LR4 = 0x1A, I40E_PHY_TYPE_1000BASE_SX = 0x1B, I40E_PHY_TYPE_1000BASE_LX = 0x1C, I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D, I40E_PHY_TYPE_20GBASE_KR2 = 0x1E, I40E_PHY_TYPE_MAX }; #define I40E_LINK_SPEED_100MB_SHIFT 0x1 #define I40E_LINK_SPEED_1000MB_SHIFT 0x2 #define I40E_LINK_SPEED_10GB_SHIFT 0x3 #define I40E_LINK_SPEED_40GB_SHIFT 0x4 #define I40E_LINK_SPEED_20GB_SHIFT 0x5 enum i40e_aq_link_speed { I40E_LINK_SPEED_UNKNOWN = 0, I40E_LINK_SPEED_100MB = (1 << I40E_LINK_SPEED_100MB_SHIFT), I40E_LINK_SPEED_1GB = (1 << I40E_LINK_SPEED_1000MB_SHIFT), I40E_LINK_SPEED_10GB = (1 << I40E_LINK_SPEED_10GB_SHIFT), I40E_LINK_SPEED_40GB = (1 << I40E_LINK_SPEED_40GB_SHIFT), I40E_LINK_SPEED_20GB = (1 << I40E_LINK_SPEED_20GB_SHIFT) }; struct i40e_aqc_module_desc { u8 oui[3]; u8 reserved1; u8 part_number[16]; u8 revision[4]; u8 reserved2[8]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_module_desc); struct i40e_aq_get_phy_abilities_resp { __le32 phy_type; /* bitmap using the above enum for offsets */ u8 link_speed; /* bitmap using the above enum bit patterns */ u8 abilities; #define I40E_AQ_PHY_FLAG_PAUSE_TX 0x01 #define I40E_AQ_PHY_FLAG_PAUSE_RX 0x02 #define I40E_AQ_PHY_FLAG_LOW_POWER 0x04 #define I40E_AQ_PHY_LINK_ENABLED 0x08 #define I40E_AQ_PHY_AN_ENABLED 0x10 #define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20 __le16 eee_capability; #define I40E_AQ_EEE_100BASE_TX 0x0002 #define I40E_AQ_EEE_1000BASE_T 0x0004 #define I40E_AQ_EEE_10GBASE_T 0x0008 #define I40E_AQ_EEE_1000BASE_KX 0x0010 #define I40E_AQ_EEE_10GBASE_KX4 0x0020 #define I40E_AQ_EEE_10GBASE_KR 0x0040 __le32 eeer_val; u8 d3_lpan; #define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01 u8 reserved[3]; u8 phy_id[4]; u8 module_type[3]; u8 qualified_module_count; #define I40E_AQ_PHY_MAX_QMS 16 struct i40e_aqc_module_desc qualified_module[I40E_AQ_PHY_MAX_QMS]; }; I40E_CHECK_STRUCT_LEN(0x218, i40e_aq_get_phy_abilities_resp); /* Set PHY Config (direct 0x0601) */ struct i40e_aq_set_phy_config { /* same bits as above in all */ __le32 phy_type; u8 link_speed; u8 abilities; /* bits 0-2 use the values from get_phy_abilities_resp */ #define I40E_AQ_PHY_ENABLE_LINK 0x08 #define I40E_AQ_PHY_ENABLE_AN 0x10 #define I40E_AQ_PHY_ENABLE_ATOMIC_LINK 0x20 __le16 eee_capability; __le32 eeer; u8 low_power_ctrl; u8 reserved[3]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config); /* Set MAC Config command data structure (direct 0x0603) */ struct i40e_aq_set_mac_config { __le16 max_frame_size; u8 params; #define I40E_AQ_SET_MAC_CONFIG_CRC_EN 0x04 #define I40E_AQ_SET_MAC_CONFIG_PACING_MASK 0x78 #define I40E_AQ_SET_MAC_CONFIG_PACING_SHIFT 3 #define I40E_AQ_SET_MAC_CONFIG_PACING_NONE 0x0 #define I40E_AQ_SET_MAC_CONFIG_PACING_1B_13TX 0xF #define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_9TX 0x9 #define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_4TX 0x8 #define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_7TX 0x7 #define I40E_AQ_SET_MAC_CONFIG_PACING_2DW_3TX 0x6 #define I40E_AQ_SET_MAC_CONFIG_PACING_1DW_1TX 0x5 #define I40E_AQ_SET_MAC_CONFIG_PACING_3DW_2TX 0x4 #define I40E_AQ_SET_MAC_CONFIG_PACING_7DW_3TX 0x3 #define I40E_AQ_SET_MAC_CONFIG_PACING_4DW_1TX 0x2 #define I40E_AQ_SET_MAC_CONFIG_PACING_9DW_1TX 0x1 u8 tx_timer_priority; /* bitmap */ __le16 tx_timer_value; __le16 fc_refresh_threshold; u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aq_set_mac_config); /* Restart Auto-Negotiation (direct 0x605) */ struct i40e_aqc_set_link_restart_an { u8 command; #define I40E_AQ_PHY_RESTART_AN 0x02 #define I40E_AQ_PHY_LINK_ENABLE 0x04 u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_link_restart_an); /* Get Link Status cmd & response data structure (direct 0x0607) */ struct i40e_aqc_get_link_status { __le16 command_flags; /* only field set on command */ #define I40E_AQ_LSE_MASK 0x3 #define I40E_AQ_LSE_NOP 0x0 #define I40E_AQ_LSE_DISABLE 0x2 #define I40E_AQ_LSE_ENABLE 0x3 /* only response uses this flag */ #define I40E_AQ_LSE_IS_ENABLED 0x1 u8 phy_type; /* i40e_aq_phy_type */ u8 link_speed; /* i40e_aq_link_speed */ u8 link_info; #define I40E_AQ_LINK_UP 0x01 #define I40E_AQ_LINK_FAULT 0x02 #define I40E_AQ_LINK_FAULT_TX 0x04 #define I40E_AQ_LINK_FAULT_RX 0x08 #define I40E_AQ_LINK_FAULT_REMOTE 0x10 #define I40E_AQ_MEDIA_AVAILABLE 0x40 #define I40E_AQ_SIGNAL_DETECT 0x80 u8 an_info; #define I40E_AQ_AN_COMPLETED 0x01 #define I40E_AQ_LP_AN_ABILITY 0x02 #define I40E_AQ_PD_FAULT 0x04 #define I40E_AQ_FEC_EN 0x08 #define I40E_AQ_PHY_LOW_POWER 0x10 #define I40E_AQ_LINK_PAUSE_TX 0x20 #define I40E_AQ_LINK_PAUSE_RX 0x40 #define I40E_AQ_QUALIFIED_MODULE 0x80 u8 ext_info; #define I40E_AQ_LINK_PHY_TEMP_ALARM 0x01 #define I40E_AQ_LINK_XCESSIVE_ERRORS 0x02 #define I40E_AQ_LINK_TX_SHIFT 0x02 #define I40E_AQ_LINK_TX_MASK (0x03 << I40E_AQ_LINK_TX_SHIFT) #define I40E_AQ_LINK_TX_ACTIVE 0x00 #define I40E_AQ_LINK_TX_DRAINED 0x01 #define I40E_AQ_LINK_TX_FLUSHED 0x03 #define I40E_AQ_LINK_FORCED_40G 0x10 u8 loopback; /* use defines from i40e_aqc_set_lb_mode */ __le16 max_frame_size; u8 config; #define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_PACING_MASK 0x78 u8 reserved[5]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); /* Set event mask command (direct 0x613) */ struct i40e_aqc_set_phy_int_mask { u8 reserved[8]; __le16 event_mask; #define I40E_AQ_EVENT_LINK_UPDOWN 0x0002 #define I40E_AQ_EVENT_MEDIA_NA 0x0004 #define I40E_AQ_EVENT_LINK_FAULT 0x0008 #define I40E_AQ_EVENT_PHY_TEMP_ALARM 0x0010 #define I40E_AQ_EVENT_EXCESSIVE_ERRORS 0x0020 #define I40E_AQ_EVENT_SIGNAL_DETECT 0x0040 #define I40E_AQ_EVENT_AN_COMPLETED 0x0080 #define I40E_AQ_EVENT_MODULE_QUAL_FAIL 0x0100 #define I40E_AQ_EVENT_PORT_TX_SUSPENDED 0x0200 u8 reserved1[6]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_int_mask); /* Get Local AN advt register (direct 0x0614) * Set Local AN advt register (direct 0x0615) * Get Link Partner AN advt register (direct 0x0616) */ struct i40e_aqc_an_advt_reg { __le32 local_an_reg0; __le16 local_an_reg1; u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_an_advt_reg); /* Set Loopback mode (0x0618) */ struct i40e_aqc_set_lb_mode { __le16 lb_mode; #define I40E_AQ_LB_PHY_LOCAL 0x01 #define I40E_AQ_LB_PHY_REMOTE 0x02 #define I40E_AQ_LB_MAC_LOCAL 0x04 u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_lb_mode); /* Set PHY Debug command (0x0622) */ struct i40e_aqc_set_phy_debug { u8 command_flags; #define I40E_AQ_PHY_DEBUG_RESET_INTERNAL 0x02 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT 2 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_MASK (0x03 << \ I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SHIFT) #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_NONE 0x00 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_HARD 0x01 #define I40E_AQ_PHY_DEBUG_RESET_EXTERNAL_SOFT 0x02 #define I40E_AQ_PHY_DEBUG_DISABLE_LINK_FW 0x10 u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_set_phy_debug); enum i40e_aq_phy_reg_type { I40E_AQC_PHY_REG_INTERNAL = 0x1, I40E_AQC_PHY_REG_EXERNAL_BASET = 0x2, I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) */ struct i40e_aqc_nvm_update { u8 command_flags; #define I40E_AQ_NVM_LAST_CMD 0x01 #define I40E_AQ_NVM_FLASH_ONLY 0x80 u8 module_pointer; __le16 length; __le32 offset; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_update); /* NVM Config Read (indirect 0x0704) */ struct i40e_aqc_nvm_config_read { __le16 cmd_flags; #define I40E_AQ_ANVM_SINGLE_OR_MULTIPLE_FEATURES_MASK 1 #define I40E_AQ_ANVM_READ_SINGLE_FEATURE 0 #define I40E_AQ_ANVM_READ_MULTIPLE_FEATURES 1 __le16 element_count; __le16 element_id; /* Feature/field ID */ __le16 element_id_msw; /* MSWord of field ID */ __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_read); /* NVM Config Write (indirect 0x0705) */ struct i40e_aqc_nvm_config_write { __le16 cmd_flags; __le16 element_count; u8 reserved[4]; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_nvm_config_write); /* Used for 0x0704 as well as for 0x0705 commands */ #define I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_SHIFT 1 #define I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_MASK (1 << I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_SHIFT) #define I40E_AQ_ANVM_FEATURE 0 #define I40E_AQ_ANVM_IMMEDIATE_FIELD (1 << FEATURE_OR_IMMEDIATE_SHIFT) struct i40e_aqc_nvm_config_data_feature { __le16 feature_id; #define I40E_AQ_ANVM_FEATURE_OPTION_OEM_ONLY 0x01 #define I40E_AQ_ANVM_FEATURE_OPTION_DWORD_MAP 0x08 #define I40E_AQ_ANVM_FEATURE_OPTION_POR_CSR 0x10 __le16 feature_options; __le16 feature_selection; }; I40E_CHECK_STRUCT_LEN(0x6, i40e_aqc_nvm_config_data_feature); struct i40e_aqc_nvm_config_data_immediate_field { __le32 field_id; __le32 field_value; __le16 field_options; __le16 reserved; }; I40E_CHECK_STRUCT_LEN(0xc, i40e_aqc_nvm_config_data_immediate_field); /* Send to PF command (indirect 0x0801) id is only used by PF * Send to VF command (indirect 0x0802) id is only used by PF * Send to Peer PF command (indirect 0x0803) */ struct i40e_aqc_pf_vf_message { __le32 id; u8 reserved[4]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_pf_vf_message); /* Alternate structure */ /* Direct write (direct 0x0900) * Direct read (direct 0x0902) */ struct i40e_aqc_alternate_write { __le32 address0; __le32 data0; __le32 address1; __le32 data1; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write); /* Indirect write (indirect 0x0901) * Indirect read (indirect 0x0903) */ struct i40e_aqc_alternate_ind_write { __le32 address; __le32 length; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_ind_write); /* Done alternate write (direct 0x0904) * uses i40e_aq_desc */ struct i40e_aqc_alternate_write_done { __le16 cmd_flags; #define I40E_AQ_ALTERNATE_MODE_BIOS_MASK 1 #define I40E_AQ_ALTERNATE_MODE_BIOS_LEGACY 0 #define I40E_AQ_ALTERNATE_MODE_BIOS_UEFI 1 #define I40E_AQ_ALTERNATE_RESET_NEEDED 2 u8 reserved[14]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_write_done); /* Set OEM mode (direct 0x0905) */ struct i40e_aqc_alternate_set_mode { __le32 mode; #define I40E_AQ_ALTERNATE_MODE_NONE 0 #define I40E_AQ_ALTERNATE_MODE_OEM 1 u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_alternate_set_mode); /* Clear port Alternate RAM (direct 0x0906) uses i40e_aq_desc */ /* async events 0x10xx */ /* Lan Queue Overflow Event (direct, 0x1001) */ struct i40e_aqc_lan_overflow { __le32 prtdcb_rupto; __le32 otx_ctl; u8 reserved[8]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lan_overflow); /* Get LLDP MIB (indirect 0x0A00) */ struct i40e_aqc_lldp_get_mib { u8 type; u8 reserved1; #define I40E_AQ_LLDP_MIB_TYPE_MASK 0x3 #define I40E_AQ_LLDP_MIB_LOCAL 0x0 #define I40E_AQ_LLDP_MIB_REMOTE 0x1 #define I40E_AQ_LLDP_MIB_LOCAL_AND_REMOTE 0x2 #define I40E_AQ_LLDP_BRIDGE_TYPE_MASK 0xC #define I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT 0x2 #define I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE 0x0 #define I40E_AQ_LLDP_BRIDGE_TYPE_NON_TPMR 0x1 #define I40E_AQ_LLDP_TX_SHIFT 0x4 #define I40E_AQ_LLDP_TX_MASK (0x03 << I40E_AQ_LLDP_TX_SHIFT) /* TX pause flags use I40E_AQ_LINK_TX_* above */ __le16 local_len; __le16 remote_len; u8 reserved2[2]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_get_mib); /* Configure LLDP MIB Change Event (direct 0x0A01) * also used for the event (with type in the command field) */ struct i40e_aqc_lldp_update_mib { u8 command; #define I40E_AQ_LLDP_MIB_UPDATE_ENABLE 0x0 #define I40E_AQ_LLDP_MIB_UPDATE_DISABLE 0x1 u8 reserved[7]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_mib); /* Add LLDP TLV (indirect 0x0A02) * Delete LLDP TLV (indirect 0x0A04) */ struct i40e_aqc_lldp_add_tlv { u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ u8 reserved1[1]; __le16 len; u8 reserved2[4]; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_add_tlv); /* Update LLDP TLV (indirect 0x0A03) */ struct i40e_aqc_lldp_update_tlv { u8 type; /* only nearest bridge and non-TPMR from 0x0A00 */ u8 reserved; __le16 old_len; __le16 new_offset; __le16 new_len; __le32 addr_high; __le32 addr_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_update_tlv); /* Stop LLDP (direct 0x0A05) */ struct i40e_aqc_lldp_stop { u8 command; #define I40E_AQ_LLDP_AGENT_STOP 0x0 #define I40E_AQ_LLDP_AGENT_SHUTDOWN 0x1 u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop); /* Start LLDP (direct 0x0A06) */ struct i40e_aqc_lldp_start { u8 command; #define I40E_AQ_LLDP_AGENT_START 0x1 u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); /* Get CEE DCBX Oper Config (0x0A07) * uses the generic descriptor struct * returns below as indirect response */ #define I40E_AQC_CEE_APP_FCOE_SHIFT 0x0 #define I40E_AQC_CEE_APP_FCOE_MASK (0x7 << I40E_AQC_CEE_APP_FCOE_SHIFT) #define I40E_AQC_CEE_APP_ISCSI_SHIFT 0x3 #define I40E_AQC_CEE_APP_ISCSI_MASK (0x7 << I40E_AQC_CEE_APP_ISCSI_SHIFT) #define I40E_AQC_CEE_APP_FIP_SHIFT 0x8 #define I40E_AQC_CEE_APP_FIP_MASK (0x7 << I40E_AQC_CEE_APP_FIP_SHIFT) #define I40E_AQC_CEE_PG_STATUS_SHIFT 0x0 #define I40E_AQC_CEE_PG_STATUS_MASK (0x7 << I40E_AQC_CEE_PG_STATUS_SHIFT) #define I40E_AQC_CEE_PFC_STATUS_SHIFT 0x3 #define I40E_AQC_CEE_PFC_STATUS_MASK (0x7 << I40E_AQC_CEE_PFC_STATUS_SHIFT) #define I40E_AQC_CEE_APP_STATUS_SHIFT 0x8 #define I40E_AQC_CEE_APP_STATUS_MASK (0x7 << I40E_AQC_CEE_APP_STATUS_SHIFT) struct i40e_aqc_get_cee_dcb_cfg_v1_resp { u8 reserved1; u8 oper_num_tc; u8 oper_prio_tc[4]; u8 reserved2; u8 oper_tc_bw[8]; u8 oper_pfc_en; u8 reserved3; __le16 oper_app_prio; u8 reserved4; __le16 tlv_status; }; I40E_CHECK_STRUCT_LEN(0x18, i40e_aqc_get_cee_dcb_cfg_v1_resp); struct i40e_aqc_get_cee_dcb_cfg_resp { u8 oper_num_tc; u8 oper_prio_tc[4]; u8 oper_tc_bw[8]; u8 oper_pfc_en; __le16 oper_app_prio; __le32 tlv_status; u8 reserved[12]; }; I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_cee_dcb_cfg_resp); /* Set Local LLDP MIB (indirect 0x0A08) * Used to replace the local MIB of a given LLDP agent. e.g. DCBx */ struct i40e_aqc_lldp_set_local_mib { #define SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT 0 #define SET_LOCAL_MIB_AC_TYPE_DCBX_MASK (1 << SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT) u8 type; u8 reserved0; __le16 length; u8 reserved1[4]; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_set_local_mib); /* Stop/Start LLDP Agent (direct 0x0A09) * Used for stopping/starting specific LLDP agent. e.g. DCBx */ struct i40e_aqc_lldp_stop_start_specific_agent { #define I40E_AQC_START_SPECIFIC_AGENT_SHIFT 0 #define I40E_AQC_START_SPECIFIC_AGENT_MASK (1 << I40E_AQC_START_SPECIFIC_AGENT_SHIFT) u8 command; u8 reserved[15]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_stop_start_specific_agent); /* Add Udp Tunnel command and completion (direct 0x0B00) */ struct i40e_aqc_add_udp_tunnel { __le16 udp_port; u8 reserved0[3]; u8 protocol_type; #define I40E_AQC_TUNNEL_TYPE_VXLAN 0x00 #define I40E_AQC_TUNNEL_TYPE_NGE 0x01 #define I40E_AQC_TUNNEL_TYPE_TEREDO 0x10 u8 reserved1[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel); struct i40e_aqc_add_udp_tunnel_completion { __le16 udp_port; u8 filter_entry_index; u8 multiple_pfs; #define I40E_AQC_SINGLE_PF 0x0 #define I40E_AQC_MULTIPLE_PFS 0x1 u8 total_filters; u8 reserved[11]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_add_udp_tunnel_completion); /* remove UDP Tunnel command (0x0B01) */ struct i40e_aqc_remove_udp_tunnel { u8 reserved[2]; u8 index; /* 0 to 15 */ u8 reserved2[13]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_remove_udp_tunnel); struct i40e_aqc_del_udp_tunnel_completion { __le16 udp_port; u8 index; /* 0 to 15 */ u8 multiple_pfs; u8 total_filters_used; u8 reserved1[11]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_del_udp_tunnel_completion); /* tunnel key structure 0x0B10 */ struct i40e_aqc_tunnel_key_structure { u8 key1_off; u8 key2_off; u8 key1_len; /* 0 to 15 */ u8 key2_len; /* 0 to 15 */ u8 flags; #define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDE 0x01 /* response flags */ #define I40E_AQC_TUNNEL_KEY_STRUCT_SUCCESS 0x01 #define I40E_AQC_TUNNEL_KEY_STRUCT_MODIFIED 0x02 #define I40E_AQC_TUNNEL_KEY_STRUCT_OVERRIDDEN 0x03 u8 network_key_index; #define I40E_AQC_NETWORK_KEY_INDEX_VXLAN 0x0 #define I40E_AQC_NETWORK_KEY_INDEX_NGE 0x1 #define I40E_AQC_NETWORK_KEY_INDEX_FLEX_MAC_IN_UDP 0x2 #define I40E_AQC_NETWORK_KEY_INDEX_GRE 0x3 u8 reserved[10]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_tunnel_key_structure); /* OEM mode commands (direct 0xFE0x) */ struct i40e_aqc_oem_param_change { __le32 param_type; #define I40E_AQ_OEM_PARAM_TYPE_PF_CTL 0 #define I40E_AQ_OEM_PARAM_TYPE_BW_CTL 1 #define I40E_AQ_OEM_PARAM_MAC 2 __le32 param_value1; __le16 param_value2; u8 reserved[6]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_param_change); struct i40e_aqc_oem_state_change { __le32 state; #define I40E_AQ_OEM_STATE_LINK_DOWN 0x0 #define I40E_AQ_OEM_STATE_LINK_UP 0x1 u8 reserved[12]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_oem_state_change); /* Initialize OCSD (0xFE02, direct) */ struct i40e_aqc_opc_oem_ocsd_initialize { u8 type_status; u8 reserved1[3]; __le32 ocsd_memory_block_addr_high; __le32 ocsd_memory_block_addr_low; __le32 requested_update_interval; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_opc_oem_ocsd_initialize); /* Initialize OCBB (0xFE03, direct) */ struct i40e_aqc_opc_oem_ocbb_initialize { u8 type_status; u8 reserved1[3]; __le32 ocbb_memory_block_addr_high; __le32 ocbb_memory_block_addr_low; u8 reserved2[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_opc_oem_ocbb_initialize); /* debug commands */ /* get device id (0xFF00) uses the generic structure */ /* set test more (0xFF01, internal) */ struct i40e_acq_set_test_mode { u8 mode; #define I40E_AQ_TEST_PARTIAL 0 #define I40E_AQ_TEST_FULL 1 #define I40E_AQ_TEST_NVM 2 u8 reserved[3]; u8 command; #define I40E_AQ_TEST_OPEN 0 #define I40E_AQ_TEST_CLOSE 1 #define I40E_AQ_TEST_INC 2 u8 reserved2[3]; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_acq_set_test_mode); /* Debug Read Register command (0xFF03) * Debug Write Register command (0xFF04) */ struct i40e_aqc_debug_reg_read_write { __le32 reserved; __le32 address; __le32 value_high; __le32 value_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_reg_read_write); /* Scatter/gather Reg Read (indirect 0xFF05) * Scatter/gather Reg Write (indirect 0xFF06) */ /* i40e_aq_desc is used for the command */ struct i40e_aqc_debug_reg_sg_element_data { __le32 address; __le32 value; }; /* Debug Modify register (direct 0xFF07) */ struct i40e_aqc_debug_modify_reg { __le32 address; __le32 value; __le32 clear_mask; __le32 set_mask; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_reg); /* dump internal data (0xFF08, indirect) */ #define I40E_AQ_CLUSTER_ID_AUX 0 #define I40E_AQ_CLUSTER_ID_SWITCH_FLU 1 #define I40E_AQ_CLUSTER_ID_TXSCHED 2 #define I40E_AQ_CLUSTER_ID_HMC 3 #define I40E_AQ_CLUSTER_ID_MAC0 4 #define I40E_AQ_CLUSTER_ID_MAC1 5 #define I40E_AQ_CLUSTER_ID_MAC2 6 #define I40E_AQ_CLUSTER_ID_MAC3 7 #define I40E_AQ_CLUSTER_ID_DCB 8 #define I40E_AQ_CLUSTER_ID_EMP_MEM 9 #define I40E_AQ_CLUSTER_ID_PKT_BUF 10 #define I40E_AQ_CLUSTER_ID_ALTRAM 11 struct i40e_aqc_debug_dump_internals { u8 cluster_id; u8 table_id; __le16 data_size; __le32 idx; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_dump_internals); struct i40e_aqc_debug_modify_internals { u8 cluster_id; u8 cluster_specific_params[7]; __le32 address_high; __le32 address_low; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_debug_modify_internals); #endif ================================================ FILE: drivers/net/i40e/base/i40e_alloc.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_ALLOC_H_ #define _I40E_ALLOC_H_ struct i40e_hw; /* Memory allocation types */ enum i40e_memory_type { i40e_mem_arq_buf = 0, /* ARQ indirect command buffer */ i40e_mem_asq_buf = 1, i40e_mem_atq_buf = 2, /* ATQ indirect command buffer */ i40e_mem_arq_ring = 3, /* ARQ descriptor ring */ i40e_mem_atq_ring = 4, /* ATQ descriptor ring */ i40e_mem_pd = 5, /* Page Descriptor */ i40e_mem_bp = 6, /* Backing Page - 4KB */ i40e_mem_bp_jumbo = 7, /* Backing Page - > 4KB */ i40e_mem_reserved }; /* prototype for functions used for dynamic memory allocation */ enum i40e_status_code i40e_allocate_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem, enum i40e_memory_type type, u64 size, u32 alignment); enum i40e_status_code i40e_free_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem); enum i40e_status_code i40e_allocate_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem, u32 size); enum i40e_status_code i40e_free_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem); #endif /* _I40E_ALLOC_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_common.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_type.h" #include "i40e_adminq.h" #include "i40e_prototype.h" #include "i40e_virtchnl.h" /** * i40e_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * vendor ID and device ID stored in the hw structure. **/ #if defined(INTEGRATED_VF) || defined(VF_DRIVER) enum i40e_status_code i40e_set_mac_type(struct i40e_hw *hw) #else STATIC enum i40e_status_code i40e_set_mac_type(struct i40e_hw *hw) #endif { enum i40e_status_code status = I40E_SUCCESS; DEBUGFUNC("i40e_set_mac_type\n"); if (hw->vendor_id == I40E_INTEL_VENDOR_ID) { switch (hw->device_id) { case I40E_DEV_ID_SFP_XL710: case I40E_DEV_ID_QEMU: case I40E_DEV_ID_KX_A: case I40E_DEV_ID_KX_B: case I40E_DEV_ID_KX_C: case I40E_DEV_ID_QSFP_A: case I40E_DEV_ID_QSFP_B: case I40E_DEV_ID_QSFP_C: case I40E_DEV_ID_10G_BASE_T: hw->mac.type = I40E_MAC_XL710; break; case I40E_DEV_ID_VF: case I40E_DEV_ID_VF_HV: hw->mac.type = I40E_MAC_VF; break; default: hw->mac.type = I40E_MAC_GENERIC; break; } } else { status = I40E_ERR_DEVICE_NOT_SUPPORTED; } DEBUGOUT2("i40e_set_mac_type found mac: %d, returns: %d\n", hw->mac.type, status); return status; } /** * i40e_debug_aq * @hw: debug mask related to admin queue * @mask: debug mask * @desc: pointer to admin queue descriptor * @buffer: pointer to command buffer * @buf_len: max length of buffer * * Dumps debug log about adminq command with descriptor contents. **/ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, void *buffer, u16 buf_len) { struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc; u16 len = LE16_TO_CPU(aq_desc->datalen); u8 *buf = (u8 *)buffer; u16 i = 0; if ((!(mask & hw->debug_mask)) || (desc == NULL)) return; i40e_debug(hw, mask, "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", LE16_TO_CPU(aq_desc->opcode), LE16_TO_CPU(aq_desc->flags), LE16_TO_CPU(aq_desc->datalen), LE16_TO_CPU(aq_desc->retval)); i40e_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n", LE32_TO_CPU(aq_desc->cookie_high), LE32_TO_CPU(aq_desc->cookie_low)); i40e_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n", LE32_TO_CPU(aq_desc->params.internal.param0), LE32_TO_CPU(aq_desc->params.internal.param1)); i40e_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n", LE32_TO_CPU(aq_desc->params.external.addr_high), LE32_TO_CPU(aq_desc->params.external.addr_low)); if ((buffer != NULL) && (aq_desc->datalen != 0)) { i40e_debug(hw, mask, "AQ CMD Buffer:\n"); if (buf_len < len) len = buf_len; /* write the full 16-byte chunks */ for (i = 0; i < (len - 16); i += 16) i40e_debug(hw, mask, "\t0x%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", i, buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7], buf[i+8], buf[i+9], buf[i+10], buf[i+11], buf[i+12], buf[i+13], buf[i+14], buf[i+15]); /* write whatever's left over without overrunning the buffer */ if (i < len) { char d_buf[80]; int j = 0; memset(d_buf, 0, sizeof(d_buf)); j += sprintf(d_buf, "\t0x%04X ", i); while (i < len) j += sprintf(&d_buf[j], " %02X", buf[i++]); i40e_debug(hw, mask, "%s\n", d_buf); } } } /** * i40e_check_asq_alive * @hw: pointer to the hw struct * * Returns true if Queue is enabled else false. **/ bool i40e_check_asq_alive(struct i40e_hw *hw) { if (hw->aq.asq.len) return !!(rd32(hw, hw->aq.asq.len) & I40E_PF_ATQLEN_ATQENABLE_MASK); else return false; } /** * i40e_aq_queue_shutdown * @hw: pointer to the hw struct * @unloading: is the driver unloading itself * * Tell the Firmware that we're shutting down the AdminQ and whether * or not the driver is unloading as well. **/ enum i40e_status_code i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading) { struct i40e_aq_desc desc; struct i40e_aqc_queue_shutdown *cmd = (struct i40e_aqc_queue_shutdown *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_queue_shutdown); if (unloading) cmd->driver_unloading = CPU_TO_LE32(I40E_AQ_DRIVER_UNLOADING); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); return status; } /* The i40e_ptype_lookup table is used to convert from the 8-bit ptype in the * hardware to a bit-field that can be used by SW to more easily determine the * packet type. * * Macros are used to shorten the table lines and make this table human * readable. * * We store the PTYPE in the top byte of the bit field - this is just so that * we can check that the table doesn't have a row missing, as the index into * the table should be the PTYPE. * * Typical work flow: * * IF NOT i40e_ptype_lookup[ptype].known * THEN * Packet is unknown * ELSE IF i40e_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP * Use the rest of the fields to look at the tunnels, inner protocols, etc * ELSE * Use the enum i40e_rx_l2_ptype to decode the packet type * ENDIF */ /* macro to make the table lines short */ #define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\ { PTYPE, \ 1, \ I40E_RX_PTYPE_OUTER_##OUTER_IP, \ I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \ I40E_RX_PTYPE_##OUTER_FRAG, \ I40E_RX_PTYPE_TUNNEL_##T, \ I40E_RX_PTYPE_TUNNEL_END_##TE, \ I40E_RX_PTYPE_##TEF, \ I40E_RX_PTYPE_INNER_PROT_##I, \ I40E_RX_PTYPE_PAYLOAD_LAYER_##PL } #define I40E_PTT_UNUSED_ENTRY(PTYPE) \ { PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* shorter macros makes the table fit but are terse */ #define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG #define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG #define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC /* Lookup table mapping the HW PTYPE to the bit field for decoding */ struct i40e_rx_ptype_decoded i40e_ptype_lookup[] = { /* L2 Packet types */ I40E_PTT_UNUSED_ENTRY(0), I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2), I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), I40E_PTT_UNUSED_ENTRY(4), I40E_PTT_UNUSED_ENTRY(5), I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), I40E_PTT_UNUSED_ENTRY(8), I40E_PTT_UNUSED_ENTRY(9), I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), /* Non Tunneled IPv4 */ I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(25), I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4), I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4), I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4), /* IPv4 --> IPv4 */ I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3), I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3), I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(32), I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4), I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), /* IPv4 --> IPv6 */ I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3), I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3), I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(39), I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4), I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), /* IPv4 --> GRE/NAT */ I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), /* IPv4 --> GRE/NAT --> IPv4 */ I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(47), I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), /* IPv4 --> GRE/NAT --> IPv6 */ I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(54), I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), /* IPv4 --> GRE/NAT --> MAC */ I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), /* IPv4 --> GRE/NAT --> MAC --> IPv4 */ I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(62), I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), /* IPv4 --> GRE/NAT -> MAC --> IPv6 */ I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(69), I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), /* IPv4 --> GRE/NAT --> MAC/VLAN */ I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */ I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(77), I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */ I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(84), I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), /* Non Tunneled IPv6 */ I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3), I40E_PTT_UNUSED_ENTRY(91), I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4), /* IPv6 --> IPv4 */ I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3), I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3), I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(98), I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4), I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), /* IPv6 --> IPv6 */ I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3), I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3), I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(105), I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4), I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT */ I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), /* IPv6 --> GRE/NAT -> IPv4 */ I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(113), I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT -> IPv6 */ I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(120), I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT -> MAC */ I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), /* IPv6 --> GRE/NAT -> MAC -> IPv4 */ I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(128), I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT -> MAC -> IPv6 */ I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(135), I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT -> MAC/VLAN */ I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */ I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(143), I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */ I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), I40E_PTT_UNUSED_ENTRY(150), I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), /* unused entries */ I40E_PTT_UNUSED_ENTRY(154), I40E_PTT_UNUSED_ENTRY(155), I40E_PTT_UNUSED_ENTRY(156), I40E_PTT_UNUSED_ENTRY(157), I40E_PTT_UNUSED_ENTRY(158), I40E_PTT_UNUSED_ENTRY(159), I40E_PTT_UNUSED_ENTRY(160), I40E_PTT_UNUSED_ENTRY(161), I40E_PTT_UNUSED_ENTRY(162), I40E_PTT_UNUSED_ENTRY(163), I40E_PTT_UNUSED_ENTRY(164), I40E_PTT_UNUSED_ENTRY(165), I40E_PTT_UNUSED_ENTRY(166), I40E_PTT_UNUSED_ENTRY(167), I40E_PTT_UNUSED_ENTRY(168), I40E_PTT_UNUSED_ENTRY(169), I40E_PTT_UNUSED_ENTRY(170), I40E_PTT_UNUSED_ENTRY(171), I40E_PTT_UNUSED_ENTRY(172), I40E_PTT_UNUSED_ENTRY(173), I40E_PTT_UNUSED_ENTRY(174), I40E_PTT_UNUSED_ENTRY(175), I40E_PTT_UNUSED_ENTRY(176), I40E_PTT_UNUSED_ENTRY(177), I40E_PTT_UNUSED_ENTRY(178), I40E_PTT_UNUSED_ENTRY(179), I40E_PTT_UNUSED_ENTRY(180), I40E_PTT_UNUSED_ENTRY(181), I40E_PTT_UNUSED_ENTRY(182), I40E_PTT_UNUSED_ENTRY(183), I40E_PTT_UNUSED_ENTRY(184), I40E_PTT_UNUSED_ENTRY(185), I40E_PTT_UNUSED_ENTRY(186), I40E_PTT_UNUSED_ENTRY(187), I40E_PTT_UNUSED_ENTRY(188), I40E_PTT_UNUSED_ENTRY(189), I40E_PTT_UNUSED_ENTRY(190), I40E_PTT_UNUSED_ENTRY(191), I40E_PTT_UNUSED_ENTRY(192), I40E_PTT_UNUSED_ENTRY(193), I40E_PTT_UNUSED_ENTRY(194), I40E_PTT_UNUSED_ENTRY(195), I40E_PTT_UNUSED_ENTRY(196), I40E_PTT_UNUSED_ENTRY(197), I40E_PTT_UNUSED_ENTRY(198), I40E_PTT_UNUSED_ENTRY(199), I40E_PTT_UNUSED_ENTRY(200), I40E_PTT_UNUSED_ENTRY(201), I40E_PTT_UNUSED_ENTRY(202), I40E_PTT_UNUSED_ENTRY(203), I40E_PTT_UNUSED_ENTRY(204), I40E_PTT_UNUSED_ENTRY(205), I40E_PTT_UNUSED_ENTRY(206), I40E_PTT_UNUSED_ENTRY(207), I40E_PTT_UNUSED_ENTRY(208), I40E_PTT_UNUSED_ENTRY(209), I40E_PTT_UNUSED_ENTRY(210), I40E_PTT_UNUSED_ENTRY(211), I40E_PTT_UNUSED_ENTRY(212), I40E_PTT_UNUSED_ENTRY(213), I40E_PTT_UNUSED_ENTRY(214), I40E_PTT_UNUSED_ENTRY(215), I40E_PTT_UNUSED_ENTRY(216), I40E_PTT_UNUSED_ENTRY(217), I40E_PTT_UNUSED_ENTRY(218), I40E_PTT_UNUSED_ENTRY(219), I40E_PTT_UNUSED_ENTRY(220), I40E_PTT_UNUSED_ENTRY(221), I40E_PTT_UNUSED_ENTRY(222), I40E_PTT_UNUSED_ENTRY(223), I40E_PTT_UNUSED_ENTRY(224), I40E_PTT_UNUSED_ENTRY(225), I40E_PTT_UNUSED_ENTRY(226), I40E_PTT_UNUSED_ENTRY(227), I40E_PTT_UNUSED_ENTRY(228), I40E_PTT_UNUSED_ENTRY(229), I40E_PTT_UNUSED_ENTRY(230), I40E_PTT_UNUSED_ENTRY(231), I40E_PTT_UNUSED_ENTRY(232), I40E_PTT_UNUSED_ENTRY(233), I40E_PTT_UNUSED_ENTRY(234), I40E_PTT_UNUSED_ENTRY(235), I40E_PTT_UNUSED_ENTRY(236), I40E_PTT_UNUSED_ENTRY(237), I40E_PTT_UNUSED_ENTRY(238), I40E_PTT_UNUSED_ENTRY(239), I40E_PTT_UNUSED_ENTRY(240), I40E_PTT_UNUSED_ENTRY(241), I40E_PTT_UNUSED_ENTRY(242), I40E_PTT_UNUSED_ENTRY(243), I40E_PTT_UNUSED_ENTRY(244), I40E_PTT_UNUSED_ENTRY(245), I40E_PTT_UNUSED_ENTRY(246), I40E_PTT_UNUSED_ENTRY(247), I40E_PTT_UNUSED_ENTRY(248), I40E_PTT_UNUSED_ENTRY(249), I40E_PTT_UNUSED_ENTRY(250), I40E_PTT_UNUSED_ENTRY(251), I40E_PTT_UNUSED_ENTRY(252), I40E_PTT_UNUSED_ENTRY(253), I40E_PTT_UNUSED_ENTRY(254), I40E_PTT_UNUSED_ENTRY(255) }; /** * i40e_validate_mac_addr - Validate unicast MAC address * @mac_addr: pointer to MAC address * * Tests a MAC address to ensure it is a valid Individual Address **/ enum i40e_status_code i40e_validate_mac_addr(u8 *mac_addr) { enum i40e_status_code status = I40E_SUCCESS; DEBUGFUNC("i40e_validate_mac_addr"); /* Broadcast addresses ARE multicast addresses * Make sure it is not a multicast address * Reject the zero address */ if (I40E_IS_MULTICAST(mac_addr) || (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)) status = I40E_ERR_INVALID_MAC_ADDR; return status; } #ifdef PF_DRIVER /** * i40e_init_shared_code - Initialize the shared code * @hw: pointer to hardware structure * * This assigns the MAC type and PHY code and inits the NVM. * Does not touch the hardware. This function must be called prior to any * other function in the shared code. The i40e_hw structure should be * memset to 0 prior to calling this function. The following fields in * hw structure should be filled in prior to calling this function: * hw_addr, back, device_id, vendor_id, subsystem_device_id, * subsystem_vendor_id, and revision_id **/ enum i40e_status_code i40e_init_shared_code(struct i40e_hw *hw) { enum i40e_status_code status = I40E_SUCCESS; u32 port, ari, func_rid; DEBUGFUNC("i40e_init_shared_code"); i40e_set_mac_type(hw); switch (hw->mac.type) { case I40E_MAC_XL710: break; default: return I40E_ERR_DEVICE_NOT_SUPPORTED; } hw->phy.get_link_info = true; /* Determine port number and PF number*/ port = (rd32(hw, I40E_PFGEN_PORTNUM) & I40E_PFGEN_PORTNUM_PORT_NUM_MASK) >> I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT; hw->port = (u8)port; ari = (rd32(hw, I40E_GLPCI_CAPSUP) & I40E_GLPCI_CAPSUP_ARI_EN_MASK) >> I40E_GLPCI_CAPSUP_ARI_EN_SHIFT; func_rid = rd32(hw, I40E_PF_FUNC_RID); if (ari) hw->pf_id = (u8)(func_rid & 0xff); else hw->pf_id = (u8)(func_rid & 0x7); status = i40e_init_nvm(hw); return status; } /** * i40e_aq_mac_address_read - Retrieve the MAC addresses * @hw: pointer to the hw struct * @flags: a return indicator of what addresses were added to the addr store * @addrs: the requestor's mac addr store * @cmd_details: pointer to command details structure or NULL **/ STATIC enum i40e_status_code i40e_aq_mac_address_read(struct i40e_hw *hw, u16 *flags, struct i40e_aqc_mac_address_read_data *addrs, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_mac_address_read *cmd_data = (struct i40e_aqc_mac_address_read *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_mac_address_read); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF); status = i40e_asq_send_command(hw, &desc, addrs, sizeof(*addrs), cmd_details); *flags = LE16_TO_CPU(cmd_data->command_flags); return status; } /** * i40e_aq_mac_address_write - Change the MAC addresses * @hw: pointer to the hw struct * @flags: indicates which MAC to be written * @mac_addr: address to write * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_mac_address_write(struct i40e_hw *hw, u16 flags, u8 *mac_addr, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_mac_address_write *cmd_data = (struct i40e_aqc_mac_address_write *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_mac_address_write); cmd_data->command_flags = CPU_TO_LE16(flags); cmd_data->mac_sah = CPU_TO_LE16((u16)mac_addr[0] << 8 | mac_addr[1]); cmd_data->mac_sal = CPU_TO_LE32(((u32)mac_addr[2] << 24) | ((u32)mac_addr[3] << 16) | ((u32)mac_addr[4] << 8) | mac_addr[5]); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_get_mac_addr - get MAC address * @hw: pointer to the HW structure * @mac_addr: pointer to MAC address * * Reads the adapter's MAC address from register **/ enum i40e_status_code i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr) { struct i40e_aqc_mac_address_read_data addrs; enum i40e_status_code status; u16 flags = 0; status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL); if (flags & I40E_AQC_LAN_ADDR_VALID) memcpy(mac_addr, &addrs.pf_lan_mac, sizeof(addrs.pf_lan_mac)); return status; } /** * i40e_get_port_mac_addr - get Port MAC address * @hw: pointer to the HW structure * @mac_addr: pointer to Port MAC address * * Reads the adapter's Port MAC address **/ enum i40e_status_code i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr) { struct i40e_aqc_mac_address_read_data addrs; enum i40e_status_code status; u16 flags = 0; status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL); if (status) return status; if (flags & I40E_AQC_PORT_ADDR_VALID) memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac)); else status = I40E_ERR_INVALID_MAC_ADDR; return status; } /** * i40e_pre_tx_queue_cfg - pre tx queue configure * @hw: pointer to the HW structure * @queue: target pf queue index * @enable: state change request * * Handles hw requirement to indicate intention to enable * or disable target queue. **/ void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable) { u32 abs_queue_idx = hw->func_caps.base_queue + queue; u32 reg_block = 0; u32 reg_val; if (abs_queue_idx >= 128) { reg_block = abs_queue_idx / 128; abs_queue_idx %= 128; } reg_val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block)); reg_val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK; reg_val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); if (enable) reg_val |= I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK; else reg_val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK; wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val); } /** * i40e_read_pba_string - Reads part number string from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number string from the EEPROM * @pba_num_size: part number string buffer length * * Reads the part number string from the EEPROM. **/ enum i40e_status_code i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num, u32 pba_num_size) { enum i40e_status_code status = I40E_SUCCESS; u16 pba_word = 0; u16 pba_size = 0; u16 pba_ptr = 0; u16 i = 0; status = i40e_read_nvm_word(hw, I40E_SR_PBA_FLAGS, &pba_word); if ((status != I40E_SUCCESS) || (pba_word != 0xFAFA)) { DEBUGOUT("Failed to read PBA flags or flag is invalid.\n"); return status; } status = i40e_read_nvm_word(hw, I40E_SR_PBA_BLOCK_PTR, &pba_ptr); if (status != I40E_SUCCESS) { DEBUGOUT("Failed to read PBA Block pointer.\n"); return status; } status = i40e_read_nvm_word(hw, pba_ptr, &pba_size); if (status != I40E_SUCCESS) { DEBUGOUT("Failed to read PBA Block size.\n"); return status; } /* Subtract one to get PBA word count (PBA Size word is included in * total size) */ pba_size--; if (pba_num_size < (((u32)pba_size * 2) + 1)) { DEBUGOUT("Buffer to small for PBA data.\n"); return I40E_ERR_PARAM; } for (i = 0; i < pba_size; i++) { status = i40e_read_nvm_word(hw, (pba_ptr + 1) + i, &pba_word); if (status != I40E_SUCCESS) { DEBUGOUT1("Failed to read PBA Block word %d.\n", i); return status; } pba_num[(i * 2)] = (pba_word >> 8) & 0xFF; pba_num[(i * 2) + 1] = pba_word & 0xFF; } pba_num[(pba_size * 2)] = '\0'; return status; } /** * i40e_get_media_type - Gets media type * @hw: pointer to the hardware structure **/ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) { enum i40e_media_type media; switch (hw->phy.link_info.phy_type) { case I40E_PHY_TYPE_10GBASE_SR: case I40E_PHY_TYPE_10GBASE_LR: case I40E_PHY_TYPE_1000BASE_SX: case I40E_PHY_TYPE_1000BASE_LX: case I40E_PHY_TYPE_40GBASE_SR4: case I40E_PHY_TYPE_40GBASE_LR4: media = I40E_MEDIA_TYPE_FIBER; break; case I40E_PHY_TYPE_100BASE_TX: case I40E_PHY_TYPE_1000BASE_T: case I40E_PHY_TYPE_10GBASE_T: media = I40E_MEDIA_TYPE_BASET; break; case I40E_PHY_TYPE_10GBASE_CR1_CU: case I40E_PHY_TYPE_40GBASE_CR4_CU: case I40E_PHY_TYPE_10GBASE_CR1: case I40E_PHY_TYPE_40GBASE_CR4: case I40E_PHY_TYPE_10GBASE_SFPP_CU: case I40E_PHY_TYPE_40GBASE_AOC: case I40E_PHY_TYPE_10GBASE_AOC: media = I40E_MEDIA_TYPE_DA; break; case I40E_PHY_TYPE_1000BASE_KX: case I40E_PHY_TYPE_10GBASE_KX4: case I40E_PHY_TYPE_10GBASE_KR: case I40E_PHY_TYPE_40GBASE_KR4: media = I40E_MEDIA_TYPE_BACKPLANE; break; case I40E_PHY_TYPE_SGMII: case I40E_PHY_TYPE_XAUI: case I40E_PHY_TYPE_XFI: case I40E_PHY_TYPE_XLAUI: case I40E_PHY_TYPE_XLPPI: default: media = I40E_MEDIA_TYPE_UNKNOWN; break; } return media; } #define I40E_PF_RESET_WAIT_COUNT 110 /** * i40e_pf_reset - Reset the PF * @hw: pointer to the hardware structure * * Assuming someone else has triggered a global reset, * assure the global reset is complete and then reset the PF **/ enum i40e_status_code i40e_pf_reset(struct i40e_hw *hw) { u32 cnt = 0; u32 cnt1 = 0; u32 reg = 0; u32 grst_del; /* Poll for Global Reset steady state in case of recent GRST. * The grst delay value is in 100ms units, and we'll wait a * couple counts longer to be sure we don't just miss the end. */ grst_del = (rd32(hw, I40E_GLGEN_RSTCTL) & I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >> I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; for (cnt = 0; cnt < grst_del + 2; cnt++) { reg = rd32(hw, I40E_GLGEN_RSTAT); if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) break; i40e_msec_delay(100); } if (reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK) { DEBUGOUT("Global reset polling failed to complete.\n"); return I40E_ERR_RESET_FAILED; } /* Now Wait for the FW to be ready */ for (cnt1 = 0; cnt1 < I40E_PF_RESET_WAIT_COUNT; cnt1++) { reg = rd32(hw, I40E_GLNVM_ULD); reg &= (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK); if (reg == (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK)) { DEBUGOUT1("Core and Global modules ready %d\n", cnt1); break; } i40e_msec_delay(10); } if (!(reg & (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK))) { DEBUGOUT("wait for FW Reset complete timedout\n"); DEBUGOUT1("I40E_GLNVM_ULD = 0x%x\n", reg); return I40E_ERR_RESET_FAILED; } /* If there was a Global Reset in progress when we got here, * we don't need to do the PF Reset */ if (!cnt) { reg = rd32(hw, I40E_PFGEN_CTRL); wr32(hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); for (cnt = 0; cnt < I40E_PF_RESET_WAIT_COUNT; cnt++) { reg = rd32(hw, I40E_PFGEN_CTRL); if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK)) break; i40e_msec_delay(1); } if (reg & I40E_PFGEN_CTRL_PFSWR_MASK) { DEBUGOUT("PF reset polling failed to complete.\n"); return I40E_ERR_RESET_FAILED; } } i40e_clear_pxe_mode(hw); return I40E_SUCCESS; } /** * i40e_clear_hw - clear out any left over hw state * @hw: pointer to the hw struct * * Clear queues and interrupts, typically called at init time, * but after the capabilities have been found so we know how many * queues and msix vectors have been allocated. **/ void i40e_clear_hw(struct i40e_hw *hw) { u32 num_queues, base_queue; u32 num_pf_int; u32 num_vf_int; u32 num_vfs; u32 i, j; u32 val; u32 eol = 0x7ff; /* get number of interrupts, queues, and vfs */ val = rd32(hw, I40E_GLPCI_CNF2); num_pf_int = (val & I40E_GLPCI_CNF2_MSI_X_PF_N_MASK) >> I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT; num_vf_int = (val & I40E_GLPCI_CNF2_MSI_X_VF_N_MASK) >> I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT; val = rd32(hw, I40E_PFLAN_QALLOC); base_queue = (val & I40E_PFLAN_QALLOC_FIRSTQ_MASK) >> I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >> I40E_PFLAN_QALLOC_LASTQ_SHIFT; if (val & I40E_PFLAN_QALLOC_VALID_MASK) num_queues = (j - base_queue) + 1; else num_queues = 0; val = rd32(hw, I40E_PF_VT_PFALLOC); i = (val & I40E_PF_VT_PFALLOC_FIRSTVF_MASK) >> I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT; j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >> I40E_PF_VT_PFALLOC_LASTVF_SHIFT; if (val & I40E_PF_VT_PFALLOC_VALID_MASK) num_vfs = (j - i) + 1; else num_vfs = 0; /* stop all the interrupts */ wr32(hw, I40E_PFINT_ICR0_ENA, 0); val = 0x3 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT; for (i = 0; i < num_pf_int - 2; i++) wr32(hw, I40E_PFINT_DYN_CTLN(i), val); /* Set the FIRSTQ_INDX field to 0x7FF in PFINT_LNKLSTx */ val = eol << I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT; wr32(hw, I40E_PFINT_LNKLST0, val); for (i = 0; i < num_pf_int - 2; i++) wr32(hw, I40E_PFINT_LNKLSTN(i), val); val = eol << I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT; for (i = 0; i < num_vfs; i++) wr32(hw, I40E_VPINT_LNKLST0(i), val); for (i = 0; i < num_vf_int - 2; i++) wr32(hw, I40E_VPINT_LNKLSTN(i), val); /* warn the HW of the coming Tx disables */ for (i = 0; i < num_queues; i++) { u32 abs_queue_idx = base_queue + i; u32 reg_block = 0; if (abs_queue_idx >= 128) { reg_block = abs_queue_idx / 128; abs_queue_idx %= 128; } val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block)); val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK; val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK; wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), val); } i40e_usec_delay(400); /* stop all the queues */ for (i = 0; i < num_queues; i++) { wr32(hw, I40E_QINT_TQCTL(i), 0); wr32(hw, I40E_QTX_ENA(i), 0); wr32(hw, I40E_QINT_RQCTL(i), 0); wr32(hw, I40E_QRX_ENA(i), 0); } /* short wait for all queue disables to settle */ i40e_usec_delay(50); } /** * i40e_clear_pxe_mode - clear pxe operations mode * @hw: pointer to the hw struct * * Make sure all PXE mode settings are cleared, including things * like descriptor fetch/write-back mode. **/ void i40e_clear_pxe_mode(struct i40e_hw *hw) { if (i40e_check_asq_alive(hw)) i40e_aq_clear_pxe_mode(hw, NULL); } /** * i40e_led_is_mine - helper to find matching led * @hw: pointer to the hw struct * @idx: index into GPIO registers * * returns: 0 if no match, otherwise the value of the GPIO_CTL register */ static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx) { u32 gpio_val = 0; u32 port; if (!hw->func_caps.led[idx]) return 0; gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx)); port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; /* if PRT_NUM_NA is 1 then this LED is not port specific, OR * if it is not our port then ignore */ if ((gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK) || (port != hw->port)) return 0; return gpio_val; } #define I40E_COMBINED_ACTIVITY 0xA #define I40E_FILTER_ACTIVITY 0xE #define I40E_LINK_ACTIVITY 0xC #define I40E_MAC_ACTIVITY 0xD #define I40E_LED0 22 /** * i40e_led_get - return current on/off mode * @hw: pointer to the hw struct * * The value returned is the 'mode' field as defined in the * GPIO register definitions: 0x0 = off, 0xf = on, and other * values are variations of possible behaviors relating to * blink, link, and wire. **/ u32 i40e_led_get(struct i40e_hw *hw) { u32 current_mode = 0; u32 mode = 0; int i; /* as per the documentation GPIO 22-29 are the LED * GPIO pins named LED0..LED7 */ for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) { u32 gpio_val = i40e_led_is_mine(hw, i); if (!gpio_val) continue; /* ignore gpio LED src mode entries related to the activity LEDs */ current_mode = ((gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >> I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT); switch (current_mode) { case I40E_COMBINED_ACTIVITY: case I40E_FILTER_ACTIVITY: case I40E_MAC_ACTIVITY: continue; default: break; } mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >> I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT; break; } return mode; } /** * i40e_led_set - set new on/off mode * @hw: pointer to the hw struct * @mode: 0=off, 0xf=on (else see manual for mode details) * @blink: true if the LED should blink when on, false if steady * * if this function is used to turn on the blink it should * be used to disable the blink when restoring the original state. **/ void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink) { u32 current_mode = 0; int i; if (mode & 0xfffffff0) DEBUGOUT1("invalid mode passed in %X\n", mode); /* as per the documentation GPIO 22-29 are the LED * GPIO pins named LED0..LED7 */ for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) { u32 gpio_val = i40e_led_is_mine(hw, i); if (!gpio_val) continue; /* ignore gpio LED src mode entries related to the activity LEDs */ current_mode = ((gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >> I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT); switch (current_mode) { case I40E_COMBINED_ACTIVITY: case I40E_FILTER_ACTIVITY: case I40E_MAC_ACTIVITY: continue; default: break; } gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK; /* this & is a bit of paranoia, but serves as a range check */ gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK); if (mode == I40E_LINK_ACTIVITY) blink = false; if (blink) gpio_val |= (1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT); else gpio_val &= ~(1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT); wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val); break; } } /* Admin command wrappers */ /** * i40e_aq_get_phy_capabilities * @hw: pointer to the hw struct * @abilities: structure for PHY capabilities to be filled * @qualified_modules: report Qualified Modules * @report_init: report init capabilities (active are default) * @cmd_details: pointer to command details structure or NULL * * Returns the various PHY abilities supported on the Port. **/ enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw, bool qualified_modules, bool report_init, struct i40e_aq_get_phy_abilities_resp *abilities, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; enum i40e_status_code status; u16 abilities_size = sizeof(struct i40e_aq_get_phy_abilities_resp); if (!abilities) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_phy_abilities); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (abilities_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); if (qualified_modules) desc.params.external.param0 |= CPU_TO_LE32(I40E_AQ_PHY_REPORT_QUALIFIED_MODULES); if (report_init) desc.params.external.param0 |= CPU_TO_LE32(I40E_AQ_PHY_REPORT_INITIAL_VALUES); status = i40e_asq_send_command(hw, &desc, abilities, abilities_size, cmd_details); if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) status = I40E_ERR_UNKNOWN_PHY; return status; } /** * i40e_aq_set_phy_config * @hw: pointer to the hw struct * @config: structure with PHY configuration to be set * @cmd_details: pointer to command details structure or NULL * * Set the various PHY configuration parameters * supported on the Port.One or more of the Set PHY config parameters may be * ignored in an MFP mode as the PF may not have the privilege to set some * of the PHY Config parameters. This status will be indicated by the * command response. **/ enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, struct i40e_aq_set_phy_config *config, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aq_set_phy_config *cmd = (struct i40e_aq_set_phy_config *)&desc.params.raw; enum i40e_status_code status; if (!config) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_phy_config); *cmd = *config; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_set_fc * @hw: pointer to the hw struct * * Set the requested flow control mode using set_phy_config. **/ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, bool atomic_restart) { enum i40e_fc_mode fc_mode = hw->fc.requested_mode; struct i40e_aq_get_phy_abilities_resp abilities; struct i40e_aq_set_phy_config config; enum i40e_status_code status; u8 pause_mask = 0x0; *aq_failures = 0x0; switch (fc_mode) { case I40E_FC_FULL: pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX; pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX; break; case I40E_FC_RX_PAUSE: pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_RX; break; case I40E_FC_TX_PAUSE: pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX; break; default: break; } /* Get the current phy config */ status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, NULL); if (status) { *aq_failures |= I40E_SET_FC_AQ_FAIL_GET; return status; } memset(&config, 0, sizeof(config)); /* clear the old pause settings */ config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) & ~(I40E_AQ_PHY_FLAG_PAUSE_RX); /* set the new abilities */ config.abilities |= pause_mask; /* If the abilities have changed, then set the new config */ if (config.abilities != abilities.abilities) { /* Auto restart link so settings take effect */ if (atomic_restart) config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; /* Copy over all the old settings */ config.phy_type = abilities.phy_type; config.link_speed = abilities.link_speed; config.eee_capability = abilities.eee_capability; config.eeer = abilities.eeer_val; config.low_power_ctrl = abilities.d3_lpan; status = i40e_aq_set_phy_config(hw, &config, NULL); if (status) *aq_failures |= I40E_SET_FC_AQ_FAIL_SET; } /* Update the link info */ status = i40e_aq_get_link_info(hw, true, NULL, NULL); if (status) { /* Wait a little bit (on 40G cards it sometimes takes a really * long time for link to come back from the atomic reset) * and try once more */ i40e_msec_delay(1000); status = i40e_aq_get_link_info(hw, true, NULL, NULL); } if (status) *aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE; return status; } /** * i40e_aq_set_mac_config * @hw: pointer to the hw struct * @max_frame_size: Maximum Frame Size to be supported by the port * @crc_en: Tell HW to append a CRC to outgoing frames * @pacing: Pacing configurations * @cmd_details: pointer to command details structure or NULL * * Configure MAC settings for frame size, jumbo frame support and the * addition of a CRC by the hardware. **/ enum i40e_status_code i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size, bool crc_en, u16 pacing, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aq_set_mac_config *cmd = (struct i40e_aq_set_mac_config *)&desc.params.raw; enum i40e_status_code status; if (max_frame_size == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_mac_config); cmd->max_frame_size = CPU_TO_LE16(max_frame_size); cmd->params = ((u8)pacing & 0x0F) << 3; if (crc_en) cmd->params |= I40E_AQ_SET_MAC_CONFIG_CRC_EN; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_clear_pxe_mode * @hw: pointer to the hw struct * @cmd_details: pointer to command details structure or NULL * * Tell the firmware that the driver is taking over from PXE **/ enum i40e_status_code i40e_aq_clear_pxe_mode(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details) { enum i40e_status_code status; struct i40e_aq_desc desc; struct i40e_aqc_clear_pxe *cmd = (struct i40e_aqc_clear_pxe *)&desc.params.raw; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_clear_pxe_mode); cmd->rx_cnt = 0x2; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); wr32(hw, I40E_GLLAN_RCTL_0, 0x1); return status; } /** * i40e_aq_set_link_restart_an * @hw: pointer to the hw struct * @enable_link: if true: enable link, if false: disable link * @cmd_details: pointer to command details structure or NULL * * Sets up the link and restarts the Auto-Negotiation over the link. **/ enum i40e_status_code i40e_aq_set_link_restart_an(struct i40e_hw *hw, bool enable_link, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_link_restart_an *cmd = (struct i40e_aqc_set_link_restart_an *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_link_restart_an); cmd->command = I40E_AQ_PHY_RESTART_AN; if (enable_link) cmd->command |= I40E_AQ_PHY_LINK_ENABLE; else cmd->command &= ~I40E_AQ_PHY_LINK_ENABLE; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_link_info * @hw: pointer to the hw struct * @enable_lse: enable/disable LinkStatusEvent reporting * @link: pointer to link status structure - optional * @cmd_details: pointer to command details structure or NULL * * Returns the link status of the adapter. **/ enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw, bool enable_lse, struct i40e_link_status *link, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_get_link_status *resp = (struct i40e_aqc_get_link_status *)&desc.params.raw; struct i40e_link_status *hw_link_info = &hw->phy.link_info; enum i40e_status_code status; bool tx_pause, rx_pause; u16 command_flags; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_link_status); if (enable_lse) command_flags = I40E_AQ_LSE_ENABLE; else command_flags = I40E_AQ_LSE_DISABLE; resp->command_flags = CPU_TO_LE16(command_flags); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status != I40E_SUCCESS) goto aq_get_link_info_exit; /* save off old link status information */ i40e_memcpy(&hw->phy.link_info_old, hw_link_info, sizeof(*hw_link_info), I40E_NONDMA_TO_NONDMA); /* update link status */ hw_link_info->phy_type = (enum i40e_aq_phy_type)resp->phy_type; hw->phy.media_type = i40e_get_media_type(hw); hw_link_info->link_speed = (enum i40e_aq_link_speed)resp->link_speed; hw_link_info->link_info = resp->link_info; hw_link_info->an_info = resp->an_info; hw_link_info->ext_info = resp->ext_info; hw_link_info->loopback = resp->loopback; hw_link_info->max_frame_size = LE16_TO_CPU(resp->max_frame_size); hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK; /* update fc info */ tx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_TX); rx_pause = !!(resp->an_info & I40E_AQ_LINK_PAUSE_RX); if (tx_pause & rx_pause) hw->fc.current_mode = I40E_FC_FULL; else if (tx_pause) hw->fc.current_mode = I40E_FC_TX_PAUSE; else if (rx_pause) hw->fc.current_mode = I40E_FC_RX_PAUSE; else hw->fc.current_mode = I40E_FC_NONE; if (resp->config & I40E_AQ_CONFIG_CRC_ENA) hw_link_info->crc_enable = true; else hw_link_info->crc_enable = false; if (resp->command_flags & CPU_TO_LE16(I40E_AQ_LSE_ENABLE)) hw_link_info->lse_enable = true; else hw_link_info->lse_enable = false; if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 && hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE) hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU; /* save link status information */ if (link) i40e_memcpy(link, hw_link_info, sizeof(*hw_link_info), I40E_NONDMA_TO_NONDMA); /* flag cleared so helper functions don't call AQ again */ hw->phy.get_link_info = false; aq_get_link_info_exit: return status; } /** * i40e_aq_set_phy_int_mask * @hw: pointer to the hw struct * @mask: interrupt mask to be set * @cmd_details: pointer to command details structure or NULL * * Set link interrupt mask. **/ enum i40e_status_code i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_phy_int_mask *cmd = (struct i40e_aqc_set_phy_int_mask *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_phy_int_mask); cmd->event_mask = CPU_TO_LE16(mask); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_local_advt_reg * @hw: pointer to the hw struct * @advt_reg: local AN advertisement register value * @cmd_details: pointer to command details structure or NULL * * Get the Local AN advertisement register value. **/ enum i40e_status_code i40e_aq_get_local_advt_reg(struct i40e_hw *hw, u64 *advt_reg, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_an_advt_reg *resp = (struct i40e_aqc_an_advt_reg *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_local_advt_reg); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status != I40E_SUCCESS) goto aq_get_local_advt_reg_exit; *advt_reg = (u64)(LE16_TO_CPU(resp->local_an_reg1)) << 32; *advt_reg |= LE32_TO_CPU(resp->local_an_reg0); aq_get_local_advt_reg_exit: return status; } /** * i40e_aq_set_local_advt_reg * @hw: pointer to the hw struct * @advt_reg: local AN advertisement register value * @cmd_details: pointer to command details structure or NULL * * Get the Local AN advertisement register value. **/ enum i40e_status_code i40e_aq_set_local_advt_reg(struct i40e_hw *hw, u64 advt_reg, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_an_advt_reg *cmd = (struct i40e_aqc_an_advt_reg *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_local_advt_reg); cmd->local_an_reg0 = CPU_TO_LE32(I40E_LO_DWORD(advt_reg)); cmd->local_an_reg1 = CPU_TO_LE16(I40E_HI_DWORD(advt_reg)); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_partner_advt * @hw: pointer to the hw struct * @advt_reg: AN partner advertisement register value * @cmd_details: pointer to command details structure or NULL * * Get the link partner AN advertisement register value. **/ enum i40e_status_code i40e_aq_get_partner_advt(struct i40e_hw *hw, u64 *advt_reg, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_an_advt_reg *resp = (struct i40e_aqc_an_advt_reg *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_partner_advt); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status != I40E_SUCCESS) goto aq_get_partner_advt_exit; *advt_reg = (u64)(LE16_TO_CPU(resp->local_an_reg1)) << 32; *advt_reg |= LE32_TO_CPU(resp->local_an_reg0); aq_get_partner_advt_exit: return status; } /** * i40e_aq_set_lb_modes * @hw: pointer to the hw struct * @lb_modes: loopback mode to be set * @cmd_details: pointer to command details structure or NULL * * Sets loopback modes. **/ enum i40e_status_code i40e_aq_set_lb_modes(struct i40e_hw *hw, u16 lb_modes, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_lb_mode *cmd = (struct i40e_aqc_set_lb_mode *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_lb_modes); cmd->lb_mode = CPU_TO_LE16(lb_modes); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_set_phy_debug * @hw: pointer to the hw struct * @cmd_flags: debug command flags * @cmd_details: pointer to command details structure or NULL * * Reset the external PHY. **/ enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_phy_debug *cmd = (struct i40e_aqc_set_phy_debug *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_phy_debug); cmd->command_flags = cmd_flags; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_add_vsi * @hw: pointer to the hw struct * @vsi_ctx: pointer to a vsi context struct * @cmd_details: pointer to command details structure or NULL * * Add a VSI context to the hardware. **/ enum i40e_status_code i40e_aq_add_vsi(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_get_update_vsi *cmd = (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw; struct i40e_aqc_add_get_update_vsi_completion *resp = (struct i40e_aqc_add_get_update_vsi_completion *) &desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_vsi); cmd->uplink_seid = CPU_TO_LE16(vsi_ctx->uplink_seid); cmd->connection_type = vsi_ctx->connection_type; cmd->vf_id = vsi_ctx->vf_num; cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info, sizeof(vsi_ctx->info), cmd_details); if (status != I40E_SUCCESS) goto aq_add_vsi_exit; vsi_ctx->seid = LE16_TO_CPU(resp->seid); vsi_ctx->vsi_number = LE16_TO_CPU(resp->vsi_number); vsi_ctx->vsis_allocated = LE16_TO_CPU(resp->vsi_used); vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); aq_add_vsi_exit: return status; } /** * i40e_aq_set_default_vsi * @hw: pointer to the hw struct * @seid: vsi number * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 seid, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_vsi_promiscuous_modes *cmd = (struct i40e_aqc_set_vsi_promiscuous_modes *) &desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_vsi_promiscuous_modes); cmd->promiscuous_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_DEFAULT); cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_DEFAULT); cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_set_vsi_unicast_promiscuous * @hw: pointer to the hw struct * @seid: vsi number * @set: set unicast promiscuous enable/disable * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, u16 seid, bool set, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_vsi_promiscuous_modes *cmd = (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; enum i40e_status_code status; u16 flags = 0; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_vsi_promiscuous_modes); if (set) flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST; cmd->promiscuous_flags = CPU_TO_LE16(flags); cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_UNICAST); cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_set_vsi_multicast_promiscuous * @hw: pointer to the hw struct * @seid: vsi number * @set: set multicast promiscuous enable/disable * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw, u16 seid, bool set, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_vsi_promiscuous_modes *cmd = (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; enum i40e_status_code status; u16 flags = 0; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_vsi_promiscuous_modes); if (set) flags |= I40E_AQC_SET_VSI_PROMISC_MULTICAST; cmd->promiscuous_flags = CPU_TO_LE16(flags); cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_MULTICAST); cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_set_vsi_broadcast * @hw: pointer to the hw struct * @seid: vsi number * @set_filter: true to set filter, false to clear filter * @cmd_details: pointer to command details structure or NULL * * Set or clear the broadcast promiscuous flag (filter) for a given VSI. **/ enum i40e_status_code i40e_aq_set_vsi_broadcast(struct i40e_hw *hw, u16 seid, bool set_filter, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_set_vsi_promiscuous_modes *cmd = (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_vsi_promiscuous_modes); if (set_filter) cmd->promiscuous_flags |= CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_BROADCAST); else cmd->promiscuous_flags &= CPU_TO_LE16(~I40E_AQC_SET_VSI_PROMISC_BROADCAST); cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_BROADCAST); cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_get_vsi_params - get VSI configuration info * @hw: pointer to the hw struct * @vsi_ctx: pointer to a vsi context struct * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_get_vsi_params(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_get_update_vsi *cmd = (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw; struct i40e_aqc_add_get_update_vsi_completion *resp = (struct i40e_aqc_add_get_update_vsi_completion *) &desc.params.raw; enum i40e_status_code status; UNREFERENCED_1PARAMETER(cmd_details); i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_vsi_parameters); cmd->uplink_seid = CPU_TO_LE16(vsi_ctx->seid); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info, sizeof(vsi_ctx->info), NULL); if (status != I40E_SUCCESS) goto aq_get_vsi_params_exit; vsi_ctx->seid = LE16_TO_CPU(resp->seid); vsi_ctx->vsi_number = LE16_TO_CPU(resp->vsi_number); vsi_ctx->vsis_allocated = LE16_TO_CPU(resp->vsi_used); vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); aq_get_vsi_params_exit: return status; } /** * i40e_aq_update_vsi_params * @hw: pointer to the hw struct * @vsi_ctx: pointer to a vsi context struct * @cmd_details: pointer to command details structure or NULL * * Update a VSI context. **/ enum i40e_status_code i40e_aq_update_vsi_params(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_get_update_vsi *cmd = (struct i40e_aqc_add_get_update_vsi *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_update_vsi_parameters); cmd->uplink_seid = CPU_TO_LE16(vsi_ctx->seid); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info, sizeof(vsi_ctx->info), cmd_details); return status; } /** * i40e_aq_get_switch_config * @hw: pointer to the hardware structure * @buf: pointer to the result buffer * @buf_size: length of input buffer * @start_seid: seid to start for the report, 0 == beginning * @cmd_details: pointer to command details structure or NULL * * Fill the buf with switch configuration returned from AdminQ command **/ enum i40e_status_code i40e_aq_get_switch_config(struct i40e_hw *hw, struct i40e_aqc_get_switch_config_resp *buf, u16 buf_size, u16 *start_seid, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_switch_seid *scfg = (struct i40e_aqc_switch_seid *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_switch_config); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); scfg->seid = CPU_TO_LE16(*start_seid); status = i40e_asq_send_command(hw, &desc, buf, buf_size, cmd_details); *start_seid = LE16_TO_CPU(scfg->seid); return status; } /** * i40e_aq_get_firmware_version * @hw: pointer to the hw struct * @fw_major_version: firmware major version * @fw_minor_version: firmware minor version * @fw_build: firmware build number * @api_major_version: major queue version * @api_minor_version: minor queue version * @cmd_details: pointer to command details structure or NULL * * Get the firmware version from the admin queue commands **/ enum i40e_status_code i40e_aq_get_firmware_version(struct i40e_hw *hw, u16 *fw_major_version, u16 *fw_minor_version, u32 *fw_build, u16 *api_major_version, u16 *api_minor_version, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_get_version *resp = (struct i40e_aqc_get_version *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_version); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status == I40E_SUCCESS) { if (fw_major_version != NULL) *fw_major_version = LE16_TO_CPU(resp->fw_major); if (fw_minor_version != NULL) *fw_minor_version = LE16_TO_CPU(resp->fw_minor); if (fw_build != NULL) *fw_build = LE32_TO_CPU(resp->fw_build); if (api_major_version != NULL) *api_major_version = LE16_TO_CPU(resp->api_major); if (api_minor_version != NULL) *api_minor_version = LE16_TO_CPU(resp->api_minor); /* A workaround to fix the API version in SW */ if (api_major_version && api_minor_version && fw_major_version && fw_minor_version && ((*api_major_version == 1) && (*api_minor_version == 1)) && (((*fw_major_version == 4) && (*fw_minor_version >= 2)) || (*fw_major_version > 4))) *api_minor_version = 2; } return status; } /** * i40e_aq_send_driver_version * @hw: pointer to the hw struct * @dv: driver's major, minor version * @cmd_details: pointer to command details structure or NULL * * Send the driver version to the firmware **/ enum i40e_status_code i40e_aq_send_driver_version(struct i40e_hw *hw, struct i40e_driver_version *dv, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_driver_version *cmd = (struct i40e_aqc_driver_version *)&desc.params.raw; enum i40e_status_code status; u16 len; if (dv == NULL) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_driver_version); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD); cmd->driver_major_ver = dv->major_version; cmd->driver_minor_ver = dv->minor_version; cmd->driver_build_ver = dv->build_version; cmd->driver_subbuild_ver = dv->subbuild_version; len = 0; while (len < sizeof(dv->driver_string) && (dv->driver_string[len] < 0x80) && dv->driver_string[len]) len++; status = i40e_asq_send_command(hw, &desc, dv->driver_string, len, cmd_details); return status; } /** * i40e_get_link_status - get status of the HW network link * @hw: pointer to the hw struct * * Returns true if link is up, false if link is down. * * Side effect: LinkStatusEvent reporting becomes enabled **/ bool i40e_get_link_status(struct i40e_hw *hw) { enum i40e_status_code status = I40E_SUCCESS; bool link_status = false; if (hw->phy.get_link_info) { status = i40e_aq_get_link_info(hw, true, NULL, NULL); if (status != I40E_SUCCESS) goto i40e_get_link_status_exit; } link_status = hw->phy.link_info.link_info & I40E_AQ_LINK_UP; i40e_get_link_status_exit: return link_status; } /** * i40e_get_link_speed * @hw: pointer to the hw struct * * Returns the link speed of the adapter. **/ enum i40e_aq_link_speed i40e_get_link_speed(struct i40e_hw *hw) { enum i40e_aq_link_speed speed = I40E_LINK_SPEED_UNKNOWN; enum i40e_status_code status = I40E_SUCCESS; if (hw->phy.get_link_info) { status = i40e_aq_get_link_info(hw, true, NULL, NULL); if (status != I40E_SUCCESS) goto i40e_link_speed_exit; } speed = hw->phy.link_info.link_speed; i40e_link_speed_exit: return speed; } /** * i40e_aq_add_veb - Insert a VEB between the VSI and the MAC * @hw: pointer to the hw struct * @uplink_seid: the MAC or other gizmo SEID * @downlink_seid: the VSI SEID * @enabled_tc: bitmap of TCs to be enabled * @default_port: true for default port VSI, false for control port * @enable_l2_filtering: true to add L2 filter table rules to regular forwarding rules for cloud support * @veb_seid: pointer to where to put the resulting VEB SEID * @cmd_details: pointer to command details structure or NULL * * This asks the FW to add a VEB between the uplink and downlink * elements. If the uplink SEID is 0, this will be a floating VEB. **/ enum i40e_status_code i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, bool default_port, bool enable_l2_filtering, u16 *veb_seid, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_veb *cmd = (struct i40e_aqc_add_veb *)&desc.params.raw; struct i40e_aqc_add_veb_completion *resp = (struct i40e_aqc_add_veb_completion *)&desc.params.raw; enum i40e_status_code status; u16 veb_flags = 0; /* SEIDs need to either both be set or both be 0 for floating VEB */ if (!!uplink_seid != !!downlink_seid) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_veb); cmd->uplink_seid = CPU_TO_LE16(uplink_seid); cmd->downlink_seid = CPU_TO_LE16(downlink_seid); cmd->enable_tcs = enabled_tc; if (!uplink_seid) veb_flags |= I40E_AQC_ADD_VEB_FLOATING; if (default_port) veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT; else veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA; if (enable_l2_filtering) veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER; cmd->veb_flags = CPU_TO_LE16(veb_flags); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status && veb_seid) *veb_seid = LE16_TO_CPU(resp->veb_seid); return status; } /** * i40e_aq_get_veb_parameters - Retrieve VEB parameters * @hw: pointer to the hw struct * @veb_seid: the SEID of the VEB to query * @switch_id: the uplink switch id * @floating: set to true if the VEB is floating * @statistic_index: index of the stats counter block for this VEB * @vebs_used: number of VEB's used by function * @vebs_free: total VEB's not reserved by any function * @cmd_details: pointer to command details structure or NULL * * This retrieves the parameters for a particular VEB, specified by * uplink_seid, and returns them to the caller. **/ enum i40e_status_code i40e_aq_get_veb_parameters(struct i40e_hw *hw, u16 veb_seid, u16 *switch_id, bool *floating, u16 *statistic_index, u16 *vebs_used, u16 *vebs_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_get_veb_parameters_completion *cmd_resp = (struct i40e_aqc_get_veb_parameters_completion *) &desc.params.raw; enum i40e_status_code status; if (veb_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_veb_parameters); cmd_resp->seid = CPU_TO_LE16(veb_seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status) goto get_veb_exit; if (switch_id) *switch_id = LE16_TO_CPU(cmd_resp->switch_id); if (statistic_index) *statistic_index = LE16_TO_CPU(cmd_resp->statistic_index); if (vebs_used) *vebs_used = LE16_TO_CPU(cmd_resp->vebs_used); if (vebs_free) *vebs_free = LE16_TO_CPU(cmd_resp->vebs_free); if (floating) { u16 flags = LE16_TO_CPU(cmd_resp->veb_flags); if (flags & I40E_AQC_ADD_VEB_FLOATING) *floating = true; else *floating = false; } get_veb_exit: return status; } /** * i40e_aq_add_macvlan * @hw: pointer to the hw struct * @seid: VSI for the mac address * @mv_list: list of macvlans to be added * @count: length of the list * @cmd_details: pointer to command details structure or NULL * * Add MAC/VLAN addresses to the HW filtering **/ enum i40e_status_code i40e_aq_add_macvlan(struct i40e_hw *hw, u16 seid, struct i40e_aqc_add_macvlan_element_data *mv_list, u16 count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_macvlan *cmd = (struct i40e_aqc_macvlan *)&desc.params.raw; enum i40e_status_code status; u16 buf_size; if (count == 0 || !mv_list || !hw) return I40E_ERR_PARAM; buf_size = count * sizeof(*mv_list); /* prep the rest of the request */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_macvlan); cmd->num_addresses = CPU_TO_LE16(count); cmd->seid[0] = CPU_TO_LE16(I40E_AQC_MACVLAN_CMD_SEID_VALID | seid); cmd->seid[1] = 0; cmd->seid[2] = 0; desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, mv_list, buf_size, cmd_details); return status; } /** * i40e_aq_remove_macvlan * @hw: pointer to the hw struct * @seid: VSI for the mac address * @mv_list: list of macvlans to be removed * @count: length of the list * @cmd_details: pointer to command details structure or NULL * * Remove MAC/VLAN addresses from the HW filtering **/ enum i40e_status_code i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid, struct i40e_aqc_remove_macvlan_element_data *mv_list, u16 count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_macvlan *cmd = (struct i40e_aqc_macvlan *)&desc.params.raw; enum i40e_status_code status; u16 buf_size; if (count == 0 || !mv_list || !hw) return I40E_ERR_PARAM; buf_size = count * sizeof(*mv_list); /* prep the rest of the request */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_macvlan); cmd->num_addresses = CPU_TO_LE16(count); cmd->seid[0] = CPU_TO_LE16(I40E_AQC_MACVLAN_CMD_SEID_VALID | seid); cmd->seid[1] = 0; cmd->seid[2] = 0; desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, mv_list, buf_size, cmd_details); return status; } /** * i40e_aq_add_vlan - Add VLAN ids to the HW filtering * @hw: pointer to the hw struct * @seid: VSI for the vlan filters * @v_list: list of vlan filters to be added * @count: length of the list * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_add_vlan(struct i40e_hw *hw, u16 seid, struct i40e_aqc_add_remove_vlan_element_data *v_list, u8 count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_macvlan *cmd = (struct i40e_aqc_macvlan *)&desc.params.raw; enum i40e_status_code status; u16 buf_size; if (count == 0 || !v_list || !hw) return I40E_ERR_PARAM; buf_size = count * sizeof(*v_list); /* prep the rest of the request */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_vlan); cmd->num_addresses = CPU_TO_LE16(count); cmd->seid[0] = CPU_TO_LE16(seid | I40E_AQC_MACVLAN_CMD_SEID_VALID); cmd->seid[1] = 0; cmd->seid[2] = 0; desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, v_list, buf_size, cmd_details); return status; } /** * i40e_aq_remove_vlan - Remove VLANs from the HW filtering * @hw: pointer to the hw struct * @seid: VSI for the vlan filters * @v_list: list of macvlans to be removed * @count: length of the list * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_remove_vlan(struct i40e_hw *hw, u16 seid, struct i40e_aqc_add_remove_vlan_element_data *v_list, u8 count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_macvlan *cmd = (struct i40e_aqc_macvlan *)&desc.params.raw; enum i40e_status_code status; u16 buf_size; if (count == 0 || !v_list || !hw) return I40E_ERR_PARAM; buf_size = count * sizeof(*v_list); /* prep the rest of the request */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_vlan); cmd->num_addresses = CPU_TO_LE16(count); cmd->seid[0] = CPU_TO_LE16(seid | I40E_AQC_MACVLAN_CMD_SEID_VALID); cmd->seid[1] = 0; cmd->seid[2] = 0; desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, v_list, buf_size, cmd_details); return status; } /** * i40e_aq_send_msg_to_vf * @hw: pointer to the hardware structure * @vfid: vf id to send msg * @v_opcode: opcodes for VF-PF communication * @v_retval: return error code * @msg: pointer to the msg buffer * @msglen: msg length * @cmd_details: pointer to command details * * send msg to vf **/ enum i40e_status_code i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, u8 *msg, u16 msglen, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_pf_vf_message *cmd = (struct i40e_aqc_pf_vf_message *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_vf); cmd->id = CPU_TO_LE32(vfid); desc.cookie_high = CPU_TO_LE32(v_opcode); desc.cookie_low = CPU_TO_LE32(v_retval); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_SI); if (msglen) { desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (msglen > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(msglen); } status = i40e_asq_send_command(hw, &desc, msg, msglen, cmd_details); return status; } /** * i40e_aq_debug_read_register * @hw: pointer to the hw struct * @reg_addr: register address * @reg_val: register value * @cmd_details: pointer to command details structure or NULL * * Read the register using the admin queue commands **/ enum i40e_status_code i40e_aq_debug_read_register(struct i40e_hw *hw, u32 reg_addr, u64 *reg_val, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_debug_reg_read_write *cmd_resp = (struct i40e_aqc_debug_reg_read_write *)&desc.params.raw; enum i40e_status_code status; if (reg_val == NULL) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_read_reg); cmd_resp->address = CPU_TO_LE32(reg_addr); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (status == I40E_SUCCESS) { *reg_val = ((u64)LE32_TO_CPU(cmd_resp->value_high) << 32) | (u64)LE32_TO_CPU(cmd_resp->value_low); } return status; } /** * i40e_aq_debug_write_register * @hw: pointer to the hw struct * @reg_addr: register address * @reg_val: register value * @cmd_details: pointer to command details structure or NULL * * Write to a register using the admin queue commands **/ enum i40e_status_code i40e_aq_debug_write_register(struct i40e_hw *hw, u32 reg_addr, u64 reg_val, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_debug_reg_read_write *cmd = (struct i40e_aqc_debug_reg_read_write *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_debug_write_reg); cmd->address = CPU_TO_LE32(reg_addr); cmd->value_high = CPU_TO_LE32((u32)(reg_val >> 32)); cmd->value_low = CPU_TO_LE32((u32)(reg_val & 0xFFFFFFFF)); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_hmc_resource_profile * @hw: pointer to the hw struct * @profile: type of profile the HMC is to be set as * @pe_vf_enabled_count: the number of PE enabled VFs the system has * @cmd_details: pointer to command details structure or NULL * * query the HMC profile of the device. **/ enum i40e_status_code i40e_aq_get_hmc_resource_profile(struct i40e_hw *hw, enum i40e_aq_hmc_profile *profile, u8 *pe_vf_enabled_count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aq_get_set_hmc_resource_profile *resp = (struct i40e_aq_get_set_hmc_resource_profile *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_query_hmc_resource_profile); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); *profile = (enum i40e_aq_hmc_profile)(resp->pm_profile & I40E_AQ_GET_HMC_RESOURCE_PROFILE_PM_MASK); *pe_vf_enabled_count = resp->pe_vf_enabled & I40E_AQ_GET_HMC_RESOURCE_PROFILE_COUNT_MASK; return status; } /** * i40e_aq_set_hmc_resource_profile * @hw: pointer to the hw struct * @profile: type of profile the HMC is to be set as * @pe_vf_enabled_count: the number of PE enabled VFs the system has * @cmd_details: pointer to command details structure or NULL * * set the HMC profile of the device. **/ enum i40e_status_code i40e_aq_set_hmc_resource_profile(struct i40e_hw *hw, enum i40e_aq_hmc_profile profile, u8 pe_vf_enabled_count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aq_get_set_hmc_resource_profile *cmd = (struct i40e_aq_get_set_hmc_resource_profile *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_hmc_resource_profile); cmd->pm_profile = (u8)profile; cmd->pe_vf_enabled = pe_vf_enabled_count; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_request_resource * @hw: pointer to the hw struct * @resource: resource id * @access: access type * @sdp_number: resource number * @timeout: the maximum time in ms that the driver may hold the resource * @cmd_details: pointer to command details structure or NULL * * requests common resource using the admin queue commands **/ enum i40e_status_code i40e_aq_request_resource(struct i40e_hw *hw, enum i40e_aq_resources_ids resource, enum i40e_aq_resource_access_type access, u8 sdp_number, u64 *timeout, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_request_resource *cmd_resp = (struct i40e_aqc_request_resource *)&desc.params.raw; enum i40e_status_code status; DEBUGFUNC("i40e_aq_request_resource"); i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_request_resource); cmd_resp->resource_id = CPU_TO_LE16(resource); cmd_resp->access_type = CPU_TO_LE16(access); cmd_resp->resource_number = CPU_TO_LE32(sdp_number); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); /* The completion specifies the maximum time in ms that the driver * may hold the resource in the Timeout field. * If the resource is held by someone else, the command completes with * busy return value and the timeout field indicates the maximum time * the current owner of the resource has to free it. */ if (status == I40E_SUCCESS || hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) *timeout = LE32_TO_CPU(cmd_resp->timeout); return status; } /** * i40e_aq_release_resource * @hw: pointer to the hw struct * @resource: resource id * @sdp_number: resource number * @cmd_details: pointer to command details structure or NULL * * release common resource using the admin queue commands **/ enum i40e_status_code i40e_aq_release_resource(struct i40e_hw *hw, enum i40e_aq_resources_ids resource, u8 sdp_number, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_request_resource *cmd = (struct i40e_aqc_request_resource *)&desc.params.raw; enum i40e_status_code status; DEBUGFUNC("i40e_aq_release_resource"); i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_release_resource); cmd->resource_id = CPU_TO_LE16(resource); cmd->resource_number = CPU_TO_LE32(sdp_number); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_read_nvm * @hw: pointer to the hw struct * @module_pointer: module pointer location in words from the NVM beginning * @offset: byte offset from the module beginning * @length: length of the section to be read (in bytes from the offset) * @data: command buffer (size [bytes] = length) * @last_command: tells if this is the last command in a series * @cmd_details: pointer to command details structure or NULL * * Read the NVM using the admin queue commands **/ enum i40e_status_code i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, void *data, bool last_command, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_nvm_update *cmd = (struct i40e_aqc_nvm_update *)&desc.params.raw; enum i40e_status_code status; DEBUGFUNC("i40e_aq_read_nvm"); /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { status = I40E_ERR_PARAM; goto i40e_aq_read_nvm_exit; } i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_read); /* If this is the last command in a series, set the proper flag. */ if (last_command) cmd->command_flags |= I40E_AQ_NVM_LAST_CMD; cmd->module_pointer = module_pointer; cmd->offset = CPU_TO_LE32(offset); cmd->length = CPU_TO_LE16(length); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (length > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, data, length, cmd_details); i40e_aq_read_nvm_exit: return status; } /** * i40e_aq_read_nvm_config - read an nvm config block * @hw: pointer to the hw struct * @cmd_flags: NVM access admin command bits * @field_id: field or feature id * @data: buffer for result * @buf_size: buffer size * @element_count: pointer to count of elements read by FW * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_read_nvm_config(struct i40e_hw *hw, u8 cmd_flags, u32 field_id, void *data, u16 buf_size, u16 *element_count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_nvm_config_read *cmd = (struct i40e_aqc_nvm_config_read *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_config_read); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); cmd->cmd_flags = CPU_TO_LE16(cmd_flags); cmd->element_id = CPU_TO_LE16((u16)(0xffff & field_id)); if (cmd_flags & I40E_AQ_ANVM_FEATURE_OR_IMMEDIATE_MASK) cmd->element_id_msw = CPU_TO_LE16((u16)(field_id >> 16)); else cmd->element_id_msw = 0; status = i40e_asq_send_command(hw, &desc, data, buf_size, cmd_details); if (!status && element_count) *element_count = LE16_TO_CPU(cmd->element_count); return status; } /** * i40e_aq_write_nvm_config - write an nvm config block * @hw: pointer to the hw struct * @cmd_flags: NVM access admin command bits * @data: buffer for result * @buf_size: buffer size * @element_count: count of elements to be written * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_write_nvm_config(struct i40e_hw *hw, u8 cmd_flags, void *data, u16 buf_size, u16 element_count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_nvm_config_write *cmd = (struct i40e_aqc_nvm_config_write *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_config_write); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buf_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); cmd->element_count = CPU_TO_LE16(element_count); cmd->cmd_flags = CPU_TO_LE16(cmd_flags); status = i40e_asq_send_command(hw, &desc, data, buf_size, cmd_details); return status; } /** * i40e_aq_erase_nvm * @hw: pointer to the hw struct * @module_pointer: module pointer location in words from the NVM beginning * @offset: offset in the module (expressed in 4 KB from module's beginning) * @length: length of the section to be erased (expressed in 4 KB) * @last_command: tells if this is the last command in a series * @cmd_details: pointer to command details structure or NULL * * Erase the NVM sector using the admin queue commands **/ enum i40e_status_code i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, bool last_command, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_nvm_update *cmd = (struct i40e_aqc_nvm_update *)&desc.params.raw; enum i40e_status_code status; DEBUGFUNC("i40e_aq_erase_nvm"); /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { status = I40E_ERR_PARAM; goto i40e_aq_erase_nvm_exit; } i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_erase); /* If this is the last command in a series, set the proper flag. */ if (last_command) cmd->command_flags |= I40E_AQ_NVM_LAST_CMD; cmd->module_pointer = module_pointer; cmd->offset = CPU_TO_LE32(offset); cmd->length = CPU_TO_LE16(length); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); i40e_aq_erase_nvm_exit: return status; } #define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01 #define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02 #define I40E_DEV_FUNC_CAP_NPAR 0x03 #define I40E_DEV_FUNC_CAP_OS2BMC 0x04 #define I40E_DEV_FUNC_CAP_VALID_FUNC 0x05 #define I40E_DEV_FUNC_CAP_SRIOV_1_1 0x12 #define I40E_DEV_FUNC_CAP_VF 0x13 #define I40E_DEV_FUNC_CAP_VMDQ 0x14 #define I40E_DEV_FUNC_CAP_802_1_QBG 0x15 #define I40E_DEV_FUNC_CAP_802_1_QBH 0x16 #define I40E_DEV_FUNC_CAP_VSI 0x17 #define I40E_DEV_FUNC_CAP_DCB 0x18 #define I40E_DEV_FUNC_CAP_FCOE 0x21 #define I40E_DEV_FUNC_CAP_ISCSI 0x22 #define I40E_DEV_FUNC_CAP_RSS 0x40 #define I40E_DEV_FUNC_CAP_RX_QUEUES 0x41 #define I40E_DEV_FUNC_CAP_TX_QUEUES 0x42 #define I40E_DEV_FUNC_CAP_MSIX 0x43 #define I40E_DEV_FUNC_CAP_MSIX_VF 0x44 #define I40E_DEV_FUNC_CAP_FLOW_DIRECTOR 0x45 #define I40E_DEV_FUNC_CAP_IEEE_1588 0x46 #define I40E_DEV_FUNC_CAP_MFP_MODE_1 0xF1 #define I40E_DEV_FUNC_CAP_CEM 0xF2 #define I40E_DEV_FUNC_CAP_IWARP 0x51 #define I40E_DEV_FUNC_CAP_LED 0x61 #define I40E_DEV_FUNC_CAP_SDP 0x62 #define I40E_DEV_FUNC_CAP_MDIO 0x63 /** * i40e_parse_discover_capabilities * @hw: pointer to the hw struct * @buff: pointer to a buffer containing device/function capability records * @cap_count: number of capability records in the list * @list_type_opc: type of capabilities list to parse * * Parse the device/function capabilities list. **/ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, u32 cap_count, enum i40e_admin_queue_opc list_type_opc) { struct i40e_aqc_list_capabilities_element_resp *cap; u32 valid_functions, num_functions; u32 number, logical_id, phys_id; struct i40e_hw_capabilities *p; u32 i = 0; u16 id; cap = (struct i40e_aqc_list_capabilities_element_resp *) buff; if (list_type_opc == i40e_aqc_opc_list_dev_capabilities) p = (struct i40e_hw_capabilities *)&hw->dev_caps; else if (list_type_opc == i40e_aqc_opc_list_func_capabilities) p = (struct i40e_hw_capabilities *)&hw->func_caps; else return; for (i = 0; i < cap_count; i++, cap++) { id = LE16_TO_CPU(cap->id); number = LE32_TO_CPU(cap->number); logical_id = LE32_TO_CPU(cap->logical_id); phys_id = LE32_TO_CPU(cap->phys_id); switch (id) { case I40E_DEV_FUNC_CAP_SWITCH_MODE: p->switch_mode = number; break; case I40E_DEV_FUNC_CAP_MGMT_MODE: p->management_mode = number; break; case I40E_DEV_FUNC_CAP_NPAR: p->npar_enable = number; break; case I40E_DEV_FUNC_CAP_OS2BMC: p->os2bmc = number; break; case I40E_DEV_FUNC_CAP_VALID_FUNC: p->valid_functions = number; break; case I40E_DEV_FUNC_CAP_SRIOV_1_1: if (number == 1) p->sr_iov_1_1 = true; break; case I40E_DEV_FUNC_CAP_VF: p->num_vfs = number; p->vf_base_id = logical_id; break; case I40E_DEV_FUNC_CAP_VMDQ: if (number == 1) p->vmdq = true; break; case I40E_DEV_FUNC_CAP_802_1_QBG: if (number == 1) p->evb_802_1_qbg = true; break; case I40E_DEV_FUNC_CAP_802_1_QBH: if (number == 1) p->evb_802_1_qbh = true; break; case I40E_DEV_FUNC_CAP_VSI: p->num_vsis = number; break; case I40E_DEV_FUNC_CAP_DCB: if (number == 1) { p->dcb = true; p->enabled_tcmap = logical_id; p->maxtc = phys_id; } break; case I40E_DEV_FUNC_CAP_FCOE: if (number == 1) p->fcoe = true; break; case I40E_DEV_FUNC_CAP_ISCSI: if (number == 1) p->iscsi = true; break; case I40E_DEV_FUNC_CAP_RSS: p->rss = true; p->rss_table_size = number; p->rss_table_entry_width = logical_id; break; case I40E_DEV_FUNC_CAP_RX_QUEUES: p->num_rx_qp = number; p->base_queue = phys_id; break; case I40E_DEV_FUNC_CAP_TX_QUEUES: p->num_tx_qp = number; p->base_queue = phys_id; break; case I40E_DEV_FUNC_CAP_MSIX: p->num_msix_vectors = number; break; case I40E_DEV_FUNC_CAP_MSIX_VF: p->num_msix_vectors_vf = number; break; case I40E_DEV_FUNC_CAP_MFP_MODE_1: if (number == 1) p->mfp_mode_1 = true; break; case I40E_DEV_FUNC_CAP_CEM: if (number == 1) p->mgmt_cem = true; break; case I40E_DEV_FUNC_CAP_IWARP: if (number == 1) p->iwarp = true; break; case I40E_DEV_FUNC_CAP_LED: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->led[phys_id] = true; break; case I40E_DEV_FUNC_CAP_SDP: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->sdp[phys_id] = true; break; case I40E_DEV_FUNC_CAP_MDIO: if (number == 1) { p->mdio_port_num = phys_id; p->mdio_port_mode = logical_id; } break; case I40E_DEV_FUNC_CAP_IEEE_1588: if (number == 1) p->ieee_1588 = true; break; case I40E_DEV_FUNC_CAP_FLOW_DIRECTOR: p->fd = true; p->fd_filters_guaranteed = number; p->fd_filters_best_effort = logical_id; break; default: break; } } #ifdef I40E_FCOE_ENA /* Software override ensuring FCoE is disabled if npar or mfp * mode because it is not supported in these modes. */ if (p->npar_enable || p->mfp_mode_1) p->fcoe = false; #else /* Always disable FCoE if compiled without the I40E_FCOE_ENA flag */ p->fcoe = false; #endif /* count the enabled ports (aka the "not disabled" ports) */ hw->num_ports = 0; for (i = 0; i < 4; i++) { u32 port_cfg_reg = I40E_PRTGEN_CNF + (4 * i); u64 port_cfg = 0; /* use AQ read to get the physical register offset instead * of the port relative offset */ i40e_aq_debug_read_register(hw, port_cfg_reg, &port_cfg, NULL); if (!(port_cfg & I40E_PRTGEN_CNF_PORT_DIS_MASK)) hw->num_ports++; } valid_functions = p->valid_functions; num_functions = 0; while (valid_functions) { if (valid_functions & 1) num_functions++; valid_functions >>= 1; } /* partition id is 1-based, and functions are evenly spread * across the ports as partitions */ hw->partition_id = (hw->pf_id / hw->num_ports) + 1; hw->num_partitions = num_functions / hw->num_ports; /* additional HW specific goodies that might * someday be HW version specific */ p->rx_buf_chain_len = I40E_MAX_CHAINED_RX_BUFFERS; } /** * i40e_aq_discover_capabilities * @hw: pointer to the hw struct * @buff: a virtual buffer to hold the capabilities * @buff_size: Size of the virtual buffer * @data_size: Size of the returned data, or buff size needed if AQ err==ENOMEM * @list_type_opc: capabilities type to discover - pass in the command opcode * @cmd_details: pointer to command details structure or NULL * * Get the device capabilities descriptions from the firmware **/ enum i40e_status_code i40e_aq_discover_capabilities(struct i40e_hw *hw, void *buff, u16 buff_size, u16 *data_size, enum i40e_admin_queue_opc list_type_opc, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aqc_list_capabilites *cmd; struct i40e_aq_desc desc; enum i40e_status_code status = I40E_SUCCESS; cmd = (struct i40e_aqc_list_capabilites *)&desc.params.raw; if (list_type_opc != i40e_aqc_opc_list_func_capabilities && list_type_opc != i40e_aqc_opc_list_dev_capabilities) { status = I40E_ERR_PARAM; goto exit; } i40e_fill_default_direct_cmd_desc(&desc, list_type_opc); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); *data_size = LE16_TO_CPU(desc.datalen); if (status) goto exit; i40e_parse_discover_capabilities(hw, buff, LE32_TO_CPU(cmd->count), list_type_opc); exit: return status; } /** * i40e_aq_update_nvm * @hw: pointer to the hw struct * @module_pointer: module pointer location in words from the NVM beginning * @offset: byte offset from the module beginning * @length: length of the section to be written (in bytes from the offset) * @data: command buffer (size [bytes] = length) * @last_command: tells if this is the last command in a series * @cmd_details: pointer to command details structure or NULL * * Update the NVM using the admin queue commands **/ enum i40e_status_code i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, void *data, bool last_command, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_nvm_update *cmd = (struct i40e_aqc_nvm_update *)&desc.params.raw; enum i40e_status_code status; DEBUGFUNC("i40e_aq_update_nvm"); /* In offset the highest byte must be zeroed. */ if (offset & 0xFF000000) { status = I40E_ERR_PARAM; goto i40e_aq_update_nvm_exit; } i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update); /* If this is the last command in a series, set the proper flag. */ if (last_command) cmd->command_flags |= I40E_AQ_NVM_LAST_CMD; cmd->module_pointer = module_pointer; cmd->offset = CPU_TO_LE32(offset); cmd->length = CPU_TO_LE16(length); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (length > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, data, length, cmd_details); i40e_aq_update_nvm_exit: return status; } /** * i40e_aq_get_lldp_mib * @hw: pointer to the hw struct * @bridge_type: type of bridge requested * @mib_type: Local, Remote or both Local and Remote MIBs * @buff: pointer to a user supplied buffer to store the MIB block * @buff_size: size of the buffer (in bytes) * @local_len : length of the returned Local LLDP MIB * @remote_len: length of the returned Remote LLDP MIB * @cmd_details: pointer to command details structure or NULL * * Requests the complete LLDP MIB (entire packet). **/ enum i40e_status_code i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type, u8 mib_type, void *buff, u16 buff_size, u16 *local_len, u16 *remote_len, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_get_mib *cmd = (struct i40e_aqc_lldp_get_mib *)&desc.params.raw; struct i40e_aqc_lldp_get_mib *resp = (struct i40e_aqc_lldp_get_mib *)&desc.params.raw; enum i40e_status_code status; if (buff_size == 0 || !buff) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_get_mib); /* Indirect Command */ desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); cmd->type = mib_type & I40E_AQ_LLDP_MIB_TYPE_MASK; cmd->type |= ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); desc.datalen = CPU_TO_LE16(buff_size); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); if (!status) { if (local_len != NULL) *local_len = LE16_TO_CPU(resp->local_len); if (remote_len != NULL) *remote_len = LE16_TO_CPU(resp->remote_len); } return status; } /** * i40e_aq_set_lldp_mib - Set the LLDP MIB * @hw: pointer to the hw struct * @mib_type: Local, Remote or both Local and Remote MIBs * @buff: pointer to a user supplied buffer to store the MIB block * @buff_size: size of the buffer (in bytes) * @cmd_details: pointer to command details structure or NULL * * Set the LLDP MIB. **/ enum i40e_status_code i40e_aq_set_lldp_mib(struct i40e_hw *hw, u8 mib_type, void *buff, u16 buff_size, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_set_local_mib *cmd = (struct i40e_aqc_lldp_set_local_mib *)&desc.params.raw; enum i40e_status_code status; if (buff_size == 0 || !buff) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_set_local_mib); /* Indirect Command */ desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(buff_size); cmd->type = mib_type; cmd->length = CPU_TO_LE16(buff_size); cmd->address_high = CPU_TO_LE32(I40E_HI_WORD((u64)buff)); cmd->address_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buff)); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); return status; } /** * i40e_aq_cfg_lldp_mib_change_event * @hw: pointer to the hw struct * @enable_update: Enable or Disable event posting * @cmd_details: pointer to command details structure or NULL * * Enable or Disable posting of an event on ARQ when LLDP MIB * associated with the interface changes **/ enum i40e_status_code i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw, bool enable_update, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_update_mib *cmd = (struct i40e_aqc_lldp_update_mib *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_update_mib); if (!enable_update) cmd->command |= I40E_AQ_LLDP_MIB_UPDATE_DISABLE; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_add_lldp_tlv * @hw: pointer to the hw struct * @bridge_type: type of bridge * @buff: buffer with TLV to add * @buff_size: length of the buffer * @tlv_len: length of the TLV to be added * @mib_len: length of the LLDP MIB returned in response * @cmd_details: pointer to command details structure or NULL * * Add the specified TLV to LLDP Local MIB for the given bridge type, * it is responsibility of the caller to make sure that the TLV is not * already present in the LLDPDU. * In return firmware will write the complete LLDP MIB with the newly * added TLV in the response buffer. **/ enum i40e_status_code i40e_aq_add_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 tlv_len, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_add_tlv *cmd = (struct i40e_aqc_lldp_add_tlv *)&desc.params.raw; enum i40e_status_code status; if (buff_size == 0 || !buff || tlv_len == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_add_tlv); /* Indirect Command */ desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(buff_size); cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); cmd->len = CPU_TO_LE16(tlv_len); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); if (!status) { if (mib_len != NULL) *mib_len = LE16_TO_CPU(desc.datalen); } return status; } /** * i40e_aq_update_lldp_tlv * @hw: pointer to the hw struct * @bridge_type: type of bridge * @buff: buffer with TLV to update * @buff_size: size of the buffer holding original and updated TLVs * @old_len: Length of the Original TLV * @new_len: Length of the Updated TLV * @offset: offset of the updated TLV in the buff * @mib_len: length of the returned LLDP MIB * @cmd_details: pointer to command details structure or NULL * * Update the specified TLV to the LLDP Local MIB for the given bridge type. * Firmware will place the complete LLDP MIB in response buffer with the * updated TLV. **/ enum i40e_status_code i40e_aq_update_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 old_len, u16 new_len, u16 offset, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_update_tlv *cmd = (struct i40e_aqc_lldp_update_tlv *)&desc.params.raw; enum i40e_status_code status; if (buff_size == 0 || !buff || offset == 0 || old_len == 0 || new_len == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_update_tlv); /* Indirect Command */ desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(buff_size); cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); cmd->old_len = CPU_TO_LE16(old_len); cmd->new_offset = CPU_TO_LE16(offset); cmd->new_len = CPU_TO_LE16(new_len); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); if (!status) { if (mib_len != NULL) *mib_len = LE16_TO_CPU(desc.datalen); } return status; } /** * i40e_aq_delete_lldp_tlv * @hw: pointer to the hw struct * @bridge_type: type of bridge * @buff: pointer to a user supplied buffer that has the TLV * @buff_size: length of the buffer * @tlv_len: length of the TLV to be deleted * @mib_len: length of the returned LLDP MIB * @cmd_details: pointer to command details structure or NULL * * Delete the specified TLV from LLDP Local MIB for the given bridge type. * The firmware places the entire LLDP MIB in the response buffer. **/ enum i40e_status_code i40e_aq_delete_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 tlv_len, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_add_tlv *cmd = (struct i40e_aqc_lldp_add_tlv *)&desc.params.raw; enum i40e_status_code status; if (buff_size == 0 || !buff) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_delete_tlv); /* Indirect Command */ desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(buff_size); cmd->len = CPU_TO_LE16(tlv_len); cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); if (!status) { if (mib_len != NULL) *mib_len = LE16_TO_CPU(desc.datalen); } return status; } /** * i40e_aq_stop_lldp * @hw: pointer to the hw struct * @shutdown_agent: True if LLDP Agent needs to be Shutdown * @cmd_details: pointer to command details structure or NULL * * Stop or Shutdown the embedded LLDP Agent **/ enum i40e_status_code i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_stop *cmd = (struct i40e_aqc_lldp_stop *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_stop); if (shutdown_agent) cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_start_lldp * @hw: pointer to the hw struct * @cmd_details: pointer to command details structure or NULL * * Start the embedded LLDP Agent on all ports. **/ enum i40e_status_code i40e_aq_start_lldp(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_start *cmd = (struct i40e_aqc_lldp_start *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start); cmd->command = I40E_AQ_LLDP_AGENT_START; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_cee_dcb_config * @hw: pointer to the hw struct * @buff: response buffer that stores CEE operational configuration * @buff_size: size of the buffer passed * @cmd_details: pointer to command details structure or NULL * * Get CEE DCBX mode operational configuration from firmware **/ enum i40e_status_code i40e_aq_get_cee_dcb_config(struct i40e_hw *hw, void *buff, u16 buff_size, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; enum i40e_status_code status; if (buff_size == 0 || !buff) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_cee_dcb_cfg); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); status = i40e_asq_send_command(hw, &desc, (void *)buff, buff_size, cmd_details); return status; } /** * i40e_aq_start_stop_dcbx - Start/Stop DCBx service in FW * @hw: pointer to the hw struct * @start_agent: True if DCBx Agent needs to be Started * False if DCBx Agent needs to be Stopped * @cmd_details: pointer to command details structure or NULL * * Start/Stop the embedded dcbx Agent **/ enum i40e_status_code i40e_aq_start_stop_dcbx(struct i40e_hw *hw, bool start_agent, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_lldp_stop_start_specific_agent *cmd = (struct i40e_aqc_lldp_stop_start_specific_agent *) &desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_stop_start_spec_agent); if (start_agent) cmd->command = I40E_AQC_START_SPECIFIC_AGENT_MASK; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_add_udp_tunnel * @hw: pointer to the hw struct * @udp_port: the UDP port to add * @header_len: length of the tunneling header length in DWords * @protocol_index: protocol index type * @filter_index: pointer to filter index * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_add_udp_tunnel(struct i40e_hw *hw, u16 udp_port, u8 protocol_index, u8 *filter_index, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_udp_tunnel *cmd = (struct i40e_aqc_add_udp_tunnel *)&desc.params.raw; struct i40e_aqc_del_udp_tunnel_completion *resp = (struct i40e_aqc_del_udp_tunnel_completion *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_udp_tunnel); cmd->udp_port = CPU_TO_LE16(udp_port); cmd->protocol_type = protocol_index; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status && filter_index) *filter_index = resp->index; return status; } /** * i40e_aq_del_udp_tunnel * @hw: pointer to the hw struct * @index: filter index * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_remove_udp_tunnel *cmd = (struct i40e_aqc_remove_udp_tunnel *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_del_udp_tunnel); cmd->index = index; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_get_switch_resource_alloc (0x0204) * @hw: pointer to the hw struct * @num_entries: pointer to u8 to store the number of resource entries returned * @buf: pointer to a user supplied buffer. This buffer must be large enough * to store the resource information for all resource types. Each * resource type is a i40e_aqc_switch_resource_alloc_data structure. * @count: size, in bytes, of the buffer provided * @cmd_details: pointer to command details structure or NULL * * Query the resources allocated to a function. **/ enum i40e_status_code i40e_aq_get_switch_resource_alloc(struct i40e_hw *hw, u8 *num_entries, struct i40e_aqc_switch_resource_alloc_element_resp *buf, u16 count, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_get_switch_resource_alloc *cmd_resp = (struct i40e_aqc_get_switch_resource_alloc *)&desc.params.raw; enum i40e_status_code status; u16 length = count * sizeof(*buf); i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_switch_resource_alloc); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (length > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, buf, length, cmd_details); if (!status && num_entries) *num_entries = cmd_resp->num_entries; return status; } /** * i40e_aq_delete_element - Delete switch element * @hw: pointer to the hw struct * @seid: the SEID to delete from the switch * @cmd_details: pointer to command details structure or NULL * * This deletes a switch element from the switch. **/ enum i40e_status_code i40e_aq_delete_element(struct i40e_hw *hw, u16 seid, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_switch_seid *cmd = (struct i40e_aqc_switch_seid *)&desc.params.raw; enum i40e_status_code status; if (seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_delete_element); cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40_aq_add_pvirt - Instantiate a Port Virtualizer on a port * @hw: pointer to the hw struct * @flags: component flags * @mac_seid: uplink seid (MAC SEID) * @vsi_seid: connected vsi seid * @ret_seid: seid of create pv component * * This instantiates an i40e port virtualizer with specified flags. * Depending on specified flags the port virtualizer can act as a * 802.1Qbr port virtualizer or a 802.1Qbg S-component. */ enum i40e_status_code i40e_aq_add_pvirt(struct i40e_hw *hw, u16 flags, u16 mac_seid, u16 vsi_seid, u16 *ret_seid) { struct i40e_aq_desc desc; struct i40e_aqc_add_update_pv *cmd = (struct i40e_aqc_add_update_pv *)&desc.params.raw; struct i40e_aqc_add_update_pv_completion *resp = (struct i40e_aqc_add_update_pv_completion *)&desc.params.raw; enum i40e_status_code status; if (vsi_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_pv); cmd->command_flags = CPU_TO_LE16(flags); cmd->uplink_seid = CPU_TO_LE16(mac_seid); cmd->connected_seid = CPU_TO_LE16(vsi_seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); if (!status && ret_seid) *ret_seid = LE16_TO_CPU(resp->pv_seid); return status; } /** * i40e_aq_add_tag - Add an S/E-tag * @hw: pointer to the hw struct * @direct_to_queue: should s-tag direct flow to a specific queue * @vsi_seid: VSI SEID to use this tag * @tag: value of the tag * @queue_num: queue number, only valid is direct_to_queue is true * @tags_used: return value, number of tags in use by this PF * @tags_free: return value, number of unallocated tags * @cmd_details: pointer to command details structure or NULL * * This associates an S- or E-tag to a VSI in the switch complex. It returns * the number of tags allocated by the PF, and the number of unallocated * tags available. **/ enum i40e_status_code i40e_aq_add_tag(struct i40e_hw *hw, bool direct_to_queue, u16 vsi_seid, u16 tag, u16 queue_num, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_tag *cmd = (struct i40e_aqc_add_tag *)&desc.params.raw; struct i40e_aqc_add_remove_tag_completion *resp = (struct i40e_aqc_add_remove_tag_completion *)&desc.params.raw; enum i40e_status_code status; if (vsi_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_tag); cmd->seid = CPU_TO_LE16(vsi_seid); cmd->tag = CPU_TO_LE16(tag); if (direct_to_queue) { cmd->flags = CPU_TO_LE16(I40E_AQC_ADD_TAG_FLAG_TO_QUEUE); cmd->queue_number = CPU_TO_LE16(queue_num); } status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status) { if (tags_used != NULL) *tags_used = LE16_TO_CPU(resp->tags_used); if (tags_free != NULL) *tags_free = LE16_TO_CPU(resp->tags_free); } return status; } /** * i40e_aq_remove_tag - Remove an S- or E-tag * @hw: pointer to the hw struct * @vsi_seid: VSI SEID this tag is associated with * @tag: value of the S-tag to delete * @tags_used: return value, number of tags in use by this PF * @tags_free: return value, number of unallocated tags * @cmd_details: pointer to command details structure or NULL * * This deletes an S- or E-tag from a VSI in the switch complex. It returns * the number of tags allocated by the PF, and the number of unallocated * tags available. **/ enum i40e_status_code i40e_aq_remove_tag(struct i40e_hw *hw, u16 vsi_seid, u16 tag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_remove_tag *cmd = (struct i40e_aqc_remove_tag *)&desc.params.raw; struct i40e_aqc_add_remove_tag_completion *resp = (struct i40e_aqc_add_remove_tag_completion *)&desc.params.raw; enum i40e_status_code status; if (vsi_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_tag); cmd->seid = CPU_TO_LE16(vsi_seid); cmd->tag = CPU_TO_LE16(tag); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status) { if (tags_used != NULL) *tags_used = LE16_TO_CPU(resp->tags_used); if (tags_free != NULL) *tags_free = LE16_TO_CPU(resp->tags_free); } return status; } /** * i40e_aq_add_mcast_etag - Add a multicast E-tag * @hw: pointer to the hw struct * @pv_seid: Port Virtualizer of this SEID to associate E-tag with * @etag: value of E-tag to add * @num_tags_in_buf: number of unicast E-tags in indirect buffer * @buf: address of indirect buffer * @tags_used: return value, number of E-tags in use by this port * @tags_free: return value, number of unallocated M-tags * @cmd_details: pointer to command details structure or NULL * * This associates a multicast E-tag to a port virtualizer. It will return * the number of tags allocated by the PF, and the number of unallocated * tags available. * * The indirect buffer pointed to by buf is a list of 2-byte E-tags, * num_tags_in_buf long. **/ enum i40e_status_code i40e_aq_add_mcast_etag(struct i40e_hw *hw, u16 pv_seid, u16 etag, u8 num_tags_in_buf, void *buf, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_mcast_etag *cmd = (struct i40e_aqc_add_remove_mcast_etag *)&desc.params.raw; struct i40e_aqc_add_remove_mcast_etag_completion *resp = (struct i40e_aqc_add_remove_mcast_etag_completion *)&desc.params.raw; enum i40e_status_code status; u16 length = sizeof(u16) * num_tags_in_buf; if ((pv_seid == 0) || (buf == NULL) || (num_tags_in_buf == 0)) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_multicast_etag); cmd->pv_seid = CPU_TO_LE16(pv_seid); cmd->etag = CPU_TO_LE16(etag); cmd->num_unicast_etags = num_tags_in_buf; desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (length > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); status = i40e_asq_send_command(hw, &desc, buf, length, cmd_details); if (!status) { if (tags_used != NULL) *tags_used = LE16_TO_CPU(resp->mcast_etags_used); if (tags_free != NULL) *tags_free = LE16_TO_CPU(resp->mcast_etags_free); } return status; } /** * i40e_aq_remove_mcast_etag - Remove a multicast E-tag * @hw: pointer to the hw struct * @pv_seid: Port Virtualizer SEID this M-tag is associated with * @etag: value of the E-tag to remove * @tags_used: return value, number of tags in use by this port * @tags_free: return value, number of unallocated tags * @cmd_details: pointer to command details structure or NULL * * This deletes an E-tag from the port virtualizer. It will return * the number of tags allocated by the port, and the number of unallocated * tags available. **/ enum i40e_status_code i40e_aq_remove_mcast_etag(struct i40e_hw *hw, u16 pv_seid, u16 etag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_mcast_etag *cmd = (struct i40e_aqc_add_remove_mcast_etag *)&desc.params.raw; struct i40e_aqc_add_remove_mcast_etag_completion *resp = (struct i40e_aqc_add_remove_mcast_etag_completion *)&desc.params.raw; enum i40e_status_code status; if (pv_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_multicast_etag); cmd->pv_seid = CPU_TO_LE16(pv_seid); cmd->etag = CPU_TO_LE16(etag); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status) { if (tags_used != NULL) *tags_used = LE16_TO_CPU(resp->mcast_etags_used); if (tags_free != NULL) *tags_free = LE16_TO_CPU(resp->mcast_etags_free); } return status; } /** * i40e_aq_update_tag - Update an S/E-tag * @hw: pointer to the hw struct * @vsi_seid: VSI SEID using this S-tag * @old_tag: old tag value * @new_tag: new tag value * @tags_used: return value, number of tags in use by this PF * @tags_free: return value, number of unallocated tags * @cmd_details: pointer to command details structure or NULL * * This updates the value of the tag currently attached to this VSI * in the switch complex. It will return the number of tags allocated * by the PF, and the number of unallocated tags available. **/ enum i40e_status_code i40e_aq_update_tag(struct i40e_hw *hw, u16 vsi_seid, u16 old_tag, u16 new_tag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_update_tag *cmd = (struct i40e_aqc_update_tag *)&desc.params.raw; struct i40e_aqc_update_tag_completion *resp = (struct i40e_aqc_update_tag_completion *)&desc.params.raw; enum i40e_status_code status; if (vsi_seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_update_tag); cmd->seid = CPU_TO_LE16(vsi_seid); cmd->old_tag = CPU_TO_LE16(old_tag); cmd->new_tag = CPU_TO_LE16(new_tag); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status) { if (tags_used != NULL) *tags_used = LE16_TO_CPU(resp->tags_used); if (tags_free != NULL) *tags_free = LE16_TO_CPU(resp->tags_free); } return status; } /** * i40e_aq_dcb_ignore_pfc - Ignore PFC for given TCs * @hw: pointer to the hw struct * @tcmap: TC map for request/release any ignore PFC condition * @request: request or release ignore PFC condition * @tcmap_ret: return TCs for which PFC is currently ignored * @cmd_details: pointer to command details structure or NULL * * This sends out request/release to ignore PFC condition for a TC. * It will return the TCs for which PFC is currently ignored. **/ enum i40e_status_code i40e_aq_dcb_ignore_pfc(struct i40e_hw *hw, u8 tcmap, bool request, u8 *tcmap_ret, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_pfc_ignore *cmd_resp = (struct i40e_aqc_pfc_ignore *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_dcb_ignore_pfc); if (request) cmd_resp->command_flags = I40E_AQC_PFC_IGNORE_SET; cmd_resp->tc_bitmap = tcmap; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status) { if (tcmap_ret != NULL) *tcmap_ret = cmd_resp->tc_bitmap; } return status; } /** * i40e_aq_dcb_updated - DCB Updated Command * @hw: pointer to the hw struct * @cmd_details: pointer to command details structure or NULL * * When LLDP is handled in PF this command is used by the PF * to notify EMP that a DCB setting is modified. * When LLDP is handled in EMP this command is used by the PF * to notify EMP whenever one of the following parameters get * modified: * - PFCLinkDelayAllowance in PRTDCB_GENC.PFCLDA * - PCIRTT in PRTDCB_GENC.PCIRTT * - Maximum Frame Size for non-FCoE TCs set by PRTDCB_TDPUC.MAX_TXFRAME. * EMP will return when the shared RPB settings have been * recomputed and modified. The retval field in the descriptor * will be set to 0 when RPB is modified. **/ enum i40e_status_code i40e_aq_dcb_updated(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_dcb_updated); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_add_statistics - Add a statistics block to a VLAN in a switch. * @hw: pointer to the hw struct * @seid: defines the SEID of the switch for which the stats are requested * @vlan_id: the VLAN ID for which the statistics are requested * @stat_index: index of the statistics counters block assigned to this VLAN * @cmd_details: pointer to command details structure or NULL * * XL710 supports 128 smonVlanStats counters.This command is used to * allocate a set of smonVlanStats counters to a specific VLAN in a specific * switch. **/ enum i40e_status_code i40e_aq_add_statistics(struct i40e_hw *hw, u16 seid, u16 vlan_id, u16 *stat_index, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_statistics *cmd_resp = (struct i40e_aqc_add_remove_statistics *)&desc.params.raw; enum i40e_status_code status; if ((seid == 0) || (stat_index == NULL)) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_statistics); cmd_resp->seid = CPU_TO_LE16(seid); cmd_resp->vlan = CPU_TO_LE16(vlan_id); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status && stat_index) *stat_index = LE16_TO_CPU(cmd_resp->stat_index); return status; } /** * i40e_aq_remove_statistics - Remove a statistics block to a VLAN in a switch. * @hw: pointer to the hw struct * @seid: defines the SEID of the switch for which the stats are requested * @vlan_id: the VLAN ID for which the statistics are requested * @stat_index: index of the statistics counters block assigned to this VLAN * @cmd_details: pointer to command details structure or NULL * * XL710 supports 128 smonVlanStats counters.This command is used to * deallocate a set of smonVlanStats counters to a specific VLAN in a specific * switch. **/ enum i40e_status_code i40e_aq_remove_statistics(struct i40e_hw *hw, u16 seid, u16 vlan_id, u16 stat_index, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_statistics *cmd = (struct i40e_aqc_add_remove_statistics *)&desc.params.raw; enum i40e_status_code status; if (seid == 0) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_statistics); cmd->seid = CPU_TO_LE16(seid); cmd->vlan = CPU_TO_LE16(vlan_id); cmd->stat_index = CPU_TO_LE16(stat_index); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_set_port_parameters - set physical port parameters. * @hw: pointer to the hw struct * @bad_frame_vsi: defines the VSI to which bad frames are forwarded * @save_bad_pac: if set packets with errors are forwarded to the bad frames VSI * @pad_short_pac: if set transmit packets smaller than 60 bytes are padded * @double_vlan: if set double VLAN is enabled * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_set_port_parameters(struct i40e_hw *hw, u16 bad_frame_vsi, bool save_bad_pac, bool pad_short_pac, bool double_vlan, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aqc_set_port_parameters *cmd; enum i40e_status_code status; struct i40e_aq_desc desc; u16 command_flags = 0; cmd = (struct i40e_aqc_set_port_parameters *)&desc.params.raw; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_port_parameters); cmd->bad_frame_vsi = CPU_TO_LE16(bad_frame_vsi); if (save_bad_pac) command_flags |= I40E_AQ_SET_P_PARAMS_SAVE_BAD_PACKETS; if (pad_short_pac) command_flags |= I40E_AQ_SET_P_PARAMS_PAD_SHORT_PACKETS; if (double_vlan) command_flags |= I40E_AQ_SET_P_PARAMS_DOUBLE_VLAN_ENA; cmd->command_flags = CPU_TO_LE16(command_flags); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_tx_sched_cmd - generic Tx scheduler AQ command handler * @hw: pointer to the hw struct * @seid: seid for the physical port/switching component/vsi * @buff: Indirect buffer to hold data parameters and response * @buff_size: Indirect buffer size * @opcode: Tx scheduler AQ command opcode * @cmd_details: pointer to command details structure or NULL * * Generic command handler for Tx scheduler AQ commands **/ static enum i40e_status_code i40e_aq_tx_sched_cmd(struct i40e_hw *hw, u16 seid, void *buff, u16 buff_size, enum i40e_admin_queue_opc opcode, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_tx_sched_ind *cmd = (struct i40e_aqc_tx_sched_ind *)&desc.params.raw; enum i40e_status_code status; bool cmd_param_flag = false; switch (opcode) { case i40e_aqc_opc_configure_vsi_ets_sla_bw_limit: case i40e_aqc_opc_configure_vsi_tc_bw: case i40e_aqc_opc_enable_switching_comp_ets: case i40e_aqc_opc_modify_switching_comp_ets: case i40e_aqc_opc_disable_switching_comp_ets: case i40e_aqc_opc_configure_switching_comp_ets_bw_limit: case i40e_aqc_opc_configure_switching_comp_bw_config: cmd_param_flag = true; break; case i40e_aqc_opc_query_vsi_bw_config: case i40e_aqc_opc_query_vsi_ets_sla_config: case i40e_aqc_opc_query_switching_comp_ets_config: case i40e_aqc_opc_query_port_ets_config: case i40e_aqc_opc_query_switching_comp_bw_config: cmd_param_flag = false; break; default: return I40E_ERR_PARAM; } i40e_fill_default_direct_cmd_desc(&desc, opcode); /* Indirect command */ desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); if (cmd_param_flag) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD); if (buff_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(buff_size); cmd->vsi_seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details); return status; } /** * i40e_aq_config_vsi_bw_limit - Configure VSI BW Limit * @hw: pointer to the hw struct * @seid: VSI seid * @credit: BW limit credits (0 = disabled) * @max_credit: Max BW limit credits * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw, u16 seid, u16 credit, u8 max_credit, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_configure_vsi_bw_limit *cmd = (struct i40e_aqc_configure_vsi_bw_limit *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_configure_vsi_bw_limit); cmd->vsi_seid = CPU_TO_LE16(seid); cmd->credit = CPU_TO_LE16(credit); cmd->max_credit = max_credit; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_config_switch_comp_bw_limit - Configure Switching component BW Limit * @hw: pointer to the hw struct * @seid: switching component seid * @credit: BW limit credits (0 = disabled) * @max_bw: Max BW limit credits * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_config_switch_comp_bw_limit(struct i40e_hw *hw, u16 seid, u16 credit, u8 max_bw, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_configure_switching_comp_bw_limit *cmd = (struct i40e_aqc_configure_switching_comp_bw_limit *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_configure_switching_comp_bw_limit); cmd->seid = CPU_TO_LE16(seid); cmd->credit = CPU_TO_LE16(credit); cmd->max_bw = max_bw; status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_aq_config_vsi_ets_sla_bw_limit - Config VSI BW Limit per TC * @hw: pointer to the hw struct * @seid: VSI seid * @bw_data: Buffer holding enabled TCs, per TC BW limit/credits * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_config_vsi_ets_sla_bw_limit(struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_vsi_ets_sla_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_configure_vsi_ets_sla_bw_limit, cmd_details); } /** * i40e_aq_config_vsi_tc_bw - Config VSI BW Allocation per TC * @hw: pointer to the hw struct * @seid: VSI seid * @bw_data: Buffer holding enabled TCs, relative TC BW limit/credits * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_vsi_tc_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_configure_vsi_tc_bw, cmd_details); } /** * i40e_aq_config_switch_comp_ets_bw_limit - Config Switch comp BW Limit per TC * @hw: pointer to the hw struct * @seid: seid of the switching component * @bw_data: Buffer holding enabled TCs, per TC BW limit/credits * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_config_switch_comp_ets_bw_limit( struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_switching_comp_ets_bw_limit_data *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_configure_switching_comp_ets_bw_limit, cmd_details); } /** * i40e_aq_query_vsi_bw_config - Query VSI BW configuration * @hw: pointer to the hw struct * @seid: seid of the VSI * @bw_data: Buffer to hold VSI BW configuration * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_query_vsi_bw_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_vsi_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_query_vsi_bw_config, cmd_details); } /** * i40e_aq_query_vsi_ets_sla_config - Query VSI BW configuration per TC * @hw: pointer to the hw struct * @seid: seid of the VSI * @bw_data: Buffer to hold VSI BW configuration per TC * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_query_vsi_ets_sla_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_vsi_ets_sla_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_query_vsi_ets_sla_config, cmd_details); } /** * i40e_aq_query_switch_comp_ets_config - Query Switch comp BW config per TC * @hw: pointer to the hw struct * @seid: seid of the switching component * @bw_data: Buffer to hold switching component's per TC BW config * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_query_switch_comp_ets_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_switching_comp_ets_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_query_switching_comp_ets_config, cmd_details); } /** * i40e_aq_query_port_ets_config - Query Physical Port ETS configuration * @hw: pointer to the hw struct * @seid: seid of the VSI or switching component connected to Physical Port * @bw_data: Buffer to hold current ETS configuration for the Physical Port * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_query_port_ets_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_port_ets_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_query_port_ets_config, cmd_details); } /** * i40e_aq_query_switch_comp_bw_config - Query Switch comp BW configuration * @hw: pointer to the hw struct * @seid: seid of the switching component * @bw_data: Buffer to hold switching component's BW configuration * @cmd_details: pointer to command details structure or NULL **/ enum i40e_status_code i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details) { return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), i40e_aqc_opc_query_switching_comp_bw_config, cmd_details); } /** * i40e_validate_filter_settings * @hw: pointer to the hardware structure * @settings: Filter control settings * * Check and validate the filter control settings passed. * The function checks for the valid filter/context sizes being * passed for FCoE and PE. * * Returns I40E_SUCCESS if the values passed are valid and within * range else returns an error. **/ STATIC enum i40e_status_code i40e_validate_filter_settings(struct i40e_hw *hw, struct i40e_filter_control_settings *settings) { u32 fcoe_cntx_size, fcoe_filt_size; u32 pe_cntx_size, pe_filt_size; u32 fcoe_fmax; u32 val; /* Validate FCoE settings passed */ switch (settings->fcoe_filt_num) { case I40E_HASH_FILTER_SIZE_1K: case I40E_HASH_FILTER_SIZE_2K: case I40E_HASH_FILTER_SIZE_4K: case I40E_HASH_FILTER_SIZE_8K: case I40E_HASH_FILTER_SIZE_16K: case I40E_HASH_FILTER_SIZE_32K: fcoe_filt_size = I40E_HASH_FILTER_BASE_SIZE; fcoe_filt_size <<= (u32)settings->fcoe_filt_num; break; default: return I40E_ERR_PARAM; } switch (settings->fcoe_cntx_num) { case I40E_DMA_CNTX_SIZE_512: case I40E_DMA_CNTX_SIZE_1K: case I40E_DMA_CNTX_SIZE_2K: case I40E_DMA_CNTX_SIZE_4K: fcoe_cntx_size = I40E_DMA_CNTX_BASE_SIZE; fcoe_cntx_size <<= (u32)settings->fcoe_cntx_num; break; default: return I40E_ERR_PARAM; } /* Validate PE settings passed */ switch (settings->pe_filt_num) { case I40E_HASH_FILTER_SIZE_1K: case I40E_HASH_FILTER_SIZE_2K: case I40E_HASH_FILTER_SIZE_4K: case I40E_HASH_FILTER_SIZE_8K: case I40E_HASH_FILTER_SIZE_16K: case I40E_HASH_FILTER_SIZE_32K: case I40E_HASH_FILTER_SIZE_64K: case I40E_HASH_FILTER_SIZE_128K: case I40E_HASH_FILTER_SIZE_256K: case I40E_HASH_FILTER_SIZE_512K: case I40E_HASH_FILTER_SIZE_1M: pe_filt_size = I40E_HASH_FILTER_BASE_SIZE; pe_filt_size <<= (u32)settings->pe_filt_num; break; default: return I40E_ERR_PARAM; } switch (settings->pe_cntx_num) { case I40E_DMA_CNTX_SIZE_512: case I40E_DMA_CNTX_SIZE_1K: case I40E_DMA_CNTX_SIZE_2K: case I40E_DMA_CNTX_SIZE_4K: case I40E_DMA_CNTX_SIZE_8K: case I40E_DMA_CNTX_SIZE_16K: case I40E_DMA_CNTX_SIZE_32K: case I40E_DMA_CNTX_SIZE_64K: case I40E_DMA_CNTX_SIZE_128K: case I40E_DMA_CNTX_SIZE_256K: pe_cntx_size = I40E_DMA_CNTX_BASE_SIZE; pe_cntx_size <<= (u32)settings->pe_cntx_num; break; default: return I40E_ERR_PARAM; } /* FCHSIZE + FCDSIZE should not be greater than PMFCOEFMAX */ val = rd32(hw, I40E_GLHMC_FCOEFMAX); fcoe_fmax = (val & I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK) >> I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT; if (fcoe_filt_size + fcoe_cntx_size > fcoe_fmax) return I40E_ERR_INVALID_SIZE; return I40E_SUCCESS; } /** * i40e_set_filter_control * @hw: pointer to the hardware structure * @settings: Filter control settings * * Set the Queue Filters for PE/FCoE and enable filters required * for a single PF. It is expected that these settings are programmed * at the driver initialization time. **/ enum i40e_status_code i40e_set_filter_control(struct i40e_hw *hw, struct i40e_filter_control_settings *settings) { enum i40e_status_code ret = I40E_SUCCESS; u32 hash_lut_size = 0; u32 val; if (!settings) return I40E_ERR_PARAM; /* Validate the input settings */ ret = i40e_validate_filter_settings(hw, settings); if (ret) return ret; /* Read the PF Queue Filter control register */ val = rd32(hw, I40E_PFQF_CTL_0); /* Program required PE hash buckets for the PF */ val &= ~I40E_PFQF_CTL_0_PEHSIZE_MASK; val |= ((u32)settings->pe_filt_num << I40E_PFQF_CTL_0_PEHSIZE_SHIFT) & I40E_PFQF_CTL_0_PEHSIZE_MASK; /* Program required PE contexts for the PF */ val &= ~I40E_PFQF_CTL_0_PEDSIZE_MASK; val |= ((u32)settings->pe_cntx_num << I40E_PFQF_CTL_0_PEDSIZE_SHIFT) & I40E_PFQF_CTL_0_PEDSIZE_MASK; /* Program required FCoE hash buckets for the PF */ val &= ~I40E_PFQF_CTL_0_PFFCHSIZE_MASK; val |= ((u32)settings->fcoe_filt_num << I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT) & I40E_PFQF_CTL_0_PFFCHSIZE_MASK; /* Program required FCoE DDP contexts for the PF */ val &= ~I40E_PFQF_CTL_0_PFFCDSIZE_MASK; val |= ((u32)settings->fcoe_cntx_num << I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT) & I40E_PFQF_CTL_0_PFFCDSIZE_MASK; /* Program Hash LUT size for the PF */ val &= ~I40E_PFQF_CTL_0_HASHLUTSIZE_MASK; if (settings->hash_lut_size == I40E_HASH_LUT_SIZE_512) hash_lut_size = 1; val |= (hash_lut_size << I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT) & I40E_PFQF_CTL_0_HASHLUTSIZE_MASK; /* Enable FDIR, Ethertype and MACVLAN filters for PF and VFs */ if (settings->enable_fdir) val |= I40E_PFQF_CTL_0_FD_ENA_MASK; if (settings->enable_ethtype) val |= I40E_PFQF_CTL_0_ETYPE_ENA_MASK; if (settings->enable_macvlan) val |= I40E_PFQF_CTL_0_MACVLAN_ENA_MASK; wr32(hw, I40E_PFQF_CTL_0, val); return I40E_SUCCESS; } /** * i40e_aq_add_rem_control_packet_filter - Add or Remove Control Packet Filter * @hw: pointer to the hw struct * @mac_addr: MAC address to use in the filter * @ethtype: Ethertype to use in the filter * @flags: Flags that needs to be applied to the filter * @vsi_seid: seid of the control VSI * @queue: VSI queue number to send the packet to * @is_add: Add control packet filter if True else remove * @stats: Structure to hold information on control filter counts * @cmd_details: pointer to command details structure or NULL * * This command will Add or Remove control packet filter for a control VSI. * In return it will update the total number of perfect filter count in * the stats member. **/ enum i40e_status_code i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, u8 *mac_addr, u16 ethtype, u16 flags, u16 vsi_seid, u16 queue, bool is_add, struct i40e_control_filter_stats *stats, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_control_packet_filter *cmd = (struct i40e_aqc_add_remove_control_packet_filter *) &desc.params.raw; struct i40e_aqc_add_remove_control_packet_filter_completion *resp = (struct i40e_aqc_add_remove_control_packet_filter_completion *) &desc.params.raw; enum i40e_status_code status; if (vsi_seid == 0) return I40E_ERR_PARAM; if (is_add) { i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_control_packet_filter); cmd->queue = CPU_TO_LE16(queue); } else { i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_control_packet_filter); } if (mac_addr) i40e_memcpy(cmd->mac, mac_addr, I40E_ETH_LENGTH_OF_ADDRESS, I40E_NONDMA_TO_NONDMA); cmd->etype = CPU_TO_LE16(ethtype); cmd->flags = CPU_TO_LE16(flags); cmd->seid = CPU_TO_LE16(vsi_seid); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); if (!status && stats) { stats->mac_etype_used = LE16_TO_CPU(resp->mac_etype_used); stats->etype_used = LE16_TO_CPU(resp->etype_used); stats->mac_etype_free = LE16_TO_CPU(resp->mac_etype_free); stats->etype_free = LE16_TO_CPU(resp->etype_free); } return status; } /** * i40e_aq_add_cloud_filters * @hw: pointer to the hardware structure * @seid: VSI seid to add cloud filters from * @filters: Buffer which contains the filters to be added * @filter_count: number of filters contained in the buffer * * Set the cloud filters for a given VSI. The contents of the * i40e_aqc_add_remove_cloud_filters_element_data are filled * in by the caller of the function. * **/ enum i40e_status_code i40e_aq_add_cloud_filters(struct i40e_hw *hw, u16 seid, struct i40e_aqc_add_remove_cloud_filters_element_data *filters, u8 filter_count) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_cloud_filters *cmd = (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw; u16 buff_len; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_cloud_filters); buff_len = filter_count * sizeof(*filters); desc.datalen = CPU_TO_LE16(buff_len); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); cmd->num_filters = filter_count; cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL); return status; } /** * i40e_aq_remove_cloud_filters * @hw: pointer to the hardware structure * @seid: VSI seid to remove cloud filters from * @filters: Buffer which contains the filters to be removed * @filter_count: number of filters contained in the buffer * * Remove the cloud filters for a given VSI. The contents of the * i40e_aqc_add_remove_cloud_filters_element_data are filled * in by the caller of the function. * **/ enum i40e_status_code i40e_aq_remove_cloud_filters(struct i40e_hw *hw, u16 seid, struct i40e_aqc_add_remove_cloud_filters_element_data *filters, u8 filter_count) { struct i40e_aq_desc desc; struct i40e_aqc_add_remove_cloud_filters *cmd = (struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw; enum i40e_status_code status; u16 buff_len; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_cloud_filters); buff_len = filter_count * sizeof(*filters); desc.datalen = CPU_TO_LE16(buff_len); desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); cmd->num_filters = filter_count; cmd->seid = CPU_TO_LE16(seid); status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL); return status; } /** * i40e_aq_alternate_write * @hw: pointer to the hardware structure * @reg_addr0: address of first dword to be read * @reg_val0: value to be written under 'reg_addr0' * @reg_addr1: address of second dword to be read * @reg_val1: value to be written under 'reg_addr1' * * Write one or two dwords to alternate structure. Fields are indicated * by 'reg_addr0' and 'reg_addr1' register numbers. * **/ enum i40e_status_code i40e_aq_alternate_write(struct i40e_hw *hw, u32 reg_addr0, u32 reg_val0, u32 reg_addr1, u32 reg_val1) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_write *cmd_resp = (struct i40e_aqc_alternate_write *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_write); cmd_resp->address0 = CPU_TO_LE32(reg_addr0); cmd_resp->address1 = CPU_TO_LE32(reg_addr1); cmd_resp->data0 = CPU_TO_LE32(reg_val0); cmd_resp->data1 = CPU_TO_LE32(reg_val1); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); return status; } /** * i40e_aq_alternate_write_indirect * @hw: pointer to the hardware structure * @addr: address of a first register to be modified * @dw_count: number of alternate structure fields to write * @buffer: pointer to the command buffer * * Write 'dw_count' dwords from 'buffer' to alternate structure * starting at 'addr'. * **/ enum i40e_status_code i40e_aq_alternate_write_indirect(struct i40e_hw *hw, u32 addr, u32 dw_count, void *buffer) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_ind_write *cmd_resp = (struct i40e_aqc_alternate_ind_write *)&desc.params.raw; enum i40e_status_code status; if (buffer == NULL) return I40E_ERR_PARAM; /* Indirect command */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_write_indirect); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_RD); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF); if (dw_count > (I40E_AQ_LARGE_BUF/4)) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); cmd_resp->address = CPU_TO_LE32(addr); cmd_resp->length = CPU_TO_LE32(dw_count); cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_WORD((u64)buffer)); cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer)); status = i40e_asq_send_command(hw, &desc, buffer, I40E_LO_DWORD(4*dw_count), NULL); return status; } /** * i40e_aq_alternate_read * @hw: pointer to the hardware structure * @reg_addr0: address of first dword to be read * @reg_val0: pointer for data read from 'reg_addr0' * @reg_addr1: address of second dword to be read * @reg_val1: pointer for data read from 'reg_addr1' * * Read one or two dwords from alternate structure. Fields are indicated * by 'reg_addr0' and 'reg_addr1' register numbers. If 'reg_val1' pointer * is not passed then only register at 'reg_addr0' is read. * **/ enum i40e_status_code i40e_aq_alternate_read(struct i40e_hw *hw, u32 reg_addr0, u32 *reg_val0, u32 reg_addr1, u32 *reg_val1) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_write *cmd_resp = (struct i40e_aqc_alternate_write *)&desc.params.raw; enum i40e_status_code status; if (reg_val0 == NULL) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_read); cmd_resp->address0 = CPU_TO_LE32(reg_addr0); cmd_resp->address1 = CPU_TO_LE32(reg_addr1); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); if (status == I40E_SUCCESS) { *reg_val0 = LE32_TO_CPU(cmd_resp->data0); if (reg_val1 != NULL) *reg_val1 = LE32_TO_CPU(cmd_resp->data1); } return status; } /** * i40e_aq_alternate_read_indirect * @hw: pointer to the hardware structure * @addr: address of the alternate structure field * @dw_count: number of alternate structure fields to read * @buffer: pointer to the command buffer * * Read 'dw_count' dwords from alternate structure starting at 'addr' and * place them in 'buffer'. The buffer should be allocated by caller. * **/ enum i40e_status_code i40e_aq_alternate_read_indirect(struct i40e_hw *hw, u32 addr, u32 dw_count, void *buffer) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_ind_write *cmd_resp = (struct i40e_aqc_alternate_ind_write *)&desc.params.raw; enum i40e_status_code status; if (buffer == NULL) return I40E_ERR_PARAM; /* Indirect command */ i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_read_indirect); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_RD); desc.flags |= CPU_TO_LE16(I40E_AQ_FLAG_BUF); if (dw_count > (I40E_AQ_LARGE_BUF/4)) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); cmd_resp->address = CPU_TO_LE32(addr); cmd_resp->length = CPU_TO_LE32(dw_count); cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buffer)); cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer)); status = i40e_asq_send_command(hw, &desc, buffer, I40E_LO_DWORD(4*dw_count), NULL); return status; } /** * i40e_aq_alternate_clear * @hw: pointer to the HW structure. * * Clear the alternate structures of the port from which the function * is called. * **/ enum i40e_status_code i40e_aq_alternate_clear(struct i40e_hw *hw) { struct i40e_aq_desc desc; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_clear_port); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); return status; } /** * i40e_aq_alternate_write_done * @hw: pointer to the HW structure. * @bios_mode: indicates whether the command is executed by UEFI or legacy BIOS * @reset_needed: indicates the SW should trigger GLOBAL reset * * Indicates to the FW that alternate structures have been changed. * **/ enum i40e_status_code i40e_aq_alternate_write_done(struct i40e_hw *hw, u8 bios_mode, bool *reset_needed) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_write_done *cmd = (struct i40e_aqc_alternate_write_done *)&desc.params.raw; enum i40e_status_code status; if (reset_needed == NULL) return I40E_ERR_PARAM; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_write_done); cmd->cmd_flags = CPU_TO_LE16(bios_mode); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); if (!status && reset_needed) *reset_needed = ((LE16_TO_CPU(cmd->cmd_flags) & I40E_AQ_ALTERNATE_RESET_NEEDED) != 0); return status; } /** * i40e_aq_set_oem_mode * @hw: pointer to the HW structure. * @oem_mode: the OEM mode to be used * * Sets the device to a specific operating mode. Currently the only supported * mode is no_clp, which causes FW to refrain from using Alternate RAM. * **/ enum i40e_status_code i40e_aq_set_oem_mode(struct i40e_hw *hw, u8 oem_mode) { struct i40e_aq_desc desc; struct i40e_aqc_alternate_write_done *cmd = (struct i40e_aqc_alternate_write_done *)&desc.params.raw; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_alternate_set_mode); cmd->cmd_flags = CPU_TO_LE16(oem_mode); status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); return status; } /** * i40e_aq_resume_port_tx * @hw: pointer to the hardware structure * @cmd_details: pointer to command details structure or NULL * * Resume port's Tx traffic **/ enum i40e_status_code i40e_aq_resume_port_tx(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_resume_port_tx); status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); return status; } /** * i40e_set_pci_config_data - store PCI bus info * @hw: pointer to hardware structure * @link_status: the link status word from PCI config space * * Stores the PCI bus info (speed, width, type) within the i40e_hw structure **/ void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status) { hw->bus.type = i40e_bus_type_pci_express; switch (link_status & I40E_PCI_LINK_WIDTH) { case I40E_PCI_LINK_WIDTH_1: hw->bus.width = i40e_bus_width_pcie_x1; break; case I40E_PCI_LINK_WIDTH_2: hw->bus.width = i40e_bus_width_pcie_x2; break; case I40E_PCI_LINK_WIDTH_4: hw->bus.width = i40e_bus_width_pcie_x4; break; case I40E_PCI_LINK_WIDTH_8: hw->bus.width = i40e_bus_width_pcie_x8; break; default: hw->bus.width = i40e_bus_width_unknown; break; } switch (link_status & I40E_PCI_LINK_SPEED) { case I40E_PCI_LINK_SPEED_2500: hw->bus.speed = i40e_bus_speed_2500; break; case I40E_PCI_LINK_SPEED_5000: hw->bus.speed = i40e_bus_speed_5000; break; case I40E_PCI_LINK_SPEED_8000: hw->bus.speed = i40e_bus_speed_8000; break; default: hw->bus.speed = i40e_bus_speed_unknown; break; } } /** * i40e_read_bw_from_alt_ram * @hw: pointer to the hardware structure * @max_bw: pointer for max_bw read * @min_bw: pointer for min_bw read * @min_valid: pointer for bool that is true if min_bw is a valid value * @max_valid: pointer for bool that is true if max_bw is a valid value * * Read bw from the alternate ram for the given pf **/ enum i40e_status_code i40e_read_bw_from_alt_ram(struct i40e_hw *hw, u32 *max_bw, u32 *min_bw, bool *min_valid, bool *max_valid) { enum i40e_status_code status; u32 max_bw_addr, min_bw_addr; /* Calculate the address of the min/max bw registers */ max_bw_addr = I40E_ALT_STRUCT_FIRST_PF_OFFSET + I40E_ALT_STRUCT_MAX_BW_OFFSET + (I40E_ALT_STRUCT_DWORDS_PER_PF*hw->pf_id); min_bw_addr = I40E_ALT_STRUCT_FIRST_PF_OFFSET + I40E_ALT_STRUCT_MIN_BW_OFFSET + (I40E_ALT_STRUCT_DWORDS_PER_PF*hw->pf_id); /* Read the bandwidths from alt ram */ status = i40e_aq_alternate_read(hw, max_bw_addr, max_bw, min_bw_addr, min_bw); if (*min_bw & I40E_ALT_BW_VALID_MASK) *min_valid = true; else *min_valid = false; if (*max_bw & I40E_ALT_BW_VALID_MASK) *max_valid = true; else *max_valid = false; return status; } /** * i40e_aq_configure_partition_bw * @hw: pointer to the hardware structure * @bw_data: Buffer holding valid pfs and bw limits * @cmd_details: pointer to command details * * Configure partitions guaranteed/max bw **/ enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw, struct i40e_aqc_configure_partition_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details) { enum i40e_status_code status; struct i40e_aq_desc desc; u16 bwd_size = sizeof(*bw_data); i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_configure_partition_bw); /* Indirect command */ desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD); if (bwd_size > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(bwd_size); status = i40e_asq_send_command(hw, &desc, bw_data, bwd_size, cmd_details); return status; } #endif /* PF_DRIVER */ #ifdef VF_DRIVER /** * i40e_aq_send_msg_to_pf * @hw: pointer to the hardware structure * @v_opcode: opcodes for VF-PF communication * @v_retval: return error code * @msg: pointer to the msg buffer * @msglen: msg length * @cmd_details: pointer to command details * * Send message to PF driver using admin queue. By default, this message * is sent asynchronously, i.e. i40e_asq_send_command() does not wait for * completion before returning. **/ enum i40e_status_code i40e_aq_send_msg_to_pf(struct i40e_hw *hw, enum i40e_virtchnl_ops v_opcode, enum i40e_status_code v_retval, u8 *msg, u16 msglen, struct i40e_asq_cmd_details *cmd_details) { struct i40e_aq_desc desc; struct i40e_asq_cmd_details details; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_send_msg_to_pf); desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_SI); desc.cookie_high = CPU_TO_LE32(v_opcode); desc.cookie_low = CPU_TO_LE32(v_retval); if (msglen) { desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); if (msglen > I40E_AQ_LARGE_BUF) desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB); desc.datalen = CPU_TO_LE16(msglen); } if (!cmd_details) { i40e_memset(&details, 0, sizeof(details), I40E_NONDMA_MEM); details.async = true; cmd_details = &details; } status = i40e_asq_send_command(hw, (struct i40e_aq_desc *)&desc, msg, msglen, cmd_details); return status; } /** * i40e_vf_parse_hw_config * @hw: pointer to the hardware structure * @msg: pointer to the virtual channel VF resource structure * * Given a VF resource message from the PF, populate the hw struct * with appropriate information. **/ void i40e_vf_parse_hw_config(struct i40e_hw *hw, struct i40e_virtchnl_vf_resource *msg) { struct i40e_virtchnl_vsi_resource *vsi_res; int i; vsi_res = &msg->vsi_res[0]; hw->dev_caps.num_vsis = msg->num_vsis; hw->dev_caps.num_rx_qp = msg->num_queue_pairs; hw->dev_caps.num_tx_qp = msg->num_queue_pairs; hw->dev_caps.num_msix_vectors_vf = msg->max_vectors; hw->dev_caps.dcb = msg->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_L2; hw->dev_caps.fcoe = (msg->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0; hw->dev_caps.iwarp = (msg->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_IWARP) ? 1 : 0; for (i = 0; i < msg->num_vsis; i++) { if (vsi_res->vsi_type == I40E_VSI_SRIOV) { i40e_memcpy(hw->mac.perm_addr, vsi_res->default_mac_addr, I40E_ETH_LENGTH_OF_ADDRESS, I40E_NONDMA_TO_NONDMA); i40e_memcpy(hw->mac.addr, vsi_res->default_mac_addr, I40E_ETH_LENGTH_OF_ADDRESS, I40E_NONDMA_TO_NONDMA); } vsi_res++; } } /** * i40e_vf_reset * @hw: pointer to the hardware structure * * Send a VF_RESET message to the PF. Does not wait for response from PF * as none will be forthcoming. Immediately after calling this function, * the admin queue should be shut down and (optionally) reinitialized. **/ enum i40e_status_code i40e_vf_reset(struct i40e_hw *hw) { return i40e_aq_send_msg_to_pf(hw, I40E_VIRTCHNL_OP_RESET_VF, I40E_SUCCESS, NULL, 0, NULL); } #endif /* VF_DRIVER */ ================================================ FILE: drivers/net/i40e/base/i40e_dcb.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_adminq.h" #include "i40e_prototype.h" #include "i40e_dcb.h" /** * i40e_get_dcbx_status * @hw: pointer to the hw struct * @status: Embedded DCBX Engine Status * * Get the DCBX status from the Firmware **/ enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status) { u32 reg; if (!status) return I40E_ERR_PARAM; reg = rd32(hw, I40E_PRTDCB_GENS); *status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >> I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT); return I40E_SUCCESS; } /** * i40e_parse_ieee_etscfg_tlv * @tlv: IEEE 802.1Qaz ETS CFG TLV * @dcbcfg: Local store to update ETS CFG data * * Parses IEEE 802.1Qaz ETS CFG TLV **/ static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { struct i40e_dcb_ets_config *etscfg; u8 *buf = tlv->tlvinfo; u16 offset = 0; u8 priority; int i; /* First Octet post subtype * -------------------------- * |will-|CBS | Re- | Max | * |ing | |served| TCs | * -------------------------- * |1bit | 1bit|3 bits|3bits| */ etscfg = &dcbcfg->etscfg; etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >> I40E_IEEE_ETS_WILLING_SHIFT); etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >> I40E_IEEE_ETS_CBS_SHIFT); etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >> I40E_IEEE_ETS_MAXTC_SHIFT); /* Move offset to Priority Assignment Table */ offset++; /* Priority Assignment Table (4 octets) * Octets:| 1 | 2 | 3 | 4 | * ----------------------------------------- * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| * ----------------------------------------- * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| * ----------------------------------------- */ for (i = 0; i < 4; i++) { priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> I40E_IEEE_ETS_PRIO_1_SHIFT); etscfg->prioritytable[i * 2] = priority; priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> I40E_IEEE_ETS_PRIO_0_SHIFT); etscfg->prioritytable[i * 2 + 1] = priority; offset++; } /* TC Bandwidth Table (8 octets) * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | * --------------------------------- * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| * --------------------------------- */ for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) etscfg->tcbwtable[i] = buf[offset++]; /* TSA Assignment Table (8 octets) * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | * --------------------------------- * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| * --------------------------------- */ for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) etscfg->tsatable[i] = buf[offset++]; } /** * i40e_parse_ieee_etsrec_tlv * @tlv: IEEE 802.1Qaz ETS REC TLV * @dcbcfg: Local store to update ETS REC data * * Parses IEEE 802.1Qaz ETS REC TLV **/ static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { u8 *buf = tlv->tlvinfo; u16 offset = 0; u8 priority; int i; /* Move offset to priority table */ offset++; /* Priority Assignment Table (4 octets) * Octets:| 1 | 2 | 3 | 4 | * ----------------------------------------- * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| * ----------------------------------------- * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| * ----------------------------------------- */ for (i = 0; i < 4; i++) { priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >> I40E_IEEE_ETS_PRIO_1_SHIFT); dcbcfg->etsrec.prioritytable[i*2] = priority; priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >> I40E_IEEE_ETS_PRIO_0_SHIFT); dcbcfg->etsrec.prioritytable[i*2 + 1] = priority; offset++; } /* TC Bandwidth Table (8 octets) * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | * --------------------------------- * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| * --------------------------------- */ for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) dcbcfg->etsrec.tcbwtable[i] = buf[offset++]; /* TSA Assignment Table (8 octets) * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | * --------------------------------- * |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7| * --------------------------------- */ for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) dcbcfg->etsrec.tsatable[i] = buf[offset++]; } /** * i40e_parse_ieee_pfccfg_tlv * @tlv: IEEE 802.1Qaz PFC CFG TLV * @dcbcfg: Local store to update PFC CFG data * * Parses IEEE 802.1Qaz PFC CFG TLV **/ static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { u8 *buf = tlv->tlvinfo; /* ---------------------------------------- * |will-|MBC | Re- | PFC | PFC Enable | * |ing | |served| cap | | * ----------------------------------------- * |1bit | 1bit|2 bits|4bits| 1 octet | */ dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >> I40E_IEEE_PFC_WILLING_SHIFT); dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >> I40E_IEEE_PFC_MBC_SHIFT); dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >> I40E_IEEE_PFC_CAP_SHIFT); dcbcfg->pfc.pfcenable = buf[1]; } /** * i40e_parse_ieee_app_tlv * @tlv: IEEE 802.1Qaz APP TLV * @dcbcfg: Local store to update APP PRIO data * * Parses IEEE 802.1Qaz APP PRIO TLV **/ static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { u16 typelength; u16 offset = 0; u16 length; int i = 0; u8 *buf; typelength = I40E_NTOHS(tlv->typelength); length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> I40E_LLDP_TLV_LEN_SHIFT); buf = tlv->tlvinfo; /* The App priority table starts 5 octets after TLV header */ length -= (sizeof(tlv->ouisubtype) + 1); /* Move offset to App Priority Table */ offset++; /* Application Priority Table (3 octets) * Octets:| 1 | 2 | 3 | * ----------------------------------------- * |Priority|Rsrvd| Sel | Protocol ID | * ----------------------------------------- * Bits:|23 21|20 19|18 16|15 0| * ----------------------------------------- */ while (offset < length) { dcbcfg->app[i].priority = (u8)((buf[offset] & I40E_IEEE_APP_PRIO_MASK) >> I40E_IEEE_APP_PRIO_SHIFT); dcbcfg->app[i].selector = (u8)((buf[offset] & I40E_IEEE_APP_SEL_MASK) >> I40E_IEEE_APP_SEL_SHIFT); dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) | buf[offset + 2]; /* Move to next app */ offset += 3; i++; if (i >= I40E_DCBX_MAX_APPS) break; } dcbcfg->numapps = i; } /** * i40e_parse_ieee_etsrec_tlv * @tlv: IEEE 802.1Qaz TLV * @dcbcfg: Local store to update ETS REC data * * Get the TLV subtype and send it to parsing function * based on the subtype value **/ static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { u32 ouisubtype; u8 subtype; ouisubtype = I40E_NTOHL(tlv->ouisubtype); subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> I40E_LLDP_TLV_SUBTYPE_SHIFT); switch (subtype) { case I40E_IEEE_SUBTYPE_ETS_CFG: i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg); break; case I40E_IEEE_SUBTYPE_ETS_REC: i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg); break; case I40E_IEEE_SUBTYPE_PFC_CFG: i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg); break; case I40E_IEEE_SUBTYPE_APP_PRI: i40e_parse_ieee_app_tlv(tlv, dcbcfg); break; default: break; } } /** * i40e_parse_org_tlv * @tlv: Organization specific TLV * @dcbcfg: Local store to update ETS REC data * * Currently only IEEE 802.1Qaz TLV is supported, all others * will be returned **/ static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv, struct i40e_dcbx_config *dcbcfg) { u32 ouisubtype; u32 oui; ouisubtype = I40E_NTOHL(tlv->ouisubtype); oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >> I40E_LLDP_TLV_OUI_SHIFT); switch (oui) { case I40E_IEEE_8021QAZ_OUI: i40e_parse_ieee_tlv(tlv, dcbcfg); break; default: break; } } /** * i40e_lldp_to_dcb_config * @lldpmib: LLDPDU to be parsed * @dcbcfg: store for LLDPDU data * * Parse DCB configuration from the LLDPDU **/ enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib, struct i40e_dcbx_config *dcbcfg) { enum i40e_status_code ret = I40E_SUCCESS; struct i40e_lldp_org_tlv *tlv; u16 type; u16 length; u16 typelength; u16 offset = 0; if (!lldpmib || !dcbcfg) return I40E_ERR_PARAM; /* set to the start of LLDPDU */ lldpmib += I40E_LLDP_MIB_HLEN; tlv = (struct i40e_lldp_org_tlv *)lldpmib; while (1) { typelength = I40E_NTOHS(tlv->typelength); type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> I40E_LLDP_TLV_TYPE_SHIFT); length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> I40E_LLDP_TLV_LEN_SHIFT); offset += sizeof(typelength) + length; /* END TLV or beyond LLDPDU size */ if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE)) break; switch (type) { case I40E_TLV_TYPE_ORG: i40e_parse_org_tlv(tlv, dcbcfg); break; default: break; } /* Move to next TLV */ tlv = (struct i40e_lldp_org_tlv *)((char *)tlv + sizeof(tlv->typelength) + length); } return ret; } /** * i40e_aq_get_dcb_config * @hw: pointer to the hw struct * @mib_type: mib type for the query * @bridgetype: bridge type for the query (remote) * @dcbcfg: store for LLDPDU data * * Query DCB configuration from the Firmware **/ enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type, u8 bridgetype, struct i40e_dcbx_config *dcbcfg) { enum i40e_status_code ret = I40E_SUCCESS; struct i40e_virt_mem mem; u8 *lldpmib; /* Allocate the LLDPDU */ ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE); if (ret) return ret; lldpmib = (u8 *)mem.va; ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type, (void *)lldpmib, I40E_LLDPDU_SIZE, NULL, NULL, NULL); if (ret) goto free_mem; /* Parse LLDP MIB to get dcb configuration */ ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg); free_mem: i40e_free_virt_mem(hw, &mem); return ret; } /** * i40e_cee_to_dcb_v1_config * @cee_cfg: pointer to CEE v1 response configuration struct * @dcbcfg: DCB configuration struct * * Convert CEE v1 configuration from firmware to DCB configuration **/ static void i40e_cee_to_dcb_v1_config( struct i40e_aqc_get_cee_dcb_cfg_v1_resp *cee_cfg, struct i40e_dcbx_config *dcbcfg) { u16 status, tlv_status = LE16_TO_CPU(cee_cfg->tlv_status); u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio); u8 i, tc, err, sync, oper; /* CEE PG data to ETS config */ dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; /* Note that the FW creates the oper_prio_tc nibbles reversed * from those in the CEE Priority Group sub-TLV. */ for (i = 0; i < 4; i++) { tc = (u8)((cee_cfg->oper_prio_tc[i] & I40E_CEE_PGID_PRIO_0_MASK) >> I40E_CEE_PGID_PRIO_0_SHIFT); dcbcfg->etscfg.prioritytable[i*2] = tc; tc = (u8)((cee_cfg->oper_prio_tc[i] & I40E_CEE_PGID_PRIO_1_MASK) >> I40E_CEE_PGID_PRIO_1_SHIFT); dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; } for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { /* Map it to next empty TC */ dcbcfg->etscfg.prioritytable[i] = cee_cfg->oper_num_tc - 1; dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; } else { dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; } } /* CEE PFC data to ETS config */ dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> I40E_AQC_CEE_APP_STATUS_SHIFT; err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; /* Add APPs if Error is False and Oper/Sync is True */ if (!err) { /* CEE operating configuration supports FCoE/iSCSI/FIP only */ dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; /* FCoE APP */ dcbcfg->app[0].priority = (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> I40E_AQC_CEE_APP_FCOE_SHIFT; dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; /* iSCSI APP */ dcbcfg->app[1].priority = (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> I40E_AQC_CEE_APP_ISCSI_SHIFT; dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; /* FIP APP */ dcbcfg->app[2].priority = (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> I40E_AQC_CEE_APP_FIP_SHIFT; dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; } } /** * i40e_cee_to_dcb_config * @cee_cfg: pointer to CEE configuration struct * @dcbcfg: DCB configuration struct * * Convert CEE configuration from firmware to DCB configuration **/ static void i40e_cee_to_dcb_config( struct i40e_aqc_get_cee_dcb_cfg_resp *cee_cfg, struct i40e_dcbx_config *dcbcfg) { u32 status, tlv_status = LE32_TO_CPU(cee_cfg->tlv_status); u16 app_prio = LE16_TO_CPU(cee_cfg->oper_app_prio); u8 i, tc, err, sync, oper; /* CEE PG data to ETS config */ dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; for (i = 0; i < 4; i++) { tc = (u8)((cee_cfg->oper_prio_tc[i] & I40E_CEE_PGID_PRIO_1_MASK) >> I40E_CEE_PGID_PRIO_1_SHIFT); dcbcfg->etscfg.prioritytable[i*2] = tc; tc = (u8)((cee_cfg->oper_prio_tc[i] & I40E_CEE_PGID_PRIO_0_MASK) >> I40E_CEE_PGID_PRIO_0_SHIFT); dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; } for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) dcbcfg->etscfg.tcbwtable[i] = cee_cfg->oper_tc_bw[i]; for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { if (dcbcfg->etscfg.prioritytable[i] == I40E_CEE_PGID_STRICT) { /* Map it to next empty TC */ dcbcfg->etscfg.prioritytable[i] = cee_cfg->oper_num_tc - 1; dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_STRICT; } else { dcbcfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS; } } /* CEE PFC data to ETS config */ dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> I40E_AQC_CEE_APP_STATUS_SHIFT; err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; /* Add APPs if Error is False and Oper/Sync is True */ if (!err && sync && oper) { /* CEE operating configuration supports FCoE/iSCSI/FIP only */ dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; /* FCoE APP */ dcbcfg->app[0].priority = (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> I40E_AQC_CEE_APP_FCOE_SHIFT; dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; /* iSCSI APP */ dcbcfg->app[1].priority = (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> I40E_AQC_CEE_APP_ISCSI_SHIFT; dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; /* FIP APP */ dcbcfg->app[2].priority = (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> I40E_AQC_CEE_APP_FIP_SHIFT; dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; } } /** * i40e_get_dcb_config * @hw: pointer to the hw struct * * Get DCB configuration from the Firmware **/ enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw) { enum i40e_status_code ret = I40E_SUCCESS; struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; /* If Firmware version < v4.33 IEEE only */ if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || (hw->aq.fw_maj_ver < 4)) goto ieee; /* If Firmware version == v4.33 use old CEE struct */ if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, sizeof(cee_v1_cfg), NULL); if (ret == I40E_SUCCESS) { /* CEE mode */ hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; i40e_cee_to_dcb_v1_config(&cee_v1_cfg, &hw->local_dcbx_config); } } else { ret = i40e_aq_get_cee_dcb_config(hw, &cee_cfg, sizeof(cee_cfg), NULL); if (ret == I40E_SUCCESS) { /* CEE mode */ hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; i40e_cee_to_dcb_config(&cee_cfg, &hw->local_dcbx_config); } } /* CEE mode not enabled try querying IEEE data */ if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) goto ieee; else goto out; ieee: /* IEEE mode */ hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; /* Get Local DCB Config */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, &hw->local_dcbx_config); if (ret) goto out; /* Get Remote DCB Config */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, &hw->remote_dcbx_config); /* Don't treat ENOENT as an error for Remote MIBs */ if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) ret = I40E_SUCCESS; out: return ret; } /** * i40e_init_dcb * @hw: pointer to the hw struct * * Update DCB configuration from the Firmware **/ enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw) { enum i40e_status_code ret = I40E_SUCCESS; struct i40e_lldp_variables lldp_cfg; u8 adminstatus = 0; if (!hw->func_caps.dcb) return ret; /* Read LLDP NVM area */ ret = i40e_read_lldp_cfg(hw, &lldp_cfg); if (ret) return ret; /* Get the LLDP AdminStatus for the current port */ adminstatus = lldp_cfg.adminstatus >> (hw->port * 4); adminstatus &= 0xF; /* LLDP agent disabled */ if (!adminstatus) { hw->dcbx_status = I40E_DCBX_STATUS_DISABLED; return ret; } /* Get DCBX status */ ret = i40e_get_dcbx_status(hw, &hw->dcbx_status); if (ret) return ret; /* Check the DCBX Status */ switch (hw->dcbx_status) { case I40E_DCBX_STATUS_DONE: case I40E_DCBX_STATUS_IN_PROGRESS: /* Get current DCBX configuration */ ret = i40e_get_dcb_config(hw); if (ret) return ret; break; case I40E_DCBX_STATUS_DISABLED: return ret; case I40E_DCBX_STATUS_NOT_STARTED: case I40E_DCBX_STATUS_MULTIPLE_PEERS: default: break; } /* Configure the LLDP MIB change event */ ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL); if (ret) return ret; return ret; } /** * i40e_read_lldp_cfg - read LLDP Configuration data from NVM * @hw: pointer to the HW structure * @lldp_cfg: pointer to hold lldp configuration variables * * Reads the LLDP configuration data from NVM **/ enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw, struct i40e_lldp_variables *lldp_cfg) { enum i40e_status_code ret = I40E_SUCCESS; u32 offset = (2 * I40E_NVM_LLDP_CFG_PTR); if (!lldp_cfg) return I40E_ERR_PARAM; ret = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (ret != I40E_SUCCESS) goto err_lldp_cfg; ret = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR, offset, sizeof(struct i40e_lldp_variables), (u8 *)lldp_cfg, true, NULL); i40e_release_nvm(hw); err_lldp_cfg: return ret; } ================================================ FILE: drivers/net/i40e/base/i40e_dcb.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_DCB_H_ #define _I40E_DCB_H_ #include "i40e_type.h" #define I40E_DCBX_OFFLOAD_DISABLED 0 #define I40E_DCBX_OFFLOAD_ENABLED 1 #define I40E_DCBX_STATUS_NOT_STARTED 0 #define I40E_DCBX_STATUS_IN_PROGRESS 1 #define I40E_DCBX_STATUS_DONE 2 #define I40E_DCBX_STATUS_MULTIPLE_PEERS 3 #define I40E_DCBX_STATUS_DISABLED 7 #define I40E_TLV_TYPE_END 0 #define I40E_TLV_TYPE_ORG 127 #define I40E_IEEE_8021QAZ_OUI 0x0080C2 #define I40E_IEEE_SUBTYPE_ETS_CFG 9 #define I40E_IEEE_SUBTYPE_ETS_REC 10 #define I40E_IEEE_SUBTYPE_PFC_CFG 11 #define I40E_IEEE_SUBTYPE_APP_PRI 12 #define I40E_LLDP_ADMINSTATUS_DISABLED 0 #define I40E_LLDP_ADMINSTATUS_ENABLED_RX 1 #define I40E_LLDP_ADMINSTATUS_ENABLED_TX 2 #define I40E_LLDP_ADMINSTATUS_ENABLED_RXTX 3 /* Defines for LLDP TLV header */ #define I40E_LLDP_MIB_HLEN 14 #define I40E_LLDP_TLV_LEN_SHIFT 0 #define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT) #define I40E_LLDP_TLV_TYPE_SHIFT 9 #define I40E_LLDP_TLV_TYPE_MASK (0x7F << I40E_LLDP_TLV_TYPE_SHIFT) #define I40E_LLDP_TLV_SUBTYPE_SHIFT 0 #define I40E_LLDP_TLV_SUBTYPE_MASK (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT) #define I40E_LLDP_TLV_OUI_SHIFT 8 #define I40E_LLDP_TLV_OUI_MASK (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT) /* Defines for IEEE ETS TLV */ #define I40E_IEEE_ETS_MAXTC_SHIFT 0 #define I40E_IEEE_ETS_MAXTC_MASK (0x7 << I40E_IEEE_ETS_MAXTC_SHIFT) #define I40E_IEEE_ETS_CBS_SHIFT 6 #define I40E_IEEE_ETS_CBS_MASK (0x1 << I40E_IEEE_ETS_CBS_SHIFT) #define I40E_IEEE_ETS_WILLING_SHIFT 7 #define I40E_IEEE_ETS_WILLING_MASK (0x1 << I40E_IEEE_ETS_WILLING_SHIFT) #define I40E_IEEE_ETS_PRIO_0_SHIFT 0 #define I40E_IEEE_ETS_PRIO_0_MASK (0x7 << I40E_IEEE_ETS_PRIO_0_SHIFT) #define I40E_IEEE_ETS_PRIO_1_SHIFT 4 #define I40E_IEEE_ETS_PRIO_1_MASK (0x7 << I40E_IEEE_ETS_PRIO_1_SHIFT) #define I40E_CEE_PGID_PRIO_0_SHIFT 0 #define I40E_CEE_PGID_PRIO_0_MASK (0xF << I40E_CEE_PGID_PRIO_0_SHIFT) #define I40E_CEE_PGID_PRIO_1_SHIFT 4 #define I40E_CEE_PGID_PRIO_1_MASK (0xF << I40E_CEE_PGID_PRIO_1_SHIFT) #define I40E_CEE_PGID_STRICT 15 /* Defines for IEEE TSA types */ #define I40E_IEEE_TSA_STRICT 0 #define I40E_IEEE_TSA_CBS 1 #define I40E_IEEE_TSA_ETS 2 #define I40E_IEEE_TSA_VENDOR 255 /* Defines for IEEE PFC TLV */ #define I40E_IEEE_PFC_CAP_SHIFT 0 #define I40E_IEEE_PFC_CAP_MASK (0xF << I40E_IEEE_PFC_CAP_SHIFT) #define I40E_IEEE_PFC_MBC_SHIFT 6 #define I40E_IEEE_PFC_MBC_MASK (0x1 << I40E_IEEE_PFC_MBC_SHIFT) #define I40E_IEEE_PFC_WILLING_SHIFT 7 #define I40E_IEEE_PFC_WILLING_MASK (0x1 << I40E_IEEE_PFC_WILLING_SHIFT) /* Defines for IEEE APP TLV */ #define I40E_IEEE_APP_SEL_SHIFT 0 #define I40E_IEEE_APP_SEL_MASK (0x7 << I40E_IEEE_APP_SEL_SHIFT) #define I40E_IEEE_APP_PRIO_SHIFT 5 #define I40E_IEEE_APP_PRIO_MASK (0x7 << I40E_IEEE_APP_PRIO_SHIFT) /* TLV definitions for preparing MIB */ #define I40E_TLV_ID_CHASSIS_ID 0 #define I40E_TLV_ID_PORT_ID 1 #define I40E_TLV_ID_TIME_TO_LIVE 2 #define I40E_IEEE_TLV_ID_ETS_CFG 3 #define I40E_IEEE_TLV_ID_ETS_REC 4 #define I40E_IEEE_TLV_ID_PFC_CFG 5 #define I40E_IEEE_TLV_ID_APP_PRI 6 #define I40E_TLV_ID_END_OF_LLDPPDU 7 #define I40E_TLV_ID_START I40E_IEEE_TLV_ID_ETS_CFG #define I40E_IEEE_ETS_TLV_LENGTH 25 #define I40E_IEEE_PFC_TLV_LENGTH 6 #define I40E_IEEE_APP_TLV_LENGTH 11 #pragma pack(1) /* IEEE 802.1AB LLDP TLV structure */ struct i40e_lldp_generic_tlv { __be16 typelength; u8 tlvinfo[1]; }; /* IEEE 802.1AB LLDP Organization specific TLV */ struct i40e_lldp_org_tlv { __be16 typelength; __be32 ouisubtype; u8 tlvinfo[1]; }; #pragma pack() /* * TODO: The below structures related LLDP/DCBX variables * and statistics are defined but need to find how to get * the required information from the Firmware to use them */ /* IEEE 802.1AB LLDP Agent Statistics */ struct i40e_lldp_stats { u64 remtablelastchangetime; u64 remtableinserts; u64 remtabledeletes; u64 remtabledrops; u64 remtableageouts; u64 txframestotal; u64 rxframesdiscarded; u64 rxportframeerrors; u64 rxportframestotal; u64 rxporttlvsdiscardedtotal; u64 rxporttlvsunrecognizedtotal; u64 remtoomanyneighbors; }; /* IEEE 802.1Qaz DCBX variables */ struct i40e_dcbx_variables { u32 defmaxtrafficclasses; u32 defprioritytcmapping; u32 deftcbandwidth; u32 deftsaassignment; }; enum i40e_status_code i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status); enum i40e_status_code i40e_lldp_to_dcb_config(u8 *lldpmib, struct i40e_dcbx_config *dcbcfg); enum i40e_status_code i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type, u8 bridgetype, struct i40e_dcbx_config *dcbcfg); enum i40e_status_code i40e_get_dcb_config(struct i40e_hw *hw); enum i40e_status_code i40e_init_dcb(struct i40e_hw *hw); #endif /* _I40E_DCB_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_diag.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_diag.h" #include "i40e_prototype.h" /** * i40e_diag_set_loopback * @hw: pointer to the hw struct * @mode: loopback mode * * Set chosen loopback mode **/ enum i40e_status_code i40e_diag_set_loopback(struct i40e_hw *hw, enum i40e_lb_mode mode) { enum i40e_status_code ret_code = I40E_SUCCESS; if (i40e_aq_set_lb_modes(hw, mode, NULL)) ret_code = I40E_ERR_DIAG_TEST_FAILED; return ret_code; } /** * i40e_diag_reg_pattern_test * @hw: pointer to the hw struct * @reg: reg to be tested * @mask: bits to be touched **/ static enum i40e_status_code i40e_diag_reg_pattern_test(struct i40e_hw *hw, u32 reg, u32 mask) { const u32 patterns[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; u32 pat, val, orig_val; int i; orig_val = rd32(hw, reg); for (i = 0; i < ARRAY_SIZE(patterns); i++) { pat = patterns[i]; wr32(hw, reg, (pat & mask)); val = rd32(hw, reg); if ((val & mask) != (pat & mask)) { return I40E_ERR_DIAG_TEST_FAILED; } } wr32(hw, reg, orig_val); val = rd32(hw, reg); if (val != orig_val) { return I40E_ERR_DIAG_TEST_FAILED; } return I40E_SUCCESS; } struct i40e_diag_reg_test_info i40e_reg_list[] = { /* offset mask elements stride */ {I40E_QTX_CTL(0), 0x0000FFBF, 1, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)}, {I40E_PFINT_ITR0(0), 0x00000FFF, 3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)}, {I40E_PFINT_ITRN(0, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)}, {I40E_PFINT_ITRN(1, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)}, {I40E_PFINT_ITRN(2, 0), 0x00000FFF, 1, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)}, {I40E_PFINT_STAT_CTL0, 0x0000000C, 1, 0}, {I40E_PFINT_LNKLST0, 0x00001FFF, 1, 0}, {I40E_PFINT_LNKLSTN(0), 0x000007FF, 1, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)}, {I40E_QINT_TQCTL(0), 0x000000FF, 1, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)}, {I40E_QINT_RQCTL(0), 0x000000FF, 1, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)}, {I40E_PFINT_ICR0_ENA, 0xF7F20000, 1, 0}, { 0 } }; /** * i40e_diag_reg_test * @hw: pointer to the hw struct * * Perform registers diagnostic test **/ enum i40e_status_code i40e_diag_reg_test(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; u32 reg, mask; u32 i, j; for (i = 0; i40e_reg_list[i].offset != 0 && ret_code == I40E_SUCCESS; i++) { /* set actual reg range for dynamically allocated resources */ if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) && hw->func_caps.num_tx_qp != 0) i40e_reg_list[i].elements = hw->func_caps.num_tx_qp; if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) || i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) || i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) || i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) || i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) && hw->func_caps.num_msix_vectors != 0) i40e_reg_list[i].elements = hw->func_caps.num_msix_vectors - 1; /* test register access */ mask = i40e_reg_list[i].mask; for (j = 0; j < i40e_reg_list[i].elements && ret_code == I40E_SUCCESS; j++) { reg = i40e_reg_list[i].offset + (j * i40e_reg_list[i].stride); ret_code = i40e_diag_reg_pattern_test(hw, reg, mask); } } return ret_code; } /** * i40e_diag_eeprom_test * @hw: pointer to the hw struct * * Perform EEPROM diagnostic test **/ enum i40e_status_code i40e_diag_eeprom_test(struct i40e_hw *hw) { enum i40e_status_code ret_code; u16 reg_val; /* read NVM control word and if NVM valid, validate EEPROM checksum*/ ret_code = i40e_read_nvm_word(hw, I40E_SR_NVM_CONTROL_WORD, ®_val); if ((ret_code == I40E_SUCCESS) && ((reg_val & I40E_SR_CONTROL_WORD_1_MASK) == (0x01 << I40E_SR_CONTROL_WORD_1_SHIFT))) { ret_code = i40e_validate_nvm_checksum(hw, NULL); } else { ret_code = I40E_ERR_DIAG_TEST_FAILED; } return ret_code; } /** * i40e_diag_fw_alive_test * @hw: pointer to the hw struct * * Perform FW alive diagnostic test **/ enum i40e_status_code i40e_diag_fw_alive_test(struct i40e_hw *hw) { UNREFERENCED_1PARAMETER(hw); return I40E_SUCCESS; } ================================================ FILE: drivers/net/i40e/base/i40e_diag.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_DIAG_H_ #define _I40E_DIAG_H_ #include "i40e_type.h" enum i40e_lb_mode { I40E_LB_MODE_NONE = 0x0, I40E_LB_MODE_PHY_LOCAL = I40E_AQ_LB_PHY_LOCAL, I40E_LB_MODE_PHY_REMOTE = I40E_AQ_LB_PHY_REMOTE, I40E_LB_MODE_MAC_LOCAL = I40E_AQ_LB_MAC_LOCAL, }; struct i40e_diag_reg_test_info { u32 offset; /* the base register */ u32 mask; /* bits that can be tested */ u32 elements; /* number of elements if array */ u32 stride; /* bytes between each element */ }; extern struct i40e_diag_reg_test_info i40e_reg_list[]; enum i40e_status_code i40e_diag_set_loopback(struct i40e_hw *hw, enum i40e_lb_mode mode); enum i40e_status_code i40e_diag_fw_alive_test(struct i40e_hw *hw); enum i40e_status_code i40e_diag_reg_test(struct i40e_hw *hw); enum i40e_status_code i40e_diag_eeprom_test(struct i40e_hw *hw); #endif /* _I40E_DIAG_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_hmc.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_osdep.h" #include "i40e_register.h" #include "i40e_status.h" #include "i40e_alloc.h" #include "i40e_hmc.h" #include "i40e_type.h" /** * i40e_add_sd_table_entry - Adds a segment descriptor to the table * @hw: pointer to our hw struct * @hmc_info: pointer to the HMC configuration information struct * @sd_index: segment descriptor index to manipulate * @type: what type of segment descriptor we're manipulating * @direct_mode_sz: size to alloc in direct mode **/ enum i40e_status_code i40e_add_sd_table_entry(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 sd_index, enum i40e_sd_entry_type type, u64 direct_mode_sz) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_sd_entry *sd_entry; enum i40e_memory_type mem_type; bool dma_mem_alloc_done = false; struct i40e_dma_mem mem; u64 alloc_len; if (NULL == hmc_info->sd_table.sd_entry) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_add_sd_table_entry: bad sd_entry\n"); goto exit; } if (sd_index >= hmc_info->sd_table.sd_cnt) { ret_code = I40E_ERR_INVALID_SD_INDEX; DEBUGOUT("i40e_add_sd_table_entry: bad sd_index\n"); goto exit; } sd_entry = &hmc_info->sd_table.sd_entry[sd_index]; if (!sd_entry->valid) { if (I40E_SD_TYPE_PAGED == type) { mem_type = i40e_mem_pd; alloc_len = I40E_HMC_PAGED_BP_SIZE; } else { mem_type = i40e_mem_bp_jumbo; alloc_len = direct_mode_sz; } /* allocate a 4K pd page or 2M backing page */ ret_code = i40e_allocate_dma_mem(hw, &mem, mem_type, alloc_len, I40E_HMC_PD_BP_BUF_ALIGNMENT); if (ret_code) goto exit; dma_mem_alloc_done = true; if (I40E_SD_TYPE_PAGED == type) { ret_code = i40e_allocate_virt_mem(hw, &sd_entry->u.pd_table.pd_entry_virt_mem, sizeof(struct i40e_hmc_pd_entry) * 512); if (ret_code) goto exit; sd_entry->u.pd_table.pd_entry = (struct i40e_hmc_pd_entry *) sd_entry->u.pd_table.pd_entry_virt_mem.va; i40e_memcpy(&sd_entry->u.pd_table.pd_page_addr, &mem, sizeof(struct i40e_dma_mem), I40E_NONDMA_TO_NONDMA); } else { i40e_memcpy(&sd_entry->u.bp.addr, &mem, sizeof(struct i40e_dma_mem), I40E_NONDMA_TO_NONDMA); sd_entry->u.bp.sd_pd_index = sd_index; } /* initialize the sd entry */ hmc_info->sd_table.sd_entry[sd_index].entry_type = type; /* increment the ref count */ I40E_INC_SD_REFCNT(&hmc_info->sd_table); } /* Increment backing page reference count */ if (I40E_SD_TYPE_DIRECT == sd_entry->entry_type) I40E_INC_BP_REFCNT(&sd_entry->u.bp); exit: if (I40E_SUCCESS != ret_code) if (dma_mem_alloc_done) i40e_free_dma_mem(hw, &mem); return ret_code; } /** * i40e_add_pd_table_entry - Adds page descriptor to the specified table * @hw: pointer to our HW structure * @hmc_info: pointer to the HMC configuration information structure * @pd_index: which page descriptor index to manipulate * * This function: * 1. Initializes the pd entry * 2. Adds pd_entry in the pd_table * 3. Mark the entry valid in i40e_hmc_pd_entry structure * 4. Initializes the pd_entry's ref count to 1 * assumptions: * 1. The memory for pd should be pinned down, physically contiguous and * aligned on 4K boundary and zeroed memory. * 2. It should be 4K in size. **/ enum i40e_status_code i40e_add_pd_table_entry(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 pd_index) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_pd_table *pd_table; struct i40e_hmc_pd_entry *pd_entry; struct i40e_dma_mem mem; u32 sd_idx, rel_pd_idx; u64 *pd_addr; u64 page_desc; if (pd_index / I40E_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) { ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX; DEBUGOUT("i40e_add_pd_table_entry: bad pd_index\n"); goto exit; } /* find corresponding sd */ sd_idx = (pd_index / I40E_HMC_PD_CNT_IN_SD); if (I40E_SD_TYPE_PAGED != hmc_info->sd_table.sd_entry[sd_idx].entry_type) goto exit; rel_pd_idx = (pd_index % I40E_HMC_PD_CNT_IN_SD); pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; pd_entry = &pd_table->pd_entry[rel_pd_idx]; if (!pd_entry->valid) { /* allocate a 4K backing page */ ret_code = i40e_allocate_dma_mem(hw, &mem, i40e_mem_bp, I40E_HMC_PAGED_BP_SIZE, I40E_HMC_PD_BP_BUF_ALIGNMENT); if (ret_code) goto exit; i40e_memcpy(&pd_entry->bp.addr, &mem, sizeof(struct i40e_dma_mem), I40E_NONDMA_TO_NONDMA); pd_entry->bp.sd_pd_index = pd_index; pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED; /* Set page address and valid bit */ page_desc = mem.pa | 0x1; pd_addr = (u64 *)pd_table->pd_page_addr.va; pd_addr += rel_pd_idx; /* Add the backing page physical address in the pd entry */ i40e_memcpy(pd_addr, &page_desc, sizeof(u64), I40E_NONDMA_TO_DMA); pd_entry->sd_index = sd_idx; pd_entry->valid = true; I40E_INC_PD_REFCNT(pd_table); } I40E_INC_BP_REFCNT(&pd_entry->bp); exit: return ret_code; } /** * i40e_remove_pd_bp - remove a backing page from a page descriptor * @hw: pointer to our HW structure * @hmc_info: pointer to the HMC configuration information structure * @idx: the page index * @is_pf: distinguishes a VF from a PF * * This function: * 1. Marks the entry in pd tabe (for paged address mode) or in sd table * (for direct address mode) invalid. * 2. Write to register PMPDINV to invalidate the backing page in FV cache * 3. Decrement the ref count for the pd _entry * assumptions: * 1. Caller can deallocate the memory used by backing storage after this * function returns. **/ enum i40e_status_code i40e_remove_pd_bp(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_pd_entry *pd_entry; struct i40e_hmc_pd_table *pd_table; struct i40e_hmc_sd_entry *sd_entry; u32 sd_idx, rel_pd_idx; u64 *pd_addr; /* calculate index */ sd_idx = idx / I40E_HMC_PD_CNT_IN_SD; rel_pd_idx = idx % I40E_HMC_PD_CNT_IN_SD; if (sd_idx >= hmc_info->sd_table.sd_cnt) { ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX; DEBUGOUT("i40e_remove_pd_bp: bad idx\n"); goto exit; } sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; if (I40E_SD_TYPE_PAGED != sd_entry->entry_type) { ret_code = I40E_ERR_INVALID_SD_TYPE; DEBUGOUT("i40e_remove_pd_bp: wrong sd_entry type\n"); goto exit; } /* get the entry and decrease its ref counter */ pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; pd_entry = &pd_table->pd_entry[rel_pd_idx]; I40E_DEC_BP_REFCNT(&pd_entry->bp); if (pd_entry->bp.ref_cnt) goto exit; /* mark the entry invalid */ pd_entry->valid = false; I40E_DEC_PD_REFCNT(pd_table); pd_addr = (u64 *)pd_table->pd_page_addr.va; pd_addr += rel_pd_idx; i40e_memset(pd_addr, 0, sizeof(u64), I40E_DMA_MEM); I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx); /* free memory here */ ret_code = i40e_free_dma_mem(hw, &(pd_entry->bp.addr)); if (I40E_SUCCESS != ret_code) goto exit; if (!pd_table->ref_cnt) i40e_free_virt_mem(hw, &pd_table->pd_entry_virt_mem); exit: return ret_code; } /** * i40e_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry * @hmc_info: pointer to the HMC configuration information structure * @idx: the page index **/ enum i40e_status_code i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info, u32 idx) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_sd_entry *sd_entry; /* get the entry and decrease its ref counter */ sd_entry = &hmc_info->sd_table.sd_entry[idx]; I40E_DEC_BP_REFCNT(&sd_entry->u.bp); if (sd_entry->u.bp.ref_cnt) { ret_code = I40E_ERR_NOT_READY; goto exit; } I40E_DEC_SD_REFCNT(&hmc_info->sd_table); /* mark the entry invalid */ sd_entry->valid = false; exit: return ret_code; } /** * i40e_remove_sd_bp_new - Removes a backing page from a segment descriptor * @hw: pointer to our hw struct * @hmc_info: pointer to the HMC configuration information structure * @idx: the page index * @is_pf: used to distinguish between VF and PF **/ enum i40e_status_code i40e_remove_sd_bp_new(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx, bool is_pf) { struct i40e_hmc_sd_entry *sd_entry; enum i40e_status_code ret_code = I40E_SUCCESS; /* get the entry and decrease its ref counter */ sd_entry = &hmc_info->sd_table.sd_entry[idx]; if (is_pf) { I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_DIRECT); } else { ret_code = I40E_NOT_SUPPORTED; goto exit; } ret_code = i40e_free_dma_mem(hw, &(sd_entry->u.bp.addr)); if (I40E_SUCCESS != ret_code) goto exit; exit: return ret_code; } /** * i40e_prep_remove_pd_page - Prepares to remove a PD page from sd entry. * @hmc_info: pointer to the HMC configuration information structure * @idx: segment descriptor index to find the relevant page descriptor **/ enum i40e_status_code i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info, u32 idx) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_sd_entry *sd_entry; sd_entry = &hmc_info->sd_table.sd_entry[idx]; if (sd_entry->u.pd_table.ref_cnt) { ret_code = I40E_ERR_NOT_READY; goto exit; } /* mark the entry invalid */ sd_entry->valid = false; I40E_DEC_SD_REFCNT(&hmc_info->sd_table); exit: return ret_code; } /** * i40e_remove_pd_page_new - Removes a PD page from sd entry. * @hw: pointer to our hw struct * @hmc_info: pointer to the HMC configuration information structure * @idx: segment descriptor index to find the relevant page descriptor * @is_pf: used to distinguish between VF and PF **/ enum i40e_status_code i40e_remove_pd_page_new(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx, bool is_pf) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_sd_entry *sd_entry; sd_entry = &hmc_info->sd_table.sd_entry[idx]; if (is_pf) { I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_PAGED); } else { ret_code = I40E_NOT_SUPPORTED; goto exit; } /* free memory here */ ret_code = i40e_free_dma_mem(hw, &(sd_entry->u.pd_table.pd_page_addr)); if (I40E_SUCCESS != ret_code) goto exit; exit: return ret_code; } ================================================ FILE: drivers/net/i40e/base/i40e_hmc.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_HMC_H_ #define _I40E_HMC_H_ #define I40E_HMC_MAX_BP_COUNT 512 /* forward-declare the HW struct for the compiler */ struct i40e_hw; #define I40E_HMC_INFO_SIGNATURE 0x484D5347 /* HMSG */ #define I40E_HMC_PD_CNT_IN_SD 512 #define I40E_HMC_DIRECT_BP_SIZE 0x200000 /* 2M */ #define I40E_HMC_PAGED_BP_SIZE 4096 #define I40E_HMC_PD_BP_BUF_ALIGNMENT 4096 #define I40E_FIRST_VF_FPM_ID 16 struct i40e_hmc_obj_info { u64 base; /* base addr in FPM */ u32 max_cnt; /* max count available for this hmc func */ u32 cnt; /* count of objects driver actually wants to create */ u64 size; /* size in bytes of one object */ }; enum i40e_sd_entry_type { I40E_SD_TYPE_INVALID = 0, I40E_SD_TYPE_PAGED = 1, I40E_SD_TYPE_DIRECT = 2 }; struct i40e_hmc_bp { enum i40e_sd_entry_type entry_type; struct i40e_dma_mem addr; /* populate to be used by hw */ u32 sd_pd_index; u32 ref_cnt; }; struct i40e_hmc_pd_entry { struct i40e_hmc_bp bp; u32 sd_index; bool valid; }; struct i40e_hmc_pd_table { struct i40e_dma_mem pd_page_addr; /* populate to be used by hw */ struct i40e_hmc_pd_entry *pd_entry; /* [512] for sw book keeping */ struct i40e_virt_mem pd_entry_virt_mem; /* virt mem for pd_entry */ u32 ref_cnt; u32 sd_index; }; struct i40e_hmc_sd_entry { enum i40e_sd_entry_type entry_type; bool valid; union { struct i40e_hmc_pd_table pd_table; struct i40e_hmc_bp bp; } u; }; struct i40e_hmc_sd_table { struct i40e_virt_mem addr; /* used to track sd_entry allocations */ u32 sd_cnt; u32 ref_cnt; struct i40e_hmc_sd_entry *sd_entry; /* (sd_cnt*512) entries max */ }; struct i40e_hmc_info { u32 signature; /* equals to pci func num for PF and dynamically allocated for VFs */ u8 hmc_fn_id; u16 first_sd_index; /* index of the first available SD */ /* hmc objects */ struct i40e_hmc_obj_info *hmc_obj; struct i40e_virt_mem hmc_obj_virt_mem; struct i40e_hmc_sd_table sd_table; }; #define I40E_INC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt++) #define I40E_INC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt++) #define I40E_INC_BP_REFCNT(bp) ((bp)->ref_cnt++) #define I40E_DEC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt--) #define I40E_DEC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt--) #define I40E_DEC_BP_REFCNT(bp) ((bp)->ref_cnt--) /** * I40E_SET_PF_SD_ENTRY - marks the sd entry as valid in the hardware * @hw: pointer to our hw struct * @pa: pointer to physical address * @sd_index: segment descriptor index * @type: if sd entry is direct or paged **/ #define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type) \ { \ u32 val1, val2, val3; \ val1 = (u32)(I40E_HI_DWORD(pa)); \ val2 = (u32)(pa) | (I40E_HMC_MAX_BP_COUNT << \ I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \ ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \ I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \ (1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \ wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \ wr32((hw), I40E_PFHMC_SDDATALOW, val2); \ wr32((hw), I40E_PFHMC_SDCMD, val3); \ } /** * I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware * @hw: pointer to our hw struct * @sd_index: segment descriptor index * @type: if sd entry is direct or paged **/ #define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type) \ { \ u32 val2, val3; \ val2 = (I40E_HMC_MAX_BP_COUNT << \ I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \ ((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \ I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \ val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \ wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \ wr32((hw), I40E_PFHMC_SDDATALOW, val2); \ wr32((hw), I40E_PFHMC_SDCMD, val3); \ } /** * I40E_INVALIDATE_PF_HMC_PD - Invalidates the pd cache in the hardware * @hw: pointer to our hw struct * @sd_idx: segment descriptor index * @pd_idx: page descriptor index **/ #define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx) \ wr32((hw), I40E_PFHMC_PDINV, \ (((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) | \ ((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT))) /** * I40E_FIND_SD_INDEX_LIMIT - finds segment descriptor index limit * @hmc_info: pointer to the HMC configuration information structure * @type: type of HMC resources we're searching * @index: starting index for the object * @cnt: number of objects we're trying to create * @sd_idx: pointer to return index of the segment descriptor in question * @sd_limit: pointer to return the maximum number of segment descriptors * * This function calculates the segment descriptor index and index limit * for the resource defined by i40e_hmc_rsrc_type. **/ #define I40E_FIND_SD_INDEX_LIMIT(hmc_info, type, index, cnt, sd_idx, sd_limit)\ { \ u64 fpm_addr, fpm_limit; \ fpm_addr = (hmc_info)->hmc_obj[(type)].base + \ (hmc_info)->hmc_obj[(type)].size * (index); \ fpm_limit = fpm_addr + (hmc_info)->hmc_obj[(type)].size * (cnt);\ *(sd_idx) = (u32)(fpm_addr / I40E_HMC_DIRECT_BP_SIZE); \ *(sd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_DIRECT_BP_SIZE); \ /* add one more to the limit to correct our range */ \ *(sd_limit) += 1; \ } /** * I40E_FIND_PD_INDEX_LIMIT - finds page descriptor index limit * @hmc_info: pointer to the HMC configuration information struct * @type: HMC resource type we're examining * @idx: starting index for the object * @cnt: number of objects we're trying to create * @pd_index: pointer to return page descriptor index * @pd_limit: pointer to return page descriptor index limit * * Calculates the page descriptor index and index limit for the resource * defined by i40e_hmc_rsrc_type. **/ #define I40E_FIND_PD_INDEX_LIMIT(hmc_info, type, idx, cnt, pd_index, pd_limit)\ { \ u64 fpm_adr, fpm_limit; \ fpm_adr = (hmc_info)->hmc_obj[(type)].base + \ (hmc_info)->hmc_obj[(type)].size * (idx); \ fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); \ *(pd_index) = (u32)(fpm_adr / I40E_HMC_PAGED_BP_SIZE); \ *(pd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_PAGED_BP_SIZE); \ /* add one more to the limit to correct our range */ \ *(pd_limit) += 1; \ } enum i40e_status_code i40e_add_sd_table_entry(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 sd_index, enum i40e_sd_entry_type type, u64 direct_mode_sz); enum i40e_status_code i40e_add_pd_table_entry(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 pd_index); enum i40e_status_code i40e_remove_pd_bp(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx); enum i40e_status_code i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info, u32 idx); enum i40e_status_code i40e_remove_sd_bp_new(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx, bool is_pf); enum i40e_status_code i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info, u32 idx); enum i40e_status_code i40e_remove_pd_page_new(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx, bool is_pf); #endif /* _I40E_HMC_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_lan_hmc.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_osdep.h" #include "i40e_register.h" #include "i40e_type.h" #include "i40e_hmc.h" #include "i40e_lan_hmc.h" #include "i40e_prototype.h" /* lan specific interface functions */ /** * i40e_align_l2obj_base - aligns base object pointer to 512 bytes * @offset: base address offset needing alignment * * Aligns the layer 2 function private memory so it's 512-byte aligned. **/ STATIC u64 i40e_align_l2obj_base(u64 offset) { u64 aligned_offset = offset; if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0) aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT - (offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT)); return aligned_offset; } /** * i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size * @txq_num: number of Tx queues needing backing context * @rxq_num: number of Rx queues needing backing context * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context * @fcoe_filt_num: number of FCoE filters needing backing context * * Calculates the maximum amount of memory for the function required, based * on the number of resources it must provide context for. **/ u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num, u32 fcoe_cntx_num, u32 fcoe_filt_num) { u64 fpm_size = 0; fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ; fpm_size = i40e_align_l2obj_base(fpm_size); fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ); fpm_size = i40e_align_l2obj_base(fpm_size); fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX); fpm_size = i40e_align_l2obj_base(fpm_size); fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT); fpm_size = i40e_align_l2obj_base(fpm_size); return fpm_size; } /** * i40e_init_lan_hmc - initialize i40e_hmc_info struct * @hw: pointer to the HW structure * @txq_num: number of Tx queues needing backing context * @rxq_num: number of Rx queues needing backing context * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context * @fcoe_filt_num: number of FCoE filters needing backing context * * This function will be called once per physical function initialization. * It will fill out the i40e_hmc_obj_info structure for LAN objects based on * the driver's provided input, as well as information from the HMC itself * loaded from NVRAM. * * Assumptions: * - HMC Resource Profile has been selected before calling this function. **/ enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, u32 rxq_num, u32 fcoe_cntx_num, u32 fcoe_filt_num) { struct i40e_hmc_obj_info *obj, *full_obj; enum i40e_status_code ret_code = I40E_SUCCESS; u64 l2fpm_size; u32 size_exp; hw->hmc.signature = I40E_HMC_INFO_SIGNATURE; hw->hmc.hmc_fn_id = hw->pf_id; /* allocate memory for hmc_obj */ ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem, sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX); if (ret_code) goto init_lan_hmc_out; hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *) hw->hmc.hmc_obj_virt_mem.va; /* The full object will be used to create the LAN HMC SD */ full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL]; full_obj->max_cnt = 0; full_obj->cnt = 0; full_obj->base = 0; full_obj->size = 0; /* Tx queue context information */ obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); obj->cnt = txq_num; obj->base = 0; size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ); obj->size = (u64)1 << size_exp; /* validate values requested by driver don't exceed HMC capacity */ if (txq_num > obj->max_cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT3("i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", txq_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; } /* aggregate values into the full LAN object for later */ full_obj->max_cnt += obj->max_cnt; full_obj->cnt += obj->cnt; /* Rx queue context information */ obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); obj->cnt = rxq_num; obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_TX].base + (hw->hmc.hmc_obj[I40E_HMC_LAN_TX].cnt * hw->hmc.hmc_obj[I40E_HMC_LAN_TX].size); obj->base = i40e_align_l2obj_base(obj->base); size_exp = rd32(hw, I40E_GLHMC_LANRXOBJSZ); obj->size = (u64)1 << size_exp; /* validate values requested by driver don't exceed HMC capacity */ if (rxq_num > obj->max_cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT3("i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", rxq_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; } /* aggregate values into the full LAN object for later */ full_obj->max_cnt += obj->max_cnt; full_obj->cnt += obj->cnt; /* FCoE context information */ obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEMAX); obj->cnt = fcoe_cntx_num; obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_RX].base + (hw->hmc.hmc_obj[I40E_HMC_LAN_RX].cnt * hw->hmc.hmc_obj[I40E_HMC_LAN_RX].size); obj->base = i40e_align_l2obj_base(obj->base); size_exp = rd32(hw, I40E_GLHMC_FCOEDDPOBJSZ); obj->size = (u64)1 << size_exp; /* validate values requested by driver don't exceed HMC capacity */ if (fcoe_cntx_num > obj->max_cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT3("i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", fcoe_cntx_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; } /* aggregate values into the full LAN object for later */ full_obj->max_cnt += obj->max_cnt; full_obj->cnt += obj->cnt; /* FCoE filter information */ obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEFMAX); obj->cnt = fcoe_filt_num; obj->base = hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].base + (hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].cnt * hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].size); obj->base = i40e_align_l2obj_base(obj->base); size_exp = rd32(hw, I40E_GLHMC_FCOEFOBJSZ); obj->size = (u64)1 << size_exp; /* validate values requested by driver don't exceed HMC capacity */ if (fcoe_filt_num > obj->max_cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT3("i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n", fcoe_filt_num, obj->max_cnt, ret_code); goto init_lan_hmc_out; } /* aggregate values into the full LAN object for later */ full_obj->max_cnt += obj->max_cnt; full_obj->cnt += obj->cnt; hw->hmc.first_sd_index = 0; hw->hmc.sd_table.ref_cnt = 0; l2fpm_size = i40e_calculate_l2fpm_size(txq_num, rxq_num, fcoe_cntx_num, fcoe_filt_num); if (NULL == hw->hmc.sd_table.sd_entry) { hw->hmc.sd_table.sd_cnt = (u32) (l2fpm_size + I40E_HMC_DIRECT_BP_SIZE - 1) / I40E_HMC_DIRECT_BP_SIZE; /* allocate the sd_entry members in the sd_table */ ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.sd_table.addr, (sizeof(struct i40e_hmc_sd_entry) * hw->hmc.sd_table.sd_cnt)); if (ret_code) goto init_lan_hmc_out; hw->hmc.sd_table.sd_entry = (struct i40e_hmc_sd_entry *)hw->hmc.sd_table.addr.va; } /* store in the LAN full object for later */ full_obj->size = l2fpm_size; init_lan_hmc_out: return ret_code; } /** * i40e_remove_pd_page - Remove a page from the page descriptor table * @hw: pointer to the HW structure * @hmc_info: pointer to the HMC configuration information structure * @idx: segment descriptor index to find the relevant page descriptor * * This function: * 1. Marks the entry in pd table (for paged address mode) invalid * 2. write to register PMPDINV to invalidate the backing page in FV cache * 3. Decrement the ref count for pd_entry * assumptions: * 1. caller can deallocate the memory used by pd after this function * returns. **/ STATIC enum i40e_status_code i40e_remove_pd_page(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx) { enum i40e_status_code ret_code = I40E_SUCCESS; if (i40e_prep_remove_pd_page(hmc_info, idx) == I40E_SUCCESS) ret_code = i40e_remove_pd_page_new(hw, hmc_info, idx, true); return ret_code; } /** * i40e_remove_sd_bp - remove a backing page from a segment descriptor * @hw: pointer to our HW structure * @hmc_info: pointer to the HMC configuration information structure * @idx: the page index * * This function: * 1. Marks the entry in sd table (for direct address mode) invalid * 2. write to register PMSDCMD, PMSDDATALOW(PMSDDATALOW.PMSDVALID set * to 0) and PMSDDATAHIGH to invalidate the sd page * 3. Decrement the ref count for the sd_entry * assumptions: * 1. caller can deallocate the memory used by backing storage after this * function returns. **/ STATIC enum i40e_status_code i40e_remove_sd_bp(struct i40e_hw *hw, struct i40e_hmc_info *hmc_info, u32 idx) { enum i40e_status_code ret_code = I40E_SUCCESS; if (i40e_prep_remove_sd_bp(hmc_info, idx) == I40E_SUCCESS) ret_code = i40e_remove_sd_bp_new(hw, hmc_info, idx, true); return ret_code; } /** * i40e_create_lan_hmc_object - allocate backing store for hmc objects * @hw: pointer to the HW structure * @info: pointer to i40e_hmc_create_obj_info struct * * This will allocate memory for PDs and backing pages and populate * the sd and pd entries. **/ enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw, struct i40e_hmc_lan_create_obj_info *info) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_sd_entry *sd_entry; u32 pd_idx1 = 0, pd_lmt1 = 0; u32 pd_idx = 0, pd_lmt = 0; bool pd_error = false; u32 sd_idx, sd_lmt; u64 sd_size; u32 i, j; if (NULL == info) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_create_lan_hmc_object: bad info ptr\n"); goto exit; } if (NULL == info->hmc_info) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_create_lan_hmc_object: bad hmc_info ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_create_lan_hmc_object: bad signature\n"); goto exit; } if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", ret_code); goto exit; } if ((info->start_idx + info->count) > info->hmc_info->hmc_obj[info->rsrc_type].cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", ret_code); goto exit; } /* find sd index and limit */ I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, info->start_idx, info->count, &sd_idx, &sd_lmt); if (sd_idx >= info->hmc_info->sd_table.sd_cnt || sd_lmt > info->hmc_info->sd_table.sd_cnt) { ret_code = I40E_ERR_INVALID_SD_INDEX; goto exit; } /* find pd index */ I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, info->start_idx, info->count, &pd_idx, &pd_lmt); /* This is to cover for cases where you may not want to have an SD with * the full 2M memory but something smaller. By not filling out any * size, the function will default the SD size to be 2M. */ if (info->direct_mode_sz == 0) sd_size = I40E_HMC_DIRECT_BP_SIZE; else sd_size = info->direct_mode_sz; /* check if all the sds are valid. If not, allocate a page and * initialize it. */ for (j = sd_idx; j < sd_lmt; j++) { /* update the sd table entry */ ret_code = i40e_add_sd_table_entry(hw, info->hmc_info, j, info->entry_type, sd_size); if (I40E_SUCCESS != ret_code) goto exit_sd_error; sd_entry = &info->hmc_info->sd_table.sd_entry[j]; if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { /* check if all the pds in this sd are valid. If not, * allocate a page and initialize it. */ /* find pd_idx and pd_lmt in this sd */ pd_idx1 = max(pd_idx, (j * I40E_HMC_MAX_BP_COUNT)); pd_lmt1 = min(pd_lmt, ((j + 1) * I40E_HMC_MAX_BP_COUNT)); for (i = pd_idx1; i < pd_lmt1; i++) { /* update the pd table entry */ ret_code = i40e_add_pd_table_entry(hw, info->hmc_info, i); if (I40E_SUCCESS != ret_code) { pd_error = true; break; } } if (pd_error) { /* remove the backing pages from pd_idx1 to i */ while (i && (i > pd_idx1)) { i40e_remove_pd_bp(hw, info->hmc_info, (i - 1)); i--; } } } if (!sd_entry->valid) { sd_entry->valid = true; switch (sd_entry->entry_type) { case I40E_SD_TYPE_PAGED: I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.pd_table.pd_page_addr.pa, j, sd_entry->entry_type); break; case I40E_SD_TYPE_DIRECT: I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.bp.addr.pa, j, sd_entry->entry_type); break; default: ret_code = I40E_ERR_INVALID_SD_TYPE; goto exit; } } } goto exit; exit_sd_error: /* cleanup for sd entries from j to sd_idx */ while (j && (j > sd_idx)) { sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1]; switch (sd_entry->entry_type) { case I40E_SD_TYPE_PAGED: pd_idx1 = max(pd_idx, ((j - 1) * I40E_HMC_MAX_BP_COUNT)); pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT)); for (i = pd_idx1; i < pd_lmt1; i++) { i40e_remove_pd_bp(hw, info->hmc_info, i); } i40e_remove_pd_page(hw, info->hmc_info, (j - 1)); break; case I40E_SD_TYPE_DIRECT: i40e_remove_sd_bp(hw, info->hmc_info, (j - 1)); break; default: ret_code = I40E_ERR_INVALID_SD_TYPE; break; } j--; } exit: return ret_code; } /** * i40e_configure_lan_hmc - prepare the HMC backing store * @hw: pointer to the hw structure * @model: the model for the layout of the SD/PD tables * * - This function will be called once per physical function initialization. * - This function will be called after i40e_init_lan_hmc() and before * any LAN/FCoE HMC objects can be created. **/ enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw, enum i40e_hmc_model model) { struct i40e_hmc_lan_create_obj_info info; u8 hmc_fn_id = hw->hmc.hmc_fn_id; struct i40e_hmc_obj_info *obj; enum i40e_status_code ret_code = I40E_SUCCESS; /* Initialize part of the create object info struct */ info.hmc_info = &hw->hmc; info.rsrc_type = I40E_HMC_LAN_FULL; info.start_idx = 0; info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size; /* Build the SD entry for the LAN objects */ switch (model) { case I40E_HMC_MODEL_DIRECT_PREFERRED: case I40E_HMC_MODEL_DIRECT_ONLY: info.entry_type = I40E_SD_TYPE_DIRECT; /* Make one big object, a single SD */ info.count = 1; ret_code = i40e_create_lan_hmc_object(hw, &info); if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED)) goto try_type_paged; else if (ret_code != I40E_SUCCESS) goto configure_lan_hmc_out; /* else clause falls through the break */ break; case I40E_HMC_MODEL_PAGED_ONLY: try_type_paged: info.entry_type = I40E_SD_TYPE_PAGED; /* Make one big object in the PD table */ info.count = 1; ret_code = i40e_create_lan_hmc_object(hw, &info); if (ret_code != I40E_SUCCESS) goto configure_lan_hmc_out; break; default: /* unsupported type */ ret_code = I40E_ERR_INVALID_SD_TYPE; DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n", ret_code); goto configure_lan_hmc_out; } /* Configure and program the FPM registers so objects can be created */ /* Tx contexts */ obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id), (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512)); wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt); /* Rx contexts */ obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id), (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512)); wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt); /* FCoE contexts */ obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id), (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512)); wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt); /* FCoE filters */ obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id), (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512)); wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt); configure_lan_hmc_out: return ret_code; } /** * i40e_delete_hmc_object - remove hmc objects * @hw: pointer to the HW structure * @info: pointer to i40e_hmc_delete_obj_info struct * * This will de-populate the SDs and PDs. It frees * the memory for PDS and backing storage. After this function is returned, * caller should deallocate memory allocated previously for * book-keeping information about PDs and backing storage. **/ enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw, struct i40e_hmc_lan_delete_obj_info *info) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_hmc_pd_table *pd_table; u32 pd_idx, pd_lmt, rel_pd_idx; u32 sd_idx, sd_lmt; u32 i, j; if (NULL == info) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n"); goto exit; } if (NULL == info->hmc_info) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n"); goto exit; } if (NULL == info->hmc_info->sd_table.sd_entry) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n"); goto exit; } if (NULL == info->hmc_info->hmc_obj) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n"); goto exit; } if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", ret_code); goto exit; } if ((info->start_idx + info->count) > info->hmc_info->hmc_obj[info->rsrc_type].cnt) { ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", ret_code); goto exit; } I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, info->start_idx, info->count, &pd_idx, &pd_lmt); for (j = pd_idx; j < pd_lmt; j++) { sd_idx = j / I40E_HMC_PD_CNT_IN_SD; if (I40E_SD_TYPE_PAGED != info->hmc_info->sd_table.sd_entry[sd_idx].entry_type) continue; rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD; pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; if (pd_table->pd_entry[rel_pd_idx].valid) { ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j); if (I40E_SUCCESS != ret_code) goto exit; } } /* find sd index and limit */ I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, info->start_idx, info->count, &sd_idx, &sd_lmt); if (sd_idx >= info->hmc_info->sd_table.sd_cnt || sd_lmt > info->hmc_info->sd_table.sd_cnt) { ret_code = I40E_ERR_INVALID_SD_INDEX; goto exit; } for (i = sd_idx; i < sd_lmt; i++) { if (!info->hmc_info->sd_table.sd_entry[i].valid) continue; switch (info->hmc_info->sd_table.sd_entry[i].entry_type) { case I40E_SD_TYPE_DIRECT: ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i); if (I40E_SUCCESS != ret_code) goto exit; break; case I40E_SD_TYPE_PAGED: ret_code = i40e_remove_pd_page(hw, info->hmc_info, i); if (I40E_SUCCESS != ret_code) goto exit; break; default: break; } } exit: return ret_code; } /** * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory * @hw: pointer to the hw structure * * This must be called by drivers as they are shutting down and being * removed from the OS. **/ enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw) { struct i40e_hmc_lan_delete_obj_info info; enum i40e_status_code ret_code; info.hmc_info = &hw->hmc; info.rsrc_type = I40E_HMC_LAN_FULL; info.start_idx = 0; info.count = 1; /* delete the object */ ret_code = i40e_delete_lan_hmc_object(hw, &info); /* free the SD table entry for LAN */ i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr); hw->hmc.sd_table.sd_cnt = 0; hw->hmc.sd_table.sd_entry = NULL; /* free memory used for hmc_obj */ i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem); hw->hmc.hmc_obj = NULL; return ret_code; } #define I40E_HMC_STORE(_struct, _ele) \ offsetof(struct _struct, _ele), \ FIELD_SIZEOF(struct _struct, _ele) struct i40e_context_ele { u16 offset; u16 size_of; u16 width; u16 lsb; }; /* LAN Tx Queue Context */ static struct i40e_context_ele i40e_hmc_txq_ce_info[] = { /* Field Width LSB */ {I40E_HMC_STORE(i40e_hmc_obj_txq, head), 13, 0 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, new_context), 1, 30 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, base), 57, 32 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena), 1, 89 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena), 1, 90 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena), 1, 91 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena), 1, 92 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid), 8, 96 }, /* line 1 */ {I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb), 13, 0 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena), 1, 32 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, qlen), 13, 33 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena), 1, 46 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena), 1, 47 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena), 1, 48 + 128 }, {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr), 64, 64 + 128 }, /* line 7 */ {I40E_HMC_STORE(i40e_hmc_obj_txq, crc), 32, 0 + (7 * 128) }, {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist), 10, 84 + (7 * 128) }, {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act), 1, 94 + (7 * 128) }, { 0 } }; /* LAN Rx Queue Context */ static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = { /* Field Width LSB */ { I40E_HMC_STORE(i40e_hmc_obj_rxq, head), 13, 0 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid), 8, 13 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, base), 57, 32 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen), 13, 89 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff), 7, 102 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff), 5, 109 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype), 2, 114 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize), 1, 116 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip), 1, 117 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena), 1, 118 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel), 1, 119 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0), 4, 120 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1), 2, 124 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv), 1, 127 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax), 14, 174 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1, 193 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1, 194 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena), 1, 195 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena), 1, 196 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh), 3, 198 }, { I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena), 1, 201 }, { 0 } }; /** * i40e_write_byte - replace HMC context byte * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be read from * @src: the struct to be read from **/ static void i40e_write_byte(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *src) { u8 src_byte, dest_byte, mask; u8 *from, *dest; u16 shift_width; /* copy from the next struct field */ from = src + ce_info->offset; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; mask = ((u8)1 << ce_info->width) - 1; src_byte = *from; src_byte &= mask; /* shift to correct alignment */ mask <<= shift_width; src_byte <<= shift_width; /* get the current bits from the target bit string */ dest = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA); dest_byte &= ~mask; /* get the bits not changing */ dest_byte |= src_byte; /* add in the new bits */ /* put it all back */ i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); } /** * i40e_write_word - replace HMC context word * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be read from * @src: the struct to be read from **/ static void i40e_write_word(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *src) { u16 src_word, mask; u8 *from, *dest; u16 shift_width; __le16 dest_word; /* copy from the next struct field */ from = src + ce_info->offset; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; mask = ((u16)1 << ce_info->width) - 1; /* don't swizzle the bits until after the mask because the mask bits * will be in a different bit position on big endian machines */ src_word = *(u16 *)from; src_word &= mask; /* shift to correct alignment */ mask <<= shift_width; src_word <<= shift_width; /* get the current bits from the target bit string */ dest = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA); dest_word &= ~(CPU_TO_LE16(mask)); /* get the bits not changing */ dest_word |= CPU_TO_LE16(src_word); /* add in the new bits */ /* put it all back */ i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); } /** * i40e_write_dword - replace HMC context dword * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be read from * @src: the struct to be read from **/ static void i40e_write_dword(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *src) { u32 src_dword, mask; u8 *from, *dest; u16 shift_width; __le32 dest_dword; /* copy from the next struct field */ from = src + ce_info->offset; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; /* if the field width is exactly 32 on an x86 machine, then the shift * operation will not work because the SHL instructions count is masked * to 5 bits so the shift will do nothing */ if (ce_info->width < 32) mask = ((u32)1 << ce_info->width) - 1; else mask = ~(u32)0; /* don't swizzle the bits until after the mask because the mask bits * will be in a different bit position on big endian machines */ src_dword = *(u32 *)from; src_dword &= mask; /* shift to correct alignment */ mask <<= shift_width; src_dword <<= shift_width; /* get the current bits from the target bit string */ dest = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA); dest_dword &= ~(CPU_TO_LE32(mask)); /* get the bits not changing */ dest_dword |= CPU_TO_LE32(src_dword); /* add in the new bits */ /* put it all back */ i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA); } /** * i40e_write_qword - replace HMC context qword * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be read from * @src: the struct to be read from **/ static void i40e_write_qword(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *src) { u64 src_qword, mask; u8 *from, *dest; u16 shift_width; __le64 dest_qword; /* copy from the next struct field */ from = src + ce_info->offset; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; /* if the field width is exactly 64 on an x86 machine, then the shift * operation will not work because the SHL instructions count is masked * to 6 bits so the shift will do nothing */ if (ce_info->width < 64) mask = ((u64)1 << ce_info->width) - 1; else mask = ~(u64)0; /* don't swizzle the bits until after the mask because the mask bits * will be in a different bit position on big endian machines */ src_qword = *(u64 *)from; src_qword &= mask; /* shift to correct alignment */ mask <<= shift_width; src_qword <<= shift_width; /* get the current bits from the target bit string */ dest = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA); dest_qword &= ~(CPU_TO_LE64(mask)); /* get the bits not changing */ dest_qword |= CPU_TO_LE64(src_qword); /* add in the new bits */ /* put it all back */ i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA); } /** * i40e_read_byte - read HMC context byte into struct * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static void i40e_read_byte(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *dest) { u8 dest_byte, mask; u8 *src, *target; u16 shift_width; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; mask = ((u8)1 << ce_info->width) - 1; /* shift to correct alignment */ mask <<= shift_width; /* get the current bits from the src bit string */ src = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA); dest_byte &= ~(mask); dest_byte >>= shift_width; /* get the address from the struct field */ target = dest + ce_info->offset; /* put it back in the struct */ i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); } /** * i40e_read_word - read HMC context word into struct * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static void i40e_read_word(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *dest) { u16 dest_word, mask; u8 *src, *target; u16 shift_width; __le16 src_word; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; mask = ((u16)1 << ce_info->width) - 1; /* shift to correct alignment */ mask <<= shift_width; /* get the current bits from the src bit string */ src = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA); /* the data in the memory is stored as little endian so mask it * correctly */ src_word &= ~(CPU_TO_LE16(mask)); /* get the data back into host order before shifting */ dest_word = LE16_TO_CPU(src_word); dest_word >>= shift_width; /* get the address from the struct field */ target = dest + ce_info->offset; /* put it back in the struct */ i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); } /** * i40e_read_dword - read HMC context dword into struct * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static void i40e_read_dword(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *dest) { u32 dest_dword, mask; u8 *src, *target; u16 shift_width; __le32 src_dword; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; /* if the field width is exactly 32 on an x86 machine, then the shift * operation will not work because the SHL instructions count is masked * to 5 bits so the shift will do nothing */ if (ce_info->width < 32) mask = ((u32)1 << ce_info->width) - 1; else mask = ~(u32)0; /* shift to correct alignment */ mask <<= shift_width; /* get the current bits from the src bit string */ src = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA); /* the data in the memory is stored as little endian so mask it * correctly */ src_dword &= ~(CPU_TO_LE32(mask)); /* get the data back into host order before shifting */ dest_dword = LE32_TO_CPU(src_dword); dest_dword >>= shift_width; /* get the address from the struct field */ target = dest + ce_info->offset; /* put it back in the struct */ i40e_memcpy(target, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA); } /** * i40e_read_qword - read HMC context qword into struct * @hmc_bits: pointer to the HMC memory * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static void i40e_read_qword(u8 *hmc_bits, struct i40e_context_ele *ce_info, u8 *dest) { u64 dest_qword, mask; u8 *src, *target; u16 shift_width; __le64 src_qword; /* prepare the bits and mask */ shift_width = ce_info->lsb % 8; /* if the field width is exactly 64 on an x86 machine, then the shift * operation will not work because the SHL instructions count is masked * to 6 bits so the shift will do nothing */ if (ce_info->width < 64) mask = ((u64)1 << ce_info->width) - 1; else mask = ~(u64)0; /* shift to correct alignment */ mask <<= shift_width; /* get the current bits from the src bit string */ src = hmc_bits + (ce_info->lsb / 8); i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA); /* the data in the memory is stored as little endian so mask it * correctly */ src_qword &= ~(CPU_TO_LE64(mask)); /* get the data back into host order before shifting */ dest_qword = LE64_TO_CPU(src_qword); dest_qword >>= shift_width; /* get the address from the struct field */ target = dest + ce_info->offset; /* put it back in the struct */ i40e_memcpy(target, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA); } /** * i40e_get_hmc_context - extract HMC context bits * @context_bytes: pointer to the context bit array * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes, struct i40e_context_ele *ce_info, u8 *dest) { int f; for (f = 0; ce_info[f].width != 0; f++) { switch (ce_info[f].size_of) { case 1: i40e_read_byte(context_bytes, &ce_info[f], dest); break; case 2: i40e_read_word(context_bytes, &ce_info[f], dest); break; case 4: i40e_read_dword(context_bytes, &ce_info[f], dest); break; case 8: i40e_read_qword(context_bytes, &ce_info[f], dest); break; default: /* nothing to do, just keep going */ break; } } return I40E_SUCCESS; } /** * i40e_clear_hmc_context - zero out the HMC context bits * @hw: the hardware struct * @context_bytes: pointer to the context bit array (DMA memory) * @hmc_type: the type of HMC resource **/ static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw, u8 *context_bytes, enum i40e_hmc_lan_rsrc_type hmc_type) { /* clean the bit array */ i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size, I40E_DMA_MEM); return I40E_SUCCESS; } /** * i40e_set_hmc_context - replace HMC context bits * @context_bytes: pointer to the context bit array * @ce_info: a description of the struct to be filled * @dest: the struct to be filled **/ static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes, struct i40e_context_ele *ce_info, u8 *dest) { int f; for (f = 0; ce_info[f].width != 0; f++) { /* we have to deal with each element of the HMC using the * correct size so that we are correct regardless of the * endianness of the machine */ switch (ce_info[f].size_of) { case 1: i40e_write_byte(context_bytes, &ce_info[f], dest); break; case 2: i40e_write_word(context_bytes, &ce_info[f], dest); break; case 4: i40e_write_dword(context_bytes, &ce_info[f], dest); break; case 8: i40e_write_qword(context_bytes, &ce_info[f], dest); break; } } return I40E_SUCCESS; } /** * i40e_hmc_get_object_va - retrieves an object's virtual address * @hw: pointer to the hw structure * @object_base: pointer to u64 to get the va * @rsrc_type: the hmc resource type * @obj_idx: hmc object index * * This function retrieves the object's virtual address from the object * base pointer. This function is used for LAN Queue contexts. **/ STATIC enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw, u8 **object_base, enum i40e_hmc_lan_rsrc_type rsrc_type, u32 obj_idx) { u32 obj_offset_in_sd, obj_offset_in_pd; struct i40e_hmc_info *hmc_info = &hw->hmc; struct i40e_hmc_sd_entry *sd_entry; struct i40e_hmc_pd_entry *pd_entry; u32 pd_idx, pd_lmt, rel_pd_idx; enum i40e_status_code ret_code = I40E_SUCCESS; u64 obj_offset_in_fpm; u32 sd_idx, sd_lmt; if (NULL == hmc_info) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info ptr\n"); goto exit; } if (NULL == hmc_info->hmc_obj) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n"); goto exit; } if (NULL == object_base) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n"); goto exit; } if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) { ret_code = I40E_ERR_BAD_PTR; DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n"); goto exit; } if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) { DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n", ret_code); ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; goto exit; } /* find sd index and limit */ I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, &sd_idx, &sd_lmt); sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base + hmc_info->hmc_obj[rsrc_type].size * obj_idx; if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, &pd_idx, &pd_lmt); rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD; pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx]; obj_offset_in_pd = (u32)(obj_offset_in_fpm % I40E_HMC_PAGED_BP_SIZE); *object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd; } else { obj_offset_in_sd = (u32)(obj_offset_in_fpm % I40E_HMC_DIRECT_BP_SIZE); *object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd; } exit: return ret_code; } /** * i40e_get_lan_tx_queue_context - return the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about * @s: the struct to be filled **/ enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_txq *s) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); if (err < 0) return err; return i40e_get_hmc_context(context_bytes, i40e_hmc_txq_ce_info, (u8 *)s); } /** * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about **/ enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw, u16 queue) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); if (err < 0) return err; return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX); } /** * i40e_set_lan_tx_queue_context - set the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about * @s: the struct to be filled **/ enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_txq *s) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); if (err < 0) return err; return i40e_set_hmc_context(context_bytes, i40e_hmc_txq_ce_info, (u8 *)s); } /** * i40e_get_lan_rx_queue_context - return the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about * @s: the struct to be filled **/ enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_rxq *s) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); if (err < 0) return err; return i40e_get_hmc_context(context_bytes, i40e_hmc_rxq_ce_info, (u8 *)s); } /** * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about **/ enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw, u16 queue) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); if (err < 0) return err; return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX); } /** * i40e_set_lan_rx_queue_context - set the HMC context for the queue * @hw: the hardware struct * @queue: the queue we care about * @s: the struct to be filled **/ enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_rxq *s) { enum i40e_status_code err; u8 *context_bytes; err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); if (err < 0) return err; return i40e_set_hmc_context(context_bytes, i40e_hmc_rxq_ce_info, (u8 *)s); } ================================================ FILE: drivers/net/i40e/base/i40e_lan_hmc.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_LAN_HMC_H_ #define _I40E_LAN_HMC_H_ /* forward-declare the HW struct for the compiler */ struct i40e_hw; /* HMC element context information */ /* Rx queue context data * * The sizes of the variables may be larger than needed due to crossing byte * boundaries. If we do not have the width of the variable set to the correct * size then we could end up shifting bits off the top of the variable when the * variable is at the top of a byte and crosses over into the next byte. */ struct i40e_hmc_obj_rxq { u16 head; u16 cpuid; /* bigger than needed, see above for reason */ u64 base; u16 qlen; #define I40E_RXQ_CTX_DBUFF_SHIFT 7 u16 dbuff; /* bigger than needed, see above for reason */ #define I40E_RXQ_CTX_HBUFF_SHIFT 6 u16 hbuff; /* bigger than needed, see above for reason */ u8 dtype; u8 dsize; u8 crcstrip; u8 fc_ena; u8 l2tsel; u8 hsplit_0; u8 hsplit_1; u8 showiv; u32 rxmax; /* bigger than needed, see above for reason */ u8 tphrdesc_ena; u8 tphwdesc_ena; u8 tphdata_ena; u8 tphhead_ena; u16 lrxqthresh; /* bigger than needed, see above for reason */ u8 prefena; /* NOTE: normally must be set to 1 at init */ }; /* Tx queue context data * * The sizes of the variables may be larger than needed due to crossing byte * boundaries. If we do not have the width of the variable set to the correct * size then we could end up shifting bits off the top of the variable when the * variable is at the top of a byte and crosses over into the next byte. */ struct i40e_hmc_obj_txq { u16 head; u8 new_context; u64 base; u8 fc_ena; u8 timesync_ena; u8 fd_ena; u8 alt_vlan_ena; u16 thead_wb; u8 cpuid; u8 head_wb_ena; u16 qlen; u8 tphrdesc_ena; u8 tphrpacket_ena; u8 tphwdesc_ena; u64 head_wb_addr; u32 crc; u16 rdylist; u8 rdylist_act; }; /* for hsplit_0 field of Rx HMC context */ enum i40e_hmc_obj_rx_hsplit_0 { I40E_HMC_OBJ_RX_HSPLIT_0_NO_SPLIT = 0, I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_L2 = 1, I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_IP = 2, I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_TCP_UDP = 4, I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_SCTP = 8, }; /* fcoe_cntx and fcoe_filt are for debugging purpose only */ struct i40e_hmc_obj_fcoe_cntx { u32 rsv[32]; }; struct i40e_hmc_obj_fcoe_filt { u32 rsv[8]; }; /* Context sizes for LAN objects */ enum i40e_hmc_lan_object_size { I40E_HMC_LAN_OBJ_SZ_8 = 0x3, I40E_HMC_LAN_OBJ_SZ_16 = 0x4, I40E_HMC_LAN_OBJ_SZ_32 = 0x5, I40E_HMC_LAN_OBJ_SZ_64 = 0x6, I40E_HMC_LAN_OBJ_SZ_128 = 0x7, I40E_HMC_LAN_OBJ_SZ_256 = 0x8, I40E_HMC_LAN_OBJ_SZ_512 = 0x9, }; #define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512 #define I40E_HMC_OBJ_SIZE_TXQ 128 #define I40E_HMC_OBJ_SIZE_RXQ 32 #define I40E_HMC_OBJ_SIZE_FCOE_CNTX 64 #define I40E_HMC_OBJ_SIZE_FCOE_FILT 64 enum i40e_hmc_lan_rsrc_type { I40E_HMC_LAN_FULL = 0, I40E_HMC_LAN_TX = 1, I40E_HMC_LAN_RX = 2, I40E_HMC_FCOE_CTX = 3, I40E_HMC_FCOE_FILT = 4, I40E_HMC_LAN_MAX = 5 }; enum i40e_hmc_model { I40E_HMC_MODEL_DIRECT_PREFERRED = 0, I40E_HMC_MODEL_DIRECT_ONLY = 1, I40E_HMC_MODEL_PAGED_ONLY = 2, I40E_HMC_MODEL_UNKNOWN, }; struct i40e_hmc_lan_create_obj_info { struct i40e_hmc_info *hmc_info; u32 rsrc_type; u32 start_idx; u32 count; enum i40e_sd_entry_type entry_type; u64 direct_mode_sz; }; struct i40e_hmc_lan_delete_obj_info { struct i40e_hmc_info *hmc_info; u32 rsrc_type; u32 start_idx; u32 count; }; enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, u32 rxq_num, u32 fcoe_cntx_num, u32 fcoe_filt_num); enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw, enum i40e_hmc_model model); enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw); u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num, u32 fcoe_cntx_num, u32 fcoe_filt_num); enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_txq *s); enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw, u16 queue); enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_txq *s); enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_rxq *s); enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw, u16 queue); enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw, u16 queue, struct i40e_hmc_obj_rxq *s); enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw, struct i40e_hmc_lan_create_obj_info *info); enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw, struct i40e_hmc_lan_delete_obj_info *info); #endif /* _I40E_LAN_HMC_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_nvm.c ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "i40e_prototype.h" enum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, u16 *data); enum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, u16 *data); enum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data); enum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data); enum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 words, void *data, bool last_command); /** * i40e_init_nvm_ops - Initialize NVM function pointers * @hw: pointer to the HW structure * * Setup the function pointers and the NVM info structure. Should be called * once per NVM initialization, e.g. inside the i40e_init_shared_code(). * Please notice that the NVM term is used here (& in all methods covered * in this file) as an equivalent of the FLASH part mapped into the SR. * We are accessing FLASH always thru the Shadow RAM. **/ enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw) { struct i40e_nvm_info *nvm = &hw->nvm; enum i40e_status_code ret_code = I40E_SUCCESS; u32 fla, gens; u8 sr_size; DEBUGFUNC("i40e_init_nvm"); /* The SR size is stored regardless of the nvm programming mode * as the blank mode may be used in the factory line. */ gens = rd32(hw, I40E_GLNVM_GENS); sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >> I40E_GLNVM_GENS_SR_SIZE_SHIFT); /* Switching to words (sr_size contains power of 2KB) */ nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB; /* Check if we are in the normal or blank NVM programming mode */ fla = rd32(hw, I40E_GLNVM_FLA); if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */ /* Max NVM timeout */ nvm->timeout = I40E_MAX_NVM_TIMEOUT; nvm->blank_nvm_mode = false; } else { /* Blank programming mode */ nvm->blank_nvm_mode = true; ret_code = I40E_ERR_NVM_BLANK_MODE; i40e_debug(hw, I40E_DEBUG_NVM, "NVM init error: unsupported blank mode.\n"); } return ret_code; } /** * i40e_acquire_nvm - Generic request for acquiring the NVM ownership * @hw: pointer to the HW structure * @access: NVM access type (read or write) * * This function will request NVM ownership for reading * via the proper Admin Command. **/ enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw, enum i40e_aq_resource_access_type access) { enum i40e_status_code ret_code = I40E_SUCCESS; u64 gtime, timeout; u64 time_left = 0; DEBUGFUNC("i40e_acquire_nvm"); if (hw->nvm.blank_nvm_mode) goto i40e_i40e_acquire_nvm_exit; ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 0, &time_left, NULL); /* Reading the Global Device Timer */ gtime = rd32(hw, I40E_GLVFGEN_TIMER); /* Store the timeout */ hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime; if (ret_code) i40e_debug(hw, I40E_DEBUG_NVM, "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n", access, time_left, ret_code, hw->aq.asq_last_status); if (ret_code && time_left) { /* Poll until the current NVM owner timeouts */ timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) + gtime; while ((gtime < timeout) && time_left) { i40e_msec_delay(10); gtime = rd32(hw, I40E_GLVFGEN_TIMER); ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 0, &time_left, NULL); if (ret_code == I40E_SUCCESS) { hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time_left) + gtime; break; } } if (ret_code != I40E_SUCCESS) { hw->nvm.hw_semaphore_timeout = 0; i40e_debug(hw, I40E_DEBUG_NVM, "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n", time_left, ret_code, hw->aq.asq_last_status); } } i40e_i40e_acquire_nvm_exit: return ret_code; } /** * i40e_release_nvm - Generic request for releasing the NVM ownership * @hw: pointer to the HW structure * * This function will release NVM resource via the proper Admin Command. **/ void i40e_release_nvm(struct i40e_hw *hw) { DEBUGFUNC("i40e_release_nvm"); if (!hw->nvm.blank_nvm_mode) i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); } /** * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit * @hw: pointer to the HW structure * * Polls the SRCTL Shadow RAM register done bit. **/ static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; u32 srctl, wait_cnt; DEBUGFUNC("i40e_poll_sr_srctl_done_bit"); /* Poll the I40E_GLNVM_SRCTL until the done bit is set */ for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) { srctl = rd32(hw, I40E_GLNVM_SRCTL); if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) { ret_code = I40E_SUCCESS; break; } i40e_usec_delay(5); } if (ret_code == I40E_ERR_TIMEOUT) i40e_debug(hw, I40E_DEBUG_NVM, "Done bit in GLNVM_SRCTL not set"); return ret_code; } /** * i40e_read_nvm_word - Reads Shadow RAM * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) * @data: word read from the Shadow RAM * * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. **/ enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, u16 *data) { return i40e_read_nvm_word_srctl(hw, offset, data); } /** * i40e_read_nvm_word_srctl - Reads Shadow RAM via SRCTL register * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) * @data: word read from the Shadow RAM * * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. **/ enum i40e_status_code i40e_read_nvm_word_srctl(struct i40e_hw *hw, u16 offset, u16 *data) { enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; u32 sr_reg; DEBUGFUNC("i40e_read_nvm_word_srctl"); if (offset >= hw->nvm.sr_size) { i40e_debug(hw, I40E_DEBUG_NVM, "NVM read error: Offset %d beyond Shadow RAM limit %d\n", offset, hw->nvm.sr_size); ret_code = I40E_ERR_PARAM; goto read_nvm_exit; } /* Poll the done bit first */ ret_code = i40e_poll_sr_srctl_done_bit(hw); if (ret_code == I40E_SUCCESS) { /* Write the address and start reading */ sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) | (1 << I40E_GLNVM_SRCTL_START_SHIFT); wr32(hw, I40E_GLNVM_SRCTL, sr_reg); /* Poll I40E_GLNVM_SRCTL until the done bit is set */ ret_code = i40e_poll_sr_srctl_done_bit(hw); if (ret_code == I40E_SUCCESS) { sr_reg = rd32(hw, I40E_GLNVM_SRDATA); *data = (u16)((sr_reg & I40E_GLNVM_SRDATA_RDDATA_MASK) >> I40E_GLNVM_SRDATA_RDDATA_SHIFT); } } if (ret_code != I40E_SUCCESS) i40e_debug(hw, I40E_DEBUG_NVM, "NVM read error: Couldn't access Shadow RAM address: 0x%x\n", offset); read_nvm_exit: return ret_code; } /** * i40e_read_nvm_word_aq - Reads Shadow RAM via AQ * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) * @data: word read from the Shadow RAM * * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. **/ enum i40e_status_code i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, u16 *data) { enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; DEBUGFUNC("i40e_read_nvm_word_aq"); ret_code = i40e_read_nvm_aq(hw, 0x0, offset, 1, data, true); *data = LE16_TO_CPU(*(__le16 *)data); return ret_code; } /** * i40e_read_nvm_buffer - Reads Shadow RAM buffer * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). * @words: (in) number of words to read; (out) number of words actually read * @data: words read from the Shadow RAM * * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() * method. The buffer read is preceded by the NVM ownership take * and followed by the release. **/ enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data) { return i40e_read_nvm_buffer_srctl(hw, offset, words, data); } /** * i40e_read_nvm_buffer_srctl - Reads Shadow RAM buffer via SRCTL register * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). * @words: (in) number of words to read; (out) number of words actually read * @data: words read from the Shadow RAM * * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() * method. The buffer read is preceded by the NVM ownership take * and followed by the release. **/ enum i40e_status_code i40e_read_nvm_buffer_srctl(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data) { enum i40e_status_code ret_code = I40E_SUCCESS; u16 index, word; DEBUGFUNC("i40e_read_nvm_buffer_srctl"); /* Loop thru the selected region */ for (word = 0; word < *words; word++) { index = offset + word; ret_code = i40e_read_nvm_word_srctl(hw, index, &data[word]); if (ret_code != I40E_SUCCESS) break; } /* Update the number of words read from the Shadow RAM */ *words = word; return ret_code; } /** * i40e_read_nvm_buffer_aq - Reads Shadow RAM buffer via AQ * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). * @words: (in) number of words to read; (out) number of words actually read * @data: words read from the Shadow RAM * * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_aq() * method. The buffer read is preceded by the NVM ownership take * and followed by the release. **/ enum i40e_status_code i40e_read_nvm_buffer_aq(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data) { enum i40e_status_code ret_code; u16 read_size = *words; bool last_cmd = false; u16 words_read = 0; u16 i = 0; DEBUGFUNC("i40e_read_nvm_buffer_aq"); do { /* Calculate number of bytes we should read in this step. * FVL AQ do not allow to read more than one page at a time or * to cross page boundaries. */ if (offset % I40E_SR_SECTOR_SIZE_IN_WORDS) read_size = min(*words, (u16)(I40E_SR_SECTOR_SIZE_IN_WORDS - (offset % I40E_SR_SECTOR_SIZE_IN_WORDS))); else read_size = min((*words - words_read), I40E_SR_SECTOR_SIZE_IN_WORDS); /* Check if this is last command, if so set proper flag */ if ((words_read + read_size) >= *words) last_cmd = true; ret_code = i40e_read_nvm_aq(hw, 0x0, offset, read_size, data + words_read, last_cmd); if (ret_code != I40E_SUCCESS) goto read_nvm_buffer_aq_exit; /* Increment counter for words already read and move offset to * new read location */ words_read += read_size; offset += read_size; } while (words_read < *words); for (i = 0; i < *words; i++) data[i] = LE16_TO_CPU(((__le16 *)data)[i]); read_nvm_buffer_aq_exit: *words = words_read; return ret_code; } /** * i40e_read_nvm_aq - Read Shadow RAM. * @hw: pointer to the HW structure. * @module_pointer: module pointer location in words from the NVM beginning * @offset: offset in words from module start * @words: number of words to write * @data: buffer with words to write to the Shadow RAM * @last_command: tells the AdminQ that this is the last command * * Writes a 16 bit words buffer to the Shadow RAM using the admin command. **/ enum i40e_status_code i40e_read_nvm_aq(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 words, void *data, bool last_command) { enum i40e_status_code ret_code = I40E_ERR_NVM; DEBUGFUNC("i40e_read_nvm_aq"); /* Here we are checking the SR limit only for the flat memory model. * We cannot do it for the module-based model, as we did not acquire * the NVM resource yet (we cannot get the module pointer value). * Firmware will check the module-based model. */ if ((offset + words) > hw->nvm.sr_size) i40e_debug(hw, I40E_DEBUG_NVM, "NVM write error: offset %d beyond Shadow RAM limit %d\n", (offset + words), hw->nvm.sr_size); else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) /* We can write only up to 4KB (one sector), in one AQ write */ i40e_debug(hw, I40E_DEBUG_NVM, "NVM write fail error: tried to write %d words, limit is %d.\n", words, I40E_SR_SECTOR_SIZE_IN_WORDS); else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) /* A single write cannot spread over two sectors */ i40e_debug(hw, I40E_DEBUG_NVM, "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n", offset, words); else ret_code = i40e_aq_read_nvm(hw, module_pointer, 2 * offset, /*bytes*/ 2 * words, /*bytes*/ data, last_command, NULL); return ret_code; } /** * i40e_write_nvm_aq - Writes Shadow RAM. * @hw: pointer to the HW structure. * @module_pointer: module pointer location in words from the NVM beginning * @offset: offset in words from module start * @words: number of words to write * @data: buffer with words to write to the Shadow RAM * @last_command: tells the AdminQ that this is the last command * * Writes a 16 bit words buffer to the Shadow RAM using the admin command. **/ enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 words, void *data, bool last_command) { enum i40e_status_code ret_code = I40E_ERR_NVM; DEBUGFUNC("i40e_write_nvm_aq"); /* Here we are checking the SR limit only for the flat memory model. * We cannot do it for the module-based model, as we did not acquire * the NVM resource yet (we cannot get the module pointer value). * Firmware will check the module-based model. */ if ((offset + words) > hw->nvm.sr_size) DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n"); else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS) /* We can write only up to 4KB (one sector), in one AQ write */ DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n"); else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS) != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS)) /* A single write cannot spread over two sectors */ DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n"); else ret_code = i40e_aq_update_nvm(hw, module_pointer, 2 * offset, /*bytes*/ 2 * words, /*bytes*/ data, last_command, NULL); return ret_code; } /** * i40e_write_nvm_word - Writes Shadow RAM word * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to write * @data: word to write to the Shadow RAM * * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method. * NVM ownership have to be acquired and released (on ARQ completion event * reception) by caller. To commit SR to NVM update checksum function * should be called. **/ enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset, void *data) { DEBUGFUNC("i40e_write_nvm_word"); *((__le16 *)data) = CPU_TO_LE16(*((u16 *)data)); /* Value 0x00 below means that we treat SR as a flat mem */ return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, false); } /** * i40e_write_nvm_buffer - Writes Shadow RAM buffer * @hw: pointer to the HW structure * @module_pointer: module pointer location in words from the NVM beginning * @offset: offset of the Shadow RAM buffer to write * @words: number of words to write * @data: words to write to the Shadow RAM * * Writes a 16 bit words buffer to the Shadow RAM using the admin command. * NVM ownership must be acquired before calling this function and released * on ARQ completion event reception by caller. To commit SR to NVM update * checksum function should be called. **/ enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 words, void *data) { __le16 *le_word_ptr = (__le16 *)data; u16 *word_ptr = (u16 *)data; u32 i = 0; DEBUGFUNC("i40e_write_nvm_buffer"); for (i = 0; i < words; i++) le_word_ptr[i] = CPU_TO_LE16(word_ptr[i]); /* Here we will only write one buffer as the size of the modules * mirrored in the Shadow RAM is always less than 4K. */ return i40e_write_nvm_aq(hw, module_pointer, offset, words, data, false); } /** * i40e_calc_nvm_checksum - Calculates and returns the checksum * @hw: pointer to hardware structure * @checksum: pointer to the checksum * * This function calculates SW Checksum that covers the whole 64kB shadow RAM * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD * is customer specific and unknown. Therefore, this function skips all maximum * possible size of VPD (1kB). **/ enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum) { enum i40e_status_code ret_code = I40E_SUCCESS; struct i40e_virt_mem vmem; u16 pcie_alt_module = 0; u16 checksum_local = 0; u16 vpd_module = 0; u16 *data; u16 i = 0; DEBUGFUNC("i40e_calc_nvm_checksum"); ret_code = i40e_allocate_virt_mem(hw, &vmem, I40E_SR_SECTOR_SIZE_IN_WORDS * sizeof(u16)); if (ret_code) goto i40e_calc_nvm_checksum_exit; data = (u16 *)vmem.va; /* read pointer to VPD area */ ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module); if (ret_code != I40E_SUCCESS) { ret_code = I40E_ERR_NVM_CHECKSUM; goto i40e_calc_nvm_checksum_exit; } /* read pointer to PCIe Alt Auto-load module */ ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, &pcie_alt_module); if (ret_code != I40E_SUCCESS) { ret_code = I40E_ERR_NVM_CHECKSUM; goto i40e_calc_nvm_checksum_exit; } /* Calculate SW checksum that covers the whole 64kB shadow RAM * except the VPD and PCIe ALT Auto-load modules */ for (i = 0; i < hw->nvm.sr_size; i++) { /* Read SR page */ if ((i % I40E_SR_SECTOR_SIZE_IN_WORDS) == 0) { u16 words = I40E_SR_SECTOR_SIZE_IN_WORDS; ret_code = i40e_read_nvm_buffer(hw, i, &words, data); if (ret_code != I40E_SUCCESS) { ret_code = I40E_ERR_NVM_CHECKSUM; goto i40e_calc_nvm_checksum_exit; } } /* Skip Checksum word */ if (i == I40E_SR_SW_CHECKSUM_WORD) continue; /* Skip VPD module (convert byte size to word count) */ if ((i >= (u32)vpd_module) && (i < ((u32)vpd_module + (I40E_SR_VPD_MODULE_MAX_SIZE / 2)))) { continue; } /* Skip PCIe ALT module (convert byte size to word count) */ if ((i >= (u32)pcie_alt_module) && (i < ((u32)pcie_alt_module + (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2)))) { continue; } checksum_local += data[i % I40E_SR_SECTOR_SIZE_IN_WORDS]; } *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local; i40e_calc_nvm_checksum_exit: i40e_free_virt_mem(hw, &vmem); return ret_code; } /** * i40e_update_nvm_checksum - Updates the NVM checksum * @hw: pointer to hardware structure * * NVM ownership must be acquired before calling this function and released * on ARQ completion event reception by caller. * This function will commit SR to NVM. **/ enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw) { enum i40e_status_code ret_code = I40E_SUCCESS; u16 checksum; DEBUGFUNC("i40e_update_nvm_checksum"); ret_code = i40e_calc_nvm_checksum(hw, &checksum); if (ret_code == I40E_SUCCESS) ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD, 1, &checksum, true); return ret_code; } /** * i40e_validate_nvm_checksum - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum: calculated checksum * * Performs checksum calculation and validates the NVM SW checksum. If the * caller does not need checksum, the value can be NULL. **/ enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw, u16 *checksum) { enum i40e_status_code ret_code = I40E_SUCCESS; u16 checksum_sr = 0; u16 checksum_local = 0; DEBUGFUNC("i40e_validate_nvm_checksum"); ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); if (ret_code != I40E_SUCCESS) goto i40e_validate_nvm_checksum_exit; /* Do not use i40e_read_nvm_word() because we do not want to take * the synchronization semaphores twice here. */ i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr); /* Verify read checksum from EEPROM is the same as * calculated checksum */ if (checksum_local != checksum_sr) ret_code = I40E_ERR_NVM_CHECKSUM; /* If the user cares, return the calculated checksum */ if (checksum) *checksum = checksum_local; i40e_validate_nvm_checksum_exit: return ret_code; } STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, int *perrno); STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw, struct i40e_nvm_access *cmd, int *perrno); STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); STATIC inline u8 i40e_nvmupd_get_module(u32 val) { return (u8)(val & I40E_NVM_MOD_PNT_MASK); } STATIC inline u8 i40e_nvmupd_get_transaction(u32 val) { return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT); } STATIC const char *i40e_nvm_update_state_str[] = { "I40E_NVMUPD_INVALID", "I40E_NVMUPD_READ_CON", "I40E_NVMUPD_READ_SNT", "I40E_NVMUPD_READ_LCB", "I40E_NVMUPD_READ_SA", "I40E_NVMUPD_WRITE_ERA", "I40E_NVMUPD_WRITE_CON", "I40E_NVMUPD_WRITE_SNT", "I40E_NVMUPD_WRITE_LCB", "I40E_NVMUPD_WRITE_SA", "I40E_NVMUPD_CSUM_CON", "I40E_NVMUPD_CSUM_SA", "I40E_NVMUPD_CSUM_LCB", }; /** * i40e_nvmupd_command - Process an NVM update command * @hw: pointer to hardware structure * @cmd: pointer to nvm update command * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * Dispatches command depending on what update state is current **/ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status; DEBUGFUNC("i40e_nvmupd_command"); /* assume success */ *perrno = 0; switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT: status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_STATE_READING: status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_STATE_WRITING: status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno); break; default: /* invalid state, should never happen */ i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: no such state %d\n", hw->nvmupd_state); status = I40E_NOT_SUPPORTED; *perrno = -ESRCH; break; } return status; } /** * i40e_nvmupd_state_init - Handle NVM update state Init * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * Process legitimate commands of the Init state and conditionally set next * state. Reject all other commands. **/ STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status = I40E_SUCCESS; enum i40e_nvmupd_cmd upd_cmd; DEBUGFUNC("i40e_nvmupd_state_init"); upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); switch (upd_cmd) { case I40E_NVMUPD_READ_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); i40e_release_nvm(hw); } break; case I40E_NVMUPD_READ_SNT: status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else hw->nvmupd_state = I40E_NVMUPD_STATE_READING; } break; case I40E_NVMUPD_WRITE_ERA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_erase(hw, cmd, perrno); if (status) i40e_release_nvm(hw); else hw->aq.nvm_release_on_done = true; } break; case I40E_NVMUPD_WRITE_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else hw->aq.nvm_release_on_done = true; } break; case I40E_NVMUPD_WRITE_SNT: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; } break; case I40E_NVMUPD_CSUM_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_update_nvm_checksum(hw); if (status) { *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; i40e_release_nvm(hw); } else { hw->aq.nvm_release_on_done = true; } } break; default: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in init state\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_ERR_NVM; *perrno = -ESRCH; break; } return status; } /** * i40e_nvmupd_state_reading - Handle NVM update state Reading * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * NVM ownership is already held. Process legitimate commands and set any * change in state; reject all other commands. **/ STATIC enum i40e_status_code i40e_nvmupd_state_reading(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status; enum i40e_nvmupd_cmd upd_cmd; DEBUGFUNC("i40e_nvmupd_state_reading"); upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); switch (upd_cmd) { case I40E_NVMUPD_READ_SA: case I40E_NVMUPD_READ_CON: status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_READ_LCB: status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); i40e_release_nvm(hw); hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; break; default: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in reading state.\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_NOT_SUPPORTED; *perrno = -ESRCH; break; } return status; } /** * i40e_nvmupd_state_writing - Handle NVM update state Writing * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * NVM ownership is already held. Process legitimate commands and set any * change in state; reject all other commands **/ STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status; enum i40e_nvmupd_cmd upd_cmd; bool retry_attempt = false; DEBUGFUNC("i40e_nvmupd_state_writing"); upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); retry: switch (upd_cmd) { case I40E_NVMUPD_WRITE_CON: status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_WRITE_LCB: status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (!status) hw->aq.nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; break; case I40E_NVMUPD_CSUM_CON: status = i40e_update_nvm_checksum(hw); if (status) { *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; } break; case I40E_NVMUPD_CSUM_LCB: status = i40e_update_nvm_checksum(hw); if (status) *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; else hw->aq.nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; break; default: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in writing state.\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_NOT_SUPPORTED; *perrno = -ESRCH; break; } /* In some circumstances, a multi-write transaction takes longer * than the default 3 minute timeout on the write semaphore. If * the write failed with an EBUSY status, this is likely the problem, * so here we try to reacquire the semaphore then retry the write. * We only do one retry, then give up. */ if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) && !retry_attempt) { enum i40e_status_code old_status = status; u32 old_asq_status = hw->aq.asq_last_status; u32 gtime; gtime = rd32(hw, I40E_GLVFGEN_TIMER); if (gtime >= hw->nvm.hw_semaphore_timeout) { i40e_debug(hw, I40E_DEBUG_ALL, "NVMUPD: write semaphore expired (%d >= %lld), retrying\n", gtime, hw->nvm.hw_semaphore_timeout); i40e_release_nvm(hw); status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { i40e_debug(hw, I40E_DEBUG_ALL, "NVMUPD: write semaphore reacquire failed aq_err = %d\n", hw->aq.asq_last_status); status = old_status; hw->aq.asq_last_status = old_asq_status; } else { retry_attempt = true; goto retry; } } } return status; } /** * i40e_nvmupd_validate_command - Validate given command * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @perrno: pointer to return error code * * Return one of the valid command types or I40E_NVMUPD_INVALID **/ STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, int *perrno) { enum i40e_nvmupd_cmd upd_cmd; u8 transaction, module; DEBUGFUNC("i40e_nvmupd_validate_command\n"); /* anything that doesn't match a recognized case is an error */ upd_cmd = I40E_NVMUPD_INVALID; transaction = i40e_nvmupd_get_transaction(cmd->config); module = i40e_nvmupd_get_module(cmd->config); /* limits on data size */ if ((cmd->data_size < 1) || (cmd->data_size > I40E_NVMUPD_MAX_DATA)) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_validate_command data_size %d\n", cmd->data_size); *perrno = -EFAULT; return I40E_NVMUPD_INVALID; } switch (cmd->command) { case I40E_NVM_READ: switch (transaction) { case I40E_NVM_CON: upd_cmd = I40E_NVMUPD_READ_CON; break; case I40E_NVM_SNT: upd_cmd = I40E_NVMUPD_READ_SNT; break; case I40E_NVM_LCB: upd_cmd = I40E_NVMUPD_READ_LCB; break; case I40E_NVM_SA: upd_cmd = I40E_NVMUPD_READ_SA; break; } break; case I40E_NVM_WRITE: switch (transaction) { case I40E_NVM_CON: upd_cmd = I40E_NVMUPD_WRITE_CON; break; case I40E_NVM_SNT: upd_cmd = I40E_NVMUPD_WRITE_SNT; break; case I40E_NVM_LCB: upd_cmd = I40E_NVMUPD_WRITE_LCB; break; case I40E_NVM_SA: upd_cmd = I40E_NVMUPD_WRITE_SA; break; case I40E_NVM_ERA: upd_cmd = I40E_NVMUPD_WRITE_ERA; break; case I40E_NVM_CSUM: upd_cmd = I40E_NVMUPD_CSUM_CON; break; case (I40E_NVM_CSUM|I40E_NVM_SA): upd_cmd = I40E_NVMUPD_CSUM_SA; break; case (I40E_NVM_CSUM|I40E_NVM_LCB): upd_cmd = I40E_NVMUPD_CSUM_LCB; break; } break; } i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n", i40e_nvm_update_state_str[upd_cmd], hw->nvmupd_state, hw->aq.nvm_release_on_done); if (upd_cmd == I40E_NVMUPD_INVALID) { *perrno = -EFAULT; i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_validate_command returns %d perrno %d\n", upd_cmd, *perrno); } return upd_cmd; } /** * i40e_nvmupd_nvm_read - Read NVM * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * cmd structure contains identifiers and data buffer **/ STATIC enum i40e_status_code i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status; u8 module, transaction; bool last; transaction = i40e_nvmupd_get_transaction(cmd->config); module = i40e_nvmupd_get_module(cmd->config); last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA); status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size, bytes, last, NULL); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n", module, cmd->offset, cmd->data_size); i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_read status %d aq %d\n", status, hw->aq.asq_last_status); *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; } /** * i40e_nvmupd_nvm_erase - Erase an NVM module * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @perrno: pointer to return error code * * module, offset, data_size and data are in cmd structure **/ STATIC enum i40e_status_code i40e_nvmupd_nvm_erase(struct i40e_hw *hw, struct i40e_nvm_access *cmd, int *perrno) { enum i40e_status_code status = I40E_SUCCESS; u8 module, transaction; bool last; transaction = i40e_nvmupd_get_transaction(cmd->config); module = i40e_nvmupd_get_module(cmd->config); last = (transaction & I40E_NVM_LCB); status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size, last, NULL); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n", module, cmd->offset, cmd->data_size); i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_erase status %d aq %d\n", status, hw->aq.asq_last_status); *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; } /** * i40e_nvmupd_nvm_write - Write NVM * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer * @perrno: pointer to return error code * * module, offset, data_size and data are in cmd structure **/ STATIC enum i40e_status_code i40e_nvmupd_nvm_write(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { enum i40e_status_code status = I40E_SUCCESS; u8 module, transaction; bool last; transaction = i40e_nvmupd_get_transaction(cmd->config); module = i40e_nvmupd_get_module(cmd->config); last = (transaction & I40E_NVM_LCB); status = i40e_aq_update_nvm(hw, module, cmd->offset, (u16)cmd->data_size, bytes, last, NULL); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n", module, cmd->offset, cmd->data_size); i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_write status %d aq %d\n", status, hw->aq.asq_last_status); *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; } ================================================ FILE: drivers/net/i40e/base/i40e_osdep.h ================================================ /****************************************************************************** Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ #ifndef _I40E_OSDEP_H_ #define _I40E_OSDEP_H_ #include #include #include #include #include #include #include #include #include #include #include "../i40e_logs.h" #define INLINE inline #define STATIC static typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; typedef int bool; typedef enum i40e_status_code i40e_status; #define __iomem #define hw_dbg(hw, S, A...) do {} while (0) #define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) #define lower_32_bits(n) ((u32)(n)) #define low_16_bits(x) ((x) & 0xFFFF) #define high_16_bits(x) (((x) & 0xFFFF0000) >> 16) #ifndef ETH_ADDR_LEN #define ETH_ADDR_LEN 6 #endif #ifndef __le16 #define __le16 uint16_t #endif #ifndef __le32 #define __le32 uint32_t #endif #ifndef __le64 #define __le64 uint64_t #endif #ifndef __be16 #define __be16 uint16_t #endif #ifndef __be32 #define __be32 uint32_t #endif #ifndef __be64 #define __be64 uint64_t #endif #define FALSE 0 #define TRUE 1 #define false 0 #define true 1 #define min(a,b) RTE_MIN(a,b) #define max(a,b) RTE_MAX(a,b) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define ASSERT(x) if(!(x)) rte_panic("IXGBE: x") #define DEBUGOUT(S) PMD_DRV_LOG_RAW(DEBUG, S) #define DEBUGOUT1(S, A...) PMD_DRV_LOG_RAW(DEBUG, S, ##A) #define DEBUGFUNC(F) DEBUGOUT(F "\n") #define DEBUGOUT2 DEBUGOUT1 #define DEBUGOUT3 DEBUGOUT2 #define DEBUGOUT6 DEBUGOUT3 #define DEBUGOUT7 DEBUGOUT6 #define i40e_debug(h, m, s, ...) \ do { \ if (((m) & (h)->debug_mask)) \ PMD_DRV_LOG_RAW(DEBUG, "i40e %02x.%x " s, \ (h)->bus.device, (h)->bus.func, \ ##__VA_ARGS__); \ } while (0) #define I40E_PCI_REG(reg) (*((volatile uint32_t *)(reg))) #define I40E_PCI_REG_ADDR(a, reg) \ ((volatile uint32_t *)((char *)(a)->hw_addr + (reg))) static inline uint32_t i40e_read_addr(volatile void *addr) { return rte_le_to_cpu_32(I40E_PCI_REG(addr)); } #define I40E_PCI_REG_WRITE(reg, value) \ do { I40E_PCI_REG((reg)) = rte_cpu_to_le_32(value); } while (0) #define I40E_WRITE_FLUSH(a) I40E_READ_REG(a, I40E_GLGEN_STAT) #define I40EVF_WRITE_FLUSH(a) I40E_READ_REG(a, I40E_VFGEN_RSTAT) #define I40E_READ_REG(hw, reg) i40e_read_addr(I40E_PCI_REG_ADDR((hw), (reg))) #define I40E_WRITE_REG(hw, reg, value) \ I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((hw), (reg)), (value)) #define rd32(a, reg) i40e_read_addr(I40E_PCI_REG_ADDR((a), (reg))) #define wr32(a, reg, value) \ I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((a), (reg)), (value)) #define flush(a) i40e_read_addr(I40E_PCI_REG_ADDR((a), (I40E_GLGEN_STAT))) #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) /* memory allocation tracking */ struct i40e_dma_mem { void *va; u64 pa; u32 size; u64 id; } __attribute__((packed)); #define i40e_allocate_dma_mem(h, m, unused, s, a) \ i40e_allocate_dma_mem_d(h, m, s, a) #define i40e_free_dma_mem(h, m) i40e_free_dma_mem_d(h, m) struct i40e_virt_mem { void *va; u32 size; } __attribute__((packed)); #define i40e_allocate_virt_mem(h, m, s) i40e_allocate_virt_mem_d(h, m, s) #define i40e_free_virt_mem(h, m) i40e_free_virt_mem_d(h, m) #define CPU_TO_LE16(o) rte_cpu_to_le_16(o) #define CPU_TO_LE32(s) rte_cpu_to_le_32(s) #define CPU_TO_LE64(h) rte_cpu_to_le_64(h) #define LE16_TO_CPU(a) rte_le_to_cpu_16(a) #define LE32_TO_CPU(c) rte_le_to_cpu_32(c) #define LE64_TO_CPU(k) rte_le_to_cpu_64(k) /* SW spinlock */ struct i40e_spinlock { rte_spinlock_t spinlock; }; #define i40e_init_spinlock(_sp) i40e_init_spinlock_d(_sp) #define i40e_acquire_spinlock(_sp) i40e_acquire_spinlock_d(_sp) #define i40e_release_spinlock(_sp) i40e_release_spinlock_d(_sp) #define i40e_destroy_spinlock(_sp) i40e_destroy_spinlock_d(_sp) #define I40E_NTOHS(a) rte_be_to_cpu_16(a) #define I40E_NTOHL(a) rte_be_to_cpu_32(a) #define I40E_HTONS(a) rte_cpu_to_be_16(a) #define I40E_HTONL(a) rte_cpu_to_be_32(a) #define i40e_memset(a, b, c, d) memset((a), (b), (c)) #define i40e_memcpy(a, b, c, d) rte_memcpy((a), (b), (c)) #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define DELAY(x) rte_delay_us(x) #define i40e_usec_delay(x) rte_delay_us(x) #define i40e_msec_delay(x) rte_delay_us(1000*(x)) #define udelay(x) DELAY(x) #define msleep(x) DELAY(1000*(x)) #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000)) #endif /* _I40E_OSDEP_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_prototype.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_PROTOTYPE_H_ #define _I40E_PROTOTYPE_H_ #include "i40e_type.h" #include "i40e_alloc.h" #include "i40e_virtchnl.h" /* Prototypes for shared code functions that are not in * the standard function pointer structures. These are * mostly because they are needed even before the init * has happened and will assist in the early SW and FW * setup. */ /* adminq functions */ enum i40e_status_code i40e_init_adminq(struct i40e_hw *hw); enum i40e_status_code i40e_shutdown_adminq(struct i40e_hw *hw); enum i40e_status_code i40e_init_asq(struct i40e_hw *hw); enum i40e_status_code i40e_init_arq(struct i40e_hw *hw); enum i40e_status_code i40e_alloc_adminq_asq_ring(struct i40e_hw *hw); enum i40e_status_code i40e_alloc_adminq_arq_ring(struct i40e_hw *hw); enum i40e_status_code i40e_shutdown_asq(struct i40e_hw *hw); enum i40e_status_code i40e_shutdown_arq(struct i40e_hw *hw); u16 i40e_clean_asq(struct i40e_hw *hw); void i40e_free_adminq_asq(struct i40e_hw *hw); void i40e_free_adminq_arq(struct i40e_hw *hw); enum i40e_status_code i40e_validate_mac_addr(u8 *mac_addr); void i40e_adminq_init_ring_data(struct i40e_hw *hw); enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw, struct i40e_arq_event_info *e, u16 *events_pending); enum i40e_status_code i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc, void *buff, /* can be NULL */ u16 buff_size, struct i40e_asq_cmd_details *cmd_details); bool i40e_asq_done(struct i40e_hw *hw); /* debug function for adminq */ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, void *buffer, u16 buf_len); void i40e_idle_aq(struct i40e_hw *hw); void i40e_resume_aq(struct i40e_hw *hw); bool i40e_check_asq_alive(struct i40e_hw *hw); enum i40e_status_code i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading); #ifdef PF_DRIVER u32 i40e_led_get(struct i40e_hw *hw); void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink); /* admin send queue commands */ enum i40e_status_code i40e_aq_get_firmware_version(struct i40e_hw *hw, u16 *fw_major_version, u16 *fw_minor_version, u32 *fw_build, u16 *api_major_version, u16 *api_minor_version, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_debug_write_register(struct i40e_hw *hw, u32 reg_addr, u64 reg_val, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_debug_read_register(struct i40e_hw *hw, u32 reg_addr, u64 *reg_val, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw, bool qualified_modules, bool report_init, struct i40e_aq_get_phy_abilities_resp *abilities, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw, struct i40e_aq_set_phy_config *config, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, bool atomic_reset); enum i40e_status_code i40e_aq_set_phy_int_mask(struct i40e_hw *hw, u16 mask, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_mac_config(struct i40e_hw *hw, u16 max_frame_size, bool crc_en, u16 pacing, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_local_advt_reg(struct i40e_hw *hw, u64 *advt_reg, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_partner_advt(struct i40e_hw *hw, u64 *advt_reg, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_lb_modes(struct i40e_hw *hw, u16 lb_modes, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_clear_pxe_mode(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_link_restart_an(struct i40e_hw *hw, bool enable_link, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw, bool enable_lse, struct i40e_link_status *link, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_local_advt_reg(struct i40e_hw *hw, u64 advt_reg, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_send_driver_version(struct i40e_hw *hw, struct i40e_driver_version *dv, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_vsi(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_vsi_broadcast(struct i40e_hw *hw, u16 vsi_id, bool set_filter, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw, u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_vsi_params(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_update_vsi_params(struct i40e_hw *hw, struct i40e_vsi_context *vsi_ctx, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid, u16 downlink_seid, u8 enabled_tc, bool default_port, bool enable_l2_filtering, u16 *pveb_seid, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_veb_parameters(struct i40e_hw *hw, u16 veb_seid, u16 *switch_id, bool *floating, u16 *statistic_index, u16 *vebs_used, u16 *vebs_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_macvlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_add_macvlan_element_data *mv_list, u16 count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_remove_macvlan_element_data *mv_list, u16 count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_vlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_add_remove_vlan_element_data *v_list, u8 count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_remove_vlan(struct i40e_hw *hw, u16 vsi_id, struct i40e_aqc_add_remove_vlan_element_data *v_list, u8 count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval, u8 *msg, u16 msglen, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_switch_config(struct i40e_hw *hw, struct i40e_aqc_get_switch_config_resp *buf, u16 buf_size, u16 *start_seid, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_request_resource(struct i40e_hw *hw, enum i40e_aq_resources_ids resource, enum i40e_aq_resource_access_type access, u8 sdp_number, u64 *timeout, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_release_resource(struct i40e_hw *hw, enum i40e_aq_resources_ids resource, u8 sdp_number, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, void *data, bool last_command, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, bool last_command, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_read_nvm_config(struct i40e_hw *hw, u8 cmd_flags, u32 field_id, void *data, u16 buf_size, u16 *element_count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_write_nvm_config(struct i40e_hw *hw, u8 cmd_flags, void *data, u16 buf_size, u16 element_count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_discover_capabilities(struct i40e_hw *hw, void *buff, u16 buff_size, u16 *data_size, enum i40e_admin_queue_opc list_type_opc, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer, u32 offset, u16 length, void *data, bool last_command, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type, u8 mib_type, void *buff, u16 buff_size, u16 *local_len, u16 *remote_len, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_lldp_mib(struct i40e_hw *hw, u8 mib_type, void *buff, u16 buff_size, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw, bool enable_update, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 tlv_len, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_update_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 old_len, u16 new_len, u16 offset, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_delete_lldp_tlv(struct i40e_hw *hw, u8 bridge_type, void *buff, u16 buff_size, u16 tlv_len, u16 *mib_len, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_start_lldp(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_cee_dcb_config(struct i40e_hw *hw, void *buff, u16 buff_size, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_start_stop_dcbx(struct i40e_hw *hw, bool start_agent, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_udp_tunnel(struct i40e_hw *hw, u16 udp_port, u8 protocol_index, u8 *filter_index, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_switch_resource_alloc(struct i40e_hw *hw, u8 *num_entries, struct i40e_aqc_switch_resource_alloc_element_resp *buf, u16 count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_pvirt(struct i40e_hw *hw, u16 flags, u16 mac_seid, u16 vsi_seid, u16 *ret_seid); enum i40e_status_code i40e_aq_add_tag(struct i40e_hw *hw, bool direct_to_queue, u16 vsi_seid, u16 tag, u16 queue_num, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_remove_tag(struct i40e_hw *hw, u16 vsi_seid, u16 tag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_mcast_etag(struct i40e_hw *hw, u16 pe_seid, u16 etag, u8 num_tags_in_buf, void *buf, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_remove_mcast_etag(struct i40e_hw *hw, u16 pe_seid, u16 etag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_update_tag(struct i40e_hw *hw, u16 vsi_seid, u16 old_tag, u16 new_tag, u16 *tags_used, u16 *tags_free, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_add_statistics(struct i40e_hw *hw, u16 seid, u16 vlan_id, u16 *stat_index, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_remove_statistics(struct i40e_hw *hw, u16 seid, u16 vlan_id, u16 stat_index, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_port_parameters(struct i40e_hw *hw, u16 bad_frame_vsi, bool save_bad_pac, bool pad_short_pac, bool double_vlan, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_delete_element(struct i40e_hw *hw, u16 seid, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_mac_address_write(struct i40e_hw *hw, u16 flags, u8 *mac_addr, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw, u16 seid, u16 credit, u8 max_credit, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_dcb_ignore_pfc(struct i40e_hw *hw, u8 tcmap, bool request, u8 *tcmap_ret, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_get_hmc_resource_profile(struct i40e_hw *hw, enum i40e_aq_hmc_profile *profile, u8 *pe_vf_enabled_count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_config_switch_comp_ets_bw_limit( struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_switching_comp_ets_bw_limit_data *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_config_vsi_ets_sla_bw_limit(struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_vsi_ets_sla_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_dcb_updated(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_set_hmc_resource_profile(struct i40e_hw *hw, enum i40e_aq_hmc_profile profile, u8 pe_vf_enabled_count, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_config_switch_comp_bw_limit(struct i40e_hw *hw, u16 seid, u16 credit, u8 max_bw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw, u16 seid, struct i40e_aqc_configure_vsi_tc_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_query_vsi_bw_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_vsi_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_query_vsi_ets_sla_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_vsi_ets_sla_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_query_switch_comp_ets_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_switching_comp_ets_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_query_port_ets_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_port_ets_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw, u16 seid, struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_aq_resume_port_tx(struct i40e_hw *hw, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_read_lldp_cfg(struct i40e_hw *hw, struct i40e_lldp_variables *lldp_cfg); enum i40e_status_code i40e_aq_add_cloud_filters(struct i40e_hw *hw, u16 vsi, struct i40e_aqc_add_remove_cloud_filters_element_data *filters, u8 filter_count); enum i40e_status_code i40e_aq_remove_cloud_filters(struct i40e_hw *hw, u16 vsi, struct i40e_aqc_add_remove_cloud_filters_element_data *filters, u8 filter_count); enum i40e_status_code i40e_aq_alternate_read(struct i40e_hw *hw, u32 reg_addr0, u32 *reg_val0, u32 reg_addr1, u32 *reg_val1); enum i40e_status_code i40e_aq_alternate_read_indirect(struct i40e_hw *hw, u32 addr, u32 dw_count, void *buffer); enum i40e_status_code i40e_aq_alternate_write(struct i40e_hw *hw, u32 reg_addr0, u32 reg_val0, u32 reg_addr1, u32 reg_val1); enum i40e_status_code i40e_aq_alternate_write_indirect(struct i40e_hw *hw, u32 addr, u32 dw_count, void *buffer); enum i40e_status_code i40e_aq_alternate_clear(struct i40e_hw *hw); enum i40e_status_code i40e_aq_alternate_write_done(struct i40e_hw *hw, u8 bios_mode, bool *reset_needed); enum i40e_status_code i40e_aq_set_oem_mode(struct i40e_hw *hw, u8 oem_mode); /* i40e_common */ enum i40e_status_code i40e_init_shared_code(struct i40e_hw *hw); enum i40e_status_code i40e_pf_reset(struct i40e_hw *hw); void i40e_clear_hw(struct i40e_hw *hw); void i40e_clear_pxe_mode(struct i40e_hw *hw); bool i40e_get_link_status(struct i40e_hw *hw); enum i40e_status_code i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr); enum i40e_status_code i40e_read_bw_from_alt_ram(struct i40e_hw *hw, u32 *max_bw, u32 *min_bw, bool *min_valid, bool *max_valid); enum i40e_status_code i40e_aq_configure_partition_bw(struct i40e_hw *hw, struct i40e_aqc_configure_partition_bw_data *bw_data, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr); enum i40e_status_code i40e_read_pba_string(struct i40e_hw *hw, u8 *pba_num, u32 pba_num_size); void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable); enum i40e_aq_link_speed i40e_get_link_speed(struct i40e_hw *hw); /* prototype for functions used for NVM access */ enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw); enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw, enum i40e_aq_resource_access_type access); void i40e_release_nvm(struct i40e_hw *hw); enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, u16 *data); enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data); enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module, u32 offset, u16 words, void *data, bool last_command); enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset, void *data); enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw, u8 module, u32 offset, u16 words, void *data); enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum); enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw); enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw, u16 *checksum); enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *); void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status); #endif /* PF_DRIVER */ #if defined(I40E_QV) || defined(VF_DRIVER) enum i40e_status_code i40e_set_mac_type(struct i40e_hw *hw); #endif extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[]; STATIC INLINE struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) { return i40e_ptype_lookup[ptype]; } /* prototype for functions used for SW spinlocks */ void i40e_init_spinlock(struct i40e_spinlock *sp); void i40e_acquire_spinlock(struct i40e_spinlock *sp); void i40e_release_spinlock(struct i40e_spinlock *sp); void i40e_destroy_spinlock(struct i40e_spinlock *sp); /* i40e_common for VF drivers*/ void i40e_vf_parse_hw_config(struct i40e_hw *hw, struct i40e_virtchnl_vf_resource *msg); enum i40e_status_code i40e_vf_reset(struct i40e_hw *hw); enum i40e_status_code i40e_aq_send_msg_to_pf(struct i40e_hw *hw, enum i40e_virtchnl_ops v_opcode, enum i40e_status_code v_retval, u8 *msg, u16 msglen, struct i40e_asq_cmd_details *cmd_details); enum i40e_status_code i40e_set_filter_control(struct i40e_hw *hw, struct i40e_filter_control_settings *settings); enum i40e_status_code i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, u8 *mac_addr, u16 ethtype, u16 flags, u16 vsi_seid, u16 queue, bool is_add, struct i40e_control_filter_stats *stats, struct i40e_asq_cmd_details *cmd_details); #endif /* _I40E_PROTOTYPE_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_register.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_REGISTER_H_ #define _I40E_REGISTER_H_ #define I40E_GL_ARQBAH 0x000801C0 /* Reset: EMPR */ #define I40E_GL_ARQBAH_ARQBAH_SHIFT 0 #define I40E_GL_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAH_ARQBAH_SHIFT) #define I40E_GL_ARQBAL 0x000800C0 /* Reset: EMPR */ #define I40E_GL_ARQBAL_ARQBAL_SHIFT 0 #define I40E_GL_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ARQBAL_ARQBAL_SHIFT) #define I40E_GL_ARQH 0x000803C0 /* Reset: EMPR */ #define I40E_GL_ARQH_ARQH_SHIFT 0 #define I40E_GL_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_GL_ARQH_ARQH_SHIFT) #define I40E_GL_ARQT 0x000804C0 /* Reset: EMPR */ #define I40E_GL_ARQT_ARQT_SHIFT 0 #define I40E_GL_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_GL_ARQT_ARQT_SHIFT) #define I40E_GL_ATQBAH 0x00080140 /* Reset: EMPR */ #define I40E_GL_ATQBAH_ATQBAH_SHIFT 0 #define I40E_GL_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAH_ATQBAH_SHIFT) #define I40E_GL_ATQBAL 0x00080040 /* Reset: EMPR */ #define I40E_GL_ATQBAL_ATQBAL_SHIFT 0 #define I40E_GL_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_ATQBAL_ATQBAL_SHIFT) #define I40E_GL_ATQH 0x00080340 /* Reset: EMPR */ #define I40E_GL_ATQH_ATQH_SHIFT 0 #define I40E_GL_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_GL_ATQH_ATQH_SHIFT) #define I40E_GL_ATQLEN 0x00080240 /* Reset: EMPR */ #define I40E_GL_ATQLEN_ATQLEN_SHIFT 0 #define I40E_GL_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_GL_ATQLEN_ATQLEN_SHIFT) #define I40E_GL_ATQLEN_ATQVFE_SHIFT 28 #define I40E_GL_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQVFE_SHIFT) #define I40E_GL_ATQLEN_ATQOVFL_SHIFT 29 #define I40E_GL_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQOVFL_SHIFT) #define I40E_GL_ATQLEN_ATQCRIT_SHIFT 30 #define I40E_GL_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQCRIT_SHIFT) #define I40E_GL_ATQLEN_ATQENABLE_SHIFT 31 #define I40E_GL_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_GL_ATQLEN_ATQENABLE_SHIFT) #define I40E_GL_ATQT 0x00080440 /* Reset: EMPR */ #define I40E_GL_ATQT_ATQT_SHIFT 0 #define I40E_GL_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_GL_ATQT_ATQT_SHIFT) #define I40E_PF_ARQBAH 0x00080180 /* Reset: EMPR */ #define I40E_PF_ARQBAH_ARQBAH_SHIFT 0 #define I40E_PF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAH_ARQBAH_SHIFT) #define I40E_PF_ARQBAL 0x00080080 /* Reset: EMPR */ #define I40E_PF_ARQBAL_ARQBAL_SHIFT 0 #define I40E_PF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ARQBAL_ARQBAL_SHIFT) #define I40E_PF_ARQH 0x00080380 /* Reset: EMPR */ #define I40E_PF_ARQH_ARQH_SHIFT 0 #define I40E_PF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_PF_ARQH_ARQH_SHIFT) #define I40E_PF_ARQLEN 0x00080280 /* Reset: EMPR */ #define I40E_PF_ARQLEN_ARQLEN_SHIFT 0 #define I40E_PF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ARQLEN_ARQLEN_SHIFT) #define I40E_PF_ARQLEN_ARQVFE_SHIFT 28 #define I40E_PF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQVFE_SHIFT) #define I40E_PF_ARQLEN_ARQOVFL_SHIFT 29 #define I40E_PF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQOVFL_SHIFT) #define I40E_PF_ARQLEN_ARQCRIT_SHIFT 30 #define I40E_PF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQCRIT_SHIFT) #define I40E_PF_ARQLEN_ARQENABLE_SHIFT 31 #define I40E_PF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_PF_ARQLEN_ARQENABLE_SHIFT) #define I40E_PF_ARQT 0x00080480 /* Reset: EMPR */ #define I40E_PF_ARQT_ARQT_SHIFT 0 #define I40E_PF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_PF_ARQT_ARQT_SHIFT) #define I40E_PF_ATQBAH 0x00080100 /* Reset: EMPR */ #define I40E_PF_ATQBAH_ATQBAH_SHIFT 0 #define I40E_PF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAH_ATQBAH_SHIFT) #define I40E_PF_ATQBAL 0x00080000 /* Reset: EMPR */ #define I40E_PF_ATQBAL_ATQBAL_SHIFT 0 #define I40E_PF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_ATQBAL_ATQBAL_SHIFT) #define I40E_PF_ATQH 0x00080300 /* Reset: EMPR */ #define I40E_PF_ATQH_ATQH_SHIFT 0 #define I40E_PF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_PF_ATQH_ATQH_SHIFT) #define I40E_PF_ATQLEN 0x00080200 /* Reset: EMPR */ #define I40E_PF_ATQLEN_ATQLEN_SHIFT 0 #define I40E_PF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_PF_ATQLEN_ATQLEN_SHIFT) #define I40E_PF_ATQLEN_ATQVFE_SHIFT 28 #define I40E_PF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQVFE_SHIFT) #define I40E_PF_ATQLEN_ATQOVFL_SHIFT 29 #define I40E_PF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQOVFL_SHIFT) #define I40E_PF_ATQLEN_ATQCRIT_SHIFT 30 #define I40E_PF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQCRIT_SHIFT) #define I40E_PF_ATQLEN_ATQENABLE_SHIFT 31 #define I40E_PF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_PF_ATQLEN_ATQENABLE_SHIFT) #define I40E_PF_ATQT 0x00080400 /* Reset: EMPR */ #define I40E_PF_ATQT_ATQT_SHIFT 0 #define I40E_PF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_PF_ATQT_ATQT_SHIFT) #define I40E_VF_ARQBAH(_VF) (0x00081400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQBAH_MAX_INDEX 127 #define I40E_VF_ARQBAH_ARQBAH_SHIFT 0 #define I40E_VF_ARQBAH_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH_ARQBAH_SHIFT) #define I40E_VF_ARQBAL(_VF) (0x00080C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQBAL_MAX_INDEX 127 #define I40E_VF_ARQBAL_ARQBAL_SHIFT 0 #define I40E_VF_ARQBAL_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL_ARQBAL_SHIFT) #define I40E_VF_ARQH(_VF) (0x00082400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQH_MAX_INDEX 127 #define I40E_VF_ARQH_ARQH_SHIFT 0 #define I40E_VF_ARQH_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH_ARQH_SHIFT) #define I40E_VF_ARQLEN(_VF) (0x00081C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQLEN_MAX_INDEX 127 #define I40E_VF_ARQLEN_ARQLEN_SHIFT 0 #define I40E_VF_ARQLEN_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN_ARQLEN_SHIFT) #define I40E_VF_ARQLEN_ARQVFE_SHIFT 28 #define I40E_VF_ARQLEN_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQVFE_SHIFT) #define I40E_VF_ARQLEN_ARQOVFL_SHIFT 29 #define I40E_VF_ARQLEN_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQOVFL_SHIFT) #define I40E_VF_ARQLEN_ARQCRIT_SHIFT 30 #define I40E_VF_ARQLEN_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQCRIT_SHIFT) #define I40E_VF_ARQLEN_ARQENABLE_SHIFT 31 #define I40E_VF_ARQLEN_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN_ARQENABLE_SHIFT) #define I40E_VF_ARQT(_VF) (0x00082C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ARQT_MAX_INDEX 127 #define I40E_VF_ARQT_ARQT_SHIFT 0 #define I40E_VF_ARQT_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT_ARQT_SHIFT) #define I40E_VF_ATQBAH(_VF) (0x00081000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQBAH_MAX_INDEX 127 #define I40E_VF_ATQBAH_ATQBAH_SHIFT 0 #define I40E_VF_ATQBAH_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH_ATQBAH_SHIFT) #define I40E_VF_ATQBAL(_VF) (0x00080800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQBAL_MAX_INDEX 127 #define I40E_VF_ATQBAL_ATQBAL_SHIFT 0 #define I40E_VF_ATQBAL_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL_ATQBAL_SHIFT) #define I40E_VF_ATQH(_VF) (0x00082000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQH_MAX_INDEX 127 #define I40E_VF_ATQH_ATQH_SHIFT 0 #define I40E_VF_ATQH_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH_ATQH_SHIFT) #define I40E_VF_ATQLEN(_VF) (0x00081800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQLEN_MAX_INDEX 127 #define I40E_VF_ATQLEN_ATQLEN_SHIFT 0 #define I40E_VF_ATQLEN_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN_ATQLEN_SHIFT) #define I40E_VF_ATQLEN_ATQVFE_SHIFT 28 #define I40E_VF_ATQLEN_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQVFE_SHIFT) #define I40E_VF_ATQLEN_ATQOVFL_SHIFT 29 #define I40E_VF_ATQLEN_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQOVFL_SHIFT) #define I40E_VF_ATQLEN_ATQCRIT_SHIFT 30 #define I40E_VF_ATQLEN_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQCRIT_SHIFT) #define I40E_VF_ATQLEN_ATQENABLE_SHIFT 31 #define I40E_VF_ATQLEN_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN_ATQENABLE_SHIFT) #define I40E_VF_ATQT(_VF) (0x00082800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: EMPR */ #define I40E_VF_ATQT_MAX_INDEX 127 #define I40E_VF_ATQT_ATQT_SHIFT 0 #define I40E_VF_ATQT_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT_ATQT_SHIFT) #define I40E_PRT_L2TAGSEN 0x001C0B20 /* Reset: CORER */ #define I40E_PRT_L2TAGSEN_ENABLE_SHIFT 0 #define I40E_PRT_L2TAGSEN_ENABLE_MASK I40E_MASK(0xFF, I40E_PRT_L2TAGSEN_ENABLE_SHIFT) #define I40E_PFCM_LAN_ERRDATA 0x0010C080 /* Reset: PFR */ #define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT 0 #define I40E_PFCM_LAN_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_PFCM_LAN_ERRDATA_ERROR_CODE_SHIFT) #define I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT 4 #define I40E_PFCM_LAN_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRDATA_Q_TYPE_SHIFT) #define I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT 8 #define I40E_PFCM_LAN_ERRDATA_Q_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LAN_ERRDATA_Q_NUM_SHIFT) #define I40E_PFCM_LAN_ERRINFO 0x0010C000 /* Reset: PFR */ #define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT 0 #define I40E_PFCM_LAN_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_PFCM_LAN_ERRINFO_ERROR_VALID_SHIFT) #define I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT 4 #define I40E_PFCM_LAN_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_PFCM_LAN_ERRINFO_ERROR_INST_SHIFT) #define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT 8 #define I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_DBL_ERROR_CNT_SHIFT) #define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT 16 #define I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLU_ERROR_CNT_SHIFT) #define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT 24 #define I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_PFCM_LAN_ERRINFO_RLS_ERROR_CNT_SHIFT) #define I40E_PFCM_LANCTXCTL 0x0010C300 /* Reset: CORER */ #define I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT 0 #define I40E_PFCM_LANCTXCTL_QUEUE_NUM_MASK I40E_MASK(0xFFF, I40E_PFCM_LANCTXCTL_QUEUE_NUM_SHIFT) #define I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT 12 #define I40E_PFCM_LANCTXCTL_SUB_LINE_MASK I40E_MASK(0x7, I40E_PFCM_LANCTXCTL_SUB_LINE_SHIFT) #define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT 15 #define I40E_PFCM_LANCTXCTL_QUEUE_TYPE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_QUEUE_TYPE_SHIFT) #define I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT 17 #define I40E_PFCM_LANCTXCTL_OP_CODE_MASK I40E_MASK(0x3, I40E_PFCM_LANCTXCTL_OP_CODE_SHIFT) #define I40E_PFCM_LANCTXDATA(_i) (0x0010C100 + ((_i) * 128)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_PFCM_LANCTXDATA_MAX_INDEX 3 #define I40E_PFCM_LANCTXDATA_DATA_SHIFT 0 #define I40E_PFCM_LANCTXDATA_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFCM_LANCTXDATA_DATA_SHIFT) #define I40E_PFCM_LANCTXSTAT 0x0010C380 /* Reset: CORER */ #define I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT 0 #define I40E_PFCM_LANCTXSTAT_CTX_DONE_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_DONE_SHIFT) #define I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT 1 #define I40E_PFCM_LANCTXSTAT_CTX_MISS_MASK I40E_MASK(0x1, I40E_PFCM_LANCTXSTAT_CTX_MISS_SHIFT) #define I40E_VFCM_PE_ERRDATA1(_VF) (0x00138800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VFCM_PE_ERRDATA1_MAX_INDEX 127 #define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT 0 #define I40E_VFCM_PE_ERRDATA1_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA1_ERROR_CODE_SHIFT) #define I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT 4 #define I40E_VFCM_PE_ERRDATA1_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA1_Q_TYPE_SHIFT) #define I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT 8 #define I40E_VFCM_PE_ERRDATA1_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA1_Q_NUM_SHIFT) #define I40E_VFCM_PE_ERRINFO1(_VF) (0x00138400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VFCM_PE_ERRINFO1_MAX_INDEX 127 #define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT 0 #define I40E_VFCM_PE_ERRINFO1_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO1_ERROR_VALID_SHIFT) #define I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT 4 #define I40E_VFCM_PE_ERRINFO1_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO1_ERROR_INST_SHIFT) #define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT 8 #define I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_DBL_ERROR_CNT_SHIFT) #define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT 16 #define I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLU_ERROR_CNT_SHIFT) #define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT 24 #define I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO1_RLS_ERROR_CNT_SHIFT) #define I40E_GLDCB_GENC 0x00083044 /* Reset: CORER */ #define I40E_GLDCB_GENC_PCIRTT_SHIFT 0 #define I40E_GLDCB_GENC_PCIRTT_MASK I40E_MASK(0xFFFF, I40E_GLDCB_GENC_PCIRTT_SHIFT) #define I40E_GLDCB_RUPTI 0x00122618 /* Reset: CORER */ #define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT 0 #define I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLDCB_RUPTI_PFCTIMEOUT_UP_SHIFT) #define I40E_PRTDCB_FCCFG 0x001E4640 /* Reset: GLOBR */ #define I40E_PRTDCB_FCCFG_TFCE_SHIFT 3 #define I40E_PRTDCB_FCCFG_TFCE_MASK I40E_MASK(0x3, I40E_PRTDCB_FCCFG_TFCE_SHIFT) #define I40E_PRTDCB_FCRTV 0x001E4600 /* Reset: GLOBR */ #define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT 0 #define I40E_PRTDCB_FCRTV_FC_REFRESH_TH_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCRTV_FC_REFRESH_TH_SHIFT) #define I40E_PRTDCB_FCTTVN(_i) (0x001E4580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: GLOBR */ #define I40E_PRTDCB_FCTTVN_MAX_INDEX 3 #define I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT 0 #define I40E_PRTDCB_FCTTVN_TTV_2N_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_SHIFT) #define I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT 16 #define I40E_PRTDCB_FCTTVN_TTV_2N_P1_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_FCTTVN_TTV_2N_P1_SHIFT) #define I40E_PRTDCB_GENC 0x00083000 /* Reset: CORER */ #define I40E_PRTDCB_GENC_RESERVED_1_SHIFT 0 #define I40E_PRTDCB_GENC_RESERVED_1_MASK I40E_MASK(0x3, I40E_PRTDCB_GENC_RESERVED_1_SHIFT) #define I40E_PRTDCB_GENC_NUMTC_SHIFT 2 #define I40E_PRTDCB_GENC_NUMTC_MASK I40E_MASK(0xF, I40E_PRTDCB_GENC_NUMTC_SHIFT) #define I40E_PRTDCB_GENC_FCOEUP_SHIFT 6 #define I40E_PRTDCB_GENC_FCOEUP_MASK I40E_MASK(0x7, I40E_PRTDCB_GENC_FCOEUP_SHIFT) #define I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT 9 #define I40E_PRTDCB_GENC_FCOEUP_VALID_MASK I40E_MASK(0x1, I40E_PRTDCB_GENC_FCOEUP_VALID_SHIFT) #define I40E_PRTDCB_GENC_PFCLDA_SHIFT 16 #define I40E_PRTDCB_GENC_PFCLDA_MASK I40E_MASK(0xFFFF, I40E_PRTDCB_GENC_PFCLDA_SHIFT) #define I40E_PRTDCB_GENS 0x00083020 /* Reset: CORER */ #define I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT 0 #define I40E_PRTDCB_GENS_DCBX_STATUS_MASK I40E_MASK(0x7, I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT) #define I40E_PRTDCB_MFLCN 0x001E2400 /* Reset: GLOBR */ #define I40E_PRTDCB_MFLCN_PMCF_SHIFT 0 #define I40E_PRTDCB_MFLCN_PMCF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_PMCF_SHIFT) #define I40E_PRTDCB_MFLCN_DPF_SHIFT 1 #define I40E_PRTDCB_MFLCN_DPF_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_DPF_SHIFT) #define I40E_PRTDCB_MFLCN_RPFCM_SHIFT 2 #define I40E_PRTDCB_MFLCN_RPFCM_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RPFCM_SHIFT) #define I40E_PRTDCB_MFLCN_RFCE_SHIFT 3 #define I40E_PRTDCB_MFLCN_RFCE_MASK I40E_MASK(0x1, I40E_PRTDCB_MFLCN_RFCE_SHIFT) #define I40E_PRTDCB_MFLCN_RPFCE_SHIFT 4 #define I40E_PRTDCB_MFLCN_RPFCE_MASK I40E_MASK(0xFF, I40E_PRTDCB_MFLCN_RPFCE_SHIFT) #define I40E_PRTDCB_RETSC 0x001223E0 /* Reset: CORER */ #define I40E_PRTDCB_RETSC_ETS_MODE_SHIFT 0 #define I40E_PRTDCB_RETSC_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_ETS_MODE_SHIFT) #define I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT 1 #define I40E_PRTDCB_RETSC_NON_ETS_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSC_NON_ETS_MODE_SHIFT) #define I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT 2 #define I40E_PRTDCB_RETSC_ETS_MAX_EXP_MASK I40E_MASK(0xF, I40E_PRTDCB_RETSC_ETS_MAX_EXP_SHIFT) #define I40E_PRTDCB_RETSC_LLTC_SHIFT 8 #define I40E_PRTDCB_RETSC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_RETSC_LLTC_SHIFT) #define I40E_PRTDCB_RETSTCC(_i) (0x00122180 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTDCB_RETSTCC_MAX_INDEX 7 #define I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT 0 #define I40E_PRTDCB_RETSTCC_BWSHARE_MASK I40E_MASK(0x7F, I40E_PRTDCB_RETSTCC_BWSHARE_SHIFT) #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT 30 #define I40E_PRTDCB_RETSTCC_UPINTC_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_UPINTC_MODE_SHIFT) #define I40E_PRTDCB_RETSTCC_ETSTC_SHIFT 31 #define I40E_PRTDCB_RETSTCC_ETSTC_MASK I40E_MASK(0x1, I40E_PRTDCB_RETSTCC_ETSTC_SHIFT) #define I40E_PRTDCB_RPPMC 0x001223A0 /* Reset: CORER */ #define I40E_PRTDCB_RPPMC_LANRPPM_SHIFT 0 #define I40E_PRTDCB_RPPMC_LANRPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_LANRPPM_SHIFT) #define I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT 8 #define I40E_PRTDCB_RPPMC_RDMARPPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RDMARPPM_SHIFT) #define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT 16 #define I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_MASK I40E_MASK(0xFF, I40E_PRTDCB_RPPMC_RX_FIFO_SIZE_SHIFT) #define I40E_PRTDCB_RUP 0x001C0B00 /* Reset: CORER */ #define I40E_PRTDCB_RUP_NOVLANUP_SHIFT 0 #define I40E_PRTDCB_RUP_NOVLANUP_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP_NOVLANUP_SHIFT) #define I40E_PRTDCB_RUP2TC 0x001C09A0 /* Reset: CORER */ #define I40E_PRTDCB_RUP2TC_UP0TC_SHIFT 0 #define I40E_PRTDCB_RUP2TC_UP0TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP0TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP1TC_SHIFT 3 #define I40E_PRTDCB_RUP2TC_UP1TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP1TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP2TC_SHIFT 6 #define I40E_PRTDCB_RUP2TC_UP2TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP2TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP3TC_SHIFT 9 #define I40E_PRTDCB_RUP2TC_UP3TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP3TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP4TC_SHIFT 12 #define I40E_PRTDCB_RUP2TC_UP4TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP4TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP5TC_SHIFT 15 #define I40E_PRTDCB_RUP2TC_UP5TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP5TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP6TC_SHIFT 18 #define I40E_PRTDCB_RUP2TC_UP6TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP6TC_SHIFT) #define I40E_PRTDCB_RUP2TC_UP7TC_SHIFT 21 #define I40E_PRTDCB_RUP2TC_UP7TC_MASK I40E_MASK(0x7, I40E_PRTDCB_RUP2TC_UP7TC_SHIFT) #define I40E_PRTDCB_RUPTQ(_i) (0x00122400 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTDCB_RUPTQ_MAX_INDEX 7 #define I40E_PRTDCB_RUPTQ_RXQNUM_SHIFT 0 #define I40E_PRTDCB_RUPTQ_RXQNUM_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_RUPTQ_RXQNUM_SHIFT) #define I40E_PRTDCB_TC2PFC 0x001C0980 /* Reset: CORER */ #define I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT 0 #define I40E_PRTDCB_TC2PFC_TC2PFC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TC2PFC_TC2PFC_SHIFT) #define I40E_PRTDCB_TCMSTC(_i) (0x000A0040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTDCB_TCMSTC_MAX_INDEX 7 #define I40E_PRTDCB_TCMSTC_MSTC_SHIFT 0 #define I40E_PRTDCB_TCMSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCMSTC_MSTC_SHIFT) #define I40E_PRTDCB_TCPMC 0x000A21A0 /* Reset: CORER */ #define I40E_PRTDCB_TCPMC_CPM_SHIFT 0 #define I40E_PRTDCB_TCPMC_CPM_MASK I40E_MASK(0x1FFF, I40E_PRTDCB_TCPMC_CPM_SHIFT) #define I40E_PRTDCB_TCPMC_LLTC_SHIFT 13 #define I40E_PRTDCB_TCPMC_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TCPMC_LLTC_SHIFT) #define I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT 30 #define I40E_PRTDCB_TCPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TCPMC_TCPM_MODE_SHIFT) #define I40E_PRTDCB_TCWSTC(_i) (0x000A2040 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTDCB_TCWSTC_MAX_INDEX 7 #define I40E_PRTDCB_TCWSTC_MSTC_SHIFT 0 #define I40E_PRTDCB_TCWSTC_MSTC_MASK I40E_MASK(0xFFFFF, I40E_PRTDCB_TCWSTC_MSTC_SHIFT) #define I40E_PRTDCB_TDPMC 0x000A0180 /* Reset: CORER */ #define I40E_PRTDCB_TDPMC_DPM_SHIFT 0 #define I40E_PRTDCB_TDPMC_DPM_MASK I40E_MASK(0xFF, I40E_PRTDCB_TDPMC_DPM_SHIFT) #define I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT 30 #define I40E_PRTDCB_TDPMC_TCPM_MODE_MASK I40E_MASK(0x1, I40E_PRTDCB_TDPMC_TCPM_MODE_SHIFT) #define I40E_PRTDCB_TETSC_TCB 0x000AE060 /* Reset: CORER */ #define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT 0 #define I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TCB_EN_LL_STRICT_PRIORITY_SHIFT) #define I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT 8 #define I40E_PRTDCB_TETSC_TCB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TCB_LLTC_SHIFT) #define I40E_PRTDCB_TETSC_TPB 0x00098060 /* Reset: CORER */ #define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT 0 #define I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_MASK I40E_MASK(0x1, I40E_PRTDCB_TETSC_TPB_EN_LL_STRICT_PRIORITY_SHIFT) #define I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT 8 #define I40E_PRTDCB_TETSC_TPB_LLTC_MASK I40E_MASK(0xFF, I40E_PRTDCB_TETSC_TPB_LLTC_SHIFT) #define I40E_PRTDCB_TFCS 0x001E4560 /* Reset: GLOBR */ #define I40E_PRTDCB_TFCS_TXOFF_SHIFT 0 #define I40E_PRTDCB_TFCS_TXOFF_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF0_SHIFT 8 #define I40E_PRTDCB_TFCS_TXOFF0_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF0_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF1_SHIFT 9 #define I40E_PRTDCB_TFCS_TXOFF1_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF1_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF2_SHIFT 10 #define I40E_PRTDCB_TFCS_TXOFF2_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF2_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF3_SHIFT 11 #define I40E_PRTDCB_TFCS_TXOFF3_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF3_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF4_SHIFT 12 #define I40E_PRTDCB_TFCS_TXOFF4_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF4_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF5_SHIFT 13 #define I40E_PRTDCB_TFCS_TXOFF5_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF5_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF6_SHIFT 14 #define I40E_PRTDCB_TFCS_TXOFF6_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF6_SHIFT) #define I40E_PRTDCB_TFCS_TXOFF7_SHIFT 15 #define I40E_PRTDCB_TFCS_TXOFF7_MASK I40E_MASK(0x1, I40E_PRTDCB_TFCS_TXOFF7_SHIFT) #define I40E_PRTDCB_TPFCTS(_i) (0x001E4660 + ((_i) * 32)) /* _i=0...7 */ /* Reset: GLOBR */ #define I40E_PRTDCB_TPFCTS_MAX_INDEX 7 #define I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT 0 #define I40E_PRTDCB_TPFCTS_PFCTIMER_MASK I40E_MASK(0x3FFF, I40E_PRTDCB_TPFCTS_PFCTIMER_SHIFT) #define I40E_GLFCOE_RCTL 0x00269B94 /* Reset: CORER */ #define I40E_GLFCOE_RCTL_FCOEVER_SHIFT 0 #define I40E_GLFCOE_RCTL_FCOEVER_MASK I40E_MASK(0xF, I40E_GLFCOE_RCTL_FCOEVER_SHIFT) #define I40E_GLFCOE_RCTL_SAVBAD_SHIFT 4 #define I40E_GLFCOE_RCTL_SAVBAD_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_SAVBAD_SHIFT) #define I40E_GLFCOE_RCTL_ICRC_SHIFT 5 #define I40E_GLFCOE_RCTL_ICRC_MASK I40E_MASK(0x1, I40E_GLFCOE_RCTL_ICRC_SHIFT) #define I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT 16 #define I40E_GLFCOE_RCTL_MAX_SIZE_MASK I40E_MASK(0x3FFF, I40E_GLFCOE_RCTL_MAX_SIZE_SHIFT) #define I40E_GL_FWSTS 0x00083048 /* Reset: POR */ #define I40E_GL_FWSTS_FWS0B_SHIFT 0 #define I40E_GL_FWSTS_FWS0B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS0B_SHIFT) #define I40E_GL_FWSTS_FWRI_SHIFT 9 #define I40E_GL_FWSTS_FWRI_MASK I40E_MASK(0x1, I40E_GL_FWSTS_FWRI_SHIFT) #define I40E_GL_FWSTS_FWS1B_SHIFT 16 #define I40E_GL_FWSTS_FWS1B_MASK I40E_MASK(0xFF, I40E_GL_FWSTS_FWS1B_SHIFT) #define I40E_GLGEN_CLKSTAT 0x000B8184 /* Reset: POR */ #define I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT 0 #define I40E_GLGEN_CLKSTAT_CLKMODE_MASK I40E_MASK(0x1, I40E_GLGEN_CLKSTAT_CLKMODE_SHIFT) #define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT 4 #define I40E_GLGEN_CLKSTAT_U_CLK_SPEED_MASK I40E_MASK(0x3, I40E_GLGEN_CLKSTAT_U_CLK_SPEED_SHIFT) #define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT 8 #define I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P0_CLK_SPEED_SHIFT) #define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT 12 #define I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P1_CLK_SPEED_SHIFT) #define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT 16 #define I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P2_CLK_SPEED_SHIFT) #define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT 20 #define I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_MASK I40E_MASK(0x7, I40E_GLGEN_CLKSTAT_P3_CLK_SPEED_SHIFT) #define I40E_GLGEN_GPIO_CTL(_i) (0x00088100 + ((_i) * 4)) /* _i=0...29 */ /* Reset: POR */ #define I40E_GLGEN_GPIO_CTL_MAX_INDEX 29 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT 0 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT) #define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT 3 #define I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_SHIFT) #define I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT 4 #define I40E_GLGEN_GPIO_CTL_PIN_DIR_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_PIN_DIR_SHIFT) #define I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT 5 #define I40E_GLGEN_GPIO_CTL_TRI_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_TRI_CTL_SHIFT) #define I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT 6 #define I40E_GLGEN_GPIO_CTL_OUT_CTL_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_CTL_SHIFT) #define I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT 7 #define I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK I40E_MASK(0x7, I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT) #define I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT 10 #define I40E_GLGEN_GPIO_CTL_LED_INVRT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_INVRT_SHIFT) #define I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT 11 #define I40E_GLGEN_GPIO_CTL_LED_BLINK_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT) #define I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT 12 #define I40E_GLGEN_GPIO_CTL_LED_MODE_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) #define I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT 17 #define I40E_GLGEN_GPIO_CTL_INT_MODE_MASK I40E_MASK(0x3, I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT) #define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT 19 #define I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_CTL_OUT_DEFAULT_SHIFT) #define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT 20 #define I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_MASK I40E_MASK(0x3F, I40E_GLGEN_GPIO_CTL_PHY_PIN_NAME_SHIFT) #define I40E_GLGEN_GPIO_CTL_PRT_BIT_MAP_SHIFT 26 #define I40E_GLGEN_GPIO_CTL_PRT_BIT_MAP_MASK I40E_MASK(0xF, I40E_GLGEN_GPIO_CTL_PRT_BIT_MAP_SHIFT) #define I40E_GLGEN_GPIO_SET 0x00088184 /* Reset: POR */ #define I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT 0 #define I40E_GLGEN_GPIO_SET_GPIO_INDX_MASK I40E_MASK(0x1F, I40E_GLGEN_GPIO_SET_GPIO_INDX_SHIFT) #define I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT 5 #define I40E_GLGEN_GPIO_SET_SDP_DATA_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_SDP_DATA_SHIFT) #define I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT 6 #define I40E_GLGEN_GPIO_SET_DRIVE_SDP_MASK I40E_MASK(0x1, I40E_GLGEN_GPIO_SET_DRIVE_SDP_SHIFT) #define I40E_GLGEN_GPIO_STAT 0x0008817C /* Reset: POR */ #define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT 0 #define I40E_GLGEN_GPIO_STAT_GPIO_VALUE_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_STAT_GPIO_VALUE_SHIFT) #define I40E_GLGEN_GPIO_TRANSIT 0x00088180 /* Reset: POR */ #define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT 0 #define I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_MASK I40E_MASK(0x3FFFFFFF, I40E_GLGEN_GPIO_TRANSIT_GPIO_TRANSITION_SHIFT) #define I40E_GLGEN_I2CCMD(_i) (0x000881E0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_I2CCMD_MAX_INDEX 3 #define I40E_GLGEN_I2CCMD_DATA_SHIFT 0 #define I40E_GLGEN_I2CCMD_DATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_I2CCMD_DATA_SHIFT) #define I40E_GLGEN_I2CCMD_REGADD_SHIFT 16 #define I40E_GLGEN_I2CCMD_REGADD_MASK I40E_MASK(0xFF, I40E_GLGEN_I2CCMD_REGADD_SHIFT) #define I40E_GLGEN_I2CCMD_PHYADD_SHIFT 24 #define I40E_GLGEN_I2CCMD_PHYADD_MASK I40E_MASK(0x7, I40E_GLGEN_I2CCMD_PHYADD_SHIFT) #define I40E_GLGEN_I2CCMD_OP_SHIFT 27 #define I40E_GLGEN_I2CCMD_OP_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_OP_SHIFT) #define I40E_GLGEN_I2CCMD_RESET_SHIFT 28 #define I40E_GLGEN_I2CCMD_RESET_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_RESET_SHIFT) #define I40E_GLGEN_I2CCMD_R_SHIFT 29 #define I40E_GLGEN_I2CCMD_R_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_R_SHIFT) #define I40E_GLGEN_I2CCMD_E_SHIFT 31 #define I40E_GLGEN_I2CCMD_E_MASK I40E_MASK(0x1, I40E_GLGEN_I2CCMD_E_SHIFT) #define I40E_GLGEN_I2CPARAMS(_i) (0x000881AC + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_I2CPARAMS_MAX_INDEX 3 #define I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT 0 #define I40E_GLGEN_I2CPARAMS_WRITE_TIME_MASK I40E_MASK(0x1F, I40E_GLGEN_I2CPARAMS_WRITE_TIME_SHIFT) #define I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT 5 #define I40E_GLGEN_I2CPARAMS_READ_TIME_MASK I40E_MASK(0x7, I40E_GLGEN_I2CPARAMS_READ_TIME_SHIFT) #define I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT 8 #define I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2CBB_EN_SHIFT) #define I40E_GLGEN_I2CPARAMS_CLK_SHIFT 9 #define I40E_GLGEN_I2CPARAMS_CLK_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_SHIFT) #define I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT 10 #define I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OUT_SHIFT) #define I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT 11 #define I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_OE_N_SHIFT) #define I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT 12 #define I40E_GLGEN_I2CPARAMS_DATA_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_DATA_IN_SHIFT) #define I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT 13 #define I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_OE_N_SHIFT) #define I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT 14 #define I40E_GLGEN_I2CPARAMS_CLK_IN_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_IN_SHIFT) #define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT 15 #define I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_CLK_STRETCH_DIS_SHIFT) #define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT 31 #define I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_MASK I40E_MASK(0x1, I40E_GLGEN_I2CPARAMS_I2C_DATA_ORDER_SHIFT) #define I40E_GLGEN_LED_CTL 0x00088178 /* Reset: POR */ #define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT 0 #define I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_LED_CTL_GLOBAL_BLINK_MODE_SHIFT) #define I40E_GLGEN_MDIO_CTRL(_i) (0x000881D0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_MDIO_CTRL_MAX_INDEX 3 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT 0 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_MASK I40E_MASK(0x1FFFF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD2_SHIFT) #define I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT 17 #define I40E_GLGEN_MDIO_CTRL_CONTMDC_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_CTRL_CONTMDC_SHIFT) #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT 18 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_MASK I40E_MASK(0x7FF, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD1_SHIFT) #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD0_SHIFT 29 #define I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD0_MASK I40E_MASK(0x7, I40E_GLGEN_MDIO_CTRL_LEGACY_RSVD0_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL(_i) (0x000881C0 + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_MDIO_I2C_SEL_MAX_INDEX 3 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT 0 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT 1 #define I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT 5 #define I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY0_ADDRESS_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT 10 #define I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY1_ADDRESS_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT 15 #define I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY2_ADDRESS_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT 20 #define I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_MASK I40E_MASK(0x1F, I40E_GLGEN_MDIO_I2C_SEL_PHY3_ADDRESS_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT 25 #define I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_MASK I40E_MASK(0xF, I40E_GLGEN_MDIO_I2C_SEL_MDIO_IF_MODE_SHIFT) #define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT 31 #define I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_MASK I40E_MASK(0x1, I40E_GLGEN_MDIO_I2C_SEL_EN_FAST_MODE_SHIFT) #define I40E_GLGEN_MSCA(_i) (0x0008818C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_MSCA_MAX_INDEX 3 #define I40E_GLGEN_MSCA_MDIADD_SHIFT 0 #define I40E_GLGEN_MSCA_MDIADD_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSCA_MDIADD_SHIFT) #define I40E_GLGEN_MSCA_DEVADD_SHIFT 16 #define I40E_GLGEN_MSCA_DEVADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_DEVADD_SHIFT) #define I40E_GLGEN_MSCA_PHYADD_SHIFT 21 #define I40E_GLGEN_MSCA_PHYADD_MASK I40E_MASK(0x1F, I40E_GLGEN_MSCA_PHYADD_SHIFT) #define I40E_GLGEN_MSCA_OPCODE_SHIFT 26 #define I40E_GLGEN_MSCA_OPCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_OPCODE_SHIFT) #define I40E_GLGEN_MSCA_STCODE_SHIFT 28 #define I40E_GLGEN_MSCA_STCODE_MASK I40E_MASK(0x3, I40E_GLGEN_MSCA_STCODE_SHIFT) #define I40E_GLGEN_MSCA_MDICMD_SHIFT 30 #define I40E_GLGEN_MSCA_MDICMD_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDICMD_SHIFT) #define I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT 31 #define I40E_GLGEN_MSCA_MDIINPROGEN_MASK I40E_MASK(0x1, I40E_GLGEN_MSCA_MDIINPROGEN_SHIFT) #define I40E_GLGEN_MSRWD(_i) (0x0008819C + ((_i) * 4)) /* _i=0...3 */ /* Reset: POR */ #define I40E_GLGEN_MSRWD_MAX_INDEX 3 #define I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT 0 #define I40E_GLGEN_MSRWD_MDIWRDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT) #define I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT 16 #define I40E_GLGEN_MSRWD_MDIRDDATA_MASK I40E_MASK(0xFFFF, I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT) #define I40E_GLGEN_PCIFCNCNT 0x001C0AB4 /* Reset: PCIR */ #define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT 0 #define I40E_GLGEN_PCIFCNCNT_PCIPFCNT_MASK I40E_MASK(0x1F, I40E_GLGEN_PCIFCNCNT_PCIPFCNT_SHIFT) #define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT 16 #define I40E_GLGEN_PCIFCNCNT_PCIVFCNT_MASK I40E_MASK(0xFF, I40E_GLGEN_PCIFCNCNT_PCIVFCNT_SHIFT) #define I40E_GLGEN_RSTAT 0x000B8188 /* Reset: POR */ #define I40E_GLGEN_RSTAT_DEVSTATE_SHIFT 0 #define I40E_GLGEN_RSTAT_DEVSTATE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_DEVSTATE_SHIFT) #define I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT 2 #define I40E_GLGEN_RSTAT_RESET_TYPE_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT) #define I40E_GLGEN_RSTAT_CORERCNT_SHIFT 4 #define I40E_GLGEN_RSTAT_CORERCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_CORERCNT_SHIFT) #define I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT 6 #define I40E_GLGEN_RSTAT_GLOBRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_GLOBRCNT_SHIFT) #define I40E_GLGEN_RSTAT_EMPRCNT_SHIFT 8 #define I40E_GLGEN_RSTAT_EMPRCNT_MASK I40E_MASK(0x3, I40E_GLGEN_RSTAT_EMPRCNT_SHIFT) #define I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT 10 #define I40E_GLGEN_RSTAT_TIME_TO_RST_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTAT_TIME_TO_RST_SHIFT) #define I40E_GLGEN_RSTCTL 0x000B8180 /* Reset: POR */ #define I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT 0 #define I40E_GLGEN_RSTCTL_GRSTDEL_MASK I40E_MASK(0x3F, I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT) #define I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT 8 #define I40E_GLGEN_RSTCTL_ECC_RST_ENA_MASK I40E_MASK(0x1, I40E_GLGEN_RSTCTL_ECC_RST_ENA_SHIFT) #define I40E_GLGEN_RTRIG 0x000B8190 /* Reset: CORER */ #define I40E_GLGEN_RTRIG_CORER_SHIFT 0 #define I40E_GLGEN_RTRIG_CORER_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_CORER_SHIFT) #define I40E_GLGEN_RTRIG_GLOBR_SHIFT 1 #define I40E_GLGEN_RTRIG_GLOBR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_GLOBR_SHIFT) #define I40E_GLGEN_RTRIG_EMPFWR_SHIFT 2 #define I40E_GLGEN_RTRIG_EMPFWR_MASK I40E_MASK(0x1, I40E_GLGEN_RTRIG_EMPFWR_SHIFT) #define I40E_GLGEN_STAT 0x000B612C /* Reset: POR */ #define I40E_GLGEN_STAT_HWRSVD0_SHIFT 0 #define I40E_GLGEN_STAT_HWRSVD0_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD0_SHIFT) #define I40E_GLGEN_STAT_DCBEN_SHIFT 2 #define I40E_GLGEN_STAT_DCBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_DCBEN_SHIFT) #define I40E_GLGEN_STAT_VTEN_SHIFT 3 #define I40E_GLGEN_STAT_VTEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_VTEN_SHIFT) #define I40E_GLGEN_STAT_FCOEN_SHIFT 4 #define I40E_GLGEN_STAT_FCOEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_FCOEN_SHIFT) #define I40E_GLGEN_STAT_EVBEN_SHIFT 5 #define I40E_GLGEN_STAT_EVBEN_MASK I40E_MASK(0x1, I40E_GLGEN_STAT_EVBEN_SHIFT) #define I40E_GLGEN_STAT_HWRSVD1_SHIFT 6 #define I40E_GLGEN_STAT_HWRSVD1_MASK I40E_MASK(0x3, I40E_GLGEN_STAT_HWRSVD1_SHIFT) #define I40E_GLGEN_VFLRSTAT(_i) (0x00092600 + ((_i) * 4)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLGEN_VFLRSTAT_MAX_INDEX 3 #define I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT 0 #define I40E_GLGEN_VFLRSTAT_VFLRE_MASK I40E_MASK(0xFFFFFFFF, I40E_GLGEN_VFLRSTAT_VFLRE_SHIFT) #define I40E_GLVFGEN_TIMER 0x000881BC /* Reset: CORER */ #define I40E_GLVFGEN_TIMER_GTIME_SHIFT 0 #define I40E_GLVFGEN_TIMER_GTIME_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVFGEN_TIMER_GTIME_SHIFT) #define I40E_PFGEN_CTRL 0x00092400 /* Reset: PFR */ #define I40E_PFGEN_CTRL_PFSWR_SHIFT 0 #define I40E_PFGEN_CTRL_PFSWR_MASK I40E_MASK(0x1, I40E_PFGEN_CTRL_PFSWR_SHIFT) #define I40E_PFGEN_DRUN 0x00092500 /* Reset: CORER */ #define I40E_PFGEN_DRUN_DRVUNLD_SHIFT 0 #define I40E_PFGEN_DRUN_DRVUNLD_MASK I40E_MASK(0x1, I40E_PFGEN_DRUN_DRVUNLD_SHIFT) #define I40E_PFGEN_PORTNUM 0x001C0480 /* Reset: CORER */ #define I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT 0 #define I40E_PFGEN_PORTNUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT) #define I40E_PFGEN_STATE 0x00088000 /* Reset: CORER */ #define I40E_PFGEN_STATE_RESERVED_0_SHIFT 0 #define I40E_PFGEN_STATE_RESERVED_0_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_RESERVED_0_SHIFT) #define I40E_PFGEN_STATE_PFFCEN_SHIFT 1 #define I40E_PFGEN_STATE_PFFCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFFCEN_SHIFT) #define I40E_PFGEN_STATE_PFLINKEN_SHIFT 2 #define I40E_PFGEN_STATE_PFLINKEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFLINKEN_SHIFT) #define I40E_PFGEN_STATE_PFSCEN_SHIFT 3 #define I40E_PFGEN_STATE_PFSCEN_MASK I40E_MASK(0x1, I40E_PFGEN_STATE_PFSCEN_SHIFT) #define I40E_PRTGEN_CNF 0x000B8120 /* Reset: POR */ #define I40E_PRTGEN_CNF_PORT_DIS_SHIFT 0 #define I40E_PRTGEN_CNF_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_PORT_DIS_SHIFT) #define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT 1 #define I40E_PRTGEN_CNF_ALLOW_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_ALLOW_PORT_DIS_SHIFT) #define I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT 2 #define I40E_PRTGEN_CNF_EMP_PORT_DIS_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF_EMP_PORT_DIS_SHIFT) #define I40E_PRTGEN_CNF2 0x000B8160 /* Reset: POR */ #define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT 0 #define I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_MASK I40E_MASK(0x1, I40E_PRTGEN_CNF2_ACTIVATE_PORT_LINK_SHIFT) #define I40E_PRTGEN_STATUS 0x000B8100 /* Reset: POR */ #define I40E_PRTGEN_STATUS_PORT_VALID_SHIFT 0 #define I40E_PRTGEN_STATUS_PORT_VALID_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_VALID_SHIFT) #define I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT 1 #define I40E_PRTGEN_STATUS_PORT_ACTIVE_MASK I40E_MASK(0x1, I40E_PRTGEN_STATUS_PORT_ACTIVE_SHIFT) #define I40E_VFGEN_RSTAT1(_VF) (0x00074400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VFGEN_RSTAT1_MAX_INDEX 127 #define I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT 0 #define I40E_VFGEN_RSTAT1_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT1_VFR_STATE_SHIFT) #define I40E_VPGEN_VFRSTAT(_VF) (0x00091C00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VPGEN_VFRSTAT_MAX_INDEX 127 #define I40E_VPGEN_VFRSTAT_VFRD_SHIFT 0 #define I40E_VPGEN_VFRSTAT_VFRD_MASK I40E_MASK(0x1, I40E_VPGEN_VFRSTAT_VFRD_SHIFT) #define I40E_VPGEN_VFRTRIG(_VF) (0x00091800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VPGEN_VFRTRIG_MAX_INDEX 127 #define I40E_VPGEN_VFRTRIG_VFSWR_SHIFT 0 #define I40E_VPGEN_VFRTRIG_VFSWR_MASK I40E_MASK(0x1, I40E_VPGEN_VFRTRIG_VFSWR_SHIFT) #define I40E_VSIGEN_RSTAT(_VSI) (0x00090800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_VSIGEN_RSTAT_MAX_INDEX 383 #define I40E_VSIGEN_RSTAT_VMRD_SHIFT 0 #define I40E_VSIGEN_RSTAT_VMRD_MASK I40E_MASK(0x1, I40E_VSIGEN_RSTAT_VMRD_SHIFT) #define I40E_VSIGEN_RTRIG(_VSI) (0x00090000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_VSIGEN_RTRIG_MAX_INDEX 383 #define I40E_VSIGEN_RTRIG_VMSWR_SHIFT 0 #define I40E_VSIGEN_RTRIG_VMSWR_MASK I40E_MASK(0x1, I40E_VSIGEN_RTRIG_VMSWR_SHIFT) #define I40E_GLHMC_FCOEDDPBASE(_i) (0x000C6600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FCOEDDPBASE_MAX_INDEX 15 #define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT 0 #define I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_SHIFT) #define I40E_GLHMC_FCOEDDPCNT(_i) (0x000C6700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FCOEDDPCNT_MAX_INDEX 15 #define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT 0 #define I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_MASK I40E_MASK(0xFFFFF, I40E_GLHMC_FCOEDDPCNT_FPMFCOEDDPCNT_SHIFT) #define I40E_GLHMC_FCOEDDPOBJSZ 0x000C2010 /* Reset: CORER */ #define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT 0 #define I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEDDPOBJSZ_PMFCOEDDPOBJSZ_SHIFT) #define I40E_GLHMC_FCOEFBASE(_i) (0x000C6800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FCOEFBASE_MAX_INDEX 15 #define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT 0 #define I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_SHIFT) #define I40E_GLHMC_FCOEFCNT(_i) (0x000C6900 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FCOEFCNT_MAX_INDEX 15 #define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT 0 #define I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_MASK I40E_MASK(0x7FFFFF, I40E_GLHMC_FCOEFCNT_FPMFCOEFCNT_SHIFT) #define I40E_GLHMC_FCOEFMAX 0x000C20D0 /* Reset: CORER */ #define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT 0 #define I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_MASK I40E_MASK(0xFFFF, I40E_GLHMC_FCOEFMAX_PMFCOEFMAX_SHIFT) #define I40E_GLHMC_FCOEFOBJSZ 0x000C2018 /* Reset: CORER */ #define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT 0 #define I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FCOEFOBJSZ_PMFCOEFOBJSZ_SHIFT) #define I40E_GLHMC_FCOEMAX 0x000C2014 /* Reset: CORER */ #define I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT 0 #define I40E_GLHMC_FCOEMAX_PMFCOEMAX_MASK I40E_MASK(0x1FFF, I40E_GLHMC_FCOEMAX_PMFCOEMAX_SHIFT) #define I40E_GLHMC_FSIAVBASE(_i) (0x000C5600 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FSIAVBASE_MAX_INDEX 15 #define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT 0 #define I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIAVBASE_FPMFSIAVBASE_SHIFT) #define I40E_GLHMC_FSIAVCNT(_i) (0x000C5700 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FSIAVCNT_MAX_INDEX 15 #define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT 0 #define I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIAVCNT_FPMFSIAVCNT_SHIFT) #define I40E_GLHMC_FSIAVCNT_RSVD_SHIFT 29 #define I40E_GLHMC_FSIAVCNT_RSVD_MASK I40E_MASK(0x7, I40E_GLHMC_FSIAVCNT_RSVD_SHIFT) #define I40E_GLHMC_FSIAVMAX 0x000C2068 /* Reset: CORER */ #define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT 0 #define I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_MASK I40E_MASK(0x1FFFF, I40E_GLHMC_FSIAVMAX_PMFSIAVMAX_SHIFT) #define I40E_GLHMC_FSIAVOBJSZ 0x000C2064 /* Reset: CORER */ #define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT 0 #define I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIAVOBJSZ_PMFSIAVOBJSZ_SHIFT) #define I40E_GLHMC_FSIMCBASE(_i) (0x000C6000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FSIMCBASE_MAX_INDEX 15 #define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT 0 #define I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_FSIMCBASE_FPMFSIMCBASE_SHIFT) #define I40E_GLHMC_FSIMCCNT(_i) (0x000C6100 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_FSIMCCNT_MAX_INDEX 15 #define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT 0 #define I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_MASK I40E_MASK(0x1FFFFFFF, I40E_GLHMC_FSIMCCNT_FPMFSIMCSZ_SHIFT) #define I40E_GLHMC_FSIMCMAX 0x000C2060 /* Reset: CORER */ #define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT 0 #define I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_MASK I40E_MASK(0x3FFF, I40E_GLHMC_FSIMCMAX_PMFSIMCMAX_SHIFT) #define I40E_GLHMC_FSIMCOBJSZ 0x000C205c /* Reset: CORER */ #define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT 0 #define I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_FSIMCOBJSZ_PMFSIMCOBJSZ_SHIFT) #define I40E_GLHMC_LANQMAX 0x000C2008 /* Reset: CORER */ #define I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT 0 #define I40E_GLHMC_LANQMAX_PMLANQMAX_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANQMAX_PMLANQMAX_SHIFT) #define I40E_GLHMC_LANRXBASE(_i) (0x000C6400 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_LANRXBASE_MAX_INDEX 15 #define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT 0 #define I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANRXBASE_FPMLANRXBASE_SHIFT) #define I40E_GLHMC_LANRXCNT(_i) (0x000C6500 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_LANRXCNT_MAX_INDEX 15 #define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT 0 #define I40E_GLHMC_LANRXCNT_FPMLANRXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANRXCNT_FPMLANRXCNT_SHIFT) #define I40E_GLHMC_LANRXOBJSZ 0x000C200c /* Reset: CORER */ #define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT 0 #define I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANRXOBJSZ_PMLANRXOBJSZ_SHIFT) #define I40E_GLHMC_LANTXBASE(_i) (0x000C6200 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_LANTXBASE_MAX_INDEX 15 #define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT 0 #define I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK I40E_MASK(0xFFFFFF, I40E_GLHMC_LANTXBASE_FPMLANTXBASE_SHIFT) #define I40E_GLHMC_LANTXBASE_RSVD_SHIFT 24 #define I40E_GLHMC_LANTXBASE_RSVD_MASK I40E_MASK(0xFF, I40E_GLHMC_LANTXBASE_RSVD_SHIFT) #define I40E_GLHMC_LANTXCNT(_i) (0x000C6300 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_LANTXCNT_MAX_INDEX 15 #define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT 0 #define I40E_GLHMC_LANTXCNT_FPMLANTXCNT_MASK I40E_MASK(0x7FF, I40E_GLHMC_LANTXCNT_FPMLANTXCNT_SHIFT) #define I40E_GLHMC_LANTXOBJSZ 0x000C2004 /* Reset: CORER */ #define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT 0 #define I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_MASK I40E_MASK(0xF, I40E_GLHMC_LANTXOBJSZ_PMLANTXOBJSZ_SHIFT) #define I40E_GLHMC_PFASSIGN(_i) (0x000C0c00 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_PFASSIGN_MAX_INDEX 15 #define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT 0 #define I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_MASK I40E_MASK(0xF, I40E_GLHMC_PFASSIGN_PMFCNPFASSIGN_SHIFT) #define I40E_GLHMC_SDPART(_i) (0x000C0800 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLHMC_SDPART_MAX_INDEX 15 #define I40E_GLHMC_SDPART_PMSDBASE_SHIFT 0 #define I40E_GLHMC_SDPART_PMSDBASE_MASK I40E_MASK(0xFFF, I40E_GLHMC_SDPART_PMSDBASE_SHIFT) #define I40E_GLHMC_SDPART_PMSDSIZE_SHIFT 16 #define I40E_GLHMC_SDPART_PMSDSIZE_MASK I40E_MASK(0x1FFF, I40E_GLHMC_SDPART_PMSDSIZE_SHIFT) #define I40E_PFHMC_ERRORDATA 0x000C0500 /* Reset: PFR */ #define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT 0 #define I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_MASK I40E_MASK(0x3FFFFFFF, I40E_PFHMC_ERRORDATA_HMC_ERROR_DATA_SHIFT) #define I40E_PFHMC_ERRORINFO 0x000C0400 /* Reset: PFR */ #define I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT 0 #define I40E_PFHMC_ERRORINFO_PMF_INDEX_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_PMF_INDEX_SHIFT) #define I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT 7 #define I40E_PFHMC_ERRORINFO_PMF_ISVF_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_PMF_ISVF_SHIFT) #define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT 8 #define I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_MASK I40E_MASK(0xF, I40E_PFHMC_ERRORINFO_HMC_ERROR_TYPE_SHIFT) #define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT 16 #define I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_MASK I40E_MASK(0x1F, I40E_PFHMC_ERRORINFO_HMC_OBJECT_TYPE_SHIFT) #define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT 31 #define I40E_PFHMC_ERRORINFO_ERROR_DETECTED_MASK I40E_MASK(0x1, I40E_PFHMC_ERRORINFO_ERROR_DETECTED_SHIFT) #define I40E_PFHMC_PDINV 0x000C0300 /* Reset: PFR */ #define I40E_PFHMC_PDINV_PMSDIDX_SHIFT 0 #define I40E_PFHMC_PDINV_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_PDINV_PMSDIDX_SHIFT) #define I40E_PFHMC_PDINV_PMPDIDX_SHIFT 16 #define I40E_PFHMC_PDINV_PMPDIDX_MASK I40E_MASK(0x1FF, I40E_PFHMC_PDINV_PMPDIDX_SHIFT) #define I40E_PFHMC_SDCMD 0x000C0000 /* Reset: PFR */ #define I40E_PFHMC_SDCMD_PMSDIDX_SHIFT 0 #define I40E_PFHMC_SDCMD_PMSDIDX_MASK I40E_MASK(0xFFF, I40E_PFHMC_SDCMD_PMSDIDX_SHIFT) #define I40E_PFHMC_SDCMD_PMSDWR_SHIFT 31 #define I40E_PFHMC_SDCMD_PMSDWR_MASK I40E_MASK(0x1, I40E_PFHMC_SDCMD_PMSDWR_SHIFT) #define I40E_PFHMC_SDDATAHIGH 0x000C0200 /* Reset: PFR */ #define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT 0 #define I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_MASK I40E_MASK(0xFFFFFFFF, I40E_PFHMC_SDDATAHIGH_PMSDDATAHIGH_SHIFT) #define I40E_PFHMC_SDDATALOW 0x000C0100 /* Reset: PFR */ #define I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT 0 #define I40E_PFHMC_SDDATALOW_PMSDVALID_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT) #define I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT 1 #define I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK I40E_MASK(0x1, I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) #define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT 2 #define I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK I40E_MASK(0x3FF, I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) #define I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT 12 #define I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK I40E_MASK(0xFFFFF, I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT) #define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */ /* Reset: POR */ #define I40E_GL_GP_FUSE_MAX_INDEX 28 #define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0 #define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT) #define I40E_GL_UFUSE 0x00094008 /* Reset: POR */ #define I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT 1 #define I40E_GL_UFUSE_FOUR_PORT_ENABLE_MASK I40E_MASK(0x1, I40E_GL_UFUSE_FOUR_PORT_ENABLE_SHIFT) #define I40E_GL_UFUSE_NIC_ID_SHIFT 2 #define I40E_GL_UFUSE_NIC_ID_MASK I40E_MASK(0x1, I40E_GL_UFUSE_NIC_ID_SHIFT) #define I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT 10 #define I40E_GL_UFUSE_ULT_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_ULT_LOCKOUT_SHIFT) #define I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT 11 #define I40E_GL_UFUSE_CLS_LOCKOUT_MASK I40E_MASK(0x1, I40E_GL_UFUSE_CLS_LOCKOUT_SHIFT) #define I40E_EMPINT_GPIO_ENA 0x00088188 /* Reset: POR */ #define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT 0 #define I40E_EMPINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO0_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT 1 #define I40E_EMPINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO1_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT 2 #define I40E_EMPINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO2_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT 3 #define I40E_EMPINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO3_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT 4 #define I40E_EMPINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO4_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT 5 #define I40E_EMPINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO5_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT 6 #define I40E_EMPINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO6_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT 7 #define I40E_EMPINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO7_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT 8 #define I40E_EMPINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO8_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT 9 #define I40E_EMPINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO9_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT 10 #define I40E_EMPINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO10_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT 11 #define I40E_EMPINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO11_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT 12 #define I40E_EMPINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO12_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT 13 #define I40E_EMPINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO13_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT 14 #define I40E_EMPINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO14_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT 15 #define I40E_EMPINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO15_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT 16 #define I40E_EMPINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO16_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT 17 #define I40E_EMPINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO17_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT 18 #define I40E_EMPINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO18_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT 19 #define I40E_EMPINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO19_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT 20 #define I40E_EMPINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO20_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT 21 #define I40E_EMPINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO21_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT 22 #define I40E_EMPINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO22_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT 23 #define I40E_EMPINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO23_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT 24 #define I40E_EMPINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO24_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT 25 #define I40E_EMPINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO25_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT 26 #define I40E_EMPINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO26_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT 27 #define I40E_EMPINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO27_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT 28 #define I40E_EMPINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO28_ENA_SHIFT) #define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT 29 #define I40E_EMPINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_EMPINT_GPIO_ENA_GPIO29_ENA_SHIFT) #define I40E_PFGEN_PORTMDIO_NUM 0x0003F100 /* Reset: CORER */ #define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT 0 #define I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_MASK I40E_MASK(0x3, I40E_PFGEN_PORTMDIO_NUM_PORT_NUM_SHIFT) #define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT 4 #define I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK I40E_MASK(0x1, I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_SHIFT) #define I40E_PFINT_AEQCTL 0x00038700 /* Reset: CORER */ #define I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT 0 #define I40E_PFINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT) #define I40E_PFINT_AEQCTL_ITR_INDX_SHIFT 11 #define I40E_PFINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_AEQCTL_ITR_INDX_SHIFT) #define I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT 13 #define I40E_PFINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_AEQCTL_MSIX0_INDX_SHIFT) #define I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT 30 #define I40E_PFINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_CAUSE_ENA_SHIFT) #define I40E_PFINT_AEQCTL_INTEVENT_SHIFT 31 #define I40E_PFINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_AEQCTL_INTEVENT_SHIFT) #define I40E_PFINT_CEQCTL(_INTPF) (0x00036800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: CORER */ #define I40E_PFINT_CEQCTL_MAX_INDEX 511 #define I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT 0 #define I40E_PFINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT) #define I40E_PFINT_CEQCTL_ITR_INDX_SHIFT 11 #define I40E_PFINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_ITR_INDX_SHIFT) #define I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT 13 #define I40E_PFINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_PFINT_CEQCTL_MSIX0_INDX_SHIFT) #define I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT 16 #define I40E_PFINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT) #define I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT 27 #define I40E_PFINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_CEQCTL_NEXTQ_TYPE_SHIFT) #define I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT 30 #define I40E_PFINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_CAUSE_ENA_SHIFT) #define I40E_PFINT_CEQCTL_INTEVENT_SHIFT 31 #define I40E_PFINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_CEQCTL_INTEVENT_SHIFT) #define I40E_PFINT_DYN_CTL0 0x00038480 /* Reset: PFR */ #define I40E_PFINT_DYN_CTL0_INTENA_SHIFT 0 #define I40E_PFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_SHIFT) #define I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT 1 #define I40E_PFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_CLEARPBA_SHIFT) #define I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2 #define I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SWINT_TRIG_SHIFT) #define I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT 3 #define I40E_PFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT) #define I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT 5 #define I40E_PFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTL0_INTERVAL_SHIFT) #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT) #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25 #define I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_SHIFT) #define I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT 31 #define I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTL0_INTENA_MSK_SHIFT) #define I40E_PFINT_DYN_CTLN(_INTPF) (0x00034800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */ #define I40E_PFINT_DYN_CTLN_MAX_INDEX 511 #define I40E_PFINT_DYN_CTLN_INTENA_SHIFT 0 #define I40E_PFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_SHIFT) #define I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT 1 #define I40E_PFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_CLEARPBA_SHIFT) #define I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2 #define I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SWINT_TRIG_SHIFT) #define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3 #define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) #define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5 #define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT) #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT) #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25 #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT) #define I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT 31 #define I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_INTENA_MSK_SHIFT) #define I40E_PFINT_GPIO_ENA 0x00088080 /* Reset: CORER */ #define I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT 0 #define I40E_PFINT_GPIO_ENA_GPIO0_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO0_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT 1 #define I40E_PFINT_GPIO_ENA_GPIO1_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO1_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT 2 #define I40E_PFINT_GPIO_ENA_GPIO2_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO2_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT 3 #define I40E_PFINT_GPIO_ENA_GPIO3_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO3_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT 4 #define I40E_PFINT_GPIO_ENA_GPIO4_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO4_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT 5 #define I40E_PFINT_GPIO_ENA_GPIO5_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO5_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT 6 #define I40E_PFINT_GPIO_ENA_GPIO6_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO6_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT 7 #define I40E_PFINT_GPIO_ENA_GPIO7_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO7_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT 8 #define I40E_PFINT_GPIO_ENA_GPIO8_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO8_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT 9 #define I40E_PFINT_GPIO_ENA_GPIO9_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO9_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT 10 #define I40E_PFINT_GPIO_ENA_GPIO10_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO10_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT 11 #define I40E_PFINT_GPIO_ENA_GPIO11_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO11_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT 12 #define I40E_PFINT_GPIO_ENA_GPIO12_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO12_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT 13 #define I40E_PFINT_GPIO_ENA_GPIO13_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO13_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT 14 #define I40E_PFINT_GPIO_ENA_GPIO14_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO14_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT 15 #define I40E_PFINT_GPIO_ENA_GPIO15_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO15_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT 16 #define I40E_PFINT_GPIO_ENA_GPIO16_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO16_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT 17 #define I40E_PFINT_GPIO_ENA_GPIO17_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO17_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT 18 #define I40E_PFINT_GPIO_ENA_GPIO18_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO18_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT 19 #define I40E_PFINT_GPIO_ENA_GPIO19_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO19_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT 20 #define I40E_PFINT_GPIO_ENA_GPIO20_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO20_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT 21 #define I40E_PFINT_GPIO_ENA_GPIO21_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO21_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT 22 #define I40E_PFINT_GPIO_ENA_GPIO22_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO22_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT 23 #define I40E_PFINT_GPIO_ENA_GPIO23_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO23_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT 24 #define I40E_PFINT_GPIO_ENA_GPIO24_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO24_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT 25 #define I40E_PFINT_GPIO_ENA_GPIO25_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO25_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT 26 #define I40E_PFINT_GPIO_ENA_GPIO26_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO26_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT 27 #define I40E_PFINT_GPIO_ENA_GPIO27_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO27_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT 28 #define I40E_PFINT_GPIO_ENA_GPIO28_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO28_ENA_SHIFT) #define I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT 29 #define I40E_PFINT_GPIO_ENA_GPIO29_ENA_MASK I40E_MASK(0x1, I40E_PFINT_GPIO_ENA_GPIO29_ENA_SHIFT) #define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */ #define I40E_PFINT_ICR0_INTEVENT_SHIFT 0 #define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT) #define I40E_PFINT_ICR0_QUEUE_0_SHIFT 1 #define I40E_PFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_0_SHIFT) #define I40E_PFINT_ICR0_QUEUE_1_SHIFT 2 #define I40E_PFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_1_SHIFT) #define I40E_PFINT_ICR0_QUEUE_2_SHIFT 3 #define I40E_PFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_2_SHIFT) #define I40E_PFINT_ICR0_QUEUE_3_SHIFT 4 #define I40E_PFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_3_SHIFT) #define I40E_PFINT_ICR0_QUEUE_4_SHIFT 5 #define I40E_PFINT_ICR0_QUEUE_4_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_4_SHIFT) #define I40E_PFINT_ICR0_QUEUE_5_SHIFT 6 #define I40E_PFINT_ICR0_QUEUE_5_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_5_SHIFT) #define I40E_PFINT_ICR0_QUEUE_6_SHIFT 7 #define I40E_PFINT_ICR0_QUEUE_6_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_6_SHIFT) #define I40E_PFINT_ICR0_QUEUE_7_SHIFT 8 #define I40E_PFINT_ICR0_QUEUE_7_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_QUEUE_7_SHIFT) #define I40E_PFINT_ICR0_ECC_ERR_SHIFT 16 #define I40E_PFINT_ICR0_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ECC_ERR_SHIFT) #define I40E_PFINT_ICR0_MAL_DETECT_SHIFT 19 #define I40E_PFINT_ICR0_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_MAL_DETECT_SHIFT) #define I40E_PFINT_ICR0_GRST_SHIFT 20 #define I40E_PFINT_ICR0_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GRST_SHIFT) #define I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT 21 #define I40E_PFINT_ICR0_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PCI_EXCEPTION_SHIFT) #define I40E_PFINT_ICR0_GPIO_SHIFT 22 #define I40E_PFINT_ICR0_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_GPIO_SHIFT) #define I40E_PFINT_ICR0_TIMESYNC_SHIFT 23 #define I40E_PFINT_ICR0_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_TIMESYNC_SHIFT) #define I40E_PFINT_ICR0_STORM_DETECT_SHIFT 24 #define I40E_PFINT_ICR0_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_STORM_DETECT_SHIFT) #define I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25 #define I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_LINK_STAT_CHANGE_SHIFT) #define I40E_PFINT_ICR0_HMC_ERR_SHIFT 26 #define I40E_PFINT_ICR0_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_HMC_ERR_SHIFT) #define I40E_PFINT_ICR0_PE_CRITERR_SHIFT 28 #define I40E_PFINT_ICR0_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_PE_CRITERR_SHIFT) #define I40E_PFINT_ICR0_VFLR_SHIFT 29 #define I40E_PFINT_ICR0_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_VFLR_SHIFT) #define I40E_PFINT_ICR0_ADMINQ_SHIFT 30 #define I40E_PFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ADMINQ_SHIFT) #define I40E_PFINT_ICR0_SWINT_SHIFT 31 #define I40E_PFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_SWINT_SHIFT) #define I40E_PFINT_ICR0_ENA 0x00038800 /* Reset: CORER */ #define I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT 16 #define I40E_PFINT_ICR0_ENA_ECC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ECC_ERR_SHIFT) #define I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT 19 #define I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_MAL_DETECT_SHIFT) #define I40E_PFINT_ICR0_ENA_GRST_SHIFT 20 #define I40E_PFINT_ICR0_ENA_GRST_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GRST_SHIFT) #define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT 21 #define I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_SHIFT) #define I40E_PFINT_ICR0_ENA_GPIO_SHIFT 22 #define I40E_PFINT_ICR0_ENA_GPIO_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_GPIO_SHIFT) #define I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT 23 #define I40E_PFINT_ICR0_ENA_TIMESYNC_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_TIMESYNC_SHIFT) #define I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT 24 #define I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_STORM_DETECT_SHIFT) #define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25 #define I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT) #define I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT 26 #define I40E_PFINT_ICR0_ENA_HMC_ERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_HMC_ERR_SHIFT) #define I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT 28 #define I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_PE_CRITERR_SHIFT) #define I40E_PFINT_ICR0_ENA_VFLR_SHIFT 29 #define I40E_PFINT_ICR0_ENA_VFLR_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_VFLR_SHIFT) #define I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT 30 #define I40E_PFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_ADMINQ_SHIFT) #define I40E_PFINT_ICR0_ENA_RSVD_SHIFT 31 #define I40E_PFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_ENA_RSVD_SHIFT) #define I40E_PFINT_ITR0(_i) (0x00038000 + ((_i) * 128)) /* _i=0...2 */ /* Reset: PFR */ #define I40E_PFINT_ITR0_MAX_INDEX 2 #define I40E_PFINT_ITR0_INTERVAL_SHIFT 0 #define I40E_PFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITR0_INTERVAL_SHIFT) #define I40E_PFINT_ITRN(_i, _INTPF) (0x00030000 + ((_i) * 2048 + (_INTPF) * 4)) /* _i=0...2, _INTPF=0...511 */ /* Reset: PFR */ #define I40E_PFINT_ITRN_MAX_INDEX 2 #define I40E_PFINT_ITRN_INTERVAL_SHIFT 0 #define I40E_PFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_ITRN_INTERVAL_SHIFT) #define I40E_PFINT_LNKLST0 0x00038500 /* Reset: PFR */ #define I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT 0 #define I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLST0_FIRSTQ_INDX_SHIFT) #define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11 #define I40E_PFINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLST0_FIRSTQ_TYPE_SHIFT) #define I40E_PFINT_LNKLSTN(_INTPF) (0x00035000 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */ #define I40E_PFINT_LNKLSTN_MAX_INDEX 511 #define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0 #define I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) #define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11 #define I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT) #define I40E_PFINT_RATE0 0x00038580 /* Reset: PFR */ #define I40E_PFINT_RATE0_INTERVAL_SHIFT 0 #define I40E_PFINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATE0_INTERVAL_SHIFT) #define I40E_PFINT_RATE0_INTRL_ENA_SHIFT 6 #define I40E_PFINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATE0_INTRL_ENA_SHIFT) #define I40E_PFINT_RATEN(_INTPF) (0x00035800 + ((_INTPF) * 4)) /* _i=0...511 */ /* Reset: PFR */ #define I40E_PFINT_RATEN_MAX_INDEX 511 #define I40E_PFINT_RATEN_INTERVAL_SHIFT 0 #define I40E_PFINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_PFINT_RATEN_INTERVAL_SHIFT) #define I40E_PFINT_RATEN_INTRL_ENA_SHIFT 6 #define I40E_PFINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_PFINT_RATEN_INTRL_ENA_SHIFT) #define I40E_PFINT_STAT_CTL0 0x00038400 /* Reset: CORER */ #define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2 #define I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT) #define I40E_QINT_RQCTL(_Q) (0x0003A000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */ #define I40E_QINT_RQCTL_MAX_INDEX 1535 #define I40E_QINT_RQCTL_MSIX_INDX_SHIFT 0 #define I40E_QINT_RQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_RQCTL_MSIX_INDX_SHIFT) #define I40E_QINT_RQCTL_ITR_INDX_SHIFT 11 #define I40E_QINT_RQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_ITR_INDX_SHIFT) #define I40E_QINT_RQCTL_MSIX0_INDX_SHIFT 13 #define I40E_QINT_RQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_RQCTL_MSIX0_INDX_SHIFT) #define I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT 16 #define I40E_QINT_RQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) #define I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT 27 #define I40E_QINT_RQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) #define I40E_QINT_RQCTL_CAUSE_ENA_SHIFT 30 #define I40E_QINT_RQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) #define I40E_QINT_RQCTL_INTEVENT_SHIFT 31 #define I40E_QINT_RQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_RQCTL_INTEVENT_SHIFT) #define I40E_QINT_TQCTL(_Q) (0x0003C000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */ #define I40E_QINT_TQCTL_MAX_INDEX 1535 #define I40E_QINT_TQCTL_MSIX_INDX_SHIFT 0 #define I40E_QINT_TQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_QINT_TQCTL_MSIX_INDX_SHIFT) #define I40E_QINT_TQCTL_ITR_INDX_SHIFT 11 #define I40E_QINT_TQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_ITR_INDX_SHIFT) #define I40E_QINT_TQCTL_MSIX0_INDX_SHIFT 13 #define I40E_QINT_TQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_QINT_TQCTL_MSIX0_INDX_SHIFT) #define I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT 16 #define I40E_QINT_TQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_QINT_TQCTL_NEXTQ_INDX_SHIFT) #define I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT 27 #define I40E_QINT_TQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT) #define I40E_QINT_TQCTL_CAUSE_ENA_SHIFT 30 #define I40E_QINT_TQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_CAUSE_ENA_SHIFT) #define I40E_QINT_TQCTL_INTEVENT_SHIFT 31 #define I40E_QINT_TQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_QINT_TQCTL_INTEVENT_SHIFT) #define I40E_VFINT_DYN_CTL0(_VF) (0x0002A400 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VFINT_DYN_CTL0_MAX_INDEX 127 #define I40E_VFINT_DYN_CTL0_INTENA_SHIFT 0 #define I40E_VFINT_DYN_CTL0_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_SHIFT) #define I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT 1 #define I40E_VFINT_DYN_CTL0_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_CLEARPBA_SHIFT) #define I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT 2 #define I40E_VFINT_DYN_CTL0_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SWINT_TRIG_SHIFT) #define I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT 3 #define I40E_VFINT_DYN_CTL0_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT 5 #define I40E_VFINT_DYN_CTL0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT) #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_ENA_SHIFT) #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT 25 #define I40E_VFINT_DYN_CTL0_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL0_SW_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT 31 #define I40E_VFINT_DYN_CTL0_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL0_INTENA_MSK_SHIFT) #define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */ #define I40E_VFINT_DYN_CTLN_MAX_INDEX 511 #define I40E_VFINT_DYN_CTLN_INTENA_SHIFT 0 #define I40E_VFINT_DYN_CTLN_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_SHIFT) #define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1 #define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT) #define I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT 2 #define I40E_VFINT_DYN_CTLN_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SWINT_TRIG_SHIFT) #define I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT 3 #define I40E_VFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT 5 #define I40E_VFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN_INTERVAL_SHIFT) #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT) #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25 #define I40E_VFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN_SW_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT 31 #define I40E_VFINT_DYN_CTLN_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_INTENA_MSK_SHIFT) #define I40E_VFINT_ICR0(_VF) (0x0002BC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VFINT_ICR0_MAX_INDEX 127 #define I40E_VFINT_ICR0_INTEVENT_SHIFT 0 #define I40E_VFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_INTEVENT_SHIFT) #define I40E_VFINT_ICR0_QUEUE_0_SHIFT 1 #define I40E_VFINT_ICR0_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_0_SHIFT) #define I40E_VFINT_ICR0_QUEUE_1_SHIFT 2 #define I40E_VFINT_ICR0_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_1_SHIFT) #define I40E_VFINT_ICR0_QUEUE_2_SHIFT 3 #define I40E_VFINT_ICR0_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_2_SHIFT) #define I40E_VFINT_ICR0_QUEUE_3_SHIFT 4 #define I40E_VFINT_ICR0_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_QUEUE_3_SHIFT) #define I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT 25 #define I40E_VFINT_ICR0_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_LINK_STAT_CHANGE_SHIFT) #define I40E_VFINT_ICR0_ADMINQ_SHIFT 30 #define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT) #define I40E_VFINT_ICR0_SWINT_SHIFT 31 #define I40E_VFINT_ICR0_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_SWINT_SHIFT) #define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VFINT_ICR0_ENA_MAX_INDEX 127 #define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT 25 #define I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_LINK_STAT_CHANGE_SHIFT) #define I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT 30 #define I40E_VFINT_ICR0_ENA_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_ADMINQ_SHIFT) #define I40E_VFINT_ICR0_ENA_RSVD_SHIFT 31 #define I40E_VFINT_ICR0_ENA_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA_RSVD_SHIFT) #define I40E_VFINT_ITR0(_i, _VF) (0x00028000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...2, _VF=0...127 */ /* Reset: VFR */ #define I40E_VFINT_ITR0_MAX_INDEX 2 #define I40E_VFINT_ITR0_INTERVAL_SHIFT 0 #define I40E_VFINT_ITR0_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR0_INTERVAL_SHIFT) #define I40E_VFINT_ITRN(_i, _INTVF) (0x00020000 + ((_i) * 2048 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...511 */ /* Reset: VFR */ #define I40E_VFINT_ITRN_MAX_INDEX 2 #define I40E_VFINT_ITRN_INTERVAL_SHIFT 0 #define I40E_VFINT_ITRN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN_INTERVAL_SHIFT) #define I40E_VFINT_STAT_CTL0(_VF) (0x0002A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VFINT_STAT_CTL0_MAX_INDEX 127 #define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT 2 #define I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL0_OTHER_ITR_INDX_SHIFT) #define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VPINT_AEQCTL_MAX_INDEX 127 #define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0 #define I40E_VPINT_AEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT) #define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11 #define I40E_VPINT_AEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_AEQCTL_ITR_INDX_SHIFT) #define I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT 13 #define I40E_VPINT_AEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_AEQCTL_MSIX0_INDX_SHIFT) #define I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT 30 #define I40E_VPINT_AEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_CAUSE_ENA_SHIFT) #define I40E_VPINT_AEQCTL_INTEVENT_SHIFT 31 #define I40E_VPINT_AEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_AEQCTL_INTEVENT_SHIFT) #define I40E_VPINT_CEQCTL(_INTVF) (0x00026800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: CORER */ #define I40E_VPINT_CEQCTL_MAX_INDEX 511 #define I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT 0 #define I40E_VPINT_CEQCTL_MSIX_INDX_MASK I40E_MASK(0xFF, I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT) #define I40E_VPINT_CEQCTL_ITR_INDX_SHIFT 11 #define I40E_VPINT_CEQCTL_ITR_INDX_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_ITR_INDX_SHIFT) #define I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT 13 #define I40E_VPINT_CEQCTL_MSIX0_INDX_MASK I40E_MASK(0x7, I40E_VPINT_CEQCTL_MSIX0_INDX_SHIFT) #define I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT 16 #define I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT) #define I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT 27 #define I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT) #define I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT 30 #define I40E_VPINT_CEQCTL_CAUSE_ENA_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_CAUSE_ENA_SHIFT) #define I40E_VPINT_CEQCTL_INTEVENT_SHIFT 31 #define I40E_VPINT_CEQCTL_INTEVENT_MASK I40E_MASK(0x1, I40E_VPINT_CEQCTL_INTEVENT_SHIFT) #define I40E_VPINT_LNKLST0(_VF) (0x0002A800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VPINT_LNKLST0_MAX_INDEX 127 #define I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT 0 #define I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLST0_FIRSTQ_INDX_SHIFT) #define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT 11 #define I40E_VPINT_LNKLST0_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLST0_FIRSTQ_TYPE_SHIFT) #define I40E_VPINT_LNKLSTN(_INTVF) (0x00025000 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */ #define I40E_VPINT_LNKLSTN_MAX_INDEX 511 #define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT 0 #define I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK I40E_MASK(0x7FF, I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) #define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT 11 #define I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK I40E_MASK(0x3, I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT) #define I40E_VPINT_RATE0(_VF) (0x0002AC00 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VPINT_RATE0_MAX_INDEX 127 #define I40E_VPINT_RATE0_INTERVAL_SHIFT 0 #define I40E_VPINT_RATE0_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATE0_INTERVAL_SHIFT) #define I40E_VPINT_RATE0_INTRL_ENA_SHIFT 6 #define I40E_VPINT_RATE0_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATE0_INTRL_ENA_SHIFT) #define I40E_VPINT_RATEN(_INTVF) (0x00025800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */ #define I40E_VPINT_RATEN_MAX_INDEX 511 #define I40E_VPINT_RATEN_INTERVAL_SHIFT 0 #define I40E_VPINT_RATEN_INTERVAL_MASK I40E_MASK(0x3F, I40E_VPINT_RATEN_INTERVAL_SHIFT) #define I40E_VPINT_RATEN_INTRL_ENA_SHIFT 6 #define I40E_VPINT_RATEN_INTRL_ENA_MASK I40E_MASK(0x1, I40E_VPINT_RATEN_INTRL_ENA_SHIFT) #define I40E_GL_RDPU_CNTRL 0x00051060 /* Reset: CORER */ #define I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT 0 #define I40E_GL_RDPU_CNTRL_RX_PAD_EN_MASK I40E_MASK(0x1, I40E_GL_RDPU_CNTRL_RX_PAD_EN_SHIFT) #define I40E_GL_RDPU_CNTRL_ECO_SHIFT 1 #define I40E_GL_RDPU_CNTRL_ECO_MASK I40E_MASK(0x7FFFFFFF, I40E_GL_RDPU_CNTRL_ECO_SHIFT) #define I40E_GLLAN_RCTL_0 0x0012A500 /* Reset: CORER */ #define I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT 0 #define I40E_GLLAN_RCTL_0_PXE_MODE_MASK I40E_MASK(0x1, I40E_GLLAN_RCTL_0_PXE_MODE_SHIFT) #define I40E_GLLAN_TSOMSK_F 0x000442D8 /* Reset: CORER */ #define I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT 0 #define I40E_GLLAN_TSOMSK_F_TCPMSKF_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_F_TCPMSKF_SHIFT) #define I40E_GLLAN_TSOMSK_L 0x000442E0 /* Reset: CORER */ #define I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT 0 #define I40E_GLLAN_TSOMSK_L_TCPMSKL_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_L_TCPMSKL_SHIFT) #define I40E_GLLAN_TSOMSK_M 0x000442DC /* Reset: CORER */ #define I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT 0 #define I40E_GLLAN_TSOMSK_M_TCPMSKM_MASK I40E_MASK(0xFFF, I40E_GLLAN_TSOMSK_M_TCPMSKM_SHIFT) #define I40E_GLLAN_TXPRE_QDIS(_i) (0x000e6500 + ((_i) * 4)) /* _i=0...11 */ /* Reset: CORER */ #define I40E_GLLAN_TXPRE_QDIS_MAX_INDEX 11 #define I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT 0 #define I40E_GLLAN_TXPRE_QDIS_QINDX_MASK I40E_MASK(0x7FF, I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT) #define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT 16 #define I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_QDIS_STAT_SHIFT) #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT 30 #define I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_SET_QDIS_SHIFT) #define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT 31 #define I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK I40E_MASK(0x1, I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_SHIFT) #define I40E_PFLAN_QALLOC 0x001C0400 /* Reset: CORER */ #define I40E_PFLAN_QALLOC_FIRSTQ_SHIFT 0 #define I40E_PFLAN_QALLOC_FIRSTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_FIRSTQ_SHIFT) #define I40E_PFLAN_QALLOC_LASTQ_SHIFT 16 #define I40E_PFLAN_QALLOC_LASTQ_MASK I40E_MASK(0x7FF, I40E_PFLAN_QALLOC_LASTQ_SHIFT) #define I40E_PFLAN_QALLOC_VALID_SHIFT 31 #define I40E_PFLAN_QALLOC_VALID_MASK I40E_MASK(0x1, I40E_PFLAN_QALLOC_VALID_SHIFT) #define I40E_QRX_ENA(_Q) (0x00120000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */ #define I40E_QRX_ENA_MAX_INDEX 1535 #define I40E_QRX_ENA_QENA_REQ_SHIFT 0 #define I40E_QRX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_REQ_SHIFT) #define I40E_QRX_ENA_FAST_QDIS_SHIFT 1 #define I40E_QRX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QRX_ENA_FAST_QDIS_SHIFT) #define I40E_QRX_ENA_QENA_STAT_SHIFT 2 #define I40E_QRX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QRX_ENA_QENA_STAT_SHIFT) #define I40E_QRX_TAIL(_Q) (0x00128000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */ #define I40E_QRX_TAIL_MAX_INDEX 1535 #define I40E_QRX_TAIL_TAIL_SHIFT 0 #define I40E_QRX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL_TAIL_SHIFT) #define I40E_QTX_CTL(_Q) (0x00104000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */ #define I40E_QTX_CTL_MAX_INDEX 1535 #define I40E_QTX_CTL_PFVF_Q_SHIFT 0 #define I40E_QTX_CTL_PFVF_Q_MASK I40E_MASK(0x3, I40E_QTX_CTL_PFVF_Q_SHIFT) #define I40E_QTX_CTL_PF_INDX_SHIFT 2 #define I40E_QTX_CTL_PF_INDX_MASK I40E_MASK(0xF, I40E_QTX_CTL_PF_INDX_SHIFT) #define I40E_QTX_CTL_VFVM_INDX_SHIFT 7 #define I40E_QTX_CTL_VFVM_INDX_MASK I40E_MASK(0x1FF, I40E_QTX_CTL_VFVM_INDX_SHIFT) #define I40E_QTX_ENA(_Q) (0x00100000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */ #define I40E_QTX_ENA_MAX_INDEX 1535 #define I40E_QTX_ENA_QENA_REQ_SHIFT 0 #define I40E_QTX_ENA_QENA_REQ_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_REQ_SHIFT) #define I40E_QTX_ENA_FAST_QDIS_SHIFT 1 #define I40E_QTX_ENA_FAST_QDIS_MASK I40E_MASK(0x1, I40E_QTX_ENA_FAST_QDIS_SHIFT) #define I40E_QTX_ENA_QENA_STAT_SHIFT 2 #define I40E_QTX_ENA_QENA_STAT_MASK I40E_MASK(0x1, I40E_QTX_ENA_QENA_STAT_SHIFT) #define I40E_QTX_HEAD(_Q) (0x000E4000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: CORER */ #define I40E_QTX_HEAD_MAX_INDEX 1535 #define I40E_QTX_HEAD_HEAD_SHIFT 0 #define I40E_QTX_HEAD_HEAD_MASK I40E_MASK(0x1FFF, I40E_QTX_HEAD_HEAD_SHIFT) #define I40E_QTX_HEAD_RS_PENDING_SHIFT 16 #define I40E_QTX_HEAD_RS_PENDING_MASK I40E_MASK(0x1, I40E_QTX_HEAD_RS_PENDING_SHIFT) #define I40E_QTX_TAIL(_Q) (0x00108000 + ((_Q) * 4)) /* _i=0...1535 */ /* Reset: PFR */ #define I40E_QTX_TAIL_MAX_INDEX 1535 #define I40E_QTX_TAIL_TAIL_SHIFT 0 #define I40E_QTX_TAIL_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL_TAIL_SHIFT) #define I40E_VPLAN_MAPENA(_VF) (0x00074000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VPLAN_MAPENA_MAX_INDEX 127 #define I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT 0 #define I40E_VPLAN_MAPENA_TXRX_ENA_MASK I40E_MASK(0x1, I40E_VPLAN_MAPENA_TXRX_ENA_SHIFT) #define I40E_VPLAN_QTABLE(_i, _VF) (0x00070000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: VFR */ #define I40E_VPLAN_QTABLE_MAX_INDEX 15 #define I40E_VPLAN_QTABLE_QINDEX_SHIFT 0 #define I40E_VPLAN_QTABLE_QINDEX_MASK I40E_MASK(0x7FF, I40E_VPLAN_QTABLE_QINDEX_SHIFT) #define I40E_VSILAN_QBASE(_VSI) (0x0020C800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */ #define I40E_VSILAN_QBASE_MAX_INDEX 383 #define I40E_VSILAN_QBASE_VSIBASE_SHIFT 0 #define I40E_VSILAN_QBASE_VSIBASE_MASK I40E_MASK(0x7FF, I40E_VSILAN_QBASE_VSIBASE_SHIFT) #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK I40E_MASK(0x1, I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT) #define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...7, _VSI=0...383 */ /* Reset: PFR */ #define I40E_VSILAN_QTABLE_MAX_INDEX 7 #define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0 #define I40E_VSILAN_QTABLE_QINDEX_0_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_0_SHIFT) #define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16 #define I40E_VSILAN_QTABLE_QINDEX_1_MASK I40E_MASK(0x7FF, I40E_VSILAN_QTABLE_QINDEX_1_SHIFT) #define I40E_PRTGL_SAH 0x001E2140 /* Reset: GLOBR */ #define I40E_PRTGL_SAH_FC_SAH_SHIFT 0 #define I40E_PRTGL_SAH_FC_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_FC_SAH_SHIFT) #define I40E_PRTGL_SAH_MFS_SHIFT 16 #define I40E_PRTGL_SAH_MFS_MASK I40E_MASK(0xFFFF, I40E_PRTGL_SAH_MFS_SHIFT) #define I40E_PRTGL_SAL 0x001E2120 /* Reset: GLOBR */ #define I40E_PRTGL_SAL_FC_SAL_SHIFT 0 #define I40E_PRTGL_SAL_FC_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTGL_SAL_FC_SAL_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP 0x001E30E0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP 0x001E3260 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP 0x001E32E0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL 0x001E3360 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_MASK I40E_MASK(0x1, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL_HSEC_CTL_RX_FORWARD_CONTROL_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1 0x001E3110 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_HSEC_CTL_RX_PAUSE_DA_UCAST_PART1_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2 0x001E3120 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_HSEC_CTL_RX_PAUSE_DA_UCAST_PART2_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE 0x001E30C0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_HSEC_CTL_RX_PAUSE_ENABLE_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1 0x001E3140 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART1_HSEC_CTL_RX_PAUSE_SA_PART1_SHIFT) #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2 0x001E3150 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_SA_PART2_HSEC_CTL_RX_PAUSE_SA_PART2_SHIFT) #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE 0x001E30D0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_MASK I40E_MASK(0x1FF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_HSEC_CTL_TX_PAUSE_ENABLE_SHIFT) #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(_i) (0x001E3370 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_MAX_INDEX 8 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA_HSEC_CTL_TX_PAUSE_QUANTA_SHIFT) #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(_i) (0x001E3400 + ((_i) * 16)) /* _i=0...8 */ /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MAX_INDEX 8 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_HSEC_CTL_TX_PAUSE_REFRESH_TIMER_SHIFT) #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1 0x001E34B0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART1_HSEC_CTL_TX_SA_PART1_SHIFT) #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2 0x001E34C0 /* Reset: GLOBR */ #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT 0 #define I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_MASK I40E_MASK(0xFFFF, I40E_PRTMAC_HSEC_CTL_TX_SA_PART2_HSEC_CTL_TX_SA_PART2_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A 0x0008C480 /* Reset: GLOBR */ #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT 0 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE3_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT 2 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE2_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT 4 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE1_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT 6 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_TX_LANE0_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT 8 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE3_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT 10 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE2_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT 12 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE1_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT 14 #define I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_A_SWAP_RX_LANE0_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B 0x0008C484 /* Reset: GLOBR */ #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT 0 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE3_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT 2 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE2_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT 4 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE1_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT 6 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_TX_LANE0_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT 8 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE3_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT 10 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE2_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT 12 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE1_SHIFT) #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK I40E_MASK(0x3, I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT) #define I40E_GL_FWRESETCNT 0x00083100 /* Reset: POR */ #define I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT 0 #define I40E_GL_FWRESETCNT_FWRESETCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FWRESETCNT_FWRESETCNT_SHIFT) #define I40E_GL_MNG_FWSM 0x000B6134 /* Reset: POR */ #define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0 #define I40E_GL_MNG_FWSM_FW_MODES_MASK I40E_MASK(0x3, I40E_GL_MNG_FWSM_FW_MODES_SHIFT) #define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10 #define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT) #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK I40E_MASK(0xF, I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT) #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT) #define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16 #define I40E_GL_MNG_FWSM_RESET_CNT_MASK I40E_MASK(0x7, I40E_GL_MNG_FWSM_RESET_CNT_SHIFT) #define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK I40E_MASK(0x3F, I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27 #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT 28 #define I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES2_CONFIG_ERR_SHIFT) #define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT 29 #define I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_MASK I40E_MASK(0x1, I40E_GL_MNG_FWSM_PHY_SERDES3_CONFIG_ERR_SHIFT) #define I40E_GL_MNG_HWARB_CTRL 0x000B6130 /* Reset: POR */ #define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT 0 #define I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_MASK I40E_MASK(0x1, I40E_GL_MNG_HWARB_CTRL_NCSI_ARB_EN_SHIFT) #define I40E_PRT_MNG_FTFT_DATA(_i) (0x000852A0 + ((_i) * 32)) /* _i=0...31 */ /* Reset: POR */ #define I40E_PRT_MNG_FTFT_DATA_MAX_INDEX 31 #define I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT 0 #define I40E_PRT_MNG_FTFT_DATA_DWORD_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_FTFT_DATA_DWORD_SHIFT) #define I40E_PRT_MNG_FTFT_LENGTH 0x00085260 /* Reset: POR */ #define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT 0 #define I40E_PRT_MNG_FTFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PRT_MNG_FTFT_LENGTH_LENGTH_SHIFT) #define I40E_PRT_MNG_FTFT_MASK(_i) (0x00085160 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */ #define I40E_PRT_MNG_FTFT_MASK_MAX_INDEX 7 #define I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT 0 #define I40E_PRT_MNG_FTFT_MASK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_FTFT_MASK_MASK_SHIFT) #define I40E_PRT_MNG_MANC 0x00256A20 /* Reset: POR */ #define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT 0 #define I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FLOW_CONTROL_DISCARD_SHIFT) #define I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT 1 #define I40E_PRT_MNG_MANC_NCSI_DISCARD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NCSI_DISCARD_SHIFT) #define I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT 17 #define I40E_PRT_MNG_MANC_RCV_TCO_EN_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_TCO_EN_SHIFT) #define I40E_PRT_MNG_MANC_RCV_ALL_SHIFT 19 #define I40E_PRT_MNG_MANC_RCV_ALL_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_RCV_ALL_SHIFT) #define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT 25 #define I40E_PRT_MNG_MANC_FIXED_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_FIXED_NET_TYPE_SHIFT) #define I40E_PRT_MNG_MANC_NET_TYPE_SHIFT 26 #define I40E_PRT_MNG_MANC_NET_TYPE_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_NET_TYPE_SHIFT) #define I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT 28 #define I40E_PRT_MNG_MANC_EN_BMC2OS_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2OS_SHIFT) #define I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT 29 #define I40E_PRT_MNG_MANC_EN_BMC2NET_MASK I40E_MASK(0x1, I40E_PRT_MNG_MANC_EN_BMC2NET_SHIFT) #define I40E_PRT_MNG_MAVTV(_i) (0x00255900 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */ #define I40E_PRT_MNG_MAVTV_MAX_INDEX 7 #define I40E_PRT_MNG_MAVTV_VID_SHIFT 0 #define I40E_PRT_MNG_MAVTV_VID_MASK I40E_MASK(0xFFF, I40E_PRT_MNG_MAVTV_VID_SHIFT) #define I40E_PRT_MNG_MDEF(_i) (0x00255D00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */ #define I40E_PRT_MNG_MDEF_MAX_INDEX 7 #define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT 0 #define I40E_PRT_MNG_MDEF_MAC_EXACT_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_AND_SHIFT) #define I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT 4 #define I40E_PRT_MNG_MDEF_BROADCAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_AND_SHIFT) #define I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT 5 #define I40E_PRT_MNG_MDEF_VLAN_AND_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MDEF_VLAN_AND_SHIFT) #define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT 13 #define I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV4_ADDRESS_AND_SHIFT) #define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT 17 #define I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_IPV6_ADDRESS_AND_SHIFT) #define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT 21 #define I40E_PRT_MNG_MDEF_MAC_EXACT_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_MAC_EXACT_OR_SHIFT) #define I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT 25 #define I40E_PRT_MNG_MDEF_BROADCAST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_BROADCAST_OR_SHIFT) #define I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT 26 #define I40E_PRT_MNG_MDEF_MULTICAST_AND_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_MULTICAST_AND_SHIFT) #define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT 27 #define I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_REQUEST_OR_SHIFT) #define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT 28 #define I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_ARP_RESPONSE_OR_SHIFT) #define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT 29 #define I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_NEIGHBOR_DISCOVERY_134_OR_SHIFT) #define I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT 30 #define I40E_PRT_MNG_MDEF_PORT_0X298_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X298_OR_SHIFT) #define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT 31 #define I40E_PRT_MNG_MDEF_PORT_0X26F_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_PORT_0X26F_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT(_i) (0x00255F00 + ((_i) * 32)) /* _i=0...7 */ /* Reset: POR */ #define I40E_PRT_MNG_MDEF_EXT_MAX_INDEX 7 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT 0 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_AND_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT 4 #define I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_MASK I40E_MASK(0xF, I40E_PRT_MNG_MDEF_EXT_L2_ETHERTYPE_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT 8 #define I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEF_EXT_FLEX_PORT_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT 24 #define I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_FLEX_TCO_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT 25 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_135_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT 26 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_136_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT 27 #define I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_NEIGHBOR_DISCOVERY_137_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT 28 #define I40E_PRT_MNG_MDEF_EXT_ICMP_OR_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_ICMP_OR_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT 29 #define I40E_PRT_MNG_MDEF_EXT_MLD_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_MLD_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT 30 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_NETWORK_TRAFFIC_SHIFT) #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT 31 #define I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_MASK I40E_MASK(0x1, I40E_PRT_MNG_MDEF_EXT_APPLY_TO_HOST_TRAFFIC_SHIFT) #define I40E_PRT_MNG_MDEFVSI(_i) (0x00256580 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */ #define I40E_PRT_MNG_MDEFVSI_MAX_INDEX 3 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT 0 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2N_SHIFT) #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT 16 #define I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MDEFVSI_MDEFVSI_2NP1_SHIFT) #define I40E_PRT_MNG_METF(_i) (0x00256780 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */ #define I40E_PRT_MNG_METF_MAX_INDEX 3 #define I40E_PRT_MNG_METF_ETYPE_SHIFT 0 #define I40E_PRT_MNG_METF_ETYPE_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_METF_ETYPE_SHIFT) #define I40E_PRT_MNG_METF_POLARITY_SHIFT 30 #define I40E_PRT_MNG_METF_POLARITY_MASK I40E_MASK(0x1, I40E_PRT_MNG_METF_POLARITY_SHIFT) #define I40E_PRT_MNG_MFUTP(_i) (0x00254E00 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */ #define I40E_PRT_MNG_MFUTP_MAX_INDEX 15 #define I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT 0 #define I40E_PRT_MNG_MFUTP_MFUTP_N_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MFUTP_MFUTP_N_SHIFT) #define I40E_PRT_MNG_MFUTP_UDP_SHIFT 16 #define I40E_PRT_MNG_MFUTP_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_UDP_SHIFT) #define I40E_PRT_MNG_MFUTP_TCP_SHIFT 17 #define I40E_PRT_MNG_MFUTP_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_TCP_SHIFT) #define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT 18 #define I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_MASK I40E_MASK(0x1, I40E_PRT_MNG_MFUTP_SOURCE_DESTINATION_SHIFT) #define I40E_PRT_MNG_MIPAF4(_i) (0x00256280 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */ #define I40E_PRT_MNG_MIPAF4_MAX_INDEX 3 #define I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT 0 #define I40E_PRT_MNG_MIPAF4_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF4_MIPAF_SHIFT) #define I40E_PRT_MNG_MIPAF6(_i) (0x00254200 + ((_i) * 32)) /* _i=0...15 */ /* Reset: POR */ #define I40E_PRT_MNG_MIPAF6_MAX_INDEX 15 #define I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT 0 #define I40E_PRT_MNG_MIPAF6_MIPAF_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MIPAF6_MIPAF_SHIFT) #define I40E_PRT_MNG_MMAH(_i) (0x00256380 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */ #define I40E_PRT_MNG_MMAH_MAX_INDEX 3 #define I40E_PRT_MNG_MMAH_MMAH_SHIFT 0 #define I40E_PRT_MNG_MMAH_MMAH_MASK I40E_MASK(0xFFFF, I40E_PRT_MNG_MMAH_MMAH_SHIFT) #define I40E_PRT_MNG_MMAL(_i) (0x00256480 + ((_i) * 32)) /* _i=0...3 */ /* Reset: POR */ #define I40E_PRT_MNG_MMAL_MAX_INDEX 3 #define I40E_PRT_MNG_MMAL_MMAL_SHIFT 0 #define I40E_PRT_MNG_MMAL_MMAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRT_MNG_MMAL_MMAL_SHIFT) #define I40E_PRT_MNG_MNGONLY 0x00256A60 /* Reset: POR */ #define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT 0 #define I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_MASK I40E_MASK(0xFF, I40E_PRT_MNG_MNGONLY_EXCLUSIVE_TO_MANAGEABILITY_SHIFT) #define I40E_PRT_MNG_MSFM 0x00256AA0 /* Reset: POR */ #define I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT 0 #define I40E_PRT_MNG_MSFM_PORT_26F_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_UDP_SHIFT) #define I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT 1 #define I40E_PRT_MNG_MSFM_PORT_26F_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_26F_TCP_SHIFT) #define I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT 2 #define I40E_PRT_MNG_MSFM_PORT_298_UDP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_UDP_SHIFT) #define I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT 3 #define I40E_PRT_MNG_MSFM_PORT_298_TCP_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_PORT_298_TCP_SHIFT) #define I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT 4 #define I40E_PRT_MNG_MSFM_IPV6_0_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_0_MASK_SHIFT) #define I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT 5 #define I40E_PRT_MNG_MSFM_IPV6_1_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_1_MASK_SHIFT) #define I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT 6 #define I40E_PRT_MNG_MSFM_IPV6_2_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_2_MASK_SHIFT) #define I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT 7 #define I40E_PRT_MNG_MSFM_IPV6_3_MASK_MASK I40E_MASK(0x1, I40E_PRT_MNG_MSFM_IPV6_3_MASK_SHIFT) #define I40E_MSIX_PBA(_i) (0x00001000 + ((_i) * 4)) /* _i=0...5 */ /* Reset: FLR */ #define I40E_MSIX_PBA_MAX_INDEX 5 #define I40E_MSIX_PBA_PENBIT_SHIFT 0 #define I40E_MSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_PBA_PENBIT_SHIFT) #define I40E_MSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */ #define I40E_MSIX_TADD_MAX_INDEX 128 #define I40E_MSIX_TADD_MSIXTADD10_SHIFT 0 #define I40E_MSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_MSIX_TADD_MSIXTADD10_SHIFT) #define I40E_MSIX_TADD_MSIXTADD_SHIFT 2 #define I40E_MSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_MSIX_TADD_MSIXTADD_SHIFT) #define I40E_MSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */ #define I40E_MSIX_TMSG_MAX_INDEX 128 #define I40E_MSIX_TMSG_MSIXTMSG_SHIFT 0 #define I40E_MSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TMSG_MSIXTMSG_SHIFT) #define I40E_MSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */ #define I40E_MSIX_TUADD_MAX_INDEX 128 #define I40E_MSIX_TUADD_MSIXTUADD_SHIFT 0 #define I40E_MSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_MSIX_TUADD_MSIXTUADD_SHIFT) #define I40E_MSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...128 */ /* Reset: FLR */ #define I40E_MSIX_TVCTRL_MAX_INDEX 128 #define I40E_MSIX_TVCTRL_MASK_SHIFT 0 #define I40E_MSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_MSIX_TVCTRL_MASK_SHIFT) #define I40E_VFMSIX_PBA1(_i) (0x00002000 + ((_i) * 4)) /* _i=0...19 */ /* Reset: VFLR */ #define I40E_VFMSIX_PBA1_MAX_INDEX 19 #define I40E_VFMSIX_PBA1_PENBIT_SHIFT 0 #define I40E_VFMSIX_PBA1_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA1_PENBIT_SHIFT) #define I40E_VFMSIX_TADD1(_i) (0x00002100 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */ #define I40E_VFMSIX_TADD1_MAX_INDEX 639 #define I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT 0 #define I40E_VFMSIX_TADD1_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD1_MSIXTADD10_SHIFT) #define I40E_VFMSIX_TADD1_MSIXTADD_SHIFT 2 #define I40E_VFMSIX_TADD1_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD1_MSIXTADD_SHIFT) #define I40E_VFMSIX_TMSG1(_i) (0x00002108 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */ #define I40E_VFMSIX_TMSG1_MAX_INDEX 639 #define I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT 0 #define I40E_VFMSIX_TMSG1_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG1_MSIXTMSG_SHIFT) #define I40E_VFMSIX_TUADD1(_i) (0x00002104 + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */ #define I40E_VFMSIX_TUADD1_MAX_INDEX 639 #define I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT 0 #define I40E_VFMSIX_TUADD1_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD1_MSIXTUADD_SHIFT) #define I40E_VFMSIX_TVCTRL1(_i) (0x0000210C + ((_i) * 16)) /* _i=0...639 */ /* Reset: VFLR */ #define I40E_VFMSIX_TVCTRL1_MAX_INDEX 639 #define I40E_VFMSIX_TVCTRL1_MASK_SHIFT 0 #define I40E_VFMSIX_TVCTRL1_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL1_MASK_SHIFT) #define I40E_GLNVM_FLA 0x000B6108 /* Reset: POR */ #define I40E_GLNVM_FLA_FL_SCK_SHIFT 0 #define I40E_GLNVM_FLA_FL_SCK_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SCK_SHIFT) #define I40E_GLNVM_FLA_FL_CE_SHIFT 1 #define I40E_GLNVM_FLA_FL_CE_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_CE_SHIFT) #define I40E_GLNVM_FLA_FL_SI_SHIFT 2 #define I40E_GLNVM_FLA_FL_SI_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SI_SHIFT) #define I40E_GLNVM_FLA_FL_SO_SHIFT 3 #define I40E_GLNVM_FLA_FL_SO_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_SO_SHIFT) #define I40E_GLNVM_FLA_FL_REQ_SHIFT 4 #define I40E_GLNVM_FLA_FL_REQ_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_REQ_SHIFT) #define I40E_GLNVM_FLA_FL_GNT_SHIFT 5 #define I40E_GLNVM_FLA_FL_GNT_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_GNT_SHIFT) #define I40E_GLNVM_FLA_LOCKED_SHIFT 6 #define I40E_GLNVM_FLA_LOCKED_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_LOCKED_SHIFT) #define I40E_GLNVM_FLA_FL_SADDR_SHIFT 18 #define I40E_GLNVM_FLA_FL_SADDR_MASK I40E_MASK(0x7FF, I40E_GLNVM_FLA_FL_SADDR_SHIFT) #define I40E_GLNVM_FLA_FL_BUSY_SHIFT 30 #define I40E_GLNVM_FLA_FL_BUSY_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_BUSY_SHIFT) #define I40E_GLNVM_FLA_FL_DER_SHIFT 31 #define I40E_GLNVM_FLA_FL_DER_MASK I40E_MASK(0x1, I40E_GLNVM_FLA_FL_DER_SHIFT) #define I40E_GLNVM_FLASHID 0x000B6104 /* Reset: POR */ #define I40E_GLNVM_FLASHID_FLASHID_SHIFT 0 #define I40E_GLNVM_FLASHID_FLASHID_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_FLASHID_FLASHID_SHIFT) #define I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT 31 #define I40E_GLNVM_FLASHID_FLEEP_PERF_MASK I40E_MASK(0x1, I40E_GLNVM_FLASHID_FLEEP_PERF_SHIFT) #define I40E_GLNVM_GENS 0x000B6100 /* Reset: POR */ #define I40E_GLNVM_GENS_NVM_PRES_SHIFT 0 #define I40E_GLNVM_GENS_NVM_PRES_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_NVM_PRES_SHIFT) #define I40E_GLNVM_GENS_SR_SIZE_SHIFT 5 #define I40E_GLNVM_GENS_SR_SIZE_MASK I40E_MASK(0x7, I40E_GLNVM_GENS_SR_SIZE_SHIFT) #define I40E_GLNVM_GENS_BANK1VAL_SHIFT 8 #define I40E_GLNVM_GENS_BANK1VAL_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_BANK1VAL_SHIFT) #define I40E_GLNVM_GENS_ALT_PRST_SHIFT 23 #define I40E_GLNVM_GENS_ALT_PRST_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_ALT_PRST_SHIFT) #define I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT 25 #define I40E_GLNVM_GENS_FL_AUTO_RD_MASK I40E_MASK(0x1, I40E_GLNVM_GENS_FL_AUTO_RD_SHIFT) #define I40E_GLNVM_PROTCSR(_i) (0x000B6010 + ((_i) * 4)) /* _i=0...59 */ /* Reset: POR */ #define I40E_GLNVM_PROTCSR_MAX_INDEX 59 #define I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT 0 #define I40E_GLNVM_PROTCSR_ADDR_BLOCK_MASK I40E_MASK(0xFFFFFF, I40E_GLNVM_PROTCSR_ADDR_BLOCK_SHIFT) #define I40E_GLNVM_SRCTL 0x000B6110 /* Reset: POR */ #define I40E_GLNVM_SRCTL_SRBUSY_SHIFT 0 #define I40E_GLNVM_SRCTL_SRBUSY_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_SRBUSY_SHIFT) #define I40E_GLNVM_SRCTL_ADDR_SHIFT 14 #define I40E_GLNVM_SRCTL_ADDR_MASK I40E_MASK(0x7FFF, I40E_GLNVM_SRCTL_ADDR_SHIFT) #define I40E_GLNVM_SRCTL_WRITE_SHIFT 29 #define I40E_GLNVM_SRCTL_WRITE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_WRITE_SHIFT) #define I40E_GLNVM_SRCTL_START_SHIFT 30 #define I40E_GLNVM_SRCTL_START_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_START_SHIFT) #define I40E_GLNVM_SRCTL_DONE_SHIFT 31 #define I40E_GLNVM_SRCTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_SRCTL_DONE_SHIFT) #define I40E_GLNVM_SRDATA 0x000B6114 /* Reset: POR */ #define I40E_GLNVM_SRDATA_WRDATA_SHIFT 0 #define I40E_GLNVM_SRDATA_WRDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_WRDATA_SHIFT) #define I40E_GLNVM_SRDATA_RDDATA_SHIFT 16 #define I40E_GLNVM_SRDATA_RDDATA_MASK I40E_MASK(0xFFFF, I40E_GLNVM_SRDATA_RDDATA_SHIFT) #define I40E_GLNVM_ULD 0x000B6008 /* Reset: POR */ #define I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT 0 #define I40E_GLNVM_ULD_CONF_PCIR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIR_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT 1 #define I40E_GLNVM_ULD_CONF_PCIRTL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIRTL_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT 2 #define I40E_GLNVM_ULD_CONF_LCB_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_LCB_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT 3 #define I40E_GLNVM_ULD_CONF_CORE_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_CORE_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT 4 #define I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_GLOBAL_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT 5 #define I40E_GLNVM_ULD_CONF_POR_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_POR_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT 6 #define I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIE_ANA_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT 7 #define I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PHY_ANA_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT 8 #define I40E_GLNVM_ULD_CONF_EMP_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_EMP_DONE_SHIFT) #define I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT 9 #define I40E_GLNVM_ULD_CONF_PCIALT_DONE_MASK I40E_MASK(0x1, I40E_GLNVM_ULD_CONF_PCIALT_DONE_SHIFT) #define I40E_GLPCI_BYTCTH 0x0009C484 /* Reset: PCIR */ #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT 0 #define I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTH_PCI_COUNT_BW_BCT_SHIFT) #define I40E_GLPCI_BYTCTL 0x0009C488 /* Reset: PCIR */ #define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT 0 #define I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_BYTCTL_PCI_COUNT_BW_BCT_SHIFT) #define I40E_GLPCI_CAPCTRL 0x000BE4A4 /* Reset: PCIR */ #define I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT 0 #define I40E_GLPCI_CAPCTRL_VPD_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPCTRL_VPD_EN_SHIFT) #define I40E_GLPCI_CAPSUP 0x000BE4A8 /* Reset: PCIR */ #define I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT 0 #define I40E_GLPCI_CAPSUP_PCIE_VER_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_PCIE_VER_SHIFT) #define I40E_GLPCI_CAPSUP_LTR_EN_SHIFT 2 #define I40E_GLPCI_CAPSUP_LTR_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LTR_EN_SHIFT) #define I40E_GLPCI_CAPSUP_TPH_EN_SHIFT 3 #define I40E_GLPCI_CAPSUP_TPH_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_TPH_EN_SHIFT) #define I40E_GLPCI_CAPSUP_ARI_EN_SHIFT 4 #define I40E_GLPCI_CAPSUP_ARI_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ARI_EN_SHIFT) #define I40E_GLPCI_CAPSUP_IOV_EN_SHIFT 5 #define I40E_GLPCI_CAPSUP_IOV_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IOV_EN_SHIFT) #define I40E_GLPCI_CAPSUP_ACS_EN_SHIFT 6 #define I40E_GLPCI_CAPSUP_ACS_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ACS_EN_SHIFT) #define I40E_GLPCI_CAPSUP_SEC_EN_SHIFT 7 #define I40E_GLPCI_CAPSUP_SEC_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_SEC_EN_SHIFT) #define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT 16 #define I40E_GLPCI_CAPSUP_ECRC_GEN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_GEN_EN_SHIFT) #define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT 17 #define I40E_GLPCI_CAPSUP_ECRC_CHK_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_ECRC_CHK_EN_SHIFT) #define I40E_GLPCI_CAPSUP_IDO_EN_SHIFT 18 #define I40E_GLPCI_CAPSUP_IDO_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_IDO_EN_SHIFT) #define I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT 19 #define I40E_GLPCI_CAPSUP_MSI_MASK_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_MSI_MASK_SHIFT) #define I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT 20 #define I40E_GLPCI_CAPSUP_CSR_CONF_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_CSR_CONF_EN_SHIFT) #define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT 30 #define I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_SUBSYS_ID_SHIFT) #define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT 31 #define I40E_GLPCI_CAPSUP_LOAD_DEV_ID_MASK I40E_MASK(0x1, I40E_GLPCI_CAPSUP_LOAD_DEV_ID_SHIFT) #define I40E_GLPCI_CNF 0x000BE4C0 /* Reset: POR */ #define I40E_GLPCI_CNF_FLEX10_SHIFT 1 #define I40E_GLPCI_CNF_FLEX10_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_FLEX10_SHIFT) #define I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT 2 #define I40E_GLPCI_CNF_WAKE_PIN_EN_MASK I40E_MASK(0x1, I40E_GLPCI_CNF_WAKE_PIN_EN_SHIFT) #define I40E_GLPCI_CNF2 0x000BE494 /* Reset: PCIR */ #define I40E_GLPCI_CNF2_RO_DIS_SHIFT 0 #define I40E_GLPCI_CNF2_RO_DIS_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_RO_DIS_SHIFT) #define I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT 1 #define I40E_GLPCI_CNF2_CACHELINE_SIZE_MASK I40E_MASK(0x1, I40E_GLPCI_CNF2_CACHELINE_SIZE_SHIFT) #define I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT 2 #define I40E_GLPCI_CNF2_MSI_X_PF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_PF_N_SHIFT) #define I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT 13 #define I40E_GLPCI_CNF2_MSI_X_VF_N_MASK I40E_MASK(0x7FF, I40E_GLPCI_CNF2_MSI_X_VF_N_SHIFT) #define I40E_GLPCI_DREVID 0x0009C480 /* Reset: PCIR */ #define I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT 0 #define I40E_GLPCI_DREVID_DEFAULT_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_DREVID_DEFAULT_REVID_SHIFT) #define I40E_GLPCI_GSCL_1 0x0009C48C /* Reset: PCIR */ #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT 0 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_0_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT 1 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_1_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT 2 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_2_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT 3 #define I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_EN_3_SHIFT) #define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT 4 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_0_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_0_SHIFT) #define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT 5 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_1_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_1_SHIFT) #define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT 6 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_2_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_2_SHIFT) #define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT 7 #define I40E_GLPCI_GSCL_1_LBC_ENABLE_3_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_LBC_ENABLE_3_SHIFT) #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT 8 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EN_SHIFT) #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT 9 #define I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_LAT_EV_SHIFT) #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT 14 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EN_SHIFT) #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT 15 #define I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_MASK I40E_MASK(0x1F, I40E_GLPCI_GSCL_1_PCI_COUNT_BW_EV_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT 28 #define I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_64_BIT_EN_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT 29 #define I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_RESET_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT 30 #define I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_STOP_SHIFT) #define I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT 31 #define I40E_GLPCI_GSCL_1_GIO_COUNT_START_MASK I40E_MASK(0x1, I40E_GLPCI_GSCL_1_GIO_COUNT_START_SHIFT) #define I40E_GLPCI_GSCL_2 0x0009C490 /* Reset: PCIR */ #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT 0 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_0_SHIFT) #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT 8 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_1_SHIFT) #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT 16 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_2_SHIFT) #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT 24 #define I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_MASK I40E_MASK(0xFF, I40E_GLPCI_GSCL_2_GIO_EVENT_NUM_3_SHIFT) #define I40E_GLPCI_GSCL_5_8(_i) (0x0009C494 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */ #define I40E_GLPCI_GSCL_5_8_MAX_INDEX 3 #define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT 0 #define I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_THRESHOLD_N_SHIFT) #define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT 16 #define I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_MASK I40E_MASK(0xFFFF, I40E_GLPCI_GSCL_5_8_LBC_TIMER_N_SHIFT) #define I40E_GLPCI_GSCN_0_3(_i) (0x0009C4A4 + ((_i) * 4)) /* _i=0...3 */ /* Reset: PCIR */ #define I40E_GLPCI_GSCN_0_3_MAX_INDEX 3 #define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT 0 #define I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_GSCN_0_3_EVENT_COUNTER_SHIFT) #define I40E_GLPCI_LBARCTRL 0x000BE484 /* Reset: POR */ #define I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT 0 #define I40E_GLPCI_LBARCTRL_PREFBAR_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_PREFBAR_SHIFT) #define I40E_GLPCI_LBARCTRL_BAR32_SHIFT 1 #define I40E_GLPCI_LBARCTRL_BAR32_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_BAR32_SHIFT) #define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT 3 #define I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_FLASH_EXPOSE_SHIFT) #define I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT 4 #define I40E_GLPCI_LBARCTRL_RSVD_4_MASK I40E_MASK(0x3, I40E_GLPCI_LBARCTRL_RSVD_4_SHIFT) #define I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT 6 #define I40E_GLPCI_LBARCTRL_FL_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT) #define I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT 10 #define I40E_GLPCI_LBARCTRL_RSVD_10_MASK I40E_MASK(0x1, I40E_GLPCI_LBARCTRL_RSVD_10_SHIFT) #define I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT 11 #define I40E_GLPCI_LBARCTRL_EXROM_SIZE_MASK I40E_MASK(0x7, I40E_GLPCI_LBARCTRL_EXROM_SIZE_SHIFT) #define I40E_GLPCI_LINKCAP 0x000BE4AC /* Reset: PCIR */ #define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT 0 #define I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_MASK I40E_MASK(0x3F, I40E_GLPCI_LINKCAP_LINK_SPEEDS_VECTOR_SHIFT) #define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT 6 #define I40E_GLPCI_LINKCAP_MAX_PAYLOAD_MASK I40E_MASK(0x7, I40E_GLPCI_LINKCAP_MAX_PAYLOAD_SHIFT) #define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT 9 #define I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_MASK I40E_MASK(0xF, I40E_GLPCI_LINKCAP_MAX_LINK_WIDTH_SHIFT) #define I40E_GLPCI_PCIERR 0x000BE4FC /* Reset: PCIR */ #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT) #define I40E_GLPCI_PKTCT 0x0009C4BC /* Reset: PCIR */ #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT) #define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4 /* Reset: PCIR */ #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0 #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT) #define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT 16 #define I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_NPQ_INNER_NPQ_SEL_SHIFT) #define I40E_GLPCI_PM_MUX_PFB 0x0009C4F0 /* Reset: PCIR */ #define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT 0 #define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK I40E_MASK(0x1F, I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT) #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16 #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK I40E_MASK(0x7, I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT) #define I40E_GLPCI_PMSUP 0x000BE4B0 /* Reset: PCIR */ #define I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT 0 #define I40E_GLPCI_PMSUP_ASPM_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_ASPM_SUP_SHIFT) #define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT 2 #define I40E_GLPCI_PMSUP_L0S_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_EXIT_LAT_SHIFT) #define I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT 5 #define I40E_GLPCI_PMSUP_L1_EXIT_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_EXIT_LAT_SHIFT) #define I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT 8 #define I40E_GLPCI_PMSUP_L0S_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L0S_ACC_LAT_SHIFT) #define I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT 11 #define I40E_GLPCI_PMSUP_L1_ACC_LAT_MASK I40E_MASK(0x7, I40E_GLPCI_PMSUP_L1_ACC_LAT_SHIFT) #define I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT 14 #define I40E_GLPCI_PMSUP_SLOT_CLK_MASK I40E_MASK(0x1, I40E_GLPCI_PMSUP_SLOT_CLK_SHIFT) #define I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT 15 #define I40E_GLPCI_PMSUP_OBFF_SUP_MASK I40E_MASK(0x3, I40E_GLPCI_PMSUP_OBFF_SUP_SHIFT) #define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC /* Reset: PCIR */ #define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0 #define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT) #define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8 #define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK I40E_MASK(0xFF, I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT) #define I40E_GLPCI_PWRDATA 0x000BE490 /* Reset: PCIR */ #define I40E_GLPCI_PWRDATA_D0_POWER_SHIFT 0 #define I40E_GLPCI_PWRDATA_D0_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D0_POWER_SHIFT) #define I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT 8 #define I40E_GLPCI_PWRDATA_COMM_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_COMM_POWER_SHIFT) #define I40E_GLPCI_PWRDATA_D3_POWER_SHIFT 16 #define I40E_GLPCI_PWRDATA_D3_POWER_MASK I40E_MASK(0xFF, I40E_GLPCI_PWRDATA_D3_POWER_SHIFT) #define I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT 24 #define I40E_GLPCI_PWRDATA_DATA_SCALE_MASK I40E_MASK(0x3, I40E_GLPCI_PWRDATA_DATA_SCALE_SHIFT) #define I40E_GLPCI_REVID 0x000BE4B4 /* Reset: PCIR */ #define I40E_GLPCI_REVID_NVM_REVID_SHIFT 0 #define I40E_GLPCI_REVID_NVM_REVID_MASK I40E_MASK(0xFF, I40E_GLPCI_REVID_NVM_REVID_SHIFT) #define I40E_GLPCI_SERH 0x000BE49C /* Reset: PCIR */ #define I40E_GLPCI_SERH_SER_NUM_H_SHIFT 0 #define I40E_GLPCI_SERH_SER_NUM_H_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SERH_SER_NUM_H_SHIFT) #define I40E_GLPCI_SERL 0x000BE498 /* Reset: PCIR */ #define I40E_GLPCI_SERL_SER_NUM_L_SHIFT 0 #define I40E_GLPCI_SERL_SER_NUM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SERL_SER_NUM_L_SHIFT) #define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8 /* Reset: PCIR */ #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0 #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT) #define I40E_GLPCI_SPARE_BITS_1 0x0009C4FC /* Reset: PCIR */ #define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT 0 #define I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPCI_SPARE_BITS_1_SPARE_BITS_SHIFT) #define I40E_GLPCI_SUBVENID 0x000BE48C /* Reset: PCIR */ #define I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT 0 #define I40E_GLPCI_SUBVENID_SUB_VEN_ID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_SUBVENID_SUB_VEN_ID_SHIFT) #define I40E_GLPCI_UPADD 0x000BE4F8 /* Reset: PCIR */ #define I40E_GLPCI_UPADD_ADDRESS_SHIFT 1 #define I40E_GLPCI_UPADD_ADDRESS_MASK I40E_MASK(0x7FFFFFFF, I40E_GLPCI_UPADD_ADDRESS_SHIFT) #define I40E_GLPCI_VENDORID 0x000BE518 /* Reset: PCIR */ #define I40E_GLPCI_VENDORID_VENDORID_SHIFT 0 #define I40E_GLPCI_VENDORID_VENDORID_MASK I40E_MASK(0xFFFF, I40E_GLPCI_VENDORID_VENDORID_SHIFT) #define I40E_GLPCI_VFSUP 0x000BE4B8 /* Reset: PCIR */ #define I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT 0 #define I40E_GLPCI_VFSUP_VF_PREFETCH_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VF_PREFETCH_SHIFT) #define I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT 1 #define I40E_GLPCI_VFSUP_VR_BAR_TYPE_MASK I40E_MASK(0x1, I40E_GLPCI_VFSUP_VR_BAR_TYPE_SHIFT) #define I40E_GLTPH_CTRL 0x000BE480 /* Reset: PCIR */ #define I40E_GLTPH_CTRL_DESC_PH_SHIFT 9 #define I40E_GLTPH_CTRL_DESC_PH_MASK I40E_MASK(0x3, I40E_GLTPH_CTRL_DESC_PH_SHIFT) #define I40E_GLTPH_CTRL_DATA_PH_SHIFT 11 #define I40E_GLTPH_CTRL_DATA_PH_MASK I40E_MASK(0x3, I40E_GLTPH_CTRL_DATA_PH_SHIFT) #define I40E_PF_FUNC_RID 0x0009C000 /* Reset: PCIR */ #define I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT 0 #define I40E_PF_FUNC_RID_FUNCTION_NUMBER_MASK I40E_MASK(0x7, I40E_PF_FUNC_RID_FUNCTION_NUMBER_SHIFT) #define I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT 3 #define I40E_PF_FUNC_RID_DEVICE_NUMBER_MASK I40E_MASK(0x1F, I40E_PF_FUNC_RID_DEVICE_NUMBER_SHIFT) #define I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT 8 #define I40E_PF_FUNC_RID_BUS_NUMBER_MASK I40E_MASK(0xFF, I40E_PF_FUNC_RID_BUS_NUMBER_SHIFT) #define I40E_PF_PCI_CIAA 0x0009C080 /* Reset: FLR */ #define I40E_PF_PCI_CIAA_ADDRESS_SHIFT 0 #define I40E_PF_PCI_CIAA_ADDRESS_MASK I40E_MASK(0xFFF, I40E_PF_PCI_CIAA_ADDRESS_SHIFT) #define I40E_PF_PCI_CIAA_VF_NUM_SHIFT 12 #define I40E_PF_PCI_CIAA_VF_NUM_MASK I40E_MASK(0x7F, I40E_PF_PCI_CIAA_VF_NUM_SHIFT) #define I40E_PF_PCI_CIAD 0x0009C100 /* Reset: FLR */ #define I40E_PF_PCI_CIAD_DATA_SHIFT 0 #define I40E_PF_PCI_CIAD_DATA_MASK I40E_MASK(0xFFFFFFFF, I40E_PF_PCI_CIAD_DATA_SHIFT) #define I40E_PFPCI_CLASS 0x000BE400 /* Reset: PCIR */ #define I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT 0 #define I40E_PFPCI_CLASS_STORAGE_CLASS_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_STORAGE_CLASS_SHIFT) #define I40E_PFPCI_CLASS_RESERVED_1_SHIFT 1 #define I40E_PFPCI_CLASS_RESERVED_1_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_RESERVED_1_SHIFT) #define I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT 2 #define I40E_PFPCI_CLASS_PF_IS_LAN_MASK I40E_MASK(0x1, I40E_PFPCI_CLASS_PF_IS_LAN_SHIFT) #define I40E_PFPCI_CNF 0x000BE000 /* Reset: PCIR */ #define I40E_PFPCI_CNF_MSI_EN_SHIFT 2 #define I40E_PFPCI_CNF_MSI_EN_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_MSI_EN_SHIFT) #define I40E_PFPCI_CNF_EXROM_DIS_SHIFT 3 #define I40E_PFPCI_CNF_EXROM_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_EXROM_DIS_SHIFT) #define I40E_PFPCI_CNF_IO_BAR_SHIFT 4 #define I40E_PFPCI_CNF_IO_BAR_MASK I40E_MASK(0x1, I40E_PFPCI_CNF_IO_BAR_SHIFT) #define I40E_PFPCI_CNF_INT_PIN_SHIFT 5 #define I40E_PFPCI_CNF_INT_PIN_MASK I40E_MASK(0x3, I40E_PFPCI_CNF_INT_PIN_SHIFT) #define I40E_PFPCI_DEVID 0x000BE080 /* Reset: PCIR */ #define I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT 0 #define I40E_PFPCI_DEVID_PF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_PF_DEV_ID_SHIFT) #define I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT 16 #define I40E_PFPCI_DEVID_VF_DEV_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_DEVID_VF_DEV_ID_SHIFT) #define I40E_PFPCI_FACTPS 0x0009C180 /* Reset: FLR */ #define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT 0 #define I40E_PFPCI_FACTPS_FUNC_POWER_STATE_MASK I40E_MASK(0x3, I40E_PFPCI_FACTPS_FUNC_POWER_STATE_SHIFT) #define I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT 3 #define I40E_PFPCI_FACTPS_FUNC_AUX_EN_MASK I40E_MASK(0x1, I40E_PFPCI_FACTPS_FUNC_AUX_EN_SHIFT) #define I40E_PFPCI_FUNC 0x000BE200 /* Reset: POR */ #define I40E_PFPCI_FUNC_FUNC_DIS_SHIFT 0 #define I40E_PFPCI_FUNC_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_FUNC_DIS_SHIFT) #define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT 1 #define I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_ALLOW_FUNC_DIS_SHIFT) #define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT 2 #define I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC_DIS_FUNC_ON_PORT_DIS_SHIFT) #define I40E_PFPCI_FUNC2 0x000BE180 /* Reset: PCIR */ #define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT 0 #define I40E_PFPCI_FUNC2_EMP_FUNC_DIS_MASK I40E_MASK(0x1, I40E_PFPCI_FUNC2_EMP_FUNC_DIS_SHIFT) #define I40E_PFPCI_ICAUSE 0x0009C200 /* Reset: PFR */ #define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT 0 #define I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_ICAUSE_PCIE_ERR_CAUSE_SHIFT) #define I40E_PFPCI_IENA 0x0009C280 /* Reset: PFR */ #define I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT 0 #define I40E_PFPCI_IENA_PCIE_ERR_EN_MASK I40E_MASK(0xFFFFFFFF, I40E_PFPCI_IENA_PCIE_ERR_EN_SHIFT) #define I40E_PFPCI_PF_FLUSH_DONE 0x0009C800 /* Reset: PCIR */ #define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_PF_FLUSH_DONE_FLUSH_DONE_SHIFT) #define I40E_PFPCI_PM 0x000BE300 /* Reset: POR */ #define I40E_PFPCI_PM_PME_EN_SHIFT 0 #define I40E_PFPCI_PM_PME_EN_MASK I40E_MASK(0x1, I40E_PFPCI_PM_PME_EN_SHIFT) #define I40E_PFPCI_STATUS1 0x000BE280 /* Reset: POR */ #define I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT 0 #define I40E_PFPCI_STATUS1_FUNC_VALID_MASK I40E_MASK(0x1, I40E_PFPCI_STATUS1_FUNC_VALID_SHIFT) #define I40E_PFPCI_SUBSYSID 0x000BE100 /* Reset: PCIR */ #define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT 0 #define I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_PF_SUBSYS_ID_SHIFT) #define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT 16 #define I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_MASK I40E_MASK(0xFFFF, I40E_PFPCI_SUBSYSID_VF_SUBSYS_ID_SHIFT) #define I40E_PFPCI_VF_FLUSH_DONE 0x0000E400 /* Reset: PCIR */ #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT) #define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: PCIR */ #define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127 #define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT) #define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880 /* Reset: PCIR */ #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK I40E_MASK(0x1, I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT) #define I40E_PFPCI_VMINDEX 0x0009C300 /* Reset: PCIR */ #define I40E_PFPCI_VMINDEX_VMINDEX_SHIFT 0 #define I40E_PFPCI_VMINDEX_VMINDEX_MASK I40E_MASK(0x1FF, I40E_PFPCI_VMINDEX_VMINDEX_SHIFT) #define I40E_PFPCI_VMPEND 0x0009C380 /* Reset: PCIR */ #define I40E_PFPCI_VMPEND_PENDING_SHIFT 0 #define I40E_PFPCI_VMPEND_PENDING_MASK I40E_MASK(0x1, I40E_PFPCI_VMPEND_PENDING_SHIFT) #define I40E_PRTPM_EEE_STAT 0x001E4320 /* Reset: GLOBR */ #define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29 #define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT) #define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT 30 #define I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_RX_LPI_STATUS_SHIFT) #define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT 31 #define I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_MASK I40E_MASK(0x1, I40E_PRTPM_EEE_STAT_TX_LPI_STATUS_SHIFT) #define I40E_PRTPM_EEEC 0x001E4380 /* Reset: GLOBR */ #define I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT 16 #define I40E_PRTPM_EEEC_TW_WAKE_MIN_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TW_WAKE_MIN_SHIFT) #define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT 24 #define I40E_PRTPM_EEEC_TX_LU_LPI_DLY_MASK I40E_MASK(0x3, I40E_PRTPM_EEEC_TX_LU_LPI_DLY_SHIFT) #define I40E_PRTPM_EEEC_TEEE_DLY_SHIFT 26 #define I40E_PRTPM_EEEC_TEEE_DLY_MASK I40E_MASK(0x3F, I40E_PRTPM_EEEC_TEEE_DLY_SHIFT) #define I40E_PRTPM_EEEFWD 0x001E4400 /* Reset: GLOBR */ #define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT 31 #define I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_MASK I40E_MASK(0x1, I40E_PRTPM_EEEFWD_EEE_FW_CONFIG_DONE_SHIFT) #define I40E_PRTPM_EEER 0x001E4360 /* Reset: GLOBR */ #define I40E_PRTPM_EEER_TW_SYSTEM_SHIFT 0 #define I40E_PRTPM_EEER_TW_SYSTEM_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEER_TW_SYSTEM_SHIFT) #define I40E_PRTPM_EEER_TX_LPI_EN_SHIFT 16 #define I40E_PRTPM_EEER_TX_LPI_EN_MASK I40E_MASK(0x1, I40E_PRTPM_EEER_TX_LPI_EN_SHIFT) #define I40E_PRTPM_EEETXC 0x001E43E0 /* Reset: GLOBR */ #define I40E_PRTPM_EEETXC_TW_PHY_SHIFT 0 #define I40E_PRTPM_EEETXC_TW_PHY_MASK I40E_MASK(0xFFFF, I40E_PRTPM_EEETXC_TW_PHY_SHIFT) #define I40E_PRTPM_GC 0x000B8140 /* Reset: POR */ #define I40E_PRTPM_GC_EMP_LINK_ON_SHIFT 0 #define I40E_PRTPM_GC_EMP_LINK_ON_MASK I40E_MASK(0x1, I40E_PRTPM_GC_EMP_LINK_ON_SHIFT) #define I40E_PRTPM_GC_MNG_VETO_SHIFT 1 #define I40E_PRTPM_GC_MNG_VETO_MASK I40E_MASK(0x1, I40E_PRTPM_GC_MNG_VETO_SHIFT) #define I40E_PRTPM_GC_RATD_SHIFT 2 #define I40E_PRTPM_GC_RATD_MASK I40E_MASK(0x1, I40E_PRTPM_GC_RATD_SHIFT) #define I40E_PRTPM_GC_LCDMP_SHIFT 3 #define I40E_PRTPM_GC_LCDMP_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LCDMP_SHIFT) #define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31 #define I40E_PRTPM_GC_LPLU_ASSERTED_MASK I40E_MASK(0x1, I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT) #define I40E_PRTPM_RLPIC 0x001E43A0 /* Reset: GLOBR */ #define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0 #define I40E_PRTPM_RLPIC_ERLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_RLPIC_ERLPIC_SHIFT) #define I40E_PRTPM_TLPIC 0x001E43C0 /* Reset: GLOBR */ #define I40E_PRTPM_TLPIC_ETLPIC_SHIFT 0 #define I40E_PRTPM_TLPIC_ETLPIC_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_TLPIC_ETLPIC_SHIFT) #define I40E_GLRPB_DPSS 0x000AC828 /* Reset: CORER */ #define I40E_GLRPB_DPSS_DPS_TCN_SHIFT 0 #define I40E_GLRPB_DPSS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_DPSS_DPS_TCN_SHIFT) #define I40E_GLRPB_GHW 0x000AC830 /* Reset: CORER */ #define I40E_GLRPB_GHW_GHW_SHIFT 0 #define I40E_GLRPB_GHW_GHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GHW_GHW_SHIFT) #define I40E_GLRPB_GLW 0x000AC834 /* Reset: CORER */ #define I40E_GLRPB_GLW_GLW_SHIFT 0 #define I40E_GLRPB_GLW_GLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_GLW_GLW_SHIFT) #define I40E_GLRPB_PHW 0x000AC844 /* Reset: CORER */ #define I40E_GLRPB_PHW_PHW_SHIFT 0 #define I40E_GLRPB_PHW_PHW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PHW_PHW_SHIFT) #define I40E_GLRPB_PLW 0x000AC848 /* Reset: CORER */ #define I40E_GLRPB_PLW_PLW_SHIFT 0 #define I40E_GLRPB_PLW_PLW_MASK I40E_MASK(0xFFFFF, I40E_GLRPB_PLW_PLW_SHIFT) #define I40E_PRTRPB_DHW(_i) (0x000AC100 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTRPB_DHW_MAX_INDEX 7 #define I40E_PRTRPB_DHW_DHW_TCN_SHIFT 0 #define I40E_PRTRPB_DHW_DHW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DHW_DHW_TCN_SHIFT) #define I40E_PRTRPB_DLW(_i) (0x000AC220 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTRPB_DLW_MAX_INDEX 7 #define I40E_PRTRPB_DLW_DLW_TCN_SHIFT 0 #define I40E_PRTRPB_DLW_DLW_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DLW_DLW_TCN_SHIFT) #define I40E_PRTRPB_DPS(_i) (0x000AC320 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTRPB_DPS_MAX_INDEX 7 #define I40E_PRTRPB_DPS_DPS_TCN_SHIFT 0 #define I40E_PRTRPB_DPS_DPS_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_DPS_DPS_TCN_SHIFT) #define I40E_PRTRPB_SHT(_i) (0x000AC480 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTRPB_SHT_MAX_INDEX 7 #define I40E_PRTRPB_SHT_SHT_TCN_SHIFT 0 #define I40E_PRTRPB_SHT_SHT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHT_SHT_TCN_SHIFT) #define I40E_PRTRPB_SHW 0x000AC580 /* Reset: CORER */ #define I40E_PRTRPB_SHW_SHW_SHIFT 0 #define I40E_PRTRPB_SHW_SHW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SHW_SHW_SHIFT) #define I40E_PRTRPB_SLT(_i) (0x000AC5A0 + ((_i) * 32)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_PRTRPB_SLT_MAX_INDEX 7 #define I40E_PRTRPB_SLT_SLT_TCN_SHIFT 0 #define I40E_PRTRPB_SLT_SLT_TCN_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLT_SLT_TCN_SHIFT) #define I40E_PRTRPB_SLW 0x000AC6A0 /* Reset: CORER */ #define I40E_PRTRPB_SLW_SLW_SHIFT 0 #define I40E_PRTRPB_SLW_SLW_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SLW_SLW_SHIFT) #define I40E_PRTRPB_SPS 0x000AC7C0 /* Reset: CORER */ #define I40E_PRTRPB_SPS_SPS_SHIFT 0 #define I40E_PRTRPB_SPS_SPS_MASK I40E_MASK(0xFFFFF, I40E_PRTRPB_SPS_SPS_SHIFT) #define I40E_GLQF_CTL 0x00269BA4 /* Reset: CORER */ #define I40E_GLQF_CTL_HTOEP_SHIFT 1 #define I40E_GLQF_CTL_HTOEP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_SHIFT) #define I40E_GLQF_CTL_HTOEP_FCOE_SHIFT 2 #define I40E_GLQF_CTL_HTOEP_FCOE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_HTOEP_FCOE_SHIFT) #define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3 #define I40E_GLQF_CTL_PCNT_ALLOC_MASK I40E_MASK(0x7, I40E_GLQF_CTL_PCNT_ALLOC_SHIFT) #define I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT 6 #define I40E_GLQF_CTL_FD_AUTO_PCTYPE_MASK I40E_MASK(0x1, I40E_GLQF_CTL_FD_AUTO_PCTYPE_SHIFT) #define I40E_GLQF_CTL_RSVD_SHIFT 7 #define I40E_GLQF_CTL_RSVD_MASK I40E_MASK(0x1, I40E_GLQF_CTL_RSVD_SHIFT) #define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8 #define I40E_GLQF_CTL_MAXPEBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXPEBLEN_SHIFT) #define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11 #define I40E_GLQF_CTL_MAXFCBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFCBLEN_SHIFT) #define I40E_GLQF_CTL_MAXFDBLEN_SHIFT 14 #define I40E_GLQF_CTL_MAXFDBLEN_MASK I40E_MASK(0x7, I40E_GLQF_CTL_MAXFDBLEN_SHIFT) #define I40E_GLQF_CTL_FDBEST_SHIFT 17 #define I40E_GLQF_CTL_FDBEST_MASK I40E_MASK(0xFF, I40E_GLQF_CTL_FDBEST_SHIFT) #define I40E_GLQF_CTL_PROGPRIO_SHIFT 25 #define I40E_GLQF_CTL_PROGPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_PROGPRIO_SHIFT) #define I40E_GLQF_CTL_INVALPRIO_SHIFT 26 #define I40E_GLQF_CTL_INVALPRIO_MASK I40E_MASK(0x1, I40E_GLQF_CTL_INVALPRIO_SHIFT) #define I40E_GLQF_CTL_IGNORE_IP_SHIFT 27 #define I40E_GLQF_CTL_IGNORE_IP_MASK I40E_MASK(0x1, I40E_GLQF_CTL_IGNORE_IP_SHIFT) #define I40E_GLQF_FDCNT_0 0x00269BAC /* Reset: CORER */ #define I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT 0 #define I40E_GLQF_FDCNT_0_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_GUARANT_CNT_SHIFT) #define I40E_GLQF_FDCNT_0_BESTCNT_SHIFT 13 #define I40E_GLQF_FDCNT_0_BESTCNT_MASK I40E_MASK(0x1FFF, I40E_GLQF_FDCNT_0_BESTCNT_SHIFT) #define I40E_GLQF_HKEY(_i) (0x00270140 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */ #define I40E_GLQF_HKEY_MAX_INDEX 12 #define I40E_GLQF_HKEY_KEY_0_SHIFT 0 #define I40E_GLQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_0_SHIFT) #define I40E_GLQF_HKEY_KEY_1_SHIFT 8 #define I40E_GLQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_1_SHIFT) #define I40E_GLQF_HKEY_KEY_2_SHIFT 16 #define I40E_GLQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_2_SHIFT) #define I40E_GLQF_HKEY_KEY_3_SHIFT 24 #define I40E_GLQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_GLQF_HKEY_KEY_3_SHIFT) #define I40E_GLQF_HSYM(_i) (0x00269D00 + ((_i) * 4)) /* _i=0...63 */ /* Reset: CORER */ #define I40E_GLQF_HSYM_MAX_INDEX 63 #define I40E_GLQF_HSYM_SYMH_ENA_SHIFT 0 #define I40E_GLQF_HSYM_SYMH_ENA_MASK I40E_MASK(0x1, I40E_GLQF_HSYM_SYMH_ENA_SHIFT) #define I40E_GLQF_PCNT(_i) (0x00266800 + ((_i) * 4)) /* _i=0...511 */ /* Reset: CORER */ #define I40E_GLQF_PCNT_MAX_INDEX 511 #define I40E_GLQF_PCNT_PCNT_SHIFT 0 #define I40E_GLQF_PCNT_PCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLQF_PCNT_PCNT_SHIFT) #define I40E_GLQF_SWAP(_i, _j) (0x00267E00 + ((_i) * 4 + (_j) * 8)) /* _i=0...1, _j=0...63 */ /* Reset: CORER */ #define I40E_GLQF_SWAP_MAX_INDEX 1 #define I40E_GLQF_SWAP_OFF0_SRC0_SHIFT 0 #define I40E_GLQF_SWAP_OFF0_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC0_SHIFT) #define I40E_GLQF_SWAP_OFF0_SRC1_SHIFT 6 #define I40E_GLQF_SWAP_OFF0_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF0_SRC1_SHIFT) #define I40E_GLQF_SWAP_FLEN0_SHIFT 12 #define I40E_GLQF_SWAP_FLEN0_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN0_SHIFT) #define I40E_GLQF_SWAP_OFF1_SRC0_SHIFT 16 #define I40E_GLQF_SWAP_OFF1_SRC0_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC0_SHIFT) #define I40E_GLQF_SWAP_OFF1_SRC1_SHIFT 22 #define I40E_GLQF_SWAP_OFF1_SRC1_MASK I40E_MASK(0x3F, I40E_GLQF_SWAP_OFF1_SRC1_SHIFT) #define I40E_GLQF_SWAP_FLEN1_SHIFT 28 #define I40E_GLQF_SWAP_FLEN1_MASK I40E_MASK(0xF, I40E_GLQF_SWAP_FLEN1_SHIFT) #define I40E_PFQF_CTL_0 0x001C0AC0 /* Reset: CORER */ #define I40E_PFQF_CTL_0_PEHSIZE_SHIFT 0 #define I40E_PFQF_CTL_0_PEHSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEHSIZE_SHIFT) #define I40E_PFQF_CTL_0_PEDSIZE_SHIFT 5 #define I40E_PFQF_CTL_0_PEDSIZE_MASK I40E_MASK(0x1F, I40E_PFQF_CTL_0_PEDSIZE_SHIFT) #define I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT 10 #define I40E_PFQF_CTL_0_PFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_PFFCHSIZE_SHIFT) #define I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT 14 #define I40E_PFQF_CTL_0_PFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_PFFCDSIZE_SHIFT) #define I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT 16 #define I40E_PFQF_CTL_0_HASHLUTSIZE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_HASHLUTSIZE_SHIFT) #define I40E_PFQF_CTL_0_FD_ENA_SHIFT 17 #define I40E_PFQF_CTL_0_FD_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_FD_ENA_SHIFT) #define I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT 18 #define I40E_PFQF_CTL_0_ETYPE_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_ETYPE_ENA_SHIFT) #define I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT 19 #define I40E_PFQF_CTL_0_MACVLAN_ENA_MASK I40E_MASK(0x1, I40E_PFQF_CTL_0_MACVLAN_ENA_SHIFT) #define I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT 20 #define I40E_PFQF_CTL_0_VFFCHSIZE_MASK I40E_MASK(0xF, I40E_PFQF_CTL_0_VFFCHSIZE_SHIFT) #define I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT 24 #define I40E_PFQF_CTL_0_VFFCDSIZE_MASK I40E_MASK(0x3, I40E_PFQF_CTL_0_VFFCDSIZE_SHIFT) #define I40E_PFQF_CTL_1 0x00245D80 /* Reset: CORER */ #define I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT 0 #define I40E_PFQF_CTL_1_CLEARFDTABLE_MASK I40E_MASK(0x1, I40E_PFQF_CTL_1_CLEARFDTABLE_SHIFT) #define I40E_PFQF_FDALLOC 0x00246280 /* Reset: CORER */ #define I40E_PFQF_FDALLOC_FDALLOC_SHIFT 0 #define I40E_PFQF_FDALLOC_FDALLOC_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDALLOC_SHIFT) #define I40E_PFQF_FDALLOC_FDBEST_SHIFT 8 #define I40E_PFQF_FDALLOC_FDBEST_MASK I40E_MASK(0xFF, I40E_PFQF_FDALLOC_FDBEST_SHIFT) #define I40E_PFQF_FDSTAT 0x00246380 /* Reset: CORER */ #define I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT 0 #define I40E_PFQF_FDSTAT_GUARANT_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT) #define I40E_PFQF_FDSTAT_BEST_CNT_SHIFT 16 #define I40E_PFQF_FDSTAT_BEST_CNT_MASK I40E_MASK(0x1FFF, I40E_PFQF_FDSTAT_BEST_CNT_SHIFT) #define I40E_PFQF_HENA(_i) (0x00245900 + ((_i) * 128)) /* _i=0...1 */ /* Reset: CORER */ #define I40E_PFQF_HENA_MAX_INDEX 1 #define I40E_PFQF_HENA_PTYPE_ENA_SHIFT 0 #define I40E_PFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_PFQF_HENA_PTYPE_ENA_SHIFT) #define I40E_PFQF_HKEY(_i) (0x00244800 + ((_i) * 128)) /* _i=0...12 */ /* Reset: CORER */ #define I40E_PFQF_HKEY_MAX_INDEX 12 #define I40E_PFQF_HKEY_KEY_0_SHIFT 0 #define I40E_PFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_0_SHIFT) #define I40E_PFQF_HKEY_KEY_1_SHIFT 8 #define I40E_PFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_1_SHIFT) #define I40E_PFQF_HKEY_KEY_2_SHIFT 16 #define I40E_PFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_2_SHIFT) #define I40E_PFQF_HKEY_KEY_3_SHIFT 24 #define I40E_PFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_PFQF_HKEY_KEY_3_SHIFT) #define I40E_PFQF_HLUT(_i) (0x00240000 + ((_i) * 128)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_PFQF_HLUT_MAX_INDEX 127 #define I40E_PFQF_HLUT_LUT0_SHIFT 0 #define I40E_PFQF_HLUT_LUT0_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT0_SHIFT) #define I40E_PFQF_HLUT_LUT1_SHIFT 8 #define I40E_PFQF_HLUT_LUT1_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT1_SHIFT) #define I40E_PFQF_HLUT_LUT2_SHIFT 16 #define I40E_PFQF_HLUT_LUT2_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT2_SHIFT) #define I40E_PFQF_HLUT_LUT3_SHIFT 24 #define I40E_PFQF_HLUT_LUT3_MASK I40E_MASK(0x3F, I40E_PFQF_HLUT_LUT3_SHIFT) #define I40E_PRTQF_CTL_0 0x00256E60 /* Reset: CORER */ #define I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT 0 #define I40E_PRTQF_CTL_0_HSYM_ENA_MASK I40E_MASK(0x1, I40E_PRTQF_CTL_0_HSYM_ENA_SHIFT) #define I40E_PRTQF_FD_FLXINSET(_i) (0x00253800 + ((_i) * 32)) /* _i=0...63 */ /* Reset: CORER */ #define I40E_PRTQF_FD_FLXINSET_MAX_INDEX 63 #define I40E_PRTQF_FD_FLXINSET_INSET_SHIFT 0 #define I40E_PRTQF_FD_FLXINSET_INSET_MASK I40E_MASK(0xFF, I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) #define I40E_PRTQF_FD_MSK(_i, _j) (0x00252000 + ((_i) * 64 + (_j) * 32)) /* _i=0...63, _j=0...1 */ /* Reset: CORER */ #define I40E_PRTQF_FD_MSK_MAX_INDEX 63 #define I40E_PRTQF_FD_MSK_MASK_SHIFT 0 #define I40E_PRTQF_FD_MSK_MASK_MASK I40E_MASK(0xFFFF, I40E_PRTQF_FD_MSK_MASK_SHIFT) #define I40E_PRTQF_FD_MSK_OFFSET_SHIFT 16 #define I40E_PRTQF_FD_MSK_OFFSET_MASK I40E_MASK(0x3F, I40E_PRTQF_FD_MSK_OFFSET_SHIFT) #define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */ /* Reset: CORER */ #define I40E_PRTQF_FLX_PIT_MAX_INDEX 8 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) #define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5 #define I40E_PRTQF_FLX_PIT_FSIZE_MASK I40E_MASK(0x1F, I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) #define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10 #define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK I40E_MASK(0x3F, I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) #define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...1, _VF=0...127 */ /* Reset: CORER */ #define I40E_VFQF_HENA1_MAX_INDEX 1 #define I40E_VFQF_HENA1_PTYPE_ENA_SHIFT 0 #define I40E_VFQF_HENA1_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA1_PTYPE_ENA_SHIFT) #define I40E_VFQF_HKEY1(_i, _VF) (0x00228000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...12, _VF=0...127 */ /* Reset: CORER */ #define I40E_VFQF_HKEY1_MAX_INDEX 12 #define I40E_VFQF_HKEY1_KEY_0_SHIFT 0 #define I40E_VFQF_HKEY1_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_0_SHIFT) #define I40E_VFQF_HKEY1_KEY_1_SHIFT 8 #define I40E_VFQF_HKEY1_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_1_SHIFT) #define I40E_VFQF_HKEY1_KEY_2_SHIFT 16 #define I40E_VFQF_HKEY1_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_2_SHIFT) #define I40E_VFQF_HKEY1_KEY_3_SHIFT 24 #define I40E_VFQF_HKEY1_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY1_KEY_3_SHIFT) #define I40E_VFQF_HLUT1(_i, _VF) (0x00220000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...15, _VF=0...127 */ /* Reset: CORER */ #define I40E_VFQF_HLUT1_MAX_INDEX 15 #define I40E_VFQF_HLUT1_LUT0_SHIFT 0 #define I40E_VFQF_HLUT1_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT0_SHIFT) #define I40E_VFQF_HLUT1_LUT1_SHIFT 8 #define I40E_VFQF_HLUT1_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT1_SHIFT) #define I40E_VFQF_HLUT1_LUT2_SHIFT 16 #define I40E_VFQF_HLUT1_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT2_SHIFT) #define I40E_VFQF_HLUT1_LUT3_SHIFT 24 #define I40E_VFQF_HLUT1_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT1_LUT3_SHIFT) #define I40E_VFQF_HREGION1(_i, _VF) (0x0022E000 + ((_i) * 1024 + (_VF) * 4)) /* _i=0...7, _VF=0...127 */ /* Reset: CORER */ #define I40E_VFQF_HREGION1_MAX_INDEX 7 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT 0 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_0_SHIFT) #define I40E_VFQF_HREGION1_REGION_0_SHIFT 1 #define I40E_VFQF_HREGION1_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_0_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT 4 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_1_SHIFT) #define I40E_VFQF_HREGION1_REGION_1_SHIFT 5 #define I40E_VFQF_HREGION1_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_1_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT 8 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_2_SHIFT) #define I40E_VFQF_HREGION1_REGION_2_SHIFT 9 #define I40E_VFQF_HREGION1_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_2_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT 12 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_3_SHIFT) #define I40E_VFQF_HREGION1_REGION_3_SHIFT 13 #define I40E_VFQF_HREGION1_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_3_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT 16 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_4_SHIFT) #define I40E_VFQF_HREGION1_REGION_4_SHIFT 17 #define I40E_VFQF_HREGION1_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_4_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT 20 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_5_SHIFT) #define I40E_VFQF_HREGION1_REGION_5_SHIFT 21 #define I40E_VFQF_HREGION1_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_5_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT 24 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_6_SHIFT) #define I40E_VFQF_HREGION1_REGION_6_SHIFT 25 #define I40E_VFQF_HREGION1_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_6_SHIFT) #define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT 28 #define I40E_VFQF_HREGION1_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION1_OVERRIDE_ENA_7_SHIFT) #define I40E_VFQF_HREGION1_REGION_7_SHIFT 29 #define I40E_VFQF_HREGION1_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION1_REGION_7_SHIFT) #define I40E_VPQF_CTL(_VF) (0x001C0000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: VFR */ #define I40E_VPQF_CTL_MAX_INDEX 127 #define I40E_VPQF_CTL_PEHSIZE_SHIFT 0 #define I40E_VPQF_CTL_PEHSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEHSIZE_SHIFT) #define I40E_VPQF_CTL_PEDSIZE_SHIFT 5 #define I40E_VPQF_CTL_PEDSIZE_MASK I40E_MASK(0x1F, I40E_VPQF_CTL_PEDSIZE_SHIFT) #define I40E_VPQF_CTL_FCHSIZE_SHIFT 10 #define I40E_VPQF_CTL_FCHSIZE_MASK I40E_MASK(0xF, I40E_VPQF_CTL_FCHSIZE_SHIFT) #define I40E_VPQF_CTL_FCDSIZE_SHIFT 14 #define I40E_VPQF_CTL_FCDSIZE_MASK I40E_MASK(0x3, I40E_VPQF_CTL_FCDSIZE_SHIFT) #define I40E_VSIQF_CTL(_VSI) (0x0020D800 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: PFR */ #define I40E_VSIQF_CTL_MAX_INDEX 383 #define I40E_VSIQF_CTL_FCOE_ENA_SHIFT 0 #define I40E_VSIQF_CTL_FCOE_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_FCOE_ENA_SHIFT) #define I40E_VSIQF_CTL_PETCP_ENA_SHIFT 1 #define I40E_VSIQF_CTL_PETCP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PETCP_ENA_SHIFT) #define I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT 2 #define I40E_VSIQF_CTL_PEUUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUUDP_ENA_SHIFT) #define I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT 3 #define I40E_VSIQF_CTL_PEMUDP_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMUDP_ENA_SHIFT) #define I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT 4 #define I40E_VSIQF_CTL_PEUFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEUFRAG_ENA_SHIFT) #define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5 #define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK I40E_MASK(0x1, I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT) #define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4)) /* _i=0...3, _VSI=0...383 */ /* Reset: PFR */ #define I40E_VSIQF_TCREGION_MAX_INDEX 3 #define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0 #define I40E_VSIQF_TCREGION_TC_OFFSET_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT) #define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9 #define I40E_VSIQF_TCREGION_TC_SIZE_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE_SHIFT) #define I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT 16 #define I40E_VSIQF_TCREGION_TC_OFFSET2_MASK I40E_MASK(0x1FF, I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT) #define I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT 25 #define I40E_VSIQF_TCREGION_TC_SIZE2_MASK I40E_MASK(0x7, I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT) #define I40E_GL_FCOECRC(_i) (0x00314d80 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOECRC_MAX_INDEX 143 #define I40E_GL_FCOECRC_FCOECRC_SHIFT 0 #define I40E_GL_FCOECRC_FCOECRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOECRC_FCOECRC_SHIFT) #define I40E_GL_FCOEDDPC(_i) (0x00314480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDDPC_MAX_INDEX 143 #define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0 #define I40E_GL_FCOEDDPC_FCOEDDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT) #define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDIFEC_MAX_INDEX 143 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT) #define I40E_GL_FCOEDIFTCL(_i) (0x00354000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDIFTCL_MAX_INDEX 143 #define I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT 0 #define I40E_GL_FCOEDIFTCL_FCOEDIFTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIFTCL_FCOEDIFTC_SHIFT) #define I40E_GL_FCOEDIXEC(_i) (0x0034c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDIXEC_MAX_INDEX 143 #define I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT 0 #define I40E_GL_FCOEDIXEC_FCOEDIXEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXEC_FCOEDIXEC_SHIFT) #define I40E_GL_FCOEDIXVC(_i) (0x00350000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDIXVC_MAX_INDEX 143 #define I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT 0 #define I40E_GL_FCOEDIXVC_FCOEDIXVC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDIXVC_FCOEDIXVC_SHIFT) #define I40E_GL_FCOEDWRCH(_i) (0x00320004 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDWRCH_MAX_INDEX 143 #define I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT 0 #define I40E_GL_FCOEDWRCH_FCOEDWRCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWRCH_FCOEDWRCH_SHIFT) #define I40E_GL_FCOEDWRCL(_i) (0x00320000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDWRCL_MAX_INDEX 143 #define I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT 0 #define I40E_GL_FCOEDWRCL_FCOEDWRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWRCL_FCOEDWRCL_SHIFT) #define I40E_GL_FCOEDWTCH(_i) (0x00348084 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDWTCH_MAX_INDEX 143 #define I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT 0 #define I40E_GL_FCOEDWTCH_FCOEDWTCH_MASK I40E_MASK(0xFFFF, I40E_GL_FCOEDWTCH_FCOEDWTCH_SHIFT) #define I40E_GL_FCOEDWTCL(_i) (0x00348080 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEDWTCL_MAX_INDEX 143 #define I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT 0 #define I40E_GL_FCOEDWTCL_FCOEDWTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEDWTCL_FCOEDWTCL_SHIFT) #define I40E_GL_FCOELAST(_i) (0x00314000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOELAST_MAX_INDEX 143 #define I40E_GL_FCOELAST_FCOELAST_SHIFT 0 #define I40E_GL_FCOELAST_FCOELAST_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOELAST_FCOELAST_SHIFT) #define I40E_GL_FCOEPRC(_i) (0x00315200 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEPRC_MAX_INDEX 143 #define I40E_GL_FCOEPRC_FCOEPRC_SHIFT 0 #define I40E_GL_FCOEPRC_FCOEPRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPRC_FCOEPRC_SHIFT) #define I40E_GL_FCOEPTC(_i) (0x00344C00 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOEPTC_MAX_INDEX 143 #define I40E_GL_FCOEPTC_FCOEPTC_SHIFT 0 #define I40E_GL_FCOEPTC_FCOEPTC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOEPTC_FCOEPTC_SHIFT) #define I40E_GL_FCOERPDC(_i) (0x00324000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_FCOERPDC_MAX_INDEX 143 #define I40E_GL_FCOERPDC_FCOERPDC_SHIFT 0 #define I40E_GL_FCOERPDC_FCOERPDC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_FCOERPDC_FCOERPDC_SHIFT) #define I40E_GL_RXERR1_L(_i) (0x00318000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_RXERR1_L_MAX_INDEX 143 #define I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT 0 #define I40E_GL_RXERR1_L_FCOEDIFRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR1_L_FCOEDIFRC_SHIFT) #define I40E_GL_RXERR2_L(_i) (0x0031c000 + ((_i) * 8)) /* _i=0...143 */ /* Reset: CORER */ #define I40E_GL_RXERR2_L_MAX_INDEX 143 #define I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT 0 #define I40E_GL_RXERR2_L_FCOEDIXAC_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_RXERR2_L_FCOEDIXAC_SHIFT) #define I40E_GLPRT_BPRCH(_i) (0x003005E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_BPRCH_MAX_INDEX 3 #define I40E_GLPRT_BPRCH_BPRCH_SHIFT 0 #define I40E_GLPRT_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPRCH_BPRCH_SHIFT) #define I40E_GLPRT_BPRCL(_i) (0x003005E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_BPRCL_MAX_INDEX 3 #define I40E_GLPRT_BPRCL_BPRCL_SHIFT 0 #define I40E_GLPRT_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPRCL_BPRCL_SHIFT) #define I40E_GLPRT_BPTCH(_i) (0x00300A04 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_BPTCH_MAX_INDEX 3 #define I40E_GLPRT_BPTCH_BPTCH_SHIFT 0 #define I40E_GLPRT_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_BPTCH_BPTCH_SHIFT) #define I40E_GLPRT_BPTCL(_i) (0x00300A00 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_BPTCL_MAX_INDEX 3 #define I40E_GLPRT_BPTCL_BPTCL_SHIFT 0 #define I40E_GLPRT_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_BPTCL_BPTCL_SHIFT) #define I40E_GLPRT_CRCERRS(_i) (0x00300080 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_CRCERRS_MAX_INDEX 3 #define I40E_GLPRT_CRCERRS_CRCERRS_SHIFT 0 #define I40E_GLPRT_CRCERRS_CRCERRS_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_CRCERRS_CRCERRS_SHIFT) #define I40E_GLPRT_GORCH(_i) (0x00300004 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_GORCH_MAX_INDEX 3 #define I40E_GLPRT_GORCH_GORCH_SHIFT 0 #define I40E_GLPRT_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GORCH_GORCH_SHIFT) #define I40E_GLPRT_GORCL(_i) (0x00300000 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_GORCL_MAX_INDEX 3 #define I40E_GLPRT_GORCL_GORCL_SHIFT 0 #define I40E_GLPRT_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GORCL_GORCL_SHIFT) #define I40E_GLPRT_GOTCH(_i) (0x00300684 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_GOTCH_MAX_INDEX 3 #define I40E_GLPRT_GOTCH_GOTCH_SHIFT 0 #define I40E_GLPRT_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_GOTCH_GOTCH_SHIFT) #define I40E_GLPRT_GOTCL(_i) (0x00300680 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_GOTCL_MAX_INDEX 3 #define I40E_GLPRT_GOTCL_GOTCL_SHIFT 0 #define I40E_GLPRT_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_GOTCL_GOTCL_SHIFT) #define I40E_GLPRT_ILLERRC(_i) (0x003000E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_ILLERRC_MAX_INDEX 3 #define I40E_GLPRT_ILLERRC_ILLERRC_SHIFT 0 #define I40E_GLPRT_ILLERRC_ILLERRC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ILLERRC_ILLERRC_SHIFT) #define I40E_GLPRT_LDPC(_i) (0x00300620 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_LDPC_MAX_INDEX 3 #define I40E_GLPRT_LDPC_LDPC_SHIFT 0 #define I40E_GLPRT_LDPC_LDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LDPC_LDPC_SHIFT) #define I40E_GLPRT_LXOFFRXC(_i) (0x00300160 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_LXOFFRXC_MAX_INDEX 3 #define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT 0 #define I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFRXC_LXOFFRXCNT_SHIFT) #define I40E_GLPRT_LXOFFTXC(_i) (0x003009A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_LXOFFTXC_MAX_INDEX 3 #define I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT 0 #define I40E_GLPRT_LXOFFTXC_LXOFFTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXOFFTXC_LXOFFTXC_SHIFT) #define I40E_GLPRT_LXONRXC(_i) (0x00300140 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_LXONRXC_MAX_INDEX 3 #define I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT 0 #define I40E_GLPRT_LXONRXC_LXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONRXC_LXONRXCNT_SHIFT) #define I40E_GLPRT_LXONTXC(_i) (0x00300980 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_LXONTXC_MAX_INDEX 3 #define I40E_GLPRT_LXONTXC_LXONTXC_SHIFT 0 #define I40E_GLPRT_LXONTXC_LXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_LXONTXC_LXONTXC_SHIFT) #define I40E_GLPRT_MLFC(_i) (0x00300020 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MLFC_MAX_INDEX 3 #define I40E_GLPRT_MLFC_MLFC_SHIFT 0 #define I40E_GLPRT_MLFC_MLFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MLFC_MLFC_SHIFT) #define I40E_GLPRT_MPRCH(_i) (0x003005C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MPRCH_MAX_INDEX 3 #define I40E_GLPRT_MPRCH_MPRCH_SHIFT 0 #define I40E_GLPRT_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPRCH_MPRCH_SHIFT) #define I40E_GLPRT_MPRCL(_i) (0x003005C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MPRCL_MAX_INDEX 3 #define I40E_GLPRT_MPRCL_MPRCL_SHIFT 0 #define I40E_GLPRT_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPRCL_MPRCL_SHIFT) #define I40E_GLPRT_MPTCH(_i) (0x003009E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MPTCH_MAX_INDEX 3 #define I40E_GLPRT_MPTCH_MPTCH_SHIFT 0 #define I40E_GLPRT_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_MPTCH_MPTCH_SHIFT) #define I40E_GLPRT_MPTCL(_i) (0x003009E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MPTCL_MAX_INDEX 3 #define I40E_GLPRT_MPTCL_MPTCL_SHIFT 0 #define I40E_GLPRT_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MPTCL_MPTCL_SHIFT) #define I40E_GLPRT_MRFC(_i) (0x00300040 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_MRFC_MAX_INDEX 3 #define I40E_GLPRT_MRFC_MRFC_SHIFT 0 #define I40E_GLPRT_MRFC_MRFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_MRFC_MRFC_SHIFT) #define I40E_GLPRT_PRC1023H(_i) (0x00300504 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC1023H_MAX_INDEX 3 #define I40E_GLPRT_PRC1023H_PRC1023H_SHIFT 0 #define I40E_GLPRT_PRC1023H_PRC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1023H_PRC1023H_SHIFT) #define I40E_GLPRT_PRC1023L(_i) (0x00300500 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC1023L_MAX_INDEX 3 #define I40E_GLPRT_PRC1023L_PRC1023L_SHIFT 0 #define I40E_GLPRT_PRC1023L_PRC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1023L_PRC1023L_SHIFT) #define I40E_GLPRT_PRC127H(_i) (0x003004A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC127H_MAX_INDEX 3 #define I40E_GLPRT_PRC127H_PRC127H_SHIFT 0 #define I40E_GLPRT_PRC127H_PRC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC127H_PRC127H_SHIFT) #define I40E_GLPRT_PRC127L(_i) (0x003004A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC127L_MAX_INDEX 3 #define I40E_GLPRT_PRC127L_PRC127L_SHIFT 0 #define I40E_GLPRT_PRC127L_PRC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC127L_PRC127L_SHIFT) #define I40E_GLPRT_PRC1522H(_i) (0x00300524 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC1522H_MAX_INDEX 3 #define I40E_GLPRT_PRC1522H_PRC1522H_SHIFT 0 #define I40E_GLPRT_PRC1522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC1522H_PRC1522H_SHIFT) #define I40E_GLPRT_PRC1522L(_i) (0x00300520 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC1522L_MAX_INDEX 3 #define I40E_GLPRT_PRC1522L_PRC1522L_SHIFT 0 #define I40E_GLPRT_PRC1522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC1522L_PRC1522L_SHIFT) #define I40E_GLPRT_PRC255H(_i) (0x003004C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC255H_MAX_INDEX 3 #define I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT 0 #define I40E_GLPRT_PRC255H_PRTPRC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC255H_PRTPRC255H_SHIFT) #define I40E_GLPRT_PRC255L(_i) (0x003004C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC255L_MAX_INDEX 3 #define I40E_GLPRT_PRC255L_PRC255L_SHIFT 0 #define I40E_GLPRT_PRC255L_PRC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC255L_PRC255L_SHIFT) #define I40E_GLPRT_PRC511H(_i) (0x003004E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC511H_MAX_INDEX 3 #define I40E_GLPRT_PRC511H_PRC511H_SHIFT 0 #define I40E_GLPRT_PRC511H_PRC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC511H_PRC511H_SHIFT) #define I40E_GLPRT_PRC511L(_i) (0x003004E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC511L_MAX_INDEX 3 #define I40E_GLPRT_PRC511L_PRC511L_SHIFT 0 #define I40E_GLPRT_PRC511L_PRC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC511L_PRC511L_SHIFT) #define I40E_GLPRT_PRC64H(_i) (0x00300484 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC64H_MAX_INDEX 3 #define I40E_GLPRT_PRC64H_PRC64H_SHIFT 0 #define I40E_GLPRT_PRC64H_PRC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC64H_PRC64H_SHIFT) #define I40E_GLPRT_PRC64L(_i) (0x00300480 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC64L_MAX_INDEX 3 #define I40E_GLPRT_PRC64L_PRC64L_SHIFT 0 #define I40E_GLPRT_PRC64L_PRC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC64L_PRC64L_SHIFT) #define I40E_GLPRT_PRC9522H(_i) (0x00300544 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC9522H_MAX_INDEX 3 #define I40E_GLPRT_PRC9522H_PRC1522H_SHIFT 0 #define I40E_GLPRT_PRC9522H_PRC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PRC9522H_PRC1522H_SHIFT) #define I40E_GLPRT_PRC9522L(_i) (0x00300540 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PRC9522L_MAX_INDEX 3 #define I40E_GLPRT_PRC9522L_PRC1522L_SHIFT 0 #define I40E_GLPRT_PRC9522L_PRC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PRC9522L_PRC1522L_SHIFT) #define I40E_GLPRT_PTC1023H(_i) (0x00300724 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC1023H_MAX_INDEX 3 #define I40E_GLPRT_PTC1023H_PTC1023H_SHIFT 0 #define I40E_GLPRT_PTC1023H_PTC1023H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1023H_PTC1023H_SHIFT) #define I40E_GLPRT_PTC1023L(_i) (0x00300720 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC1023L_MAX_INDEX 3 #define I40E_GLPRT_PTC1023L_PTC1023L_SHIFT 0 #define I40E_GLPRT_PTC1023L_PTC1023L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1023L_PTC1023L_SHIFT) #define I40E_GLPRT_PTC127H(_i) (0x003006C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC127H_MAX_INDEX 3 #define I40E_GLPRT_PTC127H_PTC127H_SHIFT 0 #define I40E_GLPRT_PTC127H_PTC127H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC127H_PTC127H_SHIFT) #define I40E_GLPRT_PTC127L(_i) (0x003006C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC127L_MAX_INDEX 3 #define I40E_GLPRT_PTC127L_PTC127L_SHIFT 0 #define I40E_GLPRT_PTC127L_PTC127L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC127L_PTC127L_SHIFT) #define I40E_GLPRT_PTC1522H(_i) (0x00300744 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC1522H_MAX_INDEX 3 #define I40E_GLPRT_PTC1522H_PTC1522H_SHIFT 0 #define I40E_GLPRT_PTC1522H_PTC1522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC1522H_PTC1522H_SHIFT) #define I40E_GLPRT_PTC1522L(_i) (0x00300740 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC1522L_MAX_INDEX 3 #define I40E_GLPRT_PTC1522L_PTC1522L_SHIFT 0 #define I40E_GLPRT_PTC1522L_PTC1522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC1522L_PTC1522L_SHIFT) #define I40E_GLPRT_PTC255H(_i) (0x003006E4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC255H_MAX_INDEX 3 #define I40E_GLPRT_PTC255H_PTC255H_SHIFT 0 #define I40E_GLPRT_PTC255H_PTC255H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC255H_PTC255H_SHIFT) #define I40E_GLPRT_PTC255L(_i) (0x003006E0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC255L_MAX_INDEX 3 #define I40E_GLPRT_PTC255L_PTC255L_SHIFT 0 #define I40E_GLPRT_PTC255L_PTC255L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC255L_PTC255L_SHIFT) #define I40E_GLPRT_PTC511H(_i) (0x00300704 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC511H_MAX_INDEX 3 #define I40E_GLPRT_PTC511H_PTC511H_SHIFT 0 #define I40E_GLPRT_PTC511H_PTC511H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC511H_PTC511H_SHIFT) #define I40E_GLPRT_PTC511L(_i) (0x00300700 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC511L_MAX_INDEX 3 #define I40E_GLPRT_PTC511L_PTC511L_SHIFT 0 #define I40E_GLPRT_PTC511L_PTC511L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC511L_PTC511L_SHIFT) #define I40E_GLPRT_PTC64H(_i) (0x003006A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC64H_MAX_INDEX 3 #define I40E_GLPRT_PTC64H_PTC64H_SHIFT 0 #define I40E_GLPRT_PTC64H_PTC64H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC64H_PTC64H_SHIFT) #define I40E_GLPRT_PTC64L(_i) (0x003006A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC64L_MAX_INDEX 3 #define I40E_GLPRT_PTC64L_PTC64L_SHIFT 0 #define I40E_GLPRT_PTC64L_PTC64L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC64L_PTC64L_SHIFT) #define I40E_GLPRT_PTC9522H(_i) (0x00300764 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC9522H_MAX_INDEX 3 #define I40E_GLPRT_PTC9522H_PTC9522H_SHIFT 0 #define I40E_GLPRT_PTC9522H_PTC9522H_MASK I40E_MASK(0xFFFF, I40E_GLPRT_PTC9522H_PTC9522H_SHIFT) #define I40E_GLPRT_PTC9522L(_i) (0x00300760 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_PTC9522L_MAX_INDEX 3 #define I40E_GLPRT_PTC9522L_PTC9522L_SHIFT 0 #define I40E_GLPRT_PTC9522L_PTC9522L_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PTC9522L_PTC9522L_SHIFT) #define I40E_GLPRT_PXOFFRXC(_i, _j) (0x00300280 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */ #define I40E_GLPRT_PXOFFRXC_MAX_INDEX 3 #define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT 0 #define I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFRXC_PRPXOFFRXCNT_SHIFT) #define I40E_GLPRT_PXOFFTXC(_i, _j) (0x00300880 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */ #define I40E_GLPRT_PXOFFTXC_MAX_INDEX 3 #define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT 0 #define I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXOFFTXC_PRPXOFFTXCNT_SHIFT) #define I40E_GLPRT_PXONRXC(_i, _j) (0x00300180 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */ #define I40E_GLPRT_PXONRXC_MAX_INDEX 3 #define I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT 0 #define I40E_GLPRT_PXONRXC_PRPXONRXCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONRXC_PRPXONRXCNT_SHIFT) #define I40E_GLPRT_PXONTXC(_i, _j) (0x00300780 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */ #define I40E_GLPRT_PXONTXC_MAX_INDEX 3 #define I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT 0 #define I40E_GLPRT_PXONTXC_PRPXONTXC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_PXONTXC_PRPXONTXC_SHIFT) #define I40E_GLPRT_RDPC(_i) (0x00300600 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RDPC_MAX_INDEX 3 #define I40E_GLPRT_RDPC_RDPC_SHIFT 0 #define I40E_GLPRT_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RDPC_RDPC_SHIFT) #define I40E_GLPRT_RFC(_i) (0x00300560 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RFC_MAX_INDEX 3 #define I40E_GLPRT_RFC_RFC_SHIFT 0 #define I40E_GLPRT_RFC_RFC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RFC_RFC_SHIFT) #define I40E_GLPRT_RJC(_i) (0x00300580 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RJC_MAX_INDEX 3 #define I40E_GLPRT_RJC_RJC_SHIFT 0 #define I40E_GLPRT_RJC_RJC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RJC_RJC_SHIFT) #define I40E_GLPRT_RLEC(_i) (0x003000A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RLEC_MAX_INDEX 3 #define I40E_GLPRT_RLEC_RLEC_SHIFT 0 #define I40E_GLPRT_RLEC_RLEC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RLEC_RLEC_SHIFT) #define I40E_GLPRT_ROC(_i) (0x00300120 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_ROC_MAX_INDEX 3 #define I40E_GLPRT_ROC_ROC_SHIFT 0 #define I40E_GLPRT_ROC_ROC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_ROC_ROC_SHIFT) #define I40E_GLPRT_RUC(_i) (0x00300100 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RUC_MAX_INDEX 3 #define I40E_GLPRT_RUC_RUC_SHIFT 0 #define I40E_GLPRT_RUC_RUC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUC_RUC_SHIFT) #define I40E_GLPRT_RUPP(_i) (0x00300660 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_RUPP_MAX_INDEX 3 #define I40E_GLPRT_RUPP_RUPP_SHIFT 0 #define I40E_GLPRT_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RUPP_RUPP_SHIFT) #define I40E_GLPRT_RXON2OFFCNT(_i, _j) (0x00300380 + ((_i) * 8 + (_j) * 32)) /* _i=0...3, _j=0...7 */ /* Reset: CORER */ #define I40E_GLPRT_RXON2OFFCNT_MAX_INDEX 3 #define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT 0 #define I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_RXON2OFFCNT_PRRXON2OFFCNT_SHIFT) #define I40E_GLPRT_TDOLD(_i) (0x00300A20 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_TDOLD_MAX_INDEX 3 #define I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT 0 #define I40E_GLPRT_TDOLD_GLPRT_TDOLD_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_TDOLD_GLPRT_TDOLD_SHIFT) #define I40E_GLPRT_UPRCH(_i) (0x003005A4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_UPRCH_MAX_INDEX 3 #define I40E_GLPRT_UPRCH_UPRCH_SHIFT 0 #define I40E_GLPRT_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPRCH_UPRCH_SHIFT) #define I40E_GLPRT_UPRCL(_i) (0x003005A0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_UPRCL_MAX_INDEX 3 #define I40E_GLPRT_UPRCL_UPRCL_SHIFT 0 #define I40E_GLPRT_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPRCL_UPRCL_SHIFT) #define I40E_GLPRT_UPTCH(_i) (0x003009C4 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_UPTCH_MAX_INDEX 3 #define I40E_GLPRT_UPTCH_UPTCH_SHIFT 0 #define I40E_GLPRT_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLPRT_UPTCH_UPTCH_SHIFT) #define I40E_GLPRT_UPTCL(_i) (0x003009C0 + ((_i) * 8)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_GLPRT_UPTCL_MAX_INDEX 3 #define I40E_GLPRT_UPTCL_VUPTCH_SHIFT 0 #define I40E_GLPRT_UPTCL_VUPTCH_MASK I40E_MASK(0xFFFFFFFF, I40E_GLPRT_UPTCL_VUPTCH_SHIFT) #define I40E_GLSW_BPRCH(_i) (0x00370104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_BPRCH_MAX_INDEX 15 #define I40E_GLSW_BPRCH_BPRCH_SHIFT 0 #define I40E_GLSW_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPRCH_BPRCH_SHIFT) #define I40E_GLSW_BPRCL(_i) (0x00370100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_BPRCL_MAX_INDEX 15 #define I40E_GLSW_BPRCL_BPRCL_SHIFT 0 #define I40E_GLSW_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPRCL_BPRCL_SHIFT) #define I40E_GLSW_BPTCH(_i) (0x00340104 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_BPTCH_MAX_INDEX 15 #define I40E_GLSW_BPTCH_BPTCH_SHIFT 0 #define I40E_GLSW_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_BPTCH_BPTCH_SHIFT) #define I40E_GLSW_BPTCL(_i) (0x00340100 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_BPTCL_MAX_INDEX 15 #define I40E_GLSW_BPTCL_BPTCL_SHIFT 0 #define I40E_GLSW_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_BPTCL_BPTCL_SHIFT) #define I40E_GLSW_GORCH(_i) (0x0035C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_GORCH_MAX_INDEX 15 #define I40E_GLSW_GORCH_GORCH_SHIFT 0 #define I40E_GLSW_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GORCH_GORCH_SHIFT) #define I40E_GLSW_GORCL(_i) (0x0035c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_GORCL_MAX_INDEX 15 #define I40E_GLSW_GORCL_GORCL_SHIFT 0 #define I40E_GLSW_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GORCL_GORCL_SHIFT) #define I40E_GLSW_GOTCH(_i) (0x0032C004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_GOTCH_MAX_INDEX 15 #define I40E_GLSW_GOTCH_GOTCH_SHIFT 0 #define I40E_GLSW_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_GOTCH_GOTCH_SHIFT) #define I40E_GLSW_GOTCL(_i) (0x0032c000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_GOTCL_MAX_INDEX 15 #define I40E_GLSW_GOTCL_GOTCL_SHIFT 0 #define I40E_GLSW_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_GOTCL_GOTCL_SHIFT) #define I40E_GLSW_MPRCH(_i) (0x00370084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_MPRCH_MAX_INDEX 15 #define I40E_GLSW_MPRCH_MPRCH_SHIFT 0 #define I40E_GLSW_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPRCH_MPRCH_SHIFT) #define I40E_GLSW_MPRCL(_i) (0x00370080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_MPRCL_MAX_INDEX 15 #define I40E_GLSW_MPRCL_MPRCL_SHIFT 0 #define I40E_GLSW_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPRCL_MPRCL_SHIFT) #define I40E_GLSW_MPTCH(_i) (0x00340084 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_MPTCH_MAX_INDEX 15 #define I40E_GLSW_MPTCH_MPTCH_SHIFT 0 #define I40E_GLSW_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_MPTCH_MPTCH_SHIFT) #define I40E_GLSW_MPTCL(_i) (0x00340080 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_MPTCL_MAX_INDEX 15 #define I40E_GLSW_MPTCL_MPTCL_SHIFT 0 #define I40E_GLSW_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_MPTCL_MPTCL_SHIFT) #define I40E_GLSW_RUPP(_i) (0x00370180 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_RUPP_MAX_INDEX 15 #define I40E_GLSW_RUPP_RUPP_SHIFT 0 #define I40E_GLSW_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_RUPP_RUPP_SHIFT) #define I40E_GLSW_TDPC(_i) (0x00348000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_TDPC_MAX_INDEX 15 #define I40E_GLSW_TDPC_TDPC_SHIFT 0 #define I40E_GLSW_TDPC_TDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_TDPC_TDPC_SHIFT) #define I40E_GLSW_UPRCH(_i) (0x00370004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_UPRCH_MAX_INDEX 15 #define I40E_GLSW_UPRCH_UPRCH_SHIFT 0 #define I40E_GLSW_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPRCH_UPRCH_SHIFT) #define I40E_GLSW_UPRCL(_i) (0x00370000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_UPRCL_MAX_INDEX 15 #define I40E_GLSW_UPRCL_UPRCL_SHIFT 0 #define I40E_GLSW_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPRCL_UPRCL_SHIFT) #define I40E_GLSW_UPTCH(_i) (0x00340004 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_UPTCH_MAX_INDEX 15 #define I40E_GLSW_UPTCH_UPTCH_SHIFT 0 #define I40E_GLSW_UPTCH_UPTCH_MASK I40E_MASK(0xFFFF, I40E_GLSW_UPTCH_UPTCH_SHIFT) #define I40E_GLSW_UPTCL(_i) (0x00340000 + ((_i) * 8)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_GLSW_UPTCL_MAX_INDEX 15 #define I40E_GLSW_UPTCL_UPTCL_SHIFT 0 #define I40E_GLSW_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLSW_UPTCL_UPTCL_SHIFT) #define I40E_GLV_BPRCH(_i) (0x0036D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_BPRCH_MAX_INDEX 383 #define I40E_GLV_BPRCH_BPRCH_SHIFT 0 #define I40E_GLV_BPRCH_BPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPRCH_BPRCH_SHIFT) #define I40E_GLV_BPRCL(_i) (0x0036d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_BPRCL_MAX_INDEX 383 #define I40E_GLV_BPRCL_BPRCL_SHIFT 0 #define I40E_GLV_BPRCL_BPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPRCL_BPRCL_SHIFT) #define I40E_GLV_BPTCH(_i) (0x0033D804 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_BPTCH_MAX_INDEX 383 #define I40E_GLV_BPTCH_BPTCH_SHIFT 0 #define I40E_GLV_BPTCH_BPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_BPTCH_BPTCH_SHIFT) #define I40E_GLV_BPTCL(_i) (0x0033d800 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_BPTCL_MAX_INDEX 383 #define I40E_GLV_BPTCL_BPTCL_SHIFT 0 #define I40E_GLV_BPTCL_BPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_BPTCL_BPTCL_SHIFT) #define I40E_GLV_GORCH(_i) (0x00358004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_GORCH_MAX_INDEX 383 #define I40E_GLV_GORCH_GORCH_SHIFT 0 #define I40E_GLV_GORCH_GORCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GORCH_GORCH_SHIFT) #define I40E_GLV_GORCL(_i) (0x00358000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_GORCL_MAX_INDEX 383 #define I40E_GLV_GORCL_GORCL_SHIFT 0 #define I40E_GLV_GORCL_GORCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GORCL_GORCL_SHIFT) #define I40E_GLV_GOTCH(_i) (0x00328004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_GOTCH_MAX_INDEX 383 #define I40E_GLV_GOTCH_GOTCH_SHIFT 0 #define I40E_GLV_GOTCH_GOTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_GOTCH_GOTCH_SHIFT) #define I40E_GLV_GOTCL(_i) (0x00328000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_GOTCL_MAX_INDEX 383 #define I40E_GLV_GOTCL_GOTCL_SHIFT 0 #define I40E_GLV_GOTCL_GOTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_GOTCL_GOTCL_SHIFT) #define I40E_GLV_MPRCH(_i) (0x0036CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_MPRCH_MAX_INDEX 383 #define I40E_GLV_MPRCH_MPRCH_SHIFT 0 #define I40E_GLV_MPRCH_MPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPRCH_MPRCH_SHIFT) #define I40E_GLV_MPRCL(_i) (0x0036cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_MPRCL_MAX_INDEX 383 #define I40E_GLV_MPRCL_MPRCL_SHIFT 0 #define I40E_GLV_MPRCL_MPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPRCL_MPRCL_SHIFT) #define I40E_GLV_MPTCH(_i) (0x0033CC04 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_MPTCH_MAX_INDEX 383 #define I40E_GLV_MPTCH_MPTCH_SHIFT 0 #define I40E_GLV_MPTCH_MPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_MPTCH_MPTCH_SHIFT) #define I40E_GLV_MPTCL(_i) (0x0033cc00 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_MPTCL_MAX_INDEX 383 #define I40E_GLV_MPTCL_MPTCL_SHIFT 0 #define I40E_GLV_MPTCL_MPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_MPTCL_MPTCL_SHIFT) #define I40E_GLV_RDPC(_i) (0x00310000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_RDPC_MAX_INDEX 383 #define I40E_GLV_RDPC_RDPC_SHIFT 0 #define I40E_GLV_RDPC_RDPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RDPC_RDPC_SHIFT) #define I40E_GLV_RUPP(_i) (0x0036E400 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_RUPP_MAX_INDEX 383 #define I40E_GLV_RUPP_RUPP_SHIFT 0 #define I40E_GLV_RUPP_RUPP_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_RUPP_RUPP_SHIFT) #define I40E_GLV_TEPC(_VSI) (0x00344000 + ((_VSI) * 4)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_TEPC_MAX_INDEX 383 #define I40E_GLV_TEPC_TEPC_SHIFT 0 #define I40E_GLV_TEPC_TEPC_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_TEPC_TEPC_SHIFT) #define I40E_GLV_UPRCH(_i) (0x0036C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_UPRCH_MAX_INDEX 383 #define I40E_GLV_UPRCH_UPRCH_SHIFT 0 #define I40E_GLV_UPRCH_UPRCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPRCH_UPRCH_SHIFT) #define I40E_GLV_UPRCL(_i) (0x0036c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_UPRCL_MAX_INDEX 383 #define I40E_GLV_UPRCL_UPRCL_SHIFT 0 #define I40E_GLV_UPRCL_UPRCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPRCL_UPRCL_SHIFT) #define I40E_GLV_UPTCH(_i) (0x0033C004 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_UPTCH_MAX_INDEX 383 #define I40E_GLV_UPTCH_GLVUPTCH_SHIFT 0 #define I40E_GLV_UPTCH_GLVUPTCH_MASK I40E_MASK(0xFFFF, I40E_GLV_UPTCH_GLVUPTCH_SHIFT) #define I40E_GLV_UPTCL(_i) (0x0033c000 + ((_i) * 8)) /* _i=0...383 */ /* Reset: CORER */ #define I40E_GLV_UPTCL_MAX_INDEX 383 #define I40E_GLV_UPTCL_UPTCL_SHIFT 0 #define I40E_GLV_UPTCL_UPTCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLV_UPTCL_UPTCL_SHIFT) #define I40E_GLVEBTC_RBCH(_i, _j) (0x00364004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_RBCH_MAX_INDEX 7 #define I40E_GLVEBTC_RBCH_TCBCH_SHIFT 0 #define I40E_GLVEBTC_RBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RBCH_TCBCH_SHIFT) #define I40E_GLVEBTC_RBCL(_i, _j) (0x00364000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_RBCL_MAX_INDEX 7 #define I40E_GLVEBTC_RBCL_TCBCL_SHIFT 0 #define I40E_GLVEBTC_RBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RBCL_TCBCL_SHIFT) #define I40E_GLVEBTC_RPCH(_i, _j) (0x00368004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_RPCH_MAX_INDEX 7 #define I40E_GLVEBTC_RPCH_TCPCH_SHIFT 0 #define I40E_GLVEBTC_RPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_RPCH_TCPCH_SHIFT) #define I40E_GLVEBTC_RPCL(_i, _j) (0x00368000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_RPCL_MAX_INDEX 7 #define I40E_GLVEBTC_RPCL_TCPCL_SHIFT 0 #define I40E_GLVEBTC_RPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_RPCL_TCPCL_SHIFT) #define I40E_GLVEBTC_TBCH(_i, _j) (0x00334004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_TBCH_MAX_INDEX 7 #define I40E_GLVEBTC_TBCH_TCBCH_SHIFT 0 #define I40E_GLVEBTC_TBCH_TCBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TBCH_TCBCH_SHIFT) #define I40E_GLVEBTC_TBCL(_i, _j) (0x00334000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_TBCL_MAX_INDEX 7 #define I40E_GLVEBTC_TBCL_TCBCL_SHIFT 0 #define I40E_GLVEBTC_TBCL_TCBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TBCL_TCBCL_SHIFT) #define I40E_GLVEBTC_TPCH(_i, _j) (0x00338004 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_TPCH_MAX_INDEX 7 #define I40E_GLVEBTC_TPCH_TCPCH_SHIFT 0 #define I40E_GLVEBTC_TPCH_TCPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBTC_TPCH_TCPCH_SHIFT) #define I40E_GLVEBTC_TPCL(_i, _j) (0x00338000 + ((_i) * 8 + (_j) * 64)) /* _i=0...7, _j=0...15 */ /* Reset: CORER */ #define I40E_GLVEBTC_TPCL_MAX_INDEX 7 #define I40E_GLVEBTC_TPCL_TCPCL_SHIFT 0 #define I40E_GLVEBTC_TPCL_TCPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBTC_TPCL_TCPCL_SHIFT) #define I40E_GLVEBVL_BPCH(_i) (0x00374804 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_BPCH_MAX_INDEX 127 #define I40E_GLVEBVL_BPCH_VLBPCH_SHIFT 0 #define I40E_GLVEBVL_BPCH_VLBPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_BPCH_VLBPCH_SHIFT) #define I40E_GLVEBVL_BPCL(_i) (0x00374800 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_BPCL_MAX_INDEX 127 #define I40E_GLVEBVL_BPCL_VLBPCL_SHIFT 0 #define I40E_GLVEBVL_BPCL_VLBPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_BPCL_VLBPCL_SHIFT) #define I40E_GLVEBVL_GORCH(_i) (0x00360004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_GORCH_MAX_INDEX 127 #define I40E_GLVEBVL_GORCH_VLBCH_SHIFT 0 #define I40E_GLVEBVL_GORCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GORCH_VLBCH_SHIFT) #define I40E_GLVEBVL_GORCL(_i) (0x00360000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_GORCL_MAX_INDEX 127 #define I40E_GLVEBVL_GORCL_VLBCL_SHIFT 0 #define I40E_GLVEBVL_GORCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GORCL_VLBCL_SHIFT) #define I40E_GLVEBVL_GOTCH(_i) (0x00330004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_GOTCH_MAX_INDEX 127 #define I40E_GLVEBVL_GOTCH_VLBCH_SHIFT 0 #define I40E_GLVEBVL_GOTCH_VLBCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_GOTCH_VLBCH_SHIFT) #define I40E_GLVEBVL_GOTCL(_i) (0x00330000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_GOTCL_MAX_INDEX 127 #define I40E_GLVEBVL_GOTCL_VLBCL_SHIFT 0 #define I40E_GLVEBVL_GOTCL_VLBCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_GOTCL_VLBCL_SHIFT) #define I40E_GLVEBVL_MPCH(_i) (0x00374404 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_MPCH_MAX_INDEX 127 #define I40E_GLVEBVL_MPCH_VLMPCH_SHIFT 0 #define I40E_GLVEBVL_MPCH_VLMPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_MPCH_VLMPCH_SHIFT) #define I40E_GLVEBVL_MPCL(_i) (0x00374400 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_MPCL_MAX_INDEX 127 #define I40E_GLVEBVL_MPCL_VLMPCL_SHIFT 0 #define I40E_GLVEBVL_MPCL_VLMPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_MPCL_VLMPCL_SHIFT) #define I40E_GLVEBVL_UPCH(_i) (0x00374004 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_UPCH_MAX_INDEX 127 #define I40E_GLVEBVL_UPCH_VLUPCH_SHIFT 0 #define I40E_GLVEBVL_UPCH_VLUPCH_MASK I40E_MASK(0xFFFF, I40E_GLVEBVL_UPCH_VLUPCH_SHIFT) #define I40E_GLVEBVL_UPCL(_i) (0x00374000 + ((_i) * 8)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_GLVEBVL_UPCL_MAX_INDEX 127 #define I40E_GLVEBVL_UPCL_VLUPCL_SHIFT 0 #define I40E_GLVEBVL_UPCL_VLUPCL_MASK I40E_MASK(0xFFFFFFFF, I40E_GLVEBVL_UPCL_VLUPCL_SHIFT) #define I40E_GL_MTG_FLU_MSK_H 0x00269F4C /* Reset: CORER */ #define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT 0 #define I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_MASK I40E_MASK(0xFFFF, I40E_GL_MTG_FLU_MSK_H_MASK_HIGH_SHIFT) #define I40E_GL_SWR_DEF_ACT(_i) (0x00270200 + ((_i) * 4)) /* _i=0...35 */ /* Reset: CORER */ #define I40E_GL_SWR_DEF_ACT_MAX_INDEX 35 #define I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT 0 #define I40E_GL_SWR_DEF_ACT_DEF_ACTION_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_DEF_ACTION_SHIFT) #define I40E_GL_SWR_DEF_ACT_EN(_i) (0x0026CFB8 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */ #define I40E_GL_SWR_DEF_ACT_EN_MAX_INDEX 1 #define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT 0 #define I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_MASK I40E_MASK(0xFFFFFFFF, I40E_GL_SWR_DEF_ACT_EN_DEF_ACT_EN_BITMAP_SHIFT) #define I40E_PRTTSYN_ADJ 0x001E4280 /* Reset: GLOBR */ #define I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT 0 #define I40E_PRTTSYN_ADJ_TSYNADJ_MASK I40E_MASK(0x7FFFFFFF, I40E_PRTTSYN_ADJ_TSYNADJ_SHIFT) #define I40E_PRTTSYN_ADJ_SIGN_SHIFT 31 #define I40E_PRTTSYN_ADJ_SIGN_MASK I40E_MASK(0x1, I40E_PRTTSYN_ADJ_SIGN_SHIFT) #define I40E_PRTTSYN_AUX_0(_i) (0x001E42A0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_AUX_0_MAX_INDEX 1 #define I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT 0 #define I40E_PRTTSYN_AUX_0_OUT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUT_ENA_SHIFT) #define I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT 1 #define I40E_PRTTSYN_AUX_0_OUTMOD_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_OUTMOD_SHIFT) #define I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT 3 #define I40E_PRTTSYN_AUX_0_OUTLVL_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_0_OUTLVL_SHIFT) #define I40E_PRTTSYN_AUX_0_PULSEW_SHIFT 8 #define I40E_PRTTSYN_AUX_0_PULSEW_MASK I40E_MASK(0xF, I40E_PRTTSYN_AUX_0_PULSEW_SHIFT) #define I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT 16 #define I40E_PRTTSYN_AUX_0_EVNTLVL_MASK I40E_MASK(0x3, I40E_PRTTSYN_AUX_0_EVNTLVL_SHIFT) #define I40E_PRTTSYN_AUX_1(_i) (0x001E42E0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_AUX_1_MAX_INDEX 1 #define I40E_PRTTSYN_AUX_1_INSTNT_SHIFT 0 #define I40E_PRTTSYN_AUX_1_INSTNT_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_INSTNT_SHIFT) #define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT 1 #define I40E_PRTTSYN_AUX_1_SAMPLE_TIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_AUX_1_SAMPLE_TIME_SHIFT) #define I40E_PRTTSYN_CLKO(_i) (0x001E4240 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_CLKO_MAX_INDEX 1 #define I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT 0 #define I40E_PRTTSYN_CLKO_TSYNCLKO_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_CLKO_TSYNCLKO_SHIFT) #define I40E_PRTTSYN_CTL0 0x001E4200 /* Reset: GLOBR */ #define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT 0 #define I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_CLEAR_TSYNTIMER_SHIFT) #define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT 1 #define I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_SHIFT) #define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT 2 #define I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_EVENT_INT_ENA_SHIFT) #define I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT 3 #define I40E_PRTTSYN_CTL0_TGT_INT_ENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TGT_INT_ENA_SHIFT) #define I40E_PRTTSYN_CTL0_PF_ID_SHIFT 8 #define I40E_PRTTSYN_CTL0_PF_ID_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL0_PF_ID_SHIFT) #define I40E_PRTTSYN_CTL0_TSYNACT_SHIFT 12 #define I40E_PRTTSYN_CTL0_TSYNACT_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL0_TSYNACT_SHIFT) #define I40E_PRTTSYN_CTL0_TSYNENA_SHIFT 31 #define I40E_PRTTSYN_CTL0_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL0_TSYNENA_SHIFT) #define I40E_PRTTSYN_CTL1 0x00085020 /* Reset: CORER */ #define I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT 0 #define I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE0_SHIFT) #define I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT 8 #define I40E_PRTTSYN_CTL1_V1MESSTYPE1_MASK I40E_MASK(0xFF, I40E_PRTTSYN_CTL1_V1MESSTYPE1_SHIFT) #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16 #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT) #define I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT 20 #define I40E_PRTTSYN_CTL1_V2MESSTYPE1_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE1_SHIFT) #define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24 #define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) #define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26 #define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT) #define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31 #define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT) #define I40E_PRTTSYN_EVNT_H(_i) (0x001E40C0 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_EVNT_H_MAX_INDEX 1 #define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT 0 #define I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_H_TSYNEVNT_H_SHIFT) #define I40E_PRTTSYN_EVNT_L(_i) (0x001E4080 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_EVNT_L_MAX_INDEX 1 #define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT 0 #define I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_EVNT_L_TSYNEVNT_L_SHIFT) #define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */ #define I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT 0 #define I40E_PRTTSYN_INC_H_TSYNINC_H_MASK I40E_MASK(0x3F, I40E_PRTTSYN_INC_H_TSYNINC_H_SHIFT) #define I40E_PRTTSYN_INC_L 0x001E4040 /* Reset: GLOBR */ #define I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT 0 #define I40E_PRTTSYN_INC_L_TSYNINC_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_INC_L_TSYNINC_L_SHIFT) #define I40E_PRTTSYN_RXTIME_H(_i) (0x00085040 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_PRTTSYN_RXTIME_H_MAX_INDEX 3 #define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT 0 #define I40E_PRTTSYN_RXTIME_H_RXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_H_RXTIEM_H_SHIFT) #define I40E_PRTTSYN_RXTIME_L(_i) (0x000850C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: CORER */ #define I40E_PRTTSYN_RXTIME_L_MAX_INDEX 3 #define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT 0 #define I40E_PRTTSYN_RXTIME_L_RXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_RXTIME_L_RXTIEM_L_SHIFT) #define I40E_PRTTSYN_STAT_0 0x001E4220 /* Reset: GLOBR */ #define I40E_PRTTSYN_STAT_0_EVENT0_SHIFT 0 #define I40E_PRTTSYN_STAT_0_EVENT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT0_SHIFT) #define I40E_PRTTSYN_STAT_0_EVENT1_SHIFT 1 #define I40E_PRTTSYN_STAT_0_EVENT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_EVENT1_SHIFT) #define I40E_PRTTSYN_STAT_0_TGT0_SHIFT 2 #define I40E_PRTTSYN_STAT_0_TGT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT0_SHIFT) #define I40E_PRTTSYN_STAT_0_TGT1_SHIFT 3 #define I40E_PRTTSYN_STAT_0_TGT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TGT1_SHIFT) #define I40E_PRTTSYN_STAT_0_TXTIME_SHIFT 4 #define I40E_PRTTSYN_STAT_0_TXTIME_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_0_TXTIME_SHIFT) #define I40E_PRTTSYN_STAT_1 0x00085140 /* Reset: CORER */ #define I40E_PRTTSYN_STAT_1_RXT0_SHIFT 0 #define I40E_PRTTSYN_STAT_1_RXT0_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT0_SHIFT) #define I40E_PRTTSYN_STAT_1_RXT1_SHIFT 1 #define I40E_PRTTSYN_STAT_1_RXT1_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT1_SHIFT) #define I40E_PRTTSYN_STAT_1_RXT2_SHIFT 2 #define I40E_PRTTSYN_STAT_1_RXT2_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT2_SHIFT) #define I40E_PRTTSYN_STAT_1_RXT3_SHIFT 3 #define I40E_PRTTSYN_STAT_1_RXT3_MASK I40E_MASK(0x1, I40E_PRTTSYN_STAT_1_RXT3_SHIFT) #define I40E_PRTTSYN_TGT_H(_i) (0x001E4180 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_TGT_H_MAX_INDEX 1 #define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT 0 #define I40E_PRTTSYN_TGT_H_TSYNTGTT_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_H_TSYNTGTT_H_SHIFT) #define I40E_PRTTSYN_TGT_L(_i) (0x001E4140 + ((_i) * 32)) /* _i=0...1 */ /* Reset: GLOBR */ #define I40E_PRTTSYN_TGT_L_MAX_INDEX 1 #define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT 0 #define I40E_PRTTSYN_TGT_L_TSYNTGTT_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TGT_L_TSYNTGTT_L_SHIFT) #define I40E_PRTTSYN_TIME_H 0x001E4120 /* Reset: GLOBR */ #define I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT 0 #define I40E_PRTTSYN_TIME_H_TSYNTIME_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_H_TSYNTIME_H_SHIFT) #define I40E_PRTTSYN_TIME_L 0x001E4100 /* Reset: GLOBR */ #define I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT 0 #define I40E_PRTTSYN_TIME_L_TSYNTIME_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TIME_L_TSYNTIME_L_SHIFT) #define I40E_PRTTSYN_TXTIME_H 0x001E41E0 /* Reset: GLOBR */ #define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT 0 #define I40E_PRTTSYN_TXTIME_H_TXTIEM_H_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_H_TXTIEM_H_SHIFT) #define I40E_PRTTSYN_TXTIME_L 0x001E41C0 /* Reset: GLOBR */ #define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT 0 #define I40E_PRTTSYN_TXTIME_L_TXTIEM_L_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTTSYN_TXTIME_L_TXTIEM_L_SHIFT) #define I40E_GL_MDET_RX 0x0012A510 /* Reset: CORER */ #define I40E_GL_MDET_RX_FUNCTION_SHIFT 0 #define I40E_GL_MDET_RX_FUNCTION_MASK I40E_MASK(0xFF, I40E_GL_MDET_RX_FUNCTION_SHIFT) #define I40E_GL_MDET_RX_EVENT_SHIFT 8 #define I40E_GL_MDET_RX_EVENT_MASK I40E_MASK(0x1FF, I40E_GL_MDET_RX_EVENT_SHIFT) #define I40E_GL_MDET_RX_QUEUE_SHIFT 17 #define I40E_GL_MDET_RX_QUEUE_MASK I40E_MASK(0x3FFF, I40E_GL_MDET_RX_QUEUE_SHIFT) #define I40E_GL_MDET_RX_VALID_SHIFT 31 #define I40E_GL_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_RX_VALID_SHIFT) #define I40E_GL_MDET_TX 0x000E6480 /* Reset: CORER */ #define I40E_GL_MDET_TX_QUEUE_SHIFT 0 #define I40E_GL_MDET_TX_QUEUE_MASK I40E_MASK(0xFFF, I40E_GL_MDET_TX_QUEUE_SHIFT) #define I40E_GL_MDET_TX_VF_NUM_SHIFT 12 #define I40E_GL_MDET_TX_VF_NUM_MASK I40E_MASK(0x1FF, I40E_GL_MDET_TX_VF_NUM_SHIFT) #define I40E_GL_MDET_TX_PF_NUM_SHIFT 21 #define I40E_GL_MDET_TX_PF_NUM_MASK I40E_MASK(0xF, I40E_GL_MDET_TX_PF_NUM_SHIFT) #define I40E_GL_MDET_TX_EVENT_SHIFT 25 #define I40E_GL_MDET_TX_EVENT_MASK I40E_MASK(0x1F, I40E_GL_MDET_TX_EVENT_SHIFT) #define I40E_GL_MDET_TX_VALID_SHIFT 31 #define I40E_GL_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_GL_MDET_TX_VALID_SHIFT) #define I40E_PF_MDET_RX 0x0012A400 /* Reset: CORER */ #define I40E_PF_MDET_RX_VALID_SHIFT 0 #define I40E_PF_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_RX_VALID_SHIFT) #define I40E_PF_MDET_TX 0x000E6400 /* Reset: CORER */ #define I40E_PF_MDET_TX_VALID_SHIFT 0 #define I40E_PF_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_PF_MDET_TX_VALID_SHIFT) #define I40E_PF_VT_PFALLOC 0x001C0500 /* Reset: CORER */ #define I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT 0 #define I40E_PF_VT_PFALLOC_FIRSTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT) #define I40E_PF_VT_PFALLOC_LASTVF_SHIFT 8 #define I40E_PF_VT_PFALLOC_LASTVF_MASK I40E_MASK(0xFF, I40E_PF_VT_PFALLOC_LASTVF_SHIFT) #define I40E_PF_VT_PFALLOC_VALID_SHIFT 31 #define I40E_PF_VT_PFALLOC_VALID_MASK I40E_MASK(0x1, I40E_PF_VT_PFALLOC_VALID_SHIFT) #define I40E_VP_MDET_RX(_VF) (0x0012A000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VP_MDET_RX_MAX_INDEX 127 #define I40E_VP_MDET_RX_VALID_SHIFT 0 #define I40E_VP_MDET_RX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_RX_VALID_SHIFT) #define I40E_VP_MDET_TX(_VF) (0x000E6000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */ #define I40E_VP_MDET_TX_MAX_INDEX 127 #define I40E_VP_MDET_TX_VALID_SHIFT 0 #define I40E_VP_MDET_TX_VALID_MASK I40E_MASK(0x1, I40E_VP_MDET_TX_VALID_SHIFT) #define I40E_GLPM_WUMC 0x0006C800 /* Reset: POR */ #define I40E_GLPM_WUMC_NOTCO_SHIFT 0 #define I40E_GLPM_WUMC_NOTCO_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_NOTCO_SHIFT) #define I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT 1 #define I40E_GLPM_WUMC_SRST_PIN_VAL_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_SRST_PIN_VAL_SHIFT) #define I40E_GLPM_WUMC_ROL_MODE_SHIFT 2 #define I40E_GLPM_WUMC_ROL_MODE_MASK I40E_MASK(0x1, I40E_GLPM_WUMC_ROL_MODE_SHIFT) #define I40E_GLPM_WUMC_RESERVED_4_SHIFT 3 #define I40E_GLPM_WUMC_RESERVED_4_MASK I40E_MASK(0x1FFF, I40E_GLPM_WUMC_RESERVED_4_SHIFT) #define I40E_GLPM_WUMC_MNG_WU_PF_SHIFT 16 #define I40E_GLPM_WUMC_MNG_WU_PF_MASK I40E_MASK(0xFFFF, I40E_GLPM_WUMC_MNG_WU_PF_SHIFT) #define I40E_PFPM_APM 0x000B8080 /* Reset: POR */ #define I40E_PFPM_APM_APME_SHIFT 0 #define I40E_PFPM_APM_APME_MASK I40E_MASK(0x1, I40E_PFPM_APM_APME_SHIFT) #define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */ /* Reset: POR */ #define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7 #define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0 #define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK I40E_MASK(0xFF, I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT) #define I40E_PFPM_WUC 0x0006B200 /* Reset: POR */ #define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5 #define I40E_PFPM_WUC_EN_APM_D0_MASK I40E_MASK(0x1, I40E_PFPM_WUC_EN_APM_D0_SHIFT) #define I40E_PFPM_WUFC 0x0006B400 /* Reset: POR */ #define I40E_PFPM_WUFC_LNKC_SHIFT 0 #define I40E_PFPM_WUFC_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_LNKC_SHIFT) #define I40E_PFPM_WUFC_MAG_SHIFT 1 #define I40E_PFPM_WUFC_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MAG_SHIFT) #define I40E_PFPM_WUFC_MNG_SHIFT 3 #define I40E_PFPM_WUFC_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_MNG_SHIFT) #define I40E_PFPM_WUFC_FLX0_ACT_SHIFT 4 #define I40E_PFPM_WUFC_FLX0_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX1_ACT_SHIFT 5 #define I40E_PFPM_WUFC_FLX1_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX2_ACT_SHIFT 6 #define I40E_PFPM_WUFC_FLX2_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX3_ACT_SHIFT 7 #define I40E_PFPM_WUFC_FLX3_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX4_ACT_SHIFT 8 #define I40E_PFPM_WUFC_FLX4_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX5_ACT_SHIFT 9 #define I40E_PFPM_WUFC_FLX5_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX6_ACT_SHIFT 10 #define I40E_PFPM_WUFC_FLX6_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX7_ACT_SHIFT 11 #define I40E_PFPM_WUFC_FLX7_ACT_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_ACT_SHIFT) #define I40E_PFPM_WUFC_FLX0_SHIFT 16 #define I40E_PFPM_WUFC_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX0_SHIFT) #define I40E_PFPM_WUFC_FLX1_SHIFT 17 #define I40E_PFPM_WUFC_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX1_SHIFT) #define I40E_PFPM_WUFC_FLX2_SHIFT 18 #define I40E_PFPM_WUFC_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX2_SHIFT) #define I40E_PFPM_WUFC_FLX3_SHIFT 19 #define I40E_PFPM_WUFC_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX3_SHIFT) #define I40E_PFPM_WUFC_FLX4_SHIFT 20 #define I40E_PFPM_WUFC_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX4_SHIFT) #define I40E_PFPM_WUFC_FLX5_SHIFT 21 #define I40E_PFPM_WUFC_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX5_SHIFT) #define I40E_PFPM_WUFC_FLX6_SHIFT 22 #define I40E_PFPM_WUFC_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX6_SHIFT) #define I40E_PFPM_WUFC_FLX7_SHIFT 23 #define I40E_PFPM_WUFC_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FLX7_SHIFT) #define I40E_PFPM_WUFC_FW_RST_WK_SHIFT 31 #define I40E_PFPM_WUFC_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUFC_FW_RST_WK_SHIFT) #define I40E_PFPM_WUS 0x0006B600 /* Reset: POR */ #define I40E_PFPM_WUS_LNKC_SHIFT 0 #define I40E_PFPM_WUS_LNKC_MASK I40E_MASK(0x1, I40E_PFPM_WUS_LNKC_SHIFT) #define I40E_PFPM_WUS_MAG_SHIFT 1 #define I40E_PFPM_WUS_MAG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MAG_SHIFT) #define I40E_PFPM_WUS_PME_STATUS_SHIFT 2 #define I40E_PFPM_WUS_PME_STATUS_MASK I40E_MASK(0x1, I40E_PFPM_WUS_PME_STATUS_SHIFT) #define I40E_PFPM_WUS_MNG_SHIFT 3 #define I40E_PFPM_WUS_MNG_MASK I40E_MASK(0x1, I40E_PFPM_WUS_MNG_SHIFT) #define I40E_PFPM_WUS_FLX0_SHIFT 16 #define I40E_PFPM_WUS_FLX0_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX0_SHIFT) #define I40E_PFPM_WUS_FLX1_SHIFT 17 #define I40E_PFPM_WUS_FLX1_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX1_SHIFT) #define I40E_PFPM_WUS_FLX2_SHIFT 18 #define I40E_PFPM_WUS_FLX2_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX2_SHIFT) #define I40E_PFPM_WUS_FLX3_SHIFT 19 #define I40E_PFPM_WUS_FLX3_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX3_SHIFT) #define I40E_PFPM_WUS_FLX4_SHIFT 20 #define I40E_PFPM_WUS_FLX4_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX4_SHIFT) #define I40E_PFPM_WUS_FLX5_SHIFT 21 #define I40E_PFPM_WUS_FLX5_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX5_SHIFT) #define I40E_PFPM_WUS_FLX6_SHIFT 22 #define I40E_PFPM_WUS_FLX6_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX6_SHIFT) #define I40E_PFPM_WUS_FLX7_SHIFT 23 #define I40E_PFPM_WUS_FLX7_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FLX7_SHIFT) #define I40E_PFPM_WUS_FW_RST_WK_SHIFT 31 #define I40E_PFPM_WUS_FW_RST_WK_MASK I40E_MASK(0x1, I40E_PFPM_WUS_FW_RST_WK_SHIFT) #define I40E_PRTPM_FHFHR 0x0006C000 /* Reset: POR */ #define I40E_PRTPM_FHFHR_UNICAST_SHIFT 0 #define I40E_PRTPM_FHFHR_UNICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_UNICAST_SHIFT) #define I40E_PRTPM_FHFHR_MULTICAST_SHIFT 1 #define I40E_PRTPM_FHFHR_MULTICAST_MASK I40E_MASK(0x1, I40E_PRTPM_FHFHR_MULTICAST_SHIFT) #define I40E_PRTPM_SAH(_i) (0x001E44C0 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */ #define I40E_PRTPM_SAH_MAX_INDEX 3 #define I40E_PRTPM_SAH_PFPM_SAH_SHIFT 0 #define I40E_PRTPM_SAH_PFPM_SAH_MASK I40E_MASK(0xFFFF, I40E_PRTPM_SAH_PFPM_SAH_SHIFT) #define I40E_PRTPM_SAH_PF_NUM_SHIFT 26 #define I40E_PRTPM_SAH_PF_NUM_MASK I40E_MASK(0xF, I40E_PRTPM_SAH_PF_NUM_SHIFT) #define I40E_PRTPM_SAH_MC_MAG_EN_SHIFT 30 #define I40E_PRTPM_SAH_MC_MAG_EN_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_MC_MAG_EN_SHIFT) #define I40E_PRTPM_SAH_AV_SHIFT 31 #define I40E_PRTPM_SAH_AV_MASK I40E_MASK(0x1, I40E_PRTPM_SAH_AV_SHIFT) #define I40E_PRTPM_SAL(_i) (0x001E4440 + ((_i) * 32)) /* _i=0...3 */ /* Reset: PFR */ #define I40E_PRTPM_SAL_MAX_INDEX 3 #define I40E_PRTPM_SAL_PFPM_SAL_SHIFT 0 #define I40E_PRTPM_SAL_PFPM_SAL_MASK I40E_MASK(0xFFFFFFFF, I40E_PRTPM_SAL_PFPM_SAL_SHIFT) #define I40E_VF_ARQBAH1 0x00006000 /* Reset: EMPR */ #define I40E_VF_ARQBAH1_ARQBAH_SHIFT 0 #define I40E_VF_ARQBAH1_ARQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAH1_ARQBAH_SHIFT) #define I40E_VF_ARQBAL1 0x00006C00 /* Reset: EMPR */ #define I40E_VF_ARQBAL1_ARQBAL_SHIFT 0 #define I40E_VF_ARQBAL1_ARQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ARQBAL1_ARQBAL_SHIFT) #define I40E_VF_ARQH1 0x00007400 /* Reset: EMPR */ #define I40E_VF_ARQH1_ARQH_SHIFT 0 #define I40E_VF_ARQH1_ARQH_MASK I40E_MASK(0x3FF, I40E_VF_ARQH1_ARQH_SHIFT) #define I40E_VF_ARQLEN1 0x00008000 /* Reset: EMPR */ #define I40E_VF_ARQLEN1_ARQLEN_SHIFT 0 #define I40E_VF_ARQLEN1_ARQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ARQLEN1_ARQLEN_SHIFT) #define I40E_VF_ARQLEN1_ARQVFE_SHIFT 28 #define I40E_VF_ARQLEN1_ARQVFE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQVFE_SHIFT) #define I40E_VF_ARQLEN1_ARQOVFL_SHIFT 29 #define I40E_VF_ARQLEN1_ARQOVFL_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQOVFL_SHIFT) #define I40E_VF_ARQLEN1_ARQCRIT_SHIFT 30 #define I40E_VF_ARQLEN1_ARQCRIT_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQCRIT_SHIFT) #define I40E_VF_ARQLEN1_ARQENABLE_SHIFT 31 #define I40E_VF_ARQLEN1_ARQENABLE_MASK I40E_MASK(0x1, I40E_VF_ARQLEN1_ARQENABLE_SHIFT) #define I40E_VF_ARQT1 0x00007000 /* Reset: EMPR */ #define I40E_VF_ARQT1_ARQT_SHIFT 0 #define I40E_VF_ARQT1_ARQT_MASK I40E_MASK(0x3FF, I40E_VF_ARQT1_ARQT_SHIFT) #define I40E_VF_ATQBAH1 0x00007800 /* Reset: EMPR */ #define I40E_VF_ATQBAH1_ATQBAH_SHIFT 0 #define I40E_VF_ATQBAH1_ATQBAH_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAH1_ATQBAH_SHIFT) #define I40E_VF_ATQBAL1 0x00007C00 /* Reset: EMPR */ #define I40E_VF_ATQBAL1_ATQBAL_SHIFT 0 #define I40E_VF_ATQBAL1_ATQBAL_MASK I40E_MASK(0xFFFFFFFF, I40E_VF_ATQBAL1_ATQBAL_SHIFT) #define I40E_VF_ATQH1 0x00006400 /* Reset: EMPR */ #define I40E_VF_ATQH1_ATQH_SHIFT 0 #define I40E_VF_ATQH1_ATQH_MASK I40E_MASK(0x3FF, I40E_VF_ATQH1_ATQH_SHIFT) #define I40E_VF_ATQLEN1 0x00006800 /* Reset: EMPR */ #define I40E_VF_ATQLEN1_ATQLEN_SHIFT 0 #define I40E_VF_ATQLEN1_ATQLEN_MASK I40E_MASK(0x3FF, I40E_VF_ATQLEN1_ATQLEN_SHIFT) #define I40E_VF_ATQLEN1_ATQVFE_SHIFT 28 #define I40E_VF_ATQLEN1_ATQVFE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQVFE_SHIFT) #define I40E_VF_ATQLEN1_ATQOVFL_SHIFT 29 #define I40E_VF_ATQLEN1_ATQOVFL_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQOVFL_SHIFT) #define I40E_VF_ATQLEN1_ATQCRIT_SHIFT 30 #define I40E_VF_ATQLEN1_ATQCRIT_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQCRIT_SHIFT) #define I40E_VF_ATQLEN1_ATQENABLE_SHIFT 31 #define I40E_VF_ATQLEN1_ATQENABLE_MASK I40E_MASK(0x1, I40E_VF_ATQLEN1_ATQENABLE_SHIFT) #define I40E_VF_ATQT1 0x00008400 /* Reset: EMPR */ #define I40E_VF_ATQT1_ATQT_SHIFT 0 #define I40E_VF_ATQT1_ATQT_MASK I40E_MASK(0x3FF, I40E_VF_ATQT1_ATQT_SHIFT) #define I40E_VFGEN_RSTAT 0x00008800 /* Reset: VFR */ #define I40E_VFGEN_RSTAT_VFR_STATE_SHIFT 0 #define I40E_VFGEN_RSTAT_VFR_STATE_MASK I40E_MASK(0x3, I40E_VFGEN_RSTAT_VFR_STATE_SHIFT) #define I40E_VFINT_DYN_CTL01 0x00005C00 /* Reset: VFR */ #define I40E_VFINT_DYN_CTL01_INTENA_SHIFT 0 #define I40E_VFINT_DYN_CTL01_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_SHIFT) #define I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT 1 #define I40E_VFINT_DYN_CTL01_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_CLEARPBA_SHIFT) #define I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT 2 #define I40E_VFINT_DYN_CTL01_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SWINT_TRIG_SHIFT) #define I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3 #define I40E_VFINT_DYN_CTL01_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT 5 #define I40E_VFINT_DYN_CTL01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTL01_INTERVAL_SHIFT) #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_ENA_SHIFT) #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT 25 #define I40E_VFINT_DYN_CTL01_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTL01_SW_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT 31 #define I40E_VFINT_DYN_CTL01_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTL01_INTENA_MSK_SHIFT) #define I40E_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */ #define I40E_VFINT_DYN_CTLN1_MAX_INDEX 15 #define I40E_VFINT_DYN_CTLN1_INTENA_SHIFT 0 #define I40E_VFINT_DYN_CTLN1_INTENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_SHIFT) #define I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT 1 #define I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_CLEARPBA_SHIFT) #define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2 #define I40E_VFINT_DYN_CTLN1_SWINT_TRIG_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT) #define I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT 3 #define I40E_VFINT_DYN_CTLN1_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT 5 #define I40E_VFINT_DYN_CTLN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT) #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT 24 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_ENA_SHIFT) #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT 25 #define I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_DYN_CTLN1_SW_ITR_INDX_SHIFT) #define I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT 31 #define I40E_VFINT_DYN_CTLN1_INTENA_MSK_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN1_INTENA_MSK_SHIFT) #define I40E_VFINT_ICR0_ENA1 0x00005000 /* Reset: CORER */ #define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT 25 #define I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_LINK_STAT_CHANGE_SHIFT) #define I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT 30 #define I40E_VFINT_ICR0_ENA1_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_ADMINQ_SHIFT) #define I40E_VFINT_ICR0_ENA1_RSVD_SHIFT 31 #define I40E_VFINT_ICR0_ENA1_RSVD_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ENA1_RSVD_SHIFT) #define I40E_VFINT_ICR01 0x00004800 /* Reset: CORER */ #define I40E_VFINT_ICR01_INTEVENT_SHIFT 0 #define I40E_VFINT_ICR01_INTEVENT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_INTEVENT_SHIFT) #define I40E_VFINT_ICR01_QUEUE_0_SHIFT 1 #define I40E_VFINT_ICR01_QUEUE_0_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_0_SHIFT) #define I40E_VFINT_ICR01_QUEUE_1_SHIFT 2 #define I40E_VFINT_ICR01_QUEUE_1_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_1_SHIFT) #define I40E_VFINT_ICR01_QUEUE_2_SHIFT 3 #define I40E_VFINT_ICR01_QUEUE_2_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_2_SHIFT) #define I40E_VFINT_ICR01_QUEUE_3_SHIFT 4 #define I40E_VFINT_ICR01_QUEUE_3_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_QUEUE_3_SHIFT) #define I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT 25 #define I40E_VFINT_ICR01_LINK_STAT_CHANGE_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_LINK_STAT_CHANGE_SHIFT) #define I40E_VFINT_ICR01_ADMINQ_SHIFT 30 #define I40E_VFINT_ICR01_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_ADMINQ_SHIFT) #define I40E_VFINT_ICR01_SWINT_SHIFT 31 #define I40E_VFINT_ICR01_SWINT_MASK I40E_MASK(0x1, I40E_VFINT_ICR01_SWINT_SHIFT) #define I40E_VFINT_ITR01(_i) (0x00004C00 + ((_i) * 4)) /* _i=0...2 */ /* Reset: VFR */ #define I40E_VFINT_ITR01_MAX_INDEX 2 #define I40E_VFINT_ITR01_INTERVAL_SHIFT 0 #define I40E_VFINT_ITR01_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITR01_INTERVAL_SHIFT) #define I40E_VFINT_ITRN1(_i, _INTVF) (0x00002800 + ((_i) * 64 + (_INTVF) * 4)) /* _i=0...2, _INTVF=0...15 */ /* Reset: VFR */ #define I40E_VFINT_ITRN1_MAX_INDEX 2 #define I40E_VFINT_ITRN1_INTERVAL_SHIFT 0 #define I40E_VFINT_ITRN1_INTERVAL_MASK I40E_MASK(0xFFF, I40E_VFINT_ITRN1_INTERVAL_SHIFT) #define I40E_VFINT_STAT_CTL01 0x00005400 /* Reset: CORER */ #define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT 2 #define I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_MASK I40E_MASK(0x3, I40E_VFINT_STAT_CTL01_OTHER_ITR_INDX_SHIFT) #define I40E_QRX_TAIL1(_Q) (0x00002000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_QRX_TAIL1_MAX_INDEX 15 #define I40E_QRX_TAIL1_TAIL_SHIFT 0 #define I40E_QRX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QRX_TAIL1_TAIL_SHIFT) #define I40E_QTX_TAIL1(_Q) (0x00000000 + ((_Q) * 4)) /* _i=0...15 */ /* Reset: PFR */ #define I40E_QTX_TAIL1_MAX_INDEX 15 #define I40E_QTX_TAIL1_TAIL_SHIFT 0 #define I40E_QTX_TAIL1_TAIL_MASK I40E_MASK(0x1FFF, I40E_QTX_TAIL1_TAIL_SHIFT) #define I40E_VFMSIX_PBA 0x00002000 /* Reset: VFLR */ #define I40E_VFMSIX_PBA_PENBIT_SHIFT 0 #define I40E_VFMSIX_PBA_PENBIT_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_PBA_PENBIT_SHIFT) #define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */ #define I40E_VFMSIX_TADD_MAX_INDEX 16 #define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0 #define I40E_VFMSIX_TADD_MSIXTADD10_MASK I40E_MASK(0x3, I40E_VFMSIX_TADD_MSIXTADD10_SHIFT) #define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2 #define I40E_VFMSIX_TADD_MSIXTADD_MASK I40E_MASK(0x3FFFFFFF, I40E_VFMSIX_TADD_MSIXTADD_SHIFT) #define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */ #define I40E_VFMSIX_TMSG_MAX_INDEX 16 #define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0 #define I40E_VFMSIX_TMSG_MSIXTMSG_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT) #define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */ #define I40E_VFMSIX_TUADD_MAX_INDEX 16 #define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0 #define I40E_VFMSIX_TUADD_MSIXTUADD_MASK I40E_MASK(0xFFFFFFFF, I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT) #define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */ /* Reset: VFLR */ #define I40E_VFMSIX_TVCTRL_MAX_INDEX 16 #define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0 #define I40E_VFMSIX_TVCTRL_MASK_MASK I40E_MASK(0x1, I40E_VFMSIX_TVCTRL_MASK_SHIFT) #define I40E_VFCM_PE_ERRDATA 0x0000DC00 /* Reset: VFR */ #define I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT 0 #define I40E_VFCM_PE_ERRDATA_ERROR_CODE_MASK I40E_MASK(0xF, I40E_VFCM_PE_ERRDATA_ERROR_CODE_SHIFT) #define I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT 4 #define I40E_VFCM_PE_ERRDATA_Q_TYPE_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRDATA_Q_TYPE_SHIFT) #define I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT 8 #define I40E_VFCM_PE_ERRDATA_Q_NUM_MASK I40E_MASK(0x3FFFF, I40E_VFCM_PE_ERRDATA_Q_NUM_SHIFT) #define I40E_VFCM_PE_ERRINFO 0x0000D800 /* Reset: VFR */ #define I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT 0 #define I40E_VFCM_PE_ERRINFO_ERROR_VALID_MASK I40E_MASK(0x1, I40E_VFCM_PE_ERRINFO_ERROR_VALID_SHIFT) #define I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT 4 #define I40E_VFCM_PE_ERRINFO_ERROR_INST_MASK I40E_MASK(0x7, I40E_VFCM_PE_ERRINFO_ERROR_INST_SHIFT) #define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT 8 #define I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_DBL_ERROR_CNT_SHIFT) #define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT 16 #define I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLU_ERROR_CNT_SHIFT) #define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT 24 #define I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_MASK I40E_MASK(0xFF, I40E_VFCM_PE_ERRINFO_RLS_ERROR_CNT_SHIFT) #define I40E_VFQF_HENA(_i) (0x0000C400 + ((_i) * 4)) /* _i=0...1 */ /* Reset: CORER */ #define I40E_VFQF_HENA_MAX_INDEX 1 #define I40E_VFQF_HENA_PTYPE_ENA_SHIFT 0 #define I40E_VFQF_HENA_PTYPE_ENA_MASK I40E_MASK(0xFFFFFFFF, I40E_VFQF_HENA_PTYPE_ENA_SHIFT) #define I40E_VFQF_HKEY(_i) (0x0000CC00 + ((_i) * 4)) /* _i=0...12 */ /* Reset: CORER */ #define I40E_VFQF_HKEY_MAX_INDEX 12 #define I40E_VFQF_HKEY_KEY_0_SHIFT 0 #define I40E_VFQF_HKEY_KEY_0_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_0_SHIFT) #define I40E_VFQF_HKEY_KEY_1_SHIFT 8 #define I40E_VFQF_HKEY_KEY_1_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_1_SHIFT) #define I40E_VFQF_HKEY_KEY_2_SHIFT 16 #define I40E_VFQF_HKEY_KEY_2_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_2_SHIFT) #define I40E_VFQF_HKEY_KEY_3_SHIFT 24 #define I40E_VFQF_HKEY_KEY_3_MASK I40E_MASK(0xFF, I40E_VFQF_HKEY_KEY_3_SHIFT) #define I40E_VFQF_HLUT(_i) (0x0000D000 + ((_i) * 4)) /* _i=0...15 */ /* Reset: CORER */ #define I40E_VFQF_HLUT_MAX_INDEX 15 #define I40E_VFQF_HLUT_LUT0_SHIFT 0 #define I40E_VFQF_HLUT_LUT0_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT0_SHIFT) #define I40E_VFQF_HLUT_LUT1_SHIFT 8 #define I40E_VFQF_HLUT_LUT1_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT1_SHIFT) #define I40E_VFQF_HLUT_LUT2_SHIFT 16 #define I40E_VFQF_HLUT_LUT2_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT2_SHIFT) #define I40E_VFQF_HLUT_LUT3_SHIFT 24 #define I40E_VFQF_HLUT_LUT3_MASK I40E_MASK(0xF, I40E_VFQF_HLUT_LUT3_SHIFT) #define I40E_VFQF_HREGION(_i) (0x0000D400 + ((_i) * 4)) /* _i=0...7 */ /* Reset: CORER */ #define I40E_VFQF_HREGION_MAX_INDEX 7 #define I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT 0 #define I40E_VFQF_HREGION_OVERRIDE_ENA_0_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT) #define I40E_VFQF_HREGION_REGION_0_SHIFT 1 #define I40E_VFQF_HREGION_REGION_0_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_0_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT 4 #define I40E_VFQF_HREGION_OVERRIDE_ENA_1_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT) #define I40E_VFQF_HREGION_REGION_1_SHIFT 5 #define I40E_VFQF_HREGION_REGION_1_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_1_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT 8 #define I40E_VFQF_HREGION_OVERRIDE_ENA_2_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT) #define I40E_VFQF_HREGION_REGION_2_SHIFT 9 #define I40E_VFQF_HREGION_REGION_2_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_2_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT 12 #define I40E_VFQF_HREGION_OVERRIDE_ENA_3_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT) #define I40E_VFQF_HREGION_REGION_3_SHIFT 13 #define I40E_VFQF_HREGION_REGION_3_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_3_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT 16 #define I40E_VFQF_HREGION_OVERRIDE_ENA_4_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT) #define I40E_VFQF_HREGION_REGION_4_SHIFT 17 #define I40E_VFQF_HREGION_REGION_4_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_4_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT 20 #define I40E_VFQF_HREGION_OVERRIDE_ENA_5_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT) #define I40E_VFQF_HREGION_REGION_5_SHIFT 21 #define I40E_VFQF_HREGION_REGION_5_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_5_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT 24 #define I40E_VFQF_HREGION_OVERRIDE_ENA_6_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT) #define I40E_VFQF_HREGION_REGION_6_SHIFT 25 #define I40E_VFQF_HREGION_REGION_6_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_6_SHIFT) #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT 28 #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK I40E_MASK(0x1, I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT) #define I40E_VFQF_HREGION_REGION_7_SHIFT 29 #define I40E_VFQF_HREGION_REGION_7_MASK I40E_MASK(0x7, I40E_VFQF_HREGION_REGION_7_SHIFT) #endif /* _I40E_REGISTER_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_status.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_STATUS_H_ #define _I40E_STATUS_H_ /* Error Codes */ enum i40e_status_code { I40E_SUCCESS = 0, I40E_ERR_NVM = -1, I40E_ERR_NVM_CHECKSUM = -2, I40E_ERR_PHY = -3, I40E_ERR_CONFIG = -4, I40E_ERR_PARAM = -5, I40E_ERR_MAC_TYPE = -6, I40E_ERR_UNKNOWN_PHY = -7, I40E_ERR_LINK_SETUP = -8, I40E_ERR_ADAPTER_STOPPED = -9, I40E_ERR_INVALID_MAC_ADDR = -10, I40E_ERR_DEVICE_NOT_SUPPORTED = -11, I40E_ERR_MASTER_REQUESTS_PENDING = -12, I40E_ERR_INVALID_LINK_SETTINGS = -13, I40E_ERR_AUTONEG_NOT_COMPLETE = -14, I40E_ERR_RESET_FAILED = -15, I40E_ERR_SWFW_SYNC = -16, I40E_ERR_NO_AVAILABLE_VSI = -17, I40E_ERR_NO_MEMORY = -18, I40E_ERR_BAD_PTR = -19, I40E_ERR_RING_FULL = -20, I40E_ERR_INVALID_PD_ID = -21, I40E_ERR_INVALID_QP_ID = -22, I40E_ERR_INVALID_CQ_ID = -23, I40E_ERR_INVALID_CEQ_ID = -24, I40E_ERR_INVALID_AEQ_ID = -25, I40E_ERR_INVALID_SIZE = -26, I40E_ERR_INVALID_ARP_INDEX = -27, I40E_ERR_INVALID_FPM_FUNC_ID = -28, I40E_ERR_QP_INVALID_MSG_SIZE = -29, I40E_ERR_QP_TOOMANY_WRS_POSTED = -30, I40E_ERR_INVALID_FRAG_COUNT = -31, I40E_ERR_QUEUE_EMPTY = -32, I40E_ERR_INVALID_ALIGNMENT = -33, I40E_ERR_FLUSHED_QUEUE = -34, I40E_ERR_INVALID_PUSH_PAGE_INDEX = -35, I40E_ERR_INVALID_IMM_DATA_SIZE = -36, I40E_ERR_TIMEOUT = -37, I40E_ERR_OPCODE_MISMATCH = -38, I40E_ERR_CQP_COMPL_ERROR = -39, I40E_ERR_INVALID_VF_ID = -40, I40E_ERR_INVALID_HMCFN_ID = -41, I40E_ERR_BACKING_PAGE_ERROR = -42, I40E_ERR_NO_PBLCHUNKS_AVAILABLE = -43, I40E_ERR_INVALID_PBLE_INDEX = -44, I40E_ERR_INVALID_SD_INDEX = -45, I40E_ERR_INVALID_PAGE_DESC_INDEX = -46, I40E_ERR_INVALID_SD_TYPE = -47, I40E_ERR_MEMCPY_FAILED = -48, I40E_ERR_INVALID_HMC_OBJ_INDEX = -49, I40E_ERR_INVALID_HMC_OBJ_COUNT = -50, I40E_ERR_INVALID_SRQ_ARM_LIMIT = -51, I40E_ERR_SRQ_ENABLED = -52, I40E_ERR_ADMIN_QUEUE_ERROR = -53, I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54, I40E_ERR_BUF_TOO_SHORT = -55, I40E_ERR_ADMIN_QUEUE_FULL = -56, I40E_ERR_ADMIN_QUEUE_NO_WORK = -57, I40E_ERR_BAD_IWARP_CQE = -58, I40E_ERR_NVM_BLANK_MODE = -59, I40E_ERR_NOT_IMPLEMENTED = -60, I40E_ERR_PE_DOORBELL_NOT_ENABLED = -61, I40E_ERR_DIAG_TEST_FAILED = -62, I40E_ERR_NOT_READY = -63, I40E_NOT_SUPPORTED = -64, I40E_ERR_FIRMWARE_API_VERSION = -65, }; #endif /* _I40E_STATUS_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_type.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_TYPE_H_ #define _I40E_TYPE_H_ #include "i40e_status.h" #include "i40e_osdep.h" #include "i40e_register.h" #include "i40e_adminq.h" #include "i40e_hmc.h" #include "i40e_lan_hmc.h" #define UNREFERENCED_XPARAMETER #define UNREFERENCED_1PARAMETER(_p) (_p); #define UNREFERENCED_2PARAMETER(_p, _q) (_p); (_q); #define UNREFERENCED_3PARAMETER(_p, _q, _r) (_p); (_q); (_r); #define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) (_p); (_q); (_r); (_s); #define UNREFERENCED_5PARAMETER(_p, _q, _r, _s, _t) (_p); (_q); (_r); (_s); (_t); /* Vendor ID */ #define I40E_INTEL_VENDOR_ID 0x8086 /* Device IDs */ #define I40E_DEV_ID_SFP_XL710 0x1572 #define I40E_DEV_ID_QEMU 0x1574 #define I40E_DEV_ID_KX_A 0x157F #define I40E_DEV_ID_KX_B 0x1580 #define I40E_DEV_ID_KX_C 0x1581 #define I40E_DEV_ID_QSFP_A 0x1583 #define I40E_DEV_ID_QSFP_B 0x1584 #define I40E_DEV_ID_QSFP_C 0x1585 #define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 #define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ (d) == I40E_DEV_ID_QSFP_B || \ (d) == I40E_DEV_ID_QSFP_C) #ifndef I40E_MASK /* I40E_MASK is a macro used on 32 bit registers */ #define I40E_MASK(mask, shift) (mask << shift) #endif #define I40E_MAX_PF 16 #define I40E_MAX_PF_VSI 64 #define I40E_MAX_PF_QP 128 #define I40E_MAX_VSI_QP 16 #define I40E_MAX_VF_VSI 3 #define I40E_MAX_CHAINED_RX_BUFFERS 5 #define I40E_MAX_PF_UDP_OFFLOAD_PORTS 16 /* something less than 1 minute */ #define I40E_HEARTBEAT_TIMEOUT (HZ * 50) /* Max default timeout in ms, */ #define I40E_MAX_NVM_TIMEOUT 18000 /* Check whether address is multicast. */ #define I40E_IS_MULTICAST(address) (bool)(((u8 *)(address))[0] & ((u8)0x01)) /* Check whether an address is broadcast. */ #define I40E_IS_BROADCAST(address) \ ((((u8 *)(address))[0] == ((u8)0xff)) && \ (((u8 *)(address))[1] == ((u8)0xff))) /* Switch from ms to the 1usec global time (this is the GTIME resolution) */ #define I40E_MS_TO_GTIME(time) ((time) * 1000) /* forward declaration */ struct i40e_hw; typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *); #define I40E_ETH_LENGTH_OF_ADDRESS 6 /* Data type manipulation macros. */ #define I40E_HI_DWORD(x) ((u32)((((x) >> 16) >> 16) & 0xFFFFFFFF)) #define I40E_LO_DWORD(x) ((u32)((x) & 0xFFFFFFFF)) #define I40E_HI_WORD(x) ((u16)(((x) >> 16) & 0xFFFF)) #define I40E_LO_WORD(x) ((u16)((x) & 0xFFFF)) #define I40E_HI_BYTE(x) ((u8)(((x) >> 8) & 0xFF)) #define I40E_LO_BYTE(x) ((u8)((x) & 0xFF)) /* Number of Transmit Descriptors must be a multiple of 8. */ #define I40E_REQ_TX_DESCRIPTOR_MULTIPLE 8 /* Number of Receive Descriptors must be a multiple of 32 if * the number of descriptors is greater than 32. */ #define I40E_REQ_RX_DESCRIPTOR_MULTIPLE 32 #define I40E_DESC_UNUSED(R) \ ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ (R)->next_to_clean - (R)->next_to_use - 1) /* bitfields for Tx queue mapping in QTX_CTL */ #define I40E_QTX_CTL_VF_QUEUE 0x0 #define I40E_QTX_CTL_VM_QUEUE 0x1 #define I40E_QTX_CTL_PF_QUEUE 0x2 /* debug masks - set these bits in hw->debug_mask to control output */ enum i40e_debug_mask { I40E_DEBUG_INIT = 0x00000001, I40E_DEBUG_RELEASE = 0x00000002, I40E_DEBUG_LINK = 0x00000010, I40E_DEBUG_PHY = 0x00000020, I40E_DEBUG_HMC = 0x00000040, I40E_DEBUG_NVM = 0x00000080, I40E_DEBUG_LAN = 0x00000100, I40E_DEBUG_FLOW = 0x00000200, I40E_DEBUG_DCB = 0x00000400, I40E_DEBUG_DIAG = 0x00000800, I40E_DEBUG_FD = 0x00001000, I40E_DEBUG_AQ_MESSAGE = 0x01000000, I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000, I40E_DEBUG_AQ_DESC_BUFFER = 0x04000000, I40E_DEBUG_AQ_COMMAND = 0x06000000, I40E_DEBUG_AQ = 0x0F000000, I40E_DEBUG_USER = 0xF0000000, I40E_DEBUG_ALL = 0xFFFFFFFF }; /* PCI Bus Info */ #define I40E_PCI_LINK_STATUS 0xB2 #define I40E_PCI_LINK_WIDTH 0x3F0 #define I40E_PCI_LINK_WIDTH_1 0x10 #define I40E_PCI_LINK_WIDTH_2 0x20 #define I40E_PCI_LINK_WIDTH_4 0x40 #define I40E_PCI_LINK_WIDTH_8 0x80 #define I40E_PCI_LINK_SPEED 0xF #define I40E_PCI_LINK_SPEED_2500 0x1 #define I40E_PCI_LINK_SPEED_5000 0x2 #define I40E_PCI_LINK_SPEED_8000 0x3 /* Memory types */ enum i40e_memset_type { I40E_NONDMA_MEM = 0, I40E_DMA_MEM }; /* Memcpy types */ enum i40e_memcpy_type { I40E_NONDMA_TO_NONDMA = 0, I40E_NONDMA_TO_DMA, I40E_DMA_TO_DMA, I40E_DMA_TO_NONDMA }; /* These are structs for managing the hardware information and the operations. * The structures of function pointers are filled out at init time when we * know for sure exactly which hardware we're working with. This gives us the * flexibility of using the same main driver code but adapting to slightly * different hardware needs as new parts are developed. For this architecture, * the Firmware and AdminQ are intended to insulate the driver from most of the * future changes, but these structures will also do part of the job. */ enum i40e_mac_type { I40E_MAC_UNKNOWN = 0, I40E_MAC_X710, I40E_MAC_XL710, I40E_MAC_VF, I40E_MAC_GENERIC, }; enum i40e_media_type { I40E_MEDIA_TYPE_UNKNOWN = 0, I40E_MEDIA_TYPE_FIBER, I40E_MEDIA_TYPE_BASET, I40E_MEDIA_TYPE_BACKPLANE, I40E_MEDIA_TYPE_CX4, I40E_MEDIA_TYPE_DA, I40E_MEDIA_TYPE_VIRTUAL }; enum i40e_fc_mode { I40E_FC_NONE = 0, I40E_FC_RX_PAUSE, I40E_FC_TX_PAUSE, I40E_FC_FULL, I40E_FC_PFC, I40E_FC_DEFAULT }; enum i40e_set_fc_aq_failures { I40E_SET_FC_AQ_FAIL_NONE = 0, I40E_SET_FC_AQ_FAIL_GET = 1, I40E_SET_FC_AQ_FAIL_SET = 2, I40E_SET_FC_AQ_FAIL_UPDATE = 4, I40E_SET_FC_AQ_FAIL_SET_UPDATE = 6 }; enum i40e_vsi_type { I40E_VSI_MAIN = 0, I40E_VSI_VMDQ1, I40E_VSI_VMDQ2, I40E_VSI_CTRL, I40E_VSI_FCOE, I40E_VSI_MIRROR, I40E_VSI_SRIOV, I40E_VSI_FDIR, I40E_VSI_TYPE_UNKNOWN }; enum i40e_queue_type { I40E_QUEUE_TYPE_RX = 0, I40E_QUEUE_TYPE_TX, I40E_QUEUE_TYPE_PE_CEQ, I40E_QUEUE_TYPE_UNKNOWN }; struct i40e_link_status { enum i40e_aq_phy_type phy_type; enum i40e_aq_link_speed link_speed; u8 link_info; u8 an_info; u8 ext_info; u8 loopback; /* is Link Status Event notification to SW enabled */ bool lse_enable; u16 max_frame_size; bool crc_enable; u8 pacing; u8 requested_speeds; }; struct i40e_phy_info { struct i40e_link_status link_info; struct i40e_link_status link_info_old; u32 autoneg_advertised; u32 phy_id; u32 module_type; bool get_link_info; enum i40e_media_type media_type; }; #define I40E_HW_CAP_MAX_GPIO 30 #define I40E_HW_CAP_MDIO_PORT_MODE_MDIO 0 #define I40E_HW_CAP_MDIO_PORT_MODE_I2C 1 /* Capabilities of a PF or a VF or the whole device */ struct i40e_hw_capabilities { u32 switch_mode; #define I40E_NVM_IMAGE_TYPE_EVB 0x0 #define I40E_NVM_IMAGE_TYPE_CLOUD 0x2 #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD 0x3 u32 management_mode; u32 npar_enable; u32 os2bmc; u32 valid_functions; bool sr_iov_1_1; bool vmdq; bool evb_802_1_qbg; /* Edge Virtual Bridging */ bool evb_802_1_qbh; /* Bridge Port Extension */ bool dcb; bool fcoe; bool iscsi; /* Indicates iSCSI enabled */ bool mfp_mode_1; bool mgmt_cem; bool ieee_1588; bool iwarp; bool fd; u32 fd_filters_guaranteed; u32 fd_filters_best_effort; bool rss; u32 rss_table_size; u32 rss_table_entry_width; bool led[I40E_HW_CAP_MAX_GPIO]; bool sdp[I40E_HW_CAP_MAX_GPIO]; u32 nvm_image_type; u32 num_flow_director_filters; u32 num_vfs; u32 vf_base_id; u32 num_vsis; u32 num_rx_qp; u32 num_tx_qp; u32 base_queue; u32 num_msix_vectors; u32 num_msix_vectors_vf; u32 led_pin_num; u32 sdp_pin_num; u32 mdio_port_num; u32 mdio_port_mode; u8 rx_buf_chain_len; u32 enabled_tcmap; u32 maxtc; }; struct i40e_mac_info { enum i40e_mac_type type; u8 addr[I40E_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[I40E_ETH_LENGTH_OF_ADDRESS]; u8 san_addr[I40E_ETH_LENGTH_OF_ADDRESS]; u8 port_addr[I40E_ETH_LENGTH_OF_ADDRESS]; u16 max_fcoeq; }; enum i40e_aq_resources_ids { I40E_NVM_RESOURCE_ID = 1 }; enum i40e_aq_resource_access_type { I40E_RESOURCE_READ = 1, I40E_RESOURCE_WRITE }; struct i40e_nvm_info { u64 hw_semaphore_timeout; /* usec global time (GTIME resolution) */ u32 timeout; /* [ms] */ u16 sr_size; /* Shadow RAM size in words */ bool blank_nvm_mode; /* is NVM empty (no FW present)*/ u16 version; /* NVM package version */ u32 eetrack; /* NVM data version */ }; /* definitions used in NVM update support */ enum i40e_nvmupd_cmd { I40E_NVMUPD_INVALID, I40E_NVMUPD_READ_CON, I40E_NVMUPD_READ_SNT, I40E_NVMUPD_READ_LCB, I40E_NVMUPD_READ_SA, I40E_NVMUPD_WRITE_ERA, I40E_NVMUPD_WRITE_CON, I40E_NVMUPD_WRITE_SNT, I40E_NVMUPD_WRITE_LCB, I40E_NVMUPD_WRITE_SA, I40E_NVMUPD_CSUM_CON, I40E_NVMUPD_CSUM_SA, I40E_NVMUPD_CSUM_LCB, }; enum i40e_nvmupd_state { I40E_NVMUPD_STATE_INIT, I40E_NVMUPD_STATE_READING, I40E_NVMUPD_STATE_WRITING }; /* nvm_access definition and its masks/shifts need to be accessible to * application, core driver, and shared code. Where is the right file? */ #define I40E_NVM_READ 0xB #define I40E_NVM_WRITE 0xC #define I40E_NVM_MOD_PNT_MASK 0xFF #define I40E_NVM_TRANS_SHIFT 8 #define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT) #define I40E_NVM_CON 0x0 #define I40E_NVM_SNT 0x1 #define I40E_NVM_LCB 0x2 #define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB) #define I40E_NVM_ERA 0x4 #define I40E_NVM_CSUM 0x8 #define I40E_NVM_ADAPT_SHIFT 16 #define I40E_NVM_ADAPT_MASK (0xffffULL << I40E_NVM_ADAPT_SHIFT) #define I40E_NVMUPD_MAX_DATA 4096 #define I40E_NVMUPD_IFACE_TIMEOUT 2 /* seconds */ struct i40e_nvm_access { u32 command; u32 config; u32 offset; /* in bytes */ u32 data_size; /* in bytes */ u8 data[1]; }; /* PCI bus types */ enum i40e_bus_type { i40e_bus_type_unknown = 0, i40e_bus_type_pci, i40e_bus_type_pcix, i40e_bus_type_pci_express, i40e_bus_type_reserved }; /* PCI bus speeds */ enum i40e_bus_speed { i40e_bus_speed_unknown = 0, i40e_bus_speed_33 = 33, i40e_bus_speed_66 = 66, i40e_bus_speed_100 = 100, i40e_bus_speed_120 = 120, i40e_bus_speed_133 = 133, i40e_bus_speed_2500 = 2500, i40e_bus_speed_5000 = 5000, i40e_bus_speed_8000 = 8000, i40e_bus_speed_reserved }; /* PCI bus widths */ enum i40e_bus_width { i40e_bus_width_unknown = 0, i40e_bus_width_pcie_x1 = 1, i40e_bus_width_pcie_x2 = 2, i40e_bus_width_pcie_x4 = 4, i40e_bus_width_pcie_x8 = 8, i40e_bus_width_32 = 32, i40e_bus_width_64 = 64, i40e_bus_width_reserved }; /* Bus parameters */ struct i40e_bus_info { enum i40e_bus_speed speed; enum i40e_bus_width width; enum i40e_bus_type type; u16 func; u16 device; u16 lan_id; }; /* Flow control (FC) parameters */ struct i40e_fc_info { enum i40e_fc_mode current_mode; /* FC mode in effect */ enum i40e_fc_mode requested_mode; /* FC mode requested by caller */ }; #define I40E_MAX_TRAFFIC_CLASS 8 #define I40E_MAX_USER_PRIORITY 8 #define I40E_DCBX_MAX_APPS 32 #define I40E_LLDPDU_SIZE 1500 #define I40E_TLV_STATUS_OPER 0x1 #define I40E_TLV_STATUS_SYNC 0x2 #define I40E_TLV_STATUS_ERR 0x4 #define I40E_CEE_OPER_MAX_APPS 3 #define I40E_APP_PROTOID_FCOE 0x8906 #define I40E_APP_PROTOID_ISCSI 0x0cbc #define I40E_APP_PROTOID_FIP 0x8914 #define I40E_APP_SEL_ETHTYPE 0x1 #define I40E_APP_SEL_TCPIP 0x2 /* CEE or IEEE 802.1Qaz ETS Configuration data */ struct i40e_dcb_ets_config { u8 willing; u8 cbs; u8 maxtcs; u8 prioritytable[I40E_MAX_TRAFFIC_CLASS]; u8 tcbwtable[I40E_MAX_TRAFFIC_CLASS]; u8 tsatable[I40E_MAX_TRAFFIC_CLASS]; }; /* CEE or IEEE 802.1Qaz PFC Configuration data */ struct i40e_dcb_pfc_config { u8 willing; u8 mbc; u8 pfccap; u8 pfcenable; }; /* CEE or IEEE 802.1Qaz Application Priority data */ struct i40e_dcb_app_priority_table { u8 priority; u8 selector; u16 protocolid; }; struct i40e_dcbx_config { u8 dcbx_mode; #define I40E_DCBX_MODE_CEE 0x1 #define I40E_DCBX_MODE_IEEE 0x2 u32 numapps; struct i40e_dcb_ets_config etscfg; struct i40e_dcb_ets_config etsrec; struct i40e_dcb_pfc_config pfc; struct i40e_dcb_app_priority_table app[I40E_DCBX_MAX_APPS]; }; /* Port hardware description */ struct i40e_hw { u8 *hw_addr; void *back; /* subsystem structs */ struct i40e_phy_info phy; struct i40e_mac_info mac; struct i40e_bus_info bus; struct i40e_nvm_info nvm; struct i40e_fc_info fc; /* pci info */ u16 device_id; u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; u8 revision_id; u8 port; bool adapter_stopped; /* capabilities for entire device and PCI func */ struct i40e_hw_capabilities dev_caps; struct i40e_hw_capabilities func_caps; /* Flow Director shared filter space */ u16 fdir_shared_filter_count; /* device profile info */ u8 pf_id; u16 main_vsi_seid; /* for multi-function MACs */ u16 partition_id; u16 num_partitions; u16 num_ports; /* Closest numa node to the device */ u16 numa_node; /* Admin Queue info */ struct i40e_adminq_info aq; /* state of nvm update process */ enum i40e_nvmupd_state nvmupd_state; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ /* LLDP/DCBX Status */ u16 dcbx_status; /* DCBX info */ struct i40e_dcbx_config local_dcbx_config; struct i40e_dcbx_config remote_dcbx_config; /* debug mask */ u32 debug_mask; }; static inline bool i40e_is_vf(struct i40e_hw *hw) { return hw->mac.type == I40E_MAC_VF; } struct i40e_driver_version { u8 major_version; u8 minor_version; u8 build_version; u8 subbuild_version; u8 driver_string[32]; }; /* RX Descriptors */ union i40e_16byte_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { struct { union { __le16 mirroring_status; __le16 fcoe_ctx_id; } mirr_fcoe; __le16 l2tag1; } lo_dword; union { __le32 rss; /* RSS Hash */ __le32 fd_id; /* Flow director filter id */ __le32 fcoe_param; /* FCoE DDP Context id */ } hi_dword; } qword0; struct { /* ext status/error/pktype/length */ __le64 status_error_len; } qword1; } wb; /* writeback */ }; union i40e_32byte_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ /* bit 0 of hdr_buffer_addr is DD bit */ __le64 rsvd1; __le64 rsvd2; } read; struct { struct { struct { union { __le16 mirroring_status; __le16 fcoe_ctx_id; } mirr_fcoe; __le16 l2tag1; } lo_dword; union { __le32 rss; /* RSS Hash */ __le32 fcoe_param; /* FCoE DDP Context id */ /* Flow director filter id in case of * Programming status desc WB */ __le32 fd_id; } hi_dword; } qword0; struct { /* status/error/pktype/length */ __le64 status_error_len; } qword1; struct { __le16 ext_status; /* extended status */ __le16 rsvd; __le16 l2tag2_1; __le16 l2tag2_2; } qword2; struct { union { __le32 flex_bytes_lo; __le32 pe_status; } lo_dword; union { __le32 flex_bytes_hi; __le32 fd_id; } hi_dword; } qword3; } wb; /* writeback */ }; #define I40E_RXD_QW0_MIRROR_STATUS_SHIFT 8 #define I40E_RXD_QW0_MIRROR_STATUS_MASK (0x3FUL << \ I40E_RXD_QW0_MIRROR_STATUS_SHIFT) #define I40E_RXD_QW0_FCOEINDX_SHIFT 0 #define I40E_RXD_QW0_FCOEINDX_MASK (0xFFFUL << \ I40E_RXD_QW0_FCOEINDX_SHIFT) enum i40e_rx_desc_status_bits { /* Note: These are predefined bit offsets */ I40E_RX_DESC_STATUS_DD_SHIFT = 0, I40E_RX_DESC_STATUS_EOF_SHIFT = 1, I40E_RX_DESC_STATUS_L2TAG1P_SHIFT = 2, I40E_RX_DESC_STATUS_L3L4P_SHIFT = 3, I40E_RX_DESC_STATUS_CRCP_SHIFT = 4, I40E_RX_DESC_STATUS_TSYNINDX_SHIFT = 5, /* 2 BITS */ I40E_RX_DESC_STATUS_TSYNVALID_SHIFT = 7, I40E_RX_DESC_STATUS_RESERVED1_SHIFT = 8, I40E_RX_DESC_STATUS_UMBCAST_SHIFT = 9, /* 2 BITS */ I40E_RX_DESC_STATUS_FLM_SHIFT = 11, I40E_RX_DESC_STATUS_FLTSTAT_SHIFT = 12, /* 2 BITS */ I40E_RX_DESC_STATUS_LPBK_SHIFT = 14, I40E_RX_DESC_STATUS_IPV6EXADD_SHIFT = 15, I40E_RX_DESC_STATUS_RESERVED2_SHIFT = 16, /* 2 BITS */ I40E_RX_DESC_STATUS_UDP_0_SHIFT = 18, I40E_RX_DESC_STATUS_LAST /* this entry must be last!!! */ }; #define I40E_RXD_QW1_STATUS_SHIFT 0 #define I40E_RXD_QW1_STATUS_MASK (((1 << I40E_RX_DESC_STATUS_LAST) - 1) << \ I40E_RXD_QW1_STATUS_SHIFT) #define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT I40E_RX_DESC_STATUS_TSYNINDX_SHIFT #define I40E_RXD_QW1_STATUS_TSYNINDX_MASK (0x3UL << \ I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT) #define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT I40E_RX_DESC_STATUS_TSYNVALID_SHIFT #define I40E_RXD_QW1_STATUS_TSYNVALID_MASK (0x1UL << \ I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT) #define I40E_RXD_QW1_STATUS_UMBCAST_SHIFT I40E_RX_DESC_STATUS_UMBCAST #define I40E_RXD_QW1_STATUS_UMBCAST_MASK (0x3UL << \ I40E_RXD_QW1_STATUS_UMBCAST_SHIFT) enum i40e_rx_desc_fltstat_values { I40E_RX_DESC_FLTSTAT_NO_DATA = 0, I40E_RX_DESC_FLTSTAT_RSV_FD_ID = 1, /* 16byte desc? FD_ID : RSV */ I40E_RX_DESC_FLTSTAT_RSV = 2, I40E_RX_DESC_FLTSTAT_RSS_HASH = 3, }; #define I40E_RXD_PACKET_TYPE_UNICAST 0 #define I40E_RXD_PACKET_TYPE_MULTICAST 1 #define I40E_RXD_PACKET_TYPE_BROADCAST 2 #define I40E_RXD_PACKET_TYPE_MIRRORED 3 #define I40E_RXD_QW1_ERROR_SHIFT 19 #define I40E_RXD_QW1_ERROR_MASK (0xFFUL << I40E_RXD_QW1_ERROR_SHIFT) enum i40e_rx_desc_error_bits { /* Note: These are predefined bit offsets */ I40E_RX_DESC_ERROR_RXE_SHIFT = 0, I40E_RX_DESC_ERROR_RECIPE_SHIFT = 1, I40E_RX_DESC_ERROR_HBO_SHIFT = 2, I40E_RX_DESC_ERROR_L3L4E_SHIFT = 3, /* 3 BITS */ I40E_RX_DESC_ERROR_IPE_SHIFT = 3, I40E_RX_DESC_ERROR_L4E_SHIFT = 4, I40E_RX_DESC_ERROR_EIPE_SHIFT = 5, I40E_RX_DESC_ERROR_OVERSIZE_SHIFT = 6, I40E_RX_DESC_ERROR_PPRS_SHIFT = 7 }; enum i40e_rx_desc_error_l3l4e_fcoe_masks { I40E_RX_DESC_ERROR_L3L4E_NONE = 0, I40E_RX_DESC_ERROR_L3L4E_PROT = 1, I40E_RX_DESC_ERROR_L3L4E_FC = 2, I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR = 3, I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN = 4 }; #define I40E_RXD_QW1_PTYPE_SHIFT 30 #define I40E_RXD_QW1_PTYPE_MASK (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT) /* Packet type non-ip values */ enum i40e_rx_l2_ptype { I40E_RX_PTYPE_L2_RESERVED = 0, I40E_RX_PTYPE_L2_MAC_PAY2 = 1, I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2, I40E_RX_PTYPE_L2_FIP_PAY2 = 3, I40E_RX_PTYPE_L2_OUI_PAY2 = 4, I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5, I40E_RX_PTYPE_L2_LLDP_PAY2 = 6, I40E_RX_PTYPE_L2_ECP_PAY2 = 7, I40E_RX_PTYPE_L2_EVB_PAY2 = 8, I40E_RX_PTYPE_L2_QCN_PAY2 = 9, I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10, I40E_RX_PTYPE_L2_ARP = 11, I40E_RX_PTYPE_L2_FCOE_PAY3 = 12, I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13, I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14, I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15, I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16, I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17, I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18, I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19, I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20, I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21, I40E_RX_PTYPE_GRENAT4_MAC_PAY3 = 58, I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87, I40E_RX_PTYPE_GRENAT6_MAC_PAY3 = 124, I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153 }; struct i40e_rx_ptype_decoded { u32 ptype:8; u32 known:1; u32 outer_ip:1; u32 outer_ip_ver:1; u32 outer_frag:1; u32 tunnel_type:3; u32 tunnel_end_prot:2; u32 tunnel_end_frag:1; u32 inner_prot:4; u32 payload_layer:3; }; enum i40e_rx_ptype_outer_ip { I40E_RX_PTYPE_OUTER_L2 = 0, I40E_RX_PTYPE_OUTER_IP = 1 }; enum i40e_rx_ptype_outer_ip_ver { I40E_RX_PTYPE_OUTER_NONE = 0, I40E_RX_PTYPE_OUTER_IPV4 = 0, I40E_RX_PTYPE_OUTER_IPV6 = 1 }; enum i40e_rx_ptype_outer_fragmented { I40E_RX_PTYPE_NOT_FRAG = 0, I40E_RX_PTYPE_FRAG = 1 }; enum i40e_rx_ptype_tunnel_type { I40E_RX_PTYPE_TUNNEL_NONE = 0, I40E_RX_PTYPE_TUNNEL_IP_IP = 1, I40E_RX_PTYPE_TUNNEL_IP_GRENAT = 2, I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3, I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4, }; enum i40e_rx_ptype_tunnel_end_prot { I40E_RX_PTYPE_TUNNEL_END_NONE = 0, I40E_RX_PTYPE_TUNNEL_END_IPV4 = 1, I40E_RX_PTYPE_TUNNEL_END_IPV6 = 2, }; enum i40e_rx_ptype_inner_prot { I40E_RX_PTYPE_INNER_PROT_NONE = 0, I40E_RX_PTYPE_INNER_PROT_UDP = 1, I40E_RX_PTYPE_INNER_PROT_TCP = 2, I40E_RX_PTYPE_INNER_PROT_SCTP = 3, I40E_RX_PTYPE_INNER_PROT_ICMP = 4, I40E_RX_PTYPE_INNER_PROT_TIMESYNC = 5 }; enum i40e_rx_ptype_payload_layer { I40E_RX_PTYPE_PAYLOAD_LAYER_NONE = 0, I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1, I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2, I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3, }; #define I40E_RX_PTYPE_BIT_MASK 0x0FFFFFFF #define I40E_RX_PTYPE_SHIFT 56 #define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38 #define I40E_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \ I40E_RXD_QW1_LENGTH_PBUF_SHIFT) #define I40E_RXD_QW1_LENGTH_HBUF_SHIFT 52 #define I40E_RXD_QW1_LENGTH_HBUF_MASK (0x7FFULL << \ I40E_RXD_QW1_LENGTH_HBUF_SHIFT) #define I40E_RXD_QW1_LENGTH_SPH_SHIFT 63 #define I40E_RXD_QW1_LENGTH_SPH_MASK (0x1ULL << \ I40E_RXD_QW1_LENGTH_SPH_SHIFT) #define I40E_RXD_QW1_NEXTP_SHIFT 38 #define I40E_RXD_QW1_NEXTP_MASK (0x1FFFULL << I40E_RXD_QW1_NEXTP_SHIFT) #define I40E_RXD_QW2_EXT_STATUS_SHIFT 0 #define I40E_RXD_QW2_EXT_STATUS_MASK (0xFFFFFUL << \ I40E_RXD_QW2_EXT_STATUS_SHIFT) enum i40e_rx_desc_ext_status_bits { /* Note: These are predefined bit offsets */ I40E_RX_DESC_EXT_STATUS_L2TAG2P_SHIFT = 0, I40E_RX_DESC_EXT_STATUS_L2TAG3P_SHIFT = 1, I40E_RX_DESC_EXT_STATUS_FLEXBL_SHIFT = 2, /* 2 BITS */ I40E_RX_DESC_EXT_STATUS_FLEXBH_SHIFT = 4, /* 2 BITS */ I40E_RX_DESC_EXT_STATUS_FDLONGB_SHIFT = 9, I40E_RX_DESC_EXT_STATUS_FCOELONGB_SHIFT = 10, I40E_RX_DESC_EXT_STATUS_PELONGB_SHIFT = 11, }; #define I40E_RXD_QW2_L2TAG2_SHIFT 0 #define I40E_RXD_QW2_L2TAG2_MASK (0xFFFFUL << I40E_RXD_QW2_L2TAG2_SHIFT) #define I40E_RXD_QW2_L2TAG3_SHIFT 16 #define I40E_RXD_QW2_L2TAG3_MASK (0xFFFFUL << I40E_RXD_QW2_L2TAG3_SHIFT) enum i40e_rx_desc_pe_status_bits { /* Note: These are predefined bit offsets */ I40E_RX_DESC_PE_STATUS_QPID_SHIFT = 0, /* 18 BITS */ I40E_RX_DESC_PE_STATUS_L4PORT_SHIFT = 0, /* 16 BITS */ I40E_RX_DESC_PE_STATUS_IPINDEX_SHIFT = 16, /* 8 BITS */ I40E_RX_DESC_PE_STATUS_QPIDHIT_SHIFT = 24, I40E_RX_DESC_PE_STATUS_APBVTHIT_SHIFT = 25, I40E_RX_DESC_PE_STATUS_PORTV_SHIFT = 26, I40E_RX_DESC_PE_STATUS_URG_SHIFT = 27, I40E_RX_DESC_PE_STATUS_IPFRAG_SHIFT = 28, I40E_RX_DESC_PE_STATUS_IPOPT_SHIFT = 29 }; #define I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT 38 #define I40E_RX_PROG_STATUS_DESC_LENGTH 0x2000000 #define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT 2 #define I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK (0x7UL << \ I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT) #define I40E_RX_PROG_STATUS_DESC_QW1_STATUS_SHIFT 0 #define I40E_RX_PROG_STATUS_DESC_QW1_STATUS_MASK (0x7FFFUL << \ I40E_RX_PROG_STATUS_DESC_QW1_STATUS_SHIFT) #define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT 19 #define I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK (0x3FUL << \ I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT) enum i40e_rx_prog_status_desc_status_bits { /* Note: These are predefined bit offsets */ I40E_RX_PROG_STATUS_DESC_DD_SHIFT = 0, I40E_RX_PROG_STATUS_DESC_PROG_ID_SHIFT = 2 /* 3 BITS */ }; enum i40e_rx_prog_status_desc_prog_id_masks { I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS = 1, I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_PROG_STATUS = 2, I40E_RX_PROG_STATUS_DESC_FCOE_CTXT_INVL_STATUS = 4, }; enum i40e_rx_prog_status_desc_error_bits { /* Note: These are predefined bit offsets */ I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT = 0, I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT = 1, I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT = 2, I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT = 3 }; #define I40E_TWO_BIT_MASK 0x3 #define I40E_THREE_BIT_MASK 0x7 #define I40E_FOUR_BIT_MASK 0xF #define I40E_EIGHTEEN_BIT_MASK 0x3FFFF /* TX Descriptor */ struct i40e_tx_desc { __le64 buffer_addr; /* Address of descriptor's data buf */ __le64 cmd_type_offset_bsz; }; #define I40E_TXD_QW1_DTYPE_SHIFT 0 #define I40E_TXD_QW1_DTYPE_MASK (0xFUL << I40E_TXD_QW1_DTYPE_SHIFT) enum i40e_tx_desc_dtype_value { I40E_TX_DESC_DTYPE_DATA = 0x0, I40E_TX_DESC_DTYPE_NOP = 0x1, /* same as Context desc */ I40E_TX_DESC_DTYPE_CONTEXT = 0x1, I40E_TX_DESC_DTYPE_FCOE_CTX = 0x2, I40E_TX_DESC_DTYPE_FILTER_PROG = 0x8, I40E_TX_DESC_DTYPE_DDP_CTX = 0x9, I40E_TX_DESC_DTYPE_FLEX_DATA = 0xB, I40E_TX_DESC_DTYPE_FLEX_CTX_1 = 0xC, I40E_TX_DESC_DTYPE_FLEX_CTX_2 = 0xD, I40E_TX_DESC_DTYPE_DESC_DONE = 0xF }; #define I40E_TXD_QW1_CMD_SHIFT 4 #define I40E_TXD_QW1_CMD_MASK (0x3FFUL << I40E_TXD_QW1_CMD_SHIFT) enum i40e_tx_desc_cmd_bits { I40E_TX_DESC_CMD_EOP = 0x0001, I40E_TX_DESC_CMD_RS = 0x0002, I40E_TX_DESC_CMD_ICRC = 0x0004, I40E_TX_DESC_CMD_IL2TAG1 = 0x0008, I40E_TX_DESC_CMD_DUMMY = 0x0010, I40E_TX_DESC_CMD_IIPT_NONIP = 0x0000, /* 2 BITS */ I40E_TX_DESC_CMD_IIPT_IPV6 = 0x0020, /* 2 BITS */ I40E_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */ I40E_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */ I40E_TX_DESC_CMD_FCOET = 0x0080, I40E_TX_DESC_CMD_L4T_EOFT_UNK = 0x0000, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_EOF_N = 0x0000, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_EOF_T = 0x0100, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_EOF_NI = 0x0200, /* 2 BITS */ I40E_TX_DESC_CMD_L4T_EOFT_EOF_A = 0x0300, /* 2 BITS */ }; #define I40E_TXD_QW1_OFFSET_SHIFT 16 #define I40E_TXD_QW1_OFFSET_MASK (0x3FFFFULL << \ I40E_TXD_QW1_OFFSET_SHIFT) enum i40e_tx_desc_length_fields { /* Note: These are predefined bit offsets */ I40E_TX_DESC_LENGTH_MACLEN_SHIFT = 0, /* 7 BITS */ I40E_TX_DESC_LENGTH_IPLEN_SHIFT = 7, /* 7 BITS */ I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT = 14 /* 4 BITS */ }; #define I40E_TXD_QW1_MACLEN_MASK (0x7FUL << I40E_TX_DESC_LENGTH_MACLEN_SHIFT) #define I40E_TXD_QW1_IPLEN_MASK (0x7FUL << I40E_TX_DESC_LENGTH_IPLEN_SHIFT) #define I40E_TXD_QW1_L4LEN_MASK (0xFUL << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT) #define I40E_TXD_QW1_FCLEN_MASK (0xFUL << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT) #define I40E_TXD_QW1_TX_BUF_SZ_SHIFT 34 #define I40E_TXD_QW1_TX_BUF_SZ_MASK (0x3FFFULL << \ I40E_TXD_QW1_TX_BUF_SZ_SHIFT) #define I40E_TXD_QW1_L2TAG1_SHIFT 48 #define I40E_TXD_QW1_L2TAG1_MASK (0xFFFFULL << I40E_TXD_QW1_L2TAG1_SHIFT) /* Context descriptors */ struct i40e_tx_context_desc { __le32 tunneling_params; __le16 l2tag2; __le16 rsvd; __le64 type_cmd_tso_mss; }; #define I40E_TXD_CTX_QW1_DTYPE_SHIFT 0 #define I40E_TXD_CTX_QW1_DTYPE_MASK (0xFUL << I40E_TXD_CTX_QW1_DTYPE_SHIFT) #define I40E_TXD_CTX_QW1_CMD_SHIFT 4 #define I40E_TXD_CTX_QW1_CMD_MASK (0xFFFFUL << I40E_TXD_CTX_QW1_CMD_SHIFT) enum i40e_tx_ctx_desc_cmd_bits { I40E_TX_CTX_DESC_TSO = 0x01, I40E_TX_CTX_DESC_TSYN = 0x02, I40E_TX_CTX_DESC_IL2TAG2 = 0x04, I40E_TX_CTX_DESC_IL2TAG2_IL2H = 0x08, I40E_TX_CTX_DESC_SWTCH_NOTAG = 0x00, I40E_TX_CTX_DESC_SWTCH_UPLINK = 0x10, I40E_TX_CTX_DESC_SWTCH_LOCAL = 0x20, I40E_TX_CTX_DESC_SWTCH_VSI = 0x30, I40E_TX_CTX_DESC_SWPE = 0x40 }; #define I40E_TXD_CTX_QW1_TSO_LEN_SHIFT 30 #define I40E_TXD_CTX_QW1_TSO_LEN_MASK (0x3FFFFULL << \ I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) #define I40E_TXD_CTX_QW1_MSS_SHIFT 50 #define I40E_TXD_CTX_QW1_MSS_MASK (0x3FFFULL << \ I40E_TXD_CTX_QW1_MSS_SHIFT) #define I40E_TXD_CTX_QW1_VSI_SHIFT 50 #define I40E_TXD_CTX_QW1_VSI_MASK (0x1FFULL << I40E_TXD_CTX_QW1_VSI_SHIFT) #define I40E_TXD_CTX_QW0_EXT_IP_SHIFT 0 #define I40E_TXD_CTX_QW0_EXT_IP_MASK (0x3ULL << \ I40E_TXD_CTX_QW0_EXT_IP_SHIFT) enum i40e_tx_ctx_desc_eipt_offload { I40E_TX_CTX_EXT_IP_NONE = 0x0, I40E_TX_CTX_EXT_IP_IPV6 = 0x1, I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM = 0x2, I40E_TX_CTX_EXT_IP_IPV4 = 0x3 }; #define I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT 2 #define I40E_TXD_CTX_QW0_EXT_IPLEN_MASK (0x3FULL << \ I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT) #define I40E_TXD_CTX_QW0_NATT_SHIFT 9 #define I40E_TXD_CTX_QW0_NATT_MASK (0x3ULL << I40E_TXD_CTX_QW0_NATT_SHIFT) #define I40E_TXD_CTX_UDP_TUNNELING (0x1ULL << I40E_TXD_CTX_QW0_NATT_SHIFT) #define I40E_TXD_CTX_GRE_TUNNELING (0x2ULL << I40E_TXD_CTX_QW0_NATT_SHIFT) #define I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT 11 #define I40E_TXD_CTX_QW0_EIP_NOINC_MASK (0x1ULL << \ I40E_TXD_CTX_QW0_EIP_NOINC_SHIFT) #define I40E_TXD_CTX_EIP_NOINC_IPID_CONST I40E_TXD_CTX_QW0_EIP_NOINC_MASK #define I40E_TXD_CTX_QW0_NATLEN_SHIFT 12 #define I40E_TXD_CTX_QW0_NATLEN_MASK (0X7FULL << \ I40E_TXD_CTX_QW0_NATLEN_SHIFT) #define I40E_TXD_CTX_QW0_DECTTL_SHIFT 19 #define I40E_TXD_CTX_QW0_DECTTL_MASK (0xFULL << \ I40E_TXD_CTX_QW0_DECTTL_SHIFT) struct i40e_nop_desc { __le64 rsvd; __le64 dtype_cmd; }; #define I40E_TXD_NOP_QW1_DTYPE_SHIFT 0 #define I40E_TXD_NOP_QW1_DTYPE_MASK (0xFUL << I40E_TXD_NOP_QW1_DTYPE_SHIFT) #define I40E_TXD_NOP_QW1_CMD_SHIFT 4 #define I40E_TXD_NOP_QW1_CMD_MASK (0x7FUL << I40E_TXD_NOP_QW1_CMD_SHIFT) enum i40e_tx_nop_desc_cmd_bits { /* Note: These are predefined bit offsets */ I40E_TX_NOP_DESC_EOP_SHIFT = 0, I40E_TX_NOP_DESC_RS_SHIFT = 1, I40E_TX_NOP_DESC_RSV_SHIFT = 2 /* 5 bits */ }; struct i40e_filter_program_desc { __le32 qindex_flex_ptype_vsi; __le32 rsvd; __le32 dtype_cmd_cntindex; __le32 fd_id; }; #define I40E_TXD_FLTR_QW0_QINDEX_SHIFT 0 #define I40E_TXD_FLTR_QW0_QINDEX_MASK (0x7FFUL << \ I40E_TXD_FLTR_QW0_QINDEX_SHIFT) #define I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT 11 #define I40E_TXD_FLTR_QW0_FLEXOFF_MASK (0x7UL << \ I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) #define I40E_TXD_FLTR_QW0_PCTYPE_SHIFT 17 #define I40E_TXD_FLTR_QW0_PCTYPE_MASK (0x3FUL << \ I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) /* Packet Classifier Types for filters */ enum i40e_filter_pctype { /* Note: Values 0-30 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_IPV4_UDP = 31, /* Note: Value 32 is reserved for future use */ I40E_FILTER_PCTYPE_NONF_IPV4_TCP = 33, I40E_FILTER_PCTYPE_NONF_IPV4_SCTP = 34, I40E_FILTER_PCTYPE_NONF_IPV4_OTHER = 35, I40E_FILTER_PCTYPE_FRAG_IPV4 = 36, /* Note: Values 37-40 are reserved for future use */ I40E_FILTER_PCTYPE_NONF_IPV6_UDP = 41, I40E_FILTER_PCTYPE_NONF_IPV6_TCP = 43, I40E_FILTER_PCTYPE_NONF_IPV6_SCTP = 44, I40E_FILTER_PCTYPE_NONF_IPV6_OTHER = 45, I40E_FILTER_PCTYPE_FRAG_IPV6 = 46, /* Note: Value 47 is reserved for future use */ I40E_FILTER_PCTYPE_FCOE_OX = 48, I40E_FILTER_PCTYPE_FCOE_RX = 49, I40E_FILTER_PCTYPE_FCOE_OTHER = 50, /* Note: Values 51-62 are reserved for future use */ I40E_FILTER_PCTYPE_L2_PAYLOAD = 63, }; enum i40e_filter_program_desc_dest { I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET = 0x0, I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX = 0x1, I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER = 0x2, }; enum i40e_filter_program_desc_fd_status { I40E_FILTER_PROGRAM_DESC_FD_STATUS_NONE = 0x0, I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID = 0x1, I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID_4FLEX_BYTES = 0x2, I40E_FILTER_PROGRAM_DESC_FD_STATUS_8FLEX_BYTES = 0x3, }; #define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23 #define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \ I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) #define I40E_TXD_FLTR_QW1_DTYPE_SHIFT 0 #define I40E_TXD_FLTR_QW1_DTYPE_MASK (0xFUL << I40E_TXD_FLTR_QW1_DTYPE_SHIFT) #define I40E_TXD_FLTR_QW1_CMD_SHIFT 4 #define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \ I40E_TXD_FLTR_QW1_CMD_SHIFT) #define I40E_TXD_FLTR_QW1_PCMD_SHIFT (0x0ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT) #define I40E_TXD_FLTR_QW1_PCMD_MASK (0x7ULL << I40E_TXD_FLTR_QW1_PCMD_SHIFT) enum i40e_filter_program_desc_pcmd { I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE = 0x1, I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE = 0x2, }; #define I40E_TXD_FLTR_QW1_DEST_SHIFT (0x3ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT) #define I40E_TXD_FLTR_QW1_DEST_MASK (0x3ULL << I40E_TXD_FLTR_QW1_DEST_SHIFT) #define I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT (0x7ULL + I40E_TXD_FLTR_QW1_CMD_SHIFT) #define I40E_TXD_FLTR_QW1_CNT_ENA_MASK (0x1ULL << \ I40E_TXD_FLTR_QW1_CNT_ENA_SHIFT) #define I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT (0x9ULL + \ I40E_TXD_FLTR_QW1_CMD_SHIFT) #define I40E_TXD_FLTR_QW1_FD_STATUS_MASK (0x3ULL << \ I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) #define I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT 20 #define I40E_TXD_FLTR_QW1_CNTINDEX_MASK (0x1FFUL << \ I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) enum i40e_filter_type { I40E_FLOW_DIRECTOR_FLTR = 0, I40E_PE_QUAD_HASH_FLTR = 1, I40E_ETHERTYPE_FLTR, I40E_FCOE_CTX_FLTR, I40E_MAC_VLAN_FLTR, I40E_HASH_FLTR }; struct i40e_vsi_context { u16 seid; u16 uplink_seid; u16 vsi_number; u16 vsis_allocated; u16 vsis_unallocated; u16 flags; u8 pf_num; u8 vf_num; u8 connection_type; struct i40e_aqc_vsi_properties_data info; }; struct i40e_veb_context { u16 seid; u16 uplink_seid; u16 veb_number; u16 vebs_allocated; u16 vebs_unallocated; u16 flags; struct i40e_aqc_get_veb_parameters_completion info; }; /* Statistics collected by each port, VSI, VEB, and S-channel */ struct i40e_eth_stats { u64 rx_bytes; /* gorc */ u64 rx_unicast; /* uprc */ u64 rx_multicast; /* mprc */ u64 rx_broadcast; /* bprc */ u64 rx_discards; /* rdpc */ u64 rx_unknown_protocol; /* rupp */ u64 tx_bytes; /* gotc */ u64 tx_unicast; /* uptc */ u64 tx_multicast; /* mptc */ u64 tx_broadcast; /* bptc */ u64 tx_discards; /* tdpc */ u64 tx_errors; /* tepc */ }; /* Statistics collected per VEB per TC */ struct i40e_veb_tc_stats { u64 tc_rx_packets[I40E_MAX_TRAFFIC_CLASS]; u64 tc_rx_bytes[I40E_MAX_TRAFFIC_CLASS]; u64 tc_tx_packets[I40E_MAX_TRAFFIC_CLASS]; u64 tc_tx_bytes[I40E_MAX_TRAFFIC_CLASS]; }; /* Statistics collected by the MAC */ struct i40e_hw_port_stats { /* eth stats collected by the port */ struct i40e_eth_stats eth; /* additional port specific stats */ u64 tx_dropped_link_down; /* tdold */ u64 crc_errors; /* crcerrs */ u64 illegal_bytes; /* illerrc */ u64 error_bytes; /* errbc */ u64 mac_local_faults; /* mlfc */ u64 mac_remote_faults; /* mrfc */ u64 rx_length_errors; /* rlec */ u64 link_xon_rx; /* lxonrxc */ u64 link_xoff_rx; /* lxoffrxc */ u64 priority_xon_rx[8]; /* pxonrxc[8] */ u64 priority_xoff_rx[8]; /* pxoffrxc[8] */ u64 link_xon_tx; /* lxontxc */ u64 link_xoff_tx; /* lxofftxc */ u64 priority_xon_tx[8]; /* pxontxc[8] */ u64 priority_xoff_tx[8]; /* pxofftxc[8] */ u64 priority_xon_2_xoff[8]; /* pxon2offc[8] */ u64 rx_size_64; /* prc64 */ u64 rx_size_127; /* prc127 */ u64 rx_size_255; /* prc255 */ u64 rx_size_511; /* prc511 */ u64 rx_size_1023; /* prc1023 */ u64 rx_size_1522; /* prc1522 */ u64 rx_size_big; /* prc9522 */ u64 rx_undersize; /* ruc */ u64 rx_fragments; /* rfc */ u64 rx_oversize; /* roc */ u64 rx_jabber; /* rjc */ u64 tx_size_64; /* ptc64 */ u64 tx_size_127; /* ptc127 */ u64 tx_size_255; /* ptc255 */ u64 tx_size_511; /* ptc511 */ u64 tx_size_1023; /* ptc1023 */ u64 tx_size_1522; /* ptc1522 */ u64 tx_size_big; /* ptc9522 */ u64 mac_short_packet_dropped; /* mspdc */ u64 checksum_error; /* xec */ /* flow director stats */ u64 fd_atr_match; u64 fd_sb_match; /* EEE LPI */ u32 tx_lpi_status; u32 rx_lpi_status; u64 tx_lpi_count; /* etlpic */ u64 rx_lpi_count; /* erlpic */ }; /* Checksum and Shadow RAM pointers */ #define I40E_SR_NVM_CONTROL_WORD 0x00 #define I40E_SR_PCIE_ANALOG_CONFIG_PTR 0x03 #define I40E_SR_PHY_ANALOG_CONFIG_PTR 0x04 #define I40E_SR_OPTION_ROM_PTR 0x05 #define I40E_SR_RO_PCIR_REGS_AUTO_LOAD_PTR 0x06 #define I40E_SR_AUTO_GENERATED_POINTERS_PTR 0x07 #define I40E_SR_PCIR_REGS_AUTO_LOAD_PTR 0x08 #define I40E_SR_EMP_GLOBAL_MODULE_PTR 0x09 #define I40E_SR_RO_PCIE_LCB_PTR 0x0A #define I40E_SR_EMP_IMAGE_PTR 0x0B #define I40E_SR_PE_IMAGE_PTR 0x0C #define I40E_SR_CSR_PROTECTED_LIST_PTR 0x0D #define I40E_SR_MNG_CONFIG_PTR 0x0E #define I40E_SR_EMP_MODULE_PTR 0x0F #define I40E_SR_PBA_FLAGS 0x15 #define I40E_SR_PBA_BLOCK_PTR 0x16 #define I40E_SR_BOOT_CONFIG_PTR 0x17 #define I40E_SR_NVM_DEV_STARTER_VERSION 0x18 #define I40E_SR_NVM_WAKE_ON_LAN 0x19 #define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27 #define I40E_SR_PERMANENT_SAN_MAC_ADDRESS_PTR 0x28 #define I40E_SR_NVM_MAP_VERSION 0x29 #define I40E_SR_NVM_IMAGE_VERSION 0x2A #define I40E_SR_NVM_STRUCTURE_VERSION 0x2B #define I40E_SR_NVM_EETRACK_LO 0x2D #define I40E_SR_NVM_EETRACK_HI 0x2E #define I40E_SR_VPD_PTR 0x2F #define I40E_SR_PXE_SETUP_PTR 0x30 #define I40E_SR_PXE_CONFIG_CUST_OPTIONS_PTR 0x31 #define I40E_SR_NVM_ORIGINAL_EETRACK_LO 0x34 #define I40E_SR_NVM_ORIGINAL_EETRACK_HI 0x35 #define I40E_SR_SW_ETHERNET_MAC_ADDRESS_PTR 0x37 #define I40E_SR_POR_REGS_AUTO_LOAD_PTR 0x38 #define I40E_SR_EMPR_REGS_AUTO_LOAD_PTR 0x3A #define I40E_SR_GLOBR_REGS_AUTO_LOAD_PTR 0x3B #define I40E_SR_CORER_REGS_AUTO_LOAD_PTR 0x3C #define I40E_SR_PCIE_ALT_AUTO_LOAD_PTR 0x3E #define I40E_SR_SW_CHECKSUM_WORD 0x3F #define I40E_SR_1ST_FREE_PROVISION_AREA_PTR 0x40 #define I40E_SR_4TH_FREE_PROVISION_AREA_PTR 0x42 #define I40E_SR_3RD_FREE_PROVISION_AREA_PTR 0x44 #define I40E_SR_2ND_FREE_PROVISION_AREA_PTR 0x46 #define I40E_SR_EMP_SR_SETTINGS_PTR 0x48 #define I40E_SR_FEATURE_CONFIGURATION_PTR 0x49 #define I40E_SR_CONFIGURATION_METADATA_PTR 0x4D #define I40E_SR_IMMEDIATE_VALUES_PTR 0x4E /* Auxiliary field, mask and shift definition for Shadow RAM and NVM Flash */ #define I40E_SR_VPD_MODULE_MAX_SIZE 1024 #define I40E_SR_PCIE_ALT_MODULE_MAX_SIZE 1024 #define I40E_SR_CONTROL_WORD_1_SHIFT 0x06 #define I40E_SR_CONTROL_WORD_1_MASK (0x03 << I40E_SR_CONTROL_WORD_1_SHIFT) /* Shadow RAM related */ #define I40E_SR_SECTOR_SIZE_IN_WORDS 0x800 #define I40E_SR_BUF_ALIGNMENT 4096 #define I40E_SR_WORDS_IN_1KB 512 /* Checksum should be calculated such that after adding all the words, * including the checksum word itself, the sum should be 0xBABA. */ #define I40E_SR_SW_CHECKSUM_BASE 0xBABA #define I40E_SRRD_SRCTL_ATTEMPTS 100000 enum i40e_switch_element_types { I40E_SWITCH_ELEMENT_TYPE_MAC = 1, I40E_SWITCH_ELEMENT_TYPE_PF = 2, I40E_SWITCH_ELEMENT_TYPE_VF = 3, I40E_SWITCH_ELEMENT_TYPE_EMP = 4, I40E_SWITCH_ELEMENT_TYPE_BMC = 6, I40E_SWITCH_ELEMENT_TYPE_PE = 16, I40E_SWITCH_ELEMENT_TYPE_VEB = 17, I40E_SWITCH_ELEMENT_TYPE_PA = 18, I40E_SWITCH_ELEMENT_TYPE_VSI = 19, }; /* Supported EtherType filters */ enum i40e_ether_type_index { I40E_ETHER_TYPE_1588 = 0, I40E_ETHER_TYPE_FIP = 1, I40E_ETHER_TYPE_OUI_EXTENDED = 2, I40E_ETHER_TYPE_MAC_CONTROL = 3, I40E_ETHER_TYPE_LLDP = 4, I40E_ETHER_TYPE_EVB_PROTOCOL1 = 5, I40E_ETHER_TYPE_EVB_PROTOCOL2 = 6, I40E_ETHER_TYPE_QCN_CNM = 7, I40E_ETHER_TYPE_8021X = 8, I40E_ETHER_TYPE_ARP = 9, I40E_ETHER_TYPE_RSV1 = 10, I40E_ETHER_TYPE_RSV2 = 11, }; /* Filter context base size is 1K */ #define I40E_HASH_FILTER_BASE_SIZE 1024 /* Supported Hash filter values */ enum i40e_hash_filter_size { I40E_HASH_FILTER_SIZE_1K = 0, I40E_HASH_FILTER_SIZE_2K = 1, I40E_HASH_FILTER_SIZE_4K = 2, I40E_HASH_FILTER_SIZE_8K = 3, I40E_HASH_FILTER_SIZE_16K = 4, I40E_HASH_FILTER_SIZE_32K = 5, I40E_HASH_FILTER_SIZE_64K = 6, I40E_HASH_FILTER_SIZE_128K = 7, I40E_HASH_FILTER_SIZE_256K = 8, I40E_HASH_FILTER_SIZE_512K = 9, I40E_HASH_FILTER_SIZE_1M = 10, }; /* DMA context base size is 0.5K */ #define I40E_DMA_CNTX_BASE_SIZE 512 /* Supported DMA context values */ enum i40e_dma_cntx_size { I40E_DMA_CNTX_SIZE_512 = 0, I40E_DMA_CNTX_SIZE_1K = 1, I40E_DMA_CNTX_SIZE_2K = 2, I40E_DMA_CNTX_SIZE_4K = 3, I40E_DMA_CNTX_SIZE_8K = 4, I40E_DMA_CNTX_SIZE_16K = 5, I40E_DMA_CNTX_SIZE_32K = 6, I40E_DMA_CNTX_SIZE_64K = 7, I40E_DMA_CNTX_SIZE_128K = 8, I40E_DMA_CNTX_SIZE_256K = 9, }; /* Supported Hash look up table (LUT) sizes */ enum i40e_hash_lut_size { I40E_HASH_LUT_SIZE_128 = 0, I40E_HASH_LUT_SIZE_512 = 1, }; /* Structure to hold a per PF filter control settings */ struct i40e_filter_control_settings { /* number of PE Quad Hash filter buckets */ enum i40e_hash_filter_size pe_filt_num; /* number of PE Quad Hash contexts */ enum i40e_dma_cntx_size pe_cntx_num; /* number of FCoE filter buckets */ enum i40e_hash_filter_size fcoe_filt_num; /* number of FCoE DDP contexts */ enum i40e_dma_cntx_size fcoe_cntx_num; /* size of the Hash LUT */ enum i40e_hash_lut_size hash_lut_size; /* enable FDIR filters for PF and its VFs */ bool enable_fdir; /* enable Ethertype filters for PF and its VFs */ bool enable_ethtype; /* enable MAC/VLAN filters for PF and its VFs */ bool enable_macvlan; }; /* Structure to hold device level control filter counts */ struct i40e_control_filter_stats { u16 mac_etype_used; /* Used perfect match MAC/EtherType filters */ u16 etype_used; /* Used perfect EtherType filters */ u16 mac_etype_free; /* Un-used perfect match MAC/EtherType filters */ u16 etype_free; /* Un-used perfect EtherType filters */ }; enum i40e_reset_type { I40E_RESET_POR = 0, I40E_RESET_CORER = 1, I40E_RESET_GLOBR = 2, I40E_RESET_EMPR = 3, }; /* IEEE 802.1AB LLDP Agent Variables from NVM */ #define I40E_NVM_LLDP_CFG_PTR 0xD struct i40e_lldp_variables { u16 length; u16 adminstatus; u16 msgfasttx; u16 msgtxinterval; u16 txparams; u16 timers; u16 crc8; }; /* Offsets into Alternate Ram */ #define I40E_ALT_STRUCT_FIRST_PF_OFFSET 0 /* in dwords */ #define I40E_ALT_STRUCT_DWORDS_PER_PF 64 /* in dwords */ #define I40E_ALT_STRUCT_OUTER_VLAN_TAG_OFFSET 0xD /* in dwords */ #define I40E_ALT_STRUCT_USER_PRIORITY_OFFSET 0xC /* in dwords */ #define I40E_ALT_STRUCT_MIN_BW_OFFSET 0xE /* in dwords */ #define I40E_ALT_STRUCT_MAX_BW_OFFSET 0xF /* in dwords */ /* Alternate Ram Bandwidth Masks */ #define I40E_ALT_BW_VALUE_MASK 0xFF #define I40E_ALT_BW_RELATIVE_MASK 0x40000000 #define I40E_ALT_BW_VALID_MASK 0x80000000 /* RSS Hash Table Size */ #define I40E_PFQF_CTL_0_HASHLUTSIZE_512 0x00010000 #endif /* _I40E_TYPE_H_ */ ================================================ FILE: drivers/net/i40e/base/i40e_virtchnl.h ================================================ /******************************************************************************* Copyright (c) 2013 - 2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _I40E_VIRTCHNL_H_ #define _I40E_VIRTCHNL_H_ #include "i40e_type.h" /* Description: * This header file describes the VF-PF communication protocol used * by the various i40e drivers. * * Admin queue buffer usage: * desc->opcode is always i40e_aqc_opc_send_msg_to_pf * flags, retval, datalen, and data addr are all used normally. * Firmware copies the cookie fields when sending messages between the PF and * VF, but uses all other fields internally. Due to this limitation, we * must send all messages as "indirect", i.e. using an external buffer. * * All the vsi indexes are relative to the VF. Each VF can have maximum of * three VSIs. All the queue indexes are relative to the VSI. Each VF can * have a maximum of sixteen queues for all of its VSIs. * * The PF is required to return a status code in v_retval for all messages * except RESET_VF, which does not require any response. The return value is of * i40e_status_code type, defined in the i40e_type.h. * * In general, VF driver initialization should roughly follow the order of these * opcodes. The VF driver must first validate the API version of the PF driver, * then request a reset, then get resources, then configure queues and * interrupts. After these operations are complete, the VF driver may start * its queues, optionally add MAC and VLAN filters, and process traffic. */ /* Opcodes for VF-PF communication. These are placed in the v_opcode field * of the virtchnl_msg structure. */ enum i40e_virtchnl_ops { /* The PF sends status change events to VFs using * the I40E_VIRTCHNL_OP_EVENT opcode. * VFs send requests to the PF using the other ops. */ I40E_VIRTCHNL_OP_UNKNOWN = 0, I40E_VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */ I40E_VIRTCHNL_OP_RESET_VF = 2, I40E_VIRTCHNL_OP_GET_VF_RESOURCES = 3, I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE = 4, I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE = 5, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES = 6, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP = 7, I40E_VIRTCHNL_OP_ENABLE_QUEUES = 8, I40E_VIRTCHNL_OP_DISABLE_QUEUES = 9, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS = 10, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS = 11, I40E_VIRTCHNL_OP_ADD_VLAN = 12, I40E_VIRTCHNL_OP_DEL_VLAN = 13, I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE = 14, I40E_VIRTCHNL_OP_GET_STATS = 15, I40E_VIRTCHNL_OP_FCOE = 16, I40E_VIRTCHNL_OP_EVENT = 17, I40E_VIRTCHNL_OP_CONFIG_RSS = 18, }; /* Virtual channel message descriptor. This overlays the admin queue * descriptor. All other data is passed in external buffers. */ struct i40e_virtchnl_msg { u8 pad[8]; /* AQ flags/opcode/len/retval fields */ enum i40e_virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */ enum i40e_status_code v_retval; /* ditto for desc->retval */ u32 vfid; /* used by PF when sending to VF */ }; /* Message descriptions and data structures.*/ /* I40E_VIRTCHNL_OP_VERSION * VF posts its version number to the PF. PF responds with its version number * in the same format, along with a return code. * Reply from PF has its major/minor versions also in param0 and param1. * If there is a major version mismatch, then the VF cannot operate. * If there is a minor version mismatch, then the VF can operate but should * add a warning to the system log. * * This enum element MUST always be specified as == 1, regardless of other * changes in the API. The PF must always respond to this message without * error regardless of version mismatch. */ #define I40E_VIRTCHNL_VERSION_MAJOR 1 #define I40E_VIRTCHNL_VERSION_MINOR 0 struct i40e_virtchnl_version_info { u32 major; u32 minor; }; /* I40E_VIRTCHNL_OP_RESET_VF * VF sends this request to PF with no parameters * PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register * until reset completion is indicated. The admin queue must be reinitialized * after this operation. * * When reset is complete, PF must ensure that all queues in all VSIs associated * with the VF are stopped, all queue configurations in the HMC are set to 0, * and all MAC and VLAN filters (except the default MAC address) on all VSIs * are cleared. */ /* I40E_VIRTCHNL_OP_GET_VF_RESOURCES * VF sends this request to PF with no parameters * PF responds with an indirect message containing * i40e_virtchnl_vf_resource and one or more * i40e_virtchnl_vsi_resource structures. */ struct i40e_virtchnl_vsi_resource { u16 vsi_id; u16 num_queue_pairs; enum i40e_vsi_type vsi_type; u16 qset_handle; u8 default_mac_addr[I40E_ETH_LENGTH_OF_ADDRESS]; }; /* VF offload flags */ #define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001 #define I40E_VIRTCHNL_VF_OFFLOAD_IWARP 0x00000002 #define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004 #define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000 struct i40e_virtchnl_vf_resource { u16 num_vsis; u16 num_queue_pairs; u16 max_vectors; u16 max_mtu; u32 vf_offload_flags; u32 max_fcoe_contexts; u32 max_fcoe_filters; struct i40e_virtchnl_vsi_resource vsi_res[1]; }; /* I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE * VF sends this message to set up parameters for one TX queue. * External data buffer contains one instance of i40e_virtchnl_txq_info. * PF configures requested queue and returns a status code. */ /* Tx queue config info */ struct i40e_virtchnl_txq_info { u16 vsi_id; u16 queue_id; u16 ring_len; /* number of descriptors, multiple of 8 */ u16 headwb_enabled; u64 dma_ring_addr; u64 dma_headwb_addr; }; /* I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE * VF sends this message to set up parameters for one RX queue. * External data buffer contains one instance of i40e_virtchnl_rxq_info. * PF configures requested queue and returns a status code. */ /* Rx queue config info */ struct i40e_virtchnl_rxq_info { u16 vsi_id; u16 queue_id; u32 ring_len; /* number of descriptors, multiple of 32 */ u16 hdr_size; u16 splithdr_enabled; u32 databuffer_size; u32 max_pkt_size; u64 dma_ring_addr; enum i40e_hmc_obj_rx_hsplit_0 rx_split_pos; }; /* I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES * VF sends this message to set parameters for all active TX and RX queues * associated with the specified VSI. * PF configures queues and returns status. * If the number of queues specified is greater than the number of queues * associated with the VSI, an error is returned and no queues are configured. */ struct i40e_virtchnl_queue_pair_info { /* NOTE: vsi_id and queue_id should be identical for both queues. */ struct i40e_virtchnl_txq_info txq; struct i40e_virtchnl_rxq_info rxq; }; struct i40e_virtchnl_vsi_queue_config_info { u16 vsi_id; u16 num_queue_pairs; struct i40e_virtchnl_queue_pair_info qpair[1]; }; /* I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP * VF uses this message to map vectors to queues. * The rxq_map and txq_map fields are bitmaps used to indicate which queues * are to be associated with the specified vector. * The "other" causes are always mapped to vector 0. * PF configures interrupt mapping and returns status. */ struct i40e_virtchnl_vector_map { u16 vsi_id; u16 vector_id; u16 rxq_map; u16 txq_map; u16 rxitr_idx; u16 txitr_idx; }; struct i40e_virtchnl_irq_map_info { u16 num_vectors; struct i40e_virtchnl_vector_map vecmap[1]; }; /* I40E_VIRTCHNL_OP_ENABLE_QUEUES * I40E_VIRTCHNL_OP_DISABLE_QUEUES * VF sends these message to enable or disable TX/RX queue pairs. * The queues fields are bitmaps indicating which queues to act upon. * (Currently, we only support 16 queues per VF, but we make the field * u32 to allow for expansion.) * PF performs requested action and returns status. */ struct i40e_virtchnl_queue_select { u16 vsi_id; u16 pad; u32 rx_queues; u32 tx_queues; }; /* I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS * VF sends this message in order to add one or more unicast or multicast * address filters for the specified VSI. * PF adds the filters and returns status. */ /* I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS * VF sends this message in order to remove one or more unicast or multicast * filters for the specified VSI. * PF removes the filters and returns status. */ struct i40e_virtchnl_ether_addr { u8 addr[I40E_ETH_LENGTH_OF_ADDRESS]; u8 pad[2]; }; struct i40e_virtchnl_ether_addr_list { u16 vsi_id; u16 num_elements; struct i40e_virtchnl_ether_addr list[1]; }; /* I40E_VIRTCHNL_OP_ADD_VLAN * VF sends this message to add one or more VLAN tag filters for receives. * PF adds the filters and returns status. * If a port VLAN is configured by the PF, this operation will return an * error to the VF. */ /* I40E_VIRTCHNL_OP_DEL_VLAN * VF sends this message to remove one or more VLAN tag filters for receives. * PF removes the filters and returns status. * If a port VLAN is configured by the PF, this operation will return an * error to the VF. */ struct i40e_virtchnl_vlan_filter_list { u16 vsi_id; u16 num_elements; u16 vlan_id[1]; }; /* I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE * VF sends VSI id and flags. * PF returns status code in retval. * Note: we assume that broadcast accept mode is always enabled. */ struct i40e_virtchnl_promisc_info { u16 vsi_id; u16 flags; }; #define I40E_FLAG_VF_UNICAST_PROMISC 0x00000001 #define I40E_FLAG_VF_MULTICAST_PROMISC 0x00000002 /* I40E_VIRTCHNL_OP_GET_STATS * VF sends this message to request stats for the selected VSI. VF uses * the i40e_virtchnl_queue_select struct to specify the VSI. The queue_id * field is ignored by the PF. * * PF replies with struct i40e_eth_stats in an external buffer. */ /* I40E_VIRTCHNL_OP_EVENT * PF sends this message to inform the VF driver of events that may affect it. * No direct response is expected from the VF, though it may generate other * messages in response to this one. */ enum i40e_virtchnl_event_codes { I40E_VIRTCHNL_EVENT_UNKNOWN = 0, I40E_VIRTCHNL_EVENT_LINK_CHANGE, I40E_VIRTCHNL_EVENT_RESET_IMPENDING, I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE, }; #define I40E_PF_EVENT_SEVERITY_INFO 0 #define I40E_PF_EVENT_SEVERITY_ATTENTION 1 #define I40E_PF_EVENT_SEVERITY_ACTION_REQUIRED 2 #define I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM 255 struct i40e_virtchnl_pf_event { enum i40e_virtchnl_event_codes event; union { struct { enum i40e_aq_link_speed link_speed; bool link_status; } link_event; } event_data; int severity; }; /* VF reset states - these are written into the RSTAT register: * I40E_VFGEN_RSTAT1 on the PF * I40E_VFGEN_RSTAT on the VF * When the PF initiates a reset, it writes 0 * When the reset is complete, it writes 1 * When the PF detects that the VF has recovered, it writes 2 * VF checks this register periodically to determine if a reset has occurred, * then polls it to know when the reset is complete. * If either the PF or VF reads the register while the hardware * is in a reset state, it will return DEADBEEF, which, when masked * will result in 3. */ enum i40e_vfr_states { I40E_VFR_INPROGRESS = 0, I40E_VFR_COMPLETED, I40E_VFR_VFACTIVE, I40E_VFR_UNKNOWN, }; #endif /* _I40E_VIRTCHNL_H_ */ ================================================ FILE: drivers/net/i40e/i40e_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i40e_logs.h" #include "base/i40e_prototype.h" #include "base/i40e_adminq_cmd.h" #include "base/i40e_type.h" #include "base/i40e_register.h" #include "i40e_ethdev.h" #include "i40e_rxtx.h" #include "i40e_pf.h" /* Maximun number of MAC addresses */ #define I40E_NUM_MACADDR_MAX 64 #define I40E_CLEAR_PXE_WAIT_MS 200 /* Maximun number of capability elements */ #define I40E_MAX_CAP_ELE_NUM 128 /* Wait count and inteval */ #define I40E_CHK_Q_ENA_COUNT 1000 #define I40E_CHK_Q_ENA_INTERVAL_US 1000 /* Maximun number of VSI */ #define I40E_MAX_NUM_VSIS (384UL) /* Default queue interrupt throttling time in microseconds */ #define I40E_ITR_INDEX_DEFAULT 0 #define I40E_QUEUE_ITR_INTERVAL_DEFAULT 32 /* 32 us */ #define I40E_QUEUE_ITR_INTERVAL_MAX 8160 /* 8160 us */ #define I40E_PRE_TX_Q_CFG_WAIT_US 10 /* 10 us */ /* Mask of PF interrupt causes */ #define I40E_PFINT_ICR0_ENA_MASK ( \ I40E_PFINT_ICR0_ENA_ECC_ERR_MASK | \ I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK | \ I40E_PFINT_ICR0_ENA_GRST_MASK | \ I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK | \ I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK | \ I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK | \ I40E_PFINT_ICR0_ENA_HMC_ERR_MASK | \ I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK | \ I40E_PFINT_ICR0_ENA_VFLR_MASK | \ I40E_PFINT_ICR0_ENA_ADMINQ_MASK) #define I40E_FLOW_TYPES ( \ (1UL << RTE_ETH_FLOW_FRAG_IPV4) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ (1UL << RTE_ETH_FLOW_FRAG_IPV6) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ (1UL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ (1UL << RTE_ETH_FLOW_L2_PAYLOAD)) #define I40E_PTP_40GB_INCVAL 0x0199999999ULL #define I40E_PTP_10GB_INCVAL 0x0333333333ULL #define I40E_PTP_1GB_INCVAL 0x2000000000ULL #define I40E_PRTTSYN_TSYNENA 0x80000000 #define I40E_PRTTSYN_TSYNTYPE 0x0e000000 static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev); static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev); static int i40e_dev_configure(struct rte_eth_dev *dev); static int i40e_dev_start(struct rte_eth_dev *dev); static void i40e_dev_stop(struct rte_eth_dev *dev); static void i40e_dev_close(struct rte_eth_dev *dev); static void i40e_dev_promiscuous_enable(struct rte_eth_dev *dev); static void i40e_dev_promiscuous_disable(struct rte_eth_dev *dev); static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev); static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev); static int i40e_dev_set_link_up(struct rte_eth_dev *dev); static int i40e_dev_set_link_down(struct rte_eth_dev *dev); static void i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void i40e_dev_stats_reset(struct rte_eth_dev *dev); static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx); static void i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void i40e_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid); static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on); static int i40e_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on); static int i40e_dev_led_on(struct rte_eth_dev *dev); static int i40e_dev_led_off(struct rte_eth_dev *dev); static int i40e_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int i40e_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf); static void i40e_macaddr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index); static int i40e_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int i40e_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int i40e_get_cap(struct i40e_hw *hw); static int i40e_pf_parameter_init(struct rte_eth_dev *dev); static int i40e_pf_setup(struct i40e_pf *pf); static int i40e_dev_rxtx_init(struct i40e_pf *pf); static int i40e_vmdq_setup(struct rte_eth_dev *dev); static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg, bool offset_loaded, uint64_t *offset, uint64_t *stat); static void i40e_stat_update_48(struct i40e_hw *hw, uint32_t hireg, uint32_t loreg, bool offset_loaded, uint64_t *offset, uint64_t *stat); static void i40e_pf_config_irq0(struct i40e_hw *hw); static void i40e_dev_interrupt_handler( __rte_unused struct rte_intr_handle *handle, void *param); static int i40e_res_pool_init(struct i40e_res_pool_info *pool, uint32_t base, uint32_t num); static void i40e_res_pool_destroy(struct i40e_res_pool_info *pool); static int i40e_res_pool_free(struct i40e_res_pool_info *pool, uint32_t base); static int i40e_res_pool_alloc(struct i40e_res_pool_info *pool, uint16_t num); static int i40e_dev_init_vlan(struct rte_eth_dev *dev); static int i40e_veb_release(struct i40e_veb *veb); static struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi); static int i40e_pf_config_mq_rx(struct i40e_pf *pf); static int i40e_vsi_config_double_vlan(struct i40e_vsi *vsi, int on); static inline int i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi, struct i40e_macvlan_filter *mv_f, int num, struct ether_addr *addr); static inline int i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi, struct i40e_macvlan_filter *mv_f, int num, uint16_t vlan); static int i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi); static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); static int i40e_dev_udp_tunnel_add(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *udp_tunnel); static int i40e_dev_udp_tunnel_del(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *udp_tunnel); static int i40e_ethertype_filter_set(struct i40e_pf *pf, struct rte_eth_ethertype_filter *filter, bool add); static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); static void i40e_configure_registers(struct i40e_hw *hw); static void i40e_hw_init(struct i40e_hw *hw); static int i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi); static int i40e_mirror_rule_set(struct rte_eth_dev *dev, struct rte_eth_mirror_conf *mirror_conf, uint8_t sw_id, uint8_t on); static int i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id); static int i40e_timesync_enable(struct rte_eth_dev *dev); static int i40e_timesync_disable(struct rte_eth_dev *dev); static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags); static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp); static const struct rte_pci_id pci_id_i40e_map[] = { #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static const struct eth_dev_ops i40e_eth_dev_ops = { .dev_configure = i40e_dev_configure, .dev_start = i40e_dev_start, .dev_stop = i40e_dev_stop, .dev_close = i40e_dev_close, .promiscuous_enable = i40e_dev_promiscuous_enable, .promiscuous_disable = i40e_dev_promiscuous_disable, .allmulticast_enable = i40e_dev_allmulticast_enable, .allmulticast_disable = i40e_dev_allmulticast_disable, .dev_set_link_up = i40e_dev_set_link_up, .dev_set_link_down = i40e_dev_set_link_down, .link_update = i40e_dev_link_update, .stats_get = i40e_dev_stats_get, .stats_reset = i40e_dev_stats_reset, .queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set, .dev_infos_get = i40e_dev_info_get, .vlan_filter_set = i40e_vlan_filter_set, .vlan_tpid_set = i40e_vlan_tpid_set, .vlan_offload_set = i40e_vlan_offload_set, .vlan_strip_queue_set = i40e_vlan_strip_queue_set, .vlan_pvid_set = i40e_vlan_pvid_set, .rx_queue_start = i40e_dev_rx_queue_start, .rx_queue_stop = i40e_dev_rx_queue_stop, .tx_queue_start = i40e_dev_tx_queue_start, .tx_queue_stop = i40e_dev_tx_queue_stop, .rx_queue_setup = i40e_dev_rx_queue_setup, .rx_queue_release = i40e_dev_rx_queue_release, .rx_queue_count = i40e_dev_rx_queue_count, .rx_descriptor_done = i40e_dev_rx_descriptor_done, .tx_queue_setup = i40e_dev_tx_queue_setup, .tx_queue_release = i40e_dev_tx_queue_release, .dev_led_on = i40e_dev_led_on, .dev_led_off = i40e_dev_led_off, .flow_ctrl_set = i40e_flow_ctrl_set, .priority_flow_ctrl_set = i40e_priority_flow_ctrl_set, .mac_addr_add = i40e_macaddr_add, .mac_addr_remove = i40e_macaddr_remove, .reta_update = i40e_dev_rss_reta_update, .reta_query = i40e_dev_rss_reta_query, .rss_hash_update = i40e_dev_rss_hash_update, .rss_hash_conf_get = i40e_dev_rss_hash_conf_get, .udp_tunnel_add = i40e_dev_udp_tunnel_add, .udp_tunnel_del = i40e_dev_udp_tunnel_del, .filter_ctrl = i40e_dev_filter_ctrl, .mirror_rule_set = i40e_mirror_rule_set, .mirror_rule_reset = i40e_mirror_rule_reset, .timesync_enable = i40e_timesync_enable, .timesync_disable = i40e_timesync_disable, .timesync_read_rx_timestamp = i40e_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp, }; static struct eth_driver rte_i40e_pmd = { .pci_drv = { .name = "rte_i40e_pmd", .id_table = pci_id_i40e_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_i40e_dev_init, .eth_dev_uninit = eth_i40e_dev_uninit, .dev_private_size = sizeof(struct i40e_adapter), }; static inline int rte_i40e_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static inline int rte_i40e_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of PCI IXGBE devices. */ static int rte_i40e_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_i40e_pmd); return 0; } static struct rte_driver rte_i40e_driver = { .type = PMD_PDEV, .init = rte_i40e_pmd_init, }; PMD_REGISTER_DRIVER(rte_i40e_driver); /* * Initialize registers for flexible payload, which should be set by NVM. * This should be removed from code once it is fixed in NVM. */ #ifndef I40E_GLQF_ORT #define I40E_GLQF_ORT(_i) (0x00268900 + ((_i) * 4)) #endif #ifndef I40E_GLQF_PIT #define I40E_GLQF_PIT(_i) (0x00268C80 + ((_i) * 4)) #endif static inline void i40e_flex_payload_reg_init(struct i40e_hw *hw) { I40E_WRITE_REG(hw, I40E_GLQF_ORT(18), 0x00000030); I40E_WRITE_REG(hw, I40E_GLQF_ORT(19), 0x00000030); I40E_WRITE_REG(hw, I40E_GLQF_ORT(26), 0x0000002B); I40E_WRITE_REG(hw, I40E_GLQF_ORT(30), 0x0000002B); I40E_WRITE_REG(hw, I40E_GLQF_ORT(33), 0x000000E0); I40E_WRITE_REG(hw, I40E_GLQF_ORT(34), 0x000000E3); I40E_WRITE_REG(hw, I40E_GLQF_ORT(35), 0x000000E6); I40E_WRITE_REG(hw, I40E_GLQF_ORT(20), 0x00000031); I40E_WRITE_REG(hw, I40E_GLQF_ORT(23), 0x00000031); I40E_WRITE_REG(hw, I40E_GLQF_ORT(63), 0x0000002D); /* GLQF_PIT Registers */ I40E_WRITE_REG(hw, I40E_GLQF_PIT(16), 0x00007480); I40E_WRITE_REG(hw, I40E_GLQF_PIT(17), 0x00007440); } static int eth_i40e_dev_init(struct rte_eth_dev *dev) { struct rte_pci_device *pci_dev; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *vsi; int ret; uint32_t len; uint8_t aq_fail = 0; PMD_INIT_FUNC_TRACE(); dev->dev_ops = &i40e_eth_dev_ops; dev->rx_pkt_burst = i40e_recv_pkts; dev->tx_pkt_burst = i40e_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX function */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (dev->data->scattered_rx) dev->rx_pkt_burst = i40e_recv_scattered_pkts; return 0; } pci_dev = dev->pci_dev; pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); pf->adapter->eth_dev = dev; pf->dev_data = dev->data; hw->back = I40E_PF_TO_ADAPTER(pf); hw->hw_addr = (uint8_t *)(pci_dev->mem_resource[0].addr); if (!hw->hw_addr) { PMD_INIT_LOG(ERR, "Hardware is not available, " "as address is NULL"); return -ENODEV; } hw->vendor_id = pci_dev->id.vendor_id; hw->device_id = pci_dev->id.device_id; hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; hw->subsystem_device_id = pci_dev->id.subsystem_device_id; hw->bus.device = pci_dev->addr.devid; hw->bus.func = pci_dev->addr.function; hw->adapter_stopped = 0; /* Make sure all is clean before doing PF reset */ i40e_clear_hw(hw); /* Initialize the hardware */ i40e_hw_init(hw); /* Reset here to make sure all is clean for each PF */ ret = i40e_pf_reset(hw); if (ret) { PMD_INIT_LOG(ERR, "Failed to reset pf: %d", ret); return ret; } /* Initialize the shared code (base driver) */ ret = i40e_init_shared_code(hw); if (ret) { PMD_INIT_LOG(ERR, "Failed to init shared code (base driver): %d", ret); return ret; } /* * To work around the NVM issue,initialize registers * for flexible payload by software. * It should be removed once issues are fixed in NVM. */ i40e_flex_payload_reg_init(hw); /* Initialize the parameters for adminq */ i40e_init_adminq_parameter(hw); ret = i40e_init_adminq(hw); if (ret != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "Failed to init adminq: %d", ret); return -EIO; } PMD_INIT_LOG(INFO, "FW %d.%d API %d.%d NVM %02d.%02d.%02d eetrack %04x", hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.api_maj_ver, hw->aq.api_min_ver, ((hw->nvm.version >> 12) & 0xf), ((hw->nvm.version >> 4) & 0xff), (hw->nvm.version & 0xf), hw->nvm.eetrack); /* Disable LLDP */ ret = i40e_aq_stop_lldp(hw, true, NULL); if (ret != I40E_SUCCESS) /* Its failure can be ignored */ PMD_INIT_LOG(INFO, "Failed to stop lldp"); /* Clear PXE mode */ i40e_clear_pxe_mode(hw); /* * On X710, performance number is far from the expectation on recent * firmware versions. The fix for this issue may not be integrated in * the following firmware version. So the workaround in software driver * is needed. It needs to modify the initial values of 3 internal only * registers. Note that the workaround can be removed when it is fixed * in firmware in the future. */ i40e_configure_registers(hw); /* Get hw capabilities */ ret = i40e_get_cap(hw); if (ret != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "Failed to get capabilities: %d", ret); goto err_get_capabilities; } /* Initialize parameters for PF */ ret = i40e_pf_parameter_init(dev); if (ret != 0) { PMD_INIT_LOG(ERR, "Failed to do parameter init: %d", ret); goto err_parameter_init; } /* Initialize the queue management */ ret = i40e_res_pool_init(&pf->qp_pool, 0, hw->func_caps.num_tx_qp); if (ret < 0) { PMD_INIT_LOG(ERR, "Failed to init queue pool"); goto err_qp_pool_init; } ret = i40e_res_pool_init(&pf->msix_pool, 1, hw->func_caps.num_msix_vectors - 1); if (ret < 0) { PMD_INIT_LOG(ERR, "Failed to init MSIX pool"); goto err_msix_pool_init; } /* Initialize lan hmc */ ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp, hw->func_caps.num_rx_qp, 0, 0); if (ret != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "Failed to init lan hmc: %d", ret); goto err_init_lan_hmc; } /* Configure lan hmc */ ret = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY); if (ret != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "Failed to configure lan hmc: %d", ret); goto err_configure_lan_hmc; } /* Get and check the mac address */ i40e_get_mac_addr(hw, hw->mac.addr); if (i40e_validate_mac_addr(hw->mac.addr) != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "mac address is not valid"); ret = -EIO; goto err_get_mac_addr; } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *) hw->mac.addr, (struct ether_addr *) hw->mac.perm_addr); /* Disable flow control */ hw->fc.requested_mode = I40E_FC_NONE; i40e_set_fc(hw, &aq_fail, TRUE); /* PF setup, which includes VSI setup */ ret = i40e_pf_setup(pf); if (ret) { PMD_INIT_LOG(ERR, "Failed to setup pf switch: %d", ret); goto err_setup_pf_switch; } vsi = pf->main_vsi; /* Disable double vlan by default */ i40e_vsi_config_double_vlan(vsi, FALSE); if (!vsi->max_macaddrs) len = ETHER_ADDR_LEN; else len = ETHER_ADDR_LEN * vsi->max_macaddrs; /* Should be after VSI initialized */ dev->data->mac_addrs = rte_zmalloc("i40e", len, 0); if (!dev->data->mac_addrs) { PMD_INIT_LOG(ERR, "Failed to allocated memory " "for storing mac address"); goto err_mac_alloc; } ether_addr_copy((struct ether_addr *)hw->mac.perm_addr, &dev->data->mac_addrs[0]); /* initialize pf host driver to setup SRIOV resource if applicable */ i40e_pf_host_init(dev); /* register callback func to eal lib */ rte_intr_callback_register(&(pci_dev->intr_handle), i40e_dev_interrupt_handler, (void *)dev); /* configure and enable device interrupt */ i40e_pf_config_irq0(hw); i40e_pf_enable_irq0(hw); /* enable uio intr after callback register */ rte_intr_enable(&(pci_dev->intr_handle)); /* initialize mirror rule list */ TAILQ_INIT(&pf->mirror_list); return 0; err_mac_alloc: i40e_vsi_release(pf->main_vsi); err_setup_pf_switch: err_get_mac_addr: err_configure_lan_hmc: (void)i40e_shutdown_lan_hmc(hw); err_init_lan_hmc: i40e_res_pool_destroy(&pf->msix_pool); err_msix_pool_init: i40e_res_pool_destroy(&pf->qp_pool); err_qp_pool_init: err_parameter_init: err_get_capabilities: (void)i40e_shutdown_adminq(hw); return ret; } static int eth_i40e_dev_uninit(struct rte_eth_dev *dev) { struct rte_pci_device *pci_dev; struct i40e_hw *hw; struct i40e_filter_control_settings settings; int ret; uint8_t aq_fail = 0; PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); pci_dev = dev->pci_dev; if (hw->adapter_stopped == 0) i40e_dev_close(dev); dev->dev_ops = NULL; dev->rx_pkt_burst = NULL; dev->tx_pkt_burst = NULL; /* Disable LLDP */ ret = i40e_aq_stop_lldp(hw, true, NULL); if (ret != I40E_SUCCESS) /* Its failure can be ignored */ PMD_INIT_LOG(INFO, "Failed to stop lldp"); /* Clear PXE mode */ i40e_clear_pxe_mode(hw); /* Unconfigure filter control */ memset(&settings, 0, sizeof(settings)); ret = i40e_set_filter_control(hw, &settings); if (ret) PMD_INIT_LOG(WARNING, "setup_pf_filter_control failed: %d", ret); /* Disable flow control */ hw->fc.requested_mode = I40E_FC_NONE; i40e_set_fc(hw, &aq_fail, TRUE); /* uninitialize pf host driver */ i40e_pf_host_uninit(dev); rte_free(dev->data->mac_addrs); dev->data->mac_addrs = NULL; /* disable uio intr before callback unregister */ rte_intr_disable(&(pci_dev->intr_handle)); /* register callback func to eal lib */ rte_intr_callback_unregister(&(pci_dev->intr_handle), i40e_dev_interrupt_handler, (void *)dev); return 0; } static int i40e_dev_configure(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); enum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode; int ret; if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) { ret = i40e_fdir_setup(pf); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to setup flow director."); return -ENOTSUP; } ret = i40e_fdir_configure(dev); if (ret < 0) { PMD_DRV_LOG(ERR, "failed to configure fdir."); goto err; } } else i40e_fdir_teardown(pf); ret = i40e_dev_init_vlan(dev); if (ret < 0) goto err; /* VMDQ setup. * Needs to move VMDQ setting out of i40e_pf_config_mq_rx() as VMDQ and * RSS setting have different requirements. * General PMD driver call sequence are NIC init, configure, * rx/tx_queue_setup and dev_start. In rx/tx_queue_setup() function, it * will try to lookup the VSI that specific queue belongs to if VMDQ * applicable. So, VMDQ setting has to be done before * rx/tx_queue_setup(). This function is good to place vmdq_setup. * For RSS setting, it will try to calculate actual configured RX queue * number, which will be available after rx_queue_setup(). dev_start() * function is good to place RSS setup. */ if (mq_mode & ETH_MQ_RX_VMDQ_FLAG) { ret = i40e_vmdq_setup(dev); if (ret) goto err; } return 0; err: i40e_fdir_teardown(pf); return ret; } void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); uint16_t msix_vect = vsi->msix_intr; uint16_t i; for (i = 0; i < vsi->nb_qps; i++) { I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0); I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), 0); rte_wmb(); } if (vsi->type != I40E_VSI_SRIOV) { I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), 0); I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT, msix_vect - 1), 0); } else { uint32_t reg; reg = (hw->func_caps.num_msix_vectors_vf - 1) * vsi->user_param + (msix_vect - 1); I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), 0); } I40E_WRITE_FLUSH(hw); } static inline uint16_t i40e_calc_itr_interval(int16_t interval) { if (interval < 0 || interval > I40E_QUEUE_ITR_INTERVAL_MAX) interval = I40E_QUEUE_ITR_INTERVAL_DEFAULT; /* Convert to hardware count, as writing each 1 represents 2 us */ return (interval/2); } void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi) { uint32_t val; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); uint16_t msix_vect = vsi->msix_intr; int i; for (i = 0; i < vsi->nb_qps; i++) I40E_WRITE_REG(hw, I40E_QINT_TQCTL(vsi->base_queue + i), 0); /* Bind all RX queues to allocated MSIX interrupt */ for (i = 0; i < vsi->nb_qps; i++) { val = (msix_vect << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | I40E_QINT_RQCTL_ITR_INDX_MASK | ((vsi->base_queue + i + 1) << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | (0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | I40E_QINT_RQCTL_CAUSE_ENA_MASK; if (i == vsi->nb_qps - 1) val |= I40E_QINT_RQCTL_NEXTQ_INDX_MASK; I40E_WRITE_REG(hw, I40E_QINT_RQCTL(vsi->base_queue + i), val); } /* Write first RX queue to Link list register as the head element */ if (vsi->type != I40E_VSI_SRIOV) { uint16_t interval = i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL); I40E_WRITE_REG(hw, I40E_PFINT_LNKLSTN(msix_vect - 1), (vsi->base_queue << I40E_PFINT_LNKLSTN_FIRSTQ_INDX_SHIFT) | (0x0 << I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)); I40E_WRITE_REG(hw, I40E_PFINT_ITRN(I40E_ITR_INDEX_DEFAULT, msix_vect - 1), interval); #ifndef I40E_GLINT_CTL #define I40E_GLINT_CTL 0x0003F800 #define I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK 0x4 #endif /* Disable auto-mask on enabling of all none-zero interrupt */ I40E_WRITE_REG(hw, I40E_GLINT_CTL, I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK); } else { uint32_t reg; /* num_msix_vectors_vf needs to minus irq0 */ reg = (hw->func_caps.num_msix_vectors_vf - 1) * vsi->user_param + (msix_vect - 1); I40E_WRITE_REG(hw, I40E_VPINT_LNKLSTN(reg), (vsi->base_queue << I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT) | (0x0 << I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)); } I40E_WRITE_FLUSH(hw); } static void i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); uint16_t interval = i40e_calc_itr_interval(\ RTE_LIBRTE_I40E_ITR_INTERVAL); I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), I40E_PFINT_DYN_CTLN_INTENA_MASK | I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | (0 << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) | (interval << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)); } static void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0); } static inline uint8_t i40e_parse_link_speed(uint16_t eth_link_speed) { uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN; switch (eth_link_speed) { case ETH_LINK_SPEED_40G: link_speed = I40E_LINK_SPEED_40GB; break; case ETH_LINK_SPEED_20G: link_speed = I40E_LINK_SPEED_20GB; break; case ETH_LINK_SPEED_10G: link_speed = I40E_LINK_SPEED_10GB; break; case ETH_LINK_SPEED_1000: link_speed = I40E_LINK_SPEED_1GB; break; case ETH_LINK_SPEED_100: link_speed = I40E_LINK_SPEED_100MB; break; } return link_speed; } static int i40e_phy_conf_link(struct i40e_hw *hw, uint8_t abilities, uint8_t force_speed) { enum i40e_status_code status; struct i40e_aq_get_phy_abilities_resp phy_ab; struct i40e_aq_set_phy_config phy_conf; const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX | I40E_AQ_PHY_FLAG_PAUSE_RX | I40E_AQ_PHY_FLAG_LOW_POWER; const uint8_t advt = I40E_LINK_SPEED_40GB | I40E_LINK_SPEED_10GB | I40E_LINK_SPEED_1GB | I40E_LINK_SPEED_100MB; int ret = -ENOTSUP; /* Skip it on 40G interfaces, as a workaround for the link issue */ if (i40e_is_40G_device(hw->device_id)) return I40E_SUCCESS; status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab, NULL); if (status) return ret; memset(&phy_conf, 0, sizeof(phy_conf)); /* bits 0-2 use the values from get_phy_abilities_resp */ abilities &= ~mask; abilities |= phy_ab.abilities & mask; /* update ablities and speed */ if (abilities & I40E_AQ_PHY_AN_ENABLED) phy_conf.link_speed = advt; else phy_conf.link_speed = force_speed; phy_conf.abilities = abilities; /* use get_phy_abilities_resp value for the rest */ phy_conf.phy_type = phy_ab.phy_type; phy_conf.eee_capability = phy_ab.eee_capability; phy_conf.eeer = phy_ab.eeer_val; phy_conf.low_power_ctrl = phy_ab.d3_lpan; PMD_DRV_LOG(DEBUG, "\tCurrent: abilities %x, link_speed %x", phy_ab.abilities, phy_ab.link_speed); PMD_DRV_LOG(DEBUG, "\tConfig: abilities %x, link_speed %x", phy_conf.abilities, phy_conf.link_speed); status = i40e_aq_set_phy_config(hw, &phy_conf, NULL); if (status) return ret; return I40E_SUCCESS; } static int i40e_apply_link_speed(struct rte_eth_dev *dev) { uint8_t speed; uint8_t abilities = 0; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_conf *conf = &dev->data->dev_conf; speed = i40e_parse_link_speed(conf->link_speed); abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; if (conf->link_speed == ETH_LINK_SPEED_AUTONEG) abilities |= I40E_AQ_PHY_AN_ENABLED; else abilities |= I40E_AQ_PHY_LINK_ENABLED; return i40e_phy_conf_link(hw, abilities, speed); } static int i40e_dev_start(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *main_vsi = pf->main_vsi; int ret, i; hw->adapter_stopped = 0; if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) && (dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) { PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu", dev->data->dev_conf.link_duplex, dev->data->port_id); return -EINVAL; } /* Initialize VSI */ ret = i40e_dev_rxtx_init(pf); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to init rx/tx queues"); goto err_up; } /* Map queues with MSIX interrupt */ i40e_vsi_queues_bind_intr(main_vsi); i40e_vsi_enable_queues_intr(main_vsi); /* Map VMDQ VSI queues with MSIX interrupt */ for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) { i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi); i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi); } /* enable FDIR MSIX interrupt */ if (pf->fdir.fdir_vsi) { i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi); i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi); } /* Enable all queues which have been configured */ ret = i40e_dev_switch_queues(pf, TRUE); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to enable VSI"); goto err_up; } /* Enable receiving broadcast packets */ ret = i40e_aq_set_vsi_broadcast(hw, main_vsi->seid, true, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(INFO, "fail to set vsi broadcast"); for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) { ret = i40e_aq_set_vsi_broadcast(hw, pf->vmdq[i].vsi->seid, true, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(INFO, "fail to set vsi broadcast"); } /* Apply link configure */ ret = i40e_apply_link_speed(dev); if (I40E_SUCCESS != ret) { PMD_DRV_LOG(ERR, "Fail to apply link setting"); goto err_up; } return I40E_SUCCESS; err_up: i40e_dev_switch_queues(pf, FALSE); i40e_dev_clear_queues(dev); return ret; } static void i40e_dev_stop(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *main_vsi = pf->main_vsi; struct i40e_mirror_rule *p_mirror; int i; /* Disable all queues */ i40e_dev_switch_queues(pf, FALSE); /* un-map queues with interrupt registers */ i40e_vsi_disable_queues_intr(main_vsi); i40e_vsi_queues_unbind_intr(main_vsi); for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) { i40e_vsi_disable_queues_intr(pf->vmdq[i].vsi); i40e_vsi_queues_unbind_intr(pf->vmdq[i].vsi); } if (pf->fdir.fdir_vsi) { i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi); i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi); } /* Clear all queues and release memory */ i40e_dev_clear_queues(dev); /* Set link down */ i40e_dev_set_link_down(dev); /* Remove all mirror rules */ while ((p_mirror = TAILQ_FIRST(&pf->mirror_list))) { TAILQ_REMOVE(&pf->mirror_list, p_mirror, rules); rte_free(p_mirror); } pf->nb_mirror_rule = 0; } static void i40e_dev_close(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; int i; PMD_INIT_FUNC_TRACE(); i40e_dev_stop(dev); hw->adapter_stopped = 1; i40e_dev_free_queues(dev); /* Disable interrupt */ i40e_pf_disable_irq0(hw); rte_intr_disable(&(dev->pci_dev->intr_handle)); /* shutdown and destroy the HMC */ i40e_shutdown_lan_hmc(hw); /* release all the existing VSIs and VEBs */ i40e_fdir_teardown(pf); i40e_vsi_release(pf->main_vsi); for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) { i40e_vsi_release(pf->vmdq[i].vsi); pf->vmdq[i].vsi = NULL; } rte_free(pf->vmdq); pf->vmdq = NULL; /* shutdown the adminq */ i40e_aq_queue_shutdown(hw, true); i40e_shutdown_adminq(hw); i40e_res_pool_destroy(&pf->qp_pool); i40e_res_pool_destroy(&pf->msix_pool); /* force a PF reset to clean anything leftover */ reg = I40E_READ_REG(hw, I40E_PFGEN_CTRL); I40E_WRITE_REG(hw, I40E_PFGEN_CTRL, (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); I40E_WRITE_FLUSH(hw); } static void i40e_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; int status; status = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid, true, NULL); if (status != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to enable unicast promiscuous"); status = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, TRUE, NULL); if (status != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to enable multicast promiscuous"); } static void i40e_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; int status; status = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid, false, NULL); if (status != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to disable unicast promiscuous"); status = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, false, NULL); if (status != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to disable multicast promiscuous"); } static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; int ret; ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, TRUE, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to enable multicast promiscuous"); } static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; int ret; if (dev->data->promiscuous == 1) return; /* must remain in all_multicast mode */ ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, FALSE, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to disable multicast promiscuous"); } /* * Set device link up. */ static int i40e_dev_set_link_up(struct rte_eth_dev *dev) { /* re-apply link speed setting */ return i40e_apply_link_speed(dev); } /* * Set device link down. */ static int i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev) { uint8_t speed = I40E_LINK_SPEED_UNKNOWN; uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); return i40e_phy_conf_link(hw, abilities, speed); } int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_REPEAT_TIME 10 /* 1s (10 * 100ms) in total */ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_link_status link_status; struct rte_eth_link link, old; int status; unsigned rep_cnt = MAX_REPEAT_TIME; memset(&link, 0, sizeof(link)); memset(&old, 0, sizeof(old)); memset(&link_status, 0, sizeof(link_status)); rte_i40e_dev_atomic_read_link_status(dev, &old); do { /* Get link status information from hardware */ status = i40e_aq_get_link_info(hw, false, &link_status, NULL); if (status != I40E_SUCCESS) { link.link_speed = ETH_LINK_SPEED_100; link.link_duplex = ETH_LINK_FULL_DUPLEX; PMD_DRV_LOG(ERR, "Failed to get link info"); goto out; } link.link_status = link_status.link_info & I40E_AQ_LINK_UP; if (!wait_to_complete) break; rte_delay_ms(CHECK_INTERVAL); } while (!link.link_status && rep_cnt--); if (!link.link_status) goto out; /* i40e uses full duplex only */ link.link_duplex = ETH_LINK_FULL_DUPLEX; /* Parse the link status */ switch (link_status.link_speed) { case I40E_LINK_SPEED_100MB: link.link_speed = ETH_LINK_SPEED_100; break; case I40E_LINK_SPEED_1GB: link.link_speed = ETH_LINK_SPEED_1000; break; case I40E_LINK_SPEED_10GB: link.link_speed = ETH_LINK_SPEED_10G; break; case I40E_LINK_SPEED_20GB: link.link_speed = ETH_LINK_SPEED_20G; break; case I40E_LINK_SPEED_40GB: link.link_speed = ETH_LINK_SPEED_40G; break; default: link.link_speed = ETH_LINK_SPEED_100; break; } out: rte_i40e_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) return -1; return 0; } /* Get all the statistics of a VSI */ void i40e_update_vsi_stats(struct i40e_vsi *vsi) { struct i40e_eth_stats *oes = &vsi->eth_stats_offset; struct i40e_eth_stats *nes = &vsi->eth_stats; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); int idx = rte_le_to_cpu_16(vsi->info.stat_counter_idx); i40e_stat_update_48(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx), vsi->offset_loaded, &oes->rx_bytes, &nes->rx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPRCH(idx), I40E_GLV_UPRCL(idx), vsi->offset_loaded, &oes->rx_unicast, &nes->rx_unicast); i40e_stat_update_48(hw, I40E_GLV_MPRCH(idx), I40E_GLV_MPRCL(idx), vsi->offset_loaded, &oes->rx_multicast, &nes->rx_multicast); i40e_stat_update_48(hw, I40E_GLV_BPRCH(idx), I40E_GLV_BPRCL(idx), vsi->offset_loaded, &oes->rx_broadcast, &nes->rx_broadcast); i40e_stat_update_32(hw, I40E_GLV_RDPC(idx), vsi->offset_loaded, &oes->rx_discards, &nes->rx_discards); /* GLV_REPC not supported */ /* GLV_RMPC not supported */ i40e_stat_update_32(hw, I40E_GLV_RUPP(idx), vsi->offset_loaded, &oes->rx_unknown_protocol, &nes->rx_unknown_protocol); i40e_stat_update_48(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx), vsi->offset_loaded, &oes->tx_bytes, &nes->tx_bytes); i40e_stat_update_48(hw, I40E_GLV_UPTCH(idx), I40E_GLV_UPTCL(idx), vsi->offset_loaded, &oes->tx_unicast, &nes->tx_unicast); i40e_stat_update_48(hw, I40E_GLV_MPTCH(idx), I40E_GLV_MPTCL(idx), vsi->offset_loaded, &oes->tx_multicast, &nes->tx_multicast); i40e_stat_update_48(hw, I40E_GLV_BPTCH(idx), I40E_GLV_BPTCL(idx), vsi->offset_loaded, &oes->tx_broadcast, &nes->tx_broadcast); /* GLV_TDPC not supported */ i40e_stat_update_32(hw, I40E_GLV_TEPC(idx), vsi->offset_loaded, &oes->tx_errors, &nes->tx_errors); vsi->offset_loaded = true; PMD_DRV_LOG(DEBUG, "***************** VSI[%u] stats start *******************", vsi->vsi_id); PMD_DRV_LOG(DEBUG, "rx_bytes: %"PRIu64"", nes->rx_bytes); PMD_DRV_LOG(DEBUG, "rx_unicast: %"PRIu64"", nes->rx_unicast); PMD_DRV_LOG(DEBUG, "rx_multicast: %"PRIu64"", nes->rx_multicast); PMD_DRV_LOG(DEBUG, "rx_broadcast: %"PRIu64"", nes->rx_broadcast); PMD_DRV_LOG(DEBUG, "rx_discards: %"PRIu64"", nes->rx_discards); PMD_DRV_LOG(DEBUG, "rx_unknown_protocol: %"PRIu64"", nes->rx_unknown_protocol); PMD_DRV_LOG(DEBUG, "tx_bytes: %"PRIu64"", nes->tx_bytes); PMD_DRV_LOG(DEBUG, "tx_unicast: %"PRIu64"", nes->tx_unicast); PMD_DRV_LOG(DEBUG, "tx_multicast: %"PRIu64"", nes->tx_multicast); PMD_DRV_LOG(DEBUG, "tx_broadcast: %"PRIu64"", nes->tx_broadcast); PMD_DRV_LOG(DEBUG, "tx_discards: %"PRIu64"", nes->tx_discards); PMD_DRV_LOG(DEBUG, "tx_errors: %"PRIu64"", nes->tx_errors); PMD_DRV_LOG(DEBUG, "***************** VSI[%u] stats end *******************", vsi->vsi_id); } /* Get all statistics of a port */ static void i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { uint32_t i; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */ struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */ /* Get statistics of struct i40e_eth_stats */ i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port), I40E_GLPRT_GORCL(hw->port), pf->offset_loaded, &os->eth.rx_bytes, &ns->eth.rx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPRCH(hw->port), I40E_GLPRT_UPRCL(hw->port), pf->offset_loaded, &os->eth.rx_unicast, &ns->eth.rx_unicast); i40e_stat_update_48(hw, I40E_GLPRT_MPRCH(hw->port), I40E_GLPRT_MPRCL(hw->port), pf->offset_loaded, &os->eth.rx_multicast, &ns->eth.rx_multicast); i40e_stat_update_48(hw, I40E_GLPRT_BPRCH(hw->port), I40E_GLPRT_BPRCL(hw->port), pf->offset_loaded, &os->eth.rx_broadcast, &ns->eth.rx_broadcast); i40e_stat_update_32(hw, I40E_GLPRT_RDPC(hw->port), pf->offset_loaded, &os->eth.rx_discards, &ns->eth.rx_discards); /* GLPRT_REPC not supported */ /* GLPRT_RMPC not supported */ i40e_stat_update_32(hw, I40E_GLPRT_RUPP(hw->port), pf->offset_loaded, &os->eth.rx_unknown_protocol, &ns->eth.rx_unknown_protocol); i40e_stat_update_48(hw, I40E_GLPRT_GOTCH(hw->port), I40E_GLPRT_GOTCL(hw->port), pf->offset_loaded, &os->eth.tx_bytes, &ns->eth.tx_bytes); i40e_stat_update_48(hw, I40E_GLPRT_UPTCH(hw->port), I40E_GLPRT_UPTCL(hw->port), pf->offset_loaded, &os->eth.tx_unicast, &ns->eth.tx_unicast); i40e_stat_update_48(hw, I40E_GLPRT_MPTCH(hw->port), I40E_GLPRT_MPTCL(hw->port), pf->offset_loaded, &os->eth.tx_multicast, &ns->eth.tx_multicast); i40e_stat_update_48(hw, I40E_GLPRT_BPTCH(hw->port), I40E_GLPRT_BPTCL(hw->port), pf->offset_loaded, &os->eth.tx_broadcast, &ns->eth.tx_broadcast); /* GLPRT_TEPC not supported */ /* additional port specific stats */ i40e_stat_update_32(hw, I40E_GLPRT_TDOLD(hw->port), pf->offset_loaded, &os->tx_dropped_link_down, &ns->tx_dropped_link_down); i40e_stat_update_32(hw, I40E_GLPRT_CRCERRS(hw->port), pf->offset_loaded, &os->crc_errors, &ns->crc_errors); i40e_stat_update_32(hw, I40E_GLPRT_ILLERRC(hw->port), pf->offset_loaded, &os->illegal_bytes, &ns->illegal_bytes); /* GLPRT_ERRBC not supported */ i40e_stat_update_32(hw, I40E_GLPRT_MLFC(hw->port), pf->offset_loaded, &os->mac_local_faults, &ns->mac_local_faults); i40e_stat_update_32(hw, I40E_GLPRT_MRFC(hw->port), pf->offset_loaded, &os->mac_remote_faults, &ns->mac_remote_faults); i40e_stat_update_32(hw, I40E_GLPRT_RLEC(hw->port), pf->offset_loaded, &os->rx_length_errors, &ns->rx_length_errors); i40e_stat_update_32(hw, I40E_GLPRT_LXONRXC(hw->port), pf->offset_loaded, &os->link_xon_rx, &ns->link_xon_rx); i40e_stat_update_32(hw, I40E_GLPRT_LXOFFRXC(hw->port), pf->offset_loaded, &os->link_xoff_rx, &ns->link_xoff_rx); for (i = 0; i < 8; i++) { i40e_stat_update_32(hw, I40E_GLPRT_PXONRXC(hw->port, i), pf->offset_loaded, &os->priority_xon_rx[i], &ns->priority_xon_rx[i]); i40e_stat_update_32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i), pf->offset_loaded, &os->priority_xoff_rx[i], &ns->priority_xoff_rx[i]); } i40e_stat_update_32(hw, I40E_GLPRT_LXONTXC(hw->port), pf->offset_loaded, &os->link_xon_tx, &ns->link_xon_tx); i40e_stat_update_32(hw, I40E_GLPRT_LXOFFTXC(hw->port), pf->offset_loaded, &os->link_xoff_tx, &ns->link_xoff_tx); for (i = 0; i < 8; i++) { i40e_stat_update_32(hw, I40E_GLPRT_PXONTXC(hw->port, i), pf->offset_loaded, &os->priority_xon_tx[i], &ns->priority_xon_tx[i]); i40e_stat_update_32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i), pf->offset_loaded, &os->priority_xoff_tx[i], &ns->priority_xoff_tx[i]); i40e_stat_update_32(hw, I40E_GLPRT_RXON2OFFCNT(hw->port, i), pf->offset_loaded, &os->priority_xon_2_xoff[i], &ns->priority_xon_2_xoff[i]); } i40e_stat_update_48(hw, I40E_GLPRT_PRC64H(hw->port), I40E_GLPRT_PRC64L(hw->port), pf->offset_loaded, &os->rx_size_64, &ns->rx_size_64); i40e_stat_update_48(hw, I40E_GLPRT_PRC127H(hw->port), I40E_GLPRT_PRC127L(hw->port), pf->offset_loaded, &os->rx_size_127, &ns->rx_size_127); i40e_stat_update_48(hw, I40E_GLPRT_PRC255H(hw->port), I40E_GLPRT_PRC255L(hw->port), pf->offset_loaded, &os->rx_size_255, &ns->rx_size_255); i40e_stat_update_48(hw, I40E_GLPRT_PRC511H(hw->port), I40E_GLPRT_PRC511L(hw->port), pf->offset_loaded, &os->rx_size_511, &ns->rx_size_511); i40e_stat_update_48(hw, I40E_GLPRT_PRC1023H(hw->port), I40E_GLPRT_PRC1023L(hw->port), pf->offset_loaded, &os->rx_size_1023, &ns->rx_size_1023); i40e_stat_update_48(hw, I40E_GLPRT_PRC1522H(hw->port), I40E_GLPRT_PRC1522L(hw->port), pf->offset_loaded, &os->rx_size_1522, &ns->rx_size_1522); i40e_stat_update_48(hw, I40E_GLPRT_PRC9522H(hw->port), I40E_GLPRT_PRC9522L(hw->port), pf->offset_loaded, &os->rx_size_big, &ns->rx_size_big); i40e_stat_update_32(hw, I40E_GLPRT_RUC(hw->port), pf->offset_loaded, &os->rx_undersize, &ns->rx_undersize); i40e_stat_update_32(hw, I40E_GLPRT_RFC(hw->port), pf->offset_loaded, &os->rx_fragments, &ns->rx_fragments); i40e_stat_update_32(hw, I40E_GLPRT_ROC(hw->port), pf->offset_loaded, &os->rx_oversize, &ns->rx_oversize); i40e_stat_update_32(hw, I40E_GLPRT_RJC(hw->port), pf->offset_loaded, &os->rx_jabber, &ns->rx_jabber); i40e_stat_update_48(hw, I40E_GLPRT_PTC64H(hw->port), I40E_GLPRT_PTC64L(hw->port), pf->offset_loaded, &os->tx_size_64, &ns->tx_size_64); i40e_stat_update_48(hw, I40E_GLPRT_PTC127H(hw->port), I40E_GLPRT_PTC127L(hw->port), pf->offset_loaded, &os->tx_size_127, &ns->tx_size_127); i40e_stat_update_48(hw, I40E_GLPRT_PTC255H(hw->port), I40E_GLPRT_PTC255L(hw->port), pf->offset_loaded, &os->tx_size_255, &ns->tx_size_255); i40e_stat_update_48(hw, I40E_GLPRT_PTC511H(hw->port), I40E_GLPRT_PTC511L(hw->port), pf->offset_loaded, &os->tx_size_511, &ns->tx_size_511); i40e_stat_update_48(hw, I40E_GLPRT_PTC1023H(hw->port), I40E_GLPRT_PTC1023L(hw->port), pf->offset_loaded, &os->tx_size_1023, &ns->tx_size_1023); i40e_stat_update_48(hw, I40E_GLPRT_PTC1522H(hw->port), I40E_GLPRT_PTC1522L(hw->port), pf->offset_loaded, &os->tx_size_1522, &ns->tx_size_1522); i40e_stat_update_48(hw, I40E_GLPRT_PTC9522H(hw->port), I40E_GLPRT_PTC9522L(hw->port), pf->offset_loaded, &os->tx_size_big, &ns->tx_size_big); i40e_stat_update_32(hw, I40E_GLQF_PCNT(pf->fdir.match_counter_index), pf->offset_loaded, &os->fd_sb_match, &ns->fd_sb_match); /* GLPRT_MSPDC not supported */ /* GLPRT_XEC not supported */ pf->offset_loaded = true; if (pf->main_vsi) i40e_update_vsi_stats(pf->main_vsi); stats->ipackets = ns->eth.rx_unicast + ns->eth.rx_multicast + ns->eth.rx_broadcast; stats->opackets = ns->eth.tx_unicast + ns->eth.tx_multicast + ns->eth.tx_broadcast; stats->ibytes = ns->eth.rx_bytes; stats->obytes = ns->eth.tx_bytes; stats->oerrors = ns->eth.tx_errors; stats->imcasts = ns->eth.rx_multicast; stats->fdirmatch = ns->fd_sb_match; /* Rx Errors */ stats->ibadcrc = ns->crc_errors; stats->ibadlen = ns->rx_length_errors + ns->rx_undersize + ns->rx_oversize + ns->rx_fragments + ns->rx_jabber; stats->imissed = ns->eth.rx_discards; stats->ierrors = stats->ibadcrc + stats->ibadlen + stats->imissed; PMD_DRV_LOG(DEBUG, "***************** PF stats start *******************"); PMD_DRV_LOG(DEBUG, "rx_bytes: %"PRIu64"", ns->eth.rx_bytes); PMD_DRV_LOG(DEBUG, "rx_unicast: %"PRIu64"", ns->eth.rx_unicast); PMD_DRV_LOG(DEBUG, "rx_multicast: %"PRIu64"", ns->eth.rx_multicast); PMD_DRV_LOG(DEBUG, "rx_broadcast: %"PRIu64"", ns->eth.rx_broadcast); PMD_DRV_LOG(DEBUG, "rx_discards: %"PRIu64"", ns->eth.rx_discards); PMD_DRV_LOG(DEBUG, "rx_unknown_protocol: %"PRIu64"", ns->eth.rx_unknown_protocol); PMD_DRV_LOG(DEBUG, "tx_bytes: %"PRIu64"", ns->eth.tx_bytes); PMD_DRV_LOG(DEBUG, "tx_unicast: %"PRIu64"", ns->eth.tx_unicast); PMD_DRV_LOG(DEBUG, "tx_multicast: %"PRIu64"", ns->eth.tx_multicast); PMD_DRV_LOG(DEBUG, "tx_broadcast: %"PRIu64"", ns->eth.tx_broadcast); PMD_DRV_LOG(DEBUG, "tx_discards: %"PRIu64"", ns->eth.tx_discards); PMD_DRV_LOG(DEBUG, "tx_errors: %"PRIu64"", ns->eth.tx_errors); PMD_DRV_LOG(DEBUG, "tx_dropped_link_down: %"PRIu64"", ns->tx_dropped_link_down); PMD_DRV_LOG(DEBUG, "crc_errors: %"PRIu64"", ns->crc_errors); PMD_DRV_LOG(DEBUG, "illegal_bytes: %"PRIu64"", ns->illegal_bytes); PMD_DRV_LOG(DEBUG, "error_bytes: %"PRIu64"", ns->error_bytes); PMD_DRV_LOG(DEBUG, "mac_local_faults: %"PRIu64"", ns->mac_local_faults); PMD_DRV_LOG(DEBUG, "mac_remote_faults: %"PRIu64"", ns->mac_remote_faults); PMD_DRV_LOG(DEBUG, "rx_length_errors: %"PRIu64"", ns->rx_length_errors); PMD_DRV_LOG(DEBUG, "link_xon_rx: %"PRIu64"", ns->link_xon_rx); PMD_DRV_LOG(DEBUG, "link_xoff_rx: %"PRIu64"", ns->link_xoff_rx); for (i = 0; i < 8; i++) { PMD_DRV_LOG(DEBUG, "priority_xon_rx[%d]: %"PRIu64"", i, ns->priority_xon_rx[i]); PMD_DRV_LOG(DEBUG, "priority_xoff_rx[%d]: %"PRIu64"", i, ns->priority_xoff_rx[i]); } PMD_DRV_LOG(DEBUG, "link_xon_tx: %"PRIu64"", ns->link_xon_tx); PMD_DRV_LOG(DEBUG, "link_xoff_tx: %"PRIu64"", ns->link_xoff_tx); for (i = 0; i < 8; i++) { PMD_DRV_LOG(DEBUG, "priority_xon_tx[%d]: %"PRIu64"", i, ns->priority_xon_tx[i]); PMD_DRV_LOG(DEBUG, "priority_xoff_tx[%d]: %"PRIu64"", i, ns->priority_xoff_tx[i]); PMD_DRV_LOG(DEBUG, "priority_xon_2_xoff[%d]: %"PRIu64"", i, ns->priority_xon_2_xoff[i]); } PMD_DRV_LOG(DEBUG, "rx_size_64: %"PRIu64"", ns->rx_size_64); PMD_DRV_LOG(DEBUG, "rx_size_127: %"PRIu64"", ns->rx_size_127); PMD_DRV_LOG(DEBUG, "rx_size_255: %"PRIu64"", ns->rx_size_255); PMD_DRV_LOG(DEBUG, "rx_size_511: %"PRIu64"", ns->rx_size_511); PMD_DRV_LOG(DEBUG, "rx_size_1023: %"PRIu64"", ns->rx_size_1023); PMD_DRV_LOG(DEBUG, "rx_size_1522: %"PRIu64"", ns->rx_size_1522); PMD_DRV_LOG(DEBUG, "rx_size_big: %"PRIu64"", ns->rx_size_big); PMD_DRV_LOG(DEBUG, "rx_undersize: %"PRIu64"", ns->rx_undersize); PMD_DRV_LOG(DEBUG, "rx_fragments: %"PRIu64"", ns->rx_fragments); PMD_DRV_LOG(DEBUG, "rx_oversize: %"PRIu64"", ns->rx_oversize); PMD_DRV_LOG(DEBUG, "rx_jabber: %"PRIu64"", ns->rx_jabber); PMD_DRV_LOG(DEBUG, "tx_size_64: %"PRIu64"", ns->tx_size_64); PMD_DRV_LOG(DEBUG, "tx_size_127: %"PRIu64"", ns->tx_size_127); PMD_DRV_LOG(DEBUG, "tx_size_255: %"PRIu64"", ns->tx_size_255); PMD_DRV_LOG(DEBUG, "tx_size_511: %"PRIu64"", ns->tx_size_511); PMD_DRV_LOG(DEBUG, "tx_size_1023: %"PRIu64"", ns->tx_size_1023); PMD_DRV_LOG(DEBUG, "tx_size_1522: %"PRIu64"", ns->tx_size_1522); PMD_DRV_LOG(DEBUG, "tx_size_big: %"PRIu64"", ns->tx_size_big); PMD_DRV_LOG(DEBUG, "mac_short_packet_dropped: %"PRIu64"", ns->mac_short_packet_dropped); PMD_DRV_LOG(DEBUG, "checksum_error: %"PRIu64"", ns->checksum_error); PMD_DRV_LOG(DEBUG, "fdir_match: %"PRIu64"", ns->fd_sb_match); PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************"); } /* Reset the statistics */ static void i40e_dev_stats_reset(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); /* It results in reloading the start point of each counter */ pf->offset_loaded = false; } static int i40e_dev_queue_stats_mapping_set(__rte_unused struct rte_eth_dev *dev, __rte_unused uint16_t queue_id, __rte_unused uint8_t stat_idx, __rte_unused uint8_t is_rx) { PMD_INIT_FUNC_TRACE(); return -ENOSYS; } static void i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; dev_info->max_rx_queues = vsi->nb_qps; dev_info->max_tx_queues = vsi->nb_qps; dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN; dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX; dev_info->max_mac_addrs = vsi->max_macaddrs; dev_info->max_vfs = dev->pci_dev->max_vfs; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_QINQ_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM | DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM | DEV_TX_OFFLOAD_TCP_TSO; dev_info->hash_key_size = (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t); dev_info->reta_size = pf->hash_lut_size; dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = I40E_DEFAULT_RX_PTHRESH, .hthresh = I40E_DEFAULT_RX_HTHRESH, .wthresh = I40E_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = I40E_DEFAULT_TX_PTHRESH, .hthresh = I40E_DEFAULT_TX_HTHRESH, .wthresh = I40E_DEFAULT_TX_WTHRESH, }, .tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH, .tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; if (pf->flags & I40E_FLAG_VMDQ) { dev_info->max_vmdq_pools = pf->max_nb_vmdq_vsi; dev_info->vmdq_queue_base = dev_info->max_rx_queues; dev_info->vmdq_queue_num = pf->vmdq_nb_qps * pf->max_nb_vmdq_vsi; dev_info->vmdq_pool_base = I40E_VMDQ_POOL_BASE; dev_info->max_rx_queues += dev_info->vmdq_queue_num; dev_info->max_tx_queues += dev_info->vmdq_queue_num; } } static int i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; PMD_INIT_FUNC_TRACE(); if (on) return i40e_vsi_add_vlan(vsi, vlan_id); else return i40e_vsi_delete_vlan(vsi, vlan_id); } static void i40e_vlan_tpid_set(__rte_unused struct rte_eth_dev *dev, __rte_unused uint16_t tpid) { PMD_INIT_FUNC_TRACE(); } static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; if (mask & ETH_VLAN_STRIP_MASK) { /* Enable or disable VLAN stripping */ if (dev->data->dev_conf.rxmode.hw_vlan_strip) i40e_vsi_config_vlan_stripping(vsi, TRUE); else i40e_vsi_config_vlan_stripping(vsi, FALSE); } if (mask & ETH_VLAN_EXTEND_MASK) { if (dev->data->dev_conf.rxmode.hw_vlan_extend) i40e_vsi_config_double_vlan(vsi, TRUE); else i40e_vsi_config_double_vlan(vsi, FALSE); } } static void i40e_vlan_strip_queue_set(__rte_unused struct rte_eth_dev *dev, __rte_unused uint16_t queue, __rte_unused int on) { PMD_INIT_FUNC_TRACE(); } static int i40e_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *vsi = pf->main_vsi; struct rte_eth_dev_data *data = I40E_VSI_TO_DEV_DATA(vsi); struct i40e_vsi_vlan_pvid_info info; memset(&info, 0, sizeof(info)); info.on = on; if (info.on) info.config.pvid = pvid; else { info.config.reject.tagged = data->dev_conf.txmode.hw_vlan_reject_tagged; info.config.reject.untagged = data->dev_conf.txmode.hw_vlan_reject_untagged; } return i40e_vsi_vlan_pvid_set(vsi, &info); } static int i40e_dev_led_on(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mode = i40e_led_get(hw); if (mode == 0) i40e_led_set(hw, 0xf, true); /* 0xf means led always true */ return 0; } static int i40e_dev_led_off(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mode = i40e_led_get(hw); if (mode != 0) i40e_led_set(hw, 0, false); return 0; } static int i40e_flow_ctrl_set(__rte_unused struct rte_eth_dev *dev, __rte_unused struct rte_eth_fc_conf *fc_conf) { PMD_INIT_FUNC_TRACE(); return -ENOSYS; } static int i40e_priority_flow_ctrl_set(__rte_unused struct rte_eth_dev *dev, __rte_unused struct rte_eth_pfc_conf *pfc_conf) { PMD_INIT_FUNC_TRACE(); return -ENOSYS; } /* Add a MAC address, and update filters */ static void i40e_macaddr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, __rte_unused uint32_t index, uint32_t pool) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_mac_filter_info mac_filter; struct i40e_vsi *vsi; int ret; /* If VMDQ not enabled or configured, return */ if (pool != 0 && (!(pf->flags | I40E_FLAG_VMDQ) || !pf->nb_cfg_vmdq_vsi)) { PMD_DRV_LOG(ERR, "VMDQ not %s, can't set mac to pool %u", pf->flags | I40E_FLAG_VMDQ ? "configured" : "enabled", pool); return; } if (pool > pf->nb_cfg_vmdq_vsi) { PMD_DRV_LOG(ERR, "Pool number %u invalid. Max pool is %u", pool, pf->nb_cfg_vmdq_vsi); return; } (void)rte_memcpy(&mac_filter.mac_addr, mac_addr, ETHER_ADDR_LEN); mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; if (pool == 0) vsi = pf->main_vsi; else vsi = pf->vmdq[pool - 1].vsi; ret = i40e_vsi_add_mac(vsi, &mac_filter); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter"); return; } } /* Remove a MAC address, and update filters */ static void i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_vsi *vsi; struct rte_eth_dev_data *data = dev->data; struct ether_addr *macaddr; int ret; uint32_t i; uint64_t pool_sel; macaddr = &(data->mac_addrs[index]); pool_sel = dev->data->mac_pool_sel[index]; for (i = 0; i < sizeof(pool_sel) * CHAR_BIT; i++) { if (pool_sel & (1ULL << i)) { if (i == 0) vsi = pf->main_vsi; else { /* No VMDQ pool enabled or configured */ if (!(pf->flags | I40E_FLAG_VMDQ) || (i > pf->nb_cfg_vmdq_vsi)) { PMD_DRV_LOG(ERR, "No VMDQ pool enabled" "/configured"); return; } vsi = pf->vmdq[i - 1].vsi; } ret = i40e_vsi_delete_mac(vsi, macaddr); if (ret) { PMD_DRV_LOG(ERR, "Failed to remove MACVLAN filter"); return; } } } } /* Set perfect match or hash match of MAC and VLAN for a VF */ static int i40e_vf_mac_filter_set(struct i40e_pf *pf, struct rte_eth_mac_filter *filter, bool add) { struct i40e_hw *hw; struct i40e_mac_filter_info mac_filter; struct ether_addr old_mac; struct ether_addr *new_mac; struct i40e_pf_vf *vf = NULL; uint16_t vf_id; int ret; if (pf == NULL) { PMD_DRV_LOG(ERR, "Invalid PF argument."); return -EINVAL; } hw = I40E_PF_TO_HW(pf); if (filter == NULL) { PMD_DRV_LOG(ERR, "Invalid mac filter argument."); return -EINVAL; } new_mac = &filter->mac_addr; if (is_zero_ether_addr(new_mac)) { PMD_DRV_LOG(ERR, "Invalid ethernet address."); return -EINVAL; } vf_id = filter->dst_id; if (vf_id > pf->vf_num - 1 || !pf->vfs) { PMD_DRV_LOG(ERR, "Invalid argument."); return -EINVAL; } vf = &pf->vfs[vf_id]; if (add && is_same_ether_addr(new_mac, &(pf->dev_addr))) { PMD_DRV_LOG(INFO, "Ignore adding permanent MAC address."); return -EINVAL; } if (add) { (void)rte_memcpy(&old_mac, hw->mac.addr, ETHER_ADDR_LEN); (void)rte_memcpy(hw->mac.addr, new_mac->addr_bytes, ETHER_ADDR_LEN); (void)rte_memcpy(&mac_filter.mac_addr, &filter->mac_addr, ETHER_ADDR_LEN); mac_filter.filter_type = filter->filter_type; ret = i40e_vsi_add_mac(vf->vsi, &mac_filter); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add MAC filter."); return -1; } ether_addr_copy(new_mac, &pf->dev_addr); } else { (void)rte_memcpy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN); ret = i40e_vsi_delete_mac(vf->vsi, &filter->mac_addr); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to delete MAC filter."); return -1; } /* Clear device address as it has been removed */ if (is_same_ether_addr(&(pf->dev_addr), new_mac)) memset(&pf->dev_addr, 0, sizeof(struct ether_addr)); } return 0; } /* MAC filter handle */ static int i40e_mac_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct rte_eth_mac_filter *filter; struct i40e_hw *hw = I40E_PF_TO_HW(pf); int ret = I40E_NOT_SUPPORTED; filter = (struct rte_eth_mac_filter *)(arg); switch (filter_op) { case RTE_ETH_FILTER_NOP: ret = I40E_SUCCESS; break; case RTE_ETH_FILTER_ADD: i40e_pf_disable_irq0(hw); if (filter->is_vf) ret = i40e_vf_mac_filter_set(pf, filter, 1); i40e_pf_enable_irq0(hw); break; case RTE_ETH_FILTER_DELETE: i40e_pf_disable_irq0(hw); if (filter->is_vf) ret = i40e_vf_mac_filter_set(pf, filter, 0); i40e_pf_enable_irq0(hw); break; default: PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); ret = I40E_ERR_PARAM; break; } return ret; } static int i40e_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t lut, l; uint16_t i, j, lut_size = pf->hash_lut_size; uint16_t idx, shift; uint8_t mask; if (reta_size != lut_size || reta_size > ETH_RSS_RETA_SIZE_512) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, lut_size); return -EINVAL; } for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & I40E_4_BIT_MASK); if (!mask) continue; if (mask == I40E_4_BIT_MASK) l = 0; else l = I40E_READ_REG(hw, I40E_PFQF_HLUT(i >> 2)); for (j = 0, lut = 0; j < I40E_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) lut |= reta_conf[idx].reta[shift + j] << (CHAR_BIT * j); else lut |= l & (I40E_8_BIT_MASK << (CHAR_BIT * j)); } I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut); } return 0; } static int i40e_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t lut; uint16_t i, j, lut_size = pf->hash_lut_size; uint16_t idx, shift; uint8_t mask; if (reta_size != lut_size || reta_size > ETH_RSS_RETA_SIZE_512) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, lut_size); return -EINVAL; } for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & I40E_4_BIT_MASK); if (!mask) continue; lut = I40E_READ_REG(hw, I40E_PFQF_HLUT(i >> 2)); for (j = 0; j < I40E_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta_conf[idx].reta[shift + j] = ((lut >> (CHAR_BIT * j)) & I40E_8_BIT_MASK); } } return 0; } /** * i40e_allocate_dma_mem_d - specific memory alloc for shared code (base driver) * @hw: pointer to the HW structure * @mem: pointer to mem struct to fill out * @size: size of memory requested * @alignment: what to align the allocation to **/ enum i40e_status_code i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw, struct i40e_dma_mem *mem, u64 size, u32 alignment) { static uint64_t id = 0; const struct rte_memzone *mz = NULL; char z_name[RTE_MEMZONE_NAMESIZE]; if (!mem) return I40E_ERR_PARAM; id++; snprintf(z_name, sizeof(z_name), "i40e_dma_%"PRIu64, id); #ifdef RTE_LIBRTE_XEN_DOM0 mz = rte_memzone_reserve_bounded(z_name, size, 0, 0, alignment, RTE_PGSIZE_2M); #else mz = rte_memzone_reserve_aligned(z_name, size, 0, 0, alignment); #endif if (!mz) return I40E_ERR_NO_MEMORY; mem->id = id; mem->size = size; mem->va = mz->addr; #ifdef RTE_LIBRTE_XEN_DOM0 mem->pa = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); #else mem->pa = mz->phys_addr; #endif return I40E_SUCCESS; } /** * i40e_free_dma_mem_d - specific memory free for shared code (base driver) * @hw: pointer to the HW structure * @mem: ptr to mem struct to free **/ enum i40e_status_code i40e_free_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw, struct i40e_dma_mem *mem) { if (!mem || !mem->va) return I40E_ERR_PARAM; mem->va = NULL; mem->pa = (u64)0; return I40E_SUCCESS; } /** * i40e_allocate_virt_mem_d - specific memory alloc for shared code (base driver) * @hw: pointer to the HW structure * @mem: pointer to mem struct to fill out * @size: size of memory requested **/ enum i40e_status_code i40e_allocate_virt_mem_d(__attribute__((unused)) struct i40e_hw *hw, struct i40e_virt_mem *mem, u32 size) { if (!mem) return I40E_ERR_PARAM; mem->size = size; mem->va = rte_zmalloc("i40e", size, 0); if (mem->va) return I40E_SUCCESS; else return I40E_ERR_NO_MEMORY; } /** * i40e_free_virt_mem_d - specific memory free for shared code (base driver) * @hw: pointer to the HW structure * @mem: pointer to mem struct to free **/ enum i40e_status_code i40e_free_virt_mem_d(__attribute__((unused)) struct i40e_hw *hw, struct i40e_virt_mem *mem) { if (!mem) return I40E_ERR_PARAM; rte_free(mem->va); mem->va = NULL; return I40E_SUCCESS; } void i40e_init_spinlock_d(struct i40e_spinlock *sp) { rte_spinlock_init(&sp->spinlock); } void i40e_acquire_spinlock_d(struct i40e_spinlock *sp) { rte_spinlock_lock(&sp->spinlock); } void i40e_release_spinlock_d(struct i40e_spinlock *sp) { rte_spinlock_unlock(&sp->spinlock); } void i40e_destroy_spinlock_d(__attribute__((unused)) struct i40e_spinlock *sp) { return; } /** * Get the hardware capabilities, which will be parsed * and saved into struct i40e_hw. */ static int i40e_get_cap(struct i40e_hw *hw) { struct i40e_aqc_list_capabilities_element_resp *buf; uint16_t len, size = 0; int ret; /* Calculate a huge enough buff for saving response data temporarily */ len = sizeof(struct i40e_aqc_list_capabilities_element_resp) * I40E_MAX_CAP_ELE_NUM; buf = rte_zmalloc("i40e", len, 0); if (!buf) { PMD_DRV_LOG(ERR, "Failed to allocate memory"); return I40E_ERR_NO_MEMORY; } /* Get, parse the capabilities and save it to hw */ ret = i40e_aq_discover_capabilities(hw, buf, len, &size, i40e_aqc_opc_list_func_capabilities, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to discover capabilities"); /* Free the temporary buffer after being used */ rte_free(buf); return ret; } static int i40e_pf_parameter_init(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint16_t sum_queues = 0, sum_vsis, left_queues; /* First check if FW support SRIOV */ if (dev->pci_dev->max_vfs && !hw->func_caps.sr_iov_1_1) { PMD_INIT_LOG(ERR, "HW configuration doesn't support SRIOV"); return -EINVAL; } pf->flags = I40E_FLAG_HEADER_SPLIT_DISABLED; pf->max_num_vsi = RTE_MIN(hw->func_caps.num_vsis, I40E_MAX_NUM_VSIS); PMD_INIT_LOG(INFO, "Max supported VSIs:%u", pf->max_num_vsi); /* Allocate queues for pf */ if (hw->func_caps.rss) { pf->flags |= I40E_FLAG_RSS; pf->lan_nb_qps = RTE_MIN(hw->func_caps.num_tx_qp, (uint32_t)(1 << hw->func_caps.rss_table_entry_width)); pf->lan_nb_qps = i40e_align_floor(pf->lan_nb_qps); } else pf->lan_nb_qps = 1; sum_queues = pf->lan_nb_qps; /* Default VSI is not counted in */ sum_vsis = 0; PMD_INIT_LOG(INFO, "PF queue pairs:%u", pf->lan_nb_qps); if (hw->func_caps.sr_iov_1_1 && dev->pci_dev->max_vfs) { pf->flags |= I40E_FLAG_SRIOV; pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF; if (dev->pci_dev->max_vfs > hw->func_caps.num_vfs) { PMD_INIT_LOG(ERR, "Config VF number %u, " "max supported %u.", dev->pci_dev->max_vfs, hw->func_caps.num_vfs); return -EINVAL; } if (pf->vf_nb_qps > I40E_MAX_QP_NUM_PER_VF) { PMD_INIT_LOG(ERR, "FVL VF queue %u, " "max support %u queues.", pf->vf_nb_qps, I40E_MAX_QP_NUM_PER_VF); return -EINVAL; } pf->vf_num = dev->pci_dev->max_vfs; sum_queues += pf->vf_nb_qps * pf->vf_num; sum_vsis += pf->vf_num; PMD_INIT_LOG(INFO, "Max VF num:%u each has queue pairs:%u", pf->vf_num, pf->vf_nb_qps); } else pf->vf_num = 0; if (hw->func_caps.vmdq) { pf->flags |= I40E_FLAG_VMDQ; pf->vmdq_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM; pf->max_nb_vmdq_vsi = 1; /* * If VMDQ available, assume a single VSI can be created. Will adjust * later. */ sum_queues += pf->vmdq_nb_qps * pf->max_nb_vmdq_vsi; sum_vsis += pf->max_nb_vmdq_vsi; } else { pf->vmdq_nb_qps = 0; pf->max_nb_vmdq_vsi = 0; } pf->nb_cfg_vmdq_vsi = 0; if (hw->func_caps.fd) { pf->flags |= I40E_FLAG_FDIR; pf->fdir_nb_qps = I40E_DEFAULT_QP_NUM_FDIR; /** * Each flow director consumes one VSI and one queue, * but can't calculate out predictably here. */ } if (sum_vsis > pf->max_num_vsi || sum_queues > hw->func_caps.num_rx_qp) { PMD_INIT_LOG(ERR, "VSI/QUEUE setting can't be satisfied"); PMD_INIT_LOG(ERR, "Max VSIs: %u, asked:%u", pf->max_num_vsi, sum_vsis); PMD_INIT_LOG(ERR, "Total queue pairs:%u, asked:%u", hw->func_caps.num_rx_qp, sum_queues); return -EINVAL; } /* Adjust VMDQ setting to support as many VMs as possible */ if (pf->flags & I40E_FLAG_VMDQ) { left_queues = hw->func_caps.num_rx_qp - sum_queues; pf->max_nb_vmdq_vsi += RTE_MIN(left_queues / pf->vmdq_nb_qps, pf->max_num_vsi - sum_vsis); /* Limit the max VMDQ number that rte_ether that can support */ pf->max_nb_vmdq_vsi = RTE_MIN(pf->max_nb_vmdq_vsi, ETH_64_POOLS - 1); PMD_INIT_LOG(INFO, "Max VMDQ VSI num:%u", pf->max_nb_vmdq_vsi); PMD_INIT_LOG(INFO, "VMDQ queue pairs:%u", pf->vmdq_nb_qps); } /* Each VSI occupy 1 MSIX interrupt at least, plus IRQ0 for misc intr * cause */ if (sum_vsis > hw->func_caps.num_msix_vectors - 1) { PMD_INIT_LOG(ERR, "Too many VSIs(%u), MSIX intr(%u) not enough", sum_vsis, hw->func_caps.num_msix_vectors); return -EINVAL; } return I40E_SUCCESS; } static int i40e_pf_get_switch_config(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_aqc_get_switch_config_resp *switch_config; struct i40e_aqc_switch_config_element_resp *element; uint16_t start_seid = 0, num_reported; int ret; switch_config = (struct i40e_aqc_get_switch_config_resp *)\ rte_zmalloc("i40e", I40E_AQ_LARGE_BUF, 0); if (!switch_config) { PMD_DRV_LOG(ERR, "Failed to allocated memory"); return -ENOMEM; } /* Get the switch configurations */ ret = i40e_aq_get_switch_config(hw, switch_config, I40E_AQ_LARGE_BUF, &start_seid, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to get switch configurations"); goto fail; } num_reported = rte_le_to_cpu_16(switch_config->header.num_reported); if (num_reported != 1) { /* The number should be 1 */ PMD_DRV_LOG(ERR, "Wrong number of switch config reported"); goto fail; } /* Parse the switch configuration elements */ element = &(switch_config->element[0]); if (element->element_type == I40E_SWITCH_ELEMENT_TYPE_VSI) { pf->mac_seid = rte_le_to_cpu_16(element->uplink_seid); pf->main_vsi_seid = rte_le_to_cpu_16(element->seid); } else PMD_DRV_LOG(INFO, "Unknown element type"); fail: rte_free(switch_config); return ret; } static int i40e_res_pool_init (struct i40e_res_pool_info *pool, uint32_t base, uint32_t num) { struct pool_entry *entry; if (pool == NULL || num == 0) return -EINVAL; entry = rte_zmalloc("i40e", sizeof(*entry), 0); if (entry == NULL) { PMD_DRV_LOG(ERR, "Failed to allocate memory for resource pool"); return -ENOMEM; } /* queue heap initialize */ pool->num_free = num; pool->num_alloc = 0; pool->base = base; LIST_INIT(&pool->alloc_list); LIST_INIT(&pool->free_list); /* Initialize element */ entry->base = 0; entry->len = num; LIST_INSERT_HEAD(&pool->free_list, entry, next); return 0; } static void i40e_res_pool_destroy(struct i40e_res_pool_info *pool) { struct pool_entry *entry; if (pool == NULL) return; LIST_FOREACH(entry, &pool->alloc_list, next) { LIST_REMOVE(entry, next); rte_free(entry); } LIST_FOREACH(entry, &pool->free_list, next) { LIST_REMOVE(entry, next); rte_free(entry); } pool->num_free = 0; pool->num_alloc = 0; pool->base = 0; LIST_INIT(&pool->alloc_list); LIST_INIT(&pool->free_list); } static int i40e_res_pool_free(struct i40e_res_pool_info *pool, uint32_t base) { struct pool_entry *entry, *next, *prev, *valid_entry = NULL; uint32_t pool_offset; int insert; if (pool == NULL) { PMD_DRV_LOG(ERR, "Invalid parameter"); return -EINVAL; } pool_offset = base - pool->base; /* Lookup in alloc list */ LIST_FOREACH(entry, &pool->alloc_list, next) { if (entry->base == pool_offset) { valid_entry = entry; LIST_REMOVE(entry, next); break; } } /* Not find, return */ if (valid_entry == NULL) { PMD_DRV_LOG(ERR, "Failed to find entry"); return -EINVAL; } /** * Found it, move it to free list and try to merge. * In order to make merge easier, always sort it by qbase. * Find adjacent prev and last entries. */ prev = next = NULL; LIST_FOREACH(entry, &pool->free_list, next) { if (entry->base > valid_entry->base) { next = entry; break; } prev = entry; } insert = 0; /* Try to merge with next one*/ if (next != NULL) { /* Merge with next one */ if (valid_entry->base + valid_entry->len == next->base) { next->base = valid_entry->base; next->len += valid_entry->len; rte_free(valid_entry); valid_entry = next; insert = 1; } } if (prev != NULL) { /* Merge with previous one */ if (prev->base + prev->len == valid_entry->base) { prev->len += valid_entry->len; /* If it merge with next one, remove next node */ if (insert == 1) { LIST_REMOVE(valid_entry, next); rte_free(valid_entry); } else { rte_free(valid_entry); insert = 1; } } } /* Not find any entry to merge, insert */ if (insert == 0) { if (prev != NULL) LIST_INSERT_AFTER(prev, valid_entry, next); else if (next != NULL) LIST_INSERT_BEFORE(next, valid_entry, next); else /* It's empty list, insert to head */ LIST_INSERT_HEAD(&pool->free_list, valid_entry, next); } pool->num_free += valid_entry->len; pool->num_alloc -= valid_entry->len; return 0; } static int i40e_res_pool_alloc(struct i40e_res_pool_info *pool, uint16_t num) { struct pool_entry *entry, *valid_entry; if (pool == NULL || num == 0) { PMD_DRV_LOG(ERR, "Invalid parameter"); return -EINVAL; } if (pool->num_free < num) { PMD_DRV_LOG(ERR, "No resource. ask:%u, available:%u", num, pool->num_free); return -ENOMEM; } valid_entry = NULL; /* Lookup in free list and find most fit one */ LIST_FOREACH(entry, &pool->free_list, next) { if (entry->len >= num) { /* Find best one */ if (entry->len == num) { valid_entry = entry; break; } if (valid_entry == NULL || valid_entry->len > entry->len) valid_entry = entry; } } /* Not find one to satisfy the request, return */ if (valid_entry == NULL) { PMD_DRV_LOG(ERR, "No valid entry found"); return -ENOMEM; } /** * The entry have equal queue number as requested, * remove it from alloc_list. */ if (valid_entry->len == num) { LIST_REMOVE(valid_entry, next); } else { /** * The entry have more numbers than requested, * create a new entry for alloc_list and minus its * queue base and number in free_list. */ entry = rte_zmalloc("res_pool", sizeof(*entry), 0); if (entry == NULL) { PMD_DRV_LOG(ERR, "Failed to allocate memory for " "resource pool"); return -ENOMEM; } entry->base = valid_entry->base; entry->len = num; valid_entry->base += num; valid_entry->len -= num; valid_entry = entry; } /* Insert it into alloc list, not sorted */ LIST_INSERT_HEAD(&pool->alloc_list, valid_entry, next); pool->num_free -= valid_entry->len; pool->num_alloc += valid_entry->len; return (valid_entry->base + pool->base); } /** * bitmap_is_subset - Check whether src2 is subset of src1 **/ static inline int bitmap_is_subset(uint8_t src1, uint8_t src2) { return !((src1 ^ src2) & src2); } static int validate_tcmap_parameter(struct i40e_vsi *vsi, uint8_t enabled_tcmap) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); /* If DCB is not supported, only default TC is supported */ if (!hw->func_caps.dcb && enabled_tcmap != I40E_DEFAULT_TCMAP) { PMD_DRV_LOG(ERR, "DCB is not enabled, only TC0 is supported"); return -EINVAL; } if (!bitmap_is_subset(hw->func_caps.enabled_tcmap, enabled_tcmap)) { PMD_DRV_LOG(ERR, "Enabled TC map 0x%x not applicable to " "HW support 0x%x", hw->func_caps.enabled_tcmap, enabled_tcmap); return -EINVAL; } return I40E_SUCCESS; } int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, struct i40e_vsi_vlan_pvid_info *info) { struct i40e_hw *hw; struct i40e_vsi_context ctxt; uint8_t vlan_flags = 0; int ret; if (vsi == NULL || info == NULL) { PMD_DRV_LOG(ERR, "invalid parameters"); return I40E_ERR_PARAM; } if (info->on) { vsi->info.pvid = info->config.pvid; /** * If insert pvid is enabled, only tagged pkts are * allowed to be sent out. */ vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID | I40E_AQ_VSI_PVLAN_MODE_TAGGED; } else { vsi->info.pvid = 0; if (info->config.reject.tagged == 0) vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED; if (info->config.reject.untagged == 0) vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED; } vsi->info.port_vlan_flags &= ~(I40E_AQ_VSI_PVLAN_INSERT_PVID | I40E_AQ_VSI_PVLAN_MODE_MASK); vsi->info.port_vlan_flags |= vlan_flags; vsi->info.valid_sections = rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); memset(&ctxt, 0, sizeof(ctxt)); (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ctxt.seid = vsi->seid; hw = I40E_VSI_TO_HW(vsi); ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to update VSI params"); return ret; } static int i40e_vsi_update_tc_bandwidth(struct i40e_vsi *vsi, uint8_t enabled_tcmap) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); int i, ret; struct i40e_aqc_configure_vsi_tc_bw_data tc_bw_data; ret = validate_tcmap_parameter(vsi, enabled_tcmap); if (ret != I40E_SUCCESS) return ret; if (!vsi->seid) { PMD_DRV_LOG(ERR, "seid not valid"); return -EINVAL; } memset(&tc_bw_data, 0, sizeof(tc_bw_data)); tc_bw_data.tc_valid_bits = enabled_tcmap; for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) tc_bw_data.tc_bw_credits[i] = (enabled_tcmap & (1 << i)) ? 1 : 0; ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw_data, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to configure TC BW"); return ret; } (void)rte_memcpy(vsi->info.qs_handle, tc_bw_data.qs_handles, sizeof(vsi->info.qs_handle)); return I40E_SUCCESS; } static int i40e_vsi_config_tc_queue_mapping(struct i40e_vsi *vsi, struct i40e_aqc_vsi_properties_data *info, uint8_t enabled_tcmap) { int ret, total_tc = 0, i; uint16_t qpnum_per_tc, bsf, qp_idx; ret = validate_tcmap_parameter(vsi, enabled_tcmap); if (ret != I40E_SUCCESS) return ret; for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) if (enabled_tcmap & (1 << i)) total_tc++; vsi->enabled_tc = enabled_tcmap; /* Number of queues per enabled TC */ qpnum_per_tc = i40e_align_floor(vsi->nb_qps / total_tc); qpnum_per_tc = RTE_MIN(qpnum_per_tc, I40E_MAX_Q_PER_TC); bsf = rte_bsf32(qpnum_per_tc); /* Adjust the queue number to actual queues that can be applied */ vsi->nb_qps = qpnum_per_tc * total_tc; /** * Configure TC and queue mapping parameters, for enabled TC, * allocate qpnum_per_tc queues to this traffic. For disabled TC, * default queue will serve it. */ qp_idx = 0; for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { if (vsi->enabled_tc & (1 << i)) { info->tc_mapping[i] = rte_cpu_to_le_16((qp_idx << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) | (bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT)); qp_idx += qpnum_per_tc; } else info->tc_mapping[i] = 0; } /* Associate queue number with VSI */ if (vsi->type == I40E_VSI_SRIOV) { info->mapping_flags |= rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG); for (i = 0; i < vsi->nb_qps; i++) info->queue_mapping[i] = rte_cpu_to_le_16(vsi->base_queue + i); } else { info->mapping_flags |= rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG); info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue); } info->valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID); return I40E_SUCCESS; } static int i40e_veb_release(struct i40e_veb *veb) { struct i40e_vsi *vsi; struct i40e_hw *hw; if (veb == NULL || veb->associate_vsi == NULL) return -EINVAL; if (!TAILQ_EMPTY(&veb->head)) { PMD_DRV_LOG(ERR, "VEB still has VSI attached, can't remove"); return -EACCES; } vsi = veb->associate_vsi; hw = I40E_VSI_TO_HW(vsi); vsi->uplink_seid = veb->uplink_seid; i40e_aq_delete_element(hw, veb->seid, NULL); rte_free(veb); vsi->veb = NULL; return I40E_SUCCESS; } /* Setup a veb */ static struct i40e_veb * i40e_veb_setup(struct i40e_pf *pf, struct i40e_vsi *vsi) { struct i40e_veb *veb; int ret; struct i40e_hw *hw; if (NULL == pf || vsi == NULL) { PMD_DRV_LOG(ERR, "veb setup failed, " "associated VSI shouldn't null"); return NULL; } hw = I40E_PF_TO_HW(pf); veb = rte_zmalloc("i40e_veb", sizeof(struct i40e_veb), 0); if (!veb) { PMD_DRV_LOG(ERR, "Failed to allocate memory for veb"); goto fail; } veb->associate_vsi = vsi; TAILQ_INIT(&veb->head); veb->uplink_seid = vsi->uplink_seid; ret = i40e_aq_add_veb(hw, veb->uplink_seid, vsi->seid, I40E_DEFAULT_TCMAP, false, false, &veb->seid, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Add veb failed, aq_err: %d", hw->aq.asq_last_status); goto fail; } /* get statistics index */ ret = i40e_aq_get_veb_parameters(hw, veb->seid, NULL, NULL, &veb->stats_idx, NULL, NULL, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Get veb statics index failed, aq_err: %d", hw->aq.asq_last_status); goto fail; } /* Get VEB bandwidth, to be implemented */ /* Now associated vsi binding to the VEB, set uplink to this VEB */ vsi->uplink_seid = veb->seid; return veb; fail: rte_free(veb); return NULL; } int i40e_vsi_release(struct i40e_vsi *vsi) { struct i40e_pf *pf; struct i40e_hw *hw; struct i40e_vsi_list *vsi_list; int ret; struct i40e_mac_filter *f; if (!vsi) return I40E_SUCCESS; pf = I40E_VSI_TO_PF(vsi); hw = I40E_VSI_TO_HW(vsi); /* VSI has child to attach, release child first */ if (vsi->veb) { TAILQ_FOREACH(vsi_list, &vsi->veb->head, list) { if (i40e_vsi_release(vsi_list->vsi) != I40E_SUCCESS) return -1; TAILQ_REMOVE(&vsi->veb->head, vsi_list, list); } i40e_veb_release(vsi->veb); } /* Remove all macvlan filters of the VSI */ i40e_vsi_remove_all_macvlan_filter(vsi); TAILQ_FOREACH(f, &vsi->mac_list, next) rte_free(f); if (vsi->type != I40E_VSI_MAIN) { /* Remove vsi from parent's sibling list */ if (vsi->parent_vsi == NULL || vsi->parent_vsi->veb == NULL) { PMD_DRV_LOG(ERR, "VSI's parent VSI is NULL"); return I40E_ERR_PARAM; } TAILQ_REMOVE(&vsi->parent_vsi->veb->head, &vsi->sib_vsi_list, list); /* Remove all switch element of the VSI */ ret = i40e_aq_delete_element(hw, vsi->seid, NULL); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to delete element"); } i40e_res_pool_free(&pf->qp_pool, vsi->base_queue); if (vsi->type != I40E_VSI_SRIOV) i40e_res_pool_free(&pf->msix_pool, vsi->msix_intr); rte_free(vsi); return I40E_SUCCESS; } static int i40e_update_default_filter_setting(struct i40e_vsi *vsi) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_remove_macvlan_element_data def_filter; struct i40e_mac_filter_info filter; int ret; if (vsi->type != I40E_VSI_MAIN) return I40E_ERR_CONFIG; memset(&def_filter, 0, sizeof(def_filter)); (void)rte_memcpy(def_filter.mac_addr, hw->mac.perm_addr, ETH_ADDR_LEN); def_filter.vlan_tag = 0; def_filter.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; ret = i40e_aq_remove_macvlan(hw, vsi->seid, &def_filter, 1, NULL); if (ret != I40E_SUCCESS) { struct i40e_mac_filter *f; struct ether_addr *mac; PMD_DRV_LOG(WARNING, "Cannot remove the default " "macvlan filter"); /* It needs to add the permanent mac into mac list */ f = rte_zmalloc("macv_filter", sizeof(*f), 0); if (f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } mac = &f->mac_info.mac_addr; (void)rte_memcpy(&mac->addr_bytes, hw->mac.perm_addr, ETH_ADDR_LEN); f->mac_info.filter_type = RTE_MACVLAN_PERFECT_MATCH; TAILQ_INSERT_TAIL(&vsi->mac_list, f, next); vsi->mac_num++; return ret; } (void)rte_memcpy(&filter.mac_addr, (struct ether_addr *)(hw->mac.perm_addr), ETH_ADDR_LEN); filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; return i40e_vsi_add_mac(vsi, &filter); } static int i40e_vsi_dump_bw_config(struct i40e_vsi *vsi) { struct i40e_aqc_query_vsi_bw_config_resp bw_config; struct i40e_aqc_query_vsi_ets_sla_config_resp ets_sla_config; struct i40e_hw *hw = &vsi->adapter->hw; i40e_status ret; int i; memset(&bw_config, 0, sizeof(bw_config)); ret = i40e_aq_query_vsi_bw_config(hw, vsi->seid, &bw_config, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "VSI failed to get bandwidth configuration %u", hw->aq.asq_last_status); return ret; } memset(&ets_sla_config, 0, sizeof(ets_sla_config)); ret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid, &ets_sla_config, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "VSI failed to get TC bandwdith " "configuration %u", hw->aq.asq_last_status); return ret; } /* Not store the info yet, just print out */ PMD_DRV_LOG(INFO, "VSI bw limit:%u", bw_config.port_bw_limit); PMD_DRV_LOG(INFO, "VSI max_bw:%u", bw_config.max_bw); for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { PMD_DRV_LOG(INFO, "\tVSI TC%u:share credits %u", i, ets_sla_config.share_credits[i]); PMD_DRV_LOG(INFO, "\tVSI TC%u:credits %u", i, rte_le_to_cpu_16(ets_sla_config.credits[i])); PMD_DRV_LOG(INFO, "\tVSI TC%u: max credits: %u", i, rte_le_to_cpu_16(ets_sla_config.credits[i / 4]) >> (i * 4)); } return 0; } /* Setup a VSI */ struct i40e_vsi * i40e_vsi_setup(struct i40e_pf *pf, enum i40e_vsi_type type, struct i40e_vsi *uplink_vsi, uint16_t user_param) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_vsi *vsi; struct i40e_mac_filter_info filter; int ret; struct i40e_vsi_context ctxt; struct ether_addr broadcast = {.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; if (type != I40E_VSI_MAIN && uplink_vsi == NULL) { PMD_DRV_LOG(ERR, "VSI setup failed, " "VSI link shouldn't be NULL"); return NULL; } if (type == I40E_VSI_MAIN && uplink_vsi != NULL) { PMD_DRV_LOG(ERR, "VSI setup failed, MAIN VSI " "uplink VSI should be NULL"); return NULL; } /* If uplink vsi didn't setup VEB, create one first */ if (type != I40E_VSI_MAIN && uplink_vsi->veb == NULL) { uplink_vsi->veb = i40e_veb_setup(pf, uplink_vsi); if (NULL == uplink_vsi->veb) { PMD_DRV_LOG(ERR, "VEB setup failed"); return NULL; } } vsi = rte_zmalloc("i40e_vsi", sizeof(struct i40e_vsi), 0); if (!vsi) { PMD_DRV_LOG(ERR, "Failed to allocate memory for vsi"); return NULL; } TAILQ_INIT(&vsi->mac_list); vsi->type = type; vsi->adapter = I40E_PF_TO_ADAPTER(pf); vsi->max_macaddrs = I40E_NUM_MACADDR_MAX; vsi->parent_vsi = uplink_vsi; vsi->user_param = user_param; /* Allocate queues */ switch (vsi->type) { case I40E_VSI_MAIN : vsi->nb_qps = pf->lan_nb_qps; break; case I40E_VSI_SRIOV : vsi->nb_qps = pf->vf_nb_qps; break; case I40E_VSI_VMDQ2: vsi->nb_qps = pf->vmdq_nb_qps; break; case I40E_VSI_FDIR: vsi->nb_qps = pf->fdir_nb_qps; break; default: goto fail_mem; } /* * The filter status descriptor is reported in rx queue 0, * while the tx queue for fdir filter programming has no * such constraints, can be non-zero queues. * To simplify it, choose FDIR vsi use queue 0 pair. * To make sure it will use queue 0 pair, queue allocation * need be done before this function is called */ if (type != I40E_VSI_FDIR) { ret = i40e_res_pool_alloc(&pf->qp_pool, vsi->nb_qps); if (ret < 0) { PMD_DRV_LOG(ERR, "VSI %d allocate queue failed %d", vsi->seid, ret); goto fail_mem; } vsi->base_queue = ret; } else vsi->base_queue = I40E_FDIR_QUEUE_ID; /* VF has MSIX interrupt in VF range, don't allocate here */ if (type != I40E_VSI_SRIOV) { ret = i40e_res_pool_alloc(&pf->msix_pool, 1); if (ret < 0) { PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret); goto fail_queue_alloc; } vsi->msix_intr = ret; } else vsi->msix_intr = 0; /* Add VSI */ if (type == I40E_VSI_MAIN) { /* For main VSI, no need to add since it's default one */ vsi->uplink_seid = pf->mac_seid; vsi->seid = pf->main_vsi_seid; /* Bind queues with specific MSIX interrupt */ /** * Needs 2 interrupt at least, one for misc cause which will * enabled from OS side, Another for queues binding the * interrupt from device side only. */ /* Get default VSI parameters from hardware */ memset(&ctxt, 0, sizeof(ctxt)); ctxt.seid = vsi->seid; ctxt.pf_num = hw->pf_id; ctxt.uplink_seid = vsi->uplink_seid; ctxt.vf_num = 0; ret = i40e_aq_get_vsi_params(hw, &ctxt, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to get VSI params"); goto fail_msix_alloc; } (void)rte_memcpy(&vsi->info, &ctxt.info, sizeof(struct i40e_aqc_vsi_properties_data)); vsi->vsi_id = ctxt.vsi_number; vsi->info.valid_sections = 0; /* Configure tc, enabled TC0 only */ if (i40e_vsi_update_tc_bandwidth(vsi, I40E_DEFAULT_TCMAP) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to update TC bandwidth"); goto fail_msix_alloc; } /* TC, queue mapping */ memset(&ctxt, 0, sizeof(ctxt)); vsi->info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); vsi->info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL | I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(struct i40e_aqc_vsi_properties_data)); ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info, I40E_DEFAULT_TCMAP); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to configure " "TC queue mapping"); goto fail_msix_alloc; } ctxt.seid = vsi->seid; ctxt.pf_num = hw->pf_id; ctxt.uplink_seid = vsi->uplink_seid; ctxt.vf_num = 0; /* Update VSI parameters */ ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to update VSI params"); goto fail_msix_alloc; } (void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping, sizeof(vsi->info.tc_mapping)); (void)rte_memcpy(&vsi->info.queue_mapping, &ctxt.info.queue_mapping, sizeof(vsi->info.queue_mapping)); vsi->info.mapping_flags = ctxt.info.mapping_flags; vsi->info.valid_sections = 0; (void)rte_memcpy(pf->dev_addr.addr_bytes, hw->mac.perm_addr, ETH_ADDR_LEN); /** * Updating default filter settings are necessary to prevent * reception of tagged packets. * Some old firmware configurations load a default macvlan * filter which accepts both tagged and untagged packets. * The updating is to use a normal filter instead if needed. * For NVM 4.2.2 or after, the updating is not needed anymore. * The firmware with correct configurations load the default * macvlan filter which is expected and cannot be removed. */ i40e_update_default_filter_setting(vsi); i40e_config_qinq(hw, vsi); } else if (type == I40E_VSI_SRIOV) { memset(&ctxt, 0, sizeof(ctxt)); /** * For other VSI, the uplink_seid equals to uplink VSI's * uplink_seid since they share same VEB */ vsi->uplink_seid = uplink_vsi->uplink_seid; ctxt.pf_num = hw->pf_id; ctxt.vf_num = hw->func_caps.vf_base_id + user_param; ctxt.uplink_seid = vsi->uplink_seid; ctxt.connection_type = 0x1; ctxt.flags = I40E_AQ_VSI_TYPE_VF; /** * Do not configure switch ID to enable VEB switch by * I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB. Because in Fortville, * if the source mac address of packet sent from VF is not * listed in the VEB's mac table, the VEB will switch the * packet back to the VF. Need to enable it when HW issue * is fixed. */ /* Configure port/vlan */ ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL; ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info, I40E_DEFAULT_TCMAP); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to configure " "TC queue mapping"); goto fail_msix_alloc; } ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP; ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID); /** * Since VSI is not created yet, only configure parameter, * will add vsi below. */ i40e_config_qinq(hw, vsi); } else if (type == I40E_VSI_VMDQ2) { memset(&ctxt, 0, sizeof(ctxt)); /* * For other VSI, the uplink_seid equals to uplink VSI's * uplink_seid since they share same VEB */ vsi->uplink_seid = uplink_vsi->uplink_seid; ctxt.pf_num = hw->pf_id; ctxt.vf_num = 0; ctxt.uplink_seid = vsi->uplink_seid; ctxt.connection_type = 0x1; ctxt.flags = I40E_AQ_VSI_TYPE_VMDQ2; ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID); /* user_param carries flag to enable loop back */ if (user_param) { ctxt.info.switch_id = rte_cpu_to_le_16(I40E_AQ_VSI_SW_ID_FLAG_LOCAL_LB); ctxt.info.switch_id |= rte_cpu_to_le_16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB); } /* Configure port/vlan */ ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL; ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info, I40E_DEFAULT_TCMAP); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to configure " "TC queue mapping"); goto fail_msix_alloc; } ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP; ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID); } else if (type == I40E_VSI_FDIR) { memset(&ctxt, 0, sizeof(ctxt)); vsi->uplink_seid = uplink_vsi->uplink_seid; ctxt.pf_num = hw->pf_id; ctxt.vf_num = 0; ctxt.uplink_seid = vsi->uplink_seid; ctxt.connection_type = 0x1; /* regular data port */ ctxt.flags = I40E_AQ_VSI_TYPE_PF; ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info, I40E_DEFAULT_TCMAP); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to configure " "TC queue mapping."); goto fail_msix_alloc; } ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP; ctxt.info.valid_sections |= rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SCHED_VALID); } else { PMD_DRV_LOG(ERR, "VSI: Not support other type VSI yet"); goto fail_msix_alloc; } if (vsi->type != I40E_VSI_MAIN) { ret = i40e_aq_add_vsi(hw, &ctxt, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "add vsi failed, aq_err=%d", hw->aq.asq_last_status); goto fail_msix_alloc; } memcpy(&vsi->info, &ctxt.info, sizeof(ctxt.info)); vsi->info.valid_sections = 0; vsi->seid = ctxt.seid; vsi->vsi_id = ctxt.vsi_number; vsi->sib_vsi_list.vsi = vsi; TAILQ_INSERT_TAIL(&uplink_vsi->veb->head, &vsi->sib_vsi_list, list); } /* MAC/VLAN configuration */ (void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN); filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; ret = i40e_vsi_add_mac(vsi, &filter); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add MACVLAN filter"); goto fail_msix_alloc; } /* Get VSI BW information */ i40e_vsi_dump_bw_config(vsi); return vsi; fail_msix_alloc: i40e_res_pool_free(&pf->msix_pool,vsi->msix_intr); fail_queue_alloc: i40e_res_pool_free(&pf->qp_pool,vsi->base_queue); fail_mem: rte_free(vsi); return NULL; } /* Configure vlan stripping on or off */ int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_vsi_context ctxt; uint8_t vlan_flags; int ret = I40E_SUCCESS; /* Check if it has been already on or off */ if (vsi->info.valid_sections & rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID)) { if (on) { if ((vsi->info.port_vlan_flags & I40E_AQ_VSI_PVLAN_EMOD_MASK) == 0) return 0; /* already on */ } else { if ((vsi->info.port_vlan_flags & I40E_AQ_VSI_PVLAN_EMOD_MASK) == I40E_AQ_VSI_PVLAN_EMOD_MASK) return 0; /* already off */ } } if (on) vlan_flags = I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH; else vlan_flags = I40E_AQ_VSI_PVLAN_EMOD_NOTHING; vsi->info.valid_sections = rte_cpu_to_le_16(I40E_AQ_VSI_PROP_VLAN_VALID); vsi->info.port_vlan_flags &= ~(I40E_AQ_VSI_PVLAN_EMOD_MASK); vsi->info.port_vlan_flags |= vlan_flags; ctxt.seid = vsi->seid; (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info)); ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL); if (ret) PMD_DRV_LOG(INFO, "Update VSI failed to %s vlan stripping", on ? "enable" : "disable"); return ret; } static int i40e_dev_init_vlan(struct rte_eth_dev *dev) { struct rte_eth_dev_data *data = dev->data; int ret; /* Apply vlan offload setting */ i40e_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK); /* Apply double-vlan setting, not implemented yet */ /* Apply pvid setting */ ret = i40e_vlan_pvid_set(dev, data->dev_conf.txmode.pvid, data->dev_conf.txmode.hw_vlan_insert_pvid); if (ret) PMD_DRV_LOG(INFO, "Failed to update VSI params"); return ret; } static int i40e_vsi_config_double_vlan(struct i40e_vsi *vsi, int on) { struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); return i40e_aq_set_port_parameters(hw, vsi->seid, 0, 1, on, NULL); } static int i40e_update_flow_control(struct i40e_hw *hw) { #define I40E_LINK_PAUSE_RXTX (I40E_AQ_LINK_PAUSE_RX | I40E_AQ_LINK_PAUSE_TX) struct i40e_link_status link_status; uint32_t rxfc = 0, txfc = 0, reg; uint8_t an_info; int ret; memset(&link_status, 0, sizeof(link_status)); ret = i40e_aq_get_link_info(hw, FALSE, &link_status, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to get link status information"); goto write_reg; /* Disable flow control */ } an_info = hw->phy.link_info.an_info; if (!(an_info & I40E_AQ_AN_COMPLETED)) { PMD_DRV_LOG(INFO, "Link auto negotiation not completed"); ret = I40E_ERR_NOT_READY; goto write_reg; /* Disable flow control */ } /** * If link auto negotiation is enabled, flow control needs to * be configured according to it */ switch (an_info & I40E_LINK_PAUSE_RXTX) { case I40E_LINK_PAUSE_RXTX: rxfc = 1; txfc = 1; hw->fc.current_mode = I40E_FC_FULL; break; case I40E_AQ_LINK_PAUSE_RX: rxfc = 1; hw->fc.current_mode = I40E_FC_RX_PAUSE; break; case I40E_AQ_LINK_PAUSE_TX: txfc = 1; hw->fc.current_mode = I40E_FC_TX_PAUSE; break; default: hw->fc.current_mode = I40E_FC_NONE; break; } write_reg: I40E_WRITE_REG(hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT); reg = I40E_READ_REG(hw, I40E_PRTDCB_MFLCN); reg &= ~I40E_PRTDCB_MFLCN_RFCE_MASK; reg |= rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT; I40E_WRITE_REG(hw, I40E_PRTDCB_MFLCN, reg); return ret; } /* PF setup */ static int i40e_pf_setup(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_filter_control_settings settings; struct i40e_vsi *vsi; int ret; /* Clear all stats counters */ pf->offset_loaded = FALSE; memset(&pf->stats, 0, sizeof(struct i40e_hw_port_stats)); memset(&pf->stats_offset, 0, sizeof(struct i40e_hw_port_stats)); ret = i40e_pf_get_switch_config(pf); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Could not get switch config, err %d", ret); return ret; } if (pf->flags & I40E_FLAG_FDIR) { /* make queue allocated first, let FDIR use queue pair 0*/ ret = i40e_res_pool_alloc(&pf->qp_pool, I40E_DEFAULT_QP_NUM_FDIR); if (ret != I40E_FDIR_QUEUE_ID) { PMD_DRV_LOG(ERR, "queue allocation fails for FDIR :" " ret =%d", ret); pf->flags &= ~I40E_FLAG_FDIR; } } /* main VSI setup */ vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, NULL, 0); if (!vsi) { PMD_DRV_LOG(ERR, "Setup of main vsi failed"); return I40E_ERR_NOT_READY; } pf->main_vsi = vsi; /* Configure filter control */ memset(&settings, 0, sizeof(settings)); if (hw->func_caps.rss_table_size == ETH_RSS_RETA_SIZE_128) settings.hash_lut_size = I40E_HASH_LUT_SIZE_128; else if (hw->func_caps.rss_table_size == ETH_RSS_RETA_SIZE_512) settings.hash_lut_size = I40E_HASH_LUT_SIZE_512; else { PMD_DRV_LOG(ERR, "Hash lookup table size (%u) not supported\n", hw->func_caps.rss_table_size); return I40E_ERR_PARAM; } PMD_DRV_LOG(INFO, "Hardware capability of hash lookup table " "size: %u\n", hw->func_caps.rss_table_size); pf->hash_lut_size = hw->func_caps.rss_table_size; /* Enable ethtype and macvlan filters */ settings.enable_ethtype = TRUE; settings.enable_macvlan = TRUE; ret = i40e_set_filter_control(hw, &settings); if (ret) PMD_INIT_LOG(WARNING, "setup_pf_filter_control failed: %d", ret); /* Update flow control according to the auto negotiation */ i40e_update_flow_control(hw); return I40E_SUCCESS; } int i40e_switch_tx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on) { uint32_t reg; uint16_t j; /** * Set or clear TX Queue Disable flags, * which is required by hardware. */ i40e_pre_tx_queue_cfg(hw, q_idx, on); rte_delay_us(I40E_PRE_TX_Q_CFG_WAIT_US); /* Wait until the request is finished */ for (j = 0; j < I40E_CHK_Q_ENA_COUNT; j++) { rte_delay_us(I40E_CHK_Q_ENA_INTERVAL_US); reg = I40E_READ_REG(hw, I40E_QTX_ENA(q_idx)); if (!(((reg >> I40E_QTX_ENA_QENA_REQ_SHIFT) & 0x1) ^ ((reg >> I40E_QTX_ENA_QENA_STAT_SHIFT) & 0x1))) { break; } } if (on) { if (reg & I40E_QTX_ENA_QENA_STAT_MASK) return I40E_SUCCESS; /* already on, skip next steps */ I40E_WRITE_REG(hw, I40E_QTX_HEAD(q_idx), 0); reg |= I40E_QTX_ENA_QENA_REQ_MASK; } else { if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK)) return I40E_SUCCESS; /* already off, skip next steps */ reg &= ~I40E_QTX_ENA_QENA_REQ_MASK; } /* Write the register */ I40E_WRITE_REG(hw, I40E_QTX_ENA(q_idx), reg); /* Check the result */ for (j = 0; j < I40E_CHK_Q_ENA_COUNT; j++) { rte_delay_us(I40E_CHK_Q_ENA_INTERVAL_US); reg = I40E_READ_REG(hw, I40E_QTX_ENA(q_idx)); if (on) { if ((reg & I40E_QTX_ENA_QENA_REQ_MASK) && (reg & I40E_QTX_ENA_QENA_STAT_MASK)) break; } else { if (!(reg & I40E_QTX_ENA_QENA_REQ_MASK) && !(reg & I40E_QTX_ENA_QENA_STAT_MASK)) break; } } /* Check if it is timeout */ if (j >= I40E_CHK_Q_ENA_COUNT) { PMD_DRV_LOG(ERR, "Failed to %s tx queue[%u]", (on ? "enable" : "disable"), q_idx); return I40E_ERR_TIMEOUT; } return I40E_SUCCESS; } /* Swith on or off the tx queues */ static int i40e_dev_switch_tx_queues(struct i40e_pf *pf, bool on) { struct rte_eth_dev_data *dev_data = pf->dev_data; struct i40e_tx_queue *txq; struct rte_eth_dev *dev = pf->adapter->eth_dev; uint16_t i; int ret; for (i = 0; i < dev_data->nb_tx_queues; i++) { txq = dev_data->tx_queues[i]; /* Don't operate the queue if not configured or * if starting only per queue */ if (!txq || !txq->q_set || (on && txq->tx_deferred_start)) continue; if (on) ret = i40e_dev_tx_queue_start(dev, i); else ret = i40e_dev_tx_queue_stop(dev, i); if ( ret != I40E_SUCCESS) return ret; } return I40E_SUCCESS; } int i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on) { uint32_t reg; uint16_t j; /* Wait until the request is finished */ for (j = 0; j < I40E_CHK_Q_ENA_COUNT; j++) { rte_delay_us(I40E_CHK_Q_ENA_INTERVAL_US); reg = I40E_READ_REG(hw, I40E_QRX_ENA(q_idx)); if (!((reg >> I40E_QRX_ENA_QENA_REQ_SHIFT) & 0x1) ^ ((reg >> I40E_QRX_ENA_QENA_STAT_SHIFT) & 0x1)) break; } if (on) { if (reg & I40E_QRX_ENA_QENA_STAT_MASK) return I40E_SUCCESS; /* Already on, skip next steps */ reg |= I40E_QRX_ENA_QENA_REQ_MASK; } else { if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK)) return I40E_SUCCESS; /* Already off, skip next steps */ reg &= ~I40E_QRX_ENA_QENA_REQ_MASK; } /* Write the register */ I40E_WRITE_REG(hw, I40E_QRX_ENA(q_idx), reg); /* Check the result */ for (j = 0; j < I40E_CHK_Q_ENA_COUNT; j++) { rte_delay_us(I40E_CHK_Q_ENA_INTERVAL_US); reg = I40E_READ_REG(hw, I40E_QRX_ENA(q_idx)); if (on) { if ((reg & I40E_QRX_ENA_QENA_REQ_MASK) && (reg & I40E_QRX_ENA_QENA_STAT_MASK)) break; } else { if (!(reg & I40E_QRX_ENA_QENA_REQ_MASK) && !(reg & I40E_QRX_ENA_QENA_STAT_MASK)) break; } } /* Check if it is timeout */ if (j >= I40E_CHK_Q_ENA_COUNT) { PMD_DRV_LOG(ERR, "Failed to %s rx queue[%u]", (on ? "enable" : "disable"), q_idx); return I40E_ERR_TIMEOUT; } return I40E_SUCCESS; } /* Switch on or off the rx queues */ static int i40e_dev_switch_rx_queues(struct i40e_pf *pf, bool on) { struct rte_eth_dev_data *dev_data = pf->dev_data; struct i40e_rx_queue *rxq; struct rte_eth_dev *dev = pf->adapter->eth_dev; uint16_t i; int ret; for (i = 0; i < dev_data->nb_rx_queues; i++) { rxq = dev_data->rx_queues[i]; /* Don't operate the queue if not configured or * if starting only per queue */ if (!rxq || !rxq->q_set || (on && rxq->rx_deferred_start)) continue; if (on) ret = i40e_dev_rx_queue_start(dev, i); else ret = i40e_dev_rx_queue_stop(dev, i); if (ret != I40E_SUCCESS) return ret; } return I40E_SUCCESS; } /* Switch on or off all the rx/tx queues */ int i40e_dev_switch_queues(struct i40e_pf *pf, bool on) { int ret; if (on) { /* enable rx queues before enabling tx queues */ ret = i40e_dev_switch_rx_queues(pf, on); if (ret) { PMD_DRV_LOG(ERR, "Failed to switch rx queues"); return ret; } ret = i40e_dev_switch_tx_queues(pf, on); } else { /* Stop tx queues before stopping rx queues */ ret = i40e_dev_switch_tx_queues(pf, on); if (ret) { PMD_DRV_LOG(ERR, "Failed to switch tx queues"); return ret; } ret = i40e_dev_switch_rx_queues(pf, on); } return ret; } /* Initialize VSI for TX */ static int i40e_dev_tx_init(struct i40e_pf *pf) { struct rte_eth_dev_data *data = pf->dev_data; uint16_t i; uint32_t ret = I40E_SUCCESS; struct i40e_tx_queue *txq; for (i = 0; i < data->nb_tx_queues; i++) { txq = data->tx_queues[i]; if (!txq || !txq->q_set) continue; ret = i40e_tx_queue_init(txq); if (ret != I40E_SUCCESS) break; } return ret; } /* Initialize VSI for RX */ static int i40e_dev_rx_init(struct i40e_pf *pf) { struct rte_eth_dev_data *data = pf->dev_data; int ret = I40E_SUCCESS; uint16_t i; struct i40e_rx_queue *rxq; i40e_pf_config_mq_rx(pf); for (i = 0; i < data->nb_rx_queues; i++) { rxq = data->rx_queues[i]; if (!rxq || !rxq->q_set) continue; ret = i40e_rx_queue_init(rxq); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to do RX queue " "initialization"); break; } } return ret; } static int i40e_dev_rxtx_init(struct i40e_pf *pf) { int err; err = i40e_dev_tx_init(pf); if (err) { PMD_DRV_LOG(ERR, "Failed to do TX initialization"); return err; } err = i40e_dev_rx_init(pf); if (err) { PMD_DRV_LOG(ERR, "Failed to do RX initialization"); return err; } return err; } static int i40e_vmdq_setup(struct rte_eth_dev *dev) { struct rte_eth_conf *conf = &dev->data->dev_conf; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int i, err, conf_vsis, j, loop; struct i40e_vsi *vsi; struct i40e_vmdq_info *vmdq_info; struct rte_eth_vmdq_rx_conf *vmdq_conf; struct i40e_hw *hw = I40E_PF_TO_HW(pf); /* * Disable interrupt to avoid message from VF. Furthermore, it will * avoid race condition in VSI creation/destroy. */ i40e_pf_disable_irq0(hw); if ((pf->flags & I40E_FLAG_VMDQ) == 0) { PMD_INIT_LOG(ERR, "FW doesn't support VMDQ"); return -ENOTSUP; } conf_vsis = conf->rx_adv_conf.vmdq_rx_conf.nb_queue_pools; if (conf_vsis > pf->max_nb_vmdq_vsi) { PMD_INIT_LOG(ERR, "VMDQ config: %u, max support:%u", conf->rx_adv_conf.vmdq_rx_conf.nb_queue_pools, pf->max_nb_vmdq_vsi); return -ENOTSUP; } if (pf->vmdq != NULL) { PMD_INIT_LOG(INFO, "VMDQ already configured"); return 0; } pf->vmdq = rte_zmalloc("vmdq_info_struct", sizeof(*vmdq_info) * conf_vsis, 0); if (pf->vmdq == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate memory"); return -ENOMEM; } vmdq_conf = &conf->rx_adv_conf.vmdq_rx_conf; /* Create VMDQ VSI */ for (i = 0; i < conf_vsis; i++) { vsi = i40e_vsi_setup(pf, I40E_VSI_VMDQ2, pf->main_vsi, vmdq_conf->enable_loop_back); if (vsi == NULL) { PMD_INIT_LOG(ERR, "Failed to create VMDQ VSI"); err = -1; goto err_vsi_setup; } vmdq_info = &pf->vmdq[i]; vmdq_info->pf = pf; vmdq_info->vsi = vsi; } pf->nb_cfg_vmdq_vsi = conf_vsis; /* Configure Vlan */ loop = sizeof(vmdq_conf->pool_map[0].pools) * CHAR_BIT; for (i = 0; i < vmdq_conf->nb_pool_maps; i++) { for (j = 0; j < loop && j < pf->nb_cfg_vmdq_vsi; j++) { if (vmdq_conf->pool_map[i].pools & (1UL << j)) { PMD_INIT_LOG(INFO, "Add vlan %u to vmdq pool %u", vmdq_conf->pool_map[i].vlan_id, j); err = i40e_vsi_add_vlan(pf->vmdq[j].vsi, vmdq_conf->pool_map[i].vlan_id); if (err) { PMD_INIT_LOG(ERR, "Failed to add vlan"); err = -1; goto err_vsi_setup; } } } } i40e_pf_enable_irq0(hw); return 0; err_vsi_setup: for (i = 0; i < conf_vsis; i++) if (pf->vmdq[i].vsi == NULL) break; else i40e_vsi_release(pf->vmdq[i].vsi); rte_free(pf->vmdq); pf->vmdq = NULL; i40e_pf_enable_irq0(hw); return err; } static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg, bool offset_loaded, uint64_t *offset, uint64_t *stat) { uint64_t new_data; new_data = (uint64_t)I40E_READ_REG(hw, reg); if (!offset_loaded) *offset = new_data; if (new_data >= *offset) *stat = (uint64_t)(new_data - *offset); else *stat = (uint64_t)((new_data + ((uint64_t)1 << I40E_32_BIT_WIDTH)) - *offset); } static void i40e_stat_update_48(struct i40e_hw *hw, uint32_t hireg, uint32_t loreg, bool offset_loaded, uint64_t *offset, uint64_t *stat) { uint64_t new_data; new_data = (uint64_t)I40E_READ_REG(hw, loreg); new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) & I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH; if (!offset_loaded) *offset = new_data; if (new_data >= *offset) *stat = new_data - *offset; else *stat = (uint64_t)((new_data + ((uint64_t)1 << I40E_48_BIT_WIDTH)) - *offset); *stat &= I40E_48_BIT_MASK; } /* Disable IRQ0 */ void i40e_pf_disable_irq0(struct i40e_hw *hw) { /* Disable all interrupt types */ I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, 0); I40E_WRITE_FLUSH(hw); } /* Enable IRQ0 */ void i40e_pf_enable_irq0(struct i40e_hw *hw) { I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTL0, I40E_PFINT_DYN_CTL0_INTENA_MASK | I40E_PFINT_DYN_CTL0_CLEARPBA_MASK | I40E_PFINT_DYN_CTL0_ITR_INDX_MASK); I40E_WRITE_FLUSH(hw); } static void i40e_pf_config_irq0(struct i40e_hw *hw) { /* read pending request and disable first */ i40e_pf_disable_irq0(hw); I40E_WRITE_REG(hw, I40E_PFINT_ICR0_ENA, I40E_PFINT_ICR0_ENA_MASK); I40E_WRITE_REG(hw, I40E_PFINT_STAT_CTL0, I40E_PFINT_STAT_CTL0_OTHER_ITR_INDX_MASK); /* Link no queues with irq0 */ I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0, I40E_PFINT_LNKLST0_FIRSTQ_INDX_MASK); } static void i40e_dev_handle_vfr_event(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int i; uint16_t abs_vf_id; uint32_t index, offset, val; if (!pf->vfs) return; /** * Try to find which VF trigger a reset, use absolute VF id to access * since the reg is global register. */ for (i = 0; i < pf->vf_num; i++) { abs_vf_id = hw->func_caps.vf_base_id + i; index = abs_vf_id / I40E_UINT32_BIT_SIZE; offset = abs_vf_id % I40E_UINT32_BIT_SIZE; val = I40E_READ_REG(hw, I40E_GLGEN_VFLRSTAT(index)); /* VFR event occured */ if (val & (0x1 << offset)) { int ret; /* Clear the event first */ I40E_WRITE_REG(hw, I40E_GLGEN_VFLRSTAT(index), (0x1 << offset)); PMD_DRV_LOG(INFO, "VF %u reset occured", abs_vf_id); /** * Only notify a VF reset event occured, * don't trigger another SW reset */ ret = i40e_pf_host_vf_reset(&pf->vfs[i], 0); if (ret != I40E_SUCCESS) PMD_DRV_LOG(ERR, "Failed to do VF reset"); } } } static void i40e_dev_handle_aq_msg(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_arq_event_info info; uint16_t pending, opcode; int ret; info.buf_len = I40E_AQ_BUF_SZ; info.msg_buf = rte_zmalloc("msg_buffer", info.buf_len, 0); if (!info.msg_buf) { PMD_DRV_LOG(ERR, "Failed to allocate mem"); return; } pending = 1; while (pending) { ret = i40e_clean_arq_element(hw, &info, &pending); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ, " "aq_err: %u", hw->aq.asq_last_status); break; } opcode = rte_le_to_cpu_16(info.desc.opcode); switch (opcode) { case i40e_aqc_opc_send_msg_to_pf: /* Refer to i40e_aq_send_msg_to_pf() for argument layout*/ i40e_pf_host_handle_vf_msg(dev, rte_le_to_cpu_16(info.desc.retval), rte_le_to_cpu_32(info.desc.cookie_high), rte_le_to_cpu_32(info.desc.cookie_low), info.msg_buf, info.msg_len); break; default: PMD_DRV_LOG(ERR, "Request %u is not supported yet", opcode); break; } } rte_free(info.msg_buf); } /* * Interrupt handler is registered as the alarm callback for handling LSC * interrupt in a definite of time, in order to wait the NIC into a stable * state. Currently it waits 1 sec in i40e for the link up interrupt, and * no need for link down interrupt. */ static void i40e_dev_interrupt_delayed_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t icr0; /* read interrupt causes again */ icr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0); #ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK) PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error\n"); if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK) PMD_DRV_LOG(ERR, "ICR0: malicious programming detected\n"); if (icr0 & I40E_PFINT_ICR0_GRST_MASK) PMD_DRV_LOG(INFO, "ICR0: global reset requested\n"); if (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK) PMD_DRV_LOG(INFO, "ICR0: PCI exception\n activated\n"); if (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK) PMD_DRV_LOG(INFO, "ICR0: a change in the storm control " "state\n"); if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) PMD_DRV_LOG(ERR, "ICR0: HMC error\n"); if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK) PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error\n"); #endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */ if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { PMD_DRV_LOG(INFO, "INT:VF reset detected\n"); i40e_dev_handle_vfr_event(dev); } if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) { PMD_DRV_LOG(INFO, "INT:ADMINQ event\n"); i40e_dev_handle_aq_msg(dev); } /* handle the link up interrupt in an alarm callback */ i40e_dev_link_update(dev, 0); _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); i40e_pf_enable_irq0(hw); rte_intr_enable(&(dev->pci_dev->intr_handle)); } /** * Interrupt handler triggered by NIC for handling * specific interrupt. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t icr0; /* Disable interrupt */ i40e_pf_disable_irq0(hw); /* read out interrupt causes */ icr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0); /* No interrupt event indicated */ if (!(icr0 & I40E_PFINT_ICR0_INTEVENT_MASK)) { PMD_DRV_LOG(INFO, "No interrupt event"); goto done; } #ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK) PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error"); if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK) PMD_DRV_LOG(ERR, "ICR0: malicious programming detected"); if (icr0 & I40E_PFINT_ICR0_GRST_MASK) PMD_DRV_LOG(INFO, "ICR0: global reset requested"); if (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK) PMD_DRV_LOG(INFO, "ICR0: PCI exception activated"); if (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK) PMD_DRV_LOG(INFO, "ICR0: a change in the storm control state"); if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK) PMD_DRV_LOG(ERR, "ICR0: HMC error"); if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK) PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error"); #endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */ if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { PMD_DRV_LOG(INFO, "ICR0: VF reset detected"); i40e_dev_handle_vfr_event(dev); } if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) { PMD_DRV_LOG(INFO, "ICR0: adminq event"); i40e_dev_handle_aq_msg(dev); } /* Link Status Change interrupt */ if (icr0 & I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK) { #define I40E_US_PER_SECOND 1000000 struct rte_eth_link link; PMD_DRV_LOG(INFO, "ICR0: link status changed\n"); memset(&link, 0, sizeof(link)); rte_i40e_dev_atomic_read_link_status(dev, &link); i40e_dev_link_update(dev, 0); /* * For link up interrupt, it needs to wait 1 second to let the * hardware be a stable state. Otherwise several consecutive * interrupts can be observed. * For link down interrupt, no need to wait. */ if (!link.link_status && rte_eal_alarm_set(I40E_US_PER_SECOND, i40e_dev_interrupt_delayed_handler, (void *)dev) >= 0) return; else _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); } done: /* Enable interrupt */ i40e_pf_enable_irq0(hw); rte_intr_enable(&(dev->pci_dev->intr_handle)); } static int i40e_add_macvlan_filters(struct i40e_vsi *vsi, struct i40e_macvlan_filter *filter, int total) { int ele_num, ele_buff_size; int num, actual_num, i; uint16_t flags; int ret = I40E_SUCCESS; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_add_macvlan_element_data *req_list; if (filter == NULL || total == 0) return I40E_ERR_PARAM; ele_num = hw->aq.asq_buf_size / sizeof(*req_list); ele_buff_size = hw->aq.asq_buf_size; req_list = rte_zmalloc("macvlan_add", ele_buff_size, 0); if (req_list == NULL) { PMD_DRV_LOG(ERR, "Fail to allocate memory"); return I40E_ERR_NO_MEMORY; } num = 0; do { actual_num = (num + ele_num > total) ? (total - num) : ele_num; memset(req_list, 0, ele_buff_size); for (i = 0; i < actual_num; i++) { (void)rte_memcpy(req_list[i].mac_addr, &filter[num + i].macaddr, ETH_ADDR_LEN); req_list[i].vlan_tag = rte_cpu_to_le_16(filter[num + i].vlan_id); switch (filter[num + i].filter_type) { case RTE_MAC_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH | I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; break; case RTE_MACVLAN_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; break; case RTE_MAC_HASH_MATCH: flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH | I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; break; case RTE_MACVLAN_HASH_MATCH: flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH; break; default: PMD_DRV_LOG(ERR, "Invalid MAC match type\n"); ret = I40E_ERR_PARAM; goto DONE; } req_list[i].queue_number = 0; req_list[i].flags = rte_cpu_to_le_16(flags); } ret = i40e_aq_add_macvlan(hw, vsi->seid, req_list, actual_num, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to add macvlan filter"); goto DONE; } num += actual_num; } while (num < total); DONE: rte_free(req_list); return ret; } static int i40e_remove_macvlan_filters(struct i40e_vsi *vsi, struct i40e_macvlan_filter *filter, int total) { int ele_num, ele_buff_size; int num, actual_num, i; uint16_t flags; int ret = I40E_SUCCESS; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); struct i40e_aqc_remove_macvlan_element_data *req_list; if (filter == NULL || total == 0) return I40E_ERR_PARAM; ele_num = hw->aq.asq_buf_size / sizeof(*req_list); ele_buff_size = hw->aq.asq_buf_size; req_list = rte_zmalloc("macvlan_remove", ele_buff_size, 0); if (req_list == NULL) { PMD_DRV_LOG(ERR, "Fail to allocate memory"); return I40E_ERR_NO_MEMORY; } num = 0; do { actual_num = (num + ele_num > total) ? (total - num) : ele_num; memset(req_list, 0, ele_buff_size); for (i = 0; i < actual_num; i++) { (void)rte_memcpy(req_list[i].mac_addr, &filter[num + i].macaddr, ETH_ADDR_LEN); req_list[i].vlan_tag = rte_cpu_to_le_16(filter[num + i].vlan_id); switch (filter[num + i].filter_type) { case RTE_MAC_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; break; case RTE_MACVLAN_PERFECT_MATCH: flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; break; case RTE_MAC_HASH_MATCH: flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH | I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; break; case RTE_MACVLAN_HASH_MATCH: flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH; break; default: PMD_DRV_LOG(ERR, "Invalid MAC filter type\n"); ret = I40E_ERR_PARAM; goto DONE; } req_list[i].flags = rte_cpu_to_le_16(flags); } ret = i40e_aq_remove_macvlan(hw, vsi->seid, req_list, actual_num, NULL); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to remove macvlan filter"); goto DONE; } num += actual_num; } while (num < total); DONE: rte_free(req_list); return ret; } /* Find out specific MAC filter */ static struct i40e_mac_filter * i40e_find_mac_filter(struct i40e_vsi *vsi, struct ether_addr *macaddr) { struct i40e_mac_filter *f; TAILQ_FOREACH(f, &vsi->mac_list, next) { if (is_same_ether_addr(macaddr, &f->mac_info.mac_addr)) return f; } return NULL; } static bool i40e_find_vlan_filter(struct i40e_vsi *vsi, uint16_t vlan_id) { uint32_t vid_idx, vid_bit; if (vlan_id > ETH_VLAN_ID_MAX) return 0; vid_idx = I40E_VFTA_IDX(vlan_id); vid_bit = I40E_VFTA_BIT(vlan_id); if (vsi->vfta[vid_idx] & vid_bit) return 1; else return 0; } static void i40e_set_vlan_filter(struct i40e_vsi *vsi, uint16_t vlan_id, bool on) { uint32_t vid_idx, vid_bit; if (vlan_id > ETH_VLAN_ID_MAX) return; vid_idx = I40E_VFTA_IDX(vlan_id); vid_bit = I40E_VFTA_BIT(vlan_id); if (on) vsi->vfta[vid_idx] |= vid_bit; else vsi->vfta[vid_idx] &= ~vid_bit; } /** * Find all vlan options for specific mac addr, * return with actual vlan found. */ static inline int i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi, struct i40e_macvlan_filter *mv_f, int num, struct ether_addr *addr) { int i; uint32_t j, k; /** * Not to use i40e_find_vlan_filter to decrease the loop time, * although the code looks complex. */ if (num < vsi->vlan_num) return I40E_ERR_PARAM; i = 0; for (j = 0; j < I40E_VFTA_SIZE; j++) { if (vsi->vfta[j]) { for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) { if (vsi->vfta[j] & (1 << k)) { if (i > num - 1) { PMD_DRV_LOG(ERR, "vlan number " "not match"); return I40E_ERR_PARAM; } (void)rte_memcpy(&mv_f[i].macaddr, addr, ETH_ADDR_LEN); mv_f[i].vlan_id = j * I40E_UINT32_BIT_SIZE + k; i++; } } } } return I40E_SUCCESS; } static inline int i40e_find_all_mac_for_vlan(struct i40e_vsi *vsi, struct i40e_macvlan_filter *mv_f, int num, uint16_t vlan) { int i = 0; struct i40e_mac_filter *f; if (num < vsi->mac_num) return I40E_ERR_PARAM; TAILQ_FOREACH(f, &vsi->mac_list, next) { if (i > num - 1) { PMD_DRV_LOG(ERR, "buffer number not match"); return I40E_ERR_PARAM; } (void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, ETH_ADDR_LEN); mv_f[i].vlan_id = vlan; mv_f[i].filter_type = f->mac_info.filter_type; i++; } return I40E_SUCCESS; } static int i40e_vsi_remove_all_macvlan_filter(struct i40e_vsi *vsi) { int i, num; struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; int ret = I40E_SUCCESS; if (vsi == NULL || vsi->mac_num == 0) return I40E_ERR_PARAM; /* Case that no vlan is set */ if (vsi->vlan_num == 0) num = vsi->mac_num; else num = vsi->mac_num * vsi->vlan_num; mv_f = rte_zmalloc("macvlan_data", num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } i = 0; if (vsi->vlan_num == 0) { TAILQ_FOREACH(f, &vsi->mac_list, next) { (void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, ETH_ADDR_LEN); mv_f[i].vlan_id = 0; i++; } } else { TAILQ_FOREACH(f, &vsi->mac_list, next) { ret = i40e_find_all_vlan_for_mac(vsi,&mv_f[i], vsi->vlan_num, &f->mac_info.mac_addr); if (ret != I40E_SUCCESS) goto DONE; i += vsi->vlan_num; } } ret = i40e_remove_macvlan_filters(vsi, mv_f, num); DONE: rte_free(mv_f); return ret; } int i40e_vsi_add_vlan(struct i40e_vsi *vsi, uint16_t vlan) { struct i40e_macvlan_filter *mv_f; int mac_num; int ret = I40E_SUCCESS; if (!vsi || vlan > ETHER_MAX_VLAN_ID) return I40E_ERR_PARAM; /* If it's already set, just return */ if (i40e_find_vlan_filter(vsi,vlan)) return I40E_SUCCESS; mac_num = vsi->mac_num; if (mac_num == 0) { PMD_DRV_LOG(ERR, "Error! VSI doesn't have a mac addr"); return I40E_ERR_PARAM; } mv_f = rte_zmalloc("macvlan_data", mac_num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } ret = i40e_find_all_mac_for_vlan(vsi, mv_f, mac_num, vlan); if (ret != I40E_SUCCESS) goto DONE; ret = i40e_add_macvlan_filters(vsi, mv_f, mac_num); if (ret != I40E_SUCCESS) goto DONE; i40e_set_vlan_filter(vsi, vlan, 1); vsi->vlan_num++; ret = I40E_SUCCESS; DONE: rte_free(mv_f); return ret; } int i40e_vsi_delete_vlan(struct i40e_vsi *vsi, uint16_t vlan) { struct i40e_macvlan_filter *mv_f; int mac_num; int ret = I40E_SUCCESS; /** * Vlan 0 is the generic filter for untagged packets * and can't be removed. */ if (!vsi || vlan == 0 || vlan > ETHER_MAX_VLAN_ID) return I40E_ERR_PARAM; /* If can't find it, just return */ if (!i40e_find_vlan_filter(vsi, vlan)) return I40E_ERR_PARAM; mac_num = vsi->mac_num; if (mac_num == 0) { PMD_DRV_LOG(ERR, "Error! VSI doesn't have a mac addr"); return I40E_ERR_PARAM; } mv_f = rte_zmalloc("macvlan_data", mac_num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } ret = i40e_find_all_mac_for_vlan(vsi, mv_f, mac_num, vlan); if (ret != I40E_SUCCESS) goto DONE; ret = i40e_remove_macvlan_filters(vsi, mv_f, mac_num); if (ret != I40E_SUCCESS) goto DONE; /* This is last vlan to remove, replace all mac filter with vlan 0 */ if (vsi->vlan_num == 1) { ret = i40e_find_all_mac_for_vlan(vsi, mv_f, mac_num, 0); if (ret != I40E_SUCCESS) goto DONE; ret = i40e_add_macvlan_filters(vsi, mv_f, mac_num); if (ret != I40E_SUCCESS) goto DONE; } i40e_set_vlan_filter(vsi, vlan, 0); vsi->vlan_num--; ret = I40E_SUCCESS; DONE: rte_free(mv_f); return ret; } int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *mac_filter) { struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; int i, vlan_num = 0; int ret = I40E_SUCCESS; /* If it's add and we've config it, return */ f = i40e_find_mac_filter(vsi, &mac_filter->mac_addr); if (f != NULL) return I40E_SUCCESS; if ((mac_filter->filter_type == RTE_MACVLAN_PERFECT_MATCH) || (mac_filter->filter_type == RTE_MACVLAN_HASH_MATCH)) { /** * If vlan_num is 0, that's the first time to add mac, * set mask for vlan_id 0. */ if (vsi->vlan_num == 0) { i40e_set_vlan_filter(vsi, 0, 1); vsi->vlan_num = 1; } vlan_num = vsi->vlan_num; } else if ((mac_filter->filter_type == RTE_MAC_PERFECT_MATCH) || (mac_filter->filter_type == RTE_MAC_HASH_MATCH)) vlan_num = 1; mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } for (i = 0; i < vlan_num; i++) { mv_f[i].filter_type = mac_filter->filter_type; (void)rte_memcpy(&mv_f[i].macaddr, &mac_filter->mac_addr, ETH_ADDR_LEN); } if (mac_filter->filter_type == RTE_MACVLAN_PERFECT_MATCH || mac_filter->filter_type == RTE_MACVLAN_HASH_MATCH) { ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, &mac_filter->mac_addr); if (ret != I40E_SUCCESS) goto DONE; } ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num); if (ret != I40E_SUCCESS) goto DONE; /* Add the mac addr into mac list */ f = rte_zmalloc("macv_filter", sizeof(*f), 0); if (f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); ret = I40E_ERR_NO_MEMORY; goto DONE; } (void)rte_memcpy(&f->mac_info.mac_addr, &mac_filter->mac_addr, ETH_ADDR_LEN); f->mac_info.filter_type = mac_filter->filter_type; TAILQ_INSERT_TAIL(&vsi->mac_list, f, next); vsi->mac_num++; ret = I40E_SUCCESS; DONE: rte_free(mv_f); return ret; } int i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr) { struct i40e_mac_filter *f; struct i40e_macvlan_filter *mv_f; int i, vlan_num; enum rte_mac_filter_type filter_type; int ret = I40E_SUCCESS; /* Can't find it, return an error */ f = i40e_find_mac_filter(vsi, addr); if (f == NULL) return I40E_ERR_PARAM; vlan_num = vsi->vlan_num; filter_type = f->mac_info.filter_type; if (filter_type == RTE_MACVLAN_PERFECT_MATCH || filter_type == RTE_MACVLAN_HASH_MATCH) { if (vlan_num == 0) { PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0\n"); return I40E_ERR_PARAM; } } else if (filter_type == RTE_MAC_PERFECT_MATCH || filter_type == RTE_MAC_HASH_MATCH) vlan_num = 1; mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0); if (mv_f == NULL) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } for (i = 0; i < vlan_num; i++) { mv_f[i].filter_type = filter_type; (void)rte_memcpy(&mv_f[i].macaddr, &f->mac_info.mac_addr, ETH_ADDR_LEN); } if (filter_type == RTE_MACVLAN_PERFECT_MATCH || filter_type == RTE_MACVLAN_HASH_MATCH) { ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num, addr); if (ret != I40E_SUCCESS) goto DONE; } ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num); if (ret != I40E_SUCCESS) goto DONE; /* Remove the mac addr into mac list */ TAILQ_REMOVE(&vsi->mac_list, f, next); rte_free(f); vsi->mac_num--; ret = I40E_SUCCESS; DONE: rte_free(mv_f); return ret; } /* Configure hash enable flags for RSS */ uint64_t i40e_config_hena(uint64_t flags) { uint64_t hena = 0; if (!flags) return hena; if (flags & ETH_RSS_FRAG_IPV4) hena |= 1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4; if (flags & ETH_RSS_NONFRAG_IPV4_TCP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP; if (flags & ETH_RSS_NONFRAG_IPV4_UDP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP; if (flags & ETH_RSS_NONFRAG_IPV4_SCTP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP; if (flags & ETH_RSS_NONFRAG_IPV4_OTHER) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER; if (flags & ETH_RSS_FRAG_IPV6) hena |= 1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6; if (flags & ETH_RSS_NONFRAG_IPV6_TCP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP; if (flags & ETH_RSS_NONFRAG_IPV6_UDP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP; if (flags & ETH_RSS_NONFRAG_IPV6_SCTP) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP; if (flags & ETH_RSS_NONFRAG_IPV6_OTHER) hena |= 1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER; if (flags & ETH_RSS_L2_PAYLOAD) hena |= 1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD; return hena; } /* Parse the hash enable flags */ uint64_t i40e_parse_hena(uint64_t flags) { uint64_t rss_hf = 0; if (!flags) return rss_hf; if (flags & (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4)) rss_hf |= ETH_RSS_FRAG_IPV4; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP)) rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP)) rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP)) rss_hf |= ETH_RSS_NONFRAG_IPV4_SCTP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER)) rss_hf |= ETH_RSS_NONFRAG_IPV4_OTHER; if (flags & (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6)) rss_hf |= ETH_RSS_FRAG_IPV6; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP)) rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP)) rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP)) rss_hf |= ETH_RSS_NONFRAG_IPV6_SCTP; if (flags & (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER)) rss_hf |= ETH_RSS_NONFRAG_IPV6_OTHER; if (flags & (1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD)) rss_hf |= ETH_RSS_L2_PAYLOAD; return rss_hf; } /* Disable RSS */ static void i40e_pf_disable_rss(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint64_t hena; hena = (uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(1))) << 32; hena &= ~I40E_RSS_HENA_ALL; I40E_WRITE_REG(hw, I40E_PFQF_HENA(0), (uint32_t)hena); I40E_WRITE_REG(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32)); I40E_WRITE_FLUSH(hw); } static int i40e_hw_rss_hash_set(struct i40e_hw *hw, struct rte_eth_rss_conf *rss_conf) { uint32_t *hash_key; uint8_t hash_key_len; uint64_t rss_hf; uint16_t i; uint64_t hena; hash_key = (uint32_t *)(rss_conf->rss_key); hash_key_len = rss_conf->rss_key_len; if (hash_key != NULL && hash_key_len >= (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) { /* Fill in RSS hash key */ for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) I40E_WRITE_REG(hw, I40E_PFQF_HKEY(i), hash_key[i]); } rss_hf = rss_conf->rss_hf; hena = (uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(1))) << 32; hena &= ~I40E_RSS_HENA_ALL; hena |= i40e_config_hena(rss_hf); I40E_WRITE_REG(hw, I40E_PFQF_HENA(0), (uint32_t)hena); I40E_WRITE_REG(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32)); I40E_WRITE_FLUSH(hw); return 0; } static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint64_t rss_hf = rss_conf->rss_hf & I40E_RSS_OFFLOAD_ALL; uint64_t hena; hena = (uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(1))) << 32; if (!(hena & I40E_RSS_HENA_ALL)) { /* RSS disabled */ if (rss_hf != 0) /* Enable RSS */ return -EINVAL; return 0; /* Nothing to do */ } /* RSS enabled */ if (rss_hf == 0) /* Disable RSS */ return -EINVAL; return i40e_hw_rss_hash_set(hw, rss_conf); } static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *hash_key = (uint32_t *)(rss_conf->rss_key); uint64_t hena; uint16_t i; if (hash_key != NULL) { for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) hash_key[i] = I40E_READ_REG(hw, I40E_PFQF_HKEY(i)); rss_conf->rss_key_len = i * sizeof(uint32_t); } hena = (uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_PFQF_HENA(1))) << 32; rss_conf->rss_hf = i40e_parse_hena(hena); return 0; } static int i40e_dev_get_filter_type(uint16_t filter_type, uint16_t *flag) { switch (filter_type) { case RTE_TUNNEL_FILTER_IMAC_IVLAN: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN; break; case RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_IVLAN_TEN_ID; break; case RTE_TUNNEL_FILTER_IMAC_TENID: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC_TEN_ID; break; case RTE_TUNNEL_FILTER_OMAC_TENID_IMAC: *flag = I40E_AQC_ADD_CLOUD_FILTER_OMAC_TEN_ID_IMAC; break; case ETH_TUNNEL_FILTER_IMAC: *flag = I40E_AQC_ADD_CLOUD_FILTER_IMAC; break; default: PMD_DRV_LOG(ERR, "invalid tunnel filter type"); return -EINVAL; } return 0; } static int i40e_dev_tunnel_filter_set(struct i40e_pf *pf, struct rte_eth_tunnel_filter_conf *tunnel_filter, uint8_t add) { uint16_t ip_type; uint8_t tun_type = 0; int val, ret = 0; struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_vsi *vsi = pf->main_vsi; struct i40e_aqc_add_remove_cloud_filters_element_data *cld_filter; struct i40e_aqc_add_remove_cloud_filters_element_data *pfilter; cld_filter = rte_zmalloc("tunnel_filter", sizeof(struct i40e_aqc_add_remove_cloud_filters_element_data), 0); if (NULL == cld_filter) { PMD_DRV_LOG(ERR, "Failed to alloc memory."); return -EINVAL; } pfilter = cld_filter; (void)rte_memcpy(&pfilter->outer_mac, tunnel_filter->outer_mac, sizeof(struct ether_addr)); (void)rte_memcpy(&pfilter->inner_mac, tunnel_filter->inner_mac, sizeof(struct ether_addr)); pfilter->inner_vlan = tunnel_filter->inner_vlan; if (tunnel_filter->ip_type == RTE_TUNNEL_IPTYPE_IPV4) { ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4; (void)rte_memcpy(&pfilter->ipaddr.v4.data, &tunnel_filter->ip_addr, sizeof(pfilter->ipaddr.v4.data)); } else { ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6; (void)rte_memcpy(&pfilter->ipaddr.v6.data, &tunnel_filter->ip_addr, sizeof(pfilter->ipaddr.v6.data)); } /* check tunneled type */ switch (tunnel_filter->tunnel_type) { case RTE_TUNNEL_TYPE_VXLAN: tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN; break; case RTE_TUNNEL_TYPE_NVGRE: tun_type = I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC; break; default: /* Other tunnel types is not supported. */ PMD_DRV_LOG(ERR, "tunnel type is not supported."); rte_free(cld_filter); return -EINVAL; } val = i40e_dev_get_filter_type(tunnel_filter->filter_type, &pfilter->flags); if (val < 0) { rte_free(cld_filter); return -EINVAL; } pfilter->flags |= I40E_AQC_ADD_CLOUD_FLAGS_TO_QUEUE | ip_type | (tun_type << I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT); pfilter->tenant_id = tunnel_filter->tenant_id; pfilter->queue_number = tunnel_filter->queue_id; if (add) ret = i40e_aq_add_cloud_filters(hw, vsi->seid, cld_filter, 1); else ret = i40e_aq_remove_cloud_filters(hw, vsi->seid, cld_filter, 1); rte_free(cld_filter); return ret; } static int i40e_get_vxlan_port_idx(struct i40e_pf *pf, uint16_t port) { uint8_t i; for (i = 0; i < I40E_MAX_PF_UDP_OFFLOAD_PORTS; i++) { if (pf->vxlan_ports[i] == port) return i; } return -1; } static int i40e_add_vxlan_port(struct i40e_pf *pf, uint16_t port) { int idx, ret; uint8_t filter_idx; struct i40e_hw *hw = I40E_PF_TO_HW(pf); idx = i40e_get_vxlan_port_idx(pf, port); /* Check if port already exists */ if (idx >= 0) { PMD_DRV_LOG(ERR, "Port %d already offloaded", port); return -EINVAL; } /* Now check if there is space to add the new port */ idx = i40e_get_vxlan_port_idx(pf, 0); if (idx < 0) { PMD_DRV_LOG(ERR, "Maximum number of UDP ports reached," "not adding port %d", port); return -ENOSPC; } ret = i40e_aq_add_udp_tunnel(hw, port, I40E_AQC_TUNNEL_TYPE_VXLAN, &filter_idx, NULL); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to add VXLAN UDP port %d", port); return -1; } PMD_DRV_LOG(INFO, "Added port %d with AQ command with index %d", port, filter_idx); /* New port: add it and mark its index in the bitmap */ pf->vxlan_ports[idx] = port; pf->vxlan_bitmap |= (1 << idx); if (!(pf->flags & I40E_FLAG_VXLAN)) pf->flags |= I40E_FLAG_VXLAN; return 0; } static int i40e_del_vxlan_port(struct i40e_pf *pf, uint16_t port) { int idx; struct i40e_hw *hw = I40E_PF_TO_HW(pf); if (!(pf->flags & I40E_FLAG_VXLAN)) { PMD_DRV_LOG(ERR, "VXLAN UDP port was not configured."); return -EINVAL; } idx = i40e_get_vxlan_port_idx(pf, port); if (idx < 0) { PMD_DRV_LOG(ERR, "Port %d doesn't exist", port); return -EINVAL; } if (i40e_aq_del_udp_tunnel(hw, idx, NULL) < 0) { PMD_DRV_LOG(ERR, "Failed to delete VXLAN UDP port %d", port); return -1; } PMD_DRV_LOG(INFO, "Deleted port %d with AQ command with index %d", port, idx); pf->vxlan_ports[idx] = 0; pf->vxlan_bitmap &= ~(1 << idx); if (!pf->vxlan_bitmap) pf->flags &= ~I40E_FLAG_VXLAN; return 0; } /* Add UDP tunneling port */ static int i40e_dev_udp_tunnel_add(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *udp_tunnel) { int ret = 0; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); if (udp_tunnel == NULL) return -EINVAL; switch (udp_tunnel->prot_type) { case RTE_TUNNEL_TYPE_VXLAN: ret = i40e_add_vxlan_port(pf, udp_tunnel->udp_port); break; case RTE_TUNNEL_TYPE_GENEVE: case RTE_TUNNEL_TYPE_TEREDO: PMD_DRV_LOG(ERR, "Tunnel type is not supported now."); ret = -1; break; default: PMD_DRV_LOG(ERR, "Invalid tunnel type"); ret = -1; break; } return ret; } /* Remove UDP tunneling port */ static int i40e_dev_udp_tunnel_del(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *udp_tunnel) { int ret = 0; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); if (udp_tunnel == NULL) return -EINVAL; switch (udp_tunnel->prot_type) { case RTE_TUNNEL_TYPE_VXLAN: ret = i40e_del_vxlan_port(pf, udp_tunnel->udp_port); break; case RTE_TUNNEL_TYPE_GENEVE: case RTE_TUNNEL_TYPE_TEREDO: PMD_DRV_LOG(ERR, "Tunnel type is not supported now."); ret = -1; break; default: PMD_DRV_LOG(ERR, "Invalid tunnel type"); ret = -1; break; } return ret; } /* Calculate the maximum number of contiguous PF queues that are configured */ static int i40e_pf_calc_configured_queues_num(struct i40e_pf *pf) { struct rte_eth_dev_data *data = pf->dev_data; int i, num; struct i40e_rx_queue *rxq; num = 0; for (i = 0; i < pf->lan_nb_qps; i++) { rxq = data->rx_queues[i]; if (rxq && rxq->q_set) num++; else break; } return num; } /* Configure RSS */ static int i40e_pf_config_rss(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct rte_eth_rss_conf rss_conf; uint32_t i, lut = 0; uint16_t j, num; /* * If both VMDQ and RSS enabled, not all of PF queues are configured. * It's necessary to calulate the actual PF queues that are configured. */ if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) { num = i40e_pf_calc_configured_queues_num(pf); num = i40e_align_floor(num); } else num = i40e_align_floor(pf->dev_data->nb_rx_queues); PMD_INIT_LOG(INFO, "Max of contiguous %u PF queues are configured", num); if (num == 0) { PMD_INIT_LOG(ERR, "No PF queues are configured to enable RSS"); return -ENOTSUP; } for (i = 0, j = 0; i < hw->func_caps.rss_table_size; i++, j++) { if (j == num) j = 0; lut = (lut << 8) | (j & ((0x1 << hw->func_caps.rss_table_entry_width) - 1)); if ((i & 3) == 3) I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i >> 2), lut); } rss_conf = pf->dev_data->dev_conf.rx_adv_conf.rss_conf; if ((rss_conf.rss_hf & I40E_RSS_OFFLOAD_ALL) == 0) { i40e_pf_disable_rss(pf); return 0; } if (rss_conf.rss_key == NULL || rss_conf.rss_key_len < (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) { /* Random default keys */ static uint32_t rss_key_default[] = {0x6b793944, 0x23504cb5, 0x5bea75b6, 0x309f4f12, 0x3dc0a2b8, 0x024ddcdf, 0x339b8ca0, 0x4c4af64a, 0x34fac605, 0x55d85839, 0x3a58997d, 0x2ec938e1, 0x66031581}; rss_conf.rss_key = (uint8_t *)rss_key_default; rss_conf.rss_key_len = (I40E_PFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t); } return i40e_hw_rss_hash_set(hw, &rss_conf); } static int i40e_tunnel_filter_param_check(struct i40e_pf *pf, struct rte_eth_tunnel_filter_conf *filter) { if (pf == NULL || filter == NULL) { PMD_DRV_LOG(ERR, "Invalid parameter"); return -EINVAL; } if (filter->queue_id >= pf->dev_data->nb_rx_queues) { PMD_DRV_LOG(ERR, "Invalid queue ID"); return -EINVAL; } if (filter->inner_vlan > ETHER_MAX_VLAN_ID) { PMD_DRV_LOG(ERR, "Invalid inner VLAN ID"); return -EINVAL; } if ((filter->filter_type & ETH_TUNNEL_FILTER_OMAC) && (is_zero_ether_addr(filter->outer_mac))) { PMD_DRV_LOG(ERR, "Cannot add NULL outer MAC address"); return -EINVAL; } if ((filter->filter_type & ETH_TUNNEL_FILTER_IMAC) && (is_zero_ether_addr(filter->inner_mac))) { PMD_DRV_LOG(ERR, "Cannot add NULL inner MAC address"); return -EINVAL; } return 0; } static int i40e_tunnel_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct rte_eth_tunnel_filter_conf *filter; struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int ret = I40E_SUCCESS; filter = (struct rte_eth_tunnel_filter_conf *)(arg); if (i40e_tunnel_filter_param_check(pf, filter) < 0) return I40E_ERR_PARAM; switch (filter_op) { case RTE_ETH_FILTER_NOP: if (!(pf->flags & I40E_FLAG_VXLAN)) ret = I40E_NOT_SUPPORTED; case RTE_ETH_FILTER_ADD: ret = i40e_dev_tunnel_filter_set(pf, filter, 1); break; case RTE_ETH_FILTER_DELETE: ret = i40e_dev_tunnel_filter_set(pf, filter, 0); break; default: PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); ret = I40E_ERR_PARAM; break; } return ret; } static int i40e_pf_config_mq_rx(struct i40e_pf *pf) { int ret = 0; enum rte_eth_rx_mq_mode mq_mode = pf->dev_data->dev_conf.rxmode.mq_mode; if (mq_mode & ETH_MQ_RX_DCB_FLAG) { PMD_INIT_LOG(ERR, "i40e doesn't support DCB yet"); return -ENOTSUP; } /* RSS setup */ if (mq_mode & ETH_MQ_RX_RSS_FLAG) ret = i40e_pf_config_rss(pf); else i40e_pf_disable_rss(pf); return ret; } /* Get the symmetric hash enable configurations per port */ static void i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable) { uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); *enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0; } /* Set the symmetric hash enable configurations per port */ static void i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable) { uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); if (enable > 0) { if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) { PMD_DRV_LOG(INFO, "Symmetric hash has already " "been enabled"); return; } reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK; } else { if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) { PMD_DRV_LOG(INFO, "Symmetric hash has already " "been disabled"); return; } reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK; } I40E_WRITE_REG(hw, I40E_PRTQF_CTL_0, reg); I40E_WRITE_FLUSH(hw); } /* * Get global configurations of hash function type and symmetric hash enable * per flow type (pctype). Note that global configuration means it affects all * the ports on the same NIC. */ static int i40e_get_hash_filter_global_config(struct i40e_hw *hw, struct rte_eth_hash_global_conf *g_cfg) { uint32_t reg, mask = I40E_FLOW_TYPES; uint16_t i; enum i40e_filter_pctype pctype; memset(g_cfg, 0, sizeof(*g_cfg)); reg = I40E_READ_REG(hw, I40E_GLQF_CTL); if (reg & I40E_GLQF_CTL_HTOEP_MASK) g_cfg->hash_func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; else g_cfg->hash_func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; PMD_DRV_LOG(DEBUG, "Hash function is %s", (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); for (i = 0; mask && i < RTE_ETH_FLOW_MAX; i++) { if (!(mask & (1UL << i))) continue; mask &= ~(1UL << i); /* Bit set indicats the coresponding flow type is supported */ g_cfg->valid_bit_mask[0] |= (1UL << i); pctype = i40e_flowtype_to_pctype(i); reg = I40E_READ_REG(hw, I40E_GLQF_HSYM(pctype)); if (reg & I40E_GLQF_HSYM_SYMH_ENA_MASK) g_cfg->sym_hash_enable_mask[0] |= (1UL << i); } return 0; } static int i40e_hash_global_config_check(struct rte_eth_hash_global_conf *g_cfg) { uint32_t i; uint32_t mask0, i40e_mask = I40E_FLOW_TYPES; if (g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_TOEPLITZ && g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_SIMPLE_XOR && g_cfg->hash_func != RTE_ETH_HASH_FUNCTION_DEFAULT) { PMD_DRV_LOG(ERR, "Unsupported hash function type %d", g_cfg->hash_func); return -EINVAL; } /* * As i40e supports less than 32 flow types, only first 32 bits need to * be checked. */ mask0 = g_cfg->valid_bit_mask[0]; for (i = 0; i < RTE_SYM_HASH_MASK_ARRAY_SIZE; i++) { if (i == 0) { /* Check if any unsupported flow type configured */ if ((mask0 | i40e_mask) ^ i40e_mask) goto mask_err; } else { if (g_cfg->valid_bit_mask[i]) goto mask_err; } } return 0; mask_err: PMD_DRV_LOG(ERR, "i40e unsupported flow type bit(s) configured"); return -EINVAL; } /* * Set global configurations of hash function type and symmetric hash enable * per flow type (pctype). Note any modifying global configuration will affect * all the ports on the same NIC. */ static int i40e_set_hash_filter_global_config(struct i40e_hw *hw, struct rte_eth_hash_global_conf *g_cfg) { int ret; uint16_t i; uint32_t reg; uint32_t mask0 = g_cfg->valid_bit_mask[0]; enum i40e_filter_pctype pctype; /* Check the input parameters */ ret = i40e_hash_global_config_check(g_cfg); if (ret < 0) return ret; for (i = 0; mask0 && i < UINT32_BIT; i++) { if (!(mask0 & (1UL << i))) continue; mask0 &= ~(1UL << i); pctype = i40e_flowtype_to_pctype(i); reg = (g_cfg->sym_hash_enable_mask[0] & (1UL << i)) ? I40E_GLQF_HSYM_SYMH_ENA_MASK : 0; I40E_WRITE_REG(hw, I40E_GLQF_HSYM(pctype), reg); } reg = I40E_READ_REG(hw, I40E_GLQF_CTL); if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_TOEPLITZ) { /* Toeplitz */ if (reg & I40E_GLQF_CTL_HTOEP_MASK) { PMD_DRV_LOG(DEBUG, "Hash function already set to " "Toeplitz"); goto out; } reg |= I40E_GLQF_CTL_HTOEP_MASK; } else if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { /* Simple XOR */ if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) { PMD_DRV_LOG(DEBUG, "Hash function already set to " "Simple XOR"); goto out; } reg &= ~I40E_GLQF_CTL_HTOEP_MASK; } else /* Use the default, and keep it as it is */ goto out; I40E_WRITE_REG(hw, I40E_GLQF_CTL, reg); out: I40E_WRITE_FLUSH(hw); return 0; } static int i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) { int ret = 0; if (!hw || !info) { PMD_DRV_LOG(ERR, "Invalid pointer"); return -EFAULT; } switch (info->info_type) { case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: i40e_get_symmetric_hash_enable_per_port(hw, &(info->info.enable)); break; case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: ret = i40e_get_hash_filter_global_config(hw, &(info->info.global_conf)); break; default: PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", info->info_type); ret = -EINVAL; break; } return ret; } static int i40e_hash_filter_set(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) { int ret = 0; if (!hw || !info) { PMD_DRV_LOG(ERR, "Invalid pointer"); return -EFAULT; } switch (info->info_type) { case RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT: i40e_set_symmetric_hash_enable_per_port(hw, info->info.enable); break; case RTE_ETH_HASH_FILTER_GLOBAL_CONFIG: ret = i40e_set_hash_filter_global_config(hw, &(info->info.global_conf)); break; default: PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", info->info_type); ret = -EINVAL; break; } return ret; } /* Operations for hash function */ static int i40e_hash_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret = 0; switch (filter_op) { case RTE_ETH_FILTER_NOP: break; case RTE_ETH_FILTER_GET: ret = i40e_hash_filter_get(hw, (struct rte_eth_hash_filter_info *)arg); break; case RTE_ETH_FILTER_SET: ret = i40e_hash_filter_set(hw, (struct rte_eth_hash_filter_info *)arg); break; default: PMD_DRV_LOG(WARNING, "Filter operation (%d) not supported", filter_op); ret = -ENOTSUP; break; } return ret; } /* * Configure ethertype filter, which can director packet by filtering * with mac address and ether_type or only ether_type */ static int i40e_ethertype_filter_set(struct i40e_pf *pf, struct rte_eth_ethertype_filter *filter, bool add) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_control_filter_stats stats; uint16_t flags = 0; int ret; if (filter->queue >= pf->dev_data->nb_rx_queues) { PMD_DRV_LOG(ERR, "Invalid queue ID"); return -EINVAL; } if (filter->ether_type == ETHER_TYPE_IPv4 || filter->ether_type == ETHER_TYPE_IPv6) { PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in" " control packet filter.", filter->ether_type); return -EINVAL; } if (filter->ether_type == ETHER_TYPE_VLAN) PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is" " not supported."); if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC)) flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC; if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP; flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE; memset(&stats, 0, sizeof(stats)); ret = i40e_aq_add_rem_control_packet_filter(hw, filter->mac_addr.addr_bytes, filter->ether_type, flags, pf->main_vsi->seid, filter->queue, add, &stats, NULL); PMD_DRV_LOG(INFO, "add/rem control packet filter, return %d," " mac_etype_used = %u, etype_used = %u," " mac_etype_free = %u, etype_free = %u\n", ret, stats.mac_etype_used, stats.etype_used, stats.mac_etype_free, stats.etype_free); if (ret < 0) return -ENOSYS; return 0; } /* * Handle operations for ethertype filter. */ static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int ret = 0; if (filter_op == RTE_ETH_FILTER_NOP) return ret; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = i40e_ethertype_filter_set(pf, (struct rte_eth_ethertype_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = i40e_ethertype_filter_set(pf, (struct rte_eth_ethertype_filter *)arg, FALSE); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op); ret = -ENOSYS; break; } return ret; } static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg) { int ret = 0; if (dev == NULL) return -EINVAL; switch (filter_type) { case RTE_ETH_FILTER_HASH: ret = i40e_hash_filter_ctrl(dev, filter_op, arg); break; case RTE_ETH_FILTER_MACVLAN: ret = i40e_mac_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_ETHERTYPE: ret = i40e_ethertype_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_TUNNEL: ret = i40e_tunnel_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_FDIR: ret = i40e_fdir_ctrl_func(dev, filter_op, arg); break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type); ret = -EINVAL; break; } return ret; } /* * As some registers wouldn't be reset unless a global hardware reset, * hardware initialization is needed to put those registers into an * expected initial state. */ static void i40e_hw_init(struct i40e_hw *hw) { /* clear the PF Queue Filter control register */ I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, 0); /* Disable symmetric hash per port */ i40e_set_symmetric_hash_enable_per_port(hw, 0); } enum i40e_filter_pctype i40e_flowtype_to_pctype(uint16_t flow_type) { static const enum i40e_filter_pctype pctype_table[] = { [RTE_ETH_FLOW_FRAG_IPV4] = I40E_FILTER_PCTYPE_FRAG_IPV4, [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = I40E_FILTER_PCTYPE_NONF_IPV4_UDP, [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = I40E_FILTER_PCTYPE_NONF_IPV4_TCP, [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = I40E_FILTER_PCTYPE_NONF_IPV4_SCTP, [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER, [RTE_ETH_FLOW_FRAG_IPV6] = I40E_FILTER_PCTYPE_FRAG_IPV6, [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = I40E_FILTER_PCTYPE_NONF_IPV6_UDP, [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = I40E_FILTER_PCTYPE_NONF_IPV6_TCP, [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = I40E_FILTER_PCTYPE_NONF_IPV6_SCTP, [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = I40E_FILTER_PCTYPE_NONF_IPV6_OTHER, [RTE_ETH_FLOW_L2_PAYLOAD] = I40E_FILTER_PCTYPE_L2_PAYLOAD, }; return pctype_table[flow_type]; } uint16_t i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype) { static const uint16_t flowtype_table[] = { [I40E_FILTER_PCTYPE_FRAG_IPV4] = RTE_ETH_FLOW_FRAG_IPV4, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = RTE_ETH_FLOW_NONFRAG_IPV4_UDP, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = RTE_ETH_FLOW_NONFRAG_IPV4_TCP, [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] = RTE_ETH_FLOW_NONFRAG_IPV4_SCTP, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, [I40E_FILTER_PCTYPE_FRAG_IPV6] = RTE_ETH_FLOW_FRAG_IPV6, [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = RTE_ETH_FLOW_NONFRAG_IPV6_UDP, [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] = RTE_ETH_FLOW_NONFRAG_IPV6_TCP, [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = RTE_ETH_FLOW_NONFRAG_IPV6_SCTP, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = RTE_ETH_FLOW_NONFRAG_IPV6_OTHER, [I40E_FILTER_PCTYPE_L2_PAYLOAD] = RTE_ETH_FLOW_L2_PAYLOAD, }; return flowtype_table[pctype]; } /* * On X710, performance number is far from the expectation on recent firmware * versions; on XL710, performance number is also far from the expectation on * recent firmware versions, if promiscuous mode is disabled, or promiscuous * mode is enabled and port MAC address is equal to the packet destination MAC * address. The fix for this issue may not be integrated in the following * firmware version. So the workaround in software driver is needed. It needs * to modify the initial values of 3 internal only registers for both X710 and * XL710. Note that the values for X710 or XL710 could be different, and the * workaround can be removed when it is fixed in firmware in the future. */ /* For both X710 and XL710 */ #define I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE 0x10000200 #define I40E_GL_SWR_PRI_JOIN_MAP_0 0x26CE00 #define I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE 0x011f0200 #define I40E_GL_SWR_PRI_JOIN_MAP_2 0x26CE08 /* For X710 */ #define I40E_GL_SWR_PM_UP_THR_EF_VALUE 0x03030303 /* For XL710 */ #define I40E_GL_SWR_PM_UP_THR_SF_VALUE 0x06060606 #define I40E_GL_SWR_PM_UP_THR 0x269FBC static void i40e_configure_registers(struct i40e_hw *hw) { static struct { uint32_t addr; uint64_t val; } reg_table[] = { {I40E_GL_SWR_PRI_JOIN_MAP_0, I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE}, {I40E_GL_SWR_PRI_JOIN_MAP_2, I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE}, {I40E_GL_SWR_PM_UP_THR, 0}, /* Compute value dynamically */ }; uint64_t reg; uint32_t i; int ret; for (i = 0; i < RTE_DIM(reg_table); i++) { if (reg_table[i].addr == I40E_GL_SWR_PM_UP_THR) { if (i40e_is_40G_device(hw->device_id)) /* For XL710 */ reg_table[i].val = I40E_GL_SWR_PM_UP_THR_SF_VALUE; else /* For X710 */ reg_table[i].val = I40E_GL_SWR_PM_UP_THR_EF_VALUE; } ret = i40e_aq_debug_read_register(hw, reg_table[i].addr, ®, NULL); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to read from 0x%"PRIx32, reg_table[i].addr); break; } PMD_DRV_LOG(DEBUG, "Read from 0x%"PRIx32": 0x%"PRIx64, reg_table[i].addr, reg); if (reg == reg_table[i].val) continue; ret = i40e_aq_debug_write_register(hw, reg_table[i].addr, reg_table[i].val, NULL); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to write 0x%"PRIx64" to the " "address of 0x%"PRIx32, reg_table[i].val, reg_table[i].addr); break; } PMD_DRV_LOG(DEBUG, "Write 0x%"PRIx64" to the address of " "0x%"PRIx32, reg_table[i].val, reg_table[i].addr); } } #define I40E_VSI_TSR(_i) (0x00050800 + ((_i) * 4)) #define I40E_VSI_TSR_QINQ_CONFIG 0xc030 #define I40E_VSI_L2TAGSTXVALID(_i) (0x00042800 + ((_i) * 4)) #define I40E_VSI_L2TAGSTXVALID_QINQ 0xab static int i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi) { uint32_t reg; int ret; if (vsi->vsi_id >= I40E_MAX_NUM_VSIS) { PMD_DRV_LOG(ERR, "VSI ID exceeds the maximum"); return -EINVAL; } /* Configure for double VLAN RX stripping */ reg = I40E_READ_REG(hw, I40E_VSI_TSR(vsi->vsi_id)); if ((reg & I40E_VSI_TSR_QINQ_CONFIG) != I40E_VSI_TSR_QINQ_CONFIG) { reg |= I40E_VSI_TSR_QINQ_CONFIG; ret = i40e_aq_debug_write_register(hw, I40E_VSI_TSR(vsi->vsi_id), reg, NULL); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to update VSI_TSR[%d]", vsi->vsi_id); return I40E_ERR_CONFIG; } } /* Configure for double VLAN TX insertion */ reg = I40E_READ_REG(hw, I40E_VSI_L2TAGSTXVALID(vsi->vsi_id)); if ((reg & 0xff) != I40E_VSI_L2TAGSTXVALID_QINQ) { reg = I40E_VSI_L2TAGSTXVALID_QINQ; ret = i40e_aq_debug_write_register(hw, I40E_VSI_L2TAGSTXVALID( vsi->vsi_id), reg, NULL); if (ret < 0) { PMD_DRV_LOG(ERR, "Failed to update " "VSI_L2TAGSTXVALID[%d]", vsi->vsi_id); return I40E_ERR_CONFIG; } } return 0; } /** * i40e_aq_add_mirror_rule * @hw: pointer to the hardware structure * @seid: VEB seid to add mirror rule to * @dst_id: destination vsi seid * @entries: Buffer which contains the entities to be mirrored * @count: number of entities contained in the buffer * @rule_id:the rule_id of the rule to be added * * Add a mirror rule for a given veb. * **/ static enum i40e_status_code i40e_aq_add_mirror_rule(struct i40e_hw *hw, uint16_t seid, uint16_t dst_id, uint16_t rule_type, uint16_t *entries, uint16_t count, uint16_t *rule_id) { struct i40e_aq_desc desc; struct i40e_aqc_add_delete_mirror_rule cmd; struct i40e_aqc_add_delete_mirror_rule_completion *resp = (struct i40e_aqc_add_delete_mirror_rule_completion *) &desc.params.raw; uint16_t buff_len; enum i40e_status_code status; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_mirror_rule); memset(&cmd, 0, sizeof(cmd)); buff_len = sizeof(uint16_t) * count; desc.datalen = rte_cpu_to_le_16(buff_len); if (buff_len > 0) desc.flags |= rte_cpu_to_le_16( (uint16_t)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); cmd.rule_type = rte_cpu_to_le_16(rule_type << I40E_AQC_MIRROR_RULE_TYPE_SHIFT); cmd.num_entries = rte_cpu_to_le_16(count); cmd.seid = rte_cpu_to_le_16(seid); cmd.destination = rte_cpu_to_le_16(dst_id); rte_memcpy(&desc.params.raw, &cmd, sizeof(cmd)); status = i40e_asq_send_command(hw, &desc, entries, buff_len, NULL); PMD_DRV_LOG(INFO, "i40e_aq_add_mirror_rule, aq_status %d," "rule_id = %u" " mirror_rules_used = %u, mirror_rules_free = %u,", hw->aq.asq_last_status, resp->rule_id, resp->mirror_rules_used, resp->mirror_rules_free); *rule_id = rte_le_to_cpu_16(resp->rule_id); return status; } /** * i40e_aq_del_mirror_rule * @hw: pointer to the hardware structure * @seid: VEB seid to add mirror rule to * @entries: Buffer which contains the entities to be mirrored * @count: number of entities contained in the buffer * @rule_id:the rule_id of the rule to be delete * * Delete a mirror rule for a given veb. * **/ static enum i40e_status_code i40e_aq_del_mirror_rule(struct i40e_hw *hw, uint16_t seid, uint16_t rule_type, uint16_t *entries, uint16_t count, uint16_t rule_id) { struct i40e_aq_desc desc; struct i40e_aqc_add_delete_mirror_rule cmd; uint16_t buff_len = 0; enum i40e_status_code status; void *buff = NULL; i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_delete_mirror_rule); memset(&cmd, 0, sizeof(cmd)); if (rule_type == I40E_AQC_MIRROR_RULE_TYPE_VLAN) { desc.flags |= rte_cpu_to_le_16((uint16_t)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); cmd.num_entries = count; buff_len = sizeof(uint16_t) * count; desc.datalen = rte_cpu_to_le_16(buff_len); buff = (void *)entries; } else /* rule id is filled in destination field for deleting mirror rule */ cmd.destination = rte_cpu_to_le_16(rule_id); cmd.rule_type = rte_cpu_to_le_16(rule_type << I40E_AQC_MIRROR_RULE_TYPE_SHIFT); cmd.seid = rte_cpu_to_le_16(seid); rte_memcpy(&desc.params.raw, &cmd, sizeof(cmd)); status = i40e_asq_send_command(hw, &desc, buff, buff_len, NULL); return status; } /** * i40e_mirror_rule_set * @dev: pointer to the hardware structure * @mirror_conf: mirror rule info * @sw_id: mirror rule's sw_id * @on: enable/disable * * set a mirror rule. * **/ static int i40e_mirror_rule_set(struct rte_eth_dev *dev, struct rte_eth_mirror_conf *mirror_conf, uint8_t sw_id, uint8_t on) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_mirror_rule *it, *mirr_rule = NULL; struct i40e_mirror_rule *parent = NULL; uint16_t seid, dst_seid, rule_id; uint16_t i, j = 0; int ret; PMD_DRV_LOG(DEBUG, "i40e_mirror_rule_set: sw_id = %d.", sw_id); if (pf->main_vsi->veb == NULL || pf->vfs == NULL) { PMD_DRV_LOG(ERR, "mirror rule can not be configured" " without veb or vfs."); return -ENOSYS; } if (pf->nb_mirror_rule > I40E_MAX_MIRROR_RULES) { PMD_DRV_LOG(ERR, "mirror table is full."); return -ENOSPC; } if (mirror_conf->dst_pool > pf->vf_num) { PMD_DRV_LOG(ERR, "invalid destination pool %u.", mirror_conf->dst_pool); return -EINVAL; } seid = pf->main_vsi->veb->seid; TAILQ_FOREACH(it, &pf->mirror_list, rules) { if (sw_id <= it->index) { mirr_rule = it; break; } parent = it; } if (mirr_rule && sw_id == mirr_rule->index) { if (on) { PMD_DRV_LOG(ERR, "mirror rule exists."); return -EEXIST; } else { ret = i40e_aq_del_mirror_rule(hw, seid, mirr_rule->rule_type, mirr_rule->entries, mirr_rule->num_entries, mirr_rule->id); if (ret < 0) { PMD_DRV_LOG(ERR, "failed to remove mirror rule:" " ret = %d, aq_err = %d.", ret, hw->aq.asq_last_status); return -ENOSYS; } TAILQ_REMOVE(&pf->mirror_list, mirr_rule, rules); rte_free(mirr_rule); pf->nb_mirror_rule--; return 0; } } else if (!on) { PMD_DRV_LOG(ERR, "mirror rule doesn't exist."); return -ENOENT; } mirr_rule = rte_zmalloc("i40e_mirror_rule", sizeof(struct i40e_mirror_rule) , 0); if (!mirr_rule) { PMD_DRV_LOG(ERR, "failed to allocate memory"); return I40E_ERR_NO_MEMORY; } switch (mirror_conf->rule_type) { case ETH_MIRROR_VLAN: for (i = 0, j = 0; i < ETH_MIRROR_MAX_VLANS; i++) { if (mirror_conf->vlan.vlan_mask & (1ULL << i)) { mirr_rule->entries[j] = mirror_conf->vlan.vlan_id[i]; j++; } } if (j == 0) { PMD_DRV_LOG(ERR, "vlan is not specified."); rte_free(mirr_rule); return -EINVAL; } mirr_rule->rule_type = I40E_AQC_MIRROR_RULE_TYPE_VLAN; break; case ETH_MIRROR_VIRTUAL_POOL_UP: case ETH_MIRROR_VIRTUAL_POOL_DOWN: /* check if the specified pool bit is out of range */ if (mirror_conf->pool_mask > (uint64_t)(1ULL << (pf->vf_num + 1))) { PMD_DRV_LOG(ERR, "pool mask is out of range."); rte_free(mirr_rule); return -EINVAL; } for (i = 0, j = 0; i < pf->vf_num; i++) { if (mirror_conf->pool_mask & (1ULL << i)) { mirr_rule->entries[j] = pf->vfs[i].vsi->seid; j++; } } if (mirror_conf->pool_mask & (1ULL << pf->vf_num)) { /* add pf vsi to entries */ mirr_rule->entries[j] = pf->main_vsi_seid; j++; } if (j == 0) { PMD_DRV_LOG(ERR, "pool is not specified."); rte_free(mirr_rule); return -EINVAL; } /* egress and ingress in aq commands means from switch but not port */ mirr_rule->rule_type = (mirror_conf->rule_type == ETH_MIRROR_VIRTUAL_POOL_UP) ? I40E_AQC_MIRROR_RULE_TYPE_VPORT_EGRESS : I40E_AQC_MIRROR_RULE_TYPE_VPORT_INGRESS; break; case ETH_MIRROR_UPLINK_PORT: /* egress and ingress in aq commands means from switch but not port*/ mirr_rule->rule_type = I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS; break; case ETH_MIRROR_DOWNLINK_PORT: mirr_rule->rule_type = I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS; break; default: PMD_DRV_LOG(ERR, "unsupported mirror type %d.", mirror_conf->rule_type); rte_free(mirr_rule); return -EINVAL; } /* If the dst_pool is equal to vf_num, consider it as PF */ if (mirror_conf->dst_pool == pf->vf_num) dst_seid = pf->main_vsi_seid; else dst_seid = pf->vfs[mirror_conf->dst_pool].vsi->seid; ret = i40e_aq_add_mirror_rule(hw, seid, dst_seid, mirr_rule->rule_type, mirr_rule->entries, j, &rule_id); if (ret < 0) { PMD_DRV_LOG(ERR, "failed to add mirror rule:" " ret = %d, aq_err = %d.", ret, hw->aq.asq_last_status); rte_free(mirr_rule); return -ENOSYS; } mirr_rule->index = sw_id; mirr_rule->num_entries = j; mirr_rule->id = rule_id; mirr_rule->dst_vsi_seid = dst_seid; if (parent) TAILQ_INSERT_AFTER(&pf->mirror_list, parent, mirr_rule, rules); else TAILQ_INSERT_HEAD(&pf->mirror_list, mirr_rule, rules); pf->nb_mirror_rule++; return 0; } /** * i40e_mirror_rule_reset * @dev: pointer to the device * @sw_id: mirror rule's sw_id * * reset a mirror rule. * **/ static int i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_mirror_rule *it, *mirr_rule = NULL; uint16_t seid; int ret; PMD_DRV_LOG(DEBUG, "i40e_mirror_rule_reset: sw_id = %d.", sw_id); seid = pf->main_vsi->veb->seid; TAILQ_FOREACH(it, &pf->mirror_list, rules) { if (sw_id == it->index) { mirr_rule = it; break; } } if (mirr_rule) { ret = i40e_aq_del_mirror_rule(hw, seid, mirr_rule->rule_type, mirr_rule->entries, mirr_rule->num_entries, mirr_rule->id); if (ret < 0) { PMD_DRV_LOG(ERR, "failed to remove mirror rule:" " status = %d, aq_err = %d.", ret, hw->aq.asq_last_status); return -ENOSYS; } TAILQ_REMOVE(&pf->mirror_list, mirr_rule, rules); rte_free(mirr_rule); pf->nb_mirror_rule--; } else { PMD_DRV_LOG(ERR, "mirror rule doesn't exist."); return -ENOENT; } return 0; } static int i40e_timesync_enable(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_link *link = &dev->data->dev_link; uint32_t tsync_ctl_l; uint32_t tsync_ctl_h; uint32_t tsync_inc_l; uint32_t tsync_inc_h; switch (link->link_speed) { case ETH_LINK_SPEED_40G: tsync_inc_l = I40E_PTP_40GB_INCVAL & 0xFFFFFFFF; tsync_inc_h = I40E_PTP_40GB_INCVAL >> 32; break; case ETH_LINK_SPEED_10G: tsync_inc_l = I40E_PTP_10GB_INCVAL & 0xFFFFFFFF; tsync_inc_h = I40E_PTP_10GB_INCVAL >> 32; break; case ETH_LINK_SPEED_1000: tsync_inc_l = I40E_PTP_1GB_INCVAL & 0xFFFFFFFF; tsync_inc_h = I40E_PTP_1GB_INCVAL >> 32; break; default: tsync_inc_l = 0x0; tsync_inc_h = 0x0; } /* Clear timesync registers. */ I40E_READ_REG(hw, I40E_PRTTSYN_STAT_0); I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(0)); I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(1)); I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(2)); I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(3)); I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); /* Set the timesync increment value. */ I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_L, tsync_inc_l); I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_H, tsync_inc_h); /* Enable timestamping of PTP packets. */ tsync_ctl_l = I40E_READ_REG(hw, I40E_PRTTSYN_CTL0); tsync_ctl_l |= I40E_PRTTSYN_TSYNENA; tsync_ctl_h = I40E_READ_REG(hw, I40E_PRTTSYN_CTL1); tsync_ctl_h |= I40E_PRTTSYN_TSYNENA; tsync_ctl_h |= I40E_PRTTSYN_TSYNTYPE; I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL0, tsync_ctl_l); I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL1, tsync_ctl_h); return 0; } static int i40e_timesync_disable(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_ctl_l; uint32_t tsync_ctl_h; /* Disable timestamping of transmitted PTP packets. */ tsync_ctl_l = I40E_READ_REG(hw, I40E_PRTTSYN_CTL0); tsync_ctl_l &= ~I40E_PRTTSYN_TSYNENA; tsync_ctl_h = I40E_READ_REG(hw, I40E_PRTTSYN_CTL1); tsync_ctl_h &= ~I40E_PRTTSYN_TSYNENA; I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL0, tsync_ctl_l); I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL1, tsync_ctl_h); /* Set the timesync increment value. */ I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_L, 0x0); I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_H, 0x0); return 0; } static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t sync_status; uint32_t rx_stmpl; uint32_t rx_stmph; uint32_t index = flags & 0x03; sync_status = I40E_READ_REG(hw, I40E_PRTTSYN_STAT_1); if ((sync_status & (1 << index)) == 0) return -EINVAL; rx_stmpl = I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(index)); rx_stmph = I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_H(index)); timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); timestamp->tv_nsec = 0; return 0; } static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t sync_status; uint32_t tx_stmpl; uint32_t tx_stmph; sync_status = I40E_READ_REG(hw, I40E_PRTTSYN_STAT_0); if ((sync_status & I40E_PRTTSYN_STAT_0_TXTIME_MASK) == 0) return -EINVAL; tx_stmpl = I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_L); tx_stmph = I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); timestamp->tv_nsec = 0; return 0; } ================================================ FILE: drivers/net/i40e/i40e_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _I40E_ETHDEV_H_ #define _I40E_ETHDEV_H_ #include #define I40E_VLAN_TAG_SIZE 4 #define I40E_AQ_LEN 32 #define I40E_AQ_BUF_SZ 4096 /* Number of queues per TC should be one of 1, 2, 4, 8, 16, 32, 64 */ #define I40E_MAX_Q_PER_TC 64 #define I40E_NUM_DESC_DEFAULT 512 #define I40E_NUM_DESC_ALIGN 32 #define I40E_BUF_SIZE_MIN 1024 #define I40E_FRAME_SIZE_MAX 9728 #define I40E_QUEUE_BASE_ADDR_UNIT 128 /* number of VSIs and queue default setting */ #define I40E_MAX_QP_NUM_PER_VF 16 #define I40E_DEFAULT_QP_NUM_FDIR 1 #define I40E_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t)) #define I40E_VFTA_SIZE (4096 / I40E_UINT32_BIT_SIZE) /* * vlan_id is a 12 bit number. * The VFTA array is actually a 4096 bit array, 128 of 32bit elements. * 2^5 = 32. The val of lower 5 bits specifies the bit in the 32bit element. * The higher 7 bit val specifies VFTA array index. */ #define I40E_VFTA_BIT(vlan_id) (1 << ((vlan_id) & 0x1F)) #define I40E_VFTA_IDX(vlan_id) ((vlan_id) >> 5) /* Default TC traffic in case DCB is not enabled */ #define I40E_DEFAULT_TCMAP 0x1 #define I40E_FDIR_QUEUE_ID 0 /* Always assign pool 0 to main VSI, VMDQ will start from 1 */ #define I40E_VMDQ_POOL_BASE 1 #define I40E_DEFAULT_RX_FREE_THRESH 32 #define I40E_DEFAULT_RX_PTHRESH 8 #define I40E_DEFAULT_RX_HTHRESH 8 #define I40E_DEFAULT_RX_WTHRESH 0 #define I40E_DEFAULT_TX_FREE_THRESH 32 #define I40E_DEFAULT_TX_PTHRESH 32 #define I40E_DEFAULT_TX_HTHRESH 0 #define I40E_DEFAULT_TX_WTHRESH 0 #define I40E_DEFAULT_TX_RSBIT_THRESH 32 /* Bit shift and mask */ #define I40E_4_BIT_WIDTH (CHAR_BIT / 2) #define I40E_4_BIT_MASK RTE_LEN2MASK(I40E_4_BIT_WIDTH, uint8_t) #define I40E_8_BIT_WIDTH CHAR_BIT #define I40E_8_BIT_MASK UINT8_MAX #define I40E_16_BIT_WIDTH (CHAR_BIT * 2) #define I40E_16_BIT_MASK UINT16_MAX #define I40E_32_BIT_WIDTH (CHAR_BIT * 4) #define I40E_32_BIT_MASK UINT32_MAX #define I40E_48_BIT_WIDTH (CHAR_BIT * 6) #define I40E_48_BIT_MASK RTE_LEN2MASK(I40E_48_BIT_WIDTH, uint64_t) /* index flex payload per layer */ enum i40e_flxpld_layer_idx { I40E_FLXPLD_L2_IDX = 0, I40E_FLXPLD_L3_IDX = 1, I40E_FLXPLD_L4_IDX = 2, I40E_MAX_FLXPLD_LAYER = 3, }; #define I40E_MAX_FLXPLD_FIED 3 /* max number of flex payload fields */ #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) #define I40E_FLAG_DCB (1ULL << 1) #define I40E_FLAG_VMDQ (1ULL << 2) #define I40E_FLAG_SRIOV (1ULL << 3) #define I40E_FLAG_HEADER_SPLIT_DISABLED (1ULL << 4) #define I40E_FLAG_HEADER_SPLIT_ENABLED (1ULL << 5) #define I40E_FLAG_FDIR (1ULL << 6) #define I40E_FLAG_VXLAN (1ULL << 7) #define I40E_FLAG_ALL (I40E_FLAG_RSS | \ I40E_FLAG_DCB | \ I40E_FLAG_VMDQ | \ I40E_FLAG_SRIOV | \ I40E_FLAG_HEADER_SPLIT_DISABLED | \ I40E_FLAG_HEADER_SPLIT_ENABLED | \ I40E_FLAG_FDIR | \ I40E_FLAG_VXLAN) #define I40E_RSS_OFFLOAD_ALL ( \ ETH_RSS_FRAG_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_NONFRAG_IPV4_UDP | \ ETH_RSS_NONFRAG_IPV4_SCTP | \ ETH_RSS_NONFRAG_IPV4_OTHER | \ ETH_RSS_FRAG_IPV6 | \ ETH_RSS_NONFRAG_IPV6_TCP | \ ETH_RSS_NONFRAG_IPV6_UDP | \ ETH_RSS_NONFRAG_IPV6_SCTP | \ ETH_RSS_NONFRAG_IPV6_OTHER | \ ETH_RSS_L2_PAYLOAD) /* All bits of RSS hash enable */ #define I40E_RSS_HENA_ALL ( \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \ (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \ (1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6) | \ (1ULL << I40E_FILTER_PCTYPE_FCOE_OX) | \ (1ULL << I40E_FILTER_PCTYPE_FCOE_RX) | \ (1ULL << I40E_FILTER_PCTYPE_FCOE_OTHER) | \ (1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD)) struct i40e_adapter; /** * MAC filter structure */ struct i40e_mac_filter_info { enum rte_mac_filter_type filter_type; struct ether_addr mac_addr; }; TAILQ_HEAD(i40e_mac_filter_list, i40e_mac_filter); /* MAC filter list structure */ struct i40e_mac_filter { TAILQ_ENTRY(i40e_mac_filter) next; struct i40e_mac_filter_info mac_info; }; TAILQ_HEAD(i40e_vsi_list_head, i40e_vsi_list); struct i40e_vsi; /* VSI list structure */ struct i40e_vsi_list { TAILQ_ENTRY(i40e_vsi_list) list; struct i40e_vsi *vsi; }; struct i40e_rx_queue; struct i40e_tx_queue; /* Structure that defines a VEB */ struct i40e_veb { struct i40e_vsi_list_head head; struct i40e_vsi *associate_vsi; /* Associate VSI who owns the VEB */ uint16_t seid; /* The seid of VEB itself */ uint16_t uplink_seid; /* The uplink seid of this VEB */ uint16_t stats_idx; struct i40e_eth_stats stats; }; /* i40e MACVLAN filter structure */ struct i40e_macvlan_filter { struct ether_addr macaddr; enum rte_mac_filter_type filter_type; uint16_t vlan_id; }; /* * Structure that defines a VSI, associated with a adapter. */ struct i40e_vsi { struct i40e_adapter *adapter; /* Backreference to associated adapter */ struct i40e_aqc_vsi_properties_data info; /* VSI properties */ struct i40e_eth_stats eth_stats_offset; struct i40e_eth_stats eth_stats; /* * When drivers loaded, only a default main VSI exists. In case new VSI * needs to add, HW needs to know the layout that VSIs are organized. * Besides that, VSI isan element and can't switch packets, which needs * to add new component VEB to perform switching. So, a new VSI needs * to specify the the uplink VSI (Parent VSI) before created. The * uplink VSI will check whether it had a VEB to switch packets. If no, * it will try to create one. Then, uplink VSI will move the new VSI * into its' sib_vsi_list to manage all the downlink VSI. * sib_vsi_list: the VSI list that shared the same uplink VSI. * parent_vsi : the uplink VSI. It's NULL for main VSI. * veb : the VEB associates with the VSI. */ struct i40e_vsi_list sib_vsi_list; /* sibling vsi list */ struct i40e_vsi *parent_vsi; struct i40e_veb *veb; /* Associated veb, could be null */ bool offset_loaded; enum i40e_vsi_type type; /* VSI types */ uint16_t vlan_num; /* Total VLAN number */ uint16_t mac_num; /* Total mac number */ uint32_t vfta[I40E_VFTA_SIZE]; /* VLAN bitmap */ struct i40e_mac_filter_list mac_list; /* macvlan filter list */ /* specific VSI-defined parameters, SRIOV stored the vf_id */ uint32_t user_param; uint16_t seid; /* The seid of VSI itself */ uint16_t uplink_seid; /* The uplink seid of this VSI */ uint16_t nb_qps; /* Number of queue pairs VSI can occupy */ uint16_t max_macaddrs; /* Maximum number of MAC addresses */ uint16_t base_queue; /* The first queue index of this VSI */ /* * The offset to visit VSI related register, assigned by HW when * creating VSI */ uint16_t vsi_id; uint16_t msix_intr; /* The MSIX interrupt binds to VSI */ uint8_t enabled_tc; /* The traffic class enabled */ }; struct pool_entry { LIST_ENTRY(pool_entry) next; uint16_t base; uint16_t len; }; LIST_HEAD(res_list, pool_entry); struct i40e_res_pool_info { uint32_t base; /* Resource start index */ uint32_t num_alloc; /* Allocated resource number */ uint32_t num_free; /* Total available resource number */ struct res_list alloc_list; /* Allocated resource list */ struct res_list free_list; /* Available resource list */ }; enum I40E_VF_STATE { I40E_VF_INACTIVE = 0, I40E_VF_INRESET, I40E_VF_ININIT, I40E_VF_ACTIVE, }; /* * Structure to store private data for PF host. */ struct i40e_pf_vf { struct i40e_pf *pf; struct i40e_vsi *vsi; enum I40E_VF_STATE state; /* The number of queue pairs availiable */ uint16_t vf_idx; /* VF index in pf->vfs */ uint16_t lan_nb_qps; /* Actual queues allocated */ uint16_t reset_cnt; /* Total vf reset times */ }; /* * Structure to store private data for VMDQ instance */ struct i40e_vmdq_info { struct i40e_pf *pf; struct i40e_vsi *vsi; }; /* * Structure to store flex pit for flow diretor. */ struct i40e_fdir_flex_pit { uint8_t src_offset; /* offset in words from the beginning of payload */ uint8_t size; /* size in words */ uint8_t dst_offset; /* offset in words of flexible payload */ }; struct i40e_fdir_flex_mask { uint8_t word_mask; /**< Bit i enables word i of flexible payload */ struct { uint8_t offset; uint16_t mask; } bitmask[I40E_FDIR_BITMASK_NUM_WORD]; }; #define I40E_FILTER_PCTYPE_MAX 64 /* * A structure used to define fields of a FDIR related info. */ struct i40e_fdir_info { struct i40e_vsi *fdir_vsi; /* pointer to fdir VSI structure */ uint16_t match_counter_index; /* Statistic counter index used for fdir*/ struct i40e_tx_queue *txq; struct i40e_rx_queue *rxq; void *prg_pkt; /* memory for fdir program packet */ uint64_t dma_addr; /* physic address of packet memory*/ /* * the rule how bytes stream is extracted as flexible payload * for each payload layer, the setting can up to three elements */ struct i40e_fdir_flex_pit flex_set[I40E_MAX_FLXPLD_LAYER * I40E_MAX_FLXPLD_FIED]; struct i40e_fdir_flex_mask flex_mask[I40E_FILTER_PCTYPE_MAX]; }; #define I40E_MIRROR_MAX_ENTRIES_PER_RULE 64 #define I40E_MAX_MIRROR_RULES 64 /* * Mirror rule structure */ struct i40e_mirror_rule { TAILQ_ENTRY(i40e_mirror_rule) rules; uint8_t rule_type; uint16_t index; /* the sw index of mirror rule */ uint16_t id; /* the rule id assigned by firmware */ uint16_t dst_vsi_seid; /* destination vsi for this mirror rule. */ uint16_t num_entries; /* the info stores depend on the rule type. If type is I40E_MIRROR_TYPE_VLAN, vlan ids are stored here. If type is I40E_MIRROR_TYPE_VPORT_*, vsi's seid are stored. */ uint16_t entries[I40E_MIRROR_MAX_ENTRIES_PER_RULE]; }; TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule); /* * Structure to store private data specific for PF instance. */ struct i40e_pf { struct i40e_adapter *adapter; /* The adapter this PF associate to */ struct i40e_vsi *main_vsi; /* pointer to main VSI structure */ uint16_t mac_seid; /* The seid of the MAC of this PF */ uint16_t main_vsi_seid; /* The seid of the main VSI */ uint16_t max_num_vsi; struct i40e_res_pool_info qp_pool; /*Queue pair pool */ struct i40e_res_pool_info msix_pool; /* MSIX interrupt pool */ struct i40e_hw_port_stats stats_offset; struct i40e_hw_port_stats stats; bool offset_loaded; struct rte_eth_dev_data *dev_data; /* Pointer to the device data */ struct ether_addr dev_addr; /* PF device mac address */ uint64_t flags; /* PF featuer flags */ /* All kinds of queue pair setting for different VSIs */ struct i40e_pf_vf *vfs; uint16_t vf_num; /* Each of below queue pairs should be power of 2 since it's the precondition after TC configuration applied */ uint16_t lan_nb_qps; /* The number of queue pairs of LAN */ uint16_t vmdq_nb_qps; /* The number of queue pairs of VMDq */ uint16_t vf_nb_qps; /* The number of queue pairs of VF */ uint16_t fdir_nb_qps; /* The number of queue pairs of Flow Director */ uint16_t hash_lut_size; /* The size of hash lookup table */ /* store VXLAN UDP ports */ uint16_t vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS]; uint16_t vxlan_bitmap; /* Vxlan bit mask */ /* VMDQ related info */ uint16_t max_nb_vmdq_vsi; /* Max number of VMDQ VSIs supported */ uint16_t nb_cfg_vmdq_vsi; /* number of VMDQ VSIs configured */ struct i40e_vmdq_info *vmdq; struct i40e_fdir_info fdir; /* flow director info */ struct i40e_mirror_rule_list mirror_list; uint16_t nb_mirror_rule; /* The number of mirror rules */ }; enum pending_msg { PFMSG_LINK_CHANGE = 0x1, PFMSG_RESET_IMPENDING = 0x2, PFMSG_DRIVER_CLOSE = 0x4, }; struct i40e_vsi_vlan_pvid_info { uint16_t on; /* Enable or disable pvid */ union { uint16_t pvid; /* Valid in case 'on' is set to set pvid */ struct { /* Valid in case 'on' is cleared. 'tagged' will reject tagged packets, * while 'untagged' will reject untagged packets. */ uint8_t tagged; uint8_t untagged; } reject; } config; }; struct i40e_vf_rx_queues { uint64_t rx_dma_addr; uint32_t rx_ring_len; uint32_t buff_size; }; struct i40e_vf_tx_queues { uint64_t tx_dma_addr; uint32_t tx_ring_len; }; /* * Structure to store private data specific for VF instance. */ struct i40e_vf { struct i40e_adapter *adapter; /* The adapter this VF associate to */ struct rte_eth_dev_data *dev_data; /* Pointer to the device data */ uint16_t num_queue_pairs; uint16_t max_pkt_len; /* Maximum packet length */ bool promisc_unicast_enabled; bool promisc_multicast_enabled; uint32_t version_major; /* Major version number */ uint32_t version_minor; /* Minor version number */ uint16_t promisc_flags; /* Promiscuous setting */ uint32_t vlan[I40E_VFTA_SIZE]; /* VLAN bit map */ /* Event from pf */ bool dev_closed; bool link_up; bool vf_reset; volatile uint32_t pend_cmd; /* pending command not finished yet */ u16 pend_msg; /* flags indicates events from pf not handled yet */ /* VSI info */ struct i40e_virtchnl_vf_resource *vf_res; /* All VSIs */ struct i40e_virtchnl_vsi_resource *vsi_res; /* LAN VSI */ struct i40e_vsi vsi; }; /* * Structure to store private data for each PF/VF instance. */ struct i40e_adapter { /* Common for both PF and VF */ struct i40e_hw hw; struct rte_eth_dev *eth_dev; /* Specific for PF or VF */ union { struct i40e_pf pf; struct i40e_vf vf; }; }; int i40e_dev_switch_queues(struct i40e_pf *pf, bool on); int i40e_vsi_release(struct i40e_vsi *vsi); struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, enum i40e_vsi_type type, struct i40e_vsi *uplink_vsi, uint16_t user_param); int i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on); int i40e_switch_tx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on); int i40e_vsi_add_vlan(struct i40e_vsi *vsi, uint16_t vlan); int i40e_vsi_delete_vlan(struct i40e_vsi *vsi, uint16_t vlan); int i40e_vsi_add_mac(struct i40e_vsi *vsi, struct i40e_mac_filter_info *filter); int i40e_vsi_delete_mac(struct i40e_vsi *vsi, struct ether_addr *addr); void i40e_update_vsi_stats(struct i40e_vsi *vsi); void i40e_pf_disable_irq0(struct i40e_hw *hw); void i40e_pf_enable_irq0(struct i40e_hw *hw); int i40e_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete); void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi); void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi); int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi, struct i40e_vsi_vlan_pvid_info *info); int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on); uint64_t i40e_config_hena(uint64_t flags); uint64_t i40e_parse_hena(uint64_t flags); enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf); enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf); int i40e_fdir_setup(struct i40e_pf *pf); const struct rte_memzone *i40e_memzone_reserve(const char *name, uint32_t len, int socket_id); int i40e_fdir_configure(struct rte_eth_dev *dev); void i40e_fdir_teardown(struct i40e_pf *pf); enum i40e_filter_pctype i40e_flowtype_to_pctype(uint16_t flow_type); uint16_t i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype); int i40e_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); /* I40E_DEV_PRIVATE_TO */ #define I40E_DEV_PRIVATE_TO_PF(adapter) \ (&((struct i40e_adapter *)adapter)->pf) #define I40E_DEV_PRIVATE_TO_HW(adapter) \ (&((struct i40e_adapter *)adapter)->hw) #define I40E_DEV_PRIVATE_TO_ADAPTER(adapter) \ ((struct i40e_adapter *)adapter) /* I40EVF_DEV_PRIVATE_TO */ #define I40EVF_DEV_PRIVATE_TO_VF(adapter) \ (&((struct i40e_adapter *)adapter)->vf) static inline struct i40e_vsi * i40e_get_vsi_from_adapter(struct i40e_adapter *adapter) { struct i40e_hw *hw; if (!adapter) return NULL; hw = I40E_DEV_PRIVATE_TO_HW(adapter); if (hw->mac.type == I40E_MAC_VF) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(adapter); return &vf->vsi; } else { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(adapter); return pf->main_vsi; } } #define I40E_DEV_PRIVATE_TO_MAIN_VSI(adapter) \ i40e_get_vsi_from_adapter((struct i40e_adapter *)adapter) /* I40E_VSI_TO */ #define I40E_VSI_TO_HW(vsi) \ (&(((struct i40e_vsi *)vsi)->adapter->hw)) #define I40E_VSI_TO_PF(vsi) \ (&(((struct i40e_vsi *)vsi)->adapter->pf)) #define I40E_VSI_TO_DEV_DATA(vsi) \ (((struct i40e_vsi *)vsi)->adapter->pf.dev_data) #define I40E_VSI_TO_ETH_DEV(vsi) \ (((struct i40e_vsi *)vsi)->adapter->eth_dev) /* I40E_PF_TO */ #define I40E_PF_TO_HW(pf) \ (&(((struct i40e_pf *)pf)->adapter->hw)) #define I40E_PF_TO_ADAPTER(pf) \ ((struct i40e_adapter *)pf->adapter) /* I40E_VF_TO */ #define I40E_VF_TO_HW(vf) \ (&(((struct i40e_vf *)vf)->adapter->hw)) static inline void i40e_init_adminq_parameter(struct i40e_hw *hw) { hw->aq.num_arq_entries = I40E_AQ_LEN; hw->aq.num_asq_entries = I40E_AQ_LEN; hw->aq.arq_buf_size = I40E_AQ_BUF_SZ; hw->aq.asq_buf_size = I40E_AQ_BUF_SZ; } static inline int i40e_align_floor(int n) { if (n == 0) return 0; return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n)); } #define I40E_VALID_FLOW(flow_type) \ ((flow_type) == RTE_ETH_FLOW_FRAG_IPV4 || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_TCP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_UDP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_SCTP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV4_OTHER || \ (flow_type) == RTE_ETH_FLOW_FRAG_IPV6 || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_TCP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_UDP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_SCTP || \ (flow_type) == RTE_ETH_FLOW_NONFRAG_IPV6_OTHER || \ (flow_type) == RTE_ETH_FLOW_L2_PAYLOAD) #define I40E_VALID_PCTYPE(pctype) \ ((pctype) == I40E_FILTER_PCTYPE_FRAG_IPV4 || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_TCP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_UDP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER || \ (pctype) == I40E_FILTER_PCTYPE_FRAG_IPV6 || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_UDP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_TCP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP || \ (pctype) == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || \ (pctype) == I40E_FILTER_PCTYPE_L2_PAYLOAD) #endif /* _I40E_ETHDEV_H_ */ ================================================ FILE: drivers/net/i40e/i40e_ethdev_vf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i40e_logs.h" #include "base/i40e_prototype.h" #include "base/i40e_adminq_cmd.h" #include "base/i40e_type.h" #include "i40e_rxtx.h" #include "i40e_ethdev.h" #include "i40e_pf.h" #define I40EVF_VSI_DEFAULT_MSIX_INTR 1 /* busy wait delay in msec */ #define I40EVF_BUSY_WAIT_DELAY 10 #define I40EVF_BUSY_WAIT_COUNT 50 #define MAX_RESET_WAIT_CNT 20 struct i40evf_arq_msg_info { enum i40e_virtchnl_ops ops; enum i40e_status_code result; uint16_t buf_len; uint16_t msg_len; uint8_t *msg; }; struct vf_cmd_info { enum i40e_virtchnl_ops ops; uint8_t *in_args; uint32_t in_args_size; uint8_t *out_buffer; /* Input & output type. pass in buffer size and pass out * actual return result */ uint32_t out_size; }; enum i40evf_aq_result { I40EVF_MSG_ERR = -1, /* Meet error when accessing admin queue */ I40EVF_MSG_NON, /* Read nothing from admin queue */ I40EVF_MSG_SYS, /* Read system msg from admin queue */ I40EVF_MSG_CMD, /* Read async command result */ }; /* A share buffer to store the command result from PF driver */ static uint8_t cmd_result_buffer[I40E_AQ_BUF_SZ]; static int i40evf_dev_configure(struct rte_eth_dev *dev); static int i40evf_dev_start(struct rte_eth_dev *dev); static void i40evf_dev_stop(struct rte_eth_dev *dev); static void i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int i40evf_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete); static void i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int i40evf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask); static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on); static void i40evf_dev_close(struct rte_eth_dev *dev); static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev); static void i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev); static void i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev); static void i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev); static int i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link); static int i40evf_init_vlan(struct rte_eth_dev *dev); static int i40evf_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id); static int i40evf_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id); static int i40evf_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id); static int i40evf_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id); static int i40evf_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int i40evf_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int i40evf_config_rss(struct i40e_vf *vf); static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); /* Default hash key buffer for RSS */ static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1]; static const struct eth_dev_ops i40evf_eth_dev_ops = { .dev_configure = i40evf_dev_configure, .dev_start = i40evf_dev_start, .dev_stop = i40evf_dev_stop, .promiscuous_enable = i40evf_dev_promiscuous_enable, .promiscuous_disable = i40evf_dev_promiscuous_disable, .allmulticast_enable = i40evf_dev_allmulticast_enable, .allmulticast_disable = i40evf_dev_allmulticast_disable, .link_update = i40evf_dev_link_update, .stats_get = i40evf_dev_stats_get, .dev_close = i40evf_dev_close, .dev_infos_get = i40evf_dev_info_get, .vlan_filter_set = i40evf_vlan_filter_set, .vlan_offload_set = i40evf_vlan_offload_set, .vlan_pvid_set = i40evf_vlan_pvid_set, .rx_queue_start = i40evf_dev_rx_queue_start, .rx_queue_stop = i40evf_dev_rx_queue_stop, .tx_queue_start = i40evf_dev_tx_queue_start, .tx_queue_stop = i40evf_dev_tx_queue_stop, .rx_queue_setup = i40e_dev_rx_queue_setup, .rx_queue_release = i40e_dev_rx_queue_release, .tx_queue_setup = i40e_dev_tx_queue_setup, .tx_queue_release = i40e_dev_tx_queue_release, .reta_update = i40evf_dev_rss_reta_update, .reta_query = i40evf_dev_rss_reta_query, .rss_hash_update = i40evf_dev_rss_hash_update, .rss_hash_conf_get = i40evf_dev_rss_hash_conf_get, }; static int i40evf_set_mac_type(struct i40e_hw *hw) { int status = I40E_ERR_DEVICE_NOT_SUPPORTED; if (hw->vendor_id == I40E_INTEL_VENDOR_ID) { switch (hw->device_id) { case I40E_DEV_ID_VF: case I40E_DEV_ID_VF_HV: hw->mac.type = I40E_MAC_VF; status = I40E_SUCCESS; break; default: ; } } return status; } /* * Parse admin queue message. * * return value: * < 0: meet error * 0: read sys msg * > 0: read cmd result */ static enum i40evf_aq_result i40evf_parse_pfmsg(struct i40e_vf *vf, struct i40e_arq_event_info *event, struct i40evf_arq_msg_info *data) { enum i40e_virtchnl_ops opcode = (enum i40e_virtchnl_ops)\ rte_le_to_cpu_32(event->desc.cookie_high); enum i40e_status_code retval = (enum i40e_status_code)\ rte_le_to_cpu_32(event->desc.cookie_low); enum i40evf_aq_result ret = I40EVF_MSG_CMD; /* pf sys event */ if (opcode == I40E_VIRTCHNL_OP_EVENT) { struct i40e_virtchnl_pf_event *vpe = (struct i40e_virtchnl_pf_event *)event->msg_buf; /* Initialize ret to sys event */ ret = I40EVF_MSG_SYS; switch (vpe->event) { case I40E_VIRTCHNL_EVENT_LINK_CHANGE: vf->link_up = vpe->event_data.link_event.link_status; vf->pend_msg |= PFMSG_LINK_CHANGE; PMD_DRV_LOG(INFO, "Link status update:%s", vf->link_up ? "up" : "down"); break; case I40E_VIRTCHNL_EVENT_RESET_IMPENDING: vf->vf_reset = true; vf->pend_msg |= PFMSG_RESET_IMPENDING; PMD_DRV_LOG(INFO, "vf is reseting"); break; case I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE: vf->dev_closed = true; vf->pend_msg |= PFMSG_DRIVER_CLOSE; PMD_DRV_LOG(INFO, "PF driver closed"); break; default: PMD_DRV_LOG(ERR, "%s: Unknown event %d from pf", __func__, vpe->event); } } else { /* async reply msg on command issued by vf previously */ ret = I40EVF_MSG_CMD; /* Actual data length read from PF */ data->msg_len = event->msg_len; } /* fill the ops and result to notify VF */ data->result = retval; data->ops = opcode; return ret; } /* * Read data in admin queue to get msg from pf driver */ static enum i40evf_aq_result i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_arq_event_info event; int ret; enum i40evf_aq_result result = I40EVF_MSG_NON; event.buf_len = data->buf_len; event.msg_buf = data->msg; ret = i40e_clean_arq_element(hw, &event, NULL); /* Can't read any msg from adminQ */ if (ret) { if (ret == I40E_ERR_ADMIN_QUEUE_NO_WORK) result = I40EVF_MSG_NON; else result = I40EVF_MSG_ERR; return result; } /* Parse the event */ result = i40evf_parse_pfmsg(vf, &event, data); return result; } /* * Polling read until command result return from pf driver or meet error. */ static int i40evf_wait_cmd_done(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data) { int i = 0; enum i40evf_aq_result ret; #define MAX_TRY_TIMES 20 #define ASQ_DELAY_MS 100 do { /* Delay some time first */ rte_delay_ms(ASQ_DELAY_MS); ret = i40evf_read_pfmsg(dev, data); if (ret == I40EVF_MSG_CMD) return 0; else if (ret == I40EVF_MSG_ERR) return -1; /* If don't read msg or read sys event, continue */ } while(i++ < MAX_TRY_TIMES); return -1; } /** * clear current command. Only call in case execute * _atomic_set_cmd successfully. */ static inline void _clear_cmd(struct i40e_vf *vf) { rte_wmb(); vf->pend_cmd = I40E_VIRTCHNL_OP_UNKNOWN; } /* * Check there is pending cmd in execution. If none, set new command. */ static inline int _atomic_set_cmd(struct i40e_vf *vf, enum i40e_virtchnl_ops ops) { int ret = rte_atomic32_cmpset(&vf->pend_cmd, I40E_VIRTCHNL_OP_UNKNOWN, ops); if (!ret) PMD_DRV_LOG(ERR, "There is incomplete cmd %d", vf->pend_cmd); return !ret; } static int i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err = -1; struct i40evf_arq_msg_info info; if (_atomic_set_cmd(vf, args->ops)) return -1; info.msg = args->out_buffer; info.buf_len = args->out_size; info.ops = I40E_VIRTCHNL_OP_UNKNOWN; info.result = I40E_SUCCESS; err = i40e_aq_send_msg_to_pf(hw, args->ops, I40E_SUCCESS, args->in_args, args->in_args_size, NULL); if (err) { PMD_DRV_LOG(ERR, "fail to send cmd %d", args->ops); _clear_cmd(vf); return err; } err = i40evf_wait_cmd_done(dev, &info); /* read message and it's expected one */ if (!err && args->ops == info.ops) _clear_cmd(vf); else if (err) { PMD_DRV_LOG(ERR, "Failed to read message from AdminQ"); _clear_cmd(vf); } else if (args->ops != info.ops) PMD_DRV_LOG(ERR, "command mismatch, expect %u, get %u", args->ops, info.ops); return (err | info.result); } /* * Check API version with sync wait until version read or fail from admin queue */ static int i40evf_check_api_version(struct rte_eth_dev *dev) { struct i40e_virtchnl_version_info version, *pver; int err; struct vf_cmd_info args; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); version.major = I40E_VIRTCHNL_VERSION_MAJOR; version.minor = I40E_VIRTCHNL_VERSION_MINOR; args.ops = I40E_VIRTCHNL_OP_VERSION; args.in_args = (uint8_t *)&version; args.in_args_size = sizeof(version); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { PMD_INIT_LOG(ERR, "fail to execute command OP_VERSION"); return err; } pver = (struct i40e_virtchnl_version_info *)args.out_buffer; vf->version_major = pver->major; vf->version_minor = pver->minor; if (vf->version_major == I40E_DPDK_VERSION_MAJOR) PMD_DRV_LOG(INFO, "Peer is DPDK PF host"); else if ((vf->version_major == I40E_VIRTCHNL_VERSION_MAJOR) && (vf->version_minor == I40E_VIRTCHNL_VERSION_MINOR)) PMD_DRV_LOG(INFO, "Peer is Linux PF host"); else { PMD_INIT_LOG(ERR, "PF/VF API version mismatch:(%u.%u)-(%u.%u)", vf->version_major, vf->version_minor, I40E_VIRTCHNL_VERSION_MAJOR, I40E_VIRTCHNL_VERSION_MINOR); return -1; } return 0; } static int i40evf_get_vf_resource(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; uint32_t len; args.ops = I40E_VIRTCHNL_OP_GET_VF_RESOURCES; args.in_args = NULL; args.in_args_size = 0; args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { PMD_DRV_LOG(ERR, "fail to execute command OP_GET_VF_RESOURCE"); return err; } len = sizeof(struct i40e_virtchnl_vf_resource) + I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource); (void)rte_memcpy(vf->vf_res, args.out_buffer, RTE_MIN(args.out_size, len)); i40e_vf_parse_hw_config(hw, vf->vf_res); return 0; } static int i40evf_config_promisc(struct rte_eth_dev *dev, bool enable_unicast, bool enable_multicast) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; struct i40e_virtchnl_promisc_info promisc; promisc.flags = 0; promisc.vsi_id = vf->vsi_res->vsi_id; if (enable_unicast) promisc.flags |= I40E_FLAG_VF_UNICAST_PROMISC; if (enable_multicast) promisc.flags |= I40E_FLAG_VF_MULTICAST_PROMISC; args.ops = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE; args.in_args = (uint8_t *)&promisc; args.in_args_size = sizeof(promisc); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command " "CONFIG_PROMISCUOUS_MODE"); return err; } /* Configure vlan and double vlan offload. Use flag to specify which part to configure */ static int i40evf_config_vlan_offload(struct rte_eth_dev *dev, bool enable_vlan_strip) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; struct i40e_virtchnl_vlan_offload_info offload; offload.vsi_id = vf->vsi_res->vsi_id; offload.enable_vlan_strip = enable_vlan_strip; args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD; args.in_args = (uint8_t *)&offload; args.in_args_size = sizeof(offload); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command CFG_VLAN_OFFLOAD"); return err; } static int i40evf_config_vlan_pvid(struct rte_eth_dev *dev, struct i40e_vsi_vlan_pvid_info *info) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int err; struct vf_cmd_info args; struct i40e_virtchnl_pvid_info tpid_info; if (dev == NULL || info == NULL) { PMD_DRV_LOG(ERR, "invalid parameters"); return I40E_ERR_PARAM; } memset(&tpid_info, 0, sizeof(tpid_info)); tpid_info.vsi_id = vf->vsi_res->vsi_id; (void)rte_memcpy(&tpid_info.info, info, sizeof(*info)); args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CFG_VLAN_PVID; args.in_args = (uint8_t *)&tpid_info; args.in_args_size = sizeof(tpid_info); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command CFG_VLAN_PVID"); return err; } static void i40evf_fill_virtchnl_vsi_txq_info(struct i40e_virtchnl_txq_info *txq_info, uint16_t vsi_id, uint16_t queue_id, uint16_t nb_txq, struct i40e_tx_queue *txq) { txq_info->vsi_id = vsi_id; txq_info->queue_id = queue_id; if (queue_id < nb_txq) { txq_info->ring_len = txq->nb_tx_desc; txq_info->dma_ring_addr = txq->tx_ring_phys_addr; } } static void i40evf_fill_virtchnl_vsi_rxq_info(struct i40e_virtchnl_rxq_info *rxq_info, uint16_t vsi_id, uint16_t queue_id, uint16_t nb_rxq, uint32_t max_pkt_size, struct i40e_rx_queue *rxq) { rxq_info->vsi_id = vsi_id; rxq_info->queue_id = queue_id; rxq_info->max_pkt_size = max_pkt_size; if (queue_id < nb_rxq) { rxq_info->ring_len = rxq->nb_rx_desc; rxq_info->dma_ring_addr = rxq->rx_ring_phys_addr; rxq_info->databuffer_size = (rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM); } } /* It configures VSI queues to co-work with Linux PF host */ static int i40evf_configure_vsi_queues(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_rx_queue **rxq = (struct i40e_rx_queue **)dev->data->rx_queues; struct i40e_tx_queue **txq = (struct i40e_tx_queue **)dev->data->tx_queues; struct i40e_virtchnl_vsi_queue_config_info *vc_vqci; struct i40e_virtchnl_queue_pair_info *vc_qpi; struct vf_cmd_info args; uint16_t i, nb_qp = vf->num_queue_pairs; const uint32_t size = I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci, nb_qp); uint8_t buff[size]; int ret; memset(buff, 0, sizeof(buff)); vc_vqci = (struct i40e_virtchnl_vsi_queue_config_info *)buff; vc_vqci->vsi_id = vf->vsi_res->vsi_id; vc_vqci->num_queue_pairs = nb_qp; for (i = 0, vc_qpi = vc_vqci->qpair; i < nb_qp; i++, vc_qpi++) { i40evf_fill_virtchnl_vsi_txq_info(&vc_qpi->txq, vc_vqci->vsi_id, i, dev->data->nb_tx_queues, txq[i]); i40evf_fill_virtchnl_vsi_rxq_info(&vc_qpi->rxq, vc_vqci->vsi_id, i, dev->data->nb_rx_queues, vf->max_pkt_len, rxq[i]); } memset(&args, 0, sizeof(args)); args.ops = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES; args.in_args = (uint8_t *)vc_vqci; args.in_args_size = size; args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) PMD_DRV_LOG(ERR, "Failed to execute command of " "I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES\n"); return ret; } /* It configures VSI queues to co-work with DPDK PF host */ static int i40evf_configure_vsi_queues_ext(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_rx_queue **rxq = (struct i40e_rx_queue **)dev->data->rx_queues; struct i40e_tx_queue **txq = (struct i40e_tx_queue **)dev->data->tx_queues; struct i40e_virtchnl_vsi_queue_config_ext_info *vc_vqcei; struct i40e_virtchnl_queue_pair_ext_info *vc_qpei; struct vf_cmd_info args; uint16_t i, nb_qp = vf->num_queue_pairs; const uint32_t size = I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei, nb_qp); uint8_t buff[size]; int ret; memset(buff, 0, sizeof(buff)); vc_vqcei = (struct i40e_virtchnl_vsi_queue_config_ext_info *)buff; vc_vqcei->vsi_id = vf->vsi_res->vsi_id; vc_vqcei->num_queue_pairs = nb_qp; vc_qpei = vc_vqcei->qpair; for (i = 0; i < nb_qp; i++, vc_qpei++) { i40evf_fill_virtchnl_vsi_txq_info(&vc_qpei->txq, vc_vqcei->vsi_id, i, dev->data->nb_tx_queues, txq[i]); i40evf_fill_virtchnl_vsi_rxq_info(&vc_qpei->rxq, vc_vqcei->vsi_id, i, dev->data->nb_rx_queues, vf->max_pkt_len, rxq[i]); if (i < dev->data->nb_rx_queues) /* * It adds extra info for configuring VSI queues, which * is needed to enable the configurable crc stripping * in VF. */ vc_qpei->rxq_ext.crcstrip = dev->data->dev_conf.rxmode.hw_strip_crc; } memset(&args, 0, sizeof(args)); args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT; args.in_args = (uint8_t *)vc_vqcei; args.in_args_size = size; args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; ret = i40evf_execute_vf_cmd(dev, &args); if (ret) PMD_DRV_LOG(ERR, "Failed to execute command of " "I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT\n"); return ret; } static int i40evf_configure_queues(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); if (vf->version_major == I40E_DPDK_VERSION_MAJOR) /* To support DPDK PF host */ return i40evf_configure_vsi_queues_ext(dev); else /* To support Linux PF host */ return i40evf_configure_vsi_queues(dev); } static int i40evf_config_irq_map(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct vf_cmd_info args; uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_irq_map_info) + \ sizeof(struct i40e_virtchnl_vector_map)]; struct i40e_virtchnl_irq_map_info *map_info; int i, err; map_info = (struct i40e_virtchnl_irq_map_info *)cmd_buffer; map_info->num_vectors = 1; map_info->vecmap[0].rxitr_idx = RTE_LIBRTE_I40E_ITR_INTERVAL / 2; map_info->vecmap[0].txitr_idx = RTE_LIBRTE_I40E_ITR_INTERVAL / 2; map_info->vecmap[0].vsi_id = vf->vsi_res->vsi_id; /* Alway use default dynamic MSIX interrupt */ map_info->vecmap[0].vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR; /* Don't map any tx queue */ map_info->vecmap[0].txq_map = 0; map_info->vecmap[0].rxq_map = 0; for (i = 0; i < dev->data->nb_rx_queues; i++) map_info->vecmap[0].rxq_map |= 1 << i; args.ops = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP; args.in_args = (u8 *)cmd_buffer; args.in_args_size = sizeof(cmd_buffer); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command OP_ENABLE_QUEUES"); return err; } static int i40evf_switch_queue(struct rte_eth_dev *dev, bool isrx, uint16_t qid, bool on) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_virtchnl_queue_select queue_select; int err; struct vf_cmd_info args; memset(&queue_select, 0, sizeof(queue_select)); queue_select.vsi_id = vf->vsi_res->vsi_id; if (isrx) queue_select.rx_queues |= 1 << qid; else queue_select.tx_queues |= 1 << qid; if (on) args.ops = I40E_VIRTCHNL_OP_ENABLE_QUEUES; else args.ops = I40E_VIRTCHNL_OP_DISABLE_QUEUES; args.in_args = (u8 *)&queue_select; args.in_args_size = sizeof(queue_select); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to switch %s %u %s", isrx ? "RX" : "TX", qid, on ? "on" : "off"); return err; } static int i40evf_start_queues(struct rte_eth_dev *dev) { struct rte_eth_dev_data *dev_data = dev->data; int i; struct i40e_rx_queue *rxq; struct i40e_tx_queue *txq; for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev_data->rx_queues[i]; if (rxq->rx_deferred_start) continue; if (i40evf_dev_rx_queue_start(dev, i) != 0) { PMD_DRV_LOG(ERR, "Fail to start queue %u", i); return -1; } } for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev_data->tx_queues[i]; if (txq->tx_deferred_start) continue; if (i40evf_dev_tx_queue_start(dev, i) != 0) { PMD_DRV_LOG(ERR, "Fail to start queue %u", i); return -1; } } return 0; } static int i40evf_stop_queues(struct rte_eth_dev *dev) { int i; /* Stop TX queues first */ for (i = 0; i < dev->data->nb_tx_queues; i++) { if (i40evf_dev_tx_queue_stop(dev, i) != 0) { PMD_DRV_LOG(ERR, "Fail to stop queue %u", i); return -1; } } /* Then stop RX queues */ for (i = 0; i < dev->data->nb_rx_queues; i++) { if (i40evf_dev_rx_queue_stop(dev, i) != 0) { PMD_DRV_LOG(ERR, "Fail to stop queue %u", i); return -1; } } return 0; } static int i40evf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) { struct i40e_virtchnl_ether_addr_list *list; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_ether_addr_list) + \ sizeof(struct i40e_virtchnl_ether_addr)]; int err; struct vf_cmd_info args; if (i40e_validate_mac_addr(addr->addr_bytes) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Invalid mac:%x:%x:%x:%x:%x:%x", addr->addr_bytes[0], addr->addr_bytes[1], addr->addr_bytes[2], addr->addr_bytes[3], addr->addr_bytes[4], addr->addr_bytes[5]); return -1; } list = (struct i40e_virtchnl_ether_addr_list *)cmd_buffer; list->vsi_id = vf->vsi_res->vsi_id; list->num_elements = 1; (void)rte_memcpy(list->list[0].addr, addr->addr_bytes, sizeof(addr->addr_bytes)); args.ops = I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command " "OP_ADD_ETHER_ADDRESS"); return err; } static int i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) { struct i40e_virtchnl_ether_addr_list *list; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_ether_addr_list) + \ sizeof(struct i40e_virtchnl_ether_addr)]; int err; struct vf_cmd_info args; if (i40e_validate_mac_addr(addr->addr_bytes) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Invalid mac:%x-%x-%x-%x-%x-%x", addr->addr_bytes[0], addr->addr_bytes[1], addr->addr_bytes[2], addr->addr_bytes[3], addr->addr_bytes[4], addr->addr_bytes[5]); return -1; } list = (struct i40e_virtchnl_ether_addr_list *)cmd_buffer; list->vsi_id = vf->vsi_res->vsi_id; list->num_elements = 1; (void)rte_memcpy(list->list[0].addr, addr->addr_bytes, sizeof(addr->addr_bytes)); args.ops = I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS; args.in_args = cmd_buffer; args.in_args_size = sizeof(cmd_buffer); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command " "OP_DEL_ETHER_ADDRESS"); return err; } static int i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_virtchnl_queue_select q_stats; struct i40e_eth_stats *pstats; int err; struct vf_cmd_info args; memset(&q_stats, 0, sizeof(q_stats)); q_stats.vsi_id = vf->vsi_res->vsi_id; args.ops = I40E_VIRTCHNL_OP_GET_STATS; args.in_args = (u8 *)&q_stats; args.in_args_size = sizeof(q_stats); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS"); return err; } pstats = (struct i40e_eth_stats *)args.out_buffer; stats->ipackets = pstats->rx_unicast + pstats->rx_multicast + pstats->rx_broadcast; stats->opackets = pstats->tx_broadcast + pstats->tx_multicast + pstats->tx_unicast; stats->ierrors = pstats->rx_discards; stats->oerrors = pstats->tx_errors + pstats->tx_discards; stats->ibytes = pstats->rx_bytes; stats->obytes = pstats->tx_bytes; return 0; } static int i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_virtchnl_vlan_filter_list *vlan_list; uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_vlan_filter_list) + sizeof(uint16_t)]; int err; struct vf_cmd_info args; vlan_list = (struct i40e_virtchnl_vlan_filter_list *)cmd_buffer; vlan_list->vsi_id = vf->vsi_res->vsi_id; vlan_list->num_elements = 1; vlan_list->vlan_id[0] = vlanid; args.ops = I40E_VIRTCHNL_OP_ADD_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command OP_ADD_VLAN"); return err; } static int i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_virtchnl_vlan_filter_list *vlan_list; uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_vlan_filter_list) + sizeof(uint16_t)]; int err; struct vf_cmd_info args; vlan_list = (struct i40e_virtchnl_vlan_filter_list *)cmd_buffer; vlan_list->vsi_id = vf->vsi_res->vsi_id; vlan_list->num_elements = 1; vlan_list->vlan_id[0] = vlanid; args.ops = I40E_VIRTCHNL_OP_DEL_VLAN; args.in_args = (u8 *)&cmd_buffer; args.in_args_size = sizeof(cmd_buffer); args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) PMD_DRV_LOG(ERR, "fail to execute command OP_DEL_VLAN"); return err; } static int i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { int err; struct vf_cmd_info args; struct rte_eth_link *new_link; args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_GET_LINK_STAT; args.in_args = NULL; args.in_args_size = 0; args.out_buffer = cmd_result_buffer; args.out_size = I40E_AQ_BUF_SZ; err = i40evf_execute_vf_cmd(dev, &args); if (err) { PMD_DRV_LOG(ERR, "fail to execute command OP_GET_LINK_STAT"); return err; } new_link = (struct rte_eth_link *)args.out_buffer; (void)rte_memcpy(link, new_link, sizeof(*link)); return 0; } static const struct rte_pci_id pci_id_i40evf_map[] = { #define RTE_PCI_DEV_ID_DECL_I40EVF(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static inline int i40evf_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static int i40evf_reset_vf(struct i40e_hw *hw) { int i, reset; if (i40e_vf_reset(hw) != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "Reset VF NIC failed"); return -1; } /** * After issuing vf reset command to pf, pf won't necessarily * reset vf, it depends on what state it exactly is. If it's not * initialized yet, it won't have vf reset since it's in a certain * state. If not, it will try to reset. Even vf is reset, pf will * set I40E_VFGEN_RSTAT to COMPLETE first, then wait 10ms and set * it to ACTIVE. In this duration, vf may not catch the moment that * COMPLETE is set. So, for vf, we'll try to wait a long time. */ rte_delay_ms(200); for (i = 0; i < MAX_RESET_WAIT_CNT; i++) { reset = rd32(hw, I40E_VFGEN_RSTAT) & I40E_VFGEN_RSTAT_VFR_STATE_MASK; reset = reset >> I40E_VFGEN_RSTAT_VFR_STATE_SHIFT; if (I40E_VFR_COMPLETED == reset || I40E_VFR_VFACTIVE == reset) break; else rte_delay_ms(50); } if (i >= MAX_RESET_WAIT_CNT) { PMD_INIT_LOG(ERR, "Reset VF NIC failed"); return -1; } return 0; } static int i40evf_init_vf(struct rte_eth_dev *dev) { int i, err, bufsz; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); vf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); vf->dev_data = dev->data; err = i40evf_set_mac_type(hw); if (err) { PMD_INIT_LOG(ERR, "set_mac_type failed: %d", err); goto err; } i40e_init_adminq_parameter(hw); err = i40e_init_adminq(hw); if (err) { PMD_INIT_LOG(ERR, "init_adminq failed: %d", err); goto err; } /* Reset VF and wait until it's complete */ if (i40evf_reset_vf(hw)) { PMD_INIT_LOG(ERR, "reset NIC failed"); goto err_aq; } /* VF reset, shutdown admin queue and initialize again */ if (i40e_shutdown_adminq(hw) != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "i40e_shutdown_adminq failed"); return -1; } i40e_init_adminq_parameter(hw); if (i40e_init_adminq(hw) != I40E_SUCCESS) { PMD_INIT_LOG(ERR, "init_adminq failed"); return -1; } if (i40evf_check_api_version(dev) != 0) { PMD_INIT_LOG(ERR, "check_api version failed"); goto err_aq; } bufsz = sizeof(struct i40e_virtchnl_vf_resource) + (I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource)); vf->vf_res = rte_zmalloc("vf_res", bufsz, 0); if (!vf->vf_res) { PMD_INIT_LOG(ERR, "unable to allocate vf_res memory"); goto err_aq; } if (i40evf_get_vf_resource(dev) != 0) { PMD_INIT_LOG(ERR, "i40evf_get_vf_config failed"); goto err_alloc; } /* got VF config message back from PF, now we can parse it */ for (i = 0; i < vf->vf_res->num_vsis; i++) { if (vf->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV) vf->vsi_res = &vf->vf_res->vsi_res[i]; } if (!vf->vsi_res) { PMD_INIT_LOG(ERR, "no LAN VSI found"); goto err_alloc; } vf->vsi.vsi_id = vf->vsi_res->vsi_id; vf->vsi.type = vf->vsi_res->vsi_type; vf->vsi.nb_qps = vf->vsi_res->num_queue_pairs; /* check mac addr, if it's not valid, genrate one */ if (I40E_SUCCESS != i40e_validate_mac_addr(\ vf->vsi_res->default_mac_addr)) eth_random_addr(vf->vsi_res->default_mac_addr); ether_addr_copy((struct ether_addr *)vf->vsi_res->default_mac_addr, (struct ether_addr *)hw->mac.addr); return 0; err_alloc: rte_free(vf->vf_res); err_aq: i40e_shutdown_adminq(hw); /* ignore error */ err: return -1; } static int i40evf_uninit_vf(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (hw->adapter_stopped == 0) i40evf_dev_close(dev); rte_free(vf->vf_res); vf->vf_res = NULL; return 0; } static int i40evf_dev_init(struct rte_eth_dev *eth_dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(\ eth_dev->data->dev_private); PMD_INIT_FUNC_TRACE(); /* assign ops func pointer */ eth_dev->dev_ops = &i40evf_eth_dev_ops; eth_dev->rx_pkt_burst = &i40e_recv_pkts; eth_dev->tx_pkt_burst = &i40e_xmit_pkts; /* * For secondary processes, we don't initialise any further as primary * has already done this work. */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (eth_dev->data->scattered_rx) eth_dev->rx_pkt_burst = i40e_recv_scattered_pkts; return 0; } hw->vendor_id = eth_dev->pci_dev->id.vendor_id; hw->device_id = eth_dev->pci_dev->id.device_id; hw->subsystem_vendor_id = eth_dev->pci_dev->id.subsystem_vendor_id; hw->subsystem_device_id = eth_dev->pci_dev->id.subsystem_device_id; hw->bus.device = eth_dev->pci_dev->addr.devid; hw->bus.func = eth_dev->pci_dev->addr.function; hw->hw_addr = (void *)eth_dev->pci_dev->mem_resource[0].addr; hw->adapter_stopped = 0; if(i40evf_init_vf(eth_dev) != 0) { PMD_INIT_LOG(ERR, "Init vf failed"); return -1; } /* copy mac addr */ eth_dev->data->mac_addrs = rte_zmalloc("i40evf_mac", ETHER_ADDR_LEN, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to " "store MAC addresses", ETHER_ADDR_LEN); return -ENOMEM; } ether_addr_copy((struct ether_addr *)hw->mac.addr, (struct ether_addr *)eth_dev->data->mac_addrs); return 0; } static int i40evf_dev_uninit(struct rte_eth_dev *eth_dev) { PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; if (i40evf_uninit_vf(eth_dev) != 0) { PMD_INIT_LOG(ERR, "i40evf_uninit_vf failed"); return -1; } rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; return 0; } /* * virtual function driver struct */ static struct eth_driver rte_i40evf_pmd = { .pci_drv = { .name = "rte_i40evf_pmd", .id_table = pci_id_i40evf_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = i40evf_dev_init, .eth_dev_uninit = i40evf_dev_uninit, .dev_private_size = sizeof(struct i40e_adapter), }; /* * VF Driver initialization routine. * Invoked one at EAL init time. * Register itself as the [Virtual Poll Mode] Driver of PCI Fortville devices. */ static int rte_i40evf_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_i40evf_pmd); return 0; } static struct rte_driver rte_i40evf_driver = { .type = PMD_PDEV, .init = rte_i40evf_pmd_init, }; PMD_REGISTER_DRIVER(rte_i40evf_driver); static int i40evf_dev_configure(struct rte_eth_dev *dev) { return i40evf_init_vlan(dev); } static int i40evf_init_vlan(struct rte_eth_dev *dev) { struct rte_eth_dev_data *data = dev->data; int ret; /* Apply vlan offload setting */ i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK); /* Apply pvid setting */ ret = i40evf_vlan_pvid_set(dev, data->dev_conf.txmode.pvid, data->dev_conf.txmode.hw_vlan_insert_pvid); return ret; } static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask) { bool enable_vlan_strip = 0; struct rte_eth_conf *dev_conf = &dev->data->dev_conf; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); /* Linux pf host doesn't support vlan offload yet */ if (vf->version_major == I40E_DPDK_VERSION_MAJOR) { /* Vlan stripping setting */ if (mask & ETH_VLAN_STRIP_MASK) { /* Enable or disable VLAN stripping */ if (dev_conf->rxmode.hw_vlan_strip) enable_vlan_strip = 1; else enable_vlan_strip = 0; i40evf_config_vlan_offload(dev, enable_vlan_strip); } } } static int i40evf_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on) { struct rte_eth_conf *dev_conf = &dev->data->dev_conf; struct i40e_vsi_vlan_pvid_info info; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); memset(&info, 0, sizeof(info)); info.on = on; /* Linux pf host don't support vlan offload yet */ if (vf->version_major == I40E_DPDK_VERSION_MAJOR) { if (info.on) info.config.pvid = pvid; else { info.config.reject.tagged = dev_conf->txmode.hw_vlan_reject_tagged; info.config.reject.untagged = dev_conf->txmode.hw_vlan_reject_untagged; } return i40evf_config_vlan_pvid(dev, &info); } return 0; } static int i40evf_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct i40e_rx_queue *rxq; int err = 0; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; err = i40e_alloc_rx_queue_mbufs(rxq); if (err) { PMD_DRV_LOG(ERR, "Failed to allocate RX queue mbuf"); return err; } rte_wmb(); /* Init the RX tail register. */ I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); I40EVF_WRITE_FLUSH(hw); /* Ready to switch the queue on */ err = i40evf_switch_queue(dev, TRUE, rx_queue_id, TRUE); if (err) PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on", rx_queue_id); } return err; } static int i40evf_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct i40e_rx_queue *rxq; int err; if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; err = i40evf_switch_queue(dev, TRUE, rx_queue_id, FALSE); if (err) { PMD_DRV_LOG(ERR, "Failed to switch RX queue %u off", rx_queue_id); return err; } i40e_rx_queue_release_mbufs(rxq); i40e_reset_rx_queue(rxq); } return 0; } static int i40evf_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) { int err = 0; PMD_INIT_FUNC_TRACE(); if (tx_queue_id < dev->data->nb_tx_queues) { /* Ready to switch the queue on */ err = i40evf_switch_queue(dev, FALSE, tx_queue_id, TRUE); if (err) PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on", tx_queue_id); } return err; } static int i40evf_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct i40e_tx_queue *txq; int err; if (tx_queue_id < dev->data->nb_tx_queues) { txq = dev->data->tx_queues[tx_queue_id]; err = i40evf_switch_queue(dev, FALSE, tx_queue_id, FALSE); if (err) { PMD_DRV_LOG(ERR, "Failed to switch TX queue %u off", tx_queue_id); return err; } i40e_tx_queue_release_mbufs(txq); i40e_reset_tx_queue(txq); } return 0; } static int i40evf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { int ret; if (on) ret = i40evf_add_vlan(dev, vlan_id); else ret = i40evf_del_vlan(dev,vlan_id); return ret; } static int i40evf_rxq_init(struct rte_eth_dev *dev, struct i40e_rx_queue *rxq) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_dev_data *dev_data = dev->data; struct rte_pktmbuf_pool_private *mbp_priv; uint16_t buf_size, len; rxq->qrx_tail = hw->hw_addr + I40E_QRX_TAIL1(rxq->queue_id); I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); I40EVF_WRITE_FLUSH(hw); /* Calculate the maximum packet length allowed */ mbp_priv = rte_mempool_get_priv(rxq->mp); buf_size = (uint16_t)(mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM); rxq->hs_mode = i40e_header_split_none; rxq->rx_hdr_len = 0; rxq->rx_buf_len = RTE_ALIGN(buf_size, (1 << I40E_RXQ_CTX_DBUFF_SHIFT)); len = rxq->rx_buf_len * I40E_MAX_CHAINED_RX_BUFFERS; rxq->max_pkt_len = RTE_MIN(len, dev_data->dev_conf.rxmode.max_rx_pkt_len); /** * Check if the jumbo frame and maximum packet length are set correctly */ if (dev_data->dev_conf.rxmode.jumbo_frame == 1) { if (rxq->max_pkt_len <= ETHER_MAX_LEN || rxq->max_pkt_len > I40E_FRAME_SIZE_MAX) { PMD_DRV_LOG(ERR, "maximum packet length must be " "larger than %u and smaller than %u, as jumbo " "frame is enabled", (uint32_t)ETHER_MAX_LEN, (uint32_t)I40E_FRAME_SIZE_MAX); return I40E_ERR_CONFIG; } } else { if (rxq->max_pkt_len < ETHER_MIN_LEN || rxq->max_pkt_len > ETHER_MAX_LEN) { PMD_DRV_LOG(ERR, "maximum packet length must be " "larger than %u and smaller than %u, as jumbo " "frame is disabled", (uint32_t)ETHER_MIN_LEN, (uint32_t)ETHER_MAX_LEN); return I40E_ERR_CONFIG; } } if (dev_data->dev_conf.rxmode.enable_scatter || (rxq->max_pkt_len + 2 * I40E_VLAN_TAG_SIZE) > buf_size) { dev_data->scattered_rx = 1; dev->rx_pkt_burst = i40e_recv_scattered_pkts; } return 0; } static int i40evf_rx_init(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); uint16_t i; struct i40e_rx_queue **rxq = (struct i40e_rx_queue **)dev->data->rx_queues; i40evf_config_rss(vf); for (i = 0; i < dev->data->nb_rx_queues; i++) { if (!rxq[i] || !rxq[i]->q_set) continue; if (i40evf_rxq_init(dev, rxq[i]) < 0) return -EFAULT; } return 0; } static void i40evf_tx_init(struct rte_eth_dev *dev) { uint16_t i; struct i40e_tx_queue **txq = (struct i40e_tx_queue **)dev->data->tx_queues; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); for (i = 0; i < dev->data->nb_tx_queues; i++) txq[i]->qtx_tail = hw->hw_addr + I40E_QTX_TAIL1(i); } static inline void i40evf_enable_queues_intr(struct i40e_hw *hw) { I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1), I40E_VFINT_DYN_CTLN1_INTENA_MASK | I40E_VFINT_DYN_CTLN_CLEARPBA_MASK); } static inline void i40evf_disable_queues_intr(struct i40e_hw *hw) { I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1), 0); } static int i40evf_dev_start(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ether_addr mac_addr; PMD_INIT_FUNC_TRACE(); hw->adapter_stopped = 0; vf->max_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len; vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues); if (i40evf_rx_init(dev) != 0){ PMD_DRV_LOG(ERR, "failed to do RX init"); return -1; } i40evf_tx_init(dev); if (i40evf_configure_queues(dev) != 0) { PMD_DRV_LOG(ERR, "configure queues failed"); goto err_queue; } if (i40evf_config_irq_map(dev)) { PMD_DRV_LOG(ERR, "config_irq_map failed"); goto err_queue; } /* Set mac addr */ (void)rte_memcpy(mac_addr.addr_bytes, hw->mac.addr, sizeof(mac_addr.addr_bytes)); if (i40evf_add_mac_addr(dev, &mac_addr)) { PMD_DRV_LOG(ERR, "Failed to add mac addr"); goto err_queue; } if (i40evf_start_queues(dev) != 0) { PMD_DRV_LOG(ERR, "enable queues failed"); goto err_mac; } i40evf_enable_queues_intr(hw); return 0; err_mac: i40evf_del_mac_addr(dev, &mac_addr); err_queue: return -1; } static void i40evf_dev_stop(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); i40evf_disable_queues_intr(hw); i40evf_stop_queues(dev); i40e_dev_clear_queues(dev); } static int i40evf_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) { struct rte_eth_link new_link; struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); /* * DPDK pf host provide interfacet to acquire link status * while Linux driver does not */ if (vf->version_major == I40E_DPDK_VERSION_MAJOR) i40evf_get_link_status(dev, &new_link); else { /* Always assume it's up, for Linux driver PF host */ new_link.link_duplex = ETH_LINK_AUTONEG_DUPLEX; new_link.link_speed = ETH_LINK_SPEED_10000; new_link.link_status = 1; } i40evf_dev_atomic_write_link_status(dev, &new_link); return 0; } static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int ret; /* If enabled, just return */ if (vf->promisc_unicast_enabled) return; ret = i40evf_config_promisc(dev, 1, vf->promisc_multicast_enabled); if (ret == 0) vf->promisc_unicast_enabled = TRUE; } static void i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int ret; /* If disabled, just return */ if (!vf->promisc_unicast_enabled) return; ret = i40evf_config_promisc(dev, 0, vf->promisc_multicast_enabled); if (ret == 0) vf->promisc_unicast_enabled = FALSE; } static void i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int ret; /* If enabled, just return */ if (vf->promisc_multicast_enabled) return; ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 1); if (ret == 0) vf->promisc_multicast_enabled = TRUE; } static void i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); int ret; /* If enabled, just return */ if (!vf->promisc_multicast_enabled) return; ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 0); if (ret == 0) vf->promisc_multicast_enabled = FALSE; } static void i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); memset(dev_info, 0, sizeof(*dev_info)); dev_info->max_rx_queues = vf->vsi_res->num_queue_pairs; dev_info->max_tx_queues = vf->vsi_res->num_queue_pairs; dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN; dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX; dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t); dev_info->reta_size = ETH_RSS_RETA_SIZE_64; dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_QINQ_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_QINQ_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = I40E_DEFAULT_RX_PTHRESH, .hthresh = I40E_DEFAULT_RX_HTHRESH, .wthresh = I40E_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = I40E_DEFAULT_TX_PTHRESH, .hthresh = I40E_DEFAULT_TX_HTHRESH, .wthresh = I40E_DEFAULT_TX_WTHRESH, }, .tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH, .tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; } static void i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { if (i40evf_get_statics(dev, stats)) PMD_DRV_LOG(ERR, "Get statics failed"); } static void i40evf_dev_close(struct rte_eth_dev *dev) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); i40evf_dev_stop(dev); hw->adapter_stopped = 1; i40e_dev_free_queues(dev); i40evf_reset_vf(hw); i40e_shutdown_adminq(hw); } static int i40evf_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t lut, l; uint16_t i, j; uint16_t idx, shift; uint8_t mask; if (reta_size != ETH_RSS_RETA_SIZE_64) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number of hardware can " "support (%d)\n", reta_size, ETH_RSS_RETA_SIZE_64); return -EINVAL; } for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & I40E_4_BIT_MASK); if (!mask) continue; if (mask == I40E_4_BIT_MASK) l = 0; else l = I40E_READ_REG(hw, I40E_VFQF_HLUT(i >> 2)); for (j = 0, lut = 0; j < I40E_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) lut |= reta_conf[idx].reta[shift + j] << (CHAR_BIT * j); else lut |= l & (I40E_8_BIT_MASK << (CHAR_BIT * j)); } I40E_WRITE_REG(hw, I40E_VFQF_HLUT(i >> 2), lut); } return 0; } static int i40evf_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t lut; uint16_t i, j; uint16_t idx, shift; uint8_t mask; if (reta_size != ETH_RSS_RETA_SIZE_64) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number of hardware can " "support (%d)\n", reta_size, ETH_RSS_RETA_SIZE_64); return -EINVAL; } for (i = 0; i < reta_size; i += I40E_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & I40E_4_BIT_MASK); if (!mask) continue; lut = I40E_READ_REG(hw, I40E_VFQF_HLUT(i >> 2)); for (j = 0; j < I40E_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta_conf[idx].reta[shift + j] = ((lut >> (CHAR_BIT * j)) & I40E_8_BIT_MASK); } } return 0; } static int i40evf_hw_rss_hash_set(struct i40e_hw *hw, struct rte_eth_rss_conf *rss_conf) { uint32_t *hash_key; uint8_t hash_key_len; uint64_t rss_hf, hena; hash_key = (uint32_t *)(rss_conf->rss_key); hash_key_len = rss_conf->rss_key_len; if (hash_key != NULL && hash_key_len >= (I40E_VFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t)) { uint16_t i; for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) I40E_WRITE_REG(hw, I40E_VFQF_HKEY(i), hash_key[i]); } rss_hf = rss_conf->rss_hf; hena = (uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(1))) << 32; hena &= ~I40E_RSS_HENA_ALL; hena |= i40e_config_hena(rss_hf); I40E_WRITE_REG(hw, I40E_VFQF_HENA(0), (uint32_t)hena); I40E_WRITE_REG(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32)); I40EVF_WRITE_FLUSH(hw); return 0; } static void i40evf_disable_rss(struct i40e_vf *vf) { struct i40e_hw *hw = I40E_VF_TO_HW(vf); uint64_t hena; hena = (uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(1))) << 32; hena &= ~I40E_RSS_HENA_ALL; I40E_WRITE_REG(hw, I40E_VFQF_HENA(0), (uint32_t)hena); I40E_WRITE_REG(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32)); I40EVF_WRITE_FLUSH(hw); } static int i40evf_config_rss(struct i40e_vf *vf) { struct i40e_hw *hw = I40E_VF_TO_HW(vf); struct rte_eth_rss_conf rss_conf; uint32_t i, j, lut = 0, nb_q = (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4; uint16_t num; if (vf->dev_data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS) { i40evf_disable_rss(vf); PMD_DRV_LOG(DEBUG, "RSS not configured\n"); return 0; } num = i40e_align_floor(vf->dev_data->nb_rx_queues); /* Fill out the look up table */ for (i = 0, j = 0; i < nb_q; i++, j++) { if (j >= num) j = 0; lut = (lut << 8) | j; if ((i & 3) == 3) I40E_WRITE_REG(hw, I40E_VFQF_HLUT(i >> 2), lut); } rss_conf = vf->dev_data->dev_conf.rx_adv_conf.rss_conf; if ((rss_conf.rss_hf & I40E_RSS_OFFLOAD_ALL) == 0) { i40evf_disable_rss(vf); PMD_DRV_LOG(DEBUG, "No hash flag is set\n"); return 0; } if (rss_conf.rss_key == NULL || rss_conf.rss_key_len < nb_q) { /* Calculate the default hash key */ for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) rss_key_default[i] = (uint32_t)rte_rand(); rss_conf.rss_key = (uint8_t *)rss_key_default; rss_conf.rss_key_len = nb_q; } return i40evf_hw_rss_hash_set(hw, &rss_conf); } static int i40evf_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint64_t rss_hf = rss_conf->rss_hf & I40E_RSS_OFFLOAD_ALL; uint64_t hena; hena = (uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(1))) << 32; if (!(hena & I40E_RSS_HENA_ALL)) { /* RSS disabled */ if (rss_hf != 0) /* Enable RSS */ return -EINVAL; return 0; } /* RSS enabled */ if (rss_hf == 0) /* Disable RSS */ return -EINVAL; return i40evf_hw_rss_hash_set(hw, rss_conf); } static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *hash_key = (uint32_t *)(rss_conf->rss_key); uint64_t hena; uint16_t i; if (hash_key) { for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) hash_key[i] = I40E_READ_REG(hw, I40E_VFQF_HKEY(i)); rss_conf->rss_key_len = i * sizeof(uint32_t); } hena = (uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(0)); hena |= ((uint64_t)I40E_READ_REG(hw, I40E_VFQF_HENA(1))) << 32; rss_conf->rss_hf = i40e_parse_hena(hena); return 0; } ================================================ FILE: drivers/net/i40e/i40e_fdir.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i40e_logs.h" #include "base/i40e_type.h" #include "i40e_ethdev.h" #include "i40e_rxtx.h" #define I40E_FDIR_MZ_NAME "FDIR_MEMZONE" #ifndef IPV6_ADDR_LEN #define IPV6_ADDR_LEN 16 #endif #define I40E_FDIR_PKT_LEN 512 #define I40E_FDIR_IP_DEFAULT_LEN 420 #define I40E_FDIR_IP_DEFAULT_TTL 0x40 #define I40E_FDIR_IP_DEFAULT_VERSION_IHL 0x45 #define I40E_FDIR_TCP_DEFAULT_DATAOFF 0x50 #define I40E_FDIR_IPv6_DEFAULT_VTC_FLOW 0x60300000 #define I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS 0xFF #define I40E_FDIR_IPv6_PAYLOAD_LEN 380 #define I40E_FDIR_UDP_DEFAULT_LEN 400 /* Wait count and interval for fdir filter programming */ #define I40E_FDIR_WAIT_COUNT 10 #define I40E_FDIR_WAIT_INTERVAL_US 1000 /* Wait count and interval for fdir filter flush */ #define I40E_FDIR_FLUSH_RETRY 50 #define I40E_FDIR_FLUSH_INTERVAL_MS 5 #define I40E_COUNTER_PF 2 /* Statistic counter index for one pf */ #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF) #define I40E_MAX_FLX_SOURCE_OFF 480 #define I40E_FLX_OFFSET_IN_FIELD_VECTOR 50 #define NONUSE_FLX_PIT_DEST_OFF 63 #define NONUSE_FLX_PIT_FSIZE 1 #define MK_FLX_PIT(src_offset, fsize, dst_offset) ( \ (((src_offset) << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) & \ I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK) | \ (((fsize) << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) & \ I40E_PRTQF_FLX_PIT_FSIZE_MASK) | \ ((((dst_offset) + I40E_FLX_OFFSET_IN_FIELD_VECTOR) << \ I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) & \ I40E_PRTQF_FLX_PIT_DEST_OFF_MASK)) #define I40E_FDIR_FLOWS ( \ (1 << RTE_ETH_FLOW_FRAG_IPV4) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ (1 << RTE_ETH_FLOW_FRAG_IPV6) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ (1 << RTE_ETH_FLOW_L2_PAYLOAD)) #define I40E_FLEX_WORD_MASK(off) (0x80 >> (off)) static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq); static int i40e_check_fdir_flex_conf( const struct rte_eth_fdir_flex_conf *conf); static void i40e_set_flx_pld_cfg(struct i40e_pf *pf, const struct rte_eth_flex_payload_cfg *cfg); static void i40e_set_flex_mask_on_pctype(struct i40e_pf *pf, enum i40e_filter_pctype pctype, const struct rte_eth_fdir_flex_mask *mask_cfg); static int i40e_fdir_construct_pkt(struct i40e_pf *pf, const struct rte_eth_fdir_input *fdir_input, unsigned char *raw_pkt); static int i40e_add_del_fdir_filter(struct rte_eth_dev *dev, const struct rte_eth_fdir_filter *filter, bool add); static int i40e_fdir_filter_programming(struct i40e_pf *pf, enum i40e_filter_pctype pctype, const struct rte_eth_fdir_filter *filter, bool add); static int i40e_fdir_flush(struct rte_eth_dev *dev); static void i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir); static void i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat); static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq) { struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi); struct i40e_hmc_obj_rxq rx_ctx; int err = I40E_SUCCESS; memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); /* Init the RX queue in hardware */ rx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT; rx_ctx.hbuff = 0; rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; rx_ctx.qlen = rxq->nb_rx_desc; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC rx_ctx.dsize = 1; #endif rx_ctx.dtype = i40e_header_split_none; rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE; rx_ctx.rxmax = ETHER_MAX_LEN; rx_ctx.tphrdesc_ena = 1; rx_ctx.tphwdesc_ena = 1; rx_ctx.tphdata_ena = 1; rx_ctx.tphhead_ena = 1; rx_ctx.lrxqthresh = 2; rx_ctx.crcstrip = 0; rx_ctx.l2tsel = 1; rx_ctx.showiv = 1; rx_ctx.prefena = 1; err = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to clear FDIR RX queue context."); return err; } err = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to set FDIR RX queue context."); return err; } rxq->qrx_tail = hw->hw_addr + I40E_QRX_TAIL(rxq->vsi->base_queue); rte_wmb(); /* Init the RX tail regieter. */ I40E_PCI_REG_WRITE(rxq->qrx_tail, 0); I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); return err; } /* * i40e_fdir_setup - reserve and initialize the Flow Director resources * @pf: board private structure */ int i40e_fdir_setup(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_vsi *vsi; int err = I40E_SUCCESS; char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz = NULL; struct rte_eth_dev *eth_dev = pf->adapter->eth_dev; if ((pf->flags & I40E_FLAG_FDIR) == 0) { PMD_INIT_LOG(ERR, "HW doesn't support FDIR"); return I40E_NOT_SUPPORTED; } PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u," " num_filters_best_effort = %u.", hw->func_caps.fd_filters_guaranteed, hw->func_caps.fd_filters_best_effort); vsi = pf->fdir.fdir_vsi; if (vsi) { PMD_DRV_LOG(INFO, "FDIR initialization has been done."); return I40E_SUCCESS; } /* make new FDIR VSI */ vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0); if (!vsi) { PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI."); return I40E_ERR_NO_AVAILABLE_VSI; } pf->fdir.fdir_vsi = vsi; /*Fdir tx queue setup*/ err = i40e_fdir_setup_tx_resources(pf); if (err) { PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources."); goto fail_setup_tx; } /*Fdir rx queue setup*/ err = i40e_fdir_setup_rx_resources(pf); if (err) { PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources."); goto fail_setup_rx; } err = i40e_tx_queue_init(pf->fdir.txq); if (err) { PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization."); goto fail_mem; } /* need switch on before dev start*/ err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE); if (err) { PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on."); goto fail_mem; } /* Init the rx queue in hardware */ err = i40e_fdir_rx_queue_init(pf->fdir.rxq); if (err) { PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization."); goto fail_mem; } /* switch on rx queue */ err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE); if (err) { PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on."); goto fail_mem; } /* reserve memory for the fdir programming packet */ snprintf(z_name, sizeof(z_name), "%s_%s_%d", eth_dev->driver->pci_drv.name, I40E_FDIR_MZ_NAME, eth_dev->data->port_id); mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY); if (!mz) { PMD_DRV_LOG(ERR, "Cannot init memzone for " "flow director program packet."); err = I40E_ERR_NO_MEMORY; goto fail_mem; } pf->fdir.prg_pkt = mz->addr; #ifdef RTE_LIBRTE_XEN_DOM0 pf->fdir.dma_addr = rte_mem_phy2mch(mz->memseg_id, mz->phys_addr); #else pf->fdir.dma_addr = (uint64_t)mz->phys_addr; #endif pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id); PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.", vsi->base_queue); return I40E_SUCCESS; fail_mem: i40e_dev_rx_queue_release(pf->fdir.rxq); pf->fdir.rxq = NULL; fail_setup_rx: i40e_dev_tx_queue_release(pf->fdir.txq); pf->fdir.txq = NULL; fail_setup_tx: i40e_vsi_release(vsi); pf->fdir.fdir_vsi = NULL; return err; } /* * i40e_fdir_teardown - release the Flow Director resources * @pf: board private structure */ void i40e_fdir_teardown(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_vsi *vsi; vsi = pf->fdir.fdir_vsi; if (!vsi) return; i40e_switch_tx_queue(hw, vsi->base_queue, FALSE); i40e_switch_rx_queue(hw, vsi->base_queue, FALSE); i40e_dev_rx_queue_release(pf->fdir.rxq); pf->fdir.rxq = NULL; i40e_dev_tx_queue_release(pf->fdir.txq); pf->fdir.txq = NULL; i40e_vsi_release(vsi); pf->fdir.fdir_vsi = NULL; } /* check whether the flow director table in empty */ static inline int i40e_fdir_empty(struct i40e_hw *hw) { uint32_t guarant_cnt, best_cnt; guarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); best_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); if (best_cnt + guarant_cnt > 0) return -1; return 0; } /* * Initialize the configuration about bytes stream extracted as flexible payload * and mask setting */ static inline void i40e_init_flx_pld(struct i40e_pf *pf) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint8_t pctype; int i, index; /* * Define the bytes stream extracted as flexible payload in * field vector. By default, select 8 words from the beginning * of payload as flexible payload. */ for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) { index = i * I40E_MAX_FLXPLD_FIED; pf->fdir.flex_set[index].src_offset = 0; pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM; pf->fdir.flex_set[index].dst_offset = 0; I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900); I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/ I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/ } /* initialize the masks */ for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)pctype)) continue; pf->fdir.flex_mask[pctype].word_mask = 0; I40E_WRITE_REG(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0); for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) { pf->fdir.flex_mask[pctype].bitmask[i].offset = 0; pf->fdir.flex_mask[pctype].bitmask[i].mask = 0; I40E_WRITE_REG(hw, I40E_PRTQF_FD_MSK(pctype, i), 0); } } } #define I40E_WORD(hi, lo) (uint16_t)((((hi) << 8) & 0xFF00) | ((lo) & 0xFF)) #define I40E_VALIDATE_FLEX_PIT(flex_pit1, flex_pit2) do { \ if ((flex_pit2).src_offset < \ (flex_pit1).src_offset + (flex_pit1).size) { \ PMD_DRV_LOG(ERR, "src_offset should be not" \ " less than than previous offset" \ " + previous FSIZE."); \ return -EINVAL; \ } \ } while (0) /* * i40e_srcoff_to_flx_pit - transform the src_offset into flex_pit structure, * and the flex_pit will be sorted by it's src_offset value */ static inline uint16_t i40e_srcoff_to_flx_pit(const uint16_t *src_offset, struct i40e_fdir_flex_pit *flex_pit) { uint16_t src_tmp, size, num = 0; uint16_t i, k, j = 0; while (j < I40E_FDIR_MAX_FLEX_LEN) { size = 1; for (; j < I40E_FDIR_MAX_FLEX_LEN - 1; j++) { if (src_offset[j + 1] == src_offset[j] + 1) size++; else break; } src_tmp = src_offset[j] + 1 - size; /* the flex_pit need to be sort by src_offset */ for (i = 0; i < num; i++) { if (src_tmp < flex_pit[i].src_offset) break; } /* if insert required, move backward */ for (k = num; k > i; k--) flex_pit[k] = flex_pit[k - 1]; /* insert */ flex_pit[i].dst_offset = j + 1 - size; flex_pit[i].src_offset = src_tmp; flex_pit[i].size = size; j++; num++; } return num; } /* i40e_check_fdir_flex_payload -check flex payload configuration arguments */ static inline int i40e_check_fdir_flex_payload(const struct rte_eth_flex_payload_cfg *flex_cfg) { struct i40e_fdir_flex_pit flex_pit[I40E_FDIR_MAX_FLEX_LEN]; uint16_t num, i; for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++) { if (flex_cfg->src_offset[i] >= I40E_MAX_FLX_SOURCE_OFF) { PMD_DRV_LOG(ERR, "exceeds maxmial payload limit."); return -EINVAL; } } memset(flex_pit, 0, sizeof(flex_pit)); num = i40e_srcoff_to_flx_pit(flex_cfg->src_offset, flex_pit); if (num > I40E_MAX_FLXPLD_FIED) { PMD_DRV_LOG(ERR, "exceeds maxmial number of flex fields."); return -EINVAL; } for (i = 0; i < num; i++) { if (flex_pit[i].size & 0x01 || flex_pit[i].dst_offset & 0x01 || flex_pit[i].src_offset & 0x01) { PMD_DRV_LOG(ERR, "flexpayload should be measured" " in word"); return -EINVAL; } if (i != num - 1) I40E_VALIDATE_FLEX_PIT(flex_pit[i], flex_pit[i + 1]); } return 0; } /* * i40e_check_fdir_flex_conf -check if the flex payload and mask configuration * arguments are valid */ static int i40e_check_fdir_flex_conf(const struct rte_eth_fdir_flex_conf *conf) { const struct rte_eth_flex_payload_cfg *flex_cfg; const struct rte_eth_fdir_flex_mask *flex_mask; uint16_t mask_tmp; uint8_t nb_bitmask; uint16_t i, j; int ret = 0; if (conf == NULL) { PMD_DRV_LOG(INFO, "NULL pointer."); return -EINVAL; } /* check flexible payload setting configuration */ if (conf->nb_payloads > RTE_ETH_L4_PAYLOAD) { PMD_DRV_LOG(ERR, "invalid number of payload setting."); return -EINVAL; } for (i = 0; i < conf->nb_payloads; i++) { flex_cfg = &conf->flex_set[i]; if (flex_cfg->type > RTE_ETH_L4_PAYLOAD) { PMD_DRV_LOG(ERR, "invalid payload type."); return -EINVAL; } ret = i40e_check_fdir_flex_payload(flex_cfg); if (ret < 0) { PMD_DRV_LOG(ERR, "invalid flex payload arguments."); return -EINVAL; } } /* check flex mask setting configuration */ if (conf->nb_flexmasks >= RTE_ETH_FLOW_MAX) { PMD_DRV_LOG(ERR, "invalid number of flex masks."); return -EINVAL; } for (i = 0; i < conf->nb_flexmasks; i++) { flex_mask = &conf->flex_mask[i]; if (!I40E_VALID_FLOW(flex_mask->flow_type)) { PMD_DRV_LOG(WARNING, "invalid flow type."); return -EINVAL; } nb_bitmask = 0; for (j = 0; j < I40E_FDIR_MAX_FLEX_LEN; j += sizeof(uint16_t)) { mask_tmp = I40E_WORD(flex_mask->mask[j], flex_mask->mask[j + 1]); if (mask_tmp != 0x0 && mask_tmp != UINT16_MAX) { nb_bitmask++; if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD) { PMD_DRV_LOG(ERR, " exceed maximal" " number of bitmasks."); return -EINVAL; } } } } return 0; } /* * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload * @pf: board private structure * @cfg: the rule how bytes stream is extracted as flexible payload */ static void i40e_set_flx_pld_cfg(struct i40e_pf *pf, const struct rte_eth_flex_payload_cfg *cfg) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED]; uint32_t flx_pit; uint16_t num, min_next_off; /* in words */ uint8_t field_idx = 0; uint8_t layer_idx = 0; uint16_t i; if (cfg->type == RTE_ETH_L2_PAYLOAD) layer_idx = I40E_FLXPLD_L2_IDX; else if (cfg->type == RTE_ETH_L3_PAYLOAD) layer_idx = I40E_FLXPLD_L3_IDX; else if (cfg->type == RTE_ETH_L4_PAYLOAD) layer_idx = I40E_FLXPLD_L4_IDX; memset(flex_pit, 0, sizeof(flex_pit)); num = i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit); for (i = 0; i < RTE_MIN(num, RTE_DIM(flex_pit)); i++) { field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; /* record the info in fdir structure */ pf->fdir.flex_set[field_idx].src_offset = flex_pit[i].src_offset / sizeof(uint16_t); pf->fdir.flex_set[field_idx].size = flex_pit[i].size / sizeof(uint16_t); pf->fdir.flex_set[field_idx].dst_offset = flex_pit[i].dst_offset / sizeof(uint16_t); flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset, pf->fdir.flex_set[field_idx].size, pf->fdir.flex_set[field_idx].dst_offset); I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit); } min_next_off = pf->fdir.flex_set[field_idx].src_offset + pf->fdir.flex_set[field_idx].size; for (; i < I40E_MAX_FLXPLD_FIED; i++) { /* set the non-used register obeying register's constrain */ flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE, NONUSE_FLX_PIT_DEST_OFF); I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(layer_idx * I40E_MAX_FLXPLD_FIED + i), flx_pit); min_next_off++; } } /* * i40e_set_flex_mask_on_pctype - configure the mask on flexible payload * @pf: board private structure * @pctype: packet classify type * @flex_masks: mask for flexible payload */ static void i40e_set_flex_mask_on_pctype(struct i40e_pf *pf, enum i40e_filter_pctype pctype, const struct rte_eth_fdir_flex_mask *mask_cfg) { struct i40e_hw *hw = I40E_PF_TO_HW(pf); struct i40e_fdir_flex_mask *flex_mask; uint32_t flxinset, fd_mask; uint16_t mask_tmp; uint8_t i, nb_bitmask = 0; flex_mask = &pf->fdir.flex_mask[pctype]; memset(flex_mask, 0, sizeof(struct i40e_fdir_flex_mask)); for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) { mask_tmp = I40E_WORD(mask_cfg->mask[i], mask_cfg->mask[i + 1]); if (mask_tmp != 0x0) { flex_mask->word_mask |= I40E_FLEX_WORD_MASK(i / sizeof(uint16_t)); if (mask_tmp != UINT16_MAX) { /* set bit mask */ flex_mask->bitmask[nb_bitmask].mask = ~mask_tmp; flex_mask->bitmask[nb_bitmask].offset = i / sizeof(uint16_t); nb_bitmask++; } } } /* write mask to hw */ flxinset = (flex_mask->word_mask << I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) & I40E_PRTQF_FD_FLXINSET_INSET_MASK; I40E_WRITE_REG(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset); for (i = 0; i < nb_bitmask; i++) { fd_mask = (flex_mask->bitmask[i].mask << I40E_PRTQF_FD_MSK_MASK_SHIFT) & I40E_PRTQF_FD_MSK_MASK_MASK; fd_mask |= ((flex_mask->bitmask[i].offset + I40E_FLX_OFFSET_IN_FIELD_VECTOR) << I40E_PRTQF_FD_MSK_OFFSET_SHIFT) & I40E_PRTQF_FD_MSK_OFFSET_MASK; I40E_WRITE_REG(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask); } } /* * Configure flow director related setting */ int i40e_fdir_configure(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_fdir_flex_conf *conf; enum i40e_filter_pctype pctype; uint32_t val; uint8_t i; int ret = 0; /* * configuration need to be done before * flow director filters are added * If filters exist, flush them. */ if (i40e_fdir_empty(hw) < 0) { ret = i40e_fdir_flush(dev); if (ret) { PMD_DRV_LOG(ERR, "failed to flush fdir table."); return ret; } } /* enable FDIR filter */ val = I40E_READ_REG(hw, I40E_PFQF_CTL_0); val |= I40E_PFQF_CTL_0_FD_ENA_MASK; I40E_WRITE_REG(hw, I40E_PFQF_CTL_0, val); i40e_init_flx_pld(pf); /* set flex config to default value */ conf = &dev->data->dev_conf.fdir_conf.flex_conf; ret = i40e_check_fdir_flex_conf(conf); if (ret < 0) { PMD_DRV_LOG(ERR, " invalid configuration arguments."); return -EINVAL; } /* configure flex payload */ for (i = 0; i < conf->nb_payloads; i++) i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]); /* configure flex mask*/ for (i = 0; i < conf->nb_flexmasks; i++) { pctype = i40e_flowtype_to_pctype(conf->flex_mask[i].flow_type); i40e_set_flex_mask_on_pctype(pf, pctype, &conf->flex_mask[i]); } return ret; } static inline void i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, unsigned char *raw_pkt) { struct ether_hdr *ether = (struct ether_hdr *)raw_pkt; struct ipv4_hdr *ip; struct ipv6_hdr *ip6; static const uint8_t next_proto[] = { [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP, [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP, [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP, [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP, [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP, [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE, [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP, [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP, [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP, [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE, }; switch (fdir_input->flow_type) { case RTE_ETH_FLOW_L2_PAYLOAD: ether->ether_type = fdir_input->flow.l2_flow.ether_type; break; case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: case RTE_ETH_FLOW_FRAG_IPV4: ip = (struct ipv4_hdr *)(raw_pkt + sizeof(struct ether_hdr)); ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL; /* set len to by default */ ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN); ip->time_to_live = I40E_FDIR_IP_DEFAULT_TTL; /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ ip->src_addr = fdir_input->flow.ip4_flow.dst_ip; ip->dst_addr = fdir_input->flow.ip4_flow.src_ip; ip->next_proto_id = next_proto[fdir_input->flow_type]; break; case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: case RTE_ETH_FLOW_FRAG_IPV6: ip6 = (struct ipv6_hdr *)(raw_pkt + sizeof(struct ether_hdr)); ether->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); ip6->vtc_flow = rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW); ip6->payload_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); ip6->hop_limits = I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS; /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ rte_memcpy(&(ip6->src_addr), &(fdir_input->flow.ipv6_flow.dst_ip), IPV6_ADDR_LEN); rte_memcpy(&(ip6->dst_addr), &(fdir_input->flow.ipv6_flow.src_ip), IPV6_ADDR_LEN); ip6->proto = next_proto[fdir_input->flow_type]; break; default: PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type); break; } } /* * i40e_fdir_construct_pkt - construct packet based on fields in input * @pf: board private structure * @fdir_input: input set of the flow director entry * @raw_pkt: a packet to be constructed */ static int i40e_fdir_construct_pkt(struct i40e_pf *pf, const struct rte_eth_fdir_input *fdir_input, unsigned char *raw_pkt) { unsigned char *payload, *ptr; struct udp_hdr *udp; struct tcp_hdr *tcp; struct sctp_hdr *sctp; uint8_t size, dst = 0; uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ /* fill the ethernet and IP head */ i40e_fdir_fill_eth_ip_head(fdir_input, raw_pkt); /* fill the L4 head */ switch (fdir_input->flow_type) { case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr)); payload = (unsigned char *)udp + sizeof(struct udp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ udp->src_port = fdir_input->flow.udp4_flow.dst_port; udp->dst_port = fdir_input->flow.udp4_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); break; case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr)); payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ tcp->src_port = fdir_input->flow.tcp4_flow.dst_port; tcp->dst_port = fdir_input->flow.tcp4_flow.src_port; tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; break; case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: sctp = (struct sctp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr)); payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); #ifdef RTE_NEXT_ABI /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ sctp->src_port = fdir_input->flow.sctp4_flow.dst_port; sctp->dst_port = fdir_input->flow.sctp4_flow.src_port; #endif sctp->tag = fdir_input->flow.sctp4_flow.verify_tag; break; case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: case RTE_ETH_FLOW_FRAG_IPV4: payload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr); set_idx = I40E_FLXPLD_L3_IDX; break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: udp = (struct udp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr)); payload = (unsigned char *)udp + sizeof(struct udp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ udp->src_port = fdir_input->flow.udp6_flow.dst_port; udp->dst_port = fdir_input->flow.udp6_flow.src_port; udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); break; case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: tcp = (struct tcp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr)); payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; tcp->src_port = fdir_input->flow.udp6_flow.dst_port; tcp->dst_port = fdir_input->flow.udp6_flow.src_port; break; case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: sctp = (struct sctp_hdr *)(raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr)); payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); #ifdef RTE_NEXT_ABI /* * The source and destination fields in the transmitted packet * need to be presented in a reversed order with respect * to the expected received packets. */ sctp->src_port = fdir_input->flow.sctp6_flow.dst_port; sctp->dst_port = fdir_input->flow.sctp6_flow.src_port; #endif sctp->tag = fdir_input->flow.sctp6_flow.verify_tag; break; case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: case RTE_ETH_FLOW_FRAG_IPV6: payload = raw_pkt + sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr); set_idx = I40E_FLXPLD_L3_IDX; break; case RTE_ETH_FLOW_L2_PAYLOAD: payload = raw_pkt + sizeof(struct ether_hdr); /* * ARP packet is a special case on which the payload * starts after the whole ARP header */ if (fdir_input->flow.l2_flow.ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) payload += sizeof(struct arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; break; default: PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type); return -EINVAL; } /* fill the flexbytes to payload */ for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) { pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i; size = pf->fdir.flex_set[pit_idx].size; if (size == 0) continue; dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t); ptr = payload + pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t); (void)rte_memcpy(ptr, &fdir_input->flow_ext.flexbytes[dst], size * sizeof(uint16_t)); } return 0; } /* Construct the tx flags */ static inline uint64_t i40e_build_ctob(uint32_t td_cmd, uint32_t td_offset, unsigned int size, uint32_t td_tag) { return rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DATA | ((uint64_t)td_cmd << I40E_TXD_QW1_CMD_SHIFT) | ((uint64_t)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) | ((uint64_t)size << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) | ((uint64_t)td_tag << I40E_TXD_QW1_L2TAG1_SHIFT)); } /* * check the programming status descriptor in rx queue. * done after Programming Flow Director is programmed on * tx queue */ static inline int i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq) { volatile union i40e_rx_desc *rxdp; uint64_t qword1; uint32_t rx_status; uint32_t len, id; uint32_t error; int ret = 0; rxdp = &rxq->rx_ring[rxq->rx_tail]; qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; if (rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) { len = qword1 >> I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT; id = (qword1 & I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK) >> I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT; if (len == I40E_RX_PROG_STATUS_DESC_LENGTH && id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS) { error = (qword1 & I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >> I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT; if (error == (0x1 << I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) { PMD_DRV_LOG(ERR, "Failed to add FDIR filter" " (FD_ID %u): programming status" " reported.", rxdp->wb.qword0.hi_dword.fd_id); ret = -1; } else if (error == (0x1 << I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) { PMD_DRV_LOG(ERR, "Failed to delete FDIR filter" " (FD_ID %u): programming status" " reported.", rxdp->wb.qword0.hi_dword.fd_id); ret = -1; } else PMD_DRV_LOG(ERR, "invalid programming status" " reported, error = %u.", error); } else PMD_DRV_LOG(ERR, "unknown programming status" " reported, len = %d, id = %u.", len, id); rxdp->wb.qword1.status_error_len = 0; rxq->rx_tail++; if (unlikely(rxq->rx_tail == rxq->nb_rx_desc)) rxq->rx_tail = 0; } return ret; } /* * i40e_add_del_fdir_filter - add or remove a flow director filter. * @pf: board private structure * @filter: fdir filter entry * @add: 0 - delete, 1 - add */ static int i40e_add_del_fdir_filter(struct rte_eth_dev *dev, const struct rte_eth_fdir_filter *filter, bool add) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt; enum i40e_filter_pctype pctype; int ret = 0; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { PMD_DRV_LOG(ERR, "FDIR is not enabled, please" " check the mode in fdir_conf."); return -ENOTSUP; } if (!I40E_VALID_FLOW(filter->input.flow_type)) { PMD_DRV_LOG(ERR, "invalid flow_type input."); return -EINVAL; } if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) { PMD_DRV_LOG(ERR, "Invalid queue ID"); return -EINVAL; } memset(pkt, 0, I40E_FDIR_PKT_LEN); ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt); if (ret < 0) { PMD_DRV_LOG(ERR, "construct packet for fdir fails."); return ret; } pctype = i40e_flowtype_to_pctype(filter->input.flow_type); ret = i40e_fdir_filter_programming(pf, pctype, filter, add); if (ret < 0) { PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).", pctype); return ret; } return ret; } /* * i40e_fdir_filter_programming - Program a flow director filter rule. * Is done by Flow Director Programming Descriptor followed by packet * structure that contains the filter fields need to match. * @pf: board private structure * @pctype: pctype * @filter: fdir filter entry * @add: 0 - delelet, 1 - add */ static int i40e_fdir_filter_programming(struct i40e_pf *pf, enum i40e_filter_pctype pctype, const struct rte_eth_fdir_filter *filter, bool add) { struct i40e_tx_queue *txq = pf->fdir.txq; struct i40e_rx_queue *rxq = pf->fdir.rxq; const struct rte_eth_fdir_action *fdir_action = &filter->action; volatile struct i40e_tx_desc *txdp; volatile struct i40e_filter_program_desc *fdirdp; uint32_t td_cmd; uint16_t i; uint8_t dest; PMD_DRV_LOG(INFO, "filling filter programming descriptor."); fdirdp = (volatile struct i40e_filter_program_desc *) (&(txq->tx_ring[txq->tx_tail])); fdirdp->qindex_flex_ptype_vsi = rte_cpu_to_le_32((fdir_action->rx_queue << I40E_TXD_FLTR_QW0_QINDEX_SHIFT) & I40E_TXD_FLTR_QW0_QINDEX_MASK); fdirdp->qindex_flex_ptype_vsi |= rte_cpu_to_le_32((fdir_action->flex_off << I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) & I40E_TXD_FLTR_QW0_FLEXOFF_MASK); fdirdp->qindex_flex_ptype_vsi |= rte_cpu_to_le_32((pctype << I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) & I40E_TXD_FLTR_QW0_PCTYPE_MASK); /* Use LAN VSI Id by default */ fdirdp->qindex_flex_ptype_vsi |= rte_cpu_to_le_32((pf->main_vsi->vsi_id << I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) & I40E_TXD_FLTR_QW0_DEST_VSI_MASK); fdirdp->dtype_cmd_cntindex = rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG); if (add) fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32( I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE << I40E_TXD_FLTR_QW1_PCMD_SHIFT); else fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32( I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << I40E_TXD_FLTR_QW1_PCMD_SHIFT); if (fdir_action->behavior == RTE_ETH_FDIR_REJECT) dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET; else dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX; fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest << I40E_TXD_FLTR_QW1_DEST_SHIFT) & I40E_TXD_FLTR_QW1_DEST_MASK); fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((fdir_action->report_status<< I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) & I40E_TXD_FLTR_QW1_FD_STATUS_MASK); fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK); fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((pf->fdir.match_counter_index << I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) & I40E_TXD_FLTR_QW1_CNTINDEX_MASK); fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id); PMD_DRV_LOG(INFO, "filling transmit descriptor."); txdp = &(txq->tx_ring[txq->tx_tail + 1]); txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr); td_cmd = I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS | I40E_TX_DESC_CMD_DUMMY; txdp->cmd_type_offset_bsz = i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0); txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */ if (txq->tx_tail >= txq->nb_tx_desc) txq->tx_tail = 0; /* Update the tx tail register */ rte_wmb(); I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail); for (i = 0; i < I40E_FDIR_WAIT_COUNT; i++) { rte_delay_us(I40E_FDIR_WAIT_INTERVAL_US); if ((txdp->cmd_type_offset_bsz & rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) == rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) break; } if (i >= I40E_FDIR_WAIT_COUNT) { PMD_DRV_LOG(ERR, "Failed to program FDIR filter:" " time out to get DD on tx queue."); return -ETIMEDOUT; } /* totally delay 10 ms to check programming status*/ rte_delay_us((I40E_FDIR_WAIT_COUNT - i) * I40E_FDIR_WAIT_INTERVAL_US); if (i40e_check_fdir_programming_status(rxq) < 0) { PMD_DRV_LOG(ERR, "Failed to program FDIR filter:" " programming status reported."); return -ENOSYS; } return 0; } /* * i40e_fdir_flush - clear all filters of Flow Director table * @pf: board private structure */ static int i40e_fdir_flush(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint32_t reg; uint16_t guarant_cnt, best_cnt; uint16_t i; I40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK); I40E_WRITE_FLUSH(hw); for (i = 0; i < I40E_FDIR_FLUSH_RETRY; i++) { rte_delay_ms(I40E_FDIR_FLUSH_INTERVAL_MS); reg = I40E_READ_REG(hw, I40E_PFQF_CTL_1); if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK)) break; } if (i >= I40E_FDIR_FLUSH_RETRY) { PMD_DRV_LOG(ERR, "FD table did not flush, may need more time."); return -ETIMEDOUT; } guarant_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); best_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); if (guarant_cnt != 0 || best_cnt != 0) { PMD_DRV_LOG(ERR, "Failed to flush FD table."); return -ENOSYS; } else PMD_DRV_LOG(INFO, "FD table Flush success."); return 0; } static inline void i40e_fdir_info_get_flex_set(struct i40e_pf *pf, struct rte_eth_flex_payload_cfg *flex_set, uint16_t *num) { struct i40e_fdir_flex_pit *flex_pit; struct rte_eth_flex_payload_cfg *ptr = flex_set; uint16_t src, dst, size, j, k; uint8_t i, layer_idx; for (layer_idx = I40E_FLXPLD_L2_IDX; layer_idx <= I40E_FLXPLD_L4_IDX; layer_idx++) { if (layer_idx == I40E_FLXPLD_L2_IDX) ptr->type = RTE_ETH_L2_PAYLOAD; else if (layer_idx == I40E_FLXPLD_L3_IDX) ptr->type = RTE_ETH_L3_PAYLOAD; else if (layer_idx == I40E_FLXPLD_L4_IDX) ptr->type = RTE_ETH_L4_PAYLOAD; for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) { flex_pit = &pf->fdir.flex_set[layer_idx * I40E_MAX_FLXPLD_FIED + i]; if (flex_pit->size == 0) continue; src = flex_pit->src_offset * sizeof(uint16_t); dst = flex_pit->dst_offset * sizeof(uint16_t); size = flex_pit->size * sizeof(uint16_t); for (j = src, k = dst; j < src + size; j++, k++) ptr->src_offset[k] = j; } (*num)++; ptr++; } } static inline void i40e_fdir_info_get_flex_mask(struct i40e_pf *pf, struct rte_eth_fdir_flex_mask *flex_mask, uint16_t *num) { struct i40e_fdir_flex_mask *mask; struct rte_eth_fdir_flex_mask *ptr = flex_mask; uint16_t flow_type; uint8_t i, j; uint16_t off_bytes, mask_tmp; for (i = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; i <= I40E_FILTER_PCTYPE_L2_PAYLOAD; i++) { mask = &pf->fdir.flex_mask[i]; if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i)) continue; flow_type = i40e_pctype_to_flowtype((enum i40e_filter_pctype)i); for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) { if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) { ptr->mask[j * sizeof(uint16_t)] = UINT8_MAX; ptr->mask[j * sizeof(uint16_t) + 1] = UINT8_MAX; } else { ptr->mask[j * sizeof(uint16_t)] = 0x0; ptr->mask[j * sizeof(uint16_t) + 1] = 0x0; } } for (j = 0; j < I40E_FDIR_BITMASK_NUM_WORD; j++) { off_bytes = mask->bitmask[j].offset * sizeof(uint16_t); mask_tmp = ~mask->bitmask[j].mask; ptr->mask[off_bytes] &= I40E_HI_BYTE(mask_tmp); ptr->mask[off_bytes + 1] &= I40E_LO_BYTE(mask_tmp); } ptr->flow_type = flow_type; ptr++; (*num)++; } } /* * i40e_fdir_info_get - get information of Flow Director * @pf: ethernet device to get info from * @fdir: a pointer to a structure of type *rte_eth_fdir_info* to be filled with * the flow director information. */ static void i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint16_t num_flex_set = 0; uint16_t num_flex_mask = 0; if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) fdir->mode = RTE_FDIR_MODE_PERFECT; else fdir->mode = RTE_FDIR_MODE_NONE; fdir->guarant_spc = (uint32_t)hw->func_caps.fd_filters_guaranteed; fdir->best_spc = (uint32_t)hw->func_caps.fd_filters_best_effort; fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN; fdir->flow_types_mask[0] = I40E_FDIR_FLOWS; fdir->flex_payload_unit = sizeof(uint16_t); fdir->flex_bitmask_unit = sizeof(uint16_t); fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED; fdir->flex_payload_limit = I40E_MAX_FLX_SOURCE_OFF; fdir->max_flex_bitmask_num = I40E_FDIR_BITMASK_NUM_WORD; i40e_fdir_info_get_flex_set(pf, fdir->flex_conf.flex_set, &num_flex_set); i40e_fdir_info_get_flex_mask(pf, fdir->flex_conf.flex_mask, &num_flex_mask); fdir->flex_conf.nb_payloads = num_flex_set; fdir->flex_conf.nb_flexmasks = num_flex_mask; } /* * i40e_fdir_stat_get - get statistics of Flow Director * @pf: ethernet device to get info from * @stat: a pointer to a structure of type *rte_eth_fdir_stats* to be filled with * the flow director statistics. */ static void i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint32_t fdstat; fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT); stat->guarant_cnt = (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); stat->best_cnt = (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); } /* * i40e_fdir_ctrl_func - deal with all operations on flow director. * @pf: board private structure * @filter_op:operation will be taken. * @arg: a pointer to specific structure corresponding to the filter_op */ int i40e_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); int ret = 0; if ((pf->flags & I40E_FLAG_FDIR) == 0) return -ENOTSUP; if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) return -EINVAL; switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = i40e_add_del_fdir_filter(dev, (struct rte_eth_fdir_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = i40e_add_del_fdir_filter(dev, (struct rte_eth_fdir_filter *)arg, FALSE); break; case RTE_ETH_FILTER_FLUSH: ret = i40e_fdir_flush(dev); break; case RTE_ETH_FILTER_INFO: i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg); break; case RTE_ETH_FILTER_STATS: i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg); break; default: PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op); ret = -EINVAL; break; } return ret; } ================================================ FILE: drivers/net/i40e/i40e_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _I40E_LOGS_H_ #define _I40E_LOGS_H_ #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) #ifdef RTE_LIBRTE_I40E_DEBUG_INIT #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_I40E_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_I40E_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_I40E_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER #define PMD_DRV_LOG_RAW(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) #else #define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) #endif #define PMD_DRV_LOG(level, fmt, args...) \ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) #endif /* _I40E_LOGS_H_ */ ================================================ FILE: drivers/net/i40e/i40e_pf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i40e_logs.h" #include "base/i40e_prototype.h" #include "base/i40e_adminq_cmd.h" #include "base/i40e_type.h" #include "i40e_ethdev.h" #include "i40e_rxtx.h" #include "i40e_pf.h" #define I40E_CFG_CRCSTRIP_DEFAULT 1 static int i40e_pf_host_switch_queues(struct i40e_pf_vf *vf, struct i40e_virtchnl_queue_select *qsel, bool on); /** * Bind PF queues with VSI and VF. **/ static int i40e_pf_vf_queues_mapping(struct i40e_pf_vf *vf) { int i; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); uint16_t vsi_id = vf->vsi->vsi_id; uint16_t vf_id = vf->vf_idx; uint16_t nb_qps = vf->vsi->nb_qps; uint16_t qbase = vf->vsi->base_queue; uint16_t q1, q2; uint32_t val; /* * VF should use scatter range queues. So, it needn't * to set QBASE in this register. */ I40E_WRITE_REG(hw, I40E_VSILAN_QBASE(vsi_id), I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK); /* Set to enable VFLAN_QTABLE[] registers valid */ I40E_WRITE_REG(hw, I40E_VPLAN_MAPENA(vf_id), I40E_VPLAN_MAPENA_TXRX_ENA_MASK); /* map PF queues to VF */ for (i = 0; i < nb_qps; i++) { val = ((qbase + i) & I40E_VPLAN_QTABLE_QINDEX_MASK); I40E_WRITE_REG(hw, I40E_VPLAN_QTABLE(i, vf_id), val); } /* map PF queues to VSI */ for (i = 0; i < I40E_MAX_QP_NUM_PER_VF / 2; i++) { if (2 * i > nb_qps - 1) q1 = I40E_VSILAN_QTABLE_QINDEX_0_MASK; else q1 = qbase + 2 * i; if (2 * i + 1 > nb_qps - 1) q2 = I40E_VSILAN_QTABLE_QINDEX_0_MASK; else q2 = qbase + 2 * i + 1; val = (q2 << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT) + q1; I40E_WRITE_REG(hw, I40E_VSILAN_QTABLE(i, vsi_id), val); } I40E_WRITE_FLUSH(hw); return I40E_SUCCESS; } /** * Proceed VF reset operation. */ int i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset) { uint32_t val, i; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); uint16_t vf_id, abs_vf_id, vf_msix_num; int ret; struct i40e_virtchnl_queue_select qsel; if (vf == NULL) return -EINVAL; vf_id = vf->vf_idx; abs_vf_id = vf_id + hw->func_caps.vf_base_id; /* Notify VF that we are in VFR progress */ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_INPROGRESS); /* * If require a SW VF reset, a VFLR interrupt will be generated, * this function will be called again. To avoid it, * disable interrupt first. */ if (do_hw_reset) { vf->state = I40E_VF_INRESET; val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id)); val |= I40E_VPGEN_VFRTRIG_VFSWR_MASK; I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val); I40E_WRITE_FLUSH(hw); } #define VFRESET_MAX_WAIT_CNT 100 /* Wait until VF reset is done */ for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) { rte_delay_us(10); val = I40E_READ_REG(hw, I40E_VPGEN_VFRSTAT(vf_id)); if (val & I40E_VPGEN_VFRSTAT_VFRD_MASK) break; } if (i >= VFRESET_MAX_WAIT_CNT) { PMD_DRV_LOG(ERR, "VF reset timeout"); return -ETIMEDOUT; } /* This is not first time to do reset, do cleanup job first */ if (vf->vsi) { /* Disable queues */ memset(&qsel, 0, sizeof(qsel)); for (i = 0; i < vf->vsi->nb_qps; i++) qsel.rx_queues |= 1 << i; qsel.tx_queues = qsel.rx_queues; ret = i40e_pf_host_switch_queues(vf, &qsel, false); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Disable VF queues failed"); return -EFAULT; } /* Disable VF interrupt setting */ vf_msix_num = hw->func_caps.num_msix_vectors_vf; for (i = 0; i < vf_msix_num; i++) { if (!i) val = I40E_VFINT_DYN_CTL0(vf_id); else val = I40E_VFINT_DYN_CTLN(((vf_msix_num - 1) * (vf_id)) + (i - 1)); I40E_WRITE_REG(hw, val, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK); } I40E_WRITE_FLUSH(hw); /* remove VSI */ ret = i40e_vsi_release(vf->vsi); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Release VSI failed"); return -EFAULT; } } #define I40E_VF_PCI_ADDR 0xAA #define I40E_VF_PEND_MASK 0x20 /* Check the pending transactions of this VF */ /* Use absolute VF id, refer to datasheet for details */ I40E_WRITE_REG(hw, I40E_PF_PCI_CIAA, I40E_VF_PCI_ADDR | (abs_vf_id << I40E_PF_PCI_CIAA_VF_NUM_SHIFT)); for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) { rte_delay_us(1); val = I40E_READ_REG(hw, I40E_PF_PCI_CIAD); if ((val & I40E_VF_PEND_MASK) == 0) break; } if (i >= VFRESET_MAX_WAIT_CNT) { PMD_DRV_LOG(ERR, "Wait VF PCI transaction end timeout"); return -ETIMEDOUT; } /* Reset done, Set COMPLETE flag and clear reset bit */ I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_PF_VFR_COMPLETED); val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id)); val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK; I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val); vf->reset_cnt++; I40E_WRITE_FLUSH(hw); /* Allocate resource again */ vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV, vf->pf->main_vsi, vf->vf_idx); if (vf->vsi == NULL) { PMD_DRV_LOG(ERR, "Add vsi failed"); return -EFAULT; } ret = i40e_pf_vf_queues_mapping(vf); if (ret != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "queue mapping error"); i40e_vsi_release(vf->vsi); return -EFAULT; } return ret; } static int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode, uint32_t retval, uint8_t *msg, uint16_t msglen) { struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); uint16_t abs_vf_id = hw->func_caps.vf_base_id + vf->vf_idx; int ret; ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, opcode, retval, msg, msglen, NULL); if (ret) { PMD_INIT_LOG(ERR, "Fail to send message to VF, err %u", hw->aq.asq_last_status); } return ret; } static void i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf) { struct i40e_virtchnl_version_info info; info.major = I40E_DPDK_VERSION_MAJOR; info.minor = I40E_DPDK_VERSION_MINOR; i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_VERSION, I40E_SUCCESS, (uint8_t *)&info, sizeof(info)); } static int i40e_pf_host_process_cmd_reset_vf(struct i40e_pf_vf *vf) { i40e_pf_host_vf_reset(vf, 1); /* No feedback will be sent to VF for VFLR */ return I40E_SUCCESS; } static int i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf) { struct i40e_virtchnl_vf_resource *vf_res = NULL; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); uint32_t len = 0; int ret = I40E_SUCCESS; /* only have 1 VSI by default */ len = sizeof(struct i40e_virtchnl_vf_resource) + I40E_DEFAULT_VF_VSI_NUM * sizeof(struct i40e_virtchnl_vsi_resource); vf_res = rte_zmalloc("i40e_vf_res", len, 0); if (vf_res == NULL) { PMD_DRV_LOG(ERR, "failed to allocate mem"); ret = I40E_ERR_NO_MEMORY; vf_res = NULL; len = 0; goto send_msg; } vf_res->vf_offload_flags = I40E_VIRTCHNL_VF_OFFLOAD_L2 | I40E_VIRTCHNL_VF_OFFLOAD_VLAN; vf_res->max_vectors = hw->func_caps.num_msix_vectors_vf; vf_res->num_queue_pairs = vf->vsi->nb_qps; vf_res->num_vsis = I40E_DEFAULT_VF_VSI_NUM; /* Change below setting if PF host can support more VSIs for VF */ vf_res->vsi_res[0].vsi_type = I40E_VSI_SRIOV; /* As assume Vf only has single VSI now, always return 0 */ vf_res->vsi_res[0].vsi_id = 0; vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps; send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_VF_RESOURCES, ret, (uint8_t *)vf_res, len); rte_free(vf_res); return ret; } static int i40e_pf_host_hmc_config_rxq(struct i40e_hw *hw, struct i40e_pf_vf *vf, struct i40e_virtchnl_rxq_info *rxq, uint8_t crcstrip) { int err = I40E_SUCCESS; struct i40e_hmc_obj_rxq rx_ctx; uint16_t abs_queue_id = vf->vsi->base_queue + rxq->queue_id; /* Clear the context structure first */ memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); rx_ctx.dbuff = rxq->databuffer_size >> I40E_RXQ_CTX_DBUFF_SHIFT; rx_ctx.hbuff = rxq->hdr_size >> I40E_RXQ_CTX_HBUFF_SHIFT; rx_ctx.base = rxq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT; rx_ctx.qlen = rxq->ring_len; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC rx_ctx.dsize = 1; #endif if (rxq->splithdr_enabled) { rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_ALL; rx_ctx.dtype = i40e_header_split_enabled; } else { rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE; rx_ctx.dtype = i40e_header_split_none; } rx_ctx.rxmax = rxq->max_pkt_size; rx_ctx.tphrdesc_ena = 1; rx_ctx.tphwdesc_ena = 1; rx_ctx.tphdata_ena = 1; rx_ctx.tphhead_ena = 1; rx_ctx.lrxqthresh = 2; rx_ctx.crcstrip = crcstrip; rx_ctx.l2tsel = 1; rx_ctx.prefena = 1; err = i40e_clear_lan_rx_queue_context(hw, abs_queue_id); if (err != I40E_SUCCESS) return err; err = i40e_set_lan_rx_queue_context(hw, abs_queue_id, &rx_ctx); return err; } static int i40e_pf_host_hmc_config_txq(struct i40e_hw *hw, struct i40e_pf_vf *vf, struct i40e_virtchnl_txq_info *txq) { int err = I40E_SUCCESS; struct i40e_hmc_obj_txq tx_ctx; uint32_t qtx_ctl; uint16_t abs_queue_id = vf->vsi->base_queue + txq->queue_id; /* clear the context structure first */ memset(&tx_ctx, 0, sizeof(tx_ctx)); tx_ctx.new_context = 1; tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT; tx_ctx.qlen = txq->ring_len; tx_ctx.rdylist = rte_le_to_cpu_16(vf->vsi->info.qs_handle[0]); err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id); if (err != I40E_SUCCESS) return err; err = i40e_set_lan_tx_queue_context(hw, abs_queue_id, &tx_ctx); if (err != I40E_SUCCESS) return err; /* bind queue with VF function, since TX/QX will appear in pair, * so only has QTX_CTL to set. */ qtx_ctl = (I40E_QTX_CTL_VF_QUEUE << I40E_QTX_CTL_PFVF_Q_SHIFT) | ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) & I40E_QTX_CTL_PF_INDX_MASK) | (((vf->vf_idx + hw->func_caps.vf_base_id) << I40E_QTX_CTL_VFVM_INDX_SHIFT) & I40E_QTX_CTL_VFVM_INDX_MASK); I40E_WRITE_REG(hw, I40E_QTX_CTL(abs_queue_id), qtx_ctl); I40E_WRITE_FLUSH(hw); return I40E_SUCCESS; } static int i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); struct i40e_vsi *vsi = vf->vsi; struct i40e_virtchnl_vsi_queue_config_info *vc_vqci = (struct i40e_virtchnl_vsi_queue_config_info *)msg; struct i40e_virtchnl_queue_pair_info *vc_qpi; int i, ret = I40E_SUCCESS; if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps || vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP || msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci, vc_vqci->num_queue_pairs)) { PMD_DRV_LOG(ERR, "vsi_queue_config_info argument wrong\n"); ret = I40E_ERR_PARAM; goto send_msg; } vc_qpi = vc_vqci->qpair; for (i = 0; i < vc_vqci->num_queue_pairs; i++) { if (vc_qpi[i].rxq.queue_id > vsi->nb_qps - 1 || vc_qpi[i].txq.queue_id > vsi->nb_qps - 1) { ret = I40E_ERR_PARAM; goto send_msg; } /* * Apply VF RX queue setting to HMC. * If the opcode is I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT, * then the extra information of * 'struct i40e_virtchnl_queue_pair_extra_info' is needed, * otherwise set the last parameter to NULL. */ if (i40e_pf_host_hmc_config_rxq(hw, vf, &vc_qpi[i].rxq, I40E_CFG_CRCSTRIP_DEFAULT) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Configure RX queue HMC failed"); ret = I40E_ERR_PARAM; goto send_msg; } /* Apply VF TX queue setting to HMC */ if (i40e_pf_host_hmc_config_txq(hw, vf, &vc_qpi[i].txq) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Configure TX queue HMC failed"); ret = I40E_ERR_PARAM; goto send_msg; } } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_config_vsi_queues_ext(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); struct i40e_vsi *vsi = vf->vsi; struct i40e_virtchnl_vsi_queue_config_ext_info *vc_vqcei = (struct i40e_virtchnl_vsi_queue_config_ext_info *)msg; struct i40e_virtchnl_queue_pair_ext_info *vc_qpei; int i, ret = I40E_SUCCESS; if (!msg || vc_vqcei->num_queue_pairs > vsi->nb_qps || vc_vqcei->num_queue_pairs > I40E_MAX_VSI_QP || msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqcei, vc_vqcei->num_queue_pairs)) { PMD_DRV_LOG(ERR, "vsi_queue_config_ext_info argument wrong\n"); ret = I40E_ERR_PARAM; goto send_msg; } vc_qpei = vc_vqcei->qpair; for (i = 0; i < vc_vqcei->num_queue_pairs; i++) { if (vc_qpei[i].rxq.queue_id > vsi->nb_qps - 1 || vc_qpei[i].txq.queue_id > vsi->nb_qps - 1) { ret = I40E_ERR_PARAM; goto send_msg; } /* * Apply VF RX queue setting to HMC. * If the opcode is I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT, * then the extra information of * 'struct i40e_virtchnl_queue_pair_ext_info' is needed, * otherwise set the last parameter to NULL. */ if (i40e_pf_host_hmc_config_rxq(hw, vf, &vc_qpei[i].rxq, vc_qpei[i].rxq_ext.crcstrip) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Configure RX queue HMC failed"); ret = I40E_ERR_PARAM; goto send_msg; } /* Apply VF TX queue setting to HMC */ if (i40e_pf_host_hmc_config_txq(hw, vf, &vc_qpei[i].txq) != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Configure TX queue HMC failed"); ret = I40E_ERR_PARAM; goto send_msg; } } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_irq_map_info *irqmap = (struct i40e_virtchnl_irq_map_info *)msg; if (msg == NULL || msglen < sizeof(struct i40e_virtchnl_irq_map_info)) { PMD_DRV_LOG(ERR, "buffer too short"); ret = I40E_ERR_PARAM; goto send_msg; } /* Assume VF only have 1 vector to bind all queues */ if (irqmap->num_vectors != 1) { PMD_DRV_LOG(ERR, "DKDK host only support 1 vector"); ret = I40E_ERR_PARAM; goto send_msg; } if (irqmap->vecmap[0].vector_id == 0) { PMD_DRV_LOG(ERR, "DPDK host don't support use IRQ0"); ret = I40E_ERR_PARAM; goto send_msg; } /* This MSIX intr store the intr in VF range */ vf->vsi->msix_intr = irqmap->vecmap[0].vector_id; /* Don't care how the TX/RX queue mapping with this vector. * Link all VF RX queues together. Only did mapping work. * VF can disable/enable the intr by itself. */ i40e_vsi_queues_bind_intr(vf->vsi); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP, ret, NULL, 0); return ret; } static int i40e_pf_host_switch_queues(struct i40e_pf_vf *vf, struct i40e_virtchnl_queue_select *qsel, bool on) { int ret = I40E_SUCCESS; int i; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); uint16_t baseq = vf->vsi->base_queue; if (qsel->rx_queues + qsel->tx_queues == 0) return I40E_ERR_PARAM; /* always enable RX first and disable last */ /* Enable RX if it's enable */ if (on) { for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++) if (qsel->rx_queues & (1 << i)) { ret = i40e_switch_rx_queue(hw, baseq + i, on); if (ret != I40E_SUCCESS) return ret; } } /* Enable/Disable TX */ for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++) if (qsel->tx_queues & (1 << i)) { ret = i40e_switch_tx_queue(hw, baseq + i, on); if (ret != I40E_SUCCESS) return ret; } /* disable RX last if it's disable */ if (!on) { /* disable RX */ for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++) if (qsel->rx_queues & (1 << i)) { ret = i40e_switch_rx_queue(hw, baseq + i, on); if (ret != I40E_SUCCESS) return ret; } } return ret; } static int i40e_pf_host_process_cmd_enable_queues(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_queue_select *q_sel = (struct i40e_virtchnl_queue_select *)msg; if (msg == NULL || msglen != sizeof(*q_sel)) { ret = I40E_ERR_PARAM; goto send_msg; } ret = i40e_pf_host_switch_queues(vf, q_sel, true); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_queue_select *q_sel = (struct i40e_virtchnl_queue_select *)msg; if (msg == NULL || msglen != sizeof(*q_sel)) { ret = I40E_ERR_PARAM; goto send_msg; } ret = i40e_pf_host_switch_queues(vf, q_sel, false); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_ether_addr_list *addr_list = (struct i40e_virtchnl_ether_addr_list *)msg; struct i40e_mac_filter_info filter; int i; struct ether_addr *mac; memset(&filter, 0 , sizeof(struct i40e_mac_filter_info)); if (msg == NULL || msglen <= sizeof(*addr_list)) { PMD_DRV_LOG(ERR, "add_ether_address argument too short"); ret = I40E_ERR_PARAM; goto send_msg; } for (i = 0; i < addr_list->num_elements; i++) { mac = (struct ether_addr *)(addr_list->list[i].addr); (void)rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN); filter.filter_type = RTE_MACVLAN_PERFECT_MATCH; if(!is_valid_assigned_ether_addr(mac) || i40e_vsi_add_mac(vf->vsi, &filter)) { ret = I40E_ERR_INVALID_MAC_ADDR; goto send_msg; } } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_ether_addr_list *addr_list = (struct i40e_virtchnl_ether_addr_list *)msg; int i; struct ether_addr *mac; if (msg == NULL || msglen <= sizeof(*addr_list)) { PMD_DRV_LOG(ERR, "delete_ether_address argument too short"); ret = I40E_ERR_PARAM; goto send_msg; } for (i = 0; i < addr_list->num_elements; i++) { mac = (struct ether_addr *)(addr_list->list[i].addr); if(!is_valid_assigned_ether_addr(mac) || i40e_vsi_delete_mac(vf->vsi, mac)) { ret = I40E_ERR_INVALID_MAC_ADDR; goto send_msg; } } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_vlan_filter_list *vlan_filter_list = (struct i40e_virtchnl_vlan_filter_list *)msg; int i; uint16_t *vid; if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) { PMD_DRV_LOG(ERR, "add_vlan argument too short"); ret = I40E_ERR_PARAM; goto send_msg; } vid = vlan_filter_list->vlan_id; for (i = 0; i < vlan_filter_list->num_elements; i++) { ret = i40e_vsi_add_vlan(vf->vsi, vid[i]); if(ret != I40E_SUCCESS) goto send_msg; } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_ADD_VLAN, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_vlan_filter_list *vlan_filter_list = (struct i40e_virtchnl_vlan_filter_list *)msg; int i; uint16_t *vid; if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) { PMD_DRV_LOG(ERR, "delete_vlan argument too short"); ret = I40E_ERR_PARAM; goto send_msg; } vid = vlan_filter_list->vlan_id; for (i = 0; i < vlan_filter_list->num_elements; i++) { ret = i40e_vsi_delete_vlan(vf->vsi, vid[i]); if(ret != I40E_SUCCESS) goto send_msg; } send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_DEL_VLAN, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_config_promisc_mode( struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_promisc_info *promisc = (struct i40e_virtchnl_promisc_info *)msg; struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf); bool unicast = FALSE, multicast = FALSE; if (msg == NULL || msglen != sizeof(*promisc)) { ret = I40E_ERR_PARAM; goto send_msg; } if (promisc->flags & I40E_FLAG_VF_UNICAST_PROMISC) unicast = TRUE; ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vf->vsi->seid, unicast, NULL); if (ret != I40E_SUCCESS) goto send_msg; if (promisc->flags & I40E_FLAG_VF_MULTICAST_PROMISC) multicast = TRUE; ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid, multicast, NULL); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf) { i40e_update_vsi_stats(vf->vsi); i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_STATS, I40E_SUCCESS, (uint8_t *)&vf->vsi->eth_stats, sizeof(vf->vsi->eth_stats)); return I40E_SUCCESS; } static void i40e_pf_host_process_cmd_get_link_status(struct i40e_pf_vf *vf) { struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(vf->pf->main_vsi); /* Update link status first to acquire latest link change */ i40e_dev_link_update(dev, 1); i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_LINK_STAT, I40E_SUCCESS, (uint8_t *)&dev->data->dev_link, sizeof(struct rte_eth_link)); } static int i40e_pf_host_process_cmd_cfg_vlan_offload( struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_vlan_offload_info *offload = (struct i40e_virtchnl_vlan_offload_info *)msg; if (msg == NULL || msglen != sizeof(*offload)) { ret = I40E_ERR_PARAM; goto send_msg; } ret = i40e_vsi_config_vlan_stripping(vf->vsi, !!offload->enable_vlan_strip); if (ret != 0) PMD_DRV_LOG(ERR, "Failed to configure vlan stripping"); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD, ret, NULL, 0); return ret; } static int i40e_pf_host_process_cmd_cfg_pvid(struct i40e_pf_vf *vf, uint8_t *msg, uint16_t msglen) { int ret = I40E_SUCCESS; struct i40e_virtchnl_pvid_info *tpid_info = (struct i40e_virtchnl_pvid_info *)msg; if (msg == NULL || msglen != sizeof(*tpid_info)) { ret = I40E_ERR_PARAM; goto send_msg; } ret = i40e_vsi_vlan_pvid_set(vf->vsi, &tpid_info->info); send_msg: i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_CFG_VLAN_PVID, ret, NULL, 0); return ret; } void i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev, uint16_t abs_vf_id, uint32_t opcode, __rte_unused uint32_t retval, uint8_t *msg, uint16_t msglen) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_pf_vf *vf; /* AdminQ will pass absolute VF id, transfer to internal vf id */ uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id; if (!dev || vf_id > pf->vf_num - 1 || !pf->vfs) { PMD_DRV_LOG(ERR, "invalid argument"); return; } vf = &pf->vfs[vf_id]; if (!vf->vsi) { PMD_DRV_LOG(ERR, "NO VSI associated with VF found"); i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_ERR_NO_AVAILABLE_VSI, NULL, 0); return; } switch (opcode) { case I40E_VIRTCHNL_OP_VERSION : PMD_DRV_LOG(INFO, "OP_VERSION received"); i40e_pf_host_process_cmd_version(vf); break; case I40E_VIRTCHNL_OP_RESET_VF : PMD_DRV_LOG(INFO, "OP_RESET_VF received"); i40e_pf_host_process_cmd_reset_vf(vf); break; case I40E_VIRTCHNL_OP_GET_VF_RESOURCES: PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received"); i40e_pf_host_process_cmd_get_vf_resource(vf); break; case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES: PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received"); i40e_pf_host_process_cmd_config_vsi_queues(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT: PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES_EXT received"); i40e_pf_host_process_cmd_config_vsi_queues_ext(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received"); i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_ENABLE_QUEUES: PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received"); i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_DISABLE_QUEUES: PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received"); i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS: PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received"); i40e_pf_host_process_cmd_add_ether_address(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS: PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received"); i40e_pf_host_process_cmd_del_ether_address(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_ADD_VLAN: PMD_DRV_LOG(INFO, "OP_ADD_VLAN received"); i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_DEL_VLAN: PMD_DRV_LOG(INFO, "OP_DEL_VLAN received"); i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received"); i40e_pf_host_process_cmd_config_promisc_mode(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_GET_STATS: PMD_DRV_LOG(INFO, "OP_GET_STATS received"); i40e_pf_host_process_cmd_get_stats(vf); break; case I40E_VIRTCHNL_OP_GET_LINK_STAT: PMD_DRV_LOG(INFO, "OP_GET_LINK_STAT received"); i40e_pf_host_process_cmd_get_link_status(vf); break; case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD: PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received"); i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen); break; case I40E_VIRTCHNL_OP_CFG_VLAN_PVID: PMD_DRV_LOG(INFO, "OP_CFG_VLAN_PVID received"); i40e_pf_host_process_cmd_cfg_pvid(vf, msg, msglen); break; /* Don't add command supported below, which will * return an error code. */ case I40E_VIRTCHNL_OP_FCOE: PMD_DRV_LOG(ERR, "OP_FCOE received, not supported"); default: PMD_DRV_LOG(ERR, "%u received, not supported", opcode); i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_ERR_PARAM, NULL, 0); break; } } int i40e_pf_host_init(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); int ret, i; uint32_t val; PMD_INIT_FUNC_TRACE(); /** * return if SRIOV not enabled, VF number not configured or * no queue assigned. */ if(!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0) return I40E_SUCCESS; /* Allocate memory to store VF structure */ pf->vfs = rte_zmalloc("i40e_pf_vf",sizeof(*pf->vfs) * pf->vf_num, 0); if(pf->vfs == NULL) return -ENOMEM; /* Disable irq0 for VFR event */ i40e_pf_disable_irq0(hw); /* Disable VF link status interrupt */ val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM); val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK; I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val); I40E_WRITE_FLUSH(hw); for (i = 0; i < pf->vf_num; i++) { pf->vfs[i].pf = pf; pf->vfs[i].state = I40E_VF_INACTIVE; pf->vfs[i].vf_idx = i; ret = i40e_pf_host_vf_reset(&pf->vfs[i], 0); if (ret != I40E_SUCCESS) goto fail; } /* restore irq0 */ i40e_pf_enable_irq0(hw); return I40E_SUCCESS; fail: rte_free(pf->vfs); i40e_pf_enable_irq0(hw); return ret; } int i40e_pf_host_uninit(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); uint32_t val; PMD_INIT_FUNC_TRACE(); /** * return if SRIOV not enabled, VF number not configured or * no queue assigned. */ if ((!hw->func_caps.sr_iov_1_1) || (pf->vf_num == 0) || (pf->vf_nb_qps == 0)) return I40E_SUCCESS; /* free memory to store VF structure */ rte_free(pf->vfs); pf->vfs = NULL; /* Disable irq0 for VFR event */ i40e_pf_disable_irq0(hw); /* Disable VF link status interrupt */ val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM); val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK; I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val); I40E_WRITE_FLUSH(hw); return I40E_SUCCESS; } ================================================ FILE: drivers/net/i40e/i40e_pf.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _I40E_PF_H_ #define _I40E_PF_H_ /* VERSION info to exchange between VF and PF host. In case VF works with * ND kernel driver, it reads I40E_VIRTCHNL_VERSION_MAJOR/MINOR. In * case works with DPDK host, it reads version below. Then VF realize who it * is talking to and use proper language to communicate. * */ #define I40E_DPDK_SIGNATURE ('D' << 24 | 'P' << 16 | 'D' << 8 | 'K') #define I40E_DPDK_VERSION_MAJOR I40E_DPDK_SIGNATURE #define I40E_DPDK_VERSION_MINOR 0 /* Default setting on number of VSIs that VF can contain */ #define I40E_DEFAULT_VF_VSI_NUM 1 #define I40E_DPDK_OFFSET 0x100 enum i40e_pf_vfr_state { I40E_PF_VFR_INPROGRESS = 0, I40E_PF_VFR_COMPLETED = 1, }; /* DPDK pf driver specific command to VF */ enum i40e_virtchnl_ops_dpdk { /* * Keep some gap between Linux PF commands and * DPDK PF extended commands. */ I40E_VIRTCHNL_OP_GET_LINK_STAT = I40E_VIRTCHNL_OP_VERSION + I40E_DPDK_OFFSET, I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD, I40E_VIRTCHNL_OP_CFG_VLAN_PVID, I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT, }; /* A structure to support extended info of a receive queue. */ struct i40e_virtchnl_rxq_ext_info { uint8_t crcstrip; }; /* * A structure to support extended info of queue pairs, an additional field * is added, comparing to original 'struct i40e_virtchnl_queue_pair_info'. */ struct i40e_virtchnl_queue_pair_ext_info { /* vsi_id and queue_id should be identical for both rx and tx queues.*/ struct i40e_virtchnl_txq_info txq; struct i40e_virtchnl_rxq_info rxq; struct i40e_virtchnl_rxq_ext_info rxq_ext; }; /* * A structure to support extended info of VSI queue pairs, * 'struct i40e_virtchnl_queue_pair_ext_info' is used, see its original * of 'struct i40e_virtchnl_queue_pair_info'. */ struct i40e_virtchnl_vsi_queue_config_ext_info { uint16_t vsi_id; uint16_t num_queue_pairs; struct i40e_virtchnl_queue_pair_ext_info qpair[0]; }; struct i40e_virtchnl_vlan_offload_info { uint16_t vsi_id; uint8_t enable_vlan_strip; uint8_t reserved; }; /* * Macro to calculate the memory size for configuring VSI queues * via virtual channel. */ #define I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(x, n) \ (sizeof(*(x)) + sizeof((x)->qpair[0]) * (n)) /* * I40E_VIRTCHNL_OP_CFG_VLAN_PVID * VF sends this message to enable/disable pvid. If it's * enable op, needs to specify the pvid. PF returns status * code in retval. */ struct i40e_virtchnl_pvid_info { uint16_t vsi_id; struct i40e_vsi_vlan_pvid_info info; }; int i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset); void i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev, uint16_t abs_vf_id, uint32_t opcode, __rte_unused uint32_t retval, uint8_t *msg, uint16_t msglen); int i40e_pf_host_init(struct rte_eth_dev *dev); int i40e_pf_host_uninit(struct rte_eth_dev *dev); #endif /* _I40E_PF_H_ */ ================================================ FILE: drivers/net/i40e/i40e_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "i40e_logs.h" #include "base/i40e_prototype.h" #include "base/i40e_type.h" #include "i40e_ethdev.h" #include "i40e_rxtx.h" #define I40E_MIN_RING_DESC 64 #define I40E_MAX_RING_DESC 4096 #define I40E_ALIGN 128 #define DEFAULT_TX_RS_THRESH 32 #define DEFAULT_TX_FREE_THRESH 32 #define I40E_MAX_PKT_TYPE 256 #define I40E_TX_MAX_BURST 32 #define I40E_DMA_MEM_ALIGN 4096 #define I40E_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ ETH_TXQ_FLAGS_NOOFFLOADS) #define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS) #define I40E_TX_CKSUM_OFFLOAD_MASK ( \ PKT_TX_IP_CKSUM | \ PKT_TX_L4_MASK | \ PKT_TX_OUTER_IP_CKSUM) #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) #define RTE_MBUF_DATA_DMA_ADDR(mb) \ ((uint64_t)((mb)->buf_physaddr + (mb)->data_off)) static const struct rte_memzone * i40e_ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id); static uint16_t i40e_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); static inline void i40e_rxd_to_vlan_tci(struct rte_mbuf *mb, volatile union i40e_rx_desc *rxdp) { if (rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len) & (1 << I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) { mb->ol_flags |= PKT_RX_VLAN_PKT; mb->vlan_tci = rte_le_to_cpu_16(rxdp->wb.qword0.lo_dword.l2tag1); PMD_RX_LOG(DEBUG, "Descriptor l2tag1: %u", rte_le_to_cpu_16(rxdp->wb.qword0.lo_dword.l2tag1)); } else { mb->vlan_tci = 0; } #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC if (rte_le_to_cpu_16(rxdp->wb.qword2.ext_status) & (1 << I40E_RX_DESC_EXT_STATUS_L2TAG2P_SHIFT)) { mb->ol_flags |= PKT_RX_QINQ_PKT; mb->vlan_tci_outer = mb->vlan_tci; mb->vlan_tci = rte_le_to_cpu_16(rxdp->wb.qword2.l2tag2_2); PMD_RX_LOG(DEBUG, "Descriptor l2tag2_1: %u, l2tag2_2: %u", rte_le_to_cpu_16(rxdp->wb.qword2.l2tag2_1), rte_le_to_cpu_16(rxdp->wb.qword2.l2tag2_2)); } else { mb->vlan_tci_outer = 0; } #endif PMD_RX_LOG(DEBUG, "Mbuf vlan_tci: %u, vlan_tci_outer: %u", mb->vlan_tci, mb->vlan_tci_outer); } /* Translate the rx descriptor status to pkt flags */ static inline uint64_t i40e_rxd_status_to_pkt_flags(uint64_t qword) { uint64_t flags; /* Check if RSS_HASH */ flags = (((qword >> I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) & I40E_RX_DESC_FLTSTAT_RSS_HASH) == I40E_RX_DESC_FLTSTAT_RSS_HASH) ? PKT_RX_RSS_HASH : 0; /* Check if FDIR Match */ flags |= (qword & (1 << I40E_RX_DESC_STATUS_FLM_SHIFT) ? PKT_RX_FDIR : 0); return flags; } static inline uint64_t i40e_rxd_error_to_pkt_flags(uint64_t qword) { uint64_t flags = 0; uint64_t error_bits = (qword >> I40E_RXD_QW1_ERROR_SHIFT); #define I40E_RX_ERR_BITS 0x3f if (likely((error_bits & I40E_RX_ERR_BITS) == 0)) return flags; /* If RXE bit set, all other status bits are meaningless */ if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_RXE_SHIFT))) { flags |= PKT_RX_MAC_ERR; return flags; } /* If RECIPE bit set, all other status indications should be ignored */ if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_RECIPE_SHIFT))) { flags |= PKT_RX_RECIP_ERR; return flags; } if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_HBO_SHIFT))) flags |= PKT_RX_HBUF_OVERFLOW; if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_IPE_SHIFT))) flags |= PKT_RX_IP_CKSUM_BAD; if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_L4E_SHIFT))) flags |= PKT_RX_L4_CKSUM_BAD; if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_EIPE_SHIFT))) flags |= PKT_RX_EIP_CKSUM_BAD; if (unlikely(error_bits & (1 << I40E_RX_DESC_ERROR_OVERSIZE_SHIFT))) flags |= PKT_RX_OVERSIZE; return flags; } /* Function to check and set the ieee1588 timesync index and get the * appropriate flags. */ #ifdef RTE_LIBRTE_IEEE1588 static inline uint64_t i40e_get_iee15888_flags(struct rte_mbuf *mb, uint64_t qword) { uint64_t pkt_flags = 0; uint16_t tsyn = (qword & (I40E_RXD_QW1_STATUS_TSYNVALID_MASK | I40E_RXD_QW1_STATUS_TSYNINDX_MASK)) >> I40E_RX_DESC_STATUS_TSYNINDX_SHIFT; #ifdef RTE_NEXT_ABI if ((mb->packet_type & RTE_PTYPE_L2_MASK) == RTE_PTYPE_L2_ETHER_TIMESYNC) pkt_flags = PKT_RX_IEEE1588_PTP; #endif if (tsyn & 0x04) { pkt_flags |= PKT_RX_IEEE1588_TMST; mb->timesync = tsyn & 0x03; } return pkt_flags; } #endif #ifdef RTE_NEXT_ABI /* For each value it means, datasheet of hardware can tell more details */ static inline uint32_t i40e_rxd_pkt_type_mapping(uint8_t ptype) { static const uint32_t ptype_table[UINT8_MAX] __rte_cache_aligned = { /* L2 types */ /* [0] reserved */ [1] = RTE_PTYPE_L2_ETHER, [2] = RTE_PTYPE_L2_ETHER_TIMESYNC, /* [3] - [5] reserved */ [6] = RTE_PTYPE_L2_ETHER_LLDP, /* [7] - [10] reserved */ [11] = RTE_PTYPE_L2_ETHER_ARP, /* [12] - [21] reserved */ /* Non tunneled IPv4 */ [22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, [23] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG, [24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_UDP, /* [25] reserved */ [26] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_TCP, [27] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_SCTP, [28] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_L4_ICMP, /* IPv4 --> IPv4 */ [29] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [30] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [31] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [32] reserved */ [33] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [35] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> IPv6 */ [36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [37] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [38] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [39] reserved */ [40] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [41] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [42] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN */ [43] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT, /* IPv4 --> GRE/Teredo/VXLAN --> IPv4 */ [44] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [45] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [46] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [47] reserved */ [48] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [49] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [50] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN --> IPv6 */ [51] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [52] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [53] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [54] reserved */ [55] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [56] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [57] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN --> MAC */ [58] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER, /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */ [59] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [60] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [61] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [62] reserved */ [63] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [64] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [65] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */ [66] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [67] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [68] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [69] reserved */ [70] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [71] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [72] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN */ [73] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN, /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */ [74] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [75] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [76] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [77] reserved */ [78] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [79] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv4 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */ [81] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [82] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [83] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [84] reserved */ [85] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [86] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [87] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* Non tunneled IPv6 */ [88] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_FRAG, [89] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_NONFRAG, [90] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_UDP, /* [91] reserved */ [92] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_TCP, [93] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_SCTP, [94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_L4_ICMP, /* IPv6 --> IPv4 */ [95] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [97] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [98] reserved */ [99] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [100] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [101] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> IPv6 */ [102] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [103] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [104] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [105] reserved */ [106] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [107] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [108] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN */ [109] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT, /* IPv6 --> GRE/Teredo/VXLAN --> IPv4 */ [110] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [111] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [112] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [113] reserved */ [114] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [115] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [116] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN --> IPv6 */ [117] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [118] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [119] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [120] reserved */ [121] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [122] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [123] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN --> MAC */ [124] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER, /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv4 */ [125] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [126] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [127] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [128] reserved */ [129] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [130] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [131] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN --> MAC --> IPv6 */ [132] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [133] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [134] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [135] reserved */ [136] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [137] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [138] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN */ [139] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN, /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv4 */ [140] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [141] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [142] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [143] reserved */ [144] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [145] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [146] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* IPv6 --> GRE/Teredo/VXLAN --> MAC/VLAN --> IPv6 */ [147] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_FRAG, [148] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_NONFRAG, [149] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_UDP, /* [150] reserved */ [151] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_TCP, [152] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_SCTP, [153] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_TUNNEL_GRENAT | RTE_PTYPE_INNER_L2_ETHER_VLAN | RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | RTE_PTYPE_INNER_L4_ICMP, /* All others reserved */ }; return ptype_table[ptype]; } #else /* RTE_NEXT_ABI */ /* Translate pkt types to pkt flags */ static inline uint64_t i40e_rxd_ptype_to_pkt_flags(uint64_t qword) { uint8_t ptype = (uint8_t)((qword & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT); static const uint64_t ip_ptype_map[I40E_MAX_PKT_TYPE] = { 0, /* PTYPE 0 */ 0, /* PTYPE 1 */ PKT_RX_IEEE1588_PTP, /* PTYPE 2 */ 0, /* PTYPE 3 */ 0, /* PTYPE 4 */ 0, /* PTYPE 5 */ 0, /* PTYPE 6 */ 0, /* PTYPE 7 */ 0, /* PTYPE 8 */ 0, /* PTYPE 9 */ 0, /* PTYPE 10 */ 0, /* PTYPE 11 */ 0, /* PTYPE 12 */ 0, /* PTYPE 13 */ 0, /* PTYPE 14 */ 0, /* PTYPE 15 */ 0, /* PTYPE 16 */ 0, /* PTYPE 17 */ 0, /* PTYPE 18 */ 0, /* PTYPE 19 */ 0, /* PTYPE 20 */ 0, /* PTYPE 21 */ PKT_RX_IPV4_HDR, /* PTYPE 22 */ PKT_RX_IPV4_HDR, /* PTYPE 23 */ PKT_RX_IPV4_HDR, /* PTYPE 24 */ 0, /* PTYPE 25 */ PKT_RX_IPV4_HDR, /* PTYPE 26 */ PKT_RX_IPV4_HDR, /* PTYPE 27 */ PKT_RX_IPV4_HDR, /* PTYPE 28 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 29 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 30 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 31 */ 0, /* PTYPE 32 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 33 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 34 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 35 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 36 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 37 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 38 */ 0, /* PTYPE 39 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 40 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 41 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 42 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 43 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 44 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 45 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 46 */ 0, /* PTYPE 47 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 48 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 49 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 50 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 51 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 52 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 53 */ 0, /* PTYPE 54 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 55 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 56 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 57 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 58 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 59 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 60 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 61 */ 0, /* PTYPE 62 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 63 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 64 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 65 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 66 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 67 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 68 */ 0, /* PTYPE 69 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 70 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 71 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 72 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 73 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 74 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 75 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 76 */ 0, /* PTYPE 77 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 78 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 79 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 80 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 81 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 82 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 83 */ 0, /* PTYPE 84 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 85 */ PKT_RX_TUNNEL_IPV4_HDR, /* PTYPE 86 */ PKT_RX_IPV4_HDR_EXT, /* PTYPE 87 */ PKT_RX_IPV6_HDR, /* PTYPE 88 */ PKT_RX_IPV6_HDR, /* PTYPE 89 */ PKT_RX_IPV6_HDR, /* PTYPE 90 */ 0, /* PTYPE 91 */ PKT_RX_IPV6_HDR, /* PTYPE 92 */ PKT_RX_IPV6_HDR, /* PTYPE 93 */ PKT_RX_IPV6_HDR, /* PTYPE 94 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 95 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 96 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 97 */ 0, /* PTYPE 98 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 99 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 100 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 101 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 102 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 103 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 104 */ 0, /* PTYPE 105 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 106 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 107 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 108 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 109 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 110 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 111 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 112 */ 0, /* PTYPE 113 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 114 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 115 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 116 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 117 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 118 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 119 */ 0, /* PTYPE 120 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 121 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 122 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 123 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 124 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 125 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 126 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 127 */ 0, /* PTYPE 128 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 129 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 130 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 131 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 132 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 133 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 134 */ 0, /* PTYPE 135 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 136 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 137 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 138 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 139 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 140 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 141 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 142 */ 0, /* PTYPE 143 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 144 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 145 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 146 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 147 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 148 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 149 */ 0, /* PTYPE 150 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 151 */ PKT_RX_TUNNEL_IPV6_HDR, /* PTYPE 152 */ PKT_RX_IPV6_HDR_EXT, /* PTYPE 153 */ 0, /* PTYPE 154 */ 0, /* PTYPE 155 */ 0, /* PTYPE 156 */ 0, /* PTYPE 157 */ 0, /* PTYPE 158 */ 0, /* PTYPE 159 */ 0, /* PTYPE 160 */ 0, /* PTYPE 161 */ 0, /* PTYPE 162 */ 0, /* PTYPE 163 */ 0, /* PTYPE 164 */ 0, /* PTYPE 165 */ 0, /* PTYPE 166 */ 0, /* PTYPE 167 */ 0, /* PTYPE 168 */ 0, /* PTYPE 169 */ 0, /* PTYPE 170 */ 0, /* PTYPE 171 */ 0, /* PTYPE 172 */ 0, /* PTYPE 173 */ 0, /* PTYPE 174 */ 0, /* PTYPE 175 */ 0, /* PTYPE 176 */ 0, /* PTYPE 177 */ 0, /* PTYPE 178 */ 0, /* PTYPE 179 */ 0, /* PTYPE 180 */ 0, /* PTYPE 181 */ 0, /* PTYPE 182 */ 0, /* PTYPE 183 */ 0, /* PTYPE 184 */ 0, /* PTYPE 185 */ 0, /* PTYPE 186 */ 0, /* PTYPE 187 */ 0, /* PTYPE 188 */ 0, /* PTYPE 189 */ 0, /* PTYPE 190 */ 0, /* PTYPE 191 */ 0, /* PTYPE 192 */ 0, /* PTYPE 193 */ 0, /* PTYPE 194 */ 0, /* PTYPE 195 */ 0, /* PTYPE 196 */ 0, /* PTYPE 197 */ 0, /* PTYPE 198 */ 0, /* PTYPE 199 */ 0, /* PTYPE 200 */ 0, /* PTYPE 201 */ 0, /* PTYPE 202 */ 0, /* PTYPE 203 */ 0, /* PTYPE 204 */ 0, /* PTYPE 205 */ 0, /* PTYPE 206 */ 0, /* PTYPE 207 */ 0, /* PTYPE 208 */ 0, /* PTYPE 209 */ 0, /* PTYPE 210 */ 0, /* PTYPE 211 */ 0, /* PTYPE 212 */ 0, /* PTYPE 213 */ 0, /* PTYPE 214 */ 0, /* PTYPE 215 */ 0, /* PTYPE 216 */ 0, /* PTYPE 217 */ 0, /* PTYPE 218 */ 0, /* PTYPE 219 */ 0, /* PTYPE 220 */ 0, /* PTYPE 221 */ 0, /* PTYPE 222 */ 0, /* PTYPE 223 */ 0, /* PTYPE 224 */ 0, /* PTYPE 225 */ 0, /* PTYPE 226 */ 0, /* PTYPE 227 */ 0, /* PTYPE 228 */ 0, /* PTYPE 229 */ 0, /* PTYPE 230 */ 0, /* PTYPE 231 */ 0, /* PTYPE 232 */ 0, /* PTYPE 233 */ 0, /* PTYPE 234 */ 0, /* PTYPE 235 */ 0, /* PTYPE 236 */ 0, /* PTYPE 237 */ 0, /* PTYPE 238 */ 0, /* PTYPE 239 */ 0, /* PTYPE 240 */ 0, /* PTYPE 241 */ 0, /* PTYPE 242 */ 0, /* PTYPE 243 */ 0, /* PTYPE 244 */ 0, /* PTYPE 245 */ 0, /* PTYPE 246 */ 0, /* PTYPE 247 */ 0, /* PTYPE 248 */ 0, /* PTYPE 249 */ 0, /* PTYPE 250 */ 0, /* PTYPE 251 */ 0, /* PTYPE 252 */ 0, /* PTYPE 253 */ 0, /* PTYPE 254 */ 0, /* PTYPE 255 */ }; return ip_ptype_map[ptype]; } #endif /* RTE_NEXT_ABI */ #define I40E_RX_DESC_EXT_STATUS_FLEXBH_MASK 0x03 #define I40E_RX_DESC_EXT_STATUS_FLEXBH_FD_ID 0x01 #define I40E_RX_DESC_EXT_STATUS_FLEXBH_FLEX 0x02 #define I40E_RX_DESC_EXT_STATUS_FLEXBL_MASK 0x03 #define I40E_RX_DESC_EXT_STATUS_FLEXBL_FLEX 0x01 static inline uint64_t i40e_rxd_build_fdir(volatile union i40e_rx_desc *rxdp, struct rte_mbuf *mb) { uint64_t flags = 0; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC uint16_t flexbh, flexbl; flexbh = (rte_le_to_cpu_32(rxdp->wb.qword2.ext_status) >> I40E_RX_DESC_EXT_STATUS_FLEXBH_SHIFT) & I40E_RX_DESC_EXT_STATUS_FLEXBH_MASK; flexbl = (rte_le_to_cpu_32(rxdp->wb.qword2.ext_status) >> I40E_RX_DESC_EXT_STATUS_FLEXBL_SHIFT) & I40E_RX_DESC_EXT_STATUS_FLEXBL_MASK; if (flexbh == I40E_RX_DESC_EXT_STATUS_FLEXBH_FD_ID) { mb->hash.fdir.hi = rte_le_to_cpu_32(rxdp->wb.qword3.hi_dword.fd_id); flags |= PKT_RX_FDIR_ID; } else if (flexbh == I40E_RX_DESC_EXT_STATUS_FLEXBH_FLEX) { mb->hash.fdir.hi = rte_le_to_cpu_32(rxdp->wb.qword3.hi_dword.flex_bytes_hi); flags |= PKT_RX_FDIR_FLX; } if (flexbl == I40E_RX_DESC_EXT_STATUS_FLEXBL_FLEX) { mb->hash.fdir.lo = rte_le_to_cpu_32(rxdp->wb.qword3.lo_dword.flex_bytes_lo); flags |= PKT_RX_FDIR_FLX; } #else mb->hash.fdir.hi = rte_le_to_cpu_32(rxdp->wb.qword0.hi_dword.fd_id); flags |= PKT_RX_FDIR_ID; #endif return flags; } static inline void i40e_txd_enable_checksum(uint64_t ol_flags, uint32_t *td_cmd, uint32_t *td_offset, union i40e_tx_offload tx_offload, uint32_t *cd_tunneling) { /* UDP tunneling packet TX checksum offload */ if (ol_flags & PKT_TX_OUTER_IP_CKSUM) { *td_offset |= (tx_offload.outer_l2_len >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; if (ol_flags & PKT_TX_OUTER_IP_CKSUM) *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV4; else if (ol_flags & PKT_TX_OUTER_IPV4) *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV4_NO_CSUM; else if (ol_flags & PKT_TX_OUTER_IPV6) *cd_tunneling |= I40E_TX_CTX_EXT_IP_IPV6; /* Now set the ctx descriptor fields */ *cd_tunneling |= (tx_offload.outer_l3_len >> 2) << I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT | (tx_offload.l2_len >> 1) << I40E_TXD_CTX_QW0_NATLEN_SHIFT; } else *td_offset |= (tx_offload.l2_len >> 1) << I40E_TX_DESC_LENGTH_MACLEN_SHIFT; /* Enable L3 checksum offloads */ if (ol_flags & PKT_TX_IP_CKSUM) { *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4_CSUM; *td_offset |= (tx_offload.l3_len >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT; } else if (ol_flags & PKT_TX_IPV4) { *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV4; *td_offset |= (tx_offload.l3_len >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT; } else if (ol_flags & PKT_TX_IPV6) { *td_cmd |= I40E_TX_DESC_CMD_IIPT_IPV6; *td_offset |= (tx_offload.l3_len >> 2) << I40E_TX_DESC_LENGTH_IPLEN_SHIFT; } if (ol_flags & PKT_TX_TCP_SEG) { *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP; *td_offset |= (tx_offload.l4_len >> 2) << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; return; } /* Enable L4 checksum offloads */ switch (ol_flags & PKT_TX_L4_MASK) { case PKT_TX_TCP_CKSUM: *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_TCP; *td_offset |= (sizeof(struct tcp_hdr) >> 2) << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; break; case PKT_TX_SCTP_CKSUM: *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_SCTP; *td_offset |= (sizeof(struct sctp_hdr) >> 2) << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; break; case PKT_TX_UDP_CKSUM: *td_cmd |= I40E_TX_DESC_CMD_L4T_EOFT_UDP; *td_offset |= (sizeof(struct udp_hdr) >> 2) << I40E_TX_DESC_LENGTH_L4_FC_LEN_SHIFT; break; default: break; } } static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return m; } /* Construct the tx flags */ static inline uint64_t i40e_build_ctob(uint32_t td_cmd, uint32_t td_offset, unsigned int size, uint32_t td_tag) { return rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DATA | ((uint64_t)td_cmd << I40E_TXD_QW1_CMD_SHIFT) | ((uint64_t)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) | ((uint64_t)size << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) | ((uint64_t)td_tag << I40E_TXD_QW1_L2TAG1_SHIFT)); } static inline int i40e_xmit_cleanup(struct i40e_tx_queue *txq) { struct i40e_tx_entry *sw_ring = txq->sw_ring; volatile struct i40e_tx_desc *txd = txq->tx_ring; uint16_t last_desc_cleaned = txq->last_desc_cleaned; uint16_t nb_tx_desc = txq->nb_tx_desc; uint16_t desc_to_clean_to; uint16_t nb_tx_to_clean; desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_rs_thresh); if (desc_to_clean_to >= nb_tx_desc) desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc); desc_to_clean_to = sw_ring[desc_to_clean_to].last_id; if ((txd[desc_to_clean_to].cmd_type_offset_bsz & rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) != rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) { PMD_TX_FREE_LOG(DEBUG, "TX descriptor %4u is not done " "(port=%d queue=%d)", desc_to_clean_to, txq->port_id, txq->queue_id); return -1; } if (last_desc_cleaned > desc_to_clean_to) nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) + desc_to_clean_to); else nb_tx_to_clean = (uint16_t)(desc_to_clean_to - last_desc_cleaned); txd[desc_to_clean_to].cmd_type_offset_bsz = 0; txq->last_desc_cleaned = desc_to_clean_to; txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean); return 0; } static inline int #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC check_rx_burst_bulk_alloc_preconditions(struct i40e_rx_queue *rxq) #else check_rx_burst_bulk_alloc_preconditions(__rte_unused struct i40e_rx_queue *rxq) #endif { int ret = 0; #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC if (!(rxq->rx_free_thresh >= RTE_PMD_I40E_RX_MAX_BURST)) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->rx_free_thresh=%d, " "RTE_PMD_I40E_RX_MAX_BURST=%d", rxq->rx_free_thresh, RTE_PMD_I40E_RX_MAX_BURST); ret = -EINVAL; } else if (!(rxq->rx_free_thresh < rxq->nb_rx_desc)) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->rx_free_thresh=%d, " "rxq->nb_rx_desc=%d", rxq->rx_free_thresh, rxq->nb_rx_desc); ret = -EINVAL; } else if (rxq->nb_rx_desc % rxq->rx_free_thresh != 0) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->nb_rx_desc=%d, " "rxq->rx_free_thresh=%d", rxq->nb_rx_desc, rxq->rx_free_thresh); ret = -EINVAL; } else if (!(rxq->nb_rx_desc < (I40E_MAX_RING_DESC - RTE_PMD_I40E_RX_MAX_BURST))) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->nb_rx_desc=%d, " "I40E_MAX_RING_DESC=%d, " "RTE_PMD_I40E_RX_MAX_BURST=%d", rxq->nb_rx_desc, I40E_MAX_RING_DESC, RTE_PMD_I40E_RX_MAX_BURST); ret = -EINVAL; } #else ret = -EINVAL; #endif return ret; } #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC #define I40E_LOOK_AHEAD 8 #if (I40E_LOOK_AHEAD != 8) #error "PMD I40E: I40E_LOOK_AHEAD must be 8\n" #endif static inline int i40e_rx_scan_hw_ring(struct i40e_rx_queue *rxq) { volatile union i40e_rx_desc *rxdp; struct i40e_rx_entry *rxep; struct rte_mbuf *mb; uint16_t pkt_len; uint64_t qword1; uint32_t rx_status; int32_t s[I40E_LOOK_AHEAD], nb_dd; int32_t i, j, nb_rx = 0; uint64_t pkt_flags; rxdp = &rxq->rx_ring[rxq->rx_tail]; rxep = &rxq->sw_ring[rxq->rx_tail]; qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; /* Make sure there is at least 1 packet to receive */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT))) return 0; /** * Scan LOOK_AHEAD descriptors at a time to determine which * descriptors reference packets that are ready to be received. */ for (i = 0; i < RTE_PMD_I40E_RX_MAX_BURST; i+=I40E_LOOK_AHEAD, rxdp += I40E_LOOK_AHEAD, rxep += I40E_LOOK_AHEAD) { /* Read desc statuses backwards to avoid race condition */ for (j = I40E_LOOK_AHEAD - 1; j >= 0; j--) { qword1 = rte_le_to_cpu_64(\ rxdp[j].wb.qword1.status_error_len); s[j] = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; } /* Compute how many status bits were set */ for (j = 0, nb_dd = 0; j < I40E_LOOK_AHEAD; j++) nb_dd += s[j] & (1 << I40E_RX_DESC_STATUS_DD_SHIFT); nb_rx += nb_dd; /* Translate descriptor info to mbuf parameters */ for (j = 0; j < nb_dd; j++) { mb = rxep[j].mbuf; qword1 = rte_le_to_cpu_64(\ rxdp[j].wb.qword1.status_error_len); pkt_len = ((qword1 & I40E_RXD_QW1_LENGTH_PBUF_MASK) >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT) - rxq->crc_len; mb->data_len = pkt_len; mb->pkt_len = pkt_len; mb->ol_flags = 0; i40e_rxd_to_vlan_tci(mb, &rxdp[j]); pkt_flags = i40e_rxd_status_to_pkt_flags(qword1); pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1); #ifdef RTE_NEXT_ABI mb->packet_type = i40e_rxd_pkt_type_mapping((uint8_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT)); #else pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1); mb->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT); #endif /* RTE_NEXT_ABI */ if (pkt_flags & PKT_RX_RSS_HASH) mb->hash.rss = rte_le_to_cpu_32(\ rxdp[j].wb.qword0.hi_dword.rss); if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxdp[j], mb); #ifdef RTE_LIBRTE_IEEE1588 pkt_flags |= i40e_get_iee15888_flags(mb, qword1); #endif mb->ol_flags |= pkt_flags; } for (j = 0; j < I40E_LOOK_AHEAD; j++) rxq->rx_stage[i + j] = rxep[j].mbuf; if (nb_dd != I40E_LOOK_AHEAD) break; } /* Clear software ring entries */ for (i = 0; i < nb_rx; i++) rxq->sw_ring[rxq->rx_tail + i].mbuf = NULL; return nb_rx; } static inline uint16_t i40e_rx_fill_from_stage(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { uint16_t i; struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail]; nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail); for (i = 0; i < nb_pkts; i++) rx_pkts[i] = stage[i]; rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts); rxq->rx_next_avail = (uint16_t)(rxq->rx_next_avail + nb_pkts); return nb_pkts; } static inline int i40e_rx_alloc_bufs(struct i40e_rx_queue *rxq) { volatile union i40e_rx_desc *rxdp; struct i40e_rx_entry *rxep; struct rte_mbuf *mb; uint16_t alloc_idx, i; uint64_t dma_addr; int diag; /* Allocate buffers in bulk */ alloc_idx = (uint16_t)(rxq->rx_free_trigger - (rxq->rx_free_thresh - 1)); rxep = &(rxq->sw_ring[alloc_idx]); diag = rte_mempool_get_bulk(rxq->mp, (void *)rxep, rxq->rx_free_thresh); if (unlikely(diag != 0)) { PMD_DRV_LOG(ERR, "Failed to get mbufs in bulk"); return -ENOMEM; } rxdp = &rxq->rx_ring[alloc_idx]; for (i = 0; i < rxq->rx_free_thresh; i++) { if (likely(i < (rxq->rx_free_thresh - 1))) /* Prefetch next mbuf */ rte_prefetch0(rxep[i + 1].mbuf); mb = rxep[i].mbuf; rte_mbuf_refcnt_set(mb, 1); mb->next = NULL; mb->data_off = RTE_PKTMBUF_HEADROOM; mb->nb_segs = 1; mb->port = rxq->port_id; dma_addr = rte_cpu_to_le_64(\ RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb)); rxdp[i].read.hdr_addr = 0; rxdp[i].read.pkt_addr = dma_addr; } /* Update rx tail regsiter */ rte_wmb(); I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->rx_free_trigger); rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_trigger + rxq->rx_free_thresh); if (rxq->rx_free_trigger >= rxq->nb_rx_desc) rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1); return 0; } static inline uint16_t rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct i40e_rx_queue *rxq = (struct i40e_rx_queue *)rx_queue; uint16_t nb_rx = 0; if (!nb_pkts) return 0; if (rxq->rx_nb_avail) return i40e_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); nb_rx = (uint16_t)i40e_rx_scan_hw_ring(rxq); rxq->rx_next_avail = 0; rxq->rx_nb_avail = nb_rx; rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_rx); if (rxq->rx_tail > rxq->rx_free_trigger) { if (i40e_rx_alloc_bufs(rxq) != 0) { uint16_t i, j; PMD_RX_LOG(DEBUG, "Rx mbuf alloc failed for " "port_id=%u, queue_id=%u", rxq->port_id, rxq->queue_id); rxq->rx_nb_avail = 0; rxq->rx_tail = (uint16_t)(rxq->rx_tail - nb_rx); for (i = 0, j = rxq->rx_tail; i < nb_rx; i++, j++) rxq->sw_ring[j].mbuf = rxq->rx_stage[i]; return 0; } } if (rxq->rx_tail >= rxq->nb_rx_desc) rxq->rx_tail = 0; if (rxq->rx_nb_avail) return i40e_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); return 0; } static uint16_t i40e_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { uint16_t nb_rx = 0, n, count; if (unlikely(nb_pkts == 0)) return 0; if (likely(nb_pkts <= RTE_PMD_I40E_RX_MAX_BURST)) return rx_recv_pkts(rx_queue, rx_pkts, nb_pkts); while (nb_pkts) { n = RTE_MIN(nb_pkts, RTE_PMD_I40E_RX_MAX_BURST); count = rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n); nb_rx = (uint16_t)(nb_rx + count); nb_pkts = (uint16_t)(nb_pkts - count); if (count < n) break; } return nb_rx; } #endif /* RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC */ uint16_t i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct i40e_rx_queue *rxq; volatile union i40e_rx_desc *rx_ring; volatile union i40e_rx_desc *rxdp; union i40e_rx_desc rxd; struct i40e_rx_entry *sw_ring; struct i40e_rx_entry *rxe; struct rte_mbuf *rxm; struct rte_mbuf *nmb; uint16_t nb_rx; uint32_t rx_status; uint64_t qword1; uint16_t rx_packet_len; uint16_t rx_id, nb_hold; uint64_t dma_addr; uint64_t pkt_flags; nb_rx = 0; nb_hold = 0; rxq = rx_queue; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; while (nb_rx < nb_pkts) { rxdp = &rx_ring[rx_id]; qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; /* Check the DD bit first */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT))) break; nmb = rte_rxmbuf_alloc(rxq->mp); if (unlikely(!nmb)) break; rxd = *rxdp; nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (unlikely(rx_id == rxq->nb_rx_desc)) rx_id = 0; /* Prefetch next mbuf */ rte_prefetch0(sw_ring[rx_id].mbuf); /** * When next RX descriptor is on a cache line boundary, * prefetch the next 4 RX descriptors and next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_prefetch0(&rx_ring[rx_id]); rte_prefetch0(&sw_ring[rx_id]); } rxm = rxe->mbuf; rxe->mbuf = nmb; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->read.hdr_addr = 0; rxdp->read.pkt_addr = dma_addr; rx_packet_len = ((qword1 & I40E_RXD_QW1_LENGTH_PBUF_MASK) >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT) - rxq->crc_len; rxm->data_off = RTE_PKTMBUF_HEADROOM; rte_prefetch0(RTE_PTR_ADD(rxm->buf_addr, RTE_PKTMBUF_HEADROOM)); rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = rx_packet_len; rxm->data_len = rx_packet_len; rxm->port = rxq->port_id; rxm->ol_flags = 0; i40e_rxd_to_vlan_tci(rxm, &rxd); pkt_flags = i40e_rxd_status_to_pkt_flags(qword1); pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1); #ifdef RTE_NEXT_ABI rxm->packet_type = i40e_rxd_pkt_type_mapping((uint8_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT)); #else pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1); rxm->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT); #endif /* RTE_NEXT_ABI */ if (pkt_flags & PKT_RX_RSS_HASH) rxm->hash.rss = rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss); if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxd, rxm); #ifdef RTE_LIBRTE_IEEE1588 pkt_flags |= i40e_get_iee15888_flags(rxm, qword1); #endif rxm->ol_flags |= pkt_flags; rx_pkts[nb_rx++] = rxm; } rxq->rx_tail = rx_id; /** * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the receive tail register of queue. * Update that register with the value of the last processed RX * descriptor minus 1. */ nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); I40E_PCI_REG_WRITE(rxq->qrx_tail, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return nb_rx; } uint16_t i40e_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct i40e_rx_queue *rxq = rx_queue; volatile union i40e_rx_desc *rx_ring = rxq->rx_ring; volatile union i40e_rx_desc *rxdp; union i40e_rx_desc rxd; struct i40e_rx_entry *sw_ring = rxq->sw_ring; struct i40e_rx_entry *rxe; struct rte_mbuf *first_seg = rxq->pkt_first_seg; struct rte_mbuf *last_seg = rxq->pkt_last_seg; struct rte_mbuf *nmb, *rxm; uint16_t rx_id = rxq->rx_tail; uint16_t nb_rx = 0, nb_hold = 0, rx_packet_len; uint32_t rx_status; uint64_t qword1; uint64_t dma_addr; uint64_t pkt_flags; while (nb_rx < nb_pkts) { rxdp = &rx_ring[rx_id]; qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; /* Check the DD bit */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT))) break; nmb = rte_rxmbuf_alloc(rxq->mp); if (unlikely(!nmb)) break; rxd = *rxdp; nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf */ rte_prefetch0(sw_ring[rx_id].mbuf); /** * When next RX descriptor is on a cache line boundary, * prefetch the next 4 RX descriptors and next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_prefetch0(&rx_ring[rx_id]); rte_prefetch0(&sw_ring[rx_id]); } rxm = rxe->mbuf; rxe->mbuf = nmb; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); /* Set data buffer address and data length of the mbuf */ rxdp->read.hdr_addr = 0; rxdp->read.pkt_addr = dma_addr; rx_packet_len = (qword1 & I40E_RXD_QW1_LENGTH_PBUF_MASK) >> I40E_RXD_QW1_LENGTH_PBUF_SHIFT; rxm->data_len = rx_packet_len; rxm->data_off = RTE_PKTMBUF_HEADROOM; /** * If this is the first buffer of the received packet, set the * pointer to the first mbuf of the packet and initialize its * context. Otherwise, update the total length and the number * of segments of the current scattered packet, and update the * pointer to the last mbuf of the current packet. */ if (!first_seg) { first_seg = rxm; first_seg->nb_segs = 1; first_seg->pkt_len = rx_packet_len; } else { first_seg->pkt_len = (uint16_t)(first_seg->pkt_len + rx_packet_len); first_seg->nb_segs++; last_seg->next = rxm; } /** * If this is not the last buffer of the received packet, * update the pointer to the last mbuf of the current scattered * packet and continue to parse the RX ring. */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_EOF_SHIFT))) { last_seg = rxm; continue; } /** * This is the last buffer of the received packet. If the CRC * is not stripped by the hardware: * - Subtract the CRC length from the total packet length. * - If the last buffer only contains the whole CRC or a part * of it, free the mbuf associated to the last buffer. If part * of the CRC is also contained in the previous mbuf, subtract * the length of that CRC part from the data length of the * previous mbuf. */ rxm->next = NULL; if (unlikely(rxq->crc_len > 0)) { first_seg->pkt_len -= ETHER_CRC_LEN; if (rx_packet_len <= ETHER_CRC_LEN) { rte_pktmbuf_free_seg(rxm); first_seg->nb_segs--; last_seg->data_len = (uint16_t)(last_seg->data_len - (ETHER_CRC_LEN - rx_packet_len)); last_seg->next = NULL; } else rxm->data_len = (uint16_t)(rx_packet_len - ETHER_CRC_LEN); } first_seg->port = rxq->port_id; first_seg->ol_flags = 0; i40e_rxd_to_vlan_tci(first_seg, &rxd); pkt_flags = i40e_rxd_status_to_pkt_flags(qword1); pkt_flags |= i40e_rxd_error_to_pkt_flags(qword1); #ifdef RTE_NEXT_ABI first_seg->packet_type = i40e_rxd_pkt_type_mapping((uint8_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT)); #else pkt_flags |= i40e_rxd_ptype_to_pkt_flags(qword1); first_seg->packet_type = (uint16_t)((qword1 & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT); #endif /* RTE_NEXT_ABI */ if (pkt_flags & PKT_RX_RSS_HASH) rxm->hash.rss = rte_le_to_cpu_32(rxd.wb.qword0.hi_dword.rss); if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxd, rxm); #ifdef RTE_LIBRTE_IEEE1588 pkt_flags |= i40e_get_iee15888_flags(first_seg, qword1); #endif first_seg->ol_flags |= pkt_flags; /* Prefetch data of first segment, if configured to do so. */ rte_prefetch0(RTE_PTR_ADD(first_seg->buf_addr, first_seg->data_off)); rx_pkts[nb_rx++] = first_seg; first_seg = NULL; } /* Record index of the next RX descriptor to probe. */ rxq->rx_tail = rx_id; rxq->pkt_first_seg = first_seg; rxq->pkt_last_seg = last_seg; /** * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. Update the RDT with the value of the last processed RX * descriptor minus 1, to guarantee that the RDT register is never * equal to the RDH register, which creates a "full" ring situtation * from the hardware point of view. */ nb_hold = (uint16_t)(nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { rx_id = (uint16_t)(rx_id == 0 ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); I40E_PCI_REG_WRITE(rxq->qrx_tail, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return nb_rx; } /* Check if the context descriptor is needed for TX offloading */ static inline uint16_t i40e_calc_context_desc(uint64_t flags) { static uint64_t mask = PKT_TX_OUTER_IP_CKSUM | PKT_TX_TCP_SEG | PKT_TX_QINQ_PKT; #ifdef RTE_LIBRTE_IEEE1588 mask |= PKT_TX_IEEE1588_TMST; #endif return ((flags & mask) ? 1 : 0); } /* set i40e TSO context descriptor */ static inline uint64_t i40e_set_tso_ctx(struct rte_mbuf *mbuf, union i40e_tx_offload tx_offload) { uint64_t ctx_desc = 0; uint32_t cd_cmd, hdr_len, cd_tso_len; if (!tx_offload.l4_len) { PMD_DRV_LOG(DEBUG, "L4 length set to 0"); return ctx_desc; } /** * in case of tunneling packet, the outer_l2_len and * outer_l3_len must be 0. */ hdr_len = tx_offload.outer_l2_len + tx_offload.outer_l3_len + tx_offload.l2_len + tx_offload.l3_len + tx_offload.l4_len; cd_cmd = I40E_TX_CTX_DESC_TSO; cd_tso_len = mbuf->pkt_len - hdr_len; ctx_desc |= ((uint64_t)cd_cmd << I40E_TXD_CTX_QW1_CMD_SHIFT) | ((uint64_t)cd_tso_len << I40E_TXD_CTX_QW1_TSO_LEN_SHIFT) | ((uint64_t)mbuf->tso_segsz << I40E_TXD_CTX_QW1_MSS_SHIFT); return ctx_desc; } uint16_t i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct i40e_tx_queue *txq; struct i40e_tx_entry *sw_ring; struct i40e_tx_entry *txe, *txn; volatile struct i40e_tx_desc *txd; volatile struct i40e_tx_desc *txr; struct rte_mbuf *tx_pkt; struct rte_mbuf *m_seg; uint32_t cd_tunneling_params; uint16_t tx_id; uint16_t nb_tx; uint32_t td_cmd; uint32_t td_offset; uint32_t tx_flags; uint32_t td_tag; uint64_t ol_flags; uint16_t nb_used; uint16_t nb_ctx; uint16_t tx_last; uint16_t slen; uint64_t buf_dma_addr; union i40e_tx_offload tx_offload = {0}; txq = tx_queue; sw_ring = txq->sw_ring; txr = txq->tx_ring; tx_id = txq->tx_tail; txe = &sw_ring[tx_id]; /* Check if the descriptor ring needs to be cleaned. */ if (txq->nb_tx_free < txq->tx_free_thresh) i40e_xmit_cleanup(txq); for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { td_cmd = 0; td_tag = 0; td_offset = 0; tx_flags = 0; tx_pkt = *tx_pkts++; RTE_MBUF_PREFETCH_TO_FREE(txe->mbuf); ol_flags = tx_pkt->ol_flags; tx_offload.l2_len = tx_pkt->l2_len; tx_offload.l3_len = tx_pkt->l3_len; tx_offload.outer_l2_len = tx_pkt->outer_l2_len; tx_offload.outer_l3_len = tx_pkt->outer_l3_len; tx_offload.l4_len = tx_pkt->l4_len; tx_offload.tso_segsz = tx_pkt->tso_segsz; /* Calculate the number of context descriptors needed. */ nb_ctx = i40e_calc_context_desc(ol_flags); /** * The number of descriptors that must be allocated for * a packet equals to the number of the segments of that * packet plus 1 context descriptor if needed. */ nb_used = (uint16_t)(tx_pkt->nb_segs + nb_ctx); tx_last = (uint16_t)(tx_id + nb_used - 1); /* Circular ring */ if (tx_last >= txq->nb_tx_desc) tx_last = (uint16_t)(tx_last - txq->nb_tx_desc); if (nb_used > txq->nb_tx_free) { if (i40e_xmit_cleanup(txq) != 0) { if (nb_tx == 0) return 0; goto end_of_tx; } if (unlikely(nb_used > txq->tx_rs_thresh)) { while (nb_used > txq->nb_tx_free) { if (i40e_xmit_cleanup(txq) != 0) { if (nb_tx == 0) return 0; goto end_of_tx; } } } } /* Descriptor based VLAN insertion */ if (ol_flags & (PKT_TX_VLAN_PKT | PKT_TX_QINQ_PKT)) { tx_flags |= tx_pkt->vlan_tci << I40E_TX_FLAG_L2TAG1_SHIFT; tx_flags |= I40E_TX_FLAG_INSERT_VLAN; td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; td_tag = (tx_flags & I40E_TX_FLAG_L2TAG1_MASK) >> I40E_TX_FLAG_L2TAG1_SHIFT; } /* Always enable CRC offload insertion */ td_cmd |= I40E_TX_DESC_CMD_ICRC; /* Enable checksum offloading */ cd_tunneling_params = 0; if (ol_flags & I40E_TX_CKSUM_OFFLOAD_MASK) { i40e_txd_enable_checksum(ol_flags, &td_cmd, &td_offset, tx_offload, &cd_tunneling_params); } if (nb_ctx) { /* Setup TX context descriptor if required */ volatile struct i40e_tx_context_desc *ctx_txd = (volatile struct i40e_tx_context_desc *)\ &txr[tx_id]; uint16_t cd_l2tag2 = 0; uint64_t cd_type_cmd_tso_mss = I40E_TX_DESC_DTYPE_CONTEXT; txn = &sw_ring[txe->next_id]; RTE_MBUF_PREFETCH_TO_FREE(txn->mbuf); if (txe->mbuf != NULL) { rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = NULL; } /* TSO enabled means no timestamp */ if (ol_flags & PKT_TX_TCP_SEG) cd_type_cmd_tso_mss |= i40e_set_tso_ctx(tx_pkt, tx_offload); else { #ifdef RTE_LIBRTE_IEEE1588 if (ol_flags & PKT_TX_IEEE1588_TMST) cd_type_cmd_tso_mss |= ((uint64_t)I40E_TX_CTX_DESC_TSYN << I40E_TXD_CTX_QW1_CMD_SHIFT); #endif } ctx_txd->tunneling_params = rte_cpu_to_le_32(cd_tunneling_params); if (ol_flags & PKT_TX_QINQ_PKT) { cd_l2tag2 = tx_pkt->vlan_tci_outer; cd_type_cmd_tso_mss |= ((uint64_t)I40E_TX_CTX_DESC_IL2TAG2 << I40E_TXD_CTX_QW1_CMD_SHIFT); } ctx_txd->l2tag2 = rte_cpu_to_le_16(cd_l2tag2); ctx_txd->type_cmd_tso_mss = rte_cpu_to_le_64(cd_type_cmd_tso_mss); PMD_TX_LOG(DEBUG, "mbuf: %p, TCD[%u]:\n" "tunneling_params: %#x;\n" "l2tag2: %#hx;\n" "rsvd: %#hx;\n" "type_cmd_tso_mss: %#"PRIx64";\n", tx_pkt, tx_id, ctx_txd->tunneling_params, ctx_txd->l2tag2, ctx_txd->rsvd, ctx_txd->type_cmd_tso_mss); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; } m_seg = tx_pkt; do { txd = &txr[tx_id]; txn = &sw_ring[txe->next_id]; if (txe->mbuf) rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = m_seg; /* Setup TX Descriptor */ slen = m_seg->data_len; buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(m_seg); PMD_TX_LOG(DEBUG, "mbuf: %p, TDD[%u]:\n" "buf_dma_addr: %#"PRIx64";\n" "td_cmd: %#x;\n" "td_offset: %#x;\n" "td_len: %u;\n" "td_tag: %#x;\n", tx_pkt, tx_id, buf_dma_addr, td_cmd, td_offset, slen, td_tag); txd->buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txd->cmd_type_offset_bsz = i40e_build_ctob(td_cmd, td_offset, slen, td_tag); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; m_seg = m_seg->next; } while (m_seg != NULL); /* The last packet data descriptor needs End Of Packet (EOP) */ td_cmd |= I40E_TX_DESC_CMD_EOP; txq->nb_tx_used = (uint16_t)(txq->nb_tx_used + nb_used); txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used); if (txq->nb_tx_used >= txq->tx_rs_thresh) { PMD_TX_FREE_LOG(DEBUG, "Setting RS bit on TXD id=" "%4u (port=%d queue=%d)", tx_last, txq->port_id, txq->queue_id); td_cmd |= I40E_TX_DESC_CMD_RS; /* Update txq RS bit counters */ txq->nb_tx_used = 0; } txd->cmd_type_offset_bsz |= rte_cpu_to_le_64(((uint64_t)td_cmd) << I40E_TXD_QW1_CMD_SHIFT); } end_of_tx: rte_wmb(); PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) tx_id, (unsigned) nb_tx); I40E_PCI_REG_WRITE(txq->qtx_tail, tx_id); txq->tx_tail = tx_id; return nb_tx; } static inline int __attribute__((always_inline)) i40e_tx_free_bufs(struct i40e_tx_queue *txq) { struct i40e_tx_entry *txep; uint16_t i; if ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz & rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) != rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE)) return 0; txep = &(txq->sw_ring[txq->tx_next_dd - (txq->tx_rs_thresh - 1)]); for (i = 0; i < txq->tx_rs_thresh; i++) rte_prefetch0((txep + i)->mbuf); if (!(txq->txq_flags & (uint32_t)ETH_TXQ_FLAGS_NOREFCOUNT)) { for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) { rte_mempool_put(txep->mbuf->pool, txep->mbuf); txep->mbuf = NULL; } } else { for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) { rte_pktmbuf_free_seg(txep->mbuf); txep->mbuf = NULL; } } txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); if (txq->tx_next_dd >= txq->nb_tx_desc) txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); return txq->tx_rs_thresh; } #define I40E_TD_CMD (I40E_TX_DESC_CMD_ICRC |\ I40E_TX_DESC_CMD_EOP) /* Populate 4 descriptors with data from 4 mbufs */ static inline void tx4(volatile struct i40e_tx_desc *txdp, struct rte_mbuf **pkts) { uint64_t dma_addr; uint32_t i; for (i = 0; i < 4; i++, txdp++, pkts++) { dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts); txdp->buffer_addr = rte_cpu_to_le_64(dma_addr); txdp->cmd_type_offset_bsz = i40e_build_ctob((uint32_t)I40E_TD_CMD, 0, (*pkts)->data_len, 0); } } /* Populate 1 descriptor with data from 1 mbuf */ static inline void tx1(volatile struct i40e_tx_desc *txdp, struct rte_mbuf **pkts) { uint64_t dma_addr; dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts); txdp->buffer_addr = rte_cpu_to_le_64(dma_addr); txdp->cmd_type_offset_bsz = i40e_build_ctob((uint32_t)I40E_TD_CMD, 0, (*pkts)->data_len, 0); } /* Fill hardware descriptor ring with mbuf data */ static inline void i40e_tx_fill_hw_ring(struct i40e_tx_queue *txq, struct rte_mbuf **pkts, uint16_t nb_pkts) { volatile struct i40e_tx_desc *txdp = &(txq->tx_ring[txq->tx_tail]); struct i40e_tx_entry *txep = &(txq->sw_ring[txq->tx_tail]); const int N_PER_LOOP = 4; const int N_PER_LOOP_MASK = N_PER_LOOP - 1; int mainpart, leftover; int i, j; mainpart = (nb_pkts & ((uint32_t) ~N_PER_LOOP_MASK)); leftover = (nb_pkts & ((uint32_t) N_PER_LOOP_MASK)); for (i = 0; i < mainpart; i += N_PER_LOOP) { for (j = 0; j < N_PER_LOOP; ++j) { (txep + i + j)->mbuf = *(pkts + i + j); } tx4(txdp + i, pkts + i); } if (unlikely(leftover > 0)) { for (i = 0; i < leftover; ++i) { (txep + mainpart + i)->mbuf = *(pkts + mainpart + i); tx1(txdp + mainpart + i, pkts + mainpart + i); } } } static inline uint16_t tx_xmit_pkts(struct i40e_tx_queue *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { volatile struct i40e_tx_desc *txr = txq->tx_ring; uint16_t n = 0; /** * Begin scanning the H/W ring for done descriptors when the number * of available descriptors drops below tx_free_thresh. For each done * descriptor, free the associated buffer. */ if (txq->nb_tx_free < txq->tx_free_thresh) i40e_tx_free_bufs(txq); /* Use available descriptor only */ nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts); if (unlikely(!nb_pkts)) return 0; txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts); if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) { n = (uint16_t)(txq->nb_tx_desc - txq->tx_tail); i40e_tx_fill_hw_ring(txq, tx_pkts, n); txr[txq->tx_next_rs].cmd_type_offset_bsz |= rte_cpu_to_le_64(((uint64_t)I40E_TX_DESC_CMD_RS) << I40E_TXD_QW1_CMD_SHIFT); txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_tail = 0; } /* Fill hardware descriptor ring with mbuf data */ i40e_tx_fill_hw_ring(txq, tx_pkts + n, (uint16_t)(nb_pkts - n)); txq->tx_tail = (uint16_t)(txq->tx_tail + (nb_pkts - n)); /* Determin if RS bit needs to be set */ if (txq->tx_tail > txq->tx_next_rs) { txr[txq->tx_next_rs].cmd_type_offset_bsz |= rte_cpu_to_le_64(((uint64_t)I40E_TX_DESC_CMD_RS) << I40E_TXD_QW1_CMD_SHIFT); txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh); if (txq->tx_next_rs >= txq->nb_tx_desc) txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); } if (txq->tx_tail >= txq->nb_tx_desc) txq->tx_tail = 0; /* Update the tx tail register */ rte_wmb(); I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail); return nb_pkts; } static uint16_t i40e_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { uint16_t nb_tx = 0; if (likely(nb_pkts <= I40E_TX_MAX_BURST)) return tx_xmit_pkts((struct i40e_tx_queue *)tx_queue, tx_pkts, nb_pkts); while (nb_pkts) { uint16_t ret, num = (uint16_t)RTE_MIN(nb_pkts, I40E_TX_MAX_BURST); ret = tx_xmit_pkts((struct i40e_tx_queue *)tx_queue, &tx_pkts[nb_tx], num); nb_tx = (uint16_t)(nb_tx + ret); nb_pkts = (uint16_t)(nb_pkts - ret); if (ret < num) break; } return nb_tx; } /* * Find the VSI the queue belongs to. 'queue_idx' is the queue index * application used, which assume having sequential ones. But from driver's * perspective, it's different. For example, q0 belongs to FDIR VSI, q1-q64 * to MAIN VSI, , q65-96 to SRIOV VSIs, q97-128 to VMDQ VSIs. For application * running on host, q1-64 and q97-128 can be used, total 96 queues. They can * use queue_idx from 0 to 95 to access queues, while real queue would be * different. This function will do a queue mapping to find VSI the queue * belongs to. */ static struct i40e_vsi* i40e_pf_get_vsi_by_qindex(struct i40e_pf *pf, uint16_t queue_idx) { /* the queue in MAIN VSI range */ if (queue_idx < pf->main_vsi->nb_qps) return pf->main_vsi; queue_idx -= pf->main_vsi->nb_qps; /* queue_idx is greater than VMDQ VSIs range */ if (queue_idx > pf->nb_cfg_vmdq_vsi * pf->vmdq_nb_qps - 1) { PMD_INIT_LOG(ERR, "queue_idx out of range. VMDQ configured?"); return NULL; } return pf->vmdq[queue_idx / pf->vmdq_nb_qps].vsi; } static uint16_t i40e_get_queue_offset_by_qindex(struct i40e_pf *pf, uint16_t queue_idx) { /* the queue in MAIN VSI range */ if (queue_idx < pf->main_vsi->nb_qps) return queue_idx; /* It's VMDQ queues */ queue_idx -= pf->main_vsi->nb_qps; if (pf->nb_cfg_vmdq_vsi) return queue_idx % pf->vmdq_nb_qps; else { PMD_INIT_LOG(ERR, "Fail to get queue offset"); return (uint16_t)(-1); } } int i40e_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct i40e_rx_queue *rxq; int err = -1; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; err = i40e_alloc_rx_queue_mbufs(rxq); if (err) { PMD_DRV_LOG(ERR, "Failed to allocate RX queue mbuf"); return err; } rte_wmb(); /* Init the RX tail regieter. */ I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); err = i40e_switch_rx_queue(hw, rxq->reg_idx, TRUE); if (err) { PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on", rx_queue_id); i40e_rx_queue_release_mbufs(rxq); i40e_reset_rx_queue(rxq); } } return err; } int i40e_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct i40e_rx_queue *rxq; int err; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; /* * rx_queue_id is queue id aplication refers to, while * rxq->reg_idx is the real queue index. */ err = i40e_switch_rx_queue(hw, rxq->reg_idx, FALSE); if (err) { PMD_DRV_LOG(ERR, "Failed to switch RX queue %u off", rx_queue_id); return err; } i40e_rx_queue_release_mbufs(rxq); i40e_reset_rx_queue(rxq); } return 0; } int i40e_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) { int err = -1; struct i40e_tx_queue *txq; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (tx_queue_id < dev->data->nb_tx_queues) { txq = dev->data->tx_queues[tx_queue_id]; /* * tx_queue_id is queue id aplication refers to, while * rxq->reg_idx is the real queue index. */ err = i40e_switch_tx_queue(hw, txq->reg_idx, TRUE); if (err) PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on", tx_queue_id); } return err; } int i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct i40e_tx_queue *txq; int err; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (tx_queue_id < dev->data->nb_tx_queues) { txq = dev->data->tx_queues[tx_queue_id]; /* * tx_queue_id is queue id aplication refers to, while * txq->reg_idx is the real queue index. */ err = i40e_switch_tx_queue(hw, txq->reg_idx, FALSE); if (err) { PMD_DRV_LOG(ERR, "Failed to switch TX queue %u of", tx_queue_id); return err; } i40e_tx_queue_release_mbufs(txq); i40e_reset_tx_queue(txq); } return 0; } int i40e_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { struct i40e_vsi *vsi; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_rx_queue *rxq; const struct rte_memzone *rz; uint32_t ring_size; uint16_t len; int use_def_burst_func = 1; if (hw->mac.type == I40E_MAC_VF) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); vsi = &vf->vsi; } else vsi = i40e_pf_get_vsi_by_qindex(pf, queue_idx); if (vsi == NULL) { PMD_DRV_LOG(ERR, "VSI not available or queue " "index exceeds the maximum"); return I40E_ERR_PARAM; } if (((nb_desc * sizeof(union i40e_rx_desc)) % I40E_ALIGN) != 0 || (nb_desc > I40E_MAX_RING_DESC) || (nb_desc < I40E_MIN_RING_DESC)) { PMD_DRV_LOG(ERR, "Number (%u) of receive descriptors is " "invalid", nb_desc); return I40E_ERR_PARAM; } /* Free memory if needed */ if (dev->data->rx_queues[queue_idx]) { i40e_dev_rx_queue_release(dev->data->rx_queues[queue_idx]); dev->data->rx_queues[queue_idx] = NULL; } /* Allocate the rx queue data structure */ rxq = rte_zmalloc_socket("i40e rx queue", sizeof(struct i40e_rx_queue), RTE_CACHE_LINE_SIZE, socket_id); if (!rxq) { PMD_DRV_LOG(ERR, "Failed to allocate memory for " "rx queue data structure"); return (-ENOMEM); } rxq->mp = mp; rxq->nb_rx_desc = nb_desc; rxq->rx_free_thresh = rx_conf->rx_free_thresh; rxq->queue_id = queue_idx; if (hw->mac.type == I40E_MAC_VF) rxq->reg_idx = queue_idx; else /* PF device */ rxq->reg_idx = vsi->base_queue + i40e_get_queue_offset_by_qindex(pf, queue_idx); rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); rxq->drop_en = rx_conf->rx_drop_en; rxq->vsi = vsi; rxq->rx_deferred_start = rx_conf->rx_deferred_start; /* Allocate the maximun number of RX ring hardware descriptor. */ ring_size = sizeof(union i40e_rx_desc) * I40E_MAX_RING_DESC; ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); rz = i40e_ring_dma_zone_reserve(dev, "rx_ring", queue_idx, ring_size, socket_id); if (!rz) { i40e_dev_rx_queue_release(rxq); PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX"); return (-ENOMEM); } /* Zero all the descriptors in the ring. */ memset(rz->addr, 0, ring_size); #ifdef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); #else rxq->rx_ring_phys_addr = (uint64_t)rz->phys_addr; #endif rxq->rx_ring = (union i40e_rx_desc *)rz->addr; #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC len = (uint16_t)(nb_desc + RTE_PMD_I40E_RX_MAX_BURST); #else len = nb_desc; #endif /* Allocate the software ring. */ rxq->sw_ring = rte_zmalloc_socket("i40e rx sw ring", sizeof(struct i40e_rx_entry) * len, RTE_CACHE_LINE_SIZE, socket_id); if (!rxq->sw_ring) { i40e_dev_rx_queue_release(rxq); PMD_DRV_LOG(ERR, "Failed to allocate memory for SW ring"); return (-ENOMEM); } i40e_reset_rx_queue(rxq); rxq->q_set = TRUE; dev->data->rx_queues[queue_idx] = rxq; use_def_burst_func = check_rx_burst_bulk_alloc_preconditions(rxq); if (!use_def_burst_func && !dev->data->scattered_rx) { #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are " "satisfied. Rx Burst Bulk Alloc function will be " "used on port=%d, queue=%d.", rxq->port_id, rxq->queue_id); dev->rx_pkt_burst = i40e_recv_pkts_bulk_alloc; #endif /* RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC */ } else { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are " "not satisfied, Scattered Rx is requested, " "or RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC is " "not enabled on port=%d, queue=%d.", rxq->port_id, rxq->queue_id); } return 0; } void i40e_dev_rx_queue_release(void *rxq) { struct i40e_rx_queue *q = (struct i40e_rx_queue *)rxq; if (!q) { PMD_DRV_LOG(DEBUG, "Pointer to rxq is NULL"); return; } i40e_rx_queue_release_mbufs(q); rte_free(q->sw_ring); rte_free(q); } uint32_t i40e_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { #define I40E_RXQ_SCAN_INTERVAL 4 volatile union i40e_rx_desc *rxdp; struct i40e_rx_queue *rxq; uint16_t desc = 0; if (unlikely(rx_queue_id >= dev->data->nb_rx_queues)) { PMD_DRV_LOG(ERR, "Invalid RX queue id %u", rx_queue_id); return 0; } rxq = dev->data->rx_queues[rx_queue_id]; rxdp = &(rxq->rx_ring[rxq->rx_tail]); while ((desc < rxq->nb_rx_desc) && ((rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len) & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT) & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) { /** * Check the DD bit of a rx descriptor of each 4 in a group, * to avoid checking too frequently and downgrading performance * too much. */ desc += I40E_RXQ_SCAN_INTERVAL; rxdp += I40E_RXQ_SCAN_INTERVAL; if (rxq->rx_tail + desc >= rxq->nb_rx_desc) rxdp = &(rxq->rx_ring[rxq->rx_tail + desc - rxq->nb_rx_desc]); } return desc; } int i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset) { volatile union i40e_rx_desc *rxdp; struct i40e_rx_queue *rxq = rx_queue; uint16_t desc; int ret; if (unlikely(offset >= rxq->nb_rx_desc)) { PMD_DRV_LOG(ERR, "Invalid RX queue id %u", offset); return 0; } desc = rxq->rx_tail + offset; if (desc >= rxq->nb_rx_desc) desc -= rxq->nb_rx_desc; rxdp = &(rxq->rx_ring[desc]); ret = !!(((rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len) & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT) & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)); return ret; } int i40e_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct i40e_vsi *vsi; struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_tx_queue *txq; const struct rte_memzone *tz; uint32_t ring_size; uint16_t tx_rs_thresh, tx_free_thresh; if (hw->mac.type == I40E_MAC_VF) { struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); vsi = &vf->vsi; } else vsi = i40e_pf_get_vsi_by_qindex(pf, queue_idx); if (vsi == NULL) { PMD_DRV_LOG(ERR, "VSI is NULL, or queue index (%u) " "exceeds the maximum", queue_idx); return I40E_ERR_PARAM; } if (((nb_desc * sizeof(struct i40e_tx_desc)) % I40E_ALIGN) != 0 || (nb_desc > I40E_MAX_RING_DESC) || (nb_desc < I40E_MIN_RING_DESC)) { PMD_DRV_LOG(ERR, "Number (%u) of transmit descriptors is " "invalid", nb_desc); return I40E_ERR_PARAM; } /** * The following two parameters control the setting of the RS bit on * transmit descriptors. TX descriptors will have their RS bit set * after txq->tx_rs_thresh descriptors have been used. The TX * descriptor ring will be cleaned after txq->tx_free_thresh * descriptors are used or if the number of descriptors required to * transmit a packet is greater than the number of free TX descriptors. * * The following constraints must be satisfied: * - tx_rs_thresh must be greater than 0. * - tx_rs_thresh must be less than the size of the ring minus 2. * - tx_rs_thresh must be less than or equal to tx_free_thresh. * - tx_rs_thresh must be a divisor of the ring size. * - tx_free_thresh must be greater than 0. * - tx_free_thresh must be less than the size of the ring minus 3. * * One descriptor in the TX ring is used as a sentinel to avoid a H/W * race condition, hence the maximum threshold constraints. When set * to zero use default values. */ tx_rs_thresh = (uint16_t)((tx_conf->tx_rs_thresh) ? tx_conf->tx_rs_thresh : DEFAULT_TX_RS_THRESH); tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH); if (tx_rs_thresh >= (nb_desc - 2)) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than the " "number of TX descriptors minus 2. " "(tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return I40E_ERR_PARAM; } if (tx_free_thresh >= (nb_desc - 3)) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than the " "tx_free_thresh must be less than the " "number of TX descriptors minus 3. " "(tx_free_thresh=%u port=%d queue=%d)", (unsigned int)tx_free_thresh, (int)dev->data->port_id, (int)queue_idx); return I40E_ERR_PARAM; } if (tx_rs_thresh > tx_free_thresh) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than or " "equal to tx_free_thresh. (tx_free_thresh=%u" " tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_free_thresh, (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return I40E_ERR_PARAM; } if ((nb_desc % tx_rs_thresh) != 0) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be a divisor of the " "number of TX descriptors. (tx_rs_thresh=%u" " port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return I40E_ERR_PARAM; } if ((tx_rs_thresh > 1) && (tx_conf->tx_thresh.wthresh != 0)) { PMD_INIT_LOG(ERR, "TX WTHRESH must be set to 0 if " "tx_rs_thresh is greater than 1. " "(tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return I40E_ERR_PARAM; } /* Free memory if needed. */ if (dev->data->tx_queues[queue_idx]) { i40e_dev_tx_queue_release(dev->data->tx_queues[queue_idx]); dev->data->tx_queues[queue_idx] = NULL; } /* Allocate the TX queue data structure. */ txq = rte_zmalloc_socket("i40e tx queue", sizeof(struct i40e_tx_queue), RTE_CACHE_LINE_SIZE, socket_id); if (!txq) { PMD_DRV_LOG(ERR, "Failed to allocate memory for " "tx queue structure"); return (-ENOMEM); } /* Allocate TX hardware ring descriptors. */ ring_size = sizeof(struct i40e_tx_desc) * I40E_MAX_RING_DESC; ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); tz = i40e_ring_dma_zone_reserve(dev, "tx_ring", queue_idx, ring_size, socket_id); if (!tz) { i40e_dev_tx_queue_release(txq); PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX"); return (-ENOMEM); } txq->nb_tx_desc = nb_desc; txq->tx_rs_thresh = tx_rs_thresh; txq->tx_free_thresh = tx_free_thresh; txq->pthresh = tx_conf->tx_thresh.pthresh; txq->hthresh = tx_conf->tx_thresh.hthresh; txq->wthresh = tx_conf->tx_thresh.wthresh; txq->queue_id = queue_idx; if (hw->mac.type == I40E_MAC_VF) txq->reg_idx = queue_idx; else /* PF device */ txq->reg_idx = vsi->base_queue + i40e_get_queue_offset_by_qindex(pf, queue_idx); txq->port_id = dev->data->port_id; txq->txq_flags = tx_conf->txq_flags; txq->vsi = vsi; txq->tx_deferred_start = tx_conf->tx_deferred_start; #ifdef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); #else txq->tx_ring_phys_addr = (uint64_t)tz->phys_addr; #endif txq->tx_ring = (struct i40e_tx_desc *)tz->addr; /* Allocate software ring */ txq->sw_ring = rte_zmalloc_socket("i40e tx sw ring", sizeof(struct i40e_tx_entry) * nb_desc, RTE_CACHE_LINE_SIZE, socket_id); if (!txq->sw_ring) { i40e_dev_tx_queue_release(txq); PMD_DRV_LOG(ERR, "Failed to allocate memory for SW TX ring"); return (-ENOMEM); } i40e_reset_tx_queue(txq); txq->q_set = TRUE; dev->data->tx_queues[queue_idx] = txq; /* Use a simple TX queue without offloads or multi segs if possible */ if (((txq->txq_flags & I40E_SIMPLE_FLAGS) == I40E_SIMPLE_FLAGS) && (txq->tx_rs_thresh >= I40E_TX_MAX_BURST)) { PMD_INIT_LOG(INFO, "Using simple tx path"); dev->tx_pkt_burst = i40e_xmit_pkts_simple; } else { PMD_INIT_LOG(INFO, "Using full-featured tx path"); dev->tx_pkt_burst = i40e_xmit_pkts; } return 0; } void i40e_dev_tx_queue_release(void *txq) { struct i40e_tx_queue *q = (struct i40e_tx_queue *)txq; if (!q) { PMD_DRV_LOG(DEBUG, "Pointer to TX queue is NULL"); return; } i40e_tx_queue_release_mbufs(q); rte_free(q->sw_ring); rte_free(q); } static const struct rte_memzone * i40e_ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); mz = rte_memzone_lookup(z_name); if (mz) return mz; #ifdef RTE_LIBRTE_XEN_DOM0 return rte_memzone_reserve_bounded(z_name, ring_size, socket_id, 0, I40E_ALIGN, RTE_PGSIZE_2M); #else return rte_memzone_reserve_aligned(z_name, ring_size, socket_id, 0, I40E_ALIGN); #endif } const struct rte_memzone * i40e_memzone_reserve(const char *name, uint32_t len, int socket_id) { const struct rte_memzone *mz = NULL; mz = rte_memzone_lookup(name); if (mz) return mz; #ifdef RTE_LIBRTE_XEN_DOM0 mz = rte_memzone_reserve_bounded(name, len, socket_id, 0, I40E_ALIGN, RTE_PGSIZE_2M); #else mz = rte_memzone_reserve_aligned(name, len, socket_id, 0, I40E_ALIGN); #endif return mz; } void i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq) { uint16_t i; if (!rxq || !rxq->sw_ring) { PMD_DRV_LOG(DEBUG, "Pointer to rxq or sw_ring is NULL"); return; } for (i = 0; i < rxq->nb_rx_desc; i++) { if (rxq->sw_ring[i].mbuf) { rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); rxq->sw_ring[i].mbuf = NULL; } } #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC if (rxq->rx_nb_avail == 0) return; for (i = 0; i < rxq->rx_nb_avail; i++) { struct rte_mbuf *mbuf; mbuf = rxq->rx_stage[rxq->rx_next_avail + i]; rte_pktmbuf_free_seg(mbuf); } rxq->rx_nb_avail = 0; #endif /* RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC */ } void i40e_reset_rx_queue(struct i40e_rx_queue *rxq) { unsigned i; uint16_t len; if (!rxq) { PMD_DRV_LOG(DEBUG, "Pointer to rxq is NULL"); return; } #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC if (check_rx_burst_bulk_alloc_preconditions(rxq) == 0) len = (uint16_t)(rxq->nb_rx_desc + RTE_PMD_I40E_RX_MAX_BURST); else #endif /* RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC */ len = rxq->nb_rx_desc; for (i = 0; i < len * sizeof(union i40e_rx_desc); i++) ((volatile char *)rxq->rx_ring)[i] = 0; #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf)); for (i = 0; i < RTE_PMD_I40E_RX_MAX_BURST; ++i) rxq->sw_ring[rxq->nb_rx_desc + i].mbuf = &rxq->fake_mbuf; rxq->rx_nb_avail = 0; rxq->rx_next_avail = 0; rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1); #endif /* RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC */ rxq->rx_tail = 0; rxq->nb_rx_hold = 0; rxq->pkt_first_seg = NULL; rxq->pkt_last_seg = NULL; } void i40e_tx_queue_release_mbufs(struct i40e_tx_queue *txq) { uint16_t i; if (!txq || !txq->sw_ring) { PMD_DRV_LOG(DEBUG, "Pointer to rxq or sw_ring is NULL"); return; } for (i = 0; i < txq->nb_tx_desc; i++) { if (txq->sw_ring[i].mbuf) { rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); txq->sw_ring[i].mbuf = NULL; } } } void i40e_reset_tx_queue(struct i40e_tx_queue *txq) { struct i40e_tx_entry *txe; uint16_t i, prev, size; if (!txq) { PMD_DRV_LOG(DEBUG, "Pointer to txq is NULL"); return; } txe = txq->sw_ring; size = sizeof(struct i40e_tx_desc) * txq->nb_tx_desc; for (i = 0; i < size; i++) ((volatile char *)txq->tx_ring)[i] = 0; prev = (uint16_t)(txq->nb_tx_desc - 1); for (i = 0; i < txq->nb_tx_desc; i++) { volatile struct i40e_tx_desc *txd = &txq->tx_ring[i]; txd->cmd_type_offset_bsz = rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE); txe[i].mbuf = NULL; txe[i].last_id = i; txe[prev].next_id = i; prev = i; } txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_tail = 0; txq->nb_tx_used = 0; txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); } /* Init the TX queue in hardware */ int i40e_tx_queue_init(struct i40e_tx_queue *txq) { enum i40e_status_code err = I40E_SUCCESS; struct i40e_vsi *vsi = txq->vsi; struct i40e_hw *hw = I40E_VSI_TO_HW(vsi); uint16_t pf_q = txq->reg_idx; struct i40e_hmc_obj_txq tx_ctx; uint32_t qtx_ctl; /* clear the context structure first */ memset(&tx_ctx, 0, sizeof(tx_ctx)); tx_ctx.new_context = 1; tx_ctx.base = txq->tx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; tx_ctx.qlen = txq->nb_tx_desc; #ifdef RTE_LIBRTE_IEEE1588 tx_ctx.timesync_ena = 1; #endif tx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[0]); if (vsi->type == I40E_VSI_FDIR) tx_ctx.fd_ena = TRUE; err = i40e_clear_lan_tx_queue_context(hw, pf_q); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failure of clean lan tx queue context"); return err; } err = i40e_set_lan_tx_queue_context(hw, pf_q, &tx_ctx); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failure of set lan tx queue context"); return err; } /* Now associate this queue with this PCI function */ qtx_ctl = I40E_QTX_CTL_PF_QUEUE; qtx_ctl |= ((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) & I40E_QTX_CTL_PF_INDX_MASK); I40E_WRITE_REG(hw, I40E_QTX_CTL(pf_q), qtx_ctl); I40E_WRITE_FLUSH(hw); txq->qtx_tail = hw->hw_addr + I40E_QTX_TAIL(pf_q); return err; } int i40e_alloc_rx_queue_mbufs(struct i40e_rx_queue *rxq) { struct i40e_rx_entry *rxe = rxq->sw_ring; uint64_t dma_addr; uint16_t i; for (i = 0; i < rxq->nb_rx_desc; i++) { volatile union i40e_rx_desc *rxd; struct rte_mbuf *mbuf = rte_rxmbuf_alloc(rxq->mp); if (unlikely(!mbuf)) { PMD_DRV_LOG(ERR, "Failed to allocate mbuf for RX"); return -ENOMEM; } rte_mbuf_refcnt_set(mbuf, 1); mbuf->next = NULL; mbuf->data_off = RTE_PKTMBUF_HEADROOM; mbuf->nb_segs = 1; mbuf->port = rxq->port_id; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf)); rxd = &rxq->rx_ring[i]; rxd->read.pkt_addr = dma_addr; rxd->read.hdr_addr = 0; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC rxd->read.rsvd1 = 0; rxd->read.rsvd2 = 0; #endif /* RTE_LIBRTE_I40E_16BYTE_RX_DESC */ rxe[i].mbuf = mbuf; } return 0; } /* * Calculate the buffer length, and check the jumbo frame * and maximum packet length. */ static int i40e_rx_queue_config(struct i40e_rx_queue *rxq) { struct i40e_pf *pf = I40E_VSI_TO_PF(rxq->vsi); struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi); struct rte_eth_dev_data *data = pf->dev_data; uint16_t buf_size, len; buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM); switch (pf->flags & (I40E_FLAG_HEADER_SPLIT_DISABLED | I40E_FLAG_HEADER_SPLIT_ENABLED)) { case I40E_FLAG_HEADER_SPLIT_ENABLED: /* Not supported */ rxq->rx_hdr_len = RTE_ALIGN(I40E_RXBUF_SZ_1024, (1 << I40E_RXQ_CTX_HBUFF_SHIFT)); rxq->rx_buf_len = RTE_ALIGN(I40E_RXBUF_SZ_2048, (1 << I40E_RXQ_CTX_DBUFF_SHIFT)); rxq->hs_mode = i40e_header_split_enabled; break; case I40E_FLAG_HEADER_SPLIT_DISABLED: default: rxq->rx_hdr_len = 0; rxq->rx_buf_len = RTE_ALIGN(buf_size, (1 << I40E_RXQ_CTX_DBUFF_SHIFT)); rxq->hs_mode = i40e_header_split_none; break; } len = hw->func_caps.rx_buf_chain_len * rxq->rx_buf_len; rxq->max_pkt_len = RTE_MIN(len, data->dev_conf.rxmode.max_rx_pkt_len); if (data->dev_conf.rxmode.jumbo_frame == 1) { if (rxq->max_pkt_len <= ETHER_MAX_LEN || rxq->max_pkt_len > I40E_FRAME_SIZE_MAX) { PMD_DRV_LOG(ERR, "maximum packet length must " "be larger than %u and smaller than %u," "as jumbo frame is enabled", (uint32_t)ETHER_MAX_LEN, (uint32_t)I40E_FRAME_SIZE_MAX); return I40E_ERR_CONFIG; } } else { if (rxq->max_pkt_len < ETHER_MIN_LEN || rxq->max_pkt_len > ETHER_MAX_LEN) { PMD_DRV_LOG(ERR, "maximum packet length must be " "larger than %u and smaller than %u, " "as jumbo frame is disabled", (uint32_t)ETHER_MIN_LEN, (uint32_t)ETHER_MAX_LEN); return I40E_ERR_CONFIG; } } return 0; } /* Init the RX queue in hardware */ int i40e_rx_queue_init(struct i40e_rx_queue *rxq) { int err = I40E_SUCCESS; struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi); struct rte_eth_dev_data *dev_data = I40E_VSI_TO_DEV_DATA(rxq->vsi); struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(rxq->vsi); uint16_t pf_q = rxq->reg_idx; uint16_t buf_size; struct i40e_hmc_obj_rxq rx_ctx; err = i40e_rx_queue_config(rxq); if (err < 0) { PMD_DRV_LOG(ERR, "Failed to config RX queue"); return err; } /* Clear the context structure first */ memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); rx_ctx.dbuff = rxq->rx_buf_len >> I40E_RXQ_CTX_DBUFF_SHIFT; rx_ctx.hbuff = rxq->rx_hdr_len >> I40E_RXQ_CTX_HBUFF_SHIFT; rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; rx_ctx.qlen = rxq->nb_rx_desc; #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC rx_ctx.dsize = 1; #endif rx_ctx.dtype = rxq->hs_mode; if (rxq->hs_mode) rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_ALL; else rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE; rx_ctx.rxmax = rxq->max_pkt_len + I40E_VLAN_TAG_SIZE; rx_ctx.tphrdesc_ena = 1; rx_ctx.tphwdesc_ena = 1; rx_ctx.tphdata_ena = 1; rx_ctx.tphhead_ena = 1; rx_ctx.lrxqthresh = 2; rx_ctx.crcstrip = (rxq->crc_len == 0) ? 1 : 0; rx_ctx.l2tsel = 1; rx_ctx.showiv = 1; rx_ctx.prefena = 1; err = i40e_clear_lan_rx_queue_context(hw, pf_q); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to clear LAN RX queue context"); return err; } err = i40e_set_lan_rx_queue_context(hw, pf_q, &rx_ctx); if (err != I40E_SUCCESS) { PMD_DRV_LOG(ERR, "Failed to set LAN RX queue context"); return err; } rxq->qrx_tail = hw->hw_addr + I40E_QRX_TAIL(pf_q); buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM); /* Check if scattered RX needs to be used. */ if ((rxq->max_pkt_len + 2 * I40E_VLAN_TAG_SIZE) > buf_size) { dev_data->scattered_rx = 1; dev->rx_pkt_burst = i40e_recv_scattered_pkts; } /* Init the RX tail regieter. */ I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); return 0; } void i40e_dev_clear_queues(struct rte_eth_dev *dev) { uint16_t i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_tx_queues; i++) { i40e_tx_queue_release_mbufs(dev->data->tx_queues[i]); i40e_reset_tx_queue(dev->data->tx_queues[i]); } for (i = 0; i < dev->data->nb_rx_queues; i++) { i40e_rx_queue_release_mbufs(dev->data->rx_queues[i]); i40e_reset_rx_queue(dev->data->rx_queues[i]); } } void i40e_dev_free_queues(struct rte_eth_dev *dev) { uint16_t i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_rx_queues; i++) { i40e_dev_rx_queue_release(dev->data->rx_queues[i]); dev->data->rx_queues[i] = NULL; } dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) { i40e_dev_tx_queue_release(dev->data->tx_queues[i]); dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; } #define I40E_FDIR_NUM_TX_DESC I40E_MIN_RING_DESC #define I40E_FDIR_NUM_RX_DESC I40E_MIN_RING_DESC enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf) { struct i40e_tx_queue *txq; const struct rte_memzone *tz = NULL; uint32_t ring_size; struct rte_eth_dev *dev = pf->adapter->eth_dev; if (!pf) { PMD_DRV_LOG(ERR, "PF is not available"); return I40E_ERR_BAD_PTR; } /* Allocate the TX queue data structure. */ txq = rte_zmalloc_socket("i40e fdir tx queue", sizeof(struct i40e_tx_queue), RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); if (!txq) { PMD_DRV_LOG(ERR, "Failed to allocate memory for " "tx queue structure."); return I40E_ERR_NO_MEMORY; } /* Allocate TX hardware ring descriptors. */ ring_size = sizeof(struct i40e_tx_desc) * I40E_FDIR_NUM_TX_DESC; ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); tz = i40e_ring_dma_zone_reserve(dev, "fdir_tx_ring", I40E_FDIR_QUEUE_ID, ring_size, SOCKET_ID_ANY); if (!tz) { i40e_dev_tx_queue_release(txq); PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for TX."); return I40E_ERR_NO_MEMORY; } txq->nb_tx_desc = I40E_FDIR_NUM_TX_DESC; txq->queue_id = I40E_FDIR_QUEUE_ID; txq->reg_idx = pf->fdir.fdir_vsi->base_queue; txq->vsi = pf->fdir.fdir_vsi; #ifdef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); #else txq->tx_ring_phys_addr = (uint64_t)tz->phys_addr; #endif txq->tx_ring = (struct i40e_tx_desc *)tz->addr; /* * don't need to allocate software ring and reset for the fdir * program queue just set the queue has been configured. */ txq->q_set = TRUE; pf->fdir.txq = txq; return I40E_SUCCESS; } enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf) { struct i40e_rx_queue *rxq; const struct rte_memzone *rz = NULL; uint32_t ring_size; struct rte_eth_dev *dev = pf->adapter->eth_dev; if (!pf) { PMD_DRV_LOG(ERR, "PF is not available"); return I40E_ERR_BAD_PTR; } /* Allocate the RX queue data structure. */ rxq = rte_zmalloc_socket("i40e fdir rx queue", sizeof(struct i40e_rx_queue), RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); if (!rxq) { PMD_DRV_LOG(ERR, "Failed to allocate memory for " "rx queue structure."); return I40E_ERR_NO_MEMORY; } /* Allocate RX hardware ring descriptors. */ ring_size = sizeof(union i40e_rx_desc) * I40E_FDIR_NUM_RX_DESC; ring_size = RTE_ALIGN(ring_size, I40E_DMA_MEM_ALIGN); rz = i40e_ring_dma_zone_reserve(dev, "fdir_rx_ring", I40E_FDIR_QUEUE_ID, ring_size, SOCKET_ID_ANY); if (!rz) { i40e_dev_rx_queue_release(rxq); PMD_DRV_LOG(ERR, "Failed to reserve DMA memory for RX."); return I40E_ERR_NO_MEMORY; } rxq->nb_rx_desc = I40E_FDIR_NUM_RX_DESC; rxq->queue_id = I40E_FDIR_QUEUE_ID; rxq->reg_idx = pf->fdir.fdir_vsi->base_queue; rxq->vsi = pf->fdir.fdir_vsi; #ifdef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); #else rxq->rx_ring_phys_addr = (uint64_t)rz->phys_addr; #endif rxq->rx_ring = (union i40e_rx_desc *)rz->addr; /* * Don't need to allocate software ring and reset for the fdir * rx queue, just set the queue has been configured. */ rxq->q_set = TRUE; pf->fdir.rxq = rxq; return I40E_SUCCESS; } ================================================ FILE: drivers/net/i40e/i40e_rxtx.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _I40E_RXTX_H_ #define _I40E_RXTX_H_ /** * 32 bits tx flags, high 16 bits for L2TAG1 (VLAN), * low 16 bits for others. */ #define I40E_TX_FLAG_L2TAG1_SHIFT 16 #define I40E_TX_FLAG_L2TAG1_MASK 0xffff0000 #define I40E_TX_FLAG_CSUM ((uint32_t)(1 << 0)) #define I40E_TX_FLAG_INSERT_VLAN ((uint32_t)(1 << 1)) #define I40E_TX_FLAG_TSYN ((uint32_t)(1 << 2)) #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC #define RTE_PMD_I40E_RX_MAX_BURST 32 #endif #define I40E_RXBUF_SZ_1024 1024 #define I40E_RXBUF_SZ_2048 2048 enum i40e_header_split_mode { i40e_header_split_none = 0, i40e_header_split_enabled = 1, i40e_header_split_always = 2, i40e_header_split_reserved }; #define I40E_HEADER_SPLIT_NONE ((uint8_t)0) #define I40E_HEADER_SPLIT_L2 ((uint8_t)(1 << 0)) #define I40E_HEADER_SPLIT_IP ((uint8_t)(1 << 1)) #define I40E_HEADER_SPLIT_UDP_TCP ((uint8_t)(1 << 2)) #define I40E_HEADER_SPLIT_SCTP ((uint8_t)(1 << 3)) #define I40E_HEADER_SPLIT_ALL (I40E_HEADER_SPLIT_L2 | \ I40E_HEADER_SPLIT_IP | \ I40E_HEADER_SPLIT_UDP_TCP | \ I40E_HEADER_SPLIT_SCTP) /* HW desc structure, both 16-byte and 32-byte types are supported */ #ifdef RTE_LIBRTE_I40E_16BYTE_RX_DESC #define i40e_rx_desc i40e_16byte_rx_desc #else #define i40e_rx_desc i40e_32byte_rx_desc #endif struct i40e_rx_entry { struct rte_mbuf *mbuf; }; /* * Structure associated with each RX queue. */ struct i40e_rx_queue { struct rte_mempool *mp; /**< mbuf pool to populate RX ring */ volatile union i40e_rx_desc *rx_ring;/**< RX ring virtual address */ uint64_t rx_ring_phys_addr; /**< RX ring DMA address */ struct i40e_rx_entry *sw_ring; /**< address of RX soft ring */ uint16_t nb_rx_desc; /**< number of RX descriptors */ uint16_t rx_free_thresh; /**< max free RX desc to hold */ uint16_t rx_tail; /**< current value of tail */ uint16_t nb_rx_hold; /**< number of held free RX desc */ struct rte_mbuf *pkt_first_seg; /**< first segment of current packet */ struct rte_mbuf *pkt_last_seg; /**< last segment of current packet */ #ifdef RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC uint16_t rx_nb_avail; /**< number of staged packets ready */ uint16_t rx_next_avail; /**< index of next staged packets */ uint16_t rx_free_trigger; /**< triggers rx buffer allocation */ struct rte_mbuf fake_mbuf; /**< dummy mbuf */ struct rte_mbuf *rx_stage[RTE_PMD_I40E_RX_MAX_BURST * 2]; #endif uint8_t port_id; /**< device port ID */ uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise */ uint16_t queue_id; /**< RX queue index */ uint16_t reg_idx; /**< RX queue register index */ uint8_t drop_en; /**< if not 0, set register bit */ volatile uint8_t *qrx_tail; /**< register address of tail */ struct i40e_vsi *vsi; /**< the VSI this queue belongs to */ uint16_t rx_buf_len; /* The packet buffer size */ uint16_t rx_hdr_len; /* The header buffer size */ uint16_t max_pkt_len; /* Maximum packet length */ uint8_t hs_mode; /* Header Split mode */ bool q_set; /**< indicate if rx queue has been configured */ bool rx_deferred_start; /**< don't start this queue in dev start */ }; struct i40e_tx_entry { struct rte_mbuf *mbuf; uint16_t next_id; uint16_t last_id; }; /* * Structure associated with each TX queue. */ struct i40e_tx_queue { uint16_t nb_tx_desc; /**< number of TX descriptors */ uint64_t tx_ring_phys_addr; /**< TX ring DMA address */ volatile struct i40e_tx_desc *tx_ring; /**< TX ring virtual address */ struct i40e_tx_entry *sw_ring; /**< virtual address of SW ring */ uint16_t tx_tail; /**< current value of tail register */ volatile uint8_t *qtx_tail; /**< register address of tail */ uint16_t nb_tx_used; /**< number of TX desc used since RS bit set */ /**< index to last TX descriptor to have been cleaned */ uint16_t last_desc_cleaned; /**< Total number of TX descriptors ready to be allocated. */ uint16_t nb_tx_free; /**< Start freeing TX buffers if there are less free descriptors than this value. */ uint16_t tx_free_thresh; /** Number of TX descriptors to use before RS bit is set. */ uint16_t tx_rs_thresh; uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold reg. */ uint8_t port_id; /**< Device port identifier. */ uint16_t queue_id; /**< TX queue index. */ uint16_t reg_idx; uint32_t txq_flags; struct i40e_vsi *vsi; /**< the VSI this queue belongs to */ uint16_t tx_next_dd; uint16_t tx_next_rs; bool q_set; /**< indicate if tx queue has been configured */ bool tx_deferred_start; /**< don't start this queue in dev start */ }; /** Offload features */ union i40e_tx_offload { uint64_t data; struct { uint64_t l2_len:7; /**< L2 (MAC) Header Length. */ uint64_t l3_len:9; /**< L3 (IP) Header Length. */ uint64_t l4_len:8; /**< L4 Header Length. */ uint64_t tso_segsz:16; /**< TCP TSO segment size */ uint64_t outer_l2_len:8; /**< outer L2 Header Length */ uint64_t outer_l3_len:16; /**< outer L3 Header Length */ }; }; int i40e_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id); int i40e_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id); int i40e_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id); int i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id); int i40e_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp); int i40e_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); void i40e_dev_rx_queue_release(void *rxq); void i40e_dev_tx_queue_release(void *txq); uint16_t i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t i40e_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int i40e_tx_queue_init(struct i40e_tx_queue *txq); int i40e_rx_queue_init(struct i40e_rx_queue *rxq); void i40e_free_tx_resources(struct i40e_tx_queue *txq); void i40e_free_rx_resources(struct i40e_rx_queue *rxq); void i40e_dev_clear_queues(struct rte_eth_dev *dev); void i40e_dev_free_queues(struct rte_eth_dev *dev); void i40e_reset_rx_queue(struct i40e_rx_queue *rxq); void i40e_reset_tx_queue(struct i40e_tx_queue *txq); void i40e_tx_queue_release_mbufs(struct i40e_tx_queue *txq); int i40e_alloc_rx_queue_mbufs(struct i40e_rx_queue *rxq); void i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq); uint32_t i40e_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id); int i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset); #endif /* _I40E_RXTX_H_ */ ================================================ FILE: drivers/net/ixgbe/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_ixgbe.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_ixgbe_version.map LIBABIVER := 1 ifeq ($(CC), icc) # # CFLAGS for icc # CFLAGS_BASE_DRIVER = -wd174 -wd593 -wd869 -wd981 -wd2259 else ifeq ($(CC), clang) # # CFLAGS for clang # CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args else # # CFLAGS for gcc # ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS += -Wno-deprecated CFLAGS_ixgbe_common.o += -Wno-unused-but-set-variable CFLAGS_ixgbe_x550.o += -Wno-unused-but-set-variable endif CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args ifeq ($(shell test $(GCC_VERSION) -ge 46 && echo 1), 1) CFLAGS_ixgbe_x550.o += -Wno-maybe-uninitialized endif ifeq ($(shell test $(GCC_VERSION) -ge 50 && echo 1), 1) CFLAGS_ixgbe_common.o += -Wno-logical-not-parentheses endif endif # # Add extra flags for base driver files (also known as shared code) # to disable warnings in them # BASE_DRIVER_OBJS=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(BASE_DRIVER_OBJS), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_common.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82598.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_x540.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_x550.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_phy.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_api.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_vf.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_dcb.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_dcb_82599.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_dcb_82598.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_mbx.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_pf.c SRCS-$(CONFIG_RTE_IXGBE_INC_VECTOR) += ixgbe_rxtx_vec.c ifeq ($(CONFIG_RTE_NIC_BYPASS),y) SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_bypass.c SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_82599_bypass.c endif # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/ixgbe/base/README ================================================ .. BSD LICENSE Copyright(c) 2010-2015 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Intel® IXGBE driver =================== This directory contains source code of FreeBSD ixgbe driver of version cid-10g-shared-code.2015.06.05 released by ND. The sub-directory of base/ contains the original source package. This driver is valid for the product(s) listed below * Intel® 10 Gigabit AF DA Dual Port Server Adapter * Intel® 10 Gigabit AT Server Adapter * Intel® 10 Gigabit AT2 Server Adapter * Intel® 10 Gigabit CX4 Dual Port Server Adapter * Intel® 10 Gigabit XF LR Server Adapter * Intel® 10 Gigabit XF SR Dual Port Server Adapter * Intel® 10 Gigabit XF SR Server Adapter * Intel® 82598 10 Gigabit Ethernet Controller * Intel® 82599 10 Gigabit Ethernet Controller * Intel® Ethernet Controller X540-AT2 * Intel® Ethernet Server Adapter X520 Series * Intel® Ethernet Server Adapter X520-T2 * Intel® Ethernet Controller X550-BT2 Updating the driver =================== NOTE: The source code in this directory should not be modified apart from the following file(s): ixgbe_osdep.h ================================================ FILE: drivers/net/ixgbe/base/ixgbe_82598.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_82598.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" #define IXGBE_82598_MAX_TX_QUEUES 32 #define IXGBE_82598_MAX_RX_QUEUES 64 #define IXGBE_82598_RAR_ENTRIES 16 #define IXGBE_82598_MC_TBL_SIZE 128 #define IXGBE_82598_VFT_TBL_SIZE 128 #define IXGBE_82598_RX_PB_SIZE 512 STATIC s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); STATIC enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); STATIC s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); STATIC s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); STATIC s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); STATIC s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); STATIC s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); STATIC s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); STATIC s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw); STATIC void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy); STATIC s32 ixgbe_read_i2c_sff8472_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); /** * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout * @hw: pointer to the HW structure * * The defaults for 82598 should be in the range of 50us to 50ms, * however the hardware default for these parts is 500us to 1ms which is less * than the 10ms recommended by the pci-e spec. To address this we need to * increase the value to either 10ms to 250ms for capability version 1 config, * or 16ms to 55ms for version 2. **/ void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) { u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); u16 pcie_devctl2; /* only take action if timeout value is defaulted to 0 */ if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) goto out; /* * if capababilities version is type 1 we can write the * timeout of 10ms to 250ms through the GCR register */ if (!(gcr & IXGBE_GCR_CAP_VER2)) { gcr |= IXGBE_GCR_CMPL_TMOUT_10ms; goto out; } /* * for version 2 capabilities we need to write the config space * directly in order to set the completion timeout value for * 16ms to 55ms */ pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); out: /* disable completion timeout resend */ gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND; IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr); } /** * ixgbe_init_ops_82598 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for 82598. * Does not touch the hardware. **/ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("ixgbe_init_ops_82598"); ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* PHY */ phy->ops.init = ixgbe_init_phy_ops_82598; /* MAC */ mac->ops.start_hw = ixgbe_start_hw_82598; mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_82598; mac->ops.reset_hw = ixgbe_reset_hw_82598; mac->ops.get_media_type = ixgbe_get_media_type_82598; mac->ops.get_supported_physical_layer = ixgbe_get_supported_physical_layer_82598; mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82598; mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82598; mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie_82598; mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82598; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = ixgbe_set_vmdq_82598; mac->ops.clear_vmdq = ixgbe_clear_vmdq_82598; mac->ops.set_vfta = ixgbe_set_vfta_82598; mac->ops.set_vlvf = NULL; mac->ops.clear_vfta = ixgbe_clear_vfta_82598; /* Flow Control */ mac->ops.fc_enable = ixgbe_fc_enable_82598; mac->mcft_size = IXGBE_82598_MC_TBL_SIZE; mac->vft_size = IXGBE_82598_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_82598_RAR_ENTRIES; mac->rx_pb_size = IXGBE_82598_RX_PB_SIZE; mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES; mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); /* SFP+ Module */ phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_82598; phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_82598; /* Link */ mac->ops.check_link = ixgbe_check_mac_link_82598; mac->ops.setup_link = ixgbe_setup_mac_link_82598; mac->ops.flap_tx_laser = NULL; mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82598; mac->ops.setup_rxpba = ixgbe_set_rxpba_82598; /* Manageability interface */ mac->ops.set_fw_drv_ver = NULL; mac->ops.get_rtrup2tc = NULL; return ret_val; } /** * ixgbe_init_phy_ops_82598 - PHY/SFP specific init * @hw: pointer to hardware structure * * Initialize any function pointers that were not able to be * set during init_shared_code because the PHY/SFP type was * not known. Perform the SFP init if necessary. * **/ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val = IXGBE_SUCCESS; u16 list_offset, data_offset; DEBUGFUNC("ixgbe_init_phy_ops_82598"); /* Identify the PHY */ phy->ops.identify(hw); /* Overwrite the link function pointers if copper PHY */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = ixgbe_setup_copper_link_82598; mac->ops.get_link_capabilities = ixgbe_get_copper_link_capabilities_generic; } switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.setup_link = ixgbe_setup_phy_link_tnx; phy->ops.check_link = ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_tnx; break; case ixgbe_phy_nl: phy->ops.reset = ixgbe_reset_phy_nl; /* Call SFP+ identify routine to get the SFP+ module type */ ret_val = phy->ops.identify_sfp(hw); if (ret_val != IXGBE_SUCCESS) goto out; else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } /* Check to see if SFP+ module is supported */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != IXGBE_SUCCESS) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } break; default: break; } out: return ret_val; } /** * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function. * Disables relaxed ordering Then set pcie completion timeout * **/ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) { u32 regval; u32 i; s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_start_hw_82598"); ret_val = ixgbe_start_hw_generic(hw); if (ret_val) return ret_val; /* Disable relaxed ordering */ for (i = 0; ((i < hw->mac.max_tx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); } for (i = 0; ((i < hw->mac.max_rx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } /* set the completion timeout for interface */ ixgbe_set_pcie_completion_timeout(hw); return ret_val; } /** * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the link capabilities by reading the AUTOC register. **/ STATIC s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = IXGBE_SUCCESS; u32 autoc = 0; DEBUGFUNC("ixgbe_get_link_capabilities_82598"); /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not been * stored, use the current register value. */ if (hw->mac.orig_link_settings_stored) autoc = hw->mac.orig_autoc; else autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; default: status = IXGBE_ERR_LINK_SETUP; break; } return status; } /** * ixgbe_get_media_type_82598 - Determines media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ STATIC enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; DEBUGFUNC("ixgbe_get_media_type_82598"); /* Detect if there is a copper PHY attached. */ switch (hw->phy.type) { case ixgbe_phy_cu_unknown: case ixgbe_phy_tn: media_type = ixgbe_media_type_copper; goto out; default: break; } /* Media type for I82598 is based on device ID */ switch (hw->device_id) { case IXGBE_DEV_ID_82598: case IXGBE_DEV_ID_82598_BX: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: media_type = ixgbe_media_type_cx4; break; case IXGBE_DEV_ID_82598AT: case IXGBE_DEV_ID_82598AT2: media_type = ixgbe_media_type_copper; break; default: media_type = ixgbe_media_type_unknown; break; } out: return media_type; } /** * ixgbe_fc_enable_82598 - Enable flow control * @hw: pointer to hardware structure * * Enable flow control according to the current settings. **/ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; u32 fctrl_reg; u32 rmcs_reg; u32 reg; u32 fcrtl, fcrth; u32 link_speed = 0; int i; bool link_up; DEBUGFUNC("ixgbe_fc_enable_82598"); /* Validate the water mark configuration */ if (!hw->fc.pause_time) { ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* Low water mark of zero causes XOFF floods */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { if (!hw->fc.low_water[i] || hw->fc.low_water[i] >= hw->fc.high_water[i]) { DEBUGOUT("Invalid water mark configuration\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } } } /* * On 82598 having Rx FC on causes resets while doing 1G * so if it's on turn it off once we know link_speed. For * more details see 82598 Specification update. */ hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) { switch (hw->fc.requested_mode) { case ixgbe_fc_full: hw->fc.requested_mode = ixgbe_fc_tx_pause; break; case ixgbe_fc_rx_pause: hw->fc.requested_mode = ixgbe_fc_none; break; default: /* no change */ break; } } /* Negotiate the fc mode to use */ ixgbe_fc_autoneg(hw); /* Disable any previous flow control settings */ fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); /* * The possible values of fc.current_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.current_mode) { case ixgbe_fc_none: /* * Flow control is disabled by software override or autoneg. * The code below will actually disable it in the HW. */ break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ fctrl_reg |= IXGBE_FCTRL_RFCE; break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ fctrl_reg |= IXGBE_FCTRL_RFCE; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; default: DEBUGOUT("Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } /* Set 802.3x based flow control settings. */ fctrl_reg |= IXGBE_FCTRL_DPF; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); /* Set up and enable Rx high/low water mark thresholds, enable XON. */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth); } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0); } } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time * 0x00010001; for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); out: return ret_val; } /** * ixgbe_start_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ STATIC s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_start_mac_link_82598"); /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { links_reg = 0; /* Just in case Autoneg time = 0 */ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msec_delay(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; DEBUGOUT("Autonegotiation did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msec_delay(50); return status; } /** * ixgbe_validate_link_ready - Function looks for phy link * @hw: pointer to hardware structure * * Function indicates success when phy link is available. If phy is not ready * within 5 seconds of MAC indicating link, the function returns error. **/ STATIC s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) { u32 timeout; u16 an_reg; if (hw->device_id != IXGBE_DEV_ID_82598AT2) return IXGBE_SUCCESS; for (timeout = 0; timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_reg); if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) && (an_reg & IXGBE_MII_AUTONEG_LINK_UP)) break; msec_delay(100); } if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) { DEBUGOUT("Link was indicated but link is down\n"); return IXGBE_ERR_LINK_SETUP; } return IXGBE_SUCCESS; } /** * ixgbe_check_mac_link_82598 - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise * @link_up_wait_to_complete: bool used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ STATIC s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { u32 links_reg; u32 i; u16 link_reg, adapt_comp_reg; DEBUGFUNC("ixgbe_check_mac_link_82598"); /* * SERDES PHY requires us to read link status from undocumented * register 0xC79F. Bit 0 set indicates link is up/ready; clear * indicates link down. OxC00C is read to check that the XAUI lanes * are active. Bit 0 clear indicates active; set indicates inactive. */ if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) { *link_up = true; break; } else { *link_up = false; } msec_delay(100); hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); } } else { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) *link_up = true; else *link_up = false; } if (*link_up == false) goto out; } links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = true; break; } else { *link_up = false; } msec_delay(100); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); } } else { if (links_reg & IXGBE_LINKS_UP) *link_up = true; else *link_up = false; } if (links_reg & IXGBE_LINKS_SPEED) *speed = IXGBE_LINK_SPEED_10GB_FULL; else *speed = IXGBE_LINK_SPEED_1GB_FULL; if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == true) && (ixgbe_validate_link_ready(hw) != IXGBE_SUCCESS)) *link_up = false; out: return IXGBE_SUCCESS; } /** * ixgbe_setup_mac_link_82598 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ STATIC s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { bool autoneg = false; s32 status = IXGBE_SUCCESS; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc = curr_autoc; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; DEBUGFUNC("ixgbe_setup_mac_link_82598"); /* Check to see if speed passed in is supported. */ ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); speed &= link_capabilities; if (speed == IXGBE_LINK_SPEED_UNKNOWN) status = IXGBE_ERR_LINK_SETUP; /* Set KX4/KX support according to speed requested */ else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN || link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK; if (speed & IXGBE_LINK_SPEED_10GB_FULL) autoc |= IXGBE_AUTOC_KX4_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; if (autoc != curr_autoc) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } if (status == IXGBE_SUCCESS) { /* * Setup and restart the link based on the new values in * ixgbe_hw This will write the AUTOC register based on the new * stored values */ status = ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); } return status; } /** * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true if waiting is needed to complete * * Sets the link speed in the AUTOC register in the MAC and restarts link. **/ STATIC s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 status; DEBUGFUNC("ixgbe_setup_copper_link_82598"); /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); /* Set up MAC */ ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); return status; } /** * ixgbe_reset_hw_82598 - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/ STATIC s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; s32 phy_status = IXGBE_SUCCESS; u32 ctrl; u32 gheccr; u32 i; u32 autoc; u8 analog_val; DEBUGFUNC("ixgbe_reset_hw_82598"); /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != IXGBE_SUCCESS) goto reset_hw_out; /* * Power up the Atlas Tx lanes if they are currently powered down. * Atlas Tx lanes are powered down for MAC loopback tests, but * they are not automatically restored on reset. */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { /* Enable Tx Atlas so packets can be transmitted again */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); } /* Reset PHY */ if (hw->phy.reset_disable == false) { /* PHY ops must be identified and initialized prior to reset */ /* Init PHY and function pointers, perform SFP setup */ phy_status = hw->phy.ops.init(hw); if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT) goto mac_reset_top; hw->phy.ops.reset(hw); } mac_reset_top: /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST; IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST)) break; } if (ctrl & IXGBE_CTRL_RST) { status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } msec_delay(50); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* * Store the original AUTOC value if it has not been * stored off yet. Otherwise restore the stored original * AUTOC value since the reset operation sets back to deaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.orig_link_settings_stored == false) { hw->mac.orig_autoc = autoc; hw->mac.orig_link_settings_stored = true; } else if (autoc != hw->mac.orig_autoc) { IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ hw->mac.ops.init_rx_addrs(hw); reset_hw_out: if (phy_status != IXGBE_SUCCESS) status = phy_status; return status; } /** * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq set index **/ s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_set_vmdq_82598"); /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { DEBUGOUT1("RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); rar_high &= ~IXGBE_RAH_VIND_MASK; rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); return IXGBE_SUCCESS; } /** * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq clear index (not used in 82598, but elsewhere) **/ STATIC s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; UNREFERENCED_1PARAMETER(vmdq); /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { DEBUGOUT1("RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); if (rar_high & IXGBE_RAH_VIND_MASK) { rar_high &= ~IXGBE_RAH_VIND_MASK; IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); } return IXGBE_SUCCESS; } /** * ixgbe_set_vfta_82598 - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFTA * @vlan_on: boolean flag to turn on/off VLAN in VFTA * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { u32 regindex; u32 bitindex; u32 bits; u32 vftabyte; DEBUGFUNC("ixgbe_set_vfta_82598"); if (vlan > 4095) return IXGBE_ERR_PARAM; /* Determine 32-bit word position in array */ regindex = (vlan >> 5) & 0x7F; /* upper seven bits */ /* Determine the location of the (VMD) queue index */ vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ /* Set the nibble for VMD queue index */ bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex)); bits &= (~(0x0F << bitindex)); bits |= (vind << bitindex); IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits); /* Determine the location of the bit for this VLAN id */ bitindex = vlan & 0x1F; /* lower five bits */ bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); if (vlan_on) /* Turn on this VLAN id */ bits |= (1 << bitindex); else /* Turn off this VLAN id */ bits &= ~(1 << bitindex); IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); return IXGBE_SUCCESS; } /** * ixgbe_clear_vfta_82598 - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ STATIC s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) { u32 offset; u32 vlanbyte; DEBUGFUNC("ixgbe_clear_vfta_82598"); for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), 0); return IXGBE_SUCCESS; } /** * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs read operation to Atlas analog register specified. **/ s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 atlas_ctl; DEBUGFUNC("ixgbe_read_analog_reg8_82598"); IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); usec_delay(10); atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); *val = (u8)atlas_ctl; return IXGBE_SUCCESS; } /** * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register * @hw: pointer to hardware structure * @reg: atlas register to write * @val: value to write * * Performs write operation to Atlas analog register specified. **/ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 atlas_ctl; DEBUGFUNC("ixgbe_write_analog_reg8_82598"); atlas_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); IXGBE_WRITE_FLUSH(hw); usec_delay(10); return IXGBE_SUCCESS; } /** * ixgbe_read_i2c_phy_82598 - Reads 8 bit word over I2C interface. * @hw: pointer to hardware structure * @dev_addr: address to read from * @byte_offset: byte offset to read from dev_addr * @eeprom_data: value read * * Performs 8 byte read operation to SFP module's EEPROM over I2C interface. **/ STATIC s32 ixgbe_read_i2c_phy_82598(struct ixgbe_hw *hw, u8 dev_addr, u8 byte_offset, u8 *eeprom_data) { s32 status = IXGBE_SUCCESS; u16 sfp_addr = 0; u16 sfp_data = 0; u16 sfp_stat = 0; u16 gssr; u32 i; DEBUGFUNC("ixgbe_read_i2c_phy_82598"); if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else gssr = IXGBE_GSSR_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS) return IXGBE_ERR_SWFW_SYNC; if (hw->phy.type == ixgbe_phy_nl) { /* * NetLogic phy SDA/SCL registers are at addresses 0xC30A to * 0xC30D. These registers are used to talk to the SFP+ * module's EEPROM through the SDA/SCL (I2C) interface. */ sfp_addr = (dev_addr << 8) + byte_offset; sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK); hw->phy.ops.write_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR, IXGBE_MDIO_PMA_PMD_DEV_TYPE, sfp_addr); /* Poll status */ for (i = 0; i < 100; i++) { hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_stat); sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) break; msec_delay(10); } if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) { DEBUGOUT("EEPROM read did not pass.\n"); status = IXGBE_ERR_SFP_NOT_PRESENT; goto out; } /* Read data */ hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data); *eeprom_data = (u8)(sfp_data >> 8); } else { status = IXGBE_ERR_PHY; } out: hw->mac.ops.release_swfw_sync(hw, gssr); return status; } /** * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface. * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs 8 byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR, byte_offset, eeprom_data); } /** * ixgbe_read_i2c_sff8472_82598 - Reads 8 bit word over I2C interface. * @hw: pointer to hardware structure * @byte_offset: byte offset at address 0xA2 * @eeprom_data: value read * * Performs 8 byte read operation to SFP module's SFF-8472 data over I2C **/ STATIC s32 ixgbe_read_i2c_sff8472_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data) { return ixgbe_read_i2c_phy_82598(hw, IXGBE_I2C_EEPROM_DEV_ADDR2, byte_offset, sff8472_data); } /** * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; DEBUGFUNC("ixgbe_get_supported_physical_layer_82598"); hw->phy.ops.identify(hw); /* Copper PHY must be checked before AUTOC LMS to determine correct * physical layer because 10GBase-T PHYs use LMS = KX4/KX */ switch (hw->phy.type) { case ixgbe_phy_tn: case ixgbe_phy_cu_unknown: hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; default: break; } switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_AN: case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: if (pma_pmd_1g == IXGBE_AUTOC_1G_KX) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX; else physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; else /* XAUI */ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: if (autoc & IXGBE_AUTOC_KX_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; if (autoc & IXGBE_AUTOC_KX4_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; break; default: break; } if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.identify_sfp(hw); switch (hw->phy.sfp_type) { case ixgbe_sfp_type_da_cu: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case ixgbe_sfp_type_sr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; break; case ixgbe_sfp_type_lr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; default: physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } } switch (hw->device_id) { case IXGBE_DEV_ID_82598_DA_DUAL_PORT: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; break; case IXGBE_DEV_ID_82598EB_XF_LR: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; default: break; } out: return physical_layer; } /** * ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple * port devices. * @hw: pointer to the HW structure * * Calls common function and corrects issue with some single port devices * that enable LAN1 but not LAN0. **/ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) { struct ixgbe_bus_info *bus = &hw->bus; u16 pci_gen = 0; u16 pci_ctrl2 = 0; DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie_82598"); ixgbe_set_lan_id_multi_port_pcie(hw); /* check if LAN0 is disabled */ hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen); if ((pci_gen != 0) && (pci_gen != 0xFFFF)) { hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2); /* if LAN0 is completely disabled force function to 0 */ if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) && !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) && !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) { bus->func = 0; } } } /** * ixgbe_enable_relaxed_ordering_82598 - enable relaxed ordering * @hw: pointer to hardware structure * **/ void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw) { u32 regval; u32 i; DEBUGFUNC("ixgbe_enable_relaxed_ordering_82598"); /* Enable relaxed ordering */ for (i = 0; ((i < hw->mac.max_tx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); } for (i = 0; ((i < hw->mac.max_rx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } } /** * ixgbe_set_rxpba_82598 - Initialize RX packet buffer * @hw: pointer to hardware structure * @num_pb: number of packet buffers to allocate * @headroom: reserve n KB of headroom * @strategy: packet buffer allocation strategy **/ STATIC void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy) { u32 rxpktsize = IXGBE_RXPBSIZE_64KB; u8 i = 0; UNREFERENCED_1PARAMETER(headroom); if (!num_pb) return; /* Setup Rx packet buffer sizes */ switch (strategy) { case PBA_STRATEGY_WEIGHTED: /* Setup the first four at 80KB */ rxpktsize = IXGBE_RXPBSIZE_80KB; for (; i < 4; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); /* Setup the last four at 48KB...don't re-init i */ rxpktsize = IXGBE_RXPBSIZE_48KB; /* Fall Through */ case PBA_STRATEGY_EQUAL: default: /* Divide the remaining Rx packet buffer evenly among the TCs */ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); break; } /* Setup Tx packet buffer sizes */ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB); } /** * ixgbe_enable_rx_dma_82598 - Enable the Rx DMA unit * @hw: pointer to hardware structure * @regval: register value to write to RXCTRL * * Enables the Rx DMA unit **/ s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval) { DEBUGFUNC("ixgbe_enable_rx_dma_82598"); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); return IXGBE_SUCCESS; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_82598.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_82598_H_ #define _IXGBE_82598_H_ u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw); s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw); void ixgbe_enable_relaxed_ordering_82598(struct ixgbe_hw *hw); s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw); void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_82598(struct ixgbe_hw *hw, u32 regval); #endif /* _IXGBE_82598_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_82599.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_82599.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" #define IXGBE_82599_MAX_TX_QUEUES 128 #define IXGBE_82599_MAX_RX_QUEUES 128 #define IXGBE_82599_RAR_ENTRIES 128 #define IXGBE_82599_MC_TBL_SIZE 128 #define IXGBE_82599_VFT_TBL_SIZE 128 #define IXGBE_82599_RX_PB_SIZE 512 STATIC s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); STATIC s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); STATIC s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, u16 offset, u16 *data); STATIC s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); STATIC s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; DEBUGFUNC("ixgbe_init_mac_link_ops_82599"); /* * enable the laser control functions for SFP+ fiber * and MNG not enabled */ if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) && !ixgbe_mng_enabled(hw)) { mac->ops.disable_tx_laser = ixgbe_disable_tx_laser_multispeed_fiber; mac->ops.enable_tx_laser = ixgbe_enable_tx_laser_multispeed_fiber; mac->ops.flap_tx_laser = ixgbe_flap_tx_laser_multispeed_fiber; } else { mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; } if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599; mac->ops.set_rate_select_speed = ixgbe_set_hard_rate_select_speed; } else { if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) && (hw->phy.smart_speed == ixgbe_smart_speed_auto || hw->phy.smart_speed == ixgbe_smart_speed_on) && !ixgbe_verify_lesm_fw_enabled_82599(hw)) { mac->ops.setup_link = ixgbe_setup_mac_link_smartspeed; } else { mac->ops.setup_link = ixgbe_setup_mac_link_82599; } } } /** * ixgbe_init_phy_ops_82599 - PHY/SFP specific init * @hw: pointer to hardware structure * * Initialize any function pointers that were not able to be * set during init_shared_code because the PHY/SFP type was * not known. Perform the SFP init if necessary. * **/ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val = IXGBE_SUCCESS; u32 esdp; DEBUGFUNC("ixgbe_init_phy_ops_82599"); if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) { /* Store flag indicating I2C bus access control unit. */ hw->phy.qsfp_shared_i2c_bus = TRUE; /* Initialize access to QSFP+ I2C bus */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0_DIR; esdp &= ~IXGBE_ESDP_SDP1_DIR; esdp &= ~IXGBE_ESDP_SDP0; esdp &= ~IXGBE_ESDP_SDP0_NATIVE; esdp &= ~IXGBE_ESDP_SDP1_NATIVE; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599; phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599; } /* Identify the PHY or SFP module */ ret_val = phy->ops.identify(hw); if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) goto init_phy_ops_out; /* Setup function pointers based on detected SFP module and speeds */ ixgbe_init_mac_link_ops_82599(hw); if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) hw->phy.ops.reset = NULL; /* If copper media, overwrite with copper function pointers */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = ixgbe_setup_copper_link_82599; mac->ops.get_link_capabilities = ixgbe_get_copper_link_capabilities_generic; } /* Set necessary function pointers based on PHY type */ switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.setup_link = ixgbe_setup_phy_link_tnx; phy->ops.check_link = ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_tnx; break; default: break; } init_phy_ops_out: return ret_val; } s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; u16 list_offset, data_offset, data_value; DEBUGFUNC("ixgbe_setup_sfp_modules_82599"); if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { ixgbe_init_mac_link_ops_82599(hw); hw->phy.ops.reset = NULL; ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != IXGBE_SUCCESS) goto setup_sfp_out; /* PHY config will finish before releasing the semaphore */ ret_val = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); if (ret_val != IXGBE_SUCCESS) { ret_val = IXGBE_ERR_SWFW_SYNC; goto setup_sfp_out; } if (hw->eeprom.ops.read(hw, ++data_offset, &data_value)) goto setup_sfp_err; while (data_value != 0xffff) { IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value); IXGBE_WRITE_FLUSH(hw); if (hw->eeprom.ops.read(hw, ++data_offset, &data_value)) goto setup_sfp_err; } /* Release the semaphore */ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* Delay obtaining semaphore again to allow FW access * prot_autoc_write uses the semaphore too. */ msec_delay(hw->eeprom.semaphore_delay); /* Restart DSP and set SFI mode */ ret_val = hw->mac.ops.prot_autoc_write(hw, hw->mac.orig_autoc | IXGBE_AUTOC_LMS_10G_SERIAL, false); if (ret_val) { DEBUGOUT("sfp module setup not complete\n"); ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE; goto setup_sfp_out; } } setup_sfp_out: return ret_val; setup_sfp_err: /* Release the semaphore */ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* Delay obtaining semaphore again to allow FW access */ msec_delay(hw->eeprom.semaphore_delay); ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", data_offset); return IXGBE_ERR_PHY; } /** * prot_autoc_read_82599 - Hides MAC differences needed for AUTOC read * @hw: pointer to hardware structure * @locked: Return the if we locked for this read. * @reg_val: Value we read from AUTOC * * For this part (82599) we need to wrap read-modify-writes with a possible * FW/SW lock. It is assumed this lock will be freed with the next * prot_autoc_write_82599(). */ s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) { s32 ret_val; *locked = false; /* If LESM is on then we need to hold the SW/FW semaphore. */ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { ret_val = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); if (ret_val != IXGBE_SUCCESS) return IXGBE_ERR_SWFW_SYNC; *locked = true; } *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); return IXGBE_SUCCESS; } /** * prot_autoc_write_82599 - Hides MAC differences needed for AUTOC write * @hw: pointer to hardware structure * @reg_val: value to write to AUTOC * @locked: bool to indicate whether the SW/FW lock was already taken by * previous proc_autoc_read_82599. * * This part (82599) may need to hold the SW/FW lock around all writes to * AUTOC. Likewise after a write we need to do a pipeline reset. */ s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 autoc, bool locked) { s32 ret_val = IXGBE_SUCCESS; /* Blocked by MNG FW so bail */ if (ixgbe_check_reset_blocked(hw)) goto out; /* We only need to get the lock if: * - We didn't do it already (in the read part of a read-modify-write) * - LESM is enabled. */ if (!locked && ixgbe_verify_lesm_fw_enabled_82599(hw)) { ret_val = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); if (ret_val != IXGBE_SUCCESS) return IXGBE_ERR_SWFW_SYNC; locked = true; } IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); ret_val = ixgbe_reset_pipeline_82599(hw); out: /* Free the SW/FW semaphore as we either grabbed it here or * already had it when this function was called. */ if (locked) hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); return ret_val; } /** * ixgbe_init_ops_82599 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for 82599. * Does not touch the hardware. **/ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; DEBUGFUNC("ixgbe_init_ops_82599"); ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* PHY */ phy->ops.identify = ixgbe_identify_phy_82599; phy->ops.init = ixgbe_init_phy_ops_82599; /* MAC */ mac->ops.reset_hw = ixgbe_reset_hw_82599; mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2; mac->ops.get_media_type = ixgbe_get_media_type_82599; mac->ops.get_supported_physical_layer = ixgbe_get_supported_physical_layer_82599; mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic; mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic; mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_82599; mac->ops.read_analog_reg8 = ixgbe_read_analog_reg8_82599; mac->ops.write_analog_reg8 = ixgbe_write_analog_reg8_82599; mac->ops.start_hw = ixgbe_start_hw_82599; mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic; mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = ixgbe_get_device_caps_generic; mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic; mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic; mac->ops.prot_autoc_read = prot_autoc_read_82599; mac->ops.prot_autoc_write = prot_autoc_write_82599; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = ixgbe_set_vmdq_generic; mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic; mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic; mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; mac->ops.set_vfta = ixgbe_set_vfta_generic; mac->ops.set_vlvf = ixgbe_set_vlvf_generic; mac->ops.clear_vfta = ixgbe_clear_vfta_generic; mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic; mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599; mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing; mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing; /* Link */ mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599; mac->ops.check_link = ixgbe_check_mac_link_generic; mac->ops.setup_rxpba = ixgbe_set_rxpba_generic; ixgbe_init_mac_link_ops_82599(hw); mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; mac->rx_pb_size = IXGBE_82599_RX_PB_SIZE; mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES; mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & IXGBE_FWSM_MODE_MASK) ? true : false; hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; /* EEPROM */ eeprom->ops.read = ixgbe_read_eeprom_82599; eeprom->ops.read_buffer = ixgbe_read_eeprom_buffer_82599; /* Manageability interface */ mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic; mac->ops.get_thermal_sensor_data = ixgbe_get_thermal_sensor_data_generic; mac->ops.init_thermal_sensor_thresh = ixgbe_init_thermal_sensor_thresh_generic; mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic; return ret_val; } /** * ixgbe_get_link_capabilities_82599 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: true when autoneg or autotry is enabled * * Determines the link capabilities by reading the AUTOC register. **/ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = IXGBE_SUCCESS; u32 autoc = 0; DEBUGFUNC("ixgbe_get_link_capabilities_82599"); /* Check if 1G SFP module. */ if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; goto out; } /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not * been stored, use the current register values. */ if (hw->mac.orig_link_settings_stored) autoc = hw->mac.orig_autoc; else autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_10G_SERIAL: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII: *speed = IXGBE_LINK_SPEED_100_FULL; if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_SGMII_1G_100M: *speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL; *autoneg = false; break; default: status = IXGBE_ERR_LINK_SETUP; goto out; break; } if (hw->phy.multispeed_fiber) { *speed |= IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; /* QSFP must not enable full auto-negotiation * Limited autoneg is enabled at 1G */ if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp) *autoneg = false; else *autoneg = true; } out: return status; } /** * ixgbe_get_media_type_82599 - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; DEBUGFUNC("ixgbe_get_media_type_82599"); /* Detect if there is a copper PHY attached. */ switch (hw->phy.type) { case ixgbe_phy_cu_unknown: case ixgbe_phy_tn: media_type = ixgbe_media_type_copper; goto out; default: break; } switch (hw->device_id) { case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_SFP_SF2: case IXGBE_DEV_ID_82599_SFP_SF_QP: case IXGBE_DEV_ID_82599EN_SFP: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: media_type = ixgbe_media_type_cx4; break; case IXGBE_DEV_ID_82599_T3_LOM: media_type = ixgbe_media_type_copper; break; case IXGBE_DEV_ID_82599_LS: media_type = ixgbe_media_type_fiber_lco; break; case IXGBE_DEV_ID_82599_QSFP_SF_QP: media_type = ixgbe_media_type_fiber_qsfp; break; default: media_type = ixgbe_media_type_unknown; break; } out: return media_type; } /** * ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3 * @hw: pointer to hardware structure * * Disables link during D3 power down sequence. * **/ void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw) { u32 autoc2_reg; u16 ee_ctrl_2 = 0; DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599"); ixgbe_read_eeprom(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2); if (!ixgbe_mng_present(hw) && !hw->wol_enabled && ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) { autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2); autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK; IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg); } } /** * ixgbe_start_mac_link_82599 - Setup MAC link settings * @hw: pointer to hardware structure * @autoneg_wait_to_complete: true when waiting for completion is needed * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; bool got_lock = false; DEBUGFUNC("ixgbe_start_mac_link_82599"); /* reset_pipeline requires us to hold this lock as it writes to * AUTOC. */ if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); if (status != IXGBE_SUCCESS) goto out; got_lock = true; } /* Restart link */ ixgbe_reset_pipeline_82599(hw); if (got_lock) hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { links_reg = 0; /* Just in case Autoneg time = 0 */ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msec_delay(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; DEBUGOUT("Autoneg did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msec_delay(50); out: return status; } /** * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser * @hw: pointer to hardware structure * * The base drivers may require better control over SFP+ module * PHY states. This includes selectively shutting down the Tx * laser on the PHY, effectively halting physical link. **/ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); /* Blocked by MNG FW so bail */ if (ixgbe_check_reset_blocked(hw)) return; /* Disable Tx laser; allow 100us to go dark per spec */ esdp_reg |= IXGBE_ESDP_SDP3; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); usec_delay(100); } /** * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser * @hw: pointer to hardware structure * * The base drivers may require better control over SFP+ module * PHY states. This includes selectively turning on the Tx * laser on the PHY, effectively starting physical link. **/ void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); /* Enable Tx laser; allow 100ms to light up */ esdp_reg &= ~IXGBE_ESDP_SDP3; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); msec_delay(100); } /** * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser * @hw: pointer to hardware structure * * When the driver changes the link speeds that it can support, * it sets autotry_restart to true to indicate that we need to * initiate a new autotry session with the link partner. To do * so, we set the speed then disable and re-enable the Tx laser, to * alert the link partner that it also needs to restart autotry on its * end. This is consistent with true clause 37 autoneg, which also * involves a loss of signal. **/ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber"); /* Blocked by MNG FW so bail */ if (ixgbe_check_reset_blocked(hw)) return; if (hw->mac.autotry_restart) { ixgbe_disable_tx_laser_multispeed_fiber(hw); ixgbe_enable_tx_laser_multispeed_fiber(hw); hw->mac.autotry_restart = false; } } /** * ixgbe_set_hard_rate_select_speed - Set module link speed * @hw: pointer to hardware structure * @speed: link speed to set * * Set module link speed via RS0/RS1 rate select pins. */ void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); break; case IXGBE_LINK_SPEED_1GB_FULL: esdp_reg &= ~IXGBE_ESDP_SDP5; esdp_reg |= IXGBE_ESDP_SDP5_DIR; break; default: DEBUGOUT("Invalid fixed module speed\n"); return; } IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Implements the Intel SmartSpeed algorithm. **/ s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 status = IXGBE_SUCCESS; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; s32 i, j; bool link_up = false; u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); DEBUGFUNC("ixgbe_setup_mac_link_smartspeed"); /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (speed & IXGBE_LINK_SPEED_100_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; /* * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the * autoneg advertisement if link is unable to be established at the * highest negotiated rate. This can sometimes happen due to integrity * issues with the physical media connection. */ /* First, try to get link with full advertisement */ hw->phy.smart_speed_active = false; for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) { status = ixgbe_setup_mac_link_82599(hw, speed, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) goto out; /* * Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per * Table 9 in the AN MAS. */ for (i = 0; i < 5; i++) { msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) goto out; if (link_up) goto out; } } /* * We didn't get link. If we advertised KR plus one of KX4/KX * (or BX4/BX), then disable KR and try again. */ if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) || ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0)) goto out; /* Turn SmartSpeed on to disable KR support */ hw->phy.smart_speed_active = true; status = ixgbe_setup_mac_link_82599(hw, speed, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) goto out; /* * Wait for the controller to acquire link. 600ms will allow for * the AN link_fail_inhibit_timer as well for multiple cycles of * parallel detect, both 10g and 1g. This allows for the maximum * connect attempts as defined in the AN MAS table 73-7. */ for (i = 0; i < 6; i++) { msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) goto out; if (link_up) goto out; } /* We didn't get link. Turn SmartSpeed back off. */ hw->phy.smart_speed_active = false; status = ixgbe_setup_mac_link_82599(hw, speed, autoneg_wait_to_complete); out: if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL)) DEBUGOUT("Smartspeed has downgraded the link speed " "from the maximum advertised\n"); return status; } /** * ixgbe_setup_mac_link_82599 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { bool autoneg = false; s32 status = IXGBE_SUCCESS; u32 pma_pmd_1g, link_mode; u32 current_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); /* holds the value of AUTOC register at this current point in time */ u32 orig_autoc = 0; /* holds the cached value of AUTOC register */ u32 autoc = current_autoc; /* Temporary variable used for comparison purposes */ u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; u32 links_reg; u32 i; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; DEBUGFUNC("ixgbe_setup_mac_link_82599"); /* Check to see if speed passed in is supported. */ status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); if (status) goto out; speed &= link_capabilities; if (speed == IXGBE_LINK_SPEED_UNKNOWN) { status = IXGBE_ERR_LINK_SETUP; goto out; } /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/ if (hw->mac.orig_link_settings_stored) orig_autoc = hw->mac.orig_autoc; else orig_autoc = autoc; link_mode = autoc & IXGBE_AUTOC_LMS_MASK; pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); if (speed & IXGBE_LINK_SPEED_10GB_FULL) { if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && (hw->phy.smart_speed_active == false)) autoc |= IXGBE_AUTOC_KR_SUPP; } if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN || link_mode == IXGBE_AUTOC_LMS_1G_AN)) { /* Switch from 1G SFI to 10G SFI if requested */ if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) { autoc &= ~IXGBE_AUTOC_LMS_MASK; autoc |= IXGBE_AUTOC_LMS_10G_SERIAL; } } else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) && (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) { /* Switch from 10G SFI to 1G SFI if requested */ if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) { autoc &= ~IXGBE_AUTOC_LMS_MASK; if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel) autoc |= IXGBE_AUTOC_LMS_1G_AN; else autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN; } } if (autoc != current_autoc) { /* Restart link */ status = hw->mac.ops.prot_autoc_write(hw, autoc, false); if (status != IXGBE_SUCCESS) goto out; /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { links_reg = 0; /*Just in case Autoneg time=0*/ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msec_delay(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; DEBUGOUT("Autoneg did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msec_delay(50); } out: return status; } /** * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true if waiting is needed to complete * * Restarts link on PHY and MAC based on settings passed in. **/ STATIC s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 status; DEBUGFUNC("ixgbe_setup_copper_link_82599"); /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); /* Set up MAC */ ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete); return status; } /** * ixgbe_reset_hw_82599 - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, perform a PHY reset, and perform a link (MAC) * reset. **/ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) { ixgbe_link_speed link_speed; s32 status; u32 ctrl = 0; u32 i, autoc, autoc2; u32 curr_lms; bool link_up = false; DEBUGFUNC("ixgbe_reset_hw_82599"); /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != IXGBE_SUCCESS) goto reset_hw_out; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); /* PHY ops must be identified and initialized prior to reset */ /* Identify PHY and related function pointers */ status = hw->phy.ops.init(hw); if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; /* Setup SFP module if there is one present. */ if (hw->phy.sfp_setup_needed) { status = hw->mac.ops.setup_sfp(hw); hw->phy.sfp_setup_needed = false; } if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; /* Reset PHY */ if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL) hw->phy.ops.reset(hw); /* remember AUTOC from before we reset */ curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK; mac_reset_top: /* * Issue global reset to the MAC. Needs to be SW reset if link is up. * If link reset is used when link is up, it might reset the PHY when * mng is using it. If link is down or the flag to force full link * reset is set, then perform link reset. */ ctrl = IXGBE_CTRL_LNK_RST; if (!hw->force_full_reset) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) ctrl = IXGBE_CTRL_RST; } ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear meaning reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } msec_delay(50); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to * allow time for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* * Store the original AUTOC/AUTOC2 values if they have not been * stored off yet. Otherwise restore the stored original * values since the reset operation sets back to defaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); /* Enable link if disabled in NVM */ if (autoc2 & IXGBE_AUTOC2_LINK_DISABLE_MASK) { autoc2 &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK; IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); IXGBE_WRITE_FLUSH(hw); } if (hw->mac.orig_link_settings_stored == false) { hw->mac.orig_autoc = autoc; hw->mac.orig_autoc2 = autoc2; hw->mac.orig_link_settings_stored = true; } else { /* If MNG FW is running on a multi-speed device that * doesn't autoneg with out driver support we need to * leave LMS in the state it was before we MAC reset. * Likewise if we support WoL we don't want change the * LMS state. */ if ((hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) || hw->wol_enabled) hw->mac.orig_autoc = (hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) | curr_lms; if (autoc != hw->mac.orig_autoc) { status = hw->mac.ops.prot_autoc_write(hw, hw->mac.orig_autoc, false); if (status != IXGBE_SUCCESS) goto reset_hw_out; } if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK; autoc2 |= (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK); IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); } } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); /* Save the SAN MAC RAR index */ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; /* Reserve the last RAR for the SAN MAC address */ hw->mac.num_rar_entries--; } /* Store the alternative WWNN/WWPN prefix */ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, &hw->mac.wwpn_prefix); reset_hw_out: return status; } /** * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete * @hw: pointer to hardware structure * @fdircmd: current value of FDIRCMD register */ STATIC s32 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, u32 *fdircmd) { int i; for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD); if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK)) return IXGBE_SUCCESS; usec_delay(10); } return IXGBE_ERR_FDIR_CMD_INCOMPLETE; } /** * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. * @hw: pointer to hardware structure **/ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) { s32 err; int i; u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); u32 fdircmd; fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; DEBUGFUNC("ixgbe_reinit_fdir_tables_82599"); /* * Before starting reinitialization process, * FDIRCMD.CMD must be zero. */ err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err) { DEBUGOUT("Flow Director previous command did not complete, aborting table re-initialization.\n"); return err; } IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0); IXGBE_WRITE_FLUSH(hw); /* * 82599 adapters flow director init flow cannot be restarted, * Workaround 82599 silicon errata by performing the following steps * before re-writing the FDIRCTRL control register with the same value. * - write 1 to bit 8 of FDIRCMD register & * - write 0 to bit 8 of FDIRCMD register */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) | IXGBE_FDIRCMD_CLEARHT)); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & ~IXGBE_FDIRCMD_CLEARHT)); IXGBE_WRITE_FLUSH(hw); /* * Clear FDIR Hash register to clear any leftover hashes * waiting to be programmed. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); IXGBE_WRITE_FLUSH(hw); /* Poll init-done after we write FDIRCTRL register */ for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; msec_delay(1); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) { DEBUGOUT("Flow Director Signature poll time exceeded!\n"); return IXGBE_ERR_FDIR_REINIT_FAILED; } /* Clear FDIR statistics registers (read to clear) */ IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT); IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); IXGBE_READ_REG(hw, IXGBE_FDIRMISS); IXGBE_READ_REG(hw, IXGBE_FDIRLEN); return IXGBE_SUCCESS; } /** * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register **/ STATIC void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl) { int i; DEBUGFUNC("ixgbe_fdir_enable_82599"); /* Prime the keys for hashing */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY); IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY); /* * Poll init-done after we write the register. Estimated times: * 10G: PBALLOC = 11b, timing is 60us * 1G: PBALLOC = 11b, timing is 600us * 100M: PBALLOC = 11b, timing is 6ms * * Multiple these timings by 4 if under full Rx load * * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for * 1 msec per poll time. If we're at line rate and drop to 100M, then * this might not finish in our poll time, but we can live with that * for now. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); IXGBE_WRITE_FLUSH(hw); for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; msec_delay(1); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) DEBUGOUT("Flow Director poll time exceeded!\n"); } /** * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register, initially * contains just the value of the Rx packet buffer allocation **/ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl) { DEBUGFUNC("ixgbe_init_fdir_signature_82599"); /* * Continue setup of fdirctrl register bits: * Move the flexible bytes to use the ethertype - shift 6 words * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 filters are left */ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); /* write hashes and fdirctrl register, poll for completion */ ixgbe_fdir_enable_82599(hw, fdirctrl); return IXGBE_SUCCESS; } /** * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register, initially * contains just the value of the Rx packet buffer allocation * @cloud_mode: true - cloud mode, false - other mode **/ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, bool cloud_mode) { DEBUGFUNC("ixgbe_init_fdir_perfect_82599"); /* * Continue setup of fdirctrl register bits: * Turn perfect match filtering on * Report hash in RSS field of Rx wb descriptor * Initialize the drop queue * Move the flexible bytes to use the ethertype - shift 6 words * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 (0x4 * 16) filters are left */ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH | IXGBE_FDIRCTRL_REPORT_STATUS | (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) | (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); if (cloud_mode) fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD << IXGBE_FDIRCTRL_FILTERMODE_SHIFT); /* write hashes and fdirctrl register, poll for completion */ ixgbe_fdir_enable_82599(hw, fdirctrl); return IXGBE_SUCCESS; } /* * These defines allow us to quickly generate all of the necessary instructions * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION * for values 0 through 15 */ #define IXGBE_ATR_COMMON_HASH_KEY \ (IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY) #define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \ common_hash ^= lo_hash_dword >> n; \ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ bucket_hash ^= lo_hash_dword >> n; \ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \ sig_hash ^= lo_hash_dword << (16 - n); \ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \ common_hash ^= hi_hash_dword >> n; \ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ bucket_hash ^= hi_hash_dword >> n; \ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \ sig_hash ^= hi_hash_dword << (16 - n); \ } while (0) /** * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash * @stream: input bitstream to compute the hash on * * This function is almost identical to the function above but contains * several optimizations such as unwinding all of the loops, letting the * compiler work out all of the conditional ifs since the keys are static * defines, and computing two keys at once since the hashed dword stream * will be the same for both keys. **/ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common) { u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; u32 sig_hash = 0, bucket_hash = 0, common_hash = 0; /* record the flow_vm_vlan bits as they are a key part to the hash */ flow_vm_vlan = IXGBE_NTOHL(input.dword); /* generate common hash dword */ hi_hash_dword = IXGBE_NTOHL(common.dword); /* low dword is word swapped version of common */ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); /* apply flow ID/VM pool/VLAN ID bits to hash words */ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); /* Process bits 0 and 16 */ IXGBE_COMPUTE_SIG_HASH_ITERATION(0); /* * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to * delay this because bit 0 of the stream should not be processed * so we do not add the VLAN until after bit 0 was processed */ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); /* Process remaining 30 bit of the key */ IXGBE_COMPUTE_SIG_HASH_ITERATION(1); IXGBE_COMPUTE_SIG_HASH_ITERATION(2); IXGBE_COMPUTE_SIG_HASH_ITERATION(3); IXGBE_COMPUTE_SIG_HASH_ITERATION(4); IXGBE_COMPUTE_SIG_HASH_ITERATION(5); IXGBE_COMPUTE_SIG_HASH_ITERATION(6); IXGBE_COMPUTE_SIG_HASH_ITERATION(7); IXGBE_COMPUTE_SIG_HASH_ITERATION(8); IXGBE_COMPUTE_SIG_HASH_ITERATION(9); IXGBE_COMPUTE_SIG_HASH_ITERATION(10); IXGBE_COMPUTE_SIG_HASH_ITERATION(11); IXGBE_COMPUTE_SIG_HASH_ITERATION(12); IXGBE_COMPUTE_SIG_HASH_ITERATION(13); IXGBE_COMPUTE_SIG_HASH_ITERATION(14); IXGBE_COMPUTE_SIG_HASH_ITERATION(15); /* combine common_hash result with signature and bucket hashes */ bucket_hash ^= common_hash; bucket_hash &= IXGBE_ATR_HASH_MASK; sig_hash ^= common_hash << 16; sig_hash &= IXGBE_ATR_HASH_MASK << 16; /* return completed signature hash */ return sig_hash ^ bucket_hash; } /** * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter * @hw: pointer to hardware structure * @input: unique input dword * @common: compressed common input dword * @queue: queue index to direct traffic to * * Note that the tunnel bit in input must not be set when the hardware * tunneling support does not exist. **/ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common, u8 queue) { u64 fdirhashcmd; u8 flow_type; bool tunnel; u32 fdircmd; s32 err; DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599"); /* * Get the flow_type in order to program FDIRCMD properly * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 * fifth is FDIRCMD.TUNNEL_FILTER */ tunnel = !!(input.formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK); flow_type = input.formatted.flow_type & (IXGBE_ATR_L4TYPE_TUNNEL_MASK - 1); switch (flow_type) { case IXGBE_ATR_FLOW_TYPE_TCPV4: case IXGBE_ATR_FLOW_TYPE_UDPV4: case IXGBE_ATR_FLOW_TYPE_SCTPV4: case IXGBE_ATR_FLOW_TYPE_TCPV6: case IXGBE_ATR_FLOW_TYPE_UDPV6: case IXGBE_ATR_FLOW_TYPE_SCTPV6: break; default: DEBUGOUT(" Error on flow type input\n"); return IXGBE_ERR_CONFIG; } /* configure FDIRCMD register */ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; fdircmd |= (u32)flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; if (tunnel) fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER; /* * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH. */ fdirhashcmd = (u64)fdircmd << 32; fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common); IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err) { DEBUGOUT("Flow Director command did not complete!\n"); return err; } DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd); return IXGBE_SUCCESS; } #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ bucket_hash ^= lo_hash_dword >> n; \ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ bucket_hash ^= hi_hash_dword >> n; \ } while (0) /** * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash * @atr_input: input bitstream to compute the hash on * @input_mask: mask for the input bitstream * * This function serves two main purposes. First it applies the input_mask * to the atr_input resulting in a cleaned up atr_input data stream. * Secondly it computes the hash and stores it in the bkt_hash field at * the end of the input byte stream. This way it will be available for * future use without needing to recompute the hash. **/ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *input_mask) { u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; u32 bucket_hash = 0; u32 hi_dword = 0; u32 i = 0; /* Apply masks to input data */ for (i = 0; i < 14; i++) input->dword_stream[i] &= input_mask->dword_stream[i]; /* record the flow_vm_vlan bits as they are a key part to the hash */ flow_vm_vlan = IXGBE_NTOHL(input->dword_stream[0]); /* generate common hash dword */ for (i = 1; i <= 13; i++) hi_dword ^= input->dword_stream[i]; hi_hash_dword = IXGBE_NTOHL(hi_dword); /* low dword is word swapped version of common */ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); /* apply flow ID/VM pool/VLAN ID bits to hash words */ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); /* Process bits 0 and 16 */ IXGBE_COMPUTE_BKT_HASH_ITERATION(0); /* * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to * delay this because bit 0 of the stream should not be processed * so we do not add the VLAN until after bit 0 was processed */ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); /* Process remaining 30 bit of the key */ for (i = 1; i <= 15; i++) IXGBE_COMPUTE_BKT_HASH_ITERATION(i); /* * Limit hash to 13 bits since max bucket count is 8K. * Store result at the end of the input stream. */ input->formatted.bkt_hash = bucket_hash & 0x1FFF; } /** * ixgbe_get_fdirtcpm_82599 - generate a TCP port from atr_input_masks * @input_mask: mask to be bit swapped * * The source and destination port masks for flow director are bit swapped * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc. In order to * generate a correctly swapped value we need to bit swap the mask and that * is what is accomplished by this function. **/ STATIC u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask) { u32 mask = IXGBE_NTOHS(input_mask->formatted.dst_port); mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT; mask |= IXGBE_NTOHS(input_mask->formatted.src_port); mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); } /* * These two macros are meant to address the fact that we have registers * that are either all or in part big-endian. As a result on big-endian * systems we will end up byte swapping the value to little-endian before * it is byte swapped again and written to the hardware in the original * big-endian format. */ #define IXGBE_STORE_AS_BE32(_value) \ (((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \ (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24)) #define IXGBE_WRITE_REG_BE32(a, reg, value) \ IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(IXGBE_NTOHL(value))) #define IXGBE_STORE_AS_BE16(_value) \ IXGBE_NTOHS(((u16)(_value) >> 8) | ((u16)(_value) << 8)) s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input_mask, bool cloud_mode) { /* mask IPv6 since it is currently not supported */ u32 fdirm = IXGBE_FDIRM_DIPv6; u32 fdirtcpm; u32 fdirip6m; DEBUGFUNC("ixgbe_fdir_set_atr_input_mask_82599"); /* * Program the relevant mask registers. If src/dst_port or src/dst_addr * are zero, then assume a full mask for that field. Also assume that * a VLAN of 0 is unspecified, so mask that out as well. L4type * cannot be masked out in this implementation. * * This also assumes IPv4 only. IPv6 masking isn't supported at this * point in time. */ /* verify bucket hash is cleared on hash generation */ if (input_mask->formatted.bkt_hash) DEBUGOUT(" bucket hash should always be 0 in mask\n"); /* Program FDIRM and verify partial masks */ switch (input_mask->formatted.vm_pool & 0x7F) { case 0x0: fdirm |= IXGBE_FDIRM_POOL; case 0x7F: break; default: DEBUGOUT(" Error on vm pool mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) { case 0x0: fdirm |= IXGBE_FDIRM_L4P; if (input_mask->formatted.dst_port || input_mask->formatted.src_port) { DEBUGOUT(" Error on src/dst port mask\n"); return IXGBE_ERR_CONFIG; } case IXGBE_ATR_L4TYPE_MASK: break; default: DEBUGOUT(" Error on flow type mask\n"); return IXGBE_ERR_CONFIG; } switch (IXGBE_NTOHS(input_mask->formatted.vlan_id) & 0xEFFF) { case 0x0000: /* mask VLAN ID, fall through to mask VLAN priority */ fdirm |= IXGBE_FDIRM_VLANID; case 0x0FFF: /* mask VLAN priority */ fdirm |= IXGBE_FDIRM_VLANP; break; case 0xE000: /* mask VLAN ID only, fall through */ fdirm |= IXGBE_FDIRM_VLANID; case 0xEFFF: /* no VLAN fields masked */ break; default: DEBUGOUT(" Error on VLAN mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.flex_bytes & 0xFFFF) { case 0x0000: /* Mask Flex Bytes, fall through */ fdirm |= IXGBE_FDIRM_FLEX; case 0xFFFF: break; default: DEBUGOUT(" Error on flexible byte mask\n"); return IXGBE_ERR_CONFIG; } if (cloud_mode) { fdirm |= IXGBE_FDIRM_L3P; fdirip6m = ((u32) 0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT); fdirip6m |= IXGBE_FDIRIP6M_ALWAYS_MASK; switch (input_mask->formatted.inner_mac[0] & 0xFF) { case 0x00: /* Mask inner MAC, fall through */ fdirip6m |= IXGBE_FDIRIP6M_INNER_MAC; case 0xFF: break; default: DEBUGOUT(" Error on inner_mac byte mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.tni_vni & 0xFFFFFFFF) { case 0x0: /* Mask vxlan id */ fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI; break; case 0x00FFFFFF: fdirip6m |= IXGBE_FDIRIP6M_TNI_VNI_24; break; case 0xFFFFFFFF: break; default: DEBUGOUT(" Error on TNI/VNI byte mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.tunnel_type & 0xFFFF) { case 0x0: /* Mask turnnel type, fall through */ fdirip6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE; case 0xFFFF: break; default: DEBUGOUT(" Error on tunnel type byte mask\n"); return IXGBE_ERR_CONFIG; } IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIP6M, fdirip6m); /* Set all bits in FDIRTCPM, FDIRUDPM, FDIRSIP4M and * FDIRDIP4M in cloud mode to allow L3/L3 packets to * tunnel. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF); } /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); if (!cloud_mode) { /* store the TCP/UDP port masks, bit reversed from port * layout */ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask); /* write both the same so that UDP and TCP use the same mask */ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); /* also use it for SCTP */ switch (hw->mac.type) { case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); break; default: break; } /* store source and destination IP masks (big-enian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, ~input_mask->formatted.src_ip[0]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, ~input_mask->formatted.dst_ip[0]); } return IXGBE_SUCCESS; } s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id, u8 queue, bool cloud_mode) { u32 fdirport, fdirvlan, fdirhash, fdircmd; u32 addr_low, addr_high; u32 cloud_type = 0; s32 err; DEBUGFUNC("ixgbe_fdir_write_perfect_filter_82599"); if (!cloud_mode) { /* currently IPv6 is not supported, must be programmed with 0 */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), input->formatted.src_ip[0]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), input->formatted.src_ip[1]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.src_ip[2]); /* record the source address (big-endian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]); /* record the first 32 bits of the destination address * (big-endian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]); /* record source and destination port (little-endian)*/ fdirport = IXGBE_NTOHS(input->formatted.dst_port); fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT; fdirport |= IXGBE_NTOHS(input->formatted.src_port); IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport); } /* record VLAN (little-endian) and flex_bytes(big-endian) */ fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes); fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT; fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id); IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan); if (cloud_mode) { if (input->formatted.tunnel_type != 0) cloud_type = 0x80000000; addr_low = ((u32)input->formatted.inner_mac[0] | ((u32)input->formatted.inner_mac[1] << 8) | ((u32)input->formatted.inner_mac[2] << 16) | ((u32)input->formatted.inner_mac[3] << 24)); addr_high = ((u32)input->formatted.inner_mac[4] | ((u32)input->formatted.inner_mac[5] << 8)); cloud_type |= addr_high; IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), addr_low); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), cloud_type); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.tni_vni); } /* configure FDIRHASH register */ fdirhash = input->formatted.bkt_hash; fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* * flush all previous writes to make certain registers are * programmed prior to issuing the command */ IXGBE_WRITE_FLUSH(hw); /* configure FDIRCMD register */ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; if (queue == IXGBE_FDIR_DROP_QUEUE) fdircmd |= IXGBE_FDIRCMD_DROP; if (input->formatted.flow_type & IXGBE_ATR_L4TYPE_TUNNEL_MASK) fdircmd |= IXGBE_FDIRCMD_TUNNEL_FILTER; fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err) { DEBUGOUT("Flow Director command did not complete!\n"); return err; } return IXGBE_SUCCESS; } s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id) { u32 fdirhash; u32 fdircmd; s32 err; /* configure FDIRHASH register */ fdirhash = input->formatted.bkt_hash; fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* flush hash to HW */ IXGBE_WRITE_FLUSH(hw); /* Query if filter is present */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err) { DEBUGOUT("Flow Director command did not complete!\n"); return err; } /* if filter exists in hardware then remove it */ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) { IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_REMOVE_FLOW); } return IXGBE_SUCCESS; } /** * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter * @hw: pointer to hardware structure * @input: input bitstream * @input_mask: mask for the input bitstream * @soft_id: software index for the filters * @queue: queue index to direct traffic to * * Note that the caller to this function must lock before calling, since the * hardware writes must be protected from one another. **/ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, union ixgbe_atr_input *input_mask, u16 soft_id, u8 queue, bool cloud_mode) { s32 err = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599"); /* * Check flow_type formatting, and bail out before we touch the hardware * if there's a configuration issue */ switch (input->formatted.flow_type) { case IXGBE_ATR_FLOW_TYPE_IPV4: case IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV4: input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK; if (input->formatted.dst_port || input->formatted.src_port) { DEBUGOUT(" Error on src/dst port\n"); return IXGBE_ERR_CONFIG; } break; case IXGBE_ATR_FLOW_TYPE_SCTPV4: case IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV4: if (input->formatted.dst_port || input->formatted.src_port) { DEBUGOUT(" Error on src/dst port\n"); return IXGBE_ERR_CONFIG; } case IXGBE_ATR_FLOW_TYPE_TCPV4: case IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV4: case IXGBE_ATR_FLOW_TYPE_UDPV4: case IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV4: input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK | IXGBE_ATR_L4TYPE_MASK; break; default: DEBUGOUT(" Error on flow type input\n"); return err; } /* program input mask into the HW */ err = ixgbe_fdir_set_input_mask_82599(hw, input_mask, cloud_mode); if (err) return err; /* apply mask and compute/store hash */ ixgbe_atr_compute_perfect_hash_82599(input, input_mask); /* program filters to filter memory */ return ixgbe_fdir_write_perfect_filter_82599(hw, input, soft_id, queue, cloud_mode); } /** * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs read operation to Omer analog register specified. **/ s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 core_ctl; DEBUGFUNC("ixgbe_read_analog_reg8_82599"); IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); usec_delay(10); core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL); *val = (u8)core_ctl; return IXGBE_SUCCESS; } /** * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register * @hw: pointer to hardware structure * @reg: atlas register to write * @val: value to write * * Performs write operation to Omer analog register specified. **/ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 core_ctl; DEBUGFUNC("ixgbe_write_analog_reg8_82599"); core_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl); IXGBE_WRITE_FLUSH(hw); usec_delay(10); return IXGBE_SUCCESS; } /** * ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function * and the generation start_hw function. * Then performs revision-specific operations, if any. **/ s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_start_hw_82599"); ret_val = ixgbe_start_hw_generic(hw); if (ret_val != IXGBE_SUCCESS) goto out; ret_val = ixgbe_start_hw_gen2(hw); if (ret_val != IXGBE_SUCCESS) goto out; /* We need to run link autotry after the driver loads */ hw->mac.autotry_restart = true; if (ret_val == IXGBE_SUCCESS) ret_val = ixgbe_verify_fw_version_82599(hw); out: return ret_val; } /** * ixgbe_identify_phy_82599 - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. * If PHY already detected, maintains current PHY type in hw struct, * otherwise executes the PHY detection routine. **/ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) { s32 status; DEBUGFUNC("ixgbe_identify_phy_82599"); /* Detect PHY if not unknown - returns success if already detected. */ status = ixgbe_identify_phy_generic(hw); if (status != IXGBE_SUCCESS) { /* 82599 10GBASE-T requires an external PHY */ if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) return status; else status = ixgbe_identify_module_generic(hw); } /* Set PHY type none if no PHY detected */ if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.type = ixgbe_phy_none; return IXGBE_SUCCESS; } /* Return error if SFP module has been detected but is not supported */ if (hw->phy.type == ixgbe_phy_sfp_unsupported) return IXGBE_ERR_SFP_NOT_SUPPORTED; return status; } /** * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; DEBUGFUNC("ixgbe_get_support_physical_layer_82599"); hw->phy.ops.identify(hw); switch (hw->phy.type) { case ixgbe_phy_tn: case ixgbe_phy_cu_unknown: hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; default: break; } switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_AN: case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) { physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX | IXGBE_PHYSICAL_LAYER_1000BASE_BX; goto out; } else /* SFI mode so read SFP module */ goto sfp_check; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI; goto out; break; case IXGBE_AUTOC_LMS_10G_SERIAL: if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) { physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR; goto out; } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) goto sfp_check; break; case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: if (autoc & IXGBE_AUTOC_KX_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; if (autoc & IXGBE_AUTOC_KX4_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; if (autoc & IXGBE_AUTOC_KR_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR; goto out; break; default: goto out; break; } sfp_check: /* SFP check must be done last since DA modules are sometimes used to * test KR mode - we need to id KR mode correctly before SFP module. * Call identify_sfp because the pluggable module may have changed */ physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); out: return physical_layer; } /** * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599 * @hw: pointer to hardware structure * @regval: register value to write to RXCTRL * * Enables the Rx DMA unit for 82599 **/ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) { DEBUGFUNC("ixgbe_enable_rx_dma_82599"); /* * Workaround for 82599 silicon errata when enabling the Rx datapath. * If traffic is incoming before we enable the Rx unit, it could hang * the Rx DMA unit. Therefore, make sure the security engine is * completely disabled prior to enabling the Rx unit. */ hw->mac.ops.disable_sec_rx_path(hw); if (regval & IXGBE_RXCTRL_RXEN) ixgbe_enable_rx(hw); else ixgbe_disable_rx(hw); hw->mac.ops.enable_sec_rx_path(hw); return IXGBE_SUCCESS; } /** * ixgbe_verify_fw_version_82599 - verify FW version for 82599 * @hw: pointer to hardware structure * * Verifies that installed the firmware version is 0.6 or higher * for SFI devices. All 82599 SFI devices should have version 0.6 or higher. * * Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or * if the FW version is not supported. **/ STATIC s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM_VERSION; u16 fw_offset, fw_ptp_cfg_offset; u16 fw_version; DEBUGFUNC("ixgbe_verify_fw_version_82599"); /* firmware check is only necessary for SFI devices */ if (hw->phy.media_type != ixgbe_media_type_fiber) { status = IXGBE_SUCCESS; goto fw_version_out; } /* get the offset to the Firmware Module block */ if (hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", IXGBE_FW_PTR); return IXGBE_ERR_EEPROM_VERSION; } if ((fw_offset == 0) || (fw_offset == 0xFFFF)) goto fw_version_out; /* get the offset to the Pass Through Patch Configuration block */ if (hw->eeprom.ops.read(hw, (fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR), &fw_ptp_cfg_offset)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR); return IXGBE_ERR_EEPROM_VERSION; } if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF)) goto fw_version_out; /* get the firmware version */ if (hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4), &fw_version)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4); return IXGBE_ERR_EEPROM_VERSION; } if (fw_version > 0x5) status = IXGBE_SUCCESS; fw_version_out: return status; } /** * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state. * @hw: pointer to hardware structure * * Returns true if the LESM FW module is present and enabled. Otherwise * returns false. Smart Speed must be disabled if LESM FW module is enabled. **/ bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) { bool lesm_enabled = false; u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; s32 status; DEBUGFUNC("ixgbe_verify_lesm_fw_enabled_82599"); /* get the offset to the Firmware Module block */ status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); if ((status != IXGBE_SUCCESS) || (fw_offset == 0) || (fw_offset == 0xFFFF)) goto out; /* get the offset to the LESM Parameters block */ status = hw->eeprom.ops.read(hw, (fw_offset + IXGBE_FW_LESM_PARAMETERS_PTR), &fw_lesm_param_offset); if ((status != IXGBE_SUCCESS) || (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF)) goto out; /* get the LESM state word */ status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset + IXGBE_FW_LESM_STATE_1), &fw_lesm_state); if ((status == IXGBE_SUCCESS) && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED)) lesm_enabled = true; out: return lesm_enabled; } /** * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using * fastest available method * * @hw: pointer to hardware structure * @offset: offset of word in EEPROM to read * @words: number of words * @data: word(s) read from the EEPROM * * Retrieves 16 bit word(s) read from EEPROM **/ STATIC s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_read_eeprom_buffer_82599"); /* * If EEPROM is detected and can be addressed using 14 bits, * use EERD otherwise use bit bang */ if ((eeprom->type == ixgbe_eeprom_spi) && (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)) ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words, data); else ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words, data); return ret_val; } /** * ixgbe_read_eeprom_82599 - Read EEPROM word using * fastest available method * * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM **/ STATIC s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, u16 offset, u16 *data) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val = IXGBE_ERR_CONFIG; DEBUGFUNC("ixgbe_read_eeprom_82599"); /* * If EEPROM is detected and can be addressed using 14 bits, * use EERD otherwise use bit bang */ if ((eeprom->type == ixgbe_eeprom_spi) && (offset <= IXGBE_EERD_MAX_ADDR)) ret_val = ixgbe_read_eerd_generic(hw, offset, data); else ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data); return ret_val; } /** * ixgbe_reset_pipeline_82599 - perform pipeline reset * * @hw: pointer to hardware structure * * Reset pipeline by asserting Restart_AN together with LMS change to ensure * full pipeline reset. This function assumes the SW/FW lock is held. **/ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw) { s32 ret_val; u32 anlp1_reg = 0; u32 i, autoc_reg, autoc2_reg; /* Enable link if disabled in NVM */ autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2); if (autoc2_reg & IXGBE_AUTOC2_LINK_DISABLE_MASK) { autoc2_reg &= ~IXGBE_AUTOC2_LINK_DISABLE_MASK; IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg); IXGBE_WRITE_FLUSH(hw); } autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ (0x4 << IXGBE_AUTOC_LMS_SHIFT)); /* Wait for AN to leave state 0 */ for (i = 0; i < 10; i++) { msec_delay(4); anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK) break; } if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) { DEBUGOUT("auto negotiation not completed\n"); ret_val = IXGBE_ERR_RESET_FAILED; goto reset_pipeline_out; } ret_val = IXGBE_SUCCESS; reset_pipeline_out: /* Write AUTOC register with original LMS field and Restart_AN */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); IXGBE_WRITE_FLUSH(hw); return ret_val; } /** * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ STATIC s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { u32 esdp; s32 status; s32 timeout = 200; DEBUGFUNC("ixgbe_read_i2c_byte_82599"); if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Acquire I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); while (timeout) { esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) break; msec_delay(5); timeout--; } if (!timeout) { DEBUGOUT("Driver can't access resource," " acquiring I2C bus timeout.\n"); status = IXGBE_ERR_I2C; goto release_i2c_access; } } status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data); release_i2c_access: if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Release I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp &= ~IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } return status; } /** * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ STATIC s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { u32 esdp; s32 status; s32 timeout = 200; DEBUGFUNC("ixgbe_write_i2c_byte_82599"); if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Acquire I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); while (timeout) { esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) break; msec_delay(5); timeout--; } if (!timeout) { DEBUGOUT("Driver can't access resource," " acquiring I2C bus timeout.\n"); status = IXGBE_ERR_I2C; goto release_i2c_access; } } status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data); release_i2c_access: if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Release I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp &= ~IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } return status; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_82599.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_82599_H_ #define _IXGBE_82599_H_ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw); void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed); s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval); s32 prot_autoc_read_82599(struct ixgbe_hw *hw, bool *locked, u32 *reg_val); s32 prot_autoc_write_82599(struct ixgbe_hw *hw, u32 reg_val, bool locked); #endif /* _IXGBE_82599_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_api.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_common.h" #define IXGBE_EMPTY_PARAM static const u32 ixgbe_mvals_base[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(IXGBE_EMPTY_PARAM) }; static const u32 ixgbe_mvals_X540[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(_X540) }; static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(_X550) }; static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { IXGBE_MVALS_INIT(_X550EM_x) }; /** * ixgbe_dcb_get_rtrup2tc - read rtrup2tc reg * @hw: pointer to hardware structure * @map: pointer to u8 arr for returning map * * Read the rtrup2tc HW register and resolve its content into map **/ void ixgbe_dcb_get_rtrup2tc(struct ixgbe_hw *hw, u8 *map) { if (hw->mac.ops.get_rtrup2tc) hw->mac.ops.get_rtrup2tc(hw, map); } /** * ixgbe_init_shared_code - Initialize the shared code * @hw: pointer to hardware structure * * This will assign function pointers and assign the MAC type and PHY code. * Does not touch the hardware. This function must be called prior to any * other function in the shared code. The ixgbe_hw structure should be * memset to 0 prior to calling this function. The following fields in * hw structure should be filled in prior to calling this function: * hw_addr, back, device_id, vendor_id, subsystem_device_id, * subsystem_vendor_id, and revision_id **/ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) { s32 status; DEBUGFUNC("ixgbe_init_shared_code"); /* * Set the mac type */ ixgbe_set_mac_type(hw); switch (hw->mac.type) { case ixgbe_mac_82598EB: status = ixgbe_init_ops_82598(hw); break; case ixgbe_mac_82599EB: status = ixgbe_init_ops_82599(hw); break; case ixgbe_mac_X540: status = ixgbe_init_ops_X540(hw); break; case ixgbe_mac_X550: status = ixgbe_init_ops_X550(hw); break; case ixgbe_mac_X550EM_x: status = ixgbe_init_ops_X550EM(hw); break; case ixgbe_mac_82599_vf: case ixgbe_mac_X540_vf: case ixgbe_mac_X550_vf: case ixgbe_mac_X550EM_x_vf: status = ixgbe_init_ops_vf(hw); break; default: status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME; return status; } /** * ixgbe_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * vendor ID and device ID stored in the hw structure. **/ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_set_mac_type\n"); if (hw->vendor_id != IXGBE_INTEL_VENDOR_ID) { ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Unsupported vendor id: %x", hw->vendor_id); return IXGBE_ERR_DEVICE_NOT_SUPPORTED; } hw->mvals = ixgbe_mvals_base; switch (hw->device_id) { case IXGBE_DEV_ID_82598: case IXGBE_DEV_ID_82598_BX: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AT: case IXGBE_DEV_ID_82598AT2: case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: hw->mac.type = ixgbe_mac_82598EB; break; case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_XAUI_LOM: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_SFP_SF2: case IXGBE_DEV_ID_82599_SFP_SF_QP: case IXGBE_DEV_ID_82599_QSFP_SF_QP: case IXGBE_DEV_ID_82599EN_SFP: case IXGBE_DEV_ID_82599_CX4: case IXGBE_DEV_ID_82599_LS: case IXGBE_DEV_ID_82599_T3_LOM: hw->mac.type = ixgbe_mac_82599EB; break; case IXGBE_DEV_ID_82599_VF: case IXGBE_DEV_ID_82599_VF_HV: hw->mac.type = ixgbe_mac_82599_vf; break; case IXGBE_DEV_ID_X540_VF: case IXGBE_DEV_ID_X540_VF_HV: hw->mac.type = ixgbe_mac_X540_vf; hw->mvals = ixgbe_mvals_X540; break; case IXGBE_DEV_ID_X540T: case IXGBE_DEV_ID_X540T1: hw->mac.type = ixgbe_mac_X540; hw->mvals = ixgbe_mvals_X540; break; case IXGBE_DEV_ID_X550T: hw->mac.type = ixgbe_mac_X550; hw->mvals = ixgbe_mvals_X550; break; case IXGBE_DEV_ID_X550EM_X_KX4: case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_10G_T: case IXGBE_DEV_ID_X550EM_X_1G_T: case IXGBE_DEV_ID_X550EM_X_SFP: hw->mac.type = ixgbe_mac_X550EM_x; hw->mvals = ixgbe_mvals_X550EM_x; break; case IXGBE_DEV_ID_X550_VF: case IXGBE_DEV_ID_X550_VF_HV: hw->mac.type = ixgbe_mac_X550_vf; hw->mvals = ixgbe_mvals_X550; break; case IXGBE_DEV_ID_X550EM_X_VF: case IXGBE_DEV_ID_X550EM_X_VF_HV: hw->mac.type = ixgbe_mac_X550EM_x_vf; hw->mvals = ixgbe_mvals_X550EM_x; break; default: ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Unsupported device id: %x", hw->device_id); break; } DEBUGOUT2("ixgbe_set_mac_type found mac: %d, returns: %d\n", hw->mac.type, ret_val); return ret_val; } /** * ixgbe_init_hw - Initialize the hardware * @hw: pointer to hardware structure * * Initialize the hardware by resetting and then starting the hardware **/ s32 ixgbe_init_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_reset_hw - Performs a hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performs a PHY reset, and performs a MAC reset **/ s32 ixgbe_reset_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.reset_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_start_hw - Prepares hardware for Rx/Tx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, * clears all on chip counters, initializes receive address registers, * multicast table, VLAN filter table, calls routine to setup link and * flow control settings, and leaves transmit and receive units disabled * and uninitialized. **/ s32 ixgbe_start_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.start_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_enable_relaxed_ordering - Enables tx relaxed ordering, * which is disabled by default in ixgbe_start_hw(); * * @hw: pointer to hardware structure * * Enable relaxed ordering; **/ void ixgbe_enable_relaxed_ordering(struct ixgbe_hw *hw) { if (hw->mac.ops.enable_relaxed_ordering) hw->mac.ops.enable_relaxed_ordering(hw); } /** * ixgbe_clear_hw_cntrs - Clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/ s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.clear_hw_cntrs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_media_type - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_media_type, (hw), ixgbe_media_type_unknown); } /** * ixgbe_get_mac_addr - Get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * * Reads the adapter's MAC address from the first Receive Address Register * (RAR0) A reset of the adapter must have been performed prior to calling * this function in order for the MAC address to have been loaded from the * EEPROM into RAR0 **/ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.get_mac_addr, (hw, mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_san_mac_addr - Get SAN MAC address * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Reads the SAN MAC address from the EEPROM, if it's available. This is * per-port, so set_lan_id() must be called before reading the addresses. **/ s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.get_san_mac_addr, (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_san_mac_addr - Write a SAN MAC address * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Writes A SAN MAC address to the EEPROM. **/ s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.set_san_mac_addr, (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_device_caps - Get additional device capabilities * @hw: pointer to hardware structure * @device_caps: the EEPROM word for device capabilities * * Reads the extra device capabilities from the EEPROM **/ s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps) { return ixgbe_call_func(hw, hw->mac.ops.get_device_caps, (hw, device_caps), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from the EEPROM * @hw: pointer to hardware structure * @wwnn_prefix: the alternative WWNN prefix * @wwpn_prefix: the alternative WWPN prefix * * This function will read the EEPROM from the alternative SAN MAC address * block to check the support for the alternative WWNN/WWPN prefix support. **/ s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix) { return ixgbe_call_func(hw, hw->mac.ops.get_wwn_prefix, (hw, wwnn_prefix, wwpn_prefix), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_fcoe_boot_status - Get FCOE boot status from EEPROM * @hw: pointer to hardware structure * @bs: the fcoe boot status * * This function will read the FCOE boot status from the iSCSI FCOE block **/ s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs) { return ixgbe_call_func(hw, hw->mac.ops.get_fcoe_boot_status, (hw, bs), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_bus_info - Set PCI bus info * @hw: pointer to hardware structure * * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure **/ s32 ixgbe_get_bus_info(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_bus_info, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_num_of_tx_queues - Get Tx queues * @hw: pointer to hardware structure * * Returns the number of transmit queues for the given adapter. **/ u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw) { return hw->mac.max_tx_queues; } /** * ixgbe_get_num_of_rx_queues - Get Rx queues * @hw: pointer to hardware structure * * Returns the number of receive queues for the given adapter. **/ u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw) { return hw->mac.max_rx_queues; } /** * ixgbe_stop_adapter - Disable Rx/Tx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.stop_adapter, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_pba_string - Reads part number string from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number string from the EEPROM * @pba_num_size: part number string buffer length * * Reads the part number string from the EEPROM. **/ s32 ixgbe_read_pba_string(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size) { return ixgbe_read_pba_string_generic(hw, pba_num, pba_num_size); } /** * ixgbe_read_pba_num - Reads part number from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number from the EEPROM * * Reads the part number from the EEPROM. **/ s32 ixgbe_read_pba_num(struct ixgbe_hw *hw, u32 *pba_num) { return ixgbe_read_pba_num_generic(hw, pba_num); } /** * ixgbe_identify_phy - Get PHY type * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ s32 ixgbe_identify_phy(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; if (hw->phy.type == ixgbe_phy_unknown) { status = ixgbe_call_func(hw, hw->phy.ops.identify, (hw), IXGBE_NOT_IMPLEMENTED); } return status; } /** * ixgbe_reset_phy - Perform a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; if (hw->phy.type == ixgbe_phy_unknown) { if (ixgbe_identify_phy(hw) != IXGBE_SUCCESS) status = IXGBE_ERR_PHY; } if (status == IXGBE_SUCCESS) { status = ixgbe_call_func(hw, hw->phy.ops.reset, (hw), IXGBE_NOT_IMPLEMENTED); } return status; } /** * ixgbe_get_phy_firmware_version - * @hw: pointer to hardware structure * @firmware_version: pointer to firmware version **/ s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status = IXGBE_SUCCESS; status = ixgbe_call_func(hw, hw->phy.ops.get_firmware_version, (hw, firmware_version), IXGBE_NOT_IMPLEMENTED); return status; } /** * ixgbe_read_phy_reg - Read PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register * * Reads a value from a specified PHY register **/ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); return ixgbe_call_func(hw, hw->phy.ops.read_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_phy_reg - Write PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @phy_data: Data to write to the PHY register * * Writes a value to specified PHY register **/ s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); return ixgbe_call_func(hw, hw->phy.ops.write_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_phy_link - Restart PHY autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->phy.ops.setup_link, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_internal_phy - Configure integrated PHY * @hw: pointer to hardware structure * * Reconfigure the integrated PHY in order to enable talk to the external PHY. * Returns success if not implemented, since nothing needs to be done in this * case. */ s32 ixgbe_setup_internal_phy(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->phy.ops.setup_internal_link, (hw), IXGBE_SUCCESS); } /** * ixgbe_check_phy_link - Determine link and speed status * @hw: pointer to hardware structure * * Reads a PHY register to determine if link is up and the current speed for * the PHY. **/ s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up) { return ixgbe_call_func(hw, hw->phy.ops.check_link, (hw, speed, link_up), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_phy_link_speed - Set auto advertise * @hw: pointer to hardware structure * @speed: new link speed * * Sets the auto advertised capabilities **/ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { return ixgbe_call_func(hw, hw->phy.ops.setup_link_speed, (hw, speed, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_phy_power - Control the phy power state * @hw: pointer to hardware structure * @on: true for on, false for off */ s32 ixgbe_set_phy_power(struct ixgbe_hw *hw, bool on) { return ixgbe_call_func(hw, hw->phy.ops.set_phy_power, (hw, on), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_check_link - Get link and speed status * @hw: pointer to hardware structure * * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { return ixgbe_call_func(hw, hw->mac.ops.check_link, (hw, speed, link_up, link_up_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_tx_laser - Disable Tx laser * @hw: pointer to hardware structure * * If the driver needs to disable the laser on SFI optics. **/ void ixgbe_disable_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); } /** * ixgbe_enable_tx_laser - Enable Tx laser * @hw: pointer to hardware structure * * If the driver needs to enable the laser on SFI optics. **/ void ixgbe_enable_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.enable_tx_laser) hw->mac.ops.enable_tx_laser(hw); } /** * ixgbe_flap_tx_laser - flap Tx laser to start autotry process * @hw: pointer to hardware structure * * When the driver changes the link speeds that it can support then * flap the tx laser to alert the link partner to start autotry * process on its end. **/ void ixgbe_flap_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.flap_tx_laser) hw->mac.ops.flap_tx_laser(hw); } /** * ixgbe_setup_link - Set link speed * @hw: pointer to hardware structure * @speed: new link speed * * Configures link settings. Restarts the link. * Performs autonegotiation if needed. **/ s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw, speed, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_mac_link - Set link speed * @hw: pointer to hardware structure * @speed: new link speed * * Configures link settings. Restarts the link. * Performs autonegotiation if needed. **/ s32 ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { return ixgbe_call_func(hw, hw->mac.ops.setup_mac_link, (hw, speed, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_link_capabilities - Returns link capabilities * @hw: pointer to hardware structure * * Determines the link capabilities of the current configuration. **/ s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { return ixgbe_call_func(hw, hw->mac.ops.get_link_capabilities, (hw, speed, autoneg), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_led_on - Turn on LEDs * @hw: pointer to hardware structure * @index: led number to turn on * * Turns on the software controllable LEDs. **/ s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.led_on, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_led_off - Turn off LEDs * @hw: pointer to hardware structure * @index: led number to turn off * * Turns off the software controllable LEDs. **/ s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.led_off, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_blink_led_start - Blink LEDs * @hw: pointer to hardware structure * @index: led number to blink * * Blink LED based on index. **/ s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.blink_led_start, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_blink_led_stop - Stop blinking LEDs * @hw: pointer to hardware structure * * Stop blinking LED based on index. **/ s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.blink_led_stop, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_eeprom_params - Initialize EEPROM parameters * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->eeprom.ops.init_params, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_eeprom - Write word to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word to be written to the EEPROM * * Writes 16 bit value to EEPROM. If ixgbe_eeprom_update_checksum is not * called after this function, the EEPROM will most likely contain an * invalid checksum. **/ s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data) { return ixgbe_call_func(hw, hw->eeprom.ops.write, (hw, offset, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_eeprom_buffer - Write word(s) to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word(s) to be written to the EEPROM * @words: number of words * * Writes 16 bit word(s) to EEPROM. If ixgbe_eeprom_update_checksum is not * called after this function, the EEPROM will most likely contain an * invalid checksum. **/ s32 ixgbe_write_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.write_buffer, (hw, offset, words, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_eeprom - Read word from EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit value from EEPROM * * Reads 16 bit value from EEPROM **/ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.read, (hw, offset, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_eeprom_buffer - Read word(s) from EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit word(s) from EEPROM * @words: number of words * * Reads 16 bit word(s) from EEPROM **/ s32 ixgbe_read_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.read_buffer, (hw, offset, words, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_validate_eeprom_checksum - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum **/ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val) { return ixgbe_call_func(hw, hw->eeprom.ops.validate_checksum, (hw, checksum_val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_eeprom_update_checksum - Updates the EEPROM checksum * @hw: pointer to hardware structure **/ s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->eeprom.ops.update_checksum, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_insert_mac_addr - Find a RAR for this mac address * @hw: pointer to hardware structure * @addr: Address to put into receive address register * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or * finds the rar that it is aleady in; adds to the pool list **/ s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.insert_mac_addr, (hw, addr, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_rar - Set Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: VMDq "set" * @enable_addr: set flag that address is active * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { return ixgbe_call_func(hw, hw->mac.ops.set_rar, (hw, index, addr, vmdq, enable_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_rar - Clear Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.clear_rar, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vmdq - Associate a VMDq index with a receive address * @hw: pointer to hardware structure * @rar: receive address register index to associate with VMDq index * @vmdq: VMDq set or pool index **/ s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.set_vmdq, (hw, rar, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vmdq_san_mac - Associate VMDq index 127 with a receive address * @hw: pointer to hardware structure * @vmdq: VMDq default pool index **/ s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.set_vmdq_san_mac, (hw, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_vmdq - Disassociate a VMDq index from a receive address * @hw: pointer to hardware structure * @rar: receive address register index to disassociate with VMDq index * @vmdq: VMDq set or pool index **/ s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.clear_vmdq, (hw, rar, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_rx_addrs - Initializes receive address filters. * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_rx_addrs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_num_rx_addrs - Returns the number of RAR entries. * @hw: pointer to hardware structure **/ u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw) { return hw->mac.num_rar_entries; } /** * ixgbe_update_uc_addr_list - Updates the MAC's list of secondary addresses * @hw: pointer to hardware structure * @addr_list: the list of new multicast addresses * @addr_count: number of addresses * @func: iterator function to walk the multicast address list * * The given list replaces any existing list. Clears the secondary addrs from * receive address registers. Uses unused receive address registers for the * first secondary addresses, and falls back to promiscuous mode as needed. **/ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func) { return ixgbe_call_func(hw, hw->mac.ops.update_uc_addr_list, (hw, addr_list, addr_count, func), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_update_mc_addr_list - Updates the MAC's list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @func: iterator function to walk the multicast address list * * The given list replaces any existing list. Clears the MC addrs from receive * address registers and the multicast table. Uses unused receive address * registers for the first multicast addresses, and hashes the rest into the * multicast table. **/ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear) { return ixgbe_call_func(hw, hw->mac.ops.update_mc_addr_list, (hw, mc_addr_list, mc_addr_count, func, clear), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_enable_mc - Enable multicast address in RAR * @hw: pointer to hardware structure * * Enables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_enable_mc(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.enable_mc, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_mc - Disable multicast address in RAR * @hw: pointer to hardware structure * * Disables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_disable_mc(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.disable_mc, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_vfta - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.clear_vfta, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vfta - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFTA * @vlan_on: boolean flag to turn on/off VLAN in VFTA * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { return ixgbe_call_func(hw, hw->mac.ops.set_vfta, (hw, vlan, vind, vlan_on), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vlvf - Set VLAN Pool Filter * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * @vfta_changed: pointer to boolean flag which indicates whether VFTA * should be changed * * Turn on/off specified bit in VLVF table. **/ s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed) { return ixgbe_call_func(hw, hw->mac.ops.set_vlvf, (hw, vlan, vind, vlan_on, vfta_changed), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_fc_enable - Enable flow control * @hw: pointer to hardware structure * * Configures the flow control settings based on SW configuration. **/ s32 ixgbe_fc_enable(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.fc_enable, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_fc - Set up flow control * @hw: pointer to hardware structure * * Called at init time to set up flow control. **/ s32 ixgbe_setup_fc(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.setup_fc, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_fw_drv_ver - Try to send the driver version number FW * @hw: pointer to hardware structure * @maj: driver major number to be sent to firmware * @min: driver minor number to be sent to firmware * @build: driver build number to be sent to firmware * @ver: driver version number to be sent to firmware **/ s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver) { return ixgbe_call_func(hw, hw->mac.ops.set_fw_drv_ver, (hw, maj, min, build, ver), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data * @hw: pointer to hardware structure * * Updates the temperatures in mac.thermal_sensor_data **/ s32 ixgbe_get_thermal_sensor_data(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_thermal_sensor_data, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds * @hw: pointer to hardware structure * * Inits the thermal sensor thresholds according to the NVM map **/ s32 ixgbe_init_thermal_sensor_thresh(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_thermal_sensor_thresh, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_dmac_config - Configure DMA Coalescing registers. * @hw: pointer to hardware structure * * Configure DMA coalescing. If enabling dmac, dmac is activated. * When disabling dmac, dmac enable dmac bit is cleared. **/ s32 ixgbe_dmac_config(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.dmac_config, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_dmac_update_tcs - Configure DMA Coalescing registers. * @hw: pointer to hardware structure * * Disables dmac, updates per TC settings, and then enable dmac. **/ s32 ixgbe_dmac_update_tcs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.dmac_update_tcs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_dmac_config_tcs - Configure DMA Coalescing registers. * @hw: pointer to hardware structure * * Configure DMA coalescing threshold per TC and set high priority bit for * FCOE TC. The dmac enable bit must be cleared before configuring. **/ s32 ixgbe_dmac_config_tcs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.dmac_config_tcs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_eee - Enable/disable EEE support * @hw: pointer to the HW structure * @enable_eee: boolean flag to enable EEE * * Enable/disable EEE based on enable_ee flag. * Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C * are modified. * **/ s32 ixgbe_setup_eee(struct ixgbe_hw *hw, bool enable_eee) { return ixgbe_call_func(hw, hw->mac.ops.setup_eee, (hw, enable_eee), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_source_address_pruning - Enable/Disable source address pruning * @hw: pointer to hardware structure * @enbale: enable or disable source address pruning * @pool: Rx pool - Rx pool to toggle source address pruning **/ void ixgbe_set_source_address_pruning(struct ixgbe_hw *hw, bool enable, unsigned int pool) { if (hw->mac.ops.set_source_address_pruning) hw->mac.ops.set_source_address_pruning(hw, enable, pool); } /** * ixgbe_set_ethertype_anti_spoofing - Enable/Disable Ethertype anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for Ethertype anti-spoofing * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing * **/ void ixgbe_set_ethertype_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) { if (hw->mac.ops.set_ethertype_anti_spoofing) hw->mac.ops.set_ethertype_anti_spoofing(hw, enable, vf); } /** * ixgbe_read_iosf_sb_reg - Read 32 bit PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @device_type: type of device you want to communicate with * @phy_data: Pointer to read data from PHY register * * Reads a value from a specified PHY register **/ s32 ixgbe_read_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 *phy_data) { return ixgbe_call_func(hw, hw->mac.ops.read_iosf_sb_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_iosf_sb_reg - Write 32 bit register through IOSF Sideband * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: type of device you want to communicate with * @phy_data: Data to write to the PHY register * * Writes a value to specified PHY register **/ s32 ixgbe_write_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 phy_data) { return ixgbe_call_func(hw, hw->mac.ops.write_iosf_sb_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_mdd - Disable malicious driver detection * @hw: pointer to hardware structure * **/ void ixgbe_disable_mdd(struct ixgbe_hw *hw) { if (hw->mac.ops.disable_mdd) hw->mac.ops.disable_mdd(hw); } /** * ixgbe_enable_mdd - Enable malicious driver detection * @hw: pointer to hardware structure * **/ void ixgbe_enable_mdd(struct ixgbe_hw *hw) { if (hw->mac.ops.enable_mdd) hw->mac.ops.enable_mdd(hw); } /** * ixgbe_mdd_event - Handle malicious driver detection event * @hw: pointer to hardware structure * @vf_bitmap: vf bitmap of malicious vfs * **/ void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap) { if (hw->mac.ops.mdd_event) hw->mac.ops.mdd_event(hw, vf_bitmap); } /** * ixgbe_restore_mdd_vf - Restore VF that was disabled during malicious driver * detection event * @hw: pointer to hardware structure * @vf: vf index * **/ void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf) { if (hw->mac.ops.restore_mdd_vf) hw->mac.ops.restore_mdd_vf(hw, vf); } /** * ixgbe_enter_lplu - Transition to low power states * @hw: pointer to hardware structure * * Configures Low Power Link Up on transition to low power states * (from D0 to non-D0). **/ s32 ixgbe_enter_lplu(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->phy.ops.enter_lplu, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_handle_lasi - Handle external Base T PHY interrupt * @hw: pointer to hardware structure * * Handle external Base T PHY interrupt. If high temperature * failure alarm then return error, else if link status change * then setup internal/external PHY link * * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature * failure alarm, else return PHY access status. */ s32 ixgbe_handle_lasi(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->phy.ops.handle_lasi, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_analog_reg8 - Reads 8 bit analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs write operation to analog register specified. **/ s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val) { return ixgbe_call_func(hw, hw->mac.ops.read_analog_reg8, (hw, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_analog_reg8 - Writes 8 bit analog register * @hw: pointer to hardware structure * @reg: analog register to write * @val: value to write * * Performs write operation to Atlas analog register specified. **/ s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val) { return ixgbe_call_func(hw, hw->mac.ops.write_analog_reg8, (hw, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_uta_tables - Initializes Unicast Table Arrays. * @hw: pointer to hardware structure * * Initializes the Unicast Table Arrays to zero on device load. This * is part of the Rx init addr execution path. **/ s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_uta_tables, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_byte - Reads 8 bit word over I2C at specified device address * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: I2C bus address to read from * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_byte, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_byte_unlocked - Reads 8 bit word via I2C from device address * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: I2C bus address to read from * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_byte_unlocked, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_combined - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * * Returns an error code on error. */ s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined, (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_combined_unlocked - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * * Returns an error code on error. **/ s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_combined_unlocked, (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: I2C bus address to write to * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface * at a specified device address. **/ s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_byte, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: I2C bus address to write to * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface * at a specified device address. **/ s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_byte_unlocked, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_combined - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * * Returns an error code on error. */ s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined, (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_combined_unlocked - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * * Returns an error code on error. **/ s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_combined_unlocked, (hw, addr, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to write * @eeprom_data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_eeprom, (hw, byte_offset, eeprom_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_eeprom - Reads 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_eeprom, (hw, byte_offset, eeprom_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_supported_physical_layer - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_supported_physical_layer, (hw), IXGBE_PHYSICAL_LAYER_UNKNOWN); } /** * ixgbe_enable_rx_dma - Enables Rx DMA unit, dependent on device specifics * @hw: pointer to hardware structure * @regval: bitfield to write to the Rx DMA register * * Enables the Rx DMA unit of the device. **/ s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval) { return ixgbe_call_func(hw, hw->mac.ops.enable_rx_dma, (hw, regval), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_sec_rx_path - Stops the receive data path * @hw: pointer to hardware structure * * Stops the receive data path. **/ s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.disable_sec_rx_path, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_enable_sec_rx_path - Enables the receive data path * @hw: pointer to hardware structure * * Enables the receive data path. **/ s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.enable_sec_rx_path, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_acquire_swfw_semaphore - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore through SW_FW_SYNC register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u32 mask) { return ixgbe_call_func(hw, hw->mac.ops.acquire_swfw_sync, (hw, mask), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_release_swfw_semaphore - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through SW_FW_SYNC register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u32 mask) { if (hw->mac.ops.release_swfw_sync) hw->mac.ops.release_swfw_sync(hw, mask); } void ixgbe_disable_rx(struct ixgbe_hw *hw) { if (hw->mac.ops.disable_rx) hw->mac.ops.disable_rx(hw); } void ixgbe_enable_rx(struct ixgbe_hw *hw) { if (hw->mac.ops.enable_rx) hw->mac.ops.enable_rx(hw); } /** * ixgbe_set_rate_select_speed - Set module link speed * @hw: pointer to hardware structure * @speed: link speed to set * * Set module link speed via the rate select. */ void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) { if (hw->mac.ops.set_rate_select_speed) hw->mac.ops.set_rate_select_speed(hw, speed); } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_api.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_API_H_ #define _IXGBE_API_H_ #include "ixgbe_type.h" void ixgbe_dcb_get_rtrup2tc(struct ixgbe_hw *hw, u8 *map); s32 ixgbe_init_shared_code(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw); s32 ixgbe_set_mac_type(struct ixgbe_hw *hw); s32 ixgbe_init_hw(struct ixgbe_hw *hw); s32 ixgbe_reset_hw(struct ixgbe_hw *hw); s32 ixgbe_start_hw(struct ixgbe_hw *hw); void ixgbe_enable_relaxed_ordering(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw); enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw); s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_get_bus_info(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw); s32 ixgbe_stop_adapter(struct ixgbe_hw *hw); s32 ixgbe_read_pba_num(struct ixgbe_hw *hw, u32 *pba_num); s32 ixgbe_read_pba_string(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size); s32 ixgbe_identify_phy(struct ixgbe_hw *hw); s32 ixgbe_reset_phy(struct ixgbe_hw *hw); s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw); s32 ixgbe_setup_internal_phy(struct ixgbe_hw *hw); s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_set_phy_power(struct ixgbe_hw *, bool on); void ixgbe_disable_tx_laser(struct ixgbe_hw *hw); void ixgbe_enable_tx_laser(struct ixgbe_hw *hw); void ixgbe_flap_tx_laser(struct ixgbe_hw *hw); s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index); s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw); s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index); s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq); s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw); u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw); s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear); void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq); s32 ixgbe_enable_mc(struct ixgbe_hw *hw); s32 ixgbe_disable_mc(struct ixgbe_hw *hw); s32 ixgbe_clear_vfta(struct ixgbe_hw *hw); s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed); s32 ixgbe_fc_enable(struct ixgbe_hw *hw); s32 ixgbe_setup_fc(struct ixgbe_hw *hw); s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver); s32 ixgbe_get_thermal_sensor_data(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh(struct ixgbe_hw *hw); void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr); s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw); s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw); s32 ixgbe_mng_fw_enabled(struct ixgbe_hw *hw); s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl); s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl, bool cloud_mode); s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common, u8 queue); s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input_mask, bool cloud_mode); s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id, u8 queue, bool cloud_mode); s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id); s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, union ixgbe_atr_input *mask, u16 soft_id, u8 queue, bool cloud_mode); void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *mask); u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common); bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_read_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_read_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val); s32 ixgbe_read_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val); s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val); s32 ixgbe_write_i2c_combined_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val); s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u32 mask); void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u32 mask); s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix); s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs); s32 ixgbe_dmac_config(struct ixgbe_hw *hw); s32 ixgbe_dmac_update_tcs(struct ixgbe_hw *hw); s32 ixgbe_dmac_config_tcs(struct ixgbe_hw *hw); s32 ixgbe_setup_eee(struct ixgbe_hw *hw, bool enable_eee); void ixgbe_set_source_address_pruning(struct ixgbe_hw *hw, bool enable, unsigned int vf); void ixgbe_set_ethertype_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_read_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 *phy_data); s32 ixgbe_write_iosf_sb_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 phy_data); void ixgbe_disable_mdd(struct ixgbe_hw *hw); void ixgbe_enable_mdd(struct ixgbe_hw *hw); void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap); void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf); s32 ixgbe_enter_lplu(struct ixgbe_hw *hw); s32 ixgbe_handle_lasi(struct ixgbe_hw *hw); void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed); void ixgbe_disable_rx(struct ixgbe_hw *hw); void ixgbe_enable_rx(struct ixgbe_hw *hw); #endif /* _IXGBE_API_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_common.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_common.h" #include "ixgbe_phy.h" #include "ixgbe_dcb.h" #include "ixgbe_dcb_82599.h" #include "ixgbe_api.h" STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); STATIC void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); STATIC s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); STATIC void ixgbe_standby_eeprom(struct ixgbe_hw *hw); STATIC void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, u16 count); STATIC u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); STATIC void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); STATIC void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); STATIC void ixgbe_release_eeprom(struct ixgbe_hw *hw); STATIC s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); STATIC s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset); STATIC s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); STATIC s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, u16 offset); /** * ixgbe_init_ops_generic - Inits function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; struct ixgbe_mac_info *mac = &hw->mac; u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); DEBUGFUNC("ixgbe_init_ops_generic"); /* EEPROM */ eeprom->ops.init_params = ixgbe_init_eeprom_params_generic; /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ if (eec & IXGBE_EEC_PRES) { eeprom->ops.read = ixgbe_read_eerd_generic; eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic; } else { eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic; eeprom->ops.read_buffer = ixgbe_read_eeprom_buffer_bit_bang_generic; } eeprom->ops.write = ixgbe_write_eeprom_generic; eeprom->ops.write_buffer = ixgbe_write_eeprom_buffer_bit_bang_generic; eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_generic; eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic; eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic; /* MAC */ mac->ops.init_hw = ixgbe_init_hw_generic; mac->ops.reset_hw = NULL; mac->ops.start_hw = ixgbe_start_hw_generic; mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic; mac->ops.get_media_type = NULL; mac->ops.get_supported_physical_layer = NULL; mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic; mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic; mac->ops.stop_adapter = ixgbe_stop_adapter_generic; mac->ops.get_bus_info = ixgbe_get_bus_info_generic; mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie; mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync; mac->ops.release_swfw_sync = ixgbe_release_swfw_sync; mac->ops.prot_autoc_read = prot_autoc_read_generic; mac->ops.prot_autoc_write = prot_autoc_write_generic; /* LEDs */ mac->ops.led_on = ixgbe_led_on_generic; mac->ops.led_off = ixgbe_led_off_generic; mac->ops.blink_led_start = ixgbe_blink_led_start_generic; mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic; /* RAR, Multicast, VLAN */ mac->ops.set_rar = ixgbe_set_rar_generic; mac->ops.clear_rar = ixgbe_clear_rar_generic; mac->ops.insert_mac_addr = NULL; mac->ops.set_vmdq = NULL; mac->ops.clear_vmdq = NULL; mac->ops.init_rx_addrs = ixgbe_init_rx_addrs_generic; mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic; mac->ops.update_mc_addr_list = ixgbe_update_mc_addr_list_generic; mac->ops.enable_mc = ixgbe_enable_mc_generic; mac->ops.disable_mc = ixgbe_disable_mc_generic; mac->ops.clear_vfta = NULL; mac->ops.set_vfta = NULL; mac->ops.set_vlvf = NULL; mac->ops.init_uta_tables = NULL; mac->ops.enable_rx = ixgbe_enable_rx_generic; mac->ops.disable_rx = ixgbe_disable_rx_generic; /* Flow Control */ mac->ops.fc_enable = ixgbe_fc_enable_generic; mac->ops.setup_fc = ixgbe_setup_fc_generic; /* Link */ mac->ops.get_link_capabilities = NULL; mac->ops.setup_link = NULL; mac->ops.check_link = NULL; mac->ops.dmac_config = NULL; mac->ops.dmac_update_tcs = NULL; mac->ops.dmac_config_tcs = NULL; return IXGBE_SUCCESS; } /** * ixgbe_device_supports_autoneg_fc - Check if device supports autonegotiation * of flow control * @hw: pointer to hardware structure * * This function returns true if the device supports flow control * autonegotiation, and false if it does not. * **/ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) { bool supported = false; ixgbe_link_speed speed; bool link_up; DEBUGFUNC("ixgbe_device_supports_autoneg_fc"); switch (hw->phy.media_type) { case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: hw->mac.ops.check_link(hw, &speed, &link_up, false); /* if link is down, assume supported */ if (link_up) supported = speed == IXGBE_LINK_SPEED_1GB_FULL ? true : false; else supported = true; break; case ixgbe_media_type_backplane: supported = true; break; case ixgbe_media_type_copper: /* only some copper devices support flow control autoneg */ switch (hw->device_id) { case IXGBE_DEV_ID_82599_T3_LOM: case IXGBE_DEV_ID_X540T: case IXGBE_DEV_ID_X540T1: case IXGBE_DEV_ID_X550T: case IXGBE_DEV_ID_X550EM_X_10G_T: supported = true; break; default: supported = false; } default: break; } ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Device %x does not support flow control autoneg", hw->device_id); return supported; } /** * ixgbe_setup_fc_generic - Set up flow control * @hw: pointer to hardware structure * * Called at init time to set up flow control. **/ s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; u32 reg = 0, reg_bp = 0; u16 reg_cu = 0; bool locked = false; DEBUGFUNC("ixgbe_setup_fc_generic"); /* Validate the requested mode */ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* * 10gig parts do not have a word in the EEPROM to determine the * default flow control setting, so we explicitly set it to full. */ if (hw->fc.requested_mode == ixgbe_fc_default) hw->fc.requested_mode = ixgbe_fc_full; /* * Set up the 1G and 10G flow control advertisement registers so the * HW will be able to do fc autoneg once the cable is plugged in. If * we link at 10G, the 1G advertisement is harmless and vice versa. */ switch (hw->phy.media_type) { case ixgbe_media_type_backplane: /* some MAC's need RMW protection on AUTOC */ ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, ®_bp); if (ret_val != IXGBE_SUCCESS) goto out; /* only backplane uses autoc so fall though */ case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); break; case ixgbe_media_type_copper: hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); break; default: break; } /* * The possible values of fc.requested_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.requested_mode) { case ixgbe_fc_none: /* Flow control completely disabled by software override. */ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); if (hw->phy.media_type == ixgbe_media_type_backplane) reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); else if (hw->phy.media_type == ixgbe_media_type_copper) reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ reg |= IXGBE_PCS1GANA_ASM_PAUSE; reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; if (hw->phy.media_type == ixgbe_media_type_backplane) { reg_bp |= IXGBE_AUTOC_ASM_PAUSE; reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; } else if (hw->phy.media_type == ixgbe_media_type_copper) { reg_cu |= IXGBE_TAF_ASM_PAUSE; reg_cu &= ~IXGBE_TAF_SYM_PAUSE; } break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE, as such we fall * through to the fc_full statement. Later, we will * disable the adapter's ability to send PAUSE frames. */ case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; if (hw->phy.media_type == ixgbe_media_type_backplane) reg_bp |= IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE; else if (hw->phy.media_type == ixgbe_media_type_copper) reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; break; default: ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } if (hw->mac.type < ixgbe_mac_X540) { /* * Enable auto-negotiation between the MAC & PHY; * the MAC will advertise clause 37 flow control. */ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); /* Disable AN timeout */ if (hw->fc.strict_ieee) reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); } /* * AUTOC restart handles negotiation of 1G and 10G on backplane * and copper. There is no need to set the PCS1GCTL register. * */ if (hw->phy.media_type == ixgbe_media_type_backplane) { reg_bp |= IXGBE_AUTOC_AN_RESTART; ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked); if (ret_val) goto out; } else if ((hw->phy.media_type == ixgbe_media_type_copper) && (ixgbe_device_supports_autoneg_fc(hw))) { hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); } DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); out: return ret_val; } /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) { s32 ret_val; u32 ctrl_ext; DEBUGFUNC("ixgbe_start_hw_generic"); /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* PHY ops initialization must be done in reset_hw() */ /* Clear the VLAN filter table */ hw->mac.ops.clear_vfta(hw); /* Clear statistics registers */ hw->mac.ops.clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); /* Setup flow control */ ret_val = ixgbe_setup_fc(hw); if (ret_val != IXGBE_SUCCESS) goto out; /* Clear adapter stopped flag */ hw->adapter_stopped = false; out: return ret_val; } /** * ixgbe_start_hw_gen2 - Init sequence for common device family * @hw: pointer to hw structure * * Performs the init sequence common to the second generation * of 10 GbE devices. * Devices in the second generation: * 82599 * X540 **/ s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) { u32 i; u32 regval; /* Clear the rate limiters */ for (i = 0; i < hw->mac.max_tx_queues; i++) { IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); } IXGBE_WRITE_FLUSH(hw); /* Disable relaxed ordering */ for (i = 0; i < hw->mac.max_tx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); } for (i = 0; i < hw->mac.max_rx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } return IXGBE_SUCCESS; } /** * ixgbe_init_hw_generic - Generic hardware initialization * @hw: pointer to hardware structure * * Initialize the hardware by resetting the hardware, filling the bus info * structure and media type, clears all on chip counters, initializes receive * address registers, multicast table, VLAN filter table, calls routine to set * up link and flow control settings, and leaves transmit and receive units * disabled and uninitialized **/ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { s32 status; DEBUGFUNC("ixgbe_init_hw_generic"); /* Reset the hardware */ status = hw->mac.ops.reset_hw(hw); if (status == IXGBE_SUCCESS) { /* Start the HW */ status = hw->mac.ops.start_hw(hw); } return status; } /** * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) { u16 i = 0; DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); IXGBE_READ_REG(hw, IXGBE_CRCERRS); IXGBE_READ_REG(hw, IXGBE_ILLERRC); IXGBE_READ_REG(hw, IXGBE_ERRBC); IXGBE_READ_REG(hw, IXGBE_MSPDC); for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_MPC(i)); IXGBE_READ_REG(hw, IXGBE_MLFC); IXGBE_READ_REG(hw, IXGBE_MRFC); IXGBE_READ_REG(hw, IXGBE_RLEC); IXGBE_READ_REG(hw, IXGBE_LXONTXC); IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); } else { IXGBE_READ_REG(hw, IXGBE_LXONRXC); IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); } for (i = 0; i < 8; i++) { IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); } else { IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); } } if (hw->mac.type >= ixgbe_mac_82599EB) for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); IXGBE_READ_REG(hw, IXGBE_PRC64); IXGBE_READ_REG(hw, IXGBE_PRC127); IXGBE_READ_REG(hw, IXGBE_PRC255); IXGBE_READ_REG(hw, IXGBE_PRC511); IXGBE_READ_REG(hw, IXGBE_PRC1023); IXGBE_READ_REG(hw, IXGBE_PRC1522); IXGBE_READ_REG(hw, IXGBE_GPRC); IXGBE_READ_REG(hw, IXGBE_BPRC); IXGBE_READ_REG(hw, IXGBE_MPRC); IXGBE_READ_REG(hw, IXGBE_GPTC); IXGBE_READ_REG(hw, IXGBE_GORCL); IXGBE_READ_REG(hw, IXGBE_GORCH); IXGBE_READ_REG(hw, IXGBE_GOTCL); IXGBE_READ_REG(hw, IXGBE_GOTCH); if (hw->mac.type == ixgbe_mac_82598EB) for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_RNBC(i)); IXGBE_READ_REG(hw, IXGBE_RUC); IXGBE_READ_REG(hw, IXGBE_RFC); IXGBE_READ_REG(hw, IXGBE_ROC); IXGBE_READ_REG(hw, IXGBE_RJC); IXGBE_READ_REG(hw, IXGBE_MNGPRC); IXGBE_READ_REG(hw, IXGBE_MNGPDC); IXGBE_READ_REG(hw, IXGBE_MNGPTC); IXGBE_READ_REG(hw, IXGBE_TORL); IXGBE_READ_REG(hw, IXGBE_TORH); IXGBE_READ_REG(hw, IXGBE_TPR); IXGBE_READ_REG(hw, IXGBE_TPT); IXGBE_READ_REG(hw, IXGBE_PTC64); IXGBE_READ_REG(hw, IXGBE_PTC127); IXGBE_READ_REG(hw, IXGBE_PTC255); IXGBE_READ_REG(hw, IXGBE_PTC511); IXGBE_READ_REG(hw, IXGBE_PTC1023); IXGBE_READ_REG(hw, IXGBE_PTC1522); IXGBE_READ_REG(hw, IXGBE_MPTC); IXGBE_READ_REG(hw, IXGBE_BPTC); for (i = 0; i < 16; i++) { IXGBE_READ_REG(hw, IXGBE_QPRC(i)); IXGBE_READ_REG(hw, IXGBE_QPTC(i)); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); } else { IXGBE_READ_REG(hw, IXGBE_QBRC(i)); IXGBE_READ_REG(hw, IXGBE_QBTC(i)); } } if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, IXGBE_MDIO_PCS_DEV_TYPE, &i); } return IXGBE_SUCCESS; } /** * ixgbe_read_pba_string_generic - Reads part number string from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number string from the EEPROM * @pba_num_size: part number string buffer length * * Reads the part number string from the EEPROM. **/ s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size) { s32 ret_val; u16 data; u16 pba_ptr; u16 offset; u16 length; DEBUGFUNC("ixgbe_read_pba_string_generic"); if (pba_num == NULL) { DEBUGOUT("PBA string buffer was null\n"); return IXGBE_ERR_INVALID_ARGUMENT; } ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } /* * if data is not ptr guard the PBA must be in legacy format which * means pba_ptr is actually our second data word for the PBA number * and we can decode it into an ascii string */ if (data != IXGBE_PBANUM_PTR_GUARD) { DEBUGOUT("NVM PBA number is not stored as string\n"); /* we will need 11 characters to store the PBA */ if (pba_num_size < 11) { DEBUGOUT("PBA string buffer too small\n"); return IXGBE_ERR_NO_SPACE; } /* extract hex string from data and pba_ptr */ pba_num[0] = (data >> 12) & 0xF; pba_num[1] = (data >> 8) & 0xF; pba_num[2] = (data >> 4) & 0xF; pba_num[3] = data & 0xF; pba_num[4] = (pba_ptr >> 12) & 0xF; pba_num[5] = (pba_ptr >> 8) & 0xF; pba_num[6] = '-'; pba_num[7] = 0; pba_num[8] = (pba_ptr >> 4) & 0xF; pba_num[9] = pba_ptr & 0xF; /* put a null character on the end of our string */ pba_num[10] = '\0'; /* switch all the data but the '-' to hex char */ for (offset = 0; offset < 10; offset++) { if (pba_num[offset] < 0xA) pba_num[offset] += '0'; else if (pba_num[offset] < 0x10) pba_num[offset] += 'A' - 0xA; } return IXGBE_SUCCESS; } ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); return IXGBE_ERR_PBA_SECTION; } /* check if pba_num buffer is big enough */ if (pba_num_size < (((u32)length * 2) - 1)) { DEBUGOUT("PBA string buffer too small\n"); return IXGBE_ERR_NO_SPACE; } /* trim pba length from start of string */ pba_ptr++; length--; for (offset = 0; offset < length; offset++) { ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } pba_num[offset * 2] = (u8)(data >> 8); pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); } pba_num[offset * 2] = '\0'; return IXGBE_SUCCESS; } /** * ixgbe_read_pba_num_generic - Reads part number from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number from the EEPROM * * Reads the part number from the EEPROM. **/ s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num) { s32 ret_val; u16 data; DEBUGFUNC("ixgbe_read_pba_num_generic"); ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } else if (data == IXGBE_PBANUM_PTR_GUARD) { DEBUGOUT("NVM Not supported\n"); return IXGBE_NOT_IMPLEMENTED; } *pba_num = (u32)(data << 16); ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } *pba_num |= data; return IXGBE_SUCCESS; } /** * ixgbe_read_pba_raw * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @max_pba_block_size: PBA block size limit * @pba: pointer to output PBA structure * * Reads PBA from EEPROM image when eeprom_buf is not NULL. * Reads PBA from physical EEPROM device when eeprom_buf is NULL. * **/ s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 max_pba_block_size, struct ixgbe_pba *pba) { s32 ret_val; u16 pba_block_size; if (pba == NULL) return IXGBE_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, &pba->word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { pba->word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; pba->word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; } else { return IXGBE_ERR_PARAM; } } if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { if (pba->pba_block == NULL) return IXGBE_ERR_PARAM; ret_val = ixgbe_get_pba_block_size(hw, eeprom_buf, eeprom_buf_size, &pba_block_size); if (ret_val) return ret_val; if (pba_block_size > max_pba_block_size) return IXGBE_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.read_buffer(hw, pba->word[1], pba_block_size, pba->pba_block); if (ret_val) return ret_val; } else { if (eeprom_buf_size > (u32)(pba->word[1] + pba_block_size)) { memcpy(pba->pba_block, &eeprom_buf[pba->word[1]], pba_block_size * sizeof(u16)); } else { return IXGBE_ERR_PARAM; } } } return IXGBE_SUCCESS; } /** * ixgbe_write_pba_raw * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @pba: pointer to PBA structure * * Writes PBA to EEPROM image when eeprom_buf is not NULL. * Writes PBA to physical EEPROM device when eeprom_buf is NULL. * **/ s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, struct ixgbe_pba *pba) { s32 ret_val; if (pba == NULL) return IXGBE_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.write_buffer(hw, IXGBE_PBANUM0_PTR, 2, &pba->word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { eeprom_buf[IXGBE_PBANUM0_PTR] = pba->word[0]; eeprom_buf[IXGBE_PBANUM1_PTR] = pba->word[1]; } else { return IXGBE_ERR_PARAM; } } if (pba->word[0] == IXGBE_PBANUM_PTR_GUARD) { if (pba->pba_block == NULL) return IXGBE_ERR_PARAM; if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.write_buffer(hw, pba->word[1], pba->pba_block[0], pba->pba_block); if (ret_val) return ret_val; } else { if (eeprom_buf_size > (u32)(pba->word[1] + pba->pba_block[0])) { memcpy(&eeprom_buf[pba->word[1]], pba->pba_block, pba->pba_block[0] * sizeof(u16)); } else { return IXGBE_ERR_PARAM; } } } return IXGBE_SUCCESS; } /** * ixgbe_get_pba_block_size * @hw: pointer to the HW structure * @eeprom_buf: optional pointer to EEPROM image * @eeprom_buf_size: size of EEPROM image in words * @pba_data_size: pointer to output variable * * Returns the size of the PBA block in words. Function operates on EEPROM * image if the eeprom_buf pointer is not NULL otherwise it accesses physical * EEPROM device. * **/ s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 *pba_block_size) { s32 ret_val; u16 pba_word[2]; u16 length; DEBUGFUNC("ixgbe_get_pba_block_size"); if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.read_buffer(hw, IXGBE_PBANUM0_PTR, 2, &pba_word[0]); if (ret_val) return ret_val; } else { if (eeprom_buf_size > IXGBE_PBANUM1_PTR) { pba_word[0] = eeprom_buf[IXGBE_PBANUM0_PTR]; pba_word[1] = eeprom_buf[IXGBE_PBANUM1_PTR]; } else { return IXGBE_ERR_PARAM; } } if (pba_word[0] == IXGBE_PBANUM_PTR_GUARD) { if (eeprom_buf == NULL) { ret_val = hw->eeprom.ops.read(hw, pba_word[1] + 0, &length); if (ret_val) return ret_val; } else { if (eeprom_buf_size > pba_word[1]) length = eeprom_buf[pba_word[1] + 0]; else return IXGBE_ERR_PARAM; } if (length == 0xFFFF || length == 0) return IXGBE_ERR_PBA_SECTION; } else { /* PBA number in legacy format, there is no PBA Block. */ length = 0; } if (pba_block_size != NULL) *pba_block_size = length; return IXGBE_SUCCESS; } /** * ixgbe_get_mac_addr_generic - Generic get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * * Reads the adapter's MAC address from first Receive Address Register (RAR0) * A reset of the adapter must be performed prior to calling this function * in order for the MAC address to have been loaded from the EEPROM into RAR0 **/ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) { u32 rar_high; u32 rar_low; u16 i; DEBUGFUNC("ixgbe_get_mac_addr_generic"); rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); for (i = 0; i < 4; i++) mac_addr[i] = (u8)(rar_low >> (i*8)); for (i = 0; i < 2; i++) mac_addr[i+4] = (u8)(rar_high >> (i*8)); return IXGBE_SUCCESS; } /** * ixgbe_set_pci_config_data_generic - Generic store PCI bus info * @hw: pointer to hardware structure * @link_status: the link status returned by the PCI config space * * Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure **/ void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status) { struct ixgbe_mac_info *mac = &hw->mac; if (hw->bus.type == ixgbe_bus_type_unknown) hw->bus.type = ixgbe_bus_type_pci_express; switch (link_status & IXGBE_PCI_LINK_WIDTH) { case IXGBE_PCI_LINK_WIDTH_1: hw->bus.width = ixgbe_bus_width_pcie_x1; break; case IXGBE_PCI_LINK_WIDTH_2: hw->bus.width = ixgbe_bus_width_pcie_x2; break; case IXGBE_PCI_LINK_WIDTH_4: hw->bus.width = ixgbe_bus_width_pcie_x4; break; case IXGBE_PCI_LINK_WIDTH_8: hw->bus.width = ixgbe_bus_width_pcie_x8; break; default: hw->bus.width = ixgbe_bus_width_unknown; break; } switch (link_status & IXGBE_PCI_LINK_SPEED) { case IXGBE_PCI_LINK_SPEED_2500: hw->bus.speed = ixgbe_bus_speed_2500; break; case IXGBE_PCI_LINK_SPEED_5000: hw->bus.speed = ixgbe_bus_speed_5000; break; case IXGBE_PCI_LINK_SPEED_8000: hw->bus.speed = ixgbe_bus_speed_8000; break; default: hw->bus.speed = ixgbe_bus_speed_unknown; break; } mac->ops.set_lan_id(hw); } /** * ixgbe_get_bus_info_generic - Generic set PCI bus info * @hw: pointer to hardware structure * * Gets the PCI bus info (speed, width, type) then calls helper function to * store this data within the ixgbe_hw structure. **/ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) { u16 link_status; DEBUGFUNC("ixgbe_get_bus_info_generic"); /* Get the negotiated link width and speed from PCI config space */ link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); ixgbe_set_pci_config_data_generic(hw, link_status); return IXGBE_SUCCESS; } /** * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices * @hw: pointer to the HW structure * * Determines the LAN function id by reading memory-mapped registers * and swaps the port value if requested. **/ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) { struct ixgbe_bus_info *bus = &hw->bus; u32 reg; DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); reg = IXGBE_READ_REG(hw, IXGBE_STATUS); bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; bus->lan_id = bus->func; /* check for a port swap */ reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); if (reg & IXGBE_FACTPS_LFS) bus->func ^= 0x1; } /** * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) { u32 reg_val; u16 i; DEBUGFUNC("ixgbe_stop_adapter_generic"); /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware */ hw->adapter_stopped = true; /* Disable the receive unit */ ixgbe_disable_rx(hw); /* Clear interrupt mask to stop interrupts from being generated */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); /* Clear any pending interrupts, flush previous writes */ IXGBE_READ_REG(hw, IXGBE_EICR); /* Disable the transmit unit. Each queue must be disabled. */ for (i = 0; i < hw->mac.max_tx_queues; i++) IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); /* Disable the receive unit by stopping each queue */ for (i = 0; i < hw->mac.max_rx_queues; i++) { reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); reg_val &= ~IXGBE_RXDCTL_ENABLE; reg_val |= IXGBE_RXDCTL_SWFLSH; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); } /* flush all queues disables */ IXGBE_WRITE_FLUSH(hw); msec_delay(2); /* * Prevent the PCI-E bus from hanging by disabling PCI-E master * access and verify no pending requests */ return ixgbe_disable_pcie_master(hw); } /** * ixgbe_led_on_generic - Turns on the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn on **/ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); DEBUGFUNC("ixgbe_led_on_generic"); /* To turn on the LED, set mode to ON. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } /** * ixgbe_led_off_generic - Turns off the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn off **/ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); DEBUGFUNC("ixgbe_led_off_generic"); /* To turn off the LED, set mode to OFF. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } /** * ixgbe_init_eeprom_params_generic - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; DEBUGFUNC("ixgbe_init_eeprom_params_generic"); if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; /* Set default semaphore delay to 10ms which is a well * tested value */ eeprom->semaphore_delay = 10; /* Clear EEPROM page size, it will be initialized as needed */ eeprom->word_page_size = 0; /* * Check for EEPROM present first. * If not present leave as none */ eec = IXGBE_READ_REG(hw, IXGBE_EEC); if (eec & IXGBE_EEC_PRES) { eeprom->type = ixgbe_eeprom_spi; /* * SPI EEPROM is assumed here. This code would need to * change if a future EEPROM is not SPI. */ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) eeprom->address_bits = 16; else eeprom->address_bits = 8; DEBUGOUT3("Eeprom params: type = %d, size = %d, address bits: " "%d\n", eeprom->type, eeprom->word_size, eeprom->address_bits); } return IXGBE_SUCCESS; } /** * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to write * @words: number of word(s) * @data: 16 bit word(s) to write to EEPROM * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = IXGBE_SUCCESS; u16 i, count; DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic"); hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } /* * The EEPROM page size cannot be queried from the chip. We do lazy * initialization. It is worth to do that when we write large buffer. */ if ((hw->eeprom.word_page_size == 0) && (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) ixgbe_detect_eeprom_page_size_generic(hw, offset); /* * We cannot hold synchronization semaphores for too long * to avoid other entity starvation. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, count, &data[i]); if (status != IXGBE_SUCCESS) break; } out: return status; } /** * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @words: number of word(s) * @data: 16 bit word(s) to be written to the EEPROM * * If ixgbe_eeprom_update_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ STATIC s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status; u16 word; u16 page_size; u16 i; u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang"); /* Prepare the EEPROM for writing */ status = ixgbe_acquire_eeprom(hw); if (status == IXGBE_SUCCESS) { if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { ixgbe_release_eeprom(hw); status = IXGBE_ERR_EEPROM; } } if (status == IXGBE_SUCCESS) { for (i = 0; i < words; i++) { ixgbe_standby_eeprom(hw); /* Send the WRITE ENABLE command (8 bit opcode ) */ ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, IXGBE_EEPROM_OPCODE_BITS); ixgbe_standby_eeprom(hw); /* * Some SPI eeproms use the 8th address bit embedded * in the opcode */ if ((hw->eeprom.address_bits == 8) && ((offset + i) >= 128)) write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, write_opcode, IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), hw->eeprom.address_bits); page_size = hw->eeprom.word_page_size; /* Send the data in burst via SPI*/ do { word = data[i]; word = (word >> 8) | (word << 8); ixgbe_shift_out_eeprom_bits(hw, word, 16); if (page_size == 0) break; /* do not wrap around page */ if (((offset + i) & (page_size - 1)) == (page_size - 1)) break; } while (++i < words); ixgbe_standby_eeprom(hw); msec_delay(10); } /* Done with writing - release the EEPROM */ ixgbe_release_eeprom(hw); } return status; } /** * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word to be written to the EEPROM * * If ixgbe_eeprom_update_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status; DEBUGFUNC("ixgbe_write_eeprom_generic"); hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); out: return status; } /** * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit words(s) from EEPROM * @words: number of word(s) * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = IXGBE_SUCCESS; u16 i, count; DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic"); hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } /* * We cannot hold synchronization semaphores for too long * to avoid other entity starvation. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, count, &data[i]); if (status != IXGBE_SUCCESS) break; } out: return status; } /** * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @words: number of word(s) * @data: read 16 bit word(s) from EEPROM * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ STATIC s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status; u16 word_in; u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; u16 i; DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang"); /* Prepare the EEPROM for reading */ status = ixgbe_acquire_eeprom(hw); if (status == IXGBE_SUCCESS) { if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) { ixgbe_release_eeprom(hw); status = IXGBE_ERR_EEPROM; } } if (status == IXGBE_SUCCESS) { for (i = 0; i < words; i++) { ixgbe_standby_eeprom(hw); /* * Some SPI eeproms use the 8th address bit embedded * in the opcode */ if ((hw->eeprom.address_bits == 8) && ((offset + i) >= 128)) read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; /* Send the READ command (opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, read_opcode, IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), hw->eeprom.address_bits); /* Read the data. */ word_in = ixgbe_shift_in_eeprom_bits(hw, 16); data[i] = (word_in >> 8) | (word_in << 8); } /* End this read operation */ ixgbe_release_eeprom(hw); } return status; } /** * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit value from EEPROM * * Reads 16 bit value from EEPROM through bit-bang method **/ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status; DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); out: return status; } /** * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @words: number of word(s) * @data: 16 bit word(s) from the EEPROM * * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { u32 eerd; s32 status = IXGBE_SUCCESS; u32 i; DEBUGFUNC("ixgbe_read_eerd_buffer_generic"); hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); goto out; } if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); goto out; } for (i = 0; i < words; i++) { eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | IXGBE_EEPROM_RW_REG_START; IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); if (status == IXGBE_SUCCESS) { data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> IXGBE_EEPROM_RW_REG_DATA); } else { DEBUGOUT("Eeprom read timed out\n"); goto out; } } out: return status; } /** * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be used as a scratch pad * * Discover EEPROM page size by writing marching data at given offset. * This function is called only when we are writing a new large buffer * at given offset so the data would be overwritten anyway. **/ STATIC s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, u16 offset) { u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; s32 status = IXGBE_SUCCESS; u16 i; DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic"); for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) data[i] = i; hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, IXGBE_EEPROM_PAGE_SIZE_MAX, data); hw->eeprom.word_page_size = 0; if (status != IXGBE_SUCCESS) goto out; status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); if (status != IXGBE_SUCCESS) goto out; /* * When writing in burst more than the actual page size * EEPROM address wraps around current page. */ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; DEBUGOUT1("Detected EEPROM page size = %d words.", hw->eeprom.word_page_size); out: return status; } /** * ixgbe_read_eerd_generic - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); } /** * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @words: number of word(s) * @data: word(s) write to the EEPROM * * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { u32 eewr; s32 status = IXGBE_SUCCESS; u16 i; DEBUGFUNC("ixgbe_write_eewr_generic"); hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM words"); goto out; } if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Invalid EEPROM offset"); goto out; } for (i = 0; i < words; i++) { eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | (data[i] << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START; status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); if (status != IXGBE_SUCCESS) { DEBUGOUT("Eeprom write EEWR timed out\n"); goto out; } IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); if (status != IXGBE_SUCCESS) { DEBUGOUT("Eeprom write EEWR timed out\n"); goto out; } } out: return status; } /** * ixgbe_write_eewr_generic - Write EEPROM word using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) { return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); } /** * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure * @ee_reg: EEPROM flag for polling * * Polls the status bit (bit 1) of the EERD or EEWR to determine when the * read or write is done respectively. **/ s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { if (ee_reg == IXGBE_NVM_POLL_READ) reg = IXGBE_READ_REG(hw, IXGBE_EERD); else reg = IXGBE_READ_REG(hw, IXGBE_EEWR); if (reg & IXGBE_EEPROM_RW_REG_DONE) { status = IXGBE_SUCCESS; break; } usec_delay(5); } if (i == IXGBE_EERD_EEWR_ATTEMPTS) ERROR_REPORT1(IXGBE_ERROR_POLLING, "EEPROM read/write done polling timed out"); return status; } /** * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang * @hw: pointer to hardware structure * * Prepares EEPROM for access using bit-bang method. This function should * be called before issuing a command to the EEPROM. **/ STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u32 eec; u32 i; DEBUGFUNC("ixgbe_acquire_eeprom"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) status = IXGBE_ERR_SWFW_SYNC; if (status == IXGBE_SUCCESS) { eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Request EEPROM Access */ eec |= IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { eec = IXGBE_READ_REG(hw, IXGBE_EEC); if (eec & IXGBE_EEC_GNT) break; usec_delay(5); } /* Release if grant not acquired */ if (!(eec & IXGBE_EEC_GNT)) { eec &= ~IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); DEBUGOUT("Could not acquire EEPROM grant\n"); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); status = IXGBE_ERR_EEPROM; } /* Setup EEPROM for Read/Write */ if (status == IXGBE_SUCCESS) { /* Clear CS and SK */ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } } return status; } /** * ixgbe_get_eeprom_semaphore - Get hardware semaphore * @hw: pointer to hardware structure * * Sets the hardware semaphores so EEPROM access can occur for bit-bang method **/ STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM; u32 timeout = 2000; u32 i; u32 swsm; DEBUGFUNC("ixgbe_get_eeprom_semaphore"); /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) { status = IXGBE_SUCCESS; break; } usec_delay(50); } if (i == timeout) { DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore " "not granted.\n"); /* * this release is particularly important because our attempts * above to get the semaphore may have succeeded, and if there * was a timeout, we should unconditionally clear the semaphore * bits to free the driver to make progress */ ixgbe_release_eeprom_semaphore(hw); usec_delay(50); /* * one last try * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) status = IXGBE_SUCCESS; } /* Now get the semaphore between SW/FW through the SWESMBI bit */ if (status == IXGBE_SUCCESS) { for (i = 0; i < timeout; i++) { swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Set the SW EEPROM semaphore bit to request access */ swsm |= IXGBE_SWSM_SWESMBI; IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); /* * If we set the bit successfully then we got the * semaphore. */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (swsm & IXGBE_SWSM_SWESMBI) break; usec_delay(50); } /* * Release semaphores and return error if SW EEPROM semaphore * was not granted because we don't have access to the EEPROM */ if (i >= timeout) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "SWESMBI Software EEPROM semaphore not granted.\n"); ixgbe_release_eeprom_semaphore(hw); status = IXGBE_ERR_EEPROM; } } else { ERROR_REPORT1(IXGBE_ERROR_POLLING, "Software semaphore SMBI between device drivers " "not granted.\n"); } return status; } /** * ixgbe_release_eeprom_semaphore - Release hardware semaphore * @hw: pointer to hardware structure * * This function clears hardware semaphore bits. **/ STATIC void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) { u32 swsm; DEBUGFUNC("ixgbe_release_eeprom_semaphore"); swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_ready_eeprom - Polls for EEPROM ready * @hw: pointer to hardware structure **/ STATIC s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 i; u8 spi_stat_reg; DEBUGFUNC("ixgbe_ready_eeprom"); /* * Read "Status Register" repeatedly until the LSB is cleared. The * EEPROM will signal that the command has been completed by clearing * bit 0 of the internal status register. If it's not cleared within * 5 milliseconds, then error out. */ for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, IXGBE_EEPROM_OPCODE_BITS); spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) break; usec_delay(5); ixgbe_standby_eeprom(hw); }; /* * On some parts, SPI write time could vary from 0-20mSec on 3.3V * devices (and only 0-5mSec on 5V devices) */ if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { DEBUGOUT("SPI EEPROM Status error\n"); status = IXGBE_ERR_EEPROM; } return status; } /** * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state * @hw: pointer to hardware structure **/ STATIC void ixgbe_standby_eeprom(struct ixgbe_hw *hw) { u32 eec; DEBUGFUNC("ixgbe_standby_eeprom"); eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Toggle CS to flush commands */ eec |= IXGBE_EEC_CS; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); eec &= ~IXGBE_EEC_CS; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } /** * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. * @hw: pointer to hardware structure * @data: data to send to the EEPROM * @count: number of bits to shift out **/ STATIC void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, u16 count) { u32 eec; u32 mask; u32 i; DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* * Mask is used to shift "count" bits of "data" out to the EEPROM * one bit at a time. Determine the starting bit based on count */ mask = 0x01 << (count - 1); for (i = 0; i < count; i++) { /* * A "1" is shifted out to the EEPROM by setting bit "DI" to a * "1", and then raising and then lowering the clock (the SK * bit controls the clock input to the EEPROM). A "0" is * shifted out to the EEPROM by setting "DI" to "0" and then * raising and then lowering the clock. */ if (data & mask) eec |= IXGBE_EEC_DI; else eec &= ~IXGBE_EEC_DI; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); ixgbe_raise_eeprom_clk(hw, &eec); ixgbe_lower_eeprom_clk(hw, &eec); /* * Shift mask to signify next bit of data to shift in to the * EEPROM */ mask = mask >> 1; }; /* We leave the "DI" bit set to "0" when we leave this routine. */ eec &= ~IXGBE_EEC_DI; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM * @hw: pointer to hardware structure **/ STATIC u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) { u32 eec; u32 i; u16 data = 0; DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); /* * In order to read a register from the EEPROM, we need to shift * 'count' bits in from the EEPROM. Bits are "shifted in" by raising * the clock input to the EEPROM (setting the SK bit), and then reading * the value of the "DO" bit. During this "shifting in" process the * "DI" bit should always be clear. */ eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); for (i = 0; i < count; i++) { data = data << 1; ixgbe_raise_eeprom_clk(hw, &eec); eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec &= ~(IXGBE_EEC_DI); if (eec & IXGBE_EEC_DO) data |= 1; ixgbe_lower_eeprom_clk(hw, &eec); } return data; } /** * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. * @hw: pointer to hardware structure * @eec: EEC register's current value **/ STATIC void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { DEBUGFUNC("ixgbe_raise_eeprom_clk"); /* * Raise the clock input to the EEPROM * (setting the SK bit), then delay */ *eec = *eec | IXGBE_EEC_SK; IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } /** * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. * @hw: pointer to hardware structure * @eecd: EECD's current value **/ STATIC void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { DEBUGFUNC("ixgbe_lower_eeprom_clk"); /* * Lower the clock input to the EEPROM (clearing the SK bit), then * delay */ *eec = *eec & ~IXGBE_EEC_SK; IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); } /** * ixgbe_release_eeprom - Release EEPROM, release semaphores * @hw: pointer to hardware structure **/ STATIC void ixgbe_release_eeprom(struct ixgbe_hw *hw) { u32 eec; DEBUGFUNC("ixgbe_release_eeprom"); eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec |= IXGBE_EEC_CS; /* Pull CS high */ eec &= ~IXGBE_EEC_SK; /* Lower SCK */ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); usec_delay(1); /* Stop requesting EEPROM access */ eec &= ~IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); /* Delay before attempt to obtain semaphore again to allow FW access */ msec_delay(hw->eeprom.semaphore_delay); } /** * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * @hw: pointer to hardware structure * * Returns a negative error code on error, or the 16-bit checksum **/ s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) { u16 i; u16 j; u16 checksum = 0; u16 length = 0; u16 pointer = 0; u16 word = 0; DEBUGFUNC("ixgbe_calc_eeprom_checksum_generic"); /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { if (hw->eeprom.ops.read(hw, i, &word)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } checksum += word; } /* Include all data from pointers except for the fw pointer */ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { if (hw->eeprom.ops.read(hw, i, &pointer)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } /* If the pointer seems invalid */ if (pointer == 0xFFFF || pointer == 0) continue; if (hw->eeprom.ops.read(hw, pointer, &length)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } if (length == 0xFFFF || length == 0) continue; for (j = pointer + 1; j <= pointer + length; j++) { if (hw->eeprom.ops.read(hw, j, &word)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } checksum += word; } } checksum = (u16)IXGBE_EEPROM_SUM - checksum; return (s32)checksum; } /** * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val) { s32 status; u16 checksum; u16 read_checksum = 0; DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } status = hw->eeprom.ops.calc_checksum(hw); if (status < 0) return status; checksum = (u16)(status & 0xffff); status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } /* Verify read checksum from EEPROM is the same as * calculated checksum */ if (read_checksum != checksum) status = IXGBE_ERR_EEPROM_CHECKSUM; /* If the user cares, return the calculated checksum */ if (checksum_val) *checksum_val = checksum; return status; } /** * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum * @hw: pointer to hardware structure **/ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) { s32 status; u16 checksum; DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } status = hw->eeprom.ops.calc_checksum(hw); if (status < 0) return status; checksum = (u16)(status & 0xffff); status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); return status; } /** * ixgbe_validate_mac_addr - Validate MAC address * @mac_addr: pointer to MAC address. * * Tests a MAC address to ensure it is a valid Individual Address **/ s32 ixgbe_validate_mac_addr(u8 *mac_addr) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_validate_mac_addr"); /* Make sure it is not a multicast address */ if (IXGBE_IS_MULTICAST(mac_addr)) { DEBUGOUT("MAC address is multicast\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; /* Not a broadcast address */ } else if (IXGBE_IS_BROADCAST(mac_addr)) { DEBUGOUT("MAC address is broadcast\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; /* Reject the zero address */ } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { DEBUGOUT("MAC address is all zeros\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; } return status; } /** * ixgbe_set_rar_generic - Set Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: VMDq "set" or "pool" index * @enable_addr: set flag that address is active * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_set_rar_generic"); /* Make sure we are using a valid rar index range */ if (index >= rar_entries) { ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, "RAR index %d is out of range.\n", index); return IXGBE_ERR_INVALID_ARGUMENT; } /* setup VMDq pool selection before this RAR gets enabled */ hw->mac.ops.set_vmdq(hw, index, vmdq); /* * HW expects these in little endian so we reverse the byte * order from network order (big endian) to little endian */ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part * of the address and the address valid bit. */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return IXGBE_SUCCESS; } /** * ixgbe_clear_rar_generic - Remove Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * * Clears an ethernet address from a receive address register. **/ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_clear_rar_generic"); /* Make sure we are using a valid rar index range */ if (index >= rar_entries) { ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, "RAR index %d is out of range.\n", index); return IXGBE_ERR_INVALID_ARGUMENT; } /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part * of the address and the address valid bit. */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); /* clear VMDq pool/queue selection for this RAR */ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); return IXGBE_SUCCESS; } /** * ixgbe_init_rx_addrs_generic - Initializes receive address filters. * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) { u32 i; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_init_rx_addrs_generic"); /* * If the current mac address is valid, assume it is a software override * to the permanent address. * Otherwise, use the permanent address from the eeprom. */ if (ixgbe_validate_mac_addr(hw->mac.addr) == IXGBE_ERR_INVALID_MAC_ADDR) { /* Get the MAC address from the RAR0 for later reference */ hw->mac.ops.get_mac_addr(hw, hw->mac.addr); DEBUGOUT3(" Keeping Current RAR0 Addr =%.2X %.2X %.2X ", hw->mac.addr[0], hw->mac.addr[1], hw->mac.addr[2]); DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], hw->mac.addr[4], hw->mac.addr[5]); } else { /* Setup the receive address. */ DEBUGOUT("Overriding MAC Address in RAR[0]\n"); DEBUGOUT3(" New MAC Addr =%.2X %.2X %.2X ", hw->mac.addr[0], hw->mac.addr[1], hw->mac.addr[2]); DEBUGOUT3("%.2X %.2X %.2X\n", hw->mac.addr[3], hw->mac.addr[4], hw->mac.addr[5]); hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); /* clear VMDq pool/queue selection for RAR 0 */ hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); } hw->addr_ctrl.overflow_promisc = 0; hw->addr_ctrl.rar_used_count = 1; /* Zero out the other receive addresses. */ DEBUGOUT1("Clearing RAR[1-%d]\n", rar_entries - 1); for (i = 1; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); } /* Clear the MTA */ hw->addr_ctrl.mta_in_use = 0; IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); DEBUGOUT(" Clearing MTA\n"); for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); ixgbe_init_uta_tables(hw); return IXGBE_SUCCESS; } /** * ixgbe_add_uc_addr - Adds a secondary unicast address. * @hw: pointer to hardware structure * @addr: new address * * Adds it to unused receive address register or goes into promiscuous mode. **/ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { u32 rar_entries = hw->mac.num_rar_entries; u32 rar; DEBUGFUNC("ixgbe_add_uc_addr"); DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); /* * Place this address in the RAR if there is room, * else put the controller into promiscuous mode */ if (hw->addr_ctrl.rar_used_count < rar_entries) { rar = hw->addr_ctrl.rar_used_count; hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar); hw->addr_ctrl.rar_used_count++; } else { hw->addr_ctrl.overflow_promisc++; } DEBUGOUT("ixgbe_add_uc_addr Complete\n"); } /** * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses * @hw: pointer to hardware structure * @addr_list: the list of new addresses * @addr_count: number of addresses * @next: iterator function to walk the address list * * The given list replaces any existing list. Clears the secondary addrs from * receive address registers. Uses unused receive address registers for the * first secondary addresses, and falls back to promiscuous mode as needed. * * Drivers using secondary unicast addresses must set user_set_promisc when * manually putting the device into promiscuous mode. **/ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr next) { u8 *addr; u32 i; u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; u32 uc_addr_in_use; u32 fctrl; u32 vmdq; DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); /* * Clear accounting of old secondary address list, * don't count RAR[0] */ uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; hw->addr_ctrl.rar_used_count -= uc_addr_in_use; hw->addr_ctrl.overflow_promisc = 0; /* Zero out the other receive addresses */ DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use+1); for (i = 0; i < uc_addr_in_use; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); } /* Add the new addresses */ for (i = 0; i < addr_count; i++) { DEBUGOUT(" Adding the secondary addresses:\n"); addr = next(hw, &addr_list, &vmdq); ixgbe_add_uc_addr(hw, addr, vmdq); } if (hw->addr_ctrl.overflow_promisc) { /* enable promisc if not already in overflow or set by user */ if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { DEBUGOUT(" Entering address overflow promisc mode\n"); fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl |= IXGBE_FCTRL_UPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } } else { /* only disable if set by overflow, not by user */ if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { DEBUGOUT(" Leaving address overflow promisc mode\n"); fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl &= ~IXGBE_FCTRL_UPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } } DEBUGOUT("ixgbe_update_uc_addr_list_generic Complete\n"); return IXGBE_SUCCESS; } /** * ixgbe_mta_vector - Determines bit-vector in multicast table to set * @hw: pointer to hardware structure * @mc_addr: the multicast address * * Extracts the 12 bits, from a multicast address, to determine which * bit-vector to set in the multicast table. The hardware uses 12 bits, from * incoming rx multicast addresses, to determine the bit-vector to check in * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ STATIC s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector = 0; DEBUGFUNC("ixgbe_mta_vector"); switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); break; case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); break; case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); break; case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); break; default: /* Invalid mc_filter_type */ DEBUGOUT("MC filter type param set incorrectly\n"); ASSERT(0); break; } /* vector can only be 12-bits or boundary will be exceeded */ vector &= 0xFFF; return vector; } /** * ixgbe_set_mta - Set bit-vector in multicast table * @hw: pointer to hardware structure * @hash_value: Multicast address hash value * * Sets the bit-vector in the multicast table. **/ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector; u32 vector_bit; u32 vector_reg; DEBUGFUNC("ixgbe_set_mta"); hw->addr_ctrl.mta_in_use++; vector = ixgbe_mta_vector(hw, mc_addr); DEBUGOUT1(" bit-vector = 0x%03X\n", vector); /* * The MTA is a register array of 128 32-bit registers. It is treated * like an array of 4096 bits. We want to set bit * BitArray[vector_value]. So we figure out what register the bit is * in, read it, OR in the new bit, then write back the new value. The * register is determined by the upper 7 bits of the vector value and * the bit within that register are determined by the lower 5 bits of * the value. */ vector_reg = (vector >> 5) & 0x7F; vector_bit = vector & 0x1F; hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); } /** * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @next: iterator function to walk the multicast address list * @clear: flag, when set clears the table beforehand * * When the clear flag is set, the given list replaces any existing list. * Hashes the given addresses into the multicast table. **/ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr next, bool clear) { u32 i; u32 vmdq; DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); /* * Set the new number of MC addresses that we are being requested to * use. */ hw->addr_ctrl.num_mc_addrs = mc_addr_count; hw->addr_ctrl.mta_in_use = 0; /* Clear mta_shadow */ if (clear) { DEBUGOUT(" Clearing MTA\n"); memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); } /* Update mta_shadow */ for (i = 0; i < mc_addr_count; i++) { DEBUGOUT(" Adding the multicast addresses:\n"); ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); } /* Enable mta */ for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, hw->mac.mta_shadow[i]); if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); DEBUGOUT("ixgbe_update_mc_addr_list_generic Complete\n"); return IXGBE_SUCCESS; } /** * ixgbe_enable_mc_generic - Enable multicast address in RAR * @hw: pointer to hardware structure * * Enables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; DEBUGFUNC("ixgbe_enable_mc_generic"); if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); return IXGBE_SUCCESS; } /** * ixgbe_disable_mc_generic - Disable multicast address in RAR * @hw: pointer to hardware structure * * Disables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; DEBUGFUNC("ixgbe_disable_mc_generic"); if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); return IXGBE_SUCCESS; } /** * ixgbe_fc_enable_generic - Enable flow control * @hw: pointer to hardware structure * * Enable flow control according to the current settings. **/ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; u32 mflcn_reg, fccfg_reg; u32 reg; u32 fcrtl, fcrth; int i; DEBUGFUNC("ixgbe_fc_enable_generic"); /* Validate the water mark configuration */ if (!hw->fc.pause_time) { ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* Low water mark of zero causes XOFF floods */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { if (!hw->fc.low_water[i] || hw->fc.low_water[i] >= hw->fc.high_water[i]) { DEBUGOUT("Invalid water mark configuration\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } } } /* Negotiate the fc mode to use */ ixgbe_fc_autoneg(hw); /* Disable any previous flow control settings */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); /* * The possible values of fc.current_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.current_mode) { case ixgbe_fc_none: /* * Flow control is disabled by software override or autoneg. * The code below will actually disable it in the HW. */ break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ mflcn_reg |= IXGBE_MFLCN_RFCE; break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; break; case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ mflcn_reg |= IXGBE_MFLCN_RFCE; fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; break; default: ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } /* Set 802.3x based flow control settings. */ mflcn_reg |= IXGBE_MFLCN_DPF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); /* Set up and enable Rx high/low water mark thresholds, enable XON. */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark * to the Rx packet buffer size - 24KB. This allows * the Tx switch to function even under heavy Rx * workloads. */ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time * 0x00010001; for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); out: return ret_val; } /** * ixgbe_negotiate_fc - Negotiate flow control * @hw: pointer to hardware structure * @adv_reg: flow control advertised settings * @lp_reg: link partner's flow control settings * @adv_sym: symmetric pause bit in advertisement * @adv_asm: asymmetric pause bit in advertisement * @lp_sym: symmetric pause bit in link partner advertisement * @lp_asm: asymmetric pause bit in link partner advertisement * * Find the intersection between advertised settings and link partner's * advertised settings **/ STATIC s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) { if ((!(adv_reg)) || (!(lp_reg))) { ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED, "Local or link partner's advertised flow control " "settings are NULL. Local: %x, link partner: %x\n", adv_reg, lp_reg); return IXGBE_ERR_FC_NOT_NEGOTIATED; } if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { /* * Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise RX * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == ixgbe_fc_full) { hw->fc.current_mode = ixgbe_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.current_mode = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control=RX PAUSE frames only\n"); } } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && (lp_reg & lp_sym) && (lp_reg & lp_asm)) { hw->fc.current_mode = ixgbe_fc_tx_pause; DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { hw->fc.current_mode = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); } else { hw->fc.current_mode = ixgbe_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } return IXGBE_SUCCESS; } /** * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber * @hw: pointer to hardware structure * * Enable flow control according on 1 gig fiber. **/ STATIC s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) { u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; /* * On multispeed fiber at 1g, bail out if * - link is up but AN did not complete, or if * - link is up and AN completed but timed out */ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { DEBUGOUT("Auto-Negotiation did not complete or timed out\n"); goto out; } pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, IXGBE_PCS1GANA_ASM_PAUSE, IXGBE_PCS1GANA_SYM_PAUSE, IXGBE_PCS1GANA_ASM_PAUSE); out: return ret_val; } /** * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 * @hw: pointer to hardware structure * * Enable flow control according to IEEE clause 37. **/ STATIC s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) { u32 links2, anlp1_reg, autoc_reg, links; s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; /* * On backplane, bail out if * - backplane autoneg was not completed, or if * - we are 82599 and link partner is not AN enabled */ links = IXGBE_READ_REG(hw, IXGBE_LINKS); if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) { DEBUGOUT("Auto-Negotiation did not complete\n"); goto out; } if (hw->mac.type == ixgbe_mac_82599EB) { links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) { DEBUGOUT("Link partner is not AN enabled\n"); goto out; } } /* * Read the 10g AN autoc and LP ability registers and resolve * local flow control settings accordingly */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); ret_val = ixgbe_negotiate_fc(hw, autoc_reg, anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); out: return ret_val; } /** * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 * @hw: pointer to hardware structure * * Enable flow control according to IEEE clause 37. **/ STATIC s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) { u16 technology_ability_reg = 0; u16 lp_technology_ability_reg = 0; hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &technology_ability_reg); hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &lp_technology_ability_reg); return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, (u32)lp_technology_ability_reg, IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); } /** * ixgbe_fc_autoneg - Configure flow control * @hw: pointer to hardware structure * * Compares our advertised flow control capabilities to those advertised by * our link partner, and determines the proper flow control mode to use. **/ void ixgbe_fc_autoneg(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; ixgbe_link_speed speed; bool link_up; DEBUGFUNC("ixgbe_fc_autoneg"); /* * AN should have completed when the cable was plugged in. * Look for reasons to bail out. Bail out if: * - FC autoneg is disabled, or if * - link is not up. */ if (hw->fc.disable_fc_autoneg) { ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, "Flow control autoneg is disabled"); goto out; } hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); goto out; } switch (hw->phy.media_type) { /* Autoneg flow control on fiber adapters */ case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: if (speed == IXGBE_LINK_SPEED_1GB_FULL) ret_val = ixgbe_fc_autoneg_fiber(hw); break; /* Autoneg flow control on backplane adapters */ case ixgbe_media_type_backplane: ret_val = ixgbe_fc_autoneg_backplane(hw); break; /* Autoneg flow control on copper adapters */ case ixgbe_media_type_copper: if (ixgbe_device_supports_autoneg_fc(hw)) ret_val = ixgbe_fc_autoneg_copper(hw); break; default: break; } out: if (ret_val == IXGBE_SUCCESS) { hw->fc.fc_was_autonegged = true; } else { hw->fc.fc_was_autonegged = false; hw->fc.current_mode = hw->fc.requested_mode; } } /* * ixgbe_pcie_timeout_poll - Return number of times to poll for completion * @hw: pointer to hardware structure * * System-wide timeout range is encoded in PCIe Device Control2 register. * * Add 10% to specified maximum and return the number of times to poll for * completion timeout, in units of 100 microsec. Never return less than * 800 = 80 millisec. */ STATIC u32 ixgbe_pcie_timeout_poll(struct ixgbe_hw *hw) { s16 devctl2; u32 pollcnt; devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); devctl2 &= IXGBE_PCIDEVCTRL2_TIMEO_MASK; switch (devctl2) { case IXGBE_PCIDEVCTRL2_65_130ms: pollcnt = 1300; /* 130 millisec */ break; case IXGBE_PCIDEVCTRL2_260_520ms: pollcnt = 5200; /* 520 millisec */ break; case IXGBE_PCIDEVCTRL2_1_2s: pollcnt = 20000; /* 2 sec */ break; case IXGBE_PCIDEVCTRL2_4_8s: pollcnt = 80000; /* 8 sec */ break; case IXGBE_PCIDEVCTRL2_17_34s: pollcnt = 34000; /* 34 sec */ break; case IXGBE_PCIDEVCTRL2_50_100us: /* 100 microsecs */ case IXGBE_PCIDEVCTRL2_1_2ms: /* 2 millisecs */ case IXGBE_PCIDEVCTRL2_16_32ms: /* 32 millisec */ case IXGBE_PCIDEVCTRL2_16_32ms_def: /* 32 millisec default */ default: pollcnt = 800; /* 80 millisec minimum */ break; } /* add 10% to spec maximum */ return (pollcnt * 11) / 10; } /** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure * * Disables PCI-Express master access and verifies there are no pending * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable * bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS * is returned signifying master requests disabled. **/ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u32 i, poll; u16 value; DEBUGFUNC("ixgbe_disable_pcie_master"); /* Always set this bit to ensure any future transactions are blocked */ IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); /* Exit if master requests are blocked */ if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) || IXGBE_REMOVED(hw->hw_addr)) goto out; /* Poll for master request bit to clear */ for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { usec_delay(100); if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) goto out; } /* * Two consecutive resets are required via CTRL.RST per datasheet * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine * of this need. The first reset prevents new master requests from * being issued by our device. We then must wait 1usec or more for any * remaining completions from the PCIe bus to trickle in, and then reset * again to clear out any effects they may have had on our device. */ DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; if (hw->mac.type >= ixgbe_mac_X550) goto out; /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. */ poll = ixgbe_pcie_timeout_poll(hw); for (i = 0; i < poll; i++) { usec_delay(100); value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); if (IXGBE_REMOVED(hw->hw_addr)) goto out; if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) goto out; } ERROR_REPORT1(IXGBE_ERROR_POLLING, "PCIe transaction pending bit also did not clear.\n"); status = IXGBE_ERR_MASTER_REQUESTS_PENDING; out: return status; } /** * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore through the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask) { u32 gssr = 0; u32 swmask = mask; u32 fwmask = mask << 5; u32 timeout = 200; u32 i; DEBUGFUNC("ixgbe_acquire_swfw_sync"); for (i = 0; i < timeout; i++) { /* * SW NVM semaphore bit is used for access to all * SW_FW_SYNC bits (not just NVM) */ if (ixgbe_get_eeprom_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); if (!(gssr & (fwmask | swmask))) { gssr |= swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw); return IXGBE_SUCCESS; } else { /* Resource is currently in use by FW or SW */ ixgbe_release_eeprom_semaphore(hw); msec_delay(5); } } /* If time expired clear the bits holding the lock and retry */ if (gssr & (fwmask | swmask)) ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask)); msec_delay(5); return IXGBE_ERR_SWFW_SYNC; } /** * ixgbe_release_swfw_sync - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask) { u32 gssr; u32 swmask = mask; DEBUGFUNC("ixgbe_release_swfw_sync"); ixgbe_get_eeprom_semaphore(hw); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); gssr &= ~swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw); } /** * ixgbe_disable_sec_rx_path_generic - Stops the receive data path * @hw: pointer to hardware structure * * Stops the receive data path and waits for the HW to internally empty * the Rx security block **/ s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) { #define IXGBE_MAX_SECRX_POLL 40 int i; int secrxreg; DEBUGFUNC("ixgbe_disable_sec_rx_path_generic"); secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); secrxreg |= IXGBE_SECRXCTRL_RX_DIS; IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) break; else /* Use interrupt-safe sleep just in case */ usec_delay(1000); } /* For informational purposes only */ if (i >= IXGBE_MAX_SECRX_POLL) DEBUGOUT("Rx unit being enabled before security " "path fully disabled. Continuing with init.\n"); return IXGBE_SUCCESS; } /** * prot_autoc_read_generic - Hides MAC differences needed for AUTOC read * @hw: pointer to hardware structure * @reg_val: Value we read from AUTOC * * The default case requires no protection so just to the register read. */ s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val) { *locked = false; *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC); return IXGBE_SUCCESS; } /** * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write * @hw: pointer to hardware structure * @reg_val: value to write to AUTOC * @locked: bool to indicate whether the SW/FW lock was already taken by * previous read. * * The default case requires no protection so just to the register write. */ s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked) { UNREFERENCED_1PARAMETER(locked); IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val); return IXGBE_SUCCESS; } /** * ixgbe_enable_sec_rx_path_generic - Enables the receive data path * @hw: pointer to hardware structure * * Enables the receive data path. **/ s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) { int secrxreg; DEBUGFUNC("ixgbe_enable_sec_rx_path_generic"); secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } /** * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit * @hw: pointer to hardware structure * @regval: register value to write to RXCTRL * * Enables the Rx DMA unit **/ s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) { DEBUGFUNC("ixgbe_enable_rx_dma_generic"); if (regval & IXGBE_RXCTRL_RXEN) ixgbe_enable_rx(hw); else ixgbe_disable_rx(hw); return IXGBE_SUCCESS; } /** * ixgbe_blink_led_start_generic - Blink LED based on index. * @hw: pointer to hardware structure * @index: led number to blink **/ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) { ixgbe_link_speed speed = 0; bool link_up = 0; u32 autoc_reg = 0; u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); s32 ret_val = IXGBE_SUCCESS; bool locked = false; DEBUGFUNC("ixgbe_blink_led_start_generic"); /* * Link must be up to auto-blink the LEDs; * Force it if link is down. */ hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); if (ret_val != IXGBE_SUCCESS) goto out; autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); if (ret_val != IXGBE_SUCCESS) goto out; IXGBE_WRITE_FLUSH(hw); msec_delay(10); } led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); out: return ret_val; } /** * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. * @hw: pointer to hardware structure * @index: led number to stop blinking **/ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) { u32 autoc_reg = 0; u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); s32 ret_val = IXGBE_SUCCESS; bool locked = false; DEBUGFUNC("ixgbe_blink_led_stop_generic"); ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg); if (ret_val != IXGBE_SUCCESS) goto out; autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked); if (ret_val != IXGBE_SUCCESS) goto out; led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg &= ~IXGBE_LED_BLINK(index); led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); out: return ret_val; } /** * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM * @hw: pointer to hardware structure * @san_mac_offset: SAN MAC address offset * * This function will read the EEPROM location for the SAN MAC address * pointer, and returns the value at that location. This is used in both * get and set mac_addr routines. **/ STATIC s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset) { s32 ret_val; DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); /* * First read the EEPROM pointer to see if the MAC addresses are * available. */ ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); if (ret_val) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom at offset %d failed", IXGBE_SAN_MAC_ADDR_PTR); } return ret_val; } /** * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Reads the SAN MAC address from the EEPROM, if it's available. This is * per-port, so set_lan_id() must be called before reading the addresses. * set_lan_id() is called by identify_sfp(), but this cannot be relied * upon for non-SFP connections, so we must call it here. **/ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) { u16 san_mac_data, san_mac_offset; u8 i; s32 ret_val; DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); /* * First read the EEPROM pointer to see if the MAC addresses are * available. If they're not, no point in calling set_lan_id() here. */ ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) goto san_mac_addr_out; /* make sure we know which port we need to program */ hw->mac.ops.set_lan_id(hw); /* apply the port offset to the address offset */ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); for (i = 0; i < 3; i++) { ret_val = hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); if (ret_val) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", san_mac_offset); goto san_mac_addr_out; } san_mac_addr[i * 2] = (u8)(san_mac_data); san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); san_mac_offset++; } return IXGBE_SUCCESS; san_mac_addr_out: /* * No addresses available in this EEPROM. It's not an * error though, so just wipe the local address and return. */ for (i = 0; i < 6; i++) san_mac_addr[i] = 0xFF; return IXGBE_SUCCESS; } /** * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Write a SAN MAC address to the EEPROM. **/ s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) { s32 ret_val; u16 san_mac_data, san_mac_offset; u8 i; DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); /* Look for SAN mac address pointer. If not defined, return */ ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF) return IXGBE_ERR_NO_SAN_ADDR_PTR; /* Make sure we know which port we need to write */ hw->mac.ops.set_lan_id(hw); /* Apply the port offset to the address offset */ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); for (i = 0; i < 3; i++) { san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); san_mac_data |= (u16)(san_mac_addr[i * 2]); hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); san_mac_offset++; } return IXGBE_SUCCESS; } /** * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count * @hw: pointer to hardware structure * * Read PCIe configuration space, and get the MSI-X vector count from * the capabilities table. **/ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) { u16 msix_count = 1; u16 max_msix_count; u16 pcie_offset; switch (hw->mac.type) { case ixgbe_mac_82598EB: pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; break; default: return msix_count; } DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); if (IXGBE_REMOVED(hw->hw_addr)) msix_count = 0; msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; /* MSI-X count is zero-based in HW */ msix_count++; if (msix_count > max_msix_count) msix_count = max_msix_count; return msix_count; } /** * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address * @hw: pointer to hardware structure * @addr: Address to put into receive address register * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or * finds the rar that it is aleady in; adds to the pool list **/ s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; u32 first_empty_rar = NO_EMPTY_RAR_FOUND; u32 rar; u32 rar_low, rar_high; u32 addr_low, addr_high; DEBUGFUNC("ixgbe_insert_mac_addr_generic"); /* swap bytes for HW little endian */ addr_low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); addr_high = addr[4] | (addr[5] << 8); /* * Either find the mac_id in rar or find the first empty space. * rar_highwater points to just after the highest currently used * rar in order to shorten the search. It grows when we add a new * rar to the top. */ for (rar = 0; rar < hw->mac.rar_highwater; rar++) { rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); if (((IXGBE_RAH_AV & rar_high) == 0) && first_empty_rar == NO_EMPTY_RAR_FOUND) { first_empty_rar = rar; } else if ((rar_high & 0xFFFF) == addr_high) { rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); if (rar_low == addr_low) break; /* found it already in the rars */ } } if (rar < hw->mac.rar_highwater) { /* already there so just add to the pool bits */ ixgbe_set_vmdq(hw, rar, vmdq); } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { /* stick it into first empty RAR slot we found */ rar = first_empty_rar; ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); } else if (rar == hw->mac.rar_highwater) { /* add it to the top of the list and inc the highwater mark */ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); hw->mac.rar_highwater++; } else if (rar >= hw->mac.num_rar_entries) { return IXGBE_ERR_INVALID_MAC_ADDR; } /* * If we found rar[0], make sure the default pool bit (we use pool 0) * remains cleared to be sure default pool packets will get delivered */ if (rar == 0) ixgbe_clear_vmdq(hw, rar, 0); return rar; } /** * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address * @hw: pointer to hardware struct * @rar: receive address register index to disassociate * @vmdq: VMDq pool index to remove from the rar **/ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 mpsar_lo, mpsar_hi; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_clear_vmdq_generic"); /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); if (IXGBE_REMOVED(hw->hw_addr)) goto done; if (!mpsar_lo && !mpsar_hi) goto done; if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { if (mpsar_lo) { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); mpsar_lo = 0; } if (mpsar_hi) { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); mpsar_hi = 0; } } else if (vmdq < 32) { mpsar_lo &= ~(1 << vmdq); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); } else { mpsar_hi &= ~(1 << (vmdq - 32)); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); } /* was that the last pool using this rar? */ if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) hw->mac.ops.clear_rar(hw, rar); done: return IXGBE_SUCCESS; } /** * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq pool index **/ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 mpsar; u32 rar_entries = hw->mac.num_rar_entries; DEBUGFUNC("ixgbe_set_vmdq_generic"); /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } if (vmdq < 32) { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); mpsar |= 1 << vmdq; IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); } else { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); mpsar |= 1 << (vmdq - 32); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); } return IXGBE_SUCCESS; } /** * This function should only be involved in the IOV mode. * In IOV mode, Default pool is next pool after the number of * VFs advertized and not 0. * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] * * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address * @hw: pointer to hardware struct * @vmdq: VMDq pool index **/ s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) { u32 rar = hw->mac.san_mac_rar_index; DEBUGFUNC("ixgbe_set_vmdq_san_mac"); if (vmdq < 32) { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); } else { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32)); } return IXGBE_SUCCESS; } /** * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array * @hw: pointer to hardware structure **/ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) { int i; DEBUGFUNC("ixgbe_init_uta_tables_generic"); DEBUGOUT(" Clearing UTA\n"); for (i = 0; i < 128; i++) IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); return IXGBE_SUCCESS; } /** * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * * return the VLVF index where this VLAN id should be placed * **/ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) { u32 bits = 0; u32 first_empty_slot = 0; s32 regindex; /* short cut the special case */ if (vlan == 0) return 0; /* * Search for the vlan id in the VLVF entries. Save off the first empty * slot found along the way */ for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); if (!bits && !(first_empty_slot)) first_empty_slot = regindex; else if ((bits & 0x0FFF) == vlan) break; } /* * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan * in the VLVF. Else use the first empty VLVF register for this * vlan id. */ if (regindex >= IXGBE_VLVF_ENTRIES) { if (first_empty_slot) regindex = first_empty_slot; else { ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n"); regindex = IXGBE_ERR_NO_SPACE; } } return regindex; } /** * ixgbe_set_vfta_generic - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { s32 regindex; u32 bitindex; u32 vfta; u32 targetbit; s32 ret_val = IXGBE_SUCCESS; bool vfta_changed = false; DEBUGFUNC("ixgbe_set_vfta_generic"); if (vlan > 4095) return IXGBE_ERR_PARAM; /* * this is a 2 part operation - first the VFTA, then the * VLVF and VLVFB if VT Mode is set * We don't write the VFTA until we know the VLVF part succeeded. */ /* Part 1 * The VFTA is a bitstring made up of 128 32-bit registers * that enable the particular VLAN id, much like the MTA: * bits[11-5]: which register * bits[4-0]: which bit in the register */ regindex = (vlan >> 5) & 0x7F; bitindex = vlan & 0x1F; targetbit = (1 << bitindex); vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); if (vlan_on) { if (!(vfta & targetbit)) { vfta |= targetbit; vfta_changed = true; } } else { if ((vfta & targetbit)) { vfta &= ~targetbit; vfta_changed = true; } } /* Part 2 * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF */ ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_changed); if (ret_val != IXGBE_SUCCESS) return ret_val; if (vfta_changed) IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta); return IXGBE_SUCCESS; } /** * ixgbe_set_vlvf_generic - Set VLAN Pool Filter * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * @vfta_changed: pointer to boolean flag which indicates whether VFTA * should be changed * * Turn on/off specified bit in VLVF table. **/ s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed) { u32 vt; DEBUGFUNC("ixgbe_set_vlvf_generic"); if (vlan > 4095) return IXGBE_ERR_PARAM; /* If VT Mode is set * Either vlan_on * make sure the vlan is in VLVF * set the vind bit in the matching VLVFB * Or !vlan_on * clear the pool bit and possibly the vind */ vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); if (vt & IXGBE_VT_CTL_VT_ENABLE) { s32 vlvf_index; u32 bits; vlvf_index = ixgbe_find_vlvf_slot(hw, vlan); if (vlvf_index < 0) return vlvf_index; if (vlan_on) { /* set the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); bits |= (1 << vind); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2), bits); } else { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); bits |= (1 << (vind - 32)); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1), bits); } } else { /* clear the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); bits &= ~(1 << vind); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2), bits); bits |= IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); } else { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); bits &= ~(1 << (vind - 32)); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1), bits); bits |= IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); } } /* * If there are still bits set in the VLVFB registers * for the VLAN ID indicated we need to see if the * caller is requesting that we clear the VFTA entry bit. * If the caller has requested that we clear the VFTA * entry bit but there are still pools/VFs using this VLAN * ID entry then ignore the request. We're not worried * about the case where we're turning the VFTA VLAN ID * entry bit on, only when requested to turn it off as * there may be multiple pools and/or VFs using the * VLAN ID entry. In that case we cannot clear the * VFTA bit until all pools/VFs using that VLAN ID have also * been cleared. This will be indicated by "bits" being * zero. */ if (bits) { IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), (IXGBE_VLVF_VIEN | vlan)); if ((!vlan_on) && (vfta_changed != NULL)) { /* someone wants to clear the vfta entry * but some pools/VFs are still using it. * Ignore it. */ *vfta_changed = false; } } else IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); } return IXGBE_SUCCESS; } /** * ixgbe_clear_vfta_generic - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) { u32 offset; DEBUGFUNC("ixgbe_clear_vfta_generic"); for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); } return IXGBE_SUCCESS; } /** * ixgbe_check_mac_link_generic - Determine link and speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true when link is up * @link_up_wait_to_complete: bool used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { u32 links_reg, links_orig; u32 i; DEBUGFUNC("ixgbe_check_mac_link_generic"); /* clear the old state */ links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_orig != links_reg) { DEBUGOUT2("LINKS changed from %08X to %08X\n", links_orig, links_reg); } if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = true; break; } else { *link_up = false; } msec_delay(100); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); } } else { if (links_reg & IXGBE_LINKS_UP) *link_up = true; else *link_up = false; } switch (links_reg & IXGBE_LINKS_SPEED_82599) { case IXGBE_LINKS_SPEED_10G_82599: *speed = IXGBE_LINK_SPEED_10GB_FULL; if (hw->mac.type >= ixgbe_mac_X550) { if (links_reg & IXGBE_LINKS_SPEED_NON_STD) *speed = IXGBE_LINK_SPEED_2_5GB_FULL; } break; case IXGBE_LINKS_SPEED_1G_82599: *speed = IXGBE_LINK_SPEED_1GB_FULL; break; case IXGBE_LINKS_SPEED_100_82599: *speed = IXGBE_LINK_SPEED_100_FULL; if (hw->mac.type >= ixgbe_mac_X550) { if (links_reg & IXGBE_LINKS_SPEED_NON_STD) *speed = IXGBE_LINK_SPEED_5GB_FULL; } break; default: *speed = IXGBE_LINK_SPEED_UNKNOWN; } return IXGBE_SUCCESS; } /** * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from * the EEPROM * @hw: pointer to hardware structure * @wwnn_prefix: the alternative WWNN prefix * @wwpn_prefix: the alternative WWPN prefix * * This function will read the EEPROM from the alternative SAN MAC address * block to check the support for the alternative WWNN/WWPN prefix support. **/ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix) { u16 offset, caps; u16 alt_san_mac_blk_offset; DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); /* clear output first */ *wwnn_prefix = 0xFFFF; *wwpn_prefix = 0xFFFF; /* check if alternative SAN MAC is supported */ offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR; if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset)) goto wwn_prefix_err; if ((alt_san_mac_blk_offset == 0) || (alt_san_mac_blk_offset == 0xFFFF)) goto wwn_prefix_out; /* check capability in alternative san mac address block */ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; if (hw->eeprom.ops.read(hw, offset, &caps)) goto wwn_prefix_err; if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) goto wwn_prefix_out; /* get the corresponding prefix for WWNN/WWPN */ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; if (hw->eeprom.ops.read(hw, offset, wwnn_prefix)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", offset); } offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; if (hw->eeprom.ops.read(hw, offset, wwpn_prefix)) goto wwn_prefix_err; wwn_prefix_out: return IXGBE_SUCCESS; wwn_prefix_err: ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", offset); return IXGBE_SUCCESS; } /** * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM * @hw: pointer to hardware structure * @bs: the fcoe boot status * * This function will read the FCOE boot status from the iSCSI FCOE block **/ s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) { u16 offset, caps, flags; s32 status; DEBUGFUNC("ixgbe_get_fcoe_boot_status_generic"); /* clear output first */ *bs = ixgbe_fcoe_bootstatus_unavailable; /* check if FCOE IBA block is present */ offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; status = hw->eeprom.ops.read(hw, offset, &caps); if (status != IXGBE_SUCCESS) goto out; if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) goto out; /* check if iSCSI FCOE block is populated */ status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); if (status != IXGBE_SUCCESS) goto out; if ((offset == 0) || (offset == 0xFFFF)) goto out; /* read fcoe flags in iSCSI FCOE block */ offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; status = hw->eeprom.ops.read(hw, offset, &flags); if (status != IXGBE_SUCCESS) goto out; if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) *bs = ixgbe_fcoe_bootstatus_enabled; else *bs = ixgbe_fcoe_bootstatus_disabled; out: return status; } /** * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for anti-spoofing * @pf: Physical Function pool - do not enable anti-spoofing for the PF * **/ void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf) { int j; int pf_target_reg = pf >> 3; int pf_target_shift = pf % 8; u32 pfvfspoof = 0; if (hw->mac.type == ixgbe_mac_82598EB) return; if (enable) pfvfspoof = IXGBE_SPOOF_MACAS_MASK; /* * PFVFSPOOF register array is size 8 with 8 bits assigned to * MAC anti-spoof enables in each register array element. */ for (j = 0; j < pf_target_reg; j++) IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); /* * The PF should be allowed to spoof so that it can support * emulation mode NICs. Do not set the bits assigned to the PF */ pfvfspoof &= (1 << pf_target_shift) - 1; IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); /* * Remaining pools belong to the PF so they do not need to have * anti-spoofing enabled. */ for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++) IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0); } /** * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for VLAN anti-spoofing * @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing * **/ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) { int vf_target_reg = vf >> 3; int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; u32 pfvfspoof; if (hw->mac.type == ixgbe_mac_82598EB) return; pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) pfvfspoof |= (1 << vf_target_shift); else pfvfspoof &= ~(1 << vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } /** * ixgbe_get_device_caps_generic - Get additional device capabilities * @hw: pointer to hardware structure * @device_caps: the EEPROM word with the extra device capabilities * * This function will read the EEPROM location for the device capabilities, * and return the word through device_caps. **/ s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) { DEBUGFUNC("ixgbe_get_device_caps_generic"); hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); return IXGBE_SUCCESS; } /** * ixgbe_enable_relaxed_ordering_gen2 - Enable relaxed ordering * @hw: pointer to hardware structure * **/ void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw) { u32 regval; u32 i; DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2"); /* Enable relaxed ordering */ for (i = 0; i < hw->mac.max_tx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); } for (i = 0; i < hw->mac.max_rx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } } /** * ixgbe_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM * @length: size of EEPROM to calculate a checksum for * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) { u32 i; u8 sum = 0; DEBUGFUNC("ixgbe_calculate_checksum"); if (!buffer) return 0; for (i = 0; i < length; i++) sum += buffer[i]; return (u8) (0 - sum); } /** * ixgbe_host_interface_command - Issue command to manageability block * @hw: pointer to the HW structure * @buffer: contains the command to write and where the return status will * be placed * @length: length of buffer, must be multiple of 4 bytes * @timeout: time in ms to wait for command completion * @return_data: read and return data from the buffer (true) or not (false) * Needed because FW structures are big endian and decoding of * these fields can be 8 bit or 16 bit based on command. Decoding * is not easily understood without making a table of commands. * So we will leave this up to the caller to read back the data * in these cases. * * Communicates with the manageability block. On success return IXGBE_SUCCESS * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. **/ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, u32 length, u32 timeout, bool return_data) { u32 hicr, i, bi, fwsts; u32 hdr_size = sizeof(struct ixgbe_hic_hdr); u16 buf_len; u16 dword_len; DEBUGFUNC("ixgbe_host_interface_command"); if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } /* Set bit 9 of FWSTS clearing FW reset indication */ fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); /* Check that the host interface is enabled. */ hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if ((hicr & IXGBE_HICR_EN) == 0) { DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs. We must be DWORD aligned */ if ((length % (sizeof(u32))) != 0) { DEBUGOUT("Buffer length failure, not aligned to dword"); return IXGBE_ERR_INVALID_ARGUMENT; } dword_len = length >> 2; /* The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < dword_len; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, i, IXGBE_CPU_TO_LE32(buffer[i])); /* Setting this bit tells the ARC that a new command is pending. */ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); for (i = 0; i < timeout; i++) { hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if (!(hicr & IXGBE_HICR_C)) break; msec_delay(1); } /* Check command completion */ if ((timeout != 0 && i == timeout) || !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { ERROR_REPORT1(IXGBE_ERROR_CAUTION, "Command has failed with no status valid.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } if (!return_data) return 0; /* Calculate length in DWORDs */ dword_len = hdr_size >> 2; /* first pull in the header so we know the buffer length */ for (bi = 0; bi < dword_len; bi++) { buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); IXGBE_LE32_TO_CPUS(&buffer[bi]); } /* If there is any thing in data position pull it in */ buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; if (buf_len == 0) return 0; if (length < buf_len + hdr_size) { DEBUGOUT("Buffer not large enough for reply message.\n"); return IXGBE_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs, add 3 for odd lengths */ dword_len = (buf_len + 3) >> 2; /* Pull in the rest of the buffer (bi is where we left off) */ for (; bi <= dword_len; bi++) { buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); IXGBE_LE32_TO_CPUS(&buffer[bi]); } return 0; } /** * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware * @hw: pointer to the HW structure * @maj: driver version major number * @min: driver version minor number * @build: driver version build number * @sub: driver version sub build number * * Sends driver version number to firmware through the manageability * block. On success return IXGBE_SUCCESS * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. **/ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 sub) { struct ixgbe_hic_drv_info fw_cmd; int i; s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_set_fw_drv_ver_generic"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != IXGBE_SUCCESS) { ret_val = IXGBE_ERR_SWFW_SYNC; goto out; } fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; fw_cmd.port_num = (u8)hw->bus.func; fw_cmd.ver_maj = maj; fw_cmd.ver_min = min; fw_cmd.ver_build = build; fw_cmd.ver_sub = sub; fw_cmd.hdr.checksum = 0; fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); fw_cmd.pad = 0; fw_cmd.pad2 = 0; for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, sizeof(fw_cmd), IXGBE_HI_COMMAND_TIMEOUT, true); if (ret_val != IXGBE_SUCCESS) continue; if (fw_cmd.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) ret_val = IXGBE_SUCCESS; else ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; break; } hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); out: return ret_val; } /** * ixgbe_set_rxpba_generic - Initialize Rx packet buffer * @hw: pointer to hardware structure * @num_pb: number of packet buffers to allocate * @headroom: reserve n KB of headroom * @strategy: packet buffer allocation strategy **/ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy) { u32 pbsize = hw->mac.rx_pb_size; int i = 0; u32 rxpktsize, txpktsize, txpbthresh; /* Reserve headroom */ pbsize -= headroom; if (!num_pb) num_pb = 1; /* Divide remaining packet buffer space amongst the number of packet * buffers requested using supplied strategy. */ switch (strategy) { case PBA_STRATEGY_WEIGHTED: /* ixgbe_dcb_pba_80_48 strategy weight first half of packet * buffer with 5/8 of the packet buffer space. */ rxpktsize = (pbsize * 5) / (num_pb * 4); pbsize -= rxpktsize * (num_pb / 2); rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; for (; i < (num_pb / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); /* Fall through to configure remaining packet buffers */ case PBA_STRATEGY_EQUAL: rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; for (; i < num_pb; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); break; default: break; } /* Only support an equally distributed Tx packet buffer strategy. */ txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; for (i = 0; i < num_pb; i++) { IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); } /* Clear unused TCs, if any, to zero buffer size*/ for (; i < IXGBE_MAX_PB; i++) { IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); } } /** * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo * @hw: pointer to the hardware structure * * The 82599 and x540 MACs can experience issues if TX work is still pending * when a reset occurs. This function prevents this by flushing the PCIe * buffers on the system. **/ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) { u32 gcr_ext, hlreg0, i, poll; u16 value; /* * If double reset is not requested then all transactions should * already be clear and as such there is no work to do */ if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) return; /* * Set loopback enable to prevent any transmits from being sent * should the link come up. This assumes that the RXCTRL.RXEN bit * has already been cleared. */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); /* Wait for a last completion before clearing buffers */ IXGBE_WRITE_FLUSH(hw); msec_delay(3); /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. */ poll = ixgbe_pcie_timeout_poll(hw); for (i = 0; i < poll; i++) { usec_delay(100); value = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS); if (IXGBE_REMOVED(hw->hw_addr)) goto out; if (!(value & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) goto out; } out: /* initiate cleaning flow for buffers in the PCIe transaction layer */ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); /* Flush all writes and allow 20usec for all transactions to clear */ IXGBE_WRITE_FLUSH(hw); usec_delay(20); /* restore previous register values */ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); } STATIC const u8 ixgbe_emc_temp_data[4] = { IXGBE_EMC_INTERNAL_DATA, IXGBE_EMC_DIODE1_DATA, IXGBE_EMC_DIODE2_DATA, IXGBE_EMC_DIODE3_DATA }; STATIC const u8 ixgbe_emc_therm_limit[4] = { IXGBE_EMC_INTERNAL_THERM_LIMIT, IXGBE_EMC_DIODE1_THERM_LIMIT, IXGBE_EMC_DIODE2_THERM_LIMIT, IXGBE_EMC_DIODE3_THERM_LIMIT }; /** * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data * @hw: pointer to hardware structure * @data: pointer to the thermal sensor data structure * * Returns the thermal sensor data structure **/ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 i; struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; DEBUGFUNC("ixgbe_get_thermal_sensor_data_generic"); /* Only support thermal sensors attached to 82599 physical port 0 */ if ((hw->mac.type != ixgbe_mac_82599EB) || (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) { status = IXGBE_NOT_IMPLEMENTED; goto out; } status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset); if (status) goto out; if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) { status = IXGBE_NOT_IMPLEMENTED; goto out; } status = hw->eeprom.ops.read(hw, ets_offset, &ets_cfg); if (status) goto out; if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) != IXGBE_ETS_TYPE_EMC) { status = IXGBE_NOT_IMPLEMENTED; goto out; } num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); if (num_sensors > IXGBE_MAX_SENSORS) num_sensors = IXGBE_MAX_SENSORS; for (i = 0; i < num_sensors; i++) { status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor); if (status) goto out; sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> IXGBE_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> IXGBE_ETS_DATA_LOC_SHIFT); if (sensor_location != 0) { status = hw->phy.ops.read_i2c_byte(hw, ixgbe_emc_temp_data[sensor_index], IXGBE_I2C_THERMAL_SENSOR_ADDR, &data->sensor[i].temp); if (status) goto out; } } out: return status; } /** * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds * @hw: pointer to hardware structure * * Inits the thermal sensor thresholds according to the NVM map * and save off the threshold and location values into mac.thermal_sensor_data **/ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 offset; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 low_thresh_delta; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 therm_limit; u8 i; struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; DEBUGFUNC("ixgbe_init_thermal_sensor_thresh_generic"); memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data)); /* Only support thermal sensors attached to 82599 physical port 0 */ if ((hw->mac.type != ixgbe_mac_82599EB) || (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) return IXGBE_NOT_IMPLEMENTED; offset = IXGBE_ETS_CFG; if (hw->eeprom.ops.read(hw, offset, &ets_offset)) goto eeprom_err; if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) return IXGBE_NOT_IMPLEMENTED; offset = ets_offset; if (hw->eeprom.ops.read(hw, offset, &ets_cfg)) goto eeprom_err; if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) != IXGBE_ETS_TYPE_EMC) return IXGBE_NOT_IMPLEMENTED; low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >> IXGBE_ETS_LTHRES_DELTA_SHIFT); num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); for (i = 0; i < num_sensors; i++) { offset = ets_offset + 1 + i; if (hw->eeprom.ops.read(hw, offset, &ets_sensor)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", offset); continue; } sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> IXGBE_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> IXGBE_ETS_DATA_LOC_SHIFT); therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK; hw->phy.ops.write_i2c_byte(hw, ixgbe_emc_therm_limit[sensor_index], IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit); if ((i < IXGBE_MAX_SENSORS) && (sensor_location != 0)) { data->sensor[i].location = sensor_location; data->sensor[i].caution_thresh = therm_limit; data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta; } } return status; eeprom_err: ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", offset); return IXGBE_NOT_IMPLEMENTED; } /** * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg * @hw: pointer to hardware structure * @map: pointer to u8 arr for returning map * * Read the rtrup2tc HW register and resolve its content into map **/ void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map) { u32 reg, i; reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) map[i] = IXGBE_RTRUP2TC_UP_MASK & (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); return; } void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) { u32 pfdtxgswc; u32 rxctrl; rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); if (rxctrl & IXGBE_RXCTRL_RXEN) { if (hw->mac.type != ixgbe_mac_82598EB) { pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); hw->mac.set_lben = true; } else { hw->mac.set_lben = false; } } rxctrl &= ~IXGBE_RXCTRL_RXEN; IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); } } void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) { u32 pfdtxgswc; u32 rxctrl; rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); if (hw->mac.type != ixgbe_mac_82598EB) { if (hw->mac.set_lben) { pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); pfdtxgswc |= IXGBE_PFDTXGSWC_VT_LBEN; IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); hw->mac.set_lben = false; } } } /** * ixgbe_mng_present - returns true when management capability is present * @hw: pointer to hardware structure */ bool ixgbe_mng_present(struct ixgbe_hw *hw) { u32 fwsm; if (hw->mac.type < ixgbe_mac_82599EB) return false; fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); fwsm &= IXGBE_FWSM_MODE_MASK; return fwsm == IXGBE_FWSM_FW_MODE_PT; } /** * ixgbe_mng_enabled - Is the manageability engine enabled? * @hw: pointer to hardware structure * * Returns true if the manageability engine is enabled. **/ bool ixgbe_mng_enabled(struct ixgbe_hw *hw) { u32 fwsm, manc, factps; fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) return false; manc = IXGBE_READ_REG(hw, IXGBE_MANC); if (!(manc & IXGBE_MANC_RCV_TCO_EN)) return false; if (hw->mac.type <= ixgbe_mac_X540) { factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); if (factps & IXGBE_FACTPS_MNGCG) return false; } return true; } /** * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the MAC and/or PHY register and restarts link. **/ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; s32 status = IXGBE_SUCCESS; u32 speedcnt = 0; u32 i = 0; bool autoneg, link_up = false; DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &autoneg); if (status != IXGBE_SUCCESS) return status; speed &= link_speed; /* Try each speed one by one, highest priority first. We do this in * software because 10Gb fiber doesn't support speed autonegotiation. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) { speedcnt++; highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; /* Set the module link speed */ switch (hw->phy.media_type) { case ixgbe_media_type_fiber: ixgbe_set_rate_select_speed(hw, IXGBE_LINK_SPEED_10GB_FULL); break; case ixgbe_media_type_fiber_qsfp: /* QSFP module automatically detects MAC link speed */ break; default: DEBUGOUT("Unexpected media type.\n"); break; } /* Allow module to change analog characteristics (1G->10G) */ msec_delay(40); status = ixgbe_setup_mac_link(hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the Tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted. 82599 uses the same timing for 10g SFI. */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { speedcnt++; if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; /* Set the module link speed */ switch (hw->phy.media_type) { case ixgbe_media_type_fiber: ixgbe_set_rate_select_speed(hw, IXGBE_LINK_SPEED_1GB_FULL); break; case ixgbe_media_type_fiber_qsfp: /* QSFP module automatically detects link speed */ break; default: DEBUGOUT("Unexpected media type.\n"); break; } /* Allow module to change analog characteristics (10G->1G) */ msec_delay(40); status = ixgbe_setup_mac_link(hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the Tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } /* We didn't get link. Configure back to the highest speed we tried, * (if there was more than one). We call ourselves back with just the * single highest speed that the user requested. */ if (speedcnt > 1) status = ixgbe_setup_mac_link_multispeed_fiber(hw, highest_link_speed, autoneg_wait_to_complete); out: /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; return status; } /** * ixgbe_set_soft_rate_select_speed - Set module link speed * @hw: pointer to hardware structure * @speed: link speed to set * * Set module link speed via the soft rate select. */ void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) { s32 status; u8 rs, eeprom_data; switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: /* one bit mask same as setting on */ rs = IXGBE_SFF_SOFT_RS_SELECT_10G; break; case IXGBE_LINK_SPEED_1GB_FULL: rs = IXGBE_SFF_SOFT_RS_SELECT_1G; break; default: DEBUGOUT("Invalid fixed module speed\n"); return; } /* Set RS0 */ status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, IXGBE_I2C_EEPROM_DEV_ADDR2, &eeprom_data); if (status) { DEBUGOUT("Failed to read Rx Rate Select RS0\n"); goto out; } eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, IXGBE_I2C_EEPROM_DEV_ADDR2, eeprom_data); if (status) { DEBUGOUT("Failed to write Rx Rate Select RS0\n"); goto out; } /* Set RS1 */ status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, IXGBE_I2C_EEPROM_DEV_ADDR2, &eeprom_data); if (status) { DEBUGOUT("Failed to read Rx Rate Select RS1\n"); goto out; } eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, IXGBE_I2C_EEPROM_DEV_ADDR2, eeprom_data); if (status) { DEBUGOUT("Failed to write Rx Rate Select RS1\n"); goto out; } out: return; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_common.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_COMMON_H_ #define _IXGBE_COMMON_H_ #include "ixgbe_type.h" #define IXGBE_WRITE_REG64(hw, reg, value) \ do { \ IXGBE_WRITE_REG(hw, reg, (u32) value); \ IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \ } while (0) #define IXGBE_REMOVED(a) (0) struct ixgbe_pba { u16 word[2]; u16 *pba_block; }; void ixgbe_dcb_get_rtrup2tc_generic(struct ixgbe_hw *hw, u8 *map); u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw); s32 ixgbe_read_pba_num_generic(struct ixgbe_hw *hw, u32 *pba_num); s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size); s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 max_pba_block_size, struct ixgbe_pba *pba); s32 ixgbe_write_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, struct ixgbe_pba *pba); s32 ixgbe_get_pba_block_size(struct ixgbe_hw *hw, u16 *eeprom_buf, u32 eeprom_buf_size, u16 *pba_block_size); s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw); void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status); void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw); s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw); s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw); s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear); s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw); bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw); void ixgbe_fc_autoneg(struct ixgbe_hw *hw); s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask); void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask); s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *, u32 *reg_val); s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq); s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw); s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed); s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan); s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix); s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs); void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf); void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy); void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw); s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver); u8 ixgbe_calculate_checksum(u8 *buffer, u32 length); s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, u32 length, u32 timeout, bool return_data); void ixgbe_clear_tx_pending(struct ixgbe_hw *hw); extern s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw); extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw); bool ixgbe_mng_present(struct ixgbe_hw *hw); bool ixgbe_mng_enabled(struct ixgbe_hw *hw); #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 #define IXGBE_EMC_INTERNAL_DATA 0x00 #define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20 #define IXGBE_EMC_DIODE1_DATA 0x01 #define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19 #define IXGBE_EMC_DIODE2_DATA 0x23 #define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A #define IXGBE_EMC_DIODE3_DATA 0x2A #define IXGBE_EMC_DIODE3_THERM_LIMIT 0x30 s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw); void ixgbe_disable_rx_generic(struct ixgbe_hw *hw); void ixgbe_enable_rx_generic(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed); #endif /* IXGBE_COMMON */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_dcb.h" #include "ixgbe_dcb_82598.h" #include "ixgbe_dcb_82599.h" /** * ixgbe_dcb_calculate_tc_credits - This calculates the ieee traffic class * credits from the configured bandwidth percentages. Credits * are the smallest unit programmable into the underlying * hardware. The IEEE 802.1Qaz specification do not use bandwidth * groups so this is much simplified from the CEE case. */ s32 ixgbe_dcb_calculate_tc_credits(u8 *bw, u16 *refill, u16 *max, int max_frame_size) { int min_percent = 100; int min_credit, multiplier; int i; min_credit = ((max_frame_size / 2) + IXGBE_DCB_CREDIT_QUANTUM - 1) / IXGBE_DCB_CREDIT_QUANTUM; for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if (bw[i] < min_percent && bw[i]) min_percent = bw[i]; } multiplier = (min_credit / min_percent) + 1; /* Find out the hw credits for each TC */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { int val = min(bw[i] * multiplier, IXGBE_DCB_MAX_CREDIT_REFILL); if (val < min_credit) val = min_credit; refill[i] = (u16)val; max[i] = bw[i] ? (bw[i]*IXGBE_DCB_MAX_CREDIT)/100 : min_credit; } return 0; } /** * ixgbe_dcb_calculate_tc_credits_cee - Calculates traffic class credits * @ixgbe_dcb_config: Struct containing DCB settings. * @direction: Configuring either Tx or Rx. * * This function calculates the credits allocated to each traffic class. * It should be called only after the rules are checked by * ixgbe_dcb_check_config_cee(). */ s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config, u32 max_frame_size, u8 direction) { struct ixgbe_dcb_tc_path *p; u32 min_multiplier = 0; u16 min_percent = 100; s32 ret_val = IXGBE_SUCCESS; /* Initialization values default for Tx settings */ u32 min_credit = 0; u32 credit_refill = 0; u32 credit_max = 0; u16 link_percentage = 0; u8 bw_percent = 0; u8 i; if (dcb_config == NULL) { ret_val = IXGBE_ERR_CONFIG; goto out; } min_credit = ((max_frame_size / 2) + IXGBE_DCB_CREDIT_QUANTUM - 1) / IXGBE_DCB_CREDIT_QUANTUM; /* Find smallest link percentage */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { p = &dcb_config->tc_config[i].path[direction]; bw_percent = dcb_config->bw_percentage[direction][p->bwg_id]; link_percentage = p->bwg_percent; link_percentage = (link_percentage * bw_percent) / 100; if (link_percentage && link_percentage < min_percent) min_percent = link_percentage; } /* * The ratio between traffic classes will control the bandwidth * percentages seen on the wire. To calculate this ratio we use * a multiplier. It is required that the refill credits must be * larger than the max frame size so here we find the smallest * multiplier that will allow all bandwidth percentages to be * greater than the max frame size. */ min_multiplier = (min_credit / min_percent) + 1; /* Find out the link percentage for each TC first */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { p = &dcb_config->tc_config[i].path[direction]; bw_percent = dcb_config->bw_percentage[direction][p->bwg_id]; link_percentage = p->bwg_percent; /* Must be careful of integer division for very small nums */ link_percentage = (link_percentage * bw_percent) / 100; if (p->bwg_percent > 0 && link_percentage == 0) link_percentage = 1; /* Save link_percentage for reference */ p->link_percent = (u8)link_percentage; /* Calculate credit refill ratio using multiplier */ credit_refill = min(link_percentage * min_multiplier, (u32)IXGBE_DCB_MAX_CREDIT_REFILL); p->data_credits_refill = (u16)credit_refill; /* Calculate maximum credit for the TC */ credit_max = (link_percentage * IXGBE_DCB_MAX_CREDIT) / 100; /* * Adjustment based on rule checking, if the percentage * of a TC is too small, the maximum credit may not be * enough to send out a jumbo frame in data plane arbitration. */ if (credit_max && (credit_max < min_credit)) credit_max = min_credit; if (direction == IXGBE_DCB_TX_CONFIG) { /* * Adjustment based on rule checking, if the * percentage of a TC is too small, the maximum * credit may not be enough to send out a TSO * packet in descriptor plane arbitration. */ if (credit_max && (credit_max < IXGBE_DCB_MIN_TSO_CREDIT) && (hw->mac.type == ixgbe_mac_82598EB)) credit_max = IXGBE_DCB_MIN_TSO_CREDIT; dcb_config->tc_config[i].desc_credits_max = (u16)credit_max; } p->data_credits_max = (u16)credit_max; } out: return ret_val; } /** * ixgbe_dcb_unpack_pfc_cee - Unpack dcb_config PFC info * @cfg: dcb configuration to unpack into hardware consumable fields * @map: user priority to traffic class map * @pfc_up: u8 to store user priority PFC bitmask * * This unpacks the dcb configuration PFC info which is stored per * traffic class into a 8bit user priority bitmask that can be * consumed by hardware routines. The priority to tc map must be * updated before calling this routine to use current up-to maps. */ void ixgbe_dcb_unpack_pfc_cee(struct ixgbe_dcb_config *cfg, u8 *map, u8 *pfc_up) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; int up; /* * If the TC for this user priority has PFC enabled then set the * matching bit in 'pfc_up' to reflect that PFC is enabled. */ for (*pfc_up = 0, up = 0; up < IXGBE_DCB_MAX_USER_PRIORITY; up++) { if (tc_config[map[up]].pfc != ixgbe_dcb_pfc_disabled) *pfc_up |= 1 << up; } } void ixgbe_dcb_unpack_refill_cee(struct ixgbe_dcb_config *cfg, int direction, u16 *refill) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; int tc; for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) refill[tc] = tc_config[tc].path[direction].data_credits_refill; } void ixgbe_dcb_unpack_max_cee(struct ixgbe_dcb_config *cfg, u16 *max) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; int tc; for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) max[tc] = tc_config[tc].desc_credits_max; } void ixgbe_dcb_unpack_bwgid_cee(struct ixgbe_dcb_config *cfg, int direction, u8 *bwgid) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; int tc; for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) bwgid[tc] = tc_config[tc].path[direction].bwg_id; } void ixgbe_dcb_unpack_tsa_cee(struct ixgbe_dcb_config *cfg, int direction, u8 *tsa) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; int tc; for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) tsa[tc] = tc_config[tc].path[direction].tsa; } u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *cfg, int direction, u8 up) { struct ixgbe_dcb_tc_config *tc_config = &cfg->tc_config[0]; u8 prio_mask = 1 << up; u8 tc = cfg->num_tcs.pg_tcs; /* If tc is 0 then DCB is likely not enabled or supported */ if (!tc) goto out; /* * Test from maximum TC to 1 and report the first match we find. If * we find no match we can assume that the TC is 0 since the TC must * be set for all user priorities */ for (tc--; tc; tc--) { if (prio_mask & tc_config[tc].path[direction].up_to_tc_bitmap) break; } out: return tc; } void ixgbe_dcb_unpack_map_cee(struct ixgbe_dcb_config *cfg, int direction, u8 *map) { u8 up; for (up = 0; up < IXGBE_DCB_MAX_USER_PRIORITY; up++) map[up] = ixgbe_dcb_get_tc_from_up(cfg, direction, up); } /** * ixgbe_dcb_config - Struct containing DCB settings. * @dcb_config: Pointer to DCB config structure * * This function checks DCB rules for DCB settings. * The following rules are checked: * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%. * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth * Group must total 100. * 3. A Traffic Class should not be set to both Link Strict Priority * and Group Strict Priority. * 4. Link strict Bandwidth Groups can only have link strict traffic classes * with zero bandwidth. */ s32 ixgbe_dcb_check_config_cee(struct ixgbe_dcb_config *dcb_config) { struct ixgbe_dcb_tc_path *p; s32 ret_val = IXGBE_SUCCESS; u8 i, j, bw = 0, bw_id; u8 bw_sum[2][IXGBE_DCB_MAX_BW_GROUP]; bool link_strict[2][IXGBE_DCB_MAX_BW_GROUP]; memset(bw_sum, 0, sizeof(bw_sum)); memset(link_strict, 0, sizeof(link_strict)); /* First Tx, then Rx */ for (i = 0; i < 2; i++) { /* Check each traffic class for rule violation */ for (j = 0; j < IXGBE_DCB_MAX_TRAFFIC_CLASS; j++) { p = &dcb_config->tc_config[j].path[i]; bw = p->bwg_percent; bw_id = p->bwg_id; if (bw_id >= IXGBE_DCB_MAX_BW_GROUP) { ret_val = IXGBE_ERR_CONFIG; goto err_config; } if (p->tsa == ixgbe_dcb_tsa_strict) { link_strict[i][bw_id] = true; /* Link strict should have zero bandwidth */ if (bw) { ret_val = IXGBE_ERR_CONFIG; goto err_config; } } else if (!bw) { /* * Traffic classes without link strict * should have non-zero bandwidth. */ ret_val = IXGBE_ERR_CONFIG; goto err_config; } bw_sum[i][bw_id] += bw; } bw = 0; /* Check each bandwidth group for rule violation */ for (j = 0; j < IXGBE_DCB_MAX_BW_GROUP; j++) { bw += dcb_config->bw_percentage[i][j]; /* * Sum of bandwidth percentages of all traffic classes * within a Bandwidth Group must total 100 except for * link strict group (zero bandwidth). */ if (link_strict[i][j]) { if (bw_sum[i][j]) { /* * Link strict group should have zero * bandwidth. */ ret_val = IXGBE_ERR_CONFIG; goto err_config; } } else if (bw_sum[i][j] != IXGBE_DCB_BW_PERCENT && bw_sum[i][j] != 0) { ret_val = IXGBE_ERR_CONFIG; goto err_config; } } if (bw != IXGBE_DCB_BW_PERCENT) { ret_val = IXGBE_ERR_CONFIG; goto err_config; } } err_config: DEBUGOUT2("DCB error code %d while checking %s settings.\n", ret_val, (i == IXGBE_DCB_TX_CONFIG) ? "Tx" : "Rx"); return ret_val; } /** * ixgbe_dcb_get_tc_stats - Returns status of each traffic class * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the status data for each of the Traffic Classes in use. */ s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { s32 ret = IXGBE_NOT_IMPLEMENTED; switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_get_tc_stats_82599(hw, stats, tc_count); break; default: break; } return ret; } /** * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the CBFC status data for each of the Traffic Classes. */ s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { s32 ret = IXGBE_NOT_IMPLEMENTED; switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_get_pfc_stats_82599(hw, stats, tc_count); break; default: break; } return ret; } /** * ixgbe_dcb_config_rx_arbiter_cee - Config Rx arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Rx Data Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = IXGBE_NOT_IMPLEMENTED; u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS] = { 0 }; u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS] = { 0 }; u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 }; u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS] = { 0 }; u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS] = { 0 }; ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa); ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map); switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwgid, tsa, map); break; default: break; } return ret; } /** * ixgbe_dcb_config_tx_desc_arbiter_cee - Config Tx Desc arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = IXGBE_NOT_IMPLEMENTED; u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS]; ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa); switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwgid, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, bwgid, tsa); break; default: break; } return ret; } /** * ixgbe_dcb_config_tx_data_arbiter_cee - Config Tx data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Data Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = IXGBE_NOT_IMPLEMENTED; u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 }; u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS]; ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa); ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map); switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwgid, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwgid, tsa, map); break; default: break; } return ret; } /** * ixgbe_dcb_config_pfc_cee - Config priority flow control * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Priority Flow Control for each traffic class. */ s32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = IXGBE_NOT_IMPLEMENTED; u8 pfc_en; u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 }; ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map); ixgbe_dcb_unpack_pfc_cee(dcb_config, map, &pfc_en); switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map); break; default: break; } return ret; } /** * ixgbe_dcb_config_tc_stats - Config traffic class statistics * @hw: pointer to hardware structure * * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw) { s32 ret = IXGBE_NOT_IMPLEMENTED; switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_tc_stats_82598(hw); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_tc_stats_82599(hw, NULL); break; default: break; } return ret; } /** * ixgbe_dcb_hw_config_cee - Config and enable DCB * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure dcb settings and enable dcb mode. */ s32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { s32 ret = IXGBE_NOT_IMPLEMENTED; u8 pfc_en; u8 tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u8 bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u8 map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 }; u16 refill[IXGBE_DCB_MAX_TRAFFIC_CLASS]; u16 max[IXGBE_DCB_MAX_TRAFFIC_CLASS]; /* Unpack CEE standard containers */ ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa); ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_TX_CONFIG, map); switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->link_speed, refill, max, bwgid, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ixgbe_dcb_config_82599(hw, dcb_config); ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->link_speed, refill, max, bwgid, tsa, map); ixgbe_dcb_config_tc_stats_82599(hw, dcb_config); break; default: break; } if (!ret && dcb_config->pfc_mode_enable) { ixgbe_dcb_unpack_pfc_cee(dcb_config, map, &pfc_en); ret = ixgbe_dcb_config_pfc(hw, pfc_en, map); } return ret; } /* Helper routines to abstract HW specifics from DCB netlink ops */ s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw, u8 pfc_en, u8 *map) { int ret = IXGBE_ERR_PARAM; switch (hw->mac.type) { case ixgbe_mac_82598EB: ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en, map); break; default: break; } return ret; } s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa, u8 *map) { switch (hw->mac.type) { case ixgbe_mac_82598EB: ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa); ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id, tsa); ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwg_id, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, tsa, map); ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, bwg_id, tsa); ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id, tsa, map); break; default: break; } return 0; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_DCB_H_ #define _IXGBE_DCB_H_ #include "ixgbe_type.h" /* DCB defines */ /* DCB credit calculation defines */ #define IXGBE_DCB_CREDIT_QUANTUM 64 #define IXGBE_DCB_MAX_CREDIT_REFILL 200 /* 200 * 64B = 12800B */ #define IXGBE_DCB_MAX_TSO_SIZE (32 * 1024) /* Max TSO pkt size in DCB*/ #define IXGBE_DCB_MAX_CREDIT (2 * IXGBE_DCB_MAX_CREDIT_REFILL) /* 513 for 32KB TSO packet */ #define IXGBE_DCB_MIN_TSO_CREDIT \ ((IXGBE_DCB_MAX_TSO_SIZE / IXGBE_DCB_CREDIT_QUANTUM) + 1) /* DCB configuration defines */ #define IXGBE_DCB_MAX_USER_PRIORITY 8 #define IXGBE_DCB_MAX_BW_GROUP 8 #define IXGBE_DCB_BW_PERCENT 100 #define IXGBE_DCB_TX_CONFIG 0 #define IXGBE_DCB_RX_CONFIG 1 /* DCB capability defines */ #define IXGBE_DCB_PG_SUPPORT 0x00000001 #define IXGBE_DCB_PFC_SUPPORT 0x00000002 #define IXGBE_DCB_BCN_SUPPORT 0x00000004 #define IXGBE_DCB_UP2TC_SUPPORT 0x00000008 #define IXGBE_DCB_GSP_SUPPORT 0x00000010 struct ixgbe_dcb_support { u32 capabilities; /* DCB capabilities */ /* Each bit represents a number of TCs configurable in the hw. * If 8 traffic classes can be configured, the value is 0x80. */ u8 traffic_classes; u8 pfc_traffic_classes; }; enum ixgbe_dcb_tsa { ixgbe_dcb_tsa_ets = 0, ixgbe_dcb_tsa_group_strict_cee, ixgbe_dcb_tsa_strict }; /* Traffic class bandwidth allocation per direction */ struct ixgbe_dcb_tc_path { u8 bwg_id; /* Bandwidth Group (BWG) ID */ u8 bwg_percent; /* % of BWG's bandwidth */ u8 link_percent; /* % of link bandwidth */ u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */ u16 data_credits_refill; /* Credit refill amount in 64B granularity */ u16 data_credits_max; /* Max credits for a configured packet buffer * in 64B granularity.*/ enum ixgbe_dcb_tsa tsa; /* Link or Group Strict Priority */ }; enum ixgbe_dcb_pfc { ixgbe_dcb_pfc_disabled = 0, ixgbe_dcb_pfc_enabled, ixgbe_dcb_pfc_enabled_txonly, ixgbe_dcb_pfc_enabled_rxonly }; /* Traffic class configuration */ struct ixgbe_dcb_tc_config { struct ixgbe_dcb_tc_path path[2]; /* One each for Tx/Rx */ enum ixgbe_dcb_pfc pfc; /* Class based flow control setting */ u16 desc_credits_max; /* For Tx Descriptor arbitration */ u8 tc; /* Traffic class (TC) */ }; enum ixgbe_dcb_pba { /* PBA[0-7] each use 64KB FIFO */ ixgbe_dcb_pba_equal = PBA_STRATEGY_EQUAL, /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ ixgbe_dcb_pba_80_48 = PBA_STRATEGY_WEIGHTED }; struct ixgbe_dcb_num_tcs { u8 pg_tcs; u8 pfc_tcs; }; struct ixgbe_dcb_config { struct ixgbe_dcb_tc_config tc_config[IXGBE_DCB_MAX_TRAFFIC_CLASS]; struct ixgbe_dcb_support support; struct ixgbe_dcb_num_tcs num_tcs; u8 bw_percentage[2][IXGBE_DCB_MAX_BW_GROUP]; /* One each for Tx/Rx */ bool pfc_mode_enable; bool round_robin_enable; enum ixgbe_dcb_pba rx_pba_cfg; u32 dcb_cfg_version; /* Not used...OS-specific? */ u32 link_speed; /* For bandwidth allocation validation purpose */ bool vt_mode; }; /* DCB driver APIs */ /* DCB rule checking */ s32 ixgbe_dcb_check_config_cee(struct ixgbe_dcb_config *); /* DCB credits calculation */ s32 ixgbe_dcb_calculate_tc_credits(u8 *, u16 *, u16 *, int); s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *, u32, u8); /* DCB PFC */ s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, u8, u8 *); s32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); /* DCB stats */ s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *); s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); /* DCB config arbiters */ s32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); /* DCB unpack routines */ void ixgbe_dcb_unpack_pfc_cee(struct ixgbe_dcb_config *, u8 *, u8 *); void ixgbe_dcb_unpack_refill_cee(struct ixgbe_dcb_config *, int, u16 *); void ixgbe_dcb_unpack_max_cee(struct ixgbe_dcb_config *, u16 *); void ixgbe_dcb_unpack_bwgid_cee(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_tsa_cee(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_map_cee(struct ixgbe_dcb_config *, int, u8 *); u8 ixgbe_dcb_get_tc_from_up(struct ixgbe_dcb_config *, int, u8); /* DCB initialization */ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *, u8 *); s32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); #endif /* _IXGBE_DCB_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb_82598.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_dcb.h" #include "ixgbe_dcb_82598.h" /** * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the status data for each of the Traffic Classes in use. */ s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { int tc; DEBUGFUNC("dcb_get_tc_stats"); if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS) return IXGBE_ERR_PARAM; /* Statistics pertaining to each traffic class */ for (tc = 0; tc < tc_count; tc++) { /* Transmitted Packets */ stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); /* Transmitted Bytes */ stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc)); /* Received Packets */ stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); /* Received Bytes */ stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc)); #if 0 /* Can we get rid of these?? Consequently, getting rid * of the tc_stats structure. */ tc_stats_array[up]->in_overflow_discards = 0; tc_stats_array[up]->out_overflow_discards = 0; #endif } return IXGBE_SUCCESS; } /** * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the CBFC status data for each of the Traffic Classes. */ s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { int tc; DEBUGFUNC("dcb_get_pfc_stats"); if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS) return IXGBE_ERR_PARAM; for (tc = 0; tc < tc_count; tc++) { /* Priority XOFF Transmitted */ stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc)); /* Priority XOFF Received */ stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc)); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Rx Data Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *tsa) { u32 reg = 0; u32 credit_refill = 0; u32 credit_max = 0; u8 i = 0; reg = IXGBE_READ_REG(hw, IXGBE_RUPPBMR) | IXGBE_RUPPBMR_MQA; IXGBE_WRITE_REG(hw, IXGBE_RUPPBMR, reg); reg = IXGBE_READ_REG(hw, IXGBE_RMCS); /* Enable Arbiter */ reg &= ~IXGBE_RMCS_ARBDIS; /* Enable Receive Recycle within the BWG */ reg |= IXGBE_RMCS_RRM; /* Enable Deficit Fixed Priority arbitration*/ reg |= IXGBE_RMCS_DFP; IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { credit_refill = refill[i]; credit_max = max[i]; reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT); if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_RT2CR_LSP; IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg); } reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); reg |= IXGBE_RDRXCTL_RDMTS_1_2; reg |= IXGBE_RDRXCTL_MPBEN; reg |= IXGBE_RDRXCTL_MCEN; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); reg = IXGBE_READ_REG(hw, IXGBE_RXCTRL); /* Make sure there is enough descriptors before arbitration */ reg &= ~IXGBE_RXCTRL_DMBYPS; IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa) { u32 reg, max_credits; u8 i; reg = IXGBE_READ_REG(hw, IXGBE_DPMCS); /* Enable arbiter */ reg &= ~IXGBE_DPMCS_ARBDIS; reg |= IXGBE_DPMCS_TSOEF; /* Configure Max TSO packet size 34KB including payload and headers */ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { max_credits = max[i]; reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT; reg |= refill[i]; reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee) reg |= IXGBE_TDTQ2TCCR_GSP; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_TDTQ2TCCR_LSP; IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Data Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa) { u32 reg; u8 i; reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS); /* Enable Data Plane Arbiter */ reg &= ~IXGBE_PDPMCS_ARBDIS; /* Enable DFP and Transmit Recycle Mode */ reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM); IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { reg = refill[i]; reg |= (u32)(max[i]) << IXGBE_TDPT2TCCR_MCL_SHIFT; reg |= (u32)(bwg_id[i]) << IXGBE_TDPT2TCCR_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee) reg |= IXGBE_TDPT2TCCR_GSP; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_TDPT2TCCR_LSP; IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg); } /* Enable Tx packet buffer division */ reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL); reg |= IXGBE_DTXCTL_ENDBUBD; IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_pfc_82598 - Config priority flow control * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Priority Flow Control for each traffic class. */ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en) { u32 fcrtl, reg; u8 i; /* Enable Transmit Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_RMCS); reg &= ~IXGBE_RMCS_TFCE_802_3X; reg |= IXGBE_RMCS_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg); /* Enable Receive Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); reg &= ~(IXGBE_FCTRL_RPFCE | IXGBE_FCTRL_RFCE); if (pfc_en) reg |= IXGBE_FCTRL_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg); /* Configure PFC Tx thresholds per TC */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if (!(pfc_en & (1 << i))) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0); continue; } fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg); } /* Configure pause time */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics * @hw: pointer to hardware structure * * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) { u32 reg = 0; u8 i = 0; u8 j = 0; /* Receive Queues stats setting - 8 queues per statistics reg */ for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) { reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i)); reg |= ((0x1010101) * j); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg); reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1)); reg |= ((0x1010101) * j); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg); } /* Transmit Queues stats setting - 4 queues per statistics reg*/ for (i = 0; i < 8; i++) { reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i)); reg |= ((0x1010101) * i); IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_hw_config_82598 - Config and enable DCB * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure dcb settings and enable dcb mode. */ s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw, int link_speed, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa) { UNREFERENCED_1PARAMETER(link_speed); ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa); ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id, tsa); ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwg_id, tsa); ixgbe_dcb_config_tc_stats_82598(hw); return IXGBE_SUCCESS; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb_82598.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_DCB_82598_H_ #define _IXGBE_DCB_82598_H_ /* DCB register definitions */ #define IXGBE_DPMCS_MTSOS_SHIFT 16 #define IXGBE_DPMCS_TDPAC 0x00000001 /* 0 Round Robin, * 1 DFP - Deficit Fixed Priority */ #define IXGBE_DPMCS_TRM 0x00000010 /* Transmit Recycle Mode */ #define IXGBE_DPMCS_ARBDIS 0x00000040 /* DCB arbiter disable */ #define IXGBE_DPMCS_TSOEF 0x00080000 /* TSO Expand Factor: 0=x4, 1=x2 */ #define IXGBE_RUPPBMR_MQA 0x80000000 /* Enable UP to queue mapping */ #define IXGBE_RT2CR_MCL_SHIFT 12 /* Offset to Max Credit Limit setting */ #define IXGBE_RT2CR_LSP 0x80000000 /* LSP enable bit */ #define IXGBE_RDRXCTL_MPBEN 0x00000010 /* DMA config for multiple packet * buffers enable */ #define IXGBE_RDRXCTL_MCEN 0x00000040 /* DMA config for multiple cores * (RSS) enable */ #define IXGBE_TDTQ2TCCR_MCL_SHIFT 12 #define IXGBE_TDTQ2TCCR_BWG_SHIFT 9 #define IXGBE_TDTQ2TCCR_GSP 0x40000000 #define IXGBE_TDTQ2TCCR_LSP 0x80000000 #define IXGBE_TDPT2TCCR_MCL_SHIFT 12 #define IXGBE_TDPT2TCCR_BWG_SHIFT 9 #define IXGBE_TDPT2TCCR_GSP 0x40000000 #define IXGBE_TDPT2TCCR_LSP 0x80000000 #define IXGBE_PDPMCS_TPPAC 0x00000020 /* 0 Round Robin, * 1 DFP - Deficit Fixed Priority */ #define IXGBE_PDPMCS_ARBDIS 0x00000040 /* Arbiter disable */ #define IXGBE_PDPMCS_TRM 0x00000100 /* Transmit Recycle Mode enable */ #define IXGBE_DTXCTL_ENDBUBD 0x00000004 /* Enable DBU buffer division */ #define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */ #define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */ #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ /* DCB driver APIs */ /* DCB PFC */ s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, u8); /* DCB stats */ s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *); s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); /* DCB config arbiters */ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *); s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *); s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *, u16 *, u16 *, u8 *); /* DCB initialization */ s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, int, u16 *, u16 *, u8 *, u8 *); #endif /* _IXGBE_DCB_82958_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb_82599.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_dcb.h" #include "ixgbe_dcb_82599.h" /** * ixgbe_dcb_get_tc_stats_82599 - Returns status for each traffic class * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the status data for each of the Traffic Classes in use. */ s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { int tc; DEBUGFUNC("dcb_get_tc_stats"); if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS) return IXGBE_ERR_PARAM; /* Statistics pertaining to each traffic class */ for (tc = 0; tc < tc_count; tc++) { /* Transmitted Packets */ stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); /* Transmitted Bytes (read low first to prevent missed carry) */ stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(tc)); stats->qbtc[tc] += (((u64)(IXGBE_READ_REG(hw, IXGBE_QBTC_H(tc)))) << 32); /* Received Packets */ stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); /* Received Bytes (read low first to prevent missed carry) */ stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(tc)); stats->qbrc[tc] += (((u64)(IXGBE_READ_REG(hw, IXGBE_QBRC_H(tc)))) << 32); /* Received Dropped Packet */ stats->qprdc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRDC(tc)); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_get_pfc_stats_82599 - Return CBFC status data * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the CBFC status data for each of the Traffic Classes. */ s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { int tc; DEBUGFUNC("dcb_get_pfc_stats"); if (tc_count > IXGBE_DCB_MAX_TRAFFIC_CLASS) return IXGBE_ERR_PARAM; for (tc = 0; tc < tc_count; tc++) { /* Priority XOFF Transmitted */ stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc)); /* Priority XOFF Received */ stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(tc)); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Rx Packet Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa, u8 *map) { u32 reg = 0; u32 credit_refill = 0; u32 credit_max = 0; u8 i = 0; /* * Disable the arbiter before changing parameters * (always enable recycle mode; WSP) */ reg = IXGBE_RTRPCS_RRM | IXGBE_RTRPCS_RAC | IXGBE_RTRPCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, reg); /* * map all UPs to TCs. up_to_tc_bitmap for each TC has corresponding * bits sets for the UPs that needs to be mappped to that TC. * e.g if priorities 6 and 7 are to be mapped to a TC then the * up_to_tc_bitmap value for that TC will be 11000000 in binary. */ reg = 0; for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) reg |= (map[i] << (i * IXGBE_RTRUP2TC_UP_SHIFT)); IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { credit_refill = refill[i]; credit_max = max[i]; reg = credit_refill | (credit_max << IXGBE_RTRPT4C_MCL_SHIFT); reg |= (u32)(bwg_id[i]) << IXGBE_RTRPT4C_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_RTRPT4C_LSP; IXGBE_WRITE_REG(hw, IXGBE_RTRPT4C(i), reg); } /* * Configure Rx packet plane (recycle mode; WSP) and * enable arbiter */ reg = IXGBE_RTRPCS_RRM | IXGBE_RTRPCS_RAC; IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tx_desc_arbiter_82599 - Config Tx Desc. arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa) { u32 reg, max_credits; u8 i; /* Clear the per-Tx queue credits; we use per-TC instead */ for (i = 0; i < 128; i++) { IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); IXGBE_WRITE_REG(hw, IXGBE_RTTDT1C, 0); } /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { max_credits = max[i]; reg = max_credits << IXGBE_RTTDT2C_MCL_SHIFT; reg |= refill[i]; reg |= (u32)(bwg_id[i]) << IXGBE_RTTDT2C_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee) reg |= IXGBE_RTTDT2C_GSP; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_RTTDT2C_LSP; IXGBE_WRITE_REG(hw, IXGBE_RTTDT2C(i), reg); } /* * Configure Tx descriptor plane (recycle mode; WSP) and * enable arbiter */ reg = IXGBE_RTTDCS_TDPAC | IXGBE_RTTDCS_TDRM; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tx_data_arbiter_82599 - Config Tx Data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Packet Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa, u8 *map) { u32 reg; u8 i; /* * Disable the arbiter before changing parameters * (always enable recycle mode; SP; arb delay) */ reg = IXGBE_RTTPCS_TPPAC | IXGBE_RTTPCS_TPRM | (IXGBE_RTTPCS_ARBD_DCB << IXGBE_RTTPCS_ARBD_SHIFT) | IXGBE_RTTPCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTPCS, reg); /* * map all UPs to TCs. up_to_tc_bitmap for each TC has corresponding * bits sets for the UPs that needs to be mappped to that TC. * e.g if priorities 6 and 7 are to be mapped to a TC then the * up_to_tc_bitmap value for that TC will be 11000000 in binary. */ reg = 0; for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) reg |= (map[i] << (i * IXGBE_RTTUP2TC_UP_SHIFT)); IXGBE_WRITE_REG(hw, IXGBE_RTTUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { reg = refill[i]; reg |= (u32)(max[i]) << IXGBE_RTTPT2C_MCL_SHIFT; reg |= (u32)(bwg_id[i]) << IXGBE_RTTPT2C_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee) reg |= IXGBE_RTTPT2C_GSP; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_RTTPT2C_LSP; IXGBE_WRITE_REG(hw, IXGBE_RTTPT2C(i), reg); } /* * Configure Tx packet plane (recycle mode; SP; arb delay) and * enable arbiter */ reg = IXGBE_RTTPCS_TPPAC | IXGBE_RTTPCS_TPRM | (IXGBE_RTTPCS_ARBD_DCB << IXGBE_RTTPCS_ARBD_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_RTTPCS, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @pfc_en: enabled pfc bitmask * @map: priority to tc assignments indexed by priority * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *map) { u32 i, j, fcrtl, reg; u8 max_tc = 0; /* Enable Transmit Priority Flow Control */ IXGBE_WRITE_REG(hw, IXGBE_FCCFG, IXGBE_FCCFG_TFCE_PRIORITY); /* Enable Receive Priority Flow Control */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg |= IXGBE_MFLCN_DPF; /* * X540 supports per TC Rx priority flow control. So * clear all TCs and only enable those that should be * enabled. */ reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); if (hw->mac.type >= ixgbe_mac_X540) reg |= pfc_en << IXGBE_MFLCN_RPFCE_SHIFT; if (pfc_en) reg |= IXGBE_MFLCN_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); for (i = 0; i < IXGBE_DCB_MAX_USER_PRIORITY; i++) { if (map[i] > max_tc) max_tc = map[i]; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i <= max_tc; i++) { int enabled = 0; for (j = 0; j < IXGBE_DCB_MAX_USER_PRIORITY; j++) { if ((map[j] == i) && (pfc_en & (1 << j))) { enabled = 1; break; } } if (enabled) { reg = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); } else { /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark * to the Rx packet buffer size - 24KB. This allows * the Tx switch to function even under heavy Rx * workloads. */ reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); } for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_tc_stats_82599 - Config traffic class statistics * @hw: pointer to hardware structure * * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { u32 reg = 0; u8 i = 0; u8 tc_count = 8; bool vt_mode = false; if (dcb_config != NULL) { tc_count = dcb_config->num_tcs.pg_tcs; vt_mode = dcb_config->vt_mode; } if (!((tc_count == 8 && vt_mode == false) || tc_count == 4)) return IXGBE_ERR_PARAM; if (tc_count == 8 && vt_mode == false) { /* * Receive Queues stats setting * 32 RQSMR registers, each configuring 4 queues. * * Set all 16 queues of each TC to the same stat * with TC 'n' going to stat 'n'. */ for (i = 0; i < 32; i++) { reg = 0x01010101 * (i / 4); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg); } /* * Transmit Queues stats setting * 32 TQSM registers, each controlling 4 queues. * * Set all queues of each TC to the same stat * with TC 'n' going to stat 'n'. * Tx queues are allocated non-uniformly to TCs: * 32, 32, 16, 16, 8, 8, 8, 8. */ for (i = 0; i < 32; i++) { if (i < 8) reg = 0x00000000; else if (i < 16) reg = 0x01010101; else if (i < 20) reg = 0x02020202; else if (i < 24) reg = 0x03030303; else if (i < 26) reg = 0x04040404; else if (i < 28) reg = 0x05050505; else if (i < 30) reg = 0x06060606; else reg = 0x07070707; IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), reg); } } else if (tc_count == 4 && vt_mode == false) { /* * Receive Queues stats setting * 32 RQSMR registers, each configuring 4 queues. * * Set all 16 queues of each TC to the same stat * with TC 'n' going to stat 'n'. */ for (i = 0; i < 32; i++) { if (i % 8 > 3) /* In 4 TC mode, odd 16-queue ranges are * not used. */ continue; reg = 0x01010101 * (i / 8); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg); } /* * Transmit Queues stats setting * 32 TQSM registers, each controlling 4 queues. * * Set all queues of each TC to the same stat * with TC 'n' going to stat 'n'. * Tx queues are allocated non-uniformly to TCs: * 64, 32, 16, 16. */ for (i = 0; i < 32; i++) { if (i < 16) reg = 0x00000000; else if (i < 24) reg = 0x01010101; else if (i < 28) reg = 0x02020202; else reg = 0x03030303; IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), reg); } } else if (tc_count == 4 && vt_mode == true) { /* * Receive Queues stats setting * 32 RQSMR registers, each configuring 4 queues. * * Queue Indexing in 32 VF with DCB mode maps 4 TC's to each * pool. Set all 32 queues of each TC across pools to the same * stat with TC 'n' going to stat 'n'. */ for (i = 0; i < 32; i++) IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), 0x03020100); /* * Transmit Queues stats setting * 32 TQSM registers, each controlling 4 queues. * * Queue Indexing in 32 VF with DCB mode maps 4 TC's to each * pool. Set all 32 queues of each TC across pools to the same * stat with TC 'n' going to stat 'n'. */ for (i = 0; i < 32; i++) IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), 0x03020100); } return IXGBE_SUCCESS; } /** * ixgbe_dcb_config_82599 - Configure general DCB parameters * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure general DCB parameters. */ s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { u32 reg; u32 q; /* Disable the Tx desc arbiter so that MTQC can be changed */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg |= IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); reg = IXGBE_READ_REG(hw, IXGBE_MRQC); if (dcb_config->num_tcs.pg_tcs == 8) { /* Enable DCB for Rx with 8 TCs */ switch (reg & IXGBE_MRQC_MRQE_MASK) { case 0: case IXGBE_MRQC_RT4TCEN: /* RSS disabled cases */ reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN; break; case IXGBE_MRQC_RSSEN: case IXGBE_MRQC_RTRSS4TCEN: /* RSS enabled cases */ reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RTRSS8TCEN; break; default: /* * Unsupported value, assume stale data, * overwrite no RSS */ ASSERT(0); reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN; } } if (dcb_config->num_tcs.pg_tcs == 4) { /* We support both VT-on and VT-off with 4 TCs. */ if (dcb_config->vt_mode) reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_VMDQRT4TCEN; else reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RTRSS4TCEN; } IXGBE_WRITE_REG(hw, IXGBE_MRQC, reg); /* Enable DCB for Tx with 8 TCs */ if (dcb_config->num_tcs.pg_tcs == 8) reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ; else { /* We support both VT-on and VT-off with 4 TCs. */ reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_4TC_4TQ; if (dcb_config->vt_mode) reg |= IXGBE_MTQC_VT_ENA; } IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg); /* Disable drop for all queues */ for (q = 0; q < 128; q++) IXGBE_WRITE_REG(hw, IXGBE_QDE, (IXGBE_QDE_WRITE | (q << IXGBE_QDE_IDX_SHIFT))); /* Enable the Tx desc arbiter */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg &= ~IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); /* Enable Security TX Buffer IFG for DCB */ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG); reg |= IXGBE_SECTX_DCB; IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg); return IXGBE_SUCCESS; } /** * ixgbe_dcb_hw_config_82599 - Configure and enable DCB * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure dcb settings and enable dcb mode. */ s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw, int link_speed, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa, u8 *map) { UNREFERENCED_1PARAMETER(link_speed); ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, tsa, map); ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, bwg_id, tsa); ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id, tsa, map); return IXGBE_SUCCESS; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_dcb_82599.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_DCB_82599_H_ #define _IXGBE_DCB_82599_H_ /* DCB register definitions */ #define IXGBE_RTTDCS_TDPAC 0x00000001 /* 0 Round Robin, * 1 WSP - Weighted Strict Priority */ #define IXGBE_RTTDCS_VMPAC 0x00000002 /* 0 Round Robin, * 1 WRR - Weighted Round Robin */ #define IXGBE_RTTDCS_TDRM 0x00000010 /* Transmit Recycle Mode */ #define IXGBE_RTTDCS_BDPM 0x00400000 /* Bypass Data Pipe - must clear! */ #define IXGBE_RTTDCS_BPBFSM 0x00800000 /* Bypass PB Free Space - must * clear! */ #define IXGBE_RTTDCS_SPEED_CHG 0x80000000 /* Link speed change */ /* Receive UP2TC mapping */ #define IXGBE_RTRUP2TC_UP_SHIFT 3 #define IXGBE_RTRUP2TC_UP_MASK 7 /* Transmit UP2TC mapping */ #define IXGBE_RTTUP2TC_UP_SHIFT 3 #define IXGBE_RTRPT4C_MCL_SHIFT 12 /* Offset to Max Credit Limit setting */ #define IXGBE_RTRPT4C_BWG_SHIFT 9 /* Offset to BWG index */ #define IXGBE_RTRPT4C_GSP 0x40000000 /* GSP enable bit */ #define IXGBE_RTRPT4C_LSP 0x80000000 /* LSP enable bit */ #define IXGBE_RDRXCTL_MPBEN 0x00000010 /* DMA config for multiple packet * buffers enable */ #define IXGBE_RDRXCTL_MCEN 0x00000040 /* DMA config for multiple cores * (RSS) enable */ /* RTRPCS Bit Masks */ #define IXGBE_RTRPCS_RRM 0x00000002 /* Receive Recycle Mode enable */ /* Receive Arbitration Control: 0 Round Robin, 1 DFP */ #define IXGBE_RTRPCS_RAC 0x00000004 #define IXGBE_RTRPCS_ARBDIS 0x00000040 /* Arbitration disable bit */ /* RTTDT2C Bit Masks */ #define IXGBE_RTTDT2C_MCL_SHIFT 12 #define IXGBE_RTTDT2C_BWG_SHIFT 9 #define IXGBE_RTTDT2C_GSP 0x40000000 #define IXGBE_RTTDT2C_LSP 0x80000000 #define IXGBE_RTTPT2C_MCL_SHIFT 12 #define IXGBE_RTTPT2C_BWG_SHIFT 9 #define IXGBE_RTTPT2C_GSP 0x40000000 #define IXGBE_RTTPT2C_LSP 0x80000000 /* RTTPCS Bit Masks */ #define IXGBE_RTTPCS_TPPAC 0x00000020 /* 0 Round Robin, * 1 SP - Strict Priority */ #define IXGBE_RTTPCS_ARBDIS 0x00000040 /* Arbiter disable */ #define IXGBE_RTTPCS_TPRM 0x00000100 /* Transmit Recycle Mode enable */ #define IXGBE_RTTPCS_ARBD_SHIFT 22 #define IXGBE_RTTPCS_ARBD_DCB 0x4 /* Arbitration delay in DCB mode */ #define IXGBE_TXPBTHRESH_DCB 0xA /* THRESH value for DCB mode */ /* SECTXMINIFG DCB */ #define IXGBE_SECTX_DCB 0x00001F00 /* DCB TX Buffer SEC IFG */ /* BCN register definitions */ #define IXGBE_RTTBCNRC_RF_INT_SHIFT 14 #define IXGBE_RTTBCNRC_RS_ENA 0x80000000 #define IXGBE_RTTBCNCR_MNG_CMTGI 0x00000001 #define IXGBE_RTTBCNCR_MGN_BCNA_MODE 0x00000002 #define IXGBE_RTTBCNCR_RSV7_11_SHIFT 5 #define IXGBE_RTTBCNCR_G 0x00000400 #define IXGBE_RTTBCNCR_I 0x00000800 #define IXGBE_RTTBCNCR_H 0x00001000 #define IXGBE_RTTBCNCR_VER_SHIFT 14 #define IXGBE_RTTBCNCR_CMT_ETH_SHIFT 16 #define IXGBE_RTTBCNACL_SMAC_L_SHIFT 16 #define IXGBE_RTTBCNTG_BCNA_MODE 0x80000000 #define IXGBE_RTTBCNRTT_TS_SHIFT 3 #define IXGBE_RTTBCNRTT_TXQ_IDX_SHIFT 16 #define IXGBE_RTTBCNRD_BCN_CLEAR_ALL 0x00000002 #define IXGBE_RTTBCNRD_DRIFT_FAC_SHIFT 2 #define IXGBE_RTTBCNRD_DRIFT_INT_SHIFT 16 #define IXGBE_RTTBCNRD_DRIFT_ENA 0x80000000 /* DCB driver APIs */ /* DCB PFC */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *, u8, u8 *); /* DCB stats */ s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); s32 ixgbe_dcb_get_pfc_stats_82599(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); /* DCB config arbiters */ s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *); s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *, u8 *); s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *, u8 *); /* DCB initialization */ s32 ixgbe_dcb_config_82599(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *, int, u16 *, u16 *, u8 *, u8 *, u8 *); #endif /* _IXGBE_DCB_82959_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_mbx.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_mbx.h" /** * ixgbe_read_mbx - Reads a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to read * * returns SUCCESS if it successfully read message from buffer **/ s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_read_mbx"); /* limit read to size of mailbox */ if (size > mbx->size) size = mbx->size; if (mbx->ops.read) ret_val = mbx->ops.read(hw, msg, size, mbx_id); return ret_val; } /** * ixgbe_write_mbx - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer **/ s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_write_mbx"); if (size > mbx->size) { ret_val = IXGBE_ERR_MBX; ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, "Invalid mailbox message size %d", size); } else if (mbx->ops.write) ret_val = mbx->ops.write(hw, msg, size, mbx_id); return ret_val; } /** * ixgbe_check_for_msg - checks to see if someone sent us mail * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_check_for_msg"); if (mbx->ops.check_for_msg) ret_val = mbx->ops.check_for_msg(hw, mbx_id); return ret_val; } /** * ixgbe_check_for_ack - checks to see if someone sent us ACK * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_check_for_ack"); if (mbx->ops.check_for_ack) ret_val = mbx->ops.check_for_ack(hw, mbx_id); return ret_val; } /** * ixgbe_check_for_rst - checks to see if other side has reset * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_check_for_rst"); if (mbx->ops.check_for_rst) ret_val = mbx->ops.check_for_rst(hw, mbx_id); return ret_val; } /** * ixgbe_poll_for_msg - Wait for message notification * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification **/ STATIC s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("ixgbe_poll_for_msg"); if (!countdown || !mbx->ops.check_for_msg) goto out; while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } if (countdown == 0) ERROR_REPORT2(IXGBE_ERROR_POLLING, "Polling for VF%d mailbox message timedout", mbx_id); out: return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; } /** * ixgbe_poll_for_ack - Wait for message acknowledgement * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message acknowledgement **/ STATIC s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("ixgbe_poll_for_ack"); if (!countdown || !mbx->ops.check_for_ack) goto out; while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } if (countdown == 0) ERROR_REPORT2(IXGBE_ERROR_POLLING, "Polling for VF%d mailbox ack timedout", mbx_id); out: return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; } /** * ixgbe_read_posted_mbx - Wait for message notification and receive message * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification and * copied it into the receive buffer. **/ s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_read_posted_mbx"); if (!mbx->ops.read) goto out; ret_val = ixgbe_poll_for_msg(hw, mbx_id); /* if ack received read message, otherwise we timed out */ if (!ret_val) ret_val = mbx->ops.read(hw, msg, size, mbx_id); out: return ret_val; } /** * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer and * received an ack to that message within delay * timeout period **/ s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct ixgbe_mbx_info *mbx = &hw->mbx; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_write_posted_mbx"); /* exit if either we can't write or there isn't a defined timeout */ if (!mbx->ops.write || !mbx->timeout) goto out; /* send msg */ ret_val = mbx->ops.write(hw, msg, size, mbx_id); /* if msg sent wait until we receive an ack */ if (!ret_val) ret_val = ixgbe_poll_for_ack(hw, mbx_id); out: return ret_val; } /** * ixgbe_init_mbx_ops_generic - Initialize MB function pointers * @hw: pointer to the HW structure * * Setups up the mailbox read and write message function pointers **/ void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; mbx->ops.read_posted = ixgbe_read_posted_mbx; mbx->ops.write_posted = ixgbe_write_posted_mbx; } /** * ixgbe_read_v2p_mailbox - read v2p mailbox * @hw: pointer to the HW structure * * This function is used to read the v2p mailbox without losing the read to * clear status bits. **/ STATIC u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw) { u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); v2p_mailbox |= hw->mbx.v2p_mailbox; hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; return v2p_mailbox; } /** * ixgbe_check_for_bit_vf - Determine if a status bit was set * @hw: pointer to the HW structure * @mask: bitmask for bits to be tested and cleared * * This function is used to check for the read to clear bits within * the V2P mailbox. **/ STATIC s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) { u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw); s32 ret_val = IXGBE_ERR_MBX; if (v2p_mailbox & mask) ret_val = IXGBE_SUCCESS; hw->mbx.v2p_mailbox &= ~mask; return ret_val; } /** * ixgbe_check_for_msg_vf - checks to see if the PF has sent mail * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the PF has set the Status bit or else ERR_MBX **/ STATIC s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id) { s32 ret_val = IXGBE_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_msg_vf"); if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { ret_val = IXGBE_SUCCESS; hw->mbx.stats.reqs++; } return ret_val; } /** * ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX **/ STATIC s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id) { s32 ret_val = IXGBE_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_ack_vf"); if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { ret_val = IXGBE_SUCCESS; hw->mbx.stats.acks++; } return ret_val; } /** * ixgbe_check_for_rst_vf - checks to see if the PF has reset * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns true if the PF has set the reset done bit or else false **/ STATIC s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id) { s32 ret_val = IXGBE_ERR_MBX; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_check_for_rst_vf"); if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | IXGBE_VFMAILBOX_RSTI))) { ret_val = IXGBE_SUCCESS; hw->mbx.stats.rsts++; } return ret_val; } /** * ixgbe_obtain_mbx_lock_vf - obtain mailbox lock * @hw: pointer to the HW structure * * return SUCCESS if we obtained the mailbox lock **/ STATIC s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_obtain_mbx_lock_vf"); /* Take ownership of the buffer */ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); /* reserve mailbox for vf use */ if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) ret_val = IXGBE_SUCCESS; return ret_val; } /** * ixgbe_write_mbx_vf - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer **/ STATIC s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { s32 ret_val; u16 i; UNREFERENCED_1PARAMETER(mbx_id); DEBUGFUNC("ixgbe_write_mbx_vf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_vf(hw); if (ret_val) goto out_no_write; /* flush msg and acks as we are overwriting the message buffer */ ixgbe_check_for_msg_vf(hw, 0); ixgbe_check_for_ack_vf(hw, 0); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); /* * Complete the remaining mailbox data registers with zero to reset * the data sent in a previous exchange (in either side) with the PF, * including exchanges performed by another Guest OS to which that VF * was previously assigned. */ while (i < hw->mbx.size) { IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, 0); i++; } /* update stats */ hw->mbx.stats.msgs_tx++; /* Drop VFU and interrupt the PF to tell it a message has been sent */ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); out_no_write: return ret_val; } /** * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to read * * returns SUCCESS if it successfully read message from buffer **/ STATIC s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { s32 ret_val = IXGBE_SUCCESS; u16 i; DEBUGFUNC("ixgbe_read_mbx_vf"); UNREFERENCED_1PARAMETER(mbx_id); /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_vf(hw); if (ret_val) goto out_no_read; /* copy the message from the mailbox memory buffer */ for (i = 0; i < size; i++) msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); /* Acknowledge receipt and release mailbox, then we're done */ IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); /* update stats */ hw->mbx.stats.msgs_rx++; out_no_read: return ret_val; } /** * ixgbe_init_mbx_params_vf - set initial values for vf mailbox * @hw: pointer to the HW structure * * Initializes the hw->mbx struct to correct values for vf mailbox */ void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; /* start mailbox as timed out and let the reset_hw call set the timeout * value to begin communications */ mbx->timeout = 0; mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; mbx->size = IXGBE_VFMAILBOX_SIZE; mbx->ops.read = ixgbe_read_mbx_vf; mbx->ops.write = ixgbe_write_mbx_vf; mbx->ops.read_posted = ixgbe_read_posted_mbx; mbx->ops.write_posted = ixgbe_write_posted_mbx; mbx->ops.check_for_msg = ixgbe_check_for_msg_vf; mbx->ops.check_for_ack = ixgbe_check_for_ack_vf; mbx->ops.check_for_rst = ixgbe_check_for_rst_vf; mbx->stats.msgs_tx = 0; mbx->stats.msgs_rx = 0; mbx->stats.reqs = 0; mbx->stats.acks = 0; mbx->stats.rsts = 0; } STATIC s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) { u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); s32 ret_val = IXGBE_ERR_MBX; if (mbvficr & mask) { ret_val = IXGBE_SUCCESS; IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); } return ret_val; } /** * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) { s32 ret_val = IXGBE_ERR_MBX; s32 index = IXGBE_MBVFICR_INDEX(vf_number); u32 vf_bit = vf_number % 16; DEBUGFUNC("ixgbe_check_for_msg_pf"); if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, index)) { ret_val = IXGBE_SUCCESS; hw->mbx.stats.reqs++; } return ret_val; } /** * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) { s32 ret_val = IXGBE_ERR_MBX; s32 index = IXGBE_MBVFICR_INDEX(vf_number); u32 vf_bit = vf_number % 16; DEBUGFUNC("ixgbe_check_for_ack_pf"); if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, index)) { ret_val = IXGBE_SUCCESS; hw->mbx.stats.acks++; } return ret_val; } /** * ixgbe_check_for_rst_pf - checks to see if the VF has reset * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ STATIC s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) { u32 reg_offset = (vf_number < 32) ? 0 : 1; u32 vf_shift = vf_number % 32; u32 vflre = 0; s32 ret_val = IXGBE_ERR_MBX; DEBUGFUNC("ixgbe_check_for_rst_pf"); switch (hw->mac.type) { case ixgbe_mac_82599EB: vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: case ixgbe_mac_X540: vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); break; default: break; } if (vflre & (1 << vf_shift)) { ret_val = IXGBE_SUCCESS; IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); hw->mbx.stats.rsts++; } return ret_val; } /** * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ STATIC s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) { s32 ret_val = IXGBE_ERR_MBX; u32 p2v_mailbox; DEBUGFUNC("ixgbe_obtain_mbx_lock_pf"); /* Take ownership of the buffer */ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) ret_val = IXGBE_SUCCESS; else ERROR_REPORT2(IXGBE_ERROR_POLLING, "Failed to obtain mailbox lock for VF%d", vf_number); return ret_val; } /** * ixgbe_write_mbx_pf - Places a message in the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * returns SUCCESS if it successfully copied message into the buffer **/ STATIC s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("ixgbe_write_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_write; /* flush msg and acks as we are overwriting the message buffer */ ixgbe_check_for_msg_pf(hw, vf_number); ixgbe_check_for_ack_pf(hw, vf_number); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); /* * Complete the remaining mailbox data registers with zero to reset * the data sent in a previous exchange (in either side) with the VF, * including exchanges performed by another Guest OS to which that VF * was previously assigned. */ while (i < hw->mbx.size) { IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, 0); i++; } /* Interrupt VF to tell it a message has been sent and release buffer*/ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); /* update stats */ hw->mbx.stats.msgs_tx++; out_no_write: return ret_val; } /** * ixgbe_read_mbx_pf - Read a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * This function copies a message from the mailbox buffer to the caller's * memory buffer. The presumption is that the caller knows that there was * a message due to a VF request so no polling for message is needed. **/ STATIC s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("ixgbe_read_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_read; /* copy the message to the mailbox memory buffer */ for (i = 0; i < size; i++) msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); /* Acknowledge the message and release buffer */ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); /* update stats */ hw->mbx.stats.msgs_rx++; out_no_read: return ret_val; } /** * ixgbe_init_mbx_params_pf - set initial values for pf mailbox * @hw: pointer to the HW structure * * Initializes the hw->mbx struct to correct values for pf mailbox */ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; if (hw->mac.type != ixgbe_mac_82599EB && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x && hw->mac.type != ixgbe_mac_X540) return; mbx->timeout = 0; mbx->usec_delay = 0; mbx->size = IXGBE_VFMAILBOX_SIZE; mbx->ops.read = ixgbe_read_mbx_pf; mbx->ops.write = ixgbe_write_mbx_pf; mbx->ops.read_posted = ixgbe_read_posted_mbx; mbx->ops.write_posted = ixgbe_write_posted_mbx; mbx->ops.check_for_msg = ixgbe_check_for_msg_pf; mbx->ops.check_for_ack = ixgbe_check_for_ack_pf; mbx->ops.check_for_rst = ixgbe_check_for_rst_pf; mbx->stats.msgs_tx = 0; mbx->stats.msgs_rx = 0; mbx->stats.reqs = 0; mbx->stats.acks = 0; mbx->stats.rsts = 0; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_mbx.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_MBX_H_ #define _IXGBE_MBX_H_ #include "ixgbe_type.h" #define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ #define IXGBE_ERR_MBX -100 #define IXGBE_VFMAILBOX 0x002FC #define IXGBE_VFMBMEM 0x00200 /* Define mailbox register bits */ #define IXGBE_VFMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ #define IXGBE_VFMAILBOX_ACK 0x00000002 /* Ack PF message received */ #define IXGBE_VFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define IXGBE_VFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define IXGBE_VFMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ #define IXGBE_VFMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ #define IXGBE_VFMAILBOX_RSTI 0x00000040 /* PF has reset indication */ #define IXGBE_VFMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */ #define IXGBE_VFMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */ #define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */ #define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ #define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ #define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ #define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ #define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ #define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ /* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the * PF. The reverse is true if it is IXGBE_PF_*. * Message ACK's are the value or'd with 0xF0000000 */ #define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with * this are the ACK */ #define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with * this are the NACK */ #define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still * clear to send requests */ #define IXGBE_VT_MSGINFO_SHIFT 16 /* bits 23:16 are used for extra info for certain messages */ #define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) /* definitions to support mailbox API version negotiation */ /* * each element denotes a version of the API; existing numbers may not * change; any additions must go at the end */ enum ixgbe_pfvf_api_rev { ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */ ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */ ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */ /* This value should always be last */ ixgbe_mbox_api_unknown, /* indicates that API version is not known */ }; /* mailbox API, legacy requests */ #define IXGBE_VF_RESET 0x01 /* VF requests reset */ #define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ /* mailbox API, version 1.0 VF requests */ #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ #define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ #define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */ /* mailbox API, version 1.1 VF requests */ #define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */ /* GET_QUEUES return data indices within the mailbox */ #define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */ #define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */ #define IXGBE_VF_TRANS_VLAN 3 /* Indication of port vlan */ #define IXGBE_VF_DEF_QUEUE 4 /* Default queue offset */ /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 /* word in permanent address message with the current multicast type */ #define IXGBE_VF_MC_TYPE_WORD 3 #define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */ /* mailbox API, version 2.0 VF requests */ #define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */ #define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */ #define IXGBE_VF_ENABLE_MACADDR 0x0A /* enable MAC address */ #define IXGBE_VF_DISABLE_MACADDR 0x0B /* disable MAC address */ #define IXGBE_VF_GET_MACADDRS 0x0C /* get all configured MAC addrs */ #define IXGBE_VF_SET_MCAST_PROMISC 0x0D /* enable multicast promiscuous */ #define IXGBE_VF_GET_MTU 0x0E /* get bounds on MTU */ #define IXGBE_VF_SET_MTU 0x0F /* set a specific MTU */ /* mailbox API, version 2.0 PF requests */ #define IXGBE_PF_TRANSPARENT_VLAN 0x0101 /* enable transparent vlan */ #define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16); s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); void ixgbe_init_mbx_params_vf(struct ixgbe_hw *); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); #endif /* _IXGBE_MBX_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_osdep.h ================================================ /****************************************************************************** Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ /*$FreeBSD$*/ #ifndef _IXGBE_OS_H_ #define _IXGBE_OS_H_ #include #include #include #include #include #include #include #include #include #include "../ixgbe_logs.h" #include "../ixgbe_bypass_defines.h" #define ASSERT(x) if(!(x)) rte_panic("IXGBE: x") #define DELAY(x) rte_delay_us(x) #define usec_delay(x) DELAY(x) #define msec_delay(x) DELAY(1000*(x)) #define DEBUGFUNC(F) DEBUGOUT(F "\n"); #define DEBUGOUT(S, args...) PMD_DRV_LOG_RAW(DEBUG, S, ##args) #define DEBUGOUT1(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT2(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT3(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT6(S, args...) DEBUGOUT(S, ##args) #define DEBUGOUT7(S, args...) DEBUGOUT(S, ##args) #define ERROR_REPORT1(e, S, args...) DEBUGOUT(S, ##args) #define ERROR_REPORT2(e, S, args...) DEBUGOUT(S, ##args) #define ERROR_REPORT3(e, S, args...) DEBUGOUT(S, ##args) #define FALSE 0 #define TRUE 1 #define false 0 #define true 1 #define min(a,b) RTE_MIN(a,b) #define EWARN(hw, S, args...) DEBUGOUT1(S, ##args) /* Bunch of defines for shared code bogosity */ #define UNREFERENCED_PARAMETER(_p) #define UNREFERENCED_1PARAMETER(_p) #define UNREFERENCED_2PARAMETER(_p, _q) #define UNREFERENCED_3PARAMETER(_p, _q, _r) #define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) /* Shared code error reporting */ enum { IXGBE_ERROR_SOFTWARE, IXGBE_ERROR_POLLING, IXGBE_ERROR_INVALID_STATE, IXGBE_ERROR_UNSUPPORTED, IXGBE_ERROR_ARGUMENT, IXGBE_ERROR_CAUTION, }; #define STATIC static #define IXGBE_NTOHL(_i) rte_be_to_cpu_32(_i) #define IXGBE_NTOHS(_i) rte_be_to_cpu_16(_i) #define IXGBE_CPU_TO_LE32(_i) rte_cpu_to_le_32(_i) #define IXGBE_LE32_TO_CPUS(_i) rte_le_to_cpu_32(_i) #define IXGBE_CPU_TO_BE16(_i) rte_cpu_to_be_16(_i) #define IXGBE_CPU_TO_BE32(_i) rte_cpu_to_be_32(_i) typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef int16_t s16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; typedef int bool; #define mb() rte_mb() #define wmb() rte_wmb() #define rmb() rte_rmb() #define IOMEM #define prefetch(x) rte_prefetch0(x) #define IXGBE_PCI_REG(reg) (*((volatile uint32_t *)(reg))) static inline uint32_t ixgbe_read_addr(volatile void* addr) { return rte_le_to_cpu_32(IXGBE_PCI_REG(addr)); } #define IXGBE_PCI_REG_WRITE(reg, value) do { \ IXGBE_PCI_REG((reg)) = (rte_cpu_to_le_32(value)); \ } while(0) #define IXGBE_PCI_REG_ADDR(hw, reg) \ ((volatile uint32_t *)((char *)(hw)->hw_addr + (reg))) #define IXGBE_PCI_REG_ARRAY_ADDR(hw, reg, index) \ IXGBE_PCI_REG_ADDR((hw), (reg) + ((index) << 2)) /* Not implemented !! */ #define IXGBE_READ_PCIE_WORD(hw, reg) 0 #define IXGBE_WRITE_PCIE_WORD(hw, reg, value) do { } while(0) #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS) #define IXGBE_READ_REG(hw, reg) \ ixgbe_read_addr(IXGBE_PCI_REG_ADDR((hw), (reg))) #define IXGBE_WRITE_REG(hw, reg, value) \ IXGBE_PCI_REG_WRITE(IXGBE_PCI_REG_ADDR((hw), (reg)), (value)) #define IXGBE_READ_REG_ARRAY(hw, reg, index) \ IXGBE_PCI_REG(IXGBE_PCI_REG_ARRAY_ADDR((hw), (reg), (index))) #define IXGBE_WRITE_REG_ARRAY(hw, reg, index, value) \ IXGBE_PCI_REG_WRITE(IXGBE_PCI_REG_ARRAY_ADDR((hw), (reg), (index)), (value)) #endif /* _IXGBE_OS_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_phy.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" STATIC void ixgbe_i2c_start(struct ixgbe_hw *hw); STATIC void ixgbe_i2c_stop(struct ixgbe_hw *hw); STATIC s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data); STATIC s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data); STATIC s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw); STATIC s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data); STATIC s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data); STATIC void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); STATIC void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); STATIC s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); STATIC bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl); STATIC s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); /** * ixgbe_out_i2c_byte_ack - Send I2C byte with ack * @hw: pointer to the hardware structure * @byte: byte to send * * Returns an error code on error. */ STATIC s32 ixgbe_out_i2c_byte_ack(struct ixgbe_hw *hw, u8 byte) { s32 status; status = ixgbe_clock_out_i2c_byte(hw, byte); if (status) return status; return ixgbe_get_i2c_ack(hw); } /** * ixgbe_in_i2c_byte_ack - Receive an I2C byte and send ack * @hw: pointer to the hardware structure * @byte: pointer to a u8 to receive the byte * * Returns an error code on error. */ STATIC s32 ixgbe_in_i2c_byte_ack(struct ixgbe_hw *hw, u8 *byte) { s32 status; status = ixgbe_clock_in_i2c_byte(hw, byte); if (status) return status; /* ACK */ return ixgbe_clock_out_i2c_bit(hw, false); } /** * ixgbe_ones_comp_byte_add - Perform one's complement addition * @add1 - addend 1 * @add2 - addend 2 * * Returns one's complement 8-bit sum. */ STATIC u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2) { u16 sum = add1 + add2; sum = (sum & 0xFF) + (sum >> 8); return sum & 0xFF; } /** * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * @lock: true if to take and release semaphore * * Returns an error code on error. */ STATIC s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 10; int retry = 0; u8 csum_byte; u8 high_bits; u8 low_bits; u8 reg_high; u8 csum; if (hw->mac.type >= ixgbe_mac_X550) max_retry = 3; reg_high = ((reg >> 7) & 0xFE) | 1; /* Indicate read combined */ csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF); csum = ~csum; do { if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ if (ixgbe_out_i2c_byte_ack(hw, addr)) goto fail; /* Write bits 14:8 */ if (ixgbe_out_i2c_byte_ack(hw, reg_high)) goto fail; /* Write bits 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF)) goto fail; /* Write csum */ if (ixgbe_out_i2c_byte_ack(hw, csum)) goto fail; /* Re-start condition */ ixgbe_i2c_start(hw); /* Device Address and read indication */ if (ixgbe_out_i2c_byte_ack(hw, addr | 1)) goto fail; /* Get upper bits */ if (ixgbe_in_i2c_byte_ack(hw, &high_bits)) goto fail; /* Get low bits */ if (ixgbe_in_i2c_byte_ack(hw, &low_bits)) goto fail; /* Get csum */ if (ixgbe_clock_in_i2c_byte(hw, &csum_byte)) goto fail; /* NACK */ if (ixgbe_clock_out_i2c_bit(hw, false)) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); *val = (high_bits << 8) | low_bits; return 0; fail: ixgbe_i2c_bus_clear(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) DEBUGOUT("I2C byte read combined error - Retrying.\n"); else DEBUGOUT("I2C byte read combined error.\n"); } while (retry < max_retry); return IXGBE_ERR_I2C; } /** * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * * Returns an error code on error. **/ STATIC s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val) { return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); } /** * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value * * Returns an error code on error. **/ STATIC s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val) { return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); } /** * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * @lock: true if to take and release semaphore * * Returns an error code on error. */ STATIC s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 1; int retry = 0; u8 reg_high; u8 csum; reg_high = (reg >> 7) & 0xFE; /* Indicate write combined */ csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF); csum = ixgbe_ones_comp_byte_add(csum, val >> 8); csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF); csum = ~csum; do { if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ if (ixgbe_out_i2c_byte_ack(hw, addr)) goto fail; /* Write bits 14:8 */ if (ixgbe_out_i2c_byte_ack(hw, reg_high)) goto fail; /* Write bits 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, reg & 0xFF)) goto fail; /* Write data 15:8 */ if (ixgbe_out_i2c_byte_ack(hw, val >> 8)) goto fail; /* Write data 7:0 */ if (ixgbe_out_i2c_byte_ack(hw, val & 0xFF)) goto fail; /* Write csum */ if (ixgbe_out_i2c_byte_ack(hw, csum)) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); return 0; fail: ixgbe_i2c_bus_clear(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) DEBUGOUT("I2C byte write combined error - Retrying.\n"); else DEBUGOUT("I2C byte write combined error.\n"); } while (retry < max_retry); return IXGBE_ERR_I2C; } /** * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * * Returns an error code on error. **/ STATIC s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val) { return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); } /** * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write * * Returns an error code on error. **/ STATIC s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val) { return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); } /** * ixgbe_init_phy_ops_generic - Inits PHY function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; DEBUGFUNC("ixgbe_init_phy_ops_generic"); /* PHY */ phy->ops.identify = ixgbe_identify_phy_generic; phy->ops.reset = ixgbe_reset_phy_generic; phy->ops.read_reg = ixgbe_read_phy_reg_generic; phy->ops.write_reg = ixgbe_write_phy_reg_generic; phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi; phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi; phy->ops.setup_link = ixgbe_setup_phy_link_generic; phy->ops.setup_link_speed = ixgbe_setup_phy_link_speed_generic; phy->ops.check_link = NULL; phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic; phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_generic; phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_generic; phy->ops.read_i2c_sff8472 = ixgbe_read_i2c_sff8472_generic; phy->ops.read_i2c_eeprom = ixgbe_read_i2c_eeprom_generic; phy->ops.write_i2c_eeprom = ixgbe_write_i2c_eeprom_generic; phy->ops.i2c_bus_clear = ixgbe_i2c_bus_clear; phy->ops.identify_sfp = ixgbe_identify_module_generic; phy->sfp_type = ixgbe_sfp_type_unknown; phy->ops.read_i2c_combined = ixgbe_read_i2c_combined_generic; phy->ops.write_i2c_combined = ixgbe_write_i2c_combined_generic; phy->ops.read_i2c_combined_unlocked = ixgbe_read_i2c_combined_generic_unlocked; phy->ops.write_i2c_combined_unlocked = ixgbe_write_i2c_combined_generic_unlocked; phy->ops.read_i2c_byte_unlocked = ixgbe_read_i2c_byte_generic_unlocked; phy->ops.write_i2c_byte_unlocked = ixgbe_write_i2c_byte_generic_unlocked; phy->ops.check_overtemp = ixgbe_tn_check_overtemp; return IXGBE_SUCCESS; } /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 phy_addr; u16 ext_ability = 0; DEBUGFUNC("ixgbe_identify_phy_generic"); if (!hw->phy.phy_semaphore_mask) { if (hw->bus.lan_id) hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; else hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; } if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { if (ixgbe_validate_phy_addr(hw, phy_addr)) { hw->phy.addr = phy_addr; ixgbe_get_phy_id(hw); hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & (IXGBE_MDIO_PHY_10GBASET_ABILITY | IXGBE_MDIO_PHY_1000BASET_ABILITY)) hw->phy.type = ixgbe_phy_cu_unknown; else hw->phy.type = ixgbe_phy_generic; } status = IXGBE_SUCCESS; break; } } /* Certain media types do not have a phy so an address will not * be found and the code will take this path. Caller has to * decide if it is an error or not. */ if (status != IXGBE_SUCCESS) { hw->phy.addr = 0; } } else { status = IXGBE_SUCCESS; } return status; } /** * ixgbe_check_reset_blocked - check status of MNG FW veto bit * @hw: pointer to the hardware structure * * This function checks the MMNGC.MNG_VETO bit to see if there are * any constraints on link from manageability. For MAC's that don't * have this bit just return faluse since the link can not be blocked * via this method. **/ s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw) { u32 mmngc; DEBUGFUNC("ixgbe_check_reset_blocked"); /* If we don't have this bit, it can't be blocking */ if (hw->mac.type == ixgbe_mac_82598EB) return false; mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC); if (mmngc & IXGBE_MMNGC_MNG_VETO) { ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "MNG_VETO bit detected.\n"); return true; } return false; } /** * ixgbe_validate_phy_addr - Determines phy address is valid * @hw: pointer to hardware structure * **/ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) { u16 phy_id = 0; bool valid = false; DEBUGFUNC("ixgbe_validate_phy_addr"); hw->phy.addr = phy_addr; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); if (phy_id != 0xFFFF && phy_id != 0x0) valid = true; return valid; } /** * ixgbe_get_phy_id - Get the phy type * @hw: pointer to hardware structure * **/ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) { u32 status; u16 phy_id_high = 0; u16 phy_id_low = 0; DEBUGFUNC("ixgbe_get_phy_id"); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_high); if (status == IXGBE_SUCCESS) { hw->phy.id = (u32)(phy_id_high << 16); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_low); hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK); hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); } return status; } /** * ixgbe_get_phy_type_from_id - Get the phy type * @hw: pointer to hardware structure * **/ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) { enum ixgbe_phy_type phy_type; DEBUGFUNC("ixgbe_get_phy_type_from_id"); switch (phy_id) { case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; break; case X550_PHY_ID1: case X550_PHY_ID2: case X550_PHY_ID3: case X540_PHY_ID: phy_type = ixgbe_phy_aq; break; case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; case ATH_PHY_ID: phy_type = ixgbe_phy_nl; break; case X557_PHY_ID: phy_type = ixgbe_phy_x550em_ext_t; break; default: phy_type = ixgbe_phy_unknown; break; } DEBUGOUT1("phy type found is %d\n", phy_type); return phy_type; } /** * ixgbe_reset_phy_generic - Performs a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) { u32 i; u16 ctrl = 0; s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_reset_phy_generic"); if (hw->phy.type == ixgbe_phy_unknown) status = ixgbe_identify_phy_generic(hw); if (status != IXGBE_SUCCESS || hw->phy.type == ixgbe_phy_none) goto out; /* Don't reset PHY if it's shut down due to overtemp. */ if (!hw->phy.reset_if_overtemp && (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw))) goto out; /* Blocked by MNG FW so bail */ if (ixgbe_check_reset_blocked(hw)) goto out; /* * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY */ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, IXGBE_MDIO_PHY_XS_RESET); /* * Poll for reset bit to self-clear indicating reset is complete. * Some PHYs could take up to 3 seconds to complete and need about * 1.7 usec delay after the reset is complete. */ for (i = 0; i < 30; i++) { msec_delay(100); hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl); if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) { usec_delay(2); break; } } if (ctrl & IXGBE_MDIO_PHY_XS_RESET) { status = IXGBE_ERR_RESET_FAILED; ERROR_REPORT1(IXGBE_ERROR_POLLING, "PHY reset polling failed to complete.\n"); } out: return status; } /** * ixgbe_read_phy_mdi - Reads a value from a specified PHY register without * the SWFW lock * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register **/ s32 ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { u32 i, data, command; /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle completed. * The MDI Command bit will clear when the operation is * complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "PHY address command did not complete.\n"); return IXGBE_ERR_PHY; } /* * Address cycle complete, setup and write the read * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle * completed. The MDI Command bit will clear when the * operation is complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "PHY read command didn't complete\n"); return IXGBE_ERR_PHY; } /* * Read operation is complete. Get the data * from MSRWD */ data = IXGBE_READ_REG(hw, IXGBE_MSRWD); data >>= IXGBE_MSRWD_READ_DATA_SHIFT; *phy_data = (u16)(data); return IXGBE_SUCCESS; } /** * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register * using the SWFW lock - this function is needed in most cases * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register **/ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { s32 status; u32 gssr = hw->phy.phy_semaphore_mask; DEBUGFUNC("ixgbe_read_phy_reg_generic"); if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) { status = ixgbe_read_phy_reg_mdi(hw, reg_addr, device_type, phy_data); hw->mac.ops.release_swfw_sync(hw, gssr); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_write_phy_reg_mdi - Writes a value to specified PHY register * without SWFW lock * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ s32 ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { u32 i, command; /* Put the data in the MDI single read and write data register*/ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle completed. * The MDI Command bit will clear when the operation is * complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "PHY address cmd didn't complete\n"); return IXGBE_ERR_PHY; } /* * Address cycle complete, setup and write the write * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle * completed. The MDI Command bit will clear when the * operation is complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { usec_delay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "PHY write cmd didn't complete\n"); return IXGBE_ERR_PHY; } return IXGBE_SUCCESS; } /** * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register * using SWFW lock- this function is needed in most cases * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { s32 status; u32 gssr = hw->phy.phy_semaphore_mask; DEBUGFUNC("ixgbe_write_phy_reg_generic"); if (hw->mac.ops.acquire_swfw_sync(hw, gssr) == IXGBE_SUCCESS) { status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); hw->mac.ops.release_swfw_sync(hw, gssr); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_setup_phy_link_generic - Set and restart auto-neg * @hw: pointer to hardware structure * * Restart auto-negotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; bool autoneg = false; ixgbe_link_speed speed; DEBUGFUNC("ixgbe_setup_phy_link_generic"); ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); if (speed & IXGBE_LINK_SPEED_10GB_FULL) { /* Set or unset auto-negotiation 10G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (hw->mac.type == ixgbe_mac_X550) { if (speed & IXGBE_LINK_SPEED_5GB_FULL) { /* Set or unset auto-negotiation 5G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) { /* Set or unset auto-negotiation 2.5G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { /* Set or unset auto-negotiation 1G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_100_FULL) { /* Set or unset auto-negotiation 100M advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~(IXGBE_MII_100BASE_T_ADVERTISE | IXGBE_MII_100BASE_T_ADVERTISE_HALF); if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } /* Blocked by MNG FW so don't reset PHY */ if (ixgbe_check_reset_blocked(hw)) return status; /* Restart PHY auto-negotiation. */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg |= IXGBE_MII_RESTART; hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); return status; } /** * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed **/ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); DEBUGFUNC("ixgbe_setup_phy_link_speed_generic"); /* * Clear autoneg_advertised and set new values based on input link * speed. */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_5GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_5GB_FULL; if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_2_5GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (speed & IXGBE_LINK_SPEED_100_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; /* Setup link based on the new speed settings */ hw->phy.ops.setup_link(hw); return IXGBE_SUCCESS; } /** * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the supported link capabilities by reading the PHY auto * negotiation register. **/ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status; u16 speed_ability; DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic"); *speed = 0; *autoneg = true; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &speed_ability); if (status == IXGBE_SUCCESS) { if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) *speed |= IXGBE_LINK_SPEED_1GB_FULL; if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M) *speed |= IXGBE_LINK_SPEED_100_FULL; } /* Internal PHY does not support 100 Mbps */ if (hw->mac.type == ixgbe_mac_X550EM_x) *speed &= ~IXGBE_LINK_SPEED_100_FULL; if (hw->mac.type == ixgbe_mac_X550) { *speed |= IXGBE_LINK_SPEED_2_5GB_FULL; *speed |= IXGBE_LINK_SPEED_5GB_FULL; } return status; } /** * ixgbe_check_phy_link_tnx - Determine link and speed status * @hw: pointer to hardware structure * * Reads the VS1 register to determine if link is up and the current speed for * the PHY. **/ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up) { s32 status = IXGBE_SUCCESS; u32 time_out; u32 max_time_out = 10; u16 phy_link = 0; u16 phy_speed = 0; u16 phy_data = 0; DEBUGFUNC("ixgbe_check_phy_link_tnx"); /* Initialize speed and link to default case */ *link_up = false; *speed = IXGBE_LINK_SPEED_10GB_FULL; /* * Check current speed and link status of the PHY register. * This is a vendor specific register and may have to * be changed for other copper PHYs. */ for (time_out = 0; time_out < max_time_out; time_out++) { usec_delay(10); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); phy_link = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; phy_speed = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { *link_up = true; if (phy_speed == IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) *speed = IXGBE_LINK_SPEED_1GB_FULL; break; } } return status; } /** * ixgbe_setup_phy_link_tnx - Set and restart auto-neg * @hw: pointer to hardware structure * * Restart auto-negotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; bool autoneg = false; ixgbe_link_speed speed; DEBUGFUNC("ixgbe_setup_phy_link_tnx"); ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); if (speed & IXGBE_LINK_SPEED_10GB_FULL) { /* Set or unset auto-negotiation 10G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { /* Set or unset auto-negotiation 1G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_100_FULL) { /* Set or unset auto-negotiation 100M advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } /* Blocked by MNG FW so don't reset PHY */ if (ixgbe_check_reset_blocked(hw)) return status; /* Restart PHY auto-negotiation. */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg |= IXGBE_MII_RESTART; hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); return status; } /** * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version **/ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status; DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx"); status = hw->phy.ops.read_reg(hw, TNX_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); return status; } /** * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version **/ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status; DEBUGFUNC("ixgbe_get_phy_firmware_version_generic"); status = hw->phy.ops.read_reg(hw, AQ_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); return status; } /** * ixgbe_reset_phy_nl - Performs a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) { u16 phy_offset, control, eword, edata, block_crc; bool end_data = false; u16 list_offset, data_offset; u16 phy_data = 0; s32 ret_val = IXGBE_SUCCESS; u32 i; DEBUGFUNC("ixgbe_reset_phy_nl"); /* Blocked by MNG FW so bail */ if (ixgbe_check_reset_blocked(hw)) goto out; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); /* reset the PHY and poll for completion */ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, (phy_data | IXGBE_MDIO_PHY_XS_RESET)); for (i = 0; i < 100; i++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0) break; msec_delay(10); } if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) { DEBUGOUT("PHY reset did not complete.\n"); ret_val = IXGBE_ERR_PHY; goto out; } /* Get init offsets */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != IXGBE_SUCCESS) goto out; ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc); data_offset++; while (!end_data) { /* * Read control word from PHY init contents offset */ ret_val = hw->eeprom.ops.read(hw, data_offset, &eword); if (ret_val) goto err_eeprom; control = (eword & IXGBE_CONTROL_MASK_NL) >> IXGBE_CONTROL_SHIFT_NL; edata = eword & IXGBE_DATA_MASK_NL; switch (control) { case IXGBE_DELAY_NL: data_offset++; DEBUGOUT1("DELAY: %d MS\n", edata); msec_delay(edata); break; case IXGBE_DATA_NL: DEBUGOUT("DATA:\n"); data_offset++; ret_val = hw->eeprom.ops.read(hw, data_offset, &phy_offset); if (ret_val) goto err_eeprom; data_offset++; for (i = 0; i < edata; i++) { ret_val = hw->eeprom.ops.read(hw, data_offset, &eword); if (ret_val) goto err_eeprom; hw->phy.ops.write_reg(hw, phy_offset, IXGBE_TWINAX_DEV, eword); DEBUGOUT2("Wrote %4.4x to %4.4x\n", eword, phy_offset); data_offset++; phy_offset++; } break; case IXGBE_CONTROL_NL: data_offset++; DEBUGOUT("CONTROL:\n"); if (edata == IXGBE_CONTROL_EOL_NL) { DEBUGOUT("EOL\n"); end_data = true; } else if (edata == IXGBE_CONTROL_SOL_NL) { DEBUGOUT("SOL\n"); } else { DEBUGOUT("Bad control value\n"); ret_val = IXGBE_ERR_PHY; goto out; } break; default: DEBUGOUT("Bad control type\n"); ret_val = IXGBE_ERR_PHY; goto out; } } out: return ret_val; err_eeprom: ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", data_offset); return IXGBE_ERR_PHY; } /** * ixgbe_identify_module_generic - Identifies module type * @hw: pointer to hardware structure * * Determines HW type and calls appropriate function. **/ s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_SFP_NOT_PRESENT; DEBUGFUNC("ixgbe_identify_module_generic"); switch (hw->mac.ops.get_media_type(hw)) { case ixgbe_media_type_fiber: status = ixgbe_identify_sfp_module_generic(hw); break; case ixgbe_media_type_fiber_qsfp: status = ixgbe_identify_qsfp_module_generic(hw); break; default: hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; break; } return status; } /** * ixgbe_identify_sfp_module_generic - Identifies SFP modules * @hw: pointer to hardware structure * * Searches for and identifies the SFP module and assigns appropriate PHY type. **/ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; u8 oui_bytes[3] = {0, 0, 0}; u8 cable_tech = 0; u8 cable_spec = 0; u16 enforce_sfp = 0; DEBUGFUNC("ixgbe_identify_sfp_module_generic"); if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; goto out; } /* LAN ID is needed for I2C access */ hw->mac.ops.set_lan_id(hw); status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &identifier); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; if (identifier != IXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } else { status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY, &cable_tech); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; /* ID Module * ========= * 0 SFP_DA_CU * 1 SFP_SR * 2 SFP_LR * 3 SFP_DA_CORE0 - 82599-specific * 4 SFP_DA_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific * 7 SFP_act_lmt_DA_CORE0 - 82599-specific * 8 SFP_act_lmt_DA_CORE1 - 82599-specific * 9 SFP_1g_cu_CORE0 - 82599-specific * 10 SFP_1g_cu_CORE1 - 82599-specific * 11 SFP_1g_sx_CORE0 - 82599-specific * 12 SFP_1g_sx_CORE1 - 82599-specific */ if (hw->mac.type == ixgbe_mac_82598EB) { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.sfp_type = ixgbe_sfp_type_da_cu; else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) hw->phy.sfp_type = ixgbe_sfp_type_sr; else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) hw->phy.sfp_type = ixgbe_sfp_type_lr; else hw->phy.sfp_type = ixgbe_sfp_type_unknown; } else { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1; } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) { hw->phy.ops.read_i2c_eeprom( hw, IXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (cable_spec & IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core1; } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; } } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | IXGBE_SFF_10GBASELR_CAPABLE)) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0; else hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1; } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_1g_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_1g_cu_core1; } else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_1g_sx_core0; else hw->phy.sfp_type = ixgbe_sfp_type_1g_sx_core1; } else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_1g_lx_core0; else hw->phy.sfp_type = ixgbe_sfp_type_1g_lx_core1; } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; } } if (hw->phy.sfp_type != stored_sfp_type) hw->phy.sfp_setup_needed = true; /* Determine if the SFP+ PHY is dual speed or not. */ hw->phy.multispeed_fiber = false; if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) hw->phy.multispeed_fiber = true; /* Determine PHY vendor */ if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = identifier; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE0, &oui_bytes[0]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE1, &oui_bytes[1]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE2, &oui_bytes[2]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; vendor_oui = ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) | (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) | (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT)); switch (vendor_oui) { case IXGBE_SFF_VENDOR_OUI_TYCO: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_passive_tyco; break; case IXGBE_SFF_VENDOR_OUI_FTL: if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_ftl_active; else hw->phy.type = ixgbe_phy_sfp_ftl; break; case IXGBE_SFF_VENDOR_OUI_AVAGO: hw->phy.type = ixgbe_phy_sfp_avago; break; case IXGBE_SFF_VENDOR_OUI_INTEL: hw->phy.type = ixgbe_phy_sfp_intel; break; default: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_passive_unknown; else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_active_unknown; else hw->phy.type = ixgbe_phy_sfp_unknown; break; } } /* Allow any DA cable vendor */ if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE | IXGBE_SFF_DA_ACTIVE_CABLE)) { status = IXGBE_SUCCESS; goto out; } /* Verify supported 1G SFP modules */ if (comp_codes_10g == 0 && !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) { hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } /* Anything else 82598-based is supported */ if (hw->mac.type == ixgbe_mac_82598EB) { status = IXGBE_SUCCESS; goto out; } ixgbe_get_device_caps(hw, &enforce_sfp); if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) && !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = IXGBE_SUCCESS; } else { if (hw->allow_unsupported_sfp == true) { EWARN(hw, "WARNING: Intel (R) Network " "Connections are quality tested " "using Intel (R) Ethernet Optics." " Using untested modules is not " "supported and may cause unstable" " operation or damage to the " "module or the adapter. Intel " "Corporation is not responsible " "for any harm caused by using " "untested modules.\n", status); status = IXGBE_SUCCESS; } else { DEBUGOUT("SFP+ module not supported\n"); hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } } else { status = IXGBE_SUCCESS; } } out: return status; err_read_i2c_eeprom: hw->phy.sfp_type = ixgbe_sfp_type_not_present; if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = 0; hw->phy.type = ixgbe_phy_unknown; } return IXGBE_ERR_SFP_NOT_PRESENT; } /** * ixgbe_get_supported_phy_sfp_layer_generic - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current SFP. */ s32 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u8 comp_codes_10g = 0; u8 comp_codes_1g = 0; DEBUGFUNC("ixgbe_get_supported_phy_sfp_layer_generic"); hw->phy.ops.identify_sfp(hw); if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) return physical_layer; switch (hw->phy.type) { case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: case ixgbe_phy_qsfp_passive_unknown: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case ixgbe_phy_sfp_ftl_active: case ixgbe_phy_sfp_active_unknown: case ixgbe_phy_qsfp_active_unknown: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; break; case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T; else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_SX; break; case ixgbe_phy_qsfp_intel: case ixgbe_phy_qsfp_unknown: hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g); if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; default: break; } return physical_layer; } /** * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules * @hw: pointer to hardware structure * * Searches for and identifies the QSFP module and assigns appropriate PHY type **/ s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; u8 oui_bytes[3] = {0, 0, 0}; u16 enforce_sfp = 0; u8 connector = 0; u8 cable_length = 0; u8 device_tech = 0; bool active_cable = false; DEBUGFUNC("ixgbe_identify_qsfp_module_generic"); if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; goto out; } /* LAN ID is needed for I2C access */ hw->mac.ops.set_lan_id(hw); status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &identifier); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) { hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } hw->phy.id = identifier; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_1GBE_COMP, &comp_codes_1g); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; if (comp_codes_10g & IXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { hw->phy.type = ixgbe_phy_qsfp_passive_unknown; if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1; } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | IXGBE_SFF_10GBASELR_CAPABLE)) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0; else hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1; } else { if (comp_codes_10g & IXGBE_SFF_QSFP_DA_ACTIVE_CABLE) active_cable = true; if (!active_cable) { /* check for active DA cables that pre-date * SFF-8436 v3.6 */ hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_CONNECTOR, &connector); hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_CABLE_LENGTH, &cable_length); hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_DEVICE_TECH, &device_tech); if ((connector == IXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE) && (cable_length > 0) && ((device_tech >> 4) == IXGBE_SFF_QSFP_TRANSMITER_850NM_VCSEL)) active_cable = true; } if (active_cable) { hw->phy.type = ixgbe_phy_qsfp_active_unknown; if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core1; } else { /* unsupported module type */ hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } } if (hw->phy.sfp_type != stored_sfp_type) hw->phy.sfp_setup_needed = true; /* Determine if the QSFP+ PHY is dual speed or not. */ hw->phy.multispeed_fiber = false; if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) hw->phy.multispeed_fiber = true; /* Determine PHY vendor for optical modules */ if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | IXGBE_SFF_10GBASELR_CAPABLE)) { status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, &oui_bytes[0]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, &oui_bytes[1]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, &oui_bytes[2]); if (status != IXGBE_SUCCESS) goto err_read_i2c_eeprom; vendor_oui = ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) | (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) | (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT)); if (vendor_oui == IXGBE_SFF_VENDOR_OUI_INTEL) hw->phy.type = ixgbe_phy_qsfp_intel; else hw->phy.type = ixgbe_phy_qsfp_unknown; ixgbe_get_device_caps(hw, &enforce_sfp); if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_qsfp_intel) { status = IXGBE_SUCCESS; } else { if (hw->allow_unsupported_sfp == true) { EWARN(hw, "WARNING: Intel (R) Network " "Connections are quality tested " "using Intel (R) Ethernet Optics." " Using untested modules is not " "supported and may cause unstable" " operation or damage to the " "module or the adapter. Intel " "Corporation is not responsible " "for any harm caused by using " "untested modules.\n", status); status = IXGBE_SUCCESS; } else { DEBUGOUT("QSFP module not supported\n"); hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } } else { status = IXGBE_SUCCESS; } } out: return status; err_read_i2c_eeprom: hw->phy.sfp_type = ixgbe_sfp_type_not_present; hw->phy.id = 0; hw->phy.type = ixgbe_phy_unknown; return IXGBE_ERR_SFP_NOT_PRESENT; } /** * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence * @hw: pointer to hardware structure * @list_offset: offset to the SFP ID list * @data_offset: offset to the SFP data block * * Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if * so it returns the offsets to the phy init sequence block. **/ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset) { u16 sfp_id; u16 sfp_type = hw->phy.sfp_type; DEBUGFUNC("ixgbe_get_sfp_init_sequence_offsets"); if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) return IXGBE_ERR_SFP_NOT_SUPPORTED; if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) return IXGBE_ERR_SFP_NOT_PRESENT; if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) && (hw->phy.sfp_type == ixgbe_sfp_type_da_cu)) return IXGBE_ERR_SFP_NOT_SUPPORTED; /* * Limiting active cables and 1G Phys must be initialized as * SR modules */ if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 || sfp_type == ixgbe_sfp_type_1g_lx_core0 || sfp_type == ixgbe_sfp_type_1g_cu_core0 || sfp_type == ixgbe_sfp_type_1g_sx_core0) sfp_type = ixgbe_sfp_type_srlr_core0; else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 || sfp_type == ixgbe_sfp_type_1g_lx_core1 || sfp_type == ixgbe_sfp_type_1g_cu_core1 || sfp_type == ixgbe_sfp_type_1g_sx_core1) sfp_type = ixgbe_sfp_type_srlr_core1; /* Read offset to PHY init contents */ if (hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset)) { ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", IXGBE_PHY_INIT_OFFSET_NL); return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT; } if ((!*list_offset) || (*list_offset == 0xFFFF)) return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT; /* Shift offset to first ID word */ (*list_offset)++; /* * Find the matching SFP ID in the EEPROM * and program the init sequence */ if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id)) goto err_phy; while (sfp_id != IXGBE_PHY_INIT_END_NL) { if (sfp_id == sfp_type) { (*list_offset)++; if (hw->eeprom.ops.read(hw, *list_offset, data_offset)) goto err_phy; if ((!*data_offset) || (*data_offset == 0xFFFF)) { DEBUGOUT("SFP+ module not supported\n"); return IXGBE_ERR_SFP_NOT_SUPPORTED; } else { break; } } else { (*list_offset) += 2; if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id)) goto err_phy; } } if (sfp_id == IXGBE_PHY_INIT_END_NL) { DEBUGOUT("No matching SFP+ module found\n"); return IXGBE_ERR_SFP_NOT_SUPPORTED; } return IXGBE_SUCCESS; err_phy: ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "eeprom read at offset %d failed", *list_offset); return IXGBE_ERR_PHY; } /** * ixgbe_read_i2c_eeprom_generic - Reads 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { DEBUGFUNC("ixgbe_read_i2c_eeprom_generic"); return hw->phy.ops.read_i2c_byte(hw, byte_offset, IXGBE_I2C_EEPROM_DEV_ADDR, eeprom_data); } /** * ixgbe_read_i2c_sff8472_generic - Reads 8 bit word over I2C interface * @hw: pointer to hardware structure * @byte_offset: byte offset at address 0xA2 * @eeprom_data: value read * * Performs byte read operation to SFP module's SFF-8472 data over I2C **/ STATIC s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *sff8472_data) { return hw->phy.ops.read_i2c_byte(hw, byte_offset, IXGBE_I2C_EEPROM_DEV_ADDR2, sff8472_data); } /** * ixgbe_write_i2c_eeprom_generic - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to write * @eeprom_data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data) { DEBUGFUNC("ixgbe_write_i2c_eeprom_generic"); return hw->phy.ops.write_i2c_byte(hw, byte_offset, IXGBE_I2C_EEPROM_DEV_ADDR, eeprom_data); } /** * ixgbe_is_sfp_probe - Returns true if SFP is being detected * @hw: pointer to hardware structure * @offset: eeprom offset to be read * @addr: I2C address to be read */ STATIC bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr) { if (addr == IXGBE_I2C_EEPROM_DEV_ADDR && offset == IXGBE_SFF_IDENTIFIER && hw->phy.sfp_type == ixgbe_sfp_type_not_present) return true; return false; } /** * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * @lock: true if to take and release semaphore * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ STATIC s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data, bool lock) { s32 status; u32 max_retry = 10; u32 retry = 0; u32 swfw_mask = hw->phy.phy_semaphore_mask; bool nack = 1; *data = 0; DEBUGFUNC("ixgbe_read_i2c_byte_generic"); if (hw->mac.type >= ixgbe_mac_X550) max_retry = 3; if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr)) max_retry = IXGBE_SFP_DETECT_RETRIES; do { if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ status = ixgbe_clock_out_i2c_byte(hw, dev_addr); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_clock_out_i2c_byte(hw, byte_offset); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; ixgbe_i2c_start(hw); /* Device Address and read indication */ status = ixgbe_clock_out_i2c_byte(hw, (dev_addr | 0x1)); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_clock_in_i2c_byte(hw, data); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_clock_out_i2c_bit(hw, nack); if (status != IXGBE_SUCCESS) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); return IXGBE_SUCCESS; fail: ixgbe_i2c_bus_clear(hw); if (lock) { hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(100); } retry++; if (retry < max_retry) DEBUGOUT("I2C byte read error - Retrying.\n"); else DEBUGOUT("I2C byte read error.\n"); } while (retry < max_retry); return status; } /** * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr, data, true); } /** * ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr, data, false); } /** * ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * @lock: true if to take and release semaphore * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ STATIC s32 ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data, bool lock) { s32 status; u32 max_retry = 1; u32 retry = 0; u32 swfw_mask = hw->phy.phy_semaphore_mask; DEBUGFUNC("ixgbe_write_i2c_byte_generic"); if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) return IXGBE_ERR_SWFW_SYNC; do { ixgbe_i2c_start(hw); status = ixgbe_clock_out_i2c_byte(hw, dev_addr); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_clock_out_i2c_byte(hw, byte_offset); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_clock_out_i2c_byte(hw, data); if (status != IXGBE_SUCCESS) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != IXGBE_SUCCESS) goto fail; ixgbe_i2c_stop(hw); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); return IXGBE_SUCCESS; fail: ixgbe_i2c_bus_clear(hw); retry++; if (retry < max_retry) DEBUGOUT("I2C byte write error - Retrying.\n"); else DEBUGOUT("I2C byte write error.\n"); } while (retry < max_retry); if (lock) hw->mac.ops.release_swfw_sync(hw, swfw_mask); return status; } /** * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr, data, true); } /** * ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr, data, false); } /** * ixgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) * Set bit-bang mode on X550 hardware. **/ STATIC void ixgbe_i2c_start(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); DEBUGFUNC("ixgbe_i2c_start"); i2cctl |= IXGBE_I2C_BB_EN_BY_MAC(hw); /* Start condition must begin with data and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 1); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Setup time for start condition (4.7us) */ usec_delay(IXGBE_I2C_T_SU_STA); ixgbe_set_i2c_data(hw, &i2cctl, 0); /* Hold time for start condition (4us) */ usec_delay(IXGBE_I2C_T_HD_STA); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(IXGBE_I2C_T_LOW); } /** * ixgbe_i2c_stop - Sets I2C stop condition * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) * Disables bit-bang mode and negates data output enable on X550 * hardware. **/ STATIC void ixgbe_i2c_stop(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN_BY_MAC(hw); u32 bb_en_bit = IXGBE_I2C_BB_EN_BY_MAC(hw); DEBUGFUNC("ixgbe_i2c_stop"); /* Stop condition must begin with data low and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 0); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Setup time for stop condition (4us) */ usec_delay(IXGBE_I2C_T_SU_STO); ixgbe_set_i2c_data(hw, &i2cctl, 1); /* bus free time between stop and start (4.7us)*/ usec_delay(IXGBE_I2C_T_BUF); if (bb_en_bit || data_oe_bit || clk_oe_bit) { i2cctl &= ~bb_en_bit; i2cctl |= data_oe_bit | clk_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); } } /** * ixgbe_clock_in_i2c_byte - Clocks in one byte via I2C * @hw: pointer to hardware structure * @data: data byte to clock in * * Clocks in one byte data via I2C data/clock **/ STATIC s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data) { s32 i; bool bit = 0; DEBUGFUNC("ixgbe_clock_in_i2c_byte"); *data = 0; for (i = 7; i >= 0; i--) { ixgbe_clock_in_i2c_bit(hw, &bit); *data |= bit << i; } return IXGBE_SUCCESS; } /** * ixgbe_clock_out_i2c_byte - Clocks out one byte via I2C * @hw: pointer to hardware structure * @data: data byte clocked out * * Clocks out one byte data via I2C data/clock **/ STATIC s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) { s32 status = IXGBE_SUCCESS; s32 i; u32 i2cctl; bool bit; DEBUGFUNC("ixgbe_clock_out_i2c_byte"); for (i = 7; i >= 0; i--) { bit = (data >> i) & 0x1; status = ixgbe_clock_out_i2c_bit(hw, bit); if (status != IXGBE_SUCCESS) break; } /* Release SDA line (set high) */ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); i2cctl |= IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); return status; } /** * ixgbe_get_i2c_ack - Polls for I2C ACK * @hw: pointer to hardware structure * * Clocks in/out one bit via I2C data/clock **/ STATIC s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) { u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); s32 status = IXGBE_SUCCESS; u32 i = 0; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); u32 timeout = 10; bool ack = 1; DEBUGFUNC("ixgbe_get_i2c_ack"); if (data_oe_bit) { i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); i2cctl |= data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); } ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(IXGBE_I2C_T_HIGH); /* Poll for ACK. Note that ACK in I2C spec is * transition from 1 to 0 */ for (i = 0; i < timeout; i++) { i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); ack = ixgbe_get_i2c_data(hw, &i2cctl); usec_delay(1); if (!ack) break; } if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = IXGBE_ERR_I2C; } ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(IXGBE_I2C_T_LOW); return status; } /** * ixgbe_clock_in_i2c_bit - Clocks in one bit via I2C data/clock * @hw: pointer to hardware structure * @data: read data value * * Clocks in one bit via I2C data/clock **/ STATIC s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); DEBUGFUNC("ixgbe_clock_in_i2c_bit"); if (data_oe_bit) { i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); i2cctl |= data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); } ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(IXGBE_I2C_T_HIGH); i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); *data = ixgbe_get_i2c_data(hw, &i2cctl); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(IXGBE_I2C_T_LOW); return IXGBE_SUCCESS; } /** * ixgbe_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock * @hw: pointer to hardware structure * @data: data value to write * * Clocks out one bit via I2C data/clock **/ STATIC s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) { s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); DEBUGFUNC("ixgbe_clock_out_i2c_bit"); status = ixgbe_set_i2c_data(hw, &i2cctl, data); if (status == IXGBE_SUCCESS) { ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(IXGBE_I2C_T_HIGH); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us. * This also takes care of the data hold time. */ usec_delay(IXGBE_I2C_T_LOW); } else { status = IXGBE_ERR_I2C; ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "I2C data was not set to %X\n", data); } return status; } /** * ixgbe_raise_i2c_clk - Raises the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' * Negates the I2C clock output enable on X550 hardware. **/ STATIC void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN_BY_MAC(hw); u32 i = 0; u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT; u32 i2cctl_r = 0; DEBUGFUNC("ixgbe_raise_i2c_clk"); if (clk_oe_bit) { *i2cctl |= clk_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); } for (i = 0; i < timeout; i++) { *i2cctl |= IXGBE_I2C_CLK_OUT_BY_MAC(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL rise time (1000ns) */ usec_delay(IXGBE_I2C_T_RISE); i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); if (i2cctl_r & IXGBE_I2C_CLK_IN_BY_MAC(hw)) break; } } /** * ixgbe_lower_i2c_clk - Lowers the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' * Asserts the I2C clock output enable on X550 hardware. **/ STATIC void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { DEBUGFUNC("ixgbe_lower_i2c_clk"); *i2cctl &= ~(IXGBE_I2C_CLK_OUT_BY_MAC(hw)); *i2cctl &= ~IXGBE_I2C_CLK_OE_N_EN_BY_MAC(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL fall time (300ns) */ usec_delay(IXGBE_I2C_T_FALL); } /** * ixgbe_set_i2c_data - Sets the I2C data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit * Asserts the I2C data output enable on X550 hardware. **/ STATIC s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_set_i2c_data"); if (data) *i2cctl |= IXGBE_I2C_DATA_OUT_BY_MAC(hw); else *i2cctl &= ~(IXGBE_I2C_DATA_OUT_BY_MAC(hw)); *i2cctl &= ~data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ usec_delay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA); if (!data) /* Can't verify data in this case */ return IXGBE_SUCCESS; if (data_oe_bit) { *i2cctl |= data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); } /* Verify data was set correctly */ *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); if (data != ixgbe_get_i2c_data(hw, i2cctl)) { status = IXGBE_ERR_I2C; ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, "Error - I2C data was not set to %X.\n", data); } return status; } /** * ixgbe_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value * Negates the I2C data output enable on X550 hardware. **/ STATIC bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl) { u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); bool data; DEBUGFUNC("ixgbe_get_i2c_data"); if (data_oe_bit) { *i2cctl |= data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL_BY_MAC(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); usec_delay(IXGBE_I2C_T_FALL); } if (*i2cctl & IXGBE_I2C_DATA_IN_BY_MAC(hw)) data = 1; else data = 0; return data; } /** * ixgbe_i2c_bus_clear - Clears the I2C bus * @hw: pointer to hardware structure * * Clears the I2C bus by sending nine clock pulses. * Used when data line is stuck low. **/ void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) { u32 i2cctl; u32 i; DEBUGFUNC("ixgbe_i2c_bus_clear"); ixgbe_i2c_start(hw); i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL_BY_MAC(hw)); ixgbe_set_i2c_data(hw, &i2cctl, 1); for (i = 0; i < 9; i++) { ixgbe_raise_i2c_clk(hw, &i2cctl); /* Min high period of clock is 4us */ usec_delay(IXGBE_I2C_T_HIGH); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Min low period of clock is 4.7us*/ usec_delay(IXGBE_I2C_T_LOW); } ixgbe_i2c_start(hw); /* Put the i2c bus back to default state */ ixgbe_i2c_stop(hw); } /** * ixgbe_tn_check_overtemp - Checks if an overtemp occurred. * @hw: pointer to hardware structure * * Checks if the LASI temp alarm status was triggered due to overtemp **/ s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; u16 phy_data = 0; DEBUGFUNC("ixgbe_tn_check_overtemp"); if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM) goto out; /* Check that the LASI temp alarm status was triggered */ hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_data); if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM)) goto out; status = IXGBE_ERR_OVERTEMP; ERROR_REPORT1(IXGBE_ERROR_CAUTION, "Device over temperature"); out: return status; } /** * ixgbe_set_copper_phy_power - Control power for copper phy * @hw: pointer to hardware structure * @on: true for on, false for off */ s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) { u32 status; u16 reg; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status) return status; if (on) { reg &= ~IXGBE_MDIO_PHY_SET_LOW_POWER_MODE; } else { if (ixgbe_check_reset_blocked(hw)) return 0; reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE; } status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, reg); return status; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_phy.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_PHY_H_ #define _IXGBE_PHY_H_ #include "ixgbe_type.h" #define IXGBE_I2C_EEPROM_DEV_ADDR 0xA0 #define IXGBE_I2C_EEPROM_DEV_ADDR2 0xA2 #define IXGBE_I2C_EEPROM_BANK_LEN 0xFF /* EEPROM byte offsets */ #define IXGBE_SFF_IDENTIFIER 0x0 #define IXGBE_SFF_IDENTIFIER_SFP 0x3 #define IXGBE_SFF_VENDOR_OUI_BYTE0 0x25 #define IXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define IXGBE_SFF_1GBE_COMP_CODES 0x6 #define IXGBE_SFF_10GBE_COMP_CODES 0x3 #define IXGBE_SFF_CABLE_TECHNOLOGY 0x8 #define IXGBE_SFF_CABLE_SPEC_COMP 0x3C #define IXGBE_SFF_SFF_8472_SWAP 0x5C #define IXGBE_SFF_SFF_8472_COMP 0x5E #define IXGBE_SFF_SFF_8472_OSCB 0x6E #define IXGBE_SFF_SFF_8472_ESCB 0x76 #define IXGBE_SFF_IDENTIFIER_QSFP_PLUS 0xD #define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0 0xA5 #define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1 0xA6 #define IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2 0xA7 #define IXGBE_SFF_QSFP_CONNECTOR 0x82 #define IXGBE_SFF_QSFP_10GBE_COMP 0x83 #define IXGBE_SFF_QSFP_1GBE_COMP 0x86 #define IXGBE_SFF_QSFP_CABLE_LENGTH 0x92 #define IXGBE_SFF_QSFP_DEVICE_TECH 0x93 /* Bitmasks */ #define IXGBE_SFF_DA_PASSIVE_CABLE 0x4 #define IXGBE_SFF_DA_ACTIVE_CABLE 0x8 #define IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 #define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_1GBASET_CAPABLE 0x8 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 #define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define IXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define IXGBE_SFF_SOFT_RS_SELECT_1G 0x0 #define IXGBE_SFF_ADDRESSING_MODE 0x4 #define IXGBE_SFF_QSFP_DA_ACTIVE_CABLE 0x1 #define IXGBE_SFF_QSFP_DA_PASSIVE_CABLE 0x8 #define IXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE 0x23 #define IXGBE_SFF_QSFP_TRANSMITER_850NM_VCSEL 0x0 #define IXGBE_I2C_EEPROM_READ_MASK 0x100 #define IXGBE_I2C_EEPROM_STATUS_MASK 0x3 #define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0 #define IXGBE_I2C_EEPROM_STATUS_PASS 0x1 #define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 #define IXGBE_CS4227 0xBE /* CS4227 address */ #define IXGBE_CS4227_GLOBAL_ID_LSB 0 #define IXGBE_CS4227_SCRATCH 2 #define IXGBE_CS4227_GLOBAL_ID_VALUE 0x03E5 #define IXGBE_CS4227_SCRATCH_VALUE 0x5aa5 #define IXGBE_CS4227_RETRIES 5 #define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to program speed */ #define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to program EDC */ #define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to program speed */ #define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */ #define IXGBE_CS4227_SPEED_1G 0x8000 #define IXGBE_CS4227_SPEED_10G 0 #define IXGBE_CS4227_EDC_MODE_CX1 0x0002 #define IXGBE_CS4227_EDC_MODE_SR 0x0004 #define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */ #define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */ #define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */ #define IXGBE_PE 0xE0 /* Port expander address */ #define IXGBE_PE_OUTPUT 1 /* Output register offset */ #define IXGBE_PE_CONFIG 3 /* Config register offset */ #define IXGBE_PE_BIT1 (1 << 1) /* Flow control defines */ #define IXGBE_TAF_SYM_PAUSE 0x400 #define IXGBE_TAF_ASM_PAUSE 0x800 /* Bit-shift macros */ #define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 24 #define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 16 #define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 8 /* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */ #define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600 #define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500 #define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00 #define IXGBE_SFF_VENDOR_OUI_INTEL 0x001B2100 /* I2C SDA and SCL timing parameters for standard mode */ #define IXGBE_I2C_T_HD_STA 4 #define IXGBE_I2C_T_LOW 5 #define IXGBE_I2C_T_HIGH 4 #define IXGBE_I2C_T_SU_STA 5 #define IXGBE_I2C_T_HD_DATA 5 #define IXGBE_I2C_T_SU_DATA 1 #define IXGBE_I2C_T_RISE 1 #define IXGBE_I2C_T_FALL 1 #define IXGBE_I2C_T_SU_STO 4 #define IXGBE_I2C_T_BUF 5 #ifndef IXGBE_SFP_DETECT_RETRIES #define IXGBE_SFP_DETECT_RETRIES 10 #endif /* IXGBE_SFP_DETECT_RETRIES */ #define IXGBE_TN_LASI_STATUS_REG 0x9005 #define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008 /* SFP+ SFF-8472 Compliance */ #define IXGBE_SFF_SFF_8472_UNSUP 0x00 #ident "$Id: ixgbe_phy.h,v 1.56 2013/09/05 23:59:49 jtkirshe Exp $" s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw); s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw); s32 ixgbe_read_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ixgbe_write_phy_reg_mdi(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw); s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw); /* PHY specific */ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw); s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw); s32 ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on); s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw); s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); s32 ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw); s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw); s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset); s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); #endif /* _IXGBE_PHY_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_type.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_TYPE_H_ #define _IXGBE_TYPE_H_ /* * The following is a brief description of the error categories used by the * ERROR_REPORT* macros. * * - IXGBE_ERROR_INVALID_STATE * This category is for errors which represent a serious failure state that is * unexpected, and could be potentially harmful to device operation. It should * not be used for errors relating to issues that can be worked around or * ignored. * * - IXGBE_ERROR_POLLING * This category is for errors related to polling/timeout issues and should be * used in any case where the timeout occured, or a failure to obtain a lock, or * failure to receive data within the time limit. * * - IXGBE_ERROR_CAUTION * This category should be used for reporting issues that may be the cause of * other errors, such as temperature warnings. It should indicate an event which * could be serious, but hasn't necessarily caused problems yet. * * - IXGBE_ERROR_SOFTWARE * This category is intended for errors due to software state preventing * something. The category is not intended for errors due to bad arguments, or * due to unsupported features. It should be used when a state occurs which * prevents action but is not a serious issue. * * - IXGBE_ERROR_ARGUMENT * This category is for when a bad or invalid argument is passed. It should be * used whenever a function is called and error checking has detected the * argument is wrong or incorrect. * * - IXGBE_ERROR_UNSUPPORTED * This category is for errors which are due to unsupported circumstances or * configuration issues. It should not be used when the issue is due to an * invalid argument, but for when something has occurred that is unsupported * (Ex: Flow control autonegotiation or an unsupported SFP+ module.) */ #include "ixgbe_osdep.h" /* Override this by setting IOMEM in your ixgbe_osdep.h header */ /* Vendor ID */ #define IXGBE_INTEL_VENDOR_ID 0x8086 /* Device IDs */ #define IXGBE_DEV_ID_82598 0x10B6 #define IXGBE_DEV_ID_82598_BX 0x1508 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT 0x10C8 #define IXGBE_DEV_ID_82598AT2 0x150B #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC #define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 #define IXGBE_DEV_ID_82599_KR 0x1517 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_SUBDEV_ID_82599_SFP_WOL0 0x1071 #define IXGBE_SUBDEV_ID_82599_RNDC 0x1F72 #define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0 #define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470 #define IXGBE_SUBDEV_ID_82599_SP_560FLR 0x211B #define IXGBE_SUBDEV_ID_82599_LOM_SFP 0x8976 #define IXGBE_SUBDEV_ID_82599_LOM_SNAP6 0x2159 #define IXGBE_SUBDEV_ID_82599_SFP_1OCP 0x000D #define IXGBE_SUBDEV_ID_82599_SFP_2OCP 0x0008 #define IXGBE_SUBDEV_ID_82599_SFP_LOM 0x06EE #define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A #define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_SFP_SF2 0x154D #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A #define IXGBE_DEV_ID_82599_QSFP_SF_QP 0x1558 #define IXGBE_DEV_ID_82599EN_SFP 0x1557 #define IXGBE_SUBDEV_ID_82599EN_SFP_OCP1 0x0001 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_T3_LOM 0x151C #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_82599_VF_HV 0x152E #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_X540_VF 0x1515 #define IXGBE_DEV_ID_X540_VF_HV 0x1530 #define IXGBE_DEV_ID_X540T1 0x1560 #define IXGBE_DEV_ID_X550T 0x1563 #define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA #define IXGBE_DEV_ID_X550EM_X_KR 0x15AB #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE #define IXGBE_DEV_ID_X550_VF_HV 0x1564 #define IXGBE_DEV_ID_X550_VF 0x1565 #define IXGBE_DEV_ID_X550EM_X_VF 0x15A8 #define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9 #define IXGBE_CAT(r, m) IXGBE_##r##m #define IXGBE_BY_MAC(_hw, r) ((_hw)->mvals[IXGBE_CAT(r, _IDX)]) /* General Registers */ #define IXGBE_CTRL 0x00000 #define IXGBE_STATUS 0x00008 #define IXGBE_CTRL_EXT 0x00018 #define IXGBE_ESDP 0x00020 #define IXGBE_EODSDP 0x00028 #define IXGBE_I2CCTL_82599 0x00028 #define IXGBE_I2CCTL IXGBE_I2CCTL_82599 #define IXGBE_I2CCTL_X540 IXGBE_I2CCTL_82599 #define IXGBE_I2CCTL_X550 0x15F5C #define IXGBE_I2CCTL_X550EM_x IXGBE_I2CCTL_X550 #define IXGBE_I2CCTL_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2CCTL) #define IXGBE_PHY_GPIO 0x00028 #define IXGBE_MAC_GPIO 0x00030 #define IXGBE_PHYINT_STATUS0 0x00100 #define IXGBE_PHYINT_STATUS1 0x00104 #define IXGBE_PHYINT_STATUS2 0x00108 #define IXGBE_LEDCTL 0x00200 #define IXGBE_FRTIMER 0x00048 #define IXGBE_TCPTIMER 0x0004C #define IXGBE_CORESPARE 0x00600 #define IXGBE_EXVET 0x05078 /* NVM Registers */ #define IXGBE_EEC 0x10010 #define IXGBE_EEC_X540 IXGBE_EEC #define IXGBE_EEC_X550 IXGBE_EEC #define IXGBE_EEC_X550EM_x IXGBE_EEC #define IXGBE_EEC_BY_MAC(_hw) IXGBE_EEC #define IXGBE_EERD 0x10014 #define IXGBE_EEWR 0x10018 #define IXGBE_FLA 0x1001C #define IXGBE_FLA_X540 IXGBE_FLA #define IXGBE_FLA_X550 IXGBE_FLA #define IXGBE_FLA_X550EM_x IXGBE_FLA #define IXGBE_FLA_BY_MAC(_hw) IXGBE_FLA #define IXGBE_EEMNGCTL 0x10110 #define IXGBE_EEMNGDATA 0x10114 #define IXGBE_FLMNGCTL 0x10118 #define IXGBE_FLMNGDATA 0x1011C #define IXGBE_FLMNGCNT 0x10120 #define IXGBE_FLOP 0x1013C #define IXGBE_GRC 0x10200 #define IXGBE_GRC_X540 IXGBE_GRC #define IXGBE_GRC_X550 IXGBE_GRC #define IXGBE_GRC_X550EM_x IXGBE_GRC #define IXGBE_GRC_BY_MAC(_hw) IXGBE_GRC #define IXGBE_SRAMREL 0x10210 #define IXGBE_SRAMREL_X540 IXGBE_SRAMREL #define IXGBE_SRAMREL_X550 IXGBE_SRAMREL #define IXGBE_SRAMREL_X550EM_x IXGBE_SRAMREL #define IXGBE_SRAMREL_BY_MAC(_hw) IXGBE_SRAMREL #define IXGBE_PHYDBG 0x10218 /* General Receive Control */ #define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */ #define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */ #define IXGBE_VPDDIAG0 0x10204 #define IXGBE_VPDDIAG1 0x10208 /* I2CCTL Bit Masks */ #define IXGBE_I2C_CLK_IN 0x00000001 #define IXGBE_I2C_CLK_IN_X540 IXGBE_I2C_CLK_IN #define IXGBE_I2C_CLK_IN_X550 0x00004000 #define IXGBE_I2C_CLK_IN_X550EM_x IXGBE_I2C_CLK_IN_X550 #define IXGBE_I2C_CLK_IN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_IN) #define IXGBE_I2C_CLK_OUT 0x00000002 #define IXGBE_I2C_CLK_OUT_X540 IXGBE_I2C_CLK_OUT #define IXGBE_I2C_CLK_OUT_X550 0x00000200 #define IXGBE_I2C_CLK_OUT_X550EM_x IXGBE_I2C_CLK_OUT_X550 #define IXGBE_I2C_CLK_OUT_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_OUT) #define IXGBE_I2C_DATA_IN 0x00000004 #define IXGBE_I2C_DATA_IN_X540 IXGBE_I2C_DATA_IN #define IXGBE_I2C_DATA_IN_X550 0x00001000 #define IXGBE_I2C_DATA_IN_X550EM_x IXGBE_I2C_DATA_IN_X550 #define IXGBE_I2C_DATA_IN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_IN) #define IXGBE_I2C_DATA_OUT 0x00000008 #define IXGBE_I2C_DATA_OUT_X540 IXGBE_I2C_DATA_OUT #define IXGBE_I2C_DATA_OUT_X550 0x00000400 #define IXGBE_I2C_DATA_OUT_X550EM_x IXGBE_I2C_DATA_OUT_X550 #define IXGBE_I2C_DATA_OUT_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_OUT) #define IXGBE_I2C_DATA_OE_N_EN 0 #define IXGBE_I2C_DATA_OE_N_EN_X540 IXGBE_I2C_DATA_OE_N_EN #define IXGBE_I2C_DATA_OE_N_EN_X550 0x00000800 #define IXGBE_I2C_DATA_OE_N_EN_X550EM_x IXGBE_I2C_DATA_OE_N_EN_X550 #define IXGBE_I2C_DATA_OE_N_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_DATA_OE_N_EN) #define IXGBE_I2C_BB_EN 0 #define IXGBE_I2C_BB_EN_X540 IXGBE_I2C_BB_EN #define IXGBE_I2C_BB_EN_X550 0x00000100 #define IXGBE_I2C_BB_EN_X550EM_x IXGBE_I2C_BB_EN_X550 #define IXGBE_I2C_BB_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_BB_EN) #define IXGBE_I2C_CLK_OE_N_EN 0 #define IXGBE_I2C_CLK_OE_N_EN_X540 IXGBE_I2C_CLK_OE_N_EN #define IXGBE_I2C_CLK_OE_N_EN_X550 0x00002000 #define IXGBE_I2C_CLK_OE_N_EN_X550EM_x IXGBE_I2C_CLK_OE_N_EN_X550 #define IXGBE_I2C_CLK_OE_N_EN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), I2C_CLK_OE_N_EN) #define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500 #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 #define IXGBE_EMC_INTERNAL_DATA 0x00 #define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20 #define IXGBE_EMC_DIODE1_DATA 0x01 #define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19 #define IXGBE_EMC_DIODE2_DATA 0x23 #define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A #define IXGBE_MAX_SENSORS 3 struct ixgbe_thermal_diode_data { u8 location; u8 temp; u8 caution_thresh; u8 max_op_thresh; }; struct ixgbe_thermal_sensor_data { struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS]; }; /* Interrupt Registers */ #define IXGBE_EICR 0x00800 #define IXGBE_EICS 0x00808 #define IXGBE_EIMS 0x00880 #define IXGBE_EIMC 0x00888 #define IXGBE_EIAC 0x00810 #define IXGBE_EIAM 0x00890 #define IXGBE_EICS_EX(_i) (0x00A90 + (_i) * 4) #define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4) #define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4) #define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4) /* 82599 EITR is only 12 bits, with the lower 3 always zero */ /* * 82598 EITR is 16 bits but set the limits based on the max * supported by all ixgbe hardware */ #define IXGBE_MAX_INT_RATE 488281 #define IXGBE_MIN_INT_RATE 956 #define IXGBE_MAX_EITR 0x00000FF8 #define IXGBE_MIN_EITR 8 #define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : \ (0x012300 + (((_i) - 24) * 4))) #define IXGBE_EITR_ITR_INT_MASK 0x00000FF8 #define IXGBE_EITR_LLI_MOD 0x00008000 #define IXGBE_EITR_CNT_WDIS 0x80000000 #define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */ #define IXGBE_IVAR_MISC 0x00A00 /* misc MSI-X interrupt causes */ #define IXGBE_EITRSEL 0x00894 #define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */ #define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */ #define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4))) #define IXGBE_GPIE 0x00898 /* Flow Control Registers */ #define IXGBE_FCADBUL 0x03210 #define IXGBE_FCADBUH 0x03214 #define IXGBE_FCAMACL 0x04328 #define IXGBE_FCAMACH 0x0432C #define IXGBE_FCRTH_82599(_i) (0x03260 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_FCRTL_82599(_i) (0x03220 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_PFCTOP 0x03008 #define IXGBE_FCTTV(_i) (0x03200 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_FCRTL(_i) (0x03220 + ((_i) * 8)) /* 8 of these (0-7) */ #define IXGBE_FCRTH(_i) (0x03260 + ((_i) * 8)) /* 8 of these (0-7) */ #define IXGBE_FCRTV 0x032A0 #define IXGBE_FCCFG 0x03D00 #define IXGBE_TFCS 0x0CE00 /* Receive DMA Registers */ #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \ (0x0D000 + (((_i) - 64) * 0x40))) #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \ (0x0D004 + (((_i) - 64) * 0x40))) #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \ (0x0D008 + (((_i) - 64) * 0x40))) #define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \ (0x0D010 + (((_i) - 64) * 0x40))) #define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \ (0x0D018 + (((_i) - 64) * 0x40))) #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \ (0x0D028 + (((_i) - 64) * 0x40))) #define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ (0x0D02C + (((_i) - 64) * 0x40))) #define IXGBE_RSCDBU 0x03028 #define IXGBE_RDDCC 0x02F20 #define IXGBE_RXMEMWRAP 0x03190 #define IXGBE_STARCTRL 0x03024 /* * Split and Replication Receive Control Registers * 00-15 : 0x02100 + n*4 * 16-64 : 0x01014 + n*0x40 * 64-127: 0x0D014 + (n-64)*0x40 */ #define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \ (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \ (0x0D014 + (((_i) - 64) * 0x40)))) /* * Rx DCA Control Register: * 00-15 : 0x02200 + n*4 * 16-64 : 0x0100C + n*0x40 * 64-127: 0x0D00C + (n-64)*0x40 */ #define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \ (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \ (0x0D00C + (((_i) - 64) * 0x40)))) #define IXGBE_RDRXCTL 0x02F00 /* 8 of these 0x03C00 - 0x03C1C */ #define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4)) #define IXGBE_RXCTRL 0x03000 #define IXGBE_DROPEN 0x03D04 #define IXGBE_RXPBSIZE_SHIFT 10 #define IXGBE_RXPBSIZE_MASK 0x000FFC00 /* Receive Registers */ #define IXGBE_RXCSUM 0x05000 #define IXGBE_RFCTL 0x05008 #define IXGBE_DRECCCTL 0x02F08 #define IXGBE_DRECCCTL_DISABLE 0 #define IXGBE_DRECCCTL2 0x02F8C /* Multicast Table Array - 128 entries */ #define IXGBE_MTA(_i) (0x05200 + ((_i) * 4)) #define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ (0x0A200 + ((_i) * 8))) #define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ (0x0A204 + ((_i) * 8))) #define IXGBE_MPSAR_LO(_i) (0x0A600 + ((_i) * 8)) #define IXGBE_MPSAR_HI(_i) (0x0A604 + ((_i) * 8)) /* Packet split receive type */ #define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : \ (0x0EA00 + ((_i) * 4))) /* array of 4096 1-bit vlan filters */ #define IXGBE_VFTA(_i) (0x0A000 + ((_i) * 4)) /*array of 4096 4-bit vlan vmdq indices */ #define IXGBE_VFTAVIND(_j, _i) (0x0A200 + ((_j) * 0x200) + ((_i) * 4)) #define IXGBE_FCTRL 0x05080 #define IXGBE_VLNCTRL 0x05088 #define IXGBE_MCSTCTRL 0x05090 #define IXGBE_MRQC 0x05818 #define IXGBE_SAQF(_i) (0x0E000 + ((_i) * 4)) /* Source Address Queue Filter */ #define IXGBE_DAQF(_i) (0x0E200 + ((_i) * 4)) /* Dest. Address Queue Filter */ #define IXGBE_SDPQF(_i) (0x0E400 + ((_i) * 4)) /* Src Dest. Addr Queue Filter */ #define IXGBE_FTQF(_i) (0x0E600 + ((_i) * 4)) /* Five Tuple Queue Filter */ #define IXGBE_ETQF(_i) (0x05128 + ((_i) * 4)) /* EType Queue Filter */ #define IXGBE_ETQS(_i) (0x0EC00 + ((_i) * 4)) /* EType Queue Select */ #define IXGBE_SYNQF 0x0EC30 /* SYN Packet Queue Filter */ #define IXGBE_RQTC 0x0EC70 #define IXGBE_MTQC 0x08120 #define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */ #define IXGBE_VMVIR(_i) (0x08000 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_PFFLPL 0x050B0 #define IXGBE_PFFLPH 0x050B4 #define IXGBE_VT_CTL 0x051B0 #define IXGBE_PFMAILBOX(_i) (0x04B00 + (4 * (_i))) /* 64 total */ /* 64 Mailboxes, 16 DW each */ #define IXGBE_PFMBMEM(_i) (0x13000 + (64 * (_i))) #define IXGBE_PFMBICR(_i) (0x00710 + (4 * (_i))) /* 4 total */ #define IXGBE_PFMBIMR(_i) (0x00720 + (4 * (_i))) /* 4 total */ #define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) #define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) #define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4)) #define IXGBE_QDE 0x2F04 #define IXGBE_VMTXSW(_i) (0x05180 + ((_i) * 4)) /* 2 total */ #define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */ #define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4)) #define IXGBE_MRCTL(_i) (0x0F600 + ((_i) * 4)) #define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) #define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) #define IXGBE_LVMMC_RX 0x2FA8 #define IXGBE_LVMMC_TX 0x8108 #define IXGBE_LMVM_RX 0x2FA4 #define IXGBE_LMVM_TX 0x8124 #define IXGBE_WQBR_RX(_i) (0x2FB0 + ((_i) * 4)) /* 4 total */ #define IXGBE_WQBR_TX(_i) (0x8130 + ((_i) * 4)) /* 4 total */ #define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ #define IXGBE_RXFECCERR0 0x051B8 #define IXGBE_LLITHRESH 0x0EC90 #define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIRVP 0x05AC0 #define IXGBE_VMD_CTL 0x0581C #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_ERETA(_i) (0x0EE80 + ((_i) * 4)) /* 96 of these (0-95) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ /* Registers for setting up RSS on X550 with SRIOV * _p - pool number (0..63) * _i - index (0..10 for PFVFRSSRK, 0..15 for PFVFRETA) */ #define IXGBE_PFVFMRQC(_p) (0x03400 + ((_p) * 4)) #define IXGBE_PFVFRSSRK(_i, _p) (0x018000 + ((_i) * 4) + ((_p) * 0x40)) #define IXGBE_PFVFRETA(_i, _p) (0x019000 + ((_i) * 4) + ((_p) * 0x40)) /* Flow Director registers */ #define IXGBE_FDIRCTRL 0x0EE00 #define IXGBE_FDIRHKEY 0x0EE68 #define IXGBE_FDIRSKEY 0x0EE6C #define IXGBE_FDIRDIP4M 0x0EE3C #define IXGBE_FDIRSIP4M 0x0EE40 #define IXGBE_FDIRTCPM 0x0EE44 #define IXGBE_FDIRUDPM 0x0EE48 #define IXGBE_FDIRSCTPM 0x0EE78 #define IXGBE_FDIRIP6M 0x0EE74 #define IXGBE_FDIRM 0x0EE70 /* Flow Director Stats registers */ #define IXGBE_FDIRFREE 0x0EE38 #define IXGBE_FDIRLEN 0x0EE4C #define IXGBE_FDIRUSTAT 0x0EE50 #define IXGBE_FDIRFSTAT 0x0EE54 #define IXGBE_FDIRMATCH 0x0EE58 #define IXGBE_FDIRMISS 0x0EE5C /* Flow Director Programming registers */ #define IXGBE_FDIRSIPv6(_i) (0x0EE0C + ((_i) * 4)) /* 3 of these (0-2) */ #define IXGBE_FDIRIPSA 0x0EE18 #define IXGBE_FDIRIPDA 0x0EE1C #define IXGBE_FDIRPORT 0x0EE20 #define IXGBE_FDIRVLAN 0x0EE24 #define IXGBE_FDIRHASH 0x0EE28 #define IXGBE_FDIRCMD 0x0EE2C /* Transmit DMA registers */ #define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of them (0-31)*/ #define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40)) #define IXGBE_TDLEN(_i) (0x06008 + ((_i) * 0x40)) #define IXGBE_TDH(_i) (0x06010 + ((_i) * 0x40)) #define IXGBE_TDT(_i) (0x06018 + ((_i) * 0x40)) #define IXGBE_TXDCTL(_i) (0x06028 + ((_i) * 0x40)) #define IXGBE_TDWBAL(_i) (0x06038 + ((_i) * 0x40)) #define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40)) #define IXGBE_DTXCTL 0x07E00 #define IXGBE_DMATXCTL 0x04A80 #define IXGBE_PFVFSPOOF(_i) (0x08200 + ((_i) * 4)) /* 8 of these 0 - 7 */ #define IXGBE_PFDTXGSWC 0x08220 #define IXGBE_DTXMXSZRQ 0x08100 #define IXGBE_DTXTCPFLGL 0x04A88 #define IXGBE_DTXTCPFLGH 0x04A8C #define IXGBE_LBDRPEN 0x0CA00 #define IXGBE_TXPBTHRESH(_i) (0x04950 + ((_i) * 4)) /* 8 of these 0 - 7 */ #define IXGBE_DMATXCTL_TE 0x1 /* Transmit Enable */ #define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */ #define IXGBE_DMATXCTL_GDV 0x8 /* Global Double VLAN */ #define IXGBE_DMATXCTL_MDP_EN 0x20 /* Bit 5 */ #define IXGBE_DMATXCTL_MBINTEN 0x40 /* Bit 6 */ #define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */ #define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */ /* Anti-spoofing defines */ #define IXGBE_SPOOF_MACAS_MASK 0xFF #define IXGBE_SPOOF_VLANAS_MASK 0xFF00 #define IXGBE_SPOOF_VLANAS_SHIFT 8 #define IXGBE_SPOOF_ETHERTYPEAS 0xFF000000 #define IXGBE_SPOOF_ETHERTYPEAS_SHIFT 16 #define IXGBE_PFVFSPOOF_REG_COUNT 8 /* 16 of these (0-15) */ #define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* Tx DCA Control register : 128 of these (0-127) */ #define IXGBE_DCA_TXCTRL_82599(_i) (0x0600C + ((_i) * 0x40)) #define IXGBE_TIPG 0x0CB00 #define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) * 4)) /* 8 of these */ #define IXGBE_MNGTXMAP 0x0CD10 #define IXGBE_TIPG_FIBER_DEFAULT 3 #define IXGBE_TXPBSIZE_SHIFT 10 /* Wake up registers */ #define IXGBE_WUC 0x05800 #define IXGBE_WUFC 0x05808 #define IXGBE_WUS 0x05810 #define IXGBE_IPAV 0x05838 #define IXGBE_IP4AT 0x05840 /* IPv4 table 0x5840-0x5858 */ #define IXGBE_IP6AT 0x05880 /* IPv6 table 0x5880-0x588F */ #define IXGBE_WUPL 0x05900 #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ #define IXGBE_PROXYS 0x05F60 /* Proxying Status Register */ #define IXGBE_PROXYFC 0x05F64 /* Proxying Filter Control Register */ #define IXGBE_VXLANCTRL 0x0000507C /* Rx filter VXLAN UDPPORT Register */ #define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */ /* Ext Flexible Host Filter Table */ #define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) #define IXGBE_FHFT_EXT_X550(_n) (0x09600 + ((_n) * 0x100)) /* Four Flexible Filters are supported */ #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX 4 /* Six Flexible Filters are supported */ #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX_6 6 /* Eight Flexible Filters are supported */ #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX_8 8 #define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 /* Each Flexible Filter is at most 128 (0x80) bytes in length */ #define IXGBE_FLEXIBLE_FILTER_SIZE_MAX 128 #define IXGBE_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */ #define IXGBE_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */ /* Definitions for power management and wakeup registers */ /* Wake Up Control */ #define IXGBE_WUC_PME_EN 0x00000002 /* PME Enable */ #define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */ #define IXGBE_WUC_WKEN 0x00000010 /* Enable PE_WAKE_N pin assertion */ /* Wake Up Filter Control */ #define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ #define IXGBE_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ #define IXGBE_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define IXGBE_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ #define IXGBE_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define IXGBE_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define IXGBE_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define IXGBE_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ #define IXGBE_WUFC_MNG 0x00000100 /* Directed Mgmt Packet Wakeup Enable */ #define IXGBE_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define IXGBE_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define IXGBE_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ #define IXGBE_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ #define IXGBE_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ #define IXGBE_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ #define IXGBE_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ #define IXGBE_WUFC_FLX_FILTERS 0x000F0000 /* Mask for 4 flex filters */ #define IXGBE_WUFC_FLX_FILTERS_6 0x003F0000 /* Mask for 6 flex filters */ #define IXGBE_WUFC_FLX_FILTERS_8 0x00FF0000 /* Mask for 8 flex filters */ #define IXGBE_WUFC_FW_RST_WK 0x80000000 /* Ena wake on FW reset assertion */ /* Mask for Ext. flex filters */ #define IXGBE_WUFC_EXT_FLX_FILTERS 0x00300000 #define IXGBE_WUFC_ALL_FILTERS 0x000F00FF /* Mask all 4 flex filters */ #define IXGBE_WUFC_ALL_FILTERS_6 0x003F00FF /* Mask all 6 flex filters */ #define IXGBE_WUFC_ALL_FILTERS_8 0x00FF00FF /* Mask all 8 flex filters */ #define IXGBE_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ /* Wake Up Status */ #define IXGBE_WUS_LNKC IXGBE_WUFC_LNKC #define IXGBE_WUS_MAG IXGBE_WUFC_MAG #define IXGBE_WUS_EX IXGBE_WUFC_EX #define IXGBE_WUS_MC IXGBE_WUFC_MC #define IXGBE_WUS_BC IXGBE_WUFC_BC #define IXGBE_WUS_ARP IXGBE_WUFC_ARP #define IXGBE_WUS_IPV4 IXGBE_WUFC_IPV4 #define IXGBE_WUS_IPV6 IXGBE_WUFC_IPV6 #define IXGBE_WUS_MNG IXGBE_WUFC_MNG #define IXGBE_WUS_FLX0 IXGBE_WUFC_FLX0 #define IXGBE_WUS_FLX1 IXGBE_WUFC_FLX1 #define IXGBE_WUS_FLX2 IXGBE_WUFC_FLX2 #define IXGBE_WUS_FLX3 IXGBE_WUFC_FLX3 #define IXGBE_WUS_FLX4 IXGBE_WUFC_FLX4 #define IXGBE_WUS_FLX5 IXGBE_WUFC_FLX5 #define IXGBE_WUS_FLX_FILTERS IXGBE_WUFC_FLX_FILTERS #define IXGBE_WUS_FW_RST_WK IXGBE_WUFC_FW_RST_WK /* Proxy Status */ #define IXGBE_PROXYS_EX 0x00000004 /* Exact packet received */ #define IXGBE_PROXYS_ARP_DIR 0x00000020 /* ARP w/filter match received */ #define IXGBE_PROXYS_NS 0x00000200 /* IPV6 NS received */ #define IXGBE_PROXYS_NS_DIR 0x00000400 /* IPV6 NS w/DA match received */ #define IXGBE_PROXYS_ARP 0x00000800 /* ARP request packet received */ #define IXGBE_PROXYS_MLD 0x00001000 /* IPv6 MLD packet received */ /* Proxying Filter Control */ #define IXGBE_PROXYFC_ENABLE 0x00000001 /* Port Proxying Enable */ #define IXGBE_PROXYFC_EX 0x00000004 /* Directed Exact Proxy Enable */ #define IXGBE_PROXYFC_ARP_DIR 0x00000020 /* Directed ARP Proxy Enable */ #define IXGBE_PROXYFC_NS 0x00000200 /* IPv6 Neighbor Solicitation */ #define IXGBE_PROXYFC_ARP 0x00000800 /* ARP Request Proxy Enable */ #define IXGBE_PROXYFC_MLD 0x00000800 /* IPv6 MLD Proxy Enable */ #define IXGBE_PROXYFC_NO_TCO 0x00008000 /* Ignore TCO packets */ #define IXGBE_WUPL_LENGTH_MASK 0xFFFF /* DCB registers */ #define IXGBE_DCB_MAX_TRAFFIC_CLASS 8 #define IXGBE_RMCS 0x03D00 #define IXGBE_DPMCS 0x07F40 #define IXGBE_PDPMCS 0x0CD00 #define IXGBE_RUPPBMR 0x050A0 #define IXGBE_RT2CR(_i) (0x03C20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RT2SR(_i) (0x03C40 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDTQ2TCCR(_i) (0x0602C + ((_i) * 0x40)) /* 8 of these (0-7) */ #define IXGBE_TDTQ2TCSR(_i) (0x0622C + ((_i) * 0x40)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ /* Power Management */ /* DMA Coalescing configuration */ struct ixgbe_dmac_config { u16 watchdog_timer; /* usec units */ bool fcoe_en; u32 link_speed; u8 fcoe_tc; u8 num_tcs; }; /* * DMA Coalescing threshold Rx PB TC[n] value in Kilobyte by link speed. * DMACRXT = 10Gbps = 10,000 bits / usec = 1250 bytes / usec 70 * 1250 == * 87500 bytes [85KB] */ #define IXGBE_DMACRXT_10G 0x55 #define IXGBE_DMACRXT_1G 0x09 #define IXGBE_DMACRXT_100M 0x01 /* DMA Coalescing registers */ #define IXGBE_DMCMNGTH 0x15F20 /* Management Threshold */ #define IXGBE_DMACR 0x02400 /* Control register */ #define IXGBE_DMCTH(_i) (0x03300 + ((_i) * 4)) /* 8 of these */ #define IXGBE_DMCTLX 0x02404 /* Time to Lx request */ /* DMA Coalescing register fields */ #define IXGBE_DMCMNGTH_DMCMNGTH_MASK 0x000FFFF0 /* Mng Threshold mask */ #define IXGBE_DMCMNGTH_DMCMNGTH_SHIFT 4 /* Management Threshold shift */ #define IXGBE_DMACR_DMACWT_MASK 0x0000FFFF /* Watchdog Timer mask */ #define IXGBE_DMACR_HIGH_PRI_TC_MASK 0x00FF0000 #define IXGBE_DMACR_HIGH_PRI_TC_SHIFT 16 #define IXGBE_DMACR_EN_MNG_IND 0x10000000 /* Enable Mng Indications */ #define IXGBE_DMACR_LX_COAL_IND 0x40000000 /* Lx Coalescing indicate */ #define IXGBE_DMACR_DMAC_EN 0x80000000 /* DMA Coalescing Enable */ #define IXGBE_DMCTH_DMACRXT_MASK 0x000001FF /* Receive Threshold mask */ #define IXGBE_DMCTLX_TTLX_MASK 0x00000FFF /* Time to Lx request mask */ /* EEE registers */ #define IXGBE_EEER 0x043A0 /* EEE register */ #define IXGBE_EEE_STAT 0x04398 /* EEE Status */ #define IXGBE_EEE_SU 0x04380 /* EEE Set up */ #define IXGBE_EEE_SU_TEEE_DLY_SHIFT 26 #define IXGBE_TLPIC 0x041F4 /* EEE Tx LPI count */ #define IXGBE_RLPIC 0x041F8 /* EEE Rx LPI count */ /* EEE register fields */ #define IXGBE_EEER_TX_LPI_EN 0x00010000 /* Enable EEE LPI TX path */ #define IXGBE_EEER_RX_LPI_EN 0x00020000 /* Enable EEE LPI RX path */ #define IXGBE_EEE_STAT_NEG 0x20000000 /* EEE support neg on link */ #define IXGBE_EEE_RX_LPI_STATUS 0x40000000 /* RX Link in LPI status */ #define IXGBE_EEE_TX_LPI_STATUS 0x80000000 /* TX Link in LPI status */ /* Security Control Registers */ #define IXGBE_SECTXCTRL 0x08800 #define IXGBE_SECTXSTAT 0x08804 #define IXGBE_SECTXBUFFAF 0x08808 #define IXGBE_SECTXMINIFG 0x08810 #define IXGBE_SECRXCTRL 0x08D00 #define IXGBE_SECRXSTAT 0x08D04 /* Security Bit Fields and Masks */ #define IXGBE_SECTXCTRL_SECTX_DIS 0x00000001 #define IXGBE_SECTXCTRL_TX_DIS 0x00000002 #define IXGBE_SECTXCTRL_STORE_FORWARD 0x00000004 #define IXGBE_SECTXSTAT_SECTX_RDY 0x00000001 #define IXGBE_SECTXSTAT_ECC_TXERR 0x00000002 #define IXGBE_SECRXCTRL_SECRX_DIS 0x00000001 #define IXGBE_SECRXCTRL_RX_DIS 0x00000002 #define IXGBE_SECRXSTAT_SECRX_RDY 0x00000001 #define IXGBE_SECRXSTAT_ECC_RXERR 0x00000002 /* LinkSec (MacSec) Registers */ #define IXGBE_LSECTXCAP 0x08A00 #define IXGBE_LSECRXCAP 0x08F00 #define IXGBE_LSECTXCTRL 0x08A04 #define IXGBE_LSECTXSCL 0x08A08 /* SCI Low */ #define IXGBE_LSECTXSCH 0x08A0C /* SCI High */ #define IXGBE_LSECTXSA 0x08A10 #define IXGBE_LSECTXPN0 0x08A14 #define IXGBE_LSECTXPN1 0x08A18 #define IXGBE_LSECTXKEY0(_n) (0x08A1C + (4 * (_n))) /* 4 of these (0-3) */ #define IXGBE_LSECTXKEY1(_n) (0x08A2C + (4 * (_n))) /* 4 of these (0-3) */ #define IXGBE_LSECRXCTRL 0x08F04 #define IXGBE_LSECRXSCL 0x08F08 #define IXGBE_LSECRXSCH 0x08F0C #define IXGBE_LSECRXSA(_i) (0x08F10 + (4 * (_i))) /* 2 of these (0-1) */ #define IXGBE_LSECRXPN(_i) (0x08F18 + (4 * (_i))) /* 2 of these (0-1) */ #define IXGBE_LSECRXKEY(_n, _m) (0x08F20 + ((0x10 * (_n)) + (4 * (_m)))) #define IXGBE_LSECTXUT 0x08A3C /* OutPktsUntagged */ #define IXGBE_LSECTXPKTE 0x08A40 /* OutPktsEncrypted */ #define IXGBE_LSECTXPKTP 0x08A44 /* OutPktsProtected */ #define IXGBE_LSECTXOCTE 0x08A48 /* OutOctetsEncrypted */ #define IXGBE_LSECTXOCTP 0x08A4C /* OutOctetsProtected */ #define IXGBE_LSECRXUT 0x08F40 /* InPktsUntagged/InPktsNoTag */ #define IXGBE_LSECRXOCTD 0x08F44 /* InOctetsDecrypted */ #define IXGBE_LSECRXOCTV 0x08F48 /* InOctetsValidated */ #define IXGBE_LSECRXBAD 0x08F4C /* InPktsBadTag */ #define IXGBE_LSECRXNOSCI 0x08F50 /* InPktsNoSci */ #define IXGBE_LSECRXUNSCI 0x08F54 /* InPktsUnknownSci */ #define IXGBE_LSECRXUNCH 0x08F58 /* InPktsUnchecked */ #define IXGBE_LSECRXDELAY 0x08F5C /* InPktsDelayed */ #define IXGBE_LSECRXLATE 0x08F60 /* InPktsLate */ #define IXGBE_LSECRXOK(_n) (0x08F64 + (0x04 * (_n))) /* InPktsOk */ #define IXGBE_LSECRXINV(_n) (0x08F6C + (0x04 * (_n))) /* InPktsInvalid */ #define IXGBE_LSECRXNV(_n) (0x08F74 + (0x04 * (_n))) /* InPktsNotValid */ #define IXGBE_LSECRXUNSA 0x08F7C /* InPktsUnusedSa */ #define IXGBE_LSECRXNUSA 0x08F80 /* InPktsNotUsingSa */ /* LinkSec (MacSec) Bit Fields and Masks */ #define IXGBE_LSECTXCAP_SUM_MASK 0x00FF0000 #define IXGBE_LSECTXCAP_SUM_SHIFT 16 #define IXGBE_LSECRXCAP_SUM_MASK 0x00FF0000 #define IXGBE_LSECRXCAP_SUM_SHIFT 16 #define IXGBE_LSECTXCTRL_EN_MASK 0x00000003 #define IXGBE_LSECTXCTRL_DISABLE 0x0 #define IXGBE_LSECTXCTRL_AUTH 0x1 #define IXGBE_LSECTXCTRL_AUTH_ENCRYPT 0x2 #define IXGBE_LSECTXCTRL_AISCI 0x00000020 #define IXGBE_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 #define IXGBE_LSECTXCTRL_RSV_MASK 0x000000D8 #define IXGBE_LSECRXCTRL_EN_MASK 0x0000000C #define IXGBE_LSECRXCTRL_EN_SHIFT 2 #define IXGBE_LSECRXCTRL_DISABLE 0x0 #define IXGBE_LSECRXCTRL_CHECK 0x1 #define IXGBE_LSECRXCTRL_STRICT 0x2 #define IXGBE_LSECRXCTRL_DROP 0x3 #define IXGBE_LSECRXCTRL_PLSH 0x00000040 #define IXGBE_LSECRXCTRL_RP 0x00000080 #define IXGBE_LSECRXCTRL_RSV_MASK 0xFFFFFF33 /* IpSec Registers */ #define IXGBE_IPSTXIDX 0x08900 #define IXGBE_IPSTXSALT 0x08904 #define IXGBE_IPSTXKEY(_i) (0x08908 + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXIDX 0x08E00 #define IXGBE_IPSRXIPADDR(_i) (0x08E04 + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXSPI 0x08E14 #define IXGBE_IPSRXIPIDX 0x08E18 #define IXGBE_IPSRXKEY(_i) (0x08E1C + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXSALT 0x08E2C #define IXGBE_IPSRXMOD 0x08E30 #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4 /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 #define IXGBE_RTTDCS_ARBDIS 0x00000040 /* DCB arbiter disable */ #define IXGBE_RTTPCS 0x0CD00 #define IXGBE_RTRUP2TC 0x03020 #define IXGBE_RTTUP2TC 0x0C800 #define IXGBE_RTRPT4C(_i) (0x02140 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TXLLQ(_i) (0x082E0 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_RTRPT4S(_i) (0x02160 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2C(_i) (0x04910 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2S(_i) (0x04930 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTPT2C(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTPT2S(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDQSEL 0x04904 #define IXGBE_RTTDT1C 0x04908 #define IXGBE_RTTDT1S 0x0490C #define IXGBE_RTTDTECC 0x04990 #define IXGBE_RTTDTECC_NO_BCN 0x00000100 #define IXGBE_RTTBCNRC 0x04984 #define IXGBE_RTTBCNRC_RS_ENA 0x80000000 #define IXGBE_RTTBCNRC_RF_DEC_MASK 0x00003FFF #define IXGBE_RTTBCNRC_RF_INT_SHIFT 14 #define IXGBE_RTTBCNRC_RF_INT_MASK \ (IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT) #define IXGBE_RTTBCNRM 0x04980 /* BCN (for DCB) Registers */ #define IXGBE_RTTBCNRS 0x04988 #define IXGBE_RTTBCNCR 0x08B00 #define IXGBE_RTTBCNACH 0x08B04 #define IXGBE_RTTBCNACL 0x08B08 #define IXGBE_RTTBCNTG 0x04A90 #define IXGBE_RTTBCNIDX 0x08B0C #define IXGBE_RTTBCNCP 0x08B10 #define IXGBE_RTFRTIMER 0x08B14 #define IXGBE_RTTBCNRTT 0x05150 #define IXGBE_RTTBCNRD 0x0498C /* FCoE DMA Context Registers */ /* FCoE Direct DMA Context */ #define IXGBE_FCDDC(_i, _j) (0x20000 + ((_i) * 0x4) + ((_j) * 0x10)) #define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */ #define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */ #define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */ #define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */ #define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */ #define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */ #define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */ #define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */ #define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */ #define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3 #define IXGBE_FCBUFF_BUFFCNT_SHIFT 8 #define IXGBE_FCBUFF_OFFSET_SHIFT 16 #define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */ #define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */ #define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */ #define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */ #define IXGBE_FCDMARW_LASTSIZE_SHIFT 16 /* FCoE SOF/EOF */ #define IXGBE_TEOFF 0x04A94 /* Tx FC EOF */ #define IXGBE_TSOFF 0x04A98 /* Tx FC SOF */ #define IXGBE_REOFF 0x05158 /* Rx FC EOF */ #define IXGBE_RSOFF 0x051F8 /* Rx FC SOF */ /* FCoE Filter Context Registers */ #define IXGBE_FCD_ID 0x05114 /* FCoE D_ID */ #define IXGBE_FCSMAC 0x0510C /* FCoE Source MAC */ #define IXGBE_FCFLTRW_SMAC_HIGH_SHIFT 16 /* FCoE Direct Filter Context */ #define IXGBE_FCDFC(_i, _j) (0x28000 + ((_i) * 0x4) + ((_j) * 0x10)) #define IXGBE_FCDFCD(_i) (0x30000 + ((_i) * 0x4)) #define IXGBE_FCFLT 0x05108 /* FC FLT Context */ #define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */ #define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */ #define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */ #define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */ #define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */ #define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */ #define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */ #define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */ #define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */ /* FCoE Receive Control */ #define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */ #define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */ #define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */ #define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */ #define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */ #define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */ #define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */ #define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */ #define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */ #define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */ #define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8 /* FCoE Redirection */ #define IXGBE_FCRECTL 0x0ED00 /* FC Redirection Control */ #define IXGBE_FCRETA0 0x0ED10 /* FC Redirection Table 0 */ #define IXGBE_FCRETA(_i) (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */ #define IXGBE_FCRECTL_ENA 0x1 /* FCoE Redir Table Enable */ #define IXGBE_FCRETASEL_ENA 0x2 /* FCoE FCRETASEL bit */ #define IXGBE_FCRETA_SIZE 8 /* Max entries in FCRETA */ #define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */ #define IXGBE_FCRETA_SIZE_X550 32 /* Max entries in FCRETA */ /* Higher 7 bits for the queue index */ #define IXGBE_FCRETA_ENTRY_HIGH_MASK 0x007F0000 #define IXGBE_FCRETA_ENTRY_HIGH_SHIFT 16 /* Stats registers */ #define IXGBE_CRCERRS 0x04000 #define IXGBE_ILLERRC 0x04004 #define IXGBE_ERRBC 0x04008 #define IXGBE_MSPDC 0x04010 #define IXGBE_MPC(_i) (0x03FA0 + ((_i) * 4)) /* 8 of these 3FA0-3FBC*/ #define IXGBE_MLFC 0x04034 #define IXGBE_MRFC 0x04038 #define IXGBE_RLEC 0x04040 #define IXGBE_LXONTXC 0x03F60 #define IXGBE_LXONRXC 0x0CF60 #define IXGBE_LXOFFTXC 0x03F68 #define IXGBE_LXOFFRXC 0x0CF68 #define IXGBE_LXONRXCNT 0x041A4 #define IXGBE_LXOFFRXCNT 0x041A8 #define IXGBE_PXONRXCNT(_i) (0x04140 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXOFFRXCNT(_i) (0x04160 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXON2OFFCNT(_i) (0x03240 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXONTXC(_i) (0x03F00 + ((_i) * 4)) /* 8 of these 3F00-3F1C*/ #define IXGBE_PXONRXC(_i) (0x0CF00 + ((_i) * 4)) /* 8 of these CF00-CF1C*/ #define IXGBE_PXOFFTXC(_i) (0x03F20 + ((_i) * 4)) /* 8 of these 3F20-3F3C*/ #define IXGBE_PXOFFRXC(_i) (0x0CF20 + ((_i) * 4)) /* 8 of these CF20-CF3C*/ #define IXGBE_PRC64 0x0405C #define IXGBE_PRC127 0x04060 #define IXGBE_PRC255 0x04064 #define IXGBE_PRC511 0x04068 #define IXGBE_PRC1023 0x0406C #define IXGBE_PRC1522 0x04070 #define IXGBE_GPRC 0x04074 #define IXGBE_BPRC 0x04078 #define IXGBE_MPRC 0x0407C #define IXGBE_GPTC 0x04080 #define IXGBE_GORCL 0x04088 #define IXGBE_GORCH 0x0408C #define IXGBE_GOTCL 0x04090 #define IXGBE_GOTCH 0x04094 #define IXGBE_RNBC(_i) (0x03FC0 + ((_i) * 4)) /* 8 of these 3FC0-3FDC*/ #define IXGBE_RUC 0x040A4 #define IXGBE_RFC 0x040A8 #define IXGBE_ROC 0x040AC #define IXGBE_RJC 0x040B0 #define IXGBE_MNGPRC 0x040B4 #define IXGBE_MNGPDC 0x040B8 #define IXGBE_MNGPTC 0x0CF90 #define IXGBE_TORL 0x040C0 #define IXGBE_TORH 0x040C4 #define IXGBE_TPR 0x040D0 #define IXGBE_TPT 0x040D4 #define IXGBE_PTC64 0x040D8 #define IXGBE_PTC127 0x040DC #define IXGBE_PTC255 0x040E0 #define IXGBE_PTC511 0x040E4 #define IXGBE_PTC1023 0x040E8 #define IXGBE_PTC1522 0x040EC #define IXGBE_MPTC 0x040F0 #define IXGBE_BPTC 0x040F4 #define IXGBE_XEC 0x04120 #define IXGBE_SSVPC 0x08780 #define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4)) #define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : \ (0x08600 + ((_i) * 4))) #define IXGBE_TQSM(_i) (0x08600 + ((_i) * 4)) #define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC_L(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC_H(_i) (0x01038 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_FCCRC 0x05118 /* Num of Good Eth CRC w/ Bad FC CRC */ #define IXGBE_FCOERPDC 0x0241C /* FCoE Rx Packets Dropped Count */ #define IXGBE_FCLAST 0x02424 /* FCoE Last Error Count */ #define IXGBE_FCOEPRC 0x02428 /* Number of FCoE Packets Received */ #define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */ #define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */ #define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */ #define IXGBE_FCCRC_CNT_MASK 0x0000FFFF /* CRC_CNT: bit 0 - 15 */ #define IXGBE_FCLAST_CNT_MASK 0x0000FFFF /* Last_CNT: bit 0 - 15 */ #define IXGBE_O2BGPTC 0x041C4 #define IXGBE_O2BSPC 0x087B0 #define IXGBE_B2OSPC 0x041C0 #define IXGBE_B2OGPRC 0x02F90 #define IXGBE_BUPRC 0x04180 #define IXGBE_BMPRC 0x04184 #define IXGBE_BBPRC 0x04188 #define IXGBE_BUPTC 0x0418C #define IXGBE_BMPTC 0x04190 #define IXGBE_BBPTC 0x04194 #define IXGBE_BCRCERRS 0x04198 #define IXGBE_BXONRXC 0x0419C #define IXGBE_BXOFFRXC 0x041E0 #define IXGBE_BXONTXC 0x041E4 #define IXGBE_BXOFFTXC 0x041E8 /* Management */ #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MFUTP(_i) (0x05030 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MANC 0x05820 #define IXGBE_MFVAL 0x05824 #define IXGBE_MANC2H 0x05860 #define IXGBE_MDEF(_i) (0x05890 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MIPAF 0x058B0 #define IXGBE_MMAL(_i) (0x05910 + ((_i) * 8)) /* 4 of these (0-3) */ #define IXGBE_MMAH(_i) (0x05914 + ((_i) * 8)) /* 4 of these (0-3) */ #define IXGBE_FTFT 0x09400 /* 0x9400-0x97FC */ #define IXGBE_METF(_i) (0x05190 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_MDEF_EXT(_i) (0x05160 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_LSWFW 0x15014 #define IXGBE_BMCIP(_i) (0x05050 + ((_i) * 4)) /* 0x5050-0x505C */ #define IXGBE_BMCIPVAL 0x05060 #define IXGBE_BMCIP_IPADDR_TYPE 0x00000001 #define IXGBE_BMCIP_IPADDR_VALID 0x00000002 /* Management Bit Fields and Masks */ #define IXGBE_MANC_MPROXYE 0x40000000 /* Management Proxy Enable */ #define IXGBE_MANC_RCV_TCO_EN 0x00020000 /* Rcv TCO packet enable */ #define IXGBE_MANC_EN_BMC2OS 0x10000000 /* Ena BMC2OS and OS2BMC traffic */ #define IXGBE_MANC_EN_BMC2OS_SHIFT 28 /* Firmware Semaphore Register */ #define IXGBE_FWSM_MODE_MASK 0xE #define IXGBE_FWSM_TS_ENABLED 0x1 #define IXGBE_FWSM_FW_MODE_PT 0x4 /* ARC Subsystem registers */ #define IXGBE_HICR 0x15F00 #define IXGBE_FWSTS 0x15F0C #define IXGBE_HSMC0R 0x15F04 #define IXGBE_HSMC1R 0x15F08 #define IXGBE_SWSR 0x15F10 #define IXGBE_HFDR 0x15FE8 #define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */ #define IXGBE_HICR_EN 0x01 /* Enable bit - RO */ /* Driver sets this bit when done to put command in RAM */ #define IXGBE_HICR_C 0x02 #define IXGBE_HICR_SV 0x04 /* Status Validity */ #define IXGBE_HICR_FW_RESET_ENABLE 0x40 #define IXGBE_HICR_FW_RESET 0x80 /* PCI-E registers */ #define IXGBE_GCR 0x11000 #define IXGBE_GTV 0x11004 #define IXGBE_FUNCTAG 0x11008 #define IXGBE_GLT 0x1100C #define IXGBE_PCIEPIPEADR 0x11004 #define IXGBE_PCIEPIPEDAT 0x11008 #define IXGBE_GSCL_1 0x11010 #define IXGBE_GSCL_2 0x11014 #define IXGBE_GSCL_3 0x11018 #define IXGBE_GSCL_4 0x1101C #define IXGBE_GSCN_0 0x11020 #define IXGBE_GSCN_1 0x11024 #define IXGBE_GSCN_2 0x11028 #define IXGBE_GSCN_3 0x1102C #define IXGBE_FACTPS 0x10150 #define IXGBE_FACTPS_X540 IXGBE_FACTPS #define IXGBE_FACTPS_X550 IXGBE_FACTPS #define IXGBE_FACTPS_X550EM_x IXGBE_FACTPS #define IXGBE_FACTPS_BY_MAC(_hw) IXGBE_FACTPS #define IXGBE_PCIEANACTL 0x11040 #define IXGBE_SWSM 0x10140 #define IXGBE_SWSM_X540 IXGBE_SWSM #define IXGBE_SWSM_X550 IXGBE_SWSM #define IXGBE_SWSM_X550EM_x IXGBE_SWSM #define IXGBE_SWSM_BY_MAC(_hw) IXGBE_SWSM #define IXGBE_FWSM 0x10148 #define IXGBE_FWSM_X540 IXGBE_FWSM #define IXGBE_FWSM_X550 IXGBE_FWSM #define IXGBE_FWSM_X550EM_x IXGBE_FWSM #define IXGBE_FWSM_BY_MAC(_hw) IXGBE_FWSM #define IXGBE_SWFW_SYNC IXGBE_GSSR #define IXGBE_SWFW_SYNC_X540 IXGBE_SWFW_SYNC #define IXGBE_SWFW_SYNC_X550 IXGBE_SWFW_SYNC #define IXGBE_SWFW_SYNC_X550EM_x IXGBE_SWFW_SYNC #define IXGBE_SWFW_SYNC_BY_MAC(_hw) IXGBE_SWFW_SYNC #define IXGBE_GSSR 0x10160 #define IXGBE_MREVID 0x11064 #define IXGBE_DCA_ID 0x11070 #define IXGBE_DCA_CTRL 0x11074 /* PCI-E registers 82599-Specific */ #define IXGBE_GCR_EXT 0x11050 #define IXGBE_GSCL_5_82599 0x11030 #define IXGBE_GSCL_6_82599 0x11034 #define IXGBE_GSCL_7_82599 0x11038 #define IXGBE_GSCL_8_82599 0x1103C #define IXGBE_PHYADR_82599 0x11040 #define IXGBE_PHYDAT_82599 0x11044 #define IXGBE_PHYCTL_82599 0x11048 #define IXGBE_PBACLR_82599 0x11068 #define IXGBE_CIAA 0x11088 #define IXGBE_CIAD 0x1108C #define IXGBE_CIAA_82599 IXGBE_CIAA #define IXGBE_CIAD_82599 IXGBE_CIAD #define IXGBE_CIAA_X540 IXGBE_CIAA #define IXGBE_CIAD_X540 IXGBE_CIAD #define IXGBE_CIAA_X550 0x11508 #define IXGBE_CIAD_X550 0x11510 #define IXGBE_CIAA_X550EM_x IXGBE_CIAA_X550 #define IXGBE_CIAD_X550EM_x IXGBE_CIAD_X550 #define IXGBE_CIAA_BY_MAC(_hw) IXGBE_BY_MAC((_hw), CIAA) #define IXGBE_CIAD_BY_MAC(_hw) IXGBE_BY_MAC((_hw), CIAD) #define IXGBE_PICAUSE 0x110B0 #define IXGBE_PIENA 0x110B8 #define IXGBE_CDQ_MBR_82599 0x110B4 #define IXGBE_PCIESPARE 0x110BC #define IXGBE_MISC_REG_82599 0x110F0 #define IXGBE_ECC_CTRL_0_82599 0x11100 #define IXGBE_ECC_CTRL_1_82599 0x11104 #define IXGBE_ECC_STATUS_82599 0x110E0 #define IXGBE_BAR_CTRL_82599 0x110F4 /* PCI Express Control */ #define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000 #define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000 #define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 #define IXGBE_GCR_CAP_VER2 0x00040000 #define IXGBE_GCR_EXT_MSIX_EN 0x80000000 #define IXGBE_GCR_EXT_BUFFERS_CLEAR 0x40000000 #define IXGBE_GCR_EXT_VT_MODE_16 0x00000001 #define IXGBE_GCR_EXT_VT_MODE_32 0x00000002 #define IXGBE_GCR_EXT_VT_MODE_64 0x00000003 #define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ IXGBE_GCR_EXT_VT_MODE_64) #define IXGBE_GCR_EXT_VT_MODE_MASK 0x00000003 /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ #define IXGBE_RXSTMPL 0x051E8 /* Rx timestamp Low - RO */ #define IXGBE_RXSTMPH 0x051A4 /* Rx timestamp High - RO */ #define IXGBE_RXSATRL 0x051A0 /* Rx timestamp attribute low - RO */ #define IXGBE_RXSATRH 0x051A8 /* Rx timestamp attribute high - RO */ #define IXGBE_RXMTRL 0x05120 /* RX message type register low - RW */ #define IXGBE_TXSTMPL 0x08C04 /* Tx timestamp value Low - RO */ #define IXGBE_TXSTMPH 0x08C08 /* Tx timestamp value High - RO */ #define IXGBE_SYSTIML 0x08C0C /* System time register Low - RO */ #define IXGBE_SYSTIMH 0x08C10 /* System time register High - RO */ #define IXGBE_SYSTIMR 0x08C58 /* System time register Residue - RO */ #define IXGBE_TIMINCA 0x08C14 /* Increment attributes register - RW */ #define IXGBE_TIMADJL 0x08C18 /* Time Adjustment Offset register Low - RW */ #define IXGBE_TIMADJH 0x08C1C /* Time Adjustment Offset register High - RW */ #define IXGBE_TSAUXC 0x08C20 /* TimeSync Auxiliary Control register - RW */ #define IXGBE_TRGTTIML0 0x08C24 /* Target Time Register 0 Low - RW */ #define IXGBE_TRGTTIMH0 0x08C28 /* Target Time Register 0 High - RW */ #define IXGBE_TRGTTIML1 0x08C2C /* Target Time Register 1 Low - RW */ #define IXGBE_TRGTTIMH1 0x08C30 /* Target Time Register 1 High - RW */ #define IXGBE_CLKTIML 0x08C34 /* Clock Out Time Register Low - RW */ #define IXGBE_CLKTIMH 0x08C38 /* Clock Out Time Register High - RW */ #define IXGBE_FREQOUT0 0x08C34 /* Frequency Out 0 Control register - RW */ #define IXGBE_FREQOUT1 0x08C38 /* Frequency Out 1 Control register - RW */ #define IXGBE_AUXSTMPL0 0x08C3C /* Auxiliary Time Stamp 0 register Low - RO */ #define IXGBE_AUXSTMPH0 0x08C40 /* Auxiliary Time Stamp 0 register High - RO */ #define IXGBE_AUXSTMPL1 0x08C44 /* Auxiliary Time Stamp 1 register Low - RO */ #define IXGBE_AUXSTMPH1 0x08C48 /* Auxiliary Time Stamp 1 register High - RO */ #define IXGBE_TSIM 0x08C68 /* TimeSync Interrupt Mask Register - RW */ #define IXGBE_TSICR 0x08C60 /* TimeSync Interrupt Cause Register - WO */ #define IXGBE_TSSDP 0x0003C /* TimeSync SDP Configuration Register - RW */ /* Diagnostic Registers */ #define IXGBE_RDSTATCTL 0x02C20 #define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ #define IXGBE_RDHMPN 0x02F08 #define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4)) #define IXGBE_RDPROBE 0x02F20 #define IXGBE_RDMAM 0x02F30 #define IXGBE_RDMAD 0x02F34 #define IXGBE_TDHMPN 0x07F08 #define IXGBE_TDHMPN2 0x082FC #define IXGBE_TXDESCIC 0x082CC #define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4)) #define IXGBE_TIC_DW2(_i) (0x082B0 + ((_i) * 4)) #define IXGBE_TDPROBE 0x07F20 #define IXGBE_TXBUFCTRL 0x0C600 #define IXGBE_TXBUFDATA0 0x0C610 #define IXGBE_TXBUFDATA1 0x0C614 #define IXGBE_TXBUFDATA2 0x0C618 #define IXGBE_TXBUFDATA3 0x0C61C #define IXGBE_RXBUFCTRL 0x03600 #define IXGBE_RXBUFDATA0 0x03610 #define IXGBE_RXBUFDATA1 0x03614 #define IXGBE_RXBUFDATA2 0x03618 #define IXGBE_RXBUFDATA3 0x0361C #define IXGBE_PCIE_DIAG(_i) (0x11090 + ((_i) * 4)) /* 8 of these */ #define IXGBE_RFVAL 0x050A4 #define IXGBE_MDFTC1 0x042B8 #define IXGBE_MDFTC2 0x042C0 #define IXGBE_MDFTFIFO1 0x042C4 #define IXGBE_MDFTFIFO2 0x042C8 #define IXGBE_MDFTS 0x042CC #define IXGBE_RXDATAWRPTR(_i) (0x03700 + ((_i) * 4)) /* 8 of these 3700-370C*/ #define IXGBE_RXDESCWRPTR(_i) (0x03710 + ((_i) * 4)) /* 8 of these 3710-371C*/ #define IXGBE_RXDATARDPTR(_i) (0x03720 + ((_i) * 4)) /* 8 of these 3720-372C*/ #define IXGBE_RXDESCRDPTR(_i) (0x03730 + ((_i) * 4)) /* 8 of these 3730-373C*/ #define IXGBE_TXDATAWRPTR(_i) (0x0C700 + ((_i) * 4)) /* 8 of these C700-C70C*/ #define IXGBE_TXDESCWRPTR(_i) (0x0C710 + ((_i) * 4)) /* 8 of these C710-C71C*/ #define IXGBE_TXDATARDPTR(_i) (0x0C720 + ((_i) * 4)) /* 8 of these C720-C72C*/ #define IXGBE_TXDESCRDPTR(_i) (0x0C730 + ((_i) * 4)) /* 8 of these C730-C73C*/ #define IXGBE_PCIEECCCTL 0x1106C #define IXGBE_RXWRPTR(_i) (0x03100 + ((_i) * 4)) /* 8 of these 3100-310C*/ #define IXGBE_RXUSED(_i) (0x03120 + ((_i) * 4)) /* 8 of these 3120-312C*/ #define IXGBE_RXRDPTR(_i) (0x03140 + ((_i) * 4)) /* 8 of these 3140-314C*/ #define IXGBE_RXRDWRPTR(_i) (0x03160 + ((_i) * 4)) /* 8 of these 3160-310C*/ #define IXGBE_TXWRPTR(_i) (0x0C100 + ((_i) * 4)) /* 8 of these C100-C10C*/ #define IXGBE_TXUSED(_i) (0x0C120 + ((_i) * 4)) /* 8 of these C120-C12C*/ #define IXGBE_TXRDPTR(_i) (0x0C140 + ((_i) * 4)) /* 8 of these C140-C14C*/ #define IXGBE_TXRDWRPTR(_i) (0x0C160 + ((_i) * 4)) /* 8 of these C160-C10C*/ #define IXGBE_PCIEECCCTL0 0x11100 #define IXGBE_PCIEECCCTL1 0x11104 #define IXGBE_RXDBUECC 0x03F70 #define IXGBE_TXDBUECC 0x0CF70 #define IXGBE_RXDBUEST 0x03F74 #define IXGBE_TXDBUEST 0x0CF74 #define IXGBE_PBTXECC 0x0C300 #define IXGBE_PBRXECC 0x03300 #define IXGBE_GHECCR 0x110B0 /* MAC Registers */ #define IXGBE_PCS1GCFIG 0x04200 #define IXGBE_PCS1GLCTL 0x04208 #define IXGBE_PCS1GLSTA 0x0420C #define IXGBE_PCS1GDBG0 0x04210 #define IXGBE_PCS1GDBG1 0x04214 #define IXGBE_PCS1GANA 0x04218 #define IXGBE_PCS1GANLP 0x0421C #define IXGBE_PCS1GANNP 0x04220 #define IXGBE_PCS1GANLPNP 0x04224 #define IXGBE_HLREG0 0x04240 #define IXGBE_HLREG1 0x04244 #define IXGBE_PAP 0x04248 #define IXGBE_MACA 0x0424C #define IXGBE_APAE 0x04250 #define IXGBE_ARD 0x04254 #define IXGBE_AIS 0x04258 #define IXGBE_MSCA 0x0425C #define IXGBE_MSRWD 0x04260 #define IXGBE_MLADD 0x04264 #define IXGBE_MHADD 0x04268 #define IXGBE_MAXFRS 0x04268 #define IXGBE_TREG 0x0426C #define IXGBE_PCSS1 0x04288 #define IXGBE_PCSS2 0x0428C #define IXGBE_XPCSS 0x04290 #define IXGBE_MFLCN 0x04294 #define IXGBE_SERDESC 0x04298 #define IXGBE_MACS 0x0429C #define IXGBE_AUTOC 0x042A0 #define IXGBE_LINKS 0x042A4 #define IXGBE_LINKS2 0x04324 #define IXGBE_AUTOC2 0x042A8 #define IXGBE_AUTOC3 0x042AC #define IXGBE_ANLP1 0x042B0 #define IXGBE_ANLP2 0x042B4 #define IXGBE_MACC 0x04330 #define IXGBE_ATLASCTL 0x04800 #define IXGBE_MMNGC 0x042D0 #define IXGBE_ANLPNP1 0x042D4 #define IXGBE_ANLPNP2 0x042D8 #define IXGBE_KRPCSFC 0x042E0 #define IXGBE_KRPCSS 0x042E4 #define IXGBE_FECS1 0x042E8 #define IXGBE_FECS2 0x042EC #define IXGBE_SMADARCTL 0x14F10 #define IXGBE_MPVC 0x04318 #define IXGBE_SGMIIC 0x04314 /* Statistics Registers */ #define IXGBE_RXNFGPC 0x041B0 #define IXGBE_RXNFGBCL 0x041B4 #define IXGBE_RXNFGBCH 0x041B8 #define IXGBE_RXDGPC 0x02F50 #define IXGBE_RXDGBCL 0x02F54 #define IXGBE_RXDGBCH 0x02F58 #define IXGBE_RXDDGPC 0x02F5C #define IXGBE_RXDDGBCL 0x02F60 #define IXGBE_RXDDGBCH 0x02F64 #define IXGBE_RXLPBKGPC 0x02F68 #define IXGBE_RXLPBKGBCL 0x02F6C #define IXGBE_RXLPBKGBCH 0x02F70 #define IXGBE_RXDLPBKGPC 0x02F74 #define IXGBE_RXDLPBKGBCL 0x02F78 #define IXGBE_RXDLPBKGBCH 0x02F7C #define IXGBE_TXDGPC 0x087A0 #define IXGBE_TXDGBCL 0x087A4 #define IXGBE_TXDGBCH 0x087A8 #define IXGBE_RXDSTATCTRL 0x02F40 /* Copper Pond 2 link timeout */ #define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50 /* Omer CORECTL */ #define IXGBE_CORECTL 0x014F00 /* BARCTRL */ #define IXGBE_BARCTRL 0x110F4 #define IXGBE_BARCTRL_FLSIZE 0x0700 #define IXGBE_BARCTRL_FLSIZE_SHIFT 8 #define IXGBE_BARCTRL_CSRSIZE 0x2000 /* RSCCTL Bit Masks */ #define IXGBE_RSCCTL_RSCEN 0x01 #define IXGBE_RSCCTL_MAXDESC_1 0x00 #define IXGBE_RSCCTL_MAXDESC_4 0x04 #define IXGBE_RSCCTL_MAXDESC_8 0x08 #define IXGBE_RSCCTL_MAXDESC_16 0x0C #define IXGBE_RSCCTL_TS_DIS 0x02 /* RSCDBU Bit Masks */ #define IXGBE_RSCDBU_RSCSMALDIS_MASK 0x0000007F #define IXGBE_RSCDBU_RSCACKDIS 0x00000080 /* RDRXCTL Bit Masks */ #define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min THLD Size */ #define IXGBE_RDRXCTL_CRCSTRIP 0x00000002 /* CRC Strip */ #define IXGBE_RDRXCTL_PSP 0x00000004 /* Pad Small Packet */ #define IXGBE_RDRXCTL_MVMEN 0x00000020 #define IXGBE_RDRXCTL_RSC_PUSH_DIS 0x00000020 #define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */ #define IXGBE_RDRXCTL_RSC_PUSH 0x00000080 #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ #define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */ #define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI*/ #define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC ena */ #define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC ena */ #define IXGBE_RDRXCTL_MBINTEN 0x10000000 #define IXGBE_RDRXCTL_MDP_EN 0x20000000 /* RQTC Bit Masks and Shifts */ #define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4) #define IXGBE_RQTC_TC0_MASK (0x7 << 0) #define IXGBE_RQTC_TC1_MASK (0x7 << 4) #define IXGBE_RQTC_TC2_MASK (0x7 << 8) #define IXGBE_RQTC_TC3_MASK (0x7 << 12) #define IXGBE_RQTC_TC4_MASK (0x7 << 16) #define IXGBE_RQTC_TC5_MASK (0x7 << 20) #define IXGBE_RQTC_TC6_MASK (0x7 << 24) #define IXGBE_RQTC_TC7_MASK (0x7 << 28) /* PSRTYPE.RQPL Bit masks and shift */ #define IXGBE_PSRTYPE_RQPL_MASK 0x7 #define IXGBE_PSRTYPE_RQPL_SHIFT 29 /* CTRL Bit Masks */ #define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */ #define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */ #define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */ #define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST) /* FACTPS */ #define IXGBE_FACTPS_MNGCG 0x20000000 /* Manageblility Clock Gated */ #define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */ /* MHADD Bit Masks */ #define IXGBE_MHADD_MFS_MASK 0xFFFF0000 #define IXGBE_MHADD_MFS_SHIFT 16 /* Extended Device Control */ #define IXGBE_CTRL_EXT_PFRSTD 0x00004000 /* Physical Function Reset Done */ #define IXGBE_CTRL_EXT_NS_DIS 0x00010000 /* No Snoop disable */ #define IXGBE_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define IXGBE_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ /* Direct Cache Access (DCA) definitions */ #define IXGBE_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ #define IXGBE_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ #define IXGBE_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ #define IXGBE_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ #define IXGBE_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_MASK_82599 0xFF000000 /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599 24 /* Rx CPUID Shift */ #define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* Rx Desc enable */ #define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* Rx Desc header ena */ #define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* Rx Desc payload ena */ #define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* Rx rd Desc Relax Order */ #define IXGBE_DCA_RXCTRL_DATA_WRO_EN (1 << 13) /* Rx wr data Relax Order */ #define IXGBE_DCA_RXCTRL_HEAD_WRO_EN (1 << 15) /* Rx wr header RO */ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_MASK_82599 0xFF000000 /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599 24 /* Tx CPUID Shift */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ #define IXGBE_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define IXGBE_DCA_TXCTRL_DESC_WRO_EN (1 << 11) /* Tx Desc writeback RO bit */ #define IXGBE_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ #define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */ /* MSCA Bit Masks */ #define IXGBE_MSCA_NP_ADDR_MASK 0x0000FFFF /* MDI Addr (new prot) */ #define IXGBE_MSCA_NP_ADDR_SHIFT 0 #define IXGBE_MSCA_DEV_TYPE_MASK 0x001F0000 /* Dev Type (new prot) */ #define IXGBE_MSCA_DEV_TYPE_SHIFT 16 /* Register Address (old prot */ #define IXGBE_MSCA_PHY_ADDR_MASK 0x03E00000 /* PHY Address mask */ #define IXGBE_MSCA_PHY_ADDR_SHIFT 21 /* PHY Address shift*/ #define IXGBE_MSCA_OP_CODE_MASK 0x0C000000 /* OP CODE mask */ #define IXGBE_MSCA_OP_CODE_SHIFT 26 /* OP CODE shift */ #define IXGBE_MSCA_ADDR_CYCLE 0x00000000 /* OP CODE 00 (addr cycle) */ #define IXGBE_MSCA_WRITE 0x04000000 /* OP CODE 01 (wr) */ #define IXGBE_MSCA_READ 0x0C000000 /* OP CODE 11 (rd) */ #define IXGBE_MSCA_READ_AUTOINC 0x08000000 /* OP CODE 10 (rd auto inc)*/ #define IXGBE_MSCA_ST_CODE_MASK 0x30000000 /* ST Code mask */ #define IXGBE_MSCA_ST_CODE_SHIFT 28 /* ST Code shift */ #define IXGBE_MSCA_NEW_PROTOCOL 0x00000000 /* ST CODE 00 (new prot) */ #define IXGBE_MSCA_OLD_PROTOCOL 0x10000000 /* ST CODE 01 (old prot) */ #define IXGBE_MSCA_MDI_COMMAND 0x40000000 /* Initiate MDI command */ #define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress ena */ /* MSRWD bit masks */ #define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF #define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 #define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 #define IXGBE_MSRWD_READ_DATA_SHIFT 16 /* Atlas registers */ #define IXGBE_ATLAS_PDN_LPBK 0x24 #define IXGBE_ATLAS_PDN_10G 0xB #define IXGBE_ATLAS_PDN_1G 0xC #define IXGBE_ATLAS_PDN_AN 0xD /* Atlas bit masks */ #define IXGBE_ATLASCTL_WRITE_CMD 0x00010000 #define IXGBE_ATLAS_PDN_TX_REG_EN 0x10 #define IXGBE_ATLAS_PDN_TX_10G_QL_ALL 0xF0 #define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0 #define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0 /* Omer bit masks */ #define IXGBE_CORECTL_WRITE_CMD 0x00010000 /* Device Type definitions for new protocol MDIO commands */ #define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 #define IXGBE_MDIO_PCS_DEV_TYPE 0x3 #define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ #define IXGBE_TWINAX_DEV 1 #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Ctrl Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0-10G, 1-1G */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010 #define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */ #define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT 0xC800 /* AUTO_NEG Vendor Status Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM 0xCC00 /* AUTO_NEG Vendor TX Reg */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */ #define IXGBE_MDIO_AUTO_NEG_VEN_LSC 0x1 /* AUTO_NEG Vendor Tx LSC */ #define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */ #define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */ #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT 0x3C /* AUTO_NEG EEE Advt Reg */ #define IXGBE_AUTO_NEG_10GBASE_EEE_ADVT 0x8 /* AUTO NEG EEE 10GBaseT Advt */ #define IXGBE_AUTO_NEG_1000BASE_EEE_ADVT 0x4 /* AUTO NEG EEE 1000BaseT Advt */ #define IXGBE_AUTO_NEG_100BASE_EEE_ADVT 0x2 /* AUTO NEG EEE 100BaseT Advt */ #define IXGBE_MDIO_PHY_XS_CONTROL 0x0 /* PHY_XS Control Reg */ #define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */ #define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ #define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ #define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */ #define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */ #define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */ #define IXGBE_MDIO_PHY_SPEED_100M 0x0020 /* 100M capable */ #define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */ #define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ #define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ #define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */ #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */ #define IXGBE_AUTO_NEG_LP_STATUS 0xE820 /* AUTO NEG Rx LP Status Reg */ #define IXGBE_AUTO_NEG_LP_1000BASE_CAP 0x8000 /* AUTO NEG Rx LP 1000BaseT Cap */ #define IXGBE_AUTO_NEG_LP_10GBASE_CAP 0x0800 /* AUTO NEG Rx LP 10GBaseT Cap */ #define IXGBE_AUTO_NEG_10GBASET_STAT 0x0021 /* AUTO NEG 10G BaseT Stat */ #define IXGBE_MDIO_TX_VENDOR_ALARMS_3 0xCC02 /* Vendor Alarms 3 Reg */ #define IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK 0x3 /* PHY Reset Complete Mask */ #define IXGBE_MDIO_GLOBAL_RES_PR_10 0xC479 /* Global Resv Provisioning 10 Reg */ #define IXGBE_MDIO_POWER_UP_STALL 0x8000 /* Power Up Stall */ #define IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK 0xFF00 /* int std mask */ #define IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG 0xFC00 /* chip std int flag */ #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK 0xFF01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG 0xFC01 /* int chip-wide mask */ #define IXGBE_MDIO_GLOBAL_ALARM_1 0xCC00 /* Global alarm 1 */ #define IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL 0x4000 /* high temp failure */ #define IXGBE_MDIO_GLOBAL_INT_MASK 0xD400 /* Global int mask */ #define IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN 0x1000 /* autoneg vendor alarm int enable */ #define IXGBE_MDIO_GLOBAL_ALARM_1_INT 0x4 /* int in Global alarm 1 */ #define IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN 0x1 /* vendor alarm int enable */ #define IXGBE_MDIO_GLOBAL_STD_ALM2_INT 0x200 /* vendor alarm2 int mask */ #define IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN 0x4000 /* int high temp enable */ #define IXGBE_MDIO_PMA_PMD_CONTROL_ADDR 0x0000 /* PMA/PMD Control Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ #define IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK 0xD401 /* PHY TX Vendor LASI */ #define IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN 0x1 /* PHY TX Vendor LASI enable */ #define IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR 0x9 /* Standard Transmit Dis Reg */ #define IXGBE_MDIO_PMD_GLOBAL_TX_DISABLE 0x0001 /* PMD Global Transmit Dis */ #define IXGBE_PCRC8ECL 0x0E810 /* PCR CRC-8 Error Count Lo */ #define IXGBE_PCRC8ECH 0x0E811 /* PCR CRC-8 Error Count Hi */ #define IXGBE_PCRC8ECH_MASK 0x1F #define IXGBE_LDPCECL 0x0E820 /* PCR Uncorrected Error Count Lo */ #define IXGBE_LDPCECH 0x0E821 /* PCR Uncorrected Error Count Hi */ /* MII clause 22/28 definitions */ #define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 #define IXGBE_MDIO_XENPAK_LASI_STATUS 0x9005 /* XENPAK LASI Status register*/ #define IXGBE_XENPAK_LASI_LINK_STATUS_ALARM 0x1 /* Link Status Alarm change */ #define IXGBE_MDIO_AUTO_NEG_LINK_STATUS 0x4 /* Indicates if link is up */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK 0x7 /* Speed/Duplex Mask */ #define IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK 0x6 /* Speed Mask */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_HALF 0x0 /* 10Mb/s Half Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10M_FULL 0x1 /* 10Mb/s Full Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_100M_HALF 0x2 /* 100Mb/s Half Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_100M_FULL 0x3 /* 100Mb/s Full Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_HALF 0x4 /* 1Gb/s Half Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL 0x5 /* 1Gb/s Full Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_HALF 0x6 /* 10Gb/s Half Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL 0x7 /* 10Gb/s Full Duplex */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB 0x4 /* 1Gb/s */ #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB 0x6 /* 10Gb/s */ #define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */ #define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ #define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ #define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */ #define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/ #define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/ #define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/ #define IXGBE_MII_2_5GBASE_T_ADVERTISE 0x0400 #define IXGBE_MII_5GBASE_T_ADVERTISE 0x0800 #define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */ #define IXGBE_MII_100BASE_T_ADVERTISE_HALF 0x0080 /* half duplex, bit:7 */ #define IXGBE_MII_RESTART 0x200 #define IXGBE_MII_AUTONEG_COMPLETE 0x20 #define IXGBE_MII_AUTONEG_LINK_UP 0x04 #define IXGBE_MII_AUTONEG_REG 0x0 #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 /* PHY IDs*/ #define TN1010_PHY_ID 0x00A19410 #define TNX_FW_REV 0xB #define X540_PHY_ID 0x01540200 #define X550_PHY_ID1 0x01540220 #define X550_PHY_ID2 0x01540223 #define X550_PHY_ID3 0x01540221 #define X557_PHY_ID 0x01540240 #define AQ_FW_REV 0x20 #define QT2022_PHY_ID 0x0043A400 #define ATH_PHY_ID 0x03429050 /* PHY Types */ #define IXGBE_M88E1145_E_PHY_ID 0x01410CD0 /* Special PHY Init Routine */ #define IXGBE_PHY_INIT_OFFSET_NL 0x002B #define IXGBE_PHY_INIT_END_NL 0xFFFF #define IXGBE_CONTROL_MASK_NL 0xF000 #define IXGBE_DATA_MASK_NL 0x0FFF #define IXGBE_CONTROL_SHIFT_NL 12 #define IXGBE_DELAY_NL 0 #define IXGBE_DATA_NL 1 #define IXGBE_CONTROL_NL 0x000F #define IXGBE_CONTROL_EOL_NL 0x0FFF #define IXGBE_CONTROL_SOL_NL 0x0000 /* General purpose Interrupt Enable */ #define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ #define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */ #define IXGBE_SDP2_GPIEN 0x00000004 /* SDP2 */ #define IXGBE_SDP0_GPIEN_X540 0x00000002 /* SDP0 on X540 and X550 */ #define IXGBE_SDP1_GPIEN_X540 0x00000004 /* SDP1 on X540 and X550 */ #define IXGBE_SDP2_GPIEN_X540 0x00000008 /* SDP2 on X540 and X550 */ #define IXGBE_SDP0_GPIEN_X550 IXGBE_SDP0_GPIEN_X540 #define IXGBE_SDP1_GPIEN_X550 IXGBE_SDP1_GPIEN_X540 #define IXGBE_SDP2_GPIEN_X550 IXGBE_SDP2_GPIEN_X540 #define IXGBE_SDP0_GPIEN_X550EM_x IXGBE_SDP0_GPIEN_X540 #define IXGBE_SDP1_GPIEN_X550EM_x IXGBE_SDP1_GPIEN_X540 #define IXGBE_SDP2_GPIEN_X550EM_x IXGBE_SDP2_GPIEN_X540 #define IXGBE_SDP0_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP0_GPIEN) #define IXGBE_SDP1_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP1_GPIEN) #define IXGBE_SDP2_GPIEN_BY_MAC(_hw) IXGBE_BY_MAC((_hw), SDP2_GPIEN) #define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ #define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ #define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ #define IXGBE_GPIE_EIAME 0x40000000 #define IXGBE_GPIE_PBA_SUPPORT 0x80000000 #define IXGBE_GPIE_RSC_DELAY_SHIFT 11 #define IXGBE_GPIE_VTMODE_MASK 0x0000C000 /* VT Mode Mask */ #define IXGBE_GPIE_VTMODE_16 0x00004000 /* 16 VFs 8 queues per VF */ #define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */ #define IXGBE_GPIE_VTMODE_64 0x0000C000 /* 64 VFs 2 queues per VF */ /* Packet Buffer Initialization */ #define IXGBE_MAX_PACKET_BUFFERS 8 #define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */ #define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */ #define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */ #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ #define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */ #define IXGBE_RXPBSIZE_MAX 0x00080000 /* 512KB Packet Buffer */ #define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer */ #define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */ #define IXGBE_MAX_PB 8 /* Packet buffer allocation strategies */ enum { PBA_STRATEGY_EQUAL = 0, /* Distribute PB space equally */ #define PBA_STRATEGY_EQUAL PBA_STRATEGY_EQUAL PBA_STRATEGY_WEIGHTED = 1, /* Weight front half of TCs */ #define PBA_STRATEGY_WEIGHTED PBA_STRATEGY_WEIGHTED }; /* Transmit Flow Control status */ #define IXGBE_TFCS_TXOFF 0x00000001 #define IXGBE_TFCS_TXOFF0 0x00000100 #define IXGBE_TFCS_TXOFF1 0x00000200 #define IXGBE_TFCS_TXOFF2 0x00000400 #define IXGBE_TFCS_TXOFF3 0x00000800 #define IXGBE_TFCS_TXOFF4 0x00001000 #define IXGBE_TFCS_TXOFF5 0x00002000 #define IXGBE_TFCS_TXOFF6 0x00004000 #define IXGBE_TFCS_TXOFF7 0x00008000 /* TCP Timer */ #define IXGBE_TCPTIMER_KS 0x00000100 #define IXGBE_TCPTIMER_COUNT_ENABLE 0x00000200 #define IXGBE_TCPTIMER_COUNT_FINISH 0x00000400 #define IXGBE_TCPTIMER_LOOP 0x00000800 #define IXGBE_TCPTIMER_DURATION_MASK 0x000000FF /* HLREG0 Bit Masks */ #define IXGBE_HLREG0_TXCRCEN 0x00000001 /* bit 0 */ #define IXGBE_HLREG0_RXCRCSTRP 0x00000002 /* bit 1 */ #define IXGBE_HLREG0_JUMBOEN 0x00000004 /* bit 2 */ #define IXGBE_HLREG0_TXPADEN 0x00000400 /* bit 10 */ #define IXGBE_HLREG0_TXPAUSEEN 0x00001000 /* bit 12 */ #define IXGBE_HLREG0_RXPAUSEEN 0x00004000 /* bit 14 */ #define IXGBE_HLREG0_LPBK 0x00008000 /* bit 15 */ #define IXGBE_HLREG0_MDCSPD 0x00010000 /* bit 16 */ #define IXGBE_HLREG0_CONTMDC 0x00020000 /* bit 17 */ #define IXGBE_HLREG0_CTRLFLTR 0x00040000 /* bit 18 */ #define IXGBE_HLREG0_PREPEND 0x00F00000 /* bits 20-23 */ #define IXGBE_HLREG0_PRIPAUSEEN 0x01000000 /* bit 24 */ #define IXGBE_HLREG0_RXPAUSERECDA 0x06000000 /* bits 25-26 */ #define IXGBE_HLREG0_RXLNGTHERREN 0x08000000 /* bit 27 */ #define IXGBE_HLREG0_RXPADSTRIPEN 0x10000000 /* bit 28 */ /* VMD_CTL bitmasks */ #define IXGBE_VMD_CTL_VMDQ_EN 0x00000001 #define IXGBE_VMD_CTL_VMDQ_FILTER 0x00000002 /* VT_CTL bitmasks */ #define IXGBE_VT_CTL_DIS_DEFPL 0x20000000 /* disable default pool */ #define IXGBE_VT_CTL_REPLEN 0x40000000 /* replication enabled */ #define IXGBE_VT_CTL_VT_ENABLE 0x00000001 /* Enable VT Mode */ #define IXGBE_VT_CTL_POOL_SHIFT 7 #define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT) /* VMOLR bitmasks */ #define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */ #define IXGBE_VMOLR_ROMPE 0x02000000 /* accept packets in MTA tbl */ #define IXGBE_VMOLR_ROPE 0x04000000 /* accept packets in UC tbl */ #define IXGBE_VMOLR_BAM 0x08000000 /* accept broadcast packets */ #define IXGBE_VMOLR_MPE 0x10000000 /* multicast promiscuous */ /* VFRE bitmask */ #define IXGBE_VFRE_ENABLE_ALL 0xFFFFFFFF #define IXGBE_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ /* RDHMPN and TDHMPN bitmasks */ #define IXGBE_RDHMPN_RDICADDR 0x007FF800 #define IXGBE_RDHMPN_RDICRDREQ 0x00800000 #define IXGBE_RDHMPN_RDICADDR_SHIFT 11 #define IXGBE_TDHMPN_TDICADDR 0x003FF800 #define IXGBE_TDHMPN_TDICRDREQ 0x00800000 #define IXGBE_TDHMPN_TDICADDR_SHIFT 11 #define IXGBE_RDMAM_MEM_SEL_SHIFT 13 #define IXGBE_RDMAM_DWORD_SHIFT 9 #define IXGBE_RDMAM_DESC_COMP_FIFO 1 #define IXGBE_RDMAM_DFC_CMD_FIFO 2 #define IXGBE_RDMAM_RSC_HEADER_ADDR 3 #define IXGBE_RDMAM_TCN_STATUS_RAM 4 #define IXGBE_RDMAM_WB_COLL_FIFO 5 #define IXGBE_RDMAM_QSC_CNT_RAM 6 #define IXGBE_RDMAM_QSC_FCOE_RAM 7 #define IXGBE_RDMAM_QSC_QUEUE_CNT 8 #define IXGBE_RDMAM_QSC_QUEUE_RAM 0xA #define IXGBE_RDMAM_QSC_RSC_RAM 0xB #define IXGBE_RDMAM_DESC_COM_FIFO_RANGE 135 #define IXGBE_RDMAM_DESC_COM_FIFO_COUNT 4 #define IXGBE_RDMAM_DFC_CMD_FIFO_RANGE 48 #define IXGBE_RDMAM_DFC_CMD_FIFO_COUNT 7 #define IXGBE_RDMAM_RSC_HEADER_ADDR_RANGE 32 #define IXGBE_RDMAM_RSC_HEADER_ADDR_COUNT 4 #define IXGBE_RDMAM_TCN_STATUS_RAM_RANGE 256 #define IXGBE_RDMAM_TCN_STATUS_RAM_COUNT 9 #define IXGBE_RDMAM_WB_COLL_FIFO_RANGE 8 #define IXGBE_RDMAM_WB_COLL_FIFO_COUNT 4 #define IXGBE_RDMAM_QSC_CNT_RAM_RANGE 64 #define IXGBE_RDMAM_QSC_CNT_RAM_COUNT 4 #define IXGBE_RDMAM_QSC_FCOE_RAM_RANGE 512 #define IXGBE_RDMAM_QSC_FCOE_RAM_COUNT 5 #define IXGBE_RDMAM_QSC_QUEUE_CNT_RANGE 32 #define IXGBE_RDMAM_QSC_QUEUE_CNT_COUNT 4 #define IXGBE_RDMAM_QSC_QUEUE_RAM_RANGE 128 #define IXGBE_RDMAM_QSC_QUEUE_RAM_COUNT 8 #define IXGBE_RDMAM_QSC_RSC_RAM_RANGE 32 #define IXGBE_RDMAM_QSC_RSC_RAM_COUNT 8 #define IXGBE_TXDESCIC_READY 0x80000000 /* Receive Checksum Control */ #define IXGBE_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define IXGBE_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* FCRTL Bit Masks */ #define IXGBE_FCRTL_XONE 0x80000000 /* XON enable */ #define IXGBE_FCRTH_FCEN 0x80000000 /* Packet buffer fc enable */ /* PAP bit masks*/ #define IXGBE_PAP_TXPAUSECNT_MASK 0x0000FFFF /* Pause counter mask */ /* RMCS Bit Masks */ #define IXGBE_RMCS_RRM 0x00000002 /* Rx Recycle Mode enable */ /* Receive Arbitration Control: 0 Round Robin, 1 DFP */ #define IXGBE_RMCS_RAC 0x00000004 /* Deficit Fixed Prio ena */ #define IXGBE_RMCS_DFP IXGBE_RMCS_RAC #define IXGBE_RMCS_TFCE_802_3X 0x00000008 /* Tx Priority FC ena */ #define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority FC ena */ #define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */ /* FCCFG Bit Masks */ #define IXGBE_FCCFG_TFCE_802_3X 0x00000008 /* Tx link FC enable */ #define IXGBE_FCCFG_TFCE_PRIORITY 0x00000010 /* Tx priority FC enable */ /* Interrupt register bitmasks */ /* Extended Interrupt Cause Read */ #define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ #define IXGBE_EICR_FLOW_DIR 0x00010000 /* FDir Exception */ #define IXGBE_EICR_RX_MISS 0x00020000 /* Packet Buffer Overrun */ #define IXGBE_EICR_PCI 0x00040000 /* PCI Exception */ #define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */ #define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */ #define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */ #define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */ #define IXGBE_EICR_TS 0x00800000 /* Thermal Sensor Event */ #define IXGBE_EICR_TIMESYNC 0x01000000 /* Timesync Event */ #define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ #define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */ #define IXGBE_EICR_GPI_SDP2 0x04000000 /* Gen Purpose Interrupt on SDP2 */ #define IXGBE_EICR_ECC 0x10000000 /* ECC Error */ #define IXGBE_EICR_GPI_SDP0_X540 0x02000000 /* Gen Purpose Interrupt on SDP0 */ #define IXGBE_EICR_GPI_SDP1_X540 0x04000000 /* Gen Purpose Interrupt on SDP1 */ #define IXGBE_EICR_GPI_SDP2_X540 0x08000000 /* Gen Purpose Interrupt on SDP2 */ #define IXGBE_EICR_GPI_SDP0_X550 IXGBE_EICR_GPI_SDP0_X540 #define IXGBE_EICR_GPI_SDP1_X550 IXGBE_EICR_GPI_SDP1_X540 #define IXGBE_EICR_GPI_SDP2_X550 IXGBE_EICR_GPI_SDP2_X540 #define IXGBE_EICR_GPI_SDP0_X550EM_x IXGBE_EICR_GPI_SDP0_X540 #define IXGBE_EICR_GPI_SDP1_X550EM_x IXGBE_EICR_GPI_SDP1_X540 #define IXGBE_EICR_GPI_SDP2_X550EM_x IXGBE_EICR_GPI_SDP2_X540 #define IXGBE_EICR_GPI_SDP0_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP0) #define IXGBE_EICR_GPI_SDP1_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP1) #define IXGBE_EICR_GPI_SDP2_BY_MAC(_hw) IXGBE_BY_MAC((_hw), EICR_GPI_SDP2) #define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */ #define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */ #define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define IXGBE_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ /* Extended Interrupt Cause Set */ #define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EICS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EICS_RX_MISS IXGBE_EICR_RX_MISS /* Pkt Buffer Overrun */ #define IXGBE_EICS_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EICS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */ #define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EICS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EICS_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EICS_GPI_SDP0_BY_MAC(_hw) IXGBE_EICR_GPI_SDP0_BY_MAC(_hw) #define IXGBE_EICS_GPI_SDP1_BY_MAC(_hw) IXGBE_EICR_GPI_SDP1_BY_MAC(_hw) #define IXGBE_EICS_GPI_SDP2_BY_MAC(_hw) IXGBE_EICR_GPI_SDP2_BY_MAC(_hw) #define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */ #define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ /* Extended Interrupt Mask Set */ #define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EIMS_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */ #define IXGBE_EIMS_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EIMS_TS IXGBE_EICR_TS /* Thermal Sensor Event */ #define IXGBE_EIMS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */ #define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EIMS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EIMS_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EIMS_GPI_SDP0_BY_MAC(_hw) IXGBE_EICR_GPI_SDP0_BY_MAC(_hw) #define IXGBE_EIMS_GPI_SDP1_BY_MAC(_hw) IXGBE_EICR_GPI_SDP1_BY_MAC(_hw) #define IXGBE_EIMS_GPI_SDP2_BY_MAC(_hw) IXGBE_EICR_GPI_SDP2_BY_MAC(_hw) #define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */ #define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ /* Extended Interrupt Mask Clear */ #define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMC_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EIMC_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */ #define IXGBE_EIMC_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EIMC_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */ #define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EIMC_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EIMC_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EIMC_GPI_SDP0_BY_MAC(_hw) IXGBE_EICR_GPI_SDP0_BY_MAC(_hw) #define IXGBE_EIMC_GPI_SDP1_BY_MAC(_hw) IXGBE_EICR_GPI_SDP1_BY_MAC(_hw) #define IXGBE_EIMC_GPI_SDP2_BY_MAC(_hw) IXGBE_EICR_GPI_SDP2_BY_MAC(_hw) #define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */ #define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ #define IXGBE_EIMS_ENABLE_MASK ( \ IXGBE_EIMS_RTX_QUEUE | \ IXGBE_EIMS_LSC | \ IXGBE_EIMS_TCP_TIMER | \ IXGBE_EIMS_OTHER) /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ #define IXGBE_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ #define IXGBE_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ #define IXGBE_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ #define IXGBE_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */ #define IXGBE_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */ #define IXGBE_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */ #define IXGBE_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */ #define IXGBE_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */ #define IXGBE_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */ #define IXGBE_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of control bits */ #define IXGBE_IMIR_SIZE_BP_82599 0x00001000 /* Packet size bypass */ #define IXGBE_IMIR_CTRL_URG_82599 0x00002000 /* Check URG bit in header */ #define IXGBE_IMIR_CTRL_ACK_82599 0x00004000 /* Check ACK bit in header */ #define IXGBE_IMIR_CTRL_PSH_82599 0x00008000 /* Check PSH bit in header */ #define IXGBE_IMIR_CTRL_RST_82599 0x00010000 /* Check RST bit in header */ #define IXGBE_IMIR_CTRL_SYN_82599 0x00020000 /* Check SYN bit in header */ #define IXGBE_IMIR_CTRL_FIN_82599 0x00040000 /* Check FIN bit in header */ #define IXGBE_IMIR_CTRL_BP_82599 0x00080000 /* Bypass chk of ctrl bits */ #define IXGBE_IMIR_LLI_EN_82599 0x00100000 /* Enables low latency Int */ #define IXGBE_IMIR_RX_QUEUE_MASK_82599 0x0000007F /* Rx Queue Mask */ #define IXGBE_IMIR_RX_QUEUE_SHIFT_82599 21 /* Rx Queue Shift */ #define IXGBE_IMIRVP_PRIORITY_MASK 0x00000007 /* VLAN priority mask */ #define IXGBE_IMIRVP_PRIORITY_EN 0x00000008 /* VLAN priority enable */ #define IXGBE_MAX_FTQF_FILTERS 128 #define IXGBE_FTQF_PROTOCOL_MASK 0x00000003 #define IXGBE_FTQF_PROTOCOL_TCP 0x00000000 #define IXGBE_FTQF_PROTOCOL_UDP 0x00000001 #define IXGBE_FTQF_PROTOCOL_SCTP 2 #define IXGBE_FTQF_PRIORITY_MASK 0x00000007 #define IXGBE_FTQF_PRIORITY_SHIFT 2 #define IXGBE_FTQF_POOL_MASK 0x0000003F #define IXGBE_FTQF_POOL_SHIFT 8 #define IXGBE_FTQF_5TUPLE_MASK_MASK 0x0000001F #define IXGBE_FTQF_5TUPLE_MASK_SHIFT 25 #define IXGBE_FTQF_SOURCE_ADDR_MASK 0x1E #define IXGBE_FTQF_DEST_ADDR_MASK 0x1D #define IXGBE_FTQF_SOURCE_PORT_MASK 0x1B #define IXGBE_FTQF_DEST_PORT_MASK 0x17 #define IXGBE_FTQF_PROTOCOL_COMP_MASK 0x0F #define IXGBE_FTQF_POOL_MASK_EN 0x40000000 #define IXGBE_FTQF_QUEUE_ENABLE 0x80000000 /* Interrupt clear mask */ #define IXGBE_IRQ_CLEAR_MASK 0xFFFFFFFF /* Interrupt Vector Allocation Registers */ #define IXGBE_IVAR_REG_NUM 25 #define IXGBE_IVAR_REG_NUM_82599 64 #define IXGBE_IVAR_TXRX_ENTRY 96 #define IXGBE_IVAR_RX_ENTRY 64 #define IXGBE_IVAR_RX_QUEUE(_i) (0 + (_i)) #define IXGBE_IVAR_TX_QUEUE(_i) (64 + (_i)) #define IXGBE_IVAR_TX_ENTRY 32 #define IXGBE_IVAR_TCP_TIMER_INDEX 96 /* 0 based index */ #define IXGBE_IVAR_OTHER_CAUSES_INDEX 97 /* 0 based index */ #define IXGBE_MSIX_VECTOR(_i) (0 + (_i)) #define IXGBE_IVAR_ALLOC_VAL 0x80 /* Interrupt Allocation valid */ /* ETYPE Queue Filter/Select Bit Masks */ #define IXGBE_MAX_ETQF_FILTERS 8 #define IXGBE_ETQF_FCOE 0x08000000 /* bit 27 */ #define IXGBE_ETQF_BCN 0x10000000 /* bit 28 */ #define IXGBE_ETQF_TX_ANTISPOOF 0x20000000 /* bit 29 */ #define IXGBE_ETQF_1588 0x40000000 /* bit 30 */ #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ #define IXGBE_ETQF_POOL_ENABLE (1 << 26) /* bit 26 */ #define IXGBE_ETQF_POOL_SHIFT 20 #define IXGBE_ETQS_RX_QUEUE 0x007F0000 /* bits 22:16 */ #define IXGBE_ETQS_RX_QUEUE_SHIFT 16 #define IXGBE_ETQS_LLI 0x20000000 /* bit 29 */ #define IXGBE_ETQS_QUEUE_EN 0x80000000 /* bit 31 */ /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters * here!! * * Current filters: * EAPOL 802.1x (0x888e): Filter 0 * FCoE (0x8906): Filter 2 * 1588 (0x88f7): Filter 3 * FIP (0x8914): Filter 4 * LLDP (0x88CC): Filter 5 * LACP (0x8809): Filter 6 */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 #define IXGBE_ETQF_FILTER_FIP 4 #define IXGBE_ETQF_FILTER_LLDP 5 #define IXGBE_ETQF_FILTER_LACP 6 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ #define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */ #define IXGBE_VLNCTRL_CFIEN 0x20000000 /* bit 29 */ #define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */ #define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */ /* VLAN pool filtering masks */ #define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */ #define IXGBE_VLVF_ENTRIES 64 #define IXGBE_VLVF_VLANID_MASK 0x00000FFF /* Per VF Port VLAN insertion rules */ #define IXGBE_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */ #define IXGBE_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */ #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ /* STATUS Bit Masks */ #define IXGBE_STATUS_LAN_ID 0x0000000C /* LAN ID */ #define IXGBE_STATUS_LAN_ID_SHIFT 2 /* LAN ID Shift*/ #define IXGBE_STATUS_GIO 0x00080000 /* GIO Master Ena Status */ #define IXGBE_STATUS_LAN_ID_0 0x00000000 /* LAN ID 0 */ #define IXGBE_STATUS_LAN_ID_1 0x00000004 /* LAN ID 1 */ /* ESDP Bit Masks */ #define IXGBE_ESDP_SDP0 0x00000001 /* SDP0 Data Value */ #define IXGBE_ESDP_SDP1 0x00000002 /* SDP1 Data Value */ #define IXGBE_ESDP_SDP2 0x00000004 /* SDP2 Data Value */ #define IXGBE_ESDP_SDP3 0x00000008 /* SDP3 Data Value */ #define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */ #define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */ #define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */ #define IXGBE_ESDP_SDP7 0x00000080 /* SDP7 Data Value */ #define IXGBE_ESDP_SDP0_DIR 0x00000100 /* SDP0 IO direction */ #define IXGBE_ESDP_SDP1_DIR 0x00000200 /* SDP1 IO direction */ #define IXGBE_ESDP_SDP2_DIR 0x00000400 /* SDP1 IO direction */ #define IXGBE_ESDP_SDP3_DIR 0x00000800 /* SDP3 IO direction */ #define IXGBE_ESDP_SDP4_DIR 0x00001000 /* SDP4 IO direction */ #define IXGBE_ESDP_SDP5_DIR 0x00002000 /* SDP5 IO direction */ #define IXGBE_ESDP_SDP6_DIR 0x00004000 /* SDP6 IO direction */ #define IXGBE_ESDP_SDP7_DIR 0x00008000 /* SDP7 IO direction */ #define IXGBE_ESDP_SDP0_NATIVE 0x00010000 /* SDP0 IO mode */ #define IXGBE_ESDP_SDP1_NATIVE 0x00020000 /* SDP1 IO mode */ /* LEDCTL Bit Masks */ #define IXGBE_LED_IVRT_BASE 0x00000040 #define IXGBE_LED_BLINK_BASE 0x00000080 #define IXGBE_LED_MODE_MASK_BASE 0x0000000F #define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i))) #define IXGBE_LED_MODE_SHIFT(_i) (8*(_i)) #define IXGBE_LED_IVRT(_i) IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i) #define IXGBE_LED_BLINK(_i) IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i) #define IXGBE_LED_MODE_MASK(_i) IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i) #define IXGBE_X557_LED_MANUAL_SET_MASK (1 << 8) #define IXGBE_X557_MAX_LED_INDEX 3 #define IXGBE_X557_LED_PROVISIONING 0xC430 /* LED modes */ #define IXGBE_LED_LINK_UP 0x0 #define IXGBE_LED_LINK_10G 0x1 #define IXGBE_LED_MAC 0x2 #define IXGBE_LED_FILTER 0x3 #define IXGBE_LED_LINK_ACTIVE 0x4 #define IXGBE_LED_LINK_1G 0x5 #define IXGBE_LED_ON 0xE #define IXGBE_LED_OFF 0xF /* AUTOC Bit Masks */ #define IXGBE_AUTOC_KX4_KX_SUPP_MASK 0xC0000000 #define IXGBE_AUTOC_KX4_SUPP 0x80000000 #define IXGBE_AUTOC_KX_SUPP 0x40000000 #define IXGBE_AUTOC_PAUSE 0x30000000 #define IXGBE_AUTOC_ASM_PAUSE 0x20000000 #define IXGBE_AUTOC_SYM_PAUSE 0x10000000 #define IXGBE_AUTOC_RF 0x08000000 #define IXGBE_AUTOC_PD_TMR 0x06000000 #define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000 #define IXGBE_AUTOC_AN_RX_DRIFT 0x00800000 #define IXGBE_AUTOC_AN_RX_ALIGN 0x007C0000 #define IXGBE_AUTOC_FECA 0x00040000 #define IXGBE_AUTOC_FECR 0x00020000 #define IXGBE_AUTOC_KR_SUPP 0x00010000 #define IXGBE_AUTOC_AN_RESTART 0x00001000 #define IXGBE_AUTOC_FLU 0x00000001 #define IXGBE_AUTOC_LMS_SHIFT 13 #define IXGBE_AUTOC_LMS_10G_SERIAL (0x3 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR (0x4 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_SGMII_1G_100M (0x5 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII (0x7 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_PMA_PMD_MASK 0x00000200 #define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9 #define IXGBE_AUTOC_10G_PMA_PMD_MASK 0x00000180 #define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7 #define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_10G_KX4 (0x1 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_10G_CX4 (0x2 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_BX (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_KX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_SFI (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_KX_BX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_UPPER_MASK 0xFFFF0000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK 0x00030000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT 16 #define IXGBE_AUTOC2_10G_KR (0x0 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK 0x50000000 #define IXGBE_AUTOC2_LINK_DISABLE_MASK 0x70000000 #define IXGBE_MACC_FLU 0x00000001 #define IXGBE_MACC_FSV_10G 0x00030000 #define IXGBE_MACC_FS 0x00040000 #define IXGBE_MAC_RX2TX_LPBK 0x00000002 /* Veto Bit definiton */ #define IXGBE_MMNGC_MNG_VETO 0x00000001 /* LINKS Bit Masks */ #define IXGBE_LINKS_KX_AN_COMP 0x80000000 #define IXGBE_LINKS_UP 0x40000000 #define IXGBE_LINKS_SPEED 0x20000000 #define IXGBE_LINKS_MODE 0x18000000 #define IXGBE_LINKS_RX_MODE 0x06000000 #define IXGBE_LINKS_TX_MODE 0x01800000 #define IXGBE_LINKS_XGXS_EN 0x00400000 #define IXGBE_LINKS_SGMII_EN 0x02000000 #define IXGBE_LINKS_PCS_1G_EN 0x00200000 #define IXGBE_LINKS_1G_AN_EN 0x00100000 #define IXGBE_LINKS_KX_AN_IDLE 0x00080000 #define IXGBE_LINKS_1G_SYNC 0x00040000 #define IXGBE_LINKS_10G_ALIGN 0x00020000 #define IXGBE_LINKS_10G_LANE_SYNC 0x00017000 #define IXGBE_LINKS_TL_FAULT 0x00001000 #define IXGBE_LINKS_SIGNAL 0x00000F00 #define IXGBE_LINKS_SPEED_NON_STD 0x08000000 #define IXGBE_LINKS_SPEED_82599 0x30000000 #define IXGBE_LINKS_SPEED_10G_82599 0x30000000 #define IXGBE_LINKS_SPEED_1G_82599 0x20000000 #define IXGBE_LINKS_SPEED_100_82599 0x10000000 #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ #define IXGBE_LINKS2_AN_SUPPORTED 0x00000040 /* PCS1GLSTA Bit Masks */ #define IXGBE_PCS1GLSTA_LINK_OK 1 #define IXGBE_PCS1GLSTA_SYNK_OK 0x10 #define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000 #define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000 #define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000 #define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000 #define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000 #define IXGBE_PCS1GANA_SYM_PAUSE 0x80 #define IXGBE_PCS1GANA_ASM_PAUSE 0x100 /* PCS1GLCTL Bit Masks */ #define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg to en */ #define IXGBE_PCS1GLCTL_FLV_LINK_UP 1 #define IXGBE_PCS1GLCTL_FORCE_LINK 0x20 #define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40 #define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 #define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 /* ANLP1 Bit Masks */ #define IXGBE_ANLP1_PAUSE 0x0C00 #define IXGBE_ANLP1_SYM_PAUSE 0x0400 #define IXGBE_ANLP1_ASM_PAUSE 0x0800 #define IXGBE_ANLP1_AN_STATE_MASK 0x000f0000 /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define IXGBE_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ #define IXGBE_SWFW_REGSMP 0x80000000 /* Register Semaphore bit 31 */ /* SW_FW_SYNC/GSSR definitions */ #define IXGBE_GSSR_EEP_SM 0x0001 #define IXGBE_GSSR_PHY0_SM 0x0002 #define IXGBE_GSSR_PHY1_SM 0x0004 #define IXGBE_GSSR_MAC_CSR_SM 0x0008 #define IXGBE_GSSR_FLASH_SM 0x0010 #define IXGBE_GSSR_NVM_UPDATE_SM 0x0200 #define IXGBE_GSSR_SW_MNG_SM 0x0400 #define IXGBE_GSSR_SHARED_I2C_SM 0x1806 /* Wait for both phys and both I2Cs */ #define IXGBE_GSSR_I2C_MASK 0x1800 #define IXGBE_GSSR_NVM_PHY_MASK 0xF /* FW Status register bitmask */ #define IXGBE_FWSTS_FWRI 0x00000200 /* Firmware Reset Indication */ /* EEC Register */ #define IXGBE_EEC_SK 0x00000001 /* EEPROM Clock */ #define IXGBE_EEC_CS 0x00000002 /* EEPROM Chip Select */ #define IXGBE_EEC_DI 0x00000004 /* EEPROM Data In */ #define IXGBE_EEC_DO 0x00000008 /* EEPROM Data Out */ #define IXGBE_EEC_FWE_MASK 0x00000030 /* FLASH Write Enable */ #define IXGBE_EEC_FWE_DIS 0x00000010 /* Disable FLASH writes */ #define IXGBE_EEC_FWE_EN 0x00000020 /* Enable FLASH writes */ #define IXGBE_EEC_FWE_SHIFT 4 #define IXGBE_EEC_REQ 0x00000040 /* EEPROM Access Request */ #define IXGBE_EEC_GNT 0x00000080 /* EEPROM Access Grant */ #define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */ #define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */ #define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */ #define IXGBE_EEC_SEC1VAL 0x02000000 /* Sector 1 Valid */ #define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 #define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */ #define IXGBE_EERD_MAX_ADDR 0x00003FFF /* EERD alows 14 bits for addr. */ #define IXGBE_EEC_SIZE_SHIFT 11 #define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 #define IXGBE_EEPROM_OPCODE_BITS 8 /* FLA Register */ #define IXGBE_FLA_LOCKED 0x00000040 /* Part Number String Length */ #define IXGBE_PBANUM_LENGTH 11 /* Checksum and EEPROM pointers */ #define IXGBE_PBANUM_PTR_GUARD 0xFAFA #define IXGBE_EEPROM_CHECKSUM 0x3F #define IXGBE_EEPROM_SUM 0xBABA #define IXGBE_PCIE_ANALOG_PTR 0x03 #define IXGBE_ATLAS0_CONFIG_PTR 0x04 #define IXGBE_PHY_PTR 0x04 #define IXGBE_ATLAS1_CONFIG_PTR 0x05 #define IXGBE_OPTION_ROM_PTR 0x05 #define IXGBE_PCIE_GENERAL_PTR 0x06 #define IXGBE_PCIE_CONFIG0_PTR 0x07 #define IXGBE_PCIE_CONFIG1_PTR 0x08 #define IXGBE_CORE0_PTR 0x09 #define IXGBE_CORE1_PTR 0x0A #define IXGBE_MAC0_PTR 0x0B #define IXGBE_MAC1_PTR 0x0C #define IXGBE_CSR0_CONFIG_PTR 0x0D #define IXGBE_CSR1_CONFIG_PTR 0x0E #define IXGBE_PCIE_ANALOG_PTR_X550 0x02 #define IXGBE_SHADOW_RAM_SIZE_X550 0x4000 #define IXGBE_IXGBE_PCIE_GENERAL_SIZE 0x24 #define IXGBE_PCIE_CONFIG_SIZE 0x08 #define IXGBE_EEPROM_LAST_WORD 0x41 #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 #define IXGBE_ALT_MAC_ADDR_PTR 0x37 #define IXGBE_FREE_SPACE_PTR 0X3E /* External Thermal Sensor Config */ #define IXGBE_ETS_CFG 0x26 #define IXGBE_ETS_LTHRES_DELTA_MASK 0x07C0 #define IXGBE_ETS_LTHRES_DELTA_SHIFT 6 #define IXGBE_ETS_TYPE_MASK 0x0038 #define IXGBE_ETS_TYPE_SHIFT 3 #define IXGBE_ETS_TYPE_EMC 0x000 #define IXGBE_ETS_NUM_SENSORS_MASK 0x0007 #define IXGBE_ETS_DATA_LOC_MASK 0x3C00 #define IXGBE_ETS_DATA_LOC_SHIFT 10 #define IXGBE_ETS_DATA_INDEX_MASK 0x0300 #define IXGBE_ETS_DATA_INDEX_SHIFT 8 #define IXGBE_ETS_DATA_HTHRESH_MASK 0x00FF #define IXGBE_SAN_MAC_ADDR_PTR 0x28 #define IXGBE_DEVICE_CAPS 0x2C #define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11 #define IXGBE_PCIE_MSIX_82599_CAPS 0x72 #define IXGBE_MAX_MSIX_VECTORS_82599 0x40 #define IXGBE_PCIE_MSIX_82598_CAPS 0x62 #define IXGBE_MAX_MSIX_VECTORS_82598 0x13 /* MSI-X capability fields masks */ #define IXGBE_PCIE_MSIX_TBL_SZ_MASK 0x7FF /* Legacy EEPROM word offsets */ #define IXGBE_ISCSI_BOOT_CAPS 0x0033 #define IXGBE_ISCSI_SETUP_PORT_0 0x0030 #define IXGBE_ISCSI_SETUP_PORT_1 0x0034 /* EEPROM Commands - SPI */ #define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */ #define IXGBE_EEPROM_STATUS_RDY_SPI 0x01 #define IXGBE_EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ #define IXGBE_EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ #define IXGBE_EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = addr bit-8 */ #define IXGBE_EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Ena latch */ /* EEPROM reset Write Enable latch */ #define IXGBE_EEPROM_WRDI_OPCODE_SPI 0x04 #define IXGBE_EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status reg */ #define IXGBE_EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status reg */ #define IXGBE_EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */ #define IXGBE_EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */ #define IXGBE_EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ /* EEPROM Read Register */ #define IXGBE_EEPROM_RW_REG_DATA 16 /* data offset in EEPROM read reg */ #define IXGBE_EEPROM_RW_REG_DONE 2 /* Offset to READ done bit */ #define IXGBE_EEPROM_RW_REG_START 1 /* First bit to start operation */ #define IXGBE_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ #define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for wr complete */ #define IXGBE_NVM_POLL_READ 0 /* Flag for polling for rd complete */ #define NVM_INIT_CTRL_3 0x38 #define NVM_INIT_CTRL_3_LPLU 0x8 #define NVM_INIT_CTRL_3_D10GMP_PORT0 0x40 #define NVM_INIT_CTRL_3_D10GMP_PORT1 0x100 #define IXGBE_ETH_LENGTH_OF_ADDRESS 6 #define IXGBE_EEPROM_PAGE_SIZE_MAX 128 #define IXGBE_EEPROM_RD_BUFFER_MAX_COUNT 256 /* words rd in burst */ #define IXGBE_EEPROM_WR_BUFFER_MAX_COUNT 256 /* words wr in burst */ #define IXGBE_EEPROM_CTRL_2 1 /* EEPROM CTRL word 2 */ #define IXGBE_EEPROM_CCD_BIT 2 #ifndef IXGBE_EEPROM_GRANT_ATTEMPTS #define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM attempts to gain grant */ #endif /* Number of 5 microseconds we wait for EERD read and * EERW write to complete */ #define IXGBE_EERD_EEWR_ATTEMPTS 100000 /* # attempts we wait for flush update to complete */ #define IXGBE_FLUDONE_ATTEMPTS 20000 #define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */ #define IXGBE_PCIE_CTRL2_DUMMY_ENABLE 0x8 /* Dummy Function Enable */ #define IXGBE_PCIE_CTRL2_LAN_DISABLE 0x2 /* LAN PCI Disable */ #define IXGBE_PCIE_CTRL2_DISABLE_SELECT 0x1 /* LAN Disable Select */ #define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET 0x0 #define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 #define IXGBE_FW_LESM_PARAMETERS_PTR 0x2 #define IXGBE_FW_LESM_STATE_1 0x1 #define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_FW_PATCH_VERSION_4 0x7 #define IXGBE_FCOE_IBA_CAPS_BLK_PTR 0x33 /* iSCSI/FCOE block */ #define IXGBE_FCOE_IBA_CAPS_FCOE 0x20 /* FCOE flags */ #define IXGBE_ISCSI_FCOE_BLK_PTR 0x17 /* iSCSI/FCOE block */ #define IXGBE_ISCSI_FCOE_FLAGS_OFFSET 0x0 /* FCOE flags */ #define IXGBE_ISCSI_FCOE_FLAGS_ENABLE 0x1 /* FCOE flags enable bit */ #define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt SAN MAC capability */ #define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt SAN MAC 0 offset */ #define IXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt SAN MAC 1 offset */ #define IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt WWNN prefix offset */ #define IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt WWPN prefix offset */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt SAN MAC exists */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt WWN base exists */ /* FW header offset */ #define IXGBE_X540_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_X540_FW_MODULE_MASK 0x7FFF /* 4KB multiplier */ #define IXGBE_X540_FW_MODULE_LENGTH 0x1000 /* version word 2 (month & day) */ #define IXGBE_X540_FW_PATCH_VERSION_2 0x5 /* version word 3 (silicon compatibility & year) */ #define IXGBE_X540_FW_PATCH_VERSION_3 0x6 /* version word 4 (major & minor numbers) */ #define IXGBE_X540_FW_PATCH_VERSION_4 0x7 #define IXGBE_DEVICE_CAPS_WOL_PORT0_1 0x4 /* WoL supported on ports 0 & 1 */ #define IXGBE_DEVICE_CAPS_WOL_PORT0 0x8 /* WoL supported on port 0 */ #define IXGBE_DEVICE_CAPS_WOL_MASK 0xC /* Mask for WoL capabilities */ /* PCI Bus Info */ #define IXGBE_PCI_DEVICE_STATUS 0xAA #define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020 #define IXGBE_PCI_LINK_STATUS 0xB2 #define IXGBE_PCI_DEVICE_CONTROL2 0xC8 #define IXGBE_PCI_LINK_WIDTH 0x3F0 #define IXGBE_PCI_LINK_WIDTH_1 0x10 #define IXGBE_PCI_LINK_WIDTH_2 0x20 #define IXGBE_PCI_LINK_WIDTH_4 0x40 #define IXGBE_PCI_LINK_WIDTH_8 0x80 #define IXGBE_PCI_LINK_SPEED 0xF #define IXGBE_PCI_LINK_SPEED_2500 0x1 #define IXGBE_PCI_LINK_SPEED_5000 0x2 #define IXGBE_PCI_LINK_SPEED_8000 0x3 #define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80 #define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005 #define IXGBE_PCIDEVCTRL2_TIMEO_MASK 0xf #define IXGBE_PCIDEVCTRL2_16_32ms_def 0x0 #define IXGBE_PCIDEVCTRL2_50_100us 0x1 #define IXGBE_PCIDEVCTRL2_1_2ms 0x2 #define IXGBE_PCIDEVCTRL2_16_32ms 0x5 #define IXGBE_PCIDEVCTRL2_65_130ms 0x6 #define IXGBE_PCIDEVCTRL2_260_520ms 0x9 #define IXGBE_PCIDEVCTRL2_1_2s 0xa #define IXGBE_PCIDEVCTRL2_4_8s 0xd #define IXGBE_PCIDEVCTRL2_17_34s 0xe /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 /* Check whether address is multicast. This is little-endian specific check.*/ #define IXGBE_IS_MULTICAST(Address) \ (bool)(((u8 *)(Address))[0] & ((u8)0x01)) /* Check whether an address is broadcast. */ #define IXGBE_IS_BROADCAST(Address) \ ((((u8 *)(Address))[0] == ((u8)0xff)) && \ (((u8 *)(Address))[1] == ((u8)0xff))) /* RAH */ #define IXGBE_RAH_VIND_MASK 0x003C0000 #define IXGBE_RAH_VIND_SHIFT 18 #define IXGBE_RAH_AV 0x80000000 #define IXGBE_CLEAR_VMDQ_ALL 0xFFFFFFFF /* Header split receive */ #define IXGBE_RFCTL_ISCSI_DIS 0x00000001 #define IXGBE_RFCTL_ISCSI_DWC_MASK 0x0000003E #define IXGBE_RFCTL_ISCSI_DWC_SHIFT 1 #define IXGBE_RFCTL_RSC_DIS 0x00000020 #define IXGBE_RFCTL_NFSW_DIS 0x00000040 #define IXGBE_RFCTL_NFSR_DIS 0x00000080 #define IXGBE_RFCTL_NFS_VER_MASK 0x00000300 #define IXGBE_RFCTL_NFS_VER_SHIFT 8 #define IXGBE_RFCTL_NFS_VER_2 0 #define IXGBE_RFCTL_NFS_VER_3 1 #define IXGBE_RFCTL_NFS_VER_4 2 #define IXGBE_RFCTL_IPV6_DIS 0x00000400 #define IXGBE_RFCTL_IPV6_XSUM_DIS 0x00000800 #define IXGBE_RFCTL_IPFRSP_DIS 0x00004000 #define IXGBE_RFCTL_IPV6_EX_DIS 0x00010000 #define IXGBE_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 /* Transmit Config masks */ #define IXGBE_TXDCTL_ENABLE 0x02000000 /* Ena specific Tx Queue */ #define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wr-bk flushing */ #define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ /* Enable short packet padding to 64 bytes */ #define IXGBE_TX_PAD_ENABLE 0x00000400 #define IXGBE_JUMBO_FRAME_ENABLE 0x00000004 /* Allow jumbo frames */ /* This allows for 16K packets + 4k for vlan */ #define IXGBE_MAX_FRAME_SZ 0x40040000 #define IXGBE_TDWBAL_HEAD_WB_ENABLE 0x1 /* Tx head write-back enable */ #define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq# write-back enable */ /* Receive Config masks */ #define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */ #define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Desc Monitor Bypass */ #define IXGBE_RXDCTL_ENABLE 0x02000000 /* Ena specific Rx Queue */ #define IXGBE_RXDCTL_SWFLSH 0x04000000 /* Rx Desc wr-bk flushing */ #define IXGBE_RXDCTL_RLPMLMASK 0x00003FFF /* X540 supported only */ #define IXGBE_RXDCTL_RLPML_EN 0x00008000 #define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */ #define IXGBE_TSAUXC_EN_CLK 0x00000004 #define IXGBE_TSAUXC_SYNCLK 0x00000008 #define IXGBE_TSAUXC_SDP0_INT 0x00000040 #define IXGBE_TSAUXC_EN_TT0 0x00000001 #define IXGBE_TSAUXC_EN_TT1 0x00000002 #define IXGBE_TSAUXC_ST0 0x00000010 #define IXGBE_TSAUXC_DISABLE_SYSTIME 0x80000000 #define IXGBE_TSSDP_TS_SDP0_SEL_MASK 0x000000C0 #define IXGBE_TSSDP_TS_SDP0_CLK0 0x00000080 #define IXGBE_TSSDP_TS_SDP0_EN 0x00000100 #define IXGBE_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define IXGBE_TSYNCTXCTL_ENABLED 0x00000010 /* Tx timestamping enabled */ #define IXGBE_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define IXGBE_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define IXGBE_TSYNCRXCTL_TYPE_L2_V2 0x00 #define IXGBE_TSYNCRXCTL_TYPE_L4_V1 0x02 #define IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 #define IXGBE_TSYNCRXCTL_TYPE_ALL 0x08 #define IXGBE_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define IXGBE_TSYNCRXCTL_ENABLED 0x00000010 /* Rx Timestamping enabled */ #define IXGBE_TSYNCRXCTL_TSIP_UT_EN 0x00800000 /* Rx Timestamp in Packet */ #define IXGBE_TSYNCRXCTL_TSIP_UP_MASK 0xFF000000 /* Rx Timestamp UP Mask */ #define IXGBE_TSIM_SYS_WRAP 0x00000001 #define IXGBE_TSIM_TXTS 0x00000002 #define IXGBE_TSIM_TADJ 0x00000080 #define IXGBE_TSICR_SYS_WRAP IXGBE_TSIM_SYS_WRAP #define IXGBE_TSICR_TXTS IXGBE_TSIM_TXTS #define IXGBE_TSICR_TADJ IXGBE_TSIM_TADJ #define IXGBE_RXMTRL_V1_CTRLT_MASK 0x000000FF #define IXGBE_RXMTRL_V1_SYNC_MSG 0x00 #define IXGBE_RXMTRL_V1_DELAY_REQ_MSG 0x01 #define IXGBE_RXMTRL_V1_FOLLOWUP_MSG 0x02 #define IXGBE_RXMTRL_V1_DELAY_RESP_MSG 0x03 #define IXGBE_RXMTRL_V1_MGMT_MSG 0x04 #define IXGBE_RXMTRL_V2_MSGID_MASK 0x0000FF00 #define IXGBE_RXMTRL_V2_SYNC_MSG 0x0000 #define IXGBE_RXMTRL_V2_DELAY_REQ_MSG 0x0100 #define IXGBE_RXMTRL_V2_PDELAY_REQ_MSG 0x0200 #define IXGBE_RXMTRL_V2_PDELAY_RESP_MSG 0x0300 #define IXGBE_RXMTRL_V2_FOLLOWUP_MSG 0x0800 #define IXGBE_RXMTRL_V2_DELAY_RESP_MSG 0x0900 #define IXGBE_RXMTRL_V2_PDELAY_FOLLOWUP_MSG 0x0A00 #define IXGBE_RXMTRL_V2_ANNOUNCE_MSG 0x0B00 #define IXGBE_RXMTRL_V2_SIGNALLING_MSG 0x0C00 #define IXGBE_RXMTRL_V2_MGMT_MSG 0x0D00 #define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */ #define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/ #define IXGBE_FCTRL_UPE 0x00000200 /* Unicast Promiscuous Ena */ #define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */ #define IXGBE_FCTRL_PMCF 0x00001000 /* Pass MAC Control Frames */ #define IXGBE_FCTRL_DPF 0x00002000 /* Discard Pause Frame */ /* Receive Priority Flow Control Enable */ #define IXGBE_FCTRL_RPFCE 0x00004000 #define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */ #define IXGBE_MFLCN_PMCF 0x00000001 /* Pass MAC Control Frames */ #define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */ #define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */ #define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */ #define IXGBE_MFLCN_RPFCE_MASK 0x00000FF4 /* Rx Priority FC bitmap mask */ #define IXGBE_MFLCN_RPFCE_SHIFT 4 /* Rx Priority FC bitmap shift */ /* Multiple Receive Queue Control */ #define IXGBE_MRQC_RSSEN 0x00000001 /* RSS Enable */ #define IXGBE_MRQC_MRQE_MASK 0xF /* Bits 3:0 */ #define IXGBE_MRQC_RT8TCEN 0x00000002 /* 8 TC no RSS */ #define IXGBE_MRQC_RT4TCEN 0x00000003 /* 4 TC no RSS */ #define IXGBE_MRQC_RTRSS8TCEN 0x00000004 /* 8 TC w/ RSS */ #define IXGBE_MRQC_RTRSS4TCEN 0x00000005 /* 4 TC w/ RSS */ #define IXGBE_MRQC_VMDQEN 0x00000008 /* VMDq2 64 pools no RSS */ #define IXGBE_MRQC_VMDQRSS32EN 0x0000000A /* VMDq2 32 pools w/ RSS */ #define IXGBE_MRQC_VMDQRSS64EN 0x0000000B /* VMDq2 64 pools w/ RSS */ #define IXGBE_MRQC_VMDQRT8TCEN 0x0000000C /* VMDq2/RT 16 pool 8 TC */ #define IXGBE_MRQC_VMDQRT4TCEN 0x0000000D /* VMDq2/RT 32 pool 4 TC */ #define IXGBE_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define IXGBE_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define IXGBE_MRQC_RSS_FIELD_IPV4 0x00020000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP 0x00040000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX 0x00080000 #define IXGBE_MRQC_RSS_FIELD_IPV6 0x00100000 #define IXGBE_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define IXGBE_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IXGBE_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000 #define IXGBE_MRQC_MULTIPLE_RSS 0x00002000 #define IXGBE_MRQC_L3L4TXSWEN 0x00008000 /* Queue Drop Enable */ #define IXGBE_QDE_ENABLE 0x00000001 #define IXGBE_QDE_HIDE_VLAN 0x00000002 #define IXGBE_QDE_IDX_MASK 0x00007F00 #define IXGBE_QDE_IDX_SHIFT 8 #define IXGBE_QDE_WRITE 0x00010000 #define IXGBE_QDE_READ 0x00020000 #define IXGBE_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ #define IXGBE_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ #define IXGBE_TXD_CMD_EOP 0x01000000 /* End of Packet */ #define IXGBE_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define IXGBE_TXD_CMD_IC 0x04000000 /* Insert Checksum */ #define IXGBE_TXD_CMD_RS 0x08000000 /* Report Status */ #define IXGBE_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ #define IXGBE_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ #define IXGBE_TXD_STAT_DD 0x00000001 /* Descriptor Done */ #define IXGBE_RXDADV_IPSEC_STATUS_SECP 0x00020000 #define IXGBE_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 #define IXGBE_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 #define IXGBE_RXDADV_IPSEC_ERROR_AUTH_FAILED 0x18000000 #define IXGBE_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 /* Multiple Transmit Queue Command Register */ #define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */ #define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */ #define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */ #define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */ #define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */ #define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA and VT_ENA */ #define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */ /* Receive Descriptor bit definitions */ #define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */ #define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */ #define IXGBE_RXD_STAT_FLM 0x04 /* FDir Match */ #define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ #define IXGBE_RXDADV_NEXTP_MASK 0x000FFFF0 /* Next Descriptor Index */ #define IXGBE_RXDADV_NEXTP_SHIFT 0x00000004 #define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */ #define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ #define IXGBE_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ #define IXGBE_RXD_STAT_OUTERIPCS 0x100 /* Cloud IP xsum calculated */ #define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */ #define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ #define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ #define IXGBE_RXD_STAT_LLINT 0x800 /* Pkt caused Low Latency Interrupt */ #define IXGBE_RXD_STAT_TSIP 0x08000 /* Time Stamp in packet buffer */ #define IXGBE_RXD_STAT_TS 0x10000 /* Time Stamp */ #define IXGBE_RXD_STAT_SECP 0x20000 /* Security Processing */ #define IXGBE_RXD_STAT_LB 0x40000 /* Loopback Status */ #define IXGBE_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ #define IXGBE_RXD_ERR_CE 0x01 /* CRC Error */ #define IXGBE_RXD_ERR_LE 0x02 /* Length Error */ #define IXGBE_RXD_ERR_PE 0x08 /* Packet Error */ #define IXGBE_RXD_ERR_OSE 0x10 /* Oversize Error */ #define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */ #define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */ #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ #define IXGBE_RXDADV_ERR_OUTERIPER 0x04000000 /* CRC IP Header error */ #define IXGBE_RXDADV_ERR_RXE 0x20000000 /* Any MAC Error */ #define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCEOFe/IPE */ #define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ #define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */ #define IXGBE_RXDADV_ERR_FDIR_DROP 0x00200000 /* FDIR Drop error */ #define IXGBE_RXDADV_ERR_FDIR_COLL 0x00400000 /* FDIR Collision error */ #define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ #define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ #define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ #define IXGBE_RXDADV_ERR_PE 0x08000000 /* Packet Error */ #define IXGBE_RXDADV_ERR_OSE 0x10000000 /* Oversize Error */ #define IXGBE_RXDADV_ERR_USE 0x20000000 /* Undersize Error */ #define IXGBE_RXDADV_ERR_TCPE 0x40000000 /* TCP/UDP Checksum Error */ #define IXGBE_RXDADV_ERR_IPE 0x80000000 /* IP Checksum Error */ #define IXGBE_RXD_VLAN_ID_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define IXGBE_RXD_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ #define IXGBE_RXD_PRI_SHIFT 13 #define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */ #define IXGBE_RXD_CFI_SHIFT 12 #define IXGBE_RXDADV_STAT_DD IXGBE_RXD_STAT_DD /* Done */ #define IXGBE_RXDADV_STAT_EOP IXGBE_RXD_STAT_EOP /* End of Packet */ #define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */ #define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */ #define IXGBE_RXDADV_STAT_MASK 0x000fffff /* Stat/NEXTP: bit 0-19 */ #define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */ #define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */ #define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */ #define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */ #define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */ #define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */ #define IXGBE_RXDADV_STAT_TS 0x00010000 /* IEEE1588 Time Stamp */ #define IXGBE_RXDADV_STAT_TSIP 0x00008000 /* Time Stamp in packet buffer */ /* PSRTYPE bit definitions */ #define IXGBE_PSRTYPE_TCPHDR 0x00000010 #define IXGBE_PSRTYPE_UDPHDR 0x00000020 #define IXGBE_PSRTYPE_IPV4HDR 0x00000100 #define IXGBE_PSRTYPE_IPV6HDR 0x00000200 #define IXGBE_PSRTYPE_L2HDR 0x00001000 /* SRRCTL bit definitions */ #define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* 64byte resolution (>> 6) * + at bit 8 offset (<< 8) * = (<< 2) */ #define IXGBE_SRRCTL_RDMTS_SHIFT 22 #define IXGBE_SRRCTL_RDMTS_MASK 0x01C00000 #define IXGBE_SRRCTL_DROP_EN 0x10000000 #define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F #define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 #define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 #define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 #define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000 #define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF #define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F #define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0 #define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0 #define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0 #define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 #define IXGBE_RXDADV_RSCCNT_SHIFT 17 #define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5 #define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000 #define IXGBE_RXDADV_SPH 0x8000 /* RSS Hash results */ #define IXGBE_RXDADV_RSSTYPE_NONE 0x00000000 #define IXGBE_RXDADV_RSSTYPE_IPV4_TCP 0x00000001 #define IXGBE_RXDADV_RSSTYPE_IPV4 0x00000002 #define IXGBE_RXDADV_RSSTYPE_IPV6_TCP 0x00000003 #define IXGBE_RXDADV_RSSTYPE_IPV6_EX 0x00000004 #define IXGBE_RXDADV_RSSTYPE_IPV6 0x00000005 #define IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006 #define IXGBE_RXDADV_RSSTYPE_IPV4_UDP 0x00000007 #define IXGBE_RXDADV_RSSTYPE_IPV6_UDP 0x00000008 #define IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 /* RSS Packet Types as indicated in the receive descriptor. */ #define IXGBE_RXDADV_PKTTYPE_NONE 0x00000000 #define IXGBE_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPv4 hdr present */ #define IXGBE_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPv4 hdr + extensions */ #define IXGBE_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPv6 hdr present */ #define IXGBE_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPv6 hdr + extensions */ #define IXGBE_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ #define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ #define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ #define IXGBE_RXDADV_PKTTYPE_VXLAN 0x00000800 /* VXLAN hdr present */ #define IXGBE_RXDADV_PKTTYPE_TUNNEL 0x00010000 /* Tunnel type */ #define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ #define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ #define IXGBE_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ #define IXGBE_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ #define IXGBE_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ #define IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ /* Security Processing bit Indication */ #define IXGBE_RXDADV_LNKSEC_STATUS_SECP 0x00020000 #define IXGBE_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 #define IXGBE_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 #define IXGBE_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 #define IXGBE_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 /* Masks to determine if packets should be dropped due to frame errors */ #define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \ IXGBE_RXD_ERR_CE | \ IXGBE_RXD_ERR_LE | \ IXGBE_RXD_ERR_PE | \ IXGBE_RXD_ERR_OSE | \ IXGBE_RXD_ERR_USE) #define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \ IXGBE_RXDADV_ERR_CE | \ IXGBE_RXDADV_ERR_LE | \ IXGBE_RXDADV_ERR_PE | \ IXGBE_RXDADV_ERR_OSE | \ IXGBE_RXDADV_ERR_USE) #define IXGBE_RXDADV_ERR_FRAME_ERR_MASK_82599 IXGBE_RXDADV_ERR_RXE /* Multicast bit mask */ #define IXGBE_MCSTCTRL_MFE 0x4 /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8 #define IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE 8 #define IXGBE_REQ_TX_BUFFER_GRANULARITY 1024 /* Vlan-specific macros */ #define IXGBE_RX_DESC_SPECIAL_VLAN_MASK 0x0FFF /* VLAN ID in lower 12 bits */ #define IXGBE_RX_DESC_SPECIAL_PRI_MASK 0xE000 /* Priority in upper 3 bits */ #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */ #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT /* SR-IOV specific macros */ #define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4) #define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4)) #define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) #define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4)) /* Translated register #defines */ #define IXGBE_PVFCTRL(P) (0x00300 + (4 * (P))) #define IXGBE_PVFSTATUS(P) (0x00008 + (0 * (P))) #define IXGBE_PVFLINKS(P) (0x042A4 + (0 * (P))) #define IXGBE_PVFRTIMER(P) (0x00048 + (0 * (P))) #define IXGBE_PVFMAILBOX(P) (0x04C00 + (4 * (P))) #define IXGBE_PVFRXMEMWRAP(P) (0x03190 + (0 * (P))) #define IXGBE_PVTEICR(P) (0x00B00 + (4 * (P))) #define IXGBE_PVTEICS(P) (0x00C00 + (4 * (P))) #define IXGBE_PVTEIMS(P) (0x00D00 + (4 * (P))) #define IXGBE_PVTEIMC(P) (0x00E00 + (4 * (P))) #define IXGBE_PVTEIAC(P) (0x00F00 + (4 * (P))) #define IXGBE_PVTEIAM(P) (0x04D00 + (4 * (P))) #define IXGBE_PVTEITR(P) (((P) < 24) ? (0x00820 + ((P) * 4)) : \ (0x012300 + (((P) - 24) * 4))) #define IXGBE_PVTIVAR(P) (0x12500 + (4 * (P))) #define IXGBE_PVTIVAR_MISC(P) (0x04E00 + (4 * (P))) #define IXGBE_PVTRSCINT(P) (0x12000 + (4 * (P))) #define IXGBE_VFPBACL(P) (0x110C8 + (4 * (P))) #define IXGBE_PVFRDBAL(P) ((P < 64) ? (0x01000 + (0x40 * (P))) \ : (0x0D000 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDBAH(P) ((P < 64) ? (0x01004 + (0x40 * (P))) \ : (0x0D004 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDLEN(P) ((P < 64) ? (0x01008 + (0x40 * (P))) \ : (0x0D008 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDH(P) ((P < 64) ? (0x01010 + (0x40 * (P))) \ : (0x0D010 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDT(P) ((P < 64) ? (0x01018 + (0x40 * (P))) \ : (0x0D018 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRXDCTL(P) ((P < 64) ? (0x01028 + (0x40 * (P))) \ : (0x0D028 + (0x40 * ((P) - 64)))) #define IXGBE_PVFSRRCTL(P) ((P < 64) ? (0x01014 + (0x40 * (P))) \ : (0x0D014 + (0x40 * ((P) - 64)))) #define IXGBE_PVFPSRTYPE(P) (0x0EA00 + (4 * (P))) #define IXGBE_PVFTDBAL(P) (0x06000 + (0x40 * (P))) #define IXGBE_PVFTDBAH(P) (0x06004 + (0x40 * (P))) #define IXGBE_PVFTTDLEN(P) (0x06008 + (0x40 * (P))) #define IXGBE_PVFTDH(P) (0x06010 + (0x40 * (P))) #define IXGBE_PVFTDT(P) (0x06018 + (0x40 * (P))) #define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P))) #define IXGBE_PVFTDWBAL(P) (0x06038 + (0x40 * (P))) #define IXGBE_PVFTDWBAH(P) (0x0603C + (0x40 * (P))) #define IXGBE_PVFDCA_RXCTRL(P) (((P) < 64) ? (0x0100C + (0x40 * (P))) \ : (0x0D00C + (0x40 * ((P) - 64)))) #define IXGBE_PVFDCA_TXCTRL(P) (0x0600C + (0x40 * (P))) #define IXGBE_PVFGPRC(x) (0x0101C + (0x40 * (x))) #define IXGBE_PVFGPTC(x) (0x08300 + (0x04 * (x))) #define IXGBE_PVFGORC_LSB(x) (0x01020 + (0x40 * (x))) #define IXGBE_PVFGORC_MSB(x) (0x0D020 + (0x40 * (x))) #define IXGBE_PVFGOTC_LSB(x) (0x08400 + (0x08 * (x))) #define IXGBE_PVFGOTC_MSB(x) (0x08404 + (0x08 * (x))) #define IXGBE_PVFMPRC(x) (0x0D01C + (0x40 * (x))) #define IXGBE_PVFTDWBALn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDWBAL((q_per_pool)*(vf_number) + (vf_q_index))) #define IXGBE_PVFTDWBAHn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDWBAH((q_per_pool)*(vf_number) + (vf_q_index))) #define IXGBE_PVFTDHn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDH((q_per_pool)*(vf_number) + (vf_q_index))) #define IXGBE_PVFTDTn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDT((q_per_pool)*(vf_number) + (vf_q_index))) /* Little Endian defines */ #ifndef __le16 #define __le16 u16 #endif #ifndef __le32 #define __le32 u32 #endif #ifndef __le64 #define __le64 u64 #endif #ifndef __be16 /* Big Endian defines */ #define __be16 u16 #define __be32 u32 #define __be64 u64 #endif enum ixgbe_fdir_pballoc_type { IXGBE_FDIR_PBALLOC_NONE = 0, IXGBE_FDIR_PBALLOC_64K = 1, IXGBE_FDIR_PBALLOC_128K = 2, IXGBE_FDIR_PBALLOC_256K = 3, }; /* Flow Director register values */ #define IXGBE_FDIRCTRL_PBALLOC_64K 0x00000001 #define IXGBE_FDIRCTRL_PBALLOC_128K 0x00000002 #define IXGBE_FDIRCTRL_PBALLOC_256K 0x00000003 #define IXGBE_FDIRCTRL_INIT_DONE 0x00000008 #define IXGBE_FDIRCTRL_PERFECT_MATCH 0x00000010 #define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020 #define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080 #define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8 #define IXGBE_FDIRCTRL_FLEX_SHIFT 16 #define IXGBE_FDIRCTRL_FILTERMODE_SHIFT 21 #define IXGBE_FDIRCTRL_FILTERMODE_MACVLAN 0x0001 /* bit 23:21, 001b */ #define IXGBE_FDIRCTRL_FILTERMODE_CLOUD 0x0002 /* bit 23:21, 010b */ #define IXGBE_FDIRCTRL_SEARCHLIM 0x00800000 #define IXGBE_FDIRCTRL_FILTERMODE_MASK 0x00E00000 #define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT 24 #define IXGBE_FDIRCTRL_FULL_THRESH_MASK 0xF0000000 #define IXGBE_FDIRCTRL_FULL_THRESH_SHIFT 28 #define IXGBE_FDIRTCPM_DPORTM_SHIFT 16 #define IXGBE_FDIRUDPM_DPORTM_SHIFT 16 #define IXGBE_FDIRIP6M_DIPM_SHIFT 16 #define IXGBE_FDIRM_VLANID 0x00000001 #define IXGBE_FDIRM_VLANP 0x00000002 #define IXGBE_FDIRM_POOL 0x00000004 #define IXGBE_FDIRM_L4P 0x00000008 #define IXGBE_FDIRM_FLEX 0x00000010 #define IXGBE_FDIRM_DIPv6 0x00000020 #define IXGBE_FDIRM_L3P 0x00000040 #define IXGBE_FDIRIP6M_INNER_MAC 0x03F0 /* bit 9:4 */ #define IXGBE_FDIRIP6M_TUNNEL_TYPE 0x0800 /* bit 11 */ #define IXGBE_FDIRIP6M_TNI_VNI 0xF000 /* bit 15:12 */ #define IXGBE_FDIRIP6M_TNI_VNI_24 0x1000 /* bit 12 */ #define IXGBE_FDIRIP6M_ALWAYS_MASK 0x040F /* bit 10, 3:0 */ #define IXGBE_FDIRFREE_FREE_MASK 0xFFFF #define IXGBE_FDIRFREE_FREE_SHIFT 0 #define IXGBE_FDIRFREE_COLL_MASK 0x7FFF0000 #define IXGBE_FDIRFREE_COLL_SHIFT 16 #define IXGBE_FDIRLEN_MAXLEN_MASK 0x3F #define IXGBE_FDIRLEN_MAXLEN_SHIFT 0 #define IXGBE_FDIRLEN_MAXHASH_MASK 0x7FFF0000 #define IXGBE_FDIRLEN_MAXHASH_SHIFT 16 #define IXGBE_FDIRUSTAT_ADD_MASK 0xFFFF #define IXGBE_FDIRUSTAT_ADD_SHIFT 0 #define IXGBE_FDIRUSTAT_REMOVE_MASK 0xFFFF0000 #define IXGBE_FDIRUSTAT_REMOVE_SHIFT 16 #define IXGBE_FDIRFSTAT_FADD_MASK 0x00FF #define IXGBE_FDIRFSTAT_FADD_SHIFT 0 #define IXGBE_FDIRFSTAT_FREMOVE_MASK 0xFF00 #define IXGBE_FDIRFSTAT_FREMOVE_SHIFT 8 #define IXGBE_FDIRPORT_DESTINATION_SHIFT 16 #define IXGBE_FDIRVLAN_FLEX_SHIFT 16 #define IXGBE_FDIRHASH_BUCKET_VALID_SHIFT 15 #define IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT 16 #define IXGBE_FDIRCMD_CMD_MASK 0x00000003 #define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001 #define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002 #define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003 #define IXGBE_FDIRCMD_FILTER_VALID 0x00000004 #define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008 #define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010 #define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020 #define IXGBE_FDIRCMD_L4TYPE_TCP 0x00000040 #define IXGBE_FDIRCMD_L4TYPE_SCTP 0x00000060 #define IXGBE_FDIRCMD_IPV6 0x00000080 #define IXGBE_FDIRCMD_CLEARHT 0x00000100 #define IXGBE_FDIRCMD_DROP 0x00000200 #define IXGBE_FDIRCMD_INT 0x00000400 #define IXGBE_FDIRCMD_LAST 0x00000800 #define IXGBE_FDIRCMD_COLLISION 0x00001000 #define IXGBE_FDIRCMD_QUEUE_EN 0x00008000 #define IXGBE_FDIRCMD_FLOW_TYPE_SHIFT 5 #define IXGBE_FDIRCMD_RX_QUEUE_SHIFT 16 #define IXGBE_FDIRCMD_TUNNEL_FILTER_SHIFT 23 #define IXGBE_FDIRCMD_VT_POOL_SHIFT 24 #define IXGBE_FDIR_INIT_DONE_POLL 10 #define IXGBE_FDIRCMD_CMD_POLL 10 #define IXGBE_FDIRCMD_TUNNEL_FILTER 0x00800000 #define IXGBE_FDIR_DROP_QUEUE 127 /* Manageablility Host Interface defines */ #define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ #define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ #define IXGBE_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ #define IXGBE_HI_FLASH_ERASE_TIMEOUT 1000 /* Process Erase command limit */ #define IXGBE_HI_FLASH_UPDATE_TIMEOUT 5000 /* Process Update command limit */ #define IXGBE_HI_FLASH_APPLY_TIMEOUT 0 /* Process Apply command limit */ #define IXGBE_HI_PHY_MGMT_REQ_TIMEOUT 2000 /* Wait up to 2 seconds */ /* CEM Support */ #define FW_CEM_HDR_LEN 0x4 #define FW_CEM_CMD_DRIVER_INFO 0xDD #define FW_CEM_CMD_DRIVER_INFO_LEN 0x5 #define FW_CEM_CMD_RESERVED 0X0 #define FW_CEM_UNUSED_VER 0x0 #define FW_CEM_MAX_RETRIES 3 #define FW_CEM_RESP_STATUS_SUCCESS 0x1 #define FW_READ_SHADOW_RAM_CMD 0x31 #define FW_READ_SHADOW_RAM_LEN 0x6 #define FW_WRITE_SHADOW_RAM_CMD 0x33 #define FW_WRITE_SHADOW_RAM_LEN 0xA /* 8 plus 1 WORD to write */ #define FW_SHADOW_RAM_DUMP_CMD 0x36 #define FW_SHADOW_RAM_DUMP_LEN 0 #define FW_DEFAULT_CHECKSUM 0xFF /* checksum always 0xFF */ #define FW_NVM_DATA_OFFSET 3 #define FW_MAX_READ_BUFFER_SIZE 1024 #define FW_DISABLE_RXEN_CMD 0xDE #define FW_DISABLE_RXEN_LEN 0x1 #define FW_PHY_MGMT_REQ_CMD 0x20 /* Host Interface Command Structures */ struct ixgbe_hic_hdr { u8 cmd; u8 buf_len; union { u8 cmd_resv; u8 ret_status; } cmd_or_resp; u8 checksum; }; struct ixgbe_hic_hdr2_req { u8 cmd; u8 buf_lenh; u8 buf_lenl; u8 checksum; }; struct ixgbe_hic_hdr2_rsp { u8 cmd; u8 buf_lenl; u8 buf_lenh_status; /* 7-5: high bits of buf_len, 4-0: status */ u8 checksum; }; union ixgbe_hic_hdr2 { struct ixgbe_hic_hdr2_req req; struct ixgbe_hic_hdr2_rsp rsp; }; struct ixgbe_hic_drv_info { struct ixgbe_hic_hdr hdr; u8 port_num; u8 ver_sub; u8 ver_build; u8 ver_min; u8 ver_maj; u8 pad; /* end spacing to ensure length is mult. of dword */ u16 pad2; /* end spacing to ensure length is mult. of dword2 */ }; /* These need to be dword aligned */ struct ixgbe_hic_read_shadow_ram { union ixgbe_hic_hdr2 hdr; u32 address; u16 length; u16 pad2; u16 data; u16 pad3; }; struct ixgbe_hic_write_shadow_ram { union ixgbe_hic_hdr2 hdr; u32 address; u16 length; u16 pad2; u16 data; u16 pad3; }; struct ixgbe_hic_disable_rxen { struct ixgbe_hic_hdr hdr; u8 port_number; u8 pad2; u16 pad3; }; /* Transmit Descriptor - Legacy */ struct ixgbe_legacy_tx_desc { u64 buffer_addr; /* Address of the descriptor's data buffer */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 cso; /* Checksum offset */ u8 cmd; /* Descriptor control */ } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 css; /* Checksum start */ __le16 vlan; } fields; } upper; }; /* Transmit Descriptor - Advanced */ union ixgbe_adv_tx_desc { struct { __le64 buffer_addr; /* Address of descriptor's data buf */ __le32 cmd_type_len; __le32 olinfo_status; } read; struct { __le64 rsvd; /* Reserved */ __le32 nxtseq_seed; __le32 status; } wb; }; /* Receive Descriptor - Legacy */ struct ixgbe_legacy_rx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ __le16 length; /* Length of data DMAed into data buffer */ __le16 csum; /* Packet checksum */ u8 status; /* Descriptor status */ u8 errors; /* Descriptor Errors */ __le16 vlan; }; /* Receive Descriptor - Advanced */ union ixgbe_adv_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { __le32 data; struct { __le16 pkt_info; /* RSS, Pkt type */ __le16 hdr_info; /* Splithdr, hdrlen */ } hs_rss; } lo_dword; union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; /* Packet length */ __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; /* Context descriptors */ struct ixgbe_adv_tx_context_desc { __le32 vlan_macip_lens; __le32 seqnum_seed; __le32 type_tucmd_mlhl; __le32 mss_l4len_idx; }; /* Adv Transmit Descriptor Config Masks */ #define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */ #define IXGBE_ADVTXD_MAC_LINKSEC 0x00040000 /* Insert LinkSec */ #define IXGBE_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 time stamp */ #define IXGBE_ADVTXD_IPSEC_SA_INDEX_MASK 0x000003FF /* IPSec SA index */ #define IXGBE_ADVTXD_IPSEC_ESP_LEN_MASK 0x000001FF /* IPSec ESP length */ #define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */ #define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Adv Context Desc */ #define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Adv Data Descriptor */ #define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */ #define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */ #define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */ #define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext 1=Adv */ #define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE /* VLAN pkt enable */ #define IXGBE_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD /* Descriptor Done */ #define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED pres in WB */ #define IXGBE_ADVTXD_STAT_RSV 0x0000000C /* STA Reserved */ #define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ #define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */ #define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */ #define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \ IXGBE_ADVTXD_POPTS_SHIFT) #define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \ IXGBE_ADVTXD_POPTS_SHIFT) #define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ /* 1st&Last TSO-full iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 #define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */ #define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ #define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ #define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ #define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ #define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ #define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ #define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* req Markers and CRC */ #define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */ #define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */ #define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */ #define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */ #define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */ #define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation End */ #define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation Start */ #define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */ #define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */ #define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */ #define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ #define IXGBE_ADVTXD_OUTER_IPLEN 16 /* Adv ctxt OUTERIPLEN shift */ #define IXGBE_ADVTXD_TUNNEL_LEN 24 /* Adv ctxt TUNNELLEN shift */ #define IXGBE_ADVTXD_TUNNEL_TYPE_SHIFT 16 /* Adv Tx Desc Tunnel Type shift */ #define IXGBE_ADVTXD_OUTERIPCS_SHIFT 17 /* Adv Tx Desc OUTERIPCS Shift */ #define IXGBE_ADVTXD_TUNNEL_TYPE_NVGRE 1 /* Adv Tx Desc Tunnel Type NVGRE */ /* Autonegotiation advertised speeds */ typedef u32 ixgbe_autoneg_advertised; /* Link speed */ typedef u32 ixgbe_link_speed; #define IXGBE_LINK_SPEED_UNKNOWN 0 #define IXGBE_LINK_SPEED_100_FULL 0x0008 #define IXGBE_LINK_SPEED_1GB_FULL 0x0020 #define IXGBE_LINK_SPEED_2_5GB_FULL 0x0400 #define IXGBE_LINK_SPEED_5GB_FULL 0x0800 #define IXGBE_LINK_SPEED_10GB_FULL 0x0080 #define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) #define IXGBE_LINK_SPEED_82599_AUTONEG (IXGBE_LINK_SPEED_100_FULL | \ IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) /* Physical layer type */ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_UNKNOWN 0 #define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001 #define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002 #define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004 #define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008 #define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010 #define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020 #define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040 #define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080 #define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100 #define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200 #define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 #define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800 #define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000 #define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000 #define IXGBE_PHYSICAL_LAYER_1000BASE_SX 0x4000 /* Flow Control Data Sheet defined values * Calculation and defines taken from 802.1bb Annex O */ /* BitTimes (BT) conversion */ #define IXGBE_BT2KB(BT) ((BT + (8 * 1024 - 1)) / (8 * 1024)) #define IXGBE_B2BT(BT) (BT * 8) /* Calculate Delay to respond to PFC */ #define IXGBE_PFC_D 672 /* Calculate Cable Delay */ #define IXGBE_CABLE_DC 5556 /* Delay Copper */ #define IXGBE_CABLE_DO 5000 /* Delay Optical */ /* Calculate Interface Delay X540 */ #define IXGBE_PHY_DC 25600 /* Delay 10G BASET */ #define IXGBE_MAC_DC 8192 /* Delay Copper XAUI interface */ #define IXGBE_XAUI_DC (2 * 2048) /* Delay Copper Phy */ #define IXGBE_ID_X540 (IXGBE_MAC_DC + IXGBE_XAUI_DC + IXGBE_PHY_DC) /* Calculate Interface Delay 82598, 82599 */ #define IXGBE_PHY_D 12800 #define IXGBE_MAC_D 4096 #define IXGBE_XAUI_D (2 * 1024) #define IXGBE_ID (IXGBE_MAC_D + IXGBE_XAUI_D + IXGBE_PHY_D) /* Calculate Delay incurred from higher layer */ #define IXGBE_HD 6144 /* Calculate PCI Bus delay for low thresholds */ #define IXGBE_PCI_DELAY 10000 /* Calculate X540 delay value in bit times */ #define IXGBE_DV_X540(_max_frame_link, _max_frame_tc) \ ((36 * \ (IXGBE_B2BT(_max_frame_link) + \ IXGBE_PFC_D + \ (2 * IXGBE_CABLE_DC) + \ (2 * IXGBE_ID_X540) + \ IXGBE_HD) / 25 + 1) + \ 2 * IXGBE_B2BT(_max_frame_tc)) /* Calculate 82599, 82598 delay value in bit times */ #define IXGBE_DV(_max_frame_link, _max_frame_tc) \ ((36 * \ (IXGBE_B2BT(_max_frame_link) + \ IXGBE_PFC_D + \ (2 * IXGBE_CABLE_DC) + \ (2 * IXGBE_ID) + \ IXGBE_HD) / 25 + 1) + \ 2 * IXGBE_B2BT(_max_frame_tc)) /* Calculate low threshold delay values */ #define IXGBE_LOW_DV_X540(_max_frame_tc) \ (2 * IXGBE_B2BT(_max_frame_tc) + \ (36 * IXGBE_PCI_DELAY / 25) + 1) #define IXGBE_LOW_DV(_max_frame_tc) \ (2 * IXGBE_LOW_DV_X540(_max_frame_tc)) /* Software ATR hash keys */ #define IXGBE_ATR_BUCKET_HASH_KEY 0x3DAD14E2 #define IXGBE_ATR_SIGNATURE_HASH_KEY 0x174D3614 /* Software ATR input stream values and masks */ #define IXGBE_ATR_HASH_MASK 0x7fff #define IXGBE_ATR_L4TYPE_MASK 0x3 #define IXGBE_ATR_L4TYPE_UDP 0x1 #define IXGBE_ATR_L4TYPE_TCP 0x2 #define IXGBE_ATR_L4TYPE_SCTP 0x3 #define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4 #define IXGBE_ATR_L4TYPE_TUNNEL_MASK 0x10 enum ixgbe_atr_flow_type { IXGBE_ATR_FLOW_TYPE_IPV4 = 0x0, IXGBE_ATR_FLOW_TYPE_UDPV4 = 0x1, IXGBE_ATR_FLOW_TYPE_TCPV4 = 0x2, IXGBE_ATR_FLOW_TYPE_SCTPV4 = 0x3, IXGBE_ATR_FLOW_TYPE_IPV6 = 0x4, IXGBE_ATR_FLOW_TYPE_UDPV6 = 0x5, IXGBE_ATR_FLOW_TYPE_TCPV6 = 0x6, IXGBE_ATR_FLOW_TYPE_SCTPV6 = 0x7, IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV4 = 0x10, IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV4 = 0x11, IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV4 = 0x12, IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV4 = 0x13, IXGBE_ATR_FLOW_TYPE_TUNNELED_IPV6 = 0x14, IXGBE_ATR_FLOW_TYPE_TUNNELED_UDPV6 = 0x15, IXGBE_ATR_FLOW_TYPE_TUNNELED_TCPV6 = 0x16, IXGBE_ATR_FLOW_TYPE_TUNNELED_SCTPV6 = 0x17, }; /* Flow Director ATR input struct. */ union ixgbe_atr_input { /* * Byte layout in order, all values with MSB first: * * vm_pool - 1 byte * flow_type - 1 byte * vlan_id - 2 bytes * src_ip - 16 bytes * inner_mac - 6 bytes * cloud_mode - 2 bytes * tni_vni - 4 bytes * dst_ip - 16 bytes * src_port - 2 bytes * dst_port - 2 bytes * flex_bytes - 2 bytes * bkt_hash - 2 bytes */ struct { u8 vm_pool; u8 flow_type; __be16 vlan_id; __be32 dst_ip[4]; __be32 src_ip[4]; u8 inner_mac[6]; __be16 tunnel_type; __be32 tni_vni; __be16 src_port; __be16 dst_port; __be16 flex_bytes; __be16 bkt_hash; } formatted; __be32 dword_stream[14]; }; /* Flow Director compressed ATR hash input struct */ union ixgbe_atr_hash_dword { struct { u8 vm_pool; u8 flow_type; __be16 vlan_id; } formatted; __be32 ip; struct { __be16 src; __be16 dst; } port; __be16 flex_bytes; __be32 dword; }; #define IXGBE_MVALS_INIT(m) \ IXGBE_CAT(EEC, m), \ IXGBE_CAT(FLA, m), \ IXGBE_CAT(GRC, m), \ IXGBE_CAT(SRAMREL, m), \ IXGBE_CAT(FACTPS, m), \ IXGBE_CAT(SWSM, m), \ IXGBE_CAT(SWFW_SYNC, m), \ IXGBE_CAT(FWSM, m), \ IXGBE_CAT(SDP0_GPIEN, m), \ IXGBE_CAT(SDP1_GPIEN, m), \ IXGBE_CAT(SDP2_GPIEN, m), \ IXGBE_CAT(EICR_GPI_SDP0, m), \ IXGBE_CAT(EICR_GPI_SDP1, m), \ IXGBE_CAT(EICR_GPI_SDP2, m), \ IXGBE_CAT(CIAA, m), \ IXGBE_CAT(CIAD, m), \ IXGBE_CAT(I2C_CLK_IN, m), \ IXGBE_CAT(I2C_CLK_OUT, m), \ IXGBE_CAT(I2C_DATA_IN, m), \ IXGBE_CAT(I2C_DATA_OUT, m), \ IXGBE_CAT(I2C_DATA_OE_N_EN, m), \ IXGBE_CAT(I2C_BB_EN, m), \ IXGBE_CAT(I2C_CLK_OE_N_EN, m), \ IXGBE_CAT(I2CCTL, m) enum ixgbe_mvals { IXGBE_MVALS_INIT(_IDX), IXGBE_MVALS_IDX_LIMIT }; /* * Unavailable: The FCoE Boot Option ROM is not present in the flash. * Disabled: Present; boot order is not set for any targets on the port. * Enabled: Present; boot order is set for at least one target on the port. */ enum ixgbe_fcoe_boot_status { ixgbe_fcoe_bootstatus_disabled = 0, ixgbe_fcoe_bootstatus_enabled = 1, ixgbe_fcoe_bootstatus_unavailable = 0xFFFF }; enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, ixgbe_flash, ixgbe_eeprom_none /* No NVM support */ }; enum ixgbe_mac_type { ixgbe_mac_unknown = 0, ixgbe_mac_82598EB, ixgbe_mac_82599EB, ixgbe_mac_82599_vf, ixgbe_mac_X540, ixgbe_mac_X540_vf, ixgbe_mac_X550, ixgbe_mac_X550EM_x, ixgbe_mac_X550_vf, ixgbe_mac_X550EM_x_vf, ixgbe_num_macs }; enum ixgbe_phy_type { ixgbe_phy_unknown = 0, ixgbe_phy_none, ixgbe_phy_tn, ixgbe_phy_aq, ixgbe_phy_x550em_kr, ixgbe_phy_x550em_kx4, ixgbe_phy_x550em_ext_t, ixgbe_phy_cu_unknown, ixgbe_phy_qt, ixgbe_phy_xaui, ixgbe_phy_nl, ixgbe_phy_sfp_passive_tyco, ixgbe_phy_sfp_passive_unknown, ixgbe_phy_sfp_active_unknown, ixgbe_phy_sfp_avago, ixgbe_phy_sfp_ftl, ixgbe_phy_sfp_ftl_active, ixgbe_phy_sfp_unknown, ixgbe_phy_sfp_intel, ixgbe_phy_qsfp_passive_unknown, ixgbe_phy_qsfp_active_unknown, ixgbe_phy_qsfp_intel, ixgbe_phy_qsfp_unknown, ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/ ixgbe_phy_generic }; /* * SFP+ module type IDs: * * ID Module Type * ============= * 0 SFP_DA_CU * 1 SFP_SR * 2 SFP_LR * 3 SFP_DA_CU_CORE0 - 82599-specific * 4 SFP_DA_CU_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific */ enum ixgbe_sfp_type { ixgbe_sfp_type_da_cu = 0, ixgbe_sfp_type_sr = 1, ixgbe_sfp_type_lr = 2, ixgbe_sfp_type_da_cu_core0 = 3, ixgbe_sfp_type_da_cu_core1 = 4, ixgbe_sfp_type_srlr_core0 = 5, ixgbe_sfp_type_srlr_core1 = 6, ixgbe_sfp_type_da_act_lmt_core0 = 7, ixgbe_sfp_type_da_act_lmt_core1 = 8, ixgbe_sfp_type_1g_cu_core0 = 9, ixgbe_sfp_type_1g_cu_core1 = 10, ixgbe_sfp_type_1g_sx_core0 = 11, ixgbe_sfp_type_1g_sx_core1 = 12, ixgbe_sfp_type_1g_lx_core0 = 13, ixgbe_sfp_type_1g_lx_core1 = 14, ixgbe_sfp_type_not_present = 0xFFFE, ixgbe_sfp_type_unknown = 0xFFFF }; enum ixgbe_media_type { ixgbe_media_type_unknown = 0, ixgbe_media_type_fiber, ixgbe_media_type_fiber_qsfp, ixgbe_media_type_fiber_lco, ixgbe_media_type_copper, ixgbe_media_type_backplane, ixgbe_media_type_cx4, ixgbe_media_type_virtual }; /* Flow Control Settings */ enum ixgbe_fc_mode { ixgbe_fc_none = 0, ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, ixgbe_fc_full, ixgbe_fc_default }; /* Smart Speed Settings */ #define IXGBE_SMARTSPEED_MAX_RETRIES 3 enum ixgbe_smart_speed { ixgbe_smart_speed_auto = 0, ixgbe_smart_speed_on, ixgbe_smart_speed_off }; /* PCI bus types */ enum ixgbe_bus_type { ixgbe_bus_type_unknown = 0, ixgbe_bus_type_pci, ixgbe_bus_type_pcix, ixgbe_bus_type_pci_express, ixgbe_bus_type_internal, ixgbe_bus_type_reserved }; /* PCI bus speeds */ enum ixgbe_bus_speed { ixgbe_bus_speed_unknown = 0, ixgbe_bus_speed_33 = 33, ixgbe_bus_speed_66 = 66, ixgbe_bus_speed_100 = 100, ixgbe_bus_speed_120 = 120, ixgbe_bus_speed_133 = 133, ixgbe_bus_speed_2500 = 2500, ixgbe_bus_speed_5000 = 5000, ixgbe_bus_speed_8000 = 8000, ixgbe_bus_speed_reserved }; /* PCI bus widths */ enum ixgbe_bus_width { ixgbe_bus_width_unknown = 0, ixgbe_bus_width_pcie_x1 = 1, ixgbe_bus_width_pcie_x2 = 2, ixgbe_bus_width_pcie_x4 = 4, ixgbe_bus_width_pcie_x8 = 8, ixgbe_bus_width_32 = 32, ixgbe_bus_width_64 = 64, ixgbe_bus_width_reserved }; struct ixgbe_addr_filter_info { u32 num_mc_addrs; u32 rar_used_count; u32 mta_in_use; u32 overflow_promisc; bool user_set_promisc; }; /* Bus parameters */ struct ixgbe_bus_info { enum ixgbe_bus_speed speed; enum ixgbe_bus_width width; enum ixgbe_bus_type type; u16 func; u16 lan_id; }; /* Flow control parameters */ struct ixgbe_fc_info { u32 high_water[IXGBE_DCB_MAX_TRAFFIC_CLASS]; /* Flow Ctrl High-water */ u32 low_water[IXGBE_DCB_MAX_TRAFFIC_CLASS]; /* Flow Ctrl Low-water */ u16 pause_time; /* Flow Control Pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ bool disable_fc_autoneg; /* Do not autonegotiate FC */ bool fc_was_autonegged; /* Is current_mode the result of autonegging? */ enum ixgbe_fc_mode current_mode; /* FC mode in effect */ enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */ }; /* Statistics counters collected by the MAC */ struct ixgbe_hw_stats { u64 crcerrs; u64 illerrc; u64 errbc; u64 mspdc; u64 mpctotal; u64 mpc[8]; u64 mlfc; u64 mrfc; u64 rlec; u64 lxontxc; u64 lxonrxc; u64 lxofftxc; u64 lxoffrxc; u64 pxontxc[8]; u64 pxonrxc[8]; u64 pxofftxc[8]; u64 pxoffrxc[8]; u64 prc64; u64 prc127; u64 prc255; u64 prc511; u64 prc1023; u64 prc1522; u64 gprc; u64 bprc; u64 mprc; u64 gptc; u64 gorc; u64 gotc; u64 rnbc[8]; u64 ruc; u64 rfc; u64 roc; u64 rjc; u64 mngprc; u64 mngpdc; u64 mngptc; u64 tor; u64 tpr; u64 tpt; u64 ptc64; u64 ptc127; u64 ptc255; u64 ptc511; u64 ptc1023; u64 ptc1522; u64 mptc; u64 bptc; u64 xec; u64 qprc[16]; u64 qptc[16]; u64 qbrc[16]; u64 qbtc[16]; u64 qprdc[16]; u64 pxon2offc[8]; u64 fdirustat_add; u64 fdirustat_remove; u64 fdirfstat_fadd; u64 fdirfstat_fremove; u64 fdirmatch; u64 fdirmiss; u64 fccrc; u64 fclast; u64 fcoerpdc; u64 fcoeprc; u64 fcoeptc; u64 fcoedwrc; u64 fcoedwtc; u64 fcoe_noddp; u64 fcoe_noddp_ext_buff; u64 ldpcec; u64 pcrc8ec; u64 b2ospc; u64 b2ogprc; u64 o2bgptc; u64 o2bspc; }; /* forward declaration */ struct ixgbe_hw; /* iterator type for walking multicast address lists */ typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq); /* Function pointer table */ struct ixgbe_eeprom_operations { s32 (*init_params)(struct ixgbe_hw *); s32 (*read)(struct ixgbe_hw *, u16, u16 *); s32 (*read_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*write)(struct ixgbe_hw *, u16, u16); s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*update_checksum)(struct ixgbe_hw *); s32 (*calc_checksum)(struct ixgbe_hw *); }; struct ixgbe_mac_operations { s32 (*init_hw)(struct ixgbe_hw *); s32 (*reset_hw)(struct ixgbe_hw *); s32 (*start_hw)(struct ixgbe_hw *); s32 (*clear_hw_cntrs)(struct ixgbe_hw *); void (*enable_relaxed_ordering)(struct ixgbe_hw *); enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); u32 (*get_supported_physical_layer)(struct ixgbe_hw *); s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); s32 (*get_wwn_prefix)(struct ixgbe_hw *, u16 *, u16 *); s32 (*get_fcoe_boot_status)(struct ixgbe_hw *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*); s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8); s32 (*setup_sfp)(struct ixgbe_hw *); s32 (*enable_rx_dma)(struct ixgbe_hw *, u32); s32 (*disable_sec_rx_path)(struct ixgbe_hw *); s32 (*enable_sec_rx_path)(struct ixgbe_hw *); s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u32); void (*release_swfw_sync)(struct ixgbe_hw *, u32); s32 (*prot_autoc_read)(struct ixgbe_hw *, bool *, u32 *); s32 (*prot_autoc_write)(struct ixgbe_hw *, u32, bool); /* Link */ void (*disable_tx_laser)(struct ixgbe_hw *); void (*enable_tx_laser)(struct ixgbe_hw *); void (*flap_tx_laser)(struct ixgbe_hw *); s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); s32 (*setup_mac_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); void (*set_rate_select_speed)(struct ixgbe_hw *, ixgbe_link_speed); /* Packet Buffer manipulation */ void (*setup_rxpba)(struct ixgbe_hw *, int, u32, int); /* LED */ s32 (*led_on)(struct ixgbe_hw *, u32); s32 (*led_off)(struct ixgbe_hw *, u32); s32 (*blink_led_start)(struct ixgbe_hw *, u32); s32 (*blink_led_stop)(struct ixgbe_hw *, u32); /* RAR, Multicast, VLAN */ s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32); s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *); s32 (*clear_rar)(struct ixgbe_hw *, u32); s32 (*insert_mac_addr)(struct ixgbe_hw *, u8 *, u32); s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*set_vmdq_san_mac)(struct ixgbe_hw *, u32); s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*init_rx_addrs)(struct ixgbe_hw *); s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr); s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr, bool clear); s32 (*enable_mc)(struct ixgbe_hw *); s32 (*disable_mc)(struct ixgbe_hw *); s32 (*clear_vfta)(struct ixgbe_hw *); s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool); s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, bool *); s32 (*init_uta_tables)(struct ixgbe_hw *); void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int); void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int); /* Flow Control */ s32 (*fc_enable)(struct ixgbe_hw *); s32 (*setup_fc)(struct ixgbe_hw *); /* Manageability interface */ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8); s32 (*get_thermal_sensor_data)(struct ixgbe_hw *); s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw); void (*get_rtrup2tc)(struct ixgbe_hw *hw, u8 *map); void (*disable_rx)(struct ixgbe_hw *hw); void (*enable_rx)(struct ixgbe_hw *hw); void (*set_source_address_pruning)(struct ixgbe_hw *, bool, unsigned int); void (*set_ethertype_anti_spoofing)(struct ixgbe_hw *, bool, int); s32 (*dmac_update_tcs)(struct ixgbe_hw *hw); s32 (*dmac_config_tcs)(struct ixgbe_hw *hw); s32 (*dmac_config)(struct ixgbe_hw *hw); s32 (*setup_eee)(struct ixgbe_hw *hw, bool enable_eee); s32 (*read_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32 *); s32 (*write_iosf_sb_reg)(struct ixgbe_hw *, u32, u32, u32); void (*disable_mdd)(struct ixgbe_hw *hw); void (*enable_mdd)(struct ixgbe_hw *hw); void (*mdd_event)(struct ixgbe_hw *hw, u32 *vf_bitmap); void (*restore_mdd_vf)(struct ixgbe_hw *hw, u32 vf); }; struct ixgbe_phy_operations { s32 (*identify)(struct ixgbe_hw *); s32 (*identify_sfp)(struct ixgbe_hw *); s32 (*init)(struct ixgbe_hw *); s32 (*reset)(struct ixgbe_hw *); s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *); s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16); s32 (*read_reg_mdi)(struct ixgbe_hw *, u32, u32, u16 *); s32 (*write_reg_mdi)(struct ixgbe_hw *, u32, u32, u16); s32 (*setup_link)(struct ixgbe_hw *); s32 (*setup_internal_link)(struct ixgbe_hw *); s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *); s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *); s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *); s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); void (*i2c_bus_clear)(struct ixgbe_hw *); s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val); s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val); s32 (*check_overtemp)(struct ixgbe_hw *); s32 (*set_phy_power)(struct ixgbe_hw *, bool on); s32 (*enter_lplu)(struct ixgbe_hw *); s32 (*handle_lasi)(struct ixgbe_hw *hw); s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *value); s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, u16 value); s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, u8 *value); s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr, u8 value); }; struct ixgbe_eeprom_info { struct ixgbe_eeprom_operations ops; enum ixgbe_eeprom_type type; u32 semaphore_delay; u16 word_size; u16 address_bits; u16 word_page_size; u16 ctrl_word_3; }; #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01 struct ixgbe_mac_info { struct ixgbe_mac_operations ops; enum ixgbe_mac_type type; u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; /* prefix for World Wide Node Name (WWNN) */ u16 wwnn_prefix; /* prefix for World Wide Port Name (WWPN) */ u16 wwpn_prefix; #define IXGBE_MAX_MTA 128 u32 mta_shadow[IXGBE_MAX_MTA]; s32 mc_filter_type; u32 mcft_size; u32 vft_size; u32 num_rar_entries; u32 rar_highwater; u32 rx_pb_size; u32 max_tx_queues; u32 max_rx_queues; u32 orig_autoc; u8 san_mac_rar_index; bool get_link_status; u32 orig_autoc2; u16 max_msix_vectors; bool arc_subsystem_valid; bool orig_link_settings_stored; bool autotry_restart; u8 flags; struct ixgbe_thermal_sensor_data thermal_sensor_data; bool thermal_sensor_enabled; struct ixgbe_dmac_config dmac_config; bool set_lben; u32 max_link_up_time; }; struct ixgbe_phy_info { struct ixgbe_phy_operations ops; enum ixgbe_phy_type type; u32 addr; u32 id; enum ixgbe_sfp_type sfp_type; bool sfp_setup_needed; u32 revision; enum ixgbe_media_type media_type; u32 phy_semaphore_mask; bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; enum ixgbe_smart_speed smart_speed; bool smart_speed_active; bool multispeed_fiber; bool reset_if_overtemp; bool qsfp_shared_i2c_bus; u32 nw_mng_if_sel; }; #include "ixgbe_mbx.h" struct ixgbe_mbx_operations { void (*init_params)(struct ixgbe_hw *hw); s32 (*read)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*write)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*check_for_msg)(struct ixgbe_hw *, u16); s32 (*check_for_ack)(struct ixgbe_hw *, u16); s32 (*check_for_rst)(struct ixgbe_hw *, u16); }; struct ixgbe_mbx_stats { u32 msgs_tx; u32 msgs_rx; u32 acks; u32 reqs; u32 rsts; }; struct ixgbe_mbx_info { struct ixgbe_mbx_operations ops; struct ixgbe_mbx_stats stats; u32 timeout; u32 usec_delay; u32 v2p_mailbox; u16 size; }; struct ixgbe_hw { u8 IOMEM *hw_addr; void *back; struct ixgbe_mac_info mac; struct ixgbe_addr_filter_info addr_ctrl; struct ixgbe_fc_info fc; struct ixgbe_phy_info phy; struct ixgbe_eeprom_info eeprom; struct ixgbe_bus_info bus; struct ixgbe_mbx_info mbx; const u32 *mvals; u16 device_id; u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; u8 revision_id; bool adapter_stopped; int api_version; bool force_full_reset; bool allow_unsupported_sfp; bool wol_enabled; }; #define ixgbe_call_func(hw, func, params, error) \ (func != NULL) ? func params : error /* Error Codes */ #define IXGBE_SUCCESS 0 #define IXGBE_ERR_EEPROM -1 #define IXGBE_ERR_EEPROM_CHECKSUM -2 #define IXGBE_ERR_PHY -3 #define IXGBE_ERR_CONFIG -4 #define IXGBE_ERR_PARAM -5 #define IXGBE_ERR_MAC_TYPE -6 #define IXGBE_ERR_UNKNOWN_PHY -7 #define IXGBE_ERR_LINK_SETUP -8 #define IXGBE_ERR_ADAPTER_STOPPED -9 #define IXGBE_ERR_INVALID_MAC_ADDR -10 #define IXGBE_ERR_DEVICE_NOT_SUPPORTED -11 #define IXGBE_ERR_MASTER_REQUESTS_PENDING -12 #define IXGBE_ERR_INVALID_LINK_SETTINGS -13 #define IXGBE_ERR_AUTONEG_NOT_COMPLETE -14 #define IXGBE_ERR_RESET_FAILED -15 #define IXGBE_ERR_SWFW_SYNC -16 #define IXGBE_ERR_PHY_ADDR_INVALID -17 #define IXGBE_ERR_I2C -18 #define IXGBE_ERR_SFP_NOT_SUPPORTED -19 #define IXGBE_ERR_SFP_NOT_PRESENT -20 #define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT -21 #define IXGBE_ERR_NO_SAN_ADDR_PTR -22 #define IXGBE_ERR_FDIR_REINIT_FAILED -23 #define IXGBE_ERR_EEPROM_VERSION -24 #define IXGBE_ERR_NO_SPACE -25 #define IXGBE_ERR_OVERTEMP -26 #define IXGBE_ERR_FC_NOT_NEGOTIATED -27 #define IXGBE_ERR_FC_NOT_SUPPORTED -28 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30 #define IXGBE_ERR_PBA_SECTION -31 #define IXGBE_ERR_INVALID_ARGUMENT -32 #define IXGBE_ERR_HOST_INTERFACE_COMMAND -33 #define IXGBE_ERR_OUT_OF_MEM -34 #define IXGBE_ERR_FEATURE_NOT_SUPPORTED -36 #define IXGBE_ERR_EEPROM_PROTECTED_REGION -37 #define IXGBE_ERR_FDIR_CMD_INCOMPLETE -38 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #define IXGBE_FUSES0_GROUP(_i) (0x11158 + ((_i) * 4)) #define IXGBE_FUSES0_300MHZ (1 << 5) #define IXGBE_FUSES0_REV1 (1 << 6) #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010) #define IXGBE_KRM_LINK_CTRL_1(P) ((P) ? 0x820C : 0x420C) #define IXGBE_KRM_AN_CNTL_1(P) ((P) ? 0x822C : 0x422C) #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634) #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P) ((P) ? 0x8B00 : 0x4B00) #define IXGBE_KRM_PMD_DFX_BURNIN(P) ((P) ? 0x8E00 : 0x4E00) #define IXGBE_KRM_TX_COEFF_CTRL_1(P) ((P) ? 0x9520 : 0x5520) #define IXGBE_KRM_RX_ANA_CTL(P) ((P) ? 0x9A00 : 0x5A00) #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B (1 << 9) #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS (1 << 11) #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK (0x7 << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G (2 << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G (4 << 8) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ (1 << 14) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC (1 << 15) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX (1 << 16) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR (1 << 18) #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX (1 << 24) #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR (1 << 26) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE (1 << 29) #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART (1 << 31) #define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE (1 << 28) #define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE (1 << 29) #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN (1 << 6) #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN (1 << 15) #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN (1 << 16) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL (1 << 4) #define IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS (1 << 2) #define IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK (0x3 << 16) #define IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN (1 << 1) #define IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN (1 << 2) #define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN (1 << 3) #define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN (1 << 31) #define IXGBE_KX4_LINK_CNTL_1 0x4C #define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX (1 << 16) #define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 (1 << 17) #define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX (1 << 24) #define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4 (1 << 25) #define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE (1 << 29) #define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP (1 << 30) #define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART (1 << 31) #define IXGBE_SB_IOSF_INDIRECT_CTRL 0x00011144 #define IXGBE_SB_IOSF_INDIRECT_DATA 0x00011148 #define IXGBE_SB_IOSF_CTRL_ADDR_SHIFT 0 #define IXGBE_SB_IOSF_CTRL_ADDR_MASK 0xFF #define IXGBE_SB_IOSF_CTRL_RESP_STAT_SHIFT 18 #define IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK \ (0x3 << IXGBE_SB_IOSF_CTRL_RESP_STAT_SHIFT) #define IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT 20 #define IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK \ (0xFF << IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT) #define IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT 28 #define IXGBE_SB_IOSF_CTRL_TARGET_SELECT_MASK 0x7 #define IXGBE_SB_IOSF_CTRL_BUSY_SHIFT 31 #define IXGBE_SB_IOSF_CTRL_BUSY (1 << IXGBE_SB_IOSF_CTRL_BUSY_SHIFT) #define IXGBE_SB_IOSF_TARGET_KR_PHY 0 #define IXGBE_SB_IOSF_TARGET_KX4_PHY 1 #define IXGBE_SB_IOSF_TARGET_KX4_PCS 2 #define IXGBE_NW_MNG_IF_SEL 0x00011178 #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24) #endif /* _IXGBE_TYPE_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_vf.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_type.h" #include "ixgbe_vf.h" #ifndef IXGBE_VFWRITE_REG #define IXGBE_VFWRITE_REG IXGBE_WRITE_REG #endif #ifndef IXGBE_VFREAD_REG #define IXGBE_VFREAD_REG IXGBE_READ_REG #endif /** * ixgbe_init_ops_vf - Initialize the pointers for vf * @hw: pointer to hardware structure * * This will assign function pointers, adapter-specific functions can * override the assignment of generic function pointers by assigning * their own adapter-specific function pointers. * Does not touch the hardware. **/ s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw) { /* MAC */ hw->mac.ops.init_hw = ixgbe_init_hw_vf; hw->mac.ops.reset_hw = ixgbe_reset_hw_vf; hw->mac.ops.start_hw = ixgbe_start_hw_vf; /* Cannot clear stats on VF */ hw->mac.ops.clear_hw_cntrs = NULL; hw->mac.ops.get_media_type = NULL; hw->mac.ops.get_mac_addr = ixgbe_get_mac_addr_vf; hw->mac.ops.stop_adapter = ixgbe_stop_adapter_vf; hw->mac.ops.get_bus_info = NULL; /* Link */ hw->mac.ops.setup_link = ixgbe_setup_mac_link_vf; hw->mac.ops.check_link = ixgbe_check_mac_link_vf; hw->mac.ops.get_link_capabilities = NULL; /* RAR, Multicast, VLAN */ hw->mac.ops.set_rar = ixgbe_set_rar_vf; hw->mac.ops.set_uc_addr = ixgbevf_set_uc_addr_vf; hw->mac.ops.init_rx_addrs = NULL; hw->mac.ops.update_mc_addr_list = ixgbe_update_mc_addr_list_vf; hw->mac.ops.enable_mc = NULL; hw->mac.ops.disable_mc = NULL; hw->mac.ops.clear_vfta = NULL; hw->mac.ops.set_vfta = ixgbe_set_vfta_vf; hw->mac.max_tx_queues = 1; hw->mac.max_rx_queues = 1; hw->mbx.ops.init_params = ixgbe_init_mbx_params_vf; return IXGBE_SUCCESS; } /* ixgbe_virt_clr_reg - Set register to default (power on) state. * @hw: pointer to hardware structure */ static void ixgbe_virt_clr_reg(struct ixgbe_hw *hw) { int i; u32 vfsrrctl; u32 vfdca_rxctrl; u32 vfdca_txctrl; /* VRSRRCTL default values (BSIZEPACKET = 2048, BSIZEHEADER = 256) */ vfsrrctl = 0x100 << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT; vfsrrctl |= 0x800 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; /* DCA_RXCTRL default value */ vfdca_rxctrl = IXGBE_DCA_RXCTRL_DESC_RRO_EN | IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN; /* DCA_TXCTRL default value */ vfdca_txctrl = IXGBE_DCA_TXCTRL_DESC_RRO_EN | IXGBE_DCA_TXCTRL_DESC_WRO_EN | IXGBE_DCA_TXCTRL_DATA_RRO_EN; IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, 0); for (i = 0; i < 7; i++) { IXGBE_WRITE_REG(hw, IXGBE_VFRDH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFRDT(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), vfsrrctl); IXGBE_WRITE_REG(hw, IXGBE_VFTDH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTDT(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFDCA_RXCTRL(i), vfdca_rxctrl); IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i), vfdca_txctrl); } IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_start_hw_vf - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ s32 ixgbe_start_hw_vf(struct ixgbe_hw *hw) { /* Clear adapter stopped flag */ hw->adapter_stopped = false; return IXGBE_SUCCESS; } /** * ixgbe_init_hw_vf - virtual function hardware initialization * @hw: pointer to hardware structure * * Initialize the hardware by resetting the hardware and then starting * the hardware **/ s32 ixgbe_init_hw_vf(struct ixgbe_hw *hw) { s32 status = hw->mac.ops.start_hw(hw); hw->mac.ops.get_mac_addr(hw, hw->mac.addr); return status; } /** * ixgbe_reset_hw_vf - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by reseting the transmit and receive units, masks and * clears all interrupts. **/ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 timeout = IXGBE_VF_INIT_TIMEOUT; s32 ret_val = IXGBE_ERR_INVALID_MAC_ADDR; u32 msgbuf[IXGBE_VF_PERMADDR_MSG_LEN]; u8 *addr = (u8 *)(&msgbuf[1]); DEBUGFUNC("ixgbevf_reset_hw_vf"); /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); /* reset the api version */ hw->api_version = ixgbe_mbox_api_10; DEBUGOUT("Issuing a function level reset to MAC\n"); IXGBE_VFWRITE_REG(hw, IXGBE_VFCTRL, IXGBE_CTRL_RST); IXGBE_WRITE_FLUSH(hw); msec_delay(50); /* we cannot reset while the RSTI / RSTD bits are asserted */ while (!mbx->ops.check_for_rst(hw, 0) && timeout) { timeout--; usec_delay(5); } if (!timeout) return IXGBE_ERR_RESET_FAILED; /* Reset VF registers to initial values */ ixgbe_virt_clr_reg(hw); /* mailbox timeout can now become active */ mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; msgbuf[0] = IXGBE_VF_RESET; mbx->ops.write_posted(hw, msgbuf, 1, 0); msec_delay(10); /* * set our "perm_addr" based on info provided by PF * also set up the mc_filter_type which is piggy backed * on the mac address in word 3 */ ret_val = mbx->ops.read_posted(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, 0); if (ret_val) return ret_val; if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) && msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK)) return IXGBE_ERR_INVALID_MAC_ADDR; memcpy(hw->mac.perm_addr, addr, IXGBE_ETH_LENGTH_OF_ADDRESS); hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD]; return ret_val; } /** * ixgbe_stop_adapter_vf - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ s32 ixgbe_stop_adapter_vf(struct ixgbe_hw *hw) { u32 reg_val; u16 i; /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware */ hw->adapter_stopped = true; /* Clear interrupt mask to stop from interrupts being generated */ IXGBE_VFWRITE_REG(hw, IXGBE_VTEIMC, IXGBE_VF_IRQ_CLEAR_MASK); /* Clear any pending interrupts, flush previous writes */ IXGBE_VFREAD_REG(hw, IXGBE_VTEICR); /* Disable the transmit unit. Each queue must be disabled. */ for (i = 0; i < hw->mac.max_tx_queues; i++) IXGBE_VFWRITE_REG(hw, IXGBE_VFTXDCTL(i), IXGBE_TXDCTL_SWFLSH); /* Disable the receive unit by stopping each queue */ for (i = 0; i < hw->mac.max_rx_queues; i++) { reg_val = IXGBE_VFREAD_REG(hw, IXGBE_VFRXDCTL(i)); reg_val &= ~IXGBE_RXDCTL_ENABLE; IXGBE_VFWRITE_REG(hw, IXGBE_VFRXDCTL(i), reg_val); } /* Clear packet split and pool config */ IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, 0); /* flush all queues disables */ IXGBE_WRITE_FLUSH(hw); msec_delay(2); return IXGBE_SUCCESS; } /** * ixgbe_mta_vector - Determines bit-vector in multicast table to set * @hw: pointer to hardware structure * @mc_addr: the multicast address * * Extracts the 12 bits, from a multicast address, to determine which * bit-vector to set in the multicast table. The hardware uses 12 bits, from * incoming rx multicast addresses, to determine the bit-vector to check in * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ STATIC s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector = 0; switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); break; case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); break; case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); break; case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); break; default: /* Invalid mc_filter_type */ DEBUGOUT("MC filter type param set incorrectly\n"); ASSERT(0); break; } /* vector can only be 12-bits or boundary will be exceeded */ vector &= 0xFFF; return vector; } STATIC void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, u32 *msg, u16 size) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 retmsg[IXGBE_VFMAILBOX_SIZE]; s32 retval = mbx->ops.write_posted(hw, msg, size, 0); if (!retval) mbx->ops.read_posted(hw, retmsg, size, 0); } /** * ixgbe_set_rar_vf - set device MAC address * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: VMDq "set" or "pool" index * @enable_addr: set flag that address is active **/ s32 ixgbe_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val; UNREFERENCED_3PARAMETER(vmdq, enable_addr, index); memset(msgbuf, 0, 12); msgbuf[0] = IXGBE_VF_SET_MAC_ADDR; memcpy(msg_addr, addr, 6); ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0); msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) ixgbe_get_mac_addr_vf(hw, hw->mac.addr); return ret_val; } /** * ixgbe_update_mc_addr_list_vf - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * @next: caller supplied function to return next address in list * * Updates the Multicast Table Array. **/ s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr next, bool clear) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; u16 *vector_list = (u16 *)&msgbuf[1]; u32 vector; u32 cnt, i; u32 vmdq; UNREFERENCED_1PARAMETER(clear); DEBUGFUNC("ixgbe_update_mc_addr_list_vf"); /* Each entry in the list uses 1 16 bit word. We have 30 * 16 bit words available in our HW msg buffer (minus 1 for the * msg type). That's 30 hash values if we pack 'em right. If * there are more than 30 MC addresses to add then punt the * extras for now and then add code to handle more than 30 later. * It would be unusual for a server to request that many multi-cast * addresses except for in large enterprise network environments. */ DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count); cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; msgbuf[0] = IXGBE_VF_SET_MULTICAST; msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT; for (i = 0; i < cnt; i++) { vector = ixgbe_mta_vector(hw, next(hw, &mc_addr_list, &vmdq)); DEBUGOUT1("Hash value = 0x%03X\n", vector); vector_list[i] = (u16)vector; } return mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE, 0); } /** * ixgbe_set_vfta_vf - Set/Unset vlan filter table address * @hw: pointer to the HW structure * @vlan: 12 bit VLAN ID * @vind: unused by VF drivers * @vlan_on: if true then set bit, else clear bit **/ s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[2]; s32 ret_val; UNREFERENCED_1PARAMETER(vind); msgbuf[0] = IXGBE_VF_SET_VLAN; msgbuf[1] = vlan; /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT; ret_val = mbx->ops.write_posted(hw, msgbuf, 2, 0); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 1, 0); if (!ret_val && (msgbuf[0] & IXGBE_VT_MSGTYPE_ACK)) return IXGBE_SUCCESS; return ret_val | (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK); } /** * ixgbe_get_num_of_tx_queues_vf - Get number of TX queues * @hw: pointer to hardware structure * * Returns the number of transmit queues for the given adapter. **/ u32 ixgbe_get_num_of_tx_queues_vf(struct ixgbe_hw *hw) { UNREFERENCED_1PARAMETER(hw); return IXGBE_VF_MAX_TX_QUEUES; } /** * ixgbe_get_num_of_rx_queues_vf - Get number of RX queues * @hw: pointer to hardware structure * * Returns the number of receive queues for the given adapter. **/ u32 ixgbe_get_num_of_rx_queues_vf(struct ixgbe_hw *hw) { UNREFERENCED_1PARAMETER(hw); return IXGBE_VF_MAX_RX_QUEUES; } /** * ixgbe_get_mac_addr_vf - Read device MAC address * @hw: pointer to the HW structure **/ s32 ixgbe_get_mac_addr_vf(struct ixgbe_hw *hw, u8 *mac_addr) { int i; for (i = 0; i < IXGBE_ETH_LENGTH_OF_ADDRESS; i++) mac_addr[i] = hw->mac.perm_addr[i]; return IXGBE_SUCCESS; } s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr) { struct ixgbe_mbx_info *mbx = &hw->mbx; u32 msgbuf[3]; u8 *msg_addr = (u8 *)(&msgbuf[1]); s32 ret_val; memset(msgbuf, 0, sizeof(msgbuf)); /* * If index is one then this is the start of a new list and needs * indication to the PF so it can do it's own list management. * If it is zero then that tells the PF to just clear all of * this VF's macvlans and there is no new list. */ msgbuf[0] |= index << IXGBE_VT_MSGINFO_SHIFT; msgbuf[0] |= IXGBE_VF_SET_MACVLAN; if (addr) memcpy(msg_addr, addr, 6); ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0); if (!ret_val) ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0); msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; if (!ret_val) if (msgbuf[0] == (IXGBE_VF_SET_MACVLAN | IXGBE_VT_MSGTYPE_NACK)) ret_val = IXGBE_ERR_OUT_OF_MEM; return ret_val; } /** * ixgbe_setup_mac_link_vf - Setup MAC link settings * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ s32 ixgbe_setup_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { UNREFERENCED_3PARAMETER(hw, speed, autoneg_wait_to_complete); return IXGBE_SUCCESS; } /** * ixgbe_check_mac_link_vf - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise * @autoneg_wait_to_complete: true when waiting for completion is needed * * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool autoneg_wait_to_complete) { struct ixgbe_mbx_info *mbx = &hw->mbx; struct ixgbe_mac_info *mac = &hw->mac; s32 ret_val = IXGBE_SUCCESS; u32 links_reg; u32 in_msg = 0; UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); /* If we were hit with a reset drop the link */ if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout) mac->get_link_status = true; if (!mac->get_link_status) goto out; /* if link status is down no point in checking to see if pf is up */ links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS); if (!(links_reg & IXGBE_LINKS_UP)) goto out; /* for SFP+ modules and DA cables on 82599 it can take up to 500usecs * before the link status is correct */ if (mac->type == ixgbe_mac_82599_vf) { int i; for (i = 0; i < 5; i++) { usec_delay(100); links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS); if (!(links_reg & IXGBE_LINKS_UP)) goto out; } } switch (links_reg & IXGBE_LINKS_SPEED_82599) { case IXGBE_LINKS_SPEED_10G_82599: *speed = IXGBE_LINK_SPEED_10GB_FULL; break; case IXGBE_LINKS_SPEED_1G_82599: *speed = IXGBE_LINK_SPEED_1GB_FULL; break; case IXGBE_LINKS_SPEED_100_82599: *speed = IXGBE_LINK_SPEED_100_FULL; break; } /* if the read failed it could just be a mailbox collision, best wait * until we are called again and don't report an error */ if (mbx->ops.read(hw, &in_msg, 1, 0)) goto out; if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) { /* msg is not CTS and is NACK we must have lost CTS status */ if (in_msg & IXGBE_VT_MSGTYPE_NACK) ret_val = -1; goto out; } /* the pf is talking, if we timed out in the past we reinit */ if (!mbx->timeout) { ret_val = -1; goto out; } /* if we passed all the tests above then the link is up and we no * longer need to check for link */ mac->get_link_status = false; out: *link_up = !mac->get_link_status; return ret_val; } /** * ixgbevf_rlpml_set_vf - Set the maximum receive packet length * @hw: pointer to the HW structure * @max_size: value to assign to max frame size **/ void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size) { u32 msgbuf[2]; msgbuf[0] = IXGBE_VF_SET_LPE; msgbuf[1] = max_size; ixgbevf_write_msg_read_ack(hw, msgbuf, 2); } /** * ixgbevf_negotiate_api_version - Negotiate supported API version * @hw: pointer to the HW structure * @api: integer containing requested API version **/ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api) { int err; u32 msg[3]; /* Negotiate the mailbox API version */ msg[0] = IXGBE_VF_API_NEGOTIATE; msg[1] = api; msg[2] = 0; err = hw->mbx.ops.write_posted(hw, msg, 3, 0); if (!err) err = hw->mbx.ops.read_posted(hw, msg, 3, 0); if (!err) { msg[0] &= ~IXGBE_VT_MSGTYPE_CTS; /* Store value and return 0 on success */ if (msg[0] == (IXGBE_VF_API_NEGOTIATE | IXGBE_VT_MSGTYPE_ACK)) { hw->api_version = api; return 0; } err = IXGBE_ERR_INVALID_ARGUMENT; } return err; } int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs, unsigned int *default_tc) { int err; u32 msg[5]; /* do nothing if API doesn't support ixgbevf_get_queues */ switch (hw->api_version) { case ixgbe_mbox_api_11: break; default: return 0; } /* Fetch queue configuration from the PF */ msg[0] = IXGBE_VF_GET_QUEUES; msg[1] = msg[2] = msg[3] = msg[4] = 0; err = hw->mbx.ops.write_posted(hw, msg, 5, 0); if (!err) err = hw->mbx.ops.read_posted(hw, msg, 5, 0); if (!err) { msg[0] &= ~IXGBE_VT_MSGTYPE_CTS; /* * if we we didn't get an ACK there must have been * some sort of mailbox error so we should treat it * as such */ if (msg[0] != (IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK)) return IXGBE_ERR_MBX; /* record and validate values from message */ hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES]; if (hw->mac.max_tx_queues == 0 || hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES) hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES; hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES]; if (hw->mac.max_rx_queues == 0 || hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES) hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES; *num_tcs = msg[IXGBE_VF_TRANS_VLAN]; /* in case of unknown state assume we cannot tag frames */ if (*num_tcs > hw->mac.max_rx_queues) *num_tcs = 1; *default_tc = msg[IXGBE_VF_DEF_QUEUE]; /* default to queue 0 on out-of-bounds queue number */ if (*default_tc >= hw->mac.max_tx_queues) *default_tc = 0; } return err; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_vf.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef __IXGBE_VF_H__ #define __IXGBE_VF_H__ #define IXGBE_VF_IRQ_CLEAR_MASK 7 #define IXGBE_VF_MAX_TX_QUEUES 8 #define IXGBE_VF_MAX_RX_QUEUES 8 /* DCB define */ #define IXGBE_VF_MAX_TRAFFIC_CLASS 8 #define IXGBE_VFCTRL 0x00000 #define IXGBE_VFSTATUS 0x00008 #define IXGBE_VFLINKS 0x00010 #define IXGBE_VFFRTIMER 0x00048 #define IXGBE_VFRXMEMWRAP 0x03190 #define IXGBE_VTEICR 0x00100 #define IXGBE_VTEICS 0x00104 #define IXGBE_VTEIMS 0x00108 #define IXGBE_VTEIMC 0x0010C #define IXGBE_VTEIAC 0x00110 #define IXGBE_VTEIAM 0x00114 #define IXGBE_VTEITR(x) (0x00820 + (4 * (x))) #define IXGBE_VTIVAR(x) (0x00120 + (4 * (x))) #define IXGBE_VTIVAR_MISC 0x00140 #define IXGBE_VTRSCINT(x) (0x00180 + (4 * (x))) /* define IXGBE_VFPBACL still says TBD in EAS */ #define IXGBE_VFRDBAL(x) (0x01000 + (0x40 * (x))) #define IXGBE_VFRDBAH(x) (0x01004 + (0x40 * (x))) #define IXGBE_VFRDLEN(x) (0x01008 + (0x40 * (x))) #define IXGBE_VFRDH(x) (0x01010 + (0x40 * (x))) #define IXGBE_VFRDT(x) (0x01018 + (0x40 * (x))) #define IXGBE_VFRXDCTL(x) (0x01028 + (0x40 * (x))) #define IXGBE_VFSRRCTL(x) (0x01014 + (0x40 * (x))) #define IXGBE_VFRSCCTL(x) (0x0102C + (0x40 * (x))) #define IXGBE_VFPSRTYPE 0x00300 #define IXGBE_VFTDBAL(x) (0x02000 + (0x40 * (x))) #define IXGBE_VFTDBAH(x) (0x02004 + (0x40 * (x))) #define IXGBE_VFTDLEN(x) (0x02008 + (0x40 * (x))) #define IXGBE_VFTDH(x) (0x02010 + (0x40 * (x))) #define IXGBE_VFTDT(x) (0x02018 + (0x40 * (x))) #define IXGBE_VFTXDCTL(x) (0x02028 + (0x40 * (x))) #define IXGBE_VFTDWBAL(x) (0x02038 + (0x40 * (x))) #define IXGBE_VFTDWBAH(x) (0x0203C + (0x40 * (x))) #define IXGBE_VFDCA_RXCTRL(x) (0x0100C + (0x40 * (x))) #define IXGBE_VFDCA_TXCTRL(x) (0x0200c + (0x40 * (x))) #define IXGBE_VFGPRC 0x0101C #define IXGBE_VFGPTC 0x0201C #define IXGBE_VFGORC_LSB 0x01020 #define IXGBE_VFGORC_MSB 0x01024 #define IXGBE_VFGOTC_LSB 0x02020 #define IXGBE_VFGOTC_MSB 0x02024 #define IXGBE_VFMPRC 0x01034 #define IXGBE_VFMRQC 0x3000 #define IXGBE_VFRSSRK(x) (0x3100 + ((x) * 4)) #define IXGBE_VFRETA(x) (0x3200 + ((x) * 4)) struct ixgbevf_hw_stats { u64 base_vfgprc; u64 base_vfgptc; u64 base_vfgorc; u64 base_vfgotc; u64 base_vfmprc; u64 last_vfgprc; u64 last_vfgptc; u64 last_vfgorc; u64 last_vfgotc; u64 last_vfmprc; u64 vfgprc; u64 vfgptc; u64 vfgorc; u64 vfgotc; u64 vfmprc; u64 saved_reset_vfgprc; u64 saved_reset_vfgptc; u64 saved_reset_vfgorc; u64 saved_reset_vfgotc; u64 saved_reset_vfmprc; }; s32 ixgbe_init_hw_vf(struct ixgbe_hw *hw); s32 ixgbe_start_hw_vf(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw); s32 ixgbe_stop_adapter_vf(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_tx_queues_vf(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_rx_queues_vf(struct ixgbe_hw *hw); s32 ixgbe_get_mac_addr_vf(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_setup_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool autoneg_wait_to_complete); s32 ixgbe_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr); s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr, bool clear); s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size); int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api); int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs, unsigned int *default_tc); #endif /* __IXGBE_VF_H__ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_x540.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_x540.h" #include "ixgbe_type.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" #define IXGBE_X540_MAX_TX_QUEUES 128 #define IXGBE_X540_MAX_RX_QUEUES 128 #define IXGBE_X540_RAR_ENTRIES 128 #define IXGBE_X540_MC_TBL_SIZE 128 #define IXGBE_X540_VFT_TBL_SIZE 128 #define IXGBE_X540_RX_PB_SIZE 384 STATIC s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw); STATIC s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw); STATIC void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw); /** * ixgbe_init_ops_X540 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for X540. * Does not touch the hardware. **/ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; DEBUGFUNC("ixgbe_init_ops_X540"); ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* EEPROM */ eeprom->ops.init_params = ixgbe_init_eeprom_params_X540; eeprom->ops.read = ixgbe_read_eerd_X540; eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_X540; eeprom->ops.write = ixgbe_write_eewr_X540; eeprom->ops.write_buffer = ixgbe_write_eewr_buffer_X540; eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X540; eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X540; eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X540; /* PHY */ phy->ops.init = ixgbe_init_phy_ops_generic; phy->ops.reset = NULL; if (!ixgbe_mng_present(hw)) phy->ops.set_phy_power = ixgbe_set_copper_phy_power; /* MAC */ mac->ops.reset_hw = ixgbe_reset_hw_X540; mac->ops.enable_relaxed_ordering = ixgbe_enable_relaxed_ordering_gen2; mac->ops.get_media_type = ixgbe_get_media_type_X540; mac->ops.get_supported_physical_layer = ixgbe_get_supported_physical_layer_X540; mac->ops.read_analog_reg8 = NULL; mac->ops.write_analog_reg8 = NULL; mac->ops.start_hw = ixgbe_start_hw_X540; mac->ops.get_san_mac_addr = ixgbe_get_san_mac_addr_generic; mac->ops.set_san_mac_addr = ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = ixgbe_get_device_caps_generic; mac->ops.get_wwn_prefix = ixgbe_get_wwn_prefix_generic; mac->ops.get_fcoe_boot_status = ixgbe_get_fcoe_boot_status_generic; mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540; mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X540; mac->ops.disable_sec_rx_path = ixgbe_disable_sec_rx_path_generic; mac->ops.enable_sec_rx_path = ixgbe_enable_sec_rx_path_generic; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = ixgbe_set_vmdq_generic; mac->ops.set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic; mac->ops.clear_vmdq = ixgbe_clear_vmdq_generic; mac->ops.insert_mac_addr = ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; mac->ops.set_vfta = ixgbe_set_vfta_generic; mac->ops.set_vlvf = ixgbe_set_vlvf_generic; mac->ops.clear_vfta = ixgbe_clear_vfta_generic; mac->ops.init_uta_tables = ixgbe_init_uta_tables_generic; mac->ops.set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing; mac->ops.set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing; /* Link */ mac->ops.get_link_capabilities = ixgbe_get_copper_link_capabilities_generic; mac->ops.setup_link = ixgbe_setup_mac_link_X540; mac->ops.setup_rxpba = ixgbe_set_rxpba_generic; mac->ops.check_link = ixgbe_check_mac_link_generic; mac->mcft_size = IXGBE_X540_MC_TBL_SIZE; mac->vft_size = IXGBE_X540_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_X540_RAR_ENTRIES; mac->rx_pb_size = IXGBE_X540_RX_PB_SIZE; mac->max_rx_queues = IXGBE_X540_MAX_RX_QUEUES; mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); /* * FWSM register * ARC supported; valid only if manageability features are * enabled. */ mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & IXGBE_FWSM_MODE_MASK) ? true : false; hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; /* LEDs */ mac->ops.blink_led_start = ixgbe_blink_led_start_X540; mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540; /* Manageability interface */ mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_generic; mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic; return ret_val; } /** * ixgbe_get_link_capabilities_X540 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: true when autoneg or autotry is enabled * * Determines the link capabilities by reading the AUTOC register. **/ s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg); return IXGBE_SUCCESS; } /** * ixgbe_get_media_type_X540 - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw) { UNREFERENCED_1PARAMETER(hw); return ixgbe_media_type_copper; } /** * ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed **/ s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { DEBUGFUNC("ixgbe_setup_mac_link_X540"); return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); } /** * ixgbe_reset_hw_X540 - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, and perform a reset. **/ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) { s32 status; u32 ctrl, i; DEBUGFUNC("ixgbe_reset_hw_X540"); /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != IXGBE_SUCCESS) goto reset_hw_out; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); mac_reset_top: ctrl = IXGBE_CTRL_RST; ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; ERROR_REPORT1(IXGBE_ERROR_POLLING, "Reset polling failed to complete.\n"); } msec_delay(100); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* Set the Rx packet buffer size. */ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT); /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); /* Save the SAN MAC RAR index */ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; /* Reserve the last RAR for the SAN MAC address */ hw->mac.num_rar_entries--; } /* Store the alternative WWNN/WWPN prefix */ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, &hw->mac.wwpn_prefix); reset_hw_out: return status; } /** * ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function * and the generation start_hw function. * Then performs revision-specific operations, if any. **/ s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_start_hw_X540"); ret_val = ixgbe_start_hw_generic(hw); if (ret_val != IXGBE_SUCCESS) goto out; ret_val = ixgbe_start_hw_gen2(hw); out: return ret_val; } /** * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u16 ext_ability = 0; DEBUGFUNC("ixgbe_get_supported_physical_layer_X540"); hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; return physical_layer; } /** * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; DEBUGFUNC("ixgbe_init_eeprom_params_X540"); if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->semaphore_delay = 10; eeprom->type = ixgbe_flash; eec = IXGBE_READ_REG(hw, IXGBE_EEC); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); DEBUGOUT2("Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); } return IXGBE_SUCCESS; } /** * ixgbe_read_eerd_X540- Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_read_eerd_X540"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_read_eerd_generic(hw, offset, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @words: number of words * @data: word(s) read from the EEPROM * * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_read_eerd_buffer_X540"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_read_eerd_buffer_generic(hw, offset, words, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_write_eewr_X540"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_write_eewr_generic(hw, offset, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @words: number of words * @data: word(s) write to the EEPROM * * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_write_eewr_buffer_X540"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_write_eewr_buffer_generic(hw, offset, words, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum * * This function does not use synchronization for EERD and EEWR. It can * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540. * * @hw: pointer to hardware structure * * Returns a negative error code on error, or the 16-bit checksum **/ s32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) { u16 i, j; u16 checksum = 0; u16 length = 0; u16 pointer = 0; u16 word = 0; u16 checksum_last_word = IXGBE_EEPROM_CHECKSUM; u16 ptr_start = IXGBE_PCIE_ANALOG_PTR; /* Do not use hw->eeprom.ops.read because we do not want to take * the synchronization semaphores here. Instead use * ixgbe_read_eerd_generic */ DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540"); /* Include 0x0-0x3F in the checksum */ for (i = 0; i <= checksum_last_word; i++) { if (ixgbe_read_eerd_generic(hw, i, &word)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } if (i != IXGBE_EEPROM_CHECKSUM) checksum += word; } /* Include all data from pointers 0x3, 0x6-0xE. This excludes the * FW, PHY module, and PCIe Expansion/Option ROM pointers. */ for (i = ptr_start; i < IXGBE_FW_PTR; i++) { if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) continue; if (ixgbe_read_eerd_generic(hw, i, &pointer)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } /* Skip pointer section if the pointer is invalid. */ if (pointer == 0xFFFF || pointer == 0 || pointer >= hw->eeprom.word_size) continue; if (ixgbe_read_eerd_generic(hw, pointer, &length)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } /* Skip pointer section if length is invalid. */ if (length == 0xFFFF || length == 0 || (pointer + length) >= hw->eeprom.word_size) continue; for (j = pointer + 1; j <= pointer + length; j++) { if (ixgbe_read_eerd_generic(hw, j, &word)) { DEBUGOUT("EEPROM read failed\n"); return IXGBE_ERR_EEPROM; } checksum += word; } } checksum = (u16)IXGBE_EEPROM_SUM - checksum; return (s32)checksum; } /** * ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, u16 *checksum_val) { s32 status; u16 checksum; u16 read_checksum = 0; DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) return IXGBE_ERR_SWFW_SYNC; status = hw->eeprom.ops.calc_checksum(hw); if (status < 0) goto out; checksum = (u16)(status & 0xffff); /* Do not use hw->eeprom.ops.read because we do not want to take * the synchronization semaphores twice here. */ status = ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); if (status) goto out; /* Verify read checksum from EEPROM is the same as * calculated checksum */ if (read_checksum != checksum) { ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, "Invalid EEPROM checksum"); status = IXGBE_ERR_EEPROM_CHECKSUM; } /* If the user cares, return the calculated checksum */ if (checksum_val) *checksum_val = checksum; out: hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash * @hw: pointer to hardware structure * * After writing EEPROM to shadow RAM using EEWR register, software calculates * checksum and updates the EEPROM and instructs the hardware to update * the flash. **/ s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) { s32 status; u16 checksum; DEBUGFUNC("ixgbe_update_eeprom_checksum_X540"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)) return IXGBE_ERR_SWFW_SYNC; status = hw->eeprom.ops.calc_checksum(hw); if (status < 0) goto out; checksum = (u16)(status & 0xffff); /* Do not use hw->eeprom.ops.write because we do not want to * take the synchronization semaphores twice here. */ status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum); if (status) goto out; status = ixgbe_update_flash_X540(hw); out: hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device * @hw: pointer to hardware structure * * Set FLUP (bit 23) of the EEC register to instruct Hardware to copy * EEPROM from shadow RAM to the flash device. **/ s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) { u32 flup; s32 status; DEBUGFUNC("ixgbe_update_flash_X540"); status = ixgbe_poll_flash_update_done_X540(hw); if (status == IXGBE_ERR_EEPROM) { DEBUGOUT("Flash update time out\n"); goto out; } flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP; IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); status = ixgbe_poll_flash_update_done_X540(hw); if (status == IXGBE_SUCCESS) DEBUGOUT("Flash update complete\n"); else DEBUGOUT("Flash update time out\n"); if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) { flup = IXGBE_READ_REG(hw, IXGBE_EEC); if (flup & IXGBE_EEC_SEC1VAL) { flup |= IXGBE_EEC_FLUP; IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); } status = ixgbe_poll_flash_update_done_X540(hw); if (status == IXGBE_SUCCESS) DEBUGOUT("Flash update complete\n"); else DEBUGOUT("Flash update time out\n"); } out: return status; } /** * ixgbe_poll_flash_update_done_X540 - Poll flash update status * @hw: pointer to hardware structure * * Polls the FLUDONE (bit 26) of the EEC Register to determine when the * flash update is done. **/ STATIC s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; DEBUGFUNC("ixgbe_poll_flash_update_done_X540"); for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) { reg = IXGBE_READ_REG(hw, IXGBE_EEC); if (reg & IXGBE_EEC_FLUDONE) { status = IXGBE_SUCCESS; break; } msec_delay(5); } if (i == IXGBE_FLUDONE_ATTEMPTS) ERROR_REPORT1(IXGBE_ERROR_POLLING, "Flash update status polling timed out"); return status; } /** * ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore thought the SW_FW_SYNC register for * the specified function (CSR, PHY0, PHY1, NVM, Flash) **/ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) { u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK; u32 fwmask = swmask << 5; u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK; u32 timeout = 200; u32 hwmask = 0; u32 swfw_sync; u32 i; DEBUGFUNC("ixgbe_acquire_swfw_sync_X540"); if (swmask & IXGBE_GSSR_EEP_SM) hwmask |= IXGBE_GSSR_FLASH_SM; /* SW only mask doesn't have FW bit pair */ if (mask & IXGBE_GSSR_SW_MNG_SM) swmask |= IXGBE_GSSR_SW_MNG_SM; swmask |= swi2c_mask; fwmask |= swi2c_mask << 2; for (i = 0; i < timeout; i++) { /* SW NVM semaphore bit is used for access to all * SW_FW_SYNC bits (not just NVM) */ if (ixgbe_get_swfw_sync_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (!(swfw_sync & (fwmask | swmask | hwmask))) { swfw_sync |= swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); return IXGBE_SUCCESS; } /* Firmware currently using resource (fwmask), hardware * currently using resource (hwmask), or other software * thread currently using resource (swmask) */ ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); } /* Failed to get SW only semaphore */ if (swmask == IXGBE_GSSR_SW_MNG_SM) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "Failed to get SW only semaphore"); return IXGBE_ERR_SWFW_SYNC; } /* If the resource is not released by the FW/HW the SW can assume that * the FW/HW malfunctions. In that case the SW should set the SW bit(s) * of the requested resource(s) while ignoring the corresponding FW/HW * bits in the SW_FW_SYNC register. */ if (ixgbe_get_swfw_sync_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (swfw_sync & (fwmask | hwmask)) { swfw_sync |= swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); return IXGBE_SUCCESS; } /* If the resource is not released by other SW the SW can assume that * the other SW malfunctions. In that case the SW should clear all SW * flags that it does not own and then repeat the whole process once * again. */ if (swfw_sync & swmask) { u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM; if (swi2c_mask) rmask |= IXGBE_GSSR_I2C_MASK; ixgbe_release_swfw_sync_X540(hw, rmask); ixgbe_release_swfw_sync_semaphore(hw); return IXGBE_ERR_SWFW_SYNC; } ixgbe_release_swfw_sync_semaphore(hw); return IXGBE_ERR_SWFW_SYNC; } /** * ixgbe_release_swfw_sync_X540 - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through the SW_FW_SYNC register * for the specified function (CSR, PHY0, PHY1, EVM, Flash) **/ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) { u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM); u32 swfw_sync; DEBUGFUNC("ixgbe_release_swfw_sync_X540"); if (mask & IXGBE_GSSR_I2C_MASK) swmask |= mask & IXGBE_GSSR_I2C_MASK; ixgbe_get_swfw_sync_semaphore(hw); swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); swfw_sync &= ~swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msec_delay(5); } /** * ixgbe_get_swfw_sync_semaphore - Get hardware semaphore * @hw: pointer to hardware structure * * Sets the hardware semaphores so SW/FW can gain control of shared resources **/ STATIC s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM; u32 timeout = 2000; u32 i; u32 swsm; DEBUGFUNC("ixgbe_get_swfw_sync_semaphore"); /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) { status = IXGBE_SUCCESS; break; } usec_delay(50); } /* Now get the semaphore between SW/FW through the REGSMP bit */ if (status == IXGBE_SUCCESS) { for (i = 0; i < timeout; i++) { swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (!(swsm & IXGBE_SWFW_REGSMP)) break; usec_delay(50); } /* * Release semaphores and return error if SW NVM semaphore * was not granted because we don't have access to the EEPROM */ if (i >= timeout) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "REGSMP Software NVM semaphore not granted.\n"); ixgbe_release_swfw_sync_semaphore(hw); status = IXGBE_ERR_EEPROM; } } else { ERROR_REPORT1(IXGBE_ERROR_POLLING, "Software semaphore SMBI between device drivers " "not granted.\n"); } return status; } /** * ixgbe_release_swfw_sync_semaphore - Release hardware semaphore * @hw: pointer to hardware structure * * This function clears hardware semaphore bits. **/ STATIC void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) { u32 swsm; DEBUGFUNC("ixgbe_release_swfw_sync_semaphore"); /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); swsm &= ~IXGBE_SWFW_REGSMP; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm); swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); swsm &= ~IXGBE_SWSM_SMBI; IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_blink_led_start_X540 - Blink LED based on index. * @hw: pointer to hardware structure * @index: led number to blink * * Devices that implement the version 2 interface: * X540 **/ s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index) { u32 macc_reg; u32 ledctl_reg; ixgbe_link_speed speed; bool link_up; DEBUGFUNC("ixgbe_blink_led_start_X540"); /* * Link should be up in order for the blink bit in the LED control * register to work. Force link and speed in the MAC if link is down. * This will be reversed when we stop the blinking. */ hw->mac.ops.check_link(hw, &speed, &link_up, false); if (link_up == false) { macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS; IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); } /* Set the LED to LINK_UP + BLINK. */ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); ledctl_reg |= IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } /** * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index. * @hw: pointer to hardware structure * @index: led number to stop blinking * * Devices that implement the version 2 interface: * X540 **/ s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index) { u32 macc_reg; u32 ledctl_reg; DEBUGFUNC("ixgbe_blink_led_stop_X540"); /* Restore the LED to its default value. */ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); ledctl_reg &= ~IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); /* Unforce link and speed in the MAC. */ macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS); IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); IXGBE_WRITE_FLUSH(hw); return IXGBE_SUCCESS; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_x540.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_X540_H_ #define _IXGBE_X540_H_ #include "ixgbe_type.h" s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool link_up_wait_to_complete); s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw); s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw); s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw); s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw); s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw); s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask); void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask); s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index); #endif /* _IXGBE_X540_H_ */ ================================================ FILE: drivers/net/ixgbe/base/ixgbe_x550.c ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "ixgbe_x550.h" #include "ixgbe_x540.h" #include "ixgbe_type.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed); /** * ixgbe_init_ops_X550 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for X550. * Does not touch the hardware. **/ s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; DEBUGFUNC("ixgbe_init_ops_X550"); ret_val = ixgbe_init_ops_X540(hw); mac->ops.dmac_config = ixgbe_dmac_config_X550; mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550; mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550; mac->ops.setup_eee = ixgbe_setup_eee_X550; mac->ops.set_source_address_pruning = ixgbe_set_source_address_pruning_X550; mac->ops.set_ethertype_anti_spoofing = ixgbe_set_ethertype_anti_spoofing_X550; mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic; eeprom->ops.init_params = ixgbe_init_eeprom_params_X550; eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; eeprom->ops.read = ixgbe_read_ee_hostif_X550; eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550; eeprom->ops.write = ixgbe_write_ee_hostif_X550; eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550; eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; mac->ops.disable_mdd = ixgbe_disable_mdd_X550; mac->ops.enable_mdd = ixgbe_enable_mdd_X550; mac->ops.mdd_event = ixgbe_mdd_event_X550; mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550; mac->ops.disable_rx = ixgbe_disable_rx_x550; if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { hw->mac.ops.led_on = ixgbe_led_on_t_X550em; hw->mac.ops.led_off = ixgbe_led_off_t_X550em; } return ret_val; } /** * ixgbe_read_cs4227 - Read CS4227 register * @hw: pointer to hardware structure * @reg: register number to write * @value: pointer to receive value read * * Returns status code **/ STATIC s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) { return ixgbe_read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value); } /** * ixgbe_write_cs4227 - Write CS4227 register * @hw: pointer to hardware structure * @reg: register number to write * @value: value to write to register * * Returns status code **/ STATIC s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) { return ixgbe_write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, value); } /** * ixgbe_get_cs4227_status - Return CS4227 status * @hw: pointer to hardware structure * * Performs a diagnostic on the CS4227 chip. Returns an error if it is * not operating correctly. * This function assumes that the caller has acquired the proper semaphore. **/ STATIC s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw) { s32 status; u16 value = 0; u16 reg_slice, reg_val; u8 retry; /* Check register reads. */ for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) { status = ixgbe_read_cs4227(hw, IXGBE_CS4227_GLOBAL_ID_LSB, &value); if (status != IXGBE_SUCCESS) return status; if (value == IXGBE_CS4227_GLOBAL_ID_VALUE) break; msec_delay(IXGBE_CS4227_CHECK_DELAY); } if (value != IXGBE_CS4227_GLOBAL_ID_VALUE) return IXGBE_ERR_PHY; status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); if (status != IXGBE_SUCCESS) return status; /* If this is the first time after power-on, check the ucode. * Otherwise, this will disrupt link on all ports. Because we * can only do this the first time, we must check all ports, * not just our own. * While we are at it, set the LINE side to 10G SR, which is * what it needs to be regardless of the actual link. */ if (value != IXGBE_CS4227_SCRATCH_VALUE) { reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB; reg_val = IXGBE_CS4227_SPEED_10G; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB; reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB; reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (1 << 12); reg_val = IXGBE_CS4227_SPEED_10G; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12); reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12); reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; status = ixgbe_write_cs4227(hw, reg_slice, reg_val); if (status != IXGBE_SUCCESS) return status; msec_delay(10); } /* Verify that the ucode is operational on all ports. */ reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB; reg_val = 0xFFFF; status = ixgbe_read_cs4227(hw, reg_slice, ®_val); if (status != IXGBE_SUCCESS) return status; if (reg_val != 0) return IXGBE_ERR_PHY; reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB; reg_val = 0xFFFF; status = ixgbe_read_cs4227(hw, reg_slice, ®_val); if (status != IXGBE_SUCCESS) return status; if (reg_val != 0) return IXGBE_ERR_PHY; reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12); reg_val = 0xFFFF; status = ixgbe_read_cs4227(hw, reg_slice, ®_val); if (status != IXGBE_SUCCESS) return status; if (reg_val != 0) return IXGBE_ERR_PHY; reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12); reg_val = 0xFFFF; status = ixgbe_read_cs4227(hw, reg_slice, ®_val); if (status != IXGBE_SUCCESS) return status; if (reg_val != 0) return IXGBE_ERR_PHY; /* Set scratch indicating that the diagnostic was successful. */ status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, IXGBE_CS4227_SCRATCH_VALUE); if (status != IXGBE_SUCCESS) return status; status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); if (status != IXGBE_SUCCESS) return status; if (value != IXGBE_CS4227_SCRATCH_VALUE) return IXGBE_ERR_PHY; return IXGBE_SUCCESS; } /** * ixgbe_read_pe - Read register from port expander * @hw: pointer to hardware structure * @reg: register number to read * @value: pointer to receive read value * * Returns status code **/ STATIC s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) { s32 status; status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); if (status != IXGBE_SUCCESS) ERROR_REPORT2(IXGBE_ERROR_CAUTION, "port expander access failed with %d\n", status); return status; } /** * ixgbe_write_pe - Write register to port expander * @hw: pointer to hardware structure * @reg: register number to write * @value: value to write * * Returns status code **/ STATIC s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) { s32 status; status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); if (status != IXGBE_SUCCESS) ERROR_REPORT2(IXGBE_ERROR_CAUTION, "port expander access failed with %d\n", status); return status; } /** * ixgbe_reset_cs4227 - Reset CS4227 using port expander * @hw: pointer to hardware structure * * Returns error code **/ STATIC s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) { s32 status; u8 reg; status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); if (status != IXGBE_SUCCESS) return status; reg |= IXGBE_PE_BIT1; status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); if (status != IXGBE_SUCCESS) return status; status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); if (status != IXGBE_SUCCESS) return status; reg &= ~IXGBE_PE_BIT1; status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); if (status != IXGBE_SUCCESS) return status; status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); if (status != IXGBE_SUCCESS) return status; reg &= ~IXGBE_PE_BIT1; status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); if (status != IXGBE_SUCCESS) return status; usec_delay(IXGBE_CS4227_RESET_HOLD); status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); if (status != IXGBE_SUCCESS) return status; reg |= IXGBE_PE_BIT1; status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); if (status != IXGBE_SUCCESS) return status; msec_delay(IXGBE_CS4227_RESET_DELAY); return IXGBE_SUCCESS; } /** * ixgbe_check_cs4227 - Check CS4227 and reset as needed * @hw: pointer to hardware structure **/ STATIC void ixgbe_check_cs4227(struct ixgbe_hw *hw) { u32 swfw_mask = hw->phy.phy_semaphore_mask; s32 status; u8 retry; for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); if (status != IXGBE_SUCCESS) { ERROR_REPORT2(IXGBE_ERROR_CAUTION, "semaphore failed with %d\n", status); return; } status = ixgbe_get_cs4227_status(hw); if (status == IXGBE_SUCCESS) { hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(hw->eeprom.semaphore_delay); return; } ixgbe_reset_cs4227(hw); hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(hw->eeprom.semaphore_delay); } ERROR_REPORT2(IXGBE_ERROR_CAUTION, "Unable to initialize CS4227, err=%d\n", status); } /** * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control * @hw: pointer to hardware structure **/ STATIC void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) { u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (hw->bus.lan_id) { esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); esdp |= IXGBE_ESDP_SDP1_DIR; } esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_identify_phy_x550em - Get PHY type based on device id * @hw: pointer to hardware structure * * Returns error code */ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) { switch (hw->device_id) { case IXGBE_DEV_ID_X550EM_X_SFP: /* set up for CS4227 usage */ hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); ixgbe_check_cs4227(hw); return ixgbe_identify_module_generic(hw); break; case IXGBE_DEV_ID_X550EM_X_KX4: hw->phy.type = ixgbe_phy_x550em_kx4; break; case IXGBE_DEV_ID_X550EM_X_KR: hw->phy.type = ixgbe_phy_x550em_kr; break; case IXGBE_DEV_ID_X550EM_X_1G_T: case IXGBE_DEV_ID_X550EM_X_10G_T: return ixgbe_identify_phy_generic(hw); default: break; } return IXGBE_SUCCESS; } STATIC s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data); return IXGBE_NOT_IMPLEMENTED; } STATIC s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data); return IXGBE_NOT_IMPLEMENTED; } /** * ixgbe_init_ops_X550EM - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and for MAC type X550EM. * Does not touch the hardware. **/ s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; DEBUGFUNC("ixgbe_init_ops_X550EM"); /* Similar to X550 so start there. */ ret_val = ixgbe_init_ops_X550(hw); /* Since this function eventually calls * ixgbe_init_ops_540 by design, we are setting * the pointers to NULL explicitly here to overwrite * the values being set in the x540 function. */ /* Thermal sensor not supported in x550EM */ mac->ops.get_thermal_sensor_data = NULL; mac->ops.init_thermal_sensor_thresh = NULL; mac->thermal_sensor_enabled = false; /* FCOE not supported in x550EM */ mac->ops.get_san_mac_addr = NULL; mac->ops.set_san_mac_addr = NULL; mac->ops.get_wwn_prefix = NULL; mac->ops.get_fcoe_boot_status = NULL; /* IPsec not supported in x550EM */ mac->ops.disable_sec_rx_path = NULL; mac->ops.enable_sec_rx_path = NULL; /* AUTOC register is not present in x550EM. */ mac->ops.prot_autoc_read = NULL; mac->ops.prot_autoc_write = NULL; /* X550EM bus type is internal*/ hw->bus.type = ixgbe_bus_type_internal; mac->ops.get_bus_info = ixgbe_get_bus_info_X550em; mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; mac->ops.get_media_type = ixgbe_get_media_type_X550em; mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em; mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em; mac->ops.reset_hw = ixgbe_reset_hw_X550em; mac->ops.get_supported_physical_layer = ixgbe_get_supported_physical_layer_X550em; if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) mac->ops.setup_fc = ixgbe_setup_fc_generic; else mac->ops.setup_fc = ixgbe_setup_fc_X550em; mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em; mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em; if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR) mac->ops.setup_eee = NULL; /* PHY */ phy->ops.init = ixgbe_init_phy_ops_X550em; phy->ops.identify = ixgbe_identify_phy_x550em; if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) phy->ops.set_phy_power = NULL; /* EEPROM */ eeprom->ops.init_params = ixgbe_init_eeprom_params_X540; eeprom->ops.read = ixgbe_read_ee_hostif_X550; eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550; eeprom->ops.write = ixgbe_write_ee_hostif_X550; eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550; eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; return ret_val; } /** * ixgbe_dmac_config_X550 * @hw: pointer to hardware structure * * Configure DMA coalescing. If enabling dmac, dmac is activated. * When disabling dmac, dmac enable dmac bit is cleared. **/ s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw) { u32 reg, high_pri_tc; DEBUGFUNC("ixgbe_dmac_config_X550"); /* Disable DMA coalescing before configuring */ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); reg &= ~IXGBE_DMACR_DMAC_EN; IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); /* Disable DMA Coalescing if the watchdog timer is 0 */ if (!hw->mac.dmac_config.watchdog_timer) goto out; ixgbe_dmac_config_tcs_X550(hw); /* Configure DMA Coalescing Control Register */ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); /* Set the watchdog timer in units of 40.96 usec */ reg &= ~IXGBE_DMACR_DMACWT_MASK; reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096; reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK; /* If fcoe is enabled, set high priority traffic class */ if (hw->mac.dmac_config.fcoe_en) { high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc; reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) & IXGBE_DMACR_HIGH_PRI_TC_MASK); } reg |= IXGBE_DMACR_EN_MNG_IND; /* Enable DMA coalescing after configuration */ reg |= IXGBE_DMACR_DMAC_EN; IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); out: return IXGBE_SUCCESS; } /** * ixgbe_dmac_config_tcs_X550 * @hw: pointer to hardware structure * * Configure DMA coalescing threshold per TC. The dmac enable bit must * be cleared before configuring. **/ s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw) { u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb; DEBUGFUNC("ixgbe_dmac_config_tcs_X550"); /* Configure DMA coalescing enabled */ switch (hw->mac.dmac_config.link_speed) { case IXGBE_LINK_SPEED_100_FULL: pb_headroom = IXGBE_DMACRXT_100M; break; case IXGBE_LINK_SPEED_1GB_FULL: pb_headroom = IXGBE_DMACRXT_1G; break; default: pb_headroom = IXGBE_DMACRXT_10G; break; } maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >> IXGBE_MHADD_MFS_SHIFT) / 1024); /* Set the per Rx packet buffer receive threshold */ for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc)); reg &= ~IXGBE_DMCTH_DMACRXT_MASK; if (tc < hw->mac.dmac_config.num_tcs) { /* Get Rx PB size */ rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc)); rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >> IXGBE_RXPBSIZE_SHIFT; /* Calculate receive buffer threshold in kilobytes */ if (rx_pb_size > pb_headroom) rx_pb_size = rx_pb_size - pb_headroom; else rx_pb_size = 0; /* Minimum of MFS shall be set for DMCTH */ reg |= (rx_pb_size > maxframe_size_kb) ? rx_pb_size : maxframe_size_kb; } IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg); } return IXGBE_SUCCESS; } /** * ixgbe_dmac_update_tcs_X550 * @hw: pointer to hardware structure * * Disables dmac, updates per TC settings, and then enables dmac. **/ s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw) { u32 reg; DEBUGFUNC("ixgbe_dmac_update_tcs_X550"); /* Disable DMA coalescing before configuring */ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); reg &= ~IXGBE_DMACR_DMAC_EN; IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); ixgbe_dmac_config_tcs_X550(hw); /* Enable DMA coalescing after configuration */ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); reg |= IXGBE_DMACR_DMAC_EN; IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); return IXGBE_SUCCESS; } /** * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; DEBUGFUNC("ixgbe_init_eeprom_params_X550"); if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->semaphore_delay = 10; eeprom->type = ixgbe_flash; eec = IXGBE_READ_REG(hw, IXGBE_EEC); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); DEBUGOUT2("Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); } return IXGBE_SUCCESS; } /** * ixgbe_setup_eee_X550 - Enable/disable EEE support * @hw: pointer to the HW structure * @enable_eee: boolean flag to enable EEE * * Enable/disable EEE based on enable_eee flag. * Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C * are modified. * **/ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee) { u32 eeer; u16 autoneg_eee_reg; u32 link_reg; s32 status; u32 fuse; DEBUGFUNC("ixgbe_setup_eee_X550"); eeer = IXGBE_READ_REG(hw, IXGBE_EEER); /* Enable or disable EEE per flag */ if (enable_eee) { eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); if (hw->device_id == IXGBE_DEV_ID_X550T) { /* Advertise EEE capability */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg); autoneg_eee_reg |= (IXGBE_AUTO_NEG_10GBASE_EEE_ADVT | IXGBE_AUTO_NEG_1000BASE_EEE_ADVT | IXGBE_AUTO_NEG_100BASE_EEE_ADVT); hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg); } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { /* Not supported on first revision. */ fuse = IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)); if (!(fuse & IXGBE_FUSES0_REV1)) return IXGBE_SUCCESS; status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg); if (status != IXGBE_SUCCESS) return status; link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR | IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX; /* Don't advertise FEC capability when EEE enabled. */ link_reg &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg); if (status != IXGBE_SUCCESS) return status; } } else { eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); if (hw->device_id == IXGBE_DEV_ID_X550T) { /* Disable advertised EEE capability */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg); autoneg_eee_reg &= ~(IXGBE_AUTO_NEG_10GBASE_EEE_ADVT | IXGBE_AUTO_NEG_1000BASE_EEE_ADVT | IXGBE_AUTO_NEG_100BASE_EEE_ADVT); hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg); } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg); if (status != IXGBE_SUCCESS) return status; link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR | IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX); /* Advertise FEC capability when EEE is disabled. */ link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg); if (status != IXGBE_SUCCESS) return status; } } IXGBE_WRITE_REG(hw, IXGBE_EEER, eeer); return IXGBE_SUCCESS; } /** * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning * @hw: pointer to hardware structure * @enable: enable or disable source address pruning * @pool: Rx pool to set source address pruning for **/ void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, unsigned int pool) { u64 pfflp; /* max rx pool is 63 */ if (pool > 63) return; pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; if (enable) pfflp |= (1ULL << pool); else pfflp &= ~(1ULL << pool); IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); } /** * ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for Ethertype anti-spoofing * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing * **/ void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, bool enable, int vf) { int vf_target_reg = vf >> 3; int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; u32 pfvfspoof; DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550"); pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) pfvfspoof |= (1 << vf_target_shift); else pfvfspoof &= ~(1 << vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } /** * ixgbe_iosf_wait - Wait for IOSF command completion * @hw: pointer to hardware structure * @ctrl: pointer to location to receive final IOSF control value * * Returns failing status on timeout * * Note: ctrl can be NULL if the IOSF control register value is not needed **/ STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) { u32 i, command = 0; /* Check every 10 usec to see if the address cycle completed. * The SB IOSF BUSY bit will clear when the operation is * complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0) break; usec_delay(10); } if (ctrl) *ctrl = command; if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n"); return IXGBE_ERR_PHY; } return IXGBE_SUCCESS; } /** * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the IOSF * device * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 3 bit device type * @data: Data to write to the register **/ s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 data) { u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; u32 command, error; s32 ret; ret = ixgbe_acquire_swfw_semaphore(hw, gssr); if (ret != IXGBE_SUCCESS) return ret; ret = ixgbe_iosf_wait(hw, NULL); if (ret != IXGBE_SUCCESS) goto out; command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); /* Write IOSF control register */ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); /* Write IOSF data register */ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); ret = ixgbe_iosf_wait(hw, &command); if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; ERROR_REPORT2(IXGBE_ERROR_POLLING, "Failed to write, error %x\n", error); ret = IXGBE_ERR_PHY; } out: ixgbe_release_swfw_semaphore(hw, gssr); return ret; } /** * ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the IOSF * device * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 3 bit device type * @phy_data: Pointer to read data from the register **/ s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 *data) { u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; u32 command, error; s32 ret; ret = ixgbe_acquire_swfw_semaphore(hw, gssr); if (ret != IXGBE_SUCCESS) return ret; ret = ixgbe_iosf_wait(hw, NULL); if (ret != IXGBE_SUCCESS) goto out; command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); /* Write IOSF control register */ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); ret = ixgbe_iosf_wait(hw, &command); if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; ERROR_REPORT2(IXGBE_ERROR_POLLING, "Failed to read, error %x\n", error); ret = IXGBE_ERR_PHY; } if (ret == IXGBE_SUCCESS) *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); out: ixgbe_release_swfw_semaphore(hw, gssr); return ret; } /** * ixgbe_disable_mdd_X550 * @hw: pointer to hardware structure * * Disable malicious driver detection **/ void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw) { u32 reg; DEBUGFUNC("ixgbe_disable_mdd_X550"); /* Disable MDD for TX DMA and interrupt */ reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); /* Disable MDD for RX and interrupt */ reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); } /** * ixgbe_enable_mdd_X550 * @hw: pointer to hardware structure * * Enable malicious driver detection **/ void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw) { u32 reg; DEBUGFUNC("ixgbe_enable_mdd_X550"); /* Enable MDD for TX DMA and interrupt */ reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); /* Enable MDD for RX and interrupt */ reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); } /** * ixgbe_restore_mdd_vf_X550 * @hw: pointer to hardware structure * @vf: vf index * * Restore VF that was disabled during malicious driver detection event **/ void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf) { u32 idx, reg, num_qs, start_q, bitmask; DEBUGFUNC("ixgbe_restore_mdd_vf_X550"); /* Map VF to queues */ reg = IXGBE_READ_REG(hw, IXGBE_MRQC); switch (reg & IXGBE_MRQC_MRQE_MASK) { case IXGBE_MRQC_VMDQRT8TCEN: num_qs = 8; /* 16 VFs / pools */ bitmask = 0x000000FF; break; case IXGBE_MRQC_VMDQRSS32EN: case IXGBE_MRQC_VMDQRT4TCEN: num_qs = 4; /* 32 VFs / pools */ bitmask = 0x0000000F; break; default: /* 64 VFs / pools */ num_qs = 2; bitmask = 0x00000003; break; } start_q = vf * num_qs; /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */ idx = start_q / 32; reg = 0; reg |= (bitmask << (start_q % 32)); IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), reg); IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg); } /** * ixgbe_mdd_event_X550 * @hw: pointer to hardware structure * @vf_bitmap: vf bitmap of malicious vfs * * Handle malicious driver detection event. **/ void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap) { u32 wqbr; u32 i, j, reg, q, shift, vf, idx; DEBUGFUNC("ixgbe_mdd_event_X550"); /* figure out pool size for mapping to vf's */ reg = IXGBE_READ_REG(hw, IXGBE_MRQC); switch (reg & IXGBE_MRQC_MRQE_MASK) { case IXGBE_MRQC_VMDQRT8TCEN: shift = 3; /* 16 VFs / pools */ break; case IXGBE_MRQC_VMDQRSS32EN: case IXGBE_MRQC_VMDQRT4TCEN: shift = 2; /* 32 VFs / pools */ break; default: shift = 1; /* 64 VFs / pools */ break; } /* Read WQBR_TX and WQBR_RX and check for malicious queues */ for (i = 0; i < 4; i++) { wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i)); wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i)); if (!wqbr) continue; /* Get malicious queue */ for (j = 0; j < 32 && wqbr; j++) { if (!(wqbr & (1 << j))) continue; /* Get queue from bitmask */ q = j + (i * 32); /* Map queue to vf */ vf = (q >> shift); /* Set vf bit in vf_bitmap */ idx = vf / 32; vf_bitmap[idx] |= (1 << (vf % 32)); wqbr &= ~(1 << j); } } } /** * ixgbe_get_media_type_X550em - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) */ enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; DEBUGFUNC("ixgbe_get_media_type_X550em"); /* Detect if there is a copper PHY attached. */ switch (hw->device_id) { case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_KX4: media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_X550EM_X_SFP: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_X550EM_X_1G_T: case IXGBE_DEV_ID_X550EM_X_10G_T: media_type = ixgbe_media_type_copper; break; default: media_type = ixgbe_media_type_unknown; break; } return media_type; } /** * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported * @hw: pointer to hardware structure * @linear: true if SFP module is linear */ STATIC s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) { DEBUGFUNC("ixgbe_supported_sfp_modules_X550em"); switch (hw->phy.sfp_type) { case ixgbe_sfp_type_not_present: return IXGBE_ERR_SFP_NOT_PRESENT; case ixgbe_sfp_type_da_cu_core0: case ixgbe_sfp_type_da_cu_core1: *linear = true; break; case ixgbe_sfp_type_srlr_core0: case ixgbe_sfp_type_srlr_core1: case ixgbe_sfp_type_da_act_lmt_core0: case ixgbe_sfp_type_da_act_lmt_core1: case ixgbe_sfp_type_1g_sx_core0: case ixgbe_sfp_type_1g_sx_core1: case ixgbe_sfp_type_1g_lx_core0: case ixgbe_sfp_type_1g_lx_core1: *linear = false; break; case ixgbe_sfp_type_unknown: case ixgbe_sfp_type_1g_cu_core0: case ixgbe_sfp_type_1g_cu_core1: default: return IXGBE_ERR_SFP_NOT_SUPPORTED; } return IXGBE_SUCCESS; } /** * ixgbe_identify_sfp_module_X550em - Identifies SFP modules * @hw: pointer to hardware structure * * Searches for and identifies the SFP module and assigns appropriate PHY type. **/ s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw) { s32 status; bool linear; DEBUGFUNC("ixgbe_identify_sfp_module_X550em"); status = ixgbe_identify_module_generic(hw); if (status != IXGBE_SUCCESS) return status; /* Check if SFP module is supported */ status = ixgbe_supported_sfp_modules_X550em(hw, &linear); return status; } /** * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops * @hw: pointer to hardware structure */ s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) { s32 status; bool linear; DEBUGFUNC("ixgbe_setup_sfp_modules_X550em"); /* Check if SFP module is supported */ status = ixgbe_supported_sfp_modules_X550em(hw, &linear); if (status != IXGBE_SUCCESS) return status; ixgbe_init_mac_link_ops_X550em(hw); hw->phy.ops.reset = NULL; return IXGBE_SUCCESS; } /** * ixgbe_init_mac_link_ops_X550em - init mac link function pointers * @hw: pointer to hardware structure */ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; DEBUGFUNC("ixgbe_init_mac_link_ops_X550em"); switch (hw->mac.ops.get_media_type(hw)) { case ixgbe_media_type_fiber: /* CS4227 does not support autoneg, so disable the laser control * functions for SFP+ fiber */ mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; mac->ops.set_rate_select_speed = ixgbe_set_soft_rate_select_speed; break; case ixgbe_media_type_copper: mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; mac->ops.check_link = ixgbe_check_link_t_X550em; break; default: break; } } /** * ixgbe_get_link_capabilities_x550em - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: true when autoneg or autotry is enabled */ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { DEBUGFUNC("ixgbe_get_link_capabilities_X550em"); /* SFP */ if (hw->phy.media_type == ixgbe_media_type_fiber) { /* CS4227 SFP must not enable auto-negotiation */ *autoneg = false; /* Check if 1G SFP module. */ if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { *speed = IXGBE_LINK_SPEED_1GB_FULL; return IXGBE_SUCCESS; } /* Link capabilities are based on SFP */ if (hw->phy.multispeed_fiber) *speed = IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; else *speed = IXGBE_LINK_SPEED_10GB_FULL; } else { *speed = IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; } return IXGBE_SUCCESS; } /** * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause * @hw: pointer to hardware structure * @lsc: pointer to boolean flag which indicates whether external Base T * PHY interrupt is lsc * * Determime if external Base T PHY interrupt cause is high temperature * failure alarm or link status change. * * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature * failure alarm, else return PHY access status. */ STATIC s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) { u32 status; u16 reg; *lsc = false; /* Vendor alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) return status; /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | IXGBE_MDIO_GLOBAL_ALARM_1_INT))) return status; /* High temperature failure alarm triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; /* If high temperature failure, then return over temp error and exit */ if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { /* power down the PHY in case the PHY FW didn't already */ ixgbe_set_copper_phy_power(hw, false); return IXGBE_ERR_OVERTEMP; } /* Vendor alarm 2 triggered */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); if (status != IXGBE_SUCCESS || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) return status; /* link connect/disconnect event occurred */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; /* Indicate LSC */ if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) *lsc = true; return IXGBE_SUCCESS; } /** * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts * @hw: pointer to hardware structure * * Enable link status change and temperature failure alarm for the external * Base T PHY * * Returns PHY access status */ STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) { u32 status; u16 reg; bool lsc; /* Clear interrupt flags */ status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); /* Enable link status change alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); if (status != IXGBE_SUCCESS) return status; /* Enables high temperature failure alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; reg |= IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, reg); if (status != IXGBE_SUCCESS) return status; /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | IXGBE_MDIO_GLOBAL_ALARM_1_INT); status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, reg); if (status != IXGBE_SUCCESS) return status; /* Enable chip-wide vendor alarm */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, reg); return status; } /** * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. * @hw: pointer to hardware structure * @speed: link speed * * Configures the integrated KR PHY. **/ STATIC s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, ixgbe_link_speed speed) { s32 status; u32 reg_val; status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status) return status; reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); /* Advertise 10G support. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; /* Advertise 1G support. */ if (speed & IXGBE_LINK_SPEED_1GB_FULL) reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; /* Restart auto-negotiation. */ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); return status; } /** * ixgbe_init_phy_ops_X550em - PHY/SFP specific init * @hw: pointer to hardware structure * * Initialize any function pointers that were not able to be * set during init_shared_code because the PHY/SFP type was * not known. Perform the SFP init if necessary. */ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; ixgbe_link_speed speed; s32 ret_val; DEBUGFUNC("ixgbe_init_phy_ops_X550em"); hw->mac.ops.set_lan_id(hw); if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); /* Save NW management interface connected on board. This is used * to determine internal PHY mode. */ phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); /* If internal PHY mode is KR, then initialize KR link */ if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { speed = IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); } phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; } /* Identify the PHY or SFP module */ ret_val = phy->ops.identify(hw); if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) return ret_val; /* Setup function pointers based on detected hardware */ ixgbe_init_mac_link_ops_X550em(hw); if (phy->sfp_type != ixgbe_sfp_type_unknown) phy->ops.reset = NULL; /* Set functions pointers based on phy type */ switch (hw->phy.type) { case ixgbe_phy_x550em_kx4: phy->ops.setup_link = ixgbe_setup_kx4_x550em; phy->ops.read_reg = ixgbe_read_phy_reg_x550em; phy->ops.write_reg = ixgbe_write_phy_reg_x550em; break; case ixgbe_phy_x550em_kr: phy->ops.setup_link = ixgbe_setup_kr_x550em; phy->ops.read_reg = ixgbe_read_phy_reg_x550em; phy->ops.write_reg = ixgbe_write_phy_reg_x550em; break; case ixgbe_phy_x550em_ext_t: /* Save NW management interface connected on board. This is used * to determine internal PHY mode */ phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); /* If internal link mode is XFI, then setup iXFI internal link, * else setup KR now. */ if (!(phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { phy->ops.setup_internal_link = ixgbe_setup_internal_phy_t_x550em; } else { speed = IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; ret_val = ixgbe_setup_kr_speed_x550em(hw, speed); } /* setup SW LPLU only for first revision */ if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; phy->ops.reset = ixgbe_reset_phy_t_X550em; break; default: break; } return ret_val; } /** * ixgbe_reset_hw_X550em - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, perform a PHY reset, and perform a link (MAC) * reset. */ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) { ixgbe_link_speed link_speed; s32 status; u32 ctrl = 0; u32 i; u32 hlreg0; bool link_up = false; DEBUGFUNC("ixgbe_reset_hw_X550em"); /* Call adapter stop to disable Tx/Rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != IXGBE_SUCCESS) return status; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); /* PHY ops must be identified and initialized prior to reset */ /* Identify PHY and related function pointers */ status = hw->phy.ops.init(hw); if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) return status; /* start the external PHY */ if (hw->phy.type == ixgbe_phy_x550em_ext_t) { status = ixgbe_init_ext_t_x550em(hw); if (status) return status; } /* Setup SFP module if there is one present. */ if (hw->phy.sfp_setup_needed) { status = hw->mac.ops.setup_sfp(hw); hw->phy.sfp_setup_needed = false; } if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) return status; /* Reset PHY */ if (!hw->phy.reset_disable && hw->phy.ops.reset) hw->phy.ops.reset(hw); mac_reset_top: /* Issue global reset to the MAC. Needs to be SW reset if link is up. * If link reset is used when link is up, it might reset the PHY when * mng is using it. If link is down or the flag to force full link * reset is set, then perform link reset. */ ctrl = IXGBE_CTRL_LNK_RST; if (!hw->force_full_reset) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) ctrl = IXGBE_CTRL_RST; } ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear meaning reset is complete */ for (i = 0; i < 10; i++) { usec_delay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; DEBUGOUT("Reset polling failed to complete.\n"); } msec_delay(50); /* Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to * allow time for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) { /* Config MDIO clock speed. */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); hlreg0 &= ~IXGBE_HLREG0_MDCSPD; IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); } if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) ixgbe_setup_mux_ctl(hw); return status; } /** * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. * @hw: pointer to hardware structure */ s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) { u32 status; u16 reg; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_TX_VENDOR_ALARMS_3, IXGBE_MDIO_PMA_PMD_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; /* If PHY FW reset completed bit is set then this is the first * SW instance after a power on so the PHY FW must be un-stalled. */ if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_RES_PR_10, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ®); if (status != IXGBE_SUCCESS) return status; reg &= ~IXGBE_MDIO_POWER_UP_STALL; status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_RES_PR_10, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, reg); if (status != IXGBE_SUCCESS) return status; } return status; } /** * ixgbe_setup_kr_x550em - Configure the KR PHY. * @hw: pointer to hardware structure * * Configures the integrated KR PHY. **/ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) { return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); } /** * ixgbe_setup_kx4_x550em - Configure the KX4 PHY. * @hw: pointer to hardware structure * * Configures the integrated KX4 PHY. **/ s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) { s32 status; u32 reg_val; status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, IXGBE_SB_IOSF_TARGET_KX4_PCS, ®_val); if (status) return status; reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; /* Advertise 10G support. */ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; /* Advertise 1G support. */ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; /* Restart auto-negotiation. */ reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1, IXGBE_SB_IOSF_TARGET_KX4_PCS, reg_val); return status; } /** * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP * @hw: pointer to hardware structure * * Configure the external PHY and the integrated KR PHY for SFP support. **/ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 ret_val; u16 reg_slice, reg_val; bool setup_linear = false; UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); /* Check if SFP module is supported and linear */ ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); /* If no SFP module present, then return success. Return success since * there is no reason to configure CS4227 and SFP not present error is * not excepted in the setup MAC link flow. */ if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) return IXGBE_SUCCESS; if (ret_val != IXGBE_SUCCESS) return ret_val; /* Configure CS4227 LINE side to 10G SR. */ reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); reg_val = IXGBE_CS4227_SPEED_10G; ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, reg_val); reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, reg_val); /* Configure CS4227 for HOST connection rate then type. */ reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, reg_val); reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); if (setup_linear) reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; else reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice, reg_val); /* If internal link mode is XFI, then setup XFI internal link. */ if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) ret_val = ixgbe_setup_ixfi_x550em(hw, &speed); return ret_val; } /** * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. * @hw: pointer to hardware structure * @speed: the link speed to force * * Configures the integrated KR PHY to use iXFI mode. Used to connect an * internal and external PHY at a specific speed, without autonegotiation. **/ STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) { s32 status; u32 reg_val; /* Disable AN and force speed to 10G Serial. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; /* Select forced link speed for internal PHY. */ switch (*speed) { case IXGBE_LINK_SPEED_10GB_FULL: reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; break; case IXGBE_LINK_SPEED_1GB_FULL: reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; break; default: /* Other link speeds are not supported by internal KR PHY. */ return IXGBE_ERR_LINK_SETUP; } status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Disable training protocol FSM. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Disable Flex from training TXFFE. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Enable override for coefficients. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Toggle port SW reset by AN reset. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); return status; } /** * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status * @hw: address of hardware structure * @link_up: address of boolean to indicate link status * * Returns error code if unable to get link status. */ STATIC s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) { u32 ret; u16 autoneg_status; *link_up = false; /* read this twice back to back to indicate current status */ ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_status); if (ret != IXGBE_SUCCESS) return ret; ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_status); if (ret != IXGBE_SUCCESS) return ret; *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); return IXGBE_SUCCESS; } /** * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link * @hw: point to hardware structure * * Configures the link between the integrated KR PHY and the external X557 PHY * The driver will call this function when it gets a link status change * interrupt from the X557 PHY. This function configures the link speed * between the PHYs to match the link speed of the BASE-T link. * * A return of a non-zero value indicates an error, and the base driver should * not report link up. */ s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) { ixgbe_link_speed force_speed; bool link_up; u32 status; u16 speed; if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) return IXGBE_ERR_CONFIG; /* If link is not up, then there is no setup necessary so return */ status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); if (status != IXGBE_SUCCESS) return status; if (!link_up) return IXGBE_SUCCESS; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &speed); if (status != IXGBE_SUCCESS) return status; /* If link is not still up, then no setup is necessary so return */ status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); if (status != IXGBE_SUCCESS) return status; if (!link_up) return IXGBE_SUCCESS; /* clear everything but the speed and duplex bits */ speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; switch (speed) { case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: force_speed = IXGBE_LINK_SPEED_10GB_FULL; break; case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: force_speed = IXGBE_LINK_SPEED_1GB_FULL; break; default: /* Internal PHY does not support anything else */ return IXGBE_ERR_INVALID_LINK_SETTINGS; } return ixgbe_setup_ixfi_x550em(hw, &force_speed); } /** * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback. * @hw: pointer to hardware structure * * Configures the integrated KR PHY to use internal loopback mode. **/ s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw) { s32 status; u32 reg_val; /* Disable AN and force speed to 10G Serial. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Set near-end loopback clocks. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B; reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Set loopback enable. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); if (status != IXGBE_SUCCESS) return status; /* Training bypass. */ status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (status != IXGBE_SUCCESS) return status; reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS; status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); return status; } /** * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command * assuming that the semaphore is already obtained. * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the hostif. **/ s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status; struct ixgbe_hic_read_shadow_ram buffer; DEBUGFUNC("ixgbe_read_ee_hostif_data_X550"); buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; buffer.hdr.req.buf_lenh = 0; buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; /* convert offset from words to bytes */ buffer.address = IXGBE_CPU_TO_BE32(offset * 2); /* one word */ buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16)); status = ixgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); if (status) return status; *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, FW_NVM_DATA_OFFSET); return 0; } /** * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the hostif. **/ s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_read_ee_hostif_X550"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @words: number of words * @data: word(s) read from the EEPROM * * Reads a 16 bit word(s) from the EEPROM using the hostif. **/ s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { struct ixgbe_hic_read_shadow_ram buffer; u32 current_word = 0; u16 words_to_read; s32 status; u32 i; DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550"); /* Take semaphore for the entire operation. */ status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); if (status) { DEBUGOUT("EEPROM read buffer - semaphore failed\n"); return status; } while (words) { if (words > FW_MAX_READ_BUFFER_SIZE / 2) words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; else words_to_read = words; buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; buffer.hdr.req.buf_lenh = 0; buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; /* convert offset from words to bytes */ buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2); buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2); status = ixgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); if (status) { DEBUGOUT("Host interface command failed\n"); goto out; } for (i = 0; i < words_to_read; i++) { u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + 2 * i; u32 value = IXGBE_READ_REG(hw, reg); data[current_word] = (u16)(value & 0xffff); current_word++; i++; if (i < words_to_read) { value >>= 16; data[current_word] = (u16)(value & 0xffff); current_word++; } } words -= words_to_read; } out: hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the hostif. **/ s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status; struct ixgbe_hic_write_shadow_ram buffer; DEBUGFUNC("ixgbe_write_ee_hostif_data_X550"); buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; buffer.hdr.req.buf_lenh = 0; buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; /* one word */ buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16)); buffer.data = data; buffer.address = IXGBE_CPU_TO_BE32(offset * 2); status = ixgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); return status; } /** * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the hostif. **/ s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status = IXGBE_SUCCESS; DEBUGFUNC("ixgbe_write_ee_hostif_X550"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == IXGBE_SUCCESS) { status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); } else { DEBUGOUT("write ee hostif failed to get semaphore"); status = IXGBE_ERR_SWFW_SYNC; } return status; } /** * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @words: number of words * @data: word(s) write to the EEPROM * * Write a 16 bit word(s) to the EEPROM using the hostif. **/ s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = IXGBE_SUCCESS; u32 i = 0; DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550"); /* Take semaphore for the entire operation. */ status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); if (status != IXGBE_SUCCESS) { DEBUGOUT("EEPROM write buffer - semaphore failed\n"); goto out; } for (i = 0; i < words; i++) { status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, data[i]); if (status != IXGBE_SUCCESS) { DEBUGOUT("Eeprom buffered write failed\n"); break; } } hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); out: return status; } /** * ixgbe_checksum_ptr_x550 - Checksum one pointer region * @hw: pointer to hardware structure * @ptr: pointer offset in eeprom * @size: size of section pointed by ptr, if 0 first word will be used as size * @csum: address of checksum to update * * Returns error status for any failure */ STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, u16 size, u16 *csum, u16 *buffer, u32 buffer_size) { u16 buf[256]; s32 status; u16 length, bufsz, i, start; u16 *local_buffer; bufsz = sizeof(buf) / sizeof(buf[0]); /* Read a chunk at the pointer location */ if (!buffer) { status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); if (status) { DEBUGOUT("Failed to read EEPROM image\n"); return status; } local_buffer = buf; } else { if (buffer_size < ptr) return IXGBE_ERR_PARAM; local_buffer = &buffer[ptr]; } if (size) { start = 0; length = size; } else { start = 1; length = local_buffer[0]; /* Skip pointer section if length is invalid. */ if (length == 0xFFFF || length == 0 || (ptr + length) >= hw->eeprom.word_size) return IXGBE_SUCCESS; } if (buffer && ((u32)start + (u32)length > buffer_size)) return IXGBE_ERR_PARAM; for (i = start; length; i++, length--) { if (i == bufsz && !buffer) { ptr += bufsz; i = 0; if (length < bufsz) bufsz = length; /* Read a chunk at the pointer location */ status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); if (status) { DEBUGOUT("Failed to read EEPROM image\n"); return status; } } *csum += local_buffer[i]; } return IXGBE_SUCCESS; } /** * ixgbe_calc_checksum_X550 - Calculates and returns the checksum * @hw: pointer to hardware structure * @buffer: pointer to buffer containing calculated checksum * @buffer_size: size of buffer * * Returns a negative error code on error, or the 16-bit checksum **/ s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size) { u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; u16 *local_buffer; s32 status; u16 checksum = 0; u16 pointer, i, size; DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550"); hw->eeprom.ops.init_params(hw); if (!buffer) { /* Read pointer area */ status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, IXGBE_EEPROM_LAST_WORD + 1, eeprom_ptrs); if (status) { DEBUGOUT("Failed to read EEPROM image\n"); return status; } local_buffer = eeprom_ptrs; } else { if (buffer_size < IXGBE_EEPROM_LAST_WORD) return IXGBE_ERR_PARAM; local_buffer = buffer; } /* * For X550 hardware include 0x0-0x41 in the checksum, skip the * checksum word itself */ for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) if (i != IXGBE_EEPROM_CHECKSUM) checksum += local_buffer[i]; /* * Include all data from pointers 0x3, 0x6-0xE. This excludes the * FW, PHY module, and PCIe Expansion/Option ROM pointers. */ for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) continue; pointer = local_buffer[i]; /* Skip pointer section if the pointer is invalid. */ if (pointer == 0xFFFF || pointer == 0 || pointer >= hw->eeprom.word_size) continue; switch (i) { case IXGBE_PCIE_GENERAL_PTR: size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; break; case IXGBE_PCIE_CONFIG0_PTR: case IXGBE_PCIE_CONFIG1_PTR: size = IXGBE_PCIE_CONFIG_SIZE; break; default: size = 0; break; } status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, buffer, buffer_size); if (status) return status; } checksum = (u16)IXGBE_EEPROM_SUM - checksum; return (s32)checksum; } /** * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum * @hw: pointer to hardware structure * * Returns a negative error code on error, or the 16-bit checksum **/ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) { return ixgbe_calc_checksum_X550(hw, NULL, 0); } /** * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val) { s32 status; u16 checksum; u16 read_checksum = 0; DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } status = hw->eeprom.ops.calc_checksum(hw); if (status < 0) return status; checksum = (u16)(status & 0xffff); status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); if (status) return status; /* Verify read checksum from EEPROM is the same as * calculated checksum */ if (read_checksum != checksum) { status = IXGBE_ERR_EEPROM_CHECKSUM; ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, "Invalid EEPROM checksum"); } /* If the user cares, return the calculated checksum */ if (checksum_val) *checksum_val = checksum; return status; } /** * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash * @hw: pointer to hardware structure * * After writing EEPROM to shadow RAM using EEWR register, software calculates * checksum and updates the EEPROM and instructs the hardware to update * the flash. **/ s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) { s32 status; u16 checksum = 0; DEBUGFUNC("ixgbe_update_eeprom_checksum_X550"); /* Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); if (status) { DEBUGOUT("EEPROM read failed\n"); return status; } status = ixgbe_calc_eeprom_checksum_X550(hw); if (status < 0) return status; checksum = (u16)(status & 0xffff); status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, checksum); if (status) return status; status = ixgbe_update_flash_X550(hw); return status; } /** * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device * @hw: pointer to hardware structure * * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. **/ s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) { s32 status = IXGBE_SUCCESS; union ixgbe_hic_hdr2 buffer; DEBUGFUNC("ixgbe_update_flash_X550"); buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; buffer.req.buf_lenh = 0; buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; buffer.req.checksum = FW_DEFAULT_CHECKSUM; status = ixgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); return status; } /** * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u16 ext_ability = 0; DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em"); hw->phy.ops.identify(hw); switch (hw->phy.type) { case ixgbe_phy_x550em_kr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR | IXGBE_PHYSICAL_LAYER_1000BASE_KX; break; case ixgbe_phy_x550em_kx4: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | IXGBE_PHYSICAL_LAYER_1000BASE_KX; break; case ixgbe_phy_x550em_ext_t: hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; break; default: break; } if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); return physical_layer; } /** * ixgbe_get_bus_info_x550em - Set PCI bus info * @hw: pointer to hardware structure * * Sets bus link width and speed to unknown because X550em is * not a PCI device. **/ s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) { DEBUGFUNC("ixgbe_get_bus_info_x550em"); hw->bus.width = ixgbe_bus_width_unknown; hw->bus.speed = ixgbe_bus_speed_unknown; hw->mac.ops.set_lan_id(hw); return IXGBE_SUCCESS; } /** * ixgbe_disable_rx_x550 - Disable RX unit * * Enables the Rx DMA unit for x550 **/ void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) { u32 rxctrl, pfdtxgswc; s32 status; struct ixgbe_hic_disable_rxen fw_cmd; DEBUGFUNC("ixgbe_enable_rx_dma_x550"); rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); if (rxctrl & IXGBE_RXCTRL_RXEN) { pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); hw->mac.set_lben = true; } else { hw->mac.set_lben = false; } fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; fw_cmd.port_number = (u8)hw->bus.lan_id; status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, sizeof(struct ixgbe_hic_disable_rxen), IXGBE_HI_COMMAND_TIMEOUT, true); /* If we fail - disable RX using register write */ if (status) { rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); if (rxctrl & IXGBE_RXCTRL_RXEN) { rxctrl &= ~IXGBE_RXCTRL_RXEN; IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); } } } } /** * ixgbe_enter_lplu_x550em - Transition to low power states * @hw: pointer to hardware structure * * Configures Low Power Link Up on transition to low power states * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the * X557 PHY immediately prior to entering LPLU. **/ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) { u16 an_10g_cntl_reg, autoneg_reg, speed; s32 status; ixgbe_link_speed lcd_speed; u32 save_autoneg; bool link_up; /* SW LPLU not required on later HW revisions. */ if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0))) return IXGBE_SUCCESS; /* If blocked by MNG FW, then don't restart AN */ if (ixgbe_check_reset_blocked(hw)) return IXGBE_SUCCESS; status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); if (status != IXGBE_SUCCESS) return status; status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3); if (status != IXGBE_SUCCESS) return status; /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability * disabled, then force link down by entering low power mode. */ if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || !(hw->wol_enabled || ixgbe_mng_present(hw))) return ixgbe_set_copper_phy_power(hw, FALSE); /* Determine LCD */ status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); if (status != IXGBE_SUCCESS) return status; /* If no valid LCD link speed, then force link down and exit. */ if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) return ixgbe_set_copper_phy_power(hw, FALSE); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &speed); if (status != IXGBE_SUCCESS) return status; /* If no link now, speed is invalid so take link down */ status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); if (status != IXGBE_SUCCESS) return ixgbe_set_copper_phy_power(hw, false); /* clear everything but the speed bits */ speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; /* If current speed is already LCD, then exit. */ if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) return status; /* Clear AN completed indication */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); if (status != IXGBE_SUCCESS) return status; status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_10g_cntl_reg); if (status != IXGBE_SUCCESS) return status; status = hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); if (status != IXGBE_SUCCESS) return status; save_autoneg = hw->phy.autoneg_advertised; /* Setup link at least common link speed */ status = hw->mac.ops.setup_link(hw, lcd_speed, false); /* restore autoneg from before setting lplu speed */ hw->phy.autoneg_advertised = save_autoneg; return status; } /** * ixgbe_get_lcd_x550em - Determine lowest common denominator * @hw: pointer to hardware structure * @lcd_speed: pointer to lowest common link speed * * Determine lowest common link speed with link partner. **/ s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed) { u16 an_lp_status; s32 status; u16 word = hw->eeprom.ctrl_word_3; *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_lp_status); if (status != IXGBE_SUCCESS) return status; /* If link partner advertised 1G, return 1G */ if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; return status; } /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) return status; /* Link partner not capable of lower speeds, return 10G */ *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; return status; } /** * ixgbe_setup_fc_X550em - Set up flow control * @hw: pointer to hardware structure * * Called at init time to set up flow control. **/ s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_SUCCESS; u32 pause, asm_dir, reg_val; DEBUGFUNC("ixgbe_setup_fc_X550em"); /* Validate the requested mode */ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* 10gig parts do not have a word in the EEPROM to determine the * default flow control setting, so we explicitly set it to full. */ if (hw->fc.requested_mode == ixgbe_fc_default) hw->fc.requested_mode = ixgbe_fc_full; /* Determine PAUSE and ASM_DIR bits. */ switch (hw->fc.requested_mode) { case ixgbe_fc_none: pause = 0; asm_dir = 0; break; case ixgbe_fc_tx_pause: pause = 0; asm_dir = 1; break; case ixgbe_fc_rx_pause: /* Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE, as such we fall * through to the fc_full statement. Later, we will * disable the adapter's ability to send PAUSE frames. */ case ixgbe_fc_full: pause = 1; asm_dir = 1; break; default: ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; } if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) { ret_val = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); if (ret_val != IXGBE_SUCCESS) goto out; reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); if (pause) reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; if (asm_dir) reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; ret_val = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); /* This device does not fully support AN. */ hw->fc.disable_fc_autoneg = true; } out: return ret_val; } /** * ixgbe_set_mux - Set mux for port 1 access with CS4227 * @hw: pointer to hardware structure * @state: set mux if 1, clear if 0 */ STATIC void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) { u32 esdp; if (!hw->bus.lan_id) return; esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (state) esdp |= IXGBE_ESDP_SDP1; else esdp &= ~IXGBE_ESDP_SDP1; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore and sets the I2C MUX **/ s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) { s32 status; DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em"); status = ixgbe_acquire_swfw_sync_X540(hw, mask); if (status) return status; if (mask & IXGBE_GSSR_I2C_MASK) ixgbe_set_mux(hw, 1); return IXGBE_SUCCESS; } /** * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore and sets the I2C MUX **/ void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) { DEBUGFUNC("ixgbe_release_swfw_sync_X550em"); if (mask & IXGBE_GSSR_I2C_MASK) ixgbe_set_mux(hw, 0); ixgbe_release_swfw_sync_X540(hw, mask); } /** * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt * @hw: pointer to hardware structure * * Handle external Base T PHY interrupt. If high temperature * failure alarm then return error, else if link status change * then setup internal/external PHY link * * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature * failure alarm, else return PHY access status. */ s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) { bool lsc; u32 status; status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); if (status != IXGBE_SUCCESS) return status; if (lsc) return ixgbe_setup_internal_phy(hw); return IXGBE_SUCCESS; } /** * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Setup internal/external PHY link speed based on link speed, then set * external PHY auto advertised link speed. * * Returns error status for any failure **/ s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 status; ixgbe_link_speed force_speed; DEBUGFUNC("ixgbe_setup_mac_link_t_X550em"); /* Setup internal/external PHY link speed to iXFI (10G), unless * only 1G is auto advertised then setup KX link. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) force_speed = IXGBE_LINK_SPEED_10GB_FULL; else force_speed = IXGBE_LINK_SPEED_1GB_FULL; /* If internal link mode is XFI, then setup XFI internal link. */ if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { status = ixgbe_setup_ixfi_x550em(hw, &force_speed); if (status != IXGBE_SUCCESS) return status; } return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); } /** * ixgbe_check_link_t_X550em - Determine link and speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true when link is up * @link_up_wait_to_complete: bool used to wait for link up or not * * Check that both the MAC and X557 external PHY have link. **/ s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { u32 status; u16 autoneg_status; if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) return IXGBE_ERR_CONFIG; status = ixgbe_check_mac_link_generic(hw, speed, link_up, link_up_wait_to_complete); /* If check link fails or MAC link is not up, then return */ if (status != IXGBE_SUCCESS || !(*link_up)) return status; /* MAC link is up, so check external PHY link. * Read this twice back to back to indicate current status. */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_status); if (status != IXGBE_SUCCESS) return status; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_status); if (status != IXGBE_SUCCESS) return status; /* If external PHY link is not up, then indicate link not up */ if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) *link_up = false; return IXGBE_SUCCESS; } /** * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) { s32 status; status = ixgbe_reset_phy_generic(hw); if (status != IXGBE_SUCCESS) return status; /* Configure Link Status Alarm and Temperature Threshold interrupts */ return ixgbe_enable_lasi_ext_t_x550em(hw); } /** * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs. * @hw: pointer to hardware structure * @led_idx: led number to turn on **/ s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx) { u16 phy_data; DEBUGFUNC("ixgbe_led_on_t_X550em"); if (led_idx >= IXGBE_X557_MAX_LED_INDEX) return IXGBE_ERR_PARAM; /* To turn on the LED, set mode to ON. */ ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); return IXGBE_SUCCESS; } /** * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs. * @hw: pointer to hardware structure * @led_idx: led number to turn off **/ s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx) { u16 phy_data; DEBUGFUNC("ixgbe_led_off_t_X550em"); if (led_idx >= IXGBE_X557_MAX_LED_INDEX) return IXGBE_ERR_PARAM; /* To turn on the LED, set mode to ON. */ ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); return IXGBE_SUCCESS; } ================================================ FILE: drivers/net/ixgbe/base/ixgbe_x550.h ================================================ /******************************************************************************* Copyright (c) 2001-2015, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #ifndef _IXGBE_X550_H_ #define _IXGBE_X550_H_ #include "ixgbe_type.h" s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw); s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw); s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw); s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw); s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw); s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw); s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw); s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size); s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw); s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_set_eee_X550(struct ixgbe_hw *hw, bool enable_eee); s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee); void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, unsigned int pool); void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 data); s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u32 *data); void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw); void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw); void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap); void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf); enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw); s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw); s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw); s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw); s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw); void ixgbe_disable_rx_x550(struct ixgbe_hw *hw); s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed); s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask); void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask); s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw); s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw); s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx); s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx); #endif /* _IXGBE_X550_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_82599_bypass.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "base/ixgbe_type.h" #include "base/ixgbe_82599.h" #include "base/ixgbe_api.h" #include "base/ixgbe_common.h" #include "base/ixgbe_phy.h" #include "ixgbe_bypass_defines.h" #include "ixgbe_bypass.h" /** * ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber * @hw: pointer to hardware structure * @speed: link speed to set * * We set the module speed differently for fixed fiber. For other * multi-speed devices we don't have an error value so here if we * detect an error we just log it and exit. */ static void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) { s32 status; u8 rs, eeprom_data; switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: /* one bit mask same as setting on */ rs = IXGBE_SFF_SOFT_RS_SELECT_10G; break; case IXGBE_LINK_SPEED_1GB_FULL: rs = IXGBE_SFF_SOFT_RS_SELECT_1G; break; default: PMD_DRV_LOG(ERR, "Invalid fixed module speed"); return; } /* Set RS0 */ status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, IXGBE_I2C_EEPROM_DEV_ADDR2, &eeprom_data); if (status) { PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS0"); goto out; } eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs; status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, IXGBE_I2C_EEPROM_DEV_ADDR2, eeprom_data); if (status) { PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS0"); goto out; } /* Set RS1 */ status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, IXGBE_I2C_EEPROM_DEV_ADDR2, &eeprom_data); if (status) { PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS1"); goto out; } eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs; status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, IXGBE_I2C_EEPROM_DEV_ADDR2, eeprom_data); if (status) { PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS1"); goto out; } out: return; } /** * ixgbe_setup_mac_link_multispeed_fixed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_multispeed_fixed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete) { s32 status = IXGBE_SUCCESS; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; u32 speedcnt = 0; u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); u32 i = 0; bool link_up = false; bool negotiation; PMD_INIT_FUNC_TRACE(); /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation); if (status != IXGBE_SUCCESS) return status; speed &= link_speed; /* * Try each speed one by one, highest priority first. We do this in * software because 10gb fiber doesn't support speed autonegotiation. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) { speedcnt++; highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; /* Set the module link speed */ ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_10GB_FULL); /* Set the module link speed */ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); /* Allow module to change analog characteristics (1G->10G) */ msec_delay(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* * Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted. 82599 uses the same timing for 10g SFI. */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { speedcnt++; if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; /* Set the module link speed */ ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_1GB_FULL); /* Allow module to change analog characteristics (10G->1G) */ msec_delay(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* Wait for the link partner to also set speed */ msec_delay(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) return status; if (link_up) goto out; } /* * We didn't get link. Configure back to the highest speed we tried, * (if there was more than one). We call ourselves back with just the * single highest speed that the user requested. */ if (speedcnt > 1) status = ixgbe_setup_mac_link_multispeed_fixed_fiber(hw, highest_link_speed, autoneg_wait_to_complete); out: /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; return status; } static enum ixgbe_media_type ixgbe_bypass_get_media_type(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; PMD_INIT_FUNC_TRACE(); if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { media_type = ixgbe_media_type_fiber; } else { media_type = ixgbe_get_media_type_82599(hw); } return (media_type); } /* * Wrapper around shared code (base driver) to support BYPASS nic. */ s32 ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw) { s32 ret_val; if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { hw->mac.type = ixgbe_mac_82599EB; } ret_val = ixgbe_init_shared_code(hw); if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type; ixgbe_init_mac_link_ops_82599(hw); } return ret_val; } s32 ixgbe_bypass_init_hw(struct ixgbe_hw *hw) { int rc; if ((rc = ixgbe_init_hw(hw)) == 0 && hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { hw->mac.ops.setup_link = &ixgbe_setup_mac_link_multispeed_fixed_fiber; hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type; hw->mac.ops.disable_tx_laser = NULL; hw->mac.ops.enable_tx_laser = NULL; hw->mac.ops.flap_tx_laser = NULL; } return (rc); } ================================================ FILE: drivers/net/ixgbe/ixgbe_bypass.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "ixgbe_ethdev.h" #include "ixgbe_bypass_api.h" #define BYPASS_STATUS_OFF_MASK 3 /* Macros to check for invlaid function pointers. */ #define FUNC_PTR_OR_ERR_RET(func, retval) do { \ if ((func) == NULL) { \ PMD_DRV_LOG(ERR, "%s:%d function not supported", \ __func__, __LINE__); \ return retval; \ } \ } while(0) #define FUNC_PTR_OR_RET(func) do { \ if ((func) == NULL) { \ PMD_DRV_LOG(ERR, "%s:%d function not supported", \ __func__, __LINE__); \ return; \ } \ } while(0) /** * ixgbe_bypass_set_time - Set bypass FW time epoc. * * @hw: pointer to hardware structure * * This function with sync the FW date stamp with that of the * system clock. **/ static void ixgbe_bypass_set_time(struct ixgbe_adapter *adapter) { u32 mask, value; u32 sec; struct ixgbe_hw *hw = &adapter->hw; sec = 0; /* * Send the FW our current time and turn on time_valid and * timer_reset bits. */ mask = BYPASS_CTL1_TIME_M | BYPASS_CTL1_VALID_M | BYPASS_CTL1_OFFTRST_M; value = (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID | BYPASS_CTL1_OFFTRST; FUNC_PTR_OR_RET(adapter->bps.ops.bypass_set); /* Store FW reset time (in seconds from epoch). */ adapter->bps.reset_tm = time(NULL); /* reset FW timer. */ adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL1, mask, value); } /** * ixgbe_bypass_init - Make some environment changes for bypass * * @adapter: pointer to ixgbe_adapter structure for access to state bits * * This function collects all the modifications needed by the bypass * driver. **/ void ixgbe_bypass_init(struct rte_eth_dev *dev) { struct ixgbe_adapter *adapter; struct ixgbe_hw *hw; adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; /* Only allow BYPASS ops on the first port */ if (hw->device_id != IXGBE_DEV_ID_82599_BYPASS || hw->bus.func != 0) { PMD_DRV_LOG(ERR, "bypass function is not supported on that device"); return; } /* set bypass ops. */ adapter->bps.ops.bypass_rw = &ixgbe_bypass_rw_generic; adapter->bps.ops.bypass_valid_rd = &ixgbe_bypass_valid_rd_generic; adapter->bps.ops.bypass_set = &ixgbe_bypass_set_generic; adapter->bps.ops.bypass_rd_eep = &ixgbe_bypass_rd_eep_generic; /* set the time for logging. */ ixgbe_bypass_set_time(adapter); /* Don't have the SDP to the laser */ hw->mac.ops.disable_tx_laser = NULL; hw->mac.ops.enable_tx_laser = NULL; hw->mac.ops.flap_tx_laser = NULL; } s32 ixgbe_bypass_state_show(struct rte_eth_dev *dev, u32 *state) { struct ixgbe_hw *hw; s32 ret_val; u32 cmd; u32 by_ctl = 0; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP); cmd = BYPASS_PAGE_CTL0; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl); /* Assume bypass_rw didn't error out, if it did state will * be ignored anyway. */ *state = (by_ctl >> BYPASS_STATUS_OFF_SHIFT) & BYPASS_STATUS_OFF_MASK; return (ret_val); } s32 ixgbe_bypass_state_store(struct rte_eth_dev *dev, u32 *new_state) { struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); struct ixgbe_hw *hw; s32 ret_val; hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP); /* Set the new state */ ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0, BYPASS_MODE_OFF_M, *new_state); if (ret_val) goto exit; /* Set AUTO back on so FW can receive events */ ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0, BYPASS_MODE_OFF_M, BYPASS_AUTO); exit: return ret_val; } s32 ixgbe_bypass_event_show(struct rte_eth_dev *dev, u32 event, u32 *state) { struct ixgbe_hw *hw; s32 ret_val; u32 shift; u32 cmd; u32 by_ctl = 0; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP); cmd = BYPASS_PAGE_CTL0; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl); /* Assume bypass_rw didn't error out, if it did event will * be ignored anyway. */ switch (event) { case BYPASS_EVENT_WDT_TO: shift = BYPASS_WDTIMEOUT_SHIFT; break; case BYPASS_EVENT_MAIN_ON: shift = BYPASS_MAIN_ON_SHIFT; break; case BYPASS_EVENT_MAIN_OFF: shift = BYPASS_MAIN_OFF_SHIFT; break; case BYPASS_EVENT_AUX_ON: shift = BYPASS_AUX_ON_SHIFT; break; case BYPASS_EVENT_AUX_OFF: shift = BYPASS_AUX_OFF_SHIFT; break; default: return EINVAL; } *state = (by_ctl >> shift) & 0x3; return ret_val; } s32 ixgbe_bypass_event_store(struct rte_eth_dev *dev, u32 event, u32 state) { struct ixgbe_hw *hw; u32 status; u32 off; s32 ret_val; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP); switch (event) { case BYPASS_EVENT_WDT_TO: off = BYPASS_WDTIMEOUT_M; status = state << BYPASS_WDTIMEOUT_SHIFT; break; case BYPASS_EVENT_MAIN_ON: off = BYPASS_MAIN_ON_M; status = state << BYPASS_MAIN_ON_SHIFT; break; case BYPASS_EVENT_MAIN_OFF: off = BYPASS_MAIN_OFF_M; status = state << BYPASS_MAIN_OFF_SHIFT; break; case BYPASS_EVENT_AUX_ON: off = BYPASS_AUX_ON_M; status = state << BYPASS_AUX_ON_SHIFT; break; case BYPASS_EVENT_AUX_OFF: off = BYPASS_AUX_OFF_M; status = state << BYPASS_AUX_OFF_SHIFT; break; default: return EINVAL; } ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0, off, status); return ret_val; } s32 ixgbe_bypass_wd_timeout_store(struct rte_eth_dev *dev, u32 timeout) { struct ixgbe_hw *hw; u32 status; u32 mask; s32 ret_val; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_set, -ENOTSUP); /* disable the timer with timeout of zero */ if (timeout == RTE_BYPASS_TMT_OFF) { status = 0x0; /* WDG enable off */ mask = BYPASS_WDT_ENABLE_M; } else { /* set time out value */ mask = BYPASS_WDT_VALUE_M; /* enable the timer */ status = timeout << BYPASS_WDT_TIME_SHIFT; status |= 0x1 << BYPASS_WDT_ENABLE_SHIFT; mask |= BYPASS_WDT_ENABLE_M; } ret_val = adapter->bps.ops.bypass_set(hw, BYPASS_PAGE_CTL0, mask, status); return ret_val; } s32 ixgbe_bypass_ver_show(struct rte_eth_dev *dev, u32 *ver) { struct ixgbe_hw *hw; u32 cmd; u32 status; s32 ret_val; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP); cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; cmd |= (BYPASS_EEPROM_VER_ADD << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status); if (ret_val) goto exit; /* wait for the write to stick */ msleep(100); /* Now read the results */ cmd &= ~BYPASS_WE; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status); if (ret_val) goto exit; *ver = status & BYPASS_CTL2_DATA_M; /* only one byte of date */ exit: return ret_val; } s32 ixgbe_bypass_wd_timeout_show(struct rte_eth_dev *dev, u32 *wd_timeout) { struct ixgbe_hw *hw; u32 by_ctl = 0; u32 cmd; u32 wdg; s32 ret_val; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP); cmd = BYPASS_PAGE_CTL0; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &by_ctl); wdg = by_ctl & BYPASS_WDT_ENABLE_M; if (!wdg) *wd_timeout = RTE_BYPASS_TMT_OFF; else *wd_timeout = (by_ctl >> BYPASS_WDT_TIME_SHIFT) & BYPASS_WDT_MASK; return ret_val; } s32 ixgbe_bypass_wd_reset(struct rte_eth_dev *dev) { u32 cmd; u32 status; u32 sec; u32 count = 0; s32 ret_val; struct ixgbe_hw *hw; struct ixgbe_adapter *adapter = IXGBE_DEV_TO_ADPATER(dev); hw = &adapter->hw; FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_rw, -ENOTSUP); FUNC_PTR_OR_ERR_RET(adapter->bps.ops.bypass_valid_rd, -ENOTSUP); /* Use the lower level bit-bang functions since we don't need * to read the register first to get it's current state as we * are setting every thing in this write. */ /* Set up WD pet */ cmd = BYPASS_PAGE_CTL1 | BYPASS_WE | BYPASS_CTL1_WDT_PET; /* Resync the FW time while writing to CTL1 anyway */ adapter->bps.reset_tm = time(NULL); sec = 0; cmd |= (sec & BYPASS_CTL1_TIME_M) | BYPASS_CTL1_VALID; /* reset FW timer offset since we are resetting the clock */ cmd |= BYPASS_CTL1_OFFTRST; ret_val = adapter->bps.ops.bypass_rw(hw, cmd, &status); /* Read until it matches what we wrote, or we time out */ do { if (count++ > 10) { ret_val = IXGBE_BYPASS_FW_WRITE_FAILURE; break; } if (adapter->bps.ops.bypass_rw(hw, BYPASS_PAGE_CTL1, &status)) { ret_val = IXGBE_ERR_INVALID_ARGUMENT; break; } } while (!adapter->bps.ops.bypass_valid_rd(cmd, status)); return ret_val; } ================================================ FILE: drivers/net/ixgbe/ixgbe_bypass.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_BYPASS_H_ #define _IXGBE_BYPASS_H_ #ifdef RTE_NIC_BYPASS struct ixgbe_bypass_mac_ops { s32 (*bypass_rw) (struct ixgbe_hw *hw, u32 cmd, u32 *status); bool (*bypass_valid_rd) (u32 in_reg, u32 out_reg); s32 (*bypass_set) (struct ixgbe_hw *hw, u32 cmd, u32 event, u32 action); s32 (*bypass_rd_eep) (struct ixgbe_hw *hw, u32 addr, u8 *value); }; struct ixgbe_bypass_info { uint64_t reset_tm; struct ixgbe_bypass_mac_ops ops; }; struct rte_eth_dev; void ixgbe_bypass_init(struct rte_eth_dev *dev); s32 ixgbe_bypass_state_show(struct rte_eth_dev *dev, u32 *state); s32 ixgbe_bypass_state_store(struct rte_eth_dev *dev, u32 *new_state); s32 ixgbe_bypass_event_show(struct rte_eth_dev *dev, u32 event, u32 *state); s32 ixgbe_bypass_event_store(struct rte_eth_dev *dev, u32 event, u32 state); s32 ixgbe_bypass_wd_timeout_store(struct rte_eth_dev *dev, u32 timeout); s32 ixgbe_bypass_ver_show(struct rte_eth_dev *dev, u32 *ver); s32 ixgbe_bypass_wd_timeout_show(struct rte_eth_dev *dev, u32 *wd_timeout); s32 ixgbe_bypass_wd_reset(struct rte_eth_dev *dev); s32 ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw); s32 ixgbe_bypass_init_hw(struct ixgbe_hw *hw); #endif /* RTE_NIC_BYPASS */ #endif /* _IXGBE_BYPASS_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_bypass_api.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_BYPASS_API_H_ #define _IXGBE_BYPASS_API_H_ #ifdef RTE_NIC_BYPASS #include "ixgbe_bypass_defines.h" /** * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW * * @hw: pointer to hardware structure * @cmd: Command we send to the FW * @status: The reply from the FW * * Bit-bangs the cmd to the by_pass FW status points to what is returned. **/ #define IXGBE_BYPASS_BB_WAIT 1 static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status) { int i; u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo; u32 esdp; if (!status) return IXGBE_ERR_PARAM; *status = 0; /* SDP vary by MAC type */ switch (hw->mac.type) { case ixgbe_mac_82599EB: sck = IXGBE_ESDP_SDP7; sdi = IXGBE_ESDP_SDP0; sdo = IXGBE_ESDP_SDP6; dir_sck = IXGBE_ESDP_SDP7_DIR; dir_sdi = IXGBE_ESDP_SDP0_DIR; dir_sdo = IXGBE_ESDP_SDP6_DIR; break; case ixgbe_mac_X540: sck = IXGBE_ESDP_SDP2; sdi = IXGBE_ESDP_SDP0; sdo = IXGBE_ESDP_SDP1; dir_sck = IXGBE_ESDP_SDP2_DIR; dir_sdi = IXGBE_ESDP_SDP0_DIR; dir_sdo = IXGBE_ESDP_SDP1_DIR; break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: sck = IXGBE_ESDP_SDP2; sdi = IXGBE_ESDP_SDP0; sdo = IXGBE_ESDP_SDP1; dir_sck = IXGBE_ESDP_SDP2_DIR; dir_sdi = IXGBE_ESDP_SDP0_DIR; dir_sdo = IXGBE_ESDP_SDP1_DIR; break; default: return IXGBE_ERR_DEVICE_NOT_SUPPORTED; } /* Set SDP pins direction */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= dir_sck; /* SCK as output */ esdp |= dir_sdi; /* SDI as output */ esdp &= ~dir_sdo; /* SDO as input */ esdp |= sck; esdp |= sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); // TODO: msleep(IXGBE_BYPASS_BB_WAIT); /* Generate start condition */ esdp &= ~sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); esdp &= ~sck; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); /* Clock out the new control word and clock in the status */ for (i = 0; i < 32; i++) { if ((cmd >> (31 - i)) & 0x01) { esdp |= sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); } else { esdp &= ~sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); } IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); esdp |= sck; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); esdp &= ~sck; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & sdo) *status = (*status << 1) | 0x01; else *status = (*status << 1) | 0x00; msleep(IXGBE_BYPASS_BB_WAIT); } /* stop condition */ esdp |= sck; esdp &= ~sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); msleep(IXGBE_BYPASS_BB_WAIT); esdp |= sdi; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); /* set the page bits to match the cmd that the status it belongs to */ *status = (*status & 0x3fffffff) | (cmd & 0xc0000000); return 0; } /** * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang. * * If we send a write we can't be sure it took until we can read back * that same register. It can be a problem as some of the feilds may * for valid reasons change between the time wrote the register and * we read it again to verify. So this function check everything we * can check and then assumes it worked. * * @u32 in_reg - The register cmd for the bit-bang read. * @u32 out_reg - The register returned from a bit-bang read. **/ static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg) { u32 mask; /* Page must match for all control pages */ if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M)) return false; switch (in_reg & BYPASS_PAGE_M) { case BYPASS_PAGE_CTL0: /* All the following can't change since the last write * - All the event actions * - The timeout value */ mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M | BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M | BYPASS_WDTIMEOUT_M | BYPASS_WDT_VALUE_M; if ((out_reg & mask) != (in_reg & mask)) return false; /* 0x0 is never a valid value for bypass status */ if (!(out_reg & BYPASS_STATUS_OFF_M)) return false; break; case BYPASS_PAGE_CTL1: /* All the following can't change since the last write * - time valid bit * - time we last sent */ mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M; if ((out_reg & mask) != (in_reg & mask)) return false; break; case BYPASS_PAGE_CTL2: /* All we can check in this page is control number * which is already done above. */ break; } /* We are as sure as we can be return true */ return true; } /** * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter. * * @hw: pointer to hardware structure * @cmd: The control word we are setting. * @event: The event we are setting in the FW. This also happens to * be the mask for the event we are setting (handy) * @action: The action we set the event to in the FW. This is in a * bit field that happens to be what we want to put in * the event spot (also handy) **/ static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event, u32 action) { u32 by_ctl = 0; u32 cmd, verify; u32 count = 0; /* Get current values */ cmd = ctrl; /* just reading only need control number */ if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) return IXGBE_ERR_INVALID_ARGUMENT; /* Set to new action */ cmd = (by_ctl & ~event) | BYPASS_WE | action; if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl)) return IXGBE_ERR_INVALID_ARGUMENT; /* Page 0 force a FW eeprom write which is slow so verify */ if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) { verify = BYPASS_PAGE_CTL0; do { if (count++ > 5) return IXGBE_BYPASS_FW_WRITE_FAILURE; if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl)) return IXGBE_ERR_INVALID_ARGUMENT; } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl)); } else { /* We have give the FW time for the write to stick */ msleep(100); } return 0; } /** * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom address. * * @hw: pointer to hardware structure * @addr: The bypass eeprom address to read. * @value: The 8b of data at the address above. **/ static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value) { u32 cmd; u32 status; /* send the request */ cmd = BYPASS_PAGE_CTL2 | BYPASS_WE; cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M; if (ixgbe_bypass_rw_generic(hw, cmd, &status)) return IXGBE_ERR_INVALID_ARGUMENT; /* We have give the FW time for the write to stick */ msleep(100); /* now read the results */ cmd &= ~BYPASS_WE; if (ixgbe_bypass_rw_generic(hw, cmd, &status)) return IXGBE_ERR_INVALID_ARGUMENT; *value = status & BYPASS_CTL2_DATA_M; return 0; } #endif /* RTE_NIC_BYPASS */ #endif /* _IXGBE_BYPASS_API_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_bypass_defines.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_BYPASS_DEFINES_H_ #define _IXGBE_BYPASS_DEFINES_H_ #ifdef RTE_NIC_BYPASS #define msleep(x) rte_delay_us(x*1000) #define usleep_range(min, max) rte_delay_us(min) #define BYPASS_PAGE_CTL0 0x00000000 #define BYPASS_PAGE_CTL1 0x40000000 #define BYPASS_PAGE_CTL2 0x80000000 #define BYPASS_PAGE_M 0xc0000000 #define BYPASS_WE 0x20000000 #define BYPASS_AUTO 0x0 #define BYPASS_NOP 0x0 #define BYPASS_NORM 0x1 #define BYPASS_BYPASS 0x2 #define BYPASS_ISOLATE 0x3 #define BYPASS_EVENT_MAIN_ON 0x1 #define BYPASS_EVENT_AUX_ON 0x2 #define BYPASS_EVENT_MAIN_OFF 0x3 #define BYPASS_EVENT_AUX_OFF 0x4 #define BYPASS_EVENT_WDT_TO 0x5 #define BYPASS_EVENT_USR 0x6 #define BYPASS_MODE_OFF_M 0x00000003 #define BYPASS_STATUS_OFF_M 0x0000000c #define BYPASS_AUX_ON_M 0x00000030 #define BYPASS_MAIN_ON_M 0x000000c0 #define BYPASS_MAIN_OFF_M 0x00000300 #define BYPASS_AUX_OFF_M 0x00000c00 #define BYPASS_WDTIMEOUT_M 0x00003000 #define BYPASS_WDT_ENABLE_M 0x00004000 #define BYPASS_WDT_VALUE_M 0x00070000 #define BYPASS_MODE_OFF_SHIFT 0 #define BYPASS_STATUS_OFF_SHIFT 2 #define BYPASS_AUX_ON_SHIFT 4 #define BYPASS_MAIN_ON_SHIFT 6 #define BYPASS_MAIN_OFF_SHIFT 8 #define BYPASS_AUX_OFF_SHIFT 10 #define BYPASS_WDTIMEOUT_SHIFT 12 #define BYPASS_WDT_ENABLE_SHIFT 14 #define BYPASS_WDT_TIME_SHIFT 16 #define BYPASS_WDT_1 0x0 #define BYPASS_WDT_1_5 0x1 #define BYPASS_WDT_2 0x2 #define BYPASS_WDT_3 0x3 #define BYPASS_WDT_4 0x4 #define BYPASS_WDT_8 0x5 #define BYPASS_WDT_16 0x6 #define BYPASS_WDT_32 0x7 #define BYPASS_WDT_OFF 0xffff #define BYPASS_WDT_MASK 0x7 #define BYPASS_CTL1_TIME_M 0x01ffffff #define BYPASS_CTL1_VALID_M 0x02000000 #define BYPASS_CTL1_OFFTRST_M 0x04000000 #define BYPASS_CTL1_WDT_PET_M 0x08000000 #define BYPASS_CTL1_VALID 0x02000000 #define BYPASS_CTL1_OFFTRST 0x04000000 #define BYPASS_CTL1_WDT_PET 0x08000000 #define BYPASS_CTL2_DATA_M 0x000000ff #define BYPASS_CTL2_OFFSET_M 0x0000ff00 #define BYPASS_CTL2_RW_M 0x00010000 #define BYPASS_CTL2_HEAD_M 0x0ff00000 #define BYPASS_CTL2_OFFSET_SHIFT 8 #define BYPASS_CTL2_HEAD_SHIFT 20 #define BYPASS_CTL2_RW 0x00010000 enum ixgbe_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, __IXGBE_SERVICE_SCHED, __IXGBE_IN_SFP_INIT, __IXGBE_IN_BYPASS_LOW, __IXGBE_IN_BYPASS_HIGH, __IXGBE_IN_BYPASS_LOG, }; #define BYPASS_MAX_LOGS 43 #define BYPASS_LOG_SIZE 5 #define BYPASS_LOG_LINE_SIZE 37 #define BYPASS_EEPROM_VER_ADD 0x02 #define BYPASS_LOG_TIME_M 0x01ffffff #define BYPASS_LOG_TIME_VALID_M 0x02000000 #define BYPASS_LOG_HEAD_M 0x04000000 #define BYPASS_LOG_CLEAR_M 0x08000000 #define BYPASS_LOG_EVENT_M 0xf0000000 #define BYPASS_LOG_ACTION_M 0x03 #define BYPASS_LOG_EVENT_SHIFT 28 #define BYPASS_LOG_CLEAR_SHIFT 24 /* bit offset */ #define IXGBE_DEV_TO_ADPATER(dev) \ ((struct ixgbe_adapter*)(dev->data->dev_private)) /* extractions from ixgbe_phy.h */ #define IXGBE_I2C_EEPROM_DEV_ADDR2 0xA2 #define IXGBE_SFF_SFF_8472_SWAP 0x5C #define IXGBE_SFF_SFF_8472_COMP 0x5E #define IXGBE_SFF_SFF_8472_OSCB 0x6E #define IXGBE_SFF_SFF_8472_ESCB 0x76 #define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define IXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define IXGBE_SFF_SOFT_RS_SELECT_1G 0x0 /* extractions from ixgbe_type.h */ #define IXGBE_DEV_ID_82599_BYPASS 0x155D #define IXGBE_BYPASS_FW_WRITE_FAILURE -35 #endif /* RTE_NIC_BYPASS */ #endif /* _IXGBE_BYPASS_DEFINES_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ixgbe_logs.h" #include "base/ixgbe_api.h" #include "base/ixgbe_vf.h" #include "base/ixgbe_common.h" #include "ixgbe_ethdev.h" #include "ixgbe_bypass.h" #include "ixgbe_rxtx.h" #include "base/ixgbe_type.h" #include "base/ixgbe_phy.h" #include "ixgbe_regs.h" /* * High threshold controlling when to start sending XOFF frames. Must be at * least 8 bytes less than receive packet buffer size. This value is in units * of 1024 bytes. */ #define IXGBE_FC_HI 0x80 /* * Low threshold controlling when to start sending XON frames. This value is * in units of 1024 bytes. */ #define IXGBE_FC_LO 0x40 /* Default minimum inter-interrupt interval for EITR configuration */ #define IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT 0x79E /* Timer value included in XOFF frames. */ #define IXGBE_FC_PAUSE 0x680 #define IXGBE_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */ #define IXGBE_LINK_UP_CHECK_TIMEOUT 1000 /* ms */ #define IXGBE_VMDQ_NUM_UC_MAC 4096 /* Maximum nb. of UC MAC addr. */ #define IXGBE_MMW_SIZE_DEFAULT 0x4 #define IXGBE_MMW_SIZE_JUMBO_FRAME 0x14 #define IXGBE_MAX_RING_DESC 4096 /* replicate define from rxtx */ /* * Default values for RX/TX configuration */ #define IXGBE_DEFAULT_RX_FREE_THRESH 32 #define IXGBE_DEFAULT_RX_PTHRESH 8 #define IXGBE_DEFAULT_RX_HTHRESH 8 #define IXGBE_DEFAULT_RX_WTHRESH 0 #define IXGBE_DEFAULT_TX_FREE_THRESH 32 #define IXGBE_DEFAULT_TX_PTHRESH 32 #define IXGBE_DEFAULT_TX_HTHRESH 0 #define IXGBE_DEFAULT_TX_WTHRESH 0 #define IXGBE_DEFAULT_TX_RSBIT_THRESH 32 /* Bit shift and mask */ #define IXGBE_4_BIT_WIDTH (CHAR_BIT / 2) #define IXGBE_4_BIT_MASK RTE_LEN2MASK(IXGBE_4_BIT_WIDTH, uint8_t) #define IXGBE_8_BIT_WIDTH CHAR_BIT #define IXGBE_8_BIT_MASK UINT8_MAX #define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */ #define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0])) #define IXGBE_HKEY_MAX_INDEX 10 /* Additional timesync values. */ #define IXGBE_TIMINCA_16NS_SHIFT 24 #define IXGBE_TIMINCA_INCVALUE 16000000 #define IXGBE_TIMINCA_INIT ((0x02 << IXGBE_TIMINCA_16NS_SHIFT) \ | IXGBE_TIMINCA_INCVALUE) static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev); static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev); static int ixgbe_dev_configure(struct rte_eth_dev *dev); static int ixgbe_dev_start(struct rte_eth_dev *dev); static void ixgbe_dev_stop(struct rte_eth_dev *dev); static int ixgbe_dev_set_link_up(struct rte_eth_dev *dev); static int ixgbe_dev_set_link_down(struct rte_eth_dev *dev); static void ixgbe_dev_close(struct rte_eth_dev *dev); static void ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev); static void ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev); static void ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev); static void ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev); static int ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); static void ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, unsigned n); static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev); static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev); static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx); static void ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static void ixgbevf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); static int ixgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id); static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on); static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue); static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue); static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev); static void ixgbe_vlan_hw_extend_disable(struct rte_eth_dev *dev); static int ixgbe_dev_led_on(struct rte_eth_dev *dev); static int ixgbe_dev_led_off(struct rte_eth_dev *dev); static int ixgbe_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); static int ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf); static int ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev); static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev); #ifdef RTE_NEXT_ABI static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev); #endif static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev); static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev); static void ixgbe_dev_interrupt_handler(struct rte_intr_handle *handle, void *param); static void ixgbe_dev_interrupt_delayed_handler(void *param); static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index); static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr); static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_config); /* For Virtual Function support */ static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev); static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev); static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev); static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev); static int ixgbevf_dev_configure(struct rte_eth_dev *dev); static int ixgbevf_dev_start(struct rte_eth_dev *dev); static void ixgbevf_dev_stop(struct rte_eth_dev *dev); static void ixgbevf_dev_close(struct rte_eth_dev *dev); static void ixgbevf_intr_disable(struct ixgbe_hw *hw); static void ixgbevf_intr_enable(struct ixgbe_hw *hw); static void ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void ixgbevf_dev_stats_reset(struct rte_eth_dev *dev); static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on); static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on); static void ixgbevf_dev_interrupt_handler(struct rte_intr_handle *handle, void *param); #ifdef RTE_NEXT_ABI static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id); static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); static void ixgbevf_set_ivar_map(struct ixgbe_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector); #endif static void ixgbevf_configure_msix(struct rte_eth_dev *dev); /* For Eth VMDQ APIs support */ static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct ether_addr* mac_addr,uint8_t on); static int ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev,uint8_t on); static int ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool, uint16_t rx_mask, uint8_t on); static int ixgbe_set_pool_rx(struct rte_eth_dev *dev,uint16_t pool,uint8_t on); static int ixgbe_set_pool_tx(struct rte_eth_dev *dev,uint16_t pool,uint8_t on); static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan, uint64_t pool_mask,uint8_t vlan_on); static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev, struct rte_eth_mirror_conf *mirror_conf, uint8_t rule_id, uint8_t on); static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id); #ifdef RTE_NEXT_ABI static int ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id); static int ixgbe_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); static void ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector); #endif static void ixgbe_configure_msix(struct rte_eth_dev *dev); static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t tx_rate); static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, uint16_t tx_rate, uint64_t q_msk); static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool); static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); static void ixgbevf_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr); static int ixgbe_syn_filter_set(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter, bool add); static int ixgbe_syn_filter_get(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter); static int ixgbe_syn_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, struct ixgbe_5tuple_filter *filter); static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, struct ixgbe_5tuple_filter *filter); static int ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *filter, bool add); static int ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *filter); static int ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter, bool add); static int ixgbe_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter); static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu); static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); static int ixgbe_get_reg_length(struct rte_eth_dev *dev); static int ixgbe_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); static int ixgbe_get_eeprom_length(struct rte_eth_dev *dev); static int ixgbe_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); static int ixgbe_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *eeprom); static int ixgbevf_get_reg_length(struct rte_eth_dev *dev); static int ixgbevf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); static int ixgbe_timesync_enable(struct rte_eth_dev *dev); static int ixgbe_timesync_disable(struct rte_eth_dev *dev); static int ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags); static int ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp); /* * Define VF Stats MACRO for Non "cleared on read" register */ #define UPDATE_VF_STAT(reg, last, cur) \ { \ uint32_t latest = IXGBE_READ_REG(hw, reg); \ cur += latest - last; \ last = latest; \ } #define UPDATE_VF_STAT_36BIT(lsb, msb, last, cur) \ { \ u64 new_lsb = IXGBE_READ_REG(hw, lsb); \ u64 new_msb = IXGBE_READ_REG(hw, msb); \ u64 latest = ((new_msb << 32) | new_lsb); \ cur += (0x1000000000LL + latest - last) & 0xFFFFFFFFFLL; \ last = latest; \ } #define IXGBE_SET_HWSTRIP(h, q) do{\ uint32_t idx = (q) / (sizeof ((h)->bitmap[0]) * NBBY); \ uint32_t bit = (q) % (sizeof ((h)->bitmap[0]) * NBBY); \ (h)->bitmap[idx] |= 1 << bit;\ }while(0) #define IXGBE_CLEAR_HWSTRIP(h, q) do{\ uint32_t idx = (q) / (sizeof ((h)->bitmap[0]) * NBBY); \ uint32_t bit = (q) % (sizeof ((h)->bitmap[0]) * NBBY); \ (h)->bitmap[idx] &= ~(1 << bit);\ }while(0) #define IXGBE_GET_HWSTRIP(h, q, r) do{\ uint32_t idx = (q) / (sizeof ((h)->bitmap[0]) * NBBY); \ uint32_t bit = (q) % (sizeof ((h)->bitmap[0]) * NBBY); \ (r) = (h)->bitmap[idx] >> bit & 1;\ }while(0) /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_ixgbe_map[] = { #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; /* * The set of PCI devices this driver supports (for 82599 VF) */ static const struct rte_pci_id pci_id_ixgbevf_map[] = { #define RTE_PCI_DEV_ID_DECL_IXGBEVF(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static const struct eth_dev_ops ixgbe_eth_dev_ops = { .dev_configure = ixgbe_dev_configure, .dev_start = ixgbe_dev_start, .dev_stop = ixgbe_dev_stop, .dev_set_link_up = ixgbe_dev_set_link_up, .dev_set_link_down = ixgbe_dev_set_link_down, .dev_close = ixgbe_dev_close, .promiscuous_enable = ixgbe_dev_promiscuous_enable, .promiscuous_disable = ixgbe_dev_promiscuous_disable, .allmulticast_enable = ixgbe_dev_allmulticast_enable, .allmulticast_disable = ixgbe_dev_allmulticast_disable, .link_update = ixgbe_dev_link_update, .stats_get = ixgbe_dev_stats_get, .xstats_get = ixgbe_dev_xstats_get, .stats_reset = ixgbe_dev_stats_reset, .xstats_reset = ixgbe_dev_xstats_reset, .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set, .dev_infos_get = ixgbe_dev_info_get, .mtu_set = ixgbe_dev_mtu_set, .vlan_filter_set = ixgbe_vlan_filter_set, .vlan_tpid_set = ixgbe_vlan_tpid_set, .vlan_offload_set = ixgbe_vlan_offload_set, .vlan_strip_queue_set = ixgbe_vlan_strip_queue_set, .rx_queue_start = ixgbe_dev_rx_queue_start, .rx_queue_stop = ixgbe_dev_rx_queue_stop, .tx_queue_start = ixgbe_dev_tx_queue_start, .tx_queue_stop = ixgbe_dev_tx_queue_stop, .rx_queue_setup = ixgbe_dev_rx_queue_setup, #ifdef RTE_NEXT_ABI .rx_queue_intr_enable = ixgbe_dev_rx_queue_intr_enable, .rx_queue_intr_disable = ixgbe_dev_rx_queue_intr_disable, #endif .rx_queue_release = ixgbe_dev_rx_queue_release, .rx_queue_count = ixgbe_dev_rx_queue_count, .rx_descriptor_done = ixgbe_dev_rx_descriptor_done, .tx_queue_setup = ixgbe_dev_tx_queue_setup, .tx_queue_release = ixgbe_dev_tx_queue_release, .dev_led_on = ixgbe_dev_led_on, .dev_led_off = ixgbe_dev_led_off, .flow_ctrl_get = ixgbe_flow_ctrl_get, .flow_ctrl_set = ixgbe_flow_ctrl_set, .priority_flow_ctrl_set = ixgbe_priority_flow_ctrl_set, .mac_addr_add = ixgbe_add_rar, .mac_addr_remove = ixgbe_remove_rar, .mac_addr_set = ixgbe_set_default_mac_addr, .uc_hash_table_set = ixgbe_uc_hash_table_set, .uc_all_hash_table_set = ixgbe_uc_all_hash_table_set, .mirror_rule_set = ixgbe_mirror_rule_set, .mirror_rule_reset = ixgbe_mirror_rule_reset, .set_vf_rx_mode = ixgbe_set_pool_rx_mode, .set_vf_rx = ixgbe_set_pool_rx, .set_vf_tx = ixgbe_set_pool_tx, .set_vf_vlan_filter = ixgbe_set_pool_vlan_filter, .set_queue_rate_limit = ixgbe_set_queue_rate_limit, .set_vf_rate_limit = ixgbe_set_vf_rate_limit, .reta_update = ixgbe_dev_rss_reta_update, .reta_query = ixgbe_dev_rss_reta_query, #ifdef RTE_NIC_BYPASS .bypass_init = ixgbe_bypass_init, .bypass_state_set = ixgbe_bypass_state_store, .bypass_state_show = ixgbe_bypass_state_show, .bypass_event_set = ixgbe_bypass_event_store, .bypass_event_show = ixgbe_bypass_event_show, .bypass_wd_timeout_set = ixgbe_bypass_wd_timeout_store, .bypass_wd_timeout_show = ixgbe_bypass_wd_timeout_show, .bypass_ver_show = ixgbe_bypass_ver_show, .bypass_wd_reset = ixgbe_bypass_wd_reset, #endif /* RTE_NIC_BYPASS */ .rss_hash_update = ixgbe_dev_rss_hash_update, .rss_hash_conf_get = ixgbe_dev_rss_hash_conf_get, .filter_ctrl = ixgbe_dev_filter_ctrl, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, .timesync_enable = ixgbe_timesync_enable, .timesync_disable = ixgbe_timesync_disable, .timesync_read_rx_timestamp = ixgbe_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = ixgbe_timesync_read_tx_timestamp, .get_reg_length = ixgbe_get_reg_length, .get_reg = ixgbe_get_regs, .get_eeprom_length = ixgbe_get_eeprom_length, .get_eeprom = ixgbe_get_eeprom, .set_eeprom = ixgbe_set_eeprom, }; /* * dev_ops for virtual function, bare necessities for basic vf * operation have been implemented */ static const struct eth_dev_ops ixgbevf_eth_dev_ops = { .dev_configure = ixgbevf_dev_configure, .dev_start = ixgbevf_dev_start, .dev_stop = ixgbevf_dev_stop, .link_update = ixgbe_dev_link_update, .stats_get = ixgbevf_dev_stats_get, .stats_reset = ixgbevf_dev_stats_reset, .dev_close = ixgbevf_dev_close, .dev_infos_get = ixgbevf_dev_info_get, .mtu_set = ixgbevf_dev_set_mtu, .vlan_filter_set = ixgbevf_vlan_filter_set, .vlan_strip_queue_set = ixgbevf_vlan_strip_queue_set, .vlan_offload_set = ixgbevf_vlan_offload_set, .rx_queue_setup = ixgbe_dev_rx_queue_setup, .rx_queue_release = ixgbe_dev_rx_queue_release, .rx_descriptor_done = ixgbe_dev_rx_descriptor_done, .tx_queue_setup = ixgbe_dev_tx_queue_setup, .tx_queue_release = ixgbe_dev_tx_queue_release, #ifdef RTE_NEXT_ABI .rx_queue_intr_enable = ixgbevf_dev_rx_queue_intr_enable, .rx_queue_intr_disable = ixgbevf_dev_rx_queue_intr_disable, #endif .mac_addr_add = ixgbevf_add_mac_addr, .mac_addr_remove = ixgbevf_remove_mac_addr, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, .mac_addr_set = ixgbevf_set_default_mac_addr, .get_reg_length = ixgbevf_get_reg_length, .get_reg = ixgbevf_get_regs, }; /* store statistics names and its offset in stats structure */ struct rte_ixgbe_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; }; static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = { {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)}, {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)}, {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)}, {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)}, {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)}, {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)}, {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)}, {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)}, {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)}, {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)}, {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)}, {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)}, {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)}, {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)}, {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)}, {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)}, {"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)}, {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)}, {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)}, {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)}, {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)}, {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)}, {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)}, }; #define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \ sizeof(rte_ixgbe_stats_strings[0])) /** * Atomically reads the link status information from global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_ixgbe_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /** * Atomically writes the link status information into global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int rte_ixgbe_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /* * This function is the same as ixgbe_is_sfp() in base/ixgbe.h. */ static inline int ixgbe_is_sfp(struct ixgbe_hw *hw) { switch (hw->phy.type) { case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: return 1; default: return 0; } } static inline int32_t ixgbe_pf_reset_hw(struct ixgbe_hw *hw) { uint32_t ctrl_ext; int32_t status; status = ixgbe_reset_hw(hw); ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); return status; } static inline void ixgbe_enable_intr(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); IXGBE_WRITE_REG(hw, IXGBE_EIMS, intr->mask); IXGBE_WRITE_FLUSH(hw); } /* * This function is based on ixgbe_disable_intr() in base/ixgbe.h. */ static void ixgbe_disable_intr(struct ixgbe_hw *hw) { PMD_INIT_FUNC_TRACE(); if (hw->mac.type == ixgbe_mac_82598EB) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, ~0); } else { IXGBE_WRITE_REG(hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), ~0); } IXGBE_WRITE_FLUSH(hw); } /* * This function resets queue statistics mapping registers. * From Niantic datasheet, Initialization of Statistics section: * "...if software requires the queue counters, the RQSMR and TQSM registers * must be re-programmed following a device reset. */ static void ixgbe_reset_qstat_mappings(struct ixgbe_hw *hw) { uint32_t i; for(i = 0; i != IXGBE_NB_STAT_MAPPING_REGS; i++) { IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), 0); } } static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx) { #define QSM_REG_NB_BITS_PER_QMAP_FIELD 8 #define NB_QMAP_FIELDS_PER_QSM_REG 4 #define QMAP_FIELD_RESERVED_BITS_MASK 0x0f struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct ixgbe_stat_mapping_registers *stat_mappings = IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(eth_dev->data->dev_private); uint32_t qsmr_mask = 0; uint32_t clearing_mask = QMAP_FIELD_RESERVED_BITS_MASK; uint32_t q_map; uint8_t n, offset; if ((hw->mac.type != ixgbe_mac_82599EB) && (hw->mac.type != ixgbe_mac_X540) && (hw->mac.type != ixgbe_mac_X550) && (hw->mac.type != ixgbe_mac_X550EM_x)) return -ENOSYS; PMD_INIT_LOG(DEBUG, "Setting port %d, %s queue_id %d to stat index %d", (int)(eth_dev->data->port_id), is_rx ? "RX" : "TX", queue_id, stat_idx); n = (uint8_t)(queue_id / NB_QMAP_FIELDS_PER_QSM_REG); if (n >= IXGBE_NB_STAT_MAPPING_REGS) { PMD_INIT_LOG(ERR, "Nb of stat mapping registers exceeded"); return -EIO; } offset = (uint8_t)(queue_id % NB_QMAP_FIELDS_PER_QSM_REG); /* Now clear any previous stat_idx set */ clearing_mask <<= (QSM_REG_NB_BITS_PER_QMAP_FIELD * offset); if (!is_rx) stat_mappings->tqsm[n] &= ~clearing_mask; else stat_mappings->rqsmr[n] &= ~clearing_mask; q_map = (uint32_t)stat_idx; q_map &= QMAP_FIELD_RESERVED_BITS_MASK; qsmr_mask = q_map << (QSM_REG_NB_BITS_PER_QMAP_FIELD * offset); if (!is_rx) stat_mappings->tqsm[n] |= qsmr_mask; else stat_mappings->rqsmr[n] |= qsmr_mask; PMD_INIT_LOG(DEBUG, "Set port %d, %s queue_id %d to stat index %d", (int)(eth_dev->data->port_id), is_rx ? "RX" : "TX", queue_id, stat_idx); PMD_INIT_LOG(DEBUG, "%s[%d] = 0x%08x", is_rx ? "RQSMR" : "TQSM", n, is_rx ? stat_mappings->rqsmr[n] : stat_mappings->tqsm[n]); /* Now write the mapping in the appropriate register */ if (is_rx) { PMD_INIT_LOG(DEBUG, "Write 0x%x to RX IXGBE stat mapping reg:%d", stat_mappings->rqsmr[n], n); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(n), stat_mappings->rqsmr[n]); } else { PMD_INIT_LOG(DEBUG, "Write 0x%x to TX IXGBE stat mapping reg:%d", stat_mappings->tqsm[n], n); IXGBE_WRITE_REG(hw, IXGBE_TQSM(n), stat_mappings->tqsm[n]); } return 0; } static void ixgbe_restore_statistics_mapping(struct rte_eth_dev * dev) { struct ixgbe_stat_mapping_registers *stat_mappings = IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(dev->data->dev_private); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int i; /* write whatever was in stat mapping table to the NIC */ for (i = 0; i < IXGBE_NB_STAT_MAPPING_REGS; i++) { /* rx */ IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), stat_mappings->rqsmr[i]); /* tx */ IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), stat_mappings->tqsm[i]); } } static void ixgbe_dcb_init(struct ixgbe_hw *hw,struct ixgbe_dcb_config *dcb_config) { uint8_t i; struct ixgbe_dcb_tc_config *tc; uint8_t dcb_max_tc = IXGBE_DCB_MAX_TRAFFIC_CLASS; dcb_config->num_tcs.pg_tcs = dcb_max_tc; dcb_config->num_tcs.pfc_tcs = dcb_max_tc; for (i = 0; i < dcb_max_tc; i++) { tc = &dcb_config->tc_config[i]; tc->path[IXGBE_DCB_TX_CONFIG].bwg_id = i; tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = (uint8_t)(100/dcb_max_tc + (i & 1)); tc->path[IXGBE_DCB_RX_CONFIG].bwg_id = i; tc->path[IXGBE_DCB_RX_CONFIG].bwg_percent = (uint8_t)(100/dcb_max_tc + (i & 1)); tc->pfc = ixgbe_dcb_pfc_disabled; } /* Initialize default user to priority mapping, UPx->TC0 */ tc = &dcb_config->tc_config[0]; tc->path[IXGBE_DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF; tc->path[IXGBE_DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF; for (i = 0; i< IXGBE_DCB_MAX_BW_GROUP; i++) { dcb_config->bw_percentage[IXGBE_DCB_TX_CONFIG][i] = 100; dcb_config->bw_percentage[IXGBE_DCB_RX_CONFIG][i] = 100; } dcb_config->rx_pba_cfg = ixgbe_dcb_pba_equal; dcb_config->pfc_mode_enable = false; dcb_config->vt_mode = true; dcb_config->round_robin_enable = false; /* support all DCB capabilities in 82599 */ dcb_config->support.capabilities = 0xFF; /*we only support 4 Tcs for X540, X550 */ if (hw->mac.type == ixgbe_mac_X540 || hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X550EM_x) { dcb_config->num_tcs.pg_tcs = 4; dcb_config->num_tcs.pfc_tcs = 4; } } /* * Ensure that all locks are released before first NVM or PHY access */ static void ixgbe_swfw_lock_reset(struct ixgbe_hw *hw) { uint16_t mask; /* * Phy lock should not fail in this early stage. If this is the case, * it is due to an improper exit of the application. * So force the release of the faulty lock. Release of common lock * is done automatically by swfw_sync function. */ mask = IXGBE_GSSR_PHY0_SM << hw->bus.func; if (ixgbe_acquire_swfw_semaphore(hw, mask) < 0) { PMD_DRV_LOG(DEBUG, "SWFW phy%d lock released", hw->bus.func); } ixgbe_release_swfw_semaphore(hw, mask); /* * These ones are more tricky since they are common to all ports; but * swfw_sync retries last long enough (1s) to be almost sure that if * lock can not be taken it is due to an improper lock of the * semaphore. */ mask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_MAC_CSR_SM | IXGBE_GSSR_SW_MNG_SM; if (ixgbe_acquire_swfw_semaphore(hw, mask) < 0) { PMD_DRV_LOG(DEBUG, "SWFW common locks released"); } ixgbe_release_swfw_semaphore(hw, mask); } /* * This function is based on code in ixgbe_attach() in base/ixgbe.c. * It returns 0 on success. */ static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); struct ixgbe_hwstrip *hwstrip = IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(eth_dev->data->dev_private); struct ixgbe_dcb_config *dcb_config = IXGBE_DEV_PRIVATE_TO_DCB_CFG(eth_dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); uint32_t ctrl_ext; uint16_t csum; int diag, i; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &ixgbe_eth_dev_ops; eth_dev->rx_pkt_burst = &ixgbe_recv_pkts; eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts; /* * For secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX and TX function. */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ struct ixgbe_tx_queue *txq; /* TX queue function in primary, set by last queue initialized * Tx queue may not initialized by primary process */ if (eth_dev->data->tx_queues) { txq = eth_dev->data->tx_queues[eth_dev->data->nb_tx_queues-1]; ixgbe_set_tx_function(eth_dev, txq); } else { /* Use default TX function if we get here */ PMD_INIT_LOG(NOTICE, "No TX queues configured yet. " "Using default TX function."); } ixgbe_set_rx_function(eth_dev); return 0; } pci_dev = eth_dev->pci_dev; /* Vendor and Device ID need to be set before init of shared code */ hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; hw->allow_unsupported_sfp = 1; /* Initialize the shared code (base driver) */ #ifdef RTE_NIC_BYPASS diag = ixgbe_bypass_init_shared_code(hw); #else diag = ixgbe_init_shared_code(hw); #endif /* RTE_NIC_BYPASS */ if (diag != IXGBE_SUCCESS) { PMD_INIT_LOG(ERR, "Shared code init failed: %d", diag); return -EIO; } /* pick up the PCI bus settings for reporting later */ ixgbe_get_bus_info(hw); /* Unlock any pending hardware semaphore */ ixgbe_swfw_lock_reset(hw); /* Initialize DCB configuration*/ memset(dcb_config, 0, sizeof(struct ixgbe_dcb_config)); ixgbe_dcb_init(hw,dcb_config); /* Get Hardware Flow Control setting */ hw->fc.requested_mode = ixgbe_fc_full; hw->fc.current_mode = ixgbe_fc_full; hw->fc.pause_time = IXGBE_FC_PAUSE; for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { hw->fc.low_water[i] = IXGBE_FC_LO; hw->fc.high_water[i] = IXGBE_FC_HI; } hw->fc.send_xon = 1; /* Make sure we have a good EEPROM before we read from it */ diag = ixgbe_validate_eeprom_checksum(hw, &csum); if (diag != IXGBE_SUCCESS) { PMD_INIT_LOG(ERR, "The EEPROM checksum is not valid: %d", diag); return -EIO; } #ifdef RTE_NIC_BYPASS diag = ixgbe_bypass_init_hw(hw); #else diag = ixgbe_init_hw(hw); #endif /* RTE_NIC_BYPASS */ /* * Devices with copper phys will fail to initialise if ixgbe_init_hw() * is called too soon after the kernel driver unbinding/binding occurs. * The failure occurs in ixgbe_identify_phy_generic() for all devices, * but for non-copper devies, ixgbe_identify_sfp_module_generic() is * also called. See ixgbe_identify_phy_82599(). The reason for the * failure is not known, and only occuts when virtualisation features * are disabled in the bios. A delay of 100ms was found to be enough by * trial-and-error, and is doubled to be safe. */ if (diag && (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)) { rte_delay_ms(200); diag = ixgbe_init_hw(hw); } if (diag == IXGBE_ERR_EEPROM_VERSION) { PMD_INIT_LOG(ERR, "This device is a pre-production adapter/" "LOM. Please be aware there may be issues associated " "with your hardware."); PMD_INIT_LOG(ERR, "If you are experiencing problems " "please contact your Intel or hardware representative " "who provided you with this hardware."); } else if (diag == IXGBE_ERR_SFP_NOT_SUPPORTED) PMD_INIT_LOG(ERR, "Unsupported SFP+ Module"); if (diag) { PMD_INIT_LOG(ERR, "Hardware Initialization Failure: %d", diag); return -EIO; } /* Reset the hw statistics */ ixgbe_dev_stats_reset(eth_dev); /* disable interrupt */ ixgbe_disable_intr(hw); /* reset mappings for queue statistics hw counters*/ ixgbe_reset_qstat_mappings(hw); /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("ixgbe", ETHER_ADDR_LEN * hw->mac.num_rar_entries, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %u bytes needed to store " "MAC addresses", ETHER_ADDR_LEN * hw->mac.num_rar_entries); return -ENOMEM; } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *) hw->mac.perm_addr, ð_dev->data->mac_addrs[0]); /* Allocate memory for storing hash filter MAC addresses */ eth_dev->data->hash_mac_addrs = rte_zmalloc("ixgbe", ETHER_ADDR_LEN * IXGBE_VMDQ_NUM_UC_MAC, 0); if (eth_dev->data->hash_mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses", ETHER_ADDR_LEN * IXGBE_VMDQ_NUM_UC_MAC); return -ENOMEM; } /* initialize the vfta */ memset(shadow_vfta, 0, sizeof(*shadow_vfta)); /* initialize the hw strip bitmap*/ memset(hwstrip, 0, sizeof(*hwstrip)); /* initialize PF if max_vfs not zero */ ixgbe_pf_host_init(eth_dev); ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); /* let hardware know driver is loaded */ ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD; /* Set PF Reset Done bit so PF/VF Mail Ops can work */ ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present) PMD_INIT_LOG(DEBUG, "MAC: %d, PHY: %d, SFP+: %d", (int) hw->mac.type, (int) hw->phy.type, (int) hw->phy.sfp_type); else PMD_INIT_LOG(DEBUG, "MAC: %d, PHY: %d", (int) hw->mac.type, (int) hw->phy.type); PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); /* enable support intr */ ixgbe_enable_intr(eth_dev); /* initialize 5tuple filter list */ TAILQ_INIT(&filter_info->fivetuple_list); memset(filter_info->fivetuple_mask, 0, sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); return 0; } static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct ixgbe_hw *hw; PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); pci_dev = eth_dev->pci_dev; if (hw->adapter_stopped == 0) ixgbe_dev_close(eth_dev); eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; /* Unlock any pending hardware semaphore */ ixgbe_swfw_lock_reset(hw); /* disable uio intr before callback unregister */ rte_intr_disable(&(pci_dev->intr_handle)); rte_intr_callback_unregister(&(pci_dev->intr_handle), ixgbe_dev_interrupt_handler, (void *)eth_dev); /* uninitialize PF if max_vfs not zero */ ixgbe_pf_host_uninit(eth_dev); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; rte_free(eth_dev->data->hash_mac_addrs); eth_dev->data->hash_mac_addrs = NULL; return 0; } /* * Negotiate mailbox API version with the PF. * After reset API version is always set to the basic one (ixgbe_mbox_api_10). * Then we try to negotiate starting with the most recent one. * If all negotiation attempts fail, then we will proceed with * the default one (ixgbe_mbox_api_10). */ static void ixgbevf_negotiate_api(struct ixgbe_hw *hw) { int32_t i; /* start with highest supported, proceed down */ static const enum ixgbe_pfvf_api_rev sup_ver[] = { ixgbe_mbox_api_11, ixgbe_mbox_api_10, }; for (i = 0; i != RTE_DIM(sup_ver) && ixgbevf_negotiate_api_version(hw, sup_ver[i]) != 0; i++) ; } static void generate_random_mac_addr(struct ether_addr *mac_addr) { uint64_t random; /* Set Organizationally Unique Identifier (OUI) prefix. */ mac_addr->addr_bytes[0] = 0x00; mac_addr->addr_bytes[1] = 0x09; mac_addr->addr_bytes[2] = 0xC0; /* Force indication of locally assigned MAC address. */ mac_addr->addr_bytes[0] |= ETHER_LOCAL_ADMIN_ADDR; /* Generate the last 3 bytes of the MAC address with a random number. */ random = rte_rand(); memcpy(&mac_addr->addr_bytes[3], &random, 3); } /* * Virtual Function device init */ static int eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev) { int diag; uint32_t tc, tcs; struct rte_pci_device *pci_dev; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); struct ixgbe_hwstrip *hwstrip = IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(eth_dev->data->dev_private); struct ether_addr *perm_addr = (struct ether_addr *) hw->mac.perm_addr; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &ixgbevf_eth_dev_ops; eth_dev->rx_pkt_burst = &ixgbe_recv_pkts; eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts; /* for secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different * RX function */ if (rte_eal_process_type() != RTE_PROC_PRIMARY){ if (eth_dev->data->scattered_rx) eth_dev->rx_pkt_burst = ixgbe_recv_pkts_lro_single_alloc; return 0; } pci_dev = eth_dev->pci_dev; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; /* initialize the vfta */ memset(shadow_vfta, 0, sizeof(*shadow_vfta)); /* initialize the hw strip bitmap*/ memset(hwstrip, 0, sizeof(*hwstrip)); /* Initialize the shared code (base driver) */ diag = ixgbe_init_shared_code(hw); if (diag != IXGBE_SUCCESS) { PMD_INIT_LOG(ERR, "Shared code init failed for ixgbevf: %d", diag); return -EIO; } /* init_mailbox_params */ hw->mbx.ops.init_params(hw); /* Reset the hw statistics */ ixgbevf_dev_stats_reset(eth_dev); /* Disable the interrupts for VF */ ixgbevf_intr_disable(hw); hw->mac.num_rar_entries = 128; /* The MAX of the underlying PF */ diag = hw->mac.ops.reset_hw(hw); /* * The VF reset operation returns the IXGBE_ERR_INVALID_MAC_ADDR when * the underlying PF driver has not assigned a MAC address to the VF. * In this case, assign a random MAC address. */ if ((diag != IXGBE_SUCCESS) && (diag != IXGBE_ERR_INVALID_MAC_ADDR)) { PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", diag); return (diag); } /* negotiate mailbox API version to use with the PF. */ ixgbevf_negotiate_api(hw); /* Get Rx/Tx queue count via mailbox, which is ready after reset_hw */ ixgbevf_get_queues(hw, &tcs, &tc); /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("ixgbevf", ETHER_ADDR_LEN * hw->mac.num_rar_entries, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %u bytes needed to store " "MAC addresses", ETHER_ADDR_LEN * hw->mac.num_rar_entries); return -ENOMEM; } /* Generate a random MAC address, if none was assigned by PF. */ if (is_zero_ether_addr(perm_addr)) { generate_random_mac_addr(perm_addr); diag = ixgbe_set_rar_vf(hw, 1, perm_addr->addr_bytes, 0, 1); if (diag) { rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; return diag; } PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF"); PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address " "%02x:%02x:%02x:%02x:%02x:%02x", perm_addr->addr_bytes[0], perm_addr->addr_bytes[1], perm_addr->addr_bytes[2], perm_addr->addr_bytes[3], perm_addr->addr_bytes[4], perm_addr->addr_bytes[5]); } /* Copy the permanent MAC address */ ether_addr_copy(perm_addr, ð_dev->data->mac_addrs[0]); /* reset the hardware with the new settings */ diag = hw->mac.ops.start_hw(hw); switch (diag) { case 0: break; default: PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", diag); return (-EIO); } PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id, "ixgbe_mac_82599_vf"); return 0; } /* Virtual Function device uninit */ static int eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev) { struct ixgbe_hw *hw; unsigned i; PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return -EPERM; hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); if (hw->adapter_stopped == 0) ixgbevf_dev_close(eth_dev); eth_dev->dev_ops = NULL; eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; /* Disable the interrupts for VF */ ixgbevf_intr_disable(hw); for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { ixgbe_dev_rx_queue_release(eth_dev->data->rx_queues[i]); eth_dev->data->rx_queues[i] = NULL; } eth_dev->data->nb_rx_queues = 0; for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { ixgbe_dev_tx_queue_release(eth_dev->data->tx_queues[i]); eth_dev->data->tx_queues[i] = NULL; } eth_dev->data->nb_tx_queues = 0; rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; return 0; } static struct eth_driver rte_ixgbe_pmd = { .pci_drv = { .name = "rte_ixgbe_pmd", .id_table = pci_id_ixgbe_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_ixgbe_dev_init, .eth_dev_uninit = eth_ixgbe_dev_uninit, .dev_private_size = sizeof(struct ixgbe_adapter), }; /* * virtual function driver struct */ static struct eth_driver rte_ixgbevf_pmd = { .pci_drv = { .name = "rte_ixgbevf_pmd", .id_table = pci_id_ixgbevf_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_ixgbevf_dev_init, .eth_dev_uninit = eth_ixgbevf_dev_uninit, .dev_private_size = sizeof(struct ixgbe_adapter), }; /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of PCI IXGBE devices. */ static int rte_ixgbe_pmd_init(const char *name __rte_unused, const char *params __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_ixgbe_pmd); return 0; } /* * VF Driver initialization routine. * Invoked one at EAL init time. * Register itself as the [Virtual Poll Mode] Driver of PCI niantic devices. */ static int rte_ixgbevf_pmd_init(const char *name __rte_unused, const char *param __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_ixgbevf_pmd); return (0); } static int ixgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vfta; uint32_t vid_idx; uint32_t vid_bit; vid_idx = (uint32_t) ((vlan_id >> 5) & 0x7F); vid_bit = (uint32_t) (1 << (vlan_id & 0x1F)); vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(vid_idx)); if (on) vfta |= vid_bit; else vfta &= ~vid_bit; IXGBE_WRITE_REG(hw, IXGBE_VFTA(vid_idx), vfta); /* update local VFTA copy */ shadow_vfta->vfta[vid_idx] = vfta; return 0; } static void ixgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) { if (on) ixgbe_vlan_hw_strip_enable(dev, queue); else ixgbe_vlan_hw_strip_disable(dev, queue); } static void ixgbe_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Only the high 16-bits is valid */ IXGBE_WRITE_REG(hw, IXGBE_EXVET, tpid << 16); } void ixgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t vlnctrl; PMD_INIT_FUNC_TRACE(); /* Filter Table Disable */ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlnctrl &= ~IXGBE_VLNCTRL_VFE; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); } void ixgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vlnctrl; uint16_t i; PMD_INIT_FUNC_TRACE(); /* Filter Table Enable */ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlnctrl &= ~IXGBE_VLNCTRL_CFIEN; vlnctrl |= IXGBE_VLNCTRL_VFE; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); /* write whatever is in local vfta copy */ for (i = 0; i < IXGBE_VFTA_SIZE; i++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), shadow_vfta->vfta[i]); } static void ixgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on) { struct ixgbe_hwstrip *hwstrip = IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(dev->data->dev_private); if(queue >= IXGBE_MAX_RX_QUEUE_NUM) return; if (on) IXGBE_SET_HWSTRIP(hwstrip, queue); else IXGBE_CLEAR_HWSTRIP(hwstrip, queue); } static void ixgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; PMD_INIT_FUNC_TRACE(); if (hw->mac.type == ixgbe_mac_82598EB) { /* No queue level support */ PMD_INIT_LOG(NOTICE, "82598EB not support queue level hw strip"); return; } else { /* Other 10G NIC, the VLAN strip can be setup per queue in RXDCTL */ ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(queue)); ctrl &= ~IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(queue), ctrl); } /* record those setting for HW strip per queue */ ixgbe_vlan_hw_strip_bitmap_set(dev, queue, 0); } static void ixgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; PMD_INIT_FUNC_TRACE(); if (hw->mac.type == ixgbe_mac_82598EB) { /* No queue level supported */ PMD_INIT_LOG(NOTICE, "82598EB not support queue level hw strip"); return; } else { /* Other 10G NIC, the VLAN strip can be setup per queue in RXDCTL */ ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(queue)); ctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(queue), ctrl); } /* record those setting for HW strip per queue */ ixgbe_vlan_hw_strip_bitmap_set(dev, queue, 1); } void ixgbe_vlan_hw_strip_disable_all(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; uint16_t i; PMD_INIT_FUNC_TRACE(); if (hw->mac.type == ixgbe_mac_82598EB) { ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); ctrl &= ~IXGBE_VLNCTRL_VME; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); } else { /* Other 10G NIC, the VLAN strip can be setup per queue in RXDCTL */ for (i = 0; i < dev->data->nb_rx_queues; i++) { ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); ctrl &= ~IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), ctrl); /* record those setting for HW strip per queue */ ixgbe_vlan_hw_strip_bitmap_set(dev, i, 0); } } } void ixgbe_vlan_hw_strip_enable_all(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; uint16_t i; PMD_INIT_FUNC_TRACE(); if (hw->mac.type == ixgbe_mac_82598EB) { ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); ctrl |= IXGBE_VLNCTRL_VME; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl); } else { /* Other 10G NIC, the VLAN strip can be setup per queue in RXDCTL */ for (i = 0; i < dev->data->nb_rx_queues; i++) { ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); ctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), ctrl); /* record those setting for HW strip per queue */ ixgbe_vlan_hw_strip_bitmap_set(dev, i, 1); } } } static void ixgbe_vlan_hw_extend_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; PMD_INIT_FUNC_TRACE(); /* DMATXCTRL: Geric Double VLAN Disable */ ctrl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); ctrl &= ~IXGBE_DMATXCTL_GDV; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, ctrl); /* CTRL_EXT: Global Double VLAN Disable */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl &= ~IXGBE_EXTENDED_VLAN; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl); } static void ixgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; PMD_INIT_FUNC_TRACE(); /* DMATXCTRL: Geric Double VLAN Enable */ ctrl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); ctrl |= IXGBE_DMATXCTL_GDV; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, ctrl); /* CTRL_EXT: Global Double VLAN Enable */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl |= IXGBE_EXTENDED_VLAN; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl); /* * VET EXT field in the EXVET register = 0x8100 by default * So no need to change. Same to VT field of DMATXCTL register */ } static void ixgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask) { if(mask & ETH_VLAN_STRIP_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_strip) ixgbe_vlan_hw_strip_enable_all(dev); else ixgbe_vlan_hw_strip_disable_all(dev); } if(mask & ETH_VLAN_FILTER_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_filter) ixgbe_vlan_hw_filter_enable(dev); else ixgbe_vlan_hw_filter_disable(dev); } if(mask & ETH_VLAN_EXTEND_MASK){ if (dev->data->dev_conf.rxmode.hw_vlan_extend) ixgbe_vlan_hw_extend_enable(dev); else ixgbe_vlan_hw_extend_disable(dev); } } static void ixgbe_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* VLNCTRL: enable vlan filtering and allow all vlan tags through */ uint32_t vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); } static int ixgbe_dev_configure(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; PMD_INIT_FUNC_TRACE(); /* set flag to update link status after init */ intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; /* * Initialize to TRUE. If any of Rx queues doesn't meet the bulk * allocation or vector Rx preconditions we will reset it. */ adapter->rx_bulk_alloc_allowed = true; adapter->rx_vec_allowed = true; return 0; } /* * Configure device link speed and setup link. * It returns 0 on success. */ static int ixgbe_dev_start(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; #ifdef RTE_NEXT_ABI uint32_t intr_vector = 0; #endif int err, link_up = 0, negotiate = 0; uint32_t speed = 0; int mask = 0; int status; uint16_t vf, idx; PMD_INIT_FUNC_TRACE(); /* IXGBE devices don't support half duplex */ if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) && (dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) { PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu", dev->data->dev_conf.link_duplex, dev->data->port_id); return -EINVAL; } /* stop adapter */ hw->adapter_stopped = 0; ixgbe_stop_adapter(hw); /* reinitialize adapter * this calls reset and start */ status = ixgbe_pf_reset_hw(hw); if (status != 0) return -1; hw->mac.ops.start_hw(hw); hw->mac.get_link_status = true; /* configure PF module if SRIOV enabled */ ixgbe_pf_host_configure(dev); #ifdef RTE_NEXT_ABI /* check and configure queue intr-vector mapping */ if (dev->data->dev_conf.intr_conf.rxq != 0) intr_vector = dev->data->nb_rx_queues; if (rte_intr_efd_enable(intr_handle, intr_vector)) return -1; if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) { intr_handle->intr_vec = rte_zmalloc("intr_vec", dev->data->nb_rx_queues * sizeof(int), 0); if (intr_handle->intr_vec == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" " intr_vec\n", dev->data->nb_rx_queues); return -ENOMEM; } } #endif /* confiugre msix for sleep until rx interrupt */ ixgbe_configure_msix(dev); /* initialize transmission unit */ ixgbe_dev_tx_init(dev); /* This can fail when allocating mbufs for descriptor rings */ err = ixgbe_dev_rx_init(dev); if (err) { PMD_INIT_LOG(ERR, "Unable to initialize RX hardware"); goto error; } err = ixgbe_dev_rxtx_start(dev); if (err < 0) { PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); goto error; } /* Skip link setup if loopback mode is enabled for 82599. */ if (hw->mac.type == ixgbe_mac_82599EB && dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) goto skip_link_setup; if (ixgbe_is_sfp(hw) && hw->phy.multispeed_fiber) { err = hw->mac.ops.setup_sfp(hw); if (err) goto error; } if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) { /* Turn on the copper */ ixgbe_set_phy_power(hw, true); } else { /* Turn on the laser */ ixgbe_enable_tx_laser(hw); } err = ixgbe_check_link(hw, &speed, &link_up, 0); if (err) goto error; dev->data->dev_link.link_status = link_up; err = ixgbe_get_link_capabilities(hw, &speed, &negotiate); if (err) goto error; switch(dev->data->dev_conf.link_speed) { case ETH_LINK_SPEED_AUTONEG: speed = (hw->mac.type != ixgbe_mac_82598EB) ? IXGBE_LINK_SPEED_82599_AUTONEG : IXGBE_LINK_SPEED_82598_AUTONEG; break; case ETH_LINK_SPEED_100: /* * Invalid for 82598 but error will be detected by * ixgbe_setup_link() */ speed = IXGBE_LINK_SPEED_100_FULL; break; case ETH_LINK_SPEED_1000: speed = IXGBE_LINK_SPEED_1GB_FULL; break; case ETH_LINK_SPEED_10000: speed = IXGBE_LINK_SPEED_10GB_FULL; break; default: PMD_INIT_LOG(ERR, "Invalid link_speed (%hu) for port %hhu", dev->data->dev_conf.link_speed, dev->data->port_id); goto error; } err = ixgbe_setup_link(hw, speed, link_up); if (err) goto error; skip_link_setup: /* check if lsc interrupt is enabled */ if (dev->data->dev_conf.intr_conf.lsc != 0) { if (rte_intr_allow_others(intr_handle)) { rte_intr_callback_register(intr_handle, ixgbe_dev_interrupt_handler, (void *)dev); ixgbe_dev_lsc_interrupt_setup(dev); } else PMD_INIT_LOG(INFO, "lsc won't enable because of" " no intr multiplex\n"); } #ifdef RTE_NEXT_ABI /* check if rxq interrupt is enabled */ if (dev->data->dev_conf.intr_conf.rxq != 0) ixgbe_dev_rxq_interrupt_setup(dev); #endif /* enable uio/vfio intr/eventfd mapping */ rte_intr_enable(intr_handle); /* resume enabled intr since hw reset */ ixgbe_enable_intr(dev); mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \ ETH_VLAN_EXTEND_MASK; ixgbe_vlan_offload_set(dev, mask); if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_VMDQ_ONLY) { /* Enable vlan filtering for VMDq */ ixgbe_vmdq_vlan_hw_filter_enable(dev); } /* Configure DCB hw */ ixgbe_configure_dcb(dev); if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_NONE) { err = ixgbe_fdir_configure(dev); if (err) goto error; } /* Restore vf rate limit */ if (vfinfo != NULL) { for (vf = 0; vf < dev->pci_dev->max_vfs; vf++) for (idx = 0; idx < IXGBE_MAX_QUEUE_NUM_PER_VF; idx++) if (vfinfo[vf].tx_rate[idx] != 0) ixgbe_set_vf_rate_limit(dev, vf, vfinfo[vf].tx_rate[idx], 1 << idx); } ixgbe_restore_statistics_mapping(dev); return (0); error: PMD_INIT_LOG(ERR, "failure in ixgbe_dev_start(): %d", err); ixgbe_dev_clear_queues(dev); return -EIO; } /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ static void ixgbe_dev_stop(struct rte_eth_dev *dev) { struct rte_eth_link link; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct ixgbe_5tuple_filter *p_5tuple, *p_5tuple_next; struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; int vf; PMD_INIT_FUNC_TRACE(); /* disable interrupts */ ixgbe_disable_intr(hw); /* disable intr eventfd mapping */ rte_intr_disable(intr_handle); /* reset the NIC */ ixgbe_pf_reset_hw(hw); hw->adapter_stopped = 0; /* stop adapter */ ixgbe_stop_adapter(hw); for (vf = 0; vfinfo != NULL && vf < dev->pci_dev->max_vfs; vf++) vfinfo[vf].clear_to_send = false; if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) { /* Turn off the copper */ ixgbe_set_phy_power(hw, false); } else { /* Turn off the laser */ ixgbe_disable_tx_laser(hw); } ixgbe_dev_clear_queues(dev); /* Clear stored conf */ dev->data->scattered_rx = 0; dev->data->lro = 0; /* Clear recorded link status */ memset(&link, 0, sizeof(link)); rte_ixgbe_dev_atomic_write_link_status(dev, &link); /* Remove all ntuple filters of the device */ for (p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list); p_5tuple != NULL; p_5tuple = p_5tuple_next) { p_5tuple_next = TAILQ_NEXT(p_5tuple, entries); TAILQ_REMOVE(&filter_info->fivetuple_list, p_5tuple, entries); rte_free(p_5tuple); } memset(filter_info->fivetuple_mask, 0, sizeof(uint32_t) * IXGBE_5TUPLE_ARRAY_SIZE); #ifdef RTE_NEXT_ABI /* Clean datapath event and queue/vec mapping */ rte_intr_efd_disable(intr_handle); if (intr_handle->intr_vec != NULL) { rte_free(intr_handle->intr_vec); intr_handle->intr_vec = NULL; } #endif } /* * Set device link up: enable tx. */ static int ixgbe_dev_set_link_up(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (hw->mac.type == ixgbe_mac_82599EB) { #ifdef RTE_NIC_BYPASS if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { /* Not suported in bypass mode */ PMD_INIT_LOG(ERR, "Set link up is not supported " "by device id 0x%x", hw->device_id); return -ENOTSUP; } #endif } if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) { /* Turn on the copper */ ixgbe_set_phy_power(hw, true); } else { /* Turn on the laser */ ixgbe_enable_tx_laser(hw); } return 0; } /* * Set device link down: disable tx. */ static int ixgbe_dev_set_link_down(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (hw->mac.type == ixgbe_mac_82599EB) { #ifdef RTE_NIC_BYPASS if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) { /* Not suported in bypass mode */ PMD_INIT_LOG(ERR, "Set link down is not supported " "by device id 0x%x", hw->device_id); return -ENOTSUP; } #endif } if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) { /* Turn off the copper */ ixgbe_set_phy_power(hw, false); } else { /* Turn off the laser */ ixgbe_disable_tx_laser(hw); } return 0; } /* * Reest and stop device. */ static void ixgbe_dev_close(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); ixgbe_pf_reset_hw(hw); ixgbe_dev_stop(dev); hw->adapter_stopped = 1; ixgbe_dev_free_queues(dev); ixgbe_disable_pcie_master(hw); /* reprogram the RAR[0] in case user changed it. */ ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } static void ixgbe_read_stats_registers(struct ixgbe_hw *hw, struct ixgbe_hw_stats *hw_stats, uint64_t *total_missed_rx, uint64_t *total_qbrc, uint64_t *total_qprc, uint64_t *total_qprdc) { uint32_t bprc, lxon, lxoff, total; unsigned i; hw_stats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); hw_stats->illerrc += IXGBE_READ_REG(hw, IXGBE_ILLERRC); hw_stats->errbc += IXGBE_READ_REG(hw, IXGBE_ERRBC); hw_stats->mspdc += IXGBE_READ_REG(hw, IXGBE_MSPDC); for (i = 0; i < 8; i++) { uint32_t mp; mp = IXGBE_READ_REG(hw, IXGBE_MPC(i)); /* global total per queue */ hw_stats->mpc[i] += mp; /* Running comprehensive total for stats display */ *total_missed_rx += hw_stats->mpc[i]; if (hw->mac.type == ixgbe_mac_82598EB) hw_stats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); hw_stats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); hw_stats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); hw_stats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); hw_stats->pxoffrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); hw_stats->pxon2offc[i] += IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); } for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) { hw_stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); hw_stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); hw_stats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); hw_stats->qbrc[i] += ((uint64_t)IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)) << 32); hw_stats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); hw_stats->qbtc[i] += ((uint64_t)IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)) << 32); *total_qprdc += hw_stats->qprdc[i] += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); *total_qprc += hw_stats->qprc[i]; *total_qbrc += hw_stats->qbrc[i]; } hw_stats->mlfc += IXGBE_READ_REG(hw, IXGBE_MLFC); hw_stats->mrfc += IXGBE_READ_REG(hw, IXGBE_MRFC); hw_stats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); /* Note that gprc counts missed packets */ hw_stats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); if (hw->mac.type != ixgbe_mac_82598EB) { hw_stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL); hw_stats->gorc += ((u64)IXGBE_READ_REG(hw, IXGBE_GORCH) << 32); hw_stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL); hw_stats->gotc += ((u64)IXGBE_READ_REG(hw, IXGBE_GOTCH) << 32); hw_stats->tor += IXGBE_READ_REG(hw, IXGBE_TORL); hw_stats->tor += ((u64)IXGBE_READ_REG(hw, IXGBE_TORH) << 32); hw_stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); hw_stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); } else { hw_stats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); hw_stats->lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); /* 82598 only has a counter in the high register */ hw_stats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); hw_stats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); hw_stats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); } /* * Workaround: mprc hardware is incorrectly counting * broadcasts, so for now we subtract those. */ bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); hw_stats->bprc += bprc; hw_stats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); if (hw->mac.type == ixgbe_mac_82598EB) hw_stats->mprc -= bprc; hw_stats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); hw_stats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); hw_stats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); hw_stats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); hw_stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); hw_stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); hw_stats->lxontxc += lxon; lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); hw_stats->lxofftxc += lxoff; total = lxon + lxoff; hw_stats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); hw_stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); hw_stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); hw_stats->gptc -= total; hw_stats->mptc -= total; hw_stats->ptc64 -= total; hw_stats->gotc -= total * ETHER_MIN_LEN; hw_stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); hw_stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); hw_stats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); hw_stats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); hw_stats->mngprc += IXGBE_READ_REG(hw, IXGBE_MNGPRC); hw_stats->mngpdc += IXGBE_READ_REG(hw, IXGBE_MNGPDC); hw_stats->mngptc += IXGBE_READ_REG(hw, IXGBE_MNGPTC); hw_stats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); hw_stats->tpt += IXGBE_READ_REG(hw, IXGBE_TPT); hw_stats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); hw_stats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); hw_stats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); hw_stats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); hw_stats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); hw_stats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); hw_stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC); hw_stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); hw_stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); /* Only read FCOE on 82599 */ if (hw->mac.type != ixgbe_mac_82598EB) { hw_stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); hw_stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); hw_stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); hw_stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); hw_stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); } /* Flow Director Stats registers */ hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS); } /* * This function is based on ixgbe_update_stats_counters() in ixgbe/ixgbe.c */ static void ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_stats *hw_stats = IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc; unsigned i; total_missed_rx = 0; total_qbrc = 0; total_qprc = 0; total_qprdc = 0; ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc, &total_qprc, &total_qprdc); if (stats == NULL) return; /* Fill out the rte_eth_stats statistics structure */ stats->ipackets = total_qprc; stats->ibytes = total_qbrc; stats->opackets = hw_stats->gptc; stats->obytes = hw_stats->gotc; for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) { stats->q_ipackets[i] = hw_stats->qprc[i]; stats->q_opackets[i] = hw_stats->qptc[i]; stats->q_ibytes[i] = hw_stats->qbrc[i]; stats->q_obytes[i] = hw_stats->qbtc[i]; stats->q_errors[i] = hw_stats->qprdc[i]; } /* Rx Errors */ stats->ierrors = hw_stats->crcerrs + hw_stats->rlec + hw_stats->ruc + hw_stats->roc + total_missed_rx + hw_stats->illerrc + hw_stats->errbc + hw_stats->xec + hw_stats->mlfc + hw_stats->mrfc + hw_stats->rfc + hw_stats->rjc + hw_stats->fccrc + hw_stats->fclast; /* Tx Errors */ stats->oerrors = 0; } static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev) { struct ixgbe_hw_stats *stats = IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* HW registers are cleared on read */ ixgbe_dev_stats_get(dev, NULL); /* Reset software totals */ memset(stats, 0, sizeof(*stats)); } static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats, unsigned n) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_stats *hw_stats = IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc; unsigned i, count = IXGBE_NB_XSTATS; if (n < count) return count; total_missed_rx = 0; total_qbrc = 0; total_qprc = 0; total_qprdc = 0; ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc, &total_qprc, &total_qprdc); /* If this is a reset xstats is NULL, and we have cleared the * registers by reading them. */ if (!xstats) return 0; /* Extended stats */ for (i = 0; i < IXGBE_NB_XSTATS; i++) { snprintf(xstats[i].name, sizeof(xstats[i].name), "%s", rte_ixgbe_stats_strings[i].name); xstats[i].value = *(uint64_t *)(((char *)hw_stats) + rte_ixgbe_stats_strings[i].offset); } return count; } static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev) { struct ixgbe_hw_stats *stats = IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* HW registers are cleared on read */ ixgbe_dev_xstats_get(dev, NULL, IXGBE_NB_XSTATS); /* Reset software totals */ memset(stats, 0, sizeof(*stats)); } static void ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*) IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* Good Rx packet, include VF loopback */ UPDATE_VF_STAT(IXGBE_VFGPRC, hw_stats->last_vfgprc, hw_stats->vfgprc); /* Good Rx octets, include VF loopback */ UPDATE_VF_STAT_36BIT(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB, hw_stats->last_vfgorc, hw_stats->vfgorc); /* Good Tx packet, include VF loopback */ UPDATE_VF_STAT(IXGBE_VFGPTC, hw_stats->last_vfgptc, hw_stats->vfgptc); /* Good Tx octets, include VF loopback */ UPDATE_VF_STAT_36BIT(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB, hw_stats->last_vfgotc, hw_stats->vfgotc); /* Rx Multicst Packet */ UPDATE_VF_STAT(IXGBE_VFMPRC, hw_stats->last_vfmprc, hw_stats->vfmprc); if (stats == NULL) return; stats->ipackets = hw_stats->vfgprc; stats->ibytes = hw_stats->vfgorc; stats->opackets = hw_stats->vfgptc; stats->obytes = hw_stats->vfgotc; stats->imcasts = hw_stats->vfmprc; /* stats->imcasts should be removed as imcasts is deprecated */ } static void ixgbevf_dev_stats_reset(struct rte_eth_dev *dev) { struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*) IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private); /* Sync HW register to the last stats */ ixgbevf_dev_stats_get(dev, NULL); /* reset HW current stats*/ hw_stats->vfgprc = 0; hw_stats->vfgorc = 0; hw_stats->vfgptc = 0; hw_stats->vfgotc = 0; hw_stats->vfmprc = 0; } static void ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues; dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues; dev_info->min_rx_bufsize = 1024; /* cf BSIZEPACKET in SRRCTL register */ dev_info->max_rx_pktlen = 15872; /* includes CRC, cf MAXFRS register */ dev_info->max_mac_addrs = hw->mac.num_rar_entries; dev_info->max_hash_mac_addrs = IXGBE_VMDQ_NUM_UC_MAC; dev_info->max_vfs = dev->pci_dev->max_vfs; if (hw->mac.type == ixgbe_mac_82598EB) dev_info->max_vmdq_pools = ETH_16_POOLS; else dev_info->max_vmdq_pools = ETH_64_POOLS; dev_info->vmdq_queue_num = dev_info->max_rx_queues; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; /* * RSC is only supported by 82599 and x540 PF devices in a non-SR-IOV * mode. */ if ((hw->mac.type == ixgbe_mac_82599EB || hw->mac.type == ixgbe_mac_X540) && !RTE_ETH_DEV_SRIOV(dev).active) dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TCP_LRO; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM | DEV_TX_OFFLOAD_TCP_TSO; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = IXGBE_DEFAULT_RX_PTHRESH, .hthresh = IXGBE_DEFAULT_RX_HTHRESH, .wthresh = IXGBE_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = IXGBE_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = IXGBE_DEFAULT_TX_PTHRESH, .hthresh = IXGBE_DEFAULT_TX_HTHRESH, .wthresh = IXGBE_DEFAULT_TX_WTHRESH, }, .tx_free_thresh = IXGBE_DEFAULT_TX_FREE_THRESH, .tx_rs_thresh = IXGBE_DEFAULT_TX_RSBIT_THRESH, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; /* * According to 82599 and x540 specifications RS bit *must* be set on the * last descriptor of *every* packet. Therefore we will not allow the * tx_rs_thresh above 1 for all NICs newer than 82598. */ if (hw->mac.type > ixgbe_mac_82598EB) dev_info->default_txconf.tx_rs_thresh = 1; dev_info->hash_key_size = IXGBE_HKEY_MAX_INDEX * sizeof(uint32_t); dev_info->reta_size = ETH_RSS_RETA_SIZE_128; dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL; } static void ixgbevf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues; dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues; dev_info->min_rx_bufsize = 1024; /* cf BSIZEPACKET in SRRCTL reg */ dev_info->max_rx_pktlen = 15872; /* includes CRC, cf MAXFRS reg */ dev_info->max_mac_addrs = hw->mac.num_rar_entries; dev_info->max_hash_mac_addrs = IXGBE_VMDQ_NUM_UC_MAC; dev_info->max_vfs = dev->pci_dev->max_vfs; if (hw->mac.type == ixgbe_mac_82598EB) dev_info->max_vmdq_pools = ETH_16_POOLS; else dev_info->max_vmdq_pools = ETH_64_POOLS; dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM; dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { .pthresh = IXGBE_DEFAULT_RX_PTHRESH, .hthresh = IXGBE_DEFAULT_RX_HTHRESH, .wthresh = IXGBE_DEFAULT_RX_WTHRESH, }, .rx_free_thresh = IXGBE_DEFAULT_RX_FREE_THRESH, .rx_drop_en = 0, }; dev_info->default_txconf = (struct rte_eth_txconf) { .tx_thresh = { .pthresh = IXGBE_DEFAULT_TX_PTHRESH, .hthresh = IXGBE_DEFAULT_TX_HTHRESH, .wthresh = IXGBE_DEFAULT_TX_WTHRESH, }, .tx_free_thresh = IXGBE_DEFAULT_TX_FREE_THRESH, /* * According to 82599 and x540 specifications RS bit *must* be * set on the last descriptor of *every* packet. Therefore we * will not allow the tx_rs_thresh above 1 for all NICs newer * than 82598. Since VFs are available only on devices starting * from 82599, tx_rs_thresh should be set to 1 for ALL VF * devices. */ .tx_rs_thresh = 1, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; } /* return 0 means link status changed, -1 means not changed */ static int ixgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_link link, old; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; int link_up; int diag; link.link_status = 0; link.link_speed = 0; link.link_duplex = 0; memset(&old, 0, sizeof(old)); rte_ixgbe_dev_atomic_read_link_status(dev, &old); hw->mac.get_link_status = true; /* check if it needs to wait to complete, if lsc interrupt is enabled */ if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0) diag = ixgbe_check_link(hw, &link_speed, &link_up, 0); else diag = ixgbe_check_link(hw, &link_speed, &link_up, 1); if (diag != 0) { link.link_speed = ETH_LINK_SPEED_100; link.link_duplex = ETH_LINK_HALF_DUPLEX; rte_ixgbe_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) return -1; return 0; } if (link_up == 0) { rte_ixgbe_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) return -1; return 0; } link.link_status = 1; link.link_duplex = ETH_LINK_FULL_DUPLEX; switch (link_speed) { default: case IXGBE_LINK_SPEED_UNKNOWN: link.link_duplex = ETH_LINK_HALF_DUPLEX; link.link_speed = ETH_LINK_SPEED_100; break; case IXGBE_LINK_SPEED_100_FULL: link.link_speed = ETH_LINK_SPEED_100; break; case IXGBE_LINK_SPEED_1GB_FULL: link.link_speed = ETH_LINK_SPEED_1000; break; case IXGBE_LINK_SPEED_10GB_FULL: link.link_speed = ETH_LINK_SPEED_10000; break; } rte_ixgbe_dev_atomic_write_link_status(dev, &link); if (link.link_status == old.link_status) return -1; return 0; } static void ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fctrl; fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } static void ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fctrl; fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl &= (~IXGBE_FCTRL_UPE); if (dev->data->all_multicast == 1) fctrl |= IXGBE_FCTRL_MPE; else fctrl &= (~IXGBE_FCTRL_MPE); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } static void ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fctrl; fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl |= IXGBE_FCTRL_MPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } static void ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fctrl; if (dev->data->promiscuous == 1) return; /* must remain in all_multicast mode */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl &= (~IXGBE_FCTRL_MPE); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } /** * It clears the interrupt causes and enables the interrupt. * It will be called once only during nic initialized. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); ixgbe_dev_link_status_print(dev); intr->mask |= IXGBE_EICR_LSC; return 0; } /** * It clears the interrupt causes and enables the interrupt. * It will be called once only during nic initialized. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ #ifdef RTE_NEXT_ABI static int ixgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); intr->mask |= IXGBE_EICR_RTX_QUEUE; return 0; } #endif /* * It reads ICR and sets flag (IXGBE_EICR_LSC) for the link_update. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev) { uint32_t eicr; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); /* clear all cause mask */ ixgbe_disable_intr(hw); /* read-on-clear nic registers here */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); PMD_DRV_LOG(DEBUG, "eicr %x", eicr); intr->flags = 0; /* set flag for async link update */ if (eicr & IXGBE_EICR_LSC) intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; if (eicr & IXGBE_EICR_MAILBOX) intr->flags |= IXGBE_FLAG_MAILBOX; return 0; } static int ixgbevf_dev_interrupt_get_status(struct rte_eth_dev *dev) { uint32_t eicr; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); /* clear all cause mask */ ixgbevf_intr_disable(hw); /* read-on-clear nic registers here */ eicr = IXGBE_READ_REG(hw, IXGBE_VTEICR); PMD_DRV_LOG(INFO, "eicr %x", eicr); intr->flags = 0; /* set flag for async link update */ if (eicr & IXGBE_EICR_LSC) intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; return 0; } /** * It gets and then prints the link status. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static void ixgbe_dev_link_status_print(struct rte_eth_dev *dev) { struct rte_eth_link link; memset(&link, 0, sizeof(link)); rte_ixgbe_dev_atomic_read_link_status(dev, &link); if (link.link_status) { PMD_INIT_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s", (int)(dev->data->port_id), (unsigned)link.link_speed, link.link_duplex == ETH_LINK_FULL_DUPLEX ? "full-duplex" : "half-duplex"); } else { PMD_INIT_LOG(INFO, " Port %d: Link Down", (int)(dev->data->port_id)); } PMD_INIT_LOG(DEBUG, "PCI Address: %04d:%02d:%02d:%d", dev->pci_dev->addr.domain, dev->pci_dev->addr.bus, dev->pci_dev->addr.devid, dev->pci_dev->addr.function); } /* * It executes link_update after knowing an interrupt occurred. * * @param dev * Pointer to struct rte_eth_dev. * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); int64_t timeout; struct rte_eth_link link; int intr_enable_delay = false; PMD_DRV_LOG(DEBUG, "intr action type %d", intr->flags); if (intr->flags & IXGBE_FLAG_MAILBOX) { ixgbe_pf_mbx_process(dev); intr->flags &= ~IXGBE_FLAG_MAILBOX; } if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { /* get the link status before link update, for predicting later */ memset(&link, 0, sizeof(link)); rte_ixgbe_dev_atomic_read_link_status(dev, &link); ixgbe_dev_link_update(dev, 0); /* likely to up */ if (!link.link_status) /* handle it 1 sec later, wait it being stable */ timeout = IXGBE_LINK_UP_CHECK_TIMEOUT; /* likely to down */ else /* handle it 4 sec later, wait it being stable */ timeout = IXGBE_LINK_DOWN_CHECK_TIMEOUT; ixgbe_dev_link_status_print(dev); intr_enable_delay = true; } if (intr_enable_delay) { if (rte_eal_alarm_set(timeout * 1000, ixgbe_dev_interrupt_delayed_handler, (void*)dev) < 0) PMD_DRV_LOG(ERR, "Error setting alarm"); } else { PMD_DRV_LOG(DEBUG, "enable intr immediately"); ixgbe_enable_intr(dev); rte_intr_enable(&(dev->pci_dev->intr_handle)); } return 0; } static int ixgbevf_dev_interrupt_action(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_DRV_LOG(DEBUG, "enable intr immediately"); ixgbevf_intr_enable(hw); rte_intr_enable(&dev->pci_dev->intr_handle); return 0; } /** * Interrupt handler which shall be registered for alarm callback for delayed * handling specific interrupt to wait for the stable nic state. As the * NIC interrupt state is not stable for ixgbe after link is just down, * it needs to wait 4 seconds to get the stable status. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void ixgbe_dev_interrupt_delayed_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t eicr; eicr = IXGBE_READ_REG(hw, IXGBE_EICR); if (eicr & IXGBE_EICR_MAILBOX) ixgbe_pf_mbx_process(dev); if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { ixgbe_dev_link_update(dev, 0); intr->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; ixgbe_dev_link_status_print(dev); _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); } PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr); ixgbe_enable_intr(dev); rte_intr_enable(&(dev->pci_dev->intr_handle)); } /** * Interrupt handler triggered by NIC for handling * specific interrupt. * * @param handle * Pointer to interrupt handle. * @param param * The address of parameter (struct rte_eth_dev *) regsitered before. * * @return * void */ static void ixgbe_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; ixgbe_dev_interrupt_get_status(dev); ixgbe_dev_interrupt_action(dev); } static void ixgbevf_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; ixgbevf_dev_interrupt_get_status(dev); ixgbevf_dev_interrupt_action(dev); } static int ixgbe_dev_led_on(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (ixgbe_led_on(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP); } static int ixgbe_dev_led_off(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); return (ixgbe_led_off(hw, 0) == IXGBE_SUCCESS ? 0 : -ENOTSUP); } static int ixgbe_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct ixgbe_hw *hw; uint32_t mflcn_reg; uint32_t fccfg_reg; int rx_pause; int tx_pause; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); fc_conf->pause_time = hw->fc.pause_time; fc_conf->high_water = hw->fc.high_water[0]; fc_conf->low_water = hw->fc.low_water[0]; fc_conf->send_xon = hw->fc.send_xon; fc_conf->autoneg = !hw->fc.disable_fc_autoneg; /* * Return rx_pause status according to actual setting of * MFLCN register. */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); if (mflcn_reg & (IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_RFCE)) rx_pause = 1; else rx_pause = 0; /* * Return tx_pause status according to actual setting of * FCCFG register. */ fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); if (fccfg_reg & (IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY)) tx_pause = 1; else tx_pause = 0; if (rx_pause && tx_pause) fc_conf->mode = RTE_FC_FULL; else if (rx_pause) fc_conf->mode = RTE_FC_RX_PAUSE; else if (tx_pause) fc_conf->mode = RTE_FC_TX_PAUSE; else fc_conf->mode = RTE_FC_NONE; return 0; } static int ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct ixgbe_hw *hw; int err; uint32_t rx_buf_size; uint32_t max_high_water; uint32_t mflcn; enum ixgbe_fc_mode rte_fcmode_2_ixgbe_fcmode[] = { ixgbe_fc_none, ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, ixgbe_fc_full }; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); rx_buf_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)); PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); /* * At least reserve one Ethernet frame for watermark * high_water/low_water in kilo bytes for ixgbe */ max_high_water = (rx_buf_size - ETHER_MAX_LEN) >> IXGBE_RXPBSIZE_SHIFT; if ((fc_conf->high_water > max_high_water) || (fc_conf->high_water < fc_conf->low_water)) { PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB"); PMD_INIT_LOG(ERR, "High_water must <= 0x%x", max_high_water); return (-EINVAL); } hw->fc.requested_mode = rte_fcmode_2_ixgbe_fcmode[fc_conf->mode]; hw->fc.pause_time = fc_conf->pause_time; hw->fc.high_water[0] = fc_conf->high_water; hw->fc.low_water[0] = fc_conf->low_water; hw->fc.send_xon = fc_conf->send_xon; hw->fc.disable_fc_autoneg = !fc_conf->autoneg; err = ixgbe_fc_enable(hw); /* Not negotiated is not an error case */ if ((err == IXGBE_SUCCESS) || (err == IXGBE_ERR_FC_NOT_NEGOTIATED)) { /* check if we want to forward MAC frames - driver doesn't have native * capability to do that, so we'll write the registers ourselves */ mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN); /* set or clear MFLCN.PMCF bit depending on configuration */ if (fc_conf->mac_ctrl_frame_fwd != 0) mflcn |= IXGBE_MFLCN_PMCF; else mflcn &= ~IXGBE_MFLCN_PMCF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn); IXGBE_WRITE_FLUSH(hw); return 0; } PMD_INIT_LOG(ERR, "ixgbe_fc_enable = 0x%x", err); return -EIO; } /** * ixgbe_pfc_enable_generic - Enable flow control * @hw: pointer to hardware structure * @tc_num: traffic class number * Enable flow control according to the current settings. */ static int ixgbe_dcb_pfc_enable_generic(struct ixgbe_hw *hw,uint8_t tc_num) { int ret_val = 0; uint32_t mflcn_reg, fccfg_reg; uint32_t reg; uint32_t fcrtl, fcrth; uint8_t i; uint8_t nb_rx_en; /* Validate the water mark configuration */ if (!hw->fc.pause_time) { ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* Low water mark of zero causes XOFF floods */ if (hw->fc.current_mode & ixgbe_fc_tx_pause) { /* High/Low water can not be 0 */ if( (!hw->fc.high_water[tc_num])|| (!hw->fc.low_water[tc_num])) { PMD_INIT_LOG(ERR, "Invalid water mark configuration"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } if(hw->fc.low_water[tc_num] >= hw->fc.high_water[tc_num]) { PMD_INIT_LOG(ERR, "Invalid water mark configuration"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } } /* Negotiate the fc mode to use */ ixgbe_fc_autoneg(hw); /* Disable any previous flow control settings */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_SHIFT | IXGBE_MFLCN_RFCE|IXGBE_MFLCN_RPFCE); fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); switch (hw->fc.current_mode) { case ixgbe_fc_none: /* * If the count of enabled RX Priority Flow control >1, * and the TX pause can not be disabled */ nb_rx_en = 0; for (i =0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { reg = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); if (reg & IXGBE_FCRTH_FCEN) nb_rx_en++; } if (nb_rx_en > 1) fccfg_reg |=IXGBE_FCCFG_TFCE_PRIORITY; break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ mflcn_reg |= IXGBE_MFLCN_RPFCE; /* * If the count of enabled RX Priority Flow control >1, * and the TX pause can not be disabled */ nb_rx_en = 0; for (i =0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { reg = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); if (reg & IXGBE_FCRTH_FCEN) nb_rx_en++; } if (nb_rx_en > 1) fccfg_reg |=IXGBE_FCCFG_TFCE_PRIORITY; break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ fccfg_reg |=IXGBE_FCCFG_TFCE_PRIORITY; break; case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ mflcn_reg |= IXGBE_MFLCN_RPFCE; fccfg_reg |= IXGBE_FCCFG_TFCE_PRIORITY; break; default: PMD_DRV_LOG(DEBUG, "Flow control param set incorrectly"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } /* Set 802.3x based flow control settings. */ mflcn_reg |= IXGBE_MFLCN_DPF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); /* Set up and enable Rx high/low water mark thresholds, enable XON. */ if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[tc_num]) { fcrtl = (hw->fc.low_water[tc_num] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(tc_num), fcrtl); fcrth = (hw->fc.high_water[tc_num] << 10) | IXGBE_FCRTH_FCEN; } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(tc_num), 0); /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark * to the maximum FCRTH value. This allows the Tx * switch to function even under heavy Rx workloads. */ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc_num)) - 32; } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(tc_num), fcrth); /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time * 0x00010001; for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); out: return ret_val; } static int ixgbe_dcb_pfc_enable(struct rte_eth_dev *dev,uint8_t tc_num) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int32_t ret_val = IXGBE_NOT_IMPLEMENTED; if(hw->mac.type != ixgbe_mac_82598EB) { ret_val = ixgbe_dcb_pfc_enable_generic(hw,tc_num); } return ret_val; } static int ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf) { int err; uint32_t rx_buf_size; uint32_t max_high_water; uint8_t tc_num; uint8_t map[IXGBE_DCB_MAX_USER_PRIORITY] = { 0 }; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_dcb_config *dcb_config = IXGBE_DEV_PRIVATE_TO_DCB_CFG(dev->data->dev_private); enum ixgbe_fc_mode rte_fcmode_2_ixgbe_fcmode[] = { ixgbe_fc_none, ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, ixgbe_fc_full }; PMD_INIT_FUNC_TRACE(); ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_RX_CONFIG, map); tc_num = map[pfc_conf->priority]; rx_buf_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc_num)); PMD_INIT_LOG(DEBUG, "Rx packet buffer size = 0x%x", rx_buf_size); /* * At least reserve one Ethernet frame for watermark * high_water/low_water in kilo bytes for ixgbe */ max_high_water = (rx_buf_size - ETHER_MAX_LEN) >> IXGBE_RXPBSIZE_SHIFT; if ((pfc_conf->fc.high_water > max_high_water) || (pfc_conf->fc.high_water <= pfc_conf->fc.low_water)) { PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB"); PMD_INIT_LOG(ERR, "High_water must <= 0x%x", max_high_water); return (-EINVAL); } hw->fc.requested_mode = rte_fcmode_2_ixgbe_fcmode[pfc_conf->fc.mode]; hw->fc.pause_time = pfc_conf->fc.pause_time; hw->fc.send_xon = pfc_conf->fc.send_xon; hw->fc.low_water[tc_num] = pfc_conf->fc.low_water; hw->fc.high_water[tc_num] = pfc_conf->fc.high_water; err = ixgbe_dcb_pfc_enable(dev,tc_num); /* Not negotiated is not an error case */ if ((err == IXGBE_SUCCESS) || (err == IXGBE_ERR_FC_NOT_NEGOTIATED)) return 0; PMD_INIT_LOG(ERR, "ixgbe_dcb_pfc_enable = 0x%x", err); return -EIO; } static int ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { uint8_t i, j, mask; uint32_t reta, r; uint16_t idx, shift; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (reta_size != ETH_RSS_RETA_SIZE_128) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128); return -EINVAL; } for (i = 0; i < reta_size; i += IXGBE_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & IXGBE_4_BIT_MASK); if (!mask) continue; if (mask == IXGBE_4_BIT_MASK) r = 0; else r = IXGBE_READ_REG(hw, IXGBE_RETA(i >> 2)); for (j = 0, reta = 0; j < IXGBE_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta |= reta_conf[idx].reta[shift + j] << (CHAR_BIT * j); else reta |= r & (IXGBE_8_BIT_MASK << (CHAR_BIT * j)); } IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); } return 0; } static int ixgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { uint8_t i, j, mask; uint32_t reta; uint16_t idx, shift; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (reta_size != ETH_RSS_RETA_SIZE_128) { PMD_DRV_LOG(ERR, "The size of hash lookup table configured " "(%d) doesn't match the number hardware can supported " "(%d)\n", reta_size, ETH_RSS_RETA_SIZE_128); return -EINVAL; } for (i = 0; i < ETH_RSS_RETA_SIZE_128; i += IXGBE_4_BIT_WIDTH) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; mask = (uint8_t)((reta_conf[idx].mask >> shift) & IXGBE_4_BIT_MASK); if (!mask) continue; reta = IXGBE_READ_REG(hw, IXGBE_RETA(i >> 2)); for (j = 0; j < IXGBE_4_BIT_WIDTH; j++) { if (mask & (0x1 << j)) reta_conf[idx].reta[shift + j] = ((reta >> (CHAR_BIT * j)) & IXGBE_8_BIT_MASK); } } return 0; } static void ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t pool) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t enable_addr = 1; ixgbe_set_rar(hw, index, mac_addr->addr_bytes, pool, enable_addr); } static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); ixgbe_clear_rar(hw, index); } static void ixgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) { ixgbe_remove_rar(dev, 0); ixgbe_add_rar(dev, addr, 0, 0); } static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) { uint32_t hlreg0; uint32_t maxfrs; struct ixgbe_hw *hw; struct rte_eth_dev_info dev_info; uint32_t frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; ixgbe_dev_info_get(dev, &dev_info); /* check that mtu is within the allowed range */ if ((mtu < ETHER_MIN_MTU) || (frame_size > dev_info.max_rx_pktlen)) return -EINVAL; /* refuse mtu that requires the support of scattered packets when this * feature has not been enabled before. */ if (!dev->data->scattered_rx && (frame_size + 2 * IXGBE_VLAN_TAG_SIZE > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)) return -EINVAL; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); /* switch to jumbo mode if needed */ if (frame_size > ETHER_MAX_LEN) { dev->data->dev_conf.rxmode.jumbo_frame = 1; hlreg0 |= IXGBE_HLREG0_JUMBOEN; } else { dev->data->dev_conf.rxmode.jumbo_frame = 0; hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; } IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); /* update max frame size */ dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size; maxfrs = IXGBE_READ_REG(hw, IXGBE_MAXFRS); maxfrs &= 0x0000FFFF; maxfrs |= (dev->data->dev_conf.rxmode.max_rx_pkt_len << 16); IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, maxfrs); return 0; } /* * Virtual Function operations */ static void ixgbevf_intr_disable(struct ixgbe_hw *hw) { PMD_INIT_FUNC_TRACE(); /* Clear interrupt mask to stop from interrupts being generated */ IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, IXGBE_VF_IRQ_CLEAR_MASK); IXGBE_WRITE_FLUSH(hw); } static void ixgbevf_intr_enable(struct ixgbe_hw *hw) { PMD_INIT_FUNC_TRACE(); /* VF enable interrupt autoclean */ IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, IXGBE_VF_IRQ_ENABLE_MASK); IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, IXGBE_VF_IRQ_ENABLE_MASK); IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, IXGBE_VF_IRQ_ENABLE_MASK); IXGBE_WRITE_FLUSH(hw); } static int ixgbevf_dev_configure(struct rte_eth_dev *dev) { struct rte_eth_conf* conf = &dev->data->dev_conf; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d", dev->data->port_id); /* * VF has no ability to enable/disable HW CRC * Keep the persistent behavior the same as Host PF */ #ifndef RTE_LIBRTE_IXGBE_PF_DISABLE_STRIP_CRC if (!conf->rxmode.hw_strip_crc) { PMD_INIT_LOG(NOTICE, "VF can't disable HW CRC Strip"); conf->rxmode.hw_strip_crc = 1; } #else if (conf->rxmode.hw_strip_crc) { PMD_INIT_LOG(NOTICE, "VF can't enable HW CRC Strip"); conf->rxmode.hw_strip_crc = 0; } #endif /* * Initialize to TRUE. If any of Rx queues doesn't meet the bulk * allocation or vector Rx preconditions we will reset it. */ adapter->rx_bulk_alloc_allowed = true; adapter->rx_vec_allowed = true; return 0; } static int ixgbevf_dev_start(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); #ifdef RTE_NEXT_ABI uint32_t intr_vector = 0; #endif struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; int err, mask = 0; PMD_INIT_FUNC_TRACE(); hw->mac.ops.reset_hw(hw); hw->mac.get_link_status = true; /* negotiate mailbox API version to use with the PF. */ ixgbevf_negotiate_api(hw); ixgbevf_dev_tx_init(dev); /* This can fail when allocating mbufs for descriptor rings */ err = ixgbevf_dev_rx_init(dev); if (err) { PMD_INIT_LOG(ERR, "Unable to initialize RX hardware (%d)", err); ixgbe_dev_clear_queues(dev); return err; } /* Set vfta */ ixgbevf_set_vfta_all(dev,1); /* Set HW strip */ mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \ ETH_VLAN_EXTEND_MASK; ixgbevf_vlan_offload_set(dev, mask); ixgbevf_dev_rxtx_start(dev); #ifdef RTE_NEXT_ABI /* check and configure queue intr-vector mapping */ if (dev->data->dev_conf.intr_conf.rxq != 0) intr_vector = dev->data->nb_rx_queues; if (rte_intr_efd_enable(intr_handle, intr_vector)) return -1; if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) { intr_handle->intr_vec = rte_zmalloc("intr_vec", dev->data->nb_rx_queues * sizeof(int), 0); if (intr_handle->intr_vec == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" " intr_vec\n", dev->data->nb_rx_queues); return -ENOMEM; } } #endif ixgbevf_configure_msix(dev); if (dev->data->dev_conf.intr_conf.lsc != 0) { if (rte_intr_allow_others(intr_handle)) rte_intr_callback_register(intr_handle, ixgbevf_dev_interrupt_handler, (void *)dev); else PMD_INIT_LOG(INFO, "lsc won't enable because of" " no intr multiplex\n"); } rte_intr_enable(intr_handle); /* Re-enable interrupt for VF */ ixgbevf_intr_enable(hw); return 0; } static void ixgbevf_dev_stop(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; PMD_INIT_FUNC_TRACE(); hw->adapter_stopped = 1; ixgbe_stop_adapter(hw); /* * Clear what we set, but we still keep shadow_vfta to * restore after device starts */ ixgbevf_set_vfta_all(dev,0); /* Clear stored conf */ dev->data->scattered_rx = 0; ixgbe_dev_clear_queues(dev); /* disable intr eventfd mapping */ rte_intr_disable(intr_handle); #ifdef RTE_NEXT_ABI /* Clean datapath event and queue/vec mapping */ rte_intr_efd_disable(intr_handle); if (intr_handle->intr_vec != NULL) { rte_free(intr_handle->intr_vec); intr_handle->intr_vec = NULL; } #endif } static void ixgbevf_dev_close(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); #ifdef RTE_NEXT_ABI struct rte_pci_device *pci_dev; #endif PMD_INIT_FUNC_TRACE(); ixgbe_reset_hw(hw); ixgbevf_dev_stop(dev); ixgbe_dev_free_queues(dev); /* reprogram the RAR[0] in case user changed it. */ ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); #ifdef RTE_NEXT_ABI pci_dev = dev->pci_dev; if (pci_dev->intr_handle.intr_vec) { rte_free(pci_dev->intr_handle.intr_vec); pci_dev->intr_handle.intr_vec = NULL; } #endif } static void ixgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); int i = 0, j = 0, vfta = 0, mask = 1; for (i = 0; i < IXGBE_VFTA_SIZE; i++){ vfta = shadow_vfta->vfta[i]; if(vfta){ mask = 1; for (j = 0; j < 32; j++){ if(vfta & mask) ixgbe_set_vfta(hw, (i<<5)+j, 0, on); mask<<=1; } } } } static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vfta * shadow_vfta = IXGBE_DEV_PRIVATE_TO_VFTA(dev->data->dev_private); uint32_t vid_idx = 0; uint32_t vid_bit = 0; int ret = 0; PMD_INIT_FUNC_TRACE(); /* vind is not used in VF driver, set to 0, check ixgbe_set_vfta_vf */ ret = ixgbe_set_vfta(hw, vlan_id, 0, !!on); if(ret){ PMD_INIT_LOG(ERR, "Unable to set VF vlan"); return ret; } vid_idx = (uint32_t) ((vlan_id >> 5) & 0x7F); vid_bit = (uint32_t) (1 << (vlan_id & 0x1F)); /* Save what we set and retore it after device reset */ if (on) shadow_vfta->vfta[vid_idx] |= vid_bit; else shadow_vfta->vfta[vid_idx] &= ~vid_bit; return 0; } static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t ctrl; PMD_INIT_FUNC_TRACE(); if(queue >= hw->mac.max_rx_queues) return; ctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(queue)); if(on) ctrl |= IXGBE_RXDCTL_VME; else ctrl &= ~IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(queue), ctrl); ixgbe_vlan_hw_strip_bitmap_set( dev, queue, on); } static void ixgbevf_vlan_offload_set(struct rte_eth_dev *dev, int mask) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint16_t i; int on = 0; /* VF function only support hw strip feature, others are not support */ if(mask & ETH_VLAN_STRIP_MASK){ on = !!(dev->data->dev_conf.rxmode.hw_vlan_strip); for(i=0; i < hw->mac.max_rx_queues; i++) ixgbevf_vlan_strip_queue_set(dev,i,on); } } static int ixgbe_vmdq_mode_check(struct ixgbe_hw *hw) { uint32_t reg_val; /* we only need to do this if VMDq is enabled */ reg_val = IXGBE_READ_REG(hw, IXGBE_VT_CTL); if (!(reg_val & IXGBE_VT_CTL_VT_ENABLE)) { PMD_INIT_LOG(ERR, "VMDq must be enabled for this setting"); return (-1); } return 0; } static uint32_t ixgbe_uta_vector(struct ixgbe_hw *hw, struct ether_addr* uc_addr) { uint32_t vector = 0; switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((uc_addr->addr_bytes[4] >> 4) | (((uint16_t)uc_addr->addr_bytes[5]) << 4)); break; case 1: /* use bits [46:35] of the address */ vector = ((uc_addr->addr_bytes[4] >> 3) | (((uint16_t)uc_addr->addr_bytes[5]) << 5)); break; case 2: /* use bits [45:34] of the address */ vector = ((uc_addr->addr_bytes[4] >> 2) | (((uint16_t)uc_addr->addr_bytes[5]) << 6)); break; case 3: /* use bits [43:32] of the address */ vector = ((uc_addr->addr_bytes[4]) | (((uint16_t)uc_addr->addr_bytes[5]) << 8)); break; default: /* Invalid mc_filter_type */ break; } /* vector can only be 12-bits or boundary will be exceeded */ vector &= 0xFFF; return vector; } static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev,struct ether_addr* mac_addr, uint8_t on) { uint32_t vector; uint32_t uta_idx; uint32_t reg_val; uint32_t uta_shift; uint32_t rc; const uint32_t ixgbe_uta_idx_mask = 0x7F; const uint32_t ixgbe_uta_bit_shift = 5; const uint32_t ixgbe_uta_bit_mask = (0x1 << ixgbe_uta_bit_shift) - 1; const uint32_t bit1 = 0x1; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_uta_info *uta_info = IXGBE_DEV_PRIVATE_TO_UTA(dev->data->dev_private); /* The UTA table only exists on 82599 hardware and newer */ if (hw->mac.type < ixgbe_mac_82599EB) return (-ENOTSUP); vector = ixgbe_uta_vector(hw,mac_addr); uta_idx = (vector >> ixgbe_uta_bit_shift) & ixgbe_uta_idx_mask; uta_shift = vector & ixgbe_uta_bit_mask; rc = ((uta_info->uta_shadow[uta_idx] >> uta_shift & bit1) != 0); if(rc == on) return 0; reg_val = IXGBE_READ_REG(hw, IXGBE_UTA(uta_idx)); if (on) { uta_info->uta_in_use++; reg_val |= (bit1 << uta_shift); uta_info->uta_shadow[uta_idx] |= (bit1 << uta_shift); } else { uta_info->uta_in_use--; reg_val &= ~(bit1 << uta_shift); uta_info->uta_shadow[uta_idx] &= ~(bit1 << uta_shift); } IXGBE_WRITE_REG(hw, IXGBE_UTA(uta_idx), reg_val); if (uta_info->uta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); else IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,hw->mac.mc_filter_type); return 0; } static int ixgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on) { int i; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_uta_info *uta_info = IXGBE_DEV_PRIVATE_TO_UTA(dev->data->dev_private); /* The UTA table only exists on 82599 hardware and newer */ if (hw->mac.type < ixgbe_mac_82599EB) return (-ENOTSUP); if(on) { for (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) { uta_info->uta_shadow[i] = ~0; IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0); } } else { for (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) { uta_info->uta_shadow[i] = 0; IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); } } return 0; } uint32_t ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val) { uint32_t new_val = orig_val; if (rx_mask & ETH_VMDQ_ACCEPT_UNTAG) new_val |= IXGBE_VMOLR_AUPE; if (rx_mask & ETH_VMDQ_ACCEPT_HASH_MC) new_val |= IXGBE_VMOLR_ROMPE; if (rx_mask & ETH_VMDQ_ACCEPT_HASH_UC) new_val |= IXGBE_VMOLR_ROPE; if (rx_mask & ETH_VMDQ_ACCEPT_BROADCAST) new_val |= IXGBE_VMOLR_BAM; if (rx_mask & ETH_VMDQ_ACCEPT_MULTICAST) new_val |= IXGBE_VMOLR_MPE; return new_val; } static int ixgbe_set_pool_rx_mode(struct rte_eth_dev *dev, uint16_t pool, uint16_t rx_mask, uint8_t on) { int val = 0; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(pool)); if (hw->mac.type == ixgbe_mac_82598EB) { PMD_INIT_LOG(ERR, "setting VF receive mode set should be done" " on 82599 hardware and newer"); return (-ENOTSUP); } if (ixgbe_vmdq_mode_check(hw) < 0) return (-ENOTSUP); val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val); if (on) vmolr |= val; else vmolr &= ~val; IXGBE_WRITE_REG(hw, IXGBE_VMOLR(pool), vmolr); return 0; } static int ixgbe_set_pool_rx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on) { uint32_t reg,addr; uint32_t val; const uint8_t bit1 = 0x1; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (ixgbe_vmdq_mode_check(hw) < 0) return (-ENOTSUP); addr = IXGBE_VFRE(pool >= ETH_64_POOLS/2); reg = IXGBE_READ_REG(hw, addr); val = bit1 << pool; if (on) reg |= val; else reg &= ~val; IXGBE_WRITE_REG(hw, addr,reg); return 0; } static int ixgbe_set_pool_tx(struct rte_eth_dev *dev, uint16_t pool, uint8_t on) { uint32_t reg,addr; uint32_t val; const uint8_t bit1 = 0x1; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (ixgbe_vmdq_mode_check(hw) < 0) return (-ENOTSUP); addr = IXGBE_VFTE(pool >= ETH_64_POOLS/2); reg = IXGBE_READ_REG(hw, addr); val = bit1 << pool; if (on) reg |= val; else reg &= ~val; IXGBE_WRITE_REG(hw, addr,reg); return 0; } static int ixgbe_set_pool_vlan_filter(struct rte_eth_dev *dev, uint16_t vlan, uint64_t pool_mask, uint8_t vlan_on) { int ret = 0; uint16_t pool_idx; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (ixgbe_vmdq_mode_check(hw) < 0) return (-ENOTSUP); for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) { if (pool_mask & ((uint64_t)(1ULL << pool_idx))) ret = hw->mac.ops.set_vfta(hw,vlan,pool_idx,vlan_on); if (ret < 0) return ret; } return ret; } #define IXGBE_MRCTL_VPME 0x01 /* Virtual Pool Mirroring. */ #define IXGBE_MRCTL_UPME 0x02 /* Uplink Port Mirroring. */ #define IXGBE_MRCTL_DPME 0x04 /* Downlink Port Mirroring. */ #define IXGBE_MRCTL_VLME 0x08 /* VLAN Mirroring. */ #define IXGBE_INVALID_MIRROR_TYPE(mirror_type) \ ((mirror_type) & ~(uint8_t)(ETH_MIRROR_VIRTUAL_POOL_UP | \ ETH_MIRROR_UPLINK_PORT | ETH_MIRROR_DOWNLINK_PORT | ETH_MIRROR_VLAN)) static int ixgbe_mirror_rule_set(struct rte_eth_dev *dev, struct rte_eth_mirror_conf *mirror_conf, uint8_t rule_id, uint8_t on) { uint32_t mr_ctl,vlvf; uint32_t mp_lsb = 0; uint32_t mv_msb = 0; uint32_t mv_lsb = 0; uint32_t mp_msb = 0; uint8_t i = 0; int reg_index = 0; uint64_t vlan_mask = 0; const uint8_t pool_mask_offset = 32; const uint8_t vlan_mask_offset = 32; const uint8_t dst_pool_offset = 8; const uint8_t rule_mr_offset = 4; const uint8_t mirror_rule_mask= 0x0F; struct ixgbe_mirror_info *mr_info = (IXGBE_DEV_PRIVATE_TO_PFDATA(dev->data->dev_private)); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint8_t mirror_type = 0; if (ixgbe_vmdq_mode_check(hw) < 0) return -ENOTSUP; if (rule_id >= IXGBE_MAX_MIRROR_RULES) return -EINVAL; if (IXGBE_INVALID_MIRROR_TYPE(mirror_conf->rule_type)) { PMD_DRV_LOG(ERR, "unsupported mirror type 0x%x.", mirror_conf->rule_type); return -EINVAL; } if (mirror_conf->rule_type & ETH_MIRROR_VLAN) { mirror_type |= IXGBE_MRCTL_VLME; /* Check if vlan id is valid and find conresponding VLAN ID index in VLVF */ for (i = 0;i < IXGBE_VLVF_ENTRIES; i++) { if (mirror_conf->vlan.vlan_mask & (1ULL << i)) { /* search vlan id related pool vlan filter index */ reg_index = ixgbe_find_vlvf_slot(hw, mirror_conf->vlan.vlan_id[i]); if(reg_index < 0) return -EINVAL; vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(reg_index)); if ((vlvf & IXGBE_VLVF_VIEN) && ((vlvf & IXGBE_VLVF_VLANID_MASK) == mirror_conf->vlan.vlan_id[i])) vlan_mask |= (1ULL << reg_index); else return -EINVAL; } } if (on) { mv_lsb = vlan_mask & 0xFFFFFFFF; mv_msb = vlan_mask >> vlan_mask_offset; mr_info->mr_conf[rule_id].vlan.vlan_mask = mirror_conf->vlan.vlan_mask; for(i = 0 ;i < ETH_VMDQ_MAX_VLAN_FILTERS; i++) { if(mirror_conf->vlan.vlan_mask & (1ULL << i)) mr_info->mr_conf[rule_id].vlan.vlan_id[i] = mirror_conf->vlan.vlan_id[i]; } } else { mv_lsb = 0; mv_msb = 0; mr_info->mr_conf[rule_id].vlan.vlan_mask = 0; for(i = 0 ;i < ETH_VMDQ_MAX_VLAN_FILTERS; i++) mr_info->mr_conf[rule_id].vlan.vlan_id[i] = 0; } } /* * if enable pool mirror, write related pool mask register,if disable * pool mirror, clear PFMRVM register */ if (mirror_conf->rule_type & ETH_MIRROR_VIRTUAL_POOL_UP) { mirror_type |= IXGBE_MRCTL_VPME; if (on) { mp_lsb = mirror_conf->pool_mask & 0xFFFFFFFF; mp_msb = mirror_conf->pool_mask >> pool_mask_offset; mr_info->mr_conf[rule_id].pool_mask = mirror_conf->pool_mask; } else { mp_lsb = 0; mp_msb = 0; mr_info->mr_conf[rule_id].pool_mask = 0; } } if (mirror_conf->rule_type & ETH_MIRROR_UPLINK_PORT) mirror_type |= IXGBE_MRCTL_UPME; if (mirror_conf->rule_type & ETH_MIRROR_DOWNLINK_PORT) mirror_type |= IXGBE_MRCTL_DPME; /* read mirror control register and recalculate it */ mr_ctl = IXGBE_READ_REG(hw, IXGBE_MRCTL(rule_id)); if (on) { mr_ctl |= mirror_type; mr_ctl &= mirror_rule_mask; mr_ctl |= mirror_conf->dst_pool << dst_pool_offset; } else mr_ctl &= ~(mirror_conf->rule_type & mirror_rule_mask); mr_info->mr_conf[rule_id].rule_type = mirror_conf->rule_type; mr_info->mr_conf[rule_id].dst_pool = mirror_conf->dst_pool; /* write mirrror control register */ IXGBE_WRITE_REG(hw, IXGBE_MRCTL(rule_id), mr_ctl); /* write pool mirrror control register */ if (mirror_conf->rule_type == ETH_MIRROR_VIRTUAL_POOL_UP) { IXGBE_WRITE_REG(hw, IXGBE_VMRVM(rule_id), mp_lsb); IXGBE_WRITE_REG(hw, IXGBE_VMRVM(rule_id + rule_mr_offset), mp_msb); } /* write VLAN mirrror control register */ if (mirror_conf->rule_type == ETH_MIRROR_VLAN) { IXGBE_WRITE_REG(hw, IXGBE_VMRVLAN(rule_id), mv_lsb); IXGBE_WRITE_REG(hw, IXGBE_VMRVLAN(rule_id + rule_mr_offset), mv_msb); } return 0; } static int ixgbe_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t rule_id) { int mr_ctl = 0; uint32_t lsb_val = 0; uint32_t msb_val = 0; const uint8_t rule_mr_offset = 4; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_mirror_info *mr_info = (IXGBE_DEV_PRIVATE_TO_PFDATA(dev->data->dev_private)); if (ixgbe_vmdq_mode_check(hw) < 0) return (-ENOTSUP); memset(&mr_info->mr_conf[rule_id], 0, sizeof(struct rte_eth_mirror_conf)); /* clear PFVMCTL register */ IXGBE_WRITE_REG(hw, IXGBE_MRCTL(rule_id), mr_ctl); /* clear pool mask register */ IXGBE_WRITE_REG(hw, IXGBE_VMRVM(rule_id), lsb_val); IXGBE_WRITE_REG(hw, IXGBE_VMRVM(rule_id + rule_mr_offset), msb_val); /* clear vlan mask register */ IXGBE_WRITE_REG(hw, IXGBE_VMRVLAN(rule_id), lsb_val); IXGBE_WRITE_REG(hw, IXGBE_VMRVLAN(rule_id + rule_mr_offset), msb_val); return 0; } #ifdef RTE_NEXT_ABI static int ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) { uint32_t mask; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS); mask |= (1 << queue_id); IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); rte_intr_enable(&dev->pci_dev->intr_handle); return 0; } static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { uint32_t mask; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); mask = IXGBE_READ_REG(hw, IXGBE_VTEIMS); mask &= ~(1 << queue_id); IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); return 0; } static int ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) { uint32_t mask; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); if (queue_id < 16) { ixgbe_disable_intr(hw); intr->mask |= (1 << queue_id); ixgbe_enable_intr(dev); } else if (queue_id < 32) { mask = IXGBE_READ_REG(hw, IXGBE_EIMS_EX(0)); mask &= (1 << queue_id); IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); } else if (queue_id < 64) { mask = IXGBE_READ_REG(hw, IXGBE_EIMS_EX(1)); mask &= (1 << (queue_id - 32)); IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); } rte_intr_enable(&dev->pci_dev->intr_handle); return 0; } static int ixgbe_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { uint32_t mask; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); if (queue_id < 16) { ixgbe_disable_intr(hw); intr->mask &= ~(1 << queue_id); ixgbe_enable_intr(dev); } else if (queue_id < 32) { mask = IXGBE_READ_REG(hw, IXGBE_EIMS_EX(0)); mask &= ~(1 << queue_id); IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); } else if (queue_id < 64) { mask = IXGBE_READ_REG(hw, IXGBE_EIMS_EX(1)); mask &= ~(1 << (queue_id - 32)); IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); } return 0; } static void ixgbevf_set_ivar_map(struct ixgbe_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector) { uint32_t tmp, idx; if (direction == -1) { /* other causes */ msix_vector |= IXGBE_IVAR_ALLOC_VAL; tmp = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); tmp &= ~0xFF; tmp |= msix_vector; IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, tmp); } else { /* rx or tx cause */ msix_vector |= IXGBE_IVAR_ALLOC_VAL; idx = ((16 * (queue & 1)) + (8 * direction)); tmp = IXGBE_READ_REG(hw, IXGBE_VTIVAR(queue >> 1)); tmp &= ~(0xFF << idx); tmp |= (msix_vector << idx); IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(queue >> 1), tmp); } } /** * set the IVAR registers, mapping interrupt causes to vectors * @param hw * pointer to ixgbe_hw struct * @direction * 0 for Rx, 1 for Tx, -1 for other causes * @queue * queue to map the corresponding interrupt to * @msix_vector * the vector to map to the corresponding queue */ static void ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction, uint8_t queue, uint8_t msix_vector) { uint32_t tmp, idx; msix_vector |= IXGBE_IVAR_ALLOC_VAL; if (hw->mac.type == ixgbe_mac_82598EB) { if (direction == -1) direction = 0; idx = (((direction * 64) + queue) >> 2) & 0x1F; tmp = IXGBE_READ_REG(hw, IXGBE_IVAR(idx)); tmp &= ~(0xFF << (8 * (queue & 0x3))); tmp |= (msix_vector << (8 * (queue & 0x3))); IXGBE_WRITE_REG(hw, IXGBE_IVAR(idx), tmp); } else if ((hw->mac.type == ixgbe_mac_82599EB) || (hw->mac.type == ixgbe_mac_X540)) { if (direction == -1) { /* other causes */ idx = ((queue & 1) * 8); tmp = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); tmp &= ~(0xFF << idx); tmp |= (msix_vector << idx); IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, tmp); } else { /* rx or tx causes */ idx = ((16 * (queue & 1)) + (8 * direction)); tmp = IXGBE_READ_REG(hw, IXGBE_IVAR(queue >> 1)); tmp &= ~(0xFF << idx); tmp |= (msix_vector << idx); IXGBE_WRITE_REG(hw, IXGBE_IVAR(queue >> 1), tmp); } } } #endif static void ixgbevf_configure_msix(struct rte_eth_dev *dev) { struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; #ifdef RTE_NEXT_ABI struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t q_idx; uint32_t vector_idx = 0; #endif /* won't configure msix register if no mapping is done * between intr vector and event fd. */ if (!rte_intr_dp_is_en(intr_handle)) return; #ifdef RTE_NEXT_ABI /* Configure all RX queues of VF */ for (q_idx = 0; q_idx < dev->data->nb_rx_queues; q_idx++) { /* Force all queue use vector 0, * as IXGBE_VF_MAXMSIVECOTR = 1 */ ixgbevf_set_ivar_map(hw, 0, q_idx, vector_idx); intr_handle->intr_vec[q_idx] = vector_idx; } /* Configure VF Rx queue ivar */ ixgbevf_set_ivar_map(hw, -1, 1, vector_idx); #endif } /** * Sets up the hardware to properly generate MSI-X interrupts * @hw * board private structure */ static void ixgbe_configure_msix(struct rte_eth_dev *dev) { struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; #ifdef RTE_NEXT_ABI struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t queue_id, vec = 0; uint32_t mask; uint32_t gpie; #endif /* won't configure msix register if no mapping is done * between intr vector and event fd */ if (!rte_intr_dp_is_en(intr_handle)) return; #ifdef RTE_NEXT_ABI /* setup GPIE for MSI-x mode */ gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD | IXGBE_GPIE_EIAME; /* auto clearing and auto setting corresponding bits in EIMS * when MSI-X interrupt is triggered */ if (hw->mac.type == ixgbe_mac_82598EB) { IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); } else { IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF); } IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); /* Populate the IVAR table and set the ITR values to the * corresponding register. */ for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) { /* by default, 1:1 mapping */ ixgbe_set_ivar_map(hw, 0, queue_id, vec); intr_handle->intr_vec[queue_id] = vec; if (vec < intr_handle->nb_efd - 1) vec++; } switch (hw->mac.type) { case ixgbe_mac_82598EB: ixgbe_set_ivar_map(hw, -1, IXGBE_IVAR_OTHER_CAUSES_INDEX, intr_handle->max_intr - 1); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: ixgbe_set_ivar_map(hw, -1, 1, intr_handle->max_intr - 1); break; default: break; } IXGBE_WRITE_REG(hw, IXGBE_EITR(queue_id), IXGBE_MIN_INTER_INTERRUPT_INTERVAL_DEFAULT & 0xFFF); /* set up to autoclear timer, and the vectors */ mask = IXGBE_EIMS_ENABLE_MASK; mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_MAILBOX | IXGBE_EIMS_LSC); IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask); #endif } static int ixgbe_set_queue_rate_limit(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t tx_rate) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t rf_dec, rf_int; uint32_t bcnrc_val; uint16_t link_speed = dev->data->dev_link.link_speed; if (queue_idx >= hw->mac.max_tx_queues) return -EINVAL; if (tx_rate != 0) { /* Calculate the rate factor values to set */ rf_int = (uint32_t)link_speed / (uint32_t)tx_rate; rf_dec = (uint32_t)link_speed % (uint32_t)tx_rate; rf_dec = (rf_dec << IXGBE_RTTBCNRC_RF_INT_SHIFT) / tx_rate; bcnrc_val = IXGBE_RTTBCNRC_RS_ENA; bcnrc_val |= ((rf_int << IXGBE_RTTBCNRC_RF_INT_SHIFT) & IXGBE_RTTBCNRC_RF_INT_MASK_M); bcnrc_val |= (rf_dec & IXGBE_RTTBCNRC_RF_DEC_MASK); } else { bcnrc_val = 0; } /* * Set global transmit compensation time to the MMW_SIZE in RTTBCNRM * register. MMW_SIZE=0x014 if 9728-byte jumbo is supported, otherwise * set as 0x4. */ if ((dev->data->dev_conf.rxmode.jumbo_frame == 1) && (dev->data->dev_conf.rxmode.max_rx_pkt_len >= IXGBE_MAX_JUMBO_FRAME_SIZE)) IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, IXGBE_MMW_SIZE_JUMBO_FRAME); else IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRM, IXGBE_MMW_SIZE_DEFAULT); /* Set RTTBCNRC of queue X */ IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, queue_idx); IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val); IXGBE_WRITE_FLUSH(hw); return 0; } static int ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf, uint16_t tx_rate, uint64_t q_msk) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); uint8_t nb_q_per_pool = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool; uint32_t queue_stride = IXGBE_MAX_RX_QUEUE_NUM / RTE_ETH_DEV_SRIOV(dev).active; uint32_t queue_idx = vf * queue_stride, idx = 0, vf_idx; uint32_t queue_end = queue_idx + nb_q_per_pool - 1; uint16_t total_rate = 0; if (queue_end >= hw->mac.max_tx_queues) return -EINVAL; if (vfinfo != NULL) { for (vf_idx = 0; vf_idx < dev->pci_dev->max_vfs; vf_idx++) { if (vf_idx == vf) continue; for (idx = 0; idx < RTE_DIM(vfinfo[vf_idx].tx_rate); idx++) total_rate += vfinfo[vf_idx].tx_rate[idx]; } } else return -EINVAL; /* Store tx_rate for this vf. */ for (idx = 0; idx < nb_q_per_pool; idx++) { if (((uint64_t)0x1 << idx) & q_msk) { if (vfinfo[vf].tx_rate[idx] != tx_rate) vfinfo[vf].tx_rate[idx] = tx_rate; total_rate += tx_rate; } } if (total_rate > dev->data->dev_link.link_speed) { /* * Reset stored TX rate of the VF if it causes exceed * link speed. */ memset(vfinfo[vf].tx_rate, 0, sizeof(vfinfo[vf].tx_rate)); return -EINVAL; } /* Set RTTBCNRC of each queue/pool for vf X */ for (; queue_idx <= queue_end; queue_idx++) { if (0x1 & q_msk) ixgbe_set_queue_rate_limit(dev, queue_idx, tx_rate); q_msk = q_msk >> 1; } return 0; } static void ixgbevf_add_mac_addr(struct rte_eth_dev *dev, struct ether_addr *mac_addr, __attribute__((unused)) uint32_t index, __attribute__((unused)) uint32_t pool) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int diag; /* * On a 82599 VF, adding again the same MAC addr is not an idempotent * operation. Trap this case to avoid exhausting the [very limited] * set of PF resources used to store VF MAC addresses. */ if (memcmp(hw->mac.perm_addr, mac_addr, sizeof(struct ether_addr)) == 0) return; diag = ixgbevf_set_uc_addr_vf(hw, 2, mac_addr->addr_bytes); if (diag == 0) return; PMD_DRV_LOG(ERR, "Unable to add MAC address - diag=%d", diag); } static void ixgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ether_addr *perm_addr = (struct ether_addr *) hw->mac.perm_addr; struct ether_addr *mac_addr; uint32_t i; int diag; /* * The IXGBE_VF_SET_MACVLAN command of the ixgbe-pf driver does * not support the deletion of a given MAC address. * Instead, it imposes to delete all MAC addresses, then to add again * all MAC addresses with the exception of the one to be deleted. */ (void) ixgbevf_set_uc_addr_vf(hw, 0, NULL); /* * Add again all MAC addresses, with the exception of the deleted one * and of the permanent MAC address. */ for (i = 0, mac_addr = dev->data->mac_addrs; i < hw->mac.num_rar_entries; i++, mac_addr++) { /* Skip the deleted MAC address */ if (i == index) continue; /* Skip NULL MAC addresses */ if (is_zero_ether_addr(mac_addr)) continue; /* Skip the permanent MAC address */ if (memcmp(perm_addr, mac_addr, sizeof(struct ether_addr)) == 0) continue; diag = ixgbevf_set_uc_addr_vf(hw, 2, mac_addr->addr_bytes); if (diag != 0) PMD_DRV_LOG(ERR, "Adding again MAC address " "%02x:%02x:%02x:%02x:%02x:%02x failed " "diag=%d", mac_addr->addr_bytes[0], mac_addr->addr_bytes[1], mac_addr->addr_bytes[2], mac_addr->addr_bytes[3], mac_addr->addr_bytes[4], mac_addr->addr_bytes[5], diag); } } static void ixgbevf_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); hw->mac.ops.set_rar(hw, 0, (void *)addr, 0, 0); } #define MAC_TYPE_FILTER_SUP(type) do {\ if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540 &&\ (type) != ixgbe_mac_X550)\ return -ENOTSUP;\ } while (0) static int ixgbe_syn_filter_set(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter, bool add) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t synqf; if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM) return -EINVAL; synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); if (add) { if (synqf & IXGBE_SYN_FILTER_ENABLE) return -EINVAL; synqf = (uint32_t)(((filter->queue << IXGBE_SYN_FILTER_QUEUE_SHIFT) & IXGBE_SYN_FILTER_QUEUE) | IXGBE_SYN_FILTER_ENABLE); if (filter->hig_pri) synqf |= IXGBE_SYN_FILTER_SYNQFP; else synqf &= ~IXGBE_SYN_FILTER_SYNQFP; } else { if (!(synqf & IXGBE_SYN_FILTER_ENABLE)) return -ENOENT; synqf &= ~(IXGBE_SYN_FILTER_QUEUE | IXGBE_SYN_FILTER_ENABLE); } IXGBE_WRITE_REG(hw, IXGBE_SYNQF, synqf); IXGBE_WRITE_FLUSH(hw); return 0; } static int ixgbe_syn_filter_get(struct rte_eth_dev *dev, struct rte_eth_syn_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t synqf = IXGBE_READ_REG(hw, IXGBE_SYNQF); if (synqf & IXGBE_SYN_FILTER_ENABLE) { filter->hig_pri = (synqf & IXGBE_SYN_FILTER_SYNQFP) ? 1 : 0; filter->queue = (uint16_t)((synqf & IXGBE_SYN_FILTER_QUEUE) >> 1); return 0; } return -ENOENT; } static int ixgbe_syn_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = ixgbe_syn_filter_set(dev, (struct rte_eth_syn_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = ixgbe_syn_filter_set(dev, (struct rte_eth_syn_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = ixgbe_syn_filter_get(dev, (struct rte_eth_syn_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u\n", filter_op); ret = -EINVAL; break; } return ret; } static inline enum ixgbe_5tuple_protocol convert_protocol_type(uint8_t protocol_value) { if (protocol_value == IPPROTO_TCP) return IXGBE_FILTER_PROTOCOL_TCP; else if (protocol_value == IPPROTO_UDP) return IXGBE_FILTER_PROTOCOL_UDP; else if (protocol_value == IPPROTO_SCTP) return IXGBE_FILTER_PROTOCOL_SCTP; else return IXGBE_FILTER_PROTOCOL_NONE; } /* * add a 5tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * index: the index the filter allocates. * filter: ponter to the filter that will be added. * rx_queue: the queue id the filter assigned to. * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_add_5tuple_filter(struct rte_eth_dev *dev, struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); int i, idx, shift; uint32_t ftqf, sdpqf; uint32_t l34timir = 0; uint8_t mask = 0xff; /* * look for an unused 5tuple filter index, * and insert the filter to list. */ for (i = 0; i < IXGBE_MAX_FTQF_FILTERS; i++) { idx = i / (sizeof(uint32_t) * NBBY); shift = i % (sizeof(uint32_t) * NBBY); if (!(filter_info->fivetuple_mask[idx] & (1 << shift))) { filter_info->fivetuple_mask[idx] |= 1 << shift; filter->index = i; TAILQ_INSERT_TAIL(&filter_info->fivetuple_list, filter, entries); break; } } if (i >= IXGBE_MAX_FTQF_FILTERS) { PMD_DRV_LOG(ERR, "5tuple filters are full."); return -ENOSYS; } sdpqf = (uint32_t)(filter->filter_info.dst_port << IXGBE_SDPQF_DSTPORT_SHIFT); sdpqf = sdpqf | (filter->filter_info.src_port & IXGBE_SDPQF_SRCPORT); ftqf = (uint32_t)(filter->filter_info.proto & IXGBE_FTQF_PROTOCOL_MASK); ftqf |= (uint32_t)((filter->filter_info.priority & IXGBE_FTQF_PRIORITY_MASK) << IXGBE_FTQF_PRIORITY_SHIFT); if (filter->filter_info.src_ip_mask == 0) /* 0 means compare. */ mask &= IXGBE_FTQF_SOURCE_ADDR_MASK; if (filter->filter_info.dst_ip_mask == 0) mask &= IXGBE_FTQF_DEST_ADDR_MASK; if (filter->filter_info.src_port_mask == 0) mask &= IXGBE_FTQF_SOURCE_PORT_MASK; if (filter->filter_info.dst_port_mask == 0) mask &= IXGBE_FTQF_DEST_PORT_MASK; if (filter->filter_info.proto_mask == 0) mask &= IXGBE_FTQF_PROTOCOL_COMP_MASK; ftqf |= mask << IXGBE_FTQF_5TUPLE_MASK_SHIFT; ftqf |= IXGBE_FTQF_POOL_MASK_EN; ftqf |= IXGBE_FTQF_QUEUE_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_DAQF(i), filter->filter_info.dst_ip); IXGBE_WRITE_REG(hw, IXGBE_SAQF(i), filter->filter_info.src_ip); IXGBE_WRITE_REG(hw, IXGBE_SDPQF(i), sdpqf); IXGBE_WRITE_REG(hw, IXGBE_FTQF(i), ftqf); l34timir |= IXGBE_L34T_IMIR_RESERVE; l34timir |= (uint32_t)(filter->queue << IXGBE_L34T_IMIR_QUEUE_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(i), l34timir); return 0; } /* * remove a 5tuple filter * * @param * dev: Pointer to struct rte_eth_dev. * filter: the pointer of the filter will be removed. */ static void ixgbe_remove_5tuple_filter(struct rte_eth_dev *dev, struct ixgbe_5tuple_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); uint16_t index = filter->index; filter_info->fivetuple_mask[index / (sizeof(uint32_t) * NBBY)] &= ~(1 << (index % (sizeof(uint32_t) * NBBY))); TAILQ_REMOVE(&filter_info->fivetuple_list, filter, entries); rte_free(filter); IXGBE_WRITE_REG(hw, IXGBE_DAQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_SAQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_SDPQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_FTQF(index), 0); IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(index), 0); } static int ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) { struct ixgbe_hw *hw; uint32_t max_frame = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if ((mtu < ETHER_MIN_MTU) || (max_frame > ETHER_MAX_JUMBO_FRAME_LEN)) return -EINVAL; /* refuse mtu that requires the support of scattered packets when this * feature has not been enabled before. */ if (!dev->data->scattered_rx && (max_frame + 2 * IXGBE_VLAN_TAG_SIZE > dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)) return -EINVAL; /* * When supported by the underlying PF driver, use the IXGBE_VF_SET_MTU * request of the version 2.0 of the mailbox API. * For now, use the IXGBE_VF_SET_LPE request of the version 1.0 * of the mailbox API. * This call to IXGBE_SET_LPE action won't work with ixgbe pf drivers * prior to 3.11.33 which contains the following change: * "ixgbe: Enable jumbo frames support w/ SR-IOV" */ ixgbevf_rlpml_set_vf(hw, max_frame); /* update max frame size */ dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame; return 0; } #define MAC_TYPE_FILTER_SUP_EXT(type) do {\ if ((type) != ixgbe_mac_82599EB && (type) != ixgbe_mac_X540)\ return -ENOTSUP;\ } while (0) static inline struct ixgbe_5tuple_filter * ixgbe_5tuple_filter_lookup(struct ixgbe_5tuple_filter_list *filter_list, struct ixgbe_5tuple_filter_info *key) { struct ixgbe_5tuple_filter *it; TAILQ_FOREACH(it, filter_list, entries) { if (memcmp(key, &it->filter_info, sizeof(struct ixgbe_5tuple_filter_info)) == 0) { return it; } } return NULL; } /* translate elements in struct rte_eth_ntuple_filter to struct ixgbe_5tuple_filter_info*/ static inline int ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, struct ixgbe_5tuple_filter_info *filter_info) { if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM || filter->priority > IXGBE_5TUPLE_MAX_PRI || filter->priority < IXGBE_5TUPLE_MIN_PRI) return -EINVAL; switch (filter->dst_ip_mask) { case UINT32_MAX: filter_info->dst_ip_mask = 0; filter_info->dst_ip = filter->dst_ip; break; case 0: filter_info->dst_ip_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid dst_ip mask."); return -EINVAL; } switch (filter->src_ip_mask) { case UINT32_MAX: filter_info->src_ip_mask = 0; filter_info->src_ip = filter->src_ip; break; case 0: filter_info->src_ip_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid src_ip mask."); return -EINVAL; } switch (filter->dst_port_mask) { case UINT16_MAX: filter_info->dst_port_mask = 0; filter_info->dst_port = filter->dst_port; break; case 0: filter_info->dst_port_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid dst_port mask."); return -EINVAL; } switch (filter->src_port_mask) { case UINT16_MAX: filter_info->src_port_mask = 0; filter_info->src_port = filter->src_port; break; case 0: filter_info->src_port_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid src_port mask."); return -EINVAL; } switch (filter->proto_mask) { case UINT8_MAX: filter_info->proto_mask = 0; filter_info->proto = convert_protocol_type(filter->proto); break; case 0: filter_info->proto_mask = 1; break; default: PMD_DRV_LOG(ERR, "invalid protocol mask."); return -EINVAL; } filter_info->priority = (uint8_t)filter->priority; return 0; } /* * add or delete a ntuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: Pointer to struct rte_eth_ntuple_filter * add: if true, add filter, if false, remove filter * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_add_del_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter, bool add) { struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct ixgbe_5tuple_filter_info filter_5tuple; struct ixgbe_5tuple_filter *filter; int ret; if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { PMD_DRV_LOG(ERR, "only 5tuple is supported."); return -EINVAL; } memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); if (ret < 0) return ret; filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, &filter_5tuple); if (filter != NULL && add) { PMD_DRV_LOG(ERR, "filter exists."); return -EEXIST; } if (filter == NULL && !add) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } if (add) { filter = rte_zmalloc("ixgbe_5tuple_filter", sizeof(struct ixgbe_5tuple_filter), 0); if (filter == NULL) return -ENOMEM; (void)rte_memcpy(&filter->filter_info, &filter_5tuple, sizeof(struct ixgbe_5tuple_filter_info)); filter->queue = ntuple_filter->queue; ret = ixgbe_add_5tuple_filter(dev, filter); if (ret < 0) { rte_free(filter); return ret; } } else ixgbe_remove_5tuple_filter(dev, filter); return 0; } /* * get a ntuple filter * * @param * dev: Pointer to struct rte_eth_dev. * ntuple_filter: Pointer to struct rte_eth_ntuple_filter * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_get_ntuple_filter(struct rte_eth_dev *dev, struct rte_eth_ntuple_filter *ntuple_filter) { struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); struct ixgbe_5tuple_filter_info filter_5tuple; struct ixgbe_5tuple_filter *filter; int ret; if (ntuple_filter->flags != RTE_5TUPLE_FLAGS) { PMD_DRV_LOG(ERR, "only 5tuple is supported."); return -EINVAL; } memset(&filter_5tuple, 0, sizeof(struct ixgbe_5tuple_filter_info)); ret = ntuple_filter_to_5tuple(ntuple_filter, &filter_5tuple); if (ret < 0) return ret; filter = ixgbe_5tuple_filter_lookup(&filter_info->fivetuple_list, &filter_5tuple); if (filter == NULL) { PMD_DRV_LOG(ERR, "filter doesn't exist."); return -ENOENT; } ntuple_filter->queue = filter->queue; return 0; } /* * ixgbe_ntuple_filter_handle - Handle operations for ntuple filter. * @dev: pointer to rte_eth_dev structure * @filter_op:operation will be taken. * @arg: a pointer to specific structure corresponding to the filter_op * * @return * - On success, zero. * - On failure, a negative value. */ static int ixgbe_ntuple_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP_EXT(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = ixgbe_add_del_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = ixgbe_add_del_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = ixgbe_get_ntuple_filter(dev, (struct rte_eth_ntuple_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); ret = -EINVAL; break; } return ret; } static inline int ixgbe_ethertype_filter_lookup(struct ixgbe_filter_info *filter_info, uint16_t ethertype) { int i; for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) { if (filter_info->ethertype_filters[i] == ethertype && (filter_info->ethertype_mask & (1 << i))) return i; } return -1; } static inline int ixgbe_ethertype_filter_insert(struct ixgbe_filter_info *filter_info, uint16_t ethertype) { int i; for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) { if (!(filter_info->ethertype_mask & (1 << i))) { filter_info->ethertype_mask |= 1 << i; filter_info->ethertype_filters[i] = ethertype; return i; } } return -1; } static inline int ixgbe_ethertype_filter_remove(struct ixgbe_filter_info *filter_info, uint8_t idx) { if (idx >= IXGBE_MAX_ETQF_FILTERS) return -1; filter_info->ethertype_mask &= ~(1 << idx); filter_info->ethertype_filters[idx] = 0; return idx; } static int ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter, bool add) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); uint32_t etqf = 0; uint32_t etqs = 0; int ret; if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM) return -EINVAL; if (filter->ether_type == ETHER_TYPE_IPv4 || filter->ether_type == ETHER_TYPE_IPv6) { PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in" " ethertype filter.", filter->ether_type); return -EINVAL; } if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) { PMD_DRV_LOG(ERR, "mac compare is unsupported."); return -EINVAL; } if (filter->flags & RTE_ETHTYPE_FLAGS_DROP) { PMD_DRV_LOG(ERR, "drop option is unsupported."); return -EINVAL; } ret = ixgbe_ethertype_filter_lookup(filter_info, filter->ether_type); if (ret >= 0 && add) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter exists.", filter->ether_type); return -EEXIST; } if (ret < 0 && !add) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", filter->ether_type); return -ENOENT; } if (add) { ret = ixgbe_ethertype_filter_insert(filter_info, filter->ether_type); if (ret < 0) { PMD_DRV_LOG(ERR, "ethertype filters are full."); return -ENOSYS; } etqf = IXGBE_ETQF_FILTER_EN; etqf |= (uint32_t)filter->ether_type; etqs |= (uint32_t)((filter->queue << IXGBE_ETQS_RX_QUEUE_SHIFT) & IXGBE_ETQS_RX_QUEUE); etqs |= IXGBE_ETQS_QUEUE_EN; } else { ret = ixgbe_ethertype_filter_remove(filter_info, (uint8_t)ret); if (ret < 0) return -ENOSYS; } IXGBE_WRITE_REG(hw, IXGBE_ETQF(ret), etqf); IXGBE_WRITE_REG(hw, IXGBE_ETQS(ret), etqs); IXGBE_WRITE_FLUSH(hw); return 0; } static int ixgbe_get_ethertype_filter(struct rte_eth_dev *dev, struct rte_eth_ethertype_filter *filter) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_filter_info *filter_info = IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); uint32_t etqf, etqs; int ret; ret = ixgbe_ethertype_filter_lookup(filter_info, filter->ether_type); if (ret < 0) { PMD_DRV_LOG(ERR, "ethertype (0x%04x) filter doesn't exist.", filter->ether_type); return -ENOENT; } etqf = IXGBE_READ_REG(hw, IXGBE_ETQF(ret)); if (etqf & IXGBE_ETQF_FILTER_EN) { etqs = IXGBE_READ_REG(hw, IXGBE_ETQS(ret)); filter->ether_type = etqf & IXGBE_ETQF_ETHERTYPE; filter->flags = 0; filter->queue = (etqs & IXGBE_ETQS_RX_QUEUE) >> IXGBE_ETQS_RX_QUEUE_SHIFT; return 0; } return -ENOENT; } /* * ixgbe_ethertype_filter_handle - Handle operations for ethertype filter. * @dev: pointer to rte_eth_dev structure * @filter_op:operation will be taken. * @arg: a pointer to specific structure corresponding to the filter_op */ static int ixgbe_ethertype_filter_handle(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret; MAC_TYPE_FILTER_SUP(hw->mac.type); if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL) { PMD_DRV_LOG(ERR, "arg shouldn't be NULL for operation %u.", filter_op); return -EINVAL; } switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = ixgbe_add_del_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = ixgbe_add_del_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg, FALSE); break; case RTE_ETH_FILTER_GET: ret = ixgbe_get_ethertype_filter(dev, (struct rte_eth_ethertype_filter *)arg); break; default: PMD_DRV_LOG(ERR, "unsupported operation %u.", filter_op); ret = -EINVAL; break; } return ret; } static int ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg) { int ret = -EINVAL; switch (filter_type) { case RTE_ETH_FILTER_NTUPLE: ret = ixgbe_ntuple_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_ETHERTYPE: ret = ixgbe_ethertype_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_SYN: ret = ixgbe_syn_filter_handle(dev, filter_op, arg); break; case RTE_ETH_FILTER_FDIR: ret = ixgbe_fdir_ctrl_func(dev, filter_op, arg); break; default: PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", filter_type); break; } return ret; } static u8 * ixgbe_dev_addr_list_itr(__attribute__((unused)) struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq) { u8 *mc_addr; *vmdq = 0; mc_addr = *mc_addr_ptr; *mc_addr_ptr = (mc_addr + sizeof(struct ether_addr)); return mc_addr; } static int ixgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct ixgbe_hw *hw; u8 *mc_addr_list; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); mc_addr_list = (u8 *)mc_addr_set; return ixgbe_update_mc_addr_list(hw, mc_addr_list, nb_mc_addr, ixgbe_dev_addr_list_itr, TRUE); } static int ixgbe_timesync_enable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_ctl; uint32_t tsauxc; /* Enable system time for platforms where it isn't on by default. */ tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC); tsauxc &= ~IXGBE_TSAUXC_DISABLE_SYSTIME; IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); /* Start incrementing the register used to timestamp PTP packets. */ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, IXGBE_TIMINCA_INIT); /* Enable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), (ETHER_TYPE_1588 | IXGBE_ETQF_FILTER_EN | IXGBE_ETQF_1588)); /* Enable timestamping of received PTP packets. */ tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); tsync_ctl |= IXGBE_TSYNCRXCTL_ENABLED; IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, tsync_ctl); /* Enable timestamping of transmitted PTP packets. */ tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); tsync_ctl |= IXGBE_TSYNCTXCTL_ENABLED; IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl); return 0; } static int ixgbe_timesync_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_ctl; /* Disable timestamping of transmitted PTP packets. */ tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); tsync_ctl &= ~IXGBE_TSYNCTXCTL_ENABLED; IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, tsync_ctl); /* Disable timestamping of received PTP packets. */ tsync_ctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); tsync_ctl &= ~IXGBE_TSYNCRXCTL_ENABLED; IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, tsync_ctl); /* Disable L2 filtering of IEEE1588/802.1AS Ethernet frame types. */ IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0); /* Stop incrementating the System Time registers. */ IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, 0); return 0; } static int ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags __rte_unused) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_rxctl; uint32_t rx_stmpl; uint32_t rx_stmph; tsync_rxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); if ((tsync_rxctl & IXGBE_TSYNCRXCTL_VALID) == 0) return -EINVAL; rx_stmpl = IXGBE_READ_REG(hw, IXGBE_RXSTMPL); rx_stmph = IXGBE_READ_REG(hw, IXGBE_RXSTMPH); timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); timestamp->tv_nsec = 0; return 0; } static int ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev, struct timespec *timestamp) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t tsync_txctl; uint32_t tx_stmpl; uint32_t tx_stmph; tsync_txctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); if ((tsync_txctl & IXGBE_TSYNCTXCTL_VALID) == 0) return -EINVAL; tx_stmpl = IXGBE_READ_REG(hw, IXGBE_TXSTMPL); tx_stmph = IXGBE_READ_REG(hw, IXGBE_TXSTMPH); timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); timestamp->tv_nsec = 0; return 0; } static int ixgbe_get_reg_length(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int count = 0; int g_ind = 0; const struct reg_info *reg_group; const struct reg_info **reg_set = (hw->mac.type == ixgbe_mac_82598EB) ? ixgbe_regs_mac_82598EB : ixgbe_regs_others; while ((reg_group = reg_set[g_ind++])) count += ixgbe_regs_group_count(reg_group); return count; } static int ixgbevf_get_reg_length(struct rte_eth_dev *dev __rte_unused) { int count = 0; int g_ind = 0; const struct reg_info *reg_group; while ((reg_group = ixgbevf_regs[g_ind++])) count += ixgbe_regs_group_count(reg_group); return count; } static int ixgbe_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *data = regs->data; int g_ind = 0; int count = 0; const struct reg_info *reg_group; const struct reg_info **reg_set = (hw->mac.type == ixgbe_mac_82598EB) ? ixgbe_regs_mac_82598EB : ixgbe_regs_others; /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)ixgbe_get_reg_length(dev))) { regs->version = hw->mac.type << 24 | hw->revision_id << 16 | hw->device_id; while ((reg_group = reg_set[g_ind++])) count += ixgbe_read_regs_group(dev, &data[count], reg_group); return 0; } return -ENOTSUP; } static int ixgbevf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t *data = regs->data; int g_ind = 0; int count = 0; const struct reg_info *reg_group; /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)ixgbevf_get_reg_length(dev))) { regs->version = hw->mac.type << 24 | hw->revision_id << 16 | hw->device_id; while ((reg_group = ixgbevf_regs[g_ind++])) count += ixgbe_read_regs_group(dev, &data[count], reg_group); return 0; } return -ENOTSUP; } static int ixgbe_get_eeprom_length(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Return unit is byte count */ return hw->eeprom.word_size * 2; } static int ixgbe_get_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *in_eeprom) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_eeprom_info *eeprom = &hw->eeprom; uint16_t *data = in_eeprom->data; int first, length; first = in_eeprom->offset >> 1; length = in_eeprom->length >> 1; if ((first >= hw->eeprom.word_size) || ((first + length) >= hw->eeprom.word_size)) return -EINVAL; in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); return eeprom->ops.read_buffer(hw, first, length, data); } static int ixgbe_set_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *in_eeprom) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_eeprom_info *eeprom = &hw->eeprom; uint16_t *data = in_eeprom->data; int first, length; first = in_eeprom->offset >> 1; length = in_eeprom->length >> 1; if ((first >= hw->eeprom.word_size) || ((first + length) >= hw->eeprom.word_size)) return -EINVAL; in_eeprom->magic = hw->vendor_id | (hw->device_id << 16); return eeprom->ops.write_buffer(hw, first, length, data); } static struct rte_driver rte_ixgbe_driver = { .type = PMD_PDEV, .init = rte_ixgbe_pmd_init, }; static struct rte_driver rte_ixgbevf_driver = { .type = PMD_PDEV, .init = rte_ixgbevf_pmd_init, }; PMD_REGISTER_DRIVER(rte_ixgbe_driver); PMD_REGISTER_DRIVER(rte_ixgbevf_driver); ================================================ FILE: drivers/net/ixgbe/ixgbe_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_ETHDEV_H_ #define _IXGBE_ETHDEV_H_ #include "base/ixgbe_dcb.h" #include "base/ixgbe_dcb_82599.h" #include "base/ixgbe_dcb_82598.h" #include "ixgbe_bypass.h" /* need update link, bit flag */ #define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) #define IXGBE_FLAG_MAILBOX (uint32_t)(1 << 1) /* * Defines that were not part of ixgbe_type.h as they are not used by the * FreeBSD driver. */ #define IXGBE_ADVTXD_MAC_1588 0x00080000 /* IEEE1588 Timestamp packet */ #define IXGBE_RXD_STAT_TMST 0x10000 /* Timestamped Packet indication */ #define IXGBE_ADVTXD_TUCMD_L4T_RSV 0x00001800 /* L4 Packet TYPE, resvd */ #define IXGBE_RXDADV_ERR_CKSUM_BIT 30 #define IXGBE_RXDADV_ERR_CKSUM_MSK 3 #define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Bit shift for l2_len */ #define IXGBE_NB_STAT_MAPPING_REGS 32 #define IXGBE_EXTENDED_VLAN (uint32_t)(1 << 26) /* EXTENDED VLAN ENABLE */ #define IXGBE_VFTA_SIZE 128 #define IXGBE_VLAN_TAG_SIZE 4 #define IXGBE_MAX_RX_QUEUE_NUM 128 #ifndef NBBY #define NBBY 8 /* number of bits in a byte */ #endif #define IXGBE_HWSTRIP_BITMAP_SIZE (IXGBE_MAX_RX_QUEUE_NUM / (sizeof(uint32_t) * NBBY)) /* EITR Inteval is in 2048ns uinits for 1G and 10G link */ #define IXGBE_EITR_INTERVAL_UNIT_NS 2048 #define IXGBE_EITR_ITR_INT_SHIFT 3 #define IXGBE_EITR_INTERVAL_US(us) \ (((us) * 1000 / IXGBE_EITR_INTERVAL_UNIT_NS << IXGBE_EITR_ITR_INT_SHIFT) & \ IXGBE_EITR_ITR_INT_MASK) /* Loopback operation modes */ /* 82599 specific loopback operation types */ #define IXGBE_LPBK_82599_NONE 0x0 /* Default value. Loopback is disabled. */ #define IXGBE_LPBK_82599_TX_RX 0x1 /* Tx->Rx loopback operation is enabled. */ #define IXGBE_MAX_JUMBO_FRAME_SIZE 0x2600 /* Maximum Jumbo frame size. */ #define IXGBE_RTTBCNRC_RF_INT_MASK_BASE 0x000003FF #define IXGBE_RTTBCNRC_RF_INT_MASK_M \ (IXGBE_RTTBCNRC_RF_INT_MASK_BASE << IXGBE_RTTBCNRC_RF_INT_SHIFT) #define IXGBE_MAX_QUEUE_NUM_PER_VF 8 #define IXGBE_SYN_FILTER_ENABLE 0x00000001 /* syn filter enable field */ #define IXGBE_SYN_FILTER_QUEUE 0x000000FE /* syn filter queue field */ #define IXGBE_SYN_FILTER_QUEUE_SHIFT 1 /* syn filter queue field shift */ #define IXGBE_SYN_FILTER_SYNQFP 0x80000000 /* syn filter SYNQFP */ #define IXGBE_ETQF_UP 0x00070000 /* ethertype filter priority field */ #define IXGBE_ETQF_SHIFT 16 #define IXGBE_ETQF_UP_EN 0x00080000 #define IXGBE_ETQF_ETHERTYPE 0x0000FFFF /* ethertype filter ethertype field */ #define IXGBE_ETQF_MAX_PRI 7 #define IXGBE_SDPQF_DSTPORT 0xFFFF0000 /* dst port field */ #define IXGBE_SDPQF_DSTPORT_SHIFT 16 /* dst port field shift */ #define IXGBE_SDPQF_SRCPORT 0x0000FFFF /* src port field */ #define IXGBE_L34T_IMIR_SIZE_BP 0x00001000 #define IXGBE_L34T_IMIR_RESERVE 0x00080000 /* bit 13 to 19 must be set to 1000000b. */ #define IXGBE_L34T_IMIR_LLI 0x00100000 #define IXGBE_L34T_IMIR_QUEUE 0x0FE00000 #define IXGBE_L34T_IMIR_QUEUE_SHIFT 21 #define IXGBE_5TUPLE_MAX_PRI 7 #define IXGBE_5TUPLE_MIN_PRI 1 #define IXGBE_RSS_OFFLOAD_ALL ( \ ETH_RSS_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_NONFRAG_IPV4_UDP | \ ETH_RSS_IPV6 | \ ETH_RSS_NONFRAG_IPV6_TCP | \ ETH_RSS_NONFRAG_IPV6_UDP | \ ETH_RSS_IPV6_EX | \ ETH_RSS_IPV6_TCP_EX | \ ETH_RSS_IPV6_UDP_EX) #define IXGBE_VF_IRQ_ENABLE_MASK 3 /* vf irq enable mask */ #define IXGBE_VF_MAXMSIVECTOR 1 /* * Information about the fdir mode. */ struct ixgbe_hw_fdir_mask { uint16_t vlan_tci_mask; uint32_t src_ipv4_mask; uint32_t dst_ipv4_mask; uint16_t src_ipv6_mask; uint16_t dst_ipv6_mask; uint16_t src_port_mask; uint16_t dst_port_mask; uint16_t flex_bytes_mask; }; struct ixgbe_hw_fdir_info { struct ixgbe_hw_fdir_mask mask; uint8_t flex_bytes_offset; uint16_t collision; uint16_t free; uint16_t maxhash; uint8_t maxlen; uint64_t add; uint64_t remove; uint64_t f_add; uint64_t f_remove; }; /* structure for interrupt relative data */ struct ixgbe_interrupt { uint32_t flags; uint32_t mask; }; struct ixgbe_stat_mapping_registers { uint32_t tqsm[IXGBE_NB_STAT_MAPPING_REGS]; uint32_t rqsmr[IXGBE_NB_STAT_MAPPING_REGS]; }; struct ixgbe_vfta { uint32_t vfta[IXGBE_VFTA_SIZE]; }; struct ixgbe_hwstrip { uint32_t bitmap[IXGBE_HWSTRIP_BITMAP_SIZE]; }; /* * VF data which used by PF host only */ #define IXGBE_MAX_VF_MC_ENTRIES 30 #define IXGBE_MAX_MR_RULE_ENTRIES 4 /* number of mirroring rules supported */ #define IXGBE_MAX_UTA 128 struct ixgbe_uta_info { uint8_t uc_filter_type; uint16_t uta_in_use; uint32_t uta_shadow[IXGBE_MAX_UTA]; }; #define IXGBE_MAX_MIRROR_RULES 4 /* Maximum nb. of mirror rules. */ struct ixgbe_mirror_info { struct rte_eth_mirror_conf mr_conf[IXGBE_MAX_MIRROR_RULES]; /**< store PF mirror rules configuration*/ }; struct ixgbe_vf_info { uint8_t vf_mac_addresses[ETHER_ADDR_LEN]; uint16_t vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES]; uint16_t num_vf_mc_hashes; uint16_t default_vf_vlan_id; uint16_t vlans_enabled; bool clear_to_send; uint16_t tx_rate[IXGBE_MAX_QUEUE_NUM_PER_VF]; uint16_t vlan_count; uint8_t spoofchk_enabled; uint8_t api_version; }; /* * Possible l4type of 5tuple filters. */ enum ixgbe_5tuple_protocol { IXGBE_FILTER_PROTOCOL_TCP = 0, IXGBE_FILTER_PROTOCOL_UDP, IXGBE_FILTER_PROTOCOL_SCTP, IXGBE_FILTER_PROTOCOL_NONE, }; TAILQ_HEAD(ixgbe_5tuple_filter_list, ixgbe_5tuple_filter); struct ixgbe_5tuple_filter_info { uint32_t dst_ip; uint32_t src_ip; uint16_t dst_port; uint16_t src_port; enum ixgbe_5tuple_protocol proto; /* l4 protocol. */ uint8_t priority; /* seven levels (001b-111b), 111b is highest, used when more than one filter matches. */ uint8_t dst_ip_mask:1, /* if mask is 1b, do not compare dst ip. */ src_ip_mask:1, /* if mask is 1b, do not compare src ip. */ dst_port_mask:1, /* if mask is 1b, do not compare dst port. */ src_port_mask:1, /* if mask is 1b, do not compare src port. */ proto_mask:1; /* if mask is 1b, do not compare protocol. */ }; /* 5tuple filter structure */ struct ixgbe_5tuple_filter { TAILQ_ENTRY(ixgbe_5tuple_filter) entries; uint16_t index; /* the index of 5tuple filter */ struct ixgbe_5tuple_filter_info filter_info; uint16_t queue; /* rx queue assigned to */ }; #define IXGBE_5TUPLE_ARRAY_SIZE \ (RTE_ALIGN(IXGBE_MAX_FTQF_FILTERS, (sizeof(uint32_t) * NBBY)) / \ (sizeof(uint32_t) * NBBY)) /* * Structure to store filters' info. */ struct ixgbe_filter_info { uint8_t ethertype_mask; /* Bit mask for every used ethertype filter */ /* store used ethertype filters*/ uint16_t ethertype_filters[IXGBE_MAX_ETQF_FILTERS]; /* Bit mask for every used 5tuple filter */ uint32_t fivetuple_mask[IXGBE_5TUPLE_ARRAY_SIZE]; struct ixgbe_5tuple_filter_list fivetuple_list; }; /* * Structure to store private data for each driver instance (for each port). */ struct ixgbe_adapter { struct ixgbe_hw hw; struct ixgbe_hw_stats stats; struct ixgbe_hw_fdir_info fdir; struct ixgbe_interrupt intr; struct ixgbe_stat_mapping_registers stat_mappings; struct ixgbe_vfta shadow_vfta; struct ixgbe_hwstrip hwstrip; struct ixgbe_dcb_config dcb_config; struct ixgbe_mirror_info mr_data; struct ixgbe_vf_info *vfdata; struct ixgbe_uta_info uta_info; #ifdef RTE_NIC_BYPASS struct ixgbe_bypass_info bps; #endif /* RTE_NIC_BYPASS */ struct ixgbe_filter_info filter; bool rx_bulk_alloc_allowed; bool rx_vec_allowed; }; #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\ (&((struct ixgbe_adapter *)adapter)->hw) #define IXGBE_DEV_PRIVATE_TO_STATS(adapter) \ (&((struct ixgbe_adapter *)adapter)->stats) #define IXGBE_DEV_PRIVATE_TO_INTR(adapter) \ (&((struct ixgbe_adapter *)adapter)->intr) #define IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter) \ (&((struct ixgbe_adapter *)adapter)->fdir) #define IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(adapter) \ (&((struct ixgbe_adapter *)adapter)->stat_mappings) #define IXGBE_DEV_PRIVATE_TO_VFTA(adapter) \ (&((struct ixgbe_adapter *)adapter)->shadow_vfta) #define IXGBE_DEV_PRIVATE_TO_HWSTRIP_BITMAP(adapter) \ (&((struct ixgbe_adapter *)adapter)->hwstrip) #define IXGBE_DEV_PRIVATE_TO_DCB_CFG(adapter) \ (&((struct ixgbe_adapter *)adapter)->dcb_config) #define IXGBE_DEV_PRIVATE_TO_P_VFDATA(adapter) \ (&((struct ixgbe_adapter *)adapter)->vfdata) #define IXGBE_DEV_PRIVATE_TO_PFDATA(adapter) \ (&((struct ixgbe_adapter *)adapter)->mr_data) #define IXGBE_DEV_PRIVATE_TO_UTA(adapter) \ (&((struct ixgbe_adapter *)adapter)->uta_info) #define IXGBE_DEV_PRIVATE_TO_FILTER_INFO(adapter) \ (&((struct ixgbe_adapter *)adapter)->filter) /* * RX/TX function prototypes */ void ixgbe_dev_clear_queues(struct rte_eth_dev *dev); void ixgbe_dev_free_queues(struct rte_eth_dev *dev); void ixgbe_dev_rx_queue_release(void *rxq); void ixgbe_dev_tx_queue_release(void *txq); int ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); int ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id); int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset); int ixgbevf_dev_rx_descriptor_done(void *rx_queue, uint16_t offset); int ixgbe_dev_rx_init(struct rte_eth_dev *dev); void ixgbe_dev_tx_init(struct rte_eth_dev *dev); int ixgbe_dev_rxtx_start(struct rte_eth_dev *dev); int ixgbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id); int ixgbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id); int ixgbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id); int ixgbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id); int ixgbevf_dev_rx_init(struct rte_eth_dev *dev); void ixgbevf_dev_tx_init(struct rte_eth_dev *dev); void ixgbevf_dev_rxtx_start(struct rte_eth_dev *dev); uint16_t ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t ixgbe_recv_pkts_lro_single_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t ixgbe_recv_pkts_lro_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int ixgbe_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); int ixgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); /* * Flow director function prototypes */ int ixgbe_fdir_configure(struct rte_eth_dev *dev); void ixgbe_configure_dcb(struct rte_eth_dev *dev); /* * misc function prototypes */ void ixgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev); void ixgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev); void ixgbe_vlan_hw_strip_enable_all(struct rte_eth_dev *dev); void ixgbe_vlan_hw_strip_disable_all(struct rte_eth_dev *dev); void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev); void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev); void ixgbe_pf_mbx_process(struct rte_eth_dev *eth_dev); int ixgbe_pf_host_configure(struct rte_eth_dev *eth_dev); uint32_t ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val); int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); #endif /* _IXGBE_ETHDEV_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_fdir.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "ixgbe_logs.h" #include "base/ixgbe_api.h" #include "base/ixgbe_common.h" #include "ixgbe_ethdev.h" /* To get PBALLOC (Packet Buffer Allocation) bits from FDIRCTRL value */ #define FDIRCTRL_PBALLOC_MASK 0x03 /* For calculating memory required for FDIR filters */ #define PBALLOC_SIZE_SHIFT 15 /* Number of bits used to mask bucket hash for different pballoc sizes */ #define PERFECT_BUCKET_64KB_HASH_MASK 0x07FF /* 11 bits */ #define PERFECT_BUCKET_128KB_HASH_MASK 0x0FFF /* 12 bits */ #define PERFECT_BUCKET_256KB_HASH_MASK 0x1FFF /* 13 bits */ #define SIG_BUCKET_64KB_HASH_MASK 0x1FFF /* 13 bits */ #define SIG_BUCKET_128KB_HASH_MASK 0x3FFF /* 14 bits */ #define SIG_BUCKET_256KB_HASH_MASK 0x7FFF /* 15 bits */ #define IXGBE_DEFAULT_FLEXBYTES_OFFSET 12 /* default flexbytes offset in bytes */ #define IXGBE_FDIR_MAX_FLEX_LEN 2 /* len in bytes of flexbytes */ #define IXGBE_MAX_FLX_SOURCE_OFF 62 #define IXGBE_FDIRCTRL_FLEX_MASK (0x1F << IXGBE_FDIRCTRL_FLEX_SHIFT) #define IXGBE_FDIRCMD_CMD_INTERVAL_US 10 #define IXGBE_FDIR_FLOW_TYPES ( \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER)) #define IPV6_ADDR_TO_MASK(ipaddr, ipv6m) do { \ uint8_t ipv6_addr[16]; \ uint8_t i; \ rte_memcpy(ipv6_addr, (ipaddr), sizeof(ipv6_addr));\ (ipv6m) = 0; \ for (i = 0; i < sizeof(ipv6_addr); i++) { \ if (ipv6_addr[i] == UINT8_MAX) \ (ipv6m) |= 1 << i; \ else if (ipv6_addr[i] != 0) { \ PMD_DRV_LOG(ERR, " invalid IPv6 address mask."); \ return -EINVAL; \ } \ } \ } while (0) #define IPV6_MASK_TO_ADDR(ipv6m, ipaddr) do { \ uint8_t ipv6_addr[16]; \ uint8_t i; \ for (i = 0; i < sizeof(ipv6_addr); i++) { \ if ((ipv6m) & (1 << i)) \ ipv6_addr[i] = UINT8_MAX; \ else \ ipv6_addr[i] = 0; \ } \ rte_memcpy((ipaddr), ipv6_addr, sizeof(ipv6_addr));\ } while (0) static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash); static int fdir_set_input_mask_82599(struct rte_eth_dev *dev, const struct rte_eth_fdir_masks *input_mask); static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl); static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl); static int ixgbe_fdir_filter_to_atr_input( const struct rte_eth_fdir_filter *fdir_filter, union ixgbe_atr_input *input); static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input, uint32_t key); static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input, enum rte_fdir_pballoc_type pballoc); static uint32_t atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, enum rte_fdir_pballoc_type pballoc); static int fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, uint8_t queue, uint32_t fdircmd, uint32_t fdirhash); static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd, uint32_t fdirhash); static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev, const struct rte_eth_fdir_filter *fdir_filter, bool del, bool update); static int ixgbe_fdir_flush(struct rte_eth_dev *dev); static void ixgbe_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info); static void ixgbe_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *fdir_stats); /** * This function is based on ixgbe_fdir_enable_82599() in base/ixgbe_82599.c. * It adds extra configuration of fdirctrl that is common for all filter types. * * Initialize Flow Director control registers * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register **/ static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl) { int i; PMD_INIT_FUNC_TRACE(); /* Prime the keys for hashing */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY); IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY); /* * Continue setup of fdirctrl register bits: * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 filters are left */ fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); /* * Poll init-done after we write the register. Estimated times: * 10G: PBALLOC = 11b, timing is 60us * 1G: PBALLOC = 11b, timing is 600us * 100M: PBALLOC = 11b, timing is 6ms * * Multiple these timings by 4 if under full Rx load * * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for * 1 msec per poll time. If we're at line rate and drop to 100M, then * this might not finish in our poll time, but we can live with that * for now. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); IXGBE_WRITE_FLUSH(hw); for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; msec_delay(1); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) { PMD_INIT_LOG(ERR, "Flow Director poll time exceeded " "during enabling!"); return -ETIMEDOUT; } return 0; } /* * Set appropriate bits in fdirctrl for: variable reporting levels, moving * flexbytes matching field, and drop queue (only for perfect matching mode). */ static inline int configure_fdir_flags(const struct rte_fdir_conf *conf, uint32_t *fdirctrl) { *fdirctrl = 0; switch (conf->pballoc) { case RTE_FDIR_PBALLOC_64K: /* 8k - 1 signature filters */ *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K; break; case RTE_FDIR_PBALLOC_128K: /* 16k - 1 signature filters */ *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K; break; case RTE_FDIR_PBALLOC_256K: /* 32k - 1 signature filters */ *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K; break; default: /* bad value */ PMD_INIT_LOG(ERR, "Invalid fdir_conf->pballoc value"); return -EINVAL; }; /* status flags: write hash & swindex in the rx descriptor */ switch (conf->status) { case RTE_FDIR_NO_REPORT_STATUS: /* do nothing, default mode */ break; case RTE_FDIR_REPORT_STATUS: /* report status when the packet matches a fdir rule */ *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS; break; case RTE_FDIR_REPORT_STATUS_ALWAYS: /* always report status */ *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS; break; default: /* bad value */ PMD_INIT_LOG(ERR, "Invalid fdir_conf->status value"); return -EINVAL; }; *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) << IXGBE_FDIRCTRL_FLEX_SHIFT; if (conf->mode == RTE_FDIR_MODE_PERFECT) { *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH; *fdirctrl |= (conf->drop_queue << IXGBE_FDIRCTRL_DROP_Q_SHIFT); } return 0; } /** * Reverse the bits in FDIR registers that store 2 x 16 bit masks. * * @hi_dword: Bits 31:16 mask to be bit swapped. * @lo_dword: Bits 15:0 mask to be bit swapped. * * Flow director uses several registers to store 2 x 16 bit masks with the * bits reversed such as FDIRTCPM, FDIRUDPM. The LS bit of the * mask affects the MS bit/byte of the target. This function reverses the * bits in these masks. * **/ static inline uint32_t reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t lo_dword) { uint32_t mask = hi_dword << 16; mask |= lo_dword; mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); } /* * This is based on ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, * but makes use of the rte_fdir_masks structure to see which bits to set. */ static int fdir_set_input_mask_82599(struct rte_eth_dev *dev, const struct rte_eth_fdir_masks *input_mask) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); /* * mask VM pool and DIPv6 since there are currently not supported * mask FLEX byte, it will be set in flex_conf */ uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6 | IXGBE_FDIRM_FLEX; uint32_t fdirtcpm; /* TCP source and destination port masks. */ uint32_t fdiripv6m; /* IPv6 source and destination masks. */ uint16_t dst_ipv6m = 0; uint16_t src_ipv6m = 0; PMD_INIT_FUNC_TRACE(); /* * Program the relevant mask registers. If src/dst_port or src/dst_addr * are zero, then assume a full mask for that field. Also assume that * a VLAN of 0 is unspecified, so mask that out as well. L4type * cannot be masked out in this implementation. */ if (input_mask->dst_port_mask == 0 && input_mask->src_port_mask == 0) /* use the L4 protocol mask for raw IPv4/IPv6 traffic */ fdirm |= IXGBE_FDIRM_L4P; if (input_mask->vlan_tci_mask == 0x0FFF) /* mask VLAN Priority */ fdirm |= IXGBE_FDIRM_VLANP; else if (input_mask->vlan_tci_mask == 0xE000) /* mask VLAN ID */ fdirm |= IXGBE_FDIRM_VLANID; else if (input_mask->vlan_tci_mask == 0) /* mask VLAN ID and Priority */ fdirm |= IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP; else if (input_mask->vlan_tci_mask != 0xEFFF) { PMD_INIT_LOG(ERR, "invalid vlan_tci_mask"); return -EINVAL; } info->mask.vlan_tci_mask = input_mask->vlan_tci_mask; IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); /* store the TCP/UDP port masks, bit reversed from port layout */ fdirtcpm = reverse_fdir_bitmasks(input_mask->dst_port_mask, input_mask->src_port_mask); /* write all the same so that UDP, TCP and SCTP use the same mask */ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); info->mask.src_port_mask = input_mask->src_port_mask; info->mask.dst_port_mask = input_mask->dst_port_mask; /* Store source and destination IPv4 masks (big-endian) */ IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, ~(input_mask->ipv4_mask.src_ip)); IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, ~(input_mask->ipv4_mask.dst_ip)); info->mask.src_ipv4_mask = input_mask->ipv4_mask.src_ip; info->mask.dst_ipv4_mask = input_mask->ipv4_mask.dst_ip; if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_SIGNATURE) { /* * IPv6 mask is only meaningful in signature mode * Store source and destination IPv6 masks (bit reversed) */ IPV6_ADDR_TO_MASK(input_mask->ipv6_mask.src_ip, src_ipv6m); IPV6_ADDR_TO_MASK(input_mask->ipv6_mask.dst_ip, dst_ipv6m); fdiripv6m = (dst_ipv6m << 16) | src_ipv6m; IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, ~fdiripv6m); info->mask.src_ipv6_mask = src_ipv6m; info->mask.dst_ipv6_mask = dst_ipv6m; } return IXGBE_SUCCESS; } /* * ixgbe_check_fdir_flex_conf -check if the flex payload and mask configuration * arguments are valid */ static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); const struct rte_eth_flex_payload_cfg *flex_cfg; const struct rte_eth_fdir_flex_mask *flex_mask; uint32_t fdirm; uint16_t flexbytes = 0; uint16_t i; fdirm = IXGBE_READ_REG(hw, IXGBE_FDIRM); if (conf == NULL) { PMD_DRV_LOG(ERR, "NULL pointer."); return -EINVAL; } for (i = 0; i < conf->nb_payloads; i++) { flex_cfg = &conf->flex_set[i]; if (flex_cfg->type != RTE_ETH_RAW_PAYLOAD) { PMD_DRV_LOG(ERR, "unsupported payload type."); return -EINVAL; } if (((flex_cfg->src_offset[0] & 0x1) == 0) && (flex_cfg->src_offset[1] == flex_cfg->src_offset[0] + 1) && (flex_cfg->src_offset[0] <= IXGBE_MAX_FLX_SOURCE_OFF)) { *fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK; *fdirctrl |= (flex_cfg->src_offset[0] / sizeof(uint16_t)) << IXGBE_FDIRCTRL_FLEX_SHIFT; } else { PMD_DRV_LOG(ERR, "invalid flexbytes arguments."); return -EINVAL; } } for (i = 0; i < conf->nb_flexmasks; i++) { flex_mask = &conf->flex_mask[i]; if (flex_mask->flow_type != RTE_ETH_FLOW_UNKNOWN) { PMD_DRV_LOG(ERR, "flexmask should be set globally."); return -EINVAL; } flexbytes = (uint16_t)(((flex_mask->mask[0] << 8) & 0xFF00) | ((flex_mask->mask[1]) & 0xFF)); if (flexbytes == UINT16_MAX) fdirm &= ~IXGBE_FDIRM_FLEX; else if (flexbytes != 0) { /* IXGBE_FDIRM_FLEX is set by default when set mask */ PMD_DRV_LOG(ERR, " invalid flexbytes mask arguments."); return -EINVAL; } } IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); info->mask.flex_bytes_mask = flexbytes ? UINT16_MAX : 0; info->flex_bytes_offset = (uint8_t)((*fdirctrl & IXGBE_FDIRCTRL_FLEX_MASK) >> IXGBE_FDIRCTRL_FLEX_SHIFT); return 0; } int ixgbe_fdir_configure(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int err; uint32_t fdirctrl, pbsize; int i; PMD_INIT_FUNC_TRACE(); if (hw->mac.type != ixgbe_mac_82599EB && hw->mac.type != ixgbe_mac_X540 && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x) return -ENOSYS; err = configure_fdir_flags(&dev->data->dev_conf.fdir_conf, &fdirctrl); if (err) return err; /* * Before enabling Flow Director, the Rx Packet Buffer size * must be reduced. The new value is the current size minus * flow director memory usage size. */ pbsize = (1 << (PBALLOC_SIZE_SHIFT + (fdirctrl & FDIRCTRL_PBALLOC_MASK))); IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize)); /* * The defaults in the HW for RX PB 1-7 are not zero and so should be * intialized to zero for non DCB mode otherwise actual total RX PB * would be bigger than programmed and filter space would run into * the PB 0 region. */ for (i = 1; i < 8; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); err = fdir_set_input_mask_82599(dev, &dev->data->dev_conf.fdir_conf.mask); if (err < 0) { PMD_INIT_LOG(ERR, " Error on setting FD mask"); return err; } err = ixgbe_set_fdir_flex_conf(dev, &dev->data->dev_conf.fdir_conf.flex_conf, &fdirctrl); if (err < 0) { PMD_INIT_LOG(ERR, " Error on setting FD flexible arguments."); return err; } err = fdir_enable_82599(hw, fdirctrl); if (err < 0) { PMD_INIT_LOG(ERR, " Error on enabling FD."); return err; } return 0; } /* * Convert DPDK rte_eth_fdir_filter struct to ixgbe_atr_input union that is used * by the IXGBE driver code. */ static int ixgbe_fdir_filter_to_atr_input(const struct rte_eth_fdir_filter *fdir_filter, union ixgbe_atr_input *input) { input->formatted.vlan_id = fdir_filter->input.flow_ext.vlan_tci; input->formatted.flex_bytes = (uint16_t)( (fdir_filter->input.flow_ext.flexbytes[1] << 8 & 0xFF00) | (fdir_filter->input.flow_ext.flexbytes[0] & 0xFF)); switch (fdir_filter->input.flow_type) { case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; break; case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; break; case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; break; case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4; break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV6; break; case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6; break; case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV6; break; case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV6; break; default: PMD_DRV_LOG(ERR, " Error on flow_type input"); return -EINVAL; } switch (fdir_filter->input.flow_type) { case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: input->formatted.src_port = fdir_filter->input.flow.udp4_flow.src_port; input->formatted.dst_port = fdir_filter->input.flow.udp4_flow.dst_port; /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/ case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: input->formatted.src_ip[0] = fdir_filter->input.flow.ip4_flow.src_ip; input->formatted.dst_ip[0] = fdir_filter->input.flow.ip4_flow.dst_ip; break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: input->formatted.src_port = fdir_filter->input.flow.udp6_flow.src_port; input->formatted.dst_port = fdir_filter->input.flow.udp6_flow.dst_port; /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/ case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: rte_memcpy(input->formatted.src_ip, fdir_filter->input.flow.ipv6_flow.src_ip, sizeof(input->formatted.src_ip)); rte_memcpy(input->formatted.dst_ip, fdir_filter->input.flow.ipv6_flow.dst_ip, sizeof(input->formatted.dst_ip)); break; default: PMD_DRV_LOG(ERR, " Error on flow_type input"); return -EINVAL; } return 0; } /* * The below function is taken from the FreeBSD IXGBE drivers release * 2.3.8. The only change is not to mask hash_result with IXGBE_ATR_HASH_MASK * before returning, as the signature hash can use 16bits. * * The newer driver has optimised functions for calculating bucket and * signature hashes. However they don't support IPv6 type packets for signature * filters so are not used here. * * Note that the bkt_hash field in the ixgbe_atr_input structure is also never * set. * * Compute the hashes for SW ATR * @stream: input bitstream to compute the hash on * @key: 32-bit hash key **/ static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input, uint32_t key) { /* * The algorithm is as follows: * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350 * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n] * and A[n] x B[n] is bitwise AND between same length strings * * K[n] is 16 bits, defined as: * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15] * for n modulo 32 < 15, K[n] = * K[(n % 32:0) | (31:31 - (14 - (n % 32)))] * * S[n] is 16 bits, defined as: * for n >= 15, S[n] = S[n:n - 15] * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))] * * To simplify for programming, the algorithm is implemented * in software this way: * * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0] * * for (i = 0; i < 352; i+=32) * hi_hash_dword[31:0] ^= Stream[(i+31):i]; * * lo_hash_dword[15:0] ^= Stream[15:0]; * lo_hash_dword[15:0] ^= hi_hash_dword[31:16]; * lo_hash_dword[31:16] ^= hi_hash_dword[15:0]; * * hi_hash_dword[31:0] ^= Stream[351:320]; * * if(key[0]) * hash[15:0] ^= Stream[15:0]; * * for (i = 0; i < 16; i++) { * if (key[i]) * hash[15:0] ^= lo_hash_dword[(i+15):i]; * if (key[i + 16]) * hash[15:0] ^= hi_hash_dword[(i+15):i]; * } * */ __be32 common_hash_dword = 0; u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; u32 hash_result = 0; u8 i; /* record the flow_vm_vlan bits as they are a key part to the hash */ flow_vm_vlan = IXGBE_NTOHL(atr_input->dword_stream[0]); /* generate common hash dword */ for (i = 1; i <= 13; i++) common_hash_dword ^= atr_input->dword_stream[i]; hi_hash_dword = IXGBE_NTOHL(common_hash_dword); /* low dword is word swapped version of common */ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); /* apply flow ID/VM pool/VLAN ID bits to hash words */ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); /* Process bits 0 and 16 */ if (key & 0x0001) hash_result ^= lo_hash_dword; if (key & 0x00010000) hash_result ^= hi_hash_dword; /* * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to * delay this because bit 0 of the stream should not be processed * so we do not add the vlan until after bit 0 was processed */ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); /* process the remaining 30 bits in the key 2 bits at a time */ for (i = 15; i; i-- ) { if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i; if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i; } return hash_result; } static uint32_t atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, enum rte_fdir_pballoc_type pballoc) { if (pballoc == RTE_FDIR_PBALLOC_256K) return ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & PERFECT_BUCKET_256KB_HASH_MASK; else if (pballoc == RTE_FDIR_PBALLOC_128K) return ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & PERFECT_BUCKET_128KB_HASH_MASK; else return ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & PERFECT_BUCKET_64KB_HASH_MASK; } /** * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete * @hw: pointer to hardware structure */ static inline int ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, uint32_t *fdircmd) { int i; for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD); if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK)) return 0; rte_delay_us(IXGBE_FDIRCMD_CMD_INTERVAL_US); } return -ETIMEDOUT; } /* * Calculate the hash value needed for signature-match filters. In the FreeBSD * driver, this is done by the optimised function * ixgbe_atr_compute_sig_hash_82599(). However that can't be used here as it * doesn't support calculating a hash for an IPv6 filter. */ static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input, enum rte_fdir_pballoc_type pballoc) { uint32_t bucket_hash, sig_hash; if (pballoc == RTE_FDIR_PBALLOC_256K) bucket_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & SIG_BUCKET_256KB_HASH_MASK; else if (pballoc == RTE_FDIR_PBALLOC_128K) bucket_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & SIG_BUCKET_128KB_HASH_MASK; else bucket_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY) & SIG_BUCKET_64KB_HASH_MASK; sig_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_SIGNATURE_HASH_KEY); return (sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT) | bucket_hash; } /* * This is based on ixgbe_fdir_write_perfect_filter_82599() in * base/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register * added, and IPv6 support also added. The hash value is also pre-calculated * as the pballoc value is needed to do it. */ static int fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, uint8_t queue, uint32_t fdircmd, uint32_t fdirhash) { uint32_t fdirport, fdirvlan; int err = 0; /* record the IPv4 address (big-endian) */ IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]); IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]); /* record source and destination port (little-endian)*/ fdirport = IXGBE_NTOHS(input->formatted.dst_port); fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT; fdirport |= IXGBE_NTOHS(input->formatted.src_port); IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport); /* record vlan (little-endian) and flex_bytes(big-endian) */ fdirvlan = input->formatted.flex_bytes; fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT; fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id); IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan); /* configure FDIRHASH register */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* * flush all previous writes to make certain registers are * programmed prior to issuing the command */ IXGBE_WRITE_FLUSH(hw); /* configure FDIRCMD register */ fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; fdircmd |= (uint32_t)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err < 0) PMD_DRV_LOG(ERR, "Timeout writing flow director filter."); return err; } /** * This function is based on ixgbe_atr_add_signature_filter_82599() in * base/ixgbe_82599.c, but uses a pre-calculated hash value. It also supports * setting extra fields in the FDIRCMD register, and removes the code that was * verifying the flow_type field. According to the documentation, a flow type of * 00 (i.e. not TCP, UDP, or SCTP) is not supported, however it appears to * work ok... * * Adds a signature hash filter * @hw: pointer to hardware structure * @input: unique input dword * @queue: queue index to direct traffic to * @fdircmd: any extra flags to set in fdircmd register * @fdirhash: pre-calculated hash value for the filter **/ static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd, uint32_t fdirhash) { int err = 0; PMD_INIT_FUNC_TRACE(); /* configure FDIRCMD register */ fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err < 0) PMD_DRV_LOG(ERR, "Timeout writing flow director filter."); return err; } /* * This is based on ixgbe_fdir_erase_perfect_filter_82599() in * base/ixgbe_82599.c. It is modified to take in the hash as a parameter so * that it can be used for removing signature and perfect filters. */ static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash) { uint32_t fdircmd = 0; int err = 0; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* flush hash to HW */ IXGBE_WRITE_FLUSH(hw); /* Query if filter is present */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT); err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err < 0) { PMD_INIT_LOG(ERR, "Timeout querying for flow director filter."); return err; } /* if filter exists in hardware then remove it */ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) { IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_REMOVE_FLOW); } err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); if (err < 0) PMD_INIT_LOG(ERR, "Timeout erasing flow director filter."); return err; } /* * ixgbe_add_del_fdir_filter - add or remove a flow diretor filter. * @dev: pointer to the structure rte_eth_dev * @fdir_filter: fdir filter entry * @del: 1 - delete, 0 - add * @update: 1 - update */ static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev, const struct rte_eth_fdir_filter *fdir_filter, bool del, bool update) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t fdircmd_flags; uint32_t fdirhash; union ixgbe_atr_input input; uint8_t queue; bool is_perfect = FALSE; int err; struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_NONE) return -ENOTSUP; /* * Sanity check for x550. * When adding a new filter with flow type set to IPv4-other, * the flow director mask should be configed before, * and the L4 protocol and ports are masked. */ if ((!del) && (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X550EM_x) && (fdir_filter->input.flow_type == RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) && (info->mask.src_port_mask != 0 || info->mask.dst_port_mask != 0)) { PMD_DRV_LOG(ERR, "By this device," " IPv4-other is not supported without" " L4 protocol and ports masked!"); return -ENOTSUP; } if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) is_perfect = TRUE; memset(&input, 0, sizeof(input)); err = ixgbe_fdir_filter_to_atr_input(fdir_filter, &input); if (err) return err; if (is_perfect) { if (input.formatted.flow_type & IXGBE_ATR_L4TYPE_IPV6_MASK) { PMD_DRV_LOG(ERR, "IPv6 is not supported in" " perfect mode!"); return -ENOTSUP; } fdirhash = atr_compute_perfect_hash_82599(&input, dev->data->dev_conf.fdir_conf.pballoc); fdirhash |= fdir_filter->soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; } else fdirhash = atr_compute_sig_hash_82599(&input, dev->data->dev_conf.fdir_conf.pballoc); if (del) { err = fdir_erase_filter_82599(hw, fdirhash); if (err < 0) PMD_DRV_LOG(ERR, "Fail to delete FDIR filter!"); else PMD_DRV_LOG(DEBUG, "Success to delete FDIR filter!"); return err; } /* add or update an fdir filter*/ fdircmd_flags = (update) ? IXGBE_FDIRCMD_FILTER_UPDATE : 0; if (fdir_filter->action.behavior == RTE_ETH_FDIR_REJECT) { if (is_perfect) { queue = dev->data->dev_conf.fdir_conf.drop_queue; fdircmd_flags |= IXGBE_FDIRCMD_DROP; } else { PMD_DRV_LOG(ERR, "Drop option is not supported in" " signature mode."); return -EINVAL; } } else if (fdir_filter->action.rx_queue < IXGBE_MAX_RX_QUEUE_NUM) queue = (uint8_t)fdir_filter->action.rx_queue; else return -EINVAL; if (is_perfect) { err = fdir_write_perfect_filter_82599(hw, &input, queue, fdircmd_flags, fdirhash); } else { err = fdir_add_signature_filter_82599(hw, &input, queue, fdircmd_flags, fdirhash); } if (err < 0) PMD_DRV_LOG(ERR, "Fail to add FDIR filter!"); else PMD_DRV_LOG(DEBUG, "Success to add FDIR filter"); return err; } static int ixgbe_fdir_flush(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); int ret; ret = ixgbe_reinit_fdir_tables_82599(hw); if (ret < 0) { PMD_INIT_LOG(ERR, "Failed to re-initialize FD table."); return ret; } info->f_add = 0; info->f_remove = 0; info->add = 0; info->remove = 0; return ret; } #define FDIRENTRIES_NUM_SHIFT 10 static void ixgbe_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); uint32_t fdirctrl, max_num; uint8_t offset; fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); offset = ((fdirctrl & IXGBE_FDIRCTRL_FLEX_MASK) >> IXGBE_FDIRCTRL_FLEX_SHIFT) * sizeof(uint16_t); fdir_info->mode = dev->data->dev_conf.fdir_conf.mode; max_num = (1 << (FDIRENTRIES_NUM_SHIFT + (fdirctrl & FDIRCTRL_PBALLOC_MASK))); if (fdir_info->mode == RTE_FDIR_MODE_PERFECT) fdir_info->guarant_spc = max_num; else if (fdir_info->mode == RTE_FDIR_MODE_SIGNATURE) fdir_info->guarant_spc = max_num * 4; fdir_info->mask.vlan_tci_mask = info->mask.vlan_tci_mask; fdir_info->mask.ipv4_mask.src_ip = info->mask.src_ipv4_mask; fdir_info->mask.ipv4_mask.dst_ip = info->mask.dst_ipv4_mask; IPV6_MASK_TO_ADDR(info->mask.src_ipv6_mask, fdir_info->mask.ipv6_mask.src_ip); IPV6_MASK_TO_ADDR(info->mask.dst_ipv6_mask, fdir_info->mask.ipv6_mask.dst_ip); fdir_info->mask.src_port_mask = info->mask.src_port_mask; fdir_info->mask.dst_port_mask = info->mask.dst_port_mask; fdir_info->max_flexpayload = IXGBE_FDIR_MAX_FLEX_LEN; fdir_info->flow_types_mask[0] = IXGBE_FDIR_FLOW_TYPES; fdir_info->flex_payload_unit = sizeof(uint16_t); fdir_info->max_flex_payload_segment_num = 1; fdir_info->flex_payload_limit = 62; fdir_info->flex_conf.nb_payloads = 1; fdir_info->flex_conf.flex_set[0].type = RTE_ETH_RAW_PAYLOAD; fdir_info->flex_conf.flex_set[0].src_offset[0] = offset; fdir_info->flex_conf.flex_set[0].src_offset[1] = offset + 1; fdir_info->flex_conf.nb_flexmasks = 1; fdir_info->flex_conf.flex_mask[0].flow_type = RTE_ETH_FLOW_UNKNOWN; fdir_info->flex_conf.flex_mask[0].mask[0] = (uint8_t)(info->mask.flex_bytes_mask & 0x00FF); fdir_info->flex_conf.flex_mask[0].mask[1] = (uint8_t)((info->mask.flex_bytes_mask & 0xFF00) >> 8); } static void ixgbe_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *fdir_stats) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_hw_fdir_info *info = IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); uint32_t reg, max_num; /* Get the information from registers */ reg = IXGBE_READ_REG(hw, IXGBE_FDIRFREE); info->collision = (uint16_t)((reg & IXGBE_FDIRFREE_COLL_MASK) >> IXGBE_FDIRFREE_COLL_SHIFT); info->free = (uint16_t)((reg & IXGBE_FDIRFREE_FREE_MASK) >> IXGBE_FDIRFREE_FREE_SHIFT); reg = IXGBE_READ_REG(hw, IXGBE_FDIRLEN); info->maxhash = (uint16_t)((reg & IXGBE_FDIRLEN_MAXHASH_MASK) >> IXGBE_FDIRLEN_MAXHASH_SHIFT); info->maxlen = (uint8_t)((reg & IXGBE_FDIRLEN_MAXLEN_MASK) >> IXGBE_FDIRLEN_MAXLEN_SHIFT); reg = IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); info->remove += (reg & IXGBE_FDIRUSTAT_REMOVE_MASK) >> IXGBE_FDIRUSTAT_REMOVE_SHIFT; info->add += (reg & IXGBE_FDIRUSTAT_ADD_MASK) >> IXGBE_FDIRUSTAT_ADD_SHIFT; reg = IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT) & 0xFFFF; info->f_remove += (reg & IXGBE_FDIRFSTAT_FREMOVE_MASK) >> IXGBE_FDIRFSTAT_FREMOVE_SHIFT; info->f_add += (reg & IXGBE_FDIRFSTAT_FADD_MASK) >> IXGBE_FDIRFSTAT_FADD_SHIFT; /* Copy the new information in the fdir parameter */ fdir_stats->collision = info->collision; fdir_stats->free = info->free; fdir_stats->maxhash = info->maxhash; fdir_stats->maxlen = info->maxlen; fdir_stats->remove = info->remove; fdir_stats->add = info->add; fdir_stats->f_remove = info->f_remove; fdir_stats->f_add = info->f_add; reg = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); max_num = (1 << (FDIRENTRIES_NUM_SHIFT + (reg & FDIRCTRL_PBALLOC_MASK))); if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) fdir_stats->guarant_cnt = max_num - fdir_stats->free; else if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_SIGNATURE) fdir_stats->guarant_cnt = max_num * 4 - fdir_stats->free; } /* * ixgbe_fdir_ctrl_func - deal with all operations on flow director. * @dev: pointer to the structure rte_eth_dev * @filter_op:operation will be taken * @arg: a pointer to specific structure corresponding to the filter_op */ int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret = 0; if (hw->mac.type != ixgbe_mac_82599EB && hw->mac.type != ixgbe_mac_X540 && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x) return -ENOTSUP; if (filter_op == RTE_ETH_FILTER_NOP) return 0; if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) return -EINVAL; switch (filter_op) { case RTE_ETH_FILTER_ADD: ret = ixgbe_add_del_fdir_filter(dev, (struct rte_eth_fdir_filter *)arg, FALSE, FALSE); break; case RTE_ETH_FILTER_UPDATE: ret = ixgbe_add_del_fdir_filter(dev, (struct rte_eth_fdir_filter *)arg, FALSE, TRUE); break; case RTE_ETH_FILTER_DELETE: ret = ixgbe_add_del_fdir_filter(dev, (struct rte_eth_fdir_filter *)arg, TRUE, FALSE); break; case RTE_ETH_FILTER_FLUSH: ret = ixgbe_fdir_flush(dev); break; case RTE_ETH_FILTER_INFO: ixgbe_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg); break; case RTE_ETH_FILTER_STATS: ixgbe_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg); break; default: PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); ret = -EINVAL; break; } return ret; } ================================================ FILE: drivers/net/ixgbe/ixgbe_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_LOGS_H_ #define _IXGBE_LOGS_H_ #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) #ifdef RTE_LIBRTE_IXGBE_DEBUG_INIT #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_IXGBE_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_IXGBE_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_IXGBE_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_IXGBE_DEBUG_DRIVER #define PMD_DRV_LOG_RAW(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) #else #define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) #endif #define PMD_DRV_LOG(level, fmt, args...) \ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) #endif /* _IXGBE_LOGS_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_pf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/ixgbe_common.h" #include "ixgbe_ethdev.h" #define IXGBE_MAX_VFTA (128) #define IXGBE_VF_MSG_SIZE_DEFAULT 1 #define IXGBE_VF_GET_QUEUE_MSG_SIZE 5 static inline uint16_t dev_num_vf(struct rte_eth_dev *eth_dev) { return eth_dev->pci_dev->max_vfs; } static inline int ixgbe_vf_perm_addr_gen(struct rte_eth_dev *dev, uint16_t vf_num) { unsigned char vf_mac_addr[ETHER_ADDR_LEN]; struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); uint16_t vfn; for (vfn = 0; vfn < vf_num; vfn++) { eth_random_addr(vf_mac_addr); /* keep the random address as default */ memcpy(vfinfo[vfn].vf_mac_addresses, vf_mac_addr, ETHER_ADDR_LEN); } return 0; } static inline int ixgbe_mb_intr_setup(struct rte_eth_dev *dev) { struct ixgbe_interrupt *intr = IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); intr->mask |= IXGBE_EICR_MAILBOX; return 0; } void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev) { struct ixgbe_vf_info **vfinfo = IXGBE_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private); struct ixgbe_mirror_info *mirror_info = IXGBE_DEV_PRIVATE_TO_PFDATA(eth_dev->data->dev_private); struct ixgbe_uta_info *uta_info = IXGBE_DEV_PRIVATE_TO_UTA(eth_dev->data->dev_private); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); uint16_t vf_num; uint8_t nb_queue; PMD_INIT_FUNC_TRACE(); RTE_ETH_DEV_SRIOV(eth_dev).active = 0; if (0 == (vf_num = dev_num_vf(eth_dev))) return; *vfinfo = rte_zmalloc("vf_info", sizeof(struct ixgbe_vf_info) * vf_num, 0); if (*vfinfo == NULL) rte_panic("Cannot allocate memory for private VF data\n"); memset(mirror_info,0,sizeof(struct ixgbe_mirror_info)); memset(uta_info,0,sizeof(struct ixgbe_uta_info)); hw->mac.mc_filter_type = 0; if (vf_num >= ETH_32_POOLS) { nb_queue = 2; RTE_ETH_DEV_SRIOV(eth_dev).active = ETH_64_POOLS; } else if (vf_num >= ETH_16_POOLS) { nb_queue = 4; RTE_ETH_DEV_SRIOV(eth_dev).active = ETH_32_POOLS; } else { nb_queue = 8; RTE_ETH_DEV_SRIOV(eth_dev).active = ETH_16_POOLS; } RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = nb_queue; RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = vf_num; RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = (uint16_t)(vf_num * nb_queue); ixgbe_vf_perm_addr_gen(eth_dev, vf_num); /* init_mailbox_params */ hw->mbx.ops.init_params(hw); /* set mb interrupt mask */ ixgbe_mb_intr_setup(eth_dev); return; } void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev) { struct ixgbe_vf_info **vfinfo; uint16_t vf_num; PMD_INIT_FUNC_TRACE(); vfinfo = IXGBE_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private); RTE_ETH_DEV_SRIOV(eth_dev).active = 0; RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = 0; RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = 0; RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = 0; vf_num = dev_num_vf(eth_dev); if (vf_num == 0) return; rte_free(*vfinfo); *vfinfo = NULL; } int ixgbe_pf_host_configure(struct rte_eth_dev *eth_dev) { uint32_t vtctl, fcrth; uint32_t vfre_slot, vfre_offset; uint16_t vf_num; const uint8_t VFRE_SHIFT = 5; /* VFRE 32 bits per slot */ const uint8_t VFRE_MASK = (uint8_t)((1U << VFRE_SHIFT) - 1); struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); uint32_t gpie, gcr_ext; uint32_t vlanctrl; int i; if (0 == (vf_num = dev_num_vf(eth_dev))) return -1; /* enable VMDq and set the default pool for PF */ vtctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); vtctl |= IXGBE_VMD_CTL_VMDQ_EN; vtctl &= ~IXGBE_VT_CTL_POOL_MASK; vtctl |= RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx << IXGBE_VT_CTL_POOL_SHIFT; vtctl |= IXGBE_VT_CTL_REPLEN; IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vtctl); vfre_offset = vf_num & VFRE_MASK; vfre_slot = (vf_num >> VFRE_SHIFT) > 0 ? 1 : 0; /* Enable pools reserved to PF only */ IXGBE_WRITE_REG(hw, IXGBE_VFRE(vfre_slot), (~0) << vfre_offset); IXGBE_WRITE_REG(hw, IXGBE_VFRE(vfre_slot ^ 1), vfre_slot - 1); IXGBE_WRITE_REG(hw, IXGBE_VFTE(vfre_slot), (~0) << vfre_offset); IXGBE_WRITE_REG(hw, IXGBE_VFTE(vfre_slot ^ 1), vfre_slot - 1); /* PFDMA Tx General Switch Control Enables VMDQ loopback */ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); /* clear VMDq map to perment rar 0 */ hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); /* clear VMDq map to scan rar 127 */ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(hw->mac.num_rar_entries), 0); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(hw->mac.num_rar_entries), 0); /* set VMDq map to default PF pool */ hw->mac.ops.set_vmdq(hw, 0, RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx); /* * SW msut set GCR_EXT.VT_Mode the same as GPIE.VT_Mode */ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); gcr_ext &= ~IXGBE_GCR_EXT_VT_MODE_MASK; gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); gpie &= ~IXGBE_GPIE_VTMODE_MASK; gpie |= IXGBE_GPIE_MSIX_MODE; switch (RTE_ETH_DEV_SRIOV(eth_dev).active) { case ETH_64_POOLS: gcr_ext |= IXGBE_GCR_EXT_VT_MODE_64; gpie |= IXGBE_GPIE_VTMODE_64; break; case ETH_32_POOLS: gcr_ext |= IXGBE_GCR_EXT_VT_MODE_32; gpie |= IXGBE_GPIE_VTMODE_32; break; case ETH_16_POOLS: gcr_ext |= IXGBE_GCR_EXT_VT_MODE_16; gpie |= IXGBE_GPIE_VTMODE_16; break; } IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); /* * enable vlan filtering and allow all vlan tags through */ vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); /* VFTA - enable all vlan filters */ for (i = 0; i < IXGBE_MAX_VFTA; i++) { IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 0xFFFFFFFF); } /* Enable MAC Anti-Spoofing */ hw->mac.ops.set_mac_anti_spoofing(hw, FALSE, vf_num); /* set flow control threshold to max to avoid tx switch hang */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); } return 0; } static void set_rx_mode(struct rte_eth_dev *dev) { struct rte_eth_dev_data *dev_data = (struct rte_eth_dev_data*)dev->data->dev_private; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE; uint16_t vfn = dev_num_vf(dev); /* Check for Promiscuous and All Multicast modes */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); /* set all bits that we expect to always be set */ fctrl &= ~IXGBE_FCTRL_SBP; /* disable store-bad-packets */ fctrl |= IXGBE_FCTRL_BAM; /* clear the bits we are changing the status of */ fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); if (dev_data->promiscuous) { fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); vmolr |= (IXGBE_VMOLR_ROPE | IXGBE_VMOLR_MPE); } else { if (dev_data->all_multicast) { fctrl |= IXGBE_FCTRL_MPE; vmolr |= IXGBE_VMOLR_MPE; } else { vmolr |= IXGBE_VMOLR_ROMPE; } } if (hw->mac.type != ixgbe_mac_82598EB) { vmolr |= IXGBE_READ_REG(hw, IXGBE_VMOLR(vfn)) & ~(IXGBE_VMOLR_MPE | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE); IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vfn), vmolr); } IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); if (dev->data->dev_conf.rxmode.hw_vlan_strip) ixgbe_vlan_hw_strip_enable_all(dev); else ixgbe_vlan_hw_strip_disable_all(dev); } static inline void ixgbe_vf_reset_event(struct rte_eth_dev *dev, uint16_t vf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); int rar_entry = hw->mac.num_rar_entries - (vf + 1); uint32_t vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); vmolr |= (IXGBE_VMOLR_ROPE | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE); IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); /* reset multicast table array for vf */ vfinfo[vf].num_vf_mc_hashes = 0; /* reset rx mode */ set_rx_mode(dev); hw->mac.ops.clear_rar(hw, rar_entry); } static inline void ixgbe_vf_reset_msg(struct rte_eth_dev *dev, uint16_t vf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t reg; uint32_t reg_offset, vf_shift; const uint8_t VFRE_SHIFT = 5; /* VFRE 32 bits per slot */ const uint8_t VFRE_MASK = (uint8_t)((1U << VFRE_SHIFT) - 1); vf_shift = vf & VFRE_MASK; reg_offset = (vf >> VFRE_SHIFT) > 0 ? 1 : 0; /* enable transmit and receive for vf */ reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset)); reg |= (reg | (1 << vf_shift)); IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg); reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); reg |= (reg | (1 << vf_shift)); IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg); /* Enable counting of spoofed packets in the SSVPC register */ reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset)); reg |= (1 << vf_shift); IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg); ixgbe_vf_reset_event(dev, vf); } static int ixgbe_vf_reset(struct rte_eth_dev *dev, uint16_t vf, uint32_t *msgbuf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); unsigned char *vf_mac = vfinfo[vf].vf_mac_addresses; int rar_entry = hw->mac.num_rar_entries - (vf + 1); uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); ixgbe_vf_reset_msg(dev, vf); hw->mac.ops.set_rar(hw, rar_entry, vf_mac, vf, IXGBE_RAH_AV); /* reply to reset with ack and vf mac address */ msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK; rte_memcpy(new_mac, vf_mac, ETHER_ADDR_LEN); /* * Piggyback the multicast filter type so VF can compute the * correct vectors */ msgbuf[3] = hw->mac.mc_filter_type; ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf); return 0; } static int ixgbe_vf_set_mac_addr(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); int rar_entry = hw->mac.num_rar_entries - (vf + 1); uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); if (is_valid_assigned_ether_addr((struct ether_addr*)new_mac)) { rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, 6); return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf, IXGBE_RAH_AV); } return -1; } static int ixgbe_vf_set_multicast(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *msgbuf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); int nb_entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; uint16_t *hash_list = (uint16_t *)&msgbuf[1]; uint32_t mta_idx; uint32_t mta_shift; const uint32_t IXGBE_MTA_INDEX_MASK = 0x7F; const uint32_t IXGBE_MTA_BIT_SHIFT = 5; const uint32_t IXGBE_MTA_BIT_MASK = (0x1 << IXGBE_MTA_BIT_SHIFT) - 1; uint32_t reg_val; int i; /* only so many hash values supported */ nb_entries = RTE_MIN(nb_entries, IXGBE_MAX_VF_MC_ENTRIES); /* store the mc entries */ vfinfo->num_vf_mc_hashes = (uint16_t)nb_entries; for (i = 0; i < nb_entries; i++) { vfinfo->vf_mc_hashes[i] = hash_list[i]; } for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { mta_idx = (vfinfo->vf_mc_hashes[i] >> IXGBE_MTA_BIT_SHIFT) & IXGBE_MTA_INDEX_MASK; mta_shift = vfinfo->vf_mc_hashes[i] & IXGBE_MTA_BIT_MASK; reg_val = IXGBE_READ_REG(hw, IXGBE_MTA(mta_idx)); reg_val |= (1 << mta_shift); IXGBE_WRITE_REG(hw, IXGBE_MTA(mta_idx), reg_val); } return 0; } static int ixgbe_vf_set_vlan(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { int add, vid; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT; vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); if (add) vfinfo[vf].vlan_count++; else if (vfinfo[vf].vlan_count) vfinfo[vf].vlan_count--; return hw->mac.ops.set_vfta(hw, vid, vf, (bool)add); } static int ixgbe_set_vf_lpe(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *msgbuf) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t new_mtu = msgbuf[1]; uint32_t max_frs; int max_frame = new_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; /* X540 and X550 support jumbo frames in IOV mode */ if (hw->mac.type != ixgbe_mac_X540 && hw->mac.type != ixgbe_mac_X550 && hw->mac.type != ixgbe_mac_X550EM_x) return -1; if ((max_frame < ETHER_MIN_LEN) || (max_frame > ETHER_MAX_JUMBO_FRAME_LEN)) return -1; max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT; if (max_frs < new_mtu) { max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs); } return 0; } static int ixgbe_negotiate_vf_api(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { uint32_t api_version = msgbuf[1]; struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); switch (api_version) { case ixgbe_mbox_api_10: case ixgbe_mbox_api_11: vfinfo[vf].api_version = (uint8_t)api_version; return 0; default: break; } RTE_LOG(ERR, PMD, "Negotiate invalid api version %u from VF %d\n", api_version, vf); return -1; } static int ixgbe_get_vf_queues(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) { struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); uint32_t default_q = vf * RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool; /* Verify if the PF supports the mbox APIs version or not */ switch (vfinfo[vf].api_version) { case ixgbe_mbox_api_20: case ixgbe_mbox_api_11: break; default: return -1; } /* Notify VF of Rx and Tx queue number */ msgbuf[IXGBE_VF_RX_QUEUES] = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool; msgbuf[IXGBE_VF_TX_QUEUES] = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool; /* Notify VF of default queue */ msgbuf[IXGBE_VF_DEF_QUEUE] = default_q; /* * FIX ME if it needs fill msgbuf[IXGBE_VF_TRANS_VLAN] * for VLAN strip or VMDQ_DCB or VMDQ_DCB_RSS */ return 0; } static int ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf) { uint16_t mbx_size = IXGBE_VFMAILBOX_SIZE; uint16_t msg_size = IXGBE_VF_MSG_SIZE_DEFAULT; uint32_t msgbuf[IXGBE_VFMAILBOX_SIZE]; int32_t retval; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); if (retval) { PMD_DRV_LOG(ERR, "Error mbx recv msg from VF %d", vf); return retval; } /* do nothing with the message already been processed */ if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK)) return retval; /* flush the ack before we write any messages back */ IXGBE_WRITE_FLUSH(hw); /* perform VF reset */ if (msgbuf[0] == IXGBE_VF_RESET) { int ret = ixgbe_vf_reset(dev, vf, msgbuf); vfinfo[vf].clear_to_send = true; return ret; } /* check & process VF to PF mailbox message */ switch ((msgbuf[0] & 0xFFFF)) { case IXGBE_VF_SET_MAC_ADDR: retval = ixgbe_vf_set_mac_addr(dev, vf, msgbuf); break; case IXGBE_VF_SET_MULTICAST: retval = ixgbe_vf_set_multicast(dev, vf, msgbuf); break; case IXGBE_VF_SET_LPE: retval = ixgbe_set_vf_lpe(dev, vf, msgbuf); break; case IXGBE_VF_SET_VLAN: retval = ixgbe_vf_set_vlan(dev, vf, msgbuf); break; case IXGBE_VF_API_NEGOTIATE: retval = ixgbe_negotiate_vf_api(dev, vf, msgbuf); break; case IXGBE_VF_GET_QUEUES: retval = ixgbe_get_vf_queues(dev, vf, msgbuf); msg_size = IXGBE_VF_GET_QUEUE_MSG_SIZE; break; default: PMD_DRV_LOG(DEBUG, "Unhandled Msg %8.8x", (unsigned)msgbuf[0]); retval = IXGBE_ERR_MBX; break; } /* response the VF according to the message process result */ if (retval) msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; else msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK; msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS; ixgbe_write_mbx(hw, msgbuf, msg_size, vf); return retval; } static inline void ixgbe_rcv_ack_from_vf(struct rte_eth_dev *dev, uint16_t vf) { uint32_t msg = IXGBE_VT_MSGTYPE_NACK; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct ixgbe_vf_info *vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); if (!vfinfo[vf].clear_to_send) ixgbe_write_mbx(hw, &msg, 1, vf); } void ixgbe_pf_mbx_process(struct rte_eth_dev *eth_dev) { uint16_t vf; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); for (vf = 0; vf < dev_num_vf(eth_dev); vf++) { /* check & process vf function level reset */ if (!ixgbe_check_for_rst(hw, vf)) ixgbe_vf_reset_event(eth_dev, vf); /* check & process vf mailbox messages */ if (!ixgbe_check_for_msg(hw, vf)) ixgbe_rcv_msg_from_vf(eth_dev, vf); /* check & process acks from vf */ if (!ixgbe_check_for_ack(hw, vf)) ixgbe_rcv_ack_from_vf(eth_dev, vf); } } ================================================ FILE: drivers/net/ixgbe/ixgbe_regs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_REGS_H_ #define _IXGBE_REGS_H_ #include "ixgbe_ethdev.h" struct ixgbe_hw; struct reg_info { uint32_t base_addr; uint32_t count; uint32_t stride; const char *name; } reg_info; static const struct reg_info ixgbe_regs_general[] = { {IXGBE_CTRL, 1, 1, "IXGBE_CTRL"}, {IXGBE_STATUS, 1, 1, "IXGBE_STATUS"}, {IXGBE_CTRL_EXT, 1, 1, "IXGBE_CTRL_EXT"}, {IXGBE_ESDP, 1, 1, "IXGBE_ESDP"}, {IXGBE_EODSDP, 1, 1, "IXGBE_EODSDP"}, {IXGBE_LEDCTL, 1, 1, "IXGBE_LEDCTL"}, {IXGBE_FRTIMER, 1, 1, "IXGBE_FRTIMER"}, {IXGBE_TCPTIMER, 1, 1, "IXGBE_TCPTIMER"}, {0, 0, 0, ""} }; static const struct reg_info ixgbevf_regs_general[] = { {IXGBE_CTRL, 1, 1, "IXGBE_CTRL"}, {IXGBE_STATUS, 1, 1, "IXGBE_STATUS"}, {IXGBE_VFLINKS, 1, 1, "IXGBE_VFLINKS"}, {IXGBE_FRTIMER, 1, 1, "IXGBE_FRTIMER"}, {IXGBE_VFMAILBOX, 1, 1, "IXGBE_VFMAILBOX"}, {IXGBE_VFMBMEM, 16, 4, "IXGBE_VFMBMEM"}, {IXGBE_VFRXMEMWRAP, 1, 1, "IXGBE_VFRXMEMWRAP"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_nvm[] = { {IXGBE_EEC, 1, 1, "IXGBE_EEC"}, {IXGBE_EERD, 1, 1, "IXGBE_EERD"}, {IXGBE_FLA, 1, 1, "IXGBE_FLA"}, {IXGBE_EEMNGCTL, 1, 1, "IXGBE_EEMNGCTL"}, {IXGBE_EEMNGDATA, 1, 1, "IXGBE_EEMNGDATA"}, {IXGBE_FLMNGCTL, 1, 1, "IXGBE_FLMNGCTL"}, {IXGBE_FLMNGDATA, 1, 1, "IXGBE_FLMNGDATA"}, {IXGBE_FLMNGCNT, 1, 1, "IXGBE_FLMNGCNT"}, {IXGBE_FLOP, 1, 1, "IXGBE_FLOP"}, {IXGBE_GRC, 1, 1, "IXGBE_GRC"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_interrupt[] = { {IXGBE_EICS, 1, 1, "IXGBE_EICS"}, {IXGBE_EIMS, 1, 1, "IXGBE_EIMS"}, {IXGBE_EIMC, 1, 1, "IXGBE_EIMC"}, {IXGBE_EIAC, 1, 1, "IXGBE_EIAC"}, {IXGBE_EIAM, 1, 1, "IXGBE_EIAM"}, {IXGBE_EITR(0), 24, 4, "IXGBE_EITR"}, {IXGBE_IVAR(0), 24, 4, "IXGBE_IVAR"}, {IXGBE_MSIXT, 1, 1, "IXGBE_MSIXT"}, {IXGBE_MSIXPBA, 1, 1, "IXGBE_MSIXPBA"}, {IXGBE_PBACL(0), 1, 4, "IXGBE_PBACL"}, {IXGBE_GPIE, 1, 1, ""}, {0, 0, 0, ""} }; static const struct reg_info ixgbevf_regs_interrupt[] = { {IXGBE_VTEICR, 1, 1, "IXGBE_VTEICR"}, {IXGBE_VTEICS, 1, 1, "IXGBE_VTEICS"}, {IXGBE_VTEIMS, 1, 1, "IXGBE_VTEIMS"}, {IXGBE_VTEIMC, 1, 1, "IXGBE_VTEIMC"}, {IXGBE_VTEIAM, 1, 1, "IXGBE_VTEIAM"}, {IXGBE_VTEITR(0), 2, 4, "IXGBE_VTEITR"}, {IXGBE_VTIVAR(0), 4, 4, "IXGBE_VTIVAR"}, {IXGBE_VTIVAR_MISC, 1, 1, "IXGBE_VTIVAR_MISC"}, {IXGBE_VTRSCINT(0), 2, 4, "IXGBE_VTRSCINT"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_fctl_mac_82598EB[] = { {IXGBE_PFCTOP, 1, 1, ""}, {IXGBE_FCTTV(0), 4, 4, ""}, {IXGBE_FCRTV, 1, 1, ""}, {IXGBE_TFCS, 1, 1, ""}, {IXGBE_FCRTL(0), 8, 8, "IXGBE_FCRTL"}, {IXGBE_FCRTH(0), 8, 8, "IXGBE_FCRTH"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_fctl_others[] = { {IXGBE_PFCTOP, 1, 1, ""}, {IXGBE_FCTTV(0), 4, 4, ""}, {IXGBE_FCRTV, 1, 1, ""}, {IXGBE_TFCS, 1, 1, ""}, {IXGBE_FCRTL_82599(0), 8, 4, "IXGBE_FCRTL"}, {IXGBE_FCRTH_82599(0), 8, 4, "IXGBE_FCRTH"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_rxdma[] = { {IXGBE_RDBAL(0), 64, 0x40, "IXGBE_RDBAL"}, {IXGBE_RDBAH(0), 64, 0x40, "IXGBE_RDBAH"}, {IXGBE_RDLEN(0), 64, 0x40, "IXGBE_RDLEN"}, {IXGBE_RDH(0), 64, 0x40, "IXGBE_RDH"}, {IXGBE_RDT(0), 64, 0x40, "IXGBE_RDT"}, {IXGBE_RXDCTL(0), 64, 0x40, "IXGBE_RXDCTL"}, {IXGBE_SRRCTL(0), 16, 0x4, "IXGBE_SRRCTL"}, {IXGBE_DCA_RXCTRL(0), 16, 4, "IXGBE_DCA_RXCTRL"}, {IXGBE_RDRXCTL, 1, 1, "IXGBE_RDRXCTL"}, {IXGBE_RXPBSIZE(0), 8, 4, "IXGBE_RXPBSIZE"}, {IXGBE_RXCTRL, 1, 1, "IXGBE_RXCTRL"}, {IXGBE_DROPEN, 1, 1, "IXGBE_DROPEN"}, {0, 0, 0, ""} }; static const struct reg_info ixgbevf_regs_rxdma[] = { {IXGBE_RDBAL(0), 8, 0x40, "IXGBE_RDBAL"}, {IXGBE_RDBAH(0), 8, 0x40, "IXGBE_RDBAH"}, {IXGBE_RDLEN(0), 8, 0x40, "IXGBE_RDLEN"}, {IXGBE_RDH(0), 8, 0x40, "IXGBE_RDH"}, {IXGBE_RDT(0), 8, 0x40, "IXGBE_RDT"}, {IXGBE_RXDCTL(0), 8, 0x40, "IXGBE_RXDCTL"}, {IXGBE_SRRCTL(0), 8, 0x40, "IXGBE_SRRCTL"}, {IXGBE_VFPSRTYPE, 1, 1, "IXGBE_VFPSRTYPE"}, {IXGBE_VFRSCCTL(0), 8, 0x40, "IXGBE_VFRSCCTL"}, {IXGBE_PVFDCA_RXCTRL(0), 8, 0x40, "IXGBE_PVFDCA_RXCTRL"}, {IXGBE_PVFDCA_TXCTRL(0), 8, 0x40, "IXGBE_PVFDCA_TXCTRL"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_rx[] = { {IXGBE_RXCSUM, 1, 1, "IXGBE_RXCSUM"}, {IXGBE_RFCTL, 1, 1, "IXGBE_RFCTL"}, {IXGBE_RAL(0), 16, 8, "IXGBE_RAL"}, {IXGBE_RAH(0), 16, 8, "IXGBE_RAH"}, {IXGBE_PSRTYPE(0), 1, 4, "IXGBE_PSRTYPE"}, {IXGBE_FCTRL, 1, 1, "IXGBE_FCTRL"}, {IXGBE_VLNCTRL, 1, 1, "IXGBE_VLNCTRL"}, {IXGBE_MCSTCTRL, 1, 1, "IXGBE_MCSTCTRL"}, {IXGBE_MRQC, 1, 1, "IXGBE_MRQC"}, {IXGBE_VMD_CTL, 1, 1, "IXGBE_VMD_CTL"}, {IXGBE_IMIR(0), 8, 4, "IXGBE_IMIR"}, {IXGBE_IMIREXT(0), 8, 4, "IXGBE_IMIREXT"}, {IXGBE_IMIRVP, 1, 1, "IXGBE_IMIRVP"}, {0, 0, 0, ""} }; static struct reg_info ixgbe_regs_tx[] = { {IXGBE_TDBAL(0), 32, 0x40, "IXGBE_TDBAL"}, {IXGBE_TDBAH(0), 32, 0x40, "IXGBE_TDBAH"}, {IXGBE_TDLEN(0), 32, 0x40, "IXGBE_TDLEN"}, {IXGBE_TDH(0), 32, 0x40, "IXGBE_TDH"}, {IXGBE_TDT(0), 32, 0x40, "IXGBE_TDT"}, {IXGBE_TXDCTL(0), 32, 0x40, "IXGBE_TXDCTL"}, {IXGBE_TDWBAL(0), 32, 0x40, "IXGBE_TDWBAL"}, {IXGBE_TDWBAH(0), 32, 0x40, "IXGBE_TDWBAH"}, {IXGBE_DTXCTL, 1, 1, "IXGBE_DTXCTL"}, {IXGBE_DCA_TXCTRL(0), 16, 4, "IXGBE_DCA_TXCTRL"}, {IXGBE_TXPBSIZE(0), 8, 4, "IXGBE_TXPBSIZE"}, {IXGBE_MNGTXMAP, 1, 1, "IXGBE_MNGTXMAP"}, {0, 0, 0, ""} }; static const struct reg_info ixgbevf_regs_tx[] = { {IXGBE_TDBAL(0), 4, 0x40, "IXGBE_TDBAL"}, {IXGBE_TDBAH(0), 4, 0x40, "IXGBE_TDBAH"}, {IXGBE_TDLEN(0), 4, 0x40, "IXGBE_TDLEN"}, {IXGBE_TDH(0), 4, 0x40, "IXGBE_TDH"}, {IXGBE_TDT(0), 4, 0x40, "IXGBE_TDT"}, {IXGBE_TXDCTL(0), 4, 0x40, "IXGBE_TXDCTL"}, {IXGBE_TDWBAL(0), 4, 0x40, "IXGBE_TDWBAL"}, {IXGBE_TDWBAH(0), 4, 0x40, "IXGBE_TDWBAH"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_wakeup[] = { {IXGBE_WUC, 1, 1, "IXGBE_WUC"}, {IXGBE_WUFC, 1, 1, "IXGBE_WUFC"}, {IXGBE_WUS, 1, 1, "IXGBE_WUS"}, {IXGBE_IPAV, 1, 1, "IXGBE_IPAV"}, {IXGBE_IP4AT, 1, 1, "IXGBE_IP4AT"}, {IXGBE_IP6AT, 1, 1, "IXGBE_IP6AT"}, {IXGBE_WUPL, 1, 1, "IXGBE_WUPL"}, {IXGBE_WUPM, 1, 1, "IXGBE_WUPM"}, {IXGBE_FHFT(0), 1, 1, "IXGBE_FHFT"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_dcb[] = { {IXGBE_RMCS, 1, 1, "IXGBE_RMCS"}, {IXGBE_DPMCS, 1, 1, "IXGBE_DPMCS"}, {IXGBE_PDPMCS, 1, 1, "IXGBE_PDPMCS"}, {IXGBE_RUPPBMR, 1, 1, "IXGBE_RUPPBMR"}, {IXGBE_RT2CR(0), 8, 4, "IXGBE_RT2CR"}, {IXGBE_RT2SR(0), 8, 4, "IXGBE_RT2SR"}, {IXGBE_TDTQ2TCCR(0), 8, 0x40, "IXGBE_TDTQ2TCCR"}, {IXGBE_TDTQ2TCSR(0), 8, 0x40, "IXGBE_TDTQ2TCSR"}, {IXGBE_TDPT2TCCR(0), 8, 4, "IXGBE_TDPT2TCCR"}, {IXGBE_TDPT2TCSR(0), 8, 4, "IXGBE_TDPT2TCSR"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_mac[] = { {IXGBE_PCS1GCFIG, 1, 1, "IXGBE_PCS1GCFIG"}, {IXGBE_PCS1GLCTL, 1, 1, "IXGBE_PCS1GLCTL"}, {IXGBE_PCS1GLSTA, 1, 1, "IXGBE_PCS1GLSTA"}, {IXGBE_PCS1GDBG0, 1, 1, "IXGBE_PCS1GDBG0"}, {IXGBE_PCS1GDBG1, 1, 1, "IXGBE_PCS1GDBG1"}, {IXGBE_PCS1GANA, 1, 1, "IXGBE_PCS1GANA"}, {IXGBE_PCS1GANLP, 1, 1, "IXGBE_PCS1GANLP"}, {IXGBE_PCS1GANNP, 1, 1, "IXGBE_PCS1GANNP"}, {IXGBE_PCS1GANLPNP, 1, 1, "IXGBE_PCS1GANLPNP"}, {IXGBE_HLREG0, 1, 1, "IXGBE_HLREG0"}, {IXGBE_HLREG1, 1, 1, "IXGBE_HLREG1"}, {IXGBE_PAP, 1, 1, "IXGBE_PAP"}, {IXGBE_MACA, 1, 1, "IXGBE_MACA"}, {IXGBE_APAE, 1, 1, "IXGBE_APAE"}, {IXGBE_ARD, 1, 1, "IXGBE_ARD"}, {IXGBE_AIS, 1, 1, "IXGBE_AIS"}, {IXGBE_MSCA, 1, 1, "IXGBE_MSCA"}, {IXGBE_MSRWD, 1, 1, "IXGBE_MSRWD"}, {IXGBE_MLADD, 1, 1, "IXGBE_MLADD"}, {IXGBE_MHADD, 1, 1, "IXGBE_MHADD"}, {IXGBE_TREG, 1, 1, "IXGBE_TREG"}, {IXGBE_PCSS1, 1, 1, "IXGBE_PCSS1"}, {IXGBE_PCSS2, 1, 1, "IXGBE_PCSS2"}, {IXGBE_XPCSS, 1, 1, "IXGBE_XPCSS"}, {IXGBE_SERDESC, 1, 1, "IXGBE_SERDESC"}, {IXGBE_MACS, 1, 1, "IXGBE_MACS"}, {IXGBE_AUTOC, 1, 1, "IXGBE_AUTOC"}, {IXGBE_LINKS, 1, 1, "IXGBE_LINKS"}, {IXGBE_AUTOC2, 1, 1, "IXGBE_AUTOC2"}, {IXGBE_AUTOC3, 1, 1, "IXGBE_AUTOC3"}, {IXGBE_ANLP1, 1, 1, "IXGBE_ANLP1"}, {IXGBE_ANLP2, 1, 1, "IXGBE_ANLP2"}, {IXGBE_ATLASCTL, 1, 1, "IXGBE_ATLASCTL"}, {0, 0, 0, ""} }; static const struct reg_info ixgbe_regs_diagnostic[] = { {IXGBE_RDSTATCTL, 1, 1, "IXGBE_RDSTATCTL"}, {IXGBE_RDSTAT(0), 8, 4, "IXGBE_RDSTAT"}, {IXGBE_RDHMPN, 1, 1, "IXGBE_RDHMPN"}, {IXGBE_RIC_DW(0), 4, 4, "IXGBE_RIC_DW"}, {IXGBE_RDPROBE, 1, 1, "IXGBE_RDPROBE"}, {IXGBE_TDHMPN, 1, 1, "IXGBE_TDHMPN"}, {IXGBE_TIC_DW(0), 4, 4, "IXGBE_TIC_DW"}, {IXGBE_TDPROBE, 1, 1, "IXGBE_TDPROBE"}, {IXGBE_TXBUFCTRL, 1, 1, "IXGBE_TXBUFCTRL"}, {IXGBE_TXBUFDATA0, 1, 1, "IXGBE_TXBUFDATA0"}, {IXGBE_TXBUFDATA1, 1, 1, "IXGBE_TXBUFDATA1"}, {IXGBE_TXBUFDATA2, 1, 1, "IXGBE_TXBUFDATA2"}, {IXGBE_TXBUFDATA3, 1, 1, "IXGBE_TXBUFDATA3"}, {IXGBE_RXBUFCTRL, 1, 1, "IXGBE_RXBUFCTRL"}, {IXGBE_RXBUFDATA0, 1, 1, "IXGBE_RXBUFDATA0"}, {IXGBE_RXBUFDATA1, 1, 1, "IXGBE_RXBUFDATA1"}, {IXGBE_RXBUFDATA2, 1, 1, "IXGBE_RXBUFDATA2"}, {IXGBE_RXBUFDATA3, 1, 1, "IXGBE_RXBUFDATA3"}, {IXGBE_PCIE_DIAG(0), 8, 4, ""}, {IXGBE_RFVAL, 1, 1, "IXGBE_RFVAL"}, {IXGBE_MDFTC1, 1, 1, "IXGBE_MDFTC1"}, {IXGBE_MDFTC2, 1, 1, "IXGBE_MDFTC2"}, {IXGBE_MDFTFIFO1, 1, 1, "IXGBE_MDFTFIFO1"}, {IXGBE_MDFTFIFO2, 1, 1, "IXGBE_MDFTFIFO2"}, {IXGBE_MDFTS, 1, 1, "IXGBE_MDFTS"}, {IXGBE_PCIEECCCTL, 1, 1, "IXGBE_PCIEECCCTL"}, {IXGBE_PBTXECC, 1, 1, "IXGBE_PBTXECC"}, {IXGBE_PBRXECC, 1, 1, "IXGBE_PBRXECC"}, {IXGBE_MFLCN, 1, 1, "IXGBE_MFLCN"}, {0, 0, 0, ""}, }; /* PF registers */ static const struct reg_info *ixgbe_regs_others[] = { ixgbe_regs_general, ixgbe_regs_nvm, ixgbe_regs_interrupt, ixgbe_regs_fctl_others, ixgbe_regs_rxdma, ixgbe_regs_rx, ixgbe_regs_tx, ixgbe_regs_wakeup, ixgbe_regs_dcb, ixgbe_regs_mac, ixgbe_regs_diagnostic, NULL}; static const struct reg_info *ixgbe_regs_mac_82598EB[] = { ixgbe_regs_general, ixgbe_regs_nvm, ixgbe_regs_interrupt, ixgbe_regs_fctl_mac_82598EB, ixgbe_regs_rxdma, ixgbe_regs_rx, ixgbe_regs_tx, ixgbe_regs_wakeup, ixgbe_regs_dcb, ixgbe_regs_mac, ixgbe_regs_diagnostic, NULL}; /* VF registers */ static const struct reg_info *ixgbevf_regs[] = { ixgbevf_regs_general, ixgbevf_regs_interrupt, ixgbevf_regs_rxdma, ixgbevf_regs_tx, NULL}; static inline int ixgbe_read_regs(struct ixgbe_hw *hw, const struct reg_info *reg, uint32_t *reg_buf) { unsigned int i; for (i = 0; i < reg->count; i++) reg_buf[i] = IXGBE_READ_REG(hw, reg->base_addr + i * reg->stride); return reg->count; }; static inline int ixgbe_regs_group_count(const struct reg_info *regs) { int count = 0; int i = 0; while (regs[i].count) count += regs[i++].count; return count; }; static inline int ixgbe_read_regs_group(struct rte_eth_dev *dev, uint32_t *reg_buf, const struct reg_info *regs) { int count = 0; int i = 0; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); while (regs[i].count) count += ixgbe_read_regs(hw, ®s[i++], ®_buf[count]); return count; }; #endif /* _IXGBE_REGS_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * Copyright 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ixgbe_logs.h" #include "base/ixgbe_api.h" #include "base/ixgbe_vf.h" #include "ixgbe_ethdev.h" #include "base/ixgbe_dcb.h" #include "base/ixgbe_common.h" #include "ixgbe_rxtx.h" /* Bit Mask to indicate what bits required for building TX context */ #define IXGBE_TX_OFFLOAD_MASK ( \ PKT_TX_VLAN_PKT | \ PKT_TX_IP_CKSUM | \ PKT_TX_L4_MASK | \ PKT_TX_TCP_SEG) static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return (m); } #if 1 #define RTE_PMD_USE_PREFETCH #endif #ifdef RTE_PMD_USE_PREFETCH /* * Prefetch a cache line into all cache levels. */ #define rte_ixgbe_prefetch(p) rte_prefetch0(p) #else #define rte_ixgbe_prefetch(p) do {} while(0) #endif /********************************************************************* * * TX functions * **********************************************************************/ /* * Check for descriptors with their DD bit set and free mbufs. * Return the total number of buffers freed. */ static inline int __attribute__((always_inline)) ixgbe_tx_free_bufs(struct ixgbe_tx_queue *txq) { struct ixgbe_tx_entry *txep; uint32_t status; int i; /* check DD bit on threshold descriptor */ status = txq->tx_ring[txq->tx_next_dd].wb.status; if (!(status & rte_cpu_to_le_32(IXGBE_ADVTXD_STAT_DD))) return 0; /* * first buffer to free from S/W ring is at index * tx_next_dd - (tx_rs_thresh-1) */ txep = &(txq->sw_ring[txq->tx_next_dd - (txq->tx_rs_thresh - 1)]); /* free buffers one at a time */ if ((txq->txq_flags & (uint32_t)ETH_TXQ_FLAGS_NOREFCOUNT) != 0) { for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) { txep->mbuf->next = NULL; rte_mempool_put(txep->mbuf->pool, txep->mbuf); txep->mbuf = NULL; } } else { for (i = 0; i < txq->tx_rs_thresh; ++i, ++txep) { rte_pktmbuf_free_seg(txep->mbuf); txep->mbuf = NULL; } } /* buffers were freed, update counters */ txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); if (txq->tx_next_dd >= txq->nb_tx_desc) txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); return txq->tx_rs_thresh; } /* Populate 4 descriptors with data from 4 mbufs */ static inline void tx4(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf **pkts) { uint64_t buf_dma_addr; uint32_t pkt_len; int i; for (i = 0; i < 4; ++i, ++txdp, ++pkts) { buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts); pkt_len = (*pkts)->data_len; /* write data to descriptor */ txdp->read.buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txdp->read.cmd_type_len = rte_cpu_to_le_32((uint32_t)DCMD_DTYP_FLAGS | pkt_len); txdp->read.olinfo_status = rte_cpu_to_le_32(pkt_len << IXGBE_ADVTXD_PAYLEN_SHIFT); rte_prefetch0(&(*pkts)->pool); } } /* Populate 1 descriptor with data from 1 mbuf */ static inline void tx1(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf **pkts) { uint64_t buf_dma_addr; uint32_t pkt_len; buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(*pkts); pkt_len = (*pkts)->data_len; /* write data to descriptor */ txdp->read.buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txdp->read.cmd_type_len = rte_cpu_to_le_32((uint32_t)DCMD_DTYP_FLAGS | pkt_len); txdp->read.olinfo_status = rte_cpu_to_le_32(pkt_len << IXGBE_ADVTXD_PAYLEN_SHIFT); rte_prefetch0(&(*pkts)->pool); } /* * Fill H/W descriptor ring with mbuf data. * Copy mbuf pointers to the S/W ring. */ static inline void ixgbe_tx_fill_hw_ring(struct ixgbe_tx_queue *txq, struct rte_mbuf **pkts, uint16_t nb_pkts) { volatile union ixgbe_adv_tx_desc *txdp = &(txq->tx_ring[txq->tx_tail]); struct ixgbe_tx_entry *txep = &(txq->sw_ring[txq->tx_tail]); const int N_PER_LOOP = 4; const int N_PER_LOOP_MASK = N_PER_LOOP-1; int mainpart, leftover; int i, j; /* * Process most of the packets in chunks of N pkts. Any * leftover packets will get processed one at a time. */ mainpart = (nb_pkts & ((uint32_t) ~N_PER_LOOP_MASK)); leftover = (nb_pkts & ((uint32_t) N_PER_LOOP_MASK)); for (i = 0; i < mainpart; i += N_PER_LOOP) { /* Copy N mbuf pointers to the S/W ring */ for (j = 0; j < N_PER_LOOP; ++j) { (txep + i + j)->mbuf = *(pkts + i + j); } tx4(txdp + i, pkts + i); } if (unlikely(leftover > 0)) { for (i = 0; i < leftover; ++i) { (txep + mainpart + i)->mbuf = *(pkts + mainpart + i); tx1(txdp + mainpart + i, pkts + mainpart + i); } } } static inline uint16_t tx_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct ixgbe_tx_queue *txq = (struct ixgbe_tx_queue *)tx_queue; volatile union ixgbe_adv_tx_desc *tx_r = txq->tx_ring; uint16_t n = 0; /* * Begin scanning the H/W ring for done descriptors when the * number of available descriptors drops below tx_free_thresh. For * each done descriptor, free the associated buffer. */ if (txq->nb_tx_free < txq->tx_free_thresh) ixgbe_tx_free_bufs(txq); /* Only use descriptors that are available */ nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts); if (unlikely(nb_pkts == 0)) return 0; /* Use exactly nb_pkts descriptors */ txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts); /* * At this point, we know there are enough descriptors in the * ring to transmit all the packets. This assumes that each * mbuf contains a single segment, and that no new offloads * are expected, which would require a new context descriptor. */ /* * See if we're going to wrap-around. If so, handle the top * of the descriptor ring first, then do the bottom. If not, * the processing looks just like the "bottom" part anyway... */ if ((txq->tx_tail + nb_pkts) > txq->nb_tx_desc) { n = (uint16_t)(txq->nb_tx_desc - txq->tx_tail); ixgbe_tx_fill_hw_ring(txq, tx_pkts, n); /* * We know that the last descriptor in the ring will need to * have its RS bit set because tx_rs_thresh has to be * a divisor of the ring size */ tx_r[txq->tx_next_rs].read.cmd_type_len |= rte_cpu_to_le_32(IXGBE_ADVTXD_DCMD_RS); txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_tail = 0; } /* Fill H/W descriptor ring with mbuf data */ ixgbe_tx_fill_hw_ring(txq, tx_pkts + n, (uint16_t)(nb_pkts - n)); txq->tx_tail = (uint16_t)(txq->tx_tail + (nb_pkts - n)); /* * Determine if RS bit should be set * This is what we actually want: * if ((txq->tx_tail - 1) >= txq->tx_next_rs) * but instead of subtracting 1 and doing >=, we can just do * greater than without subtracting. */ if (txq->tx_tail > txq->tx_next_rs) { tx_r[txq->tx_next_rs].read.cmd_type_len |= rte_cpu_to_le_32(IXGBE_ADVTXD_DCMD_RS); txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh); if (txq->tx_next_rs >= txq->nb_tx_desc) txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); } /* * Check for wrap-around. This would only happen if we used * up to the last descriptor in the ring, no more, no less. */ if (txq->tx_tail >= txq->nb_tx_desc) txq->tx_tail = 0; /* update tail pointer */ rte_wmb(); IXGBE_PCI_REG_WRITE(txq->tdt_reg_addr, txq->tx_tail); return nb_pkts; } uint16_t ixgbe_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { uint16_t nb_tx; /* Try to transmit at least chunks of TX_MAX_BURST pkts */ if (likely(nb_pkts <= RTE_PMD_IXGBE_TX_MAX_BURST)) return tx_xmit_pkts(tx_queue, tx_pkts, nb_pkts); /* transmit more than the max burst, in chunks of TX_MAX_BURST */ nb_tx = 0; while (nb_pkts) { uint16_t ret, n; n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_IXGBE_TX_MAX_BURST); ret = tx_xmit_pkts(tx_queue, &(tx_pkts[nb_tx]), n); nb_tx = (uint16_t)(nb_tx + ret); nb_pkts = (uint16_t)(nb_pkts - ret); if (ret < n) break; } return nb_tx; } static inline void ixgbe_set_xmit_ctx(struct ixgbe_tx_queue *txq, volatile struct ixgbe_adv_tx_context_desc *ctx_txd, uint64_t ol_flags, union ixgbe_tx_offload tx_offload) { uint32_t type_tucmd_mlhl; uint32_t mss_l4len_idx = 0; uint32_t ctx_idx; uint32_t vlan_macip_lens; union ixgbe_tx_offload tx_offload_mask; ctx_idx = txq->ctx_curr; tx_offload_mask.data = 0; type_tucmd_mlhl = 0; /* Specify which HW CTX to upload. */ mss_l4len_idx |= (ctx_idx << IXGBE_ADVTXD_IDX_SHIFT); if (ol_flags & PKT_TX_VLAN_PKT) { tx_offload_mask.vlan_tci |= ~0; } /* check if TCP segmentation required for this packet */ if (ol_flags & PKT_TX_TCP_SEG) { /* implies IP cksum in IPv4 */ if (ol_flags & PKT_TX_IP_CKSUM) type_tucmd_mlhl = IXGBE_ADVTXD_TUCMD_IPV4 | IXGBE_ADVTXD_TUCMD_L4T_TCP | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; else type_tucmd_mlhl = IXGBE_ADVTXD_TUCMD_IPV6 | IXGBE_ADVTXD_TUCMD_L4T_TCP | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; tx_offload_mask.l2_len |= ~0; tx_offload_mask.l3_len |= ~0; tx_offload_mask.l4_len |= ~0; tx_offload_mask.tso_segsz |= ~0; mss_l4len_idx |= tx_offload.tso_segsz << IXGBE_ADVTXD_MSS_SHIFT; mss_l4len_idx |= tx_offload.l4_len << IXGBE_ADVTXD_L4LEN_SHIFT; } else { /* no TSO, check if hardware checksum is needed */ if (ol_flags & PKT_TX_IP_CKSUM) { type_tucmd_mlhl = IXGBE_ADVTXD_TUCMD_IPV4; tx_offload_mask.l2_len |= ~0; tx_offload_mask.l3_len |= ~0; } switch (ol_flags & PKT_TX_L4_MASK) { case PKT_TX_UDP_CKSUM: type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct udp_hdr) << IXGBE_ADVTXD_L4LEN_SHIFT; tx_offload_mask.l2_len |= ~0; tx_offload_mask.l3_len |= ~0; break; case PKT_TX_TCP_CKSUM: type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct tcp_hdr) << IXGBE_ADVTXD_L4LEN_SHIFT; tx_offload_mask.l2_len |= ~0; tx_offload_mask.l3_len |= ~0; tx_offload_mask.l4_len |= ~0; break; case PKT_TX_SCTP_CKSUM: type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_SCTP | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; mss_l4len_idx |= sizeof(struct sctp_hdr) << IXGBE_ADVTXD_L4LEN_SHIFT; tx_offload_mask.l2_len |= ~0; tx_offload_mask.l3_len |= ~0; break; default: type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_RSV | IXGBE_ADVTXD_DTYP_CTXT | IXGBE_ADVTXD_DCMD_DEXT; break; } } txq->ctx_cache[ctx_idx].flags = ol_flags; txq->ctx_cache[ctx_idx].tx_offload.data = tx_offload_mask.data & tx_offload.data; txq->ctx_cache[ctx_idx].tx_offload_mask = tx_offload_mask; ctx_txd->type_tucmd_mlhl = rte_cpu_to_le_32(type_tucmd_mlhl); vlan_macip_lens = tx_offload.l3_len; vlan_macip_lens |= (tx_offload.l2_len << IXGBE_ADVTXD_MACLEN_SHIFT); vlan_macip_lens |= ((uint32_t)tx_offload.vlan_tci << IXGBE_ADVTXD_VLAN_SHIFT); ctx_txd->vlan_macip_lens = rte_cpu_to_le_32(vlan_macip_lens); ctx_txd->mss_l4len_idx = rte_cpu_to_le_32(mss_l4len_idx); ctx_txd->seqnum_seed = 0; } /* * Check which hardware context can be used. Use the existing match * or create a new context descriptor. */ static inline uint32_t what_advctx_update(struct ixgbe_tx_queue *txq, uint64_t flags, union ixgbe_tx_offload tx_offload) { /* If match with the current used context */ if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) && (txq->ctx_cache[txq->ctx_curr].tx_offload.data == (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data & tx_offload.data)))) { return txq->ctx_curr; } /* What if match with the next context */ txq->ctx_curr ^= 1; if (likely((txq->ctx_cache[txq->ctx_curr].flags == flags) && (txq->ctx_cache[txq->ctx_curr].tx_offload.data == (txq->ctx_cache[txq->ctx_curr].tx_offload_mask.data & tx_offload.data)))) { return txq->ctx_curr; } /* Mismatch, use the previous context */ return (IXGBE_CTX_NUM); } static inline uint32_t tx_desc_cksum_flags_to_olinfo(uint64_t ol_flags) { uint32_t tmp = 0; if ((ol_flags & PKT_TX_L4_MASK) != PKT_TX_L4_NO_CKSUM) tmp |= IXGBE_ADVTXD_POPTS_TXSM; if (ol_flags & PKT_TX_IP_CKSUM) tmp |= IXGBE_ADVTXD_POPTS_IXSM; if (ol_flags & PKT_TX_TCP_SEG) tmp |= IXGBE_ADVTXD_POPTS_TXSM; return tmp; } static inline uint32_t tx_desc_ol_flags_to_cmdtype(uint64_t ol_flags) { uint32_t cmdtype = 0; if (ol_flags & PKT_TX_VLAN_PKT) cmdtype |= IXGBE_ADVTXD_DCMD_VLE; if (ol_flags & PKT_TX_TCP_SEG) cmdtype |= IXGBE_ADVTXD_DCMD_TSE; return cmdtype; } /* Default RS bit threshold values */ #ifndef DEFAULT_TX_RS_THRESH #define DEFAULT_TX_RS_THRESH 32 #endif #ifndef DEFAULT_TX_FREE_THRESH #define DEFAULT_TX_FREE_THRESH 32 #endif /* Reset transmit descriptors after they have been used */ static inline int ixgbe_xmit_cleanup(struct ixgbe_tx_queue *txq) { struct ixgbe_tx_entry *sw_ring = txq->sw_ring; volatile union ixgbe_adv_tx_desc *txr = txq->tx_ring; uint16_t last_desc_cleaned = txq->last_desc_cleaned; uint16_t nb_tx_desc = txq->nb_tx_desc; uint16_t desc_to_clean_to; uint16_t nb_tx_to_clean; uint32_t status; /* Determine the last descriptor needing to be cleaned */ desc_to_clean_to = (uint16_t)(last_desc_cleaned + txq->tx_rs_thresh); if (desc_to_clean_to >= nb_tx_desc) desc_to_clean_to = (uint16_t)(desc_to_clean_to - nb_tx_desc); /* Check to make sure the last descriptor to clean is done */ desc_to_clean_to = sw_ring[desc_to_clean_to].last_id; status = txr[desc_to_clean_to].wb.status; if (!(status & rte_cpu_to_le_32(IXGBE_TXD_STAT_DD))) { PMD_TX_FREE_LOG(DEBUG, "TX descriptor %4u is not done" "(port=%d queue=%d)", desc_to_clean_to, txq->port_id, txq->queue_id); /* Failed to clean any descriptors, better luck next time */ return -(1); } /* Figure out how many descriptors will be cleaned */ if (last_desc_cleaned > desc_to_clean_to) nb_tx_to_clean = (uint16_t)((nb_tx_desc - last_desc_cleaned) + desc_to_clean_to); else nb_tx_to_clean = (uint16_t)(desc_to_clean_to - last_desc_cleaned); PMD_TX_FREE_LOG(DEBUG, "Cleaning %4u TX descriptors: %4u to %4u " "(port=%d queue=%d)", nb_tx_to_clean, last_desc_cleaned, desc_to_clean_to, txq->port_id, txq->queue_id); /* * The last descriptor to clean is done, so that means all the * descriptors from the last descriptor that was cleaned * up to the last descriptor with the RS bit set * are done. Only reset the threshold descriptor. */ txr[desc_to_clean_to].wb.status = 0; /* Update the txq to reflect the last descriptor that was cleaned */ txq->last_desc_cleaned = desc_to_clean_to; txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + nb_tx_to_clean); /* No Error */ return (0); } uint16_t ixgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct ixgbe_tx_queue *txq; struct ixgbe_tx_entry *sw_ring; struct ixgbe_tx_entry *txe, *txn; volatile union ixgbe_adv_tx_desc *txr; volatile union ixgbe_adv_tx_desc *txd; struct rte_mbuf *tx_pkt; struct rte_mbuf *m_seg; uint64_t buf_dma_addr; uint32_t olinfo_status; uint32_t cmd_type_len; uint32_t pkt_len; uint16_t slen; uint64_t ol_flags; uint16_t tx_id; uint16_t tx_last; uint16_t nb_tx; uint16_t nb_used; uint64_t tx_ol_req; uint32_t ctx = 0; uint32_t new_ctx; union ixgbe_tx_offload tx_offload = {0}; txq = tx_queue; sw_ring = txq->sw_ring; txr = txq->tx_ring; tx_id = txq->tx_tail; txe = &sw_ring[tx_id]; /* Determine if the descriptor ring needs to be cleaned. */ if (txq->nb_tx_free < txq->tx_free_thresh) ixgbe_xmit_cleanup(txq); rte_prefetch0(&txe->mbuf->pool); /* TX loop */ for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) { new_ctx = 0; tx_pkt = *tx_pkts++; pkt_len = tx_pkt->pkt_len; /* * Determine how many (if any) context descriptors * are needed for offload functionality. */ ol_flags = tx_pkt->ol_flags; /* If hardware offload required */ tx_ol_req = ol_flags & IXGBE_TX_OFFLOAD_MASK; if (tx_ol_req) { tx_offload.l2_len = tx_pkt->l2_len; tx_offload.l3_len = tx_pkt->l3_len; tx_offload.l4_len = tx_pkt->l4_len; tx_offload.vlan_tci = tx_pkt->vlan_tci; tx_offload.tso_segsz = tx_pkt->tso_segsz; /* If new context need be built or reuse the exist ctx. */ ctx = what_advctx_update(txq, tx_ol_req, tx_offload); /* Only allocate context descriptor if required*/ new_ctx = (ctx == IXGBE_CTX_NUM); ctx = txq->ctx_curr; } /* * Keep track of how many descriptors are used this loop * This will always be the number of segments + the number of * Context descriptors required to transmit the packet */ nb_used = (uint16_t)(tx_pkt->nb_segs + new_ctx); /* * The number of descriptors that must be allocated for a * packet is the number of segments of that packet, plus 1 * Context Descriptor for the hardware offload, if any. * Determine the last TX descriptor to allocate in the TX ring * for the packet, starting from the current position (tx_id) * in the ring. */ tx_last = (uint16_t) (tx_id + nb_used - 1); /* Circular ring */ if (tx_last >= txq->nb_tx_desc) tx_last = (uint16_t) (tx_last - txq->nb_tx_desc); PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u pktlen=%u" " tx_first=%u tx_last=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) pkt_len, (unsigned) tx_id, (unsigned) tx_last); /* * Make sure there are enough TX descriptors available to * transmit the entire packet. * nb_used better be less than or equal to txq->tx_rs_thresh */ if (nb_used > txq->nb_tx_free) { PMD_TX_FREE_LOG(DEBUG, "Not enough free TX descriptors " "nb_used=%4u nb_free=%4u " "(port=%d queue=%d)", nb_used, txq->nb_tx_free, txq->port_id, txq->queue_id); if (ixgbe_xmit_cleanup(txq) != 0) { /* Could not clean any descriptors */ if (nb_tx == 0) return (0); goto end_of_tx; } /* nb_used better be <= txq->tx_rs_thresh */ if (unlikely(nb_used > txq->tx_rs_thresh)) { PMD_TX_FREE_LOG(DEBUG, "The number of descriptors needed to " "transmit the packet exceeds the " "RS bit threshold. This will impact " "performance." "nb_used=%4u nb_free=%4u " "tx_rs_thresh=%4u. " "(port=%d queue=%d)", nb_used, txq->nb_tx_free, txq->tx_rs_thresh, txq->port_id, txq->queue_id); /* * Loop here until there are enough TX * descriptors or until the ring cannot be * cleaned. */ while (nb_used > txq->nb_tx_free) { if (ixgbe_xmit_cleanup(txq) != 0) { /* * Could not clean any * descriptors */ if (nb_tx == 0) return (0); goto end_of_tx; } } } } /* * By now there are enough free TX descriptors to transmit * the packet. */ /* * Set common flags of all TX Data Descriptors. * * The following bits must be set in all Data Descriptors: * - IXGBE_ADVTXD_DTYP_DATA * - IXGBE_ADVTXD_DCMD_DEXT * * The following bits must be set in the first Data Descriptor * and are ignored in the other ones: * - IXGBE_ADVTXD_DCMD_IFCS * - IXGBE_ADVTXD_MAC_1588 * - IXGBE_ADVTXD_DCMD_VLE * * The following bits must only be set in the last Data * Descriptor: * - IXGBE_TXD_CMD_EOP * * The following bits can be set in any Data Descriptor, but * are only set in the last Data Descriptor: * - IXGBE_TXD_CMD_RS */ cmd_type_len = IXGBE_ADVTXD_DTYP_DATA | IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT; #ifdef RTE_LIBRTE_IEEE1588 if (ol_flags & PKT_TX_IEEE1588_TMST) cmd_type_len |= IXGBE_ADVTXD_MAC_1588; #endif olinfo_status = 0; if (tx_ol_req) { if (ol_flags & PKT_TX_TCP_SEG) { /* when TSO is on, paylen in descriptor is the * not the packet len but the tcp payload len */ pkt_len -= (tx_offload.l2_len + tx_offload.l3_len + tx_offload.l4_len); } /* * Setup the TX Advanced Context Descriptor if required */ if (new_ctx) { volatile struct ixgbe_adv_tx_context_desc * ctx_txd; ctx_txd = (volatile struct ixgbe_adv_tx_context_desc *) &txr[tx_id]; txn = &sw_ring[txe->next_id]; rte_prefetch0(&txn->mbuf->pool); if (txe->mbuf != NULL) { rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = NULL; } ixgbe_set_xmit_ctx(txq, ctx_txd, tx_ol_req, tx_offload); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; } /* * Setup the TX Advanced Data Descriptor, * This path will go through * whatever new/reuse the context descriptor */ cmd_type_len |= tx_desc_ol_flags_to_cmdtype(ol_flags); olinfo_status |= tx_desc_cksum_flags_to_olinfo(ol_flags); olinfo_status |= ctx << IXGBE_ADVTXD_IDX_SHIFT; } olinfo_status |= (pkt_len << IXGBE_ADVTXD_PAYLEN_SHIFT); m_seg = tx_pkt; do { txd = &txr[tx_id]; txn = &sw_ring[txe->next_id]; rte_prefetch0(&txn->mbuf->pool); if (txe->mbuf != NULL) rte_pktmbuf_free_seg(txe->mbuf); txe->mbuf = m_seg; /* * Set up Transmit Data Descriptor. */ slen = m_seg->data_len; buf_dma_addr = RTE_MBUF_DATA_DMA_ADDR(m_seg); txd->read.buffer_addr = rte_cpu_to_le_64(buf_dma_addr); txd->read.cmd_type_len = rte_cpu_to_le_32(cmd_type_len | slen); txd->read.olinfo_status = rte_cpu_to_le_32(olinfo_status); txe->last_id = tx_last; tx_id = txe->next_id; txe = txn; m_seg = m_seg->next; } while (m_seg != NULL); /* * The last packet data descriptor needs End Of Packet (EOP) */ cmd_type_len |= IXGBE_TXD_CMD_EOP; txq->nb_tx_used = (uint16_t)(txq->nb_tx_used + nb_used); txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_used); /* Set RS bit only on threshold packets' last descriptor */ if (txq->nb_tx_used >= txq->tx_rs_thresh) { PMD_TX_FREE_LOG(DEBUG, "Setting RS bit on TXD id=" "%4u (port=%d queue=%d)", tx_last, txq->port_id, txq->queue_id); cmd_type_len |= IXGBE_TXD_CMD_RS; /* Update txq RS bit counters */ txq->nb_tx_used = 0; } txd->read.cmd_type_len |= rte_cpu_to_le_32(cmd_type_len); } end_of_tx: rte_wmb(); /* * Set the Transmit Descriptor Tail (TDT) */ PMD_TX_LOG(DEBUG, "port_id=%u queue_id=%u tx_tail=%u nb_tx=%u", (unsigned) txq->port_id, (unsigned) txq->queue_id, (unsigned) tx_id, (unsigned) nb_tx); IXGBE_PCI_REG_WRITE(txq->tdt_reg_addr, tx_id); txq->tx_tail = tx_id; return (nb_tx); } /********************************************************************* * * RX functions * **********************************************************************/ #ifdef RTE_NEXT_ABI #define IXGBE_PACKET_TYPE_IPV4 0X01 #define IXGBE_PACKET_TYPE_IPV4_TCP 0X11 #define IXGBE_PACKET_TYPE_IPV4_UDP 0X21 #define IXGBE_PACKET_TYPE_IPV4_SCTP 0X41 #define IXGBE_PACKET_TYPE_IPV4_EXT 0X03 #define IXGBE_PACKET_TYPE_IPV4_EXT_SCTP 0X43 #define IXGBE_PACKET_TYPE_IPV6 0X04 #define IXGBE_PACKET_TYPE_IPV6_TCP 0X14 #define IXGBE_PACKET_TYPE_IPV6_UDP 0X24 #define IXGBE_PACKET_TYPE_IPV6_EXT 0X0C #define IXGBE_PACKET_TYPE_IPV6_EXT_TCP 0X1C #define IXGBE_PACKET_TYPE_IPV6_EXT_UDP 0X2C #define IXGBE_PACKET_TYPE_IPV4_IPV6 0X05 #define IXGBE_PACKET_TYPE_IPV4_IPV6_TCP 0X15 #define IXGBE_PACKET_TYPE_IPV4_IPV6_UDP 0X25 #define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT 0X0D #define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP 0X1D #define IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP 0X2D #define IXGBE_PACKET_TYPE_MAX 0X80 #define IXGBE_PACKET_TYPE_MASK 0X7F #define IXGBE_PACKET_TYPE_SHIFT 0X04 static inline uint32_t ixgbe_rxd_pkt_info_to_pkt_type(uint16_t pkt_info) { static const uint32_t ptype_table[IXGBE_PACKET_TYPE_MAX] __rte_cache_aligned = { [IXGBE_PACKET_TYPE_IPV4] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4, [IXGBE_PACKET_TYPE_IPV4_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT, [IXGBE_PACKET_TYPE_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6, [IXGBE_PACKET_TYPE_IPV4_IPV6] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6, [IXGBE_PACKET_TYPE_IPV6_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT, [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT, [IXGBE_PACKET_TYPE_IPV4_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP, [IXGBE_PACKET_TYPE_IPV6_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP, [IXGBE_PACKET_TYPE_IPV4_IPV6_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_TCP, [IXGBE_PACKET_TYPE_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_TCP, [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_TCP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_TCP, [IXGBE_PACKET_TYPE_IPV4_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP, [IXGBE_PACKET_TYPE_IPV6_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP, [IXGBE_PACKET_TYPE_IPV4_IPV6_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6 | RTE_PTYPE_INNER_L4_UDP, [IXGBE_PACKET_TYPE_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_UDP, [IXGBE_PACKET_TYPE_IPV4_IPV6_EXT_UDP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_IP | RTE_PTYPE_INNER_L3_IPV6_EXT | RTE_PTYPE_INNER_L4_UDP, [IXGBE_PACKET_TYPE_IPV4_SCTP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP, [IXGBE_PACKET_TYPE_IPV4_EXT_SCTP] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_SCTP, }; if (unlikely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF)) return RTE_PTYPE_UNKNOWN; pkt_info = (pkt_info >> IXGBE_PACKET_TYPE_SHIFT) & IXGBE_PACKET_TYPE_MASK; return ptype_table[pkt_info]; } static inline uint64_t ixgbe_rxd_pkt_info_to_pkt_flags(uint16_t pkt_info) { static uint64_t ip_rss_types_map[16] __rte_cache_aligned = { 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, 0, 0, 0, 0, 0, PKT_RX_FDIR, }; #ifdef RTE_LIBRTE_IEEE1588 static uint64_t ip_pkt_etqf_map[8] = { 0, 0, 0, PKT_RX_IEEE1588_PTP, 0, 0, 0, 0, }; if (likely(pkt_info & IXGBE_RXDADV_PKTTYPE_ETQF)) return ip_pkt_etqf_map[(pkt_info >> 4) & 0X07] | ip_rss_types_map[pkt_info & 0XF]; else return ip_rss_types_map[pkt_info & 0XF]; #else return ip_rss_types_map[pkt_info & 0XF]; #endif } #else /* RTE_NEXT_ABI */ static inline uint64_t rx_desc_hlen_type_rss_to_pkt_flags(uint32_t hl_tp_rs) { uint64_t pkt_flags; static const uint64_t ip_pkt_types_map[16] = { 0, PKT_RX_IPV4_HDR, PKT_RX_IPV4_HDR_EXT, PKT_RX_IPV4_HDR_EXT, PKT_RX_IPV6_HDR, 0, 0, 0, PKT_RX_IPV6_HDR_EXT, 0, 0, 0, PKT_RX_IPV6_HDR_EXT, 0, 0, 0, }; static const uint64_t ip_rss_types_map[16] = { 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, 0, 0, 0, 0, 0, PKT_RX_FDIR, }; #ifdef RTE_LIBRTE_IEEE1588 static uint64_t ip_pkt_etqf_map[8] = { 0, 0, 0, PKT_RX_IEEE1588_PTP, 0, 0, 0, 0, }; pkt_flags = (hl_tp_rs & IXGBE_RXDADV_PKTTYPE_ETQF) ? ip_pkt_etqf_map[(hl_tp_rs >> 4) & 0x07] : ip_pkt_types_map[(hl_tp_rs >> 4) & 0x0F]; #else pkt_flags = (hl_tp_rs & IXGBE_RXDADV_PKTTYPE_ETQF) ? 0 : ip_pkt_types_map[(hl_tp_rs >> 4) & 0x0F]; #endif return pkt_flags | ip_rss_types_map[hl_tp_rs & 0xF]; } #endif /* RTE_NEXT_ABI */ static inline uint64_t rx_desc_status_to_pkt_flags(uint32_t rx_status) { uint64_t pkt_flags; /* * Check if VLAN present only. * Do not check whether L3/L4 rx checksum done by NIC or not, * That can be found from rte_eth_rxmode.hw_ip_checksum flag */ pkt_flags = (rx_status & IXGBE_RXD_STAT_VP) ? PKT_RX_VLAN_PKT : 0; #ifdef RTE_LIBRTE_IEEE1588 if (rx_status & IXGBE_RXD_STAT_TMST) pkt_flags = pkt_flags | PKT_RX_IEEE1588_TMST; #endif return pkt_flags; } static inline uint64_t rx_desc_error_to_pkt_flags(uint32_t rx_status) { /* * Bit 31: IPE, IPv4 checksum error * Bit 30: L4I, L4I integrity error */ static uint64_t error_to_pkt_flags_map[4] = { 0, PKT_RX_L4_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD }; return error_to_pkt_flags_map[(rx_status >> IXGBE_RXDADV_ERR_CKSUM_BIT) & IXGBE_RXDADV_ERR_CKSUM_MSK]; } /* * LOOK_AHEAD defines how many desc statuses to check beyond the * current descriptor. * It must be a pound define for optimal performance. * Do not change the value of LOOK_AHEAD, as the ixgbe_rx_scan_hw_ring * function only works with LOOK_AHEAD=8. */ #define LOOK_AHEAD 8 #if (LOOK_AHEAD != 8) #error "PMD IXGBE: LOOK_AHEAD must be 8\n" #endif static inline int ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq) { volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *rxep; struct rte_mbuf *mb; uint16_t pkt_len; uint64_t pkt_flags; #ifdef RTE_NEXT_ABI int nb_dd; uint32_t s[LOOK_AHEAD]; uint16_t pkt_info[LOOK_AHEAD]; #else int s[LOOK_AHEAD], nb_dd; #endif /* RTE_NEXT_ABI */ int i, j, nb_rx = 0; uint32_t status; /* get references to current descriptor and S/W ring entry */ rxdp = &rxq->rx_ring[rxq->rx_tail]; rxep = &rxq->sw_ring[rxq->rx_tail]; status = rxdp->wb.upper.status_error; /* check to make sure there is at least 1 packet to receive */ if (!(status & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))) return 0; /* * Scan LOOK_AHEAD descriptors at a time to determine which descriptors * reference packets that are ready to be received. */ for (i = 0; i < RTE_PMD_IXGBE_RX_MAX_BURST; i += LOOK_AHEAD, rxdp += LOOK_AHEAD, rxep += LOOK_AHEAD) { /* Read desc statuses backwards to avoid race condition */ for (j = LOOK_AHEAD-1; j >= 0; --j) s[j] = rte_le_to_cpu_32(rxdp[j].wb.upper.status_error); #ifdef RTE_NEXT_ABI for (j = LOOK_AHEAD - 1; j >= 0; --j) pkt_info[j] = rxdp[j].wb.lower.lo_dword. hs_rss.pkt_info; #endif /* RTE_NEXT_ABI */ /* Compute how many status bits were set */ nb_dd = 0; for (j = 0; j < LOOK_AHEAD; ++j) nb_dd += s[j] & IXGBE_RXDADV_STAT_DD; nb_rx += nb_dd; /* Translate descriptor info to mbuf format */ for (j = 0; j < nb_dd; ++j) { mb = rxep[j].mbuf; pkt_len = rte_le_to_cpu_16(rxdp[j].wb.upper.length) - rxq->crc_len; mb->data_len = pkt_len; mb->pkt_len = pkt_len; mb->vlan_tci = rte_le_to_cpu_16(rxdp[j].wb.upper.vlan); /* convert descriptor fields to rte mbuf flags */ #ifdef RTE_NEXT_ABI pkt_flags = rx_desc_status_to_pkt_flags(s[j]); pkt_flags |= rx_desc_error_to_pkt_flags(s[j]); pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info[j]); mb->ol_flags = pkt_flags; mb->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info[j]); #else /* RTE_NEXT_ABI */ pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags( rte_le_to_cpu_32( rxdp[j].wb.lower.lo_dword.data)); /* reuse status field from scan list */ pkt_flags |= rx_desc_status_to_pkt_flags(s[j]); pkt_flags |= rx_desc_error_to_pkt_flags(s[j]); mb->ol_flags = pkt_flags; #endif /* RTE_NEXT_ABI */ if (likely(pkt_flags & PKT_RX_RSS_HASH)) mb->hash.rss = rte_le_to_cpu_32( rxdp[j].wb.lower.hi_dword.rss); else if (pkt_flags & PKT_RX_FDIR) { mb->hash.fdir.hash = rte_le_to_cpu_16( rxdp[j].wb.lower.hi_dword.csum_ip.csum) & IXGBE_ATR_HASH_MASK; mb->hash.fdir.id = rte_le_to_cpu_16( rxdp[j].wb.lower.hi_dword.csum_ip.ip_id); } } /* Move mbuf pointers from the S/W ring to the stage */ for (j = 0; j < LOOK_AHEAD; ++j) { rxq->rx_stage[i + j] = rxep[j].mbuf; } /* stop if all requested packets could not be received */ if (nb_dd != LOOK_AHEAD) break; } /* clear software ring entries so we can cleanup correctly */ for (i = 0; i < nb_rx; ++i) { rxq->sw_ring[rxq->rx_tail + i].mbuf = NULL; } return nb_rx; } static inline int ixgbe_rx_alloc_bufs(struct ixgbe_rx_queue *rxq, bool reset_mbuf) { volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *rxep; struct rte_mbuf *mb; uint16_t alloc_idx; __le64 dma_addr; int diag, i; /* allocate buffers in bulk directly into the S/W ring */ alloc_idx = rxq->rx_free_trigger - (rxq->rx_free_thresh - 1); rxep = &rxq->sw_ring[alloc_idx]; diag = rte_mempool_get_bulk(rxq->mb_pool, (void *)rxep, rxq->rx_free_thresh); if (unlikely(diag != 0)) return (-ENOMEM); rxdp = &rxq->rx_ring[alloc_idx]; for (i = 0; i < rxq->rx_free_thresh; ++i) { /* populate the static rte mbuf fields */ mb = rxep[i].mbuf; if (reset_mbuf) { mb->next = NULL; mb->nb_segs = 1; mb->port = rxq->port_id; } rte_mbuf_refcnt_set(mb, 1); mb->data_off = RTE_PKTMBUF_HEADROOM; /* populate the descriptors */ dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb)); rxdp[i].read.hdr_addr = 0; rxdp[i].read.pkt_addr = dma_addr; } /* update state of internal queue structure */ rxq->rx_free_trigger = rxq->rx_free_trigger + rxq->rx_free_thresh; if (rxq->rx_free_trigger >= rxq->nb_rx_desc) rxq->rx_free_trigger = rxq->rx_free_thresh - 1; /* no errors */ return 0; } static inline uint16_t ixgbe_rx_fill_from_stage(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct rte_mbuf **stage = &rxq->rx_stage[rxq->rx_next_avail]; int i; /* how many packets are ready to return? */ nb_pkts = (uint16_t)RTE_MIN(nb_pkts, rxq->rx_nb_avail); /* copy mbuf pointers to the application's packet list */ for (i = 0; i < nb_pkts; ++i) rx_pkts[i] = stage[i]; /* update internal queue state */ rxq->rx_nb_avail = (uint16_t)(rxq->rx_nb_avail - nb_pkts); rxq->rx_next_avail = (uint16_t)(rxq->rx_next_avail + nb_pkts); return nb_pkts; } static inline uint16_t rx_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct ixgbe_rx_queue *rxq = (struct ixgbe_rx_queue *)rx_queue; uint16_t nb_rx = 0; /* Any previously recv'd pkts will be returned from the Rx stage */ if (rxq->rx_nb_avail) return ixgbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); /* Scan the H/W ring for packets to receive */ nb_rx = (uint16_t)ixgbe_rx_scan_hw_ring(rxq); /* update internal queue state */ rxq->rx_next_avail = 0; rxq->rx_nb_avail = nb_rx; rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_rx); /* if required, allocate new buffers to replenish descriptors */ if (rxq->rx_tail > rxq->rx_free_trigger) { uint16_t cur_free_trigger = rxq->rx_free_trigger; if (ixgbe_rx_alloc_bufs(rxq, true) != 0) { int i, j; PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed += rxq->rx_free_thresh; /* * Need to rewind any previous receives if we cannot * allocate new buffers to replenish the old ones. */ rxq->rx_nb_avail = 0; rxq->rx_tail = (uint16_t)(rxq->rx_tail - nb_rx); for (i = 0, j = rxq->rx_tail; i < nb_rx; ++i, ++j) rxq->sw_ring[j].mbuf = rxq->rx_stage[i]; return 0; } /* update tail pointer */ rte_wmb(); IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, cur_free_trigger); } if (rxq->rx_tail >= rxq->nb_rx_desc) rxq->rx_tail = 0; /* received any packets this loop? */ if (rxq->rx_nb_avail) return ixgbe_rx_fill_from_stage(rxq, rx_pkts, nb_pkts); return 0; } /* split requests into chunks of size RTE_PMD_IXGBE_RX_MAX_BURST */ static uint16_t ixgbe_recv_pkts_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { uint16_t nb_rx; if (unlikely(nb_pkts == 0)) return 0; if (likely(nb_pkts <= RTE_PMD_IXGBE_RX_MAX_BURST)) return rx_recv_pkts(rx_queue, rx_pkts, nb_pkts); /* request is relatively large, chunk it up */ nb_rx = 0; while (nb_pkts) { uint16_t ret, n; n = (uint16_t)RTE_MIN(nb_pkts, RTE_PMD_IXGBE_RX_MAX_BURST); ret = rx_recv_pkts(rx_queue, &rx_pkts[nb_rx], n); nb_rx = (uint16_t)(nb_rx + ret); nb_pkts = (uint16_t)(nb_pkts - ret); if (ret < n) break; } return nb_rx; } uint16_t ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct ixgbe_rx_queue *rxq; volatile union ixgbe_adv_rx_desc *rx_ring; volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *sw_ring; struct ixgbe_rx_entry *rxe; struct rte_mbuf *rxm; struct rte_mbuf *nmb; union ixgbe_adv_rx_desc rxd; uint64_t dma_addr; uint32_t staterr; #ifdef RTE_NEXT_ABI uint32_t pkt_info; #else uint32_t hlen_type_rss; #endif uint16_t pkt_len; uint16_t rx_id; uint16_t nb_rx; uint16_t nb_hold; uint64_t pkt_flags; nb_rx = 0; nb_hold = 0; rxq = rx_queue; rx_id = rxq->rx_tail; rx_ring = rxq->rx_ring; sw_ring = rxq->sw_ring; while (nb_rx < nb_pkts) { /* * The order of operations here is important as the DD status * bit must not be read after any other descriptor fields. * rx_ring and rxdp are pointing to volatile data so the order * of accesses cannot be reordered by the compiler. If they were * not volatile, they could be reordered which could lead to * using invalid descriptor fields when read from rxd. */ rxdp = &rx_ring[rx_id]; staterr = rxdp->wb.upper.status_error; if (!(staterr & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))) break; rxd = *rxdp; /* * End of packet. * * If the IXGBE_RXDADV_STAT_EOP flag is not set, the RX packet * is likely to be invalid and to be dropped by the various * validation checks performed by the network stack. * * Allocate a new mbuf to replenish the RX ring descriptor. * If the allocation fails: * - arrange for that RX descriptor to be the first one * being parsed the next time the receive function is * invoked [on the same queue]. * * - Stop parsing the RX ring and return immediately. * * This policy do not drop the packet received in the RX * descriptor for which the allocation of a new mbuf failed. * Thus, it allows that packet to be later retrieved if * mbuf have been freed in the mean time. * As a side effect, holding RX descriptors instead of * systematically giving them back to the NIC may lead to * RX ring exhaustion situations. * However, the NIC can gracefully prevent such situations * to happen by sending specific "back-pressure" flow control * frames to its peer(s). */ PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "ext_err_stat=0x%08x pkt_len=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) staterr, (unsigned) rte_le_to_cpu_16(rxd.wb.upper.length)); nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed port_id=%u " "queue_id=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id); rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed++; break; } nb_hold++; rxe = &sw_ring[rx_id]; rx_id++; if (rx_id == rxq->nb_rx_desc) rx_id = 0; /* Prefetch next mbuf while processing current one. */ rte_ixgbe_prefetch(sw_ring[rx_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 8 pointers * to mbufs. */ if ((rx_id & 0x3) == 0) { rte_ixgbe_prefetch(&rx_ring[rx_id]); rte_ixgbe_prefetch(&sw_ring[rx_id]); } rxm = rxe->mbuf; rxe->mbuf = nmb; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); rxdp->read.hdr_addr = 0; rxdp->read.pkt_addr = dma_addr; /* * Initialize the returned mbuf. * 1) setup generic mbuf fields: * - number of segments, * - next segment, * - packet length, * - RX port identifier. * 2) integrate hardware offload data, if any: * - RSS flag & hash, * - IP checksum flag, * - VLAN TCI, if any, * - error flags. */ pkt_len = (uint16_t) (rte_le_to_cpu_16(rxd.wb.upper.length) - rxq->crc_len); rxm->data_off = RTE_PKTMBUF_HEADROOM; rte_packet_prefetch((char *)rxm->buf_addr + rxm->data_off); rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = pkt_len; rxm->data_len = pkt_len; rxm->port = rxq->port_id; #ifdef RTE_NEXT_ABI pkt_info = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.hs_rss. pkt_info); /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan); pkt_flags = rx_desc_status_to_pkt_flags(staterr); pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr); pkt_flags = pkt_flags | ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info); rxm->ol_flags = pkt_flags; rxm->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info); #else /* RTE_NEXT_ABI */ hlen_type_rss = rte_le_to_cpu_32(rxd.wb.lower.lo_dword.data); /* Only valid if PKT_RX_VLAN_PKT set in pkt_flags */ rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan); pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss); pkt_flags = pkt_flags | rx_desc_status_to_pkt_flags(staterr); pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr); rxm->ol_flags = pkt_flags; #endif /* RTE_NEXT_ABI */ if (likely(pkt_flags & PKT_RX_RSS_HASH)) rxm->hash.rss = rte_le_to_cpu_32( rxd.wb.lower.hi_dword.rss); else if (pkt_flags & PKT_RX_FDIR) { rxm->hash.fdir.hash = rte_le_to_cpu_16( rxd.wb.lower.hi_dword.csum_ip.csum) & IXGBE_ATR_HASH_MASK; rxm->hash.fdir.id = rte_le_to_cpu_16( rxd.wb.lower.hi_dword.csum_ip.ip_id); } /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = rxm; } rxq->rx_tail = rx_id; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ nb_hold = (uint16_t) (nb_hold + rxq->nb_rx_hold); if (nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", (unsigned) rxq->port_id, (unsigned) rxq->queue_id, (unsigned) rx_id, (unsigned) nb_hold, (unsigned) nb_rx); rx_id = (uint16_t) ((rx_id == 0) ? (rxq->nb_rx_desc - 1) : (rx_id - 1)); IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return (nb_rx); } /** * Detect an RSC descriptor. */ static inline uint32_t ixgbe_rsc_count(union ixgbe_adv_rx_desc *rx) { return (rte_le_to_cpu_32(rx->wb.lower.lo_dword.data) & IXGBE_RXDADV_RSCCNT_MASK) >> IXGBE_RXDADV_RSCCNT_SHIFT; } /** * ixgbe_fill_cluster_head_buf - fill the first mbuf of the returned packet * * Fill the following info in the HEAD buffer of the Rx cluster: * - RX port identifier * - hardware offload data, if any: * - RSS flag & hash * - IP checksum flag * - VLAN TCI, if any * - error flags * @head HEAD of the packet cluster * @desc HW descriptor to get data from * @port_id Port ID of the Rx queue */ static inline void ixgbe_fill_cluster_head_buf( struct rte_mbuf *head, union ixgbe_adv_rx_desc *desc, uint8_t port_id, uint32_t staterr) { #ifdef RTE_NEXT_ABI uint16_t pkt_info; uint64_t pkt_flags; head->port = port_id; /* The vlan_tci field is only valid when PKT_RX_VLAN_PKT is * set in the pkt_flags field. */ head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan); pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.hs_rss.pkt_info); pkt_flags = rx_desc_status_to_pkt_flags(staterr); pkt_flags |= rx_desc_error_to_pkt_flags(staterr); pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags(pkt_info); head->ol_flags = pkt_flags; head->packet_type = ixgbe_rxd_pkt_info_to_pkt_type(pkt_info); #else /* RTE_NEXT_ABI */ uint32_t hlen_type_rss; uint64_t pkt_flags; head->port = port_id; /* * The vlan_tci field is only valid when PKT_RX_VLAN_PKT is * set in the pkt_flags field. */ head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan); hlen_type_rss = rte_le_to_cpu_32(desc->wb.lower.lo_dword.data); pkt_flags = rx_desc_hlen_type_rss_to_pkt_flags(hlen_type_rss); pkt_flags |= rx_desc_status_to_pkt_flags(staterr); pkt_flags |= rx_desc_error_to_pkt_flags(staterr); head->ol_flags = pkt_flags; #endif /* RTE_NEXT_ABI */ if (likely(pkt_flags & PKT_RX_RSS_HASH)) head->hash.rss = rte_le_to_cpu_32(desc->wb.lower.hi_dword.rss); else if (pkt_flags & PKT_RX_FDIR) { head->hash.fdir.hash = rte_le_to_cpu_16(desc->wb.lower.hi_dword.csum_ip.csum) & IXGBE_ATR_HASH_MASK; head->hash.fdir.id = rte_le_to_cpu_16(desc->wb.lower.hi_dword.csum_ip.ip_id); } } /** * ixgbe_recv_pkts_lro - receive handler for and LRO case. * * @rx_queue Rx queue handle * @rx_pkts table of received packets * @nb_pkts size of rx_pkts table * @bulk_alloc if TRUE bulk allocation is used for a HW ring refilling * * Handles the Rx HW ring completions when RSC feature is configured. Uses an * additional ring of ixgbe_rsc_entry's that will hold the relevant RSC info. * * We use the same logic as in Linux and in FreeBSD ixgbe drivers: * 1) When non-EOP RSC completion arrives: * a) Update the HEAD of the current RSC aggregation cluster with the new * segment's data length. * b) Set the "next" pointer of the current segment to point to the segment * at the NEXTP index. * c) Pass the HEAD of RSC aggregation cluster on to the next NEXTP entry * in the sw_rsc_ring. * 2) When EOP arrives we just update the cluster's total length and offload * flags and deliver the cluster up to the upper layers. In our case - put it * in the rx_pkts table. * * Returns the number of received packets/clusters (according to the "bulk * receive" interface). */ static inline uint16_t ixgbe_recv_pkts_lro(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, bool bulk_alloc) { struct ixgbe_rx_queue *rxq = rx_queue; volatile union ixgbe_adv_rx_desc *rx_ring = rxq->rx_ring; struct ixgbe_rx_entry *sw_ring = rxq->sw_ring; struct ixgbe_scattered_rx_entry *sw_sc_ring = rxq->sw_sc_ring; uint16_t rx_id = rxq->rx_tail; uint16_t nb_rx = 0; uint16_t nb_hold = rxq->nb_rx_hold; uint16_t prev_id = rxq->rx_tail; while (nb_rx < nb_pkts) { bool eop; struct ixgbe_rx_entry *rxe; struct ixgbe_scattered_rx_entry *sc_entry; struct ixgbe_scattered_rx_entry *next_sc_entry; struct ixgbe_rx_entry *next_rxe; struct rte_mbuf *first_seg; struct rte_mbuf *rxm; struct rte_mbuf *nmb; union ixgbe_adv_rx_desc rxd; uint16_t data_len; uint16_t next_id; volatile union ixgbe_adv_rx_desc *rxdp; uint32_t staterr; next_desc: /* * The code in this whole file uses the volatile pointer to * ensure the read ordering of the status and the rest of the * descriptor fields (on the compiler level only!!!). This is so * UGLY - why not to just use the compiler barrier instead? DPDK * even has the rte_compiler_barrier() for that. * * But most importantly this is just wrong because this doesn't * ensure memory ordering in a general case at all. For * instance, DPDK is supposed to work on Power CPUs where * compiler barrier may just not be enough! * * I tried to write only this function properly to have a * starting point (as a part of an LRO/RSC series) but the * compiler cursed at me when I tried to cast away the * "volatile" from rx_ring (yes, it's volatile too!!!). So, I'm * keeping it the way it is for now. * * The code in this file is broken in so many other places and * will just not work on a big endian CPU anyway therefore the * lines below will have to be revisited together with the rest * of the ixgbe PMD. * * TODO: * - Get rid of "volatile" crap and let the compiler do its * job. * - Use the proper memory barrier (rte_rmb()) to ensure the * memory ordering below. */ rxdp = &rx_ring[rx_id]; staterr = rte_le_to_cpu_32(rxdp->wb.upper.status_error); if (!(staterr & IXGBE_RXDADV_STAT_DD)) break; rxd = *rxdp; PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_id=%u " "staterr=0x%x data_len=%u", rxq->port_id, rxq->queue_id, rx_id, staterr, rte_le_to_cpu_16(rxd.wb.upper.length)); if (!bulk_alloc) { nmb = rte_rxmbuf_alloc(rxq->mb_pool); if (nmb == NULL) { PMD_RX_LOG(DEBUG, "RX mbuf alloc failed " "port_id=%u queue_id=%u", rxq->port_id, rxq->queue_id); rte_eth_devices[rxq->port_id].data-> rx_mbuf_alloc_failed++; break; } } else if (nb_hold > rxq->rx_free_thresh) { uint16_t next_rdt = rxq->rx_free_trigger; if (!ixgbe_rx_alloc_bufs(rxq, false)) { rte_wmb(); IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, next_rdt); nb_hold -= rxq->rx_free_thresh; } else { PMD_RX_LOG(DEBUG, "RX bulk alloc failed " "port_id=%u queue_id=%u", rxq->port_id, rxq->queue_id); rte_eth_devices[rxq->port_id].data-> rx_mbuf_alloc_failed++; break; } } nb_hold++; rxe = &sw_ring[rx_id]; eop = staterr & IXGBE_RXDADV_STAT_EOP; next_id = rx_id + 1; if (next_id == rxq->nb_rx_desc) next_id = 0; /* Prefetch next mbuf while processing current one. */ rte_ixgbe_prefetch(sw_ring[next_id].mbuf); /* * When next RX descriptor is on a cache-line boundary, * prefetch the next 4 RX descriptors and the next 4 pointers * to mbufs. */ if ((next_id & 0x3) == 0) { rte_ixgbe_prefetch(&rx_ring[next_id]); rte_ixgbe_prefetch(&sw_ring[next_id]); } rxm = rxe->mbuf; if (!bulk_alloc) { __le64 dma = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(nmb)); /* * Update RX descriptor with the physical address of the * new data buffer of the new allocated mbuf. */ rxe->mbuf = nmb; rxm->data_off = RTE_PKTMBUF_HEADROOM; rxdp->read.hdr_addr = 0; rxdp->read.pkt_addr = dma; } else rxe->mbuf = NULL; /* * Set data length & data buffer address of mbuf. */ data_len = rte_le_to_cpu_16(rxd.wb.upper.length); rxm->data_len = data_len; if (!eop) { uint16_t nextp_id; /* * Get next descriptor index: * - For RSC it's in the NEXTP field. * - For a scattered packet - it's just a following * descriptor. */ if (ixgbe_rsc_count(&rxd)) nextp_id = (staterr & IXGBE_RXDADV_NEXTP_MASK) >> IXGBE_RXDADV_NEXTP_SHIFT; else nextp_id = next_id; next_sc_entry = &sw_sc_ring[nextp_id]; next_rxe = &sw_ring[nextp_id]; rte_ixgbe_prefetch(next_rxe); } sc_entry = &sw_sc_ring[rx_id]; first_seg = sc_entry->fbuf; sc_entry->fbuf = NULL; /* * If this is the first buffer of the received packet, * set the pointer to the first mbuf of the packet and * initialize its context. * Otherwise, update the total length and the number of segments * of the current scattered packet, and update the pointer to * the last mbuf of the current packet. */ if (first_seg == NULL) { first_seg = rxm; first_seg->pkt_len = data_len; first_seg->nb_segs = 1; } else { first_seg->pkt_len += data_len; first_seg->nb_segs++; } prev_id = rx_id; rx_id = next_id; /* * If this is not the last buffer of the received packet, update * the pointer to the first mbuf at the NEXTP entry in the * sw_sc_ring and continue to parse the RX ring. */ if (!eop) { rxm->next = next_rxe->mbuf; next_sc_entry->fbuf = first_seg; goto next_desc; } /* * This is the last buffer of the received packet - return * the current cluster to the user. */ rxm->next = NULL; /* Initialize the first mbuf of the returned packet */ ixgbe_fill_cluster_head_buf(first_seg, &rxd, rxq->port_id, staterr); /* * Deal with the case, when HW CRC srip is disabled. * That can't happen when LRO is enabled, but still could * happen for scattered RX mode. */ first_seg->pkt_len -= rxq->crc_len; if (unlikely(rxm->data_len <= rxq->crc_len)) { struct rte_mbuf *lp; for (lp = first_seg; lp->next != rxm; lp = lp->next) ; first_seg->nb_segs--; lp->data_len -= rxq->crc_len - rxm->data_len; lp->next = NULL; rte_pktmbuf_free_seg(rxm); } else rxm->data_len -= rxq->crc_len; /* Prefetch data of first segment, if configured to do so. */ rte_packet_prefetch((char *)first_seg->buf_addr + first_seg->data_off); /* * Store the mbuf address into the next entry of the array * of returned packets. */ rx_pkts[nb_rx++] = first_seg; } /* * Record index of the next RX descriptor to probe. */ rxq->rx_tail = rx_id; /* * If the number of free RX descriptors is greater than the RX free * threshold of the queue, advance the Receive Descriptor Tail (RDT) * register. * Update the RDT with the value of the last processed RX descriptor * minus 1, to guarantee that the RDT register is never equal to the * RDH register, which creates a "full" ring situtation from the * hardware point of view... */ if (!bulk_alloc && nb_hold > rxq->rx_free_thresh) { PMD_RX_LOG(DEBUG, "port_id=%u queue_id=%u rx_tail=%u " "nb_hold=%u nb_rx=%u", rxq->port_id, rxq->queue_id, rx_id, nb_hold, nb_rx); rte_wmb(); IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, prev_id); nb_hold = 0; } rxq->nb_rx_hold = nb_hold; return nb_rx; } uint16_t ixgbe_recv_pkts_lro_single_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { return ixgbe_recv_pkts_lro(rx_queue, rx_pkts, nb_pkts, false); } uint16_t ixgbe_recv_pkts_lro_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { return ixgbe_recv_pkts_lro(rx_queue, rx_pkts, nb_pkts, true); } /********************************************************************* * * Queue management functions * **********************************************************************/ /* * Rings setup and release. * * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will * also optimize cache line size effect. H/W supports up to cache line size 128. */ #define IXGBE_ALIGN 128 /* * Maximum number of Ring Descriptors. * * Since RDLEN/TDLEN should be multiple of 128 bytes, the number of ring * descriptors should meet the following condition: * (num_ring_desc * sizeof(rx/tx descriptor)) % 128 == 0 */ #define IXGBE_MIN_RING_DESC 32 #define IXGBE_MAX_RING_DESC 4096 /* * Create memzone for HW rings. malloc can't be used as the physical address is * needed. If the memzone is already created, then this function returns a ptr * to the old one. */ static const struct rte_memzone * __attribute__((cold)) ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); mz = rte_memzone_lookup(z_name); if (mz) return mz; #ifdef RTE_LIBRTE_XEN_DOM0 return rte_memzone_reserve_bounded(z_name, ring_size, socket_id, 0, IXGBE_ALIGN, RTE_PGSIZE_2M); #else return rte_memzone_reserve_aligned(z_name, ring_size, socket_id, 0, IXGBE_ALIGN); #endif } static void __attribute__((cold)) ixgbe_tx_queue_release_mbufs(struct ixgbe_tx_queue *txq) { unsigned i; if (txq->sw_ring != NULL) { for (i = 0; i < txq->nb_tx_desc; i++) { if (txq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); txq->sw_ring[i].mbuf = NULL; } } } } static void __attribute__((cold)) ixgbe_tx_free_swring(struct ixgbe_tx_queue *txq) { if (txq != NULL && txq->sw_ring != NULL) rte_free(txq->sw_ring); } static void __attribute__((cold)) ixgbe_tx_queue_release(struct ixgbe_tx_queue *txq) { if (txq != NULL && txq->ops != NULL) { txq->ops->release_mbufs(txq); txq->ops->free_swring(txq); rte_free(txq); } } void __attribute__((cold)) ixgbe_dev_tx_queue_release(void *txq) { ixgbe_tx_queue_release(txq); } /* (Re)set dynamic ixgbe_tx_queue fields to defaults */ static void __attribute__((cold)) ixgbe_reset_tx_queue(struct ixgbe_tx_queue *txq) { static const union ixgbe_adv_tx_desc zeroed_desc = {{0}}; struct ixgbe_tx_entry *txe = txq->sw_ring; uint16_t prev, i; /* Zero out HW ring memory */ for (i = 0; i < txq->nb_tx_desc; i++) { txq->tx_ring[i] = zeroed_desc; } /* Initialize SW ring entries */ prev = (uint16_t) (txq->nb_tx_desc - 1); for (i = 0; i < txq->nb_tx_desc; i++) { volatile union ixgbe_adv_tx_desc *txd = &txq->tx_ring[i]; txd->wb.status = rte_cpu_to_le_32(IXGBE_TXD_STAT_DD); txe[i].mbuf = NULL; txe[i].last_id = i; txe[prev].next_id = i; prev = i; } txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_tail = 0; txq->nb_tx_used = 0; /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition */ txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); txq->ctx_curr = 0; memset((void*)&txq->ctx_cache, 0, IXGBE_CTX_NUM * sizeof(struct ixgbe_advctx_info)); } static const struct ixgbe_txq_ops def_txq_ops = { .release_mbufs = ixgbe_tx_queue_release_mbufs, .free_swring = ixgbe_tx_free_swring, .reset = ixgbe_reset_tx_queue, }; /* Takes an ethdev and a queue and sets up the tx function to be used based on * the queue parameters. Used in tx_queue_setup by primary process and then * in dev_init by secondary process when attaching to an existing ethdev. */ void __attribute__((cold)) ixgbe_set_tx_function(struct rte_eth_dev *dev, struct ixgbe_tx_queue *txq) { /* Use a simple Tx queue (no offloads, no multi segs) if possible */ if (((txq->txq_flags & IXGBE_SIMPLE_FLAGS) == IXGBE_SIMPLE_FLAGS) && (txq->tx_rs_thresh >= RTE_PMD_IXGBE_TX_MAX_BURST)) { PMD_INIT_LOG(DEBUG, "Using simple tx code path"); #ifdef RTE_IXGBE_INC_VECTOR if (txq->tx_rs_thresh <= RTE_IXGBE_TX_MAX_FREE_BUF_SZ && (rte_eal_process_type() != RTE_PROC_PRIMARY || ixgbe_txq_vec_setup(txq) == 0)) { PMD_INIT_LOG(DEBUG, "Vector tx enabled."); dev->tx_pkt_burst = ixgbe_xmit_pkts_vec; } else #endif dev->tx_pkt_burst = ixgbe_xmit_pkts_simple; } else { PMD_INIT_LOG(DEBUG, "Using full-featured tx code path"); PMD_INIT_LOG(DEBUG, " - txq_flags = %lx " "[IXGBE_SIMPLE_FLAGS=%lx]", (unsigned long)txq->txq_flags, (unsigned long)IXGBE_SIMPLE_FLAGS); PMD_INIT_LOG(DEBUG, " - tx_rs_thresh = %lu " "[RTE_PMD_IXGBE_TX_MAX_BURST=%lu]", (unsigned long)txq->tx_rs_thresh, (unsigned long)RTE_PMD_IXGBE_TX_MAX_BURST); dev->tx_pkt_burst = ixgbe_xmit_pkts; } } int __attribute__((cold)) ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { const struct rte_memzone *tz; struct ixgbe_tx_queue *txq; struct ixgbe_hw *hw; uint16_t tx_rs_thresh, tx_free_thresh; bool rs_deferring_allowed; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * According to 82599 and x540 specifications RS bit *must* be set on the * last descriptor of *every* packet. Therefore we will not allow the * tx_rs_thresh above 1 for all NICs newer than 82598. */ rs_deferring_allowed = (hw->mac.type <= ixgbe_mac_82598EB); /* * Validate number of transmit descriptors. * It must not exceed hardware maximum, and must be multiple * of IXGBE_ALIGN. */ if (((nb_desc * sizeof(union ixgbe_adv_tx_desc)) % IXGBE_ALIGN) != 0 || (nb_desc > IXGBE_MAX_RING_DESC) || (nb_desc < IXGBE_MIN_RING_DESC)) { return -EINVAL; } /* * The following two parameters control the setting of the RS bit on * transmit descriptors. * TX descriptors will have their RS bit set after txq->tx_rs_thresh * descriptors have been used. * The TX descriptor ring will be cleaned after txq->tx_free_thresh * descriptors are used or if the number of descriptors required * to transmit a packet is greater than the number of free TX * descriptors. * The following constraints must be satisfied: * tx_rs_thresh must be less than 2 for NICs for which RS deferring is * forbidden (all but 82598). * tx_rs_thresh must be greater than 0. * tx_rs_thresh must be less than the size of the ring minus 2. * tx_rs_thresh must be less than or equal to tx_free_thresh. * tx_rs_thresh must be a divisor of the ring size. * tx_free_thresh must be greater than 0. * tx_free_thresh must be less than the size of the ring minus 3. * One descriptor in the TX ring is used as a sentinel to avoid a * H/W race condition, hence the maximum threshold constraints. * When set to zero use default values. */ tx_rs_thresh = (uint16_t)((tx_conf->tx_rs_thresh) ? tx_conf->tx_rs_thresh : (rs_deferring_allowed ? DEFAULT_TX_RS_THRESH : 1)); tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH); if (!rs_deferring_allowed && tx_rs_thresh > 1) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than 2 since RS " "must be set for every packet for this HW. " "(tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } if (tx_rs_thresh >= (nb_desc - 2)) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than the number " "of TX descriptors minus 2. (tx_rs_thresh=%u " "port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } if (tx_free_thresh >= (nb_desc - 3)) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than the " "tx_free_thresh must be less than the number of " "TX descriptors minus 3. (tx_free_thresh=%u " "port=%d queue=%d)", (unsigned int)tx_free_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } if (tx_rs_thresh > tx_free_thresh) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be less than or equal to " "tx_free_thresh. (tx_free_thresh=%u " "tx_rs_thresh=%u port=%d queue=%d)", (unsigned int)tx_free_thresh, (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } if ((nb_desc % tx_rs_thresh) != 0) { PMD_INIT_LOG(ERR, "tx_rs_thresh must be a divisor of the " "number of TX descriptors. (tx_rs_thresh=%u " "port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } /* * If rs_bit_thresh is greater than 1, then TX WTHRESH should be * set to 0. If WTHRESH is greater than zero, the RS bit is ignored * by the NIC and all descriptors are written back after the NIC * accumulates WTHRESH descriptors. */ if ((tx_rs_thresh > 1) && (tx_conf->tx_thresh.wthresh != 0)) { PMD_INIT_LOG(ERR, "TX WTHRESH must be set to 0 if " "tx_rs_thresh is greater than 1. (tx_rs_thresh=%u " "port=%d queue=%d)", (unsigned int)tx_rs_thresh, (int)dev->data->port_id, (int)queue_idx); return -(EINVAL); } /* Free memory prior to re-allocation if needed... */ if (dev->data->tx_queues[queue_idx] != NULL) { ixgbe_tx_queue_release(dev->data->tx_queues[queue_idx]); dev->data->tx_queues[queue_idx] = NULL; } /* First allocate the tx queue data structure */ txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct ixgbe_tx_queue), RTE_CACHE_LINE_SIZE, socket_id); if (txq == NULL) return (-ENOMEM); /* * Allocate TX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ tz = ring_dma_zone_reserve(dev, "tx_ring", queue_idx, sizeof(union ixgbe_adv_tx_desc) * IXGBE_MAX_RING_DESC, socket_id); if (tz == NULL) { ixgbe_tx_queue_release(txq); return (-ENOMEM); } txq->nb_tx_desc = nb_desc; txq->tx_rs_thresh = tx_rs_thresh; txq->tx_free_thresh = tx_free_thresh; txq->pthresh = tx_conf->tx_thresh.pthresh; txq->hthresh = tx_conf->tx_thresh.hthresh; txq->wthresh = tx_conf->tx_thresh.wthresh; txq->queue_id = queue_idx; txq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); txq->port_id = dev->data->port_id; txq->txq_flags = tx_conf->txq_flags; txq->ops = &def_txq_ops; txq->tx_deferred_start = tx_conf->tx_deferred_start; /* * Modification to set VFTDT for virtual function if vf is detected */ if (hw->mac.type == ixgbe_mac_82599_vf || hw->mac.type == ixgbe_mac_X540_vf || hw->mac.type == ixgbe_mac_X550_vf || hw->mac.type == ixgbe_mac_X550EM_x_vf) txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_VFTDT(queue_idx)); else txq->tdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_TDT(txq->reg_idx)); #ifndef RTE_LIBRTE_XEN_DOM0 txq->tx_ring_phys_addr = (uint64_t) tz->phys_addr; #else txq->tx_ring_phys_addr = rte_mem_phy2mch(tz->memseg_id, tz->phys_addr); #endif txq->tx_ring = (union ixgbe_adv_tx_desc *) tz->addr; /* Allocate software ring */ txq->sw_ring = rte_zmalloc_socket("txq->sw_ring", sizeof(struct ixgbe_tx_entry) * nb_desc, RTE_CACHE_LINE_SIZE, socket_id); if (txq->sw_ring == NULL) { ixgbe_tx_queue_release(txq); return (-ENOMEM); } PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%"PRIx64, txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); /* set up vector or scalar TX function as appropriate */ ixgbe_set_tx_function(dev, txq); txq->ops->reset(txq); dev->data->tx_queues[queue_idx] = txq; return (0); } /** * ixgbe_free_sc_cluster - free the not-yet-completed scattered cluster * * The "next" pointer of the last segment of (not-yet-completed) RSC clusters * in the sw_rsc_ring is not set to NULL but rather points to the next * mbuf of this RSC aggregation (that has not been completed yet and still * resides on the HW ring). So, instead of calling for rte_pktmbuf_free() we * will just free first "nb_segs" segments of the cluster explicitly by calling * an rte_pktmbuf_free_seg(). * * @m scattered cluster head */ static void __attribute__((cold)) ixgbe_free_sc_cluster(struct rte_mbuf *m) { uint8_t i, nb_segs = m->nb_segs; struct rte_mbuf *next_seg; for (i = 0; i < nb_segs; i++) { next_seg = m->next; rte_pktmbuf_free_seg(m); m = next_seg; } } static void __attribute__((cold)) ixgbe_rx_queue_release_mbufs(struct ixgbe_rx_queue *rxq) { unsigned i; #ifdef RTE_IXGBE_INC_VECTOR /* SSE Vector driver has a different way of releasing mbufs. */ if (rxq->rx_using_sse) { ixgbe_rx_queue_release_mbufs_vec(rxq); return; } #endif if (rxq->sw_ring != NULL) { for (i = 0; i < rxq->nb_rx_desc; i++) { if (rxq->sw_ring[i].mbuf != NULL) { rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); rxq->sw_ring[i].mbuf = NULL; } } if (rxq->rx_nb_avail) { for (i = 0; i < rxq->rx_nb_avail; ++i) { struct rte_mbuf *mb; mb = rxq->rx_stage[rxq->rx_next_avail + i]; rte_pktmbuf_free_seg(mb); } rxq->rx_nb_avail = 0; } } if (rxq->sw_sc_ring) for (i = 0; i < rxq->nb_rx_desc; i++) if (rxq->sw_sc_ring[i].fbuf) { ixgbe_free_sc_cluster(rxq->sw_sc_ring[i].fbuf); rxq->sw_sc_ring[i].fbuf = NULL; } } static void __attribute__((cold)) ixgbe_rx_queue_release(struct ixgbe_rx_queue *rxq) { if (rxq != NULL) { ixgbe_rx_queue_release_mbufs(rxq); rte_free(rxq->sw_ring); rte_free(rxq->sw_sc_ring); rte_free(rxq); } } void __attribute__((cold)) ixgbe_dev_rx_queue_release(void *rxq) { ixgbe_rx_queue_release(rxq); } /* * Check if Rx Burst Bulk Alloc function can be used. * Return * 0: the preconditions are satisfied and the bulk allocation function * can be used. * -EINVAL: the preconditions are NOT satisfied and the default Rx burst * function must be used. */ static inline int __attribute__((cold)) check_rx_burst_bulk_alloc_preconditions(struct ixgbe_rx_queue *rxq) { int ret = 0; /* * Make sure the following pre-conditions are satisfied: * rxq->rx_free_thresh >= RTE_PMD_IXGBE_RX_MAX_BURST * rxq->rx_free_thresh < rxq->nb_rx_desc * (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0 * rxq->nb_rx_desc<(IXGBE_MAX_RING_DESC-RTE_PMD_IXGBE_RX_MAX_BURST) * Scattered packets are not supported. This should be checked * outside of this function. */ if (!(rxq->rx_free_thresh >= RTE_PMD_IXGBE_RX_MAX_BURST)) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->rx_free_thresh=%d, " "RTE_PMD_IXGBE_RX_MAX_BURST=%d", rxq->rx_free_thresh, RTE_PMD_IXGBE_RX_MAX_BURST); ret = -EINVAL; } else if (!(rxq->rx_free_thresh < rxq->nb_rx_desc)) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->rx_free_thresh=%d, " "rxq->nb_rx_desc=%d", rxq->rx_free_thresh, rxq->nb_rx_desc); ret = -EINVAL; } else if (!((rxq->nb_rx_desc % rxq->rx_free_thresh) == 0)) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->nb_rx_desc=%d, " "rxq->rx_free_thresh=%d", rxq->nb_rx_desc, rxq->rx_free_thresh); ret = -EINVAL; } else if (!(rxq->nb_rx_desc < (IXGBE_MAX_RING_DESC - RTE_PMD_IXGBE_RX_MAX_BURST))) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: " "rxq->nb_rx_desc=%d, " "IXGBE_MAX_RING_DESC=%d, " "RTE_PMD_IXGBE_RX_MAX_BURST=%d", rxq->nb_rx_desc, IXGBE_MAX_RING_DESC, RTE_PMD_IXGBE_RX_MAX_BURST); ret = -EINVAL; } return ret; } /* Reset dynamic ixgbe_rx_queue fields back to defaults */ static void __attribute__((cold)) ixgbe_reset_rx_queue(struct ixgbe_adapter *adapter, struct ixgbe_rx_queue *rxq) { static const union ixgbe_adv_rx_desc zeroed_desc = {{0}}; unsigned i; uint16_t len = rxq->nb_rx_desc; /* * By default, the Rx queue setup function allocates enough memory for * IXGBE_MAX_RING_DESC. The Rx Burst bulk allocation function requires * extra memory at the end of the descriptor ring to be zero'd out. A * pre-condition for using the Rx burst bulk alloc function is that the * number of descriptors is less than or equal to * (IXGBE_MAX_RING_DESC - RTE_PMD_IXGBE_RX_MAX_BURST). Check all the * constraints here to see if we need to zero out memory after the end * of the H/W descriptor ring. */ if (adapter->rx_bulk_alloc_allowed) /* zero out extra memory */ len += RTE_PMD_IXGBE_RX_MAX_BURST; /* * Zero out HW ring memory. Zero out extra memory at the end of * the H/W ring so look-ahead logic in Rx Burst bulk alloc function * reads extra memory as zeros. */ for (i = 0; i < len; i++) { rxq->rx_ring[i] = zeroed_desc; } /* * initialize extra software ring entries. Space for these extra * entries is always allocated */ memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf)); for (i = rxq->nb_rx_desc; i < len; ++i) { rxq->sw_ring[i].mbuf = &rxq->fake_mbuf; } rxq->rx_nb_avail = 0; rxq->rx_next_avail = 0; rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1); rxq->rx_tail = 0; rxq->nb_rx_hold = 0; rxq->pkt_first_seg = NULL; rxq->pkt_last_seg = NULL; #ifdef RTE_IXGBE_INC_VECTOR rxq->rxrearm_start = 0; rxq->rxrearm_nb = 0; #endif } int __attribute__((cold)) ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { const struct rte_memzone *rz; struct ixgbe_rx_queue *rxq; struct ixgbe_hw *hw; uint16_t len; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Validate number of receive descriptors. * It must not exceed hardware maximum, and must be multiple * of IXGBE_ALIGN. */ if (((nb_desc * sizeof(union ixgbe_adv_rx_desc)) % IXGBE_ALIGN) != 0 || (nb_desc > IXGBE_MAX_RING_DESC) || (nb_desc < IXGBE_MIN_RING_DESC)) { return (-EINVAL); } /* Free memory prior to re-allocation if needed... */ if (dev->data->rx_queues[queue_idx] != NULL) { ixgbe_rx_queue_release(dev->data->rx_queues[queue_idx]); dev->data->rx_queues[queue_idx] = NULL; } /* First allocate the rx queue data structure */ rxq = rte_zmalloc_socket("ethdev RX queue", sizeof(struct ixgbe_rx_queue), RTE_CACHE_LINE_SIZE, socket_id); if (rxq == NULL) return (-ENOMEM); rxq->mb_pool = mp; rxq->nb_rx_desc = nb_desc; rxq->rx_free_thresh = rx_conf->rx_free_thresh; rxq->queue_id = queue_idx; rxq->reg_idx = (uint16_t)((RTE_ETH_DEV_SRIOV(dev).active == 0) ? queue_idx : RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx + queue_idx); rxq->port_id = dev->data->port_id; rxq->crc_len = (uint8_t) ((dev->data->dev_conf.rxmode.hw_strip_crc) ? 0 : ETHER_CRC_LEN); rxq->drop_en = rx_conf->rx_drop_en; rxq->rx_deferred_start = rx_conf->rx_deferred_start; /* * Allocate RX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ rz = ring_dma_zone_reserve(dev, "rx_ring", queue_idx, RX_RING_SZ, socket_id); if (rz == NULL) { ixgbe_rx_queue_release(rxq); return (-ENOMEM); } /* * Zero init all the descriptors in the ring. */ memset (rz->addr, 0, RX_RING_SZ); /* * Modified to setup VFRDT for Virtual Function */ if (hw->mac.type == ixgbe_mac_82599_vf || hw->mac.type == ixgbe_mac_X540_vf || hw->mac.type == ixgbe_mac_X550_vf || hw->mac.type == ixgbe_mac_X550EM_x_vf) { rxq->rdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDT(queue_idx)); rxq->rdh_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_VFRDH(queue_idx)); } else { rxq->rdt_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_RDT(rxq->reg_idx)); rxq->rdh_reg_addr = IXGBE_PCI_REG_ADDR(hw, IXGBE_RDH(rxq->reg_idx)); } #ifndef RTE_LIBRTE_XEN_DOM0 rxq->rx_ring_phys_addr = (uint64_t) rz->phys_addr; #else rxq->rx_ring_phys_addr = rte_mem_phy2mch(rz->memseg_id, rz->phys_addr); #endif rxq->rx_ring = (union ixgbe_adv_rx_desc *) rz->addr; /* * Certain constraints must be met in order to use the bulk buffer * allocation Rx burst function. If any of Rx queues doesn't meet them * the feature should be disabled for the whole port. */ if (check_rx_burst_bulk_alloc_preconditions(rxq)) { PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Rx Bulk Alloc " "preconditions - canceling the feature for " "the whole port[%d]", rxq->queue_id, rxq->port_id); adapter->rx_bulk_alloc_allowed = false; } /* * Allocate software ring. Allow for space at the end of the * S/W ring to make sure look-ahead logic in bulk alloc Rx burst * function does not access an invalid memory region. */ len = nb_desc; if (adapter->rx_bulk_alloc_allowed) len += RTE_PMD_IXGBE_RX_MAX_BURST; rxq->sw_ring = rte_zmalloc_socket("rxq->sw_ring", sizeof(struct ixgbe_rx_entry) * len, RTE_CACHE_LINE_SIZE, socket_id); if (!rxq->sw_ring) { ixgbe_rx_queue_release(rxq); return (-ENOMEM); } /* * Always allocate even if it's not going to be needed in order to * simplify the code. * * This ring is used in LRO and Scattered Rx cases and Scattered Rx may * be requested in ixgbe_dev_rx_init(), which is called later from * dev_start() flow. */ rxq->sw_sc_ring = rte_zmalloc_socket("rxq->sw_sc_ring", sizeof(struct ixgbe_scattered_rx_entry) * len, RTE_CACHE_LINE_SIZE, socket_id); if (!rxq->sw_sc_ring) { ixgbe_rx_queue_release(rxq); return (-ENOMEM); } PMD_INIT_LOG(DEBUG, "sw_ring=%p sw_sc_ring=%p hw_ring=%p " "dma_addr=0x%"PRIx64, rxq->sw_ring, rxq->sw_sc_ring, rxq->rx_ring, rxq->rx_ring_phys_addr); if (!rte_is_power_of_2(nb_desc)) { PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Vector Rx " "preconditions - canceling the feature for " "the whole port[%d]", rxq->queue_id, rxq->port_id); adapter->rx_vec_allowed = false; } else ixgbe_rxq_vec_setup(rxq); dev->data->rx_queues[queue_idx] = rxq; ixgbe_reset_rx_queue(adapter, rxq); return 0; } uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id) { #define IXGBE_RXQ_SCAN_INTERVAL 4 volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_queue *rxq; uint32_t desc = 0; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_RX_LOG(ERR, "Invalid RX queue id=%d", rx_queue_id); return 0; } rxq = dev->data->rx_queues[rx_queue_id]; rxdp = &(rxq->rx_ring[rxq->rx_tail]); while ((desc < rxq->nb_rx_desc) && (rxdp->wb.upper.status_error & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))) { desc += IXGBE_RXQ_SCAN_INTERVAL; rxdp += IXGBE_RXQ_SCAN_INTERVAL; if (rxq->rx_tail + desc >= rxq->nb_rx_desc) rxdp = &(rxq->rx_ring[rxq->rx_tail + desc - rxq->nb_rx_desc]); } return desc; } int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset) { volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_queue *rxq = rx_queue; uint32_t desc; if (unlikely(offset >= rxq->nb_rx_desc)) return 0; desc = rxq->rx_tail + offset; if (desc >= rxq->nb_rx_desc) desc -= rxq->nb_rx_desc; rxdp = &rxq->rx_ring[desc]; return !!(rxdp->wb.upper.status_error & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD)); } void __attribute__((cold)) ixgbe_dev_clear_queues(struct rte_eth_dev *dev) { unsigned i; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_tx_queues; i++) { struct ixgbe_tx_queue *txq = dev->data->tx_queues[i]; if (txq != NULL) { txq->ops->release_mbufs(txq); txq->ops->reset(txq); } } for (i = 0; i < dev->data->nb_rx_queues; i++) { struct ixgbe_rx_queue *rxq = dev->data->rx_queues[i]; if (rxq != NULL) { ixgbe_rx_queue_release_mbufs(rxq); ixgbe_reset_rx_queue(adapter, rxq); } } } void ixgbe_dev_free_queues(struct rte_eth_dev *dev) { unsigned i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_rx_queues; i++) { ixgbe_dev_rx_queue_release(dev->data->rx_queues[i]); dev->data->rx_queues[i] = NULL; } dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) { ixgbe_dev_tx_queue_release(dev->data->tx_queues[i]); dev->data->tx_queues[i] = NULL; } dev->data->nb_tx_queues = 0; } /********************************************************************* * * Device RX/TX init functions * **********************************************************************/ /** * Receive Side Scaling (RSS) * See section 7.1.2.8 in the following document: * "Intel 82599 10 GbE Controller Datasheet" - Revision 2.1 October 2009 * * Principles: * The source and destination IP addresses of the IP header and the source * and destination ports of TCP/UDP headers, if any, of received packets are * hashed against a configurable random key to compute a 32-bit RSS hash result. * The seven (7) LSBs of the 32-bit hash result are used as an index into a * 128-entry redirection table (RETA). Each entry of the RETA provides a 3-bit * RSS output index which is used as the RX queue index where to store the * received packets. * The following output is supplied in the RX write-back descriptor: * - 32-bit result of the Microsoft RSS hash function, * - 4-bit RSS type field. */ /* * RSS random key supplied in section 7.1.2.8.3 of the Intel 82599 datasheet. * Used as the default key. */ static uint8_t rss_intel_key[40] = { 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; static void ixgbe_rss_disable(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; uint32_t mrqc; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); mrqc &= ~IXGBE_MRQC_RSSEN; IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } static void ixgbe_hw_rss_hash_set(struct ixgbe_hw *hw, struct rte_eth_rss_conf *rss_conf) { uint8_t *hash_key; uint32_t mrqc; uint32_t rss_key; uint64_t rss_hf; uint16_t i; hash_key = rss_conf->rss_key; if (hash_key != NULL) { /* Fill in RSS hash key */ for (i = 0; i < 10; i++) { rss_key = hash_key[(i * 4)]; rss_key |= hash_key[(i * 4) + 1] << 8; rss_key |= hash_key[(i * 4) + 2] << 16; rss_key |= hash_key[(i * 4) + 3] << 24; IXGBE_WRITE_REG_ARRAY(hw, IXGBE_RSSRK(0), i, rss_key); } } /* Set configured hashing protocols in MRQC register */ rss_hf = rss_conf->rss_hf; mrqc = IXGBE_MRQC_RSSEN; /* Enable RSS */ if (rss_hf & ETH_RSS_IPV4) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_TCP; if (rss_hf & ETH_RSS_IPV6) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6; if (rss_hf & ETH_RSS_IPV6_EX) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX; if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; if (rss_hf & ETH_RSS_IPV6_TCP_EX) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP; if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; if (rss_hf & ETH_RSS_IPV6_UDP_EX) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } int ixgbe_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct ixgbe_hw *hw; uint32_t mrqc; uint64_t rss_hf; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Excerpt from section 7.1.2.8 Receive-Side Scaling (RSS): * "RSS enabling cannot be done dynamically while it must be * preceded by a software reset" * Before changing anything, first check that the update RSS operation * does not attempt to disable RSS, if RSS was enabled at * initialization time, or does not attempt to enable RSS, if RSS was * disabled at initialization time. */ rss_hf = rss_conf->rss_hf & IXGBE_RSS_OFFLOAD_ALL; mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); if (!(mrqc & IXGBE_MRQC_RSSEN)) { /* RSS disabled */ if (rss_hf != 0) /* Enable RSS */ return -(EINVAL); return 0; /* Nothing to do */ } /* RSS enabled */ if (rss_hf == 0) /* Disable RSS */ return -(EINVAL); ixgbe_hw_rss_hash_set(hw, rss_conf); return 0; } int ixgbe_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) { struct ixgbe_hw *hw; uint8_t *hash_key; uint32_t mrqc; uint32_t rss_key; uint64_t rss_hf; uint16_t i; hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); hash_key = rss_conf->rss_key; if (hash_key != NULL) { /* Return RSS hash key */ for (i = 0; i < 10; i++) { rss_key = IXGBE_READ_REG_ARRAY(hw, IXGBE_RSSRK(0), i); hash_key[(i * 4)] = rss_key & 0x000000FF; hash_key[(i * 4) + 1] = (rss_key >> 8) & 0x000000FF; hash_key[(i * 4) + 2] = (rss_key >> 16) & 0x000000FF; hash_key[(i * 4) + 3] = (rss_key >> 24) & 0x000000FF; } } /* Get RSS functions configured in MRQC register */ mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); if ((mrqc & IXGBE_MRQC_RSSEN) == 0) { /* RSS is disabled */ rss_conf->rss_hf = 0; return 0; } rss_hf = 0; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4) rss_hf |= ETH_RSS_IPV4; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_TCP) rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6) rss_hf |= ETH_RSS_IPV6; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX) rss_hf |= ETH_RSS_IPV6_EX; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_TCP) rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP) rss_hf |= ETH_RSS_IPV6_TCP_EX; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV4_UDP) rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_UDP) rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP; if (mrqc & IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP) rss_hf |= ETH_RSS_IPV6_UDP_EX; rss_conf->rss_hf = rss_hf; return 0; } static void ixgbe_rss_configure(struct rte_eth_dev *dev) { struct rte_eth_rss_conf rss_conf; struct ixgbe_hw *hw; uint32_t reta; uint16_t i; uint16_t j; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Fill in redirection table * The byte-swap is needed because NIC registers are in * little-endian order. */ reta = 0; for (i = 0, j = 0; i < 128; i++, j++) { if (j == dev->data->nb_rx_queues) j = 0; reta = (reta << 8) | j; if ((i & 3) == 3) IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), rte_bswap32(reta)); } /* * Configure the RSS key and the RSS protocols used to compute * the RSS hash of input packets. */ rss_conf = dev->data->dev_conf.rx_adv_conf.rss_conf; if ((rss_conf.rss_hf & IXGBE_RSS_OFFLOAD_ALL) == 0) { ixgbe_rss_disable(dev); return; } if (rss_conf.rss_key == NULL) rss_conf.rss_key = rss_intel_key; /* Default hash key */ ixgbe_hw_rss_hash_set(hw, &rss_conf); } #define NUM_VFTA_REGISTERS 128 #define NIC_RX_BUFFER_SIZE 0x200 static void ixgbe_vmdq_dcb_configure(struct rte_eth_dev *dev) { struct rte_eth_vmdq_dcb_conf *cfg; struct ixgbe_hw *hw; enum rte_eth_nb_pools num_pools; uint32_t mrqc, vt_ctl, queue_mapping, vlanctrl; uint16_t pbsize; uint8_t nb_tcs; /* number of traffic classes */ int i; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_dcb_conf; num_pools = cfg->nb_queue_pools; /* Check we have a valid number of pools */ if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS) { ixgbe_rss_disable(dev); return; } /* 16 pools -> 8 traffic classes, 32 pools -> 4 traffic classes */ nb_tcs = (uint8_t)(ETH_VMDQ_DCB_NUM_QUEUES / (int)num_pools); /* * RXPBSIZE * split rx buffer up into sections, each for 1 traffic class */ pbsize = (uint16_t)(NIC_RX_BUFFER_SIZE / nb_tcs); for (i = 0 ; i < nb_tcs; i++) { uint32_t rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); rxpbsize &= (~(0x3FF << IXGBE_RXPBSIZE_SHIFT)); /* clear 10 bits. */ rxpbsize |= (pbsize << IXGBE_RXPBSIZE_SHIFT); /* set value */ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize); } /* zero alloc all unused TCs */ for (i = nb_tcs; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { uint32_t rxpbsize = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); rxpbsize &= (~( 0x3FF << IXGBE_RXPBSIZE_SHIFT )); /* clear 10 bits. */ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize); } /* MRQC: enable vmdq and dcb */ mrqc = ((num_pools == ETH_16_POOLS) ? \ IXGBE_MRQC_VMDQRT8TCEN : IXGBE_MRQC_VMDQRT4TCEN ); IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); /* PFVTCTL: turn on virtualisation and set the default pool */ vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN; if (cfg->enable_default_pool) { vt_ctl |= (cfg->default_pool << IXGBE_VT_CTL_POOL_SHIFT); } else { vt_ctl |= IXGBE_VT_CTL_DIS_DEFPL; } IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl); /* RTRUP2TC: mapping user priorities to traffic classes (TCs) */ queue_mapping = 0; for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) /* * mapping is done with 3 bits per priority, * so shift by i*3 each time */ queue_mapping |= ((cfg->dcb_queue[i] & 0x07) << (i * 3)); IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, queue_mapping); /* RTRPCS: DCB related */ IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, IXGBE_RMCS_RRM); /* VLNCTRL: enable vlan filtering and allow all vlan tags through */ vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); /* VFTA - enable all vlan filters */ for (i = 0; i < NUM_VFTA_REGISTERS; i++) { IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 0xFFFFFFFF); } /* VFRE: pool enabling for receive - 16 or 32 */ IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), \ num_pools == ETH_16_POOLS ? 0xFFFF : 0xFFFFFFFF); /* * MPSAR - allow pools to read specific mac addresses * In this case, all pools should be able to read from mac addr 0 */ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(0), 0xFFFFFFFF); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(0), 0xFFFFFFFF); /* PFVLVF, PFVLVFB: set up filters for vlan tags as configured */ for (i = 0; i < cfg->nb_pool_maps; i++) { /* set vlan id in VF register and set the valid bit */ IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), (IXGBE_VLVF_VIEN | \ (cfg->pool_map[i].vlan_id & 0xFFF))); /* * Put the allowed pools in VFB reg. As we only have 16 or 32 * pools, we only need to use the first half of the register * i.e. bits 0-31 */ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(i*2), cfg->pool_map[i].pools); } } /** * ixgbe_dcb_config_tx_hw_config - Configure general DCB TX parameters * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure */ static void ixgbe_dcb_tx_hw_config(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { uint32_t reg; uint32_t q; PMD_INIT_FUNC_TRACE(); if (hw->mac.type != ixgbe_mac_82598EB) { /* Disable the Tx desc arbiter so that MTQC can be changed */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg |= IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); /* Enable DCB for Tx with 8 TCs */ if (dcb_config->num_tcs.pg_tcs == 8) { reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ; } else { reg = IXGBE_MTQC_RT_ENA | IXGBE_MTQC_4TC_4TQ; } if (dcb_config->vt_mode) reg |= IXGBE_MTQC_VT_ENA; IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg); /* Disable drop for all queues */ for (q = 0; q < 128; q++) IXGBE_WRITE_REG(hw, IXGBE_QDE, (IXGBE_QDE_WRITE | (q << IXGBE_QDE_IDX_SHIFT))); /* Enable the Tx desc arbiter */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg &= ~IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); /* Enable Security TX Buffer IFG for DCB */ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG); reg |= IXGBE_SECTX_DCB; IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg); } return; } /** * ixgbe_vmdq_dcb_hw_tx_config - Configure general VMDQ+DCB TX parameters * @dev: pointer to rte_eth_dev structure * @dcb_config: pointer to ixgbe_dcb_config structure */ static void ixgbe_vmdq_dcb_hw_tx_config(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf = &dev->data->dev_conf.tx_adv_conf.vmdq_dcb_tx_conf; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); if (hw->mac.type != ixgbe_mac_82598EB) /*PF VF Transmit Enable*/ IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), vmdq_tx_conf->nb_queue_pools == ETH_16_POOLS ? 0xFFFF : 0xFFFFFFFF); /*Configure general DCB TX parameters*/ ixgbe_dcb_tx_hw_config(hw,dcb_config); return; } static void ixgbe_vmdq_dcb_rx_config(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_dcb_conf; struct ixgbe_dcb_tc_config *tc; uint8_t i,j; /* convert rte_eth_conf.rx_adv_conf to struct ixgbe_dcb_config */ if (vmdq_rx_conf->nb_queue_pools == ETH_16_POOLS ) { dcb_config->num_tcs.pg_tcs = ETH_8_TCS; dcb_config->num_tcs.pfc_tcs = ETH_8_TCS; } else { dcb_config->num_tcs.pg_tcs = ETH_4_TCS; dcb_config->num_tcs.pfc_tcs = ETH_4_TCS; } /* User Priority to Traffic Class mapping */ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { j = vmdq_rx_conf->dcb_queue[i]; tc = &dcb_config->tc_config[j]; tc->path[IXGBE_DCB_RX_CONFIG].up_to_tc_bitmap = (uint8_t)(1 << j); } } static void ixgbe_dcb_vt_tx_config(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf = &dev->data->dev_conf.tx_adv_conf.vmdq_dcb_tx_conf; struct ixgbe_dcb_tc_config *tc; uint8_t i,j; /* convert rte_eth_conf.rx_adv_conf to struct ixgbe_dcb_config */ if (vmdq_tx_conf->nb_queue_pools == ETH_16_POOLS ) { dcb_config->num_tcs.pg_tcs = ETH_8_TCS; dcb_config->num_tcs.pfc_tcs = ETH_8_TCS; } else { dcb_config->num_tcs.pg_tcs = ETH_4_TCS; dcb_config->num_tcs.pfc_tcs = ETH_4_TCS; } /* User Priority to Traffic Class mapping */ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { j = vmdq_tx_conf->dcb_queue[i]; tc = &dcb_config->tc_config[j]; tc->path[IXGBE_DCB_TX_CONFIG].up_to_tc_bitmap = (uint8_t)(1 << j); } return; } static void ixgbe_dcb_rx_config(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { struct rte_eth_dcb_rx_conf *rx_conf = &dev->data->dev_conf.rx_adv_conf.dcb_rx_conf; struct ixgbe_dcb_tc_config *tc; uint8_t i,j; dcb_config->num_tcs.pg_tcs = (uint8_t)rx_conf->nb_tcs; dcb_config->num_tcs.pfc_tcs = (uint8_t)rx_conf->nb_tcs; /* User Priority to Traffic Class mapping */ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { j = rx_conf->dcb_queue[i]; tc = &dcb_config->tc_config[j]; tc->path[IXGBE_DCB_RX_CONFIG].up_to_tc_bitmap = (uint8_t)(1 << j); } } static void ixgbe_dcb_tx_config(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { struct rte_eth_dcb_tx_conf *tx_conf = &dev->data->dev_conf.tx_adv_conf.dcb_tx_conf; struct ixgbe_dcb_tc_config *tc; uint8_t i,j; dcb_config->num_tcs.pg_tcs = (uint8_t)tx_conf->nb_tcs; dcb_config->num_tcs.pfc_tcs = (uint8_t)tx_conf->nb_tcs; /* User Priority to Traffic Class mapping */ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { j = tx_conf->dcb_queue[i]; tc = &dcb_config->tc_config[j]; tc->path[IXGBE_DCB_TX_CONFIG].up_to_tc_bitmap = (uint8_t)(1 << j); } } /** * ixgbe_dcb_rx_hw_config - Configure general DCB RX HW parameters * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure */ static void ixgbe_dcb_rx_hw_config(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { uint32_t reg; uint32_t vlanctrl; uint8_t i; PMD_INIT_FUNC_TRACE(); /* * Disable the arbiter before changing parameters * (always enable recycle mode; WSP) */ reg = IXGBE_RTRPCS_RRM | IXGBE_RTRPCS_RAC | IXGBE_RTRPCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, reg); if (hw->mac.type != ixgbe_mac_82598EB) { reg = IXGBE_READ_REG(hw, IXGBE_MRQC); if (dcb_config->num_tcs.pg_tcs == 4) { if (dcb_config->vt_mode) reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_VMDQRT4TCEN; else { IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0); reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT4TCEN; } } if (dcb_config->num_tcs.pg_tcs == 8) { if (dcb_config->vt_mode) reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_VMDQRT8TCEN; else { IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, 0); reg = (reg & ~IXGBE_MRQC_MRQE_MASK) | IXGBE_MRQC_RT8TCEN; } } IXGBE_WRITE_REG(hw, IXGBE_MRQC, reg); } /* VLNCTRL: enable vlan filtering and allow all vlan tags through */ vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); /* VFTA - enable all vlan filters */ for (i = 0; i < NUM_VFTA_REGISTERS; i++) { IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), 0xFFFFFFFF); } /* * Configure Rx packet plane (recycle mode; WSP) and * enable arbiter */ reg = IXGBE_RTRPCS_RRM | IXGBE_RTRPCS_RAC; IXGBE_WRITE_REG(hw, IXGBE_RTRPCS, reg); return; } static void ixgbe_dcb_hw_arbite_rx_config(struct ixgbe_hw *hw, uint16_t *refill, uint16_t *max,uint8_t *bwg_id, uint8_t *tsa, uint8_t *map) { switch (hw->mac.type) { case ixgbe_mac_82598EB: ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id, tsa, map); break; default: break; } } static void ixgbe_dcb_hw_arbite_tx_config(struct ixgbe_hw *hw, uint16_t *refill, uint16_t *max, uint8_t *bwg_id, uint8_t *tsa, uint8_t *map) { switch (hw->mac.type) { case ixgbe_mac_82598EB: ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max, bwg_id,tsa); ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max, bwg_id,tsa); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max, bwg_id,tsa); ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,tsa, map); break; default: break; } } #define DCB_RX_CONFIG 1 #define DCB_TX_CONFIG 1 #define DCB_TX_PB 1024 /** * ixgbe_dcb_hw_configure - Enable DCB and configure * general DCB in VT mode and non-VT mode parameters * @dev: pointer to rte_eth_dev structure * @dcb_config: pointer to ixgbe_dcb_config structure */ static int ixgbe_dcb_hw_configure(struct rte_eth_dev *dev, struct ixgbe_dcb_config *dcb_config) { int ret = 0; uint8_t i,pfc_en,nb_tcs; uint16_t pbsize; uint8_t config_dcb_rx = 0; uint8_t config_dcb_tx = 0; uint8_t tsa[IXGBE_DCB_MAX_TRAFFIC_CLASS] = {0}; uint8_t bwgid[IXGBE_DCB_MAX_TRAFFIC_CLASS] = {0}; uint16_t refill[IXGBE_DCB_MAX_TRAFFIC_CLASS] = {0}; uint16_t max[IXGBE_DCB_MAX_TRAFFIC_CLASS] = {0}; uint8_t map[IXGBE_DCB_MAX_TRAFFIC_CLASS] = {0}; struct ixgbe_dcb_tc_config *tc; uint32_t max_frame = dev->data->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); switch(dev->data->dev_conf.rxmode.mq_mode){ case ETH_MQ_RX_VMDQ_DCB: dcb_config->vt_mode = true; if (hw->mac.type != ixgbe_mac_82598EB) { config_dcb_rx = DCB_RX_CONFIG; /* *get dcb and VT rx configuration parameters *from rte_eth_conf */ ixgbe_vmdq_dcb_rx_config(dev,dcb_config); /*Configure general VMDQ and DCB RX parameters*/ ixgbe_vmdq_dcb_configure(dev); } break; case ETH_MQ_RX_DCB: dcb_config->vt_mode = false; config_dcb_rx = DCB_RX_CONFIG; /* Get dcb TX configuration parameters from rte_eth_conf */ ixgbe_dcb_rx_config(dev,dcb_config); /*Configure general DCB RX parameters*/ ixgbe_dcb_rx_hw_config(hw, dcb_config); break; default: PMD_INIT_LOG(ERR, "Incorrect DCB RX mode configuration"); break; } switch (dev->data->dev_conf.txmode.mq_mode) { case ETH_MQ_TX_VMDQ_DCB: dcb_config->vt_mode = true; config_dcb_tx = DCB_TX_CONFIG; /* get DCB and VT TX configuration parameters from rte_eth_conf */ ixgbe_dcb_vt_tx_config(dev,dcb_config); /*Configure general VMDQ and DCB TX parameters*/ ixgbe_vmdq_dcb_hw_tx_config(dev,dcb_config); break; case ETH_MQ_TX_DCB: dcb_config->vt_mode = false; config_dcb_tx = DCB_TX_CONFIG; /*get DCB TX configuration parameters from rte_eth_conf*/ ixgbe_dcb_tx_config(dev,dcb_config); /*Configure general DCB TX parameters*/ ixgbe_dcb_tx_hw_config(hw, dcb_config); break; default: PMD_INIT_LOG(ERR, "Incorrect DCB TX mode configuration"); break; } nb_tcs = dcb_config->num_tcs.pfc_tcs; /* Unpack map */ ixgbe_dcb_unpack_map_cee(dcb_config, IXGBE_DCB_RX_CONFIG, map); if(nb_tcs == ETH_4_TCS) { /* Avoid un-configured priority mapping to TC0 */ uint8_t j = 4; uint8_t mask = 0xFF; for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES - 4; i++) mask = (uint8_t)(mask & (~ (1 << map[i]))); for (i = 0; mask && (i < IXGBE_DCB_MAX_TRAFFIC_CLASS); i++) { if ((mask & 0x1) && (j < ETH_DCB_NUM_USER_PRIORITIES)) map[j++] = i; mask >>= 1; } /* Re-configure 4 TCs BW */ for (i = 0; i < nb_tcs; i++) { tc = &dcb_config->tc_config[i]; tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = (uint8_t)(100 / nb_tcs); tc->path[IXGBE_DCB_RX_CONFIG].bwg_percent = (uint8_t)(100 / nb_tcs); } for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { tc = &dcb_config->tc_config[i]; tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = 0; tc->path[IXGBE_DCB_RX_CONFIG].bwg_percent = 0; } } if(config_dcb_rx) { /* Set RX buffer size */ pbsize = (uint16_t)(NIC_RX_BUFFER_SIZE / nb_tcs); uint32_t rxpbsize = pbsize << IXGBE_RXPBSIZE_SHIFT; for (i = 0 ; i < nb_tcs; i++) { IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpbsize); } /* zero alloc all unused TCs */ for (; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); } } if(config_dcb_tx) { /* Only support an equally distributed Tx packet buffer strategy. */ uint32_t txpktsize = IXGBE_TXPBSIZE_MAX / nb_tcs; uint32_t txpbthresh = (txpktsize / DCB_TX_PB) - IXGBE_TXPKT_SIZE_MAX; for (i = 0; i < nb_tcs; i++) { IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); } /* Clear unused TCs, if any, to zero buffer size*/ for (; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); } } /*Calculates traffic class credits*/ ixgbe_dcb_calculate_tc_credits_cee(hw, dcb_config,max_frame, IXGBE_DCB_TX_CONFIG); ixgbe_dcb_calculate_tc_credits_cee(hw, dcb_config,max_frame, IXGBE_DCB_RX_CONFIG); if(config_dcb_rx) { /* Unpack CEE standard containers */ ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_RX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_RX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_RX_CONFIG, tsa); /* Configure PG(ETS) RX */ ixgbe_dcb_hw_arbite_rx_config(hw,refill,max,bwgid,tsa,map); } if(config_dcb_tx) { /* Unpack CEE standard containers */ ixgbe_dcb_unpack_refill_cee(dcb_config, IXGBE_DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max_cee(dcb_config, max); ixgbe_dcb_unpack_bwgid_cee(dcb_config, IXGBE_DCB_TX_CONFIG, bwgid); ixgbe_dcb_unpack_tsa_cee(dcb_config, IXGBE_DCB_TX_CONFIG, tsa); /* Configure PG(ETS) TX */ ixgbe_dcb_hw_arbite_tx_config(hw,refill,max,bwgid,tsa,map); } /*Configure queue statistics registers*/ ixgbe_dcb_config_tc_stats_82599(hw, dcb_config); /* Check if the PFC is supported */ if(dev->data->dev_conf.dcb_capability_en & ETH_DCB_PFC_SUPPORT) { pbsize = (uint16_t) (NIC_RX_BUFFER_SIZE / nb_tcs); for (i = 0; i < nb_tcs; i++) { /* * If the TC count is 8,and the default high_water is 48, * the low_water is 16 as default. */ hw->fc.high_water[i] = (pbsize * 3 ) / 4; hw->fc.low_water[i] = pbsize / 4; /* Enable pfc for this TC */ tc = &dcb_config->tc_config[i]; tc->pfc = ixgbe_dcb_pfc_enabled; } ixgbe_dcb_unpack_pfc_cee(dcb_config, map, &pfc_en); if(dcb_config->num_tcs.pfc_tcs == ETH_4_TCS) pfc_en &= 0x0F; ret = ixgbe_dcb_config_pfc(hw, pfc_en, map); } return ret; } /** * ixgbe_configure_dcb - Configure DCB Hardware * @dev: pointer to rte_eth_dev */ void ixgbe_configure_dcb(struct rte_eth_dev *dev) { struct ixgbe_dcb_config *dcb_cfg = IXGBE_DEV_PRIVATE_TO_DCB_CFG(dev->data->dev_private); struct rte_eth_conf *dev_conf = &(dev->data->dev_conf); PMD_INIT_FUNC_TRACE(); /* check support mq_mode for DCB */ if ((dev_conf->rxmode.mq_mode != ETH_MQ_RX_VMDQ_DCB) && (dev_conf->rxmode.mq_mode != ETH_MQ_RX_DCB)) return; if (dev->data->nb_rx_queues != ETH_DCB_NUM_QUEUES) return; /** Configure DCB hardware **/ ixgbe_dcb_hw_configure(dev,dcb_cfg); return; } /* * VMDq only support for 10 GbE NIC. */ static void ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) { struct rte_eth_vmdq_rx_conf *cfg; struct ixgbe_hw *hw; enum rte_eth_nb_pools num_pools; uint32_t mrqc, vt_ctl, vlanctrl; uint32_t vmolr = 0; int i; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; num_pools = cfg->nb_queue_pools; ixgbe_rss_disable(dev); /* MRQC: enable vmdq */ mrqc = IXGBE_MRQC_VMDQEN; IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); /* PFVTCTL: turn on virtualisation and set the default pool */ vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN; if (cfg->enable_default_pool) vt_ctl |= (cfg->default_pool << IXGBE_VT_CTL_POOL_SHIFT); else vt_ctl |= IXGBE_VT_CTL_DIS_DEFPL; IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vt_ctl); for (i = 0; i < (int)num_pools; i++) { vmolr = ixgbe_convert_vm_rx_mask_to_val(cfg->rx_mode, vmolr); IXGBE_WRITE_REG(hw, IXGBE_VMOLR(i), vmolr); } /* VLNCTRL: enable vlan filtering and allow all vlan tags through */ vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl); /* VFTA - enable all vlan filters */ for (i = 0; i < NUM_VFTA_REGISTERS; i++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), UINT32_MAX); /* VFRE: pool enabling for receive - 64 */ IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), UINT32_MAX); if (num_pools == ETH_64_POOLS) IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), UINT32_MAX); /* * MPSAR - allow pools to read specific mac addresses * In this case, all pools should be able to read from mac addr 0 */ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(0), UINT32_MAX); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(0), UINT32_MAX); /* PFVLVF, PFVLVFB: set up filters for vlan tags as configured */ for (i = 0; i < cfg->nb_pool_maps; i++) { /* set vlan id in VF register and set the valid bit */ IXGBE_WRITE_REG(hw, IXGBE_VLVF(i), (IXGBE_VLVF_VIEN | \ (cfg->pool_map[i].vlan_id & IXGBE_RXD_VLAN_ID_MASK))); /* * Put the allowed pools in VFB reg. As we only have 16 or 64 * pools, we only need to use the first half of the register * i.e. bits 0-31 */ if (((cfg->pool_map[i].pools >> 32) & UINT32_MAX) == 0) IXGBE_WRITE_REG(hw, IXGBE_VLVFB(i*2), \ (cfg->pool_map[i].pools & UINT32_MAX)); else IXGBE_WRITE_REG(hw, IXGBE_VLVFB((i*2+1)), \ ((cfg->pool_map[i].pools >> 32) \ & UINT32_MAX)); } /* PFDMA Tx General Switch Control Enables VMDQ loopback */ if (cfg->enable_loop_back) { IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); for (i = 0; i < RTE_IXGBE_VMTXSW_REGISTER_COUNT; i++) IXGBE_WRITE_REG(hw, IXGBE_VMTXSW(i), UINT32_MAX); } IXGBE_WRITE_FLUSH(hw); } /* * ixgbe_dcb_config_tx_hw_config - Configure general VMDq TX parameters * @hw: pointer to hardware structure */ static void ixgbe_vmdq_tx_hw_configure(struct ixgbe_hw *hw) { uint32_t reg; uint32_t q; PMD_INIT_FUNC_TRACE(); /*PF VF Transmit Enable*/ IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), UINT32_MAX); IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), UINT32_MAX); /* Disable the Tx desc arbiter so that MTQC can be changed */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg |= IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); reg = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF; IXGBE_WRITE_REG(hw, IXGBE_MTQC, reg); /* Disable drop for all queues */ for (q = 0; q < IXGBE_MAX_RX_QUEUE_NUM; q++) IXGBE_WRITE_REG(hw, IXGBE_QDE, (IXGBE_QDE_WRITE | (q << IXGBE_QDE_IDX_SHIFT))); /* Enable the Tx desc arbiter */ reg = IXGBE_READ_REG(hw, IXGBE_RTTDCS); reg &= ~IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, reg); IXGBE_WRITE_FLUSH(hw); return; } static int __attribute__((cold)) ixgbe_alloc_rx_queue_mbufs(struct ixgbe_rx_queue *rxq) { struct ixgbe_rx_entry *rxe = rxq->sw_ring; uint64_t dma_addr; unsigned i; /* Initialize software ring entries */ for (i = 0; i < rxq->nb_rx_desc; i++) { volatile union ixgbe_adv_rx_desc *rxd; struct rte_mbuf *mbuf = rte_rxmbuf_alloc(rxq->mb_pool); if (mbuf == NULL) { PMD_INIT_LOG(ERR, "RX mbuf alloc failed queue_id=%u", (unsigned) rxq->queue_id); return (-ENOMEM); } rte_mbuf_refcnt_set(mbuf, 1); mbuf->next = NULL; mbuf->data_off = RTE_PKTMBUF_HEADROOM; mbuf->nb_segs = 1; mbuf->port = rxq->port_id; dma_addr = rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf)); rxd = &rxq->rx_ring[i]; rxd->read.hdr_addr = 0; rxd->read.pkt_addr = dma_addr; rxe[i].mbuf = mbuf; } return 0; } static int ixgbe_config_vf_rss(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; uint32_t mrqc; ixgbe_rss_configure(dev); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* MRQC: enable VF RSS */ mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); mrqc &= ~IXGBE_MRQC_MRQE_MASK; switch (RTE_ETH_DEV_SRIOV(dev).active) { case ETH_64_POOLS: mrqc |= IXGBE_MRQC_VMDQRSS64EN; break; case ETH_32_POOLS: mrqc |= IXGBE_MRQC_VMDQRSS32EN; break; default: PMD_INIT_LOG(ERR, "Invalid pool number in IOV mode with VMDQ RSS"); return -EINVAL; } IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); return 0; } static int ixgbe_config_vf_default(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); switch (RTE_ETH_DEV_SRIOV(dev).active) { case ETH_64_POOLS: IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQEN); break; case ETH_32_POOLS: IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQRT4TCEN); break; case ETH_16_POOLS: IXGBE_WRITE_REG(hw, IXGBE_MRQC, IXGBE_MRQC_VMDQRT8TCEN); break; default: PMD_INIT_LOG(ERR, "invalid pool number in IOV mode"); break; } return 0; } static int ixgbe_dev_mq_rx_configure(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (hw->mac.type == ixgbe_mac_82598EB) return 0; if (RTE_ETH_DEV_SRIOV(dev).active == 0) { /* * SRIOV inactive scheme * any DCB/RSS w/o VMDq multi-queue setting */ switch (dev->data->dev_conf.rxmode.mq_mode) { case ETH_MQ_RX_RSS: ixgbe_rss_configure(dev); break; case ETH_MQ_RX_VMDQ_DCB: ixgbe_vmdq_dcb_configure(dev); break; case ETH_MQ_RX_VMDQ_ONLY: ixgbe_vmdq_rx_hw_configure(dev); break; case ETH_MQ_RX_NONE: /* if mq_mode is none, disable rss mode.*/ default: ixgbe_rss_disable(dev); } } else { /* * SRIOV active scheme * Support RSS together with VMDq & SRIOV */ switch (dev->data->dev_conf.rxmode.mq_mode) { case ETH_MQ_RX_RSS: case ETH_MQ_RX_VMDQ_RSS: ixgbe_config_vf_rss(dev); break; /* FIXME if support DCB/RSS together with VMDq & SRIOV */ case ETH_MQ_RX_VMDQ_DCB: case ETH_MQ_RX_VMDQ_DCB_RSS: PMD_INIT_LOG(ERR, "Could not support DCB with VMDq & SRIOV"); return -1; default: ixgbe_config_vf_default(dev); break; } } return 0; } static int ixgbe_dev_mq_tx_configure(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint32_t mtqc; uint32_t rttdcs; if (hw->mac.type == ixgbe_mac_82598EB) return 0; /* disable arbiter before setting MTQC */ rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); rttdcs |= IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); if (RTE_ETH_DEV_SRIOV(dev).active == 0) { /* * SRIOV inactive scheme * any DCB w/o VMDq multi-queue setting */ if (dev->data->dev_conf.txmode.mq_mode == ETH_MQ_TX_VMDQ_ONLY) ixgbe_vmdq_tx_hw_configure(hw); else { mtqc = IXGBE_MTQC_64Q_1PB; IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc); } } else { switch (RTE_ETH_DEV_SRIOV(dev).active) { /* * SRIOV active scheme * FIXME if support DCB together with VMDq & SRIOV */ case ETH_64_POOLS: mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF; break; case ETH_32_POOLS: mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_32VF; break; case ETH_16_POOLS: mtqc = IXGBE_MTQC_VT_ENA | IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ; break; default: mtqc = IXGBE_MTQC_64Q_1PB; PMD_INIT_LOG(ERR, "invalid pool number in IOV mode"); } IXGBE_WRITE_REG(hw, IXGBE_MTQC, mtqc); } /* re-enable arbiter */ rttdcs &= ~IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); return 0; } /** * ixgbe_get_rscctl_maxdesc - Calculate the RSCCTL[n].MAXDESC for PF * * Return the RSCCTL[n].MAXDESC for 82599 and x540 PF devices according to the * spec rev. 3.0 chapter 8.2.3.8.13. * * @pool Memory pool of the Rx queue */ static inline uint32_t ixgbe_get_rscctl_maxdesc(struct rte_mempool *pool) { struct rte_pktmbuf_pool_private *mp_priv = rte_mempool_get_priv(pool); /* MAXDESC * SRRCTL.BSIZEPKT must not exceed 64 KB minus one */ uint16_t maxdesc = IPV4_MAX_PKT_LEN / (mp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM); if (maxdesc >= 16) return IXGBE_RSCCTL_MAXDESC_16; else if (maxdesc >= 8) return IXGBE_RSCCTL_MAXDESC_8; else if (maxdesc >= 4) return IXGBE_RSCCTL_MAXDESC_4; else return IXGBE_RSCCTL_MAXDESC_1; } /** * ixgbe_set_ivar - Setup the correct IVAR register for a particular MSIX * interrupt * * (Taken from FreeBSD tree) * (yes this is all very magic and confusing :) * * @dev port handle * @entry the register array entry * @vector the MSIX vector for this queue * @type RX/TX/MISC */ static void ixgbe_set_ivar(struct rte_eth_dev *dev, u8 entry, u8 vector, s8 type) { struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); u32 ivar, index; vector |= IXGBE_IVAR_ALLOC_VAL; switch (hw->mac.type) { case ixgbe_mac_82598EB: if (type == -1) entry = IXGBE_IVAR_OTHER_CAUSES_INDEX; else entry += (type * 64); index = (entry >> 2) & 0x1F; ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index)); ivar &= ~(0xFF << (8 * (entry & 0x3))); ivar |= (vector << (8 * (entry & 0x3))); IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: if (type == -1) { /* MISC IVAR */ index = (entry & 1) * 8; ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC); ivar &= ~(0xFF << index); ivar |= (vector << index); IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar); } else { /* RX/TX IVARS */ index = (16 * (entry & 1)) + (8 * type); ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1)); ivar &= ~(0xFF << index); ivar |= (vector << index); IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar); } break; default: break; } } void __attribute__((cold)) ixgbe_set_rx_function(struct rte_eth_dev *dev) { uint16_t i, rx_using_sse; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; /* * In order to allow Vector Rx there are a few configuration * conditions to be met and Rx Bulk Allocation should be allowed. */ if (ixgbe_rx_vec_dev_conf_condition_check(dev) || !adapter->rx_bulk_alloc_allowed) { PMD_INIT_LOG(DEBUG, "Port[%d] doesn't meet Vector Rx " "preconditions or RTE_IXGBE_INC_VECTOR is " "not enabled", dev->data->port_id); adapter->rx_vec_allowed = false; } /* * Initialize the appropriate LRO callback. * * If all queues satisfy the bulk allocation preconditions * (hw->rx_bulk_alloc_allowed is TRUE) then we may use bulk allocation. * Otherwise use a single allocation version. */ if (dev->data->lro) { if (adapter->rx_bulk_alloc_allowed) { PMD_INIT_LOG(DEBUG, "LRO is requested. Using a bulk " "allocation version"); dev->rx_pkt_burst = ixgbe_recv_pkts_lro_bulk_alloc; } else { PMD_INIT_LOG(DEBUG, "LRO is requested. Using a single " "allocation version"); dev->rx_pkt_burst = ixgbe_recv_pkts_lro_single_alloc; } } else if (dev->data->scattered_rx) { /* * Set the non-LRO scattered callback: there are Vector and * single allocation versions. */ if (adapter->rx_vec_allowed) { PMD_INIT_LOG(DEBUG, "Using Vector Scattered Rx " "callback (port=%d).", dev->data->port_id); dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec; } else if (adapter->rx_bulk_alloc_allowed) { PMD_INIT_LOG(DEBUG, "Using a Scattered with bulk " "allocation callback (port=%d).", dev->data->port_id); dev->rx_pkt_burst = ixgbe_recv_pkts_lro_bulk_alloc; } else { PMD_INIT_LOG(DEBUG, "Using Regualr (non-vector, " "single allocation) " "Scattered Rx callback " "(port=%d).", dev->data->port_id); dev->rx_pkt_burst = ixgbe_recv_pkts_lro_single_alloc; } /* * Below we set "simple" callbacks according to port/queues parameters. * If parameters allow we are going to choose between the following * callbacks: * - Vector * - Bulk Allocation * - Single buffer allocation (the simplest one) */ } else if (adapter->rx_vec_allowed) { PMD_INIT_LOG(DEBUG, "Vector rx enabled, please make sure RX " "burst size no less than 32."); dev->rx_pkt_burst = ixgbe_recv_pkts_vec; } else if (adapter->rx_bulk_alloc_allowed) { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are " "satisfied. Rx Burst Bulk Alloc function " "will be used on port=%d.", dev->data->port_id); dev->rx_pkt_burst = ixgbe_recv_pkts_bulk_alloc; } else { PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are not " "satisfied, or Scattered Rx is requested " "(port=%d).", dev->data->port_id); dev->rx_pkt_burst = ixgbe_recv_pkts; } /* Propagate information about RX function choice through all queues. */ rx_using_sse = (dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec || dev->rx_pkt_burst == ixgbe_recv_pkts_vec); for (i = 0; i < dev->data->nb_rx_queues; i++) { struct ixgbe_rx_queue *rxq = dev->data->rx_queues[i]; rxq->rx_using_sse = rx_using_sse; } } /** * ixgbe_set_rsc - configure RSC related port HW registers * * Configures the port's RSC related registers according to the 4.6.7.2 chapter * of 82599 Spec (x540 configuration is virtually the same). * * @dev port handle * * Returns 0 in case of success or a non-zero error code */ static int ixgbe_set_rsc(struct rte_eth_dev *dev) { struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct rte_eth_dev_info dev_info = { 0 }; bool rsc_capable = false; uint16_t i; uint32_t rdrxctl; /* Sanity check */ dev->dev_ops->dev_infos_get(dev, &dev_info); if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) rsc_capable = true; if (!rsc_capable && rx_conf->enable_lro) { PMD_INIT_LOG(CRIT, "LRO is requested on HW that doesn't " "support it"); return -EINVAL; } /* RSC global configuration (chapter 4.6.7.2.1 of 82599 Spec) */ if (!rx_conf->hw_strip_crc && rx_conf->enable_lro) { /* * According to chapter of 4.6.7.2.1 of the Spec Rev. * 3.0 RSC configuration requires HW CRC stripping being * enabled. If user requested both HW CRC stripping off * and RSC on - return an error. */ PMD_INIT_LOG(CRIT, "LRO can't be enabled when HW CRC " "is disabled"); return -EINVAL; } /* RFCTL configuration */ if (rsc_capable) { uint32_t rfctl = IXGBE_READ_REG(hw, IXGBE_RFCTL); if (rx_conf->enable_lro) /* * Since NFS packets coalescing is not supported - clear * RFCTL.NFSW_DIS and RFCTL.NFSR_DIS when RSC is * enabled. */ rfctl &= ~(IXGBE_RFCTL_RSC_DIS | IXGBE_RFCTL_NFSW_DIS | IXGBE_RFCTL_NFSR_DIS); else rfctl |= IXGBE_RFCTL_RSC_DIS; IXGBE_WRITE_REG(hw, IXGBE_RFCTL, rfctl); } /* If LRO hasn't been requested - we are done here. */ if (!rx_conf->enable_lro) return 0; /* Set RDRXCTL.RSCACKC bit */ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); rdrxctl |= IXGBE_RDRXCTL_RSCACKC; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); /* Per-queue RSC configuration (chapter 4.6.7.2.2 of 82599 Spec) */ for (i = 0; i < dev->data->nb_rx_queues; i++) { struct ixgbe_rx_queue *rxq = dev->data->rx_queues[i]; uint32_t srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxq->reg_idx)); uint32_t rscctl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(rxq->reg_idx)); uint32_t psrtype = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx)); uint32_t eitr = IXGBE_READ_REG(hw, IXGBE_EITR(rxq->reg_idx)); /* * ixgbe PMD doesn't support header-split at the moment. * * Following the 4.6.7.2.1 chapter of the 82599/x540 * Spec if RSC is enabled the SRRCTL[n].BSIZEHEADER * should be configured even if header split is not * enabled. We will configure it 128 bytes following the * recommendation in the spec. */ srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK; srrctl |= (128 << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK; /* * TODO: Consider setting the Receive Descriptor Minimum * Threshold Size for an RSC case. This is not an obviously * beneficiary option but the one worth considering... */ rscctl |= IXGBE_RSCCTL_RSCEN; rscctl |= ixgbe_get_rscctl_maxdesc(rxq->mb_pool); psrtype |= IXGBE_PSRTYPE_TCPHDR; /* * RSC: Set ITR interval corresponding to 2K ints/s. * * Full-sized RSC aggregations for a 10Gb/s link will * arrive at about 20K aggregation/s rate. * * 2K inst/s rate will make only 10% of the * aggregations to be closed due to the interrupt timer * expiration for a streaming at wire-speed case. * * For a sparse streaming case this setting will yield * at most 500us latency for a single RSC aggregation. */ eitr &= ~IXGBE_EITR_ITR_INT_MASK; eitr |= IXGBE_EITR_INTERVAL_US(500) | IXGBE_EITR_CNT_WDIS; IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxq->reg_idx), srrctl); IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(rxq->reg_idx), rscctl); IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype); IXGBE_WRITE_REG(hw, IXGBE_EITR(rxq->reg_idx), eitr); /* * RSC requires the mapping of the queue to the * interrupt vector. */ ixgbe_set_ivar(dev, rxq->reg_idx, i, 0); } dev->data->lro = 1; PMD_INIT_LOG(DEBUG, "enabling LRO mode"); return 0; } /* * Initializes Receive Unit. */ int __attribute__((cold)) ixgbe_dev_rx_init(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_rx_queue *rxq; uint64_t bus_addr; uint32_t rxctrl; uint32_t fctrl; uint32_t hlreg0; uint32_t maxfrs; uint32_t srrctl; uint32_t rdrxctl; uint32_t rxcsum; uint16_t buf_size; uint16_t i; struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; int rc; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* * Make sure receives are disabled while setting * up the RX context (registers, descriptor rings, etc.). */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); /* Enable receipt of broadcasted frames */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl |= IXGBE_FCTRL_BAM; fctrl |= IXGBE_FCTRL_DPF; fctrl |= IXGBE_FCTRL_PMCF; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); /* * Configure CRC stripping, if any. */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); if (rx_conf->hw_strip_crc) hlreg0 |= IXGBE_HLREG0_RXCRCSTRP; else hlreg0 &= ~IXGBE_HLREG0_RXCRCSTRP; /* * Configure jumbo frame support, if any. */ if (rx_conf->jumbo_frame == 1) { hlreg0 |= IXGBE_HLREG0_JUMBOEN; maxfrs = IXGBE_READ_REG(hw, IXGBE_MAXFRS); maxfrs &= 0x0000FFFF; maxfrs |= (rx_conf->max_rx_pkt_len << 16); IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, maxfrs); } else hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; /* * If loopback mode is configured for 82599, set LPBK bit. */ if (hw->mac.type == ixgbe_mac_82599EB && dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) hlreg0 |= IXGBE_HLREG0_LPBK; else hlreg0 &= ~IXGBE_HLREG0_LPBK; IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); /* Setup RX queues */ for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; /* * Reset crc_len in case it was changed after queue setup by a * call to configure. */ rxq->crc_len = rx_conf->hw_strip_crc ? 0 : ETHER_CRC_LEN; /* Setup the Base and Length of the Rx Descriptor Rings */ bus_addr = rxq->rx_ring_phys_addr; IXGBE_WRITE_REG(hw, IXGBE_RDBAL(rxq->reg_idx), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); IXGBE_WRITE_REG(hw, IXGBE_RDBAH(rxq->reg_idx), (uint32_t)(bus_addr >> 32)); IXGBE_WRITE_REG(hw, IXGBE_RDLEN(rxq->reg_idx), rxq->nb_rx_desc * sizeof(union ixgbe_adv_rx_desc)); IXGBE_WRITE_REG(hw, IXGBE_RDH(rxq->reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), 0); /* Configure the SRRCTL register */ #ifdef RTE_HEADER_SPLIT_ENABLE /* * Configure Header Split */ if (rx_conf->header_split) { if (hw->mac.type == ixgbe_mac_82599EB) { /* Must setup the PSRTYPE register */ uint32_t psrtype; psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR; IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype); } srrctl = ((rx_conf->split_hdr_size << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK); srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; } else #endif srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; /* Set if packets are dropped when no descriptors available */ if (rxq->drop_en) srrctl |= IXGBE_SRRCTL_DROP_EN; /* * Configure the RX buffer size in the BSIZEPACKET field of * the SRRCTL register of the queue. * The value is in 1 KB resolution. Valid values can be from * 1 KB to 16 KB. */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM); srrctl |= ((buf_size >> IXGBE_SRRCTL_BSIZEPKT_SHIFT) & IXGBE_SRRCTL_BSIZEPKT_MASK); IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxq->reg_idx), srrctl); buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) << IXGBE_SRRCTL_BSIZEPKT_SHIFT); /* It adds dual VLAN length for supporting dual VLAN */ if (dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * IXGBE_VLAN_TAG_SIZE > buf_size) dev->data->scattered_rx = 1; } if (rx_conf->enable_scatter) dev->data->scattered_rx = 1; /* * Device configured with multiple RX queues. */ ixgbe_dev_mq_rx_configure(dev); /* * Setup the Checksum Register. * Disable Full-Packet Checksum which is mutually exclusive with RSS. * Enable IP/L4 checkum computation by hardware if requested to do so. */ rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); rxcsum |= IXGBE_RXCSUM_PCSD; if (rx_conf->hw_ip_checksum) rxcsum |= IXGBE_RXCSUM_IPPCSE; else rxcsum &= ~IXGBE_RXCSUM_IPPCSE; IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum); if (hw->mac.type == ixgbe_mac_82599EB || hw->mac.type == ixgbe_mac_X540) { rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); if (rx_conf->hw_strip_crc) rdrxctl |= IXGBE_RDRXCTL_CRCSTRIP; else rdrxctl &= ~IXGBE_RDRXCTL_CRCSTRIP; rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE; IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } rc = ixgbe_set_rsc(dev); if (rc) return rc; ixgbe_set_rx_function(dev); return 0; } /* * Initializes Transmit Unit. */ void __attribute__((cold)) ixgbe_dev_tx_init(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; uint64_t bus_addr; uint32_t hlreg0; uint32_t txctrl; uint16_t i; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Enable TX CRC (checksum offload requirement) and hw padding * (TSO requirement) */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); hlreg0 |= (IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_TXPADEN); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); /* Setup the Base and Length of the Tx Descriptor Rings */ for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; IXGBE_WRITE_REG(hw, IXGBE_TDBAL(txq->reg_idx), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); IXGBE_WRITE_REG(hw, IXGBE_TDBAH(txq->reg_idx), (uint32_t)(bus_addr >> 32)); IXGBE_WRITE_REG(hw, IXGBE_TDLEN(txq->reg_idx), txq->nb_tx_desc * sizeof(union ixgbe_adv_tx_desc)); /* Setup the HW Tx Head and TX Tail descriptor pointers */ IXGBE_WRITE_REG(hw, IXGBE_TDH(txq->reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(txq->reg_idx), 0); /* * Disable Tx Head Writeback RO bit, since this hoses * bookkeeping if things aren't delivered in order. */ switch (hw->mac.type) { case ixgbe_mac_82598EB: txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(txq->reg_idx)); txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(txq->reg_idx), txctrl); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: default: txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(txq->reg_idx)); txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(txq->reg_idx), txctrl); break; } } /* Device configured with multiple TX queues. */ ixgbe_dev_mq_tx_configure(dev); } /* * Set up link for 82599 loopback mode Tx->Rx. */ static inline void __attribute__((cold)) ixgbe_setup_loopback_link_82599(struct ixgbe_hw *hw) { PMD_INIT_FUNC_TRACE(); if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM) != IXGBE_SUCCESS) { PMD_INIT_LOG(ERR, "Could not enable loopback mode"); /* ignore error */ return; } } /* Restart link */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU); ixgbe_reset_pipeline_82599(hw); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); msec_delay(50); } /* * Start Transmit and Receive Units. */ int __attribute__((cold)) ixgbe_dev_rxtx_start(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; struct ixgbe_rx_queue *rxq; uint32_t txdctl; uint32_t dmatxctl; uint32_t rxctrl; uint16_t i; int ret = 0; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; /* Setup Transmit Threshold Registers */ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); txdctl |= txq->pthresh & 0x7F; txdctl |= ((txq->hthresh & 0x7F) << 8); txdctl |= ((txq->wthresh & 0x7F) << 16); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txq->reg_idx), txdctl); } if (hw->mac.type != ixgbe_mac_82598EB) { dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); dmatxctl |= IXGBE_DMATXCTL_TE; IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); } for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; if (!txq->tx_deferred_start) { ret = ixgbe_dev_tx_queue_start(dev, i); if (ret < 0) return ret; } } for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; if (!rxq->rx_deferred_start) { ret = ixgbe_dev_rx_queue_start(dev, i); if (ret < 0) return ret; } } /* Enable Receive engine */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); if (hw->mac.type == ixgbe_mac_82598EB) rxctrl |= IXGBE_RXCTRL_DMBYPS; rxctrl |= IXGBE_RXCTRL_RXEN; hw->mac.ops.enable_rx_dma(hw, rxctrl); /* If loopback mode is enabled for 82599, set up the link accordingly */ if (hw->mac.type == ixgbe_mac_82599EB && dev->data->dev_conf.lpbk_mode == IXGBE_LPBK_82599_TX_RX) ixgbe_setup_loopback_link_82599(hw); return 0; } /* * Start Receive Units for specified queue. */ int __attribute__((cold)) ixgbe_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct ixgbe_hw *hw; struct ixgbe_rx_queue *rxq; uint32_t rxdctl; int poll_ms; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; /* Allocate buffers for descriptor rings */ if (ixgbe_alloc_rx_queue_mbufs(rxq) != 0) { PMD_INIT_LOG(ERR, "Could not alloc mbuf for queue:%d", rx_queue_id); return -1; } rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); rxdctl |= IXGBE_RXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxq->reg_idx), rxdctl); /* Wait until RX Enable ready */ poll_ms = RTE_IXGBE_REGISTER_POLL_WAIT_10_MS; do { rte_delay_ms(1); rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); } while (--poll_ms && !(rxdctl & IXGBE_RXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", rx_queue_id); rte_wmb(); IXGBE_WRITE_REG(hw, IXGBE_RDH(rxq->reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_RDT(rxq->reg_idx), rxq->nb_rx_desc - 1); } else return -1; return 0; } /* * Stop Receive Units for specified queue. */ int __attribute__((cold)) ixgbe_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id) { struct ixgbe_hw *hw; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)dev->data->dev_private; struct ixgbe_rx_queue *rxq; uint32_t rxdctl; int poll_ms; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (rx_queue_id < dev->data->nb_rx_queues) { rxq = dev->data->rx_queues[rx_queue_id]; rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); rxdctl &= ~IXGBE_RXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rxq->reg_idx), rxdctl); /* Wait until RX Enable ready */ poll_ms = RTE_IXGBE_REGISTER_POLL_WAIT_10_MS; do { rte_delay_ms(1); rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rxq->reg_idx)); } while (--poll_ms && (rxdctl | IXGBE_RXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not disable Rx Queue %d", rx_queue_id); rte_delay_us(RTE_IXGBE_WAIT_100_US); ixgbe_rx_queue_release_mbufs(rxq); ixgbe_reset_rx_queue(adapter, rxq); } else return -1; return 0; } /* * Start Transmit Units for specified queue. */ int __attribute__((cold)) ixgbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; uint32_t txdctl; int poll_ms; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (tx_queue_id < dev->data->nb_tx_queues) { txq = dev->data->tx_queues[tx_queue_id]; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txq->reg_idx), txdctl); /* Wait until TX Enable ready */ if (hw->mac.type == ixgbe_mac_82599EB) { poll_ms = RTE_IXGBE_REGISTER_POLL_WAIT_10_MS; do { rte_delay_ms(1); txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); } while (--poll_ms && !(txdctl & IXGBE_TXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable " "Tx Queue %d", tx_queue_id); } rte_wmb(); IXGBE_WRITE_REG(hw, IXGBE_TDH(txq->reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(txq->reg_idx), 0); } else return -1; return 0; } /* * Stop Transmit Units for specified queue. */ int __attribute__((cold)) ixgbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; uint32_t txdctl; uint32_t txtdh, txtdt; int poll_ms; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (tx_queue_id < dev->data->nb_tx_queues) { txq = dev->data->tx_queues[tx_queue_id]; /* Wait until TX queue is empty */ if (hw->mac.type == ixgbe_mac_82599EB) { poll_ms = RTE_IXGBE_REGISTER_POLL_WAIT_10_MS; do { rte_delay_us(RTE_IXGBE_WAIT_100_US); txtdh = IXGBE_READ_REG(hw, IXGBE_TDH(txq->reg_idx)); txtdt = IXGBE_READ_REG(hw, IXGBE_TDT(txq->reg_idx)); } while (--poll_ms && (txtdh != txtdt)); if (!poll_ms) PMD_INIT_LOG(ERR, "Tx Queue %d is not empty " "when stopping.", tx_queue_id); } txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); txdctl &= ~IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(txq->reg_idx), txdctl); /* Wait until TX Enable ready */ if (hw->mac.type == ixgbe_mac_82599EB) { poll_ms = RTE_IXGBE_REGISTER_POLL_WAIT_10_MS; do { rte_delay_ms(1); txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(txq->reg_idx)); } while (--poll_ms && (txdctl | IXGBE_TXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not disable " "Tx Queue %d", tx_queue_id); } if (txq->ops != NULL) { txq->ops->release_mbufs(txq); txq->ops->reset(txq); } } else return -1; return 0; } /* * [VF] Initializes Receive Unit. */ int __attribute__((cold)) ixgbevf_dev_rx_init(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_rx_queue *rxq; uint64_t bus_addr; uint32_t srrctl, psrtype = 0; uint16_t buf_size; uint16_t i; int ret; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); if (rte_is_power_of_2(dev->data->nb_rx_queues) == 0) { PMD_INIT_LOG(ERR, "The number of Rx queue invalid, " "it should be power of 2"); return -1; } if (dev->data->nb_rx_queues > hw->mac.max_rx_queues) { PMD_INIT_LOG(ERR, "The number of Rx queue invalid, " "it should be equal to or less than %d", hw->mac.max_rx_queues); return -1; } /* * When the VF driver issues a IXGBE_VF_RESET request, the PF driver * disables the VF receipt of packets if the PF MTU is > 1500. * This is done to deal with 82599 limitations that imposes * the PF and all VFs to share the same MTU. * Then, the PF driver enables again the VF receipt of packet when * the VF driver issues a IXGBE_VF_SET_LPE request. * In the meantime, the VF device cannot be used, even if the VF driver * and the Guest VM network stack are ready to accept packets with a * size up to the PF MTU. * As a work-around to this PF behaviour, force the call to * ixgbevf_rlpml_set_vf even if jumbo frames are not used. This way, * VF packets received can work in all cases. */ ixgbevf_rlpml_set_vf(hw, (uint16_t)dev->data->dev_conf.rxmode.max_rx_pkt_len); /* Setup RX queues */ for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; /* Allocate buffers for descriptor rings */ ret = ixgbe_alloc_rx_queue_mbufs(rxq); if (ret) return ret; /* Setup the Base and Length of the Rx Descriptor Rings */ bus_addr = rxq->rx_ring_phys_addr; IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(i), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(i), (uint32_t)(bus_addr >> 32)); IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(i), rxq->nb_rx_desc * sizeof(union ixgbe_adv_rx_desc)); IXGBE_WRITE_REG(hw, IXGBE_VFRDH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFRDT(i), 0); /* Configure the SRRCTL register */ #ifdef RTE_HEADER_SPLIT_ENABLE /* * Configure Header Split */ if (dev->data->dev_conf.rxmode.header_split) { srrctl = ((dev->data->dev_conf.rxmode.split_hdr_size << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & IXGBE_SRRCTL_BSIZEHDR_MASK); srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; } else #endif srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; /* Set if packets are dropped when no descriptors available */ if (rxq->drop_en) srrctl |= IXGBE_SRRCTL_DROP_EN; /* * Configure the RX buffer size in the BSIZEPACKET field of * the SRRCTL register of the queue. * The value is in 1 KB resolution. Valid values can be from * 1 KB to 16 KB. */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM); srrctl |= ((buf_size >> IXGBE_SRRCTL_BSIZEPKT_SHIFT) & IXGBE_SRRCTL_BSIZEPKT_MASK); /* * VF modification to write virtual function SRRCTL register */ IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(i), srrctl); buf_size = (uint16_t) ((srrctl & IXGBE_SRRCTL_BSIZEPKT_MASK) << IXGBE_SRRCTL_BSIZEPKT_SHIFT); if (dev->data->dev_conf.rxmode.enable_scatter || /* It adds dual VLAN length for supporting dual VLAN */ (dev->data->dev_conf.rxmode.max_rx_pkt_len + 2 * IXGBE_VLAN_TAG_SIZE) > buf_size) { if (!dev->data->scattered_rx) PMD_INIT_LOG(DEBUG, "forcing scatter mode"); dev->data->scattered_rx = 1; } } #ifdef RTE_HEADER_SPLIT_ENABLE if (dev->data->dev_conf.rxmode.header_split) /* Must setup the PSRTYPE register */ psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR; #endif /* Set RQPL for VF RSS according to max Rx queue */ psrtype |= (dev->data->nb_rx_queues >> 1) << IXGBE_PSRTYPE_RQPL_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); ixgbe_set_rx_function(dev); return 0; } /* * [VF] Initializes Transmit Unit. */ void __attribute__((cold)) ixgbevf_dev_tx_init(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; uint64_t bus_addr; uint32_t txctrl; uint16_t i; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); /* Setup the Base and Length of the Tx Descriptor Rings */ for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; bus_addr = txq->tx_ring_phys_addr; IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(i), (uint32_t)(bus_addr & 0x00000000ffffffffULL)); IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(i), (uint32_t)(bus_addr >> 32)); IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(i), txq->nb_tx_desc * sizeof(union ixgbe_adv_tx_desc)); /* Setup the HW Tx Head and TX Tail descriptor pointers */ IXGBE_WRITE_REG(hw, IXGBE_VFTDH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_VFTDT(i), 0); /* * Disable Tx Head Writeback RO bit, since this hoses * bookkeeping if things aren't delivered in order. */ txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(i)); txctrl &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(i), txctrl); } } /* * [VF] Start Transmit and Receive Units. */ void __attribute__((cold)) ixgbevf_dev_rxtx_start(struct rte_eth_dev *dev) { struct ixgbe_hw *hw; struct ixgbe_tx_queue *txq; struct ixgbe_rx_queue *rxq; uint32_t txdctl; uint32_t rxdctl; uint16_t i; int poll_ms; PMD_INIT_FUNC_TRACE(); hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); for (i = 0; i < dev->data->nb_tx_queues; i++) { txq = dev->data->tx_queues[i]; /* Setup Transmit Threshold Registers */ txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); txdctl |= txq->pthresh & 0x7F; txdctl |= ((txq->hthresh & 0x7F) << 8); txdctl |= ((txq->wthresh & 0x7F) << 16); IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl); } for (i = 0; i < dev->data->nb_tx_queues; i++) { txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), txdctl); poll_ms = 10; /* Wait until TX Enable ready */ do { rte_delay_ms(1); txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); } while (--poll_ms && !(txdctl & IXGBE_TXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable Tx Queue %d", i); } for (i = 0; i < dev->data->nb_rx_queues; i++) { rxq = dev->data->rx_queues[i]; rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); rxdctl |= IXGBE_RXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), rxdctl); /* Wait until RX Enable ready */ poll_ms = 10; do { rte_delay_ms(1); rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); } while (--poll_ms && !(rxdctl & IXGBE_RXDCTL_ENABLE)); if (!poll_ms) PMD_INIT_LOG(ERR, "Could not enable Rx Queue %d", i); rte_wmb(); IXGBE_WRITE_REG(hw, IXGBE_VFRDT(i), rxq->nb_rx_desc - 1); } } /* Stubs needed for linkage when CONFIG_RTE_IXGBE_INC_VECTOR is set to 'n' */ int __attribute__((weak)) ixgbe_rx_vec_dev_conf_condition_check(struct rte_eth_dev __rte_unused *dev) { return -1; } uint16_t __attribute__((weak)) ixgbe_recv_pkts_vec( void __rte_unused *rx_queue, struct rte_mbuf __rte_unused **rx_pkts, uint16_t __rte_unused nb_pkts) { return 0; } uint16_t __attribute__((weak)) ixgbe_recv_scattered_pkts_vec( void __rte_unused *rx_queue, struct rte_mbuf __rte_unused **rx_pkts, uint16_t __rte_unused nb_pkts) { return 0; } int __attribute__((weak)) ixgbe_rxq_vec_setup(struct ixgbe_rx_queue __rte_unused *rxq) { return -1; } ================================================ FILE: drivers/net/ixgbe/ixgbe_rxtx.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IXGBE_RXTX_H_ #define _IXGBE_RXTX_H_ #define RTE_PMD_IXGBE_TX_MAX_BURST 32 #define RTE_PMD_IXGBE_RX_MAX_BURST 32 #define RTE_IXGBE_DESCS_PER_LOOP 4 #define RTE_MBUF_DATA_DMA_ADDR(mb) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) #ifdef RTE_IXGBE_INC_VECTOR #define RTE_IXGBE_VPMD_RX_BURST 32 #define RTE_IXGBE_VPMD_TX_BURST 32 #define RTE_IXGBE_RXQ_REARM_THRESH RTE_IXGBE_VPMD_RX_BURST #define RTE_IXGBE_TX_MAX_FREE_BUF_SZ 64 #endif #define RX_RING_SZ ((IXGBE_MAX_RING_DESC + RTE_IXGBE_DESCS_PER_LOOP - 1) * \ sizeof(union ixgbe_adv_rx_desc)) #ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch(p) rte_prefetch1(p) #else #define rte_packet_prefetch(p) do {} while(0) #endif #define RTE_IXGBE_REGISTER_POLL_WAIT_10_MS 10 #define RTE_IXGBE_WAIT_100_US 100 #define RTE_IXGBE_VMTXSW_REGISTER_COUNT 2 /** * Structure associated with each descriptor of the RX ring of a RX queue. */ struct ixgbe_rx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with RX descriptor. */ }; struct ixgbe_scattered_rx_entry { struct rte_mbuf *fbuf; /**< First segment of the fragmented packet. */ }; /** * Structure associated with each descriptor of the TX ring of a TX queue. */ struct ixgbe_tx_entry { struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ uint16_t next_id; /**< Index of next descriptor in ring. */ uint16_t last_id; /**< Index of last scattered descriptor. */ }; /** * Structure associated with each descriptor of the TX ring of a TX queue. */ struct ixgbe_tx_entry_v { struct rte_mbuf *mbuf; /**< mbuf associated with TX desc, if any. */ }; /** * Structure associated with each RX queue. */ struct ixgbe_rx_queue { struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ volatile union ixgbe_adv_rx_desc *rx_ring; /**< RX ring virtual address. */ uint64_t rx_ring_phys_addr; /**< RX ring DMA address. */ volatile uint32_t *rdt_reg_addr; /**< RDT register address. */ volatile uint32_t *rdh_reg_addr; /**< RDH register address. */ struct ixgbe_rx_entry *sw_ring; /**< address of RX software ring. */ struct ixgbe_scattered_rx_entry *sw_sc_ring; /**< address of scattered Rx software ring. */ struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ uint64_t mbuf_initializer; /**< value to init mbufs */ uint16_t nb_rx_desc; /**< number of RX descriptors. */ uint16_t rx_tail; /**< current value of RDT register. */ uint16_t nb_rx_hold; /**< number of held free RX desc. */ uint16_t rx_nb_avail; /**< nr of staged pkts ready to ret to app */ uint16_t rx_next_avail; /**< idx of next staged pkt to ret to app */ uint16_t rx_free_trigger; /**< triggers rx buffer allocation */ uint16_t rx_using_sse; /**< indicates that vector RX is in use */ #ifdef RTE_IXGBE_INC_VECTOR uint16_t rxrearm_nb; /**< number of remaining to be re-armed */ uint16_t rxrearm_start; /**< the idx we start the re-arming from */ #endif uint16_t rx_free_thresh; /**< max free RX desc to hold. */ uint16_t queue_id; /**< RX queue index. */ uint16_t reg_idx; /**< RX queue register index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ uint8_t rx_deferred_start; /**< not in global dev start. */ /** need to alloc dummy mbuf, for wraparound when scanning hw ring */ struct rte_mbuf fake_mbuf; /** hold packets to return to application */ struct rte_mbuf *rx_stage[RTE_PMD_IXGBE_RX_MAX_BURST*2]; }; /** * IXGBE CTX Constants */ enum ixgbe_advctx_num { IXGBE_CTX_0 = 0, /**< CTX0 */ IXGBE_CTX_1 = 1, /**< CTX1 */ IXGBE_CTX_NUM = 2, /**< CTX NUMBER */ }; /** Offload features */ union ixgbe_tx_offload { uint64_t data; struct { uint64_t l2_len:7; /**< L2 (MAC) Header Length. */ uint64_t l3_len:9; /**< L3 (IP) Header Length. */ uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */ uint64_t tso_segsz:16; /**< TCP TSO segment size */ uint64_t vlan_tci:16; /**< VLAN Tag Control Identifier (CPU order). */ }; }; /* * Compare mask for vlan_macip_len.data, * should be in sync with ixgbe_vlan_macip.f layout. * */ #define TX_VLAN_CMP_MASK 0xFFFF0000 /**< VLAN length - 16-bits. */ #define TX_MAC_LEN_CMP_MASK 0x0000FE00 /**< MAC length - 7-bits. */ #define TX_IP_LEN_CMP_MASK 0x000001FF /**< IP length - 9-bits. */ /** MAC+IP length. */ #define TX_MACIP_LEN_CMP_MASK (TX_MAC_LEN_CMP_MASK | TX_IP_LEN_CMP_MASK) /** * Structure to check if new context need be built */ struct ixgbe_advctx_info { uint64_t flags; /**< ol_flags for context build. */ /**< tx offload: vlan, tso, l2-l3-l4 lengths. */ union ixgbe_tx_offload tx_offload; /** compare mask for tx offload. */ union ixgbe_tx_offload tx_offload_mask; }; /** * Structure associated with each TX queue. */ struct ixgbe_tx_queue { /** TX ring virtual address. */ volatile union ixgbe_adv_tx_desc *tx_ring; uint64_t tx_ring_phys_addr; /**< TX ring DMA address. */ union { struct ixgbe_tx_entry *sw_ring; /**< address of SW ring for scalar PMD. */ struct ixgbe_tx_entry_v *sw_ring_v; /**< address of SW ring for vector PMD */ }; volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ uint16_t nb_tx_desc; /**< number of TX descriptors. */ uint16_t tx_tail; /**< current value of TDT reg. */ /**< Start freeing TX buffers if there are less free descriptors than this value. */ uint16_t tx_free_thresh; /** Number of TX descriptors to use before RS bit is set. */ uint16_t tx_rs_thresh; /** Number of TX descriptors used since RS bit was set. */ uint16_t nb_tx_used; /** Index to last TX descriptor to have been cleaned. */ uint16_t last_desc_cleaned; /** Total number of TX descriptors ready to be allocated. */ uint16_t nb_tx_free; uint16_t tx_next_dd; /**< next desc to scan for DD bit */ uint16_t tx_next_rs; /**< next desc to set RS bit */ uint16_t queue_id; /**< TX queue index. */ uint16_t reg_idx; /**< TX queue register index. */ uint8_t port_id; /**< Device port identifier. */ uint8_t pthresh; /**< Prefetch threshold register. */ uint8_t hthresh; /**< Host threshold register. */ uint8_t wthresh; /**< Write-back threshold reg. */ uint32_t txq_flags; /**< Holds flags for this TXq */ uint32_t ctx_curr; /**< Hardware context states. */ /** Hardware context0 history. */ struct ixgbe_advctx_info ctx_cache[IXGBE_CTX_NUM]; const struct ixgbe_txq_ops *ops; /**< txq ops */ uint8_t tx_deferred_start; /**< not in global dev start. */ }; struct ixgbe_txq_ops { void (*release_mbufs)(struct ixgbe_tx_queue *txq); void (*free_swring)(struct ixgbe_tx_queue *txq); void (*reset)(struct ixgbe_tx_queue *txq); }; /* * The "simple" TX queue functions require that the following * flags are set when the TX queue is configured: * - ETH_TXQ_FLAGS_NOMULTSEGS * - ETH_TXQ_FLAGS_NOVLANOFFL * - ETH_TXQ_FLAGS_NOXSUMSCTP * - ETH_TXQ_FLAGS_NOXSUMUDP * - ETH_TXQ_FLAGS_NOXSUMTCP * and that the RS bit threshold (tx_rs_thresh) is at least equal to * RTE_PMD_IXGBE_TX_MAX_BURST. */ #define IXGBE_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ ETH_TXQ_FLAGS_NOOFFLOADS) /* * Populate descriptors with the following info: * 1.) buffer_addr = phys_addr + headroom * 2.) cmd_type_len = DCMD_DTYP_FLAGS | pkt_len * 3.) olinfo_status = pkt_len << PAYLEN_SHIFT */ /* Defines for Tx descriptor */ #define DCMD_DTYP_FLAGS (IXGBE_ADVTXD_DTYP_DATA |\ IXGBE_ADVTXD_DCMD_IFCS |\ IXGBE_ADVTXD_DCMD_DEXT |\ IXGBE_ADVTXD_DCMD_EOP) /* Takes an ethdev and a queue and sets up the tx function to be used based on * the queue parameters. Used in tx_queue_setup by primary process and then * in dev_init by secondary process when attaching to an existing ethdev. */ void ixgbe_set_tx_function(struct rte_eth_dev *dev, struct ixgbe_tx_queue *txq); /** * Sets the rx_pkt_burst callback in the ixgbe rte_eth_dev instance. * * Sets the callback based on the device parameters: * - ixgbe_hw.rx_bulk_alloc_allowed * - rte_eth_dev_data.scattered_rx * - rte_eth_dev_data.lro * - conditions checked in ixgbe_rx_vec_condition_check() * * This means that the parameters above have to be configured prior to calling * to this function. * * @dev rte_eth_dev handle */ void ixgbe_set_rx_function(struct rte_eth_dev *dev); uint16_t ixgbe_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); int ixgbe_rx_vec_dev_conf_condition_check(struct rte_eth_dev *dev); int ixgbe_rxq_vec_setup(struct ixgbe_rx_queue *rxq); void ixgbe_rx_queue_release_mbufs_vec(struct ixgbe_rx_queue *rxq); #ifdef RTE_IXGBE_INC_VECTOR uint16_t ixgbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int ixgbe_txq_vec_setup(struct ixgbe_tx_queue *txq); #endif /* RTE_IXGBE_INC_VECTOR */ #endif /* _IXGBE_RXTX_H_ */ ================================================ FILE: drivers/net/ixgbe/ixgbe_rxtx_vec.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "ixgbe_ethdev.h" #include "ixgbe_rxtx.h" #include #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wcast-qual" #endif static inline void ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq) { int i; uint16_t rx_id; volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *rxep = &rxq->sw_ring[rxq->rxrearm_start]; struct rte_mbuf *mb0, *mb1; __m128i hdr_room = _mm_set_epi64x(RTE_PKTMBUF_HEADROOM, RTE_PKTMBUF_HEADROOM); __m128i dma_addr0, dma_addr1; const __m128i hba_msk = _mm_set_epi64x(0, UINT64_MAX); rxdp = rxq->rx_ring + rxq->rxrearm_start; /* Pull 'n' more MBUFs into the software ring */ if (rte_mempool_get_bulk(rxq->mb_pool, (void *)rxep, RTE_IXGBE_RXQ_REARM_THRESH) < 0) { if (rxq->rxrearm_nb + RTE_IXGBE_RXQ_REARM_THRESH >= rxq->nb_rx_desc) { dma_addr0 = _mm_setzero_si128(); for (i = 0; i < RTE_IXGBE_DESCS_PER_LOOP; i++) { rxep[i].mbuf = &rxq->fake_mbuf; _mm_store_si128((__m128i *)&rxdp[i].read, dma_addr0); } } rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed += RTE_IXGBE_RXQ_REARM_THRESH; return; } /* Initialize the mbufs in vector, process 2 mbufs in one loop */ for (i = 0; i < RTE_IXGBE_RXQ_REARM_THRESH; i += 2, rxep += 2) { __m128i vaddr0, vaddr1; uintptr_t p0, p1; mb0 = rxep[0].mbuf; mb1 = rxep[1].mbuf; /* * Flush mbuf with pkt template. * Data to be rearmed is 6 bytes long. * Though, RX will overwrite ol_flags that are coming next * anyway. So overwrite whole 8 bytes with one load: * 6 bytes of rearm_data plus first 2 bytes of ol_flags. */ p0 = (uintptr_t)&mb0->rearm_data; *(uint64_t *)p0 = rxq->mbuf_initializer; p1 = (uintptr_t)&mb1->rearm_data; *(uint64_t *)p1 = rxq->mbuf_initializer; /* load buf_addr(lo 64bit) and buf_physaddr(hi 64bit) */ vaddr0 = _mm_loadu_si128((__m128i *)&(mb0->buf_addr)); vaddr1 = _mm_loadu_si128((__m128i *)&(mb1->buf_addr)); /* convert pa to dma_addr hdr/data */ dma_addr0 = _mm_unpackhi_epi64(vaddr0, vaddr0); dma_addr1 = _mm_unpackhi_epi64(vaddr1, vaddr1); /* add headroom to pa values */ dma_addr0 = _mm_add_epi64(dma_addr0, hdr_room); dma_addr1 = _mm_add_epi64(dma_addr1, hdr_room); /* set Header Buffer Address to zero */ dma_addr0 = _mm_and_si128(dma_addr0, hba_msk); dma_addr1 = _mm_and_si128(dma_addr1, hba_msk); /* flush desc with pa dma_addr */ _mm_store_si128((__m128i *)&rxdp++->read, dma_addr0); _mm_store_si128((__m128i *)&rxdp++->read, dma_addr1); } rxq->rxrearm_start += RTE_IXGBE_RXQ_REARM_THRESH; if (rxq->rxrearm_start >= rxq->nb_rx_desc) rxq->rxrearm_start = 0; rxq->rxrearm_nb -= RTE_IXGBE_RXQ_REARM_THRESH; rx_id = (uint16_t) ((rxq->rxrearm_start == 0) ? (rxq->nb_rx_desc - 1) : (rxq->rxrearm_start - 1)); /* Update the tail pointer on the NIC */ IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id); } /* Handling the offload flags (olflags) field takes computation * time when receiving packets. Therefore we provide a flag to disable * the processing of the olflags field when they are not needed. This * gives improved performance, at the cost of losing the offload info * in the received packet */ #ifdef RTE_IXGBE_RX_OLFLAGS_ENABLE #ifndef RTE_NEXT_ABI #define OLFLAGS_MASK ((uint16_t)(PKT_RX_VLAN_PKT | PKT_RX_IPV4_HDR |\ PKT_RX_IPV4_HDR_EXT | PKT_RX_IPV6_HDR |\ PKT_RX_IPV6_HDR_EXT)) #define PTYPE_SHIFT (1) #endif /* RTE_NEXT_ABI */ #define VTAG_SHIFT (3) static inline void desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts) { #ifdef RTE_NEXT_ABI __m128i ptype0, ptype1, vtag0, vtag1; union { uint16_t e[4]; uint64_t dword; } vol; /* pkt type + vlan olflags mask */ const __m128i pkttype_msk = _mm_set_epi16( 0x0000, 0x0000, 0x0000, 0x0000, PKT_RX_VLAN_PKT, PKT_RX_VLAN_PKT, PKT_RX_VLAN_PKT, PKT_RX_VLAN_PKT); /* mask everything except rss type */ const __m128i rsstype_msk = _mm_set_epi16( 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000F, 0x000F); /* map rss type to rss hash flag */ const __m128i rss_flags = _mm_set_epi8(PKT_RX_FDIR, 0, 0, 0, 0, 0, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0); ptype0 = _mm_unpacklo_epi16(descs[0], descs[1]); ptype1 = _mm_unpacklo_epi16(descs[2], descs[3]); vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]); vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]); ptype0 = _mm_unpacklo_epi32(ptype0, ptype1); ptype0 = _mm_and_si128(ptype0, rsstype_msk); ptype0 = _mm_shuffle_epi8(rss_flags, ptype0); vtag1 = _mm_unpacklo_epi32(vtag0, vtag1); vtag1 = _mm_srli_epi16(vtag1, VTAG_SHIFT); vtag1 = _mm_and_si128(vtag1, pkttype_msk); vtag1 = _mm_or_si128(ptype0, vtag1); vol.dword = _mm_cvtsi128_si64(vtag1); #else __m128i ptype0, ptype1, vtag0, vtag1; union { uint16_t e[4]; uint64_t dword; } vol; /* pkt type + vlan olflags mask */ const __m128i pkttype_msk = _mm_set_epi16( 0x0000, 0x0000, 0x0000, 0x0000, OLFLAGS_MASK, OLFLAGS_MASK, OLFLAGS_MASK, OLFLAGS_MASK); /* mask everything except rss type */ const __m128i rsstype_msk = _mm_set_epi16( 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000F, 0x000F); /* rss type to PKT_RX_RSS_HASH translation */ const __m128i rss_flags = _mm_set_epi8(PKT_RX_FDIR, 0, 0, 0, 0, 0, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0); ptype0 = _mm_unpacklo_epi16(descs[0], descs[1]); ptype1 = _mm_unpacklo_epi16(descs[2], descs[3]); vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]); vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]); ptype1 = _mm_unpacklo_epi32(ptype0, ptype1); vtag1 = _mm_unpacklo_epi32(vtag0, vtag1); ptype0 = _mm_and_si128(ptype1, rsstype_msk); ptype0 = _mm_shuffle_epi8(rss_flags, ptype0); ptype1 = _mm_slli_epi16(ptype1, PTYPE_SHIFT); vtag1 = _mm_srli_epi16(vtag1, VTAG_SHIFT); ptype1 = _mm_or_si128(ptype1, vtag1); ptype1 = _mm_and_si128(ptype1, pkttype_msk); ptype0 = _mm_or_si128(ptype0, ptype1); vol.dword = _mm_cvtsi128_si64(ptype0); #endif /* RTE_NEXT_ABI */ rx_pkts[0]->ol_flags = vol.e[0]; rx_pkts[1]->ol_flags = vol.e[1]; rx_pkts[2]->ol_flags = vol.e[2]; rx_pkts[3]->ol_flags = vol.e[3]; } #else #define desc_to_olflags_v(desc, rx_pkts) do {} while (0) #endif /* * vPMD receive routine, now only accept (nb_pkts == RTE_IXGBE_VPMD_RX_BURST) * in one loop * * Notice: * - nb_pkts < RTE_IXGBE_VPMD_RX_BURST, just return no packet * - nb_pkts > RTE_IXGBE_VPMD_RX_BURST, only scan RTE_IXGBE_VPMD_RX_BURST * numbers of DD bit * - don't support ol_flags for rss and csum err */ static inline uint16_t _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint8_t *split_packet) { volatile union ixgbe_adv_rx_desc *rxdp; struct ixgbe_rx_entry *sw_ring; uint16_t nb_pkts_recd; int pos; uint64_t var; __m128i shuf_msk; #ifdef RTE_NEXT_ABI __m128i crc_adjust = _mm_set_epi16( 0, 0, 0, /* ignore non-length fields */ -rxq->crc_len, /* sub crc on data_len */ 0, /* ignore high-16bits of pkt_len */ -rxq->crc_len, /* sub crc on pkt_len */ 0, 0 /* ignore pkt_type field */ ); __m128i dd_check, eop_check; __m128i desc_mask = _mm_set_epi32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF07F0); #else __m128i crc_adjust = _mm_set_epi16( 0, 0, 0, 0, /* ignore non-length fields */ 0, /* ignore high-16bits of pkt_len */ -rxq->crc_len, /* sub crc on pkt_len */ -rxq->crc_len, /* sub crc on data_len */ 0 /* ignore pkt_type field */ ); __m128i dd_check, eop_check; #endif /* RTE_NEXT_ABI */ if (unlikely(nb_pkts < RTE_IXGBE_VPMD_RX_BURST)) return 0; /* Just the act of getting into the function from the application is * going to cost about 7 cycles */ rxdp = rxq->rx_ring + rxq->rx_tail; _mm_prefetch((const void *)rxdp, _MM_HINT_T0); /* See if we need to rearm the RX queue - gives the prefetch a bit * of time to act */ if (rxq->rxrearm_nb > RTE_IXGBE_RXQ_REARM_THRESH) ixgbe_rxq_rearm(rxq); /* Before we start moving massive data around, check to see if * there is actually a packet available */ if (!(rxdp->wb.upper.status_error & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))) return 0; /* 4 packets DD mask */ dd_check = _mm_set_epi64x(0x0000000100000001LL, 0x0000000100000001LL); /* 4 packets EOP mask */ eop_check = _mm_set_epi64x(0x0000000200000002LL, 0x0000000200000002LL); /* mask to shuffle from desc. to mbuf */ #ifdef RTE_NEXT_ABI shuf_msk = _mm_set_epi8( 7, 6, 5, 4, /* octet 4~7, 32bits rss */ 15, 14, /* octet 14~15, low 16 bits vlan_macip */ 13, 12, /* octet 12~13, 16 bits data_len */ 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */ 13, 12, /* octet 12~13, low 16 bits pkt_len */ 0xFF, 0xFF, /* skip high 16 bits pkt_type */ 1, /* octet 1, 8 bits pkt_type field */ 0 /* octet 0, 4 bits offset 4 pkt_type field */ ); #else shuf_msk = _mm_set_epi8( 7, 6, 5, 4, /* octet 4~7, 32bits rss */ 0xFF, 0xFF, /* skip high 16 bits vlan_macip, zero out */ 15, 14, /* octet 14~15, low 16 bits vlan_macip */ 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */ 13, 12, /* octet 12~13, low 16 bits pkt_len */ 13, 12, /* octet 12~13, 16 bits data_len */ 0xFF, 0xFF /* skip pkt_type field */ ); #endif /* RTE_NEXT_ABI */ /* Cache is empty -> need to scan the buffer rings, but first move * the next 'n' mbufs into the cache */ sw_ring = &rxq->sw_ring[rxq->rx_tail]; #ifdef RTE_NEXT_ABI /* A. load 4 packet in one loop * [A*. mask out 4 unused dirty field in desc] * B. copy 4 mbuf point from swring to rx_pkts * C. calc the number of DD bits among the 4 packets * [C*. extract the end-of-packet bit, if requested] * D. fill info. from desc to mbuf */ #else /* A. load 4 packet in one loop * B. copy 4 mbuf point from swring to rx_pkts * C. calc the number of DD bits among the 4 packets * [C*. extract the end-of-packet bit, if requested] * D. fill info. from desc to mbuf */ #endif /* RTE_NEXT_ABI */ for (pos = 0, nb_pkts_recd = 0; pos < RTE_IXGBE_VPMD_RX_BURST; pos += RTE_IXGBE_DESCS_PER_LOOP, rxdp += RTE_IXGBE_DESCS_PER_LOOP) { #ifdef RTE_NEXT_ABI __m128i descs0[RTE_IXGBE_DESCS_PER_LOOP]; #endif /* RTE_NEXT_ABI */ __m128i descs[RTE_IXGBE_DESCS_PER_LOOP]; __m128i pkt_mb1, pkt_mb2, pkt_mb3, pkt_mb4; __m128i zero, staterr, sterr_tmp1, sterr_tmp2; __m128i mbp1, mbp2; /* two mbuf pointer in one XMM reg. */ if (split_packet) { rte_prefetch0(&rx_pkts[pos]->cacheline1); rte_prefetch0(&rx_pkts[pos + 1]->cacheline1); rte_prefetch0(&rx_pkts[pos + 2]->cacheline1); rte_prefetch0(&rx_pkts[pos + 3]->cacheline1); } /* B.1 load 1 mbuf point */ mbp1 = _mm_loadu_si128((__m128i *)&sw_ring[pos]); #ifdef RTE_NEXT_ABI /* Read desc statuses backwards to avoid race condition */ /* A.1 load 4 pkts desc */ descs0[3] = _mm_loadu_si128((__m128i *)(rxdp + 3)); /* B.2 copy 2 mbuf point into rx_pkts */ _mm_storeu_si128((__m128i *)&rx_pkts[pos], mbp1); /* B.1 load 1 mbuf point */ mbp2 = _mm_loadu_si128((__m128i *)&sw_ring[pos+2]); descs0[2] = _mm_loadu_si128((__m128i *)(rxdp + 2)); /* B.1 load 2 mbuf point */ descs0[1] = _mm_loadu_si128((__m128i *)(rxdp + 1)); descs0[0] = _mm_loadu_si128((__m128i *)(rxdp)); /* B.2 copy 2 mbuf point into rx_pkts */ _mm_storeu_si128((__m128i *)&rx_pkts[pos+2], mbp2); /* A* mask out 0~3 bits RSS type */ descs[3] = _mm_and_si128(descs0[3], desc_mask); descs[2] = _mm_and_si128(descs0[2], desc_mask); /* A* mask out 0~3 bits RSS type */ descs[1] = _mm_and_si128(descs0[1], desc_mask); descs[0] = _mm_and_si128(descs0[0], desc_mask); #else /* Read desc statuses backwards to avoid race condition */ /* A.1 load 4 pkts desc */ descs[3] = _mm_loadu_si128((__m128i *)(rxdp + 3)); /* B.2 copy 2 mbuf point into rx_pkts */ _mm_storeu_si128((__m128i *)&rx_pkts[pos], mbp1); /* B.1 load 1 mbuf point */ mbp2 = _mm_loadu_si128((__m128i *)&sw_ring[pos + 2]); descs[2] = _mm_loadu_si128((__m128i *)(rxdp + 2)); /* B.1 load 2 mbuf point */ descs[1] = _mm_loadu_si128((__m128i *)(rxdp + 1)); descs[0] = _mm_loadu_si128((__m128i *)(rxdp)); /* B.2 copy 2 mbuf point into rx_pkts */ _mm_storeu_si128((__m128i *)&rx_pkts[pos + 2], mbp2); #endif /* RTE_NEXT_ABI */ /* avoid compiler reorder optimization */ rte_compiler_barrier(); /* D.1 pkt 3,4 convert format from desc to pktmbuf */ pkt_mb4 = _mm_shuffle_epi8(descs[3], shuf_msk); pkt_mb3 = _mm_shuffle_epi8(descs[2], shuf_msk); /* C.1 4=>2 filter staterr info only */ sterr_tmp2 = _mm_unpackhi_epi32(descs[3], descs[2]); /* C.1 4=>2 filter staterr info only */ sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]); #ifdef RTE_NEXT_ABI /* set ol_flags with vlan packet type */ desc_to_olflags_v(descs0, &rx_pkts[pos]); #else /* set ol_flags with packet type and vlan tag */ desc_to_olflags_v(descs, &rx_pkts[pos]); #endif /* RTE_NEXT_ABI */ /* D.2 pkt 3,4 set in_port/nb_seg and remove crc */ pkt_mb4 = _mm_add_epi16(pkt_mb4, crc_adjust); pkt_mb3 = _mm_add_epi16(pkt_mb3, crc_adjust); /* D.1 pkt 1,2 convert format from desc to pktmbuf */ pkt_mb2 = _mm_shuffle_epi8(descs[1], shuf_msk); pkt_mb1 = _mm_shuffle_epi8(descs[0], shuf_msk); /* C.2 get 4 pkts staterr value */ zero = _mm_xor_si128(dd_check, dd_check); staterr = _mm_unpacklo_epi32(sterr_tmp1, sterr_tmp2); /* D.3 copy final 3,4 data to rx_pkts */ _mm_storeu_si128((void *)&rx_pkts[pos+3]->rx_descriptor_fields1, pkt_mb4); _mm_storeu_si128((void *)&rx_pkts[pos+2]->rx_descriptor_fields1, pkt_mb3); /* D.2 pkt 1,2 set in_port/nb_seg and remove crc */ pkt_mb2 = _mm_add_epi16(pkt_mb2, crc_adjust); pkt_mb1 = _mm_add_epi16(pkt_mb1, crc_adjust); /* C* extract and record EOP bit */ if (split_packet) { __m128i eop_shuf_mask = _mm_set_epi8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x0C, 0x00, 0x08 ); /* and with mask to extract bits, flipping 1-0 */ __m128i eop_bits = _mm_andnot_si128(staterr, eop_check); /* the staterr values are not in order, as the count * count of dd bits doesn't care. However, for end of * packet tracking, we do care, so shuffle. This also * compresses the 32-bit values to 8-bit */ eop_bits = _mm_shuffle_epi8(eop_bits, eop_shuf_mask); /* store the resulting 32-bit value */ *(int *)split_packet = _mm_cvtsi128_si32(eop_bits); split_packet += RTE_IXGBE_DESCS_PER_LOOP; /* zero-out next pointers */ rx_pkts[pos]->next = NULL; rx_pkts[pos + 1]->next = NULL; rx_pkts[pos + 2]->next = NULL; rx_pkts[pos + 3]->next = NULL; } /* C.3 calc available number of desc */ staterr = _mm_and_si128(staterr, dd_check); staterr = _mm_packs_epi32(staterr, zero); /* D.3 copy final 1,2 data to rx_pkts */ _mm_storeu_si128((void *)&rx_pkts[pos+1]->rx_descriptor_fields1, pkt_mb2); _mm_storeu_si128((void *)&rx_pkts[pos]->rx_descriptor_fields1, pkt_mb1); /* C.4 calc avaialbe number of desc */ var = __builtin_popcountll(_mm_cvtsi128_si64(staterr)); nb_pkts_recd += var; if (likely(var != RTE_IXGBE_DESCS_PER_LOOP)) break; } /* Update our internal tail pointer */ rxq->rx_tail = (uint16_t)(rxq->rx_tail + nb_pkts_recd); rxq->rx_tail = (uint16_t)(rxq->rx_tail & (rxq->nb_rx_desc - 1)); rxq->rxrearm_nb = (uint16_t)(rxq->rxrearm_nb + nb_pkts_recd); return nb_pkts_recd; } /* * vPMD receive routine, now only accept (nb_pkts == RTE_IXGBE_VPMD_RX_BURST) * in one loop * * Notice: * - nb_pkts < RTE_IXGBE_VPMD_RX_BURST, just return no packet * - nb_pkts > RTE_IXGBE_VPMD_RX_BURST, only scan RTE_IXGBE_VPMD_RX_BURST * numbers of DD bit * - don't support ol_flags for rss and csum err */ uint16_t ixgbe_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL); } static inline uint16_t reassemble_packets(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_bufs, uint16_t nb_bufs, uint8_t *split_flags) { struct rte_mbuf *pkts[RTE_IXGBE_VPMD_RX_BURST]; /*finished pkts*/ struct rte_mbuf *start = rxq->pkt_first_seg; struct rte_mbuf *end = rxq->pkt_last_seg; unsigned pkt_idx, buf_idx; for (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) { if (end != NULL) { /* processing a split packet */ end->next = rx_bufs[buf_idx]; rx_bufs[buf_idx]->data_len += rxq->crc_len; start->nb_segs++; start->pkt_len += rx_bufs[buf_idx]->data_len; end = end->next; if (!split_flags[buf_idx]) { /* it's the last packet of the set */ start->hash = end->hash; start->ol_flags = end->ol_flags; /* we need to strip crc for the whole packet */ start->pkt_len -= rxq->crc_len; if (end->data_len > rxq->crc_len) end->data_len -= rxq->crc_len; else { /* free up last mbuf */ struct rte_mbuf *secondlast = start; start->nb_segs--; while (secondlast->next != end) secondlast = secondlast->next; secondlast->data_len -= (rxq->crc_len - end->data_len); secondlast->next = NULL; rte_pktmbuf_free_seg(end); end = secondlast; } pkts[pkt_idx++] = start; start = end = NULL; } } else { /* not processing a split packet */ if (!split_flags[buf_idx]) { /* not a split packet, save and skip */ pkts[pkt_idx++] = rx_bufs[buf_idx]; continue; } end = start = rx_bufs[buf_idx]; rx_bufs[buf_idx]->data_len += rxq->crc_len; rx_bufs[buf_idx]->pkt_len += rxq->crc_len; } } /* save the partial packet for next time */ rxq->pkt_first_seg = start; rxq->pkt_last_seg = end; memcpy(rx_bufs, pkts, pkt_idx * (sizeof(*pkts))); return pkt_idx; } /* * vPMD receive routine that reassembles scattered packets * * Notice: * - don't support ol_flags for rss and csum err * - now only accept (nb_pkts == RTE_IXGBE_VPMD_RX_BURST) */ uint16_t ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct ixgbe_rx_queue *rxq = rx_queue; uint8_t split_flags[RTE_IXGBE_VPMD_RX_BURST] = {0}; /* get some new buffers */ uint16_t nb_bufs = _recv_raw_pkts_vec(rxq, rx_pkts, nb_pkts, split_flags); if (nb_bufs == 0) return 0; /* happy day case, full burst + no packets to be joined */ const uint64_t *split_fl64 = (uint64_t *)split_flags; if (rxq->pkt_first_seg == NULL && split_fl64[0] == 0 && split_fl64[1] == 0 && split_fl64[2] == 0 && split_fl64[3] == 0) return nb_bufs; /* reassemble any packets that need reassembly*/ unsigned i = 0; if (rxq->pkt_first_seg == NULL) { /* find the first split flag, and only reassemble then*/ while (i < nb_bufs && !split_flags[i]) i++; if (i == nb_bufs) return nb_bufs; } return i + reassemble_packets(rxq, &rx_pkts[i], nb_bufs - i, &split_flags[i]); } static inline void vtx1(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf *pkt, uint64_t flags) { __m128i descriptor = _mm_set_epi64x((uint64_t)pkt->pkt_len << 46 | flags | pkt->data_len, pkt->buf_physaddr + pkt->data_off); _mm_store_si128((__m128i *)&txdp->read, descriptor); } static inline void vtx(volatile union ixgbe_adv_tx_desc *txdp, struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags) { int i; for (i = 0; i < nb_pkts; ++i, ++txdp, ++pkt) vtx1(txdp, *pkt, flags); } static inline int __attribute__((always_inline)) ixgbe_tx_free_bufs(struct ixgbe_tx_queue *txq) { struct ixgbe_tx_entry_v *txep; uint32_t status; uint32_t n; uint32_t i; int nb_free = 0; struct rte_mbuf *m, *free[RTE_IXGBE_TX_MAX_FREE_BUF_SZ]; /* check DD bit on threshold descriptor */ status = txq->tx_ring[txq->tx_next_dd].wb.status; if (!(status & IXGBE_ADVTXD_STAT_DD)) return 0; n = txq->tx_rs_thresh; /* * first buffer to free from S/W ring is at index * tx_next_dd - (tx_rs_thresh-1) */ txep = &txq->sw_ring_v[txq->tx_next_dd - (n - 1)]; m = __rte_pktmbuf_prefree_seg(txep[0].mbuf); if (likely(m != NULL)) { free[0] = m; nb_free = 1; for (i = 1; i < n; i++) { m = __rte_pktmbuf_prefree_seg(txep[i].mbuf); if (likely(m != NULL)) { if (likely(m->pool == free[0]->pool)) free[nb_free++] = m; else { rte_mempool_put_bulk(free[0]->pool, (void *)free, nb_free); free[0] = m; nb_free = 1; } } } rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); } else { for (i = 1; i < n; i++) { m = __rte_pktmbuf_prefree_seg(txep[i].mbuf); if (m != NULL) rte_mempool_put(m->pool, m); } } /* buffers were freed, update counters */ txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh); txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh); if (txq->tx_next_dd >= txq->nb_tx_desc) txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); return txq->tx_rs_thresh; } static inline void __attribute__((always_inline)) tx_backlog_entry(struct ixgbe_tx_entry_v *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { int i; for (i = 0; i < (int)nb_pkts; ++i) txep[i].mbuf = tx_pkts[i]; } uint16_t ixgbe_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct ixgbe_tx_queue *txq = (struct ixgbe_tx_queue *)tx_queue; volatile union ixgbe_adv_tx_desc *txdp; struct ixgbe_tx_entry_v *txep; uint16_t n, nb_commit, tx_id; uint64_t flags = DCMD_DTYP_FLAGS; uint64_t rs = IXGBE_ADVTXD_DCMD_RS|DCMD_DTYP_FLAGS; int i; if (unlikely(nb_pkts > RTE_IXGBE_VPMD_TX_BURST)) nb_pkts = RTE_IXGBE_VPMD_TX_BURST; if (txq->nb_tx_free < txq->tx_free_thresh) ixgbe_tx_free_bufs(txq); nb_commit = nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts); if (unlikely(nb_pkts == 0)) return 0; tx_id = txq->tx_tail; txdp = &txq->tx_ring[tx_id]; txep = &txq->sw_ring_v[tx_id]; txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts); n = (uint16_t)(txq->nb_tx_desc - tx_id); if (nb_commit >= n) { tx_backlog_entry(txep, tx_pkts, n); for (i = 0; i < n - 1; ++i, ++tx_pkts, ++txdp) vtx1(txdp, *tx_pkts, flags); vtx1(txdp, *tx_pkts++, rs); nb_commit = (uint16_t)(nb_commit - n); tx_id = 0; txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); /* avoid reach the end of ring */ txdp = &(txq->tx_ring[tx_id]); txep = &txq->sw_ring_v[tx_id]; } tx_backlog_entry(txep, tx_pkts, nb_commit); vtx(txdp, tx_pkts, nb_commit, flags); tx_id = (uint16_t)(tx_id + nb_commit); if (tx_id > txq->tx_next_rs) { txq->tx_ring[txq->tx_next_rs].read.cmd_type_len |= rte_cpu_to_le_32(IXGBE_ADVTXD_DCMD_RS); txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh); } txq->tx_tail = tx_id; IXGBE_PCI_REG_WRITE(txq->tdt_reg_addr, txq->tx_tail); return nb_pkts; } static void __attribute__((cold)) ixgbe_tx_queue_release_mbufs_vec(struct ixgbe_tx_queue *txq) { unsigned i; struct ixgbe_tx_entry_v *txe; const uint16_t max_desc = (uint16_t)(txq->nb_tx_desc - 1); if (txq->sw_ring == NULL || txq->nb_tx_free == max_desc) return; /* release the used mbufs in sw_ring */ for (i = txq->tx_next_dd - (txq->tx_rs_thresh - 1); i != txq->tx_tail; i = (i + 1) & max_desc) { txe = &txq->sw_ring_v[i]; rte_pktmbuf_free_seg(txe->mbuf); } txq->nb_tx_free = max_desc; /* reset tx_entry */ for (i = 0; i < txq->nb_tx_desc; i++) { txe = &txq->sw_ring_v[i]; txe->mbuf = NULL; } } void __attribute__((cold)) ixgbe_rx_queue_release_mbufs_vec(struct ixgbe_rx_queue *rxq) { const unsigned mask = rxq->nb_rx_desc - 1; unsigned i; if (rxq->sw_ring == NULL || rxq->rxrearm_nb >= rxq->nb_rx_desc) return; /* free all mbufs that are valid in the ring */ for (i = rxq->rx_tail; i != rxq->rxrearm_start; i = (i + 1) & mask) rte_pktmbuf_free_seg(rxq->sw_ring[i].mbuf); rxq->rxrearm_nb = rxq->nb_rx_desc; /* set all entries to NULL */ memset(rxq->sw_ring, 0, sizeof(rxq->sw_ring[0]) * rxq->nb_rx_desc); } static void __attribute__((cold)) ixgbe_tx_free_swring(struct ixgbe_tx_queue *txq) { if (txq == NULL) return; if (txq->sw_ring != NULL) { rte_free(txq->sw_ring_v - 1); txq->sw_ring_v = NULL; } } static void __attribute__((cold)) ixgbe_reset_tx_queue(struct ixgbe_tx_queue *txq) { static const union ixgbe_adv_tx_desc zeroed_desc = {{0}}; struct ixgbe_tx_entry_v *txe = txq->sw_ring_v; uint16_t i; /* Zero out HW ring memory */ for (i = 0; i < txq->nb_tx_desc; i++) txq->tx_ring[i] = zeroed_desc; /* Initialize SW ring entries */ for (i = 0; i < txq->nb_tx_desc; i++) { volatile union ixgbe_adv_tx_desc *txd = &txq->tx_ring[i]; txd->wb.status = IXGBE_TXD_STAT_DD; txe[i].mbuf = NULL; } txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1); txq->tx_tail = 0; txq->nb_tx_used = 0; /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition */ txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); txq->ctx_curr = 0; memset((void *)&txq->ctx_cache, 0, IXGBE_CTX_NUM * sizeof(struct ixgbe_advctx_info)); } static const struct ixgbe_txq_ops vec_txq_ops = { .release_mbufs = ixgbe_tx_queue_release_mbufs_vec, .free_swring = ixgbe_tx_free_swring, .reset = ixgbe_reset_tx_queue, }; int __attribute__((cold)) ixgbe_rxq_vec_setup(struct ixgbe_rx_queue *rxq) { uintptr_t p; struct rte_mbuf mb_def = { .buf_addr = 0 }; /* zeroed mbuf */ mb_def.nb_segs = 1; mb_def.data_off = RTE_PKTMBUF_HEADROOM; mb_def.port = rxq->port_id; rte_mbuf_refcnt_set(&mb_def, 1); /* prevent compiler reordering: rearm_data covers previous fields */ rte_compiler_barrier(); p = (uintptr_t)&mb_def.rearm_data; rxq->mbuf_initializer = *(uint64_t *)p; return 0; } int __attribute__((cold)) ixgbe_txq_vec_setup(struct ixgbe_tx_queue *txq) { if (txq->sw_ring_v == NULL) return -1; /* leave the first one for overflow */ txq->sw_ring_v = txq->sw_ring_v + 1; txq->ops = &vec_txq_ops; return 0; } int __attribute__((cold)) ixgbe_rx_vec_dev_conf_condition_check(struct rte_eth_dev *dev) { #ifndef RTE_LIBRTE_IEEE1588 struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf; #ifndef RTE_IXGBE_RX_OLFLAGS_ENABLE /* whithout rx ol_flags, no VP flag report */ if (rxmode->hw_vlan_strip != 0 || rxmode->hw_vlan_extend != 0) return -1; #endif /* no fdir support */ if (fconf->mode != RTE_FDIR_MODE_NONE) return -1; /* * - no csum error report support * - no header split support */ if (rxmode->hw_ip_checksum == 1 || rxmode->header_split == 1) return -1; return 0; #else RTE_SET_USED(dev); return -1; #endif } ================================================ FILE: drivers/net/mlx4/Makefile ================================================ # BSD LICENSE # # Copyright 2012-2015 6WIND S.A. # Copyright 2012 Mellanox. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS)$(CONFIG_RTE_BUILD_SHARED_LIB),yy) all: @echo 'MLX4: Not supported in a combined shared library' @false endif # Library name. LIB = librte_pmd_mlx4.a # Sources. SRCS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4.c # Dependencies. DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += lib/librte_mempool # Basic CFLAGS. CFLAGS += -O3 CFLAGS += -std=gnu99 -Wall -Wextra CFLAGS += -g CFLAGS += -I. CFLAGS += -D_XOPEN_SOURCE=600 CFLAGS += $(WERROR_FLAGS) LDLIBS += -libverbs # A few warnings cannot be avoided in external headers. CFLAGS += -Wno-error=cast-qual EXPORT_MAP := rte_pmd_mlx4_version.map LIBABIVER := 1 # DEBUG which is usually provided on the command-line may enable # CONFIG_RTE_LIBRTE_MLX4_DEBUG. ifeq ($(DEBUG),1) CONFIG_RTE_LIBRTE_MLX4_DEBUG := y endif # User-defined CFLAGS. ifeq ($(CONFIG_RTE_LIBRTE_MLX4_DEBUG),y) CFLAGS += -pedantic -UNDEBUG -DPEDANTIC else CFLAGS += -DNDEBUG -UPEDANTIC endif ifdef CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N CFLAGS += -DMLX4_PMD_SGE_WR_N=$(CONFIG_RTE_LIBRTE_MLX4_SGE_WR_N) endif ifdef CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE CFLAGS += -DMLX4_PMD_MAX_INLINE=$(CONFIG_RTE_LIBRTE_MLX4_MAX_INLINE) endif ifdef CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE CFLAGS += -DMLX4_PMD_TX_MP_CACHE=$(CONFIG_RTE_LIBRTE_MLX4_TX_MP_CACHE) endif ifdef CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS CFLAGS += -DMLX4_PMD_SOFT_COUNTERS=$(CONFIG_RTE_LIBRTE_MLX4_SOFT_COUNTERS) endif include $(RTE_SDK)/mk/rte.lib.mk # Generate and clean-up mlx4_autoconf.h. export CC CFLAGS CPPFLAGS EXTRA_CFLAGS EXTRA_CPPFLAGS export AUTO_CONFIG_CFLAGS = -Wno-error ifndef V AUTOCONF_OUTPUT := >/dev/null endif mlx4_autoconf.h: $(RTE_SDK)/scripts/auto-config-h.sh $Q $(RM) -f -- '$@' $Q sh -- '$<' '$@' \ RSS_SUPPORT \ infiniband/verbs.h \ enum IBV_EXP_DEVICE_UD_RSS $(AUTOCONF_OUTPUT) $Q sh -- '$<' '$@' \ INLINE_RECV \ infiniband/verbs.h \ enum IBV_EXP_DEVICE_ATTR_INLINE_RECV_SZ $(AUTOCONF_OUTPUT) $Q sh -- '$<' '$@' \ HAVE_EXP_QUERY_DEVICE \ infiniband/verbs.h \ type 'struct ibv_exp_device_attr' $(AUTOCONF_OUTPUT) $Q sh -- '$<' '$@' \ HAVE_EXP_QP_BURST_CREATE_DISABLE_ETH_LOOPBACK \ infiniband/verbs.h \ enum IBV_EXP_QP_BURST_CREATE_DISABLE_ETH_LOOPBACK \ $(AUTOCONF_OUTPUT) mlx4.o: mlx4_autoconf.h clean_mlx4: FORCE $Q rm -f -- mlx4_autoconf.h clean: clean_mlx4 ================================================ FILE: drivers/net/mlx4/mlx4.c ================================================ /*- * BSD LICENSE * * Copyright 2012-2015 6WIND S.A. * Copyright 2012 Mellanox. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Known limitations: * - RSS hash key and options cannot be modified. * - Hardware counters aren't implemented. */ /* System headers. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ #ifdef PEDANTIC #pragma GCC diagnostic ignored "-pedantic" #endif #include #ifdef PEDANTIC #pragma GCC diagnostic error "-pedantic" #endif /* DPDK headers don't like -pedantic. */ #ifdef PEDANTIC #pragma GCC diagnostic ignored "-pedantic" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PEDANTIC #pragma GCC diagnostic error "-pedantic" #endif /* Generated configuration header. */ #include "mlx4_autoconf.h" /* PMD header. */ #include "mlx4.h" /* Runtime logging through RTE_LOG() is enabled when not in debugging mode. * Intermediate LOG_*() macros add the required end-of-line characters. */ #ifndef NDEBUG #define INFO(...) DEBUG(__VA_ARGS__) #define WARN(...) DEBUG(__VA_ARGS__) #define ERROR(...) DEBUG(__VA_ARGS__) #else #define LOG__(level, m, ...) \ RTE_LOG(level, PMD, MLX4_DRIVER_NAME ": " m "%c", __VA_ARGS__) #define LOG_(level, ...) LOG__(level, __VA_ARGS__, '\n') #define INFO(...) LOG_(INFO, __VA_ARGS__) #define WARN(...) LOG_(WARNING, __VA_ARGS__) #define ERROR(...) LOG_(ERR, __VA_ARGS__) #endif /* Convenience macros for accessing mbuf fields. */ #define NEXT(m) ((m)->next) #define DATA_LEN(m) ((m)->data_len) #define PKT_LEN(m) ((m)->pkt_len) #define DATA_OFF(m) ((m)->data_off) #define SET_DATA_OFF(m, o) ((m)->data_off = (o)) #define NB_SEGS(m) ((m)->nb_segs) #define PORT(m) ((m)->port) /* Work Request ID data type (64 bit). */ typedef union { struct { uint32_t id; uint16_t offset; } data; uint64_t raw; } wr_id_t; #define WR_ID(o) (((wr_id_t *)&(o))->data) /* Compile-time check. */ static inline void wr_id_t_check(void) { wr_id_t check[1 + (2 * -!(sizeof(wr_id_t) == sizeof(uint64_t)))]; (void)check; (void)wr_id_t_check; } /* Transpose flags. Useful to convert IBV to DPDK flags. */ #define TRANSPOSE(val, from, to) \ (((from) >= (to)) ? \ (((val) & (from)) / ((from) / (to))) : \ (((val) & (from)) * ((to) / (from)))) struct mlx4_rxq_stats { unsigned int idx; /**< Mapping index. */ #ifdef MLX4_PMD_SOFT_COUNTERS uint64_t ipackets; /**< Total of successfully received packets. */ uint64_t ibytes; /**< Total of successfully received bytes. */ #endif uint64_t idropped; /**< Total of packets dropped when RX ring full. */ uint64_t rx_nombuf; /**< Total of RX mbuf allocation failures. */ }; struct mlx4_txq_stats { unsigned int idx; /**< Mapping index. */ #ifdef MLX4_PMD_SOFT_COUNTERS uint64_t opackets; /**< Total of successfully sent packets. */ uint64_t obytes; /**< Total of successfully sent bytes. */ #endif uint64_t odropped; /**< Total of packets not sent when TX ring full. */ }; /* RX element (scattered packets). */ struct rxq_elt_sp { struct ibv_recv_wr wr; /* Work Request. */ struct ibv_sge sges[MLX4_PMD_SGE_WR_N]; /* Scatter/Gather Elements. */ struct rte_mbuf *bufs[MLX4_PMD_SGE_WR_N]; /* SGEs buffers. */ }; /* RX element. */ struct rxq_elt { struct ibv_recv_wr wr; /* Work Request. */ struct ibv_sge sge; /* Scatter/Gather Element. */ /* mbuf pointer is derived from WR_ID(wr.wr_id).offset. */ }; /* RX queue descriptor. */ struct rxq { struct priv *priv; /* Back pointer to private data. */ struct rte_mempool *mp; /* Memory Pool for allocations. */ struct ibv_mr *mr; /* Memory Region (for mp). */ struct ibv_cq *cq; /* Completion Queue. */ struct ibv_qp *qp; /* Queue Pair. */ struct ibv_exp_qp_burst_family *if_qp; /* QP burst interface. */ struct ibv_exp_cq_family *if_cq; /* CQ interface. */ /* * Each VLAN ID requires a separate flow steering rule. */ BITFIELD_DECLARE(mac_configured, uint32_t, MLX4_MAX_MAC_ADDRESSES); struct ibv_flow *mac_flow[MLX4_MAX_MAC_ADDRESSES][MLX4_MAX_VLAN_IDS]; struct ibv_flow *promisc_flow; /* Promiscuous flow. */ struct ibv_flow *allmulti_flow; /* Multicast flow. */ unsigned int port_id; /* Port ID for incoming packets. */ unsigned int elts_n; /* (*elts)[] length. */ unsigned int elts_head; /* Current index in (*elts)[]. */ union { struct rxq_elt_sp (*sp)[]; /* Scattered RX elements. */ struct rxq_elt (*no_sp)[]; /* RX elements. */ } elts; unsigned int sp:1; /* Use scattered RX elements. */ unsigned int csum:1; /* Enable checksum offloading. */ unsigned int csum_l2tun:1; /* Same for L2 tunnels. */ uint32_t mb_len; /* Length of a mp-issued mbuf. */ struct mlx4_rxq_stats stats; /* RX queue counters. */ unsigned int socket; /* CPU socket ID for allocations. */ struct ibv_exp_res_domain *rd; /* Resource Domain. */ }; /* TX element. */ struct txq_elt { struct rte_mbuf *buf; }; /* Linear buffer type. It is used when transmitting buffers with too many * segments that do not fit the hardware queue (see max_send_sge). * Extra segments are copied (linearized) in such buffers, replacing the * last SGE during TX. * The size is arbitrary but large enough to hold a jumbo frame with * 8 segments considering mbuf.buf_len is about 2048 bytes. */ typedef uint8_t linear_t[16384]; /* TX queue descriptor. */ struct txq { struct priv *priv; /* Back pointer to private data. */ struct { struct rte_mempool *mp; /* Cached Memory Pool. */ struct ibv_mr *mr; /* Memory Region (for mp). */ uint32_t lkey; /* mr->lkey */ } mp2mr[MLX4_PMD_TX_MP_CACHE]; /* MP to MR translation table. */ struct ibv_cq *cq; /* Completion Queue. */ struct ibv_qp *qp; /* Queue Pair. */ struct ibv_exp_qp_burst_family *if_qp; /* QP burst interface. */ struct ibv_exp_cq_family *if_cq; /* CQ interface. */ #if MLX4_PMD_MAX_INLINE > 0 uint32_t max_inline; /* Max inline send size <= MLX4_PMD_MAX_INLINE. */ #endif unsigned int elts_n; /* (*elts)[] length. */ struct txq_elt (*elts)[]; /* TX elements. */ unsigned int elts_head; /* Current index in (*elts)[]. */ unsigned int elts_tail; /* First element awaiting completion. */ unsigned int elts_comp; /* Number of completion requests. */ unsigned int elts_comp_cd; /* Countdown for next completion request. */ unsigned int elts_comp_cd_init; /* Initial value for countdown. */ struct mlx4_txq_stats stats; /* TX queue counters. */ linear_t (*elts_linear)[]; /* Linearized buffers. */ struct ibv_mr *mr_linear; /* Memory Region for linearized buffers. */ unsigned int socket; /* CPU socket ID for allocations. */ struct ibv_exp_res_domain *rd; /* Resource Domain. */ }; struct priv { struct rte_eth_dev *dev; /* Ethernet device. */ struct ibv_context *ctx; /* Verbs context. */ struct ibv_device_attr device_attr; /* Device properties. */ struct ibv_pd *pd; /* Protection Domain. */ /* * MAC addresses array and configuration bit-field. * An extra entry that cannot be modified by the DPDK is reserved * for broadcast frames (destination MAC address ff:ff:ff:ff:ff:ff). */ struct ether_addr mac[MLX4_MAX_MAC_ADDRESSES]; BITFIELD_DECLARE(mac_configured, uint32_t, MLX4_MAX_MAC_ADDRESSES); /* VLAN filters. */ struct { unsigned int enabled:1; /* If enabled. */ unsigned int id:12; /* VLAN ID (0-4095). */ } vlan_filter[MLX4_MAX_VLAN_IDS]; /* VLAN filters table. */ /* Device properties. */ uint16_t mtu; /* Configured MTU. */ uint8_t port; /* Physical port number. */ unsigned int started:1; /* Device started, flows enabled. */ unsigned int promisc:1; /* Device in promiscuous mode. */ unsigned int allmulti:1; /* Device receives all multicast packets. */ unsigned int hw_qpg:1; /* QP groups are supported. */ unsigned int hw_tss:1; /* TSS is supported. */ unsigned int hw_rss:1; /* RSS is supported. */ unsigned int hw_csum:1; /* Checksum offload is supported. */ unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */ unsigned int rss:1; /* RSS is enabled. */ unsigned int vf:1; /* This is a VF device. */ #ifdef INLINE_RECV unsigned int inl_recv_size; /* Inline recv size */ #endif unsigned int max_rss_tbl_sz; /* Maximum number of RSS queues. */ /* RX/TX queues. */ struct rxq rxq_parent; /* Parent queue when RSS is enabled. */ unsigned int rxqs_n; /* RX queues array size. */ unsigned int txqs_n; /* TX queues array size. */ struct rxq *(*rxqs)[]; /* RX queues. */ struct txq *(*txqs)[]; /* TX queues. */ rte_spinlock_t lock; /* Lock for control functions. */ }; /** * Lock private structure to protect it from concurrent access in the * control path. * * @param priv * Pointer to private structure. */ static void priv_lock(struct priv *priv) { rte_spinlock_lock(&priv->lock); } /** * Unlock private structure. * * @param priv * Pointer to private structure. */ static void priv_unlock(struct priv *priv) { rte_spinlock_unlock(&priv->lock); } /* Allocate a buffer on the stack and fill it with a printf format string. */ #define MKSTR(name, ...) \ char name[snprintf(NULL, 0, __VA_ARGS__) + 1]; \ \ snprintf(name, sizeof(name), __VA_ARGS__) /** * Get interface name from private structure. * * @param[in] priv * Pointer to private structure. * @param[out] ifname * Interface name output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_get_ifname(const struct priv *priv, char (*ifname)[IF_NAMESIZE]) { DIR *dir; struct dirent *dent; unsigned int dev_type = 0; unsigned int dev_port_prev = ~0u; char match[IF_NAMESIZE] = ""; { MKSTR(path, "%s/device/net", priv->ctx->device->ibdev_path); dir = opendir(path); if (dir == NULL) return -1; } while ((dent = readdir(dir)) != NULL) { char *name = dent->d_name; FILE *file; unsigned int dev_port; int r; if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) continue; MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path, name, (dev_type ? "dev_id" : "dev_port")); file = fopen(path, "rb"); if (file == NULL) { if (errno != ENOENT) continue; /* * Switch to dev_id when dev_port does not exist as * is the case with Linux kernel versions < 3.15. */ try_dev_id: match[0] = '\0'; if (dev_type) break; dev_type = 1; dev_port_prev = ~0u; rewinddir(dir); continue; } r = fscanf(file, (dev_type ? "%x" : "%u"), &dev_port); fclose(file); if (r != 1) continue; /* * Switch to dev_id when dev_port returns the same value for * all ports. May happen when using a MOFED release older than * 3.0 with a Linux kernel >= 3.15. */ if (dev_port == dev_port_prev) goto try_dev_id; dev_port_prev = dev_port; if (dev_port == (priv->port - 1u)) snprintf(match, sizeof(match), "%s", name); } closedir(dir); if (match[0] == '\0') return -1; strncpy(*ifname, match, sizeof(*ifname)); return 0; } /** * Read from sysfs entry. * * @param[in] priv * Pointer to private structure. * @param[in] entry * Entry name relative to sysfs path. * @param[out] buf * Data output buffer. * @param size * Buffer size. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_sysfs_read(const struct priv *priv, const char *entry, char *buf, size_t size) { char ifname[IF_NAMESIZE]; FILE *file; int ret; int err; if (priv_get_ifname(priv, &ifname)) return -1; MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path, ifname, entry); file = fopen(path, "rb"); if (file == NULL) return -1; ret = fread(buf, 1, size, file); err = errno; if (((size_t)ret < size) && (ferror(file))) ret = -1; else ret = size; fclose(file); errno = err; return ret; } /** * Write to sysfs entry. * * @param[in] priv * Pointer to private structure. * @param[in] entry * Entry name relative to sysfs path. * @param[in] buf * Data buffer. * @param size * Buffer size. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_sysfs_write(const struct priv *priv, const char *entry, char *buf, size_t size) { char ifname[IF_NAMESIZE]; FILE *file; int ret; int err; if (priv_get_ifname(priv, &ifname)) return -1; MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path, ifname, entry); file = fopen(path, "wb"); if (file == NULL) return -1; ret = fwrite(buf, 1, size, file); err = errno; if (((size_t)ret < size) || (ferror(file))) ret = -1; else ret = size; fclose(file); errno = err; return ret; } /** * Get unsigned long sysfs property. * * @param priv * Pointer to private structure. * @param[in] name * Entry name relative to sysfs path. * @param[out] value * Value output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value) { int ret; unsigned long value_ret; char value_str[32]; ret = priv_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1)); if (ret == -1) { DEBUG("cannot read %s value from sysfs: %s", name, strerror(errno)); return -1; } value_str[ret] = '\0'; errno = 0; value_ret = strtoul(value_str, NULL, 0); if (errno) { DEBUG("invalid %s value `%s': %s", name, value_str, strerror(errno)); return -1; } *value = value_ret; return 0; } /** * Set unsigned long sysfs property. * * @param priv * Pointer to private structure. * @param[in] name * Entry name relative to sysfs path. * @param value * Value to set. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value) { int ret; MKSTR(value_str, "%lu", value); ret = priv_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1)); if (ret == -1) { DEBUG("cannot write %s `%s' (%lu) to sysfs: %s", name, value_str, value, strerror(errno)); return -1; } return 0; } /** * Perform ifreq ioctl() on associated Ethernet device. * * @param[in] priv * Pointer to private structure. * @param req * Request number to pass to ioctl(). * @param[out] ifr * Interface request structure output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_ifreq(const struct priv *priv, int req, struct ifreq *ifr) { int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); int ret = -1; if (sock == -1) return ret; if (priv_get_ifname(priv, &ifr->ifr_name) == 0) ret = ioctl(sock, req, ifr); close(sock); return ret; } /** * Get device MTU. * * @param priv * Pointer to private structure. * @param[out] mtu * MTU value output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_get_mtu(struct priv *priv, uint16_t *mtu) { unsigned long ulong_mtu; if (priv_get_sysfs_ulong(priv, "mtu", &ulong_mtu) == -1) return -1; *mtu = ulong_mtu; return 0; } /** * Set device MTU. * * @param priv * Pointer to private structure. * @param mtu * MTU value to set. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_set_mtu(struct priv *priv, uint16_t mtu) { return priv_set_sysfs_ulong(priv, "mtu", mtu); } /** * Set device flags. * * @param priv * Pointer to private structure. * @param keep * Bitmask for flags that must remain untouched. * @param flags * Bitmask for flags to modify. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags) { unsigned long tmp; if (priv_get_sysfs_ulong(priv, "flags", &tmp) == -1) return -1; tmp &= keep; tmp |= flags; return priv_set_sysfs_ulong(priv, "flags", tmp); } /* Device configuration. */ static int rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, unsigned int socket, const struct rte_eth_rxconf *conf, struct rte_mempool *mp); static void rxq_cleanup(struct rxq *rxq); /** * Ethernet device configuration. * * Prepare the driver for a given number of TX and RX queues. * Allocate parent RSS queue when several RX queues are requested. * * @param dev * Pointer to Ethernet device structure. * * @return * 0 on success, errno value on failure. */ static int dev_configure(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int rxqs_n = dev->data->nb_rx_queues; unsigned int txqs_n = dev->data->nb_tx_queues; unsigned int tmp; int ret; priv->rxqs = (void *)dev->data->rx_queues; priv->txqs = (void *)dev->data->tx_queues; if (txqs_n != priv->txqs_n) { INFO("%p: TX queues number update: %u -> %u", (void *)dev, priv->txqs_n, txqs_n); priv->txqs_n = txqs_n; } if (rxqs_n == priv->rxqs_n) return 0; INFO("%p: RX queues number update: %u -> %u", (void *)dev, priv->rxqs_n, rxqs_n); /* If RSS is enabled, disable it first. */ if (priv->rss) { unsigned int i; /* Only if there are no remaining child RX queues. */ for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] != NULL) return EINVAL; rxq_cleanup(&priv->rxq_parent); priv->rss = 0; priv->rxqs_n = 0; } if (rxqs_n <= 1) { /* Nothing else to do. */ priv->rxqs_n = rxqs_n; return 0; } /* Allocate a new RSS parent queue if supported by hardware. */ if (!priv->hw_rss) { ERROR("%p: only a single RX queue can be configured when" " hardware doesn't support RSS", (void *)dev); return EINVAL; } /* Fail if hardware doesn't support that many RSS queues. */ if (rxqs_n >= priv->max_rss_tbl_sz) { ERROR("%p: only %u RX queues can be configured for RSS", (void *)dev, priv->max_rss_tbl_sz); return EINVAL; } priv->rss = 1; tmp = priv->rxqs_n; priv->rxqs_n = rxqs_n; ret = rxq_setup(dev, &priv->rxq_parent, 0, 0, NULL, NULL); if (!ret) return 0; /* Failure, rollback. */ priv->rss = 0; priv->rxqs_n = tmp; assert(ret > 0); return ret; } /** * DPDK callback for Ethernet device configuration. * * @param dev * Pointer to Ethernet device structure. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_dev_configure(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; int ret; priv_lock(priv); ret = dev_configure(dev); assert(ret >= 0); priv_unlock(priv); return -ret; } /* TX queues handling. */ /** * Allocate TX queue elements. * * @param txq * Pointer to TX queue structure. * @param elts_n * Number of elements to allocate. * * @return * 0 on success, errno value on failure. */ static int txq_alloc_elts(struct txq *txq, unsigned int elts_n) { unsigned int i; struct txq_elt (*elts)[elts_n] = rte_calloc_socket("TXQ", 1, sizeof(*elts), 0, txq->socket); linear_t (*elts_linear)[elts_n] = rte_calloc_socket("TXQ", 1, sizeof(*elts_linear), 0, txq->socket); struct ibv_mr *mr_linear = NULL; int ret = 0; if ((elts == NULL) || (elts_linear == NULL)) { ERROR("%p: can't allocate packets array", (void *)txq); ret = ENOMEM; goto error; } mr_linear = ibv_reg_mr(txq->priv->pd, elts_linear, sizeof(*elts_linear), (IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE)); if (mr_linear == NULL) { ERROR("%p: unable to configure MR, ibv_reg_mr() failed", (void *)txq); ret = EINVAL; goto error; } for (i = 0; (i != elts_n); ++i) { struct txq_elt *elt = &(*elts)[i]; elt->buf = NULL; } DEBUG("%p: allocated and configured %u WRs", (void *)txq, elts_n); txq->elts_n = elts_n; txq->elts = elts; txq->elts_head = 0; txq->elts_tail = 0; txq->elts_comp = 0; /* Request send completion every MLX4_PMD_TX_PER_COMP_REQ packets or * at least 4 times per ring. */ txq->elts_comp_cd_init = ((MLX4_PMD_TX_PER_COMP_REQ < (elts_n / 4)) ? MLX4_PMD_TX_PER_COMP_REQ : (elts_n / 4)); txq->elts_comp_cd = txq->elts_comp_cd_init; txq->elts_linear = elts_linear; txq->mr_linear = mr_linear; assert(ret == 0); return 0; error: if (mr_linear != NULL) claim_zero(ibv_dereg_mr(mr_linear)); rte_free(elts_linear); rte_free(elts); DEBUG("%p: failed, freed everything", (void *)txq); assert(ret > 0); return ret; } /** * Free TX queue elements. * * @param txq * Pointer to TX queue structure. */ static void txq_free_elts(struct txq *txq) { unsigned int i; unsigned int elts_n = txq->elts_n; struct txq_elt (*elts)[elts_n] = txq->elts; linear_t (*elts_linear)[elts_n] = txq->elts_linear; struct ibv_mr *mr_linear = txq->mr_linear; DEBUG("%p: freeing WRs", (void *)txq); txq->elts_n = 0; txq->elts = NULL; txq->elts_linear = NULL; txq->mr_linear = NULL; if (mr_linear != NULL) claim_zero(ibv_dereg_mr(mr_linear)); rte_free(elts_linear); if (elts == NULL) return; for (i = 0; (i != elemof(*elts)); ++i) { struct txq_elt *elt = &(*elts)[i]; if (elt->buf == NULL) continue; rte_pktmbuf_free(elt->buf); } rte_free(elts); } /** * Clean up a TX queue. * * Destroy objects, free allocated memory and reset the structure for reuse. * * @param txq * Pointer to TX queue structure. */ static void txq_cleanup(struct txq *txq) { struct ibv_exp_release_intf_params params; size_t i; DEBUG("cleaning up %p", (void *)txq); txq_free_elts(txq); if (txq->if_qp != NULL) { assert(txq->priv != NULL); assert(txq->priv->ctx != NULL); assert(txq->qp != NULL); params = (struct ibv_exp_release_intf_params){ .comp_mask = 0, }; claim_zero(ibv_exp_release_intf(txq->priv->ctx, txq->if_qp, ¶ms)); } if (txq->if_cq != NULL) { assert(txq->priv != NULL); assert(txq->priv->ctx != NULL); assert(txq->cq != NULL); params = (struct ibv_exp_release_intf_params){ .comp_mask = 0, }; claim_zero(ibv_exp_release_intf(txq->priv->ctx, txq->if_cq, ¶ms)); } if (txq->qp != NULL) claim_zero(ibv_destroy_qp(txq->qp)); if (txq->cq != NULL) claim_zero(ibv_destroy_cq(txq->cq)); if (txq->rd != NULL) { struct ibv_exp_destroy_res_domain_attr attr = { .comp_mask = 0, }; assert(txq->priv != NULL); assert(txq->priv->ctx != NULL); claim_zero(ibv_exp_destroy_res_domain(txq->priv->ctx, txq->rd, &attr)); } for (i = 0; (i != elemof(txq->mp2mr)); ++i) { if (txq->mp2mr[i].mp == NULL) break; assert(txq->mp2mr[i].mr != NULL); claim_zero(ibv_dereg_mr(txq->mp2mr[i].mr)); } memset(txq, 0, sizeof(*txq)); } /** * Manage TX completions. * * When sending a burst, mlx4_tx_burst() posts several WRs. * To improve performance, a completion event is only required once every * MLX4_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information * for other WRs, but this information would not be used anyway. * * @param txq * Pointer to TX queue structure. * * @return * 0 on success, -1 on failure. */ static int txq_complete(struct txq *txq) { unsigned int elts_comp = txq->elts_comp; unsigned int elts_tail = txq->elts_tail; const unsigned int elts_n = txq->elts_n; int wcs_n; if (unlikely(elts_comp == 0)) return 0; #ifdef DEBUG_SEND DEBUG("%p: processing %u work requests completions", (void *)txq, elts_comp); #endif wcs_n = txq->if_cq->poll_cnt(txq->cq, elts_comp); if (unlikely(wcs_n == 0)) return 0; if (unlikely(wcs_n < 0)) { DEBUG("%p: ibv_poll_cq() failed (wcs_n=%d)", (void *)txq, wcs_n); return -1; } elts_comp -= wcs_n; assert(elts_comp <= txq->elts_comp); /* * Assume WC status is successful as nothing can be done about it * anyway. */ elts_tail += wcs_n * txq->elts_comp_cd_init; if (elts_tail >= elts_n) elts_tail -= elts_n; txq->elts_tail = elts_tail; txq->elts_comp = elts_comp; return 0; } /** * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[]. * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full, * remove an entry first. * * @param txq * Pointer to TX queue structure. * @param[in] mp * Memory Pool for which a Memory Region lkey must be returned. * * @return * mr->lkey on success, (uint32_t)-1 on failure. */ static uint32_t txq_mp2mr(struct txq *txq, struct rte_mempool *mp) { unsigned int i; struct ibv_mr *mr; for (i = 0; (i != elemof(txq->mp2mr)); ++i) { if (unlikely(txq->mp2mr[i].mp == NULL)) { /* Unknown MP, add a new MR for it. */ break; } if (txq->mp2mr[i].mp == mp) { assert(txq->mp2mr[i].lkey != (uint32_t)-1); assert(txq->mp2mr[i].mr->lkey == txq->mp2mr[i].lkey); return txq->mp2mr[i].lkey; } } /* Add a new entry, register MR first. */ DEBUG("%p: discovered new memory pool %p", (void *)txq, (void *)mp); mr = ibv_reg_mr(txq->priv->pd, (void *)mp->elt_va_start, (mp->elt_va_end - mp->elt_va_start), (IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE)); if (unlikely(mr == NULL)) { DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.", (void *)txq); return (uint32_t)-1; } if (unlikely(i == elemof(txq->mp2mr))) { /* Table is full, remove oldest entry. */ DEBUG("%p: MR <-> MP table full, dropping oldest entry.", (void *)txq); --i; claim_zero(ibv_dereg_mr(txq->mp2mr[i].mr)); memmove(&txq->mp2mr[0], &txq->mp2mr[1], (sizeof(txq->mp2mr) - sizeof(txq->mp2mr[0]))); } /* Store the new entry. */ txq->mp2mr[i].mp = mp; txq->mp2mr[i].mr = mr; txq->mp2mr[i].lkey = mr->lkey; DEBUG("%p: new MR lkey for MP %p: 0x%08" PRIu32, (void *)txq, (void *)mp, txq->mp2mr[i].lkey); return txq->mp2mr[i].lkey; } #if MLX4_PMD_SGE_WR_N > 1 /** * Copy scattered mbuf contents to a single linear buffer. * * @param[out] linear * Linear output buffer. * @param[in] buf * Scattered input buffer. * * @return * Number of bytes copied to the output buffer or 0 if not large enough. */ static unsigned int linearize_mbuf(linear_t *linear, struct rte_mbuf *buf) { unsigned int size = 0; unsigned int offset; do { unsigned int len = DATA_LEN(buf); offset = size; size += len; if (unlikely(size > sizeof(*linear))) return 0; memcpy(&(*linear)[offset], rte_pktmbuf_mtod(buf, uint8_t *), len); buf = NEXT(buf); } while (buf != NULL); return size; } /** * Handle scattered buffers for mlx4_tx_burst(). * * @param txq * TX queue structure. * @param segs * Number of segments in buf. * @param elt * TX queue element to fill. * @param[in] buf * Buffer to process. * @param elts_head * Index of the linear buffer to use if necessary (normally txq->elts_head). * @param[out] sges * Array filled with SGEs on success. * * @return * A structure containing the processed packet size in bytes and the * number of SGEs. Both fields are set to (unsigned int)-1 in case of * failure. */ static struct tx_burst_sg_ret { unsigned int length; unsigned int num; } tx_burst_sg(struct txq *txq, unsigned int segs, struct txq_elt *elt, struct rte_mbuf *buf, unsigned int elts_head, struct ibv_sge (*sges)[MLX4_PMD_SGE_WR_N]) { unsigned int sent_size = 0; unsigned int j; int linearize = 0; /* When there are too many segments, extra segments are * linearized in the last SGE. */ if (unlikely(segs > elemof(*sges))) { segs = (elemof(*sges) - 1); linearize = 1; } /* Update element. */ elt->buf = buf; /* Register segments as SGEs. */ for (j = 0; (j != segs); ++j) { struct ibv_sge *sge = &(*sges)[j]; uint32_t lkey; /* Retrieve Memory Region key for this memory pool. */ lkey = txq_mp2mr(txq, buf->pool); if (unlikely(lkey == (uint32_t)-1)) { /* MR does not exist. */ DEBUG("%p: unable to get MP <-> MR association", (void *)txq); /* Clean up TX element. */ elt->buf = NULL; goto stop; } /* Update SGE. */ sge->addr = rte_pktmbuf_mtod(buf, uintptr_t); if (txq->priv->vf) rte_prefetch0((volatile void *) (uintptr_t)sge->addr); sge->length = DATA_LEN(buf); sge->lkey = lkey; sent_size += sge->length; buf = NEXT(buf); } /* If buf is not NULL here and is not going to be linearized, * nb_segs is not valid. */ assert(j == segs); assert((buf == NULL) || (linearize)); /* Linearize extra segments. */ if (linearize) { struct ibv_sge *sge = &(*sges)[segs]; linear_t *linear = &(*txq->elts_linear)[elts_head]; unsigned int size = linearize_mbuf(linear, buf); assert(segs == (elemof(*sges) - 1)); if (size == 0) { /* Invalid packet. */ DEBUG("%p: packet too large to be linearized.", (void *)txq); /* Clean up TX element. */ elt->buf = NULL; goto stop; } /* If MLX4_PMD_SGE_WR_N is 1, free mbuf immediately. */ if (elemof(*sges) == 1) { do { struct rte_mbuf *next = NEXT(buf); rte_pktmbuf_free_seg(buf); buf = next; } while (buf != NULL); elt->buf = NULL; } /* Update SGE. */ sge->addr = (uintptr_t)&(*linear)[0]; sge->length = size; sge->lkey = txq->mr_linear->lkey; sent_size += size; } return (struct tx_burst_sg_ret){ .length = sent_size, .num = segs, }; stop: return (struct tx_burst_sg_ret){ .length = -1, .num = -1, }; } #endif /* MLX4_PMD_SGE_WR_N > 1 */ /** * DPDK callback for TX. * * @param dpdk_txq * Generic pointer to TX queue structure. * @param[in] pkts * Packets to transmit. * @param pkts_n * Number of packets in array. * * @return * Number of packets successfully transmitted (<= pkts_n). */ static uint16_t mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) { struct txq *txq = (struct txq *)dpdk_txq; unsigned int elts_head = txq->elts_head; const unsigned int elts_tail = txq->elts_tail; const unsigned int elts_n = txq->elts_n; unsigned int elts_comp_cd = txq->elts_comp_cd; unsigned int elts_comp = 0; unsigned int i; unsigned int max; int err; assert(elts_comp_cd != 0); txq_complete(txq); max = (elts_n - (elts_head - elts_tail)); if (max > elts_n) max -= elts_n; assert(max >= 1); assert(max <= elts_n); /* Always leave one free entry in the ring. */ --max; if (max == 0) return 0; if (max > pkts_n) max = pkts_n; for (i = 0; (i != max); ++i) { struct rte_mbuf *buf = pkts[i]; unsigned int elts_head_next = (((elts_head + 1) == elts_n) ? 0 : elts_head + 1); struct txq_elt *elt_next = &(*txq->elts)[elts_head_next]; struct txq_elt *elt = &(*txq->elts)[elts_head]; unsigned int segs = NB_SEGS(buf); #ifdef MLX4_PMD_SOFT_COUNTERS unsigned int sent_size = 0; #endif uint32_t send_flags = 0; /* Clean up old buffer. */ if (likely(elt->buf != NULL)) { struct rte_mbuf *tmp = elt->buf; /* Faster than rte_pktmbuf_free(). */ do { struct rte_mbuf *next = NEXT(tmp); rte_pktmbuf_free_seg(tmp); tmp = next; } while (tmp != NULL); } /* Request TX completion. */ if (unlikely(--elts_comp_cd == 0)) { elts_comp_cd = txq->elts_comp_cd_init; ++elts_comp; send_flags |= IBV_EXP_QP_BURST_SIGNALED; } /* Should we enable HW CKSUM offload */ if (buf->ol_flags & (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) { send_flags |= IBV_EXP_QP_BURST_IP_CSUM; /* HW does not support checksum offloads at arbitrary * offsets but automatically recognizes the packet * type. For inner L3/L4 checksums, only VXLAN (UDP) * tunnels are currently supported. */ #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_TUNNEL_PKT(buf->packet_type)) #else /* FIXME: since PKT_TX_UDP_TUNNEL_PKT has been removed, * the outer packet type is unknown. All we know is * that the L2 header is of unusual length (not * ETHER_HDR_LEN with or without 802.1Q header). */ if ((buf->l2_len != ETHER_HDR_LEN) && (buf->l2_len != (ETHER_HDR_LEN + 4))) #endif send_flags |= IBV_EXP_QP_BURST_TUNNEL; } if (likely(segs == 1)) { uintptr_t addr; uint32_t length; uint32_t lkey; /* Retrieve buffer information. */ addr = rte_pktmbuf_mtod(buf, uintptr_t); length = DATA_LEN(buf); /* Retrieve Memory Region key for this memory pool. */ lkey = txq_mp2mr(txq, buf->pool); if (unlikely(lkey == (uint32_t)-1)) { /* MR does not exist. */ DEBUG("%p: unable to get MP <-> MR" " association", (void *)txq); /* Clean up TX element. */ elt->buf = NULL; goto stop; } /* Update element. */ elt->buf = buf; if (txq->priv->vf) rte_prefetch0((volatile void *) (uintptr_t)addr); RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf); /* Put packet into send queue. */ #if MLX4_PMD_MAX_INLINE > 0 if (length <= txq->max_inline) err = txq->if_qp->send_pending_inline (txq->qp, (void *)addr, length, send_flags); else #endif err = txq->if_qp->send_pending (txq->qp, addr, length, lkey, send_flags); if (unlikely(err)) goto stop; #ifdef MLX4_PMD_SOFT_COUNTERS sent_size += length; #endif } else { #if MLX4_PMD_SGE_WR_N > 1 struct ibv_sge sges[MLX4_PMD_SGE_WR_N]; struct tx_burst_sg_ret ret; ret = tx_burst_sg(txq, segs, elt, buf, elts_head, &sges); if (ret.length == (unsigned int)-1) goto stop; RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf); /* Put SG list into send queue. */ err = txq->if_qp->send_pending_sg_list (txq->qp, sges, ret.num, send_flags); if (unlikely(err)) goto stop; #ifdef MLX4_PMD_SOFT_COUNTERS sent_size += ret.length; #endif #else /* MLX4_PMD_SGE_WR_N > 1 */ DEBUG("%p: TX scattered buffers support not" " compiled in", (void *)txq); goto stop; #endif /* MLX4_PMD_SGE_WR_N > 1 */ } elts_head = elts_head_next; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increment sent bytes counter. */ txq->stats.obytes += sent_size; #endif } stop: /* Take a shortcut if nothing must be sent. */ if (unlikely(i == 0)) return 0; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increment sent packets counter. */ txq->stats.opackets += i; #endif /* Ring QP doorbell. */ err = txq->if_qp->send_flush(txq->qp); if (unlikely(err)) { /* A nonzero value is not supposed to be returned. * Nothing can be done about it. */ DEBUG("%p: send_flush() failed with error %d", (void *)txq, err); } txq->elts_head = elts_head; txq->elts_comp += elts_comp; txq->elts_comp_cd = elts_comp_cd; return i; } /** * Configure a TX queue. * * @param dev * Pointer to Ethernet device structure. * @param txq * Pointer to TX queue structure. * @param desc * Number of descriptors to configure in queue. * @param socket * NUMA socket on which memory must be allocated. * @param[in] conf * Thresholds parameters. * * @return * 0 on success, errno value on failure. */ static int txq_setup(struct rte_eth_dev *dev, struct txq *txq, uint16_t desc, unsigned int socket, const struct rte_eth_txconf *conf) { struct priv *priv = dev->data->dev_private; struct txq tmpl = { .priv = priv, .socket = socket }; union { struct ibv_exp_query_intf_params params; struct ibv_exp_qp_init_attr init; struct ibv_exp_res_domain_init_attr rd; struct ibv_exp_cq_init_attr cq; struct ibv_exp_qp_attr mod; } attr; enum ibv_exp_query_intf_status status; int ret = 0; (void)conf; /* Thresholds configuration (ignored). */ if ((desc == 0) || (desc % MLX4_PMD_SGE_WR_N)) { ERROR("%p: invalid number of TX descriptors (must be a" " multiple of %d)", (void *)dev, MLX4_PMD_SGE_WR_N); return EINVAL; } desc /= MLX4_PMD_SGE_WR_N; /* MRs will be registered in mp2mr[] later. */ attr.rd = (struct ibv_exp_res_domain_init_attr){ .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL | IBV_EXP_RES_DOMAIN_MSG_MODEL), .thread_model = IBV_EXP_THREAD_SINGLE, .msg_model = IBV_EXP_MSG_HIGH_BW, }; tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd); if (tmpl.rd == NULL) { ret = ENOMEM; ERROR("%p: RD creation failure: %s", (void *)dev, strerror(ret)); goto error; } attr.cq = (struct ibv_exp_cq_init_attr){ .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN, .res_domain = tmpl.rd, }; tmpl.cq = ibv_exp_create_cq(priv->ctx, desc, NULL, NULL, 0, &attr.cq); if (tmpl.cq == NULL) { ret = ENOMEM; ERROR("%p: CQ creation failure: %s", (void *)dev, strerror(ret)); goto error; } DEBUG("priv->device_attr.max_qp_wr is %d", priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d", priv->device_attr.max_sge); attr.init = (struct ibv_exp_qp_init_attr){ /* CQ to be associated with the send queue. */ .send_cq = tmpl.cq, /* CQ to be associated with the receive queue. */ .recv_cq = tmpl.cq, .cap = { /* Max number of outstanding WRs. */ .max_send_wr = ((priv->device_attr.max_qp_wr < desc) ? priv->device_attr.max_qp_wr : desc), /* Max number of scatter/gather elements in a WR. */ .max_send_sge = ((priv->device_attr.max_sge < MLX4_PMD_SGE_WR_N) ? priv->device_attr.max_sge : MLX4_PMD_SGE_WR_N), #if MLX4_PMD_MAX_INLINE > 0 .max_inline_data = MLX4_PMD_MAX_INLINE, #endif }, .qp_type = IBV_QPT_RAW_PACKET, /* Do *NOT* enable this, completions events are managed per * TX burst. */ .sq_sig_all = 0, .pd = priv->pd, .res_domain = tmpl.rd, .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD | IBV_EXP_QP_INIT_ATTR_RES_DOMAIN), }; tmpl.qp = ibv_exp_create_qp(priv->ctx, &attr.init); if (tmpl.qp == NULL) { ret = (errno ? errno : EINVAL); ERROR("%p: QP creation failure: %s", (void *)dev, strerror(ret)); goto error; } #if MLX4_PMD_MAX_INLINE > 0 /* ibv_create_qp() updates this value. */ tmpl.max_inline = attr.init.cap.max_inline_data; #endif attr.mod = (struct ibv_exp_qp_attr){ /* Move the QP to this state. */ .qp_state = IBV_QPS_INIT, /* Primary port number. */ .port_num = priv->port }; ret = ibv_exp_modify_qp(tmpl.qp, &attr.mod, (IBV_EXP_QP_STATE | IBV_EXP_QP_PORT)); if (ret) { ERROR("%p: QP state to IBV_QPS_INIT failed: %s", (void *)dev, strerror(ret)); goto error; } ret = txq_alloc_elts(&tmpl, desc); if (ret) { ERROR("%p: TXQ allocation failed: %s", (void *)dev, strerror(ret)); goto error; } attr.mod = (struct ibv_exp_qp_attr){ .qp_state = IBV_QPS_RTR }; ret = ibv_exp_modify_qp(tmpl.qp, &attr.mod, IBV_EXP_QP_STATE); if (ret) { ERROR("%p: QP state to IBV_QPS_RTR failed: %s", (void *)dev, strerror(ret)); goto error; } attr.mod.qp_state = IBV_QPS_RTS; ret = ibv_exp_modify_qp(tmpl.qp, &attr.mod, IBV_EXP_QP_STATE); if (ret) { ERROR("%p: QP state to IBV_QPS_RTS failed: %s", (void *)dev, strerror(ret)); goto error; } attr.params = (struct ibv_exp_query_intf_params){ .intf_scope = IBV_EXP_INTF_GLOBAL, .intf = IBV_EXP_INTF_CQ, .obj = tmpl.cq, }; tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status); if (tmpl.if_cq == NULL) { ERROR("%p: CQ interface family query failed with status %d", (void *)dev, status); goto error; } attr.params = (struct ibv_exp_query_intf_params){ .intf_scope = IBV_EXP_INTF_GLOBAL, .intf = IBV_EXP_INTF_QP_BURST, .obj = tmpl.qp, #ifdef HAVE_EXP_QP_BURST_CREATE_DISABLE_ETH_LOOPBACK /* MC loopback must be disabled when not using a VF. */ .family_flags = (!priv->vf ? IBV_EXP_QP_BURST_CREATE_DISABLE_ETH_LOOPBACK : 0), #endif }; tmpl.if_qp = ibv_exp_query_intf(priv->ctx, &attr.params, &status); if (tmpl.if_qp == NULL) { ERROR("%p: QP interface family query failed with status %d", (void *)dev, status); goto error; } /* Clean up txq in case we're reinitializing it. */ DEBUG("%p: cleaning-up old txq just in case", (void *)txq); txq_cleanup(txq); *txq = tmpl; DEBUG("%p: txq updated with %p", (void *)txq, (void *)&tmpl); assert(ret == 0); return 0; error: txq_cleanup(&tmpl); assert(ret > 0); return ret; } /** * DPDK callback to configure a TX queue. * * @param dev * Pointer to Ethernet device structure. * @param idx * TX queue index. * @param desc * Number of descriptors to configure in queue. * @param socket * NUMA socket on which memory must be allocated. * @param[in] conf * Thresholds parameters. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, unsigned int socket, const struct rte_eth_txconf *conf) { struct priv *priv = dev->data->dev_private; struct txq *txq = (*priv->txqs)[idx]; int ret; priv_lock(priv); DEBUG("%p: configuring queue %u for %u descriptors", (void *)dev, idx, desc); if (idx >= priv->txqs_n) { ERROR("%p: queue index out of range (%u >= %u)", (void *)dev, idx, priv->txqs_n); priv_unlock(priv); return -EOVERFLOW; } if (txq != NULL) { DEBUG("%p: reusing already allocated queue index %u (%p)", (void *)dev, idx, (void *)txq); if (priv->started) { priv_unlock(priv); return -EEXIST; } (*priv->txqs)[idx] = NULL; txq_cleanup(txq); } else { txq = rte_calloc_socket("TXQ", 1, sizeof(*txq), 0, socket); if (txq == NULL) { ERROR("%p: unable to allocate queue index %u", (void *)dev, idx); priv_unlock(priv); return -ENOMEM; } } ret = txq_setup(dev, txq, desc, socket, conf); if (ret) rte_free(txq); else { txq->stats.idx = idx; DEBUG("%p: adding TX queue %p to list", (void *)dev, (void *)txq); (*priv->txqs)[idx] = txq; /* Update send callback. */ dev->tx_pkt_burst = mlx4_tx_burst; } priv_unlock(priv); return -ret; } /** * DPDK callback to release a TX queue. * * @param dpdk_txq * Generic TX queue pointer. */ static void mlx4_tx_queue_release(void *dpdk_txq) { struct txq *txq = (struct txq *)dpdk_txq; struct priv *priv; unsigned int i; if (txq == NULL) return; priv = txq->priv; priv_lock(priv); for (i = 0; (i != priv->txqs_n); ++i) if ((*priv->txqs)[i] == txq) { DEBUG("%p: removing TX queue %p from list", (void *)priv->dev, (void *)txq); (*priv->txqs)[i] = NULL; break; } txq_cleanup(txq); rte_free(txq); priv_unlock(priv); } /* RX queues handling. */ /** * Allocate RX queue elements with scattered packets support. * * @param rxq * Pointer to RX queue structure. * @param elts_n * Number of elements to allocate. * @param[in] pool * If not NULL, fetch buffers from this array instead of allocating them * with rte_pktmbuf_alloc(). * * @return * 0 on success, errno value on failure. */ static int rxq_alloc_elts_sp(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool) { unsigned int i; struct rxq_elt_sp (*elts)[elts_n] = rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0, rxq->socket); int ret = 0; if (elts == NULL) { ERROR("%p: can't allocate packets array", (void *)rxq); ret = ENOMEM; goto error; } /* For each WR (packet). */ for (i = 0; (i != elts_n); ++i) { unsigned int j; struct rxq_elt_sp *elt = &(*elts)[i]; struct ibv_recv_wr *wr = &elt->wr; struct ibv_sge (*sges)[(elemof(elt->sges))] = &elt->sges; /* These two arrays must have the same size. */ assert(elemof(elt->sges) == elemof(elt->bufs)); /* Configure WR. */ wr->wr_id = i; wr->next = &(*elts)[(i + 1)].wr; wr->sg_list = &(*sges)[0]; wr->num_sge = elemof(*sges); /* For each SGE (segment). */ for (j = 0; (j != elemof(elt->bufs)); ++j) { struct ibv_sge *sge = &(*sges)[j]; struct rte_mbuf *buf; if (pool != NULL) { buf = *(pool++); assert(buf != NULL); rte_pktmbuf_reset(buf); } else buf = rte_pktmbuf_alloc(rxq->mp); if (buf == NULL) { assert(pool == NULL); ERROR("%p: empty mbuf pool", (void *)rxq); ret = ENOMEM; goto error; } elt->bufs[j] = buf; /* Headroom is reserved by rte_pktmbuf_alloc(). */ assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM); /* Buffer is supposed to be empty. */ assert(rte_pktmbuf_data_len(buf) == 0); assert(rte_pktmbuf_pkt_len(buf) == 0); /* sge->addr must be able to store a pointer. */ assert(sizeof(sge->addr) >= sizeof(uintptr_t)); if (j == 0) { /* The first SGE keeps its headroom. */ sge->addr = rte_pktmbuf_mtod(buf, uintptr_t); sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM); } else { /* Subsequent SGEs lose theirs. */ assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM); SET_DATA_OFF(buf, 0); sge->addr = (uintptr_t)buf->buf_addr; sge->length = buf->buf_len; } sge->lkey = rxq->mr->lkey; /* Redundant check for tailroom. */ assert(sge->length == rte_pktmbuf_tailroom(buf)); } } /* The last WR pointer must be NULL. */ (*elts)[(i - 1)].wr.next = NULL; DEBUG("%p: allocated and configured %u WRs (%zu segments)", (void *)rxq, elts_n, (elts_n * elemof((*elts)[0].sges))); rxq->elts_n = elts_n; rxq->elts_head = 0; rxq->elts.sp = elts; assert(ret == 0); return 0; error: if (elts != NULL) { assert(pool == NULL); for (i = 0; (i != elemof(*elts)); ++i) { unsigned int j; struct rxq_elt_sp *elt = &(*elts)[i]; for (j = 0; (j != elemof(elt->bufs)); ++j) { struct rte_mbuf *buf = elt->bufs[j]; if (buf != NULL) rte_pktmbuf_free_seg(buf); } } rte_free(elts); } DEBUG("%p: failed, freed everything", (void *)rxq); assert(ret > 0); return ret; } /** * Free RX queue elements with scattered packets support. * * @param rxq * Pointer to RX queue structure. */ static void rxq_free_elts_sp(struct rxq *rxq) { unsigned int i; unsigned int elts_n = rxq->elts_n; struct rxq_elt_sp (*elts)[elts_n] = rxq->elts.sp; DEBUG("%p: freeing WRs", (void *)rxq); rxq->elts_n = 0; rxq->elts.sp = NULL; if (elts == NULL) return; for (i = 0; (i != elemof(*elts)); ++i) { unsigned int j; struct rxq_elt_sp *elt = &(*elts)[i]; for (j = 0; (j != elemof(elt->bufs)); ++j) { struct rte_mbuf *buf = elt->bufs[j]; if (buf != NULL) rte_pktmbuf_free_seg(buf); } } rte_free(elts); } /** * Allocate RX queue elements. * * @param rxq * Pointer to RX queue structure. * @param elts_n * Number of elements to allocate. * @param[in] pool * If not NULL, fetch buffers from this array instead of allocating them * with rte_pktmbuf_alloc(). * * @return * 0 on success, errno value on failure. */ static int rxq_alloc_elts(struct rxq *rxq, unsigned int elts_n, struct rte_mbuf **pool) { unsigned int i; struct rxq_elt (*elts)[elts_n] = rte_calloc_socket("RXQ elements", 1, sizeof(*elts), 0, rxq->socket); int ret = 0; if (elts == NULL) { ERROR("%p: can't allocate packets array", (void *)rxq); ret = ENOMEM; goto error; } /* For each WR (packet). */ for (i = 0; (i != elts_n); ++i) { struct rxq_elt *elt = &(*elts)[i]; struct ibv_recv_wr *wr = &elt->wr; struct ibv_sge *sge = &(*elts)[i].sge; struct rte_mbuf *buf; if (pool != NULL) { buf = *(pool++); assert(buf != NULL); rte_pktmbuf_reset(buf); } else buf = rte_pktmbuf_alloc(rxq->mp); if (buf == NULL) { assert(pool == NULL); ERROR("%p: empty mbuf pool", (void *)rxq); ret = ENOMEM; goto error; } /* Configure WR. Work request ID contains its own index in * the elts array and the offset between SGE buffer header and * its data. */ WR_ID(wr->wr_id).id = i; WR_ID(wr->wr_id).offset = (((uintptr_t)buf->buf_addr + RTE_PKTMBUF_HEADROOM) - (uintptr_t)buf); wr->next = &(*elts)[(i + 1)].wr; wr->sg_list = sge; wr->num_sge = 1; /* Headroom is reserved by rte_pktmbuf_alloc(). */ assert(DATA_OFF(buf) == RTE_PKTMBUF_HEADROOM); /* Buffer is supposed to be empty. */ assert(rte_pktmbuf_data_len(buf) == 0); assert(rte_pktmbuf_pkt_len(buf) == 0); /* sge->addr must be able to store a pointer. */ assert(sizeof(sge->addr) >= sizeof(uintptr_t)); /* SGE keeps its headroom. */ sge->addr = (uintptr_t) ((uint8_t *)buf->buf_addr + RTE_PKTMBUF_HEADROOM); sge->length = (buf->buf_len - RTE_PKTMBUF_HEADROOM); sge->lkey = rxq->mr->lkey; /* Redundant check for tailroom. */ assert(sge->length == rte_pktmbuf_tailroom(buf)); /* Make sure elts index and SGE mbuf pointer can be deduced * from WR ID. */ if ((WR_ID(wr->wr_id).id != i) || ((void *)((uintptr_t)sge->addr - WR_ID(wr->wr_id).offset) != buf)) { ERROR("%p: cannot store index and offset in WR ID", (void *)rxq); sge->addr = 0; rte_pktmbuf_free(buf); ret = EOVERFLOW; goto error; } } /* The last WR pointer must be NULL. */ (*elts)[(i - 1)].wr.next = NULL; DEBUG("%p: allocated and configured %u single-segment WRs", (void *)rxq, elts_n); rxq->elts_n = elts_n; rxq->elts_head = 0; rxq->elts.no_sp = elts; assert(ret == 0); return 0; error: if (elts != NULL) { assert(pool == NULL); for (i = 0; (i != elemof(*elts)); ++i) { struct rxq_elt *elt = &(*elts)[i]; struct rte_mbuf *buf; if (elt->sge.addr == 0) continue; assert(WR_ID(elt->wr.wr_id).id == i); buf = (void *)((uintptr_t)elt->sge.addr - WR_ID(elt->wr.wr_id).offset); rte_pktmbuf_free_seg(buf); } rte_free(elts); } DEBUG("%p: failed, freed everything", (void *)rxq); assert(ret > 0); return ret; } /** * Free RX queue elements. * * @param rxq * Pointer to RX queue structure. */ static void rxq_free_elts(struct rxq *rxq) { unsigned int i; unsigned int elts_n = rxq->elts_n; struct rxq_elt (*elts)[elts_n] = rxq->elts.no_sp; DEBUG("%p: freeing WRs", (void *)rxq); rxq->elts_n = 0; rxq->elts.no_sp = NULL; if (elts == NULL) return; for (i = 0; (i != elemof(*elts)); ++i) { struct rxq_elt *elt = &(*elts)[i]; struct rte_mbuf *buf; if (elt->sge.addr == 0) continue; assert(WR_ID(elt->wr.wr_id).id == i); buf = (void *)((uintptr_t)elt->sge.addr - WR_ID(elt->wr.wr_id).offset); rte_pktmbuf_free_seg(buf); } rte_free(elts); } /** * Delete flow steering rule. * * @param rxq * Pointer to RX queue structure. * @param mac_index * MAC address index. * @param vlan_index * VLAN index. */ static void rxq_del_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index) { #ifndef NDEBUG struct priv *priv = rxq->priv; const uint8_t (*mac)[ETHER_ADDR_LEN] = (const uint8_t (*)[ETHER_ADDR_LEN]) priv->mac[mac_index].addr_bytes; #endif assert(rxq->mac_flow[mac_index][vlan_index] != NULL); DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u" " (VLAN ID %" PRIu16 ")", (void *)rxq, (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], mac_index, priv->vlan_filter[vlan_index].id); claim_zero(ibv_destroy_flow(rxq->mac_flow[mac_index][vlan_index])); rxq->mac_flow[mac_index][vlan_index] = NULL; } /** * Unregister a MAC address from a RX queue. * * @param rxq * Pointer to RX queue structure. * @param mac_index * MAC address index. */ static void rxq_mac_addr_del(struct rxq *rxq, unsigned int mac_index) { struct priv *priv = rxq->priv; unsigned int i; unsigned int vlans = 0; assert(mac_index < elemof(priv->mac)); if (!BITFIELD_ISSET(rxq->mac_configured, mac_index)) return; for (i = 0; (i != elemof(priv->vlan_filter)); ++i) { if (!priv->vlan_filter[i].enabled) continue; rxq_del_flow(rxq, mac_index, i); vlans++; } if (!vlans) { rxq_del_flow(rxq, mac_index, 0); } BITFIELD_RESET(rxq->mac_configured, mac_index); } /** * Unregister all MAC addresses from a RX queue. * * @param rxq * Pointer to RX queue structure. */ static void rxq_mac_addrs_del(struct rxq *rxq) { struct priv *priv = rxq->priv; unsigned int i; for (i = 0; (i != elemof(priv->mac)); ++i) rxq_mac_addr_del(rxq, i); } static int rxq_promiscuous_enable(struct rxq *); static void rxq_promiscuous_disable(struct rxq *); /** * Add single flow steering rule. * * @param rxq * Pointer to RX queue structure. * @param mac_index * MAC address index to register. * @param vlan_index * VLAN index. Use -1 for a flow without VLAN. * * @return * 0 on success, errno value on failure. */ static int rxq_add_flow(struct rxq *rxq, unsigned int mac_index, unsigned int vlan_index) { struct ibv_flow *flow; struct priv *priv = rxq->priv; const uint8_t (*mac)[ETHER_ADDR_LEN] = (const uint8_t (*)[ETHER_ADDR_LEN]) priv->mac[mac_index].addr_bytes; /* Allocate flow specification on the stack. */ struct __attribute__((packed)) { struct ibv_flow_attr attr; struct ibv_flow_spec_eth spec; } data; struct ibv_flow_attr *attr = &data.attr; struct ibv_flow_spec_eth *spec = &data.spec; assert(mac_index < elemof(priv->mac)); assert((vlan_index < elemof(priv->vlan_filter)) || (vlan_index == -1u)); /* * No padding must be inserted by the compiler between attr and spec. * This layout is expected by libibverbs. */ assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec); *attr = (struct ibv_flow_attr){ .type = IBV_FLOW_ATTR_NORMAL, .num_of_specs = 1, .port = priv->port, .flags = 0 }; *spec = (struct ibv_flow_spec_eth){ .type = IBV_FLOW_SPEC_ETH, .size = sizeof(*spec), .val = { .dst_mac = { (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5] }, .vlan_tag = ((vlan_index != -1u) ? htons(priv->vlan_filter[vlan_index].id) : 0), }, .mask = { .dst_mac = "\xff\xff\xff\xff\xff\xff", .vlan_tag = ((vlan_index != -1u) ? htons(0xfff) : 0), } }; DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u" " (VLAN %s %" PRIu16 ")", (void *)rxq, (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], mac_index, ((vlan_index != -1u) ? "ID" : "index"), ((vlan_index != -1u) ? priv->vlan_filter[vlan_index].id : -1u)); /* Create related flow. */ errno = 0; flow = ibv_create_flow(rxq->qp, attr); if (flow == NULL) { /* It's not clear whether errno is always set in this case. */ ERROR("%p: flow configuration failed, errno=%d: %s", (void *)rxq, errno, (errno ? strerror(errno) : "Unknown error")); if (errno) return errno; return EINVAL; } if (vlan_index == -1u) vlan_index = 0; assert(rxq->mac_flow[mac_index][vlan_index] == NULL); rxq->mac_flow[mac_index][vlan_index] = flow; return 0; } /** * Register a MAC address in a RX queue. * * @param rxq * Pointer to RX queue structure. * @param mac_index * MAC address index to register. * * @return * 0 on success, errno value on failure. */ static int rxq_mac_addr_add(struct rxq *rxq, unsigned int mac_index) { struct priv *priv = rxq->priv; unsigned int i; unsigned int vlans = 0; int ret; assert(mac_index < elemof(priv->mac)); if (BITFIELD_ISSET(rxq->mac_configured, mac_index)) rxq_mac_addr_del(rxq, mac_index); /* Fill VLAN specifications. */ for (i = 0; (i != elemof(priv->vlan_filter)); ++i) { if (!priv->vlan_filter[i].enabled) continue; /* Create related flow. */ ret = rxq_add_flow(rxq, mac_index, i); if (!ret) { vlans++; continue; } /* Failure, rollback. */ while (i != 0) if (priv->vlan_filter[--i].enabled) rxq_del_flow(rxq, mac_index, i); assert(ret > 0); return ret; } /* In case there is no VLAN filter. */ if (!vlans) { ret = rxq_add_flow(rxq, mac_index, -1); if (ret) return ret; } BITFIELD_SET(rxq->mac_configured, mac_index); return 0; } /** * Register all MAC addresses in a RX queue. * * @param rxq * Pointer to RX queue structure. * * @return * 0 on success, errno value on failure. */ static int rxq_mac_addrs_add(struct rxq *rxq) { struct priv *priv = rxq->priv; unsigned int i; int ret; for (i = 0; (i != elemof(priv->mac)); ++i) { if (!BITFIELD_ISSET(priv->mac_configured, i)) continue; ret = rxq_mac_addr_add(rxq, i); if (!ret) continue; /* Failure, rollback. */ while (i != 0) rxq_mac_addr_del(rxq, --i); assert(ret > 0); return ret; } return 0; } /** * Unregister a MAC address. * * In RSS mode, the MAC address is unregistered from the parent queue, * otherwise it is unregistered from each queue directly. * * @param priv * Pointer to private structure. * @param mac_index * MAC address index. */ static void priv_mac_addr_del(struct priv *priv, unsigned int mac_index) { unsigned int i; assert(mac_index < elemof(priv->mac)); if (!BITFIELD_ISSET(priv->mac_configured, mac_index)) return; if (priv->rss) { rxq_mac_addr_del(&priv->rxq_parent, mac_index); goto end; } for (i = 0; (i != priv->dev->data->nb_rx_queues); ++i) rxq_mac_addr_del((*priv->rxqs)[i], mac_index); end: BITFIELD_RESET(priv->mac_configured, mac_index); } /** * Register a MAC address. * * In RSS mode, the MAC address is registered in the parent queue, * otherwise it is registered in each queue directly. * * @param priv * Pointer to private structure. * @param mac_index * MAC address index to use. * @param mac * MAC address to register. * * @return * 0 on success, errno value on failure. */ static int priv_mac_addr_add(struct priv *priv, unsigned int mac_index, const uint8_t (*mac)[ETHER_ADDR_LEN]) { unsigned int i; int ret; assert(mac_index < elemof(priv->mac)); /* First, make sure this address isn't already configured. */ for (i = 0; (i != elemof(priv->mac)); ++i) { /* Skip this index, it's going to be reconfigured. */ if (i == mac_index) continue; if (!BITFIELD_ISSET(priv->mac_configured, i)) continue; if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac))) continue; /* Address already configured elsewhere, return with error. */ return EADDRINUSE; } if (BITFIELD_ISSET(priv->mac_configured, mac_index)) priv_mac_addr_del(priv, mac_index); priv->mac[mac_index] = (struct ether_addr){ { (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5] } }; /* If device isn't started, this is all we need to do. */ if (!priv->started) { #ifndef NDEBUG /* Verify that all queues have this index disabled. */ for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; assert(!BITFIELD_ISSET ((*priv->rxqs)[i]->mac_configured, mac_index)); } #endif goto end; } if (priv->rss) { ret = rxq_mac_addr_add(&priv->rxq_parent, mac_index); if (ret) return ret; goto end; } for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; ret = rxq_mac_addr_add((*priv->rxqs)[i], mac_index); if (!ret) continue; /* Failure, rollback. */ while (i != 0) if ((*priv->rxqs)[(--i)] != NULL) rxq_mac_addr_del((*priv->rxqs)[i], mac_index); return ret; } end: BITFIELD_SET(priv->mac_configured, mac_index); return 0; } /** * Enable allmulti mode in a RX queue. * * @param rxq * Pointer to RX queue structure. * * @return * 0 on success, errno value on failure. */ static int rxq_allmulticast_enable(struct rxq *rxq) { struct ibv_flow *flow; struct ibv_flow_attr attr = { .type = IBV_FLOW_ATTR_MC_DEFAULT, .num_of_specs = 0, .port = rxq->priv->port, .flags = 0 }; DEBUG("%p: enabling allmulticast mode", (void *)rxq); if (rxq->allmulti_flow != NULL) return EBUSY; errno = 0; flow = ibv_create_flow(rxq->qp, &attr); if (flow == NULL) { /* It's not clear whether errno is always set in this case. */ ERROR("%p: flow configuration failed, errno=%d: %s", (void *)rxq, errno, (errno ? strerror(errno) : "Unknown error")); if (errno) return errno; return EINVAL; } rxq->allmulti_flow = flow; DEBUG("%p: allmulticast mode enabled", (void *)rxq); return 0; } /** * Disable allmulti mode in a RX queue. * * @param rxq * Pointer to RX queue structure. */ static void rxq_allmulticast_disable(struct rxq *rxq) { DEBUG("%p: disabling allmulticast mode", (void *)rxq); if (rxq->allmulti_flow == NULL) return; claim_zero(ibv_destroy_flow(rxq->allmulti_flow)); rxq->allmulti_flow = NULL; DEBUG("%p: allmulticast mode disabled", (void *)rxq); } /** * Enable promiscuous mode in a RX queue. * * @param rxq * Pointer to RX queue structure. * * @return * 0 on success, errno value on failure. */ static int rxq_promiscuous_enable(struct rxq *rxq) { struct ibv_flow *flow; struct ibv_flow_attr attr = { .type = IBV_FLOW_ATTR_ALL_DEFAULT, .num_of_specs = 0, .port = rxq->priv->port, .flags = 0 }; if (rxq->priv->vf) return 0; DEBUG("%p: enabling promiscuous mode", (void *)rxq); if (rxq->promisc_flow != NULL) return EBUSY; errno = 0; flow = ibv_create_flow(rxq->qp, &attr); if (flow == NULL) { /* It's not clear whether errno is always set in this case. */ ERROR("%p: flow configuration failed, errno=%d: %s", (void *)rxq, errno, (errno ? strerror(errno) : "Unknown error")); if (errno) return errno; return EINVAL; } rxq->promisc_flow = flow; DEBUG("%p: promiscuous mode enabled", (void *)rxq); return 0; } /** * Disable promiscuous mode in a RX queue. * * @param rxq * Pointer to RX queue structure. */ static void rxq_promiscuous_disable(struct rxq *rxq) { if (rxq->priv->vf) return; DEBUG("%p: disabling promiscuous mode", (void *)rxq); if (rxq->promisc_flow == NULL) return; claim_zero(ibv_destroy_flow(rxq->promisc_flow)); rxq->promisc_flow = NULL; DEBUG("%p: promiscuous mode disabled", (void *)rxq); } /** * Clean up a RX queue. * * Destroy objects, free allocated memory and reset the structure for reuse. * * @param rxq * Pointer to RX queue structure. */ static void rxq_cleanup(struct rxq *rxq) { struct ibv_exp_release_intf_params params; DEBUG("cleaning up %p", (void *)rxq); if (rxq->sp) rxq_free_elts_sp(rxq); else rxq_free_elts(rxq); if (rxq->if_qp != NULL) { assert(rxq->priv != NULL); assert(rxq->priv->ctx != NULL); assert(rxq->qp != NULL); params = (struct ibv_exp_release_intf_params){ .comp_mask = 0, }; claim_zero(ibv_exp_release_intf(rxq->priv->ctx, rxq->if_qp, ¶ms)); } if (rxq->if_cq != NULL) { assert(rxq->priv != NULL); assert(rxq->priv->ctx != NULL); assert(rxq->cq != NULL); params = (struct ibv_exp_release_intf_params){ .comp_mask = 0, }; claim_zero(ibv_exp_release_intf(rxq->priv->ctx, rxq->if_cq, ¶ms)); } if (rxq->qp != NULL) { rxq_promiscuous_disable(rxq); rxq_allmulticast_disable(rxq); rxq_mac_addrs_del(rxq); claim_zero(ibv_destroy_qp(rxq->qp)); } if (rxq->cq != NULL) claim_zero(ibv_destroy_cq(rxq->cq)); if (rxq->rd != NULL) { struct ibv_exp_destroy_res_domain_attr attr = { .comp_mask = 0, }; assert(rxq->priv != NULL); assert(rxq->priv->ctx != NULL); claim_zero(ibv_exp_destroy_res_domain(rxq->priv->ctx, rxq->rd, &attr)); } if (rxq->mr != NULL) claim_zero(ibv_dereg_mr(rxq->mr)); memset(rxq, 0, sizeof(*rxq)); } #ifdef RTE_NEXT_ABI /** * Translate RX completion flags to packet type. * * @param flags * RX completion flags returned by poll_length_flags(). * * @return * Packet type for struct rte_mbuf. */ static inline uint32_t rxq_cq_to_pkt_type(uint32_t flags) { uint32_t pkt_type; if (flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) pkt_type = TRANSPOSE(flags, IBV_EXP_CQ_RX_OUTER_IPV4_PACKET, RTE_PTYPE_L3_IPV4) | TRANSPOSE(flags, IBV_EXP_CQ_RX_OUTER_IPV6_PACKET, RTE_PTYPE_L3_IPV6) | TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV4_PACKET, RTE_PTYPE_INNER_L3_IPV4) | TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV6_PACKET, RTE_PTYPE_INNER_L3_IPV6); else pkt_type = TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV4_PACKET, RTE_PTYPE_L3_IPV4) | TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV6_PACKET, RTE_PTYPE_L3_IPV6); return pkt_type; } #endif /* RTE_NEXT_ABI */ /** * Translate RX completion flags to offload flags. * * @param[in] rxq * Pointer to RX queue structure. * @param flags * RX completion flags returned by poll_length_flags(). * * @return * Offload flags (ol_flags) for struct rte_mbuf. */ static inline uint32_t rxq_cq_to_ol_flags(const struct rxq *rxq, uint32_t flags) { uint32_t ol_flags = 0; #ifndef RTE_NEXT_ABI ol_flags = TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV4_PACKET, PKT_RX_IPV4_HDR) | TRANSPOSE(flags, IBV_EXP_CQ_RX_IPV6_PACKET, PKT_RX_IPV6_HDR); #endif if (rxq->csum) ol_flags |= TRANSPOSE(~flags, IBV_EXP_CQ_RX_IP_CSUM_OK, PKT_RX_IP_CKSUM_BAD) | TRANSPOSE(~flags, IBV_EXP_CQ_RX_TCP_UDP_CSUM_OK, PKT_RX_L4_CKSUM_BAD); /* * PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD are used in place * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional * (its value is 0). */ if ((flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) && (rxq->csum_l2tun)) ol_flags |= #ifndef RTE_NEXT_ABI TRANSPOSE(flags, IBV_EXP_CQ_RX_OUTER_IPV4_PACKET, PKT_RX_TUNNEL_IPV4_HDR) | TRANSPOSE(flags, IBV_EXP_CQ_RX_OUTER_IPV6_PACKET, PKT_RX_TUNNEL_IPV6_HDR) | #endif TRANSPOSE(~flags, IBV_EXP_CQ_RX_OUTER_IP_CSUM_OK, PKT_RX_IP_CKSUM_BAD) | TRANSPOSE(~flags, IBV_EXP_CQ_RX_OUTER_TCP_UDP_CSUM_OK, PKT_RX_L4_CKSUM_BAD); return ol_flags; } static uint16_t mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n); /** * DPDK callback for RX with scattered packets support. * * @param dpdk_rxq * Generic pointer to RX queue structure. * @param[out] pkts * Array to store received packets. * @param pkts_n * Maximum number of packets in array. * * @return * Number of packets successfully received (<= pkts_n). */ static uint16_t mlx4_rx_burst_sp(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) { struct rxq *rxq = (struct rxq *)dpdk_rxq; struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp; const unsigned int elts_n = rxq->elts_n; unsigned int elts_head = rxq->elts_head; struct ibv_recv_wr head; struct ibv_recv_wr **next = &head.next; struct ibv_recv_wr *bad_wr; unsigned int i; unsigned int pkts_ret = 0; int ret; if (unlikely(!rxq->sp)) return mlx4_rx_burst(dpdk_rxq, pkts, pkts_n); if (unlikely(elts == NULL)) /* See RTE_DEV_CMD_SET_MTU. */ return 0; for (i = 0; (i != pkts_n); ++i) { struct rxq_elt_sp *elt = &(*elts)[elts_head]; struct ibv_recv_wr *wr = &elt->wr; uint64_t wr_id = wr->wr_id; unsigned int len; unsigned int pkt_buf_len; struct rte_mbuf *pkt_buf = NULL; /* Buffer returned in pkts. */ struct rte_mbuf **pkt_buf_next = &pkt_buf; unsigned int seg_headroom = RTE_PKTMBUF_HEADROOM; unsigned int j = 0; uint32_t flags; /* Sanity checks. */ #ifdef NDEBUG (void)wr_id; #endif assert(wr_id < rxq->elts_n); assert(wr->sg_list == elt->sges); assert(wr->num_sge == elemof(elt->sges)); assert(elts_head < rxq->elts_n); assert(rxq->elts_head < rxq->elts_n); ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL, &flags); if (unlikely(ret < 0)) { struct ibv_wc wc; int wcs_n; DEBUG("rxq=%p, poll_length() failed (ret=%d)", (void *)rxq, ret); /* ibv_poll_cq() must be used in case of failure. */ wcs_n = ibv_poll_cq(rxq->cq, 1, &wc); if (unlikely(wcs_n == 0)) break; if (unlikely(wcs_n < 0)) { DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)", (void *)rxq, wcs_n); break; } assert(wcs_n == 1); if (unlikely(wc.status != IBV_WC_SUCCESS)) { /* Whatever, just repost the offending WR. */ DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work" " completion status (%d): %s", (void *)rxq, wc.wr_id, wc.status, ibv_wc_status_str(wc.status)); #ifdef MLX4_PMD_SOFT_COUNTERS /* Increment dropped packets counter. */ ++rxq->stats.idropped; #endif /* Link completed WRs together for repost. */ *next = wr; next = &wr->next; goto repost; } ret = wc.byte_len; } if (ret == 0) break; len = ret; pkt_buf_len = len; /* Link completed WRs together for repost. */ *next = wr; next = &wr->next; /* * Replace spent segments with new ones, concatenate and * return them as pkt_buf. */ while (1) { struct ibv_sge *sge = &elt->sges[j]; struct rte_mbuf *seg = elt->bufs[j]; struct rte_mbuf *rep; unsigned int seg_tailroom; /* * Fetch initial bytes of packet descriptor into a * cacheline while allocating rep. */ rte_prefetch0(seg); rep = __rte_mbuf_raw_alloc(rxq->mp); if (unlikely(rep == NULL)) { /* * Unable to allocate a replacement mbuf, * repost WR. */ DEBUG("rxq=%p, wr_id=%" PRIu64 ":" " can't allocate a new mbuf", (void *)rxq, wr_id); if (pkt_buf != NULL) { *pkt_buf_next = NULL; rte_pktmbuf_free(pkt_buf); } /* Increase out of memory counters. */ ++rxq->stats.rx_nombuf; ++rxq->priv->dev->data->rx_mbuf_alloc_failed; goto repost; } #ifndef NDEBUG /* Poison user-modifiable fields in rep. */ NEXT(rep) = (void *)((uintptr_t)-1); SET_DATA_OFF(rep, 0xdead); DATA_LEN(rep) = 0xd00d; PKT_LEN(rep) = 0xdeadd00d; NB_SEGS(rep) = 0x2a; PORT(rep) = 0x2a; rep->ol_flags = -1; #endif assert(rep->buf_len == seg->buf_len); assert(rep->buf_len == rxq->mb_len); /* Reconfigure sge to use rep instead of seg. */ assert(sge->lkey == rxq->mr->lkey); sge->addr = ((uintptr_t)rep->buf_addr + seg_headroom); elt->bufs[j] = rep; ++j; /* Update pkt_buf if it's the first segment, or link * seg to the previous one and update pkt_buf_next. */ *pkt_buf_next = seg; pkt_buf_next = &NEXT(seg); /* Update seg information. */ seg_tailroom = (seg->buf_len - seg_headroom); assert(sge->length == seg_tailroom); SET_DATA_OFF(seg, seg_headroom); if (likely(len <= seg_tailroom)) { /* Last segment. */ DATA_LEN(seg) = len; PKT_LEN(seg) = len; /* Sanity check. */ assert(rte_pktmbuf_headroom(seg) == seg_headroom); assert(rte_pktmbuf_tailroom(seg) == (seg_tailroom - len)); break; } DATA_LEN(seg) = seg_tailroom; PKT_LEN(seg) = seg_tailroom; /* Sanity check. */ assert(rte_pktmbuf_headroom(seg) == seg_headroom); assert(rte_pktmbuf_tailroom(seg) == 0); /* Fix len and clear headroom for next segments. */ len -= seg_tailroom; seg_headroom = 0; } /* Update head and tail segments. */ *pkt_buf_next = NULL; assert(pkt_buf != NULL); assert(j != 0); NB_SEGS(pkt_buf) = j; PORT(pkt_buf) = rxq->port_id; PKT_LEN(pkt_buf) = pkt_buf_len; #ifdef RTE_NEXT_ABI pkt_buf->packet_type = rxq_cq_to_pkt_type(flags); #endif pkt_buf->ol_flags = rxq_cq_to_ol_flags(rxq, flags); /* Return packet. */ *(pkts++) = pkt_buf; ++pkts_ret; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increase bytes counter. */ rxq->stats.ibytes += pkt_buf_len; #endif repost: if (++elts_head >= elts_n) elts_head = 0; continue; } if (unlikely(i == 0)) return 0; *next = NULL; /* Repost WRs. */ #ifdef DEBUG_RECV DEBUG("%p: reposting %d WRs", (void *)rxq, i); #endif ret = ibv_post_recv(rxq->qp, head.next, &bad_wr); if (unlikely(ret)) { /* Inability to repost WRs is fatal. */ DEBUG("%p: ibv_post_recv(): failed for WR %p: %s", (void *)rxq->priv, (void *)bad_wr, strerror(ret)); abort(); } rxq->elts_head = elts_head; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increase packets counter. */ rxq->stats.ipackets += pkts_ret; #endif return pkts_ret; } /** * DPDK callback for RX. * * The following function is the same as mlx4_rx_burst_sp(), except it doesn't * manage scattered packets. Improves performance when MRU is lower than the * size of the first segment. * * @param dpdk_rxq * Generic pointer to RX queue structure. * @param[out] pkts * Array to store received packets. * @param pkts_n * Maximum number of packets in array. * * @return * Number of packets successfully received (<= pkts_n). */ static uint16_t mlx4_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) { struct rxq *rxq = (struct rxq *)dpdk_rxq; struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp; const unsigned int elts_n = rxq->elts_n; unsigned int elts_head = rxq->elts_head; struct ibv_sge sges[pkts_n]; unsigned int i; unsigned int pkts_ret = 0; int ret; if (unlikely(rxq->sp)) return mlx4_rx_burst_sp(dpdk_rxq, pkts, pkts_n); for (i = 0; (i != pkts_n); ++i) { struct rxq_elt *elt = &(*elts)[elts_head]; struct ibv_recv_wr *wr = &elt->wr; uint64_t wr_id = wr->wr_id; unsigned int len; struct rte_mbuf *seg = (void *)((uintptr_t)elt->sge.addr - WR_ID(wr_id).offset); struct rte_mbuf *rep; uint32_t flags; /* Sanity checks. */ assert(WR_ID(wr_id).id < rxq->elts_n); assert(wr->sg_list == &elt->sge); assert(wr->num_sge == 1); assert(elts_head < rxq->elts_n); assert(rxq->elts_head < rxq->elts_n); ret = rxq->if_cq->poll_length_flags(rxq->cq, NULL, NULL, &flags); if (unlikely(ret < 0)) { struct ibv_wc wc; int wcs_n; DEBUG("rxq=%p, poll_length() failed (ret=%d)", (void *)rxq, ret); /* ibv_poll_cq() must be used in case of failure. */ wcs_n = ibv_poll_cq(rxq->cq, 1, &wc); if (unlikely(wcs_n == 0)) break; if (unlikely(wcs_n < 0)) { DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)", (void *)rxq, wcs_n); break; } assert(wcs_n == 1); if (unlikely(wc.status != IBV_WC_SUCCESS)) { /* Whatever, just repost the offending WR. */ DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work" " completion status (%d): %s", (void *)rxq, wc.wr_id, wc.status, ibv_wc_status_str(wc.status)); #ifdef MLX4_PMD_SOFT_COUNTERS /* Increment dropped packets counter. */ ++rxq->stats.idropped; #endif /* Add SGE to array for repost. */ sges[i] = elt->sge; goto repost; } ret = wc.byte_len; } if (ret == 0) break; len = ret; /* * Fetch initial bytes of packet descriptor into a * cacheline while allocating rep. */ rte_prefetch0(seg); rep = __rte_mbuf_raw_alloc(rxq->mp); if (unlikely(rep == NULL)) { /* * Unable to allocate a replacement mbuf, * repost WR. */ DEBUG("rxq=%p, wr_id=%" PRIu32 ":" " can't allocate a new mbuf", (void *)rxq, WR_ID(wr_id).id); /* Increase out of memory counters. */ ++rxq->stats.rx_nombuf; ++rxq->priv->dev->data->rx_mbuf_alloc_failed; goto repost; } /* Reconfigure sge to use rep instead of seg. */ elt->sge.addr = (uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM; assert(elt->sge.lkey == rxq->mr->lkey); WR_ID(wr->wr_id).offset = (((uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM) - (uintptr_t)rep); assert(WR_ID(wr->wr_id).id == WR_ID(wr_id).id); /* Add SGE to array for repost. */ sges[i] = elt->sge; /* Update seg information. */ SET_DATA_OFF(seg, RTE_PKTMBUF_HEADROOM); NB_SEGS(seg) = 1; PORT(seg) = rxq->port_id; NEXT(seg) = NULL; PKT_LEN(seg) = len; DATA_LEN(seg) = len; #ifdef RTE_NEXT_ABI seg->packet_type = rxq_cq_to_pkt_type(flags); #endif seg->ol_flags = rxq_cq_to_ol_flags(rxq, flags); /* Return packet. */ *(pkts++) = seg; ++pkts_ret; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increase bytes counter. */ rxq->stats.ibytes += len; #endif repost: if (++elts_head >= elts_n) elts_head = 0; continue; } if (unlikely(i == 0)) return 0; /* Repost WRs. */ #ifdef DEBUG_RECV DEBUG("%p: reposting %u WRs", (void *)rxq, i); #endif ret = rxq->if_qp->recv_burst(rxq->qp, sges, i); if (unlikely(ret)) { /* Inability to repost WRs is fatal. */ DEBUG("%p: recv_burst(): failed (ret=%d)", (void *)rxq->priv, ret); abort(); } rxq->elts_head = elts_head; #ifdef MLX4_PMD_SOFT_COUNTERS /* Increase packets counter. */ rxq->stats.ipackets += pkts_ret; #endif return pkts_ret; } /** * Allocate a Queue Pair. * Optionally setup inline receive if supported. * * @param priv * Pointer to private structure. * @param cq * Completion queue to associate with QP. * @param desc * Number of descriptors in QP (hint only). * * @return * QP pointer or NULL in case of error. */ static struct ibv_qp * rxq_setup_qp(struct priv *priv, struct ibv_cq *cq, uint16_t desc, struct ibv_exp_res_domain *rd) { struct ibv_exp_qp_init_attr attr = { /* CQ to be associated with the send queue. */ .send_cq = cq, /* CQ to be associated with the receive queue. */ .recv_cq = cq, .cap = { /* Max number of outstanding WRs. */ .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ? priv->device_attr.max_qp_wr : desc), /* Max number of scatter/gather elements in a WR. */ .max_recv_sge = ((priv->device_attr.max_sge < MLX4_PMD_SGE_WR_N) ? priv->device_attr.max_sge : MLX4_PMD_SGE_WR_N), }, .qp_type = IBV_QPT_RAW_PACKET, .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD | IBV_EXP_QP_INIT_ATTR_RES_DOMAIN), .pd = priv->pd, .res_domain = rd, }; #ifdef INLINE_RECV attr.max_inl_recv = priv->inl_recv_size; attr.comp_mask |= IBV_EXP_QP_INIT_ATTR_INL_RECV; #endif return ibv_exp_create_qp(priv->ctx, &attr); } #ifdef RSS_SUPPORT /** * Allocate a RSS Queue Pair. * Optionally setup inline receive if supported. * * @param priv * Pointer to private structure. * @param cq * Completion queue to associate with QP. * @param desc * Number of descriptors in QP (hint only). * @param parent * If nonzero, create a parent QP, otherwise a child. * * @return * QP pointer or NULL in case of error. */ static struct ibv_qp * rxq_setup_qp_rss(struct priv *priv, struct ibv_cq *cq, uint16_t desc, int parent, struct ibv_exp_res_domain *rd) { struct ibv_exp_qp_init_attr attr = { /* CQ to be associated with the send queue. */ .send_cq = cq, /* CQ to be associated with the receive queue. */ .recv_cq = cq, .cap = { /* Max number of outstanding WRs. */ .max_recv_wr = ((priv->device_attr.max_qp_wr < desc) ? priv->device_attr.max_qp_wr : desc), /* Max number of scatter/gather elements in a WR. */ .max_recv_sge = ((priv->device_attr.max_sge < MLX4_PMD_SGE_WR_N) ? priv->device_attr.max_sge : MLX4_PMD_SGE_WR_N), }, .qp_type = IBV_QPT_RAW_PACKET, .comp_mask = (IBV_EXP_QP_INIT_ATTR_PD | IBV_EXP_QP_INIT_ATTR_RES_DOMAIN | IBV_EXP_QP_INIT_ATTR_QPG), .pd = priv->pd, .res_domain = rd, }; #ifdef INLINE_RECV attr.max_inl_recv = priv->inl_recv_size, attr.comp_mask |= IBV_EXP_QP_INIT_ATTR_INL_RECV; #endif if (parent) { attr.qpg.qpg_type = IBV_EXP_QPG_PARENT; /* TSS isn't necessary. */ attr.qpg.parent_attrib.tss_child_count = 0; attr.qpg.parent_attrib.rss_child_count = priv->rxqs_n; DEBUG("initializing parent RSS queue"); } else { attr.qpg.qpg_type = IBV_EXP_QPG_CHILD_RX; attr.qpg.qpg_parent = priv->rxq_parent.qp; DEBUG("initializing child RSS queue"); } return ibv_exp_create_qp(priv->ctx, &attr); } #endif /* RSS_SUPPORT */ /** * Reconfigure a RX queue with new parameters. * * rxq_rehash() does not allocate mbufs, which, if not done from the right * thread (such as a control thread), may corrupt the pool. * In case of failure, the queue is left untouched. * * @param dev * Pointer to Ethernet device structure. * @param rxq * RX queue pointer. * * @return * 0 on success, errno value on failure. */ static int rxq_rehash(struct rte_eth_dev *dev, struct rxq *rxq) { struct priv *priv = rxq->priv; struct rxq tmpl = *rxq; unsigned int mbuf_n; unsigned int desc_n; struct rte_mbuf **pool; unsigned int i, k; struct ibv_exp_qp_attr mod; struct ibv_recv_wr *bad_wr; int err; int parent = (rxq == &priv->rxq_parent); if (parent) { ERROR("%p: cannot rehash parent queue %p", (void *)dev, (void *)rxq); return EINVAL; } DEBUG("%p: rehashing queue %p", (void *)dev, (void *)rxq); /* Number of descriptors and mbufs currently allocated. */ desc_n = (tmpl.elts_n * (tmpl.sp ? MLX4_PMD_SGE_WR_N : 1)); mbuf_n = desc_n; /* Toggle RX checksum offload if hardware supports it. */ if (priv->hw_csum) { tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; rxq->csum = tmpl.csum; } if (priv->hw_csum_l2tun) { tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; rxq->csum_l2tun = tmpl.csum_l2tun; } /* Enable scattered packets support for this queue if necessary. */ if ((dev->data->dev_conf.rxmode.jumbo_frame) && (dev->data->dev_conf.rxmode.max_rx_pkt_len > (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) { tmpl.sp = 1; desc_n /= MLX4_PMD_SGE_WR_N; } else tmpl.sp = 0; DEBUG("%p: %s scattered packets support (%u WRs)", (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc_n); /* If scatter mode is the same as before, nothing to do. */ if (tmpl.sp == rxq->sp) { DEBUG("%p: nothing to do", (void *)dev); return 0; } /* Remove attached flows if RSS is disabled (no parent queue). */ if (!priv->rss) { rxq_allmulticast_disable(&tmpl); rxq_promiscuous_disable(&tmpl); rxq_mac_addrs_del(&tmpl); /* Update original queue in case of failure. */ rxq->allmulti_flow = tmpl.allmulti_flow; rxq->promisc_flow = tmpl.promisc_flow; memcpy(rxq->mac_configured, tmpl.mac_configured, sizeof(rxq->mac_configured)); memcpy(rxq->mac_flow, tmpl.mac_flow, sizeof(rxq->mac_flow)); } /* From now on, any failure will render the queue unusable. * Reinitialize QP. */ mod = (struct ibv_exp_qp_attr){ .qp_state = IBV_QPS_RESET }; err = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE); if (err) { ERROR("%p: cannot reset QP: %s", (void *)dev, strerror(err)); assert(err > 0); return err; } err = ibv_resize_cq(tmpl.cq, desc_n); if (err) { ERROR("%p: cannot resize CQ: %s", (void *)dev, strerror(err)); assert(err > 0); return err; } mod = (struct ibv_exp_qp_attr){ /* Move the QP to this state. */ .qp_state = IBV_QPS_INIT, /* Primary port number. */ .port_num = priv->port }; err = ibv_exp_modify_qp(tmpl.qp, &mod, (IBV_EXP_QP_STATE | #ifdef RSS_SUPPORT (parent ? IBV_EXP_QP_GROUP_RSS : 0) | #endif /* RSS_SUPPORT */ IBV_EXP_QP_PORT)); if (err) { ERROR("%p: QP state to IBV_QPS_INIT failed: %s", (void *)dev, strerror(err)); assert(err > 0); return err; }; /* Reconfigure flows. Do not care for errors. */ if (!priv->rss) { rxq_mac_addrs_add(&tmpl); if (priv->promisc) rxq_promiscuous_enable(&tmpl); if (priv->allmulti) rxq_allmulticast_enable(&tmpl); /* Update original queue in case of failure. */ rxq->allmulti_flow = tmpl.allmulti_flow; rxq->promisc_flow = tmpl.promisc_flow; memcpy(rxq->mac_configured, tmpl.mac_configured, sizeof(rxq->mac_configured)); memcpy(rxq->mac_flow, tmpl.mac_flow, sizeof(rxq->mac_flow)); } /* Allocate pool. */ pool = rte_malloc(__func__, (mbuf_n * sizeof(*pool)), 0); if (pool == NULL) { ERROR("%p: cannot allocate memory", (void *)dev); return ENOBUFS; } /* Snatch mbufs from original queue. */ k = 0; if (rxq->sp) { struct rxq_elt_sp (*elts)[rxq->elts_n] = rxq->elts.sp; for (i = 0; (i != elemof(*elts)); ++i) { struct rxq_elt_sp *elt = &(*elts)[i]; unsigned int j; for (j = 0; (j != elemof(elt->bufs)); ++j) { assert(elt->bufs[j] != NULL); pool[k++] = elt->bufs[j]; } } } else { struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts.no_sp; for (i = 0; (i != elemof(*elts)); ++i) { struct rxq_elt *elt = &(*elts)[i]; struct rte_mbuf *buf = (void *) ((uintptr_t)elt->sge.addr - WR_ID(elt->wr.wr_id).offset); assert(WR_ID(elt->wr.wr_id).id == i); pool[k++] = buf; } } assert(k == mbuf_n); tmpl.elts_n = 0; tmpl.elts.sp = NULL; assert((void *)&tmpl.elts.sp == (void *)&tmpl.elts.no_sp); err = ((tmpl.sp) ? rxq_alloc_elts_sp(&tmpl, desc_n, pool) : rxq_alloc_elts(&tmpl, desc_n, pool)); if (err) { ERROR("%p: cannot reallocate WRs, aborting", (void *)dev); rte_free(pool); assert(err > 0); return err; } assert(tmpl.elts_n == desc_n); assert(tmpl.elts.sp != NULL); rte_free(pool); /* Clean up original data. */ rxq->elts_n = 0; rte_free(rxq->elts.sp); rxq->elts.sp = NULL; /* Post WRs. */ err = ibv_post_recv(tmpl.qp, (tmpl.sp ? &(*tmpl.elts.sp)[0].wr : &(*tmpl.elts.no_sp)[0].wr), &bad_wr); if (err) { ERROR("%p: ibv_post_recv() failed for WR %p: %s", (void *)dev, (void *)bad_wr, strerror(err)); goto skip_rtr; } mod = (struct ibv_exp_qp_attr){ .qp_state = IBV_QPS_RTR }; err = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE); if (err) ERROR("%p: QP state to IBV_QPS_RTR failed: %s", (void *)dev, strerror(err)); skip_rtr: *rxq = tmpl; assert(err >= 0); return err; } /** * Configure a RX queue. * * @param dev * Pointer to Ethernet device structure. * @param rxq * Pointer to RX queue structure. * @param desc * Number of descriptors to configure in queue. * @param socket * NUMA socket on which memory must be allocated. * @param[in] conf * Thresholds parameters. * @param mp * Memory pool for buffer allocations. * * @return * 0 on success, errno value on failure. */ static int rxq_setup(struct rte_eth_dev *dev, struct rxq *rxq, uint16_t desc, unsigned int socket, const struct rte_eth_rxconf *conf, struct rte_mempool *mp) { struct priv *priv = dev->data->dev_private; struct rxq tmpl = { .priv = priv, .mp = mp, .socket = socket }; struct ibv_exp_qp_attr mod; union { struct ibv_exp_query_intf_params params; struct ibv_exp_cq_init_attr cq; struct ibv_exp_res_domain_init_attr rd; } attr; enum ibv_exp_query_intf_status status; struct ibv_recv_wr *bad_wr; struct rte_mbuf *buf; int ret = 0; int parent = (rxq == &priv->rxq_parent); (void)conf; /* Thresholds configuration (ignored). */ /* * If this is a parent queue, hardware must support RSS and * RSS must be enabled. */ assert((!parent) || ((priv->hw_rss) && (priv->rss))); if (parent) { /* Even if unused, ibv_create_cq() requires at least one * descriptor. */ desc = 1; goto skip_mr; } if ((desc == 0) || (desc % MLX4_PMD_SGE_WR_N)) { ERROR("%p: invalid number of RX descriptors (must be a" " multiple of %d)", (void *)dev, MLX4_PMD_SGE_WR_N); return EINVAL; } /* Get mbuf length. */ buf = rte_pktmbuf_alloc(mp); if (buf == NULL) { ERROR("%p: unable to allocate mbuf", (void *)dev); return ENOMEM; } tmpl.mb_len = buf->buf_len; assert((rte_pktmbuf_headroom(buf) + rte_pktmbuf_tailroom(buf)) == tmpl.mb_len); assert(rte_pktmbuf_headroom(buf) == RTE_PKTMBUF_HEADROOM); rte_pktmbuf_free(buf); /* Toggle RX checksum offload if hardware supports it. */ if (priv->hw_csum) tmpl.csum = !!dev->data->dev_conf.rxmode.hw_ip_checksum; if (priv->hw_csum_l2tun) tmpl.csum_l2tun = !!dev->data->dev_conf.rxmode.hw_ip_checksum; /* Enable scattered packets support for this queue if necessary. */ if ((dev->data->dev_conf.rxmode.jumbo_frame) && (dev->data->dev_conf.rxmode.max_rx_pkt_len > (tmpl.mb_len - RTE_PKTMBUF_HEADROOM))) { tmpl.sp = 1; desc /= MLX4_PMD_SGE_WR_N; } DEBUG("%p: %s scattered packets support (%u WRs)", (void *)dev, (tmpl.sp ? "enabling" : "disabling"), desc); /* Use the entire RX mempool as the memory region. */ tmpl.mr = ibv_reg_mr(priv->pd, (void *)mp->elt_va_start, (mp->elt_va_end - mp->elt_va_start), (IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE)); if (tmpl.mr == NULL) { ret = EINVAL; ERROR("%p: MR creation failure: %s", (void *)dev, strerror(ret)); goto error; } skip_mr: attr.rd = (struct ibv_exp_res_domain_init_attr){ .comp_mask = (IBV_EXP_RES_DOMAIN_THREAD_MODEL | IBV_EXP_RES_DOMAIN_MSG_MODEL), .thread_model = IBV_EXP_THREAD_SINGLE, .msg_model = IBV_EXP_MSG_HIGH_BW, }; tmpl.rd = ibv_exp_create_res_domain(priv->ctx, &attr.rd); if (tmpl.rd == NULL) { ret = ENOMEM; ERROR("%p: RD creation failure: %s", (void *)dev, strerror(ret)); goto error; } attr.cq = (struct ibv_exp_cq_init_attr){ .comp_mask = IBV_EXP_CQ_INIT_ATTR_RES_DOMAIN, .res_domain = tmpl.rd, }; tmpl.cq = ibv_exp_create_cq(priv->ctx, desc, NULL, NULL, 0, &attr.cq); if (tmpl.cq == NULL) { ret = ENOMEM; ERROR("%p: CQ creation failure: %s", (void *)dev, strerror(ret)); goto error; } DEBUG("priv->device_attr.max_qp_wr is %d", priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d", priv->device_attr.max_sge); #ifdef RSS_SUPPORT if (priv->rss) tmpl.qp = rxq_setup_qp_rss(priv, tmpl.cq, desc, parent, tmpl.rd); else #endif /* RSS_SUPPORT */ tmpl.qp = rxq_setup_qp(priv, tmpl.cq, desc, tmpl.rd); if (tmpl.qp == NULL) { ret = (errno ? errno : EINVAL); ERROR("%p: QP creation failure: %s", (void *)dev, strerror(ret)); goto error; } mod = (struct ibv_exp_qp_attr){ /* Move the QP to this state. */ .qp_state = IBV_QPS_INIT, /* Primary port number. */ .port_num = priv->port }; ret = ibv_exp_modify_qp(tmpl.qp, &mod, (IBV_EXP_QP_STATE | #ifdef RSS_SUPPORT (parent ? IBV_EXP_QP_GROUP_RSS : 0) | #endif /* RSS_SUPPORT */ IBV_EXP_QP_PORT)); if (ret) { ERROR("%p: QP state to IBV_QPS_INIT failed: %s", (void *)dev, strerror(ret)); goto error; } if ((parent) || (!priv->rss)) { /* Configure MAC and broadcast addresses. */ ret = rxq_mac_addrs_add(&tmpl); if (ret) { ERROR("%p: QP flow attachment failed: %s", (void *)dev, strerror(ret)); goto error; } } /* Allocate descriptors for RX queues, except for the RSS parent. */ if (parent) goto skip_alloc; if (tmpl.sp) ret = rxq_alloc_elts_sp(&tmpl, desc, NULL); else ret = rxq_alloc_elts(&tmpl, desc, NULL); if (ret) { ERROR("%p: RXQ allocation failed: %s", (void *)dev, strerror(ret)); goto error; } ret = ibv_post_recv(tmpl.qp, (tmpl.sp ? &(*tmpl.elts.sp)[0].wr : &(*tmpl.elts.no_sp)[0].wr), &bad_wr); if (ret) { ERROR("%p: ibv_post_recv() failed for WR %p: %s", (void *)dev, (void *)bad_wr, strerror(ret)); goto error; } skip_alloc: mod = (struct ibv_exp_qp_attr){ .qp_state = IBV_QPS_RTR }; ret = ibv_exp_modify_qp(tmpl.qp, &mod, IBV_EXP_QP_STATE); if (ret) { ERROR("%p: QP state to IBV_QPS_RTR failed: %s", (void *)dev, strerror(ret)); goto error; } /* Save port ID. */ tmpl.port_id = dev->data->port_id; DEBUG("%p: RTE port ID: %u", (void *)rxq, tmpl.port_id); attr.params = (struct ibv_exp_query_intf_params){ .intf_scope = IBV_EXP_INTF_GLOBAL, .intf = IBV_EXP_INTF_CQ, .obj = tmpl.cq, }; tmpl.if_cq = ibv_exp_query_intf(priv->ctx, &attr.params, &status); if (tmpl.if_cq == NULL) { ERROR("%p: CQ interface family query failed with status %d", (void *)dev, status); goto error; } attr.params = (struct ibv_exp_query_intf_params){ .intf_scope = IBV_EXP_INTF_GLOBAL, .intf = IBV_EXP_INTF_QP_BURST, .obj = tmpl.qp, }; tmpl.if_qp = ibv_exp_query_intf(priv->ctx, &attr.params, &status); if (tmpl.if_qp == NULL) { ERROR("%p: QP interface family query failed with status %d", (void *)dev, status); goto error; } /* Clean up rxq in case we're reinitializing it. */ DEBUG("%p: cleaning-up old rxq just in case", (void *)rxq); rxq_cleanup(rxq); *rxq = tmpl; DEBUG("%p: rxq updated with %p", (void *)rxq, (void *)&tmpl); assert(ret == 0); return 0; error: rxq_cleanup(&tmpl); assert(ret > 0); return ret; } /** * DPDK callback to configure a RX queue. * * @param dev * Pointer to Ethernet device structure. * @param idx * RX queue index. * @param desc * Number of descriptors to configure in queue. * @param socket * NUMA socket on which memory must be allocated. * @param[in] conf * Thresholds parameters. * @param mp * Memory pool for buffer allocations. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, unsigned int socket, const struct rte_eth_rxconf *conf, struct rte_mempool *mp) { struct priv *priv = dev->data->dev_private; struct rxq *rxq = (*priv->rxqs)[idx]; int ret; priv_lock(priv); DEBUG("%p: configuring queue %u for %u descriptors", (void *)dev, idx, desc); if (idx >= priv->rxqs_n) { ERROR("%p: queue index out of range (%u >= %u)", (void *)dev, idx, priv->rxqs_n); priv_unlock(priv); return -EOVERFLOW; } if (rxq != NULL) { DEBUG("%p: reusing already allocated queue index %u (%p)", (void *)dev, idx, (void *)rxq); if (priv->started) { priv_unlock(priv); return -EEXIST; } (*priv->rxqs)[idx] = NULL; rxq_cleanup(rxq); } else { rxq = rte_calloc_socket("RXQ", 1, sizeof(*rxq), 0, socket); if (rxq == NULL) { ERROR("%p: unable to allocate queue index %u", (void *)dev, idx); priv_unlock(priv); return -ENOMEM; } } ret = rxq_setup(dev, rxq, desc, socket, conf, mp); if (ret) rte_free(rxq); else { rxq->stats.idx = idx; DEBUG("%p: adding RX queue %p to list", (void *)dev, (void *)rxq); (*priv->rxqs)[idx] = rxq; /* Update receive callback. */ if (rxq->sp) dev->rx_pkt_burst = mlx4_rx_burst_sp; else dev->rx_pkt_burst = mlx4_rx_burst; } priv_unlock(priv); return -ret; } /** * DPDK callback to release a RX queue. * * @param dpdk_rxq * Generic RX queue pointer. */ static void mlx4_rx_queue_release(void *dpdk_rxq) { struct rxq *rxq = (struct rxq *)dpdk_rxq; struct priv *priv; unsigned int i; if (rxq == NULL) return; priv = rxq->priv; priv_lock(priv); assert(rxq != &priv->rxq_parent); for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] == rxq) { DEBUG("%p: removing RX queue %p from list", (void *)priv->dev, (void *)rxq); (*priv->rxqs)[i] = NULL; break; } rxq_cleanup(rxq); rte_free(rxq); priv_unlock(priv); } /** * DPDK callback to start the device. * * Simulate device start by attaching all configured flows. * * @param dev * Pointer to Ethernet device structure. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_dev_start(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i = 0; unsigned int r; struct rxq *rxq; priv_lock(priv); if (priv->started) { priv_unlock(priv); return 0; } DEBUG("%p: attaching configured flows to all RX queues", (void *)dev); priv->started = 1; if (priv->rss) { rxq = &priv->rxq_parent; r = 1; } else { rxq = (*priv->rxqs)[0]; r = priv->rxqs_n; } /* Iterate only once when RSS is enabled. */ do { int ret; /* Ignore nonexistent RX queues. */ if (rxq == NULL) continue; ret = rxq_mac_addrs_add(rxq); if (!ret && priv->promisc) ret = rxq_promiscuous_enable(rxq); if (!ret && priv->allmulti) ret = rxq_allmulticast_enable(rxq); if (!ret) continue; WARN("%p: QP flow attachment failed: %s", (void *)dev, strerror(ret)); /* Rollback. */ while (i != 0) { rxq = (*priv->rxqs)[--i]; if (rxq != NULL) { rxq_allmulticast_disable(rxq); rxq_promiscuous_disable(rxq); rxq_mac_addrs_del(rxq); } } priv->started = 0; return -ret; } while ((--r) && ((rxq = (*priv->rxqs)[++i]), i)); priv_unlock(priv); return 0; } /** * DPDK callback to stop the device. * * Simulate device stop by detaching all configured flows. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_dev_stop(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i = 0; unsigned int r; struct rxq *rxq; priv_lock(priv); if (!priv->started) { priv_unlock(priv); return; } DEBUG("%p: detaching flows from all RX queues", (void *)dev); priv->started = 0; if (priv->rss) { rxq = &priv->rxq_parent; r = 1; } else { rxq = (*priv->rxqs)[0]; r = priv->rxqs_n; } /* Iterate only once when RSS is enabled. */ do { /* Ignore nonexistent RX queues. */ if (rxq == NULL) continue; rxq_allmulticast_disable(rxq); rxq_promiscuous_disable(rxq); rxq_mac_addrs_del(rxq); } while ((--r) && ((rxq = (*priv->rxqs)[++i]), i)); priv_unlock(priv); } /** * Dummy DPDK callback for TX. * * This function is used to temporarily replace the real callback during * unsafe control operations on the queue, or in case of error. * * @param dpdk_txq * Generic pointer to TX queue structure. * @param[in] pkts * Packets to transmit. * @param pkts_n * Number of packets in array. * * @return * Number of packets successfully transmitted (<= pkts_n). */ static uint16_t removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) { (void)dpdk_txq; (void)pkts; (void)pkts_n; return 0; } /** * Dummy DPDK callback for RX. * * This function is used to temporarily replace the real callback during * unsafe control operations on the queue, or in case of error. * * @param dpdk_rxq * Generic pointer to RX queue structure. * @param[out] pkts * Array to store received packets. * @param pkts_n * Maximum number of packets in array. * * @return * Number of packets successfully received (<= pkts_n). */ static uint16_t removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) { (void)dpdk_rxq; (void)pkts; (void)pkts_n; return 0; } /** * DPDK callback to close the device. * * Destroy all queues and objects, free memory. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_dev_close(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; void *tmp; unsigned int i; priv_lock(priv); DEBUG("%p: closing device \"%s\"", (void *)dev, ((priv->ctx != NULL) ? priv->ctx->device->name : "")); /* Prevent crashes when queues are still in use. This is unfortunately * still required for DPDK 1.3 because some programs (such as testpmd) * never release them before closing the device. */ dev->rx_pkt_burst = removed_rx_burst; dev->tx_pkt_burst = removed_tx_burst; if (priv->rxqs != NULL) { /* XXX race condition if mlx4_rx_burst() is still running. */ usleep(1000); for (i = 0; (i != priv->rxqs_n); ++i) { tmp = (*priv->rxqs)[i]; if (tmp == NULL) continue; (*priv->rxqs)[i] = NULL; rxq_cleanup(tmp); rte_free(tmp); } priv->rxqs_n = 0; priv->rxqs = NULL; } if (priv->txqs != NULL) { /* XXX race condition if mlx4_tx_burst() is still running. */ usleep(1000); for (i = 0; (i != priv->txqs_n); ++i) { tmp = (*priv->txqs)[i]; if (tmp == NULL) continue; (*priv->txqs)[i] = NULL; txq_cleanup(tmp); rte_free(tmp); } priv->txqs_n = 0; priv->txqs = NULL; } if (priv->rss) rxq_cleanup(&priv->rxq_parent); if (priv->pd != NULL) { assert(priv->ctx != NULL); claim_zero(ibv_dealloc_pd(priv->pd)); claim_zero(ibv_close_device(priv->ctx)); } else assert(priv->ctx == NULL); priv_unlock(priv); memset(priv, 0, sizeof(*priv)); } /** * DPDK callback to get information about the device. * * @param dev * Pointer to Ethernet device structure. * @param[out] info * Info structure output buffer. */ static void mlx4_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) { struct priv *priv = dev->data->dev_private; unsigned int max; priv_lock(priv); /* FIXME: we should ask the device for these values. */ info->min_rx_bufsize = 32; info->max_rx_pktlen = 65536; /* * Since we need one CQ per QP, the limit is the minimum number * between the two values. */ max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ? priv->device_attr.max_qp : priv->device_attr.max_cq); /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ if (max >= 65535) max = 65535; info->max_rx_queues = max; info->max_tx_queues = max; info->max_mac_addrs = elemof(priv->mac); info->rx_offload_capa = (priv->hw_csum ? (DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM) : 0); info->tx_offload_capa = (priv->hw_csum ? (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM) : 0); priv_unlock(priv); } /** * DPDK callback to get device statistics. * * @param dev * Pointer to Ethernet device structure. * @param[out] stats * Stats structure output buffer. */ static void mlx4_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct priv *priv = dev->data->dev_private; struct rte_eth_stats tmp = {0}; unsigned int i; unsigned int idx; priv_lock(priv); /* Add software counters. */ for (i = 0; (i != priv->rxqs_n); ++i) { struct rxq *rxq = (*priv->rxqs)[i]; if (rxq == NULL) continue; idx = rxq->stats.idx; if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { #ifdef MLX4_PMD_SOFT_COUNTERS tmp.q_ipackets[idx] += rxq->stats.ipackets; tmp.q_ibytes[idx] += rxq->stats.ibytes; #endif tmp.q_errors[idx] += (rxq->stats.idropped + rxq->stats.rx_nombuf); } #ifdef MLX4_PMD_SOFT_COUNTERS tmp.ipackets += rxq->stats.ipackets; tmp.ibytes += rxq->stats.ibytes; #endif tmp.ierrors += rxq->stats.idropped; tmp.rx_nombuf += rxq->stats.rx_nombuf; } for (i = 0; (i != priv->txqs_n); ++i) { struct txq *txq = (*priv->txqs)[i]; if (txq == NULL) continue; idx = txq->stats.idx; if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { #ifdef MLX4_PMD_SOFT_COUNTERS tmp.q_opackets[idx] += txq->stats.opackets; tmp.q_obytes[idx] += txq->stats.obytes; #endif tmp.q_errors[idx] += txq->stats.odropped; } #ifdef MLX4_PMD_SOFT_COUNTERS tmp.opackets += txq->stats.opackets; tmp.obytes += txq->stats.obytes; #endif tmp.oerrors += txq->stats.odropped; } #ifndef MLX4_PMD_SOFT_COUNTERS /* FIXME: retrieve and add hardware counters. */ #endif *stats = tmp; priv_unlock(priv); } /** * DPDK callback to clear device statistics. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_stats_reset(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i; unsigned int idx; priv_lock(priv); for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; idx = (*priv->rxqs)[i]->stats.idx; (*priv->rxqs)[i]->stats = (struct mlx4_rxq_stats){ .idx = idx }; } for (i = 0; (i != priv->txqs_n); ++i) { if ((*priv->txqs)[i] == NULL) continue; idx = (*priv->rxqs)[i]->stats.idx; (*priv->txqs)[i]->stats = (struct mlx4_txq_stats){ .idx = idx }; } #ifndef MLX4_PMD_SOFT_COUNTERS /* FIXME: reset hardware counters. */ #endif priv_unlock(priv); } /** * DPDK callback to remove a MAC address. * * @param dev * Pointer to Ethernet device structure. * @param index * MAC address index. */ static void mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) { struct priv *priv = dev->data->dev_private; priv_lock(priv); DEBUG("%p: removing MAC address from index %" PRIu32, (void *)dev, index); if (index >= MLX4_MAX_MAC_ADDRESSES) goto end; /* Refuse to remove the broadcast address, this one is special. */ if (!memcmp(priv->mac[index].addr_bytes, "\xff\xff\xff\xff\xff\xff", ETHER_ADDR_LEN)) goto end; priv_mac_addr_del(priv, index); end: priv_unlock(priv); } /** * DPDK callback to add a MAC address. * * @param dev * Pointer to Ethernet device structure. * @param mac_addr * MAC address to register. * @param index * MAC address index. * @param vmdq * VMDq pool index to associate address with (ignored). */ static void mlx4_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq) { struct priv *priv = dev->data->dev_private; (void)vmdq; priv_lock(priv); DEBUG("%p: adding MAC address at index %" PRIu32, (void *)dev, index); if (index >= MLX4_MAX_MAC_ADDRESSES) goto end; /* Refuse to add the broadcast address, this one is special. */ if (!memcmp(mac_addr->addr_bytes, "\xff\xff\xff\xff\xff\xff", ETHER_ADDR_LEN)) goto end; priv_mac_addr_add(priv, index, (const uint8_t (*)[ETHER_ADDR_LEN]) mac_addr->addr_bytes); end: priv_unlock(priv); } /** * DPDK callback to enable promiscuous mode. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_promiscuous_enable(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i; int ret; priv_lock(priv); if (priv->promisc) { priv_unlock(priv); return; } /* If device isn't started, this is all we need to do. */ if (!priv->started) goto end; if (priv->rss) { ret = rxq_promiscuous_enable(&priv->rxq_parent); if (ret) { priv_unlock(priv); return; } goto end; } for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; ret = rxq_promiscuous_enable((*priv->rxqs)[i]); if (!ret) continue; /* Failure, rollback. */ while (i != 0) if ((*priv->rxqs)[--i] != NULL) rxq_promiscuous_disable((*priv->rxqs)[i]); priv_unlock(priv); return; } end: priv->promisc = 1; priv_unlock(priv); } /** * DPDK callback to disable promiscuous mode. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_promiscuous_disable(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i; priv_lock(priv); if (!priv->promisc) { priv_unlock(priv); return; } if (priv->rss) { rxq_promiscuous_disable(&priv->rxq_parent); goto end; } for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] != NULL) rxq_promiscuous_disable((*priv->rxqs)[i]); end: priv->promisc = 0; priv_unlock(priv); } /** * DPDK callback to enable allmulti mode. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_allmulticast_enable(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i; int ret; priv_lock(priv); if (priv->allmulti) { priv_unlock(priv); return; } /* If device isn't started, this is all we need to do. */ if (!priv->started) goto end; if (priv->rss) { ret = rxq_allmulticast_enable(&priv->rxq_parent); if (ret) { priv_unlock(priv); return; } goto end; } for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; ret = rxq_allmulticast_enable((*priv->rxqs)[i]); if (!ret) continue; /* Failure, rollback. */ while (i != 0) if ((*priv->rxqs)[--i] != NULL) rxq_allmulticast_disable((*priv->rxqs)[i]); priv_unlock(priv); return; } end: priv->allmulti = 1; priv_unlock(priv); } /** * DPDK callback to disable allmulti mode. * * @param dev * Pointer to Ethernet device structure. */ static void mlx4_allmulticast_disable(struct rte_eth_dev *dev) { struct priv *priv = dev->data->dev_private; unsigned int i; priv_lock(priv); if (!priv->allmulti) { priv_unlock(priv); return; } if (priv->rss) { rxq_allmulticast_disable(&priv->rxq_parent); goto end; } for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] != NULL) rxq_allmulticast_disable((*priv->rxqs)[i]); end: priv->allmulti = 0; priv_unlock(priv); } /** * DPDK callback to retrieve physical link information (unlocked version). * * @param dev * Pointer to Ethernet device structure. * @param wait_to_complete * Wait for request completion (ignored). */ static int mlx4_link_update_unlocked(struct rte_eth_dev *dev, int wait_to_complete) { struct priv *priv = dev->data->dev_private; struct ethtool_cmd edata = { .cmd = ETHTOOL_GSET }; struct ifreq ifr; struct rte_eth_link dev_link; int link_speed = 0; (void)wait_to_complete; if (priv_ifreq(priv, SIOCGIFFLAGS, &ifr)) { WARN("ioctl(SIOCGIFFLAGS) failed: %s", strerror(errno)); return -1; } memset(&dev_link, 0, sizeof(dev_link)); dev_link.link_status = ((ifr.ifr_flags & IFF_UP) && (ifr.ifr_flags & IFF_RUNNING)); ifr.ifr_data = &edata; if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) { WARN("ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s", strerror(errno)); return -1; } link_speed = ethtool_cmd_speed(&edata); if (link_speed == -1) dev_link.link_speed = 0; else dev_link.link_speed = link_speed; dev_link.link_duplex = ((edata.duplex == DUPLEX_HALF) ? ETH_LINK_HALF_DUPLEX : ETH_LINK_FULL_DUPLEX); if (memcmp(&dev_link, &dev->data->dev_link, sizeof(dev_link))) { /* Link status changed. */ dev->data->dev_link = dev_link; return 0; } /* Link status is still the same. */ return -1; } /** * DPDK callback to retrieve physical link information. * * @param dev * Pointer to Ethernet device structure. * @param wait_to_complete * Wait for request completion (ignored). */ static int mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct priv *priv = dev->data->dev_private; int ret; priv_lock(priv); ret = mlx4_link_update_unlocked(dev, wait_to_complete); priv_unlock(priv); return ret; } /** * DPDK callback to change the MTU. * * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be * received). Use this as a hint to enable/disable scattered packets support * and improve performance when not needed. * Since failure is not an option, reconfiguring queues on the fly is not * recommended. * * @param dev * Pointer to Ethernet device structure. * @param in_mtu * New MTU. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) { struct priv *priv = dev->data->dev_private; int ret = 0; unsigned int i; uint16_t (*rx_func)(void *, struct rte_mbuf **, uint16_t) = mlx4_rx_burst; priv_lock(priv); /* Set kernel interface MTU first. */ if (priv_set_mtu(priv, mtu)) { ret = errno; WARN("cannot set port %u MTU to %u: %s", priv->port, mtu, strerror(ret)); goto out; } else DEBUG("adapter port %u MTU set to %u", priv->port, mtu); priv->mtu = mtu; /* Temporarily replace RX handler with a fake one, assuming it has not * been copied elsewhere. */ dev->rx_pkt_burst = removed_rx_burst; /* Make sure everyone has left mlx4_rx_burst() and uses * removed_rx_burst() instead. */ rte_wmb(); usleep(1000); /* Reconfigure each RX queue. */ for (i = 0; (i != priv->rxqs_n); ++i) { struct rxq *rxq = (*priv->rxqs)[i]; unsigned int max_frame_len; int sp; if (rxq == NULL) continue; /* Calculate new maximum frame length according to MTU and * toggle scattered support (sp) if necessary. */ max_frame_len = (priv->mtu + ETHER_HDR_LEN + (ETHER_MAX_VLAN_FRAME_LEN - ETHER_MAX_LEN)); sp = (max_frame_len > (rxq->mb_len - RTE_PKTMBUF_HEADROOM)); /* Provide new values to rxq_setup(). */ dev->data->dev_conf.rxmode.jumbo_frame = sp; dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame_len; ret = rxq_rehash(dev, rxq); if (ret) { /* Force SP RX if that queue requires it and abort. */ if (rxq->sp) rx_func = mlx4_rx_burst_sp; break; } /* Reenable non-RSS queue attributes. No need to check * for errors at this stage. */ if (!priv->rss) { rxq_mac_addrs_add(rxq); if (priv->promisc) rxq_promiscuous_enable(rxq); if (priv->allmulti) rxq_allmulticast_enable(rxq); } /* Scattered burst function takes priority. */ if (rxq->sp) rx_func = mlx4_rx_burst_sp; } /* Burst functions can now be called again. */ rte_wmb(); dev->rx_pkt_burst = rx_func; out: priv_unlock(priv); assert(ret >= 0); return -ret; } /** * DPDK callback to get flow control status. * * @param dev * Pointer to Ethernet device structure. * @param[out] fc_conf * Flow control output buffer. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct priv *priv = dev->data->dev_private; struct ifreq ifr; struct ethtool_pauseparam ethpause = { .cmd = ETHTOOL_GPAUSEPARAM }; int ret; ifr.ifr_data = ðpause; priv_lock(priv); if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) { ret = errno; WARN("ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM)" " failed: %s", strerror(ret)); goto out; } fc_conf->autoneg = ethpause.autoneg; if (ethpause.rx_pause && ethpause.tx_pause) fc_conf->mode = RTE_FC_FULL; else if (ethpause.rx_pause) fc_conf->mode = RTE_FC_RX_PAUSE; else if (ethpause.tx_pause) fc_conf->mode = RTE_FC_TX_PAUSE; else fc_conf->mode = RTE_FC_NONE; ret = 0; out: priv_unlock(priv); assert(ret >= 0); return -ret; } /** * DPDK callback to modify flow control parameters. * * @param dev * Pointer to Ethernet device structure. * @param[in] fc_conf * Flow control parameters. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct priv *priv = dev->data->dev_private; struct ifreq ifr; struct ethtool_pauseparam ethpause = { .cmd = ETHTOOL_SPAUSEPARAM }; int ret; ifr.ifr_data = ðpause; ethpause.autoneg = fc_conf->autoneg; if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || (fc_conf->mode & RTE_FC_RX_PAUSE)) ethpause.rx_pause = 1; else ethpause.rx_pause = 0; if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) || (fc_conf->mode & RTE_FC_TX_PAUSE)) ethpause.tx_pause = 1; else ethpause.tx_pause = 0; priv_lock(priv); if (priv_ifreq(priv, SIOCETHTOOL, &ifr)) { ret = errno; WARN("ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)" " failed: %s", strerror(ret)); goto out; } ret = 0; out: priv_unlock(priv); assert(ret >= 0); return -ret; } /** * Configure a VLAN filter. * * @param dev * Pointer to Ethernet device structure. * @param vlan_id * VLAN ID to filter. * @param on * Toggle filter. * * @return * 0 on success, errno value on failure. */ static int vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct priv *priv = dev->data->dev_private; unsigned int i; unsigned int j = -1; DEBUG("%p: %s VLAN filter ID %" PRIu16, (void *)dev, (on ? "enable" : "disable"), vlan_id); for (i = 0; (i != elemof(priv->vlan_filter)); ++i) { if (!priv->vlan_filter[i].enabled) { /* Unused index, remember it. */ j = i; continue; } if (priv->vlan_filter[i].id != vlan_id) continue; /* This VLAN ID is already known, use its index. */ j = i; break; } /* Check if there's room for another VLAN filter. */ if (j == (unsigned int)-1) return ENOMEM; /* * VLAN filters apply to all configured MAC addresses, flow * specifications must be reconfigured accordingly. */ priv->vlan_filter[j].id = vlan_id; if ((on) && (!priv->vlan_filter[j].enabled)) { /* * Filter is disabled, enable it. * Rehashing flows in all RX queues is necessary. */ if (priv->rss) rxq_mac_addrs_del(&priv->rxq_parent); else for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] != NULL) rxq_mac_addrs_del((*priv->rxqs)[i]); priv->vlan_filter[j].enabled = 1; if (priv->started) { if (priv->rss) rxq_mac_addrs_add(&priv->rxq_parent); else for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; rxq_mac_addrs_add((*priv->rxqs)[i]); } } } else if ((!on) && (priv->vlan_filter[j].enabled)) { /* * Filter is enabled, disable it. * Rehashing flows in all RX queues is necessary. */ if (priv->rss) rxq_mac_addrs_del(&priv->rxq_parent); else for (i = 0; (i != priv->rxqs_n); ++i) if ((*priv->rxqs)[i] != NULL) rxq_mac_addrs_del((*priv->rxqs)[i]); priv->vlan_filter[j].enabled = 0; if (priv->started) { if (priv->rss) rxq_mac_addrs_add(&priv->rxq_parent); else for (i = 0; (i != priv->rxqs_n); ++i) { if ((*priv->rxqs)[i] == NULL) continue; rxq_mac_addrs_add((*priv->rxqs)[i]); } } } return 0; } /** * DPDK callback to configure a VLAN filter. * * @param dev * Pointer to Ethernet device structure. * @param vlan_id * VLAN ID to filter. * @param on * Toggle filter. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct priv *priv = dev->data->dev_private; int ret; priv_lock(priv); ret = vlan_filter_set(dev, vlan_id, on); priv_unlock(priv); assert(ret >= 0); return -ret; } static const struct eth_dev_ops mlx4_dev_ops = { .dev_configure = mlx4_dev_configure, .dev_start = mlx4_dev_start, .dev_stop = mlx4_dev_stop, .dev_close = mlx4_dev_close, .promiscuous_enable = mlx4_promiscuous_enable, .promiscuous_disable = mlx4_promiscuous_disable, .allmulticast_enable = mlx4_allmulticast_enable, .allmulticast_disable = mlx4_allmulticast_disable, .link_update = mlx4_link_update, .stats_get = mlx4_stats_get, .stats_reset = mlx4_stats_reset, .queue_stats_mapping_set = NULL, .dev_infos_get = mlx4_dev_infos_get, .vlan_filter_set = mlx4_vlan_filter_set, .vlan_tpid_set = NULL, .vlan_strip_queue_set = NULL, .vlan_offload_set = NULL, .rx_queue_setup = mlx4_rx_queue_setup, .tx_queue_setup = mlx4_tx_queue_setup, .rx_queue_release = mlx4_rx_queue_release, .tx_queue_release = mlx4_tx_queue_release, .dev_led_on = NULL, .dev_led_off = NULL, .flow_ctrl_get = mlx4_dev_get_flow_ctrl, .flow_ctrl_set = mlx4_dev_set_flow_ctrl, .priority_flow_ctrl_set = NULL, .mac_addr_remove = mlx4_mac_addr_remove, .mac_addr_add = mlx4_mac_addr_add, .mtu_set = mlx4_dev_set_mtu, .udp_tunnel_add = NULL, .udp_tunnel_del = NULL, .fdir_add_signature_filter = NULL, .fdir_update_signature_filter = NULL, .fdir_remove_signature_filter = NULL, .fdir_add_perfect_filter = NULL, .fdir_update_perfect_filter = NULL, .fdir_remove_perfect_filter = NULL, .fdir_set_masks = NULL }; /** * Get PCI information from struct ibv_device. * * @param device * Pointer to Ethernet device structure. * @param[out] pci_addr * PCI bus address output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int mlx4_ibv_device_to_pci_addr(const struct ibv_device *device, struct rte_pci_addr *pci_addr) { FILE *file; char line[32]; MKSTR(path, "%s/device/uevent", device->ibdev_path); file = fopen(path, "rb"); if (file == NULL) return -1; while (fgets(line, sizeof(line), file) == line) { size_t len = strlen(line); int ret; /* Truncate long lines. */ if (len == (sizeof(line) - 1)) while (line[(len - 1)] != '\n') { ret = fgetc(file); if (ret == EOF) break; line[(len - 1)] = ret; } /* Extract information. */ if (sscanf(line, "PCI_SLOT_NAME=" "%" SCNx16 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", &pci_addr->domain, &pci_addr->bus, &pci_addr->devid, &pci_addr->function) == 4) { ret = 0; break; } } fclose(file); return 0; } /** * Get MAC address by querying netdevice. * * @param[in] priv * struct priv for the requested device. * @param[out] mac * MAC address output buffer. * * @return * 0 on success, -1 on failure and errno is set. */ static int priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN]) { struct ifreq request; if (priv_ifreq(priv, SIOCGIFHWADDR, &request)) return -1; memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); return 0; } /* Support up to 32 adapters. */ static struct { struct rte_pci_addr pci_addr; /* associated PCI address */ uint32_t ports; /* physical ports bitfield. */ } mlx4_dev[32]; /** * Get device index in mlx4_dev[] from PCI bus address. * * @param[in] pci_addr * PCI bus address to look for. * * @return * mlx4_dev[] index on success, -1 on failure. */ static int mlx4_dev_idx(struct rte_pci_addr *pci_addr) { unsigned int i; int ret = -1; assert(pci_addr != NULL); for (i = 0; (i != elemof(mlx4_dev)); ++i) { if ((mlx4_dev[i].pci_addr.domain == pci_addr->domain) && (mlx4_dev[i].pci_addr.bus == pci_addr->bus) && (mlx4_dev[i].pci_addr.devid == pci_addr->devid) && (mlx4_dev[i].pci_addr.function == pci_addr->function)) return i; if ((mlx4_dev[i].ports == 0) && (ret == -1)) ret = i; } return ret; } /** * Retrieve integer value from environment variable. * * @param[in] name * Environment variable name. * * @return * Integer value, 0 if the variable is not set. */ static int mlx4_getenv_int(const char *name) { const char *val = getenv(name); if (val == NULL) return 0; return atoi(val); } static struct eth_driver mlx4_driver; /** * DPDK callback to register a PCI device. * * This function creates an Ethernet device for each port of a given * PCI device. * * @param[in] pci_drv * PCI driver structure (mlx4_driver). * @param[in] pci_dev * PCI device information. * * @return * 0 on success, negative errno value on failure. */ static int mlx4_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) { struct ibv_device **list; struct ibv_device *ibv_dev; int err = 0; struct ibv_context *attr_ctx = NULL; struct ibv_device_attr device_attr; unsigned int vf; int idx; int i; (void)pci_drv; assert(pci_drv == &mlx4_driver.pci_drv); /* Get mlx4_dev[] index. */ idx = mlx4_dev_idx(&pci_dev->addr); if (idx == -1) { ERROR("this driver cannot support any more adapters"); return -ENOMEM; } DEBUG("using driver device index %d", idx); /* Save PCI address. */ mlx4_dev[idx].pci_addr = pci_dev->addr; list = ibv_get_device_list(&i); if (list == NULL) { assert(errno); if (errno == ENOSYS) { WARN("cannot list devices, is ib_uverbs loaded?"); return 0; } return -errno; } assert(i >= 0); /* * For each listed device, check related sysfs entry against * the provided PCI ID. */ while (i != 0) { struct rte_pci_addr pci_addr; --i; DEBUG("checking device \"%s\"", list[i]->name); if (mlx4_ibv_device_to_pci_addr(list[i], &pci_addr)) continue; if ((pci_dev->addr.domain != pci_addr.domain) || (pci_dev->addr.bus != pci_addr.bus) || (pci_dev->addr.devid != pci_addr.devid) || (pci_dev->addr.function != pci_addr.function)) continue; vf = (pci_dev->id.device_id == PCI_DEVICE_ID_MELLANOX_CONNECTX3VF); INFO("PCI information matches, using device \"%s\" (VF: %s)", list[i]->name, (vf ? "true" : "false")); attr_ctx = ibv_open_device(list[i]); err = errno; break; } if (attr_ctx == NULL) { ibv_free_device_list(list); switch (err) { case 0: WARN("cannot access device, is mlx4_ib loaded?"); return 0; case EINVAL: WARN("cannot use device, are drivers up to date?"); return 0; } assert(err > 0); return -err; } ibv_dev = list[i]; DEBUG("device opened"); if (ibv_query_device(attr_ctx, &device_attr)) goto error; INFO("%u port(s) detected", device_attr.phys_port_cnt); for (i = 0; i < device_attr.phys_port_cnt; i++) { uint32_t port = i + 1; /* ports are indexed from one */ uint32_t test = (1 << i); struct ibv_context *ctx = NULL; struct ibv_port_attr port_attr; struct ibv_pd *pd = NULL; struct priv *priv = NULL; struct rte_eth_dev *eth_dev; #ifdef HAVE_EXP_QUERY_DEVICE struct ibv_exp_device_attr exp_device_attr; #endif /* HAVE_EXP_QUERY_DEVICE */ struct ether_addr mac; #ifdef HAVE_EXP_QUERY_DEVICE exp_device_attr.comp_mask = IBV_EXP_DEVICE_ATTR_EXP_CAP_FLAGS; #ifdef RSS_SUPPORT exp_device_attr.comp_mask |= IBV_EXP_DEVICE_ATTR_RSS_TBL_SZ; #endif /* RSS_SUPPORT */ #endif /* HAVE_EXP_QUERY_DEVICE */ DEBUG("using port %u (%08" PRIx32 ")", port, test); ctx = ibv_open_device(ibv_dev); if (ctx == NULL) goto port_error; /* Check port status. */ err = ibv_query_port(ctx, port, &port_attr); if (err) { ERROR("port query failed: %s", strerror(err)); goto port_error; } if (port_attr.state != IBV_PORT_ACTIVE) WARN("bad state for port %d: \"%s\" (%d)", port, ibv_port_state_str(port_attr.state), port_attr.state); /* Allocate protection domain. */ pd = ibv_alloc_pd(ctx); if (pd == NULL) { ERROR("PD allocation failure"); err = ENOMEM; goto port_error; } mlx4_dev[idx].ports |= test; /* from rte_ethdev.c */ priv = rte_zmalloc("ethdev private structure", sizeof(*priv), RTE_CACHE_LINE_SIZE); if (priv == NULL) { ERROR("priv allocation failure"); err = ENOMEM; goto port_error; } priv->ctx = ctx; priv->device_attr = device_attr; priv->port = port; priv->pd = pd; priv->mtu = ETHER_MTU; #ifdef HAVE_EXP_QUERY_DEVICE if (ibv_exp_query_device(ctx, &exp_device_attr)) { ERROR("ibv_exp_query_device() failed"); goto port_error; } #ifdef RSS_SUPPORT if ((exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_QPG) && (exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_UD_RSS) && (exp_device_attr.comp_mask & IBV_EXP_DEVICE_ATTR_RSS_TBL_SZ) && (exp_device_attr.max_rss_tbl_sz > 0)) { priv->hw_qpg = 1; priv->hw_rss = 1; priv->max_rss_tbl_sz = exp_device_attr.max_rss_tbl_sz; } else { priv->hw_qpg = 0; priv->hw_rss = 0; priv->max_rss_tbl_sz = 0; } priv->hw_tss = !!(exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_UD_TSS); DEBUG("device flags: %s%s%s", (priv->hw_qpg ? "IBV_DEVICE_QPG " : ""), (priv->hw_tss ? "IBV_DEVICE_TSS " : ""), (priv->hw_rss ? "IBV_DEVICE_RSS " : "")); if (priv->hw_rss) DEBUG("maximum RSS indirection table size: %u", exp_device_attr.max_rss_tbl_sz); #endif /* RSS_SUPPORT */ priv->hw_csum = ((exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_RX_CSUM_TCP_UDP_PKT) && (exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_RX_CSUM_IP_PKT)); DEBUG("checksum offloading is %ssupported", (priv->hw_csum ? "" : "not ")); priv->hw_csum_l2tun = !!(exp_device_attr.exp_device_cap_flags & IBV_EXP_DEVICE_VXLAN_SUPPORT); DEBUG("L2 tunnel checksum offloads are %ssupported", (priv->hw_csum_l2tun ? "" : "not ")); #ifdef INLINE_RECV priv->inl_recv_size = mlx4_getenv_int("MLX4_INLINE_RECV_SIZE"); if (priv->inl_recv_size) { exp_device_attr.comp_mask = IBV_EXP_DEVICE_ATTR_INLINE_RECV_SZ; if (ibv_exp_query_device(ctx, &exp_device_attr)) { INFO("Couldn't query device for inline-receive" " capabilities."); priv->inl_recv_size = 0; } else { if ((unsigned)exp_device_attr.inline_recv_sz < priv->inl_recv_size) { INFO("Max inline-receive (%d) <" " requested inline-receive (%u)", exp_device_attr.inline_recv_sz, priv->inl_recv_size); priv->inl_recv_size = exp_device_attr.inline_recv_sz; } } INFO("Set inline receive size to %u", priv->inl_recv_size); } #endif /* INLINE_RECV */ #endif /* HAVE_EXP_QUERY_DEVICE */ (void)mlx4_getenv_int; priv->vf = vf; /* Configure the first MAC address by default. */ if (priv_get_mac(priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?" " (errno: %s)", strerror(errno)); goto port_error; } INFO("port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x", priv->port, mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); /* Register MAC and broadcast addresses. */ claim_zero(priv_mac_addr_add(priv, 0, (const uint8_t (*)[ETHER_ADDR_LEN]) mac.addr_bytes)); claim_zero(priv_mac_addr_add(priv, 1, &(const uint8_t [ETHER_ADDR_LEN]) { "\xff\xff\xff\xff\xff\xff" })); #ifndef NDEBUG { char ifname[IF_NAMESIZE]; if (priv_get_ifname(priv, &ifname) == 0) DEBUG("port %u ifname is \"%s\"", priv->port, ifname); else DEBUG("port %u ifname is unknown", priv->port); } #endif /* Get actual MTU if possible. */ priv_get_mtu(priv, &priv->mtu); DEBUG("port %u MTU is %u", priv->port, priv->mtu); /* from rte_ethdev.c */ { char name[RTE_ETH_NAME_MAX_LEN]; snprintf(name, sizeof(name), "%s port %u", ibv_get_device_name(ibv_dev), port); eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_PCI); } if (eth_dev == NULL) { ERROR("can not allocate rte ethdev"); err = ENOMEM; goto port_error; } eth_dev->data->dev_private = priv; eth_dev->pci_dev = pci_dev; eth_dev->driver = &mlx4_driver; eth_dev->data->rx_mbuf_alloc_failed = 0; eth_dev->data->mtu = ETHER_MTU; priv->dev = eth_dev; eth_dev->dev_ops = &mlx4_dev_ops; eth_dev->data->mac_addrs = priv->mac; /* Bring Ethernet device up. */ DEBUG("forcing Ethernet interface up"); priv_set_flags(priv, ~IFF_UP, IFF_UP); continue; port_error: rte_free(priv); if (pd) claim_zero(ibv_dealloc_pd(pd)); if (ctx) claim_zero(ibv_close_device(ctx)); break; } /* * XXX if something went wrong in the loop above, there is a resource * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as * long as the dpdk does not provide a way to deallocate a ethdev and a * way to enumerate the registered ethdevs to free the previous ones. */ /* no port found, complain */ if (!mlx4_dev[idx].ports) { err = ENODEV; goto error; } error: if (attr_ctx) claim_zero(ibv_close_device(attr_ctx)); if (list) ibv_free_device_list(list); assert(err >= 0); return -err; } static const struct rte_pci_id mlx4_pci_id_map[] = { { .vendor_id = PCI_VENDOR_ID_MELLANOX, .device_id = PCI_DEVICE_ID_MELLANOX_CONNECTX3, .subsystem_vendor_id = PCI_ANY_ID, .subsystem_device_id = PCI_ANY_ID }, { .vendor_id = PCI_VENDOR_ID_MELLANOX, .device_id = PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO, .subsystem_vendor_id = PCI_ANY_ID, .subsystem_device_id = PCI_ANY_ID }, { .vendor_id = PCI_VENDOR_ID_MELLANOX, .device_id = PCI_DEVICE_ID_MELLANOX_CONNECTX3VF, .subsystem_vendor_id = PCI_ANY_ID, .subsystem_device_id = PCI_ANY_ID }, { .vendor_id = 0 } }; static struct eth_driver mlx4_driver = { .pci_drv = { .name = MLX4_DRIVER_NAME, .id_table = mlx4_pci_id_map, .devinit = mlx4_pci_devinit, }, .dev_private_size = sizeof(struct priv) }; /** * Driver initialization routine. */ static int rte_mlx4_pmd_init(const char *name, const char *args) { (void)name; (void)args; /* * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use * huge pages. Calling ibv_fork_init() during init allows * applications to use fork() safely for purposes other than * using this PMD, which is not supported in forked processes. */ setenv("RDMAV_HUGEPAGES_SAFE", "1", 1); ibv_fork_init(); rte_eal_pci_register(&mlx4_driver.pci_drv); return 0; } static struct rte_driver rte_mlx4_driver = { .type = PMD_PDEV, .name = MLX4_DRIVER_NAME, .init = rte_mlx4_pmd_init, }; PMD_REGISTER_DRIVER(rte_mlx4_driver) ================================================ FILE: drivers/net/mlx4/mlx4.h ================================================ /*- * BSD LICENSE * * Copyright 2012-2015 6WIND S.A. * Copyright 2012 Mellanox. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_PMD_MLX4_H_ #define RTE_PMD_MLX4_H_ #include #include #include /* * Maximum number of simultaneous MAC addresses supported. * * According to ConnectX's Programmer Reference Manual: * The L2 Address Match is implemented by comparing a MAC/VLAN combination * of 128 MAC addresses and 127 VLAN values, comprising 128x127 possible * L2 addresses. */ #define MLX4_MAX_MAC_ADDRESSES 128 /* Maximum number of simultaneous VLAN filters supported. See above. */ #define MLX4_MAX_VLAN_IDS 127 /* Request send completion once in every 64 sends, might be less. */ #define MLX4_PMD_TX_PER_COMP_REQ 64 /* Maximum number of Scatter/Gather Elements per Work Request. */ #ifndef MLX4_PMD_SGE_WR_N #define MLX4_PMD_SGE_WR_N 4 #endif /* Maximum size for inline data. */ #ifndef MLX4_PMD_MAX_INLINE #define MLX4_PMD_MAX_INLINE 0 #endif /* * Maximum number of cached Memory Pools (MPs) per TX queue. Each RTE MP * from which buffers are to be transmitted will have to be mapped by this * driver to their own Memory Region (MR). This is a slow operation. * * This value is always 1 for RX queues. */ #ifndef MLX4_PMD_TX_MP_CACHE #define MLX4_PMD_TX_MP_CACHE 8 #endif /* * If defined, only use software counters. The PMD will never ask the hardware * for these, and many of them won't be available. */ #ifndef MLX4_PMD_SOFT_COUNTERS #define MLX4_PMD_SOFT_COUNTERS 1 #endif enum { PCI_VENDOR_ID_MELLANOX = 0x15b3, }; enum { PCI_DEVICE_ID_MELLANOX_CONNECTX3 = 0x1003, PCI_DEVICE_ID_MELLANOX_CONNECTX3VF = 0x1004, PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO = 0x1007, }; #define MLX4_DRIVER_NAME "librte_pmd_mlx4" /* Bit-field manipulation. */ #define BITFIELD_DECLARE(bf, type, size) \ type bf[(((size_t)(size) / (sizeof(type) * CHAR_BIT)) + \ !!((size_t)(size) % (sizeof(type) * CHAR_BIT)))] #define BITFIELD_DEFINE(bf, type, size) \ BITFIELD_DECLARE((bf), type, (size)) = { 0 } #define BITFIELD_SET(bf, b) \ (assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \ (void)((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] |= \ ((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT))))) #define BITFIELD_RESET(bf, b) \ (assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \ (void)((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] &= \ ~((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT))))) #define BITFIELD_ISSET(bf, b) \ (assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \ !!(((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] & \ ((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT)))))) /* Number of elements in array. */ #define elemof(a) (sizeof(a) / sizeof((a)[0])) /* Cast pointer p to structure member m to its parent structure of type t. */ #define containerof(p, t, m) ((t *)((uint8_t *)(p) - offsetof(t, m))) /* Branch prediction helpers. */ #ifndef likely #define likely(c) __builtin_expect(!!(c), 1) #endif #ifndef unlikely #define unlikely(c) __builtin_expect(!!(c), 0) #endif /* Debugging */ #ifndef NDEBUG #include #define DEBUG__(m, ...) \ (fprintf(stderr, "%s:%d: %s(): " m "%c", \ __FILE__, __LINE__, __func__, __VA_ARGS__), \ fflush(stderr), \ (void)0) /* * Save/restore errno around DEBUG__(). * XXX somewhat undefined behavior, but works. */ #define DEBUG_(...) \ (errno = ((int []){ \ *(volatile int *)&errno, \ (DEBUG__(__VA_ARGS__), 0) \ })[0]) #define DEBUG(...) DEBUG_(__VA_ARGS__, '\n') #define claim_zero(...) assert((__VA_ARGS__) == 0) #define claim_nonzero(...) assert((__VA_ARGS__) != 0) #define claim_positive(...) assert((__VA_ARGS__) >= 0) #else /* NDEBUG */ /* No-ops. */ #define DEBUG(...) (void)0 #define claim_zero(...) (__VA_ARGS__) #define claim_nonzero(...) (__VA_ARGS__) #define claim_positive(...) (__VA_ARGS__) #endif /* NDEBUG */ #endif /* RTE_PMD_MLX4_H_ */ ================================================ FILE: drivers/net/mpipe/Makefile ================================================ # # Copyright 2015 EZchip Semiconductor Ltd. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_pmd_mpipe.a CFLAGS += $(WERROR_FLAGS) -O3 EXPORT_MAP := rte_pmd_mpipe_version.map LIBABIVER := 1 SRCS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += mpipe_tilegx.c DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += lib/librte_net lib/librte_malloc include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/mpipe/mpipe_tilegx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 EZchip Semiconductor Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_MPIPE_PMD_DEBUG #define PMD_DEBUG_RX(...) RTE_LOG(DEBUG, PMD, __VA_ARGS__) #define PMD_DEBUG_TX(...) RTE_LOG(DEBUG, PMD, __VA_ARGS__) #else #define PMD_DEBUG_RX(...) #define PMD_DEBUG_TX(...) #endif #define MPIPE_MAX_CHANNELS 128 #define MPIPE_TX_MAX_QUEUES 128 #define MPIPE_RX_MAX_QUEUES 16 #define MPIPE_TX_DESCS 512 #define MPIPE_RX_BUCKETS 256 #define MPIPE_RX_STACK_SIZE 65536 #define MPIPE_RX_IP_ALIGN 2 #define MPIPE_BSM_ALIGN 128 #define MPIPE_LINK_UPDATE_TIMEOUT 10 /* s */ #define MPIPE_LINK_UPDATE_INTERVAL 100000 /* us */ struct mpipe_channel_config { int enable; int first_bucket; int num_buckets; int head_room; gxio_mpipe_rules_stacks_t stacks; }; struct mpipe_context { rte_spinlock_t lock; gxio_mpipe_context_t context; struct mpipe_channel_config channels[MPIPE_MAX_CHANNELS]; }; static struct mpipe_context mpipe_contexts[GXIO_MPIPE_INSTANCE_MAX]; static int mpipe_instances; /* Per queue statistics. */ struct mpipe_queue_stats { uint64_t packets, bytes, errors, nomem; }; /* Common tx/rx queue fields. */ struct mpipe_queue { struct mpipe_dev_priv *priv; /* "priv" data of its device. */ uint16_t nb_desc; /* Number of tx descriptors. */ uint16_t port_id; /* Device index. */ uint16_t stat_idx; /* Queue stats index. */ uint8_t queue_idx; /* Queue index. */ uint8_t link_status; /* 0 = link down. */ struct mpipe_queue_stats stats; /* Stat data for the queue. */ }; /* Transmit queue description. */ struct mpipe_tx_queue { struct mpipe_queue q; /* Common stuff. */ }; /* Receive queue description. */ struct mpipe_rx_queue { struct mpipe_queue q; /* Common stuff. */ gxio_mpipe_iqueue_t iqueue; /* mPIPE iqueue. */ gxio_mpipe_idesc_t *next_desc; /* Next idesc to process. */ int avail_descs; /* Number of available descs. */ void *rx_ring_mem; /* DMA ring memory. */ }; struct mpipe_dev_priv { gxio_mpipe_context_t *context; /* mPIPE context. */ gxio_mpipe_link_t link; /* mPIPE link for the device. */ gxio_mpipe_equeue_t equeue; /* mPIPE equeue. */ unsigned equeue_size; /* mPIPE equeue desc count. */ int instance; /* mPIPE instance. */ int ering; /* mPIPE eDMA ring. */ int stack; /* mPIPE buffer stack. */ int channel; /* Device channel. */ int port_id; /* DPDK port index. */ struct rte_eth_dev *eth_dev; /* DPDK device. */ struct rte_pci_device pci_dev; /* PCI device data. */ struct rte_mbuf **tx_comps; /* TX completion array. */ struct rte_mempool *rx_mpool; /* mpool used by the rx queues. */ unsigned rx_offset; /* Receive head room. */ unsigned rx_size_code; /* mPIPE rx buffer size code. */ unsigned rx_buffers; /* receive buffers on stack. */ int is_xaui:1, /* Is this an xgbe or gbe? */ initialized:1, /* Initialized port? */ running:1; /* Running port? */ struct ether_addr mac_addr; /* MAC address. */ unsigned nb_rx_queues; /* Configured tx queues. */ unsigned nb_tx_queues; /* Configured rx queues. */ int first_bucket; /* mPIPE bucket start index. */ int first_ring; /* mPIPE notif ring start index. */ int notif_group; /* mPIPE notif group. */ rte_atomic32_t dp_count; /* Active datapath thread count. */ int tx_stat_mapping[RTE_ETHDEV_QUEUE_STAT_CNTRS]; int rx_stat_mapping[RTE_ETHDEV_QUEUE_STAT_CNTRS]; }; #define mpipe_priv(dev) \ ((struct mpipe_dev_priv*)(dev)->data->dev_private) #define mpipe_name(priv) \ ((priv)->eth_dev->data->name) #define mpipe_rx_queue(priv, n) \ ((struct mpipe_rx_queue *)(priv)->eth_dev->data->rx_queues[n]) #define mpipe_tx_queue(priv, n) \ ((struct mpipe_tx_queue *)(priv)->eth_dev->data->tx_queues[n]) static void mpipe_xmit_flush(struct mpipe_dev_priv *priv); static void mpipe_recv_flush(struct mpipe_dev_priv *priv); static int mpipe_equeue_sizes[] = { [GXIO_MPIPE_EQUEUE_ENTRY_512] = 512, [GXIO_MPIPE_EQUEUE_ENTRY_2K] = 2048, [GXIO_MPIPE_EQUEUE_ENTRY_8K] = 8192, [GXIO_MPIPE_EQUEUE_ENTRY_64K] = 65536, }; static int mpipe_iqueue_sizes[] = { [GXIO_MPIPE_IQUEUE_ENTRY_128] = 128, [GXIO_MPIPE_IQUEUE_ENTRY_512] = 512, [GXIO_MPIPE_IQUEUE_ENTRY_2K] = 2048, [GXIO_MPIPE_IQUEUE_ENTRY_64K] = 65536, }; static int mpipe_buffer_sizes[] = { [GXIO_MPIPE_BUFFER_SIZE_128] = 128, [GXIO_MPIPE_BUFFER_SIZE_256] = 256, [GXIO_MPIPE_BUFFER_SIZE_512] = 512, [GXIO_MPIPE_BUFFER_SIZE_1024] = 1024, [GXIO_MPIPE_BUFFER_SIZE_1664] = 1664, [GXIO_MPIPE_BUFFER_SIZE_4096] = 4096, [GXIO_MPIPE_BUFFER_SIZE_10368] = 10368, [GXIO_MPIPE_BUFFER_SIZE_16384] = 16384, }; static gxio_mpipe_context_t * mpipe_context(int instance) { if (instance < 0 || instance >= mpipe_instances) return NULL; return &mpipe_contexts[instance].context; } static int mpipe_channel_config(int instance, int channel, struct mpipe_channel_config *config) { struct mpipe_channel_config *data; struct mpipe_context *context; gxio_mpipe_rules_t rules; int idx, rc = 0; if (instance < 0 || instance >= mpipe_instances || channel < 0 || channel >= MPIPE_MAX_CHANNELS) return -EINVAL; context = &mpipe_contexts[instance]; rte_spinlock_lock(&context->lock); gxio_mpipe_rules_init(&rules, &context->context); for (idx = 0; idx < MPIPE_MAX_CHANNELS; idx++) { data = (channel == idx) ? config : &context->channels[idx]; if (!data->enable) continue; rc = gxio_mpipe_rules_begin(&rules, data->first_bucket, data->num_buckets, &data->stacks); if (rc < 0) { goto done; } rc = gxio_mpipe_rules_add_channel(&rules, idx); if (rc < 0) { goto done; } rc = gxio_mpipe_rules_set_headroom(&rules, data->head_room); if (rc < 0) { goto done; } } rc = gxio_mpipe_rules_commit(&rules); if (rc == 0) { memcpy(&context->channels[channel], config, sizeof(*config)); } done: rte_spinlock_unlock(&context->lock); return rc; } static int mpipe_get_size_index(int *array, int count, int size, bool roundup) { int i, last = -1; for (i = 0; i < count && array[i] < size; i++) { if (array[i]) last = i; } if (roundup) return i < count ? (int)i : -ENOENT; else return last >= 0 ? last : -ENOENT; } static int mpipe_calc_size(int *array, int count, int size) { int index = mpipe_get_size_index(array, count, size, 1); return index < 0 ? index : array[index]; } static int mpipe_equeue_size(int size) { int result; result = mpipe_calc_size(mpipe_equeue_sizes, RTE_DIM(mpipe_equeue_sizes), size); return result; } static int mpipe_iqueue_size(int size) { int result; result = mpipe_calc_size(mpipe_iqueue_sizes, RTE_DIM(mpipe_iqueue_sizes), size); return result; } static int mpipe_buffer_size_index(int size) { int result; result = mpipe_get_size_index(mpipe_buffer_sizes, RTE_DIM(mpipe_buffer_sizes), size, 0); return result; } static inline int mpipe_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static inline int mpipe_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static void mpipe_infos_get(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info) { dev_info->min_rx_bufsize = 128; dev_info->max_rx_pktlen = 1518; dev_info->max_tx_queues = MPIPE_TX_MAX_QUEUES; dev_info->max_rx_queues = MPIPE_RX_MAX_QUEUES; dev_info->max_mac_addrs = 1; dev_info->rx_offload_capa = 0; dev_info->tx_offload_capa = 0; } static int mpipe_configure(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); if (dev->data->nb_tx_queues > MPIPE_TX_MAX_QUEUES) { RTE_LOG(ERR, PMD, "%s: Too many tx queues: %d > %d\n", mpipe_name(priv), dev->data->nb_tx_queues, MPIPE_TX_MAX_QUEUES); return -EINVAL; } priv->nb_tx_queues = dev->data->nb_tx_queues; if (dev->data->nb_rx_queues > MPIPE_RX_MAX_QUEUES) { RTE_LOG(ERR, PMD, "%s: Too many rx queues: %d > %d\n", mpipe_name(priv), dev->data->nb_rx_queues, MPIPE_RX_MAX_QUEUES); } priv->nb_rx_queues = dev->data->nb_rx_queues; return 0; } static inline int mpipe_link_compare(struct rte_eth_link *link1, struct rte_eth_link *link2) { return ((*(uint64_t *)link1 == *(uint64_t *)link2) ? -1 : 0); } static int mpipe_link_update(struct rte_eth_dev *dev, int wait_to_complete) { struct mpipe_dev_priv *priv = mpipe_priv(dev); struct rte_eth_link old, new; int64_t state, speed; int count, rc; memset(&old, 0, sizeof(old)); memset(&new, 0, sizeof(new)); mpipe_dev_atomic_read_link_status(dev, &old); for (count = 0, rc = 0; count < MPIPE_LINK_UPDATE_TIMEOUT; count++) { if (!priv->initialized) break; state = gxio_mpipe_link_get_attr(&priv->link, GXIO_MPIPE_LINK_CURRENT_STATE); if (state < 0) break; speed = state & GXIO_MPIPE_LINK_SPEED_MASK; if (speed == GXIO_MPIPE_LINK_1G) { new.link_speed = ETH_LINK_SPEED_1000; new.link_duplex = ETH_LINK_FULL_DUPLEX; new.link_status = 1; } else if (speed == GXIO_MPIPE_LINK_10G) { new.link_speed = ETH_LINK_SPEED_10000; new.link_duplex = ETH_LINK_FULL_DUPLEX; new.link_status = 1; } rc = mpipe_link_compare(&old, &new); if (rc == 0 || !wait_to_complete) break; rte_delay_us(MPIPE_LINK_UPDATE_INTERVAL); } mpipe_dev_atomic_write_link_status(dev, &new); return rc; } static int mpipe_set_link(struct rte_eth_dev *dev, int up) { struct mpipe_dev_priv *priv = mpipe_priv(dev); int rc; rc = gxio_mpipe_link_set_attr(&priv->link, GXIO_MPIPE_LINK_DESIRED_STATE, up ? GXIO_MPIPE_LINK_ANYSPEED : 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to set link %s.\n", mpipe_name(priv), up ? "up" : "down"); } else { mpipe_link_update(dev, 0); } return rc; } static int mpipe_set_link_up(struct rte_eth_dev *dev) { return mpipe_set_link(dev, 1); } static int mpipe_set_link_down(struct rte_eth_dev *dev) { return mpipe_set_link(dev, 0); } static inline void mpipe_dp_enter(struct mpipe_dev_priv *priv) { __insn_mtspr(SPR_DSTREAM_PF, 0); rte_atomic32_inc(&priv->dp_count); } static inline void mpipe_dp_exit(struct mpipe_dev_priv *priv) { rte_atomic32_dec(&priv->dp_count); } static inline void mpipe_dp_wait(struct mpipe_dev_priv *priv) { while (rte_atomic32_read(&priv->dp_count) != 0) { rte_pause(); } } static inline struct rte_mbuf * mpipe_recv_mbuf(struct mpipe_dev_priv *priv, gxio_mpipe_idesc_t *idesc, int in_port) { void *va = gxio_mpipe_idesc_get_va(idesc); uint16_t size = gxio_mpipe_idesc_get_xfer_size(idesc); struct rte_mbuf *mbuf = RTE_PTR_SUB(va, priv->rx_offset); rte_pktmbuf_reset(mbuf); mbuf->data_off = (uintptr_t)va - (uintptr_t)mbuf->buf_addr; mbuf->port = in_port; mbuf->data_len = size; mbuf->pkt_len = size; mbuf->hash.rss = gxio_mpipe_idesc_get_flow_hash(idesc); PMD_DEBUG_RX("%s: RX mbuf %p, buffer %p, buf_addr %p, size %d\n", mpipe_name(priv), mbuf, va, mbuf->buf_addr, size); return mbuf; } static inline void mpipe_recv_push(struct mpipe_dev_priv *priv, struct rte_mbuf *mbuf) { const int offset = RTE_PKTMBUF_HEADROOM + MPIPE_RX_IP_ALIGN; void *buf_addr = RTE_PTR_ADD(mbuf->buf_addr, offset); gxio_mpipe_push_buffer(priv->context, priv->stack, buf_addr); PMD_DEBUG_RX("%s: Pushed mbuf %p, buffer %p into stack %d\n", mpipe_name(priv), mbuf, buf_addr, priv->stack); } static inline void mpipe_recv_fill_stack(struct mpipe_dev_priv *priv, int count) { struct rte_mbuf *mbuf; int i; for (i = 0; i < count; i++) { mbuf = __rte_mbuf_raw_alloc(priv->rx_mpool); if (!mbuf) break; mpipe_recv_push(priv, mbuf); } priv->rx_buffers += count; PMD_DEBUG_RX("%s: Filled %d/%d buffers\n", mpipe_name(priv), i, count); } static inline void mpipe_recv_flush_stack(struct mpipe_dev_priv *priv) { const int offset = priv->rx_offset & ~RTE_MEMPOOL_ALIGN_MASK; uint8_t in_port = priv->port_id; struct rte_mbuf *mbuf; unsigned count; void *va; for (count = 0; count < priv->rx_buffers; count++) { va = gxio_mpipe_pop_buffer(priv->context, priv->stack); if (!va) break; mbuf = RTE_PTR_SUB(va, offset); PMD_DEBUG_RX("%s: Flushing mbuf %p, va %p\n", mpipe_name(priv), mbuf, va); mbuf->data_off = (uintptr_t)va - (uintptr_t)mbuf->buf_addr; mbuf->refcnt = 1; mbuf->nb_segs = 1; mbuf->port = in_port; mbuf->packet_type = 0; mbuf->data_len = 0; mbuf->pkt_len = 0; __rte_mbuf_raw_free(mbuf); } PMD_DEBUG_RX("%s: Returned %d/%d buffers\n", mpipe_name(priv), count, priv->rx_buffers); priv->rx_buffers -= count; } static void mpipe_register_segment(struct mpipe_dev_priv *priv, const struct rte_memseg *ms) { size_t size = ms->hugepage_sz; uint8_t *addr, *end; int rc; for (addr = ms->addr, end = addr + ms->len; addr < end; addr += size) { rc = gxio_mpipe_register_page(priv->context, priv->stack, addr, size, 0); if (rc < 0) break; } if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Could not register memseg @%p, %d.\n", mpipe_name(priv), ms->addr, rc); } else { RTE_LOG(DEBUG, PMD, "%s: Registered segment %p - %p\n", mpipe_name(priv), ms->addr, RTE_PTR_ADD(ms->addr, ms->len - 1)); } } static int mpipe_recv_init(struct mpipe_dev_priv *priv) { const struct rte_memseg *seg = rte_eal_get_physmem_layout(); size_t stack_size; void *stack_mem; int rc; if (!priv->rx_mpool) { RTE_LOG(ERR, PMD, "%s: No buffer pool.\n", mpipe_name(priv)); return -ENODEV; } /* Allocate one NotifRing for each queue. */ rc = gxio_mpipe_alloc_notif_rings(priv->context, MPIPE_RX_MAX_QUEUES, 0, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to allocate notif rings.\n", mpipe_name(priv)); return rc; } priv->first_ring = rc; /* Allocate a NotifGroup. */ rc = gxio_mpipe_alloc_notif_groups(priv->context, 1, 0, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to allocate rx group.\n", mpipe_name(priv)); return rc; } priv->notif_group = rc; /* Allocate required buckets. */ rc = gxio_mpipe_alloc_buckets(priv->context, MPIPE_RX_BUCKETS, 0, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to allocate buckets.\n", mpipe_name(priv)); return rc; } priv->first_bucket = rc; rc = gxio_mpipe_alloc_buffer_stacks(priv->context, 1, 0, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to allocate buffer stack.\n", mpipe_name(priv)); return rc; } priv->stack = rc; while (seg && seg->addr) mpipe_register_segment(priv, seg++); stack_size = gxio_mpipe_calc_buffer_stack_bytes(MPIPE_RX_STACK_SIZE); stack_mem = rte_zmalloc(NULL, stack_size, 65536); if (!stack_mem) { RTE_LOG(ERR, PMD, "%s: Failed to allocate buffer memory.\n", mpipe_name(priv)); return -ENOMEM; } else { RTE_LOG(DEBUG, PMD, "%s: Buffer stack memory %p - %p.\n", mpipe_name(priv), stack_mem, RTE_PTR_ADD(stack_mem, stack_size - 1)); } rc = gxio_mpipe_init_buffer_stack(priv->context, priv->stack, priv->rx_size_code, stack_mem, stack_size, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to initialize buffer stack.\n", mpipe_name(priv)); return rc; } return 0; } static int mpipe_xmit_init(struct mpipe_dev_priv *priv) { size_t ring_size; void *ring_mem; int rc; /* Allocate eDMA ring. */ rc = gxio_mpipe_alloc_edma_rings(priv->context, 1, 0, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to alloc tx ring.\n", mpipe_name(priv)); return rc; } priv->ering = rc; rc = mpipe_equeue_size(MPIPE_TX_DESCS); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Cannot allocate %d equeue descs.\n", mpipe_name(priv), (int)MPIPE_TX_DESCS); return -ENOMEM; } priv->equeue_size = rc; /* Initialize completion array. */ ring_size = sizeof(priv->tx_comps[0]) * priv->equeue_size; priv->tx_comps = rte_zmalloc(NULL, ring_size, RTE_CACHE_LINE_SIZE); if (!priv->tx_comps) { RTE_LOG(ERR, PMD, "%s: Failed to allocate egress comps.\n", mpipe_name(priv)); return -ENOMEM; } /* Allocate eDMA ring memory. */ ring_size = sizeof(gxio_mpipe_edesc_t) * priv->equeue_size; ring_mem = rte_zmalloc(NULL, ring_size, ring_size); if (!ring_mem) { RTE_LOG(ERR, PMD, "%s: Failed to allocate egress descs.\n", mpipe_name(priv)); return -ENOMEM; } else { RTE_LOG(DEBUG, PMD, "%s: eDMA ring memory %p - %p.\n", mpipe_name(priv), ring_mem, RTE_PTR_ADD(ring_mem, ring_size - 1)); } /* Initialize eDMA ring. */ rc = gxio_mpipe_equeue_init(&priv->equeue, priv->context, priv->ering, priv->channel, ring_mem, ring_size, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init equeue\n", mpipe_name(priv)); return rc; } return 0; } static int mpipe_link_init(struct mpipe_dev_priv *priv) { int rc; /* Open the link. */ rc = gxio_mpipe_link_open(&priv->link, priv->context, mpipe_name(priv), GXIO_MPIPE_LINK_AUTO_NONE); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to open link.\n", mpipe_name(priv)); return rc; } /* Get the channel index. */ rc = gxio_mpipe_link_channel(&priv->link); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Bad channel\n", mpipe_name(priv)); return rc; } priv->channel = rc; return 0; } static int mpipe_init(struct mpipe_dev_priv *priv) { int rc; if (priv->initialized) return 0; rc = mpipe_link_init(priv); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init link.\n", mpipe_name(priv)); return rc; } rc = mpipe_recv_init(priv); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init rx.\n", mpipe_name(priv)); return rc; } rc = mpipe_xmit_init(priv); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init tx.\n", mpipe_name(priv)); rte_free(priv); return rc; } priv->initialized = 1; return 0; } static int mpipe_start(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); struct mpipe_channel_config config; struct mpipe_rx_queue *rx_queue; struct rte_eth_link eth_link; unsigned queue, buffers = 0; size_t ring_size; void *ring_mem; int rc; memset(ð_link, 0, sizeof(eth_link)); mpipe_dev_atomic_write_link_status(dev, ð_link); rc = mpipe_init(priv); if (rc < 0) return rc; /* Initialize NotifRings. */ for (queue = 0; queue < priv->nb_rx_queues; queue++) { rx_queue = mpipe_rx_queue(priv, queue); ring_size = rx_queue->q.nb_desc * sizeof(gxio_mpipe_idesc_t); ring_mem = rte_malloc(NULL, ring_size, ring_size); if (!ring_mem) { RTE_LOG(ERR, PMD, "%s: Failed to alloc rx descs.\n", mpipe_name(priv)); return -ENOMEM; } else { RTE_LOG(DEBUG, PMD, "%s: iDMA ring %d memory %p - %p.\n", mpipe_name(priv), queue, ring_mem, RTE_PTR_ADD(ring_mem, ring_size - 1)); } rc = gxio_mpipe_iqueue_init(&rx_queue->iqueue, priv->context, priv->first_ring + queue, ring_mem, ring_size, 0); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init rx queue.\n", mpipe_name(priv)); return rc; } rx_queue->rx_ring_mem = ring_mem; buffers += rx_queue->q.nb_desc; } /* Initialize ingress NotifGroup and buckets. */ rc = gxio_mpipe_init_notif_group_and_buckets(priv->context, priv->notif_group, priv->first_ring, priv->nb_rx_queues, priv->first_bucket, MPIPE_RX_BUCKETS, GXIO_MPIPE_BUCKET_STATIC_FLOW_AFFINITY); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to init group and buckets.\n", mpipe_name(priv)); return rc; } /* Configure the classifier to deliver packets from this port. */ config.enable = 1; config.first_bucket = priv->first_bucket; config.num_buckets = MPIPE_RX_BUCKETS; memset(&config.stacks, 0xff, sizeof(config.stacks)); config.stacks.stacks[priv->rx_size_code] = priv->stack; config.head_room = priv->rx_offset & RTE_MEMPOOL_ALIGN_MASK; rc = mpipe_channel_config(priv->instance, priv->channel, &config); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to setup classifier.\n", mpipe_name(priv)); return rc; } /* Fill empty buffers into the buffer stack. */ mpipe_recv_fill_stack(priv, buffers); /* Bring up the link. */ mpipe_set_link_up(dev); /* Start xmit/recv on queues. */ for (queue = 0; queue < priv->nb_tx_queues; queue++) mpipe_tx_queue(priv, queue)->q.link_status = 1; for (queue = 0; queue < priv->nb_rx_queues; queue++) mpipe_rx_queue(priv, queue)->q.link_status = 1; priv->running = 1; return 0; } static void mpipe_stop(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); struct mpipe_channel_config config; unsigned queue; int rc; for (queue = 0; queue < priv->nb_tx_queues; queue++) mpipe_tx_queue(priv, queue)->q.link_status = 0; for (queue = 0; queue < priv->nb_rx_queues; queue++) mpipe_rx_queue(priv, queue)->q.link_status = 0; /* Make sure the link_status writes land. */ rte_wmb(); /* * Wait for link_status change to register with straggling datapath * threads. */ mpipe_dp_wait(priv); /* Bring down the link. */ mpipe_set_link_down(dev); /* Remove classifier rules. */ memset(&config, 0, sizeof(config)); rc = mpipe_channel_config(priv->instance, priv->channel, &config); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to stop classifier.\n", mpipe_name(priv)); } /* Flush completed xmit packets. */ mpipe_xmit_flush(priv); /* Flush buffer stacks. */ mpipe_recv_flush(priv); priv->running = 0; } static void mpipe_close(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); if (priv->running) mpipe_stop(dev); } static void mpipe_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct mpipe_dev_priv *priv = mpipe_priv(dev); struct mpipe_tx_queue *tx_queue; struct mpipe_rx_queue *rx_queue; unsigned i; uint16_t idx; memset(stats, 0, sizeof(*stats)); for (i = 0; i < priv->nb_tx_queues; i++) { tx_queue = mpipe_tx_queue(priv, i); stats->opackets += tx_queue->q.stats.packets; stats->obytes += tx_queue->q.stats.bytes; stats->oerrors += tx_queue->q.stats.errors; idx = tx_queue->q.stat_idx; if (idx != (uint16_t)-1) { stats->q_opackets[idx] += tx_queue->q.stats.packets; stats->q_obytes[idx] += tx_queue->q.stats.bytes; stats->q_errors[idx] += tx_queue->q.stats.errors; } } for (i = 0; i < priv->nb_rx_queues; i++) { rx_queue = mpipe_rx_queue(priv, i); stats->ipackets += rx_queue->q.stats.packets; stats->ibytes += rx_queue->q.stats.bytes; stats->ierrors += rx_queue->q.stats.errors; stats->rx_nombuf += rx_queue->q.stats.nomem; idx = rx_queue->q.stat_idx; if (idx != (uint16_t)-1) { stats->q_ipackets[idx] += rx_queue->q.stats.packets; stats->q_ibytes[idx] += rx_queue->q.stats.bytes; stats->q_errors[idx] += rx_queue->q.stats.errors; } } } static void mpipe_stats_reset(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); struct mpipe_tx_queue *tx_queue; struct mpipe_rx_queue *rx_queue; unsigned i; for (i = 0; i < priv->nb_tx_queues; i++) { tx_queue = mpipe_tx_queue(priv, i); memset(&tx_queue->q.stats, 0, sizeof(tx_queue->q.stats)); } for (i = 0; i < priv->nb_rx_queues; i++) { rx_queue = mpipe_rx_queue(priv, i); memset(&rx_queue->q.stats, 0, sizeof(rx_queue->q.stats)); } } static int mpipe_queue_stats_mapping_set(struct rte_eth_dev *dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx) { struct mpipe_dev_priv *priv = mpipe_priv(dev); if (is_rx) { priv->rx_stat_mapping[stat_idx] = queue_id; } else { priv->tx_stat_mapping[stat_idx] = queue_id; } return 0; } static int mpipe_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { struct mpipe_tx_queue *tx_queue = dev->data->tx_queues[queue_idx]; struct mpipe_dev_priv *priv = mpipe_priv(dev); uint16_t idx; tx_queue = rte_realloc(tx_queue, sizeof(*tx_queue), RTE_CACHE_LINE_SIZE); if (!tx_queue) { RTE_LOG(ERR, PMD, "%s: Failed to allocate TX queue.\n", mpipe_name(priv)); return -ENOMEM; } memset(&tx_queue->q, 0, sizeof(tx_queue->q)); tx_queue->q.priv = priv; tx_queue->q.queue_idx = queue_idx; tx_queue->q.port_id = dev->data->port_id; tx_queue->q.nb_desc = nb_desc; tx_queue->q.stat_idx = -1; for (idx = 0; idx < RTE_ETHDEV_QUEUE_STAT_CNTRS; idx++) { if (priv->tx_stat_mapping[idx] == queue_idx) tx_queue->q.stat_idx = idx; } dev->data->tx_queues[queue_idx] = tx_queue; return 0; } static void mpipe_tx_queue_release(void *_txq) { rte_free(_txq); } static int mpipe_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mp) { struct mpipe_rx_queue *rx_queue = dev->data->rx_queues[queue_idx]; struct mpipe_dev_priv *priv = mpipe_priv(dev); uint16_t idx; int size, rc; rc = mpipe_iqueue_size(nb_desc); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Cannot allocate %d iqueue descs.\n", mpipe_name(priv), (int)nb_desc); return -ENOMEM; } if (rc != nb_desc) { RTE_LOG(WARNING, PMD, "%s: Extending RX descs from %d to %d.\n", mpipe_name(priv), (int)nb_desc, rc); nb_desc = rc; } size = sizeof(*rx_queue); rx_queue = rte_realloc(rx_queue, size, RTE_CACHE_LINE_SIZE); if (!rx_queue) { RTE_LOG(ERR, PMD, "%s: Failed to allocate RX queue.\n", mpipe_name(priv)); return -ENOMEM; } memset(&rx_queue->q, 0, sizeof(rx_queue->q)); rx_queue->q.priv = priv; rx_queue->q.nb_desc = nb_desc; rx_queue->q.port_id = dev->data->port_id; rx_queue->q.queue_idx = queue_idx; if (!priv->rx_mpool) { int size = (rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM - MPIPE_RX_IP_ALIGN); priv->rx_offset = (sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(mp) + RTE_PKTMBUF_HEADROOM + MPIPE_RX_IP_ALIGN); if (size < 0) { RTE_LOG(ERR, PMD, "%s: Bad buffer size %d.\n", mpipe_name(priv), rte_pktmbuf_data_room_size(mp)); return -ENOMEM; } priv->rx_size_code = mpipe_buffer_size_index(size); priv->rx_mpool = mp; } if (priv->rx_mpool != mp) { RTE_LOG(WARNING, PMD, "%s: Ignoring multiple buffer pools.\n", mpipe_name(priv)); } rx_queue->q.stat_idx = -1; for (idx = 0; idx < RTE_ETHDEV_QUEUE_STAT_CNTRS; idx++) { if (priv->rx_stat_mapping[idx] == queue_idx) rx_queue->q.stat_idx = idx; } dev->data->rx_queues[queue_idx] = rx_queue; return 0; } static void mpipe_rx_queue_release(void *_rxq) { rte_free(_rxq); } #define MPIPE_XGBE_ENA_HASH_MULTI \ (1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__ENA_HASH_MULTI_SHIFT) #define MPIPE_XGBE_ENA_HASH_UNI \ (1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__ENA_HASH_UNI_SHIFT) #define MPIPE_XGBE_COPY_ALL \ (1UL << MPIPE_XAUI_RECEIVE_CONFIGURATION__COPY_ALL_SHIFT) #define MPIPE_GBE_ENA_MULTI_HASH \ (1UL << MPIPE_GBE_NETWORK_CONFIGURATION__MULTI_HASH_ENA_SHIFT) #define MPIPE_GBE_ENA_UNI_HASH \ (1UL << MPIPE_GBE_NETWORK_CONFIGURATION__UNI_HASH_ENA_SHIFT) #define MPIPE_GBE_COPY_ALL \ (1UL << MPIPE_GBE_NETWORK_CONFIGURATION__COPY_ALL_SHIFT) static void mpipe_promiscuous_enable(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); int64_t reg; int addr; if (priv->is_xaui) { addr = MPIPE_XAUI_RECEIVE_CONFIGURATION; reg = gxio_mpipe_link_mac_rd(&priv->link, addr); reg &= ~MPIPE_XGBE_ENA_HASH_MULTI; reg &= ~MPIPE_XGBE_ENA_HASH_UNI; reg |= MPIPE_XGBE_COPY_ALL; gxio_mpipe_link_mac_wr(&priv->link, addr, reg); } else { addr = MPIPE_GBE_NETWORK_CONFIGURATION; reg = gxio_mpipe_link_mac_rd(&priv->link, addr); reg &= ~MPIPE_GBE_ENA_MULTI_HASH; reg &= ~MPIPE_GBE_ENA_UNI_HASH; reg |= MPIPE_GBE_COPY_ALL; gxio_mpipe_link_mac_wr(&priv->link, addr, reg); } } static void mpipe_promiscuous_disable(struct rte_eth_dev *dev) { struct mpipe_dev_priv *priv = mpipe_priv(dev); int64_t reg; int addr; if (priv->is_xaui) { addr = MPIPE_XAUI_RECEIVE_CONFIGURATION; reg = gxio_mpipe_link_mac_rd(&priv->link, addr); reg |= MPIPE_XGBE_ENA_HASH_MULTI; reg |= MPIPE_XGBE_ENA_HASH_UNI; reg &= ~MPIPE_XGBE_COPY_ALL; gxio_mpipe_link_mac_wr(&priv->link, addr, reg); } else { addr = MPIPE_GBE_NETWORK_CONFIGURATION; reg = gxio_mpipe_link_mac_rd(&priv->link, addr); reg |= MPIPE_GBE_ENA_MULTI_HASH; reg |= MPIPE_GBE_ENA_UNI_HASH; reg &= ~MPIPE_GBE_COPY_ALL; gxio_mpipe_link_mac_wr(&priv->link, addr, reg); } } static struct eth_dev_ops mpipe_dev_ops = { .dev_infos_get = mpipe_infos_get, .dev_configure = mpipe_configure, .dev_start = mpipe_start, .dev_stop = mpipe_stop, .dev_close = mpipe_close, .stats_get = mpipe_stats_get, .stats_reset = mpipe_stats_reset, .queue_stats_mapping_set = mpipe_queue_stats_mapping_set, .tx_queue_setup = mpipe_tx_queue_setup, .rx_queue_setup = mpipe_rx_queue_setup, .tx_queue_release = mpipe_tx_queue_release, .rx_queue_release = mpipe_rx_queue_release, .link_update = mpipe_link_update, .dev_set_link_up = mpipe_set_link_up, .dev_set_link_down = mpipe_set_link_down, .promiscuous_enable = mpipe_promiscuous_enable, .promiscuous_disable = mpipe_promiscuous_disable, }; static inline void mpipe_xmit_null(struct mpipe_dev_priv *priv, int64_t start, int64_t end) { gxio_mpipe_edesc_t null_desc = { { .bound = 1, .ns = 1 } }; gxio_mpipe_equeue_t *equeue = &priv->equeue; int64_t slot; for (slot = start; slot < end; slot++) { gxio_mpipe_equeue_put_at(equeue, null_desc, slot); } } static void mpipe_xmit_flush(struct mpipe_dev_priv *priv) { gxio_mpipe_equeue_t *equeue = &priv->equeue; int64_t slot; /* Post a dummy descriptor and wait for its return. */ slot = gxio_mpipe_equeue_reserve(equeue, 1); if (slot < 0) { RTE_LOG(ERR, PMD, "%s: Failed to reserve stop slot.\n", mpipe_name(priv)); return; } mpipe_xmit_null(priv, slot, slot + 1); while (!gxio_mpipe_equeue_is_complete(equeue, slot, 1)) { rte_pause(); } for (slot = 0; slot < priv->equeue_size; slot++) { if (priv->tx_comps[slot]) rte_pktmbuf_free_seg(priv->tx_comps[slot]); } } static void mpipe_recv_flush(struct mpipe_dev_priv *priv) { uint8_t in_port = priv->port_id; struct mpipe_rx_queue *rx_queue; gxio_mpipe_iqueue_t *iqueue; gxio_mpipe_idesc_t idesc; struct rte_mbuf *mbuf; int retries = 0; unsigned queue; do { mpipe_recv_flush_stack(priv); /* Flush packets sitting in recv queues. */ for (queue = 0; queue < priv->nb_rx_queues; queue++) { rx_queue = mpipe_rx_queue(priv, queue); iqueue = &rx_queue->iqueue; while (gxio_mpipe_iqueue_try_get(iqueue, &idesc) >= 0) { mbuf = mpipe_recv_mbuf(priv, &idesc, in_port); rte_pktmbuf_free(mbuf); priv->rx_buffers--; } rte_free(rx_queue->rx_ring_mem); } } while (retries++ < 10 && priv->rx_buffers); if (priv->rx_buffers) { RTE_LOG(ERR, PMD, "%s: Leaked %d receive buffers.\n", mpipe_name(priv), priv->rx_buffers); } else { PMD_DEBUG_RX("%s: Returned all receive buffers.\n", mpipe_name(priv)); } } static inline uint16_t mpipe_do_xmit(struct mpipe_tx_queue *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct mpipe_dev_priv *priv = tx_queue->q.priv; gxio_mpipe_equeue_t *equeue = &priv->equeue; unsigned nb_bytes = 0; unsigned nb_sent = 0; int nb_slots, i; PMD_DEBUG_TX("Trying to transmit %d packets on %s:%d.\n", nb_pkts, mpipe_name(tx_queue->q.priv), tx_queue->q.queue_idx); /* Optimistic assumption that we need exactly one slot per packet. */ nb_slots = RTE_MIN(nb_pkts, MPIPE_TX_DESCS / 2); do { struct rte_mbuf *mbuf = NULL, *pkt = NULL; int64_t slot; /* Reserve eDMA ring slots. */ slot = gxio_mpipe_equeue_try_reserve_fast(equeue, nb_slots); if (unlikely(slot < 0)) { break; } for (i = 0; i < nb_slots; i++) { unsigned idx = (slot + i) & (priv->equeue_size - 1); rte_prefetch0(priv->tx_comps[idx]); } /* Fill up slots with descriptor and completion info. */ for (i = 0; i < nb_slots; i++) { unsigned idx = (slot + i) & (priv->equeue_size - 1); gxio_mpipe_edesc_t desc; struct rte_mbuf *next; /* Starting on a new packet? */ if (likely(!mbuf)) { int room = nb_slots - i; pkt = mbuf = tx_pkts[nb_sent]; /* Bail out if we run out of descs. */ if (unlikely(pkt->nb_segs > room)) break; nb_sent++; } /* We have a segment to send. */ next = mbuf->next; if (priv->tx_comps[idx]) rte_pktmbuf_free_seg(priv->tx_comps[idx]); desc = (gxio_mpipe_edesc_t) { { .va = rte_pktmbuf_mtod(mbuf, uintptr_t), .xfer_size = rte_pktmbuf_data_len(mbuf), .bound = next ? 0 : 1, } }; nb_bytes += mbuf->data_len; priv->tx_comps[idx] = mbuf; gxio_mpipe_equeue_put_at(equeue, desc, slot + i); PMD_DEBUG_TX("%s:%d: Sending packet %p, len %d\n", mpipe_name(priv), tx_queue->q.queue_idx, rte_pktmbuf_mtod(mbuf, void *), rte_pktmbuf_data_len(mbuf)); mbuf = next; } if (unlikely(nb_sent < nb_pkts)) { /* Fill remaining slots with null descriptors. */ mpipe_xmit_null(priv, slot + i, slot + nb_slots); /* * Calculate exact number of descriptors needed for * the next go around. */ nb_slots = 0; for (i = nb_sent; i < nb_pkts; i++) { nb_slots += tx_pkts[i]->nb_segs; } nb_slots = RTE_MIN(nb_slots, MPIPE_TX_DESCS / 2); } } while (nb_sent < nb_pkts); tx_queue->q.stats.packets += nb_sent; tx_queue->q.stats.bytes += nb_bytes; return nb_sent; } static inline uint16_t mpipe_do_recv(struct mpipe_rx_queue *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct mpipe_dev_priv *priv = rx_queue->q.priv; gxio_mpipe_iqueue_t *iqueue = &rx_queue->iqueue; gxio_mpipe_idesc_t *first_idesc, *idesc, *last_idesc; uint8_t in_port = rx_queue->q.port_id; const unsigned look_ahead = 8; int room = nb_pkts, rc = 0; unsigned nb_packets = 0; unsigned nb_dropped = 0; unsigned nb_nomem = 0; unsigned nb_bytes = 0; unsigned nb_descs, i; while (room && !rc) { if (rx_queue->avail_descs < room) { rc = gxio_mpipe_iqueue_try_peek(iqueue, &rx_queue->next_desc); rx_queue->avail_descs = rc < 0 ? 0 : rc; } if (unlikely(!rx_queue->avail_descs)) { break; } nb_descs = RTE_MIN(room, rx_queue->avail_descs); first_idesc = rx_queue->next_desc; last_idesc = first_idesc + nb_descs; rx_queue->next_desc += nb_descs; rx_queue->avail_descs -= nb_descs; for (i = 1; i < look_ahead; i++) { rte_prefetch0(first_idesc + i); } PMD_DEBUG_RX("%s:%d: Trying to receive %d packets\n", mpipe_name(rx_queue->q.priv), rx_queue->q.queue_idx, nb_descs); for (idesc = first_idesc; idesc < last_idesc; idesc++) { struct rte_mbuf *mbuf; PMD_DEBUG_RX("%s:%d: processing idesc %d/%d\n", mpipe_name(priv), rx_queue->q.queue_idx, nb_packets, nb_descs); rte_prefetch0(idesc + look_ahead); PMD_DEBUG_RX("%s:%d: idesc %p, %s%s%s%s%s%s%s%s%s%s" "size: %d, bkt: %d, chan: %d, ring: %d, sqn: %lu, va: %lu\n", mpipe_name(priv), rx_queue->q.queue_idx, idesc, idesc->me ? "me, " : "", idesc->tr ? "tr, " : "", idesc->ce ? "ce, " : "", idesc->ct ? "ct, " : "", idesc->cs ? "cs, " : "", idesc->nr ? "nr, " : "", idesc->sq ? "sq, " : "", idesc->ts ? "ts, " : "", idesc->ps ? "ps, " : "", idesc->be ? "be, " : "", idesc->l2_size, idesc->bucket_id, idesc->channel, idesc->notif_ring, (unsigned long)idesc->packet_sqn, (unsigned long)idesc->va); if (unlikely(gxio_mpipe_idesc_has_error(idesc))) { nb_dropped++; gxio_mpipe_iqueue_drop(iqueue, idesc); PMD_DEBUG_RX("%s:%d: Descriptor error\n", mpipe_name(rx_queue->q.priv), rx_queue->q.queue_idx); continue; } mbuf = __rte_mbuf_raw_alloc(priv->rx_mpool); if (unlikely(!mbuf)) { nb_nomem++; gxio_mpipe_iqueue_drop(iqueue, idesc); PMD_DEBUG_RX("%s:%d: RX alloc failure\n", mpipe_name(rx_queue->q.priv), rx_queue->q.queue_idx); continue; } mpipe_recv_push(priv, mbuf); /* Get and setup the mbuf for the received packet. */ mbuf = mpipe_recv_mbuf(priv, idesc, in_port); /* Update results and statistics counters. */ rx_pkts[nb_packets] = mbuf; nb_bytes += mbuf->pkt_len; nb_packets++; } /* * We release the ring in bursts, but do not track and release * buckets. This therefore breaks dynamic flow affinity, but * we always operate in static affinity mode, and so we're OK * with this optimization. */ gxio_mpipe_iqueue_advance(iqueue, nb_descs); gxio_mpipe_credit(iqueue->context, iqueue->ring, -1, nb_descs); /* * Go around once more if we haven't yet peeked the queue, and * if we have more room to receive. */ room = nb_pkts - nb_packets; } rx_queue->q.stats.packets += nb_packets; rx_queue->q.stats.bytes += nb_bytes; rx_queue->q.stats.errors += nb_dropped; rx_queue->q.stats.nomem += nb_nomem; PMD_DEBUG_RX("%s:%d: RX: %d/%d pkts/bytes, %d/%d drops/nomem\n", mpipe_name(rx_queue->q.priv), rx_queue->q.queue_idx, nb_packets, nb_bytes, nb_dropped, nb_nomem); return nb_packets; } static uint16_t mpipe_recv_pkts(void *_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct mpipe_rx_queue *rx_queue = _rxq; uint16_t result = 0; if (rx_queue) { mpipe_dp_enter(rx_queue->q.priv); if (likely(rx_queue->q.link_status)) result = mpipe_do_recv(rx_queue, rx_pkts, nb_pkts); mpipe_dp_exit(rx_queue->q.priv); } return result; } static uint16_t mpipe_xmit_pkts(void *_txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct mpipe_tx_queue *tx_queue = _txq; uint16_t result = 0; if (tx_queue) { mpipe_dp_enter(tx_queue->q.priv); if (likely(tx_queue->q.link_status)) result = mpipe_do_xmit(tx_queue, tx_pkts, nb_pkts); mpipe_dp_exit(tx_queue->q.priv); } return result; } static int mpipe_link_mac(const char *ifname, uint8_t *mac) { int rc, idx; char name[GXIO_MPIPE_LINK_NAME_LEN]; for (idx = 0, rc = 0; !rc; idx++) { rc = gxio_mpipe_link_enumerate_mac(idx, name, mac); if (!rc && !strncmp(name, ifname, GXIO_MPIPE_LINK_NAME_LEN)) return 0; } return -ENODEV; } static int rte_pmd_mpipe_devinit(const char *ifname, const char *params __rte_unused) { gxio_mpipe_context_t *context; struct rte_eth_dev *eth_dev; struct mpipe_dev_priv *priv; int instance, rc; uint8_t *mac; /* Get the mPIPE instance that the device belongs to. */ instance = gxio_mpipe_link_instance(ifname); context = mpipe_context(instance); if (!context) { RTE_LOG(ERR, PMD, "%s: No device for link.\n", ifname); return -ENODEV; } priv = rte_zmalloc(NULL, sizeof(*priv), 0); if (!priv) { RTE_LOG(ERR, PMD, "%s: Failed to allocate priv.\n", ifname); return -ENOMEM; } memset(&priv->tx_stat_mapping, 0xff, sizeof(priv->tx_stat_mapping)); memset(&priv->rx_stat_mapping, 0xff, sizeof(priv->rx_stat_mapping)); priv->context = context; priv->instance = instance; priv->is_xaui = (strncmp(ifname, "xgbe", 4) == 0); priv->pci_dev.numa_node = instance; priv->channel = -1; mac = priv->mac_addr.addr_bytes; rc = mpipe_link_mac(ifname, mac); if (rc < 0) { RTE_LOG(ERR, PMD, "%s: Failed to enumerate link.\n", ifname); rte_free(priv); return -ENODEV; } eth_dev = rte_eth_dev_allocate(ifname, RTE_ETH_DEV_VIRTUAL); if (!eth_dev) { RTE_LOG(ERR, PMD, "%s: Failed to allocate device.\n", ifname); rte_free(priv); } RTE_LOG(INFO, PMD, "%s: Initialized mpipe device" "(mac %02x:%02x:%02x:%02x:%02x:%02x).\n", ifname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); priv->eth_dev = eth_dev; priv->port_id = eth_dev->data->port_id; eth_dev->data->dev_private = priv; eth_dev->pci_dev = &priv->pci_dev; eth_dev->data->mac_addrs = &priv->mac_addr; eth_dev->dev_ops = &mpipe_dev_ops; eth_dev->rx_pkt_burst = &mpipe_recv_pkts; eth_dev->tx_pkt_burst = &mpipe_xmit_pkts; return 0; } static struct rte_driver pmd_mpipe_xgbe_drv = { .name = "xgbe", .type = PMD_VDEV, .init = rte_pmd_mpipe_devinit, }; static struct rte_driver pmd_mpipe_gbe_drv = { .name = "gbe", .type = PMD_VDEV, .init = rte_pmd_mpipe_devinit, }; PMD_REGISTER_DRIVER(pmd_mpipe_xgbe_drv); PMD_REGISTER_DRIVER(pmd_mpipe_gbe_drv); static void __attribute__((constructor, used)) mpipe_init_contexts(void) { struct mpipe_context *context; int rc, instance; for (instance = 0; instance < GXIO_MPIPE_INSTANCE_MAX; instance++) { context = &mpipe_contexts[instance]; rte_spinlock_init(&context->lock); rc = gxio_mpipe_init(&context->context, instance); if (rc < 0) break; } mpipe_instances = instance; } ================================================ FILE: drivers/net/null/Makefile ================================================ # BSD LICENSE # # Copyright (C) IGEL Co.,Ltd. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of IGEL Co.,Ltd. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_null.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_null_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += rte_eth_null.c # # Export include files # SYMLINK-y-include += # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += lib/librte_kvargs include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/null/rte_eth_null.c ================================================ /*- * BSD LICENSE * * Copyright (C) IGEL Co.,Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IGEL Co.,Ltd. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #define ETH_NULL_PACKET_SIZE_ARG "size" #define ETH_NULL_PACKET_COPY_ARG "copy" static unsigned default_packet_size = 64; static unsigned default_packet_copy; static const char *valid_arguments[] = { ETH_NULL_PACKET_SIZE_ARG, ETH_NULL_PACKET_COPY_ARG, NULL }; struct pmd_internals; struct null_queue { struct pmd_internals *internals; struct rte_mempool *mb_pool; struct rte_mbuf *dummy_packet; rte_atomic64_t rx_pkts; rte_atomic64_t tx_pkts; rte_atomic64_t err_pkts; }; struct pmd_internals { unsigned packet_size; unsigned packet_copy; unsigned numa_node; unsigned nb_rx_queues; unsigned nb_tx_queues; struct null_queue rx_null_queues[1]; struct null_queue tx_null_queues[1]; }; static struct ether_addr eth_addr = { .addr_bytes = {0} }; static const char *drivername = "Null PMD"; static struct rte_eth_link pmd_link = { .link_speed = 10000, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = 0 }; static uint16_t eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { int i; struct null_queue *h = q; unsigned packet_size; if ((q == NULL) || (bufs == NULL)) return 0; packet_size = h->internals->packet_size; for (i = 0; i < nb_bufs; i++) { bufs[i] = rte_pktmbuf_alloc(h->mb_pool); if (!bufs[i]) break; bufs[i]->data_len = (uint16_t)packet_size; bufs[i]->pkt_len = packet_size; bufs[i]->nb_segs = 1; bufs[i]->next = NULL; } rte_atomic64_add(&(h->rx_pkts), i); return i; } static uint16_t eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { int i; struct null_queue *h = q; unsigned packet_size; if ((q == NULL) || (bufs == NULL)) return 0; packet_size = h->internals->packet_size; for (i = 0; i < nb_bufs; i++) { bufs[i] = rte_pktmbuf_alloc(h->mb_pool); if (!bufs[i]) break; rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet, packet_size); bufs[i]->data_len = (uint16_t)packet_size; bufs[i]->pkt_len = packet_size; bufs[i]->nb_segs = 1; bufs[i]->next = NULL; } rte_atomic64_add(&(h->rx_pkts), i); return i; } static uint16_t eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { int i; struct null_queue *h = q; if ((q == NULL) || (bufs == NULL)) return 0; for (i = 0; i < nb_bufs; i++) rte_pktmbuf_free(bufs[i]); rte_atomic64_add(&(h->tx_pkts), i); return i; } static uint16_t eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { int i; struct null_queue *h = q; unsigned packet_size; if ((q == NULL) || (bufs == NULL)) return 0; packet_size = h->internals->packet_size; for (i = 0; i < nb_bufs; i++) { rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *), packet_size); rte_pktmbuf_free(bufs[i]); } rte_atomic64_add(&(h->tx_pkts), i); return i; } static int eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; } static int eth_dev_start(struct rte_eth_dev *dev) { if (dev == NULL) return -EINVAL; dev->data->dev_link.link_status = 1; return 0; } static void eth_dev_stop(struct rte_eth_dev *dev) { if (dev == NULL) return; dev->data->dev_link.link_status = 0; } static int eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool) { struct rte_mbuf *dummy_packet; struct pmd_internals *internals; unsigned packet_size; if ((dev == NULL) || (mb_pool == NULL)) return -EINVAL; if (rx_queue_id != 0) return -ENODEV; internals = dev->data->dev_private; packet_size = internals->packet_size; internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool; dev->data->rx_queues[rx_queue_id] = &internals->rx_null_queues[rx_queue_id]; dummy_packet = rte_zmalloc_socket(NULL, packet_size, 0, internals->numa_node); if (dummy_packet == NULL) return -ENOMEM; internals->rx_null_queues[rx_queue_id].internals = internals; internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet; return 0; } static int eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { struct rte_mbuf *dummy_packet; struct pmd_internals *internals; unsigned packet_size; if (dev == NULL) return -EINVAL; if (tx_queue_id != 0) return -ENODEV; internals = dev->data->dev_private; packet_size = internals->packet_size; dev->data->tx_queues[tx_queue_id] = &internals->tx_null_queues[tx_queue_id]; dummy_packet = rte_zmalloc_socket(NULL, packet_size, 0, internals->numa_node); if (dummy_packet == NULL) return -ENOMEM; internals->tx_null_queues[tx_queue_id].internals = internals; internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet; return 0; } static void eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_internals *internals; if ((dev == NULL) || (dev_info == NULL)) return; internals = dev->data->dev_private; dev_info->driver_name = drivername; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)-1; dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues; dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static void eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) { unsigned i, num_stats; unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0; const struct pmd_internals *internal; if ((dev == NULL) || (igb_stats == NULL)) return; internal = dev->data->dev_private; num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS, RTE_MIN(internal->nb_rx_queues, RTE_DIM(internal->rx_null_queues))); for (i = 0; i < num_stats; i++) { igb_stats->q_ipackets[i] = internal->rx_null_queues[i].rx_pkts.cnt; rx_total += igb_stats->q_ipackets[i]; } num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS, RTE_MIN(internal->nb_tx_queues, RTE_DIM(internal->tx_null_queues))); for (i = 0; i < num_stats; i++) { igb_stats->q_opackets[i] = internal->tx_null_queues[i].tx_pkts.cnt; igb_stats->q_errors[i] = internal->tx_null_queues[i].err_pkts.cnt; tx_total += igb_stats->q_opackets[i]; tx_err_total += igb_stats->q_errors[i]; } igb_stats->ipackets = rx_total; igb_stats->opackets = tx_total; igb_stats->oerrors = tx_err_total; } static void eth_stats_reset(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internal; if (dev == NULL) return; internal = dev->data->dev_private; for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++) internal->rx_null_queues[i].rx_pkts.cnt = 0; for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++) { internal->tx_null_queues[i].tx_pkts.cnt = 0; internal->tx_null_queues[i].err_pkts.cnt = 0; } } static struct eth_driver rte_null_pmd = { .pci_drv = { .name = "rte_null_pmd", .drv_flags = RTE_PCI_DRV_DETACHABLE, }, }; static void eth_queue_release(void *q) { struct null_queue *nq; if (q == NULL) return; nq = q; rte_free(nq->dummy_packet); } static int eth_link_update(struct rte_eth_dev *dev __rte_unused, int wait_to_complete __rte_unused) { return 0; } static const struct eth_dev_ops ops = { .dev_start = eth_dev_start, .dev_stop = eth_dev_stop, .dev_configure = eth_dev_configure, .dev_infos_get = eth_dev_info, .rx_queue_setup = eth_rx_queue_setup, .tx_queue_setup = eth_tx_queue_setup, .rx_queue_release = eth_queue_release, .tx_queue_release = eth_queue_release, .link_update = eth_link_update, .stats_get = eth_stats_get, .stats_reset = eth_stats_reset, }; static int eth_dev_null_create(const char *name, const unsigned numa_node, unsigned packet_size, unsigned packet_copy) { const unsigned nb_rx_queues = 1; const unsigned nb_tx_queues = 1; struct rte_eth_dev_data *data = NULL; struct rte_pci_device *pci_dev = NULL; struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; if (name == NULL) return -EINVAL; RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n", numa_node); /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (data == NULL) goto error; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node); if (pci_dev == NULL) goto error; internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node); if (internals == NULL) goto error; /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (eth_dev == NULL) goto error; /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver * - point eth_dev_data to internals and pci_driver * - and point eth_dev structure to new eth_dev_data structure */ /* NOTE: we'll replace the data element, of originally allocated eth_dev * so the nulls are local per-process */ internals->nb_rx_queues = nb_rx_queues; internals->nb_tx_queues = nb_tx_queues; internals->packet_size = packet_size; internals->packet_copy = packet_copy; internals->numa_node = numa_node; pci_dev->numa_node = numa_node; data->dev_private = internals; data->port_id = eth_dev->data->port_id; data->nb_rx_queues = (uint16_t)nb_rx_queues; data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = ð_addr; strncpy(data->name, eth_dev->data->name, strlen(eth_dev->data->name)); eth_dev->data = data; eth_dev->dev_ops = &ops; eth_dev->pci_dev = pci_dev; eth_dev->driver = &rte_null_pmd; /* finally assign rx and tx ops */ if (packet_copy) { eth_dev->rx_pkt_burst = eth_null_copy_rx; eth_dev->tx_pkt_burst = eth_null_copy_tx; } else { eth_dev->rx_pkt_burst = eth_null_rx; eth_dev->tx_pkt_burst = eth_null_tx; } return 0; error: rte_free(data); rte_free(pci_dev); rte_free(internals); return -1; } static inline int get_packet_size_arg(const char *key __rte_unused, const char *value, void *extra_args) { const char *a = value; unsigned *packet_size = extra_args; if ((value == NULL) || (extra_args == NULL)) return -EINVAL; *packet_size = (unsigned)strtoul(a, NULL, 0); if (*packet_size == UINT_MAX) return -1; return 0; } static inline int get_packet_copy_arg(const char *key __rte_unused, const char *value, void *extra_args) { const char *a = value; unsigned *packet_copy = extra_args; if ((value == NULL) || (extra_args == NULL)) return -EINVAL; *packet_copy = (unsigned)strtoul(a, NULL, 0); if (*packet_copy == UINT_MAX) return -1; return 0; } static int rte_pmd_null_devinit(const char *name, const char *params) { unsigned numa_node; unsigned packet_size = default_packet_size; unsigned packet_copy = default_packet_copy; struct rte_kvargs *kvlist = NULL; int ret; if (name == NULL) return -EINVAL; RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name); numa_node = rte_socket_id(); if (params != NULL) { kvlist = rte_kvargs_parse(params, valid_arguments); if (kvlist == NULL) return -1; if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) { ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_SIZE_ARG, &get_packet_size_arg, &packet_size); if (ret < 0) goto free_kvlist; } if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) { ret = rte_kvargs_process(kvlist, ETH_NULL_PACKET_COPY_ARG, &get_packet_copy_arg, &packet_copy); if (ret < 0) goto free_kvlist; } } RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, " "packet copy is %s\n", packet_size, packet_copy ? "enabled" : "disabled"); ret = eth_dev_null_create(name, numa_node, packet_size, packet_copy); free_kvlist: if (kvlist) rte_kvargs_free(kvlist); return ret; } static int rte_pmd_null_devuninit(const char *name) { struct rte_eth_dev *eth_dev = NULL; if (name == NULL) return -EINVAL; RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n", rte_socket_id()); /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocated(name); if (eth_dev == NULL) return -1; rte_free(eth_dev->data->dev_private); rte_free(eth_dev->data); rte_free(eth_dev->pci_dev); rte_eth_dev_release_port(eth_dev); return 0; } static struct rte_driver pmd_null_drv = { .name = "eth_null", .type = PMD_VDEV, .init = rte_pmd_null_devinit, .uninit = rte_pmd_null_devuninit, }; PMD_REGISTER_DRIVER(pmd_null_drv); ================================================ FILE: drivers/net/pcap/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # Copyright(c) 2014 6WIND S.A. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_pcap.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_pcap_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += rte_eth_pcap.c # # Export include files # SYMLINK-y-include += # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += lib/librte_kvargs include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/pcap/rte_eth_pcap.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #define RTE_ETH_PCAP_SNAPSHOT_LEN 65535 #define RTE_ETH_PCAP_SNAPLEN ETHER_MAX_JUMBO_FRAME_LEN #define RTE_ETH_PCAP_PROMISC 1 #define RTE_ETH_PCAP_TIMEOUT -1 #define ETH_PCAP_RX_PCAP_ARG "rx_pcap" #define ETH_PCAP_TX_PCAP_ARG "tx_pcap" #define ETH_PCAP_RX_IFACE_ARG "rx_iface" #define ETH_PCAP_TX_IFACE_ARG "tx_iface" #define ETH_PCAP_IFACE_ARG "iface" #define ETH_PCAP_ARG_MAXLEN 64 static char errbuf[PCAP_ERRBUF_SIZE]; static unsigned char tx_pcap_data[RTE_ETH_PCAP_SNAPLEN]; static struct timeval start_time; static uint64_t start_cycles; static uint64_t hz; struct pcap_rx_queue { pcap_t *pcap; uint8_t in_port; struct rte_mempool *mb_pool; volatile unsigned long rx_pkts; volatile unsigned long rx_bytes; volatile unsigned long err_pkts; char name[PATH_MAX]; char type[ETH_PCAP_ARG_MAXLEN]; }; struct pcap_tx_queue { pcap_dumper_t *dumper; pcap_t *pcap; volatile unsigned long tx_pkts; volatile unsigned long tx_bytes; volatile unsigned long err_pkts; char name[PATH_MAX]; char type[ETH_PCAP_ARG_MAXLEN]; }; struct rx_pcaps { unsigned num_of_rx; pcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS]; const char *names[RTE_PMD_RING_MAX_RX_RINGS]; const char *types[RTE_PMD_RING_MAX_RX_RINGS]; }; struct tx_pcaps { unsigned num_of_tx; pcap_dumper_t *dumpers[RTE_PMD_RING_MAX_TX_RINGS]; pcap_t *pcaps[RTE_PMD_RING_MAX_RX_RINGS]; const char *names[RTE_PMD_RING_MAX_RX_RINGS]; const char *types[RTE_PMD_RING_MAX_RX_RINGS]; }; struct pmd_internals { struct pcap_rx_queue rx_queue[RTE_PMD_RING_MAX_RX_RINGS]; struct pcap_tx_queue tx_queue[RTE_PMD_RING_MAX_TX_RINGS]; unsigned nb_rx_queues; unsigned nb_tx_queues; int if_index; int single_iface; }; const char *valid_arguments[] = { ETH_PCAP_RX_PCAP_ARG, ETH_PCAP_TX_PCAP_ARG, ETH_PCAP_RX_IFACE_ARG, ETH_PCAP_TX_IFACE_ARG, ETH_PCAP_IFACE_ARG, NULL }; static int open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper); static int open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap); static int open_single_iface(const char *iface, pcap_t **pcap); static struct ether_addr eth_addr = { .addr_bytes = { 0, 0, 0, 0x1, 0x2, 0x3 } }; static const char *drivername = "Pcap PMD"; static struct rte_eth_link pmd_link = { .link_speed = 10000, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = 0 }; static int eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf, const u_char *data, uint16_t data_len) { struct rte_mbuf *m = mbuf; /* Copy the first segment. */ uint16_t len = rte_pktmbuf_tailroom(mbuf); rte_memcpy(rte_pktmbuf_append(mbuf, len), data, len); data_len -= len; data += len; while (data_len > 0) { /* Allocate next mbuf and point to that. */ m->next = rte_pktmbuf_alloc(mb_pool); if (unlikely(!m->next)) return -1; m = m->next; /* Headroom is not needed in chained mbufs. */ rte_pktmbuf_prepend(m, rte_pktmbuf_headroom(m)); m->pkt_len = 0; m->data_len = 0; /* Copy next segment. */ len = RTE_MIN(rte_pktmbuf_tailroom(m), data_len); rte_memcpy(rte_pktmbuf_append(m, len), data, len); mbuf->nb_segs++; data_len -= len; data += len; } return mbuf->nb_segs; } /* Copy data from mbuf chain to a buffer suitable for writing to a PCAP file. */ static void eth_pcap_gather_data(unsigned char *data, struct rte_mbuf *mbuf) { uint16_t data_len = 0; while (mbuf) { rte_memcpy(data + data_len, rte_pktmbuf_mtod(mbuf, void *), mbuf->data_len); data_len += mbuf->data_len; mbuf = mbuf->next; } } static uint16_t eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { unsigned i; struct pcap_pkthdr header; const u_char *packet; struct rte_mbuf *mbuf; struct pcap_rx_queue *pcap_q = queue; uint16_t num_rx = 0; uint16_t buf_size; uint32_t rx_bytes = 0; if (unlikely(pcap_q->pcap == NULL || nb_pkts == 0)) return 0; /* Reads the given number of packets from the pcap file one by one * and copies the packet data into a newly allocated mbuf to return. */ for (i = 0; i < nb_pkts; i++) { /* Get the next PCAP packet */ packet = pcap_next(pcap_q->pcap, &header); if (unlikely(packet == NULL)) break; else mbuf = rte_pktmbuf_alloc(pcap_q->mb_pool); if (unlikely(mbuf == NULL)) break; /* Now get the space available for data in the mbuf */ buf_size = (uint16_t)(rte_pktmbuf_data_room_size(pcap_q->mb_pool) - RTE_PKTMBUF_HEADROOM); if (header.len <= buf_size) { /* pcap packet will fit in the mbuf, go ahead and copy */ rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), packet, header.len); mbuf->data_len = (uint16_t)header.len; } else { /* Try read jumbo frame into multi mbufs. */ if (unlikely(eth_pcap_rx_jumbo(pcap_q->mb_pool, mbuf, packet, header.len) == -1)) break; } mbuf->pkt_len = (uint16_t)header.len; mbuf->port = pcap_q->in_port; bufs[num_rx] = mbuf; num_rx++; rx_bytes += header.len; } pcap_q->rx_pkts += num_rx; pcap_q->rx_bytes += rx_bytes; return num_rx; } static inline void calculate_timestamp(struct timeval *ts) { uint64_t cycles; struct timeval cur_time; cycles = rte_get_timer_cycles() - start_cycles; cur_time.tv_sec = cycles / hz; cur_time.tv_usec = (cycles % hz) * 10e6 / hz; timeradd(&start_time, &cur_time, ts); } /* * Callback to handle writing packets to a pcap file. */ static uint16_t eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { unsigned i; struct rte_mbuf *mbuf; struct pcap_tx_queue *dumper_q = queue; uint16_t num_tx = 0; uint32_t tx_bytes = 0; struct pcap_pkthdr header; if (dumper_q->dumper == NULL || nb_pkts == 0) return 0; /* writes the nb_pkts packets to the previously opened pcap file dumper */ for (i = 0; i < nb_pkts; i++) { mbuf = bufs[i]; calculate_timestamp(&header.ts); header.len = mbuf->pkt_len; header.caplen = header.len; if (likely(mbuf->nb_segs == 1)) { pcap_dump((u_char *)dumper_q->dumper, &header, rte_pktmbuf_mtod(mbuf, void*)); } else { if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) { eth_pcap_gather_data(tx_pcap_data, mbuf); pcap_dump((u_char *)dumper_q->dumper, &header, tx_pcap_data); } else { RTE_LOG(ERR, PMD, "Dropping PCAP packet. " "Size (%d) > max jumbo size (%d).\n", mbuf->pkt_len, ETHER_MAX_JUMBO_FRAME_LEN); rte_pktmbuf_free(mbuf); break; } } rte_pktmbuf_free(mbuf); num_tx++; tx_bytes += mbuf->pkt_len; } /* * Since there's no place to hook a callback when the forwarding * process stops and to make sure the pcap file is actually written, * we flush the pcap dumper within each burst. */ pcap_dump_flush(dumper_q->dumper); dumper_q->tx_pkts += num_tx; dumper_q->tx_bytes += tx_bytes; dumper_q->err_pkts += nb_pkts - num_tx; return num_tx; } /* * Callback to handle sending packets through a real NIC. */ static uint16_t eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { unsigned i; int ret; struct rte_mbuf *mbuf; struct pcap_tx_queue *tx_queue = queue; uint16_t num_tx = 0; uint32_t tx_bytes = 0; if (unlikely(nb_pkts == 0 || tx_queue->pcap == NULL)) return 0; for (i = 0; i < nb_pkts; i++) { mbuf = bufs[i]; if (likely(mbuf->nb_segs == 1)) { ret = pcap_sendpacket(tx_queue->pcap, rte_pktmbuf_mtod(mbuf, u_char *), mbuf->pkt_len); } else { if (mbuf->pkt_len <= ETHER_MAX_JUMBO_FRAME_LEN) { eth_pcap_gather_data(tx_pcap_data, mbuf); ret = pcap_sendpacket(tx_queue->pcap, tx_pcap_data, mbuf->pkt_len); } else { RTE_LOG(ERR, PMD, "Dropping PCAP packet. " "Size (%d) > max jumbo size (%d).\n", mbuf->pkt_len, ETHER_MAX_JUMBO_FRAME_LEN); rte_pktmbuf_free(mbuf); break; } } if (unlikely(ret != 0)) break; num_tx++; tx_bytes += mbuf->pkt_len; rte_pktmbuf_free(mbuf); } tx_queue->tx_pkts += num_tx; tx_queue->tx_bytes += tx_bytes; tx_queue->err_pkts += nb_pkts - num_tx; return num_tx; } static int eth_dev_start(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internals = dev->data->dev_private; struct pcap_tx_queue *tx; struct pcap_rx_queue *rx; /* Special iface case. Single pcap is open and shared between tx/rx. */ if (internals->single_iface) { tx = &internals->tx_queue[0]; rx = &internals->rx_queue[0]; if (!tx->pcap && strcmp(tx->type, ETH_PCAP_IFACE_ARG) == 0) { if (open_single_iface(tx->name, &tx->pcap) < 0) return -1; rx->pcap = tx->pcap; } goto status_up; } /* If not open already, open tx pcaps/dumpers */ for (i = 0; i < internals->nb_tx_queues; i++) { tx = &internals->tx_queue[i]; if (!tx->dumper && strcmp(tx->type, ETH_PCAP_TX_PCAP_ARG) == 0) { if (open_single_tx_pcap(tx->name, &tx->dumper) < 0) return -1; } else if (!tx->pcap && strcmp(tx->type, ETH_PCAP_TX_IFACE_ARG) == 0) { if (open_single_iface(tx->name, &tx->pcap) < 0) return -1; } } /* If not open already, open rx pcaps */ for (i = 0; i < internals->nb_rx_queues; i++) { rx = &internals->rx_queue[i]; if (rx->pcap != NULL) continue; if (strcmp(rx->type, ETH_PCAP_RX_PCAP_ARG) == 0) { if (open_single_rx_pcap(rx->name, &rx->pcap) < 0) return -1; } else if (strcmp(rx->type, ETH_PCAP_RX_IFACE_ARG) == 0) { if (open_single_iface(rx->name, &rx->pcap) < 0) return -1; } } status_up: dev->data->dev_link.link_status = 1; return 0; } /* * This function gets called when the current port gets stopped. * Is the only place for us to close all the tx streams dumpers. * If not called the dumpers will be flushed within each tx burst. */ static void eth_dev_stop(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internals = dev->data->dev_private; struct pcap_tx_queue *tx; struct pcap_rx_queue *rx; /* Special iface case. Single pcap is open and shared between tx/rx. */ if (internals->single_iface) { tx = &internals->tx_queue[0]; rx = &internals->rx_queue[0]; pcap_close(tx->pcap); tx->pcap = NULL; rx->pcap = NULL; goto status_down; } for (i = 0; i < internals->nb_tx_queues; i++) { tx = &internals->tx_queue[i]; if (tx->dumper != NULL) { pcap_dump_close(tx->dumper); tx->dumper = NULL; } if (tx->pcap != NULL) { pcap_close(tx->pcap); tx->pcap = NULL; } } for (i = 0; i < internals->nb_rx_queues; i++) { rx = &internals->rx_queue[i]; if (rx->pcap != NULL) { pcap_close(rx->pcap); rx->pcap = NULL; } } status_down: dev->data->dev_link.link_status = 0; } static int eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; } static void eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_internals *internals = dev->data->dev_private; dev_info->driver_name = drivername; dev_info->if_index = internals->if_index; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t) -1; dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues; dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static void eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) { unsigned i; unsigned long rx_packets_total = 0, rx_bytes_total = 0; unsigned long tx_packets_total = 0, tx_bytes_total = 0; unsigned long tx_packets_err_total = 0; const struct pmd_internals *internal = dev->data->dev_private; for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_rx_queues; i++) { igb_stats->q_ipackets[i] = internal->rx_queue[i].rx_pkts; igb_stats->q_ibytes[i] = internal->rx_queue[i].rx_bytes; rx_packets_total += igb_stats->q_ipackets[i]; rx_bytes_total += igb_stats->q_ibytes[i]; } for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_tx_queues; i++) { igb_stats->q_opackets[i] = internal->tx_queue[i].tx_pkts; igb_stats->q_obytes[i] = internal->tx_queue[i].tx_bytes; igb_stats->q_errors[i] = internal->tx_queue[i].err_pkts; tx_packets_total += igb_stats->q_opackets[i]; tx_bytes_total += igb_stats->q_obytes[i]; tx_packets_err_total += igb_stats->q_errors[i]; } igb_stats->ipackets = rx_packets_total; igb_stats->ibytes = rx_bytes_total; igb_stats->opackets = tx_packets_total; igb_stats->obytes = tx_bytes_total; igb_stats->oerrors = tx_packets_err_total; } static void eth_stats_reset(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internal = dev->data->dev_private; for (i = 0; i < internal->nb_rx_queues; i++) { internal->rx_queue[i].rx_pkts = 0; internal->rx_queue[i].rx_bytes = 0; } for (i = 0; i < internal->nb_tx_queues; i++) { internal->tx_queue[i].tx_pkts = 0; internal->tx_queue[i].tx_bytes = 0; internal->tx_queue[i].err_pkts = 0; } } static void eth_dev_close(struct rte_eth_dev *dev __rte_unused) { } static void eth_queue_release(void *q __rte_unused) { } static int eth_link_update(struct rte_eth_dev *dev __rte_unused, int wait_to_complete __rte_unused) { return 0; } static int eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool) { struct pmd_internals *internals = dev->data->dev_private; struct pcap_rx_queue *pcap_q = &internals->rx_queue[rx_queue_id]; pcap_q->mb_pool = mb_pool; dev->data->rx_queues[rx_queue_id] = pcap_q; pcap_q->in_port = dev->data->port_id; return 0; } static int eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { struct pmd_internals *internals = dev->data->dev_private; dev->data->tx_queues[tx_queue_id] = &internals->tx_queue[tx_queue_id]; return 0; } static const struct eth_dev_ops ops = { .dev_start = eth_dev_start, .dev_stop = eth_dev_stop, .dev_close = eth_dev_close, .dev_configure = eth_dev_configure, .dev_infos_get = eth_dev_info, .rx_queue_setup = eth_rx_queue_setup, .tx_queue_setup = eth_tx_queue_setup, .rx_queue_release = eth_queue_release, .tx_queue_release = eth_queue_release, .link_update = eth_link_update, .stats_get = eth_stats_get, .stats_reset = eth_stats_reset, }; static struct eth_driver rte_pcap_pmd = { .pci_drv = { .name = "rte_pcap_pmd", .drv_flags = RTE_PCI_DRV_DETACHABLE, }, }; /* * Function handler that opens the pcap file for reading a stores a * reference of it for use it later on. */ static int open_rx_pcap(const char *key, const char *value, void *extra_args) { unsigned i; const char *pcap_filename = value; struct rx_pcaps *pcaps = extra_args; pcap_t *pcap = NULL; for (i = 0; i < pcaps->num_of_rx; i++) { if (open_single_rx_pcap(pcap_filename, &pcap) < 0) return -1; pcaps->pcaps[i] = pcap; pcaps->names[i] = pcap_filename; pcaps->types[i] = key; } return 0; } static int open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap) { if ((*pcap = pcap_open_offline(pcap_filename, errbuf)) == NULL) { RTE_LOG(ERR, PMD, "Couldn't open %s: %s\n", pcap_filename, errbuf); return -1; } return 0; } /* * Opens a pcap file for writing and stores a reference to it * for use it later on. */ static int open_tx_pcap(const char *key, const char *value, void *extra_args) { unsigned i; const char *pcap_filename = value; struct tx_pcaps *dumpers = extra_args; pcap_dumper_t *dumper; for (i = 0; i < dumpers->num_of_tx; i++) { if (open_single_tx_pcap(pcap_filename, &dumper) < 0) return -1; dumpers->dumpers[i] = dumper; dumpers->names[i] = pcap_filename; dumpers->types[i] = key; } return 0; } static int open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper) { pcap_t *tx_pcap; /* * We need to create a dummy empty pcap_t to use it * with pcap_dump_open(). We create big enough an Ethernet * pcap holder. */ if ((tx_pcap = pcap_open_dead(DLT_EN10MB, RTE_ETH_PCAP_SNAPSHOT_LEN)) == NULL) { RTE_LOG(ERR, PMD, "Couldn't create dead pcap\n"); return -1; } /* The dumper is created using the previous pcap_t reference */ if ((*dumper = pcap_dump_open(tx_pcap, pcap_filename)) == NULL) { RTE_LOG(ERR, PMD, "Couldn't open %s for writing.\n", pcap_filename); return -1; } return 0; } /* * pcap_open_live wrapper function */ static inline int open_iface_live(const char *iface, pcap_t **pcap) { *pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN, RTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf); if (*pcap == NULL) { RTE_LOG(ERR, PMD, "Couldn't open %s: %s\n", iface, errbuf); return -1; } return 0; } /* * Opens an interface for reading and writing */ static inline int open_rx_tx_iface(const char *key, const char *value, void *extra_args) { const char *iface = value; struct rx_pcaps *pcaps = extra_args; pcap_t *pcap = NULL; if (open_single_iface(iface, &pcap) < 0) return -1; pcaps->pcaps[0] = pcap; pcaps->names[0] = iface; pcaps->types[0] = key; return 0; } /* * Opens a NIC for reading packets from it */ static inline int open_rx_iface(const char *key, const char *value, void *extra_args) { unsigned i; const char *iface = value; struct rx_pcaps *pcaps = extra_args; pcap_t *pcap = NULL; for (i = 0; i < pcaps->num_of_rx; i++) { if (open_single_iface(iface, &pcap) < 0) return -1; pcaps->pcaps[i] = pcap; pcaps->names[i] = iface; pcaps->types[i] = key; } return 0; } /* * Opens a NIC for writing packets to it */ static int open_tx_iface(const char *key, const char *value, void *extra_args) { unsigned i; const char *iface = value; struct tx_pcaps *pcaps = extra_args; pcap_t *pcap; for (i = 0; i < pcaps->num_of_tx; i++) { if (open_single_iface(iface, &pcap) < 0) return -1; pcaps->pcaps[i] = pcap; pcaps->names[i] = iface; pcaps->types[i] = key; } return 0; } static int open_single_iface(const char *iface, pcap_t **pcap) { if (open_iface_live(iface, pcap) < 0) { RTE_LOG(ERR, PMD, "Couldn't open interface %s\n", iface); return -1; } return 0; } static int rte_pmd_init_internals(const char *name, const unsigned nb_rx_queues, const unsigned nb_tx_queues, const unsigned numa_node, struct pmd_internals **internals, struct rte_eth_dev **eth_dev, struct rte_kvargs *kvlist) { struct rte_eth_dev_data *data = NULL; struct rte_pci_device *pci_dev = NULL; unsigned k_idx; struct rte_kvargs_pair *pair = NULL; for (k_idx = 0; k_idx < kvlist->count; k_idx++) { pair = &kvlist->pairs[k_idx]; if (strstr(pair->key, ETH_PCAP_IFACE_ARG) != NULL) break; } RTE_LOG(INFO, PMD, "Creating pcap-backed ethdev on numa socket %u\n", numa_node); /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (data == NULL) goto error; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node); if (pci_dev == NULL) goto error; *internals = rte_zmalloc_socket(name, sizeof(**internals), 0, numa_node); if (*internals == NULL) goto error; /* reserve an ethdev entry */ *eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (*eth_dev == NULL) goto error; /* check length of device name */ if ((strlen((*eth_dev)->data->name) + 1) > sizeof(data->name)) goto error; /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver * - point eth_dev_data to internals and pci_driver * - and point eth_dev structure to new eth_dev_data structure */ /* NOTE: we'll replace the data element, of originally allocated eth_dev * so the rings are local per-process */ (*internals)->nb_rx_queues = nb_rx_queues; (*internals)->nb_tx_queues = nb_tx_queues; if (pair == NULL) (*internals)->if_index = 0; else (*internals)->if_index = if_nametoindex(pair->value); pci_dev->numa_node = numa_node; data->dev_private = *internals; data->port_id = (*eth_dev)->data->port_id; snprintf(data->name, sizeof(data->name), "%s", (*eth_dev)->data->name); data->nb_rx_queues = (uint16_t)nb_rx_queues; data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = ð_addr; strncpy(data->name, (*eth_dev)->data->name, strlen((*eth_dev)->data->name)); (*eth_dev)->data = data; (*eth_dev)->dev_ops = &ops; (*eth_dev)->pci_dev = pci_dev; (*eth_dev)->driver = &rte_pcap_pmd; return 0; error: rte_free(data); rte_free(pci_dev); rte_free(*internals); return -1; } static int rte_eth_from_pcaps_n_dumpers(const char *name, struct rx_pcaps *rx_queues, const unsigned nb_rx_queues, struct tx_pcaps *tx_queues, const unsigned nb_tx_queues, const unsigned numa_node, struct rte_kvargs *kvlist) { struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; unsigned i; /* do some parameter checking */ if (rx_queues == NULL && nb_rx_queues > 0) return -1; if (tx_queues == NULL && nb_tx_queues > 0) return -1; if (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node, &internals, ð_dev, kvlist) < 0) return -1; for (i = 0; i < nb_rx_queues; i++) { internals->rx_queue[i].pcap = rx_queues->pcaps[i]; snprintf(internals->rx_queue[i].name, sizeof(internals->rx_queue[i].name), "%s", rx_queues->names[i]); snprintf(internals->rx_queue[i].type, sizeof(internals->rx_queue[i].type), "%s", rx_queues->types[i]); } for (i = 0; i < nb_tx_queues; i++) { internals->tx_queue[i].dumper = tx_queues->dumpers[i]; snprintf(internals->tx_queue[i].name, sizeof(internals->tx_queue[i].name), "%s", tx_queues->names[i]); snprintf(internals->tx_queue[i].type, sizeof(internals->tx_queue[i].type), "%s", tx_queues->types[i]); } /* using multiple pcaps/interfaces */ internals->single_iface = 0; eth_dev->rx_pkt_burst = eth_pcap_rx; eth_dev->tx_pkt_burst = eth_pcap_tx_dumper; return 0; } static int rte_eth_from_pcaps(const char *name, struct rx_pcaps *rx_queues, const unsigned nb_rx_queues, struct tx_pcaps *tx_queues, const unsigned nb_tx_queues, const unsigned numa_node, struct rte_kvargs *kvlist, int single_iface) { struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; unsigned i; /* do some parameter checking */ if (rx_queues == NULL && nb_rx_queues > 0) return -1; if (tx_queues == NULL && nb_tx_queues > 0) return -1; if (rte_pmd_init_internals(name, nb_rx_queues, nb_tx_queues, numa_node, &internals, ð_dev, kvlist) < 0) return -1; for (i = 0; i < nb_rx_queues; i++) { internals->rx_queue[i].pcap = rx_queues->pcaps[i]; snprintf(internals->rx_queue[i].name, sizeof(internals->rx_queue[i].name), "%s", rx_queues->names[i]); snprintf(internals->rx_queue[i].type, sizeof(internals->rx_queue[i].type), "%s", rx_queues->types[i]); } for (i = 0; i < nb_tx_queues; i++) { internals->tx_queue[i].dumper = tx_queues->dumpers[i]; snprintf(internals->tx_queue[i].name, sizeof(internals->tx_queue[i].name), "%s", tx_queues->names[i]); snprintf(internals->tx_queue[i].type, sizeof(internals->tx_queue[i].type), "%s", tx_queues->types[i]); } /* store wether we are using a single interface for rx/tx or not */ internals->single_iface = single_iface; eth_dev->rx_pkt_burst = eth_pcap_rx; eth_dev->tx_pkt_burst = eth_pcap_tx; return 0; } static int rte_pmd_pcap_devinit(const char *name, const char *params) { unsigned numa_node, using_dumpers = 0; int ret; struct rte_kvargs *kvlist; struct rx_pcaps pcaps; struct tx_pcaps dumpers; RTE_LOG(INFO, PMD, "Initializing pmd_pcap for %s\n", name); numa_node = rte_socket_id(); gettimeofday(&start_time, NULL); start_cycles = rte_get_timer_cycles(); hz = rte_get_timer_hz(); kvlist = rte_kvargs_parse(params, valid_arguments); if (kvlist == NULL) return -1; /* * If iface argument is passed we open the NICs and use them for * reading / writing */ if (rte_kvargs_count(kvlist, ETH_PCAP_IFACE_ARG) == 1) { ret = rte_kvargs_process(kvlist, ETH_PCAP_IFACE_ARG, &open_rx_tx_iface, &pcaps); if (ret < 0) goto free_kvlist; dumpers.pcaps[0] = pcaps.pcaps[0]; dumpers.names[0] = pcaps.names[0]; dumpers.types[0] = pcaps.types[0]; ret = rte_eth_from_pcaps(name, &pcaps, 1, &dumpers, 1, numa_node, kvlist, 1); goto free_kvlist; } /* * We check whether we want to open a RX stream from a real NIC or a * pcap file */ if ((pcaps.num_of_rx = rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG))) { ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_PCAP_ARG, &open_rx_pcap, &pcaps); } else { pcaps.num_of_rx = rte_kvargs_count(kvlist, ETH_PCAP_RX_IFACE_ARG); ret = rte_kvargs_process(kvlist, ETH_PCAP_RX_IFACE_ARG, &open_rx_iface, &pcaps); } if (ret < 0) goto free_kvlist; /* * We check whether we want to open a TX stream to a real NIC or a * pcap file */ if ((dumpers.num_of_tx = rte_kvargs_count(kvlist, ETH_PCAP_TX_PCAP_ARG))) { ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_PCAP_ARG, &open_tx_pcap, &dumpers); using_dumpers = 1; } else { dumpers.num_of_tx = rte_kvargs_count(kvlist, ETH_PCAP_TX_IFACE_ARG); ret = rte_kvargs_process(kvlist, ETH_PCAP_TX_IFACE_ARG, &open_tx_iface, &dumpers); } if (ret < 0) goto free_kvlist; if (using_dumpers) ret = rte_eth_from_pcaps_n_dumpers(name, &pcaps, pcaps.num_of_rx, &dumpers, dumpers.num_of_tx, numa_node, kvlist); else ret = rte_eth_from_pcaps(name, &pcaps, pcaps.num_of_rx, &dumpers, dumpers.num_of_tx, numa_node, kvlist, 0); free_kvlist: rte_kvargs_free(kvlist); return ret; } static int rte_pmd_pcap_devuninit(const char *name) { struct rte_eth_dev *eth_dev = NULL; RTE_LOG(INFO, PMD, "Closing pcap ethdev on numa socket %u\n", rte_socket_id()); if (name == NULL) return -1; /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocated(name); if (eth_dev == NULL) return -1; rte_free(eth_dev->data->dev_private); rte_free(eth_dev->data); rte_free(eth_dev->pci_dev); rte_eth_dev_release_port(eth_dev); return 0; } static struct rte_driver pmd_pcap_drv = { .name = "eth_pcap", .type = PMD_VDEV, .init = rte_pmd_pcap_devinit, .uninit = rte_pmd_pcap_devuninit, }; PMD_REGISTER_DRIVER(pmd_pcap_drv); ================================================ FILE: drivers/net/ring/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_ring.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_eth_ring_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += rte_eth_ring.c # # Export include files # SYMLINK-y-include += rte_eth_ring.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += lib/librte_eal lib/librte_ring DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += lib/librte_mbuf lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += lib/librte_kvargs include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/ring/rte_eth_ring.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "rte_eth_ring.h" #include #include #include #include #include #include #include #define ETH_RING_NUMA_NODE_ACTION_ARG "nodeaction" #define ETH_RING_ACTION_CREATE "CREATE" #define ETH_RING_ACTION_ATTACH "ATTACH" static const char *ring_ethdev_driver_name = "Ring PMD"; static const char *valid_arguments[] = { ETH_RING_NUMA_NODE_ACTION_ARG, NULL }; struct ring_queue { struct rte_ring *rng; rte_atomic64_t rx_pkts; rte_atomic64_t tx_pkts; rte_atomic64_t err_pkts; }; struct pmd_internals { unsigned nb_rx_queues; unsigned nb_tx_queues; struct ring_queue rx_ring_queues[RTE_PMD_RING_MAX_RX_RINGS]; struct ring_queue tx_ring_queues[RTE_PMD_RING_MAX_TX_RINGS]; struct ether_addr address; }; static const char *drivername = "Rings PMD"; static struct rte_eth_link pmd_link = { .link_speed = 10000, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = 0 }; static uint16_t eth_ring_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { void **ptrs = (void *)&bufs[0]; struct ring_queue *r = q; const uint16_t nb_rx = (uint16_t)rte_ring_dequeue_burst(r->rng, ptrs, nb_bufs); if (r->rng->flags & RING_F_SC_DEQ) r->rx_pkts.cnt += nb_rx; else rte_atomic64_add(&(r->rx_pkts), nb_rx); return nb_rx; } static uint16_t eth_ring_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) { void **ptrs = (void *)&bufs[0]; struct ring_queue *r = q; const uint16_t nb_tx = (uint16_t)rte_ring_enqueue_burst(r->rng, ptrs, nb_bufs); if (r->rng->flags & RING_F_SP_ENQ) { r->tx_pkts.cnt += nb_tx; r->err_pkts.cnt += nb_bufs - nb_tx; } else { rte_atomic64_add(&(r->tx_pkts), nb_tx); rte_atomic64_add(&(r->err_pkts), nb_bufs - nb_tx); } return nb_tx; } static int eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; } static int eth_dev_start(struct rte_eth_dev *dev) { dev->data->dev_link.link_status = 1; return 0; } static void eth_dev_stop(struct rte_eth_dev *dev) { dev->data->dev_link.link_status = 0; } static int eth_dev_set_link_down(struct rte_eth_dev *dev) { dev->data->dev_link.link_status = 0; return 0; } static int eth_dev_set_link_up(struct rte_eth_dev *dev) { dev->data->dev_link.link_status = 1; return 0; } static int eth_rx_queue_setup(struct rte_eth_dev *dev,uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool __rte_unused) { struct pmd_internals *internals = dev->data->dev_private; dev->data->rx_queues[rx_queue_id] = &internals->rx_ring_queues[rx_queue_id]; return 0; } static int eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { struct pmd_internals *internals = dev->data->dev_private; dev->data->tx_queues[tx_queue_id] = &internals->tx_ring_queues[tx_queue_id]; return 0; } static void eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_internals *internals = dev->data->dev_private; dev_info->driver_name = drivername; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)-1; dev_info->max_rx_queues = (uint16_t)internals->nb_rx_queues; dev_info->max_tx_queues = (uint16_t)internals->nb_tx_queues; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static void eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) { unsigned i; unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0; const struct pmd_internals *internal = dev->data->dev_private; for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_rx_queues; i++) { igb_stats->q_ipackets[i] = internal->rx_ring_queues[i].rx_pkts.cnt; rx_total += igb_stats->q_ipackets[i]; } for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && i < internal->nb_tx_queues; i++) { igb_stats->q_opackets[i] = internal->tx_ring_queues[i].tx_pkts.cnt; igb_stats->q_errors[i] = internal->tx_ring_queues[i].err_pkts.cnt; tx_total += igb_stats->q_opackets[i]; tx_err_total += igb_stats->q_errors[i]; } igb_stats->ipackets = rx_total; igb_stats->opackets = tx_total; igb_stats->oerrors = tx_err_total; } static void eth_stats_reset(struct rte_eth_dev *dev) { unsigned i; struct pmd_internals *internal = dev->data->dev_private; for (i = 0; i < internal->nb_rx_queues; i++) internal->rx_ring_queues[i].rx_pkts.cnt = 0; for (i = 0; i < internal->nb_tx_queues; i++) { internal->tx_ring_queues[i].tx_pkts.cnt = 0; internal->tx_ring_queues[i].err_pkts.cnt = 0; } } static void eth_mac_addr_remove(struct rte_eth_dev *dev __rte_unused, uint32_t index __rte_unused) { } static void eth_mac_addr_add(struct rte_eth_dev *dev __rte_unused, struct ether_addr *mac_addr __rte_unused, uint32_t index __rte_unused, uint32_t vmdq __rte_unused) { } static void eth_queue_release(void *q __rte_unused) { ; } static int eth_link_update(struct rte_eth_dev *dev __rte_unused, int wait_to_complete __rte_unused) { return 0; } static const struct eth_dev_ops ops = { .dev_start = eth_dev_start, .dev_stop = eth_dev_stop, .dev_set_link_up = eth_dev_set_link_up, .dev_set_link_down = eth_dev_set_link_down, .dev_configure = eth_dev_configure, .dev_infos_get = eth_dev_info, .rx_queue_setup = eth_rx_queue_setup, .tx_queue_setup = eth_tx_queue_setup, .rx_queue_release = eth_queue_release, .tx_queue_release = eth_queue_release, .link_update = eth_link_update, .stats_get = eth_stats_get, .stats_reset = eth_stats_reset, .mac_addr_remove = eth_mac_addr_remove, .mac_addr_add = eth_mac_addr_add, }; static struct eth_driver rte_ring_pmd = { .pci_drv = { .name = "rte_ring_pmd", .drv_flags = RTE_PCI_DRV_DETACHABLE, }, }; static struct rte_pci_id id_table; int rte_eth_from_rings(const char *name, struct rte_ring *const rx_queues[], const unsigned nb_rx_queues, struct rte_ring *const tx_queues[], const unsigned nb_tx_queues, const unsigned numa_node) { struct rte_eth_dev_data *data = NULL; struct rte_pci_device *pci_dev = NULL; struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; unsigned i; /* do some parameter checking */ if (rx_queues == NULL && nb_rx_queues > 0) goto error; if (tx_queues == NULL && nb_tx_queues > 0) goto error; RTE_LOG(INFO, PMD, "Creating rings-backed ethdev on numa socket %u\n", numa_node); /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (data == NULL) goto error; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node); if (pci_dev == NULL) goto error; internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node); if (internals == NULL) goto error; /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (eth_dev == NULL) goto error; /* now put it all together * - store queue data in internals, * - store numa_node info in pci_driver * - point eth_dev_data to internals and pci_driver * - and point eth_dev structure to new eth_dev_data structure */ /* NOTE: we'll replace the data element, of originally allocated eth_dev * so the rings are local per-process */ internals->nb_rx_queues = nb_rx_queues; internals->nb_tx_queues = nb_tx_queues; for (i = 0; i < nb_rx_queues; i++) { internals->rx_ring_queues[i].rng = rx_queues[i]; } for (i = 0; i < nb_tx_queues; i++) { internals->tx_ring_queues[i].rng = tx_queues[i]; } rte_ring_pmd.pci_drv.name = ring_ethdev_driver_name; rte_ring_pmd.pci_drv.id_table = &id_table; pci_dev->numa_node = numa_node; pci_dev->driver = &rte_ring_pmd.pci_drv; data->dev_private = internals; data->port_id = eth_dev->data->port_id; memmove(data->name, eth_dev->data->name, sizeof(data->name)); data->nb_rx_queues = (uint16_t)nb_rx_queues; data->nb_tx_queues = (uint16_t)nb_tx_queues; data->dev_link = pmd_link; data->mac_addrs = &internals->address; eth_dev->data = data; eth_dev->driver = &rte_ring_pmd; eth_dev->dev_ops = &ops; eth_dev->pci_dev = pci_dev; TAILQ_INIT(&(eth_dev->link_intr_cbs)); /* finally assign rx and tx ops */ eth_dev->rx_pkt_burst = eth_ring_rx; eth_dev->tx_pkt_burst = eth_ring_tx; return data->port_id; error: rte_free(data); rte_free(pci_dev); rte_free(internals); return -1; } enum dev_action{ DEV_CREATE, DEV_ATTACH }; static int eth_dev_ring_create(const char *name, const unsigned numa_node, enum dev_action action) { /* rx and tx are so-called from point of view of first port. * They are inverted from the point of view of second port */ struct rte_ring *rxtx[RTE_PMD_RING_MAX_RX_RINGS]; unsigned i; char rng_name[RTE_RING_NAMESIZE]; unsigned num_rings = RTE_MIN(RTE_PMD_RING_MAX_RX_RINGS, RTE_PMD_RING_MAX_TX_RINGS); for (i = 0; i < num_rings; i++) { snprintf(rng_name, sizeof(rng_name), "ETH_RXTX%u_%s", i, name); rxtx[i] = (action == DEV_CREATE) ? rte_ring_create(rng_name, 1024, numa_node, RING_F_SP_ENQ|RING_F_SC_DEQ) : rte_ring_lookup(rng_name); if (rxtx[i] == NULL) return -1; } if (rte_eth_from_rings(name, rxtx, num_rings, rxtx, num_rings, numa_node) < 0) return -1; return 0; } static int eth_dev_ring_pair_create(const char *name, const unsigned numa_node, enum dev_action action) { /* rx and tx are so-called from point of view of first port. * They are inverted from the point of view of second port */ struct rte_ring *rx[RTE_PMD_RING_MAX_RX_RINGS]; struct rte_ring *tx[RTE_PMD_RING_MAX_TX_RINGS]; unsigned i; char rx_rng_name[RTE_RING_NAMESIZE]; char tx_rng_name[RTE_RING_NAMESIZE]; unsigned num_rings = RTE_MIN(RTE_PMD_RING_MAX_RX_RINGS, RTE_PMD_RING_MAX_TX_RINGS); for (i = 0; i < num_rings; i++) { snprintf(rx_rng_name, sizeof(rx_rng_name), "ETH_RX%u_%s", i, name); rx[i] = (action == DEV_CREATE) ? rte_ring_create(rx_rng_name, 1024, numa_node, RING_F_SP_ENQ|RING_F_SC_DEQ) : rte_ring_lookup(rx_rng_name); if (rx[i] == NULL) return -1; snprintf(tx_rng_name, sizeof(tx_rng_name), "ETH_TX%u_%s", i, name); tx[i] = (action == DEV_CREATE) ? rte_ring_create(tx_rng_name, 1024, numa_node, RING_F_SP_ENQ|RING_F_SC_DEQ): rte_ring_lookup(tx_rng_name); if (tx[i] == NULL) return -1; } if (rte_eth_from_rings(rx_rng_name, rx, num_rings, tx, num_rings, numa_node) < 0 || rte_eth_from_rings(tx_rng_name, tx, num_rings, rx, num_rings, numa_node) < 0) return -1; return 0; } int rte_eth_ring_pair_create(const char *name, const unsigned numa_node) { RTE_LOG(WARNING, PMD, "rte_eth_ring_pair_create is deprecated\n"); return eth_dev_ring_pair_create(name, numa_node, DEV_CREATE); } int rte_eth_ring_pair_attach(const char *name, const unsigned numa_node) { RTE_LOG(WARNING, PMD, "rte_eth_ring_pair_attach is deprecated\n"); return eth_dev_ring_pair_create(name, numa_node, DEV_ATTACH); } struct node_action_pair { char name[PATH_MAX]; unsigned node; enum dev_action action; }; struct node_action_list { unsigned total; unsigned count; struct node_action_pair *list; }; static int parse_kvlist (const char *key __rte_unused, const char *value, void *data) { struct node_action_list *info = data; int ret; char *name; char *action; char *node; char *end; name = strdup(value); ret = -EINVAL; if (!name) { RTE_LOG(WARNING, PMD, "command line paramter is empty for ring pmd!\n"); goto out; } node = strchr(name, ':'); if (!node) { RTE_LOG(WARNING, PMD, "could not parse node value from %s", name); goto out; } *node = '\0'; node++; action = strchr(node, ':'); if (!action) { RTE_LOG(WARNING, PMD, "could not action value from %s", node); goto out; } *action = '\0'; action++; /* * Need to do some sanity checking here */ if (strcmp(action, ETH_RING_ACTION_ATTACH) == 0) info->list[info->count].action = DEV_ATTACH; else if (strcmp(action, ETH_RING_ACTION_CREATE) == 0) info->list[info->count].action = DEV_CREATE; else goto out; errno = 0; info->list[info->count].node = strtol(node, &end, 10); if ((errno != 0) || (*end != '\0')) { RTE_LOG(WARNING, PMD, "node value %s is unparseable as a number\n", node); goto out; } snprintf(info->list[info->count].name, sizeof(info->list[info->count].name), "%s", name); info->count++; ret = 0; out: free(name); return ret; } static int rte_pmd_ring_devinit(const char *name, const char *params) { struct rte_kvargs *kvlist = NULL; int ret = 0; struct node_action_list *info = NULL; RTE_LOG(INFO, PMD, "Initializing pmd_ring for %s\n", name); if (params == NULL || params[0] == '\0') { ret = eth_dev_ring_create(name, rte_socket_id(), DEV_CREATE); if (ret == -1) { RTE_LOG(INFO, PMD, "Attach to pmd_ring for %s\n", name); ret = eth_dev_ring_create(name, rte_socket_id(), DEV_ATTACH); } } else { kvlist = rte_kvargs_parse(params, valid_arguments); if (!kvlist) { RTE_LOG(INFO, PMD, "Ignoring unsupported parameters when creating" " rings-backed ethernet device\n"); ret = eth_dev_ring_create(name, rte_socket_id(), DEV_CREATE); if (ret == -1) { RTE_LOG(INFO, PMD, "Attach to pmd_ring for %s\n", name); ret = eth_dev_ring_create(name, rte_socket_id(), DEV_ATTACH); } return ret; } else { ret = rte_kvargs_count(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG); info = rte_zmalloc("struct node_action_list", sizeof(struct node_action_list) + (sizeof(struct node_action_pair) * ret), 0); if (!info) goto out_free; info->total = ret; info->list = (struct node_action_pair*)(info + 1); ret = rte_kvargs_process(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG, parse_kvlist, info); if (ret < 0) goto out_free; for (info->count = 0; info->count < info->total; info->count++) { ret = eth_dev_ring_create(name, info->list[info->count].node, info->list[info->count].action); if ((ret == -1) && (info->list[info->count].action == DEV_CREATE)) { RTE_LOG(INFO, PMD, "Attach to pmd_ring for %s\n", name); ret = eth_dev_ring_create(name, info->list[info->count].node, DEV_ATTACH); } } } } out_free: rte_kvargs_free(kvlist); rte_free(info); return ret; } static int rte_pmd_ring_devuninit(const char *name) { struct rte_eth_dev *eth_dev = NULL; RTE_LOG(INFO, PMD, "Un-Initializing pmd_ring for %s\n", name); if (name == NULL) return -EINVAL; /* find an ethdev entry */ eth_dev = rte_eth_dev_allocated(name); if (eth_dev == NULL) return -ENODEV; eth_dev_stop(eth_dev); rte_free(eth_dev->data->dev_private); rte_free(eth_dev->data); rte_free(eth_dev->pci_dev); rte_eth_dev_release_port(eth_dev); return 0; } static struct rte_driver pmd_ring_drv = { .name = "eth_ring", .type = PMD_VDEV, .init = rte_pmd_ring_devinit, .uninit = rte_pmd_ring_devuninit, }; PMD_REGISTER_DRIVER(pmd_ring_drv); ================================================ FILE: drivers/net/ring/rte_eth_ring.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_RING_H_ #define _RTE_ETH_RING_H_ #ifdef __cplusplus extern "C" { #endif #include /** * Create a new ethdev port from a set of rings * * @param name * name to be given to the new ethdev port * @param rx_queues * pointer to array of rte_rings to be used as RX queues * @param nb_rx_queues * number of elements in the rx_queues array * @param tx_queues * pointer to array of rte_rings to be used as TX queues * @param nb_tx_queues * number of elements in the tx_queues array * @param numa_node * the numa node on which the memory for this port is to be allocated * @return * the port number of the newly created the ethdev or -1 on error. */ int rte_eth_from_rings(const char *name, struct rte_ring * const rx_queues[], const unsigned nb_rx_queues, struct rte_ring *const tx_queues[], const unsigned nb_tx_queues, const unsigned numa_node); int rte_eth_ring_pair_create(const char *name, const unsigned numa_node); int rte_eth_ring_pair_attach(const char *name, const unsigned numa_node); #ifdef __cplusplus } #endif #endif ================================================ FILE: drivers/net/virtio/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_virtio.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pmd_virtio_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtqueue.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_pci.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_ethdev.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/virtio/virtio_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #ifdef RTE_EXEC_ENV_LINUXAPP #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "virtio_ethdev.h" #include "virtio_pci.h" #include "virtio_logs.h" #include "virtqueue.h" static int eth_virtio_dev_init(struct rte_eth_dev *eth_dev); static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev); static int virtio_dev_configure(struct rte_eth_dev *dev); static int virtio_dev_start(struct rte_eth_dev *dev); static void virtio_dev_stop(struct rte_eth_dev *dev); static void virtio_dev_promiscuous_enable(struct rte_eth_dev *dev); static void virtio_dev_promiscuous_disable(struct rte_eth_dev *dev); static void virtio_dev_allmulticast_enable(struct rte_eth_dev *dev); static void virtio_dev_allmulticast_disable(struct rte_eth_dev *dev); static void virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete); static void virtio_set_hwaddr(struct virtio_hw *hw); static void virtio_get_hwaddr(struct virtio_hw *hw); static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void virtio_dev_stats_reset(struct rte_eth_dev *dev); static void virtio_dev_free_mbufs(struct rte_eth_dev *dev); static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on); static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused); static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); static void virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr); static int virtio_dev_queue_stats_mapping_set( __rte_unused struct rte_eth_dev *eth_dev, __rte_unused uint16_t queue_id, __rte_unused uint8_t stat_idx, __rte_unused uint8_t is_rx); /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_virtio_map[] = { #define RTE_PCI_DEV_ID_DECL_VIRTIO(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static int virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl, int *dlen, int pkt_num) { uint32_t head, i; int k, sum = 0; virtio_net_ctrl_ack status = ~0; struct virtio_pmd_ctrl result; ctrl->status = status; if (!(vq && vq->hw->cvq)) { PMD_INIT_LOG(ERR, "%s(): Control queue is not supported.", __func__); return -1; } head = vq->vq_desc_head_idx; PMD_INIT_LOG(DEBUG, "vq->vq_desc_head_idx = %d, status = %d, " "vq->hw->cvq = %p vq = %p", vq->vq_desc_head_idx, status, vq->hw->cvq, vq); if ((vq->vq_free_cnt < ((uint32_t)pkt_num + 2)) || (pkt_num < 1)) return -1; memcpy(vq->virtio_net_hdr_mz->addr, ctrl, sizeof(struct virtio_pmd_ctrl)); /* * Format is enforced in qemu code: * One TX packet for header; * At least one TX packet per argument; * One RX packet for ACK. */ vq->vq_ring.desc[head].flags = VRING_DESC_F_NEXT; vq->vq_ring.desc[head].addr = vq->virtio_net_hdr_mz->phys_addr; vq->vq_ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr); vq->vq_free_cnt--; i = vq->vq_ring.desc[head].next; for (k = 0; k < pkt_num; k++) { vq->vq_ring.desc[i].flags = VRING_DESC_F_NEXT; vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr + sizeof(struct virtio_net_ctrl_hdr) + sizeof(ctrl->status) + sizeof(uint8_t)*sum; vq->vq_ring.desc[i].len = dlen[k]; sum += dlen[k]; vq->vq_free_cnt--; i = vq->vq_ring.desc[i].next; } vq->vq_ring.desc[i].flags = VRING_DESC_F_WRITE; vq->vq_ring.desc[i].addr = vq->virtio_net_hdr_mz->phys_addr + sizeof(struct virtio_net_ctrl_hdr); vq->vq_ring.desc[i].len = sizeof(ctrl->status); vq->vq_free_cnt--; vq->vq_desc_head_idx = vq->vq_ring.desc[i].next; vq_update_avail_ring(vq, head); vq_update_avail_idx(vq); PMD_INIT_LOG(DEBUG, "vq->vq_queue_index = %d", vq->vq_queue_index); virtqueue_notify(vq); rte_rmb(); while (vq->vq_used_cons_idx == vq->vq_ring.used->idx) { rte_rmb(); usleep(100); } while (vq->vq_used_cons_idx != vq->vq_ring.used->idx) { uint32_t idx, desc_idx, used_idx; struct vring_used_elem *uep; used_idx = (uint32_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; idx = (uint32_t) uep->id; desc_idx = idx; while (vq->vq_ring.desc[desc_idx].flags & VRING_DESC_F_NEXT) { desc_idx = vq->vq_ring.desc[desc_idx].next; vq->vq_free_cnt++; } vq->vq_ring.desc[desc_idx].next = vq->vq_desc_head_idx; vq->vq_desc_head_idx = idx; vq->vq_used_cons_idx++; vq->vq_free_cnt++; } PMD_INIT_LOG(DEBUG, "vq->vq_free_cnt=%d\nvq->vq_desc_head_idx=%d", vq->vq_free_cnt, vq->vq_desc_head_idx); memcpy(&result, vq->virtio_net_hdr_mz->addr, sizeof(struct virtio_pmd_ctrl)); return result.status; } static int virtio_set_multiple_queues(struct rte_eth_dev *dev, uint16_t nb_queues) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; ctrl.hdr.class = VIRTIO_NET_CTRL_MQ; ctrl.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET; memcpy(ctrl.data, &nb_queues, sizeof(uint16_t)); dlen[0] = sizeof(uint16_t); ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); if (ret) { PMD_INIT_LOG(ERR, "Multiqueue configured but send command " "failed, this is too late now..."); return -EINVAL; } return 0; } void virtio_dev_queue_release(struct virtqueue *vq) { struct virtio_hw *hw = vq->hw; if (vq) { /* Select and deactivate the queue */ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->queue_id); VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0); rte_free(vq); vq = NULL; } } int virtio_dev_queue_setup(struct rte_eth_dev *dev, int queue_type, uint16_t queue_idx, uint16_t vtpci_queue_idx, uint16_t nb_desc, unsigned int socket_id, struct virtqueue **pvq) { char vq_name[VIRTQUEUE_MAX_NAME_SZ]; const struct rte_memzone *mz; uint16_t vq_size; int size; struct virtio_hw *hw = dev->data->dev_private; struct virtqueue *vq = NULL; /* Write the virtqueue index to the Queue Select Field */ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vtpci_queue_idx); PMD_INIT_LOG(DEBUG, "selecting queue: %d", vtpci_queue_idx); /* * Read the virtqueue size from the Queue Size field * Always power of 2 and if 0 virtqueue does not exist */ vq_size = VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM); PMD_INIT_LOG(DEBUG, "vq_size: %d nb_desc:%d", vq_size, nb_desc); if (vq_size == 0) { PMD_INIT_LOG(ERR, "%s: virtqueue does not exist", __func__); return -EINVAL; } if (!rte_is_power_of_2(vq_size)) { PMD_INIT_LOG(ERR, "%s: virtqueue size is not powerof 2", __func__); return -EINVAL; } if (queue_type == VTNET_RQ) { snprintf(vq_name, sizeof(vq_name), "port%d_rvq%d", dev->data->port_id, queue_idx); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); } else if (queue_type == VTNET_TQ) { snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d", dev->data->port_id, queue_idx); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); } else if (queue_type == VTNET_CQ) { snprintf(vq_name, sizeof(vq_name), "port%d_cvq", dev->data->port_id); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); } if (vq == NULL) { PMD_INIT_LOG(ERR, "%s: Can not allocate virtqueue", __func__); return (-ENOMEM); } vq->hw = hw; vq->port_id = dev->data->port_id; vq->queue_id = queue_idx; vq->vq_queue_index = vtpci_queue_idx; vq->vq_nentries = vq_size; if (nb_desc == 0 || nb_desc > vq_size) nb_desc = vq_size; vq->vq_free_cnt = nb_desc; /* * Reserve a memzone for vring elements */ size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN); vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN); PMD_INIT_LOG(DEBUG, "vring_size: %d, rounded_vring_size: %d", size, vq->vq_ring_size); mz = rte_memzone_reserve_aligned(vq_name, vq->vq_ring_size, socket_id, 0, VIRTIO_PCI_VRING_ALIGN); if (mz == NULL) { if (rte_errno == EEXIST) mz = rte_memzone_lookup(vq_name); if (mz == NULL) { rte_free(vq); return -ENOMEM; } } /* * Virtio PCI device VIRTIO_PCI_QUEUE_PF register is 32bit, * and only accepts 32 bit page frame number. * Check if the allocated physical memory exceeds 16TB. */ if ((mz->phys_addr + vq->vq_ring_size - 1) >> (VIRTIO_PCI_QUEUE_ADDR_SHIFT + 32)) { PMD_INIT_LOG(ERR, "vring address shouldn't be above 16TB!"); rte_free(vq); return -ENOMEM; } memset(mz->addr, 0, sizeof(mz->len)); vq->mz = mz; vq->vq_ring_mem = mz->phys_addr; vq->vq_ring_virt_mem = mz->addr; PMD_INIT_LOG(DEBUG, "vq->vq_ring_mem: 0x%"PRIx64, (uint64_t)mz->phys_addr); PMD_INIT_LOG(DEBUG, "vq->vq_ring_virt_mem: 0x%"PRIx64, (uint64_t)(uintptr_t)mz->addr); vq->virtio_net_hdr_mz = NULL; vq->virtio_net_hdr_mem = 0; if (queue_type == VTNET_TQ) { /* * For each xmit packet, allocate a virtio_net_hdr */ snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d_hdrzone", dev->data->port_id, queue_idx); vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name, vq_size * hw->vtnet_hdr_size, socket_id, 0, RTE_CACHE_LINE_SIZE); if (vq->virtio_net_hdr_mz == NULL) { if (rte_errno == EEXIST) vq->virtio_net_hdr_mz = rte_memzone_lookup(vq_name); if (vq->virtio_net_hdr_mz == NULL) { rte_free(vq); return -ENOMEM; } } vq->virtio_net_hdr_mem = vq->virtio_net_hdr_mz->phys_addr; memset(vq->virtio_net_hdr_mz->addr, 0, vq_size * hw->vtnet_hdr_size); } else if (queue_type == VTNET_CQ) { /* Allocate a page for control vq command, data and status */ snprintf(vq_name, sizeof(vq_name), "port%d_cvq_hdrzone", dev->data->port_id); vq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name, PAGE_SIZE, socket_id, 0, RTE_CACHE_LINE_SIZE); if (vq->virtio_net_hdr_mz == NULL) { if (rte_errno == EEXIST) vq->virtio_net_hdr_mz = rte_memzone_lookup(vq_name); if (vq->virtio_net_hdr_mz == NULL) { rte_free(vq); return -ENOMEM; } } vq->virtio_net_hdr_mem = vq->virtio_net_hdr_mz->phys_addr; memset(vq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE); } /* * Set guest physical address of the virtqueue * in VIRTIO_PCI_QUEUE_PFN config register of device */ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); *pvq = vq; return 0; } static int virtio_dev_cq_queue_setup(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx, uint32_t socket_id) { struct virtqueue *vq; int ret; struct virtio_hw *hw = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); ret = virtio_dev_queue_setup(dev, VTNET_CQ, VTNET_SQ_CQ_QUEUE_IDX, vtpci_queue_idx, 0, socket_id, &vq); if (ret < 0) { PMD_INIT_LOG(ERR, "control vq initialization failed"); return ret; } hw->cvq = vq; return 0; } static void virtio_free_queues(struct rte_eth_dev *dev) { unsigned int i; for (i = 0; i < dev->data->nb_rx_queues; i++) virtio_dev_rx_queue_release(dev->data->rx_queues[i]); dev->data->nb_rx_queues = 0; for (i = 0; i < dev->data->nb_tx_queues; i++) virtio_dev_tx_queue_release(dev->data->tx_queues[i]); dev->data->nb_tx_queues = 0; } static void virtio_dev_close(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "virtio_dev_close"); /* reset the NIC */ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) vtpci_irq_config(hw, VIRTIO_MSI_NO_VECTOR); vtpci_reset(hw); hw->started = 0; virtio_dev_free_mbufs(dev); virtio_free_queues(dev); } static void virtio_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control\n"); return; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC; ctrl.data[0] = 1; dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); if (ret) PMD_INIT_LOG(ERR, "Failed to enable promisc"); } static void virtio_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control\n"); return; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_PROMISC; ctrl.data[0] = 0; dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); if (ret) PMD_INIT_LOG(ERR, "Failed to disable promisc"); } static void virtio_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control\n"); return; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI; ctrl.data[0] = 1; dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); if (ret) PMD_INIT_LOG(ERR, "Failed to enable allmulticast"); } static void virtio_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int dlen[1]; int ret; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_RX)) { PMD_INIT_LOG(INFO, "host does not support rx control\n"); return; } ctrl.hdr.class = VIRTIO_NET_CTRL_RX; ctrl.hdr.cmd = VIRTIO_NET_CTRL_RX_ALLMULTI; ctrl.data[0] = 0; dlen[0] = 1; ret = virtio_send_command(hw->cvq, &ctrl, dlen, 1); if (ret) PMD_INIT_LOG(ERR, "Failed to disable allmulticast"); } /* * dev_ops for virtio, bare necessities for basic operation */ static const struct eth_dev_ops virtio_eth_dev_ops = { .dev_configure = virtio_dev_configure, .dev_start = virtio_dev_start, .dev_stop = virtio_dev_stop, .dev_close = virtio_dev_close, .promiscuous_enable = virtio_dev_promiscuous_enable, .promiscuous_disable = virtio_dev_promiscuous_disable, .allmulticast_enable = virtio_dev_allmulticast_enable, .allmulticast_disable = virtio_dev_allmulticast_disable, .dev_infos_get = virtio_dev_info_get, .stats_get = virtio_dev_stats_get, .stats_reset = virtio_dev_stats_reset, .link_update = virtio_dev_link_update, .rx_queue_setup = virtio_dev_rx_queue_setup, .rx_queue_release = virtio_dev_rx_queue_release, .tx_queue_setup = virtio_dev_tx_queue_setup, .tx_queue_release = virtio_dev_tx_queue_release, /* collect stats per queue */ .queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set, .vlan_filter_set = virtio_vlan_filter_set, .mac_addr_add = virtio_mac_addr_add, .mac_addr_remove = virtio_mac_addr_remove, .mac_addr_set = virtio_mac_addr_set, }; static inline int virtio_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /** * Atomically writes the link status information into global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static inline int virtio_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { unsigned i; for (i = 0; i < dev->data->nb_tx_queues; i++) { const struct virtqueue *txvq = dev->data->tx_queues[i]; if (txvq == NULL) continue; stats->opackets += txvq->packets; stats->obytes += txvq->bytes; stats->oerrors += txvq->errors; if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) { stats->q_opackets[i] = txvq->packets; stats->q_obytes[i] = txvq->bytes; } } for (i = 0; i < dev->data->nb_rx_queues; i++) { const struct virtqueue *rxvq = dev->data->rx_queues[i]; if (rxvq == NULL) continue; stats->ipackets += rxvq->packets; stats->ibytes += rxvq->bytes; stats->ierrors += rxvq->errors; if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) { stats->q_ipackets[i] = rxvq->packets; stats->q_ibytes[i] = rxvq->bytes; } } stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed; } static void virtio_dev_stats_reset(struct rte_eth_dev *dev) { unsigned int i; for (i = 0; i < dev->data->nb_tx_queues; i++) { struct virtqueue *txvq = dev->data->tx_queues[i]; if (txvq == NULL) continue; txvq->packets = 0; txvq->bytes = 0; txvq->errors = 0; } for (i = 0; i < dev->data->nb_rx_queues; i++) { struct virtqueue *rxvq = dev->data->rx_queues[i]; if (rxvq == NULL) continue; rxvq->packets = 0; rxvq->bytes = 0; rxvq->errors = 0; } dev->data->rx_mbuf_alloc_failed = 0; } static void virtio_set_hwaddr(struct virtio_hw *hw) { vtpci_write_dev_config(hw, offsetof(struct virtio_net_config, mac), &hw->mac_addr, ETHER_ADDR_LEN); } static void virtio_get_hwaddr(struct virtio_hw *hw) { if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) { vtpci_read_dev_config(hw, offsetof(struct virtio_net_config, mac), &hw->mac_addr, ETHER_ADDR_LEN); } else { eth_random_addr(&hw->mac_addr[0]); virtio_set_hwaddr(hw); } } static void virtio_mac_table_set(struct virtio_hw *hw, const struct virtio_net_ctrl_mac *uc, const struct virtio_net_ctrl_mac *mc) { struct virtio_pmd_ctrl ctrl; int err, len[2]; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { PMD_DRV_LOG(INFO, "host does not support mac table\n"); return; } ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_TABLE_SET; len[0] = uc->entries * ETHER_ADDR_LEN + sizeof(uc->entries); memcpy(ctrl.data, uc, len[0]); len[1] = mc->entries * ETHER_ADDR_LEN + sizeof(mc->entries); memcpy(ctrl.data + len[0], mc, len[1]); err = virtio_send_command(hw->cvq, &ctrl, len, 2); if (err != 0) PMD_DRV_LOG(NOTICE, "mac table set failed: %d", err); } static void virtio_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq __rte_unused) { struct virtio_hw *hw = dev->data->dev_private; const struct ether_addr *addrs = dev->data->mac_addrs; unsigned int i; struct virtio_net_ctrl_mac *uc, *mc; if (index >= VIRTIO_MAX_MAC_ADDRS) { PMD_DRV_LOG(ERR, "mac address index %u out of range", index); return; } uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); uc->entries = 0; mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); mc->entries = 0; for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { const struct ether_addr *addr = (i == index) ? mac_addr : addrs + i; struct virtio_net_ctrl_mac *tbl = is_multicast_ether_addr(addr) ? mc : uc; memcpy(&tbl->macs[tbl->entries++], addr, ETHER_ADDR_LEN); } virtio_mac_table_set(hw, uc, mc); } static void virtio_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) { struct virtio_hw *hw = dev->data->dev_private; struct ether_addr *addrs = dev->data->mac_addrs; struct virtio_net_ctrl_mac *uc, *mc; unsigned int i; if (index >= VIRTIO_MAX_MAC_ADDRS) { PMD_DRV_LOG(ERR, "mac address index %u out of range", index); return; } uc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(uc->entries)); uc->entries = 0; mc = alloca(VIRTIO_MAX_MAC_ADDRS * ETHER_ADDR_LEN + sizeof(mc->entries)); mc->entries = 0; for (i = 0; i < VIRTIO_MAX_MAC_ADDRS; i++) { struct virtio_net_ctrl_mac *tbl; if (i == index || is_zero_ether_addr(addrs + i)) continue; tbl = is_multicast_ether_addr(addrs + i) ? mc : uc; memcpy(&tbl->macs[tbl->entries++], addrs + i, ETHER_ADDR_LEN); } virtio_mac_table_set(hw, uc, mc); } static void virtio_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) { struct virtio_hw *hw = dev->data->dev_private; memcpy(hw->mac_addr, mac_addr, ETHER_ADDR_LEN); /* Use atomic update if available */ if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_MAC_ADDR)) { struct virtio_pmd_ctrl ctrl; int len = ETHER_ADDR_LEN; ctrl.hdr.class = VIRTIO_NET_CTRL_MAC; ctrl.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; memcpy(ctrl.data, mac_addr, ETHER_ADDR_LEN); virtio_send_command(hw->cvq, &ctrl, &len, 1); } else if (vtpci_with_feature(hw, VIRTIO_NET_F_MAC)) virtio_set_hwaddr(hw); } static int virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { struct virtio_hw *hw = dev->data->dev_private; struct virtio_pmd_ctrl ctrl; int len; if (!vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) return -ENOTSUP; ctrl.hdr.class = VIRTIO_NET_CTRL_VLAN; ctrl.hdr.cmd = on ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; memcpy(ctrl.data, &vlan_id, sizeof(vlan_id)); len = sizeof(vlan_id); return virtio_send_command(hw->cvq, &ctrl, &len, 1); } static void virtio_negotiate_features(struct virtio_hw *hw) { uint32_t host_features; /* Prepare guest_features: feature that driver wants to support */ hw->guest_features = VIRTIO_PMD_GUEST_FEATURES; PMD_INIT_LOG(DEBUG, "guest_features before negotiate = %x", hw->guest_features); /* Read device(host) feature bits */ host_features = VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES); PMD_INIT_LOG(DEBUG, "host_features before negotiate = %x", host_features); /* * Negotiate features: Subset of device feature bits are written back * guest feature bits. */ hw->guest_features = vtpci_negotiate_features(hw, host_features); PMD_INIT_LOG(DEBUG, "features after negotiate = %x", hw->guest_features); } #ifdef RTE_EXEC_ENV_LINUXAPP static int parse_sysfs_value(const char *filename, unsigned long *val) { FILE *f; char buf[BUFSIZ]; char *end = NULL; f = fopen(filename, "r"); if (f == NULL) { PMD_INIT_LOG(ERR, "%s(): cannot open sysfs value %s", __func__, filename); return -1; } if (fgets(buf, sizeof(buf), f) == NULL) { PMD_INIT_LOG(ERR, "%s(): cannot read sysfs value %s", __func__, filename); fclose(f); return -1; } *val = strtoul(buf, &end, 0); if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { PMD_INIT_LOG(ERR, "%s(): cannot parse sysfs value %s", __func__, filename); fclose(f); return -1; } fclose(f); return 0; } static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen, unsigned int *uio_num) { struct dirent *e; DIR *dir; char dirname[PATH_MAX]; /* depending on kernel version, uio can be located in uio/uioX * or uio:uioX */ snprintf(dirname, sizeof(dirname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio", loc->domain, loc->bus, loc->devid, loc->function); dir = opendir(dirname); if (dir == NULL) { /* retry with the parent directory */ snprintf(dirname, sizeof(dirname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT, loc->domain, loc->bus, loc->devid, loc->function); dir = opendir(dirname); if (dir == NULL) { PMD_INIT_LOG(ERR, "Cannot opendir %s", dirname); return -1; } } /* take the first file starting with "uio" */ while ((e = readdir(dir)) != NULL) { /* format could be uio%d ...*/ int shortprefix_len = sizeof("uio") - 1; /* ... or uio:uio%d */ int longprefix_len = sizeof("uio:uio") - 1; char *endptr; if (strncmp(e->d_name, "uio", 3) != 0) continue; /* first try uio%d */ errno = 0; *uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { snprintf(buf, buflen, "%s/uio%u", dirname, *uio_num); break; } /* then try uio:uio%d */ errno = 0; *uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + longprefix_len)) { snprintf(buf, buflen, "%s/uio:uio%u", dirname, *uio_num); break; } } closedir(dir); /* No uio resource found */ if (e == NULL) { PMD_INIT_LOG(ERR, "Could not find uio resource"); return -1; } return 0; } static int virtio_has_msix(const struct rte_pci_addr *loc) { DIR *d; char dirname[PATH_MAX]; snprintf(dirname, sizeof(dirname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/msi_irqs", loc->domain, loc->bus, loc->devid, loc->function); d = opendir(dirname); if (d) closedir(d); return (d != NULL); } /* Extract I/O port numbers from sysfs */ static int virtio_resource_init_by_uio(struct rte_pci_device *pci_dev) { char dirname[PATH_MAX]; char filename[PATH_MAX]; unsigned long start, size; unsigned int uio_num; if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname), &uio_num) < 0) return -1; /* get portio size */ snprintf(filename, sizeof(filename), "%s/portio/port0/size", dirname); if (parse_sysfs_value(filename, &size) < 0) { PMD_INIT_LOG(ERR, "%s(): cannot parse size", __func__); return -1; } /* get portio start */ snprintf(filename, sizeof(filename), "%s/portio/port0/start", dirname); if (parse_sysfs_value(filename, &start) < 0) { PMD_INIT_LOG(ERR, "%s(): cannot parse portio start", __func__); return -1; } pci_dev->mem_resource[0].addr = (void *)(uintptr_t)start; pci_dev->mem_resource[0].len = (uint64_t)size; PMD_INIT_LOG(DEBUG, "PCI Port IO found start=0x%lx with size=0x%lx", start, size); /* save fd */ memset(dirname, 0, sizeof(dirname)); snprintf(dirname, sizeof(dirname), "/dev/uio%u", uio_num); pci_dev->intr_handle.fd = open(dirname, O_RDWR); if (pci_dev->intr_handle.fd < 0) { PMD_INIT_LOG(ERR, "Cannot open %s: %s\n", dirname, strerror(errno)); return -1; } pci_dev->intr_handle.type = RTE_INTR_HANDLE_UIO; pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC; return 0; } /* Extract port I/O numbers from proc/ioports */ static int virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev) { uint16_t start, end; int size; FILE *fp; char *line = NULL; char pci_id[16]; int found = 0; size_t linesz; snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); fp = fopen("/proc/ioports", "r"); if (fp == NULL) { PMD_INIT_LOG(ERR, "%s(): can't open ioports", __func__); return -1; } while (getdelim(&line, &linesz, '\n', fp) > 0) { char *ptr = line; char *left; int n; n = strcspn(ptr, ":"); ptr[n] = 0; left = &ptr[n+1]; while (*left && isspace(*left)) left++; if (!strncmp(left, pci_id, strlen(pci_id))) { found = 1; while (*ptr && isspace(*ptr)) ptr++; sscanf(ptr, "%04hx-%04hx", &start, &end); size = end - start + 1; break; } } free(line); fclose(fp); if (!found) return -1; pci_dev->mem_resource[0].addr = (void *)(uintptr_t)(uint32_t)start; pci_dev->mem_resource[0].len = (uint64_t)size; PMD_INIT_LOG(DEBUG, "PCI Port IO found start=0x%x with size=0x%x", start, size); /* can't support lsc interrupt without uio */ pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC; return 0; } /* Extract I/O port numbers from sysfs */ static int virtio_resource_init(struct rte_pci_device *pci_dev) { if (virtio_resource_init_by_uio(pci_dev) == 0) return 0; else return virtio_resource_init_by_ioports(pci_dev); } #else static int virtio_has_msix(const struct rte_pci_addr *loc __rte_unused) { /* nic_uio does not enable interrupts, return 0 (false). */ return 0; } static int virtio_resource_init(struct rte_pci_device *pci_dev __rte_unused) { /* no setup required */ return 0; } #endif /* * Process Virtio Config changed interrupt and call the callback * if link state changed. */ static void virtio_interrupt_handler(__rte_unused struct rte_intr_handle *handle, void *param) { struct rte_eth_dev *dev = param; struct virtio_hw *hw = dev->data->dev_private; uint8_t isr; /* Read interrupt status which clears interrupt */ isr = vtpci_isr(hw); PMD_DRV_LOG(INFO, "interrupt status = %#x", isr); if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) PMD_DRV_LOG(ERR, "interrupt enable failed"); if (isr & VIRTIO_PCI_ISR_CONFIG) { if (virtio_dev_link_update(dev, 0) == 0) _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); } } static void rx_func_get(struct rte_eth_dev *eth_dev) { struct virtio_hw *hw = eth_dev->data->dev_private; if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts; else eth_dev->rx_pkt_burst = &virtio_recv_pkts; } /* * This function is based on probe() function in virtio_pci.c * It returns 0 on success. */ static int eth_virtio_dev_init(struct rte_eth_dev *eth_dev) { struct virtio_hw *hw = eth_dev->data->dev_private; struct virtio_net_config *config; struct virtio_net_config local_config; uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); eth_dev->dev_ops = &virtio_eth_dev_ops; eth_dev->tx_pkt_burst = &virtio_xmit_pkts; if (rte_eal_process_type() == RTE_PROC_SECONDARY) { rx_func_get(eth_dev); return 0; } /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("virtio", ETHER_ADDR_LEN, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses", ETHER_ADDR_LEN); return -ENOMEM; } pci_dev = eth_dev->pci_dev; if (virtio_resource_init(pci_dev) < 0) return -1; hw->use_msix = virtio_has_msix(&pci_dev->addr); hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; /* Reset the device although not necessary at startup */ vtpci_reset(hw); /* Tell the host we've noticed this device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_ACK); /* Tell the host we've known how to drive the device. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER); virtio_negotiate_features(hw); rx_func_get(eth_dev); /* Setting up rx_header size for the device */ if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); else hw->vtnet_hdr_size = sizeof(struct virtio_net_hdr); /* Copy the permanent MAC address to: virtio_hw */ virtio_get_hwaddr(hw); ether_addr_copy((struct ether_addr *) hw->mac_addr, ð_dev->data->mac_addrs[0]); PMD_INIT_LOG(DEBUG, "PORT MAC: %02X:%02X:%02X:%02X:%02X:%02X", hw->mac_addr[0], hw->mac_addr[1], hw->mac_addr[2], hw->mac_addr[3], hw->mac_addr[4], hw->mac_addr[5]); if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) { config = &local_config; if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { offset_conf += sizeof(config->status); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_STATUS is not supported"); config->status = 0; } if (vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) { offset_conf += sizeof(config->max_virtqueue_pairs); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_MQ is not supported"); config->max_virtqueue_pairs = 1; } vtpci_read_dev_config(hw, 0, (uint8_t *)config, offset_conf); hw->max_rx_queues = (VIRTIO_MAX_RX_QUEUES < config->max_virtqueue_pairs) ? VIRTIO_MAX_RX_QUEUES : config->max_virtqueue_pairs; hw->max_tx_queues = (VIRTIO_MAX_TX_QUEUES < config->max_virtqueue_pairs) ? VIRTIO_MAX_TX_QUEUES : config->max_virtqueue_pairs; virtio_dev_cq_queue_setup(eth_dev, config->max_virtqueue_pairs * 2, SOCKET_ID_ANY); PMD_INIT_LOG(DEBUG, "config->max_virtqueue_pairs=%d", config->max_virtqueue_pairs); PMD_INIT_LOG(DEBUG, "config->status=%d", config->status); PMD_INIT_LOG(DEBUG, "PORT MAC: %02X:%02X:%02X:%02X:%02X:%02X", config->mac[0], config->mac[1], config->mac[2], config->mac[3], config->mac[4], config->mac[5]); } else { hw->max_rx_queues = 1; hw->max_tx_queues = 1; } eth_dev->data->nb_rx_queues = hw->max_rx_queues; eth_dev->data->nb_tx_queues = hw->max_tx_queues; PMD_INIT_LOG(DEBUG, "hw->max_rx_queues=%d hw->max_tx_queues=%d", hw->max_rx_queues, hw->max_tx_queues); PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); /* Setup interrupt callback */ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) rte_intr_callback_register(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); virtio_dev_cq_start(eth_dev); return 0; } static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct virtio_hw *hw = eth_dev->data->dev_private; PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() == RTE_PROC_SECONDARY) return -EPERM; if (hw->started == 1) { virtio_dev_stop(eth_dev); virtio_dev_close(eth_dev); } pci_dev = eth_dev->pci_dev; eth_dev->dev_ops = NULL; eth_dev->tx_pkt_burst = NULL; eth_dev->rx_pkt_burst = NULL; virtio_dev_queue_release(hw->cvq); rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; /* reset interrupt callback */ if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) rte_intr_callback_unregister(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); PMD_INIT_LOG(DEBUG, "dev_uninit completed"); return 0; } static struct eth_driver rte_virtio_pmd = { .pci_drv = { .name = "rte_virtio_pmd", .id_table = pci_id_virtio_map, .drv_flags = RTE_PCI_DRV_DETACHABLE, }, .eth_dev_init = eth_virtio_dev_init, .eth_dev_uninit = eth_virtio_dev_uninit, .dev_private_size = sizeof(struct virtio_hw), }; /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of PCI virtio devices. * Returns 0 on success. */ static int rte_virtio_pmd_init(const char *name __rte_unused, const char *param __rte_unused) { if (rte_eal_iopl_init() != 0) { PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD"); return -1; } rte_eth_driver_register(&rte_virtio_pmd); return 0; } /* * Configure virtio device * It returns 0 on success. */ static int virtio_dev_configure(struct rte_eth_dev *dev) { const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; struct virtio_hw *hw = dev->data->dev_private; struct rte_pci_device *pci_dev = dev->pci_dev; PMD_INIT_LOG(DEBUG, "configure"); if (rxmode->hw_ip_checksum) { PMD_DRV_LOG(ERR, "HW IP checksum not supported"); return (-EINVAL); } hw->vlan_strip = rxmode->hw_vlan_strip; if (rxmode->hw_vlan_filter && !vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { PMD_DRV_LOG(NOTICE, "vlan filtering not available on this host"); return -ENOTSUP; } if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC) if (vtpci_irq_config(hw, 0) == VIRTIO_MSI_NO_VECTOR) { PMD_DRV_LOG(ERR, "failed to set config vector"); return -EBUSY; } return 0; } static int virtio_dev_start(struct rte_eth_dev *dev) { uint16_t nb_queues, i; struct virtio_hw *hw = dev->data->dev_private; struct rte_pci_device *pci_dev = dev->pci_dev; /* check if lsc interrupt feature is enabled */ if ((dev->data->dev_conf.intr_conf.lsc) && (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) { if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { PMD_DRV_LOG(ERR, "link status not supported by host"); return -ENOTSUP; } if (rte_intr_enable(&dev->pci_dev->intr_handle) < 0) { PMD_DRV_LOG(ERR, "interrupt enable failed"); return -EIO; } } /* Initialize Link state */ virtio_dev_link_update(dev, 0); /* On restart after stop do not touch queues */ if (hw->started) return 0; /* Do final configuration before rx/tx engine starts */ virtio_dev_rxtx_start(dev); vtpci_reinit_complete(hw); hw->started = 1; /*Notify the backend *Otherwise the tap backend might already stop its queue due to fullness. *vhost backend will have no chance to be waked up */ nb_queues = dev->data->nb_rx_queues; if (nb_queues > 1) { if (virtio_set_multiple_queues(dev, nb_queues) != 0) return -EINVAL; } PMD_INIT_LOG(DEBUG, "nb_queues=%d", nb_queues); for (i = 0; i < nb_queues; i++) virtqueue_notify(dev->data->rx_queues[i]); PMD_INIT_LOG(DEBUG, "Notified backend at initialization"); for (i = 0; i < dev->data->nb_rx_queues; i++) VIRTQUEUE_DUMP((struct virtqueue *)dev->data->rx_queues[i]); for (i = 0; i < dev->data->nb_tx_queues; i++) VIRTQUEUE_DUMP((struct virtqueue *)dev->data->tx_queues[i]); return 0; } static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) { struct rte_mbuf *buf; int i, mbuf_num = 0; for (i = 0; i < dev->data->nb_rx_queues; i++) { PMD_INIT_LOG(DEBUG, "Before freeing rxq[%d] used and unused buf", i); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->rx_queues[i]); PMD_INIT_LOG(DEBUG, "rx_queues[%d]=%p", i, dev->data->rx_queues[i]); while ((buf = (struct rte_mbuf *)virtqueue_detatch_unused( dev->data->rx_queues[i])) != NULL) { rte_pktmbuf_free(buf); mbuf_num++; } PMD_INIT_LOG(DEBUG, "free %d mbufs", mbuf_num); PMD_INIT_LOG(DEBUG, "After freeing rxq[%d] used and unused buf", i); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->rx_queues[i]); } for (i = 0; i < dev->data->nb_tx_queues; i++) { PMD_INIT_LOG(DEBUG, "Before freeing txq[%d] used and unused bufs", i); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->tx_queues[i]); mbuf_num = 0; while ((buf = (struct rte_mbuf *)virtqueue_detatch_unused( dev->data->tx_queues[i])) != NULL) { rte_pktmbuf_free(buf); mbuf_num++; } PMD_INIT_LOG(DEBUG, "free %d mbufs", mbuf_num); PMD_INIT_LOG(DEBUG, "After freeing txq[%d] used and unused buf", i); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->tx_queues[i]); } } /* * Stop device: disable interrupt and mark link down */ static void virtio_dev_stop(struct rte_eth_dev *dev) { struct rte_eth_link link; PMD_INIT_LOG(DEBUG, "stop"); if (dev->data->dev_conf.intr_conf.lsc) rte_intr_disable(&dev->pci_dev->intr_handle); memset(&link, 0, sizeof(link)); virtio_dev_atomic_write_link_status(dev, &link); } static int virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete) { struct rte_eth_link link, old; uint16_t status; struct virtio_hw *hw = dev->data->dev_private; memset(&link, 0, sizeof(link)); virtio_dev_atomic_read_link_status(dev, &link); old = link; link.link_duplex = FULL_DUPLEX; link.link_speed = SPEED_10G; if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { PMD_INIT_LOG(DEBUG, "Get link status from hw"); vtpci_read_dev_config(hw, offsetof(struct virtio_net_config, status), &status, sizeof(status)); if ((status & VIRTIO_NET_S_LINK_UP) == 0) { link.link_status = 0; PMD_INIT_LOG(DEBUG, "Port %d is down", dev->data->port_id); } else { link.link_status = 1; PMD_INIT_LOG(DEBUG, "Port %d is up", dev->data->port_id); } } else { link.link_status = 1; /* Link up */ } virtio_dev_atomic_write_link_status(dev, &link); return (old.link_status == link.link_status) ? -1 : 0; } static void virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct virtio_hw *hw = dev->data->dev_private; dev_info->driver_name = dev->driver->pci_drv.name; dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues; dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues; dev_info->min_rx_bufsize = VIRTIO_MIN_RX_BUFSIZE; dev_info->max_rx_pktlen = VIRTIO_MAX_RX_PKTLEN; dev_info->max_mac_addrs = VIRTIO_MAX_MAC_ADDRS; dev_info->default_txconf = (struct rte_eth_txconf) { .txq_flags = ETH_TXQ_FLAGS_NOOFFLOADS }; } /* * It enables testpmd to collect per queue stats. */ static int virtio_dev_queue_stats_mapping_set(__rte_unused struct rte_eth_dev *eth_dev, __rte_unused uint16_t queue_id, __rte_unused uint8_t stat_idx, __rte_unused uint8_t is_rx) { return 0; } static struct rte_driver rte_virtio_driver = { .type = PMD_PDEV, .init = rte_virtio_pmd_init, }; PMD_REGISTER_DRIVER(rte_virtio_driver); ================================================ FILE: drivers/net/virtio/virtio_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_ETHDEV_H_ #define _VIRTIO_ETHDEV_H_ #include #include "virtio_pci.h" #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 #define SPEED_10G 10000 #define HALF_DUPLEX 1 #define FULL_DUPLEX 2 #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif #define VIRTIO_MAX_RX_QUEUES 128 #define VIRTIO_MAX_TX_QUEUES 128 #define VIRTIO_MAX_MAC_ADDRS 64 #define VIRTIO_MIN_RX_BUFSIZE 64 #define VIRTIO_MAX_RX_PKTLEN 9728 /* Features desired/implemented by this driver. */ #define VIRTIO_PMD_GUEST_FEATURES \ (1u << VIRTIO_NET_F_MAC | \ 1u << VIRTIO_NET_F_STATUS | \ 1u << VIRTIO_NET_F_MQ | \ 1u << VIRTIO_NET_F_CTRL_MAC_ADDR | \ 1u << VIRTIO_NET_F_CTRL_VQ | \ 1u << VIRTIO_NET_F_CTRL_RX | \ 1u << VIRTIO_NET_F_CTRL_VLAN | \ 1u << VIRTIO_NET_F_MRG_RXBUF) /* * CQ function prototype */ void virtio_dev_cq_start(struct rte_eth_dev *dev); /* * RX/TX function prototypes */ void virtio_dev_rxtx_start(struct rte_eth_dev *dev); int virtio_dev_queue_setup(struct rte_eth_dev *dev, int queue_type, uint16_t queue_idx, uint16_t vtpci_queue_idx, uint16_t nb_desc, unsigned int socket_id, struct virtqueue **pvq); void virtio_dev_queue_release(struct virtqueue *vq); int virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); void virtio_dev_rx_queue_release(void *rxq); int virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); void virtio_dev_tx_queue_release(void *txq); uint16_t virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); /* * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us * frames larger than 1514 bytes. We do not yet support software LRO * via tcp_lro_rx(). */ #define VTNET_LRO_FEATURES (VIRTIO_NET_F_GUEST_TSO4 | \ VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_ECN) #endif /* _VIRTIO_ETHDEV_H_ */ ================================================ FILE: drivers/net/virtio/virtio_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_LOGS_H_ #define _VIRTIO_LOGS_H_ #include #ifdef RTE_LIBRTE_VIRTIO_DEBUG_INIT #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_LOG(level, fmt, args...) do { } while(0) #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s() rx: " fmt , __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s() tx: " fmt , __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DRIVER #define PMD_DRV_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt , __func__, ## args) #else #define PMD_DRV_LOG(level, fmt, args...) do { } while(0) #endif #endif /* _VIRTIO_LOGS_H_ */ ================================================ FILE: drivers/net/virtio/virtio_pci.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "virtio_pci.h" #include "virtio_logs.h" static uint8_t vtpci_get_status(struct virtio_hw *); void vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, void *dst, int length) { uint64_t off; uint8_t *d; int size; off = VIRTIO_PCI_CONFIG(hw) + offset; for (d = dst; length > 0; d += size, off += size, length -= size) { if (length >= 4) { size = 4; *(uint32_t *)d = VIRTIO_READ_REG_4(hw, off); } else if (length >= 2) { size = 2; *(uint16_t *)d = VIRTIO_READ_REG_2(hw, off); } else { size = 1; *d = VIRTIO_READ_REG_1(hw, off); } } } void vtpci_write_dev_config(struct virtio_hw *hw, uint64_t offset, void *src, int length) { uint64_t off; uint8_t *s; int size; off = VIRTIO_PCI_CONFIG(hw) + offset; for (s = src; length > 0; s += size, off += size, length -= size) { if (length >= 4) { size = 4; VIRTIO_WRITE_REG_4(hw, off, *(uint32_t *)s); } else if (length >= 2) { size = 2; VIRTIO_WRITE_REG_2(hw, off, *(uint16_t *)s); } else { size = 1; VIRTIO_WRITE_REG_1(hw, off, *s); } } } uint32_t vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features) { uint32_t features; /* * Limit negotiated features to what the driver, virtqueue, and * host all support. */ features = host_features & hw->guest_features; VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features); return features; } void vtpci_reset(struct virtio_hw *hw) { /* * Setting the status to RESET sets the host device to * the original, uninitialized state. */ vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_RESET); vtpci_get_status(hw); } void vtpci_reinit_complete(struct virtio_hw *hw) { vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); } static uint8_t vtpci_get_status(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); } void vtpci_set_status(struct virtio_hw *hw, uint8_t status) { if (status != VIRTIO_CONFIG_STATUS_RESET) status = (uint8_t)(status | vtpci_get_status(hw)); VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status); } uint8_t vtpci_isr(struct virtio_hw *hw) { return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR); } /* Enable one vector (0) for Link State Intrerrupt */ uint16_t vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) { VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec); return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); } ================================================ FILE: drivers/net/virtio/virtio_pci.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_PCI_H_ #define _VIRTIO_PCI_H_ #include #ifdef __FreeBSD__ #include #include #else #include #endif #include struct virtqueue; /* VirtIO PCI vendor/device ID. */ #define VIRTIO_PCI_VENDORID 0x1AF4 #define VIRTIO_PCI_DEVICEID_MIN 0x1000 #define VIRTIO_PCI_DEVICEID_MAX 0x103F /* VirtIO ABI version, this must match exactly. */ #define VIRTIO_PCI_ABI_VERSION 0 /* * VirtIO Header, located in BAR 0. */ #define VIRTIO_PCI_HOST_FEATURES 0 /* host's supported features (32bit, RO)*/ #define VIRTIO_PCI_GUEST_FEATURES 4 /* guest's supported features (32, RW) */ #define VIRTIO_PCI_QUEUE_PFN 8 /* physical address of VQ (32, RW) */ #define VIRTIO_PCI_QUEUE_NUM 12 /* number of ring entries (16, RO) */ #define VIRTIO_PCI_QUEUE_SEL 14 /* current VQ selection (16, RW) */ #define VIRTIO_PCI_QUEUE_NOTIFY 16 /* notify host regarding VQ (16, RW) */ #define VIRTIO_PCI_STATUS 18 /* device status register (8, RW) */ #define VIRTIO_PCI_ISR 19 /* interrupt status register, reading * also clears the register (8, RO) */ /* Only if MSIX is enabled: */ #define VIRTIO_MSI_CONFIG_VECTOR 20 /* configuration change vector (16, RW) */ #define VIRTIO_MSI_QUEUE_VECTOR 22 /* vector for selected VQ notifications (16, RW) */ /* The bit of the ISR which indicates a device has an interrupt. */ #define VIRTIO_PCI_ISR_INTR 0x1 /* The bit of the ISR which indicates a device configuration change. */ #define VIRTIO_PCI_ISR_CONFIG 0x2 /* Vector value used to disable MSI for queue. */ #define VIRTIO_MSI_NO_VECTOR 0xFFFF /* VirtIO device IDs. */ #define VIRTIO_ID_NETWORK 0x01 #define VIRTIO_ID_BLOCK 0x02 #define VIRTIO_ID_CONSOLE 0x03 #define VIRTIO_ID_ENTROPY 0x04 #define VIRTIO_ID_BALLOON 0x05 #define VIRTIO_ID_IOMEMORY 0x06 #define VIRTIO_ID_9P 0x09 /* Status byte for guest to report progress. */ #define VIRTIO_CONFIG_STATUS_RESET 0x00 #define VIRTIO_CONFIG_STATUS_ACK 0x01 #define VIRTIO_CONFIG_STATUS_DRIVER 0x02 #define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 #define VIRTIO_CONFIG_STATUS_FAILED 0x80 /* * Each virtqueue indirect descriptor list must be physically contiguous. * To allow us to malloc(9) each list individually, limit the number * supported to what will fit in one page. With 4KB pages, this is a limit * of 256 descriptors. If there is ever a need for more, we can switch to * contigmalloc(9) for the larger allocations, similar to what * bus_dmamem_alloc(9) does. * * Note the sizeof(struct vring_desc) is 16 bytes. */ #define VIRTIO_MAX_INDIRECT ((int) (PAGE_SIZE / 16)) /* The feature bitmap for virtio net */ #define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ #define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ #define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ #define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ #define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ #define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ #define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ #define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ #define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ #define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ #define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ #define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ #define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ #define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the * network */ #define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow * Steering */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ /* Do we get callbacks when the ring is completely used, even if we've * suppressed them? */ #define VIRTIO_F_NOTIFY_ON_EMPTY 24 /* Can the device handle any descriptor layout? */ #define VIRTIO_F_ANY_LAYOUT 27 /* We support indirect buffer descriptors */ #define VIRTIO_RING_F_INDIRECT_DESC 28 /* * Some VirtIO feature bits (currently bits 28 through 31) are * reserved for the transport being used (eg. virtio_ring), the * rest are per-device feature bits. */ #define VIRTIO_TRANSPORT_F_START 28 #define VIRTIO_TRANSPORT_F_END 32 /* The Guest publishes the used index for which it expects an interrupt * at the end of the avail ring. Host should ignore the avail->flags field. */ /* The Host publishes the avail index for which it expects a kick * at the end of the used ring. Guest should ignore the used->flags field. */ #define VIRTIO_RING_F_EVENT_IDX 29 #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ #define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ /* * Maximum number of virtqueues per device. */ #define VIRTIO_MAX_VIRTQUEUES 8 struct virtio_hw { struct virtqueue *cvq; uint32_t io_base; uint32_t guest_features; uint32_t max_tx_queues; uint32_t max_rx_queues; uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; uint8_t started; uint8_t mac_addr[ETHER_ADDR_LEN]; }; /* * This structure is just a reference to read * net device specific config space; it just a chodu structure * */ struct virtio_net_config { /* The config defining mac address (if VIRTIO_NET_F_MAC) */ uint8_t mac[ETHER_ADDR_LEN]; /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ uint16_t status; uint16_t max_virtqueue_pairs; } __attribute__((packed)); /* * The remaining space is defined by each driver as the per-driver * configuration space. */ #define VIRTIO_PCI_CONFIG(hw) (((hw)->use_msix) ? 24 : 20) /* * How many bits to shift physical queue address written to QUEUE_PFN. * 12 is historical, and due to x86 page size. */ #define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 /* The alignment to use between consumer and producer parts of vring. */ #define VIRTIO_PCI_VRING_ALIGN 4096 #ifdef __FreeBSD__ static inline void outb_p(unsigned char data, unsigned int port) { outb(port, (u_char)data); } static inline void outw_p(unsigned short data, unsigned int port) { outw(port, (u_short)data); } static inline void outl_p(unsigned int data, unsigned int port) { outl(port, (u_int)data); } #endif #define VIRTIO_PCI_REG_ADDR(hw, reg) \ (unsigned short)((hw)->io_base + (reg)) #define VIRTIO_READ_REG_1(hw, reg) \ inb((VIRTIO_PCI_REG_ADDR((hw), (reg)))) #define VIRTIO_WRITE_REG_1(hw, reg, value) \ outb_p((unsigned char)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) #define VIRTIO_READ_REG_2(hw, reg) \ inw((VIRTIO_PCI_REG_ADDR((hw), (reg)))) #define VIRTIO_WRITE_REG_2(hw, reg, value) \ outw_p((unsigned short)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) #define VIRTIO_READ_REG_4(hw, reg) \ inl((VIRTIO_PCI_REG_ADDR((hw), (reg)))) #define VIRTIO_WRITE_REG_4(hw, reg, value) \ outl_p((unsigned int)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) static inline int vtpci_with_feature(struct virtio_hw *hw, uint32_t bit) { return (hw->guest_features & (1u << bit)) != 0; } /* * Function declaration from virtio_pci.c */ void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); void vtpci_set_status(struct virtio_hw *, uint8_t); uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); void vtpci_read_dev_config(struct virtio_hw *, uint64_t, void *, int); uint8_t vtpci_isr(struct virtio_hw *); uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); #endif /* _VIRTIO_PCI_H_ */ ================================================ FILE: drivers/net/virtio/virtio_ring.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_RING_H_ #define _VIRTIO_RING_H_ #include #include /* This marks a buffer as continuing via the next field. */ #define VRING_DESC_F_NEXT 1 /* This marks a buffer as write-only (otherwise read-only). */ #define VRING_DESC_F_WRITE 2 /* This means the buffer contains a list of buffer descriptors. */ #define VRING_DESC_F_INDIRECT 4 /* The Host uses this in used->flags to advise the Guest: don't kick me * when you add a buffer. It's unreliable, so it's simply an * optimization. Guest will still kick if it's out of buffers. */ #define VRING_USED_F_NO_NOTIFY 1 /* The Guest uses this in avail->flags to advise the Host: don't * interrupt me when you consume a buffer. It's unreliable, so it's * simply an optimization. */ #define VRING_AVAIL_F_NO_INTERRUPT 1 /* VirtIO ring descriptors: 16 bytes. * These can chain together via "next". */ struct vring_desc { uint64_t addr; /* Address (guest-physical). */ uint32_t len; /* Length. */ uint16_t flags; /* The flags as indicated above. */ uint16_t next; /* We chain unused descriptors via this. */ }; struct vring_avail { uint16_t flags; uint16_t idx; uint16_t ring[0]; }; /* id is a 16bit index. uint32_t is used here for ids for padding reasons. */ struct vring_used_elem { /* Index of start of used descriptor chain. */ uint32_t id; /* Total length of the descriptor chain which was written to. */ uint32_t len; }; struct vring_used { uint16_t flags; uint16_t idx; struct vring_used_elem ring[0]; }; struct vring { unsigned int num; struct vring_desc *desc; struct vring_avail *avail; struct vring_used *used; }; /* The standard layout for the ring is a continuous chunk of memory which * looks like this. We assume num is a power of 2. * * struct vring { * // The actual descriptors (16 bytes each) * struct vring_desc desc[num]; * * // A ring of available descriptor heads with free-running index. * __u16 avail_flags; * __u16 avail_idx; * __u16 available[num]; * __u16 used_event_idx; * * // Padding to the next align boundary. * char pad[]; * * // A ring of used descriptor heads with free-running index. * __u16 used_flags; * __u16 used_idx; * struct vring_used_elem used[num]; * __u16 avail_event_idx; * }; * * NOTE: for VirtIO PCI, align is 4096. */ /* * We publish the used event index at the end of the available ring, and vice * versa. They are at the end for backwards compatibility. */ #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) #define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) static inline int vring_size(unsigned int num, unsigned long align) { int size; size = num * sizeof(struct vring_desc); size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)); size = RTE_ALIGN_CEIL(size, align); size += sizeof(struct vring_used) + (num * sizeof(struct vring_used_elem)); return size; } static inline void vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align) { vr->num = num; vr->desc = (struct vring_desc *) p; vr->avail = (struct vring_avail *) (p + num * sizeof(struct vring_desc)); vr->used = (void *) RTE_ALIGN_CEIL((uintptr_t)(&vr->avail->ring[num]), align); } /* * The following is used with VIRTIO_RING_F_EVENT_IDX. * Assuming a given event_idx value from the other size, if we have * just incremented index from old to new_idx, should we trigger an * event? */ static inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) { return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old); } #endif /* _VIRTIO_RING_H_ */ ================================================ FILE: drivers/net/virtio/virtio_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "virtio_logs.h" #include "virtio_ethdev.h" #include "virtqueue.h" #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP #define VIRTIO_DUMP_PACKET(m, len) rte_pktmbuf_dump(stdout, m, len) #else #define VIRTIO_DUMP_PACKET(m, len) do { } while (0) #endif static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) { struct vring_desc *dp, *dp_tail; struct vq_desc_extra *dxp; uint16_t desc_idx_last = desc_idx; dp = &vq->vq_ring.desc[desc_idx]; dxp = &vq->vq_descx[desc_idx]; vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt + dxp->ndescs); if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) { while (dp->flags & VRING_DESC_F_NEXT) { desc_idx_last = dp->next; dp = &vq->vq_ring.desc[dp->next]; } } dxp->ndescs = 0; /* * We must append the existing free chain, if any, to the end of * newly freed chain. If the virtqueue was completely used, then * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above). */ if (vq->vq_desc_tail_idx == VQ_RING_DESC_CHAIN_END) { vq->vq_desc_head_idx = desc_idx; } else { dp_tail = &vq->vq_ring.desc[vq->vq_desc_tail_idx]; dp_tail->next = desc_idx; } vq->vq_desc_tail_idx = desc_idx_last; dp->next = VQ_RING_DESC_CHAIN_END; } static uint16_t virtqueue_dequeue_burst_rx(struct virtqueue *vq, struct rte_mbuf **rx_pkts, uint32_t *len, uint16_t num) { struct vring_used_elem *uep; struct rte_mbuf *cookie; uint16_t used_idx, desc_idx; uint16_t i; /* Caller does the check */ for (i = 0; i < num ; i++) { used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; desc_idx = (uint16_t) uep->id; len[i] = uep->len; cookie = (struct rte_mbuf *)vq->vq_descx[desc_idx].cookie; if (unlikely(cookie == NULL)) { PMD_DRV_LOG(ERR, "vring descriptor with no mbuf cookie at %u\n", vq->vq_used_cons_idx); break; } rte_prefetch0(cookie); rte_packet_prefetch(rte_pktmbuf_mtod(cookie, void *)); rx_pkts[i] = cookie; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); vq->vq_descx[desc_idx].cookie = NULL; } return i; } #ifndef DEFAULT_TX_FREE_THRESH #define DEFAULT_TX_FREE_THRESH 32 #endif /* Cleanup from completed transmits. */ static void virtio_xmit_cleanup(struct virtqueue *vq, uint16_t num) { uint16_t i, used_idx, desc_idx; for (i = 0; i < num; i++) { struct vring_used_elem *uep; struct vq_desc_extra *dxp; used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; desc_idx = (uint16_t) uep->id; dxp = &vq->vq_descx[desc_idx]; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); if (dxp->cookie != NULL) { rte_pktmbuf_free(dxp->cookie); dxp->cookie = NULL; } } } static inline int virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie) { struct vq_desc_extra *dxp; struct virtio_hw *hw = vq->hw; struct vring_desc *start_dp; uint16_t needed = 1; uint16_t head_idx, idx; if (unlikely(vq->vq_free_cnt == 0)) return -ENOSPC; if (unlikely(vq->vq_free_cnt < needed)) return -EMSGSIZE; head_idx = vq->vq_desc_head_idx; if (unlikely(head_idx >= vq->vq_nentries)) return -EFAULT; idx = head_idx; dxp = &vq->vq_descx[idx]; dxp->cookie = (void *)cookie; dxp->ndescs = needed; start_dp = vq->vq_ring.desc; start_dp[idx].addr = (uint64_t)(cookie->buf_physaddr + RTE_PKTMBUF_HEADROOM - hw->vtnet_hdr_size); start_dp[idx].len = cookie->buf_len - RTE_PKTMBUF_HEADROOM + hw->vtnet_hdr_size; start_dp[idx].flags = VRING_DESC_F_WRITE; idx = start_dp[idx].next; vq->vq_desc_head_idx = idx; if (vq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END) vq->vq_desc_tail_idx = idx; vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed); vq_update_avail_ring(vq, head_idx); return 0; } static int virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) { struct vq_desc_extra *dxp; struct vring_desc *start_dp; uint16_t seg_num = cookie->nb_segs; uint16_t needed = 1 + seg_num; uint16_t head_idx, idx; uint16_t head_size = txvq->hw->vtnet_hdr_size; if (unlikely(txvq->vq_free_cnt == 0)) return -ENOSPC; if (unlikely(txvq->vq_free_cnt < needed)) return -EMSGSIZE; head_idx = txvq->vq_desc_head_idx; if (unlikely(head_idx >= txvq->vq_nentries)) return -EFAULT; idx = head_idx; dxp = &txvq->vq_descx[idx]; dxp->cookie = (void *)cookie; dxp->ndescs = needed; start_dp = txvq->vq_ring.desc; start_dp[idx].addr = txvq->virtio_net_hdr_mem + idx * head_size; start_dp[idx].len = (uint32_t)head_size; start_dp[idx].flags = VRING_DESC_F_NEXT; for (; ((seg_num > 0) && (cookie != NULL)); seg_num--) { idx = start_dp[idx].next; start_dp[idx].addr = RTE_MBUF_DATA_DMA_ADDR(cookie); start_dp[idx].len = cookie->data_len; start_dp[idx].flags = VRING_DESC_F_NEXT; cookie = cookie->next; } start_dp[idx].flags &= ~VRING_DESC_F_NEXT; idx = start_dp[idx].next; txvq->vq_desc_head_idx = idx; if (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END) txvq->vq_desc_tail_idx = idx; txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed); vq_update_avail_ring(txvq, head_idx); return 0; } static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return m; } static void virtio_dev_vring_start(struct virtqueue *vq, int queue_type) { struct rte_mbuf *m; int i, nbufs, error, size = vq->vq_nentries; struct vring *vr = &vq->vq_ring; uint8_t *ring_mem = vq->vq_ring_virt_mem; PMD_INIT_FUNC_TRACE(); /* * Reinitialise since virtio port might have been stopped and restarted */ memset(vq->vq_ring_virt_mem, 0, vq->vq_ring_size); vring_init(vr, size, ring_mem, VIRTIO_PCI_VRING_ALIGN); vq->vq_used_cons_idx = 0; vq->vq_desc_head_idx = 0; vq->vq_avail_idx = 0; vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1); vq->vq_free_cnt = vq->vq_nentries; memset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries); /* Chain all the descriptors in the ring with an END */ for (i = 0; i < size - 1; i++) vr->desc[i].next = (uint16_t)(i + 1); vr->desc[i].next = VQ_RING_DESC_CHAIN_END; /* * Disable device(host) interrupting guest */ virtqueue_disable_intr(vq); /* Only rx virtqueue needs mbufs to be allocated at initialization */ if (queue_type == VTNET_RQ) { if (vq->mpool == NULL) rte_exit(EXIT_FAILURE, "Cannot allocate initial mbufs for rx virtqueue"); /* Allocate blank mbufs for the each rx descriptor */ nbufs = 0; error = ENOSPC; while (!virtqueue_full(vq)) { m = rte_rxmbuf_alloc(vq->mpool); if (m == NULL) break; /****************************************** * Enqueue allocated buffers * *******************************************/ error = virtqueue_enqueue_recv_refill(vq, m); if (error) { rte_pktmbuf_free(m); break; } nbufs++; } vq_update_avail_idx(vq); PMD_INIT_LOG(DEBUG, "Allocated %d bufs", nbufs); VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } else if (queue_type == VTNET_TQ) { VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } else { VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index); VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } } void virtio_dev_cq_start(struct rte_eth_dev *dev) { struct virtio_hw *hw = dev->data->dev_private; if (hw->cvq) { virtio_dev_vring_start(hw->cvq, VTNET_CQ); VIRTQUEUE_DUMP((struct virtqueue *)hw->cvq); } } void virtio_dev_rxtx_start(struct rte_eth_dev *dev) { /* * Start receive and transmit vrings * - Setup vring structure for all queues * - Initialize descriptor for the rx vring * - Allocate blank mbufs for the each rx descriptor * */ int i; PMD_INIT_FUNC_TRACE(); /* Start rx vring. */ for (i = 0; i < dev->data->nb_rx_queues; i++) { virtio_dev_vring_start(dev->data->rx_queues[i], VTNET_RQ); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->rx_queues[i]); } /* Start tx vring. */ for (i = 0; i < dev->data->nb_tx_queues; i++) { virtio_dev_vring_start(dev->data->tx_queues[i], VTNET_TQ); VIRTQUEUE_DUMP((struct virtqueue *)dev->data->tx_queues[i]); } } int virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, __rte_unused const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { uint16_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_RQ_QUEUE_IDX; struct virtqueue *vq; int ret; PMD_INIT_FUNC_TRACE(); ret = virtio_dev_queue_setup(dev, VTNET_RQ, queue_idx, vtpci_queue_idx, nb_desc, socket_id, &vq); if (ret < 0) { PMD_INIT_LOG(ERR, "rvq initialization failed"); return ret; } /* Create mempool for rx mbuf allocation */ vq->mpool = mp; dev->data->rx_queues[queue_idx] = vq; return 0; } void virtio_dev_rx_queue_release(void *rxq) { virtio_dev_queue_release(rxq); } /* * struct rte_eth_dev *dev: Used to update dev * uint16_t nb_desc: Defaults to values read from config space * unsigned int socket_id: Used to allocate memzone * const struct rte_eth_txconf *tx_conf: Used to setup tx engine * uint16_t queue_idx: Just used as an index in dev txq list */ int virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; struct virtqueue *vq; uint16_t tx_free_thresh; int ret; PMD_INIT_FUNC_TRACE(); if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOXSUMS) != ETH_TXQ_FLAGS_NOXSUMS) { PMD_INIT_LOG(ERR, "TX checksum offload not supported\n"); return -EINVAL; } ret = virtio_dev_queue_setup(dev, VTNET_TQ, queue_idx, vtpci_queue_idx, nb_desc, socket_id, &vq); if (ret < 0) { PMD_INIT_LOG(ERR, "rvq initialization failed"); return ret; } tx_free_thresh = tx_conf->tx_free_thresh; if (tx_free_thresh == 0) tx_free_thresh = RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH); if (tx_free_thresh >= (vq->vq_nentries - 3)) { RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the " "number of TX entries minus 3 (%u)." " (tx_free_thresh=%u port=%u queue=%u)\n", vq->vq_nentries - 3, tx_free_thresh, dev->data->port_id, queue_idx); return -EINVAL; } vq->vq_free_thresh = tx_free_thresh; dev->data->tx_queues[queue_idx] = vq; return 0; } void virtio_dev_tx_queue_release(void *txq) { virtio_dev_queue_release(txq); } static void virtio_discard_rxbuf(struct virtqueue *vq, struct rte_mbuf *m) { int error; /* * Requeue the discarded mbuf. This should always be * successful since it was just dequeued. */ error = virtqueue_enqueue_recv_refill(vq, m); if (unlikely(error)) { RTE_LOG(ERR, PMD, "cannot requeue discarded mbuf"); rte_pktmbuf_free(m); } } #define VIRTIO_MBUF_BURST_SZ 64 #define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc)) uint16_t virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct virtqueue *rxvq = rx_queue; struct virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; int error; uint32_t i, nb_enqueued; const uint32_t hdr_size = sizeof(struct virtio_net_hdr); nb_used = VIRTQUEUE_NUSED(rxvq); virtio_rmb(); num = (uint16_t)(likely(nb_used <= nb_pkts) ? nb_used : nb_pkts); num = (uint16_t)(likely(num <= VIRTIO_MBUF_BURST_SZ) ? num : VIRTIO_MBUF_BURST_SZ); if (likely(num > DESC_PER_CACHELINE)) num = num - ((rxvq->vq_used_cons_idx + num) % DESC_PER_CACHELINE); if (num == 0) return 0; num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, num); PMD_RX_LOG(DEBUG, "used:%d dequeue:%d", nb_used, num); hw = rxvq->hw; nb_rx = 0; nb_enqueued = 0; for (i = 0; i < num ; i++) { rxm = rcv_pkts[i]; PMD_RX_LOG(DEBUG, "packet len:%d", len[i]); if (unlikely(len[i] < hdr_size + ETHER_HDR_LEN)) { PMD_RX_LOG(ERR, "Packet drop"); nb_enqueued++; virtio_discard_rxbuf(rxvq, rxm); rxvq->errors++; continue; } rxm->port = rxvq->port_id; rxm->data_off = RTE_PKTMBUF_HEADROOM; rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = (uint32_t)(len[i] - hdr_size); rxm->data_len = (uint16_t)(len[i] - hdr_size); if (hw->vlan_strip) rte_vlan_strip(rxm); VIRTIO_DUMP_PACKET(rxm, rxm->data_len); rx_pkts[nb_rx++] = rxm; rxvq->bytes += rx_pkts[nb_rx - 1]->pkt_len; } rxvq->packets += nb_rx; /* Allocate new mbuf for the used descriptor */ error = ENOSPC; while (likely(!virtqueue_full(rxvq))) { new_mbuf = rte_rxmbuf_alloc(rxvq->mpool); if (unlikely(new_mbuf == NULL)) { struct rte_eth_dev *dev = &rte_eth_devices[rxvq->port_id]; dev->data->rx_mbuf_alloc_failed++; break; } error = virtqueue_enqueue_recv_refill(rxvq, new_mbuf); if (unlikely(error)) { rte_pktmbuf_free(new_mbuf); break; } nb_enqueued++; } if (likely(nb_enqueued)) { vq_update_avail_idx(rxvq); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified\n"); } } return nb_rx; } uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct virtqueue *rxvq = rx_queue; struct virtio_hw *hw; struct rte_mbuf *rxm, *new_mbuf; uint16_t nb_used, num, nb_rx; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *rcv_pkts[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *prev; int error; uint32_t i, nb_enqueued; uint32_t seg_num; uint16_t extra_idx; uint32_t seg_res; const uint32_t hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf); nb_used = VIRTQUEUE_NUSED(rxvq); virtio_rmb(); if (nb_used == 0) return 0; PMD_RX_LOG(DEBUG, "used:%d\n", nb_used); hw = rxvq->hw; nb_rx = 0; i = 0; nb_enqueued = 0; seg_num = 0; extra_idx = 0; seg_res = 0; while (i < nb_used) { struct virtio_net_hdr_mrg_rxbuf *header; if (nb_rx == nb_pkts) break; num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, 1); if (num != 1) continue; i++; PMD_RX_LOG(DEBUG, "dequeue:%d\n", num); PMD_RX_LOG(DEBUG, "packet len:%d\n", len[0]); rxm = rcv_pkts[0]; if (unlikely(len[0] < hdr_size + ETHER_HDR_LEN)) { PMD_RX_LOG(ERR, "Packet drop\n"); nb_enqueued++; virtio_discard_rxbuf(rxvq, rxm); rxvq->errors++; continue; } header = (struct virtio_net_hdr_mrg_rxbuf *)((char *)rxm->buf_addr + RTE_PKTMBUF_HEADROOM - hdr_size); seg_num = header->num_buffers; if (seg_num == 0) seg_num = 1; rxm->data_off = RTE_PKTMBUF_HEADROOM; rxm->nb_segs = seg_num; rxm->next = NULL; rxm->pkt_len = (uint32_t)(len[0] - hdr_size); rxm->data_len = (uint16_t)(len[0] - hdr_size); rxm->port = rxvq->port_id; rx_pkts[nb_rx] = rxm; prev = rxm; seg_res = seg_num - 1; while (seg_res != 0) { /* * Get extra segments for current uncompleted packet. */ uint16_t rcv_cnt = RTE_MIN(seg_res, RTE_DIM(rcv_pkts)); if (likely(VIRTQUEUE_NUSED(rxvq) >= rcv_cnt)) { uint32_t rx_num = virtqueue_dequeue_burst_rx(rxvq, rcv_pkts, len, rcv_cnt); i += rx_num; rcv_cnt = rx_num; } else { PMD_RX_LOG(ERR, "No enough segments for packet.\n"); nb_enqueued++; virtio_discard_rxbuf(rxvq, rxm); rxvq->errors++; break; } extra_idx = 0; while (extra_idx < rcv_cnt) { rxm = rcv_pkts[extra_idx]; rxm->data_off = RTE_PKTMBUF_HEADROOM - hdr_size; rxm->next = NULL; rxm->pkt_len = (uint32_t)(len[extra_idx]); rxm->data_len = (uint16_t)(len[extra_idx]); if (prev) prev->next = rxm; prev = rxm; rx_pkts[nb_rx]->pkt_len += rxm->pkt_len; extra_idx++; }; seg_res -= rcv_cnt; } if (hw->vlan_strip) rte_vlan_strip(rx_pkts[nb_rx]); VIRTIO_DUMP_PACKET(rx_pkts[nb_rx], rx_pkts[nb_rx]->data_len); rxvq->bytes += rx_pkts[nb_rx]->pkt_len; nb_rx++; } rxvq->packets += nb_rx; /* Allocate new mbuf for the used descriptor */ error = ENOSPC; while (likely(!virtqueue_full(rxvq))) { new_mbuf = rte_rxmbuf_alloc(rxvq->mpool); if (unlikely(new_mbuf == NULL)) { struct rte_eth_dev *dev = &rte_eth_devices[rxvq->port_id]; dev->data->rx_mbuf_alloc_failed++; break; } error = virtqueue_enqueue_recv_refill(rxvq, new_mbuf); if (unlikely(error)) { rte_pktmbuf_free(new_mbuf); break; } nb_enqueued++; } if (likely(nb_enqueued)) { vq_update_avail_idx(rxvq); if (unlikely(virtqueue_kick_prepare(rxvq))) { virtqueue_notify(rxvq); PMD_RX_LOG(DEBUG, "Notified"); } } return nb_rx; } uint16_t virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; uint16_t nb_used, nb_tx; int error; if (unlikely(nb_pkts < 1)) return nb_pkts; PMD_TX_LOG(DEBUG, "%d packets to xmit", nb_pkts); nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); if (likely(nb_used > txvq->vq_nentries - txvq->vq_free_thresh)) virtio_xmit_cleanup(txvq, nb_used); nb_tx = 0; while (nb_tx < nb_pkts) { /* Need one more descriptor for virtio header. */ int need = tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; /*Positive value indicates it need free vring descriptors */ if (unlikely(need > 0)) { nb_used = VIRTQUEUE_NUSED(txvq); virtio_rmb(); need = RTE_MIN(need, (int)nb_used); virtio_xmit_cleanup(txvq, need); need = (int)tx_pkts[nb_tx]->nb_segs - txvq->vq_free_cnt + 1; } /* * Zero or negative value indicates it has enough free * descriptors to use for transmitting. */ if (likely(need <= 0)) { txm = tx_pkts[nb_tx]; /* Do VLAN tag insertion */ if (unlikely(txm->ol_flags & PKT_TX_VLAN_PKT)) { error = rte_vlan_insert(&txm); if (unlikely(error)) { rte_pktmbuf_free(txm); ++nb_tx; continue; } } /* Enqueue Packet buffers */ error = virtqueue_enqueue_xmit(txvq, txm); if (unlikely(error)) { if (error == ENOSPC) PMD_TX_LOG(ERR, "virtqueue_enqueue Free count = 0"); else if (error == EMSGSIZE) PMD_TX_LOG(ERR, "virtqueue_enqueue Free count < 1"); else PMD_TX_LOG(ERR, "virtqueue_enqueue error: %d", error); break; } nb_tx++; txvq->bytes += txm->pkt_len; } else { PMD_TX_LOG(ERR, "No free tx descriptors to transmit"); break; } } txvq->packets += nb_tx; if (likely(nb_tx)) { vq_update_avail_idx(txvq); if (unlikely(virtqueue_kick_prepare(txvq))) { virtqueue_notify(txvq); PMD_TX_LOG(DEBUG, "Notified backend after xmit"); } } return nb_tx; } ================================================ FILE: drivers/net/virtio/virtqueue.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "virtqueue.h" #include "virtio_logs.h" #include "virtio_pci.h" void virtqueue_disable_intr(struct virtqueue *vq) { /* * Set VRING_AVAIL_F_NO_INTERRUPT to hint host * not to interrupt when it consumes packets * Note: this is only considered a hint to the host */ vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; } /* * Two types of mbuf to be cleaned: * 1) mbuf that has been consumed by backend but not used by virtio. * 2) mbuf that hasn't been consued by backend. */ struct rte_mbuf * virtqueue_detatch_unused(struct virtqueue *vq) { struct rte_mbuf *cookie; int idx; if (vq != NULL) for (idx = 0; idx < vq->vq_nentries; idx++) { cookie = vq->vq_descx[idx].cookie; if (cookie != NULL) { vq->vq_descx[idx].cookie = NULL; return cookie; } } return NULL; } ================================================ FILE: drivers/net/virtio/virtqueue.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTQUEUE_H_ #define _VIRTQUEUE_H_ #include #include #include #include #include #include "virtio_pci.h" #include "virtio_ring.h" #include "virtio_logs.h" struct rte_mbuf; /* * Per virtio_config.h in Linux. * For virtio_pci on SMP, we don't need to order with respect to MMIO * accesses through relaxed memory I/O windows, so smp_mb() et al are * sufficient. * * This driver is for virtio_pci on SMP and therefore can assume * weaker (compiler barriers) */ #define virtio_mb() rte_mb() #define virtio_rmb() rte_compiler_barrier() #define virtio_wmb() rte_compiler_barrier() #ifdef RTE_PMD_PACKET_PREFETCH #define rte_packet_prefetch(p) rte_prefetch1(p) #else #define rte_packet_prefetch(p) do {} while(0) #endif #define VIRTQUEUE_MAX_NAME_SZ 32 #define RTE_MBUF_DATA_DMA_ADDR(mb) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) #define VTNET_SQ_RQ_QUEUE_IDX 0 #define VTNET_SQ_TQ_QUEUE_IDX 1 #define VTNET_SQ_CQ_QUEUE_IDX 2 enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; /** * The maximum virtqueue size is 2^15. Use that value as the end of * descriptor chain terminator since it will never be a valid index * in the descriptor table. This is used to verify we are correctly * handling vq_free_cnt. */ #define VQ_RING_DESC_CHAIN_END 32768 /** * Control the RX mode, ie. promiscuous, allmulti, etc... * All commands require an "out" sg entry containing a 1 byte * state value, zero = disable, non-zero = enable. Commands * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. */ #define VIRTIO_NET_CTRL_RX 0 #define VIRTIO_NET_CTRL_RX_PROMISC 0 #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 #define VIRTIO_NET_CTRL_RX_ALLUNI 2 #define VIRTIO_NET_CTRL_RX_NOMULTI 3 #define VIRTIO_NET_CTRL_RX_NOUNI 4 #define VIRTIO_NET_CTRL_RX_NOBCAST 5 /** * Control the MAC * * The MAC filter table is managed by the hypervisor, the guest should * assume the size is infinite. Filtering should be considered * non-perfect, ie. based on hypervisor resources, the guest may * received packets from sources not specified in the filter list. * * In addition to the class/cmd header, the TABLE_SET command requires * two out scatterlists. Each contains a 4 byte count of entries followed * by a concatenated byte stream of the ETH_ALEN MAC addresses. The * first sg list contains unicast addresses, the second is for multicast. * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature * is available. * * The ADDR_SET command requests one out scatterlist, it contains a * 6 bytes MAC address. This functionality is present if the * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. */ struct virtio_net_ctrl_mac { uint32_t entries; uint8_t macs[][ETHER_ADDR_LEN]; } __attribute__((__packed__)); #define VIRTIO_NET_CTRL_MAC 1 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 /** * Control VLAN filtering * * The VLAN filter table is controlled via a simple ADD/DEL interface. * VLAN IDs not added may be filtered by the hypervisor. Del is the * opposite of add. Both commands expect an out entry containing a 2 * byte VLAN ID. VLAN filtering is available with the * VIRTIO_NET_F_CTRL_VLAN feature bit. */ #define VIRTIO_NET_CTRL_VLAN 2 #define VIRTIO_NET_CTRL_VLAN_ADD 0 #define VIRTIO_NET_CTRL_VLAN_DEL 1 struct virtio_net_ctrl_hdr { uint8_t class; uint8_t cmd; } __attribute__((packed)); typedef uint8_t virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 #define VIRTIO_MAX_CTRL_DATA 2048 struct virtio_pmd_ctrl { struct virtio_net_ctrl_hdr hdr; virtio_net_ctrl_ack status; uint8_t data[VIRTIO_MAX_CTRL_DATA]; }; struct virtqueue { struct virtio_hw *hw; /**< virtio_hw structure pointer. */ const struct rte_memzone *mz; /**< mem zone to populate RX ring. */ const struct rte_memzone *virtio_net_hdr_mz; /**< memzone to populate hdr. */ struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint8_t port_id; /**< Device port identifier. */ uint16_t vq_queue_index; /**< PCI queue index */ void *vq_ring_virt_mem; /**< linear address of vring*/ unsigned int vq_ring_size; phys_addr_t vq_ring_mem; /**< physical address of vring */ struct vring vq_ring; /**< vring keeping desc, used and avail */ uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_nentries; /**< vring desc numbers */ uint16_t vq_free_thresh; /**< free threshold */ /** * Head of the free chain in the descriptor table. If * there are no free descriptors, this will be set to * VQ_RING_DESC_CHAIN_END. */ uint16_t vq_desc_head_idx; uint16_t vq_desc_tail_idx; /** * Last consumed descriptor in the used table, * trails vq_ring.used->idx. */ uint16_t vq_used_cons_idx; uint16_t vq_avail_idx; phys_addr_t virtio_net_hdr_mem; /**< hdr for each xmit packet */ /* Statistics */ uint64_t packets; uint64_t bytes; uint64_t errors; struct vq_desc_extra { void *cookie; uint16_t ndescs; } vq_descx[0]; }; /* If multiqueue is provided by host, then we suppport it. */ #define VIRTIO_NET_CTRL_MQ 4 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 /** * This is the first element of the scatter-gather list. If you don't * specify GSO or CSUM features, you can simply ignore the header. */ struct virtio_net_hdr { #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /**< Use csum_start,csum_offset*/ uint8_t flags; #define VIRTIO_NET_HDR_GSO_NONE 0 /**< Not a GSO frame */ #define VIRTIO_NET_HDR_GSO_TCPV4 1 /**< GSO frame, IPv4 TCP (TSO) */ #define VIRTIO_NET_HDR_GSO_UDP 3 /**< GSO frame, IPv4 UDP (UFO) */ #define VIRTIO_NET_HDR_GSO_TCPV6 4 /**< GSO frame, IPv6 TCP */ #define VIRTIO_NET_HDR_GSO_ECN 0x80 /**< TCP has ECN set */ uint8_t gso_type; uint16_t hdr_len; /**< Ethernet + IP + tcp/udp hdrs */ uint16_t gso_size; /**< Bytes to append to hdr_len per frame */ uint16_t csum_start; /**< Position to start checksumming from */ uint16_t csum_offset; /**< Offset after that to place checksum */ }; /** * This is the version of the header to use when the MRG_RXBUF * feature has been negotiated. */ struct virtio_net_hdr_mrg_rxbuf { struct virtio_net_hdr hdr; uint16_t num_buffers; /**< Number of merged rx buffers */ }; /** * Tell the backend not to interrupt us. */ void virtqueue_disable_intr(struct virtqueue *vq); /** * Dump virtqueue internal structures, for debug purpose only. */ void virtqueue_dump(struct virtqueue *vq); /** * Get all mbufs to be freed. */ struct rte_mbuf *virtqueue_detatch_unused(struct virtqueue *vq); static inline int virtqueue_full(const struct virtqueue *vq) { return vq->vq_free_cnt == 0; } #define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_ring.used->idx - (vq)->vq_used_cons_idx)) static inline void vq_update_avail_idx(struct virtqueue *vq) { virtio_wmb(); vq->vq_ring.avail->idx = vq->vq_avail_idx; } static inline void vq_update_avail_ring(struct virtqueue *vq, uint16_t desc_idx) { uint16_t avail_idx; /* * Place the head of the descriptor chain into the next slot and make * it usable to the host. The chain is made available now rather than * deferring to virtqueue_notify() in the hopes that if the host is * currently running on another CPU, we can keep it processing the new * descriptor. */ avail_idx = (uint16_t)(vq->vq_avail_idx & (vq->vq_nentries - 1)); vq->vq_ring.avail->ring[avail_idx] = desc_idx; vq->vq_avail_idx++; } static inline int virtqueue_kick_prepare(struct virtqueue *vq) { return !(vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY); } static inline void virtqueue_notify(struct virtqueue *vq) { /* * Ensure updated avail->idx is visible to host. * For virtio on IA, the notificaiton is through io port operation * which is a serialization instruction itself. */ VIRTIO_WRITE_REG_2(vq->hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index); } #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP #define VIRTQUEUE_DUMP(vq) do { \ uint16_t used_idx, nused; \ used_idx = (vq)->vq_ring.used->idx; \ nused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \ PMD_INIT_LOG(DEBUG, \ "VQ: - size=%d; free=%d; used=%d; desc_head_idx=%d;" \ " avail.idx=%d; used_cons_idx=%d; used.idx=%d;" \ " avail.flags=0x%x; used.flags=0x%x", \ (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \ (vq)->vq_desc_head_idx, (vq)->vq_ring.avail->idx, \ (vq)->vq_used_cons_idx, (vq)->vq_ring.used->idx, \ (vq)->vq_ring.avail->flags, (vq)->vq_ring.used->flags); \ } while (0) #else #define VIRTQUEUE_DUMP(vq) do { } while (0) #endif #endif /* _VIRTQUEUE_H_ */ ================================================ FILE: drivers/net/vmxnet3/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_vmxnet3_uio.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) ifeq ($(CC), icc) # # CFLAGS for icc # CFLAGS_BASE_DRIVER = -wd174 -wd593 -wd869 -wd981 -wd2259 else ifeq ($(CC), clang) # # CFLAGS for clang # CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args else # # CFLAGS for gcc # ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1) CFLAGS += -Wno-deprecated endif CFLAGS_BASE_DRIVER = -Wno-unused-parameter -Wno-unused-value CFLAGS_BASE_DRIVER += -Wno-strict-aliasing -Wno-format-extra-args endif VPATH += $(SRCDIR)/base EXPORT_MAP := rte_pmd_vmxnet3_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3_ethdev.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += lib/librte_net include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/vmxnet3/base/README ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Intel VMXNET3 driver =================== This directory contains source code of FreeBSD VMXNET3 driver released by VMware. In which, upt1_defs.h and vmxnet3_defs.h is introduced without any change. The other 4 files: includeCheck.h, vmware_pack_begin.h, vmware_pack_end.h and vmxnet3_osdep.h are crated to adapt to the needs from above 2 files. Updating the driver =================== NOTE: The source code in this directory should not be modified apart from the following file(s): vmxnet3_osdep.h ================================================ FILE: drivers/net/vmxnet3/base/includeCheck.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _INCLUDECHECK_H #define _INCLUDECHECK_H #include "vmxnet3_osdep.h" #endif /* _INCLUDECHECK_H */ ================================================ FILE: drivers/net/vmxnet3/base/upt1_defs.h ================================================ /********************************************************* * Copyright (C) 2007 VMware, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *********************************************************/ /* upt1_defs.h * * Definitions for UPTv1 * * Some of the defs are duplicated in vmkapi_net_upt.h, because * vmkapi_net_upt.h cannot distribute with OSS yet and vmkapi headers can * only include vmkapi headers. Make sure they are kept in sync! */ #ifndef _UPT1_DEFS_H #define _UPT1_DEFS_H #define UPT1_MAX_TX_QUEUES 64 #define UPT1_MAX_RX_QUEUES 64 #define UPT1_MAX_INTRS (UPT1_MAX_TX_QUEUES + UPT1_MAX_RX_QUEUES) typedef #include "vmware_pack_begin.h" struct UPT1_TxStats { uint64 TSOPktsTxOK; /* TSO pkts post-segmentation */ uint64 TSOBytesTxOK; uint64 ucastPktsTxOK; uint64 ucastBytesTxOK; uint64 mcastPktsTxOK; uint64 mcastBytesTxOK; uint64 bcastPktsTxOK; uint64 bcastBytesTxOK; uint64 pktsTxError; uint64 pktsTxDiscard; } #include "vmware_pack_end.h" UPT1_TxStats; typedef #include "vmware_pack_begin.h" struct UPT1_RxStats { uint64 LROPktsRxOK; /* LRO pkts */ uint64 LROBytesRxOK; /* bytes from LRO pkts */ /* the following counters are for pkts from the wire, i.e., pre-LRO */ uint64 ucastPktsRxOK; uint64 ucastBytesRxOK; uint64 mcastPktsRxOK; uint64 mcastBytesRxOK; uint64 bcastPktsRxOK; uint64 bcastBytesRxOK; uint64 pktsRxOutOfBuf; uint64 pktsRxError; } #include "vmware_pack_end.h" UPT1_RxStats; /* interrupt moderation level */ #define UPT1_IML_NONE 0 /* no interrupt moderation */ #define UPT1_IML_HIGHEST 7 /* least intr generated */ #define UPT1_IML_ADAPTIVE 8 /* adpative intr moderation */ /* values for UPT1_RSSConf.hashFunc */ #define UPT1_RSS_HASH_TYPE_NONE 0x0 #define UPT1_RSS_HASH_TYPE_IPV4 0x01 #define UPT1_RSS_HASH_TYPE_TCP_IPV4 0x02 #define UPT1_RSS_HASH_TYPE_IPV6 0x04 #define UPT1_RSS_HASH_TYPE_TCP_IPV6 0x08 #define UPT1_RSS_HASH_FUNC_NONE 0x0 #define UPT1_RSS_HASH_FUNC_TOEPLITZ 0x01 #define UPT1_RSS_MAX_KEY_SIZE 40 #define UPT1_RSS_MAX_IND_TABLE_SIZE 128 typedef #include "vmware_pack_begin.h" struct UPT1_RSSConf { uint16 hashType; uint16 hashFunc; uint16 hashKeySize; uint16 indTableSize; uint8 hashKey[UPT1_RSS_MAX_KEY_SIZE]; uint8 indTable[UPT1_RSS_MAX_IND_TABLE_SIZE]; } #include "vmware_pack_end.h" UPT1_RSSConf; /* features */ #define UPT1_F_RXCSUM 0x0001 /* rx csum verification */ #define UPT1_F_RSS 0x0002 #define UPT1_F_RXVLAN 0x0004 /* VLAN tag stripping */ #define UPT1_F_LRO 0x0008 #endif ================================================ FILE: drivers/net/vmxnet3/base/vmware_pack_begin.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ================================================ FILE: drivers/net/vmxnet3/base/vmware_pack_end.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ================================================ FILE: drivers/net/vmxnet3/base/vmxnet3_defs.h ================================================ /********************************************************* * Copyright (C) 2007 VMware, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *********************************************************/ /* * vmxnet3_defs.h -- * * Definitions shared by device emulation and guest drivers for * VMXNET3 NIC */ #ifndef _VMXNET3_DEFS_H_ #define _VMXNET3_DEFS_H_ #define INCLUDE_ALLOW_USERLEVEL #define INCLUDE_ALLOW_VMKERNEL #define INCLUDE_ALLOW_DISTRIBUTE #define INCLUDE_ALLOW_VMKDRIVERS #define INCLUDE_ALLOW_VMCORE #define INCLUDE_ALLOW_MODULE #include "includeCheck.h" #include "upt1_defs.h" /* all registers are 32 bit wide */ /* BAR 1 */ #define VMXNET3_REG_VRRS 0x0 /* Vmxnet3 Revision Report Selection */ #define VMXNET3_REG_UVRS 0x8 /* UPT Version Report Selection */ #define VMXNET3_REG_DSAL 0x10 /* Driver Shared Address Low */ #define VMXNET3_REG_DSAH 0x18 /* Driver Shared Address High */ #define VMXNET3_REG_CMD 0x20 /* Command */ #define VMXNET3_REG_MACL 0x28 /* MAC Address Low */ #define VMXNET3_REG_MACH 0x30 /* MAC Address High */ #define VMXNET3_REG_ICR 0x38 /* Interrupt Cause Register */ #define VMXNET3_REG_ECR 0x40 /* Event Cause Register */ #define VMXNET3_REG_WSAL 0xF00 /* Wireless Shared Address Lo */ #define VMXNET3_REG_WSAH 0xF08 /* Wireless Shared Address Hi */ #define VMXNET3_REG_WCMD 0xF18 /* Wireless Command */ /* BAR 0 */ #define VMXNET3_REG_IMR 0x0 /* Interrupt Mask Register */ #define VMXNET3_REG_TXPROD 0x600 /* Tx Producer Index */ #define VMXNET3_REG_RXPROD 0x800 /* Rx Producer Index for ring 1 */ #define VMXNET3_REG_RXPROD2 0xA00 /* Rx Producer Index for ring 2 */ #define VMXNET3_PT_REG_SIZE 4096 /* BAR 0 */ #define VMXNET3_VD_REG_SIZE 4096 /* BAR 1 */ /* * The two Vmxnet3 MMIO Register PCI BARs (BAR 0 at offset 10h and BAR 1 at * offset 14h) as well as the MSI-X BAR are combined into one PhysMem region: * <-VMXNET3_PT_REG_SIZE-><-VMXNET3_VD_REG_SIZE-><-VMXNET3_MSIX_BAR_SIZE--> * ------------------------------------------------------------------------- * |Pass Thru Registers | Virtual Dev Registers | MSI-X Vector/PBA Table | * ------------------------------------------------------------------------- * VMXNET3_MSIX_BAR_SIZE is defined in "vmxnet3Int.h" */ #define VMXNET3_PHYSMEM_PAGES 4 #define VMXNET3_REG_ALIGN 8 /* All registers are 8-byte aligned. */ #define VMXNET3_REG_ALIGN_MASK 0x7 /* I/O Mapped access to registers */ #define VMXNET3_IO_TYPE_PT 0 #define VMXNET3_IO_TYPE_VD 1 #define VMXNET3_IO_ADDR(type, reg) (((type) << 24) | ((reg) & 0xFFFFFF)) #define VMXNET3_IO_TYPE(addr) ((addr) >> 24) #define VMXNET3_IO_REG(addr) ((addr) & 0xFFFFFF) #ifndef __le16 #define __le16 uint16 #endif #ifndef __le32 #define __le32 uint32 #endif #ifndef __le64 #define __le64 uint64 #endif typedef enum { VMXNET3_CMD_FIRST_SET = 0xCAFE0000, VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET, VMXNET3_CMD_QUIESCE_DEV, VMXNET3_CMD_RESET_DEV, VMXNET3_CMD_UPDATE_RX_MODE, VMXNET3_CMD_UPDATE_MAC_FILTERS, VMXNET3_CMD_UPDATE_VLAN_FILTERS, VMXNET3_CMD_UPDATE_RSSIDT, VMXNET3_CMD_UPDATE_IML, VMXNET3_CMD_UPDATE_PMCFG, VMXNET3_CMD_UPDATE_FEATURE, VMXNET3_CMD_STOP_EMULATION, VMXNET3_CMD_LOAD_PLUGIN, VMXNET3_CMD_ACTIVATE_VF, VMXNET3_CMD_FIRST_GET = 0xF00D0000, VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET, VMXNET3_CMD_GET_STATS, VMXNET3_CMD_GET_LINK, VMXNET3_CMD_GET_PERM_MAC_LO, VMXNET3_CMD_GET_PERM_MAC_HI, VMXNET3_CMD_GET_DID_LO, VMXNET3_CMD_GET_DID_HI, VMXNET3_CMD_GET_DEV_EXTRA_INFO, VMXNET3_CMD_GET_CONF_INTR, VMXNET3_CMD_GET_ADAPTIVE_RING_INFO } Vmxnet3_Cmd; /* Adaptive Ring Info Flags */ #define VMXNET3_DISABLE_ADAPTIVE_RING 1 /* * Little Endian layout of bitfields - * Byte 0 : 7.....len.....0 * Byte 1 : rsvd gen 13.len.8 * Byte 2 : 5.msscof.0 ext1 dtype * Byte 3 : 13...msscof...6 * * Big Endian layout of bitfields - * Byte 0: 13...msscof...6 * Byte 1 : 5.msscof.0 ext1 dtype * Byte 2 : rsvd gen 13.len.8 * Byte 3 : 7.....len.....0 * * Thus, le32_to_cpu on the dword will allow the big endian driver to read * the bit fields correctly. And cpu_to_le32 will convert bitfields * bit fields written by big endian driver to format required by device. */ typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxDesc { __le64 addr; #ifdef __BIG_ENDIAN_BITFIELD uint32 msscof:14; /* MSS, checksum offset, flags */ uint32 ext1:1; uint32 dtype:1; /* descriptor type */ uint32 rsvd:1; uint32 gen:1; /* generation bit */ uint32 len:14; #else uint32 len:14; uint32 gen:1; /* generation bit */ uint32 rsvd:1; uint32 dtype:1; /* descriptor type */ uint32 ext1:1; uint32 msscof:14; /* MSS, checksum offset, flags */ #endif /* __BIG_ENDIAN_BITFIELD */ #ifdef __BIG_ENDIAN_BITFIELD uint32 tci:16; /* Tag to Insert */ uint32 ti:1; /* VLAN Tag Insertion */ uint32 ext2:1; uint32 cq:1; /* completion request */ uint32 eop:1; /* End Of Packet */ uint32 om:2; /* offload mode */ uint32 hlen:10; /* header len */ #else uint32 hlen:10; /* header len */ uint32 om:2; /* offload mode */ uint32 eop:1; /* End Of Packet */ uint32 cq:1; /* completion request */ uint32 ext2:1; uint32 ti:1; /* VLAN Tag Insertion */ uint32 tci:16; /* Tag to Insert */ #endif /* __BIG_ENDIAN_BITFIELD */ } #include "vmware_pack_end.h" Vmxnet3_TxDesc; /* TxDesc.OM values */ #define VMXNET3_OM_NONE 0 #define VMXNET3_OM_CSUM 2 #define VMXNET3_OM_TSO 3 /* fields in TxDesc we access w/o using bit fields */ #define VMXNET3_TXD_EOP_SHIFT 12 #define VMXNET3_TXD_CQ_SHIFT 13 #define VMXNET3_TXD_GEN_SHIFT 14 #define VMXNET3_TXD_EOP_DWORD_SHIFT 3 #define VMXNET3_TXD_GEN_DWORD_SHIFT 2 #define VMXNET3_TXD_CQ (1 << VMXNET3_TXD_CQ_SHIFT) #define VMXNET3_TXD_EOP (1 << VMXNET3_TXD_EOP_SHIFT) #define VMXNET3_TXD_GEN (1 << VMXNET3_TXD_GEN_SHIFT) #define VMXNET3_TXD_GEN_SIZE 1 #define VMXNET3_TXD_EOP_SIZE 1 #define VMXNET3_HDR_COPY_SIZE 128 typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxDataDesc { uint8 data[VMXNET3_HDR_COPY_SIZE]; } #include "vmware_pack_end.h" Vmxnet3_TxDataDesc; #define VMXNET3_TCD_GEN_SHIFT 31 #define VMXNET3_TCD_GEN_SIZE 1 #define VMXNET3_TCD_TXIDX_SHIFT 0 #define VMXNET3_TCD_TXIDX_SIZE 12 #define VMXNET3_TCD_GEN_DWORD_SHIFT 3 typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxCompDesc { uint32 txdIdx:12; /* Index of the EOP TxDesc */ uint32 ext1:20; __le32 ext2; __le32 ext3; uint32 rsvd:24; uint32 type:7; /* completion type */ uint32 gen:1; /* generation bit */ } #include "vmware_pack_end.h" Vmxnet3_TxCompDesc; typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxDesc { __le64 addr; #ifdef __BIG_ENDIAN_BITFIELD uint32 gen:1; /* Generation bit */ uint32 rsvd:15; uint32 dtype:1; /* Descriptor type */ uint32 btype:1; /* Buffer Type */ uint32 len:14; #else uint32 len:14; uint32 btype:1; /* Buffer Type */ uint32 dtype:1; /* Descriptor type */ uint32 rsvd:15; uint32 gen:1; /* Generation bit */ #endif __le32 ext1; } #include "vmware_pack_end.h" Vmxnet3_RxDesc; /* values of RXD.BTYPE */ #define VMXNET3_RXD_BTYPE_HEAD 0 /* head only */ #define VMXNET3_RXD_BTYPE_BODY 1 /* body only */ /* fields in RxDesc we access w/o using bit fields */ #define VMXNET3_RXD_BTYPE_SHIFT 14 #define VMXNET3_RXD_GEN_SHIFT 31 typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxCompDesc { #ifdef __BIG_ENDIAN_BITFIELD uint32 ext2:1; uint32 cnc:1; /* Checksum Not Calculated */ uint32 rssType:4; /* RSS hash type used */ uint32 rqID:10; /* rx queue/ring ID */ uint32 sop:1; /* Start of Packet */ uint32 eop:1; /* End of Packet */ uint32 ext1:2; uint32 rxdIdx:12; /* Index of the RxDesc */ #else uint32 rxdIdx:12; /* Index of the RxDesc */ uint32 ext1:2; uint32 eop:1; /* End of Packet */ uint32 sop:1; /* Start of Packet */ uint32 rqID:10; /* rx queue/ring ID */ uint32 rssType:4; /* RSS hash type used */ uint32 cnc:1; /* Checksum Not Calculated */ uint32 ext2:1; #endif /* __BIG_ENDIAN_BITFIELD */ __le32 rssHash; /* RSS hash value */ #ifdef __BIG_ENDIAN_BITFIELD uint32 tci:16; /* Tag stripped */ uint32 ts:1; /* Tag is stripped */ uint32 err:1; /* Error */ uint32 len:14; /* data length */ #else uint32 len:14; /* data length */ uint32 err:1; /* Error */ uint32 ts:1; /* Tag is stripped */ uint32 tci:16; /* Tag stripped */ #endif /* __BIG_ENDIAN_BITFIELD */ #ifdef __BIG_ENDIAN_BITFIELD uint32 gen:1; /* generation bit */ uint32 type:7; /* completion type */ uint32 fcs:1; /* Frame CRC correct */ uint32 frg:1; /* IP Fragment */ uint32 v4:1; /* IPv4 */ uint32 v6:1; /* IPv6 */ uint32 ipc:1; /* IP Checksum Correct */ uint32 tcp:1; /* TCP packet */ uint32 udp:1; /* UDP packet */ uint32 tuc:1; /* TCP/UDP Checksum Correct */ uint32 csum:16; #else uint32 csum:16; uint32 tuc:1; /* TCP/UDP Checksum Correct */ uint32 udp:1; /* UDP packet */ uint32 tcp:1; /* TCP packet */ uint32 ipc:1; /* IP Checksum Correct */ uint32 v6:1; /* IPv6 */ uint32 v4:1; /* IPv4 */ uint32 frg:1; /* IP Fragment */ uint32 fcs:1; /* Frame CRC correct */ uint32 type:7; /* completion type */ uint32 gen:1; /* generation bit */ #endif /* __BIG_ENDIAN_BITFIELD */ } #include "vmware_pack_end.h" Vmxnet3_RxCompDesc; typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxCompDescExt { __le32 dword1; uint8 segCnt; /* Number of aggregated packets */ uint8 dupAckCnt; /* Number of duplicate Acks */ __le16 tsDelta; /* TCP timestamp difference */ __le32 dword2[2]; } #include "vmware_pack_end.h" Vmxnet3_RxCompDescExt; /* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */ #define VMXNET3_RCD_TUC_SHIFT 16 #define VMXNET3_RCD_IPC_SHIFT 19 /* fields in RxCompDesc we access via Vmxnet3_GenericDesc.qword[1] */ #define VMXNET3_RCD_TYPE_SHIFT 56 #define VMXNET3_RCD_GEN_SHIFT 63 /* csum OK for TCP/UDP pkts over IP */ #define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | 1 << VMXNET3_RCD_IPC_SHIFT) /* value of RxCompDesc.rssType */ #define VMXNET3_RCD_RSS_TYPE_NONE 0 #define VMXNET3_RCD_RSS_TYPE_IPV4 1 #define VMXNET3_RCD_RSS_TYPE_TCPIPV4 2 #define VMXNET3_RCD_RSS_TYPE_IPV6 3 #define VMXNET3_RCD_RSS_TYPE_TCPIPV6 4 /* a union for accessing all cmd/completion descriptors */ typedef union Vmxnet3_GenericDesc { __le64 qword[2]; __le32 dword[4]; __le16 word[8]; Vmxnet3_TxDesc txd; Vmxnet3_RxDesc rxd; Vmxnet3_TxCompDesc tcd; Vmxnet3_RxCompDesc rcd; Vmxnet3_RxCompDescExt rcdExt; } Vmxnet3_GenericDesc; #define VMXNET3_INIT_GEN 1 /* Max size of a single tx buffer */ #define VMXNET3_MAX_TX_BUF_SIZE (1 << 14) /* # of tx desc needed for a tx buffer size */ #define VMXNET3_TXD_NEEDED(size) (((size) + VMXNET3_MAX_TX_BUF_SIZE - 1) / VMXNET3_MAX_TX_BUF_SIZE) /* max # of tx descs for a non-tso pkt */ #define VMXNET3_MAX_TXD_PER_PKT 16 /* Max size of a single rx buffer */ #define VMXNET3_MAX_RX_BUF_SIZE ((1 << 14) - 1) /* Minimum size of a type 0 buffer */ #define VMXNET3_MIN_T0_BUF_SIZE 128 #define VMXNET3_MAX_CSUM_OFFSET 1024 /* Ring base address alignment */ #define VMXNET3_RING_BA_ALIGN 512 #define VMXNET3_RING_BA_MASK (VMXNET3_RING_BA_ALIGN - 1) /* Ring size must be a multiple of 32 */ #define VMXNET3_RING_SIZE_ALIGN 32 #define VMXNET3_RING_SIZE_MASK (VMXNET3_RING_SIZE_ALIGN - 1) /* Max ring size */ #define VMXNET3_TX_RING_MAX_SIZE 4096 #define VMXNET3_TC_RING_MAX_SIZE 4096 #define VMXNET3_RX_RING_MAX_SIZE 4096 #define VMXNET3_RC_RING_MAX_SIZE 8192 /* a list of reasons for queue stop */ #define VMXNET3_ERR_NOEOP 0x80000000 /* cannot find the EOP desc of a pkt */ #define VMXNET3_ERR_TXD_REUSE 0x80000001 /* reuse a TxDesc before tx completion */ #define VMXNET3_ERR_BIG_PKT 0x80000002 /* too many TxDesc for a pkt */ #define VMXNET3_ERR_DESC_NOT_SPT 0x80000003 /* descriptor type not supported */ #define VMXNET3_ERR_SMALL_BUF 0x80000004 /* type 0 buffer too small */ #define VMXNET3_ERR_STRESS 0x80000005 /* stress option firing in vmkernel */ #define VMXNET3_ERR_SWITCH 0x80000006 /* mode switch failure */ #define VMXNET3_ERR_TXD_INVALID 0x80000007 /* invalid TxDesc */ /* completion descriptor types */ #define VMXNET3_CDTYPE_TXCOMP 0 /* Tx Completion Descriptor */ #define VMXNET3_CDTYPE_RXCOMP 3 /* Rx Completion Descriptor */ #define VMXNET3_CDTYPE_RXCOMP_LRO 4 /* Rx Completion Descriptor for LRO */ #define VMXNET3_GOS_BITS_UNK 0 /* unknown */ #define VMXNET3_GOS_BITS_32 1 #define VMXNET3_GOS_BITS_64 2 #define VMXNET3_GOS_TYPE_UNK 0 /* unknown */ #define VMXNET3_GOS_TYPE_LINUX 1 #define VMXNET3_GOS_TYPE_WIN 2 #define VMXNET3_GOS_TYPE_SOLARIS 3 #define VMXNET3_GOS_TYPE_FREEBSD 4 #define VMXNET3_GOS_TYPE_PXE 5 /* All structures in DriverShared are padded to multiples of 8 bytes */ typedef #include "vmware_pack_begin.h" struct Vmxnet3_GOSInfo { #ifdef __BIG_ENDIAN_BITFIELD uint32 gosMisc: 10; /* other info about gos */ uint32 gosVer: 16; /* gos version */ uint32 gosType: 4; /* which guest */ uint32 gosBits: 2; /* 32-bit or 64-bit? */ #else uint32 gosBits: 2; /* 32-bit or 64-bit? */ uint32 gosType: 4; /* which guest */ uint32 gosVer: 16; /* gos version */ uint32 gosMisc: 10; /* other info about gos */ #endif /* __BIG_ENDIAN_BITFIELD */ } #include "vmware_pack_end.h" Vmxnet3_GOSInfo; typedef #include "vmware_pack_begin.h" struct Vmxnet3_DriverInfo { __le32 version; /* driver version */ Vmxnet3_GOSInfo gos; __le32 vmxnet3RevSpt; /* vmxnet3 revision supported */ __le32 uptVerSpt; /* upt version supported */ } #include "vmware_pack_end.h" Vmxnet3_DriverInfo; #define VMXNET3_REV1_MAGIC 0xbabefee1 /* * QueueDescPA must be 128 bytes aligned. It points to an array of * Vmxnet3_TxQueueDesc followed by an array of Vmxnet3_RxQueueDesc. * The number of Vmxnet3_TxQueueDesc/Vmxnet3_RxQueueDesc are specified by * Vmxnet3_MiscConf.numTxQueues/numRxQueues, respectively. */ #define VMXNET3_QUEUE_DESC_ALIGN 128 typedef #include "vmware_pack_begin.h" struct Vmxnet3_MiscConf { Vmxnet3_DriverInfo driverInfo; __le64 uptFeatures; __le64 ddPA; /* driver data PA */ __le64 queueDescPA; /* queue descriptor table PA */ __le32 ddLen; /* driver data len */ __le32 queueDescLen; /* queue descriptor table len, in bytes */ __le32 mtu; __le16 maxNumRxSG; uint8 numTxQueues; uint8 numRxQueues; __le32 reserved[4]; } #include "vmware_pack_end.h" Vmxnet3_MiscConf; typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxQueueConf { __le64 txRingBasePA; __le64 dataRingBasePA; __le64 compRingBasePA; __le64 ddPA; /* driver data */ __le64 reserved; __le32 txRingSize; /* # of tx desc */ __le32 dataRingSize; /* # of data desc */ __le32 compRingSize; /* # of comp desc */ __le32 ddLen; /* size of driver data */ uint8 intrIdx; uint8 _pad[7]; } #include "vmware_pack_end.h" Vmxnet3_TxQueueConf; typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxQueueConf { __le64 rxRingBasePA[2]; __le64 compRingBasePA; __le64 ddPA; /* driver data */ __le64 reserved; __le32 rxRingSize[2]; /* # of rx desc */ __le32 compRingSize; /* # of rx comp desc */ __le32 ddLen; /* size of driver data */ uint8 intrIdx; uint8 _pad[7]; } #include "vmware_pack_end.h" Vmxnet3_RxQueueConf; enum vmxnet3_intr_mask_mode { VMXNET3_IMM_AUTO = 0, VMXNET3_IMM_ACTIVE = 1, VMXNET3_IMM_LAZY = 2 }; enum vmxnet3_intr_type { VMXNET3_IT_AUTO = 0, VMXNET3_IT_INTX = 1, VMXNET3_IT_MSI = 2, VMXNET3_IT_MSIX = 3 }; #define VMXNET3_MAX_TX_QUEUES 8 #define VMXNET3_MAX_RX_QUEUES 16 /* addition 1 for events */ #define VMXNET3_MAX_INTRS 25 /* value of intrCtrl */ #define VMXNET3_IC_DISABLE_ALL 0x1 /* bit 0 */ typedef #include "vmware_pack_begin.h" struct Vmxnet3_IntrConf { Bool autoMask; uint8 numIntrs; /* # of interrupts */ uint8 eventIntrIdx; uint8 modLevels[VMXNET3_MAX_INTRS]; /* moderation level for each intr */ __le32 intrCtrl; __le32 reserved[2]; } #include "vmware_pack_end.h" Vmxnet3_IntrConf; /* one bit per VLAN ID, the size is in the units of uint32 */ #define VMXNET3_VFT_SIZE (4096 / (sizeof(uint32) * 8)) typedef #include "vmware_pack_begin.h" struct Vmxnet3_QueueStatus { Bool stopped; uint8 _pad[3]; __le32 error; } #include "vmware_pack_end.h" Vmxnet3_QueueStatus; typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxQueueCtrl { __le32 txNumDeferred; __le32 txThreshold; __le64 reserved; } #include "vmware_pack_end.h" Vmxnet3_TxQueueCtrl; typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxQueueCtrl { Bool updateRxProd; uint8 _pad[7]; __le64 reserved; } #include "vmware_pack_end.h" Vmxnet3_RxQueueCtrl; #define VMXNET3_RXM_UCAST 0x01 /* unicast only */ #define VMXNET3_RXM_MCAST 0x02 /* multicast passing the filters */ #define VMXNET3_RXM_BCAST 0x04 /* broadcast only */ #define VMXNET3_RXM_ALL_MULTI 0x08 /* all multicast */ #define VMXNET3_RXM_PROMISC 0x10 /* promiscuous */ typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxFilterConf { __le32 rxMode; /* VMXNET3_RXM_xxx */ __le16 mfTableLen; /* size of the multicast filter table */ __le16 _pad1; __le64 mfTablePA; /* PA of the multicast filters table */ __le32 vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */ } #include "vmware_pack_end.h" Vmxnet3_RxFilterConf; #define VMXNET3_PM_MAX_FILTERS 6 #define VMXNET3_PM_MAX_PATTERN_SIZE 128 #define VMXNET3_PM_MAX_MASK_SIZE (VMXNET3_PM_MAX_PATTERN_SIZE / 8) #define VMXNET3_PM_WAKEUP_MAGIC 0x01 /* wake up on magic pkts */ #define VMXNET3_PM_WAKEUP_FILTER 0x02 /* wake up on pkts matching filters */ typedef #include "vmware_pack_begin.h" struct Vmxnet3_PM_PktFilter { uint8 maskSize; uint8 patternSize; uint8 mask[VMXNET3_PM_MAX_MASK_SIZE]; uint8 pattern[VMXNET3_PM_MAX_PATTERN_SIZE]; uint8 pad[6]; } #include "vmware_pack_end.h" Vmxnet3_PM_PktFilter; typedef #include "vmware_pack_begin.h" struct Vmxnet3_PMConf { __le16 wakeUpEvents; /* VMXNET3_PM_WAKEUP_xxx */ uint8 numFilters; uint8 pad[5]; Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS]; } #include "vmware_pack_end.h" Vmxnet3_PMConf; typedef #include "vmware_pack_begin.h" struct Vmxnet3_VariableLenConfDesc { __le32 confVer; __le32 confLen; __le64 confPA; } #include "vmware_pack_end.h" Vmxnet3_VariableLenConfDesc; typedef #include "vmware_pack_begin.h" struct Vmxnet3_DSDevRead { /* read-only region for device, read by dev in response to a SET cmd */ Vmxnet3_MiscConf misc; Vmxnet3_IntrConf intrConf; Vmxnet3_RxFilterConf rxFilterConf; Vmxnet3_VariableLenConfDesc rssConfDesc; Vmxnet3_VariableLenConfDesc pmConfDesc; Vmxnet3_VariableLenConfDesc pluginConfDesc; } #include "vmware_pack_end.h" Vmxnet3_DSDevRead; typedef #include "vmware_pack_begin.h" struct Vmxnet3_TxQueueDesc { Vmxnet3_TxQueueCtrl ctrl; Vmxnet3_TxQueueConf conf; /* Driver read after a GET command */ Vmxnet3_QueueStatus status; UPT1_TxStats stats; uint8 _pad[88]; /* 128 aligned */ } #include "vmware_pack_end.h" Vmxnet3_TxQueueDesc; typedef #include "vmware_pack_begin.h" struct Vmxnet3_RxQueueDesc { Vmxnet3_RxQueueCtrl ctrl; Vmxnet3_RxQueueConf conf; /* Driver read after a GET command */ Vmxnet3_QueueStatus status; UPT1_RxStats stats; uint8 _pad[88]; /* 128 aligned */ } #include "vmware_pack_end.h" Vmxnet3_RxQueueDesc; typedef #include "vmware_pack_begin.h" struct Vmxnet3_DriverShared { __le32 magic; __le32 pad; /* make devRead start at 64-bit boundaries */ Vmxnet3_DSDevRead devRead; __le32 ecr; __le32 reserved[5]; } #include "vmware_pack_end.h" Vmxnet3_DriverShared; #define VMXNET3_ECR_RQERR (1 << 0) #define VMXNET3_ECR_TQERR (1 << 1) #define VMXNET3_ECR_LINK (1 << 2) #define VMXNET3_ECR_DIC (1 << 3) #define VMXNET3_ECR_DEBUG (1 << 4) /* flip the gen bit of a ring */ #define VMXNET3_FLIP_RING_GEN(gen) ((gen) = (gen) ^ 0x1) /* only use this if moving the idx won't affect the gen bit */ #define VMXNET3_INC_RING_IDX_ONLY(idx, ring_size) \ do {\ (idx)++;\ if (UNLIKELY((idx) == (ring_size))) {\ (idx) = 0;\ }\ } while (0) #define VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid) \ vfTable[vid >> 5] |= (1 << (vid & 31)) #define VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid) \ vfTable[vid >> 5] &= ~(1 << (vid & 31)) #define VMXNET3_VFTABLE_ENTRY_IS_SET(vfTable, vid) \ ((vfTable[vid >> 5] & (1 << (vid & 31))) != 0) #define VMXNET3_MAX_MTU 9000 #define VMXNET3_MIN_MTU 60 #define VMXNET3_LINK_UP (10000 << 16 | 1) // 10 Gbps, up #define VMXNET3_LINK_DOWN 0 #define VMXWIFI_DRIVER_SHARED_LEN 8192 #define VMXNET3_DID_PASSTHRU 0xFFFF #endif /* _VMXNET3_DEFS_H_ */ ================================================ FILE: drivers/net/vmxnet3/base/vmxnet3_osdep.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VMXNET3_OSDEP_H #define _VMXNET3_OSDEP_H typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; typedef int bool; typedef char Bool; #ifndef UNLIKELY #define UNLIKELY(x) __builtin_expect((x),0) #endif /* unlikely */ #endif /* _VMXNET3_OSDEP_H */ ================================================ FILE: drivers/net/vmxnet3/vmxnet3_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/vmxnet3_defs.h" #include "vmxnet3_ring.h" #include "vmxnet3_logs.h" #include "vmxnet3_ethdev.h" #define PROCESS_SYS_EVENTS 0 static int eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev); static int vmxnet3_dev_configure(struct rte_eth_dev *dev); static int vmxnet3_dev_start(struct rte_eth_dev *dev); static void vmxnet3_dev_stop(struct rte_eth_dev *dev); static void vmxnet3_dev_close(struct rte_eth_dev *dev); static void vmxnet3_dev_set_rxmode(struct vmxnet3_hw *hw, uint32_t feature, int set); static void vmxnet3_dev_promiscuous_enable(struct rte_eth_dev *dev); static void vmxnet3_dev_promiscuous_disable(struct rte_eth_dev *dev); static void vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev); static void vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev); static int vmxnet3_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); static void vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static void vmxnet3_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vid, int on); static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask); static void vmxnet3_dev_vlan_offload_set_clear(struct rte_eth_dev *dev, int mask, int clear); #if PROCESS_SYS_EVENTS == 1 static void vmxnet3_process_events(struct vmxnet3_hw *); #endif /* * The set of PCI devices this driver supports */ static const struct rte_pci_id pci_id_vmxnet3_map[] = { #define RTE_PCI_DEV_ID_DECL_VMXNET3(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" { .vendor_id = 0, /* sentinel */ }, }; static const struct eth_dev_ops vmxnet3_eth_dev_ops = { .dev_configure = vmxnet3_dev_configure, .dev_start = vmxnet3_dev_start, .dev_stop = vmxnet3_dev_stop, .dev_close = vmxnet3_dev_close, .promiscuous_enable = vmxnet3_dev_promiscuous_enable, .promiscuous_disable = vmxnet3_dev_promiscuous_disable, .allmulticast_enable = vmxnet3_dev_allmulticast_enable, .allmulticast_disable = vmxnet3_dev_allmulticast_disable, .link_update = vmxnet3_dev_link_update, .stats_get = vmxnet3_dev_stats_get, .dev_infos_get = vmxnet3_dev_info_get, .vlan_filter_set = vmxnet3_dev_vlan_filter_set, .vlan_offload_set = vmxnet3_dev_vlan_offload_set, .rx_queue_setup = vmxnet3_dev_rx_queue_setup, .rx_queue_release = vmxnet3_dev_rx_queue_release, .tx_queue_setup = vmxnet3_dev_tx_queue_setup, .tx_queue_release = vmxnet3_dev_tx_queue_release, }; static const struct rte_memzone * gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size, const char *post_string, int socket_id, uint16_t align) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%d_%s", dev->driver->pci_drv.name, dev->data->port_id, post_string); mz = rte_memzone_lookup(z_name); if (mz) return mz; return rte_memzone_reserve_aligned(z_name, size, socket_id, 0, align); } /** * Atomically reads the link status information from global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to read from. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static int vmxnet3_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /** * Atomically writes the link status information into global * structure rte_eth_dev. * * @param dev * - Pointer to the structure rte_eth_dev to write to. * - Pointer to the buffer to be saved with the link status. * * @return * - On success, zero. * - On failure, negative value. */ static int vmxnet3_dev_atomic_write_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = &(dev->data->dev_link); struct rte_eth_link *src = link; if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } /* * This function is based on vmxnet3_disable_intr() */ static void vmxnet3_disable_intr(struct vmxnet3_hw *hw) { int i; PMD_INIT_FUNC_TRACE(); hw->shared->devRead.intrConf.intrCtrl |= VMXNET3_IC_DISABLE_ALL; for (i = 0; i < VMXNET3_MAX_INTRS; i++) VMXNET3_WRITE_BAR0_REG(hw, VMXNET3_REG_IMR + i * 8, 1); } /* * It returns 0 on success. */ static int eth_vmxnet3_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; struct vmxnet3_hw *hw = eth_dev->data->dev_private; uint32_t mac_hi, mac_lo, ver; PMD_INIT_FUNC_TRACE(); eth_dev->dev_ops = &vmxnet3_eth_dev_ops; eth_dev->rx_pkt_burst = &vmxnet3_recv_pkts; eth_dev->tx_pkt_burst = &vmxnet3_xmit_pkts; pci_dev = eth_dev->pci_dev; /* * for secondary processes, we don't initialize any further as primary * has already done this work. */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; /* Vendor and Device ID need to be set before init of shared code */ hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr0 = (void *)pci_dev->mem_resource[0].addr; hw->hw_addr1 = (void *)pci_dev->mem_resource[1].addr; hw->num_rx_queues = 1; hw->num_tx_queues = 1; hw->bufs_per_pkt = 1; /* Check h/w version compatibility with driver. */ ver = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_VRRS); PMD_INIT_LOG(DEBUG, "Hardware version : %d", ver); if (ver & 0x1) VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_VRRS, 1); else { PMD_INIT_LOG(ERR, "Incompatible h/w version, should be 0x1"); return -EIO; } /* Check UPT version compatibility with driver. */ ver = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_UVRS); PMD_INIT_LOG(DEBUG, "UPT hardware version : %d", ver); if (ver & 0x1) VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_UVRS, 1); else { PMD_INIT_LOG(ERR, "Incompatible UPT version."); return -EIO; } /* Getting MAC Address */ mac_lo = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_MACL); mac_hi = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_MACH); memcpy(hw->perm_addr , &mac_lo, 4); memcpy(hw->perm_addr+4, &mac_hi, 2); /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("vmxnet3", ETHER_ADDR_LEN * VMXNET3_MAX_MAC_ADDRS, 0); if (eth_dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to store MAC addresses", ETHER_ADDR_LEN * VMXNET3_MAX_MAC_ADDRS); return -ENOMEM; } /* Copy the permanent MAC address */ ether_addr_copy((struct ether_addr *) hw->perm_addr, ð_dev->data->mac_addrs[0]); PMD_INIT_LOG(DEBUG, "MAC Address : %02x:%02x:%02x:%02x:%02x:%02x", hw->perm_addr[0], hw->perm_addr[1], hw->perm_addr[2], hw->perm_addr[3], hw->perm_addr[4], hw->perm_addr[5]); /* Put device in Quiesce Mode */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV); return 0; } static struct eth_driver rte_vmxnet3_pmd = { .pci_drv = { .name = "rte_vmxnet3_pmd", .id_table = pci_id_vmxnet3_map, .drv_flags = RTE_PCI_DRV_NEED_MAPPING, }, .eth_dev_init = eth_vmxnet3_dev_init, .dev_private_size = sizeof(struct vmxnet3_hw), }; /* * Driver initialization routine. * Invoked once at EAL init time. * Register itself as the [Poll Mode] Driver of Virtual PCI VMXNET3 devices. */ static int rte_vmxnet3_pmd_init(const char *name __rte_unused, const char *param __rte_unused) { PMD_INIT_FUNC_TRACE(); rte_eth_driver_register(&rte_vmxnet3_pmd); return 0; } static int vmxnet3_dev_configure(struct rte_eth_dev *dev) { const struct rte_memzone *mz; struct vmxnet3_hw *hw = dev->data->dev_private; size_t size; PMD_INIT_FUNC_TRACE(); if (dev->data->nb_rx_queues > UINT8_MAX || dev->data->nb_tx_queues > UINT8_MAX) return -EINVAL; size = dev->data->nb_rx_queues * sizeof(struct Vmxnet3_TxQueueDesc) + dev->data->nb_tx_queues * sizeof(struct Vmxnet3_RxQueueDesc); if (size > UINT16_MAX) return -EINVAL; hw->num_rx_queues = (uint8_t)dev->data->nb_rx_queues; hw->num_tx_queues = (uint8_t)dev->data->nb_tx_queues; /* * Allocate a memzone for Vmxnet3_DriverShared - Vmxnet3_DSDevRead * on current socket */ mz = gpa_zone_reserve(dev, sizeof(struct Vmxnet3_DriverShared), "shared", rte_socket_id(), 8); if (mz == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating shared zone"); return -ENOMEM; } memset(mz->addr, 0, mz->len); hw->shared = mz->addr; hw->sharedPA = mz->phys_addr; /* * Allocate a memzone for Vmxnet3_RxQueueDesc - Vmxnet3_TxQueueDesc * on current socket */ mz = gpa_zone_reserve(dev, size, "queuedesc", rte_socket_id(), VMXNET3_QUEUE_DESC_ALIGN); if (mz == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone"); return -ENOMEM; } memset(mz->addr, 0, mz->len); hw->tqd_start = (Vmxnet3_TxQueueDesc *)mz->addr; hw->rqd_start = (Vmxnet3_RxQueueDesc *)(hw->tqd_start + hw->num_tx_queues); hw->queueDescPA = mz->phys_addr; hw->queue_desc_len = (uint16_t)size; if (dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_RSS) { /* Allocate memory structure for UPT1_RSSConf and configure */ mz = gpa_zone_reserve(dev, sizeof(struct VMXNET3_RSSConf), "rss_conf", rte_socket_id(), RTE_CACHE_LINE_SIZE); if (mz == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating rss_conf structure zone"); return -ENOMEM; } memset(mz->addr, 0, mz->len); hw->rss_conf = mz->addr; hw->rss_confPA = mz->phys_addr; } return 0; } static int vmxnet3_setup_driver_shared(struct rte_eth_dev *dev) { struct rte_eth_conf port_conf = dev->data->dev_conf; struct vmxnet3_hw *hw = dev->data->dev_private; Vmxnet3_DriverShared *shared = hw->shared; Vmxnet3_DSDevRead *devRead = &shared->devRead; uint32_t *mac_ptr; uint32_t val, i; int ret, mask; shared->magic = VMXNET3_REV1_MAGIC; devRead->misc.driverInfo.version = VMXNET3_DRIVER_VERSION_NUM; /* Setting up Guest OS information */ devRead->misc.driverInfo.gos.gosBits = sizeof(void *) == 4 ? VMXNET3_GOS_BITS_32 : VMXNET3_GOS_BITS_64; devRead->misc.driverInfo.gos.gosType = VMXNET3_GOS_TYPE_LINUX; devRead->misc.driverInfo.vmxnet3RevSpt = 1; devRead->misc.driverInfo.uptVerSpt = 1; devRead->misc.mtu = rte_le_to_cpu_32(dev->data->mtu); devRead->misc.queueDescPA = hw->queueDescPA; devRead->misc.queueDescLen = hw->queue_desc_len; devRead->misc.numTxQueues = hw->num_tx_queues; devRead->misc.numRxQueues = hw->num_rx_queues; /* * Set number of interrupts to 1 * PMD disables all the interrupts but this is MUST to activate device * It needs at least one interrupt for link events to handle * So we'll disable it later after device activation if needed */ devRead->intrConf.numIntrs = 1; devRead->intrConf.intrCtrl |= VMXNET3_IC_DISABLE_ALL; for (i = 0; i < hw->num_tx_queues; i++) { Vmxnet3_TxQueueDesc *tqd = &hw->tqd_start[i]; vmxnet3_tx_queue_t *txq = dev->data->tx_queues[i]; tqd->ctrl.txNumDeferred = 0; tqd->ctrl.txThreshold = 1; tqd->conf.txRingBasePA = txq->cmd_ring.basePA; tqd->conf.compRingBasePA = txq->comp_ring.basePA; tqd->conf.dataRingBasePA = txq->data_ring.basePA; tqd->conf.txRingSize = txq->cmd_ring.size; tqd->conf.compRingSize = txq->comp_ring.size; tqd->conf.dataRingSize = txq->data_ring.size; tqd->conf.intrIdx = txq->comp_ring.intr_idx; tqd->status.stopped = TRUE; tqd->status.error = 0; memset(&tqd->stats, 0, sizeof(tqd->stats)); } for (i = 0; i < hw->num_rx_queues; i++) { Vmxnet3_RxQueueDesc *rqd = &hw->rqd_start[i]; vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i]; rqd->conf.rxRingBasePA[0] = rxq->cmd_ring[0].basePA; rqd->conf.rxRingBasePA[1] = rxq->cmd_ring[1].basePA; rqd->conf.compRingBasePA = rxq->comp_ring.basePA; rqd->conf.rxRingSize[0] = rxq->cmd_ring[0].size; rqd->conf.rxRingSize[1] = rxq->cmd_ring[1].size; rqd->conf.compRingSize = rxq->comp_ring.size; rqd->conf.intrIdx = rxq->comp_ring.intr_idx; rqd->status.stopped = TRUE; rqd->status.error = 0; memset(&rqd->stats, 0, sizeof(rqd->stats)); } /* RxMode set to 0 of VMXNET3_RXM_xxx */ devRead->rxFilterConf.rxMode = 0; /* Setting up feature flags */ if (dev->data->dev_conf.rxmode.hw_ip_checksum) devRead->misc.uptFeatures |= VMXNET3_F_RXCSUM; if (port_conf.rxmode.mq_mode == ETH_MQ_RX_RSS) { ret = vmxnet3_rss_configure(dev); if (ret != VMXNET3_SUCCESS) return ret; devRead->misc.uptFeatures |= VMXNET3_F_RSS; devRead->rssConfDesc.confVer = 1; devRead->rssConfDesc.confLen = sizeof(struct VMXNET3_RSSConf); devRead->rssConfDesc.confPA = hw->rss_confPA; } mask = 0; if (dev->data->dev_conf.rxmode.hw_vlan_strip) mask |= ETH_VLAN_STRIP_MASK; if (dev->data->dev_conf.rxmode.hw_vlan_filter) mask |= ETH_VLAN_FILTER_MASK; vmxnet3_dev_vlan_offload_set_clear(dev, mask, 1); PMD_INIT_LOG(DEBUG, "Writing MAC Address : %02x:%02x:%02x:%02x:%02x:%02x", hw->perm_addr[0], hw->perm_addr[1], hw->perm_addr[2], hw->perm_addr[3], hw->perm_addr[4], hw->perm_addr[5]); /* Write MAC Address back to device */ mac_ptr = (uint32_t *)hw->perm_addr; val = *mac_ptr; VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_MACL, val); val = (hw->perm_addr[5] << 8) | hw->perm_addr[4]; VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_MACH, val); return VMXNET3_SUCCESS; } /* * Configure device link speed and setup link. * Must be called after eth_vmxnet3_dev_init. Other wise it might fail * It returns 0 on success. */ static int vmxnet3_dev_start(struct rte_eth_dev *dev) { int status, ret; struct vmxnet3_hw *hw = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); ret = vmxnet3_setup_driver_shared(dev); if (ret != VMXNET3_SUCCESS) return ret; /* Exchange shared data with device */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAL, VMXNET3_GET_ADDR_LO(hw->sharedPA)); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAH, VMXNET3_GET_ADDR_HI(hw->sharedPA)); /* Activate device by register write */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_ACTIVATE_DEV); status = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD); if (status != 0) { PMD_INIT_LOG(ERR, "Device activation in %s(): UNSUCCESSFUL", __func__); return -1; } /* Disable interrupts */ vmxnet3_disable_intr(hw); /* * Load RX queues with blank mbufs and update next2fill index for device * Update RxMode of the device */ ret = vmxnet3_dev_rxtx_init(dev); if (ret != VMXNET3_SUCCESS) { PMD_INIT_LOG(ERR, "Device receive init in %s: UNSUCCESSFUL", __func__); return ret; } /* Setting proper Rx Mode and issue Rx Mode Update command */ vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_UCAST | VMXNET3_RXM_BCAST, 1); /* * Don't need to handle events for now */ #if PROCESS_SYS_EVENTS == 1 events = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_ECR); PMD_INIT_LOG(DEBUG, "Reading events: 0x%X", events); vmxnet3_process_events(hw); #endif return status; } /* * Stop device: disable rx and tx functions to allow for reconfiguring. */ static void vmxnet3_dev_stop(struct rte_eth_dev *dev) { struct rte_eth_link link; struct vmxnet3_hw *hw = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); if (hw->adapter_stopped == TRUE) { PMD_INIT_LOG(DEBUG, "Device already closed."); return; } /* disable interrupts */ vmxnet3_disable_intr(hw); /* quiesce the device first */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAL, 0); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_DSAH, 0); /* reset the device */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV); PMD_INIT_LOG(DEBUG, "Device reset."); hw->adapter_stopped = FALSE; vmxnet3_dev_clear_queues(dev); /* Clear recorded link status */ memset(&link, 0, sizeof(link)); vmxnet3_dev_atomic_write_link_status(dev, &link); } /* * Reset and stop device. */ static void vmxnet3_dev_close(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; PMD_INIT_FUNC_TRACE(); vmxnet3_dev_stop(dev); hw->adapter_stopped = TRUE; } static void vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { unsigned int i; struct vmxnet3_hw *hw = dev->data->dev_private; VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS); RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_TX_QUEUES); for (i = 0; i < hw->num_tx_queues; i++) { struct UPT1_TxStats *txStats = &hw->tqd_start[i].stats; stats->q_opackets[i] = txStats->ucastPktsTxOK + txStats->mcastPktsTxOK + txStats->bcastPktsTxOK; stats->q_obytes[i] = txStats->ucastBytesTxOK + txStats->mcastBytesTxOK + txStats->bcastBytesTxOK; stats->opackets += stats->q_opackets[i]; stats->obytes += stats->q_obytes[i]; stats->oerrors += txStats->pktsTxError + txStats->pktsTxDiscard; } RTE_BUILD_BUG_ON(RTE_ETHDEV_QUEUE_STAT_CNTRS < VMXNET3_MAX_RX_QUEUES); for (i = 0; i < hw->num_rx_queues; i++) { struct UPT1_RxStats *rxStats = &hw->rqd_start[i].stats; stats->q_ipackets[i] = rxStats->ucastPktsRxOK + rxStats->mcastPktsRxOK + rxStats->bcastPktsRxOK; stats->q_ibytes[i] = rxStats->ucastBytesRxOK + rxStats->mcastBytesRxOK + rxStats->bcastBytesRxOK; stats->ipackets += stats->q_ipackets[i]; stats->ibytes += stats->q_ibytes[i]; stats->q_errors[i] = rxStats->pktsRxError; stats->ierrors += rxStats->pktsRxError; stats->imcasts += rxStats->mcastPktsRxOK; stats->rx_nombuf += rxStats->pktsRxOutOfBuf; } } static void vmxnet3_dev_info_get(__attribute__((unused))struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { dev_info->max_rx_queues = VMXNET3_MAX_RX_QUEUES; dev_info->max_tx_queues = VMXNET3_MAX_TX_QUEUES; dev_info->min_rx_bufsize = 1518 + RTE_PKTMBUF_HEADROOM; dev_info->max_rx_pktlen = 16384; /* includes CRC, cf MAXFRS register */ dev_info->max_mac_addrs = VMXNET3_MAX_MAC_ADDRS; dev_info->default_txconf.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS; dev_info->flow_type_rss_offloads = VMXNET3_RSS_OFFLOAD_ALL; } /* return 0 means link status changed, -1 means not changed */ static int vmxnet3_dev_link_update(struct rte_eth_dev *dev, __attribute__((unused)) int wait_to_complete) { struct vmxnet3_hw *hw = dev->data->dev_private; struct rte_eth_link old, link; uint32_t ret; if (dev->data->dev_started == 0) return -1; /* Link status doesn't change for stopped dev */ memset(&link, 0, sizeof(link)); vmxnet3_dev_atomic_read_link_status(dev, &old); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK); ret = VMXNET3_READ_BAR1_REG(hw, VMXNET3_REG_CMD); if (ret & 0x1) { link.link_status = 1; link.link_duplex = ETH_LINK_FULL_DUPLEX; link.link_speed = ETH_LINK_SPEED_10000; } vmxnet3_dev_atomic_write_link_status(dev, &link); return (old.link_status == link.link_status) ? -1 : 0; } /* Updating rxmode through Vmxnet3_DriverShared structure in adapter */ static void vmxnet3_dev_set_rxmode(struct vmxnet3_hw *hw, uint32_t feature, int set) { struct Vmxnet3_RxFilterConf *rxConf = &hw->shared->devRead.rxFilterConf; if (set) rxConf->rxMode = rxConf->rxMode | feature; else rxConf->rxMode = rxConf->rxMode & (~feature); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_RX_MODE); } /* Promiscuous supported only if Vmxnet3_DriverShared is initialized in adapter */ static void vmxnet3_dev_promiscuous_enable(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; uint32_t *vf_table = hw->shared->devRead.rxFilterConf.vfTable; memset(vf_table, 0, VMXNET3_VFT_TABLE_SIZE); vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_PROMISC, 1); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_VLAN_FILTERS); } /* Promiscuous supported only if Vmxnet3_DriverShared is initialized in adapter */ static void vmxnet3_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; uint32_t *vf_table = hw->shared->devRead.rxFilterConf.vfTable; memcpy(vf_table, hw->shadow_vfta, VMXNET3_VFT_TABLE_SIZE); vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_PROMISC, 0); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_VLAN_FILTERS); } /* Allmulticast supported only if Vmxnet3_DriverShared is initialized in adapter */ static void vmxnet3_dev_allmulticast_enable(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_ALL_MULTI, 1); } /* Allmulticast supported only if Vmxnet3_DriverShared is initialized in adapter */ static void vmxnet3_dev_allmulticast_disable(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; vmxnet3_dev_set_rxmode(hw, VMXNET3_RXM_ALL_MULTI, 0); } /* Enable/disable filter on vlan */ static int vmxnet3_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vid, int on) { struct vmxnet3_hw *hw = dev->data->dev_private; struct Vmxnet3_RxFilterConf *rxConf = &hw->shared->devRead.rxFilterConf; uint32_t *vf_table = rxConf->vfTable; /* save state for restore */ if (on) VMXNET3_SET_VFTABLE_ENTRY(hw->shadow_vfta, vid); else VMXNET3_CLEAR_VFTABLE_ENTRY(hw->shadow_vfta, vid); /* don't change active filter if in promiscious mode */ if (rxConf->rxMode & VMXNET3_RXM_PROMISC) return 0; /* set in hardware */ if (on) VMXNET3_SET_VFTABLE_ENTRY(vf_table, vid); else VMXNET3_CLEAR_VFTABLE_ENTRY(vf_table, vid); VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_VLAN_FILTERS); return 0; } static void vmxnet3_dev_vlan_offload_set_clear(struct rte_eth_dev *dev, int mask, int clear) { struct vmxnet3_hw *hw = dev->data->dev_private; Vmxnet3_DSDevRead *devRead = &hw->shared->devRead; uint32_t *vf_table = devRead->rxFilterConf.vfTable; if (mask & ETH_VLAN_STRIP_MASK) devRead->misc.uptFeatures |= UPT1_F_RXVLAN; else devRead->misc.uptFeatures &= ~UPT1_F_RXVLAN; VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_FEATURE); if (mask & ETH_VLAN_FILTER_MASK) { if (clear) { memset(hw->shadow_vfta, 0, VMXNET3_VFT_TABLE_SIZE); /* allow untagged pkts */ VMXNET3_SET_VFTABLE_ENTRY(hw->shadow_vfta, 0); } memcpy(vf_table, hw->shadow_vfta, VMXNET3_VFT_TABLE_SIZE); } else { /* allow any pkts -- no filtering */ if (clear) memset(hw->shadow_vfta, 0xff, VMXNET3_VFT_TABLE_SIZE); memset(vf_table, 0xff, VMXNET3_VFT_TABLE_SIZE); } VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_UPDATE_VLAN_FILTERS); } static void vmxnet3_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask) { vmxnet3_dev_vlan_offload_set_clear(dev, mask, 0); } #if PROCESS_SYS_EVENTS == 1 static void vmxnet3_process_events(struct vmxnet3_hw *hw) { uint32_t events = hw->shared->ecr; if (!events) { PMD_INIT_LOG(ERR, "No events to process in %s()", __func__); return; } /* * ECR bits when written with 1b are cleared. Hence write * events back to ECR so that the bits which were set will be reset. */ VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_ECR, events); /* Check if link state has changed */ if (events & VMXNET3_ECR_LINK) PMD_INIT_LOG(ERR, "Process events in %s(): VMXNET3_ECR_LINK event", __func__); /* Check if there is an error on xmit/recv queues */ if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) { VMXNET3_WRITE_BAR1_REG(hw, VMXNET3_REG_CMD, VMXNET3_CMD_GET_QUEUE_STATUS); if (hw->tqd_start->status.stopped) PMD_INIT_LOG(ERR, "tq error 0x%x", hw->tqd_start->status.error); if (hw->rqd_start->status.stopped) PMD_INIT_LOG(ERR, "rq error 0x%x", hw->rqd_start->status.error); /* Reset the device */ /* Have to reset the device */ } if (events & VMXNET3_ECR_DIC) PMD_INIT_LOG(ERR, "Device implementation change event."); if (events & VMXNET3_ECR_DEBUG) PMD_INIT_LOG(ERR, "Debug event generated by device."); } #endif static struct rte_driver rte_vmxnet3_driver = { .type = PMD_PDEV, .init = rte_vmxnet3_pmd_init, }; PMD_REGISTER_DRIVER(rte_vmxnet3_driver); ================================================ FILE: drivers/net/vmxnet3/vmxnet3_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VMXNET3_ETHDEV_H_ #define _VMXNET3_ETHDEV_H_ #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER #define VMXNET3_ASSERT(x) do { \ if (!(x)) rte_panic("VMXNET3: %s\n", #x); \ } while(0) #else #define VMXNET3_ASSERT(x) do { (void)(x); } while (0) #endif #define VMXNET3_MAX_MAC_ADDRS 1 /* UPT feature to negotiate */ #define VMXNET3_F_RXCSUM 0x0001 #define VMXNET3_F_RSS 0x0002 #define VMXNET3_F_RXVLAN 0x0004 #define VMXNET3_F_LRO 0x0008 /* Hash Types supported by device */ #define VMXNET3_RSS_HASH_TYPE_NONE 0x0 #define VMXNET3_RSS_HASH_TYPE_IPV4 0x01 #define VMXNET3_RSS_HASH_TYPE_TCP_IPV4 0x02 #define VMXNET3_RSS_HASH_TYPE_IPV6 0x04 #define VMXNET3_RSS_HASH_TYPE_TCP_IPV6 0x08 #define VMXNET3_RSS_HASH_FUNC_NONE 0x0 #define VMXNET3_RSS_HASH_FUNC_TOEPLITZ 0x01 #define VMXNET3_RSS_MAX_KEY_SIZE 40 #define VMXNET3_RSS_MAX_IND_TABLE_SIZE 128 #define VMXNET3_RSS_OFFLOAD_ALL ( \ ETH_RSS_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_IPV6 | \ ETH_RSS_NONFRAG_IPV6_TCP) /* RSS configuration structure - shared with device through GPA */ typedef struct VMXNET3_RSSConf { uint16_t hashType; uint16_t hashFunc; uint16_t hashKeySize; uint16_t indTableSize; uint8_t hashKey[VMXNET3_RSS_MAX_KEY_SIZE]; /* * indTable is only element that can be changed without * device quiesce-reset-update-activation cycle */ uint8_t indTable[VMXNET3_RSS_MAX_IND_TABLE_SIZE]; } VMXNET3_RSSConf; typedef struct vmxnet3_mf_table { void *mfTableBase; /* Multicast addresses list */ uint64_t mfTablePA; /* Physical address of the list */ uint16_t num_addrs; /* number of multicast addrs */ } vmxnet3_mf_table_t; struct vmxnet3_hw { uint8_t *hw_addr0; /* BAR0: PT-Passthrough Regs */ uint8_t *hw_addr1; /* BAR1: VD-Virtual Device Regs */ /* BAR2: MSI-X Regs */ /* BAR3: Port IO */ void *back; uint16_t device_id; uint16_t vendor_id; uint16_t subsystem_device_id; uint16_t subsystem_vendor_id; bool adapter_stopped; uint8_t perm_addr[ETHER_ADDR_LEN]; uint8_t num_tx_queues; uint8_t num_rx_queues; uint8_t bufs_per_pkt; Vmxnet3_TxQueueDesc *tqd_start; /* start address of all tx queue desc */ Vmxnet3_RxQueueDesc *rqd_start; /* start address of all rx queue desc */ Vmxnet3_DriverShared *shared; uint64_t sharedPA; uint64_t queueDescPA; uint16_t queue_desc_len; VMXNET3_RSSConf *rss_conf; uint64_t rss_confPA; vmxnet3_mf_table_t *mf_table; uint32_t shadow_vfta[VMXNET3_VFT_SIZE]; #define VMXNET3_VFT_TABLE_SIZE (VMXNET3_VFT_SIZE * sizeof(uint32_t)) }; #define VMXNET3_GET_ADDR_LO(reg) ((uint32_t)(reg)) #define VMXNET3_GET_ADDR_HI(reg) ((uint32_t)(((uint64_t)(reg)) >> 32)) /* Config space read/writes */ #define VMXNET3_PCI_REG(reg) (*((volatile uint32_t *)(reg))) static inline uint32_t vmxnet3_read_addr(volatile void *addr) { return VMXNET3_PCI_REG(addr); } #define VMXNET3_PCI_REG_WRITE(reg, value) do { \ VMXNET3_PCI_REG((reg)) = (value); \ } while(0) #define VMXNET3_PCI_BAR0_REG_ADDR(hw, reg) \ ((volatile uint32_t *)((char *)(hw)->hw_addr0 + (reg))) #define VMXNET3_READ_BAR0_REG(hw, reg) \ vmxnet3_read_addr(VMXNET3_PCI_BAR0_REG_ADDR((hw), (reg))) #define VMXNET3_WRITE_BAR0_REG(hw, reg, value) \ VMXNET3_PCI_REG_WRITE(VMXNET3_PCI_BAR0_REG_ADDR((hw), (reg)), (value)) #define VMXNET3_PCI_BAR1_REG_ADDR(hw, reg) \ ((volatile uint32_t *)((char *)(hw)->hw_addr1 + (reg))) #define VMXNET3_READ_BAR1_REG(hw, reg) \ vmxnet3_read_addr(VMXNET3_PCI_BAR1_REG_ADDR((hw), (reg))) #define VMXNET3_WRITE_BAR1_REG(hw, reg, value) \ VMXNET3_PCI_REG_WRITE(VMXNET3_PCI_BAR1_REG_ADDR((hw), (reg)), (value)) /* * RX/TX function prototypes */ void vmxnet3_dev_clear_queues(struct rte_eth_dev *dev); void vmxnet3_dev_rx_queue_release(void *rxq); void vmxnet3_dev_tx_queue_release(void *txq); int vmxnet3_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); int vmxnet3_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); int vmxnet3_dev_rxtx_init(struct rte_eth_dev *dev); int vmxnet3_rss_configure(struct rte_eth_dev *dev); uint16_t vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); uint16_t vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); #endif /* _VMXNET3_ETHDEV_H_ */ ================================================ FILE: drivers/net/vmxnet3/vmxnet3_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VMXNET3_LOGS_H_ #define _VMXNET3_LOGS_H_ #ifdef RTE_LIBRTE_VMXNET3_DEBUG_INIT #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_LOG(level, fmt, args...) do { } while(0) #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_VMXNET3_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VMXNET3_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VMXNET3_DEBUG_TX_FREE #define PMD_TX_FREE_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER #define PMD_DRV_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #else #define PMD_DRV_LOG(level, fmt, args...) do { } while(0) #endif #endif /* _VMXNET3_LOGS_H_ */ ================================================ FILE: drivers/net/vmxnet3/vmxnet3_ring.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VMXNET3_RING_H_ #define _VMXNET3_RING_H_ #define VMXNET3_RX_CMDRING_SIZE 2 #define VMXNET3_DRIVER_VERSION_NUM 0x01012000 /* Default ring size */ #define VMXNET3_DEF_TX_RING_SIZE 512 #define VMXNET3_DEF_RX_RING_SIZE 128 #define VMXNET3_SUCCESS 0 #define VMXNET3_FAIL -1 #define TRUE 1 #define FALSE 0 typedef struct vmxnet3_buf_info { uint16_t len; struct rte_mbuf *m; uint64_t bufPA; } vmxnet3_buf_info_t; typedef struct vmxnet3_cmd_ring { vmxnet3_buf_info_t *buf_info; uint32_t size; uint32_t next2fill; uint32_t next2comp; uint8_t gen; uint8_t rid; Vmxnet3_GenericDesc *base; uint64_t basePA; } vmxnet3_cmd_ring_t; static inline void vmxnet3_cmd_ring_adv_next2fill(struct vmxnet3_cmd_ring *ring) { ring->next2fill++; if (unlikely(ring->next2fill == ring->size)) { ring->next2fill = 0; ring->gen = (uint8_t)(ring->gen ^ 1); } } static inline void vmxnet3_cmd_ring_adv_next2comp(struct vmxnet3_cmd_ring *ring) { VMXNET3_INC_RING_IDX_ONLY(ring->next2comp, ring->size); } static inline uint32_t vmxnet3_cmd_ring_desc_avail(struct vmxnet3_cmd_ring *ring) { return (ring->next2comp > ring->next2fill ? 0 : ring->size) + ring->next2comp - ring->next2fill - 1; } static inline bool vmxnet3_cmd_ring_desc_empty(struct vmxnet3_cmd_ring *ring) { return (ring->next2comp == ring->next2fill); } typedef struct vmxnet3_comp_ring { uint32_t size; uint32_t next2proc; uint8_t gen; uint8_t intr_idx; Vmxnet3_GenericDesc *base; uint64_t basePA; } vmxnet3_comp_ring_t; struct vmxnet3_data_ring { struct Vmxnet3_TxDataDesc *base; uint32_t size; uint64_t basePA; }; static inline void vmxnet3_comp_ring_adv_next2proc(struct vmxnet3_comp_ring *ring) { ring->next2proc++; if (unlikely(ring->next2proc == ring->size)) { ring->next2proc = 0; ring->gen = (uint8_t)(ring->gen ^ 1); } } struct vmxnet3_txq_stats { uint64_t drop_total; /* # of pkts dropped by the driver, * the counters below track droppings due to * different reasons */ uint64_t drop_too_many_segs; uint64_t drop_tso; uint64_t tx_ring_full; }; typedef struct vmxnet3_tx_ctx { int ip_type; bool is_vlan; bool is_cso; uint16_t evl_tag; /* only valid when is_vlan == TRUE */ uint32_t eth_hdr_size; /* only valid for pkts requesting tso or csum * offloading */ uint32_t ip_hdr_size; uint32_t l4_hdr_size; } vmxnet3_tx_ctx_t; typedef struct vmxnet3_tx_queue { struct vmxnet3_hw *hw; struct vmxnet3_cmd_ring cmd_ring; struct vmxnet3_comp_ring comp_ring; struct vmxnet3_data_ring data_ring; uint32_t qid; struct Vmxnet3_TxQueueDesc *shared; struct vmxnet3_txq_stats stats; bool stopped; uint16_t queue_id; /**< Device TX queue index. */ uint8_t port_id; /**< Device port identifier. */ } vmxnet3_tx_queue_t; struct vmxnet3_rxq_stats { uint64_t drop_total; uint64_t drop_err; uint64_t drop_fcs; uint64_t rx_buf_alloc_failure; }; typedef struct vmxnet3_rx_queue { struct rte_mempool *mp; struct vmxnet3_hw *hw; struct vmxnet3_cmd_ring cmd_ring[VMXNET3_RX_CMDRING_SIZE]; struct vmxnet3_comp_ring comp_ring; uint32_t qid1; uint32_t qid2; Vmxnet3_RxQueueDesc *shared; struct vmxnet3_rxq_stats stats; bool stopped; uint16_t queue_id; /**< Device RX queue index. */ uint8_t port_id; /**< Device port identifier. */ } vmxnet3_rx_queue_t; #endif /* _VMXNET3_RING_H_ */ ================================================ FILE: drivers/net/vmxnet3/vmxnet3_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/vmxnet3_defs.h" #include "vmxnet3_ring.h" #include "vmxnet3_logs.h" #include "vmxnet3_ethdev.h" #define RTE_MBUF_DATA_DMA_ADDR(mb) \ (uint64_t) ((mb)->buf_physaddr + (mb)->data_off) #define RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mb) \ (uint64_t) ((mb)->buf_physaddr + RTE_PKTMBUF_HEADROOM) static const uint32_t rxprod_reg[2] = {VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2}; static int vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t*, uint8_t); static void vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *); #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED static void vmxnet3_rxq_dump(struct vmxnet3_rx_queue *); static void vmxnet3_txq_dump(struct vmxnet3_tx_queue *); #endif static struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return m; } #ifdef RTE_LIBRTE_VMXNET3_DEBUG_DRIVER_NOT_USED static void vmxnet3_rxq_dump(struct vmxnet3_rx_queue *rxq) { uint32_t avail = 0; if (rxq == NULL) return; PMD_RX_LOG(DEBUG, "RXQ: cmd0 base : 0x%p cmd1 base : 0x%p comp ring base : 0x%p.", rxq->cmd_ring[0].base, rxq->cmd_ring[1].base, rxq->comp_ring.base); PMD_RX_LOG(DEBUG, "RXQ: cmd0 basePA : 0x%lx cmd1 basePA : 0x%lx comp ring basePA : 0x%lx.", (unsigned long)rxq->cmd_ring[0].basePA, (unsigned long)rxq->cmd_ring[1].basePA, (unsigned long)rxq->comp_ring.basePA); avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[0]); PMD_RX_LOG(DEBUG, "RXQ:cmd0: size=%u; free=%u; next2proc=%u; queued=%u", (uint32_t)rxq->cmd_ring[0].size, avail, rxq->comp_ring.next2proc, rxq->cmd_ring[0].size - avail); avail = vmxnet3_cmd_ring_desc_avail(&rxq->cmd_ring[1]); PMD_RX_LOG(DEBUG, "RXQ:cmd1 size=%u; free=%u; next2proc=%u; queued=%u", (uint32_t)rxq->cmd_ring[1].size, avail, rxq->comp_ring.next2proc, rxq->cmd_ring[1].size - avail); } static void vmxnet3_txq_dump(struct vmxnet3_tx_queue *txq) { uint32_t avail = 0; if (txq == NULL) return; PMD_TX_LOG(DEBUG, "TXQ: cmd base : 0x%p comp ring base : 0x%p data ring base : 0x%p.", txq->cmd_ring.base, txq->comp_ring.base, txq->data_ring.base); PMD_TX_LOG(DEBUG, "TXQ: cmd basePA : 0x%lx comp ring basePA : 0x%lx data ring basePA : 0x%lx.", (unsigned long)txq->cmd_ring.basePA, (unsigned long)txq->comp_ring.basePA, (unsigned long)txq->data_ring.basePA); avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring); PMD_TX_LOG(DEBUG, "TXQ: size=%u; free=%u; next2proc=%u; queued=%u", (uint32_t)txq->cmd_ring.size, avail, txq->comp_ring.next2proc, txq->cmd_ring.size - avail); } #endif static void vmxnet3_cmd_ring_release_mbufs(vmxnet3_cmd_ring_t *ring) { while (ring->next2comp != ring->next2fill) { /* No need to worry about tx desc ownership, device is quiesced by now. */ vmxnet3_buf_info_t *buf_info = ring->buf_info + ring->next2comp; if (buf_info->m) { rte_pktmbuf_free(buf_info->m); buf_info->m = NULL; buf_info->bufPA = 0; buf_info->len = 0; } vmxnet3_cmd_ring_adv_next2comp(ring); } } static void vmxnet3_cmd_ring_release(vmxnet3_cmd_ring_t *ring) { vmxnet3_cmd_ring_release_mbufs(ring); rte_free(ring->buf_info); ring->buf_info = NULL; } void vmxnet3_dev_tx_queue_release(void *txq) { vmxnet3_tx_queue_t *tq = txq; if (tq != NULL) { /* Release the cmd_ring */ vmxnet3_cmd_ring_release(&tq->cmd_ring); } } void vmxnet3_dev_rx_queue_release(void *rxq) { int i; vmxnet3_rx_queue_t *rq = rxq; if (rq != NULL) { /* Release both the cmd_rings */ for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) vmxnet3_cmd_ring_release(&rq->cmd_ring[i]); } } static void vmxnet3_dev_tx_queue_reset(void *txq) { vmxnet3_tx_queue_t *tq = txq; struct vmxnet3_cmd_ring *ring = &tq->cmd_ring; struct vmxnet3_comp_ring *comp_ring = &tq->comp_ring; struct vmxnet3_data_ring *data_ring = &tq->data_ring; int size; if (tq != NULL) { /* Release the cmd_ring mbufs */ vmxnet3_cmd_ring_release_mbufs(&tq->cmd_ring); } /* Tx vmxnet rings structure initialization*/ ring->next2fill = 0; ring->next2comp = 0; ring->gen = VMXNET3_INIT_GEN; comp_ring->next2proc = 0; comp_ring->gen = VMXNET3_INIT_GEN; size = sizeof(struct Vmxnet3_TxDesc) * ring->size; size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size; size += sizeof(struct Vmxnet3_TxDataDesc) * data_ring->size; memset(ring->base, 0, size); } static void vmxnet3_dev_rx_queue_reset(void *rxq) { int i; vmxnet3_rx_queue_t *rq = rxq; struct vmxnet3_cmd_ring *ring0, *ring1; struct vmxnet3_comp_ring *comp_ring; int size; if (rq != NULL) { /* Release both the cmd_rings mbufs */ for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) vmxnet3_cmd_ring_release_mbufs(&rq->cmd_ring[i]); } ring0 = &rq->cmd_ring[0]; ring1 = &rq->cmd_ring[1]; comp_ring = &rq->comp_ring; /* Rx vmxnet rings structure initialization */ ring0->next2fill = 0; ring1->next2fill = 0; ring0->next2comp = 0; ring1->next2comp = 0; ring0->gen = VMXNET3_INIT_GEN; ring1->gen = VMXNET3_INIT_GEN; comp_ring->next2proc = 0; comp_ring->gen = VMXNET3_INIT_GEN; size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size); size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size; memset(ring0->base, 0, size); } void vmxnet3_dev_clear_queues(struct rte_eth_dev *dev) { unsigned i; PMD_INIT_FUNC_TRACE(); for (i = 0; i < dev->data->nb_tx_queues; i++) { struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i]; if (txq != NULL) { txq->stopped = TRUE; vmxnet3_dev_tx_queue_reset(txq); } } for (i = 0; i < dev->data->nb_rx_queues; i++) { struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i]; if (rxq != NULL) { rxq->stopped = TRUE; vmxnet3_dev_rx_queue_reset(rxq); } } } static void vmxnet3_tq_tx_complete(vmxnet3_tx_queue_t *txq) { int completed = 0; struct rte_mbuf *mbuf; vmxnet3_comp_ring_t *comp_ring = &txq->comp_ring; struct Vmxnet3_TxCompDesc *tcd = (struct Vmxnet3_TxCompDesc *) (comp_ring->base + comp_ring->next2proc); while (tcd->gen == comp_ring->gen) { /* Release cmd_ring descriptor and free mbuf */ VMXNET3_ASSERT(txq->cmd_ring.base[tcd->txdIdx].txd.eop == 1); while (txq->cmd_ring.next2comp != tcd->txdIdx) { mbuf = txq->cmd_ring.buf_info[txq->cmd_ring.next2comp].m; txq->cmd_ring.buf_info[txq->cmd_ring.next2comp].m = NULL; rte_pktmbuf_free_seg(mbuf); /* Mark the txd for which tcd was generated as completed */ vmxnet3_cmd_ring_adv_next2comp(&txq->cmd_ring); completed++; } vmxnet3_comp_ring_adv_next2proc(comp_ring); tcd = (struct Vmxnet3_TxCompDesc *)(comp_ring->base + comp_ring->next2proc); } PMD_TX_LOG(DEBUG, "Processed %d tx comps & command descs.", completed); } uint16_t vmxnet3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { uint16_t nb_tx; vmxnet3_tx_queue_t *txq = tx_queue; struct vmxnet3_hw *hw = txq->hw; if (unlikely(txq->stopped)) { PMD_TX_LOG(DEBUG, "Tx queue is stopped."); return 0; } /* Free up the comp_descriptors aggressively */ vmxnet3_tq_tx_complete(txq); nb_tx = 0; while (nb_tx < nb_pkts) { Vmxnet3_GenericDesc *gdesc; vmxnet3_buf_info_t *tbi; uint32_t first2fill, avail, dw2; struct rte_mbuf *txm = tx_pkts[nb_tx]; struct rte_mbuf *m_seg = txm; /* Is this packet execessively fragmented, then drop */ if (unlikely(txm->nb_segs > VMXNET3_MAX_TXD_PER_PKT)) { ++txq->stats.drop_too_many_segs; ++txq->stats.drop_total; rte_pktmbuf_free(txm); ++nb_tx; continue; } /* Is command ring full? */ avail = vmxnet3_cmd_ring_desc_avail(&txq->cmd_ring); if (txm->nb_segs > avail) { ++txq->stats.tx_ring_full; break; } /* use the previous gen bit for the SOP desc */ dw2 = (txq->cmd_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; first2fill = txq->cmd_ring.next2fill; do { /* Remember the transmit buffer for cleanup */ tbi = txq->cmd_ring.buf_info + txq->cmd_ring.next2fill; tbi->m = m_seg; /* NB: the following assumes that VMXNET3 maximum transmit buffer size (16K) is greater than maximum sizeof mbuf segment size. */ gdesc = txq->cmd_ring.base + txq->cmd_ring.next2fill; gdesc->txd.addr = RTE_MBUF_DATA_DMA_ADDR(m_seg); gdesc->dword[2] = dw2 | m_seg->data_len; gdesc->dword[3] = 0; /* move to the next2fill descriptor */ vmxnet3_cmd_ring_adv_next2fill(&txq->cmd_ring); /* use the right gen for non-SOP desc */ dw2 = txq->cmd_ring.gen << VMXNET3_TXD_GEN_SHIFT; } while ((m_seg = m_seg->next) != NULL); /* Update the EOP descriptor */ gdesc->dword[3] |= VMXNET3_TXD_EOP | VMXNET3_TXD_CQ; /* Add VLAN tag if present */ gdesc = txq->cmd_ring.base + first2fill; if (txm->ol_flags & PKT_TX_VLAN_PKT) { gdesc->txd.ti = 1; gdesc->txd.tci = txm->vlan_tci; } /* TODO: Add transmit checksum offload here */ /* flip the GEN bit on the SOP */ rte_compiler_barrier(); gdesc->dword[2] ^= VMXNET3_TXD_GEN; txq->shared->ctrl.txNumDeferred++; nb_tx++; } PMD_TX_LOG(DEBUG, "vmxnet3 txThreshold: %u", txq->shared->ctrl.txThreshold); if (txq->shared->ctrl.txNumDeferred >= txq->shared->ctrl.txThreshold) { txq->shared->ctrl.txNumDeferred = 0; /* Notify vSwitch that packets are available. */ VMXNET3_WRITE_BAR0_REG(hw, (VMXNET3_REG_TXPROD + txq->queue_id * VMXNET3_REG_ALIGN), txq->cmd_ring.next2fill); } return nb_tx; } /* * Allocates mbufs and clusters. Post rx descriptors with buffer details * so that device can receive packets in those buffers. * Ring layout: * Among the two rings, 1st ring contains buffers of type 0 and type1. * bufs_per_pkt is set such that for non-LRO cases all the buffers required * by a frame will fit in 1st ring (1st buf of type0 and rest of type1). * 2nd ring contains buffers of type 1 alone. Second ring mostly be used * only for LRO. * */ static int vmxnet3_post_rx_bufs(vmxnet3_rx_queue_t *rxq, uint8_t ring_id) { int err = 0; uint32_t i = 0, val = 0; struct vmxnet3_cmd_ring *ring = &rxq->cmd_ring[ring_id]; if (ring_id == 0) { /* Usually: One HEAD type buf per packet * val = (ring->next2fill % rxq->hw->bufs_per_pkt) ? * VMXNET3_RXD_BTYPE_BODY : VMXNET3_RXD_BTYPE_HEAD; */ /* We use single packet buffer so all heads here */ val = VMXNET3_RXD_BTYPE_HEAD; } else { /* All BODY type buffers for 2nd ring */ val = VMXNET3_RXD_BTYPE_BODY; } while (vmxnet3_cmd_ring_desc_avail(ring) > 0) { struct Vmxnet3_RxDesc *rxd; struct rte_mbuf *mbuf; vmxnet3_buf_info_t *buf_info = &ring->buf_info[ring->next2fill]; rxd = (struct Vmxnet3_RxDesc *)(ring->base + ring->next2fill); /* Allocate blank mbuf for the current Rx Descriptor */ mbuf = rte_rxmbuf_alloc(rxq->mp); if (unlikely(mbuf == NULL)) { PMD_RX_LOG(ERR, "Error allocating mbuf in %s", __func__); rxq->stats.rx_buf_alloc_failure++; err = ENOMEM; break; } /* * Load mbuf pointer into buf_info[ring_size] * buf_info structure is equivalent to cookie for virtio-virtqueue */ buf_info->m = mbuf; buf_info->len = (uint16_t)(mbuf->buf_len - RTE_PKTMBUF_HEADROOM); buf_info->bufPA = RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf); /* Load Rx Descriptor with the buffer's GPA */ rxd->addr = buf_info->bufPA; /* After this point rxd->addr MUST not be NULL */ rxd->btype = val; rxd->len = buf_info->len; /* Flip gen bit at the end to change ownership */ rxd->gen = ring->gen; vmxnet3_cmd_ring_adv_next2fill(ring); i++; } /* Return error only if no buffers are posted at present */ if (vmxnet3_cmd_ring_desc_avail(ring) >= (ring->size - 1)) return -err; else return i; } /* Receive side checksum and other offloads */ static void vmxnet3_rx_offload(const Vmxnet3_RxCompDesc *rcd, struct rte_mbuf *rxm) { /* Check for hardware stripped VLAN tag */ if (rcd->ts) { rxm->ol_flags |= PKT_RX_VLAN_PKT; rxm->vlan_tci = rte_le_to_cpu_16((uint16_t)rcd->tci); } /* Check for RSS */ if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE) { rxm->ol_flags |= PKT_RX_RSS_HASH; rxm->hash.rss = rcd->rssHash; } /* Check packet type, checksum errors, etc. Only support IPv4 for now. */ if (rcd->v4) { struct ether_hdr *eth = rte_pktmbuf_mtod(rxm, struct ether_hdr *); struct ipv4_hdr *ip = (struct ipv4_hdr *)(eth + 1); if (((ip->version_ihl & 0xf) << 2) > (int)sizeof(struct ipv4_hdr)) #ifdef RTE_NEXT_ABI rxm->packet_type = RTE_PTYPE_L3_IPV4_EXT; #else rxm->ol_flags |= PKT_RX_IPV4_HDR_EXT; #endif else #ifdef RTE_NEXT_ABI rxm->packet_type = RTE_PTYPE_L3_IPV4; #else rxm->ol_flags |= PKT_RX_IPV4_HDR; #endif if (!rcd->cnc) { if (!rcd->ipc) rxm->ol_flags |= PKT_RX_IP_CKSUM_BAD; if ((rcd->tcp || rcd->udp) && !rcd->tuc) rxm->ol_flags |= PKT_RX_L4_CKSUM_BAD; } } } /* * Process the Rx Completion Ring of given vmxnet3_rx_queue * for nb_pkts burst and return the number of packets received */ uint16_t vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { uint16_t nb_rx; uint32_t nb_rxd, idx; uint8_t ring_idx; vmxnet3_rx_queue_t *rxq; Vmxnet3_RxCompDesc *rcd; vmxnet3_buf_info_t *rbi; Vmxnet3_RxDesc *rxd; struct rte_mbuf *rxm = NULL; struct vmxnet3_hw *hw; nb_rx = 0; ring_idx = 0; nb_rxd = 0; idx = 0; rxq = rx_queue; hw = rxq->hw; rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd; if (unlikely(rxq->stopped)) { PMD_RX_LOG(DEBUG, "Rx queue is stopped."); return 0; } while (rcd->gen == rxq->comp_ring.gen) { if (nb_rx >= nb_pkts) break; idx = rcd->rxdIdx; ring_idx = (uint8_t)((rcd->rqID == rxq->qid1) ? 0 : 1); rxd = (Vmxnet3_RxDesc *)rxq->cmd_ring[ring_idx].base + idx; rbi = rxq->cmd_ring[ring_idx].buf_info + idx; if (unlikely(rcd->sop != 1 || rcd->eop != 1)) { rte_pktmbuf_free_seg(rbi->m); PMD_RX_LOG(DEBUG, "Packet spread across multiple buffers\n)"); goto rcd_done; } PMD_RX_LOG(DEBUG, "rxd idx: %d ring idx: %d.", idx, ring_idx); VMXNET3_ASSERT(rcd->len <= rxd->len); VMXNET3_ASSERT(rbi->m); if (unlikely(rcd->len == 0)) { PMD_RX_LOG(DEBUG, "Rx buf was skipped. rxring[%d][%d]\n)", ring_idx, idx); VMXNET3_ASSERT(rcd->sop && rcd->eop); rte_pktmbuf_free_seg(rbi->m); goto rcd_done; } /* Assuming a packet is coming in a single packet buffer */ if (unlikely(rxd->btype != VMXNET3_RXD_BTYPE_HEAD)) { PMD_RX_LOG(DEBUG, "Alert : Misbehaving device, incorrect " " buffer type used. iPacket dropped."); rte_pktmbuf_free_seg(rbi->m); goto rcd_done; } VMXNET3_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_HEAD); /* Get the packet buffer pointer from buf_info */ rxm = rbi->m; /* Clear descriptor associated buf_info to be reused */ rbi->m = NULL; rbi->bufPA = 0; /* Update the index that we received a packet */ rxq->cmd_ring[ring_idx].next2comp = idx; /* For RCD with EOP set, check if there is frame error */ if (unlikely(rcd->err)) { rxq->stats.drop_total++; rxq->stats.drop_err++; if (!rcd->fcs) { rxq->stats.drop_fcs++; PMD_RX_LOG(ERR, "Recv packet dropped due to frame err."); } PMD_RX_LOG(ERR, "Error in received packet rcd#:%d rxd:%d", (int)(rcd - (struct Vmxnet3_RxCompDesc *) rxq->comp_ring.base), rcd->rxdIdx); rte_pktmbuf_free_seg(rxm); goto rcd_done; } /* Initialize newly received packet buffer */ rxm->port = rxq->port_id; rxm->nb_segs = 1; rxm->next = NULL; rxm->pkt_len = (uint16_t)rcd->len; rxm->data_len = (uint16_t)rcd->len; rxm->data_off = RTE_PKTMBUF_HEADROOM; rxm->ol_flags = 0; rxm->vlan_tci = 0; vmxnet3_rx_offload(rcd, rxm); rx_pkts[nb_rx++] = rxm; rcd_done: rxq->cmd_ring[ring_idx].next2comp = idx; VMXNET3_INC_RING_IDX_ONLY(rxq->cmd_ring[ring_idx].next2comp, rxq->cmd_ring[ring_idx].size); /* It's time to allocate some new buf and renew descriptors */ vmxnet3_post_rx_bufs(rxq, ring_idx); if (unlikely(rxq->shared->ctrl.updateRxProd)) { VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[ring_idx] + (rxq->queue_id * VMXNET3_REG_ALIGN), rxq->cmd_ring[ring_idx].next2fill); } /* Advance to the next descriptor in comp_ring */ vmxnet3_comp_ring_adv_next2proc(&rxq->comp_ring); rcd = &rxq->comp_ring.base[rxq->comp_ring.next2proc].rcd; nb_rxd++; if (nb_rxd > rxq->cmd_ring[0].size) { PMD_RX_LOG(ERR, "Used up quota of receiving packets," " relinquish control."); break; } } return nb_rx; } /* * Create memzone for device rings. malloc can't be used as the physical address is * needed. If the memzone is already created, then this function returns a ptr * to the old one. */ static const struct rte_memzone * ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name, uint16_t queue_id, uint32_t ring_size, int socket_id) { char z_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d", dev->driver->pci_drv.name, ring_name, dev->data->port_id, queue_id); mz = rte_memzone_lookup(z_name); if (mz) return mz; return rte_memzone_reserve_aligned(z_name, ring_size, socket_id, 0, VMXNET3_RING_BA_ALIGN); } int vmxnet3_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, __attribute__((unused)) const struct rte_eth_txconf *tx_conf) { struct vmxnet3_hw *hw = dev->data->dev_private; const struct rte_memzone *mz; struct vmxnet3_tx_queue *txq; struct vmxnet3_cmd_ring *ring; struct vmxnet3_comp_ring *comp_ring; struct vmxnet3_data_ring *data_ring; int size; PMD_INIT_FUNC_TRACE(); if ((tx_conf->txq_flags & ETH_TXQ_FLAGS_NOXSUMS) != ETH_TXQ_FLAGS_NOXSUMS) { PMD_INIT_LOG(ERR, "TX no support for checksum offload yet"); return -EINVAL; } txq = rte_zmalloc("ethdev_tx_queue", sizeof(struct vmxnet3_tx_queue), RTE_CACHE_LINE_SIZE); if (txq == NULL) { PMD_INIT_LOG(ERR, "Can not allocate tx queue structure"); return -ENOMEM; } txq->queue_id = queue_idx; txq->port_id = dev->data->port_id; txq->shared = &hw->tqd_start[queue_idx]; txq->hw = hw; txq->qid = queue_idx; txq->stopped = TRUE; ring = &txq->cmd_ring; comp_ring = &txq->comp_ring; data_ring = &txq->data_ring; /* Tx vmxnet ring length should be between 512-4096 */ if (nb_desc < VMXNET3_DEF_TX_RING_SIZE) { PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Min: %u", VMXNET3_DEF_TX_RING_SIZE); return -EINVAL; } else if (nb_desc > VMXNET3_TX_RING_MAX_SIZE) { PMD_INIT_LOG(ERR, "VMXNET3 Tx Ring Size Max: %u", VMXNET3_TX_RING_MAX_SIZE); return -EINVAL; } else { ring->size = nb_desc; ring->size &= ~VMXNET3_RING_SIZE_MASK; } comp_ring->size = data_ring->size = ring->size; /* Tx vmxnet rings structure initialization*/ ring->next2fill = 0; ring->next2comp = 0; ring->gen = VMXNET3_INIT_GEN; comp_ring->next2proc = 0; comp_ring->gen = VMXNET3_INIT_GEN; size = sizeof(struct Vmxnet3_TxDesc) * ring->size; size += sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size; size += sizeof(struct Vmxnet3_TxDataDesc) * data_ring->size; mz = ring_dma_zone_reserve(dev, "txdesc", queue_idx, size, socket_id); if (mz == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone"); return -ENOMEM; } memset(mz->addr, 0, mz->len); /* cmd_ring initialization */ ring->base = mz->addr; ring->basePA = mz->phys_addr; /* comp_ring initialization */ comp_ring->base = ring->base + ring->size; comp_ring->basePA = ring->basePA + (sizeof(struct Vmxnet3_TxDesc) * ring->size); /* data_ring initialization */ data_ring->base = (Vmxnet3_TxDataDesc *)(comp_ring->base + comp_ring->size); data_ring->basePA = comp_ring->basePA + (sizeof(struct Vmxnet3_TxCompDesc) * comp_ring->size); /* cmd_ring0 buf_info allocation */ ring->buf_info = rte_zmalloc("tx_ring_buf_info", ring->size * sizeof(vmxnet3_buf_info_t), RTE_CACHE_LINE_SIZE); if (ring->buf_info == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating tx_buf_info structure"); return -ENOMEM; } /* Update the data portion with txq */ dev->data->tx_queues[queue_idx] = txq; return 0; } int vmxnet3_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t nb_desc, unsigned int socket_id, __attribute__((unused)) const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { const struct rte_memzone *mz; struct vmxnet3_rx_queue *rxq; struct vmxnet3_hw *hw = dev->data->dev_private; struct vmxnet3_cmd_ring *ring0, *ring1, *ring; struct vmxnet3_comp_ring *comp_ring; int size; uint8_t i; char mem_name[32]; uint16_t buf_size; PMD_INIT_FUNC_TRACE(); buf_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; if (dev->data->dev_conf.rxmode.max_rx_pkt_len > buf_size) { PMD_INIT_LOG(ERR, "buf_size = %u, max_pkt_len = %u, " "VMXNET3 don't support scatter packets yet", buf_size, dev->data->dev_conf.rxmode.max_rx_pkt_len); return -EINVAL; } rxq = rte_zmalloc("ethdev_rx_queue", sizeof(struct vmxnet3_rx_queue), RTE_CACHE_LINE_SIZE); if (rxq == NULL) { PMD_INIT_LOG(ERR, "Can not allocate rx queue structure"); return -ENOMEM; } rxq->mp = mp; rxq->queue_id = queue_idx; rxq->port_id = dev->data->port_id; rxq->shared = &hw->rqd_start[queue_idx]; rxq->hw = hw; rxq->qid1 = queue_idx; rxq->qid2 = queue_idx + hw->num_rx_queues; rxq->stopped = TRUE; ring0 = &rxq->cmd_ring[0]; ring1 = &rxq->cmd_ring[1]; comp_ring = &rxq->comp_ring; /* Rx vmxnet rings length should be between 256-4096 */ if (nb_desc < VMXNET3_DEF_RX_RING_SIZE) { PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Min: 256"); return -EINVAL; } else if (nb_desc > VMXNET3_RX_RING_MAX_SIZE) { PMD_INIT_LOG(ERR, "VMXNET3 Rx Ring Size Max: 4096"); return -EINVAL; } else { ring0->size = nb_desc; ring0->size &= ~VMXNET3_RING_SIZE_MASK; ring1->size = ring0->size; } comp_ring->size = ring0->size + ring1->size; /* Rx vmxnet rings structure initialization */ ring0->next2fill = 0; ring1->next2fill = 0; ring0->next2comp = 0; ring1->next2comp = 0; ring0->gen = VMXNET3_INIT_GEN; ring1->gen = VMXNET3_INIT_GEN; comp_ring->next2proc = 0; comp_ring->gen = VMXNET3_INIT_GEN; size = sizeof(struct Vmxnet3_RxDesc) * (ring0->size + ring1->size); size += sizeof(struct Vmxnet3_RxCompDesc) * comp_ring->size; mz = ring_dma_zone_reserve(dev, "rxdesc", queue_idx, size, socket_id); if (mz == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating queue descriptors zone"); return -ENOMEM; } memset(mz->addr, 0, mz->len); /* cmd_ring0 initialization */ ring0->base = mz->addr; ring0->basePA = mz->phys_addr; /* cmd_ring1 initialization */ ring1->base = ring0->base + ring0->size; ring1->basePA = ring0->basePA + sizeof(struct Vmxnet3_RxDesc) * ring0->size; /* comp_ring initialization */ comp_ring->base = ring1->base + ring1->size; comp_ring->basePA = ring1->basePA + sizeof(struct Vmxnet3_RxDesc) * ring1->size; /* cmd_ring0-cmd_ring1 buf_info allocation */ for (i = 0; i < VMXNET3_RX_CMDRING_SIZE; i++) { ring = &rxq->cmd_ring[i]; ring->rid = i; snprintf(mem_name, sizeof(mem_name), "rx_ring_%d_buf_info", i); ring->buf_info = rte_zmalloc(mem_name, ring->size * sizeof(vmxnet3_buf_info_t), RTE_CACHE_LINE_SIZE); if (ring->buf_info == NULL) { PMD_INIT_LOG(ERR, "ERROR: Creating rx_buf_info structure"); return -ENOMEM; } } /* Update the data portion with rxq */ dev->data->rx_queues[queue_idx] = rxq; return 0; } /* * Initializes Receive Unit * Load mbufs in rx queue in advance */ int vmxnet3_dev_rxtx_init(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; int i, ret; uint8_t j; PMD_INIT_FUNC_TRACE(); for (i = 0; i < hw->num_rx_queues; i++) { vmxnet3_rx_queue_t *rxq = dev->data->rx_queues[i]; for (j = 0; j < VMXNET3_RX_CMDRING_SIZE; j++) { /* Passing 0 as alloc_num will allocate full ring */ ret = vmxnet3_post_rx_bufs(rxq, j); if (ret <= 0) { PMD_INIT_LOG(ERR, "ERROR: Posting Rxq: %d buffers ring: %d", i, j); return -ret; } /* Updating device with the index:next2fill to fill the mbufs for coming packets */ if (unlikely(rxq->shared->ctrl.updateRxProd)) { VMXNET3_WRITE_BAR0_REG(hw, rxprod_reg[j] + (rxq->queue_id * VMXNET3_REG_ALIGN), rxq->cmd_ring[j].next2fill); } } rxq->stopped = FALSE; } for (i = 0; i < dev->data->nb_tx_queues; i++) { struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i]; txq->stopped = FALSE; } return 0; } static uint8_t rss_intel_key[40] = { 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA, }; /* * Configure RSS feature */ int vmxnet3_rss_configure(struct rte_eth_dev *dev) { struct vmxnet3_hw *hw = dev->data->dev_private; struct VMXNET3_RSSConf *dev_rss_conf; struct rte_eth_rss_conf *port_rss_conf; uint64_t rss_hf; uint8_t i, j; PMD_INIT_FUNC_TRACE(); dev_rss_conf = hw->rss_conf; port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf; /* loading hashFunc */ dev_rss_conf->hashFunc = VMXNET3_RSS_HASH_FUNC_TOEPLITZ; /* loading hashKeySize */ dev_rss_conf->hashKeySize = VMXNET3_RSS_MAX_KEY_SIZE; /* loading indTableSize : Must not exceed VMXNET3_RSS_MAX_IND_TABLE_SIZE (128)*/ dev_rss_conf->indTableSize = (uint16_t)(hw->num_rx_queues * 4); if (port_rss_conf->rss_key == NULL) { /* Default hash key */ port_rss_conf->rss_key = rss_intel_key; } /* loading hashKey */ memcpy(&dev_rss_conf->hashKey[0], port_rss_conf->rss_key, dev_rss_conf->hashKeySize); /* loading indTable */ for (i = 0, j = 0; i < dev_rss_conf->indTableSize; i++, j++) { if (j == dev->data->nb_rx_queues) j = 0; dev_rss_conf->indTable[i] = j; } /* loading hashType */ dev_rss_conf->hashType = 0; rss_hf = port_rss_conf->rss_hf & VMXNET3_RSS_OFFLOAD_ALL; if (rss_hf & ETH_RSS_IPV4) dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV4; if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV4; if (rss_hf & ETH_RSS_IPV6) dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_IPV6; if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) dev_rss_conf->hashType |= VMXNET3_RSS_HASH_TYPE_TCP_IPV6; return VMXNET3_SUCCESS; } ================================================ FILE: drivers/net/xenvirt/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pmd_xenvirt.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_eth_xenvirt_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += rte_eth_xenvirt.c rte_mempool_gntalloc.c rte_xen_lib.c # # Export include files # SYMLINK-y-include += rte_eth_xenvirt.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += lib/librte_eal lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += lib/librte_net DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += lib/librte_cmdline include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: drivers/net/xenvirt/rte_eth_xenvirt.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040200 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include "rte_xen_lib.h" #include "virtqueue.h" #include "rte_eth_xenvirt.h" #define VQ_DESC_NUM 256 #define VIRTIO_MBUF_BURST_SZ 64 /* virtio_idx is increased after new device is created.*/ static int virtio_idx = 0; static const char *drivername = "xen dummy virtio PMD"; static struct rte_eth_link pmd_link = { .link_speed = 10000, .link_duplex = ETH_LINK_FULL_DUPLEX, .link_status = 0 }; static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; m = __rte_mbuf_raw_alloc(mp); __rte_mbuf_sanity_check_raw(m, 0); return m; } static uint16_t eth_xenvirt_rx(void *q, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct virtqueue *rxvq = q; struct rte_mbuf *rxm, *new_mbuf; uint16_t nb_used, num; uint32_t len[VIRTIO_MBUF_BURST_SZ]; uint32_t i; struct pmd_internals *pi = rxvq->internals; nb_used = VIRTQUEUE_NUSED(rxvq); rte_compiler_barrier(); /* rmb */ num = (uint16_t)(likely(nb_used <= nb_pkts) ? nb_used : nb_pkts); num = (uint16_t)(likely(num <= VIRTIO_MBUF_BURST_SZ) ? num : VIRTIO_MBUF_BURST_SZ); if (unlikely(num == 0)) return 0; num = virtqueue_dequeue_burst(rxvq, rx_pkts, len, num); PMD_RX_LOG(DEBUG, "used:%d dequeue:%d\n", nb_used, num); for (i = 0; i < num ; i ++) { rxm = rx_pkts[i]; PMD_RX_LOG(DEBUG, "packet len:%d\n", len[i]); rxm->next = NULL; rxm->data_off = RTE_PKTMBUF_HEADROOM; rxm->data_len = (uint16_t)(len[i] - sizeof(struct virtio_net_hdr)); rxm->nb_segs = 1; rxm->port = pi->port_id; rxm->pkt_len = (uint32_t)(len[i] - sizeof(struct virtio_net_hdr)); } /* allocate new mbuf for the used descriptor */ while (likely(!virtqueue_full(rxvq))) { new_mbuf = rte_rxmbuf_alloc(rxvq->mpool); if (unlikely(new_mbuf == NULL)) { break; } if (unlikely(virtqueue_enqueue_recv_refill(rxvq, new_mbuf))) { rte_pktmbuf_free_seg(new_mbuf); break; } } pi->eth_stats.ipackets += num; return num; } static uint16_t eth_xenvirt_tx(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct virtqueue *txvq = tx_queue; struct rte_mbuf *txm; uint16_t nb_used, nb_tx, num, i; int error; uint32_t len[VIRTIO_MBUF_BURST_SZ]; struct rte_mbuf *snd_pkts[VIRTIO_MBUF_BURST_SZ]; struct pmd_internals *pi = txvq->internals; nb_tx = 0; if (unlikely(nb_pkts == 0)) return 0; PMD_TX_LOG(DEBUG, "%d packets to xmit", nb_pkts); nb_used = VIRTQUEUE_NUSED(txvq); rte_compiler_barrier(); /* rmb */ num = (uint16_t)(likely(nb_used <= VIRTIO_MBUF_BURST_SZ) ? nb_used : VIRTIO_MBUF_BURST_SZ); num = virtqueue_dequeue_burst(txvq, snd_pkts, len, num); for (i = 0; i < num ; i ++) { /* mergable not supported, one segment only */ rte_pktmbuf_free_seg(snd_pkts[i]); } while (nb_tx < nb_pkts) { if (likely(!virtqueue_full(txvq))) { /* TODO drop tx_pkts if it contains multiple segments */ txm = tx_pkts[nb_tx]; error = virtqueue_enqueue_xmit(txvq, txm); if (unlikely(error)) { if (error == ENOSPC) PMD_TX_LOG(ERR, "virtqueue_enqueue Free count = 0\n"); else if (error == EMSGSIZE) PMD_TX_LOG(ERR, "virtqueue_enqueue Free count < 1\n"); else PMD_TX_LOG(ERR, "virtqueue_enqueue error: %d\n", error); break; } nb_tx++; } else { PMD_TX_LOG(ERR, "No free tx descriptors to transmit\n"); /* virtqueue_notify not needed in our para-virt solution */ break; } } pi->eth_stats.opackets += nb_tx; return nb_tx; } static int eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { RTE_LOG(ERR, PMD, "%s\n", __func__); return 0; } /* * Create a shared page between guest and host. * Host monitors this page if it is cleared on unmap, and then * do necessary clean up. */ static void gntalloc_vring_flag(int vtidx) { char key_str[PATH_MAX]; char val_str[PATH_MAX]; uint32_t gref_tmp; void *ptr; if (grefwatch_from_alloc(&gref_tmp, &ptr)) { RTE_LOG(ERR, PMD, "grefwatch_from_alloc error\n"); exit(0); } *(uint8_t *)ptr = MAP_FLAG; snprintf(val_str, sizeof(val_str), "%u", gref_tmp); snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"VRING_FLAG_STR, vtidx); xenstore_write(key_str, val_str); } /* * Notify host this virtio device is started. * Host could start polling this device. */ static void dev_start_notify(int vtidx) { char key_str[PATH_MAX]; char val_str[PATH_MAX]; RTE_LOG(INFO, PMD, "%s: virtio %d is started\n", __func__, vtidx); gntalloc_vring_flag(vtidx); snprintf(key_str, sizeof(key_str), "%s%s%d", DPDK_XENSTORE_PATH, EVENT_TYPE_START_STR, vtidx); snprintf(val_str, sizeof(val_str), "1"); xenstore_write(key_str, val_str); } /* * Notify host this virtio device is stopped. * Host could stop polling this device. */ static void dev_stop_notify(int vtidx) { RTE_SET_USED(vtidx); } static int update_mac_address(struct ether_addr *mac_addrs, int vtidx) { char key_str[PATH_MAX]; char val_str[PATH_MAX]; int rv; if (mac_addrs == NULL) { RTE_LOG(ERR, PMD, "%s: NULL pointer mac specified\n", __func__); return -1; } rv = snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d_ether_addr", vtidx); if (rv == -1) return rv; rv = snprintf(val_str, sizeof(val_str), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addrs->addr_bytes[0], mac_addrs->addr_bytes[1], mac_addrs->addr_bytes[2], mac_addrs->addr_bytes[3], mac_addrs->addr_bytes[4], mac_addrs->addr_bytes[5]); if (rv == -1) return rv; if (xenstore_write(key_str, val_str)) return rv; return 0; } static int eth_dev_start(struct rte_eth_dev *dev) { struct virtqueue *rxvq = dev->data->rx_queues[0]; struct virtqueue *txvq = dev->data->tx_queues[0]; struct rte_mbuf *m; struct pmd_internals *pi = (struct pmd_internals *)dev->data->dev_private; int rv; dev->data->dev_link.link_status = 1; while (!virtqueue_full(rxvq)) { m = rte_rxmbuf_alloc(rxvq->mpool); if (m == NULL) break; /* Enqueue allocated buffers. */ if (virtqueue_enqueue_recv_refill(rxvq, m)) { rte_pktmbuf_free_seg(m); break; } } rxvq->internals = pi; txvq->internals = pi; rv = update_mac_address(dev->data->mac_addrs, pi->virtio_idx); if (rv) return -1; dev_start_notify(pi->virtio_idx); return 0; } static void eth_dev_stop(struct rte_eth_dev *dev) { struct pmd_internals *pi = (struct pmd_internals *)dev->data->dev_private; dev->data->dev_link.link_status = 0; dev_stop_notify(pi->virtio_idx); } /* * Notify host this virtio device is closed. * Host could do necessary clean up to this device. */ static void eth_dev_close(struct rte_eth_dev *dev) { RTE_SET_USED(dev); } static void eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) { struct pmd_internals *internals = dev->data->dev_private; RTE_SET_USED(internals); dev_info->driver_name = drivername; dev_info->max_mac_addrs = 1; dev_info->max_rx_pktlen = (uint32_t)2048; dev_info->max_rx_queues = (uint16_t)1; dev_info->max_tx_queues = (uint16_t)1; dev_info->min_rx_bufsize = 0; dev_info->pci_dev = NULL; } static void eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { struct pmd_internals *internals = dev->data->dev_private; if(stats) rte_memcpy(stats, &internals->eth_stats, sizeof(*stats)); } static void eth_stats_reset(struct rte_eth_dev *dev) { struct pmd_internals *internals = dev->data->dev_private; /* Reset software totals */ memset(&internals->eth_stats, 0, sizeof(internals->eth_stats)); } static void eth_queue_release(void *q __rte_unused) { } static int eth_link_update(struct rte_eth_dev *dev __rte_unused, int wait_to_complete __rte_unused) { return 0; } /* * Create shared vring between guest and host. * Memory is allocated through grant alloc driver, so it is not physical continuous. */ static void * gntalloc_vring_create(int queue_type, uint32_t size, int vtidx) { char key_str[PATH_MAX] = {0}; char val_str[PATH_MAX] = {0}; void *va = NULL; int pg_size; uint32_t pg_num; uint32_t *gref_arr = NULL; phys_addr_t *pa_arr = NULL; uint64_t start_index; int rv; pg_size = getpagesize(); size = RTE_ALIGN_CEIL(size, pg_size); pg_num = size / pg_size; gref_arr = calloc(pg_num, sizeof(gref_arr[0])); pa_arr = calloc(pg_num, sizeof(pa_arr[0])); if (gref_arr == NULL || pa_arr == NULL) { RTE_LOG(ERR, PMD, "%s: calloc failed\n", __func__); goto out; } va = gntalloc(size, gref_arr, &start_index); if (va == NULL) { RTE_LOG(ERR, PMD, "%s: gntalloc failed\n", __func__); goto out; } if (get_phys_map(va, pa_arr, pg_num, pg_size)) goto out; /* write in xenstore gref and pfn for each page of vring */ if (grant_node_create(pg_num, gref_arr, pa_arr, val_str, sizeof(val_str))) { gntfree(va, size, start_index); va = NULL; goto out; } if (queue_type == VTNET_RQ) rv = snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"RXVRING_XENSTORE_STR, vtidx); else rv = snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"TXVRING_XENSTORE_STR, vtidx); if (rv == -1 || xenstore_write(key_str, val_str) == -1) { gntfree(va, size, start_index); va = NULL; } out: if (pa_arr) free(pa_arr); if (gref_arr) free(gref_arr); return va; } static struct virtqueue * virtio_queue_setup(struct rte_eth_dev *dev, int queue_type) { struct virtqueue *vq = NULL; uint16_t vq_size = VQ_DESC_NUM; int i = 0; char vq_name[VIRTQUEUE_MAX_NAME_SZ]; size_t size; struct vring *vr; /* Allocate memory for virtqueue. */ if (queue_type == VTNET_RQ) { snprintf(vq_name, sizeof(vq_name), "port%d_rvq", dev->data->port_id); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); if (vq == NULL) { RTE_LOG(ERR, PMD, "%s: unabled to allocate virtqueue\n", __func__); return NULL; } memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); } else if(queue_type == VTNET_TQ) { snprintf(vq_name, sizeof(vq_name), "port%d_tvq", dev->data->port_id); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); if (vq == NULL) { RTE_LOG(ERR, PMD, "%s: unabled to allocate virtqueue\n", __func__); return NULL; } memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); } memcpy(vq->vq_name, vq_name, sizeof(vq->vq_name)); vq->vq_alignment = VIRTIO_PCI_VRING_ALIGN; vq->vq_nentries = vq_size; vq->vq_free_cnt = vq_size; /* Calcuate vring size according to virtio spec */ size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN); vq->vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN); /* Allocate memory for virtio vring through gntalloc driver*/ vq->vq_ring_virt_mem = gntalloc_vring_create(queue_type, vq->vq_ring_size, ((struct pmd_internals *)dev->data->dev_private)->virtio_idx); memset(vq->vq_ring_virt_mem, 0, vq->vq_ring_size); vr = &vq->vq_ring; vring_init(vr, vq_size, vq->vq_ring_virt_mem, vq->vq_alignment); /* * Locally maintained last consumed index, this idex trails * vq_ring.used->idx. */ vq->vq_used_cons_idx = 0; vq->vq_desc_head_idx = 0; vq->vq_free_cnt = vq->vq_nentries; memset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries); /* Chain all the descriptors in the ring with an END */ for (i = 0; i < vq_size - 1; i++) vr->desc[i].next = (uint16_t)(i + 1); vr->desc[i].next = VQ_RING_DESC_CHAIN_END; return vq; } static int eth_rx_queue_setup(struct rte_eth_dev *dev,uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_rxconf *rx_conf __rte_unused, struct rte_mempool *mb_pool) { struct virtqueue *vq; vq = dev->data->rx_queues[rx_queue_id] = virtio_queue_setup(dev, VTNET_RQ); vq->mpool = mb_pool; return 0; } static int eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused, unsigned int socket_id __rte_unused, const struct rte_eth_txconf *tx_conf __rte_unused) { dev->data->tx_queues[tx_queue_id] = virtio_queue_setup(dev, VTNET_TQ); return 0; } static const struct eth_dev_ops ops = { .dev_start = eth_dev_start, .dev_stop = eth_dev_stop, .dev_close = eth_dev_close, .dev_configure = eth_dev_configure, .dev_infos_get = eth_dev_info, .rx_queue_setup = eth_rx_queue_setup, .tx_queue_setup = eth_tx_queue_setup, .rx_queue_release = eth_queue_release, .tx_queue_release = eth_queue_release, .link_update = eth_link_update, .stats_get = eth_stats_get, .stats_reset = eth_stats_reset, }; static int rte_eth_xenvirt_parse_args(struct xenvirt_dict *dict, const char *name, const char *params) { int i; char *pairs[RTE_ETH_XENVIRT_MAX_ARGS]; int num_of_pairs; char *pair[2]; char *args; int ret = -1; if (params == NULL) return 0; args = rte_zmalloc(NULL, strlen(params) + 1, RTE_CACHE_LINE_SIZE); if (args == NULL) { RTE_LOG(ERR, PMD, "Couldn't parse %s device \n", name); return -1; } rte_memcpy(args, params, strlen(params)); num_of_pairs = rte_strsplit(args, strnlen(args, MAX_ARG_STRLEN), pairs, RTE_ETH_XENVIRT_MAX_ARGS , RTE_ETH_XENVIRT_PAIRS_DELIM); for (i = 0; i < num_of_pairs; i++) { pair[0] = NULL; pair[1] = NULL; rte_strsplit(pairs[i], strnlen(pairs[i], MAX_ARG_STRLEN), pair, 2, RTE_ETH_XENVIRT_KEY_VALUE_DELIM); if (pair[0] == NULL || pair[1] == NULL || pair[0][0] == 0 || pair[1][0] == 0) { RTE_LOG(ERR, PMD, "Couldn't parse %s device," "wrong key or value \n", name); goto err; } if (!strncmp(pair[0], RTE_ETH_XENVIRT_MAC_PARAM, sizeof(RTE_ETH_XENVIRT_MAC_PARAM))) { if (cmdline_parse_etheraddr(NULL, pair[1], &dict->addr, sizeof(dict->addr)) < 0) { RTE_LOG(ERR, PMD, "Invalid %s device ether address\n", name); goto err; } dict->addr_valid = 1; } } ret = 0; err: rte_free(args); return ret; } enum dev_action { DEV_CREATE, DEV_ATTACH }; static int eth_dev_xenvirt_create(const char *name, const char *params, const unsigned numa_node, enum dev_action action) { struct rte_eth_dev_data *data = NULL; struct rte_pci_device *pci_dev = NULL; struct pmd_internals *internals = NULL; struct rte_eth_dev *eth_dev = NULL; struct xenvirt_dict dict; bzero(&dict, sizeof(struct xenvirt_dict)); RTE_LOG(INFO, PMD, "Creating virtio rings backed ethdev on numa socket %u\n", numa_node); RTE_SET_USED(action); if (rte_eth_xenvirt_parse_args(&dict, name, params) < 0) { RTE_LOG(ERR, PMD, "%s: Failed to parse ethdev parameters\n", __func__); return -1; } /* now do all data allocation - for eth_dev structure, dummy pci driver * and internal (private) data */ data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node); if (data == NULL) goto err; pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, numa_node); if (pci_dev == NULL) goto err; internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node); if (internals == NULL) goto err; /* reserve an ethdev entry */ eth_dev = rte_eth_dev_allocate(name, RTE_ETH_DEV_VIRTUAL); if (eth_dev == NULL) goto err; pci_dev->numa_node = numa_node; data->dev_private = internals; data->port_id = eth_dev->data->port_id; data->nb_rx_queues = (uint16_t)1; data->nb_tx_queues = (uint16_t)1; data->dev_link = pmd_link; data->mac_addrs = rte_zmalloc("xen_virtio", ETHER_ADDR_LEN, 0); if(dict.addr_valid) memcpy(&data->mac_addrs->addr_bytes, &dict.addr, sizeof(struct ether_addr)); else eth_random_addr(&data->mac_addrs->addr_bytes[0]); eth_dev->data = data; eth_dev->dev_ops = &ops; eth_dev->pci_dev = pci_dev; eth_dev->rx_pkt_burst = eth_xenvirt_rx; eth_dev->tx_pkt_burst = eth_xenvirt_tx; internals->virtio_idx = virtio_idx++; internals->port_id = eth_dev->data->port_id; return 0; err: rte_free(data); rte_free(pci_dev); rte_free(internals); return -1; } /*TODO: Support multiple process model */ static int rte_pmd_xenvirt_devinit(const char *name, const char *params) { if (virtio_idx == 0) { if (xenstore_init() != 0) { RTE_LOG(ERR, PMD, "%s: xenstore init failed\n", __func__); return -1; } if (gntalloc_open() != 0) { RTE_LOG(ERR, PMD, "%s: grant init failed\n", __func__); return -1; } } eth_dev_xenvirt_create(name, params, rte_socket_id(), DEV_CREATE); return 0; } static struct rte_driver pmd_xenvirt_drv = { .name = "eth_xenvirt", .type = PMD_VDEV, .init = rte_pmd_xenvirt_devinit, }; PMD_REGISTER_DRIVER(pmd_xenvirt_drv); ================================================ FILE: drivers/net/xenvirt/rte_eth_xenvirt.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_XENVIRT_H_ #define _RTE_ETH_XENVIRT_H_ #ifdef __cplusplus extern "C" { #endif #include #include /** * Creates mempool for xen virtio PMD. * This function uses memzone_reserve to allocate memory for meta data, * and uses grant alloc driver to allocate memory for data area. * The input parameters are exactly the same as rte_mempool_create. */ struct rte_mempool * rte_mempool_gntalloc_create(const char *name, unsigned elt_num, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); #ifdef __cplusplus } #endif #endif ================================================ FILE: drivers/net/xenvirt/rte_mempool_gntalloc.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "rte_xen_lib.h" #include "rte_eth_xenvirt.h" struct _gntarr { uint32_t gref; phys_addr_t pa; uint64_t index; void *va; }; struct _mempool_gntalloc_info { struct rte_mempool *mp; uint32_t pg_num; uint32_t *gref_arr; phys_addr_t *pa_arr; void *va; uint32_t mempool_idx; uint64_t start_index; }; static rte_atomic32_t global_xenvirt_mempool_idx = RTE_ATOMIC32_INIT(-1); static int compare(const void *p1, const void *p2) { return ((const struct _gntarr *)p1)->pa - ((const struct _gntarr *)p2)->pa; } static struct _mempool_gntalloc_info _create_mempool(const char *name, unsigned elt_num, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags) { struct _mempool_gntalloc_info mgi; struct rte_mempool *mp = NULL; struct rte_mempool_objsz objsz; uint32_t pg_num, rpg_num, pg_shift, pg_sz; char *va, *orig_va, *uv; /* uv: from which, the pages could be freed */ ssize_t sz, usz; /* usz: unused size */ /* * for each page allocated through xen_gntalloc driver, * gref_arr:stores grant references, * pa_arr: stores physical address, * gnt_arr: stores all meta dat */ uint32_t *gref_arr = NULL; phys_addr_t *pa_arr = NULL; struct _gntarr *gnt_arr = NULL; /* start index of the grant referances, used for dealloc*/ uint64_t start_index; uint32_t i, j; int rv = 0; struct ioctl_gntalloc_dealloc_gref arg; mgi.mp = NULL; va = orig_va = uv = NULL; pg_num = rpg_num = 0; sz = 0; pg_sz = getpagesize(); if (rte_is_power_of_2(pg_sz) == 0) { goto out; } pg_shift = rte_bsf32(pg_sz); rte_mempool_calc_obj_size(elt_size, flags, &objsz); sz = rte_mempool_xmem_size(elt_num, objsz.total_size, pg_shift); pg_num = sz >> pg_shift; pa_arr = calloc(pg_num, sizeof(pa_arr[0])); gref_arr = calloc(pg_num, sizeof(gref_arr[0])); gnt_arr = calloc(pg_num, sizeof(gnt_arr[0])); if ((gnt_arr == NULL) || (gref_arr == NULL) || (pa_arr == NULL)) goto out; /* grant index is continuous in ascending order */ orig_va = gntalloc(sz, gref_arr, &start_index); if (orig_va == NULL) goto out; get_phys_map(orig_va, pa_arr, pg_num, pg_sz); for (i = 0; i < pg_num; i++) { gnt_arr[i].index = start_index + i * pg_sz; gnt_arr[i].gref = gref_arr[i]; gnt_arr[i].pa = pa_arr[i]; gnt_arr[i].va = RTE_PTR_ADD(orig_va, i * pg_sz); } qsort(gnt_arr, pg_num, sizeof(struct _gntarr), compare); va = get_xen_virtual(sz, pg_sz); if (va == NULL) { goto out; } /* * map one by one, as index isn't continuous now. * pg_num VMAs, doesn't linux has a limitation on this? */ for (i = 0; i < pg_num; i++) { /* update gref_arr and pa_arr after sort */ gref_arr[i] = gnt_arr[i].gref; pa_arr[i] = gnt_arr[i].pa; gnt_arr[i].va = mmap(va + i * pg_sz, pg_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, gntalloc_fd, gnt_arr[i].index); if ((gnt_arr[i].va == MAP_FAILED) || (gnt_arr[i].va != (va + i * pg_sz))) { RTE_LOG(ERR, PMD, "failed to map %d pages\n", i); goto mmap_failed; } } /* * Check that allocated size is big enough to hold elt_num * objects and a calcualte how many bytes are actually required. */ usz = rte_mempool_xmem_usage(va, elt_num, objsz.total_size, pa_arr, pg_num, pg_shift); if (usz < 0) { mp = NULL; i = pg_num; goto mmap_failed; } else { /* unmap unused pages if any */ uv = RTE_PTR_ADD(va, usz); if ((usz = va + sz - uv) > 0) { RTE_LOG(ERR, PMD, "%s(%s): unmap unused %zu of %zu " "mmaped bytes @%p orig:%p\n", __func__, name, usz, sz, uv, va); munmap(uv, usz); i = (sz - usz) / pg_sz; for (; i < pg_num; i++) { arg.count = 1; arg.index = gnt_arr[i].index; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, &arg); if (rv) { /* shouldn't fail here */ RTE_LOG(ERR, PMD, "va=%p pa=%p index=%p %s\n", gnt_arr[i].va, (void *)gnt_arr[i].pa, (void *)arg.index, strerror(errno)); rte_panic("gntdealloc failed when freeing pages\n"); } } rpg_num = (sz - usz) >> pg_shift; } else rpg_num = pg_num; mp = rte_mempool_xmem_create(name, elt_num, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags, va, pa_arr, rpg_num, pg_shift); RTE_VERIFY(elt_num == mp->size); } mgi.mp = mp; mgi.pg_num = rpg_num; mgi.gref_arr = gref_arr; mgi.pa_arr = pa_arr; if (mp) mgi.mempool_idx = rte_atomic32_add_return(&global_xenvirt_mempool_idx, 1); mgi.start_index = start_index; mgi.va = va; if (mp == NULL) { i = pg_num; goto mmap_failed; } /* * unmap only, without deallocate grant reference. * unused pages have already been unmaped, * unmap twice will fail, but it is safe. */ mmap_failed: for (j = 0; j < i; j++) { if (gnt_arr[i].va) munmap(gnt_arr[i].va, pg_sz); } out: if (gnt_arr) free(gnt_arr); if (orig_va) munmap(orig_va, sz); if (mp == NULL) { if (gref_arr) free(gref_arr); if (pa_arr) free(pa_arr); /* some gref has already been de-allocated from the list in the driver, * so dealloc one by one, and it is safe to deallocate twice */ if (orig_va) { for (i = 0; i < pg_num; i++) { arg.index = start_index + i * pg_sz; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, arg); } } } return mgi; } struct rte_mempool * rte_mempool_gntalloc_create(const char *name, unsigned elt_num, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags) { int rv; uint32_t i; struct _mempool_gntalloc_info mgi; struct ioctl_gntalloc_dealloc_gref arg; int pg_sz = getpagesize(); mgi = _create_mempool(name, elt_num, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags); if (mgi.mp) { rv = grant_gntalloc_mbuf_pool(mgi.mp, mgi.pg_num, mgi.gref_arr, mgi.pa_arr, mgi.mempool_idx); free(mgi.gref_arr); free(mgi.pa_arr); if (rv == 0) return mgi.mp; /* * in _create_mempool, unused pages have already been unmapped, deallocagted * unmap and dealloc the remained ones here. */ munmap(mgi.va, pg_sz * mgi.pg_num); for (i = 0; i < mgi.pg_num; i++) { arg.index = mgi.start_index + i * pg_sz; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, arg); } return NULL; } return NULL; } ================================================ FILE: drivers/net/xenvirt/rte_xen_lib.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040200 #include #else #include #endif #include #include #include #include "rte_xen_lib.h" /* * The grant node format in xenstore for vring/mpool is: * 0_rx_vring_gref = "gref1#, gref2#, gref3#" * 0_mempool_gref = "gref1#, gref2#, gref3#" * each gref# is a grant reference for a shared page. * In each shared page, we store the grant_node_item items. */ struct grant_node_item { uint32_t gref; uint32_t pfn; } __attribute__((packed)); /* fd for xen_gntalloc driver, used to allocate grant pages*/ int gntalloc_fd = -1; /* xenstore path for local domain, now it is '/local/domain/domid/' */ static char *dompath = NULL; /* handle to xenstore read/write operations */ static struct xs_handle *xs = NULL; /* * Reserve a virtual address space. * On success, returns the pointer. On failure, returns NULL. */ void * get_xen_virtual(size_t size, size_t page_sz) { void *addr; uintptr_t aligned_addr; addr = mmap(NULL, size + page_sz, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { RTE_LOG(ERR, PMD, "failed get a virtual area\n"); return NULL; } aligned_addr = RTE_ALIGN_CEIL((uintptr_t)addr, page_sz); addr = (void *)(aligned_addr); return addr; } /* * Get the physical address for virtual memory starting at va. */ int get_phys_map(void *va, phys_addr_t pa[], uint32_t pg_num, uint32_t pg_sz) { int32_t fd, rc = 0; uint32_t i, nb; off_t ofs; ofs = (uintptr_t)va / pg_sz * sizeof(*pa); nb = pg_num * sizeof(*pa); if ((fd = open(PAGEMAP_FNAME, O_RDONLY)) < 0 || (rc = pread(fd, pa, nb, ofs)) < 0 || (rc -= nb) != 0) { RTE_LOG(ERR, PMD, "%s: failed read of %u bytes from \'%s\' " "at offset %zu, error code: %d\n", __func__, nb, PAGEMAP_FNAME, ofs, errno); rc = ENOENT; } close(fd); for (i = 0; i != pg_num; i++) pa[i] = (pa[i] & PAGEMAP_PFN_MASK) * pg_sz; return rc; } int gntalloc_open(void) { gntalloc_fd = open(XEN_GNTALLOC_FNAME, O_RDWR); return (gntalloc_fd != -1) ? 0 : -1; } void gntalloc_close(void) { if (gntalloc_fd != -1) close(gntalloc_fd); gntalloc_fd = -1; } void * gntalloc(size_t size, uint32_t *gref, uint64_t *start_index) { int page_size = getpagesize(); uint32_t i, pg_num; void *va; int rv; struct ioctl_gntalloc_alloc_gref *arg; struct ioctl_gntalloc_dealloc_gref arg_d; if (size % page_size) { RTE_LOG(ERR, PMD, "%s: %zu isn't multiple of page size\n", __func__, size); return NULL; } pg_num = size / page_size; arg = malloc(sizeof(*arg) + (pg_num - 1) * sizeof(uint32_t)); if (arg == NULL) return NULL; arg->domid = DOM0_DOMID; arg->flags = GNTALLOC_FLAG_WRITABLE; arg->count = pg_num; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_ALLOC_GREF, arg); if (rv) { RTE_LOG(ERR, PMD, "%s: ioctl error\n", __func__); free(arg); return NULL; } va = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, gntalloc_fd, arg->index); if (va == MAP_FAILED) { RTE_LOG(ERR, PMD, "%s: mmap failed\n", __func__); arg_d.count = pg_num; arg_d.index = arg->index; ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, arg_d); free(arg); return NULL; } if (gref) { for (i = 0; i < pg_num; i++) { gref[i] = arg->gref_ids[i]; } } if (start_index) *start_index = arg->index; free(arg); return va; } int grefwatch_from_alloc(uint32_t *gref, void **pptr) { int rv; void *ptr; int pg_size = getpagesize(); struct ioctl_gntalloc_alloc_gref arg = { .domid = DOM0_DOMID, .flags = GNTALLOC_FLAG_WRITABLE, .count = 1 }; struct ioctl_gntalloc_dealloc_gref arg_d; struct ioctl_gntalloc_unmap_notify notify = { .action = UNMAP_NOTIFY_CLEAR_BYTE }; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_ALLOC_GREF, &arg); if (rv) { RTE_LOG(ERR, PMD, "%s: ioctl error\n", __func__); return -1; } ptr = (void *)mmap(NULL, pg_size, PROT_READ|PROT_WRITE, MAP_SHARED, gntalloc_fd, arg.index); arg_d.index = arg.index; arg_d.count = 1; if (ptr == MAP_FAILED) { RTE_LOG(ERR, PMD, "%s: mmap failed\n", __func__); ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, &arg_d); return -1; } if (pptr) *pptr = ptr; if (gref) *gref = arg.gref_ids[0]; notify.index = arg.index; rv = ioctl(gntalloc_fd, IOCTL_GNTALLOC_SET_UNMAP_NOTIFY, ¬ify); if (rv) { RTE_LOG(ERR, PMD, "%s: unmap notify failed\n", __func__); munmap(ptr, pg_size); ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, &arg_d); return -1; } return 0; } void gntfree(void *va, size_t sz, uint64_t start_index) { struct ioctl_gntalloc_dealloc_gref arg_d; if (va && sz) { munmap(va, sz); arg_d.count = sz / getpagesize(); arg_d.index = start_index; ioctl(gntalloc_fd, IOCTL_GNTALLOC_DEALLOC_GREF, &arg_d); } } static int xenstore_cleanup(void) { char store_path[PATH_MAX] = {0}; if (snprintf(store_path, sizeof(store_path), "%s%s", dompath, DPDK_XENSTORE_NODE) == -1) return -1; if (xs_rm(xs, XBT_NULL, store_path) == false) { RTE_LOG(ERR, PMD, "%s: failed cleanup node\n", __func__); return -1; } return 0; } int xenstore_init(void) { unsigned int len, domid; char *buf; static int cleanup = 0; char *end; xs = xs_domain_open(); if (xs == NULL) { RTE_LOG(ERR, PMD,"%s: xs_domain_open failed\n", __func__); return -1; } buf = xs_read(xs, XBT_NULL, "domid", &len); if (buf == NULL) { RTE_LOG(ERR, PMD, "%s: failed read domid\n", __func__); return -1; } errno = 0; domid = strtoul(buf, &end, 0); if (errno != 0 || end == NULL || end == buf || domid == 0) return -1; RTE_LOG(INFO, PMD, "retrieved dom ID = %d\n", domid); dompath = xs_get_domain_path(xs, domid); if (dompath == NULL) return -1; xs_transaction_start(xs); /* When to stop transaction */ if (cleanup == 0) { if (xenstore_cleanup()) return -1; cleanup = 1; } return 0; } int xenstore_write(const char *key_str, const char *val_str) { char grant_path[PATH_MAX]; int rv, len; if (xs == NULL) { RTE_LOG(ERR, PMD, "%s: xenstore init failed\n", __func__); return -1; } rv = snprintf(grant_path, sizeof(grant_path), "%s%s", dompath, key_str); if (rv == -1) { RTE_LOG(ERR, PMD, "%s: snprintf %s %s failed\n", __func__, dompath, key_str); return -1; } len = strnlen(val_str, PATH_MAX); if (xs_write(xs, XBT_NULL, grant_path, val_str, len) == false) { RTE_LOG(ERR, PMD, "%s: xs_write failed\n", __func__); return -1; } return 0; } int grant_node_create(uint32_t pg_num, uint32_t *gref_arr, phys_addr_t *pa_arr, char *val_str, size_t str_size) { uint64_t start_index; int pg_size; uint32_t pg_shift; void *ptr = NULL; uint32_t count, entries_per_pg; uint32_t i, j = 0, k = 0;; uint32_t *gref_tmp; int first = 1; char tmp_str[PATH_MAX] = {0}; int rv = -1; pg_size = getpagesize(); if (rte_is_power_of_2(pg_size) == 0) { return -1; } pg_shift = rte_bsf32(pg_size); if (pg_size % sizeof(struct grant_node_item)) { RTE_LOG(ERR, PMD, "pg_size isn't a multiple of grant node item\n"); return -1; } entries_per_pg = pg_size / sizeof(struct grant_node_item); count = (pg_num + entries_per_pg - 1 ) / entries_per_pg; gref_tmp = malloc(count * sizeof(uint32_t)); if (gref_tmp == NULL) return -1; ptr = gntalloc(pg_size * count, gref_tmp, &start_index); if (ptr == NULL) { RTE_LOG(ERR, PMD, "%s: gntalloc error of %d pages\n", __func__, count); free(gref_tmp); return -1; } while (j < pg_num) { if (first) { rv = snprintf(val_str, str_size, "%u", gref_tmp[k]); first = 0; } else { snprintf(tmp_str, PATH_MAX, "%s", val_str); rv = snprintf(val_str, str_size, "%s,%u", tmp_str, gref_tmp[k]); } k++; if (rv == -1) break; for (i = 0; i < entries_per_pg && j < pg_num ; i++) { ((struct grant_node_item *)ptr)->gref = gref_arr[j]; ((struct grant_node_item *)ptr)->pfn = pa_arr[j] >> pg_shift; ptr = RTE_PTR_ADD(ptr, sizeof(struct grant_node_item)); j++; } } if (rv == -1) { gntfree(ptr, pg_size * count, start_index); } else rv = 0; free(gref_tmp); return rv; } int grant_gntalloc_mbuf_pool(struct rte_mempool *mpool, uint32_t pg_num, uint32_t *gref_arr, phys_addr_t *pa_arr, int mempool_idx) { char key_str[PATH_MAX] = {0}; char val_str[PATH_MAX] = {0}; if (grant_node_create(pg_num, gref_arr, pa_arr, val_str, sizeof(val_str))) { return -1; } if (snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"MEMPOOL_XENSTORE_STR, mempool_idx) == -1) return -1; if (xenstore_write(key_str, val_str) == -1) return -1; if (snprintf(key_str, sizeof(key_str), DPDK_XENSTORE_PATH"%d"MEMPOOL_VA_XENSTORE_STR, mempool_idx) == -1) return -1; if (snprintf(val_str, sizeof(val_str), "%"PRIxPTR, (uintptr_t)mpool->elt_va_start) == -1) return -1; if (xenstore_write(key_str, val_str) == -1) return -1; return 0; } ================================================ FILE: drivers/net/xenvirt/rte_xen_lib.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_XEN_DUMMY_PMD_H #define _RTE_XEN_DUMMY_PMD_H #include #include #include #include #define PAGEMAP_FNAME "/proc/self/pagemap" #define XEN_GNTALLOC_FNAME "/dev/xen/gntalloc" #define DPDK_XENSTORE_PATH "/control/dpdk/" #define DPDK_XENSTORE_NODE "/control/dpdk" /*format 0_mempool_gref = "1537,1524,1533" */ #define MEMPOOL_XENSTORE_STR "_mempool_gref" /*format 0_mempool_va = 0x80340000 */ #define MEMPOOL_VA_XENSTORE_STR "_mempool_va" /*format 0_rx_vring_gref = "1537,1524,1533" */ #define RXVRING_XENSTORE_STR "_rx_vring_gref" /*format 0_tx_vring_gref = "1537,1524,1533" */ #define TXVRING_XENSTORE_STR "_tx_vring_gref" #define VRING_FLAG_STR "_vring_flag" /*format: event_type_start_0 = 1*/ #define EVENT_TYPE_START_STR "event_type_start_" #define DOM0_DOMID 0 /* * the pfn (page frame number) are bits 0-54 (see pagemap.txt in linux * Documentation). */ #define PAGEMAP_PFN_BITS 54 #define PAGEMAP_PFN_MASK RTE_LEN2MASK(PAGEMAP_PFN_BITS, phys_addr_t) #define MAP_FLAG 0xA5 #define RTE_ETH_XENVIRT_PAIRS_DELIM ';' #define RTE_ETH_XENVIRT_KEY_VALUE_DELIM '=' #define RTE_ETH_XENVIRT_MAX_ARGS 1 #define RTE_ETH_XENVIRT_MAC_PARAM "mac" struct xenvirt_dict { uint8_t addr_valid; struct ether_addr addr; }; extern int gntalloc_fd; int gntalloc_open(void); void gntalloc_close(void); void * gntalloc(size_t sz, uint32_t *gref, uint64_t *start_index); void gntfree(void *va, size_t sz, uint64_t start_index); int xenstore_init(void); int xenstore_write(const char *key_str, const char *val_str); int get_phys_map(void *va, phys_addr_t pa[], uint32_t pg_num, uint32_t pg_sz); void * get_xen_virtual(size_t size, size_t page_sz); int grefwatch_from_alloc(uint32_t *gref, void **pptr); int grant_node_create(uint32_t pg_num, uint32_t *gref_arr, phys_addr_t *pa_arr, char *val_str, size_t str_size); int grant_gntalloc_mbuf_pool(struct rte_mempool *mpool, uint32_t pg_num, uint32_t *gref_arr, phys_addr_t *pa_arr, int mempool_idx); #endif ================================================ FILE: drivers/net/xenvirt/virtio_logs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_LOGS_H_ #define _VIRTIO_LOGS_H_ #include #ifdef RTE_LIBRTE_VIRTIO_DEBUG_INIT #define PMD_INIT_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") #else #define PMD_INIT_LOG(level, fmt, args...) do { } while(0) #define PMD_INIT_FUNC_TRACE() do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_RX #define PMD_RX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s() rx: " fmt , __func__, ## args) #else #define PMD_RX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_TX #define PMD_TX_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s() tx: " fmt , __func__, ## args) #else #define PMD_TX_LOG(level, fmt, args...) do { } while(0) #endif #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DRIVER #define PMD_DRV_LOG(level, fmt, args...) \ RTE_LOG(level, PMD, "%s(): " fmt , __func__, ## args) #else #define PMD_DRV_LOG(level, fmt, args...) do { } while(0) #endif #endif /* _VIRTIO_LOGS_H_ */ ================================================ FILE: drivers/net/xenvirt/virtqueue.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTQUEUE_H_ #define _VIRTQUEUE_H_ #include #include #include #include #include #include #include #include "virtio_logs.h" struct rte_mbuf; /* The alignment to use between consumer and producer parts of vring. */ #define VIRTIO_PCI_VRING_ALIGN 4096 /* * Address translatio is between gva<->hva, * rather than gpa<->hva in virito spec. */ #define RTE_MBUF_DATA_DMA_ADDR(mb) \ rte_pktmbuf_mtod(mb, uint64_t) enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 }; /** * The maximum virtqueue size is 2^15. Use that value as the end of * descriptor chain terminator since it will never be a valid index * in the descriptor table. This is used to verify we are correctly * handling vq_free_cnt. */ #define VQ_RING_DESC_CHAIN_END 32768 #define VIRTQUEUE_MAX_NAME_SZ 32 struct pmd_internals { struct rte_eth_stats eth_stats; int port_id; int virtio_idx; }; struct virtqueue { char vq_name[VIRTQUEUE_MAX_NAME_SZ]; struct rte_mempool *mpool; /**< mempool for mbuf allocation */ uint16_t queue_id; /**< DPDK queue index. */ uint16_t vq_queue_index; /**< PCI queue index */ uint8_t port_id; /**< Device port identifier. */ void *vq_ring_virt_mem; /**< virtual address of vring*/ int vq_alignment; int vq_ring_size; struct vring vq_ring; /**< vring keeping desc, used and avail */ struct pmd_internals *internals; /**< virtio device internal info. */ uint16_t vq_nentries; /**< vring desc numbers */ uint16_t vq_desc_head_idx; uint16_t vq_free_cnt; /**< num of desc available */ uint16_t vq_used_cons_idx; /**< Last consumed desc in used table, trails vq_ring.used->idx*/ struct vq_desc_extra { void *cookie; uint16_t ndescs; } vq_descx[0] __rte_cache_aligned; }; #ifdef RTE_LIBRTE_XENVIRT_DEBUG_DUMP #define VIRTQUEUE_DUMP(vq) do { \ uint16_t used_idx, nused; \ used_idx = (vq)->vq_ring.used->idx; \ nused = (uint16_t)(used_idx - (vq)->vq_used_cons_idx); \ PMD_INIT_LOG(DEBUG, \ "VQ: %s - size=%d; free=%d; used=%d; desc_head_idx=%d;" \ " avail.idx=%d; used_cons_idx=%d; used.idx=%d;" \ " avail.flags=0x%x; used.flags=0x%x\n", \ (vq)->vq_name, (vq)->vq_nentries, (vq)->vq_free_cnt, nused, \ (vq)->vq_desc_head_idx, (vq)->vq_ring.avail->idx, \ (vq)->vq_used_cons_idx, (vq)->vq_ring.used->idx, \ (vq)->vq_ring.avail->flags, (vq)->vq_ring.used->flags); \ } while (0) #else #define VIRTQUEUE_DUMP(vq) do { } while (0) #endif /** * Dump virtqueue internal structures, for debug purpose only. */ void virtqueue_dump(struct virtqueue *vq); /** * Get all mbufs to be freed. */ struct rte_mbuf * virtqueue_detatch_unused(struct virtqueue *vq); static inline int __attribute__((always_inline)) virtqueue_full(const struct virtqueue *vq) { return (vq->vq_free_cnt == 0); } #define VIRTQUEUE_NUSED(vq) ((uint16_t)((vq)->vq_ring.used->idx - (vq)->vq_used_cons_idx)) static inline void __attribute__((always_inline)) vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) { uint16_t avail_idx; /* * Place the head of the descriptor chain into the next slot and make * it usable to the host. The chain is made available now rather than * deferring to virtqueue_notify() in the hopes that if the host is * currently running on another CPU, we can keep it processing the new * descriptor. */ avail_idx = (uint16_t)(vq->vq_ring.avail->idx & (vq->vq_nentries - 1)); vq->vq_ring.avail->ring[avail_idx] = desc_idx; rte_compiler_barrier(); /* wmb , for IA memory model barrier is enough*/ vq->vq_ring.avail->idx++; } static inline void __attribute__((always_inline)) vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) { struct vring_desc *dp; struct vq_desc_extra *dxp; dp = &vq->vq_ring.desc[desc_idx]; dxp = &vq->vq_descx[desc_idx]; vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt + dxp->ndescs); while (dp->flags & VRING_DESC_F_NEXT) { dp = &vq->vq_ring.desc[dp->next]; } dxp->ndescs = 0; /* * We must append the existing free chain, if any, to the end of * newly freed chain. If the virtqueue was completely used, then * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above). */ dp->next = vq->vq_desc_head_idx; vq->vq_desc_head_idx = desc_idx; } static inline int __attribute__((always_inline)) virtqueue_enqueue_recv_refill(struct virtqueue *rxvq, struct rte_mbuf *cookie) { const uint16_t needed = 1; const uint16_t head_idx = rxvq->vq_desc_head_idx; struct vring_desc *start_dp = rxvq->vq_ring.desc; struct vq_desc_extra *dxp; if (unlikely(rxvq->vq_free_cnt == 0)) return -ENOSPC; if (unlikely(rxvq->vq_free_cnt < needed)) return -EMSGSIZE; if (unlikely(head_idx >= rxvq->vq_nentries)) return -EFAULT; dxp = &rxvq->vq_descx[head_idx]; dxp->cookie = (void *)cookie; dxp->ndescs = needed; start_dp[head_idx].addr = (uint64_t) ((uint64_t)cookie->buf_addr + RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr)); start_dp[head_idx].len = cookie->buf_len - RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr); start_dp[head_idx].flags = VRING_DESC_F_WRITE; rxvq->vq_desc_head_idx = start_dp[head_idx].next; rxvq->vq_free_cnt = (uint16_t)(rxvq->vq_free_cnt - needed); vq_ring_update_avail(rxvq, head_idx); return 0; } static inline int __attribute__((always_inline)) virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie) { const uint16_t needed = 2; struct vring_desc *start_dp = txvq->vq_ring.desc; uint16_t head_idx = txvq->vq_desc_head_idx; uint16_t idx = head_idx; struct vq_desc_extra *dxp; if (unlikely(txvq->vq_free_cnt == 0)) return -ENOSPC; if (unlikely(txvq->vq_free_cnt < needed)) return -EMSGSIZE; if (unlikely(head_idx >= txvq->vq_nentries)) return -EFAULT; dxp = &txvq->vq_descx[idx]; dxp->cookie = (void *)cookie; dxp->ndescs = needed; start_dp = txvq->vq_ring.desc; start_dp[idx].addr = 0; /* * TODO: save one desc here? */ start_dp[idx].len = sizeof(struct virtio_net_hdr); start_dp[idx].flags = VRING_DESC_F_NEXT; start_dp[idx].addr = (uintptr_t)NULL; idx = start_dp[idx].next; start_dp[idx].addr = RTE_MBUF_DATA_DMA_ADDR(cookie); start_dp[idx].len = cookie->data_len; start_dp[idx].flags = 0; idx = start_dp[idx].next; txvq->vq_desc_head_idx = idx; txvq->vq_free_cnt = (uint16_t)(txvq->vq_free_cnt - needed); vq_ring_update_avail(txvq, head_idx); return 0; } static inline uint16_t __attribute__((always_inline)) virtqueue_dequeue_burst(struct virtqueue *vq, struct rte_mbuf **rx_pkts, uint32_t *len, uint16_t num) { struct vring_used_elem *uep; struct rte_mbuf *cookie; uint16_t used_idx, desc_idx; uint16_t i; /* Caller does the check */ for (i = 0; i < num ; i ++) { used_idx = (uint16_t)(vq->vq_used_cons_idx & (vq->vq_nentries - 1)); uep = &vq->vq_ring.used->ring[used_idx]; desc_idx = (uint16_t) uep->id; cookie = (struct rte_mbuf *)vq->vq_descx[desc_idx].cookie; if (unlikely(cookie == NULL)) { PMD_DRV_LOG(ERR, "vring descriptor with no mbuf cookie at %u\n", vq->vq_used_cons_idx); RTE_LOG(ERR, PMD, "%s: inconsistent (%u, %u)\n", __func__, used_idx , desc_idx); break; } len[i] = uep->len; rx_pkts[i] = cookie; vq->vq_used_cons_idx++; vq_ring_free_chain(vq, desc_idx); vq->vq_descx[desc_idx].cookie = NULL; } return i; } #endif /* _VIRTQUEUE_H_ */ ================================================ FILE: examples/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2014 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += bond DIRS-y += cmdline DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += distributor ifneq ($(ICP_ROOT),) DIRS-y += dpdk_qat endif DIRS-y += exception_path DIRS-y += helloworld DIRS-y += ip_pipeline DIRS-y += ip_reassembly DIRS-$(CONFIG_RTE_IP_FRAG) += ip_fragmentation DIRS-y += ipv4_multicast DIRS-$(CONFIG_RTE_LIBRTE_KNI) += kni DIRS-y += l2fwd DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += l2fwd-ivshmem DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += l2fwd-jobstats DIRS-y += l3fwd DIRS-$(CONFIG_RTE_LIBRTE_ACL) += l3fwd-acl DIRS-$(CONFIG_RTE_LIBRTE_POWER) += l3fwd-power DIRS-y += l3fwd-vf DIRS-y += link_status_interrupt DIRS-y += load_balancer DIRS-y += multi_process DIRS-y += netmap_compat/bridge DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += packet_ordering DIRS-$(CONFIG_RTE_LIBRTE_METER) += qos_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += qos_sched DIRS-y += quota_watermark DIRS-$(CONFIG_RTE_ETHDEV_RXTX_CALLBACKS) += rxtx_callbacks DIRS-y += skeleton DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += tep_termination DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += timer DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost DIRS-$(CONFIG_RTE_LIBRTE_XEN_DOM0) += vhost_xen DIRS-y += vmdq DIRS-y += vmdq_dcb DIRS-$(CONFIG_RTE_LIBRTE_POWER) += vm_power_manager include $(RTE_SDK)/mk/rte.extsubdir.mk ================================================ FILE: examples/bond/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = bond_app # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif CFLAGS += -O3 include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/bond/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include #include "rte_byteorder.h" #include "rte_cpuflags.h" #include "rte_eth_bond.h" #define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1 #define NB_MBUF (1024*8) #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define BURST_RX_INTERVAL_NS (10) /* RX poll interval ~100ns */ /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ #define RX_FTHRESH (MAX_PKT_BURST * 2)/**< Default values of RX free threshold reg. */ /* * These default values are optimized for use with the Intel(R) 82599 10 GbE * Controller and the DPDK ixgbe PMD. Consider using other values for other * network controllers and/or network drivers. */ #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ /* * Configurable number of RX/TX ring descriptors */ #define RTE_RX_DESC_DEFAULT 128 #define RTE_TX_DESC_DEFAULT 512 #define BOND_IP_1 7 #define BOND_IP_2 0 #define BOND_IP_3 0 #define BOND_IP_4 10 /* not defined under linux */ #ifndef NIPQUAD #define NIPQUAD_FMT "%u.%u.%u.%u" #endif #define MAX_PORTS 4 #define PRINT_MAC(addr) printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \ ":%02"PRIx8":%02"PRIx8":%02"PRIx8, \ addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], \ addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]) uint8_t slaves[RTE_MAX_ETHPORTS]; uint8_t slaves_count; static uint8_t BOND_PORT = 0xff; static struct rte_mempool *mbuf_pool; static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static void slave_port_init(uint8_t portid, struct rte_mempool *mbuf_pool) { int retval; if (portid >= rte_eth_dev_count()) rte_exit(EXIT_FAILURE, "Invalid port\n"); retval = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (retval != 0) rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n", portid, retval); /* RX setup */ retval = rte_eth_rx_queue_setup(portid, 0, RTE_RX_DESC_DEFAULT, rte_eth_dev_socket_id(portid), NULL, mbuf_pool); if (retval < 0) rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)", portid, retval); /* TX setup */ retval = rte_eth_tx_queue_setup(portid, 0, RTE_TX_DESC_DEFAULT, rte_eth_dev_socket_id(portid), NULL); if (retval < 0) rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)", portid, retval); retval = rte_eth_dev_start(portid); if (retval < 0) rte_exit(retval, "Start port %d failed (res=%d)", portid, retval); struct ether_addr addr; rte_eth_macaddr_get(portid, &addr); printf("Port %u MAC: ", (unsigned)portid); PRINT_MAC(addr); printf("\n"); } static void bond_port_init(struct rte_mempool *mbuf_pool) { int retval; uint8_t i; retval = rte_eth_bond_create("bond0", BONDING_MODE_ALB, 0 /*SOCKET_ID_ANY*/); if (retval < 0) rte_exit(EXIT_FAILURE, "Faled to create bond port\n"); BOND_PORT = (uint8_t)retval; retval = rte_eth_dev_configure(BOND_PORT, 1, 1, &port_conf); if (retval != 0) rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n", BOND_PORT, retval); /* RX setup */ retval = rte_eth_rx_queue_setup(BOND_PORT, 0, RTE_RX_DESC_DEFAULT, rte_eth_dev_socket_id(BOND_PORT), NULL, mbuf_pool); if (retval < 0) rte_exit(retval, " port %u: RX queue 0 setup failed (res=%d)", BOND_PORT, retval); /* TX setup */ retval = rte_eth_tx_queue_setup(BOND_PORT, 0, RTE_TX_DESC_DEFAULT, rte_eth_dev_socket_id(BOND_PORT), NULL); if (retval < 0) rte_exit(retval, "port %u: TX queue 0 setup failed (res=%d)", BOND_PORT, retval); for (i = 0; i < slaves_count; i++) { if (rte_eth_bond_slave_add(BOND_PORT, slaves[i]) == -1) rte_exit(-1, "Oooops! adding slave (%u) to bond (%u) failed!\n", slaves[i], BOND_PORT); } retval = rte_eth_dev_start(BOND_PORT); if (retval < 0) rte_exit(retval, "Start port %d failed (res=%d)", BOND_PORT, retval); rte_eth_promiscuous_enable(BOND_PORT); struct ether_addr addr; rte_eth_macaddr_get(BOND_PORT, &addr); printf("Port %u MAC: ", (unsigned)BOND_PORT); PRINT_MAC(addr); printf("\n"); } static inline size_t get_vlan_offset(struct ether_hdr *eth_hdr, uint16_t *proto) { size_t vlan_offset = 0; if (rte_cpu_to_be_16(ETHER_TYPE_VLAN) == *proto) { struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); vlan_offset = sizeof(struct vlan_hdr); *proto = vlan_hdr->eth_proto; if (rte_cpu_to_be_16(ETHER_TYPE_VLAN) == *proto) { vlan_hdr = vlan_hdr + 1; *proto = vlan_hdr->eth_proto; vlan_offset += sizeof(struct vlan_hdr); } } return vlan_offset; } struct global_flag_stru_t { int LcoreMainIsRunning; int LcoreMainCore; uint32_t port_packets[4]; rte_spinlock_t lock; }; struct global_flag_stru_t global_flag_stru; struct global_flag_stru_t *global_flag_stru_p = &global_flag_stru; /* * Main thread that does the work, reading from INPUT_PORT * and writing to OUTPUT_PORT */ static int lcore_main(__attribute__((unused)) void *arg1) { struct rte_mbuf *pkts[MAX_PKT_BURST] __rte_cache_aligned; struct ether_addr d_addr; struct ether_hdr *eth_hdr; struct arp_hdr *arp_hdr; struct ipv4_hdr *ipv4_hdr; uint16_t ether_type, offset; uint16_t rx_cnt; uint32_t bond_ip; int i = 0; uint8_t is_free; bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) | (BOND_IP_3 << 16) | (BOND_IP_4 << 24); rte_spinlock_trylock(&global_flag_stru_p->lock); while (global_flag_stru_p->LcoreMainIsRunning) { rte_spinlock_unlock(&global_flag_stru_p->lock); rx_cnt = rte_eth_rx_burst(BOND_PORT, 0, pkts, MAX_PKT_BURST); is_free = 0; /* If didn't receive any packets, wait and go to next iteration */ if (rx_cnt == 0) { rte_delay_us(50); continue; } /* Search incoming data for ARP packets and prepare response */ for (i = 0; i < rx_cnt; i++) { if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1) { global_flag_stru_p->port_packets[0]++; rte_spinlock_unlock(&global_flag_stru_p->lock); } eth_hdr = rte_pktmbuf_mtod(pkts[i], struct ether_hdr *); ether_type = eth_hdr->ether_type; if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) printf("VLAN taged frame, offset:"); offset = get_vlan_offset(eth_hdr, ðer_type); if (offset > 0) printf("%d\n", offset); if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) { if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1) { global_flag_stru_p->port_packets[1]++; rte_spinlock_unlock(&global_flag_stru_p->lock); } arp_hdr = (struct arp_hdr *)((char *)(eth_hdr + 1) + offset); if (arp_hdr->arp_data.arp_tip == bond_ip) { if (arp_hdr->arp_op == rte_cpu_to_be_16(ARP_OP_REQUEST)) { arp_hdr->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); /* Switch src and dst data and set bonding MAC */ ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); rte_eth_macaddr_get(BOND_PORT, ð_hdr->s_addr); ether_addr_copy(&arp_hdr->arp_data.arp_sha, &arp_hdr->arp_data.arp_tha); arp_hdr->arp_data.arp_tip = arp_hdr->arp_data.arp_sip; rte_eth_macaddr_get(BOND_PORT, &d_addr); ether_addr_copy(&d_addr, &arp_hdr->arp_data.arp_sha); arp_hdr->arp_data.arp_sip = bond_ip; rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1); is_free = 1; } else { rte_eth_tx_burst(BOND_PORT, 0, NULL, 0); } } } else if (ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { if (rte_spinlock_trylock(&global_flag_stru_p->lock) == 1) { global_flag_stru_p->port_packets[2]++; rte_spinlock_unlock(&global_flag_stru_p->lock); } ipv4_hdr = (struct ipv4_hdr *)((char *)(eth_hdr + 1) + offset); if (ipv4_hdr->dst_addr == bond_ip) { ether_addr_copy(ð_hdr->s_addr, ð_hdr->d_addr); rte_eth_macaddr_get(BOND_PORT, ð_hdr->s_addr); ipv4_hdr->dst_addr = ipv4_hdr->src_addr; ipv4_hdr->src_addr = bond_ip; rte_eth_tx_burst(BOND_PORT, 0, &pkts[i], 1); } } /* Free processed packets */ if (is_free == 0) rte_pktmbuf_free(pkts[i]); } rte_spinlock_trylock(&global_flag_stru_p->lock); } rte_spinlock_unlock(&global_flag_stru_p->lock); printf("BYE lcore_main\n"); return 0; } struct cmd_obj_send_result { cmdline_fixed_string_t action; cmdline_ipaddr_t ip; }; static inline void get_string(struct cmd_obj_send_result *res, char *buf, uint8_t size) { snprintf(buf, size, NIPQUAD_FMT, ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[0]), ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[1]), ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[2]), ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[3]) ); } static void cmd_obj_send_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_obj_send_result *res = parsed_result; char ip_str[INET6_ADDRSTRLEN]; struct rte_mbuf *created_pkt; struct ether_hdr *eth_hdr; struct arp_hdr *arp_hdr; uint32_t bond_ip; size_t pkt_size; if (res->ip.family == AF_INET) get_string(res, ip_str, INET_ADDRSTRLEN); else cmdline_printf(cl, "Wrong IP format. Only IPv4 is supported\n"); bond_ip = BOND_IP_1 | (BOND_IP_2 << 8) | (BOND_IP_3 << 16) | (BOND_IP_4 << 24); created_pkt = rte_pktmbuf_alloc(mbuf_pool); pkt_size = sizeof(struct ether_hdr) + sizeof(struct arp_hdr); created_pkt->data_len = pkt_size; created_pkt->pkt_len = pkt_size; eth_hdr = rte_pktmbuf_mtod(created_pkt, struct ether_hdr *); rte_eth_macaddr_get(BOND_PORT, ð_hdr->s_addr); memset(ð_hdr->d_addr, 0xFF, ETHER_ADDR_LEN); eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_ARP); arp_hdr = (struct arp_hdr *)((char *)eth_hdr + sizeof(struct ether_hdr)); arp_hdr->arp_hrd = rte_cpu_to_be_16(ARP_HRD_ETHER); arp_hdr->arp_pro = rte_cpu_to_be_16(ETHER_TYPE_IPv4); arp_hdr->arp_hln = ETHER_ADDR_LEN; arp_hdr->arp_pln = sizeof(uint32_t); arp_hdr->arp_op = rte_cpu_to_be_16(ARP_OP_REQUEST); rte_eth_macaddr_get(BOND_PORT, &arp_hdr->arp_data.arp_sha); arp_hdr->arp_data.arp_sip = bond_ip; memset(&arp_hdr->arp_data.arp_tha, 0, ETHER_ADDR_LEN); arp_hdr->arp_data.arp_tip = ((unsigned char *)&res->ip.addr.ipv4)[0] | (((unsigned char *)&res->ip.addr.ipv4)[1] << 8) | (((unsigned char *)&res->ip.addr.ipv4)[2] << 16) | (((unsigned char *)&res->ip.addr.ipv4)[3] << 24); rte_eth_tx_burst(BOND_PORT, 0, &created_pkt, 1); rte_delay_ms(100); cmdline_printf(cl, "\n"); } cmdline_parse_token_string_t cmd_obj_action_send = TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result, action, "send"); cmdline_parse_token_ipaddr_t cmd_obj_ip = TOKEN_IPV4_INITIALIZER(struct cmd_obj_send_result, ip); cmdline_parse_inst_t cmd_obj_send = { .f = cmd_obj_send_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "send client_ip", .tokens = { /* token list, NULL terminated */ (void *)&cmd_obj_action_send, (void *)&cmd_obj_ip, NULL, }, }; struct cmd_start_result { cmdline_fixed_string_t start; }; static void cmd_start_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { int slave_core_id = rte_lcore_id(); rte_spinlock_trylock(&global_flag_stru_p->lock); if (global_flag_stru_p->LcoreMainIsRunning == 0) { if (lcore_config[global_flag_stru_p->LcoreMainCore].state != WAIT) { rte_spinlock_unlock(&global_flag_stru_p->lock); return; } rte_spinlock_unlock(&global_flag_stru_p->lock); } else { cmdline_printf(cl, "lcore_main already running on core:%d\n", global_flag_stru_p->LcoreMainCore); rte_spinlock_unlock(&global_flag_stru_p->lock); return; } /* start lcore main on core != master_core - ARP response thread */ slave_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0); if ((slave_core_id >= RTE_MAX_LCORE) || (slave_core_id == 0)) return; rte_spinlock_trylock(&global_flag_stru_p->lock); global_flag_stru_p->LcoreMainIsRunning = 1; rte_spinlock_unlock(&global_flag_stru_p->lock); cmdline_printf(cl, "Starting lcore_main on core %d:%d " "Our IP:%d.%d.%d.%d\n", slave_core_id, rte_eal_remote_launch(lcore_main, NULL, slave_core_id), BOND_IP_1, BOND_IP_2, BOND_IP_3, BOND_IP_4 ); } cmdline_parse_token_string_t cmd_start_start = TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start"); cmdline_parse_inst_t cmd_start = { .f = cmd_start_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "starts listening if not started at startup", .tokens = { /* token list, NULL terminated */ (void *)&cmd_start_start, NULL, }, }; struct cmd_help_result { cmdline_fixed_string_t help; }; static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "ALB - link bonding mode 6 example\n" "send IP - sends one ARPrequest thru bonding for IP.\n" "start - starts listening ARPs.\n" "stop - stops lcore_main.\n" "show - shows some bond info: ex. active slaves etc.\n" "help - prints help.\n" "quit - terminate all threads and quit.\n" ); } cmdline_parse_token_string_t cmd_help_help = TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); cmdline_parse_inst_t cmd_help = { .f = cmd_help_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "show help", .tokens = { /* token list, NULL terminated */ (void *)&cmd_help_help, NULL, }, }; struct cmd_stop_result { cmdline_fixed_string_t stop; }; static void cmd_stop_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { rte_spinlock_trylock(&global_flag_stru_p->lock); if (global_flag_stru_p->LcoreMainIsRunning == 0) { cmdline_printf(cl, "lcore_main not running on core:%d\n", global_flag_stru_p->LcoreMainCore); rte_spinlock_unlock(&global_flag_stru_p->lock); return; } global_flag_stru_p->LcoreMainIsRunning = 0; rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore); cmdline_printf(cl, "lcore_main stopped on core:%d\n", global_flag_stru_p->LcoreMainCore); rte_spinlock_unlock(&global_flag_stru_p->lock); } cmdline_parse_token_string_t cmd_stop_stop = TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop"); cmdline_parse_inst_t cmd_stop = { .f = cmd_stop_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "this command do not handle any arguments", .tokens = { /* token list, NULL terminated */ (void *)&cmd_stop_stop, NULL, }, }; struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { rte_spinlock_trylock(&global_flag_stru_p->lock); if (global_flag_stru_p->LcoreMainIsRunning == 0) { cmdline_printf(cl, "lcore_main not running on core:%d\n", global_flag_stru_p->LcoreMainCore); rte_spinlock_unlock(&global_flag_stru_p->lock); cmdline_quit(cl); return; } global_flag_stru_p->LcoreMainIsRunning = 0; rte_eal_wait_lcore(global_flag_stru_p->LcoreMainCore); cmdline_printf(cl, "lcore_main stopped on core:%d\n", global_flag_stru_p->LcoreMainCore); rte_spinlock_unlock(&global_flag_stru_p->lock); cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "this command do not handle any arguments", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_quit, NULL, }, }; struct cmd_show_result { cmdline_fixed_string_t show; }; static void cmd_show_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { uint8_t slaves[16] = {0}; uint8_t len = 16; struct ether_addr addr; uint8_t i = 0; while (i < slaves_count) { rte_eth_macaddr_get(i, &addr); PRINT_MAC(addr); printf("\n"); i++; } rte_spinlock_trylock(&global_flag_stru_p->lock); cmdline_printf(cl, "Active_slaves:%d " "packets received:Tot:%d Arp:%d IPv4:%d\n", rte_eth_bond_active_slaves_get(BOND_PORT, slaves, len), global_flag_stru_p->port_packets[0], global_flag_stru_p->port_packets[1], global_flag_stru_p->port_packets[2]); rte_spinlock_unlock(&global_flag_stru_p->lock); } cmdline_parse_token_string_t cmd_show_show = TOKEN_STRING_INITIALIZER(struct cmd_show_result, show, "show"); cmdline_parse_inst_t cmd_show = { .f = cmd_show_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "this command do not handle any arguments", .tokens = { /* token list, NULL terminated */ (void *)&cmd_show_show, NULL, }, }; /****** CONTEXT (list of instruction) */ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_start, (cmdline_parse_inst_t *)&cmd_obj_send, (cmdline_parse_inst_t *)&cmd_stop, (cmdline_parse_inst_t *)&cmd_show, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_help, NULL, }; /* prompt function, called from main on MASTER lcore */ static void prompt(__attribute__((unused)) void *arg1) { struct cmdline *cl; cl = cmdline_stdin_new(main_ctx, "bond6>"); if (cl != NULL) { cmdline_interact(cl); cmdline_stdin_exit(cl); } } /* Main function, does initialisation and calls the per-lcore functions */ int main(int argc, char *argv[]) { int ret; uint8_t nb_ports, i; /* init EAL */ ret = rte_eal_init(argc, argv); rte_eal_devargs_dump(stdout); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Give at least one port\n"); else if (nb_ports > MAX_PORTS) rte_exit(EXIT_FAILURE, "You can have max 4 ports\n"); mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ slaves_count = nb_ports; for (i = 0; i < nb_ports; i++) { slave_port_init(i, mbuf_pool); slaves[i] = i; } bond_port_init(mbuf_pool); rte_spinlock_init(&global_flag_stru_p->lock); int slave_core_id = rte_lcore_id(); /* check state of lcores */ RTE_LCORE_FOREACH_SLAVE(slave_core_id) { if (lcore_config[slave_core_id].state != WAIT) return -EBUSY; } /* start lcore main on core != master_core - ARP response thread */ slave_core_id = rte_get_next_lcore(rte_lcore_id(), 1, 0); if ((slave_core_id >= RTE_MAX_LCORE) || (slave_core_id == 0)) return -EPERM; global_flag_stru_p->LcoreMainIsRunning = 1; global_flag_stru_p->LcoreMainCore = slave_core_id; printf("Starting lcore_main on core %d:%d Our IP:%d.%d.%d.%d\n", slave_core_id, rte_eal_remote_launch((lcore_function_t *)lcore_main, NULL, slave_core_id), BOND_IP_1, BOND_IP_2, BOND_IP_3, BOND_IP_4 ); /* Start prompt for user interact */ prompt(NULL); rte_delay_ms(100); return 0; } ================================================ FILE: examples/bond/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ int main(int argc, char *argv[]); #endif /* ifndef _MAIN_H_ */ ================================================ FILE: examples/cmdline/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = cmdline # all source are stored in SRCS-y SRCS-y := main.c commands.c parse_obj_list.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS_parse_obj_list.o := -D_GNU_SOURCE include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/cmdline/commands.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #ifndef __linux__ #ifdef __FreeBSD__ #include #else #include #endif #endif #include #include #include #include #include #include #include #include "parse_obj_list.h" struct object_list global_obj_list; /* not defined under linux */ #ifndef NIPQUAD #define NIPQUAD_FMT "%u.%u.%u.%u" #define NIPQUAD(addr) \ (unsigned)((unsigned char *)&addr)[0], \ (unsigned)((unsigned char *)&addr)[1], \ (unsigned)((unsigned char *)&addr)[2], \ (unsigned)((unsigned char *)&addr)[3] #endif #ifndef NIP6 #define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define NIP6(addr) \ (unsigned)((addr).s6_addr[0]), \ (unsigned)((addr).s6_addr[1]), \ (unsigned)((addr).s6_addr[2]), \ (unsigned)((addr).s6_addr[3]), \ (unsigned)((addr).s6_addr[4]), \ (unsigned)((addr).s6_addr[5]), \ (unsigned)((addr).s6_addr[6]), \ (unsigned)((addr).s6_addr[7]), \ (unsigned)((addr).s6_addr[8]), \ (unsigned)((addr).s6_addr[9]), \ (unsigned)((addr).s6_addr[10]), \ (unsigned)((addr).s6_addr[11]), \ (unsigned)((addr).s6_addr[12]), \ (unsigned)((addr).s6_addr[13]), \ (unsigned)((addr).s6_addr[14]), \ (unsigned)((addr).s6_addr[15]) #endif /**********************************************************/ struct cmd_obj_del_show_result { cmdline_fixed_string_t action; struct object *obj; }; static void cmd_obj_del_show_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_obj_del_show_result *res = parsed_result; char ip_str[INET6_ADDRSTRLEN]; if (res->obj->ip.family == AF_INET) snprintf(ip_str, sizeof(ip_str), NIPQUAD_FMT, NIPQUAD(res->obj->ip.addr.ipv4)); else snprintf(ip_str, sizeof(ip_str), NIP6_FMT, NIP6(res->obj->ip.addr.ipv6)); if (strcmp(res->action, "del") == 0) { SLIST_REMOVE(&global_obj_list, res->obj, object, next); cmdline_printf(cl, "Object %s removed, ip=%s\n", res->obj->name, ip_str); free(res->obj); } else if (strcmp(res->action, "show") == 0) { cmdline_printf(cl, "Object %s, ip=%s\n", res->obj->name, ip_str); } } cmdline_parse_token_string_t cmd_obj_action = TOKEN_STRING_INITIALIZER(struct cmd_obj_del_show_result, action, "show#del"); parse_token_obj_list_t cmd_obj_obj = TOKEN_OBJ_LIST_INITIALIZER(struct cmd_obj_del_show_result, obj, &global_obj_list); cmdline_parse_inst_t cmd_obj_del_show = { .f = cmd_obj_del_show_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "Show/del an object", .tokens = { /* token list, NULL terminated */ (void *)&cmd_obj_action, (void *)&cmd_obj_obj, NULL, }, }; /**********************************************************/ struct cmd_obj_add_result { cmdline_fixed_string_t action; cmdline_fixed_string_t name; cmdline_ipaddr_t ip; }; static void cmd_obj_add_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_obj_add_result *res = parsed_result; struct object *o; char ip_str[INET6_ADDRSTRLEN]; SLIST_FOREACH(o, &global_obj_list, next) { if (!strcmp(res->name, o->name)) { cmdline_printf(cl, "Object %s already exist\n", res->name); return; } break; } o = malloc(sizeof(*o)); if (!o) { cmdline_printf(cl, "mem error\n"); return; } snprintf(o->name, sizeof(o->name), "%s", res->name); o->ip = res->ip; SLIST_INSERT_HEAD(&global_obj_list, o, next); if (o->ip.family == AF_INET) snprintf(ip_str, sizeof(ip_str), NIPQUAD_FMT, NIPQUAD(o->ip.addr.ipv4)); else snprintf(ip_str, sizeof(ip_str), NIP6_FMT, NIP6(o->ip.addr.ipv6)); cmdline_printf(cl, "Object %s added, ip=%s\n", o->name, ip_str); } cmdline_parse_token_string_t cmd_obj_action_add = TOKEN_STRING_INITIALIZER(struct cmd_obj_add_result, action, "add"); cmdline_parse_token_string_t cmd_obj_name = TOKEN_STRING_INITIALIZER(struct cmd_obj_add_result, name, NULL); cmdline_parse_token_ipaddr_t cmd_obj_ip = TOKEN_IPADDR_INITIALIZER(struct cmd_obj_add_result, ip); cmdline_parse_inst_t cmd_obj_add = { .f = cmd_obj_add_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "Add an object (name, val)", .tokens = { /* token list, NULL terminated */ (void *)&cmd_obj_action_add, (void *)&cmd_obj_name, (void *)&cmd_obj_ip, NULL, }, }; /**********************************************************/ struct cmd_help_result { cmdline_fixed_string_t help; }; static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Demo example of command line interface in RTE\n\n" "This is a readline-like interface that can be used to\n" "debug your RTE application. It supports some features\n" "of GNU readline like completion, cut/paste, and some\n" "other special bindings.\n\n" "This demo shows how rte_cmdline library can be\n" "extended to handle a list of objects. There are\n" "3 commands:\n" "- add obj_name IP\n" "- del obj_name\n" "- show obj_name\n\n"); } cmdline_parse_token_string_t cmd_help_help = TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); cmdline_parse_inst_t cmd_help = { .f = cmd_help_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "show help", .tokens = { /* token list, NULL terminated */ (void *)&cmd_help_help, NULL, }, }; /**********************************************************/ /**********************************************************/ /****** CONTEXT (list of instruction) */ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_obj_del_show, (cmdline_parse_inst_t *)&cmd_obj_add, (cmdline_parse_inst_t *)&cmd_help, NULL, }; ================================================ FILE: examples/cmdline/commands.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _COMMANDS_H_ #define _COMMANDS_H_ extern cmdline_parse_ctx_t main_ctx[]; #endif /* _COMMANDS_H_ */ ================================================ FILE: examples/cmdline/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "commands.h" int main(int argc, char **argv) { int ret; struct cmdline *cl; ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); cl = cmdline_stdin_new(main_ctx, "example> "); if (cl == NULL) rte_panic("Cannot create cmdline instance\n"); cmdline_interact(cl); cmdline_stdin_exit(cl); return 0; } ================================================ FILE: examples/cmdline/parse_obj_list.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "parse_obj_list.h" /* This file is an example of extension of libcmdline. It provides an * example of objects stored in a list. */ struct cmdline_token_ops token_obj_list_ops = { .parse = parse_obj_list, .complete_get_nb = complete_get_nb_obj_list, .complete_get_elt = complete_get_elt_obj_list, .get_help = get_help_obj_list, }; int parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { struct token_obj_list *tk2 = (struct token_obj_list *)tk; struct token_obj_list_data *tkd = &tk2->obj_list_data; struct object *o; unsigned int token_len = 0; if (*buf == 0) return -1; if (res && ressize < sizeof(struct object *)) return -1; while(!cmdline_isendoftoken(buf[token_len])) token_len++; SLIST_FOREACH(o, tkd->list, next) { if (token_len != strnlen(o->name, OBJ_NAME_LEN_MAX)) continue; if (strncmp(buf, o->name, token_len)) continue; break; } if (!o) /* not found */ return -1; /* store the address of object in structure */ if (res) *(struct object **)res = o; return token_len; } int complete_get_nb_obj_list(cmdline_parse_token_hdr_t *tk) { struct token_obj_list *tk2 = (struct token_obj_list *)tk; struct token_obj_list_data *tkd = &tk2->obj_list_data; struct object *o; int ret = 0; SLIST_FOREACH(o, tkd->list, next) { ret ++; } return ret; } int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx, char *dstbuf, unsigned int size) { struct token_obj_list *tk2 = (struct token_obj_list *)tk; struct token_obj_list_data *tkd = &tk2->obj_list_data; struct object *o; int i = 0; unsigned len; SLIST_FOREACH(o, tkd->list, next) { if (i++ == idx) break; } if (!o) return -1; len = strnlen(o->name, OBJ_NAME_LEN_MAX); if ((len + 1) > size) return -1; if (dstbuf) snprintf(dstbuf, size, "%s", o->name); return 0; } int get_help_obj_list(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { snprintf(dstbuf, size, "Obj-List"); return 0; } ================================================ FILE: examples/cmdline/parse_obj_list.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_OBJ_LIST_H_ #define _PARSE_OBJ_LIST_H_ /* This file is an example of extension of libcmdline. It provides an * example of objects stored in a list. */ #include #include #define OBJ_NAME_LEN_MAX 64 struct object { SLIST_ENTRY(object) next; char name[OBJ_NAME_LEN_MAX]; cmdline_ipaddr_t ip; }; /* define struct object_list */ SLIST_HEAD(object_list, object); /* data is a pointer to a list */ struct token_obj_list_data { struct object_list *list; }; struct token_obj_list { struct cmdline_token_hdr hdr; struct token_obj_list_data obj_list_data; }; typedef struct token_obj_list parse_token_obj_list_t; extern struct cmdline_token_ops token_obj_list_ops; int parse_obj_list(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int complete_get_nb_obj_list(cmdline_parse_token_hdr_t *tk); int complete_get_elt_obj_list(cmdline_parse_token_hdr_t *tk, int idx, char *dstbuf, unsigned int size); int get_help_obj_list(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_OBJ_LIST_INITIALIZER(structure, field, obj_list_ptr) \ { \ .hdr = { \ .ops = &token_obj_list_ops, \ .offset = offsetof(structure, field), \ }, \ .obj_list_data = { \ .list = obj_list_ptr, \ }, \ } #endif /* _PARSE_OBJ_LIST_H_ */ ================================================ FILE: examples/distributor/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = distributor_app # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif EXTRA_CFLAGS += -O3 -Wfatal-errors include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/distributor/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #define RX_RING_SIZE 256 #define TX_RING_SIZE 512 #define NUM_MBUFS ((64*1024)-1) #define MBUF_CACHE_SIZE 250 #define BURST_SIZE 32 #define RTE_RING_SZ 1024 /* uncommnet below line to enable debug logs */ /* #define DEBUG */ #ifdef DEBUG #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) do { \ RTE_LOG(DEBUG, log_type, fmt, ##args); \ } while (0) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do {} while (0) #endif #define RTE_LOGTYPE_DISTRAPP RTE_LOGTYPE_USER1 /* mask of enabled ports */ static uint32_t enabled_port_mask; volatile uint8_t quit_signal; volatile uint8_t quit_signal_rx; static volatile struct app_stats { struct { uint64_t rx_pkts; uint64_t returned_pkts; uint64_t enqueued_pkts; } rx __rte_cache_aligned; struct { uint64_t dequeue_pkts; uint64_t tx_pkts; } tx __rte_cache_aligned; } app_stats; static const struct rte_eth_conf port_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .rx_adv_conf = { .rss_conf = { .rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP | ETH_RSS_SCTP, } }, }; struct output_buffer { unsigned count; struct rte_mbuf *mbufs[BURST_SIZE]; }; /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf = port_conf_default; const uint16_t rxRings = 1, txRings = rte_lcore_count() - 1; int retval; uint16_t q; if (port >= rte_eth_dev_count()) return -1; retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; for (q = 0; q < rxRings; q++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < txRings; q++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } retval = rte_eth_dev_start(port); if (retval < 0) return retval; struct rte_eth_link link; rte_eth_link_get_nowait(port, &link); if (!link.link_status) { sleep(1); rte_eth_link_get_nowait(port, &link); } if (!link.link_status) { printf("Link down on port %"PRIu8"\n", port); return 0; } struct ether_addr addr; rte_eth_macaddr_get(port, &addr); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); rte_eth_promiscuous_enable(port); return 0; } struct lcore_params { unsigned worker_id; struct rte_distributor *d; struct rte_ring *r; struct rte_mempool *mem_pool; }; static void quit_workers(struct rte_distributor *d, struct rte_mempool *p) { const unsigned num_workers = rte_lcore_count() - 2; unsigned i; struct rte_mbuf *bufs[num_workers]; rte_mempool_get_bulk(p, (void *)bufs, num_workers); for (i = 0; i < num_workers; i++) bufs[i]->hash.rss = i << 1; rte_distributor_process(d, bufs, num_workers); rte_mempool_put_bulk(p, (void *)bufs, num_workers); } static int lcore_rx(struct lcore_params *p) { struct rte_distributor *d = p->d; struct rte_mempool *mem_pool = p->mem_pool; struct rte_ring *r = p->r; const uint8_t nb_ports = rte_eth_dev_count(); const int socket_id = rte_socket_id(); uint8_t port; for (port = 0; port < nb_ports; port++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != socket_id) printf("WARNING, port %u is on remote NUMA node to " "RX thread.\n\tPerformance will not " "be optimal.\n", port); } printf("\nCore %u doing packet RX.\n", rte_lcore_id()); port = 0; while (!quit_signal_rx) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) { if (++port == nb_ports) port = 0; continue; } struct rte_mbuf *bufs[BURST_SIZE*2]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); app_stats.rx.rx_pkts += nb_rx; rte_distributor_process(d, bufs, nb_rx); const uint16_t nb_ret = rte_distributor_returned_pkts(d, bufs, BURST_SIZE*2); app_stats.rx.returned_pkts += nb_ret; if (unlikely(nb_ret == 0)) continue; uint16_t sent = rte_ring_enqueue_burst(r, (void *)bufs, nb_ret); app_stats.rx.enqueued_pkts += sent; if (unlikely(sent < nb_ret)) { LOG_DEBUG(DISTRAPP, "%s:Packet loss due to full ring\n", __func__); while (sent < nb_ret) rte_pktmbuf_free(bufs[sent++]); } if (++port == nb_ports) port = 0; } rte_distributor_process(d, NULL, 0); /* flush distributor to bring to known state */ rte_distributor_flush(d); /* set worker & tx threads quit flag */ quit_signal = 1; /* * worker threads may hang in get packet as * distributor process is not running, just make sure workers * get packets till quit_signal is actually been * received and they gracefully shutdown */ quit_workers(d, mem_pool); /* rx thread should quit at last */ return 0; } static inline void flush_one_port(struct output_buffer *outbuf, uint8_t outp) { unsigned nb_tx = rte_eth_tx_burst(outp, 0, outbuf->mbufs, outbuf->count); app_stats.tx.tx_pkts += nb_tx; if (unlikely(nb_tx < outbuf->count)) { LOG_DEBUG(DISTRAPP, "%s:Packet loss with tx_burst\n", __func__); do { rte_pktmbuf_free(outbuf->mbufs[nb_tx]); } while (++nb_tx < outbuf->count); } outbuf->count = 0; } static inline void flush_all_ports(struct output_buffer *tx_buffers, uint8_t nb_ports) { uint8_t outp; for (outp = 0; outp < nb_ports; outp++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << outp)) == 0) continue; if (tx_buffers[outp].count == 0) continue; flush_one_port(&tx_buffers[outp], outp); } } static int lcore_tx(struct rte_ring *in_r) { static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS]; const uint8_t nb_ports = rte_eth_dev_count(); const int socket_id = rte_socket_id(); uint8_t port; for (port = 0; port < nb_ports; port++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != socket_id) printf("WARNING, port %u is on remote NUMA node to " "TX thread.\n\tPerformance will not " "be optimal.\n", port); } printf("\nCore %u doing packet TX.\n", rte_lcore_id()); while (!quit_signal) { for (port = 0; port < nb_ports; port++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << port)) == 0) continue; struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_ring_dequeue_burst(in_r, (void *)bufs, BURST_SIZE); app_stats.tx.dequeue_pkts += nb_rx; /* if we get no traffic, flush anything we have */ if (unlikely(nb_rx == 0)) { flush_all_ports(tx_buffers, nb_ports); continue; } /* for traffic we receive, queue it up for transmit */ uint16_t i; _mm_prefetch(bufs[0], 0); _mm_prefetch(bufs[1], 0); _mm_prefetch(bufs[2], 0); for (i = 0; i < nb_rx; i++) { struct output_buffer *outbuf; uint8_t outp; _mm_prefetch(bufs[i + 3], 0); /* * workers should update in_port to hold the * output port value */ outp = bufs[i]->port; /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << outp)) == 0) continue; outbuf = &tx_buffers[outp]; outbuf->mbufs[outbuf->count++] = bufs[i]; if (outbuf->count == BURST_SIZE) flush_one_port(outbuf, outp); } } } return 0; } static void int_handler(int sig_num) { printf("Exiting on signal %d\n", sig_num); /* set quit flag for rx thread to exit */ quit_signal_rx = 1; } static void print_stats(void) { struct rte_eth_stats eth_stats; unsigned i; printf("\nRX thread stats:\n"); printf(" - Received: %"PRIu64"\n", app_stats.rx.rx_pkts); printf(" - Processed: %"PRIu64"\n", app_stats.rx.returned_pkts); printf(" - Enqueued: %"PRIu64"\n", app_stats.rx.enqueued_pkts); printf("\nTX thread stats:\n"); printf(" - Dequeued: %"PRIu64"\n", app_stats.tx.dequeue_pkts); printf(" - Transmitted: %"PRIu64"\n", app_stats.tx.tx_pkts); for (i = 0; i < rte_eth_dev_count(); i++) { rte_eth_stats_get(i, ð_stats); printf("\nPort %u stats:\n", i); printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); printf(" - Pkts out: %"PRIu64"\n", eth_stats.opackets); printf(" - In Errs: %"PRIu64"\n", eth_stats.ierrors); printf(" - Out Errs: %"PRIu64"\n", eth_stats.oerrors); printf(" - Mbuf Errs: %"PRIu64"\n", eth_stats.rx_nombuf); } } static int lcore_worker(struct lcore_params *p) { struct rte_distributor *d = p->d; const unsigned id = p->worker_id; /* * for single port, xor_val will be zero so we won't modify the output * port, otherwise we send traffic from 0 to 1, 2 to 3, and vice versa */ const unsigned xor_val = (rte_eth_dev_count() > 1); struct rte_mbuf *buf = NULL; printf("\nCore %u acting as worker core.\n", rte_lcore_id()); while (!quit_signal) { buf = rte_distributor_get_pkt(d, id, buf); buf->port ^= xor_val; } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n", prgname); } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; default: print_usage(prgname); return -1; } } if (optind <= 1) { print_usage(prgname); return -1; } argv[optind-1] = prgname; optind = 0; /* reset getopt lib */ return 0; } /* Main function, does initialization and calls the per-lcore functions */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; struct rte_distributor *d; struct rte_ring *output_ring; unsigned lcore_id, worker_id = 0; unsigned nb_ports; uint8_t portid; uint8_t nb_ports_available; /* catch ctrl-c so we can print on exit */ signal(SIGINT, int_handler); /* init EAL */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid distributor parameters\n"); if (rte_lcore_count() < 3) rte_exit(EXIT_FAILURE, "Error, This application needs at " "least 3 logical cores to run:\n" "1 lcore for packet RX and distribution\n" "1 lcore for packet TX\n" "and at least 1 lcore for worker threads\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); if (nb_ports != 1 && (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even, except " "when using a single port\n"); mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); nb_ports_available = nb_ports; /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... done\n", (unsigned) portid); if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize port %"PRIu8"\n", portid); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } d = rte_distributor_create("PKT_DIST", rte_socket_id(), rte_lcore_count() - 2); if (d == NULL) rte_exit(EXIT_FAILURE, "Cannot create distributor\n"); /* * scheduler ring is read only by the transmitter core, but written to * by multiple threads */ output_ring = rte_ring_create("Output_ring", RTE_RING_SZ, rte_socket_id(), RING_F_SC_DEQ); if (output_ring == NULL) rte_exit(EXIT_FAILURE, "Cannot create output ring\n"); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (worker_id == rte_lcore_count() - 2) rte_eal_remote_launch((lcore_function_t *)lcore_tx, output_ring, lcore_id); else { struct lcore_params *p = rte_malloc(NULL, sizeof(*p), 0); if (!p) rte_panic("malloc failure\n"); *p = (struct lcore_params){worker_id, d, output_ring, mbuf_pool}; rte_eal_remote_launch((lcore_function_t *)lcore_worker, p, lcore_id); } worker_id++; } /* call lcore_main on master core only */ struct lcore_params p = { 0, d, output_ring, mbuf_pool}; lcore_rx(&p); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } print_stats(); return 0; } ================================================ FILE: examples/dpdk_qat/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2013 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif ifeq ($(ICP_ROOT),) $(error "Please define ICP_ROOT environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif LBITS := $(shell uname -p) ifeq ($(CROSS_COMPILE),) ifneq ($(CONFIG_RTE_ARCH),"x86_64") ifneq ($(LBITS),i686) $(error The RTE_TARGET chosen is not compatible with this environment \ (x86_64), for this application. Please change the definition of the \ RTE_TARGET environment variable, or run the application on a 32-bit OS) endif endif endif # binary name APP = dpdk_qat # all source are stored in SRCS-y SRCS-y := main.c crypto.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS += -I$(ICP_ROOT)/quickassist/include \ -I$(ICP_ROOT)/quickassist/include/lac \ -I$(ICP_ROOT)/quickassist/lookaside/access_layer/include # From CRF 1.2 driver, library was renamed to libicp_qa_al.a ifneq ($(wildcard $(ICP_ROOT)/build/icp_qa_al.a),) ICP_LIBRARY_PATH = $(ICP_ROOT)/build/icp_qa_al.a else ICP_LIBRARY_PATH = $(ICP_ROOT)/build/libicp_qa_al.a endif LDLIBS += -L$(ICP_ROOT)/build LDLIBS += $(ICP_LIBRARY_PATH) \ -lz \ -losal \ -ladf_proxy \ -lcrypto # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/dpdk_qat/config_files/coleto/dh895xcc_qa_dev0.conf ================================================ [GENERAL] ServicesEnabled = cy;dc ConfigVersion = 2 cyHmacAuthMode = 1 dcTotalSRAMAvailable = 0 Firmware_MofPath = dh895xcc/mof_firmware.bin Firmware_MmpPath = dh895xcc/mmp_firmware.bin statsGeneral = 1 statsDc = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 SRIOV_Enabled = 0 ProcDebug = 1 [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 [SSL] NumberCyInstances = 8 NumberDcInstances = 0 NumProcesses = 1 LimitDevAccess = 0 Cy0Name = "SSL0" Cy0IsPolled = 1 Cy0CoreAffinity = 0 Cy1Name = "SSL1" Cy1IsPolled = 1 Cy1CoreAffinity = 1 Cy2Name = "SSL2" Cy2IsPolled = 1 Cy2CoreAffinity = 2 Cy3Name = "SSL3" Cy3IsPolled = 1 Cy3CoreAffinity = 3 Cy4Name = "SSL4" Cy4IsPolled = 1 Cy4CoreAffinity = 4 Cy5Name = "SSL5" Cy5IsPolled = 1 Cy5CoreAffinity = 5 Cy6Name = "SSL6" Cy6IsPolled = 1 Cy6CoreAffinity = 6 Cy7Name = "SSL7" Cy7IsPolled = 1 Cy7CoreAffinity = 7 ================================================ FILE: examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev0.conf ================================================ ######################################################################### # # @par # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ######################################################################### # ######################################################## # # This file is the configuration for a single dh89xxcc_qa # device. # # Each device has up to two accelerators. # - The client may load balance between these # accelerators. # Each accelerator has 8 independent ring banks. # - The interrupt for each can be directed to a # specific core. # Each ring bank as 16 rings (hardware assisted queues). # ######################################################### # General Section ############################################## [GENERAL] ServicesEnabled = cy0;cy1 # Use version 2 of the config file ConfigVersion = 2 # Look Aside Cryptographic Configuration cyHmacAuthMode = 1 # Look Aside Compression Configuration dcTotalSRAMAvailable = 0 # Firmware Location Configuration Firmware_MofPath = mof_firmware.bin Firmware_MmpPath = mmp_firmware.bin #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 DcNumConcurrentRequests = 512 #Statistics, valid values: 1,0 statsGeneral = 1 statsDc = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # Enables or disables Single Root Complex IO Virtualization. # If this is enabled (1) then SRIOV and VT-d need to be enabled in # BIOS and there can be no Cy or Dc instances created in PF (Dom0). # If this i disabled (0) then SRIOV and VT-d need to be disabled # in BIOS and Cy and/or Dc instances can be used in PF (Dom0) SRIOV_Enabled = 0 #Debug feature, if set to 1 it enables additional entries in /proc filesystem ProcDebug = 1 ####################################################### # # Logical Instances Section # A logical instance allows each address domain # (kernel space and individual user space processes) # to configure rings (i.e. hardware assisted queues) # to be used by that address domain and to define the # behavior of that ring. # # The address domains are in the following format # - For kernel address domains # [KERNEL] # - For user process address domains # [xxxxx] # Where xxxxx may be any ascii value which uniquely identifies # the user mode process. # To allow the driver correctly configure the # logical instances associated with this user process, # the process must call the icp_sal_userStartMultiProcess(...) # passing the xxxxx string during process initialisation. # When the user space process is finished it must call # icp_sal_userStop(...) to free resources. # NumProcesses will indicate the maximum number of processes # that can call icp_sal_userStartMultiProcess on this instance. # Warning: the resources are preallocated: if NumProcesses # is too high, the driver will fail to load # # Items configurable by a logical instance are: # - Name of the logical instance # - The accelerator associated with this logical # instance # - The core the instance is affinitized to (optional) # # Note: Logical instances may not share the same ring, but # may share a ring bank. # # The format of the logical instances are: # - For crypto: # CyName = "xxxx" # CyAcceleratorNumber = 0-3 # CyCoreAffinity = 0-7 # # - For Data Compression # DcName = "xxxx" # DcAcceleratorNumber = 0-1 # DcCoreAffinity = 0-7 # # Where: # - n is the number of this logical instance starting at 0. # - xxxx may be any ascii value which identifies the logical instance. # # Note: for user space processes, a list of values can be specified for # the accelerator number and the core affinity: for example # Cy0AcceleratorNumber = 0,2 # Cy0CoreAffinity = 0,2,4 # These comma-separated lists will allow the multiple processes to use # different accelerators and cores, and will wrap around the numbers # in the list. In the above example, process 0 will use accelerator 0, # and process 1 will use accelerator 2 # ######################################################## ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 ############################################## # User Process Instance Section ############################################## [SSL] NumberCyInstances = 16 NumberDcInstances = 0 NumProcesses = 1 LimitDevAccess = 0 # Crypto - User instance #0 Cy0Name = "SSL0" Cy0IsPolled = 1 Cy0AcceleratorNumber = 0 # List of core affinities Cy0CoreAffinity = 0 # Crypto - User instance #1 Cy1Name = "SSL1" Cy1IsPolled = 1 Cy1AcceleratorNumber = 1 # List of core affinities Cy1CoreAffinity = 1 # Crypto - User instance #2 Cy2Name = "SSL2" Cy2IsPolled = 1 Cy2AcceleratorNumber = 2 # List of core affinities Cy2CoreAffinity = 2 # Crypto - User instance #3 Cy3Name = "SSL3" Cy3IsPolled = 1 Cy3AcceleratorNumber = 3 # List of core affinities Cy3CoreAffinity = 3 # Crypto - User instance #4 Cy4Name = "SSL4" Cy4IsPolled = 1 Cy4AcceleratorNumber = 0 # List of core affinities Cy4CoreAffinity = 4 # Crypto - User instance #5 Cy5Name = "SSL5" Cy5IsPolled = 1 Cy5AcceleratorNumber = 1 # List of core affinities Cy5CoreAffinity = 5 # Crypto - User instance #6 Cy6Name = "SSL6" Cy6IsPolled = 1 Cy6AcceleratorNumber = 2 # List of core affinities Cy6CoreAffinity = 6 # Crypto - User instance #7 Cy7Name = "SSL7" Cy7IsPolled = 1 Cy7AcceleratorNumber = 3 # List of core affinities Cy7CoreAffinity = 7 # Crypto - User instance #8 Cy8Name = "SSL8" Cy8IsPolled = 1 Cy8AcceleratorNumber = 0 # List of core affinities Cy8CoreAffinity = 16 # Crypto - User instance #9 Cy9Name = "SSL9" Cy9IsPolled = 1 Cy9AcceleratorNumber = 1 # List of core affinities Cy9CoreAffinity = 17 # Crypto - User instance #10 Cy10Name = "SSL10" Cy10IsPolled = 1 Cy10AcceleratorNumber = 2 # List of core affinities Cy10CoreAffinity = 18 # Crypto - User instance #11 Cy11Name = "SSL11" Cy11IsPolled = 1 Cy11AcceleratorNumber = 3 # List of core affinities Cy11CoreAffinity = 19 # Crypto - User instance #12 Cy12Name = "SSL12" Cy12IsPolled = 1 Cy12AcceleratorNumber = 0 # List of core affinities Cy12CoreAffinity = 20 # Crypto - User instance #13 Cy13Name = "SSL13" Cy13IsPolled = 1 Cy13AcceleratorNumber = 1 # List of core affinities Cy13CoreAffinity = 21 # Crypto - User instance #14 Cy14Name = "SSL14" Cy14IsPolled = 1 Cy14AcceleratorNumber = 2 # List of core affinities Cy14CoreAffinity = 22 # Crypto - User instance #15 Cy15Name = "SSL15" Cy15IsPolled = 1 Cy15AcceleratorNumber = 3 # List of core affinities Cy15CoreAffinity = 23 ############################################## # Wireless Process Instance Section ############################################## [WIRELESS] NumberCyInstances = 0 NumberDcInstances = 0 NumProcesses = 0 ================================================ FILE: examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev1.conf ================================================ ######################################################################### # # @par # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ######################################################################### # ######################################################## # # This file is the configuration for a single dh89xxcc_qa # device. # # Each device has up to two accelerators. # - The client may load balance between these # accelerators. # Each accelerator has 8 independent ring banks. # - The interrupt for each can be directed to a # specific core. # Each ring bank as 16 rings (hardware assisted queues). # ######################################################### # General Section ############################################## [GENERAL] ServicesEnabled = cy0;cy1 # Use version 2 of the config file ConfigVersion = 2 # Look Aside Cryptographic Configuration cyHmacAuthMode = 1 # Look Aside Compression Configuration dcTotalSRAMAvailable = 0 # Firmware Location Configuration Firmware_MofPath = mof_firmware.bin Firmware_MmpPath = mmp_firmware.bin #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 DcNumConcurrentRequests = 512 #Statistics, valid values: 1,0 statsGeneral = 1 statsDc = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # Enables or disables Single Root Complex IO Virtualization. # If this is enabled (1) then SRIOV and VT-d need to be enabled in # BIOS and there can be no Cy or Dc instances created in PF (Dom0). # If this i disabled (0) then SRIOV and VT-d need to be disabled # in BIOS and Cy and/or Dc instances can be used in PF (Dom0) SRIOV_Enabled = 0 #Debug feature, if set to 1 it enables additional entries in /proc filesystem ProcDebug = 1 ####################################################### # # Logical Instances Section # A logical instance allows each address domain # (kernel space and individual user space processes) # to configure rings (i.e. hardware assisted queues) # to be used by that address domain and to define the # behavior of that ring. # # The address domains are in the following format # - For kernel address domains # [KERNEL] # - For user process address domains # [xxxxx] # Where xxxxx may be any ascii value which uniquely identifies # the user mode process. # To allow the driver correctly configure the # logical instances associated with this user process, # the process must call the icp_sal_userStartMultiProcess(...) # passing the xxxxx string during process initialisation. # When the user space process is finished it must call # icp_sal_userStop(...) to free resources. # NumProcesses will indicate the maximum number of processes # that can call icp_sal_userStartMultiProcess on this instance. # Warning: the resources are preallocated: if NumProcesses # is too high, the driver will fail to load # # Items configurable by a logical instance are: # - Name of the logical instance # - The accelerator associated with this logical # instance # - The core the instance is affinitized to (optional) # # Note: Logical instances may not share the same ring, but # may share a ring bank. # # The format of the logical instances are: # - For crypto: # CyName = "xxxx" # CyAcceleratorNumber = 0-3 # CyCoreAffinity = 0-7 # # - For Data Compression # DcName = "xxxx" # DcAcceleratorNumber = 0-1 # DcCoreAffinity = 0-7 # # Where: # - n is the number of this logical instance starting at 0. # - xxxx may be any ascii value which identifies the logical instance. # # Note: for user space processes, a list of values can be specified for # the accelerator number and the core affinity: for example # Cy0AcceleratorNumber = 0,2 # Cy0CoreAffinity = 0,2,4 # These comma-separated lists will allow the multiple processes to use # different accelerators and cores, and will wrap around the numbers # in the list. In the above example, process 0 will use accelerator 0, # and process 1 will use accelerator 2 # ######################################################## ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 ############################################## # User Process Instance Section ############################################## [SSL] NumberCyInstances = 16 NumberDcInstances = 0 NumProcesses = 1 LimitDevAccess = 0 # Crypto - User instance #0 Cy0Name = "SSL0" Cy0IsPolled = 1 Cy0AcceleratorNumber = 0 # List of core affinities Cy0CoreAffinity = 8 # Crypto - User instance #1 Cy1Name = "SSL1" Cy1IsPolled = 1 Cy1AcceleratorNumber = 1 # List of core affinities Cy1CoreAffinity = 9 # Crypto - User instance #2 Cy2Name = "SSL2" Cy2IsPolled = 1 Cy2AcceleratorNumber = 2 # List of core affinities Cy2CoreAffinity = 10 # Crypto - User instance #3 Cy3Name = "SSL3" Cy3IsPolled = 1 Cy3AcceleratorNumber = 3 # List of core affinities Cy3CoreAffinity = 11 # Crypto - User instance #4 Cy4Name = "SSL4" Cy4IsPolled = 1 Cy4AcceleratorNumber = 0 # List of core affinities Cy4CoreAffinity = 12 # Crypto - User instance #5 Cy5Name = "SSL5" Cy5IsPolled = 1 Cy5AcceleratorNumber = 1 # List of core affinities Cy5CoreAffinity = 13 # Crypto - User instance #6 Cy6Name = "SSL6" Cy6IsPolled = 1 Cy6AcceleratorNumber = 2 # List of core affinities Cy6CoreAffinity = 14 # Crypto - User instance #7 Cy7Name = "SSL7" Cy7IsPolled = 1 Cy7AcceleratorNumber = 3 # List of core affinities Cy7CoreAffinity = 15 # Crypto - User instance #8 Cy8Name = "SSL8" Cy8IsPolled = 1 Cy8AcceleratorNumber = 0 # List of core affinities Cy8CoreAffinity = 24 # Crypto - User instance #9 Cy9Name = "SSL9" Cy9IsPolled = 1 Cy9AcceleratorNumber = 1 # List of core affinities Cy9CoreAffinity = 25 # Crypto - User instance #10 Cy10Name = "SSL10" Cy10IsPolled = 1 Cy10AcceleratorNumber = 2 # List of core affinities Cy10CoreAffinity = 26 # Crypto - User instance #11 Cy11Name = "SSL11" Cy11IsPolled = 1 Cy11AcceleratorNumber = 3 # List of core affinities Cy11CoreAffinity = 27 # Crypto - User instance #12 Cy12Name = "SSL12" Cy12IsPolled = 1 Cy12AcceleratorNumber = 0 # List of core affinities Cy12CoreAffinity = 28 # Crypto - User instance #13 Cy13Name = "SSL13" Cy13IsPolled = 1 Cy13AcceleratorNumber = 1 # List of core affinities Cy13CoreAffinity = 29 # Crypto - User instance #14 Cy14Name = "SSL14" Cy14IsPolled = 1 Cy14AcceleratorNumber = 2 # List of core affinities Cy14CoreAffinity = 30 # Crypto - User instance #15 Cy15Name = "SSL15" Cy15IsPolled = 1 Cy15AcceleratorNumber = 3 # List of core affinities Cy15CoreAffinity = 31 ############################################## # Wireless Process Instance Section ############################################## [WIRELESS] NumberCyInstances = 0 NumberDcInstances = 0 NumProcesses = 0 ================================================ FILE: examples/dpdk_qat/config_files/stargo/dh89xxcc_qa_dev0.conf ================================================ ######################################################################### # # @par # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ######################################################################### # ######################################################## # # This file is the configuration for a single dh89xxcc_qa # device. # # Each device has up to two accelerators. # - The client may load balance between these # accelerators. # Each accelerator has 8 independent ring banks. # - The interrupt for each can be directed to a # specific core. # Each ring bank as 16 rings (hardware assisted queues). # ######################################################### # General Section ############################################## [GENERAL] ServicesEnabled = cy0;cy1 # Use version 2 of the config file ConfigVersion = 2 # Look Aside Cryptographic Configuration cyHmacAuthMode = 1 # Look Aside Compression Configuration dcTotalSRAMAvailable = 0 # Firmware Location Configuration Firmware_MofPath = mof_firmware.bin Firmware_MmpPath = mmp_firmware.bin #Default values for number of concurrent requests*/ CyNumConcurrentSymRequests = 512 CyNumConcurrentAsymRequests = 64 DcNumConcurrentRequests = 512 #Statistics, valid values: 1,0 statsGeneral = 1 statsDc = 1 statsDh = 1 statsDrbg = 1 statsDsa = 1 statsEcc = 1 statsKeyGen = 1 statsLn = 1 statsPrime = 1 statsRsa = 1 statsSym = 1 # Enables or disables Single Root Complex IO Virtualization. # If this is enabled (1) then SRIOV and VT-d need to be enabled in # BIOS and there can be no Cy or Dc instances created in PF (Dom0). # If this i disabled (0) then SRIOV and VT-d need to be disabled # in BIOS and Cy and/or Dc instances can be used in PF (Dom0) SRIOV_Enabled = 0 #Debug feature, if set to 1 it enables additional entries in /proc filesystem ProcDebug = 1 ####################################################### # # Logical Instances Section # A logical instance allows each address domain # (kernel space and individual user space processes) # to configure rings (i.e. hardware assisted queues) # to be used by that address domain and to define the # behavior of that ring. # # The address domains are in the following format # - For kernel address domains # [KERNEL] # - For user process address domains # [xxxxx] # Where xxxxx may be any ascii value which uniquely identifies # the user mode process. # To allow the driver correctly configure the # logical instances associated with this user process, # the process must call the icp_sal_userStartMultiProcess(...) # passing the xxxxx string during process initialisation. # When the user space process is finished it must call # icp_sal_userStop(...) to free resources. # NumProcesses will indicate the maximum number of processes # that can call icp_sal_userStartMultiProcess on this instance. # Warning: the resources are preallocated: if NumProcesses # is too high, the driver will fail to load # # Items configurable by a logical instance are: # - Name of the logical instance # - The accelerator associated with this logical # instance # - The core the instance is affinitized to (optional) # # Note: Logical instances may not share the same ring, but # may share a ring bank. # # The format of the logical instances are: # - For crypto: # CyName = "xxxx" # CyAcceleratorNumber = 0-3 # CyCoreAffinity = 0-7 # # - For Data Compression # DcName = "xxxx" # DcAcceleratorNumber = 0-1 # DcCoreAffinity = 0-7 # # Where: # - n is the number of this logical instance starting at 0. # - xxxx may be any ascii value which identifies the logical instance. # # Note: for user space processes, a list of values can be specified for # the accelerator number and the core affinity: for example # Cy0AcceleratorNumber = 0,2 # Cy0CoreAffinity = 0,2,4 # These comma-separated lists will allow the multiple processes to use # different accelerators and cores, and will wrap around the numbers # in the list. In the above example, process 0 will use accelerator 0, # and process 1 will use accelerator 2 # ######################################################## ############################################## # Kernel Instances Section ############################################## [KERNEL] NumberCyInstances = 0 NumberDcInstances = 0 ############################################## # User Process Instance Section ############################################## [SSL] NumberCyInstances = 8 NumberDcInstances = 0 NumProcesses = 1 LimitDevAccess = 0 # Crypto - User instance #0 Cy0Name = "SSL0" Cy0IsPolled = 1 Cy0AcceleratorNumber = 0 # List of core affinities Cy0CoreAffinity = 0 # Crypto - User instance #1 Cy1Name = "SSL1" Cy1IsPolled = 1 Cy1AcceleratorNumber = 1 # List of core affinities Cy1CoreAffinity = 1 # Crypto - User instance #2 Cy2Name = "SSL2" Cy2IsPolled = 1 Cy2AcceleratorNumber = 2 # List of core affinities Cy2CoreAffinity = 2 # Crypto - User instance #3 Cy3Name = "SSL3" Cy3IsPolled = 1 Cy3AcceleratorNumber = 3 # List of core affinities Cy3CoreAffinity = 3 # Crypto - User instance #4 Cy4Name = "SSL4" Cy4IsPolled = 1 Cy4AcceleratorNumber = 0 # List of core affinities Cy4CoreAffinity = 4 # Crypto - User instance #5 Cy5Name = "SSL5" Cy5IsPolled = 1 Cy5AcceleratorNumber = 1 # List of core affinities Cy5CoreAffinity = 5 # Crypto - User instance #6 Cy6Name = "SSL6" Cy6IsPolled = 1 Cy6AcceleratorNumber = 2 # List of core affinities Cy6CoreAffinity = 6 # Crypto - User instance #7 Cy7Name = "SSL7" Cy7IsPolled = 1 Cy7AcceleratorNumber = 3 # List of core affinities Cy7CoreAffinity = 7 ############################################## # Wireless Process Instance Section ############################################## [WIRELESS] NumberCyInstances = 0 NumberDcInstances = 0 NumProcesses = 0 ================================================ FILE: examples/dpdk_qat/crypto.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CPA_CY_SYM_DP_TMP_WORKAROUND 1 #include "cpa.h" #include "cpa_types.h" #include "cpa_cy_sym_dp.h" #include "cpa_cy_common.h" #include "cpa_cy_im.h" #include "icp_sal_user.h" #include "icp_sal_poll.h" #include "crypto.h" /* CIPHER KEY LENGTHS */ #define KEY_SIZE_64_IN_BYTES (64 / 8) #define KEY_SIZE_56_IN_BYTES (56 / 8) #define KEY_SIZE_128_IN_BYTES (128 / 8) #define KEY_SIZE_168_IN_BYTES (168 / 8) #define KEY_SIZE_192_IN_BYTES (192 / 8) #define KEY_SIZE_256_IN_BYTES (256 / 8) /* HMAC AUTH KEY LENGTHS */ #define AES_XCBC_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) #define SHA1_AUTH_KEY_LENGTH_IN_BYTES (160 / 8) #define SHA224_AUTH_KEY_LENGTH_IN_BYTES (224 / 8) #define SHA256_AUTH_KEY_LENGTH_IN_BYTES (256 / 8) #define SHA384_AUTH_KEY_LENGTH_IN_BYTES (384 / 8) #define SHA512_AUTH_KEY_LENGTH_IN_BYTES (512 / 8) #define MD5_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) #define KASUMI_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) /* HASH DIGEST LENGHTS */ #define AES_XCBC_DIGEST_LENGTH_IN_BYTES (128 / 8) #define AES_XCBC_96_DIGEST_LENGTH_IN_BYTES (96 / 8) #define MD5_DIGEST_LENGTH_IN_BYTES (128 / 8) #define SHA1_DIGEST_LENGTH_IN_BYTES (160 / 8) #define SHA1_96_DIGEST_LENGTH_IN_BYTES (96 / 8) #define SHA224_DIGEST_LENGTH_IN_BYTES (224 / 8) #define SHA256_DIGEST_LENGTH_IN_BYTES (256 / 8) #define SHA384_DIGEST_LENGTH_IN_BYTES (384 / 8) #define SHA512_DIGEST_LENGTH_IN_BYTES (512 / 8) #define KASUMI_DIGEST_LENGTH_IN_BYTES (32 / 8) #define IV_LENGTH_16_BYTES (16) #define IV_LENGTH_8_BYTES (8) /* * rte_memzone is used to allocate physically contiguous virtual memory. * In this application we allocate a single block and divide between variables * which require a virtual to physical mapping for use by the QAT driver. * Virt2phys is only performed during initialisation and not on the data-path. */ #define LCORE_MEMZONE_SIZE (1 << 22) struct lcore_memzone { const struct rte_memzone *memzone; void *next_free_address; }; /* * Size the qa software response queue. * Note: Head and Tail are 8 bit, therefore, the queue is * fixed to 256 entries. */ #define CRYPTO_SOFTWARE_QUEUE_SIZE 256 struct qa_callbackQueue { uint8_t head; uint8_t tail; uint16_t numEntries; struct rte_mbuf *qaCallbackRing[CRYPTO_SOFTWARE_QUEUE_SIZE]; }; struct qa_core_conf { CpaCySymDpSessionCtx *encryptSessionHandleTbl[NUM_CRYPTO][NUM_HMAC]; CpaCySymDpSessionCtx *decryptSessionHandleTbl[NUM_CRYPTO][NUM_HMAC]; CpaInstanceHandle instanceHandle; struct qa_callbackQueue callbackQueue; uint64_t qaOutstandingRequests; uint64_t numResponseAttempts; uint8_t kickFreq; void *pPacketIV; CpaPhysicalAddr packetIVPhy; struct lcore_memzone lcoreMemzone; } __rte_cache_aligned; #define MAX_CORES (RTE_MAX_LCORE) static struct qa_core_conf qaCoreConf[MAX_CORES]; /* *Create maximum possible key size, *One for cipher and one for hash */ struct glob_keys { uint8_t cipher_key[32]; uint8_t hash_key[64]; uint8_t iv[16]; }; struct glob_keys g_crypto_hash_keys = { .cipher_key = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20}, .hash_key = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20, 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, 0x39,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50}, .iv = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10} }; /* * Offsets from the start of the packet. * */ #define PACKET_DATA_START_PHYS(p) \ ((p)->buf_physaddr + (p)->data_off) /* * A fixed offset to where the crypto is to be performed, which is the first * byte after the Ethernet(14 bytes) and IPv4 headers(20 bytes) */ #define CRYPTO_START_OFFSET (14+20) #define HASH_START_OFFSET (14+20) #define CIPHER_BLOCK_DEFAULT_SIZE (16) #define HASH_BLOCK_DEFAULT_SIZE (16) /* * Offset to the opdata from the start of the data portion of packet. * Assumption: The buffer is physically contiguous. * +18 takes this to the next cache line. */ #define CRYPTO_OFFSET_TO_OPDATA (ETHER_MAX_LEN+18) /* * Default number of requests to place on the hardware ring before kicking the * ring pointers. */ #define CRYPTO_BURST_TX (16) /* * Only call the qa poll function when the number responses in the software * queue drops below this number. */ #define CRYPTO_QUEUED_RESP_POLL_THRESHOLD (32) /* * Limit the number of polls per call to get_next_response. */ #define GET_NEXT_RESPONSE_FREQ (32) /* * Max number of responses to pull from the qa in one poll. */ #define CRYPTO_MAX_RESPONSE_QUOTA \ (CRYPTO_SOFTWARE_QUEUE_SIZE-CRYPTO_QUEUED_RESP_POLL_THRESHOLD-1) #if (CRYPTO_QUEUED_RESP_POLL_THRESHOLD + CRYPTO_MAX_RESPONSE_QUOTA >= \ CRYPTO_SOFTWARE_QUEUE_SIZE) #error Its possible to overflow the qa response Q with current poll and \ response quota. #endif static void crypto_callback(CpaCySymDpOpData *pOpData, __rte_unused CpaStatus status, __rte_unused CpaBoolean verifyResult) { uint32_t lcore_id; lcore_id = rte_lcore_id(); struct qa_callbackQueue *callbackQ = &(qaCoreConf[lcore_id].callbackQueue); /* * Received a completion from the QA hardware. * Place the response on the return queue. */ callbackQ->qaCallbackRing[callbackQ->head] = pOpData->pCallbackTag; callbackQ->head++; callbackQ->numEntries++; qaCoreConf[lcore_id].qaOutstandingRequests--; } static void qa_crypto_callback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult) { crypto_callback(pOpData, status, verifyResult); } /* * Each allocation from a particular memzone lasts for the life-time of * the application. No freeing of previous allocations will occur. */ static void * alloc_memzone_region(uint32_t length, uint32_t lcore_id) { char *current_free_addr_ptr = NULL; struct lcore_memzone *lcore_memzone = &(qaCoreConf[lcore_id].lcoreMemzone); current_free_addr_ptr = lcore_memzone->next_free_address; if (current_free_addr_ptr + length >= (char *)lcore_memzone->memzone->addr + lcore_memzone->memzone->len) { printf("Crypto: No memory available in memzone\n"); return NULL; } lcore_memzone->next_free_address = current_free_addr_ptr + length; return (void *)current_free_addr_ptr; } /* * Virtual to Physical Address translation is only executed during initialization * and not on the data-path. */ static CpaPhysicalAddr qa_v2p(void *ptr) { const struct rte_memzone *memzone = NULL; uint32_t lcore_id = 0; RTE_LCORE_FOREACH(lcore_id) { memzone = qaCoreConf[lcore_id].lcoreMemzone.memzone; if ((char*) ptr >= (char *) memzone->addr && (char*) ptr < ((char*) memzone->addr + memzone->len)) { return (CpaPhysicalAddr) (memzone->phys_addr + ((char *) ptr - (char*) memzone->addr)); } } printf("Crypto: Corresponding physical address not found in memzone\n"); return (CpaPhysicalAddr) 0; } static CpaStatus getCoreAffinity(Cpa32U *coreAffinity, const CpaInstanceHandle instanceHandle) { CpaInstanceInfo2 info; Cpa16U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; bzero(&info, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(instanceHandle, &info); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: Error getting instance info\n"); return CPA_STATUS_FAIL; } for (i = 0; i < MAX_CORES; i++) { if (CPA_BITMAP_BIT_TEST(info.coreAffinity, i)) { *coreAffinity = i; return CPA_STATUS_SUCCESS; } } return CPA_STATUS_FAIL; } static CpaStatus get_crypto_instance_on_core(CpaInstanceHandle *pInstanceHandle, uint32_t lcore_id) { Cpa16U numInstances = 0, i = 0; CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle *pLocalInstanceHandles = NULL; Cpa32U coreAffinity = 0; status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { return CPA_STATUS_FAIL; } pLocalInstanceHandles = rte_malloc("pLocalInstanceHandles", sizeof(CpaInstanceHandle) * numInstances, RTE_CACHE_LINE_SIZE); if (NULL == pLocalInstanceHandles) { return CPA_STATUS_FAIL; } status = cpaCyGetInstances(numInstances, pLocalInstanceHandles); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: cpaCyGetInstances failed with status: %"PRId32"\n", status); rte_free((void *) pLocalInstanceHandles); return CPA_STATUS_FAIL; } for (i = 0; i < numInstances; i++) { status = getCoreAffinity(&coreAffinity, pLocalInstanceHandles[i]); if (CPA_STATUS_SUCCESS != status) { rte_free((void *) pLocalInstanceHandles); return CPA_STATUS_FAIL; } if (coreAffinity == lcore_id) { printf("Crypto: instance found on core %d\n", i); *pInstanceHandle = pLocalInstanceHandles[i]; return CPA_STATUS_SUCCESS; } } /* core affinity not found */ rte_free((void *) pLocalInstanceHandles); return CPA_STATUS_FAIL; } static CpaStatus initCySymSession(const int pkt_cipher_alg, const int pkt_hash_alg, const CpaCySymHashMode hashMode, const CpaCySymCipherDirection crypto_direction, CpaCySymSessionCtx **ppSessionCtx, const CpaInstanceHandle cyInstanceHandle, const uint32_t lcore_id) { Cpa32U sessionCtxSizeInBytes = 0; CpaStatus status = CPA_STATUS_FAIL; CpaBoolean isCrypto = CPA_TRUE, isHmac = CPA_TRUE; CpaCySymSessionSetupData sessionSetupData; bzero(&sessionSetupData, sizeof(CpaCySymSessionSetupData)); /* Assumption: key length is set to each algorithm's max length */ switch (pkt_cipher_alg) { case NO_CIPHER: isCrypto = CPA_FALSE; break; case CIPHER_DES: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_DES_ECB; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_64_IN_BYTES; break; case CIPHER_DES_CBC: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_DES_CBC; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_64_IN_BYTES; break; case CIPHER_DES3: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_3DES_ECB; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_192_IN_BYTES; break; case CIPHER_DES3_CBC: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_3DES_CBC; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_192_IN_BYTES; break; case CIPHER_AES: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_ECB; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_128_IN_BYTES; break; case CIPHER_AES_CBC_128: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CBC; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_128_IN_BYTES; break; case CIPHER_KASUMI_F8: sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_KASUMI_F8; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = KEY_SIZE_128_IN_BYTES; break; default: printf("Crypto: Undefined Cipher specified\n"); break; } /* Set the cipher direction */ if (isCrypto) { sessionSetupData.cipherSetupData.cipherDirection = crypto_direction; sessionSetupData.cipherSetupData.pCipherKey = g_crypto_hash_keys.cipher_key; sessionSetupData.symOperation = CPA_CY_SYM_OP_CIPHER; } /* Setup Hash common fields */ switch (pkt_hash_alg) { case NO_HASH: isHmac = CPA_FALSE; break; case HASH_AES_XCBC: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_XCBC; sessionSetupData.hashSetupData.digestResultLenInBytes = AES_XCBC_DIGEST_LENGTH_IN_BYTES; break; case HASH_AES_XCBC_96: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_XCBC; sessionSetupData.hashSetupData.digestResultLenInBytes = AES_XCBC_96_DIGEST_LENGTH_IN_BYTES; break; case HASH_MD5: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5; sessionSetupData.hashSetupData.digestResultLenInBytes = MD5_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA1: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA1_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA1_96: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA1_96_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA224: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA224; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA224_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA256: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA256_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA384: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA384; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA384_DIGEST_LENGTH_IN_BYTES; break; case HASH_SHA512: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA512; sessionSetupData.hashSetupData.digestResultLenInBytes = SHA512_DIGEST_LENGTH_IN_BYTES; break; case HASH_KASUMI_F9: sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_KASUMI_F9; sessionSetupData.hashSetupData.digestResultLenInBytes = KASUMI_DIGEST_LENGTH_IN_BYTES; break; default: printf("Crypto: Undefined Hash specified\n"); break; } if (isHmac) { sessionSetupData.hashSetupData.hashMode = hashMode; sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; /* If using authenticated hash setup key lengths */ if (CPA_CY_SYM_HASH_MODE_AUTH == hashMode) { /* Use a common max length key */ sessionSetupData.hashSetupData.authModeSetupData.authKey = g_crypto_hash_keys.hash_key; switch (pkt_hash_alg) { case HASH_AES_XCBC: case HASH_AES_XCBC_96: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = AES_XCBC_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_MD5: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA1_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_SHA1: case HASH_SHA1_96: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA1_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_SHA224: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA224_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_SHA256: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA256_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_SHA384: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA384_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_SHA512: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = SHA512_AUTH_KEY_LENGTH_IN_BYTES; break; case HASH_KASUMI_F9: sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = KASUMI_AUTH_KEY_LENGTH_IN_BYTES; break; default: printf("Crypto: Undefined Hash specified\n"); return CPA_STATUS_FAIL; } } } /* Only high priority supported */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; /* If chaining algorithms */ if (isCrypto && isHmac) { sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; /* @assumption Alg Chain order is cipher then hash for encrypt * and hash then cipher then has for decrypt*/ if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == crypto_direction) { sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; } else { sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; } } if (!isCrypto && !isHmac) { *ppSessionCtx = NULL; return CPA_STATUS_SUCCESS; } /* Set flags for digest operations */ sessionSetupData.digestIsAppended = CPA_FALSE; sessionSetupData.verifyDigest = CPA_TRUE; /* Get the session context size based on the crypto and/or hash operations*/ status = cpaCySymDpSessionCtxGetSize(cyInstanceHandle, &sessionSetupData, &sessionCtxSizeInBytes); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: cpaCySymDpSessionCtxGetSize error, status: %"PRId32"\n", status); return CPA_STATUS_FAIL; } *ppSessionCtx = alloc_memzone_region(sessionCtxSizeInBytes, lcore_id); if (NULL == *ppSessionCtx) { printf("Crypto: Failed to allocate memory for Session Context\n"); return CPA_STATUS_FAIL; } status = cpaCySymDpInitSession(cyInstanceHandle, &sessionSetupData, *ppSessionCtx); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: cpaCySymDpInitSession failed with status %"PRId32"\n", status); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } static CpaStatus initSessionDataTables(struct qa_core_conf *qaCoreConf,uint32_t lcore_id) { Cpa32U i = 0, j = 0; CpaStatus status = CPA_STATUS_FAIL; for (i = 0; i < NUM_CRYPTO; i++) { for (j = 0; j < NUM_HMAC; j++) { if (((i == CIPHER_KASUMI_F8) && (j != NO_HASH) && (j != HASH_KASUMI_F9)) || ((i != NO_CIPHER) && (i != CIPHER_KASUMI_F8) && (j == HASH_KASUMI_F9))) continue; status = initCySymSession(i, j, CPA_CY_SYM_HASH_MODE_AUTH, CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, &qaCoreConf->encryptSessionHandleTbl[i][j], qaCoreConf->instanceHandle, lcore_id); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: Failed to initialize Encrypt sessions\n"); return CPA_STATUS_FAIL; } status = initCySymSession(i, j, CPA_CY_SYM_HASH_MODE_AUTH, CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT, &qaCoreConf->decryptSessionHandleTbl[i][j], qaCoreConf->instanceHandle, lcore_id); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: Failed to initialize Decrypt sessions\n"); return CPA_STATUS_FAIL; } } } return CPA_STATUS_SUCCESS; } int crypto_init(void) { if (CPA_STATUS_SUCCESS != icp_sal_userStartMultiProcess("SSL",CPA_FALSE)) { printf("Crypto: Could not start sal for user space\n"); return CPA_STATUS_FAIL; } printf("Crypto: icp_sal_userStartMultiProcess(\"SSL\",CPA_FALSE)\n"); return 0; } /* * Per core initialisation */ int per_core_crypto_init(uint32_t lcore_id) { CpaStatus status = CPA_STATUS_FAIL; char memzone_name[RTE_MEMZONE_NAMESIZE]; int socketID = rte_lcore_to_socket_id(lcore_id); /* Allocate software ring for response messages. */ qaCoreConf[lcore_id].callbackQueue.head = 0; qaCoreConf[lcore_id].callbackQueue.tail = 0; qaCoreConf[lcore_id].callbackQueue.numEntries = 0; qaCoreConf[lcore_id].kickFreq = 0; qaCoreConf[lcore_id].qaOutstandingRequests = 0; qaCoreConf[lcore_id].numResponseAttempts = 0; /* Initialise and reserve lcore memzone for virt2phys translation */ snprintf(memzone_name, RTE_MEMZONE_NAMESIZE, "lcore_%u", lcore_id); qaCoreConf[lcore_id].lcoreMemzone.memzone = rte_memzone_reserve( memzone_name, LCORE_MEMZONE_SIZE, socketID, 0); if (NULL == qaCoreConf[lcore_id].lcoreMemzone.memzone) { printf("Crypto: Error allocating memzone on lcore %u\n",lcore_id); return -1; } qaCoreConf[lcore_id].lcoreMemzone.next_free_address = qaCoreConf[lcore_id].lcoreMemzone.memzone->addr; qaCoreConf[lcore_id].pPacketIV = alloc_memzone_region(IV_LENGTH_16_BYTES, lcore_id); if (NULL == qaCoreConf[lcore_id].pPacketIV ) { printf("Crypto: Failed to allocate memory for Initialization Vector\n"); return -1; } memcpy(qaCoreConf[lcore_id].pPacketIV, &g_crypto_hash_keys.iv, IV_LENGTH_16_BYTES); qaCoreConf[lcore_id].packetIVPhy = qa_v2p(qaCoreConf[lcore_id].pPacketIV); if (0 == qaCoreConf[lcore_id].packetIVPhy) { printf("Crypto: Invalid physical address for Initialization Vector\n"); return -1; } /* * Obtain the instance handle that is mapped to the current lcore. * This can fail if an instance is not mapped to a bank which has been * affinitized to the current lcore. */ status = get_crypto_instance_on_core(&(qaCoreConf[lcore_id].instanceHandle), lcore_id); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: get_crypto_instance_on_core failed with status: %"PRId32"\n", status); return -1; } status = cpaCySymDpRegCbFunc(qaCoreConf[lcore_id].instanceHandle, (CpaCySymDpCbFunc) qa_crypto_callback); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: cpaCySymDpRegCbFunc failed with status: %"PRId32"\n", status); return -1; } /* * Set the address translation callback for virtual to physcial address * mapping. This will be called by the QAT driver during initialisation only. */ status = cpaCySetAddressTranslation(qaCoreConf[lcore_id].instanceHandle, (CpaVirtualToPhysical) qa_v2p); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: cpaCySetAddressTranslation failed with status: %"PRId32"\n", status); return -1; } status = initSessionDataTables(&qaCoreConf[lcore_id],lcore_id); if (CPA_STATUS_SUCCESS != status) { printf("Crypto: Failed to allocate all session tables."); return -1; } return 0; } static CpaStatus enqueueOp(CpaCySymDpOpData *opData, uint32_t lcore_id) { CpaStatus status; /* * Assumption is there is no requirement to do load balancing between * acceleration units - that is one acceleration unit is tied to a core. */ opData->instanceHandle = qaCoreConf[lcore_id].instanceHandle; if ((++qaCoreConf[lcore_id].kickFreq) % CRYPTO_BURST_TX == 0) { status = cpaCySymDpEnqueueOp(opData, CPA_TRUE); } else { status = cpaCySymDpEnqueueOp(opData, CPA_FALSE); } qaCoreConf[lcore_id].qaOutstandingRequests++; return status; } void crypto_flush_tx_queue(uint32_t lcore_id) { cpaCySymDpPerformOpNow(qaCoreConf[lcore_id].instanceHandle); } enum crypto_result crypto_encrypt(struct rte_mbuf *rte_buff, enum cipher_alg c, enum hash_alg h) { CpaCySymDpOpData *opData = rte_pktmbuf_mtod_offset(rte_buff, CpaCySymDpOpData *, CRYPTO_OFFSET_TO_OPDATA); uint32_t lcore_id; if (unlikely(c >= NUM_CRYPTO || h >= NUM_HMAC)) return CRYPTO_RESULT_FAIL; lcore_id = rte_lcore_id(); bzero(opData, sizeof(CpaCySymDpOpData)); opData->srcBuffer = opData->dstBuffer = PACKET_DATA_START_PHYS(rte_buff); opData->srcBufferLen = opData->dstBufferLen = rte_buff->data_len; opData->sessionCtx = qaCoreConf[lcore_id].encryptSessionHandleTbl[c][h]; opData->thisPhys = PACKET_DATA_START_PHYS(rte_buff) + CRYPTO_OFFSET_TO_OPDATA; opData->pCallbackTag = rte_buff; /* if no crypto or hash operations are specified return fail */ if (NO_CIPHER == c && NO_HASH == h) return CRYPTO_RESULT_FAIL; if (NO_CIPHER != c) { opData->pIv = qaCoreConf[lcore_id].pPacketIV; opData->iv = qaCoreConf[lcore_id].packetIVPhy; if (CIPHER_AES_CBC_128 == c) opData->ivLenInBytes = IV_LENGTH_16_BYTES; else opData->ivLenInBytes = IV_LENGTH_8_BYTES; opData->cryptoStartSrcOffsetInBytes = CRYPTO_START_OFFSET; opData->messageLenToCipherInBytes = rte_buff->data_len - CRYPTO_START_OFFSET; /* * Work around for padding, message length has to be a multiple of * block size. */ opData->messageLenToCipherInBytes -= opData->messageLenToCipherInBytes % CIPHER_BLOCK_DEFAULT_SIZE; } if (NO_HASH != h) { opData->hashStartSrcOffsetInBytes = HASH_START_OFFSET; opData->messageLenToHashInBytes = rte_buff->data_len - HASH_START_OFFSET; /* * Work around for padding, message length has to be a multiple of block * size. */ opData->messageLenToHashInBytes -= opData->messageLenToHashInBytes % HASH_BLOCK_DEFAULT_SIZE; /* * Assumption: Ok ignore the passed digest pointer and place HMAC at end * of packet. */ opData->digestResult = rte_buff->buf_physaddr + rte_buff->data_len; } if (CPA_STATUS_SUCCESS != enqueueOp(opData, lcore_id)) { /* * Failed to place a packet on the hardware queue. * Most likely because the QA hardware is busy. */ return CRYPTO_RESULT_FAIL; } return CRYPTO_RESULT_IN_PROGRESS; } enum crypto_result crypto_decrypt(struct rte_mbuf *rte_buff, enum cipher_alg c, enum hash_alg h) { CpaCySymDpOpData *opData = rte_pktmbuf_mtod_offset(rte_buff, void *, CRYPTO_OFFSET_TO_OPDATA); uint32_t lcore_id; if (unlikely(c >= NUM_CRYPTO || h >= NUM_HMAC)) return CRYPTO_RESULT_FAIL; lcore_id = rte_lcore_id(); bzero(opData, sizeof(CpaCySymDpOpData)); opData->dstBuffer = opData->srcBuffer = PACKET_DATA_START_PHYS(rte_buff); opData->dstBufferLen = opData->srcBufferLen = rte_buff->data_len; opData->thisPhys = PACKET_DATA_START_PHYS(rte_buff) + CRYPTO_OFFSET_TO_OPDATA; opData->sessionCtx = qaCoreConf[lcore_id].decryptSessionHandleTbl[c][h]; opData->pCallbackTag = rte_buff; /* if no crypto or hmac operations are specified return fail */ if (NO_CIPHER == c && NO_HASH == h) return CRYPTO_RESULT_FAIL; if (NO_CIPHER != c) { opData->pIv = qaCoreConf[lcore_id].pPacketIV; opData->iv = qaCoreConf[lcore_id].packetIVPhy; if (CIPHER_AES_CBC_128 == c) opData->ivLenInBytes = IV_LENGTH_16_BYTES; else opData->ivLenInBytes = IV_LENGTH_8_BYTES; opData->cryptoStartSrcOffsetInBytes = CRYPTO_START_OFFSET; opData->messageLenToCipherInBytes = rte_buff->data_len - CRYPTO_START_OFFSET; /* * Work around for padding, message length has to be a multiple of block * size. */ opData->messageLenToCipherInBytes -= opData->messageLenToCipherInBytes % CIPHER_BLOCK_DEFAULT_SIZE; } if (NO_HASH != h) { opData->hashStartSrcOffsetInBytes = HASH_START_OFFSET; opData->messageLenToHashInBytes = rte_buff->data_len - HASH_START_OFFSET; /* * Work around for padding, message length has to be a multiple of block * size. */ opData->messageLenToHashInBytes -= opData->messageLenToHashInBytes % HASH_BLOCK_DEFAULT_SIZE; opData->digestResult = rte_buff->buf_physaddr + rte_buff->data_len; } if (CPA_STATUS_SUCCESS != enqueueOp(opData, lcore_id)) { /* * Failed to place a packet on the hardware queue. * Most likely because the QA hardware is busy. */ return CRYPTO_RESULT_FAIL; } return CRYPTO_RESULT_IN_PROGRESS; } void * crypto_get_next_response(void) { uint32_t lcore_id; lcore_id = rte_lcore_id(); struct qa_callbackQueue *callbackQ = &(qaCoreConf[lcore_id].callbackQueue); void *entry = NULL; if (callbackQ->numEntries) { entry = callbackQ->qaCallbackRing[callbackQ->tail]; callbackQ->tail++; callbackQ->numEntries--; } /* If there are no outstanding requests no need to poll, return entry */ if (qaCoreConf[lcore_id].qaOutstandingRequests == 0) return entry; if (callbackQ->numEntries < CRYPTO_QUEUED_RESP_POLL_THRESHOLD && qaCoreConf[lcore_id].numResponseAttempts++ % GET_NEXT_RESPONSE_FREQ == 0) { /* * Only poll the hardware when there is less than * CRYPTO_QUEUED_RESP_POLL_THRESHOLD elements in the software queue */ icp_sal_CyPollDpInstance(qaCoreConf[lcore_id].instanceHandle, CRYPTO_MAX_RESPONSE_QUOTA); } return entry; } ================================================ FILE: examples/dpdk_qat/crypto.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CRYPTO_H_ #define CRYPTO_H_ /* Pass Labels/Values to crypto units */ enum cipher_alg { /* Option to not do any cryptography */ NO_CIPHER, CIPHER_DES, CIPHER_DES_CBC, CIPHER_DES3, CIPHER_DES3_CBC, CIPHER_AES, CIPHER_AES_CBC_128, CIPHER_KASUMI_F8, NUM_CRYPTO, }; enum hash_alg { /* Option to not do any hash */ NO_HASH, HASH_MD5, HASH_SHA1, HASH_SHA1_96, HASH_SHA224, HASH_SHA256, HASH_SHA384, HASH_SHA512, HASH_AES_XCBC, HASH_AES_XCBC_96, HASH_KASUMI_F9, NUM_HMAC, }; /* Return value from crypto_{encrypt/decrypt} */ enum crypto_result { /* Packet was successfully put into crypto queue */ CRYPTO_RESULT_IN_PROGRESS, /* Cryptography has failed in some way */ CRYPTO_RESULT_FAIL, }; extern enum crypto_result crypto_encrypt(struct rte_mbuf *pkt, enum cipher_alg c, enum hash_alg h); extern enum crypto_result crypto_decrypt(struct rte_mbuf *pkt, enum cipher_alg c, enum hash_alg h); extern int crypto_init(void); extern int per_core_crypto_init(uint32_t lcore_id); extern void crypto_exit(void); extern void *crypto_get_next_response(void); extern void crypto_flush_tx_queue(uint32_t lcore_id); #endif /* CRYPTO_H_ */ ================================================ FILE: examples/dpdk_qat/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "crypto.h" #define NB_MBUF (32 * 1024) #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define TX_QUEUE_FLUSH_MASK 0xFFFFFFFF #define TSC_COUNT_LIMIT 1000 #define ACTION_ENCRYPT 1 #define ACTION_DECRYPT 2 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static unsigned enabled_port_mask = 0; static int promiscuous_on = 1; /**< Ports set in promiscuous mode on by default. */ /* list of enabled ports */ static uint32_t dst_ports[RTE_MAX_ETHPORTS]; struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; struct lcore_rx_queue { uint8_t port_id; uint8_t queue_id; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_LCORE_PARAMS 1024 struct lcore_params { uint8_t port_id; uint8_t queue_id; uint8_t lcore_id; }; static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, }; static struct lcore_params * lcore_params = lcore_params_array_default; static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool * pktmbuf_pool[RTE_MAX_NUMA_NODES]; struct lcore_conf { uint64_t tsc; uint64_t tsc_count; uint32_t tx_mask; uint16_t n_rx_queue; uint16_t rx_queue_list_pos; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct mbuf_table rx_mbuf; uint32_t rx_mbuf_pos; uint32_t rx_curr_queue; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; static inline struct rte_mbuf * nic_rx_get_packet(struct lcore_conf *qconf) { struct rte_mbuf *pkt; if (unlikely(qconf->n_rx_queue == 0)) return NULL; /* Look for the next queue with packets; return if none */ if (unlikely(qconf->rx_mbuf_pos == qconf->rx_mbuf.len)) { uint32_t i; qconf->rx_mbuf_pos = 0; for (i = 0; i < qconf->n_rx_queue; i++) { qconf->rx_mbuf.len = rte_eth_rx_burst( qconf->rx_queue_list[qconf->rx_curr_queue].port_id, qconf->rx_queue_list[qconf->rx_curr_queue].queue_id, qconf->rx_mbuf.m_table, MAX_PKT_BURST); qconf->rx_curr_queue++; if (unlikely(qconf->rx_curr_queue == qconf->n_rx_queue)) qconf->rx_curr_queue = 0; if (likely(qconf->rx_mbuf.len > 0)) break; } if (unlikely(i == qconf->n_rx_queue)) return NULL; } /* Get the next packet from the current queue; if last packet, go to next queue */ pkt = qconf->rx_mbuf.m_table[qconf->rx_mbuf_pos]; qconf->rx_mbuf_pos++; return pkt; } static inline void nic_tx_flush_queues(struct lcore_conf *qconf) { uint8_t portid; for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { struct rte_mbuf **m_table = NULL; uint16_t queueid, len; uint32_t n, i; if (likely((qconf->tx_mask & (1 << portid)) == 0)) continue; len = qconf->tx_mbufs[portid].len; if (likely(len == 0)) continue; queueid = qconf->tx_queue_id[portid]; m_table = qconf->tx_mbufs[portid].m_table; n = rte_eth_tx_burst(portid, queueid, m_table, len); for (i = n; i < len; i++){ rte_pktmbuf_free(m_table[i]); } qconf->tx_mbufs[portid].len = 0; } qconf->tx_mask = TX_QUEUE_FLUSH_MASK; } static inline void nic_tx_send_packet(struct rte_mbuf *pkt, uint8_t port) { struct lcore_conf *qconf; uint32_t lcoreid; uint16_t len; if (unlikely(pkt == NULL)) { return; } lcoreid = rte_lcore_id(); qconf = &lcore_conf[lcoreid]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = pkt; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { uint32_t n, i; uint16_t queueid; queueid = qconf->tx_queue_id[port]; n = rte_eth_tx_burst(port, queueid, qconf->tx_mbufs[port].m_table, MAX_PKT_BURST); for (i = n; i < MAX_PKT_BURST; i++){ rte_pktmbuf_free(qconf->tx_mbufs[port].m_table[i]); } qconf->tx_mask &= ~(1 << port); len = 0; } qconf->tx_mbufs[port].len = len; } /* main processing loop */ static __attribute__((noreturn)) int main_loop(__attribute__((unused)) void *dummy) { uint32_t lcoreid; struct lcore_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; lcoreid = rte_lcore_id(); qconf = &lcore_conf[lcoreid]; printf("Thread %u starting...\n", lcoreid); for (;;) { struct rte_mbuf *pkt; uint32_t pkt_from_nic_rx = 0; uint8_t port; /* Flush TX queues */ qconf->tsc_count++; if (unlikely(qconf->tsc_count == TSC_COUNT_LIMIT)) { uint64_t tsc, diff_tsc; tsc = rte_rdtsc(); diff_tsc = tsc - qconf->tsc; if (unlikely(diff_tsc > drain_tsc)) { nic_tx_flush_queues(qconf); crypto_flush_tx_queue(lcoreid); qconf->tsc = tsc; } qconf->tsc_count = 0; } /* * Check the Intel QuickAssist queues first * ***/ pkt = (struct rte_mbuf *) crypto_get_next_response(); if (pkt == NULL) { pkt = nic_rx_get_packet(qconf); pkt_from_nic_rx = 1; } if (pkt == NULL) continue; /* Send packet to either QAT encrypt, QAT decrypt or NIC TX */ if (pkt_from_nic_rx) { struct ipv4_hdr *ip = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *, sizeof(struct ether_hdr)); if (ip->src_addr & rte_cpu_to_be_32(ACTION_ENCRYPT)) { if (CRYPTO_RESULT_FAIL == crypto_encrypt(pkt, (enum cipher_alg)((ip->src_addr >> 16) & 0xFF), (enum hash_alg)((ip->src_addr >> 8) & 0xFF))) rte_pktmbuf_free(pkt); continue; } if (ip->src_addr & rte_cpu_to_be_32(ACTION_DECRYPT)) { if(CRYPTO_RESULT_FAIL == crypto_decrypt(pkt, (enum cipher_alg)((ip->src_addr >> 16) & 0xFF), (enum hash_alg)((ip->src_addr >> 8) & 0xFF))) rte_pktmbuf_free(pkt); continue; } } port = dst_ports[pkt->port]; /* Transmit the packet */ nic_tx_send_packet(pkt, (uint8_t)port); } } static inline unsigned get_port_max_rx_queues(uint8_t port_id) { struct rte_eth_dev_info dev_info; rte_eth_dev_info_get(port_id, &dev_info); return dev_info.max_rx_queues; } static inline unsigned get_port_max_tx_queues(uint8_t port_id) { struct rte_eth_dev_info dev_info; rte_eth_dev_info_get(port_id, &dev_info); return dev_info.max_tx_queues; } static int check_lcore_params(void) { uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].queue_id >= get_port_max_rx_queues(lcore_params[i].port_id)) { printf("invalid queue number: %hhu\n", lcore_params[i].queue_id); return -1; } if (!rte_lcore_is_enabled(lcore_params[i].lcore_id)) { printf("error: lcore %hhu is not enabled in lcore mask\n", lcore_params[i].lcore_id); return -1; } } return 0; } static int check_port_config(const unsigned nb_ports) { unsigned portid; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; if ((enabled_port_mask & (1 << portid)) == 0) { printf("port %u is not enabled in port mask\n", portid); return -1; } if (portid >= nb_ports) { printf("port %u is not present on the board\n", portid); return -1; } } return 0; } static uint8_t get_port_n_rx_queues(const uint8_t port) { int queue = -1; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) queue = lcore_params[i].queue_id; } return (uint8_t)(++queue); } static int init_lcore_rx_queues(void) { uint16_t i, nb_rx_queue; uint8_t lcore; for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; nb_rx_queue = lcore_conf[lcore].n_rx_queue; if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { printf("error: too many queues (%u) for lcore: %u\n", (unsigned)nb_rx_queue + 1, (unsigned)lcore); return -1; } lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = lcore_params[i].port_id; lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = lcore_params[i].queue_id; lcore_conf[lcore].n_rx_queue++; } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK [--no-promisc]" " [--config '(port,queue,lcore)[,(port,queue,lcore)]'\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " --no-promisc: disable promiscuous mode (default is ON)\n" " --config '(port,queue,lcore)': rx queues configuration\n", prgname); } static unsigned parse_portmask(const char *portmask) { char *end = NULL; unsigned pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; return pm; } static int parse_config(const char *q_arg) { char s[256]; const char *p, *p_end = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; nb_lcore_params = 0; while ((p = strchr(p_end,'(')) != NULL) { if (nb_lcore_params >= MAX_LCORE_PARAMS) { printf("exceeded max number of lcore params: %hu\n", nb_lcore_params); return -1; } ++p; if((p_end = strchr(p,')')) == NULL) return -1; size = p_end - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; ++nb_lcore_params; } lcore_params = lcore_params_array; return 0; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, {"no-promisc", 0, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* long options */ case 0: if (strcmp(lgopts[option_index].name, "config") == 0) { ret = parse_config(optarg); if (ret) { printf("invalid config\n"); print_usage(prgname); return -1; } } if (strcmp(lgopts[option_index].name, "no-promisc") == 0) { printf("Promiscuous mode disabled\n"); promiscuous_on = 0; } break; default: print_usage(prgname); return -1; } } if (enabled_port_mask == 0) { printf("portmask not specified\n"); print_usage(prgname); return -1; } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } static int init_mem(void) { int socketid; unsigned lcoreid; char s[64]; RTE_LCORE_FOREACH(lcoreid) { socketid = rte_lcore_to_socket_id(lcoreid); if (socketid >= RTE_MAX_NUMA_NODES) { printf("Socket %d of lcore %u is out of range %d\n", socketid, lcoreid, RTE_MAX_NUMA_NODES); return -1; } if (pktmbuf_pool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (pktmbuf_pool[socketid] == NULL) { printf("Cannot init mbuf pool on socket %d\n", socketid); return -1; } printf("Allocated mbuf pool on socket %d\n", socketid); } } return 0; } int main(int argc, char **argv) { struct lcore_conf *qconf; struct rte_eth_link link; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcoreid; uint32_t nb_tx_queue; uint8_t portid, nb_rx_queue, queue, socketid, last_port; unsigned nb_ports_in_mask = 0; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) return -1; argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) return -1; if (check_lcore_params() < 0) rte_panic("check_lcore_params failed\n"); ret = init_lcore_rx_queues(); if (ret < 0) return -1; ret = init_mem(); if (ret < 0) return -1; nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; if (check_port_config(nb_ports) < 0) rte_panic("check_port_config failed\n"); /* reset dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { dst_ports[portid] = last_port; dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; } if (nb_ports_in_mask % 2) { printf("Notice: odd number of ports in portmask.\n"); dst_ports[last_port] = last_port; } /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } /* init port */ printf("Initializing port %d ... ", portid ); fflush(stdout); nb_rx_queue = get_port_n_rx_queues(portid); if (nb_rx_queue > get_port_max_rx_queues(portid)) rte_panic("Number of rx queues %d exceeds max number of rx queues %u" " for port %d\n", nb_rx_queue, get_port_max_rx_queues(portid), portid); nb_tx_queue = rte_lcore_count(); if (nb_tx_queue > get_port_max_tx_queues(portid)) rte_panic("Number of lcores %u exceeds max number of tx queues %u" " for port %d\n", nb_tx_queue, get_port_max_tx_queues(portid), portid); printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)nb_tx_queue ); ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)nb_tx_queue, &port_conf); if (ret < 0) rte_panic("Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); /* init one TX queue per couple (lcore,port) */ queueid = 0; RTE_LCORE_FOREACH(lcoreid) { socketid = (uint8_t)rte_lcore_to_socket_id(lcoreid); printf("txq=%u,%d,%d ", lcoreid, queueid, socketid); fflush(stdout); ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, NULL); if (ret < 0) rte_panic("rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_conf[lcoreid]; qconf->tx_queue_id[portid] = queueid; queueid++; } printf("\n"); } RTE_LCORE_FOREACH(lcoreid) { qconf = &lcore_conf[lcoreid]; printf("\nInitializing rx queues on lcore %u ... ", lcoreid ); fflush(stdout); /* init RX queues */ for(queue = 0; queue < qconf->n_rx_queue; ++queue) { portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; socketid = (uint8_t)rte_lcore_to_socket_id(lcoreid); printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, NULL, pktmbuf_pool[socketid]); if (ret < 0) rte_panic("rte_eth_rx_queue_setup: err=%d," "port=%d\n", ret, portid); } } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) continue; /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_panic("rte_eth_dev_start: err=%d, port=%d\n", ret, portid); printf("done: Port %d ", portid); /* get link status */ rte_eth_link_get(portid, &link); if (link.link_status) printf(" Link Up - speed %u Mbps - %s\n", (unsigned) link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf(" Link Down\n"); /* * If enabled, put device in promiscuous mode. * This allows IO forwarding mode to forward packets * to itself through 2 cross-connected ports of the * target machine. */ if (promiscuous_on) rte_eth_promiscuous_enable(portid); } printf("Crypto: Initializing Crypto...\n"); if (crypto_init() != 0) return -1; RTE_LCORE_FOREACH(lcoreid) { if (per_core_crypto_init(lcoreid) != 0) { printf("Crypto: Cannot init lcore crypto on lcore %u\n", (unsigned)lcoreid); return -1; } } printf("Crypto: Initialization complete\n"); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcoreid) { if (rte_eal_wait_lcore(lcoreid) < 0) return -1; } return 0; } ================================================ FILE: examples/exception_path/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: else # binary name APP = exception_path # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk endif ================================================ FILE: examples/exception_path/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 #define FATAL_ERROR(fmt, args...) rte_exit(EXIT_FAILURE, fmt "\n", ##args) #define PRINT_INFO(fmt, args...) RTE_LOG(INFO, APP, fmt "\n", ##args) /* Max ports than can be used (each port is associated with two lcores) */ #define MAX_PORTS (RTE_MAX_LCORE / 2) /* Max size of a single packet */ #define MAX_PACKET_SZ (2048) /* Size of the data buffer in each mbuf */ #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) /* Number of mbufs in mempool that is created */ #define NB_MBUF 8192 /* How many packets to attempt to read from NIC in one go */ #define PKT_BURST_SZ 32 /* How many objects (mbufs) to keep in per-lcore mempool cache */ #define MEMPOOL_CACHE_SZ PKT_BURST_SZ /* Number of RX ring descriptors */ #define NB_RXD 128 /* Number of TX ring descriptors */ #define NB_TXD 512 /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ /* Options for configuring ethernet port */ static const struct rte_eth_conf port_conf = { .rxmode = { .header_split = 0, /* Header Split disabled */ .hw_ip_checksum = 0, /* IP checksum offload disabled */ .hw_vlan_filter = 0, /* VLAN filtering disabled */ .jumbo_frame = 0, /* Jumbo Frame Support disabled */ .hw_strip_crc = 0, /* CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; /* Mempool for mbufs */ static struct rte_mempool * pktmbuf_pool = NULL; /* Mask of enabled ports */ static uint32_t ports_mask = 0; /* Mask of cores that read from NIC and write to tap */ static uint64_t input_cores_mask = 0; /* Mask of cores that read from tap and write to NIC */ static uint64_t output_cores_mask = 0; /* Array storing port_id that is associated with each lcore */ static uint8_t port_ids[RTE_MAX_LCORE]; /* Structure type for recording lcore-specific stats */ struct stats { uint64_t rx; uint64_t tx; uint64_t dropped; }; /* Array of lcore-specific stats */ static struct stats lcore_stats[RTE_MAX_LCORE]; /* Print out statistics on packets handled */ static void print_stats(void) { unsigned i; printf("\n**Exception-Path example application statistics**\n" "======= ====== ============ ============ ===============\n" " Lcore Port RX TX Dropped on TX\n" "------- ------ ------------ ------------ ---------------\n"); RTE_LCORE_FOREACH(i) { printf("%6u %7u %13"PRIu64" %13"PRIu64" %16"PRIu64"\n", i, (unsigned)port_ids[i], lcore_stats[i].rx, lcore_stats[i].tx, lcore_stats[i].dropped); } printf("======= ====== ============ ============ ===============\n"); } /* Custom handling of signals to handle stats */ static void signal_handler(int signum) { /* When we receive a USR1 signal, print stats */ if (signum == SIGUSR1) { print_stats(); } /* When we receive a USR2 signal, reset stats */ if (signum == SIGUSR2) { memset(&lcore_stats, 0, sizeof(lcore_stats)); printf("\n**Statistics have been reset**\n"); return; } } /* * Create a tap network interface, or use existing one with same name. * If name[0]='\0' then a name is automatically assigned and returned in name. */ static int tap_create(char *name) { struct ifreq ifr; int fd, ret; fd = open("/dev/net/tun", O_RDWR); if (fd < 0) return fd; memset(&ifr, 0, sizeof(ifr)); /* TAP device without packet information */ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if (name && *name) snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name); ret = ioctl(fd, TUNSETIFF, (void *) &ifr); if (ret < 0) { close(fd); return ret; } if (name) snprintf(name, IFNAMSIZ, "%s", ifr.ifr_name); return fd; } /* Main processing loop */ static int main_loop(__attribute__((unused)) void *arg) { const unsigned lcore_id = rte_lcore_id(); char tap_name[IFNAMSIZ]; int tap_fd; if ((1ULL << lcore_id) & input_cores_mask) { /* Create new tap interface */ snprintf(tap_name, IFNAMSIZ, "tap_dpdk_%.2u", lcore_id); tap_fd = tap_create(tap_name); if (tap_fd < 0) FATAL_ERROR("Could not create tap interface \"%s\" (%d)", tap_name, tap_fd); PRINT_INFO("Lcore %u is reading from port %u and writing to %s", lcore_id, (unsigned)port_ids[lcore_id], tap_name); fflush(stdout); /* Loop forever reading from NIC and writing to tap */ for (;;) { struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; unsigned i; const unsigned nb_rx = rte_eth_rx_burst(port_ids[lcore_id], 0, pkts_burst, PKT_BURST_SZ); lcore_stats[lcore_id].rx += nb_rx; for (i = 0; likely(i < nb_rx); i++) { struct rte_mbuf *m = pkts_burst[i]; /* Ignore return val from write() */ int ret = write(tap_fd, rte_pktmbuf_mtod(m, void*), rte_pktmbuf_data_len(m)); rte_pktmbuf_free(m); if (unlikely(ret < 0)) lcore_stats[lcore_id].dropped++; else lcore_stats[lcore_id].tx++; } } } else if ((1ULL << lcore_id) & output_cores_mask) { /* Create new tap interface */ snprintf(tap_name, IFNAMSIZ, "tap_dpdk_%.2u", lcore_id); tap_fd = tap_create(tap_name); if (tap_fd < 0) FATAL_ERROR("Could not create tap interface \"%s\" (%d)", tap_name, tap_fd); PRINT_INFO("Lcore %u is reading from %s and writing to port %u", lcore_id, tap_name, (unsigned)port_ids[lcore_id]); fflush(stdout); /* Loop forever reading from tap and writing to NIC */ for (;;) { int ret; struct rte_mbuf *m = rte_pktmbuf_alloc(pktmbuf_pool); if (m == NULL) continue; ret = read(tap_fd, rte_pktmbuf_mtod(m, void *), MAX_PACKET_SZ); lcore_stats[lcore_id].rx++; if (unlikely(ret < 0)) { FATAL_ERROR("Reading from %s interface failed", tap_name); } m->nb_segs = 1; m->next = NULL; m->pkt_len = (uint16_t)ret; m->data_len = (uint16_t)ret; ret = rte_eth_tx_burst(port_ids[lcore_id], 0, &m, 1); if (unlikely(ret < 1)) { rte_pktmbuf_free(m); lcore_stats[lcore_id].dropped++; } else { lcore_stats[lcore_id].tx++; } } } else { PRINT_INFO("Lcore %u has nothing to do", lcore_id); return 0; } /* * Tap file is closed automatically when program exits. Putting close() * here will cause the compiler to give an error about unreachable code. */ } /* Display usage instructions */ static void print_usage(const char *prgname) { PRINT_INFO("\nUsage: %s [EAL options] -- -p PORTMASK -i IN_CORES -o OUT_CORES\n" " -p PORTMASK: hex bitmask of ports to use\n" " -i IN_CORES: hex bitmask of cores which read from NIC\n" " -o OUT_CORES: hex bitmask of cores which write to NIC", prgname); } /* Convert string to unsigned number. 0 is returned if error occurs */ static uint64_t parse_unsigned(const char *portmask) { char *end = NULL; uint64_t num; num = strtoull(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; return (uint64_t)num; } /* Record affinities between ports and lcores in global port_ids[] array */ static void setup_port_lcore_affinities(void) { unsigned long i; uint8_t tx_port = 0; uint8_t rx_port = 0; /* Setup port_ids[] array, and check masks were ok */ RTE_LCORE_FOREACH(i) { if (input_cores_mask & (1ULL << i)) { /* Skip ports that are not enabled */ while ((ports_mask & (1 << rx_port)) == 0) { rx_port++; if (rx_port > (sizeof(ports_mask) * 8)) goto fail; /* not enough ports */ } port_ids[i] = rx_port++; } else if (output_cores_mask & (1ULL << i)) { /* Skip ports that are not enabled */ while ((ports_mask & (1 << tx_port)) == 0) { tx_port++; if (tx_port > (sizeof(ports_mask) * 8)) goto fail; /* not enough ports */ } port_ids[i] = tx_port++; } } if (rx_port != tx_port) goto fail; /* uneven number of cores in masks */ if (ports_mask & (~((1 << rx_port) - 1))) goto fail; /* unused ports */ return; fail: FATAL_ERROR("Invalid core/port masks specified on command line"); } /* Parse the arguments given in the command line of the application */ static void parse_args(int argc, char **argv) { int opt; const char *prgname = argv[0]; /* Disable printing messages within getopt() */ opterr = 0; /* Parse command line */ while ((opt = getopt(argc, argv, "i:o:p:")) != EOF) { switch (opt) { case 'i': input_cores_mask = parse_unsigned(optarg); break; case 'o': output_cores_mask = parse_unsigned(optarg); break; case 'p': ports_mask = parse_unsigned(optarg); break; default: print_usage(prgname); FATAL_ERROR("Invalid option specified"); } } /* Check that options were parsed ok */ if (input_cores_mask == 0) { print_usage(prgname); FATAL_ERROR("IN_CORES not specified correctly"); } if (output_cores_mask == 0) { print_usage(prgname); FATAL_ERROR("OUT_CORES not specified correctly"); } if (ports_mask == 0) { print_usage(prgname); FATAL_ERROR("PORTMASK not specified correctly"); } setup_port_lcore_affinities(); } /* Initialise a single port on an Ethernet device */ static void init_port(uint8_t port) { int ret; /* Initialise device and RX/TX queues */ PRINT_INFO("Initialising port %u ...", (unsigned)port); fflush(stdout); ret = rte_eth_dev_configure(port, 1, 1, &port_conf); if (ret < 0) FATAL_ERROR("Could not configure port%u (%d)", (unsigned)port, ret); ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, rte_eth_dev_socket_id(port), NULL, pktmbuf_pool); if (ret < 0) FATAL_ERROR("Could not setup up RX queue for port%u (%d)", (unsigned)port, ret); ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, rte_eth_dev_socket_id(port), NULL); if (ret < 0) FATAL_ERROR("Could not setup up TX queue for port%u (%d)", (unsigned)port, ret); ret = rte_eth_dev_start(port); if (ret < 0) FATAL_ERROR("Could not start port%u (%d)", (unsigned)port, ret); rte_eth_promiscuous_enable(port); } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } /* Initialise ports/queues etc. and start main loop on each core */ int main(int argc, char** argv) { int ret; unsigned i,high_port; uint8_t nb_sys_ports, port; /* Associate signal_hanlder function with USR signals */ signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); /* Initialise EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) FATAL_ERROR("Could not initialise EAL (%d)", ret); argc -= ret; argv += ret; /* Parse application arguments (after the EAL ones) */ parse_args(argc, argv); /* Create the mbuf pool */ pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id()); if (pktmbuf_pool == NULL) { FATAL_ERROR("Could not initialise mbuf pool"); return -1; } /* Get number of ports found in scan */ nb_sys_ports = rte_eth_dev_count(); if (nb_sys_ports == 0) FATAL_ERROR("No supported Ethernet device found"); /* Find highest port set in portmask */ for (high_port = (sizeof(ports_mask) * 8) - 1; (high_port != 0) && !(ports_mask & (1 << high_port)); high_port--) ; /* empty body */ if (high_port > nb_sys_ports) FATAL_ERROR("Port mask requires more ports than available"); /* Initialise each port */ for (port = 0; port < nb_sys_ports; port++) { /* Skip ports that are not enabled */ if ((ports_mask & (1 << port)) == 0) { continue; } init_port(port); } check_all_ports_link_status(nb_sys_ports, ports_mask); /* Launch per-lcore function on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(i) { if (rte_eal_wait_lcore(i) < 0) return -1; } return 0; } ================================================ FILE: examples/helloworld/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = helloworld # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/helloworld/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include static int lcore_hello(__attribute__((unused)) void *arg) { unsigned lcore_id; lcore_id = rte_lcore_id(); printf("hello from core %u\n", lcore_id); return 0; } int main(int argc, char **argv) { int ret; unsigned lcore_id; ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); /* call lcore_hello() on every slave lcore */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_hello, NULL, lcore_id); } /* call it on master lcore too */ lcore_hello(NULL); rte_eal_mp_wait_lcore(); return 0; } ================================================ FILE: examples/ip_fragmentation/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = ip_fragmentation # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/ip_fragmentation/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_IP_FRAG RTE_LOGTYPE_USER1 /* allow max jumbo frame 9.5 KB */ #define JUMBO_FRAME_MAX_SIZE 0x2600 #define ROUNDUP_DIV(a, b) (((a) + (b) - 1) / (b)) /* * Default byte size for the IPv6 Maximum Transfer Unit (MTU). * This value includes the size of IPv6 header. */ #define IPV4_MTU_DEFAULT ETHER_MTU #define IPV6_MTU_DEFAULT ETHER_MTU /* * Default payload in bytes for the IPv6 packet. */ #define IPV4_DEFAULT_PAYLOAD (IPV4_MTU_DEFAULT - sizeof(struct ipv4_hdr)) #define IPV6_DEFAULT_PAYLOAD (IPV6_MTU_DEFAULT - sizeof(struct ipv6_hdr)) /* * Max number of fragments per packet expected - defined by config file. */ #define MAX_PACKET_FRAG RTE_LIBRTE_IP_FRAG_MAX_FRAG #define NB_MBUF 8192 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; #ifndef IPv4_BYTES #define IPv4_BYTES_FMT "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 #define IPv4_BYTES(addr) \ (uint8_t) (((addr) >> 24) & 0xFF),\ (uint8_t) (((addr) >> 16) & 0xFF),\ (uint8_t) (((addr) >> 8) & 0xFF),\ (uint8_t) ((addr) & 0xFF) #endif #ifndef IPv6_BYTES #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ "%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define IPv6_BYTES(addr) \ addr[0], addr[1], addr[2], addr[3], \ addr[4], addr[5], addr[6], addr[7], \ addr[8], addr[9], addr[10], addr[11],\ addr[12], addr[13],addr[14], addr[15] #endif #define IPV6_ADDR_LEN 16 /* mask of enabled ports */ static int enabled_port_mask = 0; static int rx_queue_per_lcore = 1; #define MBUF_TABLE_SIZE (2 * MAX(MAX_PKT_BURST, MAX_PACKET_FRAG)) struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MBUF_TABLE_SIZE]; }; struct rx_queue { struct rte_mempool *direct_pool; struct rte_mempool *indirect_pool; struct rte_lpm *lpm; struct rte_lpm6 *lpm6; uint8_t portid; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { uint16_t n_rx_queue; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 1, /**< Jumbo Frame Support enabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; /* * IPv4 forwarding table */ struct l3fwd_ipv4_route { uint32_t ip; uint8_t depth; uint8_t if_out; }; struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = { {IPv4(100,10,0,0), 16, 0}, {IPv4(100,20,0,0), 16, 1}, {IPv4(100,30,0,0), 16, 2}, {IPv4(100,40,0,0), 16, 3}, {IPv4(100,50,0,0), 16, 4}, {IPv4(100,60,0,0), 16, 5}, {IPv4(100,70,0,0), 16, 6}, {IPv4(100,80,0,0), 16, 7}, }; /* * IPv6 forwarding table */ struct l3fwd_ipv6_route { uint8_t ip[IPV6_ADDR_LEN]; uint8_t depth; uint8_t if_out; }; static struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = { {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0}, {{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1}, {{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2}, {{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3}, {{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4}, {{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5}, {{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6}, {{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7}, }; #define LPM_MAX_RULES 1024 #define LPM6_MAX_RULES 1024 #define LPM6_NUMBER_TBL8S (1 << 16) struct rte_lpm6_config lpm6_config = { .max_rules = LPM6_MAX_RULES, .number_tbl8s = LPM6_NUMBER_TBL8S, .flags = 0 }; static struct rte_mempool *socket_direct_pool[RTE_MAX_NUMA_NODES]; static struct rte_mempool *socket_indirect_pool[RTE_MAX_NUMA_NODES]; static struct rte_lpm *socket_lpm[RTE_MAX_NUMA_NODES]; static struct rte_lpm6 *socket_lpm6[RTE_MAX_NUMA_NODES]; /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_queue_conf *qconf, uint16_t n, uint8_t port) { struct rte_mbuf **m_table; int ret; uint16_t queueid; queueid = qconf->tx_queue_id[port]; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, queueid, m_table, n); if (unlikely(ret < n)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } static inline void l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf, uint8_t queueid, uint8_t port_in) { struct rx_queue *rxq; uint32_t i, len; uint8_t next_hop, port_out, ipv6; int32_t len2; ipv6 = 0; rxq = &qconf->rx_queue_list[queueid]; /* by default, send everything back to the source port */ port_out = port_in; /* Remove the Ethernet header and trailer from the input packet */ rte_pktmbuf_adj(m, (uint16_t)sizeof(struct ether_hdr)); /* Build transmission burst */ len = qconf->tx_mbufs[port_out].len; /* if this is an IPv4 packet */ #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { #else if (m->ol_flags & PKT_RX_IPV4_HDR) { #endif struct ipv4_hdr *ip_hdr; uint32_t ip_dst; /* Read the lookup key (i.e. ip_dst) from the input packet */ ip_hdr = rte_pktmbuf_mtod(m, struct ipv4_hdr *); ip_dst = rte_be_to_cpu_32(ip_hdr->dst_addr); /* Find destination port */ if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop) == 0 && (enabled_port_mask & 1 << next_hop) != 0) { port_out = next_hop; /* Build transmission burst for new port */ len = qconf->tx_mbufs[port_out].len; } /* if we don't need to do any fragmentation */ if (likely (IPV4_MTU_DEFAULT >= m->pkt_len)) { qconf->tx_mbufs[port_out].m_table[len] = m; len2 = 1; } else { len2 = rte_ipv4_fragment_packet(m, &qconf->tx_mbufs[port_out].m_table[len], (uint16_t)(MBUF_TABLE_SIZE - len), IPV4_MTU_DEFAULT, rxq->direct_pool, rxq->indirect_pool); /* Free input packet */ rte_pktmbuf_free(m); /* If we fail to fragment the packet */ if (unlikely (len2 < 0)) return; } #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { /* if this is an IPv6 packet */ #else } /* if this is an IPv6 packet */ else if (m->ol_flags & PKT_RX_IPV6_HDR) { #endif struct ipv6_hdr *ip_hdr; ipv6 = 1; /* Read the lookup key (i.e. ip_dst) from the input packet */ ip_hdr = rte_pktmbuf_mtod(m, struct ipv6_hdr *); /* Find destination port */ if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, &next_hop) == 0 && (enabled_port_mask & 1 << next_hop) != 0) { port_out = next_hop; /* Build transmission burst for new port */ len = qconf->tx_mbufs[port_out].len; } /* if we don't need to do any fragmentation */ if (likely (IPV6_MTU_DEFAULT >= m->pkt_len)) { qconf->tx_mbufs[port_out].m_table[len] = m; len2 = 1; } else { len2 = rte_ipv6_fragment_packet(m, &qconf->tx_mbufs[port_out].m_table[len], (uint16_t)(MBUF_TABLE_SIZE - len), IPV6_MTU_DEFAULT, rxq->direct_pool, rxq->indirect_pool); /* Free input packet */ rte_pktmbuf_free(m); /* If we fail to fragment the packet */ if (unlikely (len2 < 0)) return; } } /* else, just forward the packet */ else { qconf->tx_mbufs[port_out].m_table[len] = m; len2 = 1; } for (i = len; i < len + len2; i ++) { void *d_addr_bytes; m = qconf->tx_mbufs[port_out].m_table[i]; struct ether_hdr *eth_hdr = (struct ether_hdr *) rte_pktmbuf_prepend(m, (uint16_t)sizeof(struct ether_hdr)); if (eth_hdr == NULL) { rte_panic("No headroom in mbuf.\n"); } m->l2_len = sizeof(struct ether_hdr); /* 02:00:00:00:00:xx */ d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; *((uint64_t *)d_addr_bytes) = 0x000000000002 + ((uint64_t)port_out << 40); /* src addr */ ether_addr_copy(&ports_eth_addr[port_out], ð_hdr->s_addr); if (ipv6) eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv6); else eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); } len += len2; if (likely(len < MAX_PKT_BURST)) { qconf->tx_mbufs[port_out].len = (uint16_t)len; return; } /* Transmit packets */ send_burst(qconf, (uint16_t)len, port_out); qconf->tx_mbufs[port_out].len = 0; } /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; int i, j, nb_rx; uint8_t portid; struct lcore_queue_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, IP_FRAG, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, IP_FRAG, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].portid; RTE_LOG(INFO, IP_FRAG, " -- lcoreid=%u portid=%d\n", lcore_id, (int) portid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, portid); qconf->tx_mbufs[portid].len = 0; } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].portid; nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, MAX_PKT_BURST); /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); l3fwd_simple_forward(pkts_burst[j], qconf, i, portid); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { l3fwd_simple_forward(pkts_burst[j], qconf, i, portid); } } } } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n", prgname); } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n == 0) return -1; if (n >= MAX_RX_QUEUE_PER_LCORE) return -1; return n; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask < 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* nqueue */ case 'q': rx_queue_per_lcore = parse_nqueue(optarg); if (rx_queue_per_lcore < 0) { printf("invalid queue number\n"); print_usage(prgname); return -1; } break; /* long options */ case 0: print_usage(prgname); return -1; default: print_usage(prgname); return -1; } } if (enabled_port_mask == 0) { printf("portmask not specified\n"); print_usage(prgname); return -1; } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("\ndone\n"); } } } static int init_routing_table(void) { struct rte_lpm *lpm; struct rte_lpm6 *lpm6; int socket, ret; unsigned i; for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { if (socket_lpm[socket]) { lpm = socket_lpm[socket]; /* populate the LPM table */ for (i = 0; i < RTE_DIM(l3fwd_ipv4_route_array); i++) { ret = rte_lpm_add(lpm, l3fwd_ipv4_route_array[i].ip, l3fwd_ipv4_route_array[i].depth, l3fwd_ipv4_route_array[i].if_out); if (ret < 0) { RTE_LOG(ERR, IP_FRAG, "Unable to add entry %i to the l3fwd " "LPM table\n", i); return -1; } RTE_LOG(INFO, IP_FRAG, "Socket %i: adding route " IPv4_BYTES_FMT "/%d (port %d)\n", socket, IPv4_BYTES(l3fwd_ipv4_route_array[i].ip), l3fwd_ipv4_route_array[i].depth, l3fwd_ipv4_route_array[i].if_out); } } if (socket_lpm6[socket]) { lpm6 = socket_lpm6[socket]; /* populate the LPM6 table */ for (i = 0; i < RTE_DIM(l3fwd_ipv6_route_array); i++) { ret = rte_lpm6_add(lpm6, l3fwd_ipv6_route_array[i].ip, l3fwd_ipv6_route_array[i].depth, l3fwd_ipv6_route_array[i].if_out); if (ret < 0) { RTE_LOG(ERR, IP_FRAG, "Unable to add entry %i to the l3fwd " "LPM6 table\n", i); return -1; } RTE_LOG(INFO, IP_FRAG, "Socket %i: adding route " IPv6_BYTES_FMT "/%d (port %d)\n", socket, IPv6_BYTES(l3fwd_ipv6_route_array[i].ip), l3fwd_ipv6_route_array[i].depth, l3fwd_ipv6_route_array[i].if_out); } } } return 0; } static int init_mem(void) { char buf[PATH_MAX]; struct rte_mempool *mp; struct rte_lpm *lpm; struct rte_lpm6 *lpm6; int socket; unsigned lcore_id; /* traverse through lcores and initialize structures on each socket */ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socket = rte_lcore_to_socket_id(lcore_id); if (socket == SOCKET_ID_ANY) socket = 0; if (socket_direct_pool[socket] == NULL) { RTE_LOG(INFO, IP_FRAG, "Creating direct mempool on socket %i\n", socket); snprintf(buf, sizeof(buf), "pool_direct_%i", socket); mp = rte_pktmbuf_pool_create(buf, NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socket); if (mp == NULL) { RTE_LOG(ERR, IP_FRAG, "Cannot create direct mempool\n"); return -1; } socket_direct_pool[socket] = mp; } if (socket_indirect_pool[socket] == NULL) { RTE_LOG(INFO, IP_FRAG, "Creating indirect mempool on socket %i\n", socket); snprintf(buf, sizeof(buf), "pool_indirect_%i", socket); mp = rte_pktmbuf_pool_create(buf, NB_MBUF, 32, 0, 0, socket); if (mp == NULL) { RTE_LOG(ERR, IP_FRAG, "Cannot create indirect mempool\n"); return -1; } socket_indirect_pool[socket] = mp; } if (socket_lpm[socket] == NULL) { RTE_LOG(INFO, IP_FRAG, "Creating LPM table on socket %i\n", socket); snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket); lpm = rte_lpm_create(buf, socket, LPM_MAX_RULES, 0); if (lpm == NULL) { RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n"); return -1; } socket_lpm[socket] = lpm; } if (socket_lpm6[socket] == NULL) { RTE_LOG(INFO, IP_FRAG, "Creating LPM6 table on socket %i\n", socket); snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket); lpm6 = rte_lpm6_create("IP_FRAG_LPM6", socket, &lpm6_config); if (lpm6 == NULL) { RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n"); return -1; } socket_lpm6[socket] = lpm6; } } return 0; } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; struct rx_queue *rxq; int socket, ret; unsigned nb_ports; uint16_t queueid = 0; unsigned lcore_id = 0, rx_lcore_id = 0; uint32_t n_tx_queue, nb_lcores; uint8_t portid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eal_init failed"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid arguments"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; else if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No ports found!\n"); nb_lcores = rte_lcore_count(); /* initialize structures (mempools, lpm etc.) */ if (init_mem() < 0) rte_panic("Cannot initialize memory structures!\n"); /* check if portmask has non-existent ports */ if (enabled_port_mask & ~(RTE_LEN2MASK(nb_ports, unsigned))) rte_exit(EXIT_FAILURE, "Non-existent ports in portmask!\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %d\n", portid); continue; } qconf = &lcore_queue_conf[rx_lcore_id]; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || qconf->n_rx_queue == (unsigned)rx_queue_per_lcore) { rx_lcore_id ++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); qconf = &lcore_queue_conf[rx_lcore_id]; } socket = (int) rte_lcore_to_socket_id(rx_lcore_id); if (socket == SOCKET_ID_ANY) socket = 0; rxq = &qconf->rx_queue_list[qconf->n_rx_queue]; rxq->portid = portid; rxq->direct_pool = socket_direct_pool[socket]; rxq->indirect_pool = socket_indirect_pool[socket]; rxq->lpm = socket_lpm[socket]; rxq->lpm6 = socket_lpm6[socket]; qconf->n_rx_queue++; /* init port */ printf("Initializing port %d on lcore %u...", portid, rx_lcore_id); fflush(stdout); n_tx_queue = nb_lcores; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) { printf("\n"); rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%d\n", ret, portid); } /* init one RX queue */ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, socket, NULL, socket_direct_pool[socket]); if (ret < 0) { printf("\n"); rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: " "err=%d, port=%d\n", ret, portid); } rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf("\n"); /* init one TX queue per couple (lcore,port) */ queueid = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socket = (int) rte_lcore_to_socket_id(lcore_id); printf("txq=%u,%d ", lcore_id, queueid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socket, txconf); if (ret < 0) { printf("\n"); rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: " "err=%d, port=%d\n", ret, portid); } qconf = &lcore_queue_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; queueid++; } printf("\n"); } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); rte_eth_promiscuous_enable(portid); } if (init_routing_table() < 0) rte_exit(EXIT_FAILURE, "Cannot init routing table\n"); check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/ip_pipeline/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc DIRS-(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = ip_pipeline VPATH += $(SRCDIR)/pipeline INC += $(wildcard *.h) $(wildcard pipeline/*.h) # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += thread.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cpu_core_map.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_common_fe.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -Wno-error=unused-function -Wno-error=unused-variable include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/ip_pipeline/app.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_APP_H__ #define __INCLUDE_APP_H__ #include #include #include #include #include #include #include #include #include "cpu_core_map.h" #include "pipeline.h" #define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE struct app_mempool_params { char *name; uint32_t parsed; uint32_t buffer_size; uint32_t pool_size; uint32_t cache_size; uint32_t cpu_socket_id; }; struct app_link_params { char *name; uint32_t parsed; uint32_t pmd_id; /* Generated based on port mask */ uint32_t arp_q; /* 0 = Disabled (packets go to default queue 0) */ uint32_t tcp_syn_local_q; /* 0 = Disabled (pkts go to default queue) */ uint32_t ip_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t sctp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t state; /* DOWN = 0, UP = 1 */ uint32_t ip; /* 0 = Invalid */ uint32_t depth; /* Valid only when IP is valid */ uint64_t mac_addr; /* Read from HW */ struct rte_eth_conf conf; uint8_t promisc; }; struct app_pktq_hwq_in_params { char *name; uint32_t parsed; uint32_t mempool_id; /* Position in the app->mempool_params */ uint32_t size; uint32_t burst; struct rte_eth_rxconf conf; }; struct app_pktq_hwq_out_params { char *name; uint32_t parsed; uint32_t size; uint32_t burst; uint32_t dropless; uint64_t n_retries; struct rte_eth_txconf conf; }; struct app_pktq_swq_params { char *name; uint32_t parsed; uint32_t size; uint32_t burst_read; uint32_t burst_write; uint32_t dropless; uint64_t n_retries; uint32_t cpu_socket_id; }; #ifndef APP_FILE_NAME_SIZE #define APP_FILE_NAME_SIZE 256 #endif #ifndef APP_MAX_SCHED_SUBPORTS #define APP_MAX_SCHED_SUBPORTS 8 #endif #ifndef APP_MAX_SCHED_PIPES #define APP_MAX_SCHED_PIPES 4096 #endif struct app_pktq_tm_params { char *name; uint32_t parsed; const char *file_name; struct rte_sched_port_params sched_port_params; struct rte_sched_subport_params sched_subport_params[APP_MAX_SCHED_SUBPORTS]; struct rte_sched_pipe_params sched_pipe_profiles[RTE_SCHED_PIPE_PROFILES_PER_PORT]; int sched_pipe_to_profile[APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES]; uint32_t burst_read; uint32_t burst_write; }; struct app_pktq_source_params { char *name; uint32_t parsed; uint32_t mempool_id; /* Position in the app->mempool_params array */ uint32_t burst; }; struct app_pktq_sink_params { char *name; uint8_t parsed; }; struct app_msgq_params { char *name; uint32_t parsed; uint32_t size; uint32_t cpu_socket_id; }; enum app_pktq_in_type { APP_PKTQ_IN_HWQ, APP_PKTQ_IN_SWQ, APP_PKTQ_IN_TM, APP_PKTQ_IN_SOURCE, }; struct app_pktq_in_params { enum app_pktq_in_type type; uint32_t id; /* Position in the appropriate app array */ }; enum app_pktq_out_type { APP_PKTQ_OUT_HWQ, APP_PKTQ_OUT_SWQ, APP_PKTQ_OUT_TM, APP_PKTQ_OUT_SINK, }; struct app_pktq_out_params { enum app_pktq_out_type type; uint32_t id; /* Position in the appropriate app array */ }; #ifndef APP_PIPELINE_TYPE_SIZE #define APP_PIPELINE_TYPE_SIZE 64 #endif #define APP_MAX_PIPELINE_PKTQ_IN PIPELINE_MAX_PORT_IN #define APP_MAX_PIPELINE_PKTQ_OUT PIPELINE_MAX_PORT_OUT #define APP_MAX_PIPELINE_MSGQ_IN PIPELINE_MAX_MSGQ_IN #define APP_MAX_PIPELINE_MSGQ_OUT PIPELINE_MAX_MSGQ_OUT #define APP_MAX_PIPELINE_ARGS PIPELINE_MAX_ARGS struct app_pipeline_params { char *name; uint8_t parsed; char type[APP_PIPELINE_TYPE_SIZE]; uint32_t socket_id; uint32_t core_id; uint32_t hyper_th_id; struct app_pktq_in_params pktq_in[APP_MAX_PIPELINE_PKTQ_IN]; struct app_pktq_out_params pktq_out[APP_MAX_PIPELINE_PKTQ_OUT]; uint32_t msgq_in[APP_MAX_PIPELINE_MSGQ_IN]; uint32_t msgq_out[APP_MAX_PIPELINE_MSGQ_OUT]; uint32_t n_pktq_in; uint32_t n_pktq_out; uint32_t n_msgq_in; uint32_t n_msgq_out; uint32_t timer_period; char *args_name[APP_MAX_PIPELINE_ARGS]; char *args_value[APP_MAX_PIPELINE_ARGS]; uint32_t n_args; }; struct app_pipeline_data { void *be; void *fe; uint64_t timer_period; }; struct app_thread_pipeline_data { void *be; pipeline_be_op_run f_run; pipeline_be_op_timer f_timer; uint64_t timer_period; uint64_t deadline; }; #ifndef APP_MAX_THREAD_PIPELINES #define APP_MAX_THREAD_PIPELINES 16 #endif struct app_thread_data { struct app_thread_pipeline_data regular[APP_MAX_THREAD_PIPELINES]; struct app_thread_pipeline_data custom[APP_MAX_THREAD_PIPELINES]; uint32_t n_regular; uint32_t n_custom; uint64_t deadline; }; struct app_eal_params { /* Map lcore set to physical cpu set */ char *coremap; /* Core ID that is used as master */ uint32_t master_lcore_present; uint32_t master_lcore; /* Number of memory channels */ uint32_t channels_present; uint32_t channels; /* Memory to allocate (see also --socket-mem) */ uint32_t memory_present; uint32_t memory; /* Force number of memory ranks (don't detect) */ uint32_t ranks_present; uint32_t ranks; /* Add a PCI device in black list. */ char *pci_blacklist; /* Add a PCI device in white list. */ char *pci_whitelist; /* Add a virtual device. */ char *vdev; /* Use VMware TSC map instead of native RDTSC */ uint32_t vmware_tsc_map_present; int vmware_tsc_map; /* Type of this process (primary|secondary|auto) */ char *proc_type; /* Set syslog facility */ char *syslog; /* Set default log level */ uint32_t log_level_present; uint32_t log_level; /* Display version information on startup */ uint32_t version_present; int version; /* This help */ uint32_t help_present; int help; /* Use malloc instead of hugetlbfs */ uint32_t no_huge_present; int no_huge; /* Disable PCI */ uint32_t no_pci_present; int no_pci; /* Disable HPET */ uint32_t no_hpet_present; int no_hpet; /* No shared config (mmap'd files) */ uint32_t no_shconf_present; int no_shconf; /* Add driver */ char *add_driver; /* Memory to allocate on sockets (comma separated values)*/ char *socket_mem; /* Directory where hugetlbfs is mounted */ char *huge_dir; /* Prefix for hugepage filenames */ char *file_prefix; /* Base virtual address */ char *base_virtaddr; /* Create /dev/uioX (usually done by hotplug) */ uint32_t create_uio_dev_present; int create_uio_dev; /* Interrupt mode for VFIO (legacy|msi|msix) */ char *vfio_intr; /* Support running on Xen dom0 without hugetlbfs */ uint32_t xen_dom0_present; int xen_dom0; }; #ifndef APP_APPNAME_SIZE #define APP_APPNAME_SIZE 256 #endif #ifndef APP_MAX_MEMPOOLS #define APP_MAX_MEMPOOLS 8 #endif #ifndef APP_MAX_LINKS #define APP_MAX_LINKS 16 #endif #ifndef APP_LINK_MAX_HWQ_IN #define APP_LINK_MAX_HWQ_IN 64 #endif #ifndef APP_LINK_MAX_HWQ_OUT #define APP_LINK_MAX_HWQ_OUT 64 #endif #define APP_MAX_HWQ_IN (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN) #define APP_MAX_HWQ_OUT (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT) #ifndef APP_MAX_PKTQ_SWQ #define APP_MAX_PKTQ_SWQ 256 #endif #define APP_MAX_PKTQ_TM APP_MAX_LINKS #ifndef APP_MAX_PKTQ_SOURCE #define APP_MAX_PKTQ_SOURCE 16 #endif #ifndef APP_MAX_PKTQ_SINK #define APP_MAX_PKTQ_SINK 16 #endif #ifndef APP_MAX_MSGQ #define APP_MAX_MSGQ 64 #endif #ifndef APP_MAX_PIPELINES #define APP_MAX_PIPELINES 64 #endif #ifndef APP_EAL_ARGC #define APP_EAL_ARGC 32 #endif #ifndef APP_MAX_PIPELINE_TYPES #define APP_MAX_PIPELINE_TYPES 64 #endif #ifndef APP_MAX_THREADS #define APP_MAX_THREADS RTE_MAX_LCORE #endif #ifndef APP_MAX_CMDS #define APP_MAX_CMDS 64 #endif struct app_params { /* Config */ char app_name[APP_APPNAME_SIZE]; const char *config_file; const char *script_file; uint64_t port_mask; uint32_t log_level; struct app_eal_params eal_params; struct app_mempool_params mempool_params[APP_MAX_MEMPOOLS]; struct app_link_params link_params[APP_MAX_LINKS]; struct app_pktq_hwq_in_params hwq_in_params[APP_MAX_HWQ_IN]; struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT]; struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ]; struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM]; struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE]; struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK]; struct app_msgq_params msgq_params[APP_MAX_MSGQ]; struct app_pipeline_params pipeline_params[APP_MAX_PIPELINES]; uint32_t n_mempools; uint32_t n_links; uint32_t n_pktq_hwq_in; uint32_t n_pktq_hwq_out; uint32_t n_pktq_swq; uint32_t n_pktq_tm; uint32_t n_pktq_source; uint32_t n_pktq_sink; uint32_t n_msgq; uint32_t n_pipelines; /* Init */ char *eal_argv[1 + APP_EAL_ARGC]; struct cpu_core_map *core_map; uint64_t core_mask; struct rte_mempool *mempool[APP_MAX_MEMPOOLS]; struct rte_ring *swq[APP_MAX_PKTQ_SWQ]; struct rte_sched_port *tm[APP_MAX_PKTQ_TM]; struct rte_ring *msgq[APP_MAX_MSGQ]; struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES]; struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES]; struct app_thread_data thread_data[APP_MAX_THREADS]; cmdline_parse_ctx_t cmds[APP_MAX_CMDS + 1]; int eal_argc; uint32_t n_pipeline_types; uint32_t n_cmds; }; #define APP_PARAM_VALID(obj) ((obj)->name != NULL) #define APP_PARAM_COUNT(obj_array, n_objs) \ { \ size_t i; \ \ n_objs = 0; \ for (i = 0; i < RTE_DIM(obj_array); i++) \ if (APP_PARAM_VALID(&((obj_array)[i]))) \ n_objs++; \ } #define APP_PARAM_FIND(obj_array, key) \ ({ \ ssize_t obj_idx; \ const ssize_t obj_count = RTE_DIM(obj_array); \ \ for (obj_idx = 0; obj_idx < obj_count; obj_idx++) { \ if (!APP_PARAM_VALID(&((obj_array)[obj_idx]))) \ continue; \ \ if (strcmp(key, (obj_array)[obj_idx].name) == 0) \ break; \ } \ obj_idx < obj_count ? obj_idx : -ENOENT; \ }) #define APP_PARAM_FIND_BY_ID(obj_array, prefix, id, obj) \ do { \ char name[APP_PARAM_NAME_SIZE]; \ ssize_t pos; \ \ sprintf(name, prefix "%" PRIu32, id); \ pos = APP_PARAM_FIND(obj_array, name); \ obj = (pos < 0) ? NULL : &((obj_array)[pos]); \ } while (0) #define APP_PARAM_GET_ID(obj, prefix, id) \ do \ sscanf(obj->name, prefix "%" SCNu32, &id); \ while (0) \ #define APP_PARAM_ADD(obj_array, obj_name) \ ({ \ ssize_t obj_idx; \ const ssize_t obj_count = RTE_DIM(obj_array); \ \ obj_idx = APP_PARAM_FIND(obj_array, obj_name); \ if (obj_idx < 0) { \ for (obj_idx = 0; obj_idx < obj_count; obj_idx++) { \ if (!APP_PARAM_VALID(&((obj_array)[obj_idx]))) \ break; \ } \ \ if (obj_idx < obj_count) { \ (obj_array)[obj_idx].name = strdup(obj_name); \ if ((obj_array)[obj_idx].name == NULL) \ obj_idx = -EINVAL; \ } else \ obj_idx = -ENOMEM; \ } \ obj_idx; \ }) #define APP_CHECK(exp, fmt, ...) \ do { \ if (!(exp)) { \ fprintf(stderr, fmt "\n", ## __VA_ARGS__); \ abort(); \ } \ } while (0) enum app_log_level { APP_LOG_LEVEL_HIGH = 1, APP_LOG_LEVEL_LOW, APP_LOG_LEVELS }; #define APP_LOG(app, level, fmt, ...) \ do { \ if (app->log_level >= APP_LOG_LEVEL_ ## level) \ fprintf(stdout, "[APP] " fmt "\n", ## __VA_ARGS__); \ } while (0) static inline uint32_t app_link_get_n_rxq(struct app_params *app, struct app_link_params *link) { uint32_t n_rxq = 0, link_id, i; uint32_t n_pktq_hwq_in = RTE_MIN(app->n_pktq_hwq_in, RTE_DIM(app->hwq_in_params)); APP_PARAM_GET_ID(link, "LINK", link_id); for (i = 0; i < n_pktq_hwq_in; i++) { struct app_pktq_hwq_in_params *p = &app->hwq_in_params[i]; uint32_t rxq_link_id, rxq_queue_id; sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32, &rxq_link_id, &rxq_queue_id); if (rxq_link_id == link_id) n_rxq++; } return n_rxq; } static inline uint32_t app_link_get_n_txq(struct app_params *app, struct app_link_params *link) { uint32_t n_txq = 0, link_id, i; uint32_t n_pktq_hwq_out = RTE_MIN(app->n_pktq_hwq_out, RTE_DIM(app->hwq_out_params)); APP_PARAM_GET_ID(link, "LINK", link_id); for (i = 0; i < n_pktq_hwq_out; i++) { struct app_pktq_hwq_out_params *p = &app->hwq_out_params[i]; uint32_t txq_link_id, txq_queue_id; sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32, &txq_link_id, &txq_queue_id); if (txq_link_id == link_id) n_txq++; } return n_txq; } static inline uint32_t app_rxq_get_readers(struct app_params *app, struct app_pktq_hwq_in_params *rxq) { uint32_t pos = rxq - app->hwq_in_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_readers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); uint32_t j; for (j = 0; j < n_pktq_in; j++) { struct app_pktq_in_params *pktq = &p->pktq_in[j]; if ((pktq->type == APP_PKTQ_IN_HWQ) && (pktq->id == pos)) n_readers++; } } return n_readers; } static inline uint32_t app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq) { uint32_t pos = swq - app->swq_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_readers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); uint32_t j; for (j = 0; j < n_pktq_in; j++) { struct app_pktq_in_params *pktq = &p->pktq_in[j]; if ((pktq->type == APP_PKTQ_IN_SWQ) && (pktq->id == pos)) n_readers++; } } return n_readers; } static inline uint32_t app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) { uint32_t pos = tm - app->tm_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_readers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); uint32_t j; for (j = 0; j < n_pktq_in; j++) { struct app_pktq_in_params *pktq = &p->pktq_in[j]; if ((pktq->type == APP_PKTQ_IN_TM) && (pktq->id == pos)) n_readers++; } } return n_readers; } static inline uint32_t app_source_get_readers(struct app_params *app, struct app_pktq_source_params *source) { uint32_t pos = source - app->source_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_readers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); uint32_t j; for (j = 0; j < n_pktq_in; j++) { struct app_pktq_in_params *pktq = &p->pktq_in[j]; if ((pktq->type == APP_PKTQ_IN_SOURCE) && (pktq->id == pos)) n_readers++; } } return n_readers; } static inline uint32_t app_msgq_get_readers(struct app_params *app, struct app_msgq_params *msgq) { uint32_t pos = msgq - app->msgq_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_readers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_msgq_in = RTE_MIN(p->n_msgq_in, RTE_DIM(p->msgq_in)); uint32_t j; for (j = 0; j < n_msgq_in; j++) if (p->msgq_in[j] == pos) n_readers++; } return n_readers; } static inline uint32_t app_txq_get_writers(struct app_params *app, struct app_pktq_hwq_out_params *txq) { uint32_t pos = txq - app->hwq_out_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_writers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, RTE_DIM(p->pktq_out)); uint32_t j; for (j = 0; j < n_pktq_out; j++) { struct app_pktq_out_params *pktq = &p->pktq_out[j]; if ((pktq->type == APP_PKTQ_OUT_HWQ) && (pktq->id == pos)) n_writers++; } } return n_writers; } static inline uint32_t app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq) { uint32_t pos = swq - app->swq_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_writers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, RTE_DIM(p->pktq_out)); uint32_t j; for (j = 0; j < n_pktq_out; j++) { struct app_pktq_out_params *pktq = &p->pktq_out[j]; if ((pktq->type == APP_PKTQ_OUT_SWQ) && (pktq->id == pos)) n_writers++; } } return n_writers; } static inline uint32_t app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) { uint32_t pos = tm - app->tm_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_writers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, RTE_DIM(p->pktq_out)); uint32_t j; for (j = 0; j < n_pktq_out; j++) { struct app_pktq_out_params *pktq = &p->pktq_out[j]; if ((pktq->type == APP_PKTQ_OUT_TM) && (pktq->id == pos)) n_writers++; } } return n_writers; } static inline uint32_t app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink) { uint32_t pos = sink - app->sink_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_writers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, RTE_DIM(p->pktq_out)); uint32_t j; for (j = 0; j < n_pktq_out; j++) { struct app_pktq_out_params *pktq = &p->pktq_out[j]; if ((pktq->type == APP_PKTQ_OUT_SINK) && (pktq->id == pos)) n_writers++; } } return n_writers; } static inline uint32_t app_msgq_get_writers(struct app_params *app, struct app_msgq_params *msgq) { uint32_t pos = msgq - app->msgq_params; uint32_t n_pipelines = RTE_MIN(app->n_pipelines, RTE_DIM(app->pipeline_params)); uint32_t n_writers = 0, i; for (i = 0; i < n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; uint32_t n_msgq_out = RTE_MIN(p->n_msgq_out, RTE_DIM(p->msgq_out)); uint32_t j; for (j = 0; j < n_msgq_out; j++) if (p->msgq_out[j] == pos) n_writers++; } return n_writers; } static inline struct app_link_params * app_get_link_for_rxq(struct app_params *app, struct app_pktq_hwq_in_params *p) { char link_name[APP_PARAM_NAME_SIZE]; ssize_t link_param_idx; uint32_t rxq_link_id, rxq_queue_id; sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32, &rxq_link_id, &rxq_queue_id); sprintf(link_name, "LINK%" PRIu32, rxq_link_id); link_param_idx = APP_PARAM_FIND(app->link_params, link_name); APP_CHECK((link_param_idx >= 0), "Cannot find %s for %s", link_name, p->name); return &app->link_params[link_param_idx]; } static inline struct app_link_params * app_get_link_for_txq(struct app_params *app, struct app_pktq_hwq_out_params *p) { char link_name[APP_PARAM_NAME_SIZE]; ssize_t link_param_idx; uint32_t txq_link_id, txq_queue_id; sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32, &txq_link_id, &txq_queue_id); sprintf(link_name, "LINK%" PRIu32, txq_link_id); link_param_idx = APP_PARAM_FIND(app->link_params, link_name); APP_CHECK((link_param_idx >= 0), "Cannot find %s for %s", link_name, p->name); return &app->link_params[link_param_idx]; } static inline struct app_link_params * app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm) { char link_name[APP_PARAM_NAME_SIZE]; uint32_t link_id; ssize_t link_param_idx; sscanf(p_tm->name, "TM%" PRIu32, &link_id); sprintf(link_name, "LINK%" PRIu32, link_id); link_param_idx = APP_PARAM_FIND(app->link_params, link_name); APP_CHECK((link_param_idx >= 0), "Cannot find %s for %s", link_name, p_tm->name); return &app->link_params[link_param_idx]; } int app_config_init(struct app_params *app); int app_config_args(struct app_params *app, int argc, char **argv); int app_config_parse(struct app_params *app, const char *file_name); int app_config_parse_tm(struct app_params *app); void app_config_save(struct app_params *app, const char *file_name); int app_config_check(struct app_params *app); int app_init(struct app_params *app); int app_thread(void *arg); int app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype); struct pipeline_type *app_pipeline_type_find(struct app_params *app, char *name); void app_link_up_internal(struct app_params *app, struct app_link_params *cp); void app_link_down_internal(struct app_params *app, struct app_link_params *cp); #endif ================================================ FILE: examples/ip_pipeline/config/ip_pipeline.cfg ================================================ [PIPELINE0] type = MASTER core = 0 [PIPELINE1] type = PASS-THROUGH core = 1 pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 ================================================ FILE: examples/ip_pipeline/config/ip_pipeline.sh ================================================ # #run config/ip_pipeline.sh # p 1 ping ================================================ FILE: examples/ip_pipeline/config/tm_profile.cfg ================================================ ; BSD LICENSE ; ; Copyright(c) 2010-2014 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; This file enables the following hierarchical scheduler configuration for each ; 10GbE output port: ; * Single subport (subport 0): ; - Subport rate set to 100% of port rate ; - Each of the 4 traffic classes has rate set to 100% of port rate ; * 4K pipes per subport 0 (pipes 0 .. 4095) with identical configuration: ; - Pipe rate set to 1/4K of port rate ; - Each of the 4 traffic classes has rate set to 100% of pipe rate ; - Within each traffic class, the byte-level WRR weights for the 4 queues ; are set to 1:1:1:1 ; ; For more details, please refer to chapter "Quality of Service (QoS) Framework" ; of Intel Data Plane Development Kit (Intel DPDK) Programmer's Guide. ; Port configuration [port] frame overhead = 24 ; frame overhead = Preamble (7) + SFD (1) + FCS (4) + IFG (12) mtu = 1522; mtu = Q-in-Q MTU (FCS not included) number of subports per port = 1 number of pipes per subport = 4096 queue sizes = 64 64 64 64 ; Subport configuration [subport 0] tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes tc 0 rate = 1250000000 ; Bytes per second tc 1 rate = 1250000000 ; Bytes per second tc 2 rate = 1250000000 ; Bytes per second tc 3 rate = 1250000000 ; Bytes per second tc period = 10 ; Milliseconds pipe 0-4095 = 0 ; These pipes are configured with pipe profile 0 ; Pipe configuration [pipe profile 0] tb rate = 305175 ; Bytes per second tb size = 1000000 ; Bytes tc 0 rate = 305175 ; Bytes per second tc 1 rate = 305175 ; Bytes per second tc 2 rate = 305175 ; Bytes per second tc 3 rate = 305175 ; Bytes per second tc period = 40 ; Milliseconds tc 3 oversubscription weight = 1 tc 0 wrr weights = 1 1 1 1 tc 1 wrr weights = 1 1 1 1 tc 2 wrr weights = 1 1 1 1 tc 3 wrr weights = 1 1 1 1 ; RED params per traffic class and color (Green / Yellow / Red) [red] tc 0 wred min = 48 40 32 tc 0 wred max = 64 64 64 tc 0 wred inv prob = 10 10 10 tc 0 wred weight = 9 9 9 tc 1 wred min = 48 40 32 tc 1 wred max = 64 64 64 tc 1 wred inv prob = 10 10 10 tc 1 wred weight = 9 9 9 tc 2 wred min = 48 40 32 tc 2 wred max = 64 64 64 tc 2 wred inv prob = 10 10 10 tc 2 wred weight = 9 9 9 tc 3 wred min = 48 40 32 tc 3 wred max = 64 64 64 tc 3 wred inv prob = 10 10 10 tc 3 wred weight = 9 9 9 ================================================ FILE: examples/ip_pipeline/config_check.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "app.h" static void check_mempools(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_mempools; i++) { struct app_mempool_params *p = &app->mempool_params[i]; APP_CHECK((p->pool_size > 0), "Mempool %s size is 0\n", p->name); APP_CHECK((p->cache_size > 0), "Mempool %s cache size is 0\n", p->name); APP_CHECK(rte_is_power_of_2(p->cache_size), "Mempool %s cache size not a power of 2\n", p->name); } } static void check_links(struct app_params *app) { uint32_t n_links_port_mask = __builtin_popcountll(app->port_mask); uint32_t i; /* Check that number of links matches the port mask */ APP_CHECK((app->n_links == n_links_port_mask), "Not enough links provided in the PORT_MASK\n"); for (i = 0; i < app->n_links; i++) { struct app_link_params *link = &app->link_params[i]; uint32_t rxq_max, n_rxq, n_txq, link_id, i; APP_PARAM_GET_ID(link, "LINK", link_id); /* Check that link RXQs are contiguous */ rxq_max = 0; if (link->arp_q > rxq_max) rxq_max = link->arp_q; if (link->tcp_syn_local_q > rxq_max) rxq_max = link->tcp_syn_local_q; if (link->ip_local_q > rxq_max) rxq_max = link->ip_local_q; if (link->tcp_local_q > rxq_max) rxq_max = link->tcp_local_q; if (link->udp_local_q > rxq_max) rxq_max = link->udp_local_q; if (link->sctp_local_q > rxq_max) rxq_max = link->sctp_local_q; for (i = 1; i <= rxq_max; i++) APP_CHECK(((link->arp_q == i) || (link->tcp_syn_local_q == i) || (link->ip_local_q == i) || (link->tcp_local_q == i) || (link->udp_local_q == i) || (link->sctp_local_q == i)), "%s RXQs are not contiguous (A)\n", link->name); n_rxq = app_link_get_n_rxq(app, link); APP_CHECK((n_rxq == rxq_max + 1), "%s RXQs are not contiguous (B)\n", link->name); for (i = 0; i < n_rxq; i++) { char name[APP_PARAM_NAME_SIZE]; int pos; sprintf(name, "RXQ%" PRIu32 ".%" PRIu32, link_id, i); pos = APP_PARAM_FIND(app->hwq_in_params, name); APP_CHECK((pos >= 0), "%s RXQs are not contiguous (C)\n", link->name); } /* Check that link RXQs are contiguous */ n_txq = app_link_get_n_txq(app, link); for (i = 0; i < n_txq; i++) { char name[APP_PARAM_NAME_SIZE]; int pos; sprintf(name, "TXQ%" PRIu32 ".%" PRIu32, link_id, i); pos = APP_PARAM_FIND(app->hwq_out_params, name); APP_CHECK((pos >= 0), "%s TXQs are not contiguous\n", link->name); } } } static void check_rxqs(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_hwq_in; i++) { struct app_pktq_hwq_in_params *p = &app->hwq_in_params[i]; uint32_t n_readers = app_rxq_get_readers(app, p); APP_CHECK((p->size > 0), "%s size is 0\n", p->name); APP_CHECK((rte_is_power_of_2(p->size)), "%s size is not a power of 2\n", p->name); APP_CHECK((p->burst > 0), "%s burst size is 0\n", p->name); APP_CHECK((p->burst <= p->size), "%s burst size is bigger than its size\n", p->name); APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); APP_CHECK((n_readers == 1), "%s has more than one reader\n", p->name); } } static void check_txqs(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_hwq_out; i++) { struct app_pktq_hwq_out_params *p = &app->hwq_out_params[i]; uint32_t n_writers = app_txq_get_writers(app, p); APP_CHECK((p->size > 0), "%s size is 0\n", p->name); APP_CHECK((rte_is_power_of_2(p->size)), "%s size is not a power of 2\n", p->name); APP_CHECK((p->burst > 0), "%s burst size is 0\n", p->name); APP_CHECK((p->burst <= p->size), "%s burst size is bigger than its size\n", p->name); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); APP_CHECK((n_writers == 1), "%s has more than one writer\n", p->name); } } static void check_swqs(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_swq; i++) { struct app_pktq_swq_params *p = &app->swq_params[i]; uint32_t n_readers = app_swq_get_readers(app, p); uint32_t n_writers = app_swq_get_writers(app, p); APP_CHECK((p->size > 0), "%s size is 0\n", p->name); APP_CHECK((rte_is_power_of_2(p->size)), "%s size is not a power of 2\n", p->name); APP_CHECK((p->burst_read > 0), "%s read burst size is 0\n", p->name); APP_CHECK((p->burst_read <= p->size), "%s read burst size is bigger than its size\n", p->name); APP_CHECK((p->burst_write > 0), "%s write burst size is 0\n", p->name); APP_CHECK((p->burst_write <= p->size), "%s write burst size is bigger than its size\n", p->name); APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); APP_CHECK((n_readers == 1), "%s has more than one reader\n", p->name); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); APP_CHECK((n_writers == 1), "%s has more than one writer\n", p->name); } } static void check_tms(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_tm; i++) { struct app_pktq_tm_params *p = &app->tm_params[i]; uint32_t n_readers = app_tm_get_readers(app, p); uint32_t n_writers = app_tm_get_writers(app, p); APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); APP_CHECK((n_readers == 1), "%s has more than one reader\n", p->name); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); APP_CHECK((n_writers == 1), "%s has more than one writer\n", p->name); } } static void check_sources(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_source; i++) { struct app_pktq_source_params *p = &app->source_params[i]; uint32_t n_readers = app_source_get_readers(app, p); APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); APP_CHECK((n_readers == 1), "%s has more than one reader\n", p->name); } } static void check_sinks(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_sink; i++) { struct app_pktq_sink_params *p = &app->sink_params[i]; uint32_t n_writers = app_sink_get_writers(app, p); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); APP_CHECK((n_writers == 1), "%s has more than one writer\n", p->name); } } static void check_msgqs(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_msgq; i++) { struct app_msgq_params *p = &app->msgq_params[i]; uint32_t n_readers = app_msgq_get_readers(app, p); uint32_t n_writers = app_msgq_get_writers(app, p); uint32_t msgq_req_pipeline, msgq_rsp_pipeline; uint32_t msgq_req_core, msgq_rsp_core; APP_CHECK((p->size > 0), "%s size is 0\n", p->name); APP_CHECK((rte_is_power_of_2(p->size)), "%s size is not a power of 2\n", p->name); msgq_req_pipeline = (strncmp(p->name, "MSGQ-REQ-PIPELINE", strlen("MSGQ-REQ-PIPELINE")) == 0); msgq_rsp_pipeline = (strncmp(p->name, "MSGQ-RSP-PIPELINE", strlen("MSGQ-RSP-PIPELINE")) == 0); msgq_req_core = (strncmp(p->name, "MSGQ-REQ-CORE", strlen("MSGQ-REQ-CORE")) == 0); msgq_rsp_core = (strncmp(p->name, "MSGQ-RSP-CORE", strlen("MSGQ-RSP-CORE")) == 0); if ((msgq_req_pipeline == 0) && (msgq_rsp_pipeline == 0) && (msgq_req_core == 0) && (msgq_rsp_core == 0)) { APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); APP_CHECK((n_readers == 1), "%s has more than one reader\n", p->name); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); APP_CHECK((n_writers == 1), "%s has more than one writer\n", p->name); } if (msgq_req_pipeline) { struct app_pipeline_params *pipeline; uint32_t pipeline_id; APP_PARAM_GET_ID(p, "MSGQ-REQ-PIPELINE", pipeline_id); APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pipeline); APP_CHECK((pipeline != NULL), "%s is not associated with a valid pipeline\n", p->name); } if (msgq_rsp_pipeline) { struct app_pipeline_params *pipeline; uint32_t pipeline_id; APP_PARAM_GET_ID(p, "MSGQ-RSP-PIPELINE", pipeline_id); APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pipeline); APP_CHECK((pipeline != NULL), "%s is not associated with a valid pipeline\n", p->name); } } } static void check_pipelines(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; APP_CHECK((p->n_msgq_in == p->n_msgq_out), "%s number of input MSGQs does not match " "the number of output MSGQs\n", p->name); } } int app_config_check(struct app_params *app) { check_mempools(app); check_links(app); check_rxqs(app); check_txqs(app); check_swqs(app); check_tms(app); check_sources(app); check_sinks(app); check_msgqs(app); check_pipelines(app); return 0; } ================================================ FILE: examples/ip_pipeline/config_parse.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" /** * Default config values **/ static struct app_params app_params_default = { .config_file = "./config/ip_pipeline.cfg", .log_level = APP_LOG_LEVEL_HIGH, .eal_params = { .channels = 4, }, }; static const struct app_mempool_params mempool_params_default = { .parsed = 0, .buffer_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM, .pool_size = 32 * 1024, .cache_size = 256, .cpu_socket_id = 0, }; static const struct app_link_params link_params_default = { .parsed = 0, .pmd_id = 0, .arp_q = 0, .tcp_syn_local_q = 0, .ip_local_q = 0, .tcp_local_q = 0, .udp_local_q = 0, .sctp_local_q = 0, .state = 0, .ip = 0, .depth = 0, .mac_addr = 0, .conf = { .link_speed = 0, .link_duplex = 0, .rxmode = { .mq_mode = ETH_MQ_RX_NONE, .header_split = 0, /* Header split */ .hw_ip_checksum = 0, /* IP checksum offload */ .hw_vlan_filter = 0, /* VLAN filtering */ .hw_vlan_strip = 0, /* VLAN strip */ .hw_vlan_extend = 0, /* Extended VLAN */ .jumbo_frame = 0, /* Jumbo frame support */ .hw_strip_crc = 0, /* CRC strip by HW */ .enable_scatter = 0, /* Scattered packets RX handler */ .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ .split_hdr_size = 0, /* Header split buffer size */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .lpbk_mode = 0, }, .promisc = 1, }; static const struct app_pktq_hwq_in_params default_hwq_in_params = { .parsed = 0, .mempool_id = 0, .size = 128, .burst = 32, .conf = { .rx_thresh = { .pthresh = 8, .hthresh = 8, .wthresh = 4, }, .rx_free_thresh = 64, .rx_drop_en = 0, .rx_deferred_start = 0, } }; static const struct app_pktq_hwq_out_params default_hwq_out_params = { .parsed = 0, .size = 512, .burst = 32, .dropless = 0, .n_retries = 0, .conf = { .tx_thresh = { .pthresh = 36, .hthresh = 0, .wthresh = 0, }, .tx_rs_thresh = 0, .tx_free_thresh = 0, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, .tx_deferred_start = 0, } }; static const struct app_pktq_swq_params default_swq_params = { .parsed = 0, .size = 256, .burst_read = 32, .burst_write = 32, .dropless = 0, .n_retries = 0, .cpu_socket_id = 0, }; struct app_pktq_tm_params default_tm_params = { .parsed = 0, .file_name = "./config/tm_profile.cfg", .burst_read = 64, .burst_write = 32, }; struct app_pktq_source_params default_source_params = { .parsed = 0, .mempool_id = 0, .burst = 32, }; struct app_pktq_sink_params default_sink_params = { .parsed = 0, }; struct app_msgq_params default_msgq_params = { .parsed = 0, .size = 64, .cpu_socket_id = 0, }; struct app_pipeline_params default_pipeline_params = { .parsed = 0, .socket_id = 0, .core_id = 0, .hyper_th_id = 0, .n_pktq_in = 0, .n_pktq_out = 0, .n_msgq_in = 0, .n_msgq_out = 0, .timer_period = 1, .n_args = 0, }; static const char app_usage[] = "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK " "[-l LOG_LEVEL]\n" "\n" "Arguments:\n" "\t-f CONFIG_FILE: Default config file is %s\n" "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n" "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n" "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n" "\n"; static void app_print_usage(char *prgname) { rte_exit(0, app_usage, prgname, app_params_default.config_file); } #define skip_white_spaces(pos) \ ({ \ __typeof__(pos) _p = (pos); \ for ( ; isspace(*_p); _p++); \ _p; \ }) #define PARSER_IMPLICIT_PARAM_ADD_CHECK(result, section_name) \ do { \ APP_CHECK((result != -EINVAL), \ "CFG: [%s] name too long", section_name); \ APP_CHECK(result != -ENOMEM, \ "CFG: [%s] too much sections", section_name); \ APP_CHECK(result >= 0, \ "CFG: [%s] Unknown error while adding '%s'", \ section_name, section_name); \ } while (0) #define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \ do { \ APP_CHECK((result != -EINVAL), \ "CFG: [%s] name too long", section_name); \ APP_CHECK((result != -ENOMEM), \ "CFG: [%s] too much sections", section_name); \ APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\ "CFG: [%s] duplicate section", section_name); \ APP_CHECK((result >= 0), \ "CFG: [%s] Unknown error while adding '%s'", \ section_name, section_name); \ } while (0) static int parser_read_arg_bool(const char *p) { p = skip_white_spaces(p); int result = -EINVAL; if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { p += 3; result = 1; } if (((p[0] == 'o') && (p[1] == 'n')) || ((p[0] == 'O') && (p[1] == 'N'))) { p += 2; result = 1; } if (((p[0] == 'n') && (p[1] == 'o')) || ((p[0] == 'N') && (p[1] == 'O'))) { p += 2; result = 0; } if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { p += 3; result = 0; } p = skip_white_spaces(p); if (p[0] != '\0') return -EINVAL; return result; } #define PARSE_ERROR(exp, section, entry) \ APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry) #define PARSE_ERROR_MALLOC(exp) \ APP_CHECK(exp, "Parse error: no free memory\n") #define PARSE_ERROR_SECTION(exp, section) \ APP_CHECK(exp, "Parse error in section \"%s\"", section) #define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section) \ APP_CHECK(exp, "Parse error in section \"%s\": no entries\n", section) #define PARSE_WARNING_IGNORED(exp, section, entry) \ do \ if (!(exp)) \ fprintf(stderr, "Parse warning in section \"%s\": " \ "entry \"%s\" is ignored\n", section, entry); \ while (0) #define PARSE_ERROR_INVALID(exp, section, entry) \ APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\ section, entry) #define PARSE_ERROR_DUPLICATE(exp, section, entry) \ APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\ section, entry) static int parser_read_uint64(uint64_t *value, const char *p) { char *next; uint64_t val; p = skip_white_spaces(p); if (!isdigit(*p)) return -EINVAL; val = strtoul(p, &next, 10); if (p == next) return -EINVAL; p = next; switch (*p) { case 'T': val *= 1024ULL; /* fall trought */ case 'G': val *= 1024ULL; /* fall trought */ case 'M': val *= 1024ULL; /* fall trought */ case 'k': case 'K': val *= 1024ULL; p++; break; } p = skip_white_spaces(p); if (*p != '\0') return -EINVAL; *value = val; return 0; } static int parser_read_uint32(uint32_t *value, const char *p) { uint64_t val = 0; int ret = parser_read_uint64(&val, p); if (ret < 0) return ret; else if (val > UINT32_MAX) return -ERANGE; *value = val; return 0; } static int parse_pipeline_core(uint32_t *socket, uint32_t *core, uint32_t *ht, const char *entry) { size_t num_len; char num[8]; uint32_t s = 0, c = 0, h = 0, val; uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; const char *next = skip_white_spaces(entry); char type; /* Expect or [sX][cY][h]. At least one parameter is required. */ while (*next != '\0') { /* If everything parsed nothing should left */ if (s_parsed && c_parsed && h_parsed) return -EINVAL; type = *next; switch (type) { case 's': case 'S': if (s_parsed || c_parsed || h_parsed) return -EINVAL; s_parsed = 1; next++; break; case 'c': case 'C': if (c_parsed || h_parsed) return -EINVAL; c_parsed = 1; next++; break; case 'h': case 'H': if (h_parsed) return -EINVAL; h_parsed = 1; next++; break; default: /* If it start from digit it must be only core id. */ if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) return -EINVAL; type = 'C'; } for (num_len = 0; *next != '\0'; next++, num_len++) { if (num_len == RTE_DIM(num)) return -EINVAL; if (!isdigit(*next)) break; num[num_len] = *next; } if (num_len == 0 && type != 'h' && type != 'H') return -EINVAL; if (num_len != 0 && (type == 'h' || type == 'H')) return -EINVAL; num[num_len] = '\0'; val = strtol(num, NULL, 10); h = 0; switch (type) { case 's': case 'S': s = val; break; case 'c': case 'C': c = val; break; case 'h': case 'H': h = 1; break; } } *socket = s; *core = c; *ht = h; return 0; } static size_t skip_digits(const char *src) { size_t i; for (i = 0; isdigit(src[i]); i++); return i; } static int validate_name(const char *name, const char *prefix, int num) { size_t i, j; for (i = 0; (name[i] != '\0') && (prefix[i] != '\0'); i++) { if (name[i] != prefix[i]) return -1; } if (prefix[i] != '\0') return -1; if (!num) { if (name[i] != '\0') return -1; else return 0; } if (num == 2) { j = skip_digits(&name[i]); i += j; if ((j == 0) || (name[i] != '.')) return -1; i++; } if (num == 1) { j = skip_digits(&name[i]); i += j; if ((j == 0) || (name[i] != '\0')) return -1; } return 0; } static void parse_eal(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_eal_params *p = &app->eal_params; struct rte_cfgfile_entry *entries; int n_entries, i; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *entry = &entries[i]; /* coremask */ if (strcmp(entry->name, "c") == 0) { PARSE_WARNING_IGNORED(0, section_name, entry->name); continue; } /* corelist */ if (strcmp(entry->name, "l") == 0) { PARSE_WARNING_IGNORED(0, section_name, entry->name); continue; } /* coremap */ if (strcmp(entry->name, "lcores") == 0) { PARSE_ERROR_DUPLICATE((p->coremap == NULL), section_name, entry->name); p->coremap = strdup(entry->value); continue; } /* master_lcore */ if (strcmp(entry->name, "master_lcore") == 0) { int status; PARSE_ERROR_DUPLICATE((p->master_lcore_present == 0), section_name, entry->name); p->master_lcore_present = 1; status = parser_read_uint32(&p->master_lcore, entry->value); PARSE_ERROR((status == 0), section_name, entry->name); continue; } /* channels */ if (strcmp(entry->name, "n") == 0) { int status; PARSE_ERROR_DUPLICATE((p->channels_present == 0), section_name, entry->name); p->channels_present = 1; status = parser_read_uint32(&p->channels, entry->value); PARSE_ERROR((status == 0), section_name, entry->name); continue; } /* memory */ if (strcmp(entry->name, "m") == 0) { int status; PARSE_ERROR_DUPLICATE((p->memory_present == 0), section_name, entry->name); p->memory_present = 1; status = parser_read_uint32(&p->memory, entry->value); PARSE_ERROR((status == 0), section_name, entry->name); continue; } /* ranks */ if (strcmp(entry->name, "r") == 0) { int status; PARSE_ERROR_DUPLICATE((p->ranks_present == 0), section_name, entry->name); p->ranks_present = 1; status = parser_read_uint32(&p->ranks, entry->value); PARSE_ERROR((status == 0), section_name, entry->name); continue; } /* pci_blacklist */ if ((strcmp(entry->name, "pci_blacklist") == 0) || (strcmp(entry->name, "b") == 0)) { PARSE_ERROR_DUPLICATE((p->pci_blacklist == NULL), section_name, entry->name); p->pci_blacklist = strdup(entry->value); continue; } /* pci_whitelist */ if ((strcmp(entry->name, "pci_whitelist") == 0) || (strcmp(entry->name, "w") == 0)) { PARSE_ERROR_DUPLICATE((p->pci_whitelist == NULL), section_name, entry->name); p->pci_whitelist = strdup(entry->value); continue; } /* vdev */ if (strcmp(entry->name, "vdev") == 0) { PARSE_ERROR_DUPLICATE((p->vdev == NULL), section_name, entry->name); p->vdev = strdup(entry->value); continue; } /* vmware_tsc_map */ if (strcmp(entry->name, "vmware_tsc_map") == 0) { int val; PARSE_ERROR_DUPLICATE((p->vmware_tsc_map_present == 0), section_name, entry->name); p->vmware_tsc_map_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->vmware_tsc_map = val; continue; } /* proc_type */ if (strcmp(entry->name, "proc_type") == 0) { PARSE_ERROR_DUPLICATE((p->proc_type == NULL), section_name, entry->name); p->proc_type = strdup(entry->value); continue; } /* syslog */ if (strcmp(entry->name, "syslog") == 0) { PARSE_ERROR_DUPLICATE((p->syslog == NULL), section_name, entry->name); p->syslog = strdup(entry->value); continue; } /* log_level */ if (strcmp(entry->name, "log_level") == 0) { int status; PARSE_ERROR_DUPLICATE((p->log_level_present == 0), section_name, entry->name); p->log_level_present = 1; status = parser_read_uint32(&p->log_level, entry->value); PARSE_ERROR((status == 0), section_name, entry->name); continue; } /* version */ if (strcmp(entry->name, "v") == 0) { int val; PARSE_ERROR_DUPLICATE((p->version_present == 0), section_name, entry->name); p->version_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->version = val; continue; } /* help */ if ((strcmp(entry->name, "help") == 0) || (strcmp(entry->name, "h") == 0)) { int val; PARSE_ERROR_DUPLICATE((p->help_present == 0), section_name, entry->name); p->help_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->help = val; continue; } /* no_huge */ if (strcmp(entry->name, "no_huge") == 0) { int val; PARSE_ERROR_DUPLICATE((p->no_huge_present == 0), section_name, entry->name); p->no_huge_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->no_huge = val; continue; } /* no_pci */ if (strcmp(entry->name, "no_pci") == 0) { int val; PARSE_ERROR_DUPLICATE((p->no_pci_present == 0), section_name, entry->name); p->no_pci_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->no_pci = val; continue; } /* no_hpet */ if (strcmp(entry->name, "no_hpet") == 0) { int val; PARSE_ERROR_DUPLICATE((p->no_hpet_present == 0), section_name, entry->name); p->no_hpet_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->no_hpet = val; continue; } /* no_shconf */ if (strcmp(entry->name, "no_shconf") == 0) { int val; PARSE_ERROR_DUPLICATE((p->no_shconf_present == 0), section_name, entry->name); p->no_shconf_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->no_shconf = val; continue; } /* add_driver */ if (strcmp(entry->name, "d") == 0) { PARSE_ERROR_DUPLICATE((p->add_driver == NULL), section_name, entry->name); p->add_driver = strdup(entry->value); continue; } /* socket_mem */ if (strcmp(entry->name, "socket_mem") == 0) { PARSE_ERROR_DUPLICATE((p->socket_mem == NULL), section_name, entry->name); p->socket_mem = strdup(entry->value); continue; } /* huge_dir */ if (strcmp(entry->name, "huge_dir") == 0) { PARSE_ERROR_DUPLICATE((p->huge_dir == NULL), section_name, entry->name); p->huge_dir = strdup(entry->value); continue; } /* file_prefix */ if (strcmp(entry->name, "file_prefix") == 0) { PARSE_ERROR_DUPLICATE((p->file_prefix == NULL), section_name, entry->name); p->file_prefix = strdup(entry->value); continue; } /* base_virtaddr */ if (strcmp(entry->name, "base_virtaddr") == 0) { PARSE_ERROR_DUPLICATE((p->base_virtaddr == NULL), section_name, entry->name); p->base_virtaddr = strdup(entry->value); continue; } /* create_uio_dev */ if (strcmp(entry->name, "create_uio_dev") == 0) { int val; PARSE_ERROR_DUPLICATE((p->create_uio_dev_present == 0), section_name, entry->name); p->create_uio_dev_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->create_uio_dev = val; continue; } /* vfio_intr */ if (strcmp(entry->name, "vfio_intr") == 0) { PARSE_ERROR_DUPLICATE((p->vfio_intr == NULL), section_name, entry->name); p->vfio_intr = strdup(entry->value); continue; } /* xen_dom0 */ if (strcmp(entry->name, "xen_dom0") == 0) { int val; PARSE_ERROR_DUPLICATE((p->xen_dom0_present == 0), section_name, entry->name); p->xen_dom0_present = 1; val = parser_read_arg_bool(entry->value); PARSE_ERROR((val >= 0), section_name, entry->name); p->xen_dom0 = val; continue; } /* unrecognized */ PARSE_ERROR_INVALID(0, section_name, entry->name); } free(entries); } static int parse_pipeline_pktq_in(struct app_params *app, struct app_pipeline_params *p, const char *value) { const char *next = value; char *end; char name[APP_PARAM_NAME_SIZE]; size_t name_len; while (*next != '\0') { enum app_pktq_in_type type; int id; end = strchr(next, ' '); if (!end) name_len = strlen(next); else name_len = end - next; if (name_len == 0 || name_len == sizeof(name)) return -EINVAL; strncpy(name, next, name_len); name[name_len] = '\0'; next += name_len; if (*next != '\0') next++; if (validate_name(name, "RXQ", 2) == 0) { type = APP_PKTQ_IN_HWQ; id = APP_PARAM_ADD(app->hwq_in_params, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_IN_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_IN_TM; id = APP_PARAM_ADD(app->tm_params, name); } else if (validate_name(name, "SOURCE", 1) == 0) { type = APP_PKTQ_IN_SOURCE; id = APP_PARAM_ADD(app->source_params, name); } else return -EINVAL; if (id < 0) return id; p->pktq_in[p->n_pktq_in].type = type; p->pktq_in[p->n_pktq_in].id = (uint32_t) id; p->n_pktq_in++; } return 0; } static int parse_pipeline_pktq_out(struct app_params *app, struct app_pipeline_params *p, const char *value) { const char *next = value; char *end; char name[APP_PARAM_NAME_SIZE]; size_t name_len; while (*next != '\0') { enum app_pktq_out_type type; int id; end = strchr(next, ' '); if (!end) name_len = strlen(next); else name_len = end - next; if (name_len == 0 || name_len == sizeof(name)) return -EINVAL; strncpy(name, next, name_len); name[name_len] = '\0'; next += name_len; if (*next != '\0') next++; if (validate_name(name, "TXQ", 2) == 0) { type = APP_PKTQ_OUT_HWQ; id = APP_PARAM_ADD(app->hwq_out_params, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_OUT_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_OUT_TM; id = APP_PARAM_ADD(app->tm_params, name); } else if (validate_name(name, "SINK", 1) == 0) { type = APP_PKTQ_OUT_SINK; id = APP_PARAM_ADD(app->sink_params, name); } else return -EINVAL; if (id < 0) return id; p->pktq_out[p->n_pktq_out].type = type; p->pktq_out[p->n_pktq_out].id = id; p->n_pktq_out++; } return 0; } static int parse_pipeline_msgq_in(struct app_params *app, struct app_pipeline_params *p, const char *value) { const char *next = value; char *end; char name[APP_PARAM_NAME_SIZE]; size_t name_len; ssize_t idx; while (*next != '\0') { end = strchr(next, ' '); if (!end) name_len = strlen(next); else name_len = end - next; if (name_len == 0 || name_len == sizeof(name)) return -EINVAL; strncpy(name, next, name_len); name[name_len] = '\0'; next += name_len; if (*next != '\0') next++; if (validate_name(name, "MSGQ", 1) != 0) return -EINVAL; idx = APP_PARAM_ADD(app->msgq_params, name); if (idx < 0) return idx; p->msgq_in[p->n_msgq_in] = idx; p->n_msgq_in++; } return 0; } static int parse_pipeline_msgq_out(struct app_params *app, struct app_pipeline_params *p, const char *value) { const char *next = value; char *end; char name[APP_PARAM_NAME_SIZE]; size_t name_len; ssize_t idx; while (*next != '\0') { end = strchr(next, ' '); if (!end) name_len = strlen(next); else name_len = end - next; if (name_len == 0 || name_len == sizeof(name)) return -EINVAL; strncpy(name, next, name_len); name[name_len] = '\0'; next += name_len; if (*next != '\0') next++; if (validate_name(name, "MSGQ", 1) != 0) return -EINVAL; idx = APP_PARAM_ADD(app->msgq_params, name); if (idx < 0) return idx; p->msgq_out[p->n_msgq_out] = idx; p->n_msgq_out++; } return 0; } static void parse_pipeline(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { char name[CFG_NAME_LEN]; struct app_pipeline_params *param; struct rte_cfgfile_entry *entries; ssize_t param_idx; int n_entries, ret, i; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->pipeline_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name); param = &app->pipeline_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; if (strcmp(ent->name, "type") == 0) { ret = snprintf(param->type, RTE_DIM(param->type), "%s", ent->value); if ((ret > 0) && (ret < (int)RTE_DIM(param->type))) ret = 0; else ret = -EINVAL; } else if (strcmp(ent->name, "core") == 0) ret = parse_pipeline_core(¶m->socket_id, ¶m->core_id, ¶m->hyper_th_id, ent->value); else if (strcmp(ent->name, "pktq_in") == 0) ret = parse_pipeline_pktq_in(app, param, ent->value); else if (strcmp(ent->name, "pktq_out") == 0) ret = parse_pipeline_pktq_out(app, param, ent->value); else if (strcmp(ent->name, "msgq_in") == 0) ret = parse_pipeline_msgq_in(app, param, ent->value); else if (strcmp(ent->name, "msgq_out") == 0) ret = parse_pipeline_msgq_out(app, param, ent->value); else if (strcmp(ent->name, "timer_period") == 0) ret = parser_read_uint32(¶m->timer_period, ent->value); else { param->args_name[param->n_args] = strdup(ent->name); param->args_value[param->n_args] = strdup(ent->value); APP_CHECK((param->args_name[param->n_args] != NULL) && (param->args_value[param->n_args] != NULL), "CFG: [%s] out of memory", section_name); param->n_args++; ret = 0; } APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_in[param->n_msgq_in++] = param_idx; snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_out[param->n_msgq_out++] = param_idx; snprintf(name, sizeof(name), "MSGQ-REQ-CORE-s%" PRIu32 "c%" PRIu32 "%s", param->socket_id, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", param->socket_id, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; free(entries); } static void parse_mempool(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_mempool_params *param; struct rte_cfgfile_entry *entries; ssize_t param_idx; int n_entries, ret, i; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->mempool_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name); param = &app->mempool_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "buffer_size") == 0) ret = parser_read_uint32(¶m->buffer_size, ent->value); else if (strcmp(ent->name, "pool_size") == 0) ret = parser_read_uint32(¶m->pool_size, ent->value); else if (strcmp(ent->name, "cache_size") == 0) ret = parser_read_uint32(¶m->cache_size, ent->value); else if (strcmp(ent->name, "cpu") == 0) ret = parser_read_uint32(¶m->cpu_socket_id, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_link(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_link_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->link_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name); param = &app->link_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "arp_q") == 0) ret = parser_read_uint32(¶m->arp_q, ent->value); else if (strcmp(ent->name, "tcp_syn_q") == 0) ret = parser_read_uint32(¶m->tcp_syn_local_q, ent->value); else if (strcmp(ent->name, "ip_local_q") == 0) ret = parser_read_uint32(¶m->ip_local_q, ent->value); else if (strcmp(ent->name, "tcp_local_q") == 0) ret = parser_read_uint32(¶m->tcp_local_q, ent->value); else if (strcmp(ent->name, "udp_local_q") == 0) ret = parser_read_uint32(¶m->udp_local_q, ent->value); else if (strcmp(ent->name, "sctp_local_q") == 0) ret = parser_read_uint32(¶m->sctp_local_q, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_rxq(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_pktq_hwq_in_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name); param = &app->hwq_in_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "mempool") == 0) { int status = validate_name(ent->value, "MEMPOOL", 1); ssize_t idx; APP_CHECK((status == 0), "CFG: [%s] entry '%s': invalid mempool\n", section_name, ent->name); idx = APP_PARAM_ADD(app->mempool_params, ent->value); PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); param->mempool_id = idx; ret = 0; } else if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); else if (strcmp(ent->name, "burst") == 0) ret = parser_read_uint32(¶m->burst, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_txq(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_pktq_hwq_out_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name); param = &app->hwq_out_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); else if (strcmp(ent->name, "burst") == 0) ret = parser_read_uint32(¶m->burst, ent->value); else if (strcmp(ent->name, "dropless") == 0) { ret = parser_read_arg_bool(ent->value); if (ret >= 0) { param->dropless = ret; ret = 0; } } APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_swq(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_pktq_swq_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->swq_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name); param = &app->swq_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); else if (strcmp(ent->name, "burst_read") == 0) ret = parser_read_uint32(¶m->burst_read, ent->value); else if (strcmp(ent->name, "burst_write") == 0) ret = parser_read_uint32(¶m->burst_write, ent->value); else if (strcmp(ent->name, "dropless") == 0) { ret = parser_read_arg_bool(ent->value); if (ret >= 0) { param->dropless = ret; ret = 0; } } else if (strcmp(ent->name, "n_retries") == 0) ret = parser_read_uint64(¶m->n_retries, ent->value); else if (strcmp(ent->name, "cpu") == 0) ret = parser_read_uint32(¶m->cpu_socket_id, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_tm(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_pktq_tm_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->tm_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name); param = &app->tm_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "cfg") == 0) { param->file_name = strdup(ent->value); if (param->file_name == NULL) ret = -EINVAL; ret = 0; } else if (strcmp(ent->name, "burst_read") == 0) ret = parser_read_uint32(¶m->burst_read, ent->value); else if (strcmp(ent->name, "burst_write") == 0) ret = parser_read_uint32(¶m->burst_write, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret != -EBADF, "CFG: [%s] entry '%s': TM cfg parse error '%s'\n", section_name, ent->name, ent->value); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_source(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_pktq_source_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->source_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name); param = &app->source_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "mempool") == 0) { int status = validate_name(ent->value, "MEMPOOL", 1); ssize_t idx; APP_CHECK((status == 0), "CFG: [%s] entry '%s': invalid mempool\n", section_name, ent->name); idx = APP_PARAM_ADD(app->mempool_params, ent->value); PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); param->mempool_id = idx; ret = 0; } else if (strcmp(ent->name, "burst") == 0) ret = parser_read_uint32(¶m->burst, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_msgq_req_pipeline(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_msgq_rsp_pipeline(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } static void parse_msgq(struct app_params *app, const char *section_name, struct rte_cfgfile *cfg) { struct app_msgq_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); PARSE_ERROR_MALLOC(entries != NULL); rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); param = &app->msgq_params[param_idx]; param->parsed = 1; for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; ret = -ESRCH; if (strcmp(ent->name, "size") == 0) ret = parser_read_uint32(¶m->size, ent->value); else if (strcmp(ent->name, "cpu") == 0) ret = parser_read_uint32(¶m->cpu_socket_id, ent->value); APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", section_name, ent->name); APP_CHECK(ret == 0, "CFG: [%s] entry '%s': Invalid value '%s'\n", section_name, ent->name, ent->value); } free(entries); } typedef void (*config_section_load)(struct app_params *p, const char *section_name, struct rte_cfgfile *cfg); struct config_section { const char prefix[CFG_NAME_LEN]; int numbers; config_section_load load; }; static const struct config_section cfg_file_scheme[] = { {"EAL", 0, parse_eal}, {"PIPELINE", 1, parse_pipeline}, {"MEMPOOL", 1, parse_mempool}, {"LINK", 1, parse_link}, {"RXQ", 2, parse_rxq}, {"TXQ", 2, parse_txq}, {"SWQ", 1, parse_swq}, {"TM", 1, parse_tm}, {"SOURCE", 1, parse_source}, {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline}, {"MSGQ-RSP-PIPELINE", 1, parse_msgq_rsp_pipeline}, {"MSGQ", 1, parse_msgq}, }; static void create_implicit_mempools(struct app_params *app) { ssize_t idx; idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, "start-up"); } static void parse_port_mask(struct app_params *app, uint64_t port_mask) { uint32_t pmd_id, link_id; link_id = 0; for (pmd_id = 0; pmd_id < RTE_MAX_ETHPORTS; pmd_id++) { char name[APP_PARAM_NAME_SIZE]; ssize_t idx; if ((port_mask & (1LLU << pmd_id)) == 0) continue; snprintf(name, sizeof(name), "LINK%" PRIu32, link_id); idx = APP_PARAM_ADD(app->link_params, name); PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, name); app->link_params[idx].pmd_id = pmd_id; link_id++; } } int app_config_parse(struct app_params *app, const char *file_name) { char config_file_out[APP_FILE_NAME_SIZE]; struct rte_cfgfile *cfg; char **section_names; int i, j, sect_count; /* Implicit mempools */ create_implicit_mempools(app); /* Port mask */ parse_port_mask(app, app->port_mask); /* Load application configuration file */ cfg = rte_cfgfile_load(file_name, 0); APP_CHECK(cfg != NULL, "Unable to load config file %s", file_name); sect_count = rte_cfgfile_num_sections(cfg, NULL, 0); section_names = malloc(sect_count * sizeof(char *)); for (i = 0; i < sect_count; i++) section_names[i] = malloc(CFG_NAME_LEN); rte_cfgfile_sections(cfg, section_names, sect_count); for (i = 0; i < sect_count; i++) { const struct config_section *sch_s; int len, cfg_name_len; cfg_name_len = strlen(section_names[i]); /* Find section type */ for (j = 0; j < (int)RTE_DIM(cfg_file_scheme); j++) { sch_s = &cfg_file_scheme[j]; len = strlen(sch_s->prefix); if (cfg_name_len < len) continue; /* After section name we expect only '\0' or digit or * digit dot digit, so protect against false matching, * for example: "ABC" should match section name * "ABC0.0", but it should not match section_name * "ABCDEF". */ if ((section_names[i][len] != '\0') && !isdigit(section_names[i][len])) continue; if (strncmp(sch_s->prefix, section_names[i], len) == 0) break; } APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme), "Unknown section %s", section_names[i]); APP_CHECK(validate_name(section_names[i], sch_s->prefix, sch_s->numbers) == 0, "Invalid section name '%s'", section_names[i]); sch_s->load(app, section_names[i], cfg); } for (i = 0; i < sect_count; i++) free(section_names[i]); free(section_names); rte_cfgfile_close(cfg); APP_PARAM_COUNT(app->mempool_params, app->n_mempools); APP_PARAM_COUNT(app->link_params, app->n_links); APP_PARAM_COUNT(app->hwq_in_params, app->n_pktq_hwq_in); APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out); APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq); APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm); APP_PARAM_COUNT(app->source_params, app->n_pktq_source); APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink); APP_PARAM_COUNT(app->msgq_params, app->n_msgq); APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); /* Save configuration to output file */ snprintf(config_file_out, APP_FILE_NAME_SIZE, "%s.out", app->config_file); app_config_save(app, config_file_out); /* Load TM configuration files */ app_config_parse_tm(app); return 0; } static void save_eal_params(struct app_params *app, FILE *f) { struct app_eal_params *p = &app->eal_params; fprintf(f, "[EAL]\n"); if (p->coremap) fprintf(f, "%s = %s\n", "lcores", p->coremap); if (p->master_lcore_present) fprintf(f, "%s = %" PRIu32 "\n", "master_lcore", p->master_lcore); fprintf(f, "%s = %" PRIu32 "\n", "n", p->channels); if (p->memory_present) fprintf(f, "%s = %" PRIu32 "\n", "m", p->memory); if (p->ranks_present) fprintf(f, "%s = %" PRIu32 "\n", "r", p->ranks); if (p->pci_blacklist) fprintf(f, "%s = %s\n", "pci_blacklist", p->pci_blacklist); if (p->pci_whitelist) fprintf(f, "%s = %s\n", "pci_whitelist", p->pci_whitelist); if (p->vdev) fprintf(f, "%s = %s\n", "vdev", p->vdev); if (p->vmware_tsc_map_present) fprintf(f, "%s = %s\n", "vmware_tsc_map", (p->vmware_tsc_map) ? "yes" : "no"); if (p->proc_type) fprintf(f, "%s = %s\n", "proc_type", p->proc_type); if (p->syslog) fprintf(f, "%s = %s\n", "syslog", p->syslog); if (p->log_level_present) fprintf(f, "%s = %" PRIu32 "\n", "log_level", p->log_level); if (p->version_present) fprintf(f, "%s = %s\n", "v", (p->version) ? "yes" : "no"); if (p->help_present) fprintf(f, "%s = %s\n", "help", (p->help) ? "yes" : "no"); if (p->no_huge_present) fprintf(f, "%s = %s\n", "no_huge", (p->no_huge) ? "yes" : "no"); if (p->no_pci_present) fprintf(f, "%s = %s\n", "no_pci", (p->no_pci) ? "yes" : "no"); if (p->no_hpet_present) fprintf(f, "%s = %s\n", "no_hpet", (p->no_hpet) ? "yes" : "no"); if (p->no_shconf_present) fprintf(f, "%s = %s\n", "no_shconf", (p->no_shconf) ? "yes" : "no"); if (p->add_driver) fprintf(f, "%s = %s\n", "d", p->add_driver); if (p->socket_mem) fprintf(f, "%s = %s\n", "socket_mem", p->socket_mem); if (p->huge_dir) fprintf(f, "%s = %s\n", "huge_dir", p->huge_dir); if (p->file_prefix) fprintf(f, "%s = %s\n", "file_prefix", p->file_prefix); if (p->base_virtaddr) fprintf(f, "%s = %s\n", "base_virtaddr", p->base_virtaddr); if (p->create_uio_dev_present) fprintf(f, "%s = %s\n", "create_uio_dev", (p->create_uio_dev) ? "yes" : "no"); if (p->vfio_intr) fprintf(f, "%s = %s\n", "vfio_intr", p->vfio_intr); if (p->xen_dom0_present) fprintf(f, "%s = %s\n", "xen_dom0", (p->xen_dom0) ? "yes" : "no"); fputc('\n', f); } static void save_mempool_params(struct app_params *app, FILE *f) { struct app_mempool_params *p; size_t i, count; count = RTE_DIM(app->mempool_params); for (i = 0; i < count; i++) { p = &app->mempool_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %" PRIu32 "\n", "buffer_size", p->buffer_size); fprintf(f, "%s = %" PRIu32 "\n", "pool_size", p->pool_size); fprintf(f, "%s = %" PRIu32 "\n", "cache_size", p->cache_size); fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); fputc('\n', f); } } static void save_links_params(struct app_params *app, FILE *f) { struct app_link_params *p; size_t i, count; count = RTE_DIM(app->link_params); for (i = 0; i < count; i++) { p = &app->link_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "; %s = %" PRIu32 "\n", "pmd_id", p->pmd_id); fprintf(f, "%s = %" PRIu32 "\n", "arp_q", p->arp_q); fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_local_q", p->tcp_syn_local_q); fprintf(f, "%s = %" PRIu32 "\n", "ip_local_q", p->ip_local_q); fprintf(f, "%s = %" PRIu32 "\n", "tcp_local_q", p->tcp_local_q); fprintf(f, "%s = %" PRIu32 "\n", "udp_local_q", p->udp_local_q); fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q", p->sctp_local_q); fputc('\n', f); } } static void save_rxq_params(struct app_params *app, FILE *f) { struct app_pktq_hwq_in_params *p; size_t i, count; count = RTE_DIM(app->hwq_in_params); for (i = 0; i < count; i++) { p = &app->hwq_in_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %s\n", "mempool", app->mempool_params[p->mempool_id].name); fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); fputc('\n', f); } } static void save_txq_params(struct app_params *app, FILE *f) { struct app_pktq_hwq_out_params *p; size_t i, count; count = RTE_DIM(app->hwq_out_params); for (i = 0; i < count; i++) { p = &app->hwq_out_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); fputc('\n', f); } } static void save_swq_params(struct app_params *app, FILE *f) { struct app_pktq_swq_params *p; size_t i, count; count = RTE_DIM(app->swq_params); for (i = 0; i < count; i++) { p = &app->swq_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); fputc('\n', f); } } static void save_tm_params(struct app_params *app, FILE *f) { struct app_pktq_tm_params *p; size_t i, count; count = RTE_DIM(app->tm_params); for (i = 0; i < count; i++) { p = &app->tm_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %s\n", "cfg", p->file_name); fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); fputc('\n', f); } } static void save_source_params(struct app_params *app, FILE *f) { struct app_pktq_source_params *p; size_t i, count; count = RTE_DIM(app->source_params); for (i = 0; i < count; i++) { p = &app->source_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %s\n", "mempool", app->mempool_params[p->mempool_id].name); fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst); fputc('\n', f); } } static void save_msgq_params(struct app_params *app, FILE *f) { struct app_msgq_params *p; size_t i, count; count = RTE_DIM(app->msgq_params); for (i = 0; i < count; i++) { p = &app->msgq_params[i]; if (!APP_PARAM_VALID(p)) continue; fprintf(f, "[%s]\n", p->name); fprintf(f, "%s = %" PRIu32 "\n", "size", p->size); fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); fputc('\n', f); } } static void save_pipeline_params(struct app_params *app, FILE *f) { size_t i, count; count = RTE_DIM(app->pipeline_params); for (i = 0; i < count; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; if (!APP_PARAM_VALID(p)) continue; /* section name */ fprintf(f, "[%s]\n", p->name); /* type */ fprintf(f, "type = %s\n", p->type); /* core */ fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n", p->socket_id, p->core_id, (p->hyper_th_id) ? "h" : ""); /* pktq_in */ if (p->n_pktq_in) { uint32_t j; fprintf(f, "pktq_in ="); for (j = 0; j < p->n_pktq_in; j++) { struct app_pktq_in_params *pp = &p->pktq_in[j]; char *name; switch (pp->type) { case APP_PKTQ_IN_HWQ: name = app->hwq_in_params[pp->id].name; break; case APP_PKTQ_IN_SWQ: name = app->swq_params[pp->id].name; break; case APP_PKTQ_IN_TM: name = app->tm_params[pp->id].name; break; case APP_PKTQ_IN_SOURCE: name = app->source_params[pp->id].name; break; default: APP_CHECK(0, "Error\n"); } fprintf(f, " %s", name); } fprintf(f, "\n"); } /* pktq_in */ if (p->n_pktq_out) { uint32_t j; fprintf(f, "pktq_out ="); for (j = 0; j < p->n_pktq_out; j++) { struct app_pktq_out_params *pp = &p->pktq_out[j]; char *name; switch (pp->type) { case APP_PKTQ_OUT_HWQ: name = app->hwq_out_params[pp->id].name; break; case APP_PKTQ_OUT_SWQ: name = app->swq_params[pp->id].name; break; case APP_PKTQ_OUT_TM: name = app->tm_params[pp->id].name; break; case APP_PKTQ_OUT_SINK: name = app->sink_params[pp->id].name; break; default: APP_CHECK(0, "Error\n"); } fprintf(f, " %s", name); } fprintf(f, "\n"); } /* msgq_in */ if (p->n_msgq_in) { uint32_t j; fprintf(f, "msgq_in ="); for (j = 0; j < p->n_msgq_in; j++) { uint32_t id = p->msgq_in[j]; char *name = app->msgq_params[id].name; fprintf(f, " %s", name); } fprintf(f, "\n"); } /* msgq_out */ if (p->n_msgq_in) { uint32_t j; fprintf(f, "msgq_out ="); for (j = 0; j < p->n_msgq_out; j++) { uint32_t id = p->msgq_out[j]; char *name = app->msgq_params[id].name; fprintf(f, " %s", name); } fprintf(f, "\n"); } /* timer_period */ fprintf(f, "timer_period = %" PRIu32 "\n", p->timer_period); /* args */ if (p->n_args) { uint32_t j; for (j = 0; j < p->n_args; j++) fprintf(f, "%s = %s\n", p->args_name[j], p->args_value[j]); } fprintf(f, "\n"); } } void app_config_save(struct app_params *app, const char *file_name) { FILE *file; char *name, *dir_name; int status; name = strdup(file_name); dir_name = dirname(name); status = access(dir_name, W_OK); APP_CHECK((status == 0), "Need write access to directory \"%s\" to save configuration\n", dir_name); file = fopen(file_name, "w"); APP_CHECK((file != NULL), "Failed to save configuration to file \"%s\"", file_name); save_eal_params(app, file); save_pipeline_params(app, file); save_mempool_params(app, file); save_links_params(app, file); save_rxq_params(app, file); save_txq_params(app, file); save_swq_params(app, file); save_tm_params(app, file); save_source_params(app, file); save_msgq_params(app, file); fclose(file); free(name); } int app_config_init(struct app_params *app) { size_t i; memcpy(app, &app_params_default, sizeof(struct app_params)); for (i = 0; i < RTE_DIM(app->mempool_params); i++) memcpy(&app->mempool_params[i], &mempool_params_default, sizeof(struct app_mempool_params)); for (i = 0; i < RTE_DIM(app->link_params); i++) memcpy(&app->link_params[i], &link_params_default, sizeof(struct app_link_params)); for (i = 0; i < RTE_DIM(app->hwq_in_params); i++) memcpy(&app->hwq_in_params[i], &default_hwq_in_params, sizeof(default_hwq_in_params)); for (i = 0; i < RTE_DIM(app->hwq_out_params); i++) memcpy(&app->hwq_out_params[i], &default_hwq_out_params, sizeof(default_hwq_out_params)); for (i = 0; i < RTE_DIM(app->swq_params); i++) memcpy(&app->swq_params[i], &default_swq_params, sizeof(default_swq_params)); for (i = 0; i < RTE_DIM(app->tm_params); i++) memcpy(&app->tm_params[i], &default_tm_params, sizeof(default_tm_params)); for (i = 0; i < RTE_DIM(app->source_params); i++) memcpy(&app->source_params[i], &default_source_params, sizeof(default_source_params)); for (i = 0; i < RTE_DIM(app->sink_params); i++) memcpy(&app->sink_params[i], &default_sink_params, sizeof(default_sink_params)); for (i = 0; i < RTE_DIM(app->msgq_params); i++) memcpy(&app->msgq_params[i], &default_msgq_params, sizeof(default_msgq_params)); for (i = 0; i < RTE_DIM(app->pipeline_params); i++) memcpy(&app->pipeline_params[i], &default_pipeline_params, sizeof(default_pipeline_params)); return 0; } int app_config_args(struct app_params *app, int argc, char **argv) { int opt; int option_index, f_present, s_present, p_present, l_present; int scaned = 0; static struct option lgopts[] = { {NULL, 0, 0, 0} }; /* Copy application name */ strncpy(app->app_name, argv[0], APP_APPNAME_SIZE - 1); f_present = 0; s_present = 0; p_present = 0; l_present = 0; while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts, &option_index)) != EOF) switch (opt) { case 'f': if (f_present) rte_panic("Error: Config file is provided " "more than once\n"); f_present = 1; if (!strlen(optarg)) rte_panic("Error: Config file name is null\n"); app->config_file = strdup(optarg); if (app->config_file == NULL) rte_panic("Error: Memory allocation failure\n"); break; case 's': if (s_present) rte_panic("Error: Script file is provided " "more than once\n"); s_present = 1; if (!strlen(optarg)) rte_panic("Error: Script file name is null\n"); app->script_file = strdup(optarg); if (app->script_file == NULL) rte_panic("Error: Memory allocation failure\n"); break; case 'p': if (p_present) rte_panic("Error: PORT_MASK is provided " "more than once\n"); p_present = 1; if ((sscanf(optarg, "%" SCNx64 "%n", &app->port_mask, &scaned) != 1) || ((size_t) scaned != strlen(optarg))) rte_panic("Error: PORT_MASK is not " "a hexadecimal integer\n"); if (app->port_mask == 0) rte_panic("Error: PORT_MASK is null\n"); break; case 'l': if (l_present) rte_panic("Error: LOG_LEVEL is provided " "more than once\n"); l_present = 1; if ((sscanf(optarg, "%" SCNu32 "%n", &app->log_level, &scaned) != 1) || ((size_t) scaned != strlen(optarg)) || (app->log_level >= APP_LOG_LEVELS)) rte_panic("Error: LOG_LEVEL invalid value\n"); break; default: app_print_usage(argv[0]); } optind = 0; /* reset getopt lib */ /* Check that mandatory args have been provided */ if (!p_present) rte_panic("Error: PORT_MASK is not provided\n"); return 0; } ================================================ FILE: examples/ip_pipeline/config_parse_tm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" static int tm_cfgfile_load_sched_port( struct rte_cfgfile *file, struct rte_sched_port_params *port_params) { const char *entry; int j; entry = rte_cfgfile_get_entry(file, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(file, "port", "mtu"); if (entry) port_params->mtu = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(file, "port", "number of subports per port"); if (entry) port_params->n_subports_per_port = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, "port", "number of pipes per subport"); if (entry) port_params->n_pipes_per_subport = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, "port", "queue sizes"); if (entry) { char *next; for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { port_params->qsize[j] = (uint16_t) strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } #ifdef RTE_SCHED_RED for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { char str[32]; /* Parse WRED min thresholds */ snprintf(str, sizeof(str), "tc %" PRId32 " wred min", j); entry = rte_cfgfile_get_entry(file, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].min_th = (uint16_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED max thresholds */ snprintf(str, sizeof(str), "tc %" PRId32 " wred max", j); entry = rte_cfgfile_get_entry(file, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].max_th = (uint16_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED inverse mark probabilities */ snprintf(str, sizeof(str), "tc %" PRId32 " wred inv prob", j); entry = rte_cfgfile_get_entry(file, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].maxp_inv = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED EWMA filter weights */ snprintf(str, sizeof(str), "tc %" PRId32 " wred weight", j); entry = rte_cfgfile_get_entry(file, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].wq_log2 = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } } #endif /* RTE_SCHED_RED */ return 0; } static int tm_cfgfile_load_sched_pipe( struct rte_cfgfile *file, struct rte_sched_port_params *port_params, struct rte_sched_pipe_params *pipe_params) { int i, j; char *next; const char *entry; int profiles; profiles = rte_cfgfile_num_sections(file, "pipe profile", sizeof("pipe profile") - 1); port_params->n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; snprintf(pipe_name, sizeof(pipe_name), "pipe profile %" PRId32, j); entry = rte_cfgfile_get_entry(file, pipe_name, "tb rate"); if (entry) pipe_params[j].tb_rate = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tb size"); if (entry) pipe_params[j].tb_size = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tc period"); if (entry) pipe_params[j].tc_period = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tc 0 rate"); if (entry) pipe_params[j].tc_rate[0] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 rate"); if (entry) pipe_params[j].tc_rate[1] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 rate"); if (entry) pipe_params[j].tc_rate[2] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 rate"); if (entry) pipe_params[j].tc_rate[3] = (uint32_t) atoi(entry); #ifdef RTE_SCHED_SUBPORT_TC_OV entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 oversubscription weight"); if (entry) pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry); #endif entry = rte_cfgfile_get_entry(file, pipe_name, "tc 0 wrr weights"); if (entry) for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] = (uint8_t) strtol(entry, &next, 10); if (next == NULL) break; entry = next; } entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 wrr weights"); if (entry) for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] = (uint8_t) strtol(entry, &next, 10); if (next == NULL) break; entry = next; } entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 wrr weights"); if (entry) for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] = (uint8_t) strtol(entry, &next, 10); if (next == NULL) break; entry = next; } entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 wrr weights"); if (entry) for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] = (uint8_t) strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } return 0; } static int tm_cfgfile_load_sched_subport( struct rte_cfgfile *file, struct rte_sched_subport_params *subport_params, int *pipe_to_profile) { const char *entry; int i, j, k; for (i = 0; i < APP_MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %" PRId32, i); if (rte_cfgfile_has_section(file, sec_name)) { entry = rte_cfgfile_get_entry(file, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tb size"); if (entry) subport_params[i].tb_size = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tc period"); if (entry) subport_params[i].tc_period = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tc 0 rate"); if (entry) subport_params[i].tc_rate[0] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tc 1 rate"); if (entry) subport_params[i].tc_rate[1] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tc 2 rate"); if (entry) subport_params[i].tc_rate[2] = (uint32_t) atoi(entry); entry = rte_cfgfile_get_entry(file, sec_name, "tc 3 rate"); if (entry) subport_params[i].tc_rate[3] = (uint32_t) atoi(entry); int n_entries = rte_cfgfile_section_num_entries(file, sec_name); struct rte_cfgfile_entry entries[n_entries]; rte_cfgfile_section_entries(file, sec_name, entries, n_entries); for (j = 0; j < n_entries; j++) if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { int profile; char *tokens[2] = {NULL, NULL}; int n_tokens; int begin, end; char name[CFG_NAME_LEN]; profile = atoi(entries[j].value); strncpy(name, entries[j].name, sizeof(name)); n_tokens = rte_strsplit( &name[sizeof("pipe")], strnlen(name, CFG_NAME_LEN), tokens, 2, '-'); begin = atoi(tokens[0]); if (n_tokens == 2) end = atoi(tokens[1]); else end = begin; if ((end >= APP_MAX_SCHED_PIPES) || (begin > end)) return -1; for (k = begin; k <= end; k++) { char profile_name[CFG_NAME_LEN]; snprintf(profile_name, sizeof(profile_name), "pipe profile %" PRId32, profile); if (rte_cfgfile_has_section(file, profile_name)) pipe_to_profile[i * APP_MAX_SCHED_PIPES + k] = profile; else rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", entries[j].value); } } } } return 0; } static int tm_cfgfile_load(struct app_pktq_tm_params *tm) { struct rte_cfgfile *file; uint32_t i; memset(tm->sched_subport_params, 0, sizeof(tm->sched_subport_params)); memset(tm->sched_pipe_profiles, 0, sizeof(tm->sched_pipe_profiles)); memset(&tm->sched_port_params, 0, sizeof(tm->sched_pipe_profiles)); for (i = 0; i < APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES; i++) tm->sched_pipe_to_profile[i] = -1; tm->sched_port_params.pipe_profiles = &tm->sched_pipe_profiles[0]; if (tm->file_name[0] == '\0') return -1; file = rte_cfgfile_load(tm->file_name, 0); if (file == NULL) return -1; tm_cfgfile_load_sched_port(file, &tm->sched_port_params); tm_cfgfile_load_sched_subport(file, tm->sched_subport_params, tm->sched_pipe_to_profile); tm_cfgfile_load_sched_pipe(file, &tm->sched_port_params, tm->sched_pipe_profiles); rte_cfgfile_close(file); return 0; } int app_config_parse_tm(struct app_params *app) { uint32_t i; for (i = 0; i < RTE_DIM(app->tm_params); i++) { struct app_pktq_tm_params *p = &app->tm_params[i]; int status; if (!APP_PARAM_VALID(p)) break; status = tm_cfgfile_load(p); APP_CHECK(status == 0, "Parse error for %s configuration file \"%s\"\n", p->name, p->file_name); } return 0; } ================================================ FILE: examples/ip_pipeline/cpu_core_map.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "cpu_core_map.h" struct cpu_core_map { uint32_t n_max_sockets; uint32_t n_max_cores_per_socket; uint32_t n_max_ht_per_core; uint32_t n_sockets; uint32_t n_cores_per_socket; uint32_t n_ht_per_core; int map[0]; }; static inline uint32_t cpu_core_map_pos(struct cpu_core_map *map, uint32_t socket_id, uint32_t core_id, uint32_t ht_id) { return (socket_id * map->n_max_cores_per_socket + core_id) * map->n_max_ht_per_core + ht_id; } static int cpu_core_map_compute_eal(struct cpu_core_map *map); static int cpu_core_map_compute_linux(struct cpu_core_map *map); static int cpu_core_map_compute_and_check(struct cpu_core_map *map); struct cpu_core_map * cpu_core_map_init(uint32_t n_max_sockets, uint32_t n_max_cores_per_socket, uint32_t n_max_ht_per_core, uint32_t eal_initialized) { uint32_t map_size, map_mem_size, i; struct cpu_core_map *map; int status; /* Check input arguments */ if ((n_max_sockets == 0) || (n_max_cores_per_socket == 0) || (n_max_ht_per_core == 0)) return NULL; /* Memory allocation */ map_size = n_max_sockets * n_max_cores_per_socket * n_max_ht_per_core; map_mem_size = sizeof(struct cpu_core_map) + map_size * sizeof(int); map = (struct cpu_core_map *) malloc(map_mem_size); if (map == NULL) return NULL; /* Initialization */ map->n_max_sockets = n_max_sockets; map->n_max_cores_per_socket = n_max_cores_per_socket; map->n_max_ht_per_core = n_max_ht_per_core; map->n_sockets = 0; map->n_cores_per_socket = 0; map->n_ht_per_core = 0; for (i = 0; i < map_size; i++) map->map[i] = -1; status = (eal_initialized) ? cpu_core_map_compute_eal(map) : cpu_core_map_compute_linux(map); if (status) { free(map); return NULL; } status = cpu_core_map_compute_and_check(map); if (status) { free(map); return NULL; } return map; } int cpu_core_map_compute_eal(struct cpu_core_map *map) { uint32_t socket_id, core_id, ht_id; /* Compute map */ for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { uint32_t n_detected, core_id_contig; int lcore_id; n_detected = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { struct lcore_config *p = &lcore_config[lcore_id]; if ((p->detected) && (p->socket_id == socket_id)) n_detected++; } core_id_contig = 0; for (core_id = 0; n_detected ; core_id++) { ht_id = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { struct lcore_config *p = &lcore_config[lcore_id]; if ((p->detected) && (p->socket_id == socket_id) && (p->core_id == core_id)) { uint32_t pos = cpu_core_map_pos(map, socket_id, core_id_contig, ht_id); map->map[pos] = lcore_id; ht_id++; n_detected--; } } if (ht_id) { core_id_contig++; if (core_id_contig == map->n_max_cores_per_socket) return -1; } } } return 0; } int cpu_core_map_compute_and_check(struct cpu_core_map *map) { uint32_t socket_id, core_id, ht_id; /* Compute n_ht_per_core, n_cores_per_socket, n_sockets */ for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) { if (map->map[ht_id] == -1) break; map->n_ht_per_core++; } if (map->n_ht_per_core == 0) return -1; for (core_id = 0; core_id < map->n_max_cores_per_socket; core_id++) { uint32_t pos = core_id * map->n_max_ht_per_core; if (map->map[pos] == -1) break; map->n_cores_per_socket++; } if (map->n_cores_per_socket == 0) return -1; for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { uint32_t pos = socket_id * map->n_max_cores_per_socket * map->n_max_ht_per_core; if (map->map[pos] == -1) break; map->n_sockets++; } if (map->n_sockets == 0) return -1; /* Check that each socket has exactly the same number of cores and that each core has exactly the same number of hyper-threads */ for (socket_id = 0; socket_id < map->n_sockets; socket_id++) { for (core_id = 0; core_id < map->n_cores_per_socket; core_id++) for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) { uint32_t pos = (socket_id * map->n_max_cores_per_socket + core_id) * map->n_max_ht_per_core + ht_id; if (((ht_id < map->n_ht_per_core) && (map->map[pos] == -1)) || ((ht_id >= map->n_ht_per_core) && (map->map[pos] != -1))) return -1; } for ( ; core_id < map->n_max_cores_per_socket; core_id++) for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) { uint32_t pos = cpu_core_map_pos(map, socket_id, core_id, ht_id); if (map->map[pos] != -1) return -1; } } return 0; } #define FILE_LINUX_CPU_N_LCORES \ "/sys/devices/system/cpu/present" static int cpu_core_map_get_n_lcores_linux(void) { char buffer[64], *string; FILE *fd; fd = fopen(FILE_LINUX_CPU_N_LCORES, "r"); if (fd == NULL) return -1; if (fgets(buffer, sizeof(buffer), fd) == NULL) { fclose(fd); return -1; } fclose(fd); string = index(buffer, '-'); if (string == NULL) return -1; return (atoi(++string) + 1); } #define FILE_LINUX_CPU_CORE_ID \ "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id" static int cpu_core_map_get_core_id_linux(int lcore_id) { char buffer[64]; FILE *fd; int core_id; snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_CORE_ID, lcore_id); fd = fopen(buffer, "r"); if (fd == NULL) return -1; if (fgets(buffer, sizeof(buffer), fd) == NULL) { fclose(fd); return -1; } fclose(fd); core_id = atoi(buffer); return core_id; } #define FILE_LINUX_CPU_SOCKET_ID \ "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id" static int cpu_core_map_get_socket_id_linux(int lcore_id) { char buffer[64]; FILE *fd; int socket_id; snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_SOCKET_ID, lcore_id); fd = fopen(buffer, "r"); if (fd == NULL) return -1; if (fgets(buffer, sizeof(buffer), fd) == NULL) { fclose(fd); return -1; } fclose(fd); socket_id = atoi(buffer); return socket_id; } int cpu_core_map_compute_linux(struct cpu_core_map *map) { uint32_t socket_id, core_id, ht_id; int n_lcores; n_lcores = cpu_core_map_get_n_lcores_linux(); if (n_lcores <= 0) return -1; /* Compute map */ for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) { uint32_t n_detected, core_id_contig; int lcore_id; n_detected = 0; for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) { int lcore_socket_id = cpu_core_map_get_socket_id_linux(lcore_id); if (lcore_socket_id < 0) return -1; if (((uint32_t) lcore_socket_id) == socket_id) n_detected++; } core_id_contig = 0; for (core_id = 0; n_detected ; core_id++) { ht_id = 0; for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) { int lcore_socket_id = cpu_core_map_get_socket_id_linux( lcore_id); if (lcore_socket_id < 0) return -1; int lcore_core_id = cpu_core_map_get_core_id_linux( lcore_id); if (lcore_core_id < 0) return -1; if (((uint32_t) lcore_socket_id == socket_id) && ((uint32_t) lcore_core_id == core_id)) { uint32_t pos = cpu_core_map_pos(map, socket_id, core_id_contig, ht_id); map->map[pos] = lcore_id; ht_id++; n_detected--; } } if (ht_id) { core_id_contig++; if (core_id_contig == map->n_max_cores_per_socket) return -1; } } } return 0; } void cpu_core_map_print(struct cpu_core_map *map) { uint32_t socket_id, core_id, ht_id; if (map == NULL) return; for (socket_id = 0; socket_id < map->n_sockets; socket_id++) { printf("Socket %" PRIu32 ":\n", socket_id); for (core_id = 0; core_id < map->n_cores_per_socket; core_id++) { printf("[%" PRIu32 "] = [", core_id); for (ht_id = 0; ht_id < map->n_ht_per_core; ht_id++) { int lcore_id = cpu_core_map_get_lcore_id(map, socket_id, core_id, ht_id); uint32_t core_id_noncontig = cpu_core_map_get_core_id_linux( lcore_id); printf(" %" PRId32 " (%" PRIu32 ") ", lcore_id, core_id_noncontig); } printf("]\n"); } } } uint32_t cpu_core_map_get_n_sockets(struct cpu_core_map *map) { if (map == NULL) return 0; return map->n_sockets; } uint32_t cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map) { if (map == NULL) return 0; return map->n_cores_per_socket; } uint32_t cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map) { if (map == NULL) return 0; return map->n_ht_per_core; } int cpu_core_map_get_lcore_id(struct cpu_core_map *map, uint32_t socket_id, uint32_t core_id, uint32_t ht_id) { uint32_t pos; if ((map == NULL) || (socket_id >= map->n_sockets) || (core_id >= map->n_cores_per_socket) || (ht_id >= map->n_ht_per_core)) return -1; pos = cpu_core_map_pos(map, socket_id, core_id, ht_id); return map->map[pos]; } void cpu_core_map_free(struct cpu_core_map *map) { if (map) free(map); } ================================================ FILE: examples/ip_pipeline/cpu_core_map.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_CPU_CORE_MAP_H__ #define __INCLUDE_CPU_CORE_MAP_H__ #include #include struct cpu_core_map; struct cpu_core_map * cpu_core_map_init(uint32_t n_max_sockets, uint32_t n_max_cores_per_socket, uint32_t n_max_ht_per_core, uint32_t eal_initialized); uint32_t cpu_core_map_get_n_sockets(struct cpu_core_map *map); uint32_t cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map); uint32_t cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map); int cpu_core_map_get_lcore_id(struct cpu_core_map *map, uint32_t socket_id, uint32_t core_id, uint32_t ht_id); void cpu_core_map_print(struct cpu_core_map *map); void cpu_core_map_free(struct cpu_core_map *map); #endif ================================================ FILE: examples/ip_pipeline/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "app.h" #include "pipeline.h" #include "pipeline_common_fe.h" #include "pipeline_master.h" #include "pipeline_passthrough.h" #include "pipeline_firewall.h" #include "pipeline_flow_classification.h" #include "pipeline_routing.h" #define APP_NAME_SIZE 32 static void app_init_core_map(struct app_params *app) { APP_LOG(app, HIGH, "Initializing CPU core map ..."); app->core_map = cpu_core_map_init(4, 32, 4, 0); if (app->core_map == NULL) rte_panic("Cannot create CPU core map\n"); if (app->log_level >= APP_LOG_LEVEL_LOW) cpu_core_map_print(app->core_map); } static void app_init_core_mask(struct app_params *app) { uint64_t mask = 0; uint32_t i; for (i = 0; i < app->n_pipelines; i++) { struct app_pipeline_params *p = &app->pipeline_params[i]; int lcore_id; lcore_id = cpu_core_map_get_lcore_id(app->core_map, p->socket_id, p->core_id, p->hyper_th_id); if (lcore_id < 0) rte_panic("Cannot create CPU core mask\n"); mask |= 1LLU << lcore_id; } app->core_mask = mask; APP_LOG(app, HIGH, "CPU core mask = 0x%016" PRIx64, app->core_mask); } static void app_init_eal(struct app_params *app) { char buffer[32]; struct app_eal_params *p = &app->eal_params; uint32_t n_args = 0; int status; app->eal_argv[n_args++] = strdup(app->app_name); snprintf(buffer, sizeof(buffer), "-c%" PRIx64, app->core_mask); app->eal_argv[n_args++] = strdup(buffer); if (p->coremap) { snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap); app->eal_argv[n_args++] = strdup(buffer); } if (p->master_lcore_present) { snprintf(buffer, sizeof(buffer), "--master-lcore=%" PRIu32, p->master_lcore); app->eal_argv[n_args++] = strdup(buffer); } snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels); app->eal_argv[n_args++] = strdup(buffer); if (p->memory_present) { snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory); app->eal_argv[n_args++] = strdup(buffer); } if (p->ranks_present) { snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks); app->eal_argv[n_args++] = strdup(buffer); } if (p->pci_blacklist) { snprintf(buffer, sizeof(buffer), "--pci-blacklist=%s", p->pci_blacklist); app->eal_argv[n_args++] = strdup(buffer); } if (p->pci_whitelist) { snprintf(buffer, sizeof(buffer), "--pci-whitelist=%s", p->pci_whitelist); app->eal_argv[n_args++] = strdup(buffer); } if (p->vdev) { snprintf(buffer, sizeof(buffer), "--vdev=%s", p->vdev); app->eal_argv[n_args++] = strdup(buffer); } if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) { snprintf(buffer, sizeof(buffer), "--vmware-tsc-map"); app->eal_argv[n_args++] = strdup(buffer); } if (p->proc_type) { snprintf(buffer, sizeof(buffer), "--proc-type=%s", p->proc_type); app->eal_argv[n_args++] = strdup(buffer); } if (p->syslog) { snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog); app->eal_argv[n_args++] = strdup(buffer); } if (p->log_level_present) { snprintf(buffer, sizeof(buffer), "--log-level=%" PRIu32, p->log_level); app->eal_argv[n_args++] = strdup(buffer); } if ((p->version_present) && p->version) { snprintf(buffer, sizeof(buffer), "-v"); app->eal_argv[n_args++] = strdup(buffer); } if ((p->help_present) && p->help) { snprintf(buffer, sizeof(buffer), "--help"); app->eal_argv[n_args++] = strdup(buffer); } if ((p->no_huge_present) && p->no_huge) { snprintf(buffer, sizeof(buffer), "--no-huge"); app->eal_argv[n_args++] = strdup(buffer); } if ((p->no_pci_present) && p->no_pci) { snprintf(buffer, sizeof(buffer), "--no-pci"); app->eal_argv[n_args++] = strdup(buffer); } if ((p->no_hpet_present) && p->no_hpet) { snprintf(buffer, sizeof(buffer), "--no-hpet"); app->eal_argv[n_args++] = strdup(buffer); } if ((p->no_shconf_present) && p->no_shconf) { snprintf(buffer, sizeof(buffer), "--no-shconf"); app->eal_argv[n_args++] = strdup(buffer); } if (p->add_driver) { snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver); app->eal_argv[n_args++] = strdup(buffer); } if (p->socket_mem) { snprintf(buffer, sizeof(buffer), "--socket-mem=%s", p->socket_mem); app->eal_argv[n_args++] = strdup(buffer); } if (p->huge_dir) { snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir); app->eal_argv[n_args++] = strdup(buffer); } if (p->file_prefix) { snprintf(buffer, sizeof(buffer), "--file-prefix=%s", p->file_prefix); app->eal_argv[n_args++] = strdup(buffer); } if (p->base_virtaddr) { snprintf(buffer, sizeof(buffer), "--base-virtaddr=%s", p->base_virtaddr); app->eal_argv[n_args++] = strdup(buffer); } if ((p->create_uio_dev_present) && p->create_uio_dev) { snprintf(buffer, sizeof(buffer), "--create-uio-dev"); app->eal_argv[n_args++] = strdup(buffer); } if (p->vfio_intr) { snprintf(buffer, sizeof(buffer), "--vfio-intr=%s", p->vfio_intr); app->eal_argv[n_args++] = strdup(buffer); } if ((p->xen_dom0_present) && (p->xen_dom0)) { snprintf(buffer, sizeof(buffer), "--xen-dom0"); app->eal_argv[n_args++] = strdup(buffer); } snprintf(buffer, sizeof(buffer), "--"); app->eal_argv[n_args++] = strdup(buffer); app->eal_argc = n_args; APP_LOG(app, HIGH, "Initializing EAL ..."); status = rte_eal_init(app->eal_argc, app->eal_argv); if (status < 0) rte_panic("EAL init error\n"); } static void app_init_mempool(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_mempools; i++) { struct app_mempool_params *p = &app->mempool_params[i]; APP_LOG(app, HIGH, "Initializing %s ...", p->name); app->mempool[i] = rte_mempool_create( p->name, p->pool_size, p->buffer_size, p->cache_size, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, p->cpu_socket_id, 0); if (app->mempool[i] == NULL) rte_panic("%s init error\n", p->name); } } static inline int app_link_filter_arp_add(struct app_link_params *link) { struct rte_eth_ethertype_filter filter = { .ether_type = ETHER_TYPE_ARP, .flags = 0, .queue = link->arp_q, }; return rte_eth_dev_filter_ctrl(link->pmd_id, RTE_ETH_FILTER_ETHERTYPE, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_tcp_syn_add(struct app_link_params *link) { struct rte_eth_syn_filter filter = { .hig_pri = 1, .queue = link->tcp_syn_local_q, }; return rte_eth_dev_filter_ctrl(link->pmd_id, RTE_ETH_FILTER_SYN, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = 0, .proto_mask = 0, /* Disable */ .tcp_flags = 0, .priority = 1, /* Lowest */ .queue = l1->ip_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = 0, .proto_mask = 0, /* Disable */ .tcp_flags = 0, .priority = 1, /* Lowest */ .queue = l1->ip_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); } static inline int app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_TCP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->tcp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_TCP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->tcp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); } static inline int app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_UDP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->udp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_UDP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->udp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); } static inline int app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_SCTP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->sctp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_ADD, &filter); } static inline int app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2) { struct rte_eth_ntuple_filter filter = { .flags = RTE_5TUPLE_FLAGS, .dst_ip = rte_bswap32(l2->ip), .dst_ip_mask = UINT32_MAX, /* Enable */ .src_ip = 0, .src_ip_mask = 0, /* Disable */ .dst_port = 0, .dst_port_mask = 0, /* Disable */ .src_port = 0, .src_port_mask = 0, /* Disable */ .proto = IPPROTO_SCTP, .proto_mask = UINT8_MAX, /* Enable */ .tcp_flags = 0, .priority = 2, /* Higher priority than IP */ .queue = l1->sctp_local_q, }; return rte_eth_dev_filter_ctrl(l1->pmd_id, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_DELETE, &filter); } static void app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp) { if (cp->arp_q != 0) { int status = app_link_filter_arp_add(cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding ARP filter (queue = %" PRIu32 ")", cp->name, cp->pmd_id, cp->arp_q); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding ARP filter " "(queue = %" PRIu32 ") (%" PRId32 ")\n", cp->name, cp->pmd_id, cp->arp_q, status); } } static void app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp) { if (cp->tcp_syn_local_q != 0) { int status = app_link_filter_tcp_syn_add(cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding TCP SYN filter (queue = %" PRIu32 ")", cp->name, cp->pmd_id, cp->tcp_syn_local_q); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding TCP SYN filter " "(queue = %" PRIu32 ") (%" PRId32 ")\n", cp->name, cp->pmd_id, cp->tcp_syn_local_q, status); } } void app_link_up_internal(struct app_params *app, struct app_link_params *cp) { uint32_t i; int status; /* For each link, add filters for IP of current link */ if (cp->ip != 0) { for (i = 0; i < app->n_links; i++) { struct app_link_params *p = &app->link_params[i]; /* IP */ if (p->ip_local_q != 0) { int status = app_link_filter_ip_add(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding IP filter (queue= %" PRIu32 ", IP = 0x%08" PRIx32 ")", p->name, p->pmd_id, p->ip_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding IP " "filter (queue= %" PRIu32 ", " "IP = 0x%08" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->ip_local_q, cp->ip, status); } /* TCP */ if (p->tcp_local_q != 0) { int status = app_link_filter_tcp_add(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding TCP filter " "(queue = %" PRIu32 ", IP = 0x%08" PRIx32 ")", p->name, p->pmd_id, p->tcp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding TCP " "filter (queue = %" PRIu32 ", " "IP = 0x%08" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->tcp_local_q, cp->ip, status); } /* UDP */ if (p->udp_local_q != 0) { int status = app_link_filter_udp_add(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): " "Adding UDP filter " "(queue = %" PRIu32 ", IP = 0x%08" PRIx32 ")", p->name, p->pmd_id, p->udp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding UDP " "filter (queue = %" PRIu32 ", " "IP = 0x%08" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->udp_local_q, cp->ip, status); } /* SCTP */ if (p->sctp_local_q != 0) { int status = app_link_filter_sctp_add(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): Adding SCTP filter " "(queue = %" PRIu32 ", IP = 0x%08" PRIx32 ")", p->name, p->pmd_id, p->sctp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): " "Error adding SCTP " "filter (queue = %" PRIu32 ", " "IP = 0x%08" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->sctp_local_q, cp->ip, status); } } } /* PMD link up */ status = rte_eth_dev_set_link_up(cp->pmd_id); if (status < 0) rte_panic("%s (%" PRIu32 "): PMD set up error %" PRId32 "\n", cp->name, cp->pmd_id, status); /* Mark link as UP */ cp->state = 1; } void app_link_down_internal(struct app_params *app, struct app_link_params *cp) { uint32_t i; /* PMD link down */ rte_eth_dev_set_link_down(cp->pmd_id); /* Mark link as DOWN */ cp->state = 0; /* Return if current link IP is not valid */ if (cp->ip == 0) return; /* For each link, remove filters for IP of current link */ for (i = 0; i < app->n_links; i++) { struct app_link_params *p = &app->link_params[i]; /* IP */ if (p->ip_local_q != 0) { int status = app_link_filter_ip_del(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): Deleting IP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", p->name, p->pmd_id, p->ip_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): Error deleting IP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->ip_local_q, cp->ip, status); } /* TCP */ if (p->tcp_local_q != 0) { int status = app_link_filter_tcp_del(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): Deleting TCP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", p->name, p->pmd_id, p->tcp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): Error deleting TCP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->tcp_local_q, cp->ip, status); } /* UDP */ if (p->udp_local_q != 0) { int status = app_link_filter_udp_del(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): Deleting UDP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", p->name, p->pmd_id, p->udp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): Error deleting UDP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->udp_local_q, cp->ip, status); } /* SCTP */ if (p->sctp_local_q != 0) { int status = app_link_filter_sctp_del(p, cp); APP_LOG(app, LOW, "%s (%" PRIu32 "): Deleting SCTP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")", p->name, p->pmd_id, p->sctp_local_q, cp->ip); if (status) rte_panic("%s (%" PRIu32 "): Error deleting SCTP filter " "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ") (%" PRId32 ")\n", p->name, p->pmd_id, p->sctp_local_q, cp->ip, status); } } } static void app_check_link(struct app_params *app) { uint32_t all_links_up, i; all_links_up = 1; for (i = 0; i < app->n_links; i++) { struct app_link_params *p = &app->link_params[i]; struct rte_eth_link link_params; memset(&link_params, 0, sizeof(link_params)); rte_eth_link_get(p->pmd_id, &link_params); APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s", p->name, p->pmd_id, link_params.link_speed / 1000, link_params.link_status ? "UP" : "DOWN"); if (link_params.link_status == 0) all_links_up = 0; } if (all_links_up == 0) rte_panic("Some links are DOWN\n"); } static void app_init_link(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_links; i++) { struct app_link_params *p_link = &app->link_params[i]; uint32_t link_id, n_hwq_in, n_hwq_out, j; int status; sscanf(p_link->name, "LINK%" PRIu32, &link_id); n_hwq_in = app_link_get_n_rxq(app, p_link); n_hwq_out = app_link_get_n_txq(app, p_link); APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") " "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...", p_link->name, p_link->pmd_id, n_hwq_in, n_hwq_out); /* LINK */ status = rte_eth_dev_configure( p_link->pmd_id, n_hwq_in, n_hwq_out, &p_link->conf); if (status < 0) rte_panic("%s (%" PRId32 "): " "init error (%" PRId32 ")\n", p_link->name, p_link->pmd_id, status); rte_eth_macaddr_get(p_link->pmd_id, (struct ether_addr *) &p_link->mac_addr); if (p_link->promisc) rte_eth_promiscuous_enable(p_link->pmd_id); /* RXQ */ for (j = 0; j < app->n_pktq_hwq_in; j++) { struct app_pktq_hwq_in_params *p_rxq = &app->hwq_in_params[j]; uint32_t rxq_link_id, rxq_queue_id; sscanf(p_rxq->name, "RXQ%" PRIu32 ".%" PRIu32, &rxq_link_id, &rxq_queue_id); if (rxq_link_id != link_id) continue; status = rte_eth_rx_queue_setup( p_link->pmd_id, rxq_queue_id, p_rxq->size, rte_eth_dev_socket_id(p_link->pmd_id), &p_rxq->conf, app->mempool[p_rxq->mempool_id]); if (status < 0) rte_panic("%s (%" PRIu32 "): " "%s init error (%" PRId32 ")\n", p_link->name, p_link->pmd_id, p_rxq->name, status); } /* TXQ */ for (j = 0; j < app->n_pktq_hwq_out; j++) { struct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[j]; uint32_t txq_link_id, txq_queue_id; sscanf(p_txq->name, "TXQ%" PRIu32 ".%" PRIu32, &txq_link_id, &txq_queue_id); if (txq_link_id != link_id) continue; status = rte_eth_tx_queue_setup( p_link->pmd_id, txq_queue_id, p_txq->size, rte_eth_dev_socket_id(p_link->pmd_id), &p_txq->conf); if (status < 0) rte_panic("%s (%" PRIu32 "): " "%s init error (%" PRId32 ")\n", p_link->name, p_link->pmd_id, p_txq->name, status); } /* LINK START */ status = rte_eth_dev_start(p_link->pmd_id); if (status < 0) rte_panic("Cannot start %s (error %" PRId32 ")\n", p_link->name, status); /* LINK UP */ app_link_set_arp_filter(app, p_link); app_link_set_tcp_syn_filter(app, p_link); app_link_up_internal(app, p_link); } app_check_link(app); } static void app_init_swq(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_swq; i++) { struct app_pktq_swq_params *p = &app->swq_params[i]; APP_LOG(app, HIGH, "Initializing %s...", p->name); app->swq[i] = rte_ring_create( p->name, p->size, p->cpu_socket_id, RING_F_SP_ENQ | RING_F_SC_DEQ); if (app->swq[i] == NULL) rte_panic("%s init error\n", p->name); } } static void app_init_tm(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_pktq_tm; i++) { struct app_pktq_tm_params *p_tm = &app->tm_params[i]; struct app_link_params *p_link; struct rte_eth_link link_eth_params; struct rte_sched_port *sched; uint32_t n_subports, subport_id; int status; p_link = app_get_link_for_tm(app, p_tm); /* LINK */ rte_eth_link_get(p_link->pmd_id, &link_eth_params); /* TM */ p_tm->sched_port_params.name = p_tm->name; p_tm->sched_port_params.socket = rte_eth_dev_socket_id(p_link->pmd_id); p_tm->sched_port_params.rate = (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8; APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name); sched = rte_sched_port_config(&p_tm->sched_port_params); if (sched == NULL) rte_panic("%s init error\n", p_tm->name); app->tm[i] = sched; /* Subport */ n_subports = p_tm->sched_port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { uint32_t n_pipes_per_subport, pipe_id; status = rte_sched_subport_config(sched, subport_id, &p_tm->sched_subport_params[subport_id]); if (status) rte_panic("%s subport %" PRIu32 " init error (%" PRId32 ")\n", p_tm->name, subport_id, status); /* Pipe */ n_pipes_per_subport = p_tm->sched_port_params.n_pipes_per_subport; for (pipe_id = 0; pipe_id < n_pipes_per_subport; pipe_id++) { int profile_id = p_tm->sched_pipe_to_profile[ subport_id * APP_MAX_SCHED_PIPES + pipe_id]; if (profile_id == -1) continue; status = rte_sched_pipe_config(sched, subport_id, pipe_id, profile_id); if (status) rte_panic("%s subport %" PRIu32 " pipe %" PRIu32 " (profile %" PRId32 ") " "init error (% " PRId32 ")\n", p_tm->name, subport_id, pipe_id, profile_id, status); } } } } static void app_init_msgq(struct app_params *app) { uint32_t i; for (i = 0; i < app->n_msgq; i++) { struct app_msgq_params *p = &app->msgq_params[i]; APP_LOG(app, HIGH, "Initializing %s ...", p->name); app->msgq[i] = rte_ring_create( p->name, p->size, p->cpu_socket_id, RING_F_SP_ENQ | RING_F_SC_DEQ); if (app->msgq[i] == NULL) rte_panic("%s init error\n", p->name); } } static void app_pipeline_params_get(struct app_params *app, struct app_pipeline_params *p_in, struct pipeline_params *p_out) { uint32_t i; strcpy(p_out->name, p_in->name); p_out->socket_id = (int) p_in->socket_id; p_out->log_level = app->log_level; /* pktq_in */ p_out->n_ports_in = p_in->n_pktq_in; for (i = 0; i < p_in->n_pktq_in; i++) { struct app_pktq_in_params *in = &p_in->pktq_in[i]; struct pipeline_port_in_params *out = &p_out->port_in[i]; switch (in->type) { case APP_PKTQ_IN_HWQ: { struct app_pktq_hwq_in_params *p_hwq_in = &app->hwq_in_params[in->id]; struct app_link_params *p_link = app_get_link_for_rxq(app, p_hwq_in); uint32_t rxq_link_id, rxq_queue_id; sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32, &rxq_link_id, &rxq_queue_id); out->type = PIPELINE_PORT_IN_ETHDEV_READER; out->params.ethdev.port_id = p_link->pmd_id; out->params.ethdev.queue_id = rxq_queue_id; out->burst_size = p_hwq_in->burst; break; } case APP_PKTQ_IN_SWQ: out->type = PIPELINE_PORT_IN_RING_READER; out->params.ring.ring = app->swq[in->id]; out->burst_size = app->swq_params[in->id].burst_read; /* What about frag and ras ports? */ break; case APP_PKTQ_IN_TM: out->type = PIPELINE_PORT_IN_SCHED_READER; out->params.sched.sched = app->tm[in->id]; out->burst_size = app->tm_params[in->id].burst_read; break; case APP_PKTQ_IN_SOURCE: out->type = PIPELINE_PORT_IN_SOURCE; out->params.source.mempool = app->mempool[in->id]; out->burst_size = app->source_params[in->id].burst; break; default: break; } } /* pktq_out */ p_out->n_ports_out = p_in->n_pktq_out; for (i = 0; i < p_in->n_pktq_out; i++) { struct app_pktq_out_params *in = &p_in->pktq_out[i]; struct pipeline_port_out_params *out = &p_out->port_out[i]; switch (in->type) { case APP_PKTQ_OUT_HWQ: { struct app_pktq_hwq_out_params *p_hwq_out = &app->hwq_out_params[in->id]; struct app_link_params *p_link = app_get_link_for_txq(app, p_hwq_out); uint32_t txq_link_id, txq_queue_id; sscanf(p_hwq_out->name, "TXQ%" SCNu32 ".%" SCNu32, &txq_link_id, &txq_queue_id); if (p_hwq_out->dropless == 0) { struct rte_port_ethdev_writer_params *params = &out->params.ethdev; out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER; params->port_id = p_link->pmd_id; params->queue_id = txq_queue_id; params->tx_burst_sz = app->hwq_out_params[in->id].burst; } else { struct rte_port_ethdev_writer_nodrop_params *params = &out->params.ethdev_nodrop; out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP; params->port_id = p_link->pmd_id; params->queue_id = txq_queue_id; params->tx_burst_sz = p_hwq_out->burst; params->n_retries = p_hwq_out->n_retries; } break; } case APP_PKTQ_OUT_SWQ: if (app->swq_params[in->id].dropless == 0) { struct rte_port_ring_writer_params *params = &out->params.ring; out->type = PIPELINE_PORT_OUT_RING_WRITER; params->ring = app->swq[in->id]; params->tx_burst_sz = app->swq_params[in->id].burst_write; } else { struct rte_port_ring_writer_nodrop_params *params = &out->params.ring_nodrop; out->type = PIPELINE_PORT_OUT_RING_WRITER_NODROP; params->ring = app->swq[in->id]; params->tx_burst_sz = app->swq_params[in->id].burst_write; params->n_retries = app->swq_params[in->id].n_retries; } /* What about frag and ras ports? */ break; case APP_PKTQ_OUT_TM: { struct rte_port_sched_writer_params *params = &out->params.sched; out->type = PIPELINE_PORT_OUT_SCHED_WRITER; params->sched = app->tm[in->id]; params->tx_burst_sz = app->tm_params[in->id].burst_write; break; } case APP_PKTQ_OUT_SINK: out->type = PIPELINE_PORT_OUT_SINK; break; default: break; } } /* msgq */ p_out->n_msgq = p_in->n_msgq_in; for (i = 0; i < p_in->n_msgq_in; i++) p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]]; for (i = 0; i < p_in->n_msgq_out; i++) p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]]; /* args */ p_out->n_args = p_in->n_args; for (i = 0; i < p_in->n_args; i++) { p_out->args_name[i] = p_in->args_name[i]; p_out->args_value[i] = p_in->args_value[i]; } } static void app_init_pipelines(struct app_params *app) { uint32_t p_id; for (p_id = 0; p_id < app->n_pipelines; p_id++) { struct app_pipeline_params *params = &app->pipeline_params[p_id]; struct app_pipeline_data *data = &app->pipeline_data[p_id]; struct pipeline_type *ptype; struct pipeline_params pp; APP_LOG(app, HIGH, "Initializing %s ...", params->name); ptype = app_pipeline_type_find(app, params->type); if (ptype == NULL) rte_panic("Init error: Unknown pipeline type \"%s\"\n", params->type); app_pipeline_params_get(app, params, &pp); /* Back-end */ data->be = NULL; if (ptype->be_ops->f_init) { data->be = ptype->be_ops->f_init(&pp, (void *) app); if (data->be == NULL) rte_panic("Pipeline instance \"%s\" back-end " "init error\n", params->name); } /* Front-end */ data->fe = NULL; if (ptype->fe_ops->f_init) { data->fe = ptype->fe_ops->f_init(&pp, (void *) app); if (data->fe == NULL) rte_panic("Pipeline instance \"%s\" front-end " "init error\n", params->name); } data->timer_period = (rte_get_tsc_hz() * params->timer_period) / 1000; } } static void app_init_threads(struct app_params *app) { uint64_t time = rte_get_tsc_cycles(); uint32_t p_id; for (p_id = 0; p_id < app->n_pipelines; p_id++) { struct app_pipeline_params *params = &app->pipeline_params[p_id]; struct app_pipeline_data *data = &app->pipeline_data[p_id]; struct pipeline_type *ptype; struct app_thread_data *t; struct app_thread_pipeline_data *p; int lcore_id; lcore_id = cpu_core_map_get_lcore_id(app->core_map, params->socket_id, params->core_id, params->hyper_th_id); if (lcore_id < 0) rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n", params->socket_id, params->core_id, (params->hyper_th_id) ? "h" : ""); t = &app->thread_data[lcore_id]; ptype = app_pipeline_type_find(app, params->type); if (ptype == NULL) rte_panic("Init error: Unknown pipeline " "type \"%s\"\n", params->type); p = (ptype->be_ops->f_run == NULL) ? &t->regular[t->n_regular] : &t->custom[t->n_custom]; p->be = data->be; p->f_run = ptype->be_ops->f_run; p->f_timer = ptype->be_ops->f_timer; p->timer_period = data->timer_period; p->deadline = time + data->timer_period; if (ptype->be_ops->f_run == NULL) t->n_regular++; else t->n_custom++; } } int app_init(struct app_params *app) { app_init_core_map(app); app_init_core_mask(app); app_init_eal(app); app_init_mempool(app); app_init_link(app); app_init_swq(app); app_init_tm(app); app_init_msgq(app); app_pipeline_common_cmd_push(app); app_pipeline_type_register(app, &pipeline_master); app_pipeline_type_register(app, &pipeline_passthrough); app_pipeline_type_register(app, &pipeline_flow_classification); app_pipeline_type_register(app, &pipeline_firewall); app_pipeline_type_register(app, &pipeline_routing); app_init_pipelines(app); app_init_threads(app); return 0; } static int app_pipeline_type_cmd_push(struct app_params *app, struct pipeline_type *ptype) { cmdline_parse_ctx_t *cmds; uint32_t n_cmds, i; /* Check input arguments */ if ((app == NULL) || (ptype == NULL)) return -EINVAL; n_cmds = pipeline_type_cmds_count(ptype); if (n_cmds == 0) return 0; cmds = ptype->fe_ops->cmds; /* Check for available slots in the application commands array */ if (n_cmds > APP_MAX_CMDS - app->n_cmds) return -ENOMEM; /* Push pipeline commands into the application */ memcpy(&app->cmds[app->n_cmds], cmds, n_cmds * sizeof(cmdline_parse_ctx_t *)); for (i = 0; i < n_cmds; i++) app->cmds[app->n_cmds + i]->data = app; app->n_cmds += n_cmds; app->cmds[app->n_cmds] = NULL; return 0; } int app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype) { uint32_t n_cmds, i; /* Check input arguments */ if ((app == NULL) || (ptype == NULL) || (ptype->name == NULL) || (strlen(ptype->name) == 0) || (ptype->be_ops->f_init == NULL) || (ptype->be_ops->f_timer == NULL)) return -EINVAL; /* Check for duplicate entry */ for (i = 0; i < app->n_pipeline_types; i++) if (strcmp(app->pipeline_type[i].name, ptype->name) == 0) return -EEXIST; /* Check for resource availability */ n_cmds = pipeline_type_cmds_count(ptype); if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) || (n_cmds > APP_MAX_CMDS - app->n_cmds)) return -ENOMEM; /* Copy pipeline type */ memcpy(&app->pipeline_type[app->n_pipeline_types++], ptype, sizeof(struct pipeline_type)); /* Copy CLI commands */ if (n_cmds) app_pipeline_type_cmd_push(app, ptype); return 0; } struct pipeline_type *app_pipeline_type_find(struct app_params *app, char *name) { uint32_t i; for (i = 0; i < app->n_pipeline_types; i++) if (strcmp(app->pipeline_type[i].name, name) == 0) return &app->pipeline_type[i]; return NULL; } ================================================ FILE: examples/ip_pipeline/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "app.h" static struct app_params app; int main(int argc, char **argv) { rte_openlog_stream(stderr); /* Config */ app_config_init(&app); app_config_args(&app, argc, argv); app_config_parse(&app, app.config_file); app_config_check(&app); /* Init */ app_init(&app); /* Run-time */ rte_eal_mp_remote_launch( app_thread, (void *) &app, CALL_MASTER); return 0; } ================================================ FILE: examples/ip_pipeline/pipeline/hash_func.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_HASH_FUNC_H__ #define __INCLUDE_HASH_FUNC_H__ static inline uint64_t hash_xor_key8(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0; xor0 = seed ^ k[0]; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key16(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0; xor0 = (k[0] ^ seed) ^ k[1]; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key24(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0; xor0 = (k[0] ^ seed) ^ k[1]; xor0 ^= k[2]; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key32(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0, xor1; xor0 = (k[0] ^ seed) ^ k[1]; xor1 = k[2] ^ k[3]; xor0 ^= xor1; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key40(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0, xor1; xor0 = (k[0] ^ seed) ^ k[1]; xor1 = k[2] ^ k[3]; xor0 ^= xor1; xor0 ^= k[4]; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key48(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0, xor1, xor2; xor0 = (k[0] ^ seed) ^ k[1]; xor1 = k[2] ^ k[3]; xor2 = k[4] ^ k[5]; xor0 ^= xor1; xor0 ^= xor2; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key56(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0, xor1, xor2; xor0 = (k[0] ^ seed) ^ k[1]; xor1 = k[2] ^ k[3]; xor2 = k[4] ^ k[5]; xor0 ^= xor1; xor2 ^= k[6]; xor0 ^= xor2; return (xor0 >> 32) ^ xor0; } static inline uint64_t hash_xor_key64(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t xor0, xor1, xor2, xor3; xor0 = (k[0] ^ seed) ^ k[1]; xor1 = k[2] ^ k[3]; xor2 = k[4] ^ k[5]; xor3 = k[6] ^ k[7]; xor0 ^= xor1; xor2 ^= xor3; xor0 ^= xor2; return (xor0 >> 32) ^ xor0; } #if defined(__x86_64__) #include static inline uint64_t hash_crc_key8(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t crc0; crc0 = _mm_crc32_u64(seed, k[0]); return crc0; } static inline uint64_t hash_crc_key16(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, crc0, crc1; k0 = k[0]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key24(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, crc0, crc1; k0 = k[0]; k2 = k[2]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc0 = _mm_crc32_u64(crc0, k2); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key32(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, crc0, crc1, crc2, crc3; k0 = k[0]; k2 = k[2]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc2 = _mm_crc32_u64(k2, k[3]); crc3 = k2 >> 32; crc0 = _mm_crc32_u64(crc0, crc1); crc1 = _mm_crc32_u64(crc2, crc3); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key40(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, crc0, crc1, crc2, crc3; k0 = k[0]; k2 = k[2]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc2 = _mm_crc32_u64(k2, k[3]); crc3 = _mm_crc32_u64(k2 >> 32, k[4]); crc0 = _mm_crc32_u64(crc0, crc1); crc1 = _mm_crc32_u64(crc2, crc3); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key48(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, k5, crc0, crc1, crc2, crc3; k0 = k[0]; k2 = k[2]; k5 = k[5]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc2 = _mm_crc32_u64(k2, k[3]); crc3 = _mm_crc32_u64(k2 >> 32, k[4]); crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); crc1 = _mm_crc32_u64(crc3, k5); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key56(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5; k0 = k[0]; k2 = k[2]; k5 = k[5]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc2 = _mm_crc32_u64(k2, k[3]); crc3 = _mm_crc32_u64(k2 >> 32, k[4]); crc4 = _mm_crc32_u64(k5, k[6]); crc5 = k5 >> 32; crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5); crc0 ^= crc1; return crc0; } static inline uint64_t hash_crc_key64(void *key, __rte_unused uint32_t key_size, uint64_t seed) { uint64_t *k = key; uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5; k0 = k[0]; k2 = k[2]; k5 = k[5]; crc0 = _mm_crc32_u64(k0, seed); crc1 = _mm_crc32_u64(k0 >> 32, k[1]); crc2 = _mm_crc32_u64(k2, k[3]); crc3 = _mm_crc32_u64(k2 >> 32, k[4]); crc4 = _mm_crc32_u64(k5, k[6]); crc5 = _mm_crc32_u64(k5 >> 32, k[7]); crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2); crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5); crc0 ^= crc1; return crc0; } #define hash_default_key8 hash_crc_key8 #define hash_default_key16 hash_crc_key16 #define hash_default_key24 hash_crc_key24 #define hash_default_key32 hash_crc_key32 #define hash_default_key40 hash_crc_key40 #define hash_default_key48 hash_crc_key48 #define hash_default_key56 hash_crc_key56 #define hash_default_key64 hash_crc_key64 #else #define hash_default_key8 hash_xor_key8 #define hash_default_key16 hash_xor_key16 #define hash_default_key24 hash_xor_key24 #define hash_default_key32 hash_xor_key32 #define hash_default_key40 hash_xor_key40 #define hash_default_key48 hash_xor_key48 #define hash_default_key56 hash_xor_key56 #define hash_default_key64 hash_xor_key64 #endif #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_actions_common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_ACTIONS_COMMON_H__ #define __INCLUDE_PIPELINE_ACTIONS_COMMON_H__ #define PIPELINE_PORT_IN_AH(f_ah, f_pkt_work, f_pkt4_work) \ static int \ f_ah( \ struct rte_mbuf **pkts, \ uint32_t n_pkts, \ uint64_t *pkts_mask, \ void *arg) \ { \ uint32_t i; \ \ for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ f_pkt4_work(&pkts[i], arg); \ \ for ( ; i < n_pkts; i++) \ f_pkt_work(pkts[i], arg); \ \ *pkts_mask = (~0LLU) >> (64 - n_pkts); \ \ return 0; \ } #define PIPELINE_TABLE_AH_HIT(f_ah, f_pkt_work, f_pkt4_work) \ static int \ f_ah( \ struct rte_mbuf **pkts, \ uint64_t *pkts_mask, \ struct rte_pipeline_table_entry **entries, \ void *arg) \ { \ uint64_t pkts_in_mask = *pkts_mask; \ \ if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ uint32_t i; \ \ for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ f_pkt4_work(&pkts[i], &entries[i], arg); \ \ for ( ; i < n_pkts; i++) \ f_pkt_work(pkts[i], entries[i], arg); \ } else \ for ( ; pkts_in_mask; ) { \ uint32_t pos = __builtin_ctzll(pkts_in_mask); \ uint64_t pkt_mask = 1LLU << pos; \ \ pkts_in_mask &= ~pkt_mask; \ f_pkt_work(pkts[pos], entries[pos], arg); \ } \ \ return 0; \ } #define PIPELINE_TABLE_AH_MISS(f_ah, f_pkt_work, f_pkt4_work) \ static int \ f_ah( \ struct rte_mbuf **pkts, \ uint64_t *pkts_mask, \ struct rte_pipeline_table_entry *entry, \ void *arg) \ { \ uint64_t pkts_in_mask = *pkts_mask; \ \ if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \ uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \ uint32_t i; \ \ for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) \ f_pkt4_work(&pkts[i], entry, arg); \ \ for ( ; i < n_pkts; i++) \ f_pkt_work(pkts[i], entry, arg); \ } else \ for ( ; pkts_in_mask; ) { \ uint32_t pos = __builtin_ctzll(pkts_in_mask); \ uint64_t pkt_mask = 1LLU << pos; \ \ pkts_in_mask &= ~pkt_mask; \ f_pkt_work(pkts[pos], entry, arg); \ } \ \ return 0; \ } #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_common_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "pipeline_common_be.h" void * pipeline_msg_req_ping_handler(__rte_unused struct pipeline *p, void *msg) { struct pipeline_msg_rsp *rsp = msg; rsp->status = 0; /* OK */ return rsp; } void * pipeline_msg_req_stats_port_in_handler(struct pipeline *p, void *msg) { struct pipeline_stats_msg_req *req = msg; struct pipeline_stats_port_in_msg_rsp *rsp = msg; uint32_t port_id; /* Check request */ if (req->id >= p->n_ports_in) { rsp->status = -1; return rsp; } port_id = p->port_in_id[req->id]; /* Process request */ rsp->status = rte_pipeline_port_in_stats_read(p->p, port_id, &rsp->stats, 1); return rsp; } void * pipeline_msg_req_stats_port_out_handler(struct pipeline *p, void *msg) { struct pipeline_stats_msg_req *req = msg; struct pipeline_stats_port_out_msg_rsp *rsp = msg; uint32_t port_id; /* Check request */ if (req->id >= p->n_ports_out) { rsp->status = -1; return rsp; } port_id = p->port_out_id[req->id]; /* Process request */ rsp->status = rte_pipeline_port_out_stats_read(p->p, port_id, &rsp->stats, 1); return rsp; } void * pipeline_msg_req_stats_table_handler(struct pipeline *p, void *msg) { struct pipeline_stats_msg_req *req = msg; struct pipeline_stats_table_msg_rsp *rsp = msg; uint32_t table_id; /* Check request */ if (req->id >= p->n_tables) { rsp->status = -1; return rsp; } table_id = p->table_id[req->id]; /* Process request */ rsp->status = rte_pipeline_table_stats_read(p->p, table_id, &rsp->stats, 1); return rsp; } void * pipeline_msg_req_port_in_enable_handler(struct pipeline *p, void *msg) { struct pipeline_port_in_msg_req *req = msg; struct pipeline_msg_rsp *rsp = msg; uint32_t port_id; /* Check request */ if (req->port_id >= p->n_ports_in) { rsp->status = -1; return rsp; } port_id = p->port_in_id[req->port_id]; /* Process request */ rsp->status = rte_pipeline_port_in_enable(p->p, port_id); return rsp; } void * pipeline_msg_req_port_in_disable_handler(struct pipeline *p, void *msg) { struct pipeline_port_in_msg_req *req = msg; struct pipeline_msg_rsp *rsp = msg; uint32_t port_id; /* Check request */ if (req->port_id >= p->n_ports_in) { rsp->status = -1; return rsp; } port_id = p->port_in_id[req->port_id]; /* Process request */ rsp->status = rte_pipeline_port_in_disable(p->p, port_id); return rsp; } void * pipeline_msg_req_invalid_handler(__rte_unused struct pipeline *p, void *msg) { struct pipeline_msg_rsp *rsp = msg; rsp->status = -1; /* Error */ return rsp; } int pipeline_msg_req_handle(struct pipeline *p) { uint32_t msgq_id; for (msgq_id = 0; msgq_id < p->n_msgq; msgq_id++) { for ( ; ; ) { struct pipeline_msg_req *req; pipeline_msg_req_handler f_handle; req = pipeline_msg_recv(p, msgq_id); if (req == NULL) break; f_handle = (req->type < PIPELINE_MSG_REQS) ? p->handlers[req->type] : pipeline_msg_req_invalid_handler; if (f_handle == NULL) f_handle = pipeline_msg_req_invalid_handler; pipeline_msg_send(p, msgq_id, f_handle(p, (void *) req)); } } return 0; } ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_common_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_COMMON_BE_H__ #define __INCLUDE_PIPELINE_COMMON_BE_H__ #include #include #include #include "pipeline_be.h" struct pipeline; enum pipeline_msg_req_type { PIPELINE_MSG_REQ_PING = 0, PIPELINE_MSG_REQ_STATS_PORT_IN, PIPELINE_MSG_REQ_STATS_PORT_OUT, PIPELINE_MSG_REQ_STATS_TABLE, PIPELINE_MSG_REQ_PORT_IN_ENABLE, PIPELINE_MSG_REQ_PORT_IN_DISABLE, PIPELINE_MSG_REQ_CUSTOM, PIPELINE_MSG_REQS }; typedef void *(*pipeline_msg_req_handler)(struct pipeline *p, void *msg); struct pipeline { struct rte_pipeline *p; uint32_t port_in_id[PIPELINE_MAX_PORT_IN]; uint32_t port_out_id[PIPELINE_MAX_PORT_OUT]; uint32_t table_id[PIPELINE_MAX_TABLES]; struct rte_ring *msgq_in[PIPELINE_MAX_MSGQ_IN]; struct rte_ring *msgq_out[PIPELINE_MAX_MSGQ_OUT]; uint32_t n_ports_in; uint32_t n_ports_out; uint32_t n_tables; uint32_t n_msgq; pipeline_msg_req_handler handlers[PIPELINE_MSG_REQS]; char name[PIPELINE_NAME_SIZE]; uint32_t log_level; }; enum pipeline_log_level { PIPELINE_LOG_LEVEL_HIGH = 1, PIPELINE_LOG_LEVEL_LOW, PIPELINE_LOG_LEVELS }; #define PLOG(p, level, fmt, ...) \ do { \ if (p->log_level >= PIPELINE_LOG_LEVEL_ ## level) \ fprintf(stdout, "[%s] " fmt "\n", p->name, ## __VA_ARGS__);\ } while (0) static inline void * pipeline_msg_recv(struct pipeline *p, uint32_t msgq_id) { struct rte_ring *r = p->msgq_in[msgq_id]; void *msg; int status = rte_ring_sc_dequeue(r, &msg); if (status != 0) return NULL; return msg; } static inline void pipeline_msg_send(struct pipeline *p, uint32_t msgq_id, void *msg) { struct rte_ring *r = p->msgq_out[msgq_id]; int status; do { status = rte_ring_sp_enqueue(r, msg); } while (status == -ENOBUFS); } struct pipeline_msg_req { enum pipeline_msg_req_type type; }; struct pipeline_stats_msg_req { enum pipeline_msg_req_type type; uint32_t id; }; struct pipeline_port_in_msg_req { enum pipeline_msg_req_type type; uint32_t port_id; }; struct pipeline_custom_msg_req { enum pipeline_msg_req_type type; uint32_t subtype; }; struct pipeline_msg_rsp { int status; }; struct pipeline_stats_port_in_msg_rsp { int status; struct rte_pipeline_port_in_stats stats; }; struct pipeline_stats_port_out_msg_rsp { int status; struct rte_pipeline_port_out_stats stats; }; struct pipeline_stats_table_msg_rsp { int status; struct rte_pipeline_table_stats stats; }; void *pipeline_msg_req_ping_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_stats_port_in_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_stats_port_out_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_stats_table_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_port_in_enable_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_port_in_disable_handler(struct pipeline *p, void *msg); void *pipeline_msg_req_invalid_handler(struct pipeline *p, void *msg); int pipeline_msg_req_handle(struct pipeline *p); #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_common_fe.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pipeline_common_fe.h" int app_pipeline_ping(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_params *p; struct pipeline_msg_req *req; struct pipeline_msg_rsp *rsp; int status = 0; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if (p == NULL) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_PING; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_pipeline_stats_port_in(struct app_params *app, uint32_t pipeline_id, uint32_t port_id, struct rte_pipeline_port_in_stats *stats) { struct app_pipeline_params *p; struct pipeline_stats_msg_req *req; struct pipeline_stats_port_in_msg_rsp *rsp; int status = 0; /* Check input arguments */ if ((app == NULL) || (stats == NULL)) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if ((p == NULL) || (port_id >= p->n_pktq_in)) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_STATS_PORT_IN; req->id = port_id; /* Send request and wait for response */ rsp = (struct pipeline_stats_port_in_msg_rsp *) app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; if (status == 0) memcpy(stats, &rsp->stats, sizeof(rsp->stats)); /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_pipeline_stats_port_out(struct app_params *app, uint32_t pipeline_id, uint32_t port_id, struct rte_pipeline_port_out_stats *stats) { struct app_pipeline_params *p; struct pipeline_stats_msg_req *req; struct pipeline_stats_port_out_msg_rsp *rsp; int status = 0; /* Check input arguments */ if ((app == NULL) || (pipeline_id >= app->n_pipelines) || (stats == NULL)) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if ((p == NULL) || (port_id >= p->n_pktq_out)) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_STATS_PORT_OUT; req->id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; if (status == 0) memcpy(stats, &rsp->stats, sizeof(rsp->stats)); /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_pipeline_stats_table(struct app_params *app, uint32_t pipeline_id, uint32_t table_id, struct rte_pipeline_table_stats *stats) { struct app_pipeline_params *p; struct pipeline_stats_msg_req *req; struct pipeline_stats_table_msg_rsp *rsp; int status = 0; /* Check input arguments */ if ((app == NULL) || (stats == NULL)) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if (p == NULL) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_STATS_TABLE; req->id = table_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; if (status == 0) memcpy(stats, &rsp->stats, sizeof(rsp->stats)); /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_pipeline_port_in_enable(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct app_pipeline_params *p; struct pipeline_port_in_msg_req *req; struct pipeline_msg_rsp *rsp; int status = 0; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if ((p == NULL) || (port_id >= p->n_pktq_in)) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_PORT_IN_ENABLE; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_pipeline_port_in_disable(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct app_pipeline_params *p; struct pipeline_port_in_msg_req *req; struct pipeline_msg_rsp *rsp; int status = 0; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); if ((p == NULL) || (port_id >= p->n_pktq_in)) return -1; /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) return -1; /* Fill in request */ req->type = PIPELINE_MSG_REQ_PORT_IN_DISABLE; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Check response */ status = rsp->status; /* Message buffer free */ app_msg_free(app, rsp); return status; } int app_link_config(struct app_params *app, uint32_t link_id, uint32_t ip, uint32_t depth) { struct app_link_params *p; uint32_t i, netmask, host, bcast; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); if (p == NULL) { APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", link_id); return -1; } if (p->state) { APP_LOG(app, HIGH, "%s is UP, please bring it DOWN first", p->name); return -1; } netmask = (~0) << (32 - depth); host = ip & netmask; bcast = host | (~netmask); if ((ip == 0) || (ip == UINT32_MAX) || (ip == host) || (ip == bcast)) { APP_LOG(app, HIGH, "Illegal IP address"); return -1; } for (i = 0; i < app->n_links; i++) { struct app_link_params *link = &app->link_params[i]; if (strcmp(p->name, link->name) == 0) continue; if (link->ip == ip) { APP_LOG(app, HIGH, "%s is already assigned this IP address", p->name); return -1; } } if ((depth == 0) || (depth > 32)) { APP_LOG(app, HIGH, "Illegal value for depth parameter " "(%" PRIu32 ")", depth); return -1; } /* Save link parameters */ p->ip = ip; p->depth = depth; return 0; } int app_link_up(struct app_params *app, uint32_t link_id) { struct app_link_params *p; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); if (p == NULL) { APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", link_id); return -1; } /* Check link state */ if (p->state) { APP_LOG(app, HIGH, "%s is already UP", p->name); return 0; } /* Check that IP address is valid */ if (p->ip == 0) { APP_LOG(app, HIGH, "%s IP address is not set", p->name); return 0; } app_link_up_internal(app, p); return 0; } int app_link_down(struct app_params *app, uint32_t link_id) { struct app_link_params *p; /* Check input arguments */ if (app == NULL) return -1; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); if (p == NULL) { APP_LOG(app, HIGH, "LINK%" PRIu32 " is not a valid link", link_id); return -1; } /* Check link state */ if (p->state == 0) { APP_LOG(app, HIGH, "%s is already DOWN", p->name); return 0; } app_link_down_internal(app, p); return 0; } /* * ping */ struct cmd_ping_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t ping_string; }; static void cmd_ping_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_ping_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_ping(app, params->pipeline_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_ping_p_string = TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p"); cmdline_parse_token_num_t cmd_ping_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_ping_ping_string = TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping"); cmdline_parse_inst_t cmd_ping = { .f = cmd_ping_parsed, .data = NULL, .help_str = "Pipeline ping", .tokens = { (void *) &cmd_ping_p_string, (void *) &cmd_ping_pipeline_id, (void *) &cmd_ping_ping_string, NULL, }, }; /* * stats port in */ struct cmd_stats_port_in_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t stats_string; cmdline_fixed_string_t port_string; cmdline_fixed_string_t in_string; uint32_t port_in_id; }; static void cmd_stats_port_in_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_stats_port_in_result *params = parsed_result; struct app_params *app = data; struct rte_pipeline_port_in_stats stats; int status; status = app_pipeline_stats_port_in(app, params->pipeline_id, params->port_in_id, &stats); if (status != 0) { printf("Command failed\n"); return; } /* Display stats */ printf("Pipeline %" PRIu32 " - stats for input port %" PRIu32 ":\n" "\tPkts in: %" PRIu64 "\n" "\tPkts dropped by AH: %" PRIu64 "\n" "\tPkts dropped by other: %" PRIu64 "\n", params->pipeline_id, params->port_in_id, stats.stats.n_pkts_in, stats.n_pkts_dropped_by_ah, stats.stats.n_pkts_drop); } cmdline_parse_token_string_t cmd_stats_port_in_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string, "p"); cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_stats_port_in_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_stats_port_in_port_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string, "port"); cmdline_parse_token_string_t cmd_stats_port_in_in_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string, "in"); cmdline_parse_token_num_t cmd_stats_port_in_port_in_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id, UINT32); cmdline_parse_inst_t cmd_stats_port_in = { .f = cmd_stats_port_in_parsed, .data = NULL, .help_str = "Pipeline input port stats", .tokens = { (void *) &cmd_stats_port_in_p_string, (void *) &cmd_stats_port_in_pipeline_id, (void *) &cmd_stats_port_in_stats_string, (void *) &cmd_stats_port_in_port_string, (void *) &cmd_stats_port_in_in_string, (void *) &cmd_stats_port_in_port_in_id, NULL, }, }; /* * stats port out */ struct cmd_stats_port_out_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t stats_string; cmdline_fixed_string_t port_string; cmdline_fixed_string_t out_string; uint32_t port_out_id; }; static void cmd_stats_port_out_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_stats_port_out_result *params = parsed_result; struct app_params *app = data; struct rte_pipeline_port_out_stats stats; int status; status = app_pipeline_stats_port_out(app, params->pipeline_id, params->port_out_id, &stats); if (status != 0) { printf("Command failed\n"); return; } /* Display stats */ printf("Pipeline %" PRIu32 " - stats for output port %" PRIu32 ":\n" "\tPkts in: %" PRIu64 "\n" "\tPkts dropped by AH: %" PRIu64 "\n" "\tPkts dropped by other: %" PRIu64 "\n", params->pipeline_id, params->port_out_id, stats.stats.n_pkts_in, stats.n_pkts_dropped_by_ah, stats.stats.n_pkts_drop); } cmdline_parse_token_string_t cmd_stats_port_out_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string, "p"); cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_stats_port_out_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_stats_port_out_port_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string, "port"); cmdline_parse_token_string_t cmd_stats_port_out_out_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string, "out"); cmdline_parse_token_num_t cmd_stats_port_out_port_out_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id, UINT32); cmdline_parse_inst_t cmd_stats_port_out = { .f = cmd_stats_port_out_parsed, .data = NULL, .help_str = "Pipeline output port stats", .tokens = { (void *) &cmd_stats_port_out_p_string, (void *) &cmd_stats_port_out_pipeline_id, (void *) &cmd_stats_port_out_stats_string, (void *) &cmd_stats_port_out_port_string, (void *) &cmd_stats_port_out_out_string, (void *) &cmd_stats_port_out_port_out_id, NULL, }, }; /* * stats table */ struct cmd_stats_table_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t stats_string; cmdline_fixed_string_t table_string; uint32_t table_id; }; static void cmd_stats_table_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_stats_table_result *params = parsed_result; struct app_params *app = data; struct rte_pipeline_table_stats stats; int status; status = app_pipeline_stats_table(app, params->pipeline_id, params->table_id, &stats); if (status != 0) { printf("Command failed\n"); return; } /* Display stats */ printf("Pipeline %" PRIu32 " - stats for table %" PRIu32 ":\n" "\tPkts in: %" PRIu64 "\n" "\tPkts in with lookup miss: %" PRIu64 "\n" "\tPkts in with lookup hit dropped by AH: %" PRIu64 "\n" "\tPkts in with lookup hit dropped by others: %" PRIu64 "\n" "\tPkts in with lookup miss dropped by AH: %" PRIu64 "\n" "\tPkts in with lookup miss dropped by others: %" PRIu64 "\n", params->pipeline_id, params->table_id, stats.stats.n_pkts_in, stats.stats.n_pkts_lookup_miss, stats.n_pkts_dropped_by_lkp_hit_ah, stats.n_pkts_dropped_lkp_hit, stats.n_pkts_dropped_by_lkp_miss_ah, stats.n_pkts_dropped_lkp_miss); } cmdline_parse_token_string_t cmd_stats_table_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string, "p"); cmdline_parse_token_num_t cmd_stats_table_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_stats_table_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_stats_table_table_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string, "table"); cmdline_parse_token_num_t cmd_stats_table_table_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32); cmdline_parse_inst_t cmd_stats_table = { .f = cmd_stats_table_parsed, .data = NULL, .help_str = "Pipeline table stats", .tokens = { (void *) &cmd_stats_table_p_string, (void *) &cmd_stats_table_pipeline_id, (void *) &cmd_stats_table_stats_string, (void *) &cmd_stats_table_table_string, (void *) &cmd_stats_table_table_id, NULL, }, }; /* * port in enable */ struct cmd_port_in_enable_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t port_string; cmdline_fixed_string_t in_string; uint32_t port_in_id; cmdline_fixed_string_t enable_string; }; static void cmd_port_in_enable_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_port_in_enable_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_port_in_enable(app, params->pipeline_id, params->port_in_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_port_in_enable_p_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string, "p"); cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_port_in_enable_port_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string, "port"); cmdline_parse_token_string_t cmd_port_in_enable_in_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string, "in"); cmdline_parse_token_num_t cmd_port_in_enable_port_in_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id, UINT32); cmdline_parse_token_string_t cmd_port_in_enable_enable_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, enable_string, "enable"); cmdline_parse_inst_t cmd_port_in_enable = { .f = cmd_port_in_enable_parsed, .data = NULL, .help_str = "Pipeline input port enable", .tokens = { (void *) &cmd_port_in_enable_p_string, (void *) &cmd_port_in_enable_pipeline_id, (void *) &cmd_port_in_enable_port_string, (void *) &cmd_port_in_enable_in_string, (void *) &cmd_port_in_enable_port_in_id, (void *) &cmd_port_in_enable_enable_string, NULL, }, }; /* * port in disable */ struct cmd_port_in_disable_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t port_string; cmdline_fixed_string_t in_string; uint32_t port_in_id; cmdline_fixed_string_t disable_string; }; static void cmd_port_in_disable_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_port_in_disable_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_port_in_disable(app, params->pipeline_id, params->port_in_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_port_in_disable_p_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string, "p"); cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_port_in_disable_port_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string, "port"); cmdline_parse_token_string_t cmd_port_in_disable_in_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string, "in"); cmdline_parse_token_num_t cmd_port_in_disable_port_in_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id, UINT32); cmdline_parse_token_string_t cmd_port_in_disable_disable_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, disable_string, "disable"); cmdline_parse_inst_t cmd_port_in_disable = { .f = cmd_port_in_disable_parsed, .data = NULL, .help_str = "Pipeline input port disable", .tokens = { (void *) &cmd_port_in_disable_p_string, (void *) &cmd_port_in_disable_pipeline_id, (void *) &cmd_port_in_disable_port_string, (void *) &cmd_port_in_disable_in_string, (void *) &cmd_port_in_disable_port_in_id, (void *) &cmd_port_in_disable_disable_string, NULL, }, }; /* * link config */ static void print_link_info(struct app_link_params *p) { struct rte_eth_stats stats; struct ether_addr *mac_addr; uint32_t netmask = (~0) << (32 - p->depth); uint32_t host = p->ip & netmask; uint32_t bcast = host | (~netmask); memset(&stats, 0, sizeof(stats)); rte_eth_stats_get(p->pmd_id, &stats); mac_addr = (struct ether_addr *) &p->mac_addr; printf("%s: flags=<%s>\n", p->name, (p->state) ? "UP" : "DOWN"); if (p->ip) printf("\tinet %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 " netmask %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 " " "broadcast %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", (p->ip >> 24) & 0xFF, (p->ip >> 16) & 0xFF, (p->ip >> 8) & 0xFF, p->ip & 0xFF, (netmask >> 24) & 0xFF, (netmask >> 16) & 0xFF, (netmask >> 8) & 0xFF, netmask & 0xFF, (bcast >> 24) & 0xFF, (bcast >> 16) & 0xFF, (bcast >> 8) & 0xFF, bcast & 0xFF); printf("\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n", mac_addr->addr_bytes[0], mac_addr->addr_bytes[1], mac_addr->addr_bytes[2], mac_addr->addr_bytes[3], mac_addr->addr_bytes[4], mac_addr->addr_bytes[5]); printf("\tRX packets %" PRIu64 " bytes %" PRIu64 "\n", stats.ipackets, stats.ibytes); printf("\tRX mcast %" PRIu64 " fdirmatch %" PRIu64 " fdirmiss %" PRIu64 " lb-packets %" PRIu64 " lb-bytes %" PRIu64 " xon %" PRIu64 " xoff %" PRIu64 "\n", stats.imcasts, stats.fdirmatch, stats.fdirmiss, stats.ilbpackets, stats.ilbbytes, stats.rx_pause_xon, stats.rx_pause_xoff); printf("\tRX errors %" PRIu64 " missed %" PRIu64 " badcrc %" PRIu64 " badlen %" PRIu64 " no-mbuf %" PRIu64 "\n", stats.ierrors, stats.imissed, stats.ibadcrc, stats.ibadlen, stats.rx_nombuf); printf("\tTX packets %" PRIu64 " bytes %" PRIu64 "\n", stats.opackets, stats.obytes); printf("\tTX lb-packets %" PRIu64 " lb-bytes %" PRIu64 " xon %" PRIu64 " xoff %" PRIu64 "\n", stats.olbpackets, stats.olbbytes, stats.tx_pause_xon, stats.tx_pause_xoff); printf("\tTX errors %" PRIu64 "\n", stats.oerrors); printf("\n"); } struct cmd_link_config_result { cmdline_fixed_string_t link_string; uint32_t link_id; cmdline_fixed_string_t config_string; cmdline_ipaddr_t ip; uint32_t depth; }; static void cmd_link_config_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_link_config_result *params = parsed_result; struct app_params *app = data; int status; uint32_t link_id = params->link_id; uint32_t ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); uint32_t depth = params->depth; status = app_link_config(app, link_id, ip, depth); if (status) printf("Command failed\n"); else { struct app_link_params *p; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); print_link_info(p); } } cmdline_parse_token_string_t cmd_link_config_link_string = TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, link_string, "link"); cmdline_parse_token_num_t cmd_link_config_link_id = TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, link_id, UINT32); cmdline_parse_token_string_t cmd_link_config_config_string = TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, config_string, "config"); cmdline_parse_token_ipaddr_t cmd_link_config_ip = TOKEN_IPV4_INITIALIZER(struct cmd_link_config_result, ip); cmdline_parse_token_num_t cmd_link_config_depth = TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, depth, UINT32); cmdline_parse_inst_t cmd_link_config = { .f = cmd_link_config_parsed, .data = NULL, .help_str = "Link configuration", .tokens = { (void *)&cmd_link_config_link_string, (void *)&cmd_link_config_link_id, (void *)&cmd_link_config_config_string, (void *)&cmd_link_config_ip, (void *)&cmd_link_config_depth, NULL, }, }; /* * link up */ struct cmd_link_up_result { cmdline_fixed_string_t link_string; uint32_t link_id; cmdline_fixed_string_t up_string; }; static void cmd_link_up_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_link_up_result *params = parsed_result; struct app_params *app = data; int status; status = app_link_up(app, params->link_id); if (status != 0) printf("Command failed\n"); else { struct app_link_params *p; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p); print_link_info(p); } } cmdline_parse_token_string_t cmd_link_up_link_string = TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, link_string, "link"); cmdline_parse_token_num_t cmd_link_up_link_id = TOKEN_NUM_INITIALIZER(struct cmd_link_up_result, link_id, UINT32); cmdline_parse_token_string_t cmd_link_up_up_string = TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up"); cmdline_parse_inst_t cmd_link_up = { .f = cmd_link_up_parsed, .data = NULL, .help_str = "Link UP", .tokens = { (void *)&cmd_link_up_link_string, (void *)&cmd_link_up_link_id, (void *)&cmd_link_up_up_string, NULL, }, }; /* * link down */ struct cmd_link_down_result { cmdline_fixed_string_t link_string; uint32_t link_id; cmdline_fixed_string_t down_string; }; static void cmd_link_down_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_link_down_result *params = parsed_result; struct app_params *app = data; int status; status = app_link_down(app, params->link_id); if (status != 0) printf("Command failed\n"); else { struct app_link_params *p; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, p); print_link_info(p); } } cmdline_parse_token_string_t cmd_link_down_link_string = TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string, "link"); cmdline_parse_token_num_t cmd_link_down_link_id = TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32); cmdline_parse_token_string_t cmd_link_down_down_string = TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string, "down"); cmdline_parse_inst_t cmd_link_down = { .f = cmd_link_down_parsed, .data = NULL, .help_str = "Link DOWN", .tokens = { (void *) &cmd_link_down_link_string, (void *) &cmd_link_down_link_id, (void *) &cmd_link_down_down_string, NULL, }, }; /* * link ls */ struct cmd_link_ls_result { cmdline_fixed_string_t link_string; cmdline_fixed_string_t ls_string; }; static void cmd_link_ls_parsed( __attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct app_params *app = data; uint32_t link_id; for (link_id = 0; link_id < app->n_links; link_id++) { struct app_link_params *p; APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); print_link_info(p); } } cmdline_parse_token_string_t cmd_link_ls_link_string = TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string, "link"); cmdline_parse_token_string_t cmd_link_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, ls_string, "ls"); cmdline_parse_inst_t cmd_link_ls = { .f = cmd_link_ls_parsed, .data = NULL, .help_str = "Link list", .tokens = { (void *)&cmd_link_ls_link_string, (void *)&cmd_link_ls_ls_string, NULL, }, }; /* * quit */ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed( __rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { cmdline_quit(cl); } static cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); static cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, .data = NULL, .help_str = "Quit", .tokens = { (void *) &cmd_quit_quit, NULL, }, }; /* * run */ static void app_run_file( cmdline_parse_ctx_t *ctx, const char *file_name) { struct cmdline *file_cl; int fd; fd = open(file_name, O_RDONLY); if (fd < 0) { printf("Cannot open file \"%s\"\n", file_name); return; } file_cl = cmdline_new(ctx, "", fd, 1); cmdline_interact(file_cl); close(fd); } struct cmd_run_file_result { cmdline_fixed_string_t run_string; char file_name[APP_FILE_NAME_SIZE]; }; static void cmd_run_parsed( void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_run_file_result *params = parsed_result; app_run_file(cl->ctx, params->file_name); } cmdline_parse_token_string_t cmd_run_run_string = TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, "run"); cmdline_parse_token_string_t cmd_run_file_name = TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_name, NULL); cmdline_parse_inst_t cmd_run = { .f = cmd_run_parsed, .data = NULL, .help_str = "Run CLI script file", .tokens = { (void *) &cmd_run_run_string, (void *) &cmd_run_file_name, NULL, }, }; static cmdline_parse_ctx_t pipeline_common_cmds[] = { (cmdline_parse_inst_t *) &cmd_quit, (cmdline_parse_inst_t *) &cmd_run, (cmdline_parse_inst_t *) &cmd_link_config, (cmdline_parse_inst_t *) &cmd_link_up, (cmdline_parse_inst_t *) &cmd_link_down, (cmdline_parse_inst_t *) &cmd_link_ls, (cmdline_parse_inst_t *) &cmd_ping, (cmdline_parse_inst_t *) &cmd_stats_port_in, (cmdline_parse_inst_t *) &cmd_stats_port_out, (cmdline_parse_inst_t *) &cmd_stats_table, (cmdline_parse_inst_t *) &cmd_port_in_enable, (cmdline_parse_inst_t *) &cmd_port_in_disable, NULL, }; int app_pipeline_common_cmd_push(struct app_params *app) { uint32_t n_cmds, i; /* Check for available slots in the application commands array */ n_cmds = RTE_DIM(pipeline_common_cmds) - 1; if (n_cmds > APP_MAX_CMDS - app->n_cmds) return -ENOMEM; /* Push pipeline commands into the application */ memcpy(&app->cmds[app->n_cmds], pipeline_common_cmds, n_cmds * sizeof(cmdline_parse_ctx_t *)); for (i = 0; i < n_cmds; i++) app->cmds[app->n_cmds + i]->data = app; app->n_cmds += n_cmds; app->cmds[app->n_cmds] = NULL; return 0; } ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_common_fe.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_COMMON_FE_H__ #define __INCLUDE_PIPELINE_COMMON_FE_H__ #include #include #include #include #include "pipeline_common_be.h" #include "pipeline.h" #include "app.h" #ifndef MSG_TIMEOUT_DEFAULT #define MSG_TIMEOUT_DEFAULT 1000 #endif static inline struct app_pipeline_data * app_pipeline_data(struct app_params *app, uint32_t id) { struct app_pipeline_params *params; APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", id, params); if (params == NULL) return NULL; return &app->pipeline_data[params - app->pipeline_params]; } static inline void * app_pipeline_data_fe(struct app_params *app, uint32_t id) { struct app_pipeline_data *pipeline_data; pipeline_data = app_pipeline_data(app, id); if (pipeline_data == NULL) return NULL; return pipeline_data->fe; } static inline struct rte_ring * app_pipeline_msgq_in_get(struct app_params *app, uint32_t pipeline_id) { struct app_msgq_params *p; APP_PARAM_FIND_BY_ID(app->msgq_params, "MSGQ-REQ-PIPELINE", pipeline_id, p); if (p == NULL) return NULL; return app->msgq[p - app->msgq_params]; } static inline struct rte_ring * app_pipeline_msgq_out_get(struct app_params *app, uint32_t pipeline_id) { struct app_msgq_params *p; APP_PARAM_FIND_BY_ID(app->msgq_params, "MSGQ-RSP-PIPELINE", pipeline_id, p); if (p == NULL) return NULL; return app->msgq[p - app->msgq_params]; } static inline void * app_msg_alloc(__rte_unused struct app_params *app) { return rte_malloc(NULL, 2048, RTE_CACHE_LINE_SIZE); } static inline void app_msg_free(__rte_unused struct app_params *app, void *msg) { rte_free(msg); } static inline void app_msg_send(struct app_params *app, uint32_t pipeline_id, void *msg) { struct rte_ring *r = app_pipeline_msgq_in_get(app, pipeline_id); int status; do { status = rte_ring_sp_enqueue(r, msg); } while (status == -ENOBUFS); } static inline void * app_msg_recv(struct app_params *app, uint32_t pipeline_id) { struct rte_ring *r = app_pipeline_msgq_out_get(app, pipeline_id); void *msg; int status = rte_ring_sc_dequeue(r, &msg); if (status != 0) return NULL; return msg; } static inline void * app_msg_send_recv(struct app_params *app, uint32_t pipeline_id, void *msg, uint32_t timeout_ms) { struct rte_ring *r_req = app_pipeline_msgq_in_get(app, pipeline_id); struct rte_ring *r_rsp = app_pipeline_msgq_out_get(app, pipeline_id); uint64_t hz = rte_get_tsc_hz(); void *msg_recv; uint64_t deadline; int status; /* send */ do { status = rte_ring_sp_enqueue(r_req, (void *) msg); } while (status == -ENOBUFS); /* recv */ deadline = (timeout_ms) ? (rte_rdtsc() + ((hz * timeout_ms) / 1000)) : UINT64_MAX; do { if (rte_rdtsc() > deadline) return NULL; status = rte_ring_sc_dequeue(r_rsp, &msg_recv); } while (status != 0); return msg_recv; } int app_pipeline_ping(struct app_params *app, uint32_t pipeline_id); int app_pipeline_stats_port_in(struct app_params *app, uint32_t pipeline_id, uint32_t port_id, struct rte_pipeline_port_in_stats *stats); int app_pipeline_stats_port_out(struct app_params *app, uint32_t pipeline_id, uint32_t port_id, struct rte_pipeline_port_out_stats *stats); int app_pipeline_stats_table(struct app_params *app, uint32_t pipeline_id, uint32_t table_id, struct rte_pipeline_table_stats *stats); int app_pipeline_port_in_enable(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_pipeline_port_in_disable(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_link_config(struct app_params *app, uint32_t link_id, uint32_t ip, uint32_t depth); int app_link_up(struct app_params *app, uint32_t link_id); int app_link_down(struct app_params *app, uint32_t link_id); int app_pipeline_common_cmd_push(struct app_params *app); #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_firewall.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_firewall.h" struct app_pipeline_firewall_rule { struct pipeline_firewall_key key; int32_t priority; uint32_t port_id; void *entry_ptr; TAILQ_ENTRY(app_pipeline_firewall_rule) node; }; struct app_pipeline_firewall { /* parameters */ uint32_t n_ports_in; uint32_t n_ports_out; /* rules */ TAILQ_HEAD(, app_pipeline_firewall_rule) rules; uint32_t n_rules; uint32_t default_rule_present; uint32_t default_rule_port_id; void *default_rule_entry_ptr; }; static void print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule) { printf("Prio = %" PRId32 " (SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 ", " "DA = %" PRIu32 ".%" PRIu32 ".%"PRIu32 ".%" PRIu32 "/%" PRIu32 ", " "SP = %" PRIu32 "-%" PRIu32 ", " "DP = %" PRIu32 "-%" PRIu32 ", " "Proto = %" PRIu32 " / 0x%" PRIx32 ") => " "Port = %" PRIu32 " (entry ptr = %p)\n", rule->priority, (rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF, (rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF, (rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF, rule->key.key.ipv4_5tuple.src_ip & 0xFF, rule->key.key.ipv4_5tuple.src_ip_mask, (rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF, (rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF, (rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF, rule->key.key.ipv4_5tuple.dst_ip & 0xFF, rule->key.key.ipv4_5tuple.dst_ip_mask, rule->key.key.ipv4_5tuple.src_port_from, rule->key.key.ipv4_5tuple.src_port_to, rule->key.key.ipv4_5tuple.dst_port_from, rule->key.key.ipv4_5tuple.dst_port_to, rule->key.key.ipv4_5tuple.proto, rule->key.key.ipv4_5tuple.proto_mask, rule->port_id, rule->entry_ptr); } static struct app_pipeline_firewall_rule * app_pipeline_firewall_rule_find(struct app_pipeline_firewall *p, struct pipeline_firewall_key *key) { struct app_pipeline_firewall_rule *r; TAILQ_FOREACH(r, &p->rules, node) if (memcmp(key, &r->key, sizeof(struct pipeline_firewall_key)) == 0) return r; return NULL; } static void app_pipeline_firewall_ls( struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_firewall *p; struct app_pipeline_firewall_rule *rule; uint32_t n_rules; int priority; /* Check input arguments */ if (app == NULL) return; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return; n_rules = p->n_rules; for (priority = 0; n_rules; priority++) TAILQ_FOREACH(rule, &p->rules, node) if (rule->priority == priority) { print_firewall_ipv4_rule(rule); n_rules--; } if (p->default_rule_present) printf("Default rule: port %" PRIu32 " (entry ptr = %p)\n", p->default_rule_port_id, p->default_rule_entry_ptr); else printf("Default rule: DROP\n"); printf("\n"); } static void* app_pipeline_firewall_init(struct pipeline_params *params, __rte_unused void *arg) { struct app_pipeline_firewall *p; uint32_t size; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_firewall)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; /* Initialization */ p->n_ports_in = params->n_ports_in; p->n_ports_out = params->n_ports_out; TAILQ_INIT(&p->rules); p->n_rules = 0; p->default_rule_present = 0; p->default_rule_port_id = 0; p->default_rule_entry_ptr = NULL; return (void *) p; } static int app_pipeline_firewall_free(void *pipeline) { struct app_pipeline_firewall *p = pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ while (!TAILQ_EMPTY(&p->rules)) { struct app_pipeline_firewall_rule *rule; rule = TAILQ_FIRST(&p->rules); TAILQ_REMOVE(&p->rules, rule, node); rte_free(rule); } rte_free(p); return 0; } static int app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key) { switch (key->type) { case PIPELINE_FIREWALL_IPV4_5TUPLE: { uint32_t src_ip_depth = key->key.ipv4_5tuple.src_ip_mask; uint32_t dst_ip_depth = key->key.ipv4_5tuple.dst_ip_mask; uint16_t src_port_from = key->key.ipv4_5tuple.src_port_from; uint16_t src_port_to = key->key.ipv4_5tuple.src_port_to; uint16_t dst_port_from = key->key.ipv4_5tuple.dst_port_from; uint16_t dst_port_to = key->key.ipv4_5tuple.dst_port_to; uint32_t src_ip_netmask = 0; uint32_t dst_ip_netmask = 0; if ((src_ip_depth > 32) || (dst_ip_depth > 32) || (src_port_from > src_port_to) || (dst_port_from > dst_port_to)) return -1; if (src_ip_depth) src_ip_netmask = (~0) << (32 - src_ip_depth); if (dst_ip_depth) dst_ip_netmask = ((~0) << (32 - dst_ip_depth)); key->key.ipv4_5tuple.src_ip &= src_ip_netmask; key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask; return 0; } default: return -1; } } int app_pipeline_firewall_add_rule(struct app_params *app, uint32_t pipeline_id, struct pipeline_firewall_key *key, uint32_t priority, uint32_t port_id) { struct app_pipeline_firewall *p; struct app_pipeline_firewall_rule *rule; struct pipeline_firewall_add_msg_req *req; struct pipeline_firewall_add_msg_rsp *rsp; int new_rule; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; if (app_pipeline_firewall_key_check_and_normalize(key) != 0) return -1; /* Find existing rule or allocate new rule */ rule = app_pipeline_firewall_rule_find(p, key); new_rule = (rule == NULL); if (rule == NULL) { rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE); if (rule == NULL) return -1; } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) { if (new_rule) rte_free(rule); return -1; } req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD; memcpy(&req->key, key, sizeof(*key)); req->priority = priority; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) { if (new_rule) rte_free(rule); return -1; } /* Read response and write rule */ if (rsp->status || (rsp->entry_ptr == NULL) || ((new_rule == 0) && (rsp->key_found == 0)) || ((new_rule == 1) && (rsp->key_found == 1))) { app_msg_free(app, rsp); if (new_rule) rte_free(rule); return -1; } memcpy(&rule->key, key, sizeof(*key)); rule->priority = priority; rule->port_id = port_id; rule->entry_ptr = rsp->entry_ptr; /* Commit rule */ if (new_rule) { TAILQ_INSERT_TAIL(&p->rules, rule, node); p->n_rules++; } print_firewall_ipv4_rule(rule); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_firewall_delete_rule(struct app_params *app, uint32_t pipeline_id, struct pipeline_firewall_key *key) { struct app_pipeline_firewall *p; struct app_pipeline_firewall_rule *rule; struct pipeline_firewall_del_msg_req *req; struct pipeline_firewall_del_msg_rsp *rsp; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (app_pipeline_firewall_key_check_and_normalize(key) != 0) return -1; /* Find rule */ rule = app_pipeline_firewall_rule_find(p, key); if (rule == NULL) return 0; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL; memcpy(&req->key, key, sizeof(*key)); /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status || !rsp->key_found) { app_msg_free(app, rsp); return -1; } /* Remove rule */ TAILQ_REMOVE(&p->rules, rule, node); p->n_rules--; rte_free(rule); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_firewall_add_default_rule(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct app_pipeline_firewall *p; struct pipeline_firewall_add_default_msg_req *req; struct pipeline_firewall_add_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write rule */ if (rsp->status || (rsp->entry_ptr == NULL)) { app_msg_free(app, rsp); return -1; } p->default_rule_port_id = port_id; p->default_rule_entry_ptr = rsp->entry_ptr; /* Commit rule */ p->default_rule_present = 1; /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_firewall_delete_default_rule(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_firewall *p; struct pipeline_firewall_del_default_msg_req *req; struct pipeline_firewall_del_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write rule */ if (rsp->status) { app_msg_free(app, rsp); return -1; } /* Commit rule */ p->default_rule_present = 0; /* Free response */ app_msg_free(app, rsp); return 0; } /* * p firewall add ipv4 */ struct cmd_firewall_add_ipv4_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv4_string; int32_t priority; cmdline_ipaddr_t src_ip; uint32_t src_ip_mask; cmdline_ipaddr_t dst_ip; uint32_t dst_ip_mask; uint16_t src_port_from; uint16_t src_port_to; uint16_t dst_port_from; uint16_t dst_port_to; uint8_t proto; uint8_t proto_mask; uint8_t port_id; }; static void cmd_firewall_add_ipv4_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_firewall_add_ipv4_result *params = parsed_result; struct app_params *app = data; struct pipeline_firewall_key key; int status; key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; key.key.ipv4_5tuple.src_ip = rte_bswap32( (uint32_t) params->src_ip.addr.ipv4.s_addr); key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; key.key.ipv4_5tuple.dst_ip = rte_bswap32( (uint32_t) params->dst_ip.addr.ipv4.s_addr); key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; key.key.ipv4_5tuple.src_port_from = params->src_port_from; key.key.ipv4_5tuple.src_port_to = params->src_port_to; key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; key.key.ipv4_5tuple.proto = params->proto; key.key.ipv4_5tuple.proto_mask = params->proto_mask; status = app_pipeline_firewall_add_rule(app, params->pipeline_id, &key, params->priority, params->port_id); if (status != 0) { printf("Command failed\n"); return; } } cmdline_parse_token_string_t cmd_firewall_add_ipv4_p_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, p_string, "p"); cmdline_parse_token_num_t cmd_firewall_add_ipv4_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_firewall_add_ipv4_firewall_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, firewall_string, "firewall"); cmdline_parse_token_string_t cmd_firewall_add_ipv4_add_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, add_string, "add"); cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, ipv4_string, "ipv4"); cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority, INT32); cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip = TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip); cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_ip_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip_mask, UINT32); cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_dst_ip = TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip); cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_ip_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip_mask, UINT32); cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_from = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_from, UINT16); cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_to = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_to, UINT16); cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_from = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_from, UINT16); cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_to = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_to, UINT16); cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto, UINT8); cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto_mask, UINT8); cmdline_parse_token_num_t cmd_firewall_add_ipv4_port_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, port_id, UINT8); cmdline_parse_inst_t cmd_firewall_add_ipv4 = { .f = cmd_firewall_add_ipv4_parsed, .data = NULL, .help_str = "Firewall rule add", .tokens = { (void *) &cmd_firewall_add_ipv4_p_string, (void *) &cmd_firewall_add_ipv4_pipeline_id, (void *) &cmd_firewall_add_ipv4_firewall_string, (void *) &cmd_firewall_add_ipv4_add_string, (void *) &cmd_firewall_add_ipv4_ipv4_string, (void *) &cmd_firewall_add_ipv4_priority, (void *) &cmd_firewall_add_ipv4_src_ip, (void *) &cmd_firewall_add_ipv4_src_ip_mask, (void *) &cmd_firewall_add_ipv4_dst_ip, (void *) &cmd_firewall_add_ipv4_dst_ip_mask, (void *) &cmd_firewall_add_ipv4_src_port_from, (void *) &cmd_firewall_add_ipv4_src_port_to, (void *) &cmd_firewall_add_ipv4_dst_port_from, (void *) &cmd_firewall_add_ipv4_dst_port_to, (void *) &cmd_firewall_add_ipv4_proto, (void *) &cmd_firewall_add_ipv4_proto_mask, (void *) &cmd_firewall_add_ipv4_port_id, NULL, }, }; /* * p firewall del ipv4 */ struct cmd_firewall_del_ipv4_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t ipv4_string; cmdline_ipaddr_t src_ip; uint32_t src_ip_mask; cmdline_ipaddr_t dst_ip; uint32_t dst_ip_mask; uint16_t src_port_from; uint16_t src_port_to; uint16_t dst_port_from; uint16_t dst_port_to; uint8_t proto; uint8_t proto_mask; }; static void cmd_firewall_del_ipv4_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_firewall_del_ipv4_result *params = parsed_result; struct app_params *app = data; struct pipeline_firewall_key key; int status; key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; key.key.ipv4_5tuple.src_ip = rte_bswap32( (uint32_t) params->src_ip.addr.ipv4.s_addr); key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; key.key.ipv4_5tuple.dst_ip = rte_bswap32( (uint32_t) params->dst_ip.addr.ipv4.s_addr); key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; key.key.ipv4_5tuple.src_port_from = params->src_port_from; key.key.ipv4_5tuple.src_port_to = params->src_port_to; key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; key.key.ipv4_5tuple.proto = params->proto; key.key.ipv4_5tuple.proto_mask = params->proto_mask; status = app_pipeline_firewall_delete_rule(app, params->pipeline_id, &key); if (status != 0) { printf("Command failed\n"); return; } } cmdline_parse_token_string_t cmd_firewall_del_ipv4_p_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, p_string, "p"); cmdline_parse_token_num_t cmd_firewall_del_ipv4_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_firewall_del_ipv4_firewall_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, firewall_string, "firewall"); cmdline_parse_token_string_t cmd_firewall_del_ipv4_del_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, del_string, "del"); cmdline_parse_token_string_t cmd_firewall_del_ipv4_ipv4_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, ipv4_string, "ipv4"); cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_src_ip = TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip); cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_ip_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip_mask, UINT32); cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_dst_ip = TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip); cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_ip_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip_mask, UINT32); cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_from = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_from, UINT16); cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_to = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_to, UINT16); cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_from = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_from, UINT16); cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_to = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_to, UINT16); cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto, UINT8); cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask, UINT8); cmdline_parse_inst_t cmd_firewall_del_ipv4 = { .f = cmd_firewall_del_ipv4_parsed, .data = NULL, .help_str = "Firewall rule delete", .tokens = { (void *) &cmd_firewall_del_ipv4_p_string, (void *) &cmd_firewall_del_ipv4_pipeline_id, (void *) &cmd_firewall_del_ipv4_firewall_string, (void *) &cmd_firewall_del_ipv4_del_string, (void *) &cmd_firewall_del_ipv4_ipv4_string, (void *) &cmd_firewall_del_ipv4_src_ip, (void *) &cmd_firewall_del_ipv4_src_ip_mask, (void *) &cmd_firewall_del_ipv4_dst_ip, (void *) &cmd_firewall_del_ipv4_dst_ip_mask, (void *) &cmd_firewall_del_ipv4_src_port_from, (void *) &cmd_firewall_del_ipv4_src_port_to, (void *) &cmd_firewall_del_ipv4_dst_port_from, (void *) &cmd_firewall_del_ipv4_dst_port_to, (void *) &cmd_firewall_del_ipv4_proto, (void *) &cmd_firewall_del_ipv4_proto_mask, NULL, }, }; /* * p firewall add default */ struct cmd_firewall_add_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t default_string; uint8_t port_id; }; static void cmd_firewall_add_default_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_firewall_add_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_firewall_add_default_rule(app, params->pipeline_id, params->port_id); if (status != 0) { printf("Command failed\n"); return; } } cmdline_parse_token_string_t cmd_firewall_add_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_firewall_add_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_firewall_add_default_firewall_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, firewall_string, "firewall"); cmdline_parse_token_string_t cmd_firewall_add_default_add_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, add_string, "add"); cmdline_parse_token_string_t cmd_firewall_add_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, default_string, "default"); cmdline_parse_token_num_t cmd_firewall_add_default_port_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id, UINT8); cmdline_parse_inst_t cmd_firewall_add_default = { .f = cmd_firewall_add_default_parsed, .data = NULL, .help_str = "Firewall default rule add", .tokens = { (void *) &cmd_firewall_add_default_p_string, (void *) &cmd_firewall_add_default_pipeline_id, (void *) &cmd_firewall_add_default_firewall_string, (void *) &cmd_firewall_add_default_add_string, (void *) &cmd_firewall_add_default_default_string, (void *) &cmd_firewall_add_default_port_id, NULL, }, }; /* * p firewall del default */ struct cmd_firewall_del_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t default_string; }; static void cmd_firewall_del_default_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_firewall_del_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_firewall_delete_default_rule(app, params->pipeline_id); if (status != 0) { printf("Command failed\n"); return; } } cmdline_parse_token_string_t cmd_firewall_del_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_firewall_del_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_firewall_del_default_firewall_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, firewall_string, "firewall"); cmdline_parse_token_string_t cmd_firewall_del_default_del_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, del_string, "del"); cmdline_parse_token_string_t cmd_firewall_del_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, default_string, "default"); cmdline_parse_inst_t cmd_firewall_del_default = { .f = cmd_firewall_del_default_parsed, .data = NULL, .help_str = "Firewall default rule delete", .tokens = { (void *) &cmd_firewall_del_default_p_string, (void *) &cmd_firewall_del_default_pipeline_id, (void *) &cmd_firewall_del_default_firewall_string, (void *) &cmd_firewall_del_default_del_string, (void *) &cmd_firewall_del_default_default_string, NULL, }, }; /* * p firewall ls */ struct cmd_firewall_ls_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; cmdline_fixed_string_t ls_string; }; static void cmd_firewall_ls_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_firewall_ls_result *params = parsed_result; struct app_params *app = data; app_pipeline_firewall_ls(app, params->pipeline_id); } cmdline_parse_token_string_t cmd_firewall_ls_p_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string, "p"); cmdline_parse_token_num_t cmd_firewall_ls_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_firewall_ls_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_firewall_ls_firewall_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, firewall_string, "firewall"); cmdline_parse_token_string_t cmd_firewall_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, ls_string, "ls"); cmdline_parse_inst_t cmd_firewall_ls = { .f = cmd_firewall_ls_parsed, .data = NULL, .help_str = "Firewall rule list", .tokens = { (void *) &cmd_firewall_ls_p_string, (void *) &cmd_firewall_ls_pipeline_id, (void *) &cmd_firewall_ls_firewall_string, (void *) &cmd_firewall_ls_ls_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { (cmdline_parse_inst_t *) &cmd_firewall_add_ipv4, (cmdline_parse_inst_t *) &cmd_firewall_del_ipv4, (cmdline_parse_inst_t *) &cmd_firewall_add_default, (cmdline_parse_inst_t *) &cmd_firewall_del_default, (cmdline_parse_inst_t *) &cmd_firewall_ls, NULL, }; static struct pipeline_fe_ops pipeline_firewall_fe_ops = { .f_init = app_pipeline_firewall_init, .f_free = app_pipeline_firewall_free, .cmds = pipeline_cmds, }; struct pipeline_type pipeline_firewall = { .name = "FIREWALL", .be_ops = &pipeline_firewall_be_ops, .fe_ops = &pipeline_firewall_fe_ops, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_firewall.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_FIREWALL_H__ #define __INCLUDE_PIPELINE_FIREWALL_H__ #include "pipeline.h" #include "pipeline_firewall_be.h" int app_pipeline_firewall_add_rule(struct app_params *app, uint32_t pipeline_id, struct pipeline_firewall_key *key, uint32_t priority, uint32_t port_id); int app_pipeline_firewall_delete_rule(struct app_params *app, uint32_t pipeline_id, struct pipeline_firewall_key *key); int app_pipeline_firewall_add_default_rule(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_pipeline_firewall_delete_default_rule(struct app_params *app, uint32_t pipeline_id); extern struct pipeline_type pipeline_firewall; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_firewall_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "pipeline_firewall_be.h" struct pipeline_firewall { struct pipeline p; pipeline_msg_req_handler custom_handlers[PIPELINE_FIREWALL_MSG_REQS]; uint32_t n_rules; uint32_t n_rule_fields; struct rte_acl_field_def *field_format; uint32_t field_format_size; } __rte_cache_aligned; static void * pipeline_firewall_msg_req_custom_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler handlers[] = { [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler, [PIPELINE_MSG_REQ_STATS_PORT_IN] = pipeline_msg_req_stats_port_in_handler, [PIPELINE_MSG_REQ_STATS_PORT_OUT] = pipeline_msg_req_stats_port_out_handler, [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler, [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = pipeline_msg_req_port_in_enable_handler, [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = pipeline_msg_req_port_in_disable_handler, [PIPELINE_MSG_REQ_CUSTOM] = pipeline_firewall_msg_req_custom_handler, }; static void * pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg); static void * pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg); static void * pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg); static void * pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler custom_handlers[] = { [PIPELINE_FIREWALL_MSG_REQ_ADD] = pipeline_firewall_msg_req_add_handler, [PIPELINE_FIREWALL_MSG_REQ_DEL] = pipeline_firewall_msg_req_del_handler, [PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] = pipeline_firewall_msg_req_add_default_handler, [PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] = pipeline_firewall_msg_req_del_default_handler, }; /* * Firewall table */ struct firewall_table_entry { struct rte_pipeline_table_entry head; }; static struct rte_acl_field_def field_format_ipv4[] = { /* Protocol */ [0] = { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = 0, .input_index = 0, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, next_proto_id), }, /* Source IP address (IPv4) */ [1] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 1, .input_index = 1, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, src_addr), }, /* Destination IP address (IPv4) */ [2] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 2, .input_index = 2, .offset = sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, dst_addr), }, /* Source Port */ [3] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 3, .input_index = 3, .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port), }, /* Destination Port */ [4] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 4, .input_index = 4, .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port), }, }; #define SIZEOF_VLAN_HDR 4 static struct rte_acl_field_def field_format_vlan_ipv4[] = { /* Protocol */ [0] = { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = 0, .input_index = 0, .offset = sizeof(struct ether_hdr) + SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, next_proto_id), }, /* Source IP address (IPv4) */ [1] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 1, .input_index = 1, .offset = sizeof(struct ether_hdr) + SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, src_addr), }, /* Destination IP address (IPv4) */ [2] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 2, .input_index = 2, .offset = sizeof(struct ether_hdr) + SIZEOF_VLAN_HDR + offsetof(struct ipv4_hdr, dst_addr), }, /* Source Port */ [3] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 3, .input_index = 3, .offset = sizeof(struct ether_hdr) + SIZEOF_VLAN_HDR + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port), }, /* Destination Port */ [4] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 4, .input_index = 4, .offset = sizeof(struct ether_hdr) + SIZEOF_VLAN_HDR + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port), }, }; #define SIZEOF_QINQ_HEADER 8 static struct rte_acl_field_def field_format_qinq_ipv4[] = { /* Protocol */ [0] = { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = 0, .input_index = 0, .offset = sizeof(struct ether_hdr) + SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, next_proto_id), }, /* Source IP address (IPv4) */ [1] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 1, .input_index = 1, .offset = sizeof(struct ether_hdr) + SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, src_addr), }, /* Destination IP address (IPv4) */ [2] = { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = 2, .input_index = 2, .offset = sizeof(struct ether_hdr) + SIZEOF_QINQ_HEADER + offsetof(struct ipv4_hdr, dst_addr), }, /* Source Port */ [3] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 3, .input_index = 3, .offset = sizeof(struct ether_hdr) + SIZEOF_QINQ_HEADER + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, src_port), }, /* Destination Port */ [4] = { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = 4, .input_index = 4, .offset = sizeof(struct ether_hdr) + SIZEOF_QINQ_HEADER + sizeof(struct ipv4_hdr) + offsetof(struct tcp_hdr, dst_port), }, }; static int pipeline_firewall_parse_args(struct pipeline_firewall *p, struct pipeline_params *params) { uint32_t n_rules_present = 0; uint32_t pkt_type_present = 0; uint32_t i; /* defaults */ p->n_rules = 4 * 1024; p->n_rule_fields = RTE_DIM(field_format_ipv4); p->field_format = field_format_ipv4; p->field_format_size = sizeof(field_format_ipv4); for (i = 0; i < params->n_args; i++) { char *arg_name = params->args_name[i]; char *arg_value = params->args_value[i]; if (strcmp(arg_name, "n_rules") == 0) { if (n_rules_present) return -1; n_rules_present = 1; p->n_rules = atoi(arg_value); continue; } if (strcmp(arg_name, "pkt_type") == 0) { if (pkt_type_present) return -1; pkt_type_present = 1; /* ipv4 */ if (strcmp(arg_value, "ipv4") == 0) { p->n_rule_fields = RTE_DIM(field_format_ipv4); p->field_format = field_format_ipv4; p->field_format_size = sizeof(field_format_ipv4); continue; } /* vlan_ipv4 */ if (strcmp(arg_value, "vlan_ipv4") == 0) { p->n_rule_fields = RTE_DIM(field_format_vlan_ipv4); p->field_format = field_format_vlan_ipv4; p->field_format_size = sizeof(field_format_vlan_ipv4); continue; } /* qinq_ipv4 */ if (strcmp(arg_value, "qinq_ipv4") == 0) { p->n_rule_fields = RTE_DIM(field_format_qinq_ipv4); p->field_format = field_format_qinq_ipv4; p->field_format_size = sizeof(field_format_qinq_ipv4); continue; } /* other */ return -1; } /* other */ return -1; } return 0; } static void * pipeline_firewall_init(struct pipeline_params *params, __rte_unused void *arg) { struct pipeline *p; struct pipeline_firewall *p_fw; uint32_t size, i; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_firewall)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); p_fw = (struct pipeline_firewall *) p; if (p == NULL) return NULL; strcpy(p->name, params->name); p->log_level = params->log_level; PLOG(p, HIGH, "Firewall"); /* Parse arguments */ if (pipeline_firewall_parse_args(p_fw, params)) return NULL; /* Pipeline */ { struct rte_pipeline_params pipeline_params = { .name = params->name, .socket_id = params->socket_id, .offset_port_id = 0, }; p->p = rte_pipeline_create(&pipeline_params); if (p->p == NULL) { rte_free(p); return NULL; } } /* Input ports */ p->n_ports_in = params->n_ports_in; for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_port_in_params port_params = { .ops = pipeline_port_in_params_get_ops( ¶ms->port_in[i]), .arg_create = pipeline_port_in_params_convert( ¶ms->port_in[i]), .f_action = NULL, .arg_ah = NULL, .burst_size = params->port_in[i].burst_size, }; int status = rte_pipeline_port_in_create(p->p, &port_params, &p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Output ports */ p->n_ports_out = params->n_ports_out; for (i = 0; i < p->n_ports_out; i++) { struct rte_pipeline_port_out_params port_params = { .ops = pipeline_port_out_params_get_ops( ¶ms->port_out[i]), .arg_create = pipeline_port_out_params_convert( ¶ms->port_out[i]), .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; int status = rte_pipeline_port_out_create(p->p, &port_params, &p->port_out_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Tables */ p->n_tables = 1; { struct rte_table_acl_params table_acl_params = { .name = params->name, .n_rules = p_fw->n_rules, .n_rule_fields = p_fw->n_rule_fields, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_acl_ops, .arg_create = &table_acl_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = sizeof(struct firewall_table_entry) - sizeof(struct rte_pipeline_table_entry), }; int status; memcpy(table_acl_params.field_format, p_fw->field_format, p_fw->field_format_size); status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Connecting input ports to tables */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_connect_to_table(p->p, p->port_in_id[i], p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Enable input ports */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_enable(p->p, p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Check pipeline consistency */ if (rte_pipeline_check(p->p) < 0) { rte_pipeline_free(p->p); rte_free(p); return NULL; } /* Message queues */ p->n_msgq = params->n_msgq; for (i = 0; i < p->n_msgq; i++) p->msgq_in[i] = params->msgq_in[i]; for (i = 0; i < p->n_msgq; i++) p->msgq_out[i] = params->msgq_out[i]; /* Message handlers */ memcpy(p->handlers, handlers, sizeof(p->handlers)); memcpy(p_fw->custom_handlers, custom_handlers, sizeof(p_fw->custom_handlers)); return p; } static int pipeline_firewall_free(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ rte_pipeline_free(p->p); rte_free(p); return 0; } static int pipeline_firewall_track(void *pipeline, __rte_unused uint32_t port_in, uint32_t *port_out) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL)) return -1; if (p->n_ports_in == 1) { *port_out = 0; return 0; } return -1; } static int pipeline_firewall_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; pipeline_msg_req_handle(p); rte_pipeline_flush(p->p); return 0; } void * pipeline_firewall_msg_req_custom_handler(struct pipeline *p, void *msg) { struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p; struct pipeline_custom_msg_req *req = msg; pipeline_msg_req_handler f_handle; f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS) ? p_fw->custom_handlers[req->subtype] : pipeline_msg_req_invalid_handler; if (f_handle == NULL) f_handle = pipeline_msg_req_invalid_handler; return f_handle(p, req); } void * pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg) { struct pipeline_firewall_add_msg_req *req = msg; struct pipeline_firewall_add_msg_rsp *rsp = msg; struct rte_table_acl_rule_add_params params; struct firewall_table_entry entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, }; memset(¶ms, 0, sizeof(params)); switch (req->key.type) { case PIPELINE_FIREWALL_IPV4_5TUPLE: params.priority = req->priority; params.field_value[0].value.u8 = req->key.key.ipv4_5tuple.proto; params.field_value[0].mask_range.u8 = req->key.key.ipv4_5tuple.proto_mask; params.field_value[1].value.u32 = req->key.key.ipv4_5tuple.src_ip; params.field_value[1].mask_range.u32 = req->key.key.ipv4_5tuple.src_ip_mask; params.field_value[2].value.u32 = req->key.key.ipv4_5tuple.dst_ip; params.field_value[2].mask_range.u32 = req->key.key.ipv4_5tuple.dst_ip_mask; params.field_value[3].value.u16 = req->key.key.ipv4_5tuple.src_port_from; params.field_value[3].mask_range.u16 = req->key.key.ipv4_5tuple.src_port_to; params.field_value[4].value.u16 = req->key.key.ipv4_5tuple.dst_port_from; params.field_value[4].mask_range.u16 = req->key.key.ipv4_5tuple.dst_port_to; break; default: rsp->status = -1; /* Error */ return rsp; } rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], ¶ms, (struct rte_pipeline_table_entry *) &entry, &rsp->key_found, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg) { struct pipeline_firewall_del_msg_req *req = msg; struct pipeline_firewall_del_msg_rsp *rsp = msg; struct rte_table_acl_rule_delete_params params; memset(¶ms, 0, sizeof(params)); switch (req->key.type) { case PIPELINE_FIREWALL_IPV4_5TUPLE: params.field_value[0].value.u8 = req->key.key.ipv4_5tuple.proto; params.field_value[0].mask_range.u8 = req->key.key.ipv4_5tuple.proto_mask; params.field_value[1].value.u32 = req->key.key.ipv4_5tuple.src_ip; params.field_value[1].mask_range.u32 = req->key.key.ipv4_5tuple.src_ip_mask; params.field_value[2].value.u32 = req->key.key.ipv4_5tuple.dst_ip; params.field_value[2].mask_range.u32 = req->key.key.ipv4_5tuple.dst_ip_mask; params.field_value[3].value.u16 = req->key.key.ipv4_5tuple.src_port_from; params.field_value[3].mask_range.u16 = req->key.key.ipv4_5tuple.src_port_to; params.field_value[4].value.u16 = req->key.key.ipv4_5tuple.dst_port_from; params.field_value[4].mask_range.u16 = req->key.key.ipv4_5tuple.dst_port_to; break; default: rsp->status = -1; /* Error */ return rsp; } rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], ¶ms, &rsp->key_found, NULL); return rsp; } void * pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg) { struct pipeline_firewall_add_default_msg_req *req = msg; struct pipeline_firewall_add_default_msg_rsp *rsp = msg; struct firewall_table_entry default_entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, }; rsp->status = rte_pipeline_table_default_entry_add(p->p, p->table_id[0], (struct rte_pipeline_table_entry *) &default_entry, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg) { struct pipeline_firewall_del_default_msg_rsp *rsp = msg; rsp->status = rte_pipeline_table_default_entry_delete(p->p, p->table_id[0], NULL); return rsp; } struct pipeline_be_ops pipeline_firewall_be_ops = { .f_init = pipeline_firewall_init, .f_free = pipeline_firewall_free, .f_run = NULL, .f_timer = pipeline_firewall_timer, .f_track = pipeline_firewall_track, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_firewall_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_FIREWALL_BE_H__ #define __INCLUDE_PIPELINE_FIREWALL_BE_H__ #include "pipeline_common_be.h" enum pipeline_firewall_key_type { PIPELINE_FIREWALL_IPV4_5TUPLE, }; struct pipeline_firewall_key_ipv4_5tuple { uint32_t src_ip; uint32_t src_ip_mask; uint32_t dst_ip; uint32_t dst_ip_mask; uint16_t src_port_from; uint16_t src_port_to; uint16_t dst_port_from; uint16_t dst_port_to; uint8_t proto; uint8_t proto_mask; }; struct pipeline_firewall_key { enum pipeline_firewall_key_type type; union { struct pipeline_firewall_key_ipv4_5tuple ipv4_5tuple; } key; }; enum pipeline_firewall_msg_req_type { PIPELINE_FIREWALL_MSG_REQ_ADD = 0, PIPELINE_FIREWALL_MSG_REQ_DEL, PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT, PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT, PIPELINE_FIREWALL_MSG_REQS }; /* * MSG ADD */ struct pipeline_firewall_add_msg_req { enum pipeline_msg_req_type type; enum pipeline_firewall_msg_req_type subtype; /* key */ struct pipeline_firewall_key key; /* data */ int32_t priority; uint32_t port_id; }; struct pipeline_firewall_add_msg_rsp { int status; int key_found; void *entry_ptr; }; /* * MSG DEL */ struct pipeline_firewall_del_msg_req { enum pipeline_msg_req_type type; enum pipeline_firewall_msg_req_type subtype; /* key */ struct pipeline_firewall_key key; }; struct pipeline_firewall_del_msg_rsp { int status; int key_found; }; /* * MSG ADD DEFAULT */ struct pipeline_firewall_add_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_firewall_msg_req_type subtype; /* data */ uint32_t port_id; }; struct pipeline_firewall_add_default_msg_rsp { int status; void *entry_ptr; }; /* * MSG DEL DEFAULT */ struct pipeline_firewall_del_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_firewall_msg_req_type subtype; }; struct pipeline_firewall_del_default_msg_rsp { int status; }; extern struct pipeline_be_ops pipeline_firewall_be_ops; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_flow_classification.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_flow_classification.h" #include "hash_func.h" /* * Key conversion */ struct pkt_key_qinq { uint16_t ethertype_svlan; uint16_t svlan; uint16_t ethertype_cvlan; uint16_t cvlan; } __attribute__((__packed__)); struct pkt_key_ipv4_5tuple { uint8_t ttl; uint8_t proto; uint16_t checksum; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; } __attribute__((__packed__)); struct pkt_key_ipv6_5tuple { uint16_t payload_length; uint8_t proto; uint8_t hop_limit; uint8_t ip_src[16]; uint8_t ip_dst[16]; uint16_t port_src; uint16_t port_dst; } __attribute__((__packed__)); static int app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, uint8_t *key_out, uint32_t *signature) { uint8_t buffer[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; void *key_buffer = (key_out) ? key_out : buffer; switch (key_in->type) { case FLOW_KEY_QINQ: { struct pkt_key_qinq *qinq = key_buffer; qinq->ethertype_svlan = 0; qinq->svlan = rte_bswap16(key_in->key.qinq.svlan); qinq->ethertype_cvlan = 0; qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan); if (signature) *signature = (uint32_t) hash_default_key8(qinq, 8, 0); return 0; } case FLOW_KEY_IPV4_5TUPLE: { struct pkt_key_ipv4_5tuple *ipv4 = key_buffer; ipv4->ttl = 0; ipv4->proto = key_in->key.ipv4_5tuple.proto; ipv4->checksum = 0; ipv4->ip_src = rte_bswap32(key_in->key.ipv4_5tuple.ip_src); ipv4->ip_dst = rte_bswap32(key_in->key.ipv4_5tuple.ip_dst); ipv4->port_src = rte_bswap16(key_in->key.ipv4_5tuple.port_src); ipv4->port_dst = rte_bswap16(key_in->key.ipv4_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key16(ipv4, 16, 0); return 0; } case FLOW_KEY_IPV6_5TUPLE: { struct pkt_key_ipv6_5tuple *ipv6 = key_buffer; memset(ipv6, 0, 64); ipv6->payload_length = 0; ipv6->proto = key_in->key.ipv6_5tuple.proto; ipv6->hop_limit = 0; memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16); memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16); ipv6->port_src = rte_bswap16(key_in->key.ipv6_5tuple.port_src); ipv6->port_dst = rte_bswap16(key_in->key.ipv6_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key64(ipv6, 64, 0); return 0; } default: return -1; } } /* * Flow classification pipeline */ struct app_pipeline_fc_flow { struct pipeline_fc_key key; uint32_t port_id; uint32_t signature; void *entry_ptr; TAILQ_ENTRY(app_pipeline_fc_flow) node; }; #define N_BUCKETS 65536 struct app_pipeline_fc { /* Parameters */ uint32_t n_ports_in; uint32_t n_ports_out; /* Flows */ TAILQ_HEAD(, app_pipeline_fc_flow) flows[N_BUCKETS]; uint32_t n_flows; /* Default flow */ uint32_t default_flow_present; uint32_t default_flow_port_id; void *default_flow_entry_ptr; }; static struct app_pipeline_fc_flow * app_pipeline_fc_flow_find(struct app_pipeline_fc *p, struct pipeline_fc_key *key) { struct app_pipeline_fc_flow *f; uint32_t signature, bucket_id; app_pipeline_fc_key_convert(key, NULL, &signature); bucket_id = signature & (N_BUCKETS - 1); TAILQ_FOREACH(f, &p->flows[bucket_id], node) if ((signature == f->signature) && (memcmp(key, &f->key, sizeof(struct pipeline_fc_key)) == 0)) return f; return NULL; } static void* app_pipeline_fc_init(struct pipeline_params *params, __rte_unused void *arg) { struct app_pipeline_fc *p; uint32_t size, i; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; /* Initialization */ p->n_ports_in = params->n_ports_in; p->n_ports_out = params->n_ports_out; for (i = 0; i < N_BUCKETS; i++) TAILQ_INIT(&p->flows[i]); p->n_flows = 0; return (void *) p; } static int app_pipeline_fc_free(void *pipeline) { struct app_pipeline_fc *p = pipeline; uint32_t i; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ for (i = 0; i < N_BUCKETS; i++) while (!TAILQ_EMPTY(&p->flows[i])) { struct app_pipeline_fc_flow *flow; flow = TAILQ_FIRST(&p->flows[i]); TAILQ_REMOVE(&p->flows[i], flow, node); rte_free(flow); } rte_free(p); return 0; } static int app_pipeline_fc_key_check(struct pipeline_fc_key *key) { switch (key->type) { case FLOW_KEY_QINQ: { uint16_t svlan = key->key.qinq.svlan; uint16_t cvlan = key->key.qinq.cvlan; if ((svlan & 0xF000) || (cvlan & 0xF000)) return -1; return 0; } case FLOW_KEY_IPV4_5TUPLE: return 0; case FLOW_KEY_IPV6_5TUPLE: return 0; default: return -1; } } int app_pipeline_fc_add(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t port_id) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; struct pipeline_fc_add_msg_req *req; struct pipeline_fc_add_msg_rsp *rsp; uint32_t signature; int new_flow; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; if (app_pipeline_fc_key_check(key) != 0) return -1; /* Find existing flow or allocate new flow */ flow = app_pipeline_fc_flow_find(p, key); new_flow = (flow == NULL); if (flow == NULL) { flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE); if (flow == NULL) return -1; } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD; app_pipeline_fc_key_convert(key, req->key, &signature); req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) { if (new_flow) rte_free(flow); return -1; } /* Read response and write flow */ if (rsp->status || (rsp->entry_ptr == NULL) || ((new_flow == 0) && (rsp->key_found == 0)) || ((new_flow == 1) && (rsp->key_found == 1))) { app_msg_free(app, rsp); if (new_flow) rte_free(flow); return -1; } memset(&flow->key, 0, sizeof(flow->key)); memcpy(&flow->key, key, sizeof(flow->key)); flow->port_id = port_id; flow->signature = signature; flow->entry_ptr = rsp->entry_ptr; /* Commit rule */ if (new_flow) { uint32_t bucket_id = signature & (N_BUCKETS - 1); TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow, node); p->n_flows++; } /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_add_bulk(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t *port_id, uint32_t n_keys) { struct app_pipeline_fc *p; struct pipeline_fc_add_bulk_msg_req *req; struct pipeline_fc_add_bulk_msg_rsp *rsp; struct app_pipeline_fc_flow **flow; uint32_t *signature; int *new_flow; struct pipeline_fc_add_bulk_flow_req *flow_req; struct pipeline_fc_add_bulk_flow_rsp *flow_rsp; uint32_t i; int status; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (port_id == NULL) || (n_keys == 0)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; for (i = 0; i < n_keys; i++) if (port_id[i] >= p->n_ports_out) return -1; for (i = 0; i < n_keys; i++) if (app_pipeline_fc_key_check(&key[i]) != 0) return -1; /* Memory allocation */ flow = rte_malloc(NULL, n_keys * sizeof(struct app_pipeline_fc_flow *), RTE_CACHE_LINE_SIZE); if (flow == NULL) return -1; signature = rte_malloc(NULL, n_keys * sizeof(uint32_t), RTE_CACHE_LINE_SIZE); if (signature == NULL) { rte_free(flow); return -1; } new_flow = rte_malloc( NULL, n_keys * sizeof(int), RTE_CACHE_LINE_SIZE); if (new_flow == NULL) { rte_free(signature); rte_free(flow); return -1; } flow_req = rte_malloc(NULL, n_keys * sizeof(struct pipeline_fc_add_bulk_flow_req), RTE_CACHE_LINE_SIZE); if (flow_req == NULL) { rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } flow_rsp = rte_malloc(NULL, n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp), RTE_CACHE_LINE_SIZE); if (flow_req == NULL) { rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } /* Find existing flow or allocate new flow */ for (i = 0; i < n_keys; i++) { flow[i] = app_pipeline_fc_flow_find(p, &key[i]); new_flow[i] = (flow[i] == NULL); if (flow[i] == NULL) { flow[i] = rte_zmalloc(NULL, sizeof(struct app_pipeline_fc_flow), RTE_CACHE_LINE_SIZE); if (flow[i] == NULL) { uint32_t j; for (j = 0; j < i; j++) if (new_flow[j]) rte_free(flow[j]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } } } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) { for (i = 0; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } for (i = 0; i < n_keys; i++) { app_pipeline_fc_key_convert(&key[i], flow_req[i].key, &signature[i]); flow_req[i].port_id = port_id[i]; } req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK; req->req = flow_req; req->rsp = flow_rsp; req->n_keys = n_keys; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, 10000); if (rsp == NULL) { for (i = 0; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return -1; } /* Read response */ status = 0; for (i = 0; i < rsp->n_keys; i++) if ((flow_rsp[i].entry_ptr == NULL) || ((new_flow[i] == 0) && (flow_rsp[i].key_found == 0)) || ((new_flow[i] == 1) && (flow_rsp[i].key_found == 1))) status = -1; if (rsp->n_keys < n_keys) status = -1; /* Commit flows */ for (i = 0; i < rsp->n_keys; i++) { memcpy(&flow[i]->key, &key[i], sizeof(flow[i]->key)); flow[i]->port_id = port_id[i]; flow[i]->signature = signature[i]; flow[i]->entry_ptr = flow_rsp[i].entry_ptr; if (new_flow[i]) { uint32_t bucket_id = signature[i] & (N_BUCKETS - 1); TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow[i], node); p->n_flows++; } } /* Free resources */ app_msg_free(app, rsp); for (i = rsp->n_keys; i < n_keys; i++) if (new_flow[i]) rte_free(flow[i]); rte_free(flow_rsp); rte_free(flow_req); rte_free(new_flow); rte_free(signature); rte_free(flow); return status; } int app_pipeline_fc_del(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; struct pipeline_fc_del_msg_req *req; struct pipeline_fc_del_msg_rsp *rsp; uint32_t signature, bucket_id; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (app_pipeline_fc_key_check(key) != 0) return -1; /* Find rule */ flow = app_pipeline_fc_flow_find(p, key); if (flow == NULL) return 0; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL; app_pipeline_fc_key_convert(key, req->key, &signature); /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status || !rsp->key_found) { app_msg_free(app, rsp); return -1; } /* Remove rule */ bucket_id = signature & (N_BUCKETS - 1); TAILQ_REMOVE(&p->flows[bucket_id], flow, node); p->n_flows--; rte_free(flow); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_add_default(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct app_pipeline_fc *p; struct pipeline_fc_add_default_msg_req *req; struct pipeline_fc_add_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write flow */ if (rsp->status || (rsp->entry_ptr == NULL)) { app_msg_free(app, rsp); return -1; } p->default_flow_port_id = port_id; p->default_flow_entry_ptr = rsp->entry_ptr; /* Commit route */ p->default_flow_present = 1; /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_fc_del_default(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_fc *p; struct pipeline_fc_del_default_msg_req *req; struct pipeline_fc_del_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -EINVAL; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status) { app_msg_free(app, rsp); return -1; } /* Commit route */ p->default_flow_present = 0; /* Free response */ app_msg_free(app, rsp); return 0; } /* * Flow ls */ static void print_fc_qinq_flow(struct app_pipeline_fc_flow *flow) { printf("(SVLAN = %" PRIu32 ", " "CVLAN = %" PRIu32 ") => " "Port = %" PRIu32 " " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", flow->key.key.qinq.svlan, flow->key.key.qinq.cvlan, flow->port_id, flow->signature, flow->entry_ptr); } static void print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow) { printf("(SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " "DA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", " "SP = %" PRIu32 ", " "DP = %" PRIu32 ", " "Proto = %" PRIu32 ") => " "Port = %" PRIu32 " " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF, (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF, (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF, flow->key.key.ipv4_5tuple.ip_src & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF, (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF, flow->key.key.ipv4_5tuple.ip_dst & 0xFF, flow->key.key.ipv4_5tuple.port_src, flow->key.key.ipv4_5tuple.port_dst, flow->key.key.ipv4_5tuple.proto, flow->port_id, flow->signature, flow->entry_ptr); } static void print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) { printf("(SA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " "DA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", " "SP = %" PRIu32 ", " "DP = %" PRIu32 " " "Proto = %" PRIu32 " " "=> Port = %" PRIu32 " " "(signature = 0x%08" PRIx32 ", " "entry_ptr = %p)\n", flow->key.key.ipv6_5tuple.ip_src[0], flow->key.key.ipv6_5tuple.ip_src[1], flow->key.key.ipv6_5tuple.ip_src[2], flow->key.key.ipv6_5tuple.ip_src[3], flow->key.key.ipv6_5tuple.ip_src[4], flow->key.key.ipv6_5tuple.ip_src[5], flow->key.key.ipv6_5tuple.ip_src[6], flow->key.key.ipv6_5tuple.ip_src[7], flow->key.key.ipv6_5tuple.ip_src[8], flow->key.key.ipv6_5tuple.ip_src[9], flow->key.key.ipv6_5tuple.ip_src[10], flow->key.key.ipv6_5tuple.ip_src[11], flow->key.key.ipv6_5tuple.ip_src[12], flow->key.key.ipv6_5tuple.ip_src[13], flow->key.key.ipv6_5tuple.ip_src[14], flow->key.key.ipv6_5tuple.ip_src[15], flow->key.key.ipv6_5tuple.ip_dst[0], flow->key.key.ipv6_5tuple.ip_dst[1], flow->key.key.ipv6_5tuple.ip_dst[2], flow->key.key.ipv6_5tuple.ip_dst[3], flow->key.key.ipv6_5tuple.ip_dst[4], flow->key.key.ipv6_5tuple.ip_dst[5], flow->key.key.ipv6_5tuple.ip_dst[6], flow->key.key.ipv6_5tuple.ip_dst[7], flow->key.key.ipv6_5tuple.ip_dst[8], flow->key.key.ipv6_5tuple.ip_dst[9], flow->key.key.ipv6_5tuple.ip_dst[10], flow->key.key.ipv6_5tuple.ip_dst[11], flow->key.key.ipv6_5tuple.ip_dst[12], flow->key.key.ipv6_5tuple.ip_dst[13], flow->key.key.ipv6_5tuple.ip_dst[14], flow->key.key.ipv6_5tuple.ip_dst[15], flow->key.key.ipv6_5tuple.port_src, flow->key.key.ipv6_5tuple.port_dst, flow->key.key.ipv6_5tuple.proto, flow->port_id, flow->signature, flow->entry_ptr); } static void print_fc_flow(struct app_pipeline_fc_flow *flow) { switch (flow->key.type) { case FLOW_KEY_QINQ: print_fc_qinq_flow(flow); break; case FLOW_KEY_IPV4_5TUPLE: print_fc_ipv4_5tuple_flow(flow); break; case FLOW_KEY_IPV6_5TUPLE: print_fc_ipv6_5tuple_flow(flow); break; } } static int app_pipeline_fc_ls(struct app_params *app, uint32_t pipeline_id) { struct app_pipeline_fc *p; struct app_pipeline_fc_flow *flow; uint32_t i; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; for (i = 0; i < N_BUCKETS; i++) TAILQ_FOREACH(flow, &p->flows[i], node) print_fc_flow(flow); if (p->default_flow_present) printf("Default flow: port %" PRIu32 " (entry ptr = %p)\n", p->default_flow_port_id, p->default_flow_entry_ptr); else printf("Default: DROP\n"); return 0; } /* * flow add qinq */ struct cmd_fc_add_qinq_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t qinq_string; uint16_t svlan; uint16_t cvlan; uint32_t port; }; static void cmd_fc_add_qinq_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_qinq_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_QINQ; key.key.qinq.svlan = params->svlan; key.key.qinq.cvlan = params->cvlan; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_qinq_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_qinq_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, qinq_string, "qinq"); cmdline_parse_token_num_t cmd_fc_add_qinq_svlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16); cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16); cmdline_parse_token_num_t cmd_fc_add_qinq_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32); cmdline_parse_inst_t cmd_fc_add_qinq = { .f = cmd_fc_add_qinq_parsed, .data = NULL, .help_str = "Flow add (Q-in-Q)", .tokens = { (void *) &cmd_fc_add_qinq_p_string, (void *) &cmd_fc_add_qinq_pipeline_id, (void *) &cmd_fc_add_qinq_flow_string, (void *) &cmd_fc_add_qinq_add_string, (void *) &cmd_fc_add_qinq_qinq_string, (void *) &cmd_fc_add_qinq_svlan, (void *) &cmd_fc_add_qinq_cvlan, (void *) &cmd_fc_add_qinq_port, NULL, }, }; /* * flow add qinq all */ struct cmd_fc_add_qinq_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t qinq_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; #ifndef N_FLOWS_BULK #define N_FLOWS_BULK 4096 #endif static void cmd_fc_add_qinq_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_qinq_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t flow_id; key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } for (flow_id = 0; flow_id < params->n_flows; flow_id++) { uint32_t pos = flow_id & (N_FLOWS_BULK - 1); key[pos].type = FLOW_KEY_QINQ; key[pos].key.qinq.svlan = flow_id >> 12; key[pos].key.qinq.cvlan = flow_id & 0xFFF; port_id[pos] = flow_id % params->n_ports; if ((pos == N_FLOWS_BULK - 1) || (flow_id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_qinq_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_qinq_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_qinq_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, qinq_string, "qinq"); cmdline_parse_token_string_t cmd_fc_add_qinq_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_qinq_all = { .f = cmd_fc_add_qinq_all_parsed, .data = NULL, .help_str = "Flow add all (Q-in-Q)", .tokens = { (void *) &cmd_fc_add_qinq_all_p_string, (void *) &cmd_fc_add_qinq_all_pipeline_id, (void *) &cmd_fc_add_qinq_all_flow_string, (void *) &cmd_fc_add_qinq_all_add_string, (void *) &cmd_fc_add_qinq_all_qinq_string, (void *) &cmd_fc_add_qinq_all_all_string, (void *) &cmd_fc_add_qinq_all_n_flows, (void *) &cmd_fc_add_qinq_all_n_ports, NULL, }, }; /* * flow add ipv4_5tuple */ struct cmd_fc_add_ipv4_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; uint32_t port; }; static void cmd_fc_add_ipv4_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV4_5TUPLE; key.key.ipv4_5tuple.ip_src = rte_bswap32( params->ip_src.addr.ipv4.s_addr); key.key.ipv4_5tuple.ip_dst = rte_bswap32( params->ip_dst.addr.ipv4.s_addr); key.key.ipv4_5tuple.port_src = params->port_src; key.key.ipv4_5tuple.port_dst = params->port_dst; key.key.ipv4_5tuple.proto = params->proto; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src = TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst = TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = { .f = cmd_fc_add_ipv4_5tuple_parsed, .data = NULL, .help_str = "Flow add (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv4_5tuple_p_string, (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id, (void *) &cmd_fc_add_ipv4_5tuple_flow_string, (void *) &cmd_fc_add_ipv4_5tuple_add_string, (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string, (void *) &cmd_fc_add_ipv4_5tuple_ip_src, (void *) &cmd_fc_add_ipv4_5tuple_ip_dst, (void *) &cmd_fc_add_ipv4_5tuple_port_src, (void *) &cmd_fc_add_ipv4_5tuple_port_dst, (void *) &cmd_fc_add_ipv4_5tuple_proto, (void *) &cmd_fc_add_ipv4_5tuple_port, NULL, }, }; /* * flow add ipv4_5tuple all */ struct cmd_fc_add_ipv4_5tuple_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; static void cmd_fc_add_ipv4_5tuple_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv4_5tuple_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t flow_id; key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } for (flow_id = 0; flow_id < params->n_flows; flow_id++) { uint32_t pos = flow_id & (N_FLOWS_BULK - 1); key[pos].type = FLOW_KEY_IPV4_5TUPLE; key[pos].key.ipv4_5tuple.ip_src = 0; key[pos].key.ipv4_5tuple.ip_dst = flow_id; key[pos].key.ipv4_5tuple.port_src = 0; key[pos].key.ipv4_5tuple.port_dst = 0; key[pos].key.ipv4_5tuple.proto = 6; port_id[pos] = flow_id % params->n_ports; if ((pos == N_FLOWS_BULK - 1) || (flow_id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple_all = { .f = cmd_fc_add_ipv4_5tuple_all_parsed, .data = NULL, .help_str = "Flow add all (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv4_5tuple_all_p_string, (void *) &cmd_fc_add_ipv4_5tuple_all_pipeline_id, (void *) &cmd_fc_add_ipv4_5tuple_all_flow_string, (void *) &cmd_fc_add_ipv4_5tuple_all_add_string, (void *) &cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string, (void *) &cmd_fc_add_ipv4_5tuple_all_all_string, (void *) &cmd_fc_add_ipv4_5tuple_all_n_flows, (void *) &cmd_fc_add_ipv4_5tuple_all_n_ports, NULL, }, }; /* * flow add ipv6_5tuple */ struct cmd_fc_add_ipv6_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; uint32_t port; }; static void cmd_fc_add_ipv6_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV6_5TUPLE; memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); key.key.ipv6_5tuple.port_src = params->port_src; key.key.ipv6_5tuple.port_dst = params->port_dst; key.key.ipv6_5tuple.proto = params->proto; status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src = TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst = TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = { .f = cmd_fc_add_ipv6_5tuple_parsed, .data = NULL, .help_str = "Flow add (IPv6 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv6_5tuple_p_string, (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id, (void *) &cmd_fc_add_ipv6_5tuple_flow_string, (void *) &cmd_fc_add_ipv6_5tuple_add_string, (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string, (void *) &cmd_fc_add_ipv6_5tuple_ip_src, (void *) &cmd_fc_add_ipv6_5tuple_ip_dst, (void *) &cmd_fc_add_ipv6_5tuple_port_src, (void *) &cmd_fc_add_ipv6_5tuple_port_dst, (void *) &cmd_fc_add_ipv6_5tuple_proto, (void *) &cmd_fc_add_ipv6_5tuple_port, NULL, }, }; /* * flow add ipv6_5tuple all */ struct cmd_fc_add_ipv6_5tuple_all_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_fixed_string_t all_string; uint32_t n_flows; uint32_t n_ports; }; static void cmd_fc_add_ipv6_5tuple_all_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_ipv6_5tuple_all_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key *key; uint32_t *port_id; uint32_t flow_id; key = rte_zmalloc(NULL, N_FLOWS_BULK * sizeof(*key), RTE_CACHE_LINE_SIZE); if (key == NULL) { printf("Memory allocation failed\n"); return; } port_id = rte_malloc(NULL, N_FLOWS_BULK * sizeof(*port_id), RTE_CACHE_LINE_SIZE); if (port_id == NULL) { rte_free(key); printf("Memory allocation failed\n"); return; } for (flow_id = 0; flow_id < params->n_flows; flow_id++) { uint32_t pos = flow_id & (N_FLOWS_BULK - 1); uint32_t *x; key[pos].type = FLOW_KEY_IPV6_5TUPLE; x = (uint32_t *) key[pos].key.ipv6_5tuple.ip_dst; *x = rte_bswap32(flow_id); key[pos].key.ipv6_5tuple.proto = 6; port_id[pos] = flow_id % params->n_ports; if ((pos == N_FLOWS_BULK - 1) || (flow_id == params->n_flows - 1)) { int status; status = app_pipeline_fc_add_bulk(app, params->pipeline_id, key, port_id, pos + 1); if (status != 0) { printf("Command failed\n"); break; } } } rte_free(port_id); rte_free(key); } cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_all_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, all_string, "all"); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_flows = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_flows, UINT32); cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_ports = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, n_ports, UINT32); cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple_all = { .f = cmd_fc_add_ipv6_5tuple_all_parsed, .data = NULL, .help_str = "Flow add all (ipv6 5-tuple)", .tokens = { (void *) &cmd_fc_add_ipv6_5tuple_all_p_string, (void *) &cmd_fc_add_ipv6_5tuple_all_pipeline_id, (void *) &cmd_fc_add_ipv6_5tuple_all_flow_string, (void *) &cmd_fc_add_ipv6_5tuple_all_add_string, (void *) &cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string, (void *) &cmd_fc_add_ipv6_5tuple_all_all_string, (void *) &cmd_fc_add_ipv6_5tuple_all_n_flows, (void *) &cmd_fc_add_ipv6_5tuple_all_n_ports, NULL, }, }; /* * flow del qinq */ struct cmd_fc_del_qinq_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t qinq_string; uint16_t svlan; uint16_t cvlan; }; static void cmd_fc_del_qinq_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_qinq_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_QINQ; key.key.qinq.svlan = params->svlan; key.key.qinq.cvlan = params->cvlan; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_qinq_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_qinq_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string, "qinq"); cmdline_parse_token_num_t cmd_fc_del_qinq_svlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16); cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16); cmdline_parse_inst_t cmd_fc_del_qinq = { .f = cmd_fc_del_qinq_parsed, .data = NULL, .help_str = "Flow delete (Q-in-Q)", .tokens = { (void *) &cmd_fc_del_qinq_p_string, (void *) &cmd_fc_del_qinq_pipeline_id, (void *) &cmd_fc_del_qinq_flow_string, (void *) &cmd_fc_del_qinq_del_string, (void *) &cmd_fc_del_qinq_qinq_string, (void *) &cmd_fc_del_qinq_svlan, (void *) &cmd_fc_del_qinq_cvlan, NULL, }, }; /* * flow del ipv4_5tuple */ struct cmd_fc_del_ipv4_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t ipv4_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; static void cmd_fc_del_ipv4_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV4_5TUPLE; key.key.ipv4_5tuple.ip_src = rte_bswap32( params->ip_src.addr.ipv4.s_addr); key.key.ipv4_5tuple.ip_dst = rte_bswap32( params->ip_dst.addr.ipv4.s_addr); key.key.ipv4_5tuple.port_src = params->port_src; key.key.ipv4_5tuple.port_dst = params->port_dst; key.key.ipv4_5tuple.proto = params->proto; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src = TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst = TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, proto, UINT32); cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = { .f = cmd_fc_del_ipv4_5tuple_parsed, .data = NULL, .help_str = "Flow delete (IPv4 5-tuple)", .tokens = { (void *) &cmd_fc_del_ipv4_5tuple_p_string, (void *) &cmd_fc_del_ipv4_5tuple_pipeline_id, (void *) &cmd_fc_del_ipv4_5tuple_flow_string, (void *) &cmd_fc_del_ipv4_5tuple_del_string, (void *) &cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string, (void *) &cmd_fc_del_ipv4_5tuple_ip_src, (void *) &cmd_fc_del_ipv4_5tuple_ip_dst, (void *) &cmd_fc_del_ipv4_5tuple_port_src, (void *) &cmd_fc_del_ipv4_5tuple_port_dst, (void *) &cmd_fc_del_ipv4_5tuple_proto, NULL, }, }; /* * flow del ipv6_5tuple */ struct cmd_fc_del_ipv6_5tuple_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t ipv6_5tuple_string; cmdline_ipaddr_t ip_src; cmdline_ipaddr_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; static void cmd_fc_del_ipv6_5tuple_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result; struct app_params *app = data; struct pipeline_fc_key key; int status; memset(&key, 0, sizeof(key)); key.type = FLOW_KEY_IPV6_5TUPLE; memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); key.key.ipv6_5tuple.port_src = params->port_src; key.key.ipv6_5tuple.port_dst = params->port_dst; key.key.ipv6_5tuple.proto = params->proto; status = app_pipeline_fc_del(app, params->pipeline_id, &key); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src = TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src); cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst = TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst, UINT16); cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto, UINT32); cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = { .f = cmd_fc_del_ipv6_5tuple_parsed, .data = NULL, .help_str = "Flow delete (IPv6 5-tuple)", .tokens = { (void *) &cmd_fc_del_ipv6_5tuple_p_string, (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id, (void *) &cmd_fc_del_ipv6_5tuple_flow_string, (void *) &cmd_fc_del_ipv6_5tuple_del_string, (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string, (void *) &cmd_fc_del_ipv6_5tuple_ip_src, (void *) &cmd_fc_del_ipv6_5tuple_ip_dst, (void *) &cmd_fc_del_ipv6_5tuple_port_src, (void *) &cmd_fc_del_ipv6_5tuple_port_dst, (void *) &cmd_fc_del_ipv6_5tuple_proto, NULL, }, }; /* * flow add default */ struct cmd_fc_add_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t default_string; uint32_t port; }; static void cmd_fc_add_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_add_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_add_default(app, params->pipeline_id, params->port); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_add_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_add_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_add_default_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_add_default_add_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, add_string, "add"); cmdline_parse_token_string_t cmd_fc_add_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, default_string, "default"); cmdline_parse_token_num_t cmd_fc_add_default_port = TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, port, UINT32); cmdline_parse_inst_t cmd_fc_add_default = { .f = cmd_fc_add_default_parsed, .data = NULL, .help_str = "Flow add default", .tokens = { (void *) &cmd_fc_add_default_p_string, (void *) &cmd_fc_add_default_pipeline_id, (void *) &cmd_fc_add_default_flow_string, (void *) &cmd_fc_add_default_add_string, (void *) &cmd_fc_add_default_default_string, (void *) &cmd_fc_add_default_port, NULL, }, }; /* * flow del default */ struct cmd_fc_del_default_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t default_string; }; static void cmd_fc_del_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_fc_del_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_del_default(app, params->pipeline_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_del_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_del_default_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_del_default_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_del_default_del_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, del_string, "del"); cmdline_parse_token_string_t cmd_fc_del_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, default_string, "default"); cmdline_parse_inst_t cmd_fc_del_default = { .f = cmd_fc_del_default_parsed, .data = NULL, .help_str = "Flow delete default", .tokens = { (void *) &cmd_fc_del_default_p_string, (void *) &cmd_fc_del_default_pipeline_id, (void *) &cmd_fc_del_default_flow_string, (void *) &cmd_fc_del_default_del_string, (void *) &cmd_fc_del_default_default_string, NULL, }, }; /* * flow ls */ struct cmd_fc_ls_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; cmdline_fixed_string_t ls_string; }; static void cmd_fc_ls_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_fc_ls_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_fc_ls(app, params->pipeline_id); if (status != 0) printf("Command failed\n"); } cmdline_parse_token_string_t cmd_fc_ls_p_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p"); cmdline_parse_token_num_t cmd_fc_ls_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32); cmdline_parse_token_string_t cmd_fc_ls_flow_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, flow_string, "flow"); cmdline_parse_token_string_t cmd_fc_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string, "ls"); cmdline_parse_inst_t cmd_fc_ls = { .f = cmd_fc_ls_parsed, .data = NULL, .help_str = "Flow list", .tokens = { (void *) &cmd_fc_ls_p_string, (void *) &cmd_fc_ls_pipeline_id, (void *) &cmd_fc_ls_flow_string, (void *) &cmd_fc_ls_ls_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { (cmdline_parse_inst_t *) &cmd_fc_add_qinq, (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple, (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple, (cmdline_parse_inst_t *) &cmd_fc_del_qinq, (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple, (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple, (cmdline_parse_inst_t *) &cmd_fc_add_default, (cmdline_parse_inst_t *) &cmd_fc_del_default, (cmdline_parse_inst_t *) &cmd_fc_add_qinq_all, (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple_all, (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple_all, (cmdline_parse_inst_t *) &cmd_fc_ls, NULL, }; static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = { .f_init = app_pipeline_fc_init, .f_free = app_pipeline_fc_free, .cmds = pipeline_cmds, }; struct pipeline_type pipeline_flow_classification = { .name = "FLOW_CLASSIFICATION", .be_ops = &pipeline_flow_classification_be_ops, .fe_ops = &pipeline_flow_classification_fe_ops, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_flow_classification.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ #define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ #include "pipeline.h" #include "pipeline_flow_classification_be.h" enum flow_key_type { FLOW_KEY_QINQ, FLOW_KEY_IPV4_5TUPLE, FLOW_KEY_IPV6_5TUPLE, }; struct flow_key_qinq { uint16_t svlan; uint16_t cvlan; }; struct flow_key_ipv4_5tuple { uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; struct flow_key_ipv6_5tuple { uint8_t ip_src[16]; uint8_t ip_dst[16]; uint16_t port_src; uint16_t port_dst; uint32_t proto; }; struct pipeline_fc_key { enum flow_key_type type; union { struct flow_key_qinq qinq; struct flow_key_ipv4_5tuple ipv4_5tuple; struct flow_key_ipv6_5tuple ipv6_5tuple; } key; }; int app_pipeline_fc_add(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t port_id); int app_pipeline_fc_add_bulk(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, uint32_t *port_id, uint32_t n_keys); int app_pipeline_fc_del(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key); int app_pipeline_fc_add_default(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_pipeline_fc_del_default(struct app_params *app, uint32_t pipeline_id); extern struct pipeline_type pipeline_flow_classification; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "pipeline_flow_classification_be.h" #include "hash_func.h" struct pipeline_flow_classification { struct pipeline p; pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS]; uint32_t n_flows; uint32_t key_offset; uint32_t key_size; uint32_t hash_offset; } __rte_cache_aligned; static void * pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler handlers[] = { [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler, [PIPELINE_MSG_REQ_STATS_PORT_IN] = pipeline_msg_req_stats_port_in_handler, [PIPELINE_MSG_REQ_STATS_PORT_OUT] = pipeline_msg_req_stats_port_out_handler, [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler, [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = pipeline_msg_req_port_in_enable_handler, [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = pipeline_msg_req_port_in_disable_handler, [PIPELINE_MSG_REQ_CUSTOM] = pipeline_fc_msg_req_custom_handler, }; static void * pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg); static void * pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg); static void * pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg); static void * pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg); static void * pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler custom_handlers[] = { [PIPELINE_FC_MSG_REQ_FLOW_ADD] = pipeline_fc_msg_req_add_handler, [PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK] = pipeline_fc_msg_req_add_bulk_handler, [PIPELINE_FC_MSG_REQ_FLOW_DEL] = pipeline_fc_msg_req_del_handler, [PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT] = pipeline_fc_msg_req_add_default_handler, [PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT] = pipeline_fc_msg_req_del_default_handler, }; /* * Flow table */ struct flow_table_entry { struct rte_pipeline_table_entry head; }; rte_table_hash_op_hash hash_func[] = { hash_default_key8, hash_default_key16, hash_default_key24, hash_default_key32, hash_default_key40, hash_default_key48, hash_default_key56, hash_default_key64 }; static int pipeline_fc_parse_args(struct pipeline_flow_classification *p, struct pipeline_params *params) { uint32_t n_flows_present = 0; uint32_t key_offset_present = 0; uint32_t key_size_present = 0; uint32_t hash_offset_present = 0; uint32_t i; for (i = 0; i < params->n_args; i++) { char *arg_name = params->args_name[i]; char *arg_value = params->args_value[i]; /* n_flows */ if (strcmp(arg_name, "n_flows") == 0) { if (n_flows_present) return -1; n_flows_present = 1; p->n_flows = atoi(arg_value); if (p->n_flows == 0) return -1; continue; } /* key_offset */ if (strcmp(arg_name, "key_offset") == 0) { if (key_offset_present) return -1; key_offset_present = 1; p->key_offset = atoi(arg_value); continue; } /* key_size */ if (strcmp(arg_name, "key_size") == 0) { if (key_size_present) return -1; key_size_present = 1; p->key_size = atoi(arg_value); if ((p->key_size == 0) || (p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) || (p->key_size % 8)) return -1; continue; } /* hash_offset */ if (strcmp(arg_name, "hash_offset") == 0) { if (hash_offset_present) return -1; hash_offset_present = 1; p->hash_offset = atoi(arg_value); continue; } /* Unknown argument */ return -1; } /* Check that mandatory arguments are present */ if ((n_flows_present == 0) || (key_offset_present == 0) || (key_size_present == 0) || (hash_offset_present == 0)) return -1; return 0; } static void *pipeline_fc_init(struct pipeline_params *params, __rte_unused void *arg) { struct pipeline *p; struct pipeline_flow_classification *p_fc; uint32_t size, i; /* Check input arguments */ if (params == NULL) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP( sizeof(struct pipeline_flow_classification)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; p_fc = (struct pipeline_flow_classification *) p; strcpy(p->name, params->name); p->log_level = params->log_level; PLOG(p, HIGH, "Flow classification"); /* Parse arguments */ if (pipeline_fc_parse_args(p_fc, params)) return NULL; /* Pipeline */ { struct rte_pipeline_params pipeline_params = { .name = params->name, .socket_id = params->socket_id, .offset_port_id = 0, }; p->p = rte_pipeline_create(&pipeline_params); if (p->p == NULL) { rte_free(p); return NULL; } } /* Input ports */ p->n_ports_in = params->n_ports_in; for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_port_in_params port_params = { .ops = pipeline_port_in_params_get_ops( ¶ms->port_in[i]), .arg_create = pipeline_port_in_params_convert( ¶ms->port_in[i]), .f_action = NULL, .arg_ah = NULL, .burst_size = params->port_in[i].burst_size, }; int status = rte_pipeline_port_in_create(p->p, &port_params, &p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Output ports */ p->n_ports_out = params->n_ports_out; for (i = 0; i < p->n_ports_out; i++) { struct rte_pipeline_port_out_params port_params = { .ops = pipeline_port_out_params_get_ops( ¶ms->port_out[i]), .arg_create = pipeline_port_out_params_convert( ¶ms->port_out[i]), .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; int status = rte_pipeline_port_out_create(p->p, &port_params, &p->port_out_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Tables */ p->n_tables = 1; { struct rte_table_hash_key8_ext_params table_hash_key8_params = { .n_entries = p_fc->n_flows, .n_entries_ext = p_fc->n_flows, .signature_offset = p_fc->hash_offset, .key_offset = p_fc->key_offset, .f_hash = hash_func[(p_fc->key_size / 8) - 1], .seed = 0, }; struct rte_table_hash_key16_ext_params table_hash_key16_params = { .n_entries = p_fc->n_flows, .n_entries_ext = p_fc->n_flows, .signature_offset = p_fc->hash_offset, .key_offset = p_fc->key_offset, .f_hash = hash_func[(p_fc->key_size / 8) - 1], .seed = 0, }; struct rte_table_hash_ext_params table_hash_params = { .key_size = p_fc->key_size, .n_keys = p_fc->n_flows, .n_buckets = p_fc->n_flows / 4, .n_buckets_ext = p_fc->n_flows / 4, .f_hash = hash_func[(p_fc->key_size / 8) - 1], .seed = 0, .signature_offset = p_fc->hash_offset, .key_offset = p_fc->key_offset, }; struct rte_pipeline_table_params table_params = { .ops = NULL, /* set below */ .arg_create = NULL, /* set below */ .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = sizeof(struct flow_table_entry) - sizeof(struct rte_pipeline_table_entry), }; int status; switch (p_fc->key_size) { case 8: table_params.ops = &rte_table_hash_key8_lru_ops; table_params.arg_create = &table_hash_key8_params; break; case 16: table_params.ops = &rte_table_hash_key16_ext_ops; table_params.arg_create = &table_hash_key16_params; break; default: table_params.ops = &rte_table_hash_ext_ops; table_params.arg_create = &table_hash_params; } status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Connecting input ports to tables */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_connect_to_table(p->p, p->port_in_id[i], p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Enable input ports */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_enable(p->p, p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Check pipeline consistency */ if (rte_pipeline_check(p->p) < 0) { rte_pipeline_free(p->p); rte_free(p); return NULL; } /* Message queues */ p->n_msgq = params->n_msgq; for (i = 0; i < p->n_msgq; i++) p->msgq_in[i] = params->msgq_in[i]; for (i = 0; i < p->n_msgq; i++) p->msgq_out[i] = params->msgq_out[i]; /* Message handlers */ memcpy(p->handlers, handlers, sizeof(p->handlers)); memcpy(p_fc->custom_handlers, custom_handlers, sizeof(p_fc->custom_handlers)); return p; } static int pipeline_fc_free(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ rte_pipeline_free(p->p); rte_free(p); return 0; } static int pipeline_fc_track(void *pipeline, __rte_unused uint32_t port_in, uint32_t *port_out) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL)) return -1; if (p->n_ports_in == 1) { *port_out = 0; return 0; } return -1; } static int pipeline_fc_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; pipeline_msg_req_handle(p); rte_pipeline_flush(p->p); return 0; } static void * pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg) { struct pipeline_flow_classification *p_fc = (struct pipeline_flow_classification *) p; struct pipeline_custom_msg_req *req = msg; pipeline_msg_req_handler f_handle; f_handle = (req->subtype < PIPELINE_FC_MSG_REQS) ? p_fc->custom_handlers[req->subtype] : pipeline_msg_req_invalid_handler; if (f_handle == NULL) f_handle = pipeline_msg_req_invalid_handler; return f_handle(p, req); } static void * pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg) { struct pipeline_fc_add_msg_req *req = msg; struct pipeline_fc_add_msg_rsp *rsp = msg; struct flow_table_entry entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, }; rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], &req->key, (struct rte_pipeline_table_entry *) &entry, &rsp->key_found, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } static void * pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg) { struct pipeline_fc_add_bulk_msg_req *req = msg; struct pipeline_fc_add_bulk_msg_rsp *rsp = msg; uint32_t i; for (i = 0; i < req->n_keys; i++) { struct pipeline_fc_add_bulk_flow_req *flow_req = &req->req[i]; struct pipeline_fc_add_bulk_flow_rsp *flow_rsp = &req->rsp[i]; struct flow_table_entry entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[flow_req->port_id]}, }, }; int status = rte_pipeline_table_entry_add(p->p, p->table_id[0], &flow_req->key, (struct rte_pipeline_table_entry *) &entry, &flow_rsp->key_found, (struct rte_pipeline_table_entry **) &flow_rsp->entry_ptr); if (status) break; } rsp->n_keys = i; return rsp; } static void * pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg) { struct pipeline_fc_del_msg_req *req = msg; struct pipeline_fc_del_msg_rsp *rsp = msg; rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], &req->key, &rsp->key_found, NULL); return rsp; } static void * pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg) { struct pipeline_fc_add_default_msg_req *req = msg; struct pipeline_fc_add_default_msg_rsp *rsp = msg; struct flow_table_entry default_entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, }; rsp->status = rte_pipeline_table_default_entry_add(p->p, p->table_id[0], (struct rte_pipeline_table_entry *) &default_entry, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } static void * pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg) { struct pipeline_fc_del_default_msg_rsp *rsp = msg; rsp->status = rte_pipeline_table_default_entry_delete(p->p, p->table_id[0], NULL); return rsp; } struct pipeline_be_ops pipeline_flow_classification_be_ops = { .f_init = pipeline_fc_init, .f_free = pipeline_fc_free, .f_run = NULL, .f_timer = pipeline_fc_timer, .f_track = pipeline_fc_track, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_BE_H__ #define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_BE_H__ #include "pipeline_common_be.h" enum pipeline_fc_msg_req_type { PIPELINE_FC_MSG_REQ_FLOW_ADD = 0, PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK, PIPELINE_FC_MSG_REQ_FLOW_DEL, PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT, PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT, PIPELINE_FC_MSG_REQS, }; #ifndef PIPELINE_FC_FLOW_KEY_MAX_SIZE #define PIPELINE_FC_FLOW_KEY_MAX_SIZE 64 #endif /* * MSG ADD */ struct pipeline_fc_add_msg_req { enum pipeline_msg_req_type type; enum pipeline_fc_msg_req_type subtype; uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; uint32_t port_id; }; struct pipeline_fc_add_msg_rsp { int status; int key_found; void *entry_ptr; }; /* * MSG ADD BULK */ struct pipeline_fc_add_bulk_flow_req { uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; uint32_t port_id; }; struct pipeline_fc_add_bulk_flow_rsp { int key_found; void *entry_ptr; }; struct pipeline_fc_add_bulk_msg_req { enum pipeline_msg_req_type type; enum pipeline_fc_msg_req_type subtype; struct pipeline_fc_add_bulk_flow_req *req; struct pipeline_fc_add_bulk_flow_rsp *rsp; uint32_t n_keys; }; struct pipeline_fc_add_bulk_msg_rsp { uint32_t n_keys; }; /* * MSG DEL */ struct pipeline_fc_del_msg_req { enum pipeline_msg_req_type type; enum pipeline_fc_msg_req_type subtype; uint8_t key[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; }; struct pipeline_fc_del_msg_rsp { int status; int key_found; }; /* * MSG ADD DEFAULT */ struct pipeline_fc_add_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_fc_msg_req_type subtype; uint32_t port_id; }; struct pipeline_fc_add_default_msg_rsp { int status; void *entry_ptr; }; /* * MSG DEL DEFAULT */ struct pipeline_fc_del_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_fc_msg_req_type subtype; }; struct pipeline_fc_del_default_msg_rsp { int status; }; extern struct pipeline_be_ops pipeline_flow_classification_be_ops; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_master.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "pipeline_master.h" #include "pipeline_master_be.h" static struct pipeline_fe_ops pipeline_master_fe_ops = { .f_init = NULL, .f_free = NULL, .cmds = NULL, }; struct pipeline_type pipeline_master = { .name = "MASTER", .be_ops = &pipeline_master_be_ops, .fe_ops = &pipeline_master_fe_ops, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_master.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_MASTER_H__ #define __INCLUDE_PIPELINE_MASTER_H__ #include "pipeline.h" extern struct pipeline_type pipeline_master; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_master_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "app.h" #include "pipeline_master_be.h" struct pipeline_master { struct app_params *app; struct cmdline *cl; int script_file_done; } __rte_cache_aligned; static void* pipeline_init(__rte_unused struct pipeline_params *params, void *arg) { struct app_params *app = (struct app_params *) arg; struct pipeline_master *p; uint32_t size; /* Check input arguments */ if (app == NULL) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_master)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; /* Initialization */ p->app = app; p->cl = cmdline_stdin_new(app->cmds, "pipeline> "); if (p->cl == NULL) { rte_free(p); return NULL; } p->script_file_done = 0; if (app->script_file == NULL) p->script_file_done = 1; return (void *) p; } static int pipeline_free(void *pipeline) { struct pipeline_master *p = (struct pipeline_master *) pipeline; if (p == NULL) return -EINVAL; cmdline_stdin_exit(p->cl); rte_free(p); return 0; } static int pipeline_run(void *pipeline) { struct pipeline_master *p = (struct pipeline_master *) pipeline; int status; if (p->script_file_done == 0) { struct app_params *app = p->app; int fd = open(app->script_file, O_RDONLY); if (fd < 0) printf("Cannot open CLI script file \"%s\"\n", app->script_file); else { struct cmdline *file_cl; printf("Running CLI script file \"%s\" ...\n", app->script_file); file_cl = cmdline_new(p->cl->ctx, "", fd, 1); cmdline_interact(file_cl); close(fd); } p->script_file_done = 1; } status = cmdline_poll(p->cl); if (status < 0) rte_panic("CLI poll error (%" PRId32 ")\n", status); else if (status == RDLINE_EXITED) { cmdline_stdin_exit(p->cl); rte_exit(0, "Bye!\n"); } return 0; } static int pipeline_timer(__rte_unused void *pipeline) { return 0; } struct pipeline_be_ops pipeline_master_be_ops = { .f_init = pipeline_init, .f_free = pipeline_free, .f_run = pipeline_run, .f_timer = pipeline_timer, .f_track = NULL, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_master_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_MASTER_BE_H__ #define __INCLUDE_PIPELINE_MASTER_BE_H__ #include "pipeline_common_be.h" extern struct pipeline_be_ops pipeline_master_be_ops; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_passthrough.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "pipeline_passthrough.h" #include "pipeline_passthrough_be.h" static struct pipeline_fe_ops pipeline_passthrough_fe_ops = { .f_init = NULL, .f_free = NULL, .cmds = NULL, }; struct pipeline_type pipeline_passthrough = { .name = "PASS-THROUGH", .be_ops = &pipeline_passthrough_be_ops, .fe_ops = &pipeline_passthrough_fe_ops, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_passthrough.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_PASSTHROUGH_H__ #define __INCLUDE_PIPELINE_PASSTHROUGH_H__ #include "pipeline.h" extern struct pipeline_type pipeline_passthrough; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_passthrough_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "pipeline_passthrough_be.h" #include "pipeline_actions_common.h" #include "hash_func.h" enum flow_key_type { FLOW_KEY_QINQ, FLOW_KEY_IPV4_5TUPLE, FLOW_KEY_IPV6_5TUPLE, }; struct pipeline_passthrough { struct pipeline p; uint32_t key_type_valid; enum flow_key_type key_type; uint32_t key_offset_rd; uint32_t key_offset_wr; uint32_t hash_offset; rte_table_hash_op_hash f_hash; rte_pipeline_port_in_action_handler f_port_in_ah; } __rte_cache_aligned; static pipeline_msg_req_handler handlers[] = { [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler, [PIPELINE_MSG_REQ_STATS_PORT_IN] = pipeline_msg_req_stats_port_in_handler, [PIPELINE_MSG_REQ_STATS_PORT_OUT] = pipeline_msg_req_stats_port_out_handler, [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler, [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = pipeline_msg_req_port_in_enable_handler, [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = pipeline_msg_req_port_in_disable_handler, [PIPELINE_MSG_REQ_CUSTOM] = pipeline_msg_req_invalid_handler, }; static inline void pkt_work_key_qinq( struct rte_mbuf *pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_rd); uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_wr); uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, hash_offset); /* Read */ uint64_t key_qinq = *key_rd & rte_bswap64(0x00000FFF00000FFFLLU); /* Compute */ uint32_t hash_qinq = p_pt->f_hash(&key_qinq, 8, 0); /* Write */ *key_wr = key_qinq; *hash = hash_qinq; } static inline void pkt4_work_key_qinq( struct rte_mbuf **pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_rd); uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_wr); uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], hash_offset); uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_rd); uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_wr); uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], hash_offset); uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_rd); uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_wr); uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], hash_offset); uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_rd); uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_wr); uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], hash_offset); /* Read */ uint64_t key_qinq0 = *key_rd0 & rte_bswap64(0x00000FFF00000FFFLLU); uint64_t key_qinq1 = *key_rd1 & rte_bswap64(0x00000FFF00000FFFLLU); uint64_t key_qinq2 = *key_rd2 & rte_bswap64(0x00000FFF00000FFFLLU); uint64_t key_qinq3 = *key_rd3 & rte_bswap64(0x00000FFF00000FFFLLU); /* Compute */ uint32_t hash_qinq0 = p_pt->f_hash(&key_qinq0, 8, 0); uint32_t hash_qinq1 = p_pt->f_hash(&key_qinq1, 8, 0); uint32_t hash_qinq2 = p_pt->f_hash(&key_qinq2, 8, 0); uint32_t hash_qinq3 = p_pt->f_hash(&key_qinq3, 8, 0); /* Write */ *key_wr0 = key_qinq0; *key_wr1 = key_qinq1; *key_wr2 = key_qinq2; *key_wr3 = key_qinq3; *hash0 = hash_qinq0; *hash1 = hash_qinq1; *hash2 = hash_qinq2; *hash3 = hash_qinq3; } PIPELINE_PORT_IN_AH(port_in_ah_key_qinq, pkt_work_key_qinq, pkt4_work_key_qinq); static inline void pkt_work_key_ipv4( struct rte_mbuf *pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_rd); uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_wr); uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, hash_offset); uint64_t key_ipv4[2]; uint32_t hash_ipv4; /* Read */ key_ipv4[0] = key_rd[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU); key_ipv4[1] = key_rd[1]; /* Compute */ hash_ipv4 = p_pt->f_hash(key_ipv4, 16, 0); /* Write */ key_wr[0] = key_ipv4[0]; key_wr[1] = key_ipv4[1]; *hash = hash_ipv4; } static inline void pkt4_work_key_ipv4( struct rte_mbuf **pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_rd); uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_wr); uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], hash_offset); uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_rd); uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_wr); uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], hash_offset); uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_rd); uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_wr); uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], hash_offset); uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_rd); uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_wr); uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], hash_offset); uint64_t key_ipv4_0[2]; uint64_t key_ipv4_1[2]; uint64_t key_ipv4_2[2]; uint64_t key_ipv4_3[2]; uint32_t hash_ipv4_0; uint32_t hash_ipv4_1; uint32_t hash_ipv4_2; uint32_t hash_ipv4_3; /* Read */ key_ipv4_0[0] = key_rd0[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU); key_ipv4_1[0] = key_rd1[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU); key_ipv4_2[0] = key_rd2[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU); key_ipv4_3[0] = key_rd3[0] & rte_bswap64(0x00FF0000FFFFFFFFLLU); key_ipv4_0[1] = key_rd0[1]; key_ipv4_1[1] = key_rd1[1]; key_ipv4_2[1] = key_rd2[1]; key_ipv4_3[1] = key_rd3[1]; /* Compute */ hash_ipv4_0 = p_pt->f_hash(key_ipv4_0, 16, 0); hash_ipv4_1 = p_pt->f_hash(key_ipv4_1, 16, 0); hash_ipv4_2 = p_pt->f_hash(key_ipv4_2, 16, 0); hash_ipv4_3 = p_pt->f_hash(key_ipv4_3, 16, 0); /* Write */ key_wr0[0] = key_ipv4_0[0]; key_wr1[0] = key_ipv4_1[0]; key_wr2[0] = key_ipv4_2[0]; key_wr3[0] = key_ipv4_3[0]; key_wr0[1] = key_ipv4_0[1]; key_wr1[1] = key_ipv4_1[1]; key_wr2[1] = key_ipv4_2[1]; key_wr3[1] = key_ipv4_3[1]; *hash0 = hash_ipv4_0; *hash1 = hash_ipv4_1; *hash2 = hash_ipv4_2; *hash3 = hash_ipv4_3; } PIPELINE_PORT_IN_AH(port_in_ah_key_ipv4, pkt_work_key_ipv4, pkt4_work_key_ipv4); static inline void pkt_work_key_ipv6( struct rte_mbuf *pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_rd); uint64_t *key_wr = RTE_MBUF_METADATA_UINT64_PTR(pkt, key_offset_wr); uint32_t *hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, hash_offset); uint64_t key_ipv6[8]; uint32_t hash_ipv6; /* Read */ key_ipv6[0] = key_rd[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU); key_ipv6[1] = key_rd[1]; key_ipv6[2] = key_rd[2]; key_ipv6[3] = key_rd[3]; key_ipv6[4] = key_rd[4]; key_ipv6[5] = 0; key_ipv6[6] = 0; key_ipv6[7] = 0; /* Compute */ hash_ipv6 = p_pt->f_hash(key_ipv6, 64, 0); /* Write */ key_wr[0] = key_ipv6[0]; key_wr[1] = key_ipv6[1]; key_wr[2] = key_ipv6[2]; key_wr[3] = key_ipv6[3]; key_wr[4] = key_ipv6[4]; key_wr[5] = 0; key_wr[6] = 0; key_wr[7] = 0; *hash = hash_ipv6; } static inline void pkt4_work_key_ipv6( struct rte_mbuf **pkt, void *arg) { struct pipeline_passthrough *p_pt = arg; uint32_t key_offset_rd = p_pt->key_offset_rd; uint32_t key_offset_wr = p_pt->key_offset_wr; uint32_t hash_offset = p_pt->hash_offset; uint64_t *key_rd0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_rd); uint64_t *key_wr0 = RTE_MBUF_METADATA_UINT64_PTR(pkt[0], key_offset_wr); uint32_t *hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0], hash_offset); uint64_t *key_rd1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_rd); uint64_t *key_wr1 = RTE_MBUF_METADATA_UINT64_PTR(pkt[1], key_offset_wr); uint32_t *hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1], hash_offset); uint64_t *key_rd2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_rd); uint64_t *key_wr2 = RTE_MBUF_METADATA_UINT64_PTR(pkt[2], key_offset_wr); uint32_t *hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2], hash_offset); uint64_t *key_rd3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_rd); uint64_t *key_wr3 = RTE_MBUF_METADATA_UINT64_PTR(pkt[3], key_offset_wr); uint32_t *hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3], hash_offset); uint64_t key_ipv6_0[8]; uint64_t key_ipv6_1[8]; uint64_t key_ipv6_2[8]; uint64_t key_ipv6_3[8]; uint32_t hash_ipv6_0; uint32_t hash_ipv6_1; uint32_t hash_ipv6_2; uint32_t hash_ipv6_3; /* Read */ key_ipv6_0[0] = key_rd0[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU); key_ipv6_1[0] = key_rd1[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU); key_ipv6_2[0] = key_rd2[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU); key_ipv6_3[0] = key_rd3[0] & rte_bswap64(0x0000FF00FFFFFFFFLLU); key_ipv6_0[1] = key_rd0[1]; key_ipv6_1[1] = key_rd1[1]; key_ipv6_2[1] = key_rd2[1]; key_ipv6_3[1] = key_rd3[1]; key_ipv6_0[2] = key_rd0[2]; key_ipv6_1[2] = key_rd1[2]; key_ipv6_2[2] = key_rd2[2]; key_ipv6_3[2] = key_rd3[2]; key_ipv6_0[3] = key_rd0[3]; key_ipv6_1[3] = key_rd1[3]; key_ipv6_2[3] = key_rd2[3]; key_ipv6_3[3] = key_rd3[3]; key_ipv6_0[4] = key_rd0[4]; key_ipv6_1[4] = key_rd1[4]; key_ipv6_2[4] = key_rd2[4]; key_ipv6_3[4] = key_rd3[4]; key_ipv6_0[5] = 0; key_ipv6_1[5] = 0; key_ipv6_2[5] = 0; key_ipv6_3[5] = 0; key_ipv6_0[6] = 0; key_ipv6_1[6] = 0; key_ipv6_2[6] = 0; key_ipv6_3[6] = 0; key_ipv6_0[7] = 0; key_ipv6_1[7] = 0; key_ipv6_2[7] = 0; key_ipv6_3[7] = 0; /* Compute */ hash_ipv6_0 = p_pt->f_hash(key_ipv6_0, 64, 0); hash_ipv6_1 = p_pt->f_hash(key_ipv6_1, 64, 0); hash_ipv6_2 = p_pt->f_hash(key_ipv6_2, 64, 0); hash_ipv6_3 = p_pt->f_hash(key_ipv6_3, 64, 0); /* Write */ key_wr0[0] = key_ipv6_0[0]; key_wr1[0] = key_ipv6_1[0]; key_wr2[0] = key_ipv6_2[0]; key_wr3[0] = key_ipv6_3[0]; key_wr0[1] = key_ipv6_0[1]; key_wr1[1] = key_ipv6_1[1]; key_wr2[1] = key_ipv6_2[1]; key_wr3[1] = key_ipv6_3[1]; key_wr0[2] = key_ipv6_0[2]; key_wr1[2] = key_ipv6_1[2]; key_wr2[2] = key_ipv6_2[2]; key_wr3[2] = key_ipv6_3[2]; key_wr0[3] = key_ipv6_0[3]; key_wr1[3] = key_ipv6_1[3]; key_wr2[3] = key_ipv6_2[3]; key_wr3[3] = key_ipv6_3[3]; key_wr0[4] = key_ipv6_0[4]; key_wr1[4] = key_ipv6_1[4]; key_wr2[4] = key_ipv6_2[4]; key_wr3[4] = key_ipv6_3[4]; key_wr0[5] = 0; key_wr0[5] = 0; key_wr0[5] = 0; key_wr0[5] = 0; key_wr0[6] = 0; key_wr0[6] = 0; key_wr0[6] = 0; key_wr0[6] = 0; key_wr0[7] = 0; key_wr0[7] = 0; key_wr0[7] = 0; key_wr0[7] = 0; *hash0 = hash_ipv6_0; *hash1 = hash_ipv6_1; *hash2 = hash_ipv6_2; *hash3 = hash_ipv6_3; } PIPELINE_PORT_IN_AH(port_in_ah_key_ipv6, pkt_work_key_ipv6, pkt4_work_key_ipv6); static int pipeline_passthrough_parse_args(struct pipeline_passthrough *p, struct pipeline_params *params) { uint32_t key_type_present = 0; uint32_t key_offset_rd_present = 0; uint32_t key_offset_wr_present = 0; uint32_t hash_offset_present = 0; uint32_t i; for (i = 0; i < params->n_args; i++) { char *arg_name = params->args_name[i]; char *arg_value = params->args_value[i]; /* key_type */ if (strcmp(arg_name, "key_type") == 0) { if (key_type_present) return -1; key_type_present = 1; if ((strcmp(arg_value, "q-in-q") == 0) || (strcmp(arg_value, "qinq") == 0)) p->key_type = FLOW_KEY_QINQ; else if (strcmp(arg_value, "ipv4_5tuple") == 0) p->key_type = FLOW_KEY_IPV4_5TUPLE; else if (strcmp(arg_value, "ipv6_5tuple") == 0) p->key_type = FLOW_KEY_IPV6_5TUPLE; else return -1; p->key_type_valid = 1; continue; } /* key_offset_rd */ if (strcmp(arg_name, "key_offset_rd") == 0) { if (key_offset_rd_present) return -1; key_offset_rd_present = 1; p->key_offset_rd = atoi(arg_value); continue; } /* key_offset_wr */ if (strcmp(arg_name, "key_offset_wr") == 0) { if (key_offset_wr_present) return -1; key_offset_wr_present = 1; p->key_offset_wr = atoi(arg_value); continue; } /* hash_offset */ if (strcmp(arg_name, "hash_offset") == 0) { if (hash_offset_present) return -1; hash_offset_present = 1; p->hash_offset = atoi(arg_value); continue; } /* any other */ return -1; } /* Check that mandatory arguments are present */ if ((key_offset_rd_present != key_type_present) || (key_offset_wr_present != key_type_present) || (hash_offset_present != key_type_present)) return -1; return 0; } static void* pipeline_passthrough_init(struct pipeline_params *params, __rte_unused void *arg) { struct pipeline *p; struct pipeline_passthrough *p_pt; uint32_t size, i; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0) || (params->n_ports_in < params->n_ports_out) || (params->n_ports_in % params->n_ports_out)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_passthrough)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); p_pt = (struct pipeline_passthrough *) p; if (p == NULL) return NULL; strcpy(p->name, params->name); p->log_level = params->log_level; PLOG(p, HIGH, "Pass-through"); /* Parse arguments */ if (pipeline_passthrough_parse_args(p_pt, params)) return NULL; if (p_pt->key_type_valid == 0) { p_pt->f_hash = NULL; p_pt->f_port_in_ah = NULL; } else switch (p_pt->key_type) { case FLOW_KEY_QINQ: p_pt->f_hash = hash_default_key8; p_pt->f_port_in_ah = port_in_ah_key_qinq; break; case FLOW_KEY_IPV4_5TUPLE: p_pt->f_hash = hash_default_key16; p_pt->f_port_in_ah = port_in_ah_key_ipv4; break; case FLOW_KEY_IPV6_5TUPLE: p_pt->f_hash = hash_default_key64; p_pt->f_port_in_ah = port_in_ah_key_ipv6; break; default: p_pt->f_hash = NULL; p_pt->f_port_in_ah = NULL; } /* Pipeline */ { struct rte_pipeline_params pipeline_params = { .name = "PASS-THROUGH", .socket_id = params->socket_id, .offset_port_id = 0, }; p->p = rte_pipeline_create(&pipeline_params); if (p->p == NULL) { rte_free(p); return NULL; } } /* Input ports */ p->n_ports_in = params->n_ports_in; for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_port_in_params port_params = { .ops = pipeline_port_in_params_get_ops( ¶ms->port_in[i]), .arg_create = pipeline_port_in_params_convert( ¶ms->port_in[i]), .f_action = p_pt->f_port_in_ah, .arg_ah = p_pt, .burst_size = params->port_in[i].burst_size, }; int status = rte_pipeline_port_in_create(p->p, &port_params, &p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Output ports */ p->n_ports_out = params->n_ports_out; for (i = 0; i < p->n_ports_out; i++) { struct rte_pipeline_port_out_params port_params = { .ops = pipeline_port_out_params_get_ops( ¶ms->port_out[i]), .arg_create = pipeline_port_out_params_convert( ¶ms->port_out[i]), .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; int status = rte_pipeline_port_out_create(p->p, &port_params, &p->port_out_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Tables */ p->n_tables = p->n_ports_in; for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_table_params table_params = { .ops = &rte_table_stub_ops, .arg_create = NULL, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; int status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Connecting input ports to tables */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_connect_to_table(p->p, p->port_in_id[i], p->table_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Add entries to tables */ for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[ i / (p->n_ports_in / p->n_ports_out)]}, }; struct rte_pipeline_table_entry *default_entry_ptr; int status = rte_pipeline_table_default_entry_add(p->p, p->table_id[i], &default_entry, &default_entry_ptr); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Enable input ports */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_enable(p->p, p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Check pipeline consistency */ if (rte_pipeline_check(p->p) < 0) { rte_pipeline_free(p->p); rte_free(p); return NULL; } /* Message queues */ p->n_msgq = params->n_msgq; for (i = 0; i < p->n_msgq; i++) p->msgq_in[i] = params->msgq_in[i]; for (i = 0; i < p->n_msgq; i++) p->msgq_out[i] = params->msgq_out[i]; /* Message handlers */ memcpy(p->handlers, handlers, sizeof(p->handlers)); return p; } static int pipeline_passthrough_free(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ rte_pipeline_free(p->p); rte_free(p); return 0; } static int pipeline_passthrough_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; pipeline_msg_req_handle(p); rte_pipeline_flush(p->p); return 0; } static int pipeline_passthrough_track(void *pipeline, uint32_t port_in, uint32_t *port_out) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL)) return -1; *port_out = port_in / p->n_ports_in; return 0; } struct pipeline_be_ops pipeline_passthrough_be_ops = { .f_init = pipeline_passthrough_init, .f_free = pipeline_passthrough_free, .f_run = NULL, .f_timer = pipeline_passthrough_timer, .f_track = pipeline_passthrough_track, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_passthrough_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__ #define __INCLUDE_PIPELINE_PASSTHROUGH_BE_H__ #include "pipeline_common_be.h" extern struct pipeline_be_ops pipeline_passthrough_be_ops; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_routing.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_routing.h" struct app_pipeline_routing_route { struct pipeline_routing_route_key key; struct app_pipeline_routing_route_params params; void *entry_ptr; TAILQ_ENTRY(app_pipeline_routing_route) node; }; struct app_pipeline_routing_arp_entry { struct pipeline_routing_arp_key key; struct ether_addr macaddr; void *entry_ptr; TAILQ_ENTRY(app_pipeline_routing_arp_entry) node; }; struct pipeline_routing { /* Parameters */ uint32_t n_ports_in; uint32_t n_ports_out; /* Routes */ TAILQ_HEAD(, app_pipeline_routing_route) routes; uint32_t n_routes; uint32_t default_route_present; uint32_t default_route_port_id; void *default_route_entry_ptr; /* ARP entries */ TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries; uint32_t n_arp_entries; uint32_t default_arp_entry_present; uint32_t default_arp_entry_port_id; void *default_arp_entry_ptr; }; static void * pipeline_routing_init(struct pipeline_params *params, __rte_unused void *arg) { struct pipeline_routing *p; uint32_t size; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); if (p == NULL) return NULL; /* Initialization */ p->n_ports_in = params->n_ports_in; p->n_ports_out = params->n_ports_out; TAILQ_INIT(&p->routes); p->n_routes = 0; TAILQ_INIT(&p->arp_entries); p->n_arp_entries = 0; return p; } static int app_pipeline_routing_free(void *pipeline) { struct pipeline_routing *p = pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ while (!TAILQ_EMPTY(&p->routes)) { struct app_pipeline_routing_route *route; route = TAILQ_FIRST(&p->routes); TAILQ_REMOVE(&p->routes, route, node); rte_free(route); } while (!TAILQ_EMPTY(&p->arp_entries)) { struct app_pipeline_routing_arp_entry *arp_entry; arp_entry = TAILQ_FIRST(&p->arp_entries); TAILQ_REMOVE(&p->arp_entries, arp_entry, node); rte_free(arp_entry); } rte_free(p); return 0; } static struct app_pipeline_routing_route * app_pipeline_routing_find_route(struct pipeline_routing *p, const struct pipeline_routing_route_key *key) { struct app_pipeline_routing_route *it, *found; found = NULL; TAILQ_FOREACH(it, &p->routes, node) { if ((key->type == it->key.type) && (key->key.ipv4.ip == it->key.key.ipv4.ip) && (key->key.ipv4.depth == it->key.key.ipv4.depth)) { found = it; break; } } return found; } static struct app_pipeline_routing_arp_entry * app_pipeline_routing_find_arp_entry(struct pipeline_routing *p, const struct pipeline_routing_arp_key *key) { struct app_pipeline_routing_arp_entry *it, *found; found = NULL; TAILQ_FOREACH(it, &p->arp_entries, node) { if ((key->type == it->key.type) && (key->key.ipv4.port_id == it->key.key.ipv4.port_id) && (key->key.ipv4.ip == it->key.key.ipv4.ip)) { found = it; break; } } return found; } static void print_route(const struct app_pipeline_routing_route *route) { if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) { const struct pipeline_routing_route_key_ipv4 *key = &route->key.key.ipv4; printf("IP Prefix = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32 " => " "(Port = %" PRIu32 ", Next Hop IP = " "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ")\n", (key->ip >> 24) & 0xFF, (key->ip >> 16) & 0xFF, (key->ip >> 8) & 0xFF, key->ip & 0xFF, key->depth, route->params.port_id, (route->params.ip >> 24) & 0xFF, (route->params.ip >> 16) & 0xFF, (route->params.ip >> 8) & 0xFF, route->params.ip & 0xFF); } } static void print_arp_entry(const struct app_pipeline_routing_arp_entry *entry) { printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ") => " "HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n", entry->key.key.ipv4.port_id, (entry->key.key.ipv4.ip >> 24) & 0xFF, (entry->key.key.ipv4.ip >> 16) & 0xFF, (entry->key.key.ipv4.ip >> 8) & 0xFF, entry->key.key.ipv4.ip & 0xFF, entry->macaddr.addr_bytes[0], entry->macaddr.addr_bytes[1], entry->macaddr.addr_bytes[2], entry->macaddr.addr_bytes[3], entry->macaddr.addr_bytes[4], entry->macaddr.addr_bytes[5]); } static int app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id) { struct pipeline_routing *p; struct app_pipeline_routing_route *it; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -EINVAL; TAILQ_FOREACH(it, &p->routes, node) print_route(it); if (p->default_route_present) printf("Default route: port %" PRIu32 " (entry ptr = %p)\n", p->default_route_port_id, p->default_route_entry_ptr); else printf("Default: DROP\n"); return 0; } int app_pipeline_routing_add_route(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_route_key *key, struct app_pipeline_routing_route_params *route_params) { struct pipeline_routing *p; struct pipeline_routing_route_add_msg_req *req; struct pipeline_routing_route_add_msg_rsp *rsp; struct app_pipeline_routing_route *entry; int new_entry; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (route_params == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; switch (key->type) { case PIPELINE_ROUTING_ROUTE_IPV4: { uint32_t depth = key->key.ipv4.depth; uint32_t netmask; /* key */ if ((depth == 0) || (depth > 32)) return -1; netmask = (~0) << (32 - depth); key->key.ipv4.ip &= netmask; /* route params */ if (route_params->port_id >= p->n_ports_out) return -1; } break; default: return -1; } /* Find existing rule or allocate new rule */ entry = app_pipeline_routing_find_route(p, key); new_entry = (entry == NULL); if (entry == NULL) { entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE); if (entry == NULL) return -1; } /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) { if (new_entry) rte_free(entry); return -1; } req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD; memcpy(&req->key, key, sizeof(*key)); req->flags = route_params->flags; req->port_id = route_params->port_id; req->ip = route_params->ip; rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) { if (new_entry) rte_free(entry); return -1; } /* Read response and write entry */ if (rsp->status || (rsp->entry_ptr == NULL) || ((new_entry == 0) && (rsp->key_found == 0)) || ((new_entry == 1) && (rsp->key_found == 1))) { app_msg_free(app, rsp); if (new_entry) rte_free(entry); return -1; } memcpy(&entry->key, key, sizeof(*key)); memcpy(&entry->params, route_params, sizeof(*route_params)); entry->entry_ptr = rsp->entry_ptr; /* Commit entry */ if (new_entry) { TAILQ_INSERT_TAIL(&p->routes, entry, node); p->n_routes++; } print_route(entry); /* Message buffer free */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_delete_route(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_route_key *key) { struct pipeline_routing *p; struct pipeline_routing_route_delete_msg_req *req; struct pipeline_routing_route_delete_msg_rsp *rsp; struct app_pipeline_routing_route *entry; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; switch (key->type) { case PIPELINE_ROUTING_ROUTE_IPV4: { uint32_t depth = key->key.ipv4.depth; uint32_t netmask; /* key */ if ((depth == 0) || (depth > 32)) return -1; netmask = (~0) << (32 - depth); key->key.ipv4.ip &= netmask; } break; default: return -1; } /* Find rule */ entry = app_pipeline_routing_find_route(p, key); if (entry == NULL) return 0; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL; memcpy(&req->key, key, sizeof(*key)); rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status || !rsp->key_found) { app_msg_free(app, rsp); return -1; } /* Remove route */ TAILQ_REMOVE(&p->routes, entry, node); p->n_routes--; rte_free(entry); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_add_default_route(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct pipeline_routing *p; struct pipeline_routing_route_add_default_msg_req *req; struct pipeline_routing_route_add_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write route */ if (rsp->status || (rsp->entry_ptr == NULL)) { app_msg_free(app, rsp); return -1; } p->default_route_port_id = port_id; p->default_route_entry_ptr = rsp->entry_ptr; /* Commit route */ p->default_route_present = 1; /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_delete_default_route(struct app_params *app, uint32_t pipeline_id) { struct pipeline_routing *p; struct pipeline_routing_arp_delete_default_msg_req *req; struct pipeline_routing_arp_delete_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write route */ if (rsp->status) { app_msg_free(app, rsp); return -1; } /* Commit route */ p->default_route_present = 0; /* Free response */ app_msg_free(app, rsp); return 0; } static int app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id) { struct pipeline_routing *p; struct app_pipeline_routing_arp_entry *it; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -EINVAL; TAILQ_FOREACH(it, &p->arp_entries, node) print_arp_entry(it); if (p->default_arp_entry_present) printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n", p->default_arp_entry_port_id, p->default_arp_entry_ptr); else printf("Default: DROP\n"); return 0; } int app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_arp_key *key, struct ether_addr *macaddr) { struct pipeline_routing *p; struct pipeline_routing_arp_add_msg_req *req; struct pipeline_routing_arp_add_msg_rsp *rsp; struct app_pipeline_routing_arp_entry *entry; int new_entry; /* Check input arguments */ if ((app == NULL) || (key == NULL) || (macaddr == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; switch (key->type) { case PIPELINE_ROUTING_ARP_IPV4: { uint32_t port_id = key->key.ipv4.port_id; /* key */ if (port_id >= p->n_ports_out) return -1; } break; default: return -1; } /* Find existing entry or allocate new */ entry = app_pipeline_routing_find_arp_entry(p, key); new_entry = (entry == NULL); if (entry == NULL) { entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE); if (entry == NULL) return -1; } /* Message buffer allocation */ req = app_msg_alloc(app); if (req == NULL) { if (new_entry) rte_free(entry); return -1; } req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD; memcpy(&req->key, key, sizeof(*key)); ether_addr_copy(macaddr, &req->macaddr); /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) { if (new_entry) rte_free(entry); return -1; } /* Read response and write entry */ if (rsp->status || (rsp->entry_ptr == NULL) || ((new_entry == 0) && (rsp->key_found == 0)) || ((new_entry == 1) && (rsp->key_found == 1))) { app_msg_free(app, rsp); if (new_entry) rte_free(entry); return -1; } memcpy(&entry->key, key, sizeof(*key)); ether_addr_copy(macaddr, &entry->macaddr); entry->entry_ptr = rsp->entry_ptr; /* Commit entry */ if (new_entry) { TAILQ_INSERT_TAIL(&p->arp_entries, entry, node); p->n_arp_entries++; } print_arp_entry(entry); /* Message buffer free */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_delete_arp_entry(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_arp_key *key) { struct pipeline_routing *p; struct pipeline_routing_arp_delete_msg_req *req; struct pipeline_routing_arp_delete_msg_rsp *rsp; struct app_pipeline_routing_arp_entry *entry; /* Check input arguments */ if ((app == NULL) || (key == NULL)) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -EINVAL; switch (key->type) { case PIPELINE_ROUTING_ARP_IPV4: { uint32_t port_id = key->key.ipv4.port_id; /* key */ if (port_id >= p->n_ports_out) return -1; } break; default: return -1; } /* Find rule */ entry = app_pipeline_routing_find_arp_entry(p, key); if (entry == NULL) return 0; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL; memcpy(&req->key, key, sizeof(*key)); rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response */ if (rsp->status || !rsp->key_found) { app_msg_free(app, rsp); return -1; } /* Remove entry */ TAILQ_REMOVE(&p->arp_entries, entry, node); p->n_arp_entries--; rte_free(entry); /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_add_default_arp_entry(struct app_params *app, uint32_t pipeline_id, uint32_t port_id) { struct pipeline_routing *p; struct pipeline_routing_arp_add_default_msg_req *req; struct pipeline_routing_arp_add_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -1; if (port_id >= p->n_ports_out) return -1; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -1; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT; req->port_id = port_id; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -1; /* Read response and write entry */ if (rsp->status || rsp->entry_ptr == NULL) { app_msg_free(app, rsp); return -1; } p->default_arp_entry_port_id = port_id; p->default_arp_entry_ptr = rsp->entry_ptr; /* Commit entry */ p->default_arp_entry_present = 1; /* Free response */ app_msg_free(app, rsp); return 0; } int app_pipeline_routing_delete_default_arp_entry(struct app_params *app, uint32_t pipeline_id) { struct pipeline_routing *p; struct pipeline_routing_arp_delete_default_msg_req *req; struct pipeline_routing_arp_delete_default_msg_rsp *rsp; /* Check input arguments */ if (app == NULL) return -1; p = app_pipeline_data_fe(app, pipeline_id); if (p == NULL) return -EINVAL; /* Allocate and write request */ req = app_msg_alloc(app); if (req == NULL) return -ENOMEM; req->type = PIPELINE_MSG_REQ_CUSTOM; req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT; /* Send request and wait for response */ rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); if (rsp == NULL) return -ETIMEDOUT; /* Read response and write entry */ if (rsp->status) { app_msg_free(app, rsp); return rsp->status; } /* Commit entry */ p->default_arp_entry_present = 0; /* Free response */ app_msg_free(app, rsp); return 0; } /* * route add */ struct cmd_route_add_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; cmdline_fixed_string_t add_string; cmdline_ipaddr_t ip; uint32_t depth; uint32_t port; cmdline_ipaddr_t nh_ip; }; static void cmd_route_add_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_route_add_result *params = parsed_result; struct app_params *app = data; struct pipeline_routing_route_key key; struct app_pipeline_routing_route_params rt_params; int status; /* Create route */ key.type = PIPELINE_ROUTING_ROUTE_IPV4; key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); key.key.ipv4.depth = params->depth; rt_params.flags = 0; /* remote route */ rt_params.port_id = params->port; rt_params.ip = rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr); status = app_pipeline_routing_add_route(app, params->p, &key, &rt_params); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_route_add_p_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, p_string, "p"); static cmdline_parse_token_num_t cmd_route_add_p = TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, p, UINT32); static cmdline_parse_token_string_t cmd_route_add_route_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, route_string, "route"); static cmdline_parse_token_string_t cmd_route_add_add_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_result, add_string, "add"); static cmdline_parse_token_ipaddr_t cmd_route_add_ip = TOKEN_IPV4_INITIALIZER(struct cmd_route_add_result, ip); static cmdline_parse_token_num_t cmd_route_add_depth = TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, depth, UINT32); static cmdline_parse_token_num_t cmd_route_add_port = TOKEN_NUM_INITIALIZER(struct cmd_route_add_result, port, UINT32); static cmdline_parse_token_ipaddr_t cmd_route_add_nh_ip = TOKEN_IPV4_INITIALIZER(struct cmd_route_add_result, nh_ip); static cmdline_parse_inst_t cmd_route_add = { .f = cmd_route_add_parsed, .data = NULL, .help_str = "Route add", .tokens = { (void *)&cmd_route_add_p_string, (void *)&cmd_route_add_p, (void *)&cmd_route_add_route_string, (void *)&cmd_route_add_add_string, (void *)&cmd_route_add_ip, (void *)&cmd_route_add_depth, (void *)&cmd_route_add_port, (void *)&cmd_route_add_nh_ip, NULL, }, }; /* * route del */ struct cmd_route_del_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; cmdline_fixed_string_t del_string; cmdline_ipaddr_t ip; uint32_t depth; }; static void cmd_route_del_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_route_del_result *params = parsed_result; struct app_params *app = data; struct pipeline_routing_route_key key; int status; /* Create route */ key.type = PIPELINE_ROUTING_ROUTE_IPV4; key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); key.key.ipv4.depth = params->depth; status = app_pipeline_routing_delete_route(app, params->p, &key); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_route_del_p_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, p_string, "p"); static cmdline_parse_token_num_t cmd_route_del_p = TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, p, UINT32); static cmdline_parse_token_string_t cmd_route_del_route_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string, "route"); static cmdline_parse_token_string_t cmd_route_del_del_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string, "del"); static cmdline_parse_token_ipaddr_t cmd_route_del_ip = TOKEN_IPV4_INITIALIZER(struct cmd_route_del_result, ip); static cmdline_parse_token_num_t cmd_route_del_depth = TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT32); static cmdline_parse_inst_t cmd_route_del = { .f = cmd_route_del_parsed, .data = NULL, .help_str = "Route delete", .tokens = { (void *)&cmd_route_del_p_string, (void *)&cmd_route_del_p, (void *)&cmd_route_del_route_string, (void *)&cmd_route_del_del_string, (void *)&cmd_route_del_ip, (void *)&cmd_route_del_depth, NULL, }, }; /* * route add default */ struct cmd_route_add_default_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t default_string; uint32_t port; }; static void cmd_route_add_default_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, void *data) { struct cmd_route_add_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_routing_add_default_route(app, params->p, params->port); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_route_add_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, p_string, "p"); static cmdline_parse_token_num_t cmd_route_add_default_p = TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, p, UINT32); cmdline_parse_token_string_t cmd_route_add_default_route_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, route_string, "route"); cmdline_parse_token_string_t cmd_route_add_default_add_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, add_string, "add"); cmdline_parse_token_string_t cmd_route_add_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, default_string, "default"); cmdline_parse_token_num_t cmd_route_add_default_port = TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, port, UINT32); cmdline_parse_inst_t cmd_route_add_default = { .f = cmd_route_add_default_parsed, .data = NULL, .help_str = "Route default set", .tokens = { (void *)&cmd_route_add_default_p_string, (void *)&cmd_route_add_default_p, (void *)&cmd_route_add_default_route_string, (void *)&cmd_route_add_default_add_string, (void *)&cmd_route_add_default_default_string, (void *)&cmd_route_add_default_port, NULL, }, }; /* * route del default */ struct cmd_route_del_default_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t default_string; }; static void cmd_route_del_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_route_del_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_routing_delete_default_route(app, params->p); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_route_del_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, p_string, "p"); static cmdline_parse_token_num_t cmd_route_del_default_p = TOKEN_NUM_INITIALIZER(struct cmd_route_del_default_result, p, UINT32); static cmdline_parse_token_string_t cmd_route_del_default_route_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, route_string, "route"); static cmdline_parse_token_string_t cmd_route_del_default_del_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, del_string, "del"); static cmdline_parse_token_string_t cmd_route_del_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, default_string, "default"); static cmdline_parse_inst_t cmd_route_del_default = { .f = cmd_route_del_default_parsed, .data = NULL, .help_str = "Route default clear", .tokens = { (void *)&cmd_route_del_default_p_string, (void *)&cmd_route_del_default_p, (void *)&cmd_route_del_default_route_string, (void *)&cmd_route_del_default_del_string, (void *)&cmd_route_del_default_default_string, NULL, }, }; /* * route ls */ struct cmd_route_ls_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; cmdline_fixed_string_t ls_string; }; static void cmd_route_ls_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_route_ls_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_routing_route_ls(app, params->p); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_route_ls_p_string = TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, p_string, "p"); static cmdline_parse_token_num_t cmd_route_ls_p = TOKEN_NUM_INITIALIZER(struct cmd_route_ls_result, p, UINT32); static cmdline_parse_token_string_t cmd_route_ls_route_string = TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, route_string, "route"); static cmdline_parse_token_string_t cmd_route_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, ls_string, "ls"); static cmdline_parse_inst_t cmd_route_ls = { .f = cmd_route_ls_parsed, .data = NULL, .help_str = "Route list", .tokens = { (void *)&cmd_route_ls_p_string, (void *)&cmd_route_ls_p, (void *)&cmd_route_ls_route_string, (void *)&cmd_route_ls_ls_string, NULL, }, }; /* * arp add */ struct cmd_arp_add_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; cmdline_fixed_string_t add_string; uint32_t port_id; cmdline_ipaddr_t ip; struct ether_addr macaddr; }; static void cmd_arp_add_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_arp_add_result *params = parsed_result; struct app_params *app = data; struct pipeline_routing_arp_key key; int status; key.type = PIPELINE_ROUTING_ARP_IPV4; key.key.ipv4.port_id = params->port_id; key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr); status = app_pipeline_routing_add_arp_entry(app, params->p, &key, ¶ms->macaddr); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_arp_add_p_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, p_string, "p"); static cmdline_parse_token_num_t cmd_arp_add_p = TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, p, UINT32); static cmdline_parse_token_string_t cmd_arp_add_arp_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp"); static cmdline_parse_token_string_t cmd_arp_add_add_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add"); static cmdline_parse_token_num_t cmd_arp_add_port_id = TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, port_id, UINT32); static cmdline_parse_token_ipaddr_t cmd_arp_add_ip = TOKEN_IPV4_INITIALIZER(struct cmd_arp_add_result, ip); static cmdline_parse_token_etheraddr_t cmd_arp_add_macaddr = TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, macaddr); static cmdline_parse_inst_t cmd_arp_add = { .f = cmd_arp_add_parsed, .data = NULL, .help_str = "ARP add", .tokens = { (void *)&cmd_arp_add_p_string, (void *)&cmd_arp_add_p, (void *)&cmd_arp_add_arp_string, (void *)&cmd_arp_add_add_string, (void *)&cmd_arp_add_port_id, (void *)&cmd_arp_add_ip, (void *)&cmd_arp_add_macaddr, NULL, }, }; /* * arp del */ struct cmd_arp_del_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; cmdline_fixed_string_t del_string; uint32_t port_id; cmdline_ipaddr_t ip; }; static void cmd_arp_del_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_arp_del_result *params = parsed_result; struct app_params *app = data; struct pipeline_routing_arp_key key; int status; key.type = PIPELINE_ROUTING_ARP_IPV4; key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr); key.key.ipv4.port_id = params->port_id; status = app_pipeline_routing_delete_arp_entry(app, params->p, &key); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_arp_del_p_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, p_string, "p"); static cmdline_parse_token_num_t cmd_arp_del_p = TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, p, UINT32); static cmdline_parse_token_string_t cmd_arp_del_arp_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp"); static cmdline_parse_token_string_t cmd_arp_del_del_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del"); static cmdline_parse_token_num_t cmd_arp_del_port_id = TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, port_id, UINT32); static cmdline_parse_token_ipaddr_t cmd_arp_del_ip = TOKEN_IPV4_INITIALIZER(struct cmd_arp_del_result, ip); static cmdline_parse_inst_t cmd_arp_del = { .f = cmd_arp_del_parsed, .data = NULL, .help_str = "ARP delete", .tokens = { (void *)&cmd_arp_del_p_string, (void *)&cmd_arp_del_p, (void *)&cmd_arp_del_arp_string, (void *)&cmd_arp_del_del_string, (void *)&cmd_arp_del_port_id, (void *)&cmd_arp_del_ip, NULL, }, }; /* * arp add default */ struct cmd_arp_add_default_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; cmdline_fixed_string_t add_string; cmdline_fixed_string_t default_string; uint32_t port_id; }; static void cmd_arp_add_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_arp_add_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_routing_add_default_arp_entry(app, params->p, params->port_id); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_arp_add_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, p_string, "p"); static cmdline_parse_token_num_t cmd_arp_add_default_p = TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, p, UINT32); static cmdline_parse_token_string_t cmd_arp_add_default_arp_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, arp_string, "arp"); static cmdline_parse_token_string_t cmd_arp_add_default_add_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, add_string, "add"); static cmdline_parse_token_string_t cmd_arp_add_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, default_string, "default"); static cmdline_parse_token_num_t cmd_arp_add_default_port_id = TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, port_id, UINT32); static cmdline_parse_inst_t cmd_arp_add_default = { .f = cmd_arp_add_default_parsed, .data = NULL, .help_str = "ARP add default", .tokens = { (void *)&cmd_arp_add_default_p_string, (void *)&cmd_arp_add_default_p, (void *)&cmd_arp_add_default_arp_string, (void *)&cmd_arp_add_default_add_string, (void *)&cmd_arp_add_default_default_string, (void *)&cmd_arp_add_default_port_id, NULL, }, }; /* * arp del default */ struct cmd_arp_del_default_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; cmdline_fixed_string_t del_string; cmdline_fixed_string_t default_string; }; static void cmd_arp_del_default_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_arp_del_default_result *params = parsed_result; struct app_params *app = data; int status; status = app_pipeline_routing_delete_default_arp_entry(app, params->p); if (status != 0) { printf("Command failed\n"); return; } } static cmdline_parse_token_string_t cmd_arp_del_default_p_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, p_string, "p"); static cmdline_parse_token_num_t cmd_arp_del_default_p = TOKEN_NUM_INITIALIZER(struct cmd_arp_del_default_result, p, UINT32); static cmdline_parse_token_string_t cmd_arp_del_default_arp_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, arp_string, "arp"); static cmdline_parse_token_string_t cmd_arp_del_default_del_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, del_string, "del"); static cmdline_parse_token_string_t cmd_arp_del_default_default_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, default_string, "default"); static cmdline_parse_inst_t cmd_arp_del_default = { .f = cmd_arp_del_default_parsed, .data = NULL, .help_str = "ARP delete default", .tokens = { (void *)&cmd_arp_del_default_p_string, (void *)&cmd_arp_del_default_p, (void *)&cmd_arp_del_default_arp_string, (void *)&cmd_arp_del_default_del_string, (void *)&cmd_arp_del_default_default_string, NULL, }, }; /* * arp ls */ struct cmd_arp_ls_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; cmdline_fixed_string_t ls_string; }; static void cmd_arp_ls_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { struct cmd_arp_ls_result *params = parsed_result; struct app_params *app = data; struct pipeline_routing *p; p = app_pipeline_data_fe(app, params->p); if (p == NULL) return; app_pipeline_routing_arp_ls(app, params->p); } static cmdline_parse_token_string_t cmd_arp_ls_p_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, p_string, "p"); static cmdline_parse_token_num_t cmd_arp_ls_p = TOKEN_NUM_INITIALIZER(struct cmd_arp_ls_result, p, UINT32); static cmdline_parse_token_string_t cmd_arp_ls_arp_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, arp_string, "arp"); static cmdline_parse_token_string_t cmd_arp_ls_ls_string = TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, ls_string, "ls"); static cmdline_parse_inst_t cmd_arp_ls = { .f = cmd_arp_ls_parsed, .data = NULL, .help_str = "ARP list", .tokens = { (void *)&cmd_arp_ls_p_string, (void *)&cmd_arp_ls_p, (void *)&cmd_arp_ls_arp_string, (void *)&cmd_arp_ls_ls_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { (cmdline_parse_inst_t *)&cmd_route_add, (cmdline_parse_inst_t *)&cmd_route_del, (cmdline_parse_inst_t *)&cmd_route_add_default, (cmdline_parse_inst_t *)&cmd_route_del_default, (cmdline_parse_inst_t *)&cmd_route_ls, (cmdline_parse_inst_t *)&cmd_arp_add, (cmdline_parse_inst_t *)&cmd_arp_del, (cmdline_parse_inst_t *)&cmd_arp_add_default, (cmdline_parse_inst_t *)&cmd_arp_del_default, (cmdline_parse_inst_t *)&cmd_arp_ls, NULL, }; static struct pipeline_fe_ops pipeline_routing_fe_ops = { .f_init = pipeline_routing_init, .f_free = app_pipeline_routing_free, .cmds = pipeline_cmds, }; struct pipeline_type pipeline_routing = { .name = "ROUTING", .be_ops = &pipeline_routing_be_ops, .fe_ops = &pipeline_routing_fe_ops, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_routing.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_ROUTING_H__ #define __INCLUDE_PIPELINE_ROUTING_H__ #include "pipeline.h" #include "pipeline_routing_be.h" /* * Route */ struct app_pipeline_routing_route_params { uint32_t flags; uint32_t port_id; /* Output port ID */ uint32_t ip; /* IP address for the next hop (only for remote routes) */ }; int app_pipeline_routing_add_route(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_route_key *key, struct app_pipeline_routing_route_params *route_params); int app_pipeline_routing_delete_route(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_route_key *key); int app_pipeline_routing_add_default_route(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_pipeline_routing_delete_default_route(struct app_params *app, uint32_t pipeline_id); /* * ARP */ int app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_arp_key *key, struct ether_addr *macaddr); int app_pipeline_routing_delete_arp_entry(struct app_params *app, uint32_t pipeline_id, struct pipeline_routing_arp_key *key); int app_pipeline_routing_add_default_arp_entry(struct app_params *app, uint32_t pipeline_id, uint32_t port_id); int app_pipeline_routing_delete_default_arp_entry(struct app_params *app, uint32_t pipeline_id); /* * Pipeline type */ extern struct pipeline_type pipeline_routing; #endif ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_routing_be.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "pipeline_routing_be.h" #include "pipeline_actions_common.h" #include "hash_func.h" struct pipeline_routing { struct pipeline p; pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS]; uint32_t n_routes; uint32_t n_arp_entries; uint32_t ip_da_offset; uint32_t arp_key_offset; } __rte_cache_aligned; static void * pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler handlers[] = { [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler, [PIPELINE_MSG_REQ_STATS_PORT_IN] = pipeline_msg_req_stats_port_in_handler, [PIPELINE_MSG_REQ_STATS_PORT_OUT] = pipeline_msg_req_stats_port_out_handler, [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler, [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = pipeline_msg_req_port_in_enable_handler, [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = pipeline_msg_req_port_in_disable_handler, [PIPELINE_MSG_REQ_CUSTOM] = pipeline_routing_msg_req_custom_handler, }; static void * pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg); static void * pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg); static pipeline_msg_req_handler custom_handlers[] = { [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] = pipeline_routing_msg_req_route_add_handler, [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] = pipeline_routing_msg_req_route_del_handler, [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] = pipeline_routing_msg_req_route_add_default_handler, [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] = pipeline_routing_msg_req_route_del_default_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] = pipeline_routing_msg_req_arp_add_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] = pipeline_routing_msg_req_arp_del_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] = pipeline_routing_msg_req_arp_add_default_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] = pipeline_routing_msg_req_arp_del_default_handler, }; /* * Routing table */ struct routing_table_entry { struct rte_pipeline_table_entry head; uint32_t flags; uint32_t port_id; /* Output port ID */ uint32_t ip; /* Next hop IP address (only valid for remote routes) */ }; static inline void pkt_work_routing( struct rte_mbuf *pkt, struct rte_pipeline_table_entry *table_entry, void *arg) { struct routing_table_entry *entry = (struct routing_table_entry *) table_entry; struct pipeline_routing *p_rt = arg; struct pipeline_routing_arp_key_ipv4 *arp_key = (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->arp_key_offset); uint32_t ip = RTE_MBUF_METADATA_UINT32(pkt, p_rt->ip_da_offset); arp_key->port_id = entry->port_id; arp_key->ip = entry->ip; if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL) arp_key->ip = ip; } static inline void pkt4_work_routing( struct rte_mbuf **pkts, struct rte_pipeline_table_entry **table_entries, void *arg) { struct routing_table_entry *entry0 = (struct routing_table_entry *) table_entries[0]; struct routing_table_entry *entry1 = (struct routing_table_entry *) table_entries[1]; struct routing_table_entry *entry2 = (struct routing_table_entry *) table_entries[2]; struct routing_table_entry *entry3 = (struct routing_table_entry *) table_entries[3]; struct pipeline_routing *p_rt = arg; struct pipeline_routing_arp_key_ipv4 *arp_key0 = (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkts[0], p_rt->arp_key_offset); struct pipeline_routing_arp_key_ipv4 *arp_key1 = (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkts[1], p_rt->arp_key_offset); struct pipeline_routing_arp_key_ipv4 *arp_key2 = (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkts[2], p_rt->arp_key_offset); struct pipeline_routing_arp_key_ipv4 *arp_key3 = (struct pipeline_routing_arp_key_ipv4 *) RTE_MBUF_METADATA_UINT8_PTR(pkts[3], p_rt->arp_key_offset); uint32_t ip0 = RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->ip_da_offset); uint32_t ip1 = RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->ip_da_offset); uint32_t ip2 = RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->ip_da_offset); uint32_t ip3 = RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->ip_da_offset); arp_key0->port_id = entry0->port_id; arp_key1->port_id = entry1->port_id; arp_key2->port_id = entry2->port_id; arp_key3->port_id = entry3->port_id; arp_key0->ip = entry0->ip; if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL) arp_key0->ip = ip0; arp_key1->ip = entry1->ip; if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL) arp_key1->ip = ip1; arp_key2->ip = entry2->ip; if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL) arp_key2->ip = ip2; arp_key3->ip = entry3->ip; if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL) arp_key3->ip = ip3; } PIPELINE_TABLE_AH_HIT(routing_table_ah_hit, pkt_work_routing, pkt4_work_routing); /* * ARP table */ struct arp_table_entry { struct rte_pipeline_table_entry head; uint64_t macaddr; }; static inline void pkt_work_arp( struct rte_mbuf *pkt, struct rte_pipeline_table_entry *table_entry, __rte_unused void *arg) { struct arp_table_entry *entry = (struct arp_table_entry *) table_entry; /* Read: pkt buffer - mbuf */ uint8_t *raw = rte_pktmbuf_mtod(pkt, uint8_t *); /* Read: table entry */ uint64_t mac_addr_dst = entry->macaddr; uint64_t mac_addr_src = 0; /* Compute: Ethernet header */ uint64_t slab0 = mac_addr_dst | (mac_addr_src << 48); uint32_t slab1 = mac_addr_src >> 16; /* Write: pkt buffer - pkt headers */ *((uint64_t *) raw) = slab0; *((uint32_t *) (raw + 8)) = slab1; } static inline void pkt4_work_arp( struct rte_mbuf **pkts, struct rte_pipeline_table_entry **table_entries, __rte_unused void *arg) { struct arp_table_entry *entry0 = (struct arp_table_entry *) table_entries[0]; struct arp_table_entry *entry1 = (struct arp_table_entry *) table_entries[1]; struct arp_table_entry *entry2 = (struct arp_table_entry *) table_entries[2]; struct arp_table_entry *entry3 = (struct arp_table_entry *) table_entries[3]; /* Read: pkt buffer - mbuf */ uint8_t *raw0 = rte_pktmbuf_mtod(pkts[0], uint8_t *); uint8_t *raw1 = rte_pktmbuf_mtod(pkts[1], uint8_t *); uint8_t *raw2 = rte_pktmbuf_mtod(pkts[2], uint8_t *); uint8_t *raw3 = rte_pktmbuf_mtod(pkts[3], uint8_t *); /* Read: table entry */ uint64_t mac_addr_dst0 = entry0->macaddr; uint64_t mac_addr_dst1 = entry1->macaddr; uint64_t mac_addr_dst2 = entry2->macaddr; uint64_t mac_addr_dst3 = entry3->macaddr; uint64_t mac_addr_src0 = 0; uint64_t mac_addr_src1 = 0; uint64_t mac_addr_src2 = 0; uint64_t mac_addr_src3 = 0; /* Compute: Ethernet header */ uint64_t pkt0_slab0 = mac_addr_dst0 | (mac_addr_src0 << 48); uint64_t pkt1_slab0 = mac_addr_dst1 | (mac_addr_src1 << 48); uint64_t pkt2_slab0 = mac_addr_dst2 | (mac_addr_src2 << 48); uint64_t pkt3_slab0 = mac_addr_dst3 | (mac_addr_src3 << 48); uint32_t pkt0_slab1 = mac_addr_src0 >> 16; uint32_t pkt1_slab1 = mac_addr_src1 >> 16; uint32_t pkt2_slab1 = mac_addr_src2 >> 16; uint32_t pkt3_slab1 = mac_addr_src3 >> 16; /* Write: pkt buffer - pkt headers */ *((uint64_t *) raw0) = pkt0_slab0; *((uint32_t *) (raw0 + 8)) = pkt0_slab1; *((uint64_t *) raw1) = pkt1_slab0; *((uint32_t *) (raw1 + 8)) = pkt1_slab1; *((uint64_t *) raw2) = pkt2_slab0; *((uint32_t *) (raw2 + 8)) = pkt2_slab1; *((uint64_t *) raw3) = pkt3_slab0; *((uint32_t *) (raw3 + 8)) = pkt3_slab1; } PIPELINE_TABLE_AH_HIT(arp_table_ah_hit, pkt_work_arp, pkt4_work_arp); static int pipeline_routing_parse_args(struct pipeline_routing *p, struct pipeline_params *params) { uint32_t n_routes_present = 0; uint32_t n_arp_entries_present = 0; uint32_t ip_da_offset_present = 0; uint32_t arp_key_offset_present = 0; uint32_t i; for (i = 0; i < params->n_args; i++) { char *arg_name = params->args_name[i]; char *arg_value = params->args_value[i]; /* n_routes */ if (strcmp(arg_name, "n_routes") == 0) { if (n_routes_present) return -1; n_routes_present = 1; p->n_routes = atoi(arg_value); if (p->n_routes == 0) return -1; continue; } /* n_arp_entries */ if (strcmp(arg_name, "n_arp_entries") == 0) { if (n_arp_entries_present) return -1; n_arp_entries_present = 1; p->n_arp_entries = atoi(arg_value); if (p->n_arp_entries == 0) return -1; continue; } /* ip_da_offset */ if (strcmp(arg_name, "ip_da_offset") == 0) { if (ip_da_offset_present) return -1; ip_da_offset_present = 1; p->ip_da_offset = atoi(arg_value); continue; } /* arp_key_offset */ if (strcmp(arg_name, "arp_key_offset") == 0) { if (arp_key_offset_present) return -1; arp_key_offset_present = 1; p->arp_key_offset = atoi(arg_value); continue; } /* any other */ return -1; } /* Check that mandatory arguments are present */ if ((n_routes_present == 0) || (n_arp_entries_present == 0) || (ip_da_offset_present == 0) || (n_arp_entries_present && (arp_key_offset_present == 0))) return -1; return 0; } static void * pipeline_routing_init(struct pipeline_params *params, __rte_unused void *arg) { struct pipeline *p; struct pipeline_routing *p_rt; uint32_t size, i; /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || (params->n_ports_out == 0)) return NULL; /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); p_rt = (struct pipeline_routing *) p; if (p == NULL) return NULL; strcpy(p->name, params->name); p->log_level = params->log_level; PLOG(p, HIGH, "Routing"); /* Parse arguments */ if (pipeline_routing_parse_args(p_rt, params)) return NULL; /* Pipeline */ { struct rte_pipeline_params pipeline_params = { .name = params->name, .socket_id = params->socket_id, .offset_port_id = 0, }; p->p = rte_pipeline_create(&pipeline_params); if (p->p == NULL) { rte_free(p); return NULL; } } /* Input ports */ p->n_ports_in = params->n_ports_in; for (i = 0; i < p->n_ports_in; i++) { struct rte_pipeline_port_in_params port_params = { .ops = pipeline_port_in_params_get_ops( ¶ms->port_in[i]), .arg_create = pipeline_port_in_params_convert( ¶ms->port_in[i]), .f_action = NULL, .arg_ah = NULL, .burst_size = params->port_in[i].burst_size, }; int status = rte_pipeline_port_in_create(p->p, &port_params, &p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Output ports */ p->n_ports_out = params->n_ports_out; for (i = 0; i < p->n_ports_out; i++) { struct rte_pipeline_port_out_params port_params = { .ops = pipeline_port_out_params_get_ops( ¶ms->port_out[i]), .arg_create = pipeline_port_out_params_convert( ¶ms->port_out[i]), .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; int status = rte_pipeline_port_out_create(p->p, &port_params, &p->port_out_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Routing table */ p->n_tables = 1; { struct rte_table_lpm_params table_lpm_params = { .n_rules = p_rt->n_routes, .entry_unique_size = sizeof(struct routing_table_entry), .offset = p_rt->ip_da_offset, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_lpm_ops, .arg_create = &table_lpm_params, .f_action_hit = routing_table_ah_hit, .f_action_miss = NULL, .arg_ah = p_rt, .action_data_size = sizeof(struct routing_table_entry) - sizeof(struct rte_pipeline_table_entry), }; int status; status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* ARP table configuration */ if (p_rt->n_arp_entries) { struct rte_table_hash_key8_ext_params table_arp_params = { .n_entries = p_rt->n_arp_entries, .n_entries_ext = p_rt->n_arp_entries, .f_hash = hash_default_key8, .seed = 0, .signature_offset = 0, /* Unused */ .key_offset = p_rt->arp_key_offset, }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_hash_key8_ext_dosig_ops, .arg_create = &table_arp_params, .f_action_hit = arp_table_ah_hit, .f_action_miss = NULL, .arg_ah = p_rt, .action_data_size = sizeof(struct arp_table_entry) - sizeof(struct rte_pipeline_table_entry), }; int status; status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[1]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } p->n_tables++; } /* Connecting input ports to tables */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_connect_to_table(p->p, p->port_in_id[i], p->table_id[0]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Enable input ports */ for (i = 0; i < p->n_ports_in; i++) { int status = rte_pipeline_port_in_enable(p->p, p->port_in_id[i]); if (status) { rte_pipeline_free(p->p); rte_free(p); return NULL; } } /* Check pipeline consistency */ if (rte_pipeline_check(p->p) < 0) { rte_pipeline_free(p->p); rte_free(p); return NULL; } /* Message queues */ p->n_msgq = params->n_msgq; for (i = 0; i < p->n_msgq; i++) p->msgq_in[i] = params->msgq_in[i]; for (i = 0; i < p->n_msgq; i++) p->msgq_out[i] = params->msgq_out[i]; /* Message handlers */ memcpy(p->handlers, handlers, sizeof(p->handlers)); memcpy(p_rt->custom_handlers, custom_handlers, sizeof(p_rt->custom_handlers)); return p; } static int pipeline_routing_free(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if (p == NULL) return -1; /* Free resources */ rte_pipeline_free(p->p); rte_free(p); return 0; } static int pipeline_routing_track(void *pipeline, __rte_unused uint32_t port_in, uint32_t *port_out) { struct pipeline *p = (struct pipeline *) pipeline; /* Check input arguments */ if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL)) return -1; if (p->n_ports_in == 1) { *port_out = 0; return 0; } return -1; } static int pipeline_routing_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; pipeline_msg_req_handle(p); rte_pipeline_flush(p->p); return 0; } void * pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg) { struct pipeline_routing *p_rt = (struct pipeline_routing *) p; struct pipeline_custom_msg_req *req = msg; pipeline_msg_req_handler f_handle; f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ? p_rt->custom_handlers[req->subtype] : pipeline_msg_req_invalid_handler; if (f_handle == NULL) f_handle = pipeline_msg_req_invalid_handler; return f_handle(p, req); } void * pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) { struct pipeline_routing_route_add_msg_req *req = msg; struct pipeline_routing_route_add_msg_rsp *rsp = msg; struct rte_table_lpm_key key = { .ip = req->key.key.ipv4.ip, .depth = req->key.key.ipv4.depth, }; struct routing_table_entry entry = { .head = { .action = RTE_PIPELINE_ACTION_TABLE, {.table_id = p->table_id[1]}, }, .flags = req->flags, .port_id = req->port_id, .ip = rte_bswap32(req->ip), }; if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) { rsp->status = -1; return rsp; } rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], &key, (struct rte_pipeline_table_entry *) &entry, &rsp->key_found, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg) { struct pipeline_routing_route_delete_msg_req *req = msg; struct pipeline_routing_route_delete_msg_rsp *rsp = msg; struct rte_table_lpm_key key = { .ip = req->key.key.ipv4.ip, .depth = req->key.key.ipv4.depth, }; if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) { rsp->status = -1; return rsp; } rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], &key, &rsp->key_found, NULL); return rsp; } void * pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p, void *msg) { struct pipeline_routing_route_add_default_msg_req *req = msg; struct pipeline_routing_route_add_default_msg_rsp *rsp = msg; struct routing_table_entry default_entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, .flags = 0, .port_id = 0, .ip = 0, }; rsp->status = rte_pipeline_table_default_entry_add(p->p, p->table_id[0], (struct rte_pipeline_table_entry *) &default_entry, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p, void *msg) { struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg; rsp->status = rte_pipeline_table_default_entry_delete(p->p, p->table_id[0], NULL); return rsp; } void * pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg) { struct pipeline_routing_arp_add_msg_req *req = msg; struct pipeline_routing_arp_add_msg_rsp *rsp = msg; struct pipeline_routing_arp_key_ipv4 key = { .port_id = req->key.key.ipv4.port_id, .ip = rte_bswap32(req->key.key.ipv4.ip), }; struct arp_table_entry entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->key.key.ipv4.port_id]}, }, .macaddr = 0, /* set below */ }; if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) { rsp->status = -1; return rsp; } *((struct ether_addr *) &entry.macaddr) = req->macaddr; rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[1], &key, (struct rte_pipeline_table_entry *) &entry, &rsp->key_found, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg) { struct pipeline_routing_arp_delete_msg_req *req = msg; struct pipeline_routing_arp_delete_msg_rsp *rsp = msg; struct pipeline_routing_arp_key_ipv4 key = { .port_id = req->key.key.ipv4.port_id, .ip = rte_bswap32(req->key.key.ipv4.ip), }; if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) { rsp->status = -1; return rsp; } rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[1], &key, &rsp->key_found, NULL); return rsp; } void * pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg) { struct pipeline_routing_arp_add_default_msg_req *req = msg; struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg; struct arp_table_entry default_entry = { .head = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, .macaddr = 0, }; rsp->status = rte_pipeline_table_default_entry_add(p->p, p->table_id[1], (struct rte_pipeline_table_entry *) &default_entry, (struct rte_pipeline_table_entry **) &rsp->entry_ptr); return rsp; } void * pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg) { struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg; rsp->status = rte_pipeline_table_default_entry_delete(p->p, p->table_id[1], NULL); return rsp; } struct pipeline_be_ops pipeline_routing_be_ops = { .f_init = pipeline_routing_init, .f_free = pipeline_routing_free, .f_run = NULL, .f_timer = pipeline_routing_timer, .f_track = pipeline_routing_track, }; ================================================ FILE: examples/ip_pipeline/pipeline/pipeline_routing_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_ROUTING_BE_H__ #define __INCLUDE_PIPELINE_ROUTING_BE_H__ #include #include "pipeline_common_be.h" /* * Route */ enum pipeline_routing_route_key_type { PIPELINE_ROUTING_ROUTE_IPV4, }; struct pipeline_routing_route_key_ipv4 { uint32_t ip; uint32_t depth; }; struct pipeline_routing_route_key { enum pipeline_routing_route_key_type type; union { struct pipeline_routing_route_key_ipv4 ipv4; } key; }; enum pipeline_routing_route_flags { PIPELINE_ROUTING_ROUTE_LOCAL = 1 << 0, /* 0 = remote; 1 = local */ }; /* * ARP */ enum pipeline_routing_arp_key_type { PIPELINE_ROUTING_ARP_IPV4, }; struct pipeline_routing_arp_key_ipv4 { uint32_t port_id; uint32_t ip; }; struct pipeline_routing_arp_key { enum pipeline_routing_arp_key_type type; union { struct pipeline_routing_arp_key_ipv4 ipv4; } key; }; /* * Messages */ enum pipeline_routing_msg_req_type { PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD, PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL, PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT, PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT, PIPELINE_ROUTING_MSG_REQ_ARP_ADD, PIPELINE_ROUTING_MSG_REQ_ARP_DEL, PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT, PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT, PIPELINE_ROUTING_MSG_REQS }; /* * MSG ROUTE ADD */ struct pipeline_routing_route_add_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* key */ struct pipeline_routing_route_key key; /* data */ uint32_t flags; uint32_t port_id; /* Output port ID */ uint32_t ip; /* Next hop IP address (only valid for remote routes) */ }; struct pipeline_routing_route_add_msg_rsp { int status; int key_found; void *entry_ptr; }; /* * MSG ROUTE DELETE */ struct pipeline_routing_route_delete_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* key */ struct pipeline_routing_route_key key; }; struct pipeline_routing_route_delete_msg_rsp { int status; int key_found; }; /* * MSG ROUTE ADD DEFAULT */ struct pipeline_routing_route_add_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* data */ uint32_t port_id; }; struct pipeline_routing_route_add_default_msg_rsp { int status; void *entry_ptr; }; /* * MSG ROUTE DELETE DEFAULT */ struct pipeline_routing_route_delete_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; }; struct pipeline_routing_route_delete_default_msg_rsp { int status; }; /* * MSG ARP ADD */ struct pipeline_routing_arp_add_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* key */ struct pipeline_routing_arp_key key; /* data */ struct ether_addr macaddr; }; struct pipeline_routing_arp_add_msg_rsp { int status; int key_found; void *entry_ptr; }; /* * MSG ARP DELETE */ struct pipeline_routing_arp_delete_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* key */ struct pipeline_routing_arp_key key; }; struct pipeline_routing_arp_delete_msg_rsp { int status; int key_found; }; /* * MSG ARP ADD DEFAULT */ struct pipeline_routing_arp_add_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; /* data */ uint32_t port_id; }; struct pipeline_routing_arp_add_default_msg_rsp { int status; void *entry_ptr; }; /* * MSG ARP DELETE DEFAULT */ struct pipeline_routing_arp_delete_default_msg_req { enum pipeline_msg_req_type type; enum pipeline_routing_msg_req_type subtype; }; struct pipeline_routing_arp_delete_default_msg_rsp { int status; }; extern struct pipeline_be_ops pipeline_routing_be_ops; #endif ================================================ FILE: examples/ip_pipeline/pipeline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_H__ #define __INCLUDE_PIPELINE_H__ #include #include "pipeline_be.h" /* * Pipeline type front-end operations */ typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, void *arg); typedef int (*pipeline_fe_op_free)(void *pipeline); struct pipeline_fe_ops { pipeline_fe_op_init f_init; pipeline_fe_op_free f_free; cmdline_parse_ctx_t *cmds; }; /* * Pipeline type */ struct pipeline_type { const char *name; /* pipeline back-end */ struct pipeline_be_ops *be_ops; /* pipeline front-end */ struct pipeline_fe_ops *fe_ops; }; static inline uint32_t pipeline_type_cmds_count(struct pipeline_type *ptype) { cmdline_parse_ctx_t *cmds; uint32_t n_cmds; if (ptype->fe_ops == NULL) return 0; cmds = ptype->fe_ops->cmds; if (cmds == NULL) return 0; for (n_cmds = 0; cmds[n_cmds]; n_cmds++); return n_cmds; } #endif ================================================ FILE: examples/ip_pipeline/pipeline_be.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_PIPELINE_BE_H__ #define __INCLUDE_PIPELINE_BE_H__ #include #include #include #include #include #include #include enum pipeline_port_in_type { PIPELINE_PORT_IN_ETHDEV_READER, PIPELINE_PORT_IN_RING_READER, PIPELINE_PORT_IN_RING_READER_IPV4_FRAG, PIPELINE_PORT_IN_RING_READER_IPV6_FRAG, PIPELINE_PORT_IN_SCHED_READER, PIPELINE_PORT_IN_SOURCE, }; struct pipeline_port_in_params { enum pipeline_port_in_type type; union { struct rte_port_ethdev_reader_params ethdev; struct rte_port_ring_reader_params ring; struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag; struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag; struct rte_port_sched_reader_params sched; struct rte_port_source_params source; } params; uint32_t burst_size; }; static inline void * pipeline_port_in_params_convert(struct pipeline_port_in_params *p) { switch (p->type) { case PIPELINE_PORT_IN_ETHDEV_READER: return (void *) &p->params.ethdev; case PIPELINE_PORT_IN_RING_READER: return (void *) &p->params.ring; case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: return (void *) &p->params.ring_ipv4_frag; case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: return (void *) &p->params.ring_ipv6_frag; case PIPELINE_PORT_IN_SCHED_READER: return (void *) &p->params.sched; case PIPELINE_PORT_IN_SOURCE: return (void *) &p->params.source; default: return NULL; } } static inline struct rte_port_in_ops * pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p) { switch (p->type) { case PIPELINE_PORT_IN_ETHDEV_READER: return &rte_port_ethdev_reader_ops; case PIPELINE_PORT_IN_RING_READER: return &rte_port_ring_reader_ops; case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: return &rte_port_ring_reader_ipv4_frag_ops; case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: return &rte_port_ring_reader_ipv6_frag_ops; case PIPELINE_PORT_IN_SCHED_READER: return &rte_port_sched_reader_ops; case PIPELINE_PORT_IN_SOURCE: return &rte_port_source_ops; default: return NULL; } } enum pipeline_port_out_type { PIPELINE_PORT_OUT_ETHDEV_WRITER, PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP, PIPELINE_PORT_OUT_RING_WRITER, PIPELINE_PORT_OUT_RING_WRITER_NODROP, PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS, PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS, PIPELINE_PORT_OUT_SCHED_WRITER, PIPELINE_PORT_OUT_SINK, }; struct pipeline_port_out_params { enum pipeline_port_out_type type; union { struct rte_port_ethdev_writer_params ethdev; struct rte_port_ethdev_writer_nodrop_params ethdev_nodrop; struct rte_port_ring_writer_params ring; struct rte_port_ring_writer_nodrop_params ring_nodrop; struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras; struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras; struct rte_port_sched_writer_params sched; } params; }; static inline void * pipeline_port_out_params_convert(struct pipeline_port_out_params *p) { switch (p->type) { case PIPELINE_PORT_OUT_ETHDEV_WRITER: return (void *) &p->params.ethdev; case PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP: return (void *) &p->params.ethdev_nodrop; case PIPELINE_PORT_OUT_RING_WRITER: return (void *) &p->params.ring; case PIPELINE_PORT_OUT_RING_WRITER_NODROP: return (void *) &p->params.ring_nodrop; case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: return (void *) &p->params.ring_ipv4_ras; case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: return (void *) &p->params.ring_ipv6_ras; case PIPELINE_PORT_OUT_SCHED_WRITER: return (void *) &p->params.sched; case PIPELINE_PORT_OUT_SINK: default: return NULL; } } static inline void * pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) { switch (p->type) { case PIPELINE_PORT_OUT_ETHDEV_WRITER: return &rte_port_ethdev_writer_ops; case PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP: return &rte_port_ethdev_writer_nodrop_ops; case PIPELINE_PORT_OUT_RING_WRITER: return &rte_port_ring_writer_ops; case PIPELINE_PORT_OUT_RING_WRITER_NODROP: return &rte_port_ring_writer_nodrop_ops; case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: return &rte_port_ring_writer_ipv4_ras_ops; case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: return &rte_port_ring_writer_ipv6_ras_ops; case PIPELINE_PORT_OUT_SCHED_WRITER: return &rte_port_sched_writer_ops; case PIPELINE_PORT_OUT_SINK: return &rte_port_sink_ops; default: return NULL; } } #ifndef PIPELINE_NAME_SIZE #define PIPELINE_NAME_SIZE 32 #endif #ifndef PIPELINE_MAX_PORT_IN #define PIPELINE_MAX_PORT_IN 16 #endif #ifndef PIPELINE_MAX_PORT_OUT #define PIPELINE_MAX_PORT_OUT 16 #endif #ifndef PIPELINE_MAX_TABLES #define PIPELINE_MAX_TABLES 16 #endif #ifndef PIPELINE_MAX_MSGQ_IN #define PIPELINE_MAX_MSGQ_IN 16 #endif #ifndef PIPELINE_MAX_MSGQ_OUT #define PIPELINE_MAX_MSGQ_OUT 16 #endif #ifndef PIPELINE_MAX_ARGS #define PIPELINE_MAX_ARGS 32 #endif struct pipeline_params { char name[PIPELINE_NAME_SIZE]; struct pipeline_port_in_params port_in[PIPELINE_MAX_PORT_IN]; struct pipeline_port_out_params port_out[PIPELINE_MAX_PORT_OUT]; struct rte_ring *msgq_in[PIPELINE_MAX_MSGQ_IN]; struct rte_ring *msgq_out[PIPELINE_MAX_MSGQ_OUT]; uint32_t n_ports_in; uint32_t n_ports_out; uint32_t n_msgq; int socket_id; char *args_name[PIPELINE_MAX_ARGS]; char *args_value[PIPELINE_MAX_ARGS]; uint32_t n_args; uint32_t log_level; }; /* * Pipeline type back-end operations */ typedef void* (*pipeline_be_op_init)(struct pipeline_params *params, void *arg); typedef int (*pipeline_be_op_free)(void *pipeline); typedef int (*pipeline_be_op_run)(void *pipeline); typedef int (*pipeline_be_op_timer)(void *pipeline); typedef int (*pipeline_be_op_track)(void *pipeline, uint32_t port_in, uint32_t *port_out); struct pipeline_be_ops { pipeline_be_op_init f_init; pipeline_be_op_free f_free; pipeline_be_op_run f_run; pipeline_be_op_timer f_timer; pipeline_be_op_track f_track; }; #endif ================================================ FILE: examples/ip_pipeline/thread.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "pipeline_common_be.h" #include "app.h" int app_thread(void *arg) { struct app_params *app = (struct app_params *) arg; uint32_t core_id = rte_lcore_id(), i, j; struct app_thread_data *t = &app->thread_data[core_id]; uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular)); uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom)); for (i = 0; ; i++) { /* Run regular pipelines */ for (j = 0; j < n_regular; j++) { struct app_thread_pipeline_data *data = &t->regular[j]; struct pipeline *p = data->be; rte_pipeline_run(p->p); } /* Run custom pipelines */ for (j = 0; j < n_custom; j++) { struct app_thread_pipeline_data *data = &t->custom[j]; data->f_run(data->be); } /* Timer */ if ((i & 0xF) == 0) { uint64_t time = rte_get_tsc_cycles(); uint64_t t_deadline = UINT64_MAX; if (time < t->deadline) continue; /* Timer for regular pipelines */ for (j = 0; j < n_regular; j++) { struct app_thread_pipeline_data *data = &t->regular[j]; uint64_t p_deadline = data->deadline; if (p_deadline <= time) { data->f_timer(data->be); p_deadline = time + data->timer_period; data->deadline = p_deadline; } if (p_deadline < t_deadline) t_deadline = p_deadline; } /* Timer for custom pipelines */ for (j = 0; j < n_custom; j++) { struct app_thread_pipeline_data *data = &t->custom[j]; uint64_t p_deadline = data->deadline; if (p_deadline <= time) { data->f_timer(data->be); p_deadline = time + data->timer_period; data->deadline = p_deadline; } if (p_deadline < t_deadline) t_deadline = p_deadline; } t->deadline = t_deadline; } } return 0; } ================================================ FILE: examples/ip_reassembly/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = ip_reassembly # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/ip_reassembly/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_PKT_BURST 32 #define RTE_LOGTYPE_IP_RSMBL RTE_LOGTYPE_USER1 #define MAX_JUMBO_PKT_LEN 9600 #define BUF_SIZE RTE_MBUF_DEFAULT_DATAROOM #define MBUF_SIZE \ (BUF_SIZE + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) #define NB_MBUF 8192 /* allow max jumbo frame 9.5 KB */ #define JUMBO_FRAME_MAX_SIZE 0x2600 #define MAX_FLOW_NUM UINT16_MAX #define MIN_FLOW_NUM 1 #define DEF_FLOW_NUM 0x1000 /* TTL numbers are in ms. */ #define MAX_FLOW_TTL (3600 * MS_PER_S) #define MIN_FLOW_TTL 1 #define DEF_FLOW_TTL MS_PER_S #define MAX_FRAG_NUM RTE_LIBRTE_IP_FRAG_MAX_FRAG /* Should be power of two. */ #define IP_FRAG_TBL_BUCKET_ENTRIES 16 static uint32_t max_flow_num = DEF_FLOW_NUM; static uint32_t max_flow_ttl = DEF_FLOW_TTL; #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 8 /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; #ifndef IPv4_BYTES #define IPv4_BYTES_FMT "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 #define IPv4_BYTES(addr) \ (uint8_t) (((addr) >> 24) & 0xFF),\ (uint8_t) (((addr) >> 16) & 0xFF),\ (uint8_t) (((addr) >> 8) & 0xFF),\ (uint8_t) ((addr) & 0xFF) #endif #ifndef IPv6_BYTES #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ "%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define IPv6_BYTES(addr) \ addr[0], addr[1], addr[2], addr[3], \ addr[4], addr[5], addr[6], addr[7], \ addr[8], addr[9], addr[10], addr[11],\ addr[12], addr[13],addr[14], addr[15] #endif #define IPV6_ADDR_LEN 16 /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; static int rx_queue_per_lcore = 1; struct mbuf_table { uint32_t len; uint32_t head; uint32_t tail; struct rte_mbuf *m_table[0]; }; struct rx_queue { struct rte_ip_frag_tbl *frag_tbl; struct rte_mempool *pool; struct rte_lpm *lpm; struct rte_lpm6 *lpm6; uint8_t portid; }; struct tx_lcore_stat { uint64_t call; uint64_t drop; uint64_t queue; uint64_t send; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 #define MAX_RX_QUEUE_PER_PORT 128 struct lcore_queue_conf { uint16_t n_rx_queue; struct rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct rte_ip_frag_death_row death_row; struct mbuf_table *tx_mbufs[RTE_MAX_ETHPORTS]; struct tx_lcore_stat tx_stat; } __rte_cache_aligned; static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 1, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; /* * IPv4 forwarding table */ struct l3fwd_ipv4_route { uint32_t ip; uint8_t depth; uint8_t if_out; }; struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = { {IPv4(100,10,0,0), 16, 0}, {IPv4(100,20,0,0), 16, 1}, {IPv4(100,30,0,0), 16, 2}, {IPv4(100,40,0,0), 16, 3}, {IPv4(100,50,0,0), 16, 4}, {IPv4(100,60,0,0), 16, 5}, {IPv4(100,70,0,0), 16, 6}, {IPv4(100,80,0,0), 16, 7}, }; /* * IPv6 forwarding table */ struct l3fwd_ipv6_route { uint8_t ip[IPV6_ADDR_LEN]; uint8_t depth; uint8_t if_out; }; static struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = { {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0}, {{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1}, {{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2}, {{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3}, {{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4}, {{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5}, {{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6}, {{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7}, }; #define LPM_MAX_RULES 1024 #define LPM6_MAX_RULES 1024 #define LPM6_NUMBER_TBL8S (1 << 16) struct rte_lpm6_config lpm6_config = { .max_rules = LPM6_MAX_RULES, .number_tbl8s = LPM6_NUMBER_TBL8S, .flags = 0 }; static struct rte_lpm *socket_lpm[RTE_MAX_NUMA_NODES]; static struct rte_lpm6 *socket_lpm6[RTE_MAX_NUMA_NODES]; #ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT #define TX_LCORE_STAT_UPDATE(s, f, v) ((s)->f += (v)) #else #define TX_LCORE_STAT_UPDATE(s, f, v) do {} while (0) #endif /* RTE_LIBRTE_IP_FRAG_TBL_STAT */ /* * If number of queued packets reached given threahold, then * send burst of packets on an output interface. */ static inline uint32_t send_burst(struct lcore_queue_conf *qconf, uint32_t thresh, uint8_t port) { uint32_t fill, len, k, n; struct mbuf_table *txmb; txmb = qconf->tx_mbufs[port]; len = txmb->len; if ((int32_t)(fill = txmb->head - txmb->tail) < 0) fill += len; if (fill >= thresh) { n = RTE_MIN(len - txmb->tail, fill); k = rte_eth_tx_burst(port, qconf->tx_queue_id[port], txmb->m_table + txmb->tail, (uint16_t)n); TX_LCORE_STAT_UPDATE(&qconf->tx_stat, call, 1); TX_LCORE_STAT_UPDATE(&qconf->tx_stat, send, k); fill -= k; if ((txmb->tail += k) == len) txmb->tail = 0; } return (fill); } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { uint32_t fill, lcore_id, len; struct lcore_queue_conf *qconf; struct mbuf_table *txmb; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; txmb = qconf->tx_mbufs[port]; len = txmb->len; fill = send_burst(qconf, MAX_PKT_BURST, port); if (fill == len - 1) { TX_LCORE_STAT_UPDATE(&qconf->tx_stat, drop, 1); rte_pktmbuf_free(txmb->m_table[txmb->tail]); if (++txmb->tail == len) txmb->tail = 0; } TX_LCORE_STAT_UPDATE(&qconf->tx_stat, queue, 1); txmb->m_table[txmb->head] = m; if(++txmb->head == len) txmb->head = 0; return (0); } static inline void reassemble(struct rte_mbuf *m, uint8_t portid, uint32_t queue, struct lcore_queue_conf *qconf, uint64_t tms) { struct ether_hdr *eth_hdr; struct rte_ip_frag_tbl *tbl; struct rte_ip_frag_death_row *dr; struct rx_queue *rxq; void *d_addr_bytes; uint8_t next_hop, dst_port; rxq = &qconf->rx_queue_list[queue]; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); dst_port = portid; /* if packet is IPv4 */ #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { #else if (m->ol_flags & (PKT_RX_IPV4_HDR)) { #endif struct ipv4_hdr *ip_hdr; uint32_t ip_dst; ip_hdr = (struct ipv4_hdr *)(eth_hdr + 1); /* if it is a fragmented packet, then try to reassemble. */ if (rte_ipv4_frag_pkt_is_fragmented(ip_hdr)) { struct rte_mbuf *mo; tbl = rxq->frag_tbl; dr = &qconf->death_row; /* prepare mbuf: setup l2_len/l3_len. */ m->l2_len = sizeof(*eth_hdr); m->l3_len = sizeof(*ip_hdr); /* process this fragment. */ mo = rte_ipv4_frag_reassemble_packet(tbl, dr, m, tms, ip_hdr); if (mo == NULL) /* no packet to send out. */ return; /* we have our packet reassembled. */ if (mo != m) { m = mo; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); ip_hdr = (struct ipv4_hdr *)(eth_hdr + 1); } } ip_dst = rte_be_to_cpu_32(ip_hdr->dst_addr); /* Find destination port */ if (rte_lpm_lookup(rxq->lpm, ip_dst, &next_hop) == 0 && (enabled_port_mask & 1 << next_hop) != 0) { dst_port = next_hop; } eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { /* if packet is IPv6 */ #else } /* if packet is IPv6 */ else if (m->ol_flags & (PKT_RX_IPV6_HDR | PKT_RX_IPV6_HDR_EXT)) { #endif struct ipv6_extension_fragment *frag_hdr; struct ipv6_hdr *ip_hdr; ip_hdr = (struct ipv6_hdr *)(eth_hdr + 1); frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(ip_hdr); if (frag_hdr != NULL) { struct rte_mbuf *mo; tbl = rxq->frag_tbl; dr = &qconf->death_row; /* prepare mbuf: setup l2_len/l3_len. */ m->l2_len = sizeof(*eth_hdr); m->l3_len = sizeof(*ip_hdr) + sizeof(*frag_hdr); mo = rte_ipv6_frag_reassemble_packet(tbl, dr, m, tms, ip_hdr, frag_hdr); if (mo == NULL) return; if (mo != m) { m = mo; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); ip_hdr = (struct ipv6_hdr *)(eth_hdr + 1); } } /* Find destination port */ if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr, &next_hop) == 0 && (enabled_port_mask & 1 << next_hop) != 0) { dst_port = next_hop; } eth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv6); } /* if packet wasn't IPv4 or IPv6, it's forwarded to the port it came from */ /* 02:00:00:00:00:xx */ d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; *((uint64_t *)d_addr_bytes) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); } /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t diff_tsc, cur_tsc, prev_tsc; int i, j, nb_rx; uint8_t portid; struct lcore_queue_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, IP_RSMBL, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, IP_RSMBL, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].portid; RTE_LOG(INFO, IP_RSMBL, " -- lcoreid=%u portid=%hhu\n", lcore_id, portid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if ((enabled_port_mask & (1 << portid)) != 0) send_burst(qconf, 1, portid); } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; ++i) { portid = qconf->rx_queue_list[i].portid; nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, MAX_PKT_BURST); /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); reassemble(pkts_burst[j], portid, i, qconf, cur_tsc); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { reassemble(pkts_burst[j], portid, i, qconf, cur_tsc); } rte_ip_frag_free_death_row(&qconf->death_row, PREFETCH_OFFSET); } } } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]" " [--max-pkt-len PKTLEN]" " [--maxflows=] [--flowttl=[(s|ms)]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of RX queues per lcore\n" " --maxflows=: optional, maximum number of flows " "supported\n" " --flowttl=[(s|ms)]: optional, maximum TTL for each " "flow\n", prgname); } static uint32_t parse_flow_num(const char *str, uint32_t min, uint32_t max, uint32_t *val) { char *end; uint64_t v; /* parse decimal string */ errno = 0; v = strtoul(str, &end, 10); if (errno != 0 || *end != '\0') return (-EINVAL); if (v < min || v > max) return (-EINVAL); *val = (uint32_t)v; return (0); } static int parse_flow_ttl(const char *str, uint32_t min, uint32_t max, uint32_t *val) { char *end; uint64_t v; static const char frmt_sec[] = "s"; static const char frmt_msec[] = "ms"; /* parse decimal string */ errno = 0; v = strtoul(str, &end, 10); if (errno != 0) return (-EINVAL); if (*end != '\0') { if (strncmp(frmt_sec, end, sizeof(frmt_sec)) == 0) v *= MS_PER_S; else if (strncmp(frmt_msec, end, sizeof (frmt_msec)) != 0) return (-EINVAL); } if (v < min || v > max) return (-EINVAL); *val = (uint32_t)v; return (0); } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; printf("%p\n", q_arg); /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n == 0) return -1; if (n >= MAX_RX_QUEUE_PER_LCORE) return -1; return n; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"max-pkt-len", 1, 0, 0}, {"maxflows", 1, 0, 0}, {"flowttl", 1, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* nqueue */ case 'q': rx_queue_per_lcore = parse_nqueue(optarg); if (rx_queue_per_lcore < 0) { printf("invalid queue number\n"); print_usage(prgname); return -1; } break; /* long options */ case 0: if (!strncmp(lgopts[option_index].name, "maxflows", 8)) { if ((ret = parse_flow_num(optarg, MIN_FLOW_NUM, MAX_FLOW_NUM, &max_flow_num)) != 0) { printf("invalid value: \"%s\" for " "parameter %s\n", optarg, lgopts[option_index].name); print_usage(prgname); return (ret); } } if (!strncmp(lgopts[option_index].name, "flowttl", 7)) { if ((ret = parse_flow_ttl(optarg, MIN_FLOW_TTL, MAX_FLOW_TTL, &max_flow_ttl)) != 0) { printf("invalid value: \"%s\" for " "parameter %s\n", optarg, lgopts[option_index].name); print_usage(prgname); return (ret); } } break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("\ndone\n"); } } } static int init_routing_table(void) { struct rte_lpm *lpm; struct rte_lpm6 *lpm6; int socket, ret; unsigned i; for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { if (socket_lpm[socket]) { lpm = socket_lpm[socket]; /* populate the LPM table */ for (i = 0; i < RTE_DIM(l3fwd_ipv4_route_array); i++) { ret = rte_lpm_add(lpm, l3fwd_ipv4_route_array[i].ip, l3fwd_ipv4_route_array[i].depth, l3fwd_ipv4_route_array[i].if_out); if (ret < 0) { RTE_LOG(ERR, IP_RSMBL, "Unable to add entry %i to the l3fwd " "LPM table\n", i); return -1; } RTE_LOG(INFO, IP_RSMBL, "Socket %i: adding route " IPv4_BYTES_FMT "/%d (port %d)\n", socket, IPv4_BYTES(l3fwd_ipv4_route_array[i].ip), l3fwd_ipv4_route_array[i].depth, l3fwd_ipv4_route_array[i].if_out); } } if (socket_lpm6[socket]) { lpm6 = socket_lpm6[socket]; /* populate the LPM6 table */ for (i = 0; i < RTE_DIM(l3fwd_ipv6_route_array); i++) { ret = rte_lpm6_add(lpm6, l3fwd_ipv6_route_array[i].ip, l3fwd_ipv6_route_array[i].depth, l3fwd_ipv6_route_array[i].if_out); if (ret < 0) { RTE_LOG(ERR, IP_RSMBL, "Unable to add entry %i to the l3fwd " "LPM6 table\n", i); return -1; } RTE_LOG(INFO, IP_RSMBL, "Socket %i: adding route " IPv6_BYTES_FMT "/%d (port %d)\n", socket, IPv6_BYTES(l3fwd_ipv6_route_array[i].ip), l3fwd_ipv6_route_array[i].depth, l3fwd_ipv6_route_array[i].if_out); } } } return 0; } static int setup_port_tbl(struct lcore_queue_conf *qconf, uint32_t lcore, int socket, uint32_t port) { struct mbuf_table *mtb; uint32_t n; size_t sz; n = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST); sz = sizeof (*mtb) + sizeof (mtb->m_table[0]) * n; if ((mtb = rte_zmalloc_socket(__func__, sz, RTE_CACHE_LINE_SIZE, socket)) == NULL) { RTE_LOG(ERR, IP_RSMBL, "%s() for lcore: %u, port: %u " "failed to allocate %zu bytes\n", __func__, lcore, port, sz); return -1; } mtb->len = n; qconf->tx_mbufs[port] = mtb; return 0; } static int setup_queue_tbl(struct rx_queue *rxq, uint32_t lcore, uint32_t queue) { int socket; uint32_t nb_mbuf; uint64_t frag_cycles; char buf[RTE_MEMPOOL_NAMESIZE]; socket = rte_lcore_to_socket_id(lcore); if (socket == SOCKET_ID_ANY) socket = 0; frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl; if ((rxq->frag_tbl = rte_ip_frag_table_create(max_flow_num, IP_FRAG_TBL_BUCKET_ENTRIES, max_flow_num, frag_cycles, socket)) == NULL) { RTE_LOG(ERR, IP_RSMBL, "ip_frag_tbl_create(%u) on " "lcore: %u for queue: %u failed\n", max_flow_num, lcore, queue); return -1; } /* * At any given moment up to * mbufs could be stored int the fragment table. * Plus, each TX queue can hold up to packets. */ nb_mbuf = RTE_MAX(max_flow_num, 2UL * MAX_PKT_BURST) * MAX_FRAG_NUM; nb_mbuf *= (port_conf.rxmode.max_rx_pkt_len + BUF_SIZE - 1) / BUF_SIZE; nb_mbuf *= 2; /* ipv4 and ipv6 */ nb_mbuf += RTE_TEST_RX_DESC_DEFAULT + RTE_TEST_TX_DESC_DEFAULT; nb_mbuf = RTE_MAX(nb_mbuf, (uint32_t)NB_MBUF); snprintf(buf, sizeof(buf), "mbuf_pool_%u_%u", lcore, queue); if ((rxq->pool = rte_mempool_create(buf, nb_mbuf, MBUF_SIZE, 0, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, socket, MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET)) == NULL) { RTE_LOG(ERR, IP_RSMBL, "mempool_create(%s) failed", buf); return -1; } return 0; } static int init_mem(void) { char buf[PATH_MAX]; struct rte_lpm *lpm; struct rte_lpm6 *lpm6; int socket; unsigned lcore_id; /* traverse through lcores and initialize structures on each socket */ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socket = rte_lcore_to_socket_id(lcore_id); if (socket == SOCKET_ID_ANY) socket = 0; if (socket_lpm[socket] == NULL) { RTE_LOG(INFO, IP_RSMBL, "Creating LPM table on socket %i\n", socket); snprintf(buf, sizeof(buf), "IP_RSMBL_LPM_%i", socket); lpm = rte_lpm_create(buf, socket, LPM_MAX_RULES, 0); if (lpm == NULL) { RTE_LOG(ERR, IP_RSMBL, "Cannot create LPM table\n"); return -1; } socket_lpm[socket] = lpm; } if (socket_lpm6[socket] == NULL) { RTE_LOG(INFO, IP_RSMBL, "Creating LPM6 table on socket %i\n", socket); snprintf(buf, sizeof(buf), "IP_RSMBL_LPM_%i", socket); lpm6 = rte_lpm6_create("IP_RSMBL_LPM6", socket, &lpm6_config); if (lpm6 == NULL) { RTE_LOG(ERR, IP_RSMBL, "Cannot create LPM table\n"); return -1; } socket_lpm6[socket] = lpm6; } } return 0; } static void queue_dump_stat(void) { uint32_t i, lcore; const struct lcore_queue_conf *qconf; for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) { if (rte_lcore_is_enabled(lcore) == 0) continue; qconf = &lcore_queue_conf[lcore]; for (i = 0; i < qconf->n_rx_queue; i++) { fprintf(stdout, " -- lcoreid=%u portid=%hhu " "frag tbl stat:\n", lcore, qconf->rx_queue_list[i].portid); rte_ip_frag_table_statistics_dump(stdout, qconf->rx_queue_list[i].frag_tbl); fprintf(stdout, "TX bursts:\t%" PRIu64 "\n" "TX packets _queued:\t%" PRIu64 "\n" "TX packets dropped:\t%" PRIu64 "\n" "TX packets send:\t%" PRIu64 "\n", qconf->tx_stat.call, qconf->tx_stat.queue, qconf->tx_stat.drop, qconf->tx_stat.send); } } } static void signal_handler(int signum) { queue_dump_stat(); if (signum != SIGUSR1) rte_exit(0, "received signal: %d, exiting\n", signum); } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; struct rx_queue *rxq; int ret, socket; unsigned nb_ports; uint16_t queueid; unsigned lcore_id = 0, rx_lcore_id = 0; uint32_t n_tx_queue, nb_lcores; uint8_t portid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid IP reassembly parameters\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; else if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No ports found!\n"); nb_lcores = rte_lcore_count(); /* initialize structures (mempools, lpm etc.) */ if (init_mem() < 0) rte_panic("Cannot initialize memory structures!\n"); /* check if portmask has non-existent ports */ if (enabled_port_mask & ~(RTE_LEN2MASK(nb_ports, unsigned))) rte_exit(EXIT_FAILURE, "Non-existent ports in portmask!\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } qconf = &lcore_queue_conf[rx_lcore_id]; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || qconf->n_rx_queue == (unsigned)rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); qconf = &lcore_queue_conf[rx_lcore_id]; } socket = rte_lcore_to_socket_id(portid); if (socket == SOCKET_ID_ANY) socket = 0; queueid = qconf->n_rx_queue; rxq = &qconf->rx_queue_list[queueid]; rxq->portid = portid; rxq->lpm = socket_lpm[socket]; rxq->lpm6 = socket_lpm6[socket]; if (setup_queue_tbl(rxq, rx_lcore_id, queueid) < 0) rte_exit(EXIT_FAILURE, "Failed to set up queue table\n"); qconf->n_rx_queue++; /* init port */ printf("Initializing port %d ... ", portid ); fflush(stdout); n_tx_queue = nb_lcores; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) { printf("\n"); rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%d\n", ret, portid); } /* init one RX queue */ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, socket, NULL, rxq->pool); if (ret < 0) { printf("\n"); rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: " "err=%d, port=%d\n", ret, portid); } rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf("\n"); /* init one TX queue per couple (lcore,port) */ queueid = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socket = (int) rte_lcore_to_socket_id(lcore_id); printf("txq=%u,%d,%d ", lcore_id, queueid, socket); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socket, txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_queue_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; setup_port_tbl(qconf, lcore_id, socket, portid); queueid++; } printf("\n"); } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); rte_eth_promiscuous_enable(portid); } if (init_routing_table() < 0) rte_exit(EXIT_FAILURE, "Cannot init routing table\n"); check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); signal(SIGUSR1, signal_handler); signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/ipv4_multicast/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = ipv4_multicast # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/ipv4_multicast/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_IPv4_MULTICAST RTE_LOGTYPE_USER1 #define MAX_PORTS 16 #define MCAST_CLONE_PORTS 2 #define MCAST_CLONE_SEGS 2 #define PKT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE #define NB_PKT_MBUF 8192 #define HDR_MBUF_DATA_SIZE (2 * RTE_PKTMBUF_HEADROOM) #define NB_HDR_MBUF (NB_PKT_MBUF * MAX_PORTS) #define NB_CLONE_MBUF (NB_PKT_MBUF * MCAST_CLONE_PORTS * MCAST_CLONE_SEGS * 2) /* allow max jumbo frame 9.5 KB */ #define JUMBO_FRAME_MAX_SIZE 0x2600 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Construct Ethernet multicast address from IPv4 multicast address. * Citing RFC 1112, section 6.4: * "An IP host group address is mapped to an Ethernet multicast address * by placing the low-order 23-bits of the IP address into the low-order * 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex)." */ #define ETHER_ADDR_FOR_IPV4_MCAST(x) \ (rte_cpu_to_be_64(0x01005e000000ULL | ((x) & 0x7fffff)) >> 16) /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[MAX_PORTS]; /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; static uint8_t nb_ports = 0; static int rx_queue_per_lcore = 1; struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { uint64_t tx_tsc; uint16_t n_rx_queue; uint8_t rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[MAX_PORTS]; struct mbuf_table tx_mbufs[MAX_PORTS]; } __rte_cache_aligned; static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 1, /**< Jumbo Frame Support enabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool *packet_pool, *header_pool, *clone_pool; /* Multicast */ static struct rte_fbk_hash_params mcast_hash_params = { .name = "MCAST_HASH", .entries = 1024, .entries_per_bucket = 4, .socket_id = 0, .hash_func = NULL, .init_val = 0, }; struct rte_fbk_hash_table *mcast_hash = NULL; struct mcast_group_params { uint32_t ip; uint16_t port_mask; }; static struct mcast_group_params mcast_group_table[] = { {IPv4(224,0,0,101), 0x1}, {IPv4(224,0,0,102), 0x2}, {IPv4(224,0,0,103), 0x3}, {IPv4(224,0,0,104), 0x4}, {IPv4(224,0,0,105), 0x5}, {IPv4(224,0,0,106), 0x6}, {IPv4(224,0,0,107), 0x7}, {IPv4(224,0,0,108), 0x8}, {IPv4(224,0,0,109), 0x9}, {IPv4(224,0,0,110), 0xA}, {IPv4(224,0,0,111), 0xB}, {IPv4(224,0,0,112), 0xC}, {IPv4(224,0,0,113), 0xD}, {IPv4(224,0,0,114), 0xE}, {IPv4(224,0,0,115), 0xF}, }; #define N_MCAST_GROUPS \ (sizeof (mcast_group_table) / sizeof (mcast_group_table[0])) /* Send burst of packets on an output interface */ static void send_burst(struct lcore_queue_conf *qconf, uint8_t port) { struct rte_mbuf **m_table; uint16_t n, queueid; int ret; queueid = qconf->tx_queue_id[port]; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; n = qconf->tx_mbufs[port].len; ret = rte_eth_tx_burst(port, queueid, m_table, n); while (unlikely (ret < n)) { rte_pktmbuf_free(m_table[ret]); ret++; } qconf->tx_mbufs[port].len = 0; } /* Get number of bits set. */ static inline uint32_t bitcnt(uint32_t v) { uint32_t n; for (n = 0; v != 0; v &= v - 1, n++) ; return (n); } /** * Create the output multicast packet based on the given input packet. * There are two approaches for creating outgoing packet, though both * are based on data zero-copy idea, they differ in few details: * First one creates a clone of the input packet, e.g - walk though all * segments of the input packet, and for each of them create a new packet * mbuf and attach that new mbuf to the segment (refer to rte_pktmbuf_clone() * for more details). Then new mbuf is allocated for the packet header * and is prepended to the 'clone' mbuf. * Second approach doesn't make a clone, it just increment refcnt for all * input packet segments. Then it allocates new mbuf for the packet header * and prepends it to the input packet. * Basically first approach reuses only input packet's data, but creates * it's own copy of packet's metadata. Second approach reuses both input's * packet data and metadata. * The advantage of first approach - is that each outgoing packet has it's * own copy of metadata, so we can safely modify data pointer of the * input packet. That allows us to skip creation if the output packet for * the last destination port, but instead modify input packet's header inplace, * e.g: for N destination ports we need to invoke mcast_out_pkt (N-1) times. * The advantage of second approach - less work for each outgoing packet, * e.g: we skip "clone" operation completely. Though it comes with a price - * input packet's metadata has to be intact. So for N destination ports we * need to invoke mcast_out_pkt N times. * So for small number of outgoing ports (and segments in the input packet) * first approach will be faster. * As number of outgoing ports (and/or input segments) will grow, * second way will become more preferable. * * @param pkt * Input packet mbuf. * @param use_clone * Control which of the two approaches described above should be used: * - 0 - use second approach: * Don't "clone" input packet. * Prepend new header directly to the input packet * - 1 - use first approach: * Make a "clone" of input packet first. * Prepend new header to the clone of the input packet * @return * - The pointer to the new outgoing packet. * - NULL if operation failed. */ static inline struct rte_mbuf * mcast_out_pkt(struct rte_mbuf *pkt, int use_clone) { struct rte_mbuf *hdr; /* Create new mbuf for the header. */ if (unlikely ((hdr = rte_pktmbuf_alloc(header_pool)) == NULL)) return (NULL); /* If requested, then make a new clone packet. */ if (use_clone != 0 && unlikely ((pkt = rte_pktmbuf_clone(pkt, clone_pool)) == NULL)) { rte_pktmbuf_free(hdr); return (NULL); } /* prepend new header */ hdr->next = pkt; /* update header's fields */ hdr->pkt_len = (uint16_t)(hdr->data_len + pkt->pkt_len); hdr->nb_segs = (uint8_t)(pkt->nb_segs + 1); /* copy metadata from source packet*/ hdr->port = pkt->port; hdr->vlan_tci = pkt->vlan_tci; hdr->vlan_tci_outer = pkt->vlan_tci_outer; hdr->tx_offload = pkt->tx_offload; hdr->hash = pkt->hash; hdr->ol_flags = pkt->ol_flags; __rte_mbuf_sanity_check(hdr, 1); return (hdr); } /* * Write new Ethernet header to the outgoing packet, * and put it into the outgoing queue for the given port. */ static inline void mcast_send_pkt(struct rte_mbuf *pkt, struct ether_addr *dest_addr, struct lcore_queue_conf *qconf, uint8_t port) { struct ether_hdr *ethdr; uint16_t len; /* Construct Ethernet header. */ ethdr = (struct ether_hdr *)rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(*ethdr)); RTE_MBUF_ASSERT(ethdr != NULL); ether_addr_copy(dest_addr, ðdr->d_addr); ether_addr_copy(&ports_eth_addr[port], ðdr->s_addr); ethdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4); /* Put new packet into the output queue */ len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = pkt; qconf->tx_mbufs[port].len = ++len; /* Transmit packets */ if (unlikely(MAX_PKT_BURST == len)) send_burst(qconf, port); } /* Multicast forward of the input packet */ static inline void mcast_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf) { struct rte_mbuf *mc; struct ipv4_hdr *iphdr; uint32_t dest_addr, port_mask, port_num, use_clone; int32_t hash; uint8_t port; union { uint64_t as_int; struct ether_addr as_addr; } dst_eth_addr; /* Remove the Ethernet header from the input packet */ iphdr = (struct ipv4_hdr *)rte_pktmbuf_adj(m, (uint16_t)sizeof(struct ether_hdr)); RTE_MBUF_ASSERT(iphdr != NULL); dest_addr = rte_be_to_cpu_32(iphdr->dst_addr); /* * Check that it is a valid multicast address and * we have some active ports assigned to it. */ if(!IS_IPV4_MCAST(dest_addr) || (hash = rte_fbk_hash_lookup(mcast_hash, dest_addr)) <= 0 || (port_mask = hash & enabled_port_mask) == 0) { rte_pktmbuf_free(m); return; } /* Calculate number of destination ports. */ port_num = bitcnt(port_mask); /* Should we use rte_pktmbuf_clone() or not. */ use_clone = (port_num <= MCAST_CLONE_PORTS && m->nb_segs <= MCAST_CLONE_SEGS); /* Mark all packet's segments as referenced port_num times */ if (use_clone == 0) rte_pktmbuf_refcnt_update(m, (uint16_t)port_num); /* construct destination ethernet address */ dst_eth_addr.as_int = ETHER_ADDR_FOR_IPV4_MCAST(dest_addr); for (port = 0; use_clone != port_mask; port_mask >>= 1, port++) { /* Prepare output packet and send it out. */ if ((port_mask & 1) != 0) { if (likely ((mc = mcast_out_pkt(m, use_clone)) != NULL)) mcast_send_pkt(mc, &dst_eth_addr.as_addr, qconf, port); else if (use_clone == 0) rte_pktmbuf_free(m); } } /* * If we making clone packets, then, for the last destination port, * we can overwrite input packet's metadata. */ if (use_clone != 0) mcast_send_pkt(m, &dst_eth_addr.as_addr, qconf, port); else rte_pktmbuf_free(m); } /* Send burst of outgoing packet, if timeout expires. */ static inline void send_timeout_burst(struct lcore_queue_conf *qconf) { uint64_t cur_tsc; uint8_t portid; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; cur_tsc = rte_rdtsc(); if (likely (cur_tsc < qconf->tx_tsc + drain_tsc)) return; for (portid = 0; portid < MAX_PORTS; portid++) { if (qconf->tx_mbufs[portid].len != 0) send_burst(qconf, portid); } qconf->tx_tsc = cur_tsc; } /* main processing loop */ static int main_loop(__rte_unused void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; int i, j, nb_rx; uint8_t portid; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, IPv4_MULTICAST, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, IPv4_MULTICAST, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i]; RTE_LOG(INFO, IPv4_MULTICAST, " -- lcoreid=%u portid=%d\n", lcore_id, (int) portid); } while (1) { /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i]; nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, MAX_PKT_BURST); /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); mcast_forward(pkts_burst[j], qconf); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { mcast_forward(pkts_burst[j], qconf); } } /* Send out packets from TX queues */ send_timeout_burst(qconf); } } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n", prgname); } static uint32_t parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; return ((uint32_t)pm); } static int parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse numerical string */ errno = 0; n = strtoul(q_arg, &end, 0); if (errno != 0 || end == NULL || *end != '\0' || n == 0 || n >= MAX_RX_QUEUE_PER_LCORE) return (-1); return (n); } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* nqueue */ case 'q': rx_queue_per_lcore = parse_nqueue(optarg); if (rx_queue_per_lcore < 0) { printf("invalid queue number\n"); print_usage(prgname); return -1; } break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } static int init_mcast_hash(void) { uint32_t i; mcast_hash_params.socket_id = rte_socket_id(); mcast_hash = rte_fbk_hash_create(&mcast_hash_params); if (mcast_hash == NULL){ return -1; } for (i = 0; i < N_MCAST_GROUPS; i ++){ if (rte_fbk_hash_add_key(mcast_hash, mcast_group_table[i].ip, mcast_group_table[i].port_mask) < 0) { return -1; } } return 0; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; int ret; uint16_t queueid; unsigned lcore_id = 0, rx_lcore_id = 0; uint32_t n_tx_queue, nb_lcores; uint8_t portid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid IPV4_MULTICAST parameters\n"); /* create the mbuf pools */ packet_pool = rte_pktmbuf_pool_create("packet_pool", NB_PKT_MBUF, 32, 0, PKT_MBUF_DATA_SIZE, rte_socket_id()); if (packet_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init packet mbuf pool\n"); header_pool = rte_pktmbuf_pool_create("header_pool", NB_HDR_MBUF, 32, 0, HDR_MBUF_DATA_SIZE, rte_socket_id()); if (header_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init header mbuf pool\n"); clone_pool = rte_pktmbuf_pool_create("clone_pool", NB_CLONE_MBUF, 32, 0, 0, rte_socket_id()); if (clone_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init clone mbuf pool\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No physical ports!\n"); if (nb_ports > MAX_PORTS) nb_ports = MAX_PORTS; nb_lcores = rte_lcore_count(); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %d\n", portid); continue; } qconf = &lcore_queue_conf[rx_lcore_id]; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || qconf->n_rx_queue == (unsigned)rx_queue_per_lcore) { rx_lcore_id ++; qconf = &lcore_queue_conf[rx_lcore_id]; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } qconf->rx_queue_list[qconf->n_rx_queue] = portid; qconf->n_rx_queue++; /* init port */ printf("Initializing port %d on lcore %u... ", portid, rx_lcore_id); fflush(stdout); n_tx_queue = nb_lcores; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); /* init one RX queue */ queueid = 0; printf("rxq=%hu ", queueid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, rte_eth_dev_socket_id(portid), NULL, packet_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, port=%d\n", ret, portid); /* init one TX queue per couple (lcore,port) */ queueid = 0; RTE_LCORE_FOREACH(lcore_id) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; printf("txq=%u,%hu ", lcore_id, queueid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, rte_lcore_to_socket_id(lcore_id), txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_queue_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; queueid++; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); printf("done:\n"); } check_all_ports_link_status(nb_ports, enabled_port_mask); /* initialize the multicast hash */ int retval = init_mcast_hash(); if (retval != 0) rte_exit(EXIT_FAILURE, "Cannot build the multicast hash\n"); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/kni/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif # binary name APP = kni # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/kni/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 /* Max size of a single packet */ #define MAX_PACKET_SZ 2048 /* Size of the data buffer in each mbuf */ #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) /* Number of mbufs in mempool that is created */ #define NB_MBUF (8192 * 16) /* How many packets to attempt to read from NIC in one go */ #define PKT_BURST_SZ 32 /* How many objects (mbufs) to keep in per-lcore mempool cache */ #define MEMPOOL_CACHE_SZ PKT_BURST_SZ /* Number of RX ring descriptors */ #define NB_RXD 128 /* Number of TX ring descriptors */ #define NB_TXD 512 /* Total octets in ethernet header */ #define KNI_ENET_HEADER_SIZE 14 /* Total octets in the FCS */ #define KNI_ENET_FCS_SIZE 4 #define KNI_US_PER_SECOND 1000000 #define KNI_SECOND_PER_DAY 86400 #define KNI_MAX_KTHREAD 32 /* * Structure of port parameters */ struct kni_port_params { uint8_t port_id;/* Port ID */ unsigned lcore_rx; /* lcore ID for RX */ unsigned lcore_tx; /* lcore ID for TX */ uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */ uint32_t nb_kni; /* Number of KNI devices to be created */ unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */ struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */ } __rte_cache_aligned; static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS]; /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { .rxmode = { .header_split = 0, /* Header Split disabled */ .hw_ip_checksum = 0, /* IP checksum offload disabled */ .hw_vlan_filter = 0, /* VLAN filtering disabled */ .jumbo_frame = 0, /* Jumbo Frame Support disabled */ .hw_strip_crc = 0, /* CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; /* Mempool for mbufs */ static struct rte_mempool * pktmbuf_pool = NULL; /* Mask of enabled ports */ static uint32_t ports_mask = 0; /* Ports set in promiscuous mode off by default. */ static int promiscuous_on = 0; /* Structure type for recording kni interface specific stats */ struct kni_interface_stats { /* number of pkts received from NIC, and sent to KNI */ uint64_t rx_packets; /* number of pkts received from NIC, but failed to send to KNI */ uint64_t rx_dropped; /* number of pkts received from KNI, and sent to NIC */ uint64_t tx_packets; /* number of pkts received from KNI, but failed to send to NIC */ uint64_t tx_dropped; }; /* kni device statistics array */ static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS]; static int kni_change_mtu(uint8_t port_id, unsigned new_mtu); static int kni_config_network_interface(uint8_t port_id, uint8_t if_up); static rte_atomic32_t kni_stop = RTE_ATOMIC32_INIT(0); /* Print out statistics on packets handled */ static void print_stats(void) { uint8_t i; printf("\n**KNI example application statistics**\n" "====== ============== ============ ============ ============ ============\n" " Port Lcore(RX/TX) rx_packets rx_dropped tx_packets tx_dropped\n" "------ -------------- ------------ ------------ ------------ ------------\n"); for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (!kni_port_params_array[i]) continue; printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" " "%13"PRIu64"\n", i, kni_port_params_array[i]->lcore_rx, kni_port_params_array[i]->lcore_tx, kni_stats[i].rx_packets, kni_stats[i].rx_dropped, kni_stats[i].tx_packets, kni_stats[i].tx_dropped); } printf("====== ============== ============ ============ ============ ============\n"); } /* Custom handling of signals to handle stats and kni processing */ static void signal_handler(int signum) { /* When we receive a USR1 signal, print stats */ if (signum == SIGUSR1) { print_stats(); } /* When we receive a USR2 signal, reset stats */ if (signum == SIGUSR2) { memset(&kni_stats, 0, sizeof(kni_stats)); printf("\n**Statistics have been reset**\n"); return; } /* When we receive a RTMIN or SIGINT signal, stop kni processing */ if (signum == SIGRTMIN || signum == SIGINT){ printf("SIGRTMIN is received, and the KNI processing is " "going to stop\n"); rte_atomic32_inc(&kni_stop); return; } } static void kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num) { unsigned i; if (pkts == NULL) return; for (i = 0; i < num; i++) { rte_pktmbuf_free(pkts[i]); pkts[i] = NULL; } } /** * Interface to burst rx and enqueue mbufs into rx_q */ static void kni_ingress(struct kni_port_params *p) { uint8_t i, port_id; unsigned nb_rx, num; uint32_t nb_kni; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; if (p == NULL) return; nb_kni = p->nb_kni; port_id = p->port_id; for (i = 0; i < nb_kni; i++) { /* Burst rx from eth */ nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ); if (unlikely(nb_rx > PKT_BURST_SZ)) { RTE_LOG(ERR, APP, "Error receiving from eth\n"); return; } /* Burst tx to kni */ num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx); kni_stats[port_id].rx_packets += num; rte_kni_handle_request(p->kni[i]); if (unlikely(num < nb_rx)) { /* Free mbufs not tx to kni interface */ kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num); kni_stats[port_id].rx_dropped += nb_rx - num; } } } /** * Interface to dequeue mbufs from tx_q and burst tx */ static void kni_egress(struct kni_port_params *p) { uint8_t i, port_id; unsigned nb_tx, num; uint32_t nb_kni; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; if (p == NULL) return; nb_kni = p->nb_kni; port_id = p->port_id; for (i = 0; i < nb_kni; i++) { /* Burst rx from kni */ num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ); if (unlikely(num > PKT_BURST_SZ)) { RTE_LOG(ERR, APP, "Error receiving from KNI\n"); return; } /* Burst tx to eth */ nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num); kni_stats[port_id].tx_packets += nb_tx; if (unlikely(nb_tx < num)) { /* Free mbufs not tx to NIC */ kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx); kni_stats[port_id].tx_dropped += num - nb_tx; } } } static int main_loop(__rte_unused void *arg) { uint8_t i, nb_ports = rte_eth_dev_count(); int32_t f_stop; const unsigned lcore_id = rte_lcore_id(); enum lcore_rxtx { LCORE_NONE, LCORE_RX, LCORE_TX, LCORE_MAX }; enum lcore_rxtx flag = LCORE_NONE; nb_ports = (uint8_t)(nb_ports < RTE_MAX_ETHPORTS ? nb_ports : RTE_MAX_ETHPORTS); for (i = 0; i < nb_ports; i++) { if (!kni_port_params_array[i]) continue; if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) { flag = LCORE_RX; break; } else if (kni_port_params_array[i]->lcore_tx == (uint8_t)lcore_id) { flag = LCORE_TX; break; } } if (flag == LCORE_RX) { RTE_LOG(INFO, APP, "Lcore %u is reading from port %d\n", kni_port_params_array[i]->lcore_rx, kni_port_params_array[i]->port_id); while (1) { f_stop = rte_atomic32_read(&kni_stop); if (f_stop) break; kni_ingress(kni_port_params_array[i]); } } else if (flag == LCORE_TX) { RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n", kni_port_params_array[i]->lcore_tx, kni_port_params_array[i]->port_id); while (1) { f_stop = rte_atomic32_read(&kni_stop); if (f_stop) break; kni_egress(kni_port_params_array[i]); } } else RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id); return 0; } /* Display usage instructions */ static void print_usage(const char *prgname) { RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P " "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)" "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n" " -p PORTMASK: hex bitmask of ports to use\n" " -P : enable promiscuous mode\n" " --config (port,lcore_rx,lcore_tx,lcore_kthread...): " "port and lcore configurations\n", prgname); } /* Convert string to unsigned number. 0 is returned if error occurs */ static uint32_t parse_unsigned(const char *portmask) { char *end = NULL; unsigned long num; num = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; return (uint32_t)num; } static void print_config(void) { uint32_t i, j; struct kni_port_params **p = kni_port_params_array; for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (!p[i]) continue; RTE_LOG(DEBUG, APP, "Port ID: %d\n", p[i]->port_id); RTE_LOG(DEBUG, APP, "Rx lcore ID: %u, Tx lcore ID: %u\n", p[i]->lcore_rx, p[i]->lcore_tx); for (j = 0; j < p[i]->nb_lcore_k; j++) RTE_LOG(DEBUG, APP, "Kernel thread lcore ID: %u\n", p[i]->lcore_k[j]); } } static int parse_config(const char *arg) { const char *p, *p0 = arg; char s[256], *end; unsigned size; enum fieldnames { FLD_PORT = 0, FLD_LCORE_RX, FLD_LCORE_TX, _NUM_FLD = KNI_MAX_KTHREAD + 3, }; int i, j, nb_token; char *str_fld[_NUM_FLD]; unsigned long int_fld[_NUM_FLD]; uint8_t port_id, nb_kni_port_params = 0; memset(&kni_port_params_array, 0, sizeof(kni_port_params_array)); while (((p = strchr(p0, '(')) != NULL) && nb_kni_port_params < RTE_MAX_ETHPORTS) { p++; if ((p0 = strchr(p, ')')) == NULL) goto fail; size = p0 - p; if (size >= sizeof(s)) { printf("Invalid config parameters\n"); goto fail; } snprintf(s, sizeof(s), "%.*s", size, p); nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ','); if (nb_token <= FLD_LCORE_TX) { printf("Invalid config parameters\n"); goto fail; } for (i = 0; i < nb_token; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i]) { printf("Invalid config parameters\n"); goto fail; } } i = 0; port_id = (uint8_t)int_fld[i++]; if (port_id >= RTE_MAX_ETHPORTS) { printf("Port ID %d could not exceed the maximum %d\n", port_id, RTE_MAX_ETHPORTS); goto fail; } if (kni_port_params_array[port_id]) { printf("Port %d has been configured\n", port_id); goto fail; } kni_port_params_array[port_id] = rte_zmalloc("KNI_port_params", sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE); kni_port_params_array[port_id]->port_id = port_id; kni_port_params_array[port_id]->lcore_rx = (uint8_t)int_fld[i++]; kni_port_params_array[port_id]->lcore_tx = (uint8_t)int_fld[i++]; if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE || kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) { printf("lcore_rx %u or lcore_tx %u ID could not " "exceed the maximum %u\n", kni_port_params_array[port_id]->lcore_rx, kni_port_params_array[port_id]->lcore_tx, (unsigned)RTE_MAX_LCORE); goto fail; } for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++) kni_port_params_array[port_id]->lcore_k[j] = (uint8_t)int_fld[i]; kni_port_params_array[port_id]->nb_lcore_k = j; } print_config(); return 0; fail: for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (kni_port_params_array[i]) { rte_free(kni_port_params_array[i]); kni_port_params_array[i] = NULL; } } return -1; } static int validate_parameters(uint32_t portmask) { uint32_t i; if (!portmask) { printf("No port configured in port mask\n"); return -1; } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (((portmask & (1 << i)) && !kni_port_params_array[i]) || (!(portmask & (1 << i)) && kni_port_params_array[i])) rte_exit(EXIT_FAILURE, "portmask is not consistent " "to port ids specified in --config\n"); if (kni_port_params_array[i] && !rte_lcore_is_enabled(\ (unsigned)(kni_port_params_array[i]->lcore_rx))) rte_exit(EXIT_FAILURE, "lcore id %u for " "port %d receiving not enabled\n", kni_port_params_array[i]->lcore_rx, kni_port_params_array[i]->port_id); if (kni_port_params_array[i] && !rte_lcore_is_enabled(\ (unsigned)(kni_port_params_array[i]->lcore_tx))) rte_exit(EXIT_FAILURE, "lcore id %u for " "port %d transmitting not enabled\n", kni_port_params_array[i]->lcore_tx, kni_port_params_array[i]->port_id); } return 0; } #define CMDLINE_OPT_CONFIG "config" /* Parse the arguments given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, longindex, ret = 0; const char *prgname = argv[0]; static struct option longopts[] = { {CMDLINE_OPT_CONFIG, required_argument, NULL, 0}, {NULL, 0, NULL, 0} }; /* Disable printing messages within getopt() */ opterr = 0; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:P", longopts, &longindex)) != EOF) { switch (opt) { case 'p': ports_mask = parse_unsigned(optarg); break; case 'P': promiscuous_on = 1; break; case 0: if (!strncmp(longopts[longindex].name, CMDLINE_OPT_CONFIG, sizeof(CMDLINE_OPT_CONFIG))) { ret = parse_config(optarg); if (ret) { printf("Invalid config\n"); print_usage(prgname); return -1; } } break; default: print_usage(prgname); rte_exit(EXIT_FAILURE, "Invalid option specified\n"); } } /* Check that options were parsed ok */ if (validate_parameters(ports_mask) < 0) { print_usage(prgname); rte_exit(EXIT_FAILURE, "Invalid parameters\n"); } return ret; } /* Initialize KNI subsystem */ static void init_kni(void) { unsigned int num_of_kni_ports = 0, i; struct kni_port_params **params = kni_port_params_array; /* Calculate the maximum number of KNI interfaces that will be used */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (kni_port_params_array[i]) { num_of_kni_ports += (params[i]->nb_lcore_k ? params[i]->nb_lcore_k : 1); } } /* Invoke rte KNI init to preallocate the ports */ rte_kni_init(num_of_kni_ports); } /* Initialise a single port on an Ethernet device */ static void init_port(uint8_t port) { int ret; /* Initialise device and RX/TX queues */ RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port); fflush(stdout); ret = rte_eth_dev_configure(port, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n", (unsigned)port, ret); ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, rte_eth_dev_socket_id(port), NULL, pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not setup up RX queue for " "port%u (%d)\n", (unsigned)port, ret); ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, rte_eth_dev_socket_id(port), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not setup up TX queue for " "port%u (%d)\n", (unsigned)port, ret); ret = rte_eth_dev_start(port); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not start port%u (%d)\n", (unsigned)port, ret); if (promiscuous_on) rte_eth_promiscuous_enable(port); } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status\n"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } /* Callback for request of changing MTU */ static int kni_change_mtu(uint8_t port_id, unsigned new_mtu) { int ret; struct rte_eth_conf conf; if (port_id >= rte_eth_dev_count()) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu); /* Stop specific port */ rte_eth_dev_stop(port_id); memcpy(&conf, &port_conf, sizeof(conf)); /* Set new MTU */ if (new_mtu > ETHER_MAX_LEN) conf.rxmode.jumbo_frame = 1; else conf.rxmode.jumbo_frame = 0; /* mtu + length of header + length of FCS = max pkt length */ conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE + KNI_ENET_FCS_SIZE; ret = rte_eth_dev_configure(port_id, 1, 1, &conf); if (ret < 0) { RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id); return ret; } /* Restart specific port */ ret = rte_eth_dev_start(port_id); if (ret < 0) { RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id); return ret; } return 0; } /* Callback for request of configuring network interface up/down */ static int kni_config_network_interface(uint8_t port_id, uint8_t if_up) { int ret = 0; if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } RTE_LOG(INFO, APP, "Configure network interface of %d %s\n", port_id, if_up ? "up" : "down"); if (if_up != 0) { /* Configure network interface up */ rte_eth_dev_stop(port_id); ret = rte_eth_dev_start(port_id); } else /* Configure network interface down */ rte_eth_dev_stop(port_id); if (ret < 0) RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id); return ret; } static int kni_alloc(uint8_t port_id) { uint8_t i; struct rte_kni *kni; struct rte_kni_conf conf; struct kni_port_params **params = kni_port_params_array; if (port_id >= RTE_MAX_ETHPORTS || !params[port_id]) return -1; params[port_id]->nb_kni = params[port_id]->nb_lcore_k ? params[port_id]->nb_lcore_k : 1; for (i = 0; i < params[port_id]->nb_kni; i++) { /* Clear conf at first */ memset(&conf, 0, sizeof(conf)); if (params[port_id]->nb_lcore_k) { snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u_%u", port_id, i); conf.core_id = params[port_id]->lcore_k[i]; conf.force_bind = 1; } else snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", port_id); conf.group_id = (uint16_t)port_id; conf.mbuf_size = MAX_PACKET_SZ; /* * The first KNI device associated to a port * is the master, for multiple kernel thread * environment. */ if (i == 0) { struct rte_kni_ops ops; struct rte_eth_dev_info dev_info; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); conf.addr = dev_info.pci_dev->addr; conf.id = dev_info.pci_dev->id; memset(&ops, 0, sizeof(ops)); ops.port_id = port_id; ops.change_mtu = kni_change_mtu; ops.config_network_if = kni_config_network_interface; kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops); } else kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL); if (!kni) rte_exit(EXIT_FAILURE, "Fail to create kni for " "port: %d\n", port_id); params[port_id]->kni[i] = kni; } return 0; } static int kni_free_kni(uint8_t port_id) { uint8_t i; struct kni_port_params **p = kni_port_params_array; if (port_id >= RTE_MAX_ETHPORTS || !p[port_id]) return -1; for (i = 0; i < p[port_id]->nb_kni; i++) { rte_kni_release(p[port_id]->kni[i]); p[port_id]->kni[i] = NULL; } rte_eth_dev_stop(port_id); return 0; } /* Initialise ports/queues etc. and start main loop on each core */ int main(int argc, char** argv) { int ret; uint8_t nb_sys_ports, port; unsigned i; /* Associate signal_hanlder function with USR signals */ signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); signal(SIGRTMIN, signal_handler); signal(SIGINT, signal_handler); /* Initialise EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)\n", ret); argc -= ret; argv += ret; /* Parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not parse input parameters\n"); /* Create the mbuf pool */ pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id()); if (pktmbuf_pool == NULL) { rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n"); return -1; } /* Get number of ports found in scan */ nb_sys_ports = rte_eth_dev_count(); if (nb_sys_ports == 0) rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n"); /* Check if the configured port ID is valid */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) if (kni_port_params_array[i] && i >= nb_sys_ports) rte_exit(EXIT_FAILURE, "Configured invalid " "port ID %u\n", i); /* Initialize KNI subsystem */ init_kni(); /* Initialise each port */ for (port = 0; port < nb_sys_ports; port++) { /* Skip ports that are not enabled */ if (!(ports_mask & (1 << port))) continue; init_port(port); if (port >= RTE_MAX_ETHPORTS) rte_exit(EXIT_FAILURE, "Can not use more than " "%d ports for kni\n", RTE_MAX_ETHPORTS); kni_alloc(port); } check_all_ports_link_status(nb_sys_ports, ports_mask); /* Launch per-lcore function on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(i) { if (rte_eal_wait_lcore(i) < 0) return -1; } /* Release resources */ for (port = 0; port < nb_sys_ports; port++) { if (!(ports_mask & (1 << port))) continue; kni_free_kni(port); } #ifdef RTE_LIBRTE_XEN_DOM0 rte_kni_close(); #endif for (i = 0; i < RTE_MAX_ETHPORTS; i++) if (kni_port_params_array[i]) { rte_free(kni_port_params_array[i]); kni_port_params_array[i] = NULL; } return 0; } ================================================ FILE: examples/l2fwd/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l2fwd # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l2fwd/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 #define NB_MBUF 8192 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t l2fwd_enabled_port_mask = 0; /* list of enabled ports */ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; static unsigned int l2fwd_rx_queue_per_lcore = 1; struct mbuf_table { unsigned len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; struct rte_mempool * l2fwd_pktmbuf_pool = NULL; /* Per-port statistics struct */ struct l2fwd_port_statistics { uint64_t tx; uint64_t rx; uint64_t dropped; } __rte_cache_aligned; struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; /* A tsc-based timer responsible for triggering statistics printout */ #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ #define MAX_TIMER_PERIOD 86400 /* 1 day max */ static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ /* Print out statistics on packets dropped */ static void print_stats(void) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("\nPort statistics ===================================="); for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { /* skip disabled ports */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, port_statistics[portid].tx, port_statistics[portid].rx, port_statistics[portid].dropped); total_packets_dropped += port_statistics[portid].dropped; total_packets_tx += port_statistics[portid].tx; total_packets_rx += port_statistics[portid].rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64, total_packets_tx, total_packets_rx, total_packets_dropped); printf("\n====================================================\n"); } /* Send the burst of packets on an output interface */ static int l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port) { struct rte_mbuf **m_table; unsigned ret; unsigned queueid =0; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n); port_statistics[port].tx += ret; if (unlikely(ret < n)) { port_statistics[port].dropped += (n - ret); do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue packets for TX and prepare them to be sent */ static int l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { l2fwd_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } static void l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port; dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); l2fwd_send_packet(m, (uint8_t) dst_port); } /* main processing loop */ static void l2fwd_main_loop(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *m; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; unsigned i, j, portid, nb_rx; struct lcore_queue_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; timer_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; l2fwd_send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); port_statistics[portid].rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } } } } static int l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) { l2fwd_main_loop(); return 0; } /* display usage */ static void l2fwd_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", prgname); } static int l2fwd_parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static unsigned int l2fwd_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int l2fwd_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int l2fwd_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:T:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); if (l2fwd_enabled_port_mask == 0) { printf("invalid portmask\n"); l2fwd_usage(prgname); return -1; } break; /* nqueue */ case 'q': l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); if (l2fwd_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); l2fwd_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = l2fwd_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; if (timer_period < 0) { printf("invalid timer period\n"); l2fwd_usage(prgname); return -1; } break; /* long options */ case 0: l2fwd_usage(prgname); return -1; default: l2fwd_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; int ret; uint8_t nb_ports; uint8_t nb_ports_available; uint8_t portid, last_port; unsigned lcore_id, rx_lcore_id; unsigned nb_ports_in_mask = 0; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); /* create the mbuf pool */ l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* reset l2fwd_dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { l2fwd_dst_ports[portid] = last_port; l2fwd_dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get(portid, &dev_info); } if (nb_ports_in_mask % 2) { printf("Notice: odd number of ports in portmask.\n"); l2fwd_dst_ports[last_port] = last_port; } rx_lcore_id = 0; qconf = NULL; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->n_rx_port++; printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); } nb_ports_available = nb_ports; /* Initialise each port */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", (unsigned) portid); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... ", (unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, (unsigned) portid); rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, l2fwd_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, (unsigned) portid); printf("done: \n"); rte_eth_promiscuous_enable(portid); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, l2fwd_ports_eth_addr[portid].addr_bytes[0], l2fwd_ports_eth_addr[portid].addr_bytes[1], l2fwd_ports_eth_addr[portid].addr_bytes[2], l2fwd_ports_eth_addr[portid].addr_bytes[3], l2fwd_ports_eth_addr[portid].addr_bytes[4], l2fwd_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ memset(&port_statistics, 0, sizeof(port_statistics)); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l2fwd-ivshmem/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += host guest include $(RTE_SDK)/mk/rte.extsubdir.mk ================================================ FILE: examples/l2fwd-ivshmem/guest/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = guest # all source are stored in SRCS-y SRCS-y := guest.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l2fwd-ivshmem/guest/guest.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/common.h" #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table rx_mbufs[RTE_MAX_ETHPORTS]; struct vm_port_param * port_param[MAX_RX_QUEUE_PER_LCORE]; } __rte_cache_aligned; static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; /* Print out statistics on packets dropped */ static void print_stats(void) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("\nPort statistics ===================================="); for (portid = 0; portid < ctrl->nb_ports; portid++) { /* skip ports that are not enabled */ printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, ctrl->vm_ports[portid].stats.tx, ctrl->vm_ports[portid].stats.rx, ctrl->vm_ports[portid].stats.dropped); total_packets_dropped += ctrl->vm_ports[portid].stats.dropped; total_packets_tx += ctrl->vm_ports[portid].stats.tx; total_packets_rx += ctrl->vm_ports[portid].stats.rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64, total_packets_tx, total_packets_rx, total_packets_dropped); printf("\n====================================================\n"); } /* display usage */ static void l2fwd_ivshmem_usage(const char *prgname) { printf("%s [EAL options] -- [-q NQ -T PERIOD]\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", prgname); } static unsigned int l2fwd_ivshmem_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int l2fwd_ivshmem_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int l2fwd_ivshmem_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "q:p:T:", lgopts, &option_index)) != EOF) { switch (opt) { /* nqueue */ case 'q': l2fwd_ivshmem_rx_queue_per_lcore = l2fwd_ivshmem_parse_nqueue(optarg); if (l2fwd_ivshmem_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); l2fwd_ivshmem_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = l2fwd_ivshmem_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; if (timer_period < 0) { printf("invalid timer period\n"); l2fwd_ivshmem_usage(prgname); return -1; } break; /* long options */ case 0: l2fwd_ivshmem_usage(prgname); return -1; default: l2fwd_ivshmem_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /* * this loop is getting packets from RX rings of each port, and puts them * into TX rings of destination ports. */ static void fwd_loop(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf **m_table; struct rte_mbuf *m; struct rte_ring *rx, *tx; unsigned lcore_id, len; uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; unsigned i, j, portid, nb_rx; struct lcore_queue_conf *qconf; struct ether_hdr *eth; void *tmp; prev_tsc = 0; timer_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD_IVSHMEM, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, L2FWD_IVSHMEM, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD_IVSHMEM, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } while (ctrl->state == STATE_FWD) { cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; /* * Read packet from RX queues and send it to TX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; len = qconf->rx_mbufs[portid].len; rx = ctrl->vm_ports[portid].rx_ring; tx = ctrl->vm_ports[portid].dst->tx_ring; m_table = qconf->rx_mbufs[portid].m_table; /* if we have something in the queue, try and transmit it down */ if (len != 0) { /* if we succeed in sending the packets down, mark queue as free */ if (rte_ring_enqueue_bulk(tx, (void**) m_table, len) == 0) { ctrl->vm_ports[portid].stats.tx += len; qconf->rx_mbufs[portid].len = 0; len = 0; } } nb_rx = rte_ring_count(rx); nb_rx = RTE_MIN(nb_rx, (unsigned) MAX_PKT_BURST); if (nb_rx == 0) continue; /* if we can get packets into the m_table */ if (nb_rx < (RTE_DIM(qconf->rx_mbufs[portid].m_table) - len)) { /* this situation cannot exist, so if we fail to dequeue, that * means something went horribly wrong, hence the failure. */ if (rte_ring_dequeue_bulk(rx, (void**) pkts_burst, nb_rx) < 0) { ctrl->state = STATE_FAIL; return; } ctrl->vm_ports[portid].stats.rx += nb_rx; /* put packets into the queue */ for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); m_table[len + j] = m; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)portid << 40); /* src addr */ ether_addr_copy(&ctrl->vm_ports[portid].dst->ethaddr, ð->s_addr); } qconf->rx_mbufs[portid].len += nb_rx; } } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } } static int l2fwd_ivshmem_launch_one_lcore(__attribute__((unused)) void *dummy) { fwd_loop(); return 0; } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; const struct rte_memzone * mz; int ret; uint8_t portid; unsigned rx_lcore_id, lcore_id; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_ivshmem_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid l2fwd-ivshmem arguments\n"); /* find control structure */ mz = rte_memzone_lookup(CTRL_MZ_NAME); if (mz == NULL) rte_exit(EXIT_FAILURE, "Cannot find control memzone\n"); ctrl = (struct ivshmem_ctrl*) mz->addr; /* lock the ctrl so that we don't have conflicts with anything else */ rte_spinlock_lock(&ctrl->lock); if (ctrl->state == STATE_FWD) rte_exit(EXIT_FAILURE, "Forwarding already started!\n"); rx_lcore_id = 0; qconf = NULL; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < ctrl->nb_ports; portid++) { /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_ivshmem_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->port_param[qconf->n_rx_port] = &ctrl->vm_ports[portid]; qconf->n_rx_port++; printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); } sigsetup(); /* indicate that we are ready to forward */ ctrl->state = STATE_FWD; /* unlock */ rte_spinlock_unlock(&ctrl->lock); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l2fwd_ivshmem_launch_one_lcore, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l2fwd-ivshmem/host/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = host # all source are stored in SRCS-y SRCS-y := host.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l2fwd-ivshmem/host/host.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/common.h" /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* mask of enabled ports */ static uint32_t l2fwd_ivshmem_enabled_port_mask = 0; static struct ether_addr l2fwd_ivshmem_ports_eth_addr[RTE_MAX_ETHPORTS]; #define NB_MBUF 8192 #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct vm_port_param * port_param[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; struct mbuf_table rx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; #define METADATA_NAME "l2fwd_ivshmem" #define CMDLINE_OPT_FWD_CONF "fwd-conf" #define QEMU_CMD_FMT "/tmp/ivshmem_qemu_cmdline_%s" struct port_statistics port_statistics[RTE_MAX_ETHPORTS]; struct rte_mempool * l2fwd_ivshmem_pktmbuf_pool = NULL; /* Print out statistics on packets dropped */ static void print_stats(void) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; uint64_t total_vm_packets_dropped, total_vm_packets_tx, total_vm_packets_rx; unsigned portid; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; total_vm_packets_tx = 0; total_vm_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("\nPort statistics ===================================="); for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { /* skip disabled ports */ if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0) continue; printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, port_statistics[portid].tx, port_statistics[portid].rx, port_statistics[portid].dropped); total_packets_dropped += port_statistics[portid].dropped; total_packets_tx += port_statistics[portid].tx; total_packets_rx += port_statistics[portid].rx; } printf("\nVM statistics ======================================"); for (portid = 0; portid < ctrl->nb_ports; portid++) { printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64, portid, ctrl->vm_ports[portid].stats.tx, ctrl->vm_ports[portid].stats.rx); total_vm_packets_dropped += ctrl->vm_ports[portid].stats.dropped; total_vm_packets_tx += ctrl->vm_ports[portid].stats.tx; total_vm_packets_rx += ctrl->vm_ports[portid].stats.rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64 "\nTotal VM packets sent: %15"PRIu64 "\nTotal VM packets received: %11"PRIu64, total_packets_tx, total_packets_rx, total_packets_dropped, total_vm_packets_tx, total_vm_packets_rx); printf("\n====================================================\n"); } static int print_to_file(const char *cmdline, const char *config_name) { FILE *file; char path[PATH_MAX]; snprintf(path, sizeof(path), QEMU_CMD_FMT, config_name); file = fopen(path, "w"); if (file == NULL) { RTE_LOG(ERR, L2FWD_IVSHMEM, "Could not open '%s' \n", path); return -1; } RTE_LOG(DEBUG, L2FWD_IVSHMEM, "QEMU command line for config '%s': %s \n", config_name, cmdline); fprintf(file, "%s\n", cmdline); fclose(file); return 0; } static int generate_ivshmem_cmdline(const char *config_name) { char cmdline[PATH_MAX]; if (rte_ivshmem_metadata_cmdline_generate(cmdline, sizeof(cmdline), config_name) < 0) return -1; if (print_to_file(cmdline, config_name) < 0) return -1; rte_ivshmem_metadata_dump(stdout, config_name); return 0; } /* display usage */ static void l2fwd_ivshmem_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ -T PERIOD]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds " "(0 to disable, 10 default, 86400 maximum)\n", prgname); } static unsigned int l2fwd_ivshmem_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int l2fwd_ivshmem_parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int l2fwd_ivshmem_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int l2fwd_ivshmem_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {CMDLINE_OPT_FWD_CONF, 1, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "q:p:T:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': l2fwd_ivshmem_enabled_port_mask = l2fwd_ivshmem_parse_portmask(optarg); if (l2fwd_ivshmem_enabled_port_mask == 0) { printf("invalid portmask\n"); l2fwd_ivshmem_usage(prgname); return -1; } break; /* nqueue */ case 'q': l2fwd_ivshmem_rx_queue_per_lcore = l2fwd_ivshmem_parse_nqueue(optarg); if (l2fwd_ivshmem_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); l2fwd_ivshmem_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = l2fwd_ivshmem_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; if (timer_period < 0) { printf("invalid timer period\n"); l2fwd_ivshmem_usage(prgname); return -1; } break; /* long options */ case 0: l2fwd_ivshmem_usage(prgname); return -1; default: l2fwd_ivshmem_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } /* Send the burst of packets on an output interface */ static int l2fwd_ivshmem_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port) { struct rte_mbuf **m_table; unsigned ret; unsigned queueid =0; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n); port_statistics[port].tx += ret; if (unlikely(ret < n)) { port_statistics[port].dropped += (n - ret); do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue packets for TX and prepare them to be sent on the network */ static int l2fwd_ivshmem_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { l2fwd_ivshmem_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } static int l2fwd_ivshmem_receive_burst(struct lcore_queue_conf *qconf, unsigned portid, unsigned vm_port) { struct rte_mbuf ** m; struct rte_ring * rx; unsigned len, pkt_idx; m = qconf->rx_mbufs[portid].m_table; len = qconf->rx_mbufs[portid].len; rx = qconf->port_param[vm_port]->rx_ring; /* if enqueueing failed, ring is probably full, so drop the packets */ if (rte_ring_enqueue_bulk(rx, (void**) m, len) < 0) { port_statistics[portid].dropped += len; pkt_idx = 0; do { rte_pktmbuf_free(m[pkt_idx]); } while (++pkt_idx < len); } else /* increment rx stats by however many packets we managed to receive */ port_statistics[portid].rx += len; return 0; } /* Enqueue packets for RX and prepare them to be sent to VM */ static int l2fwd_ivshmem_receive_packets(struct rte_mbuf ** m, unsigned n, unsigned portid, unsigned vm_port) { unsigned lcore_id, len, pkt_idx; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->rx_mbufs[portid].len; pkt_idx = 0; /* enqueue packets */ while (pkt_idx < n && len < MAX_PKT_BURST * 2) { qconf->rx_mbufs[portid].m_table[len++] = m[pkt_idx++]; } /* increment queue len by however many packets we managed to receive */ qconf->rx_mbufs[portid].len += pkt_idx; /* drop the unreceived packets */ if (unlikely(pkt_idx < n)) { port_statistics[portid].dropped += n - pkt_idx; do { rte_pktmbuf_free(m[pkt_idx]); } while (++pkt_idx < n); } /* drain the queue halfway through the maximum capacity */ if (unlikely(qconf->rx_mbufs[portid].len >= MAX_PKT_BURST)) l2fwd_ivshmem_receive_burst(qconf, portid, vm_port); return 0; } /* loop for host forwarding mode. * the data flow is as follows: * 1) get packets from TX queue and send it out from a given port * 2) RX packets from given port and enqueue them on RX ring * 3) dequeue packets from TX ring and put them on TX queue for a given port */ static void fwd_loop(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST * 2]; struct rte_mbuf *m; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; unsigned i, j, portid, nb_rx; struct lcore_queue_conf *qconf; struct rte_ring *tx; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; timer_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD_IVSHMEM, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, L2FWD_IVSHMEM, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD_IVSHMEM, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } while (ctrl->state == STATE_FWD) { cur_tsc = rte_rdtsc(); /* * Burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * TX */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; l2fwd_ivshmem_send_burst(qconf, qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } /* * RX */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; if (qconf->rx_mbufs[portid].len == 0) continue; l2fwd_ivshmem_receive_burst(qconf, portid, i); qconf->rx_mbufs[portid].len = 0; } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } /* * packet RX and forwarding */ for (i = 0; i < qconf->n_rx_port; i++) { /* RX packets from port and put them on RX ring */ portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); if (nb_rx != 0) l2fwd_ivshmem_receive_packets(pkts_burst, nb_rx, portid, i); /* dequeue packets from TX ring and send them to TX queue */ tx = qconf->port_param[i]->tx_ring; nb_rx = rte_ring_count(tx); nb_rx = RTE_MIN(nb_rx, (unsigned) MAX_PKT_BURST); if (nb_rx == 0) continue; /* should not happen */ if (unlikely(rte_ring_dequeue_bulk(tx, (void**) pkts_burst, nb_rx) < 0)) { ctrl->state = STATE_FAIL; return; } for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; l2fwd_ivshmem_send_packet(m, portid); } } } } static int l2fwd_ivshmem_launch_one_lcore(__attribute__((unused)) void *dummy) { fwd_loop(); return 0; } int main(int argc, char **argv) { char name[RTE_RING_NAMESIZE]; struct rte_ring *r; struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; uint8_t portid, port_nr; uint8_t nb_ports, nb_ports_available; uint8_t nb_ports_in_mask; int ret; unsigned lcore_id, rx_lcore_id; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_ivshmem_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid l2fwd-ivshmem arguments\n"); /* create a shared mbuf pool */ l2fwd_ivshmem_pktmbuf_pool = rte_pktmbuf_pool_create(MBUF_MP_NAME, NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (l2fwd_ivshmem_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * reserve memzone to communicate with VMs - we cannot use rte_malloc here * because while it is technically possible, it is a very bad idea to share * the heap between two primary processes. */ ctrl_mz = rte_memzone_reserve(CTRL_MZ_NAME, sizeof(struct ivshmem_ctrl), SOCKET_ID_ANY, 0); if (ctrl_mz == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve control memzone\n"); ctrl = (struct ivshmem_ctrl*) ctrl_mz->addr; memset(ctrl, 0, sizeof(struct ivshmem_ctrl)); /* * Each port is assigned an output port. */ nb_ports_in_mask = 0; for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0) continue; if (portid % 2) { ctrl->vm_ports[nb_ports_in_mask].dst = &ctrl->vm_ports[nb_ports_in_mask-1]; ctrl->vm_ports[nb_ports_in_mask-1].dst = &ctrl->vm_ports[nb_ports_in_mask]; } nb_ports_in_mask++; rte_eth_dev_info_get(portid, &dev_info); } if (nb_ports_in_mask % 2) { printf("Notice: odd number of ports in portmask.\n"); ctrl->vm_ports[nb_ports_in_mask-1].dst = &ctrl->vm_ports[nb_ports_in_mask-1]; } rx_lcore_id = 0; qconf = NULL; printf("Initializing ports configuration...\n"); nb_ports_available = nb_ports; /* Initialise each port */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", (unsigned) portid); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... ", (unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, (unsigned) portid); rte_eth_macaddr_get(portid,&l2fwd_ivshmem_ports_eth_addr[portid]); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, l2fwd_ivshmem_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, (unsigned) portid); printf("done: \n"); rte_eth_promiscuous_enable(portid); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[0], l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[1], l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[2], l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[3], l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[4], l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ memset(&port_statistics, 0, sizeof(port_statistics)); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } port_nr = 0; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < nb_ports; portid++) { if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0) continue; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_ivshmem_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; rte_eth_macaddr_get(portid, &ctrl->vm_ports[port_nr].ethaddr); qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->port_param[qconf->n_rx_port] = &ctrl->vm_ports[port_nr]; qconf->n_rx_port++; port_nr++; printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); } check_all_ports_link_status(nb_ports_available, l2fwd_ivshmem_enabled_port_mask); /* create rings for each VM port (several ports can be on the same VM). * note that we store the pointers in ctrl - that way, they are the same * and valid across all VMs because ctrl is also in DPDK memory */ for (portid = 0; portid < nb_ports_available; portid++) { /* RX ring. SP/SC because it's only used by host and a single VM */ snprintf(name, sizeof(name), "%s%i", RX_RING_PREFIX, portid); r = rte_ring_create(name, NB_MBUF, SOCKET_ID_ANY, RING_F_SP_ENQ | RING_F_SC_DEQ); if (r == NULL) rte_exit(EXIT_FAILURE, "Cannot create ring %s\n", name); ctrl->vm_ports[portid].rx_ring = r; /* TX ring. SP/SC because it's only used by host and a single VM */ snprintf(name, sizeof(name), "%s%i", TX_RING_PREFIX, portid); r = rte_ring_create(name, NB_MBUF, SOCKET_ID_ANY, RING_F_SP_ENQ | RING_F_SC_DEQ); if (r == NULL) rte_exit(EXIT_FAILURE, "Cannot create ring %s\n", name); ctrl->vm_ports[portid].tx_ring = r; } /* create metadata, output cmdline */ if (rte_ivshmem_metadata_create(METADATA_NAME) < 0) rte_exit(EXIT_FAILURE, "Cannot create IVSHMEM metadata\n"); if (rte_ivshmem_metadata_add_memzone(ctrl_mz, METADATA_NAME)) rte_exit(EXIT_FAILURE, "Cannot add memzone to IVSHMEM metadata\n"); if (rte_ivshmem_metadata_add_mempool(l2fwd_ivshmem_pktmbuf_pool, METADATA_NAME)) rte_exit(EXIT_FAILURE, "Cannot add mbuf mempool to IVSHMEM metadata\n"); for (portid = 0; portid < nb_ports_available; portid++) { if (rte_ivshmem_metadata_add_ring(ctrl->vm_ports[portid].rx_ring, METADATA_NAME) < 0) rte_exit(EXIT_FAILURE, "Cannot add ring %s to IVSHMEM metadata\n", ctrl->vm_ports[portid].rx_ring->name); if (rte_ivshmem_metadata_add_ring(ctrl->vm_ports[portid].tx_ring, METADATA_NAME) < 0) rte_exit(EXIT_FAILURE, "Cannot add ring %s to IVSHMEM metadata\n", ctrl->vm_ports[portid].tx_ring->name); } generate_ivshmem_cmdline(METADATA_NAME); ctrl->nb_ports = nb_ports_available; printf("Waiting for VM to initialize...\n"); /* wait for VM to initialize */ while (ctrl->state != STATE_FWD) { if (ctrl->state == STATE_FAIL) rte_exit(EXIT_FAILURE, "VM reported failure\n"); sleep(1); } printf("Done!\n"); sigsetup(); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l2fwd_ivshmem_launch_one_lcore, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } if (ctrl->state == STATE_FAIL) rte_exit(EXIT_FAILURE, "VM reported failure\n"); return 0; } ================================================ FILE: examples/l2fwd-ivshmem/include/common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IVSHMEM_COMMON_H_ #define _IVSHMEM_COMMON_H_ #define RTE_LOGTYPE_L2FWD_IVSHMEM RTE_LOGTYPE_USER1 #define CTRL_MZ_NAME "CTRL_MEMZONE" #define MBUF_MP_NAME "MBUF_MEMPOOL" #define RX_RING_PREFIX "RX_" #define TX_RING_PREFIX "TX_" /* A tsc-based timer responsible for triggering statistics printout */ #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ #define MAX_TIMER_PERIOD 86400 /* 1 day max */ static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ #define DIM(x)\ (sizeof(x)/sizeof(x)[0]) #define MAX_PKT_BURST 32 const struct rte_memzone * ctrl_mz; enum l2fwd_state { STATE_NONE = 0, STATE_FWD, STATE_EXIT, STATE_FAIL }; /* Per-port statistics struct */ struct port_statistics { uint64_t tx; uint64_t rx; uint64_t dropped; } __rte_cache_aligned; struct mbuf_table { unsigned len; struct rte_mbuf *m_table[MAX_PKT_BURST * 2]; /**< allow up to two bursts */ }; struct vm_port_param { struct rte_ring * rx_ring; /**< receiving ring for current port */ struct rte_ring * tx_ring; /**< transmitting ring for current port */ struct vm_port_param * dst; /**< current port's destination port */ volatile struct port_statistics stats; /**< statistics for current port */ struct ether_addr ethaddr; /**< Ethernet address of the port */ }; /* control structure, to synchronize host and VM */ struct ivshmem_ctrl { rte_spinlock_t lock; uint8_t nb_ports; /**< total nr of ports */ volatile enum l2fwd_state state; /**< report state */ struct vm_port_param vm_ports[RTE_MAX_ETHPORTS]; }; struct ivshmem_ctrl * ctrl; static unsigned int l2fwd_ivshmem_rx_queue_per_lcore = 1; static void sighandler(int __rte_unused s) { ctrl->state = STATE_EXIT; } static void sigsetup(void) { struct sigaction sigIntHandler; sigIntHandler.sa_handler = sighandler; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); } #endif /* _IVSHMEM_COMMON_H_ */ ================================================ FILE: examples/l2fwd-jobstats/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l2fwd-jobstats # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l2fwd-jobstats/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 #define NB_MBUF 8192 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t l2fwd_enabled_port_mask; /* list of enabled ports */ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; #define UPDATE_STEP_UP 1 #define UPDATE_STEP_DOWN 32 static unsigned int l2fwd_rx_queue_per_lcore = 1; struct mbuf_table { uint64_t next_flush_time; unsigned len; struct rte_mbuf *mbufs[MAX_PKT_BURST]; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; struct rte_timer rx_timers[MAX_RX_QUEUE_PER_LCORE]; struct rte_jobstats port_fwd_jobs[MAX_RX_QUEUE_PER_LCORE]; struct rte_timer flush_timer; struct rte_jobstats flush_job; struct rte_jobstats idle_job; struct rte_jobstats_context jobs_context; rte_atomic16_t stats_read_pending; rte_spinlock_t lock; } __rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; struct rte_mempool *l2fwd_pktmbuf_pool = NULL; /* Per-port statistics struct */ struct l2fwd_port_statistics { uint64_t tx; uint64_t rx; uint64_t dropped; } __rte_cache_aligned; struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; /* 1 day max */ #define MAX_TIMER_PERIOD 86400 /* default period is 10 seconds */ static int64_t timer_period = 10; /* default timer frequency */ static double hz; /* BURST_TX_DRAIN_US converted to cycles */ uint64_t drain_tsc; /* Convert cycles to ns */ static inline double cycles_to_ns(uint64_t cycles) { double t = cycles; t *= (double)NS_PER_S; t /= hz; return t; } static void show_lcore_stats(unsigned lcore_id) { struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; struct rte_jobstats_context *ctx = &qconf->jobs_context; struct rte_jobstats *job; uint8_t i; /* LCore statistics. */ uint64_t stats_period, loop_count; uint64_t exec, exec_min, exec_max; uint64_t management, management_min, management_max; uint64_t busy, busy_min, busy_max; /* Jobs statistics. */ const uint8_t port_cnt = qconf->n_rx_port; uint64_t jobs_exec_cnt[port_cnt], jobs_period[port_cnt]; uint64_t jobs_exec[port_cnt], jobs_exec_min[port_cnt], jobs_exec_max[port_cnt]; uint64_t flush_exec_cnt, flush_period; uint64_t flush_exec, flush_exec_min, flush_exec_max; uint64_t idle_exec_cnt; uint64_t idle_exec, idle_exec_min, idle_exec_max; uint64_t collection_time = rte_get_timer_cycles(); /* Ask forwarding thread to give us stats. */ rte_atomic16_set(&qconf->stats_read_pending, 1); rte_spinlock_lock(&qconf->lock); rte_atomic16_set(&qconf->stats_read_pending, 0); /* Collect context statistics. */ stats_period = ctx->state_time - ctx->start_time; loop_count = ctx->loop_cnt; exec = ctx->exec_time; exec_min = ctx->min_exec_time; exec_max = ctx->max_exec_time; management = ctx->management_time; management_min = ctx->min_management_time; management_max = ctx->max_management_time; rte_jobstats_context_reset(ctx); for (i = 0; i < port_cnt; i++) { job = &qconf->port_fwd_jobs[i]; jobs_exec_cnt[i] = job->exec_cnt; jobs_period[i] = job->period; jobs_exec[i] = job->exec_time; jobs_exec_min[i] = job->min_exec_time; jobs_exec_max[i] = job->max_exec_time; rte_jobstats_reset(job); } flush_exec_cnt = qconf->flush_job.exec_cnt; flush_period = qconf->flush_job.period; flush_exec = qconf->flush_job.exec_time; flush_exec_min = qconf->flush_job.min_exec_time; flush_exec_max = qconf->flush_job.max_exec_time; rte_jobstats_reset(&qconf->flush_job); idle_exec_cnt = qconf->idle_job.exec_cnt; idle_exec = qconf->idle_job.exec_time; idle_exec_min = qconf->idle_job.min_exec_time; idle_exec_max = qconf->idle_job.max_exec_time; rte_jobstats_reset(&qconf->idle_job); rte_spinlock_unlock(&qconf->lock); exec -= idle_exec; busy = exec + management; busy_min = exec_min + management_min; busy_max = exec_max + management_max; collection_time = rte_get_timer_cycles() - collection_time; #define STAT_FMT "\n%-18s %'14.0f %6.1f%% %'10.0f %'10.0f %'10.0f" printf("\n----------------" "\nLCore %3u: statistics (time in ns, collected in %'9.0f)" "\n%-18s %14s %7s %10s %10s %10s " "\n%-18s %'14.0f" "\n%-18s %'14" PRIu64 STAT_FMT /* Exec */ STAT_FMT /* Management */ STAT_FMT /* Busy */ STAT_FMT, /* Idle */ lcore_id, cycles_to_ns(collection_time), "Stat type", "total", "%total", "avg", "min", "max", "Stats duration:", cycles_to_ns(stats_period), "Loop count:", loop_count, "Exec time", cycles_to_ns(exec), exec * 100.0 / stats_period, cycles_to_ns(loop_count ? exec / loop_count : 0), cycles_to_ns(exec_min), cycles_to_ns(exec_max), "Management time", cycles_to_ns(management), management * 100.0 / stats_period, cycles_to_ns(loop_count ? management / loop_count : 0), cycles_to_ns(management_min), cycles_to_ns(management_max), "Exec + management", cycles_to_ns(busy), busy * 100.0 / stats_period, cycles_to_ns(loop_count ? busy / loop_count : 0), cycles_to_ns(busy_min), cycles_to_ns(busy_max), "Idle (job)", cycles_to_ns(idle_exec), idle_exec * 100.0 / stats_period, cycles_to_ns(idle_exec_cnt ? idle_exec / idle_exec_cnt : 0), cycles_to_ns(idle_exec_min), cycles_to_ns(idle_exec_max)); for (i = 0; i < qconf->n_rx_port; i++) { job = &qconf->port_fwd_jobs[i]; printf("\n\nJob %" PRIu32 ": %-20s " "\n%-18s %'14" PRIu64 "\n%-18s %'14.0f" STAT_FMT, i, job->name, "Exec count:", jobs_exec_cnt[i], "Exec period: ", cycles_to_ns(jobs_period[i]), "Exec time", cycles_to_ns(jobs_exec[i]), jobs_exec[i] * 100.0 / stats_period, cycles_to_ns(jobs_exec_cnt[i] ? jobs_exec[i] / jobs_exec_cnt[i] : 0), cycles_to_ns(jobs_exec_min[i]), cycles_to_ns(jobs_exec_max[i])); } if (qconf->n_rx_port > 0) { job = &qconf->flush_job; printf("\n\nJob %" PRIu32 ": %-20s " "\n%-18s %'14" PRIu64 "\n%-18s %'14.0f" STAT_FMT, i, job->name, "Exec count:", flush_exec_cnt, "Exec period: ", cycles_to_ns(flush_period), "Exec time", cycles_to_ns(flush_exec), flush_exec * 100.0 / stats_period, cycles_to_ns(flush_exec_cnt ? flush_exec / flush_exec_cnt : 0), cycles_to_ns(flush_exec_min), cycles_to_ns(flush_exec_max)); } } /* Print out statistics on packets dropped */ static void show_stats_cb(__rte_unused void *param) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid, lcore_id; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; /* Clear screen and move to top left */ printf("%s%s" "\nPort statistics ===================================", clr, topLeft); for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { /* skip disabled ports */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, port_statistics[portid].tx, port_statistics[portid].rx, port_statistics[portid].dropped); total_packets_dropped += port_statistics[portid].dropped; total_packets_tx += port_statistics[portid].tx; total_packets_rx += port_statistics[portid].rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64 "\n====================================================", total_packets_tx, total_packets_rx, total_packets_dropped); RTE_LCORE_FOREACH(lcore_id) { if (lcore_queue_conf[lcore_id].n_rx_port > 0) show_lcore_stats(lcore_id); } printf("\n====================================================\n"); rte_eal_alarm_set(timer_period * US_PER_S, show_stats_cb, NULL); } /* Send the burst of packets on an output interface */ static void l2fwd_send_burst(struct lcore_queue_conf *qconf, uint8_t port) { struct mbuf_table *m_table; uint16_t ret; uint16_t queueid = 0; uint16_t n; m_table = &qconf->tx_mbufs[port]; n = m_table->len; m_table->next_flush_time = rte_get_timer_cycles() + drain_tsc; m_table->len = 0; ret = rte_eth_tx_burst(port, queueid, m_table->mbufs, n); port_statistics[port].tx += ret; if (unlikely(ret < n)) { port_statistics[port].dropped += (n - ret); do { rte_pktmbuf_free(m_table->mbufs[ret]); } while (++ret < n); } } /* Enqueue packets for TX and prepare them to be sent */ static int l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) { const unsigned lcore_id = rte_lcore_id(); struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; struct mbuf_table *m_table = &qconf->tx_mbufs[port]; uint16_t len = qconf->tx_mbufs[port].len; m_table->mbufs[len] = m; len++; m_table->len = len; /* Enough pkts to be sent. */ if (unlikely(len == MAX_PKT_BURST)) l2fwd_send_burst(qconf, port); return 0; } static void l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port; dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); l2fwd_send_packet(m, (uint8_t) dst_port); } static void l2fwd_job_update_cb(struct rte_jobstats *job, int64_t result) { int64_t err = job->target - result; int64_t histeresis = job->target / 8; if (err < -histeresis) { if (job->min_period + UPDATE_STEP_DOWN < job->period) job->period -= UPDATE_STEP_DOWN; } else if (err > histeresis) { if (job->period + UPDATE_STEP_UP < job->max_period) job->period += UPDATE_STEP_UP; } } static void l2fwd_fwd_job(__rte_unused struct rte_timer *timer, void *arg) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *m; const uint8_t port_idx = (uintptr_t) arg; const unsigned lcore_id = rte_lcore_id(); struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; struct rte_jobstats *job = &qconf->port_fwd_jobs[port_idx]; const uint8_t portid = qconf->rx_port_list[port_idx]; uint8_t j; uint16_t total_nb_rx; rte_jobstats_start(&qconf->jobs_context, job); /* Call rx burst 2 times. This allow rte_jobstats logic to see if this * function must be called more frequently. */ total_nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); for (j = 0; j < total_nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } if (total_nb_rx == MAX_PKT_BURST) { const uint16_t nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); total_nb_rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } } port_statistics[portid].rx += total_nb_rx; /* Adjust period time in which we are running here. */ if (rte_jobstats_finish(job, total_nb_rx) != 0) { rte_timer_reset(&qconf->rx_timers[port_idx], job->period, PERIODICAL, lcore_id, l2fwd_fwd_job, arg); } } static void l2fwd_flush_job(__rte_unused struct rte_timer *timer, __rte_unused void *arg) { uint64_t now; unsigned lcore_id; struct lcore_queue_conf *qconf; struct mbuf_table *m_table; uint8_t portid; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; rte_jobstats_start(&qconf->jobs_context, &qconf->flush_job); now = rte_get_timer_cycles(); lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { m_table = &qconf->tx_mbufs[portid]; if (m_table->len == 0 || m_table->next_flush_time <= now) continue; l2fwd_send_burst(qconf, portid); } /* Pass target to indicate that this job is happy of time interwal * in which it was called. */ rte_jobstats_finish(&qconf->flush_job, qconf->flush_job.target); } /* main processing loop */ static void l2fwd_main_loop(void) { unsigned lcore_id; unsigned i, portid; struct lcore_queue_conf *qconf; uint8_t stats_read_pending = 0; uint8_t need_manage; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } rte_jobstats_init(&qconf->idle_job, "idle", 0, 0, 0, 0); for (;;) { rte_spinlock_lock(&qconf->lock); do { rte_jobstats_context_start(&qconf->jobs_context); /* Do the Idle job: * - Read stats_read_pending flag * - check if some real job need to be executed */ rte_jobstats_start(&qconf->jobs_context, &qconf->idle_job); do { uint8_t i; uint64_t now = rte_get_timer_cycles(); need_manage = qconf->flush_timer.expire < now; /* Check if we was esked to give a stats. */ stats_read_pending = rte_atomic16_read(&qconf->stats_read_pending); need_manage |= stats_read_pending; for (i = 0; i < qconf->n_rx_port && !need_manage; i++) need_manage = qconf->rx_timers[i].expire < now; } while (!need_manage); rte_jobstats_finish(&qconf->idle_job, qconf->idle_job.target); rte_timer_manage(); rte_jobstats_context_finish(&qconf->jobs_context); } while (likely(stats_read_pending == 0)); rte_spinlock_unlock(&qconf->lock); rte_pause(); } } static int l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) { l2fwd_main_loop(); return 0; } /* display usage */ static void l2fwd_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" " -l set system default locale instead of default (\"C\" locale) for thousands separator in stats.", prgname); } static int l2fwd_parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static unsigned int l2fwd_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int l2fwd_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int l2fwd_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:T:l", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); if (l2fwd_enabled_port_mask == 0) { printf("invalid portmask\n"); l2fwd_usage(prgname); return -1; } break; /* nqueue */ case 'q': l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); if (l2fwd_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); l2fwd_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = l2fwd_parse_timer_period(optarg); if (timer_period < 0) { printf("invalid timer period\n"); l2fwd_usage(prgname); return -1; } break; /* For thousands separator in printf. */ case 'l': setlocale(LC_ALL, ""); break; /* long options */ case 0: l2fwd_usage(prgname); return -1; default: l2fwd_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; unsigned lcore_id, rx_lcore_id; unsigned nb_ports_in_mask = 0; int ret; char name[RTE_JOBSTATS_NAMESIZE]; uint8_t nb_ports; uint8_t nb_ports_available; uint8_t portid, last_port; uint8_t i; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); rte_timer_subsystem_init(); /* fetch default timer frequency. */ hz = rte_get_timer_hz(); /* create the mbuf pool */ l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* reset l2fwd_dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { l2fwd_dst_ports[portid] = last_port; l2fwd_dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get(portid, &dev_info); } if (nb_ports_in_mask % 2) { printf("Notice: odd number of ports in portmask.\n"); l2fwd_dst_ports[last_port] = last_port; } rx_lcore_id = 0; qconf = NULL; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->n_rx_port++; printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); } nb_ports_available = nb_ports; /* Initialise each port */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", (unsigned) portid); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... ", (unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, (unsigned) portid); rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, l2fwd_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, (unsigned) portid); printf("done:\n"); rte_eth_promiscuous_enable(portid); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, l2fwd_ports_eth_addr[portid].addr_bytes[0], l2fwd_ports_eth_addr[portid].addr_bytes[1], l2fwd_ports_eth_addr[portid].addr_bytes[2], l2fwd_ports_eth_addr[portid].addr_bytes[3], l2fwd_ports_eth_addr[portid].addr_bytes[4], l2fwd_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ memset(&port_statistics, 0, sizeof(port_statistics)); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); drain_tsc = (hz + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; RTE_LCORE_FOREACH(lcore_id) { qconf = &lcore_queue_conf[lcore_id]; rte_spinlock_init(&qconf->lock); if (rte_jobstats_context_init(&qconf->jobs_context) != 0) rte_panic("Jobs stats context for core %u init failed\n", lcore_id); if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD, "lcore %u: no ports so no jobs stats context initialization\n", lcore_id); continue; } /* Add flush job. * Set fixed period by setting min = max = initial period. Set target to * zero as it is irrelevant for this job. */ rte_jobstats_init(&qconf->flush_job, "flush", drain_tsc, drain_tsc, drain_tsc, 0); rte_timer_init(&qconf->flush_timer); ret = rte_timer_reset(&qconf->flush_timer, drain_tsc, PERIODICAL, lcore_id, &l2fwd_flush_job, NULL); if (ret < 0) { rte_exit(1, "Failed to reset flush job timer for lcore %u: %s", lcore_id, rte_strerror(-ret)); } for (i = 0; i < qconf->n_rx_port; i++) { struct rte_jobstats *job = &qconf->port_fwd_jobs[i]; portid = qconf->rx_port_list[i]; printf("Setting forward jon for port %u\n", portid); snprintf(name, RTE_DIM(name), "port %u fwd", portid); /* Setup forward job. * Set min, max and initial period. Set target to MAX_PKT_BURST as * this is desired optimal RX/TX burst size. */ rte_jobstats_init(job, name, 0, drain_tsc, 0, MAX_PKT_BURST); rte_jobstats_set_update_period_function(job, l2fwd_job_update_cb); rte_timer_init(&qconf->rx_timers[i]); ret = rte_timer_reset(&qconf->rx_timers[i], 0, PERIODICAL, lcore_id, &l2fwd_fwd_job, (void *)(uintptr_t)i); if (ret < 0) { rte_exit(1, "Failed to reset lcore %u port %u job timer: %s", lcore_id, qconf->rx_port_list[i], rte_strerror(-ret)); } } } if (timer_period) rte_eal_alarm_set(timer_period * MS_PER_S, show_stats_cb, NULL); else RTE_LOG(INFO, L2FWD, "Stats display disabled\n"); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l3fwd/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l3fwd # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 $(USER_FLAGS) CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l3fwd/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define APP_LOOKUP_EXACT_MATCH 0 #define APP_LOOKUP_LPM 1 #define DO_RFC_1812_CHECKS #ifndef APP_LOOKUP_METHOD #define APP_LOOKUP_METHOD APP_LOOKUP_LPM #endif /* * When set to zero, simple forwaring path is eanbled. * When set to one, optimized forwarding path is enabled. * Note that LPM optimisation path uses SSE4.1 instructions. */ #if ((APP_LOOKUP_METHOD == APP_LOOKUP_LPM) && !defined(__SSE4_1__)) #define ENABLE_MULTI_BUFFER_OPTIMIZE 0 #else #define ENABLE_MULTI_BUFFER_OPTIMIZE 1 #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #include #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) #include #include #else #error "APP_LOOKUP_METHOD set to incorrect value" #endif #ifndef IPv6_BYTES #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ "%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define IPv6_BYTES(addr) \ addr[0], addr[1], addr[2], addr[3], \ addr[4], addr[5], addr[6], addr[7], \ addr[8], addr[9], addr[10], addr[11],\ addr[12], addr[13],addr[14], addr[15] #endif #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 #define MAX_JUMBO_PKT_LEN 9600 #define IPV6_ADDR_LEN 16 #define MEMPOOL_CACHE_SIZE 256 /* * This expression is used to calculate the number of mbufs needed depending on user input, taking * into account memory for rx and tx hardware rings, cache per lcore and mtable per port per lcore. * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum value of 8192 */ #define NB_MBUF RTE_MAX ( \ (nb_ports*nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT + \ nb_ports*nb_lcores*MAX_PKT_BURST + \ nb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT + \ nb_lcores*MEMPOOL_CACHE_SIZE), \ (unsigned)8192) #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* * Try to avoid TX buffering if we have at least MAX_TX_BURST packets to send. */ #define MAX_TX_BURST (MAX_PKT_BURST / 2) #define NB_SOCKETS 8 /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* Used to mark destination port as 'invalid'. */ #define BAD_PORT ((uint16_t)-1) #define FWDSTEP 4 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static uint64_t dest_eth_addr[RTE_MAX_ETHPORTS]; static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; static __m128i val_eth[RTE_MAX_ETHPORTS]; /* replace first 12B of the ethernet header. */ #define MASK_ETH 0x3f /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; static int promiscuous_on = 0; /**< Ports set in promiscuous mode off by default. */ static int numa_on = 1; /**< NUMA is enabled by default. */ #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static int ipv6 = 0; /**< ipv6 is false by default. */ #endif struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; struct lcore_rx_queue { uint8_t port_id; uint8_t queue_id; } __rte_cache_aligned; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS #define MAX_RX_QUEUE_PER_PORT 128 #define MAX_LCORE_PARAMS 1024 struct lcore_params { uint8_t port_id; uint8_t queue_id; uint8_t lcore_id; } __rte_cache_aligned; static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, }; static struct lcore_params * lcore_params = lcore_params_array_default; static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #define DEFAULT_HASH_FUNC rte_hash_crc #else #include #define DEFAULT_HASH_FUNC rte_jhash #endif struct ipv4_5tuple { uint32_t ip_dst; uint32_t ip_src; uint16_t port_dst; uint16_t port_src; uint8_t proto; } __attribute__((__packed__)); union ipv4_5tuple_host { struct { uint8_t pad0; uint8_t proto; uint16_t pad1; uint32_t ip_src; uint32_t ip_dst; uint16_t port_src; uint16_t port_dst; }; __m128i xmm; }; #define XMM_NUM_IN_IPV6_5TUPLE 3 struct ipv6_5tuple { uint8_t ip_dst[IPV6_ADDR_LEN]; uint8_t ip_src[IPV6_ADDR_LEN]; uint16_t port_dst; uint16_t port_src; uint8_t proto; } __attribute__((__packed__)); union ipv6_5tuple_host { struct { uint16_t pad0; uint8_t proto; uint8_t pad1; uint8_t ip_src[IPV6_ADDR_LEN]; uint8_t ip_dst[IPV6_ADDR_LEN]; uint16_t port_src; uint16_t port_dst; uint64_t reserve; }; __m128i xmm[XMM_NUM_IN_IPV6_5TUPLE]; }; struct ipv4_l3fwd_route { struct ipv4_5tuple key; uint8_t if_out; }; struct ipv6_l3fwd_route { struct ipv6_5tuple key; uint8_t if_out; }; static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { {{IPv4(101,0,0,0), IPv4(100,10,0,1), 101, 11, IPPROTO_TCP}, 0}, {{IPv4(201,0,0,0), IPv4(200,20,0,1), 102, 12, IPPROTO_TCP}, 1}, {{IPv4(111,0,0,0), IPv4(100,30,0,1), 101, 11, IPPROTO_TCP}, 2}, {{IPv4(211,0,0,0), IPv4(200,40,0,1), 102, 12, IPPROTO_TCP}, 3}, }; static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { {{ {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x02, 0x1e, 0x67, 0xff, 0xfe, 0, 0, 0}, {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 101, 11, IPPROTO_TCP}, 0}, {{ {0xfe, 0x90, 0, 0, 0, 0, 0, 0, 0x02, 0x1e, 0x67, 0xff, 0xfe, 0, 0, 0}, {0xfe, 0x90, 0, 0, 0, 0, 0, 0, 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 102, 12, IPPROTO_TCP}, 1}, {{ {0xfe, 0xa0, 0, 0, 0, 0, 0, 0, 0x02, 0x1e, 0x67, 0xff, 0xfe, 0, 0, 0}, {0xfe, 0xa0, 0, 0, 0, 0, 0, 0, 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 101, 11, IPPROTO_TCP}, 2}, {{ {0xfe, 0xb0, 0, 0, 0, 0, 0, 0, 0x02, 0x1e, 0x67, 0xff, 0xfe, 0, 0, 0}, {0xfe, 0xb0, 0, 0, 0, 0, 0, 0, 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, 102, 12, IPPROTO_TCP}, 3}, }; typedef struct rte_hash lookup_struct_t; static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; static lookup_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; #ifdef RTE_ARCH_X86_64 /* default to 4 million hash entries (approx) */ #define L3FWD_HASH_ENTRIES 1024*1024*4 #else /* 32-bit has less address-space for hugepage memory, limit to 1M entries */ #define L3FWD_HASH_ENTRIES 1024*1024*1 #endif #define HASH_ENTRY_NUMBER_DEFAULT 4 static uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT; static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val) { const union ipv4_5tuple_host *k; uint32_t t; const uint32_t *p; k = data; t = k->proto; p = (const uint32_t *)&k->port_src; #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 init_val = rte_hash_crc_4byte(t, init_val); init_val = rte_hash_crc_4byte(k->ip_src, init_val); init_val = rte_hash_crc_4byte(k->ip_dst, init_val); init_val = rte_hash_crc_4byte(*p, init_val); #else /* RTE_MACHINE_CPUFLAG_SSE4_2 */ init_val = rte_jhash_1word(t, init_val); init_val = rte_jhash_1word(k->ip_src, init_val); init_val = rte_jhash_1word(k->ip_dst, init_val); init_val = rte_jhash_1word(*p, init_val); #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ return (init_val); } static inline uint32_t ipv6_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val) { const union ipv6_5tuple_host *k; uint32_t t; const uint32_t *p; #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 const uint32_t *ip_src0, *ip_src1, *ip_src2, *ip_src3; const uint32_t *ip_dst0, *ip_dst1, *ip_dst2, *ip_dst3; #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ k = data; t = k->proto; p = (const uint32_t *)&k->port_src; #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 ip_src0 = (const uint32_t *) k->ip_src; ip_src1 = (const uint32_t *)(k->ip_src+4); ip_src2 = (const uint32_t *)(k->ip_src+8); ip_src3 = (const uint32_t *)(k->ip_src+12); ip_dst0 = (const uint32_t *) k->ip_dst; ip_dst1 = (const uint32_t *)(k->ip_dst+4); ip_dst2 = (const uint32_t *)(k->ip_dst+8); ip_dst3 = (const uint32_t *)(k->ip_dst+12); init_val = rte_hash_crc_4byte(t, init_val); init_val = rte_hash_crc_4byte(*ip_src0, init_val); init_val = rte_hash_crc_4byte(*ip_src1, init_val); init_val = rte_hash_crc_4byte(*ip_src2, init_val); init_val = rte_hash_crc_4byte(*ip_src3, init_val); init_val = rte_hash_crc_4byte(*ip_dst0, init_val); init_val = rte_hash_crc_4byte(*ip_dst1, init_val); init_val = rte_hash_crc_4byte(*ip_dst2, init_val); init_val = rte_hash_crc_4byte(*ip_dst3, init_val); init_val = rte_hash_crc_4byte(*p, init_val); #else /* RTE_MACHINE_CPUFLAG_SSE4_2 */ init_val = rte_jhash_1word(t, init_val); init_val = rte_jhash(k->ip_src, sizeof(uint8_t) * IPV6_ADDR_LEN, init_val); init_val = rte_jhash(k->ip_dst, sizeof(uint8_t) * IPV6_ADDR_LEN, init_val); init_val = rte_jhash_1word(*p, init_val); #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ return (init_val); } #define IPV4_L3FWD_NUM_ROUTES \ (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) #define IPV6_L3FWD_NUM_ROUTES \ (sizeof(ipv6_l3fwd_route_array) / sizeof(ipv6_l3fwd_route_array[0])) static uint8_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) struct ipv4_l3fwd_route { uint32_t ip; uint8_t depth; uint8_t if_out; }; struct ipv6_l3fwd_route { uint8_t ip[16]; uint8_t depth; uint8_t if_out; }; static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { {IPv4(1,1,1,0), 24, 0}, {IPv4(2,1,1,0), 24, 1}, {IPv4(3,1,1,0), 24, 2}, {IPv4(4,1,1,0), 24, 3}, {IPv4(5,1,1,0), 24, 4}, {IPv4(6,1,1,0), 24, 5}, {IPv4(7,1,1,0), 24, 6}, {IPv4(8,1,1,0), 24, 7}, }; static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0}, {{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1}, {{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2}, {{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3}, {{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4}, {{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5}, {{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6}, {{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7}, }; #define IPV4_L3FWD_NUM_ROUTES \ (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) #define IPV6_L3FWD_NUM_ROUTES \ (sizeof(ipv6_l3fwd_route_array) / sizeof(ipv6_l3fwd_route_array[0])) #define IPV4_L3FWD_LPM_MAX_RULES 1024 #define IPV6_L3FWD_LPM_MAX_RULES 1024 #define IPV6_L3FWD_LPM_NUMBER_TBL8S (1 << 16) typedef struct rte_lpm lookup_struct_t; typedef struct rte_lpm6 lookup6_struct_t; static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; static lookup6_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; #endif struct lcore_conf { uint16_t n_rx_queue; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; lookup_struct_t * ipv4_lookup_struct; #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) lookup6_struct_t * ipv6_lookup_struct; #else lookup_struct_t * ipv6_lookup_struct; #endif } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) { struct rte_mbuf **m_table; int ret; uint16_t queueid; queueid = qconf->tx_queue_id[port]; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, queueid, m_table, n); if (unlikely(ret < n)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { uint32_t lcore_id; uint16_t len; struct lcore_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static inline __attribute__((always_inline)) void send_packetsx4(struct lcore_conf *qconf, uint8_t port, struct rte_mbuf *m[], uint32_t num) { uint32_t len, j, n; len = qconf->tx_mbufs[port].len; /* * If TX buffer for that queue is empty, and we have enough packets, * then send them straightway. */ if (num >= MAX_TX_BURST && len == 0) { n = rte_eth_tx_burst(port, qconf->tx_queue_id[port], m, num); if (unlikely(n < num)) { do { rte_pktmbuf_free(m[n]); } while (++n < num); } return; } /* * Put packets into TX buffer for that queue. */ n = len + num; n = (n > MAX_PKT_BURST) ? MAX_PKT_BURST - len : num; j = 0; switch (n % FWDSTEP) { while (j < n) { case 0: qconf->tx_mbufs[port].m_table[len + j] = m[j]; j++; case 3: qconf->tx_mbufs[port].m_table[len + j] = m[j]; j++; case 2: qconf->tx_mbufs[port].m_table[len + j] = m[j]; j++; case 1: qconf->tx_mbufs[port].m_table[len + j] = m[j]; j++; } } len += n; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { send_burst(qconf, MAX_PKT_BURST, port); /* copy rest of the packets into the TX buffer. */ len = num - n; j = 0; switch (len % FWDSTEP) { while (j < len) { case 0: qconf->tx_mbufs[port].m_table[j] = m[n + j]; j++; case 3: qconf->tx_mbufs[port].m_table[j] = m[n + j]; j++; case 2: qconf->tx_mbufs[port].m_table[j] = m[n + j]; j++; case 1: qconf->tx_mbufs[port].m_table[j] = m[n + j]; j++; } } } qconf->tx_mbufs[port].len = len; } #endif /* APP_LOOKUP_LPM */ #ifdef DO_RFC_1812_CHECKS static inline int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len) { /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ /* * 1. The packet length reported by the Link Layer must be large * enough to hold the minimum length legal IP datagram (20 bytes). */ if (link_len < sizeof(struct ipv4_hdr)) return -1; /* 2. The IP checksum must be correct. */ /* this is checked in H/W */ /* * 3. The IP version number must be 4. If the version number is not 4 * then the packet may be another version of IP, such as IPng or * ST-II. */ if (((pkt->version_ihl) >> 4) != 4) return -3; /* * 4. The IP header length field must be large enough to hold the * minimum length legal IP datagram (20 bytes = 5 words). */ if ((pkt->version_ihl & 0xf) < 5) return -4; /* * 5. The IP total length field must be large enough to hold the IP * datagram header, whose length is specified in the IP header length * field. */ if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr)) return -5; return 0; } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static __m128i mask0; static __m128i mask1; static __m128i mask2; static inline uint8_t get_ipv4_dst_port(void *ipv4_hdr, uint8_t portid, lookup_struct_t * ipv4_l3fwd_lookup_struct) { int ret = 0; union ipv4_5tuple_host key; ipv4_hdr = (uint8_t *)ipv4_hdr + offsetof(struct ipv4_hdr, time_to_live); __m128i data = _mm_loadu_si128((__m128i*)(ipv4_hdr)); /* Get 5 tuple: dst port, src port, dst IP address, src IP address and protocol */ key.xmm = _mm_and_si128(data, mask0); /* Find destination port */ ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : ipv4_l3fwd_out_if[ret]); } static inline uint8_t get_ipv6_dst_port(void *ipv6_hdr, uint8_t portid, lookup_struct_t * ipv6_l3fwd_lookup_struct) { int ret = 0; union ipv6_5tuple_host key; ipv6_hdr = (uint8_t *)ipv6_hdr + offsetof(struct ipv6_hdr, payload_len); __m128i data0 = _mm_loadu_si128((__m128i*)(ipv6_hdr)); __m128i data1 = _mm_loadu_si128((__m128i*)(((uint8_t*)ipv6_hdr)+sizeof(__m128i))); __m128i data2 = _mm_loadu_si128((__m128i*)(((uint8_t*)ipv6_hdr)+sizeof(__m128i)+sizeof(__m128i))); /* Get part of 5 tuple: src IP address lower 96 bits and protocol */ key.xmm[0] = _mm_and_si128(data0, mask1); /* Get part of 5 tuple: dst IP address lower 96 bits and src IP address higher 32 bits */ key.xmm[1] = data1; /* Get part of 5 tuple: dst port and src port and dst IP address higher 32 bits */ key.xmm[2] = _mm_and_si128(data2, mask2); /* Find destination port */ ret = rte_hash_lookup(ipv6_l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : ipv6_l3fwd_out_if[ret]); } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static inline uint8_t get_ipv4_dst_port(void *ipv4_hdr, uint8_t portid, lookup_struct_t * ipv4_l3fwd_lookup_struct) { uint8_t next_hop; return (uint8_t) ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(((struct ipv4_hdr *)ipv4_hdr)->dst_addr), &next_hop) == 0) ? next_hop : portid); } static inline uint8_t get_ipv6_dst_port(void *ipv6_hdr, uint8_t portid, lookup6_struct_t * ipv6_l3fwd_lookup_struct) { uint8_t next_hop; return (uint8_t) ((rte_lpm6_lookup(ipv6_l3fwd_lookup_struct, ((struct ipv6_hdr*)ipv6_hdr)->dst_addr, &next_hop) == 0)? next_hop : portid); } #endif static inline void l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qconf) __attribute__((unused)); #if ((APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) && \ (ENABLE_MULTI_BUFFER_OPTIMIZE == 1)) #define MASK_ALL_PKTS 0xff #define EXCLUDE_1ST_PKT 0xfe #define EXCLUDE_2ND_PKT 0xfd #define EXCLUDE_3RD_PKT 0xfb #define EXCLUDE_4TH_PKT 0xf7 #define EXCLUDE_5TH_PKT 0xef #define EXCLUDE_6TH_PKT 0xdf #define EXCLUDE_7TH_PKT 0xbf #define EXCLUDE_8TH_PKT 0x7f static inline void simple_ipv4_fwd_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_conf *qconf) { struct ether_hdr *eth_hdr[8]; struct ipv4_hdr *ipv4_hdr[8]; uint8_t dst_port[8]; int32_t ret[8]; union ipv4_5tuple_host key[8]; __m128i data[8]; eth_hdr[0] = rte_pktmbuf_mtod(m[0], struct ether_hdr *); eth_hdr[1] = rte_pktmbuf_mtod(m[1], struct ether_hdr *); eth_hdr[2] = rte_pktmbuf_mtod(m[2], struct ether_hdr *); eth_hdr[3] = rte_pktmbuf_mtod(m[3], struct ether_hdr *); eth_hdr[4] = rte_pktmbuf_mtod(m[4], struct ether_hdr *); eth_hdr[5] = rte_pktmbuf_mtod(m[5], struct ether_hdr *); eth_hdr[6] = rte_pktmbuf_mtod(m[6], struct ether_hdr *); eth_hdr[7] = rte_pktmbuf_mtod(m[7], struct ether_hdr *); /* Handle IPv4 headers.*/ ipv4_hdr[0] = rte_pktmbuf_mtod_offset(m[0], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[1] = rte_pktmbuf_mtod_offset(m[1], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[2] = rte_pktmbuf_mtod_offset(m[2], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[3] = rte_pktmbuf_mtod_offset(m[3], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[4] = rte_pktmbuf_mtod_offset(m[4], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[5] = rte_pktmbuf_mtod_offset(m[5], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[6] = rte_pktmbuf_mtod_offset(m[6], struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_hdr[7] = rte_pktmbuf_mtod_offset(m[7], struct ipv4_hdr *, sizeof(struct ether_hdr)); #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ uint8_t valid_mask = MASK_ALL_PKTS; if (is_valid_ipv4_pkt(ipv4_hdr[0], m[0]->pkt_len) < 0) { rte_pktmbuf_free(m[0]); valid_mask &= EXCLUDE_1ST_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[1], m[1]->pkt_len) < 0) { rte_pktmbuf_free(m[1]); valid_mask &= EXCLUDE_2ND_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[2], m[2]->pkt_len) < 0) { rte_pktmbuf_free(m[2]); valid_mask &= EXCLUDE_3RD_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[3], m[3]->pkt_len) < 0) { rte_pktmbuf_free(m[3]); valid_mask &= EXCLUDE_4TH_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[4], m[4]->pkt_len) < 0) { rte_pktmbuf_free(m[4]); valid_mask &= EXCLUDE_5TH_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[5], m[5]->pkt_len) < 0) { rte_pktmbuf_free(m[5]); valid_mask &= EXCLUDE_6TH_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[6], m[6]->pkt_len) < 0) { rte_pktmbuf_free(m[6]); valid_mask &= EXCLUDE_7TH_PKT; } if (is_valid_ipv4_pkt(ipv4_hdr[7], m[7]->pkt_len) < 0) { rte_pktmbuf_free(m[7]); valid_mask &= EXCLUDE_8TH_PKT; } if (unlikely(valid_mask != MASK_ALL_PKTS)) { if (valid_mask == 0){ return; } else { uint8_t i = 0; for (i = 0; i < 8; i++) { if ((0x1 << i) & valid_mask) { l3fwd_simple_forward(m[i], portid, qconf); } } return; } } #endif // End of #ifdef DO_RFC_1812_CHECKS data[0] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[0], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[1] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[1], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[2] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[2], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[3] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[3], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[4] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[4], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[5] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[5], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[6] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[6], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); data[7] = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m[7], __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv4_hdr, time_to_live))); key[0].xmm = _mm_and_si128(data[0], mask0); key[1].xmm = _mm_and_si128(data[1], mask0); key[2].xmm = _mm_and_si128(data[2], mask0); key[3].xmm = _mm_and_si128(data[3], mask0); key[4].xmm = _mm_and_si128(data[4], mask0); key[5].xmm = _mm_and_si128(data[5], mask0); key[6].xmm = _mm_and_si128(data[6], mask0); key[7].xmm = _mm_and_si128(data[7], mask0); const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7]}; rte_hash_lookup_multi(qconf->ipv4_lookup_struct, &key_array[0], 8, ret); dst_port[0] = (uint8_t) ((ret[0] < 0) ? portid : ipv4_l3fwd_out_if[ret[0]]); dst_port[1] = (uint8_t) ((ret[1] < 0) ? portid : ipv4_l3fwd_out_if[ret[1]]); dst_port[2] = (uint8_t) ((ret[2] < 0) ? portid : ipv4_l3fwd_out_if[ret[2]]); dst_port[3] = (uint8_t) ((ret[3] < 0) ? portid : ipv4_l3fwd_out_if[ret[3]]); dst_port[4] = (uint8_t) ((ret[4] < 0) ? portid : ipv4_l3fwd_out_if[ret[4]]); dst_port[5] = (uint8_t) ((ret[5] < 0) ? portid : ipv4_l3fwd_out_if[ret[5]]); dst_port[6] = (uint8_t) ((ret[6] < 0) ? portid : ipv4_l3fwd_out_if[ret[6]]); dst_port[7] = (uint8_t) ((ret[7] < 0) ? portid : ipv4_l3fwd_out_if[ret[7]]); if (dst_port[0] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[0]) == 0) dst_port[0] = portid; if (dst_port[1] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[1]) == 0) dst_port[1] = portid; if (dst_port[2] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[2]) == 0) dst_port[2] = portid; if (dst_port[3] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[3]) == 0) dst_port[3] = portid; if (dst_port[4] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[4]) == 0) dst_port[4] = portid; if (dst_port[5] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[5]) == 0) dst_port[5] = portid; if (dst_port[6] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[6]) == 0) dst_port[6] = portid; if (dst_port[7] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[7]) == 0) dst_port[7] = portid; #ifdef DO_RFC_1812_CHECKS /* Update time to live and header checksum */ --(ipv4_hdr[0]->time_to_live); --(ipv4_hdr[1]->time_to_live); --(ipv4_hdr[2]->time_to_live); --(ipv4_hdr[3]->time_to_live); ++(ipv4_hdr[0]->hdr_checksum); ++(ipv4_hdr[1]->hdr_checksum); ++(ipv4_hdr[2]->hdr_checksum); ++(ipv4_hdr[3]->hdr_checksum); --(ipv4_hdr[4]->time_to_live); --(ipv4_hdr[5]->time_to_live); --(ipv4_hdr[6]->time_to_live); --(ipv4_hdr[7]->time_to_live); ++(ipv4_hdr[4]->hdr_checksum); ++(ipv4_hdr[5]->hdr_checksum); ++(ipv4_hdr[6]->hdr_checksum); ++(ipv4_hdr[7]->hdr_checksum); #endif /* dst addr */ *(uint64_t *)ð_hdr[0]->d_addr = dest_eth_addr[dst_port[0]]; *(uint64_t *)ð_hdr[1]->d_addr = dest_eth_addr[dst_port[1]]; *(uint64_t *)ð_hdr[2]->d_addr = dest_eth_addr[dst_port[2]]; *(uint64_t *)ð_hdr[3]->d_addr = dest_eth_addr[dst_port[3]]; *(uint64_t *)ð_hdr[4]->d_addr = dest_eth_addr[dst_port[4]]; *(uint64_t *)ð_hdr[5]->d_addr = dest_eth_addr[dst_port[5]]; *(uint64_t *)ð_hdr[6]->d_addr = dest_eth_addr[dst_port[6]]; *(uint64_t *)ð_hdr[7]->d_addr = dest_eth_addr[dst_port[7]]; /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port[0]], ð_hdr[0]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[1]], ð_hdr[1]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[2]], ð_hdr[2]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[3]], ð_hdr[3]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[4]], ð_hdr[4]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[5]], ð_hdr[5]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[6]], ð_hdr[6]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[7]], ð_hdr[7]->s_addr); send_single_packet(m[0], (uint8_t)dst_port[0]); send_single_packet(m[1], (uint8_t)dst_port[1]); send_single_packet(m[2], (uint8_t)dst_port[2]); send_single_packet(m[3], (uint8_t)dst_port[3]); send_single_packet(m[4], (uint8_t)dst_port[4]); send_single_packet(m[5], (uint8_t)dst_port[5]); send_single_packet(m[6], (uint8_t)dst_port[6]); send_single_packet(m[7], (uint8_t)dst_port[7]); } static inline void get_ipv6_5tuple(struct rte_mbuf* m0, __m128i mask0, __m128i mask1, union ipv6_5tuple_host * key) { __m128i tmpdata0 = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m0, __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv6_hdr, payload_len))); __m128i tmpdata1 = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m0, __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv6_hdr, payload_len) + sizeof(__m128i))); __m128i tmpdata2 = _mm_loadu_si128(rte_pktmbuf_mtod_offset(m0, __m128i *, sizeof(struct ether_hdr) + offsetof(struct ipv6_hdr, payload_len) + sizeof(__m128i) + sizeof(__m128i))); key->xmm[0] = _mm_and_si128(tmpdata0, mask0); key->xmm[1] = tmpdata1; key->xmm[2] = _mm_and_si128(tmpdata2, mask1); return; } static inline void simple_ipv6_fwd_8pkts(struct rte_mbuf *m[8], uint8_t portid, struct lcore_conf *qconf) { struct ether_hdr *eth_hdr[8]; __attribute__((unused)) struct ipv6_hdr *ipv6_hdr[8]; uint8_t dst_port[8]; int32_t ret[8]; union ipv6_5tuple_host key[8]; eth_hdr[0] = rte_pktmbuf_mtod(m[0], struct ether_hdr *); eth_hdr[1] = rte_pktmbuf_mtod(m[1], struct ether_hdr *); eth_hdr[2] = rte_pktmbuf_mtod(m[2], struct ether_hdr *); eth_hdr[3] = rte_pktmbuf_mtod(m[3], struct ether_hdr *); eth_hdr[4] = rte_pktmbuf_mtod(m[4], struct ether_hdr *); eth_hdr[5] = rte_pktmbuf_mtod(m[5], struct ether_hdr *); eth_hdr[6] = rte_pktmbuf_mtod(m[6], struct ether_hdr *); eth_hdr[7] = rte_pktmbuf_mtod(m[7], struct ether_hdr *); /* Handle IPv6 headers.*/ ipv6_hdr[0] = rte_pktmbuf_mtod_offset(m[0], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[1] = rte_pktmbuf_mtod_offset(m[1], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[2] = rte_pktmbuf_mtod_offset(m[2], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[3] = rte_pktmbuf_mtod_offset(m[3], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[4] = rte_pktmbuf_mtod_offset(m[4], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[5] = rte_pktmbuf_mtod_offset(m[5], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[6] = rte_pktmbuf_mtod_offset(m[6], struct ipv6_hdr *, sizeof(struct ether_hdr)); ipv6_hdr[7] = rte_pktmbuf_mtod_offset(m[7], struct ipv6_hdr *, sizeof(struct ether_hdr)); get_ipv6_5tuple(m[0], mask1, mask2, &key[0]); get_ipv6_5tuple(m[1], mask1, mask2, &key[1]); get_ipv6_5tuple(m[2], mask1, mask2, &key[2]); get_ipv6_5tuple(m[3], mask1, mask2, &key[3]); get_ipv6_5tuple(m[4], mask1, mask2, &key[4]); get_ipv6_5tuple(m[5], mask1, mask2, &key[5]); get_ipv6_5tuple(m[6], mask1, mask2, &key[6]); get_ipv6_5tuple(m[7], mask1, mask2, &key[7]); const void *key_array[8] = {&key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7]}; rte_hash_lookup_multi(qconf->ipv6_lookup_struct, &key_array[0], 4, ret); dst_port[0] = (uint8_t) ((ret[0] < 0) ? portid:ipv6_l3fwd_out_if[ret[0]]); dst_port[1] = (uint8_t) ((ret[1] < 0) ? portid:ipv6_l3fwd_out_if[ret[1]]); dst_port[2] = (uint8_t) ((ret[2] < 0) ? portid:ipv6_l3fwd_out_if[ret[2]]); dst_port[3] = (uint8_t) ((ret[3] < 0) ? portid:ipv6_l3fwd_out_if[ret[3]]); dst_port[4] = (uint8_t) ((ret[4] < 0) ? portid:ipv6_l3fwd_out_if[ret[4]]); dst_port[5] = (uint8_t) ((ret[5] < 0) ? portid:ipv6_l3fwd_out_if[ret[5]]); dst_port[6] = (uint8_t) ((ret[6] < 0) ? portid:ipv6_l3fwd_out_if[ret[6]]); dst_port[7] = (uint8_t) ((ret[7] < 0) ? portid:ipv6_l3fwd_out_if[ret[7]]); if (dst_port[0] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[0]) == 0) dst_port[0] = portid; if (dst_port[1] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[1]) == 0) dst_port[1] = portid; if (dst_port[2] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[2]) == 0) dst_port[2] = portid; if (dst_port[3] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[3]) == 0) dst_port[3] = portid; if (dst_port[4] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[4]) == 0) dst_port[4] = portid; if (dst_port[5] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[5]) == 0) dst_port[5] = portid; if (dst_port[6] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[6]) == 0) dst_port[6] = portid; if (dst_port[7] >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port[7]) == 0) dst_port[7] = portid; /* dst addr */ *(uint64_t *)ð_hdr[0]->d_addr = dest_eth_addr[dst_port[0]]; *(uint64_t *)ð_hdr[1]->d_addr = dest_eth_addr[dst_port[1]]; *(uint64_t *)ð_hdr[2]->d_addr = dest_eth_addr[dst_port[2]]; *(uint64_t *)ð_hdr[3]->d_addr = dest_eth_addr[dst_port[3]]; *(uint64_t *)ð_hdr[4]->d_addr = dest_eth_addr[dst_port[4]]; *(uint64_t *)ð_hdr[5]->d_addr = dest_eth_addr[dst_port[5]]; *(uint64_t *)ð_hdr[6]->d_addr = dest_eth_addr[dst_port[6]]; *(uint64_t *)ð_hdr[7]->d_addr = dest_eth_addr[dst_port[7]]; /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port[0]], ð_hdr[0]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[1]], ð_hdr[1]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[2]], ð_hdr[2]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[3]], ð_hdr[3]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[4]], ð_hdr[4]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[5]], ð_hdr[5]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[6]], ð_hdr[6]->s_addr); ether_addr_copy(&ports_eth_addr[dst_port[7]], ð_hdr[7]->s_addr); send_single_packet(m[0], (uint8_t)dst_port[0]); send_single_packet(m[1], (uint8_t)dst_port[1]); send_single_packet(m[2], (uint8_t)dst_port[2]); send_single_packet(m[3], (uint8_t)dst_port[3]); send_single_packet(m[4], (uint8_t)dst_port[4]); send_single_packet(m[5], (uint8_t)dst_port[5]); send_single_packet(m[6], (uint8_t)dst_port[6]); send_single_packet(m[7], (uint8_t)dst_port[7]); } #endif /* APP_LOOKUP_METHOD */ static inline __attribute__((always_inline)) void l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qconf) { struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; uint8_t dst_port; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { #else if (m->ol_flags & PKT_RX_IPV4_HDR) { #endif /* Handle IPv4 headers.*/ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, sizeof(struct ether_hdr)); #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { rte_pktmbuf_free(m); return; } #endif dst_port = get_ipv4_dst_port(ipv4_hdr, portid, qconf->ipv4_lookup_struct); if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; #ifdef DO_RFC_1812_CHECKS /* Update time to live and header checksum */ --(ipv4_hdr->time_to_live); ++(ipv4_hdr->hdr_checksum); #endif /* dst addr */ *(uint64_t *)ð_hdr->d_addr = dest_eth_addr[dst_port]; /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { #else } else { #endif /* Handle IPv6 headers.*/ struct ipv6_hdr *ipv6_hdr; ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, sizeof(struct ether_hdr)); dst_port = get_ipv6_dst_port(ipv6_hdr, portid, qconf->ipv6_lookup_struct); if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; /* dst addr */ *(uint64_t *)ð_hdr->d_addr = dest_eth_addr[dst_port]; /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); #ifdef RTE_NEXT_ABI } else /* Free the mbuf that contains non-IPV4/IPV6 packet */ rte_pktmbuf_free(m); #else } #endif } #if ((APP_LOOKUP_METHOD == APP_LOOKUP_LPM) && \ (ENABLE_MULTI_BUFFER_OPTIMIZE == 1)) #ifdef DO_RFC_1812_CHECKS #define IPV4_MIN_VER_IHL 0x45 #define IPV4_MAX_VER_IHL 0x4f #define IPV4_MAX_VER_IHL_DIFF (IPV4_MAX_VER_IHL - IPV4_MIN_VER_IHL) /* Minimum value of IPV4 total length (20B) in network byte order. */ #define IPV4_MIN_LEN_BE (sizeof(struct ipv4_hdr) << 8) /* * From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2: * - The IP version number must be 4. * - The IP header length field must be large enough to hold the * minimum length legal IP datagram (20 bytes = 5 words). * - The IP total length field must be large enough to hold the IP * datagram header, whose length is specified in the IP header length * field. * If we encounter invalid IPV4 packet, then set destination port for it * to BAD_PORT value. */ static inline __attribute__((always_inline)) void #ifdef RTE_NEXT_ABI rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t ptype) #else rfc1812_process(struct ipv4_hdr *ipv4_hdr, uint16_t *dp, uint32_t flags) #endif { uint8_t ihl; #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(ptype)) { #else if ((flags & PKT_RX_IPV4_HDR) != 0) { #endif ihl = ipv4_hdr->version_ihl - IPV4_MIN_VER_IHL; ipv4_hdr->time_to_live--; ipv4_hdr->hdr_checksum++; if (ihl > IPV4_MAX_VER_IHL_DIFF || ((uint8_t)ipv4_hdr->total_length == 0 && ipv4_hdr->total_length < IPV4_MIN_LEN_BE)) { dp[0] = BAD_PORT; } } } #else #define rfc1812_process(mb, dp) do { } while (0) #endif /* DO_RFC_1812_CHECKS */ #endif /* APP_LOOKUP_LPM && ENABLE_MULTI_BUFFER_OPTIMIZE */ #if ((APP_LOOKUP_METHOD == APP_LOOKUP_LPM) && \ (ENABLE_MULTI_BUFFER_OPTIMIZE == 1)) static inline __attribute__((always_inline)) uint16_t get_dst_port(const struct lcore_conf *qconf, struct rte_mbuf *pkt, uint32_t dst_ipv4, uint8_t portid) { uint8_t next_hop; struct ipv6_hdr *ipv6_hdr; struct ether_hdr *eth_hdr; #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { #else if (pkt->ol_flags & PKT_RX_IPV4_HDR) { #endif if (rte_lpm_lookup(qconf->ipv4_lookup_struct, dst_ipv4, &next_hop) != 0) next_hop = portid; #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { #else } else if (pkt->ol_flags & PKT_RX_IPV6_HDR) { #endif eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); ipv6_hdr = (struct ipv6_hdr *)(eth_hdr + 1); if (rte_lpm6_lookup(qconf->ipv6_lookup_struct, ipv6_hdr->dst_addr, &next_hop) != 0) next_hop = portid; } else { next_hop = portid; } return next_hop; } static inline void process_packet(struct lcore_conf *qconf, struct rte_mbuf *pkt, uint16_t *dst_port, uint8_t portid) { struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; uint32_t dst_ipv4; uint16_t dp; __m128i te, ve; eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); dst_ipv4 = ipv4_hdr->dst_addr; dst_ipv4 = rte_be_to_cpu_32(dst_ipv4); dp = get_dst_port(qconf, pkt, dst_ipv4, portid); te = _mm_load_si128((__m128i *)eth_hdr); ve = val_eth[dp]; dst_port[0] = dp; #ifdef RTE_NEXT_ABI rfc1812_process(ipv4_hdr, dst_port, pkt->packet_type); #else rfc1812_process(ipv4_hdr, dst_port, pkt->ol_flags); #endif te = _mm_blend_epi16(te, ve, MASK_ETH); _mm_store_si128((__m128i *)eth_hdr, te); } #ifdef RTE_NEXT_ABI /* * Read packet_type and destination IPV4 addresses from 4 mbufs. */ static inline void processx4_step1(struct rte_mbuf *pkt[FWDSTEP], __m128i *dip, uint32_t *ipv4_flag) { struct ipv4_hdr *ipv4_hdr; struct ether_hdr *eth_hdr; uint32_t x0, x1, x2, x3; eth_hdr = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x0 = ipv4_hdr->dst_addr; ipv4_flag[0] = pkt[0]->packet_type & RTE_PTYPE_L3_IPV4; eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x1 = ipv4_hdr->dst_addr; ipv4_flag[0] &= pkt[1]->packet_type; eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x2 = ipv4_hdr->dst_addr; ipv4_flag[0] &= pkt[2]->packet_type; eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x3 = ipv4_hdr->dst_addr; ipv4_flag[0] &= pkt[3]->packet_type; dip[0] = _mm_set_epi32(x3, x2, x1, x0); } #else /* RTE_NEXT_ABI */ /* * Read ol_flags and destination IPV4 addresses from 4 mbufs. */ static inline void processx4_step1(struct rte_mbuf *pkt[FWDSTEP], __m128i *dip, uint32_t *flag) { struct ipv4_hdr *ipv4_hdr; struct ether_hdr *eth_hdr; uint32_t x0, x1, x2, x3; eth_hdr = rte_pktmbuf_mtod(pkt[0], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x0 = ipv4_hdr->dst_addr; flag[0] = pkt[0]->ol_flags & PKT_RX_IPV4_HDR; eth_hdr = rte_pktmbuf_mtod(pkt[1], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x1 = ipv4_hdr->dst_addr; flag[0] &= pkt[1]->ol_flags; eth_hdr = rte_pktmbuf_mtod(pkt[2], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x2 = ipv4_hdr->dst_addr; flag[0] &= pkt[2]->ol_flags; eth_hdr = rte_pktmbuf_mtod(pkt[3], struct ether_hdr *); ipv4_hdr = (struct ipv4_hdr *)(eth_hdr + 1); x3 = ipv4_hdr->dst_addr; flag[0] &= pkt[3]->ol_flags; dip[0] = _mm_set_epi32(x3, x2, x1, x0); } #endif /* RTE_NEXT_ABI */ /* * Lookup into LPM for destination port. * If lookup fails, use incoming port (portid) as destination port. */ static inline void #ifdef RTE_NEXT_ABI processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t ipv4_flag, uint8_t portid, struct rte_mbuf *pkt[FWDSTEP], uint16_t dprt[FWDSTEP]) #else processx4_step2(const struct lcore_conf *qconf, __m128i dip, uint32_t flag, uint8_t portid, struct rte_mbuf *pkt[FWDSTEP], uint16_t dprt[FWDSTEP]) #endif /* RTE_NEXT_ABI */ { rte_xmm_t dst; const __m128i bswap_mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3); /* Byte swap 4 IPV4 addresses. */ dip = _mm_shuffle_epi8(dip, bswap_mask); /* if all 4 packets are IPV4. */ #ifdef RTE_NEXT_ABI if (likely(ipv4_flag)) { #else if (likely(flag != 0)) { #endif rte_lpm_lookupx4(qconf->ipv4_lookup_struct, dip, dprt, portid); } else { dst.x = dip; dprt[0] = get_dst_port(qconf, pkt[0], dst.u32[0], portid); dprt[1] = get_dst_port(qconf, pkt[1], dst.u32[1], portid); dprt[2] = get_dst_port(qconf, pkt[2], dst.u32[2], portid); dprt[3] = get_dst_port(qconf, pkt[3], dst.u32[3], portid); } } /* * Update source and destination MAC addresses in the ethernet header. * Perform RFC1812 checks and updates for IPV4 packets. */ static inline void processx4_step3(struct rte_mbuf *pkt[FWDSTEP], uint16_t dst_port[FWDSTEP]) { __m128i te[FWDSTEP]; __m128i ve[FWDSTEP]; __m128i *p[FWDSTEP]; p[0] = rte_pktmbuf_mtod(pkt[0], __m128i *); p[1] = rte_pktmbuf_mtod(pkt[1], __m128i *); p[2] = rte_pktmbuf_mtod(pkt[2], __m128i *); p[3] = rte_pktmbuf_mtod(pkt[3], __m128i *); ve[0] = val_eth[dst_port[0]]; te[0] = _mm_load_si128(p[0]); ve[1] = val_eth[dst_port[1]]; te[1] = _mm_load_si128(p[1]); ve[2] = val_eth[dst_port[2]]; te[2] = _mm_load_si128(p[2]); ve[3] = val_eth[dst_port[3]]; te[3] = _mm_load_si128(p[3]); /* Update first 12 bytes, keep rest bytes intact. */ te[0] = _mm_blend_epi16(te[0], ve[0], MASK_ETH); te[1] = _mm_blend_epi16(te[1], ve[1], MASK_ETH); te[2] = _mm_blend_epi16(te[2], ve[2], MASK_ETH); te[3] = _mm_blend_epi16(te[3], ve[3], MASK_ETH); _mm_store_si128(p[0], te[0]); _mm_store_si128(p[1], te[1]); _mm_store_si128(p[2], te[2]); _mm_store_si128(p[3], te[3]); #ifdef RTE_NEXT_ABI rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1), &dst_port[0], pkt[0]->packet_type); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1), &dst_port[1], pkt[1]->packet_type); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1), &dst_port[2], pkt[2]->packet_type); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1), &dst_port[3], pkt[3]->packet_type); #else /* RTE_NEXT_ABI */ rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[0] + 1), &dst_port[0], pkt[0]->ol_flags); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[1] + 1), &dst_port[1], pkt[1]->ol_flags); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[2] + 1), &dst_port[2], pkt[2]->ol_flags); rfc1812_process((struct ipv4_hdr *)((struct ether_hdr *)p[3] + 1), &dst_port[3], pkt[3]->ol_flags); #endif /* RTE_NEXT_ABI */ } /* * We group consecutive packets with the same destionation port into one burst. * To avoid extra latency this is done together with some other packet * processing, but after we made a final decision about packet's destination. * To do this we maintain: * pnum - array of number of consecutive packets with the same dest port for * each packet in the input burst. * lp - pointer to the last updated element in the pnum. * dlp - dest port value lp corresponds to. */ #define GRPSZ (1 << FWDSTEP) #define GRPMSK (GRPSZ - 1) #define GROUP_PORT_STEP(dlp, dcp, lp, pn, idx) do { \ if (likely((dlp) == (dcp)[(idx)])) { \ (lp)[0]++; \ } else { \ (dlp) = (dcp)[idx]; \ (lp) = (pn) + (idx); \ (lp)[0] = 1; \ } \ } while (0) /* * Group consecutive packets with the same destination port in bursts of 4. * Suppose we have array of destionation ports: * dst_port[] = {a, b, c, d,, e, ... } * dp1 should contain: , dp2: . * We doing 4 comparisions at once and the result is 4 bit mask. * This mask is used as an index into prebuild array of pnum values. */ static inline uint16_t * port_groupx4(uint16_t pn[FWDSTEP + 1], uint16_t *lp, __m128i dp1, __m128i dp2) { static const struct { uint64_t pnum; /* prebuild 4 values for pnum[]. */ int32_t idx; /* index for new last updated elemnet. */ uint16_t lpv; /* add value to the last updated element. */ } gptbl[GRPSZ] = { { /* 0: a != b, b != c, c != d, d != e */ .pnum = UINT64_C(0x0001000100010001), .idx = 4, .lpv = 0, }, { /* 1: a == b, b != c, c != d, d != e */ .pnum = UINT64_C(0x0001000100010002), .idx = 4, .lpv = 1, }, { /* 2: a != b, b == c, c != d, d != e */ .pnum = UINT64_C(0x0001000100020001), .idx = 4, .lpv = 0, }, { /* 3: a == b, b == c, c != d, d != e */ .pnum = UINT64_C(0x0001000100020003), .idx = 4, .lpv = 2, }, { /* 4: a != b, b != c, c == d, d != e */ .pnum = UINT64_C(0x0001000200010001), .idx = 4, .lpv = 0, }, { /* 5: a == b, b != c, c == d, d != e */ .pnum = UINT64_C(0x0001000200010002), .idx = 4, .lpv = 1, }, { /* 6: a != b, b == c, c == d, d != e */ .pnum = UINT64_C(0x0001000200030001), .idx = 4, .lpv = 0, }, { /* 7: a == b, b == c, c == d, d != e */ .pnum = UINT64_C(0x0001000200030004), .idx = 4, .lpv = 3, }, { /* 8: a != b, b != c, c != d, d == e */ .pnum = UINT64_C(0x0002000100010001), .idx = 3, .lpv = 0, }, { /* 9: a == b, b != c, c != d, d == e */ .pnum = UINT64_C(0x0002000100010002), .idx = 3, .lpv = 1, }, { /* 0xa: a != b, b == c, c != d, d == e */ .pnum = UINT64_C(0x0002000100020001), .idx = 3, .lpv = 0, }, { /* 0xb: a == b, b == c, c != d, d == e */ .pnum = UINT64_C(0x0002000100020003), .idx = 3, .lpv = 2, }, { /* 0xc: a != b, b != c, c == d, d == e */ .pnum = UINT64_C(0x0002000300010001), .idx = 2, .lpv = 0, }, { /* 0xd: a == b, b != c, c == d, d == e */ .pnum = UINT64_C(0x0002000300010002), .idx = 2, .lpv = 1, }, { /* 0xe: a != b, b == c, c == d, d == e */ .pnum = UINT64_C(0x0002000300040001), .idx = 1, .lpv = 0, }, { /* 0xf: a == b, b == c, c == d, d == e */ .pnum = UINT64_C(0x0002000300040005), .idx = 0, .lpv = 4, }, }; union { uint16_t u16[FWDSTEP + 1]; uint64_t u64; } *pnum = (void *)pn; int32_t v; dp1 = _mm_cmpeq_epi16(dp1, dp2); dp1 = _mm_unpacklo_epi16(dp1, dp1); v = _mm_movemask_ps((__m128)dp1); /* update last port counter. */ lp[0] += gptbl[v].lpv; /* if dest port value has changed. */ if (v != GRPMSK) { lp = pnum->u16 + gptbl[v].idx; lp[0] = 1; pnum->u64 = gptbl[v].pnum; } return lp; } #endif /* APP_LOOKUP_METHOD */ /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; int i, j, nb_rx; uint8_t portid, queueid; struct lcore_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; #if ((APP_LOOKUP_METHOD == APP_LOOKUP_LPM) && \ (ENABLE_MULTI_BUFFER_OPTIMIZE == 1)) int32_t k; uint16_t dlp; uint16_t *lp; uint16_t dst_port[MAX_PKT_BURST]; __m128i dip[MAX_PKT_BURST / FWDSTEP]; #ifdef RTE_NEXT_ABI uint32_t ipv4_flag[MAX_PKT_BURST / FWDSTEP]; #else uint32_t flag[MAX_PKT_BURST / FWDSTEP]; #endif uint16_t pnum[MAX_PKT_BURST + 1]; #endif prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; RTE_LOG(INFO, L3FWD, " -- lcoreid=%u portid=%hhu rxqueueid=%hhu\n", lcore_id, portid, queueid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; send_burst(qconf, qconf->tx_mbufs[portid].len, portid); qconf->tx_mbufs[portid].len = 0; } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; ++i) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); if (nb_rx == 0) continue; #if (ENABLE_MULTI_BUFFER_OPTIMIZE == 1) #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) { /* * Send nb_rx - nb_rx%8 packets * in groups of 8. */ int32_t n = RTE_ALIGN_FLOOR(nb_rx, 8); for (j = 0; j < n; j += 8) { #ifdef RTE_NEXT_ABI uint32_t pkt_type = pkts_burst[j]->packet_type & pkts_burst[j+1]->packet_type & pkts_burst[j+2]->packet_type & pkts_burst[j+3]->packet_type & pkts_burst[j+4]->packet_type & pkts_burst[j+5]->packet_type & pkts_burst[j+6]->packet_type & pkts_burst[j+7]->packet_type; if (pkt_type & RTE_PTYPE_L3_IPV4) { simple_ipv4_fwd_8pkts( &pkts_burst[j], portid, qconf); } else if (pkt_type & RTE_PTYPE_L3_IPV6) { #else /* RTE_NEXT_ABI */ uint32_t ol_flag = pkts_burst[j]->ol_flags & pkts_burst[j+1]->ol_flags & pkts_burst[j+2]->ol_flags & pkts_burst[j+3]->ol_flags & pkts_burst[j+4]->ol_flags & pkts_burst[j+5]->ol_flags & pkts_burst[j+6]->ol_flags & pkts_burst[j+7]->ol_flags; if (ol_flag & PKT_RX_IPV4_HDR ) { simple_ipv4_fwd_8pkts(&pkts_burst[j], portid, qconf); } else if (ol_flag & PKT_RX_IPV6_HDR) { #endif /* RTE_NEXT_ABI */ simple_ipv6_fwd_8pkts(&pkts_burst[j], portid, qconf); } else { l3fwd_simple_forward(pkts_burst[j], portid, qconf); l3fwd_simple_forward(pkts_burst[j+1], portid, qconf); l3fwd_simple_forward(pkts_burst[j+2], portid, qconf); l3fwd_simple_forward(pkts_burst[j+3], portid, qconf); l3fwd_simple_forward(pkts_burst[j+4], portid, qconf); l3fwd_simple_forward(pkts_burst[j+5], portid, qconf); l3fwd_simple_forward(pkts_burst[j+6], portid, qconf); l3fwd_simple_forward(pkts_burst[j+7], portid, qconf); } } for (; j < nb_rx ; j++) { l3fwd_simple_forward(pkts_burst[j], portid, qconf); } } #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); for (j = 0; j != k; j += FWDSTEP) { processx4_step1(&pkts_burst[j], &dip[j / FWDSTEP], #ifdef RTE_NEXT_ABI &ipv4_flag[j / FWDSTEP]); #else &flag[j / FWDSTEP]); #endif } k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); for (j = 0; j != k; j += FWDSTEP) { processx4_step2(qconf, dip[j / FWDSTEP], #ifdef RTE_NEXT_ABI ipv4_flag[j / FWDSTEP], portid, #else flag[j / FWDSTEP], portid, #endif &pkts_burst[j], &dst_port[j]); } /* * Finish packet processing and group consecutive * packets with the same destination port. */ k = RTE_ALIGN_FLOOR(nb_rx, FWDSTEP); if (k != 0) { __m128i dp1, dp2; lp = pnum; lp[0] = 1; processx4_step3(pkts_burst, dst_port); /* dp1: */ dp1 = _mm_loadu_si128((__m128i *)dst_port); for (j = FWDSTEP; j != k; j += FWDSTEP) { processx4_step3(&pkts_burst[j], &dst_port[j]); /* * dp2: * */ dp2 = _mm_loadu_si128((__m128i *) &dst_port[j - FWDSTEP + 1]); lp = port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); /* * dp1: * */ dp1 = _mm_srli_si128(dp2, (FWDSTEP - 1) * sizeof(dst_port[0])); } /* * dp2: */ dp2 = _mm_shufflelo_epi16(dp1, 0xf9); lp = port_groupx4(&pnum[j - FWDSTEP], lp, dp1, dp2); /* * remove values added by the last repeated * dst port. */ lp[0]--; dlp = dst_port[j - 1]; } else { /* set dlp and lp to the never used values. */ dlp = BAD_PORT - 1; lp = pnum + MAX_PKT_BURST; } /* Process up to last 3 packets one by one. */ switch (nb_rx % FWDSTEP) { case 3: process_packet(qconf, pkts_burst[j], dst_port + j, portid); GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); j++; case 2: process_packet(qconf, pkts_burst[j], dst_port + j, portid); GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); j++; case 1: process_packet(qconf, pkts_burst[j], dst_port + j, portid); GROUP_PORT_STEP(dlp, dst_port, lp, pnum, j); j++; } /* * Send packets out, through destination port. * Consecuteve pacekts with the same destination port * are already grouped together. * If destination port for the packet equals BAD_PORT, * then free the packet without sending it out. */ for (j = 0; j < nb_rx; j += k) { int32_t m; uint16_t pn; pn = dst_port[j]; k = pnum[j]; if (likely(pn != BAD_PORT)) { send_packetsx4(qconf, pn, pkts_burst + j, k); } else { for (m = j; m != j + k; m++) rte_pktmbuf_free(pkts_burst[m]); } } #endif /* APP_LOOKUP_METHOD */ #else /* ENABLE_MULTI_BUFFER_OPTIMIZE == 0 */ /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); l3fwd_simple_forward(pkts_burst[j], portid, qconf); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { l3fwd_simple_forward(pkts_burst[j], portid, qconf); } #endif /* ENABLE_MULTI_BUFFER_OPTIMIZE */ } } } static int check_lcore_params(void) { uint8_t queue, lcore; uint16_t i; int socketid; for (i = 0; i < nb_lcore_params; ++i) { queue = lcore_params[i].queue_id; if (queue >= MAX_RX_QUEUE_PER_PORT) { printf("invalid queue number: %hhu\n", queue); return -1; } lcore = lcore_params[i].lcore_id; if (!rte_lcore_is_enabled(lcore)) { printf("error: lcore %hhu is not enabled in lcore mask\n", lcore); return -1; } if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && (numa_on == 0)) { printf("warning: lcore %hhu is on socket %d with numa off \n", lcore, socketid); } } return 0; } static int check_port_config(const unsigned nb_ports) { unsigned portid; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; if ((enabled_port_mask & (1 << portid)) == 0) { printf("port %u is not enabled in port mask\n", portid); return -1; } if (portid >= nb_ports) { printf("port %u is not present on the board\n", portid); return -1; } } return 0; } static uint8_t get_port_n_rx_queues(const uint8_t port) { int queue = -1; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) queue = lcore_params[i].queue_id; } return (uint8_t)(++queue); } static int init_lcore_rx_queues(void) { uint16_t i, nb_rx_queue; uint8_t lcore; for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; nb_rx_queue = lcore_conf[lcore].n_rx_queue; if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { printf("error: too many queues (%u) for lcore: %u\n", (unsigned)nb_rx_queue + 1, (unsigned)lcore); return -1; } else { lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = lcore_params[i].port_id; lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = lcore_params[i].queue_id; lcore_conf[lcore].n_rx_queue++; } } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK -P" " [--config (port,queue,lcore)[,(port,queue,lcore]]" " [--enable-jumbo [--max-pkt-len PKTLEN]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -P : enable promiscuous mode\n" " --config (port,queue,lcore): rx queues configuration\n" " --eth-dest=X,MM:MM:MM:MM:MM:MM: optional, ethernet destination for port X\n" " --no-numa: optional, disable numa awareness\n" " --ipv6: optional, specify it if running ipv6 packets\n" " --enable-jumbo: enable jumbo frame" " which max packet len is PKTLEN in decimal (64-9600)\n" " --hash-entry-num: specify the hash entry number in hexadecimal to be setup\n", prgname); } static int parse_max_pkt_len(const char *pktlen) { char *end = NULL; unsigned long len; /* parse decimal string */ len = strtoul(pktlen, &end, 10); if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (len == 0) return -1; return len; } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static int parse_hash_entry_number(const char *hash_entry_num) { char *end = NULL; unsigned long hash_en; /* parse hexadecimal string */ hash_en = strtoul(hash_entry_num, &end, 16); if ((hash_entry_num[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (hash_en == 0) return -1; return hash_en; } #endif static int parse_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; nb_lcore_params = 0; while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++){ errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } if (nb_lcore_params >= MAX_LCORE_PARAMS) { printf("exceeded max number of lcore params: %hu\n", nb_lcore_params); return -1; } lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; ++nb_lcore_params; } lcore_params = lcore_params_array; return 0; } static void parse_eth_dest(const char *optarg) { uint8_t portid; char *port_end; uint8_t c, *dest, peer_addr[6]; errno = 0; portid = strtoul(optarg, &port_end, 10); if (errno != 0 || port_end == optarg || *port_end++ != ',') rte_exit(EXIT_FAILURE, "Invalid eth-dest: %s", optarg); if (portid >= RTE_MAX_ETHPORTS) rte_exit(EXIT_FAILURE, "eth-dest: port %d >= RTE_MAX_ETHPORTS(%d)\n", portid, RTE_MAX_ETHPORTS); if (cmdline_parse_etheraddr(NULL, port_end, &peer_addr, sizeof(peer_addr)) < 0) rte_exit(EXIT_FAILURE, "Invalid ethernet address: %s\n", port_end); dest = (uint8_t *)&dest_eth_addr[portid]; for (c = 0; c < 6; c++) dest[c] = peer_addr[c]; *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; } #define CMD_LINE_OPT_CONFIG "config" #define CMD_LINE_OPT_ETH_DEST "eth-dest" #define CMD_LINE_OPT_NO_NUMA "no-numa" #define CMD_LINE_OPT_IPV6 "ipv6" #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo" #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num" /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {CMD_LINE_OPT_CONFIG, 1, 0, 0}, {CMD_LINE_OPT_ETH_DEST, 1, 0, 0}, {CMD_LINE_OPT_NO_NUMA, 0, 0, 0}, {CMD_LINE_OPT_IPV6, 0, 0, 0}, {CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, 0}, {CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:P", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; case 'P': printf("Promiscuous mode selected\n"); promiscuous_on = 1; break; /* long options */ case 0: if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_CONFIG, sizeof (CMD_LINE_OPT_CONFIG))) { ret = parse_config(optarg); if (ret) { printf("invalid config\n"); print_usage(prgname); return -1; } } if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_ETH_DEST, sizeof(CMD_LINE_OPT_CONFIG))) { parse_eth_dest(optarg); } if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_NO_NUMA, sizeof(CMD_LINE_OPT_NO_NUMA))) { printf("numa is disabled \n"); numa_on = 0; } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_IPV6, sizeof(CMD_LINE_OPT_IPV6))) { printf("ipv6 is specified \n"); ipv6 = 1; } #endif if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_ENABLE_JUMBO, sizeof (CMD_LINE_OPT_ENABLE_JUMBO))) { struct option lenopts = {"max-pkt-len", required_argument, 0, 0}; printf("jumbo frame is enabled - disabling simple TX path\n"); port_conf.rxmode.jumbo_frame = 1; /* if no max-pkt-len set, use the default value ETHER_MAX_LEN */ if (0 == getopt_long(argc, argvopt, "", &lenopts, &option_index)) { ret = parse_max_pkt_len(optarg); if ((ret < 64) || (ret > MAX_JUMBO_PKT_LEN)){ printf("invalid packet length\n"); print_usage(prgname); return -1; } port_conf.rxmode.max_rx_pkt_len = ret; } printf("set jumbo frame max packet length to %u\n", (unsigned int)port_conf.rxmode.max_rx_pkt_len); } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) if (!strncmp(lgopts[option_index].name, CMD_LINE_OPT_HASH_ENTRY_NUM, sizeof(CMD_LINE_OPT_HASH_ENTRY_NUM))) { ret = parse_hash_entry_number(optarg); if ((ret > 0) && (ret <= L3FWD_HASH_ENTRIES)) { hash_entry_number = ret; } else { printf("invalid hash entry number\n"); print_usage(prgname); return -1; } } #endif break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void convert_ipv4_5tuple(struct ipv4_5tuple* key1, union ipv4_5tuple_host* key2) { key2->ip_dst = rte_cpu_to_be_32(key1->ip_dst); key2->ip_src = rte_cpu_to_be_32(key1->ip_src); key2->port_dst = rte_cpu_to_be_16(key1->port_dst); key2->port_src = rte_cpu_to_be_16(key1->port_src); key2->proto = key1->proto; key2->pad0 = 0; key2->pad1 = 0; return; } static void convert_ipv6_5tuple(struct ipv6_5tuple* key1, union ipv6_5tuple_host* key2) { uint32_t i; for (i = 0; i < 16; i++) { key2->ip_dst[i] = key1->ip_dst[i]; key2->ip_src[i] = key1->ip_src[i]; } key2->port_dst = rte_cpu_to_be_16(key1->port_dst); key2->port_src = rte_cpu_to_be_16(key1->port_src); key2->proto = key1->proto; key2->pad0 = 0; key2->pad1 = 0; key2->reserve = 0; return; } #define BYTE_VALUE_MAX 256 #define ALL_32_BITS 0xffffffff #define BIT_8_TO_15 0x0000ff00 static inline void populate_ipv4_few_flow_into_table(const struct rte_hash* h) { uint32_t i; int32_t ret; uint32_t array_len = sizeof(ipv4_l3fwd_route_array)/sizeof(ipv4_l3fwd_route_array[0]); mask0 = _mm_set_epi32(ALL_32_BITS, ALL_32_BITS, ALL_32_BITS, BIT_8_TO_15); for (i = 0; i < array_len; i++) { struct ipv4_l3fwd_route entry; union ipv4_5tuple_host newkey; entry = ipv4_l3fwd_route_array[i]; convert_ipv4_5tuple(&entry.key, &newkey); ret = rte_hash_add_key (h,(void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } ipv4_l3fwd_out_if[ret] = entry.if_out; } printf("Hash: Adding 0x%" PRIx32 " keys\n", array_len); } #define BIT_16_TO_23 0x00ff0000 static inline void populate_ipv6_few_flow_into_table(const struct rte_hash* h) { uint32_t i; int32_t ret; uint32_t array_len = sizeof(ipv6_l3fwd_route_array)/sizeof(ipv6_l3fwd_route_array[0]); mask1 = _mm_set_epi32(ALL_32_BITS, ALL_32_BITS, ALL_32_BITS, BIT_16_TO_23); mask2 = _mm_set_epi32(0, 0, ALL_32_BITS, ALL_32_BITS); for (i = 0; i < array_len; i++) { struct ipv6_l3fwd_route entry; union ipv6_5tuple_host newkey; entry = ipv6_l3fwd_route_array[i]; convert_ipv6_5tuple(&entry.key, &newkey); ret = rte_hash_add_key (h, (void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32 " to the l3fwd hash.\n", i); } ipv6_l3fwd_out_if[ret] = entry.if_out; } printf("Hash: Adding 0x%" PRIx32 "keys\n", array_len); } #define NUMBER_PORT_USED 4 static inline void populate_ipv4_many_flow_into_table(const struct rte_hash* h, unsigned int nr_flow) { unsigned i; mask0 = _mm_set_epi32(ALL_32_BITS, ALL_32_BITS, ALL_32_BITS, BIT_8_TO_15); for (i = 0; i < nr_flow; i++) { struct ipv4_l3fwd_route entry; union ipv4_5tuple_host newkey; uint8_t a = (uint8_t) ((i/NUMBER_PORT_USED)%BYTE_VALUE_MAX); uint8_t b = (uint8_t) (((i/NUMBER_PORT_USED)/BYTE_VALUE_MAX)%BYTE_VALUE_MAX); uint8_t c = (uint8_t) ((i/NUMBER_PORT_USED)/(BYTE_VALUE_MAX*BYTE_VALUE_MAX)); /* Create the ipv4 exact match flow */ memset(&entry, 0, sizeof(entry)); switch (i & (NUMBER_PORT_USED -1)) { case 0: entry = ipv4_l3fwd_route_array[0]; entry.key.ip_dst = IPv4(101,c,b,a); break; case 1: entry = ipv4_l3fwd_route_array[1]; entry.key.ip_dst = IPv4(201,c,b,a); break; case 2: entry = ipv4_l3fwd_route_array[2]; entry.key.ip_dst = IPv4(111,c,b,a); break; case 3: entry = ipv4_l3fwd_route_array[3]; entry.key.ip_dst = IPv4(211,c,b,a); break; }; convert_ipv4_5tuple(&entry.key, &newkey); int32_t ret = rte_hash_add_key(h,(void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); } ipv4_l3fwd_out_if[ret] = (uint8_t) entry.if_out; } printf("Hash: Adding 0x%x keys\n", nr_flow); } static inline void populate_ipv6_many_flow_into_table(const struct rte_hash* h, unsigned int nr_flow) { unsigned i; mask1 = _mm_set_epi32(ALL_32_BITS, ALL_32_BITS, ALL_32_BITS, BIT_16_TO_23); mask2 = _mm_set_epi32(0, 0, ALL_32_BITS, ALL_32_BITS); for (i = 0; i < nr_flow; i++) { struct ipv6_l3fwd_route entry; union ipv6_5tuple_host newkey; uint8_t a = (uint8_t) ((i/NUMBER_PORT_USED)%BYTE_VALUE_MAX); uint8_t b = (uint8_t) (((i/NUMBER_PORT_USED)/BYTE_VALUE_MAX)%BYTE_VALUE_MAX); uint8_t c = (uint8_t) ((i/NUMBER_PORT_USED)/(BYTE_VALUE_MAX*BYTE_VALUE_MAX)); /* Create the ipv6 exact match flow */ memset(&entry, 0, sizeof(entry)); switch (i & (NUMBER_PORT_USED - 1)) { case 0: entry = ipv6_l3fwd_route_array[0]; break; case 1: entry = ipv6_l3fwd_route_array[1]; break; case 2: entry = ipv6_l3fwd_route_array[2]; break; case 3: entry = ipv6_l3fwd_route_array[3]; break; }; entry.key.ip_dst[13] = c; entry.key.ip_dst[14] = b; entry.key.ip_dst[15] = a; convert_ipv6_5tuple(&entry.key, &newkey); int32_t ret = rte_hash_add_key(h,(void *) &newkey); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i); } ipv6_l3fwd_out_if[ret] = (uint8_t) entry.if_out; } printf("Hash: Adding 0x%x keys\n", nr_flow); } static void setup_hash(int socketid) { struct rte_hash_parameters ipv4_l3fwd_hash_params = { .name = NULL, .entries = L3FWD_HASH_ENTRIES, .key_len = sizeof(union ipv4_5tuple_host), .hash_func = ipv4_hash_crc, .hash_func_init_val = 0, }; struct rte_hash_parameters ipv6_l3fwd_hash_params = { .name = NULL, .entries = L3FWD_HASH_ENTRIES, .key_len = sizeof(union ipv6_5tuple_host), .hash_func = ipv6_hash_crc, .hash_func_init_val = 0, }; char s[64]; /* create ipv4 hash */ snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid); ipv4_l3fwd_hash_params.name = s; ipv4_l3fwd_hash_params.socket_id = socketid; ipv4_l3fwd_lookup_struct[socketid] = rte_hash_create(&ipv4_l3fwd_hash_params); if (ipv4_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " "socket %d\n", socketid); /* create ipv6 hash */ snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid); ipv6_l3fwd_hash_params.name = s; ipv6_l3fwd_hash_params.socket_id = socketid; ipv6_l3fwd_lookup_struct[socketid] = rte_hash_create(&ipv6_l3fwd_hash_params); if (ipv6_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " "socket %d\n", socketid); if (hash_entry_number != HASH_ENTRY_NUMBER_DEFAULT) { /* For testing hash matching with a large number of flows we * generate millions of IP 5-tuples with an incremented dst * address to initialize the hash table. */ if (ipv6 == 0) { /* populate the ipv4 hash */ populate_ipv4_many_flow_into_table( ipv4_l3fwd_lookup_struct[socketid], hash_entry_number); } else { /* populate the ipv6 hash */ populate_ipv6_many_flow_into_table( ipv6_l3fwd_lookup_struct[socketid], hash_entry_number); } } else { /* Use data in ipv4/ipv6 l3fwd lookup table directly to initialize the hash table */ if (ipv6 == 0) { /* populate the ipv4 hash */ populate_ipv4_few_flow_into_table(ipv4_l3fwd_lookup_struct[socketid]); } else { /* populate the ipv6 hash */ populate_ipv6_few_flow_into_table(ipv6_l3fwd_lookup_struct[socketid]); } } } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static void setup_lpm(int socketid) { struct rte_lpm6_config config; unsigned i; int ret; char s[64]; /* create the LPM table */ snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid); ipv4_l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid, IPV4_L3FWD_LPM_MAX_RULES, 0); if (ipv4_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" " on socket %d\n", socketid); /* populate the LPM table */ for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { /* skip unused ports */ if ((1 << ipv4_l3fwd_route_array[i].if_out & enabled_port_mask) == 0) continue; ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid], ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " "l3fwd LPM table on socket %d\n", i, socketid); } printf("LPM: Adding route 0x%08x / %d (%d)\n", (unsigned)ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); } /* create the LPM6 table */ snprintf(s, sizeof(s), "IPV6_L3FWD_LPM_%d", socketid); config.max_rules = IPV6_L3FWD_LPM_MAX_RULES; config.number_tbl8s = IPV6_L3FWD_LPM_NUMBER_TBL8S; config.flags = 0; ipv6_l3fwd_lookup_struct[socketid] = rte_lpm6_create(s, socketid, &config); if (ipv6_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" " on socket %d\n", socketid); /* populate the LPM table */ for (i = 0; i < IPV6_L3FWD_NUM_ROUTES; i++) { /* skip unused ports */ if ((1 << ipv6_l3fwd_route_array[i].if_out & enabled_port_mask) == 0) continue; ret = rte_lpm6_add(ipv6_l3fwd_lookup_struct[socketid], ipv6_l3fwd_route_array[i].ip, ipv6_l3fwd_route_array[i].depth, ipv6_l3fwd_route_array[i].if_out); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " "l3fwd LPM table on socket %d\n", i, socketid); } printf("LPM: Adding route %s / %d (%d)\n", "IPV6", ipv6_l3fwd_route_array[i].depth, ipv6_l3fwd_route_array[i].if_out); } } #endif static int init_mem(unsigned nb_mbuf) { struct lcore_conf *qconf; int socketid; unsigned lcore_id; char s[64]; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = rte_lcore_to_socket_id(lcore_id); else socketid = 0; if (socketid >= NB_SOCKETS) { rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", socketid, lcore_id, NB_SOCKETS); } if (pktmbuf_pool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (pktmbuf_pool[socketid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); else printf("Allocated mbuf pool on socket %d\n", socketid); #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) setup_lpm(socketid); #else setup_hash(socketid); #endif } qconf = &lcore_conf[lcore_id]; qconf->ipv4_lookup_struct = ipv4_l3fwd_lookup_struct[socketid]; qconf->ipv6_lookup_struct = ipv6_l3fwd_lookup_struct[socketid]; } return 0; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcore_id; uint32_t n_tx_queue, nb_lcores; uint8_t portid, nb_rx_queue, queue, socketid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { dest_eth_addr[portid] = ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; } /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); ret = init_lcore_rx_queues(); if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; if (check_port_config(nb_ports) < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } /* init port */ printf("Initializing port %d ... ", portid ); fflush(stdout); nb_rx_queue = get_port_n_rx_queues(portid); n_tx_queue = nb_lcores; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)n_tx_queue ); ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); print_ethaddr("Destination:", (const struct ether_addr *)&dest_eth_addr[portid]); printf(", "); /* * prepare src MACs for each port. */ ether_addr_copy(&ports_eth_addr[portid], (struct ether_addr *)(val_eth + portid) + 1); /* init memory */ ret = init_mem(NB_MBUF); if (ret < 0) rte_exit(EXIT_FAILURE, "init_mem failed\n"); /* init one TX queue per couple (lcore,port) */ queueid = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; if (port_conf.rxmode.jumbo_frame) txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; queueid++; } printf("\n"); } for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; qconf = &lcore_conf[lcore_id]; printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); fflush(stdout); /* init RX queues */ for(queue = 0; queue < qconf->n_rx_queue; ++queue) { portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; if (numa_on) socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, NULL, pktmbuf_pool[socketid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," "port=%d\n", ret, portid); } } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); /* * If enabled, put device in promiscuous mode. * This allows IO forwarding mode to forward packets * to itself through 2 cross-connected ports of the * target machine. */ if (promiscuous_on) rte_eth_promiscuous_enable(portid); } check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l3fwd-acl/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l3fwd-acl # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l3fwd-acl/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DO_RFC_1812_CHECKS #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 #define MAX_JUMBO_PKT_LEN 9600 #define MEMPOOL_CACHE_SIZE 256 /* * This expression is used to calculate the number of mbufs needed * depending on user input, taking into account memory for rx and tx hardware * rings, cache per lcore and mtable per port per lcore. * RTE_MAX is used to ensure that NB_MBUF never goes below a * minimum value of 8192 */ #define NB_MBUF RTE_MAX(\ (nb_ports * nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT + \ nb_ports * nb_lcores * MAX_PKT_BURST + \ nb_ports * n_tx_queue * RTE_TEST_TX_DESC_DEFAULT + \ nb_lcores * MEMPOOL_CACHE_SIZE), \ (unsigned)8192) #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 8 /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t enabled_port_mask; static int promiscuous_on; /**< Ports set in promiscuous mode off by default. */ static int numa_on = 1; /**< NUMA is enabled by default. */ struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; struct lcore_rx_queue { uint8_t port_id; uint8_t queue_id; } __rte_cache_aligned; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS #define MAX_RX_QUEUE_PER_PORT 128 #define MAX_LCORE_PARAMS 1024 struct lcore_params { uint8_t port_id; uint8_t queue_id; uint8_t lcore_id; } __rte_cache_aligned; static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, }; static struct lcore_params *lcore_params = lcore_params_array_default; static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP | ETH_RSS_SCTP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; /***********************start of ACL part******************************/ #ifdef DO_RFC_1812_CHECKS static inline int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len); #endif static inline int send_single_packet(struct rte_mbuf *m, uint8_t port); #define MAX_ACL_RULE_NUM 100000 #define DEFAULT_MAX_CATEGORIES 1 #define L3FWD_ACL_IPV4_NAME "l3fwd-acl-ipv4" #define L3FWD_ACL_IPV6_NAME "l3fwd-acl-ipv6" #define ACL_LEAD_CHAR ('@') #define ROUTE_LEAD_CHAR ('R') #define COMMENT_LEAD_CHAR ('#') #define OPTION_CONFIG "config" #define OPTION_NONUMA "no-numa" #define OPTION_ENBJMO "enable-jumbo" #define OPTION_RULE_IPV4 "rule_ipv4" #define OPTION_RULE_IPV6 "rule_ipv6" #define OPTION_SCALAR "scalar" #define ACL_DENY_SIGNATURE 0xf0000000 #define RTE_LOGTYPE_L3FWDACL RTE_LOGTYPE_USER3 #define acl_log(format, ...) RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__) #define uint32_t_to_char(ip, a, b, c, d) do {\ *a = (unsigned char)(ip >> 24 & 0xff);\ *b = (unsigned char)(ip >> 16 & 0xff);\ *c = (unsigned char)(ip >> 8 & 0xff);\ *d = (unsigned char)(ip & 0xff);\ } while (0) #define OFF_ETHHEAD (sizeof(struct ether_hdr)) #define OFF_IPV42PROTO (offsetof(struct ipv4_hdr, next_proto_id)) #define OFF_IPV62PROTO (offsetof(struct ipv6_hdr, proto)) #define MBUF_IPV4_2PROTO(m) \ rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO) #define MBUF_IPV6_2PROTO(m) \ rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO) #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ unsigned long val; \ char *end; \ errno = 0; \ val = strtoul((in), &end, (base)); \ if (errno != 0 || end[0] != (dlm) || val > (lim)) \ return -EINVAL; \ (fd) = (typeof(fd))val; \ (in) = end + 1; \ } while (0) /* * ACL rules should have higher priorities than route ones to ensure ACL rule * always be found when input packets have multi-matches in the database. * A exception case is performance measure, which can define route rules with * higher priority and route rules will always be returned in each lookup. * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to * RTE_ACL_MAX_PRIORITY for route entries in performance measure */ #define ACL_RULE_PRIORITY_MAX 0x10000000 /* * Forward port info save in ACL lib starts from 1 * since ACL assume 0 is invalid. * So, need add 1 when saving and minus 1 when forwarding packets. */ #define FWD_PORT_SHIFT 1 /* * Rule and trace formats definitions. */ enum { PROTO_FIELD_IPV4, SRC_FIELD_IPV4, DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, NUM_FIELDS_IPV4 }; struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PROTO, .offset = 0, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_SRC, .offset = offsetof(struct ipv4_hdr, src_addr) - offsetof(struct ipv4_hdr, next_proto_id), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_DST, .offset = offsetof(struct ipv4_hdr, dst_addr) - offsetof(struct ipv4_hdr, next_proto_id), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PORTS, .offset = sizeof(struct ipv4_hdr) - offsetof(struct ipv4_hdr, next_proto_id), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV4, .input_index = RTE_ACL_IPV4VLAN_PORTS, .offset = sizeof(struct ipv4_hdr) - offsetof(struct ipv4_hdr, next_proto_id) + sizeof(uint16_t), }, }; #define IPV6_ADDR_LEN 16 #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) #define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) enum { PROTO_FIELD_IPV6, SRC1_FIELD_IPV6, SRC2_FIELD_IPV6, SRC3_FIELD_IPV6, SRC4_FIELD_IPV6, DST1_FIELD_IPV6, DST2_FIELD_IPV6, DST3_FIELD_IPV6, DST4_FIELD_IPV6, SRCP_FIELD_IPV6, DSTP_FIELD_IPV6, NUM_FIELDS_IPV6 }; struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = PROTO_FIELD_IPV6, .input_index = PROTO_FIELD_IPV6, .offset = 0, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC1_FIELD_IPV6, .input_index = SRC1_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, src_addr) - offsetof(struct ipv6_hdr, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC2_FIELD_IPV6, .input_index = SRC2_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, src_addr) - offsetof(struct ipv6_hdr, proto) + sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC3_FIELD_IPV6, .input_index = SRC3_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, src_addr) - offsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = SRC4_FIELD_IPV6, .input_index = SRC4_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, src_addr) - offsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST1_FIELD_IPV6, .input_index = DST1_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, dst_addr) - offsetof(struct ipv6_hdr, proto), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST2_FIELD_IPV6, .input_index = DST2_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, dst_addr) - offsetof(struct ipv6_hdr, proto) + sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST3_FIELD_IPV6, .input_index = DST3_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, dst_addr) - offsetof(struct ipv6_hdr, proto) + 2 * sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = DST4_FIELD_IPV6, .input_index = DST4_FIELD_IPV6, .offset = offsetof(struct ipv6_hdr, dst_addr) - offsetof(struct ipv6_hdr, proto) + 3 * sizeof(uint32_t), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = SRCP_FIELD_IPV6, .input_index = SRCP_FIELD_IPV6, .offset = sizeof(struct ipv6_hdr) - offsetof(struct ipv6_hdr, proto), }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = DSTP_FIELD_IPV6, .input_index = SRCP_FIELD_IPV6, .offset = sizeof(struct ipv6_hdr) - offsetof(struct ipv6_hdr, proto) + sizeof(uint16_t), }, }; enum { CB_FLD_SRC_ADDR, CB_FLD_DST_ADDR, CB_FLD_SRC_PORT_LOW, CB_FLD_SRC_PORT_DLM, CB_FLD_SRC_PORT_HIGH, CB_FLD_DST_PORT_LOW, CB_FLD_DST_PORT_DLM, CB_FLD_DST_PORT_HIGH, CB_FLD_PROTO, CB_FLD_USERDATA, CB_FLD_NUM, }; RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs)); RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs)); struct acl_search_t { const uint8_t *data_ipv4[MAX_PKT_BURST]; struct rte_mbuf *m_ipv4[MAX_PKT_BURST]; uint32_t res_ipv4[MAX_PKT_BURST]; int num_ipv4; const uint8_t *data_ipv6[MAX_PKT_BURST]; struct rte_mbuf *m_ipv6[MAX_PKT_BURST]; uint32_t res_ipv6[MAX_PKT_BURST]; int num_ipv6; }; static struct { char mapped[NB_SOCKETS]; struct rte_acl_ctx *acx_ipv4[NB_SOCKETS]; struct rte_acl_ctx *acx_ipv6[NB_SOCKETS]; #ifdef L3FWDACL_DEBUG struct acl4_rule *rule_ipv4; struct acl6_rule *rule_ipv6; #endif } acl_config; static struct{ const char *rule_ipv4_name; const char *rule_ipv6_name; int scalar; } parm_config; const char cb_port_delim[] = ":"; static inline void print_one_ipv4_rule(struct acl4_rule *rule, int extra) { unsigned char a, b, c, d; uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32, &a, &b, &c, &d); printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d, rule->field[SRC_FIELD_IPV4].mask_range.u32); uint32_t_to_char(rule->field[DST_FIELD_IPV4].value.u32, &a, &b, &c, &d); printf("%hhu.%hhu.%hhu.%hhu/%u ", a, b, c, d, rule->field[DST_FIELD_IPV4].mask_range.u32); printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", rule->field[SRCP_FIELD_IPV4].value.u16, rule->field[SRCP_FIELD_IPV4].mask_range.u16, rule->field[DSTP_FIELD_IPV4].value.u16, rule->field[DSTP_FIELD_IPV4].mask_range.u16, rule->field[PROTO_FIELD_IPV4].value.u8, rule->field[PROTO_FIELD_IPV4].mask_range.u8); if (extra) printf("0x%x-0x%x-0x%x ", rule->data.category_mask, rule->data.priority, rule->data.userdata); } static inline void print_one_ipv6_rule(struct acl6_rule *rule, int extra) { unsigned char a, b, c, d; uint32_t_to_char(rule->field[SRC1_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf("%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[SRC2_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[SRC3_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[SRC4_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, rule->field[SRC1_FIELD_IPV6].mask_range.u32 + rule->field[SRC2_FIELD_IPV6].mask_range.u32 + rule->field[SRC3_FIELD_IPV6].mask_range.u32 + rule->field[SRC4_FIELD_IPV6].mask_range.u32); uint32_t_to_char(rule->field[DST1_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf("%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[DST2_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[DST3_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); uint32_t_to_char(rule->field[DST4_FIELD_IPV6].value.u32, &a, &b, &c, &d); printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, rule->field[DST1_FIELD_IPV6].mask_range.u32 + rule->field[DST2_FIELD_IPV6].mask_range.u32 + rule->field[DST3_FIELD_IPV6].mask_range.u32 + rule->field[DST4_FIELD_IPV6].mask_range.u32); printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", rule->field[SRCP_FIELD_IPV6].value.u16, rule->field[SRCP_FIELD_IPV6].mask_range.u16, rule->field[DSTP_FIELD_IPV6].value.u16, rule->field[DSTP_FIELD_IPV6].mask_range.u16, rule->field[PROTO_FIELD_IPV6].value.u8, rule->field[PROTO_FIELD_IPV6].mask_range.u8); if (extra) printf("0x%x-0x%x-0x%x ", rule->data.category_mask, rule->data.priority, rule->data.userdata); } /* Bypass comment and empty lines */ static inline int is_bypass_line(char *buff) { int i = 0; /* comment line */ if (buff[0] == COMMENT_LEAD_CHAR) return 1; /* empty line */ while (buff[i] != '\0') { if (!isspace(buff[i])) return 0; i++; } return 1; } #ifdef L3FWDACL_DEBUG static inline void dump_acl4_rule(struct rte_mbuf *m, uint32_t sig) { uint32_t offset = sig & ~ACL_DENY_SIGNATURE; unsigned char a, b, c, d; struct ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, sizeof(struct ether_hdr)); uint32_t_to_char(rte_bswap32(ipv4_hdr->src_addr), &a, &b, &c, &d); printf("Packet Src:%hhu.%hhu.%hhu.%hhu ", a, b, c, d); uint32_t_to_char(rte_bswap32(ipv4_hdr->dst_addr), &a, &b, &c, &d); printf("Dst:%hhu.%hhu.%hhu.%hhu ", a, b, c, d); printf("Src port:%hu,Dst port:%hu ", rte_bswap16(*(uint16_t *)(ipv4_hdr + 1)), rte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1))); printf("hit ACL %d - ", offset); print_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1); printf("\n\n"); } static inline void dump_acl6_rule(struct rte_mbuf *m, uint32_t sig) { unsigned i; uint32_t offset = sig & ~ACL_DENY_SIGNATURE; struct ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, sizeof(struct ether_hdr)); printf("Packet Src"); for (i = 0; i < RTE_DIM(ipv6_hdr->src_addr); i += sizeof(uint16_t)) printf(":%.2x%.2x", ipv6_hdr->src_addr[i], ipv6_hdr->src_addr[i + 1]); printf("\nDst"); for (i = 0; i < RTE_DIM(ipv6_hdr->dst_addr); i += sizeof(uint16_t)) printf(":%.2x%.2x", ipv6_hdr->dst_addr[i], ipv6_hdr->dst_addr[i + 1]); printf("\nSrc port:%hu,Dst port:%hu ", rte_bswap16(*(uint16_t *)(ipv6_hdr + 1)), rte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1))); printf("hit ACL %d - ", offset); print_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1); printf("\n\n"); } #endif /* L3FWDACL_DEBUG */ static inline void dump_ipv4_rules(struct acl4_rule *rule, int num, int extra) { int i; for (i = 0; i < num; i++, rule++) { printf("\t%d:", i + 1); print_one_ipv4_rule(rule, extra); printf("\n"); } } static inline void dump_ipv6_rules(struct acl6_rule *rule, int num, int extra) { int i; for (i = 0; i < num; i++, rule++) { printf("\t%d:", i + 1); print_one_ipv6_rule(rule, extra); printf("\n"); } } #ifdef DO_RFC_1812_CHECKS static inline void prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl, int index) { struct ipv4_hdr *ipv4_hdr; struct rte_mbuf *pkt = pkts_in[index]; #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { #else int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR); if (type == PKT_RX_IPV4_HDR) { #endif ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *, sizeof(struct ether_hdr)); /* Check to make sure the packet is valid (RFC1812) */ if (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) { /* Update time to live and header checksum */ --(ipv4_hdr->time_to_live); ++(ipv4_hdr->hdr_checksum); /* Fill acl structure */ acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt); acl->m_ipv4[(acl->num_ipv4)++] = pkt; } else { /* Not a valid IPv4 packet */ rte_pktmbuf_free(pkt); } #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { #else } else if (type == PKT_RX_IPV6_HDR) { #endif /* Fill acl structure */ acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt); acl->m_ipv6[(acl->num_ipv6)++] = pkt; } else { /* Unknown type, drop the packet */ rte_pktmbuf_free(pkt); } } #else static inline void prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl, int index) { struct rte_mbuf *pkt = pkts_in[index]; #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) { #else int type = pkt->ol_flags & (PKT_RX_IPV4_HDR | PKT_RX_IPV6_HDR); if (type == PKT_RX_IPV4_HDR) { #endif /* Fill acl structure */ acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt); acl->m_ipv4[(acl->num_ipv4)++] = pkt; #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) { #else } else if (type == PKT_RX_IPV6_HDR) { #endif /* Fill acl structure */ acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt); acl->m_ipv6[(acl->num_ipv6)++] = pkt; } else { /* Unknown type, drop the packet */ rte_pktmbuf_free(pkt); } } #endif /* DO_RFC_1812_CHECKS */ static inline void prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_search_t *acl, int nb_rx) { int i; acl->num_ipv4 = 0; acl->num_ipv6 = 0; /* Prefetch first packets */ for (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_in[i], void *)); } for (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_in[ i + PREFETCH_OFFSET], void *)); prepare_one_packet(pkts_in, acl, i); } /* Process left packets */ for (; i < nb_rx; i++) prepare_one_packet(pkts_in, acl, i); } static inline void send_one_packet(struct rte_mbuf *m, uint32_t res) { if (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) { /* forward packets */ send_single_packet(m, (uint8_t)(res - FWD_PORT_SHIFT)); } else{ /* in the ACL list, drop it */ #ifdef L3FWDACL_DEBUG if ((res & ACL_DENY_SIGNATURE) != 0) { #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) dump_acl4_rule(m, res); else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) dump_acl6_rule(m, res); #else if (m->ol_flags & PKT_RX_IPV4_HDR) dump_acl4_rule(m, res); else dump_acl6_rule(m, res); #endif /* RTE_NEXT_ABI */ } #endif rte_pktmbuf_free(m); } } static inline void send_packets(struct rte_mbuf **m, uint32_t *res, int num) { int i; /* Prefetch first packets */ for (i = 0; i < PREFETCH_OFFSET && i < num; i++) { rte_prefetch0(rte_pktmbuf_mtod( m[i], void *)); } for (i = 0; i < (num - PREFETCH_OFFSET); i++) { rte_prefetch0(rte_pktmbuf_mtod(m[ i + PREFETCH_OFFSET], void *)); send_one_packet(m[i], res[i]); } /* Process left packets */ for (; i < num; i++) send_one_packet(m[i], res[i]); } /* * Parses IPV6 address, exepcts the following format: * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit). */ static int parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32], char dlm) { uint32_t addr[IPV6_ADDR_U16]; GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':'); GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm); *end = in; v[0] = (addr[0] << 16) + addr[1]; v[1] = (addr[2] << 16) + addr[3]; v[2] = (addr[4] << 16) + addr[5]; v[3] = (addr[6] << 16) + addr[7]; return 0; } static int parse_ipv6_net(const char *in, struct rte_acl_field field[4]) { int32_t rc; const char *mp; uint32_t i, m, v[4]; const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; /* get address. */ rc = parse_ipv6_addr(in, &mp, v, '/'); if (rc != 0) return rc; /* get mask. */ GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); /* put all together. */ for (i = 0; i != RTE_DIM(v); i++) { if (m >= (i + 1) * nbu32) field[i].mask_range.u32 = nbu32; else field[i].mask_range.u32 = m > (i * nbu32) ? m - (i * 32) : 0; field[i].value.u32 = v[i]; } return 0; } static int parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata) { int i, rc; char *s, *sp, *in[CB_FLD_NUM]; static const char *dlm = " \t\n"; int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; s = str; for (i = 0; i != dim; i++, s = NULL) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; } rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); if (rc != 0) { acl_log("failed to read source address/mask: %s\n", in[CB_FLD_SRC_ADDR]); return rc; } rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); if (rc != 0) { acl_log("failed to read destination address/mask: %s\n", in[CB_FLD_DST_ADDR]); return rc; } /* source port. */ GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], v->field[SRCP_FIELD_IPV6].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], v->field[SRCP_FIELD_IPV6].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; /* destination port. */ GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], v->field[DSTP_FIELD_IPV6].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], v->field[DSTP_FIELD_IPV6].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; if (v->field[SRCP_FIELD_IPV6].mask_range.u16 < v->field[SRCP_FIELD_IPV6].value.u16 || v->field[DSTP_FIELD_IPV6].mask_range.u16 < v->field[DSTP_FIELD_IPV6].value.u16) return -EINVAL; GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8, 0, UINT8_MAX, '/'); GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8, 0, UINT8_MAX, 0); if (has_userdata) GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0, UINT32_MAX, 0); return 0; } /* * Parse ClassBench rules file. * Expected format: * '@''/' \ * '/' \ * ":" \ * ":" \ * '/' */ static int parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) { uint8_t a, b, c, d, m; GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); addr[0] = IPv4(a, b, c, d); mask_len[0] = m; return 0; } static int parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata) { int i, rc; char *s, *sp, *in[CB_FLD_NUM]; static const char *dlm = " \t\n"; int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA; s = str; for (i = 0; i != dim; i++, s = NULL) { in[i] = strtok_r(s, dlm, &sp); if (in[i] == NULL) return -EINVAL; } rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], &v->field[SRC_FIELD_IPV4].value.u32, &v->field[SRC_FIELD_IPV4].mask_range.u32); if (rc != 0) { acl_log("failed to read source address/mask: %s\n", in[CB_FLD_SRC_ADDR]); return rc; } rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], &v->field[DST_FIELD_IPV4].value.u32, &v->field[DST_FIELD_IPV4].mask_range.u32); if (rc != 0) { acl_log("failed to read destination address/mask: %s\n", in[CB_FLD_DST_ADDR]); return rc; } GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], v->field[SRCP_FIELD_IPV4].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], v->field[SRCP_FIELD_IPV4].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], v->field[DSTP_FIELD_IPV4].value.u16, 0, UINT16_MAX, 0); GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], v->field[DSTP_FIELD_IPV4].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; if (v->field[SRCP_FIELD_IPV4].mask_range.u16 < v->field[SRCP_FIELD_IPV4].value.u16 || v->field[DSTP_FIELD_IPV4].mask_range.u16 < v->field[DSTP_FIELD_IPV4].value.u16) return -EINVAL; GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8, 0, UINT8_MAX, '/'); GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8, 0, UINT8_MAX, 0); if (has_userdata) GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0, UINT32_MAX, 0); return 0; } static int add_rules(const char *rule_path, struct rte_acl_rule **proute_base, unsigned int *proute_num, struct rte_acl_rule **pacl_base, unsigned int *pacl_num, uint32_t rule_size, int (*parser)(char *, struct rte_acl_rule*, int)) { uint8_t *acl_rules, *route_rules; struct rte_acl_rule *next; unsigned int acl_num = 0, route_num = 0, total_num = 0; unsigned int acl_cnt = 0, route_cnt = 0; char buff[LINE_MAX]; FILE *fh = fopen(rule_path, "rb"); unsigned int i = 0; if (fh == NULL) rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__, rule_path); while ((fgets(buff, LINE_MAX, fh) != NULL)) { if (buff[0] == ROUTE_LEAD_CHAR) route_num++; else if (buff[0] == ACL_LEAD_CHAR) acl_num++; } if (0 == route_num) rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n", rule_path); fseek(fh, 0, SEEK_SET); acl_rules = calloc(acl_num, rule_size); if (NULL == acl_rules) rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", __func__); route_rules = calloc(route_num, rule_size); if (NULL == route_rules) rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n", __func__); i = 0; while (fgets(buff, LINE_MAX, fh) != NULL) { i++; if (is_bypass_line(buff)) continue; char s = buff[0]; /* Route entry */ if (s == ROUTE_LEAD_CHAR) next = (struct rte_acl_rule *)(route_rules + route_cnt * rule_size); /* ACL entry */ else if (s == ACL_LEAD_CHAR) next = (struct rte_acl_rule *)(acl_rules + acl_cnt * rule_size); /* Illegal line */ else rte_exit(EXIT_FAILURE, "%s Line %u: should start with leading " "char %c or %c\n", rule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR); if (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0) rte_exit(EXIT_FAILURE, "%s Line %u: parse rules error\n", rule_path, i); if (s == ROUTE_LEAD_CHAR) { /* Check the forwarding port number */ if ((enabled_port_mask & (1 << next->data.userdata)) == 0) rte_exit(EXIT_FAILURE, "%s Line %u: fwd number illegal:%u\n", rule_path, i, next->data.userdata); next->data.userdata += FWD_PORT_SHIFT; route_cnt++; } else { next->data.userdata = ACL_DENY_SIGNATURE + acl_cnt; acl_cnt++; } next->data.priority = RTE_ACL_MAX_PRIORITY - total_num; next->data.category_mask = -1; total_num++; } fclose(fh); *pacl_base = (struct rte_acl_rule *)acl_rules; *pacl_num = acl_num; *proute_base = (struct rte_acl_rule *)route_rules; *proute_num = route_cnt; return 0; } static void dump_acl_config(void) { printf("ACL option are:\n"); printf(OPTION_RULE_IPV4": %s\n", parm_config.rule_ipv4_name); printf(OPTION_RULE_IPV6": %s\n", parm_config.rule_ipv6_name); printf(OPTION_SCALAR": %d\n", parm_config.scalar); } static int check_acl_config(void) { if (parm_config.rule_ipv4_name == NULL) { acl_log("ACL IPv4 rule file not specified\n"); return -1; } else if (parm_config.rule_ipv6_name == NULL) { acl_log("ACL IPv6 rule file not specified\n"); return -1; } return 0; } static struct rte_acl_ctx* setup_acl(struct rte_acl_rule *route_base, struct rte_acl_rule *acl_base, unsigned int route_num, unsigned int acl_num, int ipv6, int socketid) { char name[PATH_MAX]; struct rte_acl_param acl_param; struct rte_acl_config acl_build_param; struct rte_acl_ctx *context; int dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs); /* Create ACL contexts */ snprintf(name, sizeof(name), "%s%d", ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME, socketid); acl_param.name = name; acl_param.socket_id = socketid; acl_param.rule_size = RTE_ACL_RULE_SZ(dim); acl_param.max_rule_num = MAX_ACL_RULE_NUM; if ((context = rte_acl_create(&acl_param)) == NULL) rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); if (parm_config.scalar && rte_acl_set_ctx_classify(context, RTE_ACL_CLASSIFY_SCALAR) != 0) rte_exit(EXIT_FAILURE, "Failed to setup classify method for ACL context\n"); if (rte_acl_add_rules(context, route_base, route_num) < 0) rte_exit(EXIT_FAILURE, "add rules failed\n"); if (rte_acl_add_rules(context, acl_base, acl_num) < 0) rte_exit(EXIT_FAILURE, "add rules failed\n"); /* Perform builds */ memset(&acl_build_param, 0, sizeof(acl_build_param)); acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; acl_build_param.num_fields = dim; memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs, ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs)); if (rte_acl_build(context, &acl_build_param) != 0) rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); rte_acl_dump(context); return context; } static int app_acl_init(void) { unsigned lcore_id; unsigned int i; int socketid; struct rte_acl_rule *acl_base_ipv4, *route_base_ipv4, *acl_base_ipv6, *route_base_ipv6; unsigned int acl_num_ipv4 = 0, route_num_ipv4 = 0, acl_num_ipv6 = 0, route_num_ipv6 = 0; if (check_acl_config() != 0) rte_exit(EXIT_FAILURE, "Failed to get valid ACL options\n"); dump_acl_config(); /* Load rules from the input file */ if (add_rules(parm_config.rule_ipv4_name, &route_base_ipv4, &route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4, sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0) rte_exit(EXIT_FAILURE, "Failed to add rules\n"); acl_log("IPv4 Route entries %u:\n", route_num_ipv4); dump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1); acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4); dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1); if (add_rules(parm_config.rule_ipv6_name, &route_base_ipv6, &route_num_ipv6, &acl_base_ipv6, &acl_num_ipv6, sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0) rte_exit(EXIT_FAILURE, "Failed to add rules\n"); acl_log("IPv6 Route entries %u:\n", route_num_ipv6); dump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1); acl_log("IPv6 ACL entries %u:\n", acl_num_ipv6); dump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1); memset(&acl_config, 0, sizeof(acl_config)); /* Check sockets a context should be created on */ if (!numa_on) acl_config.mapped[0] = 1; else { for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; socketid = rte_lcore_to_socket_id(lcore_id); if (socketid >= NB_SOCKETS) { acl_log("Socket %d of lcore %u is out " "of range %d\n", socketid, lcore_id, NB_SOCKETS); free(route_base_ipv4); free(route_base_ipv6); free(acl_base_ipv4); free(acl_base_ipv6); return -1; } acl_config.mapped[socketid] = 1; } } for (i = 0; i < NB_SOCKETS; i++) { if (acl_config.mapped[i]) { acl_config.acx_ipv4[i] = setup_acl(route_base_ipv4, acl_base_ipv4, route_num_ipv4, acl_num_ipv4, 0, i); acl_config.acx_ipv6[i] = setup_acl(route_base_ipv6, acl_base_ipv6, route_num_ipv6, acl_num_ipv6, 1, i); } } free(route_base_ipv4); free(route_base_ipv6); #ifdef L3FWDACL_DEBUG acl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4; acl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6; #else free(acl_base_ipv4); free(acl_base_ipv6); #endif return 0; } /***********************end of ACL part******************************/ struct lcore_conf { uint16_t n_rx_queue; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) { struct rte_mbuf **m_table; int ret; uint16_t queueid; queueid = qconf->tx_queue_id[port]; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, queueid, m_table, n); if (unlikely(ret < n)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { uint32_t lcore_id; uint16_t len; struct lcore_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } #ifdef DO_RFC_1812_CHECKS static inline int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len) { /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ /* * 1. The packet length reported by the Link Layer must be large * enough to hold the minimum length legal IP datagram (20 bytes). */ if (link_len < sizeof(struct ipv4_hdr)) return -1; /* 2. The IP checksum must be correct. */ /* this is checked in H/W */ /* * 3. The IP version number must be 4. If the version number is not 4 * then the packet may be another version of IP, such as IPng or * ST-II. */ if (((pkt->version_ihl) >> 4) != 4) return -3; /* * 4. The IP header length field must be large enough to hold the * minimum length legal IP datagram (20 bytes = 5 words). */ if ((pkt->version_ihl & 0xf) < 5) return -4; /* * 5. The IP total length field must be large enough to hold the IP * datagram header, whose length is specified in the IP header length * field. */ if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr)) return -5; return 0; } #endif /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; int i, nb_rx; uint8_t portid, queueid; struct lcore_conf *qconf; int socketid; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; socketid = rte_lcore_to_socket_id(lcore_id); if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; RTE_LOG(INFO, L3FWD, " -- lcoreid=%u portid=%hhu rxqueueid=%hhu\n", lcore_id, portid, queueid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; send_burst(&lcore_conf[lcore_id], qconf->tx_mbufs[portid].len, portid); qconf->tx_mbufs[portid].len = 0; } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; ++i) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); if (nb_rx > 0) { struct acl_search_t acl_search; prepare_acl_parameter(pkts_burst, &acl_search, nb_rx); if (acl_search.num_ipv4) { rte_acl_classify( acl_config.acx_ipv4[socketid], acl_search.data_ipv4, acl_search.res_ipv4, acl_search.num_ipv4, DEFAULT_MAX_CATEGORIES); send_packets(acl_search.m_ipv4, acl_search.res_ipv4, acl_search.num_ipv4); } if (acl_search.num_ipv6) { rte_acl_classify( acl_config.acx_ipv6[socketid], acl_search.data_ipv6, acl_search.res_ipv6, acl_search.num_ipv6, DEFAULT_MAX_CATEGORIES); send_packets(acl_search.m_ipv6, acl_search.res_ipv6, acl_search.num_ipv6); } } } } } static int check_lcore_params(void) { uint8_t queue, lcore; uint16_t i; int socketid; for (i = 0; i < nb_lcore_params; ++i) { queue = lcore_params[i].queue_id; if (queue >= MAX_RX_QUEUE_PER_PORT) { printf("invalid queue number: %hhu\n", queue); return -1; } lcore = lcore_params[i].lcore_id; if (!rte_lcore_is_enabled(lcore)) { printf("error: lcore %hhu is not enabled in " "lcore mask\n", lcore); return -1; } socketid = rte_lcore_to_socket_id(lcore); if (socketid != 0 && numa_on == 0) { printf("warning: lcore %hhu is on socket %d " "with numa off\n", lcore, socketid); } } return 0; } static int check_port_config(const unsigned nb_ports) { unsigned portid; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; if ((enabled_port_mask & (1 << portid)) == 0) { printf("port %u is not enabled in port mask\n", portid); return -1; } if (portid >= nb_ports) { printf("port %u is not present on the board\n", portid); return -1; } } return 0; } static uint8_t get_port_n_rx_queues(const uint8_t port) { int queue = -1; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) queue = lcore_params[i].queue_id; } return (uint8_t)(++queue); } static int init_lcore_rx_queues(void) { uint16_t i, nb_rx_queue; uint8_t lcore; for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; nb_rx_queue = lcore_conf[lcore].n_rx_queue; if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { printf("error: too many queues (%u) for lcore: %u\n", (unsigned)nb_rx_queue + 1, (unsigned)lcore); return -1; } else { lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = lcore_params[i].port_id; lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = lcore_params[i].queue_id; lcore_conf[lcore].n_rx_queue++; } } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK -P" "--"OPTION_RULE_IPV4"=FILE" "--"OPTION_RULE_IPV6"=FILE" " [--"OPTION_CONFIG" (port,queue,lcore)[,(port,queue,lcore]]" " [--"OPTION_ENBJMO" [--max-pkt-len PKTLEN]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -P : enable promiscuous mode\n" " --"OPTION_CONFIG": (port,queue,lcore): " "rx queues configuration\n" " --"OPTION_NONUMA": optional, disable numa awareness\n" " --"OPTION_ENBJMO": enable jumbo frame" " which max packet len is PKTLEN in decimal (64-9600)\n" " --"OPTION_RULE_IPV4"=FILE: specify the ipv4 rules entries " "file. " "Each rule occupy one line. " "2 kinds of rules are supported. " "One is ACL entry at while line leads with character '%c', " "another is route entry at while line leads with " "character '%c'.\n" " --"OPTION_RULE_IPV6"=FILE: specify the ipv6 rules " "entries file.\n" " --"OPTION_SCALAR": Use scalar function to do lookup\n", prgname, ACL_LEAD_CHAR, ROUTE_LEAD_CHAR); } static int parse_max_pkt_len(const char *pktlen) { char *end = NULL; unsigned long len; /* parse decimal string */ len = strtoul(pktlen, &end, 10); if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (len == 0) return -1; return len; } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int parse_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; nb_lcore_params = 0; while ((p = strchr(p0, '(')) != NULL) { ++p; if ((p0 = strchr(p, ')')) == NULL) return -1; size = p0 - p; if (size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++) { errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } if (nb_lcore_params >= MAX_LCORE_PARAMS) { printf("exceeded max number of lcore params: %hu\n", nb_lcore_params); return -1; } lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; ++nb_lcore_params; } lcore_params = lcore_params_array; return 0; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {OPTION_CONFIG, 1, 0, 0}, {OPTION_NONUMA, 0, 0, 0}, {OPTION_ENBJMO, 0, 0, 0}, {OPTION_RULE_IPV4, 1, 0, 0}, {OPTION_RULE_IPV6, 1, 0, 0}, {OPTION_SCALAR, 0, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:P", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; case 'P': printf("Promiscuous mode selected\n"); promiscuous_on = 1; break; /* long options */ case 0: if (!strncmp(lgopts[option_index].name, OPTION_CONFIG, sizeof(OPTION_CONFIG))) { ret = parse_config(optarg); if (ret) { printf("invalid config\n"); print_usage(prgname); return -1; } } if (!strncmp(lgopts[option_index].name, OPTION_NONUMA, sizeof(OPTION_NONUMA))) { printf("numa is disabled\n"); numa_on = 0; } if (!strncmp(lgopts[option_index].name, OPTION_ENBJMO, sizeof(OPTION_ENBJMO))) { struct option lenopts = { "max-pkt-len", required_argument, 0, 0 }; printf("jumbo frame is enabled\n"); port_conf.rxmode.jumbo_frame = 1; /* * if no max-pkt-len set, then use the * default value ETHER_MAX_LEN */ if (0 == getopt_long(argc, argvopt, "", &lenopts, &option_index)) { ret = parse_max_pkt_len(optarg); if ((ret < 64) || (ret > MAX_JUMBO_PKT_LEN)) { printf("invalid packet " "length\n"); print_usage(prgname); return -1; } port_conf.rxmode.max_rx_pkt_len = ret; } printf("set jumbo frame max packet length " "to %u\n", (unsigned int) port_conf.rxmode.max_rx_pkt_len); } if (!strncmp(lgopts[option_index].name, OPTION_RULE_IPV4, sizeof(OPTION_RULE_IPV4))) parm_config.rule_ipv4_name = optarg; if (!strncmp(lgopts[option_index].name, OPTION_RULE_IPV6, sizeof(OPTION_RULE_IPV6))) { parm_config.rule_ipv6_name = optarg; } if (!strncmp(lgopts[option_index].name, OPTION_SCALAR, sizeof(OPTION_SCALAR))) parm_config.scalar = 1; break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } static int init_mem(unsigned nb_mbuf) { int socketid; unsigned lcore_id; char s[64]; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = rte_lcore_to_socket_id(lcore_id); else socketid = 0; if (socketid >= NB_SOCKETS) { rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", socketid, lcore_id, NB_SOCKETS); } if (pktmbuf_pool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (pktmbuf_pool[socketid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); else printf("Allocated mbuf pool on socket %d\n", socketid); } } return 0; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcore_id; uint32_t n_tx_queue, nb_lcores; uint8_t portid, nb_rx_queue, queue, socketid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); ret = init_lcore_rx_queues(); if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; if (check_port_config(nb_ports) < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); /* Add ACL rules and route entries, build trie */ if (app_acl_init() < 0) rte_exit(EXIT_FAILURE, "app_acl_init failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } /* init port */ printf("Initializing port %d ... ", portid); fflush(stdout); nb_rx_queue = get_port_n_rx_queues(portid); n_tx_queue = nb_lcores; if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) n_tx_queue = MAX_TX_QUEUE_PER_PORT; printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)n_tx_queue); ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); /* init memory */ ret = init_mem(NB_MBUF); if (ret < 0) rte_exit(EXIT_FAILURE, "init_mem failed\n"); /* init one TX queue per couple (lcore,port) */ queueid = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = (uint8_t) rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; if (port_conf.rxmode.jumbo_frame) txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; queueid++; } printf("\n"); } for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; qconf = &lcore_conf[lcore_id]; printf("\nInitializing rx queues on lcore %u ... ", lcore_id); fflush(stdout); /* init RX queues */ for (queue = 0; queue < qconf->n_rx_queue; ++queue) { portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; if (numa_on) socketid = (uint8_t) rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, NULL, pktmbuf_pool[socketid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," "port=%d\n", ret, portid); } } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) continue; /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); /* * If enabled, put device in promiscuous mode. * This allows IO forwarding mode to forward packets * to itself through 2 cross-connected ports of the * target machine. */ if (promiscuous_on) rte_eth_promiscuous_enable(portid); } check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l3fwd-power/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l3fwd-power # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l3fwd-power/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_L3FWD_POWER RTE_LOGTYPE_USER1 #define MAX_PKT_BURST 32 #define MIN_ZERO_POLL_COUNT 10 /* around 100ms at 2 Ghz */ #define TIMER_RESOLUTION_CYCLES 200000000ULL /* 100 ms interval */ #define TIMER_NUMBER_PER_SECOND 10 /* 100000 us */ #define SCALING_PERIOD (1000000/TIMER_NUMBER_PER_SECOND) #define SCALING_DOWN_TIME_RATIO_THRESHOLD 0.25 #define APP_LOOKUP_EXACT_MATCH 0 #define APP_LOOKUP_LPM 1 #define DO_RFC_1812_CHECKS #ifndef APP_LOOKUP_METHOD #define APP_LOOKUP_METHOD APP_LOOKUP_LPM #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #include #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) #include #else #error "APP_LOOKUP_METHOD set to incorrect value" #endif #ifndef IPv6_BYTES #define IPv6_BYTES_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"\ "%02x%02x:%02x%02x:%02x%02x:%02x%02x" #define IPv6_BYTES(addr) \ addr[0], addr[1], addr[2], addr[3], \ addr[4], addr[5], addr[6], addr[7], \ addr[8], addr[9], addr[10], addr[11],\ addr[12], addr[13],addr[14], addr[15] #endif #define MAX_JUMBO_PKT_LEN 9600 #define IPV6_ADDR_LEN 16 #define MEMPOOL_CACHE_SIZE 256 /* * This expression is used to calculate the number of mbufs needed depending on * user input, taking into account memory for rx and tx hardware rings, cache * per lcore and mtable per port per lcore. RTE_MAX is used to ensure that * NB_MBUF never goes below a minimum value of 8192. */ #define NB_MBUF RTE_MAX ( \ (nb_ports*nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT + \ nb_ports*nb_lcores*MAX_PKT_BURST + \ nb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT + \ nb_lcores*MEMPOOL_CACHE_SIZE), \ (unsigned)8192) #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 8 /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* ethernet addresses of ports */ static rte_spinlock_t locks[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; /* Ports set in promiscuous mode off by default. */ static int promiscuous_on = 0; /* NUMA is enabled by default. */ static int numa_on = 1; enum freq_scale_hint_t { FREQ_LOWER = -1, FREQ_CURRENT = 0, FREQ_HIGHER = 1, FREQ_HIGHEST = 2 }; struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; struct lcore_rx_queue { uint8_t port_id; uint8_t queue_id; enum freq_scale_hint_t freq_up_hint; uint32_t zero_rx_packet_count; uint32_t idle_hint; } __rte_cache_aligned; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS #define MAX_RX_QUEUE_PER_PORT 128 #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16 #define MAX_LCORE_PARAMS 1024 struct lcore_params { uint8_t port_id; uint8_t queue_id; uint8_t lcore_id; } __rte_cache_aligned; static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, }; static struct lcore_params * lcore_params = lcore_params_array_default; static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_UDP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .intr_conf = { .lsc = 1, #ifdef RTE_NEXT_ABI .rxq = 1, #endif }, }; static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #define DEFAULT_HASH_FUNC rte_hash_crc #else #include #define DEFAULT_HASH_FUNC rte_jhash #endif struct ipv4_5tuple { uint32_t ip_dst; uint32_t ip_src; uint16_t port_dst; uint16_t port_src; uint8_t proto; } __attribute__((__packed__)); struct ipv6_5tuple { uint8_t ip_dst[IPV6_ADDR_LEN]; uint8_t ip_src[IPV6_ADDR_LEN]; uint16_t port_dst; uint16_t port_src; uint8_t proto; } __attribute__((__packed__)); struct ipv4_l3fwd_route { struct ipv4_5tuple key; uint8_t if_out; }; struct ipv6_l3fwd_route { struct ipv6_5tuple key; uint8_t if_out; }; static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { {{IPv4(100,10,0,1), IPv4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0}, {{IPv4(100,20,0,2), IPv4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1}, {{IPv4(100,30,0,3), IPv4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2}, {{IPv4(100,40,0,4), IPv4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3}, }; static struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = { { { {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1b, 0x21, 0xff, 0xfe, 0x91, 0x38, 0x05}, {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x67, 0xff, 0xfe, 0x0d, 0xb6, 0x0a}, 1, 10, IPPROTO_UDP }, 4 }, }; typedef struct rte_hash lookup_struct_t; static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; static lookup_struct_t *ipv6_l3fwd_lookup_struct[NB_SOCKETS]; #define L3FWD_HASH_ENTRIES 1024 #define IPV4_L3FWD_NUM_ROUTES \ (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) #define IPV6_L3FWD_NUM_ROUTES \ (sizeof(ipv6_l3fwd_route_array) / sizeof(ipv6_l3fwd_route_array[0])) static uint8_t ipv4_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; static uint8_t ipv6_l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) struct ipv4_l3fwd_route { uint32_t ip; uint8_t depth; uint8_t if_out; }; static struct ipv4_l3fwd_route ipv4_l3fwd_route_array[] = { {IPv4(1,1,1,0), 24, 0}, {IPv4(2,1,1,0), 24, 1}, {IPv4(3,1,1,0), 24, 2}, {IPv4(4,1,1,0), 24, 3}, {IPv4(5,1,1,0), 24, 4}, {IPv4(6,1,1,0), 24, 5}, {IPv4(7,1,1,0), 24, 6}, {IPv4(8,1,1,0), 24, 7}, }; #define IPV4_L3FWD_NUM_ROUTES \ (sizeof(ipv4_l3fwd_route_array) / sizeof(ipv4_l3fwd_route_array[0])) #define IPV4_L3FWD_LPM_MAX_RULES 1024 typedef struct rte_lpm lookup_struct_t; static lookup_struct_t *ipv4_l3fwd_lookup_struct[NB_SOCKETS]; #endif struct lcore_conf { uint16_t n_rx_queue; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; lookup_struct_t * ipv4_lookup_struct; lookup_struct_t * ipv6_lookup_struct; } __rte_cache_aligned; struct lcore_stats { /* total sleep time in ms since last frequency scaling down */ uint32_t sleep_time; /* number of long sleep recently */ uint32_t nb_long_sleep; /* freq. scaling up trend */ uint32_t trend; /* total packet processed recently */ uint64_t nb_rx_processed; /* total iterations looped recently */ uint64_t nb_iteration_looped; uint32_t padding[9]; } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE] __rte_cache_aligned; static struct lcore_stats stats[RTE_MAX_LCORE] __rte_cache_aligned; static struct rte_timer power_timers[RTE_MAX_LCORE]; static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count); static inline enum freq_scale_hint_t power_freq_scaleup_heuristic( \ unsigned lcore_id, uint8_t port_id, uint16_t queue_id); /* exit signal handler */ static void signal_exit_now(int sigtype) { unsigned lcore_id; int ret; if (sigtype == SIGINT) { for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; /* init power management library */ ret = rte_power_exit(lcore_id); if (ret) rte_exit(EXIT_FAILURE, "Power management " "library de-initialization failed on " "core%u\n", lcore_id); } } rte_exit(EXIT_SUCCESS, "User forced exit\n"); } /* Freqency scale down timer callback */ static void power_timer_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg) { uint64_t hz; float sleep_time_ratio; unsigned lcore_id = rte_lcore_id(); /* accumulate total execution time in us when callback is invoked */ sleep_time_ratio = (float)(stats[lcore_id].sleep_time) / (float)SCALING_PERIOD; /** * check whether need to scale down frequency a step if it sleep a lot. */ if (sleep_time_ratio >= SCALING_DOWN_TIME_RATIO_THRESHOLD) { if (rte_power_freq_down) rte_power_freq_down(lcore_id); } else if ( (unsigned)(stats[lcore_id].nb_rx_processed / stats[lcore_id].nb_iteration_looped) < MAX_PKT_BURST) { /** * scale down a step if average packet per iteration less * than expectation. */ if (rte_power_freq_down) rte_power_freq_down(lcore_id); } /** * initialize another timer according to current frequency to ensure * timer interval is relatively fixed. */ hz = rte_get_timer_hz(); rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, SINGLE, lcore_id, power_timer_cb, NULL); stats[lcore_id].nb_rx_processed = 0; stats[lcore_id].nb_iteration_looped = 0; stats[lcore_id].sleep_time = 0; } /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) { struct rte_mbuf **m_table; int ret; uint16_t queueid; queueid = qconf->tx_queue_id[port]; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, queueid, m_table, n); if (unlikely(ret < n)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { uint32_t lcore_id; uint16_t len; struct lcore_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } #ifdef DO_RFC_1812_CHECKS static inline int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len) { /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ /* * 1. The packet length reported by the Link Layer must be large * enough to hold the minimum length legal IP datagram (20 bytes). */ if (link_len < sizeof(struct ipv4_hdr)) return -1; /* 2. The IP checksum must be correct. */ /* this is checked in H/W */ /* * 3. The IP version number must be 4. If the version number is not 4 * then the packet may be another version of IP, such as IPng or * ST-II. */ if (((pkt->version_ihl) >> 4) != 4) return -3; /* * 4. The IP header length field must be large enough to hold the * minimum length legal IP datagram (20 bytes = 5 words). */ if ((pkt->version_ihl & 0xf) < 5) return -4; /* * 5. The IP total length field must be large enough to hold the IP * datagram header, whose length is specified in the IP header length * field. */ if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr)) return -5; return 0; } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void print_ipv4_key(struct ipv4_5tuple key) { printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, " "proto = %d\n", (unsigned)key.ip_dst, (unsigned)key.ip_src, key.port_dst, key.port_src, key.proto); } static void print_ipv6_key(struct ipv6_5tuple key) { printf( "IP dst = " IPv6_BYTES_FMT ", IP src = " IPv6_BYTES_FMT ", " "port dst = %d, port src = %d, proto = %d\n", IPv6_BYTES(key.ip_dst), IPv6_BYTES(key.ip_src), key.port_dst, key.port_src, key.proto); } static inline uint8_t get_ipv4_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid, lookup_struct_t * ipv4_l3fwd_lookup_struct) { struct ipv4_5tuple key; struct tcp_hdr *tcp; struct udp_hdr *udp; int ret = 0; key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr); key.proto = ipv4_hdr->next_proto_id; switch (ipv4_hdr->next_proto_id) { case IPPROTO_TCP: tcp = (struct tcp_hdr *)((unsigned char *)ipv4_hdr + sizeof(struct ipv4_hdr)); key.port_dst = rte_be_to_cpu_16(tcp->dst_port); key.port_src = rte_be_to_cpu_16(tcp->src_port); break; case IPPROTO_UDP: udp = (struct udp_hdr *)((unsigned char *)ipv4_hdr + sizeof(struct ipv4_hdr)); key.port_dst = rte_be_to_cpu_16(udp->dst_port); key.port_src = rte_be_to_cpu_16(udp->src_port); break; default: key.port_dst = 0; key.port_src = 0; break; } /* Find destination port */ ret = rte_hash_lookup(ipv4_l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : ipv4_l3fwd_out_if[ret]); } static inline uint8_t get_ipv6_dst_port(struct ipv6_hdr *ipv6_hdr, uint8_t portid, lookup_struct_t *ipv6_l3fwd_lookup_struct) { struct ipv6_5tuple key; struct tcp_hdr *tcp; struct udp_hdr *udp; int ret = 0; memcpy(key.ip_dst, ipv6_hdr->dst_addr, IPV6_ADDR_LEN); memcpy(key.ip_src, ipv6_hdr->src_addr, IPV6_ADDR_LEN); key.proto = ipv6_hdr->proto; switch (ipv6_hdr->proto) { case IPPROTO_TCP: tcp = (struct tcp_hdr *)((unsigned char *) ipv6_hdr + sizeof(struct ipv6_hdr)); key.port_dst = rte_be_to_cpu_16(tcp->dst_port); key.port_src = rte_be_to_cpu_16(tcp->src_port); break; case IPPROTO_UDP: udp = (struct udp_hdr *)((unsigned char *) ipv6_hdr + sizeof(struct ipv6_hdr)); key.port_dst = rte_be_to_cpu_16(udp->dst_port); key.port_src = rte_be_to_cpu_16(udp->src_port); break; default: key.port_dst = 0; key.port_src = 0; break; } /* Find destination port */ ret = rte_hash_lookup(ipv6_l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : ipv6_l3fwd_out_if[ret]); } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static inline uint8_t get_ipv4_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid, lookup_struct_t *ipv4_l3fwd_lookup_struct) { uint8_t next_hop; return (uint8_t) ((rte_lpm_lookup(ipv4_l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid); } #endif static inline void l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, struct lcore_conf *qconf) { struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; void *d_addr_bytes; uint8_t dst_port; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); #ifdef RTE_NEXT_ABI if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { #else if (m->ol_flags & PKT_RX_IPV4_HDR) { #endif /* Handle IPv4 headers.*/ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, sizeof(struct ether_hdr)); #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { rte_pktmbuf_free(m); return; } #endif dst_port = get_ipv4_dst_port(ipv4_hdr, portid, qconf->ipv4_lookup_struct); if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; /* 02:00:00:00:00:xx */ d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; *((uint64_t *)d_addr_bytes) = 0x000000000002 + ((uint64_t)dst_port << 40); #ifdef DO_RFC_1812_CHECKS /* Update time to live and header checksum */ --(ipv4_hdr->time_to_live); ++(ipv4_hdr->hdr_checksum); #endif /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); #ifdef RTE_NEXT_ABI } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) { #else } else { #endif /* Handle IPv6 headers.*/ #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) struct ipv6_hdr *ipv6_hdr; ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, sizeof(struct ether_hdr)); dst_port = get_ipv6_dst_port(ipv6_hdr, portid, qconf->ipv6_lookup_struct); if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; /* 02:00:00:00:00:xx */ d_addr_bytes = ð_hdr->d_addr.addr_bytes[0]; *((uint64_t *)d_addr_bytes) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); #else /* We don't currently handle IPv6 packets in LPM mode. */ rte_pktmbuf_free(m); #endif } } #define MINIMUM_SLEEP_TIME 1 #define SUSPEND_THRESHOLD 300 static inline uint32_t power_idle_heuristic(uint32_t zero_rx_packet_count) { /* If zero count is less than 100, sleep 1us */ if (zero_rx_packet_count < SUSPEND_THRESHOLD) return MINIMUM_SLEEP_TIME; /* If zero count is less than 1000, sleep 100 us which is the minimum latency switching from C3/C6 to C0 */ else return SUSPEND_THRESHOLD; return 0; } static inline enum freq_scale_hint_t power_freq_scaleup_heuristic(unsigned lcore_id, uint8_t port_id, uint16_t queue_id) { /** * HW Rx queue size is 128 by default, Rx burst read at maximum 32 entries * per iteration */ #define FREQ_GEAR1_RX_PACKET_THRESHOLD MAX_PKT_BURST #define FREQ_GEAR2_RX_PACKET_THRESHOLD (MAX_PKT_BURST*2) #define FREQ_GEAR3_RX_PACKET_THRESHOLD (MAX_PKT_BURST*3) #define FREQ_UP_TREND1_ACC 1 #define FREQ_UP_TREND2_ACC 100 #define FREQ_UP_THRESHOLD 10000 if (likely(rte_eth_rx_descriptor_done(port_id, queue_id, FREQ_GEAR3_RX_PACKET_THRESHOLD) > 0)) { stats[lcore_id].trend = 0; return FREQ_HIGHEST; } else if (likely(rte_eth_rx_descriptor_done(port_id, queue_id, FREQ_GEAR2_RX_PACKET_THRESHOLD) > 0)) stats[lcore_id].trend += FREQ_UP_TREND2_ACC; else if (likely(rte_eth_rx_descriptor_done(port_id, queue_id, FREQ_GEAR1_RX_PACKET_THRESHOLD) > 0)) stats[lcore_id].trend += FREQ_UP_TREND1_ACC; if (likely(stats[lcore_id].trend > FREQ_UP_THRESHOLD)) { stats[lcore_id].trend = 0; return FREQ_HIGHER; } return FREQ_CURRENT; } /** * force polling thread sleep until one-shot rx interrupt triggers * @param port_id * Port id. * @param queue_id * Rx queue id. * @return * 0 on success */ static int sleep_until_rx_interrupt(int num) { struct rte_epoll_event event[num]; int n, i; uint8_t port_id, queue_id; void *data; RTE_LOG(INFO, L3FWD_POWER, "lcore %u sleeps until interrupt triggers\n", rte_lcore_id()); n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, -1); for (i = 0; i < n; i++) { data = event[i].epdata.data; port_id = ((uintptr_t)data) >> CHAR_BIT; queue_id = ((uintptr_t)data) & RTE_LEN2MASK(CHAR_BIT, uint8_t); RTE_LOG(INFO, L3FWD_POWER, "lcore %u is waked up from rx interrupt on" " port %d queue %d\n", rte_lcore_id(), port_id, queue_id); } return 0; } static void turn_on_intr(struct lcore_conf *qconf) { int i; struct lcore_rx_queue *rx_queue; uint8_t port_id, queue_id; for (i = 0; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); port_id = rx_queue->port_id; queue_id = rx_queue->queue_id; rte_spinlock_lock(&(locks[port_id])); rte_eth_dev_rx_intr_enable(port_id, queue_id); rte_spinlock_unlock(&(locks[port_id])); } } static int event_register(struct lcore_conf *qconf) { struct lcore_rx_queue *rx_queue; uint8_t portid, queueid; uint32_t data; int ret; int i; for (i = 0; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); portid = rx_queue->port_id; queueid = rx_queue->queue_id; data = portid << CHAR_BIT | queueid; ret = rte_eth_dev_rx_intr_ctl_q(portid, queueid, RTE_EPOLL_PER_THREAD, RTE_INTR_EVENT_ADD, (void *)((uintptr_t)data)); if (ret) return ret; } return 0; } /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; uint64_t prev_tsc_power = 0, cur_tsc_power, diff_tsc_power; int i, j, nb_rx; uint8_t portid, queueid; struct lcore_conf *qconf; struct lcore_rx_queue *rx_queue; enum freq_scale_hint_t lcore_scaleup_hint; uint32_t lcore_rx_idle_count = 0; uint32_t lcore_idle_hint = 0; int intr_en = 0; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD_POWER, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, L3FWD_POWER, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; RTE_LOG(INFO, L3FWD_POWER, " -- lcoreid=%u portid=%hhu " "rxqueueid=%hhu\n", lcore_id, portid, queueid); } /* add into event wait list */ if (event_register(qconf) == 0) intr_en = 1; else RTE_LOG(INFO, L3FWD_POWER, "RX interrupt won't enable.\n"); while (1) { stats[lcore_id].nb_iteration_looped++; cur_tsc = rte_rdtsc(); cur_tsc_power = cur_tsc; /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; send_burst(&lcore_conf[lcore_id], qconf->tx_mbufs[portid].len, portid); qconf->tx_mbufs[portid].len = 0; } prev_tsc = cur_tsc; } diff_tsc_power = cur_tsc_power - prev_tsc_power; if (diff_tsc_power > TIMER_RESOLUTION_CYCLES) { rte_timer_manage(); prev_tsc_power = cur_tsc_power; } start_rx: /* * Read packet from RX queues */ lcore_scaleup_hint = FREQ_CURRENT; lcore_rx_idle_count = 0; for (i = 0; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); rx_queue->idle_hint = 0; portid = rx_queue->port_id; queueid = rx_queue->queue_id; nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); stats[lcore_id].nb_rx_processed += nb_rx; if (unlikely(nb_rx == 0)) { /** * no packet received from rx queue, try to * sleep for a while forcing CPU enter deeper * C states. */ rx_queue->zero_rx_packet_count++; if (rx_queue->zero_rx_packet_count <= MIN_ZERO_POLL_COUNT) continue; rx_queue->idle_hint = power_idle_heuristic(\ rx_queue->zero_rx_packet_count); lcore_rx_idle_count++; } else { rx_queue->zero_rx_packet_count = 0; /** * do not scale up frequency immediately as * user to kernel space communication is costly * which might impact packet I/O for received * packets. */ rx_queue->freq_up_hint = power_freq_scaleup_heuristic(lcore_id, portid, queueid); } /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); l3fwd_simple_forward(pkts_burst[j], portid, qconf); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { l3fwd_simple_forward(pkts_burst[j], portid, qconf); } } if (likely(lcore_rx_idle_count != qconf->n_rx_queue)) { for (i = 1, lcore_scaleup_hint = qconf->rx_queue_list[0].freq_up_hint; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); if (rx_queue->freq_up_hint > lcore_scaleup_hint) lcore_scaleup_hint = rx_queue->freq_up_hint; } if (lcore_scaleup_hint == FREQ_HIGHEST) { if (rte_power_freq_max) rte_power_freq_max(lcore_id); } else if (lcore_scaleup_hint == FREQ_HIGHER) { if (rte_power_freq_up) rte_power_freq_up(lcore_id); } } else { /** * All Rx queues empty in recent consecutive polls, * sleep in a conservative manner, meaning sleep as * less as possible. */ for (i = 1, lcore_idle_hint = qconf->rx_queue_list[0].idle_hint; i < qconf->n_rx_queue; ++i) { rx_queue = &(qconf->rx_queue_list[i]); if (rx_queue->idle_hint < lcore_idle_hint) lcore_idle_hint = rx_queue->idle_hint; } if (lcore_idle_hint < SUSPEND_THRESHOLD) /** * execute "pause" instruction to avoid context * switch which generally take hundred of * microseconds for short sleep. */ rte_delay_us(lcore_idle_hint); else { /* suspend until rx interrupt trigges */ if (intr_en) { turn_on_intr(qconf); sleep_until_rx_interrupt( qconf->n_rx_queue); } /* start receiving packets immediately */ goto start_rx; } stats[lcore_id].sleep_time += lcore_idle_hint; } } } static int check_lcore_params(void) { uint8_t queue, lcore; uint16_t i; int socketid; for (i = 0; i < nb_lcore_params; ++i) { queue = lcore_params[i].queue_id; if (queue >= MAX_RX_QUEUE_PER_PORT) { printf("invalid queue number: %hhu\n", queue); return -1; } lcore = lcore_params[i].lcore_id; if (!rte_lcore_is_enabled(lcore)) { printf("error: lcore %hhu is not enabled in lcore " "mask\n", lcore); return -1; } if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && (numa_on == 0)) { printf("warning: lcore %hhu is on socket %d with numa " "off\n", lcore, socketid); } } return 0; } static int check_port_config(const unsigned nb_ports) { unsigned portid; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; if ((enabled_port_mask & (1 << portid)) == 0) { printf("port %u is not enabled in port mask\n", portid); return -1; } if (portid >= nb_ports) { printf("port %u is not present on the board\n", portid); return -1; } } return 0; } static uint8_t get_port_n_rx_queues(const uint8_t port) { int queue = -1; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) queue = lcore_params[i].queue_id; } return (uint8_t)(++queue); } static int init_lcore_rx_queues(void) { uint16_t i, nb_rx_queue; uint8_t lcore; for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; nb_rx_queue = lcore_conf[lcore].n_rx_queue; if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { printf("error: too many queues (%u) for lcore: %u\n", (unsigned)nb_rx_queue + 1, (unsigned)lcore); return -1; } else { lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = lcore_params[i].port_id; lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = lcore_params[i].queue_id; lcore_conf[lcore].n_rx_queue++; } } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK -P" " [--config (port,queue,lcore)[,(port,queue,lcore]]" " [--enable-jumbo [--max-pkt-len PKTLEN]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -P : enable promiscuous mode\n" " --config (port,queue,lcore): rx queues configuration\n" " --no-numa: optional, disable numa awareness\n" " --enable-jumbo: enable jumbo frame" " which max packet len is PKTLEN in decimal (64-9600)\n", prgname); } static int parse_max_pkt_len(const char *pktlen) { char *end = NULL; unsigned long len; /* parse decimal string */ len = strtoul(pktlen, &end, 10); if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (len == 0) return -1; return len; } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int parse_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; nb_lcore_params = 0; while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++){ errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } if (nb_lcore_params >= MAX_LCORE_PARAMS) { printf("exceeded max number of lcore params: %hu\n", nb_lcore_params); return -1; } lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; ++nb_lcore_params; } lcore_params = lcore_params_array; return 0; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, {"no-numa", 0, 0, 0}, {"enable-jumbo", 0, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:P", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; case 'P': printf("Promiscuous mode selected\n"); promiscuous_on = 1; break; /* long options */ case 0: if (!strncmp(lgopts[option_index].name, "config", 6)) { ret = parse_config(optarg); if (ret) { printf("invalid config\n"); print_usage(prgname); return -1; } } if (!strncmp(lgopts[option_index].name, "no-numa", 7)) { printf("numa is disabled \n"); numa_on = 0; } if (!strncmp(lgopts[option_index].name, "enable-jumbo", 12)) { struct option lenopts = {"max-pkt-len", required_argument, \ 0, 0}; printf("jumbo frame is enabled \n"); port_conf.rxmode.jumbo_frame = 1; /** * if no max-pkt-len set, use the default value * ETHER_MAX_LEN */ if (0 == getopt_long(argc, argvopt, "", &lenopts, &option_index)) { ret = parse_max_pkt_len(optarg); if ((ret < 64) || (ret > MAX_JUMBO_PKT_LEN)){ printf("invalid packet " "length\n"); print_usage(prgname); return -1; } port_conf.rxmode.max_rx_pkt_len = ret; } printf("set jumbo frame " "max packet length to %u\n", (unsigned int)port_conf.rxmode.max_rx_pkt_len); } break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void setup_hash(int socketid) { struct rte_hash_parameters ipv4_l3fwd_hash_params = { .name = NULL, .entries = L3FWD_HASH_ENTRIES, .key_len = sizeof(struct ipv4_5tuple), .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, }; struct rte_hash_parameters ipv6_l3fwd_hash_params = { .name = NULL, .entries = L3FWD_HASH_ENTRIES, .key_len = sizeof(struct ipv6_5tuple), .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, }; unsigned i; int ret; char s[64]; /* create ipv4 hash */ rte_snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid); ipv4_l3fwd_hash_params.name = s; ipv4_l3fwd_hash_params.socket_id = socketid; ipv4_l3fwd_lookup_struct[socketid] = rte_hash_create(&ipv4_l3fwd_hash_params); if (ipv4_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " "socket %d\n", socketid); /* create ipv6 hash */ rte_snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid); ipv6_l3fwd_hash_params.name = s; ipv6_l3fwd_hash_params.socket_id = socketid; ipv6_l3fwd_lookup_struct[socketid] = rte_hash_create(&ipv6_l3fwd_hash_params); if (ipv6_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " "socket %d\n", socketid); /* populate the ipv4 hash */ for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { ret = rte_hash_add_key (ipv4_l3fwd_lookup_struct[socketid], (void *) &ipv4_l3fwd_route_array[i].key); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" "l3fwd hash on socket %d\n", i, socketid); } ipv4_l3fwd_out_if[ret] = ipv4_l3fwd_route_array[i].if_out; printf("Hash: Adding key\n"); print_ipv4_key(ipv4_l3fwd_route_array[i].key); } /* populate the ipv6 hash */ for (i = 0; i < IPV6_L3FWD_NUM_ROUTES; i++) { ret = rte_hash_add_key (ipv6_l3fwd_lookup_struct[socketid], (void *) &ipv6_l3fwd_route_array[i].key); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" "l3fwd hash on socket %d\n", i, socketid); } ipv6_l3fwd_out_if[ret] = ipv6_l3fwd_route_array[i].if_out; printf("Hash: Adding key\n"); print_ipv6_key(ipv6_l3fwd_route_array[i].key); } } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static void setup_lpm(int socketid) { unsigned i; int ret; char s[64]; /* create the LPM table */ snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid); ipv4_l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid, IPV4_L3FWD_LPM_MAX_RULES, 0); if (ipv4_l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" " on socket %d\n", socketid); /* populate the LPM table */ for (i = 0; i < IPV4_L3FWD_NUM_ROUTES; i++) { ret = rte_lpm_add(ipv4_l3fwd_lookup_struct[socketid], ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " "l3fwd LPM table on socket %d\n", i, socketid); } printf("LPM: Adding route 0x%08x / %d (%d)\n", (unsigned)ipv4_l3fwd_route_array[i].ip, ipv4_l3fwd_route_array[i].depth, ipv4_l3fwd_route_array[i].if_out); } } #endif static int init_mem(unsigned nb_mbuf) { struct lcore_conf *qconf; int socketid; unsigned lcore_id; char s[64]; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = rte_lcore_to_socket_id(lcore_id); else socketid = 0; if (socketid >= NB_SOCKETS) { rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is " "out of range %d\n", socketid, lcore_id, NB_SOCKETS); } if (pktmbuf_pool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (pktmbuf_pool[socketid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); else printf("Allocated mbuf pool on socket %d\n", socketid); #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) setup_lpm(socketid); #else setup_hash(socketid); #endif } qconf = &lcore_conf[lcore_id]; qconf->ipv4_lookup_struct = ipv4_l3fwd_lookup_struct[socketid]; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) qconf->ipv6_lookup_struct = ipv6_l3fwd_lookup_struct[socketid]; #endif } return 0; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcore_id; uint64_t hz; uint32_t n_tx_queue, nb_lcores; uint32_t dev_rxq_num, dev_txq_num; uint8_t portid, nb_rx_queue, queue, socketid; /* catch SIGINT and restore cpufreq governor to ondemand */ signal(SIGINT, signal_exit_now); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* init RTE timer library to be used late */ rte_timer_subsystem_init(); /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); ret = init_lcore_rx_queues(); if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; if (check_port_config(nb_ports) < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } /* init port */ printf("Initializing port %d ... ", portid ); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); dev_rxq_num = dev_info.max_rx_queues; dev_txq_num = dev_info.max_tx_queues; nb_rx_queue = get_port_n_rx_queues(portid); if (nb_rx_queue > dev_rxq_num) rte_exit(EXIT_FAILURE, "Cannot configure not existed rxq: " "port=%d\n", portid); n_tx_queue = nb_lcores; if (n_tx_queue > dev_txq_num) n_tx_queue = dev_txq_num; printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)n_tx_queue ); ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); /* init memory */ ret = init_mem(NB_MBUF); if (ret < 0) rte_exit(EXIT_FAILURE, "init_mem failed\n"); /* init one TX queue per couple (lcore,port) */ queueid = 0; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (queueid >= dev_txq_num) continue; if (numa_on) socketid = \ (uint8_t)rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; if (port_conf.rxmode.jumbo_frame) txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); qconf = &lcore_conf[lcore_id]; qconf->tx_queue_id[portid] = queueid; queueid++; } printf("\n"); } for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; /* init power management library */ ret = rte_power_init(lcore_id); if (ret) RTE_LOG(ERR, POWER, "Library initialization failed on core %u\n", lcore_id); /* init timer structures for each enabled lcore */ rte_timer_init(&power_timers[lcore_id]); hz = rte_get_timer_hz(); rte_timer_reset(&power_timers[lcore_id], hz/TIMER_NUMBER_PER_SECOND, SINGLE, lcore_id, power_timer_cb, NULL); qconf = &lcore_conf[lcore_id]; printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); fflush(stdout); /* init RX queues */ for(queue = 0; queue < qconf->n_rx_queue; ++queue) { portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; if (numa_on) socketid = \ (uint8_t)rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, NULL, pktmbuf_pool[socketid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d, " "port=%d\n", ret, portid); } } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, " "port=%d\n", ret, portid); /* * If enabled, put device in promiscuous mode. * This allows IO forwarding mode to forward packets * to itself through 2 cross-connected ports of the * target machine. */ if (promiscuous_on) rte_eth_promiscuous_enable(portid); /* initialize spinlock for each port */ rte_spinlock_init(&(locks[portid])); } check_all_ports_link_status((uint8_t)nb_ports, enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/l3fwd-vf/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l3fwd-vf # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 $(USER_FLAGS) CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/l3fwd-vf/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define APP_LOOKUP_EXACT_MATCH 0 #define APP_LOOKUP_LPM 1 #define DO_RFC_1812_CHECKS //#define APP_LOOKUP_METHOD APP_LOOKUP_EXACT_MATCH #ifndef APP_LOOKUP_METHOD #define APP_LOOKUP_METHOD APP_LOOKUP_LPM #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #include #elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) #include #else #error "APP_LOOKUP_METHOD set to incorrect value" #endif #define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 #define MEMPOOL_CACHE_SIZE 256 /* * This expression is used to calculate the number of mbufs needed depending on user input, taking * into account memory for rx and tx hardware rings, cache per lcore and mtable per port per lcore. * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum value of 8192 */ #define NB_MBUF RTE_MAX ( \ (nb_ports*nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT + \ nb_ports*nb_lcores*MAX_PKT_BURST + \ nb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT + \ nb_lcores*MEMPOOL_CACHE_SIZE), \ (unsigned)8192) /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ /* * These default values are optimized for use with the Intel(R) 82599 10 GbE * Controller and the DPDK ixgbe PMD. Consider using other values for other * network controllers and/or network drivers. */ #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define NB_SOCKETS 8 #define SOCKET0 0 /* Configure how many packets ahead to prefetch, when reading packets */ #define PREFETCH_OFFSET 3 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; static int numa_on = 1; /**< NUMA is enabled by default. */ struct mbuf_table { uint16_t len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; struct lcore_rx_queue { uint8_t port_id; uint8_t queue_id; } __rte_cache_aligned; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 1 #define MAX_RX_QUEUE_PER_PORT 1 #define MAX_LCORE_PARAMS 1024 struct lcore_params { uint8_t port_id; uint8_t queue_id; uint8_t lcore_id; } __rte_cache_aligned; static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, }; static struct lcore_params * lcore_params = lcore_params_array_default; static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #define DEFAULT_HASH_FUNC rte_hash_crc #else #include #define DEFAULT_HASH_FUNC rte_jhash #endif struct ipv4_5tuple { uint32_t ip_dst; uint32_t ip_src; uint16_t port_dst; uint16_t port_src; uint8_t proto; } __attribute__((__packed__)); struct l3fwd_route { struct ipv4_5tuple key; uint8_t if_out; }; static struct l3fwd_route l3fwd_route_array[] = { {{IPv4(100,10,0,1), IPv4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0}, {{IPv4(100,20,0,2), IPv4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1}, {{IPv4(100,30,0,3), IPv4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2}, {{IPv4(100,40,0,4), IPv4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3}, }; typedef struct rte_hash lookup_struct_t; static lookup_struct_t *l3fwd_lookup_struct[NB_SOCKETS]; #define L3FWD_HASH_ENTRIES 1024 struct rte_hash_parameters l3fwd_hash_params = { .name = "l3fwd_hash_0", .entries = L3FWD_HASH_ENTRIES, .key_len = sizeof(struct ipv4_5tuple), .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, .socket_id = SOCKET0, }; #define L3FWD_NUM_ROUTES \ (sizeof(l3fwd_route_array) / sizeof(l3fwd_route_array[0])) static uint8_t l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) struct l3fwd_route { uint32_t ip; uint8_t depth; uint8_t if_out; }; static struct l3fwd_route l3fwd_route_array[] = { {IPv4(1,1,1,0), 24, 0}, {IPv4(2,1,1,0), 24, 1}, {IPv4(3,1,1,0), 24, 2}, {IPv4(4,1,1,0), 24, 3}, {IPv4(5,1,1,0), 24, 4}, {IPv4(6,1,1,0), 24, 5}, {IPv4(7,1,1,0), 24, 6}, {IPv4(8,1,1,0), 24, 7}, }; #define L3FWD_NUM_ROUTES \ (sizeof(l3fwd_route_array) / sizeof(l3fwd_route_array[0])) #define L3FWD_LPM_MAX_RULES 1024 typedef struct rte_lpm lookup_struct_t; static lookup_struct_t *l3fwd_lookup_struct[NB_SOCKETS]; #endif struct lcore_conf { uint16_t n_rx_queue; struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; uint16_t tx_queue_id; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; lookup_struct_t * lookup_struct; } __rte_cache_aligned; static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; static rte_spinlock_t spinlock_conf[RTE_MAX_ETHPORTS] = {RTE_SPINLOCK_INITIALIZER}; /* Send burst of packets on an output interface */ static inline int send_burst(struct lcore_conf *qconf, uint16_t n, uint8_t port) { struct rte_mbuf **m_table; int ret; uint16_t queueid; queueid = qconf->tx_queue_id; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; rte_spinlock_lock(&spinlock_conf[port]); ret = rte_eth_tx_burst(port, queueid, m_table, n); rte_spinlock_unlock(&spinlock_conf[port]); if (unlikely(ret < n)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Enqueue a single packet, and send burst if queue is filled */ static inline int send_single_packet(struct rte_mbuf *m, uint8_t port) { uint32_t lcore_id; uint16_t len; struct lcore_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } #ifdef DO_RFC_1812_CHECKS static inline int is_valid_ipv4_pkt(struct ipv4_hdr *pkt, uint32_t link_len) { /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ /* * 1. The packet length reported by the Link Layer must be large * enough to hold the minimum length legal IP datagram (20 bytes). */ if (link_len < sizeof(struct ipv4_hdr)) return -1; /* 2. The IP checksum must be correct. */ /* this is checked in H/W */ /* * 3. The IP version number must be 4. If the version number is not 4 * then the packet may be another version of IP, such as IPng or * ST-II. */ if (((pkt->version_ihl) >> 4) != 4) return -3; /* * 4. The IP header length field must be large enough to hold the * minimum length legal IP datagram (20 bytes = 5 words). */ if ((pkt->version_ihl & 0xf) < 5) return -4; /* * 5. The IP total length field must be large enough to hold the IP * datagram header, whose length is specified in the IP header length * field. */ if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct ipv4_hdr)) return -5; return 0; } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void print_key(struct ipv4_5tuple key) { printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, proto = %d\n", (unsigned)key.ip_dst, (unsigned)key.ip_src, key.port_dst, key.port_src, key.proto); } static inline uint8_t get_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) { struct ipv4_5tuple key; struct tcp_hdr *tcp; struct udp_hdr *udp; int ret = 0; key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr); key.proto = ipv4_hdr->next_proto_id; switch (ipv4_hdr->next_proto_id) { case IPPROTO_TCP: tcp = (struct tcp_hdr *)((unsigned char *) ipv4_hdr + sizeof(struct ipv4_hdr)); key.port_dst = rte_be_to_cpu_16(tcp->dst_port); key.port_src = rte_be_to_cpu_16(tcp->src_port); break; case IPPROTO_UDP: udp = (struct udp_hdr *)((unsigned char *) ipv4_hdr + sizeof(struct ipv4_hdr)); key.port_dst = rte_be_to_cpu_16(udp->dst_port); key.port_src = rte_be_to_cpu_16(udp->src_port); break; default: key.port_dst = 0; key.port_src = 0; } /* Find destination port */ ret = rte_hash_lookup(l3fwd_lookup_struct, (const void *)&key); return (uint8_t)((ret < 0)? portid : l3fwd_out_if[ret]); } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static inline uint8_t get_dst_port(struct ipv4_hdr *ipv4_hdr, uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) { uint8_t next_hop; return (uint8_t) ((rte_lpm_lookup(l3fwd_lookup_struct, rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0)? next_hop : portid); } #endif static inline void l3fwd_simple_forward(struct rte_mbuf *m, uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) { struct ether_hdr *eth_hdr; struct ipv4_hdr *ipv4_hdr; void *tmp; uint8_t dst_port; eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, sizeof(struct ether_hdr)); #ifdef DO_RFC_1812_CHECKS /* Check to make sure the packet is valid (RFC1812) */ if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { rte_pktmbuf_free(m); return; } #endif dst_port = get_dst_port(ipv4_hdr, portid, l3fwd_lookup_struct); if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) dst_port = portid; /* 02:00:00:00:00:xx */ tmp = ð_hdr->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); #ifdef DO_RFC_1812_CHECKS /* Update time to live and header checksum */ --(ipv4_hdr->time_to_live); ++(ipv4_hdr->hdr_checksum); #endif /* src addr */ ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); send_single_packet(m, dst_port); } /* main processing loop */ static int main_loop(__attribute__((unused)) void *dummy) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; int i, j, nb_rx; uint8_t portid, queueid; struct lcore_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_conf[lcore_id]; if (qconf->n_rx_queue == 0) { RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); return 0; } RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_queue; i++) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; RTE_LOG(INFO, L3FWD, " -- lcoreid=%u portid=%hhu rxqueueid=%hhu\n", lcore_id, portid, queueid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * This could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; send_burst(&lcore_conf[lcore_id], qconf->tx_mbufs[portid].len, portid); qconf->tx_mbufs[portid].len = 0; } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_queue; ++i) { portid = qconf->rx_queue_list[i].port_id; queueid = qconf->rx_queue_list[i].queue_id; nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); /* Prefetch first packets */ for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { rte_prefetch0(rte_pktmbuf_mtod( pkts_burst[j], void *)); } /* Prefetch and forward already prefetched packets */ for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ j + PREFETCH_OFFSET], void *)); l3fwd_simple_forward(pkts_burst[j], portid, qconf->lookup_struct); } /* Forward remaining prefetched packets */ for (; j < nb_rx; j++) { l3fwd_simple_forward(pkts_burst[j], portid, qconf->lookup_struct); } } } } static int check_lcore_params(void) { uint8_t queue, lcore; uint16_t i; int socketid; for (i = 0; i < nb_lcore_params; ++i) { queue = lcore_params[i].queue_id; if (queue >= MAX_RX_QUEUE_PER_PORT) { printf("invalid queue number: %hhu\n", queue); return -1; } lcore = lcore_params[i].lcore_id; if (!rte_lcore_is_enabled(lcore)) { printf("error: lcore %hhu is not enabled in lcore mask\n", lcore); return -1; } if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && (numa_on == 0)) { printf("warning: lcore %hhu is on socket %d with numa off \n", lcore, socketid); } } return 0; } static int check_port_config(const unsigned nb_ports) { unsigned portid; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { portid = lcore_params[i].port_id; if ((enabled_port_mask & (1 << portid)) == 0) { printf("port %u is not enabled in port mask\n", portid); return -1; } if (portid >= nb_ports) { printf("port %u is not present on the board\n", portid); return -1; } } return 0; } static uint8_t get_port_n_rx_queues(const uint8_t port) { int queue = -1; uint16_t i; for (i = 0; i < nb_lcore_params; ++i) { if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) queue = lcore_params[i].queue_id; } return (uint8_t)(++queue); } static int init_lcore_rx_queues(void) { uint16_t i, nb_rx_queue; uint8_t lcore; for (i = 0; i < nb_lcore_params; ++i) { lcore = lcore_params[i].lcore_id; nb_rx_queue = lcore_conf[lcore].n_rx_queue; if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { printf("error: too many queues (%u) for lcore: %u\n", (unsigned)nb_rx_queue + 1, (unsigned)lcore); return -1; } else { lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = lcore_params[i].port_id; lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = lcore_params[i].queue_id; lcore_conf[lcore].n_rx_queue++; } } return 0; } /* display usage */ static void print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK" " [--config (port,queue,lcore)[,(port,queue,lcore]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " --config (port,queue,lcore): rx queues configuration\n" " --no-numa: optional, disable numa awareness\n", prgname); } /* Custom handling of signals to handle process terminal */ static void signal_handler(int signum) { uint8_t portid; uint8_t nb_ports = rte_eth_dev_count(); /* When we receive a SIGINT signal */ if (signum == SIGINT) { for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) continue; rte_eth_dev_close(portid); } } rte_exit(EXIT_SUCCESS, "\n User forced exit\n"); } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static int parse_config(const char *q_arg) { char s[256]; const char *p, *p0 = q_arg; char *end; enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; unsigned long int_fld[_NUM_FLD]; char *str_fld[_NUM_FLD]; int i; unsigned size; nb_lcore_params = 0; while ((p = strchr(p0,'(')) != NULL) { ++p; if((p0 = strchr(p,')')) == NULL) return -1; size = p0 - p; if(size >= sizeof(s)) return -1; snprintf(s, sizeof(s), "%.*s", size, p); if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) return -1; for (i = 0; i < _NUM_FLD; i++){ errno = 0; int_fld[i] = strtoul(str_fld[i], &end, 0); if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) return -1; } if (nb_lcore_params >= MAX_LCORE_PARAMS) { printf("exceeded max number of lcore params: %hu\n", nb_lcore_params); return -1; } lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; ++nb_lcore_params; } lcore_params = lcore_params_array; return 0; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, {"no-numa", 0, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* long options */ case 0: if (!strcmp(lgopts[option_index].name, "config")) { ret = parse_config(optarg); if (ret) { printf("invalid config\n"); print_usage(prgname); return -1; } } if (!strcmp(lgopts[option_index].name, "no-numa")) { printf("numa is disabled \n"); numa_on = 0; } break; default: print_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void print_ethaddr(const char *name, const struct ether_addr *eth_addr) { char buf[ETHER_ADDR_FMT_SIZE]; ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); printf("%s%s", name, buf); } #if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) static void setup_hash(int socketid) { unsigned i; int ret; char s[64]; /* create hashes */ snprintf(s, sizeof(s), "l3fwd_hash_%d", socketid); l3fwd_hash_params.name = s; l3fwd_hash_params.socket_id = socketid; l3fwd_lookup_struct[socketid] = rte_hash_create(&l3fwd_hash_params); if (l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " "socket %d\n", socketid); /* populate the hash */ for (i = 0; i < L3FWD_NUM_ROUTES; i++) { ret = rte_hash_add_key (l3fwd_lookup_struct[socketid], (void *) &l3fwd_route_array[i].key); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" "l3fwd hash on socket %d\n", i, socketid); } l3fwd_out_if[ret] = l3fwd_route_array[i].if_out; printf("Hash: Adding key\n"); print_key(l3fwd_route_array[i].key); } } #endif #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) static void setup_lpm(int socketid) { unsigned i; int ret; char s[64]; /* create the LPM table */ snprintf(s, sizeof(s), "L3FWD_LPM_%d", socketid); l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid, L3FWD_LPM_MAX_RULES, 0); if (l3fwd_lookup_struct[socketid] == NULL) rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" " on socket %d\n", socketid); /* populate the LPM table */ for (i = 0; i < L3FWD_NUM_ROUTES; i++) { ret = rte_lpm_add(l3fwd_lookup_struct[socketid], l3fwd_route_array[i].ip, l3fwd_route_array[i].depth, l3fwd_route_array[i].if_out); if (ret < 0) { rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " "l3fwd LPM table on socket %d\n", i, socketid); } printf("LPM: Adding route 0x%08x / %d (%d)\n", (unsigned)l3fwd_route_array[i].ip, l3fwd_route_array[i].depth, l3fwd_route_array[i].if_out); } } #endif static int init_mem(unsigned nb_mbuf) { struct lcore_conf *qconf; int socketid; unsigned lcore_id; char s[64]; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; if (numa_on) socketid = rte_lcore_to_socket_id(lcore_id); else socketid = 0; if (socketid >= NB_SOCKETS) { rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", socketid, lcore_id, NB_SOCKETS); } if (pktmbuf_pool[socketid] == NULL) { snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, nb_mbuf, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, socketid); if (pktmbuf_pool[socketid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); else printf("Allocated mbuf pool on socket %d\n", socketid); #if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) setup_lpm(socketid); #else setup_hash(socketid); #endif } qconf = &lcore_conf[lcore_id]; qconf->lookup_struct = l3fwd_lookup_struct[socketid]; } return 0; } int main(int argc, char **argv) { struct lcore_conf *qconf; struct rte_eth_dev_info dev_info; struct rte_eth_txconf *txconf; int ret; unsigned nb_ports; uint16_t queueid; unsigned lcore_id; uint32_t nb_lcores; uint16_t n_tx_queue; uint8_t portid, nb_rx_queue, queue, socketid; signal(SIGINT, signal_handler); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD-VF parameters\n"); if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); ret = init_lcore_rx_queues(); if (ret < 0) rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; if (check_port_config(nb_ports) < 0) rte_exit(EXIT_FAILURE, "check_port_config failed\n"); nb_lcores = rte_lcore_count(); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } /* init port */ printf("Initializing port %d ... ", portid ); fflush(stdout); /* must always equal(=1) */ nb_rx_queue = get_port_n_rx_queues(portid); n_tx_queue = MAX_TX_QUEUE_PER_PORT; printf("Creating queues: nb_rxq=%d nb_txq=%u... ", nb_rx_queue, (unsigned)1 ); ret = rte_eth_dev_configure(portid, nb_rx_queue, n_tx_queue, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", ret, portid); rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); print_ethaddr(" Address:", &ports_eth_addr[portid]); printf(", "); ret = init_mem(NB_MBUF); if (ret < 0) rte_exit(EXIT_FAILURE, "init_mem failed\n"); /* init one TX queue */ socketid = (uint8_t)rte_lcore_to_socket_id(rte_get_master_lcore()); printf("txq=%d,%d,%d ", portid, 0, socketid); fflush(stdout); rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; if (port_conf.rxmode.jumbo_frame) txconf->txq_flags = 0; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, socketid, txconf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%d\n", ret, portid); printf("\n"); } for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) == 0) continue; qconf = &lcore_conf[lcore_id]; qconf->tx_queue_id = 0; printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); fflush(stdout); /* init RX queues */ for(queue = 0; queue < qconf->n_rx_queue; ++queue) { portid = qconf->rx_queue_list[queue].port_id; queueid = qconf->rx_queue_list[queue].queue_id; if (numa_on) socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); else socketid = 0; printf("rxq=%d,%d,%d ", portid, queueid, socketid); fflush(stdout); ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid, NULL, pktmbuf_pool[socketid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," "port=%d\n", ret, portid); } } printf("\n"); /* start ports */ for (portid = 0; portid < nb_ports; portid++) { if ((enabled_port_mask & (1 << portid)) == 0) { continue; } /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", ret, portid); printf("done: Port %d\n", portid); } /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/link_status_interrupt/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = link_status_interrupt # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/link_status_interrupt/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_LSI RTE_LOGTYPE_USER1 #define NB_MBUF 8192 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr lsi_ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t lsi_enabled_port_mask = 0; static unsigned int lsi_rx_queue_per_lcore = 1; /* destination port for L2 forwarding */ static unsigned lsi_dst_ports[RTE_MAX_ETHPORTS] = {0}; #define MAX_PKT_BURST 32 struct mbuf_table { unsigned len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; unsigned tx_queue_id; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .intr_conf = { .lsc = 1, /**< lsc interrupt feature enabled */ }, }; struct rte_mempool * lsi_pktmbuf_pool = NULL; /* Per-port statistics struct */ struct lsi_port_statistics { uint64_t tx; uint64_t rx; uint64_t dropped; } __rte_cache_aligned; struct lsi_port_statistics port_statistics[RTE_MAX_ETHPORTS]; /* A tsc-based timer responsible for triggering statistics printout */ #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ #define MAX_TIMER_PERIOD 86400 /* 1 day max */ static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ /* Print out statistics on packets dropped */ static void print_stats(void) { struct rte_eth_link link; uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("\nPort statistics ===================================="); for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { /* skip ports that are not enabled */ if ((lsi_enabled_port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait((uint8_t)portid, &link); printf("\nStatistics for port %u ------------------------------" "\nLink status: %25s" "\nLink speed: %26u" "\nLink duplex: %25s" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, (link.link_status ? "Link up" : "Link down"), (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX ? \ "full-duplex" : "half-duplex"), port_statistics[portid].tx, port_statistics[portid].rx, port_statistics[portid].dropped); total_packets_dropped += port_statistics[portid].dropped; total_packets_tx += port_statistics[portid].tx; total_packets_rx += port_statistics[portid].rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64, total_packets_tx, total_packets_rx, total_packets_dropped); printf("\n====================================================\n"); } /* Send the packet on an output interface */ static int lsi_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port) { struct rte_mbuf **m_table; unsigned ret; unsigned queueid; queueid = (uint16_t) qconf->tx_queue_id; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n); port_statistics[port].tx += ret; if (unlikely(ret < n)) { port_statistics[port].dropped += (n - ret); do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Send the packet on an output interface */ static int lsi_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { lsi_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } static void lsi_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port = lsi_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&lsi_ports_eth_addr[dst_port], ð->s_addr); lsi_send_packet(m, (uint8_t) dst_port); } /* main processing loop */ static void lsi_main_loop(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *m; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; unsigned i, j, portid, nb_rx; struct lcore_queue_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; timer_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, LSI, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, LSI, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, LSI, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* this could be optimized (use queueid instead of * portid), but it is not called so often */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; lsi_send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { print_stats(); /* reset the timer */ timer_tsc = 0; } } } prev_tsc = cur_tsc; } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); port_statistics[portid].rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); lsi_simple_forward(m, portid); } } } } static int lsi_launch_one_lcore(__attribute__((unused)) void *dummy) { lsi_main_loop(); return 0; } /* display usage */ static void lsi_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", prgname); } static int lsi_parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static unsigned int lsi_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int lsi_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int lsi_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:T:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': lsi_enabled_port_mask = lsi_parse_portmask(optarg); if (lsi_enabled_port_mask == 0) { printf("invalid portmask\n"); lsi_usage(prgname); return -1; } break; /* nqueue */ case 'q': lsi_rx_queue_per_lcore = lsi_parse_nqueue(optarg); if (lsi_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); lsi_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = lsi_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; if (timer_period < 0) { printf("invalid timer period\n"); lsi_usage(prgname); return -1; } break; /* long options */ case 0: lsi_usage(prgname); return -1; default: lsi_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /** * It will be called as the callback for specified port after a LSI interrupt * has been fully handled. This callback needs to be implemented carefully as * it will be called in the interrupt host thread which is different from the * application main thread. * * @param port_id * Port id. * @param type * event type. * @param param * Pointer to(address of) the parameters. * * @return * void. */ static void lsi_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param) { struct rte_eth_link link; RTE_SET_USED(param); printf("\n\nIn registered callback...\n"); printf("Event type: %s\n", type == RTE_ETH_EVENT_INTR_LSC ? "LSC interrupt" : "unknown event"); rte_eth_link_get_nowait(port_id, &link); if (link.link_status) { printf("Port %d Link Up - speed %u Mbps - %s\n\n", port_id, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex")); } else printf("Port %d Link Down\n\n", port_id); } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; int ret; uint8_t nb_ports; uint8_t portid, portid_last = 0; unsigned lcore_id, rx_lcore_id; unsigned nb_ports_in_mask = 0; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eal_init failed"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = lsi_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid arguments"); /* create the mbuf pool */ lsi_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (lsi_pktmbuf_pool == NULL) rte_panic("Cannot init mbuf pool\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_panic("No Ethernet port - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((lsi_enabled_port_mask & (1 << portid)) == 0) continue; /* save the destination port id */ if (nb_ports_in_mask % 2) { lsi_dst_ports[portid] = portid_last; lsi_dst_ports[portid_last] = portid; } else portid_last = portid; nb_ports_in_mask++; rte_eth_dev_info_get(portid, &dev_info); } if (nb_ports_in_mask < 2 || nb_ports_in_mask % 2) rte_exit(EXIT_FAILURE, "Current enabled port number is %u, " "but it should be even and at least 2\n", nb_ports_in_mask); rx_lcore_id = 0; qconf = &lcore_queue_conf[rx_lcore_id]; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((lsi_enabled_port_mask & (1 << portid)) == 0) continue; /* get the lcore_id for this port */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || lcore_queue_conf[rx_lcore_id].n_rx_port == lsi_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->n_rx_port++; printf("Lcore %u: RX port %u\n",rx_lcore_id, (unsigned) portid); } /* Initialise each port */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((lsi_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", (unsigned) portid); continue; } /* init port */ printf("Initializing port %u... ", (unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, (unsigned) portid); /* register lsi interrupt callback, need to be after * rte_eth_dev_configure(). if (intr_conf.lsc == 0), no * lsc interrupt will be present, and below callback to * be registered will never be called. */ rte_eth_dev_callback_register(portid, RTE_ETH_EVENT_INTR_LSC, lsi_event_callback, NULL); rte_eth_macaddr_get(portid, &lsi_ports_eth_addr[portid]); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, lsi_pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d, port=%u\n", ret, (unsigned) portid); /* init one TX queue logical core on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d,port=%u\n", ret, (unsigned) portid); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%u\n", ret, (unsigned) portid); printf("done:\n"); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, lsi_ports_eth_addr[portid].addr_bytes[0], lsi_ports_eth_addr[portid].addr_bytes[1], lsi_ports_eth_addr[portid].addr_bytes[2], lsi_ports_eth_addr[portid].addr_bytes[3], lsi_ports_eth_addr[portid].addr_bytes[4], lsi_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ memset(&port_statistics, 0, sizeof(port_statistics)); } check_all_ports_link_status(nb_ports, lsi_enabled_port_mask); /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(lsi_launch_one_lcore, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/load_balancer/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = load_balancer # all source are stored in SRCS-y SRCS-y := main.c config.c init.c runtime.c CFLAGS += -O3 -g CFLAGS += $(WERROR_FLAGS) CFLAGS_config.o := -D_GNU_SOURCE # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/load_balancer/config.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" struct app_params app; static const char usage[] = " \n" " load_balancer -- \n" " \n" "Application manadatory parameters: \n" " --rx \"(PORT, QUEUE, LCORE), ...\" : List of NIC RX ports and queues \n" " handled by the I/O RX lcores \n" " --tx \"(PORT, LCORE), ...\" : List of NIC TX ports handled by the I/O TX \n" " lcores \n" " --w \"LCORE, ...\" : List of the worker lcores \n" " --lpm \"IP / PREFIX => PORT; ...\" : List of LPM rules used by the worker \n" " lcores for packet forwarding \n" " \n" "Application optional parameters: \n" " --rsz \"A, B, C, D\" : Ring sizes \n" " A = Size (in number of buffer descriptors) of each of the NIC RX \n" " rings read by the I/O RX lcores (default value is %u) \n" " B = Size (in number of elements) of each of the SW rings used by the\n" " I/O RX lcores to send packets to worker lcores (default value is\n" " %u) \n" " C = Size (in number of elements) of each of the SW rings used by the\n" " worker lcores to send packets to I/O TX lcores (default value is\n" " %u) \n" " D = Size (in number of buffer descriptors) of each of the NIC TX \n" " rings written by I/O TX lcores (default value is %u) \n" " --bsz \"(A, B), (C, D), (E, F)\" : Burst sizes \n" " A = I/O RX lcore read burst size from NIC RX (default value is %u) \n" " B = I/O RX lcore write burst size to output SW rings (default value \n" " is %u) \n" " C = Worker lcore read burst size from input SW rings (default value \n" " is %u) \n" " D = Worker lcore write burst size to output SW rings (default value \n" " is %u) \n" " E = I/O TX lcore read burst size from input SW rings (default value \n" " is %u) \n" " F = I/O TX lcore write burst size to NIC TX (default value is %u) \n" " --pos-lb POS : Position of the 1-byte field within the input packet used by\n" " the I/O RX lcores to identify the worker lcore for the current \n" " packet (default value is %u) \n"; void app_print_usage(void) { printf(usage, APP_DEFAULT_NIC_RX_RING_SIZE, APP_DEFAULT_RING_RX_SIZE, APP_DEFAULT_RING_TX_SIZE, APP_DEFAULT_NIC_TX_RING_SIZE, APP_DEFAULT_BURST_SIZE_IO_RX_READ, APP_DEFAULT_BURST_SIZE_IO_RX_WRITE, APP_DEFAULT_BURST_SIZE_WORKER_READ, APP_DEFAULT_BURST_SIZE_WORKER_WRITE, APP_DEFAULT_BURST_SIZE_IO_TX_READ, APP_DEFAULT_BURST_SIZE_IO_TX_WRITE, APP_DEFAULT_IO_RX_LB_POS ); } #ifndef APP_ARG_RX_MAX_CHARS #define APP_ARG_RX_MAX_CHARS 4096 #endif #ifndef APP_ARG_RX_MAX_TUPLES #define APP_ARG_RX_MAX_TUPLES 128 #endif static int str_to_unsigned_array( const char *s, size_t sbuflen, char separator, unsigned num_vals, unsigned *vals) { char str[sbuflen+1]; char *splits[num_vals]; char *endptr = NULL; int i, num_splits = 0; /* copy s so we don't modify original string */ snprintf(str, sizeof(str), "%s", s); num_splits = rte_strsplit(str, sizeof(str), splits, num_vals, separator); errno = 0; for (i = 0; i < num_splits; i++) { vals[i] = strtoul(splits[i], &endptr, 0); if (errno != 0 || *endptr != '\0') return -1; } return num_splits; } static int str_to_unsigned_vals( const char *s, size_t sbuflen, char separator, unsigned num_vals, ...) { unsigned i, vals[num_vals]; va_list ap; num_vals = str_to_unsigned_array(s, sbuflen, separator, num_vals, vals); va_start(ap, num_vals); for (i = 0; i < num_vals; i++) { unsigned *u = va_arg(ap, unsigned *); *u = vals[i]; } va_end(ap); return num_vals; } static int parse_arg_rx(const char *arg) { const char *p0 = arg, *p = arg; uint32_t n_tuples; if (strnlen(arg, APP_ARG_RX_MAX_CHARS + 1) == APP_ARG_RX_MAX_CHARS + 1) { return -1; } n_tuples = 0; while ((p = strchr(p0,'(')) != NULL) { struct app_lcore_params *lp; uint32_t port, queue, lcore, i; p0 = strchr(p++, ')'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, ',', 3, &port, &queue, &lcore) != 3)) { return -2; } /* Enable port and queue for later initialization */ if ((port >= APP_MAX_NIC_PORTS) || (queue >= APP_MAX_RX_QUEUES_PER_NIC_PORT)) { return -3; } if (app.nic_rx_queue_mask[port][queue] != 0) { return -4; } app.nic_rx_queue_mask[port][queue] = 1; /* Check and assign (port, queue) to I/O lcore */ if (rte_lcore_is_enabled(lcore) == 0) { return -5; } if (lcore >= APP_MAX_LCORES) { return -6; } lp = &app.lcore_params[lcore]; if (lp->type == e_APP_LCORE_WORKER) { return -7; } lp->type = e_APP_LCORE_IO; const size_t n_queues = RTE_MIN(lp->io.rx.n_nic_queues, RTE_DIM(lp->io.rx.nic_queues)); for (i = 0; i < n_queues; i ++) { if ((lp->io.rx.nic_queues[i].port == port) && (lp->io.rx.nic_queues[i].queue == queue)) { return -8; } } if (lp->io.rx.n_nic_queues >= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE) { return -9; } lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = (uint8_t) port; lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = (uint8_t) queue; lp->io.rx.n_nic_queues ++; n_tuples ++; if (n_tuples > APP_ARG_RX_MAX_TUPLES) { return -10; } } if (n_tuples == 0) { return -11; } return 0; } #ifndef APP_ARG_TX_MAX_CHARS #define APP_ARG_TX_MAX_CHARS 4096 #endif #ifndef APP_ARG_TX_MAX_TUPLES #define APP_ARG_TX_MAX_TUPLES 128 #endif static int parse_arg_tx(const char *arg) { const char *p0 = arg, *p = arg; uint32_t n_tuples; if (strnlen(arg, APP_ARG_TX_MAX_CHARS + 1) == APP_ARG_TX_MAX_CHARS + 1) { return -1; } n_tuples = 0; while ((p = strchr(p0,'(')) != NULL) { struct app_lcore_params *lp; uint32_t port, lcore, i; p0 = strchr(p++, ')'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, ',', 2, &port, &lcore) != 2)) { return -2; } /* Enable port and queue for later initialization */ if (port >= APP_MAX_NIC_PORTS) { return -3; } if (app.nic_tx_port_mask[port] != 0) { return -4; } app.nic_tx_port_mask[port] = 1; /* Check and assign (port, queue) to I/O lcore */ if (rte_lcore_is_enabled(lcore) == 0) { return -5; } if (lcore >= APP_MAX_LCORES) { return -6; } lp = &app.lcore_params[lcore]; if (lp->type == e_APP_LCORE_WORKER) { return -7; } lp->type = e_APP_LCORE_IO; const size_t n_ports = RTE_MIN(lp->io.tx.n_nic_ports, RTE_DIM(lp->io.tx.nic_ports)); for (i = 0; i < n_ports; i ++) { if (lp->io.tx.nic_ports[i] == port) { return -8; } } if (lp->io.tx.n_nic_ports >= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE) { return -9; } lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = (uint8_t) port; lp->io.tx.n_nic_ports ++; n_tuples ++; if (n_tuples > APP_ARG_TX_MAX_TUPLES) { return -10; } } if (n_tuples == 0) { return -11; } return 0; } #ifndef APP_ARG_W_MAX_CHARS #define APP_ARG_W_MAX_CHARS 4096 #endif #ifndef APP_ARG_W_MAX_TUPLES #define APP_ARG_W_MAX_TUPLES APP_MAX_WORKER_LCORES #endif static int parse_arg_w(const char *arg) { const char *p = arg; uint32_t n_tuples; if (strnlen(arg, APP_ARG_W_MAX_CHARS + 1) == APP_ARG_W_MAX_CHARS + 1) { return -1; } n_tuples = 0; while (*p != 0) { struct app_lcore_params *lp; uint32_t lcore; errno = 0; lcore = strtoul(p, NULL, 0); if ((errno != 0)) { return -2; } /* Check and enable worker lcore */ if (rte_lcore_is_enabled(lcore) == 0) { return -3; } if (lcore >= APP_MAX_LCORES) { return -4; } lp = &app.lcore_params[lcore]; if (lp->type == e_APP_LCORE_IO) { return -5; } lp->type = e_APP_LCORE_WORKER; n_tuples ++; if (n_tuples > APP_ARG_W_MAX_TUPLES) { return -6; } p = strchr(p, ','); if (p == NULL) { break; } p ++; } if (n_tuples == 0) { return -7; } if ((n_tuples & (n_tuples - 1)) != 0) { return -8; } return 0; } #ifndef APP_ARG_LPM_MAX_CHARS #define APP_ARG_LPM_MAX_CHARS 4096 #endif static int parse_arg_lpm(const char *arg) { const char *p = arg, *p0; if (strnlen(arg, APP_ARG_LPM_MAX_CHARS + 1) == APP_ARG_TX_MAX_CHARS + 1) { return -1; } while (*p != 0) { uint32_t ip_a, ip_b, ip_c, ip_d, ip, depth, if_out; char *endptr; p0 = strchr(p, '/'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, '.', 4, &ip_a, &ip_b, &ip_c, &ip_d) != 4)) { return -2; } p = p0 + 1; errno = 0; depth = strtoul(p, &endptr, 0); if (errno != 0 || *endptr != '=') { return -3; } p = strchr(p, '>'); if (p == NULL) { return -4; } if_out = strtoul(++p, &endptr, 0); if (errno != 0 || (*endptr != '\0' && *endptr != ';')) { return -5; } if ((ip_a >= 256) || (ip_b >= 256) || (ip_c >= 256) || (ip_d >= 256) || (depth == 0) || (depth >= 32) || (if_out >= APP_MAX_NIC_PORTS)) { return -6; } ip = (ip_a << 24) | (ip_b << 16) | (ip_c << 8) | ip_d; if (app.n_lpm_rules >= APP_MAX_LPM_RULES) { return -7; } app.lpm_rules[app.n_lpm_rules].ip = ip; app.lpm_rules[app.n_lpm_rules].depth = (uint8_t) depth; app.lpm_rules[app.n_lpm_rules].if_out = (uint8_t) if_out; app.n_lpm_rules ++; p = strchr(p, ';'); if (p == NULL) { return -8; } p ++; } if (app.n_lpm_rules == 0) { return -9; } return 0; } static int app_check_lpm_table(void) { uint32_t rule; /* For each rule, check that the output I/F is enabled */ for (rule = 0; rule < app.n_lpm_rules; rule ++) { uint32_t port = app.lpm_rules[rule].if_out; if (app.nic_tx_port_mask[port] == 0) { return -1; } } return 0; } static int app_check_every_rx_port_is_tx_enabled(void) { uint8_t port; for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { if ((app_get_nic_rx_queues_per_port(port) > 0) && (app.nic_tx_port_mask[port] == 0)) { return -1; } } return 0; } #ifndef APP_ARG_RSZ_CHARS #define APP_ARG_RSZ_CHARS 63 #endif static int parse_arg_rsz(const char *arg) { if (strnlen(arg, APP_ARG_RSZ_CHARS + 1) == APP_ARG_RSZ_CHARS + 1) { return -1; } if (str_to_unsigned_vals(arg, APP_ARG_RSZ_CHARS, ',', 4, &app.nic_rx_ring_size, &app.ring_rx_size, &app.ring_tx_size, &app.nic_tx_ring_size) != 4) return -2; if ((app.nic_rx_ring_size == 0) || (app.nic_tx_ring_size == 0) || (app.ring_rx_size == 0) || (app.ring_tx_size == 0)) { return -3; } return 0; } #ifndef APP_ARG_BSZ_CHARS #define APP_ARG_BSZ_CHARS 63 #endif static int parse_arg_bsz(const char *arg) { const char *p = arg, *p0; if (strnlen(arg, APP_ARG_BSZ_CHARS + 1) == APP_ARG_BSZ_CHARS + 1) { return -1; } p0 = strchr(p++, ')'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_io_rx_read, &app.burst_size_io_rx_write) != 2)) { return -2; } p = strchr(p0, '('); if (p == NULL) { return -3; } p0 = strchr(p++, ')'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_worker_read, &app.burst_size_worker_write) != 2)) { return -4; } p = strchr(p0, '('); if (p == NULL) { return -5; } p0 = strchr(p++, ')'); if ((p0 == NULL) || (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_io_tx_read, &app.burst_size_io_tx_write) != 2)) { return -6; } if ((app.burst_size_io_rx_read == 0) || (app.burst_size_io_rx_write == 0) || (app.burst_size_worker_read == 0) || (app.burst_size_worker_write == 0) || (app.burst_size_io_tx_read == 0) || (app.burst_size_io_tx_write == 0)) { return -7; } if ((app.burst_size_io_rx_read > APP_MBUF_ARRAY_SIZE) || (app.burst_size_io_rx_write > APP_MBUF_ARRAY_SIZE) || (app.burst_size_worker_read > APP_MBUF_ARRAY_SIZE) || (app.burst_size_worker_write > APP_MBUF_ARRAY_SIZE) || ((2 * app.burst_size_io_tx_read) > APP_MBUF_ARRAY_SIZE) || (app.burst_size_io_tx_write > APP_MBUF_ARRAY_SIZE)) { return -8; } return 0; } #ifndef APP_ARG_NUMERICAL_SIZE_CHARS #define APP_ARG_NUMERICAL_SIZE_CHARS 15 #endif static int parse_arg_pos_lb(const char *arg) { uint32_t x; char *endpt; if (strnlen(arg, APP_ARG_NUMERICAL_SIZE_CHARS + 1) == APP_ARG_NUMERICAL_SIZE_CHARS + 1) { return -1; } errno = 0; x = strtoul(arg, &endpt, 10); if (errno != 0 || endpt == arg || *endpt != '\0'){ return -2; } if (x >= 64) { return -3; } app.pos_lb = (uint8_t) x; return 0; } /* Parse the argument given in the command line of the application */ int app_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {"rx", 1, 0, 0}, {"tx", 1, 0, 0}, {"w", 1, 0, 0}, {"lpm", 1, 0, 0}, {"rsz", 1, 0, 0}, {"bsz", 1, 0, 0}, {"pos-lb", 1, 0, 0}, {NULL, 0, 0, 0} }; uint32_t arg_w = 0; uint32_t arg_rx = 0; uint32_t arg_tx = 0; uint32_t arg_lpm = 0; uint32_t arg_rsz = 0; uint32_t arg_bsz = 0; uint32_t arg_pos_lb = 0; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "", lgopts, &option_index)) != EOF) { switch (opt) { /* long options */ case 0: if (!strcmp(lgopts[option_index].name, "rx")) { arg_rx = 1; ret = parse_arg_rx(optarg); if (ret) { printf("Incorrect value for --rx argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "tx")) { arg_tx = 1; ret = parse_arg_tx(optarg); if (ret) { printf("Incorrect value for --tx argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "w")) { arg_w = 1; ret = parse_arg_w(optarg); if (ret) { printf("Incorrect value for --w argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "lpm")) { arg_lpm = 1; ret = parse_arg_lpm(optarg); if (ret) { printf("Incorrect value for --lpm argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "rsz")) { arg_rsz = 1; ret = parse_arg_rsz(optarg); if (ret) { printf("Incorrect value for --rsz argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "bsz")) { arg_bsz = 1; ret = parse_arg_bsz(optarg); if (ret) { printf("Incorrect value for --bsz argument (%d)\n", ret); return -1; } } if (!strcmp(lgopts[option_index].name, "pos-lb")) { arg_pos_lb = 1; ret = parse_arg_pos_lb(optarg); if (ret) { printf("Incorrect value for --pos-lb argument (%d)\n", ret); return -1; } } break; default: return -1; } } /* Check that all mandatory arguments are provided */ if ((arg_rx == 0) || (arg_tx == 0) || (arg_w == 0) || (arg_lpm == 0)){ printf("Not all mandatory arguments are present\n"); return -1; } /* Assign default values for the optional arguments not provided */ if (arg_rsz == 0) { app.nic_rx_ring_size = APP_DEFAULT_NIC_RX_RING_SIZE; app.nic_tx_ring_size = APP_DEFAULT_NIC_TX_RING_SIZE; app.ring_rx_size = APP_DEFAULT_RING_RX_SIZE; app.ring_tx_size = APP_DEFAULT_RING_TX_SIZE; } if (arg_bsz == 0) { app.burst_size_io_rx_read = APP_DEFAULT_BURST_SIZE_IO_RX_READ; app.burst_size_io_rx_write = APP_DEFAULT_BURST_SIZE_IO_RX_WRITE; app.burst_size_io_tx_read = APP_DEFAULT_BURST_SIZE_IO_TX_READ; app.burst_size_io_tx_write = APP_DEFAULT_BURST_SIZE_IO_TX_WRITE; app.burst_size_worker_read = APP_DEFAULT_BURST_SIZE_WORKER_READ; app.burst_size_worker_write = APP_DEFAULT_BURST_SIZE_WORKER_WRITE; } if (arg_pos_lb == 0) { app.pos_lb = APP_DEFAULT_IO_RX_LB_POS; } /* Check cross-consistency of arguments */ if ((ret = app_check_lpm_table()) < 0) { printf("At least one LPM rule is inconsistent (%d)\n", ret); return -1; } if (app_check_every_rx_port_is_tx_enabled() < 0) { printf("On LPM lookup miss, packet is sent back on the input port.\n"); printf("At least one RX port is not enabled for TX.\n"); return -2; } if (optind >= 0) argv[optind - 1] = prgname; ret = optind - 1; optind = 0; /* reset getopt lib */ return ret; } int app_get_nic_rx_queues_per_port(uint8_t port) { uint32_t i, count; if (port >= APP_MAX_NIC_PORTS) { return -1; } count = 0; for (i = 0; i < APP_MAX_RX_QUEUES_PER_NIC_PORT; i ++) { if (app.nic_rx_queue_mask[port][i] == 1) { count ++; } } return count; } int app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out) { uint32_t lcore; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; uint32_t i; if (app.lcore_params[lcore].type != e_APP_LCORE_IO) { continue; } const size_t n_queues = RTE_MIN(lp->rx.n_nic_queues, RTE_DIM(lp->rx.nic_queues)); for (i = 0; i < n_queues; i ++) { if ((lp->rx.nic_queues[i].port == port) && (lp->rx.nic_queues[i].queue == queue)) { *lcore_out = lcore; return 0; } } } return -1; } int app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out) { uint32_t lcore; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; uint32_t i; if (app.lcore_params[lcore].type != e_APP_LCORE_IO) { continue; } const size_t n_ports = RTE_MIN(lp->tx.n_nic_ports, RTE_DIM(lp->tx.nic_ports)); for (i = 0; i < n_ports; i ++) { if (lp->tx.nic_ports[i] == port) { *lcore_out = lcore; return 0; } } } return -1; } int app_is_socket_used(uint32_t socket) { uint32_t lcore; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) { continue; } if (socket == rte_lcore_to_socket_id(lcore)) { return 1; } } return 0; } uint32_t app_get_lcores_io_rx(void) { uint32_t lcore, count; count = 0; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp_io->rx.n_nic_queues == 0)) { continue; } count ++; } return count; } uint32_t app_get_lcores_worker(void) { uint32_t lcore, count; count = 0; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } count ++; } if (count > APP_MAX_WORKER_LCORES) { rte_panic("Algorithmic error (too many worker lcores)\n"); return 0; } return count; } void app_print_params(void) { unsigned port, queue, lcore, rule, i, j; /* Print NIC RX configuration */ printf("NIC RX ports: "); for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { uint32_t n_rx_queues = app_get_nic_rx_queues_per_port((uint8_t) port); if (n_rx_queues == 0) { continue; } printf("%u (", port); for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) { if (app.nic_rx_queue_mask[port][queue] == 1) { printf("%u ", queue); } } printf(") "); } printf(";\n"); /* Print I/O lcore RX params */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp->rx.n_nic_queues == 0)) { continue; } printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore)); printf("RX ports "); for (i = 0; i < lp->rx.n_nic_queues; i ++) { printf("(%u, %u) ", (unsigned) lp->rx.nic_queues[i].port, (unsigned) lp->rx.nic_queues[i].queue); } printf("; "); printf("Output rings "); for (i = 0; i < lp->rx.n_rings; i ++) { printf("%p ", lp->rx.rings[i]); } printf(";\n"); } /* Print worker lcore RX params */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } printf("Worker lcore %u (socket %u) ID %u: ", lcore, rte_lcore_to_socket_id(lcore), (unsigned)lp->worker_id); printf("Input rings "); for (i = 0; i < lp->n_rings_in; i ++) { printf("%p ", lp->rings_in[i]); } printf(";\n"); } printf("\n"); /* Print NIC TX configuration */ printf("NIC TX ports: "); for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { if (app.nic_tx_port_mask[port] == 1) { printf("%u ", port); } } printf(";\n"); /* Print I/O TX lcore params */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; uint32_t n_workers = app_get_lcores_worker(); if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp->tx.n_nic_ports == 0)) { continue; } printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore)); printf("Input rings per TX port "); for (i = 0; i < lp->tx.n_nic_ports; i ++) { port = lp->tx.nic_ports[i]; printf("%u (", port); for (j = 0; j < n_workers; j ++) { printf("%p ", lp->tx.rings[port][j]); } printf(") "); } printf(";\n"); } /* Print worker lcore TX params */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } printf("Worker lcore %u (socket %u) ID %u: \n", lcore, rte_lcore_to_socket_id(lcore), (unsigned)lp->worker_id); printf("Output rings per TX port "); for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { if (lp->rings_out[port] != NULL) { printf("%u (%p) ", port, lp->rings_out[port]); } } printf(";\n"); } /* Print LPM rules */ printf("LPM rules: \n"); for (rule = 0; rule < app.n_lpm_rules; rule ++) { uint32_t ip = app.lpm_rules[rule].ip; uint8_t depth = app.lpm_rules[rule].depth; uint8_t if_out = app.lpm_rules[rule].if_out; printf("\t%u: %u.%u.%u.%u/%u => %u;\n", rule, (unsigned) (ip & 0xFF000000) >> 24, (unsigned) (ip & 0x00FF0000) >> 16, (unsigned) (ip & 0x0000FF00) >> 8, (unsigned) ip & 0x000000FF, (unsigned) depth, (unsigned) if_out ); } /* Rings */ printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n", (unsigned) app.nic_rx_ring_size, (unsigned) app.ring_rx_size, (unsigned) app.ring_tx_size, (unsigned) app.nic_tx_ring_size); /* Bursts */ printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n", (unsigned) app.burst_size_io_rx_read, (unsigned) app.burst_size_io_rx_write, (unsigned) app.burst_size_worker_read, (unsigned) app.burst_size_worker_write, (unsigned) app.burst_size_io_tx_read, (unsigned) app.burst_size_io_tx_write); } ================================================ FILE: examples/load_balancer/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static void app_assign_worker_ids(void) { uint32_t lcore, worker_id; /* Assign ID for each worker */ worker_id = 0; for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } lp_worker->worker_id = worker_id; worker_id ++; } } static void app_init_mbuf_pools(void) { unsigned socket, lcore; /* Init the buffer pools */ for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) { char name[32]; if (app_is_socket_used(socket) == 0) { continue; } snprintf(name, sizeof(name), "mbuf_pool_%u", socket); printf("Creating the mbuf pool for socket %u ...\n", socket); app.pools[socket] = rte_pktmbuf_pool_create( name, APP_DEFAULT_MEMPOOL_BUFFERS, APP_DEFAULT_MEMPOOL_CACHE_SIZE, 0, APP_DEFAULT_MBUF_DATA_SIZE, socket); if (app.pools[socket] == NULL) { rte_panic("Cannot create mbuf pool on socket %u\n", socket); } } for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) { continue; } socket = rte_lcore_to_socket_id(lcore); app.lcore_params[lcore].pool = app.pools[socket]; } } static void app_init_lpm_tables(void) { unsigned socket, lcore; /* Init the LPM tables */ for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) { char name[32]; uint32_t rule; if (app_is_socket_used(socket) == 0) { continue; } snprintf(name, sizeof(name), "lpm_table_%u", socket); printf("Creating the LPM table for socket %u ...\n", socket); app.lpm_tables[socket] = rte_lpm_create( name, socket, APP_MAX_LPM_RULES, 0); if (app.lpm_tables[socket] == NULL) { rte_panic("Unable to create LPM table on socket %u\n", socket); } for (rule = 0; rule < app.n_lpm_rules; rule ++) { int ret; ret = rte_lpm_add(app.lpm_tables[socket], app.lpm_rules[rule].ip, app.lpm_rules[rule].depth, app.lpm_rules[rule].if_out); if (ret < 0) { rte_panic("Unable to add entry %u (%x/%u => %u) to the LPM table on socket %u (%d)\n", (unsigned) rule, (unsigned) app.lpm_rules[rule].ip, (unsigned) app.lpm_rules[rule].depth, (unsigned) app.lpm_rules[rule].if_out, socket, ret); } } } for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } socket = rte_lcore_to_socket_id(lcore); app.lcore_params[lcore].worker.lpm_table = app.lpm_tables[socket]; } } static void app_init_rings_rx(void) { unsigned lcore; /* Initialize the rings for the RX side */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; unsigned socket_io, lcore_worker; if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp_io->rx.n_nic_queues == 0)) { continue; } socket_io = rte_lcore_to_socket_id(lcore); for (lcore_worker = 0; lcore_worker < APP_MAX_LCORES; lcore_worker ++) { char name[32]; struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore_worker].worker; struct rte_ring *ring = NULL; if (app.lcore_params[lcore_worker].type != e_APP_LCORE_WORKER) { continue; } printf("Creating ring to connect I/O lcore %u (socket %u) with worker lcore %u ...\n", lcore, socket_io, lcore_worker); snprintf(name, sizeof(name), "app_ring_rx_s%u_io%u_w%u", socket_io, lcore, lcore_worker); ring = rte_ring_create( name, app.ring_rx_size, socket_io, RING_F_SP_ENQ | RING_F_SC_DEQ); if (ring == NULL) { rte_panic("Cannot create ring to connect I/O core %u with worker core %u\n", lcore, lcore_worker); } lp_io->rx.rings[lp_io->rx.n_rings] = ring; lp_io->rx.n_rings ++; lp_worker->rings_in[lp_worker->n_rings_in] = ring; lp_worker->n_rings_in ++; } } for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp_io->rx.n_nic_queues == 0)) { continue; } if (lp_io->rx.n_rings != app_get_lcores_worker()) { rte_panic("Algorithmic error (I/O RX rings)\n"); } } for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } if (lp_worker->n_rings_in != app_get_lcores_io_rx()) { rte_panic("Algorithmic error (worker input rings)\n"); } } } static void app_init_rings_tx(void) { unsigned lcore; /* Initialize the rings for the TX side */ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; unsigned port; if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { continue; } for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { char name[32]; struct app_lcore_params_io *lp_io = NULL; struct rte_ring *ring; uint32_t socket_io, lcore_io; if (app.nic_tx_port_mask[port] == 0) { continue; } if (app_get_lcore_for_nic_tx((uint8_t) port, &lcore_io) < 0) { rte_panic("Algorithmic error (no I/O core to handle TX of port %u)\n", port); } lp_io = &app.lcore_params[lcore_io].io; socket_io = rte_lcore_to_socket_id(lcore_io); printf("Creating ring to connect worker lcore %u with TX port %u (through I/O lcore %u) (socket %u) ...\n", lcore, port, (unsigned)lcore_io, (unsigned)socket_io); snprintf(name, sizeof(name), "app_ring_tx_s%u_w%u_p%u", socket_io, lcore, port); ring = rte_ring_create( name, app.ring_tx_size, socket_io, RING_F_SP_ENQ | RING_F_SC_DEQ); if (ring == NULL) { rte_panic("Cannot create ring to connect worker core %u with TX port %u\n", lcore, port); } lp_worker->rings_out[port] = ring; lp_io->tx.rings[port][lp_worker->worker_id] = ring; } } for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; unsigned i; if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || (lp_io->tx.n_nic_ports == 0)) { continue; } for (i = 0; i < lp_io->tx.n_nic_ports; i ++){ unsigned port, j; port = lp_io->tx.nic_ports[i]; for (j = 0; j < app_get_lcores_worker(); j ++) { if (lp_io->tx.rings[port][j] == NULL) { rte_panic("Algorithmic error (I/O TX rings)\n"); } } } } } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; uint32_t n_rx_queues, n_tx_queues; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; n_rx_queues = app_get_nic_rx_queues_per_port(portid); n_tx_queues = app.nic_tx_port_mask[portid]; if ((n_rx_queues == 0) && (n_tx_queues == 0)) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } static void app_init_nics(void) { unsigned socket; uint32_t lcore; uint8_t port, queue; int ret; uint32_t n_rx_queues, n_tx_queues; /* Init NIC ports and queues, then start the ports */ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { struct rte_mempool *pool; n_rx_queues = app_get_nic_rx_queues_per_port(port); n_tx_queues = app.nic_tx_port_mask[port]; if ((n_rx_queues == 0) && (n_tx_queues == 0)) { continue; } /* Init port */ printf("Initializing NIC port %u ...\n", (unsigned) port); ret = rte_eth_dev_configure( port, (uint8_t) n_rx_queues, (uint8_t) n_tx_queues, &port_conf); if (ret < 0) { rte_panic("Cannot init NIC port %u (%d)\n", (unsigned) port, ret); } rte_eth_promiscuous_enable(port); /* Init RX queues */ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) { if (app.nic_rx_queue_mask[port][queue] == 0) { continue; } app_get_lcore_for_nic_rx(port, queue, &lcore); socket = rte_lcore_to_socket_id(lcore); pool = app.lcore_params[lcore].pool; printf("Initializing NIC port %u RX queue %u ...\n", (unsigned) port, (unsigned) queue); ret = rte_eth_rx_queue_setup( port, queue, (uint16_t) app.nic_rx_ring_size, socket, NULL, pool); if (ret < 0) { rte_panic("Cannot init RX queue %u for port %u (%d)\n", (unsigned) queue, (unsigned) port, ret); } } /* Init TX queues */ if (app.nic_tx_port_mask[port] == 1) { app_get_lcore_for_nic_tx(port, &lcore); socket = rte_lcore_to_socket_id(lcore); printf("Initializing NIC port %u TX queue 0 ...\n", (unsigned) port); ret = rte_eth_tx_queue_setup( port, 0, (uint16_t) app.nic_tx_ring_size, socket, NULL); if (ret < 0) { rte_panic("Cannot init TX queue 0 for port %d (%d)\n", port, ret); } } /* Start port */ ret = rte_eth_dev_start(port); if (ret < 0) { rte_panic("Cannot start port %d (%d)\n", port, ret); } } check_all_ports_link_status(APP_MAX_NIC_PORTS, (~0x0)); } void app_init(void) { app_assign_worker_ids(); app_init_mbuf_pools(); app_init_lpm_tables(); app_init_rings_rx(); app_init_rings_tx(); app_init_nics(); printf("Initialization completed.\n"); } ================================================ FILE: examples/load_balancer/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" int main(int argc, char **argv) { uint32_t lcore; int ret; /* Init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) return -1; argc -= ret; argv += ret; /* Parse application arguments (after the EAL ones) */ ret = app_parse_args(argc, argv); if (ret < 0) { app_print_usage(); return -1; } /* Init */ app_init(); app_print_params(); /* Launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore) { if (rte_eal_wait_lcore(lcore) < 0) { return -1; } } return 0; } ================================================ FILE: examples/load_balancer/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ /* Logical cores */ #ifndef APP_MAX_SOCKETS #define APP_MAX_SOCKETS 2 #endif #ifndef APP_MAX_LCORES #define APP_MAX_LCORES RTE_MAX_LCORE #endif #ifndef APP_MAX_NIC_PORTS #define APP_MAX_NIC_PORTS RTE_MAX_ETHPORTS #endif #ifndef APP_MAX_RX_QUEUES_PER_NIC_PORT #define APP_MAX_RX_QUEUES_PER_NIC_PORT 128 #endif #ifndef APP_MAX_TX_QUEUES_PER_NIC_PORT #define APP_MAX_TX_QUEUES_PER_NIC_PORT 128 #endif #ifndef APP_MAX_IO_LCORES #define APP_MAX_IO_LCORES 16 #endif #if (APP_MAX_IO_LCORES > APP_MAX_LCORES) #error "APP_MAX_IO_LCORES is too big" #endif #ifndef APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE #define APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE 16 #endif #ifndef APP_MAX_NIC_TX_PORTS_PER_IO_LCORE #define APP_MAX_NIC_TX_PORTS_PER_IO_LCORE 16 #endif #if (APP_MAX_NIC_TX_PORTS_PER_IO_LCORE > APP_MAX_NIC_PORTS) #error "APP_MAX_NIC_TX_PORTS_PER_IO_LCORE too big" #endif #ifndef APP_MAX_WORKER_LCORES #define APP_MAX_WORKER_LCORES 16 #endif #if (APP_MAX_WORKER_LCORES > APP_MAX_LCORES) #error "APP_MAX_WORKER_LCORES is too big" #endif /* Mempools */ #ifndef APP_DEFAULT_MBUF_DATA_SIZE #define APP_DEFAULT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE #endif #ifndef APP_DEFAULT_MEMPOOL_BUFFERS #define APP_DEFAULT_MEMPOOL_BUFFERS 8192 * 4 #endif #ifndef APP_DEFAULT_MEMPOOL_CACHE_SIZE #define APP_DEFAULT_MEMPOOL_CACHE_SIZE 256 #endif /* LPM Tables */ #ifndef APP_MAX_LPM_RULES #define APP_MAX_LPM_RULES 1024 #endif /* NIC RX */ #ifndef APP_DEFAULT_NIC_RX_RING_SIZE #define APP_DEFAULT_NIC_RX_RING_SIZE 1024 #endif /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ #ifndef APP_DEFAULT_NIC_RX_PTHRESH #define APP_DEFAULT_NIC_RX_PTHRESH 8 #endif #ifndef APP_DEFAULT_NIC_RX_HTHRESH #define APP_DEFAULT_NIC_RX_HTHRESH 8 #endif #ifndef APP_DEFAULT_NIC_RX_WTHRESH #define APP_DEFAULT_NIC_RX_WTHRESH 4 #endif #ifndef APP_DEFAULT_NIC_RX_FREE_THRESH #define APP_DEFAULT_NIC_RX_FREE_THRESH 64 #endif #ifndef APP_DEFAULT_NIC_RX_DROP_EN #define APP_DEFAULT_NIC_RX_DROP_EN 0 #endif /* NIC TX */ #ifndef APP_DEFAULT_NIC_TX_RING_SIZE #define APP_DEFAULT_NIC_TX_RING_SIZE 1024 #endif /* * These default values are optimized for use with the Intel(R) 82599 10 GbE * Controller and the DPDK ixgbe PMD. Consider using other values for other * network controllers and/or network drivers. */ #ifndef APP_DEFAULT_NIC_TX_PTHRESH #define APP_DEFAULT_NIC_TX_PTHRESH 36 #endif #ifndef APP_DEFAULT_NIC_TX_HTHRESH #define APP_DEFAULT_NIC_TX_HTHRESH 0 #endif #ifndef APP_DEFAULT_NIC_TX_WTHRESH #define APP_DEFAULT_NIC_TX_WTHRESH 0 #endif #ifndef APP_DEFAULT_NIC_TX_FREE_THRESH #define APP_DEFAULT_NIC_TX_FREE_THRESH 0 #endif #ifndef APP_DEFAULT_NIC_TX_RS_THRESH #define APP_DEFAULT_NIC_TX_RS_THRESH 0 #endif /* Software Rings */ #ifndef APP_DEFAULT_RING_RX_SIZE #define APP_DEFAULT_RING_RX_SIZE 1024 #endif #ifndef APP_DEFAULT_RING_TX_SIZE #define APP_DEFAULT_RING_TX_SIZE 1024 #endif /* Bursts */ #ifndef APP_MBUF_ARRAY_SIZE #define APP_MBUF_ARRAY_SIZE 512 #endif #ifndef APP_DEFAULT_BURST_SIZE_IO_RX_READ #define APP_DEFAULT_BURST_SIZE_IO_RX_READ 144 #endif #if (APP_DEFAULT_BURST_SIZE_IO_RX_READ > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_IO_RX_READ is too big" #endif #ifndef APP_DEFAULT_BURST_SIZE_IO_RX_WRITE #define APP_DEFAULT_BURST_SIZE_IO_RX_WRITE 144 #endif #if (APP_DEFAULT_BURST_SIZE_IO_RX_WRITE > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_IO_RX_WRITE is too big" #endif #ifndef APP_DEFAULT_BURST_SIZE_IO_TX_READ #define APP_DEFAULT_BURST_SIZE_IO_TX_READ 144 #endif #if (APP_DEFAULT_BURST_SIZE_IO_TX_READ > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_IO_TX_READ is too big" #endif #ifndef APP_DEFAULT_BURST_SIZE_IO_TX_WRITE #define APP_DEFAULT_BURST_SIZE_IO_TX_WRITE 144 #endif #if (APP_DEFAULT_BURST_SIZE_IO_TX_WRITE > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_IO_TX_WRITE is too big" #endif #ifndef APP_DEFAULT_BURST_SIZE_WORKER_READ #define APP_DEFAULT_BURST_SIZE_WORKER_READ 144 #endif #if ((2 * APP_DEFAULT_BURST_SIZE_WORKER_READ) > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_WORKER_READ is too big" #endif #ifndef APP_DEFAULT_BURST_SIZE_WORKER_WRITE #define APP_DEFAULT_BURST_SIZE_WORKER_WRITE 144 #endif #if (APP_DEFAULT_BURST_SIZE_WORKER_WRITE > APP_MBUF_ARRAY_SIZE) #error "APP_DEFAULT_BURST_SIZE_WORKER_WRITE is too big" #endif /* Load balancing logic */ #ifndef APP_DEFAULT_IO_RX_LB_POS #define APP_DEFAULT_IO_RX_LB_POS 29 #endif #if (APP_DEFAULT_IO_RX_LB_POS >= 64) #error "APP_DEFAULT_IO_RX_LB_POS is too big" #endif struct app_mbuf_array { struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE]; uint32_t n_mbufs; }; enum app_lcore_type { e_APP_LCORE_DISABLED = 0, e_APP_LCORE_IO, e_APP_LCORE_WORKER }; struct app_lcore_params_io { /* I/O RX */ struct { /* NIC */ struct { uint8_t port; uint8_t queue; } nic_queues[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; uint32_t n_nic_queues; /* Rings */ struct rte_ring *rings[APP_MAX_WORKER_LCORES]; uint32_t n_rings; /* Internal buffers */ struct app_mbuf_array mbuf_in; struct app_mbuf_array mbuf_out[APP_MAX_WORKER_LCORES]; uint8_t mbuf_out_flush[APP_MAX_WORKER_LCORES]; /* Stats */ uint32_t nic_queues_count[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; uint32_t nic_queues_iters[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; uint32_t rings_count[APP_MAX_WORKER_LCORES]; uint32_t rings_iters[APP_MAX_WORKER_LCORES]; } rx; /* I/O TX */ struct { /* Rings */ struct rte_ring *rings[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; /* NIC */ uint8_t nic_ports[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; uint32_t n_nic_ports; /* Internal buffers */ struct app_mbuf_array mbuf_out[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; uint8_t mbuf_out_flush[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; /* Stats */ uint32_t rings_count[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; uint32_t rings_iters[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; uint32_t nic_ports_count[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; uint32_t nic_ports_iters[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; } tx; }; struct app_lcore_params_worker { /* Rings */ struct rte_ring *rings_in[APP_MAX_IO_LCORES]; uint32_t n_rings_in; struct rte_ring *rings_out[APP_MAX_NIC_PORTS]; /* LPM table */ struct rte_lpm *lpm_table; uint32_t worker_id; /* Internal buffers */ struct app_mbuf_array mbuf_in; struct app_mbuf_array mbuf_out[APP_MAX_NIC_PORTS]; uint8_t mbuf_out_flush[APP_MAX_NIC_PORTS]; /* Stats */ uint32_t rings_in_count[APP_MAX_IO_LCORES]; uint32_t rings_in_iters[APP_MAX_IO_LCORES]; uint32_t rings_out_count[APP_MAX_NIC_PORTS]; uint32_t rings_out_iters[APP_MAX_NIC_PORTS]; }; struct app_lcore_params { union { struct app_lcore_params_io io; struct app_lcore_params_worker worker; }; enum app_lcore_type type; struct rte_mempool *pool; } __rte_cache_aligned; struct app_lpm_rule { uint32_t ip; uint8_t depth; uint8_t if_out; }; struct app_params { /* lcore */ struct app_lcore_params lcore_params[APP_MAX_LCORES]; /* NIC */ uint8_t nic_rx_queue_mask[APP_MAX_NIC_PORTS][APP_MAX_RX_QUEUES_PER_NIC_PORT]; uint8_t nic_tx_port_mask[APP_MAX_NIC_PORTS]; /* mbuf pools */ struct rte_mempool *pools[APP_MAX_SOCKETS]; /* LPM tables */ struct rte_lpm *lpm_tables[APP_MAX_SOCKETS]; struct app_lpm_rule lpm_rules[APP_MAX_LPM_RULES]; uint32_t n_lpm_rules; /* rings */ uint32_t nic_rx_ring_size; uint32_t nic_tx_ring_size; uint32_t ring_rx_size; uint32_t ring_tx_size; /* burst size */ uint32_t burst_size_io_rx_read; uint32_t burst_size_io_rx_write; uint32_t burst_size_io_tx_read; uint32_t burst_size_io_tx_write; uint32_t burst_size_worker_read; uint32_t burst_size_worker_write; /* load balancing */ uint8_t pos_lb; } __rte_cache_aligned; extern struct app_params app; int app_parse_args(int argc, char **argv); void app_print_usage(void); void app_init(void); int app_lcore_main_loop(void *arg); int app_get_nic_rx_queues_per_port(uint8_t port); int app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out); int app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out); int app_is_socket_used(uint32_t socket); uint32_t app_get_lcores_io_rx(void); uint32_t app_get_lcores_worker(void); void app_print_params(void); #endif /* _MAIN_H_ */ ================================================ FILE: examples/load_balancer/runtime.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #ifndef APP_LCORE_IO_FLUSH #define APP_LCORE_IO_FLUSH 1000000 #endif #ifndef APP_LCORE_WORKER_FLUSH #define APP_LCORE_WORKER_FLUSH 1000000 #endif #ifndef APP_STATS #define APP_STATS 1000000 #endif #define APP_IO_RX_DROP_ALL_PACKETS 0 #define APP_WORKER_DROP_ALL_PACKETS 0 #define APP_IO_TX_DROP_ALL_PACKETS 0 #ifndef APP_IO_RX_PREFETCH_ENABLE #define APP_IO_RX_PREFETCH_ENABLE 1 #endif #ifndef APP_WORKER_PREFETCH_ENABLE #define APP_WORKER_PREFETCH_ENABLE 1 #endif #ifndef APP_IO_TX_PREFETCH_ENABLE #define APP_IO_TX_PREFETCH_ENABLE 1 #endif #if APP_IO_RX_PREFETCH_ENABLE #define APP_IO_RX_PREFETCH0(p) rte_prefetch0(p) #define APP_IO_RX_PREFETCH1(p) rte_prefetch1(p) #else #define APP_IO_RX_PREFETCH0(p) #define APP_IO_RX_PREFETCH1(p) #endif #if APP_WORKER_PREFETCH_ENABLE #define APP_WORKER_PREFETCH0(p) rte_prefetch0(p) #define APP_WORKER_PREFETCH1(p) rte_prefetch1(p) #else #define APP_WORKER_PREFETCH0(p) #define APP_WORKER_PREFETCH1(p) #endif #if APP_IO_TX_PREFETCH_ENABLE #define APP_IO_TX_PREFETCH0(p) rte_prefetch0(p) #define APP_IO_TX_PREFETCH1(p) rte_prefetch1(p) #else #define APP_IO_TX_PREFETCH0(p) #define APP_IO_TX_PREFETCH1(p) #endif static inline void app_lcore_io_rx_buffer_to_send ( struct app_lcore_params_io *lp, uint32_t worker, struct rte_mbuf *mbuf, uint32_t bsz) { uint32_t pos; int ret; pos = lp->rx.mbuf_out[worker].n_mbufs; lp->rx.mbuf_out[worker].array[pos ++] = mbuf; if (likely(pos < bsz)) { lp->rx.mbuf_out[worker].n_mbufs = pos; return; } ret = rte_ring_sp_enqueue_bulk( lp->rx.rings[worker], (void **) lp->rx.mbuf_out[worker].array, bsz); if (unlikely(ret == -ENOBUFS)) { uint32_t k; for (k = 0; k < bsz; k ++) { struct rte_mbuf *m = lp->rx.mbuf_out[worker].array[k]; rte_pktmbuf_free(m); } } lp->rx.mbuf_out[worker].n_mbufs = 0; lp->rx.mbuf_out_flush[worker] = 0; #if APP_STATS lp->rx.rings_iters[worker] ++; if (likely(ret == 0)) { lp->rx.rings_count[worker] ++; } if (unlikely(lp->rx.rings_iters[worker] == APP_STATS)) { unsigned lcore = rte_lcore_id(); printf("\tI/O RX %u out (worker %u): enq success rate = %.2f\n", lcore, (unsigned)worker, ((double) lp->rx.rings_count[worker]) / ((double) lp->rx.rings_iters[worker])); lp->rx.rings_iters[worker] = 0; lp->rx.rings_count[worker] = 0; } #endif } static inline void app_lcore_io_rx( struct app_lcore_params_io *lp, uint32_t n_workers, uint32_t bsz_rd, uint32_t bsz_wr, uint8_t pos_lb) { struct rte_mbuf *mbuf_1_0, *mbuf_1_1, *mbuf_2_0, *mbuf_2_1; uint8_t *data_1_0, *data_1_1 = NULL; uint32_t i; for (i = 0; i < lp->rx.n_nic_queues; i ++) { uint8_t port = lp->rx.nic_queues[i].port; uint8_t queue = lp->rx.nic_queues[i].queue; uint32_t n_mbufs, j; n_mbufs = rte_eth_rx_burst( port, queue, lp->rx.mbuf_in.array, (uint16_t) bsz_rd); if (unlikely(n_mbufs == 0)) { continue; } #if APP_STATS lp->rx.nic_queues_iters[i] ++; lp->rx.nic_queues_count[i] += n_mbufs; if (unlikely(lp->rx.nic_queues_iters[i] == APP_STATS)) { struct rte_eth_stats stats; unsigned lcore = rte_lcore_id(); rte_eth_stats_get(port, &stats); printf("I/O RX %u in (NIC port %u): NIC drop ratio = %.2f avg burst size = %.2f\n", lcore, (unsigned) port, (double) stats.imissed / (double) (stats.imissed + stats.ipackets), ((double) lp->rx.nic_queues_count[i]) / ((double) lp->rx.nic_queues_iters[i])); lp->rx.nic_queues_iters[i] = 0; lp->rx.nic_queues_count[i] = 0; } #endif #if APP_IO_RX_DROP_ALL_PACKETS for (j = 0; j < n_mbufs; j ++) { struct rte_mbuf *pkt = lp->rx.mbuf_in.array[j]; rte_pktmbuf_free(pkt); } continue; #endif mbuf_1_0 = lp->rx.mbuf_in.array[0]; mbuf_1_1 = lp->rx.mbuf_in.array[1]; data_1_0 = rte_pktmbuf_mtod(mbuf_1_0, uint8_t *); if (likely(n_mbufs > 1)) { data_1_1 = rte_pktmbuf_mtod(mbuf_1_1, uint8_t *); } mbuf_2_0 = lp->rx.mbuf_in.array[2]; mbuf_2_1 = lp->rx.mbuf_in.array[3]; APP_IO_RX_PREFETCH0(mbuf_2_0); APP_IO_RX_PREFETCH0(mbuf_2_1); for (j = 0; j + 3 < n_mbufs; j += 2) { struct rte_mbuf *mbuf_0_0, *mbuf_0_1; uint8_t *data_0_0, *data_0_1; uint32_t worker_0, worker_1; mbuf_0_0 = mbuf_1_0; mbuf_0_1 = mbuf_1_1; data_0_0 = data_1_0; data_0_1 = data_1_1; mbuf_1_0 = mbuf_2_0; mbuf_1_1 = mbuf_2_1; data_1_0 = rte_pktmbuf_mtod(mbuf_2_0, uint8_t *); data_1_1 = rte_pktmbuf_mtod(mbuf_2_1, uint8_t *); APP_IO_RX_PREFETCH0(data_1_0); APP_IO_RX_PREFETCH0(data_1_1); mbuf_2_0 = lp->rx.mbuf_in.array[j+4]; mbuf_2_1 = lp->rx.mbuf_in.array[j+5]; APP_IO_RX_PREFETCH0(mbuf_2_0); APP_IO_RX_PREFETCH0(mbuf_2_1); worker_0 = data_0_0[pos_lb] & (n_workers - 1); worker_1 = data_0_1[pos_lb] & (n_workers - 1); app_lcore_io_rx_buffer_to_send(lp, worker_0, mbuf_0_0, bsz_wr); app_lcore_io_rx_buffer_to_send(lp, worker_1, mbuf_0_1, bsz_wr); } /* Handle the last 1, 2 (when n_mbufs is even) or 3 (when n_mbufs is odd) packets */ for ( ; j < n_mbufs; j += 1) { struct rte_mbuf *mbuf; uint8_t *data; uint32_t worker; mbuf = mbuf_1_0; mbuf_1_0 = mbuf_1_1; mbuf_1_1 = mbuf_2_0; mbuf_2_0 = mbuf_2_1; data = rte_pktmbuf_mtod(mbuf, uint8_t *); APP_IO_RX_PREFETCH0(mbuf_1_0); worker = data[pos_lb] & (n_workers - 1); app_lcore_io_rx_buffer_to_send(lp, worker, mbuf, bsz_wr); } } } static inline void app_lcore_io_rx_flush(struct app_lcore_params_io *lp, uint32_t n_workers) { uint32_t worker; for (worker = 0; worker < n_workers; worker ++) { int ret; if (likely((lp->rx.mbuf_out_flush[worker] == 0) || (lp->rx.mbuf_out[worker].n_mbufs == 0))) { lp->rx.mbuf_out_flush[worker] = 1; continue; } ret = rte_ring_sp_enqueue_bulk( lp->rx.rings[worker], (void **) lp->rx.mbuf_out[worker].array, lp->rx.mbuf_out[worker].n_mbufs); if (unlikely(ret < 0)) { uint32_t k; for (k = 0; k < lp->rx.mbuf_out[worker].n_mbufs; k ++) { struct rte_mbuf *pkt_to_free = lp->rx.mbuf_out[worker].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->rx.mbuf_out[worker].n_mbufs = 0; lp->rx.mbuf_out_flush[worker] = 1; } } static inline void app_lcore_io_tx( struct app_lcore_params_io *lp, uint32_t n_workers, uint32_t bsz_rd, uint32_t bsz_wr) { uint32_t worker; for (worker = 0; worker < n_workers; worker ++) { uint32_t i; for (i = 0; i < lp->tx.n_nic_ports; i ++) { uint8_t port = lp->tx.nic_ports[i]; struct rte_ring *ring = lp->tx.rings[port][worker]; uint32_t n_mbufs, n_pkts; int ret; n_mbufs = lp->tx.mbuf_out[port].n_mbufs; ret = rte_ring_sc_dequeue_bulk( ring, (void **) &lp->tx.mbuf_out[port].array[n_mbufs], bsz_rd); if (unlikely(ret == -ENOENT)) { continue; } n_mbufs += bsz_rd; #if APP_IO_TX_DROP_ALL_PACKETS { uint32_t j; APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[0]); APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[1]); for (j = 0; j < n_mbufs; j ++) { if (likely(j < n_mbufs - 2)) { APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[j + 2]); } rte_pktmbuf_free(lp->tx.mbuf_out[port].array[j]); } lp->tx.mbuf_out[port].n_mbufs = 0; continue; } #endif if (unlikely(n_mbufs < bsz_wr)) { lp->tx.mbuf_out[port].n_mbufs = n_mbufs; continue; } n_pkts = rte_eth_tx_burst( port, 0, lp->tx.mbuf_out[port].array, (uint16_t) n_mbufs); #if APP_STATS lp->tx.nic_ports_iters[port] ++; lp->tx.nic_ports_count[port] += n_pkts; if (unlikely(lp->tx.nic_ports_iters[port] == APP_STATS)) { unsigned lcore = rte_lcore_id(); printf("\t\t\tI/O TX %u out (port %u): avg burst size = %.2f\n", lcore, (unsigned) port, ((double) lp->tx.nic_ports_count[port]) / ((double) lp->tx.nic_ports_iters[port])); lp->tx.nic_ports_iters[port] = 0; lp->tx.nic_ports_count[port] = 0; } #endif if (unlikely(n_pkts < n_mbufs)) { uint32_t k; for (k = n_pkts; k < n_mbufs; k ++) { struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->tx.mbuf_out[port].n_mbufs = 0; lp->tx.mbuf_out_flush[port] = 0; } } } static inline void app_lcore_io_tx_flush(struct app_lcore_params_io *lp) { uint8_t port; for (port = 0; port < lp->tx.n_nic_ports; port ++) { uint32_t n_pkts; if (likely((lp->tx.mbuf_out_flush[port] == 0) || (lp->tx.mbuf_out[port].n_mbufs == 0))) { lp->tx.mbuf_out_flush[port] = 1; continue; } n_pkts = rte_eth_tx_burst( port, 0, lp->tx.mbuf_out[port].array, (uint16_t) lp->tx.mbuf_out[port].n_mbufs); if (unlikely(n_pkts < lp->tx.mbuf_out[port].n_mbufs)) { uint32_t k; for (k = n_pkts; k < lp->tx.mbuf_out[port].n_mbufs; k ++) { struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->tx.mbuf_out[port].n_mbufs = 0; lp->tx.mbuf_out_flush[port] = 1; } } static void app_lcore_main_loop_io(void) { uint32_t lcore = rte_lcore_id(); struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; uint32_t n_workers = app_get_lcores_worker(); uint64_t i = 0; uint32_t bsz_rx_rd = app.burst_size_io_rx_read; uint32_t bsz_rx_wr = app.burst_size_io_rx_write; uint32_t bsz_tx_rd = app.burst_size_io_tx_read; uint32_t bsz_tx_wr = app.burst_size_io_tx_write; uint8_t pos_lb = app.pos_lb; for ( ; ; ) { if (APP_LCORE_IO_FLUSH && (unlikely(i == APP_LCORE_IO_FLUSH))) { if (likely(lp->rx.n_nic_queues > 0)) { app_lcore_io_rx_flush(lp, n_workers); } if (likely(lp->tx.n_nic_ports > 0)) { app_lcore_io_tx_flush(lp); } i = 0; } if (likely(lp->rx.n_nic_queues > 0)) { app_lcore_io_rx(lp, n_workers, bsz_rx_rd, bsz_rx_wr, pos_lb); } if (likely(lp->tx.n_nic_ports > 0)) { app_lcore_io_tx(lp, n_workers, bsz_tx_rd, bsz_tx_wr); } i ++; } } static inline void app_lcore_worker( struct app_lcore_params_worker *lp, uint32_t bsz_rd, uint32_t bsz_wr) { uint32_t i; for (i = 0; i < lp->n_rings_in; i ++) { struct rte_ring *ring_in = lp->rings_in[i]; uint32_t j; int ret; ret = rte_ring_sc_dequeue_bulk( ring_in, (void **) lp->mbuf_in.array, bsz_rd); if (unlikely(ret == -ENOENT)) { continue; } #if APP_WORKER_DROP_ALL_PACKETS for (j = 0; j < bsz_rd; j ++) { struct rte_mbuf *pkt = lp->mbuf_in.array[j]; rte_pktmbuf_free(pkt); } continue; #endif APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[0], unsigned char *)); APP_WORKER_PREFETCH0(lp->mbuf_in.array[1]); for (j = 0; j < bsz_rd; j ++) { struct rte_mbuf *pkt; struct ipv4_hdr *ipv4_hdr; uint32_t ipv4_dst, pos; uint8_t port; if (likely(j < bsz_rd - 1)) { APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[j+1], unsigned char *)); } if (likely(j < bsz_rd - 2)) { APP_WORKER_PREFETCH0(lp->mbuf_in.array[j+2]); } pkt = lp->mbuf_in.array[j]; ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct ipv4_hdr *, sizeof(struct ether_hdr)); ipv4_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); if (unlikely(rte_lpm_lookup(lp->lpm_table, ipv4_dst, &port) != 0)) { port = pkt->port; } pos = lp->mbuf_out[port].n_mbufs; lp->mbuf_out[port].array[pos ++] = pkt; if (likely(pos < bsz_wr)) { lp->mbuf_out[port].n_mbufs = pos; continue; } ret = rte_ring_sp_enqueue_bulk( lp->rings_out[port], (void **) lp->mbuf_out[port].array, bsz_wr); #if APP_STATS lp->rings_out_iters[port] ++; if (ret == 0) { lp->rings_out_count[port] += 1; } if (lp->rings_out_iters[port] == APP_STATS){ printf("\t\tWorker %u out (NIC port %u): enq success rate = %.2f\n", (unsigned) lp->worker_id, (unsigned) port, ((double) lp->rings_out_count[port]) / ((double) lp->rings_out_iters[port])); lp->rings_out_iters[port] = 0; lp->rings_out_count[port] = 0; } #endif if (unlikely(ret == -ENOBUFS)) { uint32_t k; for (k = 0; k < bsz_wr; k ++) { struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->mbuf_out[port].n_mbufs = 0; lp->mbuf_out_flush[port] = 0; } } } static inline void app_lcore_worker_flush(struct app_lcore_params_worker *lp) { uint32_t port; for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { int ret; if (unlikely(lp->rings_out[port] == NULL)) { continue; } if (likely((lp->mbuf_out_flush[port] == 0) || (lp->mbuf_out[port].n_mbufs == 0))) { lp->mbuf_out_flush[port] = 1; continue; } ret = rte_ring_sp_enqueue_bulk( lp->rings_out[port], (void **) lp->mbuf_out[port].array, lp->mbuf_out[port].n_mbufs); if (unlikely(ret < 0)) { uint32_t k; for (k = 0; k < lp->mbuf_out[port].n_mbufs; k ++) { struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k]; rte_pktmbuf_free(pkt_to_free); } } lp->mbuf_out[port].n_mbufs = 0; lp->mbuf_out_flush[port] = 1; } } static void app_lcore_main_loop_worker(void) { uint32_t lcore = rte_lcore_id(); struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; uint64_t i = 0; uint32_t bsz_rd = app.burst_size_worker_read; uint32_t bsz_wr = app.burst_size_worker_write; for ( ; ; ) { if (APP_LCORE_WORKER_FLUSH && (unlikely(i == APP_LCORE_WORKER_FLUSH))) { app_lcore_worker_flush(lp); i = 0; } app_lcore_worker(lp, bsz_rd, bsz_wr); i ++; } } int app_lcore_main_loop(__attribute__((unused)) void *arg) { struct app_lcore_params *lp; unsigned lcore; lcore = rte_lcore_id(); lp = &app.lcore_params[lcore]; if (lp->type == e_APP_LCORE_IO) { printf("Logical core %u (I/O) main loop.\n", lcore); app_lcore_main_loop_io(); } if (lp->type == e_APP_LCORE_WORKER) { printf("Logical core %u (worker %u) main loop.\n", lcore, (unsigned) lp->worker.worker_id); app_lcore_main_loop_worker(); } return 0; } ================================================ FILE: examples/multi_process/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += client_server_mp DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += simple_mp DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += symmetric_mp include $(RTE_SDK)/mk/rte.extsubdir.mk ================================================ FILE: examples/multi_process/client_server_mp/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += mp_client DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += mp_server include $(RTE_SDK)/mk/rte.extsubdir.mk ================================================ FILE: examples/multi_process/client_server_mp/mp_client/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = mp_client # all source are stored in SRCS-y SRCS-y := client.c CFLAGS += $(WERROR_FLAGS) -O3 CFLAGS += -I$(SRCDIR)/../shared include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/multi_process/client_server_mp/mp_client/client.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" /* Number of packets to attempt to read from queue */ #define PKT_READ_SIZE ((uint16_t)32) /* our client id number - tells us which rx queue to read, and NIC TX * queue to write to. */ static uint8_t client_id = 0; struct mbuf_queue { #define MBQ_CAPACITY 32 struct rte_mbuf *bufs[MBQ_CAPACITY]; uint16_t top; }; /* maps input ports to output ports for packets */ static uint8_t output_ports[RTE_MAX_ETHPORTS]; /* buffers up a set of packet that are ready to send */ static struct mbuf_queue output_bufs[RTE_MAX_ETHPORTS]; /* shared data from server. We update statistics here */ static volatile struct tx_stats *tx_stats; /* * print a usage message */ static void usage(const char *progname) { printf("Usage: %s [EAL args] -- -n \n\n", progname); } /* * Convert the client id number from a string to an int. */ static int parse_client_num(const char *client) { char *end = NULL; unsigned long temp; if (client == NULL || *client == '\0') return -1; temp = strtoul(client, &end, 10); if (end == NULL || *end != '\0') return -1; client_id = (uint8_t)temp; return 0; } /* * Parse the application arguments to the client app. */ static int parse_app_args(int argc, char *argv[]) { int option_index, opt; char **argvopt = argv; const char *progname = NULL; static struct option lgopts[] = { /* no long options */ {NULL, 0, 0, 0 } }; progname = argv[0]; while ((opt = getopt_long(argc, argvopt, "n:", lgopts, &option_index)) != EOF){ switch (opt){ case 'n': if (parse_client_num(optarg) != 0){ usage(progname); return -1; } break; default: usage(progname); return -1; } } return 0; } /* * set up output ports so that all traffic on port gets sent out * its paired port. Index using actual port numbers since that is * what comes in the mbuf structure. */ static void configure_output_ports(const struct port_info *ports) { int i; if (ports->num_ports > RTE_MAX_ETHPORTS) rte_exit(EXIT_FAILURE, "Too many ethernet ports. RTE_MAX_ETHPORTS = %u\n", (unsigned)RTE_MAX_ETHPORTS); for (i = 0; i < ports->num_ports - 1; i+=2){ uint8_t p1 = ports->id[i]; uint8_t p2 = ports->id[i+1]; output_ports[p1] = p2; output_ports[p2] = p1; } } static inline void send_packets(uint8_t port) { uint16_t i, sent; struct mbuf_queue *mbq = &output_bufs[port]; if (unlikely(mbq->top == 0)) return; sent = rte_eth_tx_burst(port, client_id, mbq->bufs, mbq->top); if (unlikely(sent < mbq->top)){ for (i = sent; i < mbq->top; i++) rte_pktmbuf_free(mbq->bufs[i]); tx_stats->tx_drop[port] += (mbq->top - sent); } tx_stats->tx[port] += sent; mbq->top = 0; } /* * Enqueue a packet to be sent on a particular port, but * don't send it yet. Only when the buffer is full. */ static inline void enqueue_packet(struct rte_mbuf *buf, uint8_t port) { struct mbuf_queue *mbq = &output_bufs[port]; mbq->bufs[mbq->top++] = buf; if (mbq->top == MBQ_CAPACITY) send_packets(port); } /* * This function performs routing of packets * Just sends each input packet out an output port based solely on the input * port it arrived on. */ static void handle_packet(struct rte_mbuf *buf) { const uint8_t in_port = buf->port; const uint8_t out_port = output_ports[in_port]; enqueue_packet(buf, out_port); } /* * Application main function - loops through * receiving and processing packets. Never returns */ int main(int argc, char *argv[]) { const struct rte_memzone *mz; struct rte_ring *rx_ring; struct rte_mempool *mp; struct port_info *ports; int need_flush = 0; /* indicates whether we have unsent packets */ int retval; void *pkts[PKT_READ_SIZE]; if ((retval = rte_eal_init(argc, argv)) < 0) return -1; argc -= retval; argv += retval; if (parse_app_args(argc, argv) < 0) rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); if (rte_eth_dev_count() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); rx_ring = rte_ring_lookup(get_rx_queue_name(client_id)); if (rx_ring == NULL) rte_exit(EXIT_FAILURE, "Cannot get RX ring - is server process running?\n"); mp = rte_mempool_lookup(PKTMBUF_POOL_NAME); if (mp == NULL) rte_exit(EXIT_FAILURE, "Cannot get mempool for mbufs\n"); mz = rte_memzone_lookup(MZ_PORT_INFO); if (mz == NULL) rte_exit(EXIT_FAILURE, "Cannot get port info structure\n"); ports = mz->addr; tx_stats = &(ports->tx_stats[client_id]); configure_output_ports(ports); RTE_LOG(INFO, APP, "Finished Process Init.\n"); printf("\nClient process %d handling packets\n", client_id); printf("[Press Ctrl-C to quit ...]\n"); for (;;) { uint16_t i, rx_pkts = PKT_READ_SIZE; uint8_t port; /* try dequeuing max possible packets first, if that fails, get the * most we can. Loop body should only execute once, maximum */ while (rx_pkts > 0 && unlikely(rte_ring_dequeue_bulk(rx_ring, pkts, rx_pkts) != 0)) rx_pkts = (uint16_t)RTE_MIN(rte_ring_count(rx_ring), PKT_READ_SIZE); if (unlikely(rx_pkts == 0)){ if (need_flush) for (port = 0; port < ports->num_ports; port++) send_packets(ports->id[port]); need_flush = 0; continue; } for (i = 0; i < rx_pkts; i++) handle_packet(pkts[i]); need_flush = 1; } } ================================================ FILE: examples/multi_process/client_server_mp/mp_server/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif # binary name APP = mp_server # all source are stored in SRCS-y SRCS-y := main.c init.c args.c INC := $(wildcard *.h) CFLAGS += $(WERROR_FLAGS) -O3 CFLAGS += -I$(SRCDIR)/../shared # for newer gcc, e.g. 4.4, no-strict-aliasing may not be necessary # and so the next line can be removed in those cases. EXTRA_CFLAGS += -fno-strict-aliasing include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/multi_process/client_server_mp/mp_server/args.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "common.h" #include "args.h" #include "init.h" /* global var for number of clients - extern in header */ uint8_t num_clients; static const char *progname; /** * Prints out usage information to stdout */ static void usage(void) { printf( "%s [EAL options] -- -p PORTMASK -n NUM_CLIENTS [-s NUM_SOCKETS]\n" " -p PORTMASK: hexadecimal bitmask of ports to use\n" " -n NUM_CLIENTS: number of client processes to use\n" , progname); } /** * The ports to be used by the application are passed in * the form of a bitmask. This function parses the bitmask * and places the port numbers to be used into the port[] * array variable */ static int parse_portmask(uint8_t max_ports, const char *portmask) { char *end = NULL; unsigned long pm; uint8_t count = 0; if (portmask == NULL || *portmask == '\0') return -1; /* convert parameter to a number and verify */ pm = strtoul(portmask, &end, 16); if (end == NULL || *end != '\0' || pm == 0) return -1; /* loop through bits of the mask and mark ports */ while (pm != 0){ if (pm & 0x01){ /* bit is set in mask, use port */ if (count >= max_ports) printf("WARNING: requested port %u not present" " - ignoring\n", (unsigned)count); else ports->id[ports->num_ports++] = count; } pm = (pm >> 1); count++; } return 0; } /** * Take the number of clients parameter passed to the app * and convert to a number to store in the num_clients variable */ static int parse_num_clients(const char *clients) { char *end = NULL; unsigned long temp; if (clients == NULL || *clients == '\0') return -1; temp = strtoul(clients, &end, 10); if (end == NULL || *end != '\0' || temp == 0) return -1; num_clients = (uint8_t)temp; return 0; } /** * The application specific arguments follow the DPDK-specific * arguments which are stripped by the DPDK init. This function * processes these application arguments, printing usage info * on error. */ int parse_app_args(uint8_t max_ports, int argc, char *argv[]) { int option_index, opt; char **argvopt = argv; static struct option lgopts[] = { /* no long options */ {NULL, 0, 0, 0 } }; progname = argv[0]; while ((opt = getopt_long(argc, argvopt, "n:p:", lgopts, &option_index)) != EOF){ switch (opt){ case 'p': if (parse_portmask(max_ports, optarg) != 0){ usage(); return -1; } break; case 'n': if (parse_num_clients(optarg) != 0){ usage(); return -1; } break; default: printf("ERROR: Unknown option '%c'\n", opt); usage(); return -1; } } if (ports->num_ports == 0 || num_clients == 0){ usage(); return -1; } if (ports->num_ports % 2 != 0){ printf("ERROR: application requires an even number of ports to use\n"); return -1; } return 0; } ================================================ FILE: examples/multi_process/client_server_mp/mp_server/args.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ARGS_H_ #define _ARGS_H_ int parse_app_args(uint8_t max_ports, int argc, char *argv[]); #endif /* ifndef _ARGS_H_ */ ================================================ FILE: examples/multi_process/client_server_mp/mp_server/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "args.h" #include "init.h" #define MBUFS_PER_CLIENT 1536 #define MBUFS_PER_PORT 1536 #define MBUF_CACHE_SIZE 512 #define RTE_MP_RX_DESC_DEFAULT 512 #define RTE_MP_TX_DESC_DEFAULT 512 #define CLIENT_QUEUE_RINGSIZE 128 #define NO_FLAGS 0 /* The mbuf pool for packet rx */ struct rte_mempool *pktmbuf_pool; /* array of info/queues for clients */ struct client *clients = NULL; /* the port details */ struct port_info *ports; /** * Initialise the mbuf pool for packet reception for the NIC, and any other * buffer pools needed by the app - currently none. */ static int init_mbuf_pools(void) { const unsigned num_mbufs = (num_clients * MBUFS_PER_CLIENT) \ + (ports->num_ports * MBUFS_PER_PORT); /* don't pass single-producer/single-consumer flags to mbuf create as it * seems faster to use a cache instead */ printf("Creating mbuf pool '%s' [%u mbufs] ...\n", PKTMBUF_POOL_NAME, num_mbufs); pktmbuf_pool = rte_pktmbuf_pool_create(PKTMBUF_POOL_NAME, num_mbufs, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); return (pktmbuf_pool == NULL); /* 0 on success */ } /** * Initialise an individual port: * - configure number of rx and tx rings * - set up each rx ring, to pull from the main mbuf pool * - set up each tx ring * - start the port and report its status to stdout */ static int init_port(uint8_t port_num) { /* for port configuration all features are off by default */ const struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS } }; const uint16_t rx_rings = 1, tx_rings = num_clients; const uint16_t rx_ring_size = RTE_MP_RX_DESC_DEFAULT; const uint16_t tx_ring_size = RTE_MP_TX_DESC_DEFAULT; uint16_t q; int retval; printf("Port %u init ... ", (unsigned)port_num); fflush(stdout); /* Standard DPDK port initialisation - config port, then set up * rx and tx rings */ if ((retval = rte_eth_dev_configure(port_num, rx_rings, tx_rings, &port_conf)) != 0) return retval; for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port_num, q, rx_ring_size, rte_eth_dev_socket_id(port_num), NULL, pktmbuf_pool); if (retval < 0) return retval; } for ( q = 0; q < tx_rings; q ++ ) { retval = rte_eth_tx_queue_setup(port_num, q, tx_ring_size, rte_eth_dev_socket_id(port_num), NULL); if (retval < 0) return retval; } rte_eth_promiscuous_enable(port_num); retval = rte_eth_dev_start(port_num); if (retval < 0) return retval; printf( "done: \n"); return 0; } /** * Set up the DPDK rings which will be used to pass packets, via * pointers, between the multi-process server and client processes. * Each client needs one RX queue. */ static int init_shm_rings(void) { unsigned i; unsigned socket_id; const char * q_name; const unsigned ringsize = CLIENT_QUEUE_RINGSIZE; clients = rte_malloc("client details", sizeof(*clients) * num_clients, 0); if (clients == NULL) rte_exit(EXIT_FAILURE, "Cannot allocate memory for client program details\n"); for (i = 0; i < num_clients; i++) { /* Create an RX queue for each client */ socket_id = rte_socket_id(); q_name = get_rx_queue_name(i); clients[i].rx_q = rte_ring_create(q_name, ringsize, socket_id, RING_F_SP_ENQ | RING_F_SC_DEQ ); /* single prod, single cons */ if (clients[i].rx_q == NULL) rte_exit(EXIT_FAILURE, "Cannot create rx ring queue for client %u\n", i); } return 0; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << ports->id[portid])) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(ports->id[portid], &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", ports->id[portid], (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)ports->id[portid]); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } /** * Main init function for the multi-process server app, * calls subfunctions to do each stage of the initialisation. */ int init(int argc, char *argv[]) { int retval; const struct rte_memzone *mz; uint8_t i, total_ports; /* init EAL, parsing EAL args */ retval = rte_eal_init(argc, argv); if (retval < 0) return -1; argc -= retval; argv += retval; /* get total number of ports */ total_ports = rte_eth_dev_count(); /* set up array for port data */ mz = rte_memzone_reserve(MZ_PORT_INFO, sizeof(*ports), rte_socket_id(), NO_FLAGS); if (mz == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for port information\n"); memset(mz->addr, 0, sizeof(*ports)); ports = mz->addr; /* parse additional, application arguments */ retval = parse_app_args(total_ports, argc, argv); if (retval != 0) return -1; /* initialise mbuf pools */ retval = init_mbuf_pools(); if (retval != 0) rte_exit(EXIT_FAILURE, "Cannot create needed mbuf pools\n"); /* now initialise the ports we will use */ for (i = 0; i < ports->num_ports; i++) { retval = init_port(ports->id[i]); if (retval != 0) rte_exit(EXIT_FAILURE, "Cannot initialise port %u\n", (unsigned)i); } check_all_ports_link_status(ports->num_ports, (~0x0)); /* initialise the client queues/rings for inter-eu comms */ init_shm_rings(); return 0; } ================================================ FILE: examples/multi_process/client_server_mp/mp_server/init.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _INIT_H_ #define _INIT_H_ /* * #include * #include "args.h" */ /* * Define a client structure with all needed info, including * stats from the clients. */ struct client { struct rte_ring *rx_q; unsigned client_id; /* these stats hold how many packets the client will actually receive, * and how many packets were dropped because the client's queue was full. * The port-info stats, in contrast, record how many packets were received * or transmitted on an actual NIC port. */ struct { volatile uint64_t rx; volatile uint64_t rx_drop; } stats; }; extern struct client *clients; /* the shared port information: port numbers, rx and tx stats etc. */ extern struct port_info *ports; extern struct rte_mempool *pktmbuf_pool; extern uint8_t num_clients; extern unsigned num_sockets; extern struct port_info *ports; int init(int argc, char *argv[]); #endif /* ifndef _INIT_H_ */ ================================================ FILE: examples/multi_process/client_server_mp/mp_server/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "args.h" #include "init.h" /* * When doing reads from the NIC or the client queues, * use this batch size */ #define PACKET_READ_SIZE 32 /* * Local buffers to put packets in, used to send packets in bursts to the * clients */ struct client_rx_buf { struct rte_mbuf *buffer[PACKET_READ_SIZE]; uint16_t count; }; /* One buffer per client rx queue - dynamically allocate array */ static struct client_rx_buf *cl_rx_buf; static const char * get_printable_mac_addr(uint8_t port) { static const char err_address[] = "00:00:00:00:00:00"; static char addresses[RTE_MAX_ETHPORTS][sizeof(err_address)]; if (unlikely(port >= RTE_MAX_ETHPORTS)) return err_address; if (unlikely(addresses[port][0]=='\0')){ struct ether_addr mac; rte_eth_macaddr_get(port, &mac); snprintf(addresses[port], sizeof(addresses[port]), "%02x:%02x:%02x:%02x:%02x:%02x\n", mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); } return addresses[port]; } /* * This function displays the recorded statistics for each port * and for each client. It uses ANSI terminal codes to clear * screen when called. It is called from a single non-master * thread in the server process, when the process is run with more * than one lcore enabled. */ static void do_stats_display(void) { unsigned i, j; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; uint64_t port_tx[RTE_MAX_ETHPORTS], port_tx_drop[RTE_MAX_ETHPORTS]; uint64_t client_tx[MAX_CLIENTS], client_tx_drop[MAX_CLIENTS]; /* to get TX stats, we need to do some summing calculations */ memset(port_tx, 0, sizeof(port_tx)); memset(port_tx_drop, 0, sizeof(port_tx_drop)); memset(client_tx, 0, sizeof(client_tx)); memset(client_tx_drop, 0, sizeof(client_tx_drop)); for (i = 0; i < num_clients; i++){ const volatile struct tx_stats *tx = &ports->tx_stats[i]; for (j = 0; j < ports->num_ports; j++){ /* assign to local variables here, save re-reading volatile vars */ const uint64_t tx_val = tx->tx[ports->id[j]]; const uint64_t drop_val = tx->tx_drop[ports->id[j]]; port_tx[j] += tx_val; port_tx_drop[j] += drop_val; client_tx[i] += tx_val; client_tx_drop[i] += drop_val; } } /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("PORTS\n"); printf("-----\n"); for (i = 0; i < ports->num_ports; i++) printf("Port %u: '%s'\t", (unsigned)ports->id[i], get_printable_mac_addr(ports->id[i])); printf("\n\n"); for (i = 0; i < ports->num_ports; i++){ printf("Port %u - rx: %9"PRIu64"\t" "tx: %9"PRIu64"\n", (unsigned)ports->id[i], ports->rx_stats.rx[i], port_tx[i]); } printf("\nCLIENTS\n"); printf("-------\n"); for (i = 0; i < num_clients; i++){ const unsigned long long rx = clients[i].stats.rx; const unsigned long long rx_drop = clients[i].stats.rx_drop; printf("Client %2u - rx: %9llu, rx_drop: %9llu\n" " tx: %9"PRIu64", tx_drop: %9"PRIu64"\n", i, rx, rx_drop, client_tx[i], client_tx_drop[i]); } printf("\n"); } /* * The function called from each non-master lcore used by the process. * The test_and_set function is used to randomly pick a single lcore on which * the code to display the statistics will run. Otherwise, the code just * repeatedly sleeps. */ static int sleep_lcore(__attribute__((unused)) void *dummy) { /* Used to pick a display thread - static, so zero-initialised */ static rte_atomic32_t display_stats; /* Only one core should display stats */ if (rte_atomic32_test_and_set(&display_stats)) { const unsigned sleeptime = 1; printf("Core %u displaying statistics\n", rte_lcore_id()); /* Longer initial pause so above printf is seen */ sleep(sleeptime * 3); /* Loop forever: sleep always returns 0 or <= param */ while (sleep(sleeptime) <= sleeptime) do_stats_display(); } return 0; } /* * Function to set all the client statistic values to zero. * Called at program startup. */ static void clear_stats(void) { unsigned i; for (i = 0; i < num_clients; i++) clients[i].stats.rx = clients[i].stats.rx_drop = 0; } /* * send a burst of traffic to a client, assuming there are packets * available to be sent to this client */ static void flush_rx_queue(uint16_t client) { uint16_t j; struct client *cl; if (cl_rx_buf[client].count == 0) return; cl = &clients[client]; if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[client].buffer, cl_rx_buf[client].count) != 0){ for (j = 0; j < cl_rx_buf[client].count; j++) rte_pktmbuf_free(cl_rx_buf[client].buffer[j]); cl->stats.rx_drop += cl_rx_buf[client].count; } else cl->stats.rx += cl_rx_buf[client].count; cl_rx_buf[client].count = 0; } /* * marks a packet down to be sent to a particular client process */ static inline void enqueue_rx_packet(uint8_t client, struct rte_mbuf *buf) { cl_rx_buf[client].buffer[cl_rx_buf[client].count++] = buf; } /* * This function takes a group of packets and routes them * individually to the client process. Very simply round-robins the packets * without checking any of the packet contents. */ static void process_packets(uint32_t port_num __rte_unused, struct rte_mbuf *pkts[], uint16_t rx_count) { uint16_t i; uint8_t client = 0; for (i = 0; i < rx_count; i++) { enqueue_rx_packet(client, pkts[i]); if (++client == num_clients) client = 0; } for (i = 0; i < num_clients; i++) flush_rx_queue(i); } /* * Function called by the master lcore of the DPDK process. */ static void do_packet_forwarding(void) { unsigned port_num = 0; /* indexes the port[] array */ for (;;) { struct rte_mbuf *buf[PACKET_READ_SIZE]; uint16_t rx_count; /* read a port */ rx_count = rte_eth_rx_burst(ports->id[port_num], 0, \ buf, PACKET_READ_SIZE); ports->rx_stats.rx[port_num] += rx_count; /* Now process the NIC packets read */ if (likely(rx_count > 0)) process_packets(port_num, buf, rx_count); /* move to next port */ if (++port_num == ports->num_ports) port_num = 0; } } int main(int argc, char *argv[]) { /* initialise the system */ if (init(argc, argv) < 0 ) return -1; RTE_LOG(INFO, APP, "Finished Process Init.\n"); cl_rx_buf = calloc(num_clients, sizeof(cl_rx_buf[0])); /* clear statistics */ clear_stats(); /* put all other cores to sleep bar master */ rte_eal_mp_remote_launch(sleep_lcore, NULL, SKIP_MASTER); do_packet_forwarding(); return 0; } ================================================ FILE: examples/multi_process/client_server_mp/shared/common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _COMMON_H_ #define _COMMON_H_ #define MAX_CLIENTS 16 /* * Shared port info, including statistics information for display by server. * Structure will be put in a memzone. * - All port id values share one cache line as this data will be read-only * during operation. * - All rx statistic values share cache lines, as this data is written only * by the server process. (rare reads by stats display) * - The tx statistics have values for all ports per cache line, but the stats * themselves are written by the clients, so we have a distinct set, on different * cache lines for each client to use. */ struct rx_stats{ uint64_t rx[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct tx_stats{ uint64_t tx[RTE_MAX_ETHPORTS]; uint64_t tx_drop[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct port_info { uint8_t num_ports; uint8_t id[RTE_MAX_ETHPORTS]; volatile struct rx_stats rx_stats; volatile struct tx_stats tx_stats[MAX_CLIENTS]; }; /* define common names for structures shared between server and client */ #define MP_CLIENT_RXQ_NAME "MProc_Client_%u_RX" #define PKTMBUF_POOL_NAME "MProc_pktmbuf_pool" #define MZ_PORT_INFO "MProc_port_info" /* * Given the rx queue name template above, get the queue name */ static inline const char * get_rx_queue_name(unsigned id) { /* buffer for return value. Size calculated by %u being replaced * by maximum 3 digits (plus an extra byte for safety) */ static char buffer[sizeof(MP_CLIENT_RXQ_NAME) + 2]; snprintf(buffer, sizeof(buffer) - 1, MP_CLIENT_RXQ_NAME, id); return buffer; } #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 #endif ================================================ FILE: examples/multi_process/l2fwd_fork/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = l2fwd_fork # all source are stored in SRCS-y SRCS-y := main.c flib.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/multi_process/l2fwd_fork/flib.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "flib.h" #define SIG_PARENT_EXIT SIGUSR1 struct lcore_stat { pid_t pid; /**< pthread identifier */ lcore_function_t *f; /**< function to call */ void *arg; /**< argument of function */ slave_exit_notify *cb_fn; } __rte_cache_aligned; static struct lcore_stat *core_cfg; static uint16_t *lcore_cfg = NULL; /* signal handler to be notified after parent leaves */ static void sighand_parent_exit(int sig) { printf("lcore = %u : Find parent leaves, sig=%d\n", rte_lcore_id(), sig); printf("Child leaving\n"); exit(0); return; } /** * Real function entrance ran in slave process **/ static int slave_proc_func(void) { struct rte_config *config; unsigned slave_id = rte_lcore_id(); struct lcore_stat *cfg = &core_cfg[slave_id]; if (prctl(PR_SET_PDEATHSIG, SIG_PARENT_EXIT, 0, 0, 0, 0) != 0) printf("Warning: Slave can't register for being notified in" "case master process exited\n"); else { struct sigaction act; memset(&act, 0 , sizeof(act)); act.sa_handler = sighand_parent_exit; if (sigaction(SIG_PARENT_EXIT, &act, NULL) != 0) printf("Fail to register signal handler:%d\n", SIG_PARENT_EXIT); } /* Set slave process to SECONDARY to avoid operation like dev_start/stop etc */ config = rte_eal_get_configuration(); if (NULL == config) printf("Warning:Can't get rte_config\n"); else config->process_type = RTE_PROC_SECONDARY; printf("Core %u is ready (pid=%d)\n", slave_id, (int)cfg->pid); exit(cfg->f(cfg->arg)); } /** * function entrance ran in master thread, which will spawn slave process and wait until * specific slave exited. **/ static int lcore_func(void *arg __attribute__((unused))) { unsigned slave_id = rte_lcore_id(); struct lcore_stat *cfg = &core_cfg[slave_id]; int pid, stat; if (rte_get_master_lcore() == slave_id) return cfg->f(cfg->arg); /* fork a slave process */ pid = fork(); if (pid == -1) { printf("Failed to fork\n"); return -1; } else if (pid == 0) /* child */ return slave_proc_func(); else { /* parent */ cfg->pid = pid; waitpid(pid, &stat, 0); cfg->pid = 0; cfg->f = NULL; cfg->arg = NULL; /* Notify slave's exit if applicable */ if(cfg->cb_fn) cfg->cb_fn(slave_id, stat); return stat; } } static int lcore_id_init(void) { int i; /* Setup lcore ID allocation map */ lcore_cfg = rte_zmalloc("LCORE_ID_MAP", sizeof(uint16_t) * RTE_MAX_LCORE, RTE_CACHE_LINE_SIZE); if(lcore_cfg == NULL) rte_panic("Failed to malloc\n"); for (i = 0; i < RTE_MAX_LCORE; i++) { if (rte_lcore_is_enabled(i)) lcore_cfg[i] = 1; } return 0; } int flib_assign_lcore_id(void) { unsigned i; int ret; /** * thread assigned a lcore id previously, or a slave thread. But still have * a bug here: If the core mask includes core 0, and that core call this * function, it still can get a new lcore id. **/ if (rte_lcore_id() != 0) return -1; do { /* Find a lcore id not used yet, avoid to use lcore ID 0 */ for (i = 1; i < RTE_MAX_LCORE; i++) { if (lcore_cfg[i] == 0) break; } if (i == RTE_MAX_LCORE) return -1; /* Assign new lcore id to this thread */ ret = rte_atomic16_cmpset(&lcore_cfg[i], 0, 1); } while (unlikely(ret == 0)); RTE_PER_LCORE(_lcore_id) = i; return i; } void flib_free_lcore_id(unsigned lcore_id) { /* id is not valid or belongs to pinned core id */ if (lcore_id >= RTE_MAX_LCORE || lcore_id == 0 || rte_lcore_is_enabled(lcore_id)) return; lcore_cfg[lcore_id] = 0; } int flib_register_slave_exit_notify(unsigned slave_id, slave_exit_notify *cb) { if (cb == NULL) return -EFAULT; if (!rte_lcore_is_enabled(slave_id)) return -ENOENT; core_cfg[slave_id].cb_fn = cb; return 0; } enum slave_stat flib_query_slave_status(unsigned slave_id) { if (!rte_lcore_is_enabled(slave_id)) return ST_FREEZE; /* pid only be set when slave process spawned */ if (core_cfg[slave_id].pid != 0) return ST_RUN; else return ST_IDLE; } int flib_remote_launch(lcore_function_t *f, void *arg, unsigned slave_id) { if (f == NULL) return -1; if (!rte_lcore_is_enabled(slave_id)) return -1; /* Wait until specific lcore state change to WAIT */ rte_eal_wait_lcore(slave_id); core_cfg[slave_id].f = f; core_cfg[slave_id].arg = arg; return rte_eal_remote_launch(lcore_func, NULL, slave_id); } int flib_mp_remote_launch(lcore_function_t *f, void *arg, enum rte_rmt_call_master_t call_master) { int i; RTE_LCORE_FOREACH_SLAVE(i) { core_cfg[i].arg = arg; core_cfg[i].f = f; } return rte_eal_mp_remote_launch(lcore_func, NULL, call_master); } int flib_init(void) { if ((core_cfg = rte_zmalloc("core_cfg", sizeof(struct lcore_stat) * RTE_MAX_LCORE, RTE_CACHE_LINE_SIZE)) == NULL ) { printf("rte_zmalloc failed\n"); return -1; } if (lcore_id_init() != 0) { printf("lcore_id_init failed\n"); return -1; } return 0; } ================================================ FILE: examples/multi_process/l2fwd_fork/flib.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __FLIB_H #define __FLIB_H /* callback function pointer when specific slave leaves */ typedef void (slave_exit_notify)(unsigned slaveid, int stat); enum slave_stat{ ST_FREEZE = 1, ST_IDLE, ST_RUN, ST_ZOMBIE, /* Not implemented yet */ }; /** * Initialize the fork lib. * * @return * - 0 : fork lib initialized successfully * - -1 : fork lib initialized failed */ int flib_init(void); /** * Check that every SLAVE lcores are in WAIT state, then call * flib_remote_launch() for all of them. If call_master is true * (set to CALL_MASTER), also call the function on the master lcore. * * @param f: * function pointer need to run * @param arg: * argument for f to carry * @param call_master * - SKIP_MASTER : only launch function on slave lcores * - CALL_MASTER : launch function on master and slave lcores * @return * - 0 : function execute successfully * - -1 : function execute failed */ int flib_mp_remote_launch(lcore_function_t *f, void *arg, enum rte_rmt_call_master_t call_master); /** * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. * * @param f: * function pointer need to run * @param arg: * argument for f to carry * @param slave_id * slave lcore id to run on * @return * - 0 : function execute successfully * - -1 : function execute failed */ int flib_remote_launch(lcore_function_t *f, void *arg, unsigned slave_id); /** * Query the running stat for specific slave, wont' work in with master id * * @param slave_id: * lcore id which should not be master id * @return * - ST_FREEZE : lcore is not in enabled core mask * - ST_IDLE : lcore is idle * - ST_RUN : lcore is running something */ enum slave_stat flib_query_slave_status(unsigned slave_id); /** * Register a callback function to be notified in case specific slave exit. * * @param slave_id: * lcore id which should not be master id * @param cb: * callback pointer to register * @return * - 0 : function execute successfully * - -EFAULT : argument error * - -ENOENT : slave_id not correct */ int flib_register_slave_exit_notify(unsigned slave_id, slave_exit_notify *cb); /** * Assign a lcore ID to non-slave thread. Non-slave thread refers to thread that * not created by function rte_eal_remote_launch or rte_eal_mp_remote_launch. * These threads can either bind lcore or float among differnt lcores. * This lcore ID will be unique in multi-thread or multi-process DPDK running * environment, then it can benefit from using the cache mechanism provided in * mempool library. * After calling successfully, use rte_lcore_id() to get the assigned lcore ID, but * other lcore funtions can't guarantee to work correctly. * * @return * - -1 : can't assign a lcore id with 3 possibilities. * - it's not non-slave thread. * - it had assign a lcore id previously * - the lcore id is running out. * - > 0 : the assigned lcore id. */ int flib_assign_lcore_id(void); /** * Free the lcore_id that assigned in flib_assign_lcore_id(). * call it in case non-slave thread is leaving or left. * * @param lcore_id * The identifier of the lcore, which MUST be between 1 and * RTE_MAX_LCORE-1. */ void flib_free_lcore_id(unsigned lcore_id); #endif /* __FLIB_H */ ================================================ FILE: examples/multi_process/l2fwd_fork/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "flib.h" #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 #define MBUF_NAME "mbuf_pool_%d" #define MBUF_SIZE \ (RTE_MBUF_DEFAULT_DATAROOM + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) #define NB_MBUF 8192 #define RING_MASTER_NAME "l2fwd_ring_m2s_" #define RING_SLAVE_NAME "l2fwd_ring_s2m_" #define MAX_NAME_LEN 32 /* RECREATE flag indicate needs initialize resource and launch slave_core again */ #define SLAVE_RECREATE_FLAG 0x1 /* RESTART flag indicate needs restart port and send START command again */ #define SLAVE_RESTART_FLAG 0x2 #define INVALID_MAPPING_ID ((unsigned)LCORE_ID_ANY) /* Maximum message buffer per slave */ #define NB_CORE_MSGBUF 32 enum l2fwd_cmd{ CMD_START, CMD_STOP, }; #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /* ethernet addresses of ports */ static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; /* mask of enabled ports */ static uint32_t l2fwd_enabled_port_mask = 0; /* list of enabled ports */ static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; static unsigned int l2fwd_rx_queue_per_lcore = 1; struct mbuf_table { unsigned len; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; #define MAX_RX_QUEUE_PER_LCORE 16 #define MAX_TX_QUEUE_PER_PORT 16 struct lcore_queue_conf { unsigned n_rx_port; unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; } __rte_cache_aligned; struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; struct lcore_resource_struct { int enabled; /* Only set in case this lcore involved into packet forwarding */ int flags; /* Set only slave need to restart or recreate */ unsigned lcore_id; /* lcore ID */ unsigned pair_id; /* dependency lcore ID on port */ char ring_name[2][MAX_NAME_LEN]; /* ring[0] for master send cmd, slave read */ /* ring[1] for slave send ack, master read */ struct rte_ring *ring[2]; int port_num; /* Total port numbers */ uint8_t port[RTE_MAX_ETHPORTS]; /* Port id for that lcore to receive packets */ }__attribute__((packed)) __rte_cache_aligned; static struct lcore_resource_struct lcore_resource[RTE_MAX_LCORE]; static struct rte_mempool *message_pool; static rte_spinlock_t res_lock = RTE_SPINLOCK_INITIALIZER; /* use floating processes */ static int float_proc = 0; /* Save original cpu affinity */ struct cpu_aff_arg{ cpu_set_t set; size_t size; }cpu_aff; static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; static struct rte_mempool * l2fwd_pktmbuf_pool[RTE_MAX_ETHPORTS]; /* Per-port statistics struct */ struct l2fwd_port_statistics { uint64_t tx; uint64_t rx; uint64_t dropped; } __rte_cache_aligned; struct l2fwd_port_statistics *port_statistics; /** * pointer to lcore ID mapping array, used to return lcore id in case slave * process exited unexpectedly, use only floating process option applied **/ unsigned *mapping_id; /* A tsc-based timer responsible for triggering statistics printout */ #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ #define MAX_TIMER_PERIOD 86400 /* 1 day max */ static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ static int l2fwd_launch_one_lcore(void *dummy); /* Print out statistics on packets dropped */ static void print_stats(void) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid; total_packets_dropped = 0; total_packets_tx = 0; total_packets_rx = 0; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); printf("\nPort statistics ===================================="); for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { /* skip disabled ports */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; printf("\nStatistics for port %u ------------------------------" "\nPackets sent: %24"PRIu64 "\nPackets received: %20"PRIu64 "\nPackets dropped: %21"PRIu64, portid, port_statistics[portid].tx, port_statistics[portid].rx, port_statistics[portid].dropped); total_packets_dropped += port_statistics[portid].dropped; total_packets_tx += port_statistics[portid].tx; total_packets_rx += port_statistics[portid].rx; } printf("\nAggregate statistics ===============================" "\nTotal packets sent: %18"PRIu64 "\nTotal packets received: %14"PRIu64 "\nTotal packets dropped: %15"PRIu64, total_packets_tx, total_packets_rx, total_packets_dropped); printf("\n====================================================\n"); } static int clear_cpu_affinity(void) { int s; s = sched_setaffinity(0, cpu_aff.size, &cpu_aff.set); if (s != 0) { printf("sched_setaffinity failed:%s\n", strerror(errno)); return -1; } return 0; } static int get_cpu_affinity(void) { int s; cpu_aff.size = sizeof(cpu_set_t); CPU_ZERO(&cpu_aff.set); s = sched_getaffinity(0, cpu_aff.size, &cpu_aff.set); if (s != 0) { printf("sched_getaffinity failed:%s\n", strerror(errno)); return -1; } return 0; } /** * This fnciton demonstrates the approach to create ring in first instance * or re-attach an existed ring in later instance. **/ static struct rte_ring * create_ring(const char *name, unsigned count, int socket_id,unsigned flags) { struct rte_ring *ring; if (name == NULL) return NULL; /* If already create, just attached it */ if (likely((ring = rte_ring_lookup(name)) != NULL)) return ring; /* First call it, create one */ return rte_ring_create(name, count, socket_id, flags); } /* Malloc with rte_malloc on structures that shared by master and slave */ static int l2fwd_malloc_shared_struct(void) { port_statistics = rte_zmalloc("port_stat", sizeof(struct l2fwd_port_statistics) * RTE_MAX_ETHPORTS, 0); if (port_statistics == NULL) return -1; /* allocate mapping_id array */ if (float_proc) { int i; mapping_id = rte_malloc("mapping_id", sizeof(unsigned) * RTE_MAX_LCORE, 0); if (mapping_id == NULL) return -1; for (i = 0 ;i < RTE_MAX_LCORE; i++) mapping_id[i] = INVALID_MAPPING_ID; } return 0; } /* Create ring which used for communicate among master and slave */ static int create_ms_ring(unsigned slaveid) { unsigned flag = RING_F_SP_ENQ | RING_F_SC_DEQ; struct lcore_resource_struct *res = &lcore_resource[slaveid]; unsigned socketid = rte_socket_id(); /* Always assume create ring on master socket_id */ /* Default only create a ring size 32 */ snprintf(res->ring_name[0], MAX_NAME_LEN, "%s%u", RING_MASTER_NAME, slaveid); if ((res->ring[0] = create_ring(res->ring_name[0], NB_CORE_MSGBUF, socketid, flag)) == NULL) { printf("Create m2s ring %s failed\n", res->ring_name[0]); return -1; } snprintf(res->ring_name[1], MAX_NAME_LEN, "%s%u", RING_SLAVE_NAME, slaveid); if ((res->ring[1] = create_ring(res->ring_name[1], NB_CORE_MSGBUF, socketid, flag)) == NULL) { printf("Create s2m ring %s failed\n", res->ring_name[1]); return -1; } return 0; } /* send command to pair in paired master and slave ring */ static inline int sendcmd(unsigned slaveid, enum l2fwd_cmd cmd, int is_master) { struct lcore_resource_struct *res = &lcore_resource[slaveid]; void *msg; int fd = !is_master; /* Only check master, it must be enabled and running if it is slave */ if (is_master && !res->enabled) return -1; if (res->ring[fd] == NULL) return -1; if (rte_mempool_get(message_pool, &msg) < 0) { printf("Error to get message buffer\n"); return -1; } *(enum l2fwd_cmd *)msg = cmd; if (rte_ring_enqueue(res->ring[fd], msg) != 0) { printf("Enqueue error\n"); rte_mempool_put(message_pool, msg); return -1; } return 0; } /* Get command from pair in paired master and slave ring */ static inline int getcmd(unsigned slaveid, enum l2fwd_cmd *cmd, int is_master) { struct lcore_resource_struct *res = &lcore_resource[slaveid]; void *msg; int fd = !!is_master; int ret; /* Only check master, it must be enabled and running if it is slave */ if (is_master && (!res->enabled)) return -1; if (res->ring[fd] == NULL) return -1; ret = rte_ring_dequeue(res->ring[fd], &msg); if (ret == 0) { *cmd = *(enum l2fwd_cmd *)msg; rte_mempool_put(message_pool, msg); } return ret; } /* Master send command to slave and wait until ack received or error met */ static int master_sendcmd_with_ack(unsigned slaveid, enum l2fwd_cmd cmd) { enum l2fwd_cmd ack_cmd; int ret = -1; if (sendcmd(slaveid, cmd, 1) != 0) rte_exit(EXIT_FAILURE, "Failed to send message\n"); /* Get ack */ while (1) { ret = getcmd(slaveid, &ack_cmd, 1); if (ret == 0 && cmd == ack_cmd) break; /* If slave not running yet, return an error */ if (flib_query_slave_status(slaveid) != ST_RUN) { ret = -ENOENT; break; } } return ret; } /* restart all port that assigned to that slave lcore */ static int reset_slave_all_ports(unsigned slaveid) { struct lcore_resource_struct *slave = &lcore_resource[slaveid]; int i, ret = 0; /* stop/start port */ for (i = 0; i < slave->port_num; i++) { char buf_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *pool; printf("Stop port :%d\n", slave->port[i]); rte_eth_dev_stop(slave->port[i]); snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, slave->port[i]); pool = rte_mempool_lookup(buf_name); if (pool) printf("Port %d mempool free object is %u(%u)\n", slave->port[i], rte_mempool_count(pool), (unsigned)NB_MBUF); else printf("Can't find mempool %s\n", buf_name); printf("Start port :%d\n", slave->port[i]); ret = rte_eth_dev_start(slave->port[i]); if (ret != 0) break; } return ret; } static int reset_shared_structures(unsigned slaveid) { int ret; /* Only port are shared resource here */ ret = reset_slave_all_ports(slaveid); return ret; } /** * Call this function to re-create resource that needed for slave process that * exited in last instance **/ static int init_slave_res(unsigned slaveid) { struct lcore_resource_struct *slave = &lcore_resource[slaveid]; enum l2fwd_cmd cmd; if (!slave->enabled) { printf("Something wrong with lcore=%u enabled=%d\n",slaveid, slave->enabled); return -1; } /* Initialize ring */ if (create_ms_ring(slaveid) != 0) rte_exit(EXIT_FAILURE, "failed to create ring for slave %u\n", slaveid); /* drain un-read buffer if have */ while (getcmd(slaveid, &cmd, 1) == 0); while (getcmd(slaveid, &cmd, 0) == 0); return 0; } static int recreate_one_slave(unsigned slaveid) { int ret = 0; /* Re-initialize resource for stalled slave */ if ((ret = init_slave_res(slaveid)) != 0) { printf("Init slave=%u failed\n", slaveid); return ret; } if ((ret = flib_remote_launch(l2fwd_launch_one_lcore, NULL, slaveid)) != 0) printf("Launch slave %u failed\n", slaveid); return ret; } /** * remapping resource belong to slave_id to new lcore that gets from flib_assign_lcore_id(), * used only floating process option applied. * * @param slaveid * original lcore_id that apply for remapping */ static void remapping_slave_resource(unsigned slaveid, unsigned map_id) { /* remapping lcore_resource */ memcpy(&lcore_resource[map_id], &lcore_resource[slaveid], sizeof(struct lcore_resource_struct)); /* remapping lcore_queue_conf */ memcpy(&lcore_queue_conf[map_id], &lcore_queue_conf[slaveid], sizeof(struct lcore_queue_conf)); } static int reset_pair(unsigned slaveid, unsigned pairid) { int ret; if ((ret = reset_shared_structures(slaveid)) != 0) goto back; if((ret = reset_shared_structures(pairid)) != 0) goto back; if (float_proc) { unsigned map_id = mapping_id[slaveid]; if (map_id != INVALID_MAPPING_ID) { printf("%u return mapping id %u\n", slaveid, map_id); flib_free_lcore_id(map_id); mapping_id[slaveid] = INVALID_MAPPING_ID; } map_id = mapping_id[pairid]; if (map_id != INVALID_MAPPING_ID) { printf("%u return mapping id %u\n", pairid, map_id); flib_free_lcore_id(map_id); mapping_id[pairid] = INVALID_MAPPING_ID; } } if((ret = recreate_one_slave(slaveid)) != 0) goto back; ret = recreate_one_slave(pairid); back: return ret; } static void slave_exit_cb(unsigned slaveid, __attribute__((unused))int stat) { struct lcore_resource_struct *slave = &lcore_resource[slaveid]; printf("Get slave %u leave info\n", slaveid); if (!slave->enabled) { printf("Lcore=%u not registered for it's exit\n", slaveid); return; } rte_spinlock_lock(&res_lock); /* Change the state and wait master to start them */ slave->flags = SLAVE_RECREATE_FLAG; rte_spinlock_unlock(&res_lock); } /* Send the packet on an output interface */ static int l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port) { struct rte_mbuf **m_table; unsigned ret; unsigned queueid =0; m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n); port_statistics[port].tx += ret; if (unlikely(ret < n)) { port_statistics[port].dropped += (n - ret); do { rte_pktmbuf_free(m_table[ret]); } while (++ret < n); } return 0; } /* Send the packet on an output interface */ static int l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) { unsigned lcore_id, len; struct lcore_queue_conf *qconf; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; len = qconf->tx_mbufs[port].len; qconf->tx_mbufs[port].m_table[len] = m; len++; /* enough pkts to be sent */ if (unlikely(len == MAX_PKT_BURST)) { l2fwd_send_burst(qconf, MAX_PKT_BURST, port); len = 0; } qconf->tx_mbufs[port].len = len; return 0; } static void l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) { struct ether_hdr *eth; void *tmp; unsigned dst_port; dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); l2fwd_send_packet(m, (uint8_t) dst_port); } /* main processing loop */ static void l2fwd_main_loop(void) { struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_mbuf *m; unsigned lcore_id; uint64_t prev_tsc, diff_tsc, cur_tsc; unsigned i, j, portid, nb_rx; struct lcore_queue_conf *qconf; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; prev_tsc = 0; lcore_id = rte_lcore_id(); qconf = &lcore_queue_conf[lcore_id]; if (qconf->n_rx_port == 0) { RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); return; } RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, portid); } while (1) { enum l2fwd_cmd cmd; cur_tsc = rte_rdtsc(); if (unlikely(getcmd(lcore_id, &cmd, 0) == 0)) { sendcmd(lcore_id, cmd, 0); /* If get stop command, stop forwarding and exit */ if (cmd == CMD_STOP) { return; } } /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { if (qconf->tx_mbufs[portid].len == 0) continue; l2fwd_send_burst(&lcore_queue_conf[lcore_id], qconf->tx_mbufs[portid].len, (uint8_t) portid); qconf->tx_mbufs[portid].len = 0; } } /* * Read packet from RX queues */ for (i = 0; i < qconf->n_rx_port; i++) { portid = qconf->rx_port_list[i]; nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, pkts_burst, MAX_PKT_BURST); port_statistics[portid].rx += nb_rx; for (j = 0; j < nb_rx; j++) { m = pkts_burst[j]; rte_prefetch0(rte_pktmbuf_mtod(m, void *)); l2fwd_simple_forward(m, portid); } } } } static int l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) { unsigned lcore_id = rte_lcore_id(); if (float_proc) { unsigned flcore_id; /* Change it to floating process, also change it's lcore_id */ clear_cpu_affinity(); RTE_PER_LCORE(_lcore_id) = 0; /* Get a lcore_id */ if (flib_assign_lcore_id() < 0 ) { printf("flib_assign_lcore_id failed\n"); return -1; } flcore_id = rte_lcore_id(); /* Set mapping id, so master can return it after slave exited */ mapping_id[lcore_id] = flcore_id; printf("Org lcore_id = %u, cur lcore_id = %u\n", lcore_id, flcore_id); remapping_slave_resource(lcore_id, flcore_id); } l2fwd_main_loop(); /* return lcore_id before return */ if (float_proc) { flib_free_lcore_id(rte_lcore_id()); mapping_id[lcore_id] = INVALID_MAPPING_ID; } return 0; } /* display usage */ static void l2fwd_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK -s COREMASK [-q NQ] -f\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" " -f use floating process which won't bind to any core to run\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", prgname); } static int l2fwd_parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } static unsigned int l2fwd_parse_nqueue(const char *q_arg) { char *end = NULL; unsigned long n; /* parse hexadecimal string */ n = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return 0; if (n == 0) return 0; if (n >= MAX_RX_QUEUE_PER_LCORE) return 0; return n; } static int l2fwd_parse_timer_period(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n >= MAX_TIMER_PERIOD) return -1; return n; } /* Parse the argument given in the command line of the application */ static int l2fwd_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; int has_pmask = 0; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:q:T:f", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); if (l2fwd_enabled_port_mask == 0) { printf("invalid portmask\n"); l2fwd_usage(prgname); return -1; } has_pmask = 1; break; /* nqueue */ case 'q': l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); if (l2fwd_rx_queue_per_lcore == 0) { printf("invalid queue number\n"); l2fwd_usage(prgname); return -1; } break; /* timer period */ case 'T': timer_period = l2fwd_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; if (timer_period < 0) { printf("invalid timer period\n"); l2fwd_usage(prgname); return -1; } break; /* use floating process */ case 'f': float_proc = 1; break; /* long options */ case 0: l2fwd_usage(prgname); return -1; default: l2fwd_usage(prgname); return -1; } } if (optind >= 0) argv[optind-1] = prgname; if (!has_pmask) { l2fwd_usage(prgname); return -1; } ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } int main(int argc, char **argv) { struct lcore_queue_conf *qconf; struct rte_eth_dev_info dev_info; int ret; uint8_t nb_ports; uint8_t nb_ports_available; uint8_t portid, last_port; unsigned rx_lcore_id; unsigned nb_ports_in_mask = 0; unsigned i; int flags = 0; uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; /* Save cpu_affinity first, restore it in case it's floating process option */ if (get_cpu_affinity() != 0) rte_exit(EXIT_FAILURE, "get_cpu_affinity error\n"); /* Also tries to set cpu affinity to detect whether it will fail in child process */ if(clear_cpu_affinity() != 0) rte_exit(EXIT_FAILURE, "clear_cpu_affinity error\n"); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); argc -= ret; argv += ret; /* parse application arguments (after the EAL ones) */ ret = l2fwd_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); /*flib init */ if (flib_init() != 0) rte_exit(EXIT_FAILURE, "flib init error"); /** * Allocated structures that slave lcore would change. For those that slaves are * read only, needn't use malloc to share and global or static variables is ok since * slave inherit all the knowledge that master initialized. **/ if (l2fwd_malloc_shared_struct() != 0) rte_exit(EXIT_FAILURE, "malloc mem failed\n"); /* Initialize lcore_resource structures */ memset(lcore_resource, 0, sizeof(lcore_resource)); for (i = 0; i < RTE_MAX_LCORE; i++) lcore_resource[i].lcore_id = i; nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* create the mbuf pool */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; char buf_name[RTE_MEMPOOL_NAMESIZE]; flags = MEMPOOL_F_SP_PUT | MEMPOOL_F_SC_GET; snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, portid); l2fwd_pktmbuf_pool[portid] = rte_mempool_create(buf_name, NB_MBUF, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), flags); if (l2fwd_pktmbuf_pool[portid] == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); printf("Create mbuf %s\n", buf_name); } /* reset l2fwd_dst_ports */ for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) l2fwd_dst_ports[portid] = 0; last_port = 0; /* * Each logical core is assigned a dedicated TX queue on each port. */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; if (nb_ports_in_mask % 2) { l2fwd_dst_ports[portid] = last_port; l2fwd_dst_ports[last_port] = portid; } else last_port = portid; nb_ports_in_mask++; rte_eth_dev_info_get(portid, &dev_info); } if (nb_ports_in_mask % 2) { printf("Notice: odd number of ports in portmask.\n"); l2fwd_dst_ports[last_port] = last_port; } rx_lcore_id = 0; qconf = NULL; /* Initialize the port/queue configuration of each logical core */ for (portid = 0; portid < nb_ports; portid++) { struct lcore_resource_struct *res; /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; /* get the lcore_id for this port */ /* skip master lcore */ while (rte_lcore_is_enabled(rx_lcore_id) == 0 || rte_get_master_lcore() == rx_lcore_id || lcore_queue_conf[rx_lcore_id].n_rx_port == l2fwd_rx_queue_per_lcore) { rx_lcore_id++; if (rx_lcore_id >= RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); } if (qconf != &lcore_queue_conf[rx_lcore_id]) /* Assigned a new logical core in the loop above. */ qconf = &lcore_queue_conf[rx_lcore_id]; qconf->rx_port_list[qconf->n_rx_port] = portid; qconf->n_rx_port++; /* Save the port resource info into lcore_resource strucutres */ res = &lcore_resource[rx_lcore_id]; res->enabled = 1; res->port[res->port_num++] = portid; printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); } nb_ports_available = nb_ports; /* Initialise each port */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { printf("Skipping disabled port %u\n", (unsigned) portid); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... ", (unsigned) portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, (unsigned) portid); rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, rte_eth_dev_socket_id(portid), NULL, l2fwd_pktmbuf_pool[portid]); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* init one TX queue on each port */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", ret, (unsigned) portid); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, (unsigned) portid); printf("done: \n"); rte_eth_promiscuous_enable(portid); printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", (unsigned) portid, l2fwd_ports_eth_addr[portid].addr_bytes[0], l2fwd_ports_eth_addr[portid].addr_bytes[1], l2fwd_ports_eth_addr[portid].addr_bytes[2], l2fwd_ports_eth_addr[portid].addr_bytes[3], l2fwd_ports_eth_addr[portid].addr_bytes[4], l2fwd_ports_eth_addr[portid].addr_bytes[5]); /* initialize port stats */ //memset(&port_statistics, 0, sizeof(port_statistics)); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); /* Record pair lcore */ /** * Since l2fwd example would create pair between different neighbour port, that's * port 0 receive and forward to port 1, the same to port 1, these 2 ports will have * dependency. If one port stopped working (killed, for example), the port need to * be stopped/started again. During the time, another port need to wait until stop/start * procedure completed. So, record the pair relationship for those lcores working * on ports. **/ for (portid = 0; portid < nb_ports; portid++) { uint32_t pair_port; unsigned lcore = 0, pair_lcore = 0; unsigned j, find_lcore, find_pair_lcore; /* skip ports that are not enabled */ if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) continue; /* Find pair ports' lcores */ find_lcore = find_pair_lcore = 0; pair_port = l2fwd_dst_ports[portid]; for (i = 0; i < RTE_MAX_LCORE; i++) { if (!rte_lcore_is_enabled(i)) continue; for (j = 0; j < lcore_queue_conf[i].n_rx_port;j++) { if (lcore_queue_conf[i].rx_port_list[j] == portid) { lcore = i; find_lcore = 1; break; } if (lcore_queue_conf[i].rx_port_list[j] == pair_port) { pair_lcore = i; find_pair_lcore = 1; break; } } if (find_lcore && find_pair_lcore) break; } if (!find_lcore || !find_pair_lcore) rte_exit(EXIT_FAILURE, "Not find port=%d pair\n", portid); printf("lcore %u and %u paired\n", lcore, pair_lcore); lcore_resource[lcore].pair_id = pair_lcore; lcore_resource[pair_lcore].pair_id = lcore; } /* Create message buffer for all master and slave */ message_pool = rte_mempool_create("ms_msg_pool", NB_CORE_MSGBUF * RTE_MAX_LCORE, sizeof(enum l2fwd_cmd), NB_CORE_MSGBUF / 2, 0, rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); if (message_pool == NULL) rte_exit(EXIT_FAILURE, "Create msg mempool failed\n"); /* Create ring for each master and slave pair, also register cb when slave leaves */ for (i = 0; i < RTE_MAX_LCORE; i++) { /** * Only create ring and register slave_exit cb in case that core involved into * packet forwarding **/ if (lcore_resource[i].enabled) { /* Create ring for master and slave communication */ ret = create_ms_ring(i); if (ret != 0) rte_exit(EXIT_FAILURE, "Create ring for lcore=%u failed", i); if (flib_register_slave_exit_notify(i, slave_exit_cb) != 0) rte_exit(EXIT_FAILURE, "Register master_trace_slave_exit failed"); } } /* launch per-lcore init on every lcore except master */ flib_mp_remote_launch(l2fwd_launch_one_lcore, NULL, SKIP_MASTER); /* print statistics 10 second */ prev_tsc = cur_tsc = rte_rdtsc(); timer_tsc = 0; while (1) { sleep(1); cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; /* if timer is enabled */ if (timer_period > 0) { /* advance the timer */ timer_tsc += diff_tsc; /* if timer has reached its timeout */ if (unlikely(timer_tsc >= (uint64_t) timer_period)) { print_stats(); /* reset the timer */ timer_tsc = 0; } } prev_tsc = cur_tsc; /* Check any slave need restart or recreate */ rte_spinlock_lock(&res_lock); for (i = 0; i < RTE_MAX_LCORE; i++) { struct lcore_resource_struct *res = &lcore_resource[i]; struct lcore_resource_struct *pair = &lcore_resource[res->pair_id]; /* If find slave exited, try to reset pair */ if (res->enabled && res->flags && pair->enabled) { if (!pair->flags) { master_sendcmd_with_ack(pair->lcore_id, CMD_STOP); rte_spinlock_unlock(&res_lock); sleep(1); rte_spinlock_lock(&res_lock); if (pair->flags) continue; } if (reset_pair(res->lcore_id, pair->lcore_id) != 0) rte_exit(EXIT_FAILURE, "failed to reset slave"); res->flags = 0; pair->flags = 0; } } rte_spinlock_unlock(&res_lock); } } ================================================ FILE: examples/multi_process/simple_mp/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = simple_mp # all source are stored in SRCS-y SRCS-y := main.c mp_commands.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/multi_process/simple_mp/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This sample application is a simple multi-process application which * demostrates sharing of queues and memory pools between processes, and * using those queues/pools for communication between the processes. * * Application is designed to run with two processes, a primary and a * secondary, and each accepts commands on the commandline, the most * important of which is "send", which just sends a string to the other * process. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mp_commands.h" #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 static const char *_MSG_POOL = "MSG_POOL"; static const char *_SEC_2_PRI = "SEC_2_PRI"; static const char *_PRI_2_SEC = "PRI_2_SEC"; const unsigned string_size = 64; struct rte_ring *send_ring, *recv_ring; struct rte_mempool *message_pool; volatile int quit = 0; static int lcore_recv(__attribute__((unused)) void *arg) { unsigned lcore_id = rte_lcore_id(); printf("Starting core %u\n", lcore_id); while (!quit){ void *msg; if (rte_ring_dequeue(recv_ring, &msg) < 0){ usleep(5); continue; } printf("core %u: Received '%s'\n", lcore_id, (char *)msg); rte_mempool_put(message_pool, msg); } return 0; } int main(int argc, char **argv) { const unsigned flags = 0; const unsigned ring_size = 64; const unsigned pool_size = 1024; const unsigned pool_cache = 32; const unsigned priv_data_sz = 0; int ret; unsigned lcore_id; ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot init EAL\n"); if (rte_eal_process_type() == RTE_PROC_PRIMARY){ send_ring = rte_ring_create(_PRI_2_SEC, ring_size, rte_socket_id(), flags); recv_ring = rte_ring_create(_SEC_2_PRI, ring_size, rte_socket_id(), flags); message_pool = rte_mempool_create(_MSG_POOL, pool_size, string_size, pool_cache, priv_data_sz, NULL, NULL, NULL, NULL, rte_socket_id(), flags); } else { recv_ring = rte_ring_lookup(_PRI_2_SEC); send_ring = rte_ring_lookup(_SEC_2_PRI); message_pool = rte_mempool_lookup(_MSG_POOL); } if (send_ring == NULL) rte_exit(EXIT_FAILURE, "Problem getting sending ring\n"); if (recv_ring == NULL) rte_exit(EXIT_FAILURE, "Problem getting receiving ring\n"); if (message_pool == NULL) rte_exit(EXIT_FAILURE, "Problem getting message pool\n"); RTE_LOG(INFO, APP, "Finished Process Init.\n"); /* call lcore_recv() on every slave lcore */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_recv, NULL, lcore_id); } /* call cmd prompt on master lcore */ struct cmdline *cl = cmdline_stdin_new(simple_mp_ctx, "\nsimple_mp > "); if (cl == NULL) rte_exit(EXIT_FAILURE, "Cannot create cmdline instance\n"); cmdline_interact(cl); cmdline_stdin_exit(cl); rte_eal_mp_wait_lcore(); return 0; } ================================================ FILE: examples/multi_process/simple_mp/mp_commands.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mp_commands.h" /**********************************************************/ struct cmd_send_result { cmdline_fixed_string_t action; cmdline_fixed_string_t message; }; static void cmd_send_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { void *msg = NULL; struct cmd_send_result *res = parsed_result; if (rte_mempool_get(message_pool, &msg) < 0) rte_panic("Failed to get message buffer\n"); snprintf((char *)msg, string_size, "%s", res->message); if (rte_ring_enqueue(send_ring, msg) < 0) { printf("Failed to send message - message discarded\n"); rte_mempool_put(message_pool, msg); } } cmdline_parse_token_string_t cmd_send_action = TOKEN_STRING_INITIALIZER(struct cmd_send_result, action, "send"); cmdline_parse_token_string_t cmd_send_message = TOKEN_STRING_INITIALIZER(struct cmd_send_result, message, NULL); cmdline_parse_inst_t cmd_send = { .f = cmd_send_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "send a string to another process", .tokens = { /* token list, NULL terminated */ (void *)&cmd_send_action, (void *)&cmd_send_message, NULL, }, }; /**********************************************************/ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { quit = 1; cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "close the application", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_quit, NULL, }, }; /**********************************************************/ struct cmd_help_result { cmdline_fixed_string_t help; }; static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Simple demo example of multi-process in RTE\n\n" "This is a readline-like interface that can be used to\n" "send commands to the simple app. Commands supported are:\n\n" "- send [string]\n" "- help\n" "- quit\n\n"); } cmdline_parse_token_string_t cmd_help_help = TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); cmdline_parse_inst_t cmd_help = { .f = cmd_help_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "show help", .tokens = { /* token list, NULL terminated */ (void *)&cmd_help_help, NULL, }, }; /****** CONTEXT (list of instruction) */ cmdline_parse_ctx_t simple_mp_ctx[] = { (cmdline_parse_inst_t *)&cmd_send, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_help, NULL, }; ================================================ FILE: examples/multi_process/simple_mp/mp_commands.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SIMPLE_MP_COMMANDS_H_ #define _SIMPLE_MP_COMMANDS_H_ extern const unsigned string_size; extern struct rte_ring *send_ring; extern struct rte_mempool *message_pool; extern volatile int quit; extern cmdline_parse_ctx_t simple_mp_ctx[]; #endif /* _SIMPLE_MP_COMMANDS_H_ */ ================================================ FILE: examples/multi_process/symmetric_mp/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = symmetric_mp # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/multi_process/symmetric_mp/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Sample application demostrating how to do packet I/O in a multi-process * environment. The same code can be run as a primary process and as a * secondary process, just with a different proc-id parameter in each case * (apart from the EAL flag to indicate a secondary process). * * Each process will read from the same ports, given by the port-mask * parameter, which should be the same in each case, just using a different * queue per port as determined by the proc-id parameter. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 #define NB_MBUFS 64*1024 /* use 64k mbufs */ #define MBUF_CACHE_SIZE 256 #define PKT_BURST 32 #define RX_RING_SIZE 128 #define TX_RING_SIZE 512 #define PARAM_PROC_ID "proc-id" #define PARAM_NUM_PROCS "num-procs" /* for each lcore, record the elements of the ports array to use */ struct lcore_ports{ unsigned start_port; unsigned num_ports; }; /* structure to record the rx and tx packets. Put two per cache line as ports * used in pairs */ struct port_stats{ unsigned rx; unsigned tx; unsigned drop; } __attribute__((aligned(RTE_CACHE_LINE_SIZE / 2))); static int proc_id = -1; static unsigned num_procs = 0; static uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned num_ports = 0; static struct lcore_ports lcore_ports[RTE_MAX_LCORE]; static struct port_stats pstats[RTE_MAX_ETHPORTS]; /* prints the usage statement and quits with an error message */ static void smp_usage(const char *prgname, const char *errmsg) { printf("\nError: %s\n",errmsg); printf("\n%s [EAL options] -- -p " "--"PARAM_NUM_PROCS" " " --"PARAM_PROC_ID" \n" "-p : a hex bitmask indicating what ports are to be used\n" "--num-procs: the number of processes which will be used\n" "--proc-id : the id of the current process (id < num-procs)\n" "\n", prgname); exit(1); } /* signal handler configured for SIGTERM and SIGINT to print stats on exit */ static void print_stats(int signum) { unsigned i; printf("\nExiting on signal %d\n\n", signum); for (i = 0; i < num_ports; i++){ const uint8_t p_num = ports[i]; printf("Port %u: RX - %u, TX - %u, Drop - %u\n", (unsigned)p_num, pstats[p_num].rx, pstats[p_num].tx, pstats[p_num].drop); } exit(0); } /* Parse the argument given in the command line of the application */ static int smp_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; unsigned i, port_mask = 0; char *prgname = argv[0]; static struct option lgopts[] = { {PARAM_NUM_PROCS, 1, 0, 0}, {PARAM_PROC_ID, 1, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", \ lgopts, &option_index)) != EOF) { switch (opt) { case 'p': port_mask = strtoull(optarg, NULL, 16); break; /* long options */ case 0: if (strncmp(lgopts[option_index].name, PARAM_NUM_PROCS, 8) == 0) num_procs = atoi(optarg); else if (strncmp(lgopts[option_index].name, PARAM_PROC_ID, 7) == 0) proc_id = atoi(optarg); break; default: smp_usage(prgname, "Cannot parse all command-line arguments\n"); } } if (optind >= 0) argv[optind-1] = prgname; if (proc_id < 0) smp_usage(prgname, "Invalid or missing proc-id parameter\n"); if (rte_eal_process_type() == RTE_PROC_PRIMARY && num_procs == 0) smp_usage(prgname, "Invalid or missing num-procs parameter\n"); if (port_mask == 0) smp_usage(prgname, "Invalid or missing port mask\n"); /* get the port numbers from the port mask */ for(i = 0; i < rte_eth_dev_count(); i++) if(port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; ret = optind-1; optind = 0; /* reset getopt lib */ return (ret); } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int smp_port_init(uint8_t port, struct rte_mempool *mbuf_pool, uint16_t num_queues) { struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 1, /**< IP checksum offload enabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, } }; const uint16_t rx_rings = num_queues, tx_rings = num_queues; struct rte_eth_dev_info info; int retval; uint16_t q; if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; if (port >= rte_eth_dev_count()) return -1; printf("# Initialising port %u... ", (unsigned)port); fflush(stdout); rte_eth_dev_info_get(port, &info); info.default_rxconf.rx_drop_en = 1; retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval < 0) return retval; for (q = 0; q < rx_rings; q ++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), &info.default_rxconf, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < tx_rings; q ++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } rte_eth_promiscuous_enable(port); retval = rte_eth_dev_start(port); if (retval < 0) return retval; return 0; } /* Goes through each of the lcores and calculates what ports should * be used by that core. Fills in the global lcore_ports[] array. */ static void assign_ports_to_cores(void) { const unsigned lcores = rte_eal_get_configuration()->lcore_count; const unsigned port_pairs = num_ports / 2; const unsigned pairs_per_lcore = port_pairs / lcores; unsigned extra_pairs = port_pairs % lcores; unsigned ports_assigned = 0; unsigned i; RTE_LCORE_FOREACH(i) { lcore_ports[i].start_port = ports_assigned; lcore_ports[i].num_ports = pairs_per_lcore * 2; if (extra_pairs > 0) { lcore_ports[i].num_ports += 2; extra_pairs--; } ports_assigned += lcore_ports[i].num_ports; } } /* Main function used by the processing threads. * Prints out some configuration details for the thread and then begins * performing packet RX and TX. */ static int lcore_main(void *arg __rte_unused) { const unsigned id = rte_lcore_id(); const unsigned start_port = lcore_ports[id].start_port; const unsigned end_port = start_port + lcore_ports[id].num_ports; const uint16_t q_id = (uint16_t)proc_id; unsigned p, i; char msgbuf[256]; int msgbufpos = 0; if (start_port == end_port){ printf("Lcore %u has nothing to do\n", id); return 0; } /* build up message in msgbuf before printing to decrease likelihood * of multi-core message interleaving. */ msgbufpos += snprintf(msgbuf, sizeof(msgbuf) - msgbufpos, "Lcore %u using ports ", id); for (p = start_port; p < end_port; p++){ msgbufpos += snprintf(msgbuf + msgbufpos, sizeof(msgbuf) - msgbufpos, "%u ", (unsigned)ports[p]); } printf("%s\n", msgbuf); printf("lcore %u using queue %u of each port\n", id, (unsigned)q_id); /* handle packet I/O from the ports, reading and writing to the * queue number corresponding to our process number (not lcore id) */ for (;;) { struct rte_mbuf *buf[PKT_BURST]; for (p = start_port; p < end_port; p++) { const uint8_t src = ports[p]; const uint8_t dst = ports[p ^ 1]; /* 0 <-> 1, 2 <-> 3 etc */ const uint16_t rx_c = rte_eth_rx_burst(src, q_id, buf, PKT_BURST); if (rx_c == 0) continue; pstats[src].rx += rx_c; const uint16_t tx_c = rte_eth_tx_burst(dst, q_id, buf, rx_c); pstats[dst].tx += tx_c; if (tx_c != rx_c) { pstats[dst].drop += (rx_c - tx_c); for (i = tx_c; i < rx_c; i++) rte_pktmbuf_free(buf[i]); } } } } /* Check the link status of all ports in up to 9s, and print them finally */ static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ uint8_t portid, count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; for (portid = 0; portid < port_num; portid++) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); rte_eth_link_get_nowait(portid, &link); /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) printf("Port %d Link Up - speed %u " "Mbps - %s\n", (uint8_t)portid, (unsigned)link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); else printf("Port %d Link Down\n", (uint8_t)portid); continue; } /* clear all_ports_up flag if any link down */ if (link.link_status == 0) { all_ports_up = 0; break; } } /* after finally printing all link status, get out */ if (print_flag == 1) break; if (all_ports_up == 0) { printf("."); fflush(stdout); rte_delay_ms(CHECK_INTERVAL); } /* set the print_flag if all ports up or timeout */ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { print_flag = 1; printf("done\n"); } } } /* Main function. * Performs initialisation and then calls the lcore_main on each core * to do the packet-processing work. */ int main(int argc, char **argv) { static const char *_SMP_MBUF_POOL = "SMP_MBUF_POOL"; int ret; unsigned i; enum rte_proc_type_t proc_type; struct rte_mempool *mp; /* set up signal handlers to print stats on exit */ signal(SIGINT, print_stats); signal(SIGTERM, print_stats); /* initialise the EAL for all */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot init EAL\n"); argc -= ret; argv += ret; /* determine the NIC devices available */ if (rte_eth_dev_count() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); /* parse application arguments (those after the EAL ones) */ smp_parse_args(argc, argv); proc_type = rte_eal_process_type(); mp = (proc_type == RTE_PROC_SECONDARY) ? rte_mempool_lookup(_SMP_MBUF_POOL) : rte_pktmbuf_pool_create(_SMP_MBUF_POOL, NB_MBUFS, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mp == NULL) rte_exit(EXIT_FAILURE, "Cannot get memory pool for buffers\n"); if (num_ports & 1) rte_exit(EXIT_FAILURE, "Application must use an even number of ports\n"); for(i = 0; i < num_ports; i++){ if(proc_type == RTE_PROC_PRIMARY) if (smp_port_init(ports[i], mp, (uint16_t)num_procs) < 0) rte_exit(EXIT_FAILURE, "Error initialising ports\n"); } if (proc_type == RTE_PROC_PRIMARY) check_all_ports_link_status((uint8_t)num_ports, (~0x0)); assign_ports_to_cores(); RTE_LOG(INFO, APP, "Finished Process Init.\n"); rte_eal_mp_remote_launch(lcore_main, NULL, CALL_MASTER); return 0; } ================================================ FILE: examples/netmap_compat/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk unexport RTE_SRCDIR RTE_OUTPUT RTE_EXTMK DIRS-y += bridge .PHONY: all clean $(DIRS-y) all: $(DIRS-y) clean: $(DIRS-y) $(DIRS-y): $(MAKE) -C $@ $(MAKECMDGOALS) O=$(RTE_OUTPUT) ================================================ FILE: examples/netmap_compat/bridge/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define the RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: else # binary name APP = bridge # for compat_netmap.c VPATH := $(SRCDIR)/../lib # all source are stored in SRCS-y SRCS-y := bridge.c SRCS-y += compat_netmap.c CFLAGS += -O3 -I$(SRCDIR)/../lib -I$(SRCDIR)/../netmap CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk endif ================================================ FILE: examples/netmap_compat/bridge/bridge.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "compat_netmap.h" #define BUF_SIZE RTE_MBUF_DEFAULT_DATAROOM #define MBUF_DATA_SIZE (BUF_SIZE + RTE_PKTMBUF_HEADROOM) #define MBUF_PER_POOL 8192 struct rte_eth_conf eth_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, .hw_ip_checksum = 0, .hw_vlan_filter = 0, .jumbo_frame = 0, .hw_strip_crc = 0, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; #define MAX_QUEUE_NUM 1 #define RX_QUEUE_NUM 1 #define TX_QUEUE_NUM 1 #define MAX_DESC_NUM 0x400 #define RX_DESC_NUM 0x100 #define TX_DESC_NUM 0x200 #define RX_SYNC_NUM 0x20 #define TX_SYNC_NUM 0x20 struct rte_netmap_port_conf port_conf = { .eth_conf = ð_conf, .socket_id = SOCKET_ID_ANY, .nr_tx_rings = TX_QUEUE_NUM, .nr_rx_rings = RX_QUEUE_NUM, .nr_tx_slots = TX_DESC_NUM, .nr_rx_slots = RX_DESC_NUM, .tx_burst = TX_SYNC_NUM, .rx_burst = RX_SYNC_NUM, }; struct rte_netmap_conf netmap_conf = { .socket_id = SOCKET_ID_ANY, .max_bufsz = BUF_SIZE, .max_rings = MAX_QUEUE_NUM, .max_slots = MAX_DESC_NUM, }; static int stop = 0; #define MAX_PORT_NUM 2 struct netmap_port { int fd; struct netmap_if *nmif; struct netmap_ring *rx_ring; struct netmap_ring *tx_ring; const char *str; uint8_t id; }; static struct { uint32_t num; struct netmap_port p[MAX_PORT_NUM]; void *mem; } ports; static void usage(const char *prgname) { fprintf(stderr, "Usage: %s [EAL args] -- [OPTION]...\n" "-h, --help \t Show this help message and exit\n" "-i INTERFACE_A \t Interface (DPDK port number) to use\n" "[ -i INTERFACE_B \t Interface (DPDK port number) to use ]\n", prgname); } static uint8_t parse_portid(const char *portid_str) { char *end; unsigned id; id = strtoul(portid_str, &end, 10); if (end == portid_str || *end != '\0' || id > RTE_MAX_ETHPORTS) rte_exit(EXIT_FAILURE, "Invalid port number\n"); return (uint8_t) id; } static int parse_args(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "hi:")) != -1) { switch (opt) { case 'h': usage(argv[0]); rte_exit(EXIT_SUCCESS, "exiting..."); break; case 'i': if (ports.num >= RTE_DIM(ports.p)) { usage(argv[0]); rte_exit(EXIT_FAILURE, "configs with %u " "ports are not supported\n", ports.num + 1); } ports.p[ports.num].str = optarg; ports.p[ports.num].id = parse_portid(optarg); ports.num++; break; default: usage(argv[0]); rte_exit(EXIT_FAILURE, "invalid option: %c\n", opt); } } return 0; } static void sigint_handler(__rte_unused int sig) { stop = 1; signal(SIGINT, SIG_DFL); } static void move(int n, struct netmap_ring *rx, struct netmap_ring *tx) { uint32_t tmp; while (n-- > 0) { tmp = tx->slot[tx->cur].buf_idx; tx->slot[tx->cur].buf_idx = rx->slot[rx->cur].buf_idx; tx->slot[tx->cur].len = rx->slot[rx->cur].len; tx->slot[tx->cur].flags |= NS_BUF_CHANGED; tx->cur = NETMAP_RING_NEXT(tx, tx->cur); tx->avail--; rx->slot[rx->cur].buf_idx = tmp; rx->slot[rx->cur].flags |= NS_BUF_CHANGED; rx->cur = NETMAP_RING_NEXT(rx, rx->cur); rx->avail--; } } static int netmap_port_open(uint32_t idx) { int err; struct netmap_port *port; struct nmreq req; port = ports.p + idx; port->fd = rte_netmap_open("/dev/netmap", O_RDWR); snprintf(req.nr_name, sizeof(req.nr_name), "%s", port->str); req.nr_version = NETMAP_API; req.nr_ringid = 0; err = rte_netmap_ioctl(port->fd, NIOCGINFO, &req); if (err) { printf("[E] NIOCGINFO ioctl failed (error %d)\n", err); return (err); } snprintf(req.nr_name, sizeof(req.nr_name), "%s", port->str); req.nr_version = NETMAP_API; req.nr_ringid = 0; err = rte_netmap_ioctl(port->fd, NIOCREGIF, &req); if (err) { printf("[E] NIOCREGIF ioctl failed (error %d)\n", err); return (err); } /* mmap only once. */ if (ports.mem == NULL) ports.mem = rte_netmap_mmap(NULL, req.nr_memsize, PROT_WRITE | PROT_READ, MAP_PRIVATE, port->fd, 0); if (ports.mem == MAP_FAILED) { printf("[E] NETMAP mmap failed for fd: %d)\n", port->fd); return (-ENOMEM); } port->nmif = NETMAP_IF(ports.mem, req.nr_offset); port->tx_ring = NETMAP_TXRING(port->nmif, 0); port->rx_ring = NETMAP_RXRING(port->nmif, 0); return (0); } int main(int argc, char *argv[]) { int err, ret; uint32_t i, pmsk; struct nmreq req; struct pollfd pollfd[MAX_PORT_NUM]; struct rte_mempool *pool; struct netmap_ring *rx_ring, *tx_ring; ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); argc -= ret; argv += ret; parse_args(argc, argv); if (ports.num == 0) rte_exit(EXIT_FAILURE, "no ports specified\n"); if (rte_eth_dev_count() < 1) rte_exit(EXIT_FAILURE, "Not enough ethernet ports available\n"); pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, MBUF_DATA_SIZE, rte_socket_id()); if (pool == NULL) rte_exit(EXIT_FAILURE, "Couldn't create mempool\n"); netmap_conf.socket_id = rte_socket_id(); err = rte_netmap_init(&netmap_conf); if (err < 0) rte_exit(EXIT_FAILURE, "Couldn't initialize librte_compat_netmap\n"); else printf("librte_compat_netmap initialized\n"); port_conf.pool = pool; port_conf.socket_id = rte_socket_id(); for (i = 0; i != ports.num; i++) { err = rte_netmap_init_port(ports.p[i].id, &port_conf); if (err < 0) rte_exit(EXIT_FAILURE, "Couldn't setup port %hhu\n", ports.p[i].id); rte_eth_promiscuous_enable(ports.p[i].id); } for (i = 0; i != ports.num; i++) { err = netmap_port_open(i); if (err) { rte_exit(EXIT_FAILURE, "Couldn't set port %hhu " "under NETMAP control\n", ports.p[i].id); } else printf("Port %hhu now in Netmap mode\n", ports.p[i].id); } memset(pollfd, 0, sizeof(pollfd)); for (i = 0; i != ports.num; i++) { pollfd[i].fd = ports.p[i].fd; pollfd[i].events = POLLIN | POLLOUT; } signal(SIGINT, sigint_handler); pmsk = ports.num - 1; printf("Bridge up and running!\n"); while (!stop) { uint32_t n_pkts; pollfd[0].revents = 0; pollfd[1].revents = 0; ret = rte_netmap_poll(pollfd, ports.num, 0); if (ret < 0) { stop = 1; printf("[E] poll returned with error %d\n", ret); } if (((pollfd[0].revents | pollfd[1].revents) & POLLERR) != 0) { printf("POLLERR!\n"); } if ((pollfd[0].revents & POLLIN) != 0 && (pollfd[pmsk].revents & POLLOUT) != 0) { rx_ring = ports.p[0].rx_ring; tx_ring = ports.p[pmsk].tx_ring; n_pkts = RTE_MIN(rx_ring->avail, tx_ring->avail); move(n_pkts, rx_ring, tx_ring); } if (pmsk != 0 && (pollfd[pmsk].revents & POLLIN) != 0 && (pollfd[0].revents & POLLOUT) != 0) { rx_ring = ports.p[pmsk].rx_ring; tx_ring = ports.p[0].tx_ring; n_pkts = RTE_MIN(rx_ring->avail, tx_ring->avail); move(n_pkts, rx_ring, tx_ring); } } printf("Bridge stopped!\n"); for (i = 0; i != ports.num; i++) { err = rte_netmap_ioctl(ports.p[i].fd, NIOCUNREGIF, &req); if (err) { printf("[E] NIOCUNREGIF ioctl failed (error %d)\n", err); } else printf("Port %hhu unregistered from Netmap mode\n", ports.p[i].id); rte_netmap_close(ports.p[i].fd); } return 0; } ================================================ FILE: examples/netmap_compat/lib/compat_netmap.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "compat_netmap.h" struct netmap_port { struct rte_mempool *pool; struct netmap_if *nmif; struct rte_eth_conf eth_conf; struct rte_eth_txconf tx_conf; struct rte_eth_rxconf rx_conf; int32_t socket_id; uint16_t nr_tx_rings; uint16_t nr_rx_rings; uint32_t nr_tx_slots; uint32_t nr_rx_slots; uint16_t tx_burst; uint16_t rx_burst; uint32_t fd; }; struct fd_port { uint32_t port; }; #define FD_PORT_FREE UINT32_MAX #define FD_PORT_RSRV (FD_PORT_FREE - 1) struct netmap_state { struct rte_netmap_conf conf; uintptr_t buf_start; void *mem; uint32_t mem_sz; uint32_t netif_memsz; }; #define COMPAT_NETMAP_MAX_NOFILE (2 * RTE_MAX_ETHPORTS) #define COMPAT_NETMAP_MAX_BURST 64 #define COMPAT_NETMAP_MAX_PKT_PER_SYNC (2 * COMPAT_NETMAP_MAX_BURST) static struct netmap_port ports[RTE_MAX_ETHPORTS]; static struct netmap_state netmap; static struct fd_port fd_port[COMPAT_NETMAP_MAX_NOFILE]; static const int next_fd_start = RLIMIT_NOFILE + 1; static rte_spinlock_t netmap_lock; #define IDX_TO_FD(x) ((x) + next_fd_start) #define FD_TO_IDX(x) ((x) - next_fd_start) #define FD_VALID(x) ((x) >= next_fd_start && \ (x) < (typeof (x))(RTE_DIM(fd_port) + next_fd_start)) #define PORT_NUM_RINGS (2 * netmap.conf.max_rings) #define PORT_NUM_SLOTS (PORT_NUM_RINGS * netmap.conf.max_slots) #define BUF_IDX(port, ring, slot) \ (((port) * PORT_NUM_RINGS + (ring)) * netmap.conf.max_slots + \ (slot)) #define NETMAP_IF_RING_OFS(rid, rings, slots) ({\ struct netmap_if *_if; \ struct netmap_ring *_rg; \ sizeof(*_if) + \ (rings) * sizeof(_if->ring_ofs[0]) + \ (rid) * sizeof(*_rg) + \ (slots) * sizeof(_rg->slot[0]); \ }) static void netmap_unregif(uint32_t idx, uint32_t port); static int32_t ifname_to_portid(const char *ifname, uint8_t *port) { char *endptr; uint64_t portid; errno = 0; portid = strtoul(ifname, &endptr, 10); if (endptr == ifname || *endptr != '\0' || portid >= RTE_DIM(ports) || errno != 0) return (-EINVAL); *port = (uint8_t)portid; return (0); } /** * Given a dpdk mbuf, fill in the Netmap slot in ring r and its associated * buffer with the data held by the mbuf. * Note that mbuf chains are not supported. */ static void mbuf_to_slot(struct rte_mbuf *mbuf, struct netmap_ring *r, uint32_t index) { char *data; uint16_t length; data = rte_pktmbuf_mtod(mbuf, char *); length = rte_pktmbuf_data_len(mbuf); if (length > r->nr_buf_size) length = 0; r->slot[index].len = length; rte_memcpy(NETMAP_BUF(r, r->slot[index].buf_idx), data, length); } /** * Given a Netmap ring and a slot index for that ring, construct a dpdk mbuf * from the data held in the buffer associated with the slot. * Allocation/deallocation of the dpdk mbuf are the responsability of the * caller. * Note that mbuf chains are not supported. */ static void slot_to_mbuf(struct netmap_ring *r, uint32_t index, struct rte_mbuf *mbuf) { char *data; uint16_t length; rte_pktmbuf_reset(mbuf); length = r->slot[index].len; data = rte_pktmbuf_append(mbuf, length); if (data != NULL) rte_memcpy(data, NETMAP_BUF(r, r->slot[index].buf_idx), length); } static int32_t fd_reserve(void) { uint32_t i; for (i = 0; i != RTE_DIM(fd_port) && fd_port[i].port != FD_PORT_FREE; i++) ; if (i == RTE_DIM(fd_port)) return (-ENOMEM); fd_port[i].port = FD_PORT_RSRV; return (IDX_TO_FD(i)); } static int32_t fd_release(int32_t fd) { uint32_t idx, port; idx = FD_TO_IDX(fd); if (!FD_VALID(fd) || (port = fd_port[idx].port) == FD_PORT_FREE) return (-EINVAL); /* if we still have a valid port attached, release the port */ if (port < RTE_DIM(ports) && ports[port].fd == idx) { netmap_unregif(idx, port); } fd_port[idx].port = FD_PORT_FREE; return (0); } static int check_nmreq(struct nmreq *req, uint8_t *port) { int32_t rc; uint8_t portid; if (req == NULL) return (-EINVAL); if (req->nr_version != NETMAP_API) { req->nr_version = NETMAP_API; return (-EINVAL); } if ((rc = ifname_to_portid(req->nr_name, &portid)) != 0) { RTE_LOG(ERR, USER1, "Invalid interface name:\"%s\" " "in NIOCGINFO call\n", req->nr_name); return (rc); } if (ports[portid].pool == NULL) { RTE_LOG(ERR, USER1, "Misconfigured portid %hhu\n", portid); return (-EINVAL); } *port = portid; return (0); } /** * Simulate a Netmap NIOCGINFO ioctl: given a struct nmreq holding an interface * name (a port number in our case), fill the struct nmreq in with advisory * information about the interface: number of rings and their size, total memory * required in the map, ... * Those are preconfigured using rte_eth_{,tx,rx}conf and * rte_netmap_port_conf structures * and calls to rte_netmap_init_port() in the Netmap application. */ static int ioctl_niocginfo(__rte_unused int fd, void * param) { uint8_t portid; struct nmreq *req; int32_t rc; req = (struct nmreq *)param; if ((rc = check_nmreq(req, &portid)) != 0) return (rc); req->nr_tx_rings = (uint16_t)(ports[portid].nr_tx_rings - 1); req->nr_rx_rings = (uint16_t)(ports[portid].nr_rx_rings - 1); req->nr_tx_slots = ports[portid].nr_tx_slots; req->nr_rx_slots = ports[portid].nr_rx_slots; /* in current implementation we have all NETIFs shared aone region. */ req->nr_memsize = netmap.mem_sz; req->nr_offset = 0; return (0); } static void netmap_ring_setup(struct netmap_ring *ring, uint8_t port, uint32_t ringid, uint32_t num_slots) { uint32_t j; ring->buf_ofs = netmap.buf_start - (uintptr_t)ring; ring->num_slots = num_slots; ring->cur = 0; ring->reserved = 0; ring->nr_buf_size = netmap.conf.max_bufsz; ring->flags = 0; ring->ts.tv_sec = 0; ring->ts.tv_usec = 0; for (j = 0; j < ring->num_slots; j++) { ring->slot[j].buf_idx = BUF_IDX(port, ringid, j); ring->slot[j].len = 0; ring->flags = 0; } } static int netmap_regif(struct nmreq *req, uint32_t idx, uint8_t port) { struct netmap_if *nmif; struct netmap_ring *ring; uint32_t i, slots, start_ring; int32_t rc; if (ports[port].fd < RTE_DIM(fd_port)) { RTE_LOG(ERR, USER1, "port %hhu already in use by fd: %u\n", port, IDX_TO_FD(ports[port].fd)); return (-EBUSY); } if (fd_port[idx].port != FD_PORT_RSRV) { RTE_LOG(ERR, USER1, "fd: %u is misconfigured\n", IDX_TO_FD(idx)); return (-EBUSY); } nmif = ports[port].nmif; /* setup netmap_if fields. */ memset(nmif, 0, netmap.netif_memsz); /* only ALL rings supported right now. */ if (req->nr_ringid != 0) return (-EINVAL); snprintf(nmif->ni_name, sizeof(nmif->ni_name), "%s", req->nr_name); nmif->ni_version = req->nr_version; /* Netmap uses ni_(r|t)x_rings + 1 */ nmif->ni_rx_rings = ports[port].nr_rx_rings - 1; nmif->ni_tx_rings = ports[port].nr_tx_rings - 1; /* * Setup TX rings and slots. * Refer to the comments in netmap.h for details */ slots = 0; for (i = 0; i < nmif->ni_tx_rings + 1; i++) { nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i, PORT_NUM_RINGS, slots); ring = NETMAP_TXRING(nmif, i); netmap_ring_setup(ring, port, i, ports[port].nr_tx_slots); ring->avail = ring->num_slots; slots += ports[port].nr_tx_slots; } /* * Setup RX rings and slots. * Refer to the comments in netmap.h for details */ start_ring = i; for (; i < nmif->ni_rx_rings + 1 + start_ring; i++) { nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i, PORT_NUM_RINGS, slots); ring = NETMAP_RXRING(nmif, (i - start_ring)); netmap_ring_setup(ring, port, i, ports[port].nr_rx_slots); ring->avail = 0; slots += ports[port].nr_rx_slots; } if ((rc = rte_eth_dev_start(port)) < 0) { RTE_LOG(ERR, USER1, "Couldn't start ethernet device %s (error %d)\n", req->nr_name, rc); return (rc); } /* setup fdi <--> port relationtip. */ ports[port].fd = idx; fd_port[idx].port = port; req->nr_memsize = netmap.mem_sz; req->nr_offset = (uintptr_t)nmif - (uintptr_t)netmap.mem; return (0); } /** * Simulate a Netmap NIOCREGIF ioctl: */ static int ioctl_niocregif(int32_t fd, void * param) { uint8_t portid; int32_t rc; uint32_t idx; struct nmreq *req; req = (struct nmreq *)param; if ((rc = check_nmreq(req, &portid)) != 0) return (rc); idx = FD_TO_IDX(fd); rte_spinlock_lock(&netmap_lock); rc = netmap_regif(req, idx, portid); rte_spinlock_unlock(&netmap_lock); return (rc); } static void netmap_unregif(uint32_t idx, uint32_t port) { fd_port[idx].port = FD_PORT_RSRV; ports[port].fd = UINT32_MAX; rte_eth_dev_stop((uint8_t)port); } /** * Simulate a Netmap NIOCUNREGIF ioctl: put an interface running in Netmap * mode back in "normal" mode. In our case, we just stop the port associated * with this file descriptor. */ static int ioctl_niocunregif(int fd) { uint32_t idx, port; int32_t rc; idx = FD_TO_IDX(fd); rte_spinlock_lock(&netmap_lock); port = fd_port[idx].port; if (port < RTE_DIM(ports) && ports[port].fd == idx) { netmap_unregif(idx, port); rc = 0; } else { RTE_LOG(ERR, USER1, "%s: %d is not associated with valid port\n", __func__, fd); rc = -EINVAL; } rte_spinlock_unlock(&netmap_lock); return (rc); } /** * A call to rx_sync_ring will try to fill a Netmap RX ring with as many * packets as it can hold coming from its dpdk port. */ static inline int rx_sync_ring(struct netmap_ring *ring, uint8_t port, uint16_t ring_number, uint16_t max_burst) { int32_t i, n_rx; uint16_t burst_size; uint32_t cur_slot, n_free_slots; struct rte_mbuf *rx_mbufs[COMPAT_NETMAP_MAX_BURST]; n_free_slots = ring->num_slots - (ring->avail + ring->reserved); n_free_slots = RTE_MIN(n_free_slots, max_burst); cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1); while (n_free_slots) { burst_size = (uint16_t)RTE_MIN(n_free_slots, RTE_DIM(rx_mbufs)); /* receive up to burst_size packets from the NIC's queue */ n_rx = rte_eth_rx_burst(port, ring_number, rx_mbufs, burst_size); if (n_rx == 0) return 0; if (unlikely(n_rx < 0)) return -1; /* Put those n_rx packets in the Netmap structures */ for (i = 0; i < n_rx ; i++) { mbuf_to_slot(rx_mbufs[i], ring, cur_slot); rte_pktmbuf_free(rx_mbufs[i]); cur_slot = NETMAP_RING_NEXT(ring, cur_slot); } /* Update the Netmap ring structure to reflect the change */ ring->avail += n_rx; n_free_slots -= n_rx; } return 0; } static inline int rx_sync_if(uint32_t port) { uint16_t burst; uint32_t i, rc; struct netmap_if *nifp; struct netmap_ring *r; nifp = ports[port].nmif; burst = ports[port].rx_burst; rc = 0; for (i = 0; i < nifp->ni_rx_rings + 1; i++) { r = NETMAP_RXRING(nifp, i); rx_sync_ring(r, (uint8_t)port, (uint16_t)i, burst); rc += r->avail; } return (rc); } /** * Simulate a Netmap NIOCRXSYNC ioctl: */ static int ioctl_niocrxsync(int fd) { uint32_t idx, port; idx = FD_TO_IDX(fd); if ((port = fd_port[idx].port) < RTE_DIM(ports) && ports[port].fd == idx) { return (rx_sync_if(fd_port[idx].port)); } else { return (-EINVAL); } } /** * A call to tx_sync_ring will try to empty a Netmap TX ring by converting its * buffers into rte_mbufs and sending them out on the rings's dpdk port. */ static int tx_sync_ring(struct netmap_ring *ring, uint8_t port, uint16_t ring_number, struct rte_mempool *pool, uint16_t max_burst) { uint32_t i, n_tx; uint16_t burst_size; uint32_t cur_slot, n_used_slots; struct rte_mbuf *tx_mbufs[COMPAT_NETMAP_MAX_BURST]; n_used_slots = ring->num_slots - ring->avail; n_used_slots = RTE_MIN(n_used_slots, max_burst); cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1); while (n_used_slots) { burst_size = (uint16_t)RTE_MIN(n_used_slots, RTE_DIM(tx_mbufs)); for (i = 0; i < burst_size; i++) { tx_mbufs[i] = rte_pktmbuf_alloc(pool); if (tx_mbufs[i] == NULL) goto err; slot_to_mbuf(ring, cur_slot, tx_mbufs[i]); cur_slot = NETMAP_RING_NEXT(ring, cur_slot); } n_tx = rte_eth_tx_burst(port, ring_number, tx_mbufs, burst_size); /* Update the Netmap ring structure to reflect the change */ ring->avail += n_tx; n_used_slots -= n_tx; /* Return the mbufs that failed to transmit to their pool */ if (unlikely(n_tx != burst_size)) { for (i = n_tx; i < burst_size; i++) rte_pktmbuf_free(tx_mbufs[i]); break; } } return 0; err: for (; i == 0; --i) rte_pktmbuf_free(tx_mbufs[i]); RTE_LOG(ERR, USER1, "Couldn't get mbuf from mempool is the mempool too small?\n"); return -1; } static int tx_sync_if(uint32_t port) { uint16_t burst; uint32_t i, rc; struct netmap_if *nifp; struct netmap_ring *r; struct rte_mempool *mp; nifp = ports[port].nmif; mp = ports[port].pool; burst = ports[port].tx_burst; rc = 0; for (i = 0; i < nifp->ni_tx_rings + 1; i++) { r = NETMAP_TXRING(nifp, i); tx_sync_ring(r, (uint8_t)port, (uint16_t)i, mp, burst); rc += r->avail; } return (rc); } /** * Simulate a Netmap NIOCTXSYNC ioctl: */ static inline int ioctl_nioctxsync(int fd) { uint32_t idx, port; idx = FD_TO_IDX(fd); if ((port = fd_port[idx].port) < RTE_DIM(ports) && ports[port].fd == idx) { return (tx_sync_if(fd_port[idx].port)); } else { return (-EINVAL); } } /** * Give the library a mempool of rte_mbufs with which it can do the * rte_mbuf <--> netmap slot conversions. */ int rte_netmap_init(const struct rte_netmap_conf *conf) { size_t buf_ofs, nmif_sz, sz; size_t port_rings, port_slots, port_bufs; uint32_t i, port_num; port_num = RTE_MAX_ETHPORTS; port_rings = 2 * conf->max_rings; port_slots = port_rings * conf->max_slots; port_bufs = port_slots; nmif_sz = NETMAP_IF_RING_OFS(port_rings, port_rings, port_slots); sz = nmif_sz * port_num; buf_ofs = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE); sz = buf_ofs + port_bufs * conf->max_bufsz * port_num; if (sz > UINT32_MAX || (netmap.mem = rte_zmalloc_socket(__func__, sz, RTE_CACHE_LINE_SIZE, conf->socket_id)) == NULL) { RTE_LOG(ERR, USER1, "%s: failed to allocate %zu bytes\n", __func__, sz); return (-ENOMEM); } netmap.mem_sz = sz; netmap.netif_memsz = nmif_sz; netmap.buf_start = (uintptr_t)netmap.mem + buf_ofs; netmap.conf = *conf; rte_spinlock_init(&netmap_lock); /* Mark all ports as unused and set NETIF pointer. */ for (i = 0; i != RTE_DIM(ports); i++) { ports[i].fd = UINT32_MAX; ports[i].nmif = (struct netmap_if *) ((uintptr_t)netmap.mem + nmif_sz * i); } /* Mark all fd_ports as unused. */ for (i = 0; i != RTE_DIM(fd_port); i++) { fd_port[i].port = FD_PORT_FREE; } return (0); } int rte_netmap_init_port(uint8_t portid, const struct rte_netmap_port_conf *conf) { int32_t ret; uint16_t i; uint16_t rx_slots, tx_slots; if (conf == NULL || portid >= RTE_DIM(ports) || conf->nr_tx_rings > netmap.conf.max_rings || conf->nr_rx_rings > netmap.conf.max_rings) { RTE_LOG(ERR, USER1, "%s(%hhu): invalid parameters\n", __func__, portid); return (-EINVAL); } rx_slots = (uint16_t)rte_align32pow2(conf->nr_rx_slots); tx_slots = (uint16_t)rte_align32pow2(conf->nr_tx_slots); if (tx_slots > netmap.conf.max_slots || rx_slots > netmap.conf.max_slots) { RTE_LOG(ERR, USER1, "%s(%hhu): invalid parameters\n", __func__, portid); return (-EINVAL); } ret = rte_eth_dev_configure(portid, conf->nr_rx_rings, conf->nr_tx_rings, conf->eth_conf); if (ret < 0) { RTE_LOG(ERR, USER1, "Couldn't configure port %hhu\n", portid); return (ret); } for (i = 0; i < conf->nr_tx_rings; i++) { ret = rte_eth_tx_queue_setup(portid, i, tx_slots, conf->socket_id, NULL); if (ret < 0) { RTE_LOG(ERR, USER1, "Couldn't configure TX queue %"PRIu16" of " "port %"PRIu8"\n", i, portid); return (ret); } ret = rte_eth_rx_queue_setup(portid, i, rx_slots, conf->socket_id, NULL, conf->pool); if (ret < 0) { RTE_LOG(ERR, USER1, "Couldn't configure RX queue %"PRIu16" of " "port %"PRIu8"\n", i, portid); return (ret); } } /* copy config to the private storage. */ ports[portid].eth_conf = conf->eth_conf[0]; ports[portid].pool = conf->pool; ports[portid].socket_id = conf->socket_id; ports[portid].nr_tx_rings = conf->nr_tx_rings; ports[portid].nr_rx_rings = conf->nr_rx_rings; ports[portid].nr_tx_slots = tx_slots; ports[portid].nr_rx_slots = rx_slots; ports[portid].tx_burst = conf->tx_burst; ports[portid].rx_burst = conf->rx_burst; return (0); } int rte_netmap_close(__rte_unused int fd) { int32_t rc; rte_spinlock_lock(&netmap_lock); rc = fd_release(fd); rte_spinlock_unlock(&netmap_lock); if (rc < 0) { errno =-rc; rc = -1; } return (rc); } int rte_netmap_ioctl(int fd, uint32_t op, void *param) { int ret; if (!FD_VALID(fd)) { errno = EBADF; return (-1); } switch (op) { case NIOCGINFO: ret = ioctl_niocginfo(fd, param); break; case NIOCREGIF: ret = ioctl_niocregif(fd, param); break; case NIOCUNREGIF: ret = ioctl_niocunregif(fd); break; case NIOCRXSYNC: ret = ioctl_niocrxsync(fd); break; case NIOCTXSYNC: ret = ioctl_nioctxsync(fd); break; default: ret = -ENOTTY; } if (ret < 0) { errno = -ret; ret = -1; } else { ret = 0; } return (ret); } void * rte_netmap_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { static const int cprot = PROT_WRITE | PROT_READ; if (!FD_VALID(fd) || length + offset > netmap.mem_sz || (prot & cprot) != cprot || ((flags & MAP_FIXED) != 0 && addr != NULL)) { errno = EINVAL; return (MAP_FAILED); } return (void *)((uintptr_t)netmap.mem + (uintptr_t)offset); } /** * Return a "fake" file descriptor with a value above RLIMIT_NOFILE so that * any attempt to use that file descriptor with the usual API will fail. */ int rte_netmap_open(__rte_unused const char *pathname, __rte_unused int flags) { int fd; rte_spinlock_lock(&netmap_lock); fd = fd_reserve(); rte_spinlock_unlock(&netmap_lock); if (fd < 0) { errno = -fd; fd = -1; } return (fd); } /** * Doesn't support timeout other than 0 or infinite (negative) timeout */ int rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout) { int32_t count_it, ret; uint32_t i, idx, port; uint32_t want_rx, want_tx; ret = 0; do { for (i = 0; i < nfds; i++) { count_it = 0; if (!FD_VALID(fds[i].fd) || fds[i].events == 0) { fds[i].revents = 0; continue; } idx = FD_TO_IDX(fds[i].fd); if ((port = fd_port[idx].port) >= RTE_DIM(ports) || ports[port].fd != idx) { fds[i].revents |= POLLERR; ret++; continue; } want_rx = fds[i].events & (POLLIN | POLLRDNORM); want_tx = fds[i].events & (POLLOUT | POLLWRNORM); if (want_rx && rx_sync_if(port) > 0) { fds[i].revents = (uint16_t) (fds[i].revents | want_rx); count_it = 1; } if (want_tx && tx_sync_if(port) > 0) { fds[i].revents = (uint16_t) (fds[i].revents | want_tx); count_it = 1; } ret += count_it; } } while ((ret == 0 && timeout < 0) || timeout); return ret; } ================================================ FILE: examples/netmap_compat/lib/compat_netmap.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_COMPAT_NETMAP_H_ #include #include #include #include #include #include "netmap.h" #include "netmap_user.h" /** * One can overwrite Netmap macros here as needed */ struct rte_netmap_conf { int32_t socket_id; uint32_t max_rings; /* number of rings(queues) per netmap_if(port) */ uint32_t max_slots; /* number of slots(descriptors) per netmap ring. */ uint16_t max_bufsz; /* size of each netmap buffer. */ }; struct rte_netmap_port_conf { struct rte_eth_conf *eth_conf; struct rte_mempool *pool; int32_t socket_id; uint16_t nr_tx_rings; uint16_t nr_rx_rings; uint32_t nr_tx_slots; uint32_t nr_rx_slots; uint16_t tx_burst; uint16_t rx_burst; }; int rte_netmap_init(const struct rte_netmap_conf *conf); int rte_netmap_init_port(uint8_t portid, const struct rte_netmap_port_conf *conf); int rte_netmap_close(int fd); int rte_netmap_ioctl(int fd, uint32_t op, void *param); int rte_netmap_open(const char *pathname, int flags); int rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout); void *rte_netmap_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); #endif /* _RTE_COMPAT_NETMAP_H_ */ ================================================ FILE: examples/netmap_compat/netmap/netmap.h ================================================ /* * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * 3. Neither the name of the authors nor the names of their contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTEO LANDI OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * $FreeBSD: head/sys/net/netmap.h 231198 2012-02-08 11:43:29Z luigi $ * $Id: netmap.h 10879 2012-04-12 22:48:59Z luigi $ * * Definitions of constants and the structures used by the netmap * framework, for the part visible to both kernel and userspace. * Detailed info on netmap is available with "man netmap" or at * * http://info.iet.unipi.it/~luigi/netmap/ */ #ifndef _NET_NETMAP_H_ #define _NET_NETMAP_H_ /* * --- Netmap data structures --- * * The data structures used by netmap are shown below. Those in * capital letters are in an mmapp()ed area shared with userspace, * while others are private to the kernel. * Shared structures do not contain pointers but only memory * offsets, so that addressing is portable between kernel and userspace. softc +----------------+ | standard fields| | if_pspare[0] ----------+ +----------------+ | | +----------------+<------+ |(netmap_adapter)| | | netmap_kring | tx_rings *--------------------------------->+---------------+ | | netmap_kring | ring *---------. | rx_rings *--------->+---------------+ | nr_hwcur | | +----------------+ | ring *--------. | nr_hwavail | V | nr_hwcur | | | selinfo | | | nr_hwavail | | +---------------+ . | selinfo | | | ... | . +---------------+ | |(ntx+1 entries)| | .... | | | | |(nrx+1 entries)| | +---------------+ | | | KERNEL +---------------+ | | ==================================================================== | USERSPACE | NETMAP_RING +---->+-------------+ / | cur | NETMAP_IF (nifp, one per file desc.) / | avail | +---------------+ / | buf_ofs | | ni_tx_rings | / +=============+ | ni_rx_rings | / | buf_idx | slot[0] | | / | len, flags | | | / +-------------+ +===============+ / | buf_idx | slot[1] | txring_ofs[0] | (rel.to nifp)--' | len, flags | | txring_ofs[1] | +-------------+ (num_rings+1 entries) (nr_num_slots entries) | txring_ofs[n] | | buf_idx | slot[n-1] +---------------+ | len, flags | | rxring_ofs[0] | +-------------+ | rxring_ofs[1] | (num_rings+1 entries) | txring_ofs[n] | +---------------+ * The private descriptor ('softc' or 'adapter') of each interface * is extended with a "struct netmap_adapter" containing netmap-related * info (see description in dev/netmap/netmap_kernel.h. * Among other things, tx_rings and rx_rings point to the arrays of * "struct netmap_kring" which in turn reache the various * "struct netmap_ring", shared with userspace. * The NETMAP_RING is the userspace-visible replica of the NIC ring. * Each slot has the index of a buffer, its length and some flags. * In user space, the buffer address is computed as * (char *)ring + buf_ofs + index*NETMAP_BUF_SIZE * In the kernel, buffers do not necessarily need to be contiguous, * and the virtual and physical addresses are derived through * a lookup table. * To associate a different buffer to a slot, applications must * write the new index in buf_idx, and set NS_BUF_CHANGED flag to * make sure that the kernel updates the hardware ring as needed. * * Normally the driver is not requested to report the result of * transmissions (this can dramatically speed up operation). * However the user may request to report completion by setting * NS_REPORT. */ struct netmap_slot { uint32_t buf_idx; /* buffer index */ uint16_t len; /* packet length, to be copied to/from the hw ring */ uint16_t flags; /* buf changed, etc. */ #define NS_BUF_CHANGED 0x0001 /* must resync the map, buffer changed */ #define NS_REPORT 0x0002 /* ask the hardware to report results * e.g. by generating an interrupt */ }; /* * Netmap representation of a TX or RX ring (also known as "queue"). * This is a queue implemented as a fixed-size circular array. * At the software level, two fields are important: avail and cur. * * In TX rings: * avail indicates the number of slots available for transmission. * It is updated by the kernel after every netmap system call. * It MUST BE decremented by the application when it appends a * packet. * cur indicates the slot to use for the next packet * to send (i.e. the "tail" of the queue). * It MUST BE incremented by the application before * netmap system calls to reflect the number of newly * sent packets. * It is checked by the kernel on netmap system calls * (normally unmodified by the kernel unless invalid). * * The kernel side of netmap uses two additional fields in its own * private ring structure, netmap_kring: * nr_hwcur is a copy of nr_cur on an NIOCTXSYNC. * nr_hwavail is the number of slots known as available by the * hardware. It is updated on an INTR (inc by the * number of packets sent) and on a NIOCTXSYNC * (decrease by nr_cur - nr_hwcur) * A special case, nr_hwavail is -1 if the transmit * side is idle (no pending transmits). * * In RX rings: * avail is the number of packets available (possibly 0). * It MUST BE decremented by the application when it consumes * a packet, and it is updated to nr_hwavail on a NIOCRXSYNC * cur indicates the first slot that contains a packet not * processed yet (the "head" of the queue). * It MUST BE incremented by the software when it consumes * a packet. * reserved indicates the number of buffers before 'cur' * that the application has still in use. Normally 0, * it MUST BE incremented by the application when it * does not return the buffer immediately, and decremented * when the buffer is finally freed. * * The kernel side of netmap uses two additional fields in the kring: * nr_hwcur is a copy of nr_cur on an NIOCRXSYNC * nr_hwavail is the number of packets available. It is updated * on INTR (inc by the number of new packets arrived) * and on NIOCRXSYNC (decreased by nr_cur - nr_hwcur). * * DATA OWNERSHIP/LOCKING: * The netmap_ring is owned by the user program and it is only * accessed or modified in the upper half of the kernel during * a system call. * * The netmap_kring is only modified by the upper half of the kernel. */ struct netmap_ring { /* * nr_buf_base_ofs is meant to be used through macros. * It contains the offset of the buffer region from this * descriptor. */ ssize_t buf_ofs; uint32_t num_slots; /* number of slots in the ring. */ uint32_t avail; /* number of usable slots */ uint32_t cur; /* 'current' r/w position */ uint32_t reserved; /* not refilled before current */ uint16_t nr_buf_size; uint16_t flags; #define NR_TIMESTAMP 0x0002 /* set timestamp on *sync() */ struct timeval ts; /* time of last *sync() */ /* the slots follow. This struct has variable size */ struct netmap_slot slot[0]; /* array of slots. */ }; /* * Netmap representation of an interface and its queue(s). * There is one netmap_if for each file descriptor on which we want * to select/poll. We assume that on each interface has the same number * of receive and transmit queues. * select/poll operates on one or all pairs depending on the value of * nmr_queueid passed on the ioctl. */ struct netmap_if { char ni_name[IFNAMSIZ]; /* name of the interface. */ u_int ni_version; /* API version, currently unused */ u_int ni_rx_rings; /* number of rx rings */ u_int ni_tx_rings; /* if zero, same as ni_rx_rings */ /* * The following array contains the offset of each netmap ring * from this structure. The first ni_tx_queues+1 entries refer * to the tx rings, the next ni_rx_queues+1 refer to the rx rings * (the last entry in each block refers to the host stack rings). * The area is filled up by the kernel on NIOCREG, * and then only read by userspace code. */ ssize_t ring_ofs[0]; }; #ifndef NIOCREGIF /* * ioctl names and related fields * * NIOCGINFO takes a struct ifreq, the interface name is the input, * the outputs are number of queues and number of descriptor * for each queue (useful to set number of threads etc.). * * NIOCREGIF takes an interface name within a struct ifreq, * and activates netmap mode on the interface (if possible). * * NIOCUNREGIF unregisters the interface associated to the fd. * * NIOCTXSYNC, NIOCRXSYNC synchronize tx or rx queues, * whose identity is set in NIOCREGIF through nr_ringid */ /* * struct nmreq overlays a struct ifreq */ struct nmreq { char nr_name[IFNAMSIZ]; uint32_t nr_version; /* API version */ #define NETMAP_API 3 /* current version */ uint32_t nr_offset; /* nifp offset in the shared region */ uint32_t nr_memsize; /* size of the shared region */ uint32_t nr_tx_slots; /* slots in tx rings */ uint32_t nr_rx_slots; /* slots in rx rings */ uint16_t nr_tx_rings; /* number of tx rings */ uint16_t nr_rx_rings; /* number of rx rings */ uint16_t nr_ringid; /* ring(s) we care about */ #define NETMAP_HW_RING 0x4000 /* low bits indicate one hw ring */ #define NETMAP_SW_RING 0x2000 /* process the sw ring */ #define NETMAP_NO_TX_POLL 0x1000 /* no automatic txsync on poll */ #define NETMAP_RING_MASK 0xfff /* the ring number */ uint16_t spare1; uint32_t spare2[4]; }; /* * FreeBSD uses the size value embedded in the _IOWR to determine * how much to copy in/out. So we need it to match the actual * data structure we pass. We put some spares in the structure * to ease compatibility with other versions */ #define NIOCGINFO _IOWR('i', 145, struct nmreq) /* return IF info */ #define NIOCREGIF _IOWR('i', 146, struct nmreq) /* interface register */ #define NIOCUNREGIF _IO('i', 147) /* interface unregister */ #define NIOCTXSYNC _IO('i', 148) /* sync tx queues */ #define NIOCRXSYNC _IO('i', 149) /* sync rx queues */ #endif /* !NIOCREGIF */ #endif /* _NET_NETMAP_H_ */ ================================================ FILE: examples/netmap_compat/netmap/netmap_user.h ================================================ /* * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * 3. Neither the name of the authors nor the names of their contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTEO LANDI OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /* * $FreeBSD: head/sys/net/netmap_user.h 231198 2012-02-08 11:43:29Z luigi $ * $Id: netmap_user.h 10879 2012-04-12 22:48:59Z luigi $ * * This header contains the macros used to manipulate netmap structures * and packets in userspace. See netmap(4) for more information. * * The address of the struct netmap_if, say nifp, is computed from the * value returned from ioctl(.., NIOCREG, ...) and the mmap region: * ioctl(fd, NIOCREG, &req); * mem = mmap(0, ... ); * nifp = NETMAP_IF(mem, req.nr_nifp); * (so simple, we could just do it manually) * * From there: * struct netmap_ring *NETMAP_TXRING(nifp, index) * struct netmap_ring *NETMAP_RXRING(nifp, index) * we can access ring->nr_cur, ring->nr_avail, ring->nr_flags * * ring->slot[i] gives us the i-th slot (we can access * directly plen, flags, bufindex) * * char *buf = NETMAP_BUF(ring, index) returns a pointer to * the i-th buffer * * Since rings are circular, we have macros to compute the next index * i = NETMAP_RING_NEXT(ring, i); */ #ifndef _NET_NETMAP_USER_H_ #define _NET_NETMAP_USER_H_ #define NETMAP_IF(b, o) (struct netmap_if *)((char *)(b) + (o)) #define NETMAP_TXRING(nifp, index) \ ((struct netmap_ring *)((char *)(nifp) + \ (nifp)->ring_ofs[index] ) ) #define NETMAP_RXRING(nifp, index) \ ((struct netmap_ring *)((char *)(nifp) + \ (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] ) ) #define NETMAP_BUF(ring, index) \ ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size)) #define NETMAP_BUF_IDX(ring, buf) \ ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \ (ring)->nr_buf_size ) #define NETMAP_RING_NEXT(r, i) \ ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) #define NETMAP_RING_FIRST_RESERVED(r) \ ( (r)->cur < (r)->reserved ? \ (r)->cur + (r)->num_slots - (r)->reserved : \ (r)->cur - (r)->reserved ) /* * Return 1 if the given tx ring is empty. */ #define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1) #endif /* _NET_NETMAP_USER_H_ */ ================================================ FILE: examples/packet_ordering/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = packet_ordering # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/packet_ordering/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #define RX_DESC_PER_QUEUE 128 #define TX_DESC_PER_QUEUE 512 #define MAX_PKTS_BURST 32 #define REORDER_BUFFER_SIZE 8192 #define MBUF_PER_POOL 65535 #define MBUF_POOL_CACHE_SIZE 250 #define RING_SIZE 16384 /* uncommnet below line to enable debug logs */ /* #define DEBUG */ #ifdef DEBUG #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) RTE_LOG(DEBUG, log_type, fmt, ##args) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do {} while (0) #endif /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_REORDERAPP RTE_LOGTYPE_USER1 unsigned int portmask; unsigned int disable_reorder; volatile uint8_t quit_signal; static struct rte_mempool *mbuf_pool; static struct rte_eth_conf port_conf_default; struct worker_thread_args { struct rte_ring *ring_in; struct rte_ring *ring_out; }; struct send_thread_args { struct rte_ring *ring_in; struct rte_reorder_buffer *buffer; }; struct output_buffer { unsigned count; struct rte_mbuf *mbufs[MAX_PKTS_BURST]; }; volatile struct app_stats { struct { uint64_t rx_pkts; uint64_t enqueue_pkts; uint64_t enqueue_failed_pkts; } rx __rte_cache_aligned; struct { uint64_t dequeue_pkts; uint64_t enqueue_pkts; uint64_t enqueue_failed_pkts; } wkr __rte_cache_aligned; struct { uint64_t dequeue_pkts; /* Too early pkts transmitted directly w/o reordering */ uint64_t early_pkts_txtd_woro; /* Too early pkts failed from direct transmit */ uint64_t early_pkts_tx_failed_woro; uint64_t ro_tx_pkts; uint64_t ro_tx_failed_pkts; } tx __rte_cache_aligned; } app_stats; /** * Get the last enabled lcore ID * * @return * The last enabled lcore ID. */ static unsigned int get_last_lcore_id(void) { int i; for (i = RTE_MAX_LCORE - 1; i >= 0; i--) if (rte_lcore_is_enabled(i)) return i; return 0; } /** * Get the previous enabled lcore ID * @param id * The current lcore ID * @return * The previous enabled lcore ID or the current lcore * ID if it is the first available core. */ static unsigned int get_previous_lcore_id(unsigned int id) { int i; for (i = id - 1; i >= 0; i--) if (rte_lcore_is_enabled(i)) return i; return id; } static inline void pktmbuf_free_bulk(struct rte_mbuf *mbuf_table[], unsigned n) { unsigned int i; for (i = 0; i < n; i++) rte_pktmbuf_free(mbuf_table[i]); } /* display usage */ static void print_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n", prgname); } static int parse_portmask(const char *portmask) { unsigned long pm; char *end = NULL; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt; int option_index; char **argvopt; char *prgname = argv[0]; static struct option lgopts[] = { {"disable-reorder", 0, 0, 0}, {NULL, 0, 0, 0} }; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': portmask = parse_portmask(optarg); if (portmask == 0) { printf("invalid portmask\n"); print_usage(prgname); return -1; } break; /* long options */ case 0: if (!strcmp(lgopts[option_index].name, "disable-reorder")) { printf("reorder disabled\n"); disable_reorder = 1; } break; default: print_usage(prgname); return -1; } } if (optind <= 1) { print_usage(prgname); return -1; } argv[optind-1] = prgname; optind = 0; /* reset getopt lib */ return 0; } static inline int configure_eth_port(uint8_t port_id) { struct ether_addr addr; const uint16_t rxRings = 1, txRings = 1; const uint8_t nb_ports = rte_eth_dev_count(); int ret; uint16_t q; if (port_id > nb_ports) return -1; ret = rte_eth_dev_configure(port_id, rxRings, txRings, &port_conf_default); if (ret != 0) return ret; for (q = 0; q < rxRings; q++) { ret = rte_eth_rx_queue_setup(port_id, q, RX_DESC_PER_QUEUE, rte_eth_dev_socket_id(port_id), NULL, mbuf_pool); if (ret < 0) return ret; } for (q = 0; q < txRings; q++) { ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE, rte_eth_dev_socket_id(port_id), NULL); if (ret < 0) return ret; } ret = rte_eth_dev_start(port_id); if (ret < 0) return ret; rte_eth_macaddr_get(port_id, &addr); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port_id, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); rte_eth_promiscuous_enable(port_id); return 0; } static void print_stats(void) { const uint8_t nb_ports = rte_eth_dev_count(); unsigned i; struct rte_eth_stats eth_stats; printf("\nRX thread stats:\n"); printf(" - Pkts rxd: %"PRIu64"\n", app_stats.rx.rx_pkts); printf(" - Pkts enqd to workers ring: %"PRIu64"\n", app_stats.rx.enqueue_pkts); printf("\nWorker thread stats:\n"); printf(" - Pkts deqd from workers ring: %"PRIu64"\n", app_stats.wkr.dequeue_pkts); printf(" - Pkts enqd to tx ring: %"PRIu64"\n", app_stats.wkr.enqueue_pkts); printf(" - Pkts enq to tx failed: %"PRIu64"\n", app_stats.wkr.enqueue_failed_pkts); printf("\nTX stats:\n"); printf(" - Pkts deqd from tx ring: %"PRIu64"\n", app_stats.tx.dequeue_pkts); printf(" - Ro Pkts transmitted: %"PRIu64"\n", app_stats.tx.ro_tx_pkts); printf(" - Ro Pkts tx failed: %"PRIu64"\n", app_stats.tx.ro_tx_failed_pkts); printf(" - Pkts transmitted w/o reorder: %"PRIu64"\n", app_stats.tx.early_pkts_txtd_woro); printf(" - Pkts tx failed w/o reorder: %"PRIu64"\n", app_stats.tx.early_pkts_tx_failed_woro); for (i = 0; i < nb_ports; i++) { rte_eth_stats_get(i, ð_stats); printf("\nPort %u stats:\n", i); printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); printf(" - Pkts out: %"PRIu64"\n", eth_stats.opackets); printf(" - In Errs: %"PRIu64"\n", eth_stats.ierrors); printf(" - Out Errs: %"PRIu64"\n", eth_stats.oerrors); printf(" - Mbuf Errs: %"PRIu64"\n", eth_stats.rx_nombuf); } } static void int_handler(int sig_num) { printf("Exiting on signal %d\n", sig_num); quit_signal = 1; } /** * This thread receives mbufs from the port and affects them an internal * sequence number to keep track of their order of arrival through an * mbuf structure. * The mbufs are then passed to the worker threads via the rx_to_workers * ring. */ static int rx_thread(struct rte_ring *ring_out) { const uint8_t nb_ports = rte_eth_dev_count(); uint32_t seqn = 0; uint16_t i, ret = 0; uint16_t nb_rx_pkts; uint8_t port_id; struct rte_mbuf *pkts[MAX_PKTS_BURST]; RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); while (!quit_signal) { for (port_id = 0; port_id < nb_ports; port_id++) { if ((portmask & (1 << port_id)) != 0) { /* receive packets */ nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, MAX_PKTS_BURST); if (nb_rx_pkts == 0) { LOG_DEBUG(REORDERAPP, "%s():Received zero packets\n", __func__); continue; } app_stats.rx.rx_pkts += nb_rx_pkts; /* mark sequence number */ for (i = 0; i < nb_rx_pkts; ) pkts[i++]->seqn = seqn++; /* enqueue to rx_to_workers ring */ ret = rte_ring_enqueue_burst(ring_out, (void *) pkts, nb_rx_pkts); app_stats.rx.enqueue_pkts += ret; if (unlikely(ret < nb_rx_pkts)) { app_stats.rx.enqueue_failed_pkts += (nb_rx_pkts-ret); pktmbuf_free_bulk(&pkts[ret], nb_rx_pkts - ret); } } } } return 0; } /** * This thread takes bursts of packets from the rx_to_workers ring and * Changes the input port value to output port value. And feds it to * workers_to_tx */ static int worker_thread(void *args_ptr) { const uint8_t nb_ports = rte_eth_dev_count(); uint16_t i, ret = 0; uint16_t burst_size = 0; struct worker_thread_args *args; struct rte_mbuf *burst_buffer[MAX_PKTS_BURST] = { NULL }; struct rte_ring *ring_in, *ring_out; const unsigned xor_val = (nb_ports > 1); args = (struct worker_thread_args *) args_ptr; ring_in = args->ring_in; ring_out = args->ring_out; RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); while (!quit_signal) { /* dequeue the mbufs from rx_to_workers ring */ burst_size = rte_ring_dequeue_burst(ring_in, (void *)burst_buffer, MAX_PKTS_BURST); if (unlikely(burst_size == 0)) continue; __sync_fetch_and_add(&app_stats.wkr.dequeue_pkts, burst_size); /* just do some operation on mbuf */ for (i = 0; i < burst_size;) burst_buffer[i++]->port ^= xor_val; /* enqueue the modified mbufs to workers_to_tx ring */ ret = rte_ring_enqueue_burst(ring_out, (void *)burst_buffer, burst_size); __sync_fetch_and_add(&app_stats.wkr.enqueue_pkts, ret); if (unlikely(ret < burst_size)) { /* Return the mbufs to their respective pool, dropping packets */ __sync_fetch_and_add(&app_stats.wkr.enqueue_failed_pkts, (int)burst_size - ret); pktmbuf_free_bulk(&burst_buffer[ret], burst_size - ret); } } return 0; } static inline void flush_one_port(struct output_buffer *outbuf, uint8_t outp) { unsigned nb_tx = rte_eth_tx_burst(outp, 0, outbuf->mbufs, outbuf->count); app_stats.tx.ro_tx_pkts += nb_tx; if (unlikely(nb_tx < outbuf->count)) { /* free the mbufs which failed from transmit */ app_stats.tx.ro_tx_failed_pkts += (outbuf->count - nb_tx); LOG_DEBUG(REORDERAPP, "%s:Packet loss with tx_burst\n", __func__); pktmbuf_free_bulk(&outbuf->mbufs[nb_tx], outbuf->count - nb_tx); } outbuf->count = 0; } /** * Dequeue mbufs from the workers_to_tx ring and reorder them before * transmitting. */ static int send_thread(struct send_thread_args *args) { int ret; unsigned int i, dret; uint16_t nb_dq_mbufs; uint8_t outp; static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS]; struct rte_mbuf *mbufs[MAX_PKTS_BURST]; struct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL}; RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); while (!quit_signal) { /* deque the mbufs from workers_to_tx ring */ nb_dq_mbufs = rte_ring_dequeue_burst(args->ring_in, (void *)mbufs, MAX_PKTS_BURST); if (unlikely(nb_dq_mbufs == 0)) continue; app_stats.tx.dequeue_pkts += nb_dq_mbufs; for (i = 0; i < nb_dq_mbufs; i++) { /* send dequeued mbufs for reordering */ ret = rte_reorder_insert(args->buffer, mbufs[i]); if (ret == -1 && rte_errno == ERANGE) { /* Too early pkts should be transmitted out directly */ LOG_DEBUG(REORDERAPP, "%s():Cannot reorder early packet " "direct enqueuing to TX\n", __func__); outp = mbufs[i]->port; if ((portmask & (1 << outp)) == 0) { rte_pktmbuf_free(mbufs[i]); continue; } if (rte_eth_tx_burst(outp, 0, (void *)mbufs[i], 1) != 1) { rte_pktmbuf_free(mbufs[i]); app_stats.tx.early_pkts_tx_failed_woro++; } else app_stats.tx.early_pkts_txtd_woro++; } else if (ret == -1 && rte_errno == ENOSPC) { /** * Early pkts just outside of window should be dropped */ rte_pktmbuf_free(mbufs[i]); } } /* * drain MAX_PKTS_BURST of reordered * mbufs for transmit */ dret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST); for (i = 0; i < dret; i++) { struct output_buffer *outbuf; uint8_t outp1; outp1 = rombufs[i]->port; /* skip ports that are not enabled */ if ((portmask & (1 << outp1)) == 0) { rte_pktmbuf_free(rombufs[i]); continue; } outbuf = &tx_buffers[outp1]; outbuf->mbufs[outbuf->count++] = rombufs[i]; if (outbuf->count == MAX_PKTS_BURST) flush_one_port(outbuf, outp1); } } return 0; } /** * Dequeue mbufs from the workers_to_tx ring and transmit them */ static int tx_thread(struct rte_ring *ring_in) { uint32_t i, dqnum; uint8_t outp; static struct output_buffer tx_buffers[RTE_MAX_ETHPORTS]; struct rte_mbuf *mbufs[MAX_PKTS_BURST]; struct output_buffer *outbuf; RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); while (!quit_signal) { /* deque the mbufs from workers_to_tx ring */ dqnum = rte_ring_dequeue_burst(ring_in, (void *)mbufs, MAX_PKTS_BURST); if (unlikely(dqnum == 0)) continue; app_stats.tx.dequeue_pkts += dqnum; for (i = 0; i < dqnum; i++) { outp = mbufs[i]->port; /* skip ports that are not enabled */ if ((portmask & (1 << outp)) == 0) { rte_pktmbuf_free(mbufs[i]); continue; } outbuf = &tx_buffers[outp]; outbuf->mbufs[outbuf->count++] = mbufs[i]; if (outbuf->count == MAX_PKTS_BURST) flush_one_port(outbuf, outp); } } return 0; } int main(int argc, char **argv) { int ret; unsigned nb_ports; unsigned int lcore_id, last_lcore_id, master_lcore_id; uint8_t port_id; uint8_t nb_ports_available; struct worker_thread_args worker_args = {NULL, NULL}; struct send_thread_args send_args = {NULL, NULL}; struct rte_ring *rx_to_workers; struct rte_ring *workers_to_tx; /* catch ctrl-c so we can print on exit */ signal(SIGINT, int_handler); /* Initialize EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) return -1; argc -= ret; argv += ret; /* Parse the application specific arguments */ ret = parse_args(argc, argv); if (ret < 0) return -1; /* Check if we have enought cores */ if (rte_lcore_count() < 3) rte_exit(EXIT_FAILURE, "Error, This application needs at " "least 3 logical cores to run:\n" "1 lcore for packet RX\n" "1 lcore for packet TX\n" "and at least 1 lcore for worker threads\n"); nb_ports = rte_eth_dev_count(); if (nb_ports == 0) rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); if (nb_ports != 1 && (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even, except " "when using a single port\n"); mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, MBUF_POOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); nb_ports_available = nb_ports; /* initialize all ports */ for (port_id = 0; port_id < nb_ports; port_id++) { /* skip ports that are not enabled */ if ((portmask & (1 << port_id)) == 0) { printf("\nSkipping disabled port %d\n", port_id); nb_ports_available--; continue; } /* init port */ printf("Initializing port %u... done\n", (unsigned) port_id); if (configure_eth_port(port_id) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize port %"PRIu8"\n", port_id); } if (!nb_ports_available) { rte_exit(EXIT_FAILURE, "All available ports are disabled. Please set portmask.\n"); } /* Create rings for inter core communication */ rx_to_workers = rte_ring_create("rx_to_workers", RING_SIZE, rte_socket_id(), RING_F_SP_ENQ); if (rx_to_workers == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); workers_to_tx = rte_ring_create("workers_to_tx", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ); if (workers_to_tx == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); if (!disable_reorder) { send_args.buffer = rte_reorder_create("PKT_RO", rte_socket_id(), REORDER_BUFFER_SIZE); if (send_args.buffer == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); } last_lcore_id = get_last_lcore_id(); master_lcore_id = rte_get_master_lcore(); worker_args.ring_in = rx_to_workers; worker_args.ring_out = workers_to_tx; /* Start worker_thread() on all the available slave cores but the last 1 */ for (lcore_id = 0; lcore_id <= get_previous_lcore_id(last_lcore_id); lcore_id++) if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) rte_eal_remote_launch(worker_thread, (void *)&worker_args, lcore_id); if (disable_reorder) { /* Start tx_thread() on the last slave core */ rte_eal_remote_launch((lcore_function_t *)tx_thread, workers_to_tx, last_lcore_id); } else { send_args.ring_in = workers_to_tx; /* Start send_thread() on the last slave core */ rte_eal_remote_launch((lcore_function_t *)send_thread, (void *)&send_args, last_lcore_id); } /* Start rx_thread() on the master core */ rx_thread(rx_to_workers); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } print_stats(); return 0; } ================================================ FILE: examples/qos_meter/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = qos_meter # all source are stored in SRCS-y SRCS-y := main.c rte_policer.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/qos_meter/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include /* * Traffic metering configuration * */ #define APP_MODE_FWD 0 #define APP_MODE_SRTCM_COLOR_BLIND 1 #define APP_MODE_SRTCM_COLOR_AWARE 2 #define APP_MODE_TRTCM_COLOR_BLIND 3 #define APP_MODE_TRTCM_COLOR_AWARE 4 #define APP_MODE APP_MODE_SRTCM_COLOR_BLIND #include "main.h" #define APP_PKT_FLOW_POS 33 #define APP_PKT_COLOR_POS 5 #if APP_PKT_FLOW_POS > 64 || APP_PKT_COLOR_POS > 64 #error Byte offset needs to be less than 64 #endif /* * Buffer pool configuration * ***/ #define NB_MBUF 8192 #define MEMPOOL_CACHE_SIZE 256 static struct rte_mempool *pool = NULL; /* * NIC configuration * ***/ static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, .hw_ip_checksum = 1, .hw_vlan_filter = 0, .jumbo_frame = 0, .hw_strip_crc = 0, }, .rx_adv_conf = { .rss_conf = { .rss_key = NULL, .rss_hf = ETH_RSS_IP, }, }, .txmode = { .mq_mode = ETH_DCB_NONE, }, }; #define NIC_RX_QUEUE_DESC 128 #define NIC_TX_QUEUE_DESC 512 #define NIC_RX_QUEUE 0 #define NIC_TX_QUEUE 0 /* * Packet RX/TX * ***/ #define PKT_RX_BURST_MAX 32 #define PKT_TX_BURST_MAX 32 #define TIME_TX_DRAIN 200000ULL static uint8_t port_rx; static uint8_t port_tx; static struct rte_mbuf *pkts_rx[PKT_RX_BURST_MAX]; static struct rte_mbuf *pkts_tx[PKT_TX_BURST_MAX]; static uint16_t pkts_tx_len = 0; struct rte_meter_srtcm_params app_srtcm_params[] = { {.cir = 1000000 * 46, .cbs = 2048, .ebs = 2048}, }; struct rte_meter_trtcm_params app_trtcm_params[] = { {.cir = 1000000 * 46, .pir = 1500000 * 46, .cbs = 2048, .pbs = 2048}, }; #define APP_FLOWS_MAX 256 FLOW_METER app_flows[APP_FLOWS_MAX]; static void app_configure_flow_table(void) { uint32_t i, j; for (i = 0, j = 0; i < APP_FLOWS_MAX; i ++, j = (j + 1) % RTE_DIM(PARAMS)){ FUNC_CONFIG(&app_flows[i], &PARAMS[j]); } } static inline void app_set_pkt_color(uint8_t *pkt_data, enum policer_action color) { pkt_data[APP_PKT_COLOR_POS] = (uint8_t)color; } static inline int app_pkt_handle(struct rte_mbuf *pkt, uint64_t time) { uint8_t input_color, output_color; uint8_t *pkt_data = rte_pktmbuf_mtod(pkt, uint8_t *); uint32_t pkt_len = rte_pktmbuf_pkt_len(pkt) - sizeof(struct ether_hdr); uint8_t flow_id = (uint8_t)(pkt_data[APP_PKT_FLOW_POS] & (APP_FLOWS_MAX - 1)); input_color = pkt_data[APP_PKT_COLOR_POS]; enum policer_action action; /* color input is not used for blind modes */ output_color = (uint8_t) FUNC_METER(&app_flows[flow_id], time, pkt_len, (enum rte_meter_color) input_color); /* Apply policing and set the output color */ action = policer_table[input_color][output_color]; app_set_pkt_color(pkt_data, action); return action; } static __attribute__((noreturn)) int main_loop(__attribute__((unused)) void *dummy) { uint64_t current_time, last_time = rte_rdtsc(); uint32_t lcore_id = rte_lcore_id(); printf("Core %u: port RX = %d, port TX = %d\n", lcore_id, port_rx, port_tx); while (1) { uint64_t time_diff; int i, nb_rx; /* Mechanism to avoid stale packets in the output buffer */ current_time = rte_rdtsc(); time_diff = current_time - last_time; if (unlikely(time_diff > TIME_TX_DRAIN)) { int ret; if (pkts_tx_len == 0) { last_time = current_time; continue; } /* Write packet burst to NIC TX */ ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, pkts_tx_len); /* Free buffers for any packets not written successfully */ if (unlikely(ret < pkts_tx_len)) { for ( ; ret < pkts_tx_len; ret ++) { rte_pktmbuf_free(pkts_tx[ret]); } } /* Empty the output buffer */ pkts_tx_len = 0; last_time = current_time; } /* Read packet burst from NIC RX */ nb_rx = rte_eth_rx_burst(port_rx, NIC_RX_QUEUE, pkts_rx, PKT_RX_BURST_MAX); /* Handle packets */ for (i = 0; i < nb_rx; i ++) { struct rte_mbuf *pkt = pkts_rx[i]; /* Handle current packet */ if (app_pkt_handle(pkt, current_time) == DROP) rte_pktmbuf_free(pkt); else { pkts_tx[pkts_tx_len] = pkt; pkts_tx_len ++; } /* Write packets from output buffer to NIC TX when full burst is available */ if (unlikely(pkts_tx_len == PKT_TX_BURST_MAX)) { /* Write packet burst to NIC TX */ int ret = rte_eth_tx_burst(port_tx, NIC_TX_QUEUE, pkts_tx, PKT_TX_BURST_MAX); /* Free buffers for any packets not written successfully */ if (unlikely(ret < PKT_TX_BURST_MAX)) { for ( ; ret < PKT_TX_BURST_MAX; ret ++) { rte_pktmbuf_free(pkts_tx[ret]); } } /* Empty the output buffer */ pkts_tx_len = 0; } } } } static void print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n", prgname); } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /* Parse the argument given in the command line of the application */ static int parse_args(int argc, char **argv) { int opt; char **argvopt; int option_index; char *prgname = argv[0]; static struct option lgopts[] = { {NULL, 0, 0, 0} }; uint64_t port_mask, i, mask; argvopt = argv; while ((opt = getopt_long(argc, argvopt, "p:", lgopts, &option_index)) != EOF) { switch (opt) { case 'p': port_mask = parse_portmask(optarg); if (port_mask == 0) { printf("invalid port mask (null port mask)\n"); print_usage(prgname); return -1; } for (i = 0, mask = 1; i < 64; i ++, mask <<= 1){ if (mask & port_mask){ port_rx = i; port_mask &= ~ mask; break; } } for (i = 0, mask = 1; i < 64; i ++, mask <<= 1){ if (mask & port_mask){ port_tx = i; port_mask &= ~ mask; break; } } if (port_mask != 0) { printf("invalid port mask (more than 2 ports)\n"); print_usage(prgname); return -1; } break; default: print_usage(prgname); return -1; } } if (optind <= 1) { print_usage(prgname); return -1; } argv[optind-1] = prgname; optind = 0; /* reset getopt lib */ return 0; } int main(int argc, char **argv) { uint32_t lcore_id; int ret; /* EAL init */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); argc -= ret; argv += ret; if (rte_lcore_count() != 1) { rte_exit(EXIT_FAILURE, "This application does not accept more than one core. " "Please adjust the \"-c COREMASK\" parameter accordingly.\n"); } /* Application non-EAL arguments parse */ ret = parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid input arguments\n"); /* Buffer pool init */ pool = rte_pktmbuf_pool_create("pool", NB_MBUF, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (pool == NULL) rte_exit(EXIT_FAILURE, "Buffer pool creation error\n"); /* NIC init */ ret = rte_eth_dev_configure(port_rx, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_rx, ret); ret = rte_eth_rx_queue_setup(port_rx, NIC_RX_QUEUE, NIC_RX_QUEUE_DESC, rte_eth_dev_socket_id(port_rx), NULL, pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_rx, ret); ret = rte_eth_tx_queue_setup(port_rx, NIC_TX_QUEUE, NIC_TX_QUEUE_DESC, rte_eth_dev_socket_id(port_rx), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d TX queue setup error (%d)\n", port_rx, ret); ret = rte_eth_dev_configure(port_tx, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_tx, ret); ret = rte_eth_rx_queue_setup(port_tx, NIC_RX_QUEUE, NIC_RX_QUEUE_DESC, rte_eth_dev_socket_id(port_tx), NULL, pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_tx, ret); ret = rte_eth_tx_queue_setup(port_tx, NIC_TX_QUEUE, NIC_TX_QUEUE_DESC, rte_eth_dev_socket_id(port_tx), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d TX queue setup error (%d)\n", port_tx, ret); ret = rte_eth_dev_start(port_rx); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d start error (%d)\n", port_rx, ret); ret = rte_eth_dev_start(port_tx); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d start error (%d)\n", port_tx, ret); rte_eth_promiscuous_enable(port_rx); rte_eth_promiscuous_enable(port_tx); /* App configuration */ app_configure_flow_table(); /* Launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/qos_meter/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ enum policer_action { GREEN = e_RTE_METER_GREEN, YELLOW = e_RTE_METER_YELLOW, RED = e_RTE_METER_RED, DROP = 3, }; enum policer_action policer_table[e_RTE_METER_COLORS][e_RTE_METER_COLORS] = { { GREEN, RED, RED}, { DROP, YELLOW, RED}, { DROP, DROP, RED} }; #if APP_MODE == APP_MODE_FWD #define FUNC_METER(a,b,c,d) color, flow_id=flow_id, pkt_len=pkt_len, time=time #define FUNC_CONFIG(a,b) #define PARAMS app_srtcm_params #define FLOW_METER int #elif APP_MODE == APP_MODE_SRTCM_COLOR_BLIND #define FUNC_METER(a,b,c,d) rte_meter_srtcm_color_blind_check(a,b,c) #define FUNC_CONFIG rte_meter_srtcm_config #define PARAMS app_srtcm_params #define FLOW_METER struct rte_meter_srtcm #elif (APP_MODE == APP_MODE_SRTCM_COLOR_AWARE) #define FUNC_METER rte_meter_srtcm_color_aware_check #define FUNC_CONFIG rte_meter_srtcm_config #define PARAMS app_srtcm_params #define FLOW_METER struct rte_meter_srtcm #elif (APP_MODE == APP_MODE_TRTCM_COLOR_BLIND) #define FUNC_METER(a,b,c,d) rte_meter_trtcm_color_blind_check(a,b,c) #define FUNC_CONFIG rte_meter_trtcm_config #define PARAMS app_trtcm_params #define FLOW_METER struct rte_meter_trtcm #elif (APP_MODE == APP_MODE_TRTCM_COLOR_AWARE) #define FUNC_METER rte_meter_trtcm_color_aware_check #define FUNC_CONFIG rte_meter_trtcm_config #define PARAMS app_trtcm_params #define FLOW_METER struct rte_meter_trtcm #else #error Invalid value for APP_MODE #endif #endif /* _MAIN_H_ */ ================================================ FILE: examples/qos_meter/rte_policer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "rte_policer.h" int rte_phb_config(struct rte_phb *phb_table, uint32_t phb_table_index, enum rte_meter_color pre_meter, enum rte_meter_color post_meter, enum rte_phb_action action) { struct rte_phb *phb = NULL; /* User argument checking */ if (phb_table == NULL) { return -1; } if ((pre_meter > e_RTE_METER_RED) || (post_meter > e_RTE_METER_RED) || (pre_meter > post_meter)) { return -2; } /* Set action in PHB table entry */ phb = &phb_table[phb_table_index]; phb->actions[pre_meter][post_meter] = action; return 0; } ================================================ FILE: examples/qos_meter/rte_policer.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_POLICER_H__ #define __INCLUDE_RTE_POLICER_H__ #include #include enum rte_phb_action { e_RTE_PHB_ACTION_GREEN = e_RTE_METER_GREEN, e_RTE_PHB_ACTION_YELLOW = e_RTE_METER_YELLOW, e_RTE_PHB_ACTION_RED = e_RTE_METER_RED, e_RTE_PHB_ACTION_DROP = 3, }; struct rte_phb { enum rte_phb_action actions[e_RTE_METER_COLORS][e_RTE_METER_COLORS]; }; int rte_phb_config(struct rte_phb *phb_table, uint32_t phb_table_index, enum rte_meter_color pre_meter, enum rte_meter_color post_meter, enum rte_phb_action action); static inline enum rte_phb_action policer_run(struct rte_phb *phb_table, uint32_t phb_table_index, enum rte_meter_color pre_meter, enum rte_meter_color post_meter) { struct rte_phb *phb = &phb_table[phb_table_index]; enum rte_phb_action action = phb->actions[pre_meter][post_meter]; return action; } #endif ================================================ FILE: examples/qos_sched/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: else # binary name APP = qos_sched # all source are stored in SRCS-y SRCS-y := main.c args.c init.c app_thread.c cfg_file.c cmdline.c stats.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS_args.o := -D_GNU_SOURCE CFLAGS_cfg_file.o := -D_GNU_SOURCE include $(RTE_SDK)/mk/rte.extapp.mk endif ================================================ FILE: examples/qos_sched/app_thread.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "main.h" /* * QoS parameters are encoded as follows: * Outer VLAN ID defines subport * Inner VLAN ID defines pipe * Destination IP 0.0.XXX.0 defines traffic class * Destination IP host (0.0.0.XXX) defines queue * Values below define offset to each field from start of frame */ #define SUBPORT_OFFSET 7 #define PIPE_OFFSET 9 #define TC_OFFSET 20 #define QUEUE_OFFSET 20 #define COLOR_OFFSET 19 static inline int get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint32_t *traffic_class, uint32_t *queue, uint32_t *color) { uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ *traffic_class = (pdata[QUEUE_OFFSET] & 0x0F) & (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1); /* Destination IP */ *queue = ((pdata[QUEUE_OFFSET] >> 8) & 0x0F) & (RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS - 1) ; /* Destination IP */ *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ return 0; } void app_rx_thread(struct thread_conf **confs) { uint32_t i, nb_rx; struct rte_mbuf *rx_mbufs[burst_conf.rx_burst] __rte_cache_aligned; struct thread_conf *conf; int conf_idx = 0; uint32_t subport; uint32_t pipe; uint32_t traffic_class; uint32_t queue; uint32_t color; while ((conf = confs[conf_idx])) { nb_rx = rte_eth_rx_burst(conf->rx_port, conf->rx_queue, rx_mbufs, burst_conf.rx_burst); if (likely(nb_rx != 0)) { APP_STATS_ADD(conf->stat.nb_rx, nb_rx); for(i = 0; i < nb_rx; i++) { get_pkt_sched(rx_mbufs[i], &subport, &pipe, &traffic_class, &queue, &color); rte_sched_port_pkt_write(rx_mbufs[i], subport, pipe, traffic_class, queue, (enum rte_meter_color) color); } if (unlikely(rte_ring_sp_enqueue_bulk(conf->rx_ring, (void **)rx_mbufs, nb_rx) != 0)) { for(i = 0; i < nb_rx; i++) { rte_pktmbuf_free(rx_mbufs[i]); APP_STATS_ADD(conf->stat.nb_drop, 1); } } } conf_idx++; if (confs[conf_idx] == NULL) conf_idx = 0; } } /* Send the packet to an output interface * For performance reason function returns number of packets dropped, not sent, * so 0 means that all packets were sent successfully */ static inline void app_send_burst(struct thread_conf *qconf) { struct rte_mbuf **mbufs; uint32_t n, ret; mbufs = (struct rte_mbuf **)qconf->m_table; n = qconf->n_mbufs; do { ret = rte_eth_tx_burst(qconf->tx_port, qconf->tx_queue, mbufs, (uint16_t)n); /* we cannot drop the packets, so re-send */ /* update number of packets to be sent */ n -= ret; mbufs = (struct rte_mbuf **)&mbufs[ret]; } while (n); } /* Send the packet to an output interface */ static void app_send_packets(struct thread_conf *qconf, struct rte_mbuf **mbufs, uint32_t nb_pkt) { uint32_t i, len; len = qconf->n_mbufs; for(i = 0; i < nb_pkt; i++) { qconf->m_table[len] = mbufs[i]; len++; /* enough pkts to be sent */ if (unlikely(len == burst_conf.tx_burst)) { qconf->n_mbufs = len; app_send_burst(qconf); len = 0; } } qconf->n_mbufs = len; } void app_tx_thread(struct thread_conf **confs) { struct rte_mbuf *mbufs[burst_conf.qos_dequeue]; struct thread_conf *conf; int conf_idx = 0; int retval; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; while ((conf = confs[conf_idx])) { retval = rte_ring_sc_dequeue_bulk(conf->tx_ring, (void **)mbufs, burst_conf.qos_dequeue); if (likely(retval == 0)) { app_send_packets(conf, mbufs, burst_conf.qos_dequeue); conf->counter = 0; /* reset empty read loop counter */ } conf->counter++; /* drain ring and TX queues */ if (unlikely(conf->counter > drain_tsc)) { /* now check is there any packets left to be transmitted */ if (conf->n_mbufs != 0) { app_send_burst(conf); conf->n_mbufs = 0; } conf->counter = 0; } conf_idx++; if (confs[conf_idx] == NULL) conf_idx = 0; } } void app_worker_thread(struct thread_conf **confs) { struct rte_mbuf *mbufs[burst_conf.ring_burst]; struct thread_conf *conf; int conf_idx = 0; while ((conf = confs[conf_idx])) { uint32_t nb_pkt; int retval; /* Read packet from the ring */ retval = rte_ring_sc_dequeue_bulk(conf->rx_ring, (void **)mbufs, burst_conf.ring_burst); if (likely(retval == 0)) { int nb_sent = rte_sched_port_enqueue(conf->sched_port, mbufs, burst_conf.ring_burst); APP_STATS_ADD(conf->stat.nb_drop, burst_conf.ring_burst - nb_sent); APP_STATS_ADD(conf->stat.nb_rx, burst_conf.ring_burst); } nb_pkt = rte_sched_port_dequeue(conf->sched_port, mbufs, burst_conf.qos_dequeue); if (likely(nb_pkt > 0)) while (rte_ring_sp_enqueue_bulk(conf->tx_ring, (void **)mbufs, nb_pkt) != 0); conf_idx++; if (confs[conf_idx] == NULL) conf_idx = 0; } } void app_mixed_thread(struct thread_conf **confs) { struct rte_mbuf *mbufs[burst_conf.ring_burst]; struct thread_conf *conf; int conf_idx = 0; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; while ((conf = confs[conf_idx])) { uint32_t nb_pkt; int retval; /* Read packet from the ring */ retval = rte_ring_sc_dequeue_bulk(conf->rx_ring, (void **)mbufs, burst_conf.ring_burst); if (likely(retval == 0)) { int nb_sent = rte_sched_port_enqueue(conf->sched_port, mbufs, burst_conf.ring_burst); APP_STATS_ADD(conf->stat.nb_drop, burst_conf.ring_burst - nb_sent); APP_STATS_ADD(conf->stat.nb_rx, burst_conf.ring_burst); } nb_pkt = rte_sched_port_dequeue(conf->sched_port, mbufs, burst_conf.qos_dequeue); if (likely(nb_pkt > 0)) { app_send_packets(conf, mbufs, nb_pkt); conf->counter = 0; /* reset empty read loop counter */ } conf->counter++; /* drain ring and TX queues */ if (unlikely(conf->counter > drain_tsc)) { /* now check is there any packets left to be transmitted */ if (conf->n_mbufs != 0) { app_send_burst(conf); conf->n_mbufs = 0; } conf->counter = 0; } conf_idx++; if (confs[conf_idx] == NULL) conf_idx = 0; } } ================================================ FILE: examples/qos_sched/args.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #define APP_NAME "qos_sched" #define MAX_OPT_VALUES 8 #define SYS_CPU_DIR "/sys/devices/system/cpu/cpu%u/topology/" static uint32_t app_master_core = 1; static uint32_t app_numa_mask; static uint64_t app_used_core_mask = 0; static uint64_t app_used_port_mask = 0; static uint64_t app_used_rx_port_mask = 0; static uint64_t app_used_tx_port_mask = 0; static const char usage[] = " \n" " %s \n" " \n" "Application mandatory parameters: \n" " --pfc \"RX PORT, TX PORT, RX LCORE, WT LCORE\" : Packet flow configuration \n" " multiple pfc can be configured in command line \n" " \n" "Application optional parameters: \n" " --i : run in interactive mode (default value is %u) \n" " --mst I : master core index (default value is %u) \n" " --rsz \"A, B, C\" : Ring sizes \n" " A = Size (in number of buffer descriptors) of each of the NIC RX \n" " rings read by the I/O RX lcores (default value is %u) \n" " B = Size (in number of elements) of each of the SW rings used by the\n" " I/O RX lcores to send packets to worker lcores (default value is\n" " %u) \n" " C = Size (in number of buffer descriptors) of each of the NIC TX \n" " rings written by worker lcores (default value is %u) \n" " --bsz \"A, B, C, D\": Burst sizes \n" " A = I/O RX lcore read burst size from NIC RX (default value is %u) \n" " B = I/O RX lcore write burst size to output SW rings, \n" " Worker lcore read burst size from input SW rings, \n" " QoS enqueue size (default value is %u) \n" " C = QoS dequeue size (default value is %u) \n" " D = Worker lcore write burst size to NIC TX (default value is %u) \n" " --msz M : Mempool size (in number of mbufs) for each pfc (default %u) \n" " --rth \"A, B, C\" : RX queue threshold parameters \n" " A = RX prefetch threshold (default value is %u) \n" " B = RX host threshold (default value is %u) \n" " C = RX write-back threshold (default value is %u) \n" " --tth \"A, B, C\" : TX queue threshold parameters \n" " A = TX prefetch threshold (default value is %u) \n" " B = TX host threshold (default value is %u) \n" " C = TX write-back threshold (default value is %u) \n" " --cfg FILE : profile configuration to load \n" ; /* display usage */ static void app_usage(const char *prgname) { printf(usage, prgname, APP_INTERACTIVE_DEFAULT, app_master_core, APP_RX_DESC_DEFAULT, APP_RING_SIZE, APP_TX_DESC_DEFAULT, MAX_PKT_RX_BURST, PKT_ENQUEUE, PKT_DEQUEUE, MAX_PKT_TX_BURST, NB_MBUF, RX_PTHRESH, RX_HTHRESH, RX_WTHRESH, TX_PTHRESH, TX_HTHRESH, TX_WTHRESH ); } static inline int str_is(const char *str, const char *is) { return (strcmp(str, is) == 0); } /* returns core mask used by DPDK */ static uint64_t app_eal_core_mask(void) { uint32_t i; uint64_t cm = 0; struct rte_config *cfg = rte_eal_get_configuration(); for (i = 0; i < RTE_MAX_LCORE; i++) { if (cfg->lcore_role[i] == ROLE_RTE) cm |= (1ULL << i); } cm |= (1ULL << cfg->master_lcore); return cm; } /* returns total number of cores presented in a system */ static uint32_t app_cpu_core_count(void) { int i, len; char path[PATH_MAX]; uint32_t ncores = 0; for(i = 0; i < RTE_MAX_LCORE; i++) { len = snprintf(path, sizeof(path), SYS_CPU_DIR, i); if (len <= 0 || (unsigned)len >= sizeof(path)) continue; if (access(path, F_OK) == 0) ncores++; } return ncores; } /* returns: number of values parsed -1 in case of error */ static int app_parse_opt_vals(const char *conf_str, char separator, uint32_t n_vals, uint32_t *opt_vals) { char *string; uint32_t i, n_tokens; char *tokens[MAX_OPT_VALUES]; if (conf_str == NULL || opt_vals == NULL || n_vals == 0 || n_vals > MAX_OPT_VALUES) return -1; /* duplicate configuration string before splitting it to tokens */ string = strdup(conf_str); if (string == NULL) return -1; n_tokens = rte_strsplit(string, strnlen(string, 32), tokens, n_vals, separator); for(i = 0; i < n_tokens; i++) { opt_vals[i] = (uint32_t)atol(tokens[i]); } free(string); return n_tokens; } static int app_parse_ring_conf(const char *conf_str) { int ret; uint32_t vals[3]; ret = app_parse_opt_vals(conf_str, ',', 3, vals); if (ret != 3) return ret; ring_conf.rx_size = vals[0]; ring_conf.ring_size = vals[1]; ring_conf.tx_size = vals[2]; return 0; } static int app_parse_rth_conf(const char *conf_str) { int ret; uint32_t vals[3]; ret = app_parse_opt_vals(conf_str, ',', 3, vals); if (ret != 3) return ret; rx_thresh.pthresh = (uint8_t)vals[0]; rx_thresh.hthresh = (uint8_t)vals[1]; rx_thresh.wthresh = (uint8_t)vals[2]; return 0; } static int app_parse_tth_conf(const char *conf_str) { int ret; uint32_t vals[3]; ret = app_parse_opt_vals(conf_str, ',', 3, vals); if (ret != 3) return ret; tx_thresh.pthresh = (uint8_t)vals[0]; tx_thresh.hthresh = (uint8_t)vals[1]; tx_thresh.wthresh = (uint8_t)vals[2]; return 0; } static int app_parse_flow_conf(const char *conf_str) { int ret; uint32_t vals[5]; struct flow_conf *pconf; uint64_t mask; ret = app_parse_opt_vals(conf_str, ',', 6, vals); if (ret < 4 || ret > 5) return ret; pconf = &qos_conf[nb_pfc]; pconf->rx_port = (uint8_t)vals[0]; pconf->tx_port = (uint8_t)vals[1]; pconf->rx_core = (uint8_t)vals[2]; pconf->wt_core = (uint8_t)vals[3]; if (ret == 5) pconf->tx_core = (uint8_t)vals[4]; else pconf->tx_core = pconf->wt_core; if (pconf->rx_core == pconf->wt_core) { RTE_LOG(ERR, APP, "pfc %u: rx thread and worker thread cannot share same core\n", nb_pfc); return -1; } if (pconf->rx_port >= RTE_MAX_ETHPORTS) { RTE_LOG(ERR, APP, "pfc %u: invalid rx port %"PRIu8" index\n", nb_pfc, pconf->rx_port); return -1; } if (pconf->tx_port >= RTE_MAX_ETHPORTS) { RTE_LOG(ERR, APP, "pfc %u: invalid tx port %"PRIu8" index\n", nb_pfc, pconf->rx_port); return -1; } mask = 1lu << pconf->rx_port; if (app_used_rx_port_mask & mask) { RTE_LOG(ERR, APP, "pfc %u: rx port %"PRIu8" is used already\n", nb_pfc, pconf->rx_port); return -1; } app_used_rx_port_mask |= mask; app_used_port_mask |= mask; mask = 1lu << pconf->tx_port; if (app_used_tx_port_mask & mask) { RTE_LOG(ERR, APP, "pfc %u: port %"PRIu8" is used already\n", nb_pfc, pconf->tx_port); return -1; } app_used_tx_port_mask |= mask; app_used_port_mask |= mask; mask = 1lu << pconf->rx_core; app_used_core_mask |= mask; mask = 1lu << pconf->wt_core; app_used_core_mask |= mask; mask = 1lu << pconf->tx_core; app_used_core_mask |= mask; nb_pfc++; return 0; } static int app_parse_burst_conf(const char *conf_str) { int ret; uint32_t vals[4]; ret = app_parse_opt_vals(conf_str, ',', 4, vals); if (ret != 4) return ret; burst_conf.rx_burst = (uint16_t)vals[0]; burst_conf.ring_burst = (uint16_t)vals[1]; burst_conf.qos_dequeue = (uint16_t)vals[2]; burst_conf.tx_burst = (uint16_t)vals[3]; return 0; } /* * Parses the argument given in the command line of the application, * calculates mask for used cores and initializes EAL with calculated core mask */ int app_parse_args(int argc, char **argv) { int opt, ret; int option_index; const char *optname; char *prgname = argv[0]; uint32_t i, nb_lcores; static struct option lgopts[] = { { "pfc", 1, 0, 0 }, { "mst", 1, 0, 0 }, { "rsz", 1, 0, 0 }, { "bsz", 1, 0, 0 }, { "msz", 1, 0, 0 }, { "rth", 1, 0, 0 }, { "tth", 1, 0, 0 }, { "cfg", 1, 0, 0 }, { NULL, 0, 0, 0 } }; /* initialize EAL first */ ret = rte_eal_init(argc, argv); if (ret < 0) return -1; argc -= ret; argv += ret; /* set en_US locale to print big numbers with ',' */ setlocale(LC_NUMERIC, "en_US.utf-8"); while ((opt = getopt_long(argc, argv, "i", lgopts, &option_index)) != EOF) { switch (opt) { case 'i': printf("Interactive-mode selected\n"); interactive = 1; break; /* long options */ case 0: optname = lgopts[option_index].name; if (str_is(optname, "pfc")) { ret = app_parse_flow_conf(optarg); if (ret) { RTE_LOG(ERR, APP, "Invalid pipe configuration %s\n", optarg); return -1; } break; } if (str_is(optname, "mst")) { app_master_core = (uint32_t)atoi(optarg); break; } if (str_is(optname, "rsz")) { ret = app_parse_ring_conf(optarg); if (ret) { RTE_LOG(ERR, APP, "Invalid ring configuration %s\n", optarg); return -1; } break; } if (str_is(optname, "bsz")) { ret = app_parse_burst_conf(optarg); if (ret) { RTE_LOG(ERR, APP, "Invalid burst configuration %s\n", optarg); return -1; } break; } if (str_is(optname, "msz")) { mp_size = atoi(optarg); if (mp_size <= 0) { RTE_LOG(ERR, APP, "Invalid mempool size %s\n", optarg); return -1; } break; } if (str_is(optname, "rth")) { ret = app_parse_rth_conf(optarg); if (ret) { RTE_LOG(ERR, APP, "Invalid RX threshold configuration %s\n", optarg); return -1; } break; } if (str_is(optname, "tth")) { ret = app_parse_tth_conf(optarg); if (ret) { RTE_LOG(ERR, APP, "Invalid TX threshold configuration %s\n", optarg); return -1; } break; } if (str_is(optname, "cfg")) { cfg_profile = optarg; break; } break; default: app_usage(prgname); return -1; } } /* check master core index validity */ for(i = 0; i <= app_master_core; i++) { if (app_used_core_mask & (1u << app_master_core)) { RTE_LOG(ERR, APP, "Master core index is not configured properly\n"); app_usage(prgname); return -1; } } app_used_core_mask |= 1u << app_master_core; if ((app_used_core_mask != app_eal_core_mask()) || (app_master_core != rte_get_master_lcore())) { RTE_LOG(ERR, APP, "EAL core mask not configured properly, must be %" PRIx64 " instead of %" PRIx64 "\n" , app_used_core_mask, app_eal_core_mask()); return -1; } if (nb_pfc == 0) { RTE_LOG(ERR, APP, "Packet flow not configured!\n"); app_usage(prgname); return -1; } /* sanity check for cores assignment */ nb_lcores = app_cpu_core_count(); for(i = 0; i < nb_pfc; i++) { if (qos_conf[i].rx_core >= nb_lcores) { RTE_LOG(ERR, APP, "pfc %u: invalid RX lcore index %u\n", i + 1, qos_conf[i].rx_core); return -1; } if (qos_conf[i].wt_core >= nb_lcores) { RTE_LOG(ERR, APP, "pfc %u: invalid WT lcore index %u\n", i + 1, qos_conf[i].wt_core); return -1; } uint32_t rx_sock = rte_lcore_to_socket_id(qos_conf[i].rx_core); uint32_t wt_sock = rte_lcore_to_socket_id(qos_conf[i].wt_core); if (rx_sock != wt_sock) { RTE_LOG(ERR, APP, "pfc %u: RX and WT must be on the same socket\n", i + 1); return -1; } app_numa_mask |= 1 << rte_lcore_to_socket_id(qos_conf[i].rx_core); } return 0; } ================================================ FILE: examples/qos_sched/cfg_file.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "cfg_file.h" #include "main.h" /** when we resize a file structure, how many extra entries * for new sections do we add in */ #define CFG_ALLOC_SECTION_BATCH 8 /** when we resize a section structure, how many extra entries * for new entries do we add in */ #define CFG_ALLOC_ENTRY_BATCH 16 static unsigned _strip(char *str, unsigned len) { int newlen = len; if (len == 0) return 0; if (isspace(str[len-1])) { /* strip trailing whitespace */ while (newlen > 0 && isspace(str[newlen - 1])) str[--newlen] = '\0'; } if (isspace(str[0])) { /* strip leading whitespace */ int i,start = 1; while (isspace(str[start]) && start < newlen) start++ ; /* do nothing */ newlen -= start; for (i = 0; i < newlen; i++) str[i] = str[i+start]; str[i] = '\0'; } return newlen; } struct cfg_file * cfg_load(const char *filename, int flags) { int allocated_sections = CFG_ALLOC_SECTION_BATCH; int allocated_entries = 0; int curr_section = -1; int curr_entry = -1; char buffer[256]; int lineno = 0; struct cfg_file *cfg = NULL; FILE *f = fopen(filename, "r"); if (f == NULL) return NULL; cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (cfg == NULL) goto error2; memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections); while (fgets(buffer, sizeof(buffer), f) != NULL) { char *pos = NULL; size_t len = strnlen(buffer, sizeof(buffer)); lineno++; if (len >=sizeof(buffer) - 1 && buffer[len-1] != '\n'){ printf("Error line %d - no \\n found on string. " "Check if line too long\n", lineno); goto error1; } if ((pos = memchr(buffer, ';', sizeof(buffer))) != NULL) { *pos = '\0'; len = pos - buffer; } len = _strip(buffer, len); if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) continue; if (buffer[0] == '[') { /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { printf("Error line %d - no terminating '[' found\n", lineno); goto error1; } *end = '\0'; _strip(&buffer[1], end - &buffer[1]); /* close off old section and add start new one */ if (curr_section >= 0) cfg->sections[curr_section]->num_entries = curr_entry + 1; curr_section++; /* resize overall struct if we don't have room for more sections */ if (curr_section == allocated_sections) { allocated_sections += CFG_ALLOC_SECTION_BATCH; struct cfg_file *n_cfg = realloc(cfg, sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (n_cfg == NULL) { printf("Error - no more memory\n"); goto error1; } cfg = n_cfg; } /* allocate space for new section */ allocated_entries = CFG_ALLOC_ENTRY_BATCH; curr_entry = -1; cfg->sections[curr_section] = malloc(sizeof(*cfg->sections[0]) + sizeof(cfg->sections[0]->entries[0]) * allocated_entries); if (cfg->sections[curr_section] == NULL) { printf("Error - no more memory\n"); goto error1; } snprintf(cfg->sections[curr_section]->name, sizeof(cfg->sections[0]->name), "%s", &buffer[1]); } else { /* value line */ if (curr_section < 0) { printf("Error line %d - value outside of section\n", lineno); goto error1; } struct cfg_section *sect = cfg->sections[curr_section]; char *split[2]; if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=') != 2) { printf("Error at line %d - cannot split string\n", lineno); goto error1; } curr_entry++; if (curr_entry == allocated_entries) { allocated_entries += CFG_ALLOC_ENTRY_BATCH; struct cfg_section *n_sect = realloc(sect, sizeof(*sect) + sizeof(sect->entries[0]) * allocated_entries); if (n_sect == NULL) { printf("Error - no more memory\n"); goto error1; } sect = cfg->sections[curr_section] = n_sect; } sect->entries[curr_entry] = malloc(sizeof(*sect->entries[0])); if (sect->entries[curr_entry] == NULL) { printf("Error - no more memory\n"); goto error1; } struct cfg_entry *entry = sect->entries[curr_entry]; snprintf(entry->name, sizeof(entry->name), "%s", split[0]); snprintf(entry->value, sizeof(entry->value), "%s", split[1]); _strip(entry->name, strnlen(entry->name, sizeof(entry->name))); _strip(entry->value, strnlen(entry->value, sizeof(entry->value))); } } fclose(f); cfg->flags = flags; cfg->sections[curr_section]->num_entries = curr_entry + 1; cfg->num_sections = curr_section + 1; return cfg; error1: cfg_close(cfg); error2: fclose(f); return NULL; } int cfg_close(struct cfg_file *cfg) { int i, j; if (cfg == NULL) return -1; for(i = 0; i < cfg->num_sections; i++) { if (cfg->sections[i] != NULL) { if (cfg->sections[i]->num_entries) { for(j = 0; j < cfg->sections[i]->num_entries; j++) { if (cfg->sections[i]->entries[j] != NULL) free(cfg->sections[i]->entries[j]); } } free(cfg->sections[i]); } } free(cfg); return 0; } int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; int j; if (!cfg || !port_params) return -1; entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port"); if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); if (entry) port_params->n_pipes_per_subport = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); if (entry) { char *next; for(j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } #ifdef RTE_SCHED_RED for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { char str[32]; /* Parse WRED min thresholds */ snprintf(str, sizeof(str), "tc %d wred min", j); entry = rte_cfgfile_get_entry(cfg, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].min_th = (uint16_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED max thresholds */ snprintf(str, sizeof(str), "tc %d wred max", j); entry = rte_cfgfile_get_entry(cfg, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].max_th = (uint16_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED inverse mark probabilities */ snprintf(str, sizeof(str), "tc %d wred inv prob", j); entry = rte_cfgfile_get_entry(cfg, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].maxp_inv = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } /* Parse WRED EWMA filter weights */ snprintf(str, sizeof(str), "tc %d wred weight", j); entry = rte_cfgfile_get_entry(cfg, "red", str); if (entry) { char *next; int k; /* for each packet colour (green, yellow, red) */ for (k = 0; k < e_RTE_METER_COLORS; k++) { port_params->red_params[j][k].wq_log2 = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } } #endif /* RTE_SCHED_RED */ return 0; } int cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params) { int i, j; char *next; const char *entry; int profiles; if (!cfg || !pipe_params) return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); port_params.n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate"); if (entry) pipe_params[j].tb_rate = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size"); if (entry) pipe_params[j].tb_size = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period"); if (entry) pipe_params[j].tc_period = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate"); if (entry) pipe_params[j].tc_rate[0] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate"); if (entry) pipe_params[j].tc_rate[1] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate"); if (entry) pipe_params[j].tc_rate[2] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate"); if (entry) pipe_params[j].tc_rate[3] = (uint32_t)atoi(entry); #ifdef RTE_SCHED_SUBPORT_TC_OV entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 oversubscription weight"); if (entry) pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry); #endif entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 wrr weights"); if (entry) { for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 wrr weights"); if (entry) { for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 wrr weights"); if (entry) { for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 wrr weights"); if (entry) { for(i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] = (uint8_t)strtol(entry, &next, 10); if (next == NULL) break; entry = next; } } } return 0; } int cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params) { const char *entry; int i, j, k; if (!cfg || !subport_params) return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size"); if (entry) subport_params[i].tb_size = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period"); if (entry) subport_params[i].tc_period = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate"); if (entry) subport_params[i].tc_rate[0] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate"); if (entry) subport_params[i].tc_rate[1] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate"); if (entry) subport_params[i].tc_rate[2] = (uint32_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate"); if (entry) subport_params[i].tc_rate[3] = (uint32_t)atoi(entry); int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); struct rte_cfgfile_entry entries[n_entries]; rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries); for (j = 0; j < n_entries; j++) { if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) { int profile; char *tokens[2] = {NULL, NULL}; int n_tokens; int begin, end; profile = atoi(entries[j].value); n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")], strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-'); begin = atoi(tokens[0]); if (n_tokens == 2) end = atoi(tokens[1]); else end = begin; if (end >= MAX_SCHED_PIPES || begin > end) return -1; for (k = begin; k <= end; k++) { char profile_name[CFG_NAME_LEN]; snprintf(profile_name, sizeof(profile_name), "pipe profile %d", profile); if (rte_cfgfile_has_section(cfg, profile_name)) app_pipe_to_profile[i][k] = profile; else rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n", entries[j].value); } } } } } return 0; } ================================================ FILE: examples/qos_sched/cfg_file.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __CFG_FILE_H__ #define __CFG_FILE_H__ #include #include #define CFG_NAME_LEN 32 #define CFG_VALUE_LEN 64 struct cfg_entry { char name[CFG_NAME_LEN]; char value[CFG_VALUE_LEN]; }; struct cfg_section { char name[CFG_NAME_LEN]; int num_entries; struct cfg_entry *entries[0]; }; struct cfg_file { int flags; int num_sections; struct cfg_section *sections[0]; }; int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port); int cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe); int cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport); /* reads a config file from disk and returns a handle to the config * 'flags' is reserved for future use and must be 0 */ struct cfg_file *cfg_load(const char *filename, int flags); /* cleans up memory allocated by cfg_load() */ int cfg_close(struct cfg_file *cfg); #endif ================================================ FILE: examples/qos_sched/cmdline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "main.h" /* *** Help command with introduction. *** */ struct cmd_help_result { cmdline_fixed_string_t help; }; static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf( cl, "\n" "The following commands are currently available:\n\n" "Control:\n" " quit : Quit the application.\n" "\nStatistics:\n" " stats app : Show app statistics.\n" " stats port X subport Y : Show stats of a specific subport.\n" " stats port X subport Y pipe Z : Show stats of a specific pipe.\n" "\nAverage queue size:\n" " qavg port X subport Y : Show average queue size per subport.\n" " qavg port X subport Y tc Z : Show average queue size per subport and TC.\n" " qavg port X subport Y pipe Z : Show average queue size per pipe.\n" " qavg port X subport Y pipe Z tc A : Show average queue size per pipe and TC.\n" " qavg port X subport Y pipe Z tc A q B : Show average queue size of a specific queue.\n" " qavg [n|period] X : Set number of times and peiod (us).\n\n" ); } cmdline_parse_token_string_t cmd_help_help = TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); cmdline_parse_inst_t cmd_help = { .f = cmd_help_parsed, .data = NULL, .help_str = "show help", .tokens = { (void *)&cmd_help_help, NULL, }, }; /* *** QUIT *** */ struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, .data = NULL, .help_str = "exit application", .tokens = { (void *)&cmd_quit_quit, NULL, }, }; /* *** SET QAVG PARAMETERS *** */ struct cmd_setqavg_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t param_string; uint32_t number; }; static void cmd_setqavg_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_setqavg_result *res = parsed_result; if (!strcmp(res->param_string, "period")) qavg_period = res->number; else if (!strcmp(res->param_string, "n")) qavg_ntimes = res->number; else printf("\nUnknown parameter.\n\n"); } cmdline_parse_token_string_t cmd_setqavg_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_setqavg_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_setqavg_param_string = TOKEN_STRING_INITIALIZER(struct cmd_setqavg_result, param_string, "period#n"); cmdline_parse_token_num_t cmd_setqavg_number = TOKEN_NUM_INITIALIZER(struct cmd_setqavg_result, number, UINT32); cmdline_parse_inst_t cmd_setqavg = { .f = cmd_setqavg_parsed, .data = NULL, .help_str = "Show subport stats.", .tokens = { (void *)&cmd_setqavg_qavg_string, (void *)&cmd_setqavg_param_string, (void *)&cmd_setqavg_number, NULL, }, }; /* *** SHOW APP STATS *** */ struct cmd_appstats_result { cmdline_fixed_string_t stats_string; cmdline_fixed_string_t app_string; }; static void cmd_appstats_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { app_stat(); } cmdline_parse_token_string_t cmd_appstats_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_appstats_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_appstats_app_string = TOKEN_STRING_INITIALIZER(struct cmd_appstats_result, app_string, "app"); cmdline_parse_inst_t cmd_appstats = { .f = cmd_appstats_parsed, .data = NULL, .help_str = "Show app stats.", .tokens = { (void *)&cmd_appstats_stats_string, (void *)&cmd_appstats_app_string, NULL, }, }; /* *** SHOW SUBPORT STATS *** */ struct cmd_subportstats_result { cmdline_fixed_string_t stats_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; }; static void cmd_subportstats_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_subportstats_result *res = parsed_result; if (subport_stat(res->port_number, res->subport_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_subportstats_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_subportstats_port_string = TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, port_string, "port"); cmdline_parse_token_string_t cmd_subportstats_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_subportstats_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_subportstats_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_subportstats_result, subport_number, UINT32); cmdline_parse_token_num_t cmd_subportstats_port_number = TOKEN_NUM_INITIALIZER(struct cmd_subportstats_result, port_number, UINT8); cmdline_parse_inst_t cmd_subportstats = { .f = cmd_subportstats_parsed, .data = NULL, .help_str = "Show subport stats.", .tokens = { (void *)&cmd_subportstats_stats_string, (void *)&cmd_subportstats_port_string, (void *)&cmd_subportstats_port_number, (void *)&cmd_subportstats_subport_string, (void *)&cmd_subportstats_subport_number, NULL, }, }; /* *** SHOW PIPE STATS *** */ struct cmd_pipestats_result { cmdline_fixed_string_t stats_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; cmdline_fixed_string_t pipe_string; uint32_t pipe_number; }; static void cmd_pipestats_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_pipestats_result *res = parsed_result; if (pipe_stat(res->port_number, res->subport_number, res->pipe_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_pipestats_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, stats_string, "stats"); cmdline_parse_token_string_t cmd_pipestats_port_string = TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, port_string, "port"); cmdline_parse_token_num_t cmd_pipestats_port_number = TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, port_number, UINT8); cmdline_parse_token_string_t cmd_pipestats_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_pipestats_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, subport_number, UINT32); cmdline_parse_token_string_t cmd_pipestats_pipe_string = TOKEN_STRING_INITIALIZER(struct cmd_pipestats_result, pipe_string, "pipe"); cmdline_parse_token_num_t cmd_pipestats_pipe_number = TOKEN_NUM_INITIALIZER(struct cmd_pipestats_result, pipe_number, UINT32); cmdline_parse_inst_t cmd_pipestats = { .f = cmd_pipestats_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_pipestats_stats_string, (void *)&cmd_pipestats_port_string, (void *)&cmd_pipestats_port_number, (void *)&cmd_pipestats_subport_string, (void *)&cmd_pipestats_subport_number, (void *)&cmd_pipestats_pipe_string, (void *)&cmd_pipestats_pipe_number, NULL, }, }; /* *** SHOW AVERAGE QUEUE SIZE (QUEUE) *** */ struct cmd_avg_q_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; cmdline_fixed_string_t pipe_string; uint32_t pipe_number; cmdline_fixed_string_t tc_string; uint8_t tc_number; cmdline_fixed_string_t q_string; uint8_t q_number; }; static void cmd_avg_q_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_avg_q_result *res = parsed_result; if (qavg_q(res->port_number, res->subport_number, res->pipe_number, res->tc_number, res->q_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_avg_q_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_avg_q_port_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, port_string, "port"); cmdline_parse_token_num_t cmd_avg_q_port_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, port_number, UINT8); cmdline_parse_token_string_t cmd_avg_q_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_avg_q_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, subport_number, UINT32); cmdline_parse_token_string_t cmd_avg_q_pipe_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, pipe_string, "pipe"); cmdline_parse_token_num_t cmd_avg_q_pipe_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, pipe_number, UINT32); cmdline_parse_token_string_t cmd_avg_q_tc_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, tc_string, "tc"); cmdline_parse_token_num_t cmd_avg_q_tc_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, tc_number, UINT8); cmdline_parse_token_string_t cmd_avg_q_q_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_q_result, q_string, "q"); cmdline_parse_token_num_t cmd_avg_q_q_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_q_result, q_number, UINT8); cmdline_parse_inst_t cmd_avg_q = { .f = cmd_avg_q_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_avg_q_qavg_string, (void *)&cmd_avg_q_port_string, (void *)&cmd_avg_q_port_number, (void *)&cmd_avg_q_subport_string, (void *)&cmd_avg_q_subport_number, (void *)&cmd_avg_q_pipe_string, (void *)&cmd_avg_q_pipe_number, (void *)&cmd_avg_q_tc_string, (void *)&cmd_avg_q_tc_number, (void *)&cmd_avg_q_q_string, (void *)&cmd_avg_q_q_number, NULL, }, }; /* *** SHOW AVERAGE QUEUE SIZE (tc/pipe) *** */ struct cmd_avg_tcpipe_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; cmdline_fixed_string_t pipe_string; uint32_t pipe_number; cmdline_fixed_string_t tc_string; uint8_t tc_number; }; static void cmd_avg_tcpipe_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_avg_tcpipe_result *res = parsed_result; if (qavg_tcpipe(res->port_number, res->subport_number, res->pipe_number, res->tc_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_avg_tcpipe_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_avg_tcpipe_port_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, port_string, "port"); cmdline_parse_token_num_t cmd_avg_tcpipe_port_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, port_number, UINT8); cmdline_parse_token_string_t cmd_avg_tcpipe_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_avg_tcpipe_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, subport_number, UINT32); cmdline_parse_token_string_t cmd_avg_tcpipe_pipe_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, pipe_string, "pipe"); cmdline_parse_token_num_t cmd_avg_tcpipe_pipe_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, pipe_number, UINT32); cmdline_parse_token_string_t cmd_avg_tcpipe_tc_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcpipe_result, tc_string, "tc"); cmdline_parse_token_num_t cmd_avg_tcpipe_tc_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcpipe_result, tc_number, UINT8); cmdline_parse_inst_t cmd_avg_tcpipe = { .f = cmd_avg_tcpipe_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_avg_tcpipe_qavg_string, (void *)&cmd_avg_tcpipe_port_string, (void *)&cmd_avg_tcpipe_port_number, (void *)&cmd_avg_tcpipe_subport_string, (void *)&cmd_avg_tcpipe_subport_number, (void *)&cmd_avg_tcpipe_pipe_string, (void *)&cmd_avg_tcpipe_pipe_number, (void *)&cmd_avg_tcpipe_tc_string, (void *)&cmd_avg_tcpipe_tc_number, NULL, }, }; /* *** SHOW AVERAGE QUEUE SIZE (pipe) *** */ struct cmd_avg_pipe_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; cmdline_fixed_string_t pipe_string; uint32_t pipe_number; }; static void cmd_avg_pipe_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_avg_pipe_result *res = parsed_result; if (qavg_pipe(res->port_number, res->subport_number, res->pipe_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_avg_pipe_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_avg_pipe_port_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, port_string, "port"); cmdline_parse_token_num_t cmd_avg_pipe_port_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, port_number, UINT8); cmdline_parse_token_string_t cmd_avg_pipe_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_avg_pipe_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, subport_number, UINT32); cmdline_parse_token_string_t cmd_avg_pipe_pipe_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_pipe_result, pipe_string, "pipe"); cmdline_parse_token_num_t cmd_avg_pipe_pipe_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_pipe_result, pipe_number, UINT32); cmdline_parse_inst_t cmd_avg_pipe = { .f = cmd_avg_pipe_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_avg_pipe_qavg_string, (void *)&cmd_avg_pipe_port_string, (void *)&cmd_avg_pipe_port_number, (void *)&cmd_avg_pipe_subport_string, (void *)&cmd_avg_pipe_subport_number, (void *)&cmd_avg_pipe_pipe_string, (void *)&cmd_avg_pipe_pipe_number, NULL, }, }; /* *** SHOW AVERAGE QUEUE SIZE (tc/subport) *** */ struct cmd_avg_tcsubport_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; cmdline_fixed_string_t tc_string; uint8_t tc_number; }; static void cmd_avg_tcsubport_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_avg_tcsubport_result *res = parsed_result; if (qavg_tcsubport(res->port_number, res->subport_number, res->tc_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_avg_tcsubport_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_avg_tcsubport_port_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, port_string, "port"); cmdline_parse_token_num_t cmd_avg_tcsubport_port_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, port_number, UINT8); cmdline_parse_token_string_t cmd_avg_tcsubport_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_avg_tcsubport_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, subport_number, UINT32); cmdline_parse_token_string_t cmd_avg_tcsubport_tc_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_tcsubport_result, tc_string, "tc"); cmdline_parse_token_num_t cmd_avg_tcsubport_tc_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_tcsubport_result, tc_number, UINT8); cmdline_parse_inst_t cmd_avg_tcsubport = { .f = cmd_avg_tcsubport_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_avg_tcsubport_qavg_string, (void *)&cmd_avg_tcsubport_port_string, (void *)&cmd_avg_tcsubport_port_number, (void *)&cmd_avg_tcsubport_subport_string, (void *)&cmd_avg_tcsubport_subport_number, (void *)&cmd_avg_tcsubport_tc_string, (void *)&cmd_avg_tcsubport_tc_number, NULL, }, }; /* *** SHOW AVERAGE QUEUE SIZE (subport) *** */ struct cmd_avg_subport_result { cmdline_fixed_string_t qavg_string; cmdline_fixed_string_t port_string; uint8_t port_number; cmdline_fixed_string_t subport_string; uint32_t subport_number; }; static void cmd_avg_subport_parsed(void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_avg_subport_result *res = parsed_result; if (qavg_subport(res->port_number, res->subport_number) < 0) printf ("\nStats not available for these parameters. Check that both the port and subport are correct.\n\n"); } cmdline_parse_token_string_t cmd_avg_subport_qavg_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, qavg_string, "qavg"); cmdline_parse_token_string_t cmd_avg_subport_port_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, port_string, "port"); cmdline_parse_token_num_t cmd_avg_subport_port_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_subport_result, port_number, UINT8); cmdline_parse_token_string_t cmd_avg_subport_subport_string = TOKEN_STRING_INITIALIZER(struct cmd_avg_subport_result, subport_string, "subport"); cmdline_parse_token_num_t cmd_avg_subport_subport_number = TOKEN_NUM_INITIALIZER(struct cmd_avg_subport_result, subport_number, UINT32); cmdline_parse_inst_t cmd_avg_subport = { .f = cmd_avg_subport_parsed, .data = NULL, .help_str = "Show pipe stats.", .tokens = { (void *)&cmd_avg_subport_qavg_string, (void *)&cmd_avg_subport_port_string, (void *)&cmd_avg_subport_port_number, (void *)&cmd_avg_subport_subport_string, (void *)&cmd_avg_subport_subport_number, NULL, }, }; /* ******************************************************************************** */ /* list of instructions */ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help, (cmdline_parse_inst_t *)&cmd_setqavg, (cmdline_parse_inst_t *)&cmd_appstats, (cmdline_parse_inst_t *)&cmd_subportstats, (cmdline_parse_inst_t *)&cmd_pipestats, (cmdline_parse_inst_t *)&cmd_avg_q, (cmdline_parse_inst_t *)&cmd_avg_tcpipe, (cmdline_parse_inst_t *)&cmd_avg_pipe, (cmdline_parse_inst_t *)&cmd_avg_tcsubport, (cmdline_parse_inst_t *)&cmd_avg_subport, (cmdline_parse_inst_t *)&cmd_quit, NULL, }; /* prompt function, called from main on MASTER lcore */ void prompt(void) { struct cmdline *cl; cl = cmdline_stdin_new(main_ctx, "qos_sched> "); if (cl == NULL) { return; } cmdline_interact(cl); cmdline_stdin_exit(cl); } ================================================ FILE: examples/qos_sched/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "cfg_file.h" uint32_t app_numa_mask = 0; static uint32_t app_inited_port_mask = 0; int app_pipe_to_profile[MAX_SCHED_SUBPORTS][MAX_SCHED_PIPES]; #define MAX_NAME_LEN 32 struct ring_conf ring_conf = { .rx_size = APP_RX_DESC_DEFAULT, .ring_size = APP_RING_SIZE, .tx_size = APP_TX_DESC_DEFAULT, }; struct burst_conf burst_conf = { .rx_burst = MAX_PKT_RX_BURST, .ring_burst = PKT_ENQUEUE, .qos_dequeue = PKT_DEQUEUE, .tx_burst = MAX_PKT_TX_BURST, }; struct ring_thresh rx_thresh = { .pthresh = RX_PTHRESH, .hthresh = RX_HTHRESH, .wthresh = RX_WTHRESH, }; struct ring_thresh tx_thresh = { .pthresh = TX_PTHRESH, .hthresh = TX_HTHRESH, .wthresh = TX_WTHRESH, }; uint32_t nb_pfc; const char *cfg_profile = NULL; int mp_size = NB_MBUF; struct flow_conf qos_conf[MAX_DATA_STREAMS]; static const struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_DCB_NONE, }, }; static int app_init_port(uint8_t portid, struct rte_mempool *mp) { int ret; struct rte_eth_link link; struct rte_eth_rxconf rx_conf; struct rte_eth_txconf tx_conf; /* check if port already initialized (multistream configuration) */ if (app_inited_port_mask & (1u << portid)) return 0; rx_conf.rx_thresh.pthresh = rx_thresh.pthresh; rx_conf.rx_thresh.hthresh = rx_thresh.hthresh; rx_conf.rx_thresh.wthresh = rx_thresh.wthresh; rx_conf.rx_free_thresh = 32; rx_conf.rx_drop_en = 0; tx_conf.tx_thresh.pthresh = tx_thresh.pthresh; tx_conf.tx_thresh.hthresh = tx_thresh.hthresh; tx_conf.tx_thresh.wthresh = tx_thresh.wthresh; tx_conf.tx_free_thresh = 0; tx_conf.tx_rs_thresh = 0; tx_conf.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS; /* init port */ RTE_LOG(INFO, APP, "Initializing port %"PRIu8"... ", portid); fflush(stdout); ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure device: " "err=%d, port=%"PRIu8"\n", ret, portid); /* init one RX queue */ fflush(stdout); ret = rte_eth_rx_queue_setup(portid, 0, (uint16_t)ring_conf.rx_size, rte_eth_dev_socket_id(portid), &rx_conf, mp); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: " "err=%d, port=%"PRIu8"\n", ret, portid); /* init one TX queue */ fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, (uint16_t)ring_conf.tx_size, rte_eth_dev_socket_id(portid), &tx_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " "port=%"PRIu8" queue=%d\n", ret, portid, 0); /* Start device */ ret = rte_eth_dev_start(portid); if (ret < 0) rte_exit(EXIT_FAILURE, "rte_pmd_port_start: " "err=%d, port=%"PRIu8"\n", ret, portid); printf("done: "); /* get link status */ rte_eth_link_get(portid, &link); if (link.link_status) { printf(" Link Up - speed %u Mbps - %s\n", (uint32_t) link.link_speed, (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? ("full-duplex") : ("half-duplex\n")); } else { printf(" Link Down\n"); } rte_eth_promiscuous_enable(portid); /* mark port as initialized */ app_inited_port_mask |= 1u << portid; return 0; } static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { { .tb_rate = 1250000000, .tb_size = 1000000, .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000}, .tc_period = 10, }, }; static struct rte_sched_pipe_params pipe_profiles[RTE_SCHED_PIPE_PROFILES_PER_PORT] = { { /* Profile #0 */ .tb_rate = 305175, .tb_size = 1000000, .tc_rate = {305175, 305175, 305175, 305175}, .tc_period = 40, #ifdef RTE_SCHED_SUBPORT_TC_OV .tc_ov_weight = 1, #endif .wrr_weights = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, }, }; struct rte_sched_port_params port_params = { .name = "port_scheduler_0", .socket = 0, /* computed */ .rate = 0, /* computed */ .mtu = 6 + 6 + 4 + 4 + 2 + 1500, .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 4096, .qsize = {64, 64, 64, 64}, .pipe_profiles = pipe_profiles, .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ [0][0] = {.min_th = 48, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [0][1] = {.min_th = 40, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [0][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, /* Traffic Class 1 - Colors Green / Yellow / Red */ [1][0] = {.min_th = 48, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [1][1] = {.min_th = 40, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [1][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, /* Traffic Class 2 - Colors Green / Yellow / Red */ [2][0] = {.min_th = 48, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [2][1] = {.min_th = 40, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [2][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, /* Traffic Class 3 - Colors Green / Yellow / Red */ [3][0] = {.min_th = 48, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [3][1] = {.min_th = 40, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, [3][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9} } #endif /* RTE_SCHED_RED */ }; static struct rte_sched_port * app_init_sched_port(uint32_t portid, uint32_t socketid) { static char port_name[32]; /* static as referenced from global port_params*/ struct rte_eth_link link; struct rte_sched_port *port = NULL; uint32_t pipe, subport; int err; rte_eth_link_get((uint8_t)portid, &link); port_params.socket = socketid; port_params.rate = (uint64_t) link.link_speed * 1000 * 1000 / 8; snprintf(port_name, sizeof(port_name), "port_%d", portid); port_params.name = port_name; port = rte_sched_port_config(&port_params); if (port == NULL){ rte_exit(EXIT_FAILURE, "Unable to config sched port\n"); } for (subport = 0; subport < port_params.n_subports_per_port; subport ++) { err = rte_sched_subport_config(port, subport, &subport_params[subport]); if (err) { rte_exit(EXIT_FAILURE, "Unable to config sched subport %u, err=%d\n", subport, err); } for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe ++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); if (err) { rte_exit(EXIT_FAILURE, "Unable to config sched pipe %u " "for profile %d, err=%d\n", pipe, app_pipe_to_profile[subport][pipe], err); } } } } return port; } static int app_load_cfg_profile(const char *profile) { if (profile == NULL) return 0; struct rte_cfgfile *file = rte_cfgfile_load(profile, 0); if (file == NULL) rte_exit(EXIT_FAILURE, "Cannot load configuration profile %s\n", profile); cfg_load_port(file, &port_params); cfg_load_subport(file, subport_params); cfg_load_pipe(file, pipe_profiles); rte_cfgfile_close(file); return 0; } int app_init(void) { uint32_t i; char ring_name[MAX_NAME_LEN]; char pool_name[MAX_NAME_LEN]; if (rte_eth_dev_count() == 0) rte_exit(EXIT_FAILURE, "No Ethernet port - bye\n"); /* load configuration profile */ if (app_load_cfg_profile(cfg_profile) != 0) rte_exit(EXIT_FAILURE, "Invalid configuration profile\n"); /* Initialize each active flow */ for(i = 0; i < nb_pfc; i++) { uint32_t socket = rte_lcore_to_socket_id(qos_conf[i].rx_core); struct rte_ring *ring; snprintf(ring_name, MAX_NAME_LEN, "ring-%u-%u", i, qos_conf[i].rx_core); ring = rte_ring_lookup(ring_name); if (ring == NULL) qos_conf[i].rx_ring = rte_ring_create(ring_name, ring_conf.ring_size, socket, RING_F_SP_ENQ | RING_F_SC_DEQ); else qos_conf[i].rx_ring = ring; snprintf(ring_name, MAX_NAME_LEN, "ring-%u-%u", i, qos_conf[i].tx_core); ring = rte_ring_lookup(ring_name); if (ring == NULL) qos_conf[i].tx_ring = rte_ring_create(ring_name, ring_conf.ring_size, socket, RING_F_SP_ENQ | RING_F_SC_DEQ); else qos_conf[i].tx_ring = ring; /* create the mbuf pools for each RX Port */ snprintf(pool_name, MAX_NAME_LEN, "mbuf_pool%u", i); qos_conf[i].mbuf_pool = rte_pktmbuf_pool_create(pool_name, mp_size, burst_conf.rx_burst * 4, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_eth_dev_socket_id(qos_conf[i].rx_port)); if (qos_conf[i].mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool for socket %u\n", i); app_init_port(qos_conf[i].rx_port, qos_conf[i].mbuf_pool); app_init_port(qos_conf[i].tx_port, qos_conf[i].mbuf_pool); qos_conf[i].sched_port = app_init_sched_port(qos_conf[i].tx_port, socket); } RTE_LOG(INFO, APP, "time stamp clock running at %" PRIu64 " Hz\n", rte_get_timer_hz()); RTE_LOG(INFO, APP, "Ring sizes: NIC RX = %u, Mempool = %d SW queue = %u," "NIC TX = %u\n", ring_conf.rx_size, mp_size, ring_conf.ring_size, ring_conf.tx_size); RTE_LOG(INFO, APP, "Burst sizes: RX read = %hu, RX write = %hu,\n" " Worker read/QoS enqueue = %hu,\n" " QoS dequeue = %hu, Worker write = %hu\n", burst_conf.rx_burst, burst_conf.ring_burst, burst_conf.ring_burst, burst_conf.qos_dequeue, burst_conf.tx_burst); RTE_LOG(INFO, APP, "NIC thresholds RX (p = %hhu, h = %hhu, w = %hhu)," "TX (p = %hhu, h = %hhu, w = %hhu)\n", rx_thresh.pthresh, rx_thresh.hthresh, rx_thresh.wthresh, tx_thresh.pthresh, tx_thresh.hthresh, tx_thresh.wthresh); return 0; } ================================================ FILE: examples/qos_sched/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #define APP_MODE_NONE 0 #define APP_RX_MODE 1 #define APP_WT_MODE 2 #define APP_TX_MODE 4 uint8_t interactive = APP_INTERACTIVE_DEFAULT; uint32_t qavg_period = APP_QAVG_PERIOD; uint32_t qavg_ntimes = APP_QAVG_NTIMES; /* main processing loop */ static int app_main_loop(__attribute__((unused))void *dummy) { uint32_t lcore_id; uint32_t i, mode; uint32_t rx_idx = 0; uint32_t wt_idx = 0; uint32_t tx_idx = 0; struct thread_conf *rx_confs[MAX_DATA_STREAMS]; struct thread_conf *wt_confs[MAX_DATA_STREAMS]; struct thread_conf *tx_confs[MAX_DATA_STREAMS]; memset(rx_confs, 0, sizeof(rx_confs)); memset(wt_confs, 0, sizeof(wt_confs)); memset(tx_confs, 0, sizeof(tx_confs)); mode = APP_MODE_NONE; lcore_id = rte_lcore_id(); for (i = 0; i < nb_pfc; i++) { struct flow_conf *flow = &qos_conf[i]; if (flow->rx_core == lcore_id) { flow->rx_thread.rx_port = flow->rx_port; flow->rx_thread.rx_ring = flow->rx_ring; flow->rx_thread.rx_queue = flow->rx_queue; rx_confs[rx_idx++] = &flow->rx_thread; mode |= APP_RX_MODE; } if (flow->tx_core == lcore_id) { flow->tx_thread.tx_port = flow->tx_port; flow->tx_thread.tx_ring = flow->tx_ring; flow->tx_thread.tx_queue = flow->tx_queue; tx_confs[tx_idx++] = &flow->tx_thread; mode |= APP_TX_MODE; } if (flow->wt_core == lcore_id) { flow->wt_thread.rx_ring = flow->rx_ring; flow->wt_thread.tx_ring = flow->tx_ring; flow->wt_thread.tx_port = flow->tx_port; flow->wt_thread.sched_port = flow->sched_port; wt_confs[wt_idx++] = &flow->wt_thread; mode |= APP_WT_MODE; } } if (mode == APP_MODE_NONE) { RTE_LOG(INFO, APP, "lcore %u has nothing to do\n", lcore_id); return -1; } if (mode == (APP_RX_MODE | APP_WT_MODE)) { RTE_LOG(INFO, APP, "lcore %u was configured for both RX and WT !!!\n", lcore_id); return -1; } RTE_LOG(INFO, APP, "entering main loop on lcore %u\n", lcore_id); /* initialize mbuf memory */ if (mode == APP_RX_MODE) { for (i = 0; i < rx_idx; i++) { RTE_LOG(INFO, APP, "flow %u lcoreid %u " "reading port %"PRIu8"\n", i, lcore_id, rx_confs[i]->rx_port); } app_rx_thread(rx_confs); } else if (mode == (APP_TX_MODE | APP_WT_MODE)) { for (i = 0; i < wt_idx; i++) { wt_confs[i]->m_table = rte_malloc("table_wt", sizeof(struct rte_mbuf *) * burst_conf.tx_burst, RTE_CACHE_LINE_SIZE); if (wt_confs[i]->m_table == NULL) rte_panic("flow %u unable to allocate memory buffer\n", i); RTE_LOG(INFO, APP, "flow %u lcoreid %u sched+write " "port %"PRIu8"\n", i, lcore_id, wt_confs[i]->tx_port); } app_mixed_thread(wt_confs); } else if (mode == APP_TX_MODE) { for (i = 0; i < tx_idx; i++) { tx_confs[i]->m_table = rte_malloc("table_tx", sizeof(struct rte_mbuf *) * burst_conf.tx_burst, RTE_CACHE_LINE_SIZE); if (tx_confs[i]->m_table == NULL) rte_panic("flow %u unable to allocate memory buffer\n", i); RTE_LOG(INFO, APP, "flow %u lcoreid %u " "writing port %"PRIu8"\n", i, lcore_id, tx_confs[i]->tx_port); } app_tx_thread(tx_confs); } else if (mode == APP_WT_MODE){ for (i = 0; i < wt_idx; i++) { RTE_LOG(INFO, APP, "flow %u lcoreid %u scheduling \n", i, lcore_id); } app_worker_thread(wt_confs); } return 0; } void app_stat(void) { uint32_t i; struct rte_eth_stats stats; static struct rte_eth_stats rx_stats[MAX_DATA_STREAMS]; static struct rte_eth_stats tx_stats[MAX_DATA_STREAMS]; /* print statistics */ for(i = 0; i < nb_pfc; i++) { struct flow_conf *flow = &qos_conf[i]; rte_eth_stats_get(flow->rx_port, &stats); printf("\nRX port %"PRIu8": rx: %"PRIu64 " err: %"PRIu64 " no_mbuf: %"PRIu64 "\n", flow->rx_port, stats.ipackets - rx_stats[i].ipackets, stats.ierrors - rx_stats[i].ierrors, stats.rx_nombuf - rx_stats[i].rx_nombuf); memcpy(&rx_stats[i], &stats, sizeof(stats)); rte_eth_stats_get(flow->tx_port, &stats); printf("TX port %"PRIu8": tx: %" PRIu64 " err: %" PRIu64 "\n", flow->tx_port, stats.opackets - tx_stats[i].opackets, stats.oerrors - tx_stats[i].oerrors); memcpy(&tx_stats[i], &stats, sizeof(stats)); //printf("MP = %d\n", rte_mempool_count(conf->app_pktmbuf_pool)); #if APP_COLLECT_STAT printf("-------+------------+------------+\n"); printf(" | received | dropped |\n"); printf("-------+------------+------------+\n"); printf(" RX | %10" PRIu64 " | %10" PRIu64 " |\n", flow->rx_thread.stat.nb_rx, flow->rx_thread.stat.nb_drop); printf("QOS+TX | %10" PRIu64 " | %10" PRIu64 " | pps: %"PRIu64 " \n", flow->wt_thread.stat.nb_rx, flow->wt_thread.stat.nb_drop, flow->wt_thread.stat.nb_rx - flow->wt_thread.stat.nb_drop); printf("-------+------------+------------+\n"); memset(&flow->rx_thread.stat, 0, sizeof(struct thread_stat)); memset(&flow->wt_thread.stat, 0, sizeof(struct thread_stat)); #endif } } int main(int argc, char **argv) { int ret; ret = app_parse_args(argc, argv); if (ret < 0) return -1; ret = app_init(); if (ret < 0) return -1; /* launch per-lcore init on every lcore */ rte_eal_mp_remote_launch(app_main_loop, NULL, SKIP_MASTER); if (interactive) { sleep(1); prompt(); } else { /* print statistics every second */ while(1) { sleep(1); app_stat(); } } return 0; } ================================================ FILE: examples/qos_sched/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ #ifdef __cplusplus extern "C" { #endif #include #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 /* * Configurable number of RX/TX ring descriptors */ #define APP_INTERACTIVE_DEFAULT 0 #define APP_RX_DESC_DEFAULT 128 #define APP_TX_DESC_DEFAULT 256 #define APP_RING_SIZE (8*1024) #define NB_MBUF (2*1024*1024) #define MAX_PKT_RX_BURST 64 #define PKT_ENQUEUE 64 #define PKT_DEQUEUE 32 #define MAX_PKT_TX_BURST 64 #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ #define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ #define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ #define BURST_TX_DRAIN_US 100 #define MAX_DATA_STREAMS (RTE_MAX_LCORE/2) #define MAX_SCHED_SUBPORTS 8 #define MAX_SCHED_PIPES 4096 #ifndef APP_COLLECT_STAT #define APP_COLLECT_STAT 1 #endif #if APP_COLLECT_STAT #define APP_STATS_ADD(stat,val) (stat) += (val) #else #define APP_STATS_ADD(stat,val) do {(void) (val);} while (0) #endif #define APP_QAVG_NTIMES 10 #define APP_QAVG_PERIOD 100 struct thread_stat { uint64_t nb_rx; uint64_t nb_drop; }; struct thread_conf { uint32_t counter; uint32_t n_mbufs; struct rte_mbuf **m_table; uint8_t rx_port; uint8_t tx_port; uint16_t rx_queue; uint16_t tx_queue; struct rte_ring *rx_ring; struct rte_ring *tx_ring; struct rte_sched_port *sched_port; #if APP_COLLECT_STAT struct thread_stat stat; #endif } __rte_cache_aligned; struct flow_conf { uint32_t rx_core; uint32_t wt_core; uint32_t tx_core; uint8_t rx_port; uint8_t tx_port; uint16_t rx_queue; uint16_t tx_queue; struct rte_ring *rx_ring; struct rte_ring *tx_ring; struct rte_sched_port *sched_port; struct rte_mempool *mbuf_pool; struct thread_conf rx_thread; struct thread_conf wt_thread; struct thread_conf tx_thread; }; struct ring_conf { uint32_t rx_size; uint32_t ring_size; uint32_t tx_size; }; struct burst_conf { uint16_t rx_burst; uint16_t ring_burst; uint16_t qos_dequeue; uint16_t tx_burst; }; struct ring_thresh { uint8_t pthresh; /**< Ring prefetch threshold. */ uint8_t hthresh; /**< Ring host threshold. */ uint8_t wthresh; /**< Ring writeback threshold. */ }; extern uint8_t interactive; extern uint32_t qavg_period; extern uint32_t qavg_ntimes; extern uint32_t nb_pfc; extern const char *cfg_profile; extern int mp_size; extern struct flow_conf qos_conf[]; extern int app_pipe_to_profile[MAX_SCHED_SUBPORTS][MAX_SCHED_PIPES]; extern struct ring_conf ring_conf; extern struct burst_conf burst_conf; extern struct ring_thresh rx_thresh; extern struct ring_thresh tx_thresh; extern struct rte_sched_port_params port_params; int app_parse_args(int argc, char **argv); int app_init(void); void prompt(void); void app_rx_thread(struct thread_conf **qconf); void app_tx_thread(struct thread_conf **qconf); void app_worker_thread(struct thread_conf **qconf); void app_mixed_thread(struct thread_conf **qconf); void app_stat(void); int subport_stat(uint8_t port_id, uint32_t subport_id); int pipe_stat(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id); int qavg_q(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, uint8_t q); int qavg_tcpipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc); int qavg_pipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id); int qavg_tcsubport(uint8_t port_id, uint32_t subport_id, uint8_t tc); int qavg_subport(uint8_t port_id, uint32_t subport_id); #ifdef __cplusplus } #endif #endif /* _MAIN_H_ */ ================================================ FILE: examples/qos_sched/profile.cfg ================================================ ; BSD LICENSE ; ; Copyright(c) 2010-2014 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; This file enables the following hierarchical scheduler configuration for each ; 10GbE output port: ; * Single subport (subport 0): ; - Subport rate set to 100% of port rate ; - Each of the 4 traffic classes has rate set to 100% of port rate ; * 4K pipes per subport 0 (pipes 0 .. 4095) with identical configuration: ; - Pipe rate set to 1/4K of port rate ; - Each of the 4 traffic classes has rate set to 100% of pipe rate ; - Within each traffic class, the byte-level WRR weights for the 4 queues ; are set to 1:1:1:1 ; ; For more details, please refer to chapter "Quality of Service (QoS) Framework" ; of Intel Data Plane Development Kit (Intel DPDK) Programmer's Guide. ; Port configuration [port] frame overhead = 24 number of subports per port = 1 number of pipes per subport = 4096 queue sizes = 64 64 64 64 ; Subport configuration [subport 0] tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes tc 0 rate = 1250000000 ; Bytes per second tc 1 rate = 1250000000 ; Bytes per second tc 2 rate = 1250000000 ; Bytes per second tc 3 rate = 1250000000 ; Bytes per second tc period = 10 ; Milliseconds pipe 0-4095 = 0 ; These pipes are configured with pipe profile 0 ; Pipe configuration [pipe profile 0] tb rate = 305175 ; Bytes per second tb size = 1000000 ; Bytes tc 0 rate = 305175 ; Bytes per second tc 1 rate = 305175 ; Bytes per second tc 2 rate = 305175 ; Bytes per second tc 3 rate = 305175 ; Bytes per second tc period = 40 ; Milliseconds tc 3 oversubscription weight = 1 tc 0 wrr weights = 1 1 1 1 tc 1 wrr weights = 1 1 1 1 tc 2 wrr weights = 1 1 1 1 tc 3 wrr weights = 1 1 1 1 ; RED params per traffic class and color (Green / Yellow / Red) [red] tc 0 wred min = 48 40 32 tc 0 wred max = 64 64 64 tc 0 wred inv prob = 10 10 10 tc 0 wred weight = 9 9 9 tc 1 wred min = 48 40 32 tc 1 wred max = 64 64 64 tc 1 wred inv prob = 10 10 10 tc 1 wred weight = 9 9 9 tc 2 wred min = 48 40 32 tc 2 wred max = 64 64 64 tc 2 wred inv prob = 10 10 10 tc 2 wred weight = 9 9 9 tc 3 wred min = 48 40 32 tc 3 wred max = 64 64 64 tc 3 wred inv prob = 10 10 10 tc 3 wred weight = 9 9 9 ================================================ FILE: examples/qos_sched/profile_ov.cfg ================================================ ; BSD LICENSE ; ; Copyright(c) 2010-2014 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; Port configuration [port] frame overhead = 24 number of subports per port = 1 number of pipes per subport = 32 queue sizes = 64 64 64 64 ; Subport configuration [subport 0] tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes tc 0 rate = 8400000 ; Bytes per second tc 1 rate = 8400000 ; Bytes per second tc 2 rate = 8400000 ; Bytes per second tc 3 rate = 8400000 ; Bytes per second tc period = 10 ; Milliseconds pipe 0-31 = 0 ; These pipes are configured with pipe profile 0 ; Pipe configuration [pipe profile 0] tb rate = 16800000 ; Bytes per second tb size = 1000000 ; Bytes tc 0 rate = 16800000 ; Bytes per second tc 1 rate = 16800000 ; Bytes per second tc 2 rate = 16800000 ; Bytes per second tc 3 rate = 16800000 ; Bytes per second tc period = 28 ; Milliseconds tc 3 oversubscription weight = 1 tc 0 wrr weights = 1 1 1 1 tc 1 wrr weights = 1 1 1 1 tc 2 wrr weights = 1 1 1 1 tc 3 wrr weights = 1 1 1 1 ; RED params per traffic class and color (Green / Yellow / Red) [red] tc 0 wred min = 48 40 32 tc 0 wred max = 64 64 64 tc 0 wred inv prob = 10 10 10 tc 0 wred weight = 9 9 9 tc 1 wred min = 48 40 32 tc 1 wred max = 64 64 64 tc 1 wred inv prob = 10 10 10 tc 1 wred weight = 9 9 9 tc 2 wred min = 48 40 32 tc 2 wred max = 64 64 64 tc 2 wred inv prob = 10 10 10 tc 2 wred weight = 9 9 9 tc 3 wred min = 48 40 32 tc 3 wred max = 64 64 64 tc 3 wred inv prob = 10 10 10 tc 3 wred weight = 9 9 9 ================================================ FILE: examples/qos_sched/stats.c ================================================ /*- * * BSD LICENSE * * * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * * * * Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in * * the documentation and/or other materials provided with the * * distribution. * * * Neither the name of Intel Corporation nor the names of its * * contributors may be used to endorse or promote products derived * * from this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "main.h" int qavg_q(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, uint8_t q) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint32_t queue_id, count, i; uint32_t average; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS) return -1; port = qos_conf[i].sched_port; queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); queue_id = queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + q); average = 0; for (count = 0; count < qavg_ntimes; count++) { rte_sched_queue_read_stats(port, queue_id, &stats, &qlen); average += qlen; usleep(qavg_period); } average /= qavg_ntimes; printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); return 0; } int qavg_tcpipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint32_t queue_id, count, i; uint32_t average, part_average; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { rte_sched_queue_read_stats(port, queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + i), &stats, &qlen); part_average += qlen; } average += part_average / RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; usleep(qavg_period); } average /= qavg_ntimes; printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); return 0; } int qavg_pipe(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint32_t queue_id, count, i; uint32_t average, part_average; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { rte_sched_queue_read_stats(port, queue_id + i, &stats, &qlen); part_average += qlen; } average += part_average / (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); usleep(qavg_period); } average /= qavg_ntimes; printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); return 0; } int qavg_tcsubport(uint8_t port_id, uint32_t subport_id, uint8_t tc) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint32_t queue_id, count, i, j; uint32_t average, part_average; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; for (i = 0; i < port_params.n_pipes_per_subport; i++) { queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + i); for (j = 0; j < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { rte_sched_queue_read_stats(port, queue_id + (tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + j), &stats, &qlen); part_average += qlen; } } average += part_average / (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); usleep(qavg_period); } average /= qavg_ntimes; printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); return 0; } int qavg_subport(uint8_t port_id, uint32_t subport_id) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint32_t queue_id, count, i, j; uint32_t average, part_average; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port) return -1; port = qos_conf[i].sched_port; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; for (i = 0; i < port_params.n_pipes_per_subport; i++) { queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + i); for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { rte_sched_queue_read_stats(port, queue_id + j, &stats, &qlen); part_average += qlen; } } average += part_average / (port_params.n_pipes_per_subport * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS); usleep(qavg_period); } average /= qavg_ntimes; printf("\nAverage queue size: %" PRIu32 " bytes.\n\n", average); return 0; } int subport_stat(uint8_t port_id, uint32_t subport_id) { struct rte_sched_subport_stats stats; struct rte_sched_port *port; uint32_t tc_ov[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t i; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port) return -1; port = qos_conf[i].sched_port; memset (tc_ov, 0, sizeof(tc_ov)); rte_sched_subport_read_stats(port, subport_id, &stats, tc_ov); printf("\n"); printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); printf("| TC | Pkts OK |Pkts Dropped | Bytes OK |Bytes Dropped| OV Status |\n"); printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { printf("| %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " |\n", i, stats.n_pkts_tc[i], stats.n_pkts_tc_dropped[i], stats.n_bytes_tc[i], stats.n_bytes_tc_dropped[i], tc_ov[i]); printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); } printf("\n"); return 0; } int pipe_stat(uint8_t port_id, uint32_t subport_id, uint32_t pipe_id) { struct rte_sched_queue_stats stats; struct rte_sched_port *port; uint16_t qlen; uint8_t i, j; uint32_t queue_id; for (i = 0; i < nb_pfc; i++) { if (qos_conf[i].tx_port == port_id) break; } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || pipe_id >= port_params.n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; queue_id = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * (subport_id * port_params.n_pipes_per_subport + pipe_id); printf("\n"); printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); printf("| TC | Queue | Pkts OK |Pkts Dropped | Bytes OK |Bytes Dropped| Length |\n"); printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { for (j = 0; j < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; j++) { rte_sched_queue_read_stats(port, queue_id + (i * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + j), &stats, &qlen); printf("| %d | %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11i |\n", i, j, stats.n_pkts, stats.n_pkts_dropped, stats.n_bytes, stats.n_bytes_dropped, qlen); printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); } if (i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1) printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); } printf("\n"); return 0; } ================================================ FILE: examples/quota_watermark/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += qw DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += qwctl include $(RTE_SDK)/mk/rte.extsubdir.mk ================================================ FILE: examples/quota_watermark/include/conf.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CONF_H_ #define _CONF_H_ #define RING_SIZE 1024 #define MAX_PKT_QUOTA 64 #define RX_DESC_PER_QUEUE 128 #define TX_DESC_PER_QUEUE 512 #define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE #define MBUF_PER_POOL 8192 #define QUOTA_WATERMARK_MEMZONE_NAME "qw_global_vars" #endif /* _CONF_H_ */ ================================================ FILE: examples/quota_watermark/qw/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = qw # all source are stored in SRCS-y SRCS-y := args.c init.c main.c CFLAGS += -O3 -DQW_SOFTWARE_FC CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/quota_watermark/qw/args.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "args.h" unsigned int portmask = 0; static void usage(const char *prgname) { fprintf(stderr, "Usage: %s [EAL args] -- -p \n" "-p PORTMASK: hexadecimal bitmask of NIC ports to configure\n", prgname); } static unsigned long parse_portmask(const char *portmask_str) { return strtoul(portmask_str, NULL, 16); } static void check_core_count(void) { if (rte_lcore_count() < 3) rte_exit(EXIT_FAILURE, "At least 3 cores need to be passed in the coremask\n"); } static void check_portmask_value(unsigned int portmask) { unsigned int port_nb = 0; port_nb = __builtin_popcount(portmask); if (port_nb == 0) rte_exit(EXIT_FAILURE, "At least 2 ports need to be passed in the portmask\n"); if (port_nb % 2 != 0) rte_exit(EXIT_FAILURE, "An even number of ports is required in the portmask\n"); } int parse_qw_args(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "h:p:")) != -1) { switch (opt) { case 'h': usage(argv[0]); break; case 'p': portmask = parse_portmask(optarg); break; default: usage(argv[0]); } } check_core_count(); check_portmask_value(portmask); return 0; } ================================================ FILE: examples/quota_watermark/qw/args.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ARGS_H_ #define _ARGS_H_ extern unsigned int portmask; int parse_qw_args(int argc, char **argv); #endif /* _ARGS_H_ */ ================================================ FILE: examples/quota_watermark/qw/init.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "args.h" #include "init.h" #include "main.h" #include "../include/conf.h" static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_DCB_NONE, }, }; static struct rte_eth_fc_conf fc_conf = { .mode = RTE_FC_TX_PAUSE, .high_water = 80 * 510 / 100, .low_water = 60 * 510 / 100, .pause_time = 1337, .send_xon = 0, }; void configure_eth_port(uint8_t port_id) { int ret; rte_eth_dev_stop(port_id); ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot configure port %u (error %d)\n", (unsigned) port_id, ret); /* Initialize the port's RX queue */ ret = rte_eth_rx_queue_setup(port_id, 0, RX_DESC_PER_QUEUE, rte_eth_dev_socket_id(port_id), NULL, mbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Failed to setup RX queue on " "port %u (error %d)\n", (unsigned) port_id, ret); /* Initialize the port's TX queue */ ret = rte_eth_tx_queue_setup(port_id, 0, TX_DESC_PER_QUEUE, rte_eth_dev_socket_id(port_id), NULL); if (ret < 0) rte_exit(EXIT_FAILURE, "Failed to setup TX queue on " "port %u (error %d)\n", (unsigned) port_id, ret); /* Initialize the port's flow control */ ret = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Failed to setup hardware flow control on " "port %u (error %d)\n", (unsigned) port_id, ret); /* Start the port */ ret = rte_eth_dev_start(port_id); if (ret < 0) rte_exit(EXIT_FAILURE, "Failed to start port %u (error %d)\n", (unsigned) port_id, ret); /* Put it in promiscuous mode */ rte_eth_promiscuous_enable(port_id); } void init_dpdk(void) { if (rte_eth_dev_count() < 2) rte_exit(EXIT_FAILURE, "Not enough ethernet port available\n"); } void init_ring(int lcore_id, uint8_t port_id) { struct rte_ring *ring; char ring_name[RTE_RING_NAMESIZE]; snprintf(ring_name, RTE_RING_NAMESIZE, "core%d_port%d", lcore_id, port_id); ring = rte_ring_create(ring_name, RING_SIZE, rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); if (ring == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); rte_ring_set_water_mark(ring, 80 * RING_SIZE / 100); rings[lcore_id][port_id] = ring; } void pair_ports(void) { uint8_t i, j; /* Pair ports with their "closest neighbour" in the portmask */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) if (is_bit_set(i, portmask)) for (j = (uint8_t) (i + 1); j < RTE_MAX_ETHPORTS; j++) if (is_bit_set(j, portmask)) { port_pairs[i] = j; port_pairs[j] = i; i = j; break; } } void setup_shared_variables(void) { const struct rte_memzone *qw_memzone; qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, 2 * sizeof(int), rte_socket_id(), RTE_MEMZONE_2MB); if (qw_memzone == NULL) rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); quota = qw_memzone->addr; low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); } ================================================ FILE: examples/quota_watermark/qw/init.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _INIT_H_ #define _INIT_H_ void configure_eth_port(uint8_t port_id); void init_dpdk(void); void init_ring(int lcore_id, uint8_t port_id); void pair_ports(void); void setup_shared_variables(void); #endif /* _INIT_H_ */ ================================================ FILE: examples/quota_watermark/qw/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "args.h" #include "main.h" #include "init.h" #include "../include/conf.h" #ifdef QW_SOFTWARE_FC #define SEND_PAUSE_FRAME(port_id, duration) send_pause_frame(port_id, duration) #else #define SEND_PAUSE_FRAME(port_id, duration) do { } while(0) #endif #define ETHER_TYPE_FLOW_CONTROL 0x8808 struct ether_fc_frame { uint16_t opcode; uint16_t param; } __attribute__((__packed__)); int *quota; unsigned int *low_watermark; uint8_t port_pairs[RTE_MAX_ETHPORTS]; struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS]; struct rte_mempool *mbuf_pool; static void send_pause_frame(uint8_t port_id, uint16_t duration) { struct rte_mbuf *mbuf; struct ether_fc_frame *pause_frame; struct ether_hdr *hdr; struct ether_addr mac_addr; RTE_LOG(DEBUG, USER1, "Sending PAUSE frame (duration=%d) on port %d\n", duration, port_id); /* Get a mbuf from the pool */ mbuf = rte_pktmbuf_alloc(mbuf_pool); if (unlikely(mbuf == NULL)) return; /* Prepare a PAUSE frame */ hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *); pause_frame = (struct ether_fc_frame *) &hdr[1]; rte_eth_macaddr_get(port_id, &mac_addr); ether_addr_copy(&mac_addr, &hdr->s_addr); void *tmp = &hdr->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x010000C28001ULL; hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_FLOW_CONTROL); pause_frame->opcode = rte_cpu_to_be_16(0x0001); pause_frame->param = rte_cpu_to_be_16(duration); mbuf->pkt_len = 60; mbuf->data_len = 60; rte_eth_tx_burst(port_id, 0, &mbuf, 1); } /** * Get the previous enabled lcore ID * * @param lcore_id * The current lcore ID. * @return * The previous enabled lcore_id or -1 if not found. */ static unsigned int get_previous_lcore_id(unsigned int lcore_id) { int i; for (i = lcore_id - 1; i >= 0; i--) if (rte_lcore_is_enabled(i)) return i; return -1; } /** * Get the last enabled lcore ID * * @return * The last enabled lcore_id. */ static unsigned int get_last_lcore_id(void) { int i; for (i = RTE_MAX_LCORE; i >= 0; i--) if (rte_lcore_is_enabled(i)) return i; return 0; } static void receive_stage(__attribute__((unused)) void *args) { int i, ret; uint8_t port_id; uint16_t nb_rx_pkts; unsigned int lcore_id; struct rte_mbuf *pkts[MAX_PKT_QUOTA]; struct rte_ring *ring; enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY }; lcore_id = rte_lcore_id(); RTE_LOG(INFO, USER1, "%s() started on core %u\n", __func__, lcore_id); while (1) { /* Process each port round robin style */ for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; ring = rings[lcore_id][port_id]; if (ring_state[port_id] != RING_READY) { if (rte_ring_count(ring) > *low_watermark) continue; else ring_state[port_id] = RING_READY; } /* Enqueue received packets on the RX ring */ nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, (uint16_t) *quota); ret = rte_ring_enqueue_bulk(ring, (void *) pkts, nb_rx_pkts); if (ret == -EDQUOT) { ring_state[port_id] = RING_OVERLOADED; send_pause_frame(port_id, 1337); } else if (ret == -ENOBUFS) { /* Return mbufs to the pool, effectively dropping packets */ for (i = 0; i < nb_rx_pkts; i++) rte_pktmbuf_free(pkts[i]); } } } } static void pipeline_stage(__attribute__((unused)) void *args) { int i, ret; int nb_dq_pkts; uint8_t port_id; unsigned int lcore_id, previous_lcore_id; void *pkts[MAX_PKT_QUOTA]; struct rte_ring *rx, *tx; enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY }; lcore_id = rte_lcore_id(); previous_lcore_id = get_previous_lcore_id(lcore_id); RTE_LOG(INFO, USER1, "%s() started on core %u - processing packets from core %u\n", __func__, lcore_id, previous_lcore_id); while (1) { for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; tx = rings[lcore_id][port_id]; rx = rings[previous_lcore_id][port_id]; if (ring_state[port_id] != RING_READY) { if (rte_ring_count(tx) > *low_watermark) continue; else ring_state[port_id] = RING_READY; } /* Dequeue up to quota mbuf from rx */ nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, *quota); if (unlikely(nb_dq_pkts < 0)) continue; /* Enqueue them on tx */ ret = rte_ring_enqueue_bulk(tx, pkts, nb_dq_pkts); if (ret == -EDQUOT) ring_state[port_id] = RING_OVERLOADED; else if (ret == -ENOBUFS) { /* Return mbufs to the pool, effectively dropping packets */ for (i = 0; i < nb_dq_pkts; i++) rte_pktmbuf_free(pkts[i]); } } } } static void send_stage(__attribute__((unused)) void *args) { uint16_t nb_dq_pkts; uint8_t port_id; uint8_t dest_port_id; unsigned int lcore_id, previous_lcore_id; struct rte_ring *tx; struct rte_mbuf *tx_pkts[MAX_PKT_QUOTA]; lcore_id = rte_lcore_id(); previous_lcore_id = get_previous_lcore_id(lcore_id); RTE_LOG(INFO, USER1, "%s() started on core %u - processing packets from core %u\n", __func__, lcore_id, previous_lcore_id); while (1) { /* Process each ring round robin style */ for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { if (!is_bit_set(port_id, portmask)) continue; dest_port_id = port_pairs[port_id]; tx = rings[previous_lcore_id][port_id]; if (rte_ring_empty(tx)) continue; /* Dequeue packets from tx and send them */ nb_dq_pkts = (uint16_t) rte_ring_dequeue_burst(tx, (void *) tx_pkts, *quota); rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts); /* TODO: Check if nb_dq_pkts == nb_tx_pkts? */ } } } int main(int argc, char **argv) { int ret; unsigned int lcore_id, master_lcore_id, last_lcore_id; uint8_t port_id; rte_set_log_level(RTE_LOG_INFO); ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); argc -= ret; argv += ret; init_dpdk(); setup_shared_variables(); *quota = 32; *low_watermark = 60 * RING_SIZE / 100; last_lcore_id = get_last_lcore_id(); master_lcore_id = rte_get_master_lcore(); /* Parse the application's arguments */ ret = parse_qw_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid quota/watermark argument(s)\n"); /* Create a pool of mbuf to store packets */ mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, MBUF_DATA_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_panic("%s\n", rte_strerror(rte_errno)); for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) if (is_bit_set(port_id, portmask)) { configure_eth_port(port_id); init_ring(master_lcore_id, port_id); } pair_ports(); /* Start pipeline_connect() on all the available slave lcore but the last */ for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) { if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) { for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) if (is_bit_set(port_id, portmask)) init_ring(lcore_id, port_id); /* typecast is a workaround for GCC 4.3 bug */ rte_eal_remote_launch((int (*)(void *))pipeline_stage, NULL, lcore_id); } } /* Start send_stage() on the last slave core */ /* typecast is a workaround for GCC 4.3 bug */ rte_eal_remote_launch((int (*)(void *))send_stage, NULL, last_lcore_id); /* Start receive_stage() on the master core */ receive_stage(NULL); return 0; } ================================================ FILE: examples/quota_watermark/qw/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ #include "../include/conf.h" enum ring_state { RING_READY, RING_OVERLOADED, }; extern int *quota; extern unsigned int *low_watermark; extern uint8_t port_pairs[RTE_MAX_ETHPORTS]; extern struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS]; extern struct rte_mempool *mbuf_pool; static inline int is_bit_set(int i, unsigned int mask) { return ((1 << i) & mask); } #endif /* _MAIN_H_ */ ================================================ FILE: examples/quota_watermark/qwctl/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = qwctl # all source are stored in SRCS-y SRCS-y := commands.c qwctl.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/quota_watermark/qwctl/commands.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "qwctl.h" #include "../include/conf.h" /** * help command */ struct cmd_help_tokens { cmdline_fixed_string_t verb; }; cmdline_parse_token_string_t cmd_help_verb = TOKEN_STRING_INITIALIZER(struct cmd_help_tokens, verb, "help"); static void cmd_help_handler(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { cmdline_printf(cl, "Available commands:\n" "- help\n" "- set [ring_name|variable] \n" "- show [ring_name|variable]\n" "\n" "Available variables:\n" "- low_watermark\n" "- quota\n" "- ring names follow the core%%u_port%%u format\n"); } cmdline_parse_inst_t cmd_help = { .f = cmd_help_handler, .data = NULL, .help_str = "show help", .tokens = { (void *) &cmd_help_verb, NULL, }, }; /** * set command */ struct cmd_set_tokens { cmdline_fixed_string_t verb; cmdline_fixed_string_t variable; uint32_t value; }; cmdline_parse_token_string_t cmd_set_verb = TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, verb, "set"); cmdline_parse_token_string_t cmd_set_variable = TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, variable, NULL); cmdline_parse_token_num_t cmd_set_value = TOKEN_NUM_INITIALIZER(struct cmd_set_tokens, value, UINT32); static void cmd_set_handler(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_tokens *tokens = parsed_result; struct rte_ring *ring; if (!strcmp(tokens->variable, "quota")) { if (tokens->value > 0 && tokens->value <= MAX_PKT_QUOTA) *quota = tokens->value; else cmdline_printf(cl, "quota must be between 1 and %u\n", MAX_PKT_QUOTA); } else if (!strcmp(tokens->variable, "low_watermark")) { if (tokens->value <= 100) *low_watermark = tokens->value * RING_SIZE / 100; else cmdline_printf(cl, "low_watermark must be between 0%% and 100%%\n"); } else { ring = rte_ring_lookup(tokens->variable); if (ring == NULL) cmdline_printf(cl, "Cannot find ring \"%s\"\n", tokens->variable); else if (tokens->value >= *low_watermark * 100 / RING_SIZE && tokens->value <= 100) rte_ring_set_water_mark(ring, tokens->value * RING_SIZE / 100); else cmdline_printf(cl, "ring high watermark must be between %u%% " "and 100%%\n", *low_watermark * 100 / RING_SIZE); } } cmdline_parse_inst_t cmd_set = { .f = cmd_set_handler, .data = NULL, .help_str = "Set a variable value", .tokens = { (void *) &cmd_set_verb, (void *) &cmd_set_variable, (void *) &cmd_set_value, NULL, }, }; /** * show command */ struct cmd_show_tokens { cmdline_fixed_string_t verb; cmdline_fixed_string_t variable; }; cmdline_parse_token_string_t cmd_show_verb = TOKEN_STRING_INITIALIZER(struct cmd_show_tokens, verb, "show"); cmdline_parse_token_string_t cmd_show_variable = TOKEN_STRING_INITIALIZER(struct cmd_show_tokens, variable, NULL); static void cmd_show_handler(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_tokens *tokens = parsed_result; struct rte_ring *ring; if (!strcmp(tokens->variable, "quota")) cmdline_printf(cl, "Global quota: %d\n", *quota); else if (!strcmp(tokens->variable, "low_watermark")) cmdline_printf(cl, "Global low_watermark: %u\n", *low_watermark); else { ring = rte_ring_lookup(tokens->variable); if (ring == NULL) cmdline_printf(cl, "Cannot find ring \"%s\"\n", tokens->variable); else rte_ring_dump(stdout, ring); } } cmdline_parse_inst_t cmd_show = { .f = cmd_show_handler, .data = NULL, .help_str = "Show a variable value", .tokens = { (void *) &cmd_show_verb, (void *) &cmd_show_variable, NULL, }, }; cmdline_parse_ctx_t qwctl_ctx[] = { (cmdline_parse_inst_t *)&cmd_help, (cmdline_parse_inst_t *)&cmd_set, (cmdline_parse_inst_t *)&cmd_show, NULL, }; ================================================ FILE: examples/quota_watermark/qwctl/commands.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _COMMANDS_H_ #define _COMMANDS_H_ #include extern cmdline_parse_ctx_t qwctl_ctx[]; #endif /* _COMMANDS_H_ */ ================================================ FILE: examples/quota_watermark/qwctl/qwctl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qwctl.h" #include "commands.h" #include "../include/conf.h" int *quota; unsigned int *low_watermark; static void setup_shared_variables(void) { const struct rte_memzone *qw_memzone; qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME); if (qw_memzone == NULL) rte_exit(EXIT_FAILURE, "Couldn't find memzone\n"); quota = qw_memzone->addr; low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); } int main(int argc, char **argv) { int ret; struct cmdline *cl; rte_set_log_level(RTE_LOG_INFO); ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); setup_shared_variables(); cl = cmdline_stdin_new(qwctl_ctx, "qwctl> "); if (cl == NULL) rte_exit(EXIT_FAILURE, "Cannot create cmdline instance\n"); cmdline_interact(cl); cmdline_stdin_exit(cl); return 0; } ================================================ FILE: examples/quota_watermark/qwctl/qwctl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ extern int *quota; extern unsigned int *low_watermark; #endif /* _MAIN_H_ */ ================================================ FILE: examples/rxtx_callbacks/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = rxtx_callbacks # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif EXTRA_CFLAGS += -O3 -g -Wfatal-errors include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/rxtx_callbacks/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #define RX_RING_SIZE 128 #define TX_RING_SIZE 512 #define NUM_MBUFS 8191 #define MBUF_CACHE_SIZE 250 #define BURST_SIZE 32 static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, }, }; static unsigned nb_ports; static struct { uint64_t total_cycles; uint64_t total_pkts; } latency_numbers; static uint16_t add_timestamps(uint8_t port __rte_unused, uint16_t qidx __rte_unused, struct rte_mbuf **pkts, uint16_t nb_pkts, uint16_t max_pkts __rte_unused, void *_ __rte_unused) { unsigned i; uint64_t now = rte_rdtsc(); for (i = 0; i < nb_pkts; i++) pkts[i]->udata64 = now; return nb_pkts; } static uint16_t calc_latency(uint8_t port __rte_unused, uint16_t qidx __rte_unused, struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused) { uint64_t cycles = 0; uint64_t now = rte_rdtsc(); unsigned i; for (i = 0; i < nb_pkts; i++) cycles += now - pkts[i]->udata64; latency_numbers.total_cycles += cycles; latency_numbers.total_pkts += nb_pkts; if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) { printf("Latency = %"PRIu64" cycles\n", latency_numbers.total_cycles / latency_numbers.total_pkts); latency_numbers.total_cycles = latency_numbers.total_pkts = 0; } return nb_pkts; } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf = port_conf_default; const uint16_t rx_rings = 1, tx_rings = 1; int retval; uint16_t q; if (port >= rte_eth_dev_count()) return -1; retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } retval = rte_eth_dev_start(port); if (retval < 0) return retval; struct ether_addr addr; rte_eth_macaddr_get(port, &addr); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); rte_eth_promiscuous_enable(port); rte_eth_add_rx_callback(port, 0, add_timestamps, NULL); rte_eth_add_tx_callback(port, 0, calc_latency, NULL); return 0; } /* * Main thread that does the work, reading from INPUT_PORT * and writing to OUTPUT_PORT */ static __attribute__((noreturn)) void lcore_main(void) { uint8_t port; for (port = 0; port < nb_ports; port++) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) printf("WARNING, port %u is on remote NUMA node to " "polling thread.\n\tPerformance will " "not be optimal.\n", port); printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id()); for (;;) { for (port = 0; port < nb_ports; port++) { struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx == 0)) continue; const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf = nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } } } /* Main function, does initialisation and calls the per-lcore functions */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; uint8_t portid; /* init EAL */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; nb_ports = rte_eth_dev_count(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n", portid); if (rte_lcore_count() > 1) printf("\nWARNING: Too much enabled lcores - " "App uses only 1 lcore\n"); /* call lcore_main on master core only */ lcore_main(); return 0; } ================================================ FILE: examples/skeleton/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = basicfwd # all source are stored in SRCS-y SRCS-y := basicfwd.c CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif EXTRA_CFLAGS += -O3 -g -Wfatal-errors include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/skeleton/basicfwd.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #define RX_RING_SIZE 128 #define TX_RING_SIZE 512 #define NUM_MBUFS 8191 #define MBUF_CACHE_SIZE 250 #define BURST_SIZE 32 static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN } }; /* basicfwd.c: Basic DPDK skeleton forwarding example. */ /* * Initializes a given port using global settings and with the RX buffers * coming from the mbuf_pool passed as a parameter. */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf = port_conf_default; const uint16_t rx_rings = 1, tx_rings = 1; int retval; uint16_t q; if (port >= rte_eth_dev_count()) return -1; /* Configure the Ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; /* Allocate and set up 1 RX queue per Ethernet port. */ for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } /* Start the Ethernet port. */ retval = rte_eth_dev_start(port); if (retval < 0) return retval; /* Display the port MAC address. */ struct ether_addr addr; rte_eth_macaddr_get(port, &addr); printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", (unsigned)port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); /* Enable RX in promiscuous mode for the Ethernet device. */ rte_eth_promiscuous_enable(port); return 0; } /* * The lcore main. This is the main thread that does the work, reading from * an input port and writing to an output port. */ static __attribute__((noreturn)) void lcore_main(void) { const uint8_t nb_ports = rte_eth_dev_count(); uint8_t port; /* * Check that the port is on the same NUMA node as the polling thread * for best performance. */ for (port = 0; port < nb_ports; port++) if (rte_eth_dev_socket_id(port) > 0 && rte_eth_dev_socket_id(port) != (int)rte_socket_id()) printf("WARNING, port %u is on remote NUMA node to " "polling thread.\n\tPerformance will " "not be optimal.\n", port); printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n", rte_lcore_id()); /* Run until the application is quit or killed. */ for (;;) { /* * Receive packets on a port and forward them on the paired * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc. */ for (port = 0; port < nb_ports; port++) { /* Get burst of RX packets, from first port of pair. */ struct rte_mbuf *bufs[BURST_SIZE]; const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx == 0)) continue; /* Send burst of TX packets, to second port of pair. */ const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); /* Free any unsent packets. */ if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf = nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } } } /* * The main function, which does initialization and calls the per-lcore * functions. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; unsigned nb_ports; uint8_t portid; /* Initialize the Environment Abstraction Layer (EAL). */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* Check that there is an even number of ports to send/receive on. */ nb_ports = rte_eth_dev_count(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); /* Creates a new mempool in memory to hold the mbufs. */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ for (portid = 0; portid < nb_ports; portid++) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", portid); if (rte_lcore_count() > 1) printf("\nWARNING: Too many lcores enabled. Only 1 used.\n"); /* Call lcore_main on the master core only. */ lcore_main(); return 0; } ================================================ FILE: examples/tep_termination/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif # binary name APP = tep_termination # all source are stored in SRCS-y SRCS-y := main.c vxlan_setup.c vxlan.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/tep_termination/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "vxlan.h" #include "vxlan_setup.h" /* the maximum number of external ports supported */ #define MAX_SUP_PORTS 1 /** * Calculate the number of buffers needed per port */ #define NUM_MBUFS_PER_PORT ((MAX_QUEUES * RTE_TEST_RX_DESC_DEFAULT) +\ (nb_switching_cores * MAX_PKT_BURST) +\ (nb_switching_cores * \ RTE_TEST_TX_DESC_DEFAULT) +\ (nb_switching_cores * MBUF_CACHE_SIZE)) #define MBUF_CACHE_SIZE 128 #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) #define MAX_PKT_BURST 32 /* Max burst size for RX/TX */ #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* Defines how long we wait between retries on RX */ #define BURST_RX_WAIT_US 15 #define BURST_RX_RETRIES 4 /* Number of retries on RX. */ #define JUMBO_FRAME_MAX_SIZE 0x2600 /* State of virtio device. */ #define DEVICE_MAC_LEARNING 0 #define DEVICE_RX 1 #define DEVICE_SAFE_REMOVE 2 /* Config_core_flag status definitions. */ #define REQUEST_DEV_REMOVAL 1 #define ACK_DEV_REMOVAL 0 /* Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 1024 #define RTE_TEST_TX_DESC_DEFAULT 512 /* Get first 4 bytes in mbuf headroom. */ #define MBUF_HEADROOM_UINT32(mbuf) (*(uint32_t *)((uint8_t *)(mbuf) \ + sizeof(struct rte_mbuf))) #define INVALID_PORT_ID 0xFF /* Size of buffers used for snprintfs. */ #define MAX_PRINT_BUFF 6072 /* Maximum character device basename size. */ #define MAX_BASENAME_SZ 20 /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 /* Used to compare MAC addresses. */ #define MAC_ADDR_CMP 0xFFFFFFFFFFFFULL #define CMD_LINE_OPT_NB_DEVICES "nb-devices" #define CMD_LINE_OPT_UDP_PORT "udp-port" #define CMD_LINE_OPT_TX_CHECKSUM "tx-checksum" #define CMD_LINE_OPT_TSO_SEGSZ "tso-segsz" #define CMD_LINE_OPT_FILTER_TYPE "filter-type" #define CMD_LINE_OPT_ENCAP "encap" #define CMD_LINE_OPT_DECAP "decap" #define CMD_LINE_OPT_RX_RETRY "rx-retry" #define CMD_LINE_OPT_RX_RETRY_DELAY "rx-retry-delay" #define CMD_LINE_OPT_RX_RETRY_NUM "rx-retry-num" #define CMD_LINE_OPT_STATS "stats" #define CMD_LINE_OPT_DEV_BASENAME "dev-basename" /* mask of enabled ports */ static uint32_t enabled_port_mask; /*Number of switching cores enabled*/ static uint32_t nb_switching_cores; /* number of devices/queues to support*/ uint16_t nb_devices = 2; /* max ring descriptor, ixgbe, i40e, e1000 all are 4096. */ #define MAX_RING_DESC 4096 struct vpool { struct rte_mempool *pool; struct rte_ring *ring; uint32_t buf_size; } vpool_array[MAX_QUEUES+MAX_QUEUES]; /* UDP tunneling port */ uint16_t udp_port = 4789; /* enable/disable inner TX checksum */ uint8_t tx_checksum = 0; /* TCP segment size */ uint16_t tso_segsz = 0; /* enable/disable decapsulation */ uint8_t rx_decap = 1; /* enable/disable encapsulation */ uint8_t tx_encap = 1; /* RX filter type for tunneling packet */ uint8_t filter_idx = 1; /* overlay packet operation */ struct ol_switch_ops overlay_options = { .port_configure = vxlan_port_init, .tunnel_setup = vxlan_link, .tunnel_destroy = vxlan_unlink, .tx_handle = vxlan_tx_pkts, .rx_handle = vxlan_rx_pkts, .param_handle = NULL, }; /* Enable stats. */ uint32_t enable_stats = 0; /* Enable retries on RX. */ static uint32_t enable_retry = 1; /* Specify timeout (in useconds) between retries on RX. */ static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US; /* Specify the number of retries on RX. */ static uint32_t burst_rx_retry_num = BURST_RX_RETRIES; /* Character device basename. Can be set by user. */ static char dev_basename[MAX_BASENAME_SZ] = "vhost-net"; static unsigned lcore_ids[RTE_MAX_LCORE]; uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned nb_ports; /**< The number of ports specified in command line */ /* ethernet addresses of ports */ struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* heads for the main used and free linked lists for the data path. */ static struct virtio_net_data_ll *ll_root_used; static struct virtio_net_data_ll *ll_root_free; /** * Array of data core structures containing information on * individual core linked lists. */ static struct lcore_info lcore_info[RTE_MAX_LCORE]; /* Used for queueing bursts of TX packets. */ struct mbuf_table { unsigned len; unsigned txq_id; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; /* TX queue for each data core. */ struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE]; struct device_statistics dev_statistics[MAX_DEVICES]; /** * Set character device basename. */ static int us_vhost_parse_basename(const char *q_arg) { /* parse number string */ if (strlen(q_arg) >= MAX_BASENAME_SZ) return -1; else snprintf((char *)&dev_basename, MAX_BASENAME_SZ, "%s", q_arg); return 0; } /** * Parse the portmask provided at run time. */ static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /** * Parse num options at run time. */ static int parse_num_opt(const char *q_arg, uint32_t max_valid_value) { char *end = NULL; unsigned long num; /* parse unsigned int string */ num = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (num > max_valid_value) return -1; return num; } /** * Display usage */ static void tep_termination_usage(const char *prgname) { RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK\n" " --udp-port: UDP destination port for VXLAN packet\n" " --nb-devices[1-64]: The number of virtIO device\n" " --tx-checksum [0|1]: inner Tx checksum offload\n" " --tso-segsz [0-N]: TCP segment size\n" " --decap [0|1]: tunneling packet decapsulation\n" " --encap [0|1]: tunneling packet encapsulation\n" " --filter-type[1-3]: filter type for tunneling packet\n" " 1: Inner MAC and tenent ID\n" " 2: Inner MAC and VLAN, and tenent ID\n" " 3: Outer MAC, Inner MAC and tenent ID\n" " -p PORTMASK: Set mask for ports to be used by application\n" " --rx-retry [0|1]: disable/enable(default) retries on rx." " Enable retry if destintation queue is full\n" " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX." " This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx." " This makes effect only if retries on rx enabled\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n", prgname); } /** * Parse the arguments given in the command line of the application. */ static int tep_termination_parse_args(int argc, char **argv) { int opt, ret; int option_index; unsigned i; const char *prgname = argv[0]; static struct option long_option[] = { {CMD_LINE_OPT_NB_DEVICES, required_argument, NULL, 0}, {CMD_LINE_OPT_UDP_PORT, required_argument, NULL, 0}, {CMD_LINE_OPT_TX_CHECKSUM, required_argument, NULL, 0}, {CMD_LINE_OPT_TSO_SEGSZ, required_argument, NULL, 0}, {CMD_LINE_OPT_DECAP, required_argument, NULL, 0}, {CMD_LINE_OPT_ENCAP, required_argument, NULL, 0}, {CMD_LINE_OPT_FILTER_TYPE, required_argument, NULL, 0}, {CMD_LINE_OPT_RX_RETRY, required_argument, NULL, 0}, {CMD_LINE_OPT_RX_RETRY_DELAY, required_argument, NULL, 0}, {CMD_LINE_OPT_RX_RETRY_NUM, required_argument, NULL, 0}, {CMD_LINE_OPT_STATS, required_argument, NULL, 0}, {CMD_LINE_OPT_DEV_BASENAME, required_argument, NULL, 0}, {NULL, 0, 0, 0}, }; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:", long_option, &option_index)) != EOF) { switch (opt) { /* Portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid portmask\n"); tep_termination_usage(prgname); return -1; } break; case 0: if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_NB_DEVICES, sizeof(CMD_LINE_OPT_NB_DEVICES))) { ret = parse_num_opt(optarg, MAX_DEVICES); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for nb-devices [0-%d]\n", MAX_DEVICES); tep_termination_usage(prgname); return -1; } else nb_devices = ret; } /* Enable/disable retries on RX. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_RX_RETRY, sizeof(CMD_LINE_OPT_RX_RETRY))) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry [0|1]\n"); tep_termination_usage(prgname); return -1; } else enable_retry = ret; } if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_TSO_SEGSZ, sizeof(CMD_LINE_OPT_TSO_SEGSZ))) { ret = parse_num_opt(optarg, INT16_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for TCP segment size [0-N]\n"); tep_termination_usage(prgname); return -1; } else tso_segsz = ret; } if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_UDP_PORT, sizeof(CMD_LINE_OPT_UDP_PORT))) { ret = parse_num_opt(optarg, INT16_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for UDP port [0-N]\n"); tep_termination_usage(prgname); return -1; } else udp_port = ret; } /* Specify the retries delay time (in useconds) on RX.*/ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_RX_RETRY_DELAY, sizeof(CMD_LINE_OPT_RX_RETRY_DELAY))) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-delay [0-N]\n"); tep_termination_usage(prgname); return -1; } else burst_rx_delay_time = ret; } /* Specify the retries number on RX. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_RX_RETRY_NUM, sizeof(CMD_LINE_OPT_RX_RETRY_NUM))) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-num [0-N]\n"); tep_termination_usage(prgname); return -1; } else burst_rx_retry_num = ret; } if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_TX_CHECKSUM, sizeof(CMD_LINE_OPT_TX_CHECKSUM))) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tx-checksum [0|1]\n"); tep_termination_usage(prgname); return -1; } else tx_checksum = ret; } if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_FILTER_TYPE, sizeof(CMD_LINE_OPT_FILTER_TYPE))) { ret = parse_num_opt(optarg, 3); if ((ret == -1) || (ret == 0)) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for filter type [1-3]\n"); tep_termination_usage(prgname); return -1; } else filter_idx = ret - 1; } /* Enable/disable encapsulation on RX. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_DECAP, sizeof(CMD_LINE_OPT_DECAP))) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for decap [0|1]\n"); tep_termination_usage(prgname); return -1; } else rx_decap = ret; } /* Enable/disable encapsulation on TX. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_ENCAP, sizeof(CMD_LINE_OPT_ENCAP))) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for encap [0|1]\n"); tep_termination_usage(prgname); return -1; } else tx_encap = ret; } /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_STATS, sizeof(CMD_LINE_OPT_STATS))) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n"); tep_termination_usage(prgname); return -1; } else enable_stats = ret; } /* Set character device basename. */ if (!strncmp(long_option[option_index].name, CMD_LINE_OPT_DEV_BASENAME, sizeof(CMD_LINE_OPT_DEV_BASENAME))) { if (us_vhost_parse_basename(optarg) == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for character " "device basename (Max %d characters)\n", MAX_BASENAME_SZ); tep_termination_usage(prgname); return -1; } } break; /* Invalid option - print options. */ default: tep_termination_usage(prgname); return -1; } } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (enabled_port_mask & (1 << i)) ports[nb_ports++] = (uint8_t)i; } if ((nb_ports == 0) || (nb_ports > MAX_SUP_PORTS)) { RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u," "but only %u port can be enabled\n", nb_ports, MAX_SUP_PORTS); return -1; } return 0; } /** * Update the global var NB_PORTS and array PORTS * according to system ports number and return valid ports number */ static unsigned check_ports_num(unsigned max_nb_ports) { unsigned valid_nb_ports = nb_ports; unsigned portid; if (nb_ports > max_nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port number(%u) " " exceeds total system port number(%u)\n", nb_ports, max_nb_ports); nb_ports = max_nb_ports; } for (portid = 0; portid < nb_ports; portid++) { if (ports[portid] >= max_nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max " " system port ID(%u)\n", ports[portid], (max_nb_ports - 1)); ports[portid] = INVALID_PORT_ID; valid_nb_ports--; } } return valid_nb_ports; } /** * This function routes the TX packet to the correct interface. This may be a local device * or the physical port. */ static inline void __attribute__((always_inline)) virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m) { struct mbuf_table *tx_q; struct rte_mbuf **m_table; unsigned len, ret = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n", dev->device_fh); /* Add packet to the port tx queue */ tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; tx_q->m_table[len] = m; len++; if (enable_stats) { dev_statistics[dev->device_fh].tx_total++; dev_statistics[dev->device_fh].tx++; } if (unlikely(len == MAX_PKT_BURST)) { m_table = (struct rte_mbuf **)tx_q->m_table; ret = overlay_options.tx_handle(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t)tx_q->len); /* Free any buffers not handled by TX and update * the port stats. */ if (unlikely(ret < len)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < len); } len = 0; } tx_q->len = len; return; } /** * This function is called by each data core. It handles all * RX/TX registered with the core. For TX the specific lcore * linked list is used. For RX, MAC addresses are compared * with all devices in the main linked list. */ static int switch_worker(__rte_unused void *arg) { struct rte_mempool *mbuf_pool = arg; struct virtio_net *dev = NULL; struct vhost_dev *vdev = NULL; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct virtio_net_data_ll *dev_ll; struct mbuf_table *tx_q; volatile struct lcore_ll_info *lcore_ll; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0; unsigned i, ret = 0; const uint16_t lcore_id = rte_lcore_id(); const uint16_t num_cores = (uint16_t)rte_lcore_count(); uint16_t rx_count = 0; uint16_t tx_count; uint32_t retry = 0; RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id); lcore_ll = lcore_info[lcore_id].lcore_ll; prev_tsc = 0; tx_q = &lcore_tx_queue[lcore_id]; for (i = 0; i < num_cores; i++) { if (lcore_ids[i] == lcore_id) { tx_q->txq_id = i; break; } } while (1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { if (tx_q->len) { LOG_DEBUG(VHOST_DATA, "TX queue drained after " "timeout with burst size %u\n", tx_q->len); ret = overlay_options.tx_handle(ports[0], (uint16_t)tx_q->txq_id, (struct rte_mbuf **)tx_q->m_table, (uint16_t)tx_q->len); if (unlikely(ret < tx_q->len)) { do { rte_pktmbuf_free(tx_q->m_table[ret]); } while (++ret < tx_q->len); } tx_q->len = 0; } prev_tsc = cur_tsc; } rte_prefetch0(lcore_ll->ll_root_used); /** * Inform the configuration core that we have exited * the linked list and that no devices are * in use if requested. */ if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL) lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; /* * Process devices */ dev_ll = lcore_ll->ll_root_used; while (dev_ll != NULL) { vdev = dev_ll->vdev; dev = vdev->dev; if (unlikely(vdev->remove)) { dev_ll = dev_ll->next; overlay_options.tunnel_destroy(vdev); vdev->ready = DEVICE_SAFE_REMOVE; continue; } if (likely(vdev->ready == DEVICE_RX)) { /* Handle guest RX */ rx_count = rte_eth_rx_burst(ports[0], vdev->rx_q, pkts_burst, MAX_PKT_BURST); if (rx_count) { /* * Retry is enabled and the queue is * full then we wait and retry to * avoid packet loss. Here MAX_PKT_BURST * must be less than virtio queue size */ if (enable_retry && unlikely(rx_count > rte_vring_available_entries(dev, VIRTIO_RXQ))) { for (retry = 0; retry < burst_rx_retry_num; retry++) { rte_delay_us(burst_rx_delay_time); if (rx_count <= rte_vring_available_entries(dev, VIRTIO_RXQ)) break; } } ret_count = overlay_options.rx_handle(dev, pkts_burst, rx_count); if (enable_stats) { rte_atomic64_add( &dev_statistics[dev->device_fh].rx_total_atomic, rx_count); rte_atomic64_add( &dev_statistics[dev->device_fh].rx_atomic, ret_count); } while (likely(rx_count)) { rx_count--; rte_pktmbuf_free(pkts_burst[rx_count]); } } } if (likely(!vdev->remove)) { /* Handle guest TX*/ tx_count = rte_vhost_dequeue_burst(dev, VIRTIO_TXQ, mbuf_pool, pkts_burst, MAX_PKT_BURST); /* If this is the first received packet we need to learn the MAC */ if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && tx_count) { if (vdev->remove || (overlay_options.tunnel_setup(vdev, pkts_burst[0]) == -1)) { while (tx_count) rte_pktmbuf_free(pkts_burst[--tx_count]); } } while (tx_count) virtio_tx_route(vdev, pkts_burst[--tx_count]); } /* move to the next device in the list */ dev_ll = dev_ll->next; } } return 0; } /** * Add an entry to a used linked list. A free entry must first be found * in the free linked list using get_data_ll_free_entry(); */ static void add_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll = *ll_root_addr; /* Set next as NULL and use a compiler barrier to avoid reordering. */ ll_dev->next = NULL; rte_compiler_barrier(); /* If ll == NULL then this is the first device. */ if (ll) { /* Increment to the tail of the linked list. */ while (ll->next != NULL) ll = ll->next; ll->next = ll_dev; } else { *ll_root_addr = ll_dev; } } /** * Remove an entry from a used linked list. The entry must then be added to * the free linked list using put_data_ll_free_entry(). */ static void rm_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev, struct virtio_net_data_ll *ll_dev_last) { struct virtio_net_data_ll *ll = *ll_root_addr; if (unlikely((ll == NULL) || (ll_dev == NULL))) return; if (ll_dev == ll) *ll_root_addr = ll_dev->next; else if (likely(ll_dev_last != NULL)) ll_dev_last->next = ll_dev->next; else RTE_LOG(ERR, VHOST_CONFIG, "Remove entry form ll failed.\n"); } /** * Find and return an entry from the free linked list. */ static struct virtio_net_data_ll * get_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr) { struct virtio_net_data_ll *ll_free = *ll_root_addr; struct virtio_net_data_ll *ll_dev; if (ll_free == NULL) return NULL; ll_dev = ll_free; *ll_root_addr = ll_free->next; return ll_dev; } /** * Place an entry back on to the free linked list. */ static void put_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll_free = *ll_root_addr; if (ll_dev == NULL) return; ll_dev->next = ll_free; *ll_root_addr = ll_dev; } /** * Creates a linked list of a given size. */ static struct virtio_net_data_ll * alloc_data_ll(uint32_t size) { struct virtio_net_data_ll *ll_new; uint32_t i; /* Malloc and then chain the linked list. */ ll_new = malloc(size * sizeof(struct virtio_net_data_ll)); if (ll_new == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for ll_new.\n"); return NULL; } for (i = 0; i < size - 1; i++) { ll_new[i].vdev = NULL; ll_new[i].next = &ll_new[i+1]; } ll_new[i].next = NULL; return ll_new; } /** * Create the main linked list along with each individual cores * linked list. A used and a free list are created to manage entries. */ static int init_data_ll(void) { int lcore; RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll = malloc(sizeof(struct lcore_ll_info)); if (lcore_info[lcore].lcore_ll == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for lcore_ll.\n"); return -1; } lcore_info[lcore].lcore_ll->device_num = 0; lcore_info[lcore].lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; lcore_info[lcore].lcore_ll->ll_root_used = NULL; if (nb_devices % nb_switching_cores) lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll((nb_devices / nb_switching_cores) + 1); else lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll(nb_devices / nb_switching_cores); } /* Allocate devices up to a maximum of MAX_DEVICES. */ ll_root_free = alloc_data_ll(MIN((nb_devices), MAX_DEVICES)); return 0; } /** * Remove a device from the specific data core linked list and * from the main linked list. Synchonization occurs through the use * of the lcore dev_removal_flag. Device is made volatile here * to avoid re-ordering of dev->remove=1 which can cause an infinite * loop in the rte_pause loop. */ static void destroy_device(volatile struct virtio_net *dev) { struct virtio_net_data_ll *ll_lcore_dev_cur; struct virtio_net_data_ll *ll_main_dev_cur; struct virtio_net_data_ll *ll_lcore_dev_last = NULL; struct virtio_net_data_ll *ll_main_dev_last = NULL; struct vhost_dev *vdev; int lcore; dev->flags &= ~VIRTIO_DEV_RUNNING; vdev = (struct vhost_dev *)dev->priv; /* set the remove flag. */ vdev->remove = 1; while (vdev->ready != DEVICE_SAFE_REMOVE) rte_pause(); /* Search for entry to be removed from lcore ll */ ll_lcore_dev_cur = lcore_info[vdev->coreid].lcore_ll->ll_root_used; while (ll_lcore_dev_cur != NULL) { if (ll_lcore_dev_cur->vdev == vdev) { break; } else { ll_lcore_dev_last = ll_lcore_dev_cur; ll_lcore_dev_cur = ll_lcore_dev_cur->next; } } if (ll_lcore_dev_cur == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find the dev to be destroy.\n", dev->device_fh); return; } /* Search for entry to be removed from main ll */ ll_main_dev_cur = ll_root_used; ll_main_dev_last = NULL; while (ll_main_dev_cur != NULL) { if (ll_main_dev_cur->vdev == vdev) { break; } else { ll_main_dev_last = ll_main_dev_cur; ll_main_dev_cur = ll_main_dev_cur->next; } } /* Remove entries from the lcore and main ll. */ rm_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_lcore_dev_cur, ll_lcore_dev_last); rm_data_ll_entry(&ll_root_used, ll_main_dev_cur, ll_main_dev_last); /* Set the dev_removal_flag on each lcore. */ RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll->dev_removal_flag = REQUEST_DEV_REMOVAL; } /* * Once each core has set the dev_removal_flag to * ACK_DEV_REMOVAL we can be sure that they can no longer access * the device removed from the linked lists and that the devices * are no longer in use. */ RTE_LCORE_FOREACH_SLAVE(lcore) { while (lcore_info[lcore].lcore_ll->dev_removal_flag != ACK_DEV_REMOVAL) rte_pause(); } /* Add the entries back to the lcore and main free ll.*/ put_data_ll_free_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_free, ll_lcore_dev_cur); put_data_ll_free_entry(&ll_root_free, ll_main_dev_cur); /* Decrement number of device on the lcore. */ lcore_info[vdev->coreid].lcore_ll->device_num--; RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been removed " "from data core\n", dev->device_fh); rte_free(vdev); } /** * A new device is added to a data core. First the device is added * to the main linked list and the allocated to a specific data core. */ static int new_device(struct virtio_net *dev) { struct virtio_net_data_ll *ll_dev; int lcore, core_add = 0; uint32_t device_num_min = nb_devices; struct vhost_dev *vdev; vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE); if (vdev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Couldn't allocate memory for vhost dev\n", dev->device_fh); return -1; } vdev->dev = dev; dev->priv = vdev; /* Add device to main ll */ ll_dev = get_data_ll_free_entry(&ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in" " linked list Device limit of %d devices per core" " has been reached\n", dev->device_fh, nb_devices); if (vdev->regions_hpa) rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } ll_dev->vdev = vdev; add_data_ll_entry(&ll_root_used, ll_dev); vdev->rx_q = dev->device_fh; /* reset ready flag */ vdev->ready = DEVICE_MAC_LEARNING; vdev->remove = 0; /* Find a suitable lcore to add the device. */ RTE_LCORE_FOREACH_SLAVE(lcore) { if (lcore_info[lcore].lcore_ll->device_num < device_num_min) { device_num_min = lcore_info[lcore].lcore_ll->device_num; core_add = lcore; } } /* Add device to lcore ll */ ll_dev = get_data_ll_free_entry(&lcore_info[core_add].lcore_ll->ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh); vdev->ready = DEVICE_SAFE_REMOVE; destroy_device(dev); rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } ll_dev->vdev = vdev; vdev->coreid = core_add; add_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_dev); /* Initialize device stats */ memset(&dev_statistics[dev->device_fh], 0, sizeof(struct device_statistics)); /* Disable notifications. */ rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0); rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0); lcore_info[vdev->coreid].lcore_ll->device_num++; dev->flags |= VIRTIO_DEV_RUNNING; RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, vdev->coreid); return 0; } /** * These callback allow devices to be added to the data core when configuration * has been fully complete. */ static const struct virtio_net_device_ops virtio_net_device_ops = { .new_device = new_device, .destroy_device = destroy_device, }; /** * This is a thread will wake up after a period to print stats if the user has * enabled them. */ static void print_stats(void) { struct virtio_net_data_ll *dev_ll; uint64_t tx_dropped, rx_dropped; uint64_t tx, tx_total, rx, rx_total, rx_ip_csum, rx_l4_csum; uint32_t device_fh; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' }; while (1) { sleep(enable_stats); /* Clear screen and move to top left */ printf("%s%s", clr, top_left); printf("\nDevice statistics ================================"); dev_ll = ll_root_used; while (dev_ll != NULL) { device_fh = (uint32_t)dev_ll->vdev->dev->device_fh; tx_total = dev_statistics[device_fh].tx_total; tx = dev_statistics[device_fh].tx; tx_dropped = tx_total - tx; rx_total = rte_atomic64_read( &dev_statistics[device_fh].rx_total_atomic); rx = rte_atomic64_read( &dev_statistics[device_fh].rx_atomic); rx_dropped = rx_total - rx; rx_ip_csum = rte_atomic64_read( &dev_statistics[device_fh].rx_bad_ip_csum); rx_l4_csum = rte_atomic64_read( &dev_statistics[device_fh].rx_bad_l4_csum); printf("\nStatistics for device %"PRIu32" ----------" "\nTX total: %"PRIu64"" "\nTX dropped: %"PRIu64"" "\nTX successful: %"PRIu64"" "\nRX total: %"PRIu64"" "\nRX bad IP csum: %"PRIu64"" "\nRX bad L4 csum: %"PRIu64"" "\nRX dropped: %"PRIu64"" "\nRX successful: %"PRIu64"", device_fh, tx_total, tx_dropped, tx, rx_total, rx_ip_csum, rx_l4_csum, rx_dropped, rx); dev_ll = dev_ll->next; } printf("\n================================================\n"); } } /** * Main function, does initialisation and calls the per-lcore functions. The CUSE * device is also registered here to handle the IOCTLs. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool = NULL; unsigned lcore_id, core_id = 0; unsigned nb_ports, valid_nb_ports; int ret; uint8_t portid; uint16_t queue_id; static pthread_t tid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse app arguments */ ret = tep_termination_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid argument\n"); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) if (rte_lcore_is_enabled(lcore_id)) lcore_ids[core_id++] = lcore_id; /* set the number of swithcing cores available */ nb_switching_cores = rte_lcore_count()-1; /* Get the number of physical ports. */ nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Update the global var NB_PORTS and global array PORTS * and get value of var VALID_NB_PORTS according to system ports number */ valid_nb_ports = check_ports_num(nb_ports); if ((valid_nb_ports == 0) || (valid_nb_ports > MAX_SUP_PORTS)) { rte_exit(EXIT_FAILURE, "Current enabled port number is %u," "but only %u port can be enabled\n", nb_ports, MAX_SUP_PORTS); } /* Create the mbuf pool. */ mbuf_pool = rte_mempool_create( "MBUF_POOL", NUM_MBUFS_PER_PORT * valid_nb_ports, MBUF_SIZE, MBUF_CACHE_SIZE, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); for (queue_id = 0; queue_id < MAX_QUEUES + 1; queue_id++) vpool_array[queue_id].pool = mbuf_pool; /* Set log level. */ rte_set_log_level(LOG_LEVEL); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { RTE_LOG(INFO, VHOST_PORT, "Skipping disabled port %d\n", portid); continue; } if (overlay_options.port_configure(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); } /* Initialise all linked lists. */ if (init_data_ll() == -1) rte_exit(EXIT_FAILURE, "Failed to initialize linked list\n"); /* Initialize device stats */ memset(&dev_statistics, 0, sizeof(dev_statistics)); /* Enable stats if the user option is set. */ if (enable_stats) pthread_create(&tid, NULL, (void *)print_stats, NULL); /* Launch all data cores. */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(switch_worker, mbuf_pool, lcore_id); } rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF); /* Register CUSE device to handle IOCTLs. */ ret = rte_vhost_driver_register((char *)&dev_basename); if (ret != 0) rte_exit(EXIT_FAILURE, "CUSE device setup failure.\n"); rte_vhost_driver_callback_register(&virtio_net_device_ops); /* Start CUSE session. */ rte_vhost_driver_session_start(); return 0; } ================================================ FILE: examples/tep_termination/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ #include #ifdef DEBUG #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) RTE_LOG(DEBUG, log_type, fmt, ##args) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do {} while (0) #endif /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2 #define RTE_LOGTYPE_VHOST_PORT RTE_LOGTYPE_USER3 /* State of virtio device. */ #define DEVICE_MAC_LEARNING 0 #define DEVICE_RX 1 #define DEVICE_SAFE_REMOVE 2 #define MAX_QUEUES 512 /* Max burst size for RX/TX */ #define MAX_PKT_BURST 32 /* Max number of devices. Limited by the application. */ #define MAX_DEVICES 64 /* Per-device statistics struct */ struct device_statistics { uint64_t tx_total; rte_atomic64_t rx_total_atomic; uint64_t rx_total; uint64_t tx; rte_atomic64_t rx_atomic; /**< Bad inner IP csum for tunneling pkt */ rte_atomic64_t rx_bad_ip_csum; /**< Bad inner L4 csum for tunneling pkt */ rte_atomic64_t rx_bad_l4_csum; } __rte_cache_aligned; /** * Device linked list structure for data path. */ struct vhost_dev { /**< Pointer to device created by vhost lib. */ struct virtio_net *dev; /**< Number of memory regions for gpa to hpa translation. */ uint32_t nregions_hpa; /**< Memory region information for gpa to hpa translation. */ struct virtio_memory_regions_hpa *regions_hpa; /**< Device MAC address (Obtained on first TX packet). */ struct ether_addr mac_address; /**< RX queue number. */ uint16_t rx_q; /**< Data core that the device is added to. */ uint16_t coreid; /**< A device is set as ready if the MAC address has been set. */ volatile uint8_t ready; /**< Device is marked for removal from the data core. */ volatile uint8_t remove; } __rte_cache_aligned; /** * Structure containing data core specific information. */ struct lcore_ll_info { /**< Pointer to head in free linked list. */ struct virtio_net_data_ll *ll_root_free; /**< Pointer to head of used linked list. */ struct virtio_net_data_ll *ll_root_used; /**< Number of devices on lcore. */ uint32_t device_num; /**< Flag to synchronize device removal. */ volatile uint8_t dev_removal_flag; }; struct lcore_info { /**< Pointer to data core specific lcore_ll_info struct */ struct lcore_ll_info *lcore_ll; }; struct virtio_net_data_ll { /**< Pointer to device created by configuration core. */ struct vhost_dev *vdev; /**< Pointer to next device in linked list. */ struct virtio_net_data_ll *next; }; uint32_t virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count); #endif /* _MAIN_H_ */ ================================================ FILE: examples/tep_termination/vxlan.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "main.h" #include "vxlan.h" static uint16_t get_psd_sum(void *l3_hdr, uint16_t ethertype, uint64_t ol_flags) { if (ethertype == ETHER_TYPE_IPv4) return rte_ipv4_phdr_cksum(l3_hdr, ol_flags); else /* assume ethertype == ETHER_TYPE_IPv6 */ return rte_ipv6_phdr_cksum(l3_hdr, ol_flags); } /** * Parse an ethernet header to fill the ethertype, outer_l2_len, outer_l3_len and * ipproto. This function is able to recognize IPv4/IPv6 with one optional vlan * header. */ static void parse_ethernet(struct ether_hdr *eth_hdr, union tunnel_offload_info *info, uint8_t *l4_proto) { struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; uint16_t ethertype; info->outer_l2_len = sizeof(struct ether_hdr); ethertype = rte_be_to_cpu_16(eth_hdr->ether_type); if (ethertype == ETHER_TYPE_VLAN) { struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); info->outer_l2_len += sizeof(struct vlan_hdr); ethertype = rte_be_to_cpu_16(vlan_hdr->eth_proto); } switch (ethertype) { case ETHER_TYPE_IPv4: ipv4_hdr = (struct ipv4_hdr *) ((char *)eth_hdr + info->outer_l2_len); info->outer_l3_len = sizeof(struct ipv4_hdr); *l4_proto = ipv4_hdr->next_proto_id; break; case ETHER_TYPE_IPv6: ipv6_hdr = (struct ipv6_hdr *) ((char *)eth_hdr + info->outer_l2_len); info->outer_l3_len = sizeof(struct ipv6_hdr); *l4_proto = ipv6_hdr->proto; break; default: info->outer_l3_len = 0; *l4_proto = 0; break; } } /** * Calculate the checksum of a packet in hardware */ static uint64_t process_inner_cksums(struct ether_hdr *eth_hdr, union tunnel_offload_info *info) { void *l3_hdr = NULL; uint8_t l4_proto; uint16_t ethertype; struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; struct udp_hdr *udp_hdr; struct tcp_hdr *tcp_hdr; struct sctp_hdr *sctp_hdr; uint64_t ol_flags = 0; info->l2_len = sizeof(struct ether_hdr); ethertype = rte_be_to_cpu_16(eth_hdr->ether_type); if (ethertype == ETHER_TYPE_VLAN) { struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1); info->l2_len += sizeof(struct vlan_hdr); ethertype = rte_be_to_cpu_16(vlan_hdr->eth_proto); } l3_hdr = (char *)eth_hdr + info->l2_len; if (ethertype == ETHER_TYPE_IPv4) { ipv4_hdr = (struct ipv4_hdr *)l3_hdr; ipv4_hdr->hdr_checksum = 0; ol_flags |= PKT_TX_IPV4; ol_flags |= PKT_TX_IP_CKSUM; info->l3_len = sizeof(struct ipv4_hdr); l4_proto = ipv4_hdr->next_proto_id; } else if (ethertype == ETHER_TYPE_IPv6) { ipv6_hdr = (struct ipv6_hdr *)l3_hdr; info->l3_len = sizeof(struct ipv6_hdr); l4_proto = ipv6_hdr->proto; ol_flags |= PKT_TX_IPV6; } else return 0; /* packet type not supported, nothing to do */ if (l4_proto == IPPROTO_UDP) { udp_hdr = (struct udp_hdr *)((char *)l3_hdr + info->l3_len); ol_flags |= PKT_TX_UDP_CKSUM; udp_hdr->dgram_cksum = get_psd_sum(l3_hdr, ethertype, ol_flags); } else if (l4_proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + info->l3_len); ol_flags |= PKT_TX_TCP_CKSUM; tcp_hdr->cksum = get_psd_sum(l3_hdr, ethertype, ol_flags); if (tso_segsz != 0) { ol_flags |= PKT_TX_TCP_SEG; info->tso_segsz = tso_segsz; info->l4_len = sizeof(struct tcp_hdr); } } else if (l4_proto == IPPROTO_SCTP) { sctp_hdr = (struct sctp_hdr *)((char *)l3_hdr + info->l3_len); sctp_hdr->cksum = 0; ol_flags |= PKT_TX_SCTP_CKSUM; } return ol_flags; } int decapsulation(struct rte_mbuf *pkt) { uint8_t l4_proto = 0; uint16_t outer_header_len; struct udp_hdr *udp_hdr; union tunnel_offload_info info = { .data = 0 }; struct ether_hdr *phdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *); parse_ethernet(phdr, &info, &l4_proto); if (l4_proto != IPPROTO_UDP) return -1; udp_hdr = (struct udp_hdr *)((char *)phdr + info.outer_l2_len + info.outer_l3_len); /** check udp destination port, 4789 is the default vxlan port * (rfc7348) or that the rx offload flag is set (i40e only * currently)*/ if (udp_hdr->dst_port != rte_cpu_to_be_16(DEFAULT_VXLAN_PORT) && #ifdef RTE_NEXT_ABI (pkt->packet_type & RTE_PTYPE_TUNNEL_MASK) == 0) #else (pkt->ol_flags & (PKT_RX_TUNNEL_IPV4_HDR | PKT_RX_TUNNEL_IPV6_HDR)) == 0) #endif return -1; outer_header_len = info.outer_l2_len + info.outer_l3_len + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr); rte_pktmbuf_adj(pkt, outer_header_len); return 0; } void encapsulation(struct rte_mbuf *m, uint8_t queue_id) { uint vport_id; uint64_t ol_flags = 0; uint32_t old_len = m->pkt_len, hash; union tunnel_offload_info tx_offload = { .data = 0 }; struct ether_hdr *phdr = rte_pktmbuf_mtod(m, struct ether_hdr *); /*Allocate space for new ethernet, IPv4, UDP and VXLAN headers*/ struct ether_hdr *pneth = (struct ether_hdr *) rte_pktmbuf_prepend(m, sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)); struct ipv4_hdr *ip = (struct ipv4_hdr *) &pneth[1]; struct udp_hdr *udp = (struct udp_hdr *) &ip[1]; struct vxlan_hdr *vxlan = (struct vxlan_hdr *) &udp[1]; /* convert TX queue ID to vport ID */ vport_id = queue_id - 1; /* replace original Ethernet header with ours */ pneth = rte_memcpy(pneth, &app_l2_hdr[vport_id], sizeof(struct ether_hdr)); /* copy in IP header */ ip = rte_memcpy(ip, &app_ip_hdr[vport_id], sizeof(struct ipv4_hdr)); ip->total_length = rte_cpu_to_be_16(m->data_len - sizeof(struct ether_hdr)); /* outer IP checksum */ ol_flags |= PKT_TX_OUTER_IP_CKSUM; ip->hdr_checksum = 0; /* inner IP checksum offload */ if (tx_checksum) { ol_flags |= process_inner_cksums(phdr, &tx_offload); m->l2_len = tx_offload.l2_len; m->l3_len = tx_offload.l3_len; m->l4_len = tx_offload.l4_len; m->l2_len += ETHER_VXLAN_HLEN; } m->outer_l2_len = sizeof(struct ether_hdr); m->outer_l3_len = sizeof(struct ipv4_hdr); m->ol_flags |= ol_flags; m->tso_segsz = tx_offload.tso_segsz; /*VXLAN HEADER*/ vxlan->vx_flags = rte_cpu_to_be_32(VXLAN_HF_VNI); vxlan->vx_vni = rte_cpu_to_be_32(vxdev.out_key << 8); /*UDP HEADER*/ udp->dgram_cksum = 0; udp->dgram_len = rte_cpu_to_be_16(old_len + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)); udp->dst_port = rte_cpu_to_be_16(vxdev.dst_port); hash = rte_hash_crc(phdr, 2 * ETHER_ADDR_LEN, phdr->ether_type); udp->src_port = rte_cpu_to_be_16((((uint64_t) hash * PORT_RANGE) >> 32) + PORT_MIN); return; } ================================================ FILE: examples/tep_termination/vxlan.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VXLAN_H_ #define _VXLAN_H_ #include #include #define PORT_MIN 49152 #define PORT_MAX 65535 #define PORT_RANGE ((PORT_MAX - PORT_MIN) + 1) #define VXLAN_N_PORTS 2 #define VXLAN_HF_VNI 0x08000000 #define DEFAULT_VXLAN_PORT 4789 extern struct ipv4_hdr app_ip_hdr[VXLAN_N_PORTS]; extern struct ether_hdr app_l2_hdr[VXLAN_N_PORTS]; extern uint8_t tx_checksum; extern uint16_t tso_segsz; struct vxlan_port { uint32_t vport_id; /**< VirtIO port id */ uint32_t peer_ip; /**< remote VTEP IP address */ struct ether_addr peer_mac; /**< remote VTEP MAC address */ struct ether_addr vport_mac; /**< VirtIO port MAC address */ } __rte_cache_aligned; struct vxlan_conf { uint16_t dst_port; /**< VXLAN UDP destination port */ uint32_t port_ip; /**< DPDK port IP address*/ uint32_t in_key; /**< VLAN ID */ uint32_t out_key; /**< VXLAN VNI */ struct vxlan_port port[VXLAN_N_PORTS]; /**< VXLAN configuration */ } __rte_cache_aligned; extern struct vxlan_conf vxdev; /* structure that caches offload info for the current packet */ union tunnel_offload_info { uint64_t data; struct { uint64_t l2_len:7; /**< L2 (MAC) Header Length. */ uint64_t l3_len:9; /**< L3 (IP) Header Length. */ uint64_t l4_len:8; /**< L4 Header Length. */ uint64_t tso_segsz:16; /**< TCP TSO segment size */ uint64_t outer_l2_len:7; /**< outer L2 Header Length */ uint64_t outer_l3_len:16; /**< outer L3 Header Length */ }; } __rte_cache_aligned; int decapsulation(struct rte_mbuf *pkt); void encapsulation(struct rte_mbuf *m, uint8_t queue_id); #endif /* _VXLAN_H_ */ ================================================ FILE: examples/tep_termination/vxlan_setup.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "rte_virtio_net.h" #include "vxlan.h" #include "vxlan_setup.h" #define IPV4_HEADER_LEN 20 #define UDP_HEADER_LEN 8 #define VXLAN_HEADER_LEN 8 #define IP_VERSION 0x40 #define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */ #define IP_DEFTTL 64 /* from RFC 1340. */ #define IP_VHL_DEF (IP_VERSION | IP_HDRLEN) #define IP_DN_FRAGMENT_FLAG 0x0040 /* Used to compare MAC addresses. */ #define MAC_ADDR_CMP 0xFFFFFFFFFFFFULL /* Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 1024 #define RTE_TEST_TX_DESC_DEFAULT 512 /* Default inner VLAN ID */ #define INNER_VLAN_ID 100 /* VXLAN device */ struct vxlan_conf vxdev; struct ipv4_hdr app_ip_hdr[VXLAN_N_PORTS]; struct ether_hdr app_l2_hdr[VXLAN_N_PORTS]; /* local VTEP IP address */ uint8_t vxlan_multicast_ips[2][4] = { {239, 1, 1, 1 }, {239, 1, 2, 1 } }; /* Remote VTEP IP address */ uint8_t vxlan_overlay_ips[2][4] = { {192, 168, 10, 1}, {192, 168, 30, 1} }; /* Remote VTEP MAC address */ uint8_t peer_mac[6] = {0x00, 0x11, 0x01, 0x00, 0x00, 0x01}; /* VXLAN RX filter type */ uint8_t tep_filter_type[] = {RTE_TUNNEL_FILTER_IMAC_TENID, RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID, RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,}; /* Options for configuring ethernet port */ static const struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; /** * The one or two device(s) that belongs to the same tenant ID can * be assigned in a VM. */ const uint16_t tenant_id_conf[] = { 1000, 1000, 1001, 1001, 1002, 1002, 1003, 1003, 1004, 1004, 1005, 1005, 1006, 1006, 1007, 1007, 1008, 1008, 1009, 1009, 1010, 1010, 1011, 1011, 1012, 1012, 1013, 1013, 1014, 1014, 1015, 1015, 1016, 1016, 1017, 1017, 1018, 1018, 1019, 1019, 1020, 1020, 1021, 1021, 1022, 1022, 1023, 1023, 1024, 1024, 1025, 1025, 1026, 1026, 1027, 1027, 1028, 1028, 1029, 1029, 1030, 1030, 1031, 1031, }; /** * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ int vxlan_port_init(uint8_t port, struct rte_mempool *mbuf_pool) { int retval; uint16_t q; struct rte_eth_dev_info dev_info; uint16_t rx_rings, tx_rings = (uint16_t)rte_lcore_count(); const uint16_t rx_ring_size = RTE_TEST_RX_DESC_DEFAULT; const uint16_t tx_ring_size = RTE_TEST_TX_DESC_DEFAULT; struct rte_eth_udp_tunnel tunnel_udp; struct rte_eth_rxconf *rxconf; struct rte_eth_txconf *txconf; struct vxlan_conf *pconf = &vxdev; pconf->dst_port = udp_port; rte_eth_dev_info_get(port, &dev_info); if (dev_info.max_rx_queues > MAX_QUEUES) { rte_exit(EXIT_FAILURE, "please define MAX_QUEUES no less than %u in %s\n", dev_info.max_rx_queues, __FILE__); } rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; txconf->txq_flags = 0; if (port >= rte_eth_dev_count()) return -1; rx_rings = nb_devices; /* Configure ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; /* Setup the queues. */ for (q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, rx_ring_size, rte_eth_dev_socket_id(port), rxconf, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, tx_ring_size, rte_eth_dev_socket_id(port), txconf); if (retval < 0) return retval; } /* Start the device. */ retval = rte_eth_dev_start(port); if (retval < 0) return retval; /* Configure UDP port for UDP tunneling */ tunnel_udp.udp_port = udp_port; tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN; retval = rte_eth_dev_udp_tunnel_add(port, &tunnel_udp); if (retval < 0) return retval; rte_eth_macaddr_get(port, &ports_eth_addr[port]); RTE_LOG(INFO, PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, ports_eth_addr[port].addr_bytes[0], ports_eth_addr[port].addr_bytes[1], ports_eth_addr[port].addr_bytes[2], ports_eth_addr[port].addr_bytes[3], ports_eth_addr[port].addr_bytes[4], ports_eth_addr[port].addr_bytes[5]); if (tso_segsz != 0) { struct rte_eth_dev_info dev_info; rte_eth_dev_info_get(port, &dev_info); if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) RTE_LOG(WARNING, PORT, "hardware TSO offload is not supported\n"); } return 0; } static int vxlan_rx_process(struct rte_mbuf *pkt) { int ret = 0; if (rx_decap) ret = decapsulation(pkt); return ret; } static void vxlan_tx_process(uint8_t queue_id, struct rte_mbuf *pkt) { if (tx_encap) encapsulation(pkt, queue_id); return; } /* * This function learns the MAC address of the device and set init * L2 header and L3 header info. */ int vxlan_link(struct vhost_dev *vdev, struct rte_mbuf *m) { int i, ret; struct ether_hdr *pkt_hdr; struct virtio_net *dev = vdev->dev; uint64_t portid = dev->device_fh; struct ipv4_hdr *ip; struct rte_eth_tunnel_filter_conf tunnel_filter_conf; if (unlikely(portid > VXLAN_N_PORTS)) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: Not configuring device," "as already have %d ports for VXLAN.", dev->device_fh, VXLAN_N_PORTS); return -1; } /* Learn MAC address of guest device from packet */ pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); if (is_same_ether_addr(&(pkt_hdr->s_addr), &vdev->mac_address)) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing" " MAC address and has not been registered.\n", dev->device_fh); return -1; } for (i = 0; i < ETHER_ADDR_LEN; i++) { vdev->mac_address.addr_bytes[i] = vxdev.port[portid].vport_mac.addr_bytes[i] = pkt_hdr->s_addr.addr_bytes[i]; vxdev.port[portid].peer_mac.addr_bytes[i] = peer_mac[i]; } memset(&tunnel_filter_conf, 0, sizeof(struct rte_eth_tunnel_filter_conf)); tunnel_filter_conf.outer_mac = &ports_eth_addr[0]; tunnel_filter_conf.filter_type = tep_filter_type[filter_idx]; /* inner MAC */ tunnel_filter_conf.inner_mac = &vdev->mac_address; tunnel_filter_conf.queue_id = vdev->rx_q; tunnel_filter_conf.tenant_id = tenant_id_conf[vdev->rx_q]; if (tep_filter_type[filter_idx] == RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID) tunnel_filter_conf.inner_vlan = INNER_VLAN_ID; tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN; ret = rte_eth_dev_filter_ctrl(ports[0], RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_ADD, &tunnel_filter_conf); if (ret) { RTE_LOG(ERR, VHOST_DATA, "%d Failed to add device MAC address to cloud filter\n", vdev->rx_q); return -1; } /* Print out inner MAC and VNI info. */ RTE_LOG(INFO, VHOST_DATA, "(%d) MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VNI %d registered\n", vdev->rx_q, vdev->mac_address.addr_bytes[0], vdev->mac_address.addr_bytes[1], vdev->mac_address.addr_bytes[2], vdev->mac_address.addr_bytes[3], vdev->mac_address.addr_bytes[4], vdev->mac_address.addr_bytes[5], tenant_id_conf[vdev->rx_q]); vxdev.port[portid].vport_id = portid; for (i = 0; i < 4; i++) { /* Local VTEP IP */ vxdev.port_ip |= vxlan_multicast_ips[portid][i] << (8 * i); /* Remote VTEP IP */ vxdev.port[portid].peer_ip |= vxlan_overlay_ips[portid][i] << (8 * i); } vxdev.out_key = tenant_id_conf[vdev->rx_q]; ether_addr_copy(&vxdev.port[portid].peer_mac, &app_l2_hdr[portid].d_addr); ether_addr_copy(&ports_eth_addr[0], &app_l2_hdr[portid].s_addr); app_l2_hdr[portid].ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); ip = &app_ip_hdr[portid]; ip->version_ihl = IP_VHL_DEF; ip->type_of_service = 0; ip->total_length = 0; ip->packet_id = 0; ip->fragment_offset = IP_DN_FRAGMENT_FLAG; ip->time_to_live = IP_DEFTTL; ip->next_proto_id = IPPROTO_UDP; ip->hdr_checksum = 0; ip->src_addr = vxdev.port_ip; ip->dst_addr = vxdev.port[portid].peer_ip; /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; return 0; } /** * Removes cloud filter. Ensures that nothing is adding buffers to the RX * queue before disabling RX on the device. */ void vxlan_unlink(struct vhost_dev *vdev) { unsigned i = 0, rx_count; int ret; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct rte_eth_tunnel_filter_conf tunnel_filter_conf; if (vdev->ready == DEVICE_RX) { memset(&tunnel_filter_conf, 0, sizeof(struct rte_eth_tunnel_filter_conf)); tunnel_filter_conf.outer_mac = &ports_eth_addr[0]; tunnel_filter_conf.inner_mac = &vdev->mac_address; tunnel_filter_conf.tenant_id = tenant_id_conf[vdev->rx_q]; tunnel_filter_conf.filter_type = tep_filter_type[filter_idx]; if (tep_filter_type[filter_idx] == RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID) tunnel_filter_conf.inner_vlan = INNER_VLAN_ID; tunnel_filter_conf.queue_id = vdev->rx_q; tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN; ret = rte_eth_dev_filter_ctrl(ports[0], RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_DELETE, &tunnel_filter_conf); if (ret) { RTE_LOG(ERR, VHOST_DATA, "%d Failed to add device MAC address to cloud filter\n", vdev->rx_q); return; } for (i = 0; i < ETHER_ADDR_LEN; i++) vdev->mac_address.addr_bytes[i] = 0; /* Clear out the receive buffers */ rx_count = rte_eth_rx_burst(ports[0], (uint16_t)vdev->rx_q, pkts_burst, MAX_PKT_BURST); while (rx_count) { for (i = 0; i < rx_count; i++) rte_pktmbuf_free(pkts_burst[i]); rx_count = rte_eth_rx_burst(ports[0], (uint16_t)vdev->rx_q, pkts_burst, MAX_PKT_BURST); } vdev->ready = DEVICE_MAC_LEARNING; } } /* Transmit packets after encapsulating */ int vxlan_tx_pkts(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { int ret = 0; uint16_t i; for (i = 0; i < nb_pkts; i++) vxlan_tx_process(queue_id, tx_pkts[i]); ret = rte_eth_tx_burst(port_id, queue_id, tx_pkts, nb_pkts); return ret; } /* Check for decapsulation and pass packets directly to VIRTIO device */ int vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts_burst, uint32_t rx_count) { uint32_t i = 0; uint32_t count = 0; int ret; struct rte_mbuf *pkts_valid[rx_count]; for (i = 0; i < rx_count; i++) { if (enable_stats) { rte_atomic64_add( &dev_statistics[dev->device_fh].rx_bad_ip_csum, (pkts_burst[i]->ol_flags & PKT_RX_IP_CKSUM_BAD) != 0); rte_atomic64_add( &dev_statistics[dev->device_fh].rx_bad_ip_csum, (pkts_burst[i]->ol_flags & PKT_RX_L4_CKSUM_BAD) != 0); } ret = vxlan_rx_process(pkts_burst[i]); if (unlikely(ret < 0)) continue; pkts_valid[count] = pkts_burst[i]; count++; } ret = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ, pkts_valid, count); return ret; } ================================================ FILE: examples/tep_termination/vxlan_setup.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef VXLAN_SETUP_H_ #define VXLAN_SETUP_H_ extern uint16_t nb_devices; extern uint16_t udp_port; extern uint8_t filter_idx; extern uint8_t ports[RTE_MAX_ETHPORTS]; extern struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; extern uint32_t enable_stats; extern struct device_statistics dev_statistics[MAX_DEVICES]; extern uint8_t rx_decap; extern uint8_t tx_encap; typedef int (*ol_port_configure_t)(uint8_t port, struct rte_mempool *mbuf_pool); typedef int (*ol_tunnel_setup_t)(struct vhost_dev *vdev, struct rte_mbuf *m); typedef void (*ol_tunnel_destroy_t)(struct vhost_dev *vdev); typedef int (*ol_tx_handle_t)(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); typedef int (*ol_rx_handle_t)(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count); typedef int (*ol_param_handle)(struct virtio_net *dev); struct ol_switch_ops { ol_port_configure_t port_configure; ol_tunnel_setup_t tunnel_setup; ol_tunnel_destroy_t tunnel_destroy; ol_tx_handle_t tx_handle; ol_rx_handle_t rx_handle; ol_param_handle param_handle; }; int vxlan_port_init(uint8_t port, struct rte_mempool *mbuf_pool); int vxlan_link(struct vhost_dev *vdev, struct rte_mbuf *m); void vxlan_unlink(struct vhost_dev *vdev); int vxlan_tx_pkts(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count); #endif /* VXLAN_SETUP_H_ */ ================================================ FILE: examples/timer/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = timer # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/timer/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */ static struct rte_timer timer0; static struct rte_timer timer1; /* timer0 callback */ static void timer0_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg) { static unsigned counter = 0; unsigned lcore_id = rte_lcore_id(); printf("%s() on lcore %u\n", __func__, lcore_id); /* this timer is automatically reloaded until we decide to * stop it, when counter reaches 20. */ if ((counter ++) == 20) rte_timer_stop(tim); } /* timer1 callback */ static void timer1_cb(__attribute__((unused)) struct rte_timer *tim, __attribute__((unused)) void *arg) { unsigned lcore_id = rte_lcore_id(); uint64_t hz; printf("%s() on lcore %u\n", __func__, lcore_id); /* reload it on another lcore */ hz = rte_get_timer_hz(); lcore_id = rte_get_next_lcore(lcore_id, 0, 1); rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL); } static __attribute__((noreturn)) int lcore_mainloop(__attribute__((unused)) void *arg) { uint64_t prev_tsc = 0, cur_tsc, diff_tsc; unsigned lcore_id; lcore_id = rte_lcore_id(); printf("Starting mainloop on core %u\n", lcore_id); while (1) { /* * Call the timer handler on each core: as we don't * need a very precise timer, so only call * rte_timer_manage() every ~10ms (at 2Ghz). In a real * application, this will enhance performances as * reading the HPET timer is not efficient. */ cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; if (diff_tsc > TIMER_RESOLUTION_CYCLES) { rte_timer_manage(); prev_tsc = cur_tsc; } } } int main(int argc, char **argv) { int ret; uint64_t hz; unsigned lcore_id; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); /* init RTE timer library */ rte_timer_subsystem_init(); /* init timer structures */ rte_timer_init(&timer0); rte_timer_init(&timer1); /* load timer0, every second, on master lcore, reloaded automatically */ hz = rte_get_timer_hz(); lcore_id = rte_lcore_id(); rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL); /* load timer1, every second/3, on next lcore, reloaded manually */ lcore_id = rte_get_next_lcore(lcore_id, 0, 1); rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL); /* call lcore_mainloop() on every slave lcore */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id); } /* call it on master lcore too */ (void) lcore_mainloop(NULL); return 0; } ================================================ FILE: examples/vhost/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: else # binary name APP = vhost-switch # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk endif ================================================ FILE: examples/vhost/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #define MAX_QUEUES 512 /* the maximum number of external ports supported */ #define MAX_SUP_PORTS 1 /* * Calculate the number of buffers needed per port */ #define NUM_MBUFS_PER_PORT ((MAX_QUEUES*RTE_TEST_RX_DESC_DEFAULT) + \ (num_switching_cores*MAX_PKT_BURST) + \ (num_switching_cores*RTE_TEST_TX_DESC_DEFAULT) +\ (num_switching_cores*MBUF_CACHE_SIZE)) #define MBUF_CACHE_SIZE 128 #define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE /* * No frame data buffer allocated from host are required for zero copy * implementation, guest will allocate the frame data buffer, and vhost * directly use it. */ #define VIRTIO_DESCRIPTOR_LEN_ZCP RTE_MBUF_DEFAULT_DATAROOM #define MBUF_DATA_SIZE_ZCP RTE_MBUF_DEFAULT_BUF_SIZE #define MBUF_CACHE_SIZE_ZCP 0 #define MAX_PKT_BURST 32 /* Max burst size for RX/TX */ #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ #define BURST_RX_WAIT_US 15 /* Defines how long we wait between retries on RX */ #define BURST_RX_RETRIES 4 /* Number of retries on RX. */ #define JUMBO_FRAME_MAX_SIZE 0x2600 /* State of virtio device. */ #define DEVICE_MAC_LEARNING 0 #define DEVICE_RX 1 #define DEVICE_SAFE_REMOVE 2 /* Config_core_flag status definitions. */ #define REQUEST_DEV_REMOVAL 1 #define ACK_DEV_REMOVAL 0 /* Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 1024 #define RTE_TEST_TX_DESC_DEFAULT 512 /* * Need refine these 2 macros for legacy and DPDK based front end: * Max vring avail descriptor/entries from guest - MAX_PKT_BURST * And then adjust power 2. */ /* * For legacy front end, 128 descriptors, * half for virtio header, another half for mbuf. */ #define RTE_TEST_RX_DESC_DEFAULT_ZCP 32 /* legacy: 32, DPDK virt FE: 128. */ #define RTE_TEST_TX_DESC_DEFAULT_ZCP 64 /* legacy: 64, DPDK virt FE: 64. */ /* Get first 4 bytes in mbuf headroom. */ #define MBUF_HEADROOM_UINT32(mbuf) (*(uint32_t *)((uint8_t *)(mbuf) \ + sizeof(struct rte_mbuf))) /* true if x is a power of 2 */ #define POWEROF2(x) ((((x)-1) & (x)) == 0) #define INVALID_PORT_ID 0xFF /* Max number of devices. Limited by vmdq. */ #define MAX_DEVICES 64 /* Size of buffers used for snprintfs. */ #define MAX_PRINT_BUFF 6072 /* Maximum character device basename size. */ #define MAX_BASENAME_SZ 10 /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 /* Used to compare MAC addresses. */ #define MAC_ADDR_CMP 0xFFFFFFFFFFFFULL /* Number of descriptors per cacheline. */ #define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc)) #define MBUF_EXT_MEM(mb) (rte_mbuf_from_indirect(mb) != (mb)) /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; /* Promiscuous mode */ static uint32_t promiscuous; /*Number of switching cores enabled*/ static uint32_t num_switching_cores = 0; /* number of devices/queues to support*/ static uint32_t num_queues = 0; static uint32_t num_devices; /* * Enable zero copy, pkts buffer will directly dma to hw descriptor, * disabled on default. */ static uint32_t zero_copy; static int mergeable; /* Do vlan strip on host, enabled on default */ static uint32_t vlan_strip = 1; /* number of descriptors to apply*/ static uint32_t num_rx_descriptor = RTE_TEST_RX_DESC_DEFAULT_ZCP; static uint32_t num_tx_descriptor = RTE_TEST_TX_DESC_DEFAULT_ZCP; /* max ring descriptor, ixgbe, i40e, e1000 all are 4096. */ #define MAX_RING_DESC 4096 struct vpool { struct rte_mempool *pool; struct rte_ring *ring; uint32_t buf_size; } vpool_array[MAX_QUEUES+MAX_QUEUES]; /* Enable VM2VM communications. If this is disabled then the MAC address compare is skipped. */ typedef enum { VM2VM_DISABLED = 0, VM2VM_SOFTWARE = 1, VM2VM_HARDWARE = 2, VM2VM_LAST } vm2vm_type; static vm2vm_type vm2vm_mode = VM2VM_SOFTWARE; /* The type of host physical address translated from guest physical address. */ typedef enum { PHYS_ADDR_CONTINUOUS = 0, PHYS_ADDR_CROSS_SUBREG = 1, PHYS_ADDR_INVALID = 2, PHYS_ADDR_LAST } hpa_type; /* Enable stats. */ static uint32_t enable_stats = 0; /* Enable retries on RX. */ static uint32_t enable_retry = 1; /* Specify timeout (in useconds) between retries on RX. */ static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US; /* Specify the number of retries on RX. */ static uint32_t burst_rx_retry_num = BURST_RX_RETRIES; /* Character device basename. Can be set by user. */ static char dev_basename[MAX_BASENAME_SZ] = "vhost-net"; /* empty vmdq configuration structure. Filled in programatically */ static struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ /* * It is necessary for 1G NIC such as I350, * this fixes bug of ipv4 forwarding in guest can't * forward pakets from one virtio dev to another virtio dev. */ .hw_vlan_strip = 1, /**< VLAN strip enabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .rx_adv_conf = { /* * should be overridden separately in code with * appropriate values */ .vmdq_rx_conf = { .nb_queue_pools = ETH_8_POOLS, .enable_default_pool = 0, .default_pool = 0, .nb_pool_maps = 0, .pool_map = {{0, 0},}, }, }, }; static unsigned lcore_ids[RTE_MAX_LCORE]; static uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned num_ports = 0; /**< The number of ports specified in command line */ static uint16_t num_pf_queues, num_vmdq_queues; static uint16_t vmdq_pool_base, vmdq_queue_base; static uint16_t queues_per_pool; static const uint16_t external_pkt_default_vlan_tag = 2000; const uint16_t vlan_tags[] = { 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, }; /* ethernet addresses of ports */ static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS]; /* heads for the main used and free linked lists for the data path. */ static struct virtio_net_data_ll *ll_root_used = NULL; static struct virtio_net_data_ll *ll_root_free = NULL; /* Array of data core structures containing information on individual core linked lists. */ static struct lcore_info lcore_info[RTE_MAX_LCORE]; /* Used for queueing bursts of TX packets. */ struct mbuf_table { unsigned len; unsigned txq_id; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; /* TX queue for each data core. */ struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE]; /* TX queue fori each virtio device for zero copy. */ struct mbuf_table tx_queue_zcp[MAX_QUEUES]; /* Vlan header struct used to insert vlan tags on TX. */ struct vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; __be16 h_vlan_proto; __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; /* IPv4 Header */ struct ipv4_hdr { uint8_t version_ihl; /**< version and header length */ uint8_t type_of_service; /**< type of service */ uint16_t total_length; /**< length of packet */ uint16_t packet_id; /**< packet ID */ uint16_t fragment_offset; /**< fragmentation offset */ uint8_t time_to_live; /**< time to live */ uint8_t next_proto_id; /**< protocol ID */ uint16_t hdr_checksum; /**< header checksum */ uint32_t src_addr; /**< source address */ uint32_t dst_addr; /**< destination address */ } __attribute__((__packed__)); /* Header lengths. */ #define VLAN_HLEN 4 #define VLAN_ETH_HLEN 18 /* Per-device statistics struct */ struct device_statistics { uint64_t tx_total; rte_atomic64_t rx_total_atomic; uint64_t rx_total; uint64_t tx; rte_atomic64_t rx_atomic; uint64_t rx; } __rte_cache_aligned; struct device_statistics dev_statistics[MAX_DEVICES]; /* * Builds up the correct configuration for VMDQ VLAN pool map * according to the pool & queue limits. */ static inline int get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_devices) { struct rte_eth_vmdq_rx_conf conf; struct rte_eth_vmdq_rx_conf *def_conf = &vmdq_conf_default.rx_adv_conf.vmdq_rx_conf; unsigned i; memset(&conf, 0, sizeof(conf)); conf.nb_queue_pools = (enum rte_eth_nb_pools)num_devices; conf.nb_pool_maps = num_devices; conf.enable_loop_back = def_conf->enable_loop_back; conf.rx_mode = def_conf->rx_mode; for (i = 0; i < conf.nb_pool_maps; i++) { conf.pool_map[i].vlan_id = vlan_tags[ i ]; conf.pool_map[i].pools = (1UL << i); } (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf))); (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_rx_conf, &conf, sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf))); return 0; } /* * Validate the device number according to the max pool number gotten form * dev_info. If the device number is invalid, give the error message and * return -1. Each device must have its own pool. */ static inline int validate_num_devices(uint32_t max_nb_devices) { if (num_devices > max_nb_devices) { RTE_LOG(ERR, VHOST_PORT, "invalid number of devices\n"); return -1; } return 0; } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port) { struct rte_eth_dev_info dev_info; struct rte_eth_conf port_conf; struct rte_eth_rxconf *rxconf; struct rte_eth_txconf *txconf; int16_t rx_rings, tx_rings; uint16_t rx_ring_size, tx_ring_size; int retval; uint16_t q; /* The max pool number from dev_info will be used to validate the pool number specified in cmd line */ rte_eth_dev_info_get (port, &dev_info); if (dev_info.max_rx_queues > MAX_QUEUES) { rte_exit(EXIT_FAILURE, "please define MAX_QUEUES no less than %u in %s\n", dev_info.max_rx_queues, __FILE__); } rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; rxconf->rx_drop_en = 1; /* Enable vlan offload */ txconf->txq_flags &= ~ETH_TXQ_FLAGS_NOVLANOFFL; /* * Zero copy defers queue RX/TX start to the time when guest * finishes its startup and packet buffers from that guest are * available. */ if (zero_copy) { rxconf->rx_deferred_start = 1; rxconf->rx_drop_en = 0; txconf->tx_deferred_start = 1; } /*configure the number of supported virtio devices based on VMDQ limits */ num_devices = dev_info.max_vmdq_pools; if (zero_copy) { rx_ring_size = num_rx_descriptor; tx_ring_size = num_tx_descriptor; tx_rings = dev_info.max_tx_queues; } else { rx_ring_size = RTE_TEST_RX_DESC_DEFAULT; tx_ring_size = RTE_TEST_TX_DESC_DEFAULT; tx_rings = (uint16_t)rte_lcore_count(); } retval = validate_num_devices(MAX_DEVICES); if (retval < 0) return retval; /* Get port configuration. */ retval = get_eth_conf(&port_conf, num_devices); if (retval < 0) return retval; /* NIC queues are divided into pf queues and vmdq queues. */ num_pf_queues = dev_info.max_rx_queues - dev_info.vmdq_queue_num; queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools; num_vmdq_queues = num_devices * queues_per_pool; num_queues = num_pf_queues + num_vmdq_queues; vmdq_queue_base = dev_info.vmdq_queue_base; vmdq_pool_base = dev_info.vmdq_pool_base; printf("pf queue num: %u, configured vmdq pool num: %u, each vmdq pool has %u queues\n", num_pf_queues, num_devices, queues_per_pool); if (port >= rte_eth_dev_count()) return -1; rx_rings = (uint16_t)dev_info.max_rx_queues; /* Configure ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; /* Setup the queues. */ for (q = 0; q < rx_rings; q ++) { retval = rte_eth_rx_queue_setup(port, q, rx_ring_size, rte_eth_dev_socket_id(port), rxconf, vpool_array[q].pool); if (retval < 0) return retval; } for (q = 0; q < tx_rings; q ++) { retval = rte_eth_tx_queue_setup(port, q, tx_ring_size, rte_eth_dev_socket_id(port), txconf); if (retval < 0) return retval; } /* Start the device. */ retval = rte_eth_dev_start(port); if (retval < 0) { RTE_LOG(ERR, VHOST_DATA, "Failed to start the device.\n"); return retval; } if (promiscuous) rte_eth_promiscuous_enable(port); rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]); RTE_LOG(INFO, VHOST_PORT, "Max virtio devices supported: %u\n", num_devices); RTE_LOG(INFO, VHOST_PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, vmdq_ports_eth_addr[port].addr_bytes[0], vmdq_ports_eth_addr[port].addr_bytes[1], vmdq_ports_eth_addr[port].addr_bytes[2], vmdq_ports_eth_addr[port].addr_bytes[3], vmdq_ports_eth_addr[port].addr_bytes[4], vmdq_ports_eth_addr[port].addr_bytes[5]); return 0; } /* * Set character device basename. */ static int us_vhost_parse_basename(const char *q_arg) { /* parse number string */ if (strnlen(q_arg, MAX_BASENAME_SZ) > MAX_BASENAME_SZ) return -1; else snprintf((char*)&dev_basename, MAX_BASENAME_SZ, "%s", q_arg); return 0; } /* * Parse the portmask provided at run time. */ static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; errno = 0; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) return -1; if (pm == 0) return -1; return pm; } /* * Parse num options at run time. */ static int parse_num_opt(const char *q_arg, uint32_t max_valid_value) { char *end = NULL; unsigned long num; errno = 0; /* parse unsigned int string */ num = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) return -1; if (num > max_valid_value) return -1; return num; } /* * Display usage */ static void us_vhost_usage(const char *prgname) { RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK\n" " --vm2vm [0|1|2]\n" " --rx_retry [0|1] --mergeable [0|1] --stats [0-N]\n" " --dev-basename \n" " --nb-devices ND\n" " -p PORTMASK: Set mask for ports to be used by application\n" " --vm2vm [0|1|2]: disable/software(default)/hardware vm2vm comms\n" " --rx-retry [0|1]: disable/enable(default) retries on rx. Enable retry if destintation queue is full\n" " --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n" " --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n" " --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n" " --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n" " --dev-basename: The basename to be used for the character device.\n" " --zero-copy [0|1]: disable(default)/enable rx/tx " "zero copy\n" " --rx-desc-num [0-N]: the number of descriptors on rx, " "used only when zero copy is enabled.\n" " --tx-desc-num [0-N]: the number of descriptors on tx, " "used only when zero copy is enabled.\n", prgname); } /* * Parse the arguments given in the command line of the application. */ static int us_vhost_parse_args(int argc, char **argv) { int opt, ret; int option_index; unsigned i; const char *prgname = argv[0]; static struct option long_option[] = { {"vm2vm", required_argument, NULL, 0}, {"rx-retry", required_argument, NULL, 0}, {"rx-retry-delay", required_argument, NULL, 0}, {"rx-retry-num", required_argument, NULL, 0}, {"mergeable", required_argument, NULL, 0}, {"vlan-strip", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {"dev-basename", required_argument, NULL, 0}, {"zero-copy", required_argument, NULL, 0}, {"rx-desc-num", required_argument, NULL, 0}, {"tx-desc-num", required_argument, NULL, 0}, {NULL, 0, 0, 0}, }; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:P", long_option, &option_index)) != EOF) { switch (opt) { /* Portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid portmask\n"); us_vhost_usage(prgname); return -1; } break; case 'P': promiscuous = 1; vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode = ETH_VMDQ_ACCEPT_BROADCAST | ETH_VMDQ_ACCEPT_MULTICAST; rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX); break; case 0: /* Enable/disable vm2vm comms. */ if (!strncmp(long_option[option_index].name, "vm2vm", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, (VM2VM_LAST - 1)); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for " "vm2vm [0|1|2]\n"); us_vhost_usage(prgname); return -1; } else { vm2vm_mode = (vm2vm_type)ret; } } /* Enable/disable retries on RX. */ if (!strncmp(long_option[option_index].name, "rx-retry", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry [0|1]\n"); us_vhost_usage(prgname); return -1; } else { enable_retry = ret; } } /* Specify the retries delay time (in useconds) on RX. */ if (!strncmp(long_option[option_index].name, "rx-retry-delay", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-delay [0-N]\n"); us_vhost_usage(prgname); return -1; } else { burst_rx_delay_time = ret; } } /* Specify the retries number on RX. */ if (!strncmp(long_option[option_index].name, "rx-retry-num", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-num [0-N]\n"); us_vhost_usage(prgname); return -1; } else { burst_rx_retry_num = ret; } } /* Enable/disable RX mergeable buffers. */ if (!strncmp(long_option[option_index].name, "mergeable", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for mergeable [0|1]\n"); us_vhost_usage(prgname); return -1; } else { mergeable = !!ret; if (ret) { vmdq_conf_default.rxmode.jumbo_frame = 1; vmdq_conf_default.rxmode.max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE; } } } /* Enable/disable RX VLAN strip on host. */ if (!strncmp(long_option[option_index].name, "vlan-strip", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for VLAN strip [0|1]\n"); us_vhost_usage(prgname); return -1; } else { vlan_strip = !!ret; vmdq_conf_default.rxmode.hw_vlan_strip = vlan_strip; } } /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n"); us_vhost_usage(prgname); return -1; } else { enable_stats = ret; } } /* Set character device basename. */ if (!strncmp(long_option[option_index].name, "dev-basename", MAX_LONG_OPT_SZ)) { if (us_vhost_parse_basename(optarg) == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for character device basename (Max %d characters)\n", MAX_BASENAME_SZ); us_vhost_usage(prgname); return -1; } } /* Enable/disable rx/tx zero copy. */ if (!strncmp(long_option[option_index].name, "zero-copy", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument" " for zero-copy [0|1]\n"); us_vhost_usage(prgname); return -1; } else zero_copy = ret; } /* Specify the descriptor number on RX. */ if (!strncmp(long_option[option_index].name, "rx-desc-num", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, MAX_RING_DESC); if ((ret == -1) || (!POWEROF2(ret))) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-desc-num[0-N]," "power of 2 required.\n"); us_vhost_usage(prgname); return -1; } else { num_rx_descriptor = ret; } } /* Specify the descriptor number on TX. */ if (!strncmp(long_option[option_index].name, "tx-desc-num", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, MAX_RING_DESC); if ((ret == -1) || (!POWEROF2(ret))) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tx-desc-num [0-N]," "power of 2 required.\n"); us_vhost_usage(prgname); return -1; } else { num_tx_descriptor = ret; } } break; /* Invalid option - print options. */ default: us_vhost_usage(prgname); return -1; } } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (enabled_port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; } if ((num_ports == 0) || (num_ports > MAX_SUP_PORTS)) { RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u," "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS); return -1; } if ((zero_copy == 1) && (vm2vm_mode == VM2VM_SOFTWARE)) { RTE_LOG(INFO, VHOST_PORT, "Vhost zero copy doesn't support software vm2vm," "please specify 'vm2vm 2' to use hardware vm2vm.\n"); return -1; } if ((zero_copy == 1) && (vmdq_conf_default.rxmode.jumbo_frame == 1)) { RTE_LOG(INFO, VHOST_PORT, "Vhost zero copy doesn't support jumbo frame," "please specify '--mergeable 0' to disable the " "mergeable feature.\n"); return -1; } return 0; } /* * Update the global var NUM_PORTS and array PORTS according to system ports number * and return valid ports number */ static unsigned check_ports_num(unsigned nb_ports) { unsigned valid_num_ports = num_ports; unsigned portid; if (num_ports > nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port number(%u) exceeds total system port number(%u)\n", num_ports, nb_ports); num_ports = nb_ports; } for (portid = 0; portid < num_ports; portid ++) { if (ports[portid] >= nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max system port ID(%u)\n", ports[portid], (nb_ports - 1)); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } } return valid_num_ports; } /* * Macro to print out packet contents. Wrapped in debug define so that the * data path is not effected when debug is disabled. */ #ifdef DEBUG #define PRINT_PACKET(device, addr, size, header) do { \ char *pkt_addr = (char*)(addr); \ unsigned int index; \ char packet[MAX_PRINT_BUFF]; \ \ if ((header)) \ snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Header size %d: ", (device->device_fh), (size)); \ else \ snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Packet size %d: ", (device->device_fh), (size)); \ for (index = 0; index < (size); index++) { \ snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), \ "%02hhx ", pkt_addr[index]); \ } \ snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), "\n"); \ \ LOG_DEBUG(VHOST_DATA, "%s", packet); \ } while(0) #else #define PRINT_PACKET(device, addr, size, header) do{} while(0) #endif /* * Function to convert guest physical addresses to vhost physical addresses. * This is used to convert virtio buffer addresses. */ static inline uint64_t __attribute__((always_inline)) gpa_to_hpa(struct vhost_dev *vdev, uint64_t guest_pa, uint32_t buf_len, hpa_type *addr_type) { struct virtio_memory_regions_hpa *region; uint32_t regionidx; uint64_t vhost_pa = 0; *addr_type = PHYS_ADDR_INVALID; for (regionidx = 0; regionidx < vdev->nregions_hpa; regionidx++) { region = &vdev->regions_hpa[regionidx]; if ((guest_pa >= region->guest_phys_address) && (guest_pa <= region->guest_phys_address_end)) { vhost_pa = region->host_phys_addr_offset + guest_pa; if (likely((guest_pa + buf_len - 1) <= region->guest_phys_address_end)) *addr_type = PHYS_ADDR_CONTINUOUS; else *addr_type = PHYS_ADDR_CROSS_SUBREG; break; } } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") GPA %p| HPA %p\n", vdev->dev->device_fh, (void *)(uintptr_t)guest_pa, (void *)(uintptr_t)vhost_pa); return vhost_pa; } /* * Compares a packet destination MAC address to a device MAC address. */ static inline int __attribute__((always_inline)) ether_addr_cmp(struct ether_addr *ea, struct ether_addr *eb) { return (((*(uint64_t *)ea ^ *(uint64_t *)eb) & MAC_ADDR_CMP) == 0); } /* * This function learns the MAC address of the device and registers this along with a * vlan tag to a VMDQ. */ static int link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m) { struct ether_hdr *pkt_hdr; struct virtio_net_data_ll *dev_ll; struct virtio_net *dev = vdev->dev; int i, ret; /* Learn MAC address of guest device from packet */ pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); dev_ll = ll_root_used; while (dev_ll != NULL) { if (ether_addr_cmp(&(pkt_hdr->s_addr), &dev_ll->vdev->mac_address)) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing MAC address and has not been registered.\n", dev->device_fh); return -1; } dev_ll = dev_ll->next; } for (i = 0; i < ETHER_ADDR_LEN; i++) vdev->mac_address.addr_bytes[i] = pkt_hdr->s_addr.addr_bytes[i]; /* vlan_tag currently uses the device_id. */ vdev->vlan_tag = vlan_tags[dev->device_fh]; /* Print out VMDQ registration info. */ RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n", dev->device_fh, vdev->mac_address.addr_bytes[0], vdev->mac_address.addr_bytes[1], vdev->mac_address.addr_bytes[2], vdev->mac_address.addr_bytes[3], vdev->mac_address.addr_bytes[4], vdev->mac_address.addr_bytes[5], vdev->vlan_tag); /* Register the MAC address. */ ret = rte_eth_dev_mac_addr_add(ports[0], &vdev->mac_address, (uint32_t)dev->device_fh + vmdq_pool_base); if (ret) RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n", dev->device_fh); /* Enable stripping of the vlan tag as we handle routing. */ if (vlan_strip) rte_eth_dev_set_vlan_strip_on_queue(ports[0], (uint16_t)vdev->vmdq_rx_q, 1); /* Set device as ready for RX. */ vdev->ready = DEVICE_RX; return 0; } /* * Removes MAC address and vlan tag from VMDQ. Ensures that nothing is adding buffers to the RX * queue before disabling RX on the device. */ static inline void unlink_vmdq(struct vhost_dev *vdev) { unsigned i = 0; unsigned rx_count; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; if (vdev->ready == DEVICE_RX) { /*clear MAC and VLAN settings*/ rte_eth_dev_mac_addr_remove(ports[0], &vdev->mac_address); for (i = 0; i < 6; i++) vdev->mac_address.addr_bytes[i] = 0; vdev->vlan_tag = 0; /*Clear out the receive buffers*/ rx_count = rte_eth_rx_burst(ports[0], (uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); while (rx_count) { for (i = 0; i < rx_count; i++) rte_pktmbuf_free(pkts_burst[i]); rx_count = rte_eth_rx_burst(ports[0], (uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); } vdev->ready = DEVICE_MAC_LEARNING; } } /* * Check if the packet destination MAC address is for a local device. If so then put * the packet on that devices RX queue. If not then return. */ static inline int __attribute__((always_inline)) virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m) { struct virtio_net_data_ll *dev_ll; struct ether_hdr *pkt_hdr; uint64_t ret = 0; struct virtio_net *dev = vdev->dev; struct virtio_net *tdev; /* destination virito device */ pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); /*get the used devices list*/ dev_ll = ll_root_used; while (dev_ll != NULL) { if ((dev_ll->vdev->ready == DEVICE_RX) && ether_addr_cmp(&(pkt_hdr->d_addr), &dev_ll->vdev->mac_address)) { /* Drop the packet if the TX packet is destined for the TX device. */ if (dev_ll->vdev->dev->device_fh == dev->device_fh) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: Source and destination MAC addresses are the same. Dropping packet.\n", dev->device_fh); return 0; } tdev = dev_ll->vdev->dev; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is local\n", tdev->device_fh); if (unlikely(dev_ll->vdev->remove)) { /*drop the packet if the device is marked for removal*/ LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Device is marked for removal\n", tdev->device_fh); } else { /*send the packet to the local virtio device*/ ret = rte_vhost_enqueue_burst(tdev, VIRTIO_RXQ, &m, 1); if (enable_stats) { rte_atomic64_add( &dev_statistics[tdev->device_fh].rx_total_atomic, 1); rte_atomic64_add( &dev_statistics[tdev->device_fh].rx_atomic, ret); dev_statistics[tdev->device_fh].tx_total++; dev_statistics[tdev->device_fh].tx += ret; } } return 0; } dev_ll = dev_ll->next; } return -1; } /* * Check if the destination MAC of a packet is one local VM, * and get its vlan tag, and offset if it is. */ static inline int __attribute__((always_inline)) find_local_dest(struct virtio_net *dev, struct rte_mbuf *m, uint32_t *offset, uint16_t *vlan_tag) { struct virtio_net_data_ll *dev_ll = ll_root_used; struct ether_hdr *pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); while (dev_ll != NULL) { if ((dev_ll->vdev->ready == DEVICE_RX) && ether_addr_cmp(&(pkt_hdr->d_addr), &dev_ll->vdev->mac_address)) { /* * Drop the packet if the TX packet is * destined for the TX device. */ if (dev_ll->vdev->dev->device_fh == dev->device_fh) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: Source and destination" " MAC addresses are the same. Dropping " "packet.\n", dev_ll->vdev->dev->device_fh); return -1; } /* * HW vlan strip will reduce the packet length * by minus length of vlan tag, so need restore * the packet length by plus it. */ *offset = VLAN_HLEN; *vlan_tag = (uint16_t) vlan_tags[(uint16_t)dev_ll->vdev->dev->device_fh]; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: pkt to local VM device id:" "(%"PRIu64") vlan tag: %d.\n", dev->device_fh, dev_ll->vdev->dev->device_fh, (int)*vlan_tag); break; } dev_ll = dev_ll->next; } return 0; } /* * This function routes the TX packet to the correct interface. This may be a local device * or the physical port. */ static inline void __attribute__((always_inline)) virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) { struct mbuf_table *tx_q; struct rte_mbuf **m_table; unsigned len, ret, offset = 0; const uint16_t lcore_id = rte_lcore_id(); struct virtio_net *dev = vdev->dev; struct ether_hdr *nh; /*check if destination is local VM*/ if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) { rte_pktmbuf_free(m); return; } if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { if (unlikely(find_local_dest(dev, m, &offset, &vlan_tag) != 0)) { rte_pktmbuf_free(m); return; } } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n", dev->device_fh); /*Add packet to the port tx queue*/ tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; nh = rte_pktmbuf_mtod(m, struct ether_hdr *); if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) { /* Guest has inserted the vlan tag. */ struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1); uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag); if ((vm2vm_mode == VM2VM_HARDWARE) && (vh->vlan_tci != vlan_tag_be)) vh->vlan_tci = vlan_tag_be; } else { m->ol_flags = PKT_TX_VLAN_PKT; /* * Find the right seg to adjust the data len when offset is * bigger than tail room size. */ if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) { if (likely(offset <= rte_pktmbuf_tailroom(m))) m->data_len += offset; else { struct rte_mbuf *seg = m; while ((seg->next != NULL) && (offset > rte_pktmbuf_tailroom(seg))) seg = seg->next; seg->data_len += offset; } m->pkt_len += offset; } m->vlan_tci = vlan_tag; } tx_q->m_table[len] = m; len++; if (enable_stats) { dev_statistics[dev->device_fh].tx_total++; dev_statistics[dev->device_fh].tx++; } if (unlikely(len == MAX_PKT_BURST)) { m_table = (struct rte_mbuf **)tx_q->m_table; ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t) len); /* Free any buffers not handled by TX and update the port stats. */ if (unlikely(ret < len)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < len); } len = 0; } tx_q->len = len; return; } /* * This function is called by each data core. It handles all RX/TX registered with the * core. For TX the specific lcore linked list is used. For RX, MAC addresses are compared * with all devices in the main linked list. */ static int switch_worker(__attribute__((unused)) void *arg) { struct rte_mempool *mbuf_pool = arg; struct virtio_net *dev = NULL; struct vhost_dev *vdev = NULL; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct virtio_net_data_ll *dev_ll; struct mbuf_table *tx_q; volatile struct lcore_ll_info *lcore_ll; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0; unsigned ret, i; const uint16_t lcore_id = rte_lcore_id(); const uint16_t num_cores = (uint16_t)rte_lcore_count(); uint16_t rx_count = 0; uint16_t tx_count; uint32_t retry = 0; RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id); lcore_ll = lcore_info[lcore_id].lcore_ll; prev_tsc = 0; tx_q = &lcore_tx_queue[lcore_id]; for (i = 0; i < num_cores; i ++) { if (lcore_ids[i] == lcore_id) { tx_q->txq_id = i; break; } } while(1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { if (tx_q->len) { LOG_DEBUG(VHOST_DATA, "TX queue drained after timeout with burst size %u \n", tx_q->len); /*Tx any packets in the queue*/ ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, (struct rte_mbuf **)tx_q->m_table, (uint16_t)tx_q->len); if (unlikely(ret < tx_q->len)) { do { rte_pktmbuf_free(tx_q->m_table[ret]); } while (++ret < tx_q->len); } tx_q->len = 0; } prev_tsc = cur_tsc; } rte_prefetch0(lcore_ll->ll_root_used); /* * Inform the configuration core that we have exited the linked list and that no devices are * in use if requested. */ if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL) lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; /* * Process devices */ dev_ll = lcore_ll->ll_root_used; while (dev_ll != NULL) { /*get virtio device ID*/ vdev = dev_ll->vdev; dev = vdev->dev; if (unlikely(vdev->remove)) { dev_ll = dev_ll->next; unlink_vmdq(vdev); vdev->ready = DEVICE_SAFE_REMOVE; continue; } if (likely(vdev->ready == DEVICE_RX)) { /*Handle guest RX*/ rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); if (rx_count) { /* * Retry is enabled and the queue is full then we wait and retry to avoid packet loss * Here MAX_PKT_BURST must be less than virtio queue size */ if (enable_retry && unlikely(rx_count > rte_vring_available_entries(dev, VIRTIO_RXQ))) { for (retry = 0; retry < burst_rx_retry_num; retry++) { rte_delay_us(burst_rx_delay_time); if (rx_count <= rte_vring_available_entries(dev, VIRTIO_RXQ)) break; } } ret_count = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ, pkts_burst, rx_count); if (enable_stats) { rte_atomic64_add( &dev_statistics[dev_ll->vdev->dev->device_fh].rx_total_atomic, rx_count); rte_atomic64_add( &dev_statistics[dev_ll->vdev->dev->device_fh].rx_atomic, ret_count); } while (likely(rx_count)) { rx_count--; rte_pktmbuf_free(pkts_burst[rx_count]); } } } if (likely(!vdev->remove)) { /* Handle guest TX*/ tx_count = rte_vhost_dequeue_burst(dev, VIRTIO_TXQ, mbuf_pool, pkts_burst, MAX_PKT_BURST); /* If this is the first received packet we need to learn the MAC and setup VMDQ */ if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && tx_count) { if (vdev->remove || (link_vmdq(vdev, pkts_burst[0]) == -1)) { while (tx_count) rte_pktmbuf_free(pkts_burst[--tx_count]); } } while (tx_count) virtio_tx_route(vdev, pkts_burst[--tx_count], (uint16_t)dev->device_fh); } /*move to the next device in the list*/ dev_ll = dev_ll->next; } } return 0; } /* * This function gets available ring number for zero copy rx. * Only one thread will call this funciton for a paticular virtio device, * so, it is designed as non-thread-safe function. */ static inline uint32_t __attribute__((always_inline)) get_available_ring_num_zcp(struct virtio_net *dev) { struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_RXQ]; uint16_t avail_idx; avail_idx = *((volatile uint16_t *)&vq->avail->idx); return (uint32_t)(avail_idx - vq->last_used_idx_res); } /* * This function gets available ring index for zero copy rx, * it will retry 'burst_rx_retry_num' times till it get enough ring index. * Only one thread will call this funciton for a paticular virtio device, * so, it is designed as non-thread-safe function. */ static inline uint32_t __attribute__((always_inline)) get_available_ring_index_zcp(struct virtio_net *dev, uint16_t *res_base_idx, uint32_t count) { struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_RXQ]; uint16_t avail_idx; uint32_t retry = 0; uint16_t free_entries; *res_base_idx = vq->last_used_idx_res; avail_idx = *((volatile uint16_t *)&vq->avail->idx); free_entries = (avail_idx - *res_base_idx); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in get_available_ring_index_zcp: " "avail idx: %d, " "res base idx:%d, free entries:%d\n", dev->device_fh, avail_idx, *res_base_idx, free_entries); /* * If retry is enabled and the queue is full then we wait * and retry to avoid packet loss. */ if (enable_retry && unlikely(count > free_entries)) { for (retry = 0; retry < burst_rx_retry_num; retry++) { rte_delay_us(burst_rx_delay_time); avail_idx = *((volatile uint16_t *)&vq->avail->idx); free_entries = (avail_idx - *res_base_idx); if (count <= free_entries) break; } } /*check that we have enough buffers*/ if (unlikely(count > free_entries)) count = free_entries; if (unlikely(count == 0)) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Fail in get_available_ring_index_zcp: " "avail idx: %d, res base idx:%d, free entries:%d\n", dev->device_fh, avail_idx, *res_base_idx, free_entries); return 0; } vq->last_used_idx_res = *res_base_idx + count; return count; } /* * This function put descriptor back to used list. */ static inline void __attribute__((always_inline)) put_desc_to_used_list_zcp(struct vhost_virtqueue *vq, uint16_t desc_idx) { uint16_t res_cur_idx = vq->last_used_idx; vq->used->ring[res_cur_idx & (vq->size - 1)].id = (uint32_t)desc_idx; vq->used->ring[res_cur_idx & (vq->size - 1)].len = 0; rte_compiler_barrier(); *(volatile uint16_t *)&vq->used->idx += 1; vq->last_used_idx += 1; /* Kick the guest if necessary. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); } /* * This function get available descriptor from vitio vring and un-attached mbuf * from vpool->ring, and then attach them together. It needs adjust the offset * for buff_addr and phys_addr accroding to PMD implementation, otherwise the * frame data may be put to wrong location in mbuf. */ static inline void __attribute__((always_inline)) attach_rxmbuf_zcp(struct virtio_net *dev) { uint16_t res_base_idx, desc_idx; uint64_t buff_addr, phys_addr; struct vhost_virtqueue *vq; struct vring_desc *desc; struct rte_mbuf *mbuf = NULL; struct vpool *vpool; hpa_type addr_type; struct vhost_dev *vdev = (struct vhost_dev *)dev->priv; vpool = &vpool_array[vdev->vmdq_rx_q]; vq = dev->virtqueue[VIRTIO_RXQ]; do { if (unlikely(get_available_ring_index_zcp(vdev->dev, &res_base_idx, 1) != 1)) return; desc_idx = vq->avail->ring[(res_base_idx) & (vq->size - 1)]; desc = &vq->desc[desc_idx]; if (desc->flags & VRING_DESC_F_NEXT) { desc = &vq->desc[desc->next]; buff_addr = gpa_to_vva(dev, desc->addr); phys_addr = gpa_to_hpa(vdev, desc->addr, desc->len, &addr_type); } else { buff_addr = gpa_to_vva(dev, desc->addr + vq->vhost_hlen); phys_addr = gpa_to_hpa(vdev, desc->addr + vq->vhost_hlen, desc->len, &addr_type); } if (unlikely(addr_type == PHYS_ADDR_INVALID)) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Invalid frame buffer" " address found when attaching RX frame buffer" " address!\n", dev->device_fh); put_desc_to_used_list_zcp(vq, desc_idx); continue; } /* * Check if the frame buffer address from guest crosses * sub-region or not. */ if (unlikely(addr_type == PHYS_ADDR_CROSS_SUBREG)) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Frame buffer address cross " "sub-regioin found when attaching RX frame " "buffer address!\n", dev->device_fh); put_desc_to_used_list_zcp(vq, desc_idx); continue; } } while (unlikely(phys_addr == 0)); rte_ring_sc_dequeue(vpool->ring, (void **)&mbuf); if (unlikely(mbuf == NULL)) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in attach_rxmbuf_zcp: " "ring_sc_dequeue fail.\n", dev->device_fh); put_desc_to_used_list_zcp(vq, desc_idx); return; } if (unlikely(vpool->buf_size > desc->len)) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in attach_rxmbuf_zcp: frame buffer " "length(%d) of descriptor idx: %d less than room " "size required: %d\n", dev->device_fh, desc->len, desc_idx, vpool->buf_size); put_desc_to_used_list_zcp(vq, desc_idx); rte_ring_sp_enqueue(vpool->ring, (void *)mbuf); return; } mbuf->buf_addr = (void *)(uintptr_t)(buff_addr - RTE_PKTMBUF_HEADROOM); mbuf->data_off = RTE_PKTMBUF_HEADROOM; mbuf->buf_physaddr = phys_addr - RTE_PKTMBUF_HEADROOM; mbuf->data_len = desc->len; MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in attach_rxmbuf_zcp: res base idx:%d, " "descriptor idx:%d\n", dev->device_fh, res_base_idx, desc_idx); __rte_mbuf_raw_free(mbuf); return; } /* * Detach an attched packet mbuf - * - restore original mbuf address and length values. * - reset pktmbuf data and data_len to their default values. * All other fields of the given packet mbuf will be left intact. * * @param m * The attached packet mbuf. */ static inline void pktmbuf_detach_zcp(struct rte_mbuf *m) { const struct rte_mempool *mp = m->pool; void *buf = rte_mbuf_to_baddr(m); uint32_t buf_ofs; uint32_t buf_len = mp->elt_size - sizeof(*m); m->buf_physaddr = rte_mempool_virt2phy(mp, m) + sizeof(*m); m->buf_addr = buf; m->buf_len = (uint16_t)buf_len; buf_ofs = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ? RTE_PKTMBUF_HEADROOM : m->buf_len; m->data_off = buf_ofs; m->data_len = 0; } /* * This function is called after packets have been transimited. It fetchs mbuf * from vpool->pool, detached it and put into vpool->ring. It also update the * used index and kick the guest if necessary. */ static inline uint32_t __attribute__((always_inline)) txmbuf_clean_zcp(struct virtio_net *dev, struct vpool *vpool) { struct rte_mbuf *mbuf; struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_TXQ]; uint32_t used_idx = vq->last_used_idx & (vq->size - 1); uint32_t index = 0; uint32_t mbuf_count = rte_mempool_count(vpool->pool); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in mempool before " "clean is: %d\n", dev->device_fh, mbuf_count); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in ring before " "clean is : %d\n", dev->device_fh, rte_ring_count(vpool->ring)); for (index = 0; index < mbuf_count; index++) { mbuf = __rte_mbuf_raw_alloc(vpool->pool); if (likely(MBUF_EXT_MEM(mbuf))) pktmbuf_detach_zcp(mbuf); rte_ring_sp_enqueue(vpool->ring, mbuf); /* Update used index buffer information. */ vq->used->ring[used_idx].id = MBUF_HEADROOM_UINT32(mbuf); vq->used->ring[used_idx].len = 0; used_idx = (used_idx + 1) & (vq->size - 1); } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in mempool after " "clean is: %d\n", dev->device_fh, rte_mempool_count(vpool->pool)); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: mbuf count in ring after " "clean is : %d\n", dev->device_fh, rte_ring_count(vpool->ring)); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: before updated " "vq->last_used_idx:%d\n", dev->device_fh, vq->last_used_idx); vq->last_used_idx += mbuf_count; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in txmbuf_clean_zcp: after updated " "vq->last_used_idx:%d\n", dev->device_fh, vq->last_used_idx); rte_compiler_barrier(); *(volatile uint16_t *)&vq->used->idx += mbuf_count; /* Kick guest if required. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); return 0; } /* * This function is called when a virtio device is destroy. * It fetchs mbuf from vpool->pool, and detached it, and put into vpool->ring. */ static void mbuf_destroy_zcp(struct vpool *vpool) { struct rte_mbuf *mbuf = NULL; uint32_t index, mbuf_count = rte_mempool_count(vpool->pool); LOG_DEBUG(VHOST_CONFIG, "in mbuf_destroy_zcp: mbuf count in mempool before " "mbuf_destroy_zcp is: %d\n", mbuf_count); LOG_DEBUG(VHOST_CONFIG, "in mbuf_destroy_zcp: mbuf count in ring before " "mbuf_destroy_zcp is : %d\n", rte_ring_count(vpool->ring)); for (index = 0; index < mbuf_count; index++) { mbuf = __rte_mbuf_raw_alloc(vpool->pool); if (likely(mbuf != NULL)) { if (likely(MBUF_EXT_MEM(mbuf))) pktmbuf_detach_zcp(mbuf); rte_ring_sp_enqueue(vpool->ring, (void *)mbuf); } } LOG_DEBUG(VHOST_CONFIG, "in mbuf_destroy_zcp: mbuf count in mempool after " "mbuf_destroy_zcp is: %d\n", rte_mempool_count(vpool->pool)); LOG_DEBUG(VHOST_CONFIG, "in mbuf_destroy_zcp: mbuf count in ring after " "mbuf_destroy_zcp is : %d\n", rte_ring_count(vpool->ring)); } /* * This function update the use flag and counter. */ static inline uint32_t __attribute__((always_inline)) virtio_dev_rx_zcp(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count) { struct vhost_virtqueue *vq; struct vring_desc *desc; struct rte_mbuf *buff; /* The virtio_hdr is initialised to 0. */ struct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0, 0, 0, 0, 0, 0}, 0}; uint64_t buff_hdr_addr = 0; uint32_t head[MAX_PKT_BURST], packet_len = 0; uint32_t head_idx, packet_success = 0; uint16_t res_cur_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh); if (count == 0) return 0; vq = dev->virtqueue[VIRTIO_RXQ]; count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; res_cur_idx = vq->last_used_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| End Index %d\n", dev->device_fh, res_cur_idx, res_cur_idx + count); /* Retrieve all of the head indexes first to avoid caching issues. */ for (head_idx = 0; head_idx < count; head_idx++) head[head_idx] = MBUF_HEADROOM_UINT32(pkts[head_idx]); /*Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); while (packet_success != count) { /* Get descriptor from available ring */ desc = &vq->desc[head[packet_success]]; buff = pkts[packet_success]; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in dev_rx_zcp: update the used idx for " "pkt[%d] descriptor idx: %d\n", dev->device_fh, packet_success, MBUF_HEADROOM_UINT32(buff)); PRINT_PACKET(dev, (uintptr_t)(((uint64_t)(uintptr_t)buff->buf_addr) + RTE_PKTMBUF_HEADROOM), rte_pktmbuf_data_len(buff), 0); /* Buffer address translation for virtio header. */ buff_hdr_addr = gpa_to_vva(dev, desc->addr); packet_len = rte_pktmbuf_data_len(buff) + vq->vhost_hlen; /* * If the descriptors are chained the header and data are * placed in separate buffers. */ if (desc->flags & VRING_DESC_F_NEXT) { desc->len = vq->vhost_hlen; desc = &vq->desc[desc->next]; desc->len = rte_pktmbuf_data_len(buff); } else { desc->len = packet_len; } /* Update used ring with desc information */ vq->used->ring[res_cur_idx & (vq->size - 1)].id = head[packet_success]; vq->used->ring[res_cur_idx & (vq->size - 1)].len = packet_len; res_cur_idx++; packet_success++; /* A header is required per buffer. */ rte_memcpy((void *)(uintptr_t)buff_hdr_addr, (const void *)&virtio_hdr, vq->vhost_hlen); PRINT_PACKET(dev, (uintptr_t)buff_hdr_addr, vq->vhost_hlen, 1); if (likely(packet_success < count)) { /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); } } rte_compiler_barrier(); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in dev_rx_zcp: before update used idx: " "vq.last_used_idx: %d, vq->used->idx: %d\n", dev->device_fh, vq->last_used_idx, vq->used->idx); *(volatile uint16_t *)&vq->used->idx += count; vq->last_used_idx += count; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in dev_rx_zcp: after update used idx: " "vq.last_used_idx: %d, vq->used->idx: %d\n", dev->device_fh, vq->last_used_idx, vq->used->idx); /* Kick the guest if necessary. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); return count; } /* * This function routes the TX packet to the correct interface. * This may be a local device or the physical port. */ static inline void __attribute__((always_inline)) virtio_tx_route_zcp(struct virtio_net *dev, struct rte_mbuf *m, uint32_t desc_idx, uint8_t need_copy) { struct mbuf_table *tx_q; struct rte_mbuf **m_table; struct rte_mbuf *mbuf = NULL; unsigned len, ret, offset = 0; struct vpool *vpool; uint16_t vlan_tag = (uint16_t)vlan_tags[(uint16_t)dev->device_fh]; uint16_t vmdq_rx_q = ((struct vhost_dev *)dev->priv)->vmdq_rx_q; /*Add packet to the port tx queue*/ tx_q = &tx_queue_zcp[vmdq_rx_q]; len = tx_q->len; /* Allocate an mbuf and populate the structure. */ vpool = &vpool_array[MAX_QUEUES + vmdq_rx_q]; rte_ring_sc_dequeue(vpool->ring, (void **)&mbuf); if (unlikely(mbuf == NULL)) { struct vhost_virtqueue *vq = dev->virtqueue[VIRTIO_TXQ]; RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to allocate memory for mbuf.\n", dev->device_fh); put_desc_to_used_list_zcp(vq, desc_idx); return; } if (vm2vm_mode == VM2VM_HARDWARE) { /* Avoid using a vlan tag from any vm for external pkt, such as * vlan_tags[dev->device_fh], oterwise, it conflicts when pool * selection, MAC address determines it as an external pkt * which should go to network, while vlan tag determine it as * a vm2vm pkt should forward to another vm. Hardware confuse * such a ambiguous situation, so pkt will lost. */ vlan_tag = external_pkt_default_vlan_tag; if (find_local_dest(dev, m, &offset, &vlan_tag) != 0) { MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx; __rte_mbuf_raw_free(mbuf); return; } } mbuf->nb_segs = m->nb_segs; mbuf->next = m->next; mbuf->data_len = m->data_len + offset; mbuf->pkt_len = mbuf->data_len; if (unlikely(need_copy)) { /* Copy the packet contents to the mbuf. */ rte_memcpy(rte_pktmbuf_mtod(mbuf, void *), rte_pktmbuf_mtod(m, void *), m->data_len); } else { mbuf->data_off = m->data_off; mbuf->buf_physaddr = m->buf_physaddr; mbuf->buf_addr = m->buf_addr; } mbuf->ol_flags = PKT_TX_VLAN_PKT; mbuf->vlan_tci = vlan_tag; mbuf->l2_len = sizeof(struct ether_hdr); mbuf->l3_len = sizeof(struct ipv4_hdr); MBUF_HEADROOM_UINT32(mbuf) = (uint32_t)desc_idx; tx_q->m_table[len] = mbuf; len++; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") in tx_route_zcp: pkt: nb_seg: %d, next:%s\n", dev->device_fh, mbuf->nb_segs, (mbuf->next == NULL) ? "null" : "non-null"); if (enable_stats) { dev_statistics[dev->device_fh].tx_total++; dev_statistics[dev->device_fh].tx++; } if (unlikely(len == MAX_PKT_BURST)) { m_table = (struct rte_mbuf **)tx_q->m_table; ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t) len); /* * Free any buffers not handled by TX and update * the port stats. */ if (unlikely(ret < len)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < len); } len = 0; txmbuf_clean_zcp(dev, vpool); } tx_q->len = len; return; } /* * This function TX all available packets in virtio TX queue for one * virtio-net device. If it is first packet, it learns MAC address and * setup VMDQ. */ static inline void __attribute__((always_inline)) virtio_dev_tx_zcp(struct virtio_net *dev) { struct rte_mbuf m; struct vhost_virtqueue *vq; struct vring_desc *desc; uint64_t buff_addr = 0, phys_addr; uint32_t head[MAX_PKT_BURST]; uint32_t i; uint16_t free_entries, packet_success = 0; uint16_t avail_idx; uint8_t need_copy = 0; hpa_type addr_type; struct vhost_dev *vdev = (struct vhost_dev *)dev->priv; vq = dev->virtqueue[VIRTIO_TXQ]; avail_idx = *((volatile uint16_t *)&vq->avail->idx); /* If there are no available buffers then return. */ if (vq->last_used_idx_res == avail_idx) return; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_tx()\n", dev->device_fh); /* Prefetch available ring to retrieve head indexes. */ rte_prefetch0(&vq->avail->ring[vq->last_used_idx_res & (vq->size - 1)]); /* Get the number of free entries in the ring */ free_entries = (avail_idx - vq->last_used_idx_res); /* Limit to MAX_PKT_BURST. */ free_entries = (free_entries > MAX_PKT_BURST) ? MAX_PKT_BURST : free_entries; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Buffers available %d\n", dev->device_fh, free_entries); /* Retrieve all of the head indexes first to avoid caching issues. */ for (i = 0; i < free_entries; i++) head[i] = vq->avail->ring[(vq->last_used_idx_res + i) & (vq->size - 1)]; vq->last_used_idx_res += free_entries; /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); rte_prefetch0(&vq->used->ring[vq->last_used_idx & (vq->size - 1)]); while (packet_success < free_entries) { desc = &vq->desc[head[packet_success]]; /* Discard first buffer as it is the virtio header */ desc = &vq->desc[desc->next]; /* Buffer address translation. */ buff_addr = gpa_to_vva(dev, desc->addr); /* Need check extra VLAN_HLEN size for inserting VLAN tag */ phys_addr = gpa_to_hpa(vdev, desc->addr, desc->len + VLAN_HLEN, &addr_type); if (likely(packet_success < (free_entries - 1))) /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success + 1]]); if (unlikely(addr_type == PHYS_ADDR_INVALID)) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Invalid frame buffer address found" "when TX packets!\n", dev->device_fh); packet_success++; continue; } /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)buff_addr); /* * Setup dummy mbuf. This is copied to a real mbuf if * transmitted out the physical port. */ m.data_len = desc->len; m.nb_segs = 1; m.next = NULL; m.data_off = 0; m.buf_addr = (void *)(uintptr_t)buff_addr; m.buf_physaddr = phys_addr; /* * Check if the frame buffer address from guest crosses * sub-region or not. */ if (unlikely(addr_type == PHYS_ADDR_CROSS_SUBREG)) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Frame buffer address cross " "sub-regioin found when attaching TX frame " "buffer address!\n", dev->device_fh); need_copy = 1; } else need_copy = 0; PRINT_PACKET(dev, (uintptr_t)buff_addr, desc->len, 0); /* * If this is the first received packet we need to learn * the MAC and setup VMDQ */ if (unlikely(vdev->ready == DEVICE_MAC_LEARNING)) { if (vdev->remove || (link_vmdq(vdev, &m) == -1)) { /* * Discard frame if device is scheduled for * removal or a duplicate MAC address is found. */ packet_success += free_entries; vq->last_used_idx += packet_success; break; } } virtio_tx_route_zcp(dev, &m, head[packet_success], need_copy); packet_success++; } } /* * This function is called by each data core. It handles all RX/TX registered * with the core. For TX the specific lcore linked list is used. For RX, MAC * addresses are compared with all devices in the main linked list. */ static int switch_worker_zcp(__attribute__((unused)) void *arg) { struct virtio_net *dev = NULL; struct vhost_dev *vdev = NULL; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct virtio_net_data_ll *dev_ll; struct mbuf_table *tx_q; volatile struct lcore_ll_info *lcore_ll; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0; unsigned ret; const uint16_t lcore_id = rte_lcore_id(); uint16_t count_in_ring, rx_count = 0; RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id); lcore_ll = lcore_info[lcore_id].lcore_ll; prev_tsc = 0; while (1) { cur_tsc = rte_rdtsc(); /* TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { /* * Get mbuf from vpool.pool and detach mbuf and * put back into vpool.ring. */ dev_ll = lcore_ll->ll_root_used; while ((dev_ll != NULL) && (dev_ll->vdev != NULL)) { /* Get virtio device ID */ vdev = dev_ll->vdev; dev = vdev->dev; if (likely(!vdev->remove)) { tx_q = &tx_queue_zcp[(uint16_t)vdev->vmdq_rx_q]; if (tx_q->len) { LOG_DEBUG(VHOST_DATA, "TX queue drained after timeout" " with burst size %u\n", tx_q->len); /* * Tx any packets in the queue */ ret = rte_eth_tx_burst( ports[0], (uint16_t)tx_q->txq_id, (struct rte_mbuf **) tx_q->m_table, (uint16_t)tx_q->len); if (unlikely(ret < tx_q->len)) { do { rte_pktmbuf_free( tx_q->m_table[ret]); } while (++ret < tx_q->len); } tx_q->len = 0; txmbuf_clean_zcp(dev, &vpool_array[MAX_QUEUES+vdev->vmdq_rx_q]); } } dev_ll = dev_ll->next; } prev_tsc = cur_tsc; } rte_prefetch0(lcore_ll->ll_root_used); /* * Inform the configuration core that we have exited the linked * list and that no devices are in use if requested. */ if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL) lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; /* Process devices */ dev_ll = lcore_ll->ll_root_used; while ((dev_ll != NULL) && (dev_ll->vdev != NULL)) { vdev = dev_ll->vdev; dev = vdev->dev; if (unlikely(vdev->remove)) { dev_ll = dev_ll->next; unlink_vmdq(vdev); vdev->ready = DEVICE_SAFE_REMOVE; continue; } if (likely(vdev->ready == DEVICE_RX)) { uint32_t index = vdev->vmdq_rx_q; uint16_t i; count_in_ring = rte_ring_count(vpool_array[index].ring); uint16_t free_entries = (uint16_t)get_available_ring_num_zcp(dev); /* * Attach all mbufs in vpool.ring and put back * into vpool.pool. */ for (i = 0; i < RTE_MIN(free_entries, RTE_MIN(count_in_ring, MAX_PKT_BURST)); i++) attach_rxmbuf_zcp(dev); /* Handle guest RX */ rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); if (rx_count) { ret_count = virtio_dev_rx_zcp(dev, pkts_burst, rx_count); if (enable_stats) { dev_statistics[dev->device_fh].rx_total += rx_count; dev_statistics[dev->device_fh].rx += ret_count; } while (likely(rx_count)) { rx_count--; pktmbuf_detach_zcp( pkts_burst[rx_count]); rte_ring_sp_enqueue( vpool_array[index].ring, (void *)pkts_burst[rx_count]); } } } if (likely(!vdev->remove)) /* Handle guest TX */ virtio_dev_tx_zcp(dev); /* Move to the next device in the list */ dev_ll = dev_ll->next; } } return 0; } /* * Add an entry to a used linked list. A free entry must first be found * in the free linked list using get_data_ll_free_entry(); */ static void add_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll = *ll_root_addr; /* Set next as NULL and use a compiler barrier to avoid reordering. */ ll_dev->next = NULL; rte_compiler_barrier(); /* If ll == NULL then this is the first device. */ if (ll) { /* Increment to the tail of the linked list. */ while ((ll->next != NULL) ) ll = ll->next; ll->next = ll_dev; } else { *ll_root_addr = ll_dev; } } /* * Remove an entry from a used linked list. The entry must then be added to * the free linked list using put_data_ll_free_entry(). */ static void rm_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev, struct virtio_net_data_ll *ll_dev_last) { struct virtio_net_data_ll *ll = *ll_root_addr; if (unlikely((ll == NULL) || (ll_dev == NULL))) return; if (ll_dev == ll) *ll_root_addr = ll_dev->next; else if (likely(ll_dev_last != NULL)) ll_dev_last->next = ll_dev->next; else RTE_LOG(ERR, VHOST_CONFIG, "Remove entry form ll failed.\n"); } /* * Find and return an entry from the free linked list. */ static struct virtio_net_data_ll * get_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr) { struct virtio_net_data_ll *ll_free = *ll_root_addr; struct virtio_net_data_ll *ll_dev; if (ll_free == NULL) return NULL; ll_dev = ll_free; *ll_root_addr = ll_free->next; return ll_dev; } /* * Place an entry back on to the free linked list. */ static void put_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll_free = *ll_root_addr; if (ll_dev == NULL) return; ll_dev->next = ll_free; *ll_root_addr = ll_dev; } /* * Creates a linked list of a given size. */ static struct virtio_net_data_ll * alloc_data_ll(uint32_t size) { struct virtio_net_data_ll *ll_new; uint32_t i; /* Malloc and then chain the linked list. */ ll_new = malloc(size * sizeof(struct virtio_net_data_ll)); if (ll_new == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for ll_new.\n"); return NULL; } for (i = 0; i < size - 1; i++) { ll_new[i].vdev = NULL; ll_new[i].next = &ll_new[i+1]; } ll_new[i].next = NULL; return (ll_new); } /* * Create the main linked list along with each individual cores linked list. A used and a free list * are created to manage entries. */ static int init_data_ll (void) { int lcore; RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll = malloc(sizeof(struct lcore_ll_info)); if (lcore_info[lcore].lcore_ll == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for lcore_ll.\n"); return -1; } lcore_info[lcore].lcore_ll->device_num = 0; lcore_info[lcore].lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; lcore_info[lcore].lcore_ll->ll_root_used = NULL; if (num_devices % num_switching_cores) lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll((num_devices / num_switching_cores) + 1); else lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll(num_devices / num_switching_cores); } /* Allocate devices up to a maximum of MAX_DEVICES. */ ll_root_free = alloc_data_ll(MIN((num_devices), MAX_DEVICES)); return 0; } /* * Remove a device from the specific data core linked list and from the main linked list. Synchonization * occurs through the use of the lcore dev_removal_flag. Device is made volatile here to avoid re-ordering * of dev->remove=1 which can cause an infinite loop in the rte_pause loop. */ static void destroy_device (volatile struct virtio_net *dev) { struct virtio_net_data_ll *ll_lcore_dev_cur; struct virtio_net_data_ll *ll_main_dev_cur; struct virtio_net_data_ll *ll_lcore_dev_last = NULL; struct virtio_net_data_ll *ll_main_dev_last = NULL; struct vhost_dev *vdev; int lcore; dev->flags &= ~VIRTIO_DEV_RUNNING; vdev = (struct vhost_dev *)dev->priv; /*set the remove flag. */ vdev->remove = 1; while(vdev->ready != DEVICE_SAFE_REMOVE) { rte_pause(); } /* Search for entry to be removed from lcore ll */ ll_lcore_dev_cur = lcore_info[vdev->coreid].lcore_ll->ll_root_used; while (ll_lcore_dev_cur != NULL) { if (ll_lcore_dev_cur->vdev == vdev) { break; } else { ll_lcore_dev_last = ll_lcore_dev_cur; ll_lcore_dev_cur = ll_lcore_dev_cur->next; } } if (ll_lcore_dev_cur == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find the dev to be destroy.\n", dev->device_fh); return; } /* Search for entry to be removed from main ll */ ll_main_dev_cur = ll_root_used; ll_main_dev_last = NULL; while (ll_main_dev_cur != NULL) { if (ll_main_dev_cur->vdev == vdev) { break; } else { ll_main_dev_last = ll_main_dev_cur; ll_main_dev_cur = ll_main_dev_cur->next; } } /* Remove entries from the lcore and main ll. */ rm_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_lcore_dev_cur, ll_lcore_dev_last); rm_data_ll_entry(&ll_root_used, ll_main_dev_cur, ll_main_dev_last); /* Set the dev_removal_flag on each lcore. */ RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll->dev_removal_flag = REQUEST_DEV_REMOVAL; } /* * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL we can be sure that * they can no longer access the device removed from the linked lists and that the devices * are no longer in use. */ RTE_LCORE_FOREACH_SLAVE(lcore) { while (lcore_info[lcore].lcore_ll->dev_removal_flag != ACK_DEV_REMOVAL) { rte_pause(); } } /* Add the entries back to the lcore and main free ll.*/ put_data_ll_free_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_free, ll_lcore_dev_cur); put_data_ll_free_entry(&ll_root_free, ll_main_dev_cur); /* Decrement number of device on the lcore. */ lcore_info[vdev->coreid].lcore_ll->device_num--; RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been removed from data core\n", dev->device_fh); if (zero_copy) { struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q]; /* Stop the RX queue. */ if (rte_eth_dev_rx_queue_stop(ports[0], vdev->vmdq_rx_q) != 0) { LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") In destroy_device: Failed to stop " "rx queue:%d\n", dev->device_fh, vdev->vmdq_rx_q); } LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in destroy_device: Start put mbuf in " "mempool back to ring for RX queue: %d\n", dev->device_fh, vdev->vmdq_rx_q); mbuf_destroy_zcp(vpool); /* Stop the TX queue. */ if (rte_eth_dev_tx_queue_stop(ports[0], vdev->vmdq_rx_q) != 0) { LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") In destroy_device: Failed to " "stop tx queue:%d\n", dev->device_fh, vdev->vmdq_rx_q); } vpool = &vpool_array[vdev->vmdq_rx_q + MAX_QUEUES]; LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") destroy_device: Start put mbuf in mempool " "back to ring for TX queue: %d, dev:(%"PRIu64")\n", dev->device_fh, (vdev->vmdq_rx_q + MAX_QUEUES), dev->device_fh); mbuf_destroy_zcp(vpool); rte_free(vdev->regions_hpa); } rte_free(vdev); } /* * Calculate the region count of physical continous regions for one particular * region of whose vhost virtual address is continous. The particular region * start from vva_start, with size of 'size' in argument. */ static uint32_t check_hpa_regions(uint64_t vva_start, uint64_t size) { uint32_t i, nregions = 0, page_size = getpagesize(); uint64_t cur_phys_addr = 0, next_phys_addr = 0; if (vva_start % page_size) { LOG_DEBUG(VHOST_CONFIG, "in check_countinous: vva start(%p) mod page_size(%d) " "has remainder\n", (void *)(uintptr_t)vva_start, page_size); return 0; } if (size % page_size) { LOG_DEBUG(VHOST_CONFIG, "in check_countinous: " "size((%"PRIu64")) mod page_size(%d) has remainder\n", size, page_size); return 0; } for (i = 0; i < size - page_size; i = i + page_size) { cur_phys_addr = rte_mem_virt2phy((void *)(uintptr_t)(vva_start + i)); next_phys_addr = rte_mem_virt2phy( (void *)(uintptr_t)(vva_start + i + page_size)); if ((cur_phys_addr + page_size) != next_phys_addr) { ++nregions; LOG_DEBUG(VHOST_CONFIG, "in check_continuous: hva addr:(%p) is not " "continuous with hva addr:(%p), diff:%d\n", (void *)(uintptr_t)(vva_start + (uint64_t)i), (void *)(uintptr_t)(vva_start + (uint64_t)i + page_size), page_size); LOG_DEBUG(VHOST_CONFIG, "in check_continuous: hpa addr:(%p) is not " "continuous with hpa addr:(%p), " "diff:(%"PRIu64")\n", (void *)(uintptr_t)cur_phys_addr, (void *)(uintptr_t)next_phys_addr, (next_phys_addr-cur_phys_addr)); } } return nregions; } /* * Divide each region whose vhost virtual address is continous into a few * sub-regions, make sure the physical address within each sub-region are * continous. And fill offset(to GPA) and size etc. information of each * sub-region into regions_hpa. */ static uint32_t fill_hpa_memory_regions(struct virtio_memory_regions_hpa *mem_region_hpa, struct virtio_memory *virtio_memory) { uint32_t regionidx, regionidx_hpa = 0, i, k, page_size = getpagesize(); uint64_t cur_phys_addr = 0, next_phys_addr = 0, vva_start; if (mem_region_hpa == NULL) return 0; for (regionidx = 0; regionidx < virtio_memory->nregions; regionidx++) { vva_start = virtio_memory->regions[regionidx].guest_phys_address + virtio_memory->regions[regionidx].address_offset; mem_region_hpa[regionidx_hpa].guest_phys_address = virtio_memory->regions[regionidx].guest_phys_address; mem_region_hpa[regionidx_hpa].host_phys_addr_offset = rte_mem_virt2phy((void *)(uintptr_t)(vva_start)) - mem_region_hpa[regionidx_hpa].guest_phys_address; LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr start[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].guest_phys_address)); LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: host phys addr start[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].host_phys_addr_offset)); for (i = 0, k = 0; i < virtio_memory->regions[regionidx].memory_size - page_size; i += page_size) { cur_phys_addr = rte_mem_virt2phy( (void *)(uintptr_t)(vva_start + i)); next_phys_addr = rte_mem_virt2phy( (void *)(uintptr_t)(vva_start + i + page_size)); if ((cur_phys_addr + page_size) != next_phys_addr) { mem_region_hpa[regionidx_hpa].guest_phys_address_end = mem_region_hpa[regionidx_hpa].guest_phys_address + k + page_size; mem_region_hpa[regionidx_hpa].memory_size = k + page_size; LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest " "phys addr end [%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].guest_phys_address_end)); LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr " "size [%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].memory_size)); mem_region_hpa[regionidx_hpa + 1].guest_phys_address = mem_region_hpa[regionidx_hpa].guest_phys_address_end; ++regionidx_hpa; mem_region_hpa[regionidx_hpa].host_phys_addr_offset = next_phys_addr - mem_region_hpa[regionidx_hpa].guest_phys_address; LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest" " phys addr start[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].guest_phys_address)); LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: host phys addr " "start[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].host_phys_addr_offset)); k = 0; } else { k += page_size; } } mem_region_hpa[regionidx_hpa].guest_phys_address_end = mem_region_hpa[regionidx_hpa].guest_phys_address + k + page_size; mem_region_hpa[regionidx_hpa].memory_size = k + page_size; LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr end " "[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].guest_phys_address_end)); LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr size " "[%d]:(%p)\n", regionidx_hpa, (void *)(uintptr_t) (mem_region_hpa[regionidx_hpa].memory_size)); ++regionidx_hpa; } return regionidx_hpa; } /* * A new device is added to a data core. First the device is added to the main linked list * and the allocated to a specific data core. */ static int new_device (struct virtio_net *dev) { struct virtio_net_data_ll *ll_dev; int lcore, core_add = 0; uint32_t device_num_min = num_devices; struct vhost_dev *vdev; uint32_t regionidx; vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE); if (vdev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Couldn't allocate memory for vhost dev\n", dev->device_fh); return -1; } vdev->dev = dev; dev->priv = vdev; if (zero_copy) { vdev->nregions_hpa = dev->mem->nregions; for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) { vdev->nregions_hpa += check_hpa_regions( dev->mem->regions[regionidx].guest_phys_address + dev->mem->regions[regionidx].address_offset, dev->mem->regions[regionidx].memory_size); } vdev->regions_hpa = rte_calloc("vhost hpa region", vdev->nregions_hpa, sizeof(struct virtio_memory_regions_hpa), RTE_CACHE_LINE_SIZE); if (vdev->regions_hpa == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Cannot allocate memory for hpa region\n"); rte_free(vdev); return -1; } if (fill_hpa_memory_regions( vdev->regions_hpa, dev->mem ) != vdev->nregions_hpa) { RTE_LOG(ERR, VHOST_CONFIG, "hpa memory regions number mismatch: " "[%d]\n", vdev->nregions_hpa); rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } } /* Add device to main ll */ ll_dev = get_data_ll_free_entry(&ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in linked list. Device limit " "of %d devices per core has been reached\n", dev->device_fh, num_devices); if (vdev->regions_hpa) rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } ll_dev->vdev = vdev; add_data_ll_entry(&ll_root_used, ll_dev); vdev->vmdq_rx_q = dev->device_fh * queues_per_pool + vmdq_queue_base; if (zero_copy) { uint32_t index = vdev->vmdq_rx_q; uint32_t count_in_ring, i; struct mbuf_table *tx_q; count_in_ring = rte_ring_count(vpool_array[index].ring); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in mempool " "before attach is: %d\n", dev->device_fh, rte_mempool_count(vpool_array[index].pool)); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in ring " "before attach is : %d\n", dev->device_fh, count_in_ring); /* * Attach all mbufs in vpool.ring and put back intovpool.pool. */ for (i = 0; i < count_in_ring; i++) attach_rxmbuf_zcp(dev); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in " "mempool after attach is: %d\n", dev->device_fh, rte_mempool_count(vpool_array[index].pool)); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") in new_device: mbuf count in " "ring after attach is : %d\n", dev->device_fh, rte_ring_count(vpool_array[index].ring)); tx_q = &tx_queue_zcp[(uint16_t)vdev->vmdq_rx_q]; tx_q->txq_id = vdev->vmdq_rx_q; if (rte_eth_dev_tx_queue_start(ports[0], vdev->vmdq_rx_q) != 0) { struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q]; LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") In new_device: Failed to start " "tx queue:%d\n", dev->device_fh, vdev->vmdq_rx_q); mbuf_destroy_zcp(vpool); rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } if (rte_eth_dev_rx_queue_start(ports[0], vdev->vmdq_rx_q) != 0) { struct vpool *vpool = &vpool_array[vdev->vmdq_rx_q]; LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") In new_device: Failed to start " "rx queue:%d\n", dev->device_fh, vdev->vmdq_rx_q); /* Stop the TX queue. */ if (rte_eth_dev_tx_queue_stop(ports[0], vdev->vmdq_rx_q) != 0) { LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") In new_device: Failed to " "stop tx queue:%d\n", dev->device_fh, vdev->vmdq_rx_q); } mbuf_destroy_zcp(vpool); rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } } /*reset ready flag*/ vdev->ready = DEVICE_MAC_LEARNING; vdev->remove = 0; /* Find a suitable lcore to add the device. */ RTE_LCORE_FOREACH_SLAVE(lcore) { if (lcore_info[lcore].lcore_ll->device_num < device_num_min) { device_num_min = lcore_info[lcore].lcore_ll->device_num; core_add = lcore; } } /* Add device to lcore ll */ ll_dev = get_data_ll_free_entry(&lcore_info[core_add].lcore_ll->ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh); vdev->ready = DEVICE_SAFE_REMOVE; destroy_device(dev); rte_free(vdev->regions_hpa); rte_free(vdev); return -1; } ll_dev->vdev = vdev; vdev->coreid = core_add; add_data_ll_entry(&lcore_info[vdev->coreid].lcore_ll->ll_root_used, ll_dev); /* Initialize device stats */ memset(&dev_statistics[dev->device_fh], 0, sizeof(struct device_statistics)); /* Disable notifications. */ rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0); rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0); lcore_info[vdev->coreid].lcore_ll->device_num++; dev->flags |= VIRTIO_DEV_RUNNING; RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, vdev->coreid); return 0; } /* * These callback allow devices to be added to the data core when configuration * has been fully complete. */ static const struct virtio_net_device_ops virtio_net_device_ops = { .new_device = new_device, .destroy_device = destroy_device, }; /* * This is a thread will wake up after a period to print stats if the user has * enabled them. */ static void print_stats(void) { struct virtio_net_data_ll *dev_ll; uint64_t tx_dropped, rx_dropped; uint64_t tx, tx_total, rx, rx_total; uint32_t device_fh; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char top_left[] = { 27, '[', '1', ';', '1', 'H','\0' }; while(1) { sleep(enable_stats); /* Clear screen and move to top left */ printf("%s%s", clr, top_left); printf("\nDevice statistics ===================================="); dev_ll = ll_root_used; while (dev_ll != NULL) { device_fh = (uint32_t)dev_ll->vdev->dev->device_fh; tx_total = dev_statistics[device_fh].tx_total; tx = dev_statistics[device_fh].tx; tx_dropped = tx_total - tx; if (zero_copy == 0) { rx_total = rte_atomic64_read( &dev_statistics[device_fh].rx_total_atomic); rx = rte_atomic64_read( &dev_statistics[device_fh].rx_atomic); } else { rx_total = dev_statistics[device_fh].rx_total; rx = dev_statistics[device_fh].rx; } rx_dropped = rx_total - rx; printf("\nStatistics for device %"PRIu32" ------------------------------" "\nTX total: %"PRIu64"" "\nTX dropped: %"PRIu64"" "\nTX successful: %"PRIu64"" "\nRX total: %"PRIu64"" "\nRX dropped: %"PRIu64"" "\nRX successful: %"PRIu64"", device_fh, tx_total, tx_dropped, tx, rx_total, rx_dropped, rx); dev_ll = dev_ll->next; } printf("\n======================================================\n"); } } static void setup_mempool_tbl(int socket, uint32_t index, char *pool_name, char *ring_name, uint32_t nb_mbuf) { vpool_array[index].pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf, MBUF_CACHE_SIZE_ZCP, 0, MBUF_DATA_SIZE_ZCP, socket); if (vpool_array[index].pool != NULL) { vpool_array[index].ring = rte_ring_create(ring_name, rte_align32pow2(nb_mbuf + 1), socket, RING_F_SP_ENQ | RING_F_SC_DEQ); if (likely(vpool_array[index].ring != NULL)) { LOG_DEBUG(VHOST_CONFIG, "in setup_mempool_tbl: mbuf count in " "mempool is: %d\n", rte_mempool_count(vpool_array[index].pool)); LOG_DEBUG(VHOST_CONFIG, "in setup_mempool_tbl: mbuf count in " "ring is: %d\n", rte_ring_count(vpool_array[index].ring)); } else { rte_exit(EXIT_FAILURE, "ring_create(%s) failed", ring_name); } /* Need consider head room. */ vpool_array[index].buf_size = VIRTIO_DESCRIPTOR_LEN_ZCP; } else { rte_exit(EXIT_FAILURE, "mempool_create(%s) failed", pool_name); } } /* When we receive a INT signal, unregister vhost driver */ static void sigint_handler(__rte_unused int signum) { /* Unregister vhost driver. */ int ret = rte_vhost_driver_unregister((char *)&dev_basename); if (ret != 0) rte_exit(EXIT_FAILURE, "vhost driver unregister failure.\n"); exit(0); } /* * Main function, does initialisation and calls the per-lcore functions. The CUSE * device is also registered here to handle the IOCTLs. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool = NULL; unsigned lcore_id, core_id = 0; unsigned nb_ports, valid_num_ports; int ret; uint8_t portid; uint16_t queue_id; static pthread_t tid; signal(SIGINT, sigint_handler); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse app arguments */ ret = us_vhost_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid argument\n"); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++) if (rte_lcore_is_enabled(lcore_id)) lcore_ids[core_id ++] = lcore_id; if (rte_lcore_count() > RTE_MAX_LCORE) rte_exit(EXIT_FAILURE,"Not enough cores\n"); /*set the number of swithcing cores available*/ num_switching_cores = rte_lcore_count()-1; /* Get the number of physical ports. */ nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Update the global var NUM_PORTS and global array PORTS * and get value of var VALID_NUM_PORTS according to system ports number */ valid_num_ports = check_ports_num(nb_ports); if ((valid_num_ports == 0) || (valid_num_ports > MAX_SUP_PORTS)) { RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u," "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS); return -1; } if (zero_copy == 0) { /* Create the mbuf pool. */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS_PER_PORT * valid_num_ports, MBUF_CACHE_SIZE, 0, MBUF_DATA_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); for (queue_id = 0; queue_id < MAX_QUEUES + 1; queue_id++) vpool_array[queue_id].pool = mbuf_pool; if (vm2vm_mode == VM2VM_HARDWARE) { /* Enable VT loop back to let L2 switch to do it. */ vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1; LOG_DEBUG(VHOST_CONFIG, "Enable loop back for L2 switch in vmdq.\n"); } } else { uint32_t nb_mbuf; char pool_name[RTE_MEMPOOL_NAMESIZE]; char ring_name[RTE_MEMPOOL_NAMESIZE]; nb_mbuf = num_rx_descriptor + num_switching_cores * MBUF_CACHE_SIZE_ZCP + num_switching_cores * MAX_PKT_BURST; for (queue_id = 0; queue_id < MAX_QUEUES; queue_id++) { snprintf(pool_name, sizeof(pool_name), "rxmbuf_pool_%u", queue_id); snprintf(ring_name, sizeof(ring_name), "rxmbuf_ring_%u", queue_id); setup_mempool_tbl(rte_socket_id(), queue_id, pool_name, ring_name, nb_mbuf); } nb_mbuf = num_tx_descriptor + num_switching_cores * MBUF_CACHE_SIZE_ZCP + num_switching_cores * MAX_PKT_BURST; for (queue_id = 0; queue_id < MAX_QUEUES; queue_id++) { snprintf(pool_name, sizeof(pool_name), "txmbuf_pool_%u", queue_id); snprintf(ring_name, sizeof(ring_name), "txmbuf_ring_%u", queue_id); setup_mempool_tbl(rte_socket_id(), (queue_id + MAX_QUEUES), pool_name, ring_name, nb_mbuf); } if (vm2vm_mode == VM2VM_HARDWARE) { /* Enable VT loop back to let L2 switch to do it. */ vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1; LOG_DEBUG(VHOST_CONFIG, "Enable loop back for L2 switch in vmdq.\n"); } } /* Set log level. */ rte_set_log_level(LOG_LEVEL); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { RTE_LOG(INFO, VHOST_PORT, "Skipping disabled port %d\n", portid); continue; } if (port_init(portid) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); } /* Initialise all linked lists. */ if (init_data_ll() == -1) rte_exit(EXIT_FAILURE, "Failed to initialize linked list\n"); /* Initialize device stats */ memset(&dev_statistics, 0, sizeof(dev_statistics)); /* Enable stats if the user option is set. */ if (enable_stats) pthread_create(&tid, NULL, (void*)print_stats, NULL ); /* Launch all data cores. */ if (zero_copy == 0) { RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(switch_worker, mbuf_pool, lcore_id); } } else { uint32_t count_in_mempool, index, i; for (index = 0; index < 2*MAX_QUEUES; index++) { /* For all RX and TX queues. */ count_in_mempool = rte_mempool_count(vpool_array[index].pool); /* * Transfer all un-attached mbufs from vpool.pool * to vpoo.ring. */ for (i = 0; i < count_in_mempool; i++) { struct rte_mbuf *mbuf = __rte_mbuf_raw_alloc( vpool_array[index].pool); rte_ring_sp_enqueue(vpool_array[index].ring, (void *)mbuf); } LOG_DEBUG(VHOST_CONFIG, "in main: mbuf count in mempool at initial " "is: %d\n", count_in_mempool); LOG_DEBUG(VHOST_CONFIG, "in main: mbuf count in ring at initial is :" " %d\n", rte_ring_count(vpool_array[index].ring)); } RTE_LCORE_FOREACH_SLAVE(lcore_id) rte_eal_remote_launch(switch_worker_zcp, NULL, lcore_id); } if (mergeable == 0) rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF); /* Register vhost(cuse or user) driver to handle vhost messages. */ ret = rte_vhost_driver_register((char *)&dev_basename); if (ret != 0) rte_exit(EXIT_FAILURE, "vhost driver register failure.\n"); rte_vhost_driver_callback_register(&virtio_net_device_ops); /* Start CUSE session. */ rte_vhost_driver_session_start(); return 0; } ================================================ FILE: examples/vhost/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ //#define DEBUG #ifdef DEBUG #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) do { \ RTE_LOG(DEBUG, log_type, fmt, ##args); \ } while (0) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do{} while(0) #endif /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2 #define RTE_LOGTYPE_VHOST_PORT RTE_LOGTYPE_USER3 /** * Information relating to memory regions including offsets to * addresses in host physical space. */ struct virtio_memory_regions_hpa { /**< Base guest physical address of region. */ uint64_t guest_phys_address; /**< End guest physical address of region. */ uint64_t guest_phys_address_end; /**< Size of region. */ uint64_t memory_size; /**< Offset of region for gpa to hpa translation. */ uint64_t host_phys_addr_offset; }; /* * Device linked list structure for data path. */ struct vhost_dev { /**< Pointer to device created by vhost lib. */ struct virtio_net *dev; /**< Number of memory regions for gpa to hpa translation. */ uint32_t nregions_hpa; /**< Memory region information for gpa to hpa translation. */ struct virtio_memory_regions_hpa *regions_hpa; /**< Device MAC address (Obtained on first TX packet). */ struct ether_addr mac_address; /**< RX VMDQ queue number. */ uint16_t vmdq_rx_q; /**< Vlan tag assigned to the pool */ uint32_t vlan_tag; /**< Data core that the device is added to. */ uint16_t coreid; /**< A device is set as ready if the MAC address has been set. */ volatile uint8_t ready; /**< Device is marked for removal from the data core. */ volatile uint8_t remove; } __rte_cache_aligned; struct virtio_net_data_ll { struct vhost_dev *vdev; /* Pointer to device created by configuration core. */ struct virtio_net_data_ll *next; /* Pointer to next device in linked list. */ }; /* * Structure containing data core specific information. */ struct lcore_ll_info { struct virtio_net_data_ll *ll_root_free; /* Pointer to head in free linked list. */ struct virtio_net_data_ll *ll_root_used; /* Pointer to head of used linked list. */ uint32_t device_num; /* Number of devices on lcore. */ volatile uint8_t dev_removal_flag; /* Flag to synchronize device removal. */ }; struct lcore_info { struct lcore_ll_info *lcore_ll; /* Pointer to data core specific lcore_ll_info struct */ }; #endif /* _MAIN_H_ */ ================================================ FILE: examples/vhost_xen/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = vhost-switch # all source are stored in SRCS-y SRCS-y := main.c vhost_monitor.c xenstore_parse.c CFLAGS += -O2 -I/usr/local/include -D_FILE_OFFSET_BITS=64 -Wno-unused-parameter CFLAGS += $(WERROR_FLAGS) LDFLAGS += -lxenstore include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/vhost_xen/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "virtio-net.h" #include "xen_vhost.h" #define MAX_QUEUES 128 /* the maximum number of external ports supported */ #define MAX_SUP_PORTS 1 /* * Calculate the number of buffers needed per port */ #define NUM_MBUFS_PER_PORT ((MAX_QUEUES*RTE_TEST_RX_DESC_DEFAULT) + \ (num_switching_cores*MAX_PKT_BURST) + \ (num_switching_cores*RTE_TEST_TX_DESC_DEFAULT) +\ (num_switching_cores*MBUF_CACHE_SIZE)) #define MBUF_CACHE_SIZE 64 /* * RX and TX Prefetch, Host, and Write-back threshold values should be * carefully set for optimal performance. Consult the network * controller's datasheet and supporting DPDK documentation for guidance * on how these parameters should be set. */ #define RX_PTHRESH 8 /* Default values of RX prefetch threshold reg. */ #define RX_HTHRESH 8 /* Default values of RX host threshold reg. */ #define RX_WTHRESH 4 /* Default values of RX write-back threshold reg. */ /* * These default values are optimized for use with the Intel(R) 82599 10 GbE * Controller and the DPDK ixgbe PMD. Consider using other values for other * network controllers and/or network drivers. */ #define TX_PTHRESH 36 /* Default values of TX prefetch threshold reg. */ #define TX_HTHRESH 0 /* Default values of TX host threshold reg. */ #define TX_WTHRESH 0 /* Default values of TX write-back threshold reg. */ #define MAX_PKT_BURST 32 /* Max burst size for RX/TX */ #define MAX_MRG_PKT_BURST 16 /* Max burst for merge buffers. Set to 1 due to performance issue. */ #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ /* State of virtio device. */ #define DEVICE_NOT_READY 0 #define DEVICE_READY 1 #define DEVICE_SAFE_REMOVE 2 /* Config_core_flag status definitions. */ #define REQUEST_DEV_REMOVAL 1 #define ACK_DEV_REMOVAL 0 /* Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 #define INVALID_PORT_ID 0xFF /* Max number of devices. Limited by vmdq. */ #define MAX_DEVICES 64 /* Size of buffers used for snprintfs. */ #define MAX_PRINT_BUFF 6072 /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 /* Used to compare MAC addresses. */ #define MAC_ADDR_CMP 0xFFFFFFFFFFFF /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; /*Number of switching cores enabled*/ static uint32_t num_switching_cores = 0; /* number of devices/queues to support*/ static uint32_t num_queues = 0; uint32_t num_devices = 0; /* Enable VM2VM communications. If this is disabled then the MAC address compare is skipped. */ static uint32_t enable_vm2vm = 1; /* Enable stats. */ static uint32_t enable_stats = 0; /* empty vmdq configuration structure. Filled in programatically */ static const struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ /* * It is necessary for 1G NIC such as I350, * this fixes bug of ipv4 forwarding in guest can't * forward pakets from one virtio dev to another virtio dev. */ .hw_vlan_strip = 1, /**< VLAN strip enabled. */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .rx_adv_conf = { /* * should be overridden separately in code with * appropriate values */ .vmdq_rx_conf = { .nb_queue_pools = ETH_8_POOLS, .enable_default_pool = 0, .default_pool = 0, .nb_pool_maps = 0, .pool_map = {{0, 0},}, }, }, }; static unsigned lcore_ids[RTE_MAX_LCORE]; static uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned num_ports = 0; /**< The number of ports specified in command line */ const uint16_t vlan_tags[] = { 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, }; /* ethernet addresses of ports */ static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS]; /* heads for the main used and free linked lists for the data path. */ static struct virtio_net_data_ll *ll_root_used = NULL; static struct virtio_net_data_ll *ll_root_free = NULL; /* Array of data core structures containing information on individual core linked lists. */ static struct lcore_info lcore_info[RTE_MAX_LCORE]; /* Used for queueing bursts of TX packets. */ struct mbuf_table { unsigned len; unsigned txq_id; struct rte_mbuf *m_table[MAX_PKT_BURST]; }; /* TX queue for each data core. */ struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE]; /* Vlan header struct used to insert vlan tags on TX. */ struct vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; __be16 h_vlan_proto; __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; /* Header lengths. */ #define VLAN_HLEN 4 #define VLAN_ETH_HLEN 18 /* Per-device statistics struct */ struct device_statistics { uint64_t tx_total; rte_atomic64_t rx_total; uint64_t tx; rte_atomic64_t rx; } __rte_cache_aligned; struct device_statistics dev_statistics[MAX_DEVICES]; /* * Builds up the correct configuration for VMDQ VLAN pool map * according to the pool & queue limits. */ static inline int get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_devices) { struct rte_eth_vmdq_rx_conf conf; unsigned i; memset(&conf, 0, sizeof(conf)); conf.nb_queue_pools = (enum rte_eth_nb_pools)num_devices; conf.nb_pool_maps = num_devices; for (i = 0; i < conf.nb_pool_maps; i++) { conf.pool_map[i].vlan_id = vlan_tags[ i ]; conf.pool_map[i].pools = (1UL << i); } (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf))); (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_rx_conf, &conf, sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf))); return 0; } /* * Validate the device number according to the max pool number gotten form dev_info * If the device number is invalid, give the error message and return -1. * Each device must have its own pool. */ static inline int validate_num_devices(uint32_t max_nb_devices) { if (num_devices > max_nb_devices) { RTE_LOG(ERR, VHOST_PORT, "invalid number of devices\n"); return -1; } return 0; } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_dev_info dev_info; struct rte_eth_rxconf *rxconf; struct rte_eth_conf port_conf; uint16_t rx_rings, tx_rings = (uint16_t)rte_lcore_count(); const uint16_t rx_ring_size = RTE_TEST_RX_DESC_DEFAULT, tx_ring_size = RTE_TEST_TX_DESC_DEFAULT; int retval; uint16_t q; /* The max pool number from dev_info will be used to validate the pool number specified in cmd line */ rte_eth_dev_info_get (port, &dev_info); /*configure the number of supported virtio devices based on VMDQ limits */ num_devices = dev_info.max_vmdq_pools; num_queues = dev_info.max_rx_queues; retval = validate_num_devices(MAX_DEVICES); if (retval < 0) return retval; /* Get port configuration. */ retval = get_eth_conf(&port_conf, num_devices); if (retval < 0) return retval; if (port >= rte_eth_dev_count()) return -1; rx_rings = (uint16_t)num_queues, /* Configure ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) return retval; rte_eth_dev_info_get(port, &dev_info); rxconf = &dev_info.default_rxconf; rxconf->rx_drop_en = 1; /* Setup the queues. */ for (q = 0; q < rx_rings; q ++) { retval = rte_eth_rx_queue_setup(port, q, rx_ring_size, rte_eth_dev_socket_id(port), rxconf, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < tx_rings; q ++) { retval = rte_eth_tx_queue_setup(port, q, tx_ring_size, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } /* Start the device. */ retval = rte_eth_dev_start(port); if (retval < 0) return retval; rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]); RTE_LOG(INFO, VHOST_PORT, "Max virtio devices supported: %u\n", num_devices); RTE_LOG(INFO, VHOST_PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, vmdq_ports_eth_addr[port].addr_bytes[0], vmdq_ports_eth_addr[port].addr_bytes[1], vmdq_ports_eth_addr[port].addr_bytes[2], vmdq_ports_eth_addr[port].addr_bytes[3], vmdq_ports_eth_addr[port].addr_bytes[4], vmdq_ports_eth_addr[port].addr_bytes[5]); return 0; } /* * Parse the portmask provided at run time. */ static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; errno = 0; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) return -1; if (pm == 0) return -1; return pm; } /* * Parse num options at run time. */ static int parse_num_opt(const char *q_arg, uint32_t max_valid_value) { char *end = NULL; unsigned long num; errno = 0; /* parse unsigned int string */ num = strtoul(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) return -1; if (num > max_valid_value) return -1; return num; } /* * Display usage */ static void us_vhost_usage(const char *prgname) { RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK --vm2vm [0|1] --stats [0-N] --nb-devices ND\n" " -p PORTMASK: Set mask for ports to be used by application\n" " --vm2vm [0|1]: disable/enable(default) vm2vm comms\n" " --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n", prgname); } /* * Parse the arguments given in the command line of the application. */ static int us_vhost_parse_args(int argc, char **argv) { int opt, ret; int option_index; unsigned i; const char *prgname = argv[0]; static struct option long_option[] = { {"vm2vm", required_argument, NULL, 0}, {"stats", required_argument, NULL, 0}, {NULL, 0, 0, 0} }; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:",long_option, &option_index)) != EOF) { switch (opt) { /* Portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid portmask\n"); us_vhost_usage(prgname); return -1; } break; case 0: /* Enable/disable vm2vm comms. */ if (!strncmp(long_option[option_index].name, "vm2vm", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, 1); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for vm2vm [0|1]\n"); us_vhost_usage(prgname); return -1; } else { enable_vm2vm = ret; } } /* Enable/disable stats. */ if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); if (ret == -1) { RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n"); us_vhost_usage(prgname); return -1; } else { enable_stats = ret; } } break; /* Invalid option - print options. */ default: us_vhost_usage(prgname); return -1; } } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (enabled_port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; } if ((num_ports == 0) || (num_ports > MAX_SUP_PORTS)) { RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u," "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS); return -1; } return 0; } /* * Update the global var NUM_PORTS and array PORTS according to system ports number * and return valid ports number */ static unsigned check_ports_num(unsigned nb_ports) { unsigned valid_num_ports = num_ports; unsigned portid; if (num_ports > nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port number(%u) exceeds total system port number(%u)\n", num_ports, nb_ports); num_ports = nb_ports; } for (portid = 0; portid < num_ports; portid ++) { if (ports[portid] >= nb_ports) { RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max system port ID(%u)\n", ports[portid], (nb_ports - 1)); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } } return valid_num_ports; } /* * Macro to print out packet contents. Wrapped in debug define so that the * data path is not effected when debug is disabled. */ #ifdef DEBUG #define PRINT_PACKET(device, addr, size, header) do { \ char *pkt_addr = (char*)(addr); \ unsigned int index; \ char packet[MAX_PRINT_BUFF]; \ \ if ((header)) \ snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Header size %d: ", (device->device_fh), (size)); \ else \ snprintf(packet, MAX_PRINT_BUFF, "(%"PRIu64") Packet size %d: ", (device->device_fh), (size)); \ for (index = 0; index < (size); index++) { \ snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), \ "%02hhx ", pkt_addr[index]); \ } \ snprintf(packet + strnlen(packet, MAX_PRINT_BUFF), MAX_PRINT_BUFF - strnlen(packet, MAX_PRINT_BUFF), "\n"); \ \ LOG_DEBUG(VHOST_DATA, "%s", packet); \ } while(0) #else #define PRINT_PACKET(device, addr, size, header) do{} while(0) #endif /* * Function to convert guest physical addresses to vhost virtual addresses. This * is used to convert virtio buffer addresses. */ static inline uint64_t __attribute__((always_inline)) gpa_to_vva(struct virtio_net *dev, uint64_t guest_pa) { struct virtio_memory_regions *region; uint32_t regionidx; uint64_t vhost_va = 0; for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) { region = &dev->mem->regions[regionidx]; if ((guest_pa >= region->guest_phys_address) && (guest_pa <= region->guest_phys_address_end)) { vhost_va = region->address_offset + guest_pa; break; } } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") GPA %p| VVA %p\n", dev->device_fh, (void*)(uintptr_t)guest_pa, (void*)(uintptr_t)vhost_va); return vhost_va; } /* * This function adds buffers to the virtio devices RX virtqueue. Buffers can * be received from the physical port or from another virtio device. A packet * count is returned to indicate the number of packets that were succesfully * added to the RX queue. */ static inline uint32_t __attribute__((always_inline)) virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count) { struct vhost_virtqueue *vq; struct vring_desc *desc; struct rte_mbuf *buff; /* The virtio_hdr is initialised to 0. */ struct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0,0,0,0,0,0},0}; uint64_t buff_addr = 0; uint64_t buff_hdr_addr = 0; uint32_t head[MAX_PKT_BURST], packet_len = 0; uint32_t head_idx, packet_success = 0; uint16_t avail_idx, res_cur_idx; uint16_t res_base_idx, res_end_idx; uint16_t free_entries; uint8_t success = 0; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh); vq = dev->virtqueue_rx; count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; /* As many data cores may want access to available buffers, they need to be reserved. */ do { res_base_idx = vq->last_used_idx_res; avail_idx = *((volatile uint16_t *)&vq->avail->idx); free_entries = (avail_idx - res_base_idx); /*check that we have enough buffers*/ if (unlikely(count > free_entries)) count = free_entries; if (count == 0) return 0; res_end_idx = res_base_idx + count; /* vq->last_used_idx_res is atomically updated. */ success = rte_atomic16_cmpset(&vq->last_used_idx_res, res_base_idx, res_end_idx); } while (unlikely(success == 0)); res_cur_idx = res_base_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| End Index %d\n", dev->device_fh, res_cur_idx, res_end_idx); /* Prefetch available ring to retrieve indexes. */ rte_prefetch0(&vq->avail->ring[res_cur_idx & (vq->size - 1)]); /* Retrieve all of the head indexes first to avoid caching issues. */ for (head_idx = 0; head_idx < count; head_idx++) head[head_idx] = vq->avail->ring[(res_cur_idx + head_idx) & (vq->size - 1)]; /*Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); while (res_cur_idx != res_end_idx) { /* Get descriptor from available ring */ desc = &vq->desc[head[packet_success]]; /* Prefetch descriptor address. */ rte_prefetch0(desc); buff = pkts[packet_success]; /* Convert from gpa to vva (guest physical addr -> vhost virtual addr) */ buff_addr = gpa_to_vva(dev, desc->addr); /* Prefetch buffer address. */ rte_prefetch0((void*)(uintptr_t)buff_addr); { /* Copy virtio_hdr to packet and increment buffer address */ buff_hdr_addr = buff_addr; packet_len = rte_pktmbuf_data_len(buff) + vq->vhost_hlen; /* * If the descriptors are chained the header and data are placed in * separate buffers. */ if (desc->flags & VRING_DESC_F_NEXT) { desc->len = vq->vhost_hlen; desc = &vq->desc[desc->next]; /* Buffer address translation. */ buff_addr = gpa_to_vva(dev, desc->addr); desc->len = rte_pktmbuf_data_len(buff); } else { buff_addr += vq->vhost_hlen; desc->len = packet_len; } } /* Update used ring with desc information */ vq->used->ring[res_cur_idx & (vq->size - 1)].id = head[packet_success]; vq->used->ring[res_cur_idx & (vq->size - 1)].len = packet_len; /* Copy mbuf data to buffer */ rte_memcpy((void *)(uintptr_t)buff_addr, (const void*)buff->data, rte_pktmbuf_data_len(buff)); res_cur_idx++; packet_success++; /* mergeable is disabled then a header is required per buffer. */ rte_memcpy((void *)(uintptr_t)buff_hdr_addr, (const void*)&virtio_hdr, vq->vhost_hlen); if (res_cur_idx < res_end_idx) { /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); } } rte_compiler_barrier(); /* Wait until it's our turn to add our buffer to the used ring. */ while (unlikely(vq->last_used_idx != res_base_idx)) rte_pause(); *(volatile uint16_t *)&vq->used->idx += count; vq->last_used_idx = res_end_idx; return count; } /* * Compares a packet destination MAC address to a device MAC address. */ static inline int __attribute__((always_inline)) ether_addr_cmp(struct ether_addr *ea, struct ether_addr *eb) { return (((*(uint64_t *)ea ^ *(uint64_t *)eb) & MAC_ADDR_CMP) == 0); } /* * This function registers mac along with a * vlan tag to a VMDQ. */ static int link_vmdq(struct virtio_net *dev) { int ret; struct virtio_net_data_ll *dev_ll; dev_ll = ll_root_used; while (dev_ll != NULL) { if ((dev != dev_ll->dev) && ether_addr_cmp(&dev->mac_address, &dev_ll->dev->mac_address)) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing MAC address and has not been registered.\n", dev->device_fh); return -1; } dev_ll = dev_ll->next; } /* vlan_tag currently uses the device_id. */ dev->vlan_tag = vlan_tags[dev->device_fh]; dev->vmdq_rx_q = dev->device_fh * (num_queues/num_devices); /* Print out VMDQ registration info. */ RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n", dev->device_fh, dev->mac_address.addr_bytes[0], dev->mac_address.addr_bytes[1], dev->mac_address.addr_bytes[2], dev->mac_address.addr_bytes[3], dev->mac_address.addr_bytes[4], dev->mac_address.addr_bytes[5], dev->vlan_tag); /* Register the MAC address. */ ret = rte_eth_dev_mac_addr_add(ports[0], &dev->mac_address, (uint32_t)dev->device_fh); if (ret) { RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n", dev->device_fh); return -1; } /* Enable stripping of the vlan tag as we handle routing. */ rte_eth_dev_set_vlan_strip_on_queue(ports[0], dev->vmdq_rx_q, 1); rte_compiler_barrier(); /* Set device as ready for RX. */ dev->ready = DEVICE_READY; return 0; } /* * Removes MAC address and vlan tag from VMDQ. Ensures that nothing is adding buffers to the RX * queue before disabling RX on the device. */ static inline void unlink_vmdq(struct virtio_net *dev) { unsigned i = 0; unsigned rx_count; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; if (dev->ready == DEVICE_READY) { /*clear MAC and VLAN settings*/ rte_eth_dev_mac_addr_remove(ports[0], &dev->mac_address); for (i = 0; i < 6; i++) dev->mac_address.addr_bytes[i] = 0; dev->vlan_tag = 0; /*Clear out the receive buffers*/ rx_count = rte_eth_rx_burst(ports[0], (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); while (rx_count) { for (i = 0; i < rx_count; i++) rte_pktmbuf_free(pkts_burst[i]); rx_count = rte_eth_rx_burst(ports[0], (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); } dev->ready = DEVICE_NOT_READY; } } /* * Check if the packet destination MAC address is for a local device. If so then put * the packet on that devices RX queue. If not then return. */ static inline unsigned __attribute__((always_inline)) virtio_tx_local(struct virtio_net *dev, struct rte_mbuf *m) { struct virtio_net_data_ll *dev_ll; struct ether_hdr *pkt_hdr; uint64_t ret = 0; pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); /*get the used devices list*/ dev_ll = ll_root_used; while (dev_ll != NULL) { if (likely(dev_ll->dev->ready == DEVICE_READY) && ether_addr_cmp(&(pkt_hdr->d_addr), &dev_ll->dev->mac_address)) { /* Drop the packet if the TX packet is destined for the TX device. */ if (dev_ll->dev->device_fh == dev->device_fh) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: Source and destination MAC addresses are the same. Dropping packet.\n", dev_ll->dev->device_fh); return 0; } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is local\n", dev_ll->dev->device_fh); if (dev_ll->dev->remove) { /*drop the packet if the device is marked for removal*/ LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Device is marked for removal\n", dev_ll->dev->device_fh); } else { /*send the packet to the local virtio device*/ ret = virtio_dev_rx(dev_ll->dev, &m, 1); if (enable_stats) { rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx_total, 1); rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx, ret); dev_statistics[dev->device_fh].tx_total++; dev_statistics[dev->device_fh].tx += ret; } } return 0; } dev_ll = dev_ll->next; } return -1; } /* * This function routes the TX packet to the correct interface. This may be a local device * or the physical port. */ static inline void __attribute__((always_inline)) virtio_tx_route(struct virtio_net* dev, struct rte_mbuf *m, struct rte_mempool *mbuf_pool, uint16_t vlan_tag) { struct mbuf_table *tx_q; struct vlan_ethhdr *vlan_hdr; struct rte_mbuf **m_table; struct rte_mbuf *mbuf; unsigned len, ret; const uint16_t lcore_id = rte_lcore_id(); /*check if destination is local VM*/ if (enable_vm2vm && (virtio_tx_local(dev, m) == 0)) { return; } LOG_DEBUG(VHOST_DATA, "(%"PRIu64") TX: MAC address is external\n", dev->device_fh); /*Add packet to the port tx queue*/ tx_q = &lcore_tx_queue[lcore_id]; len = tx_q->len; /* Allocate an mbuf and populate the structure. */ mbuf = rte_pktmbuf_alloc(mbuf_pool); if(!mbuf) return; mbuf->data_len = m->data_len + VLAN_HLEN; mbuf->pkt_len = mbuf->data_len; /* Copy ethernet header to mbuf. */ rte_memcpy(rte_pktmbuf_mtod(mbuf, void*), rte_pktmbuf_mtod(m, const void*), ETH_HLEN); /* Setup vlan header. Bytes need to be re-ordered for network with htons()*/ vlan_hdr = rte_pktmbuf_mtod(mbuf, struct vlan_ethhdr *); vlan_hdr->h_vlan_encapsulated_proto = vlan_hdr->h_vlan_proto; vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q); vlan_hdr->h_vlan_TCI = htons(vlan_tag); /* Copy the remaining packet contents to the mbuf. */ rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, void *, VLAN_ETH_HLEN), rte_pktmbuf_mtod_offset(m, const void *, ETH_HLEN), (m->data_len - ETH_HLEN)); tx_q->m_table[len] = mbuf; len++; if (enable_stats) { dev_statistics[dev->device_fh].tx_total++; dev_statistics[dev->device_fh].tx++; } if (unlikely(len == MAX_PKT_BURST)) { m_table = (struct rte_mbuf **)tx_q->m_table; ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t) len); /* Free any buffers not handled by TX and update the port stats. */ if (unlikely(ret < len)) { do { rte_pktmbuf_free(m_table[ret]); } while (++ret < len); } len = 0; } tx_q->len = len; return; } static inline void __attribute__((always_inline)) virtio_dev_tx(struct virtio_net* dev, struct rte_mempool *mbuf_pool) { struct rte_mbuf m; struct vhost_virtqueue *vq; struct vring_desc *desc; uint64_t buff_addr = 0; uint32_t head[MAX_PKT_BURST]; uint32_t used_idx; uint32_t i; uint16_t free_entries, packet_success = 0; uint16_t avail_idx; vq = dev->virtqueue_tx; avail_idx = *((volatile uint16_t *)&vq->avail->idx); /* If there are no available buffers then return. */ if (vq->last_used_idx == avail_idx) return; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_tx()\n", dev->device_fh); /* Prefetch available ring to retrieve head indexes. */ rte_prefetch0(&vq->avail->ring[vq->last_used_idx & (vq->size - 1)]); /*get the number of free entries in the ring*/ free_entries = avail_idx - vq->last_used_idx; free_entries = unlikely(free_entries < MAX_PKT_BURST) ? free_entries : MAX_PKT_BURST; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Buffers available %d\n", dev->device_fh, free_entries); /* Retrieve all of the head indexes first to avoid caching issues. */ for (i = 0; i < free_entries; i++) head[i] = vq->avail->ring[(vq->last_used_idx + i) & (vq->size - 1)]; /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); while (packet_success < free_entries) { desc = &vq->desc[head[packet_success]]; /* Prefetch descriptor address. */ rte_prefetch0(desc); if (packet_success < (free_entries - 1)) { /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success+1]]); } /* Update used index buffer information. */ used_idx = vq->last_used_idx & (vq->size - 1); vq->used->ring[used_idx].id = head[packet_success]; vq->used->ring[used_idx].len = 0; /* Discard first buffer as it is the virtio header */ desc = &vq->desc[desc->next]; /* Buffer address translation. */ buff_addr = gpa_to_vva(dev, desc->addr); /* Prefetch buffer address. */ rte_prefetch0((void*)(uintptr_t)buff_addr); /* Setup dummy mbuf. This is copied to a real mbuf if transmitted out the physical port. */ m.data_len = desc->len; m.data_off = 0; m.nb_segs = 1; virtio_tx_route(dev, &m, mbuf_pool, 0); vq->last_used_idx++; packet_success++; } rte_compiler_barrier(); vq->used->idx += packet_success; /* Kick guest if required. */ } /* * This function is called by each data core. It handles all RX/TX registered with the * core. For TX the specific lcore linked list is used. For RX, MAC addresses are compared * with all devices in the main linked list. */ static int switch_worker(__attribute__((unused)) void *arg) { struct rte_mempool *mbuf_pool = arg; struct virtio_net *dev = NULL; struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; struct virtio_net_data_ll *dev_ll; struct mbuf_table *tx_q; volatile struct lcore_ll_info *lcore_ll; const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0; unsigned ret, i; const uint16_t lcore_id = rte_lcore_id(); const uint16_t num_cores = (uint16_t)rte_lcore_count(); uint16_t rx_count = 0; RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started \n", lcore_id); lcore_ll = lcore_info[lcore_id].lcore_ll; prev_tsc = 0; tx_q = &lcore_tx_queue[lcore_id]; for (i = 0; i < num_cores; i ++) { if (lcore_ids[i] == lcore_id) { tx_q->txq_id = i; break; } } while(1) { cur_tsc = rte_rdtsc(); /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; if (unlikely(diff_tsc > drain_tsc)) { if (tx_q->len) { LOG_DEBUG(VHOST_DATA, "TX queue drained after timeout with burst size %u \n", tx_q->len); /*Tx any packets in the queue*/ ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, (struct rte_mbuf **)tx_q->m_table, (uint16_t)tx_q->len); if (unlikely(ret < tx_q->len)) { do { rte_pktmbuf_free(tx_q->m_table[ret]); } while (++ret < tx_q->len); } tx_q->len = 0; } prev_tsc = cur_tsc; } /* * Inform the configuration core that we have exited the linked list and that no devices are * in use if requested. */ if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL) lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; /* * Process devices */ dev_ll = lcore_ll->ll_root_used; while (dev_ll != NULL) { /*get virtio device ID*/ dev = dev_ll->dev; if (unlikely(dev->remove)) { dev_ll = dev_ll->next; unlink_vmdq(dev); dev->ready = DEVICE_SAFE_REMOVE; continue; } if (likely(dev->ready == DEVICE_READY)) { /*Handle guest RX*/ rx_count = rte_eth_rx_burst(ports[0], (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST); if (rx_count) { ret_count = virtio_dev_rx(dev, pkts_burst, rx_count); if (enable_stats) { rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx_total, rx_count); rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx, ret_count); } while (likely(rx_count)) { rx_count--; rte_pktmbuf_free_seg(pkts_burst[rx_count]); } } } if (likely(!dev->remove)) /*Handle guest TX*/ virtio_dev_tx(dev, mbuf_pool); /*move to the next device in the list*/ dev_ll = dev_ll->next; } } return 0; } /* * Add an entry to a used linked list. A free entry must first be found in the free linked list * using get_data_ll_free_entry(); */ static void add_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll = *ll_root_addr; /* Set next as NULL and use a compiler barrier to avoid reordering. */ ll_dev->next = NULL; rte_compiler_barrier(); /* If ll == NULL then this is the first device. */ if (ll) { /* Increment to the tail of the linked list. */ while ((ll->next != NULL) ) ll = ll->next; ll->next = ll_dev; } else { *ll_root_addr = ll_dev; } } /* * Remove an entry from a used linked list. The entry must then be added to the free linked list * using put_data_ll_free_entry(). */ static void rm_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev, struct virtio_net_data_ll *ll_dev_last) { struct virtio_net_data_ll *ll = *ll_root_addr; if (ll_dev == ll) *ll_root_addr = ll_dev->next; else ll_dev_last->next = ll_dev->next; } /* * Find and return an entry from the free linked list. */ static struct virtio_net_data_ll * get_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr) { struct virtio_net_data_ll *ll_free = *ll_root_addr; struct virtio_net_data_ll *ll_dev; if (ll_free == NULL) return NULL; ll_dev = ll_free; *ll_root_addr = ll_free->next; return ll_dev; } /* * Place an entry back on to the free linked list. */ static void put_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev) { struct virtio_net_data_ll *ll_free = *ll_root_addr; ll_dev->next = ll_free; *ll_root_addr = ll_dev; } /* * Creates a linked list of a given size. */ static struct virtio_net_data_ll * alloc_data_ll(uint32_t size) { struct virtio_net_data_ll *ll_new; uint32_t i; /* Malloc and then chain the linked list. */ ll_new = malloc(size * sizeof(struct virtio_net_data_ll)); if (ll_new == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for ll_new.\n"); return NULL; } for (i = 0; i < size - 1; i++) { ll_new[i].dev = NULL; ll_new[i].next = &ll_new[i+1]; } ll_new[i].next = NULL; return (ll_new); } /* * Create the main linked list along with each individual cores linked list. A used and a free list * are created to manage entries. */ static int init_data_ll (void) { int lcore; RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll = malloc(sizeof(struct lcore_ll_info)); if (lcore_info[lcore].lcore_ll == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for lcore_ll.\n"); return -1; } lcore_info[lcore].lcore_ll->device_num = 0; lcore_info[lcore].lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL; lcore_info[lcore].lcore_ll->ll_root_used = NULL; if (num_devices % num_switching_cores) lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll((num_devices / num_switching_cores) + 1); else lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll(num_devices / num_switching_cores); } /* Allocate devices up to a maximum of MAX_DEVICES. */ ll_root_free = alloc_data_ll(MIN((num_devices), MAX_DEVICES)); return 0; } /* * Remove a device from the specific data core linked list and from the main linked list. The * rx/tx thread must be set the flag to indicate that it is safe to remove the device. * used. */ static void destroy_device (volatile struct virtio_net *dev) { struct virtio_net_data_ll *ll_lcore_dev_cur; struct virtio_net_data_ll *ll_main_dev_cur; struct virtio_net_data_ll *ll_lcore_dev_last = NULL; struct virtio_net_data_ll *ll_main_dev_last = NULL; int lcore; dev->flags &= ~VIRTIO_DEV_RUNNING; /*set the remove flag. */ dev->remove = 1; while(dev->ready != DEVICE_SAFE_REMOVE) { rte_pause(); } /* Search for entry to be removed from lcore ll */ ll_lcore_dev_cur = lcore_info[dev->coreid].lcore_ll->ll_root_used; while (ll_lcore_dev_cur != NULL) { if (ll_lcore_dev_cur->dev == dev) { break; } else { ll_lcore_dev_last = ll_lcore_dev_cur; ll_lcore_dev_cur = ll_lcore_dev_cur->next; } } /* Search for entry to be removed from main ll */ ll_main_dev_cur = ll_root_used; ll_main_dev_last = NULL; while (ll_main_dev_cur != NULL) { if (ll_main_dev_cur->dev == dev) { break; } else { ll_main_dev_last = ll_main_dev_cur; ll_main_dev_cur = ll_main_dev_cur->next; } } if (ll_lcore_dev_cur == NULL || ll_main_dev_cur == NULL) { RTE_LOG(ERR, XENHOST, "%s: could find device in per_cpu list or main_list\n", __func__); return; } /* Remove entries from the lcore and main ll. */ rm_data_ll_entry(&lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->ll_root_used, ll_lcore_dev_cur, ll_lcore_dev_last); rm_data_ll_entry(&ll_root_used, ll_main_dev_cur, ll_main_dev_last); /* Set the dev_removal_flag on each lcore. */ RTE_LCORE_FOREACH_SLAVE(lcore) { lcore_info[lcore].lcore_ll->dev_removal_flag = REQUEST_DEV_REMOVAL; } /* * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL we can be sure that * they can no longer access the device removed from the linked lists and that the devices * are no longer in use. */ RTE_LCORE_FOREACH_SLAVE(lcore) { while (lcore_info[lcore].lcore_ll->dev_removal_flag != ACK_DEV_REMOVAL) { rte_pause(); } } /* Add the entries back to the lcore and main free ll.*/ put_data_ll_free_entry(&lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->ll_root_free, ll_lcore_dev_cur); put_data_ll_free_entry(&ll_root_free, ll_main_dev_cur); /* Decrement number of device on the lcore. */ lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->device_num--; RTE_LOG(INFO, VHOST_DATA, " #####(%"PRIu64") Device has been removed from data core\n", dev->device_fh); } /* * A new device is added to a data core. First the device is added to the main linked list * and the allocated to a specific data core. */ static int new_device (struct virtio_net *dev) { struct virtio_net_data_ll *ll_dev; int lcore, core_add = 0; uint32_t device_num_min = num_devices; /* Add device to main ll */ ll_dev = get_data_ll_free_entry(&ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in linked list. Device limit " "of %d devices per core has been reached\n", dev->device_fh, num_devices); return -1; } ll_dev->dev = dev; add_data_ll_entry(&ll_root_used, ll_dev); /*reset ready flag*/ dev->ready = DEVICE_NOT_READY; dev->remove = 0; /* Find a suitable lcore to add the device. */ RTE_LCORE_FOREACH_SLAVE(lcore) { if (lcore_info[lcore].lcore_ll->device_num < device_num_min) { device_num_min = lcore_info[lcore].lcore_ll->device_num; core_add = lcore; } } /* Add device to lcore ll */ ll_dev->dev->coreid = core_add; ll_dev = get_data_ll_free_entry(&lcore_info[ll_dev->dev->coreid].lcore_ll->ll_root_free); if (ll_dev == NULL) { RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh); destroy_device(dev); return -1; } ll_dev->dev = dev; add_data_ll_entry(&lcore_info[ll_dev->dev->coreid].lcore_ll->ll_root_used, ll_dev); /* Initialize device stats */ memset(&dev_statistics[dev->device_fh], 0, sizeof(struct device_statistics)); lcore_info[ll_dev->dev->coreid].lcore_ll->device_num++; dev->flags |= VIRTIO_DEV_RUNNING; RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, dev->coreid); link_vmdq(dev); return 0; } /* * These callback allow devices to be added to the data core when configuration * has been fully complete. */ static const struct virtio_net_device_ops virtio_net_device_ops = { .new_device = new_device, .destroy_device = destroy_device, }; /* * This is a thread will wake up after a period to print stats if the user has * enabled them. */ static void print_stats(void) { struct virtio_net_data_ll *dev_ll; uint64_t tx_dropped, rx_dropped; uint64_t tx, tx_total, rx, rx_total; uint32_t device_fh; const char clr[] = { 27, '[', '2', 'J', '\0' }; const char top_left[] = { 27, '[', '1', ';', '1', 'H','\0' }; while(1) { sleep(enable_stats); /* Clear screen and move to top left */ printf("%s%s", clr, top_left); printf("\nDevice statistics ===================================="); dev_ll = ll_root_used; while (dev_ll != NULL) { device_fh = (uint32_t)dev_ll->dev->device_fh; tx_total = dev_statistics[device_fh].tx_total; tx = dev_statistics[device_fh].tx; tx_dropped = tx_total - tx; rx_total = rte_atomic64_read(&dev_statistics[device_fh].rx_total); rx = rte_atomic64_read(&dev_statistics[device_fh].rx); rx_dropped = rx_total - rx; printf("\nStatistics for device %"PRIu32" ------------------------------" "\nTX total: %"PRIu64"" "\nTX dropped: %"PRIu64"" "\nTX successful: %"PRIu64"" "\nRX total: %"PRIu64"" "\nRX dropped: %"PRIu64"" "\nRX successful: %"PRIu64"", device_fh, tx_total, tx_dropped, tx, rx_total, rx_dropped, rx); dev_ll = dev_ll->next; } printf("\n======================================================\n"); } } int init_virtio_net(struct virtio_net_device_ops const * const ops); /* * Main function, does initialisation and calls the per-lcore functions. The CUSE * device is also registered here to handle the IOCTLs. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; unsigned lcore_id, core_id = 0; unsigned nb_ports, valid_num_ports; int ret; uint8_t portid; static pthread_t tid; /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse app arguments */ ret = us_vhost_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid argument\n"); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++) if (rte_lcore_is_enabled(lcore_id)) lcore_ids[core_id ++] = lcore_id; if (rte_lcore_count() > RTE_MAX_LCORE) rte_exit(EXIT_FAILURE,"Not enough cores\n"); /*set the number of swithcing cores available*/ num_switching_cores = rte_lcore_count()-1; /* Get the number of physical ports. */ nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Update the global var NUM_PORTS and global array PORTS * and get value of var VALID_NUM_PORTS according to system ports number */ valid_num_ports = check_ports_num(nb_ports); if ((valid_num_ports == 0) || (valid_num_ports > MAX_SUP_PORTS)) { RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u," "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS); return -1; } /* Create the mbuf pool. */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS_PER_PORT * valid_num_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Set log level. */ rte_set_log_level(LOG_LEVEL); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { RTE_LOG(INFO, VHOST_PORT, "Skipping disabled port %d\n", portid); continue; } if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); } /* Initialise all linked lists. */ if (init_data_ll() == -1) rte_exit(EXIT_FAILURE, "Failed to initialize linked list\n"); /* Initialize device stats */ memset(&dev_statistics, 0, sizeof(dev_statistics)); /* Enable stats if the user option is set. */ if (enable_stats) pthread_create(&tid, NULL, (void*)print_stats, NULL ); /* Launch all data cores. */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(switch_worker, mbuf_pool, lcore_id); } init_virtio_xen(&virtio_net_device_ops); virtio_monitor_loop(); return 0; } ================================================ FILE: examples/vhost_xen/main.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _MAIN_H_ #define _MAIN_H_ //#define DEBUG #ifdef DEBUG #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) \ RTE_LOG(DEBUG, log_type, fmt, ##args) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do{} while(0) #endif /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER2 #define RTE_LOGTYPE_VHOST_PORT RTE_LOGTYPE_USER3 /* * Device linked list structure for data path. */ struct virtio_net_data_ll { struct virtio_net *dev; /* Pointer to device created by configuration core. */ struct virtio_net_data_ll *next; /* Pointer to next device in linked list. */ }; /* * Structure containing data core specific information. */ struct lcore_ll_info { struct virtio_net_data_ll *ll_root_free; /* Pointer to head in free linked list. */ struct virtio_net_data_ll *ll_root_used; /* Pointer to head of used linked list. */ uint32_t device_num; /* Number of devices on lcore. */ volatile uint8_t dev_removal_flag; /* Flag to synchronize device removal. */ }; struct lcore_info { struct lcore_ll_info *lcore_ll; /* Pointer to data core specific lcore_ll_info struct */ }; #endif /* _MAIN_H_ */ ================================================ FILE: examples/vhost_xen/vhost_monitor.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040200 #include #else #include #endif #include #include #include #include #include #include #include #include "virtio-net.h" #include "xen_vhost.h" struct virtio_watch { struct xs_handle *xs; int watch_fd; }; /* device ops to add/remove device to/from data core. */ static struct virtio_net_device_ops const *notify_ops; /* root address of the linked list in the configuration core. */ static struct virtio_net_config_ll *ll_root = NULL; /* root address of VM. */ static struct xen_guestlist guest_root; static struct virtio_watch watch; static void vq_vring_init(struct vhost_virtqueue *vq, unsigned int num, uint8_t *p, unsigned long align) { vq->size = num; vq->desc = (struct vring_desc *) p; vq->avail = (struct vring_avail *) (p + num * sizeof(struct vring_desc)); vq->used = (void *) RTE_ALIGN_CEIL( (uintptr_t)(&vq->avail->ring[num]), align); } static int init_watch(void) { struct xs_handle *xs; int ret; int fd; /* get a connection to the daemon */ xs = xs_daemon_open(); if (xs == NULL) { RTE_LOG(ERR, XENHOST, "xs_daemon_open failed\n"); return (-1); } ret = xs_watch(xs, "/local/domain", "mytoken"); if (ret == 0) { RTE_LOG(ERR, XENHOST, "%s: xs_watch failed\n", __func__); xs_daemon_close(xs); return (-1); } /* We are notified of read availability on the watch via the file descriptor. */ fd = xs_fileno(xs); watch.xs = xs; watch.watch_fd = fd; TAILQ_INIT(&guest_root); return 0; } static struct xen_guest * get_xen_guest(int dom_id) { struct xen_guest *guest = NULL; TAILQ_FOREACH(guest, &guest_root, next) { if(guest->dom_id == dom_id) return guest; } return (NULL); } static struct xen_guest * add_xen_guest(int32_t dom_id) { struct xen_guest *guest = NULL; if ((guest = get_xen_guest(dom_id)) != NULL) return guest; guest = calloc(1, sizeof(struct xen_guest)); if (guest) { RTE_LOG(ERR, XENHOST, " %s: return newly created guest with %d rings\n", __func__, guest->vring_num); TAILQ_INSERT_TAIL(&guest_root, guest, next); guest->dom_id = dom_id; } return guest; } static void cleanup_device(struct virtio_net_config_ll *ll_dev) { if (ll_dev == NULL) return; if (ll_dev->dev.virtqueue_rx) { rte_free(ll_dev->dev.virtqueue_rx); ll_dev->dev.virtqueue_rx = NULL; } if (ll_dev->dev.virtqueue_tx) { rte_free(ll_dev->dev.virtqueue_tx); ll_dev->dev.virtqueue_tx = NULL; } free(ll_dev); } /* * Add entry containing a device to the device configuration linked list. */ static void add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev) { struct virtio_net_config_ll *ll_dev = ll_root; /* If ll_dev == NULL then this is the first device so go to else */ if (ll_dev) { /* If the 1st device_id != 0 then we insert our device here. */ if (ll_dev->dev.device_fh != 0) { new_ll_dev->dev.device_fh = 0; new_ll_dev->next = ll_dev; ll_root = new_ll_dev; } else { /* increment through the ll until we find un unused device_id, * insert the device at that entry */ while ((ll_dev->next != NULL) && (ll_dev->dev.device_fh == (ll_dev->next->dev.device_fh - 1))) ll_dev = ll_dev->next; new_ll_dev->dev.device_fh = ll_dev->dev.device_fh + 1; new_ll_dev->next = ll_dev->next; ll_dev->next = new_ll_dev; } } else { ll_root = new_ll_dev; ll_root->dev.device_fh = 0; } } /* * Remove an entry from the device configuration linked list. */ static struct virtio_net_config_ll * rm_config_ll_entry(struct virtio_net_config_ll *ll_dev, struct virtio_net_config_ll *ll_dev_last) { /* First remove the device and then clean it up. */ if (ll_dev == ll_root) { ll_root = ll_dev->next; cleanup_device(ll_dev); return ll_root; } else { ll_dev_last->next = ll_dev->next; cleanup_device(ll_dev); return ll_dev_last->next; } } /* * Retrieves an entry from the devices configuration linked list. */ static struct virtio_net_config_ll * get_config_ll_entry(unsigned int virtio_idx, unsigned int dom_id) { struct virtio_net_config_ll *ll_dev = ll_root; /* Loop through linked list until the dom_id is found. */ while (ll_dev != NULL) { if (ll_dev->dev.dom_id == dom_id && ll_dev->dev.virtio_idx == virtio_idx) return ll_dev; ll_dev = ll_dev->next; } return NULL; } /* * Initialise all variables in device structure. */ static void init_dev(struct virtio_net *dev) { RTE_SET_USED(dev); } static struct virtio_net_config_ll *new_device(unsigned int virtio_idx, struct xen_guest *guest) { struct virtio_net_config_ll *new_ll_dev; struct vhost_virtqueue *virtqueue_rx, *virtqueue_tx; size_t size, vq_ring_size, vq_size = VQ_DESC_NUM; void *vq_ring_virt_mem; uint64_t gpa; uint32_t i; /* Setup device and virtqueues. */ new_ll_dev = calloc(1, sizeof(struct virtio_net_config_ll)); virtqueue_rx = rte_zmalloc(NULL, sizeof(struct vhost_virtqueue), RTE_CACHE_LINE_SIZE); virtqueue_tx = rte_zmalloc(NULL, sizeof(struct vhost_virtqueue), RTE_CACHE_LINE_SIZE); if (new_ll_dev == NULL || virtqueue_rx == NULL || virtqueue_tx == NULL) goto err; new_ll_dev->dev.virtqueue_rx = virtqueue_rx; new_ll_dev->dev.virtqueue_tx = virtqueue_tx; new_ll_dev->dev.dom_id = guest->dom_id; new_ll_dev->dev.virtio_idx = virtio_idx; /* Initialise device and virtqueues. */ init_dev(&new_ll_dev->dev); size = vring_size(vq_size, VIRTIO_PCI_VRING_ALIGN); vq_ring_size = RTE_ALIGN_CEIL(size, VIRTIO_PCI_VRING_ALIGN); (void)vq_ring_size; vq_ring_virt_mem = guest->vring[virtio_idx].rxvring_addr; vq_vring_init(virtqueue_rx, vq_size, vq_ring_virt_mem, VIRTIO_PCI_VRING_ALIGN); virtqueue_rx->size = vq_size; virtqueue_rx->vhost_hlen = sizeof(struct virtio_net_hdr); vq_ring_virt_mem = guest->vring[virtio_idx].txvring_addr; vq_vring_init(virtqueue_tx, vq_size, vq_ring_virt_mem, VIRTIO_PCI_VRING_ALIGN); virtqueue_tx->size = vq_size; memcpy(&new_ll_dev->dev.mac_address, &guest->vring[virtio_idx].addr, sizeof(struct ether_addr)); /* virtio_memory has to be one per domid */ new_ll_dev->dev.mem = malloc(sizeof(struct virtio_memory) + sizeof(struct virtio_memory_regions) * MAX_XENVIRT_MEMPOOL); new_ll_dev->dev.mem->nregions = guest->pool_num; for (i = 0; i < guest->pool_num; i++) { gpa = new_ll_dev->dev.mem->regions[i].guest_phys_address = (uint64_t)guest->mempool[i].gva; new_ll_dev->dev.mem->regions[i].guest_phys_address_end = gpa + guest->mempool[i].mempfn_num * getpagesize(); new_ll_dev->dev.mem->regions[i].address_offset = (uint64_t)guest->mempool[i].hva - gpa; } new_ll_dev->next = NULL; /* Add entry to device configuration linked list. */ add_config_ll_entry(new_ll_dev); return new_ll_dev; err: if (new_ll_dev) free(new_ll_dev); rte_free(virtqueue_rx); rte_free(virtqueue_tx); return NULL; } static void destroy_guest(struct xen_guest *guest) { uint32_t i; for (i = 0; i < guest->vring_num; i++) cleanup_vring(&guest->vring[i]); /* clean mempool */ for (i = 0; i < guest->pool_num; i++) cleanup_mempool(&guest->mempool[i]); free(guest); return; } /* * This function will cleanup the device and remove it from device configuration linked list. */ static void destroy_device(unsigned int virtio_idx, unsigned int dom_id) { struct virtio_net_config_ll *ll_dev_cur_ctx, *ll_dev_last = NULL; struct virtio_net_config_ll *ll_dev_cur = ll_root; /* clean virtio device */ struct xen_guest *guest = NULL; guest = get_xen_guest(dom_id); if (guest == NULL) return; /* Find the linked list entry for the device to be removed. */ ll_dev_cur_ctx = get_config_ll_entry(virtio_idx, dom_id); while (ll_dev_cur != NULL) { /* If the device is found or a device that doesn't exist is found then it is removed. */ if (ll_dev_cur == ll_dev_cur_ctx) { if ((ll_dev_cur->dev.flags & VIRTIO_DEV_RUNNING)) notify_ops->destroy_device(&(ll_dev_cur->dev)); ll_dev_cur = rm_config_ll_entry(ll_dev_cur, ll_dev_last); } else { ll_dev_last = ll_dev_cur; ll_dev_cur = ll_dev_cur->next; } } RTE_LOG(INFO, XENHOST, " %s guest:%p vring:%p rxvring:%p txvring:%p flag:%p\n", __func__, guest, &guest->vring[virtio_idx], guest->vring[virtio_idx].rxvring_addr, guest->vring[virtio_idx].txvring_addr, guest->vring[virtio_idx].flag); cleanup_vring(&guest->vring[virtio_idx]); guest->vring[virtio_idx].removed = 1; guest->vring_num -= 1; } static void watch_unmap_event(void) { int i; struct xen_guest *guest = NULL; bool remove_request; TAILQ_FOREACH(guest, &guest_root, next) { for (i = 0; i < MAX_VIRTIO; i++) { if (guest->vring[i].dom_id && guest->vring[i].removed == 0 && *guest->vring[i].flag == 0) { RTE_LOG(INFO, XENHOST, "\n\n"); RTE_LOG(INFO, XENHOST, " #####%s: (%d, %d) to be removed\n", __func__, guest->vring[i].dom_id, i); destroy_device(i, guest->dom_id); RTE_LOG(INFO, XENHOST, " %s: DOM %u, vring num: %d\n", __func__, guest->dom_id, guest->vring_num); } } } _find_next_remove: guest = NULL; remove_request = false; TAILQ_FOREACH(guest, &guest_root, next) { if (guest->vring_num == 0) { remove_request = true; break; } } if (remove_request == true) { TAILQ_REMOVE(&guest_root, guest, next); RTE_LOG(INFO, XENHOST, " #####%s: destroy guest (%d)\n", __func__, guest->dom_id); destroy_guest(guest); goto _find_next_remove; } return; } /* * OK, if the guest starts first, it is ok. * if host starts first, it is ok. * if guest starts, and has run for sometime, and host stops and restarts, * then last_used_idx 0? how to solve this. */ static void virtio_init(void) { uint32_t len, e_num; uint32_t i,j; char **dom; char *status; int dom_id; char path[PATH_MAX]; char node[PATH_MAX]; xs_transaction_t th; struct xen_guest *guest; struct virtio_net_config_ll *net_config; char *end; int val; /* init env for watch the node */ if (init_watch() < 0) return; dom = xs_directory(watch.xs, XBT_NULL, "/local/domain", &e_num); for (i = 0; i < e_num; i++) { errno = 0; dom_id = strtol(dom[i], &end, 0); if (errno != 0 || end == NULL || dom_id == 0) continue; for (j = 0; j < RTE_MAX_ETHPORTS; j++) { snprintf(node, PATH_MAX, "%s%d", VIRTIO_START, j); snprintf(path, PATH_MAX, XEN_VM_NODE_FMT, dom_id, node); th = xs_transaction_start(watch.xs); status = xs_read(watch.xs, th, path, &len); xs_transaction_end(watch.xs, th, false); if (status == NULL) break; /* if there's any valid virtio device */ errno = 0; val = strtol(status, &end, 0); if (errno != 0 || end == NULL || dom_id == 0) val = 0; if (val == 1) { guest = add_xen_guest(dom_id); if (guest == NULL) continue; RTE_LOG(INFO, XENHOST, " there's a new virtio existed, new a virtio device\n\n"); RTE_LOG(INFO, XENHOST, " parse_vringnode dom_id %d virtioidx %d\n",dom_id,j); if (parse_vringnode(guest, j)) { RTE_LOG(ERR, XENHOST, " there is invalid information in xenstore\n"); TAILQ_REMOVE(&guest_root, guest, next); destroy_guest(guest); continue; } /*if pool_num > 0, then mempool has already been parsed*/ if (guest->pool_num == 0 && parse_mempoolnode(guest)) { RTE_LOG(ERR, XENHOST, " there is error information in xenstore\n"); TAILQ_REMOVE(&guest_root, guest, next); destroy_guest(guest); continue; } net_config = new_device(j, guest); /* every thing is ready now, added into data core */ notify_ops->new_device(&net_config->dev); } } } free(dom); return; } void virtio_monitor_loop(void) { char **vec; xs_transaction_t th; char *buf; unsigned int len; unsigned int dom_id; uint32_t virtio_idx; struct xen_guest *guest; struct virtio_net_config_ll *net_config; enum fieldnames { FLD_NULL = 0, FLD_LOCAL, FLD_DOMAIN, FLD_ID, FLD_CONTROL, FLD_DPDK, FLD_NODE, _NUM_FLD }; char *str_fld[_NUM_FLD]; char *str; char *end; virtio_init(); while (1) { watch_unmap_event(); usleep(50); vec = xs_check_watch(watch.xs); if (vec == NULL) continue; th = xs_transaction_start(watch.xs); buf = xs_read(watch.xs, th, vec[XS_WATCH_PATH],&len); xs_transaction_end(watch.xs, th, false); if (buf) { /* theres' some node for vhost existed */ if (rte_strsplit(vec[XS_WATCH_PATH], strnlen(vec[XS_WATCH_PATH], PATH_MAX), str_fld, _NUM_FLD, '/') == _NUM_FLD) { if (strstr(str_fld[FLD_NODE], VIRTIO_START)) { errno = 0; str = str_fld[FLD_ID]; dom_id = strtoul(str, &end, 0); if (errno != 0 || end == NULL || end == str ) { RTE_LOG(INFO, XENHOST, "invalid domain id\n"); continue; } errno = 0; str = str_fld[FLD_NODE] + sizeof(VIRTIO_START) - 1; virtio_idx = strtoul(str, &end, 0); if (errno != 0 || end == NULL || end == str || virtio_idx > MAX_VIRTIO) { RTE_LOG(INFO, XENHOST, "invalid virtio idx\n"); continue; } RTE_LOG(INFO, XENHOST, " #####virtio dev (%d, %d) is started\n", dom_id, virtio_idx); guest = add_xen_guest(dom_id); if (guest == NULL) continue; guest->dom_id = dom_id; if (parse_vringnode(guest, virtio_idx)) { RTE_LOG(ERR, XENHOST, " there is invalid information in xenstore\n"); /*guest newly created? guest existed ?*/ TAILQ_REMOVE(&guest_root, guest, next); destroy_guest(guest); continue; } /*if pool_num > 0, then mempool has already been parsed*/ if (guest->pool_num == 0 && parse_mempoolnode(guest)) { RTE_LOG(ERR, XENHOST, " there is error information in xenstore\n"); TAILQ_REMOVE(&guest_root, guest, next); destroy_guest(guest); continue; } net_config = new_device(virtio_idx, guest); RTE_LOG(INFO, XENHOST, " Add to dataplane core\n"); notify_ops->new_device(&net_config->dev); } } } free(vec); } return; } /* * Register ops so that we can add/remove device to data core. */ int init_virtio_xen(struct virtio_net_device_ops const *const ops) { notify_ops = ops; if (xenhost_init()) return -1; return 0; } ================================================ FILE: examples/vhost_xen/virtio-net.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_NET_H_ #define _VIRTIO_NET_H_ #include #define VQ_DESC_NUM 256 /* Used to indicate that the device is running on a data core */ #define VIRTIO_DEV_RUNNING 1 /* * Structure contains variables relevant to TX/RX virtqueues. */ struct vhost_virtqueue { struct vring_desc *desc; /* Virtqueue descriptor ring. */ struct vring_avail *avail; /* Virtqueue available ring. */ struct vring_used *used; /* Virtqueue used ring. */ uint32_t size; /* Size of descriptor ring. */ uint32_t vhost_hlen; /* Vhost header length (varies depending on RX merge buffers. */ volatile uint16_t last_used_idx; /* Last index used on the available ring */ volatile uint16_t last_used_idx_res; /* Used for multiple devices reserving buffers. */ } __rte_cache_aligned; /* * Device structure contains all configuration information relating to the device. */ struct virtio_net { struct vhost_virtqueue *virtqueue_tx; /* Contains all TX virtqueue information. */ struct vhost_virtqueue *virtqueue_rx; /* Contains all RX virtqueue information. */ struct virtio_memory *mem; /* QEMU memory and memory region information. */ struct ether_addr mac_address; /* Device MAC address (Obtained on first TX packet). */ uint32_t flags; /* Device flags. Only used to check if device is running on data core. */ uint32_t vlan_tag; /* Vlan tag for device. Currently set to device_id (0-63). */ uint32_t vmdq_rx_q; uint64_t device_fh; /* device identifier. */ uint16_t coreid; volatile uint8_t ready; /* A device is set as ready if the MAC address has been set. */ volatile uint8_t remove; /* Device is marked for removal from the data core. */ uint32_t virtio_idx; /* Index of virtio device */ uint32_t dom_id; /* Domain id of xen guest */ } ___rte_cache_aligned; /* * Device linked list structure for configuration. */ struct virtio_net_config_ll { struct virtio_net dev; /* Virtio device. */ struct virtio_net_config_ll *next; /* Next entry on linked list. */ }; /* * Information relating to memory regions including offsets to addresses in QEMUs memory file. */ struct virtio_memory_regions { uint64_t guest_phys_address; /* Base guest physical address of region. */ uint64_t guest_phys_address_end; /* End guest physical address of region. */ uint64_t memory_size; /* Size of region. */ uint64_t userspace_address; /* Base userspace address of region. */ uint64_t address_offset; /* Offset of region for address translation. */ }; /* * Memory structure includes region and mapping information. */ struct virtio_memory { uint32_t nregions; /* Number of memory regions. */ struct virtio_memory_regions regions[0]; /* Memory region information. */ }; /* * Device operations to add/remove device. */ struct virtio_net_device_ops { int (* new_device)(struct virtio_net *); /* Add device. */ void (* destroy_device) (volatile struct virtio_net *); /* Remove device. */ }; struct vhost_net_device_ops const * get_virtio_net_callbacks(void); #endif ================================================ FILE: examples/vhost_xen/xen_vhost.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _XEN_VHOST_H_ #define _XEN_VHOST_H_ #include #include #include "virtio-net.h" #define RTE_LOGTYPE_XENHOST RTE_LOGTYPE_USER1 #define XEN_VM_ROOTNODE_FMT "/local/domain/%d/control/dpdk" #define XEN_VM_NODE_FMT "/local/domain/%d/control/dpdk/%s" #define XEN_MEMPOOL_SUFFIX "mempool_gref" #define XEN_RXVRING_SUFFIX "rx_vring_gref" #define XEN_TXVRING_SUFFIX "tx_vring_gref" #define XEN_GVA_SUFFIX "mempool_va" #define XEN_VRINGFLAG_SUFFIX "vring_flag" #define XEN_ADDR_SUFFIX "ether_addr" #define VIRTIO_START "event_type_start_" #define XEN_GREF_SPLITTOKEN ',' #define MAX_XENVIRT_MEMPOOL 16 #define MAX_VIRTIO 32 #define MAX_GREF_PER_NODE 64 /* 128 MB memory */ #define PAGE_SIZE 4096 #define PAGE_PFNNUM (PAGE_SIZE / sizeof(uint32_t)) #define XEN_GNTDEV_FNAME "/dev/xen/gntdev" /* xen grant reference info in one grant node */ struct xen_gnt { uint32_t gref; /* grant reference for this node */ union { int gref; /* grant reference */ uint32_t pfn_num; /* guest pfn number of grant reference */ } gref_pfn[PAGE_PFNNUM]; }__attribute__((__packed__)); /* structure for mempool or vring node list */ struct xen_gntnode { uint32_t gnt_num; /* grant reference number */ struct xen_gnt *gnt_info; /* grant reference info */ }; struct xen_vring { uint32_t dom_id; uint32_t virtio_idx; /* index of virtio device */ void *rxvring_addr; /* mapped virtual address of rxvring */ void *txvring_addr; /* mapped virtual address of txvring */ uint32_t rxpfn_num; /* number of gpfn for rxvring */ uint32_t txpfn_num; /* number of gpfn for txvring */ uint32_t *rxpfn_tbl; /* array of rxvring gpfn */ uint32_t *txpfn_tbl; /* array of txvring gpfn */ uint64_t *rx_pindex; /* index used to release rx grefs */ uint64_t *tx_pindex; /* index used to release tx grefs */ uint64_t flag_index; uint8_t *flag; /* cleared to zero on guest unmap */ struct ether_addr addr; /* ethernet address of virtio device */ uint8_t removed; }; struct xen_mempool { uint32_t dom_id; /* guest domain id */ uint32_t pool_idx; /* index of memory pool */ void *gva; /* guest virtual address of mbuf pool */ void *hva; /* host virtual address of mbuf pool */ uint32_t mempfn_num; /* number of gpfn for mbuf pool */ uint32_t *mempfn_tbl; /* array of mbuf pool gpfn */ uint64_t *pindex; /* index used to release grefs */ }; struct xen_guest { TAILQ_ENTRY(xen_guest) next; int32_t dom_id; /* guest domain id */ uint32_t pool_num; /* number of mbuf pool of the guest */ uint32_t vring_num; /* number of virtio ports of the guest */ /* array contain the guest mbuf pool info */ struct xen_mempool mempool[MAX_XENVIRT_MEMPOOL]; /* array contain the guest rx/tx vring info */ struct xen_vring vring[MAX_VIRTIO]; }; TAILQ_HEAD(xen_guestlist, xen_guest); int parse_mempoolnode(struct xen_guest *guest); int xenhost_init(void); int parse_vringnode(struct xen_guest *guest, uint32_t virtio_idx); int parse_mempoolnode(struct xen_guest *guest); void cleanup_mempool(struct xen_mempool *mempool); void cleanup_vring(struct xen_vring *vring); void virtio_monitor_loop(void); int init_virtio_xen(struct virtio_net_device_ops const * const); #endif ================================================ FILE: examples/vhost_xen/xenstore_parse.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #if __XEN_LATEST_INTERFACE_VERSION__ < 0x00040200 #include #else #include #endif #include #include #include #include #include #include #include #include "xen_vhost.h" /* xenstore handle */ static struct xs_handle *xs = NULL; /* gntdev file descriptor to map grant pages */ static int d_fd = -1; /* * The grant node format in xenstore for vring/mpool is like: * idx#_rx_vring_gref = "gref1#, gref2#, gref3#" * idx#_mempool_gref = "gref1#, gref2#, gref3#" * each gref# is the grant reference for a shared page. * In each shared page, we store the grant_node_item items. */ struct grant_node_item { uint32_t gref; uint32_t pfn; } __attribute__((packed)); int cmdline_parse_etheraddr(void *tk, const char *srcbuf, void *res, unsigned ressize); /* Map grant ref refid at addr_ori*/ static void * xen_grant_mmap(void *addr_ori, int domid, int refid, uint64_t *pindex) { struct ioctl_gntdev_map_grant_ref arg; void *addr = NULL; int pg_sz = getpagesize(); arg.count = 1; arg.refs[0].domid = domid; arg.refs[0].ref = refid; int rv = ioctl(d_fd, IOCTL_GNTDEV_MAP_GRANT_REF, &arg); if (rv) { RTE_LOG(ERR, XENHOST, " %s: (%d,%d) %s (ioctl failed)\n", __func__, domid, refid, strerror(errno)); return NULL; } if (addr_ori == NULL) addr = mmap(addr_ori, pg_sz, PROT_READ|PROT_WRITE, MAP_SHARED, d_fd, arg.index); else addr = mmap(addr_ori, pg_sz, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_FIXED, d_fd, arg.index); if (addr == MAP_FAILED) { RTE_LOG(ERR, XENHOST, " %s: (%d, %d) %s (map failed)\n", __func__, domid, refid, strerror(errno)); return NULL; } if (pindex) *pindex = arg.index; return addr; } /* Unmap one grant ref, and munmap must be called before this */ static int xen_unmap_grant_ref(uint64_t index) { struct ioctl_gntdev_unmap_grant_ref arg; int rv; arg.count = 1; arg.index = index; rv = ioctl(d_fd, IOCTL_GNTDEV_UNMAP_GRANT_REF, &arg); if (rv) { RTE_LOG(ERR, XENHOST, " %s: index 0x%" PRIx64 "unmap failed\n", __func__, index); return -1; } return 0; } /* * Reserve a virtual address space. * On success, returns the pointer. On failure, returns NULL. */ static void * get_xen_virtual(size_t size, size_t page_sz) { void *addr; uintptr_t aligned_addr; addr = mmap(NULL, size + page_sz, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { RTE_LOG(ERR, XENHOST, "failed get a virtual area\n"); return NULL; } aligned_addr = RTE_ALIGN_CEIL((uintptr_t)addr, page_sz); munmap(addr, aligned_addr - (uintptr_t)addr); munmap((void *)(aligned_addr + size), page_sz + (uintptr_t)addr - aligned_addr); addr = (void *)(aligned_addr); return addr; } static void free_xen_virtual(void *addr, size_t size, size_t page_sz __rte_unused) { if (addr) munmap(addr, size); } /* * Returns val str in xenstore. * @param path * Full path string for key * @return * Pointer to Val str, NULL on failure */ static char * xen_read_node(char *path, uint32_t *len) { char *buf; buf = xs_read(xs, XBT_NULL, path, len); return buf; } static int cal_pagenum(struct xen_gnt *gnt) { unsigned int i; /* * the items in the page are in the format of * gref#,pfn#,...,gref#,pfn# * FIXME, 0 is reserved by system, use it as terminator. */ for (i = 0; i < (PAGE_PFNNUM) / 2; i++) { if (gnt->gref_pfn[i * 2].gref <= 0) break; } return i; } /* Frees memory allocated to a grant node */ static void xen_free_gntnode(struct xen_gntnode *gntnode) { if (gntnode == NULL) return; if (gntnode->gnt_info) free(gntnode->gnt_info); free(gntnode); } /* * Parse a grant node. * @param domid * Guest domain id. * @param path * Full path string for a grant node, like for the following (key, val) pair * idx#_mempool_gref = "gref#, gref#, gref#" * path = 'local/domain/domid/control/dpdk/idx#_mempool_gref' * gref# is a shared page contain packed (gref,pfn) entries * @return * Returns the pointer to xen_gntnode */ static struct xen_gntnode * parse_gntnode(int dom_id, char *path) { char **gref_list = NULL; uint32_t i, len, gref_num; void *addr = NULL; char *buf = NULL; struct xen_gntnode *gntnode = NULL; struct xen_gnt *gnt = NULL; int pg_sz = getpagesize(); char *end; uint64_t index; if ((buf = xen_read_node(path, &len)) == NULL) goto err; gref_list = malloc(MAX_GREF_PER_NODE * sizeof(char *)); if (gref_list == NULL) goto err; gref_num = rte_strsplit(buf, len, gref_list, MAX_GREF_PER_NODE, XEN_GREF_SPLITTOKEN); if (gref_num == 0) { RTE_LOG(ERR, XENHOST, " %s: invalid grant node format\n", __func__); goto err; } gntnode = calloc(1, sizeof(struct xen_gntnode)); gnt = calloc(gref_num, sizeof(struct xen_gnt)); if (gnt == NULL || gntnode == NULL) goto err; for (i = 0; i < gref_num; i++) { errno = 0; gnt[i].gref = strtol(gref_list[i], &end, 0); if (errno != 0 || end == NULL || end == gref_list[i] || (*end != '\0' && *end != XEN_GREF_SPLITTOKEN)) { RTE_LOG(ERR, XENHOST, " %s: parse grant node item failed\n", __func__); goto err; } addr = xen_grant_mmap(NULL, dom_id, gnt[i].gref, &index); if (addr == NULL) { RTE_LOG(ERR, XENHOST, " %s: map gref %u failed\n", __func__, gnt[i].gref); goto err; } RTE_LOG(INFO, XENHOST, " %s: map gref %u to %p\n", __func__, gnt[i].gref, addr); memcpy(gnt[i].gref_pfn, addr, pg_sz); if (munmap(addr, pg_sz)) { RTE_LOG(INFO, XENHOST, " %s: unmap gref %u failed\n", __func__, gnt[i].gref); goto err; } if (xen_unmap_grant_ref(index)) { RTE_LOG(INFO, XENHOST, " %s: release gref %u failed\n", __func__, gnt[i].gref); goto err; } } gntnode->gnt_num = gref_num; gntnode->gnt_info = gnt; free(buf); free(gref_list); return gntnode; err: if (gnt) free(gnt); if (gntnode) free(gntnode); if (gref_list) free(gref_list); if (buf) free(buf); return NULL; } /* * This function maps grant node of vring or mbuf pool to a continous virtual address space, * and returns mapped address, pfn array, index array * @param gntnode * Pointer to grant node * @param domid * Guest domain id * @param ppfn * Pointer to pfn array, caller should free this array * @param pgs * Pointer to number of pages * @param ppindex * Pointer to index array, used to release grefs when to free this node * @return * Pointer to mapped virtual address, NULL on failure */ static void * map_gntnode(struct xen_gntnode *gntnode, int domid, uint32_t **ppfn, uint32_t *pgs, uint64_t **ppindex) { struct xen_gnt *gnt; uint32_t i, j; size_t total_pages = 0; void *addr; uint32_t *pfn; uint64_t *pindex; uint32_t pfn_num = 0; int pg_sz; if (gntnode == NULL) return NULL; pg_sz = getpagesize(); for (i = 0; i < gntnode->gnt_num; i++) { gnt = gntnode->gnt_info + i; total_pages += cal_pagenum(gnt); } if ((addr = get_xen_virtual(total_pages * pg_sz, pg_sz)) == NULL) { RTE_LOG(ERR, XENHOST, " %s: failed get_xen_virtual\n", __func__); return NULL; } pfn = calloc(total_pages, (size_t)sizeof(uint32_t)); pindex = calloc(total_pages, (size_t)sizeof(uint64_t)); if (pfn == NULL || pindex == NULL) { free_xen_virtual(addr, total_pages * pg_sz, pg_sz); free(pfn); free(pindex); return NULL; } RTE_LOG(INFO, XENHOST, " %s: total pages:%zu, map to [%p, %p]\n", __func__, total_pages, addr, RTE_PTR_ADD(addr, total_pages * pg_sz - 1)); for (i = 0; i < gntnode->gnt_num; i++) { gnt = gntnode->gnt_info + i; for (j = 0; j < (PAGE_PFNNUM) / 2; j++) { if ((gnt->gref_pfn[j * 2].gref) <= 0) goto _end; /*alternative: batch map, or through libxc*/ if (xen_grant_mmap(RTE_PTR_ADD(addr, pfn_num * pg_sz), domid, gnt->gref_pfn[j * 2].gref, &pindex[pfn_num]) == NULL) { goto mmap_failed; } pfn[pfn_num] = gnt->gref_pfn[j * 2 + 1].pfn_num; pfn_num++; } } mmap_failed: if (pfn_num) munmap(addr, pfn_num * pg_sz); for (i = 0; i < pfn_num; i++) { xen_unmap_grant_ref(pindex[i]); } free(pindex); free(pfn); return NULL; _end: if (ppindex) *ppindex = pindex; else free(pindex); if (ppfn) *ppfn = pfn; else free(pfn); if (pgs) *pgs = total_pages; return addr; } static int parse_mpool_va(struct xen_mempool *mempool) { char path[PATH_MAX] = {0}; char *buf; uint32_t len; char *end; int ret = -1; errno = 0; snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_GVA_SUFFIX, mempool->dom_id, mempool->pool_idx); if((buf = xen_read_node(path, &len)) == NULL) goto out; mempool->gva = (void *)strtoul(buf, &end, 16); if (errno != 0 || end == NULL || end == buf || *end != '\0') { mempool->gva = NULL; goto out; } ret = 0; out: if (buf) free(buf); return ret; } /* * map mbuf pool */ static int map_mempoolnode(struct xen_gntnode *gntnode, struct xen_mempool *mempool) { if (gntnode == NULL || mempool == NULL) return -1; mempool->hva = map_gntnode(gntnode, mempool->dom_id, &mempool->mempfn_tbl, &mempool->mempfn_num, &mempool->pindex); RTE_LOG(INFO, XENHOST, " %s: map mempool at %p\n", __func__, (void *)mempool->hva); if (mempool->hva) return 0; else { return -1; } } void cleanup_mempool(struct xen_mempool *mempool) { int pg_sz = getpagesize(); uint32_t i; if (mempool->hva) munmap(mempool->hva, mempool->mempfn_num * pg_sz); mempool->hva = NULL; if (mempool->pindex) { RTE_LOG(INFO, XENHOST, " %s: unmap dom %02u mempool%02u %u grefs\n", __func__, mempool->dom_id, mempool->pool_idx, mempool->mempfn_num); for (i = 0; i < mempool->mempfn_num; i ++) { xen_unmap_grant_ref(mempool->pindex[i]); } } mempool->pindex = NULL; if (mempool->mempfn_tbl) free(mempool->mempfn_tbl); mempool->mempfn_tbl = NULL; } /* * process mempool node idx#_mempool_gref, idx = 0, 1, 2... * untill we encounter a node that doesn't exist. */ int parse_mempoolnode(struct xen_guest *guest) { uint32_t i, len; char path[PATH_MAX] = {0}; struct xen_gntnode *gntnode = NULL; struct xen_mempool *mempool = NULL; char *buf; bzero(&guest->mempool, MAX_XENVIRT_MEMPOOL * sizeof(guest->mempool[0])); guest->pool_num = 0; while (1) { /* check if null terminated */ snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_MEMPOOL_SUFFIX, guest->dom_id, guest->pool_num); if ((buf = xen_read_node(path, &len)) != NULL) { /* this node exists */ free(buf); } else { if (guest->pool_num == 0) { RTE_LOG(ERR, PMD, "no mempool found\n"); return -1; } break; } mempool = &guest->mempool[guest->pool_num]; mempool->dom_id = guest->dom_id; mempool->pool_idx = guest->pool_num; RTE_LOG(INFO, XENHOST, " %s: mempool %u parse gntnode %s\n", __func__, guest->pool_num, path); gntnode = parse_gntnode(guest->dom_id, path); if (gntnode == NULL) goto err; if (parse_mpool_va(mempool)) goto err; RTE_LOG(INFO, XENHOST, " %s: mempool %u map gntnode %s\n", __func__, guest->pool_num, path); if (map_mempoolnode(gntnode, mempool)) goto err; xen_free_gntnode(gntnode); guest->pool_num++; } return 0; err: if (gntnode) xen_free_gntnode(gntnode); for (i = 0; i < MAX_XENVIRT_MEMPOOL ; i++) { cleanup_mempool(&guest->mempool[i]); } /* reinitialise mempool */ bzero(&guest->mempool, MAX_XENVIRT_MEMPOOL * sizeof(guest->mempool[0])); return -1; } static int xen_map_vringflag(struct xen_vring *vring) { char path[PATH_MAX] = {0}; char *buf; uint32_t len,gref; int pg_sz = getpagesize(); char *end; snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_VRINGFLAG_SUFFIX, vring->dom_id, vring->virtio_idx); if((buf = xen_read_node(path, &len)) == NULL) goto err; errno = 0; gref = strtol(buf, &end, 0); if (errno != 0 || end == NULL || end == buf) { goto err; } vring->flag = xen_grant_mmap(0, vring->dom_id, gref, &vring->flag_index); if (vring->flag == NULL || *vring->flag == 0) goto err; free(buf); return 0; err: if (buf) free(buf); if (vring->flag) { munmap(vring->flag, pg_sz); vring->flag = NULL; xen_unmap_grant_ref(vring->flag_index); } return -1; } static int xen_map_rxvringnode(struct xen_gntnode *gntnode, struct xen_vring *vring) { vring->rxvring_addr = map_gntnode(gntnode, vring->dom_id, &vring->rxpfn_tbl, &vring->rxpfn_num, &vring->rx_pindex); RTE_LOG(INFO, XENHOST, " %s: map rx vring at %p\n", __func__, (void *)vring->rxvring_addr); if (vring->rxvring_addr) return 0; else return -1; } static int xen_map_txvringnode(struct xen_gntnode *gntnode, struct xen_vring *vring) { vring->txvring_addr = map_gntnode(gntnode, vring->dom_id, &vring->txpfn_tbl, &vring->txpfn_num, &vring->tx_pindex); RTE_LOG(INFO, XENHOST, " %s: map tx vring at %p\n", __func__, (void *)vring->txvring_addr); if (vring->txvring_addr) return 0; else return -1; } void cleanup_vring(struct xen_vring *vring) { int pg_sz = getpagesize(); uint32_t i; RTE_LOG(INFO, XENHOST, " %s: cleanup dom %u vring %u\n", __func__, vring->dom_id, vring->virtio_idx); if (vring->rxvring_addr) { munmap(vring->rxvring_addr, vring->rxpfn_num * pg_sz); RTE_LOG(INFO, XENHOST, " %s: unmap rx vring [%p, %p]\n", __func__, vring->rxvring_addr, RTE_PTR_ADD(vring->rxvring_addr, vring->rxpfn_num * pg_sz - 1)); } vring->rxvring_addr = NULL; if (vring->rx_pindex) { RTE_LOG(INFO, XENHOST, " %s: unmap rx vring %u grefs\n", __func__, vring->rxpfn_num); for (i = 0; i < vring->rxpfn_num; i++) { xen_unmap_grant_ref(vring->rx_pindex[i]); } } vring->rx_pindex = NULL; if (vring->rxpfn_tbl) free(vring->rxpfn_tbl); vring->rxpfn_tbl = NULL; if (vring->txvring_addr) { munmap(vring->txvring_addr, vring->txpfn_num * pg_sz); RTE_LOG(INFO, XENHOST, " %s: unmap tx vring [%p, %p]\n", __func__, vring->txvring_addr, RTE_PTR_ADD(vring->txvring_addr, vring->txpfn_num * pg_sz - 1)); } vring->txvring_addr = NULL; if (vring->tx_pindex) { RTE_LOG(INFO, XENHOST, " %s: unmap tx vring %u grefs\n", __func__, vring->txpfn_num); for (i = 0; i < vring->txpfn_num; i++) { xen_unmap_grant_ref(vring->tx_pindex[i]); } } vring->tx_pindex = NULL; if (vring->txpfn_tbl) free(vring->txpfn_tbl); vring->txpfn_tbl = NULL; if (vring->flag) { if (!munmap((void *)vring->flag, pg_sz)) RTE_LOG(INFO, XENHOST, " %s: unmap flag page at %p\n", __func__, vring->flag); if (!xen_unmap_grant_ref(vring->flag_index)) RTE_LOG(INFO, XENHOST, " %s: release flag ref index 0x%" PRIx64 "\n", __func__, vring->flag_index); } vring->flag = NULL; return; } static int xen_parse_etheraddr(struct xen_vring *vring) { char path[PATH_MAX] = {0}; char *buf; uint32_t len; int ret = -1; snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_ADDR_SUFFIX, vring->dom_id, vring->virtio_idx); if ((buf = xen_read_node(path, &len)) == NULL) goto out; if (cmdline_parse_etheraddr(NULL, buf, &vring->addr, sizeof(vring->addr)) < 0) goto out; ret = 0; out: if (buf) free(buf); return ret; } int parse_vringnode(struct xen_guest *guest, uint32_t virtio_idx) { char path[PATH_MAX] = {0}; struct xen_gntnode *rx_gntnode = NULL; struct xen_gntnode *tx_gntnode = NULL; struct xen_vring *vring = NULL; /*check if null terminated */ snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_RXVRING_SUFFIX, guest->dom_id, virtio_idx); RTE_LOG(INFO, XENHOST, " %s: virtio %u parse rx gntnode %s\n", __func__, virtio_idx, path); rx_gntnode = parse_gntnode(guest->dom_id, path); if (rx_gntnode == NULL) goto err; /*check if null terminated */ snprintf(path, sizeof(path), XEN_VM_ROOTNODE_FMT"/%d_"XEN_TXVRING_SUFFIX, guest->dom_id, virtio_idx); RTE_LOG(INFO, XENHOST, " %s: virtio %u parse tx gntnode %s\n", __func__, virtio_idx, path); tx_gntnode = parse_gntnode(guest->dom_id, path); if (tx_gntnode == NULL) goto err; vring = &guest->vring[virtio_idx]; bzero(vring, sizeof(*vring)); vring->dom_id = guest->dom_id; vring->virtio_idx = virtio_idx; if (xen_parse_etheraddr(vring) != 0) goto err; RTE_LOG(INFO, XENHOST, " %s: virtio %u map rx gntnode %s\n", __func__, virtio_idx, path); if (xen_map_rxvringnode(rx_gntnode, vring) != 0) goto err; RTE_LOG(INFO, XENHOST, " %s: virtio %u map tx gntnode %s\n", __func__, virtio_idx, path); if (xen_map_txvringnode(tx_gntnode, vring) != 0) goto err; if (xen_map_vringflag(vring) != 0) goto err; guest->vring_num++; xen_free_gntnode(rx_gntnode); xen_free_gntnode(tx_gntnode); return 0; err: if (rx_gntnode) xen_free_gntnode(rx_gntnode); if (tx_gntnode) xen_free_gntnode(tx_gntnode); if (vring) { cleanup_vring(vring); bzero(vring, sizeof(*vring)); } return -1; } /* * Open xen grant dev driver * @return * 0 on success, -1 on failure. */ static int xen_grant_init(void) { d_fd = open(XEN_GNTDEV_FNAME, O_RDWR); return d_fd == -1? (-1): (0); } /* * Initialise xenstore handle and open grant dev driver. * @return * 0 on success, -1 on failure. */ int xenhost_init(void) { xs = xs_daemon_open(); if (xs == NULL) { rte_panic("failed initialize xen daemon handler"); return -1; } if (xen_grant_init()) return -1; return 0; } ================================================ FILE: examples/vm_power_manager/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = vm_power_mgr # all source are stored in SRCS-y SRCS-y := main.c vm_power_cli.c power_manager.c channel_manager.c SRCS-y += channel_monitor.c CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) LDLIBS += -lvirt # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/vm_power_manager/channel_manager.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "channel_manager.h" #include "channel_commands.h" #include "channel_monitor.h" #define RTE_LOGTYPE_CHANNEL_MANAGER RTE_LOGTYPE_USER1 #define ITERATIVE_BITMASK_CHECK_64(mask_u64b, i) \ for (i = 0; mask_u64b; mask_u64b &= ~(1ULL << i++)) \ if ((mask_u64b >> i) & 1) \ /* Global pointer to libvirt connection */ static virConnectPtr global_vir_conn_ptr; static unsigned char *global_cpumaps; static virVcpuInfo *global_vircpuinfo; static size_t global_maplen; static unsigned global_n_host_cpus; /* * Represents a single Virtual Machine */ struct virtual_machine_info { char name[CHANNEL_MGR_MAX_NAME_LEN]; rte_atomic64_t pcpu_mask[CHANNEL_CMDS_MAX_CPUS]; struct channel_info *channels[CHANNEL_CMDS_MAX_VM_CHANNELS]; uint64_t channel_mask; uint8_t num_channels; enum vm_status status; virDomainPtr domainPtr; virDomainInfo info; rte_spinlock_t config_spinlock; LIST_ENTRY(virtual_machine_info) vms_info; }; LIST_HEAD(, virtual_machine_info) vm_list_head; static struct virtual_machine_info * find_domain_by_name(const char *name) { struct virtual_machine_info *info; LIST_FOREACH(info, &vm_list_head, vms_info) { if (!strncmp(info->name, name, CHANNEL_MGR_MAX_NAME_LEN-1)) return info; } return NULL; } static int update_pcpus_mask(struct virtual_machine_info *vm_info) { virVcpuInfoPtr cpuinfo; unsigned i, j; int n_vcpus; uint64_t mask; memset(global_cpumaps, 0, CHANNEL_CMDS_MAX_CPUS*global_maplen); if (!virDomainIsActive(vm_info->domainPtr)) { n_vcpus = virDomainGetVcpuPinInfo(vm_info->domainPtr, vm_info->info.nrVirtCpu, global_cpumaps, global_maplen, VIR_DOMAIN_AFFECT_CONFIG); if (n_vcpus < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for " "in-active VM '%s'\n", vm_info->name); return -1; } goto update_pcpus; } memset(global_vircpuinfo, 0, sizeof(*global_vircpuinfo)* CHANNEL_CMDS_MAX_CPUS); cpuinfo = global_vircpuinfo; n_vcpus = virDomainGetVcpus(vm_info->domainPtr, cpuinfo, CHANNEL_CMDS_MAX_CPUS, global_cpumaps, global_maplen); if (n_vcpus < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting vCPU info for " "active VM '%s'\n", vm_info->name); return -1; } update_pcpus: if (n_vcpus >= CHANNEL_CMDS_MAX_CPUS) { RTE_LOG(ERR, CHANNEL_MANAGER, "Number of vCPUS(%u) is out of range " "0...%d\n", n_vcpus, CHANNEL_CMDS_MAX_CPUS-1); return -1; } if (n_vcpus != vm_info->info.nrVirtCpu) { RTE_LOG(INFO, CHANNEL_MANAGER, "Updating the number of vCPUs for VM '%s" " from %d -> %d\n", vm_info->name, vm_info->info.nrVirtCpu, n_vcpus); vm_info->info.nrVirtCpu = n_vcpus; } for (i = 0; i < vm_info->info.nrVirtCpu; i++) { mask = 0; for (j = 0; j < global_n_host_cpus; j++) { if (VIR_CPU_USABLE(global_cpumaps, global_maplen, i, j) > 0) { mask |= 1ULL << j; } } rte_atomic64_set(&vm_info->pcpu_mask[i], mask); } return 0; } int set_pcpus_mask(char *vm_name, unsigned vcpu, uint64_t core_mask) { unsigned i = 0; int flags = VIR_DOMAIN_AFFECT_LIVE|VIR_DOMAIN_AFFECT_CONFIG; struct virtual_machine_info *vm_info; uint64_t mask = core_mask; if (vcpu >= CHANNEL_CMDS_MAX_CPUS) { RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds max allowable(%d)\n", vcpu, CHANNEL_CMDS_MAX_CPUS-1); return -1; } vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name); return -1; } if (!virDomainIsActive(vm_info->domainPtr)) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU " "mask(0x%"PRIx64") for VM '%s', VM is not active\n", vcpu, core_mask, vm_info->name); return -1; } if (vcpu >= vm_info->info.nrVirtCpu) { RTE_LOG(ERR, CHANNEL_MANAGER, "vCPU(%u) exceeds the assigned number of " "vCPUs(%u)\n", vcpu, vm_info->info.nrVirtCpu); return -1; } memset(global_cpumaps, 0 , CHANNEL_CMDS_MAX_CPUS * global_maplen); ITERATIVE_BITMASK_CHECK_64(mask, i) { VIR_USE_CPU(global_cpumaps, i); if (i >= global_n_host_cpus) { RTE_LOG(ERR, CHANNEL_MANAGER, "CPU(%u) exceeds the available " "number of CPUs(%u)\n", i, global_n_host_cpus); return -1; } } if (virDomainPinVcpuFlags(vm_info->domainPtr, vcpu, global_cpumaps, global_maplen, flags) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to set vCPU(%u) to pCPU " "mask(0x%"PRIx64") for VM '%s'\n", vcpu, core_mask, vm_info->name); return -1; } rte_atomic64_set(&vm_info->pcpu_mask[vcpu], core_mask); return 0; } int set_pcpu(char *vm_name, unsigned vcpu, unsigned core_num) { uint64_t mask = 1ULL << core_num; return set_pcpus_mask(vm_name, vcpu, mask); } uint64_t get_pcpus_mask(struct channel_info *chan_info, unsigned vcpu) { struct virtual_machine_info *vm_info = (struct virtual_machine_info *)chan_info->priv_info; return rte_atomic64_read(&vm_info->pcpu_mask[vcpu]); } static inline int channel_exists(struct virtual_machine_info *vm_info, unsigned channel_num) { rte_spinlock_lock(&(vm_info->config_spinlock)); if (vm_info->channel_mask & (1ULL << channel_num)) { rte_spinlock_unlock(&(vm_info->config_spinlock)); return 1; } rte_spinlock_unlock(&(vm_info->config_spinlock)); return 0; } static int open_non_blocking_channel(struct channel_info *info) { int ret, flags; struct sockaddr_un sock_addr; fd_set soc_fd_set; struct timeval tv; info->fd = socket(AF_UNIX, SOCK_STREAM, 0); if (info->fd == -1) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error(%s) creating socket for '%s'\n", strerror(errno), info->channel_path); return -1; } sock_addr.sun_family = AF_UNIX; memcpy(&sock_addr.sun_path, info->channel_path, strlen(info->channel_path)+1); /* Get current flags */ flags = fcntl(info->fd, F_GETFL, 0); if (flags < 0) { RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) fcntl get flags socket for" "'%s'\n", strerror(errno), info->channel_path); return 1; } /* Set to Non Blocking */ flags |= O_NONBLOCK; if (fcntl(info->fd, F_SETFL, flags) < 0) { RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) setting non-blocking " "socket for '%s'\n", strerror(errno), info->channel_path); return -1; } ret = connect(info->fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); if (ret < 0) { /* ECONNREFUSED error is given when VM is not active */ if (errno == ECONNREFUSED) { RTE_LOG(WARNING, CHANNEL_MANAGER, "VM is not active or has not " "activated its endpoint to channel %s\n", info->channel_path); return -1; } /* Wait for tv_sec if in progress */ else if (errno == EINPROGRESS) { tv.tv_sec = 2; tv.tv_usec = 0; FD_ZERO(&soc_fd_set); FD_SET(info->fd, &soc_fd_set); if (select(info->fd+1, NULL, &soc_fd_set, NULL, &tv) > 0) { RTE_LOG(WARNING, CHANNEL_MANAGER, "Timeout or error on channel " "'%s'\n", info->channel_path); return -1; } } else { /* Any other error */ RTE_LOG(WARNING, CHANNEL_MANAGER, "Error(%s) connecting socket" " for '%s'\n", strerror(errno), info->channel_path); return -1; } } return 0; } static int setup_channel_info(struct virtual_machine_info **vm_info_dptr, struct channel_info **chan_info_dptr, unsigned channel_num) { struct channel_info *chan_info = *chan_info_dptr; struct virtual_machine_info *vm_info = *vm_info_dptr; chan_info->channel_num = channel_num; chan_info->priv_info = (void *)vm_info; chan_info->status = CHANNEL_MGR_CHANNEL_DISCONNECTED; if (open_non_blocking_channel(chan_info) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Could not open channel: " "'%s' for VM '%s'\n", chan_info->channel_path, vm_info->name); return -1; } if (add_channel_to_monitor(&chan_info) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Could add channel: " "'%s' to epoll ctl for VM '%s'\n", chan_info->channel_path, vm_info->name); return -1; } rte_spinlock_lock(&(vm_info->config_spinlock)); vm_info->num_channels++; vm_info->channel_mask |= 1ULL << channel_num; vm_info->channels[channel_num] = chan_info; chan_info->status = CHANNEL_MGR_CHANNEL_CONNECTED; rte_spinlock_unlock(&(vm_info->config_spinlock)); return 0; } int add_all_channels(const char *vm_name) { DIR *d; struct dirent *dir; struct virtual_machine_info *vm_info; struct channel_info *chan_info; char *token, *remaining, *tail_ptr; char socket_name[PATH_MAX]; unsigned channel_num; int num_channels_enabled = 0; /* verify VM exists */ vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' not found" " during channel discovery\n", vm_name); return 0; } if (!virDomainIsActive(vm_info->domainPtr)) { RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name); vm_info->status = CHANNEL_MGR_VM_INACTIVE; return 0; } d = opendir(CHANNEL_MGR_SOCKET_PATH); if (d == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error opening directory '%s': %s\n", CHANNEL_MGR_SOCKET_PATH, strerror(errno)); return -1; } while ((dir = readdir(d)) != NULL) { if (!strncmp(dir->d_name, ".", 1) || !strncmp(dir->d_name, "..", 2)) continue; snprintf(socket_name, sizeof(socket_name), "%s", dir->d_name); remaining = socket_name; /* Extract vm_name from "." */ token = strsep(&remaining, "."); if (remaining == NULL) continue; if (strncmp(vm_name, token, CHANNEL_MGR_MAX_NAME_LEN)) continue; /* remaining should contain only */ errno = 0; channel_num = (unsigned)strtol(remaining, &tail_ptr, 0); if ((errno != 0) || (remaining[0] == '\0') || tail_ptr == NULL || (*tail_ptr != '\0')) { RTE_LOG(WARNING, CHANNEL_MANAGER, "Malformed channel name" "'%s' found it should be in the form of " "'.(decimal)'\n", dir->d_name); continue; } if (channel_num >= CHANNEL_CMDS_MAX_VM_CHANNELS) { RTE_LOG(WARNING, CHANNEL_MANAGER, "Channel number(%u) is " "greater than max allowable: %d, skipping '%s%s'\n", channel_num, CHANNEL_CMDS_MAX_VM_CHANNELS-1, CHANNEL_MGR_SOCKET_PATH, dir->d_name); continue; } /* if channel has not been added previously */ if (channel_exists(vm_info, channel_num)) continue; chan_info = rte_malloc(NULL, sizeof(*chan_info), RTE_CACHE_LINE_SIZE); if (chan_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for " "channel '%s%s'\n", CHANNEL_MGR_SOCKET_PATH, dir->d_name); continue; } snprintf(chan_info->channel_path, sizeof(chan_info->channel_path), "%s%s", CHANNEL_MGR_SOCKET_PATH, dir->d_name); if (setup_channel_info(&vm_info, &chan_info, channel_num) < 0) { rte_free(chan_info); continue; } num_channels_enabled++; } closedir(d); return num_channels_enabled; } int add_channels(const char *vm_name, unsigned *channel_list, unsigned len_channel_list) { struct virtual_machine_info *vm_info; struct channel_info *chan_info; char socket_path[PATH_MAX]; unsigned i; int num_channels_enabled = 0; vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' " "not found\n", vm_name); return 0; } if (!virDomainIsActive(vm_info->domainPtr)) { RTE_LOG(ERR, CHANNEL_MANAGER, "VM: '%s' is not active\n", vm_name); vm_info->status = CHANNEL_MGR_VM_INACTIVE; return 0; } for (i = 0; i < len_channel_list; i++) { if (channel_list[i] >= CHANNEL_CMDS_MAX_VM_CHANNELS) { RTE_LOG(INFO, CHANNEL_MANAGER, "Channel(%u) is out of range " "0...%d\n", channel_list[i], CHANNEL_CMDS_MAX_VM_CHANNELS-1); continue; } if (channel_exists(vm_info, channel_list[i])) { RTE_LOG(INFO, CHANNEL_MANAGER, "Channel already exists, skipping " "'%s.%u'\n", vm_name, i); continue; } snprintf(socket_path, sizeof(socket_path), "%s%s.%u", CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]); errno = 0; if (access(socket_path, F_OK) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Channel path '%s' error: " "%s\n", socket_path, strerror(errno)); continue; } chan_info = rte_malloc(NULL, sizeof(*chan_info), RTE_CACHE_LINE_SIZE); if (chan_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for " "channel '%s'\n", socket_path); continue; } snprintf(chan_info->channel_path, sizeof(chan_info->channel_path), "%s%s.%u", CHANNEL_MGR_SOCKET_PATH, vm_name, channel_list[i]); if (setup_channel_info(&vm_info, &chan_info, channel_list[i]) < 0) { rte_free(chan_info); continue; } num_channels_enabled++; } return num_channels_enabled; } int remove_channel(struct channel_info **chan_info_dptr) { struct virtual_machine_info *vm_info; struct channel_info *chan_info = *chan_info_dptr; close(chan_info->fd); vm_info = (struct virtual_machine_info *)chan_info->priv_info; rte_spinlock_lock(&(vm_info->config_spinlock)); vm_info->channel_mask &= ~(1ULL << chan_info->channel_num); vm_info->num_channels--; rte_spinlock_unlock(&(vm_info->config_spinlock)); rte_free(chan_info); return 0; } int set_channel_status_all(const char *vm_name, enum channel_status status) { struct virtual_machine_info *vm_info; unsigned i; uint64_t mask; int num_channels_changed = 0; if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED || status == CHANNEL_MGR_CHANNEL_DISABLED)) { RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or " "disabled: Unable to change status for VM '%s'\n", vm_name); } vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to disable channels: VM '%s' " "not found\n", vm_name); return 0; } rte_spinlock_lock(&(vm_info->config_spinlock)); mask = vm_info->channel_mask; ITERATIVE_BITMASK_CHECK_64(mask, i) { vm_info->channels[i]->status = status; num_channels_changed++; } rte_spinlock_unlock(&(vm_info->config_spinlock)); return num_channels_changed; } int set_channel_status(const char *vm_name, unsigned *channel_list, unsigned len_channel_list, enum channel_status status) { struct virtual_machine_info *vm_info; unsigned i; int num_channels_changed = 0; if (!(status == CHANNEL_MGR_CHANNEL_CONNECTED || status == CHANNEL_MGR_CHANNEL_DISABLED)) { RTE_LOG(ERR, CHANNEL_MANAGER, "Channels can only be enabled or " "disabled: Unable to change status for VM '%s'\n", vm_name); } vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add channels: VM '%s' " "not found\n", vm_name); return 0; } for (i = 0; i < len_channel_list; i++) { if (channel_exists(vm_info, channel_list[i])) { rte_spinlock_lock(&(vm_info->config_spinlock)); vm_info->channels[channel_list[i]]->status = status; rte_spinlock_unlock(&(vm_info->config_spinlock)); num_channels_changed++; } } return num_channels_changed; } int get_info_vm(const char *vm_name, struct vm_info *info) { struct virtual_machine_info *vm_info; unsigned i, channel_num = 0; uint64_t mask; vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "VM '%s' not found\n", vm_name); return -1; } info->status = CHANNEL_MGR_VM_ACTIVE; if (!virDomainIsActive(vm_info->domainPtr)) info->status = CHANNEL_MGR_VM_INACTIVE; rte_spinlock_lock(&(vm_info->config_spinlock)); mask = vm_info->channel_mask; ITERATIVE_BITMASK_CHECK_64(mask, i) { info->channels[channel_num].channel_num = i; memcpy(info->channels[channel_num].channel_path, vm_info->channels[i]->channel_path, UNIX_PATH_MAX); info->channels[channel_num].status = vm_info->channels[i]->status; info->channels[channel_num].fd = vm_info->channels[i]->fd; channel_num++; } info->num_channels = channel_num; info->num_vcpus = vm_info->info.nrVirtCpu; rte_spinlock_unlock(&(vm_info->config_spinlock)); memcpy(info->name, vm_info->name, sizeof(vm_info->name)); for (i = 0; i < info->num_vcpus; i++) { info->pcpu_mask[i] = rte_atomic64_read(&vm_info->pcpu_mask[i]); } return 0; } int add_vm(const char *vm_name) { struct virtual_machine_info *new_domain; virDomainPtr dom_ptr; int i; if (find_domain_by_name(vm_name) != NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to add VM: VM '%s' " "already exists\n", vm_name); return -1; } if (global_vir_conn_ptr == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "No connection to hypervisor exists\n"); return -1; } dom_ptr = virDomainLookupByName(global_vir_conn_ptr, vm_name); if (dom_ptr == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error on VM lookup with libvirt: " "VM '%s' not found\n", vm_name); return -1; } new_domain = rte_malloc("virtual_machine_info", sizeof(*new_domain), RTE_CACHE_LINE_SIZE); if (new_domain == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to allocate memory for VM " "info\n"); return -1; } new_domain->domainPtr = dom_ptr; if (virDomainGetInfo(new_domain->domainPtr, &new_domain->info) != 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to get libvirt VM info\n"); rte_free(new_domain); return -1; } if (new_domain->info.nrVirtCpu > CHANNEL_CMDS_MAX_CPUS) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error the number of virtual CPUs(%u) is " "greater than allowable(%d)\n", new_domain->info.nrVirtCpu, CHANNEL_CMDS_MAX_CPUS); rte_free(new_domain); return -1; } for (i = 0; i < CHANNEL_CMDS_MAX_CPUS; i++) { rte_atomic64_init(&new_domain->pcpu_mask[i]); } if (update_pcpus_mask(new_domain) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error getting physical CPU pinning\n"); rte_free(new_domain); return -1; } strncpy(new_domain->name, vm_name, sizeof(new_domain->name)); new_domain->channel_mask = 0; new_domain->num_channels = 0; if (!virDomainIsActive(dom_ptr)) new_domain->status = CHANNEL_MGR_VM_INACTIVE; else new_domain->status = CHANNEL_MGR_VM_ACTIVE; rte_spinlock_init(&(new_domain->config_spinlock)); LIST_INSERT_HEAD(&vm_list_head, new_domain, vms_info); return 0; } int remove_vm(const char *vm_name) { struct virtual_machine_info *vm_info = find_domain_by_name(vm_name); if (vm_info == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM: VM '%s' " "not found\n", vm_name); return -1; } rte_spinlock_lock(&vm_info->config_spinlock); if (vm_info->num_channels != 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to remove VM '%s', there are " "%"PRId8" channels still active\n", vm_name, vm_info->num_channels); rte_spinlock_unlock(&vm_info->config_spinlock); return -1; } LIST_REMOVE(vm_info, vms_info); rte_spinlock_unlock(&vm_info->config_spinlock); rte_free(vm_info); return 0; } static void disconnect_hypervisor(void) { if (global_vir_conn_ptr != NULL) { virConnectClose(global_vir_conn_ptr); global_vir_conn_ptr = NULL; } } static int connect_hypervisor(const char *path) { if (global_vir_conn_ptr != NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error connecting to %s, connection " "already established\n", path); return -1; } global_vir_conn_ptr = virConnectOpen(path); if (global_vir_conn_ptr == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error failed to open connection to " "Hypervisor '%s'\n", path); return -1; } return 0; } int channel_manager_init(const char *path) { int n_cpus; LIST_INIT(&vm_list_head); if (connect_hypervisor(path) < 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to initialize channel manager\n"); return -1; } global_maplen = VIR_CPU_MAPLEN(CHANNEL_CMDS_MAX_CPUS); global_vircpuinfo = rte_zmalloc(NULL, sizeof(*global_vircpuinfo) * CHANNEL_CMDS_MAX_CPUS, RTE_CACHE_LINE_SIZE); if (global_vircpuinfo == NULL) { RTE_LOG(ERR, CHANNEL_MANAGER, "Error allocating memory for CPU Info\n"); goto error; } global_cpumaps = rte_zmalloc(NULL, CHANNEL_CMDS_MAX_CPUS * global_maplen, RTE_CACHE_LINE_SIZE); if (global_cpumaps == NULL) { goto error; } n_cpus = virNodeGetCPUMap(global_vir_conn_ptr, NULL, NULL, 0); if (n_cpus <= 0) { RTE_LOG(ERR, CHANNEL_MANAGER, "Unable to get the number of Host " "CPUs\n"); goto error; } global_n_host_cpus = (unsigned)n_cpus; if (global_n_host_cpus > CHANNEL_CMDS_MAX_CPUS) { RTE_LOG(WARNING, CHANNEL_MANAGER, "The number of host CPUs(%u) exceeds the " "maximum of %u. No cores over %u should be used.\n", global_n_host_cpus, CHANNEL_CMDS_MAX_CPUS, CHANNEL_CMDS_MAX_CPUS - 1); global_n_host_cpus = CHANNEL_CMDS_MAX_CPUS; } return 0; error: disconnect_hypervisor(); return -1; } void channel_manager_exit(void) { unsigned i; uint64_t mask; struct virtual_machine_info *vm_info; LIST_FOREACH(vm_info, &vm_list_head, vms_info) { rte_spinlock_lock(&(vm_info->config_spinlock)); mask = vm_info->channel_mask; ITERATIVE_BITMASK_CHECK_64(mask, i) { remove_channel_from_monitor(vm_info->channels[i]); close(vm_info->channels[i]->fd); rte_free(vm_info->channels[i]); } rte_spinlock_unlock(&(vm_info->config_spinlock)); LIST_REMOVE(vm_info, vms_info); rte_free(vm_info); } rte_free(global_cpumaps); rte_free(global_vircpuinfo); disconnect_hypervisor(); } ================================================ FILE: examples/vm_power_manager/channel_manager.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CHANNEL_MANAGER_H_ #define CHANNEL_MANAGER_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include "channel_commands.h" /* Maximum name length including '\0' terminator */ #define CHANNEL_MGR_MAX_NAME_LEN 64 /* Maximum number of channels to each Virtual Machine */ #define CHANNEL_MGR_MAX_CHANNELS 64 /* Hypervisor Path for libvirt(qemu/KVM) */ #define CHANNEL_MGR_DEFAULT_HV_PATH "qemu:///system" /* File socket directory */ #define CHANNEL_MGR_SOCKET_PATH "/tmp/powermonitor/" #ifndef UNIX_PATH_MAX struct sockaddr_un _sockaddr_un; #define UNIX_PATH_MAX sizeof(_sockaddr_un.sun_path) #endif /* Communication Channel Status */ enum channel_status { CHANNEL_MGR_CHANNEL_DISCONNECTED = 0, CHANNEL_MGR_CHANNEL_CONNECTED, CHANNEL_MGR_CHANNEL_DISABLED, CHANNEL_MGR_CHANNEL_PROCESSING}; /* VM libvirt(qemu/KVM) connection status */ enum vm_status { CHANNEL_MGR_VM_INACTIVE = 0, CHANNEL_MGR_VM_ACTIVE}; /* * Represents a single and exclusive VM channel that exists between a guest and * the host. */ struct channel_info { char channel_path[UNIX_PATH_MAX]; /**< Path to host socket */ volatile uint32_t status; /**< Connection status(enum channel_status) */ int fd; /**< AF_UNIX socket fd */ unsigned channel_num; /**< CHANNEL_MGR_SOCKET_PATH/.channel_num */ void *priv_info; /**< Pointer to private info, do not modify */ }; /* Represents a single VM instance used to return internal information about * a VM */ struct vm_info { char name[CHANNEL_MGR_MAX_NAME_LEN]; /**< VM name */ enum vm_status status; /**< libvirt status */ uint64_t pcpu_mask[CHANNEL_CMDS_MAX_CPUS]; /**< pCPU mask for each vCPU */ unsigned num_vcpus; /**< number of vCPUS */ struct channel_info channels[CHANNEL_MGR_MAX_CHANNELS]; /**< Array of channel_info */ unsigned num_channels; /**< Number of channels */ }; /** * Initialize the Channel Manager resources and connect to the Hypervisor * specified in path. * This must be successfully called first before calling any other functions. * It must only be call once; * * @param path * Must be a local path, e.g. qemu:///system. * * @return * - 0 on success. * - Negative on error. */ int channel_manager_init(const char *path); /** * Free resources associated with the Channel Manager. * * @param path * Must be a local path, e.g. qemu:///system. * * @return * None */ void channel_manager_exit(void); /** * Get the Physical CPU mask for VM lcore channel(vcpu), result is assigned to * core_mask. * It is not thread-safe. * * @param chan_info * Pointer to struct channel_info * * @param vcpu * The virtual CPU to query. * * * @return * - 0 on error. * - >0 on success. */ uint64_t get_pcpus_mask(struct channel_info *chan_info, unsigned vcpu); /** * Set the Physical CPU mask for the specified vCPU. * It is not thread-safe. * * @param name * Virtual Machine name to lookup * * @param vcpu * The virtual CPU to set. * * @param core_mask * The core mask of the physical CPU(s) to bind the vCPU * * @return * - 0 on success. * - Negative on error. */ int set_pcpus_mask(char *vm_name, unsigned vcpu, uint64_t core_mask); /** * Set the Physical CPU for the specified vCPU. * It is not thread-safe. * * @param name * Virtual Machine name to lookup * * @param vcpu * The virtual CPU to set. * * @param core_num * The core number of the physical CPU(s) to bind the vCPU * * @return * - 0 on success. * - Negative on error. */ int set_pcpu(char *vm_name, unsigned vcpu, unsigned core_num); /** * Add a VM as specified by name to the Channel Manager. The name must * correspond to a valid libvirt domain name. * This is required prior to adding channels. * It is not thread-safe. * * @param name * Virtual Machine name to lookup. * * @return * - 0 on success. * - Negative on error. */ int add_vm(const char *name); /** * Remove a previously added Virtual Machine from the Channel Manager * It is not thread-safe. * * @param name * Virtual Machine name to lookup. * * @return * - 0 on success. * - Negative on error. */ int remove_vm(const char *name); /** * Add all available channels to the VM as specified by name. * Channels in the form of paths * (CHANNEL_MGR_SOCKET_PATH/.) will only be parsed. * It is not thread-safe. * * @param name * Virtual Machine name to lookup. * * @return * - N the number of channels added for the VM */ int add_all_channels(const char *vm_name); /** * Add the channel numbers in channel_list to the domain specified by name. * Channels in the form of paths * (CHANNEL_MGR_SOCKET_PATH/.) will only be parsed. * It is not thread-safe. * * @param name * Virtual Machine name to add channels. * * @param channel_list * Pointer to list of unsigned integers, representing the channel number to add * It must be allocated outside of this function. * * @param num_channels * The amount of channel numbers in channel_list * * @return * - N the number of channels added for the VM * - 0 for error */ int add_channels(const char *vm_name, unsigned *channel_list, unsigned num_channels); /** * Remove a channel definition from the channel manager. This must only be * called from the channel monitor thread. * * @param chan_info * Pointer to a valid struct channel_info. * * @return * - 0 on success. * - Negative on error. */ int remove_channel(struct channel_info **chan_info_dptr); /** * For all channels associated with a Virtual Machine name, update the * connection status. Valid states are CHANNEL_MGR_CHANNEL_CONNECTED or * CHANNEL_MGR_CHANNEL_DISABLED only. * * * @param name * Virtual Machine name to modify all channels. * * @param status * The status to set each channel * * @param num_channels * The amount of channel numbers in channel_list * * @return * - N the number of channels added for the VM * - 0 for error */ int set_channel_status_all(const char *name, enum channel_status status); /** * For all channels in channel_list associated with a Virtual Machine name * update the connection status of each. * Valid states are CHANNEL_MGR_CHANNEL_CONNECTED or * CHANNEL_MGR_CHANNEL_DISABLED only. * It is not thread-safe. * * @param name * Virtual Machine name to add channels. * * @param channel_list * Pointer to list of unsigned integers, representing the channel numbers to * modify. * It must be allocated outside of this function. * * @param num_channels * The amount of channel numbers in channel_list * * @return * - N the number of channels modified for the VM * - 0 for error */ int set_channel_status(const char *vm_name, unsigned *channel_list, unsigned len_channel_list, enum channel_status status); /** * Populates a pointer to struct vm_info associated with vm_name. * * @param vm_name * The name of the virtual machine to lookup. * * @param vm_info * Pointer to a struct vm_info, this must be allocated prior to calling this * function. * * @return * - 0 on success. * - Negative on error. */ int get_info_vm(const char *vm_name, struct vm_info *info); #ifdef __cplusplus } #endif #endif /* CHANNEL_MANAGER_H_ */ ================================================ FILE: examples/vm_power_manager/channel_monitor.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "channel_monitor.h" #include "channel_commands.h" #include "channel_manager.h" #include "power_manager.h" #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 #define MAX_EVENTS 256 static volatile unsigned run_loop = 1; static int global_event_fd; static struct epoll_event *global_events_list; void channel_monitor_exit(void) { run_loop = 0; rte_free(global_events_list); } static int process_request(struct channel_packet *pkt, struct channel_info *chan_info) { uint64_t core_mask; if (chan_info == NULL) return -1; if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED, CHANNEL_MGR_CHANNEL_PROCESSING) == 0) return -1; if (pkt->command == CPU_POWER) { core_mask = get_pcpus_mask(chan_info, pkt->resource_id); if (core_mask == 0) { RTE_LOG(ERR, CHANNEL_MONITOR, "Error get physical CPU mask for " "channel '%s' using vCPU(%u)\n", chan_info->channel_path, (unsigned)pkt->unit); return -1; } if (__builtin_popcountll(core_mask) == 1) { unsigned core_num = __builtin_ffsll(core_mask) - 1; switch (pkt->unit) { case(CPU_POWER_SCALE_MIN): power_manager_scale_core_min(core_num); break; case(CPU_POWER_SCALE_MAX): power_manager_scale_core_max(core_num); break; case(CPU_POWER_SCALE_DOWN): power_manager_scale_core_down(core_num); break; case(CPU_POWER_SCALE_UP): power_manager_scale_core_up(core_num); break; default: break; } } else { switch (pkt->unit) { case(CPU_POWER_SCALE_MIN): power_manager_scale_mask_min(core_mask); break; case(CPU_POWER_SCALE_MAX): power_manager_scale_mask_max(core_mask); break; case(CPU_POWER_SCALE_DOWN): power_manager_scale_mask_down(core_mask); break; case(CPU_POWER_SCALE_UP): power_manager_scale_mask_up(core_mask); break; default: break; } } } /* Return is not checked as channel status may have been set to DISABLED * from management thread */ rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING, CHANNEL_MGR_CHANNEL_CONNECTED); return 0; } int add_channel_to_monitor(struct channel_info **chan_info) { struct channel_info *info = *chan_info; struct epoll_event event; event.events = EPOLLIN; event.data.ptr = info; if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) { RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' " "to epoll\n", info->channel_path); return -1; } return 0; } int remove_channel_from_monitor(struct channel_info *chan_info) { if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, chan_info->fd, NULL) < 0) { RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' " "from epoll\n", chan_info->channel_path); return -1; } return 0; } int channel_monitor_init(void) { global_event_fd = epoll_create1(0); if (global_event_fd == 0) { RTE_LOG(ERR, CHANNEL_MONITOR, "Error creating epoll context with " "error %s\n", strerror(errno)); return -1; } global_events_list = rte_malloc("epoll_events", sizeof(*global_events_list) * MAX_EVENTS, RTE_CACHE_LINE_SIZE); if (global_events_list == NULL) { RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for " "epoll events\n"); return -1; } return 0; } void run_channel_monitor(void) { while (run_loop) { int n_events, i; n_events = epoll_wait(global_event_fd, global_events_list, MAX_EVENTS, 1); if (!run_loop) break; for (i = 0; i < n_events; i++) { struct channel_info *chan_info = (struct channel_info *) global_events_list[i].data.ptr; if ((global_events_list[i].events & EPOLLERR) || (global_events_list[i].events & EPOLLHUP)) { RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for " "channel '%s'\n", chan_info->channel_path); remove_channel(&chan_info); continue; } if (global_events_list[i].events & EPOLLIN) { int n_bytes, err = 0; struct channel_packet pkt; void *buffer = &pkt; int buffer_len = sizeof(pkt); while (buffer_len > 0) { n_bytes = read(chan_info->fd, buffer, buffer_len); if (n_bytes == buffer_len) break; if (n_bytes == -1) { err = errno; RTE_LOG(DEBUG, CHANNEL_MONITOR, "Received error on " "channel '%s' read: %s\n", chan_info->channel_path, strerror(err)); remove_channel(&chan_info); break; } buffer = (char *)buffer + n_bytes; buffer_len -= n_bytes; } if (!err) process_request(&pkt, chan_info); } } } } ================================================ FILE: examples/vm_power_manager/channel_monitor.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CHANNEL_MONITOR_H_ #define CHANNEL_MONITOR_H_ #include "channel_manager.h" #ifdef __cplusplus extern "C" { #endif /** * Setup the Channel Monitor resources required to initialize epoll. * Must be called first before calling other functions. * * @return * - 0 on success. * - Negative on error. */ int channel_monitor_init(void); /** * Run the channel monitor, loops forever on on epoll_wait. * * * @return * None */ void run_channel_monitor(void); /** * Exit the Channel Monitor, exiting the epoll_wait loop and events processing. * * @return * - 0 on success. * - Negative on error. */ void channel_monitor_exit(void); /** * Add an open channel to monitor via epoll. A pointer to struct channel_info * will be registered with epoll for event processing. * It is thread-safe. * * @param chan_info * Pointer to struct channel_info pointer. * * @return * - 0 on success. * - Negative on error. */ int add_channel_to_monitor(struct channel_info **chan_info); /** * Remove a previously added channel from epoll control. * * @param chan_info * Pointer to struct channel_info. * * @return * - 0 on success. * - Negative on error. */ int remove_channel_from_monitor(struct channel_info *chan_info); #ifdef __cplusplus } #endif #endif /* CHANNEL_MONITOR_H_ */ ================================================ FILE: examples/vm_power_manager/guest_cli/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = guest_vm_power_mgr # all source are stored in SRCS-y SRCS-y := main.c vm_power_cli_guest.c CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/vm_power_manager/guest_cli/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* #include #include #include #include #include #include #include #include #include #include */ #include #include #include #include #include #include "vm_power_cli_guest.h" static void sig_handler(int signo) { printf("Received signal %d, exiting...\n", signo); unsigned lcore_id; RTE_LCORE_FOREACH(lcore_id) { rte_power_exit(lcore_id); } } int main(int argc, char **argv) { int ret; unsigned lcore_id; ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); rte_power_set_env(PM_ENV_KVM_VM); RTE_LCORE_FOREACH(lcore_id) { rte_power_init(lcore_id); } run_cli(NULL); return 0; } ================================================ FILE: examples/vm_power_manager/guest_cli/vm_power_cli_guest.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vm_power_cli_guest.h" #define CHANNEL_PATH "/dev/virtio-ports/virtio.serial.port.poweragent" #define RTE_LOGTYPE_GUEST_CHANNEL RTE_LOGTYPE_USER1 struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) { unsigned lcore_id; RTE_LCORE_FOREACH(lcore_id) { rte_power_exit(lcore_id); } cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "close the application", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_quit, NULL, }, }; /* *** VM operations *** */ struct cmd_set_cpu_freq_result { cmdline_fixed_string_t set_cpu_freq; uint8_t lcore_id; cmdline_fixed_string_t cmd; }; static void cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { int ret = -1; struct cmd_set_cpu_freq_result *res = parsed_result; if (!strcmp(res->cmd , "up")) ret = rte_power_freq_up(res->lcore_id); else if (!strcmp(res->cmd , "down")) ret = rte_power_freq_down(res->lcore_id); else if (!strcmp(res->cmd , "min")) ret = rte_power_freq_min(res->lcore_id); else if (!strcmp(res->cmd , "max")) ret = rte_power_freq_max(res->lcore_id); if (ret != 1) cmdline_printf(cl, "Error sending message: %s\n", strerror(ret)); } cmdline_parse_token_string_t cmd_set_cpu_freq = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, set_cpu_freq, "set_cpu_freq"); cmdline_parse_token_string_t cmd_set_cpu_freq_core_num = TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result, lcore_id, UINT8); cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, cmd, "up#down#min#max"); cmdline_parse_inst_t cmd_set_cpu_freq_set = { .f = cmd_set_cpu_freq_parsed, .data = NULL, .help_str = "set_cpu_freq , Set the current " "frequency for the specified core by scaling up/down/min/max", .tokens = { (void *)&cmd_set_cpu_freq, (void *)&cmd_set_cpu_freq_core_num, (void *)&cmd_set_cpu_freq_cmd_cmd, NULL, }, }; cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set, NULL, }; void run_cli(__attribute__((unused)) void *arg) { struct cmdline *cl; cl = cmdline_stdin_new(main_ctx, "vmpower(guest)> "); if (cl == NULL) return; cmdline_interact(cl); cmdline_stdin_exit(cl); } ================================================ FILE: examples/vm_power_manager/guest_cli/vm_power_cli_guest.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef VM_POWER_CLI_H_ #define VM_POWER_CLI_H_ #ifdef __cplusplus extern "C" { #endif #include "channel_commands.h" int guest_channel_host_connect(unsigned lcore_id); int guest_channel_send_msg(struct channel_packet *pkt, unsigned lcore_id); void guest_channel_host_disconnect(unsigned lcore_id); void run_cli(__attribute__((unused)) void *arg); #ifdef __cplusplus } #endif #endif /* VM_POWER_CLI_H_ */ ================================================ FILE: examples/vm_power_manager/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "channel_manager.h" #include "channel_monitor.h" #include "power_manager.h" #include "vm_power_cli.h" static int run_monitor(__attribute__((unused)) void *arg) { if (channel_monitor_init() < 0) { printf("Unable to initialize channel monitor\n"); return -1; } run_channel_monitor(); return 0; } static void sig_handler(int signo) { printf("Received signal %d, exiting...\n", signo); channel_monitor_exit(); channel_manager_exit(); power_manager_exit(); } int main(int argc, char **argv) { int ret; unsigned lcore_id; ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); lcore_id = rte_get_next_lcore(-1, 1, 0); if (lcore_id == RTE_MAX_LCORE) { RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " "application\n"); return 0; } rte_eal_remote_launch(run_monitor, NULL, lcore_id); if (power_manager_init() < 0) { printf("Unable to initialize power manager\n"); return -1; } if (channel_manager_init(CHANNEL_MGR_DEFAULT_HV_PATH) < 0) { printf("Unable to initialize channel manager\n"); return -1; } run_cli(NULL); rte_eal_mp_wait_lcore(); return 0; } ================================================ FILE: examples/vm_power_manager/power_manager.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "power_manager.h" #define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1 #define POWER_SCALE_CORE(DIRECTION, core_num , ret) do { \ if (core_num >= POWER_MGR_MAX_CPUS) \ return -1; \ if (!(global_enabled_cpus & (1ULL << core_num))) \ return -1; \ rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); \ ret = rte_power_freq_##DIRECTION(core_num); \ rte_spinlock_unlock(&global_core_freq_info[core_num].power_sl); \ } while (0) #define POWER_SCALE_MASK(DIRECTION, core_mask, ret) do { \ int i; \ for (i = 0; core_mask; core_mask &= ~(1 << i++)) { \ if ((core_mask >> i) & 1) { \ if (!(global_enabled_cpus & (1ULL << i))) \ continue; \ rte_spinlock_lock(&global_core_freq_info[i].power_sl); \ if (rte_power_freq_##DIRECTION(i) != 1) \ ret = -1; \ rte_spinlock_unlock(&global_core_freq_info[i].power_sl); \ } \ } \ } while (0) struct freq_info { rte_spinlock_t power_sl; uint32_t freqs[RTE_MAX_LCORE_FREQS]; unsigned num_freqs; } __rte_cache_aligned; static struct freq_info global_core_freq_info[POWER_MGR_MAX_CPUS]; static uint64_t global_enabled_cpus; #define SYSFS_CPU_PATH "/sys/devices/system/cpu/cpu%u/topology/core_id" static unsigned set_host_cpus_mask(void) { char path[PATH_MAX]; unsigned i; unsigned num_cpus = 0; for (i = 0; i < POWER_MGR_MAX_CPUS; i++) { snprintf(path, sizeof(path), SYSFS_CPU_PATH, i); if (access(path, F_OK) == 0) { global_enabled_cpus |= 1ULL << i; num_cpus++; } else return num_cpus; } return num_cpus; } int power_manager_init(void) { unsigned i, num_cpus; uint64_t cpu_mask; int ret = 0; num_cpus = set_host_cpus_mask(); if (num_cpus == 0) { RTE_LOG(ERR, POWER_MANAGER, "Unable to detected host CPUs, please " "ensure that sufficient privileges exist to inspect sysfs\n"); return -1; } rte_power_set_env(PM_ENV_ACPI_CPUFREQ); cpu_mask = global_enabled_cpus; for (i = 0; cpu_mask; cpu_mask &= ~(1 << i++)) { if (rte_power_init(i) < 0 || rte_power_freqs(i, global_core_freq_info[i].freqs, RTE_MAX_LCORE_FREQS) == 0) { RTE_LOG(ERR, POWER_MANAGER, "Unable to initialize power manager " "for core %u\n", i); global_enabled_cpus &= ~(1 << i); num_cpus--; ret = -1; } rte_spinlock_init(&global_core_freq_info[i].power_sl); } RTE_LOG(INFO, POWER_MANAGER, "Detected %u host CPUs , enabled core mask:" " 0x%"PRIx64"\n", num_cpus, global_enabled_cpus); return ret; } uint32_t power_manager_get_current_frequency(unsigned core_num) { uint32_t freq, index; if (core_num >= POWER_MGR_MAX_CPUS) { RTE_LOG(ERR, POWER_MANAGER, "Core(%u) is out of range 0...%d\n", core_num, POWER_MGR_MAX_CPUS-1); return -1; } if (!(global_enabled_cpus & (1ULL << core_num))) return 0; rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); index = rte_power_get_freq(core_num); rte_spinlock_unlock(&global_core_freq_info[core_num].power_sl); if (index >= POWER_MGR_MAX_CPUS) freq = 0; else freq = global_core_freq_info[core_num].freqs[index]; return freq; } int power_manager_exit(void) { unsigned int i; int ret = 0; for (i = 0; global_enabled_cpus; global_enabled_cpus &= ~(1 << i++)) { if (rte_power_exit(i) < 0) { RTE_LOG(ERR, POWER_MANAGER, "Unable to shutdown power manager " "for core %u\n", i); ret = -1; } } global_enabled_cpus = 0; return ret; } int power_manager_scale_mask_up(uint64_t core_mask) { int ret = 0; POWER_SCALE_MASK(up, core_mask, ret); return ret; } int power_manager_scale_mask_down(uint64_t core_mask) { int ret = 0; POWER_SCALE_MASK(down, core_mask, ret); return ret; } int power_manager_scale_mask_min(uint64_t core_mask) { int ret = 0; POWER_SCALE_MASK(min, core_mask, ret); return ret; } int power_manager_scale_mask_max(uint64_t core_mask) { int ret = 0; POWER_SCALE_MASK(max, core_mask, ret); return ret; } int power_manager_scale_core_up(unsigned core_num) { int ret = 0; POWER_SCALE_CORE(up, core_num, ret); return ret; } int power_manager_scale_core_down(unsigned core_num) { int ret = 0; POWER_SCALE_CORE(down, core_num, ret); return ret; } int power_manager_scale_core_min(unsigned core_num) { int ret = 0; POWER_SCALE_CORE(min, core_num, ret); return ret; } int power_manager_scale_core_max(unsigned core_num) { int ret = 0; POWER_SCALE_CORE(max, core_num, ret); return ret; } ================================================ FILE: examples/vm_power_manager/power_manager.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef POWER_MANAGER_H_ #define POWER_MANAGER_H_ #ifdef __cplusplus extern "C" { #endif /* Maximum number of CPUS to manage */ #define POWER_MGR_MAX_CPUS 64 /** * Initialize power management. * Initializes resources and verifies the number of CPUs on the system. * Wraps librte_power int rte_power_init(unsigned lcore_id); * * @return * - 0 on success. * - Negative on error. */ int power_manager_init(void); /** * Exit power management. Must be called prior to exiting the application. * * @return * - 0 on success. * - Negative on error. */ int power_manager_exit(void); /** * Scale up the frequency of the cores specified in core_mask. * It is thread-safe. * * @param core_mask * The uint64_t bit-mask of cores to change frequency. * * @return * - 1 on success. * - Negative on error. */ int power_manager_scale_mask_up(uint64_t core_mask); /** * Scale down the frequency of the cores specified in core_mask. * It is thread-safe. * * @param core_mask * The uint64_t bit-mask of cores to change frequency. * * @return * - 1 on success. * - Negative on error. */ int power_manager_scale_mask_down(uint64_t core_mask); /** * Scale to the minimum frequency of the cores specified in core_mask. * It is thread-safe. * * @param core_mask * The uint64_t bit-mask of cores to change frequency. * * @return * - 1 on success. * - Negative on error. */ int power_manager_scale_mask_min(uint64_t core_mask); /** * Scale to the maximum frequency of the cores specified in core_mask. * It is thread-safe. * * @param core_mask * The uint64_t bit-mask of cores to change frequency. * * @return * - 1 on success. * - Negative on error. */ int power_manager_scale_mask_max(uint64_t core_mask); /** * Scale up frequency for the core specified by core_num. * It is thread-safe. * * @param core_num * The core number to change frequency * * @return * - 1 on success. * - Negative on error. */ int power_manager_scale_core_up(unsigned core_num); /** * Scale down frequency for the core specified by core_num. * It is thread-safe. * * @param core_num * The core number to change frequency * * @return * - 1 on success. * - 0 if frequency not changed. * - Negative on error. */ int power_manager_scale_core_down(unsigned core_num); /** * Scale to minimum frequency for the core specified by core_num. * It is thread-safe. * * @param core_num * The core number to change frequency * * @return * - 1 on success. * - 0 if frequency not changed. * - Negative on error. */ int power_manager_scale_core_min(unsigned core_num); /** * Scale to maximum frequency for the core specified by core_num. * It is thread-safe. * * @param core_num * The core number to change frequency * * @return * - 1 on success. * - 0 if frequency not changed. * - Negative on error. */ int power_manager_scale_core_max(unsigned core_num); /** * Get the current freuency of the core specified by core_num * * @param core_num * The core number to get the current frequency * * @return * - 0 on error * - >0 for current frequency. */ uint32_t power_manager_get_current_frequency(unsigned core_num); #ifdef __cplusplus } #endif #endif /* POWER_MANAGER_H_ */ ================================================ FILE: examples/vm_power_manager/vm_power_cli.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vm_power_cli.h" #include "channel_manager.h" #include "channel_monitor.h" #include "power_manager.h" #include "channel_commands.h" struct cmd_quit_result { cmdline_fixed_string_t quit; }; static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { channel_monitor_exit(); channel_manager_exit(); power_manager_exit(); cmdline_quit(cl); } cmdline_parse_token_string_t cmd_quit_quit = TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); cmdline_parse_inst_t cmd_quit = { .f = cmd_quit_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = "close the application", .tokens = { /* token list, NULL terminated */ (void *)&cmd_quit_quit, NULL, }, }; /* *** VM operations *** */ struct cmd_show_vm_result { cmdline_fixed_string_t show_vm; cmdline_fixed_string_t vm_name; }; static void cmd_show_vm_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_vm_result *res = parsed_result; struct vm_info info; unsigned i; if (get_info_vm(res->vm_name, &info) != 0) return; cmdline_printf(cl, "VM: '%s', status = ", info.name); if (info.status == CHANNEL_MGR_VM_ACTIVE) cmdline_printf(cl, "ACTIVE\n"); else cmdline_printf(cl, "INACTIVE\n"); cmdline_printf(cl, "Channels %u\n", info.num_channels); for (i = 0; i < info.num_channels; i++) { cmdline_printf(cl, " [%u]: %s, status = ", i, info.channels[i].channel_path); switch (info.channels[i].status) { case CHANNEL_MGR_CHANNEL_CONNECTED: cmdline_printf(cl, "CONNECTED\n"); break; case CHANNEL_MGR_CHANNEL_DISCONNECTED: cmdline_printf(cl, "DISCONNECTED\n"); break; case CHANNEL_MGR_CHANNEL_DISABLED: cmdline_printf(cl, "DISABLED\n"); break; case CHANNEL_MGR_CHANNEL_PROCESSING: cmdline_printf(cl, "PROCESSING\n"); break; default: cmdline_printf(cl, "UNKNOWN\n"); break; } } cmdline_printf(cl, "Virtual CPU(s): %u\n", info.num_vcpus); for (i = 0; i < info.num_vcpus; i++) { cmdline_printf(cl, " [%u]: Physical CPU Mask 0x%"PRIx64"\n", i, info.pcpu_mask[i]); } } cmdline_parse_token_string_t cmd_vm_show = TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result, show_vm, "show_vm"); cmdline_parse_token_string_t cmd_show_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_show_vm_result, vm_name, NULL); cmdline_parse_inst_t cmd_show_vm_set = { .f = cmd_show_vm_parsed, .data = NULL, .help_str = "show_vm , prints the information on the " "specified VM(s), the information lists the number of vCPUS, the " "pinning to pCPU(s) as a bit mask, along with any communication " "channels associated with each VM", .tokens = { (void *)&cmd_vm_show, (void *)&cmd_show_vm_name, NULL, }, }; /* *** vCPU to pCPU mapping operations *** */ struct cmd_set_pcpu_mask_result { cmdline_fixed_string_t set_pcpu_mask; cmdline_fixed_string_t vm_name; uint8_t vcpu; uint64_t core_mask; }; static void cmd_set_pcpu_mask_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_pcpu_mask_result *res = parsed_result; if (set_pcpus_mask(res->vm_name, res->vcpu, res->core_mask) == 0) cmdline_printf(cl, "Pinned vCPU(%"PRId8") to pCPU core " "mask(0x%"PRIx64")\n", res->vcpu, res->core_mask); else cmdline_printf(cl, "Unable to pin vCPU(%"PRId8") to pCPU core " "mask(0x%"PRIx64")\n", res->vcpu, res->core_mask); } cmdline_parse_token_string_t cmd_set_pcpu_mask = TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_mask_result, set_pcpu_mask, "set_pcpu_mask"); cmdline_parse_token_string_t cmd_set_pcpu_mask_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_mask_result, vm_name, NULL); cmdline_parse_token_num_t set_pcpu_mask_vcpu = TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_mask_result, vcpu, UINT8); cmdline_parse_token_num_t set_pcpu_mask_core_mask = TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_mask_result, core_mask, UINT64); cmdline_parse_inst_t cmd_set_pcpu_mask_set = { .f = cmd_set_pcpu_mask_parsed, .data = NULL, .help_str = "set_pcpu_mask , Set the binding " "of Virtual CPU on VM to the Physical CPU mask.", .tokens = { (void *)&cmd_set_pcpu_mask, (void *)&cmd_set_pcpu_mask_vm_name, (void *)&set_pcpu_mask_vcpu, (void *)&set_pcpu_mask_core_mask, NULL, }, }; struct cmd_set_pcpu_result { cmdline_fixed_string_t set_pcpu; cmdline_fixed_string_t vm_name; uint8_t vcpu; uint8_t core; }; static void cmd_set_pcpu_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_pcpu_result *res = parsed_result; if (set_pcpu(res->vm_name, res->vcpu, res->core) == 0) cmdline_printf(cl, "Pinned vCPU(%"PRId8") to pCPU core " "%"PRId8")\n", res->vcpu, res->core); else cmdline_printf(cl, "Unable to pin vCPU(%"PRId8") to pCPU core " "%"PRId8")\n", res->vcpu, res->core); } cmdline_parse_token_string_t cmd_set_pcpu = TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result, set_pcpu, "set_pcpu"); cmdline_parse_token_string_t cmd_set_pcpu_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_set_pcpu_result, vm_name, NULL); cmdline_parse_token_num_t set_pcpu_vcpu = TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result, vcpu, UINT8); cmdline_parse_token_num_t set_pcpu_core = TOKEN_NUM_INITIALIZER(struct cmd_set_pcpu_result, core, UINT64); cmdline_parse_inst_t cmd_set_pcpu_set = { .f = cmd_set_pcpu_parsed, .data = NULL, .help_str = "set_pcpu , Set the binding " "of Virtual CPU on VM to the Physical CPU.", .tokens = { (void *)&cmd_set_pcpu, (void *)&cmd_set_pcpu_vm_name, (void *)&set_pcpu_vcpu, (void *)&set_pcpu_core, NULL, }, }; struct cmd_vm_op_result { cmdline_fixed_string_t op_vm; cmdline_fixed_string_t vm_name; }; static void cmd_vm_op_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_vm_op_result *res = parsed_result; if (!strcmp(res->op_vm, "add_vm")) { if (add_vm(res->vm_name) < 0) cmdline_printf(cl, "Unable to add VM '%s'\n", res->vm_name); } else if (remove_vm(res->vm_name) < 0) cmdline_printf(cl, "Unable to remove VM '%s'\n", res->vm_name); } cmdline_parse_token_string_t cmd_vm_op = TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result, op_vm, "add_vm#rm_vm"); cmdline_parse_token_string_t cmd_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_vm_op_result, vm_name, NULL); cmdline_parse_inst_t cmd_vm_op_set = { .f = cmd_vm_op_parsed, .data = NULL, .help_str = "add_vm|rm_vm , add a VM for " "subsequent operations with the CLI or remove a previously added " "VM from the VM Power Manager", .tokens = { (void *)&cmd_vm_op, (void *)&cmd_vm_name, NULL, }, }; /* *** VM channel operations *** */ struct cmd_channels_op_result { cmdline_fixed_string_t op; cmdline_fixed_string_t vm_name; cmdline_fixed_string_t channel_list; }; static void cmd_channels_op_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { unsigned num_channels = 0, channel_num, i; int channels_added; unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS]; char *token, *remaining, *tail_ptr; struct cmd_channels_op_result *res = parsed_result; if (!strcmp(res->channel_list, "all")) { channels_added = add_all_channels(res->vm_name); cmdline_printf(cl, "Added %d channels for VM '%s'\n", channels_added, res->vm_name); return; } remaining = res->channel_list; while (1) { if (remaining == NULL || remaining[0] == '\0') break; token = strsep(&remaining, ","); if (token == NULL) break; errno = 0; channel_num = (unsigned)strtol(token, &tail_ptr, 10); if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0')) break; if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) { cmdline_printf(cl, "Channel number '%u' exceeds the maximum number " "of allowable channels(%u) for VM '%s'\n", channel_num, CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name); return; } channel_list[num_channels++] = channel_num; } for (i = 0; i < num_channels; i++) cmdline_printf(cl, "[%u]: Adding channel %u\n", i, channel_list[i]); channels_added = add_channels(res->vm_name, channel_list, num_channels); cmdline_printf(cl, "Enabled %d channels for '%s'\n", channels_added, res->vm_name); } cmdline_parse_token_string_t cmd_channels_op = TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result, op, "add_channels"); cmdline_parse_token_string_t cmd_channels_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result, vm_name, NULL); cmdline_parse_token_string_t cmd_channels_list = TOKEN_STRING_INITIALIZER(struct cmd_channels_op_result, channel_list, NULL); cmdline_parse_inst_t cmd_channels_op_set = { .f = cmd_channels_op_parsed, .data = NULL, .help_str = "add_channels |all, add " "communication channels for the specified VM, the " "virtio channels must be enabled in the VM " "configuration(qemu/libvirt) and the associated VM must be active. " " is a comma-separated list of channel numbers to add, using " "the keyword 'all' will attempt to add all channels for the VM", .tokens = { (void *)&cmd_channels_op, (void *)&cmd_channels_vm_name, (void *)&cmd_channels_list, NULL, }, }; struct cmd_channels_status_op_result { cmdline_fixed_string_t op; cmdline_fixed_string_t vm_name; cmdline_fixed_string_t channel_list; cmdline_fixed_string_t status; }; static void cmd_channels_status_op_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { unsigned num_channels = 0, channel_num; int changed; unsigned channel_list[CHANNEL_CMDS_MAX_VM_CHANNELS]; char *token, *remaining, *tail_ptr; struct cmd_channels_status_op_result *res = parsed_result; enum channel_status status; if (!strcmp(res->status, "enabled")) status = CHANNEL_MGR_CHANNEL_CONNECTED; else status = CHANNEL_MGR_CHANNEL_DISABLED; if (!strcmp(res->channel_list, "all")) { changed = set_channel_status_all(res->vm_name, status); cmdline_printf(cl, "Updated status of %d channels " "for VM '%s'\n", changed, res->vm_name); return; } remaining = res->channel_list; while (1) { if (remaining == NULL || remaining[0] == '\0') break; token = strsep(&remaining, ","); if (token == NULL) break; errno = 0; channel_num = (unsigned)strtol(token, &tail_ptr, 10); if ((errno != 0) || tail_ptr == NULL || (*tail_ptr != '\0')) break; if (channel_num == CHANNEL_CMDS_MAX_VM_CHANNELS) { cmdline_printf(cl, "%u exceeds the maximum number of allowable " "channels(%u) for VM '%s'\n", channel_num, CHANNEL_CMDS_MAX_VM_CHANNELS, res->vm_name); return; } channel_list[num_channels++] = channel_num; } changed = set_channel_status(res->vm_name, channel_list, num_channels, status); cmdline_printf(cl, "Updated status of %d channels " "for VM '%s'\n", changed, res->vm_name); } cmdline_parse_token_string_t cmd_channels_status_op = TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result, op, "set_channel_status"); cmdline_parse_token_string_t cmd_channels_status_vm_name = TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result, vm_name, NULL); cmdline_parse_token_string_t cmd_channels_status_list = TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result, channel_list, NULL); cmdline_parse_token_string_t cmd_channels_status = TOKEN_STRING_INITIALIZER(struct cmd_channels_status_op_result, status, "enabled#disabled"); cmdline_parse_inst_t cmd_channels_status_op_set = { .f = cmd_channels_status_op_parsed, .data = NULL, .help_str = "set_channel_status |all enabled|disabled, " " enable or disable the communication channels in " "list(comma-separated) for the specified VM, alternatively " "list can be replaced with keyword 'all'. " "Disabled channels will still receive packets on the host, " "however the commands they specify will be ignored. " "Set status to 'enabled' to begin processing requests again.", .tokens = { (void *)&cmd_channels_status_op, (void *)&cmd_channels_status_vm_name, (void *)&cmd_channels_status_list, (void *)&cmd_channels_status, NULL, }, }; /* *** CPU Frequency operations *** */ struct cmd_show_cpu_freq_mask_result { cmdline_fixed_string_t show_cpu_freq_mask; uint64_t core_mask; }; static void cmd_show_cpu_freq_mask_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_cpu_freq_mask_result *res = parsed_result; unsigned i; uint64_t mask = res->core_mask; uint32_t freq; for (i = 0; mask; mask &= ~(1ULL << i++)) { if ((mask >> i) & 1) { freq = power_manager_get_current_frequency(i); if (freq > 0) cmdline_printf(cl, "Core %u: %"PRId32"\n", i, freq); } } } cmdline_parse_token_string_t cmd_show_cpu_freq_mask = TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_mask_result, show_cpu_freq_mask, "show_cpu_freq_mask"); cmdline_parse_token_num_t cmd_show_cpu_freq_mask_core_mask = TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_mask_result, core_mask, UINT64); cmdline_parse_inst_t cmd_show_cpu_freq_mask_set = { .f = cmd_show_cpu_freq_mask_parsed, .data = NULL, .help_str = "show_cpu_freq_mask , Get the current frequency for each " "core specified in the mask", .tokens = { (void *)&cmd_show_cpu_freq_mask, (void *)&cmd_show_cpu_freq_mask_core_mask, NULL, }, }; struct cmd_set_cpu_freq_mask_result { cmdline_fixed_string_t set_cpu_freq_mask; uint64_t core_mask; cmdline_fixed_string_t cmd; }; static void cmd_set_cpu_freq_mask_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_set_cpu_freq_mask_result *res = parsed_result; int ret = -1; if (!strcmp(res->cmd , "up")) ret = power_manager_scale_mask_up(res->core_mask); else if (!strcmp(res->cmd , "down")) ret = power_manager_scale_mask_down(res->core_mask); else if (!strcmp(res->cmd , "min")) ret = power_manager_scale_mask_min(res->core_mask); else if (!strcmp(res->cmd , "max")) ret = power_manager_scale_mask_max(res->core_mask); if (ret < 0) { cmdline_printf(cl, "Error scaling core_mask(0x%"PRIx64") '%s' , not " "all cores specified have been scaled\n", res->core_mask, res->cmd); }; } cmdline_parse_token_string_t cmd_set_cpu_freq_mask = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result, set_cpu_freq_mask, "set_cpu_freq_mask"); cmdline_parse_token_num_t cmd_set_cpu_freq_mask_core_mask = TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_mask_result, core_mask, UINT64); cmdline_parse_token_string_t cmd_set_cpu_freq_mask_result = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_mask_result, cmd, "up#down#min#max"); cmdline_parse_inst_t cmd_set_cpu_freq_mask_set = { .f = cmd_set_cpu_freq_mask_parsed, .data = NULL, .help_str = "set_cpu_freq , Set the current " "frequency for the cores specified in by scaling " "each up/down/min/max.", .tokens = { (void *)&cmd_set_cpu_freq_mask, (void *)&cmd_set_cpu_freq_mask_core_mask, (void *)&cmd_set_cpu_freq_mask_result, NULL, }, }; struct cmd_show_cpu_freq_result { cmdline_fixed_string_t show_cpu_freq; uint8_t core_num; }; static void cmd_show_cpu_freq_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_show_cpu_freq_result *res = parsed_result; uint32_t curr_freq = power_manager_get_current_frequency(res->core_num); if (curr_freq == 0) { cmdline_printf(cl, "Unable to get frequency for core %u\n", res->core_num); return; } cmdline_printf(cl, "Core %u frequency: %"PRId32"\n", res->core_num, curr_freq); } cmdline_parse_token_string_t cmd_show_cpu_freq = TOKEN_STRING_INITIALIZER(struct cmd_show_cpu_freq_result, show_cpu_freq, "show_cpu_freq"); cmdline_parse_token_num_t cmd_show_cpu_freq_core_num = TOKEN_NUM_INITIALIZER(struct cmd_show_cpu_freq_result, core_num, UINT8); cmdline_parse_inst_t cmd_show_cpu_freq_set = { .f = cmd_show_cpu_freq_parsed, .data = NULL, .help_str = "Get the current frequency for the specified core", .tokens = { (void *)&cmd_show_cpu_freq, (void *)&cmd_show_cpu_freq_core_num, NULL, }, }; struct cmd_set_cpu_freq_result { cmdline_fixed_string_t set_cpu_freq; uint8_t core_num; cmdline_fixed_string_t cmd; }; static void cmd_set_cpu_freq_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { int ret = -1; struct cmd_set_cpu_freq_result *res = parsed_result; if (!strcmp(res->cmd , "up")) ret = power_manager_scale_core_up(res->core_num); else if (!strcmp(res->cmd , "down")) ret = power_manager_scale_core_down(res->core_num); else if (!strcmp(res->cmd , "min")) ret = power_manager_scale_core_min(res->core_num); else if (!strcmp(res->cmd , "max")) ret = power_manager_scale_core_max(res->core_num); if (ret < 0) { cmdline_printf(cl, "Error scaling core(%u) '%s'\n", res->core_num, res->cmd); } } cmdline_parse_token_string_t cmd_set_cpu_freq = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, set_cpu_freq, "set_cpu_freq"); cmdline_parse_token_num_t cmd_set_cpu_freq_core_num = TOKEN_NUM_INITIALIZER(struct cmd_set_cpu_freq_result, core_num, UINT8); cmdline_parse_token_string_t cmd_set_cpu_freq_cmd_cmd = TOKEN_STRING_INITIALIZER(struct cmd_set_cpu_freq_result, cmd, "up#down#min#max"); cmdline_parse_inst_t cmd_set_cpu_freq_set = { .f = cmd_set_cpu_freq_parsed, .data = NULL, .help_str = "set_cpu_freq , Set the current " "frequency for the specified core by scaling up/down/min/max", .tokens = { (void *)&cmd_set_cpu_freq, (void *)&cmd_set_cpu_freq_core_num, (void *)&cmd_set_cpu_freq_cmd_cmd, NULL, }, }; cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_vm_op_set, (cmdline_parse_inst_t *)&cmd_channels_op_set, (cmdline_parse_inst_t *)&cmd_channels_status_op_set, (cmdline_parse_inst_t *)&cmd_show_vm_set, (cmdline_parse_inst_t *)&cmd_show_cpu_freq_mask_set, (cmdline_parse_inst_t *)&cmd_set_cpu_freq_mask_set, (cmdline_parse_inst_t *)&cmd_show_cpu_freq_set, (cmdline_parse_inst_t *)&cmd_set_cpu_freq_set, (cmdline_parse_inst_t *)&cmd_set_pcpu_mask_set, (cmdline_parse_inst_t *)&cmd_set_pcpu_set, NULL, }; void run_cli(__attribute__((unused)) void *arg) { struct cmdline *cl; cl = cmdline_stdin_new(main_ctx, "vmpower> "); if (cl == NULL) return; cmdline_interact(cl); cmdline_stdin_exit(cl); } ================================================ FILE: examples/vm_power_manager/vm_power_cli.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef VM_POWER_CLI_H_ #define VM_POWER_CLI_H_ #ifdef __cplusplus extern "C" { #endif void run_cli(__attribute__((unused)) void *arg); #ifdef __cplusplus } #endif #endif /* VM_POWER_CLI_H_ */ ================================================ FILE: examples/vmdq/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = vmdq_app # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += $(WERROR_FLAGS) EXTRA_CFLAGS += -O3 include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/vmdq/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_QUEUES 128 /* * For 10 GbE, 128 queues require roughly * 128*512 (RX/TX_queue_nb * RX/TX_ring_descriptors_nb) per port. */ #define NUM_MBUFS_PER_PORT (128*512) #define MBUF_CACHE_SIZE 64 #define MAX_PKT_BURST 32 /* * Configurable number of RX/TX ring descriptors */ #define RTE_TEST_RX_DESC_DEFAULT 128 #define RTE_TEST_TX_DESC_DEFAULT 512 #define INVALID_PORT_ID 0xFF /* mask of enabled ports */ static uint32_t enabled_port_mask; /* number of pools (if user does not specify any, 8 by default */ static uint32_t num_queues = 8; static uint32_t num_pools = 8; /* empty vmdq configuration structure. Filled in programatically */ static const struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .rx_adv_conf = { /* * should be overridden separately in code with * appropriate values */ .vmdq_rx_conf = { .nb_queue_pools = ETH_8_POOLS, .enable_default_pool = 0, .default_pool = 0, .nb_pool_maps = 0, .pool_map = {{0, 0},}, }, }, }; static unsigned lcore_ids[RTE_MAX_LCORE]; static uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned num_ports; /**< The number of ports specified in command line */ /* array used for printing out statistics */ volatile unsigned long rxPackets[MAX_QUEUES] = {0}; const uint16_t vlan_tags[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }; const uint16_t num_vlans = RTE_DIM(vlan_tags); static uint16_t num_pf_queues, num_vmdq_queues; static uint16_t vmdq_pool_base, vmdq_queue_base; /* pool mac addr template, pool mac addr is like: 52 54 00 12 port# pool# */ static struct ether_addr pool_addr_template = { .addr_bytes = {0x52, 0x54, 0x00, 0x12, 0x00, 0x00} }; /* ethernet addresses of ports */ static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS]; #define MAX_QUEUE_NUM_10G 128 #define MAX_QUEUE_NUM_1G 8 #define MAX_POOL_MAP_NUM_10G 64 #define MAX_POOL_MAP_NUM_1G 32 #define MAX_POOL_NUM_10G 64 #define MAX_POOL_NUM_1G 8 /* * Builds up the correct configuration for vmdq based on the vlan tags array * given above, and determine the queue number and pool map number according to * valid pool number */ static inline int get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_pools) { struct rte_eth_vmdq_rx_conf conf; unsigned i; conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools; conf.nb_pool_maps = num_pools; conf.enable_default_pool = 0; conf.default_pool = 0; /* set explicit value, even if not used */ for (i = 0; i < conf.nb_pool_maps; i++) { conf.pool_map[i].vlan_id = vlan_tags[i]; conf.pool_map[i].pools = (1UL << (i % num_pools)); } (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf))); (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_rx_conf, &conf, sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf))); return 0; } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_dev_info dev_info; struct rte_eth_rxconf *rxconf; struct rte_eth_conf port_conf; uint16_t rxRings, txRings; const uint16_t rxRingSize = RTE_TEST_RX_DESC_DEFAULT, txRingSize = RTE_TEST_TX_DESC_DEFAULT; int retval; uint16_t q; uint16_t queues_per_pool; uint32_t max_nb_pools; /* * The max pool number from dev_info will be used to validate the pool * number specified in cmd line */ rte_eth_dev_info_get(port, &dev_info); max_nb_pools = (uint32_t)dev_info.max_vmdq_pools; /* * We allow to process part of VMDQ pools specified by num_pools in * command line. */ if (num_pools > max_nb_pools) { printf("num_pools %d >max_nb_pools %d\n", num_pools, max_nb_pools); return -1; } retval = get_eth_conf(&port_conf, max_nb_pools); if (retval < 0) return retval; /* * NIC queues are divided into pf queues and vmdq queues. */ /* There is assumption here all ports have the same configuration! */ num_pf_queues = dev_info.max_rx_queues - dev_info.vmdq_queue_num; queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools; num_vmdq_queues = num_pools * queues_per_pool; num_queues = num_pf_queues + num_vmdq_queues; vmdq_queue_base = dev_info.vmdq_queue_base; vmdq_pool_base = dev_info.vmdq_pool_base; printf("pf queue num: %u, configured vmdq pool num: %u," " each vmdq pool has %u queues\n", num_pf_queues, num_pools, queues_per_pool); printf("vmdq queue base: %d pool base %d\n", vmdq_queue_base, vmdq_pool_base); if (port >= rte_eth_dev_count()) return -1; /* * Though in this example, we only receive packets from the first queue * of each pool and send packets through first rte_lcore_count() tx * queues of vmdq queues, all queues including pf queues are setup. * This is because VMDQ queues doesn't always start from zero, and the * PMD layer doesn't support selectively initialising part of rx/tx * queues. */ rxRings = (uint16_t)dev_info.max_rx_queues; txRings = (uint16_t)dev_info.max_tx_queues; retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; rte_eth_dev_info_get(port, &dev_info); rxconf = &dev_info.default_rxconf; rxconf->rx_drop_en = 1; for (q = 0; q < rxRings; q++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, rte_eth_dev_socket_id(port), rxconf, mbuf_pool); if (retval < 0) { printf("initialise rx queue %d failed\n", q); return retval; } } for (q = 0; q < txRings; q++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, rte_eth_dev_socket_id(port), NULL); if (retval < 0) { printf("initialise tx queue %d failed\n", q); return retval; } } retval = rte_eth_dev_start(port); if (retval < 0) { printf("port %d start failed\n", port); return retval; } rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, vmdq_ports_eth_addr[port].addr_bytes[0], vmdq_ports_eth_addr[port].addr_bytes[1], vmdq_ports_eth_addr[port].addr_bytes[2], vmdq_ports_eth_addr[port].addr_bytes[3], vmdq_ports_eth_addr[port].addr_bytes[4], vmdq_ports_eth_addr[port].addr_bytes[5]); /* * Set mac for each pool. * There is no default mac for the pools in i40. * Removes this after i40e fixes this issue. */ for (q = 0; q < num_pools; q++) { struct ether_addr mac; mac = pool_addr_template; mac.addr_bytes[4] = port; mac.addr_bytes[5] = q; printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n", port, q, mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); retval = rte_eth_dev_mac_addr_add(port, &mac, q + vmdq_pool_base); if (retval) { printf("mac addr add failed at pool %d\n", q); return retval; } } return 0; } /* Check num_pools parameter and set it if OK*/ static int vmdq_parse_num_pools(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (num_pools > num_vlans) { printf("num_pools %d > num_vlans %d\n", num_pools, num_vlans); return -1; } num_pools = n; return 0; } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /* Display usage */ static void vmdq_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK]\n" " --nb-pools NP: number of pools\n", prgname); } /* Parse the argument (num_pools) given in the command line of the application */ static int vmdq_parse_args(int argc, char **argv) { int opt; int option_index; unsigned i; const char *prgname = argv[0]; static struct option long_option[] = { {"nb-pools", required_argument, NULL, 0}, {NULL, 0, 0, 0} }; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:", long_option, &option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); vmdq_usage(prgname); return -1; } break; case 0: if (vmdq_parse_num_pools(optarg) == -1) { printf("invalid number of pools\n"); vmdq_usage(prgname); return -1; } break; default: vmdq_usage(prgname); return -1; } } for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (enabled_port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; } if (num_ports < 2 || num_ports % 2) { printf("Current enabled port number is %u," "but it should be even and at least 2\n", num_ports); return -1; } return 0; } static void update_mac_address(struct rte_mbuf *m, unsigned dst_port) { struct ether_hdr *eth; void *tmp; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); /* src addr */ ether_addr_copy(&vmdq_ports_eth_addr[dst_port], ð->s_addr); } /* When we receive a HUP signal, print out our stats */ static void sighup_handler(int signum) { unsigned q; for (q = 0; q < num_queues; q++) { if (q % (num_queues/num_pools) == 0) printf("\nPool %u: ", q/(num_queues/num_pools)); printf("%lu ", rxPackets[q]); } printf("\nFinished handling signal %d\n", signum); } /* * Main thread that does the work, reading from INPUT_PORT * and writing to OUTPUT_PORT */ static int lcore_main(__attribute__((__unused__)) void *dummy) { const uint16_t lcore_id = (uint16_t)rte_lcore_id(); const uint16_t num_cores = (uint16_t)rte_lcore_count(); uint16_t core_id = 0; uint16_t startQueue, endQueue; uint16_t q, i, p; const uint16_t remainder = (uint16_t)(num_vmdq_queues % num_cores); for (i = 0; i < num_cores; i++) if (lcore_ids[i] == lcore_id) { core_id = i; break; } if (remainder != 0) { if (core_id < remainder) { startQueue = (uint16_t)(core_id * (num_vmdq_queues / num_cores + 1)); endQueue = (uint16_t)(startQueue + (num_vmdq_queues / num_cores) + 1); } else { startQueue = (uint16_t)(core_id * (num_vmdq_queues / num_cores) + remainder); endQueue = (uint16_t)(startQueue + (num_vmdq_queues / num_cores)); } } else { startQueue = (uint16_t)(core_id * (num_vmdq_queues / num_cores)); endQueue = (uint16_t)(startQueue + (num_vmdq_queues / num_cores)); } /* vmdq queue idx doesn't always start from zero.*/ startQueue += vmdq_queue_base; endQueue += vmdq_queue_base; printf("core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_id, (unsigned)lcore_id, startQueue, endQueue - 1); if (startQueue == endQueue) { printf("lcore %u has nothing to do\n", lcore_id); return 0; } for (;;) { struct rte_mbuf *buf[MAX_PKT_BURST]; const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]); for (p = 0; p < num_ports; p++) { const uint8_t sport = ports[p]; /* 0 <-> 1, 2 <-> 3 etc */ const uint8_t dport = ports[p ^ 1]; if ((sport == INVALID_PORT_ID) || (dport == INVALID_PORT_ID)) continue; for (q = startQueue; q < endQueue; q++) { const uint16_t rxCount = rte_eth_rx_burst(sport, q, buf, buf_size); if (unlikely(rxCount == 0)) continue; rxPackets[q] += rxCount; for (i = 0; i < rxCount; i++) update_mac_address(buf[i], dport); const uint16_t txCount = rte_eth_tx_burst(dport, vmdq_queue_base + core_id, buf, rxCount); if (txCount != rxCount) { for (i = txCount; i < rxCount; i++) rte_pktmbuf_free(buf[i]); } } } } } /* * Update the global var NUM_PORTS and array PORTS according to system ports number * and return valid ports number */ static unsigned check_ports_num(unsigned nb_ports) { unsigned valid_num_ports = num_ports; unsigned portid; if (num_ports > nb_ports) { printf("\nSpecified port number(%u) exceeds total system port number(%u)\n", num_ports, nb_ports); num_ports = nb_ports; } for (portid = 0; portid < num_ports; portid++) { if (ports[portid] >= nb_ports) { printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", ports[portid], (nb_ports - 1)); ports[portid] = INVALID_PORT_ID; valid_num_ports--; } } return valid_num_ports; } /* Main function, does initialisation and calls the per-lcore functions */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; unsigned lcore_id, core_id = 0; int ret; unsigned nb_ports, valid_num_ports; uint8_t portid; signal(SIGHUP, sighup_handler); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse app arguments */ ret = vmdq_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid VMDQ argument\n"); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) if (rte_lcore_is_enabled(lcore_id)) lcore_ids[core_id++] = lcore_id; if (rte_lcore_count() > RTE_MAX_LCORE) rte_exit(EXIT_FAILURE, "Not enough cores\n"); nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Update the global var NUM_PORTS and global array PORTS * and get value of var VALID_NUM_PORTS according to system ports number */ valid_num_ports = check_ports_num(nb_ports); if (valid_num_ports < 2 || valid_num_ports % 2) { printf("Current valid ports number is %u\n", valid_num_ports); rte_exit(EXIT_FAILURE, "Error with valid ports number is not even or less than 2\n"); } mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS_PER_PORT * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); } /* call lcore_main() on every lcore */ rte_eal_mp_remote_launch(lcore_main, NULL, CALL_MASTER); RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; } return 0; } ================================================ FILE: examples/vmdq_dcb/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif # Default target, can be overriden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = vmdq_dcb_app # all source are stored in SRCS-y SRCS-y := main.c CFLAGS += $(WERROR_FLAGS) # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_main.o += -Wno-return-type endif EXTRA_CFLAGS += -O3 -g include $(RTE_SDK)/mk/rte.extapp.mk ================================================ FILE: examples/vmdq_dcb/main.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* basic constants used in application */ #define NUM_QUEUES 128 #define NUM_MBUFS 64*1024 #define MBUF_CACHE_SIZE 64 #define INVALID_PORT_ID 0xFF /* mask of enabled ports */ static uint32_t enabled_port_mask = 0; /* number of pools (if user does not specify any, 16 by default */ static enum rte_eth_nb_pools num_pools = ETH_16_POOLS; /* empty vmdq+dcb configuration structure. Filled in programatically */ static const struct rte_eth_conf vmdq_dcb_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_DCB, .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, .rx_adv_conf = { /* * should be overridden separately in code with * appropriate values */ .vmdq_dcb_conf = { .nb_queue_pools = ETH_16_POOLS, .enable_default_pool = 0, .default_pool = 0, .nb_pool_maps = 0, .pool_map = {{0, 0},}, .dcb_queue = {0}, }, }, }; static uint8_t ports[RTE_MAX_ETHPORTS]; static unsigned num_ports = 0; /* array used for printing out statistics */ volatile unsigned long rxPackets[ NUM_QUEUES ] = {0}; const uint16_t vlan_tags[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array * given above, and the number of traffic classes available for use. */ static inline int get_eth_conf(struct rte_eth_conf *eth_conf, enum rte_eth_nb_pools num_pools) { struct rte_eth_vmdq_dcb_conf conf; unsigned i; if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS ) return -1; conf.nb_queue_pools = num_pools; conf.enable_default_pool = 0; conf.default_pool = 0; /* set explicit value, even if not used */ conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); for (i = 0; i < conf.nb_pool_maps; i++){ conf.pool_map[i].vlan_id = vlan_tags[ i ]; conf.pool_map[i].pools = 1 << (i % num_pools); } for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ conf.dcb_queue[i] = (uint8_t)(i % (NUM_QUEUES/num_pools)); } (void)(rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(*eth_conf))); (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &conf, sizeof(eth_conf->rx_adv_conf.vmdq_dcb_conf))); return 0; } /* * Initialises a given port using global settings and with the rx buffers * coming from the mbuf_pool passed as parameter */ static inline int port_init(uint8_t port, struct rte_mempool *mbuf_pool) { struct rte_eth_conf port_conf; const uint16_t rxRings = ETH_VMDQ_DCB_NUM_QUEUES, txRings = (uint16_t)rte_lcore_count(); const uint16_t rxRingSize = 128, txRingSize = 512; int retval; uint16_t q; retval = get_eth_conf(&port_conf, num_pools); if (retval < 0) return retval; if (port >= rte_eth_dev_count()) return -1; retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; for (q = 0; q < rxRings; q ++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } for (q = 0; q < txRings; q ++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, rte_eth_dev_socket_id(port), NULL); if (retval < 0) return retval; } retval = rte_eth_dev_start(port); if (retval < 0) return retval; struct ether_addr addr; rte_eth_macaddr_get(port, &addr); printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", (unsigned)port, addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); return 0; } /* Check num_pools parameter and set it if OK*/ static int vmdq_parse_num_pools(const char *q_arg) { char *end = NULL; int n; /* parse number string */ n = strtol(q_arg, &end, 10); if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (n != 16 && n != 32) return -1; if (n == 16) num_pools = ETH_16_POOLS; else num_pools = ETH_32_POOLS; return 0; } static int parse_portmask(const char *portmask) { char *end = NULL; unsigned long pm; /* parse hexadecimal string */ pm = strtoul(portmask, &end, 16); if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) return -1; if (pm == 0) return -1; return pm; } /* Display usage */ static void vmdq_usage(const char *prgname) { printf("%s [EAL options] -- -p PORTMASK]\n" " --nb-pools NP: number of pools (16 default, 32)\n", prgname); } /* Parse the argument (num_pools) given in the command line of the application */ static int vmdq_parse_args(int argc, char **argv) { int opt; int option_index; unsigned i; const char *prgname = argv[0]; static struct option long_option[] = { {"nb-pools", required_argument, NULL, 0}, {NULL, 0, 0, 0} }; /* Parse command line */ while ((opt = getopt_long(argc, argv, "p:",long_option,&option_index)) != EOF) { switch (opt) { /* portmask */ case 'p': enabled_port_mask = parse_portmask(optarg); if (enabled_port_mask == 0) { printf("invalid portmask\n"); vmdq_usage(prgname); return -1; } break; case 0: if (vmdq_parse_num_pools(optarg) == -1){ printf("invalid number of pools\n"); vmdq_usage(prgname); return -1; } break; default: vmdq_usage(prgname); return -1; } } for(i = 0; i < RTE_MAX_ETHPORTS; i++) { if (enabled_port_mask & (1 << i)) ports[num_ports++] = (uint8_t)i; } if (num_ports < 2 || num_ports % 2) { printf("Current enabled port number is %u," "but it should be even and at least 2\n",num_ports); return -1; } return 0; } /* When we receive a HUP signal, print out our stats */ static void sighup_handler(int signum) { unsigned q; for (q = 0; q < NUM_QUEUES; q ++) { if (q % (NUM_QUEUES/num_pools) == 0) printf("\nPool %u: ", q/(NUM_QUEUES/num_pools)); printf("%lu ", rxPackets[ q ]); } printf("\nFinished handling signal %d\n", signum); } /* * Main thread that does the work, reading from INPUT_PORT * and writing to OUTPUT_PORT */ static __attribute__((noreturn)) int lcore_main(void *arg) { const uintptr_t core_num = (uintptr_t)arg; const unsigned num_cores = rte_lcore_count(); uint16_t startQueue = (uint16_t)(core_num * (NUM_QUEUES/num_cores)); uint16_t endQueue = (uint16_t)(startQueue + (NUM_QUEUES/num_cores)); uint16_t q, i, p; printf("Core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_num, rte_lcore_id(), startQueue, endQueue - 1); for (;;) { struct rte_mbuf *buf[32]; const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]); for (p = 0; p < num_ports; p++) { const uint8_t src = ports[p]; const uint8_t dst = ports[p ^ 1]; /* 0 <-> 1, 2 <-> 3 etc */ if ((src == INVALID_PORT_ID) || (dst == INVALID_PORT_ID)) continue; for (q = startQueue; q < endQueue; q++) { const uint16_t rxCount = rte_eth_rx_burst(src, q, buf, buf_size); if (rxCount == 0) continue; rxPackets[q] += rxCount; const uint16_t txCount = rte_eth_tx_burst(dst, (uint16_t)core_num, buf, rxCount); if (txCount != rxCount) { for (i = txCount; i < rxCount; i++) rte_pktmbuf_free(buf[i]); } } } } } /* * Update the global var NUM_PORTS and array PORTS according to system ports number * and return valid ports number */ static unsigned check_ports_num(unsigned nb_ports) { unsigned valid_num_ports = num_ports; unsigned portid; if (num_ports > nb_ports) { printf("\nSpecified port number(%u) exceeds total system port number(%u)\n", num_ports, nb_ports); num_ports = nb_ports; } for (portid = 0; portid < num_ports; portid ++) { if (ports[portid] >= nb_ports) { printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", ports[portid], (nb_ports - 1)); ports[portid] = INVALID_PORT_ID; valid_num_ports --; } } return valid_num_ports; } /* Main function, does initialisation and calls the per-lcore functions */ int main(int argc, char *argv[]) { unsigned cores; struct rte_mempool *mbuf_pool; unsigned lcore_id; uintptr_t i; int ret; unsigned nb_ports, valid_num_ports; uint8_t portid; signal(SIGHUP, sighup_handler); /* init EAL */ ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* parse app arguments */ ret = vmdq_parse_args(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid VMDQ argument\n"); cores = rte_lcore_count(); if ((cores & (cores - 1)) != 0 || cores > 128) { rte_exit(EXIT_FAILURE,"This program can only run on an even" "number of cores(1-128)\n\n"); } nb_ports = rte_eth_dev_count(); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; /* * Update the global var NUM_PORTS and global array PORTS * and get value of var VALID_NUM_PORTS according to system ports number */ valid_num_ports = check_ports_num(nb_ports); if (valid_num_ports < 2 || valid_num_ports % 2) { printf("Current valid ports number is %u\n", valid_num_ports); rte_exit(EXIT_FAILURE, "Error with valid ports number is not even or less than 2\n"); } mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* initialize all ports */ for (portid = 0; portid < nb_ports; portid++) { /* skip ports that are not enabled */ if ((enabled_port_mask & (1 << portid)) == 0) { printf("\nSkipping disabled port %d\n", portid); continue; } if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); } /* call lcore_main() on every slave lcore */ i = 0; RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(lcore_main, (void*)i++, lcore_id); } /* call on master too */ (void) lcore_main((void*)i); return 0; } ================================================ FILE: lib/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-y += librte_compat DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_malloc DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += librte_timer DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether DIRS-$(CONFIG_RTE_LIBRTE_VHOST) += librte_vhost DIRS-$(CONFIG_RTE_LIBRTE_HASH) += librte_hash DIRS-$(CONFIG_RTE_LIBRTE_LPM) += librte_lpm DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += librte_distributor DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += librte_ivshmem endif include $(RTE_SDK)/mk/rte.sharelib.mk include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: lib/librte_acl/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_acl.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_acl_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_ACL) += tb_mem.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += rte_acl.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += acl_bld.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += acl_gen.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += acl_run_scalar.c SRCS-$(CONFIG_RTE_LIBRTE_ACL) += acl_run_sse.c CFLAGS_acl_run_sse.o += -msse4.1 # # If the compiler supports AVX2 instructions, # then add support for AVX2 classify method. # CC_AVX2_SUPPORT=$(shell $(CC) -march=core-avx2 -dM -E - &1 | \ grep -q AVX2 && echo 1) ifeq ($(CC_AVX2_SUPPORT), 1) SRCS-$(CONFIG_RTE_LIBRTE_ACL) += acl_run_avx2.c CFLAGS_rte_acl.o += -DCC_AVX2_SUPPORT ifeq ($(CC), icc) CFLAGS_acl_run_avx2.o += -march=core-avx2 else CFLAGS_acl_run_avx2.o += -mavx2 endif endif # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include := rte_acl_osdep.h SYMLINK-$(CONFIG_RTE_LIBRTE_ACL)-include += rte_acl.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_ACL) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_acl/acl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ACL_H_ #define _ACL_H_ #ifdef __cplusplus extern"C" { #endif /* __cplusplus */ #define RTE_ACL_QUAD_MAX 5 #define RTE_ACL_QUAD_SIZE 4 #define RTE_ACL_QUAD_SINGLE UINT64_C(0x7f7f7f7f00000000) #define RTE_ACL_SINGLE_TRIE_SIZE 2000 #define RTE_ACL_DFA_MAX UINT8_MAX #define RTE_ACL_DFA_SIZE (UINT8_MAX + 1) #define RTE_ACL_DFA_GR64_SIZE 64 #define RTE_ACL_DFA_GR64_NUM (RTE_ACL_DFA_SIZE / RTE_ACL_DFA_GR64_SIZE) #define RTE_ACL_DFA_GR64_BIT \ (CHAR_BIT * sizeof(uint32_t) / RTE_ACL_DFA_GR64_NUM) typedef int bits_t; #define RTE_ACL_BIT_SET_SIZE ((UINT8_MAX + 1) / (sizeof(bits_t) * CHAR_BIT)) struct rte_acl_bitset { bits_t bits[RTE_ACL_BIT_SET_SIZE]; }; #define RTE_ACL_NODE_DFA (0 << RTE_ACL_TYPE_SHIFT) #define RTE_ACL_NODE_SINGLE (1U << RTE_ACL_TYPE_SHIFT) #define RTE_ACL_NODE_QRANGE (3U << RTE_ACL_TYPE_SHIFT) #define RTE_ACL_NODE_MATCH (4U << RTE_ACL_TYPE_SHIFT) #define RTE_ACL_NODE_TYPE (7U << RTE_ACL_TYPE_SHIFT) #define RTE_ACL_NODE_UNDEFINED UINT32_MAX /* * ACL RT structure is a set of multibit tries (with stride == 8) * represented by an array of transitions. The next position is calculated * based on the current position and the input byte. * Each transition is 64 bit value with the following format: * | node_type_specific : 32 | node_type : 3 | node_addr : 29 | * For all node types except RTE_ACL_NODE_MATCH, node_addr is an index * to the start of the node in the transtions array. * Few different node types are used: * RTE_ACL_NODE_MATCH: * node_addr value is and index into an array that contains the return value * and its priority for each category. * Upper 32 bits of the transition value are not used for that node type. * RTE_ACL_NODE_QRANGE: * that node consist of up to 5 transitions. * Upper 32 bits are interpreted as 4 signed character values which * are ordered from smallest(INT8_MIN) to largest (INT8_MAX). * These values define 5 ranges: * INT8_MIN <= range[0] <= ((int8_t *)&transition)[4] * ((int8_t *)&transition)[4] < range[1] <= ((int8_t *)&transition)[5] * ((int8_t *)&transition)[5] < range[2] <= ((int8_t *)&transition)[6] * ((int8_t *)&transition)[6] < range[3] <= ((int8_t *)&transition)[7] * ((int8_t *)&transition)[7] < range[4] <= INT8_MAX * So for input byte value within range[i] i-th transition within that node * will be used. * RTE_ACL_NODE_SINGLE: * always transitions to the same node regardless of the input value. * RTE_ACL_NODE_DFA: * that node consits of up to 256 transitions. * In attempt to conserve space all transitions are divided into 4 consecutive * groups, by 64 transitions per group: * group64[i] contains transitions[i * 64, .. i * 64 + 63]. * Upper 32 bits are interpreted as 4 unsigned character values one per group, * which contain index to the start of the given group within the node. * So to calculate transition index within the node for given input byte value: * input_byte - ((uint8_t *)&transition)[4 + input_byte / 64]. */ /* * Structure of a node is a set of ptrs and each ptr has a bit map * of values associated with this transition. */ struct rte_acl_ptr_set { struct rte_acl_bitset values; /* input values associated with ptr */ struct rte_acl_node *ptr; /* transition to next node */ }; struct rte_acl_classifier_results { int results[RTE_ACL_MAX_CATEGORIES]; }; struct rte_acl_match_results { uint32_t results[RTE_ACL_MAX_CATEGORIES]; int32_t priority[RTE_ACL_MAX_CATEGORIES]; }; struct rte_acl_node { uint64_t node_index; /* index for this node */ uint32_t level; /* level 0-n in the trie */ uint32_t ref_count; /* ref count for this node */ struct rte_acl_bitset values; /* set of all values that map to another node * (union of bits in each transition. */ uint32_t num_ptrs; /* number of ptr_set in use */ uint32_t max_ptrs; /* number of allocated ptr_set */ uint32_t min_add; /* number of ptr_set per allocation */ struct rte_acl_ptr_set *ptrs; /* transitions array for this node */ int32_t match_flag; int32_t match_index; /* index to match data */ uint32_t node_type; int32_t fanout; /* number of ranges (transitions w/ consecutive bits) */ int32_t id; struct rte_acl_match_results *mrt; /* only valid when match_flag != 0 */ union { char transitions[RTE_ACL_QUAD_SIZE]; /* boundaries for ranged node */ uint8_t dfa_gr64[RTE_ACL_DFA_GR64_NUM]; }; struct rte_acl_node *next; /* free list link or pointer to duplicate node during merge */ struct rte_acl_node *prev; /* points to node from which this node was duplicated */ }; /* * Types of tries used to generate runtime structure(s) */ enum { RTE_ACL_FULL_TRIE = 0, RTE_ACL_NOSRC_TRIE = 1, RTE_ACL_NODST_TRIE = 2, RTE_ACL_NOPORTS_TRIE = 4, RTE_ACL_NOVLAN_TRIE = 8, RTE_ACL_UNUSED_TRIE = 0x80000000 }; /** MAX number of tries per one ACL context.*/ #define RTE_ACL_MAX_TRIES 8 /** Max number of characters in PM name.*/ #define RTE_ACL_NAMESIZE 32 struct rte_acl_trie { uint32_t type; uint32_t count; uint32_t root_index; const uint32_t *data_index; uint32_t num_data_indexes; }; struct rte_acl_bld_trie { struct rte_acl_node *trie; }; struct rte_acl_ctx { char name[RTE_ACL_NAMESIZE]; /** Name of the ACL context. */ int32_t socket_id; /** Socket ID to allocate memory from. */ enum rte_acl_classify_alg alg; void *rules; uint32_t max_rules; uint32_t rule_sz; uint32_t num_rules; uint32_t num_categories; uint32_t num_tries; uint32_t match_index; uint64_t no_match; uint64_t idle; uint64_t *trans_table; uint32_t *data_indexes; struct rte_acl_trie trie[RTE_ACL_MAX_TRIES]; void *mem; size_t mem_sz; struct rte_acl_config config; /* copy of build config. */ }; int rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie, struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries, uint32_t num_categories, uint32_t data_index_sz, size_t max_size); typedef int (*rte_acl_classify_t) (const struct rte_acl_ctx *, const uint8_t **, uint32_t *, uint32_t, uint32_t); /* * Different implementations of ACL classify. */ int rte_acl_classify_scalar(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories); int rte_acl_classify_sse(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories); int rte_acl_classify_avx2(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _ACL_H_ */ ================================================ FILE: lib/librte_acl/acl_bld.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "tb_mem.h" #include "acl.h" #define ACL_POOL_ALIGN 8 #define ACL_POOL_ALLOC_MIN 0x800000 /* number of pointers per alloc */ #define ACL_PTR_ALLOC 32 /* macros for dividing rule sets heuristics */ #define NODE_MAX 0x4000 #define NODE_MIN 0x800 /* TALLY are statistics per field */ enum { TALLY_0 = 0, /* number of rules that are 0% or more wild. */ TALLY_25, /* number of rules that are 25% or more wild. */ TALLY_50, TALLY_75, TALLY_100, TALLY_DEACTIVATED, /* deactivated fields (100% wild in all rules). */ TALLY_DEPTH, /* number of rules that are 100% wild for this field and higher. */ TALLY_NUM }; static const uint32_t wild_limits[TALLY_DEACTIVATED] = {0, 25, 50, 75, 100}; enum { ACL_INTERSECT_NONE = 0, ACL_INTERSECT_A = 1, /* set A is a superset of A and B intersect */ ACL_INTERSECT_B = 2, /* set B is a superset of A and B intersect */ ACL_INTERSECT = 4, /* sets A and B intersect */ }; enum { ACL_PRIORITY_EQUAL = 0, ACL_PRIORITY_NODE_A = 1, ACL_PRIORITY_NODE_B = 2, ACL_PRIORITY_MIXED = 3 }; struct acl_mem_block { uint32_t block_size; void *mem_ptr; }; #define MEM_BLOCK_NUM 16 /* Single ACL rule, build representation.*/ struct rte_acl_build_rule { struct rte_acl_build_rule *next; struct rte_acl_config *config; /**< configuration for each field in the rule. */ const struct rte_acl_rule *f; uint32_t *wildness; }; /* Context for build phase */ struct acl_build_context { const struct rte_acl_ctx *acx; struct rte_acl_build_rule *build_rules; struct rte_acl_config cfg; int32_t node_max; int32_t cur_node_max; uint32_t node; uint32_t num_nodes; uint32_t category_mask; uint32_t num_rules; uint32_t node_id; uint32_t src_mask; uint32_t num_build_rules; uint32_t num_tries; struct tb_mem_pool pool; struct rte_acl_trie tries[RTE_ACL_MAX_TRIES]; struct rte_acl_bld_trie bld_tries[RTE_ACL_MAX_TRIES]; uint32_t data_indexes[RTE_ACL_MAX_TRIES][RTE_ACL_MAX_FIELDS]; /* memory free lists for nodes and blocks used for node ptrs */ struct acl_mem_block blocks[MEM_BLOCK_NUM]; struct rte_acl_node *node_free_list; }; static int acl_merge_trie(struct acl_build_context *context, struct rte_acl_node *node_a, struct rte_acl_node *node_b, uint32_t level, struct rte_acl_node **node_c); static void acl_deref_ptr(struct acl_build_context *context, struct rte_acl_node *node, int index); static void * acl_build_alloc(struct acl_build_context *context, size_t n, size_t s) { uint32_t m; void *p; size_t alloc_size = n * s; /* * look for memory in free lists */ for (m = 0; m < RTE_DIM(context->blocks); m++) { if (context->blocks[m].block_size == alloc_size && context->blocks[m].mem_ptr != NULL) { p = context->blocks[m].mem_ptr; context->blocks[m].mem_ptr = *((void **)p); memset(p, 0, alloc_size); return p; } } /* * return allocation from memory pool */ p = tb_alloc(&context->pool, alloc_size); return p; } /* * Free memory blocks (kept in context for reuse). */ static void acl_build_free(struct acl_build_context *context, size_t s, void *p) { uint32_t n; for (n = 0; n < RTE_DIM(context->blocks); n++) { if (context->blocks[n].block_size == s) { *((void **)p) = context->blocks[n].mem_ptr; context->blocks[n].mem_ptr = p; return; } } for (n = 0; n < RTE_DIM(context->blocks); n++) { if (context->blocks[n].block_size == 0) { context->blocks[n].block_size = s; *((void **)p) = NULL; context->blocks[n].mem_ptr = p; return; } } } /* * Allocate and initialize a new node. */ static struct rte_acl_node * acl_alloc_node(struct acl_build_context *context, int level) { struct rte_acl_node *node; if (context->node_free_list != NULL) { node = context->node_free_list; context->node_free_list = node->next; memset(node, 0, sizeof(struct rte_acl_node)); } else { node = acl_build_alloc(context, sizeof(struct rte_acl_node), 1); } if (node != NULL) { node->num_ptrs = 0; node->level = level; node->node_type = RTE_ACL_NODE_UNDEFINED; node->node_index = RTE_ACL_NODE_UNDEFINED; context->num_nodes++; node->id = context->node_id++; } return node; } /* * Dereference all nodes to which this node points */ static void acl_free_node(struct acl_build_context *context, struct rte_acl_node *node) { uint32_t n; if (node->prev != NULL) node->prev->next = NULL; for (n = 0; n < node->num_ptrs; n++) acl_deref_ptr(context, node, n); /* free mrt if this is a match node */ if (node->mrt != NULL) { acl_build_free(context, sizeof(struct rte_acl_match_results), node->mrt); node->mrt = NULL; } /* free transitions to other nodes */ if (node->ptrs != NULL) { acl_build_free(context, node->max_ptrs * sizeof(struct rte_acl_ptr_set), node->ptrs); node->ptrs = NULL; } /* put it on the free list */ context->num_nodes--; node->next = context->node_free_list; context->node_free_list = node; } /* * Include src bitset in dst bitset */ static void acl_include(struct rte_acl_bitset *dst, struct rte_acl_bitset *src, bits_t mask) { uint32_t n; for (n = 0; n < RTE_ACL_BIT_SET_SIZE; n++) dst->bits[n] = (dst->bits[n] & mask) | src->bits[n]; } /* * Set dst to bits of src1 that are not in src2 */ static int acl_exclude(struct rte_acl_bitset *dst, struct rte_acl_bitset *src1, struct rte_acl_bitset *src2) { uint32_t n; bits_t all_bits = 0; for (n = 0; n < RTE_ACL_BIT_SET_SIZE; n++) { dst->bits[n] = src1->bits[n] & ~src2->bits[n]; all_bits |= dst->bits[n]; } return all_bits != 0; } /* * Add a pointer (ptr) to a node. */ static int acl_add_ptr(struct acl_build_context *context, struct rte_acl_node *node, struct rte_acl_node *ptr, struct rte_acl_bitset *bits) { uint32_t n, num_ptrs; struct rte_acl_ptr_set *ptrs = NULL; /* * If there's already a pointer to the same node, just add to the bitset */ for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) { if (node->ptrs[n].ptr == ptr) { acl_include(&node->ptrs[n].values, bits, -1); acl_include(&node->values, bits, -1); return 0; } } } /* if there's no room for another pointer, make room */ if (node->num_ptrs >= node->max_ptrs) { /* add room for more pointers */ num_ptrs = node->max_ptrs + ACL_PTR_ALLOC; ptrs = acl_build_alloc(context, num_ptrs, sizeof(*ptrs)); /* copy current points to new memory allocation */ if (node->ptrs != NULL) { memcpy(ptrs, node->ptrs, node->num_ptrs * sizeof(*ptrs)); acl_build_free(context, node->max_ptrs * sizeof(*ptrs), node->ptrs); } node->ptrs = ptrs; node->max_ptrs = num_ptrs; } /* Find available ptr and add a new pointer to this node */ for (n = node->min_add; n < node->max_ptrs; n++) { if (node->ptrs[n].ptr == NULL) { node->ptrs[n].ptr = ptr; acl_include(&node->ptrs[n].values, bits, 0); acl_include(&node->values, bits, -1); if (ptr != NULL) ptr->ref_count++; if (node->num_ptrs <= n) node->num_ptrs = n + 1; return 0; } } return 0; } /* * Add a pointer for a range of values */ static int acl_add_ptr_range(struct acl_build_context *context, struct rte_acl_node *root, struct rte_acl_node *node, uint8_t low, uint8_t high) { uint32_t n; struct rte_acl_bitset bitset; /* clear the bitset values */ for (n = 0; n < RTE_ACL_BIT_SET_SIZE; n++) bitset.bits[n] = 0; /* for each bit in range, add bit to set */ for (n = 0; n < UINT8_MAX + 1; n++) if (n >= low && n <= high) bitset.bits[n / (sizeof(bits_t) * 8)] |= 1 << (n % (sizeof(bits_t) * 8)); return acl_add_ptr(context, root, node, &bitset); } /* * Generate a bitset from a byte value and mask. */ static int acl_gen_mask(struct rte_acl_bitset *bitset, uint32_t value, uint32_t mask) { int range = 0; uint32_t n; /* clear the bitset values */ for (n = 0; n < RTE_ACL_BIT_SET_SIZE; n++) bitset->bits[n] = 0; /* for each bit in value/mask, add bit to set */ for (n = 0; n < UINT8_MAX + 1; n++) { if ((n & mask) == value) { range++; bitset->bits[n / (sizeof(bits_t) * 8)] |= 1 << (n % (sizeof(bits_t) * 8)); } } return range; } /* * Determine how A and B intersect. * Determine if A and/or B are supersets of the intersection. */ static int acl_intersect_type(const struct rte_acl_bitset *a_bits, const struct rte_acl_bitset *b_bits, struct rte_acl_bitset *intersect) { uint32_t n; bits_t intersect_bits = 0; bits_t a_superset = 0; bits_t b_superset = 0; /* * calculate and store intersection and check if A and/or B have * bits outside the intersection (superset) */ for (n = 0; n < RTE_ACL_BIT_SET_SIZE; n++) { intersect->bits[n] = a_bits->bits[n] & b_bits->bits[n]; a_superset |= a_bits->bits[n] ^ intersect->bits[n]; b_superset |= b_bits->bits[n] ^ intersect->bits[n]; intersect_bits |= intersect->bits[n]; } n = (intersect_bits == 0 ? ACL_INTERSECT_NONE : ACL_INTERSECT) | (b_superset == 0 ? 0 : ACL_INTERSECT_B) | (a_superset == 0 ? 0 : ACL_INTERSECT_A); return n; } /* * Duplicate a node */ static struct rte_acl_node * acl_dup_node(struct acl_build_context *context, struct rte_acl_node *node) { uint32_t n; struct rte_acl_node *next; next = acl_alloc_node(context, node->level); /* allocate the pointers */ if (node->num_ptrs > 0) { next->ptrs = acl_build_alloc(context, node->max_ptrs, sizeof(struct rte_acl_ptr_set)); next->max_ptrs = node->max_ptrs; } /* copy over the pointers */ for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) { next->ptrs[n].ptr = node->ptrs[n].ptr; next->ptrs[n].ptr->ref_count++; acl_include(&next->ptrs[n].values, &node->ptrs[n].values, -1); } } next->num_ptrs = node->num_ptrs; /* copy over node's match results */ if (node->match_flag == 0) next->match_flag = 0; else { next->match_flag = -1; next->mrt = acl_build_alloc(context, 1, sizeof(*next->mrt)); memcpy(next->mrt, node->mrt, sizeof(*next->mrt)); } /* copy over node's bitset */ acl_include(&next->values, &node->values, -1); node->next = next; next->prev = node; return next; } /* * Dereference a pointer from a node */ static void acl_deref_ptr(struct acl_build_context *context, struct rte_acl_node *node, int index) { struct rte_acl_node *ref_node; /* De-reference the node at the specified pointer */ if (node != NULL && node->ptrs[index].ptr != NULL) { ref_node = node->ptrs[index].ptr; ref_node->ref_count--; if (ref_node->ref_count == 0) acl_free_node(context, ref_node); } } /* * acl_exclude rte_acl_bitset from src and copy remaining pointer to dst */ static int acl_copy_ptr(struct acl_build_context *context, struct rte_acl_node *dst, struct rte_acl_node *src, int index, struct rte_acl_bitset *b_bits) { int rc; struct rte_acl_bitset bits; if (b_bits != NULL) if (!acl_exclude(&bits, &src->ptrs[index].values, b_bits)) return 0; rc = acl_add_ptr(context, dst, src->ptrs[index].ptr, &bits); if (rc < 0) return rc; return 1; } /* * Fill in gaps in ptrs list with the ptr at the end of the list */ static void acl_compact_node_ptrs(struct rte_acl_node *node_a) { uint32_t n; int min_add = node_a->min_add; while (node_a->num_ptrs > 0 && node_a->ptrs[node_a->num_ptrs - 1].ptr == NULL) node_a->num_ptrs--; for (n = min_add; n + 1 < node_a->num_ptrs; n++) { /* if this entry is empty */ if (node_a->ptrs[n].ptr == NULL) { /* move the last pointer to this entry */ acl_include(&node_a->ptrs[n].values, &node_a->ptrs[node_a->num_ptrs - 1].values, 0); node_a->ptrs[n].ptr = node_a->ptrs[node_a->num_ptrs - 1].ptr; /* * mark the end as empty and adjust the number * of used pointer enum_tries */ node_a->ptrs[node_a->num_ptrs - 1].ptr = NULL; while (node_a->num_ptrs > 0 && node_a->ptrs[node_a->num_ptrs - 1].ptr == NULL) node_a->num_ptrs--; } } } static int acl_resolve_leaf(struct acl_build_context *context, struct rte_acl_node *node_a, struct rte_acl_node *node_b, struct rte_acl_node **node_c) { uint32_t n; int combined_priority = ACL_PRIORITY_EQUAL; for (n = 0; n < context->cfg.num_categories; n++) { if (node_a->mrt->priority[n] != node_b->mrt->priority[n]) { combined_priority |= (node_a->mrt->priority[n] > node_b->mrt->priority[n]) ? ACL_PRIORITY_NODE_A : ACL_PRIORITY_NODE_B; } } /* * if node a is higher or equal priority for all categories, * then return node_a. */ if (combined_priority == ACL_PRIORITY_NODE_A || combined_priority == ACL_PRIORITY_EQUAL) { *node_c = node_a; return 0; } /* * if node b is higher or equal priority for all categories, * then return node_b. */ if (combined_priority == ACL_PRIORITY_NODE_B) { *node_c = node_b; return 0; } /* * mixed priorities - create a new node with the highest priority * for each category. */ /* force new duplication. */ node_a->next = NULL; *node_c = acl_dup_node(context, node_a); for (n = 0; n < context->cfg.num_categories; n++) { if ((*node_c)->mrt->priority[n] < node_b->mrt->priority[n]) { (*node_c)->mrt->priority[n] = node_b->mrt->priority[n]; (*node_c)->mrt->results[n] = node_b->mrt->results[n]; } } return 0; } /* * Merge nodes A and B together, * returns a node that is the path for the intersection * * If match node (leaf on trie) * For each category * return node = highest priority result * * Create C as a duplicate of A to point to child intersections * If any pointers in C intersect with any in B * For each intersection * merge children * remove intersection from C pointer * add a pointer from C to child intersection node * Compact the pointers in A and B * Copy any B pointers that are outside of the intersection to C * If C has no references to the B trie * free C and return A * Else If C has no references to the A trie * free C and return B * Else * return C */ static int acl_merge_trie(struct acl_build_context *context, struct rte_acl_node *node_a, struct rte_acl_node *node_b, uint32_t level, struct rte_acl_node **return_c) { uint32_t n, m, ptrs_c, ptrs_b; uint32_t min_add_c, min_add_b; int node_intersect_type; struct rte_acl_bitset node_intersect; struct rte_acl_node *node_c; struct rte_acl_node *node_a_next; int node_b_refs; int node_a_refs; node_c = node_a; node_a_next = node_a->next; min_add_c = 0; min_add_b = 0; node_a_refs = node_a->num_ptrs; node_b_refs = 0; node_intersect_type = 0; /* Resolve leaf nodes (matches) */ if (node_a->match_flag != 0) { acl_resolve_leaf(context, node_a, node_b, return_c); return 0; } /* * Create node C as a copy of node A, and do: C = merge(A,B); * If node A can be used instead (A==C), then later we'll * destroy C and return A. */ if (level > 0) node_c = acl_dup_node(context, node_a); /* * If the two node transitions intersect then merge the transitions. * Check intersection for entire node (all pointers) */ node_intersect_type = acl_intersect_type(&node_c->values, &node_b->values, &node_intersect); if (node_intersect_type & ACL_INTERSECT) { min_add_b = node_b->min_add; node_b->min_add = node_b->num_ptrs; ptrs_b = node_b->num_ptrs; min_add_c = node_c->min_add; node_c->min_add = node_c->num_ptrs; ptrs_c = node_c->num_ptrs; for (n = 0; n < ptrs_c; n++) { if (node_c->ptrs[n].ptr == NULL) { node_a_refs--; continue; } node_c->ptrs[n].ptr->next = NULL; for (m = 0; m < ptrs_b; m++) { struct rte_acl_bitset child_intersect; int child_intersect_type; struct rte_acl_node *child_node_c = NULL; if (node_b->ptrs[m].ptr == NULL || node_c->ptrs[n].ptr == node_b->ptrs[m].ptr) continue; child_intersect_type = acl_intersect_type( &node_c->ptrs[n].values, &node_b->ptrs[m].values, &child_intersect); if ((child_intersect_type & ACL_INTERSECT) != 0) { if (acl_merge_trie(context, node_c->ptrs[n].ptr, node_b->ptrs[m].ptr, level + 1, &child_node_c)) return 1; if (child_node_c != NULL && child_node_c != node_c->ptrs[n].ptr) { node_b_refs++; /* * Added link from C to * child_C for all transitions * in the intersection. */ acl_add_ptr(context, node_c, child_node_c, &child_intersect); /* * inc refs if pointer is not * to node b. */ node_a_refs += (child_node_c != node_b->ptrs[m].ptr); /* * Remove intersection from C * pointer. */ if (!acl_exclude( &node_c->ptrs[n].values, &node_c->ptrs[n].values, &child_intersect)) { acl_deref_ptr(context, node_c, n); node_c->ptrs[n].ptr = NULL; node_a_refs--; } } } } } /* Compact pointers */ node_c->min_add = min_add_c; acl_compact_node_ptrs(node_c); node_b->min_add = min_add_b; acl_compact_node_ptrs(node_b); } /* * Copy pointers outside of the intersection from B to C */ if ((node_intersect_type & ACL_INTERSECT_B) != 0) { node_b_refs++; for (m = 0; m < node_b->num_ptrs; m++) if (node_b->ptrs[m].ptr != NULL) acl_copy_ptr(context, node_c, node_b, m, &node_intersect); } /* * Free node C if top of trie is contained in A or B * if node C is a duplicate of node A && * node C was not an existing duplicate */ if (node_c != node_a && node_c != node_a_next) { /* * if the intersection has no references to the * B side, then it is contained in A */ if (node_b_refs == 0) { acl_free_node(context, node_c); node_c = node_a; } else { /* * if the intersection has no references to the * A side, then it is contained in B. */ if (node_a_refs == 0) { acl_free_node(context, node_c); node_c = node_b; } } } if (return_c != NULL) *return_c = node_c; if (level == 0) acl_free_node(context, node_b); return 0; } /* * Reset current runtime fields before next build: * - free allocated RT memory. * - reset all RT related fields to zero. */ static void acl_build_reset(struct rte_acl_ctx *ctx) { rte_free(ctx->mem); memset(&ctx->num_categories, 0, sizeof(*ctx) - offsetof(struct rte_acl_ctx, num_categories)); } static void acl_gen_range(struct acl_build_context *context, const uint8_t *hi, const uint8_t *lo, int size, int level, struct rte_acl_node *root, struct rte_acl_node *end) { struct rte_acl_node *node, *prev; uint32_t n; prev = root; for (n = size - 1; n > 0; n--) { node = acl_alloc_node(context, level++); acl_add_ptr_range(context, prev, node, lo[n], hi[n]); prev = node; } acl_add_ptr_range(context, prev, end, lo[0], hi[0]); } static struct rte_acl_node * acl_gen_range_trie(struct acl_build_context *context, const void *min, const void *max, int size, int level, struct rte_acl_node **pend) { int32_t n; struct rte_acl_node *root; const uint8_t *lo = (const uint8_t *)min; const uint8_t *hi = (const uint8_t *)max; *pend = acl_alloc_node(context, level+size); root = acl_alloc_node(context, level++); if (lo[size - 1] == hi[size - 1]) { acl_gen_range(context, hi, lo, size, level, root, *pend); } else { uint8_t limit_lo[64]; uint8_t limit_hi[64]; uint8_t hi_ff = UINT8_MAX; uint8_t lo_00 = 0; memset(limit_lo, 0, RTE_DIM(limit_lo)); memset(limit_hi, UINT8_MAX, RTE_DIM(limit_hi)); for (n = size - 2; n >= 0; n--) { hi_ff = (uint8_t)(hi_ff & hi[n]); lo_00 = (uint8_t)(lo_00 | lo[n]); } if (hi_ff != UINT8_MAX) { limit_lo[size - 1] = hi[size - 1]; acl_gen_range(context, hi, limit_lo, size, level, root, *pend); } if (lo_00 != 0) { limit_hi[size - 1] = lo[size - 1]; acl_gen_range(context, limit_hi, lo, size, level, root, *pend); } if (hi[size - 1] - lo[size - 1] > 1 || lo_00 == 0 || hi_ff == UINT8_MAX) { limit_lo[size-1] = (uint8_t)(lo[size-1] + (lo_00 != 0)); limit_hi[size-1] = (uint8_t)(hi[size-1] - (hi_ff != UINT8_MAX)); acl_gen_range(context, limit_hi, limit_lo, size, level, root, *pend); } } return root; } static struct rte_acl_node * acl_gen_mask_trie(struct acl_build_context *context, const void *value, const void *mask, int size, int level, struct rte_acl_node **pend) { int32_t n; struct rte_acl_node *root; struct rte_acl_node *node, *prev; struct rte_acl_bitset bits; const uint8_t *val = (const uint8_t *)value; const uint8_t *msk = (const uint8_t *)mask; root = acl_alloc_node(context, level++); prev = root; for (n = size - 1; n >= 0; n--) { node = acl_alloc_node(context, level++); acl_gen_mask(&bits, val[n] & msk[n], msk[n]); acl_add_ptr(context, prev, node, &bits); prev = node; } *pend = prev; return root; } static struct rte_acl_node * build_trie(struct acl_build_context *context, struct rte_acl_build_rule *head, struct rte_acl_build_rule **last, uint32_t *count) { uint32_t n, m; int field_index, node_count; struct rte_acl_node *trie; struct rte_acl_build_rule *prev, *rule; struct rte_acl_node *end, *merge, *root, *end_prev; const struct rte_acl_field *fld; prev = head; rule = head; *last = prev; trie = acl_alloc_node(context, 0); while (rule != NULL) { root = acl_alloc_node(context, 0); root->ref_count = 1; end = root; for (n = 0; n < rule->config->num_fields; n++) { field_index = rule->config->defs[n].field_index; fld = rule->f->field + field_index; end_prev = end; /* build a mini-trie for this field */ switch (rule->config->defs[n].type) { case RTE_ACL_FIELD_TYPE_BITMASK: merge = acl_gen_mask_trie(context, &fld->value, &fld->mask_range, rule->config->defs[n].size, end->level + 1, &end); break; case RTE_ACL_FIELD_TYPE_MASK: { /* * set msb for the size of the field and * all higher bits. */ uint64_t mask; mask = RTE_ACL_MASKLEN_TO_BITMASK( fld->mask_range.u32, rule->config->defs[n].size); /* gen a mini-trie for this field */ merge = acl_gen_mask_trie(context, &fld->value, (char *)&mask, rule->config->defs[n].size, end->level + 1, &end); } break; case RTE_ACL_FIELD_TYPE_RANGE: merge = acl_gen_range_trie(context, &rule->f->field[field_index].value, &rule->f->field[field_index].mask_range, rule->config->defs[n].size, end->level + 1, &end); break; default: RTE_LOG(ERR, ACL, "Error in rule[%u] type - %hhu\n", rule->f->data.userdata, rule->config->defs[n].type); return NULL; } /* merge this field on to the end of the rule */ if (acl_merge_trie(context, end_prev, merge, 0, NULL) != 0) { return NULL; } } end->match_flag = ++context->num_build_rules; /* * Setup the results for this rule. * The result and priority of each category. */ if (end->mrt == NULL) end->mrt = acl_build_alloc(context, 1, sizeof(*end->mrt)); for (m = context->cfg.num_categories; 0 != m--; ) { if (rule->f->data.category_mask & (1 << m)) { end->mrt->results[m] = rule->f->data.userdata; end->mrt->priority[m] = rule->f->data.priority; } else { end->mrt->results[m] = 0; end->mrt->priority[m] = 0; } } node_count = context->num_nodes; (*count)++; /* merge this rule into the trie */ if (acl_merge_trie(context, trie, root, 0, NULL)) return NULL; node_count = context->num_nodes - node_count; if (node_count > context->cur_node_max) { *last = prev; return trie; } prev = rule; rule = rule->next; } *last = NULL; return trie; } static void acl_calc_wildness(struct rte_acl_build_rule *head, const struct rte_acl_config *config) { uint32_t n; struct rte_acl_build_rule *rule; for (rule = head; rule != NULL; rule = rule->next) { for (n = 0; n < config->num_fields; n++) { double wild = 0; uint32_t bit_len = CHAR_BIT * config->defs[n].size; uint64_t msk_val = RTE_LEN2MASK(bit_len, typeof(msk_val)); double size = bit_len; int field_index = config->defs[n].field_index; const struct rte_acl_field *fld = rule->f->field + field_index; switch (rule->config->defs[n].type) { case RTE_ACL_FIELD_TYPE_BITMASK: wild = (size - __builtin_popcountll( fld->mask_range.u64 & msk_val)) / size; break; case RTE_ACL_FIELD_TYPE_MASK: wild = (size - fld->mask_range.u32) / size; break; case RTE_ACL_FIELD_TYPE_RANGE: wild = (fld->mask_range.u64 & msk_val) - (fld->value.u64 & msk_val); wild = wild / msk_val; break; } rule->wildness[field_index] = (uint32_t)(wild * 100); } } } static void acl_rule_stats(struct rte_acl_build_rule *head, struct rte_acl_config *config) { struct rte_acl_build_rule *rule; uint32_t n, m, fields_deactivated = 0; uint32_t start = 0, deactivate = 0; int tally[RTE_ACL_MAX_LEVELS][TALLY_NUM]; memset(tally, 0, sizeof(tally)); for (rule = head; rule != NULL; rule = rule->next) { for (n = 0; n < config->num_fields; n++) { uint32_t field_index = config->defs[n].field_index; tally[n][TALLY_0]++; for (m = 1; m < RTE_DIM(wild_limits); m++) { if (rule->wildness[field_index] >= wild_limits[m]) tally[n][m]++; } } for (n = config->num_fields - 1; n > 0; n--) { uint32_t field_index = config->defs[n].field_index; if (rule->wildness[field_index] == 100) tally[n][TALLY_DEPTH]++; else break; } } /* * Look for any field that is always wild and drop it from the config * Only deactivate if all fields for a given input loop are deactivated. */ for (n = 1; n < config->num_fields; n++) { if (config->defs[n].input_index != config->defs[n - 1].input_index) { for (m = start; m < n; m++) tally[m][TALLY_DEACTIVATED] = deactivate; fields_deactivated += deactivate; start = n; deactivate = 1; } /* if the field is not always completely wild */ if (tally[n][TALLY_100] != tally[n][TALLY_0]) deactivate = 0; } for (m = start; m < n; m++) tally[m][TALLY_DEACTIVATED] = deactivate; fields_deactivated += deactivate; /* remove deactivated fields */ if (fields_deactivated) { uint32_t k, l = 0; for (k = 0; k < config->num_fields; k++) { if (tally[k][TALLY_DEACTIVATED] == 0) { memmove(&tally[l][0], &tally[k][0], TALLY_NUM * sizeof(tally[0][0])); memmove(&config->defs[l++], &config->defs[k], sizeof(struct rte_acl_field_def)); } } config->num_fields = l; } } static int rule_cmp_wildness(struct rte_acl_build_rule *r1, struct rte_acl_build_rule *r2) { uint32_t n; for (n = 1; n < r1->config->num_fields; n++) { int field_index = r1->config->defs[n].field_index; if (r1->wildness[field_index] != r2->wildness[field_index]) return (r1->wildness[field_index] - r2->wildness[field_index]); } return 0; } /* * Sort list of rules based on the rules wildness. */ static struct rte_acl_build_rule * sort_rules(struct rte_acl_build_rule *head) { struct rte_acl_build_rule *new_head; struct rte_acl_build_rule *l, *r, **p; new_head = NULL; while (head != NULL) { /* remove element from the head of the old list. */ r = head; head = r->next; r->next = NULL; /* walk through new sorted list to find a proper place. */ for (p = &new_head; (l = *p) != NULL && rule_cmp_wildness(l, r) >= 0; p = &l->next) ; /* insert element into the new sorted list. */ r->next = *p; *p = r; } return new_head; } static uint32_t acl_build_index(const struct rte_acl_config *config, uint32_t *data_index) { uint32_t n, m; int32_t last_header; m = 0; last_header = -1; for (n = 0; n < config->num_fields; n++) { if (last_header != config->defs[n].input_index) { last_header = config->defs[n].input_index; data_index[m++] = config->defs[n].offset; } } return m; } static struct rte_acl_build_rule * build_one_trie(struct acl_build_context *context, struct rte_acl_build_rule *rule_sets[RTE_ACL_MAX_TRIES], uint32_t n, int32_t node_max) { struct rte_acl_build_rule *last; struct rte_acl_config *config; config = rule_sets[n]->config; acl_rule_stats(rule_sets[n], config); rule_sets[n] = sort_rules(rule_sets[n]); context->tries[n].type = RTE_ACL_FULL_TRIE; context->tries[n].count = 0; context->tries[n].num_data_indexes = acl_build_index(config, context->data_indexes[n]); context->tries[n].data_index = context->data_indexes[n]; context->cur_node_max = node_max; context->bld_tries[n].trie = build_trie(context, rule_sets[n], &last, &context->tries[n].count); return last; } static int acl_build_tries(struct acl_build_context *context, struct rte_acl_build_rule *head) { uint32_t n, num_tries; struct rte_acl_config *config; struct rte_acl_build_rule *last; struct rte_acl_build_rule *rule_sets[RTE_ACL_MAX_TRIES]; config = head->config; rule_sets[0] = head; /* initialize tries */ for (n = 0; n < RTE_DIM(context->tries); n++) { context->tries[n].type = RTE_ACL_UNUSED_TRIE; context->bld_tries[n].trie = NULL; context->tries[n].count = 0; } context->tries[0].type = RTE_ACL_FULL_TRIE; /* calc wildness of each field of each rule */ acl_calc_wildness(head, config); for (n = 0;; n = num_tries) { num_tries = n + 1; last = build_one_trie(context, rule_sets, n, context->node_max); if (context->bld_tries[n].trie == NULL) { RTE_LOG(ERR, ACL, "Build of %u-th trie failed\n", n); return -ENOMEM; } /* Build of the last trie completed. */ if (last == NULL) break; if (num_tries == RTE_DIM(context->tries)) { RTE_LOG(ERR, ACL, "Exceeded max number of tries: %u\n", num_tries); return -ENOMEM; } /* Trie is getting too big, split remaining rule set. */ rule_sets[num_tries] = last->next; last->next = NULL; acl_free_node(context, context->bld_tries[n].trie); /* Create a new copy of config for remaining rules. */ config = acl_build_alloc(context, 1, sizeof(*config)); memcpy(config, rule_sets[n]->config, sizeof(*config)); /* Make remaining rules use new config. */ for (head = rule_sets[num_tries]; head != NULL; head = head->next) head->config = config; /* * Rebuild the trie for the reduced rule-set. * Don't try to split it any further. */ last = build_one_trie(context, rule_sets, n, INT32_MAX); if (context->bld_tries[n].trie == NULL || last != NULL) { RTE_LOG(ERR, ACL, "Build of %u-th trie failed\n", n); return -ENOMEM; } } context->num_tries = num_tries; return 0; } static void acl_build_log(const struct acl_build_context *ctx) { uint32_t n; RTE_LOG(DEBUG, ACL, "Build phase for ACL \"%s\":\n" "node limit for tree split: %u\n" "nodes created: %u\n" "memory consumed: %zu\n", ctx->acx->name, ctx->node_max, ctx->num_nodes, ctx->pool.alloc); for (n = 0; n < RTE_DIM(ctx->tries); n++) { if (ctx->tries[n].count != 0) RTE_LOG(DEBUG, ACL, "trie %u: number of rules: %u, indexes: %u\n", n, ctx->tries[n].count, ctx->tries[n].num_data_indexes); } } static int acl_build_rules(struct acl_build_context *bcx) { struct rte_acl_build_rule *br, *head; const struct rte_acl_rule *rule; uint32_t *wp; uint32_t fn, i, n, num; size_t ofs, sz; fn = bcx->cfg.num_fields; n = bcx->acx->num_rules; ofs = n * sizeof(*br); sz = ofs + n * fn * sizeof(*wp); br = tb_alloc(&bcx->pool, sz); wp = (uint32_t *)((uintptr_t)br + ofs); num = 0; head = NULL; for (i = 0; i != n; i++) { rule = (const struct rte_acl_rule *) ((uintptr_t)bcx->acx->rules + bcx->acx->rule_sz * i); if ((rule->data.category_mask & bcx->category_mask) != 0) { br[num].next = head; br[num].config = &bcx->cfg; br[num].f = rule; br[num].wildness = wp; wp += fn; head = br + num; num++; } } bcx->num_rules = num; bcx->build_rules = head; return 0; } /* * Copy data_indexes for each trie into RT location. */ static void acl_set_data_indexes(struct rte_acl_ctx *ctx) { uint32_t i, n, ofs; ofs = 0; for (i = 0; i != ctx->num_tries; i++) { n = ctx->trie[i].num_data_indexes; memcpy(ctx->data_indexes + ofs, ctx->trie[i].data_index, n * sizeof(ctx->data_indexes[0])); ctx->trie[i].data_index = ctx->data_indexes + ofs; ofs += RTE_ACL_MAX_FIELDS; } } /* * Internal routine, performs 'build' phase of trie generation: * - setups build context. * - analizes given set of rules. * - builds internal tree(s). */ static int acl_bld(struct acl_build_context *bcx, struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg, uint32_t node_max) { int32_t rc; /* setup build context. */ memset(bcx, 0, sizeof(*bcx)); bcx->acx = ctx; bcx->pool.alignment = ACL_POOL_ALIGN; bcx->pool.min_alloc = ACL_POOL_ALLOC_MIN; bcx->cfg = *cfg; bcx->category_mask = RTE_LEN2MASK(bcx->cfg.num_categories, typeof(bcx->category_mask)); bcx->node_max = node_max; rc = sigsetjmp(bcx->pool.fail, 0); /* build phase runs out of memory. */ if (rc != 0) { RTE_LOG(ERR, ACL, "ACL context: %s, %s() failed with error code: %d\n", bcx->acx->name, __func__, rc); return rc; } /* Create a build rules copy. */ rc = acl_build_rules(bcx); if (rc != 0) return rc; /* No rules to build for that context+config */ if (bcx->build_rules == NULL) { rc = -EINVAL; } else { /* build internal trie representation. */ rc = acl_build_tries(bcx, bcx->build_rules); } return rc; } /* * Check that parameters for acl_build() are valid. */ static int acl_check_bld_param(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg) { static const size_t field_sizes[] = { sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t), }; uint32_t i, j; if (ctx == NULL || cfg == NULL || cfg->num_categories == 0 || cfg->num_categories > RTE_ACL_MAX_CATEGORIES || cfg->num_fields == 0 || cfg->num_fields > RTE_ACL_MAX_FIELDS) return -EINVAL; for (i = 0; i != cfg->num_fields; i++) { if (cfg->defs[i].type > RTE_ACL_FIELD_TYPE_BITMASK) { RTE_LOG(ERR, ACL, "ACL context: %s, invalid type: %hhu for %u-th field\n", ctx->name, cfg->defs[i].type, i); return -EINVAL; } for (j = 0; j != RTE_DIM(field_sizes) && cfg->defs[i].size != field_sizes[j]; j++) ; if (j == RTE_DIM(field_sizes)) { RTE_LOG(ERR, ACL, "ACL context: %s, invalid size: %hhu for %u-th field\n", ctx->name, cfg->defs[i].size, i); return -EINVAL; } } return 0; } int rte_acl_build(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg) { int32_t rc; uint32_t n; size_t max_size; struct acl_build_context bcx; rc = acl_check_bld_param(ctx, cfg); if (rc != 0) return rc; acl_build_reset(ctx); if (cfg->max_size == 0) { n = NODE_MIN; max_size = SIZE_MAX; } else { n = NODE_MAX; max_size = cfg->max_size; } for (rc = -ERANGE; n >= NODE_MIN && rc == -ERANGE; n /= 2) { /* perform build phase. */ rc = acl_bld(&bcx, ctx, cfg, n); if (rc == 0) { /* allocate and fill run-time structures. */ rc = rte_acl_gen(ctx, bcx.tries, bcx.bld_tries, bcx.num_tries, bcx.cfg.num_categories, RTE_ACL_MAX_FIELDS * RTE_DIM(bcx.tries) * sizeof(ctx->data_indexes[0]), max_size); if (rc == 0) { /* set data indexes. */ acl_set_data_indexes(ctx); /* copy in build config. */ ctx->config = *cfg; } } acl_build_log(&bcx); /* cleanup after build. */ tb_free_pool(&bcx.pool); } return rc; } ================================================ FILE: lib/librte_acl/acl_gen.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "acl.h" #define QRANGE_MIN ((uint8_t)INT8_MIN) #define RTE_ACL_VERIFY(exp) do { \ if (!(exp)) \ rte_panic("line %d\tassert \"" #exp "\" failed\n", __LINE__); \ } while (0) struct acl_node_counters { int32_t match; int32_t match_used; int32_t single; int32_t quad; int32_t quad_vectors; int32_t dfa; int32_t dfa_gr64; }; struct rte_acl_indices { int32_t dfa_index; int32_t quad_index; int32_t single_index; int32_t match_index; int32_t match_start; }; static void acl_gen_log_stats(const struct rte_acl_ctx *ctx, const struct acl_node_counters *counts, const struct rte_acl_indices *indices, size_t max_size) { RTE_LOG(DEBUG, ACL, "Gen phase for ACL \"%s\":\n" "runtime memory footprint on socket %d:\n" "single nodes/bytes used: %d/%zu\n" "quad nodes/vectors/bytes used: %d/%d/%zu\n" "DFA nodes/group64/bytes used: %d/%d/%zu\n" "match nodes/bytes used: %d/%zu\n" "total: %zu bytes\n" "max limit: %zu bytes\n", ctx->name, ctx->socket_id, counts->single, counts->single * sizeof(uint64_t), counts->quad, counts->quad_vectors, (indices->quad_index - indices->dfa_index) * sizeof(uint64_t), counts->dfa, counts->dfa_gr64, indices->dfa_index * sizeof(uint64_t), counts->match, counts->match * sizeof(struct rte_acl_match_results), ctx->mem_sz, max_size); } static uint64_t acl_dfa_gen_idx(const struct rte_acl_node *node, uint32_t index) { uint64_t idx; uint32_t i; idx = 0; for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) { RTE_ACL_VERIFY(node->dfa_gr64[i] < RTE_ACL_DFA_GR64_NUM); RTE_ACL_VERIFY(node->dfa_gr64[i] < node->fanout); idx |= (i - node->dfa_gr64[i]) << (6 + RTE_ACL_DFA_GR64_BIT * i); } return idx << (CHAR_BIT * sizeof(index)) | index | node->node_type; } static void acl_dfa_fill_gr64(const struct rte_acl_node *node, const uint64_t src[RTE_ACL_DFA_SIZE], uint64_t dst[RTE_ACL_DFA_SIZE]) { uint32_t i; for (i = 0; i != RTE_DIM(node->dfa_gr64); i++) { memcpy(dst + node->dfa_gr64[i] * RTE_ACL_DFA_GR64_SIZE, src + i * RTE_ACL_DFA_GR64_SIZE, RTE_ACL_DFA_GR64_SIZE * sizeof(dst[0])); } } static uint32_t acl_dfa_count_gr64(const uint64_t array_ptr[RTE_ACL_DFA_SIZE], uint8_t gr64[RTE_ACL_DFA_GR64_NUM]) { uint32_t i, j, k; k = 0; for (i = 0; i != RTE_ACL_DFA_GR64_NUM; i++) { gr64[i] = i; for (j = 0; j != i; j++) { if (memcmp(array_ptr + i * RTE_ACL_DFA_GR64_SIZE, array_ptr + j * RTE_ACL_DFA_GR64_SIZE, RTE_ACL_DFA_GR64_SIZE * sizeof(array_ptr[0])) == 0) break; } gr64[i] = (j != i) ? gr64[j] : k++; } return k; } static uint32_t acl_node_fill_dfa(const struct rte_acl_node *node, uint64_t dfa[RTE_ACL_DFA_SIZE], uint64_t no_match, int32_t resolved) { uint32_t n, x; uint32_t ranges, last_bit; struct rte_acl_node *child; struct rte_acl_bitset *bits; ranges = 0; last_bit = 0; for (n = 0; n < RTE_ACL_DFA_SIZE; n++) dfa[n] = no_match; for (x = 0; x < node->num_ptrs; x++) { child = node->ptrs[x].ptr; if (child == NULL) continue; bits = &node->ptrs[x].values; for (n = 0; n < RTE_ACL_DFA_SIZE; n++) { if (bits->bits[n / (sizeof(bits_t) * CHAR_BIT)] & (1 << (n % (sizeof(bits_t) * CHAR_BIT)))) { dfa[n] = resolved ? child->node_index : x; ranges += (last_bit == 0); last_bit = 1; } else { last_bit = 0; } } } return ranges; } /* * Counts the number of groups of sequential bits that are * either 0 or 1, as specified by the zero_one parameter. This is used to * calculate the number of ranges in a node to see if it fits in a quad range * node. */ static int acl_count_sequential_groups(struct rte_acl_bitset *bits, int zero_one) { int n, ranges, last_bit; ranges = 0; last_bit = zero_one ^ 1; for (n = QRANGE_MIN; n < UINT8_MAX + 1; n++) { if (bits->bits[n / (sizeof(bits_t) * 8)] & (1 << (n % (sizeof(bits_t) * 8)))) { if (zero_one == 1 && last_bit != 1) ranges++; last_bit = 1; } else { if (zero_one == 0 && last_bit != 0) ranges++; last_bit = 0; } } for (n = 0; n < QRANGE_MIN; n++) { if (bits->bits[n / (sizeof(bits_t) * 8)] & (1 << (n % (sizeof(bits_t) * 8)))) { if (zero_one == 1 && last_bit != 1) ranges++; last_bit = 1; } else { if (zero_one == 0 && last_bit != 0) ranges++; last_bit = 0; } } return ranges; } /* * Count number of ranges spanned by the node's pointers */ static int acl_count_fanout(struct rte_acl_node *node) { uint32_t n; int ranges; if (node->fanout != 0) return node->fanout; ranges = acl_count_sequential_groups(&node->values, 0); for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) ranges += acl_count_sequential_groups( &node->ptrs[n].values, 1); } node->fanout = ranges; return node->fanout; } /* * Determine the type of nodes and count each type */ static void acl_count_trie_types(struct acl_node_counters *counts, struct rte_acl_node *node, uint64_t no_match, int force_dfa) { uint32_t n; int num_ptrs; uint64_t dfa[RTE_ACL_DFA_SIZE]; /* skip if this node has been counted */ if (node->node_type != (uint32_t)RTE_ACL_NODE_UNDEFINED) return; if (node->match_flag != 0 || node->num_ptrs == 0) { counts->match++; node->node_type = RTE_ACL_NODE_MATCH; return; } num_ptrs = acl_count_fanout(node); /* Force type to dfa */ if (force_dfa) num_ptrs = RTE_ACL_DFA_SIZE; /* determine node type based on number of ranges */ if (num_ptrs == 1) { counts->single++; node->node_type = RTE_ACL_NODE_SINGLE; } else if (num_ptrs <= RTE_ACL_QUAD_MAX) { counts->quad++; counts->quad_vectors += node->fanout; node->node_type = RTE_ACL_NODE_QRANGE; } else { counts->dfa++; node->node_type = RTE_ACL_NODE_DFA; if (force_dfa != 0) { /* always expand to a max number of nodes. */ for (n = 0; n != RTE_DIM(node->dfa_gr64); n++) node->dfa_gr64[n] = n; node->fanout = n; } else { acl_node_fill_dfa(node, dfa, no_match, 0); node->fanout = acl_dfa_count_gr64(dfa, node->dfa_gr64); } counts->dfa_gr64 += node->fanout; } /* * recursively count the types of all children */ for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) acl_count_trie_types(counts, node->ptrs[n].ptr, no_match, 0); } } static void acl_add_ptrs(struct rte_acl_node *node, uint64_t *node_array, uint64_t no_match, int resolved) { uint32_t x; int32_t m; uint64_t *node_a, index, dfa[RTE_ACL_DFA_SIZE]; acl_node_fill_dfa(node, dfa, no_match, resolved); /* * Rather than going from 0 to 256, the range count and * the layout are from 80-ff then 0-7f due to signed compare * for SSE (cmpgt). */ if (node->node_type == RTE_ACL_NODE_QRANGE) { m = 0; node_a = node_array; index = dfa[QRANGE_MIN]; *node_a++ = index; for (x = QRANGE_MIN + 1; x < UINT8_MAX + 1; x++) { if (dfa[x] != index) { index = dfa[x]; *node_a++ = index; node->transitions[m++] = (uint8_t)(x - 1); } } for (x = 0; x < INT8_MAX + 1; x++) { if (dfa[x] != index) { index = dfa[x]; *node_a++ = index; node->transitions[m++] = (uint8_t)(x - 1); } } /* fill unused locations with max value - nothing is greater */ for (; m < RTE_ACL_QUAD_SIZE; m++) node->transitions[m] = INT8_MAX; RTE_ACL_VERIFY(m <= RTE_ACL_QUAD_SIZE); } else if (node->node_type == RTE_ACL_NODE_DFA && resolved) { acl_dfa_fill_gr64(node, dfa, node_array); } } /* * Routine that allocates space for this node and recursively calls * to allocate space for each child. Once all the children are allocated, * then resolve all transitions for this node. */ static void acl_gen_node(struct rte_acl_node *node, uint64_t *node_array, uint64_t no_match, struct rte_acl_indices *index, int num_categories) { uint32_t n, sz, *qtrp; uint64_t *array_ptr; struct rte_acl_match_results *match; if (node->node_index != RTE_ACL_NODE_UNDEFINED) return; array_ptr = NULL; switch (node->node_type) { case RTE_ACL_NODE_DFA: array_ptr = &node_array[index->dfa_index]; node->node_index = acl_dfa_gen_idx(node, index->dfa_index); sz = node->fanout * RTE_ACL_DFA_GR64_SIZE; index->dfa_index += sz; for (n = 0; n < sz; n++) array_ptr[n] = no_match; break; case RTE_ACL_NODE_SINGLE: node->node_index = RTE_ACL_QUAD_SINGLE | index->single_index | node->node_type; array_ptr = &node_array[index->single_index]; index->single_index += 1; array_ptr[0] = no_match; break; case RTE_ACL_NODE_QRANGE: array_ptr = &node_array[index->quad_index]; acl_add_ptrs(node, array_ptr, no_match, 0); qtrp = (uint32_t *)node->transitions; node->node_index = qtrp[0]; node->node_index <<= sizeof(index->quad_index) * CHAR_BIT; node->node_index |= index->quad_index | node->node_type; index->quad_index += node->fanout; break; case RTE_ACL_NODE_MATCH: match = ((struct rte_acl_match_results *) (node_array + index->match_start)); for (n = 0; n != RTE_DIM(match->results); n++) RTE_ACL_VERIFY(match->results[0] == 0); memcpy(match + index->match_index, node->mrt, sizeof(*node->mrt)); node->node_index = index->match_index | node->node_type; index->match_index += 1; break; case RTE_ACL_NODE_UNDEFINED: RTE_ACL_VERIFY(node->node_type != (uint32_t)RTE_ACL_NODE_UNDEFINED); break; } /* recursively allocate space for all children */ for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) acl_gen_node(node->ptrs[n].ptr, node_array, no_match, index, num_categories); } /* All children are resolved, resolve this node's pointers */ switch (node->node_type) { case RTE_ACL_NODE_DFA: acl_add_ptrs(node, array_ptr, no_match, 1); break; case RTE_ACL_NODE_SINGLE: for (n = 0; n < node->num_ptrs; n++) { if (node->ptrs[n].ptr != NULL) array_ptr[0] = node->ptrs[n].ptr->node_index; } break; case RTE_ACL_NODE_QRANGE: acl_add_ptrs(node, array_ptr, no_match, 1); break; case RTE_ACL_NODE_MATCH: break; case RTE_ACL_NODE_UNDEFINED: RTE_ACL_VERIFY(node->node_type != (uint32_t)RTE_ACL_NODE_UNDEFINED); break; } } static void acl_calc_counts_indices(struct acl_node_counters *counts, struct rte_acl_indices *indices, struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries, uint64_t no_match) { uint32_t n; memset(indices, 0, sizeof(*indices)); memset(counts, 0, sizeof(*counts)); /* Get stats on nodes */ for (n = 0; n < num_tries; n++) { acl_count_trie_types(counts, node_bld_trie[n].trie, no_match, 1); } indices->dfa_index = RTE_ACL_DFA_SIZE + 1; indices->quad_index = indices->dfa_index + counts->dfa_gr64 * RTE_ACL_DFA_GR64_SIZE; indices->single_index = indices->quad_index + counts->quad_vectors; indices->match_start = indices->single_index + counts->single + 1; indices->match_start = RTE_ALIGN(indices->match_start, (XMM_SIZE / sizeof(uint64_t))); indices->match_index = 1; } /* * Generate the runtime structure using build structure */ int rte_acl_gen(struct rte_acl_ctx *ctx, struct rte_acl_trie *trie, struct rte_acl_bld_trie *node_bld_trie, uint32_t num_tries, uint32_t num_categories, uint32_t data_index_sz, size_t max_size) { void *mem; size_t total_size; uint64_t *node_array, no_match; uint32_t n, match_index; struct rte_acl_match_results *match; struct acl_node_counters counts; struct rte_acl_indices indices; no_match = RTE_ACL_NODE_MATCH; /* Fill counts and indices arrays from the nodes. */ acl_calc_counts_indices(&counts, &indices, node_bld_trie, num_tries, no_match); /* Allocate runtime memory (align to cache boundary) */ total_size = RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE) + indices.match_start * sizeof(uint64_t) + (counts.match + 1) * sizeof(struct rte_acl_match_results) + XMM_SIZE; if (total_size > max_size) { RTE_LOG(DEBUG, ACL, "Gen phase for ACL ctx \"%s\" exceeds max_size limit, " "bytes required: %zu, allowed: %zu\n", ctx->name, total_size, max_size); return -ERANGE; } mem = rte_zmalloc_socket(ctx->name, total_size, RTE_CACHE_LINE_SIZE, ctx->socket_id); if (mem == NULL) { RTE_LOG(ERR, ACL, "allocation of %zu bytes on socket %d for %s failed\n", total_size, ctx->socket_id, ctx->name); return -ENOMEM; } /* Fill the runtime structure */ match_index = indices.match_start; node_array = (uint64_t *)((uintptr_t)mem + RTE_ALIGN(data_index_sz, RTE_CACHE_LINE_SIZE)); /* * Setup the NOMATCH node (a SINGLE at the * highest index, that points to itself) */ node_array[RTE_ACL_DFA_SIZE] = RTE_ACL_DFA_SIZE | RTE_ACL_NODE_SINGLE; for (n = 0; n < RTE_ACL_DFA_SIZE; n++) node_array[n] = no_match; /* NOMATCH result at index 0 */ match = ((struct rte_acl_match_results *)(node_array + match_index)); memset(match, 0, sizeof(*match)); for (n = 0; n < num_tries; n++) { acl_gen_node(node_bld_trie[n].trie, node_array, no_match, &indices, num_categories); if (node_bld_trie[n].trie->node_index == no_match) trie[n].root_index = 0; else trie[n].root_index = node_bld_trie[n].trie->node_index; } ctx->mem = mem; ctx->mem_sz = total_size; ctx->data_indexes = mem; ctx->num_tries = num_tries; ctx->num_categories = num_categories; ctx->match_index = match_index; ctx->no_match = no_match; ctx->idle = node_array[RTE_ACL_DFA_SIZE]; ctx->trans_table = node_array; memcpy(ctx->trie, trie, sizeof(ctx->trie)); acl_gen_log_stats(ctx, &counts, &indices, max_size); return 0; } ================================================ FILE: lib/librte_acl/acl_run.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _ACL_RUN_H_ #define _ACL_RUN_H_ #include #include "acl.h" #define MAX_SEARCHES_AVX16 16 #define MAX_SEARCHES_SSE8 8 #define MAX_SEARCHES_SSE4 4 #define MAX_SEARCHES_SCALAR 2 #define GET_NEXT_4BYTES(prm, idx) \ (*((const int32_t *)((prm)[(idx)].data + *(prm)[idx].data_index++))) #define RTE_ACL_NODE_INDEX ((uint32_t)~RTE_ACL_NODE_TYPE) #define SCALAR_QRANGE_MULT 0x01010101 #define SCALAR_QRANGE_MASK 0x7f7f7f7f #define SCALAR_QRANGE_MIN 0x80808080 /* * Structure to manage N parallel trie traversals. * The runtime trie traversal routines can process 8, 4, or 2 tries * in parallel. Each packet may require multiple trie traversals (up to 4). * This structure is used to fill the slots (0 to n-1) for parallel processing * with the trie traversals needed for each packet. */ struct acl_flow_data { uint32_t num_packets; /* number of packets processed */ uint32_t started; /* number of trie traversals in progress */ uint32_t trie; /* current trie index (0 to N-1) */ uint32_t cmplt_size; uint32_t total_packets; uint32_t categories; /* number of result categories per packet. */ /* maximum number of packets to process */ const uint64_t *trans; const uint8_t **data; uint32_t *results; struct completion *last_cmplt; struct completion *cmplt_array; }; /* * Structure to maintain running results for * a single packet (up to 4 tries). */ struct completion { uint32_t *results; /* running results. */ int32_t priority[RTE_ACL_MAX_CATEGORIES]; /* running priorities. */ uint32_t count; /* num of remaining tries */ /* true for allocated struct */ } __attribute__((aligned(XMM_SIZE))); /* * One parms structure for each slot in the search engine. */ struct parms { const uint8_t *data; /* input data for this packet */ const uint32_t *data_index; /* data indirection for this trie */ struct completion *cmplt; /* completion data for this packet */ }; /* * Define an global idle node for unused engine slots */ static const uint32_t idle[UINT8_MAX + 1]; /* * Allocate a completion structure to manage the tries for a packet. */ static inline struct completion * alloc_completion(struct completion *p, uint32_t size, uint32_t tries, uint32_t *results) { uint32_t n; for (n = 0; n < size; n++) { if (p[n].count == 0) { /* mark as allocated and set number of tries. */ p[n].count = tries; p[n].results = results; return &(p[n]); } } /* should never get here */ return NULL; } /* * Resolve priority for a single result trie. */ static inline void resolve_single_priority(uint64_t transition, int n, const struct rte_acl_ctx *ctx, struct parms *parms, const struct rte_acl_match_results *p) { if (parms[n].cmplt->count == ctx->num_tries || parms[n].cmplt->priority[0] <= p[transition].priority[0]) { parms[n].cmplt->priority[0] = p[transition].priority[0]; parms[n].cmplt->results[0] = p[transition].results[0]; } } /* * Routine to fill a slot in the parallel trie traversal array (parms) from * the list of packets (flows). */ static inline uint64_t acl_start_next_trie(struct acl_flow_data *flows, struct parms *parms, int n, const struct rte_acl_ctx *ctx) { uint64_t transition; /* if there are any more packets to process */ if (flows->num_packets < flows->total_packets) { parms[n].data = flows->data[flows->num_packets]; parms[n].data_index = ctx->trie[flows->trie].data_index; /* if this is the first trie for this packet */ if (flows->trie == 0) { flows->last_cmplt = alloc_completion(flows->cmplt_array, flows->cmplt_size, ctx->num_tries, flows->results + flows->num_packets * flows->categories); } /* set completion parameters and starting index for this slot */ parms[n].cmplt = flows->last_cmplt; transition = flows->trans[parms[n].data[*parms[n].data_index++] + ctx->trie[flows->trie].root_index]; /* * if this is the last trie for this packet, * then setup next packet. */ flows->trie++; if (flows->trie >= ctx->num_tries) { flows->trie = 0; flows->num_packets++; } /* keep track of number of active trie traversals */ flows->started++; /* no more tries to process, set slot to an idle position */ } else { transition = ctx->idle; parms[n].data = (const uint8_t *)idle; parms[n].data_index = idle; } return transition; } static inline void acl_set_flow(struct acl_flow_data *flows, struct completion *cmplt, uint32_t cmplt_size, const uint8_t **data, uint32_t *results, uint32_t data_num, uint32_t categories, const uint64_t *trans) { flows->num_packets = 0; flows->started = 0; flows->trie = 0; flows->last_cmplt = NULL; flows->cmplt_array = cmplt; flows->total_packets = data_num; flows->categories = categories; flows->cmplt_size = cmplt_size; flows->data = data; flows->results = results; flows->trans = trans; } typedef void (*resolve_priority_t) (uint64_t transition, int n, const struct rte_acl_ctx *ctx, struct parms *parms, const struct rte_acl_match_results *p, uint32_t categories); /* * Detect matches. If a match node transition is found, then this trie * traversal is complete and fill the slot with the next trie * to be processed. */ static inline uint64_t acl_match_check(uint64_t transition, int slot, const struct rte_acl_ctx *ctx, struct parms *parms, struct acl_flow_data *flows, resolve_priority_t resolve_priority) { const struct rte_acl_match_results *p; p = (const struct rte_acl_match_results *) (flows->trans + ctx->match_index); if (transition & RTE_ACL_NODE_MATCH) { /* Remove flags from index and decrement active traversals */ transition &= RTE_ACL_NODE_INDEX; flows->started--; /* Resolve priorities for this trie and running results */ if (flows->categories == 1) resolve_single_priority(transition, slot, ctx, parms, p); else resolve_priority(transition, slot, ctx, parms, p, flows->categories); /* Count down completed tries for this search request */ parms[slot].cmplt->count--; /* Fill the slot with the next trie or idle trie */ transition = acl_start_next_trie(flows, parms, slot, ctx); } return transition; } #endif /* _ACL_RUN_H_ */ ================================================ FILE: lib/librte_acl/acl_run_avx2.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "acl_run_avx2.h" /* * Note, that to be able to use AVX2 classify method, * both compiler and target cpu have to support AVX2 instructions. */ int rte_acl_classify_avx2(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories) { if (likely(num >= MAX_SEARCHES_AVX16)) return search_avx2x16(ctx, data, results, num, categories); else if (num >= MAX_SEARCHES_SSE8) return search_sse_8(ctx, data, results, num, categories); else if (num >= MAX_SEARCHES_SSE4) return search_sse_4(ctx, data, results, num, categories); else return rte_acl_classify_scalar(ctx, data, results, num, categories); } ================================================ FILE: lib/librte_acl/acl_run_avx2.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "acl_run_sse.h" static const rte_ymm_t ymm_match_mask = { .u32 = { RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, }, }; static const rte_ymm_t ymm_index_mask = { .u32 = { RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, }, }; static const rte_ymm_t ymm_shuffle_input = { .u32 = { 0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c, 0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c, }, }; static const rte_ymm_t ymm_ones_16 = { .u16 = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, }; static const rte_ymm_t ymm_range_base = { .u32 = { 0xffffff00, 0xffffff04, 0xffffff08, 0xffffff0c, 0xffffff00, 0xffffff04, 0xffffff08, 0xffffff0c, }, }; /* * Process 8 transitions in parallel. * tr_lo contains low 32 bits for 8 transition. * tr_hi contains high 32 bits for 8 transition. * next_input contains up to 4 input bytes for 8 flows. */ static inline __attribute__((always_inline)) ymm_t transition8(ymm_t next_input, const uint64_t *trans, ymm_t *tr_lo, ymm_t *tr_hi) { const int32_t *tr; ymm_t addr; tr = (const int32_t *)(uintptr_t)trans; /* Calculate the address (array index) for all 8 transitions. */ ACL_TR_CALC_ADDR(mm256, 256, addr, ymm_index_mask.y, next_input, ymm_shuffle_input.y, ymm_ones_16.y, ymm_range_base.y, *tr_lo, *tr_hi); /* load lower 32 bits of 8 transactions at once. */ *tr_lo = _mm256_i32gather_epi32(tr, addr, sizeof(trans[0])); next_input = _mm256_srli_epi32(next_input, CHAR_BIT); /* load high 32 bits of 8 transactions at once. */ *tr_hi = _mm256_i32gather_epi32(tr + 1, addr, sizeof(trans[0])); return next_input; } /* * Process matches for 8 flows. * tr_lo contains low 32 bits for 8 transition. * tr_hi contains high 32 bits for 8 transition. */ static inline void acl_process_matches_avx2x8(const struct rte_acl_ctx *ctx, struct parms *parms, struct acl_flow_data *flows, uint32_t slot, ymm_t matches, ymm_t *tr_lo, ymm_t *tr_hi) { ymm_t t0, t1; ymm_t lo, hi; xmm_t l0, l1; uint32_t i; uint64_t tr[MAX_SEARCHES_SSE8]; l1 = _mm256_extracti128_si256(*tr_lo, 1); l0 = _mm256_castsi256_si128(*tr_lo); for (i = 0; i != RTE_DIM(tr) / 2; i++) { /* * Extract low 32bits of each transition. * That's enough to process the match. */ tr[i] = (uint32_t)_mm_cvtsi128_si32(l0); tr[i + 4] = (uint32_t)_mm_cvtsi128_si32(l1); l0 = _mm_srli_si128(l0, sizeof(uint32_t)); l1 = _mm_srli_si128(l1, sizeof(uint32_t)); tr[i] = acl_match_check(tr[i], slot + i, ctx, parms, flows, resolve_priority_sse); tr[i + 4] = acl_match_check(tr[i + 4], slot + i + 4, ctx, parms, flows, resolve_priority_sse); } /* Collect new transitions into 2 YMM registers. */ t0 = _mm256_set_epi64x(tr[5], tr[4], tr[1], tr[0]); t1 = _mm256_set_epi64x(tr[7], tr[6], tr[3], tr[2]); /* For each transition: put low 32 into tr_lo and high 32 into tr_hi */ ACL_TR_HILO(mm256, __m256, t0, t1, lo, hi); /* Keep transitions wth NOMATCH intact. */ *tr_lo = _mm256_blendv_epi8(*tr_lo, lo, matches); *tr_hi = _mm256_blendv_epi8(*tr_hi, hi, matches); } static inline void acl_match_check_avx2x8(const struct rte_acl_ctx *ctx, struct parms *parms, struct acl_flow_data *flows, uint32_t slot, ymm_t *tr_lo, ymm_t *tr_hi, ymm_t match_mask) { uint32_t msk; ymm_t matches, temp; /* test for match node */ temp = _mm256_and_si256(match_mask, *tr_lo); matches = _mm256_cmpeq_epi32(temp, match_mask); msk = _mm256_movemask_epi8(matches); while (msk != 0) { acl_process_matches_avx2x8(ctx, parms, flows, slot, matches, tr_lo, tr_hi); temp = _mm256_and_si256(match_mask, *tr_lo); matches = _mm256_cmpeq_epi32(temp, match_mask); msk = _mm256_movemask_epi8(matches); } } /* * Execute trie traversal for up to 16 flows in parallel. */ static inline int search_avx2x16(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t total_packets, uint32_t categories) { uint32_t n; struct acl_flow_data flows; uint64_t index_array[MAX_SEARCHES_AVX16]; struct completion cmplt[MAX_SEARCHES_AVX16]; struct parms parms[MAX_SEARCHES_AVX16]; ymm_t input[2], tr_lo[2], tr_hi[2]; ymm_t t0, t1; acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, total_packets, categories, ctx->trans_table); for (n = 0; n < RTE_DIM(cmplt); n++) { cmplt[n].count = 0; index_array[n] = acl_start_next_trie(&flows, parms, n, ctx); } t0 = _mm256_set_epi64x(index_array[5], index_array[4], index_array[1], index_array[0]); t1 = _mm256_set_epi64x(index_array[7], index_array[6], index_array[3], index_array[2]); ACL_TR_HILO(mm256, __m256, t0, t1, tr_lo[0], tr_hi[0]); t0 = _mm256_set_epi64x(index_array[13], index_array[12], index_array[9], index_array[8]); t1 = _mm256_set_epi64x(index_array[15], index_array[14], index_array[11], index_array[10]); ACL_TR_HILO(mm256, __m256, t0, t1, tr_lo[1], tr_hi[1]); /* Check for any matches. */ acl_match_check_avx2x8(ctx, parms, &flows, 0, &tr_lo[0], &tr_hi[0], ymm_match_mask.y); acl_match_check_avx2x8(ctx, parms, &flows, 8, &tr_lo[1], &tr_hi[1], ymm_match_mask.y); while (flows.started > 0) { uint32_t in[MAX_SEARCHES_SSE8]; /* Gather 4 bytes of input data for first 8 flows. */ in[0] = GET_NEXT_4BYTES(parms, 0); in[4] = GET_NEXT_4BYTES(parms, 4); in[1] = GET_NEXT_4BYTES(parms, 1); in[5] = GET_NEXT_4BYTES(parms, 5); in[2] = GET_NEXT_4BYTES(parms, 2); in[6] = GET_NEXT_4BYTES(parms, 6); in[3] = GET_NEXT_4BYTES(parms, 3); in[7] = GET_NEXT_4BYTES(parms, 7); input[0] = _mm256_set_epi32(in[7], in[6], in[5], in[4], in[3], in[2], in[1], in[0]); /* Gather 4 bytes of input data for last 8 flows. */ in[0] = GET_NEXT_4BYTES(parms, 8); in[4] = GET_NEXT_4BYTES(parms, 12); in[1] = GET_NEXT_4BYTES(parms, 9); in[5] = GET_NEXT_4BYTES(parms, 13); in[2] = GET_NEXT_4BYTES(parms, 10); in[6] = GET_NEXT_4BYTES(parms, 14); in[3] = GET_NEXT_4BYTES(parms, 11); in[7] = GET_NEXT_4BYTES(parms, 15); input[1] = _mm256_set_epi32(in[7], in[6], in[5], in[4], in[3], in[2], in[1], in[0]); input[0] = transition8(input[0], flows.trans, &tr_lo[0], &tr_hi[0]); input[1] = transition8(input[1], flows.trans, &tr_lo[1], &tr_hi[1]); input[0] = transition8(input[0], flows.trans, &tr_lo[0], &tr_hi[0]); input[1] = transition8(input[1], flows.trans, &tr_lo[1], &tr_hi[1]); input[0] = transition8(input[0], flows.trans, &tr_lo[0], &tr_hi[0]); input[1] = transition8(input[1], flows.trans, &tr_lo[1], &tr_hi[1]); input[0] = transition8(input[0], flows.trans, &tr_lo[0], &tr_hi[0]); input[1] = transition8(input[1], flows.trans, &tr_lo[1], &tr_hi[1]); /* Check for any matches. */ acl_match_check_avx2x8(ctx, parms, &flows, 0, &tr_lo[0], &tr_hi[0], ymm_match_mask.y); acl_match_check_avx2x8(ctx, parms, &flows, 8, &tr_lo[1], &tr_hi[1], ymm_match_mask.y); } return 0; } ================================================ FILE: lib/librte_acl/acl_run_scalar.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "acl_run.h" /* * Resolve priority for multiple results (scalar version). * This consists comparing the priority of the current traversal with the * running set of results for the packet. * For each result, keep a running array of the result (rule number) and * its priority for each category. */ static inline void resolve_priority_scalar(uint64_t transition, int n, const struct rte_acl_ctx *ctx, struct parms *parms, const struct rte_acl_match_results *p, uint32_t categories) { uint32_t i; int32_t *saved_priority; uint32_t *saved_results; const int32_t *priority; const uint32_t *results; saved_results = parms[n].cmplt->results; saved_priority = parms[n].cmplt->priority; /* results and priorities for completed trie */ results = p[transition].results; priority = p[transition].priority; /* if this is not the first completed trie */ if (parms[n].cmplt->count != ctx->num_tries) { for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) { if (saved_priority[i] <= priority[i]) { saved_priority[i] = priority[i]; saved_results[i] = results[i]; } if (saved_priority[i + 1] <= priority[i + 1]) { saved_priority[i + 1] = priority[i + 1]; saved_results[i + 1] = results[i + 1]; } if (saved_priority[i + 2] <= priority[i + 2]) { saved_priority[i + 2] = priority[i + 2]; saved_results[i + 2] = results[i + 2]; } if (saved_priority[i + 3] <= priority[i + 3]) { saved_priority[i + 3] = priority[i + 3]; saved_results[i + 3] = results[i + 3]; } } } else { for (i = 0; i < categories; i += RTE_ACL_RESULTS_MULTIPLIER) { saved_priority[i] = priority[i]; saved_priority[i + 1] = priority[i + 1]; saved_priority[i + 2] = priority[i + 2]; saved_priority[i + 3] = priority[i + 3]; saved_results[i] = results[i]; saved_results[i + 1] = results[i + 1]; saved_results[i + 2] = results[i + 2]; saved_results[i + 3] = results[i + 3]; } } } static inline uint32_t scan_forward(uint32_t input, uint32_t max) { return (input == 0) ? max : rte_bsf32(input); } static inline uint64_t scalar_transition(const uint64_t *trans_table, uint64_t transition, uint8_t input) { uint32_t addr, index, ranges, x, a, b, c; /* break transition into component parts */ ranges = transition >> (sizeof(index) * CHAR_BIT); index = transition & ~RTE_ACL_NODE_INDEX; addr = transition ^ index; if (index != RTE_ACL_NODE_DFA) { /* calc address for a QRANGE/SINGLE node */ c = (uint32_t)input * SCALAR_QRANGE_MULT; a = ranges | SCALAR_QRANGE_MIN; a -= (c & SCALAR_QRANGE_MASK); b = c & SCALAR_QRANGE_MIN; a &= SCALAR_QRANGE_MIN; a ^= (ranges ^ b) & (a ^ b); x = scan_forward(a, 32) >> 3; } else { /* calc address for a DFA node */ x = ranges >> (input / RTE_ACL_DFA_GR64_SIZE * RTE_ACL_DFA_GR64_BIT); x &= UINT8_MAX; x = input - x; } addr += x; /* pickup next transition */ transition = *(trans_table + addr); return transition; } int rte_acl_classify_scalar(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories) { int n; uint64_t transition0, transition1; uint32_t input0, input1; struct acl_flow_data flows; uint64_t index_array[MAX_SEARCHES_SCALAR]; struct completion cmplt[MAX_SEARCHES_SCALAR]; struct parms parms[MAX_SEARCHES_SCALAR]; acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, num, categories, ctx->trans_table); for (n = 0; n < MAX_SEARCHES_SCALAR; n++) { cmplt[n].count = 0; index_array[n] = acl_start_next_trie(&flows, parms, n, ctx); } transition0 = index_array[0]; transition1 = index_array[1]; while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) { transition0 = acl_match_check(transition0, 0, ctx, parms, &flows, resolve_priority_scalar); transition1 = acl_match_check(transition1, 1, ctx, parms, &flows, resolve_priority_scalar); } while (flows.started > 0) { input0 = GET_NEXT_4BYTES(parms, 0); input1 = GET_NEXT_4BYTES(parms, 1); for (n = 0; n < 4; n++) { transition0 = scalar_transition(flows.trans, transition0, (uint8_t)input0); input0 >>= CHAR_BIT; transition1 = scalar_transition(flows.trans, transition1, (uint8_t)input1); input1 >>= CHAR_BIT; } while ((transition0 | transition1) & RTE_ACL_NODE_MATCH) { transition0 = acl_match_check(transition0, 0, ctx, parms, &flows, resolve_priority_scalar); transition1 = acl_match_check(transition1, 1, ctx, parms, &flows, resolve_priority_scalar); } } return 0; } ================================================ FILE: lib/librte_acl/acl_run_sse.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "acl_run_sse.h" int rte_acl_classify_sse(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories) { if (likely(num >= MAX_SEARCHES_SSE8)) return search_sse_8(ctx, data, results, num, categories); else if (num >= MAX_SEARCHES_SSE4) return search_sse_4(ctx, data, results, num, categories); else return rte_acl_classify_scalar(ctx, data, results, num, categories); } ================================================ FILE: lib/librte_acl/acl_run_sse.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "acl_run.h" #include "acl_vect.h" enum { SHUFFLE32_SLOT1 = 0xe5, SHUFFLE32_SLOT2 = 0xe6, SHUFFLE32_SLOT3 = 0xe7, SHUFFLE32_SWAP64 = 0x4e, }; static const rte_xmm_t xmm_shuffle_input = { .u32 = {0x00000000, 0x04040404, 0x08080808, 0x0c0c0c0c}, }; static const rte_xmm_t xmm_ones_16 = { .u16 = {1, 1, 1, 1, 1, 1, 1, 1}, }; static const rte_xmm_t xmm_match_mask = { .u32 = { RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, RTE_ACL_NODE_MATCH, }, }; static const rte_xmm_t xmm_index_mask = { .u32 = { RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, RTE_ACL_NODE_INDEX, }, }; static const rte_xmm_t xmm_range_base = { .u32 = { 0xffffff00, 0xffffff04, 0xffffff08, 0xffffff0c, }, }; /* * Resolve priority for multiple results (sse version). * This consists comparing the priority of the current traversal with the * running set of results for the packet. * For each result, keep a running array of the result (rule number) and * its priority for each category. */ static inline void resolve_priority_sse(uint64_t transition, int n, const struct rte_acl_ctx *ctx, struct parms *parms, const struct rte_acl_match_results *p, uint32_t categories) { uint32_t x; xmm_t results, priority, results1, priority1, selector; xmm_t *saved_results, *saved_priority; for (x = 0; x < categories; x += RTE_ACL_RESULTS_MULTIPLIER) { saved_results = (xmm_t *)(&parms[n].cmplt->results[x]); saved_priority = (xmm_t *)(&parms[n].cmplt->priority[x]); /* get results and priorities for completed trie */ results = _mm_loadu_si128( (const xmm_t *)&p[transition].results[x]); priority = _mm_loadu_si128( (const xmm_t *)&p[transition].priority[x]); /* if this is not the first completed trie */ if (parms[n].cmplt->count != ctx->num_tries) { /* get running best results and their priorities */ results1 = _mm_loadu_si128(saved_results); priority1 = _mm_loadu_si128(saved_priority); /* select results that are highest priority */ selector = _mm_cmpgt_epi32(priority1, priority); results = _mm_blendv_epi8(results, results1, selector); priority = _mm_blendv_epi8(priority, priority1, selector); } /* save running best results and their priorities */ _mm_storeu_si128(saved_results, results); _mm_storeu_si128(saved_priority, priority); } } /* * Extract transitions from an XMM register and check for any matches */ static void acl_process_matches(xmm_t *indices, int slot, const struct rte_acl_ctx *ctx, struct parms *parms, struct acl_flow_data *flows) { uint64_t transition1, transition2; /* extract transition from low 64 bits. */ transition1 = _mm_cvtsi128_si64(*indices); /* extract transition from high 64 bits. */ *indices = _mm_shuffle_epi32(*indices, SHUFFLE32_SWAP64); transition2 = _mm_cvtsi128_si64(*indices); transition1 = acl_match_check(transition1, slot, ctx, parms, flows, resolve_priority_sse); transition2 = acl_match_check(transition2, slot + 1, ctx, parms, flows, resolve_priority_sse); /* update indices with new transitions. */ *indices = _mm_set_epi64x(transition2, transition1); } /* * Check for any match in 4 transitions (contained in 2 SSE registers) */ static inline __attribute__((always_inline)) void acl_match_check_x4(int slot, const struct rte_acl_ctx *ctx, struct parms *parms, struct acl_flow_data *flows, xmm_t *indices1, xmm_t *indices2, xmm_t match_mask) { xmm_t temp; /* put low 32 bits of each transition into one register */ temp = (xmm_t)_mm_shuffle_ps((__m128)*indices1, (__m128)*indices2, 0x88); /* test for match node */ temp = _mm_and_si128(match_mask, temp); while (!_mm_testz_si128(temp, temp)) { acl_process_matches(indices1, slot, ctx, parms, flows); acl_process_matches(indices2, slot + 2, ctx, parms, flows); temp = (xmm_t)_mm_shuffle_ps((__m128)*indices1, (__m128)*indices2, 0x88); temp = _mm_and_si128(match_mask, temp); } } /* * Process 4 transitions (in 2 XMM registers) in parallel */ static inline __attribute__((always_inline)) xmm_t transition4(xmm_t next_input, const uint64_t *trans, xmm_t *indices1, xmm_t *indices2) { xmm_t addr, tr_lo, tr_hi; uint64_t trans0, trans2; /* Shuffle low 32 into tr_lo and high 32 into tr_hi */ ACL_TR_HILO(mm, __m128, *indices1, *indices2, tr_lo, tr_hi); /* Calculate the address (array index) for all 4 transitions. */ ACL_TR_CALC_ADDR(mm, 128, addr, xmm_index_mask.x, next_input, xmm_shuffle_input.x, xmm_ones_16.x, xmm_range_base.x, tr_lo, tr_hi); /* Gather 64 bit transitions and pack back into 2 registers. */ trans0 = trans[_mm_cvtsi128_si32(addr)]; /* get slot 2 */ /* {x0, x1, x2, x3} -> {x2, x1, x2, x3} */ addr = _mm_shuffle_epi32(addr, SHUFFLE32_SLOT2); trans2 = trans[_mm_cvtsi128_si32(addr)]; /* get slot 1 */ /* {x2, x1, x2, x3} -> {x1, x1, x2, x3} */ addr = _mm_shuffle_epi32(addr, SHUFFLE32_SLOT1); *indices1 = _mm_set_epi64x(trans[_mm_cvtsi128_si32(addr)], trans0); /* get slot 3 */ /* {x1, x1, x2, x3} -> {x3, x1, x2, x3} */ addr = _mm_shuffle_epi32(addr, SHUFFLE32_SLOT3); *indices2 = _mm_set_epi64x(trans[_mm_cvtsi128_si32(addr)], trans2); return _mm_srli_epi32(next_input, CHAR_BIT); } /* * Execute trie traversal with 8 traversals in parallel */ static inline int search_sse_8(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t total_packets, uint32_t categories) { int n; struct acl_flow_data flows; uint64_t index_array[MAX_SEARCHES_SSE8]; struct completion cmplt[MAX_SEARCHES_SSE8]; struct parms parms[MAX_SEARCHES_SSE8]; xmm_t input0, input1; xmm_t indices1, indices2, indices3, indices4; acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, total_packets, categories, ctx->trans_table); for (n = 0; n < MAX_SEARCHES_SSE8; n++) { cmplt[n].count = 0; index_array[n] = acl_start_next_trie(&flows, parms, n, ctx); } /* * indices1 contains index_array[0,1] * indices2 contains index_array[2,3] * indices3 contains index_array[4,5] * indices4 contains index_array[6,7] */ indices1 = _mm_loadu_si128((xmm_t *) &index_array[0]); indices2 = _mm_loadu_si128((xmm_t *) &index_array[2]); indices3 = _mm_loadu_si128((xmm_t *) &index_array[4]); indices4 = _mm_loadu_si128((xmm_t *) &index_array[6]); /* Check for any matches. */ acl_match_check_x4(0, ctx, parms, &flows, &indices1, &indices2, xmm_match_mask.x); acl_match_check_x4(4, ctx, parms, &flows, &indices3, &indices4, xmm_match_mask.x); while (flows.started > 0) { /* Gather 4 bytes of input data for each stream. */ input0 = _mm_cvtsi32_si128(GET_NEXT_4BYTES(parms, 0)); input1 = _mm_cvtsi32_si128(GET_NEXT_4BYTES(parms, 4)); input0 = _mm_insert_epi32(input0, GET_NEXT_4BYTES(parms, 1), 1); input1 = _mm_insert_epi32(input1, GET_NEXT_4BYTES(parms, 5), 1); input0 = _mm_insert_epi32(input0, GET_NEXT_4BYTES(parms, 2), 2); input1 = _mm_insert_epi32(input1, GET_NEXT_4BYTES(parms, 6), 2); input0 = _mm_insert_epi32(input0, GET_NEXT_4BYTES(parms, 3), 3); input1 = _mm_insert_epi32(input1, GET_NEXT_4BYTES(parms, 7), 3); /* Process the 4 bytes of input on each stream. */ input0 = transition4(input0, flows.trans, &indices1, &indices2); input1 = transition4(input1, flows.trans, &indices3, &indices4); input0 = transition4(input0, flows.trans, &indices1, &indices2); input1 = transition4(input1, flows.trans, &indices3, &indices4); input0 = transition4(input0, flows.trans, &indices1, &indices2); input1 = transition4(input1, flows.trans, &indices3, &indices4); input0 = transition4(input0, flows.trans, &indices1, &indices2); input1 = transition4(input1, flows.trans, &indices3, &indices4); /* Check for any matches. */ acl_match_check_x4(0, ctx, parms, &flows, &indices1, &indices2, xmm_match_mask.x); acl_match_check_x4(4, ctx, parms, &flows, &indices3, &indices4, xmm_match_mask.x); } return 0; } /* * Execute trie traversal with 4 traversals in parallel */ static inline int search_sse_4(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, int total_packets, uint32_t categories) { int n; struct acl_flow_data flows; uint64_t index_array[MAX_SEARCHES_SSE4]; struct completion cmplt[MAX_SEARCHES_SSE4]; struct parms parms[MAX_SEARCHES_SSE4]; xmm_t input, indices1, indices2; acl_set_flow(&flows, cmplt, RTE_DIM(cmplt), data, results, total_packets, categories, ctx->trans_table); for (n = 0; n < MAX_SEARCHES_SSE4; n++) { cmplt[n].count = 0; index_array[n] = acl_start_next_trie(&flows, parms, n, ctx); } indices1 = _mm_loadu_si128((xmm_t *) &index_array[0]); indices2 = _mm_loadu_si128((xmm_t *) &index_array[2]); /* Check for any matches. */ acl_match_check_x4(0, ctx, parms, &flows, &indices1, &indices2, xmm_match_mask.x); while (flows.started > 0) { /* Gather 4 bytes of input data for each stream. */ input = _mm_cvtsi32_si128(GET_NEXT_4BYTES(parms, 0)); input = _mm_insert_epi32(input, GET_NEXT_4BYTES(parms, 1), 1); input = _mm_insert_epi32(input, GET_NEXT_4BYTES(parms, 2), 2); input = _mm_insert_epi32(input, GET_NEXT_4BYTES(parms, 3), 3); /* Process the 4 bytes of input on each stream. */ input = transition4(input, flows.trans, &indices1, &indices2); input = transition4(input, flows.trans, &indices1, &indices2); input = transition4(input, flows.trans, &indices1, &indices2); input = transition4(input, flows.trans, &indices1, &indices2); /* Check for any matches. */ acl_match_check_x4(0, ctx, parms, &flows, &indices1, &indices2, xmm_match_mask.x); } return 0; } ================================================ FILE: lib/librte_acl/acl_vect.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ACL_VECT_H_ #define _RTE_ACL_VECT_H_ /** * @file * * RTE ACL SSE/AVX related header. */ #ifdef __cplusplus extern "C" { #endif /* * Takes 2 SIMD registers containing N transitions eachi (tr0, tr1). * Shuffles it into different representation: * lo - contains low 32 bits of given N transitions. * hi - contains high 32 bits of given N transitions. */ #define ACL_TR_HILO(P, TC, tr0, tr1, lo, hi) do { \ lo = (typeof(lo))_##P##_shuffle_ps((TC)(tr0), (TC)(tr1), 0x88); \ hi = (typeof(hi))_##P##_shuffle_ps((TC)(tr0), (TC)(tr1), 0xdd); \ } while (0) /* * Calculate the address of the next transition for * all types of nodes. Note that only DFA nodes and range * nodes actually transition to another node. Match * nodes not supposed to be encountered here. * For quad range nodes: * Calculate number of range boundaries that are less than the * input value. Range boundaries for each node are in signed 8 bit, * ordered from -128 to 127. * This is effectively a popcnt of bytes that are greater than the * input byte. * Single nodes are processed in the same ways as quad range nodes. */ #define ACL_TR_CALC_ADDR(P, S, \ addr, index_mask, next_input, shuffle_input, \ ones_16, range_base, tr_lo, tr_hi) do { \ \ typeof(addr) in, node_type, r, t; \ typeof(addr) dfa_msk, dfa_ofs, quad_ofs; \ \ t = _##P##_xor_si##S(index_mask, index_mask); \ in = _##P##_shuffle_epi8(next_input, shuffle_input); \ \ /* Calc node type and node addr */ \ node_type = _##P##_andnot_si##S(index_mask, tr_lo); \ addr = _##P##_and_si##S(index_mask, tr_lo); \ \ /* mask for DFA type(0) nodes */ \ dfa_msk = _##P##_cmpeq_epi32(node_type, t); \ \ /* DFA calculations. */ \ r = _##P##_srli_epi32(in, 30); \ r = _##P##_add_epi8(r, range_base); \ t = _##P##_srli_epi32(in, 24); \ r = _##P##_shuffle_epi8(tr_hi, r); \ \ dfa_ofs = _##P##_sub_epi32(t, r); \ \ /* QUAD/SINGLE caluclations. */ \ t = _##P##_cmpgt_epi8(in, tr_hi); \ t = _##P##_sign_epi8(t, t); \ t = _##P##_maddubs_epi16(t, t); \ quad_ofs = _##P##_madd_epi16(t, ones_16); \ \ /* blend DFA and QUAD/SINGLE. */ \ t = _##P##_blendv_epi8(quad_ofs, dfa_ofs, dfa_msk); \ \ /* calculate address for next transitions. */ \ addr = _##P##_add_epi32(addr, t); \ } while (0) #ifdef __cplusplus } #endif #endif /* _RTE_ACL_VECT_H_ */ ================================================ FILE: lib/librte_acl/rte_acl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "acl.h" #define BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT) TAILQ_HEAD(rte_acl_list, rte_tailq_entry); static struct rte_tailq_elem rte_acl_tailq = { .name = "RTE_ACL", }; EAL_REGISTER_TAILQ(rte_acl_tailq) /* * If the compiler doesn't support AVX2 instructions, * then the dummy one would be used instead for AVX2 classify method. */ int __attribute__ ((weak)) rte_acl_classify_avx2(__rte_unused const struct rte_acl_ctx *ctx, __rte_unused const uint8_t **data, __rte_unused uint32_t *results, __rte_unused uint32_t num, __rte_unused uint32_t categories) { return -ENOTSUP; } static const rte_acl_classify_t classify_fns[] = { [RTE_ACL_CLASSIFY_DEFAULT] = rte_acl_classify_scalar, [RTE_ACL_CLASSIFY_SCALAR] = rte_acl_classify_scalar, [RTE_ACL_CLASSIFY_SSE] = rte_acl_classify_sse, [RTE_ACL_CLASSIFY_AVX2] = rte_acl_classify_avx2, }; /* by default, use always available scalar code path. */ static enum rte_acl_classify_alg rte_acl_default_classify = RTE_ACL_CLASSIFY_SCALAR; static void rte_acl_set_default_classify(enum rte_acl_classify_alg alg) { rte_acl_default_classify = alg; } extern int rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg) { if (ctx == NULL || (uint32_t)alg >= RTE_DIM(classify_fns)) return -EINVAL; ctx->alg = alg; return 0; } /* * Select highest available classify method as default one. * Note that CLASSIFY_AVX2 should be set as a default only * if both conditions are met: * at build time compiler supports AVX2 and target cpu supports AVX2. */ static void __attribute__((constructor)) rte_acl_init(void) { enum rte_acl_classify_alg alg = RTE_ACL_CLASSIFY_DEFAULT; #ifdef CC_AVX2_SUPPORT if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2)) alg = RTE_ACL_CLASSIFY_AVX2; else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) #else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) #endif alg = RTE_ACL_CLASSIFY_SSE; rte_acl_set_default_classify(alg); } int rte_acl_classify_alg(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories, enum rte_acl_classify_alg alg) { if (categories != 1 && ((RTE_ACL_RESULTS_MULTIPLIER - 1) & categories) != 0) return -EINVAL; return classify_fns[alg](ctx, data, results, num, categories); } int rte_acl_classify(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories) { return rte_acl_classify_alg(ctx, data, results, num, categories, ctx->alg); } struct rte_acl_ctx * rte_acl_find_existing(const char *name) { struct rte_acl_ctx *ctx = NULL; struct rte_acl_list *acl_list; struct rte_tailq_entry *te; acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, acl_list, next) { ctx = (struct rte_acl_ctx *) te->data; if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return ctx; } void rte_acl_free(struct rte_acl_ctx *ctx) { struct rte_acl_list *acl_list; struct rte_tailq_entry *te; if (ctx == NULL) return; acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find our tailq entry */ TAILQ_FOREACH(te, acl_list, next) { if (te->data == (void *) ctx) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(acl_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(ctx->mem); rte_free(ctx); rte_free(te); } struct rte_acl_ctx * rte_acl_create(const struct rte_acl_param *param) { size_t sz; struct rte_acl_ctx *ctx; struct rte_acl_list *acl_list; struct rte_tailq_entry *te; char name[sizeof(ctx->name)]; acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); /* check that input parameters are valid. */ if (param == NULL || param->name == NULL) { rte_errno = EINVAL; return NULL; } snprintf(name, sizeof(name), "ACL_%s", param->name); /* calculate amount of memory required for pattern set. */ sz = sizeof(*ctx) + param->max_rule_num * param->rule_size; /* get EAL TAILQ lock. */ rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* if we already have one with that name */ TAILQ_FOREACH(te, acl_list, next) { ctx = (struct rte_acl_ctx *) te->data; if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0) break; } /* if ACL with such name doesn't exist, then create a new one. */ if (te == NULL) { ctx = NULL; te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n"); goto exit; } ctx = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, param->socket_id); if (ctx == NULL) { RTE_LOG(ERR, ACL, "allocation of %zu bytes on socket %d for %s failed\n", sz, param->socket_id, name); rte_free(te); goto exit; } /* init new allocated context. */ ctx->rules = ctx + 1; ctx->max_rules = param->max_rule_num; ctx->rule_sz = param->rule_size; ctx->socket_id = param->socket_id; ctx->alg = rte_acl_default_classify; snprintf(ctx->name, sizeof(ctx->name), "%s", param->name); te->data = (void *) ctx; TAILQ_INSERT_TAIL(acl_list, te, next); } exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return ctx; } static int acl_add_rules(struct rte_acl_ctx *ctx, const void *rules, uint32_t num) { uint8_t *pos; if (num + ctx->num_rules > ctx->max_rules) return -ENOMEM; pos = ctx->rules; pos += ctx->rule_sz * ctx->num_rules; memcpy(pos, rules, num * ctx->rule_sz); ctx->num_rules += num; return 0; } static int acl_check_rule(const struct rte_acl_rule_data *rd) { if ((RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES, typeof(rd->category_mask)) & rd->category_mask) == 0 || rd->priority > RTE_ACL_MAX_PRIORITY || rd->priority < RTE_ACL_MIN_PRIORITY || rd->userdata == RTE_ACL_INVALID_USERDATA) return -EINVAL; return 0; } int rte_acl_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_rule *rules, uint32_t num) { const struct rte_acl_rule *rv; uint32_t i; int32_t rc; if (ctx == NULL || rules == NULL || 0 == ctx->rule_sz) return -EINVAL; for (i = 0; i != num; i++) { rv = (const struct rte_acl_rule *) ((uintptr_t)rules + i * ctx->rule_sz); rc = acl_check_rule(&rv->data); if (rc != 0) { RTE_LOG(ERR, ACL, "%s(%s): rule #%u is invalid\n", __func__, ctx->name, i + 1); return rc; } } return acl_add_rules(ctx, rules, num); } /* * Reset all rules. * Note that RT structures are not affected. */ void rte_acl_reset_rules(struct rte_acl_ctx *ctx) { if (ctx != NULL) ctx->num_rules = 0; } /* * Reset all rules and destroys RT structures. */ void rte_acl_reset(struct rte_acl_ctx *ctx) { if (ctx != NULL) { rte_acl_reset_rules(ctx); rte_acl_build(ctx, &ctx->config); } } /* * Dump ACL context to the stdout. */ void rte_acl_dump(const struct rte_acl_ctx *ctx) { if (!ctx) return; printf("acl context <%s>@%p\n", ctx->name, ctx); printf(" socket_id=%"PRId32"\n", ctx->socket_id); printf(" alg=%"PRId32"\n", ctx->alg); printf(" max_rules=%"PRIu32"\n", ctx->max_rules); printf(" rule_size=%"PRIu32"\n", ctx->rule_sz); printf(" num_rules=%"PRIu32"\n", ctx->num_rules); printf(" num_categories=%"PRIu32"\n", ctx->num_categories); printf(" num_tries=%"PRIu32"\n", ctx->num_tries); } /* * Dump all ACL contexts to the stdout. */ void rte_acl_list_dump(void) { struct rte_acl_ctx *ctx; struct rte_acl_list *acl_list; struct rte_tailq_entry *te; acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, acl_list, next) { ctx = (struct rte_acl_ctx *) te->data; rte_acl_dump(ctx); } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); } /* * Support for legacy ipv4vlan rules. */ RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS); static int acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule) { if (rule->src_port_low > rule->src_port_high || rule->dst_port_low > rule->dst_port_high || rule->src_mask_len > BIT_SIZEOF(rule->src_addr) || rule->dst_mask_len > BIT_SIZEOF(rule->dst_addr)) return -EINVAL; return acl_check_rule(&rule->data); } static void acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule *ri, struct acl_ipv4vlan_rule *ro) { ro->data = ri->data; ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto; ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan; ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr; ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low; ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low; ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask; ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask; ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 = ri->domain_mask; ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = ri->src_mask_len; ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len; ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 = ri->src_port_high; ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 = ri->dst_port_high; } int rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_ipv4vlan_rule *rules, uint32_t num) { int32_t rc; uint32_t i; struct acl_ipv4vlan_rule rv; if (ctx == NULL || rules == NULL || ctx->rule_sz != sizeof(rv)) return -EINVAL; /* check input rules. */ for (i = 0; i != num; i++) { rc = acl_ipv4vlan_check_rule(rules + i); if (rc != 0) { RTE_LOG(ERR, ACL, "%s(%s): rule #%u is invalid\n", __func__, ctx->name, i + 1); return rc; } } if (num + ctx->num_rules > ctx->max_rules) return -ENOMEM; /* perform conversion to the internal format and add to the context. */ for (i = 0, rc = 0; i != num && rc == 0; i++) { acl_ipv4vlan_convert_rule(rules + i, &rv); rc = acl_add_rules(ctx, &rv, 1); } return rc; } static void acl_ipv4vlan_config(struct rte_acl_config *cfg, const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], uint32_t num_categories) { static const struct rte_acl_field_def ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD, .input_index = RTE_ACL_IPV4VLAN_PROTO, }, { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD, .input_index = RTE_ACL_IPV4VLAN_VLAN, }, { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD, .input_index = RTE_ACL_IPV4VLAN_VLAN, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD, .input_index = RTE_ACL_IPV4VLAN_SRC, }, { .type = RTE_ACL_FIELD_TYPE_MASK, .size = sizeof(uint32_t), .field_index = RTE_ACL_IPV4VLAN_DST_FIELD, .input_index = RTE_ACL_IPV4VLAN_DST, }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD, .input_index = RTE_ACL_IPV4VLAN_PORTS, }, { .type = RTE_ACL_FIELD_TYPE_RANGE, .size = sizeof(uint16_t), .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD, .input_index = RTE_ACL_IPV4VLAN_PORTS, }, }; memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs)); cfg->num_fields = RTE_DIM(ipv4_defs); cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PROTO]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset = layout[RTE_ACL_IPV4VLAN_VLAN]; cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset = layout[RTE_ACL_IPV4VLAN_VLAN] + cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size; cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset = layout[RTE_ACL_IPV4VLAN_SRC]; cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = layout[RTE_ACL_IPV4VLAN_DST]; cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PORTS]; cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = layout[RTE_ACL_IPV4VLAN_PORTS] + cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size; cfg->num_categories = num_categories; } int rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx, const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], uint32_t num_categories) { struct rte_acl_config cfg; if (ctx == NULL || layout == NULL) return -EINVAL; memset(&cfg, 0, sizeof(cfg)); acl_ipv4vlan_config(&cfg, layout, num_categories); return rte_acl_build(ctx, &cfg); } ================================================ FILE: lib/librte_acl/rte_acl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ACL_H_ #define _RTE_ACL_H_ /** * @file * * RTE Classifier. */ #include #ifdef __cplusplus extern "C" { #endif #define RTE_ACL_MAX_CATEGORIES 16 #define RTE_ACL_RESULTS_MULTIPLIER (XMM_SIZE / sizeof(uint32_t)) #define RTE_ACL_MAX_LEVELS 64 #define RTE_ACL_MAX_FIELDS 64 union rte_acl_field_types { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64; }; enum { RTE_ACL_FIELD_TYPE_MASK = 0, RTE_ACL_FIELD_TYPE_RANGE, RTE_ACL_FIELD_TYPE_BITMASK }; /** * ACL Field definition. * Each field in the ACL rule has an associate definition. * It defines the type of field, its size, its offset in the input buffer, * the field index, and the input index. * For performance reasons, the inner loop of the search function is unrolled * to process four input bytes at a time. This requires the input to be grouped * into sets of 4 consecutive bytes. The loop processes the first input byte as * part of the setup and then subsequent bytes must be in groups of 4 * consecutive bytes. */ struct rte_acl_field_def { uint8_t type; /**< type - RTE_ACL_FIELD_TYPE_*. */ uint8_t size; /**< size of field 1,2,4, or 8. */ uint8_t field_index; /**< index of field inside the rule. */ uint8_t input_index; /**< 0-N input index. */ uint32_t offset; /**< offset to start of field. */ }; /** * ACL build configuration. * Defines the fields of an ACL trie and number of categories to build with. */ struct rte_acl_config { uint32_t num_categories; /**< Number of categories to build with. */ uint32_t num_fields; /**< Number of field definitions. */ struct rte_acl_field_def defs[RTE_ACL_MAX_FIELDS]; /**< array of field definitions. */ size_t max_size; /**< max memory limit for internal run-time structures. */ }; /** * Defines the value of a field for a rule. */ struct rte_acl_field { union rte_acl_field_types value; /**< a 1,2,4, or 8 byte value of the field. */ union rte_acl_field_types mask_range; /**< * depending on field type: * mask -> 1.2.3.4/32 value=0x1020304, mask_range=32, * range -> 0 : 65535 value=0, mask_range=65535, * bitmask -> 0x06/0xff value=6, mask_range=0xff. */ }; enum { RTE_ACL_TYPE_SHIFT = 29, RTE_ACL_MAX_INDEX = RTE_LEN2MASK(RTE_ACL_TYPE_SHIFT, uint32_t), RTE_ACL_MAX_PRIORITY = RTE_ACL_MAX_INDEX, RTE_ACL_MIN_PRIORITY = 0, }; #define RTE_ACL_INVALID_USERDATA 0 #define RTE_ACL_MASKLEN_TO_BITMASK(v, s) \ ((v) == 0 ? (v) : (typeof(v))((uint64_t)-1 << ((s) * CHAR_BIT - (v)))) /** * Miscellaneous data for ACL rule. */ struct rte_acl_rule_data { uint32_t category_mask; /**< Mask of categories for that rule. */ int32_t priority; /**< Priority for that rule. */ uint32_t userdata; /**< Associated with the rule user data. */ }; /** * Defines single ACL rule. * data - miscellaneous data for the rule. * field[] - value and mask or range for each field. */ #define RTE_ACL_RULE_DEF(name, fld_num) struct name {\ struct rte_acl_rule_data data; \ struct rte_acl_field field[fld_num]; \ } RTE_ACL_RULE_DEF(rte_acl_rule, 0); #define RTE_ACL_RULE_SZ(fld_num) \ (sizeof(struct rte_acl_rule) + sizeof(struct rte_acl_field) * (fld_num)) /** Max number of characters in name.*/ #define RTE_ACL_NAMESIZE 32 /** * Parameters used when creating the ACL context. */ struct rte_acl_param { const char *name; /**< Name of the ACL context. */ int socket_id; /**< Socket ID to allocate memory for. */ uint32_t rule_size; /**< Size of each rule. */ uint32_t max_rule_num; /**< Maximum number of rules. */ }; /** * Create a new ACL context. * * @param param * Parameters used to create and initialise the ACL context. * @return * Pointer to ACL context structure that is used in future ACL * operations, or NULL on error, with error code set in rte_errno. * Possible rte_errno errors include: * - EINVAL - invalid parameter passed to function */ struct rte_acl_ctx * rte_acl_create(const struct rte_acl_param *param); /** * Find an existing ACL context object and return a pointer to it. * * @param name * Name of the ACL context as passed to rte_acl_create() * @return * Pointer to ACL context or NULL if object not found * with rte_errno set appropriately. Possible rte_errno values include: * - ENOENT - value not available for return */ struct rte_acl_ctx * rte_acl_find_existing(const char *name); /** * De-allocate all memory used by ACL context. * * @param ctx * ACL context to free */ void rte_acl_free(struct rte_acl_ctx *ctx); /** * Add rules to an existing ACL context. * This function is not multi-thread safe. * * @param ctx * ACL context to add patterns to. * @param rules * Array of rules to add to the ACL context. * Note that all fields in rte_acl_rule structures are expected * to be in host byte order. * Each rule expected to be in the same format and not exceed size * specified at ACL context creation time. * @param num * Number of elements in the input array of rules. * @return * - -ENOMEM if there is no space in the ACL context for these rules. * - -EINVAL if the parameters are invalid. * - Zero if operation completed successfully. */ int rte_acl_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_rule *rules, uint32_t num); /** * Delete all rules from the ACL context. * This function is not multi-thread safe. * Note that internal run-time structures are not affected. * * @param ctx * ACL context to delete rules from. */ void rte_acl_reset_rules(struct rte_acl_ctx *ctx); /** * Analyze set of rules and build required internal run-time structures. * This function is not multi-thread safe. * * @param ctx * ACL context to build. * @param cfg * Pointer to struct rte_acl_config - defines build parameters. * @return * - -ENOMEM if couldn't allocate enough memory. * - -EINVAL if the parameters are invalid. * - Negative error code if operation failed. * - Zero if operation completed successfully. */ int rte_acl_build(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg); /** * Delete all rules from the ACL context and * destroy all internal run-time structures. * This function is not multi-thread safe. * * @param ctx * ACL context to reset. */ void rte_acl_reset(struct rte_acl_ctx *ctx); /** * Available implementations of ACL classify. */ enum rte_acl_classify_alg { RTE_ACL_CLASSIFY_DEFAULT = 0, RTE_ACL_CLASSIFY_SCALAR = 1, /**< generic implementation. */ RTE_ACL_CLASSIFY_SSE = 2, /**< requires SSE4.1 support. */ RTE_ACL_CLASSIFY_AVX2 = 3, /**< requires AVX2 support. */ RTE_ACL_CLASSIFY_NUM /* should always be the last one. */ }; /** * Perform search for a matching ACL rule for each input data buffer. * Each input data buffer can have up to *categories* matches. * That implies that results array should be big enough to hold * (categories * num) elements. * Also categories parameter should be either one or multiple of * RTE_ACL_RESULTS_MULTIPLIER and can't be bigger than RTE_ACL_MAX_CATEGORIES. * If more than one rule is applicable for given input buffer and * given category, then rule with highest priority will be returned as a match. * Note, that it is a caller's responsibility to ensure that input parameters * are valid and point to correct memory locations. * * @param ctx * ACL context to search with. * @param data * Array of pointers to input data buffers to perform search. * Note that all fields in input data buffers supposed to be in network * byte order (MSB). * @param results * Array of search results, *categories* results per each input data buffer. * @param num * Number of elements in the input data buffers array. * @param categories * Number of maximum possible matches for each input buffer, one possible * match per category. * @return * zero on successful completion. * -EINVAL for incorrect arguments. */ extern int rte_acl_classify(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories); /** * Perform search using specified algorithm for a matching ACL rule for * each input data buffer. * Each input data buffer can have up to *categories* matches. * That implies that results array should be big enough to hold * (categories * num) elements. * Also categories parameter should be either one or multiple of * RTE_ACL_RESULTS_MULTIPLIER and can't be bigger than RTE_ACL_MAX_CATEGORIES. * If more than one rule is applicable for given input buffer and * given category, then rule with highest priority will be returned as a match. * Note, that it is a caller's responsibility to ensure that input parameters * are valid and point to correct memory locations. * * @param ctx * ACL context to search with. * @param data * Array of pointers to input data buffers to perform search. * Note that all fields in input data buffers supposed to be in network * byte order (MSB). * @param results * Array of search results, *categories* results per each input data buffer. * @param num * Number of elements in the input data buffers array. * @param categories * Number of maximum possible matches for each input buffer, one possible * match per category. * @param alg * Algorithm to be used for the search. * It is the caller responsibility to ensure that the value refers to the * existing algorithm, and that it could be run on the given CPU. * @return * zero on successful completion. * -EINVAL for incorrect arguments. */ extern int rte_acl_classify_alg(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories, enum rte_acl_classify_alg alg); /* * Override the default classifier function for a given ACL context. * @param ctx * ACL context to change classify function for. * @param alg * New default classify algorithm for given ACL context. * It is the caller responsibility to ensure that the value refers to the * existing algorithm, and that it could be run on the given CPU. * @return * - -EINVAL if the parameters are invalid. * - Zero if operation completed successfully. */ extern int rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg); /** * Dump an ACL context structure to the console. * * @param ctx * ACL context to dump. */ void rte_acl_dump(const struct rte_acl_ctx *ctx); /** * Dump all ACL context structures to the console. */ void rte_acl_list_dump(void); /** * Legacy support for 7-tuple IPv4 and VLAN rule. * This structure and corresponding API is deprecated. */ struct rte_acl_ipv4vlan_rule { struct rte_acl_rule_data data; /**< Miscellaneous data for the rule. */ uint8_t proto; /**< IPv4 protocol ID. */ uint8_t proto_mask; /**< IPv4 protocol ID mask. */ uint16_t vlan; /**< VLAN ID. */ uint16_t vlan_mask; /**< VLAN ID mask. */ uint16_t domain; /**< VLAN domain. */ uint16_t domain_mask; /**< VLAN domain mask. */ uint32_t src_addr; /**< IPv4 source address. */ uint32_t src_mask_len; /**< IPv4 source address mask. */ uint32_t dst_addr; /**< IPv4 destination address. */ uint32_t dst_mask_len; /**< IPv4 destination address mask. */ uint16_t src_port_low; /**< L4 source port low. */ uint16_t src_port_high; /**< L4 source port high. */ uint16_t dst_port_low; /**< L4 destination port low. */ uint16_t dst_port_high; /**< L4 destination port high. */ }; /** * Specifies fields layout inside rte_acl_rule for rte_acl_ipv4vlan_rule. */ enum { RTE_ACL_IPV4VLAN_PROTO_FIELD, RTE_ACL_IPV4VLAN_VLAN1_FIELD, RTE_ACL_IPV4VLAN_VLAN2_FIELD, RTE_ACL_IPV4VLAN_SRC_FIELD, RTE_ACL_IPV4VLAN_DST_FIELD, RTE_ACL_IPV4VLAN_SRCP_FIELD, RTE_ACL_IPV4VLAN_DSTP_FIELD, RTE_ACL_IPV4VLAN_NUM_FIELDS }; /** * Macro to define rule size for rte_acl_ipv4vlan_rule. */ #define RTE_ACL_IPV4VLAN_RULE_SZ \ RTE_ACL_RULE_SZ(RTE_ACL_IPV4VLAN_NUM_FIELDS) /* * That effectively defines order of IPV4VLAN classifications: * - PROTO * - VLAN (TAG and DOMAIN) * - SRC IP ADDRESS * - DST IP ADDRESS * - PORTS (SRC and DST) */ enum { RTE_ACL_IPV4VLAN_PROTO, RTE_ACL_IPV4VLAN_VLAN, RTE_ACL_IPV4VLAN_SRC, RTE_ACL_IPV4VLAN_DST, RTE_ACL_IPV4VLAN_PORTS, RTE_ACL_IPV4VLAN_NUM }; /** * Add ipv4vlan rules to an existing ACL context. * This function is not multi-thread safe. * * @param ctx * ACL context to add patterns to. * @param rules * Array of rules to add to the ACL context. * Note that all fields in rte_acl_ipv4vlan_rule structures are expected * to be in host byte order. * @param num * Number of elements in the input array of rules. * @return * - -ENOMEM if there is no space in the ACL context for these rules. * - -EINVAL if the parameters are invalid. * - Zero if operation completed successfully. */ int rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_ipv4vlan_rule *rules, uint32_t num); /** * Analyze set of ipv4vlan rules and build required internal * run-time structures. * This function is not multi-thread safe. * * @param ctx * ACL context to build. * @param layout * Layout of input data to search through. * @param num_categories * Maximum number of categories to use in that build. * @return * - -ENOMEM if couldn't allocate enough memory. * - -EINVAL if the parameters are invalid. * - Negative error code if operation failed. * - Zero if operation completed successfully. */ int rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx, const uint32_t layout[RTE_ACL_IPV4VLAN_NUM], uint32_t num_categories); #ifdef __cplusplus } #endif #endif /* _RTE_ACL_H_ */ ================================================ FILE: lib/librte_acl/rte_acl_osdep.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ACL_OSDEP_H_ #define _RTE_ACL_OSDEP_H_ /** * @file * * RTE ACL DPDK/OS dependent file. */ #include #include #include #include #include #include #include #include #include #include #include /* * Common defines. */ #define DIM(x) RTE_DIM(x) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* _RTE_ACL_OSDEP_H_ */ ================================================ FILE: lib/librte_acl/tb_mem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tb_mem.h" /* * Memory management routines for temporary memory. * That memory is used only during build phase and is released after * build is finished. * Note, that tb_pool/tb_alloc() are not supposed to return NULL. * Instead, in the case of failure to allocate memory, * it would do siglongjmp(pool->fail). * It is responsibility of the caller to save the proper context/environment, * in the pool->fail before calling tb_alloc() for the given pool first time. */ static struct tb_mem_block * tb_pool(struct tb_mem_pool *pool, size_t sz) { struct tb_mem_block *block; uint8_t *ptr; size_t size; size = sz + pool->alignment - 1; block = calloc(1, size + sizeof(*pool->block)); if (block == NULL) { RTE_LOG(ERR, MALLOC, "%s(%zu)\n failed, currently allocated " "by pool: %zu bytes\n", __func__, sz, pool->alloc); siglongjmp(pool->fail, -ENOMEM); return NULL; } block->pool = pool; block->next = pool->block; pool->block = block; pool->alloc += size; ptr = (uint8_t *)(block + 1); block->mem = RTE_PTR_ALIGN_CEIL(ptr, pool->alignment); block->size = size - (block->mem - ptr); return block; } void * tb_alloc(struct tb_mem_pool *pool, size_t size) { struct tb_mem_block *block; void *ptr; size_t new_sz; size = RTE_ALIGN_CEIL(size, pool->alignment); block = pool->block; if (block == NULL || block->size < size) { new_sz = (size > pool->min_alloc) ? size : pool->min_alloc; block = tb_pool(pool, new_sz); } ptr = block->mem; block->size -= size; block->mem += size; return ptr; } void tb_free_pool(struct tb_mem_pool *pool) { struct tb_mem_block *next, *block; for (block = pool->block; block != NULL; block = next) { next = block->next; free(block); } pool->block = NULL; pool->alloc = 0; } ================================================ FILE: lib/librte_acl/tb_mem.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _TB_MEM_H_ #define _TB_MEM_H_ /** * @file * * RTE ACL temporary (build phase) memory management. * Contains structures and functions to manage temporary (used by build only) * memory. Memory allocated in large blocks to speed 'free' when trie is * destructed (finish of build phase). */ #ifdef __cplusplus extern "C" { #endif #include #include struct tb_mem_block { struct tb_mem_block *next; struct tb_mem_pool *pool; size_t size; uint8_t *mem; }; struct tb_mem_pool { struct tb_mem_block *block; size_t alignment; size_t min_alloc; size_t alloc; /* jump target in case of memory allocation failure. */ sigjmp_buf fail; }; void *tb_alloc(struct tb_mem_pool *pool, size_t size); void tb_free_pool(struct tb_mem_pool *pool); #ifdef __cplusplus } #endif #endif /* _TB_MEM_H_ */ ================================================ FILE: lib/librte_cfgfile/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_cfgfile.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_cfgfile_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_CFGFILE) += rte_cfgfile.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_CFGFILE)-include += rte_cfgfile.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_cfgfile/rte_cfgfile.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_cfgfile.h" struct rte_cfgfile_section { char name[CFG_NAME_LEN]; int num_entries; struct rte_cfgfile_entry *entries[0]; }; struct rte_cfgfile { int flags; int num_sections; struct rte_cfgfile_section *sections[0]; }; /** when we resize a file structure, how many extra entries * for new sections do we add in */ #define CFG_ALLOC_SECTION_BATCH 8 /** when we resize a section structure, how many extra entries * for new entries do we add in */ #define CFG_ALLOC_ENTRY_BATCH 16 static unsigned _strip(char *str, unsigned len) { int newlen = len; if (len == 0) return 0; if (isspace(str[len-1])) { /* strip trailing whitespace */ while (newlen > 0 && isspace(str[newlen - 1])) str[--newlen] = '\0'; } if (isspace(str[0])) { /* strip leading whitespace */ int i, start = 1; while (isspace(str[start]) && start < newlen) start++ ; /* do nothing */ newlen -= start; for (i = 0; i < newlen; i++) str[i] = str[i+start]; str[i] = '\0'; } return newlen; } struct rte_cfgfile * rte_cfgfile_load(const char *filename, int flags) { int allocated_sections = CFG_ALLOC_SECTION_BATCH; int allocated_entries = 0; int curr_section = -1; int curr_entry = -1; char buffer[256] = {0}; int lineno = 0; struct rte_cfgfile *cfg = NULL; FILE *f = fopen(filename, "r"); if (f == NULL) return NULL; cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (cfg == NULL) goto error2; memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections); while (fgets(buffer, sizeof(buffer), f) != NULL) { char *pos = NULL; size_t len = strnlen(buffer, sizeof(buffer)); lineno++; if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) { printf("Error line %d - no \\n found on string. " "Check if line too long\n", lineno); goto error1; } pos = memchr(buffer, ';', sizeof(buffer)); if (pos != NULL) { *pos = '\0'; len = pos - buffer; } len = _strip(buffer, len); if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) continue; if (buffer[0] == '[') { /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { printf("Error line %d - no terminating '['" "character found\n", lineno); goto error1; } *end = '\0'; _strip(&buffer[1], end - &buffer[1]); /* close off old section and add start new one */ if (curr_section >= 0) cfg->sections[curr_section]->num_entries = curr_entry + 1; curr_section++; /* resize overall struct if we don't have room for more sections */ if (curr_section == allocated_sections) { allocated_sections += CFG_ALLOC_SECTION_BATCH; struct rte_cfgfile *n_cfg = realloc(cfg, sizeof(*cfg) + sizeof(cfg->sections[0]) * allocated_sections); if (n_cfg == NULL) { printf("Error - no more memory\n"); goto error1; } cfg = n_cfg; } /* allocate space for new section */ allocated_entries = CFG_ALLOC_ENTRY_BATCH; curr_entry = -1; cfg->sections[curr_section] = malloc( sizeof(*cfg->sections[0]) + sizeof(cfg->sections[0]->entries[0]) * allocated_entries); if (cfg->sections[curr_section] == NULL) { printf("Error - no more memory\n"); goto error1; } snprintf(cfg->sections[curr_section]->name, sizeof(cfg->sections[0]->name), "%s", &buffer[1]); } else { /* value line */ if (curr_section < 0) { printf("Error line %d - value outside of" "section\n", lineno); goto error1; } struct rte_cfgfile_section *sect = cfg->sections[curr_section]; char *split[2]; if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=') != 2) { printf("Error at line %d - cannot split " "string\n", lineno); goto error1; } curr_entry++; if (curr_entry == allocated_entries) { allocated_entries += CFG_ALLOC_ENTRY_BATCH; struct rte_cfgfile_section *n_sect = realloc( sect, sizeof(*sect) + sizeof(sect->entries[0]) * allocated_entries); if (n_sect == NULL) { printf("Error - no more memory\n"); goto error1; } sect = cfg->sections[curr_section] = n_sect; } sect->entries[curr_entry] = malloc( sizeof(*sect->entries[0])); if (sect->entries[curr_entry] == NULL) { printf("Error - no more memory\n"); goto error1; } struct rte_cfgfile_entry *entry = sect->entries[ curr_entry]; snprintf(entry->name, sizeof(entry->name), "%s", split[0]); snprintf(entry->value, sizeof(entry->value), "%s", split[1]); _strip(entry->name, strnlen(entry->name, sizeof(entry->name))); _strip(entry->value, strnlen(entry->value, sizeof(entry->value))); } } fclose(f); cfg->flags = flags; cfg->num_sections = curr_section + 1; /* curr_section will still be -1 if we have an empty file */ if (curr_section >= 0) cfg->sections[curr_section]->num_entries = curr_entry + 1; return cfg; error1: rte_cfgfile_close(cfg); error2: fclose(f); return NULL; } int rte_cfgfile_close(struct rte_cfgfile *cfg) { int i, j; if (cfg == NULL) return -1; for (i = 0; i < cfg->num_sections; i++) { if (cfg->sections[i] != NULL) { if (cfg->sections[i]->num_entries) { for (j = 0; j < cfg->sections[i]->num_entries; j++) { if (cfg->sections[i]->entries[j] != NULL) free(cfg->sections[i]-> entries[j]); } } free(cfg->sections[i]); } } free(cfg); return 0; } int rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sectionname, size_t length) { int i; int num_sections = 0; for (i = 0; i < cfg->num_sections; i++) { if (strncmp(cfg->sections[i]->name, sectionname, length) == 0) num_sections++; } return num_sections; } int rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[], int max_sections) { int i; for (i = 0; i < cfg->num_sections && i < max_sections; i++) snprintf(sections[i], CFG_NAME_LEN, "%s", cfg->sections[i]->name); return i; } static const struct rte_cfgfile_section * _get_section(struct rte_cfgfile *cfg, const char *sectionname) { int i; for (i = 0; i < cfg->num_sections; i++) { if (strncmp(cfg->sections[i]->name, sectionname, sizeof(cfg->sections[0]->name)) == 0) return cfg->sections[i]; } return NULL; } int rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname) { return (_get_section(cfg, sectionname) != NULL); } int rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg, const char *sectionname) { const struct rte_cfgfile_section *s = _get_section(cfg, sectionname); if (s == NULL) return -1; return s->num_entries; } int rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname, struct rte_cfgfile_entry *entries, int max_entries) { int i; const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname); if (sect == NULL) return -1; for (i = 0; i < max_entries && i < sect->num_entries; i++) entries[i] = *sect->entries[i]; return i; } const char * rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname, const char *entryname) { int i; const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname); if (sect == NULL) return NULL; for (i = 0; i < sect->num_entries; i++) if (strncmp(sect->entries[i]->name, entryname, CFG_NAME_LEN) == 0) return sect->entries[i]->value; return NULL; } int rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname, const char *entryname) { return (rte_cfgfile_get_entry(cfg, sectionname, entryname) != NULL); } ================================================ FILE: lib/librte_cfgfile/rte_cfgfile.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_CFGFILE_H__ #define __INCLUDE_RTE_CFGFILE_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Configuration File * * This library allows reading application defined parameters from standard * format configuration file. * ***/ #define CFG_NAME_LEN 32 #define CFG_VALUE_LEN 64 /** Configuration file */ struct rte_cfgfile; /** Configuration file entry */ struct rte_cfgfile_entry { char name[CFG_NAME_LEN]; /**< Name */ char value[CFG_VALUE_LEN]; /**< Value */ }; /** * Open config file * * @param filename * Config file name * @param flags * Config file flags, Reserved for future use. Must be set to 0. * @return * Handle to configuration file */ struct rte_cfgfile *rte_cfgfile_load(const char *filename, int flags); /** * Get number of sections in config file * * @param cfg * Config file * @param sec_name * Section name * @param length * Maximum section name length * @return * 0 on success, error code otherwise */ int rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name, size_t length); /** * Get name of all config file sections. * * Fills in the array sections with the name of all the sections in the file * (up to the number of max_sections sections). * * @param cfg * Config file * @param sections * Array containing section names after successful invocation. Each elemen * of this array should be preallocated by the user with at least * CFG_NAME_LEN characters. * @param max_sections * Maximum number of section names to be stored in sections array * @return * 0 on success, error code otherwise */ int rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[], int max_sections); /** * Check if given section exists in config file * * @param cfg * Config file * @param sectionname * Section name * @return * TRUE (value different than 0) if section exists, FALSE (value 0) otherwise */ int rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname); /** * Get number of entries in given config file section * * @param cfg * Config file * @param sectionname * Section name * @return * Number of entries in section */ int rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg, const char *sectionname); /** Get section entries as key-value pairs * * @param cfg * Config file * @param sectionname * Section name * @param entries * Pre-allocated array of at least max_entries entries where the section * entries are stored as key-value pair after successful invocation * @param max_entries * Maximum number of section entries to be stored in entries array * @return * 0 on success, error code otherwise */ int rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname, struct rte_cfgfile_entry *entries, int max_entries); /** Get value of the named entry in named config file section * * @param cfg * Config file * @param sectionname * Section name * @param entryname * Entry name * @return * Entry value */ const char *rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname, const char *entryname); /** Check if given entry exists in named config file section * * @param cfg * Config file * @param sectionname * Section name * @param entryname * Entry name * @return * TRUE (value different than 0) if entry exists, FALSE (value 0) otherwise */ int rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname, const char *entryname); /** Close config file * * @param cfg * Config file * @return * 0 on success, error code otherwise */ int rte_cfgfile_close(struct rte_cfgfile *cfg); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_cmdline/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_cmdline.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_cmdline_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := cmdline.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_cirbuf.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_etheraddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_ipaddr.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_num.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_string.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_rdline.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_vt100.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_socket.c SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_parse_portlist.c CFLAGS += -D_GNU_SOURCE # install includes INCS := cmdline.h cmdline_parse.h cmdline_parse_num.h cmdline_parse_ipaddr.h INCS += cmdline_parse_etheraddr.h cmdline_parse_string.h cmdline_rdline.h INCS += cmdline_vt100.h cmdline_socket.h cmdline_cirbuf.h cmdline_parse_portlist.h SYMLINK-$(CONFIG_RTE_LIBRTE_CMDLINE)-include := $(INCS) # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_cmdline/cmdline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_rdline.h" #include "cmdline.h" static void cmdline_valid_buffer(struct rdline *rdl, const char *buf, __attribute__((unused)) unsigned int size) { struct cmdline *cl = rdl->opaque; int ret; ret = cmdline_parse(cl, buf); if (ret == CMDLINE_PARSE_AMBIGUOUS) cmdline_printf(cl, "Ambiguous command\n"); else if (ret == CMDLINE_PARSE_NOMATCH) cmdline_printf(cl, "Command not found\n"); else if (ret == CMDLINE_PARSE_BAD_ARGS) cmdline_printf(cl, "Bad arguments\n"); } static int cmdline_complete_buffer(struct rdline *rdl, const char *buf, char *dstbuf, unsigned int dstsize, int *state) { struct cmdline *cl = rdl->opaque; return cmdline_complete(cl, buf, state, dstbuf, dstsize); } int cmdline_write_char(struct rdline *rdl, char c) { int ret = -1; struct cmdline *cl; if (!rdl) return -1; cl = rdl->opaque; if (cl->s_out >= 0) ret = write(cl->s_out, &c, 1); return ret; } void cmdline_set_prompt(struct cmdline *cl, const char *prompt) { if (!cl || !prompt) return; snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); } struct cmdline * cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) { struct cmdline *cl; if (!ctx || !prompt) return NULL; cl = malloc(sizeof(struct cmdline)); if (cl == NULL) return NULL; memset(cl, 0, sizeof(struct cmdline)); cl->s_in = s_in; cl->s_out = s_out; cl->ctx = ctx; rdline_init(&cl->rdl, cmdline_write_char, cmdline_valid_buffer, cmdline_complete_buffer); cl->rdl.opaque = cl; cmdline_set_prompt(cl, prompt); rdline_newline(&cl->rdl, cl->prompt); return cl; } void cmdline_free(struct cmdline *cl) { dprintf("called\n"); if (!cl) return; if (cl->s_in > 2) close(cl->s_in); if (cl->s_out != cl->s_in && cl->s_out > 2) close(cl->s_out); free(cl); } void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) { va_list ap; if (!cl || !fmt) return; #ifdef _GNU_SOURCE if (cl->s_out < 0) return; va_start(ap, fmt); vdprintf(cl->s_out, fmt, ap); va_end(ap); #else int ret; char *buf; if (cl->s_out < 0) return; buf = malloc(BUFSIZ); if (buf == NULL) return; va_start(ap, fmt); ret = vsnprintf(buf, BUFSIZ, fmt, ap); va_end(ap); if (ret < 0) { free(buf); return; } if (ret >= BUFSIZ) ret = BUFSIZ - 1; write(cl->s_out, buf, ret); free(buf); #endif } int cmdline_in(struct cmdline *cl, const char *buf, int size) { const char *history, *buffer; size_t histlen, buflen; int ret = 0; int i, same; if (!cl || !buf) return -1; for (i=0; irdl, buf[i]); if (ret == RDLINE_RES_VALIDATED) { buffer = rdline_get_buffer(&cl->rdl); history = rdline_get_history_item(&cl->rdl, 0); if (history) { histlen = strnlen(history, RDLINE_BUF_SIZE); same = !memcmp(buffer, history, histlen) && buffer[histlen] == '\n'; } else same = 0; buflen = strnlen(buffer, RDLINE_BUF_SIZE); if (buflen > 1 && !same) rdline_add_history(&cl->rdl, buffer); rdline_newline(&cl->rdl, cl->prompt); } else if (ret == RDLINE_RES_EOF) return -1; else if (ret == RDLINE_RES_EXITED) return -1; } return i; } void cmdline_quit(struct cmdline *cl) { if (!cl) return; rdline_quit(&cl->rdl); } int cmdline_poll(struct cmdline *cl) { struct pollfd pfd; int status; ssize_t read_status; char c; if (!cl) return -EINVAL; else if (cl->rdl.status == RDLINE_EXITED) return RDLINE_EXITED; pfd.fd = cl->s_in; pfd.events = POLLIN; pfd.revents = 0; status = poll(&pfd, 1, 0); if (status < 0) return status; else if (status > 0) { c = -1; read_status = read(cl->s_in, &c, 1); if (read_status < 0) return read_status; status = cmdline_in(cl, &c, 1); if (status < 0 && cl->rdl.status != RDLINE_EXITED) return status; } return cl->rdl.status; } void cmdline_interact(struct cmdline *cl) { char c; if (!cl) return; c = -1; while (1) { if (read(cl->s_in, &c, 1) <= 0) break; if (cmdline_in(cl, &c, 1) < 0) break; } } ================================================ FILE: lib/librte_cmdline/cmdline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CMDLINE_H_ #define _CMDLINE_H_ #include #include /** * @file * * Command line API */ #ifdef __cplusplus extern "C" { #endif struct cmdline { int s_in; int s_out; cmdline_parse_ctx_t *ctx; struct rdline rdl; char prompt[RDLINE_PROMPT_SIZE]; struct termios oldterm; }; struct cmdline *cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out); void cmdline_set_prompt(struct cmdline *cl, const char *prompt); void cmdline_free(struct cmdline *cl); void cmdline_printf(const struct cmdline *cl, const char *fmt, ...) __attribute__((format(printf,2,3))); int cmdline_in(struct cmdline *cl, const char *buf, int size); int cmdline_write_char(struct rdline *rdl, char c); /** * This function is nonblocking equivalent of ``cmdline_interact()``. It polls * *cl* for one character and interpret it. If return value is *RDLINE_EXITED* * it mean that ``cmdline_quit()`` was invoked. * * @param cl * The command line object. * * @return * On success return object status - one of *enum rdline_status*. * On error return negative value. */ int cmdline_poll(struct cmdline *cl); void cmdline_interact(struct cmdline *cl); void cmdline_quit(struct cmdline *cl); #ifdef __cplusplus } #endif #endif /* _CMDLINE_SOCKET_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_cirbuf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "cmdline_cirbuf.h" int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen) { if (!cbuf || !buf) return -EINVAL; cbuf->maxlen = maxlen; cbuf->len = 0; cbuf->start = start; cbuf->end = start; cbuf->buf = buf; return 0; } /* multiple add */ int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n) { unsigned int e; if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) return -EINVAL; e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; if (n < cbuf->start + e) { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start - n + e, n); memcpy(cbuf->buf + cbuf->start - n + e, c, n); } else { dprintf("s[%d] -> d[%d] (%d)\n", + n - (cbuf->start + e), 0, cbuf->start + e); dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + (cbuf->start + e), 0, n - (cbuf->start + e)); memcpy(cbuf->buf, c + n - (cbuf->start + e) , cbuf->start + e); memcpy(cbuf->buf + cbuf->maxlen - n + (cbuf->start + e), c, n - (cbuf->start + e)); } cbuf->len += n; cbuf->start += (cbuf->maxlen - n + e); cbuf->start %= cbuf->maxlen; return n; } /* multiple add */ int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n) { unsigned int e; if (!cbuf || !c || !n || n > CIRBUF_GET_FREELEN(cbuf)) return -EINVAL; e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; if (n < cbuf->maxlen - cbuf->end - 1 + e) { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); memcpy(cbuf->buf + cbuf->end + !e, c, n); } else { dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, cbuf->maxlen - cbuf->end - 1 + e); dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - cbuf->end - 1 + e); memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, n - cbuf->maxlen + cbuf->end + 1 - e); } cbuf->len += n; cbuf->end += n - e; cbuf->end %= cbuf->maxlen; return n; } /* add at head */ static inline void __cirbuf_add_head(struct cirbuf * cbuf, char c) { if (!CIRBUF_IS_EMPTY(cbuf)) { cbuf->start += (cbuf->maxlen - 1); cbuf->start %= cbuf->maxlen; } cbuf->buf[cbuf->start] = c; cbuf->len ++; } int cirbuf_add_head_safe(struct cirbuf * cbuf, char c) { if (cbuf && !CIRBUF_IS_FULL(cbuf)) { __cirbuf_add_head(cbuf, c); return 0; } return -EINVAL; } void cirbuf_add_head(struct cirbuf * cbuf, char c) { __cirbuf_add_head(cbuf, c); } /* add at tail */ static inline void __cirbuf_add_tail(struct cirbuf * cbuf, char c) { if (!CIRBUF_IS_EMPTY(cbuf)) { cbuf->end ++; cbuf->end %= cbuf->maxlen; } cbuf->buf[cbuf->end] = c; cbuf->len ++; } int cirbuf_add_tail_safe(struct cirbuf * cbuf, char c) { if (cbuf && !CIRBUF_IS_FULL(cbuf)) { __cirbuf_add_tail(cbuf, c); return 0; } return -EINVAL; } void cirbuf_add_tail(struct cirbuf * cbuf, char c) { __cirbuf_add_tail(cbuf, c); } static inline void __cirbuf_shift_left(struct cirbuf *cbuf) { unsigned int i; char tmp = cbuf->buf[cbuf->start]; for (i=0 ; ilen ; i++) { cbuf->buf[(cbuf->start+i)%cbuf->maxlen] = cbuf->buf[(cbuf->start+i+1)%cbuf->maxlen]; } cbuf->buf[(cbuf->start-1+cbuf->maxlen)%cbuf->maxlen] = tmp; cbuf->start += (cbuf->maxlen - 1); cbuf->start %= cbuf->maxlen; cbuf->end += (cbuf->maxlen - 1); cbuf->end %= cbuf->maxlen; } static inline void __cirbuf_shift_right(struct cirbuf *cbuf) { unsigned int i; char tmp = cbuf->buf[cbuf->end]; for (i=0 ; ilen ; i++) { cbuf->buf[(cbuf->end+cbuf->maxlen-i)%cbuf->maxlen] = cbuf->buf[(cbuf->end+cbuf->maxlen-i-1)%cbuf->maxlen]; } cbuf->buf[(cbuf->end+1)%cbuf->maxlen] = tmp; cbuf->start += 1; cbuf->start %= cbuf->maxlen; cbuf->end += 1; cbuf->end %= cbuf->maxlen; } /* XXX we could do a better algorithm here... */ int cirbuf_align_left(struct cirbuf * cbuf) { if (!cbuf) return -EINVAL; if (cbuf->start < cbuf->maxlen/2) { while (cbuf->start != 0) { __cirbuf_shift_left(cbuf); } } else { while (cbuf->start != 0) { __cirbuf_shift_right(cbuf); } } return 0; } /* XXX we could do a better algorithm here... */ int cirbuf_align_right(struct cirbuf * cbuf) { if (!cbuf) return -EINVAL; if (cbuf->start >= cbuf->maxlen/2) { while (cbuf->end != cbuf->maxlen-1) { __cirbuf_shift_left(cbuf); } } else { while (cbuf->start != cbuf->maxlen-1) { __cirbuf_shift_right(cbuf); } } return 0; } /* buffer del */ int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size) { if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) return -EINVAL; cbuf->len -= size; if (CIRBUF_IS_EMPTY(cbuf)) { cbuf->start += size - 1; cbuf->start %= cbuf->maxlen; } else { cbuf->start += size; cbuf->start %= cbuf->maxlen; } return 0; } /* buffer del */ int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size) { if (!cbuf || !size || size > CIRBUF_GET_LEN(cbuf)) return -EINVAL; cbuf->len -= size; if (CIRBUF_IS_EMPTY(cbuf)) { cbuf->end += (cbuf->maxlen - size + 1); cbuf->end %= cbuf->maxlen; } else { cbuf->end += (cbuf->maxlen - size); cbuf->end %= cbuf->maxlen; } return 0; } /* del at head */ static inline void __cirbuf_del_head(struct cirbuf * cbuf) { cbuf->len --; if (!CIRBUF_IS_EMPTY(cbuf)) { cbuf->start ++; cbuf->start %= cbuf->maxlen; } } int cirbuf_del_head_safe(struct cirbuf * cbuf) { if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { __cirbuf_del_head(cbuf); return 0; } return -EINVAL; } void cirbuf_del_head(struct cirbuf * cbuf) { __cirbuf_del_head(cbuf); } /* del at tail */ static inline void __cirbuf_del_tail(struct cirbuf * cbuf) { cbuf->len --; if (!CIRBUF_IS_EMPTY(cbuf)) { cbuf->end += (cbuf->maxlen - 1); cbuf->end %= cbuf->maxlen; } } int cirbuf_del_tail_safe(struct cirbuf * cbuf) { if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { __cirbuf_del_tail(cbuf); return 0; } return -EINVAL; } void cirbuf_del_tail(struct cirbuf * cbuf) { __cirbuf_del_tail(cbuf); } /* convert to buffer */ int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size) { unsigned int n; if (!cbuf || !c) return -EINVAL; n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); if (!n) return 0; if (cbuf->start <= cbuf->end) { dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, n); memcpy(c, cbuf->buf + cbuf->start , n); } else { /* check if we need to go from end to the beginning */ if (n <= cbuf->maxlen - cbuf->start) { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->start, n); memcpy(c, cbuf->buf + cbuf->start , n); } else { dprintf("s[%d] -> d[%d] (%d)\n", cbuf->start, 0, cbuf->maxlen - cbuf->start); dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, n - cbuf->maxlen + cbuf->start); memcpy(c, cbuf->buf + cbuf->start , cbuf->maxlen - cbuf->start); memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, n - cbuf->maxlen + cbuf->start); } } return n; } /* convert to buffer */ int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size) { unsigned int n; if (!cbuf || !c) return -EINVAL; n = (size < CIRBUF_GET_LEN(cbuf)) ? size : CIRBUF_GET_LEN(cbuf); if (!n) return 0; if (cbuf->start <= cbuf->end) { dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end - n + 1, 0, n); memcpy(c, cbuf->buf + cbuf->end - n + 1, n); } else { /* check if we need to go from end to the beginning */ if (n <= cbuf->end + 1) { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end - n + 1, n); memcpy(c, cbuf->buf + cbuf->end - n + 1, n); } else { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->maxlen - cbuf->start, cbuf->end + 1); dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - n + cbuf->end + 1, 0, n - cbuf->end - 1); memcpy(c + cbuf->maxlen - cbuf->start, cbuf->buf, cbuf->end + 1); memcpy(c, cbuf->buf + cbuf->maxlen - n + cbuf->end +1, n - cbuf->end - 1); } } return n; } /* get head or get tail */ char cirbuf_get_head(struct cirbuf * cbuf) { return cbuf->buf[cbuf->start]; } /* get head or get tail */ char cirbuf_get_tail(struct cirbuf * cbuf) { return cbuf->buf[cbuf->end]; } ================================================ FILE: lib/librte_cmdline/cmdline_cirbuf.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CIRBUF_H_ #define _CIRBUF_H_ #ifdef __cplusplus extern "C" { #endif /** * This structure is the header of a cirbuf type. */ struct cirbuf { unsigned int maxlen; /**< total len of the fifo (number of elements) */ unsigned int start; /**< indice of the first elt */ unsigned int end; /**< indice of the last elt */ unsigned int len; /**< current len of fifo */ char *buf; }; #ifdef RTE_LIBRTE_CMDLINE_DEBUG #define dprintf_(fmt, ...) printf("line %3.3d - " fmt "%.0s", __LINE__, __VA_ARGS__) #define dprintf(...) dprintf_(__VA_ARGS__, "dummy") #else #define dprintf(...) (void)0 #endif /** * Init the circular buffer */ int cirbuf_init(struct cirbuf *cbuf, char *buf, unsigned int start, unsigned int maxlen); /** * Return 1 if the circular buffer is full */ #define CIRBUF_IS_FULL(cirbuf) ((cirbuf)->maxlen == (cirbuf)->len) /** * Return 1 if the circular buffer is empty */ #define CIRBUF_IS_EMPTY(cirbuf) ((cirbuf)->len == 0) /** * return current size of the circular buffer (number of used elements) */ #define CIRBUF_GET_LEN(cirbuf) ((cirbuf)->len) /** * return size of the circular buffer (used + free elements) */ #define CIRBUF_GET_MAXLEN(cirbuf) ((cirbuf)->maxlen) /** * return the number of free elts */ #define CIRBUF_GET_FREELEN(cirbuf) ((cirbuf)->maxlen - (cirbuf)->len) /** * Iterator for a circular buffer * c: struct cirbuf pointer * i: an integer type internally used in the macro * e: char that takes the value for each iteration */ #define CIRBUF_FOREACH(c, i, e) \ for ( i=0, e=(c)->buf[(c)->start] ; \ i<((c)->len) ; \ i ++, e=(c)->buf[((c)->start+i)%((c)->maxlen)]) /** * Add a character at head of the circular buffer. Return 0 on success, or * a negative value on error. */ int cirbuf_add_head_safe(struct cirbuf *cbuf, char c); /** * Add a character at head of the circular buffer. You _must_ check that you * have enough free space in the buffer before calling this func. */ void cirbuf_add_head(struct cirbuf *cbuf, char c); /** * Add a character at tail of the circular buffer. Return 0 on success, or * a negative value on error. */ int cirbuf_add_tail_safe(struct cirbuf *cbuf, char c); /** * Add a character at tail of the circular buffer. You _must_ check that you * have enough free space in the buffer before calling this func. */ void cirbuf_add_tail(struct cirbuf *cbuf, char c); /** * Remove a char at the head of the circular buffer. Return 0 on * success, or a negative value on error. */ int cirbuf_del_head_safe(struct cirbuf *cbuf); /** * Remove a char at the head of the circular buffer. You _must_ check * that buffer is not empty before calling the function. */ void cirbuf_del_head(struct cirbuf *cbuf); /** * Remove a char at the tail of the circular buffer. Return 0 on * success, or a negative value on error. */ int cirbuf_del_tail_safe(struct cirbuf *cbuf); /** * Remove a char at the tail of the circular buffer. You _must_ check * that buffer is not empty before calling the function. */ void cirbuf_del_tail(struct cirbuf *cbuf); /** * Return the head of the circular buffer. You _must_ check that * buffer is not empty before calling the function. */ char cirbuf_get_head(struct cirbuf *cbuf); /** * Return the tail of the circular buffer. You _must_ check that * buffer is not empty before calling the function. */ char cirbuf_get_tail(struct cirbuf *cbuf); /** * Add a buffer at head of the circular buffer. 'c' is a pointer to a * buffer, and n is the number of char to add. Return the number of * copied bytes on success, or a negative value on error. */ int cirbuf_add_buf_head(struct cirbuf *cbuf, const char *c, unsigned int n); /** * Add a buffer at tail of the circular buffer. 'c' is a pointer to a * buffer, and n is the number of char to add. Return the number of * copied bytes on success, or a negative value on error. */ int cirbuf_add_buf_tail(struct cirbuf *cbuf, const char *c, unsigned int n); /** * Remove chars at the head of the circular buffer. Return 0 on * success, or a negative value on error. */ int cirbuf_del_buf_head(struct cirbuf *cbuf, unsigned int size); /** * Remove chars at the tail of the circular buffer. Return 0 on * success, or a negative value on error. */ int cirbuf_del_buf_tail(struct cirbuf *cbuf, unsigned int size); /** * Copy a maximum of 'size' characters from the head of the circular * buffer to a flat one pointed by 'c'. Return the number of copied * chars. */ int cirbuf_get_buf_head(struct cirbuf *cbuf, char *c, unsigned int size); /** * Copy a maximum of 'size' characters from the tail of the circular * buffer to a flat one pointed by 'c'. Return the number of copied * chars. */ int cirbuf_get_buf_tail(struct cirbuf *cbuf, char *c, unsigned int size); /** * Set the start of the data to the index 0 of the internal buffer. */ int cirbuf_align_left(struct cirbuf *cbuf); /** * Set the end of the data to the last index of the internal buffer. */ int cirbuf_align_right(struct cirbuf *cbuf); #ifdef __cplusplus } #endif #endif /* _CIRBUF_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "cmdline_rdline.h" #include "cmdline_parse.h" #include "cmdline.h" #ifdef RTE_LIBRTE_CMDLINE_DEBUG #define debug_printf printf #else #define debug_printf(args...) do {} while(0) #endif #define CMDLINE_BUFFER_SIZE 64 /* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our * own. */ static int isblank2(char c) { if (c == ' ' || c == '\t' ) return 1; return 0; } static int isendofline(char c) { if (c == '\n' || c == '\r' ) return 1; return 0; } static int iscomment(char c) { if (c == '#') return 1; return 0; } int cmdline_isendoftoken(char c) { if (!c || iscomment(c) || isblank2(c) || isendofline(c)) return 1; return 0; } static unsigned int nb_common_chars(const char * s1, const char * s2) { unsigned int i=0; while (*s1==*s2 && *s1) { s1++; s2++; i++; } return i; } /** * try to match the buffer with an instruction (only the first * nb_match_token tokens if != 0). Return 0 if we match all the * tokens, else the number of matched tokens, else -1. */ static int match_inst(cmdline_parse_inst_t *inst, const char *buf, unsigned int nb_match_token, void *resbuf, unsigned resbuf_size) { unsigned int token_num=0; cmdline_parse_token_hdr_t * token_p; unsigned int i=0; int n = 0; struct cmdline_token_hdr token_hdr; token_p = inst->tokens[token_num]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); /* check if we match all tokens of inst */ while (token_p && (!nb_match_token || iparse(token_p, buf, NULL, 0); } else { unsigned rb_sz; if (token_hdr.offset > resbuf_size) { printf("Parse error(%s:%d): Token offset(%u) " "exceeds maximum size(%u)\n", __FILE__, __LINE__, token_hdr.offset, resbuf_size); return -ENOBUFS; } rb_sz = resbuf_size - token_hdr.offset; n = token_hdr.ops->parse(token_p, buf, (char *)resbuf + token_hdr.offset, rb_sz); } if (n < 0) break; debug_printf("TK parsed (len=%d)\n", n); i++; buf += n; token_num ++; token_p = inst->tokens[token_num]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); } /* does not match */ if (i==0) return -1; /* in case we want to match a specific num of token */ if (nb_match_token) { if (i == nb_match_token) { return 0; } return i; } /* we don't match all the tokens */ if (token_p) { return i; } /* are there are some tokens more */ while (isblank2(*buf)) { buf++; } /* end of buf */ if ( isendofline(*buf) || iscomment(*buf) ) return 0; /* garbage after inst */ return i; } int cmdline_parse(struct cmdline *cl, const char * buf) { unsigned int inst_num=0; cmdline_parse_inst_t *inst; const char *curbuf; char result_buf[CMDLINE_PARSE_RESULT_BUFSIZE]; void (*f)(void *, struct cmdline *, void *) = NULL; void *data = NULL; int comment = 0; int linelen = 0; int parse_it = 0; int err = CMDLINE_PARSE_NOMATCH; int tok; cmdline_parse_ctx_t *ctx; #ifdef RTE_LIBRTE_CMDLINE_DEBUG char debug_buf[BUFSIZ]; #endif if (!cl || !buf) return CMDLINE_PARSE_BAD_ARGS; ctx = cl->ctx; /* * - look if the buffer contains at least one line * - look if line contains only spaces or comments * - count line length */ curbuf = buf; while (! isendofline(*curbuf)) { if ( *curbuf == '\0' ) { debug_printf("Incomplete buf (len=%d)\n", linelen); return 0; } if ( iscomment(*curbuf) ) { comment = 1; } if ( ! isblank2(*curbuf) && ! comment) { parse_it = 1; } curbuf++; linelen++; } /* skip all endofline chars */ while (isendofline(buf[linelen])) { linelen++; } /* empty line */ if ( parse_it == 0 ) { debug_printf("Empty line (len=%d)\n", linelen); return linelen; } #ifdef RTE_LIBRTE_CMDLINE_DEBUG snprintf(debug_buf, (linelen>64 ? 64 : linelen), "%s", buf); debug_printf("Parse line : len=%d, <%s>\n", linelen, debug_buf); #endif /* parse it !! */ inst = ctx[inst_num]; while (inst) { debug_printf("INST %d\n", inst_num); /* fully parsed */ tok = match_inst(inst, buf, 0, result_buf, sizeof(result_buf)); if (tok > 0) /* we matched at least one token */ err = CMDLINE_PARSE_BAD_ARGS; else if (!tok) { debug_printf("INST fully parsed\n"); /* skip spaces */ while (isblank2(*curbuf)) { curbuf++; } /* if end of buf -> there is no garbage after inst */ if (isendofline(*curbuf) || iscomment(*curbuf)) { if (!f) { memcpy(&f, &inst->f, sizeof(f)); memcpy(&data, &inst->data, sizeof(data)); } else { /* more than 1 inst matches */ err = CMDLINE_PARSE_AMBIGUOUS; f=NULL; debug_printf("Ambiguous cmd\n"); break; } } } inst_num ++; inst = ctx[inst_num]; } /* call func */ if (f) { f(result_buf, cl, data); } /* no match */ else { debug_printf("No match err=%d\n", err); return err; } return linelen; } int cmdline_complete(struct cmdline *cl, const char *buf, int *state, char *dst, unsigned int size) { const char *partial_tok = buf; unsigned int inst_num = 0; cmdline_parse_inst_t *inst; cmdline_parse_token_hdr_t *token_p; struct cmdline_token_hdr token_hdr; char tmpbuf[CMDLINE_BUFFER_SIZE], comp_buf[CMDLINE_BUFFER_SIZE]; unsigned int partial_tok_len; int comp_len = -1; int tmp_len = -1; int nb_token = 0; unsigned int i, n; int l; unsigned int nb_completable; unsigned int nb_non_completable; int local_state = 0; const char *help_str; cmdline_parse_ctx_t *ctx; if (!cl || !buf || !state || !dst) return -1; ctx = cl->ctx; debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); /* count the number of complete token to parse */ for (i=0 ; buf[i] ; i++) { if (!isblank2(buf[i]) && isblank2(buf[i+1])) nb_token++; if (isblank2(buf[i]) && !isblank2(buf[i+1])) partial_tok = buf+i+1; } partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); /* first call -> do a first pass */ if (*state <= 0) { debug_printf("try complete <%s>\n", buf); debug_printf("there is %d complete tokens, <%s> is incomplete\n", nb_token, partial_tok); nb_completable = 0; nb_non_completable = 0; inst = ctx[inst_num]; while (inst) { /* parse the first tokens of the inst */ if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next; debug_printf("instruction match\n"); token_p = inst->tokens[nb_token]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); /* non completable */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { nb_non_completable++; goto next; } debug_printf("%d choices for this token\n", n); for (i=0 ; icomplete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; /* we have at least room for one char */ tmp_len = strnlen(tmpbuf, sizeof(tmpbuf)); if (tmp_len < CMDLINE_BUFFER_SIZE - 1) { tmpbuf[tmp_len] = ' '; tmpbuf[tmp_len+1] = 0; } debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the * beginning of the word ? */ if (!strncmp(partial_tok, tmpbuf, partial_tok_len)) { if (comp_len == -1) { snprintf(comp_buf, sizeof(comp_buf), "%s", tmpbuf + partial_tok_len); comp_len = strnlen(tmpbuf + partial_tok_len, sizeof(tmpbuf) - partial_tok_len); } else { comp_len = nb_common_chars(comp_buf, tmpbuf+partial_tok_len); comp_buf[comp_len] = 0; } nb_completable++; } } next: debug_printf("next\n"); inst_num ++; inst = ctx[inst_num]; } debug_printf("total choices %d for this completion\n", nb_completable); /* no possible completion */ if (nb_completable == 0 && nb_non_completable == 0) return 0; /* if multichoice is not required */ if (*state == 0 && partial_tok_len > 0) { /* one or several choices starting with the same chars */ if (comp_len > 0) { if ((unsigned)(comp_len + 1) > size) return 0; snprintf(dst, size, "%s", comp_buf); dst[comp_len] = 0; return 2; } } } /* init state correctly */ if (*state == -1) *state = 0; debug_printf("Multiple choice STATE=%d\n", *state); inst_num = 0; inst = ctx[inst_num]; while (inst) { /* we need to redo it */ inst = ctx[inst_num]; if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next2; token_p = inst->tokens[nb_token]; if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); /* one choice for this token */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { if (local_state < *state) { local_state++; goto next2; } (*state)++; if (token_p && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = inst->help_str; if (help_str) snprintf(dst, size, "[%s]: %s", tmpbuf, help_str); else snprintf(dst, size, "[%s]: No help", tmpbuf); } else { snprintf(dst, size, "[RETURN]"); } return 1; } /* several choices */ for (i=0 ; icomplete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; /* we have at least room for one char */ tmp_len = strnlen(tmpbuf, sizeof(tmpbuf)); if (tmp_len < CMDLINE_BUFFER_SIZE - 1) { tmpbuf[tmp_len] = ' '; tmpbuf[tmp_len + 1] = 0; } debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the beginning of * the word ? */ if (!strncmp(partial_tok, tmpbuf, partial_tok_len)) { if (local_state < *state) { local_state++; continue; } (*state)++; l=snprintf(dst, size, "%s", tmpbuf); if (l>=0 && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = inst->help_str; if (help_str) snprintf(dst+l, size-l, "[%s]: %s", tmpbuf, help_str); else snprintf(dst+l, size-l, "[%s]: No help", tmpbuf); } return 1; } } next2: inst_num ++; inst = ctx[inst_num]; } return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CMDLINE_PARSE_H_ #define _CMDLINE_PARSE_H_ #ifdef __cplusplus extern "C" { #endif #ifndef offsetof #define offsetof(type, field) ((size_t) &( ((type *)0)->field) ) #endif /* return status for parsing */ #define CMDLINE_PARSE_SUCCESS 0 #define CMDLINE_PARSE_AMBIGUOUS -1 #define CMDLINE_PARSE_NOMATCH -2 #define CMDLINE_PARSE_BAD_ARGS -3 /* return status for completion */ #define CMDLINE_PARSE_COMPLETE_FINISHED 0 #define CMDLINE_PARSE_COMPLETE_AGAIN 1 #define CMDLINE_PARSE_COMPLETED_BUFFER 2 /* maximum buffer size for parsed result */ #define CMDLINE_PARSE_RESULT_BUFSIZE 8192 /** * Stores a pointer to the ops struct, and the offset: the place to * write the parsed result in the destination structure. */ struct cmdline_token_hdr { struct cmdline_token_ops *ops; unsigned int offset; }; typedef struct cmdline_token_hdr cmdline_parse_token_hdr_t; /** * A token is defined by this structure. * * parse() takes the token as first argument, then the source buffer * starting at the token we want to parse. The 3rd arg is a pointer * where we store the parsed data (as binary). It returns the number of * parsed chars on success and a negative value on error. * * complete_get_nb() returns the number of possible values for this * token if completion is possible. If it is NULL or if it returns 0, * no completion is possible. * * complete_get_elt() copy in dstbuf (the size is specified in the * parameter) the i-th possible completion for this token. returns 0 * on success or and a negative value on error. * * get_help() fills the dstbuf with the help for the token. It returns * -1 on error and 0 on success. */ struct cmdline_token_ops { /** parse(token ptr, buf, res pts, buf len) */ int (*parse)(cmdline_parse_token_hdr_t *, const char *, void *, unsigned int); /** return the num of possible choices for this token */ int (*complete_get_nb)(cmdline_parse_token_hdr_t *); /** return the elt x for this token (token, idx, dstbuf, size) */ int (*complete_get_elt)(cmdline_parse_token_hdr_t *, int, char *, unsigned int); /** get help for this token (token, dstbuf, size) */ int (*get_help)(cmdline_parse_token_hdr_t *, char *, unsigned int); }; struct cmdline; /** * Store a instruction, which is a pointer to a callback function and * its parameter that is called when the instruction is parsed, a help * string, and a list of token composing this instruction. */ struct cmdline_inst { /* f(parsed_struct, data) */ void (*f)(void *, struct cmdline *, void *); void *data; const char *help_str; cmdline_parse_token_hdr_t *tokens[]; }; typedef struct cmdline_inst cmdline_parse_inst_t; /** * A context is identified by its name, and contains a list of * instruction * */ typedef cmdline_parse_inst_t *cmdline_parse_ctx_t; /** * Try to parse a buffer according to the specified context. The * argument buf must ends with "\n\0". The function returns * CMDLINE_PARSE_AMBIGUOUS, CMDLINE_PARSE_NOMATCH or * CMDLINE_PARSE_BAD_ARGS on error. Else it calls the associated * function (defined in the context) and returns 0 * (CMDLINE_PARSE_SUCCESS). */ int cmdline_parse(struct cmdline *cl, const char *buf); /** * complete() must be called with *state==0 (try to complete) or * with *state==-1 (just display choices), then called without * modifying *state until it returns CMDLINE_PARSE_COMPLETED_BUFFER or * CMDLINE_PARSE_COMPLETED_BUFFER. * * It returns < 0 on error. * * Else it returns: * - CMDLINE_PARSE_COMPLETED_BUFFER on completion (one possible * choice). In this case, the chars are appended in dst buffer. * - CMDLINE_PARSE_COMPLETE_AGAIN if there is several possible * choices. In this case, you must call the function again, * keeping the value of state intact. * - CMDLINE_PARSE_COMPLETED_BUFFER when the iteration is * finished. The dst is not valid for this last call. * * The returned dst buf ends with \0. */ int cmdline_complete(struct cmdline *cl, const char *buf, int *state, char *dst, unsigned int size); /* return true if(!c || iscomment(c) || isblank(c) || * isendofline(c)) */ int cmdline_isendoftoken(char c); #ifdef __cplusplus } #endif #endif /* _CMDLINE_PARSE_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse_etheraddr.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_parse_etheraddr.h" struct cmdline_token_ops cmdline_token_etheraddr_ops = { .parse = cmdline_parse_etheraddr, .complete_get_nb = NULL, .complete_get_elt = NULL, .get_help = cmdline_get_help_etheraddr, }; /* the format can be either XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX */ #define ETHER_ADDRSTRLENLONG 18 #define ETHER_ADDRSTRLENSHORT 15 #ifdef __linux__ #define ea_oct ether_addr_octet #else #define ea_oct octet #endif static struct ether_addr * my_ether_aton(const char *a) { int i; char *end; unsigned long o[ETHER_ADDR_LEN]; static struct ether_addr ether_addr; i = 0; do { errno = 0; o[i] = strtoul(a, &end, 16); if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) return NULL; a = end + 1; } while (++i != sizeof (o) / sizeof (o[0]) && end[0] != 0); /* Junk at the end of line */ if (end[0] != 0) return NULL; /* Support the format XX:XX:XX:XX:XX:XX */ if (i == ETHER_ADDR_LEN) { while (i-- != 0) { if (o[i] > UINT8_MAX) return NULL; ether_addr.ea_oct[i] = (uint8_t)o[i]; } /* Support the format XXXX:XXXX:XXXX */ } else if (i == ETHER_ADDR_LEN / 2) { while (i-- != 0) { if (o[i] > UINT16_MAX) return NULL; ether_addr.ea_oct[i * 2] = (uint8_t)(o[i] >> 8); ether_addr.ea_oct[i * 2 + 1] = (uint8_t)(o[i] & 0xff); } /* unknown format */ } else return NULL; return (struct ether_addr *)ðer_addr; } int cmdline_parse_etheraddr(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { unsigned int token_len = 0; char ether_str[ETHER_ADDRSTRLENLONG+1]; struct ether_addr *tmp; if (res && ressize < sizeof(struct ether_addr)) return -1; if (!buf || ! *buf) return -1; while (!cmdline_isendoftoken(buf[token_len])) token_len++; /* if token doesn't match possible string lengths... */ if ((token_len != ETHER_ADDRSTRLENLONG - 1) && (token_len != ETHER_ADDRSTRLENSHORT - 1)) return -1; snprintf(ether_str, token_len+1, "%s", buf); tmp = my_ether_aton(ether_str); if (tmp == NULL) return -1; if (res) memcpy(res, tmp, sizeof(struct ether_addr)); return token_len; } int cmdline_get_help_etheraddr(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { int ret; ret = snprintf(dstbuf, size, "Ethernet address"); if (ret < 0) return -1; return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse_etheraddr.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_ETHERADDR_H_ #define _PARSE_ETHERADDR_H_ #ifdef __cplusplus extern "C" { #endif struct cmdline_token_etheraddr { struct cmdline_token_hdr hdr; }; typedef struct cmdline_token_etheraddr cmdline_parse_token_etheraddr_t; extern struct cmdline_token_ops cmdline_token_etheraddr_ops; int cmdline_parse_etheraddr(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int cmdline_get_help_etheraddr(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_ETHERADDR_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_etheraddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ } #ifdef __cplusplus } #endif #endif /* _PARSE_ETHERADDR_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse_ipaddr.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * For inet_ntop() functions: * * Copyright (c) 1996 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include #include #include #include #include #include #include #ifndef __linux__ #ifndef __FreeBSD__ #include #else #include #endif #endif #include #include "cmdline_parse.h" #include "cmdline_parse_ipaddr.h" struct cmdline_token_ops cmdline_token_ipaddr_ops = { .parse = cmdline_parse_ipaddr, .complete_get_nb = NULL, .complete_get_elt = NULL, .get_help = cmdline_get_help_ipaddr, }; #define INADDRSZ 4 #define IN6ADDRSZ 16 #define PREFIXMAX 128 #define V4PREFIXMAX 32 /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static int inet_pton4(const char *src, unsigned char *dst); static int inet_pton6(const char *src, unsigned char *dst); /* int * inet_pton(af, src, dst) * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). * return: * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * author: * Paul Vixie, 1996. */ static int my_inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: return inet_pton4(src, dst); case AF_INET6: return inet_pton6(src, dst); default: errno = EAFNOSUPPORT; return -1; } /* NOTREACHED */ } /* int * inet_pton4(src, dst) * like inet_aton() but without all the hexadecimal and shorthand. * return: * 1 if `src' is a valid dotted quad, else 0. * notice: * does not touch `dst' unless it's returning 1. * author: * Paul Vixie, 1996. */ static int inet_pton4(const char *src, unsigned char *dst) { static const char digits[] = "0123456789"; int saw_digit, octets, ch; unsigned char tmp[INADDRSZ], *tp; saw_digit = 0; octets = 0; *(tp = tmp) = 0; while ((ch = *src++) != '\0') { const char *pch; if ((pch = strchr(digits, ch)) != NULL) { unsigned int new = *tp * 10 + (pch - digits); if (new > 255) return 0; if (! saw_digit) { if (++octets > 4) return 0; saw_digit = 1; } *tp = (unsigned char)new; } else if (ch == '.' && saw_digit) { if (octets == 4) return 0; *++tp = 0; saw_digit = 0; } else return 0; } if (octets < 4) return 0; memcpy(dst, tmp, INADDRSZ); return 1; } /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. * return: * 1 if `src' is a valid [RFC1884 2.2] address, else 0. * notice: * (1) does not touch `dst' unless it's returning 1. * (2) :: in a full address is silently ignored. * credit: * inspired by Mark Andrews. * author: * Paul Vixie, 1996. */ static int inet_pton6(const char *src, unsigned char *dst) { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; const char *xdigits = 0, *curtok = 0; int ch = 0, saw_xdigit = 0, count_xdigit = 0; unsigned int val = 0; unsigned dbloct_count = 0; memset((tp = tmp), '\0', IN6ADDRSZ); endp = tp + IN6ADDRSZ; colonp = NULL; /* Leading :: requires some special handling. */ if (*src == ':') if (*++src != ':') return 0; curtok = src; saw_xdigit = count_xdigit = 0; val = 0; while ((ch = *src++) != '\0') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) pch = strchr((xdigits = xdigits_u), ch); if (pch != NULL) { if (count_xdigit >= 4) return 0; val <<= 4; val |= (pch - xdigits); if (val > 0xffff) return 0; saw_xdigit = 1; count_xdigit++; continue; } if (ch == ':') { curtok = src; if (!saw_xdigit) { if (colonp) return 0; colonp = tp; continue; } else if (*src == '\0') { return 0; } if (tp + sizeof(int16_t) > endp) return 0; *tp++ = (unsigned char) ((val >> 8) & 0xff); *tp++ = (unsigned char) (val & 0xff); saw_xdigit = 0; count_xdigit = 0; val = 0; dbloct_count++; continue; } if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) { tp += INADDRSZ; saw_xdigit = 0; dbloct_count += 2; break; /* '\0' was seen by inet_pton4(). */ } return 0; } if (saw_xdigit) { if (tp + sizeof(int16_t) > endp) return 0; *tp++ = (unsigned char) ((val >> 8) & 0xff); *tp++ = (unsigned char) (val & 0xff); dbloct_count++; } if (colonp != NULL) { /* if we already have 8 double octets, having a colon means error */ if (dbloct_count == 8) return 0; /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const int n = tp - colonp; int i; for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if (tp != endp) return 0; memcpy(dst, tmp, IN6ADDRSZ); return 1; } int cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { struct cmdline_token_ipaddr *tk2; unsigned int token_len = 0; char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */ cmdline_ipaddr_t ipaddr; char *prefix, *prefix_end; long prefixlen = 0; if (res && ressize < sizeof(cmdline_ipaddr_t)) return -1; if (!buf || !tk || ! *buf) return -1; tk2 = (struct cmdline_token_ipaddr *)tk; while (!cmdline_isendoftoken(buf[token_len])) token_len++; /* if token is too big... */ if (token_len >= INET6_ADDRSTRLEN+4) return -1; snprintf(ip_str, token_len+1, "%s", buf); /* convert the network prefix */ if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) { prefix = strrchr(ip_str, '/'); if (prefix == NULL) return -1; *prefix = '\0'; prefix ++; errno = 0; prefixlen = strtol(prefix, &prefix_end, 10); if (errno || (*prefix_end != '\0') || prefixlen < 0 || prefixlen > PREFIXMAX) return -1; ipaddr.prefixlen = prefixlen; } else { ipaddr.prefixlen = 0; } /* convert the IP addr */ if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) && my_inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 && prefixlen <= V4PREFIXMAX) { ipaddr.family = AF_INET; if (res) memcpy(res, &ipaddr, sizeof(ipaddr)); return token_len; } if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) && my_inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) { ipaddr.family = AF_INET6; if (res) memcpy(res, &ipaddr, sizeof(ipaddr)); return token_len; } return -1; } int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { struct cmdline_token_ipaddr *tk2; if (!tk || !dstbuf) return -1; tk2 = (struct cmdline_token_ipaddr *)tk; switch (tk2->ipaddr_data.flags) { case CMDLINE_IPADDR_V4: snprintf(dstbuf, size, "IPv4"); break; case CMDLINE_IPADDR_V6: snprintf(dstbuf, size, "IPv6"); break; case CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6: snprintf(dstbuf, size, "IPv4/IPv6"); break; case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4: snprintf(dstbuf, size, "IPv4 network"); break; case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V6: snprintf(dstbuf, size, "IPv6 network"); break; case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6: snprintf(dstbuf, size, "IPv4/IPv6 network"); break; default: snprintf(dstbuf, size, "IPaddr (bad flags)"); break; } return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse_ipaddr.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_IPADDR_H_ #define _PARSE_IPADDR_H_ #include #ifdef __cplusplus extern "C" { #endif #define CMDLINE_IPADDR_V4 0x01 #define CMDLINE_IPADDR_V6 0x02 #define CMDLINE_IPADDR_NETWORK 0x04 struct cmdline_ipaddr { uint8_t family; union { struct in_addr ipv4; struct in6_addr ipv6; } addr; unsigned int prefixlen; /* in case of network only */ }; typedef struct cmdline_ipaddr cmdline_ipaddr_t; struct cmdline_token_ipaddr_data { uint8_t flags; }; struct cmdline_token_ipaddr { struct cmdline_token_hdr hdr; struct cmdline_token_ipaddr_data ipaddr_data; }; typedef struct cmdline_token_ipaddr cmdline_parse_token_ipaddr_t; extern struct cmdline_token_ops cmdline_token_ipaddr_ops; int cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_IPADDR_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V4 | /* flags */ \ CMDLINE_IPADDR_V6, \ }, \ } #define TOKEN_IPV4_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V4, /* flags */ \ }, \ } #define TOKEN_IPV6_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V6, /* flags */ \ }, \ } #define TOKEN_IPNET_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V4 | /* flags */ \ CMDLINE_IPADDR_V6 | \ CMDLINE_IPADDR_NETWORK, \ }, \ } #define TOKEN_IPV4NET_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V4 | /* flags */ \ CMDLINE_IPADDR_NETWORK, \ }, \ } #define TOKEN_IPV6NET_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_ipaddr_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* ipaddr_data */ \ { \ CMDLINE_IPADDR_V4 | /* flags */ \ CMDLINE_IPADDR_NETWORK, \ }, \ } #ifdef __cplusplus } #endif #endif /* _PARSE_IPADDR_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse_num.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_parse_num.h" #ifdef RTE_LIBRTE_CMDLINE_DEBUG #define debug_printf(args...) printf(args) #else #define debug_printf(args...) do {} while(0) #endif struct cmdline_token_ops cmdline_token_num_ops = { .parse = cmdline_parse_num, .complete_get_nb = NULL, .complete_get_elt = NULL, .get_help = cmdline_get_help_num, }; enum num_parse_state_t { START, DEC_NEG, BIN, HEX, ERROR, FIRST_OK, /* not used */ ZERO_OK, HEX_OK, OCTAL_OK, BIN_OK, DEC_NEG_OK, DEC_POS_OK, }; /* Keep it sync with enum in .h */ static const char * num_help[] = { "UINT8", "UINT16", "UINT32", "UINT64", "INT8", "INT16", "INT32", "INT64", }; static inline int add_to_res(unsigned int c, uint64_t *res, unsigned int base) { /* overflow */ if ( (UINT64_MAX - c) / base < *res ) { return -1; } *res = (uint64_t) (*res * base + c); return 0; } static int check_res_size(struct cmdline_token_num_data *nd, unsigned ressize) { switch (nd->type) { case INT8: case UINT8: if (ressize < sizeof(int8_t)) return -1; break; case INT16: case UINT16: if (ressize < sizeof(int16_t)) return -1; break; case INT32: case UINT32: if (ressize < sizeof(int32_t)) return -1; break; case INT64: case UINT64: if (ressize < sizeof(int64_t)) return -1; break; default: return -1; } return 0; } /* parse an int */ int cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize) { struct cmdline_token_num_data nd; enum num_parse_state_t st = START; const char * buf; char c; uint64_t res1 = 0; if (!tk) return -1; if (!srcbuf || !*srcbuf) return -1; buf = srcbuf; c = *buf; memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd)); /* check that we have enough room in res */ if (res) { if (check_res_size(&nd, ressize) < 0) return -1; } while ( st != ERROR && c && ! cmdline_isendoftoken(c) ) { debug_printf("%c %x -> ", c, c); switch (st) { case START: if (c == '-') { st = DEC_NEG; } else if (c == '0') { st = ZERO_OK; } else if (c >= '1' && c <= '9') { if (add_to_res(c - '0', &res1, 10) < 0) st = ERROR; else st = DEC_POS_OK; } else { st = ERROR; } break; case ZERO_OK: if (c == 'x') { st = HEX; } else if (c == 'b') { st = BIN; } else if (c >= '0' && c <= '7') { if (add_to_res(c - '0', &res1, 10) < 0) st = ERROR; else st = OCTAL_OK; } else { st = ERROR; } break; case DEC_NEG: if (c >= '0' && c <= '9') { if (add_to_res(c - '0', &res1, 10) < 0) st = ERROR; else st = DEC_NEG_OK; } else { st = ERROR; } break; case DEC_NEG_OK: if (c >= '0' && c <= '9') { if (add_to_res(c - '0', &res1, 10) < 0) st = ERROR; } else { st = ERROR; } break; case DEC_POS_OK: if (c >= '0' && c <= '9') { if (add_to_res(c - '0', &res1, 10) < 0) st = ERROR; } else { st = ERROR; } break; case HEX: st = HEX_OK; /* no break */ case HEX_OK: if (c >= '0' && c <= '9') { if (add_to_res(c - '0', &res1, 16) < 0) st = ERROR; } else if (c >= 'a' && c <= 'f') { if (add_to_res(c - 'a' + 10, &res1, 16) < 0) st = ERROR; } else if (c >= 'A' && c <= 'F') { if (add_to_res(c - 'A' + 10, &res1, 16) < 0) st = ERROR; } else { st = ERROR; } break; case OCTAL_OK: if (c >= '0' && c <= '7') { if (add_to_res(c - '0', &res1, 8) < 0) st = ERROR; } else { st = ERROR; } break; case BIN: st = BIN_OK; /* no break */ case BIN_OK: if (c >= '0' && c <= '1') { if (add_to_res(c - '0', &res1, 2) < 0) st = ERROR; } else { st = ERROR; } break; default: debug_printf("not impl "); } debug_printf("(%"PRIu64")\n", res1); buf ++; c = *buf; /* token too long */ if (buf-srcbuf > 127) return -1; } switch (st) { case ZERO_OK: case DEC_POS_OK: case HEX_OK: case OCTAL_OK: case BIN_OK: if ( nd.type == INT8 && res1 <= INT8_MAX ) { if (res) *(int8_t *)res = (int8_t) res1; return buf-srcbuf; } else if ( nd.type == INT16 && res1 <= INT16_MAX ) { if (res) *(int16_t *)res = (int16_t) res1; return buf-srcbuf; } else if ( nd.type == INT32 && res1 <= INT32_MAX ) { if (res) *(int32_t *)res = (int32_t) res1; return buf-srcbuf; } else if ( nd.type == INT64 && res1 <= INT64_MAX ) { if (res) *(int64_t *)res = (int64_t) res1; return buf-srcbuf; } else if ( nd.type == UINT8 && res1 <= UINT8_MAX ) { if (res) *(uint8_t *)res = (uint8_t) res1; return buf-srcbuf; } else if (nd.type == UINT16 && res1 <= UINT16_MAX ) { if (res) *(uint16_t *)res = (uint16_t) res1; return buf-srcbuf; } else if ( nd.type == UINT32 && res1 <= UINT32_MAX ) { if (res) *(uint32_t *)res = (uint32_t) res1; return buf-srcbuf; } else if ( nd.type == UINT64 ) { if (res) *(uint64_t *)res = res1; return buf-srcbuf; } else { return -1; } break; case DEC_NEG_OK: if ( nd.type == INT8 && res1 <= INT8_MAX + 1 ) { if (res) *(int8_t *)res = (int8_t) (-res1); return buf-srcbuf; } else if ( nd.type == INT16 && res1 <= (uint16_t)INT16_MAX + 1 ) { if (res) *(int16_t *)res = (int16_t) (-res1); return buf-srcbuf; } else if ( nd.type == INT32 && res1 <= (uint32_t)INT32_MAX + 1 ) { if (res) *(int32_t *)res = (int32_t) (-res1); return buf-srcbuf; } else if ( nd.type == INT64 && res1 <= (uint64_t)INT64_MAX + 1 ) { if (res) *(int64_t *)res = (int64_t) (-res1); return buf-srcbuf; } else { return -1; } break; default: debug_printf("error\n"); return -1; } } /* parse an int */ int cmdline_get_help_num(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { struct cmdline_token_num_data nd; int ret; if (!tk) return -1; memcpy(&nd, &((struct cmdline_token_num *)tk)->num_data, sizeof(nd)); /* should not happen.... don't so this test */ /* if (nd.type >= (sizeof(num_help)/sizeof(const char *))) */ /* return -1; */ ret = snprintf(dstbuf, size, "%s", num_help[nd.type]); if (ret < 0) return -1; dstbuf[size-1] = '\0'; return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse_num.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_NUM_H_ #define _PARSE_NUM_H_ #ifdef __cplusplus extern "C" { #endif enum cmdline_numtype { UINT8 = 0, UINT16, UINT32, UINT64, INT8, INT16, INT32, INT64 }; struct cmdline_token_num_data { enum cmdline_numtype type; }; struct cmdline_token_num { struct cmdline_token_hdr hdr; struct cmdline_token_num_data num_data; }; typedef struct cmdline_token_num cmdline_parse_token_num_t; extern struct cmdline_token_ops cmdline_token_num_ops; int cmdline_parse_num(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int cmdline_get_help_num(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_NUM_INITIALIZER(structure, field, numtype) \ { \ /* hdr */ \ { \ &cmdline_token_num_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* num_data */ \ { \ numtype, /* type */ \ }, \ } #ifdef __cplusplus } #endif #endif /* _PARSE_NUM_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse_portlist.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2010, Keith Wiles * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_parse_portlist.h" struct cmdline_token_ops cmdline_token_portlist_ops = { .parse = cmdline_parse_portlist, .complete_get_nb = NULL, .complete_get_elt = NULL, .get_help = cmdline_get_help_portlist, }; static void parse_set_list(cmdline_portlist_t *pl, size_t low, size_t high) { do { pl->map |= (1 << low++); } while (low <= high); } static int parse_ports(cmdline_portlist_t *pl, const char *str) { size_t ps, pe; const char *first, *last; char *end; for (first = str, last = first; first != NULL && last != NULL; first = last + 1) { last = strchr(first, ','); errno = 0; ps = strtoul(first, &end, 10); if (errno != 0 || end == first || (end[0] != '-' && end[0] != 0 && end != last)) return -1; /* Support for N-M portlist format */ if (end[0] == '-') { errno = 0; first = end + 1; pe = strtoul(first, &end, 10); if (errno != 0 || end == first || (end[0] != 0 && end != last)) return -1; } else { pe = ps; } if (ps > pe || pe >= sizeof (pl->map) * 8) return -1; parse_set_list(pl, ps, pe); } return 0; } int cmdline_parse_portlist(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { unsigned int token_len = 0; char portlist_str[PORTLIST_TOKEN_SIZE+1]; cmdline_portlist_t *pl; if (!buf || ! *buf) return -1; if (res && ressize < sizeof(cmdline_portlist_t)) return -1; pl = res; while (!cmdline_isendoftoken(buf[token_len]) && (token_len < PORTLIST_TOKEN_SIZE)) token_len++; if (token_len >= PORTLIST_TOKEN_SIZE) return -1; snprintf(portlist_str, token_len+1, "%s", buf); if (pl) { pl->map = 0; if (strcmp("all", portlist_str) == 0) pl->map = UINT32_MAX; else if (parse_ports(pl, portlist_str) != 0) return -1; } return token_len; } int cmdline_get_help_portlist(__attribute__((unused)) cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { int ret; ret = snprintf(dstbuf, size, "range of ports as 3,4-6,8-19,20"); if (ret < 0) return -1; return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse_portlist.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2010, Keith Wiles * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_PORTLIST_H_ #define _PARSE_PORTLIST_H_ #ifdef __cplusplus extern "C" { #endif /* size of a parsed string */ #define PORTLIST_TOKEN_SIZE 128 #define PORTLIST_MAX_TOKENS 32 typedef struct cmdline_portlist { uint32_t map; } cmdline_portlist_t; struct cmdline_token_portlist { struct cmdline_token_hdr hdr; }; typedef struct cmdline_token_portlist cmdline_parse_token_portlist_t; extern struct cmdline_token_ops cmdline_token_portlist_ops; int cmdline_parse_portlist(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int cmdline_get_help_portlist(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_PORTLIST_INITIALIZER(structure, field) \ { \ /* hdr */ \ { \ &cmdline_token_portlist_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ } #ifdef __cplusplus } #endif #endif /* _PARSE_PORTLIST_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_parse_string.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_parse_string.h" struct cmdline_token_ops cmdline_token_string_ops = { .parse = cmdline_parse_string, .complete_get_nb = cmdline_complete_get_nb_string, .complete_get_elt = cmdline_complete_get_elt_string, .get_help = cmdline_get_help_string, }; #define MULTISTRING_HELP "Mul-choice STRING" #define ANYSTRING_HELP "Any STRING" #define FIXEDSTRING_HELP "Fixed STRING" static unsigned int get_token_len(const char *s) { char c; unsigned int i=0; c = s[i]; while (c!='#' && c!='\0') { i++; c = s[i]; } return i; } static const char * get_next_token(const char *s) { unsigned int i; i = get_token_len(s); if (s[i] == '#') return s+i+1; return NULL; } int cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, unsigned ressize) { struct cmdline_token_string *tk2; struct cmdline_token_string_data *sd; unsigned int token_len; const char *str; if (res && ressize < STR_TOKEN_SIZE) return -1; if (!tk || !buf || ! *buf) return -1; tk2 = (struct cmdline_token_string *)tk; sd = &tk2->string_data; /* fixed string */ if (sd->str) { str = sd->str; do { token_len = get_token_len(str); /* if token is too big... */ if (token_len >= STR_TOKEN_SIZE - 1) { continue; } if ( strncmp(buf, str, token_len) ) { continue; } if ( !cmdline_isendoftoken(*(buf+token_len)) ) { continue; } break; } while ( (str = get_next_token(str)) != NULL ); if (!str) return -1; } /* unspecified string */ else { token_len = 0; while(!cmdline_isendoftoken(buf[token_len]) && token_len < (STR_TOKEN_SIZE-1)) token_len++; /* return if token too long */ if (token_len >= STR_TOKEN_SIZE - 1) { return -1; } } if (res) { /* we are sure that token_len is < STR_TOKEN_SIZE-1 */ snprintf(res, STR_TOKEN_SIZE, "%s", buf); *((char *)res + token_len) = 0; } return token_len; } int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk) { struct cmdline_token_string *tk2; struct cmdline_token_string_data *sd; const char *str; int ret = 1; if (!tk) return -1; tk2 = (struct cmdline_token_string *)tk; sd = &tk2->string_data; if (!sd->str) return 0; str = sd->str; while( (str = get_next_token(str)) != NULL ) { ret++; } return ret; } int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx, char *dstbuf, unsigned int size) { struct cmdline_token_string *tk2; struct cmdline_token_string_data *sd; const char *s; unsigned int len; if (!tk || !dstbuf || idx < 0) return -1; tk2 = (struct cmdline_token_string *)tk; sd = &tk2->string_data; s = sd->str; while (idx-- && s) s = get_next_token(s); if (!s) return -1; len = get_token_len(s); if (len > size - 1) return -1; memcpy(dstbuf, s, len); dstbuf[len] = '\0'; return 0; } int cmdline_get_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size) { struct cmdline_token_string *tk2; struct cmdline_token_string_data *sd; const char *s; if (!tk || !dstbuf) return -1; tk2 = (struct cmdline_token_string *)tk; sd = &tk2->string_data; s = sd->str; if (s) { if (get_next_token(s)) snprintf(dstbuf, size, MULTISTRING_HELP); else snprintf(dstbuf, size, FIXEDSTRING_HELP); } else snprintf(dstbuf, size, ANYSTRING_HELP); return 0; } ================================================ FILE: lib/librte_cmdline/cmdline_parse_string.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PARSE_STRING_H_ #define _PARSE_STRING_H_ #ifdef __cplusplus extern "C" { #endif /* size of a parsed string */ #define STR_TOKEN_SIZE 128 typedef char cmdline_fixed_string_t[STR_TOKEN_SIZE]; struct cmdline_token_string_data { const char *str; }; struct cmdline_token_string { struct cmdline_token_hdr hdr; struct cmdline_token_string_data string_data; }; typedef struct cmdline_token_string cmdline_parse_token_string_t; extern struct cmdline_token_ops cmdline_token_string_ops; int cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *srcbuf, void *res, unsigned ressize); int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk); int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx, char *dstbuf, unsigned int size); int cmdline_get_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf, unsigned int size); #define TOKEN_STRING_INITIALIZER(structure, field, string) \ { \ /* hdr */ \ { \ &cmdline_token_string_ops, /* ops */ \ offsetof(structure, field), /* offset */ \ }, \ /* string_data */ \ { \ string, /* str */ \ }, \ } #ifdef __cplusplus } #endif #endif /* _PARSE_STRING_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_rdline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "cmdline_cirbuf.h" #include "cmdline_rdline.h" static void rdline_puts(struct rdline *rdl, const char *buf); static void rdline_miniprintf(struct rdline *rdl, const char *buf, unsigned int val); static void rdline_remove_old_history_item(struct rdline *rdl); static void rdline_remove_first_history_item(struct rdline *rdl); static unsigned int rdline_get_history_size(struct rdline *rdl); /* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our * own. */ static int isblank2(char c) { if (c == ' ' || c == '\t' ) return 1; return 0; } int rdline_init(struct rdline *rdl, rdline_write_char_t *write_char, rdline_validate_t *validate, rdline_complete_t *complete) { if (!rdl || !write_char || !validate || !complete) return -EINVAL; memset(rdl, 0, sizeof(*rdl)); rdl->validate = validate; rdl->complete = complete; rdl->write_char = write_char; rdl->status = RDLINE_INIT; return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); } void rdline_newline(struct rdline *rdl, const char *prompt) { unsigned int i; if (!rdl || !prompt) return; vt100_init(&rdl->vt100); cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1); if (prompt != rdl->prompt) memcpy(rdl->prompt, prompt, rdl->prompt_size); rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0'; for (i=0 ; iprompt_size ; i++) rdl->write_char(rdl, rdl->prompt[i]); rdl->status = RDLINE_RUNNING; rdl->history_cur_line = -1; } void rdline_stop(struct rdline *rdl) { if (!rdl) return; rdl->status = RDLINE_INIT; } void rdline_quit(struct rdline *rdl) { if (!rdl) return; rdl->status = RDLINE_EXITED; } void rdline_restart(struct rdline *rdl) { if (!rdl) return; rdl->status = RDLINE_RUNNING; } void rdline_reset(struct rdline *rdl) { if (!rdl) return; vt100_init(&rdl->vt100); cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); rdl->status = RDLINE_RUNNING; rdl->history_cur_line = -1; } const char * rdline_get_buffer(struct rdline *rdl) { if (!rdl) return NULL; unsigned int len_l, len_r; cirbuf_align_left(&rdl->left); cirbuf_align_left(&rdl->right); len_l = CIRBUF_GET_LEN(&rdl->left); len_r = CIRBUF_GET_LEN(&rdl->right); memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r); rdl->left_buf[len_l + len_r] = '\n'; rdl->left_buf[len_l + len_r + 1] = '\0'; return rdl->left_buf; } static void display_right_buffer(struct rdline *rdl, int force) { unsigned int i; char tmp; if (!force && CIRBUF_IS_EMPTY(&rdl->right)) return; rdline_puts(rdl, vt100_clear_right); CIRBUF_FOREACH(&rdl->right, i, tmp) { rdl->write_char(rdl, tmp); } if (!CIRBUF_IS_EMPTY(&rdl->right)) rdline_miniprintf(rdl, vt100_multi_left, CIRBUF_GET_LEN(&rdl->right)); } void rdline_redisplay(struct rdline *rdl) { unsigned int i; char tmp; if (!rdl) return; rdline_puts(rdl, vt100_home); for (i=0 ; iprompt_size ; i++) rdl->write_char(rdl, rdl->prompt[i]); CIRBUF_FOREACH(&rdl->left, i, tmp) { rdl->write_char(rdl, tmp); } display_right_buffer(rdl, 1); } int rdline_char_in(struct rdline *rdl, char c) { unsigned int i; int cmd; char tmp; char *buf; if (!rdl) return -EINVAL; if (rdl->status == RDLINE_EXITED) return RDLINE_RES_EXITED; if (rdl->status != RDLINE_RUNNING) return RDLINE_RES_NOT_RUNNING; cmd = vt100_parser(&rdl->vt100, c); if (cmd == -2) return RDLINE_RES_SUCCESS; if (cmd >= 0) { switch (cmd) { /* move caret 1 char to the left */ case CMDLINE_KEY_CTRL_B: case CMDLINE_KEY_LEFT_ARR: if (CIRBUF_IS_EMPTY(&rdl->left)) break; tmp = cirbuf_get_tail(&rdl->left); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); rdline_puts(rdl, vt100_left_arr); break; /* move caret 1 char to the right */ case CMDLINE_KEY_CTRL_F: case CMDLINE_KEY_RIGHT_ARR: if (CIRBUF_IS_EMPTY(&rdl->right)) break; tmp = cirbuf_get_head(&rdl->right); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); rdline_puts(rdl, vt100_right_arr); break; /* move caret 1 word to the left */ /* keyboard equivalent: Alt+B */ case CMDLINE_KEY_WLEFT: while (! CIRBUF_IS_EMPTY(&rdl->left) && (tmp = cirbuf_get_tail(&rdl->left)) && isblank2(tmp)) { rdline_puts(rdl, vt100_left_arr); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); } while (! CIRBUF_IS_EMPTY(&rdl->left) && (tmp = cirbuf_get_tail(&rdl->left)) && !isblank2(tmp)) { rdline_puts(rdl, vt100_left_arr); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); } break; /* move caret 1 word to the right */ /* keyboard equivalent: Alt+F */ case CMDLINE_KEY_WRIGHT: while (! CIRBUF_IS_EMPTY(&rdl->right) && (tmp = cirbuf_get_head(&rdl->right)) && isblank2(tmp)) { rdline_puts(rdl, vt100_right_arr); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); } while (! CIRBUF_IS_EMPTY(&rdl->right) && (tmp = cirbuf_get_head(&rdl->right)) && !isblank2(tmp)) { rdline_puts(rdl, vt100_right_arr); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); } break; /* move caret to the left */ case CMDLINE_KEY_CTRL_A: if (CIRBUF_IS_EMPTY(&rdl->left)) break; rdline_miniprintf(rdl, vt100_multi_left, CIRBUF_GET_LEN(&rdl->left)); while (! CIRBUF_IS_EMPTY(&rdl->left)) { tmp = cirbuf_get_tail(&rdl->left); cirbuf_del_tail(&rdl->left); cirbuf_add_head(&rdl->right, tmp); } break; /* move caret to the right */ case CMDLINE_KEY_CTRL_E: if (CIRBUF_IS_EMPTY(&rdl->right)) break; rdline_miniprintf(rdl, vt100_multi_right, CIRBUF_GET_LEN(&rdl->right)); while (! CIRBUF_IS_EMPTY(&rdl->right)) { tmp = cirbuf_get_head(&rdl->right); cirbuf_del_head(&rdl->right); cirbuf_add_tail(&rdl->left, tmp); } break; /* delete 1 char from the left */ case CMDLINE_KEY_BKSPACE: if(!cirbuf_del_tail_safe(&rdl->left)) { rdline_puts(rdl, vt100_bs); display_right_buffer(rdl, 1); } break; /* delete 1 char from the right */ case CMDLINE_KEY_SUPPR: case CMDLINE_KEY_CTRL_D: if (cmd == CMDLINE_KEY_CTRL_D && CIRBUF_IS_EMPTY(&rdl->left) && CIRBUF_IS_EMPTY(&rdl->right)) { return RDLINE_RES_EOF; } if (!cirbuf_del_head_safe(&rdl->right)) { display_right_buffer(rdl, 1); } break; /* delete 1 word from the left */ case CMDLINE_KEY_META_BKSPACE: case CMDLINE_KEY_CTRL_W: while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) { rdline_puts(rdl, vt100_bs); cirbuf_del_tail(&rdl->left); } while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) { rdline_puts(rdl, vt100_bs); cirbuf_del_tail(&rdl->left); } display_right_buffer(rdl, 1); break; /* delete 1 word from the right */ case CMDLINE_KEY_META_D: while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right))) cirbuf_del_head(&rdl->right); while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right))) cirbuf_del_head(&rdl->right); display_right_buffer(rdl, 1); break; /* set kill buffer to contents on the right side of caret */ case CMDLINE_KEY_CTRL_K: cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE); rdl->kill_size = CIRBUF_GET_LEN(&rdl->right); cirbuf_del_buf_head(&rdl->right, rdl->kill_size); rdline_puts(rdl, vt100_clear_right); break; /* paste contents of kill buffer to the left side of caret */ case CMDLINE_KEY_CTRL_Y: i=0; while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < RDLINE_BUF_SIZE && i < rdl->kill_size) { cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]); rdl->write_char(rdl, rdl->kill_buf[i]); i++; } display_right_buffer(rdl, 0); break; /* clear and newline */ case CMDLINE_KEY_CTRL_C: rdline_puts(rdl, "\r\n"); rdline_newline(rdl, rdl->prompt); break; /* redisplay (helps when prompt is lost in other output) */ case CMDLINE_KEY_CTRL_L: rdline_redisplay(rdl); break; /* autocomplete */ case CMDLINE_KEY_TAB: case CMDLINE_KEY_HELP: cirbuf_align_left(&rdl->left); rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0'; if (rdl->complete) { char tmp_buf[BUFSIZ]; int complete_state; int ret; unsigned int tmp_size; if (cmd == CMDLINE_KEY_TAB) complete_state = 0; else complete_state = -1; /* see in parse.h for help on complete() */ ret = rdl->complete(rdl, rdl->left_buf, tmp_buf, sizeof(tmp_buf), &complete_state); /* no completion or error */ if (ret <= 0) { return RDLINE_RES_COMPLETE; } tmp_size = strnlen(tmp_buf, sizeof(tmp_buf)); /* add chars */ if (ret == RDLINE_RES_COMPLETE) { i=0; while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) < RDLINE_BUF_SIZE && i < tmp_size) { cirbuf_add_tail(&rdl->left, tmp_buf[i]); rdl->write_char(rdl, tmp_buf[i]); i++; } display_right_buffer(rdl, 1); return RDLINE_RES_COMPLETE; /* ?? */ } /* choice */ rdline_puts(rdl, "\r\n"); while (ret) { rdl->write_char(rdl, ' '); for (i=0 ; tmp_buf[i] ; i++) rdl->write_char(rdl, tmp_buf[i]); rdline_puts(rdl, "\r\n"); ret = rdl->complete(rdl, rdl->left_buf, tmp_buf, sizeof(tmp_buf), &complete_state); } rdline_redisplay(rdl); } return RDLINE_RES_COMPLETE; /* complete buffer */ case CMDLINE_KEY_RETURN: case CMDLINE_KEY_RETURN2: rdline_get_buffer(rdl); rdl->status = RDLINE_INIT; rdline_puts(rdl, "\r\n"); if (rdl->history_cur_line != -1) rdline_remove_first_history_item(rdl); if (rdl->validate) rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2); /* user may have stopped rdline */ if (rdl->status == RDLINE_EXITED) return RDLINE_RES_EXITED; return RDLINE_RES_VALIDATED; /* previous element in history */ case CMDLINE_KEY_UP_ARR: case CMDLINE_KEY_CTRL_P: if (rdl->history_cur_line == 0) { rdline_remove_first_history_item(rdl); } if (rdl->history_cur_line <= 0) { rdline_add_history(rdl, rdline_get_buffer(rdl)); rdl->history_cur_line = 0; } buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1); if (!buf) break; rdl->history_cur_line ++; vt100_init(&rdl->vt100); cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); rdline_redisplay(rdl); break; /* next element in history */ case CMDLINE_KEY_DOWN_ARR: case CMDLINE_KEY_CTRL_N: if (rdl->history_cur_line - 1 < 0) break; rdl->history_cur_line --; buf = rdline_get_history_item(rdl, rdl->history_cur_line); if (!buf) break; vt100_init(&rdl->vt100); cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE); cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE); cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE)); rdline_redisplay(rdl); break; default: break; } return RDLINE_RES_SUCCESS; } if (!isprint((int)c)) return RDLINE_RES_SUCCESS; /* standard chars */ if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE) return RDLINE_RES_SUCCESS; if (cirbuf_add_tail_safe(&rdl->left, c)) return RDLINE_RES_SUCCESS; rdl->write_char(rdl, c); display_right_buffer(rdl, 0); return RDLINE_RES_SUCCESS; } /* HISTORY */ static void rdline_remove_old_history_item(struct rdline * rdl) { char tmp; while (! CIRBUF_IS_EMPTY(&rdl->history) ) { tmp = cirbuf_get_head(&rdl->history); cirbuf_del_head(&rdl->history); if (!tmp) break; } } static void rdline_remove_first_history_item(struct rdline * rdl) { char tmp; if ( CIRBUF_IS_EMPTY(&rdl->history) ) { return; } else { cirbuf_del_tail(&rdl->history); } while (! CIRBUF_IS_EMPTY(&rdl->history) ) { tmp = cirbuf_get_tail(&rdl->history); if (!tmp) break; cirbuf_del_tail(&rdl->history); } } static unsigned int rdline_get_history_size(struct rdline * rdl) { unsigned int i, tmp, ret=0; CIRBUF_FOREACH(&rdl->history, i, tmp) { if (tmp == 0) ret ++; } return ret; } char * rdline_get_history_item(struct rdline * rdl, unsigned int idx) { unsigned int len, i, tmp; if (!rdl) return NULL; len = rdline_get_history_size(rdl); if ( idx >= len ) { return NULL; } cirbuf_align_left(&rdl->history); CIRBUF_FOREACH(&rdl->history, i, tmp) { if ( idx == len - 1) { return rdl->history_buf + i; } if (tmp == 0) len --; } return NULL; } int rdline_add_history(struct rdline * rdl, const char * buf) { unsigned int len, i; if (!rdl || !buf) return -EINVAL; len = strnlen(buf, RDLINE_BUF_SIZE); for (i=0; i= RDLINE_HISTORY_BUF_SIZE ) return -1; while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) { rdline_remove_old_history_item(rdl); } cirbuf_add_buf_tail(&rdl->history, buf, len); cirbuf_add_tail(&rdl->history, 0); return 0; } void rdline_clear_history(struct rdline * rdl) { if (!rdl) return; cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE); } /* STATIC USEFUL FUNCS */ static void rdline_puts(struct rdline * rdl, const char * buf) { char c; while ( (c = *(buf++)) != '\0' ) { rdl->write_char(rdl, c); } } /* a very very basic printf with one arg and one format 'u' */ static void rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val) { char c, started=0, div=100; while ( (c=*(buf++)) ) { if (c != '%') { rdl->write_char(rdl, c); continue; } c = *(buf++); if (c != 'u') { rdl->write_char(rdl, '%'); rdl->write_char(rdl, c); continue; } /* val is never more than 255 */ while (div) { c = (char)(val / div); if (c || started) { rdl->write_char(rdl, (char)(c+'0')); started = 1; } val %= div; div /= 10; } } } ================================================ FILE: lib/librte_cmdline/cmdline_rdline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RDLINE_H_ #define _RDLINE_H_ /** * This file is a small equivalent to the GNU readline library, but it * was originally designed for small systems, like Atmel AVR * microcontrollers (8 bits). Indeed, we don't use any malloc that is * sometimes not implemented (or just not recommended) on such * systems. * * Obviously, it does not support as many things as the GNU readline, * but at least it supports some interesting features like a kill * buffer and a command history. * * It also have a feature that does not have the GNU readline (as far * as I know): we can have several instances of it running at the same * time, even on a monothread program, since it works with callbacks. * * The lib is designed for a client-side or a server-side use: * - server-side: the server receives all data from a socket, including * control chars, like arrows, tabulations, ... The client is * very simple, it can be a telnet or a minicom through a serial line. * - client-side: the client receives its data through its stdin for * instance. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* configuration */ #define RDLINE_BUF_SIZE 256 #define RDLINE_PROMPT_SIZE 32 #define RDLINE_VT100_BUF_SIZE 8 #define RDLINE_HISTORY_BUF_SIZE BUFSIZ #define RDLINE_HISTORY_MAX_LINE 64 enum rdline_status { RDLINE_INIT, RDLINE_RUNNING, RDLINE_EXITED }; struct rdline; typedef int (rdline_write_char_t)(struct rdline *rdl, char); typedef void (rdline_validate_t)(struct rdline *rdl, const char *buf, unsigned int size); typedef int (rdline_complete_t)(struct rdline *rdl, const char *buf, char *dstbuf, unsigned int dstsize, int *state); struct rdline { enum rdline_status status; /* rdline bufs */ struct cirbuf left; struct cirbuf right; char left_buf[RDLINE_BUF_SIZE+2]; /* reserve 2 chars for the \n\0 */ char right_buf[RDLINE_BUF_SIZE]; char prompt[RDLINE_PROMPT_SIZE]; unsigned int prompt_size; char kill_buf[RDLINE_BUF_SIZE]; unsigned int kill_size; /* history */ struct cirbuf history; char history_buf[RDLINE_HISTORY_BUF_SIZE]; int history_cur_line; /* callbacks and func pointers */ rdline_write_char_t *write_char; rdline_validate_t *validate; rdline_complete_t *complete; /* vt100 parser */ struct cmdline_vt100 vt100; /* opaque pointer */ void *opaque; }; /** * Init fields for a struct rdline. Call this only once at the beginning * of your program. * \param rdl A pointer to an uninitialized struct rdline * \param write_char The function used by the function to write a character * \param validate A pointer to the function to execute when the * user validates the buffer. * \param complete A pointer to the function to execute when the * user completes the buffer. */ int rdline_init(struct rdline *rdl, rdline_write_char_t *write_char, rdline_validate_t *validate, rdline_complete_t *complete); /** * Init the current buffer, and display a prompt. * \param rdl A pointer to a struct rdline * \param prompt A string containing the prompt */ void rdline_newline(struct rdline *rdl, const char *prompt); /** * Call it and all received chars will be ignored. * \param rdl A pointer to a struct rdline */ void rdline_stop(struct rdline *rdl); /** * Same than rdline_stop() except that next calls to rdline_char_in() * will return RDLINE_RES_EXITED. * \param rdl A pointer to a struct rdline */ void rdline_quit(struct rdline *rdl); /** * Restart after a call to rdline_stop() or rdline_quit() * \param rdl A pointer to a struct rdline */ void rdline_restart(struct rdline *rdl); /** * Redisplay the current buffer * \param rdl A pointer to a struct rdline */ void rdline_redisplay(struct rdline *rdl); /** * Reset the current buffer and setup for a new line. * \param rdl A pointer to a struct rdline */ void rdline_reset(struct rdline *rdl); /* return status for rdline_char_in() */ #define RDLINE_RES_SUCCESS 0 #define RDLINE_RES_VALIDATED 1 #define RDLINE_RES_COMPLETE 2 #define RDLINE_RES_NOT_RUNNING -1 #define RDLINE_RES_EOF -2 #define RDLINE_RES_EXITED -3 /** * append a char to the readline buffer. * Return RDLINE_RES_VALIDATE when the line has been validated. * Return RDLINE_RES_COMPLETE when the user asked to complete the buffer. * Return RDLINE_RES_NOT_RUNNING if it is not running. * Return RDLINE_RES_EOF if EOF (ctrl-d on an empty line). * Else return RDLINE_RES_SUCCESS. * XXX error case when the buffer is full ? * * \param rdl A pointer to a struct rdline * \param c The character to append */ int rdline_char_in(struct rdline *rdl, char c); /** * Return the current buffer, terminated by '\0'. * \param rdl A pointer to a struct rdline */ const char *rdline_get_buffer(struct rdline *rdl); /** * Add the buffer to history. * return < 0 on error. * \param rdl A pointer to a struct rdline * \param buf A buffer that is terminated by '\0' */ int rdline_add_history(struct rdline *rdl, const char *buf); /** * Clear current history * \param rdl A pointer to a struct rdline */ void rdline_clear_history(struct rdline *rdl); /** * Get the i-th history item */ char *rdline_get_history_item(struct rdline *rdl, unsigned int i); #ifdef __cplusplus } #endif #endif /* _RDLINE_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_socket.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "cmdline_parse.h" #include "cmdline_rdline.h" #include "cmdline_socket.h" #include "cmdline.h" struct cmdline * cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path) { int fd; /* everything else is checked in cmdline_new() */ if (!path) return NULL; fd = open(path, O_RDONLY, 0); if (fd < 0) { dprintf("open() failed\n"); return NULL; } return cmdline_new(ctx, prompt, fd, -1); } struct cmdline * cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt) { struct cmdline *cl; struct termios oldterm, term; tcgetattr(0, &oldterm); memcpy(&term, &oldterm, sizeof(term)); term.c_lflag &= ~(ICANON | ECHO | ISIG); tcsetattr(0, TCSANOW, &term); setbuf(stdin, NULL); cl = cmdline_new(ctx, prompt, 0, 1); if (cl) memcpy(&cl->oldterm, &oldterm, sizeof(term)); return cl; } void cmdline_stdin_exit(struct cmdline *cl) { if (!cl) return; tcsetattr(fileno(stdin), TCSANOW, &cl->oldterm); } ================================================ FILE: lib/librte_cmdline/cmdline_socket.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CMDLINE_SOCKET_H_ #define _CMDLINE_SOCKET_H_ #ifdef __cplusplus extern "C" { #endif struct cmdline *cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path); struct cmdline *cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt); void cmdline_stdin_exit(struct cmdline *cl); #ifdef __cplusplus } #endif #endif /* _CMDLINE_SOCKET_H_ */ ================================================ FILE: lib/librte_cmdline/cmdline_vt100.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "cmdline_vt100.h" const char *cmdline_vt100_commands[] = { vt100_up_arr, vt100_down_arr, vt100_right_arr, vt100_left_arr, "\177", "\n", "\001", "\005", "\013", "\031", "\003", "\006", "\002", vt100_suppr, vt100_tab, "\004", "\014", "\r", "\033\177", vt100_word_left, vt100_word_right, "?", "\027", "\020", "\016", "\033\144", }; void vt100_init(struct cmdline_vt100 *vt) { if (!vt) return; vt->state = CMDLINE_VT100_INIT; } static int match_command(char *buf, unsigned int size) { const char *cmd; size_t cmdlen; unsigned int i = 0; for (i=0 ; ibufpos >= CMDLINE_VT100_BUF_SIZE) { vt->state = CMDLINE_VT100_INIT; vt->bufpos = 0; } vt->buf[vt->bufpos++] = c; size = vt->bufpos; switch (vt->state) { case CMDLINE_VT100_INIT: if (c == 033) { vt->state = CMDLINE_VT100_ESCAPE; } else { vt->bufpos = 0; goto match_command; } break; case CMDLINE_VT100_ESCAPE: if (c == 0133) { vt->state = CMDLINE_VT100_ESCAPE_CSI; } else if (c >= 060 && c <= 0177) { /* XXX 0177 ? */ vt->bufpos = 0; vt->state = CMDLINE_VT100_INIT; goto match_command; } break; case CMDLINE_VT100_ESCAPE_CSI: if (c >= 0100 && c <= 0176) { vt->bufpos = 0; vt->state = CMDLINE_VT100_INIT; goto match_command; } break; default: vt->bufpos = 0; break; } return -2; match_command: return match_command(vt->buf, size); } ================================================ FILE: lib/librte_cmdline/cmdline_vt100.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2009, Olivier MATZ * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _CMDLINE_VT100_H_ #define _CMDLINE_VT100_H_ #include #ifdef __cplusplus extern "C" { #endif #define vt100_bell "\007" #define vt100_bs "\010" #define vt100_bs_clear "\010 \010" #define vt100_tab "\011" #define vt100_crnl "\012\015" #define vt100_clear_right "\033[0K" #define vt100_clear_left "\033[1K" #define vt100_clear_down "\033[0J" #define vt100_clear_up "\033[1J" #define vt100_clear_line "\033[2K" #define vt100_clear_screen "\033[2J" #define vt100_up_arr "\033\133\101" #define vt100_down_arr "\033\133\102" #define vt100_right_arr "\033\133\103" #define vt100_left_arr "\033\133\104" #define vt100_multi_right "\033\133%uC" #define vt100_multi_left "\033\133%uD" #define vt100_suppr "\033\133\063\176" #define vt100_home "\033M\033E" #define vt100_word_left "\033\142" #define vt100_word_right "\033\146" /* Result of parsing : it must be synchronized with * cmdline_vt100_commands[] in vt100.c */ #define CMDLINE_KEY_UP_ARR 0 #define CMDLINE_KEY_DOWN_ARR 1 #define CMDLINE_KEY_RIGHT_ARR 2 #define CMDLINE_KEY_LEFT_ARR 3 #define CMDLINE_KEY_BKSPACE 4 #define CMDLINE_KEY_RETURN 5 #define CMDLINE_KEY_CTRL_A 6 #define CMDLINE_KEY_CTRL_E 7 #define CMDLINE_KEY_CTRL_K 8 #define CMDLINE_KEY_CTRL_Y 9 #define CMDLINE_KEY_CTRL_C 10 #define CMDLINE_KEY_CTRL_F 11 #define CMDLINE_KEY_CTRL_B 12 #define CMDLINE_KEY_SUPPR 13 #define CMDLINE_KEY_TAB 14 #define CMDLINE_KEY_CTRL_D 15 #define CMDLINE_KEY_CTRL_L 16 #define CMDLINE_KEY_RETURN2 17 #define CMDLINE_KEY_META_BKSPACE 18 #define CMDLINE_KEY_WLEFT 19 #define CMDLINE_KEY_WRIGHT 20 #define CMDLINE_KEY_HELP 21 #define CMDLINE_KEY_CTRL_W 22 #define CMDLINE_KEY_CTRL_P 23 #define CMDLINE_KEY_CTRL_N 24 #define CMDLINE_KEY_META_D 25 extern const char *cmdline_vt100_commands[]; enum cmdline_vt100_parser_state { CMDLINE_VT100_INIT, CMDLINE_VT100_ESCAPE, CMDLINE_VT100_ESCAPE_CSI }; #define CMDLINE_VT100_BUF_SIZE 8 struct cmdline_vt100 { uint8_t bufpos; char buf[CMDLINE_VT100_BUF_SIZE]; enum cmdline_vt100_parser_state state; }; /** * Init */ void vt100_init(struct cmdline_vt100 *vt); /** * Input a new character. * Return -1 if the character is not part of a control sequence * Return -2 if c is not the last char of a control sequence * Else return the index in vt100_commands[] */ int vt100_parser(struct cmdline_vt100 *vt, char c); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_compat/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2013 Neil Horman # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk LIBABIVER := 1 # install includes SYMLINK-y-include := rte_compat.h include $(RTE_SDK)/mk/rte.install.mk ================================================ FILE: lib/librte_compat/rte_compat.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Neil Horman . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_COMPAT_H_ #define _RTE_COMPAT_H_ #include #ifdef RTE_BUILD_SHARED_LIB /* * Provides backwards compatibility when updating exported functions. * When a symol is exported from a library to provide an API, it also provides a * calling convention (ABI) that is embodied in its name, return type, * arguments, etc. On occasion that function may need to change to accommodate * new functionality, behavior, etc. When that occurs, it is desireable to * allow for backwards compatibility for a time with older binaries that are * dynamically linked to the dpdk. To support that, the __vsym and * VERSION_SYMBOL macros are created. They, in conjunction with the * _version.map file for a given library allow for multiple versions of * a symbol to exist in a shared library so that older binaries need not be * immediately recompiled. * * Refer to the guidelines document in the docs subdirectory for details on the * use of these macros */ /* * Macro Parameters: * b - function base name * e - function version extension, to be concatenated with base name * n - function symbol version string to be applied * f - function prototype * p - full function symbol name */ /* * VERSION_SYMBOL * Creates a symbol version table entry binding symbol @DPDK_ to the internal * function name _ */ #define VERSION_SYMBOL(b, e, n) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b) "@DPDK_" RTE_STR(n)) /* * BIND_DEFAULT_SYMBOL * Creates a symbol version entry instructing the linker to bind references to * symbol to the internal symbol _ */ #define BIND_DEFAULT_SYMBOL(b, e, n) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b) "@@DPDK_" RTE_STR(n)) #define __vsym __attribute__((used)) /* * MAP_STATIC_SYMBOL * If a function has been bifurcated into multiple versions, none of which * are defined as the exported symbol name in the map file, this macro can be * used to alias a specific version of the symbol to its exported name. For * example, if you have 2 versions of a function foo_v1 and foo_v2, where the * former is mapped to foo@DPDK_1 and the latter is mapped to foo@DPDK_2 when * building a shared library, this macro can be used to map either foo_v1 or * foo_v2 to the symbol foo when building a static library, e.g.: * MAP_STATIC_SYMBOL(void foo(), foo_v2); */ #define MAP_STATIC_SYMBOL(f, p) #else /* * No symbol versioning in use */ #define VERSION_SYMBOL(b, e, n) #define __vsym #define BIND_DEFAULT_SYMBOL(b, e, n) #define MAP_STATIC_SYMBOL(f, p) f __attribute__((alias(RTE_STR(p)))) /* * RTE_BUILD_SHARED_LIB=n */ #endif #endif /* _RTE_COMPAT_H_ */ ================================================ FILE: lib/librte_distributor/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_distributor.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_distributor_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) := rte_distributor.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR)-include := rte_distributor.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += lib/librte_mbuf include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_distributor/rte_distributor.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "rte_distributor.h" #define NO_FLAGS 0 #define RTE_DISTRIB_PREFIX "DT_" /* we will use the bottom four bits of pointer for flags, shifting out * the top four bits to make room (since a 64-bit pointer actually only uses * 48 bits). An arithmetic-right-shift will then appropriately restore the * original pointer value with proper sign extension into the top bits. */ #define RTE_DISTRIB_FLAG_BITS 4 #define RTE_DISTRIB_FLAGS_MASK (0x0F) #define RTE_DISTRIB_NO_BUF 0 /**< empty flags: no buffer requested */ #define RTE_DISTRIB_GET_BUF (1) /**< worker requests a buffer, returns old */ #define RTE_DISTRIB_RETURN_BUF (2) /**< worker returns a buffer, no request */ #define RTE_DISTRIB_BACKLOG_SIZE 8 #define RTE_DISTRIB_BACKLOG_MASK (RTE_DISTRIB_BACKLOG_SIZE - 1) #define RTE_DISTRIB_MAX_RETURNS 128 #define RTE_DISTRIB_RETURNS_MASK (RTE_DISTRIB_MAX_RETURNS - 1) /** * Maximum number of workers allowed. * Be aware of increasing the limit, becaus it is limited by how we track * in-flight tags. See @in_flight_bitmask and @rte_distributor_process */ #define RTE_DISTRIB_MAX_WORKERS 64 /** * Buffer structure used to pass the pointer data between cores. This is cache * line aligned, but to improve performance and prevent adjacent cache-line * prefetches of buffers for other workers, e.g. when worker 1's buffer is on * the next cache line to worker 0, we pad this out to three cache lines. * Only 64-bits of the memory is actually used though. */ union rte_distributor_buffer { volatile int64_t bufptr64; char pad[RTE_CACHE_LINE_SIZE*3]; } __rte_cache_aligned; struct rte_distributor_backlog { unsigned start; unsigned count; int64_t pkts[RTE_DISTRIB_BACKLOG_SIZE]; }; struct rte_distributor_returned_pkts { unsigned start; unsigned count; struct rte_mbuf *mbufs[RTE_DISTRIB_MAX_RETURNS]; }; struct rte_distributor { TAILQ_ENTRY(rte_distributor) next; /**< Next in list. */ char name[RTE_DISTRIBUTOR_NAMESIZE]; /**< Name of the ring. */ unsigned num_workers; /**< Number of workers polling */ uint32_t in_flight_tags[RTE_DISTRIB_MAX_WORKERS]; /**< Tracks the tag being processed per core */ uint64_t in_flight_bitmask; /**< on/off bits for in-flight tags. * Note that if RTE_DISTRIB_MAX_WORKERS is larger than 64 then * the bitmask has to expand. */ struct rte_distributor_backlog backlog[RTE_DISTRIB_MAX_WORKERS]; union rte_distributor_buffer bufs[RTE_DISTRIB_MAX_WORKERS]; struct rte_distributor_returned_pkts returns; }; TAILQ_HEAD(rte_distributor_list, rte_distributor); static struct rte_tailq_elem rte_distributor_tailq = { .name = "RTE_DISTRIBUTOR", }; EAL_REGISTER_TAILQ(rte_distributor_tailq) /**** APIs called by workers ****/ void rte_distributor_request_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *oldpkt) { union rte_distributor_buffer *buf = &d->bufs[worker_id]; int64_t req = (((int64_t)(uintptr_t)oldpkt) << RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_GET_BUF; while (unlikely(buf->bufptr64 & RTE_DISTRIB_FLAGS_MASK)) rte_pause(); buf->bufptr64 = req; } struct rte_mbuf * rte_distributor_poll_pkt(struct rte_distributor *d, unsigned worker_id) { union rte_distributor_buffer *buf = &d->bufs[worker_id]; if (buf->bufptr64 & RTE_DISTRIB_GET_BUF) return NULL; /* since bufptr64 is signed, this should be an arithmetic shift */ int64_t ret = buf->bufptr64 >> RTE_DISTRIB_FLAG_BITS; return (struct rte_mbuf *)((uintptr_t)ret); } struct rte_mbuf * rte_distributor_get_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *oldpkt) { struct rte_mbuf *ret; rte_distributor_request_pkt(d, worker_id, oldpkt); while ((ret = rte_distributor_poll_pkt(d, worker_id)) == NULL) rte_pause(); return ret; } int rte_distributor_return_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *oldpkt) { union rte_distributor_buffer *buf = &d->bufs[worker_id]; uint64_t req = (((int64_t)(uintptr_t)oldpkt) << RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_RETURN_BUF; buf->bufptr64 = req; return 0; } /**** APIs called on distributor core ***/ /* as name suggests, adds a packet to the backlog for a particular worker */ static int add_to_backlog(struct rte_distributor_backlog *bl, int64_t item) { if (bl->count == RTE_DISTRIB_BACKLOG_SIZE) return -1; bl->pkts[(bl->start + bl->count++) & (RTE_DISTRIB_BACKLOG_MASK)] = item; return 0; } /* takes the next packet for a worker off the backlog */ static int64_t backlog_pop(struct rte_distributor_backlog *bl) { bl->count--; return bl->pkts[bl->start++ & RTE_DISTRIB_BACKLOG_MASK]; } /* stores a packet returned from a worker inside the returns array */ static inline void store_return(uintptr_t oldbuf, struct rte_distributor *d, unsigned *ret_start, unsigned *ret_count) { /* store returns in a circular buffer - code is branch-free */ d->returns.mbufs[(*ret_start + *ret_count) & RTE_DISTRIB_RETURNS_MASK] = (void *)oldbuf; *ret_start += (*ret_count == RTE_DISTRIB_RETURNS_MASK) & !!(oldbuf); *ret_count += (*ret_count != RTE_DISTRIB_RETURNS_MASK) & !!(oldbuf); } static inline void handle_worker_shutdown(struct rte_distributor *d, unsigned wkr) { d->in_flight_tags[wkr] = 0; d->in_flight_bitmask &= ~(1UL << wkr); d->bufs[wkr].bufptr64 = 0; if (unlikely(d->backlog[wkr].count != 0)) { /* On return of a packet, we need to move the * queued packets for this core elsewhere. * Easiest solution is to set things up for * a recursive call. That will cause those * packets to be queued up for the next free * core, i.e. it will return as soon as a * core becomes free to accept the first * packet, as subsequent ones will be added to * the backlog for that core. */ struct rte_mbuf *pkts[RTE_DISTRIB_BACKLOG_SIZE]; unsigned i; struct rte_distributor_backlog *bl = &d->backlog[wkr]; for (i = 0; i < bl->count; i++) { unsigned idx = (bl->start + i) & RTE_DISTRIB_BACKLOG_MASK; pkts[i] = (void *)((uintptr_t)(bl->pkts[idx] >> RTE_DISTRIB_FLAG_BITS)); } /* recursive call. * Note that the tags were set before first level call * to rte_distributor_process. */ rte_distributor_process(d, pkts, i); bl->count = bl->start = 0; } } /* this function is called when process() fn is called without any new * packets. It goes through all the workers and clears any returned packets * to do a partial flush. */ static int process_returns(struct rte_distributor *d) { unsigned wkr; unsigned flushed = 0; unsigned ret_start = d->returns.start, ret_count = d->returns.count; for (wkr = 0; wkr < d->num_workers; wkr++) { const int64_t data = d->bufs[wkr].bufptr64; uintptr_t oldbuf = 0; if (data & RTE_DISTRIB_GET_BUF) { flushed++; if (d->backlog[wkr].count) d->bufs[wkr].bufptr64 = backlog_pop(&d->backlog[wkr]); else { d->bufs[wkr].bufptr64 = RTE_DISTRIB_GET_BUF; d->in_flight_tags[wkr] = 0; d->in_flight_bitmask &= ~(1UL << wkr); } oldbuf = data >> RTE_DISTRIB_FLAG_BITS; } else if (data & RTE_DISTRIB_RETURN_BUF) { handle_worker_shutdown(d, wkr); oldbuf = data >> RTE_DISTRIB_FLAG_BITS; } store_return(oldbuf, d, &ret_start, &ret_count); } d->returns.start = ret_start; d->returns.count = ret_count; return flushed; } /* process a set of packets to distribute them to workers */ int rte_distributor_process(struct rte_distributor *d, struct rte_mbuf **mbufs, unsigned num_mbufs) { unsigned next_idx = 0; unsigned wkr = 0; struct rte_mbuf *next_mb = NULL; int64_t next_value = 0; uint32_t new_tag = 0; unsigned ret_start = d->returns.start, ret_count = d->returns.count; if (unlikely(num_mbufs == 0)) return process_returns(d); while (next_idx < num_mbufs || next_mb != NULL) { int64_t data = d->bufs[wkr].bufptr64; uintptr_t oldbuf = 0; if (!next_mb) { next_mb = mbufs[next_idx++]; next_value = (((int64_t)(uintptr_t)next_mb) << RTE_DISTRIB_FLAG_BITS); /* * User is advocated to set tag vaue for each * mbuf before calling rte_distributor_process. * User defined tags are used to identify flows, * or sessions. */ new_tag = next_mb->hash.usr; /* * Note that if RTE_DISTRIB_MAX_WORKERS is larger than 64 * then the size of match has to be expanded. */ uint64_t match = 0; unsigned i; /* * to scan for a match use "xor" and "not" to get a 0/1 * value, then use shifting to merge to single "match" * variable, where a one-bit indicates a match for the * worker given by the bit-position */ for (i = 0; i < d->num_workers; i++) match |= (!(d->in_flight_tags[i] ^ new_tag) << i); /* Only turned-on bits are considered as match */ match &= d->in_flight_bitmask; if (match) { next_mb = NULL; unsigned worker = __builtin_ctzl(match); if (add_to_backlog(&d->backlog[worker], next_value) < 0) next_idx--; } } if ((data & RTE_DISTRIB_GET_BUF) && (d->backlog[wkr].count || next_mb)) { if (d->backlog[wkr].count) d->bufs[wkr].bufptr64 = backlog_pop(&d->backlog[wkr]); else { d->bufs[wkr].bufptr64 = next_value; d->in_flight_tags[wkr] = new_tag; d->in_flight_bitmask |= (1UL << wkr); next_mb = NULL; } oldbuf = data >> RTE_DISTRIB_FLAG_BITS; } else if (data & RTE_DISTRIB_RETURN_BUF) { handle_worker_shutdown(d, wkr); oldbuf = data >> RTE_DISTRIB_FLAG_BITS; } /* store returns in a circular buffer */ store_return(oldbuf, d, &ret_start, &ret_count); if (++wkr == d->num_workers) wkr = 0; } /* to finish, check all workers for backlog and schedule work for them * if they are ready */ for (wkr = 0; wkr < d->num_workers; wkr++) if (d->backlog[wkr].count && (d->bufs[wkr].bufptr64 & RTE_DISTRIB_GET_BUF)) { int64_t oldbuf = d->bufs[wkr].bufptr64 >> RTE_DISTRIB_FLAG_BITS; store_return(oldbuf, d, &ret_start, &ret_count); d->bufs[wkr].bufptr64 = backlog_pop(&d->backlog[wkr]); } d->returns.start = ret_start; d->returns.count = ret_count; return num_mbufs; } /* return to the caller, packets returned from workers */ int rte_distributor_returned_pkts(struct rte_distributor *d, struct rte_mbuf **mbufs, unsigned max_mbufs) { struct rte_distributor_returned_pkts *returns = &d->returns; unsigned retval = (max_mbufs < returns->count) ? max_mbufs : returns->count; unsigned i; for (i = 0; i < retval; i++) { unsigned idx = (returns->start + i) & RTE_DISTRIB_RETURNS_MASK; mbufs[i] = returns->mbufs[idx]; } returns->start += i; returns->count -= i; return retval; } /* return the number of packets in-flight in a distributor, i.e. packets * being workered on or queued up in a backlog. */ static inline unsigned total_outstanding(const struct rte_distributor *d) { unsigned wkr, total_outstanding; total_outstanding = __builtin_popcountl(d->in_flight_bitmask); for (wkr = 0; wkr < d->num_workers; wkr++) total_outstanding += d->backlog[wkr].count; return total_outstanding; } /* flush the distributor, so that there are no outstanding packets in flight or * queued up. */ int rte_distributor_flush(struct rte_distributor *d) { const unsigned flushed = total_outstanding(d); while (total_outstanding(d) > 0) rte_distributor_process(d, NULL, 0); return flushed; } /* clears the internal returns array in the distributor */ void rte_distributor_clear_returns(struct rte_distributor *d) { d->returns.start = d->returns.count = 0; #ifndef __OPTIMIZE__ memset(d->returns.mbufs, 0, sizeof(d->returns.mbufs)); #endif } /* creates a distributor instance */ struct rte_distributor * rte_distributor_create(const char *name, unsigned socket_id, unsigned num_workers) { struct rte_distributor *d; struct rte_distributor_list *distributor_list; char mz_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; /* compilation-time checks */ RTE_BUILD_BUG_ON((sizeof(*d) & RTE_CACHE_LINE_MASK) != 0); RTE_BUILD_BUG_ON((RTE_DISTRIB_MAX_WORKERS & 7) != 0); RTE_BUILD_BUG_ON(RTE_DISTRIB_MAX_WORKERS > sizeof(d->in_flight_bitmask) * CHAR_BIT); if (name == NULL || num_workers >= RTE_DISTRIB_MAX_WORKERS) { rte_errno = EINVAL; return NULL; } snprintf(mz_name, sizeof(mz_name), RTE_DISTRIB_PREFIX"%s", name); mz = rte_memzone_reserve(mz_name, sizeof(*d), socket_id, NO_FLAGS); if (mz == NULL) { rte_errno = ENOMEM; return NULL; } d = mz->addr; snprintf(d->name, sizeof(d->name), "%s", name); d->num_workers = num_workers; distributor_list = RTE_TAILQ_CAST(rte_distributor_tailq.head, rte_distributor_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_INSERT_TAIL(distributor_list, d, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return d; } ================================================ FILE: lib/librte_distributor/rte_distributor.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_DISTRIBUTE_H_ #define _RTE_DISTRIBUTE_H_ /** * @file * RTE distributor * * The distributor is a component which is designed to pass packets * one-at-a-time to workers, with dynamic load balancing. */ #ifdef __cplusplus extern "C" { #endif #define RTE_DISTRIBUTOR_NAMESIZE 32 /**< Length of name for instance */ struct rte_distributor; struct rte_mbuf; /** * Function to create a new distributor instance * * Reserves the memory needed for the distributor operation and * initializes the distributor to work with the configured number of workers. * * @param name * The name to be given to the distributor instance. * @param socket_id * The NUMA node on which the memory is to be allocated * @param num_workers * The maximum number of workers that will request packets from this * distributor * @return * The newly created distributor instance */ struct rte_distributor * rte_distributor_create(const char *name, unsigned socket_id, unsigned num_workers); /* *** APIS to be called on the distributor lcore *** */ /* * The following APIs are the public APIs which are designed for use on a * single lcore which acts as the distributor lcore for a given distributor * instance. These functions cannot be called on multiple cores simultaneously * without using locking to protect access to the internals of the distributor. * * NOTE: a given lcore cannot act as both a distributor lcore and a worker lcore * for the same distributor instance, otherwise deadlock will result. */ /** * Process a set of packets by distributing them among workers that request * packets. The distributor will ensure that no two packets that have the * same flow id, or tag, in the mbuf will be procesed at the same time. * * The user is advocated to set tag for each mbuf before calling this function. * If user doesn't set the tag, the tag value can be various values depending on * driver implementation and configuration. * * This is not multi-thread safe and should only be called on a single lcore. * * @param d * The distributor instance to be used * @param mbufs * The mbufs to be distributed * @param num_mbufs * The number of mbufs in the mbufs array * @return * The number of mbufs processed. */ int rte_distributor_process(struct rte_distributor *d, struct rte_mbuf **mbufs, unsigned num_mbufs); /** * Get a set of mbufs that have been returned to the distributor by workers * * This should only be called on the same lcore as rte_distributor_process() * * @param d * The distributor instance to be used * @param mbufs * The mbufs pointer array to be filled in * @param max_mbufs * The size of the mbufs array * @return * The number of mbufs returned in the mbufs array. */ int rte_distributor_returned_pkts(struct rte_distributor *d, struct rte_mbuf **mbufs, unsigned max_mbufs); /** * Flush the distributor component, so that there are no in-flight or * backlogged packets awaiting processing * * This should only be called on the same lcore as rte_distributor_process() * * @param d * The distributor instance to be used * @return * The number of queued/in-flight packets that were completed by this call. */ int rte_distributor_flush(struct rte_distributor *d); /** * Clears the array of returned packets used as the source for the * rte_distributor_returned_pkts() API call. * * This should only be called on the same lcore as rte_distributor_process() * * @param d * The distributor instance to be used */ void rte_distributor_clear_returns(struct rte_distributor *d); /* *** APIS to be called on the worker lcores *** */ /* * The following APIs are the public APIs which are designed for use on * multiple lcores which act as workers for a distributor. Each lcore should use * a unique worker id when requesting packets. * * NOTE: a given lcore cannot act as both a distributor lcore and a worker lcore * for the same distributor instance, otherwise deadlock will result. */ /** * API called by a worker to get a new packet to process. Any previous packet * given to the worker is assumed to have completed processing, and may be * optionally returned to the distributor via the oldpkt parameter. * * @param d * The distributor instance to be used * @param worker_id * The worker instance number to use - must be less that num_workers passed * at distributor creation time. * @param oldpkt * The previous packet, if any, being processed by the worker * * @return * A new packet to be processed by the worker thread. */ struct rte_mbuf * rte_distributor_get_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *oldpkt); /** * API called by a worker to return a completed packet without requesting a * new packet, for example, because a worker thread is shutting down * * @param d * The distributor instance to be used * @param worker_id * The worker instance number to use - must be less that num_workers passed * at distributor creation time. * @param mbuf * The previous packet being processed by the worker */ int rte_distributor_return_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *mbuf); /** * API called by a worker to request a new packet to process. * Any previous packet given to the worker is assumed to have completed * processing, and may be optionally returned to the distributor via * the oldpkt parameter. * Unlike rte_distributor_get_pkt(), this function does not wait for a new * packet to be provided by the distributor. * * NOTE: after calling this function, rte_distributor_poll_pkt() should * be used to poll for the packet requested. The rte_distributor_get_pkt() * API should *not* be used to try and retrieve the new packet. * * @param d * The distributor instance to be used * @param worker_id * The worker instance number to use - must be less that num_workers passed * at distributor creation time. * @param oldpkt * The previous packet, if any, being processed by the worker */ void rte_distributor_request_pkt(struct rte_distributor *d, unsigned worker_id, struct rte_mbuf *oldpkt); /** * API called by a worker to check for a new packet that was previously * requested by a call to rte_distributor_request_pkt(). It does not wait * for the new packet to be available, but returns NULL if the request has * not yet been fulfilled by the distributor. * * @param d * The distributor instance to be used * @param worker_id * The worker instance number to use - must be less that num_workers passed * at distributor creation time. * * @return * A new packet to be processed by the worker thread, or NULL if no * packet is yet available. */ struct rte_mbuf * rte_distributor_poll_pkt(struct rte_distributor *d, unsigned worker_id); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_eal/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += common DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += linuxapp DIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += common DIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += bsdapp include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: lib/librte_eal/bsdapp/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal DIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += contigmem DIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += nic_uio include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: lib/librte_eal/bsdapp/contigmem/BSDmakefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # KMOD= contigmem SRCS= contigmem.c device_if.h bus_if.h .include ================================================ FILE: lib/librte_eal/bsdapp/contigmem/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # module name and path # MODULE = contigmem # # CFLAGS # MODULE_CFLAGS += -I$(SRCDIR) MODULE_CFLAGS += -I$(RTE_OUTPUT)/include MODULE_CFLAGS += -Winline -Wall -Werror MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h # # all source are stored in SRCS-y # SRCS-y := contigmem.c include $(RTE_SDK)/mk/rte.bsdmodule.mk ================================================ FILE: lib/librte_eal/bsdapp/contigmem/contigmem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int contigmem_load(void); static int contigmem_unload(void); static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); static d_mmap_t contigmem_mmap; static d_mmap_single_t contigmem_mmap_single; static d_open_t contigmem_open; static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; static eventhandler_tag contigmem_eh_tag; static void *contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; static struct cdev *contigmem_cdev = NULL; TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); static SYSCTL_NODE(_hw, OID_AUTO, contigmem, CTLFLAG_RD, 0, "contigmem"); SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, &contigmem_buffer_size, 0, "Size of each contiguous buffer"); static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, "physaddr"); MALLOC_DEFINE(M_CONTIGMEM, "contigmem", "contigmem(4) allocations"); static int contigmem_modevent(module_t mod, int type, void *arg) { int error = 0; switch (type) { case MOD_LOAD: error = contigmem_load(); break; case MOD_UNLOAD: error = contigmem_unload(); break; default: break; } return error; } moduledata_t contigmem_mod = { "contigmem", (modeventhand_t)contigmem_modevent, 0 }; DECLARE_MODULE(contigmem, contigmem_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_VERSION(contigmem, 1); static struct cdevsw contigmem_ops = { .d_name = "contigmem", .d_version = D_VERSION, .d_mmap = contigmem_mmap, .d_mmap_single = contigmem_mmap_single, .d_open = contigmem_open, }; static int contigmem_load() { char index_string[8], description[32]; int i; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); return EINVAL; } if (contigmem_buffer_size < PAGE_SIZE || (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { printf("buffer size 0x%lx is not greater than PAGE_SIZE and " "power of two\n", contigmem_buffer_size); return EINVAL; } for (i = 0; i < contigmem_num_buffers; i++) { contigmem_buffers[i] = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); if (contigmem_buffers[i] == NULL) { printf("contigmalloc failed for buffer %d\n", i); return ENOMEM; } printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], (void *)pmap_kextract((vm_offset_t)contigmem_buffers[i])); snprintf(index_string, sizeof(index_string), "%d", i); snprintf(description, sizeof(description), "phys addr for buffer %d", i); SYSCTL_ADD_PROC(NULL, &SYSCTL_NODE_CHILDREN(_hw_contigmem, physaddr), OID_AUTO, index_string, CTLTYPE_U64 | CTLFLAG_RD, (void *)(uintptr_t)i, 0, contigmem_physaddr, "LU", description); } contigmem_cdev = make_dev_credf(0, &contigmem_ops, 0, NULL, UID_ROOT, GID_WHEEL, 0600, "contigmem"); return 0; } static int contigmem_unload() { int i; if (contigmem_cdev != NULL) destroy_dev(contigmem_cdev); if (contigmem_eh_tag != NULL) EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) if (contigmem_buffers[i] != NULL) contigfree(contigmem_buffers[i], contigmem_buffer_size, M_CONTIGMEM); return 0; } static int contigmem_physaddr(SYSCTL_HANDLER_ARGS) { uint64_t physaddr; int index = (int)(uintptr_t)arg1; physaddr = (uint64_t)vtophys(contigmem_buffers[index]); return sysctl_handle_64(oidp, &physaddr, 0, req); } static int contigmem_open(struct cdev *cdev, int fflags, int devtype, struct thread *td) { return 0; } static int contigmem_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { *paddr = offset; return 0; } static int contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj, int nprot) { /* * The buffer index is encoded in the offset. Divide the offset by * PAGE_SIZE to get the index of the buffer requested by the user * app. */ if ((*offset/PAGE_SIZE) >= contigmem_num_buffers) return EINVAL; *offset = (vm_ooffset_t)vtophys(contigmem_buffers[*offset/PAGE_SIZE]); *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, curthread->td_ucred); return 0; } ================================================ FILE: lib/librte_eal/bsdapp/eal/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_eal.a VPATH += $(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(SRCDIR)/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include CFLAGS += -I$(RTE_SDK)/lib/librte_ring CFLAGS += -I$(RTE_SDK)/lib/librte_mempool CFLAGS += $(WERROR_FLAGS) -O3 EXPORT_MAP := rte_eal_version.map LIBABIVER := 1 # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) := eal.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_memory.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_hugepage_info.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_thread.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_log.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_pci.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_debug.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_lcore.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_timer.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_interrupts.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_alarm.c # from common dir SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_lcore.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_timer.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_memzone.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_log.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_launch.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_pci.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_pci_uio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_memory.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_tailqs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_errno.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_cpuflags.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_devargs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += malloc_heap.c CFLAGS_eal.o := -D_GNU_SOURCE #CFLAGS_eal_thread.o := -D_GNU_SOURCE CFLAGS_eal_log.o := -D_GNU_SOURCE CFLAGS_eal_common_log.o := -D_GNU_SOURCE # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_eal_thread.o += -Wno-return-type CFLAGS_eal_hpet.o += -Wno-return-type endif INC := rte_interrupts.h SYMLINK-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP)-include/exec-env := \ $(addprefix include/exec-env/,$(INC)) DEPDIRS-$(CONFIG_RTE_LIBRTE_EAL_BSDAPP) += lib/librte_eal/common include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_eal/bsdapp/eal/eal.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include "eal_hugepages.h" #include "eal_options.h" #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) /* Allow the application to print its usage message too if set */ static rte_usage_hook_t rte_application_usage_hook = NULL; /* early configuration structure, when memory config is not mmapped */ static struct rte_mem_config early_mem_config; /* define fd variable here, because file needs to be kept open for the * duration of the program, as we hold a write lock on it in the primary proc */ static int mem_cfg_fd = -1; static struct flock wr_lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = offsetof(struct rte_mem_config, memseg), .l_len = sizeof(early_mem_config.memseg), }; /* Address of global and public configuration */ static struct rte_config rte_config = { .mem_config = &early_mem_config, }; /* internal configuration (per-core) */ struct lcore_config lcore_config[RTE_MAX_LCORE]; /* internal configuration */ struct internal_config internal_config; /* used by rte_rdtsc() */ int rte_cycles_vmware_tsc_map; /* Return a pointer to the configuration structure */ struct rte_config * rte_eal_get_configuration(void) { return &rte_config; } /* parse a sysfs (or other) file containing one integer value */ int eal_parse_sysfs_value(const char *filename, unsigned long *val) { FILE *f; char buf[BUFSIZ]; char *end = NULL; if ((f = fopen(filename, "r")) == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n", __func__, filename); return -1; } if (fgets(buf, sizeof(buf), f) == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n", __func__, filename); fclose(f); return -1; } *val = strtoul(buf, &end, 0); if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n", __func__, filename); fclose(f); return -1; } fclose(f); return 0; } /* create memory configuration in shared/mmap memory. Take out * a write lock on the memsegs, so we can auto-detect primary/secondary. * This means we never close the file while running (auto-close on exit). * We also don't lock the whole file, so that in future we can use read-locks * on other parts, e.g. memzones, to detect if there are running secondary * processes. */ static void rte_eal_config_create(void) { void *rte_mem_cfg_addr; int retval; const char *pathname = eal_runtime_config_path(); if (internal_config.no_shconf) return; if (mem_cfg_fd < 0){ mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660); if (mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config)); if (retval < 0){ close(mem_cfg_fd); rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname); } retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock); if (retval < 0){ close(mem_cfg_fd); rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary " "process running?\n", pathname); } rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); if (rte_mem_cfg_addr == MAP_FAILED){ rte_panic("Cannot mmap memory for rte_config\n"); } memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; } /* attach to an existing shared memory config */ static void rte_eal_config_attach(void) { void *rte_mem_cfg_addr; const char *pathname = eal_runtime_config_path(); if (internal_config.no_shconf) return; if (mem_cfg_fd < 0){ mem_cfg_fd = open(pathname, O_RDWR); if (mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); close(mem_cfg_fd); if (rte_mem_cfg_addr == MAP_FAILED) rte_panic("Cannot mmap memory for rte_config\n"); rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; } /* Detect if we are a primary or a secondary process */ enum rte_proc_type_t eal_proc_type_detect(void) { enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; const char *pathname = eal_runtime_config_path(); /* if we can open the file but not get a write-lock we are a secondary * process. NOTE: if we get a file handle back, we keep that open * and don't close it to prevent a race condition between multiple opens */ if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) && (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) ptype = RTE_PROC_SECONDARY; RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); return ptype; } /* Sets up rte_config structure with the pointer to shared memory config.*/ static void rte_config_init(void) { rte_config.process_type = internal_config.process_type; switch (rte_config.process_type){ case RTE_PROC_PRIMARY: rte_eal_config_create(); break; case RTE_PROC_SECONDARY: rte_eal_config_attach(); rte_eal_mcfg_wait_complete(rte_config.mem_config); break; case RTE_PROC_AUTO: case RTE_PROC_INVALID: rte_panic("Invalid process type\n"); } } /* display usage */ static void eal_usage(const char *prgname) { printf("\nUsage: %s ", prgname); eal_common_usage(); /* Allow the application to print its usage message too if hook is set */ if ( rte_application_usage_hook ) { printf("===== Application Usage =====\n\n"); rte_application_usage_hook(prgname); } } /* Set a per-application usage message */ rte_usage_hook_t rte_set_application_usage_hook( rte_usage_hook_t usage_func ) { rte_usage_hook_t old_func; /* Will be NULL on the first call to denote the last usage routine. */ old_func = rte_application_usage_hook; rte_application_usage_hook = usage_func; return old_func; } static inline size_t eal_get_hugepage_mem_size(void) { uint64_t size = 0; unsigned i, j; for (i = 0; i < internal_config.num_hugepage_sizes; i++) { struct hugepage_info *hpi = &internal_config.hugepage_info[i]; if (hpi->hugedir != NULL) { for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { size += hpi->hugepage_sz * hpi->num_pages[j]; } } } return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; } /* Parse the arguments for --log-level only */ static void eal_log_level_parse(int argc, char **argv) { int opt; char **argvopt; int option_index; argvopt = argv; eal_reset_internal_config(&internal_config); while ((opt = getopt_long(argc, argvopt, eal_short_options, eal_long_options, &option_index)) != EOF) { int ret; /* getopt is not happy, stop right now */ if (opt == '?') break; ret = (opt == OPT_LOG_LEVEL_NUM) ? eal_parse_common_option(opt, optarg, &internal_config) : 0; /* common parser is not happy */ if (ret < 0) break; } optind = 0; /* reset getopt lib */ } /* Parse the argument given in the command line of the application */ static int eal_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; argvopt = argv; while ((opt = getopt_long(argc, argvopt, eal_short_options, eal_long_options, &option_index)) != EOF) { int ret; /* getopt is not happy, stop right now */ if (opt == '?') { eal_usage(prgname); return -1; } ret = eal_parse_common_option(opt, optarg, &internal_config); /* common parser is not happy */ if (ret < 0) { eal_usage(prgname); return -1; } /* common parser handled this option */ if (ret == 0) continue; switch (opt) { case 'h': eal_usage(prgname); exit(EXIT_SUCCESS); default: if (opt < OPT_LONG_MIN_NUM && isprint(opt)) { RTE_LOG(ERR, EAL, "Option %c is not supported " "on FreeBSD\n", opt); } else if (opt >= OPT_LONG_MIN_NUM && opt < OPT_LONG_MAX_NUM) { RTE_LOG(ERR, EAL, "Option %s is not supported " "on FreeBSD\n", eal_long_options[option_index].name); } else { RTE_LOG(ERR, EAL, "Option %d is not supported " "on FreeBSD\n", opt); } eal_usage(prgname); return -1; } } if (eal_adjust_config(&internal_config) != 0) return -1; /* sanity checks */ if (eal_check_common_options(&internal_config) != 0) { eal_usage(prgname); return -1; } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void eal_check_mem_on_local_socket(void) { const struct rte_memseg *ms; int i, socket_id; socket_id = rte_lcore_to_socket_id(rte_config.master_lcore); ms = rte_eal_get_physmem_layout(); for (i = 0; i < RTE_MAX_MEMSEG; i++) if (ms[i].socket_id == socket_id && ms[i].len > 0) return; RTE_LOG(WARNING, EAL, "WARNING: Master core has no " "memory on local socket!\n"); } static int sync_func(__attribute__((unused)) void *arg) { return 0; } inline static void rte_eal_mcfg_complete(void) { /* ALL shared mem_config related INIT DONE */ if (rte_config.process_type == RTE_PROC_PRIMARY) rte_config.mem_config->magic = RTE_MAGIC; } /* return non-zero if hugepages are enabled. */ int rte_eal_has_hugepages(void) { return !internal_config.no_hugetlbfs; } /* Abstraction for port I/0 privilege */ int rte_eal_iopl_init(void) { static int fd; fd = open("/dev/io", O_RDWR); if (fd < 0) return -1; /* keep fd open for iopl */ return 0; } /* Launch threads, called at application init(). */ int rte_eal_init(int argc, char **argv) { int i, fctret, ret; pthread_t thread_id; static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0); char cpuset[RTE_CPU_AFFINITY_STR_LEN]; if (!rte_atomic32_test_and_set(&run_once)) return -1; thread_id = pthread_self(); if (rte_eal_log_early_init() < 0) rte_panic("Cannot init early logs\n"); eal_log_level_parse(argc, argv); /* set log level as early as possible */ rte_set_log_level(internal_config.log_level); if (rte_eal_cpu_init() < 0) rte_panic("Cannot detect lcores\n"); fctret = eal_parse_args(argc, argv); if (fctret < 0) exit(1); if (internal_config.no_hugetlbfs == 0 && internal_config.process_type != RTE_PROC_SECONDARY && eal_hugepage_info_init() < 0) rte_panic("Cannot get hugepage information\n"); if (internal_config.memory == 0 && internal_config.force_sockets == 0) { if (internal_config.no_hugetlbfs) internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE; else internal_config.memory = eal_get_hugepage_mem_size(); } if (internal_config.vmware_tsc_map == 1) { #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT rte_cycles_vmware_tsc_map = 1; RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, " "you must have monitor_control.pseudo_perfctr = TRUE\n"); #else RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because " "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n"); #endif } rte_srand(rte_rdtsc()); rte_config_init(); if (rte_eal_memory_init() < 0) rte_panic("Cannot init memory\n"); if (rte_eal_memzone_init() < 0) rte_panic("Cannot init memzone\n"); if (rte_eal_tailqs_init() < 0) rte_panic("Cannot init tail queues for objects\n"); /* if (rte_eal_log_init(argv[0], internal_config.syslog_facility) < 0) rte_panic("Cannot init logs\n");*/ if (rte_eal_alarm_init() < 0) rte_panic("Cannot init interrupt-handling thread\n"); if (rte_eal_intr_init() < 0) rte_panic("Cannot init interrupt-handling thread\n"); if (rte_eal_timer_init() < 0) rte_panic("Cannot init HPET or TSC timers\n"); if (rte_eal_pci_init() < 0) rte_panic("Cannot init PCI\n"); eal_check_mem_on_local_socket(); rte_eal_mcfg_complete(); eal_thread_init_master(rte_config.master_lcore); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%p;cpuset=[%s%s])\n", rte_config.master_lcore, thread_id, cpuset, ret == 0 ? "" : "..."); if (rte_eal_dev_init() < 0) rte_panic("Cannot init pmd devices\n"); RTE_LCORE_FOREACH_SLAVE(i) { /* * create communication pipes between master thread * and children */ if (pipe(lcore_config[i].pipe_master2slave) < 0) rte_panic("Cannot create pipe\n"); if (pipe(lcore_config[i].pipe_slave2master) < 0) rte_panic("Cannot create pipe\n"); lcore_config[i].state = WAIT; /* create a thread for each lcore */ ret = pthread_create(&lcore_config[i].thread_id, NULL, eal_thread_loop, NULL); if (ret != 0) rte_panic("Cannot create thread\n"); } /* * Launch a dummy function on all slave lcores, so that master lcore * knows they are all ready when this function returns. */ rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); rte_eal_mp_wait_lcore(); /* Probe & Initialize PCI devices */ if (rte_eal_pci_probe()) rte_panic("Cannot probe PCI\n"); return fctret; } /* get core role */ enum rte_lcore_role_t rte_eal_lcore_role(unsigned lcore_id) { return rte_config.lcore_role[lcore_id]; } enum rte_proc_type_t rte_eal_process_type(void) { return rte_config.process_type; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_alarm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "eal_private.h" int rte_eal_alarm_init(void) { return 0; } int rte_eal_alarm_set(uint64_t us __rte_unused, rte_eal_alarm_callback cb_fn __rte_unused, void *cb_arg __rte_unused) { return -ENOTSUP; } int rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn __rte_unused, void *cb_arg __rte_unused) { return -ENOTSUP; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_debug.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #define BACKTRACE_SIZE 256 /* dump the stack of the calling core */ void rte_dump_stack(void) { void *func[BACKTRACE_SIZE]; char **symb = NULL; int size; size = backtrace(func, BACKTRACE_SIZE); symb = backtrace_symbols(func, size); while (size > 0) { rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL, "%d: [%s]\n", size, symb[size - 1]); size --; } } /* not implemented in this environment */ void rte_dump_registers(void) { return; } /* call abort(), it will generate a coredump if enabled */ void __rte_panic(const char *funcname, const char *format, ...) { va_list ap; /* disable history */ rte_log_set_history(0); rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n", funcname); va_start(ap, format); rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap); va_end(ap); rte_dump_stack(); rte_dump_registers(); abort(); } /* * Like rte_panic this terminates the application. However, no traceback is * provided and no core-dump is generated. */ void rte_exit(int exit_code, const char *format, ...) { va_list ap; /* disable history */ rte_log_set_history(0); if (exit_code != 0) RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n" " Cause: ", exit_code); va_start(ap, format); rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap); va_end(ap); #ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR exit(exit_code); #else rte_dump_stack(); rte_dump_registers(); abort(); #endif } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_hugepage_info.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "eal_hugepages.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #define CONTIGMEM_DEV "/dev/contigmem" /* * Uses mmap to create a shared memory area for storage of data * Used in this file to store the hugepage file map on disk */ static void * create_shared_memory(const char *filename, const size_t mem_size) { void *retval; int fd = open(filename, O_CREAT | O_RDWR, 0666); if (fd < 0) return NULL; if (ftruncate(fd, mem_size) < 0) { close(fd); return NULL; } retval = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); return retval; } /* * No hugepage support on freebsd, but we dummy it, using contigmem driver */ int eal_hugepage_info_init(void) { size_t sysctl_size; int num_buffers, fd, error; int64_t buffer_size; /* re-use the linux "internal config" structure for our memory data */ struct hugepage_info *hpi = &internal_config.hugepage_info[0]; struct hugepage_info *tmp_hpi; sysctl_size = sizeof(num_buffers); error = sysctlbyname("hw.contigmem.num_buffers", &num_buffers, &sysctl_size, NULL, 0); if (error != 0) { RTE_LOG(ERR, EAL, "could not read sysctl hw.contigmem.num_buffers"); return -1; } sysctl_size = sizeof(buffer_size); error = sysctlbyname("hw.contigmem.buffer_size", &buffer_size, &sysctl_size, NULL, 0); if (error != 0) { RTE_LOG(ERR, EAL, "could not read sysctl hw.contigmem.buffer_size"); return -1; } fd = open(CONTIGMEM_DEV, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "could not open "CONTIGMEM_DEV"\n"); return -1; } if (buffer_size >= 1<<30) RTE_LOG(INFO, EAL, "Contigmem driver has %d buffers, each of size %dGB\n", num_buffers, (int)(buffer_size>>30)); else if (buffer_size >= 1<<20) RTE_LOG(INFO, EAL, "Contigmem driver has %d buffers, each of size %dMB\n", num_buffers, (int)(buffer_size>>20)); else RTE_LOG(INFO, EAL, "Contigmem driver has %d buffers, each of size %dKB\n", num_buffers, (int)(buffer_size>>10)); internal_config.num_hugepage_sizes = 1; hpi->hugedir = CONTIGMEM_DEV; hpi->hugepage_sz = buffer_size; hpi->num_pages[0] = num_buffers; hpi->lock_descriptor = fd; tmp_hpi = create_shared_memory(eal_hugepage_info_path(), sizeof(struct hugepage_info)); if (tmp_hpi == NULL ) { RTE_LOG(ERR, EAL, "Failed to create shared memory!\n"); return -1; } memcpy(tmp_hpi, hpi, sizeof(struct hugepage_info)); if ( munmap(tmp_hpi, sizeof(struct hugepage_info)) < 0) { RTE_LOG(ERR, EAL, "Failed to unmap shared memory!\n"); return -1; } return 0; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_interrupts.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "eal_private.h" int rte_intr_callback_register(struct rte_intr_handle *intr_handle __rte_unused, rte_intr_callback_fn cb __rte_unused, void *cb_arg __rte_unused) { return -ENOTSUP; } int rte_intr_callback_unregister(struct rte_intr_handle *intr_handle __rte_unused, rte_intr_callback_fn cb_fn __rte_unused, void *cb_arg __rte_unused) { return -ENOTSUP; } int rte_intr_enable(struct rte_intr_handle *intr_handle __rte_unused) { return -ENOTSUP; } int rte_intr_disable(struct rte_intr_handle *intr_handle __rte_unused) { return -ENOTSUP; } int rte_eal_intr_init(void) { return 0; } int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data) { RTE_SET_USED(intr_handle); RTE_SET_USED(epfd); RTE_SET_USED(op); RTE_SET_USED(vec); RTE_SET_USED(data); return -ENOTSUP; } int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) { RTE_SET_USED(intr_handle); RTE_SET_USED(nb_efd); return 0; } void rte_intr_efd_disable(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); } int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); return 0; } int rte_intr_allow_others(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); return 1; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_lcore.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" /* No topology information available on FreeBSD including NUMA info */ unsigned eal_cpu_core_id(__rte_unused unsigned lcore_id) { return 0; } static int eal_get_ncpus(void) { int mib[2] = {CTL_HW, HW_NCPU}; int ncpu; size_t len = sizeof(ncpu); sysctl(mib, 2, &ncpu, &len, NULL, 0); RTE_LOG(INFO, EAL, "Sysctl reports %d cpus\n", ncpu); return ncpu; } unsigned eal_cpu_socket_id(__rte_unused unsigned cpu_id) { return 0; } /* Check if a cpu is present by the presence of the * cpu information for it. */ int eal_cpu_detected(unsigned lcore_id) { const unsigned ncpus = eal_get_ncpus(); return (lcore_id < ncpus); } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_log.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include /* * set the log to default function, called during eal init process, * once memzones are available. */ int rte_eal_log_init(const char *id __rte_unused, int facility __rte_unused) { if (rte_eal_common_log_init(stderr) < 0) return -1; return 0; } int rte_eal_log_early_init(void) { rte_openlog_stream(stderr); return 0; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_memory.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #define EAL_PAGE_SIZE (sysconf(_SC_PAGESIZE)) /* * Get physical address of any mapped virtual address in the current process. */ phys_addr_t rte_mem_virt2phy(const void *virtaddr) { /* XXX not implemented. This function is only used by * rte_mempool_virt2phy() when hugepages are disabled. */ (void)virtaddr; return RTE_BAD_PHYS_ADDR; } int rte_eal_hugepage_init(void) { struct rte_mem_config *mcfg; uint64_t total_mem = 0; void *addr; unsigned i, j, seg_idx = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* for debug purposes, hugetlbfs can be disabled */ if (internal_config.no_hugetlbfs) { addr = malloc(internal_config.memory); mcfg->memseg[0].phys_addr = (phys_addr_t)(uintptr_t)addr; mcfg->memseg[0].addr = addr; mcfg->memseg[0].hugepage_sz = RTE_PGSIZE_4K; mcfg->memseg[0].len = internal_config.memory; mcfg->memseg[0].socket_id = 0; return 0; } /* map all hugepages and sort them */ for (i = 0; i < internal_config.num_hugepage_sizes; i ++){ struct hugepage_info *hpi; hpi = &internal_config.hugepage_info[i]; for (j = 0; j < hpi->num_pages[0]; j++) { struct rte_memseg *seg; uint64_t physaddr; int error; size_t sysctl_size = sizeof(physaddr); char physaddr_str[64]; addr = mmap(NULL, hpi->hugepage_sz, PROT_READ|PROT_WRITE, MAP_SHARED, hpi->lock_descriptor, j * EAL_PAGE_SIZE); if (addr == MAP_FAILED) { RTE_LOG(ERR, EAL, "Failed to mmap buffer %u from %s\n", j, hpi->hugedir); return -1; } snprintf(physaddr_str, sizeof(physaddr_str), "hw.contigmem" ".physaddr.%d", j); error = sysctlbyname(physaddr_str, &physaddr, &sysctl_size, NULL, 0); if (error < 0) { RTE_LOG(ERR, EAL, "Failed to get physical addr for buffer %u " "from %s\n", j, hpi->hugedir); return -1; } seg = &mcfg->memseg[seg_idx++]; seg->addr = addr; seg->phys_addr = physaddr; seg->hugepage_sz = hpi->hugepage_sz; seg->len = hpi->hugepage_sz; seg->nchannel = mcfg->nchannel; seg->nrank = mcfg->nrank; seg->socket_id = 0; RTE_LOG(INFO, EAL, "Mapped memory segment %u @ %p: physaddr:0x%" PRIx64", len %zu\n", seg_idx, addr, physaddr, hpi->hugepage_sz); if (total_mem >= internal_config.memory || seg_idx >= RTE_MAX_MEMSEG) break; } } return 0; } int rte_eal_hugepage_attach(void) { const struct hugepage_info *hpi; int fd_hugepage_info, fd_hugepage = -1; unsigned i = 0; struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; /* Obtain a file descriptor for hugepage_info */ fd_hugepage_info = open(eal_hugepage_info_path(), O_RDONLY); if (fd_hugepage_info < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", eal_hugepage_info_path()); return -1; } /* Map the shared hugepage_info into the process address spaces */ hpi = mmap(NULL, sizeof(struct hugepage_info), PROT_READ, MAP_PRIVATE, fd_hugepage_info, 0); if (hpi == NULL) { RTE_LOG(ERR, EAL, "Could not mmap %s\n", eal_hugepage_info_path()); goto error; } /* Obtain a file descriptor for contiguous memory */ fd_hugepage = open(hpi->hugedir, O_RDWR); if (fd_hugepage < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", hpi->hugedir); goto error; } /* Map the contiguous memory into each memory segment */ for (i = 0; i < hpi->num_pages[0]; i++) { void *addr; struct rte_memseg *seg = &mcfg->memseg[i]; addr = mmap(seg->addr, hpi->hugepage_sz, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd_hugepage, i * EAL_PAGE_SIZE); if (addr == MAP_FAILED || addr != seg->addr) { RTE_LOG(ERR, EAL, "Failed to mmap buffer %u from %s\n", i, hpi->hugedir); goto error; } } /* hugepage_info is no longer required */ munmap((void *)(uintptr_t)hpi, sizeof(struct hugepage_info)); close(fd_hugepage_info); close(fd_hugepage); return 0; error: if (fd_hugepage_info >= 0) close(fd_hugepage_info); if (fd_hugepage >= 0) close(fd_hugepage); return -1; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_pci.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_filesystem.h" #include "eal_private.h" /** * @file * PCI probing under linux * * This code is used to simulate a PCI probe by parsing information in * sysfs. Moreover, when a registered driver matches a device, the * kernel driver currently using it is unloaded and replaced by * igb_uio module, which is a very minimal userland driver for Intel * network card, only providing access to PCI BAR to applications, and * enabling bus master. */ /* unbind kernel driver for this device */ int pci_unbind_kernel_driver(struct rte_pci_device *dev __rte_unused) { RTE_LOG(ERR, EAL, "RTE_PCI_DRV_FORCE_UNBIND flag is not implemented " "for BSD\n"); return -ENOTSUP; } /* Map pci device */ int pci_map_device(struct rte_pci_device *dev) { int ret = -1; /* try mapping the NIC resources */ switch (dev->kdrv) { case RTE_KDRV_NIC_UIO: /* map resources for devices that use uio */ ret = pci_uio_map_resource(dev); break; default: RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver, skipped\n"); ret = 1; break; } return ret; } /* Unmap pci device */ void pci_unmap_device(struct rte_pci_device *dev) { /* try unmapping the NIC resources */ switch (dev->kdrv) { case RTE_KDRV_NIC_UIO: /* unmap resources for devices that use uio */ pci_uio_unmap_resource(dev); break; default: RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver, skipped\n"); break; } } void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res) { rte_free(uio_res); if (dev->intr_handle.fd) { close(dev->intr_handle.fd); dev->intr_handle.fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; } } int pci_uio_alloc_resource(struct rte_pci_device *dev, struct mapped_pci_resource **uio_res) { char devname[PATH_MAX]; /* contains the /dev/uioX */ struct rte_pci_addr *loc; loc = &dev->addr; snprintf(devname, sizeof(devname), "/dev/uio@pci:%u:%u:%u", dev->addr.bus, dev->addr.devid, dev->addr.function); if (access(devname, O_RDWR) < 0) { RTE_LOG(WARNING, EAL, " "PCI_PRI_FMT" not managed by UIO driver, " "skipping\n", loc->domain, loc->bus, loc->devid, loc->function); return 1; } /* save fd if in primary process */ dev->intr_handle.fd = open(devname, O_RDWR); if (dev->intr_handle.fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); goto error; } dev->intr_handle.type = RTE_INTR_HANDLE_UIO; /* allocate the mapping details for secondary processes*/ *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0); if (*uio_res == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot store uio mmap details\n", __func__); goto error; } snprintf((*uio_res)->path, sizeof((*uio_res)->path), "%s", devname); memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr)); return 0; error: pci_uio_free_resource(dev, *uio_res); return -1; } int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx, struct mapped_pci_resource *uio_res, int map_idx) { int fd; char *devname; void *mapaddr; uint64_t offset; uint64_t pagesz; struct pci_map *maps; maps = uio_res->maps; devname = uio_res->path; pagesz = sysconf(_SC_PAGESIZE); /* allocate memory to keep path */ maps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0); if (maps[map_idx].path == NULL) { RTE_LOG(ERR, EAL, "Cannot allocate memory for path: %s\n", strerror(errno)); return -1; } /* * open resource file, to mmap it */ fd = open(devname, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); goto error; } /* if matching map is found, then use it */ offset = res_idx * pagesz; mapaddr = pci_map_resource(NULL, fd, (off_t)offset, (size_t)dev->mem_resource[res_idx].len, 0); close(fd); if (mapaddr == MAP_FAILED) goto error; maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr; maps[map_idx].size = dev->mem_resource[res_idx].len; maps[map_idx].addr = mapaddr; maps[map_idx].offset = offset; strcpy(maps[map_idx].path, devname); dev->mem_resource[res_idx].addr = mapaddr; return 0; error: rte_free(maps[map_idx].path); return -1; } static int pci_scan_one(int dev_pci_fd, struct pci_conf *conf) { struct rte_pci_device *dev; struct pci_bar_io bar; unsigned i, max; dev = malloc(sizeof(*dev)); if (dev == NULL) { return -1; } memset(dev, 0, sizeof(*dev)); dev->addr.domain = conf->pc_sel.pc_domain; dev->addr.bus = conf->pc_sel.pc_bus; dev->addr.devid = conf->pc_sel.pc_dev; dev->addr.function = conf->pc_sel.pc_func; /* get vendor id */ dev->id.vendor_id = conf->pc_vendor; /* get device id */ dev->id.device_id = conf->pc_device; /* get subsystem_vendor id */ dev->id.subsystem_vendor_id = conf->pc_subvendor; /* get subsystem_device id */ dev->id.subsystem_device_id = conf->pc_subdevice; /* TODO: get max_vfs */ dev->max_vfs = 0; /* FreeBSD has no NUMA support (yet) */ dev->numa_node = 0; /* FreeBSD has only one pass through driver */ dev->kdrv = RTE_KDRV_NIC_UIO; /* parse resources */ switch (conf->pc_hdr & PCIM_HDRTYPE) { case PCIM_HDRTYPE_NORMAL: max = PCIR_MAX_BAR_0; break; case PCIM_HDRTYPE_BRIDGE: max = PCIR_MAX_BAR_1; break; case PCIM_HDRTYPE_CARDBUS: max = PCIR_MAX_BAR_2; break; default: goto skipdev; } for (i = 0; i <= max; i++) { bar.pbi_sel = conf->pc_sel; bar.pbi_reg = PCIR_BAR(i); if (ioctl(dev_pci_fd, PCIOCGETBAR, &bar) < 0) continue; dev->mem_resource[i].len = bar.pbi_length; if (PCI_BAR_IO(bar.pbi_base)) { dev->mem_resource[i].addr = (void *)(bar.pbi_base & ~((uint64_t)0xf)); continue; } dev->mem_resource[i].phys_addr = bar.pbi_base & ~((uint64_t)0xf); } /* device is valid, add in list (sorted) */ if (TAILQ_EMPTY(&pci_device_list)) { TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } else { struct rte_pci_device *dev2 = NULL; int ret; TAILQ_FOREACH(dev2, &pci_device_list, next) { ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr); if (ret > 0) continue; else if (ret < 0) { TAILQ_INSERT_BEFORE(dev2, dev, next); return 0; } else { /* already registered */ dev2->kdrv = dev->kdrv; dev2->max_vfs = dev->max_vfs; memmove(dev2->mem_resource, dev->mem_resource, sizeof(dev->mem_resource)); free(dev); return 0; } } TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } return 0; skipdev: free(dev); return 0; } /* * Scan the content of the PCI bus, and add the devices in the devices * list. Call pci_scan_one() for each pci entry found. */ int rte_eal_pci_scan(void) { int fd; unsigned dev_count = 0; struct pci_conf matches[16]; struct pci_conf_io conf_io = { .pat_buf_len = 0, .num_patterns = 0, .patterns = NULL, .match_buf_len = sizeof(matches), .matches = &matches[0], }; fd = open("/dev/pci", O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__); goto error; } do { unsigned i; if (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) { RTE_LOG(ERR, EAL, "%s(): error with ioctl on /dev/pci: %s\n", __func__, strerror(errno)); goto error; } for (i = 0; i < conf_io.num_matches; i++) if (pci_scan_one(fd, &matches[i]) < 0) goto error; dev_count += conf_io.num_matches; } while(conf_io.status == PCI_GETCONF_MORE_DEVS); close(fd); RTE_LOG(ERR, EAL, "PCI scan found %u devices\n", dev_count); return 0; error: if (fd >= 0) close(fd); return -1; } /* Read PCI config space. */ int rte_eal_pci_read_config(const struct rte_pci_device *dev, void *buf, size_t len, off_t offset) { int fd = -1; struct pci_io pi = { .pi_sel = { .pc_domain = dev->addr.domain, .pc_bus = dev->addr.bus, .pc_dev = dev->addr.devid, .pc_func = dev->addr.function, }, .pi_reg = offset, .pi_width = len, }; if (len == 3 || len > sizeof(pi.pi_data)) { RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__); goto error; } fd = open("/dev/pci", O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__); goto error; } if (ioctl(fd, PCIOCREAD, &pi) < 0) goto error; close(fd); memcpy(buf, &pi.pi_data, len); return 0; error: if (fd >= 0) close(fd); return -1; } /* Write PCI config space. */ int rte_eal_pci_write_config(const struct rte_pci_device *dev, const void *buf, size_t len, off_t offset) { int fd = -1; struct pci_io pi = { .pi_sel = { .pc_domain = dev->addr.domain, .pc_bus = dev->addr.bus, .pc_dev = dev->addr.devid, .pc_func = dev->addr.function, }, .pi_reg = offset, .pi_data = *(const uint32_t *)buf, .pi_width = len, }; if (len == 3 || len > sizeof(pi.pi_data)) { RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__); goto error; } memcpy(&pi.pi_data, buf, len); fd = open("/dev/pci", O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__); goto error; } if (ioctl(fd, PCIOCWRITE, &pi) < 0) goto error; close(fd); return 0; error: if (fd >= 0) close(fd); return -1; } /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) { TAILQ_INIT(&pci_driver_list); TAILQ_INIT(&pci_device_list); /* for debug purposes, PCI can be disabled */ if (internal_config.no_pci) return 0; if (rte_eal_pci_scan() < 0) { RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__); return -1; } return 0; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_thread.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" RTE_DEFINE_PER_LCORE(unsigned, _lcore_id) = LCORE_ID_ANY; RTE_DEFINE_PER_LCORE(unsigned, _socket_id) = (unsigned)SOCKET_ID_ANY; RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); /* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the * remote lcore switch in FINISHED state. */ int rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id) { int n; char c = 0; int m2s = lcore_config[slave_id].pipe_master2slave[1]; int s2m = lcore_config[slave_id].pipe_slave2master[0]; if (lcore_config[slave_id].state != WAIT) return -EBUSY; lcore_config[slave_id].f = f; lcore_config[slave_id].arg = arg; /* send message */ n = 0; while (n == 0 || (n < 0 && errno == EINTR)) n = write(m2s, &c, 1); if (n < 0) rte_panic("cannot write on configuration pipe\n"); /* wait ack */ do { n = read(s2m, &c, 1); } while (n < 0 && errno == EINTR); if (n <= 0) rte_panic("cannot read on configuration pipe\n"); return 0; } /* set affinity for current thread */ static int eal_thread_set_affinity(void) { unsigned lcore_id = rte_lcore_id(); /* acquire system unique id */ rte_gettid(); /* update EAL thread core affinity */ return rte_thread_set_affinity(&lcore_config[lcore_id].cpuset); } void eal_thread_init_master(unsigned lcore_id) { /* set the lcore ID in per-lcore memory area */ RTE_PER_LCORE(_lcore_id) = lcore_id; /* set CPU affinity */ if (eal_thread_set_affinity() < 0) rte_panic("cannot set affinity\n"); } /* main loop of threads */ __attribute__((noreturn)) void * eal_thread_loop(__attribute__((unused)) void *arg) { char c; int n, ret; unsigned lcore_id; pthread_t thread_id; int m2s, s2m; char cpuset[RTE_CPU_AFFINITY_STR_LEN]; thread_id = pthread_self(); /* retrieve our lcore_id from the configuration structure */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (thread_id == lcore_config[lcore_id].thread_id) break; } if (lcore_id == RTE_MAX_LCORE) rte_panic("cannot retrieve lcore id\n"); m2s = lcore_config[lcore_id].pipe_master2slave[0]; s2m = lcore_config[lcore_id].pipe_slave2master[1]; /* set the lcore ID in per-lcore memory area */ RTE_PER_LCORE(_lcore_id) = lcore_id; /* set CPU affinity */ if (eal_thread_set_affinity() < 0) rte_panic("cannot set affinity\n"); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%p;cpuset=[%s%s])\n", lcore_id, thread_id, cpuset, ret == 0 ? "" : "..."); /* read on our pipe to get commands */ while (1) { void *fct_arg; /* wait command */ do { n = read(m2s, &c, 1); } while (n < 0 && errno == EINTR); if (n <= 0) rte_panic("cannot read on configuration pipe\n"); lcore_config[lcore_id].state = RUNNING; /* send ack */ n = 0; while (n == 0 || (n < 0 && errno == EINTR)) n = write(s2m, &c, 1); if (n < 0) rte_panic("cannot write on configuration pipe\n"); if (lcore_config[lcore_id].f == NULL) rte_panic("NULL function pointer\n"); /* call the function and store the return value */ fct_arg = lcore_config[lcore_id].arg; ret = lcore_config[lcore_id].f(fct_arg); lcore_config[lcore_id].ret = ret; rte_wmb(); lcore_config[lcore_id].state = FINISHED; } /* never reached */ /* pthread_exit(NULL); */ /* return NULL; */ } /* require calling thread tid by gettid() */ int rte_sys_gettid(void) { long lwpid; thr_self(&lwpid); return (int)lwpid; } ================================================ FILE: lib/librte_eal/bsdapp/eal/eal_timer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" #ifdef RTE_LIBEAL_USE_HPET #warning HPET is not supported in FreeBSD #endif enum timer_source eal_timer_source = EAL_TIMER_TSC; uint64_t get_tsc_freq(void) { size_t sz; int tmp; uint64_t tsc_hz; sz = sizeof(tmp); tmp = 0; if (sysctlbyname("kern.timecounter.smp_tsc", &tmp, &sz, NULL, 0)) RTE_LOG(WARNING, EAL, "%s\n", strerror(errno)); else if (tmp != 1) RTE_LOG(WARNING, EAL, "TSC is not safe to use in SMP mode\n"); tmp = 0; if (sysctlbyname("kern.timecounter.invariant_tsc", &tmp, &sz, NULL, 0)) RTE_LOG(WARNING, EAL, "%s\n", strerror(errno)); else if (tmp != 1) RTE_LOG(WARNING, EAL, "TSC is not invariant\n"); sz = sizeof(tsc_hz); if (sysctlbyname("machdep.tsc_freq", &tsc_hz, &sz, NULL, 0)) { RTE_LOG(WARNING, EAL, "%s\n", strerror(errno)); return 0; } return tsc_hz; } int rte_eal_timer_init(void) { set_tsc_freq(); return 0; } ================================================ FILE: lib/librte_eal/bsdapp/eal/include/exec-env/rte_dom0_common.h ================================================ /*- * This file is provided under a dual BSD/LGPLv2 license. When using or * redistributing this file, you may do so under either license. * * GNU LESSER GENERAL PUBLIC LICENSE * * Copyright(c) 2007-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation * * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _RTE_DOM0_COMMON_H_ #define _RTE_DOM0_COMMON_H_ #ifdef __KERNEL__ #include #endif #define DOM0_NAME_MAX 256 #define DOM0_MM_DEV "/dev/dom0_mm" #define DOM0_CONTIG_NUM_ORDER 9 /**< 2M order */ #define DOM0_NUM_MEMSEG 512 /**< Maximum nb. of memory segment. */ #define DOM0_MEMBLOCK_SIZE 0x200000 /**< Maximum nb. of memory block(2M). */ #define DOM0_CONFIG_MEMSIZE 4096 /**< Maximum config memory size(4G). */ #define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */ #define RTE_DOM0_IOCTL_PREPARE_MEMSEG _IOWR(0, 1 , struct memory_info) #define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG _IOWR(0, 2 , char *) #define RTE_DOM0_IOCTL_GET_NUM_MEMSEG _IOWR(0, 3, int) #define RTE_DOM0_IOCTL_GET_MEMSEG_INFO _IOWR(0, 4, void *) /** * A structure used to store memory information. */ struct memory_info { char name[DOM0_NAME_MAX]; uint64_t size; }; /** * A structure used to store memory segment information. */ struct memseg_info { uint32_t idx; uint64_t pfn; uint64_t size; uint64_t mfn[DOM0_NUM_MEMBLOCK]; }; /** * A structure used to store memory block information. */ struct memblock_info { uint8_t exchange_flag; uint64_t vir_addr; uint64_t pfn; uint64_t mfn; }; #endif /* _RTE_DOM0_COMMON_H_ */ ================================================ FILE: lib/librte_eal/bsdapp/eal/include/exec-env/rte_interrupts.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_INTERRUPTS_H_ #error "don't include this file directly, please include generic " #endif #ifndef _RTE_BSDAPP_INTERRUPTS_H_ #define _RTE_BSDAPP_INTERRUPTS_H_ enum rte_intr_handle_type { RTE_INTR_HANDLE_UNKNOWN = 0, RTE_INTR_HANDLE_UIO, /**< uio device handle */ RTE_INTR_HANDLE_ALARM, /**< alarm handle */ RTE_INTR_HANDLE_MAX }; /** Handle for interrupts. */ struct rte_intr_handle { int fd; /**< file descriptor */ int uio_cfg_fd; /**< UIO config file descriptor */ enum rte_intr_handle_type type; /**< handle type */ #ifdef RTE_NEXT_ABI int max_intr; /**< max interrupt requested */ uint32_t nb_efd; /**< number of available efds */ int *intr_vec; /**< intr vector number array */ #endif }; /** * @param intr_handle * Pointer to the interrupt handle. * @param epfd * Epoll instance fd which the intr vector associated to. * @param op * The operation be performed for the vector. * Operation type of {ADD, DEL}. * @param vec * RX intr vector number added to the epoll instance wait list. * @param data * User raw data. * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data); /** * It enables the fastpath event fds if it's necessary. * It creates event fds when multi-vectors allowed, * otherwise it multiplexes the single event fds. * * @param intr_handle * Pointer to the interrupt handle. * @param nb_vec * Number of interrupt vector trying to enable. * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); /** * It disable the fastpath event fds. * It deletes registered eventfds and closes the open fds. * * @param intr_handle * Pointer to the interrupt handle. */ void rte_intr_efd_disable(struct rte_intr_handle *intr_handle); /** * The fastpath interrupt is enabled or not. * * @param intr_handle * Pointer to the interrupt handle. */ int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); /** * The interrupt handle instance allows other cause or not. * Other cause stands for none fastpath interrupt. * * @param intr_handle * Pointer to the interrupt handle. */ int rte_intr_allow_others(struct rte_intr_handle *intr_handle); #endif /* _RTE_BSDAPP_INTERRUPTS_H_ */ ================================================ FILE: lib/librte_eal/bsdapp/nic_uio/BSDmakefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # KMOD= nic_uio SRCS= nic_uio.c device_if.h bus_if.h pci_if.h .include ================================================ FILE: lib/librte_eal/bsdapp/nic_uio/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # module name and path # MODULE = nic_uio # # CFLAGS # MODULE_CFLAGS += -I$(SRCDIR) MODULE_CFLAGS += -I$(RTE_OUTPUT)/include MODULE_CFLAGS += -Winline -Wall -Werror MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h # # all source are stored in SRCS-y # SRCS-y := nic_uio.c include $(RTE_SDK)/mk/rte.bsdmodule.mk ================================================ FILE: lib/librte_eal/bsdapp/nic_uio/nic_uio.c ================================================ /* - * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include /* defines used in kernel.h */ #include #include /* types used in module initialization */ #include /* cdevsw struct */ #include /* structs, prototypes for pci bus stuff and DEVMETHOD */ #include #include #include #include #include #include /* For pci_get macros! */ #include /* The softc holds our per-instance data. */ #include #include #include #include #include #define MAX_BARS (PCIR_MAX_BAR_0 + 1) #define MAX_DETACHED_DEVICES 128 static device_t detached_devices[MAX_DETACHED_DEVICES] = {}; static int num_detached = 0; struct nic_uio_softc { device_t dev_t; struct cdev *my_cdev; int bar_id[MAX_BARS]; struct resource *bar_res[MAX_BARS]; u_long bar_start[MAX_BARS]; u_long bar_size[MAX_BARS]; }; /* Function prototypes */ static d_open_t nic_uio_open; static d_close_t nic_uio_close; static d_mmap_t nic_uio_mmap; static d_mmap_single_t nic_uio_mmap_single; static int nic_uio_probe(device_t dev); static int nic_uio_attach(device_t dev); static int nic_uio_detach(device_t dev); static int nic_uio_shutdown(void); static int nic_uio_modevent(module_t mod, int type, void *arg); static struct cdevsw uio_cdevsw = { .d_name = "nic_uio", .d_version = D_VERSION, .d_open = nic_uio_open, .d_close = nic_uio_close, .d_mmap = nic_uio_mmap, .d_mmap_single = nic_uio_mmap_single, }; static device_method_t nic_uio_methods[] = { DEVMETHOD(device_probe, nic_uio_probe), DEVMETHOD(device_attach, nic_uio_attach), DEVMETHOD(device_detach, nic_uio_detach), DEVMETHOD_END }; struct device { int vend; int dev; }; struct pci_bdf { uint32_t bus; uint32_t devid; uint32_t function; }; static devclass_t nic_uio_devclass; DEFINE_CLASS_0(nic_uio, nic_uio_driver, nic_uio_methods, sizeof(struct nic_uio_softc)); DRIVER_MODULE(nic_uio, pci, nic_uio_driver, nic_uio_devclass, nic_uio_modevent, 0); static int nic_uio_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, int prot, vm_memattr_t *memattr) { *paddr = offset; return 0; } static int nic_uio_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj, int nprot) { /* * The BAR index is encoded in the offset. Divide the offset by * PAGE_SIZE to get the index of the bar requested by the user * app. */ unsigned bar = *offset/PAGE_SIZE; struct nic_uio_softc *sc = cdev->si_drv1; if (bar >= MAX_BARS) return EINVAL; if (sc->bar_res[bar] == NULL) { sc->bar_id[bar] = PCIR_BAR(bar); if (PCI_BAR_IO(pci_read_config(sc->dev_t, sc->bar_id[bar], 4))) sc->bar_res[bar] = bus_alloc_resource_any(sc->dev_t, SYS_RES_IOPORT, &sc->bar_id[bar], RF_ACTIVE); else sc->bar_res[bar] = bus_alloc_resource_any(sc->dev_t, SYS_RES_MEMORY, &sc->bar_id[bar], RF_ACTIVE); } if (sc->bar_res[bar] == NULL) return ENXIO; sc->bar_start[bar] = rman_get_start(sc->bar_res[bar]); sc->bar_size[bar] = rman_get_size(sc->bar_res[bar]); device_printf(sc->dev_t, "Bar %u @ %lx, size %lx\n", bar, sc->bar_start[bar], sc->bar_size[bar]); *offset = sc->bar_start[bar]; *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, curthread->td_ucred); return 0; } int nic_uio_open(struct cdev *dev, int oflags, int devtype, struct thread *td) { return 0; } int nic_uio_close(struct cdev *dev, int fflag, int devtype, struct thread *td) { return 0; } static int nic_uio_probe (device_t dev) { int i; unsigned int bus = pci_get_bus(dev); unsigned int device = pci_get_slot(dev); unsigned int function = pci_get_function(dev); for (i = 0; i < num_detached; i++) if (bus == pci_get_bus(detached_devices[i]) && device == pci_get_slot(detached_devices[i]) && function == pci_get_function(detached_devices[i])) { device_set_desc(dev, "DPDK PCI Device"); return BUS_PROBE_SPECIFIC; } return ENXIO; } static int nic_uio_attach(device_t dev) { int i; struct nic_uio_softc *sc; sc = device_get_softc(dev); sc->dev_t = dev; sc->my_cdev = make_dev(&uio_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "uio@pci:%u:%u:%u", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); if (sc->my_cdev == NULL) return ENXIO; sc->my_cdev->si_drv1 = sc; for (i = 0; i < MAX_BARS; i++) sc->bar_res[i] = NULL; pci_enable_busmaster(dev); return 0; } static int nic_uio_detach(device_t dev) { int i; struct nic_uio_softc *sc; sc = device_get_softc(dev); for (i = 0; i < MAX_BARS; i++) if (sc->bar_res[i] != NULL) { if (PCI_BAR_IO(pci_read_config(dev, sc->bar_id[i], 4))) bus_release_resource(dev, SYS_RES_IOPORT, sc->bar_id[i], sc->bar_res[i]); else bus_release_resource(dev, SYS_RES_MEMORY, sc->bar_id[i], sc->bar_res[i]); } if (sc->my_cdev != NULL) destroy_dev(sc->my_cdev); return 0; } static void nic_uio_load(void) { uint32_t bus, device, function; device_t dev; char bdf_str[256]; char *token, *remaining; memset(bdf_str, 0, sizeof(bdf_str)); TUNABLE_STR_FETCH("hw.nic_uio.bdfs", bdf_str, sizeof(bdf_str)); remaining = bdf_str; /* * Users should specify PCI BDFs in the format "b:d:f,b:d:f,b:d:f". * But the code below does not try differentiate between : and , * and just blindly uses 3 tokens at a time to construct a * bus/device/function tuple. * * There is no checking on strtol() return values, but this should * be OK. Worst case is it cannot convert and returns 0. This * could give us a different BDF than intended, but as long as the * PCI device/vendor ID does not match it will not matter. */ while (1) { if (remaining == NULL || remaining[0] == '\0') break; token = strsep(&remaining, ",:"); if (token == NULL) break; bus = strtol(token, NULL, 10); token = strsep(&remaining, ",:"); if (token == NULL) break; device = strtol(token, NULL, 10); token = strsep(&remaining, ",:"); if (token == NULL) break; function = strtol(token, NULL, 10); dev = pci_find_bsf(bus, device, function); if (dev == NULL) continue; if (num_detached < MAX_DETACHED_DEVICES) { printf("nic_uio_load: detaching and storing dev=%p\n", dev); detached_devices[num_detached++] = dev; } else { printf("nic_uio_load: reached MAX_DETACHED_DEVICES=%d. dev=%p won't be reattached\n", MAX_DETACHED_DEVICES, dev); } device_detach(dev); } } static void nic_uio_unload(void) { int i; printf("nic_uio_unload: entered...\n"); for (i = 0; i < num_detached; i++) { printf("nic_uio_unload: calling to device_probe_and_attach for dev=%p...\n", detached_devices[i]); device_probe_and_attach(detached_devices[i]); printf("nic_uio_unload: done.\n"); } printf("nic_uio_unload: leaving...\n"); } static int nic_uio_shutdown(void) { return 0; } static int nic_uio_modevent(module_t mod, int type, void *arg) { switch (type) { case MOD_LOAD: nic_uio_load(); break; case MOD_UNLOAD: nic_uio_unload(); break; case MOD_SHUTDOWN: nic_uio_shutdown(); break; default: break; } return 0; } ================================================ FILE: lib/librte_eal/common/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk INC := rte_branch_prediction.h rte_common.h INC += rte_debug.h rte_eal.h rte_errno.h rte_launch.h rte_lcore.h INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h INC += rte_pci_dev_ids.h rte_per_lcore.h rte_random.h INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_string_fns.h rte_version.h INC += rte_eal_memconfig.h rte_malloc_heap.h INC += rte_hexdump.h rte_devargs.h rte_dev.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y) INC += rte_warnings.h endif GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h # defined in mk/arch/$(RTE_ARCH)/rte.vars.mk ARCH_DIR ?= $(RTE_ARCH) ARCH_INC := $(notdir $(wildcard $(RTE_SDK)/lib/librte_eal/common/include/arch/$(ARCH_DIR)/*.h)) SYMLINK-$(CONFIG_RTE_LIBRTE_EAL)-include := $(addprefix include/,$(INC)) SYMLINK-$(CONFIG_RTE_LIBRTE_EAL)-include += \ $(addprefix include/arch/$(ARCH_DIR)/,$(ARCH_INC)) SYMLINK-$(CONFIG_RTE_LIBRTE_EAL)-include/generic := \ $(addprefix include/generic/,$(GENERIC_INC)) include $(RTE_SDK)/mk/rte.install.mk ================================================ FILE: lib/librte_eal/common/eal_common_cpuflags.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * This should prevent use of advanced instruction sets in this file. Otherwise * the check function itself could cause a crash. */ #ifdef __INTEL_COMPILER #pragma optimize ("", off) #else #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION > 404000 #pragma GCC optimize ("O0") #endif #endif /** * Checks if the machine is adequate for running the binary. If it is not, the * program exits with status 1. * The function attribute forces this function to be called before main(). But * with ICC, the check is generated by the compiler. */ #ifndef __INTEL_COMPILER void __attribute__ ((__constructor__)) #else void #endif rte_cpu_check_supported(void) { /* This is generated at compile-time by the build system */ static const enum rte_cpu_flag_t compile_time_flags[] = { RTE_COMPILE_TIME_CPUFLAGS }; unsigned count = RTE_DIM(compile_time_flags), i; int ret; for (i = 0; i < count; i++) { ret = rte_cpu_get_flag_enabled(compile_time_flags[i]); if (ret < 0) { fprintf(stderr, "ERROR: CPU feature flag lookup failed with error %d\n", ret); exit(1); } if (!ret) { fprintf(stderr, "ERROR: This system does not support \"%s\".\n" "Please check that RTE_MACHINE is set correctly.\n", cpu_feature_table[compile_time_flags[i]].name); exit(1); } } } ================================================ FILE: lib/librte_eal/common/eal_common_dev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "eal_private.h" /** Global list of device drivers. */ static struct rte_driver_list dev_driver_list = TAILQ_HEAD_INITIALIZER(dev_driver_list); /* register a driver */ void rte_eal_driver_register(struct rte_driver *driver) { TAILQ_INSERT_TAIL(&dev_driver_list, driver, next); } /* unregister a driver */ void rte_eal_driver_unregister(struct rte_driver *driver) { TAILQ_REMOVE(&dev_driver_list, driver, next); } int rte_eal_vdev_init(const char *name, const char *args) { struct rte_driver *driver; if (name == NULL) return -EINVAL; TAILQ_FOREACH(driver, &dev_driver_list, next) { if (driver->type != PMD_VDEV) continue; /* * search a driver prefix in virtual device name. * For example, if the driver is pcap PMD, driver->name * will be "eth_pcap", but "name" will be "eth_pcapN". * So use strncmp to compare. */ if (!strncmp(driver->name, name, strlen(driver->name))) return driver->init(name, args); } RTE_LOG(ERR, EAL, "no driver found for %s\n", name); return -EINVAL; } int rte_eal_dev_init(void) { struct rte_devargs *devargs; struct rte_driver *driver; /* * Note that the dev_driver_list is populated here * from calls made to rte_eal_driver_register from constructor functions * embedded into PMD modules via the PMD_REGISTER_DRIVER macro */ /* call the init function for each virtual device */ TAILQ_FOREACH(devargs, &devargs_list, next) { if (devargs->type != RTE_DEVTYPE_VIRTUAL) continue; if (rte_eal_vdev_init(devargs->virtual.drv_name, devargs->args)) { RTE_LOG(ERR, EAL, "failed to initialize %s device\n", devargs->virtual.drv_name); return -1; } } /* Once the vdevs are initalized, start calling all the pdev drivers */ TAILQ_FOREACH(driver, &dev_driver_list, next) { if (driver->type != PMD_PDEV) continue; /* PDEV drivers don't get passed any parameters */ driver->init(NULL, NULL); } return 0; } int rte_eal_vdev_uninit(const char *name) { struct rte_driver *driver; if (name == NULL) return -EINVAL; TAILQ_FOREACH(driver, &dev_driver_list, next) { if (driver->type != PMD_VDEV) continue; /* * search a driver prefix in virtual device name. * For example, if the driver is pcap PMD, driver->name * will be "eth_pcap", but "name" will be "eth_pcapN". * So use strncmp to compare. */ if (!strncmp(driver->name, name, strlen(driver->name))) return driver->uninit(name); } RTE_LOG(ERR, EAL, "no driver found for %s\n", name); return -EINVAL; } ================================================ FILE: lib/librte_eal/common/eal_common_devargs.c ================================================ /*- * BSD LICENSE * * Copyright 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* This file manages the list of devices and their arguments, as given * by the user at startup * * Code here should not call rte_log since the EAL environment * may not be initialized. */ #include #include #include #include #include "eal_private.h" /** Global list of user devices */ struct rte_devargs_list devargs_list = TAILQ_HEAD_INITIALIZER(devargs_list); int rte_eal_parse_devargs_str(const char *devargs_str, char **drvname, char **drvargs) { char *sep; if ((devargs_str) == NULL || (drvname) == NULL || (drvargs == NULL)) return -1; *drvname = strdup(devargs_str); if (drvname == NULL) return -1; /* set the first ',' to '\0' to split name and arguments */ sep = strchr(*drvname, ','); if (sep != NULL) { sep[0] = '\0'; *drvargs = strdup(sep + 1); } else { *drvargs = strdup(""); } if (*drvargs == NULL) { free(*drvname); return -1; } return 0; } /* store a whitelist parameter for later parsing */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str) { struct rte_devargs *devargs = NULL; char *buf = NULL; int ret; /* use malloc instead of rte_malloc as it's called early at init */ devargs = malloc(sizeof(*devargs)); if (devargs == NULL) goto fail; memset(devargs, 0, sizeof(*devargs)); devargs->type = devtype; if (rte_eal_parse_devargs_str(devargs_str, &buf, &devargs->args)) goto fail; switch (devargs->type) { case RTE_DEVTYPE_WHITELISTED_PCI: case RTE_DEVTYPE_BLACKLISTED_PCI: /* try to parse pci identifier */ if (eal_parse_pci_BDF(buf, &devargs->pci.addr) != 0 && eal_parse_pci_DomBDF(buf, &devargs->pci.addr) != 0) goto fail; break; case RTE_DEVTYPE_VIRTUAL: /* save driver name */ ret = snprintf(devargs->virtual.drv_name, sizeof(devargs->virtual.drv_name), "%s", buf); if (ret < 0 || ret >= (int)sizeof(devargs->virtual.drv_name)) goto fail; break; } free(buf); TAILQ_INSERT_TAIL(&devargs_list, devargs, next); return 0; fail: if (buf) free(buf); if (devargs) { free(devargs->args); free(devargs); } return -1; } /* count the number of devices of a specified type */ unsigned int rte_eal_devargs_type_count(enum rte_devtype devtype) { struct rte_devargs *devargs; unsigned int count = 0; TAILQ_FOREACH(devargs, &devargs_list, next) { if (devargs->type != devtype) continue; count++; } return count; } /* dump the user devices on the console */ void rte_eal_devargs_dump(FILE *f) { struct rte_devargs *devargs; fprintf(f, "User device white list:\n"); TAILQ_FOREACH(devargs, &devargs_list, next) { if (devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) fprintf(f, " PCI whitelist " PCI_PRI_FMT " %s\n", devargs->pci.addr.domain, devargs->pci.addr.bus, devargs->pci.addr.devid, devargs->pci.addr.function, devargs->args); else if (devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) fprintf(f, " PCI blacklist " PCI_PRI_FMT " %s\n", devargs->pci.addr.domain, devargs->pci.addr.bus, devargs->pci.addr.devid, devargs->pci.addr.function, devargs->args); else if (devargs->type == RTE_DEVTYPE_VIRTUAL) fprintf(f, " VIRTUAL %s %s\n", devargs->virtual.drv_name, devargs->args); else fprintf(f, " UNKNOWN %s\n", devargs->args); } } ================================================ FILE: lib/librte_eal/common/eal_common_errno.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include RTE_DEFINE_PER_LCORE(int, _rte_errno); const char * rte_strerror(int errnum) { #define RETVAL_SZ 256 static RTE_DEFINE_PER_LCORE(char[RETVAL_SZ], retval); /* since some implementations of strerror_r throw an error * themselves if errnum is too big, we handle that case here */ if (errnum > RTE_MAX_ERRNO) snprintf(RTE_PER_LCORE(retval), RETVAL_SZ, #ifdef RTE_EXEC_ENV_BSDAPP "Unknown error: %d", errnum); #else "Unknown error %d", errnum); #endif else switch (errnum){ case E_RTE_SECONDARY: return "Invalid call in secondary process"; case E_RTE_NO_CONFIG: return "Missing rte_config structure"; default: strerror_r(errnum, RTE_PER_LCORE(retval), RETVAL_SZ); } return RTE_PER_LCORE(retval); } ================================================ FILE: lib/librte_eal/common/eal_common_hexdump.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #define LINE_LEN 128 /**************************************************************************//** * * rte_hexdump - Dump out memory in a special hex dump format. * * DESCRIPTION * Dump out the message buffer in a special hex dump output format with characters * printed for each line of 16 hex values. * * RETURNS: N/A * * SEE ALSO: */ void rte_hexdump(FILE *f, const char * title, const void * buf, unsigned int len) { unsigned int i, out, ofs; const unsigned char *data = buf; char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */ fprintf(f, "%s at [%p], len=%u\n", (title)? title : " Dump data", data, len); ofs = 0; while (ofs < len) { /* format the line in the buffer, then use printf to output to screen */ out = snprintf(line, LINE_LEN, "%08X:", ofs); for (i = 0; ((ofs + i) < len) && (i < 16); i++) out += snprintf(line+out, LINE_LEN - out, " %02X", (data[ofs+i] & 0xff)); for(; i <= 16; i++) out += snprintf(line+out, LINE_LEN - out, " | "); for(i = 0; (ofs < len) && (i < 16); i++, ofs++) { unsigned char c = data[ofs]; if ( (c < ' ') || (c > '~')) c = '.'; out += snprintf(line+out, LINE_LEN - out, "%c", c); } fprintf(f, "%s\n", line); } fflush(f); } /**************************************************************************//** * * rte_memdump - Dump out memory in hex bytes with colons. * * DESCRIPTION * Dump out the message buffer in hex bytes with colons xx:xx:xx:xx:... * * RETURNS: N/A * * SEE ALSO: */ void rte_memdump(FILE *f, const char * title, const void * buf, unsigned int len) { unsigned int i, out; const unsigned char *data = buf; char line[LINE_LEN]; if ( title ) fprintf(f, "%s: ", title); line[0] = '\0'; for (i = 0, out = 0; i < len; i++) { // Make sure we do not overrun the line buffer length. if ( out >= (LINE_LEN - 4) ) { fprintf(f, "%s", line); out = 0; line[out] = '\0'; } out += snprintf(line+out, LINE_LEN - out, "%02x%s", (data[i] & 0xff), ((i+1) < len)? ":" : ""); } if ( out > 0 ) fprintf(f, "%s", line); fprintf(f, "\n"); fflush(f); } ================================================ FILE: lib/librte_eal/common/eal_common_launch.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include /* * Wait until a lcore finished its job. */ int rte_eal_wait_lcore(unsigned slave_id) { if (lcore_config[slave_id].state == WAIT) return 0; while (lcore_config[slave_id].state != WAIT && lcore_config[slave_id].state != FINISHED); rte_rmb(); /* we are in finished state, go to wait state */ lcore_config[slave_id].state = WAIT; return lcore_config[slave_id].ret; } /* * Check that every SLAVE lcores are in WAIT state, then call * rte_eal_remote_launch() for all of them. If call_master is true * (set to CALL_MASTER), also call the function on the master lcore. */ int rte_eal_mp_remote_launch(int (*f)(void *), void *arg, enum rte_rmt_call_master_t call_master) { int lcore_id; int master = rte_get_master_lcore(); /* check state of lcores */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (lcore_config[lcore_id].state != WAIT) return -EBUSY; } /* send messages to cores */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_remote_launch(f, arg, lcore_id); } if (call_master == CALL_MASTER) { lcore_config[master].ret = f(arg); lcore_config[master].state = FINISHED; } return 0; } /* * Return the state of the lcore identified by slave_id. */ enum rte_lcore_state_t rte_eal_get_lcore_state(unsigned lcore_id) { return lcore_config[lcore_id].state; } /* * Do a rte_eal_wait_lcore() for every lcore. The return values are * ignored. */ void rte_eal_mp_wait_lcore(void) { unsigned lcore_id; RTE_LCORE_FOREACH_SLAVE(lcore_id) { rte_eal_wait_lcore(lcore_id); } } ================================================ FILE: lib/librte_eal/common/eal_common_lcore.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" /* * Parse /sys/devices/system/cpu to get the number of physical and logical * processors on the machine. The function will fill the cpu_info * structure. */ int rte_eal_cpu_init(void) { /* pointer to global configuration */ struct rte_config *config = rte_eal_get_configuration(); unsigned lcore_id; unsigned count = 0; /* * Parse the maximum set of logical cores, detect the subset of running * ones and enable them by default. */ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { /* init cpuset for per lcore config */ CPU_ZERO(&lcore_config[lcore_id].cpuset); /* in 1:1 mapping, record related cpu detected state */ lcore_config[lcore_id].detected = eal_cpu_detected(lcore_id); if (lcore_config[lcore_id].detected == 0) { config->lcore_role[lcore_id] = ROLE_OFF; continue; } /* By default, lcore 1:1 map to cpu id */ CPU_SET(lcore_id, &lcore_config[lcore_id].cpuset); /* By default, each detected core is enabled */ config->lcore_role[lcore_id] = ROLE_RTE; lcore_config[lcore_id].core_id = eal_cpu_core_id(lcore_id); lcore_config[lcore_id].socket_id = eal_cpu_socket_id(lcore_id); if (lcore_config[lcore_id].socket_id >= RTE_MAX_NUMA_NODES) #ifdef RTE_EAL_ALLOW_INV_SOCKET_ID lcore_config[lcore_id].socket_id = 0; #else rte_panic("Socket ID (%u) is greater than " "RTE_MAX_NUMA_NODES (%d)\n", lcore_config[lcore_id].socket_id, RTE_MAX_NUMA_NODES); #endif RTE_LOG(DEBUG, EAL, "Detected lcore %u as " "core %u on socket %u\n", lcore_id, lcore_config[lcore_id].core_id, lcore_config[lcore_id].socket_id); count++; } /* Set the count of enabled logical cores of the EAL configuration */ config->lcore_count = count; RTE_LOG(DEBUG, EAL, "Support maximum %u logical core(s) by configuration.\n", RTE_MAX_LCORE); RTE_LOG(DEBUG, EAL, "Detected %u lcore(s)\n", config->lcore_count); return 0; } ================================================ FILE: lib/librte_eal/common/eal_common_log.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #define LOG_ELT_SIZE 2048 #define LOG_HISTORY_MP_NAME "log_history" STAILQ_HEAD(log_history_list, log_history); /** * The structure of a message log in the log history. */ struct log_history { STAILQ_ENTRY(log_history) next; unsigned size; char buf[0]; }; static struct rte_mempool *log_history_mp = NULL; static unsigned log_history_size = 0; static struct log_history_list log_history; /* global log structure */ struct rte_logs rte_logs = { .type = ~0, .level = RTE_LOG_DEBUG, .file = NULL, }; static rte_spinlock_t log_dump_lock = RTE_SPINLOCK_INITIALIZER; static rte_spinlock_t log_list_lock = RTE_SPINLOCK_INITIALIZER; static FILE *default_log_stream; static int history_enabled = 1; /** * This global structure stores some informations about the message * that is currently beeing processed by one lcore */ struct log_cur_msg { uint32_t loglevel; /**< log level - see rte_log.h */ uint32_t logtype; /**< log type - see rte_log.h */ } __rte_cache_aligned; static struct log_cur_msg log_cur_msg[RTE_MAX_LCORE]; /**< per core log */ /* default logs */ int rte_log_add_in_history(const char *buf, size_t size) { struct log_history *hist_buf = NULL; static const unsigned hist_buf_size = LOG_ELT_SIZE - sizeof(*hist_buf); void *obj; if (history_enabled == 0) return 0; rte_spinlock_lock(&log_list_lock); /* get a buffer for adding in history */ if (log_history_size > RTE_LOG_HISTORY) { hist_buf = STAILQ_FIRST(&log_history); if (hist_buf) { STAILQ_REMOVE_HEAD(&log_history, next); log_history_size--; } } else { if (rte_mempool_mc_get(log_history_mp, &obj) < 0) obj = NULL; hist_buf = obj; } /* no buffer */ if (hist_buf == NULL) { rte_spinlock_unlock(&log_list_lock); return -ENOBUFS; } /* not enough room for msg, buffer go back in mempool */ if (size >= hist_buf_size) { rte_mempool_mp_put(log_history_mp, hist_buf); rte_spinlock_unlock(&log_list_lock); return -ENOBUFS; } /* add in history */ memcpy(hist_buf->buf, buf, size); hist_buf->buf[size] = hist_buf->buf[hist_buf_size-1] = '\0'; hist_buf->size = size; STAILQ_INSERT_TAIL(&log_history, hist_buf, next); log_history_size++; rte_spinlock_unlock(&log_list_lock); return 0; } void rte_log_set_history(int enable) { history_enabled = enable; } /* Change the stream that will be used by logging system */ int rte_openlog_stream(FILE *f) { if (f == NULL) rte_logs.file = default_log_stream; else rte_logs.file = f; return 0; } /* Set global log level */ void rte_set_log_level(uint32_t level) { rte_logs.level = (uint32_t)level; } /* Get global log level */ uint32_t rte_get_log_level(void) { return rte_logs.level; } /* Set global log type */ void rte_set_log_type(uint32_t type, int enable) { if (enable) rte_logs.type |= type; else rte_logs.type &= (~type); } /* Get global log type */ uint32_t rte_get_log_type(void) { return rte_logs.type; } /* get the current loglevel for the message beeing processed */ int rte_log_cur_msg_loglevel(void) { unsigned lcore_id; lcore_id = rte_lcore_id(); if (lcore_id >= RTE_MAX_LCORE) return rte_get_log_level(); return log_cur_msg[lcore_id].loglevel; } /* get the current logtype for the message beeing processed */ int rte_log_cur_msg_logtype(void) { unsigned lcore_id; lcore_id = rte_lcore_id(); if (lcore_id >= RTE_MAX_LCORE) return rte_get_log_type(); return log_cur_msg[lcore_id].logtype; } /* Dump log history to file */ void rte_log_dump_history(FILE *out) { struct log_history_list tmp_log_history; struct log_history *hist_buf; unsigned i; /* only one dump at a time */ rte_spinlock_lock(&log_dump_lock); /* save list, and re-init to allow logging during dump */ rte_spinlock_lock(&log_list_lock); tmp_log_history = log_history; STAILQ_INIT(&log_history); log_history_size = 0; rte_spinlock_unlock(&log_list_lock); for (i=0; ibuf, hist_buf->size, 1, out) == 0) { rte_mempool_mp_put(log_history_mp, hist_buf); break; } /* put back message structure in pool */ rte_mempool_mp_put(log_history_mp, hist_buf); } fflush(out); rte_spinlock_unlock(&log_dump_lock); } /* * Generates a log message The message will be sent in the stream * defined by the previous call to rte_openlog_stream(). */ int rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap) { int ret; FILE *f = rte_logs.file; unsigned lcore_id; if ((level > rte_logs.level) || !(logtype & rte_logs.type)) return 0; /* save loglevel and logtype in a global per-lcore variable */ lcore_id = rte_lcore_id(); if (lcore_id < RTE_MAX_LCORE) { log_cur_msg[lcore_id].loglevel = level; log_cur_msg[lcore_id].logtype = logtype; } ret = vfprintf(f, format, ap); fflush(f); return ret; } /* * Generates a log message The message will be sent in the stream * defined by the previous call to rte_openlog_stream(). * No need to check level here, done by rte_vlog(). */ int rte_log(uint32_t level, uint32_t logtype, const char *format, ...) { va_list ap; int ret; va_start(ap, format); ret = rte_vlog(level, logtype, format, ap); va_end(ap); return ret; } /* * called by environment-specific log init function to initialize log * history */ int rte_eal_common_log_init(FILE *default_log) { STAILQ_INIT(&log_history); /* reserve RTE_LOG_HISTORY*2 elements, so we can dump and * keep logging during this time */ log_history_mp = rte_mempool_create(LOG_HISTORY_MP_NAME, RTE_LOG_HISTORY*2, LOG_ELT_SIZE, 0, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); if ((log_history_mp == NULL) && ((log_history_mp = rte_mempool_lookup(LOG_HISTORY_MP_NAME)) == NULL)){ RTE_LOG(ERR, EAL, "%s(): cannot create log_history mempool\n", __func__); return -1; } default_log_stream = default_log; rte_openlog_stream(default_log); return 0; } ================================================ FILE: lib/librte_eal/common/eal_common_memory.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" /* * Return a pointer to a read-only table of struct rte_physmem_desc * elements, containing the layout of all addressable physical * memory. The last element of the table contains a NULL address. */ const struct rte_memseg * rte_eal_get_physmem_layout(void) { return rte_eal_get_configuration()->mem_config->memseg; } /* get the total size of memory */ uint64_t rte_eal_get_physmem_size(void) { const struct rte_mem_config *mcfg; unsigned i = 0; uint64_t total_len = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (mcfg->memseg[i].addr == NULL) break; total_len += mcfg->memseg[i].len; } return total_len; } /* Dump the physical memory layout on console */ void rte_dump_physmem_layout(FILE *f) { const struct rte_mem_config *mcfg; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (mcfg->memseg[i].addr == NULL) break; fprintf(f, "Segment %u: phys:0x%"PRIx64", len:%zu, " "virt:%p, socket_id:%"PRId32", " "hugepage_sz:%"PRIu64", nchannel:%"PRIx32", " "nrank:%"PRIx32"\n", i, mcfg->memseg[i].phys_addr, mcfg->memseg[i].len, mcfg->memseg[i].addr, mcfg->memseg[i].socket_id, mcfg->memseg[i].hugepage_sz, mcfg->memseg[i].nchannel, mcfg->memseg[i].nrank); } } /* return the number of memory channels */ unsigned rte_memory_get_nchannel(void) { return rte_eal_get_configuration()->mem_config->nchannel; } /* return the number of memory rank */ unsigned rte_memory_get_nrank(void) { return rte_eal_get_configuration()->mem_config->nrank; } static int rte_eal_memdevice_init(void) { struct rte_config *config; if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; config = rte_eal_get_configuration(); config->mem_config->nchannel = internal_config.force_nchannel; config->mem_config->nrank = internal_config.force_nrank; return 0; } /* init memory subsystem */ int rte_eal_memory_init(void) { RTE_LOG(INFO, EAL, "Setting up physically contiguous memory...\n"); const int retval = rte_eal_process_type() == RTE_PROC_PRIMARY ? rte_eal_hugepage_init() : rte_eal_hugepage_attach(); if (retval < 0) return -1; if (internal_config.no_shconf == 0 && rte_eal_memdevice_init() < 0) return -1; return 0; } ================================================ FILE: lib/librte_eal/common/eal_common_memzone.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "malloc_heap.h" #include "malloc_elem.h" #include "eal_private.h" static inline const struct rte_memzone * memzone_lookup_thread_unsafe(const char *name) { const struct rte_mem_config *mcfg; const struct rte_memzone *mz; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* * the algorithm is not optimal (linear), but there are few * zones and this function should be called at init only */ for (i = 0; i < RTE_MAX_MEMZONE; i++) { mz = &mcfg->memzone[i]; if (mz->addr != NULL && !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE)) return &mcfg->memzone[i]; } return NULL; } static inline struct rte_memzone * get_next_free_memzone(void) { struct rte_mem_config *mcfg; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMZONE; i++) { if (mcfg->memzone[i].addr == NULL) return &mcfg->memzone[i]; } return NULL; } /* This function will return the greatest free block if a heap has been * specified. If no heap has been specified, it will return the heap and * length of the greatest free block available in all heaps */ static size_t find_heap_max_free_elem(int *s, unsigned align) { struct rte_mem_config *mcfg; struct rte_malloc_socket_stats stats; int i, socket = *s; size_t len = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { if ((socket != SOCKET_ID_ANY) && (socket != i)) continue; malloc_heap_get_stats(&mcfg->malloc_heaps[i], &stats); if (stats.greatest_free_size > len) { len = stats.greatest_free_size; *s = i; } } return (len - MALLOC_ELEM_OVERHEAD - align); } static const struct rte_memzone * memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, int socket_id, unsigned flags, unsigned align, unsigned bound) { struct rte_mem_config *mcfg; size_t requested_len; int socket, i; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* no more room in config */ if (mcfg->memzone_cnt >= RTE_MAX_MEMZONE) { RTE_LOG(ERR, EAL, "%s(): No more room in config\n", __func__); rte_errno = ENOSPC; return NULL; } /* zone already exist */ if ((memzone_lookup_thread_unsafe(name)) != NULL) { RTE_LOG(DEBUG, EAL, "%s(): memzone <%s> already exists\n", __func__, name); rte_errno = EEXIST; return NULL; } /* if alignment is not a power of two */ if (align && !rte_is_power_of_2(align)) { RTE_LOG(ERR, EAL, "%s(): Invalid alignment: %u\n", __func__, align); rte_errno = EINVAL; return NULL; } /* alignment less than cache size is not allowed */ if (align < RTE_CACHE_LINE_SIZE) align = RTE_CACHE_LINE_SIZE; /* align length on cache boundary. Check for overflow before doing so */ if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) { rte_errno = EINVAL; /* requested size too big */ return NULL; } len += RTE_CACHE_LINE_MASK; len &= ~((size_t) RTE_CACHE_LINE_MASK); /* save minimal requested length */ requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len); /* check that boundary condition is valid */ if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) { rte_errno = EINVAL; return NULL; } if ((socket_id != SOCKET_ID_ANY) && (socket_id >= RTE_MAX_NUMA_NODES)) { rte_errno = EINVAL; return NULL; } if (!rte_eal_has_hugepages()) socket_id = SOCKET_ID_ANY; if (len == 0) { if (bound != 0) requested_len = bound; else requested_len = find_heap_max_free_elem(&socket_id, align); } if (socket_id == SOCKET_ID_ANY) socket = malloc_get_numa_socket(); else socket = socket_id; /* allocate memory on heap */ void *mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[socket], NULL, requested_len, flags, align, bound); if ((mz_addr == NULL) && (socket_id == SOCKET_ID_ANY)) { /* try other heaps */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { if (socket == i) continue; mz_addr = malloc_heap_alloc(&mcfg->malloc_heaps[i], NULL, requested_len, flags, align, bound); if (mz_addr != NULL) break; } } if (mz_addr == NULL) { rte_errno = ENOMEM; return NULL; } const struct malloc_elem *elem = malloc_elem_from_data(mz_addr); /* fill the zone in config */ struct rte_memzone *mz = get_next_free_memzone(); if (mz == NULL) { RTE_LOG(ERR, EAL, "%s(): Cannot find free memzone but there is room " "in config!\n", __func__); rte_errno = ENOSPC; return NULL; } mcfg->memzone_cnt++; snprintf(mz->name, sizeof(mz->name), "%s", name); mz->phys_addr = rte_malloc_virt2phy(mz_addr); mz->addr = mz_addr; mz->len = (requested_len == 0 ? elem->size : requested_len); mz->hugepage_sz = elem->ms->hugepage_sz; mz->socket_id = elem->ms->socket_id; mz->flags = 0; mz->memseg_id = elem->ms - rte_eal_get_configuration()->mem_config->memseg; return mz; } static const struct rte_memzone * rte_memzone_reserve_thread_safe(const char *name, size_t len, int socket_id, unsigned flags, unsigned align, unsigned bound) { struct rte_mem_config *mcfg; const struct rte_memzone *mz = NULL; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_write_lock(&mcfg->mlock); mz = memzone_reserve_aligned_thread_unsafe( name, len, socket_id, flags, align, bound); rte_rwlock_write_unlock(&mcfg->mlock); return mz; } /* * Return a pointer to a correctly filled memzone descriptor (with a * specified alignment and boundary). If the allocation cannot be done, * return NULL. */ const struct rte_memzone * rte_memzone_reserve_bounded(const char *name, size_t len, int socket_id, unsigned flags, unsigned align, unsigned bound) { return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, align, bound); } /* * Return a pointer to a correctly filled memzone descriptor (with a * specified alignment). If the allocation cannot be done, return NULL. */ const struct rte_memzone * rte_memzone_reserve_aligned(const char *name, size_t len, int socket_id, unsigned flags, unsigned align) { return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, align, 0); } /* * Return a pointer to a correctly filled memzone descriptor. If the * allocation cannot be done, return NULL. */ const struct rte_memzone * rte_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) { return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, RTE_CACHE_LINE_SIZE, 0); } int rte_memzone_free(const struct rte_memzone *mz) { struct rte_mem_config *mcfg; int ret = 0; void *addr; unsigned idx; if (mz == NULL) return -EINVAL; mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_write_lock(&mcfg->mlock); idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone); idx = idx / sizeof(struct rte_memzone); addr = mcfg->memzone[idx].addr; #ifdef RTE_LIBRTE_IVSHMEM /* * If ioremap_addr is set, it's an IVSHMEM memzone and we cannot * free it. */ if (mcfg->memzone[idx].ioremap_addr != 0) ret = -EINVAL; #endif if (addr == NULL) ret = -EINVAL; else if (mcfg->memzone_cnt == 0) { rte_panic("%s(): memzone address not NULL but memzone_cnt is 0!\n", __func__); } else { memset(&mcfg->memzone[idx], 0, sizeof(mcfg->memzone[idx])); mcfg->memzone_cnt--; } rte_rwlock_write_unlock(&mcfg->mlock); rte_free(addr); return ret; } /* * Lookup for the memzone identified by the given name */ const struct rte_memzone * rte_memzone_lookup(const char *name) { struct rte_mem_config *mcfg; const struct rte_memzone *memzone = NULL; mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_read_lock(&mcfg->mlock); memzone = memzone_lookup_thread_unsafe(name); rte_rwlock_read_unlock(&mcfg->mlock); return memzone; } /* Dump all reserved memory zones on console */ void rte_memzone_dump(FILE *f) { struct rte_mem_config *mcfg; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_read_lock(&mcfg->mlock); /* dump all zones */ for (i=0; imemzone[i].addr == NULL) break; fprintf(f, "Zone %u: name:<%s>, phys:0x%"PRIx64", len:0x%zx" ", virt:%p, socket_id:%"PRId32", flags:%"PRIx32"\n", i, mcfg->memzone[i].name, mcfg->memzone[i].phys_addr, mcfg->memzone[i].len, mcfg->memzone[i].addr, mcfg->memzone[i].socket_id, mcfg->memzone[i].flags); } rte_rwlock_read_unlock(&mcfg->mlock); } /* * Init the memzone subsystem */ int rte_eal_memzone_init(void) { struct rte_mem_config *mcfg; const struct rte_memseg *memseg; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* secondary processes don't need to initialise anything */ if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; memseg = rte_eal_get_physmem_layout(); if (memseg == NULL) { RTE_LOG(ERR, EAL, "%s(): Cannot get physical layout\n", __func__); return -1; } rte_rwlock_write_lock(&mcfg->mlock); /* delete all zones */ mcfg->memzone_cnt = 0; memset(mcfg->memzone, 0, sizeof(mcfg->memzone)); rte_rwlock_write_unlock(&mcfg->mlock); return rte_eal_malloc_heap_init(); } /* Walk all reserved memory zones */ void rte_memzone_walk(void (*func)(const struct rte_memzone *, void *), void *arg) { struct rte_mem_config *mcfg; unsigned i; mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_read_lock(&mcfg->mlock); for (i=0; imemzone[i].addr != NULL) (*func)(&mcfg->memzone[i], arg); } rte_rwlock_read_unlock(&mcfg->mlock); } ================================================ FILE: lib/librte_eal/common/eal_common_options.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_internal_cfg.h" #include "eal_options.h" #include "eal_filesystem.h" #define BITS_PER_HEX 4 const char eal_short_options[] = "b:" /* pci-blacklist */ "c:" /* coremask */ "d:" /* driver */ "h" /* help */ "l:" /* corelist */ "m:" /* memory size */ "n:" /* memory channels */ "r:" /* memory ranks */ "v" /* version */ "w:" /* pci-whitelist */ ; const struct option eal_long_options[] = { {OPT_BASE_VIRTADDR, 1, NULL, OPT_BASE_VIRTADDR_NUM }, {OPT_CREATE_UIO_DEV, 0, NULL, OPT_CREATE_UIO_DEV_NUM }, {OPT_FILE_PREFIX, 1, NULL, OPT_FILE_PREFIX_NUM }, {OPT_HELP, 0, NULL, OPT_HELP_NUM }, {OPT_HUGE_DIR, 1, NULL, OPT_HUGE_DIR_NUM }, {OPT_LCORES, 1, NULL, OPT_LCORES_NUM }, {OPT_LOG_LEVEL, 1, NULL, OPT_LOG_LEVEL_NUM }, {OPT_MASTER_LCORE, 1, NULL, OPT_MASTER_LCORE_NUM }, {OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM }, {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM }, {OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM }, {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM }, {OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM }, {OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM }, {OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM }, {OPT_SOCKET_MEM, 1, NULL, OPT_SOCKET_MEM_NUM }, {OPT_SYSLOG, 1, NULL, OPT_SYSLOG_NUM }, {OPT_VDEV, 1, NULL, OPT_VDEV_NUM }, {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM }, {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM }, {OPT_XEN_DOM0, 0, NULL, OPT_XEN_DOM0_NUM }, {0, 0, NULL, 0 } }; static int lcores_parsed; static int master_lcore_parsed; static int mem_parsed; void eal_reset_internal_config(struct internal_config *internal_cfg) { int i; internal_cfg->memory = 0; internal_cfg->force_nrank = 0; internal_cfg->force_nchannel = 0; internal_cfg->hugefile_prefix = HUGEFILE_PREFIX_DEFAULT; internal_cfg->hugepage_dir = NULL; internal_cfg->force_sockets = 0; /* zero out the NUMA config */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) internal_cfg->socket_mem[i] = 0; /* zero out hugedir descriptors */ for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) internal_cfg->hugepage_info[i].lock_descriptor = -1; internal_cfg->base_virtaddr = 0; internal_cfg->syslog_facility = LOG_DAEMON; /* default value from build option */ internal_cfg->log_level = RTE_LOG_LEVEL; internal_cfg->xen_dom0_support = 0; /* if set to NONE, interrupt mode is determined automatically */ internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE; #ifdef RTE_LIBEAL_USE_HPET internal_cfg->no_hpet = 0; #else internal_cfg->no_hpet = 1; #endif internal_cfg->vmware_tsc_map = 0; internal_cfg->create_uio_dev = 0; } /* * Parse the coremask given as argument (hexadecimal string) and fill * the global configuration (core role and core count) with the parsed * value. */ static int xdigit2val(unsigned char c) { int val; if (isdigit(c)) val = c - '0'; else if (isupper(c)) val = c - 'A' + 10; else val = c - 'a' + 10; return val; } static int eal_parse_coremask(const char *coremask) { struct rte_config *cfg = rte_eal_get_configuration(); int i, j, idx = 0; unsigned count = 0; char c; int val; if (coremask == NULL) return -1; /* Remove all blank characters ahead and after . * Remove 0x/0X if exists. */ while (isblank(*coremask)) coremask++; if (coremask[0] == '0' && ((coremask[1] == 'x') || (coremask[1] == 'X'))) coremask += 2; i = strlen(coremask); while ((i > 0) && isblank(coremask[i - 1])) i--; if (i == 0) return -1; for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) { c = coremask[i]; if (isxdigit(c) == 0) { /* invalid characters */ return -1; } val = xdigit2val(c); for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++) { if ((1 << j) & val) { if (!lcore_config[idx].detected) { RTE_LOG(ERR, EAL, "lcore %u " "unavailable\n", idx); return -1; } cfg->lcore_role[idx] = ROLE_RTE; lcore_config[idx].core_index = count; count++; } else { cfg->lcore_role[idx] = ROLE_OFF; lcore_config[idx].core_index = -1; } } } for (; i >= 0; i--) if (coremask[i] != '0') return -1; for (; idx < RTE_MAX_LCORE; idx++) { cfg->lcore_role[idx] = ROLE_OFF; lcore_config[idx].core_index = -1; } if (count == 0) return -1; /* Update the count of enabled logical cores of the EAL configuration */ cfg->lcore_count = count; lcores_parsed = 1; return 0; } static int eal_parse_corelist(const char *corelist) { struct rte_config *cfg = rte_eal_get_configuration(); int i, idx = 0; unsigned count = 0; char *end = NULL; int min, max; if (corelist == NULL) return -1; /* Remove all blank characters ahead and after */ while (isblank(*corelist)) corelist++; i = strlen(corelist); while ((i > 0) && isblank(corelist[i - 1])) i--; /* Reset config */ for (idx = 0; idx < RTE_MAX_LCORE; idx++) { cfg->lcore_role[idx] = ROLE_OFF; lcore_config[idx].core_index = -1; } /* Get list of cores */ min = RTE_MAX_LCORE; do { while (isblank(*corelist)) corelist++; if (*corelist == '\0') return -1; errno = 0; idx = strtoul(corelist, &end, 10); if (errno || end == NULL) return -1; while (isblank(*end)) end++; if (*end == '-') { min = idx; } else if ((*end == ',') || (*end == '\0')) { max = idx; if (min == RTE_MAX_LCORE) min = idx; for (idx = min; idx <= max; idx++) { if (cfg->lcore_role[idx] != ROLE_RTE) { cfg->lcore_role[idx] = ROLE_RTE; lcore_config[idx].core_index = count; count++; } } min = RTE_MAX_LCORE; } else return -1; corelist = end + 1; } while (*end != '\0'); if (count == 0) return -1; /* Update the count of enabled logical cores of the EAL configuration */ cfg->lcore_count = count; lcores_parsed = 1; return 0; } /* Changes the lcore id of the master thread */ static int eal_parse_master_lcore(const char *arg) { char *parsing_end; struct rte_config *cfg = rte_eal_get_configuration(); errno = 0; cfg->master_lcore = (uint32_t) strtol(arg, &parsing_end, 0); if (errno || parsing_end[0] != 0) return -1; if (cfg->master_lcore >= RTE_MAX_LCORE) return -1; master_lcore_parsed = 1; return 0; } /* * Parse elem, the elem could be single number/range or '(' ')' group * 1) A single number elem, it's just a simple digit. e.g. 9 * 2) A single range elem, two digits with a '-' between. e.g. 2-6 * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6) * Within group elem, '-' used for a range separator; * ',' used for a single number. */ static int eal_parse_set(const char *input, uint16_t set[], unsigned num) { unsigned idx; const char *str = input; char *end = NULL; unsigned min, max; memset(set, 0, num * sizeof(uint16_t)); while (isblank(*str)) str++; /* only digit or left bracket is qualify for start point */ if ((!isdigit(*str) && *str != '(') || *str == '\0') return -1; /* process single number or single range of number */ if (*str != '(') { errno = 0; idx = strtoul(str, &end, 10); if (errno || end == NULL || idx >= num) return -1; else { while (isblank(*end)) end++; min = idx; max = idx; if (*end == '-') { /* process single - */ end++; while (isblank(*end)) end++; if (!isdigit(*end)) return -1; errno = 0; idx = strtoul(end, &end, 10); if (errno || end == NULL || idx >= num) return -1; max = idx; while (isblank(*end)) end++; if (*end != ',' && *end != '\0') return -1; } if (*end != ',' && *end != '\0' && *end != '@') return -1; for (idx = RTE_MIN(min, max); idx <= RTE_MAX(min, max); idx++) set[idx] = 1; return end - input; } } /* process set within bracket */ str++; while (isblank(*str)) str++; if (*str == '\0') return -1; min = RTE_MAX_LCORE; do { /* go ahead to the first digit */ while (isblank(*str)) str++; if (!isdigit(*str)) return -1; /* get the digit value */ errno = 0; idx = strtoul(str, &end, 10); if (errno || end == NULL || idx >= num) return -1; /* go ahead to separator '-',',' and ')' */ while (isblank(*end)) end++; if (*end == '-') { if (min == RTE_MAX_LCORE) min = idx; else /* avoid continuous '-' */ return -1; } else if ((*end == ',') || (*end == ')')) { max = idx; if (min == RTE_MAX_LCORE) min = idx; for (idx = RTE_MIN(min, max); idx <= RTE_MAX(min, max); idx++) set[idx] = 1; min = RTE_MAX_LCORE; } else return -1; str = end + 1; } while (*end != '\0' && *end != ')'); return str - input; } /* convert from set array to cpuset bitmap */ static int convert_to_cpuset(rte_cpuset_t *cpusetp, uint16_t *set, unsigned num) { unsigned idx; CPU_ZERO(cpusetp); for (idx = 0; idx < num; idx++) { if (!set[idx]) continue; if (!lcore_config[idx].detected) { RTE_LOG(ERR, EAL, "core %u " "unavailable\n", idx); return -1; } CPU_SET(idx, cpusetp); } return 0; } /* * The format pattern: --lcores='[<,lcores[@cpus]>...]' * lcores, cpus could be a single digit/range or a group. * '(' and ')' are necessary if it's a group. * If not supply '@cpus', the value of cpus uses the same as lcores. * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below * lcore 0 runs on cpuset 0x41 (cpu 0,6) * lcore 1 runs on cpuset 0x2 (cpu 1) * lcore 2 runs on cpuset 0xe0 (cpu 5,6,7) * lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2) * lcore 6 runs on cpuset 0x41 (cpu 0,6) * lcore 7 runs on cpuset 0x80 (cpu 7) * lcore 8 runs on cpuset 0x100 (cpu 8) */ static int eal_parse_lcores(const char *lcores) { struct rte_config *cfg = rte_eal_get_configuration(); static uint16_t set[RTE_MAX_LCORE]; unsigned idx = 0; int i; unsigned count = 0; const char *lcore_start = NULL; const char *end = NULL; int offset; rte_cpuset_t cpuset; int lflags = 0; int ret = -1; if (lcores == NULL) return -1; /* Remove all blank characters ahead and after */ while (isblank(*lcores)) lcores++; i = strlen(lcores); while ((i > 0) && isblank(lcores[i - 1])) i--; CPU_ZERO(&cpuset); /* Reset lcore config */ for (idx = 0; idx < RTE_MAX_LCORE; idx++) { cfg->lcore_role[idx] = ROLE_OFF; lcore_config[idx].core_index = -1; CPU_ZERO(&lcore_config[idx].cpuset); } /* Get list of cores */ do { while (isblank(*lcores)) lcores++; if (*lcores == '\0') goto err; /* record lcore_set start point */ lcore_start = lcores; /* go across a complete bracket */ if (*lcore_start == '(') { lcores += strcspn(lcores, ")"); if (*lcores++ == '\0') goto err; } /* scan the separator '@', ','(next) or '\0'(finish) */ lcores += strcspn(lcores, "@,"); if (*lcores == '@') { /* explicit assign cpu_set */ offset = eal_parse_set(lcores + 1, set, RTE_DIM(set)); if (offset < 0) goto err; /* prepare cpu_set and update the end cursor */ if (0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set))) goto err; end = lcores + 1 + offset; } else { /* ',' or '\0' */ /* haven't given cpu_set, current loop done */ end = lcores; /* go back to check - */ offset = strcspn(lcore_start, "(-"); if (offset < (end - lcore_start) && *(lcore_start + offset) != '(') lflags = 1; } if (*end != ',' && *end != '\0') goto err; /* parse lcore_set from start point */ if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set))) goto err; /* without '@', by default using lcore_set as cpu_set */ if (*lcores != '@' && 0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set))) goto err; /* start to update lcore_set */ for (idx = 0; idx < RTE_MAX_LCORE; idx++) { if (!set[idx]) continue; if (cfg->lcore_role[idx] != ROLE_RTE) { lcore_config[idx].core_index = count; cfg->lcore_role[idx] = ROLE_RTE; count++; } if (lflags) { CPU_ZERO(&cpuset); CPU_SET(idx, &cpuset); } rte_memcpy(&lcore_config[idx].cpuset, &cpuset, sizeof(rte_cpuset_t)); } lcores = end + 1; } while (*end != '\0'); if (count == 0) goto err; cfg->lcore_count = count; lcores_parsed = 1; ret = 0; err: return ret; } static int eal_parse_syslog(const char *facility, struct internal_config *conf) { int i; static struct { const char *name; int value; } map[] = { { "auth", LOG_AUTH }, { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "ftp", LOG_FTP }, { "kern", LOG_KERN }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, { "news", LOG_NEWS }, { "syslog", LOG_SYSLOG }, { "user", LOG_USER }, { "uucp", LOG_UUCP }, { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { NULL, 0 } }; for (i = 0; map[i].name; i++) { if (!strcmp(facility, map[i].name)) { conf->syslog_facility = map[i].value; return 0; } } return -1; } static int eal_parse_log_level(const char *level, uint32_t *log_level) { char *end; unsigned long tmp; errno = 0; tmp = strtoul(level, &end, 0); /* check for errors */ if ((errno != 0) || (level[0] == '\0') || end == NULL || (*end != '\0')) return -1; /* log_level is a uint32_t */ if (tmp >= UINT32_MAX) return -1; *log_level = tmp; return 0; } static enum rte_proc_type_t eal_parse_proc_type(const char *arg) { if (strncasecmp(arg, "primary", sizeof("primary")) == 0) return RTE_PROC_PRIMARY; if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0) return RTE_PROC_SECONDARY; if (strncasecmp(arg, "auto", sizeof("auto")) == 0) return RTE_PROC_AUTO; return RTE_PROC_INVALID; } int eal_parse_common_option(int opt, const char *optarg, struct internal_config *conf) { switch (opt) { /* blacklist */ case 'b': if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI, optarg) < 0) { return -1; } break; /* whitelist */ case 'w': if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, optarg) < 0) { return -1; } break; /* coremask */ case 'c': if (eal_parse_coremask(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid coremask\n"); return -1; } break; /* corelist */ case 'l': if (eal_parse_corelist(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid core list\n"); return -1; } break; /* size of memory */ case 'm': conf->memory = atoi(optarg); conf->memory *= 1024ULL; conf->memory *= 1024ULL; mem_parsed = 1; break; /* force number of channels */ case 'n': conf->force_nchannel = atoi(optarg); if (conf->force_nchannel == 0 || conf->force_nchannel > 4) { RTE_LOG(ERR, EAL, "invalid channel number\n"); return -1; } break; /* force number of ranks */ case 'r': conf->force_nrank = atoi(optarg); if (conf->force_nrank == 0 || conf->force_nrank > 16) { RTE_LOG(ERR, EAL, "invalid rank number\n"); return -1; } break; case 'v': /* since message is explicitly requested by user, we * write message at highest log level so it can always * be seen * even if info or warning messages are disabled */ RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version()); break; /* long options */ case OPT_NO_HUGE_NUM: conf->no_hugetlbfs = 1; break; case OPT_NO_PCI_NUM: conf->no_pci = 1; break; case OPT_NO_HPET_NUM: conf->no_hpet = 1; break; case OPT_VMWARE_TSC_MAP_NUM: conf->vmware_tsc_map = 1; break; case OPT_NO_SHCONF_NUM: conf->no_shconf = 1; break; case OPT_PROC_TYPE_NUM: conf->process_type = eal_parse_proc_type(optarg); break; case OPT_MASTER_LCORE_NUM: if (eal_parse_master_lcore(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid parameter for --" OPT_MASTER_LCORE "\n"); return -1; } break; case OPT_VDEV_NUM: if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL, optarg) < 0) { return -1; } break; case OPT_SYSLOG_NUM: if (eal_parse_syslog(optarg, conf) < 0) { RTE_LOG(ERR, EAL, "invalid parameters for --" OPT_SYSLOG "\n"); return -1; } break; case OPT_LOG_LEVEL_NUM: { uint32_t log; if (eal_parse_log_level(optarg, &log) < 0) { RTE_LOG(ERR, EAL, "invalid parameters for --" OPT_LOG_LEVEL "\n"); return -1; } conf->log_level = log; break; } case OPT_LCORES_NUM: if (eal_parse_lcores(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid parameter for --" OPT_LCORES "\n"); return -1; } break; /* don't know what to do, leave this to caller */ default: return 1; } return 0; } int eal_adjust_config(struct internal_config *internal_cfg) { int i; struct rte_config *cfg = rte_eal_get_configuration(); if (internal_config.process_type == RTE_PROC_AUTO) internal_config.process_type = eal_proc_type_detect(); /* default master lcore is the first one */ if (!master_lcore_parsed) cfg->master_lcore = rte_get_next_lcore(-1, 0, 0); /* if no memory amounts were requested, this will result in 0 and * will be overridden later, right after eal_hugepage_info_init() */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) internal_cfg->memory += internal_cfg->socket_mem[i]; return 0; } int eal_check_common_options(struct internal_config *internal_cfg) { struct rte_config *cfg = rte_eal_get_configuration(); if (!lcores_parsed) { RTE_LOG(ERR, EAL, "CPU cores must be enabled with options " "-c, -l or --lcores\n"); return -1; } if (cfg->lcore_role[cfg->master_lcore] != ROLE_RTE) { RTE_LOG(ERR, EAL, "Master lcore is not enabled for DPDK\n"); return -1; } if (internal_cfg->process_type == RTE_PROC_INVALID) { RTE_LOG(ERR, EAL, "Invalid process type specified\n"); return -1; } if (internal_cfg->process_type == RTE_PROC_PRIMARY && internal_cfg->force_nchannel == 0) { RTE_LOG(ERR, EAL, "Number of memory channels (-n) not " "specified\n"); return -1; } if (index(internal_cfg->hugefile_prefix, '%') != NULL) { RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" " "option\n"); return -1; } if (mem_parsed && internal_cfg->force_sockets == 1) { RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot " "be specified at the same time\n"); return -1; } if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) { RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot " "be specified together with --"OPT_NO_HUGE"\n"); return -1; } if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 && rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) { RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) " "cannot be used at the same time\n"); return -1; } return 0; } void eal_common_usage(void) { printf("-c COREMASK|-l CORELIST -n CHANNELS [options]\n\n" "EAL common options:\n" " -c COREMASK Hexadecimal bitmask of cores to run on\n" " -l CORELIST List of cores to run on\n" " The argument format is [-c2][,c3[-c4],...]\n" " where c1, c2, etc are core indexes between 0 and %d\n" " --"OPT_LCORES" COREMAP Map lcore set to physical cpu set\n" " The argument format is\n" " '[<,lcores[@cpus]>...]'\n" " lcores and cpus list are grouped by '(' and ')'\n" " Within the group, '-' is used for range separator,\n" " ',' is used for single number separator.\n" " '( )' can be omitted for single element group,\n" " '@' can be omitted if cpus and lcores have the same value\n" " --"OPT_MASTER_LCORE" ID Core ID that is used as master\n" " -n CHANNELS Number of memory channels\n" " -m MB Memory to allocate (see also --"OPT_SOCKET_MEM")\n" " -r RANKS Force number of memory ranks (don't detect)\n" " -b, --"OPT_PCI_BLACKLIST" Add a PCI device in black list.\n" " Prevent EAL from using this PCI device. The argument\n" " format is .\n" " -w, --"OPT_PCI_WHITELIST" Add a PCI device in white list.\n" " Only use the specified PCI devices. The argument format\n" " is <[domain:]bus:devid.func>. This option can be present\n" " several times (once per device).\n" " [NOTE: PCI whitelist cannot be used with -b option]\n" " --"OPT_VDEV" Add a virtual device.\n" " The argument format is [,key=val,...]\n" " (ex: --vdev=eth_pcap0,iface=eth2).\n" " --"OPT_VMWARE_TSC_MAP" Use VMware TSC map instead of native RDTSC\n" " --"OPT_PROC_TYPE" Type of this process (primary|secondary|auto)\n" " --"OPT_SYSLOG" Set syslog facility\n" " --"OPT_LOG_LEVEL" Set default log level\n" " -v Display version information on startup\n" " -h, --help This help\n" "\nEAL options for DEBUG use only:\n" " --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n" " --"OPT_NO_PCI" Disable PCI\n" " --"OPT_NO_HPET" Disable HPET\n" " --"OPT_NO_SHCONF" No shared config (mmap'd files)\n" "\n", RTE_MAX_LCORE); } ================================================ FILE: lib/librte_eal/common/eal_common_pci.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* BSD LICENSE * * Copyright 2013-2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" struct pci_driver_list pci_driver_list; struct pci_device_list pci_device_list; static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev) { struct rte_devargs *devargs; TAILQ_FOREACH(devargs, &devargs_list, next) { if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI && devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) continue; if (!rte_eal_compare_pci_addr(&dev->addr, &devargs->pci.addr)) return devargs; } return NULL; } /* map a particular resource from a file */ void * pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size, int additional_flags) { void *mapaddr; /* Map the PCI memory resource of device */ mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE, MAP_SHARED | additional_flags, fd, offset); if (mapaddr == MAP_FAILED) { RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n", __func__, fd, requested_addr, (unsigned long)size, (unsigned long)offset, strerror(errno), mapaddr); } else RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", mapaddr); return mapaddr; } /* unmap a particular resource */ void pci_unmap_resource(void *requested_addr, size_t size) { if (requested_addr == NULL) return; /* Unmap the PCI memory resource of device */ if (munmap(requested_addr, size)) { RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n", __func__, requested_addr, (unsigned long)size, strerror(errno)); } else RTE_LOG(DEBUG, EAL, " PCI memory unmapped at %p\n", requested_addr); } /* * If vendor/device ID match, call the devinit() function of the * driver. */ static int rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev) { int ret; const struct rte_pci_id *id_table; for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) { /* check if device's identifiers match the driver's ones */ if (id_table->vendor_id != dev->id.vendor_id && id_table->vendor_id != PCI_ANY_ID) continue; if (id_table->device_id != dev->id.device_id && id_table->device_id != PCI_ANY_ID) continue; if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id && id_table->subsystem_vendor_id != PCI_ANY_ID) continue; if (id_table->subsystem_device_id != dev->id.subsystem_device_id && id_table->subsystem_device_id != PCI_ANY_ID) continue; struct rte_pci_addr *loc = &dev->addr; RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n", loc->domain, loc->bus, loc->devid, loc->function, dev->numa_node); RTE_LOG(DEBUG, EAL, " probe driver: %x:%x %s\n", dev->id.vendor_id, dev->id.device_id, dr->name); /* no initialization when blacklisted, return without error */ if (dev->devargs != NULL && dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) { RTE_LOG(DEBUG, EAL, " Device is blacklisted, not initializing\n"); return 1; } if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) { #ifdef RTE_PCI_CONFIG /* * Set PCIe config space for high performance. * Return value can be ignored. */ pci_config_space_set(dev); #endif /* map resources for devices that use igb_uio */ ret = pci_map_device(dev); if (ret != 0) return ret; } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND && rte_eal_process_type() == RTE_PROC_PRIMARY) { /* unbind current driver */ if (pci_unbind_kernel_driver(dev) < 0) return -1; } /* reference driver structure */ dev->driver = dr; /* call the driver devinit() function */ return dr->devinit(dr, dev); } /* return positive value if driver is not found */ return 1; } /* * If vendor/device ID match, call the devuninit() function of the * driver. */ static int rte_eal_pci_detach_dev(struct rte_pci_driver *dr, struct rte_pci_device *dev) { const struct rte_pci_id *id_table; if ((dr == NULL) || (dev == NULL)) return -EINVAL; for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) { /* check if device's identifiers match the driver's ones */ if (id_table->vendor_id != dev->id.vendor_id && id_table->vendor_id != PCI_ANY_ID) continue; if (id_table->device_id != dev->id.device_id && id_table->device_id != PCI_ANY_ID) continue; if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id && id_table->subsystem_vendor_id != PCI_ANY_ID) continue; if (id_table->subsystem_device_id != dev->id.subsystem_device_id && id_table->subsystem_device_id != PCI_ANY_ID) continue; struct rte_pci_addr *loc = &dev->addr; RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n", loc->domain, loc->bus, loc->devid, loc->function, dev->numa_node); RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", dev->id.vendor_id, dev->id.device_id, dr->name); if (dr->devuninit && (dr->devuninit(dev) < 0)) return -1; /* negative value is an error */ /* clear driver structure */ dev->driver = NULL; if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) /* unmap resources for devices that use igb_uio */ pci_unmap_device(dev); return 0; } /* return positive value if driver is not found */ return 1; } /* * If vendor/device ID match, call the devinit() function of all * registered driver for the given device. Return -1 if initialization * failed, return 1 if no driver is found for this device. */ static int pci_probe_all_drivers(struct rte_pci_device *dev) { struct rte_pci_driver *dr = NULL; int rc = 0; if (dev == NULL) return -1; TAILQ_FOREACH(dr, &pci_driver_list, next) { rc = rte_eal_pci_probe_one_driver(dr, dev); if (rc < 0) /* negative value is an error */ return -1; if (rc > 0) /* positive value means driver not found */ continue; return 0; } return 1; } /* * If vendor/device ID match, call the devuninit() function of all * registered driver for the given device. Return -1 if initialization * failed, return 1 if no driver is found for this device. */ static int pci_detach_all_drivers(struct rte_pci_device *dev) { struct rte_pci_driver *dr = NULL; int rc = 0; if (dev == NULL) return -1; TAILQ_FOREACH(dr, &pci_driver_list, next) { rc = rte_eal_pci_detach_dev(dr, dev); if (rc < 0) /* negative value is an error */ return -1; if (rc > 0) /* positive value means driver not found */ continue; return 0; } return 1; } /* * Find the pci device specified by pci address, then invoke probe function of * the driver of the devive. */ int rte_eal_pci_probe_one(const struct rte_pci_addr *addr) { struct rte_pci_device *dev = NULL; int ret = 0; if (addr == NULL) return -1; TAILQ_FOREACH(dev, &pci_device_list, next) { if (rte_eal_compare_pci_addr(&dev->addr, addr)) continue; ret = pci_probe_all_drivers(dev); if (ret < 0) goto err_return; return 0; } return -1; err_return: RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT " cannot be used\n", dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); return -1; } int __attribute__ ((deprecated)) rte_eal_pci_close_one(const struct rte_pci_addr *addr) { return rte_eal_pci_detach(addr); } /* * Detach device specified by its pci address. */ int rte_eal_pci_detach(const struct rte_pci_addr *addr) { struct rte_pci_device *dev = NULL; int ret = 0; if (addr == NULL) return -1; TAILQ_FOREACH(dev, &pci_device_list, next) { if (rte_eal_compare_pci_addr(&dev->addr, addr)) continue; ret = pci_detach_all_drivers(dev); if (ret < 0) goto err_return; TAILQ_REMOVE(&pci_device_list, dev, next); return 0; } return -1; err_return: RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT " cannot be used\n", dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); return -1; } /* * Scan the content of the PCI bus, and call the devinit() function for * all registered drivers that have a matching entry in its id_table * for discovered devices. */ int rte_eal_pci_probe(void) { struct rte_pci_device *dev = NULL; struct rte_devargs *devargs; int probe_all = 0; int ret = 0; if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0) probe_all = 1; TAILQ_FOREACH(dev, &pci_device_list, next) { /* set devargs in PCI structure */ devargs = pci_devargs_lookup(dev); if (devargs != NULL) dev->devargs = devargs; /* probe all or only whitelisted devices */ if (probe_all) ret = pci_probe_all_drivers(dev); else if (devargs != NULL && devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) ret = pci_probe_all_drivers(dev); if (ret < 0) rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT " cannot be used\n", dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); } return 0; } /* dump one device */ static int pci_dump_one_device(FILE *f, struct rte_pci_device *dev) { int i; fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id, dev->id.device_id); for (i = 0; i != sizeof(dev->mem_resource) / sizeof(dev->mem_resource[0]); i++) { fprintf(f, " %16.16"PRIx64" %16.16"PRIx64"\n", dev->mem_resource[i].phys_addr, dev->mem_resource[i].len); } return 0; } /* dump devices on the bus */ void rte_eal_pci_dump(FILE *f) { struct rte_pci_device *dev = NULL; TAILQ_FOREACH(dev, &pci_device_list, next) { pci_dump_one_device(f, dev); } } /* register a driver */ void rte_eal_pci_register(struct rte_pci_driver *driver) { TAILQ_INSERT_TAIL(&pci_driver_list, driver, next); } /* unregister a driver */ void rte_eal_pci_unregister(struct rte_pci_driver *driver) { TAILQ_REMOVE(&pci_driver_list, driver, next); } ================================================ FILE: lib/librte_eal/common/eal_common_pci_uio.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" static struct rte_tailq_elem rte_uio_tailq = { .name = "UIO_RESOURCE_LIST", }; EAL_REGISTER_TAILQ(rte_uio_tailq) static int pci_uio_map_secondary(struct rte_pci_device *dev) { int fd, i; struct mapped_pci_resource *uio_res; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); TAILQ_FOREACH(uio_res, uio_res_list, next) { /* skip this element if it doesn't match our PCI address */ if (rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) continue; for (i = 0; i != uio_res->nb_maps; i++) { /* * open devname, to mmap it */ fd = open(uio_res->maps[i].path, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", uio_res->maps[i].path, strerror(errno)); return -1; } void *mapaddr = pci_map_resource(uio_res->maps[i].addr, fd, (off_t)uio_res->maps[i].offset, (size_t)uio_res->maps[i].size, 0); /* fd is not needed in slave process, close it */ close(fd); if (mapaddr != uio_res->maps[i].addr) { RTE_LOG(ERR, EAL, "Cannot mmap device resource file %s to address: %p\n", uio_res->maps[i].path, uio_res->maps[i].addr); return -1; } } return 0; } RTE_LOG(ERR, EAL, "Cannot find resource for device\n"); return 1; } /* map the PCI resource of a PCI device in virtual memory */ int pci_uio_map_resource(struct rte_pci_device *dev) { int i, map_idx = 0, ret; uint64_t phaddr; struct mapped_pci_resource *uio_res = NULL; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); dev->intr_handle.fd = -1; dev->intr_handle.uio_cfg_fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; /* secondary processes - use already recorded details */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return pci_uio_map_secondary(dev); /* allocate uio resource */ ret = pci_uio_alloc_resource(dev, &uio_res); if (ret) return ret; /* Map all BARs */ for (i = 0; i != PCI_MAX_RESOURCE; i++) { /* skip empty BAR */ phaddr = dev->mem_resource[i].phys_addr; if (phaddr == 0) continue; ret = pci_uio_map_resource_by_index(dev, i, uio_res, map_idx); if (ret) goto error; map_idx++; } uio_res->nb_maps = map_idx; TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); return 0; error: for (i = 0; i < map_idx; i++) { pci_unmap_resource(uio_res->maps[i].addr, (size_t)uio_res->maps[i].size); rte_free(uio_res->maps[i].path); } pci_uio_free_resource(dev, uio_res); return -1; } static void pci_uio_unmap(struct mapped_pci_resource *uio_res) { int i; if (uio_res == NULL) return; for (i = 0; i != uio_res->nb_maps; i++) { pci_unmap_resource(uio_res->maps[i].addr, (size_t)uio_res->maps[i].size); rte_free(uio_res->maps[i].path); } } static struct mapped_pci_resource * pci_uio_find_resource(struct rte_pci_device *dev) { struct mapped_pci_resource *uio_res; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); if (dev == NULL) return NULL; TAILQ_FOREACH(uio_res, uio_res_list, next) { /* skip this element if it doesn't match our PCI address */ if (!rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr)) return uio_res; } return NULL; } /* unmap the PCI resource of a PCI device in virtual memory */ void pci_uio_unmap_resource(struct rte_pci_device *dev) { struct mapped_pci_resource *uio_res; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); if (dev == NULL) return; /* find an entry for the device */ uio_res = pci_uio_find_resource(dev); if (uio_res == NULL) return; /* secondary processes - just free maps */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return pci_uio_unmap(uio_res); TAILQ_REMOVE(uio_res_list, uio_res, next); /* unmap all resources */ pci_uio_unmap(uio_res); /* free uio resource */ rte_free(uio_res); /* close fd if in primary process */ close(dev->intr_handle.fd); if (dev->intr_handle.uio_cfg_fd >= 0) { close(dev->intr_handle.uio_cfg_fd); dev->intr_handle.uio_cfg_fd = -1; } dev->intr_handle.fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; } ================================================ FILE: lib/librte_eal/common/eal_common_string_fns.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include /* split string into tokens */ int rte_strsplit(char *string, int stringlen, char **tokens, int maxtokens, char delim) { int i, tok = 0; int tokstart = 1; /* first token is right at start of string */ if (string == NULL || tokens == NULL) goto einval_error; for (i = 0; i < stringlen; i++) { if (string[i] == '\0' || tok >= maxtokens) break; if (tokstart) { tokstart = 0; tokens[tok++] = &string[i]; } if (string[i] == delim) { string[i] = '\0'; tokstart = 1; } } return tok; einval_error: errno = EINVAL; return -1; } ================================================ FILE: lib/librte_eal/common/eal_common_tailqs.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" TAILQ_HEAD(rte_tailq_elem_head, rte_tailq_elem); /* local tailq list */ static struct rte_tailq_elem_head rte_tailq_elem_head = TAILQ_HEAD_INITIALIZER(rte_tailq_elem_head); /* number of tailqs registered, -1 before call to rte_eal_tailqs_init */ static int rte_tailqs_count = -1; struct rte_tailq_head * rte_eal_tailq_lookup(const char *name) { unsigned i; struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; if (name == NULL) return NULL; for (i = 0; i < RTE_MAX_TAILQ; i++) { if (!strncmp(name, mcfg->tailq_head[i].name, RTE_TAILQ_NAMESIZE-1)) return &mcfg->tailq_head[i]; } return NULL; } void rte_dump_tailq(FILE *f) { struct rte_mem_config *mcfg; unsigned i = 0; mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_read_lock(&mcfg->qlock); for (i = 0; i < RTE_MAX_TAILQ; i++) { const struct rte_tailq_head *tailq = &mcfg->tailq_head[i]; const struct rte_tailq_entry_head *head = &tailq->tailq_head; fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n", i, tailq->name, head->tqh_first, head->tqh_last); } rte_rwlock_read_unlock(&mcfg->qlock); } static struct rte_tailq_head * rte_eal_tailq_create(const char *name) { struct rte_tailq_head *head = NULL; if (!rte_eal_tailq_lookup(name) && (rte_tailqs_count + 1 < RTE_MAX_TAILQ)) { struct rte_mem_config *mcfg; mcfg = rte_eal_get_configuration()->mem_config; head = &mcfg->tailq_head[rte_tailqs_count]; snprintf(head->name, sizeof(head->name) - 1, "%s", name); TAILQ_INIT(&head->tailq_head); rte_tailqs_count++; } return head; } /* local register, used to store "early" tailqs before rte_eal_init() and to * ensure secondary process only registers tailqs once. */ static int rte_eal_tailq_local_register(struct rte_tailq_elem *t) { struct rte_tailq_elem *temp; TAILQ_FOREACH(temp, &rte_tailq_elem_head, next) { if (!strncmp(t->name, temp->name, sizeof(temp->name))) return -1; } TAILQ_INSERT_TAIL(&rte_tailq_elem_head, t, next); return 0; } static void rte_eal_tailq_update(struct rte_tailq_elem *t) { if (rte_eal_process_type() == RTE_PROC_PRIMARY) { /* primary process is the only one that creates */ t->head = rte_eal_tailq_create(t->name); } else { t->head = rte_eal_tailq_lookup(t->name); } } int rte_eal_tailq_register(struct rte_tailq_elem *t) { if (rte_eal_tailq_local_register(t) < 0) { RTE_LOG(ERR, EAL, "%s tailq is already registered\n", t->name); goto error; } /* if a register happens after rte_eal_tailqs_init(), then we can update * tailq head */ if (rte_tailqs_count >= 0) { rte_eal_tailq_update(t); if (t->head == NULL) { RTE_LOG(ERR, EAL, "Cannot initialize tailq: %s\n", t->name); TAILQ_REMOVE(&rte_tailq_elem_head, t, next); goto error; } } return 0; error: t->head = NULL; return -1; } int rte_eal_tailqs_init(void) { struct rte_tailq_elem *t; rte_tailqs_count = 0; TAILQ_FOREACH(t, &rte_tailq_elem_head, next) { /* second part of register job for "early" tailqs, see * rte_eal_tailq_register and EAL_REGISTER_TAILQ */ rte_eal_tailq_update(t); if (t->head == NULL) { RTE_LOG(ERR, EAL, "Cannot initialize tailq: %s\n", t->name); /* no need to TAILQ_REMOVE, we are going to panic in * rte_eal_init() */ goto fail; } } return 0; fail: rte_dump_tailq(stderr); return -1; } ================================================ FILE: lib/librte_eal/common/eal_common_thread.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "eal_thread.h" RTE_DECLARE_PER_LCORE(unsigned , _socket_id); unsigned rte_socket_id(void) { return RTE_PER_LCORE(_socket_id); } int eal_cpuset_socket_id(rte_cpuset_t *cpusetp) { unsigned cpu = 0; int socket_id = SOCKET_ID_ANY; int sid; if (cpusetp == NULL) return SOCKET_ID_ANY; do { if (!CPU_ISSET(cpu, cpusetp)) continue; if (socket_id == SOCKET_ID_ANY) socket_id = eal_cpu_socket_id(cpu); sid = eal_cpu_socket_id(cpu); if (socket_id != sid) { socket_id = SOCKET_ID_ANY; break; } } while (++cpu < RTE_MAX_LCORE); return socket_id; } int rte_thread_set_affinity(rte_cpuset_t *cpusetp) { int s; unsigned lcore_id; pthread_t tid; tid = pthread_self(); s = pthread_setaffinity_np(tid, sizeof(rte_cpuset_t), cpusetp); if (s != 0) { RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n"); return -1; } /* store socket_id in TLS for quick access */ RTE_PER_LCORE(_socket_id) = eal_cpuset_socket_id(cpusetp); /* store cpuset in TLS for quick access */ memmove(&RTE_PER_LCORE(_cpuset), cpusetp, sizeof(rte_cpuset_t)); lcore_id = rte_lcore_id(); if (lcore_id != (unsigned)LCORE_ID_ANY) { /* EAL thread will update lcore_config */ lcore_config[lcore_id].socket_id = RTE_PER_LCORE(_socket_id); memmove(&lcore_config[lcore_id].cpuset, cpusetp, sizeof(rte_cpuset_t)); } return 0; } void rte_thread_get_affinity(rte_cpuset_t *cpusetp) { assert(cpusetp); memmove(cpusetp, &RTE_PER_LCORE(_cpuset), sizeof(rte_cpuset_t)); } int eal_thread_dump_affinity(char *str, unsigned size) { rte_cpuset_t cpuset; unsigned cpu; int ret; unsigned int out = 0; rte_thread_get_affinity(&cpuset); for (cpu = 0; cpu < RTE_MAX_LCORE; cpu++) { if (!CPU_ISSET(cpu, &cpuset)) continue; ret = snprintf(str + out, size - out, "%u,", cpu); if (ret < 0 || (unsigned)ret >= size - out) { /* string will be truncated */ ret = -1; goto exit; } out += ret; } ret = 0; exit: /* remove the last separator */ if (out > 0) str[out - 1] = '\0'; return ret; } ================================================ FILE: lib/librte_eal/common/eal_common_timer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "eal_private.h" /* The frequency of the RDTSC timer resolution */ static uint64_t eal_tsc_resolution_hz; void rte_delay_us(unsigned us) { const uint64_t start = rte_get_timer_cycles(); const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; while ((rte_get_timer_cycles() - start) < ticks) rte_pause(); } uint64_t rte_get_tsc_hz(void) { return eal_tsc_resolution_hz; } static uint64_t estimate_tsc_freq(void) { RTE_LOG(WARNING, EAL, "WARNING: TSC frequency estimated roughly" " - clock timings may be less accurate.\n"); /* assume that the sleep(1) will sleep for 1 second */ uint64_t start = rte_rdtsc(); sleep(1); return rte_rdtsc() - start; } void set_tsc_freq(void) { uint64_t freq = get_tsc_freq(); if (!freq) freq = estimate_tsc_freq(); RTE_LOG(INFO, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); eal_tsc_resolution_hz = freq; } ================================================ FILE: lib/librte_eal/common/eal_filesystem.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Stores functions and path defines for files and directories * on the filesystem for Linux, that are used by the Linux EAL. */ #ifndef EAL_FILESYSTEM_H #define EAL_FILESYSTEM_H /** Path of rte config file. */ #define RUNTIME_CONFIG_FMT "%s/.%s_config" #include #include #include #include #include #include "eal_internal_cfg.h" static const char *default_config_dir = "/var/run"; static inline const char * eal_runtime_config_path(void) { static char buffer[PATH_MAX]; /* static so auto-zeroed */ const char *directory = default_config_dir; const char *home_dir = getenv("HOME"); if (getuid() != 0 && home_dir != NULL) directory = home_dir; snprintf(buffer, sizeof(buffer) - 1, RUNTIME_CONFIG_FMT, directory, internal_config.hugefile_prefix); return buffer; } /** Path of hugepage info file. */ #define HUGEPAGE_INFO_FMT "%s/.%s_hugepage_info" static inline const char * eal_hugepage_info_path(void) { static char buffer[PATH_MAX]; /* static so auto-zeroed */ const char *directory = default_config_dir; const char *home_dir = getenv("HOME"); if (getuid() != 0 && home_dir != NULL) directory = home_dir; snprintf(buffer, sizeof(buffer) - 1, HUGEPAGE_INFO_FMT, directory, internal_config.hugefile_prefix); return buffer; } /** String format for hugepage map files. */ #define HUGEFILE_FMT "%s/%smap_%d" #define TEMP_HUGEFILE_FMT "%s/%smap_temp_%d" static inline const char * eal_get_hugefile_path(char *buffer, size_t buflen, const char *hugedir, int f_id) { snprintf(buffer, buflen, HUGEFILE_FMT, hugedir, internal_config.hugefile_prefix, f_id); buffer[buflen - 1] = '\0'; return buffer; } #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS static inline const char * eal_get_hugefile_temp_path(char *buffer, size_t buflen, const char *hugedir, int f_id) { snprintf(buffer, buflen, TEMP_HUGEFILE_FMT, hugedir, internal_config.hugefile_prefix, f_id); buffer[buflen - 1] = '\0'; return buffer; } #endif /** define the default filename prefix for the %s values above */ #define HUGEFILE_PREFIX_DEFAULT "rte" /** Function to read a single numeric value from a file on the filesystem. * Used to read information from files on /sys */ int eal_parse_sysfs_value(const char *filename, unsigned long *val); #endif /* EAL_FILESYSTEM_H */ ================================================ FILE: lib/librte_eal/common/eal_hugepages.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EAL_HUGEPAGES_H #define EAL_HUGEPAGES_H #include #include #include #define MAX_HUGEPAGE_PATH PATH_MAX /** * Structure used to store informations about hugepages that we mapped * through the files in hugetlbfs. */ struct hugepage_file { void *orig_va; /**< virtual addr of first mmap() */ void *final_va; /**< virtual addr of 2nd mmap() */ uint64_t physaddr; /**< physical addr */ size_t size; /**< the page size */ int socket_id; /**< NUMA socket ID */ int file_id; /**< the '%d' in HUGEFILE_FMT */ int memseg_id; /**< the memory segment to which page belongs */ #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS int repeated; /**< number of times the page size is repeated */ #endif char filepath[MAX_HUGEPAGE_PATH]; /**< path to backing file on filesystem */ }; /** * Read the information from linux on what hugepages are available * for the EAL to use */ int eal_hugepage_info_init(void); #endif /* EAL_HUGEPAGES_H */ ================================================ FILE: lib/librte_eal/common/eal_internal_cfg.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Holds the structures for the eal internal configuration */ #ifndef EAL_INTERNAL_CFG_H #define EAL_INTERNAL_CFG_H #include #include #define MAX_HUGEPAGE_SIZES 3 /**< support up to 3 page sizes */ /* * internal configuration structure for the number, size and * mount points of hugepages */ struct hugepage_info { uint64_t hugepage_sz; /**< size of a huge page */ const char *hugedir; /**< dir where hugetlbfs is mounted */ uint32_t num_pages[RTE_MAX_NUMA_NODES]; /**< number of hugepages of that size on each socket */ int lock_descriptor; /**< file descriptor for hugepage dir */ }; /** * internal configuration */ struct internal_config { volatile size_t memory; /**< amount of asked memory */ volatile unsigned force_nchannel; /**< force number of channels */ volatile unsigned force_nrank; /**< force number of ranks */ volatile unsigned no_hugetlbfs; /**< true to disable hugetlbfs */ volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/ volatile unsigned no_pci; /**< true to disable PCI */ volatile unsigned no_hpet; /**< true to disable HPET */ volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping * instead of native TSC */ volatile unsigned no_shconf; /**< true if there is no shared config */ volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */ volatile enum rte_proc_type_t process_type; /**< multi-process proc type */ /** true to try allocating memory on specific sockets */ volatile unsigned force_sockets; volatile uint64_t socket_mem[RTE_MAX_NUMA_NODES]; /**< amount of memory per socket */ uintptr_t base_virtaddr; /**< base address to try and reserve memory from */ volatile int syslog_facility; /**< facility passed to openlog() */ volatile uint32_t log_level; /**< default log level */ /** default interrupt mode for VFIO */ volatile enum rte_intr_mode vfio_intr_mode; const char *hugefile_prefix; /**< the base filename of hugetlbfs files */ const char *hugepage_dir; /**< specific hugetlbfs directory to use */ unsigned num_hugepage_sizes; /**< how many sizes on this system */ struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES]; }; extern struct internal_config internal_config; /**< Global EAL configuration. */ void eal_reset_internal_config(struct internal_config *internal_cfg); #endif /* EAL_INTERNAL_CFG_H */ ================================================ FILE: lib/librte_eal/common/eal_options.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EAL_OPTIONS_H #define EAL_OPTIONS_H enum { /* long options mapped to a short option */ #define OPT_HELP "help" OPT_HELP_NUM = 'h', #define OPT_PCI_BLACKLIST "pci-blacklist" OPT_PCI_BLACKLIST_NUM = 'b', #define OPT_PCI_WHITELIST "pci-whitelist" OPT_PCI_WHITELIST_NUM = 'w', /* first long only option value must be >= 256, so that we won't * conflict with short options */ OPT_LONG_MIN_NUM = 256, #define OPT_BASE_VIRTADDR "base-virtaddr" OPT_BASE_VIRTADDR_NUM, #define OPT_CREATE_UIO_DEV "create-uio-dev" OPT_CREATE_UIO_DEV_NUM, #define OPT_FILE_PREFIX "file-prefix" OPT_FILE_PREFIX_NUM, #define OPT_HUGE_DIR "huge-dir" OPT_HUGE_DIR_NUM, #define OPT_LCORES "lcores" OPT_LCORES_NUM, #define OPT_LOG_LEVEL "log-level" OPT_LOG_LEVEL_NUM, #define OPT_MASTER_LCORE "master-lcore" OPT_MASTER_LCORE_NUM, #define OPT_PROC_TYPE "proc-type" OPT_PROC_TYPE_NUM, #define OPT_NO_HPET "no-hpet" OPT_NO_HPET_NUM, #define OPT_NO_HUGE "no-huge" OPT_NO_HUGE_NUM, #define OPT_NO_PCI "no-pci" OPT_NO_PCI_NUM, #define OPT_NO_SHCONF "no-shconf" OPT_NO_SHCONF_NUM, #define OPT_SOCKET_MEM "socket-mem" OPT_SOCKET_MEM_NUM, #define OPT_SYSLOG "syslog" OPT_SYSLOG_NUM, #define OPT_VDEV "vdev" OPT_VDEV_NUM, #define OPT_VFIO_INTR "vfio-intr" OPT_VFIO_INTR_NUM, #define OPT_VMWARE_TSC_MAP "vmware-tsc-map" OPT_VMWARE_TSC_MAP_NUM, #define OPT_XEN_DOM0 "xen-dom0" OPT_XEN_DOM0_NUM, OPT_LONG_MAX_NUM }; extern const char eal_short_options[]; extern const struct option eal_long_options[]; int eal_parse_common_option(int opt, const char *argv, struct internal_config *conf); int eal_adjust_config(struct internal_config *internal_cfg); int eal_check_common_options(struct internal_config *internal_cfg); void eal_common_usage(void); enum rte_proc_type_t eal_proc_type_detect(void); #endif /* EAL_OPTIONS_H */ ================================================ FILE: lib/librte_eal/common/eal_private.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _EAL_PRIVATE_H_ #define _EAL_PRIVATE_H_ #include #include /** * Initialize the memzone subsystem (private to eal). * * @return * - 0 on success * - Negative on error */ int rte_eal_memzone_init(void); /** * Common log initialization function (private to eal). * * Called by environment-specific log initialization function to initialize * log history. * * @param default_log * The default log stream to be used. * @return * - 0 on success * - Negative on error */ int rte_eal_common_log_init(FILE *default_log); /** * Fill configuration with number of physical and logical processors * * This function is private to EAL. * * Parse /proc/cpuinfo to get the number of physical and logical * processors on the machine. * * @return * 0 on success, negative on error */ int rte_eal_cpu_init(void); /** * Map memory * * This function is private to EAL. * * Fill configuration structure with these infos, and return 0 on success. * * @return * 0 on success, negative on error */ int rte_eal_memory_init(void); /** * Configure timers * * This function is private to EAL. * * Mmap memory areas used by HPET (high precision event timer) that will * provide our time reference, and configure the TSC frequency also for it * to be used as a reference. * * @return * 0 on success, negative on error */ int rte_eal_timer_init(void); /** * Init early logs * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_log_early_init(void); /** * Init the default log stream * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_log_init(const char *id, int facility); /** * Init the default log stream * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_pci_init(void); #ifdef RTE_LIBRTE_IVSHMEM /** * Init the memory from IVSHMEM devices * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_ivshmem_init(void); /** * Init objects in IVSHMEM devices * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_ivshmem_obj_init(void); #endif struct rte_pci_driver; struct rte_pci_device; /** * Unbind kernel driver for this device * * This function is private to EAL. * * @return * 0 on success, negative on error */ int pci_unbind_kernel_driver(struct rte_pci_device *dev); /** * Map this device * * This function is private to EAL. * * @return * 0 on success, negative on error and positive if no driver * is found for the device. */ int pci_map_device(struct rte_pci_device *dev); /** * Unmap this device * * This function is private to EAL. */ void pci_unmap_device(struct rte_pci_device *dev); /** * Map the PCI resource of a PCI device in virtual memory * * This function is private to EAL. * * @return * 0 on success, negative on error */ int pci_uio_map_resource(struct rte_pci_device *dev); /** * Unmap the PCI resource of a PCI device * * This function is private to EAL. */ void pci_uio_unmap_resource(struct rte_pci_device *dev); /** * Allocate uio resource for PCI device * * This function is private to EAL. * * @param dev * PCI device to allocate uio resource * @param uio_res * Pointer to uio resource. * If the function returns 0, the pointer will be filled. * @return * 0 on success, negative on error */ int pci_uio_alloc_resource(struct rte_pci_device *dev, struct mapped_pci_resource **uio_res); /** * Free uio resource for PCI device * * This function is private to EAL. * * @param dev * PCI device to free uio resource * @param uio_res * Pointer to uio resource. */ void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res); /** * Map device memory to uio resource * * This function is private to EAL. * * @param dev * PCI device that has memory information. * @param res_idx * Memory resource index of the PCI device. * @param uio_res * uio resource that will keep mapping information. * @param map_idx * Mapping information index of the uio resource. * @return * 0 on success, negative on error */ int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx, struct mapped_pci_resource *uio_res, int map_idx); /** * Init tail queues for non-EAL library structures. This is to allow * the rings, mempools, etc. lists to be shared among multiple processes * * This function is private to EAL * * @return * 0 on success, negative on error */ int rte_eal_tailqs_init(void); /** * Init interrupt handling. * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_intr_init(void); /** * Init alarm mechanism. This is to allow a callback be called after * specific time. * * This function is private to EAL. * * @return * 0 on success, negative on error */ int rte_eal_alarm_init(void); /** * This function initialises any virtual devices * * This function is private to the EAL. */ int rte_eal_dev_init(void); /** * Function is to check if the kernel module(like, vfio, vfio_iommu_type1, * etc.) loaded. * * @param module_name * The module's name which need to be checked * * @return * -1 means some error happens(NULL pointer or open failure) * 0 means the module not loaded * 1 means the module loaded */ int rte_eal_check_module(const char *module_name); /** * Get cpu core_id. * * This function is private to the EAL. */ unsigned eal_cpu_core_id(unsigned lcore_id); /** * Check if cpu is present. * * This function is private to the EAL. */ int eal_cpu_detected(unsigned lcore_id); /** * Set TSC frequency from precise value or estimation * * This function is private to the EAL. */ void set_tsc_freq(void); /** * Get precise TSC frequency from system * * This function is private to the EAL. */ uint64_t get_tsc_freq(void); /** * Prepare physical memory mapping * i.e. hugepages on Linux and * contigmem on BSD. * * This function is private to the EAL. */ int rte_eal_hugepage_init(void); /** * Creates memory mapping in secondary process * i.e. hugepages on Linux and * contigmem on BSD. * * This function is private to the EAL. */ int rte_eal_hugepage_attach(void); #endif /* _EAL_PRIVATE_H_ */ ================================================ FILE: lib/librte_eal/common/eal_thread.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EAL_THREAD_H #define EAL_THREAD_H #include /** * basic loop of thread, called for each thread by eal_init(). * * @param arg * opaque pointer */ __attribute__((noreturn)) void *eal_thread_loop(void *arg); /** * Init per-lcore info for master thread * * @param lcore_id * identifier of master lcore */ void eal_thread_init_master(unsigned lcore_id); /** * Get the NUMA socket id from cpu id. * This function is private to EAL. * * @param cpu_id * The logical process id. * @return * socket_id or SOCKET_ID_ANY */ unsigned eal_cpu_socket_id(unsigned cpu_id); /** * Get the NUMA socket id from cpuset. * This function is private to EAL. * * @param cpusetp * The point to a valid cpu set. * @return * socket_id or SOCKET_ID_ANY */ int eal_cpuset_socket_id(rte_cpuset_t *cpusetp); /** * Default buffer size to use with eal_thread_dump_affinity() */ #define RTE_CPU_AFFINITY_STR_LEN 256 /** * Dump the current pthread cpuset. * This function is private to EAL. * * Note: * If the dump size is greater than the size of given buffer, * the string will be truncated and with '\0' at the end. * * @param str * The string buffer the cpuset will dump to. * @param size * The string buffer size. * @return * 0 for success, -1 if truncation happens. */ int eal_thread_dump_affinity(char *str, unsigned size); #endif /* EAL_THREAD_H */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_atomic.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Inspired from FreeBSD src/sys/powerpc/include/atomic.h * Copyright (c) 2008 Marcel Moolenaar * Copyright (c) 2001 Benno Rice * Copyright (c) 2001 David E. O'Brien * Copyright (c) 1998 Doug Rabson * All rights reserved. */ #ifndef _RTE_ATOMIC_PPC_64_H_ #define _RTE_ATOMIC_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_atomic.h" /** * General memory barrier. * * Guarantees that the LOAD and STORE operations generated before the * barrier occur before the LOAD and STORE operations generated after. */ #define rte_mb() {asm volatile("sync" : : : "memory"); } /** * Write memory barrier. * * Guarantees that the STORE operations generated before the barrier * occur before the STORE operations generated after. */ #define rte_wmb() {asm volatile("sync" : : : "memory"); } /** * Read memory barrier. * * Guarantees that the LOAD operations generated before the barrier * occur before the LOAD operations generated after. */ #define rte_rmb() {asm volatile("sync" : : : "memory"); } /*------------------------- 16 bit atomic operations -------------------------*/ /* To be compatible with Power7, use GCC built-in functions for 16 bit * operations */ #ifndef RTE_FORCE_INTRINSICS static inline int rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src) { return __atomic_compare_exchange(dst, &exp, &src, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE) ? 1 : 0; } static inline int rte_atomic16_test_and_set(rte_atomic16_t *v) { return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1); } static inline void rte_atomic16_inc(rte_atomic16_t *v) { __atomic_add_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE); } static inline void rte_atomic16_dec(rte_atomic16_t *v) { __atomic_sub_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE); } static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v) { return (__atomic_add_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE) == 0); } static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v) { return (__atomic_sub_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE) == 0); } /*------------------------- 32 bit atomic operations -------------------------*/ static inline int rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src) { unsigned int ret = 0; asm volatile( "\tlwsync\n" "1:\tlwarx %[ret], 0, %[dst]\n" "cmplw %[exp], %[ret]\n" "bne 2f\n" "stwcx. %[src], 0, %[dst]\n" "bne- 1b\n" "li %[ret], 1\n" "b 3f\n" "2:\n" "stwcx. %[ret], 0, %[dst]\n" "li %[ret], 0\n" "3:\n" "isync\n" : [ret] "=&r" (ret), "=m" (*dst) : [dst] "r" (dst), [exp] "r" (exp), [src] "r" (src), "m" (*dst) : "cc", "memory"); return ret; } static inline int rte_atomic32_test_and_set(rte_atomic32_t *v) { return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1); } static inline void rte_atomic32_inc(rte_atomic32_t *v) { int t; asm volatile( "1: lwarx %[t],0,%[cnt]\n" "addic %[t],%[t],1\n" "stwcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "=m" (v->cnt) : [cnt] "r" (&v->cnt), "m" (v->cnt) : "cc", "xer", "memory"); } static inline void rte_atomic32_dec(rte_atomic32_t *v) { int t; asm volatile( "1: lwarx %[t],0,%[cnt]\n" "addic %[t],%[t],-1\n" "stwcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "=m" (v->cnt) : [cnt] "r" (&v->cnt), "m" (v->cnt) : "cc", "xer", "memory"); } static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v) { int ret; asm volatile( "\n\tlwsync\n" "1: lwarx %[ret],0,%[cnt]\n" "addic %[ret],%[ret],1\n" "stwcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [cnt] "r" (&v->cnt) : "cc", "xer", "memory"); return (ret == 0); } static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v) { int ret; asm volatile( "\n\tlwsync\n" "1: lwarx %[ret],0,%[cnt]\n" "addic %[ret],%[ret],-1\n" "stwcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [cnt] "r" (&v->cnt) : "cc", "xer", "memory"); return (ret == 0); } /*------------------------- 64 bit atomic operations -------------------------*/ static inline int rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src) { unsigned int ret = 0; asm volatile ( "\tlwsync\n" "1: ldarx %[ret], 0, %[dst]\n" "cmpld %[exp], %[ret]\n" "bne 2f\n" "stdcx. %[src], 0, %[dst]\n" "bne- 1b\n" "li %[ret], 1\n" "b 3f\n" "2:\n" "stdcx. %[ret], 0, %[dst]\n" "li %[ret], 0\n" "3:\n" "isync\n" : [ret] "=&r" (ret), "=m" (*dst) : [dst] "r" (dst), [exp] "r" (exp), [src] "r" (src), "m" (*dst) : "cc", "memory"); return ret; } static inline void rte_atomic64_init(rte_atomic64_t *v) { v->cnt = 0; } static inline int64_t rte_atomic64_read(rte_atomic64_t *v) { long ret; asm volatile("ld%U1%X1 %[ret],%[cnt]" : [ret] "=r"(ret) : [cnt] "m"(v->cnt)); return ret; } static inline void rte_atomic64_set(rte_atomic64_t *v, int64_t new_value) { asm volatile("std%U0%X0 %[new_value],%[cnt]" : [cnt] "=m"(v->cnt) : [new_value] "r"(new_value)); } static inline void rte_atomic64_add(rte_atomic64_t *v, int64_t inc) { long t; asm volatile( "1: ldarx %[t],0,%[cnt]\n" "add %[t],%[inc],%[t]\n" "stdcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "=m" (v->cnt) : [cnt] "r" (&v->cnt), [inc] "r" (inc), "m" (v->cnt) : "cc", "memory"); } static inline void rte_atomic64_sub(rte_atomic64_t *v, int64_t dec) { long t; asm volatile( "1: ldarx %[t],0,%[cnt]\n" "subf %[t],%[dec],%[t]\n" "stdcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "+m" (v->cnt) : [cnt] "r" (&v->cnt), [dec] "r" (dec), "m" (v->cnt) : "cc", "memory"); } static inline void rte_atomic64_inc(rte_atomic64_t *v) { long t; asm volatile( "1: ldarx %[t],0,%[cnt]\n" "addic %[t],%[t],1\n" "stdcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "+m" (v->cnt) : [cnt] "r" (&v->cnt), "m" (v->cnt) : "cc", "xer", "memory"); } static inline void rte_atomic64_dec(rte_atomic64_t *v) { long t; asm volatile( "1: ldarx %[t],0,%[cnt]\n" "addic %[t],%[t],-1\n" "stdcx. %[t],0,%[cnt]\n" "bne- 1b\n" : [t] "=&r" (t), "+m" (v->cnt) : [cnt] "r" (&v->cnt), "m" (v->cnt) : "cc", "xer", "memory"); } static inline int64_t rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc) { long ret; asm volatile( "\n\tlwsync\n" "1: ldarx %[ret],0,%[cnt]\n" "add %[ret],%[inc],%[ret]\n" "stdcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [inc] "r" (inc), [cnt] "r" (&v->cnt) : "cc", "memory"); return ret; } static inline int64_t rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec) { long ret; asm volatile( "\n\tlwsync\n" "1: ldarx %[ret],0,%[cnt]\n" "subf %[ret],%[dec],%[ret]\n" "stdcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [dec] "r" (dec), [cnt] "r" (&v->cnt) : "cc", "memory"); return ret; } static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v) { long ret; asm volatile( "\n\tlwsync\n" "1: ldarx %[ret],0,%[cnt]\n" "addic %[ret],%[ret],1\n" "stdcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [cnt] "r" (&v->cnt) : "cc", "xer", "memory"); return (ret == 0); } static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v) { long ret; asm volatile( "\n\tlwsync\n" "1: ldarx %[ret],0,%[cnt]\n" "addic %[ret],%[ret],-1\n" "stdcx. %[ret],0,%[cnt]\n" "bne- 1b\n" "isync\n" : [ret] "=&r" (ret) : [cnt] "r" (&v->cnt) : "cc", "xer", "memory"); return (ret == 0); } static inline int rte_atomic64_test_and_set(rte_atomic64_t *v) { return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1); } /** * Atomically set a 64-bit counter to 0. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic64_clear(rte_atomic64_t *v) { v->cnt = 0; } #endif #ifdef __cplusplus } #endif #endif /* _RTE_ATOMIC_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_byteorder.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Inspired from FreeBSD src/sys/powerpc/include/endian.h * Copyright (c) 1987, 1991, 1993 * The Regents of the University of California. All rights reserved. */ #ifndef _RTE_BYTEORDER_PPC_64_H_ #define _RTE_BYTEORDER_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_byteorder.h" /* * An architecture-optimized byte swap for a 16-bit value. * * Do not use this function directly. The preferred function is rte_bswap16(). */ static inline uint16_t rte_arch_bswap16(uint16_t _x) { return ((_x >> 8) | ((_x << 8) & 0xff00)); } /* * An architecture-optimized byte swap for a 32-bit value. * * Do not use this function directly. The preferred function is rte_bswap32(). */ static inline uint32_t rte_arch_bswap32(uint32_t _x) { return ((_x >> 24) | ((_x >> 8) & 0xff00) | ((_x << 8) & 0xff0000) | ((_x << 24) & 0xff000000)); } /* * An architecture-optimized byte swap for a 64-bit value. * * Do not use this function directly. The preferred function is rte_bswap64(). */ /* 64-bit mode */ static inline uint64_t rte_arch_bswap64(uint64_t _x) { return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | ((_x >> 8) & 0xff000000) | ((_x << 8) & (0xffULL << 32)) | ((_x << 24) & (0xffULL << 40)) | ((_x << 40) & (0xffULL << 48)) | ((_x << 56))); } #ifndef RTE_FORCE_INTRINSICS #define rte_bswap16(x) ((uint16_t)(__builtin_constant_p(x) ? \ rte_constant_bswap16(x) : \ rte_arch_bswap16(x))) #define rte_bswap32(x) ((uint32_t)(__builtin_constant_p(x) ? \ rte_constant_bswap32(x) : \ rte_arch_bswap32(x))) #define rte_bswap64(x) ((uint64_t)(__builtin_constant_p(x) ? \ rte_constant_bswap64(x) : \ rte_arch_bswap64(x))) #else /* * __builtin_bswap16 is only available gcc 4.8 and upwards */ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) #define rte_bswap16(x) ((uint16_t)(__builtin_constant_p(x) ? \ rte_constant_bswap16(x) : \ rte_arch_bswap16(x))) #endif #endif /* Power 8 have both little endian and big endian mode * Power 7 only support big endian */ #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define rte_cpu_to_le_16(x) (x) #define rte_cpu_to_le_32(x) (x) #define rte_cpu_to_le_64(x) (x) #define rte_cpu_to_be_16(x) rte_bswap16(x) #define rte_cpu_to_be_32(x) rte_bswap32(x) #define rte_cpu_to_be_64(x) rte_bswap64(x) #define rte_le_to_cpu_16(x) (x) #define rte_le_to_cpu_32(x) (x) #define rte_le_to_cpu_64(x) (x) #define rte_be_to_cpu_16(x) rte_bswap16(x) #define rte_be_to_cpu_32(x) rte_bswap32(x) #define rte_be_to_cpu_64(x) rte_bswap64(x) #else /* RTE_BIG_ENDIAN */ #define rte_cpu_to_le_16(x) rte_bswap16(x) #define rte_cpu_to_le_32(x) rte_bswap32(x) #define rte_cpu_to_le_64(x) rte_bswap64(x) #define rte_cpu_to_be_16(x) (x) #define rte_cpu_to_be_32(x) (x) #define rte_cpu_to_be_64(x) (x) #define rte_le_to_cpu_16(x) rte_bswap16(x) #define rte_le_to_cpu_32(x) rte_bswap32(x) #define rte_le_to_cpu_64(x) rte_bswap64(x) #define rte_be_to_cpu_16(x) (x) #define rte_be_to_cpu_32(x) (x) #define rte_be_to_cpu_64(x) (x) #endif #ifdef __cplusplus } #endif #endif /* _RTE_BYTEORDER_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_cpuflags.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CPUFLAGS_PPC_64_H_ #define _RTE_CPUFLAGS_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include "generic/rte_cpuflags.h" /* Symbolic values for the entries in the auxiliary table */ #define AT_HWCAP 16 #define AT_HWCAP2 26 /* software based registers */ enum cpu_register_t __RTE_REGISTER_UNDERLYING_TYPE { REG_HWCAP = 0, REG_HWCAP2, }; /** * Enumeration of all CPU features supported */ enum rte_cpu_flag_t __RTE_CPUFLAG_UNDERLYING_TYPE { RTE_CPUFLAG_PPC_LE = 0, RTE_CPUFLAG_TRUE_LE, RTE_CPUFLAG_PSERIES_PERFMON_COMPAT, RTE_CPUFLAG_VSX, RTE_CPUFLAG_ARCH_2_06, RTE_CPUFLAG_POWER6_EXT, RTE_CPUFLAG_DFP, RTE_CPUFLAG_PA6T, RTE_CPUFLAG_ARCH_2_05, RTE_CPUFLAG_ICACHE_SNOOP, RTE_CPUFLAG_SMT, RTE_CPUFLAG_BOOKE, RTE_CPUFLAG_CELLBE, RTE_CPUFLAG_POWER5_PLUS, RTE_CPUFLAG_POWER5, RTE_CPUFLAG_POWER4, RTE_CPUFLAG_NOTB, RTE_CPUFLAG_EFP_DOUBLE, RTE_CPUFLAG_EFP_SINGLE, RTE_CPUFLAG_SPE, RTE_CPUFLAG_UNIFIED_CACHE, RTE_CPUFLAG_4xxMAC, RTE_CPUFLAG_MMU, RTE_CPUFLAG_FPU, RTE_CPUFLAG_ALTIVEC, RTE_CPUFLAG_PPC601, RTE_CPUFLAG_PPC64, RTE_CPUFLAG_PPC32, RTE_CPUFLAG_TAR, RTE_CPUFLAG_LSEL, RTE_CPUFLAG_EBB, RTE_CPUFLAG_DSCR, RTE_CPUFLAG_HTM, RTE_CPUFLAG_ARCH_2_07, /* The last item */ RTE_CPUFLAG_NUMFLAGS,/**< This should always be the last! */ }; static const struct feature_entry cpu_feature_table[] = { FEAT_DEF(PPC_LE, 0x00000001, 0, REG_HWCAP, 0) FEAT_DEF(TRUE_LE, 0x00000001, 0, REG_HWCAP, 1) FEAT_DEF(PSERIES_PERFMON_COMPAT, 0x00000001, 0, REG_HWCAP, 6) FEAT_DEF(VSX, 0x00000001, 0, REG_HWCAP, 7) FEAT_DEF(ARCH_2_06, 0x00000001, 0, REG_HWCAP, 8) FEAT_DEF(POWER6_EXT, 0x00000001, 0, REG_HWCAP, 9) FEAT_DEF(DFP, 0x00000001, 0, REG_HWCAP, 10) FEAT_DEF(PA6T, 0x00000001, 0, REG_HWCAP, 11) FEAT_DEF(ARCH_2_05, 0x00000001, 0, REG_HWCAP, 12) FEAT_DEF(ICACHE_SNOOP, 0x00000001, 0, REG_HWCAP, 13) FEAT_DEF(SMT, 0x00000001, 0, REG_HWCAP, 14) FEAT_DEF(BOOKE, 0x00000001, 0, REG_HWCAP, 15) FEAT_DEF(CELLBE, 0x00000001, 0, REG_HWCAP, 16) FEAT_DEF(POWER5_PLUS, 0x00000001, 0, REG_HWCAP, 17) FEAT_DEF(POWER5, 0x00000001, 0, REG_HWCAP, 18) FEAT_DEF(POWER4, 0x00000001, 0, REG_HWCAP, 19) FEAT_DEF(NOTB, 0x00000001, 0, REG_HWCAP, 20) FEAT_DEF(EFP_DOUBLE, 0x00000001, 0, REG_HWCAP, 21) FEAT_DEF(EFP_SINGLE, 0x00000001, 0, REG_HWCAP, 22) FEAT_DEF(SPE, 0x00000001, 0, REG_HWCAP, 23) FEAT_DEF(UNIFIED_CACHE, 0x00000001, 0, REG_HWCAP, 24) FEAT_DEF(4xxMAC, 0x00000001, 0, REG_HWCAP, 25) FEAT_DEF(MMU, 0x00000001, 0, REG_HWCAP, 26) FEAT_DEF(FPU, 0x00000001, 0, REG_HWCAP, 27) FEAT_DEF(ALTIVEC, 0x00000001, 0, REG_HWCAP, 28) FEAT_DEF(PPC601, 0x00000001, 0, REG_HWCAP, 29) FEAT_DEF(PPC64, 0x00000001, 0, REG_HWCAP, 30) FEAT_DEF(PPC32, 0x00000001, 0, REG_HWCAP, 31) FEAT_DEF(TAR, 0x00000001, 0, REG_HWCAP2, 26) FEAT_DEF(LSEL, 0x00000001, 0, REG_HWCAP2, 27) FEAT_DEF(EBB, 0x00000001, 0, REG_HWCAP2, 28) FEAT_DEF(DSCR, 0x00000001, 0, REG_HWCAP2, 29) FEAT_DEF(HTM, 0x00000001, 0, REG_HWCAP2, 30) FEAT_DEF(ARCH_2_07, 0x00000001, 0, REG_HWCAP2, 31) }; /* * Read AUXV software register and get cpu features for Power */ static inline void rte_cpu_get_features(__attribute__((unused)) uint32_t leaf, __attribute__((unused)) uint32_t subleaf, cpuid_registers_t out) { int auxv_fd; Elf64_auxv_t auxv; auxv_fd = open("/proc/self/auxv", O_RDONLY); assert(auxv_fd); while (read(auxv_fd, &auxv, sizeof(Elf64_auxv_t)) == sizeof(Elf64_auxv_t)) { if (auxv.a_type == AT_HWCAP) out[REG_HWCAP] = auxv.a_un.a_val; else if (auxv.a_type == AT_HWCAP2) out[REG_HWCAP2] = auxv.a_un.a_val; } } /* * Checks if a particular flag is available on current machine. */ static inline int rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature) { const struct feature_entry *feat; cpuid_registers_t regs = {0}; if (feature >= RTE_CPUFLAG_NUMFLAGS) /* Flag does not match anything in the feature tables */ return -ENOENT; feat = &cpu_feature_table[feature]; if (!feat->leaf) /* This entry in the table wasn't filled out! */ return -EFAULT; /* get the cpuid leaf containing the desired feature */ rte_cpu_get_features(feat->leaf, feat->subleaf, regs); /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) & 1; } #ifdef __cplusplus } #endif #endif /* _RTE_CPUFLAGS_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_cycles.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CYCLES_PPC_64_H_ #define _RTE_CYCLES_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_cycles.h" #include /** * Read the time base register. * * @return * The time base for this lcore. */ static inline uint64_t rte_rdtsc(void) { union { uint64_t tsc_64; struct { #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN uint32_t hi_32; uint32_t lo_32; #else uint32_t lo_32; uint32_t hi_32; #endif }; } tsc; uint32_t tmp; asm volatile( "0:\n" "mftbu %[hi32]\n" "mftb %[lo32]\n" "mftbu %[tmp]\n" "cmpw %[tmp],%[hi32]\n" "bne 0b\n" : [hi32] "=r"(tsc.hi_32), [lo32] "=r"(tsc.lo_32), [tmp] "=r"(tmp) ); return tsc.tsc_64; } static inline uint64_t rte_rdtsc_precise(void) { rte_mb(); return rte_rdtsc(); } static inline uint64_t rte_get_tsc_cycles(void) { return rte_rdtsc(); } #ifdef __cplusplus } #endif #endif /* _RTE_CYCLES_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_memcpy.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMCPY_PPC_64_H_ #define _RTE_MEMCPY_PPC_64_H_ #include #include /*To include altivec.h, GCC version must >= 4.8 */ #include #ifdef __cplusplus extern "C" { #endif #include "generic/rte_memcpy.h" static inline void rte_mov16(uint8_t *dst, const uint8_t *src) { vec_vsx_st(vec_vsx_ld(0, src), 0, dst); } static inline void rte_mov32(uint8_t *dst, const uint8_t *src) { vec_vsx_st(vec_vsx_ld(0, src), 0, dst); vec_vsx_st(vec_vsx_ld(16, src), 16, dst); } static inline void rte_mov48(uint8_t *dst, const uint8_t *src) { vec_vsx_st(vec_vsx_ld(0, src), 0, dst); vec_vsx_st(vec_vsx_ld(16, src), 16, dst); vec_vsx_st(vec_vsx_ld(32, src), 32, dst); } static inline void rte_mov64(uint8_t *dst, const uint8_t *src) { vec_vsx_st(vec_vsx_ld(0, src), 0, dst); vec_vsx_st(vec_vsx_ld(16, src), 16, dst); vec_vsx_st(vec_vsx_ld(32, src), 32, dst); vec_vsx_st(vec_vsx_ld(48, src), 48, dst); } static inline void rte_mov128(uint8_t *dst, const uint8_t *src) { vec_vsx_st(vec_vsx_ld(0, src), 0, dst); vec_vsx_st(vec_vsx_ld(16, src), 16, dst); vec_vsx_st(vec_vsx_ld(32, src), 32, dst); vec_vsx_st(vec_vsx_ld(48, src), 48, dst); vec_vsx_st(vec_vsx_ld(64, src), 64, dst); vec_vsx_st(vec_vsx_ld(80, src), 80, dst); vec_vsx_st(vec_vsx_ld(96, src), 96, dst); vec_vsx_st(vec_vsx_ld(112, src), 112, dst); } static inline void rte_mov256(uint8_t *dst, const uint8_t *src) { rte_mov128(dst, src); rte_mov128(dst + 128, src + 128); } #define rte_memcpy(dst, src, n) \ ({ (__builtin_constant_p(n)) ? \ memcpy((dst), (src), (n)) : \ rte_memcpy_func((dst), (src), (n)); }) static inline void * rte_memcpy_func(void *dst, const void *src, size_t n) { void *ret = dst; /* We can't copy < 16 bytes using XMM registers so do it manually. */ if (n < 16) { if (n & 0x01) { *(uint8_t *)dst = *(const uint8_t *)src; dst = (uint8_t *)dst + 1; src = (const uint8_t *)src + 1; } if (n & 0x02) { *(uint16_t *)dst = *(const uint16_t *)src; dst = (uint16_t *)dst + 1; src = (const uint16_t *)src + 1; } if (n & 0x04) { *(uint32_t *)dst = *(const uint32_t *)src; dst = (uint32_t *)dst + 1; src = (const uint32_t *)src + 1; } if (n & 0x08) *(uint64_t *)dst = *(const uint64_t *)src; return ret; } /* Special fast cases for <= 128 bytes */ if (n <= 32) { rte_mov16((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n <= 64) { rte_mov32((uint8_t *)dst, (const uint8_t *)src); rte_mov32((uint8_t *)dst - 32 + n, (const uint8_t *)src - 32 + n); return ret; } if (n <= 128) { rte_mov64((uint8_t *)dst, (const uint8_t *)src); rte_mov64((uint8_t *)dst - 64 + n, (const uint8_t *)src - 64 + n); return ret; } /* * For large copies > 128 bytes. This combination of 256, 64 and 16 byte * copies was found to be faster than doing 128 and 32 byte copies as * well. */ for ( ; n >= 256; n -= 256) { rte_mov256((uint8_t *)dst, (const uint8_t *)src); dst = (uint8_t *)dst + 256; src = (const uint8_t *)src + 256; } /* * We split the remaining bytes (which will be less than 256) into * 64byte (2^6) chunks. * Using incrementing integers in the case labels of a switch statement * enourages the compiler to use a jump table. To get incrementing * integers, we shift the 2 relevant bits to the LSB position to first * get decrementing integers, and then subtract. */ switch (3 - (n >> 6)) { case 0x00: rte_mov64((uint8_t *)dst, (const uint8_t *)src); n -= 64; dst = (uint8_t *)dst + 64; src = (const uint8_t *)src + 64; /* fallthrough */ case 0x01: rte_mov64((uint8_t *)dst, (const uint8_t *)src); n -= 64; dst = (uint8_t *)dst + 64; src = (const uint8_t *)src + 64; /* fallthrough */ case 0x02: rte_mov64((uint8_t *)dst, (const uint8_t *)src); n -= 64; dst = (uint8_t *)dst + 64; src = (const uint8_t *)src + 64; /* fallthrough */ default: ; } /* * We split the remaining bytes (which will be less than 64) into * 16byte (2^4) chunks, using the same switch structure as above. */ switch (3 - (n >> 4)) { case 0x00: rte_mov16((uint8_t *)dst, (const uint8_t *)src); n -= 16; dst = (uint8_t *)dst + 16; src = (const uint8_t *)src + 16; /* fallthrough */ case 0x01: rte_mov16((uint8_t *)dst, (const uint8_t *)src); n -= 16; dst = (uint8_t *)dst + 16; src = (const uint8_t *)src + 16; /* fallthrough */ case 0x02: rte_mov16((uint8_t *)dst, (const uint8_t *)src); n -= 16; dst = (uint8_t *)dst + 16; src = (const uint8_t *)src + 16; /* fallthrough */ default: ; } /* Copy any remaining bytes, without going beyond end of buffers */ if (n != 0) rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } #ifdef __cplusplus } #endif #endif /* _RTE_MEMCPY_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_prefetch.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PREFETCH_PPC_64_H_ #define _RTE_PREFETCH_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_prefetch.h" static inline void rte_prefetch0(const volatile void *p) { asm volatile ("dcbt 0,%[p],1" : : [p] "r" (p)); } static inline void rte_prefetch1(const volatile void *p) { asm volatile ("dcbt 0,%[p],1" : : [p] "r" (p)); } static inline void rte_prefetch2(const volatile void *p) { asm volatile ("dcbt 0,%[p],1" : : [p] "r" (p)); } #ifdef __cplusplus } #endif #endif /* _RTE_PREFETCH_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_rwlock.h ================================================ #ifndef _RTE_RWLOCK_PPC_64_H_ #define _RTE_RWLOCK_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_rwlock.h" static inline void rte_rwlock_read_lock_tm(rte_rwlock_t *rwl) { rte_rwlock_read_lock(rwl); } static inline void rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl) { rte_rwlock_read_unlock(rwl); } static inline void rte_rwlock_write_lock_tm(rte_rwlock_t *rwl) { rte_rwlock_write_lock(rwl); } static inline void rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl) { rte_rwlock_write_unlock(rwl); } #ifdef __cplusplus } #endif #endif /* _RTE_RWLOCK_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/ppc_64/rte_spinlock.h ================================================ /* * BSD LICENSE * * Copyright (C) IBM Corporation 2014. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_SPINLOCK_PPC_64_H_ #define _RTE_SPINLOCK_PPC_64_H_ #ifdef __cplusplus extern "C" { #endif #include #include "generic/rte_spinlock.h" /* Fixme: Use intrinsics to implement the spinlock on Power architecture */ #ifndef RTE_FORCE_INTRINSICS static inline void rte_spinlock_lock(rte_spinlock_t *sl) { while (__sync_lock_test_and_set(&sl->locked, 1)) while (sl->locked) rte_pause(); } static inline void rte_spinlock_unlock(rte_spinlock_t *sl) { __sync_lock_release(&sl->locked); } static inline int rte_spinlock_trylock(rte_spinlock_t *sl) { return (__sync_lock_test_and_set(&sl->locked, 1) == 0); } #endif static inline int rte_tm_supported(void) { return 0; } static inline void rte_spinlock_lock_tm(rte_spinlock_t *sl) { rte_spinlock_lock(sl); /* fall-back */ } static inline int rte_spinlock_trylock_tm(rte_spinlock_t *sl) { return rte_spinlock_trylock(sl); } static inline void rte_spinlock_unlock_tm(rte_spinlock_t *sl) { rte_spinlock_unlock(sl); } static inline void rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr) { rte_spinlock_recursive_lock(slr); /* fall-back */ } static inline void rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr) { rte_spinlock_recursive_unlock(slr); } static inline int rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr) { return rte_spinlock_recursive_trylock(slr); } #ifdef __cplusplus } #endif #endif /* _RTE_SPINLOCK_PPC_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_atomic.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ATOMIC_TILE_H_ #define _RTE_ATOMIC_TILE_H_ #ifndef RTE_FORCE_INTRINSICS # error Platform must be built with CONFIG_RTE_FORCE_INTRINSICS #endif #ifdef __cplusplus extern "C" { #endif #include "generic/rte_atomic.h" /** * General memory barrier. * * Guarantees that the LOAD and STORE operations generated before the * barrier occur before the LOAD and STORE operations generated after. * This function is architecture dependent. */ static inline void rte_mb(void) { __sync_synchronize(); } /** * Write memory barrier. * * Guarantees that the STORE operations generated before the barrier * occur before the STORE operations generated after. * This function is architecture dependent. */ static inline void rte_wmb(void) { __sync_synchronize(); } /** * Read memory barrier. * * Guarantees that the LOAD operations generated before the barrier * occur before the LOAD operations generated after. * This function is architecture dependent. */ static inline void rte_rmb(void) { __sync_synchronize(); } #ifdef __cplusplus } #endif #endif /* _RTE_ATOMIC_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_byteorder.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_BYTEORDER_TILE_H_ #define _RTE_BYTEORDER_TILE_H_ #ifndef RTE_FORCE_INTRINSICS # error Platform must be built with CONFIG_RTE_FORCE_INTRINSICS #endif #ifdef __cplusplus extern "C" { #endif #include "generic/rte_byteorder.h" #if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) #define rte_bswap16(x) rte_constant_bswap16(x) #endif #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define rte_cpu_to_le_16(x) (x) #define rte_cpu_to_le_32(x) (x) #define rte_cpu_to_le_64(x) (x) #define rte_cpu_to_be_16(x) rte_bswap16(x) #define rte_cpu_to_be_32(x) rte_bswap32(x) #define rte_cpu_to_be_64(x) rte_bswap64(x) #define rte_le_to_cpu_16(x) (x) #define rte_le_to_cpu_32(x) (x) #define rte_le_to_cpu_64(x) (x) #define rte_be_to_cpu_16(x) rte_bswap16(x) #define rte_be_to_cpu_32(x) rte_bswap32(x) #define rte_be_to_cpu_64(x) rte_bswap64(x) #else /* RTE_BIG_ENDIAN */ #define rte_cpu_to_le_16(x) rte_bswap16(x) #define rte_cpu_to_le_32(x) rte_bswap32(x) #define rte_cpu_to_le_64(x) rte_bswap64(x) #define rte_cpu_to_be_16(x) (x) #define rte_cpu_to_be_32(x) (x) #define rte_cpu_to_be_64(x) (x) #define rte_le_to_cpu_16(x) rte_bswap16(x) #define rte_le_to_cpu_32(x) rte_bswap32(x) #define rte_le_to_cpu_64(x) rte_bswap64(x) #define rte_be_to_cpu_16(x) (x) #define rte_be_to_cpu_32(x) (x) #define rte_be_to_cpu_64(x) (x) #endif #ifdef __cplusplus } #endif #endif /* _RTE_BYTEORDER_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_cpuflags.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CPUFLAGS_TILE_H_ #define _RTE_CPUFLAGS_TILE_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include "generic/rte_cpuflags.h" /* software based registers */ enum cpu_register_t __RTE_REGISTER_UNDERLYING_TYPE { REG_DUMMY = 0 }; /** * Enumeration of all CPU features supported */ enum rte_cpu_flag_t __RTE_CPUFLAG_UNDERLYING_TYPE { RTE_CPUFLAG_NUMFLAGS /**< This should always be the last! */ }; static const struct feature_entry cpu_feature_table[] = { }; /* * Read AUXV software register and get cpu features for Power */ static inline void rte_cpu_get_features(__attribute__((unused)) uint32_t leaf, __attribute__((unused)) uint32_t subleaf, __attribute__((unused)) cpuid_registers_t out) { } /* * Checks if a particular flag is available on current machine. */ static inline int rte_cpu_get_flag_enabled(__attribute__((unused)) enum rte_cpu_flag_t feature) { return -ENOENT; } #ifdef __cplusplus } #endif #endif /* _RTE_CPUFLAGS_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_cycles.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CYCLES_TILE_H_ #define _RTE_CYCLES_TILE_H_ #ifdef __cplusplus extern "C" { #endif #include #include "generic/rte_cycles.h" /** * Read the time base register. * * @return * The time base for this lcore. */ static inline uint64_t rte_rdtsc(void) { return get_cycle_count(); } static inline uint64_t rte_rdtsc_precise(void) { rte_mb(); return rte_rdtsc(); } static inline uint64_t rte_get_tsc_cycles(void) { return rte_rdtsc(); } #ifdef __cplusplus } #endif #endif /* _RTE_CYCLES_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_memcpy.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMCPY_TILE_H_ #define _RTE_MEMCPY_TILE_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include "generic/rte_memcpy.h" static inline void rte_mov16(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 16); } static inline void rte_mov32(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 32); } static inline void rte_mov48(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 48); } static inline void rte_mov64(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 64); } static inline void rte_mov128(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 128); } static inline void rte_mov256(uint8_t *dst, const uint8_t *src) { memcpy(dst, src, 256); } #define rte_memcpy(d, s, n) memcpy((d), (s), (n)) static inline void * rte_memcpy_func(void *dst, const void *src, size_t n) { return memcpy(dst, src, n); } #ifdef __cplusplus } #endif #endif /* _RTE_MEMCPY_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_prefetch.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PREFETCH_TILE_H_ #define _RTE_PREFETCH_TILE_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_prefetch.h" static inline void rte_prefetch0(const volatile void *p) { __builtin_prefetch((const void *)(uintptr_t)p, 0, 3); } static inline void rte_prefetch1(const volatile void *p) { __builtin_prefetch((const void *)(uintptr_t)p, 0, 2); } static inline void rte_prefetch2(const volatile void *p) { __builtin_prefetch((const void *)(uintptr_t)p, 0, 1); } #ifdef __cplusplus } #endif #endif /* _RTE_PREFETCH_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_rwlock.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_RWLOCK_TILE_H_ #define _RTE_RWLOCK_TILE_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_rwlock.h" static inline void rte_rwlock_read_lock_tm(rte_rwlock_t *rwl) { rte_rwlock_read_lock(rwl); } static inline void rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl) { rte_rwlock_read_unlock(rwl); } static inline void rte_rwlock_write_lock_tm(rte_rwlock_t *rwl) { rte_rwlock_write_lock(rwl); } static inline void rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl) { rte_rwlock_write_unlock(rwl); } #ifdef __cplusplus } #endif #endif /* _RTE_RWLOCK_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/tile/rte_spinlock.h ================================================ /* * BSD LICENSE * * Copyright (C) EZchip Semiconductor Ltd. 2015. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of EZchip Semiconductor nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_SPINLOCK_TILE_H_ #define _RTE_SPINLOCK_TILE_H_ #ifndef RTE_FORCE_INTRINSICS # error Platform must be built with CONFIG_RTE_FORCE_INTRINSICS #endif #ifdef __cplusplus extern "C" { #endif #include #include "generic/rte_spinlock.h" static inline int rte_tm_supported(void) { return 0; } static inline void rte_spinlock_lock_tm(rte_spinlock_t *sl) { rte_spinlock_lock(sl); /* fall-back */ } static inline int rte_spinlock_trylock_tm(rte_spinlock_t *sl) { return rte_spinlock_trylock(sl); } static inline void rte_spinlock_unlock_tm(rte_spinlock_t *sl) { rte_spinlock_unlock(sl); } static inline void rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr) { rte_spinlock_recursive_lock(slr); /* fall-back */ } static inline void rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr) { rte_spinlock_recursive_unlock(slr); } static inline int rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr) { return rte_spinlock_recursive_trylock(slr); } #ifdef __cplusplus } #endif #endif /* _RTE_SPINLOCK_TILE_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_atomic.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ATOMIC_X86_H_ #define _RTE_ATOMIC_X86_H_ #ifdef __cplusplus extern "C" { #endif #include #include "generic/rte_atomic.h" #if RTE_MAX_LCORE == 1 #define MPLOCKED /**< No need to insert MP lock prefix. */ #else #define MPLOCKED "lock ; " /**< Insert MP lock prefix. */ #endif #define rte_mb() _mm_mfence() #define rte_wmb() _mm_sfence() #define rte_rmb() _mm_lfence() /*------------------------- 16 bit atomic operations -------------------------*/ #ifndef RTE_FORCE_INTRINSICS static inline int rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src) { uint8_t res; asm volatile( MPLOCKED "cmpxchgw %[src], %[dst];" "sete %[res];" : [res] "=a" (res), /* output */ [dst] "=m" (*dst) : [src] "r" (src), /* input */ "a" (exp), "m" (*dst) : "memory"); /* no-clobber list */ return res; } static inline int rte_atomic16_test_and_set(rte_atomic16_t *v) { return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1); } static inline void rte_atomic16_inc(rte_atomic16_t *v) { asm volatile( MPLOCKED "incw %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline void rte_atomic16_dec(rte_atomic16_t *v) { asm volatile( MPLOCKED "decw %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v) { uint8_t ret; asm volatile( MPLOCKED "incw %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return (ret != 0); } static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v) { uint8_t ret; asm volatile(MPLOCKED "decw %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return (ret != 0); } /*------------------------- 32 bit atomic operations -------------------------*/ static inline int rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src) { uint8_t res; asm volatile( MPLOCKED "cmpxchgl %[src], %[dst];" "sete %[res];" : [res] "=a" (res), /* output */ [dst] "=m" (*dst) : [src] "r" (src), /* input */ "a" (exp), "m" (*dst) : "memory"); /* no-clobber list */ return res; } static inline int rte_atomic32_test_and_set(rte_atomic32_t *v) { return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1); } static inline void rte_atomic32_inc(rte_atomic32_t *v) { asm volatile( MPLOCKED "incl %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline void rte_atomic32_dec(rte_atomic32_t *v) { asm volatile( MPLOCKED "decl %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v) { uint8_t ret; asm volatile( MPLOCKED "incl %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return (ret != 0); } static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v) { uint8_t ret; asm volatile(MPLOCKED "decl %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return (ret != 0); } #endif #ifdef RTE_ARCH_I686 #include "rte_atomic_32.h" #else #include "rte_atomic_64.h" #endif #ifdef __cplusplus } #endif #endif /* _RTE_ATOMIC_X86_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_atomic_32.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Inspired from FreeBSD src/sys/i386/include/atomic.h * Copyright (c) 1998 Doug Rabson * All rights reserved. */ #ifndef _RTE_ATOMIC_I686_H_ #define _RTE_ATOMIC_I686_H_ /*------------------------- 64 bit atomic operations -------------------------*/ #ifndef RTE_FORCE_INTRINSICS static inline int rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src) { uint8_t res; union { struct { uint32_t l32; uint32_t h32; }; uint64_t u64; } _exp, _src; _exp.u64 = exp; _src.u64 = src; #ifndef __PIC__ asm volatile ( MPLOCKED "cmpxchg8b (%[dst]);" "setz %[res];" : [res] "=a" (res) /* result in eax */ : [dst] "S" (dst), /* esi */ "b" (_src.l32), /* ebx */ "c" (_src.h32), /* ecx */ "a" (_exp.l32), /* eax */ "d" (_exp.h32) /* edx */ : "memory" ); /* no-clobber list */ #else asm volatile ( "mov %%ebx, %%edi\n" MPLOCKED "cmpxchg8b (%[dst]);" "setz %[res];" "xchgl %%ebx, %%edi;\n" : [res] "=a" (res) /* result in eax */ : [dst] "S" (dst), /* esi */ "D" (_src.l32), /* ebx */ "c" (_src.h32), /* ecx */ "a" (_exp.l32), /* eax */ "d" (_exp.h32) /* edx */ : "memory" ); /* no-clobber list */ #endif return res; } static inline void rte_atomic64_init(rte_atomic64_t *v) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, 0); } } static inline int64_t rte_atomic64_read(rte_atomic64_t *v) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; /* replace the value by itself */ success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp); } return tmp; } static inline void rte_atomic64_set(rte_atomic64_t *v, int64_t new_value) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, new_value); } } static inline void rte_atomic64_add(rte_atomic64_t *v, int64_t inc) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp + inc); } } static inline void rte_atomic64_sub(rte_atomic64_t *v, int64_t dec) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp - dec); } } static inline void rte_atomic64_inc(rte_atomic64_t *v) { rte_atomic64_add(v, 1); } static inline void rte_atomic64_dec(rte_atomic64_t *v) { rte_atomic64_sub(v, 1); } static inline int64_t rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp + inc); } return tmp + inc; } static inline int64_t rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec) { int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp - dec); } return tmp - dec; } static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v) { return rte_atomic64_add_return(v, 1) == 0; } static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v) { return rte_atomic64_sub_return(v, 1) == 0; } static inline int rte_atomic64_test_and_set(rte_atomic64_t *v) { return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1); } static inline void rte_atomic64_clear(rte_atomic64_t *v) { rte_atomic64_set(v, 0); } #endif #endif /* _RTE_ATOMIC_I686_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_atomic_64.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Inspired from FreeBSD src/sys/amd64/include/atomic.h * Copyright (c) 1998 Doug Rabson * All rights reserved. */ #ifndef _RTE_ATOMIC_X86_64_H_ #define _RTE_ATOMIC_X86_64_H_ /*------------------------- 64 bit atomic operations -------------------------*/ #ifndef RTE_FORCE_INTRINSICS static inline int rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src) { uint8_t res; asm volatile( MPLOCKED "cmpxchgq %[src], %[dst];" "sete %[res];" : [res] "=a" (res), /* output */ [dst] "=m" (*dst) : [src] "r" (src), /* input */ "a" (exp), "m" (*dst) : "memory"); /* no-clobber list */ return res; } static inline void rte_atomic64_init(rte_atomic64_t *v) { v->cnt = 0; } static inline int64_t rte_atomic64_read(rte_atomic64_t *v) { return v->cnt; } static inline void rte_atomic64_set(rte_atomic64_t *v, int64_t new_value) { v->cnt = new_value; } static inline void rte_atomic64_add(rte_atomic64_t *v, int64_t inc) { asm volatile( MPLOCKED "addq %[inc], %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : [inc] "ir" (inc), /* input */ "m" (v->cnt) ); } static inline void rte_atomic64_sub(rte_atomic64_t *v, int64_t dec) { asm volatile( MPLOCKED "subq %[dec], %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : [dec] "ir" (dec), /* input */ "m" (v->cnt) ); } static inline void rte_atomic64_inc(rte_atomic64_t *v) { asm volatile( MPLOCKED "incq %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline void rte_atomic64_dec(rte_atomic64_t *v) { asm volatile( MPLOCKED "decq %[cnt]" : [cnt] "=m" (v->cnt) /* output */ : "m" (v->cnt) /* input */ ); } static inline int64_t rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc) { int64_t prev = inc; asm volatile( MPLOCKED "xaddq %[prev], %[cnt]" : [prev] "+r" (prev), /* output */ [cnt] "=m" (v->cnt) : "m" (v->cnt) /* input */ ); return prev + inc; } static inline int64_t rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec) { return rte_atomic64_add_return(v, -dec); } static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v) { uint8_t ret; asm volatile( MPLOCKED "incq %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return ret != 0; } static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v) { uint8_t ret; asm volatile( MPLOCKED "decq %[cnt] ; " "sete %[ret]" : [cnt] "+m" (v->cnt), /* output */ [ret] "=qm" (ret) ); return ret != 0; } static inline int rte_atomic64_test_and_set(rte_atomic64_t *v) { return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1); } static inline void rte_atomic64_clear(rte_atomic64_t *v) { v->cnt = 0; } #endif #endif /* _RTE_ATOMIC_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_byteorder.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_BYTEORDER_X86_H_ #define _RTE_BYTEORDER_X86_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_byteorder.h" #ifndef RTE_BYTE_ORDER #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN #endif /* * An architecture-optimized byte swap for a 16-bit value. * * Do not use this function directly. The preferred function is rte_bswap16(). */ static inline uint16_t rte_arch_bswap16(uint16_t _x) { register uint16_t x = _x; asm volatile ("xchgb %b[x1],%h[x2]" : [x1] "=Q" (x) : [x2] "0" (x) ); return x; } /* * An architecture-optimized byte swap for a 32-bit value. * * Do not use this function directly. The preferred function is rte_bswap32(). */ static inline uint32_t rte_arch_bswap32(uint32_t _x) { register uint32_t x = _x; asm volatile ("bswap %[x]" : [x] "+r" (x) ); return x; } #ifndef RTE_FORCE_INTRINSICS #define rte_bswap16(x) ((uint16_t)(__builtin_constant_p(x) ? \ rte_constant_bswap16(x) : \ rte_arch_bswap16(x))) #define rte_bswap32(x) ((uint32_t)(__builtin_constant_p(x) ? \ rte_constant_bswap32(x) : \ rte_arch_bswap32(x))) #define rte_bswap64(x) ((uint64_t)(__builtin_constant_p(x) ? \ rte_constant_bswap64(x) : \ rte_arch_bswap64(x))) #else /* * __builtin_bswap16 is only available gcc 4.8 and upwards */ #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8) #define rte_bswap16(x) ((uint16_t)(__builtin_constant_p(x) ? \ rte_constant_bswap16(x) : \ rte_arch_bswap16(x))) #endif #endif #define rte_cpu_to_le_16(x) (x) #define rte_cpu_to_le_32(x) (x) #define rte_cpu_to_le_64(x) (x) #define rte_cpu_to_be_16(x) rte_bswap16(x) #define rte_cpu_to_be_32(x) rte_bswap32(x) #define rte_cpu_to_be_64(x) rte_bswap64(x) #define rte_le_to_cpu_16(x) (x) #define rte_le_to_cpu_32(x) (x) #define rte_le_to_cpu_64(x) (x) #define rte_be_to_cpu_16(x) rte_bswap16(x) #define rte_be_to_cpu_32(x) rte_bswap32(x) #define rte_be_to_cpu_64(x) rte_bswap64(x) #ifdef RTE_ARCH_I686 #include "rte_byteorder_32.h" #else #include "rte_byteorder_64.h" #endif #ifdef __cplusplus } #endif #endif /* _RTE_BYTEORDER_X86_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_byteorder_32.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_BYTEORDER_I686_H_ #define _RTE_BYTEORDER_I686_H_ /* * An architecture-optimized byte swap for a 64-bit value. * * Do not use this function directly. The preferred function is rte_bswap64(). */ /* Compat./Leg. mode */ static inline uint64_t rte_arch_bswap64(uint64_t x) { uint64_t ret = 0; ret |= ((uint64_t)rte_arch_bswap32(x & 0xffffffffUL) << 32); ret |= ((uint64_t)rte_arch_bswap32((x >> 32) & 0xffffffffUL)); return ret; } #endif /* _RTE_BYTEORDER_I686_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_byteorder_64.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_BYTEORDER_X86_64_H_ #define _RTE_BYTEORDER_X86_64_H_ /* * An architecture-optimized byte swap for a 64-bit value. * * Do not use this function directly. The preferred function is rte_bswap64(). */ /* 64-bit mode */ static inline uint64_t rte_arch_bswap64(uint64_t _x) { register uint64_t x = _x; asm volatile ("bswap %[x]" : [x] "+r" (x) ); return x; } #endif /* _RTE_BYTEORDER_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_cpuflags.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CPUFLAGS_X86_64_H_ #define _RTE_CPUFLAGS_X86_64_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include "generic/rte_cpuflags.h" enum rte_cpu_flag_t __RTE_CPUFLAG_UNDERLYING_TYPE { /* (EAX 01h) ECX features*/ RTE_CPUFLAG_SSE3 = 0, /**< SSE3 */ RTE_CPUFLAG_PCLMULQDQ, /**< PCLMULQDQ */ RTE_CPUFLAG_DTES64, /**< DTES64 */ RTE_CPUFLAG_MONITOR, /**< MONITOR */ RTE_CPUFLAG_DS_CPL, /**< DS_CPL */ RTE_CPUFLAG_VMX, /**< VMX */ RTE_CPUFLAG_SMX, /**< SMX */ RTE_CPUFLAG_EIST, /**< EIST */ RTE_CPUFLAG_TM2, /**< TM2 */ RTE_CPUFLAG_SSSE3, /**< SSSE3 */ RTE_CPUFLAG_CNXT_ID, /**< CNXT_ID */ RTE_CPUFLAG_FMA, /**< FMA */ RTE_CPUFLAG_CMPXCHG16B, /**< CMPXCHG16B */ RTE_CPUFLAG_XTPR, /**< XTPR */ RTE_CPUFLAG_PDCM, /**< PDCM */ RTE_CPUFLAG_PCID, /**< PCID */ RTE_CPUFLAG_DCA, /**< DCA */ RTE_CPUFLAG_SSE4_1, /**< SSE4_1 */ RTE_CPUFLAG_SSE4_2, /**< SSE4_2 */ RTE_CPUFLAG_X2APIC, /**< X2APIC */ RTE_CPUFLAG_MOVBE, /**< MOVBE */ RTE_CPUFLAG_POPCNT, /**< POPCNT */ RTE_CPUFLAG_TSC_DEADLINE, /**< TSC_DEADLINE */ RTE_CPUFLAG_AES, /**< AES */ RTE_CPUFLAG_XSAVE, /**< XSAVE */ RTE_CPUFLAG_OSXSAVE, /**< OSXSAVE */ RTE_CPUFLAG_AVX, /**< AVX */ RTE_CPUFLAG_F16C, /**< F16C */ RTE_CPUFLAG_RDRAND, /**< RDRAND */ /* (EAX 01h) EDX features */ RTE_CPUFLAG_FPU, /**< FPU */ RTE_CPUFLAG_VME, /**< VME */ RTE_CPUFLAG_DE, /**< DE */ RTE_CPUFLAG_PSE, /**< PSE */ RTE_CPUFLAG_TSC, /**< TSC */ RTE_CPUFLAG_MSR, /**< MSR */ RTE_CPUFLAG_PAE, /**< PAE */ RTE_CPUFLAG_MCE, /**< MCE */ RTE_CPUFLAG_CX8, /**< CX8 */ RTE_CPUFLAG_APIC, /**< APIC */ RTE_CPUFLAG_SEP, /**< SEP */ RTE_CPUFLAG_MTRR, /**< MTRR */ RTE_CPUFLAG_PGE, /**< PGE */ RTE_CPUFLAG_MCA, /**< MCA */ RTE_CPUFLAG_CMOV, /**< CMOV */ RTE_CPUFLAG_PAT, /**< PAT */ RTE_CPUFLAG_PSE36, /**< PSE36 */ RTE_CPUFLAG_PSN, /**< PSN */ RTE_CPUFLAG_CLFSH, /**< CLFSH */ RTE_CPUFLAG_DS, /**< DS */ RTE_CPUFLAG_ACPI, /**< ACPI */ RTE_CPUFLAG_MMX, /**< MMX */ RTE_CPUFLAG_FXSR, /**< FXSR */ RTE_CPUFLAG_SSE, /**< SSE */ RTE_CPUFLAG_SSE2, /**< SSE2 */ RTE_CPUFLAG_SS, /**< SS */ RTE_CPUFLAG_HTT, /**< HTT */ RTE_CPUFLAG_TM, /**< TM */ RTE_CPUFLAG_PBE, /**< PBE */ /* (EAX 06h) EAX features */ RTE_CPUFLAG_DIGTEMP, /**< DIGTEMP */ RTE_CPUFLAG_TRBOBST, /**< TRBOBST */ RTE_CPUFLAG_ARAT, /**< ARAT */ RTE_CPUFLAG_PLN, /**< PLN */ RTE_CPUFLAG_ECMD, /**< ECMD */ RTE_CPUFLAG_PTM, /**< PTM */ /* (EAX 06h) ECX features */ RTE_CPUFLAG_MPERF_APERF_MSR, /**< MPERF_APERF_MSR */ RTE_CPUFLAG_ACNT2, /**< ACNT2 */ RTE_CPUFLAG_ENERGY_EFF, /**< ENERGY_EFF */ /* (EAX 07h, ECX 0h) EBX features */ RTE_CPUFLAG_FSGSBASE, /**< FSGSBASE */ RTE_CPUFLAG_BMI1, /**< BMI1 */ RTE_CPUFLAG_HLE, /**< Hardware Lock elision */ RTE_CPUFLAG_AVX2, /**< AVX2 */ RTE_CPUFLAG_SMEP, /**< SMEP */ RTE_CPUFLAG_BMI2, /**< BMI2 */ RTE_CPUFLAG_ERMS, /**< ERMS */ RTE_CPUFLAG_INVPCID, /**< INVPCID */ RTE_CPUFLAG_RTM, /**< Transactional memory */ /* (EAX 80000001h) ECX features */ RTE_CPUFLAG_LAHF_SAHF, /**< LAHF_SAHF */ RTE_CPUFLAG_LZCNT, /**< LZCNT */ /* (EAX 80000001h) EDX features */ RTE_CPUFLAG_SYSCALL, /**< SYSCALL */ RTE_CPUFLAG_XD, /**< XD */ RTE_CPUFLAG_1GB_PG, /**< 1GB_PG */ RTE_CPUFLAG_RDTSCP, /**< RDTSCP */ RTE_CPUFLAG_EM64T, /**< EM64T */ /* (EAX 80000007h) EDX features */ RTE_CPUFLAG_INVTSC, /**< INVTSC */ /* The last item */ RTE_CPUFLAG_NUMFLAGS, /**< This should always be the last! */ }; enum cpu_register_t __RTE_REGISTER_UNDERLYING_TYPE { RTE_REG_EAX = 0, RTE_REG_EBX, RTE_REG_ECX, RTE_REG_EDX, }; static const struct feature_entry cpu_feature_table[] = { FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX, 0) FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX, 1) FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX, 2) FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX, 3) FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX, 4) FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX, 5) FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX, 6) FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX, 7) FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX, 8) FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX, 9) FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10) FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12) FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13) FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14) FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15) FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17) FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18) FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19) FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20) FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21) FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22) FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23) FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24) FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25) FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26) FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27) FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28) FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29) FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30) FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX, 0) FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX, 1) FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX, 2) FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX, 3) FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX, 4) FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX, 5) FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX, 6) FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX, 7) FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX, 8) FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX, 9) FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11) FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12) FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13) FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14) FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15) FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16) FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17) FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18) FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19) FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21) FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22) FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23) FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24) FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25) FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26) FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27) FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28) FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29) FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31) FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX, 0) FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX, 1) FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX, 2) FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX, 4) FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX, 5) FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX, 6) FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX, 0) FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX, 1) FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX, 3) FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX, 0) FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX, 2) FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX, 4) FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX, 5) FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX, 6) FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX, 7) FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX, 8) FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10) FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11) FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX, 0) FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX, 4) FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11) FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20) FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26) FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27) FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29) FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX, 8) }; static inline void rte_cpu_get_features(uint32_t leaf, uint32_t subleaf, cpuid_registers_t out) { #if defined(__i386__) && defined(__PIC__) /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */ asm volatile("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0" : "=r" (out[RTE_REG_EBX]), "=a" (out[RTE_REG_EAX]), "=c" (out[RTE_REG_ECX]), "=d" (out[RTE_REG_EDX]) : "a" (leaf), "c" (subleaf)); #else asm volatile("cpuid" : "=a" (out[RTE_REG_EAX]), "=b" (out[RTE_REG_EBX]), "=c" (out[RTE_REG_ECX]), "=d" (out[RTE_REG_EDX]) : "a" (leaf), "c" (subleaf)); #endif } static inline int rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature) { const struct feature_entry *feat; cpuid_registers_t regs; if (feature >= RTE_CPUFLAG_NUMFLAGS) /* Flag does not match anything in the feature tables */ return -ENOENT; feat = &cpu_feature_table[feature]; if (!feat->leaf) /* This entry in the table wasn't filled out! */ return -EFAULT; rte_cpu_get_features(feat->leaf & 0xffff0000, 0, regs); if (((regs[RTE_REG_EAX] ^ feat->leaf) & 0xffff0000) || regs[RTE_REG_EAX] < feat->leaf) return 0; /* get the cpuid leaf containing the desired feature */ rte_cpu_get_features(feat->leaf, feat->subleaf, regs); /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) & 1; } #ifdef __cplusplus } #endif #endif /* _RTE_CPUFLAGS_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_cycles.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* BSD LICENSE * * Copyright(c) 2013 6WIND. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_cycles.h" #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT /* Global switch to use VMWARE mapping of TSC instead of RDTSC */ extern int rte_cycles_vmware_tsc_map; #include #endif static inline uint64_t rte_rdtsc(void) { union { uint64_t tsc_64; struct { uint32_t lo_32; uint32_t hi_32; }; } tsc; #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely(rte_cycles_vmware_tsc_map)) { /* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" : "=a" (tsc.lo_32), "=d" (tsc.hi_32) : "c"(0x10000)); return tsc.tsc_64; } #endif asm volatile("rdtsc" : "=a" (tsc.lo_32), "=d" (tsc.hi_32)); return tsc.tsc_64; } static inline uint64_t rte_rdtsc_precise(void) { rte_mb(); return rte_rdtsc(); } static inline uint64_t rte_get_tsc_cycles(void) { return rte_rdtsc(); } #ifdef __cplusplus } #endif #endif /* _RTE_CYCLES_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_memcpy.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMCPY_X86_64_H_ #define _RTE_MEMCPY_X86_64_H_ /** * @file * * Functions for SSE/AVX/AVX2 implementation of memcpy(). */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Copy bytes from one location to another. The locations must not overlap. * * @note This is implemented as a macro, so it's address should not be taken * and care is needed as parameter expressions may be evaluated multiple times. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. * @param n * Number of bytes to copy. * @return * Pointer to the destination data. */ static inline void * rte_memcpy(void *dst, const void *src, size_t n) __attribute__((always_inline)); #ifdef RTE_MACHINE_CPUFLAG_AVX2 /** * AVX2 implementation below */ /** * Copy 16 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov16(uint8_t *dst, const uint8_t *src) { __m128i xmm0; xmm0 = _mm_loadu_si128((const __m128i *)src); _mm_storeu_si128((__m128i *)dst, xmm0); } /** * Copy 32 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov32(uint8_t *dst, const uint8_t *src) { __m256i ymm0; ymm0 = _mm256_loadu_si256((const __m256i *)src); _mm256_storeu_si256((__m256i *)dst, ymm0); } /** * Copy 64 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov64(uint8_t *dst, const uint8_t *src) { rte_mov32((uint8_t *)dst + 0 * 32, (const uint8_t *)src + 0 * 32); rte_mov32((uint8_t *)dst + 1 * 32, (const uint8_t *)src + 1 * 32); } /** * Copy 128 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov128(uint8_t *dst, const uint8_t *src) { rte_mov32((uint8_t *)dst + 0 * 32, (const uint8_t *)src + 0 * 32); rte_mov32((uint8_t *)dst + 1 * 32, (const uint8_t *)src + 1 * 32); rte_mov32((uint8_t *)dst + 2 * 32, (const uint8_t *)src + 2 * 32); rte_mov32((uint8_t *)dst + 3 * 32, (const uint8_t *)src + 3 * 32); } /** * Copy 256 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov256(uint8_t *dst, const uint8_t *src) { rte_mov32((uint8_t *)dst + 0 * 32, (const uint8_t *)src + 0 * 32); rte_mov32((uint8_t *)dst + 1 * 32, (const uint8_t *)src + 1 * 32); rte_mov32((uint8_t *)dst + 2 * 32, (const uint8_t *)src + 2 * 32); rte_mov32((uint8_t *)dst + 3 * 32, (const uint8_t *)src + 3 * 32); rte_mov32((uint8_t *)dst + 4 * 32, (const uint8_t *)src + 4 * 32); rte_mov32((uint8_t *)dst + 5 * 32, (const uint8_t *)src + 5 * 32); rte_mov32((uint8_t *)dst + 6 * 32, (const uint8_t *)src + 6 * 32); rte_mov32((uint8_t *)dst + 7 * 32, (const uint8_t *)src + 7 * 32); } /** * Copy 64-byte blocks from one location to another, * locations should not overlap. */ static inline void rte_mov64blocks(uint8_t *dst, const uint8_t *src, size_t n) { __m256i ymm0, ymm1; while (n >= 64) { ymm0 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 0 * 32)); n -= 64; ymm1 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 1 * 32)); src = (const uint8_t *)src + 64; _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 0 * 32), ymm0); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 1 * 32), ymm1); dst = (uint8_t *)dst + 64; } } /** * Copy 256-byte blocks from one location to another, * locations should not overlap. */ static inline void rte_mov256blocks(uint8_t *dst, const uint8_t *src, size_t n) { __m256i ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7; while (n >= 256) { ymm0 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 0 * 32)); n -= 256; ymm1 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 1 * 32)); ymm2 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 2 * 32)); ymm3 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 3 * 32)); ymm4 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 4 * 32)); ymm5 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 5 * 32)); ymm6 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 6 * 32)); ymm7 = _mm256_loadu_si256((const __m256i *)((const uint8_t *)src + 7 * 32)); src = (const uint8_t *)src + 256; _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 0 * 32), ymm0); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 1 * 32), ymm1); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 2 * 32), ymm2); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 3 * 32), ymm3); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 4 * 32), ymm4); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 5 * 32), ymm5); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 6 * 32), ymm6); _mm256_storeu_si256((__m256i *)((uint8_t *)dst + 7 * 32), ymm7); dst = (uint8_t *)dst + 256; } } static inline void * rte_memcpy(void *dst, const void *src, size_t n) { uintptr_t dstu = (uintptr_t)dst; uintptr_t srcu = (uintptr_t)src; void *ret = dst; size_t dstofss; size_t bits; /** * Copy less than 16 bytes */ if (n < 16) { if (n & 0x01) { *(uint8_t *)dstu = *(const uint8_t *)srcu; srcu = (uintptr_t)((const uint8_t *)srcu + 1); dstu = (uintptr_t)((uint8_t *)dstu + 1); } if (n & 0x02) { *(uint16_t *)dstu = *(const uint16_t *)srcu; srcu = (uintptr_t)((const uint16_t *)srcu + 1); dstu = (uintptr_t)((uint16_t *)dstu + 1); } if (n & 0x04) { *(uint32_t *)dstu = *(const uint32_t *)srcu; srcu = (uintptr_t)((const uint32_t *)srcu + 1); dstu = (uintptr_t)((uint32_t *)dstu + 1); } if (n & 0x08) { *(uint64_t *)dstu = *(const uint64_t *)srcu; } return ret; } /** * Fast way when copy size doesn't exceed 512 bytes */ if (n <= 32) { rte_mov16((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n <= 64) { rte_mov32((uint8_t *)dst, (const uint8_t *)src); rte_mov32((uint8_t *)dst - 32 + n, (const uint8_t *)src - 32 + n); return ret; } if (n <= 512) { if (n >= 256) { n -= 256; rte_mov256((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 256; dst = (uint8_t *)dst + 256; } if (n >= 128) { n -= 128; rte_mov128((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 128; dst = (uint8_t *)dst + 128; } if (n >= 64) { n -= 64; rte_mov64((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 64; dst = (uint8_t *)dst + 64; } COPY_BLOCK_64_BACK31: if (n > 32) { rte_mov32((uint8_t *)dst, (const uint8_t *)src); rte_mov32((uint8_t *)dst - 32 + n, (const uint8_t *)src - 32 + n); return ret; } if (n > 0) { rte_mov32((uint8_t *)dst - 32 + n, (const uint8_t *)src - 32 + n); } return ret; } /** * Make store aligned when copy size exceeds 512 bytes */ dstofss = 32 - ((uintptr_t)dst & 0x1F); n -= dstofss; rte_mov32((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + dstofss; dst = (uint8_t *)dst + dstofss; /** * Copy 256-byte blocks. * Use copy block function for better instruction order control, * which is important when load is unaligned. */ rte_mov256blocks((uint8_t *)dst, (const uint8_t *)src, n); bits = n; n = n & 255; bits -= n; src = (const uint8_t *)src + bits; dst = (uint8_t *)dst + bits; /** * Copy 64-byte blocks. * Use copy block function for better instruction order control, * which is important when load is unaligned. */ if (n >= 64) { rte_mov64blocks((uint8_t *)dst, (const uint8_t *)src, n); bits = n; n = n & 63; bits -= n; src = (const uint8_t *)src + bits; dst = (uint8_t *)dst + bits; } /** * Copy whatever left */ goto COPY_BLOCK_64_BACK31; } #else /* RTE_MACHINE_CPUFLAG_AVX2 */ /** * SSE & AVX implementation below */ /** * Copy 16 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov16(uint8_t *dst, const uint8_t *src) { __m128i xmm0; xmm0 = _mm_loadu_si128((const __m128i *)(const __m128i *)src); _mm_storeu_si128((__m128i *)dst, xmm0); } /** * Copy 32 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov32(uint8_t *dst, const uint8_t *src) { rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16); rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16); } /** * Copy 64 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov64(uint8_t *dst, const uint8_t *src) { rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16); rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16); rte_mov16((uint8_t *)dst + 2 * 16, (const uint8_t *)src + 2 * 16); rte_mov16((uint8_t *)dst + 3 * 16, (const uint8_t *)src + 3 * 16); } /** * Copy 128 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov128(uint8_t *dst, const uint8_t *src) { rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16); rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16); rte_mov16((uint8_t *)dst + 2 * 16, (const uint8_t *)src + 2 * 16); rte_mov16((uint8_t *)dst + 3 * 16, (const uint8_t *)src + 3 * 16); rte_mov16((uint8_t *)dst + 4 * 16, (const uint8_t *)src + 4 * 16); rte_mov16((uint8_t *)dst + 5 * 16, (const uint8_t *)src + 5 * 16); rte_mov16((uint8_t *)dst + 6 * 16, (const uint8_t *)src + 6 * 16); rte_mov16((uint8_t *)dst + 7 * 16, (const uint8_t *)src + 7 * 16); } /** * Copy 256 bytes from one location to another, * locations should not overlap. */ static inline void rte_mov256(uint8_t *dst, const uint8_t *src) { rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16); rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16); rte_mov16((uint8_t *)dst + 2 * 16, (const uint8_t *)src + 2 * 16); rte_mov16((uint8_t *)dst + 3 * 16, (const uint8_t *)src + 3 * 16); rte_mov16((uint8_t *)dst + 4 * 16, (const uint8_t *)src + 4 * 16); rte_mov16((uint8_t *)dst + 5 * 16, (const uint8_t *)src + 5 * 16); rte_mov16((uint8_t *)dst + 6 * 16, (const uint8_t *)src + 6 * 16); rte_mov16((uint8_t *)dst + 7 * 16, (const uint8_t *)src + 7 * 16); rte_mov16((uint8_t *)dst + 8 * 16, (const uint8_t *)src + 8 * 16); rte_mov16((uint8_t *)dst + 9 * 16, (const uint8_t *)src + 9 * 16); rte_mov16((uint8_t *)dst + 10 * 16, (const uint8_t *)src + 10 * 16); rte_mov16((uint8_t *)dst + 11 * 16, (const uint8_t *)src + 11 * 16); rte_mov16((uint8_t *)dst + 12 * 16, (const uint8_t *)src + 12 * 16); rte_mov16((uint8_t *)dst + 13 * 16, (const uint8_t *)src + 13 * 16); rte_mov16((uint8_t *)dst + 14 * 16, (const uint8_t *)src + 14 * 16); rte_mov16((uint8_t *)dst + 15 * 16, (const uint8_t *)src + 15 * 16); } /** * Macro for copying unaligned block from one location to another with constant load offset, * 47 bytes leftover maximum, * locations should not overlap. * Requirements: * - Store is aligned * - Load offset is , which must be immediate value within [1, 15] * - For , make sure bit backwards & <16 - offset> bit forwards are available for loading * - , , must be variables * - __m128i ~ must be pre-defined */ #define MOVEUNALIGNED_LEFT47_IMM(dst, src, len, offset) \ ({ \ int tmp; \ while (len >= 128 + 16 - offset) { \ xmm0 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 0 * 16)); \ len -= 128; \ xmm1 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 1 * 16)); \ xmm2 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 2 * 16)); \ xmm3 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 3 * 16)); \ xmm4 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 4 * 16)); \ xmm5 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 5 * 16)); \ xmm6 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 6 * 16)); \ xmm7 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 7 * 16)); \ xmm8 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 8 * 16)); \ src = (const uint8_t *)src + 128; \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 0 * 16), _mm_alignr_epi8(xmm1, xmm0, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 1 * 16), _mm_alignr_epi8(xmm2, xmm1, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 2 * 16), _mm_alignr_epi8(xmm3, xmm2, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 3 * 16), _mm_alignr_epi8(xmm4, xmm3, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 4 * 16), _mm_alignr_epi8(xmm5, xmm4, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 5 * 16), _mm_alignr_epi8(xmm6, xmm5, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 6 * 16), _mm_alignr_epi8(xmm7, xmm6, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 7 * 16), _mm_alignr_epi8(xmm8, xmm7, offset)); \ dst = (uint8_t *)dst + 128; \ } \ tmp = len; \ len = ((len - 16 + offset) & 127) + 16 - offset; \ tmp -= len; \ src = (const uint8_t *)src + tmp; \ dst = (uint8_t *)dst + tmp; \ if (len >= 32 + 16 - offset) { \ while (len >= 32 + 16 - offset) { \ xmm0 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 0 * 16)); \ len -= 32; \ xmm1 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 1 * 16)); \ xmm2 = _mm_loadu_si128((const __m128i *)((const uint8_t *)src - offset + 2 * 16)); \ src = (const uint8_t *)src + 32; \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 0 * 16), _mm_alignr_epi8(xmm1, xmm0, offset)); \ _mm_storeu_si128((__m128i *)((uint8_t *)dst + 1 * 16), _mm_alignr_epi8(xmm2, xmm1, offset)); \ dst = (uint8_t *)dst + 32; \ } \ tmp = len; \ len = ((len - 16 + offset) & 31) + 16 - offset; \ tmp -= len; \ src = (const uint8_t *)src + tmp; \ dst = (uint8_t *)dst + tmp; \ } \ }) /** * Macro for copying unaligned block from one location to another, * 47 bytes leftover maximum, * locations should not overlap. * Use switch here because the aligning instruction requires immediate value for shift count. * Requirements: * - Store is aligned * - Load offset is , which must be within [1, 15] * - For , make sure bit backwards & <16 - offset> bit forwards are available for loading * - , , must be variables * - __m128i ~ used in MOVEUNALIGNED_LEFT47_IMM must be pre-defined */ #define MOVEUNALIGNED_LEFT47(dst, src, len, offset) \ ({ \ switch (offset) { \ case 0x01: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x01); break; \ case 0x02: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x02); break; \ case 0x03: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x03); break; \ case 0x04: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x04); break; \ case 0x05: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x05); break; \ case 0x06: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x06); break; \ case 0x07: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x07); break; \ case 0x08: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x08); break; \ case 0x09: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x09); break; \ case 0x0A: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0A); break; \ case 0x0B: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0B); break; \ case 0x0C: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0C); break; \ case 0x0D: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0D); break; \ case 0x0E: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0E); break; \ case 0x0F: MOVEUNALIGNED_LEFT47_IMM(dst, src, n, 0x0F); break; \ default:; \ } \ }) static inline void * rte_memcpy(void *dst, const void *src, size_t n) { __m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; uintptr_t dstu = (uintptr_t)dst; uintptr_t srcu = (uintptr_t)src; void *ret = dst; size_t dstofss; size_t srcofs; /** * Copy less than 16 bytes */ if (n < 16) { if (n & 0x01) { *(uint8_t *)dstu = *(const uint8_t *)srcu; srcu = (uintptr_t)((const uint8_t *)srcu + 1); dstu = (uintptr_t)((uint8_t *)dstu + 1); } if (n & 0x02) { *(uint16_t *)dstu = *(const uint16_t *)srcu; srcu = (uintptr_t)((const uint16_t *)srcu + 1); dstu = (uintptr_t)((uint16_t *)dstu + 1); } if (n & 0x04) { *(uint32_t *)dstu = *(const uint32_t *)srcu; srcu = (uintptr_t)((const uint32_t *)srcu + 1); dstu = (uintptr_t)((uint32_t *)dstu + 1); } if (n & 0x08) { *(uint64_t *)dstu = *(const uint64_t *)srcu; } return ret; } /** * Fast way when copy size doesn't exceed 512 bytes */ if (n <= 32) { rte_mov16((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n <= 48) { rte_mov32((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n <= 64) { rte_mov32((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst + 32, (const uint8_t *)src + 32); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n <= 128) { goto COPY_BLOCK_128_BACK15; } if (n <= 512) { if (n >= 256) { n -= 256; rte_mov128((uint8_t *)dst, (const uint8_t *)src); rte_mov128((uint8_t *)dst + 128, (const uint8_t *)src + 128); src = (const uint8_t *)src + 256; dst = (uint8_t *)dst + 256; } COPY_BLOCK_255_BACK15: if (n >= 128) { n -= 128; rte_mov128((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 128; dst = (uint8_t *)dst + 128; } COPY_BLOCK_128_BACK15: if (n >= 64) { n -= 64; rte_mov64((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 64; dst = (uint8_t *)dst + 64; } COPY_BLOCK_64_BACK15: if (n >= 32) { n -= 32; rte_mov32((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + 32; dst = (uint8_t *)dst + 32; } if (n > 16) { rte_mov16((uint8_t *)dst, (const uint8_t *)src); rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); return ret; } if (n > 0) { rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n); } return ret; } /** * Make store aligned when copy size exceeds 512 bytes, * and make sure the first 15 bytes are copied, because * unaligned copy functions require up to 15 bytes * backwards access. */ dstofss = 16 - ((uintptr_t)dst & 0x0F) + 16; n -= dstofss; rte_mov32((uint8_t *)dst, (const uint8_t *)src); src = (const uint8_t *)src + dstofss; dst = (uint8_t *)dst + dstofss; srcofs = ((uintptr_t)src & 0x0F); /** * For aligned copy */ if (srcofs == 0) { /** * Copy 256-byte blocks */ for (; n >= 256; n -= 256) { rte_mov256((uint8_t *)dst, (const uint8_t *)src); dst = (uint8_t *)dst + 256; src = (const uint8_t *)src + 256; } /** * Copy whatever left */ goto COPY_BLOCK_255_BACK15; } /** * For copy with unaligned load */ MOVEUNALIGNED_LEFT47(dst, src, n, srcofs); /** * Copy whatever left */ goto COPY_BLOCK_64_BACK15; } #endif /* RTE_MACHINE_CPUFLAG_AVX2 */ #ifdef __cplusplus } #endif #endif /* _RTE_MEMCPY_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_prefetch.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PREFETCH_X86_64_H_ #define _RTE_PREFETCH_X86_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_prefetch.h" static inline void rte_prefetch0(const volatile void *p) { asm volatile ("prefetcht0 %[p]" : : [p] "m" (*(const volatile char *)p)); } static inline void rte_prefetch1(const volatile void *p) { asm volatile ("prefetcht1 %[p]" : : [p] "m" (*(const volatile char *)p)); } static inline void rte_prefetch2(const volatile void *p) { asm volatile ("prefetcht2 %[p]" : : [p] "m" (*(const volatile char *)p)); } #ifdef __cplusplus } #endif #endif /* _RTE_PREFETCH_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_rtm.h ================================================ #ifndef _RTE_RTM_H_ #define _RTE_RTM_H_ 1 /* * Copyright (c) 2012,2013 Intel Corporation * Author: Andi Kleen * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */ #ifdef __cplusplus extern "C" { #endif #define RTE_XBEGIN_STARTED (~0u) #define RTE_XABORT_EXPLICIT (1 << 0) #define RTE_XABORT_RETRY (1 << 1) #define RTE_XABORT_CONFLICT (1 << 2) #define RTE_XABORT_CAPACITY (1 << 3) #define RTE_XABORT_DEBUG (1 << 4) #define RTE_XABORT_NESTED (1 << 5) #define RTE_XABORT_CODE(x) (((x) >> 24) & 0xff) static __attribute__((__always_inline__)) inline unsigned int rte_xbegin(void) { unsigned int ret = RTE_XBEGIN_STARTED; asm volatile(".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); return ret; } static __attribute__((__always_inline__)) inline void rte_xend(void) { asm volatile(".byte 0x0f,0x01,0xd5" ::: "memory"); } static __attribute__((__always_inline__)) inline void rte_xabort(const unsigned int status) { asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); } static __attribute__((__always_inline__)) inline int rte_xtest(void) { unsigned char out; asm volatile(".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory"); return out; } #ifdef __cplusplus } #endif #endif /* _RTE_RTM_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_rwlock.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_RWLOCK_X86_64_H_ #define _RTE_RWLOCK_X86_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_rwlock.h" #include "rte_spinlock.h" static inline void rte_rwlock_read_lock_tm(rte_rwlock_t *rwl) { if (likely(rte_try_tm(&rwl->cnt))) return; rte_rwlock_read_lock(rwl); } static inline void rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl) { if (unlikely(rwl->cnt)) rte_rwlock_read_unlock(rwl); else rte_xend(); } static inline void rte_rwlock_write_lock_tm(rte_rwlock_t *rwl) { if (likely(rte_try_tm(&rwl->cnt))) return; rte_rwlock_write_lock(rwl); } static inline void rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl) { if (unlikely(rwl->cnt)) rte_rwlock_write_unlock(rwl); else rte_xend(); } #ifdef __cplusplus } #endif #endif /* _RTE_RWLOCK_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_spinlock.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_SPINLOCK_X86_64_H_ #define _RTE_SPINLOCK_X86_64_H_ #ifdef __cplusplus extern "C" { #endif #include "generic/rte_spinlock.h" #include "rte_rtm.h" #include "rte_cpuflags.h" #include "rte_branch_prediction.h" #include "rte_common.h" #define RTE_RTM_MAX_RETRIES (10) #define RTE_XABORT_LOCK_BUSY (0xff) #ifndef RTE_FORCE_INTRINSICS static inline void rte_spinlock_lock(rte_spinlock_t *sl) { int lock_val = 1; asm volatile ( "1:\n" "xchg %[locked], %[lv]\n" "test %[lv], %[lv]\n" "jz 3f\n" "2:\n" "pause\n" "cmpl $0, %[locked]\n" "jnz 2b\n" "jmp 1b\n" "3:\n" : [locked] "=m" (sl->locked), [lv] "=q" (lock_val) : "[lv]" (lock_val) : "memory"); } static inline void rte_spinlock_unlock (rte_spinlock_t *sl) { int unlock_val = 0; asm volatile ( "xchg %[locked], %[ulv]\n" : [locked] "=m" (sl->locked), [ulv] "=q" (unlock_val) : "[ulv]" (unlock_val) : "memory"); } static inline int rte_spinlock_trylock (rte_spinlock_t *sl) { int lockval = 1; asm volatile ( "xchg %[locked], %[lockval]" : [locked] "=m" (sl->locked), [lockval] "=q" (lockval) : "[lockval]" (lockval) : "memory"); return (lockval == 0); } #endif static uint8_t rtm_supported; /* cache the flag to avoid the overhead of the rte_cpu_get_flag_enabled function */ static inline void __attribute__((constructor)) rte_rtm_init(void) { rtm_supported = rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM); } static inline int rte_tm_supported(void) { return rtm_supported; } static inline int rte_try_tm(volatile int *lock) { if (!rtm_supported) return 0; int retries = RTE_RTM_MAX_RETRIES; while (likely(retries--)) { unsigned int status = rte_xbegin(); if (likely(RTE_XBEGIN_STARTED == status)) { if (unlikely(*lock)) rte_xabort(RTE_XABORT_LOCK_BUSY); else return 1; } while (*lock) rte_pause(); if ((status & RTE_XABORT_EXPLICIT) && (RTE_XABORT_CODE(status) == RTE_XABORT_LOCK_BUSY)) continue; if ((status & RTE_XABORT_RETRY) == 0) /* do not retry */ break; } return 0; } static inline void rte_spinlock_lock_tm(rte_spinlock_t *sl) { if (likely(rte_try_tm(&sl->locked))) return; rte_spinlock_lock(sl); /* fall-back */ } static inline int rte_spinlock_trylock_tm(rte_spinlock_t *sl) { if (likely(rte_try_tm(&sl->locked))) return 1; return rte_spinlock_trylock(sl); } static inline void rte_spinlock_unlock_tm(rte_spinlock_t *sl) { if (unlikely(sl->locked)) rte_spinlock_unlock(sl); else rte_xend(); } static inline void rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr) { if (likely(rte_try_tm(&slr->sl.locked))) return; rte_spinlock_recursive_lock(slr); /* fall-back */ } static inline void rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr) { if (unlikely(slr->sl.locked)) rte_spinlock_recursive_unlock(slr); else rte_xend(); } static inline int rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr) { if (likely(rte_try_tm(&slr->sl.locked))) return 1; return rte_spinlock_recursive_trylock(slr); } #ifdef __cplusplus } #endif #endif /* _RTE_SPINLOCK_X86_64_H_ */ ================================================ FILE: lib/librte_eal/common/include/arch/x86/rte_vect.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_VECT_H_ #define _RTE_VECT_H_ /** * @file * * RTE SSE/AVX related header. */ #if (defined(__ICC) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) #ifdef __SSE__ #include #endif #ifdef __SSE2__ #include #endif #ifdef __SSE3__ #include #endif #if defined(__SSE4_2__) || defined(__SSE4_1__) #include #endif #if defined(__AVX__) #include #endif #else #include #endif #ifdef __cplusplus extern "C" { #endif typedef __m128i xmm_t; #define XMM_SIZE (sizeof(xmm_t)) #define XMM_MASK (XMM_SIZE - 1) typedef union rte_xmm { xmm_t x; uint8_t u8[XMM_SIZE / sizeof(uint8_t)]; uint16_t u16[XMM_SIZE / sizeof(uint16_t)]; uint32_t u32[XMM_SIZE / sizeof(uint32_t)]; uint64_t u64[XMM_SIZE / sizeof(uint64_t)]; double pd[XMM_SIZE / sizeof(double)]; } rte_xmm_t; #ifdef __AVX__ typedef __m256i ymm_t; #define YMM_SIZE (sizeof(ymm_t)) #define YMM_MASK (YMM_SIZE - 1) typedef union rte_ymm { ymm_t y; xmm_t x[YMM_SIZE / sizeof(xmm_t)]; uint8_t u8[YMM_SIZE / sizeof(uint8_t)]; uint16_t u16[YMM_SIZE / sizeof(uint16_t)]; uint32_t u32[YMM_SIZE / sizeof(uint32_t)]; uint64_t u64[YMM_SIZE / sizeof(uint64_t)]; double pd[YMM_SIZE / sizeof(double)]; } rte_ymm_t; #endif /* __AVX__ */ #ifdef RTE_ARCH_I686 #define _mm_cvtsi128_si64(a) ({ \ rte_xmm_t m; \ m.x = (a); \ (m.u64[0]); \ }) #endif /* * Prior to version 12.1 icc doesn't support _mm_set_epi64x. */ #if (defined(__ICC) && __ICC < 1210) #define _mm_set_epi64x(a, b) ({ \ rte_xmm_t m; \ m.u64[0] = b; \ m.u64[1] = a; \ (m.x); \ }) #endif /* (defined(__ICC) && __ICC < 1210) */ #ifdef __cplusplus } #endif #endif /* _RTE_VECT_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_atomic.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ATOMIC_H_ #define _RTE_ATOMIC_H_ /** * @file * Atomic Operations * * This file defines a generic API for atomic operations. */ #include #ifdef __DOXYGEN__ /** * General memory barrier. * * Guarantees that the LOAD and STORE operations generated before the * barrier occur before the LOAD and STORE operations generated after. * This function is architecture dependent. */ static inline void rte_mb(void); /** * Write memory barrier. * * Guarantees that the STORE operations generated before the barrier * occur before the STORE operations generated after. * This function is architecture dependent. */ static inline void rte_wmb(void); /** * Read memory barrier. * * Guarantees that the LOAD operations generated before the barrier * occur before the LOAD operations generated after. * This function is architecture dependent. */ static inline void rte_rmb(void); #endif /* __DOXYGEN__ */ /** * Compiler barrier. * * Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ #define rte_compiler_barrier() do { \ asm volatile ("" : : : "memory"); \ } while(0) /*------------------------- 16 bit atomic operations -------------------------*/ /** * Atomic compare and set. * * (atomic) equivalent to: * if (*dst == exp) * *dst = src (all 16-bit words) * * @param dst * The destination location into which the value will be written. * @param exp * The expected value. * @param src * The new value. * @return * Non-zero on success; 0 on failure. */ static inline int rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src) { return __sync_bool_compare_and_swap(dst, exp, src); } #endif /** * The atomic counter structure. */ typedef struct { volatile int16_t cnt; /**< An internal counter value. */ } rte_atomic16_t; /** * Static initializer for an atomic counter. */ #define RTE_ATOMIC16_INIT(val) { (val) } /** * Initialize an atomic counter. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic16_init(rte_atomic16_t *v) { v->cnt = 0; } /** * Atomically read a 16-bit value from a counter. * * @param v * A pointer to the atomic counter. * @return * The value of the counter. */ static inline int16_t rte_atomic16_read(const rte_atomic16_t *v) { return v->cnt; } /** * Atomically set a counter to a 16-bit value. * * @param v * A pointer to the atomic counter. * @param new_value * The new value for the counter. */ static inline void rte_atomic16_set(rte_atomic16_t *v, int16_t new_value) { v->cnt = new_value; } /** * Atomically add a 16-bit value to an atomic counter. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. */ static inline void rte_atomic16_add(rte_atomic16_t *v, int16_t inc) { __sync_fetch_and_add(&v->cnt, inc); } /** * Atomically subtract a 16-bit value from an atomic counter. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. */ static inline void rte_atomic16_sub(rte_atomic16_t *v, int16_t dec) { __sync_fetch_and_sub(&v->cnt, dec); } /** * Atomically increment a counter by one. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic16_inc(rte_atomic16_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic16_inc(rte_atomic16_t *v) { rte_atomic16_add(v, 1); } #endif /** * Atomically decrement a counter by one. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic16_dec(rte_atomic16_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic16_dec(rte_atomic16_t *v) { rte_atomic16_sub(v, 1); } #endif /** * Atomically add a 16-bit value to a counter and return the result. * * Atomically adds the 16-bits value (inc) to the atomic counter (v) and * returns the value of v after addition. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. * @return * The value of v after the addition. */ static inline int16_t rte_atomic16_add_return(rte_atomic16_t *v, int16_t inc) { return __sync_add_and_fetch(&v->cnt, inc); } /** * Atomically subtract a 16-bit value from a counter and return * the result. * * Atomically subtracts the 16-bit value (inc) from the atomic counter * (v) and returns the value of v after the subtraction. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. * @return * The value of v after the subtraction. */ static inline int16_t rte_atomic16_sub_return(rte_atomic16_t *v, int16_t dec) { return __sync_sub_and_fetch(&v->cnt, dec); } /** * Atomically increment a 16-bit counter by one and test. * * Atomically increments the atomic counter (v) by one and returns true if * the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after the increment operation is 0; false otherwise. */ static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v) { return (__sync_add_and_fetch(&v->cnt, 1) == 0); } #endif /** * Atomically decrement a 16-bit counter by one and test. * * Atomically decrements the atomic counter (v) by one and returns true if * the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after the decrement operation is 0; false otherwise. */ static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v) { return (__sync_sub_and_fetch(&v->cnt, 1) == 0); } #endif /** * Atomically test and set a 16-bit atomic counter. * * If the counter value is already set, return 0 (failed). Otherwise, set * the counter value to 1 and return 1 (success). * * @param v * A pointer to the atomic counter. * @return * 0 if failed; else 1, success. */ static inline int rte_atomic16_test_and_set(rte_atomic16_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic16_test_and_set(rte_atomic16_t *v) { return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1); } #endif /** * Atomically set a 16-bit counter to 0. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic16_clear(rte_atomic16_t *v) { v->cnt = 0; } /*------------------------- 32 bit atomic operations -------------------------*/ /** * Atomic compare and set. * * (atomic) equivalent to: * if (*dst == exp) * *dst = src (all 32-bit words) * * @param dst * The destination location into which the value will be written. * @param exp * The expected value. * @param src * The new value. * @return * Non-zero on success; 0 on failure. */ static inline int rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src) { return __sync_bool_compare_and_swap(dst, exp, src); } #endif /** * The atomic counter structure. */ typedef struct { volatile int32_t cnt; /**< An internal counter value. */ } rte_atomic32_t; /** * Static initializer for an atomic counter. */ #define RTE_ATOMIC32_INIT(val) { (val) } /** * Initialize an atomic counter. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic32_init(rte_atomic32_t *v) { v->cnt = 0; } /** * Atomically read a 32-bit value from a counter. * * @param v * A pointer to the atomic counter. * @return * The value of the counter. */ static inline int32_t rte_atomic32_read(const rte_atomic32_t *v) { return v->cnt; } /** * Atomically set a counter to a 32-bit value. * * @param v * A pointer to the atomic counter. * @param new_value * The new value for the counter. */ static inline void rte_atomic32_set(rte_atomic32_t *v, int32_t new_value) { v->cnt = new_value; } /** * Atomically add a 32-bit value to an atomic counter. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. */ static inline void rte_atomic32_add(rte_atomic32_t *v, int32_t inc) { __sync_fetch_and_add(&v->cnt, inc); } /** * Atomically subtract a 32-bit value from an atomic counter. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. */ static inline void rte_atomic32_sub(rte_atomic32_t *v, int32_t dec) { __sync_fetch_and_sub(&v->cnt, dec); } /** * Atomically increment a counter by one. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic32_inc(rte_atomic32_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic32_inc(rte_atomic32_t *v) { rte_atomic32_add(v, 1); } #endif /** * Atomically decrement a counter by one. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic32_dec(rte_atomic32_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic32_dec(rte_atomic32_t *v) { rte_atomic32_sub(v,1); } #endif /** * Atomically add a 32-bit value to a counter and return the result. * * Atomically adds the 32-bits value (inc) to the atomic counter (v) and * returns the value of v after addition. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. * @return * The value of v after the addition. */ static inline int32_t rte_atomic32_add_return(rte_atomic32_t *v, int32_t inc) { return __sync_add_and_fetch(&v->cnt, inc); } /** * Atomically subtract a 32-bit value from a counter and return * the result. * * Atomically subtracts the 32-bit value (inc) from the atomic counter * (v) and returns the value of v after the subtraction. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. * @return * The value of v after the subtraction. */ static inline int32_t rte_atomic32_sub_return(rte_atomic32_t *v, int32_t dec) { return __sync_sub_and_fetch(&v->cnt, dec); } /** * Atomically increment a 32-bit counter by one and test. * * Atomically increments the atomic counter (v) by one and returns true if * the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after the increment operation is 0; false otherwise. */ static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v) { return (__sync_add_and_fetch(&v->cnt, 1) == 0); } #endif /** * Atomically decrement a 32-bit counter by one and test. * * Atomically decrements the atomic counter (v) by one and returns true if * the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after the decrement operation is 0; false otherwise. */ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v) { return (__sync_sub_and_fetch(&v->cnt, 1) == 0); } #endif /** * Atomically test and set a 32-bit atomic counter. * * If the counter value is already set, return 0 (failed). Otherwise, set * the counter value to 1 and return 1 (success). * * @param v * A pointer to the atomic counter. * @return * 0 if failed; else 1, success. */ static inline int rte_atomic32_test_and_set(rte_atomic32_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic32_test_and_set(rte_atomic32_t *v) { return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1); } #endif /** * Atomically set a 32-bit counter to 0. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic32_clear(rte_atomic32_t *v) { v->cnt = 0; } /*------------------------- 64 bit atomic operations -------------------------*/ /** * An atomic compare and set function used by the mutex functions. * (atomic) equivalent to: * if (*dst == exp) * *dst = src (all 64-bit words) * * @param dst * The destination into which the value will be written. * @param exp * The expected value. * @param src * The new value. * @return * Non-zero on success; 0 on failure. */ static inline int rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src) { return __sync_bool_compare_and_swap(dst, exp, src); } #endif /** * The atomic counter structure. */ typedef struct { volatile int64_t cnt; /**< Internal counter value. */ } rte_atomic64_t; /** * Static initializer for an atomic counter. */ #define RTE_ATOMIC64_INIT(val) { (val) } /** * Initialize the atomic counter. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic64_init(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_init(rte_atomic64_t *v) { #ifdef __LP64__ v->cnt = 0; #else int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, 0); } #endif } #endif /** * Atomically read a 64-bit counter. * * @param v * A pointer to the atomic counter. * @return * The value of the counter. */ static inline int64_t rte_atomic64_read(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int64_t rte_atomic64_read(rte_atomic64_t *v) { #ifdef __LP64__ return v->cnt; #else int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; /* replace the value by itself */ success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, tmp); } return tmp; #endif } #endif /** * Atomically set a 64-bit counter. * * @param v * A pointer to the atomic counter. * @param new_value * The new value of the counter. */ static inline void rte_atomic64_set(rte_atomic64_t *v, int64_t new_value); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_set(rte_atomic64_t *v, int64_t new_value) { #ifdef __LP64__ v->cnt = new_value; #else int success = 0; uint64_t tmp; while (success == 0) { tmp = v->cnt; success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, tmp, new_value); } #endif } #endif /** * Atomically add a 64-bit value to a counter. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. */ static inline void rte_atomic64_add(rte_atomic64_t *v, int64_t inc); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_add(rte_atomic64_t *v, int64_t inc) { __sync_fetch_and_add(&v->cnt, inc); } #endif /** * Atomically subtract a 64-bit value from a counter. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. */ static inline void rte_atomic64_sub(rte_atomic64_t *v, int64_t dec); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_sub(rte_atomic64_t *v, int64_t dec) { __sync_fetch_and_sub(&v->cnt, dec); } #endif /** * Atomically increment a 64-bit counter by one and test. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic64_inc(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_inc(rte_atomic64_t *v) { rte_atomic64_add(v, 1); } #endif /** * Atomically decrement a 64-bit counter by one and test. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic64_dec(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_dec(rte_atomic64_t *v) { rte_atomic64_sub(v, 1); } #endif /** * Add a 64-bit value to an atomic counter and return the result. * * Atomically adds the 64-bit value (inc) to the atomic counter (v) and * returns the value of v after the addition. * * @param v * A pointer to the atomic counter. * @param inc * The value to be added to the counter. * @return * The value of v after the addition. */ static inline int64_t rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc); #ifdef RTE_FORCE_INTRINSICS static inline int64_t rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc) { return __sync_add_and_fetch(&v->cnt, inc); } #endif /** * Subtract a 64-bit value from an atomic counter and return the result. * * Atomically subtracts the 64-bit value (dec) from the atomic counter (v) * and returns the value of v after the subtraction. * * @param v * A pointer to the atomic counter. * @param dec * The value to be subtracted from the counter. * @return * The value of v after the subtraction. */ static inline int64_t rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec); #ifdef RTE_FORCE_INTRINSICS static inline int64_t rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec) { return __sync_sub_and_fetch(&v->cnt, dec); } #endif /** * Atomically increment a 64-bit counter by one and test. * * Atomically increments the atomic counter (v) by one and returns * true if the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after the addition is 0; false otherwise. */ static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v) { return rte_atomic64_add_return(v, 1) == 0; } #endif /** * Atomically decrement a 64-bit counter by one and test. * * Atomically decrements the atomic counter (v) by one and returns true if * the result is 0, or false in all other cases. * * @param v * A pointer to the atomic counter. * @return * True if the result after subtraction is 0; false otherwise. */ static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v) { return rte_atomic64_sub_return(v, 1) == 0; } #endif /** * Atomically test and set a 64-bit atomic counter. * * If the counter value is already set, return 0 (failed). Otherwise, set * the counter value to 1 and return 1 (success). * * @param v * A pointer to the atomic counter. * @return * 0 if failed; else 1, success. */ static inline int rte_atomic64_test_and_set(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline int rte_atomic64_test_and_set(rte_atomic64_t *v) { return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1); } #endif /** * Atomically set a 64-bit counter to 0. * * @param v * A pointer to the atomic counter. */ static inline void rte_atomic64_clear(rte_atomic64_t *v); #ifdef RTE_FORCE_INTRINSICS static inline void rte_atomic64_clear(rte_atomic64_t *v) { rte_atomic64_set(v, 0); } #endif #endif /* _RTE_ATOMIC_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_byteorder.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_BYTEORDER_H_ #define _RTE_BYTEORDER_H_ /** * @file * * Byte Swap Operations * * This file defines a generic API for byte swap operations. Part of * the implementation is architecture-specific. */ #include #ifdef RTE_EXEC_ENV_BSDAPP #include #else #include #endif /* * Compile-time endianness detection */ #define RTE_BIG_ENDIAN 1 #define RTE_LITTLE_ENDIAN 2 #if defined __BYTE_ORDER__ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define RTE_BYTE_ORDER RTE_BIG_ENDIAN #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN #endif /* __BYTE_ORDER__ */ #elif defined __BYTE_ORDER #if __BYTE_ORDER == __BIG_ENDIAN #define RTE_BYTE_ORDER RTE_BIG_ENDIAN #elif __BYTE_ORDER == __LITTLE_ENDIAN #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN #endif /* __BYTE_ORDER */ #elif defined __BIG_ENDIAN__ #define RTE_BYTE_ORDER RTE_BIG_ENDIAN #elif defined __LITTLE_ENDIAN__ #define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN #endif /* * An internal function to swap bytes in a 16-bit value. * * It is used by rte_bswap16() when the value is constant. Do not use * this function directly; rte_bswap16() is preferred. */ static inline uint16_t rte_constant_bswap16(uint16_t x) { return (uint16_t)(((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8)); } /* * An internal function to swap bytes in a 32-bit value. * * It is used by rte_bswap32() when the value is constant. Do not use * this function directly; rte_bswap32() is preferred. */ static inline uint32_t rte_constant_bswap32(uint32_t x) { return ((x & 0x000000ffUL) << 24) | ((x & 0x0000ff00UL) << 8) | ((x & 0x00ff0000UL) >> 8) | ((x & 0xff000000UL) >> 24); } /* * An internal function to swap bytes of a 64-bit value. * * It is used by rte_bswap64() when the value is constant. Do not use * this function directly; rte_bswap64() is preferred. */ static inline uint64_t rte_constant_bswap64(uint64_t x) { return ((x & 0x00000000000000ffULL) << 56) | ((x & 0x000000000000ff00ULL) << 40) | ((x & 0x0000000000ff0000ULL) << 24) | ((x & 0x00000000ff000000ULL) << 8) | ((x & 0x000000ff00000000ULL) >> 8) | ((x & 0x0000ff0000000000ULL) >> 24) | ((x & 0x00ff000000000000ULL) >> 40) | ((x & 0xff00000000000000ULL) >> 56); } #ifdef __DOXYGEN__ /** * Swap bytes in a 16-bit value. */ static uint16_t rte_bswap16(uint16_t _x); /** * Swap bytes in a 32-bit value. */ static uint32_t rte_bswap32(uint32_t x); /** * Swap bytes in a 64-bit value. */ static uint64_t rte_bswap64(uint64_t x); /** * Convert a 16-bit value from CPU order to little endian. */ static uint16_t rte_cpu_to_le_16(uint16_t x); /** * Convert a 32-bit value from CPU order to little endian. */ static uint32_t rte_cpu_to_le_32(uint32_t x); /** * Convert a 64-bit value from CPU order to little endian. */ static uint64_t rte_cpu_to_le_64(uint64_t x); /** * Convert a 16-bit value from CPU order to big endian. */ static uint16_t rte_cpu_to_be_16(uint16_t x); /** * Convert a 32-bit value from CPU order to big endian. */ static uint32_t rte_cpu_to_be_32(uint32_t x); /** * Convert a 64-bit value from CPU order to big endian. */ static uint64_t rte_cpu_to_be_64(uint64_t x); /** * Convert a 16-bit value from little endian to CPU order. */ static uint16_t rte_le_to_cpu_16(uint16_t x); /** * Convert a 32-bit value from little endian to CPU order. */ static uint32_t rte_le_to_cpu_32(uint32_t x); /** * Convert a 64-bit value from little endian to CPU order. */ static uint64_t rte_le_to_cpu_64(uint64_t x); /** * Convert a 16-bit value from big endian to CPU order. */ static uint16_t rte_be_to_cpu_16(uint16_t x); /** * Convert a 32-bit value from big endian to CPU order. */ static uint32_t rte_be_to_cpu_32(uint32_t x); /** * Convert a 64-bit value from big endian to CPU order. */ static uint64_t rte_be_to_cpu_64(uint64_t x); #endif /* __DOXYGEN__ */ #ifdef RTE_FORCE_INTRINSICS #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) #define rte_bswap16(x) __builtin_bswap16(x) #endif #define rte_bswap32(x) __builtin_bswap32(x) #define rte_bswap64(x) __builtin_bswap64(x) #endif #endif /* _RTE_BYTEORDER_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_cpuflags.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CPUFLAGS_H_ #define _RTE_CPUFLAGS_H_ /** * @file * Architecture specific API to determine available CPU features at runtime. */ #include #include #include #include #ifdef __cplusplus #define __RTE_CPUFLAG_UNDERLYING_TYPE : unsigned int #define __RTE_REGISTER_UNDERLYING_TYPE : unsigned int #else #define __RTE_CPUFLAG_UNDERLYING_TYPE #define __RTE_REGISTER_UNDERLYING_TYPE #endif /** * Enumeration of all CPU features supported */ enum rte_cpu_flag_t __RTE_CPUFLAG_UNDERLYING_TYPE; /** * Enumeration of CPU registers */ enum cpu_register_t __RTE_REGISTER_UNDERLYING_TYPE; typedef uint32_t cpuid_registers_t[4]; #define CPU_FLAG_NAME_MAX_LEN 64 /** * Struct to hold a processor feature entry */ struct feature_entry { uint32_t leaf; /**< cpuid leaf */ uint32_t subleaf; /**< cpuid subleaf */ uint32_t reg; /**< cpuid register */ uint32_t bit; /**< cpuid register bit */ char name[CPU_FLAG_NAME_MAX_LEN]; /**< String for printing */ }; #define FEAT_DEF(name, leaf, subleaf, reg, bit) \ [RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name }, /** * An array that holds feature entries * * Defined in arch-specific rte_cpuflags.h. */ #ifdef __DOXYGEN__ static const struct feature_entry cpu_feature_table[]; #endif /** * Execute CPUID instruction and get contents of a specific register * * This function, when compiled with GCC, will generate architecture-neutral * code, as per GCC manual. */ static inline void rte_cpu_get_features(uint32_t leaf, uint32_t subleaf, cpuid_registers_t out); /** * Function for checking a CPU flag availability * * @param feature * CPU flag to query CPU for * @return * 1 if flag is available * 0 if flag is not available * -ENOENT if flag is invalid */ static inline int rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature); /** * This function checks that the currently used CPU supports the CPU features * that were specified at compile time. It is called automatically within the * EAL, so does not need to be used by applications. */ void rte_cpu_check_supported(void); #endif /* _RTE_CPUFLAGS_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_cycles.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* BSD LICENSE * * Copyright(c) 2013 6WIND. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_CYCLES_H_ #define _RTE_CYCLES_H_ /** * @file * * Simple Time Reference Functions (Cycles and HPET). */ #include #include #include #define MS_PER_S 1000 #define US_PER_S 1000000 #define NS_PER_S 1000000000 enum timer_source { EAL_TIMER_TSC = 0, EAL_TIMER_HPET }; extern enum timer_source eal_timer_source; /** * Get the measured frequency of the RDTSC counter * * @return * The TSC frequency for this lcore */ uint64_t rte_get_tsc_hz(void); /** * Return the number of TSC cycles since boot * * @return * the number of cycles */ static inline uint64_t rte_get_tsc_cycles(void); #ifdef RTE_LIBEAL_USE_HPET /** * Return the number of HPET cycles since boot * * This counter is global for all execution units. The number of * cycles in one second can be retrieved using rte_get_hpet_hz(). * * @return * the number of cycles */ uint64_t rte_get_hpet_cycles(void); /** * Get the number of HPET cycles in one second. * * @return * The number of cycles in one second. */ uint64_t rte_get_hpet_hz(void); /** * Initialise the HPET for use. This must be called before the rte_get_hpet_hz * and rte_get_hpet_cycles APIs are called. If this function does not succeed, * then the HPET functions are unavailable and should not be called. * * @param make_default * If set, the hpet timer becomes the default timer whose values are * returned by the rte_get_timer_hz/cycles API calls * * @return * 0 on success, * -1 on error, and the make_default parameter is ignored. */ int rte_eal_hpet_init(int make_default); #endif /** * Get the number of cycles since boot from the default timer. * * @return * The number of cycles */ static inline uint64_t rte_get_timer_cycles(void) { switch(eal_timer_source) { case EAL_TIMER_TSC: return rte_get_tsc_cycles(); case EAL_TIMER_HPET: #ifdef RTE_LIBEAL_USE_HPET return rte_get_hpet_cycles(); #endif default: rte_panic("Invalid timer source specified\n"); } } /** * Get the number of cycles in one second for the default timer. * * @return * The number of cycles in one second. */ static inline uint64_t rte_get_timer_hz(void) { switch(eal_timer_source) { case EAL_TIMER_TSC: return rte_get_tsc_hz(); case EAL_TIMER_HPET: #ifdef RTE_LIBEAL_USE_HPET return rte_get_hpet_hz(); #endif default: rte_panic("Invalid timer source specified\n"); } } /** * Wait at least us microseconds. * * @param us * The number of microseconds to wait. */ void rte_delay_us(unsigned us); /** * Wait at least ms milliseconds. * * @param ms * The number of milliseconds to wait. */ static inline void rte_delay_ms(unsigned ms) { rte_delay_us(ms * 1000); } #endif /* _RTE_CYCLES_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_memcpy.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMCPY_H_ #define _RTE_MEMCPY_H_ /** * @file * * Functions for vectorised implementation of memcpy(). */ /** * Copy 16 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov16(uint8_t *dst, const uint8_t *src); /** * Copy 32 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov32(uint8_t *dst, const uint8_t *src); /** * Copy 48 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov48(uint8_t *dst, const uint8_t *src); /** * Copy 64 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov64(uint8_t *dst, const uint8_t *src); /** * Copy 128 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov128(uint8_t *dst, const uint8_t *src); /** * Copy 256 bytes from one location to another using optimised * instructions. The locations should not overlap. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. */ static inline void rte_mov256(uint8_t *dst, const uint8_t *src); #ifdef __DOXYGEN__ /** * Copy bytes from one location to another. The locations must not overlap. * * @note This is implemented as a macro, so it's address should not be taken * and care is needed as parameter expressions may be evaluated multiple times. * * @param dst * Pointer to the destination of the data. * @param src * Pointer to the source data. * @param n * Number of bytes to copy. * @return * Pointer to the destination data. */ static void * rte_memcpy(void *dst, const void *src, size_t n); #endif /* __DOXYGEN__ */ /* * memcpy() function used by rte_memcpy macro */ static inline void * rte_memcpy_func(void *dst, const void *src, size_t n) __attribute__((always_inline)); #endif /* _RTE_MEMCPY_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_prefetch.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PREFETCH_H_ #define _RTE_PREFETCH_H_ /** * @file * * Prefetch operations. * * This file defines an API for prefetch macros / inline-functions, * which are architecture-dependent. Prefetching occurs when a * processor requests an instruction or data from memory to cache * before it is actually needed, potentially speeding up the execution of the * program. */ /** * Prefetch a cache line into all cache levels. * @param p * Address to prefetch */ static inline void rte_prefetch0(const volatile void *p); /** * Prefetch a cache line into all cache levels except the 0th cache level. * @param p * Address to prefetch */ static inline void rte_prefetch1(const volatile void *p); /** * Prefetch a cache line into all cache levels except the 0th and 1th cache * levels. * @param p * Address to prefetch */ static inline void rte_prefetch2(const volatile void *p); #endif /* _RTE_PREFETCH_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_rwlock.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_RWLOCK_H_ #define _RTE_RWLOCK_H_ /** * @file * * RTE Read-Write Locks * * This file defines an API for read-write locks. The lock is used to * protect data that allows multiple readers in parallel, but only * one writer. All readers are blocked until the writer is finished * writing. * */ #ifdef __cplusplus extern "C" { #endif #include #include /** * The rte_rwlock_t type. * * cnt is -1 when write lock is held, and > 0 when read locks are held. */ typedef struct { volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */ } rte_rwlock_t; /** * A static rwlock initializer. */ #define RTE_RWLOCK_INITIALIZER { 0 } /** * Initialize the rwlock to an unlocked state. * * @param rwl * A pointer to the rwlock structure. */ static inline void rte_rwlock_init(rte_rwlock_t *rwl) { rwl->cnt = 0; } /** * Take a read lock. Loop until the lock is held. * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_read_lock(rte_rwlock_t *rwl) { int32_t x; int success = 0; while (success == 0) { x = rwl->cnt; /* write lock is held */ if (x < 0) { rte_pause(); continue; } success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, x, x + 1); } } /** * Release a read lock. * * @param rwl * A pointer to the rwlock structure. */ static inline void rte_rwlock_read_unlock(rte_rwlock_t *rwl) { rte_atomic32_dec((rte_atomic32_t *)(intptr_t)&rwl->cnt); } /** * Take a write lock. Loop until the lock is held. * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_write_lock(rte_rwlock_t *rwl) { int32_t x; int success = 0; while (success == 0) { x = rwl->cnt; /* a lock is held */ if (x != 0) { rte_pause(); continue; } success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt, 0, -1); } } /** * Release a write lock. * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_write_unlock(rte_rwlock_t *rwl) { rte_atomic32_inc((rte_atomic32_t *)(intptr_t)&rwl->cnt); } /** * Try to execute critical section in a hardware memory transaction, if it * fails or not available take a read lock * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_read_lock_tm(rte_rwlock_t *rwl); /** * Commit hardware memory transaction or release the read lock if the lock is used as a fall-back * * @param rwl * A pointer to the rwlock structure. */ static inline void rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl); /** * Try to execute critical section in a hardware memory transaction, if it * fails or not available take a write lock * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_write_lock_tm(rte_rwlock_t *rwl); /** * Commit hardware memory transaction or release the write lock if the lock is used as a fall-back * * @param rwl * A pointer to a rwlock structure. */ static inline void rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl); #ifdef __cplusplus } #endif #endif /* _RTE_RWLOCK_H_ */ ================================================ FILE: lib/librte_eal/common/include/generic/rte_spinlock.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_SPINLOCK_H_ #define _RTE_SPINLOCK_H_ /** * @file * * RTE Spinlocks * * This file defines an API for read-write locks, which are implemented * in an architecture-specific way. This kind of lock simply waits in * a loop repeatedly checking until the lock becomes available. * * All locks must be initialised before use, and only initialised once. * */ #include #ifdef RTE_FORCE_INTRINSICS #include #endif /** * The rte_spinlock_t type. */ typedef struct { volatile int locked; /**< lock status 0 = unlocked, 1 = locked */ } rte_spinlock_t; /** * A static spinlock initializer. */ #define RTE_SPINLOCK_INITIALIZER { 0 } /** * Initialize the spinlock to an unlocked state. * * @param sl * A pointer to the spinlock. */ static inline void rte_spinlock_init(rte_spinlock_t *sl) { sl->locked = 0; } /** * Take the spinlock. * * @param sl * A pointer to the spinlock. */ static inline void rte_spinlock_lock(rte_spinlock_t *sl); #ifdef RTE_FORCE_INTRINSICS static inline void rte_spinlock_lock(rte_spinlock_t *sl) { while (__sync_lock_test_and_set(&sl->locked, 1)) while(sl->locked) rte_pause(); } #endif /** * Release the spinlock. * * @param sl * A pointer to the spinlock. */ static inline void rte_spinlock_unlock (rte_spinlock_t *sl); #ifdef RTE_FORCE_INTRINSICS static inline void rte_spinlock_unlock (rte_spinlock_t *sl) { __sync_lock_release(&sl->locked); } #endif /** * Try to take the lock. * * @param sl * A pointer to the spinlock. * @return * 1 if the lock is successfully taken; 0 otherwise. */ static inline int rte_spinlock_trylock (rte_spinlock_t *sl); #ifdef RTE_FORCE_INTRINSICS static inline int rte_spinlock_trylock (rte_spinlock_t *sl) { return (__sync_lock_test_and_set(&sl->locked,1) == 0); } #endif /** * Test if the lock is taken. * * @param sl * A pointer to the spinlock. * @return * 1 if the lock is currently taken; 0 otherwise. */ static inline int rte_spinlock_is_locked (rte_spinlock_t *sl) { return sl->locked; } /** * Test if hardware transactional memory (lock elision) is supported * * @return * 1 if the hardware transactional memory is supported; 0 otherwise. */ static inline int rte_tm_supported(void); /** * Try to execute critical section in a hardware memory transaction, * if it fails or not available take the spinlock. * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param sl * A pointer to the spinlock. */ static inline void rte_spinlock_lock_tm(rte_spinlock_t *sl); /** * Commit hardware memory transaction or release the spinlock if * the spinlock is used as a fall-back * * @param sl * A pointer to the spinlock. */ static inline void rte_spinlock_unlock_tm(rte_spinlock_t *sl); /** * Try to execute critical section in a hardware memory transaction, * if it fails or not available try to take the lock. * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param sl * A pointer to the spinlock. * @return * 1 if the hardware memory transaction is successfully started * or lock is successfully taken; 0 otherwise. */ static inline int rte_spinlock_trylock_tm(rte_spinlock_t *sl); /** * The rte_spinlock_recursive_t type. */ typedef struct { rte_spinlock_t sl; /**< the actual spinlock */ volatile int user; /**< core id using lock, -1 for unused */ volatile int count; /**< count of time this lock has been called */ } rte_spinlock_recursive_t; /** * A static recursive spinlock initializer. */ #define RTE_SPINLOCK_RECURSIVE_INITIALIZER {RTE_SPINLOCK_INITIALIZER, -1, 0} /** * Initialize the recursive spinlock to an unlocked state. * * @param slr * A pointer to the recursive spinlock. */ static inline void rte_spinlock_recursive_init(rte_spinlock_recursive_t *slr) { rte_spinlock_init(&slr->sl); slr->user = -1; slr->count = 0; } /** * Take the recursive spinlock. * * @param slr * A pointer to the recursive spinlock. */ static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr) { int id = rte_gettid(); if (slr->user != id) { rte_spinlock_lock(&slr->sl); slr->user = id; } slr->count++; } /** * Release the recursive spinlock. * * @param slr * A pointer to the recursive spinlock. */ static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr) { if (--(slr->count) == 0) { slr->user = -1; rte_spinlock_unlock(&slr->sl); } } /** * Try to take the recursive lock. * * @param slr * A pointer to the recursive spinlock. * @return * 1 if the lock is successfully taken; 0 otherwise. */ static inline int rte_spinlock_recursive_trylock(rte_spinlock_recursive_t *slr) { int id = rte_gettid(); if (slr->user != id) { if (rte_spinlock_trylock(&slr->sl) == 0) return 0; slr->user = id; } slr->count++; return 1; } /** * Try to execute critical section in a hardware memory transaction, * if it fails or not available take the recursive spinlocks * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param slr * A pointer to the recursive spinlock. */ static inline void rte_spinlock_recursive_lock_tm( rte_spinlock_recursive_t *slr); /** * Commit hardware memory transaction or release the recursive spinlock * if the recursive spinlock is used as a fall-back * * @param slr * A pointer to the recursive spinlock. */ static inline void rte_spinlock_recursive_unlock_tm( rte_spinlock_recursive_t *slr); /** * Try to execute critical section in a hardware memory transaction, * if it fails or not available try to take the recursive lock * * NOTE: An attempt to perform a HW I/O operation inside a hardware memory * transaction always aborts the transaction since the CPU is not able to * roll-back should the transaction fail. Therefore, hardware transactional * locks are not advised to be used around rte_eth_rx_burst() and * rte_eth_tx_burst() calls. * * @param slr * A pointer to the recursive spinlock. * @return * 1 if the hardware memory transaction is successfully started * or lock is successfully taken; 0 otherwise. */ static inline int rte_spinlock_recursive_trylock_tm( rte_spinlock_recursive_t *slr); #endif /* _RTE_SPINLOCK_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_alarm.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ALARM_H_ #define _RTE_ALARM_H_ /** * @file * * Alarm functions * * Simple alarm-clock functionality supplied by eal. * Does not require hpet support. */ #ifdef __cplusplus extern "C" { #endif #include /** * Signature of callback back function called when an alarm goes off. */ typedef void (*rte_eal_alarm_callback)(void *arg); /** * Function to set a callback to be triggered when us microseconds * have expired. Accuracy of timing to the microsecond is not guaranteed. The * alarm function will not be called *before* the requested time, but may * be called a short period of time afterwards. * The alarm handler will be called only once. There is no need to call * "rte_eal_alarm_cancel" from within the callback function. * * @param us * The time in microseconds before the callback is called * @param cb * The function to be called when the alarm expires * @param cb_arg * Pointer parameter to be passed to the callback function * * @return * On success, zero. * On failure, a negative error number */ int rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb, void *cb_arg); /** * Function to cancel an alarm callback which has been registered before. If * used outside alarm callback it wait for all callbacks to finish execution. * * @param cb_fn * alarm callback * @param cb_arg * Pointer parameter to be passed to the callback function. To remove all * copies of a given callback function, irrespective of parameter, (void *)-1 * can be used here. * * @return * - value greater than 0 and rte_errno not changed - returned value is * the number of canceled alarm callback functions * - value greater or equal 0 and rte_errno set to EINPROGRESS, at least one * alarm could not be canceled because cancellation was requested from alarm * callback context. Returned value is the number of succesfuly canceled * alarm callbacks * - 0 and rte_errno set to ENOENT - no alarm found * - -1 and rte_errno set to EINVAL - invalid parameter (NULL callback) */ int rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg); #ifdef __cplusplus } #endif #endif /* _RTE_ALARM_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_branch_prediction.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Branch Prediction Helpers in RTE */ #ifndef _RTE_BRANCH_PREDICTION_H_ #define _RTE_BRANCH_PREDICTION_H_ /** * Check if a branch is likely to be taken. * * This compiler builtin allows the developer to indicate if a branch is * likely to be taken. Example: * * if (likely(x > 1)) * do_stuff(); * */ #ifndef likely #define likely(x) __builtin_expect((x),1) #endif /* likely */ /** * Check if a branch is unlikely to be taken. * * This compiler builtin allows the developer to indicate if a branch is * unlikely to be taken. Example: * * if (unlikely(x < 1)) * do_stuff(); * */ #ifndef unlikely #define unlikely(x) __builtin_expect((x),0) #endif /* unlikely */ #endif /* _RTE_BRANCH_PREDICTION_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_COMMON_H_ #define _RTE_COMMON_H_ /** * @file * * Generic, commonly-used macro and inline function definitions * for Intel DPDK. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #ifndef typeof #define typeof __typeof__ #endif #ifndef asm #define asm __asm__ #endif #ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __attribute__ ((aligned(1))); typedef uint32_t unaligned_uint32_t __attribute__ ((aligned(1))); typedef uint16_t unaligned_uint16_t __attribute__ ((aligned(1))); #else typedef uint64_t unaligned_uint64_t; typedef uint32_t unaligned_uint32_t; typedef uint16_t unaligned_uint16_t; #endif /*********** Macros to eliminate unused variable warnings ********/ /** * short definition to mark a function parameter unused */ #define __rte_unused __attribute__((__unused__)) /** * definition to mark a variable or function parameter as used so * as to avoid a compiler warning */ #define RTE_SET_USED(x) (void)(x) /*********** Macros for pointer arithmetic ********/ /** * add a byte-value offset from a pointer */ #define RTE_PTR_ADD(ptr, x) ((void*)((uintptr_t)(ptr) + (x))) /** * subtract a byte-value offset from a pointer */ #define RTE_PTR_SUB(ptr, x) ((void*)((uintptr_t)ptr - (x))) /** * get the difference between two pointer values, i.e. how far apart * in bytes are the locations they point two. It is assumed that * ptr1 is greater than ptr2. */ #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2)) /*********** Macros/static functions for doing alignment ********/ /** * Macro to align a pointer to a given power-of-two. The resultant * pointer will be a pointer of the same type as the first parameter, and * point to an address no higher than the first parameter. Second parameter * must be a power-of-two value. */ #define RTE_PTR_ALIGN_FLOOR(ptr, align) \ ((typeof(ptr))RTE_ALIGN_FLOOR((uintptr_t)ptr, align)) /** * Macro to align a value to a given power-of-two. The resultant value * will be of the same type as the first parameter, and will be no * bigger than the first parameter. Second parameter must be a * power-of-two value. */ #define RTE_ALIGN_FLOOR(val, align) \ (typeof(val))((val) & (~((typeof(val))((align) - 1)))) /** * Macro to align a pointer to a given power-of-two. The resultant * pointer will be a pointer of the same type as the first parameter, and * point to an address no lower than the first parameter. Second parameter * must be a power-of-two value. */ #define RTE_PTR_ALIGN_CEIL(ptr, align) \ RTE_PTR_ALIGN_FLOOR((typeof(ptr))RTE_PTR_ADD(ptr, (align) - 1), align) /** * Macro to align a value to a given power-of-two. The resultant value * will be of the same type as the first parameter, and will be no lower * than the first parameter. Second parameter must be a power-of-two * value. */ #define RTE_ALIGN_CEIL(val, align) \ RTE_ALIGN_FLOOR(((val) + ((typeof(val)) (align) - 1)), align) /** * Macro to align a pointer to a given power-of-two. The resultant * pointer will be a pointer of the same type as the first parameter, and * point to an address no lower than the first parameter. Second parameter * must be a power-of-two value. * This function is the same as RTE_PTR_ALIGN_CEIL */ #define RTE_PTR_ALIGN(ptr, align) RTE_PTR_ALIGN_CEIL(ptr, align) /** * Macro to align a value to a given power-of-two. The resultant * value will be of the same type as the first parameter, and * will be no lower than the first parameter. Second parameter * must be a power-of-two value. * This function is the same as RTE_ALIGN_CEIL */ #define RTE_ALIGN(val, align) RTE_ALIGN_CEIL(val, align) /** * Checks if a pointer is aligned to a given power-of-two value * * @param ptr * The pointer whose alignment is to be checked * @param align * The power-of-two value to which the ptr should be aligned * * @return * True(1) where the pointer is correctly aligned, false(0) otherwise */ static inline int rte_is_aligned(void *ptr, unsigned align) { return RTE_PTR_ALIGN(ptr, align) == ptr; } /*********** Macros for compile type checks ********/ /** * Triggers an error at compilation time if the condition is true. */ #ifndef __OPTIMIZE__ #define RTE_BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #else extern int RTE_BUILD_BUG_ON_detected_error; #define RTE_BUILD_BUG_ON(condition) do { \ ((void)sizeof(char[1 - 2*!!(condition)])); \ if (condition) \ RTE_BUILD_BUG_ON_detected_error = 1; \ } while(0) #endif /*********** Macros to work with powers of 2 ********/ /** * Returns true if n is a power of 2 * @param n * Number to check * @return 1 if true, 0 otherwise */ static inline int rte_is_power_of_2(uint32_t n) { return n && !(n & (n - 1)); } /** * Aligns input parameter to the next power of 2 * * @param x * The integer value to algin * * @return * Input parameter aligned to the next power of 2 */ static inline uint32_t rte_align32pow2(uint32_t x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return x + 1; } /** * Aligns 64b input parameter to the next power of 2 * * @param v * The 64b value to align * * @return * Input parameter aligned to the next power of 2 */ static inline uint64_t rte_align64pow2(uint64_t v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v |= v >> 32; return v + 1; } /*********** Macros for calculating min and max **********/ /** * Macro to return the minimum of two numbers */ #define RTE_MIN(a, b) ({ \ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a < _b ? _a : _b; \ }) /** * Macro to return the maximum of two numbers */ #define RTE_MAX(a, b) ({ \ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a > _b ? _a : _b; \ }) /*********** Other general functions / macros ********/ #ifdef __SSE2__ #include /** * PAUSE instruction for tight loops (avoid busy waiting) */ static inline void rte_pause (void) { _mm_pause(); } #else static inline void rte_pause(void) {} #endif /** * Searches the input parameter for the least significant set bit * (starting from zero). * If a least significant 1 bit is found, its bit index is returned. * If the content of the input parameter is zero, then the content of the return * value is undefined. * @param v * input parameter, should not be zero. * @return * least significant set bit in the input parameter. */ static inline uint32_t rte_bsf32(uint32_t v) { return __builtin_ctz(v); } #ifndef offsetof /** Return the offset of a field in a structure. */ #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) #endif #define _RTE_STR(x) #x /** Take a macro value and get a string version of it */ #define RTE_STR(x) _RTE_STR(x) /** Mask value of type "tp" for the first "ln" bit set. */ #define RTE_LEN2MASK(ln, tp) \ ((tp)((uint64_t)-1 >> (sizeof(uint64_t) * CHAR_BIT - (ln)))) /** Number of elements in the array. */ #define RTE_DIM(a) (sizeof (a) / sizeof ((a)[0])) /** * Converts a numeric string to the equivalent uint64_t value. * As well as straight number conversion, also recognises the suffixes * k, m and g for kilobytes, megabytes and gigabytes respectively. * * If a negative number is passed in i.e. a string with the first non-black * character being "-", zero is returned. Zero is also returned in the case of * an error with the strtoull call in the function. * * @param str * String containing number to convert. * @return * Number. */ static inline uint64_t rte_str_to_size(const char *str) { char *endptr; unsigned long long size; while (isspace((int)*str)) str++; if (*str == '-') return 0; errno = 0; size = strtoull(str, &endptr, 0); if (errno) return 0; if (*endptr == ' ') endptr++; /* allow 1 space gap */ switch (*endptr){ case 'G': case 'g': size *= 1024; /* fall-through */ case 'M': case 'm': size *= 1024; /* fall-through */ case 'K': case 'k': size *= 1024; /* fall-through */ default: break; } return size; } /** * Function to terminate the application immediately, printing an error * message and returning the exit_code back to the shell. * * This function never returns * * @param exit_code * The exit code to be returned by the application * @param format * The format string to be used for printing the message. This can include * printf format characters which will be expanded using any further parameters * to the function. */ void rte_exit(int exit_code, const char *format, ...) __attribute__((noreturn)) __attribute__((format(printf, 2, 3))); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_eal/common/include/rte_debug.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_DEBUG_H_ #define _RTE_DEBUG_H_ /** * @file * * Debug Functions in RTE * * This file defines a generic API for debug operations. Part of * the implementation is architecture-specific. */ #ifdef __cplusplus extern "C" { #endif /** * Dump the stack of the calling core to the console. */ void rte_dump_stack(void); /** * Dump the registers of the calling core to the console. * * Note: Not implemented in a userapp environment; use gdb instead. */ void rte_dump_registers(void); /** * Provide notification of a critical non-recoverable error and terminate * execution abnormally. * * Display the format string and its expanded arguments (printf-like). * * In a linuxapp environment, this function dumps the stack and calls * abort() resulting in a core dump if enabled. * * The function never returns. * * @param ... * The format string, followed by the variable list of arguments. */ #define rte_panic(...) rte_panic_(__func__, __VA_ARGS__, "dummy") #define rte_panic_(func, format, ...) __rte_panic(func, format "%.0s", __VA_ARGS__) #define RTE_VERIFY(exp) do { \ if (!(exp)) \ rte_panic("line %d\tassert \"" #exp "\" failed\n", __LINE__); \ } while (0) /* * Provide notification of a critical non-recoverable error and stop. * * This function should not be called directly. Refer to rte_panic() macro * documentation. */ void __rte_panic(const char *funcname , const char *format, ...) #ifdef __GNUC__ #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) __attribute__((cold)) #endif #endif __attribute__((noreturn)) __attribute__((format(printf, 2, 3))); #ifdef __cplusplus } #endif #endif /* _RTE_DEBUG_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_dev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_DEV_H_ #define _RTE_DEV_H_ /** * @file * * RTE PMD Driver Registration Interface * * This file manages the list of device drivers. */ #ifdef __cplusplus extern "C" { #endif #include /** Double linked list of device drivers. */ TAILQ_HEAD(rte_driver_list, rte_driver); /** * Initialization function called for each device driver once. */ typedef int (rte_dev_init_t)(const char *name, const char *args); /** * Uninitilization function called for each device driver once. */ typedef int (rte_dev_uninit_t)(const char *name); /** * Driver type enumeration */ enum pmd_type { PMD_VDEV = 0, PMD_PDEV = 1, }; /** * A structure describing a device driver. */ struct rte_driver { TAILQ_ENTRY(rte_driver) next; /**< Next in list. */ enum pmd_type type; /**< PMD Driver type */ const char *name; /**< Driver name. */ rte_dev_init_t *init; /**< Device init. function. */ rte_dev_uninit_t *uninit; /**< Device uninit. function. */ }; /** * Register a device driver. * * @param driver * A pointer to a rte_dev structure describing the driver * to be registered. */ void rte_eal_driver_register(struct rte_driver *driver); /** * Unregister a device driver. * * @param driver * A pointer to a rte_dev structure describing the driver * to be unregistered. */ void rte_eal_driver_unregister(struct rte_driver *driver); /** * Initalize all the registered drivers in this process */ int rte_eal_dev_init(void); /** * Initialize a driver specified by name. * * @param name * The pointer to a driver name to be initialized. * @param args * The pointer to arguments used by driver initialization. * @return * 0 on success, negative on error */ int rte_eal_vdev_init(const char *name, const char *args); /** * Uninitalize a driver specified by name. * * @param name * The pointer to a driver name to be initialized. * @return * 0 on success, negative on error */ int rte_eal_vdev_uninit(const char *name); #define PMD_REGISTER_DRIVER(d)\ void devinitfn_ ##d(void);\ void __attribute__((constructor, used)) devinitfn_ ##d(void)\ {\ rte_eal_driver_register(&d);\ } #ifdef __cplusplus } #endif #endif /* _RTE_VDEV_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_devargs.h ================================================ /*- * BSD LICENSE * * Copyright 2014 6WIND S.A. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_DEVARGS_H_ #define _RTE_DEVARGS_H_ /** * @file * * RTE devargs: list of devices and their user arguments * * This file stores a list of devices and their arguments given by * the user when a DPDK application is started. These devices can be PCI * devices or virtual devices. These devices are stored at startup in a * list of rte_devargs structures. */ #ifdef __cplusplus extern "C" { #endif #include #include #include /** * Type of generic device */ enum rte_devtype { RTE_DEVTYPE_WHITELISTED_PCI, RTE_DEVTYPE_BLACKLISTED_PCI, RTE_DEVTYPE_VIRTUAL, }; /** * Structure that stores a device given by the user with its arguments * * A user device is a physical or a virtual device given by the user to * the DPDK application at startup through command line arguments. * * The structure stores the configuration of the device, its PCI * identifier if it's a PCI device or the driver name if it's a virtual * device. */ struct rte_devargs { /** Next in list. */ TAILQ_ENTRY(rte_devargs) next; /** Type of device. */ enum rte_devtype type; union { /** Used if type is RTE_DEVTYPE_*_PCI. */ struct { /** PCI location. */ struct rte_pci_addr addr; } pci; /** Used if type is RTE_DEVTYPE_VIRTUAL. */ struct { /** Driver name. */ char drv_name[32]; } virtual; }; /** Arguments string as given by user or "" for no argument. */ char *args; }; /** user device double-linked queue type definition */ TAILQ_HEAD(rte_devargs_list, rte_devargs); /** Global list of user devices */ extern struct rte_devargs_list devargs_list; /** * Parse a devargs string. * * For PCI devices, the format of arguments string is "PCI_ADDR" or * "PCI_ADDR,key=val,key2=val2,...". Examples: "08:00.1", "0000:5:00.0", * "04:00.0,arg=val". * * For virtual devices, the format of arguments string is "DRIVER_NAME*" * or "DRIVER_NAME*,key=val,key2=val2,...". Examples: "eth_ring", * "eth_ring0", "eth_pmdAnything,arg=0:arg2=1". * * The function parses the arguments string to get driver name and driver * arguments. * * @param devargs_str * The arguments as given by the user. * @param drvname * The pointer to the string to store parsed driver name. * @param drvargs * The pointer to the string to store parsed driver arguments. * * @return * - 0 on success * - A negative value on error */ int rte_eal_parse_devargs_str(const char *devargs_str, char **drvname, char **drvargs); /** * Add a device to the user device list * * For PCI devices, the format of arguments string is "PCI_ADDR" or * "PCI_ADDR,key=val,key2=val2,...". Examples: "08:00.1", "0000:5:00.0", * "04:00.0,arg=val". * * For virtual devices, the format of arguments string is "DRIVER_NAME*" * or "DRIVER_NAME*,key=val,key2=val2,...". Examples: "eth_ring", * "eth_ring0", "eth_pmdAnything,arg=0:arg2=1". The validity of the * driver name is not checked by this function, it is done when probing * the drivers. * * @param devtype * The type of the device. * @param devargs_str * The arguments as given by the user. * * @return * - 0 on success * - A negative value on error */ int rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str); /** * Count the number of user devices of a specified type * * @param devtype * The type of the devices to counted. * * @return * The number of devices. */ unsigned int rte_eal_devargs_type_count(enum rte_devtype devtype); /** * This function dumps the list of user device and their arguments. * * @param f * A pointer to a file for output */ void rte_eal_devargs_dump(FILE *f); #ifdef __cplusplus } #endif #endif /* _RTE_DEVARGS_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_eal.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_EAL_H_ #define _RTE_EAL_H_ /** * @file * * EAL Configuration API */ #include #include #include #ifdef __cplusplus extern "C" { #endif #define RTE_MAGIC 19820526 /**< Magic number written by the main partition when ready. */ /** * The lcore role (used in RTE or not). */ enum rte_lcore_role_t { ROLE_RTE, ROLE_OFF, }; /** * The type of process in a linuxapp, multi-process setup */ enum rte_proc_type_t { RTE_PROC_AUTO = -1, /* allow auto-detection of primary/secondary */ RTE_PROC_PRIMARY = 0, /* set to zero, so primary is the default */ RTE_PROC_SECONDARY, RTE_PROC_INVALID }; /** * The global RTE configuration structure. */ struct rte_config { uint32_t master_lcore; /**< Id of the master lcore */ uint32_t lcore_count; /**< Number of available logical cores. */ enum rte_lcore_role_t lcore_role[RTE_MAX_LCORE]; /**< State of cores. */ /** Primary or secondary configuration */ enum rte_proc_type_t process_type; /** * Pointer to memory configuration, which may be shared across multiple * Intel DPDK instances */ struct rte_mem_config *mem_config; } __attribute__((__packed__)); /** * Get the global configuration structure. * * @return * A pointer to the global configuration structure. */ struct rte_config *rte_eal_get_configuration(void); /** * Get a lcore's role. * * @param lcore_id * The identifier of the lcore. * @return * The role of the lcore. */ enum rte_lcore_role_t rte_eal_lcore_role(unsigned lcore_id); /** * Get the process type in a multi-process setup * * @return * The process type */ enum rte_proc_type_t rte_eal_process_type(void); /** * Request iopl privilege for all RPL. * * This function should be called by pmds which need access to ioports. * @return * - On success, returns 0. * - On failure, returns -1. */ int rte_eal_iopl_init(void); /** * Initialize the Environment Abstraction Layer (EAL). * * This function is to be executed on the MASTER lcore only, as soon * as possible in the application's main() function. * * The function finishes the initialization process before main() is called. * It puts the SLAVE lcores in the WAIT state. * * When the multi-partition feature is supported, depending on the * configuration (if CONFIG_RTE_EAL_MAIN_PARTITION is disabled), this * function waits to ensure that the magic number is set before * returning. See also the rte_eal_get_configuration() function. Note: * This behavior may change in the future. * * @param argc * The argc argument that was given to the main() function. * @param argv * The argv argument that was given to the main() function. * @return * - On success, the number of parsed arguments, which is greater or * equal to zero. After the call to rte_eal_init(), * all arguments argv[x] with x < ret may be modified and should * not be accessed by the application. * - On failure, a negative error value. */ int rte_eal_init(int argc, char **argv); /** * Usage function typedef used by the application usage function. * * Use this function typedef to define and call rte_set_applcation_usage_hook() * routine. */ typedef void (*rte_usage_hook_t)(const char * prgname); /** * Add application usage routine callout from the eal_usage() routine. * * This function allows the application to include its usage message * in the EAL system usage message. The routine rte_set_application_usage_hook() * needs to be called before the rte_eal_init() routine in the application. * * This routine is optional for the application and will behave as if the set * routine was never called as the default behavior. * * @param usage_func * The func argument is a function pointer to the application usage routine. * Called function is defined using rte_usage_hook_t typedef, which is of * the form void rte_usage_func(const char * prgname). * * Calling this routine with a NULL value will reset the usage hook routine and * return the current value, which could be NULL. * @return * - Returns the current value of the rte_application_usage pointer to allow * the caller to daisy chain the usage routines if needing more then one. */ rte_usage_hook_t rte_set_application_usage_hook(rte_usage_hook_t usage_func); /** * macro to get the lock of tailq in mem_config */ #define RTE_EAL_TAILQ_RWLOCK (&rte_eal_get_configuration()->mem_config->qlock) /** * macro to get the multiple lock of mempool shared by mutiple-instance */ #define RTE_EAL_MEMPOOL_RWLOCK (&rte_eal_get_configuration()->mem_config->mplock) /** * Whether EAL is using huge pages (disabled by --no-huge option). * The no-huge mode cannot be used with UIO poll-mode drivers like igb/ixgbe. * It is useful for NIC drivers (e.g. librte_pmd_mlx4, librte_pmd_vmxnet3) or * crypto drivers (e.g. librte_crypto_nitrox) provided by third-parties such * as 6WIND. * * @return * Nonzero if hugepages are enabled. */ int rte_eal_has_hugepages(void); /** * A wrap API for syscall gettid. * * @return * On success, returns the thread ID of calling process. * It is always successful. */ int rte_sys_gettid(void); /** * Get system unique thread id. * * @return * On success, returns the thread ID of calling process. * It is always successful. */ static inline int rte_gettid(void) { static RTE_DEFINE_PER_LCORE(int, _thread_id) = -1; if (RTE_PER_LCORE(_thread_id) == -1) RTE_PER_LCORE(_thread_id) = rte_sys_gettid(); return RTE_PER_LCORE(_thread_id); } #ifdef __cplusplus } #endif #endif /* _RTE_EAL_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_eal_memconfig.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_EAL_MEMCONFIG_H_ #define _RTE_EAL_MEMCONFIG_H_ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * the structure for the memory configuration for the RTE. * Used by the rte_config structure. It is separated out, as for multi-process * support, the memory details should be shared across instances */ struct rte_mem_config { volatile uint32_t magic; /**< Magic number - Sanity check. */ /* memory topology */ uint32_t nchannel; /**< Number of channels (0 if unknown). */ uint32_t nrank; /**< Number of ranks (0 if unknown). */ /** * current lock nest order * - qlock->mlock (ring/hash/lpm) * - mplock->qlock->mlock (mempool) * Notice: * *ALWAYS* obtain qlock first if having to obtain both qlock and mlock */ rte_rwlock_t mlock; /**< only used by memzone LIB for thread-safe. */ rte_rwlock_t qlock; /**< used for tailq operation for thread safe. */ rte_rwlock_t mplock; /**< only used by mempool LIB for thread-safe. */ uint32_t memzone_cnt; /**< Number of allocated memzones */ /* memory segments and zones */ struct rte_memseg memseg[RTE_MAX_MEMSEG]; /**< Physmem descriptors. */ struct rte_memzone memzone[RTE_MAX_MEMZONE]; /**< Memzone descriptors. */ struct rte_tailq_head tailq_head[RTE_MAX_TAILQ]; /**< Tailqs for objects */ /* Heaps of Malloc per socket */ struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES]; /* address of mem_config in primary process. used to map shared config into * exact same address the primary process maps it. */ uint64_t mem_cfg_addr; } __attribute__((__packed__)); inline static void rte_eal_mcfg_wait_complete(struct rte_mem_config* mcfg) { /* wait until shared mem_config finish initialising */ while(mcfg->magic != RTE_MAGIC) rte_pause(); } #ifdef __cplusplus } #endif #endif /*__RTE_EAL_MEMCONFIG_H_*/ ================================================ FILE: lib/librte_eal/common/include/rte_errno.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * * API for error cause tracking */ #ifndef _RTE_ERRNO_H_ #define _RTE_ERRNO_H_ #ifdef __cplusplus extern "C" { #endif #include RTE_DECLARE_PER_LCORE(int, _rte_errno); /**< Per core error number. */ /** * Error number value, stored per-thread, which can be queried after * calls to certain functions to determine why those functions failed. * * Uses standard values from errno.h wherever possible, with a small number * of additional possible values for RTE-specific conditions. */ #define rte_errno RTE_PER_LCORE(_rte_errno) /** * Function which returns a printable string describing a particular * error code. For non-RTE-specific error codes, this function returns * the value from the libc strerror function. * * @param errnum * The error number to be looked up - generally the value of rte_errno * @return * A pointer to a thread-local string containing the text describing * the error. */ const char *rte_strerror(int errnum); #ifndef __ELASTERROR /** * Check if we have a defined value for the max system-defined errno values. * if no max defined, start from 1000 to prevent overlap with standard values */ #define __ELASTERROR 1000 #endif /** Error types */ enum { RTE_MIN_ERRNO = __ELASTERROR, /**< Start numbering above std errno vals */ E_RTE_SECONDARY, /**< Operation not allowed in secondary processes */ E_RTE_NO_CONFIG, /**< Missing rte_config */ RTE_MAX_ERRNO /**< Max RTE error number */ }; #ifdef __cplusplus } #endif #endif /* _RTE_ERRNO_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_hexdump.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_HEXDUMP_H_ #define _RTE_HEXDUMP_H_ /** * @file * Simple API to dump out memory in a special hex format. */ #include #ifdef __cplusplus extern "C" { #endif /** * Dump out memory in a special hex dump format. * * @param f * A pointer to a file for output * @param title * If not NULL this string is printed as a header to the output. * @param buf * This is the buffer address to print out. * @param len * The number of bytes to dump out * @return * None. */ extern void rte_hexdump(FILE *f, const char * title, const void * buf, unsigned int len); /** * Dump out memory in a hex format with colons between bytes. * * @param f * A pointer to a file for output * @param title * If not NULL this string is printed as a header to the output. * @param buf * This is the buffer address to print out. * @param len * The number of bytes to dump out * @return * None. */ void rte_memdump(FILE *f, const char * title, const void * buf, unsigned int len); #ifdef __cplusplus } #endif #endif /* _RTE_HEXDUMP_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_interrupts.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_INTERRUPTS_H_ #define _RTE_INTERRUPTS_H_ /** * @file * * The RTE interrupt interface provides functions to register/unregister * callbacks for a specific interrupt. */ #ifdef __cplusplus extern "C" { #endif /** Interrupt handle */ struct rte_intr_handle; /** Function to be registered for the specific interrupt */ typedef void (*rte_intr_callback_fn)(struct rte_intr_handle *intr_handle, void *cb_arg); #include /** * It registers the callback for the specific interrupt. Multiple * callbacks cal be registered at the same time. * @param intr_handle * Pointer to the interrupt handle. * @param cb * callback address. * @param cb_arg * address of parameter for callback. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_callback_register(struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg); /** * It unregisters the callback according to the specified interrupt handle. * * @param intr_handle * pointer to the interrupt handle. * @param cb * callback address. * @param cb_arg * address of parameter for callback, (void *)-1 means to remove all * registered which has the same callback address. * * @return * - On success, return the number of callback entities removed. * - On failure, a negative value. */ int rte_intr_callback_unregister(struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg); /** * It enables the interrupt for the specified handle. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_enable(struct rte_intr_handle *intr_handle); /** * It disables the interrupt for the specified handle. * * @param intr_handle * pointer to the interrupt handle. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_disable(struct rte_intr_handle *intr_handle); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_eal/common/include/rte_launch.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_LAUNCH_H_ #define _RTE_LAUNCH_H_ /** * @file * * Launch tasks on other lcores */ #ifdef __cplusplus extern "C" { #endif /** * State of an lcore. */ enum rte_lcore_state_t { WAIT, /**< waiting a new command */ RUNNING, /**< executing command */ FINISHED, /**< command executed */ }; /** * Definition of a remote launch function. */ typedef int (lcore_function_t)(void *); /** * Launch a function on another lcore. * * To be executed on the MASTER lcore only. * * Sends a message to a slave lcore (identified by the slave_id) that * is in the WAIT state (this is true after the first call to * rte_eal_init()). This can be checked by first calling * rte_eal_wait_lcore(slave_id). * * When the remote lcore receives the message, it switches to * the RUNNING state, then calls the function f with argument arg. Once the * execution is done, the remote lcore switches to a FINISHED state and * the return value of f is stored in a local variable to be read using * rte_eal_wait_lcore(). * * The MASTER lcore returns as soon as the message is sent and knows * nothing about the completion of f. * * Note: This function is not designed to offer optimum * performance. It is just a practical way to launch a function on * another lcore at initialization time. * * @param f * The function to be called. * @param arg * The argument for the function. * @param slave_id * The identifier of the lcore on which the function should be executed. * @return * - 0: Success. Execution of function f started on the remote lcore. * - (-EBUSY): The remote lcore is not in a WAIT state. */ int rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned slave_id); /** * This enum indicates whether the master core must execute the handler * launched on all logical cores. */ enum rte_rmt_call_master_t { SKIP_MASTER = 0, /**< lcore handler not executed by master core. */ CALL_MASTER, /**< lcore handler executed by master core. */ }; /** * Launch a function on all lcores. * * Check that each SLAVE lcore is in a WAIT state, then call * rte_eal_remote_launch() for each lcore. * * @param f * The function to be called. * @param arg * The argument for the function. * @param call_master * If call_master set to SKIP_MASTER, the MASTER lcore does not call * the function. If call_master is set to CALL_MASTER, the function * is also called on master before returning. In any case, the master * lcore returns as soon as it finished its job and knows nothing * about the completion of f on the other lcores. * @return * - 0: Success. Execution of function f started on all remote lcores. * - (-EBUSY): At least one remote lcore is not in a WAIT state. In this * case, no message is sent to any of the lcores. */ int rte_eal_mp_remote_launch(lcore_function_t *f, void *arg, enum rte_rmt_call_master_t call_master); /** * Get the state of the lcore identified by slave_id. * * To be executed on the MASTER lcore only. * * @param slave_id * The identifier of the lcore. * @return * The state of the lcore. */ enum rte_lcore_state_t rte_eal_get_lcore_state(unsigned slave_id); /** * Wait until an lcore finishes its job. * * To be executed on the MASTER lcore only. * * If the slave lcore identified by the slave_id is in a FINISHED state, * switch to the WAIT state. If the lcore is in RUNNING state, wait until * the lcore finishes its job and moves to the FINISHED state. * * @param slave_id * The identifier of the lcore. * @return * - 0: If the lcore identified by the slave_id is in a WAIT state. * - The value that was returned by the previous remote launch * function call if the lcore identified by the slave_id was in a * FINISHED or RUNNING state. In this case, it changes the state * of the lcore to WAIT. */ int rte_eal_wait_lcore(unsigned slave_id); /** * Wait until all lcores finish their jobs. * * To be executed on the MASTER lcore only. Issue an * rte_eal_wait_lcore() for every lcore. The return values are * ignored. * * After a call to rte_eal_mp_wait_lcore(), the caller can assume * that all slave lcores are in a WAIT state. */ void rte_eal_mp_wait_lcore(void); #ifdef __cplusplus } #endif #endif /* _RTE_LAUNCH_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_lcore.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_LCORE_H_ #define _RTE_LCORE_H_ /** * @file * * API for lcore and socket manipulation * */ #include #include #include #ifdef __cplusplus extern "C" { #endif #define LCORE_ID_ANY UINT32_MAX /**< Any lcore. */ #if defined(__linux__) typedef cpu_set_t rte_cpuset_t; #elif defined(__FreeBSD__) #include typedef cpuset_t rte_cpuset_t; #endif /** * Structure storing internal configuration (per-lcore) */ struct lcore_config { unsigned detected; /**< true if lcore was detected */ pthread_t thread_id; /**< pthread identifier */ int pipe_master2slave[2]; /**< communication pipe with master */ int pipe_slave2master[2]; /**< communication pipe with master */ lcore_function_t * volatile f; /**< function to call */ void * volatile arg; /**< argument of function */ volatile int ret; /**< return value of function */ volatile enum rte_lcore_state_t state; /**< lcore state */ unsigned socket_id; /**< physical socket id for this lcore */ unsigned core_id; /**< core number on socket for this lcore */ int core_index; /**< relative index, starting from 0 */ rte_cpuset_t cpuset; /**< cpu set which the lcore affinity to */ }; /** * Internal configuration (per-lcore) */ extern struct lcore_config lcore_config[RTE_MAX_LCORE]; RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per thread "lcore id". */ RTE_DECLARE_PER_LCORE(rte_cpuset_t, _cpuset); /**< Per thread "cpuset". */ /** * Return the ID of the execution unit we are running on. * @return * Logical core ID (in EAL thread) or LCORE_ID_ANY (in non-EAL thread) */ static inline unsigned rte_lcore_id(void) { return RTE_PER_LCORE(_lcore_id); } /** * Get the id of the master lcore * * @return * the id of the master lcore */ static inline unsigned rte_get_master_lcore(void) { return rte_eal_get_configuration()->master_lcore; } /** * Return the number of execution units (lcores) on the system. * * @return * the number of execution units (lcores) on the system. */ static inline unsigned rte_lcore_count(void) { const struct rte_config *cfg = rte_eal_get_configuration(); return cfg->lcore_count; } /** * Return the index of the lcore starting from zero. * The order is physical or given by command line (-l option). * * @param lcore_id * The targeted lcore, or -1 for the current one. * @return * The relative index, or -1 if not enabled. */ static inline int rte_lcore_index(int lcore_id) { if (lcore_id >= RTE_MAX_LCORE) return -1; if (lcore_id < 0) lcore_id = rte_lcore_id(); return lcore_config[lcore_id].core_index; } /** * Return the ID of the physical socket of the logical core we are * running on. * @return * the ID of current lcoreid's physical socket */ unsigned rte_socket_id(void); /** * Get the ID of the physical socket of the specified lcore * * @param lcore_id * the targeted lcore, which MUST be between 0 and RTE_MAX_LCORE-1. * @return * the ID of lcoreid's physical socket */ static inline unsigned rte_lcore_to_socket_id(unsigned lcore_id) { return lcore_config[lcore_id].socket_id; } /** * Test if an lcore is enabled. * * @param lcore_id * The identifier of the lcore, which MUST be between 0 and * RTE_MAX_LCORE-1. * @return * True if the given lcore is enabled; false otherwise. */ static inline int rte_lcore_is_enabled(unsigned lcore_id) { struct rte_config *cfg = rte_eal_get_configuration(); if (lcore_id >= RTE_MAX_LCORE) return 0; return (cfg->lcore_role[lcore_id] != ROLE_OFF); } /** * Get the next enabled lcore ID. * * @param i * The current lcore (reference). * @param skip_master * If true, do not return the ID of the master lcore. * @param wrap * If true, go back to 0 when RTE_MAX_LCORE is reached; otherwise, * return RTE_MAX_LCORE. * @return * The next lcore_id or RTE_MAX_LCORE if not found. */ static inline unsigned rte_get_next_lcore(unsigned i, int skip_master, int wrap) { i++; if (wrap) i %= RTE_MAX_LCORE; while (i < RTE_MAX_LCORE) { if (!rte_lcore_is_enabled(i) || (skip_master && (i == rte_get_master_lcore()))) { i++; if (wrap) i %= RTE_MAX_LCORE; continue; } break; } return i; } /** * Macro to browse all running lcores. */ #define RTE_LCORE_FOREACH(i) \ for (i = rte_get_next_lcore(-1, 0, 0); \ i #include #include /** The rte_log structure. */ struct rte_logs { uint32_t type; /**< Bitfield with enabled logs. */ uint32_t level; /**< Log level. */ FILE *file; /**< Pointer to current FILE* for logs. */ }; /** Global log informations */ extern struct rte_logs rte_logs; /* SDK log type */ #define RTE_LOGTYPE_EAL 0x00000001 /**< Log related to eal. */ #define RTE_LOGTYPE_MALLOC 0x00000002 /**< Log related to malloc. */ #define RTE_LOGTYPE_RING 0x00000004 /**< Log related to ring. */ #define RTE_LOGTYPE_MEMPOOL 0x00000008 /**< Log related to mempool. */ #define RTE_LOGTYPE_TIMER 0x00000010 /**< Log related to timers. */ #define RTE_LOGTYPE_PMD 0x00000020 /**< Log related to poll mode driver. */ #define RTE_LOGTYPE_HASH 0x00000040 /**< Log related to hash table. */ #define RTE_LOGTYPE_LPM 0x00000080 /**< Log related to LPM. */ #define RTE_LOGTYPE_KNI 0x00000100 /**< Log related to KNI. */ #define RTE_LOGTYPE_ACL 0x00000200 /**< Log related to ACL. */ #define RTE_LOGTYPE_POWER 0x00000400 /**< Log related to power. */ #define RTE_LOGTYPE_METER 0x00000800 /**< Log related to QoS meter. */ #define RTE_LOGTYPE_SCHED 0x00001000 /**< Log related to QoS port scheduler. */ #define RTE_LOGTYPE_PORT 0x00002000 /**< Log related to port. */ #define RTE_LOGTYPE_TABLE 0x00004000 /**< Log related to table. */ #define RTE_LOGTYPE_PIPELINE 0x00008000 /**< Log related to pipeline. */ #define RTE_LOGTYPE_MBUF 0x00010000 /**< Log related to mbuf. */ /* these log types can be used in an application */ #define RTE_LOGTYPE_USER1 0x01000000 /**< User-defined log type 1. */ #define RTE_LOGTYPE_USER2 0x02000000 /**< User-defined log type 2. */ #define RTE_LOGTYPE_USER3 0x04000000 /**< User-defined log type 3. */ #define RTE_LOGTYPE_USER4 0x08000000 /**< User-defined log type 4. */ #define RTE_LOGTYPE_USER5 0x10000000 /**< User-defined log type 5. */ #define RTE_LOGTYPE_USER6 0x20000000 /**< User-defined log type 6. */ #define RTE_LOGTYPE_USER7 0x40000000 /**< User-defined log type 7. */ #define RTE_LOGTYPE_USER8 0x80000000 /**< User-defined log type 8. */ /* Can't use 0, as it gives compiler warnings */ #define RTE_LOG_EMERG 1U /**< System is unusable. */ #define RTE_LOG_ALERT 2U /**< Action must be taken immediately. */ #define RTE_LOG_CRIT 3U /**< Critical conditions. */ #define RTE_LOG_ERR 4U /**< Error conditions. */ #define RTE_LOG_WARNING 5U /**< Warning conditions. */ #define RTE_LOG_NOTICE 6U /**< Normal but significant condition. */ #define RTE_LOG_INFO 7U /**< Informational. */ #define RTE_LOG_DEBUG 8U /**< Debug-level messages. */ /** The default log stream. */ extern FILE *eal_default_log_stream; /** * Change the stream that will be used by the logging system. * * This can be done at any time. The f argument represents the stream * to be used to send the logs. If f is NULL, the default output is * used (stderr). * * @param f * Pointer to the stream. * @return * - 0 on success. * - Negative on error. */ int rte_openlog_stream(FILE *f); /** * Set the global log level. * * After this call, all logs that are lower or equal than level and * lower or equal than the RTE_LOG_LEVEL configuration option will be * displayed. * * @param level * Log level. A value between RTE_LOG_EMERG (1) and RTE_LOG_DEBUG (8). */ void rte_set_log_level(uint32_t level); /** * Get the global log level. */ uint32_t rte_get_log_level(void); /** * Enable or disable the log type. * * @param type * Log type, for example, RTE_LOGTYPE_EAL. * @param enable * True for enable; false for disable. */ void rte_set_log_type(uint32_t type, int enable); /** * Get the global log type. */ uint32_t rte_get_log_type(void); /** * Get the current loglevel for the message being processed. * * Before calling the user-defined stream for logging, the log * subsystem sets a per-lcore variable containing the loglevel and the * logtype of the message being processed. This information can be * accessed by the user-defined log output function through this * function. * * @return * The loglevel of the message being processed. */ int rte_log_cur_msg_loglevel(void); /** * Get the current logtype for the message being processed. * * Before calling the user-defined stream for logging, the log * subsystem sets a per-lcore variable containing the loglevel and the * logtype of the message being processed. This information can be * accessed by the user-defined log output function through this * function. * * @return * The logtype of the message being processed. */ int rte_log_cur_msg_logtype(void); /** * Enable or disable the history (enabled by default) * * @param enable * true to enable, or 0 to disable history. */ void rte_log_set_history(int enable); /** * Dump the log history to a file * * @param f * A pointer to a file for output */ void rte_log_dump_history(FILE *f); /** * Add a log message to the history. * * This function can be called from a user-defined log stream. It adds * the given message in the history that can be dumped using * rte_log_dump_history(). * * @param buf * A data buffer containing the message to be saved in the history. * @param size * The length of the data buffer. * @return * - 0: Success. * - (-ENOBUFS) if there is no room to store the message. */ int rte_log_add_in_history(const char *buf, size_t size); /** * Generates a log message. * * The message will be sent in the stream defined by the previous call * to rte_openlog_stream(). * * The level argument determines if the log should be displayed or * not, depending on the global rte_logs variable. * * The preferred alternative is the RTE_LOG() function because debug logs may * be removed at compilation time if optimization is enabled. Moreover, * logs are automatically prefixed by type when using the macro. * * @param level * Log level. A value between RTE_LOG_EMERG (1) and RTE_LOG_DEBUG (8). * @param logtype * The log type, for example, RTE_LOGTYPE_EAL. * @param format * The format string, as in printf(3), followed by the variable arguments * required by the format. * @return * - 0: Success. * - Negative on error. */ int rte_log(uint32_t level, uint32_t logtype, const char *format, ...) #ifdef __GNUC__ #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) __attribute__((cold)) #endif #endif __attribute__((format(printf, 3, 4))); /** * Generates a log message. * * The message will be sent in the stream defined by the previous call * to rte_openlog_stream(). * * The level argument determines if the log should be displayed or * not, depending on the global rte_logs variable. A trailing * newline may be added if needed. * * The preferred alternative is the RTE_LOG() because debug logs may be * removed at compilation time. * * @param level * Log level. A value between RTE_LOG_EMERG (1) and RTE_LOG_DEBUG (8). * @param logtype * The log type, for example, RTE_LOGTYPE_EAL. * @param format * The format string, as in printf(3), followed by the variable arguments * required by the format. * @param ap * The va_list of the variable arguments required by the format. * @return * - 0: Success. * - Negative on error. */ int rte_vlog(uint32_t level, uint32_t logtype, const char *format, va_list ap) __attribute__((format(printf,3,0))); /** * Generates a log message. * * The RTE_LOG() is equivalent to rte_log() with two differences: * - RTE_LOG() can be used to remove debug logs at compilation time, * depending on RTE_LOG_LEVEL configuration option, and compilation * optimization level. If optimization is enabled, the tests * involving constants only are pre-computed. If compilation is done * with -O0, these tests will be done at run time. * - The log level and log type names are smaller, for example: * RTE_LOG(INFO, EAL, "this is a %s", "log"); * * @param l * Log level. A value between EMERG (1) and DEBUG (8). The short name is * expanded by the macro, so it cannot be an integer value. * @param t * The log type, for example, EAL. The short name is expanded by the * macro, so it cannot be an integer value. * @param ... * The fmt string, as in printf(3), followed by the variable arguments * required by the format. * @return * - 0: Success. * - Negative on error. */ #define RTE_LOG(l, t, ...) \ (void)((RTE_LOG_ ## l <= RTE_LOG_LEVEL) ? \ rte_log(RTE_LOG_ ## l, \ RTE_LOGTYPE_ ## t, # t ": " __VA_ARGS__) : \ 0) #ifdef __cplusplus } #endif #endif /* _RTE_LOG_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_malloc.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MALLOC_H_ #define _RTE_MALLOC_H_ /** * @file * RTE Malloc. This library provides methods for dynamically allocating memory * from hugepages. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Structure to hold heap statistics obtained from rte_malloc_get_socket_stats function. */ struct rte_malloc_socket_stats { size_t heap_totalsz_bytes; /**< Total bytes on heap */ size_t heap_freesz_bytes; /**< Total free bytes on heap */ size_t greatest_free_size; /**< Size in bytes of largest free block */ unsigned free_count; /**< Number of free elements on heap */ unsigned alloc_count; /**< Number of allocated elements on heap */ size_t heap_allocsz_bytes; /**< Total allocated bytes on heap */ }; /** * This function allocates memory from the huge-page area of memory. The memory * is not cleared. In NUMA systems, the memory allocated resides on the same * NUMA socket as the core that calls this function. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param size * Size (in bytes) to be allocated. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_malloc(const char *type, size_t size, unsigned align); /** * Allocate zero'ed memory from the heap. * * Equivalent to rte_malloc() except that the memory zone is * initialised with zeros. In NUMA systems, the memory allocated resides on the * same NUMA socket as the core that calls this function. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param size * Size (in bytes) to be allocated. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must obviously be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_zmalloc(const char *type, size_t size, unsigned align); /** * Replacement function for calloc(), using huge-page memory. Memory area is * initialised with zeros. In NUMA systems, the memory allocated resides on the * same NUMA socket as the core that calls this function. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param num * Number of elements to be allocated. * @param size * Size (in bytes) of a single element. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must obviously be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_calloc(const char *type, size_t num, size_t size, unsigned align); /** * Replacement function for realloc(), using huge-page memory. Reserved area * memory is resized, preserving contents. In NUMA systems, the new area * resides on the same NUMA socket as the old area. * * @param ptr * Pointer to already allocated memory * @param size * Size (in bytes) of new area. If this is 0, memory is freed. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must obviously be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the reallocated memory. */ void * rte_realloc(void *ptr, size_t size, unsigned align); /** * This function allocates memory from the huge-page area of memory. The memory * is not cleared. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param size * Size (in bytes) to be allocated. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @param socket * NUMA socket to allocate memory on. If SOCKET_ID_ANY is used, this function * will behave the same as rte_malloc(). * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_malloc_socket(const char *type, size_t size, unsigned align, int socket); /** * Allocate zero'ed memory from the heap. * * Equivalent to rte_malloc() except that the memory zone is * initialised with zeros. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param size * Size (in bytes) to be allocated. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must obviously be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @param socket * NUMA socket to allocate memory on. If SOCKET_ID_ANY is used, this function * will behave the same as rte_zmalloc(). * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket); /** * Replacement function for calloc(), using huge-page memory. Memory area is * initialised with zeros. * * @param type * A string identifying the type of allocated objects (useful for debug * purposes, such as identifying the cause of a memory leak). Can be NULL. * @param num * Number of elements to be allocated. * @param size * Size (in bytes) of a single element. * @param align * If 0, the return is a pointer that is suitably aligned for any kind of * variable (in the same manner as malloc()). * Otherwise, the return is a pointer that is a multiple of *align*. In * this case, it must obviously be a power of two. (Minimum alignment is the * cacheline size, i.e. 64-bytes) * @param socket * NUMA socket to allocate memory on. If SOCKET_ID_ANY is used, this function * will behave the same as rte_calloc(). * @return * - NULL on error. Not enough memory, or invalid arguments (size is 0, * align is not a power of two). * - Otherwise, the pointer to the allocated object. */ void * rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket); /** * Frees the memory space pointed to by the provided pointer. * * This pointer must have been returned by a previous call to * rte_malloc(), rte_zmalloc(), rte_calloc() or rte_realloc(). The behaviour of * rte_free() is undefined if the pointer does not match this requirement. * * If the pointer is NULL, the function does nothing. * * @param ptr * The pointer to memory to be freed. */ void rte_free(void *ptr); /** * If malloc debug is enabled, check a memory block for header * and trailer markers to indicate that all is well with the block. * If size is non-null, also return the size of the block. * * @param ptr * pointer to the start of a data block, must have been returned * by a previous call to rte_malloc(), rte_zmalloc(), rte_calloc() * or rte_realloc() * @param size * if non-null, and memory block pointer is valid, returns the size * of the memory block * @return * -1 on error, invalid pointer passed or header and trailer markers * are missing or corrupted * 0 on success */ int rte_malloc_validate(const void *ptr, size_t *size); /** * Get heap statistics for the specified heap. * * @param socket * An unsigned integer specifying the socket to get heap statistics for * @param socket_stats * A structure which provides memory to store statistics * @return * Null on error * Pointer to structure storing statistics on success */ int rte_malloc_get_socket_stats(int socket, struct rte_malloc_socket_stats *socket_stats); /** * Dump statistics. * * Dump for the specified type to the console. If the type argument is * NULL, all memory types will be dumped. * * @param f * A pointer to a file for output * @param type * A string identifying the type of objects to dump, or NULL * to dump all objects. */ void rte_malloc_dump_stats(FILE *f, const char *type); /** * Set the maximum amount of allocated memory for this type. * * This is not yet implemented * * @param type * A string identifying the type of allocated objects. * @param max * The maximum amount of allocated bytes for this type. * @return * - 0: Success. * - (-1): Error. */ int rte_malloc_set_limit(const char *type, size_t max); /** * Return the physical address of a virtual address obtained through * rte_malloc * * @param addr * Adress obtained from a previous rte_malloc call * @return * NULL on error * otherwise return physical address of the buffer */ phys_addr_t rte_malloc_virt2phy(const void *addr); #ifdef __cplusplus } #endif #endif /* _RTE_MALLOC_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_malloc_heap.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MALLOC_HEAP_H_ #define _RTE_MALLOC_HEAP_H_ #include #include #include #include /* Number of free lists per heap, grouped by size. */ #define RTE_HEAP_NUM_FREELISTS 13 /** * Structure to hold malloc heap */ struct malloc_heap { rte_spinlock_t lock; LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS]; unsigned alloc_count; size_t total_size; } __rte_cache_aligned; #endif /* _RTE_MALLOC_HEAP_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_memory.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMORY_H_ #define _RTE_MEMORY_H_ /** * @file * * Memory-related RTE API. */ #include #include #include #ifdef RTE_EXEC_ENV_LINUXAPP #include #endif #ifdef __cplusplus extern "C" { #endif enum rte_page_sizes { RTE_PGSIZE_4K = 1ULL << 12, RTE_PGSIZE_64K = 1ULL << 16, RTE_PGSIZE_256K = 1ULL << 18, RTE_PGSIZE_2M = 1ULL << 21, RTE_PGSIZE_16M = 1ULL << 24, RTE_PGSIZE_256M = 1ULL << 28, RTE_PGSIZE_512M = 1ULL << 29, RTE_PGSIZE_1G = 1ULL << 30, RTE_PGSIZE_4G = 1ULL << 32, RTE_PGSIZE_16G = 1ULL << 34, }; #define SOCKET_ID_ANY -1 /**< Any NUMA socket. */ #ifndef RTE_CACHE_LINE_SIZE #define RTE_CACHE_LINE_SIZE 64 /**< Cache line size. */ #endif #define RTE_CACHE_LINE_MASK (RTE_CACHE_LINE_SIZE-1) /**< Cache line mask. */ #define RTE_CACHE_LINE_ROUNDUP(size) \ (RTE_CACHE_LINE_SIZE * ((size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE)) /**< Return the first cache-aligned value greater or equal to size. */ /** * Force alignment to cache line. */ #define __rte_cache_aligned __attribute__((__aligned__(RTE_CACHE_LINE_SIZE))) typedef uint64_t phys_addr_t; /**< Physical address definition. */ #define RTE_BAD_PHYS_ADDR ((phys_addr_t)-1) /** * Physical memory segment descriptor. */ struct rte_memseg { phys_addr_t phys_addr; /**< Start physical address. */ union { void *addr; /**< Start virtual address. */ uint64_t addr_64; /**< Makes sure addr is always 64 bits */ }; #ifdef RTE_LIBRTE_IVSHMEM phys_addr_t ioremap_addr; /**< Real physical address inside the VM */ #endif size_t len; /**< Length of the segment. */ uint64_t hugepage_sz; /**< The pagesize of underlying memory */ int32_t socket_id; /**< NUMA socket ID. */ uint32_t nchannel; /**< Number of channels. */ uint32_t nrank; /**< Number of ranks. */ #ifdef RTE_LIBRTE_XEN_DOM0 /**< store segment MFNs */ uint64_t mfn[DOM0_NUM_MEMBLOCK]; #endif } __attribute__((__packed__)); /** * Lock page in physical memory and prevent from swapping. * * @param virt * The virtual address. * @return * 0 on success, negative on error. */ int rte_mem_lock_page(const void *virt); /** * Get physical address of any mapped virtual address in the current process. * It is found by browsing the /proc/self/pagemap special file. * The page must be locked. * * @param virt * The virtual address. * @return * The physical address or RTE_BAD_PHYS_ADDR on error. */ phys_addr_t rte_mem_virt2phy(const void *virt); /** * Get the layout of the available physical memory. * * It can be useful for an application to have the full physical * memory layout to decide the size of a memory zone to reserve. This * table is stored in rte_config (see rte_eal_get_configuration()). * * @return * - On success, return a pointer to a read-only table of struct * rte_physmem_desc elements, containing the layout of all * addressable physical memory. The last element of the table * contains a NULL address. * - On error, return NULL. This should not happen since it is a fatal * error that will probably cause the entire system to panic. */ const struct rte_memseg *rte_eal_get_physmem_layout(void); /** * Dump the physical memory layout to the console. * * @param f * A pointer to a file for output */ void rte_dump_physmem_layout(FILE *f); /** * Get the total amount of available physical memory. * * @return * The total amount of available physical memory in bytes. */ uint64_t rte_eal_get_physmem_size(void); /** * Get the number of memory channels. * * @return * The number of memory channels on the system. The value is 0 if unknown * or not the same on all devices. */ unsigned rte_memory_get_nchannel(void); /** * Get the number of memory ranks. * * @return * The number of memory ranks on the system. The value is 0 if unknown or * not the same on all devices. */ unsigned rte_memory_get_nrank(void); #ifdef RTE_LIBRTE_XEN_DOM0 /** * Return the physical address of elt, which is an element of the pool mp. * * @param memseg_id * The mempool is from which memory segment. * @param phy_addr * physical address of elt. * * @return * The physical address or error. */ phys_addr_t rte_mem_phy2mch(uint32_t memseg_id, const phys_addr_t phy_addr); /** * Memory init for supporting application running on Xen domain0. * * @param void * * @return * 0: successfully * negative: error */ int rte_xen_dom0_memory_init(void); /** * Attach to memory setments of primary process on Xen domain0. * * @param void * * @return * 0: successfully * negative: error */ int rte_xen_dom0_memory_attach(void); #endif #ifdef __cplusplus } #endif #endif /* _RTE_MEMORY_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_memzone.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMZONE_H_ #define _RTE_MEMZONE_H_ /** * @file * RTE Memzone * * The goal of the memzone allocator is to reserve contiguous * portions of physical memory. These zones are identified by a name. * * The memzone descriptors are shared by all partitions and are * located in a known place of physical memory. This zone is accessed * using rte_eal_get_configuration(). The lookup (by name) of a * memory zone can be done in any partition and returns the same * physical address. * * A reserved memory zone cannot be unreserved. The reservation shall * be done at initialization time only. */ #include #include #ifdef __cplusplus extern "C" { #endif #define RTE_MEMZONE_2MB 0x00000001 /**< Use 2MB pages. */ #define RTE_MEMZONE_1GB 0x00000002 /**< Use 1GB pages. */ #define RTE_MEMZONE_16MB 0x00000100 /**< Use 16MB pages. */ #define RTE_MEMZONE_16GB 0x00000200 /**< Use 16GB pages. */ #define RTE_MEMZONE_256KB 0x00010000 /**< Use 256KB pages. */ #define RTE_MEMZONE_256MB 0x00020000 /**< Use 256MB pages. */ #define RTE_MEMZONE_512MB 0x00040000 /**< Use 512MB pages. */ #define RTE_MEMZONE_4GB 0x00080000 /**< Use 4GB pages. */ #define RTE_MEMZONE_SIZE_HINT_ONLY 0x00000004 /**< Use available page size */ /** * A structure describing a memzone, which is a contiguous portion of * physical memory identified by a name. */ struct rte_memzone { #define RTE_MEMZONE_NAMESIZE 32 /**< Maximum length of memory zone name.*/ char name[RTE_MEMZONE_NAMESIZE]; /**< Name of the memory zone. */ phys_addr_t phys_addr; /**< Start physical address. */ union { void *addr; /**< Start virtual address. */ uint64_t addr_64; /**< Makes sure addr is always 64-bits */ }; #ifdef RTE_LIBRTE_IVSHMEM phys_addr_t ioremap_addr; /**< Real physical address inside the VM */ #endif size_t len; /**< Length of the memzone. */ uint64_t hugepage_sz; /**< The page size of underlying memory */ int32_t socket_id; /**< NUMA socket ID. */ uint32_t flags; /**< Characteristics of this memzone. */ uint32_t memseg_id; /** #include #include #include #include #include #include #include TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */ TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */ extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */ extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */ /** Pathname of PCI devices directory. */ #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" /** Formatting string for PCI device identifier: Ex: 0000:00:01.0 */ #define PCI_PRI_FMT "%.4" PRIx16 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8 /** Short formatting string, without domain, for PCI device: Ex: 00:01.0 */ #define PCI_SHORT_PRI_FMT "%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8 /** Nb. of values in PCI device identifier format string. */ #define PCI_FMT_NVAL 4 /** Nb. of values in PCI resource format. */ #define PCI_RESOURCE_FMT_NVAL 3 /** IO resource type: memory address space */ #define IORESOURCE_MEM 0x00000200 /** * A structure describing a PCI resource. */ struct rte_pci_resource { uint64_t phys_addr; /**< Physical address, 0 if no resource. */ uint64_t len; /**< Length of the resource. */ void *addr; /**< Virtual address, NULL when not mapped. */ }; /** Maximum number of PCI resources. */ #define PCI_MAX_RESOURCE 6 /** * A structure describing an ID for a PCI driver. Each driver provides a * table of these IDs for each device that it supports. */ struct rte_pci_id { uint16_t vendor_id; /**< Vendor ID or PCI_ANY_ID. */ uint16_t device_id; /**< Device ID or PCI_ANY_ID. */ uint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */ uint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */ }; /** * A structure describing the location of a PCI device. */ struct rte_pci_addr { uint16_t domain; /**< Device domain */ uint8_t bus; /**< Device bus */ uint8_t devid; /**< Device ID */ uint8_t function; /**< Device function. */ }; struct rte_devargs; enum rte_kernel_driver { RTE_KDRV_UNKNOWN = 0, RTE_KDRV_IGB_UIO, RTE_KDRV_VFIO, RTE_KDRV_UIO_GENERIC, RTE_KDRV_NIC_UIO, }; /** * A structure describing a PCI device. */ struct rte_pci_device { TAILQ_ENTRY(rte_pci_device) next; /**< Next probed PCI device. */ struct rte_pci_addr addr; /**< PCI location. */ struct rte_pci_id id; /**< PCI ID. */ struct rte_pci_resource mem_resource[PCI_MAX_RESOURCE]; /**< PCI Memory Resource */ struct rte_intr_handle intr_handle; /**< Interrupt handle */ struct rte_pci_driver *driver; /**< Associated driver */ uint16_t max_vfs; /**< sriov enable if not zero */ int numa_node; /**< NUMA node connection */ struct rte_devargs *devargs; /**< Device user arguments */ enum rte_kernel_driver kdrv; /**< Kernel driver passthrough */ }; /** Any PCI device identifier (vendor, device, ...) */ #define PCI_ANY_ID (0xffff) #ifdef __cplusplus /** C++ macro used to help building up tables of device IDs */ #define RTE_PCI_DEVICE(vend, dev) \ (vend), \ (dev), \ PCI_ANY_ID, \ PCI_ANY_ID #else /** Macro used to help building up tables of device IDs */ #define RTE_PCI_DEVICE(vend, dev) \ .vendor_id = (vend), \ .device_id = (dev), \ .subsystem_vendor_id = PCI_ANY_ID, \ .subsystem_device_id = PCI_ANY_ID #endif struct rte_pci_driver; /** * Initialisation function for the driver called during PCI probing. */ typedef int (pci_devinit_t)(struct rte_pci_driver *, struct rte_pci_device *); /** * Uninitialisation function for the driver called during hotplugging. */ typedef int (pci_devuninit_t)(struct rte_pci_device *); /** * A structure describing a PCI driver. */ struct rte_pci_driver { TAILQ_ENTRY(rte_pci_driver) next; /**< Next in list. */ const char *name; /**< Driver name. */ pci_devinit_t *devinit; /**< Device init. function. */ pci_devuninit_t *devuninit; /**< Device uninit function. */ const struct rte_pci_id *id_table; /**< ID table, NULL terminated. */ uint32_t drv_flags; /**< Flags contolling handling of device. */ }; /** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */ #define RTE_PCI_DRV_NEED_MAPPING 0x0001 /** Device driver must be registered several times until failure - deprecated */ #pragma GCC poison RTE_PCI_DRV_MULTIPLE /** Device needs to be unbound even if no module is provided */ #define RTE_PCI_DRV_FORCE_UNBIND 0x0004 /** Device driver supports link state interrupt */ #define RTE_PCI_DRV_INTR_LSC 0x0008 /** Device driver supports detaching capability */ #define RTE_PCI_DRV_DETACHABLE 0x0010 /** * A structure describing a PCI mapping. */ struct pci_map { void *addr; char *path; uint64_t offset; uint64_t size; uint64_t phaddr; }; /** * A structure describing a mapped PCI resource. * For multi-process we need to reproduce all PCI mappings in secondary * processes, so save them in a tailq. */ struct mapped_pci_resource { TAILQ_ENTRY(mapped_pci_resource) next; struct rte_pci_addr pci_addr; char path[PATH_MAX]; int nb_maps; struct pci_map maps[PCI_MAX_RESOURCE]; }; /** mapped pci device list */ TAILQ_HEAD(mapped_pci_res_list, mapped_pci_resource); /**< Internal use only - Macro used by pci addr parsing functions **/ #define GET_PCIADDR_FIELD(in, fd, lim, dlm) \ do { \ unsigned long val; \ char *end; \ errno = 0; \ val = strtoul((in), &end, 16); \ if (errno != 0 || end[0] != (dlm) || val > (lim)) \ return -EINVAL; \ (fd) = (typeof (fd))val; \ (in) = end + 1; \ } while(0) /** * Utility function to produce a PCI Bus-Device-Function value * given a string representation. Assumes that the BDF is provided without * a domain prefix (i.e. domain returned is always 0) * * @param input * The input string to be parsed. Should have the format XX:XX.X * @param dev_addr * The PCI Bus-Device-Function address to be returned. Domain will always be * returned as 0 * @return * 0 on success, negative on error. */ static inline int eal_parse_pci_BDF(const char *input, struct rte_pci_addr *dev_addr) { dev_addr->domain = 0; GET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':'); GET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.'); GET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0); return 0; } /** * Utility function to produce a PCI Bus-Device-Function value * given a string representation. Assumes that the BDF is provided including * a domain prefix. * * @param input * The input string to be parsed. Should have the format XXXX:XX:XX.X * @param dev_addr * The PCI Bus-Device-Function address to be returned * @return * 0 on success, negative on error. */ static inline int eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr) { GET_PCIADDR_FIELD(input, dev_addr->domain, UINT16_MAX, ':'); GET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':'); GET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.'); GET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0); return 0; } #undef GET_PCIADDR_FIELD /* Compare two PCI device addresses. */ /** * Utility function to compare two PCI device addresses. * * @param addr * The PCI Bus-Device-Function address to compare * @param addr2 * The PCI Bus-Device-Function address to compare * @return * 0 on equal PCI address. * Positive on addr is greater than addr2. * Negative on addr is less than addr2, or error. */ static inline int rte_eal_compare_pci_addr(const struct rte_pci_addr *addr, const struct rte_pci_addr *addr2) { uint64_t dev_addr, dev_addr2; if ((addr == NULL) || (addr2 == NULL)) return -1; dev_addr = (addr->domain << 24) | (addr->bus << 16) | (addr->devid << 8) | addr->function; dev_addr2 = (addr2->domain << 24) | (addr2->bus << 16) | (addr2->devid << 8) | addr2->function; if (dev_addr > dev_addr2) return 1; else if (dev_addr < dev_addr2) return -1; else return 0; } /** * Scan the content of the PCI bus, and the devices in the devices * list * * @return * 0 on success, negative on error */ int rte_eal_pci_scan(void); /** * Probe the PCI bus for registered drivers. * * Scan the content of the PCI bus, and call the probe() function for * all registered drivers that have a matching entry in its id_table * for discovered devices. * * @return * - 0 on success. * - Negative on error. */ int rte_eal_pci_probe(void); /** * @internal * Map a particular resource from a file. * * @param requested_addr * The starting address for the new mapping range. * @param fd * The file descriptor. * @param offset * The offset for the mapping range. * @param size * The size for the mapping range. * @param additional_flags * The additional flags for the mapping range. * @return * - On success, the function returns a pointer to the mapped area. * - On error, the value MAP_FAILED is returned. */ void *pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size, int additional_flags); /** * @internal * Unmap a particular resource. * * @param requested_addr * The address for the unmapping range. * @param size * The size for the unmapping range. */ void pci_unmap_resource(void *requested_addr, size_t size); /** * Probe the single PCI device. * * Scan the content of the PCI bus, and find the pci device specified by pci * address, then call the probe() function for registered driver that has a * matching entry in its id_table for discovered device. * * @param addr * The PCI Bus-Device-Function address to probe. * @return * - 0 on success. * - Negative on error. */ int rte_eal_pci_probe_one(const struct rte_pci_addr *addr); /** * Close the single PCI device. * * Scan the content of the PCI bus, and find the pci device specified by pci * address, then call the devuninit() function for registered driver that has a * matching entry in its id_table for discovered device. * * @param addr * The PCI Bus-Device-Function address to close. * @return * - 0 on success. * - Negative on error. */ int rte_eal_pci_detach(const struct rte_pci_addr *addr); int __attribute__ ((deprecated)) rte_eal_pci_close_one(const struct rte_pci_addr *addr); /** * Dump the content of the PCI bus. * * @param f * A pointer to a file for output */ void rte_eal_pci_dump(FILE *f); /** * Register a PCI driver. * * @param driver * A pointer to a rte_pci_driver structure describing the driver * to be registered. */ void rte_eal_pci_register(struct rte_pci_driver *driver); /** * Unregister a PCI driver. * * @param driver * A pointer to a rte_pci_driver structure describing the driver * to be unregistered. */ void rte_eal_pci_unregister(struct rte_pci_driver *driver); /** * Read PCI config space. * * @param device * A pointer to a rte_pci_device structure describing the device * to use * @param buf * A data buffer where the bytes should be read into * @param len * The length of the data buffer. * @param offset * The offset into PCI config space */ int rte_eal_pci_read_config(const struct rte_pci_device *device, void *buf, size_t len, off_t offset); /** * Write PCI config space. * * @param device * A pointer to a rte_pci_device structure describing the device * to use * @param buf * A data buffer containing the bytes should be written * @param len * The length of the data buffer. * @param offset * The offset into PCI config space */ int rte_eal_pci_write_config(const struct rte_pci_device *device, const void *buf, size_t len, off_t offset); #ifdef RTE_PCI_CONFIG /** * Set special config space registers for performance purpose. * * @param dev * A pointer to a rte_pci_device structure describing the device * to use */ void pci_config_space_set(struct rte_pci_device *dev); #endif /* RTE_PCI_CONFIG */ #ifdef __cplusplus } #endif #endif /* _RTE_PCI_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_pci_dev_feature_defs.h ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PCI_DEV_DEFS_H_ #define _RTE_PCI_DEV_DEFS_H_ /* interrupt mode */ enum rte_intr_mode { RTE_INTR_MODE_NONE = 0, RTE_INTR_MODE_LEGACY, RTE_INTR_MODE_MSI, RTE_INTR_MODE_MSIX }; #endif /* _RTE_PCI_DEV_DEFS_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_pci_dev_features.h ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PCI_DEV_FEATURES_H #define _RTE_PCI_DEV_FEATURES_H #include #define RTE_INTR_MODE_NONE_NAME "none" #define RTE_INTR_MODE_LEGACY_NAME "legacy" #define RTE_INTR_MODE_MSI_NAME "msi" #define RTE_INTR_MODE_MSIX_NAME "msix" #endif ================================================ FILE: lib/librte_eal/common/include/rte_pci_dev_ids.h ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** * @file * * This file contains a list of the PCI device IDs recognised by DPDK, which * can be used to fill out an array of structures describing the devices. * * Currently four families of devices are recognised: those supported by the * IGB driver, by EM driver, those supported by the IXGBE driver, and by virtio * driver which is a para virtualization driver running in guest virtual machine. * The inclusion of these in an array built using this file depends on the * definition of * RTE_PCI_DEV_ID_DECL_EM * RTE_PCI_DEV_ID_DECL_IGB * RTE_PCI_DEV_ID_DECL_IGBVF * RTE_PCI_DEV_ID_DECL_IXGBE * RTE_PCI_DEV_ID_DECL_IXGBEVF * RTE_PCI_DEV_ID_DECL_I40E * RTE_PCI_DEV_ID_DECL_I40EVF * RTE_PCI_DEV_ID_DECL_VIRTIO * at the time when this file is included. * * In order to populate an array, the user of this file must define this macro: * RTE_PCI_DEV_ID_DECL_IXGBE(vendorID, deviceID). For example: * * @code * struct device { * int vend; * int dev; * }; * * struct device devices[] = { * #define RTE_PCI_DEV_ID_DECL_IXGBE(vendorID, deviceID) {vend, dev}, * #include * }; * @endcode * * Note that this file can be included multiple times within the same file. */ #ifndef RTE_PCI_DEV_ID_DECL_EM #define RTE_PCI_DEV_ID_DECL_EM(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_IGB #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_IGBVF #define RTE_PCI_DEV_ID_DECL_IGBVF(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_IXGBE #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_IXGBEVF #define RTE_PCI_DEV_ID_DECL_IXGBEVF(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_I40E #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_I40EVF #define RTE_PCI_DEV_ID_DECL_I40EVF(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_VIRTIO #define RTE_PCI_DEV_ID_DECL_VIRTIO(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_VMXNET3 #define RTE_PCI_DEV_ID_DECL_VMXNET3(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_FM10K #define RTE_PCI_DEV_ID_DECL_FM10K(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_FM10KVF #define RTE_PCI_DEV_ID_DECL_FM10KVF(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_ENIC #define RTE_PCI_DEV_ID_DECL_ENIC(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_BNX2X #define RTE_PCI_DEV_ID_DECL_BNX2X(vend, dev) #endif #ifndef RTE_PCI_DEV_ID_DECL_BNX2XVF #define RTE_PCI_DEV_ID_DECL_BNX2XVF(vend, dev) #endif #ifndef PCI_VENDOR_ID_INTEL /** Vendor ID used by Intel devices */ #define PCI_VENDOR_ID_INTEL 0x8086 #endif #ifndef PCI_VENDOR_ID_QUMRANET /** Vendor ID used by virtio devices */ #define PCI_VENDOR_ID_QUMRANET 0x1AF4 #endif #ifndef PCI_VENDOR_ID_VMWARE /** Vendor ID used by VMware devices */ #define PCI_VENDOR_ID_VMWARE 0x15AD #endif #ifndef PCI_VENDOR_ID_CISCO /** Vendor ID used by Cisco VIC devices */ #define PCI_VENDOR_ID_CISCO 0x1137 #endif #ifndef PCI_VENDOR_ID_BROADCOM /** Vendor ID used by Broadcom devices */ #define PCI_VENDOR_ID_BROADCOM 0x14E4 #endif /******************** Physical EM devices from e1000_hw.h ********************/ #define E1000_DEV_ID_82542 0x1000 #define E1000_DEV_ID_82543GC_FIBER 0x1001 #define E1000_DEV_ID_82543GC_COPPER 0x1004 #define E1000_DEV_ID_82544EI_COPPER 0x1008 #define E1000_DEV_ID_82544EI_FIBER 0x1009 #define E1000_DEV_ID_82544GC_COPPER 0x100C #define E1000_DEV_ID_82544GC_LOM 0x100D #define E1000_DEV_ID_82540EM 0x100E #define E1000_DEV_ID_82540EM_LOM 0x1015 #define E1000_DEV_ID_82540EP_LOM 0x1016 #define E1000_DEV_ID_82540EP 0x1017 #define E1000_DEV_ID_82540EP_LP 0x101E #define E1000_DEV_ID_82545EM_COPPER 0x100F #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82545GM_COPPER 0x1026 #define E1000_DEV_ID_82545GM_FIBER 0x1027 #define E1000_DEV_ID_82545GM_SERDES 0x1028 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82546GB_COPPER 0x1079 #define E1000_DEV_ID_82546GB_FIBER 0x107A #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A #define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 #define E1000_DEV_ID_82541EI 0x1013 #define E1000_DEV_ID_82541EI_MOBILE 0x1018 #define E1000_DEV_ID_82541ER_LOM 0x1014 #define E1000_DEV_ID_82541ER 0x1078 #define E1000_DEV_ID_82541GI 0x1076 #define E1000_DEV_ID_82541GI_LF 0x107C #define E1000_DEV_ID_82541GI_MOBILE 0x1077 #define E1000_DEV_ID_82547EI 0x1019 #define E1000_DEV_ID_82547EI_MOBILE 0x101A #define E1000_DEV_ID_82547GI 0x1075 #define E1000_DEV_ID_82571EB_COPPER 0x105E #define E1000_DEV_ID_82571EB_FIBER 0x105F #define E1000_DEV_ID_82571EB_SERDES 0x1060 #define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 #define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 #define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 #define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 #define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F #define E1000_DEV_ID_82572EI 0x10B9 #define E1000_DEV_ID_82573E 0x108B #define E1000_DEV_ID_82573E_IAMT 0x108C #define E1000_DEV_ID_82573L 0x109A #define E1000_DEV_ID_82574L 0x10D3 #define E1000_DEV_ID_82574LA 0x10F6 #define E1000_DEV_ID_82583V 0x150C #define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 #define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA #define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB #define E1000_DEV_ID_ICH8_82567V_3 0x1501 #define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 #define E1000_DEV_ID_ICH8_IGP_AMT 0x104A #define E1000_DEV_ID_ICH8_IGP_C 0x104B #define E1000_DEV_ID_ICH8_IFE 0x104C #define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 #define E1000_DEV_ID_ICH8_IFE_G 0x10C5 #define E1000_DEV_ID_ICH8_IGP_M 0x104D #define E1000_DEV_ID_ICH9_IGP_M 0x10BF #define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 #define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB #define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD #define E1000_DEV_ID_ICH9_BM 0x10E5 #define E1000_DEV_ID_ICH9_IGP_C 0x294C #define E1000_DEV_ID_ICH9_IFE 0x10C0 #define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 #define E1000_DEV_ID_ICH9_IFE_G 0x10C2 #define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC #define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD #define E1000_DEV_ID_ICH10_R_BM_V 0x10CE #define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE #define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF #define E1000_DEV_ID_ICH10_D_BM_V 0x1525 #define E1000_DEV_ID_PCH_M_HV_LM 0x10EA #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_DEV_ID_PCH2_LV_LM 0x1502 #define E1000_DEV_ID_PCH2_LV_V 0x1503 #define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A #define E1000_DEV_ID_PCH_LPT_I217_V 0x153B #define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A #define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 /* * Tested (supported) on VM emulated HW. */ RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82540EM) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82545EM_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82545EM_FIBER) /* * Tested (supported) on real HW. */ RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82546EB_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82546EB_FIBER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82546EB_QUAD_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_FIBER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_COPPER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_FIBER) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI_SERDES) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82572EI) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82573L) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82574L) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82574LA) RTE_PCI_DEV_ID_DECL_EM(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82583V) /******************** Physical IGB devices from e1000_hw.h ********************/ #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526 #define E1000_DEV_ID_82576_NS 0x150A #define E1000_DEV_ID_82576_NS_SERDES 0x1518 #define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 #define E1000_DEV_ID_82580_COPPER 0x150E #define E1000_DEV_ID_82580_FIBER 0x150F #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 #define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 #define E1000_DEV_ID_I350_COPPER 0x1521 #define E1000_DEV_ID_I350_FIBER 0x1522 #define E1000_DEV_ID_I350_SERDES 0x1523 #define E1000_DEV_ID_I350_SGMII 0x1524 #define E1000_DEV_ID_I350_DA4 0x1546 #define E1000_DEV_ID_I210_COPPER 0x1533 #define E1000_DEV_ID_I210_COPPER_OEM1 0x1534 #define E1000_DEV_ID_I210_COPPER_IT 0x1535 #define E1000_DEV_ID_I210_FIBER 0x1536 #define E1000_DEV_ID_I210_SERDES 0x1537 #define E1000_DEV_ID_I210_SGMII 0x1538 #define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B #define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C #define E1000_DEV_ID_I211_COPPER 0x1539 #define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40 #define E1000_DEV_ID_I354_SGMII 0x1F41 #define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45 #define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C #define E1000_DEV_ID_DH89XXCC_SFP 0x0440 RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_FIBER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_NS_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_SERDES_QUAD) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_FIBER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_SGMII) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_COPPER_DUAL) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82580_QUAD_FIBER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_FIBER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_SGMII) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_DA4) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER_OEM1) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_COPPER_IT) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_FIBER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I210_SGMII) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I211_COPPER) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I354_SGMII) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SGMII) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SERDES) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE) RTE_PCI_DEV_ID_DECL_IGB(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_DH89XXCC_SFP) /****************** Physical IXGBE devices from ixgbe_type.h ******************/ #define IXGBE_DEV_ID_82598 0x10B6 #define IXGBE_DEV_ID_82598_BX 0x1508 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT 0x10C8 #define IXGBE_DEV_ID_82598AT2 0x150B #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC #define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 #define IXGBE_DEV_ID_82599_KR 0x1517 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_SUBDEV_ID_82599_RNDC 0x1F72 #define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0 #define IXGBE_SUBDEV_ID_82599_ECNA_DP 0x0470 #define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A #define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_SFP_SF2 0x154D #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A #define IXGBE_DEV_ID_82599_QSFP_SF_QP 0x1558 #define IXGBE_DEV_ID_82599EN_SFP 0x1557 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_T3_LOM 0x151C #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_X540T1 0x1560 #define IXGBE_DEV_ID_X550EM_X_SFP 0x15AC #define IXGBE_DEV_ID_X550EM_X_10G_T 0x15AD #define IXGBE_DEV_ID_X550EM_X_1G_T 0x15AE #define IXGBE_DEV_ID_X550T 0x1563 #define IXGBE_DEV_ID_X550EM_X_KX4 0x15AA #define IXGBE_DEV_ID_X550EM_X_KR 0x15AB #ifdef RTE_NIC_BYPASS #define IXGBE_DEV_ID_82599_BYPASS 0x155D #endif RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598_BX) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, \ IXGBE_DEV_ID_82598AF_SINGLE_PORT) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598AT) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598AT2) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598EB_CX4) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, \ IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82598EB_XF_LR) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_KX4) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_KR) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, \ IXGBE_DEV_ID_82599_COMBO_BACKPLANE) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, \ IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_CX4) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_SFP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_SUBDEV_ID_82599_SFP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_SUBDEV_ID_82599_RNDC) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_SUBDEV_ID_82599_560FLR) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_SUBDEV_ID_82599_ECNA_DP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_SFP_FCOE) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_SFP_EM) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_SFP_SF2) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_QSFP_SF_QP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599EN_SFP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_XAUI_LOM) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_T3_LOM) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_LS) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540T) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540T1) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_SFP) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_10G_T) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_1G_T) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550T) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_KX4) RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_KR) #ifdef RTE_NIC_BYPASS RTE_PCI_DEV_ID_DECL_IXGBE(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_BYPASS) #endif /*************** Physical I40E devices from i40e_type.h *****************/ #define I40E_DEV_ID_SFP_XL710 0x1572 #define I40E_DEV_ID_QEMU 0x1574 #define I40E_DEV_ID_KX_A 0x157F #define I40E_DEV_ID_KX_B 0x1580 #define I40E_DEV_ID_KX_C 0x1581 #define I40E_DEV_ID_QSFP_A 0x1583 #define I40E_DEV_ID_QSFP_B 0x1584 #define I40E_DEV_ID_QSFP_C 0x1585 #define I40E_DEV_ID_10G_BASE_T 0x1586 RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_SFP_XL710) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_QEMU) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_KX_A) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_KX_B) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_KX_C) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_QSFP_A) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_QSFP_B) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_QSFP_C) RTE_PCI_DEV_ID_DECL_I40E(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_10G_BASE_T) /*************** Physical FM10K devices from fm10k_type.h ***************/ #define FM10K_DEV_ID_PF 0x15A4 RTE_PCI_DEV_ID_DECL_FM10K(PCI_VENDOR_ID_INTEL, FM10K_DEV_ID_PF) /****************** Virtual IGB devices from e1000_hw.h ******************/ #define E1000_DEV_ID_82576_VF 0x10CA #define E1000_DEV_ID_82576_VF_HV 0x152D #define E1000_DEV_ID_I350_VF 0x1520 #define E1000_DEV_ID_I350_VF_HV 0x152F RTE_PCI_DEV_ID_DECL_IGBVF(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF) RTE_PCI_DEV_ID_DECL_IGBVF(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF_HV) RTE_PCI_DEV_ID_DECL_IGBVF(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_VF) RTE_PCI_DEV_ID_DECL_IGBVF(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_I350_VF_HV) /****************** Virtual IXGBE devices from ixgbe_type.h ******************/ #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_82599_VF_HV 0x152E #define IXGBE_DEV_ID_X540_VF 0x1515 #define IXGBE_DEV_ID_X540_VF_HV 0x1530 #define IXGBE_DEV_ID_X550_VF_HV 0x1564 #define IXGBE_DEV_ID_X550_VF 0x1565 #define IXGBE_DEV_ID_X550EM_X_VF 0x15A8 #define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9 RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_VF) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_82599_VF_HV) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540_VF) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X540_VF_HV) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550_VF_HV) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550_VF) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_VF) RTE_PCI_DEV_ID_DECL_IXGBEVF(PCI_VENDOR_ID_INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV) /****************** Virtual I40E devices from i40e_type.h ********************/ #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 RTE_PCI_DEV_ID_DECL_I40EVF(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_VF) RTE_PCI_DEV_ID_DECL_I40EVF(PCI_VENDOR_ID_INTEL, I40E_DEV_ID_VF_HV) /****************** Virtio devices from virtio.h ******************/ #define QUMRANET_DEV_ID_VIRTIO 0x1000 RTE_PCI_DEV_ID_DECL_VIRTIO(PCI_VENDOR_ID_QUMRANET, QUMRANET_DEV_ID_VIRTIO) /****************** VMware VMXNET3 devices ******************/ #define VMWARE_DEV_ID_VMXNET3 0x07B0 RTE_PCI_DEV_ID_DECL_VMXNET3(PCI_VENDOR_ID_VMWARE, VMWARE_DEV_ID_VMXNET3) /*************** Virtual FM10K devices from fm10k_type.h ***************/ #define FM10K_DEV_ID_VF 0x15A5 RTE_PCI_DEV_ID_DECL_FM10KVF(PCI_VENDOR_ID_INTEL, FM10K_DEV_ID_VF) /****************** Cisco VIC devices ******************/ #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ #define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ RTE_PCI_DEV_ID_DECL_ENIC(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) RTE_PCI_DEV_ID_DECL_ENIC(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) /****************** QLogic devices ******************/ /* Broadcom/QLogic BNX2X */ #define BNX2X_DEV_ID_57710 0x164e #define BNX2X_DEV_ID_57711 0x164f #define BNX2X_DEV_ID_57711E 0x1650 #define BNX2X_DEV_ID_57712 0x1662 #define BNX2X_DEV_ID_57712_MF 0x1663 #define BNX2X_DEV_ID_57712_VF 0x166f #define BNX2X_DEV_ID_57713 0x1651 #define BNX2X_DEV_ID_57713E 0x1652 #define BNX2X_DEV_ID_57800 0x168a #define BNX2X_DEV_ID_57800_MF 0x16a5 #define BNX2X_DEV_ID_57800_VF 0x16a9 #define BNX2X_DEV_ID_57810 0x168e #define BNX2X_DEV_ID_57810_MF 0x16ae #define BNX2X_DEV_ID_57810_VF 0x16af #define BNX2X_DEV_ID_57811 0x163d #define BNX2X_DEV_ID_57811_MF 0x163e #define BNX2X_DEV_ID_57811_VF 0x163f #define BNX2X_DEV_ID_57840_OBS 0x168d #define BNX2X_DEV_ID_57840_OBS_MF 0x16ab #define BNX2X_DEV_ID_57840_4_10 0x16a1 #define BNX2X_DEV_ID_57840_2_20 0x16a2 #define BNX2X_DEV_ID_57840_MF 0x16a4 #define BNX2X_DEV_ID_57840_VF 0x16ad RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57800) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57800_VF) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57711) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57810) RTE_PCI_DEV_ID_DECL_BNX2XVF(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57810_VF) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57811) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57811_VF) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_OBS) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_4_10) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_2_20) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_VF) #ifdef RTE_LIBRTE_BNX2X_MF_SUPPORT RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57810_MF) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57811_MF) RTE_PCI_DEV_ID_DECL_BNX2X(PCI_VENDOR_ID_BROADCOM, BNX2X_DEV_ID_57840_MF) #endif /* * Undef all RTE_PCI_DEV_ID_DECL_* here. */ #undef RTE_PCI_DEV_ID_DECL_BNX2X #undef RTE_PCI_DEV_ID_DECL_BNX2XVF #undef RTE_PCI_DEV_ID_DECL_EM #undef RTE_PCI_DEV_ID_DECL_IGB #undef RTE_PCI_DEV_ID_DECL_IGBVF #undef RTE_PCI_DEV_ID_DECL_IXGBE #undef RTE_PCI_DEV_ID_DECL_IXGBEVF #undef RTE_PCI_DEV_ID_DECL_I40E #undef RTE_PCI_DEV_ID_DECL_I40EVF #undef RTE_PCI_DEV_ID_DECL_VIRTIO #undef RTE_PCI_DEV_ID_DECL_VMXNET3 #undef RTE_PCI_DEV_ID_DECL_FM10K #undef RTE_PCI_DEV_ID_DECL_FM10KVF ================================================ FILE: lib/librte_eal/common/include/rte_per_lcore.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_PER_LCORE_H_ #define _RTE_PER_LCORE_H_ /** * @file * * Per-lcore variables in RTE * * This file defines an API for instantiating per-lcore "global * variables" that are environment-specific. Note that in all * environments, a "shared variable" is the default when you use a * global variable. * * Parts of this are execution environment specific. */ #ifdef __cplusplus extern "C" { #endif #include /** * Macro to define a per lcore variable "var" of type "type", don't * use keywords like "static" or "volatile" in type, just prefix the * whole macro. */ #define RTE_DEFINE_PER_LCORE(type, name) \ __thread __typeof__(type) per_lcore_##name /** * Macro to declare an extern per lcore variable "var" of type "type" */ #define RTE_DECLARE_PER_LCORE(type, name) \ extern __thread __typeof__(type) per_lcore_##name /** * Read/write the per-lcore variable value */ #define RTE_PER_LCORE(name) (per_lcore_##name) #ifdef __cplusplus } #endif #endif /* _RTE_PER_LCORE_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_random.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_RANDOM_H_ #define _RTE_RANDOM_H_ /** * @file * * Pseudo-random Generators in RTE */ #ifdef __cplusplus extern "C" { #endif #include #include /** * Seed the pseudo-random generator. * * The generator is automatically seeded by the EAL init with a timer * value. It may need to be re-seeded by the user with a real random * value. * * @param seedval * The value of the seed. */ static inline void rte_srand(uint64_t seedval) { srand48((long unsigned int)seedval); } /** * Get a pseudo-random value. * * This function generates pseudo-random numbers using the linear * congruential algorithm and 48-bit integer arithmetic, called twice * to generate a 64-bit value. * * @return * A pseudo-random value between 0 and (1<<64)-1. */ static inline uint64_t rte_rand(void) { uint64_t val; val = lrand48(); val <<= 32; val += lrand48(); return val; } #ifdef __cplusplus } #endif #endif /* _RTE_PER_LCORE_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_string_fns.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * * String-related functions as replacement for libc equivalents */ #ifndef _RTE_STRING_FNS_H_ #define _RTE_STRING_FNS_H_ #ifdef __cplusplus extern "C" { #endif /** * Takes string "string" parameter and splits it at character "delim" * up to maxtokens-1 times - to give "maxtokens" resulting tokens. Like * strtok or strsep functions, this modifies its input string, by replacing * instances of "delim" with '\\0'. All resultant tokens are returned in the * "tokens" array which must have enough entries to hold "maxtokens". * * @param string * The input string to be split into tokens * * @param stringlen * The max length of the input buffer * * @param tokens * The array to hold the pointers to the tokens in the string * * @param maxtokens * The number of elements in the tokens array. At most, maxtokens-1 splits * of the string will be done. * * @param delim * The character on which the split of the data will be done * * @return * The number of tokens in the tokens array. */ int rte_strsplit(char *string, int stringlen, char **tokens, int maxtokens, char delim); #ifdef __cplusplus } #endif #endif /* RTE_STRING_FNS_H */ ================================================ FILE: lib/librte_eal/common/include/rte_tailq.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_TAILQ_H_ #define _RTE_TAILQ_H_ /** * @file * Here defines rte_tailq APIs for only internal use * */ #ifdef __cplusplus extern "C" { #endif #include #include #include /** dummy structure type used by the rte_tailq APIs */ struct rte_tailq_entry { TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */ void *data; /**< Pointer to the data referenced by this tailq entry */ }; /** dummy */ TAILQ_HEAD(rte_tailq_entry_head, rte_tailq_entry); #define RTE_TAILQ_NAMESIZE 32 /** * The structure defining a tailq header entry for storing * in the rte_config structure in shared memory. Each tailq * is identified by name. * Any library storing a set of objects e.g. rings, mempools, hash-tables, * is recommended to use an entry here, so as to make it easy for * a multi-process app to find already-created elements in shared memory. */ struct rte_tailq_head { struct rte_tailq_entry_head tailq_head; /**< NOTE: must be first element */ char name[RTE_TAILQ_NAMESIZE]; }; struct rte_tailq_elem { /** * Reference to head in shared mem, updated at init time by * rte_eal_tailqs_init() */ struct rte_tailq_head *head; TAILQ_ENTRY(rte_tailq_elem) next; const char name[RTE_TAILQ_NAMESIZE]; }; /** * Return the first tailq entry casted to the right struct. */ #define RTE_TAILQ_CAST(tailq_entry, struct_name) \ (struct struct_name *)&(tailq_entry)->tailq_head /** * Utility macro to make looking up a tailqueue for a particular struct easier. * * @param name * The name of tailq * * @param struct_name * The name of the list type we are using. (Generally this is the same as the * first parameter passed to TAILQ_HEAD macro) * * @return * The return value from rte_eal_tailq_lookup, typecast to the appropriate * structure pointer type. * NULL on error, since the tailq_head is the first * element in the rte_tailq_head structure. */ #define RTE_TAILQ_LOOKUP(name, struct_name) \ RTE_TAILQ_CAST(rte_eal_tailq_lookup(name), struct_name) /** * Dump tail queues to the console. * * @param f * A pointer to a file for output */ void rte_dump_tailq(FILE *f); /** * Lookup for a tail queue. * * Get a pointer to a tail queue header of a tail * queue identified by the name given as an argument. * Note: this function is not multi-thread safe, and should only be called from * a single thread at a time * * @param name * The name of the queue. * @return * A pointer to the tail queue head structure. */ struct rte_tailq_head *rte_eal_tailq_lookup(const char *name); /** * Register a tail queue. * * Register a tail queue from shared memory. * This function is mainly used by EAL_REGISTER_TAILQ macro which is used to * register tailq from the different dpdk libraries. Since this macro is a * constructor, the function has no access to dpdk shared memory, so the * registered tailq can not be used before call to rte_eal_init() which calls * rte_eal_tailqs_init(). * * @param t * The tailq element which contains the name of the tailq you want to * create (/retrieve when in secondary process). * @return * 0 on success or -1 in case of an error. */ int rte_eal_tailq_register(struct rte_tailq_elem *t); #define EAL_REGISTER_TAILQ(t) \ void tailqinitfn_ ##t(void); \ void __attribute__((constructor, used)) tailqinitfn_ ##t(void) \ { \ if (rte_eal_tailq_register(&t) < 0) \ rte_panic("Cannot initialize tailq: %s\n", t.name); \ } #ifdef __cplusplus } #endif #endif /* _RTE_TAILQ_H_ */ ================================================ FILE: lib/librte_eal/common/include/rte_version.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Definitions of Intel(R) DPDK version numbers */ #ifndef _RTE_VERSION_H_ #define _RTE_VERSION_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include /** * String that appears before the version number */ #define RTE_VER_PREFIX "RTE" /** * Major version number i.e. the x in x.y.z */ #define RTE_VER_MAJOR 2 /** * Minor version number i.e. the y in x.y.z */ #define RTE_VER_MINOR 1 /** * Patch level number i.e. the z in x.y.z */ #define RTE_VER_PATCH_LEVEL 0 /** * Extra string to be appended to version number */ #define RTE_VER_SUFFIX "" /** * Patch release number * 0-15 = release candidates * 16 = release */ #define RTE_VER_PATCH_RELEASE 16 /** * Macro to compute a version number usable for comparisons */ #define RTE_VERSION_NUM(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) /** * All version numbers in one to compare with RTE_VERSION_NUM() */ #define RTE_VERSION RTE_VERSION_NUM( \ RTE_VER_MAJOR, \ RTE_VER_MINOR, \ RTE_VER_PATCH_LEVEL, \ RTE_VER_PATCH_RELEASE) /** * Function returning version string * @return * string */ static inline const char * rte_version(void) { static char version[32]; if (version[0] != 0) return version; if (strlen(RTE_VER_SUFFIX) == 0) snprintf(version, sizeof(version), "%s %d.%d.%d", RTE_VER_PREFIX, RTE_VER_MAJOR, RTE_VER_MINOR, RTE_VER_PATCH_LEVEL); else snprintf(version, sizeof(version), "%s %d.%d.%d%s%d", RTE_VER_PREFIX, RTE_VER_MAJOR, RTE_VER_MINOR, RTE_VER_PATCH_LEVEL, RTE_VER_SUFFIX, RTE_VER_PATCH_RELEASE < 16 ? RTE_VER_PATCH_RELEASE : RTE_VER_PATCH_RELEASE - 16); return version; } #ifdef __cplusplus } #endif #endif /* RTE_VERSION_H */ ================================================ FILE: lib/librte_eal/common/include/rte_warnings.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @file * Definitions of warnings for use of various insecure functions */ #ifndef _RTE_WARNINGS_H_ #define _RTE_WARNINGS_H_ #ifdef RTE_INSECURE_FUNCTION_WARNING /* we need to include all used standard header files so that they appear * _before_ we poison the function names. */ #include #include #include #include #include #ifdef RTE_LIBRTE_EAL_LINUXAPP #include #endif /* the following function are deemed not fully secure for use e.g. they * do not always null-terminate arguments */ #pragma GCC poison sprintf strtok snprintf vsnprintf #pragma GCC poison strlen strcpy strcat #pragma GCC poison sscanf /* other unsafe functions may be implemented as macros so just undef them */ #ifdef strsep #undef strsep #else #pragma GCC poison strsep #endif #ifdef strncpy #undef strncpy #else #pragma GCC poison strncpy #endif #ifdef strncat #undef strncat #else #pragma GCC poison strncat #endif #endif #endif /* RTE_WARNINGS_H */ ================================================ FILE: lib/librte_eal/common/malloc_elem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "malloc_elem.h" #include "malloc_heap.h" #define MIN_DATA_SIZE (RTE_CACHE_LINE_SIZE) /* * initialise a general malloc_elem header structure */ void malloc_elem_init(struct malloc_elem *elem, struct malloc_heap *heap, const struct rte_memseg *ms, size_t size) { elem->heap = heap; elem->ms = ms; elem->prev = NULL; memset(&elem->free_list, 0, sizeof(elem->free_list)); elem->state = ELEM_FREE; elem->size = size; elem->pad = 0; set_header(elem); set_trailer(elem); } /* * initialise a dummy malloc_elem header for the end-of-memseg marker */ void malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev) { malloc_elem_init(elem, prev->heap, prev->ms, 0); elem->prev = prev; elem->state = ELEM_BUSY; /* mark busy so its never merged */ } /* * calculate the starting point of where data of the requested size * and alignment would fit in the current element. If the data doesn't * fit, return NULL. */ static void * elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align, size_t bound) { const size_t bmask = ~(bound - 1); uintptr_t end_pt = (uintptr_t)elem + elem->size - MALLOC_ELEM_TRAILER_LEN; uintptr_t new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align); uintptr_t new_elem_start; /* check boundary */ if ((new_data_start & bmask) != ((end_pt - 1) & bmask)) { end_pt = RTE_ALIGN_FLOOR(end_pt, bound); new_data_start = RTE_ALIGN_FLOOR((end_pt - size), align); if (((end_pt - 1) & bmask) != (new_data_start & bmask)) return NULL; } new_elem_start = new_data_start - MALLOC_ELEM_HEADER_LEN; /* if the new start point is before the exist start, it won't fit */ return (new_elem_start < (uintptr_t)elem) ? NULL : (void *)new_elem_start; } /* * use elem_start_pt to determine if we get meet the size and * alignment request from the current element */ int malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align, size_t bound) { return elem_start_pt(elem, size, align, bound) != NULL; } /* * split an existing element into two smaller elements at the given * split_pt parameter. */ static void split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt) { struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size); const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem; const size_t new_elem_size = elem->size - old_elem_size; malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size); split_pt->prev = elem; next_elem->prev = split_pt; elem->size = old_elem_size; set_trailer(elem); } /* * Given an element size, compute its freelist index. * We free an element into the freelist containing similarly-sized elements. * We try to allocate elements starting with the freelist containing * similarly-sized elements, and if necessary, we search freelists * containing larger elements. * * Example element size ranges for a heap with five free lists: * heap->free_head[0] - (0 , 2^8] * heap->free_head[1] - (2^8 , 2^10] * heap->free_head[2] - (2^10 ,2^12] * heap->free_head[3] - (2^12, 2^14] * heap->free_head[4] - (2^14, MAX_SIZE] */ size_t malloc_elem_free_list_index(size_t size) { #define MALLOC_MINSIZE_LOG2 8 #define MALLOC_LOG2_INCREMENT 2 size_t log2; size_t index; if (size <= (1UL << MALLOC_MINSIZE_LOG2)) return 0; /* Find next power of 2 >= size. */ log2 = sizeof(size) * 8 - __builtin_clzl(size-1); /* Compute freelist index, based on log2(size). */ index = (log2 - MALLOC_MINSIZE_LOG2 + MALLOC_LOG2_INCREMENT - 1) / MALLOC_LOG2_INCREMENT; return (index <= RTE_HEAP_NUM_FREELISTS-1? index: RTE_HEAP_NUM_FREELISTS-1); } /* * Add the specified element to its heap's free list. */ void malloc_elem_free_list_insert(struct malloc_elem *elem) { size_t idx; idx = malloc_elem_free_list_index(elem->size - MALLOC_ELEM_HEADER_LEN); elem->state = ELEM_FREE; LIST_INSERT_HEAD(&elem->heap->free_head[idx], elem, free_list); } /* * Remove the specified element from its heap's free list. */ static void elem_free_list_remove(struct malloc_elem *elem) { LIST_REMOVE(elem, free_list); } /* * reserve a block of data in an existing malloc_elem. If the malloc_elem * is much larger than the data block requested, we split the element in two. * This function is only called from malloc_heap_alloc so parameter checking * is not done here, as it's done there previously. */ struct malloc_elem * malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align, size_t bound) { struct malloc_elem *new_elem = elem_start_pt(elem, size, align, bound); const size_t old_elem_size = (uintptr_t)new_elem - (uintptr_t)elem; const size_t trailer_size = elem->size - old_elem_size - size - MALLOC_ELEM_OVERHEAD; elem_free_list_remove(elem); if (trailer_size > MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) { /* split it, too much free space after elem */ struct malloc_elem *new_free_elem = RTE_PTR_ADD(new_elem, size + MALLOC_ELEM_OVERHEAD); split_elem(elem, new_free_elem); malloc_elem_free_list_insert(new_free_elem); } if (old_elem_size < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) { /* don't split it, pad the element instead */ elem->state = ELEM_BUSY; elem->pad = old_elem_size; /* put a dummy header in padding, to point to real element header */ if (elem->pad > 0){ /* pad will be at least 64-bytes, as everything * is cache-line aligned */ new_elem->pad = elem->pad; new_elem->state = ELEM_PAD; new_elem->size = elem->size - elem->pad; set_header(new_elem); } return new_elem; } /* we are going to split the element in two. The original element * remains free, and the new element is the one allocated. * Re-insert original element, in case its new size makes it * belong on a different list. */ split_elem(elem, new_elem); new_elem->state = ELEM_BUSY; malloc_elem_free_list_insert(elem); return new_elem; } /* * joing two struct malloc_elem together. elem1 and elem2 must * be contiguous in memory. */ static inline void join_elem(struct malloc_elem *elem1, struct malloc_elem *elem2) { struct malloc_elem *next = RTE_PTR_ADD(elem2, elem2->size); elem1->size += elem2->size; next->prev = elem1; } /* * free a malloc_elem block by adding it to the free list. If the * blocks either immediately before or immediately after newly freed block * are also free, the blocks are merged together. */ int malloc_elem_free(struct malloc_elem *elem) { if (!malloc_elem_cookies_ok(elem) || elem->state != ELEM_BUSY) return -1; rte_spinlock_lock(&(elem->heap->lock)); struct malloc_elem *next = RTE_PTR_ADD(elem, elem->size); if (next->state == ELEM_FREE){ /* remove from free list, join to this one */ elem_free_list_remove(next); join_elem(elem, next); } /* check if previous element is free, if so join with it and return, * need to re-insert in free list, as that element's size is changing */ if (elem->prev != NULL && elem->prev->state == ELEM_FREE) { elem_free_list_remove(elem->prev); join_elem(elem->prev, elem); malloc_elem_free_list_insert(elem->prev); } /* otherwise add ourselves to the free list */ else { malloc_elem_free_list_insert(elem); elem->pad = 0; } /* decrease heap's count of allocated elements */ elem->heap->alloc_count--; rte_spinlock_unlock(&(elem->heap->lock)); return 0; } /* * attempt to resize a malloc_elem by expanding into any free space * immediately after it in memory. */ int malloc_elem_resize(struct malloc_elem *elem, size_t size) { const size_t new_size = size + MALLOC_ELEM_OVERHEAD; /* if we request a smaller size, then always return ok */ const size_t current_size = elem->size - elem->pad; if (current_size >= new_size) return 0; struct malloc_elem *next = RTE_PTR_ADD(elem, elem->size); rte_spinlock_lock(&elem->heap->lock); if (next ->state != ELEM_FREE) goto err_return; if (current_size + next->size < new_size) goto err_return; /* we now know the element fits, so remove from free list, * join the two */ elem_free_list_remove(next); join_elem(elem, next); if (elem->size - new_size >= MIN_DATA_SIZE + MALLOC_ELEM_OVERHEAD){ /* now we have a big block together. Lets cut it down a bit, by splitting */ struct malloc_elem *split_pt = RTE_PTR_ADD(elem, new_size); split_pt = RTE_PTR_ALIGN_CEIL(split_pt, RTE_CACHE_LINE_SIZE); split_elem(elem, split_pt); malloc_elem_free_list_insert(split_pt); } rte_spinlock_unlock(&elem->heap->lock); return 0; err_return: rte_spinlock_unlock(&elem->heap->lock); return -1; } ================================================ FILE: lib/librte_eal/common/malloc_elem.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MALLOC_ELEM_H_ #define MALLOC_ELEM_H_ #include /* dummy definition of struct so we can use pointers to it in malloc_elem struct */ struct malloc_heap; enum elem_state { ELEM_FREE = 0, ELEM_BUSY, ELEM_PAD /* element is a padding-only header */ }; struct malloc_elem { struct malloc_heap *heap; struct malloc_elem *volatile prev; /* points to prev elem in memseg */ LIST_ENTRY(malloc_elem) free_list; /* list of free elements in heap */ const struct rte_memseg *ms; volatile enum elem_state state; uint32_t pad; size_t size; #ifdef RTE_LIBRTE_MALLOC_DEBUG uint64_t header_cookie; /* Cookie marking start of data */ /* trailer cookie at start + size */ #endif } __rte_cache_aligned; #ifndef RTE_LIBRTE_MALLOC_DEBUG static const unsigned MALLOC_ELEM_TRAILER_LEN = 0; /* dummy function - just check if pointer is non-null */ static inline int malloc_elem_cookies_ok(const struct malloc_elem *elem){ return elem != NULL; } /* dummy function - no header if malloc_debug is not enabled */ static inline void set_header(struct malloc_elem *elem __rte_unused){ } /* dummy function - no trailer if malloc_debug is not enabled */ static inline void set_trailer(struct malloc_elem *elem __rte_unused){ } #else static const unsigned MALLOC_ELEM_TRAILER_LEN = RTE_CACHE_LINE_SIZE; #define MALLOC_HEADER_COOKIE 0xbadbadbadadd2e55ULL /**< Header cookie. */ #define MALLOC_TRAILER_COOKIE 0xadd2e55badbadbadULL /**< Trailer cookie.*/ /* define macros to make referencing the header and trailer cookies easier */ #define MALLOC_ELEM_TRAILER(elem) (*((uint64_t*)RTE_PTR_ADD(elem, \ elem->size - MALLOC_ELEM_TRAILER_LEN))) #define MALLOC_ELEM_HEADER(elem) (elem->header_cookie) static inline void set_header(struct malloc_elem *elem) { if (elem != NULL) MALLOC_ELEM_HEADER(elem) = MALLOC_HEADER_COOKIE; } static inline void set_trailer(struct malloc_elem *elem) { if (elem != NULL) MALLOC_ELEM_TRAILER(elem) = MALLOC_TRAILER_COOKIE; } /* check that the header and trailer cookies are set correctly */ static inline int malloc_elem_cookies_ok(const struct malloc_elem *elem) { return (elem != NULL && MALLOC_ELEM_HEADER(elem) == MALLOC_HEADER_COOKIE && MALLOC_ELEM_TRAILER(elem) == MALLOC_TRAILER_COOKIE); } #endif static const unsigned MALLOC_ELEM_HEADER_LEN = sizeof(struct malloc_elem); #define MALLOC_ELEM_OVERHEAD (MALLOC_ELEM_HEADER_LEN + MALLOC_ELEM_TRAILER_LEN) /* * Given a pointer to the start of a memory block returned by malloc, get * the actual malloc_elem header for that block. */ static inline struct malloc_elem * malloc_elem_from_data(const void *data) { if (data == NULL) return NULL; struct malloc_elem *elem = RTE_PTR_SUB(data, MALLOC_ELEM_HEADER_LEN); if (!malloc_elem_cookies_ok(elem)) return NULL; return elem->state != ELEM_PAD ? elem: RTE_PTR_SUB(elem, elem->pad); } /* * initialise a malloc_elem header */ void malloc_elem_init(struct malloc_elem *elem, struct malloc_heap *heap, const struct rte_memseg *ms, size_t size); /* * initialise a dummy malloc_elem header for the end-of-memseg marker */ void malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev_free); /* * return true if the current malloc_elem can hold a block of data * of the requested size and with the requested alignment */ int malloc_elem_can_hold(struct malloc_elem *elem, size_t size, unsigned align, size_t bound); /* * reserve a block of data in an existing malloc_elem. If the malloc_elem * is much larger than the data block requested, we split the element in two. */ struct malloc_elem * malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align, size_t bound); /* * free a malloc_elem block by adding it to the free list. If the * blocks either immediately before or immediately after newly freed block * are also free, the blocks are merged together. */ int malloc_elem_free(struct malloc_elem *elem); /* * attempt to resize a malloc_elem by expanding into any free space * immediately after it in memory. */ int malloc_elem_resize(struct malloc_elem *elem, size_t size); /* * Given an element size, compute its freelist index. */ size_t malloc_elem_free_list_index(size_t size); /* * Add element to its heap's free list. */ void malloc_elem_free_list_insert(struct malloc_elem *elem); #endif /* MALLOC_ELEM_H_ */ ================================================ FILE: lib/librte_eal/common/malloc_heap.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "malloc_elem.h" #include "malloc_heap.h" static unsigned check_hugepage_sz(unsigned flags, uint64_t hugepage_sz) { unsigned check_flag = 0; if (!(flags & ~RTE_MEMZONE_SIZE_HINT_ONLY)) return 1; switch (hugepage_sz) { case RTE_PGSIZE_256K: check_flag = RTE_MEMZONE_256KB; break; case RTE_PGSIZE_2M: check_flag = RTE_MEMZONE_2MB; break; case RTE_PGSIZE_16M: check_flag = RTE_MEMZONE_16MB; break; case RTE_PGSIZE_256M: check_flag = RTE_MEMZONE_256MB; break; case RTE_PGSIZE_512M: check_flag = RTE_MEMZONE_512MB; break; case RTE_PGSIZE_1G: check_flag = RTE_MEMZONE_1GB; break; case RTE_PGSIZE_4G: check_flag = RTE_MEMZONE_4GB; break; case RTE_PGSIZE_16G: check_flag = RTE_MEMZONE_16GB; } return (check_flag & flags); } /* * Expand the heap with a memseg. * This reserves the zone and sets a dummy malloc_elem header at the end * to prevent overflow. The rest of the zone is added to free list as a single * large free block */ static void malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms) { /* allocate the memory block headers, one at end, one at start */ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr; struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr, ms->len - MALLOC_ELEM_OVERHEAD); end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE); const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem; malloc_elem_init(start_elem, heap, ms, elem_size); malloc_elem_mkend(end_elem, start_elem); malloc_elem_free_list_insert(start_elem); heap->total_size += elem_size; } /* * Iterates through the freelist for a heap to find a free element * which can store data of the required size and with the requested alignment. * If size is 0, find the biggest available elem. * Returns null on failure, or pointer to element on success. */ static struct malloc_elem * find_suitable_element(struct malloc_heap *heap, size_t size, unsigned flags, size_t align, size_t bound) { size_t idx; struct malloc_elem *elem, *alt_elem = NULL; for (idx = malloc_elem_free_list_index(size); idx < RTE_HEAP_NUM_FREELISTS; idx++) { for (elem = LIST_FIRST(&heap->free_head[idx]); !!elem; elem = LIST_NEXT(elem, free_list)) { if (malloc_elem_can_hold(elem, size, align, bound)) { if (check_hugepage_sz(flags, elem->ms->hugepage_sz)) return elem; if (alt_elem == NULL) alt_elem = elem; } } } if ((alt_elem != NULL) && (flags & RTE_MEMZONE_SIZE_HINT_ONLY)) return alt_elem; return NULL; } /* * Main function to allocate a block of memory from the heap. * It locks the free list, scans it, and adds a new memseg if the * scan fails. Once the new memseg is added, it re-scans and should return * the new element after releasing the lock. */ void * malloc_heap_alloc(struct malloc_heap *heap, const char *type __attribute__((unused)), size_t size, unsigned flags, size_t align, size_t bound) { struct malloc_elem *elem; size = RTE_CACHE_LINE_ROUNDUP(size); align = RTE_CACHE_LINE_ROUNDUP(align); rte_spinlock_lock(&heap->lock); elem = find_suitable_element(heap, size, flags, align, bound); if (elem != NULL) { elem = malloc_elem_alloc(elem, size, align, bound); /* increase heap's count of allocated elements */ heap->alloc_count++; } rte_spinlock_unlock(&heap->lock); return elem == NULL ? NULL : (void *)(&elem[1]); } /* * Function to retrieve data for heap on given socket */ int malloc_heap_get_stats(const struct malloc_heap *heap, struct rte_malloc_socket_stats *socket_stats) { size_t idx; struct malloc_elem *elem; /* Initialise variables for heap */ socket_stats->free_count = 0; socket_stats->heap_freesz_bytes = 0; socket_stats->greatest_free_size = 0; /* Iterate through free list */ for (idx = 0; idx < RTE_HEAP_NUM_FREELISTS; idx++) { for (elem = LIST_FIRST(&heap->free_head[idx]); !!elem; elem = LIST_NEXT(elem, free_list)) { socket_stats->free_count++; socket_stats->heap_freesz_bytes += elem->size; if (elem->size > socket_stats->greatest_free_size) socket_stats->greatest_free_size = elem->size; } } /* Get stats on overall heap and allocated memory on this heap */ socket_stats->heap_totalsz_bytes = heap->total_size; socket_stats->heap_allocsz_bytes = (socket_stats->heap_totalsz_bytes - socket_stats->heap_freesz_bytes); socket_stats->alloc_count = heap->alloc_count; return 0; } int rte_eal_malloc_heap_init(void) { struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; unsigned ms_cnt; struct rte_memseg *ms; if (mcfg == NULL) return -1; for (ms = &mcfg->memseg[0], ms_cnt = 0; (ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0); ms_cnt++, ms++) { #ifdef RTE_LIBRTE_IVSHMEM /* * if segment has ioremap address set, it's an IVSHMEM segment and * it is not memory to allocate from. */ if (ms->ioremap_addr != 0) continue; #endif malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms); } return 0; } ================================================ FILE: lib/librte_eal/common/malloc_heap.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MALLOC_HEAP_H_ #define MALLOC_HEAP_H_ #include #include #ifdef __cplusplus extern "C" { #endif static inline unsigned malloc_get_numa_socket(void) { unsigned socket_id = rte_socket_id(); if (socket_id == (unsigned)SOCKET_ID_ANY) return 0; return socket_id; } void * malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size, unsigned flags, size_t align, size_t bound); int malloc_heap_get_stats(const struct malloc_heap *heap, struct rte_malloc_socket_stats *socket_stats); int rte_eal_malloc_heap_init(void); #ifdef __cplusplus } #endif #endif /* MALLOC_HEAP_H_ */ ================================================ FILE: lib/librte_eal/common/rte_malloc.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "malloc_elem.h" #include "malloc_heap.h" /* Free the memory space back to heap */ void rte_free(void *addr) { if (addr == NULL) return; if (malloc_elem_free(malloc_elem_from_data(addr)) < 0) rte_panic("Fatal error: Invalid memory\n"); } /* * Allocate memory on specified heap. */ void * rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg) { struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; int socket, i; void *ret; /* return NULL if size is 0 or alignment is not power-of-2 */ if (size == 0 || (align && !rte_is_power_of_2(align))) return NULL; if (!rte_eal_has_hugepages()) socket_arg = SOCKET_ID_ANY; if (socket_arg == SOCKET_ID_ANY) socket = malloc_get_numa_socket(); else socket = socket_arg; /* Check socket parameter */ if (socket >= RTE_MAX_NUMA_NODES) return NULL; ret = malloc_heap_alloc(&mcfg->malloc_heaps[socket], type, size, 0, align == 0 ? 1 : align, 0); if (ret != NULL || socket_arg != SOCKET_ID_ANY) return ret; /* try other heaps */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { /* we already tried this one */ if (i == socket) continue; ret = malloc_heap_alloc(&mcfg->malloc_heaps[i], type, size, 0, align == 0 ? 1 : align, 0); if (ret != NULL) return ret; } return NULL; } /* * Allocate memory on default heap. */ void * rte_malloc(const char *type, size_t size, unsigned align) { return rte_malloc_socket(type, size, align, SOCKET_ID_ANY); } /* * Allocate zero'd memory on specified heap. */ void * rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket) { void *ptr = rte_malloc_socket(type, size, align, socket); if (ptr != NULL) memset(ptr, 0, size); return ptr; } /* * Allocate zero'd memory on default heap. */ void * rte_zmalloc(const char *type, size_t size, unsigned align) { return rte_zmalloc_socket(type, size, align, SOCKET_ID_ANY); } /* * Allocate zero'd memory on specified heap. */ void * rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket) { return rte_zmalloc_socket(type, num * size, align, socket); } /* * Allocate zero'd memory on default heap. */ void * rte_calloc(const char *type, size_t num, size_t size, unsigned align) { return rte_zmalloc(type, num * size, align); } /* * Resize allocated memory. */ void * rte_realloc(void *ptr, size_t size, unsigned align) { if (ptr == NULL) return rte_malloc(NULL, size, align); struct malloc_elem *elem = malloc_elem_from_data(ptr); if (elem == NULL) rte_panic("Fatal error: memory corruption detected\n"); size = RTE_CACHE_LINE_ROUNDUP(size), align = RTE_CACHE_LINE_ROUNDUP(align); /* check alignment matches first, and if ok, see if we can resize block */ if (RTE_PTR_ALIGN(ptr,align) == ptr && malloc_elem_resize(elem, size) == 0) return ptr; /* either alignment is off, or we have no room to expand, * so move data. */ void *new_ptr = rte_malloc(NULL, size, align); if (new_ptr == NULL) return NULL; const unsigned old_size = elem->size - MALLOC_ELEM_OVERHEAD; rte_memcpy(new_ptr, ptr, old_size < size ? old_size : size); rte_free(ptr); return new_ptr; } int rte_malloc_validate(const void *ptr, size_t *size) { const struct malloc_elem *elem = malloc_elem_from_data(ptr); if (!malloc_elem_cookies_ok(elem)) return -1; if (size != NULL) *size = elem->size - elem->pad - MALLOC_ELEM_OVERHEAD; return 0; } /* * Function to retrieve data for heap on given socket */ int rte_malloc_get_socket_stats(int socket, struct rte_malloc_socket_stats *socket_stats) { struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; if (socket >= RTE_MAX_NUMA_NODES || socket < 0) return -1; return malloc_heap_get_stats(&mcfg->malloc_heaps[socket], socket_stats); } /* * Print stats on memory type. If type is NULL, info on all types is printed */ void rte_malloc_dump_stats(FILE *f, __rte_unused const char *type) { unsigned int socket; struct rte_malloc_socket_stats sock_stats; /* Iterate through all initialised heaps */ for (socket=0; socket< RTE_MAX_NUMA_NODES; socket++) { if ((rte_malloc_get_socket_stats(socket, &sock_stats) < 0)) continue; fprintf(f, "Socket:%u\n", socket); fprintf(f, "\tHeap_size:%zu,\n", sock_stats.heap_totalsz_bytes); fprintf(f, "\tFree_size:%zu,\n", sock_stats.heap_freesz_bytes); fprintf(f, "\tAlloc_size:%zu,\n", sock_stats.heap_allocsz_bytes); fprintf(f, "\tGreatest_free_size:%zu,\n", sock_stats.greatest_free_size); fprintf(f, "\tAlloc_count:%u,\n",sock_stats.alloc_count); fprintf(f, "\tFree_count:%u,\n", sock_stats.free_count); } return; } /* * TODO: Set limit to memory that can be allocated to memory type */ int rte_malloc_set_limit(__rte_unused const char *type, __rte_unused size_t max) { return 0; } /* * Return the physical address of a virtual address obtained through rte_malloc */ phys_addr_t rte_malloc_virt2phy(const void *addr) { const struct malloc_elem *elem = malloc_elem_from_data(addr); if (elem == NULL) return 0; return elem->ms->phys_addr + ((uintptr_t)addr - (uintptr_t)elem->ms->addr); } ================================================ FILE: lib/librte_eal/linuxapp/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk ifeq ($(CONFIG_RTE_EAL_IGB_UIO),y) DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += igb_uio endif DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal ifeq ($(CONFIG_RTE_KNI_KMOD),y) DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += kni endif ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y) DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += xen_dom0 endif include $(RTE_SDK)/mk/rte.subdir.mk ================================================ FILE: lib/librte_eal/linuxapp/eal/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_eal.a EXPORT_MAP := rte_eal_version.map LIBABIVER := 1 VPATH += $(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(SRCDIR)/include CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include CFLAGS += -I$(RTE_SDK)/lib/librte_ring CFLAGS += -I$(RTE_SDK)/lib/librte_mempool CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem CFLAGS += $(WERROR_FLAGS) -O3 # specific to linuxapp exec-env SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) := eal.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_hugepage_info.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_memory.c ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y) SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_xen_memory.c endif SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_thread.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_log.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_uio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio_mp_sync.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_debug.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_lcore.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_timer.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_interrupts.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_alarm.c ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y) SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_ivshmem.c endif # from common dir SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_lcore.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_timer.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_memzone.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_log.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_launch.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_pci.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_pci_uio.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_memory.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_tailqs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_errno.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_cpuflags.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_string_fns.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_hexdump.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_devargs.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += malloc_heap.c CFLAGS_eal.o := -D_GNU_SOURCE CFLAGS_eal_interrupts.o := -D_GNU_SOURCE CFLAGS_eal_lcore.o := -D_GNU_SOURCE CFLAGS_eal_thread.o := -D_GNU_SOURCE CFLAGS_eal_log.o := -D_GNU_SOURCE CFLAGS_eal_common_log.o := -D_GNU_SOURCE CFLAGS_eal_hugepage_info.o := -D_GNU_SOURCE CFLAGS_eal_pci.o := -D_GNU_SOURCE CFLAGS_eal_pci_uio.o := -D_GNU_SOURCE CFLAGS_eal_pci_vfio.o := -D_GNU_SOURCE CFLAGS_eal_common_whitelist.o := -D_GNU_SOURCE CFLAGS_eal_common_options.o := -D_GNU_SOURCE CFLAGS_eal_common_thread.o := -D_GNU_SOURCE CFLAGS_eal_common_lcore.o := -D_GNU_SOURCE # workaround for a gcc bug with noreturn attribute # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) CFLAGS_eal_thread.o += -Wno-return-type endif INC := rte_interrupts.h rte_kni_common.h rte_dom0_common.h SYMLINK-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP)-include/exec-env := \ $(addprefix include/exec-env/,$(INC)) DEPDIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += lib/librte_eal/common include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_eal/linuxapp/eal/eal.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2012-2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include "eal_hugepages.h" #include "eal_options.h" #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) #define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10) /* Allow the application to print its usage message too if set */ static rte_usage_hook_t rte_application_usage_hook = NULL; TAILQ_HEAD(shared_driver_list, shared_driver); /* Definition for shared object drivers. */ struct shared_driver { TAILQ_ENTRY(shared_driver) next; char name[PATH_MAX]; void* lib_handle; }; /* List of external loadable drivers */ static struct shared_driver_list solib_list = TAILQ_HEAD_INITIALIZER(solib_list); /* early configuration structure, when memory config is not mmapped */ static struct rte_mem_config early_mem_config; /* define fd variable here, because file needs to be kept open for the * duration of the program, as we hold a write lock on it in the primary proc */ static int mem_cfg_fd = -1; static struct flock wr_lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = offsetof(struct rte_mem_config, memseg), .l_len = sizeof(early_mem_config.memseg), }; /* Address of global and public configuration */ static struct rte_config rte_config = { .mem_config = &early_mem_config, }; /* internal configuration (per-core) */ struct lcore_config lcore_config[RTE_MAX_LCORE]; /* internal configuration */ struct internal_config internal_config; /* used by rte_rdtsc() */ int rte_cycles_vmware_tsc_map; /* Return a pointer to the configuration structure */ struct rte_config * rte_eal_get_configuration(void) { return &rte_config; } /* parse a sysfs (or other) file containing one integer value */ int eal_parse_sysfs_value(const char *filename, unsigned long *val) { FILE *f; char buf[BUFSIZ]; char *end = NULL; if ((f = fopen(filename, "r")) == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n", __func__, filename); return -1; } if (fgets(buf, sizeof(buf), f) == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n", __func__, filename); fclose(f); return -1; } *val = strtoul(buf, &end, 0); if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n", __func__, filename); fclose(f); return -1; } fclose(f); return 0; } /* create memory configuration in shared/mmap memory. Take out * a write lock on the memsegs, so we can auto-detect primary/secondary. * This means we never close the file while running (auto-close on exit). * We also don't lock the whole file, so that in future we can use read-locks * on other parts, e.g. memzones, to detect if there are running secondary * processes. */ static void rte_eal_config_create(void) { void *rte_mem_cfg_addr; int retval; const char *pathname = eal_runtime_config_path(); if (internal_config.no_shconf) return; /* map the config before hugepage address so that we don't waste a page */ if (internal_config.base_virtaddr != 0) rte_mem_cfg_addr = (void *) RTE_ALIGN_FLOOR(internal_config.base_virtaddr - sizeof(struct rte_mem_config), sysconf(_SC_PAGE_SIZE)); else rte_mem_cfg_addr = NULL; if (mem_cfg_fd < 0){ mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660); if (mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config)); if (retval < 0){ close(mem_cfg_fd); rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname); } retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock); if (retval < 0){ close(mem_cfg_fd); rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary " "process running?\n", pathname); } rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); if (rte_mem_cfg_addr == MAP_FAILED){ rte_panic("Cannot mmap memory for rte_config\n"); } memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config)); rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr; /* store address of the config in the config itself so that secondary * processes could later map the config into this exact location */ rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr; } /* attach to an existing shared memory config */ static void rte_eal_config_attach(void) { struct rte_mem_config *mem_config; const char *pathname = eal_runtime_config_path(); if (internal_config.no_shconf) return; if (mem_cfg_fd < 0){ mem_cfg_fd = open(pathname, O_RDWR); if (mem_cfg_fd < 0) rte_panic("Cannot open '%s' for rte_mem_config\n", pathname); } /* map it as read-only first */ mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config), PROT_READ, MAP_SHARED, mem_cfg_fd, 0); if (mem_config == MAP_FAILED) rte_panic("Cannot mmap memory for rte_config\n"); rte_config.mem_config = mem_config; } /* reattach the shared config at exact memory location primary process has it */ static void rte_eal_config_reattach(void) { struct rte_mem_config *mem_config; void *rte_mem_cfg_addr; if (internal_config.no_shconf) return; /* save the address primary process has mapped shared config to */ rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr; /* unmap original config */ munmap(rte_config.mem_config, sizeof(struct rte_mem_config)); /* remap the config at proper address */ mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr, sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0); close(mem_cfg_fd); if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr) rte_panic("Cannot mmap memory for rte_config\n"); rte_config.mem_config = mem_config; } /* Detect if we are a primary or a secondary process */ enum rte_proc_type_t eal_proc_type_detect(void) { enum rte_proc_type_t ptype = RTE_PROC_PRIMARY; const char *pathname = eal_runtime_config_path(); /* if we can open the file but not get a write-lock we are a secondary * process. NOTE: if we get a file handle back, we keep that open * and don't close it to prevent a race condition between multiple opens */ if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) && (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0)) ptype = RTE_PROC_SECONDARY; RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n", ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY"); return ptype; } /* Sets up rte_config structure with the pointer to shared memory config.*/ static void rte_config_init(void) { rte_config.process_type = internal_config.process_type; switch (rte_config.process_type){ case RTE_PROC_PRIMARY: rte_eal_config_create(); break; case RTE_PROC_SECONDARY: rte_eal_config_attach(); rte_eal_mcfg_wait_complete(rte_config.mem_config); rte_eal_config_reattach(); break; case RTE_PROC_AUTO: case RTE_PROC_INVALID: rte_panic("Invalid process type\n"); } } /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */ static void eal_hugedirs_unlock(void) { int i; for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) { /* skip uninitialized */ if (internal_config.hugepage_info[i].lock_descriptor < 0) continue; /* unlock hugepage file */ flock(internal_config.hugepage_info[i].lock_descriptor, LOCK_UN); close(internal_config.hugepage_info[i].lock_descriptor); /* reset the field */ internal_config.hugepage_info[i].lock_descriptor = -1; } } /* display usage */ static void eal_usage(const char *prgname) { printf("\nUsage: %s ", prgname); eal_common_usage(); printf("EAL Linux options:\n" " -d LIB.so Add driver (can be used multiple times)\n" " --"OPT_SOCKET_MEM" Memory to allocate on sockets (comma separated values)\n" " --"OPT_HUGE_DIR" Directory where hugetlbfs is mounted\n" " --"OPT_FILE_PREFIX" Prefix for hugepage filenames\n" " --"OPT_BASE_VIRTADDR" Base virtual address\n" " --"OPT_CREATE_UIO_DEV" Create /dev/uioX (usually done by hotplug)\n" " --"OPT_VFIO_INTR" Interrupt mode for VFIO (legacy|msi|msix)\n" " --"OPT_XEN_DOM0" Support running on Xen dom0 without hugetlbfs\n" "\n"); /* Allow the application to print its usage message too if hook is set */ if ( rte_application_usage_hook ) { printf("===== Application Usage =====\n\n"); rte_application_usage_hook(prgname); } } /* Set a per-application usage message */ rte_usage_hook_t rte_set_application_usage_hook( rte_usage_hook_t usage_func ) { rte_usage_hook_t old_func; /* Will be NULL on the first call to denote the last usage routine. */ old_func = rte_application_usage_hook; rte_application_usage_hook = usage_func; return old_func; } static int eal_parse_socket_mem(char *socket_mem) { char * arg[RTE_MAX_NUMA_NODES]; char *end; int arg_num, i, len; uint64_t total_mem = 0; len = strnlen(socket_mem, SOCKET_MEM_STRLEN); if (len == SOCKET_MEM_STRLEN) { RTE_LOG(ERR, EAL, "--socket-mem is too long\n"); return -1; } /* all other error cases will be caught later */ if (!isdigit(socket_mem[len-1])) return -1; /* split the optarg into separate socket values */ arg_num = rte_strsplit(socket_mem, len, arg, RTE_MAX_NUMA_NODES, ','); /* if split failed, or 0 arguments */ if (arg_num <= 0) return -1; internal_config.force_sockets = 1; /* parse each defined socket option */ errno = 0; for (i = 0; i < arg_num; i++) { end = NULL; internal_config.socket_mem[i] = strtoull(arg[i], &end, 10); /* check for invalid input */ if ((errno != 0) || (arg[i][0] == '\0') || (end == NULL) || (*end != '\0')) return -1; internal_config.socket_mem[i] *= 1024ULL; internal_config.socket_mem[i] *= 1024ULL; total_mem += internal_config.socket_mem[i]; } /* check if we have a positive amount of total memory */ if (total_mem == 0) return -1; return 0; } static int eal_parse_base_virtaddr(const char *arg) { char *end; uint64_t addr; errno = 0; addr = strtoull(arg, &end, 16); /* check for errors */ if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0')) return -1; /* make sure we don't exceed 32-bit boundary on 32-bit target */ #ifndef RTE_ARCH_64 if (addr >= UINTPTR_MAX) return -1; #endif /* align the addr on 16M boundary, 16MB is the minimum huge page * size on IBM Power architecture. If the addr is aligned to 16MB, * it can align to 2MB for x86. So this alignment can also be used * on x86 */ internal_config.base_virtaddr = RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M); return 0; } static int eal_parse_vfio_intr(const char *mode) { unsigned i; static struct { const char *name; enum rte_intr_mode value; } map[] = { { "legacy", RTE_INTR_MODE_LEGACY }, { "msi", RTE_INTR_MODE_MSI }, { "msix", RTE_INTR_MODE_MSIX }, }; for (i = 0; i < RTE_DIM(map); i++) { if (!strcmp(mode, map[i].name)) { internal_config.vfio_intr_mode = map[i].value; return 0; } } return -1; } static inline size_t eal_get_hugepage_mem_size(void) { uint64_t size = 0; unsigned i, j; for (i = 0; i < internal_config.num_hugepage_sizes; i++) { struct hugepage_info *hpi = &internal_config.hugepage_info[i]; if (hpi->hugedir != NULL) { for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { size += hpi->hugepage_sz * hpi->num_pages[j]; } } } return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX; } /* Parse the arguments for --log-level only */ static void eal_log_level_parse(int argc, char **argv) { int opt; char **argvopt; int option_index; argvopt = argv; eal_reset_internal_config(&internal_config); while ((opt = getopt_long(argc, argvopt, eal_short_options, eal_long_options, &option_index)) != EOF) { int ret; /* getopt is not happy, stop right now */ if (opt == '?') break; ret = (opt == OPT_LOG_LEVEL_NUM) ? eal_parse_common_option(opt, optarg, &internal_config) : 0; /* common parser is not happy */ if (ret < 0) break; } optind = 0; /* reset getopt lib */ } /* Parse the argument given in the command line of the application */ static int eal_parse_args(int argc, char **argv) { int opt, ret; char **argvopt; int option_index; char *prgname = argv[0]; struct shared_driver *solib; argvopt = argv; while ((opt = getopt_long(argc, argvopt, eal_short_options, eal_long_options, &option_index)) != EOF) { int ret; /* getopt is not happy, stop right now */ if (opt == '?') { eal_usage(prgname); return -1; } ret = eal_parse_common_option(opt, optarg, &internal_config); /* common parser is not happy */ if (ret < 0) { eal_usage(prgname); return -1; } /* common parser handled this option */ if (ret == 0) continue; switch (opt) { case 'h': eal_usage(prgname); exit(EXIT_SUCCESS); /* force loading of external driver */ case 'd': solib = malloc(sizeof(*solib)); if (solib == NULL) { RTE_LOG(ERR, EAL, "malloc(solib) failed\n"); return -1; } memset(solib, 0, sizeof(*solib)); strncpy(solib->name, optarg, PATH_MAX-1); solib->name[PATH_MAX-1] = 0; TAILQ_INSERT_TAIL(&solib_list, solib, next); break; /* long options */ case OPT_XEN_DOM0_NUM: #ifdef RTE_LIBRTE_XEN_DOM0 internal_config.xen_dom0_support = 1; #else RTE_LOG(ERR, EAL, "Can't support DPDK app " "running on Dom0, please configure" " RTE_LIBRTE_XEN_DOM0=y\n"); return -1; #endif break; case OPT_HUGE_DIR_NUM: internal_config.hugepage_dir = optarg; break; case OPT_FILE_PREFIX_NUM: internal_config.hugefile_prefix = optarg; break; case OPT_SOCKET_MEM_NUM: if (eal_parse_socket_mem(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid parameters for --" OPT_SOCKET_MEM "\n"); eal_usage(prgname); return -1; } break; case OPT_BASE_VIRTADDR_NUM: if (eal_parse_base_virtaddr(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid parameter for --" OPT_BASE_VIRTADDR "\n"); eal_usage(prgname); return -1; } break; case OPT_VFIO_INTR_NUM: if (eal_parse_vfio_intr(optarg) < 0) { RTE_LOG(ERR, EAL, "invalid parameters for --" OPT_VFIO_INTR "\n"); eal_usage(prgname); return -1; } break; case OPT_CREATE_UIO_DEV_NUM: internal_config.create_uio_dev = 1; break; default: if (opt < OPT_LONG_MIN_NUM && isprint(opt)) { RTE_LOG(ERR, EAL, "Option %c is not supported " "on Linux\n", opt); } else if (opt >= OPT_LONG_MIN_NUM && opt < OPT_LONG_MAX_NUM) { RTE_LOG(ERR, EAL, "Option %s is not supported " "on Linux\n", eal_long_options[option_index].name); } else { RTE_LOG(ERR, EAL, "Option %d is not supported " "on Linux\n", opt); } eal_usage(prgname); return -1; } } if (eal_adjust_config(&internal_config) != 0) return -1; /* sanity checks */ if (eal_check_common_options(&internal_config) != 0) { eal_usage(prgname); return -1; } /* --xen-dom0 doesn't make sense with --socket-mem */ if (internal_config.xen_dom0_support && internal_config.force_sockets == 1) { RTE_LOG(ERR, EAL, "Options --"OPT_SOCKET_MEM" cannot be specified " "together with --"OPT_XEN_DOM0"\n"); eal_usage(prgname); return -1; } if (optind >= 0) argv[optind-1] = prgname; ret = optind-1; optind = 0; /* reset getopt lib */ return ret; } static void eal_check_mem_on_local_socket(void) { const struct rte_memseg *ms; int i, socket_id; socket_id = rte_lcore_to_socket_id(rte_config.master_lcore); ms = rte_eal_get_physmem_layout(); for (i = 0; i < RTE_MAX_MEMSEG; i++) if (ms[i].socket_id == socket_id && ms[i].len > 0) return; RTE_LOG(WARNING, EAL, "WARNING: Master core has no " "memory on local socket!\n"); } static int sync_func(__attribute__((unused)) void *arg) { return 0; } inline static void rte_eal_mcfg_complete(void) { /* ALL shared mem_config related INIT DONE */ if (rte_config.process_type == RTE_PROC_PRIMARY) rte_config.mem_config->magic = RTE_MAGIC; } /* * Request iopl privilege for all RPL, returns 0 on success * iopl() call is mostly for the i386 architecture. For other architectures, * return -1 to indicate IO privilege can't be changed in this way. */ int rte_eal_iopl_init(void) { #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) if (iopl(3) != 0) return -1; return 0; #else return -1; #endif } /* Launch threads, called at application init(). */ int rte_eal_init(int argc, char **argv) { int i, fctret, ret; pthread_t thread_id; static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0); struct shared_driver *solib = NULL; const char *logid; char cpuset[RTE_CPU_AFFINITY_STR_LEN]; if (!rte_atomic32_test_and_set(&run_once)) return -1; logid = strrchr(argv[0], '/'); logid = strdup(logid ? logid + 1: argv[0]); thread_id = pthread_self(); if (rte_eal_log_early_init() < 0) rte_panic("Cannot init early logs\n"); eal_log_level_parse(argc, argv); /* set log level as early as possible */ rte_set_log_level(internal_config.log_level); if (rte_eal_cpu_init() < 0) rte_panic("Cannot detect lcores\n"); fctret = eal_parse_args(argc, argv); if (fctret < 0) exit(1); if (internal_config.no_hugetlbfs == 0 && internal_config.process_type != RTE_PROC_SECONDARY && internal_config.xen_dom0_support == 0 && eal_hugepage_info_init() < 0) rte_panic("Cannot get hugepage information\n"); if (internal_config.memory == 0 && internal_config.force_sockets == 0) { if (internal_config.no_hugetlbfs) internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE; else internal_config.memory = eal_get_hugepage_mem_size(); } if (internal_config.vmware_tsc_map == 1) { #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT rte_cycles_vmware_tsc_map = 1; RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, " "you must have monitor_control.pseudo_perfctr = TRUE\n"); #else RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because " "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n"); #endif } rte_srand(rte_rdtsc()); rte_config_init(); if (rte_eal_pci_init() < 0) rte_panic("Cannot init PCI\n"); #ifdef RTE_LIBRTE_IVSHMEM if (rte_eal_ivshmem_init() < 0) rte_panic("Cannot init IVSHMEM\n"); #endif if (rte_eal_memory_init() < 0) rte_panic("Cannot init memory\n"); /* the directories are locked during eal_hugepage_info_init */ eal_hugedirs_unlock(); if (rte_eal_memzone_init() < 0) rte_panic("Cannot init memzone\n"); if (rte_eal_tailqs_init() < 0) rte_panic("Cannot init tail queues for objects\n"); #ifdef RTE_LIBRTE_IVSHMEM if (rte_eal_ivshmem_obj_init() < 0) rte_panic("Cannot init IVSHMEM objects\n"); #endif if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0) rte_panic("Cannot init logs\n"); if (rte_eal_alarm_init() < 0) rte_panic("Cannot init interrupt-handling thread\n"); if (rte_eal_intr_init() < 0) rte_panic("Cannot init interrupt-handling thread\n"); if (rte_eal_timer_init() < 0) rte_panic("Cannot init HPET or TSC timers\n"); eal_check_mem_on_local_socket(); rte_eal_mcfg_complete(); TAILQ_FOREACH(solib, &solib_list, next) { RTE_LOG(DEBUG, EAL, "open shared lib %s\n", solib->name); solib->lib_handle = dlopen(solib->name, RTLD_NOW); if (solib->lib_handle == NULL) RTE_LOG(WARNING, EAL, "%s\n", dlerror()); } eal_thread_init_master(rte_config.master_lcore); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%x;cpuset=[%s%s])\n", rte_config.master_lcore, (int)thread_id, cpuset, ret == 0 ? "" : "..."); if (rte_eal_dev_init() < 0) rte_panic("Cannot init pmd devices\n"); RTE_LCORE_FOREACH_SLAVE(i) { /* * create communication pipes between master thread * and children */ if (pipe(lcore_config[i].pipe_master2slave) < 0) rte_panic("Cannot create pipe\n"); if (pipe(lcore_config[i].pipe_slave2master) < 0) rte_panic("Cannot create pipe\n"); lcore_config[i].state = WAIT; /* create a thread for each lcore */ ret = pthread_create(&lcore_config[i].thread_id, NULL, eal_thread_loop, NULL); if (ret != 0) rte_panic("Cannot create thread\n"); } /* * Launch a dummy function on all slave lcores, so that master lcore * knows they are all ready when this function returns. */ rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); rte_eal_mp_wait_lcore(); /* Probe & Initialize PCI devices */ if (rte_eal_pci_probe()) rte_panic("Cannot probe PCI\n"); return fctret; } /* get core role */ enum rte_lcore_role_t rte_eal_lcore_role(unsigned lcore_id) { return rte_config.lcore_role[lcore_id]; } enum rte_proc_type_t rte_eal_process_type(void) { return rte_config.process_type; } int rte_eal_has_hugepages(void) { return ! internal_config.no_hugetlbfs; } int rte_eal_check_module(const char *module_name) { char mod_name[30]; /* Any module names can be longer than 30 bytes? */ int ret = 0; int n; if (NULL == module_name) return -1; FILE *fd = fopen("/proc/modules", "r"); if (NULL == fd) { RTE_LOG(ERR, EAL, "Open /proc/modules failed!" " error %i (%s)\n", errno, strerror(errno)); return -1; } while (!feof(fd)) { n = fscanf(fd, "%29s %*[^\n]", mod_name); if ((n == 1) && !strcmp(mod_name, module_name)) { ret = 1; break; } } fclose(fd); return ret; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_alarm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef TFD_NONBLOCK #include #define TFD_NONBLOCK O_NONBLOCK #endif #define NS_PER_US 1000 #define US_PER_MS 1000 #define MS_PER_S 1000 #define US_PER_S (US_PER_MS * MS_PER_S) struct alarm_entry { LIST_ENTRY(alarm_entry) next; struct timeval time; rte_eal_alarm_callback cb_fn; void *cb_arg; volatile uint8_t executing; volatile pthread_t executing_id; }; static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER(); static rte_spinlock_t alarm_list_lk = RTE_SPINLOCK_INITIALIZER; static struct rte_intr_handle intr_handle = {.fd = -1 }; static int handler_registered = 0; static void eal_alarm_callback(struct rte_intr_handle *hdl, void *arg); int rte_eal_alarm_init(void) { intr_handle.type = RTE_INTR_HANDLE_ALARM; /* create a timerfd file descriptor */ intr_handle.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if (intr_handle.fd == -1) goto error; return 0; error: rte_errno = errno; return -1; } static void eal_alarm_callback(struct rte_intr_handle *hdl __rte_unused, void *arg __rte_unused) { struct timeval now; struct alarm_entry *ap; rte_spinlock_lock(&alarm_list_lk); while ((ap = LIST_FIRST(&alarm_list)) !=NULL && gettimeofday(&now, NULL) == 0 && (ap->time.tv_sec < now.tv_sec || (ap->time.tv_sec == now.tv_sec && ap->time.tv_usec <= now.tv_usec))){ ap->executing = 1; ap->executing_id = pthread_self(); rte_spinlock_unlock(&alarm_list_lk); ap->cb_fn(ap->cb_arg); rte_spinlock_lock(&alarm_list_lk); LIST_REMOVE(ap, next); rte_free(ap); } if (!LIST_EMPTY(&alarm_list)) { struct itimerspec atime = { .it_interval = { 0, 0 } }; ap = LIST_FIRST(&alarm_list); atime.it_value.tv_sec = ap->time.tv_sec; atime.it_value.tv_nsec = ap->time.tv_usec * NS_PER_US; /* perform borrow for subtraction if necessary */ if (now.tv_usec > ap->time.tv_usec) atime.it_value.tv_sec--, atime.it_value.tv_nsec += US_PER_S * NS_PER_US; atime.it_value.tv_sec -= now.tv_sec; atime.it_value.tv_nsec -= now.tv_usec * NS_PER_US; timerfd_settime(intr_handle.fd, 0, &atime, NULL); } rte_spinlock_unlock(&alarm_list_lk); } int rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg) { struct timeval now; int ret = 0; struct alarm_entry *ap, *new_alarm; /* Check parameters, including that us won't cause a uint64_t overflow */ if (us < 1 || us > (UINT64_MAX - US_PER_S) || cb_fn == NULL) return -EINVAL; new_alarm = rte_zmalloc(NULL, sizeof(*new_alarm), 0); if (new_alarm == NULL) return -ENOMEM; /* use current time to calculate absolute time of alarm */ gettimeofday(&now, NULL); new_alarm->cb_fn = cb_fn; new_alarm->cb_arg = cb_arg; new_alarm->time.tv_usec = (now.tv_usec + us) % US_PER_S; new_alarm->time.tv_sec = now.tv_sec + ((now.tv_usec + us) / US_PER_S); rte_spinlock_lock(&alarm_list_lk); if (!handler_registered) { ret |= rte_intr_callback_register(&intr_handle, eal_alarm_callback, NULL); handler_registered = (ret == 0) ? 1 : 0; } if (LIST_EMPTY(&alarm_list)) LIST_INSERT_HEAD(&alarm_list, new_alarm, next); else { LIST_FOREACH(ap, &alarm_list, next) { if (ap->time.tv_sec > new_alarm->time.tv_sec || (ap->time.tv_sec == new_alarm->time.tv_sec && ap->time.tv_usec > new_alarm->time.tv_usec)){ LIST_INSERT_BEFORE(ap, new_alarm, next); break; } if (LIST_NEXT(ap, next) == NULL) { LIST_INSERT_AFTER(ap, new_alarm, next); break; } } } if (LIST_FIRST(&alarm_list) == new_alarm) { struct itimerspec alarm_time = { .it_interval = {0, 0}, .it_value = { .tv_sec = us / US_PER_S, .tv_nsec = (us % US_PER_S) * NS_PER_US, }, }; ret |= timerfd_settime(intr_handle.fd, 0, &alarm_time, NULL); } rte_spinlock_unlock(&alarm_list_lk); return ret; } int rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg) { struct alarm_entry *ap, *ap_prev; int count = 0; int err = 0; int executing; if (!cb_fn) { rte_errno = EINVAL; return -1; } do { executing = 0; rte_spinlock_lock(&alarm_list_lk); /* remove any matches at the start of the list */ while ((ap = LIST_FIRST(&alarm_list)) != NULL && cb_fn == ap->cb_fn && (cb_arg == (void *)-1 || cb_arg == ap->cb_arg)) { if (ap->executing == 0) { LIST_REMOVE(ap, next); rte_free(ap); count++; } else { /* If calling from other context, mark that alarm is executing * so loop can spin till it finish. Otherwise we are trying to * cancel our self - mark it by EINPROGRESS */ if (pthread_equal(ap->executing_id, pthread_self()) == 0) executing++; else err = EINPROGRESS; break; } } ap_prev = ap; /* now go through list, removing entries not at start */ LIST_FOREACH(ap, &alarm_list, next) { /* this won't be true first time through */ if (cb_fn == ap->cb_fn && (cb_arg == (void *)-1 || cb_arg == ap->cb_arg)) { if (ap->executing == 0) { LIST_REMOVE(ap, next); rte_free(ap); count++; ap = ap_prev; } else if (pthread_equal(ap->executing_id, pthread_self()) == 0) executing++; else err = EINPROGRESS; } ap_prev = ap; } rte_spinlock_unlock(&alarm_list_lk); } while (executing != 0); if (count == 0 && err == 0) rte_errno = ENOENT; else if (err) rte_errno = err; return count; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_debug.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #define BACKTRACE_SIZE 256 /* dump the stack of the calling core */ void rte_dump_stack(void) { void *func[BACKTRACE_SIZE]; char **symb = NULL; int size; size = backtrace(func, BACKTRACE_SIZE); symb = backtrace_symbols(func, size); while (size > 0) { rte_log(RTE_LOG_ERR, RTE_LOGTYPE_EAL, "%d: [%s]\n", size, symb[size - 1]); size --; } } /* not implemented in this environment */ void rte_dump_registers(void) { return; } /* call abort(), it will generate a coredump if enabled */ void __rte_panic(const char *funcname, const char *format, ...) { va_list ap; /* disable history */ rte_log_set_history(0); rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n", funcname); va_start(ap, format); rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap); va_end(ap); rte_dump_stack(); rte_dump_registers(); abort(); } /* * Like rte_panic this terminates the application. However, no traceback is * provided and no core-dump is generated. */ void rte_exit(int exit_code, const char *format, ...) { va_list ap; /* disable history */ rte_log_set_history(0); if (exit_code != 0) RTE_LOG(CRIT, EAL, "Error - exiting with code: %d\n" " Cause: ", exit_code); va_start(ap, format); rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap); va_end(ap); #ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR exit(exit_code); #else rte_dump_stack(); rte_dump_registers(); abort(); #endif } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_hugepage_info.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_string_fns.h" #include "eal_internal_cfg.h" #include "eal_hugepages.h" #include "eal_filesystem.h" static const char sys_dir_path[] = "/sys/kernel/mm/hugepages"; /* this function is only called from eal_hugepage_info_init which itself * is only called from a primary process */ static uint32_t get_num_hugepages(const char *subdir) { char path[PATH_MAX]; long unsigned resv_pages, num_pages = 0; const char *nr_hp_file = "free_hugepages"; const char *nr_rsvd_file = "resv_hugepages"; /* first, check how many reserved pages kernel reports */ snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_rsvd_file); if (eal_parse_sysfs_value(path, &resv_pages) < 0) return 0; snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); if (eal_parse_sysfs_value(path, &num_pages) < 0) return 0; if (num_pages == 0) RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n", subdir); /* adjust num_pages */ if (num_pages >= resv_pages) num_pages -= resv_pages; else if (resv_pages) num_pages = 0; /* we want to return a uint32_t and more than this looks suspicious * anyway ... */ if (num_pages > UINT32_MAX) num_pages = UINT32_MAX; return num_pages; } static uint64_t get_default_hp_size(void) { const char proc_meminfo[] = "/proc/meminfo"; const char str_hugepagesz[] = "Hugepagesize:"; unsigned hugepagesz_len = sizeof(str_hugepagesz) - 1; char buffer[256]; unsigned long long size = 0; FILE *fd = fopen(proc_meminfo, "r"); if (fd == NULL) rte_panic("Cannot open %s\n", proc_meminfo); while(fgets(buffer, sizeof(buffer), fd)){ if (strncmp(buffer, str_hugepagesz, hugepagesz_len) == 0){ size = rte_str_to_size(&buffer[hugepagesz_len]); break; } } fclose(fd); if (size == 0) rte_panic("Cannot get default hugepage size from %s\n", proc_meminfo); return size; } static const char * get_hugepage_dir(uint64_t hugepage_sz) { enum proc_mount_fieldnames { DEVICE = 0, MOUNTPT, FSTYPE, OPTIONS, _FIELDNAME_MAX }; static uint64_t default_size = 0; const char proc_mounts[] = "/proc/mounts"; const char hugetlbfs_str[] = "hugetlbfs"; const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1; const char pagesize_opt[] = "pagesize="; const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1; const char split_tok = ' '; char *splitstr[_FIELDNAME_MAX]; char buf[BUFSIZ]; char *retval = NULL; FILE *fd = fopen(proc_mounts, "r"); if (fd == NULL) rte_panic("Cannot open %s\n", proc_mounts); if (default_size == 0) default_size = get_default_hp_size(); while (fgets(buf, sizeof(buf), fd)){ if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX, split_tok) != _FIELDNAME_MAX) { RTE_LOG(ERR, EAL, "Error parsing %s\n", proc_mounts); break; /* return NULL */ } /* we have a specified --huge-dir option, only examine that dir */ if (internal_config.hugepage_dir != NULL && strcmp(splitstr[MOUNTPT], internal_config.hugepage_dir) != 0) continue; if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) == 0){ const char *pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt); /* if no explicit page size, the default page size is compared */ if (pagesz_str == NULL){ if (hugepage_sz == default_size){ retval = strdup(splitstr[MOUNTPT]); break; } } /* there is an explicit page size, so check it */ else { uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]); if (pagesz == hugepage_sz) { retval = strdup(splitstr[MOUNTPT]); break; } } } /* end if strncmp hugetlbfs */ } /* end while fgets */ fclose(fd); return retval; } /* * Clear the hugepage directory of whatever hugepage files * there are. Checks if the file is locked (i.e. * if it's in use by another DPDK process). */ static int clear_hugedir(const char * hugedir) { DIR *dir; struct dirent *dirent; int dir_fd, fd, lck_result; const char filter[] = "*map_*"; /* matches hugepage files */ /* open directory */ dir = opendir(hugedir); if (!dir) { RTE_LOG(ERR, EAL, "Unable to open hugepage directory %s\n", hugedir); goto error; } dir_fd = dirfd(dir); dirent = readdir(dir); if (!dirent) { RTE_LOG(ERR, EAL, "Unable to read hugepage directory %s\n", hugedir); goto error; } while(dirent != NULL){ /* skip files that don't match the hugepage pattern */ if (fnmatch(filter, dirent->d_name, 0) > 0) { dirent = readdir(dir); continue; } /* try and lock the file */ fd = openat(dir_fd, dirent->d_name, O_RDONLY); /* skip to next file */ if (fd == -1) { dirent = readdir(dir); continue; } /* non-blocking lock */ lck_result = flock(fd, LOCK_EX | LOCK_NB); /* if lock succeeds, unlock and remove the file */ if (lck_result != -1) { flock(fd, LOCK_UN); unlinkat(dir_fd, dirent->d_name, 0); } close (fd); dirent = readdir(dir); } closedir(dir); return 0; error: if (dir) closedir(dir); RTE_LOG(ERR, EAL, "Error while clearing hugepage dir: %s\n", strerror(errno)); return -1; } static int compare_hpi(const void *a, const void *b) { const struct hugepage_info *hpi_a = a; const struct hugepage_info *hpi_b = b; return hpi_b->hugepage_sz - hpi_a->hugepage_sz; } /* * when we initialize the hugepage info, everything goes * to socket 0 by default. it will later get sorted by memory * initialization procedure. */ int eal_hugepage_info_init(void) { const char dirent_start_text[] = "hugepages-"; const size_t dirent_start_len = sizeof(dirent_start_text) - 1; unsigned i, num_sizes = 0; DIR *dir; struct dirent *dirent; dir = opendir(sys_dir_path); if (dir == NULL) rte_panic("Cannot open directory %s to read system hugepage " "info\n", sys_dir_path); for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) { struct hugepage_info *hpi; if (strncmp(dirent->d_name, dirent_start_text, dirent_start_len) != 0) continue; if (num_sizes >= MAX_HUGEPAGE_SIZES) break; hpi = &internal_config.hugepage_info[num_sizes]; hpi->hugepage_sz = rte_str_to_size(&dirent->d_name[dirent_start_len]); hpi->hugedir = get_hugepage_dir(hpi->hugepage_sz); /* first, check if we have a mountpoint */ if (hpi->hugedir == NULL) { uint32_t num_pages; num_pages = get_num_hugepages(dirent->d_name); if (num_pages > 0) RTE_LOG(NOTICE, EAL, "%" PRIu32 " hugepages of size " "%" PRIu64 " reserved, but no mounted " "hugetlbfs found for that size\n", num_pages, hpi->hugepage_sz); continue; } /* try to obtain a writelock */ hpi->lock_descriptor = open(hpi->hugedir, O_RDONLY); /* if blocking lock failed */ if (flock(hpi->lock_descriptor, LOCK_EX) == -1) { RTE_LOG(CRIT, EAL, "Failed to lock hugepage directory!\n"); break; } /* clear out the hugepages dir from unused pages */ if (clear_hugedir(hpi->hugedir) == -1) break; /* for now, put all pages into socket 0, * later they will be sorted */ hpi->num_pages[0] = get_num_hugepages(dirent->d_name); #ifndef RTE_ARCH_64 /* for 32-bit systems, limit number of hugepages to * 1GB per page size */ hpi->num_pages[0] = RTE_MIN(hpi->num_pages[0], RTE_PGSIZE_1G / hpi->hugepage_sz); #endif num_sizes++; } closedir(dir); /* something went wrong, and we broke from the for loop above */ if (dirent != NULL) return -1; internal_config.num_hugepage_sizes = num_sizes; /* sort the page directory entries by size, largest to smallest */ qsort(&internal_config.hugepage_info[0], num_sizes, sizeof(internal_config.hugepage_info[0]), compare_hpi); /* now we have all info, check we have at least one valid size */ for (i = 0; i < num_sizes; i++) if (internal_config.hugepage_info[i].hugedir != NULL && internal_config.hugepage_info[i].num_pages[0] > 0) return 0; /* no valid hugepage mounts available, return error */ return -1; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_interrupts.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_vfio.h" #define EAL_INTR_EPOLL_WAIT_FOREVER (-1) #define NB_OTHER_INTR 1 static RTE_DEFINE_PER_LCORE(int, _epfd) = -1; /**< epoll fd per thread */ /** * union for pipe fds. */ union intr_pipefds{ struct { int pipefd[2]; }; struct { int readfd; int writefd; }; }; /** * union buffer for reading on different devices */ union rte_intr_read_buffer { int uio_intr_count; /* for uio device */ #ifdef VFIO_PRESENT uint64_t vfio_intr_count; /* for vfio device */ #endif uint64_t timerfd_num; /* for timerfd */ char charbuf[16]; /* for others */ }; TAILQ_HEAD(rte_intr_cb_list, rte_intr_callback); TAILQ_HEAD(rte_intr_source_list, rte_intr_source); struct rte_intr_callback { TAILQ_ENTRY(rte_intr_callback) next; rte_intr_callback_fn cb_fn; /**< callback address */ void *cb_arg; /**< parameter for callback */ }; struct rte_intr_source { TAILQ_ENTRY(rte_intr_source) next; struct rte_intr_handle intr_handle; /**< interrupt handle */ struct rte_intr_cb_list callbacks; /**< user callbacks */ uint32_t active; }; /* global spinlock for interrupt data operation */ static rte_spinlock_t intr_lock = RTE_SPINLOCK_INITIALIZER; /* union buffer for pipe read/write */ static union intr_pipefds intr_pipe; /* interrupt sources list */ static struct rte_intr_source_list intr_sources; /* interrupt handling thread */ static pthread_t intr_thread; /* VFIO interrupts */ #ifdef VFIO_PRESENT #define IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + sizeof(int)) /* irq set buffer length for queue interrupts and LSC interrupt */ #define MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \ sizeof(int) * (RTE_MAX_RXTX_INTR_VEC_ID + 1)) /* enable legacy (INTx) interrupts */ static int vfio_enable_intx(struct rte_intr_handle *intr_handle) { struct vfio_irq_set *irq_set; char irq_set_buf[IRQ_SET_BUF_LEN]; int len, ret; int *fd_ptr; len = sizeof(irq_set_buf); /* enable INTx */ irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; irq_set->count = 1; irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_INTX_IRQ_INDEX; irq_set->start = 0; fd_ptr = (int *) &irq_set->data; *fd_ptr = intr_handle->fd; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error enabling INTx interrupts for fd %d\n", intr_handle->fd); return -1; } /* unmask INTx after enabling */ memset(irq_set, 0, len); len = sizeof(struct vfio_irq_set); irq_set->argsz = len; irq_set->count = 1; irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK; irq_set->index = VFIO_PCI_INTX_IRQ_INDEX; irq_set->start = 0; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd %d\n", intr_handle->fd); return -1; } return 0; } /* disable legacy (INTx) interrupts */ static int vfio_disable_intx(struct rte_intr_handle *intr_handle) { struct vfio_irq_set *irq_set; char irq_set_buf[IRQ_SET_BUF_LEN]; int len, ret; len = sizeof(struct vfio_irq_set); /* mask interrupts before disabling */ irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; irq_set->count = 1; irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK; irq_set->index = VFIO_PCI_INTX_IRQ_INDEX; irq_set->start = 0; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error unmasking INTx interrupts for fd %d\n", intr_handle->fd); return -1; } /* disable INTx*/ memset(irq_set, 0, len); irq_set->argsz = len; irq_set->count = 0; irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_INTX_IRQ_INDEX; irq_set->start = 0; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error disabling INTx interrupts for fd %d\n", intr_handle->fd); return -1; } return 0; } /* enable MSI interrupts */ static int vfio_enable_msi(struct rte_intr_handle *intr_handle) { int len, ret; char irq_set_buf[IRQ_SET_BUF_LEN]; struct vfio_irq_set *irq_set; int *fd_ptr; len = sizeof(irq_set_buf); irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; irq_set->count = 1; irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_MSI_IRQ_INDEX; irq_set->start = 0; fd_ptr = (int *) &irq_set->data; *fd_ptr = intr_handle->fd; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error enabling MSI interrupts for fd %d\n", intr_handle->fd); return -1; } return 0; } /* disable MSI interrupts */ static int vfio_disable_msi(struct rte_intr_handle *intr_handle) { struct vfio_irq_set *irq_set; char irq_set_buf[IRQ_SET_BUF_LEN]; int len, ret; len = sizeof(struct vfio_irq_set); irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; irq_set->count = 0; irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_MSI_IRQ_INDEX; irq_set->start = 0; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) RTE_LOG(ERR, EAL, "Error disabling MSI interrupts for fd %d\n", intr_handle->fd); return ret; } /* enable MSI-X interrupts */ static int vfio_enable_msix(struct rte_intr_handle *intr_handle) { int len, ret; char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; struct vfio_irq_set *irq_set; int *fd_ptr; len = sizeof(irq_set_buf); irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; #ifdef RTE_NEXT_ABI if (!intr_handle->max_intr) intr_handle->max_intr = 1; else if (intr_handle->max_intr > RTE_MAX_RXTX_INTR_VEC_ID) intr_handle->max_intr = RTE_MAX_RXTX_INTR_VEC_ID + 1; irq_set->count = intr_handle->max_intr; #else irq_set->count = 1; #endif irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; irq_set->start = 0; fd_ptr = (int *) &irq_set->data; #ifdef RTE_NEXT_ABI memcpy(fd_ptr, intr_handle->efds, sizeof(intr_handle->efds)); fd_ptr[intr_handle->max_intr - 1] = intr_handle->fd; #else fd_ptr[0] = intr_handle->fd; #endif ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) { RTE_LOG(ERR, EAL, "Error enabling MSI-X interrupts for fd %d\n", intr_handle->fd); return -1; } return 0; } /* disable MSI-X interrupts */ static int vfio_disable_msix(struct rte_intr_handle *intr_handle) { struct vfio_irq_set *irq_set; char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; int len, ret; len = sizeof(struct vfio_irq_set); irq_set = (struct vfio_irq_set *) irq_set_buf; irq_set->argsz = len; irq_set->count = 0; irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER; irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; irq_set->start = 0; ret = ioctl(intr_handle->vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); if (ret) RTE_LOG(ERR, EAL, "Error disabling MSI-X interrupts for fd %d\n", intr_handle->fd); return ret; } #endif static int uio_intx_intr_disable(struct rte_intr_handle *intr_handle) { unsigned char command_high; /* use UIO config file descriptor for uio_pci_generic */ if (pread(intr_handle->uio_cfg_fd, &command_high, 1, 5) != 1) { RTE_LOG(ERR, EAL, "Error reading interrupts status for fd %d\n", intr_handle->uio_cfg_fd); return -1; } /* disable interrupts */ command_high |= 0x4; if (pwrite(intr_handle->uio_cfg_fd, &command_high, 1, 5) != 1) { RTE_LOG(ERR, EAL, "Error disabling interrupts for fd %d\n", intr_handle->uio_cfg_fd); return -1; } return 0; } static int uio_intx_intr_enable(struct rte_intr_handle *intr_handle) { unsigned char command_high; /* use UIO config file descriptor for uio_pci_generic */ if (pread(intr_handle->uio_cfg_fd, &command_high, 1, 5) != 1) { RTE_LOG(ERR, EAL, "Error reading interrupts status for fd %d\n", intr_handle->uio_cfg_fd); return -1; } /* enable interrupts */ command_high &= ~0x4; if (pwrite(intr_handle->uio_cfg_fd, &command_high, 1, 5) != 1) { RTE_LOG(ERR, EAL, "Error enabling interrupts for fd %d\n", intr_handle->uio_cfg_fd); return -1; } return 0; } static int uio_intr_disable(struct rte_intr_handle *intr_handle) { const int value = 0; if (write(intr_handle->fd, &value, sizeof(value)) < 0) { RTE_LOG(ERR, EAL, "Error disabling interrupts for fd %d (%s)\n", intr_handle->fd, strerror(errno)); return -1; } return 0; } static int uio_intr_enable(struct rte_intr_handle *intr_handle) { const int value = 1; if (write(intr_handle->fd, &value, sizeof(value)) < 0) { RTE_LOG(ERR, EAL, "Error enabling interrupts for fd %d (%s)\n", intr_handle->fd, strerror(errno)); return -1; } return 0; } int rte_intr_callback_register(struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb, void *cb_arg) { int ret, wake_thread; struct rte_intr_source *src; struct rte_intr_callback *callback; wake_thread = 0; /* first do parameter checking */ if (intr_handle == NULL || intr_handle->fd < 0 || cb == NULL) { RTE_LOG(ERR, EAL, "Registering with invalid input parameter\n"); return -EINVAL; } /* allocate a new interrupt callback entity */ callback = rte_zmalloc("interrupt callback list", sizeof(*callback), 0); if (callback == NULL) { RTE_LOG(ERR, EAL, "Can not allocate memory\n"); return -ENOMEM; } callback->cb_fn = cb; callback->cb_arg = cb_arg; rte_spinlock_lock(&intr_lock); /* check if there is at least one callback registered for the fd */ TAILQ_FOREACH(src, &intr_sources, next) { if (src->intr_handle.fd == intr_handle->fd) { /* we had no interrupts for this */ if TAILQ_EMPTY(&src->callbacks) wake_thread = 1; TAILQ_INSERT_TAIL(&(src->callbacks), callback, next); ret = 0; break; } } /* no existing callbacks for this - add new source */ if (src == NULL) { if ((src = rte_zmalloc("interrupt source list", sizeof(*src), 0)) == NULL) { RTE_LOG(ERR, EAL, "Can not allocate memory\n"); rte_free(callback); ret = -ENOMEM; } else { src->intr_handle = *intr_handle; TAILQ_INIT(&src->callbacks); TAILQ_INSERT_TAIL(&(src->callbacks), callback, next); TAILQ_INSERT_TAIL(&intr_sources, src, next); wake_thread = 1; ret = 0; } } rte_spinlock_unlock(&intr_lock); /** * check if need to notify the pipe fd waited by epoll_wait to * rebuild the wait list. */ if (wake_thread) if (write(intr_pipe.writefd, "1", 1) < 0) return -EPIPE; return ret; } int rte_intr_callback_unregister(struct rte_intr_handle *intr_handle, rte_intr_callback_fn cb_fn, void *cb_arg) { int ret; struct rte_intr_source *src; struct rte_intr_callback *cb, *next; /* do parameter checking first */ if (intr_handle == NULL || intr_handle->fd < 0) { RTE_LOG(ERR, EAL, "Unregistering with invalid input parameter\n"); return -EINVAL; } rte_spinlock_lock(&intr_lock); /* check if the insterrupt source for the fd is existent */ TAILQ_FOREACH(src, &intr_sources, next) if (src->intr_handle.fd == intr_handle->fd) break; /* No interrupt source registered for the fd */ if (src == NULL) { ret = -ENOENT; /* interrupt source has some active callbacks right now. */ } else if (src->active != 0) { ret = -EAGAIN; /* ok to remove. */ } else { ret = 0; /*walk through the callbacks and remove all that match. */ for (cb = TAILQ_FIRST(&src->callbacks); cb != NULL; cb = next) { next = TAILQ_NEXT(cb, next); if (cb->cb_fn == cb_fn && (cb_arg == (void *)-1 || cb->cb_arg == cb_arg)) { TAILQ_REMOVE(&src->callbacks, cb, next); rte_free(cb); ret++; } } /* all callbacks for that source are removed. */ if (TAILQ_EMPTY(&src->callbacks)) { TAILQ_REMOVE(&intr_sources, src, next); rte_free(src); } } rte_spinlock_unlock(&intr_lock); /* notify the pipe fd waited by epoll_wait to rebuild the wait list */ if (ret >= 0 && write(intr_pipe.writefd, "1", 1) < 0) { ret = -EPIPE; } return ret; } int rte_intr_enable(struct rte_intr_handle *intr_handle) { if (!intr_handle || intr_handle->fd < 0 || intr_handle->uio_cfg_fd < 0) return -1; switch (intr_handle->type){ /* write to the uio fd to enable the interrupt */ case RTE_INTR_HANDLE_UIO: if (uio_intr_enable(intr_handle)) return -1; break; case RTE_INTR_HANDLE_UIO_INTX: if (uio_intx_intr_enable(intr_handle)) return -1; break; /* not used at this moment */ case RTE_INTR_HANDLE_ALARM: return -1; #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: if (vfio_enable_msix(intr_handle)) return -1; break; case RTE_INTR_HANDLE_VFIO_MSI: if (vfio_enable_msi(intr_handle)) return -1; break; case RTE_INTR_HANDLE_VFIO_LEGACY: if (vfio_enable_intx(intr_handle)) return -1; break; #endif /* unknown handle type */ default: RTE_LOG(ERR, EAL, "Unknown handle type of fd %d\n", intr_handle->fd); return -1; } return 0; } int rte_intr_disable(struct rte_intr_handle *intr_handle) { if (!intr_handle || intr_handle->fd < 0 || intr_handle->uio_cfg_fd < 0) return -1; switch (intr_handle->type){ /* write to the uio fd to disable the interrupt */ case RTE_INTR_HANDLE_UIO: if (uio_intr_disable(intr_handle)) return -1; break; case RTE_INTR_HANDLE_UIO_INTX: if (uio_intx_intr_disable(intr_handle)) return -1; break; /* not used at this moment */ case RTE_INTR_HANDLE_ALARM: return -1; #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: if (vfio_disable_msix(intr_handle)) return -1; break; case RTE_INTR_HANDLE_VFIO_MSI: if (vfio_disable_msi(intr_handle)) return -1; break; case RTE_INTR_HANDLE_VFIO_LEGACY: if (vfio_disable_intx(intr_handle)) return -1; break; #endif /* unknown handle type */ default: RTE_LOG(ERR, EAL, "Unknown handle type of fd %d\n", intr_handle->fd); return -1; } return 0; } static int eal_intr_process_interrupts(struct epoll_event *events, int nfds) { int n, bytes_read; struct rte_intr_source *src; struct rte_intr_callback *cb; union rte_intr_read_buffer buf; struct rte_intr_callback active_cb; for (n = 0; n < nfds; n++) { /** * if the pipe fd is ready to read, return out to * rebuild the wait list. */ if (events[n].data.fd == intr_pipe.readfd){ int r = read(intr_pipe.readfd, buf.charbuf, sizeof(buf.charbuf)); RTE_SET_USED(r); return -1; } rte_spinlock_lock(&intr_lock); TAILQ_FOREACH(src, &intr_sources, next) if (src->intr_handle.fd == events[n].data.fd) break; if (src == NULL){ rte_spinlock_unlock(&intr_lock); continue; } /* mark this interrupt source as active and release the lock. */ src->active = 1; rte_spinlock_unlock(&intr_lock); /* set the length to be read dor different handle type */ switch (src->intr_handle.type) { case RTE_INTR_HANDLE_UIO: case RTE_INTR_HANDLE_UIO_INTX: bytes_read = sizeof(buf.uio_intr_count); break; case RTE_INTR_HANDLE_ALARM: bytes_read = sizeof(buf.timerfd_num); break; #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: case RTE_INTR_HANDLE_VFIO_MSI: case RTE_INTR_HANDLE_VFIO_LEGACY: bytes_read = sizeof(buf.vfio_intr_count); break; #endif default: bytes_read = 1; break; } /** * read out to clear the ready-to-be-read flag * for epoll_wait. */ bytes_read = read(events[n].data.fd, &buf, bytes_read); if (bytes_read < 0) { if (errno == EINTR || errno == EWOULDBLOCK) continue; RTE_LOG(ERR, EAL, "Error reading from file " "descriptor %d: %s\n", events[n].data.fd, strerror(errno)); } else if (bytes_read == 0) RTE_LOG(ERR, EAL, "Read nothing from file " "descriptor %d\n", events[n].data.fd); /* grab a lock, again to call callbacks and update status. */ rte_spinlock_lock(&intr_lock); if (bytes_read > 0) { /* Finally, call all callbacks. */ TAILQ_FOREACH(cb, &src->callbacks, next) { /* make a copy and unlock. */ active_cb = *cb; rte_spinlock_unlock(&intr_lock); /* call the actual callback */ active_cb.cb_fn(&src->intr_handle, active_cb.cb_arg); /*get the lock back. */ rte_spinlock_lock(&intr_lock); } } /* we done with that interrupt source, release it. */ src->active = 0; rte_spinlock_unlock(&intr_lock); } return 0; } /** * It handles all the interrupts. * * @param pfd * epoll file descriptor. * @param totalfds * The number of file descriptors added in epoll. * * @return * void */ static void eal_intr_handle_interrupts(int pfd, unsigned totalfds) { struct epoll_event events[totalfds]; int nfds = 0; for(;;) { nfds = epoll_wait(pfd, events, totalfds, EAL_INTR_EPOLL_WAIT_FOREVER); /* epoll_wait fail */ if (nfds < 0) { if (errno == EINTR) continue; RTE_LOG(ERR, EAL, "epoll_wait returns with fail\n"); return; } /* epoll_wait timeout, will never happens here */ else if (nfds == 0) continue; /* epoll_wait has at least one fd ready to read */ if (eal_intr_process_interrupts(events, nfds) < 0) return; } } /** * It builds/rebuilds up the epoll file descriptor with all the * file descriptors being waited on. Then handles the interrupts. * * @param arg * pointer. (unused) * * @return * never return; */ static __attribute__((noreturn)) void * eal_intr_thread_main(__rte_unused void *arg) { struct epoll_event ev; /* host thread, never break out */ for (;;) { /* build up the epoll fd with all descriptors we are to * wait on then pass it to the handle_interrupts function */ static struct epoll_event pipe_event = { .events = EPOLLIN | EPOLLPRI, }; struct rte_intr_source *src; unsigned numfds = 0; /* create epoll fd */ int pfd = epoll_create(1); if (pfd < 0) rte_panic("Cannot create epoll instance\n"); pipe_event.data.fd = intr_pipe.readfd; /** * add pipe fd into wait list, this pipe is used to * rebuild the wait list. */ if (epoll_ctl(pfd, EPOLL_CTL_ADD, intr_pipe.readfd, &pipe_event) < 0) { rte_panic("Error adding fd to %d epoll_ctl, %s\n", intr_pipe.readfd, strerror(errno)); } numfds++; rte_spinlock_lock(&intr_lock); TAILQ_FOREACH(src, &intr_sources, next) { if (src->callbacks.tqh_first == NULL) continue; /* skip those with no callbacks */ ev.events = EPOLLIN | EPOLLPRI; ev.data.fd = src->intr_handle.fd; /** * add all the uio device file descriptor * into wait list. */ if (epoll_ctl(pfd, EPOLL_CTL_ADD, src->intr_handle.fd, &ev) < 0){ rte_panic("Error adding fd %d epoll_ctl, %s\n", src->intr_handle.fd, strerror(errno)); } else numfds++; } rte_spinlock_unlock(&intr_lock); /* serve the interrupt */ eal_intr_handle_interrupts(pfd, numfds); /** * when we return, we need to rebuild the * list of fds to monitor. */ close(pfd); } } int rte_eal_intr_init(void) { int ret = 0; /* init the global interrupt source head */ TAILQ_INIT(&intr_sources); /** * create a pipe which will be waited by epoll and notified to * rebuild the wait list of epoll. */ if (pipe(intr_pipe.pipefd) < 0) return -1; /* create the host thread to wait/handle the interrupt */ ret = pthread_create(&intr_thread, NULL, eal_intr_thread_main, NULL); if (ret != 0) RTE_LOG(ERR, EAL, "Failed to create thread for interrupt handling\n"); return -ret; } #ifdef RTE_NEXT_ABI static void eal_intr_proc_rxtx_intr(int fd, const struct rte_intr_handle *intr_handle) { union rte_intr_read_buffer buf; int bytes_read = 1; switch (intr_handle->type) { case RTE_INTR_HANDLE_UIO: case RTE_INTR_HANDLE_UIO_INTX: bytes_read = sizeof(buf.uio_intr_count); break; #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: case RTE_INTR_HANDLE_VFIO_MSI: case RTE_INTR_HANDLE_VFIO_LEGACY: bytes_read = sizeof(buf.vfio_intr_count); break; #endif default: bytes_read = 1; RTE_LOG(INFO, EAL, "unexpected intr type\n"); break; } /** * read out to clear the ready-to-be-read flag * for epoll_wait. */ do { bytes_read = read(fd, &buf, bytes_read); if (bytes_read < 0) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) continue; RTE_LOG(ERR, EAL, "Error reading from fd %d: %s\n", fd, strerror(errno)); } else if (bytes_read == 0) RTE_LOG(ERR, EAL, "Read nothing from fd %d\n", fd); return; } while (1); } #endif static int eal_epoll_process_event(struct epoll_event *evs, unsigned int n, struct rte_epoll_event *events) { unsigned int i, count = 0; struct rte_epoll_event *rev; for (i = 0; i < n; i++) { rev = evs[i].data.ptr; if (!rev || !rte_atomic32_cmpset(&rev->status, RTE_EPOLL_VALID, RTE_EPOLL_EXEC)) continue; events[count].status = RTE_EPOLL_VALID; events[count].fd = rev->fd; events[count].epfd = rev->epfd; events[count].epdata.event = rev->epdata.event; events[count].epdata.data = rev->epdata.data; if (rev->epdata.cb_fun) rev->epdata.cb_fun(rev->fd, rev->epdata.cb_arg); rte_compiler_barrier(); rev->status = RTE_EPOLL_VALID; count++; } return count; } static inline int eal_init_tls_epfd(void) { int pfd = epoll_create(255); if (pfd < 0) { RTE_LOG(ERR, EAL, "Cannot create epoll instance\n"); return -1; } return pfd; } int rte_intr_tls_epfd(void) { if (RTE_PER_LCORE(_epfd) == -1) RTE_PER_LCORE(_epfd) = eal_init_tls_epfd(); return RTE_PER_LCORE(_epfd); } int rte_epoll_wait(int epfd, struct rte_epoll_event *events, int maxevents, int timeout) { struct epoll_event evs[maxevents]; int rc; if (!events) { RTE_LOG(ERR, EAL, "rte_epoll_event can't be NULL\n"); return -1; } /* using per thread epoll fd */ if (epfd == RTE_EPOLL_PER_THREAD) epfd = rte_intr_tls_epfd(); while (1) { rc = epoll_wait(epfd, evs, maxevents, timeout); if (likely(rc > 0)) { /* epoll_wait has at least one fd ready to read */ rc = eal_epoll_process_event(evs, rc, events); break; } else if (rc < 0) { if (errno == EINTR) continue; /* epoll_wait fail */ RTE_LOG(ERR, EAL, "epoll_wait returns with fail %s\n", strerror(errno)); rc = -1; break; } } return rc; } static inline void eal_epoll_data_safe_free(struct rte_epoll_event *ev) { while (!rte_atomic32_cmpset(&ev->status, RTE_EPOLL_VALID, RTE_EPOLL_INVALID)) while (ev->status != RTE_EPOLL_VALID) rte_pause(); memset(&ev->epdata, 0, sizeof(ev->epdata)); ev->fd = -1; ev->epfd = -1; } int rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event) { struct epoll_event ev; if (!event) { RTE_LOG(ERR, EAL, "rte_epoll_event can't be NULL\n"); return -1; } /* using per thread epoll fd */ if (epfd == RTE_EPOLL_PER_THREAD) epfd = rte_intr_tls_epfd(); if (op == EPOLL_CTL_ADD) { event->status = RTE_EPOLL_VALID; event->fd = fd; /* ignore fd in event */ event->epfd = epfd; ev.data.ptr = (void *)event; } ev.events = event->epdata.event; if (epoll_ctl(epfd, op, fd, &ev) < 0) { RTE_LOG(ERR, EAL, "Error op %d fd %d epoll_ctl, %s\n", op, fd, strerror(errno)); if (op == EPOLL_CTL_ADD) /* rollback status when CTL_ADD fail */ event->status = RTE_EPOLL_INVALID; return -1; } if (op == EPOLL_CTL_DEL && event->status != RTE_EPOLL_INVALID) eal_epoll_data_safe_free(event); return 0; } #ifdef RTE_NEXT_ABI int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data) { struct rte_epoll_event *rev; struct rte_epoll_data *epdata; int epfd_op; int rc = 0; if (!intr_handle || intr_handle->nb_efd == 0 || vec >= intr_handle->nb_efd) { RTE_LOG(ERR, EAL, "Wrong intr vector number.\n"); return -EPERM; } switch (op) { case RTE_INTR_EVENT_ADD: epfd_op = EPOLL_CTL_ADD; rev = &intr_handle->elist[vec]; if (rev->status != RTE_EPOLL_INVALID) { RTE_LOG(INFO, EAL, "Event already been added.\n"); return -EEXIST; } /* attach to intr vector fd */ epdata = &rev->epdata; epdata->event = EPOLLIN | EPOLLPRI | EPOLLET; epdata->data = data; epdata->cb_fun = (rte_intr_event_cb_t)eal_intr_proc_rxtx_intr; epdata->cb_arg = (void *)intr_handle; rc = rte_epoll_ctl(epfd, epfd_op, intr_handle->efds[vec], rev); if (!rc) RTE_LOG(DEBUG, EAL, "efd %d associated with vec %d added on epfd %d" "\n", rev->fd, vec, epfd); else rc = -EPERM; break; case RTE_INTR_EVENT_DEL: epfd_op = EPOLL_CTL_DEL; rev = &intr_handle->elist[vec]; if (rev->status == RTE_EPOLL_INVALID) { RTE_LOG(INFO, EAL, "Event does not exist.\n"); return -EPERM; } rc = rte_epoll_ctl(rev->epfd, epfd_op, rev->fd, rev); if (rc) rc = -EPERM; break; default: RTE_LOG(ERR, EAL, "event op type mismatch\n"); rc = -EPERM; } return rc; } int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) { uint32_t i; int fd; uint32_t n = RTE_MIN(nb_efd, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); if (intr_handle->type == RTE_INTR_HANDLE_VFIO_MSIX) { for (i = 0; i < n; i++) { fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (fd < 0) { RTE_LOG(ERR, EAL, "can't setup eventfd, error %i (%s)\n", errno, strerror(errno)); return -1; } intr_handle->efds[i] = fd; } intr_handle->nb_efd = n; intr_handle->max_intr = NB_OTHER_INTR + n; } else { intr_handle->efds[0] = intr_handle->fd; intr_handle->nb_efd = RTE_MIN(nb_efd, 1U); intr_handle->max_intr = NB_OTHER_INTR; } return 0; } void rte_intr_efd_disable(struct rte_intr_handle *intr_handle) { uint32_t i; struct rte_epoll_event *rev; for (i = 0; i < intr_handle->nb_efd; i++) { rev = &intr_handle->elist[i]; if (rev->status == RTE_EPOLL_INVALID) continue; if (rte_epoll_ctl(rev->epfd, EPOLL_CTL_DEL, rev->fd, rev)) { /* force free if the entry valid */ eal_epoll_data_safe_free(rev); rev->status = RTE_EPOLL_INVALID; } } if (intr_handle->max_intr > intr_handle->nb_efd) { for (i = 0; i < intr_handle->nb_efd; i++) close(intr_handle->efds[i]); } intr_handle->nb_efd = 0; intr_handle->max_intr = 0; } int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) { return !(!intr_handle->nb_efd); } int rte_intr_allow_others(struct rte_intr_handle *intr_handle) { return !!(intr_handle->max_intr - intr_handle->nb_efd); } #else int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data) { RTE_SET_USED(intr_handle); RTE_SET_USED(epfd); RTE_SET_USED(op); RTE_SET_USED(vec); RTE_SET_USED(data); return -ENOTSUP; } int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd) { RTE_SET_USED(intr_handle); RTE_SET_USED(nb_efd); return 0; } void rte_intr_efd_disable(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); } int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); return 0; } int rte_intr_allow_others(struct rte_intr_handle *intr_handle) { RTE_SET_USED(intr_handle); return 1; } #endif ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_ivshmem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef RTE_LIBRTE_IVSHMEM /* hide it from coverage */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_internal_cfg.h" #include "eal_private.h" #define PCI_VENDOR_ID_IVSHMEM 0x1Af4 #define PCI_DEVICE_ID_IVSHMEM 0x1110 #define IVSHMEM_MAGIC 0x0BADC0DE #define IVSHMEM_RESOURCE_PATH "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource2" #define IVSHMEM_CONFIG_PATH "/var/run/.%s_ivshmem_config" #define PHYS 0x1 #define VIRT 0x2 #define IOREMAP 0x4 #define FULL (PHYS|VIRT|IOREMAP) #define METADATA_SIZE_ALIGNED \ (RTE_ALIGN_CEIL(sizeof(struct rte_ivshmem_metadata),pagesz)) #define CONTAINS(x,y)\ (((y).addr_64 >= (x).addr_64) && ((y).addr_64 < (x).addr_64 + (x).len)) #define DIM(x) (sizeof(x)/sizeof(x[0])) struct ivshmem_pci_device { char path[PATH_MAX]; phys_addr_t ioremap_addr; }; /* data type to store in config */ struct ivshmem_segment { struct rte_ivshmem_metadata_entry entry; uint64_t align; char path[PATH_MAX]; }; struct ivshmem_shared_config { struct ivshmem_segment segment[RTE_MAX_MEMSEG]; uint32_t segment_idx; struct ivshmem_pci_device pci_devs[RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS]; uint32_t pci_devs_idx; }; static struct ivshmem_shared_config * ivshmem_config; static int memseg_idx; static int pagesz; /* Tailq heads to add rings to */ TAILQ_HEAD(rte_ring_list, rte_tailq_entry); /* * Utility functions */ static int is_ivshmem_device(struct rte_pci_device * dev) { return (dev->id.vendor_id == PCI_VENDOR_ID_IVSHMEM && dev->id.device_id == PCI_DEVICE_ID_IVSHMEM); } static void * map_metadata(int fd, uint64_t len) { size_t metadata_len = sizeof(struct rte_ivshmem_metadata); size_t aligned_len = METADATA_SIZE_ALIGNED; return mmap(NULL, metadata_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, len - aligned_len); } static void unmap_metadata(void * ptr) { munmap(ptr, sizeof(struct rte_ivshmem_metadata)); } static int has_ivshmem_metadata(int fd, uint64_t len) { struct rte_ivshmem_metadata metadata; void * ptr; ptr = map_metadata(fd, len); if (ptr == MAP_FAILED) return -1; metadata = *(struct rte_ivshmem_metadata*) (ptr); unmap_metadata(ptr); return metadata.magic_number == IVSHMEM_MAGIC; } static void remove_segment(struct ivshmem_segment * ms, int len, int idx) { int i; for (i = idx; i < len - 1; i++) memcpy(&ms[i], &ms[i+1], sizeof(struct ivshmem_segment)); memset(&ms[len-1], 0, sizeof(struct ivshmem_segment)); } static int overlap(const struct rte_memzone * mz1, const struct rte_memzone * mz2) { uint64_t start1, end1, start2, end2; uint64_t p_start1, p_end1, p_start2, p_end2; uint64_t i_start1, i_end1, i_start2, i_end2; int result = 0; /* gather virtual addresses */ start1 = mz1->addr_64; end1 = mz1->addr_64 + mz1->len; start2 = mz2->addr_64; end2 = mz2->addr_64 + mz2->len; /* gather physical addresses */ p_start1 = mz1->phys_addr; p_end1 = mz1->phys_addr + mz1->len; p_start2 = mz2->phys_addr; p_end2 = mz2->phys_addr + mz2->len; /* gather ioremap addresses */ i_start1 = mz1->ioremap_addr; i_end1 = mz1->ioremap_addr + mz1->len; i_start2 = mz2->ioremap_addr; i_end2 = mz2->ioremap_addr + mz2->len; /* check for overlap in virtual addresses */ if (start1 >= start2 && start1 < end2) result |= VIRT; if (start2 >= start1 && start2 < end1) result |= VIRT; /* check for overlap in physical addresses */ if (p_start1 >= p_start2 && p_start1 < p_end2) result |= PHYS; if (p_start2 >= p_start1 && p_start2 < p_end1) result |= PHYS; /* check for overlap in ioremap addresses */ if (i_start1 >= i_start2 && i_start1 < i_end2) result |= IOREMAP; if (i_start2 >= i_start1 && i_start2 < i_end1) result |= IOREMAP; return result; } static int adjacent(const struct rte_memzone * mz1, const struct rte_memzone * mz2) { uint64_t start1, end1, start2, end2; uint64_t p_start1, p_end1, p_start2, p_end2; uint64_t i_start1, i_end1, i_start2, i_end2; int result = 0; /* gather virtual addresses */ start1 = mz1->addr_64; end1 = mz1->addr_64 + mz1->len; start2 = mz2->addr_64; end2 = mz2->addr_64 + mz2->len; /* gather physical addresses */ p_start1 = mz1->phys_addr; p_end1 = mz1->phys_addr + mz1->len; p_start2 = mz2->phys_addr; p_end2 = mz2->phys_addr + mz2->len; /* gather ioremap addresses */ i_start1 = mz1->ioremap_addr; i_end1 = mz1->ioremap_addr + mz1->len; i_start2 = mz2->ioremap_addr; i_end2 = mz2->ioremap_addr + mz2->len; /* check if segments are virtually adjacent */ if (start1 == end2) result |= VIRT; if (start2 == end1) result |= VIRT; /* check if segments are physically adjacent */ if (p_start1 == p_end2) result |= PHYS; if (p_start2 == p_end1) result |= PHYS; /* check if segments are ioremap-adjacent */ if (i_start1 == i_end2) result |= IOREMAP; if (i_start2 == i_end1) result |= IOREMAP; return result; } static int has_adjacent_segments(struct ivshmem_segment * ms, int len) { int i, j, a; for (i = 0; i < len; i++) for (j = i + 1; j < len; j++) { a = adjacent(&ms[i].entry.mz, &ms[j].entry.mz); /* check if segments are adjacent virtually and/or physically but * not ioremap (since that would indicate that they are from * different PCI devices and thus don't need to be concatenated. */ if ((a & (VIRT|PHYS)) > 0 && (a & IOREMAP) == 0) return 1; } return 0; } static int has_overlapping_segments(struct ivshmem_segment * ms, int len) { int i, j; for (i = 0; i < len; i++) for (j = i + 1; j < len; j++) if (overlap(&ms[i].entry.mz, &ms[j].entry.mz)) return 1; return 0; } static int seg_compare(const void * a, const void * b) { const struct ivshmem_segment * s1 = (const struct ivshmem_segment*) a; const struct ivshmem_segment * s2 = (const struct ivshmem_segment*) b; /* move unallocated zones to the end */ if (s1->entry.mz.addr == NULL && s2->entry.mz.addr == NULL) return 0; if (s1->entry.mz.addr == 0) return 1; if (s2->entry.mz.addr == 0) return -1; return s1->entry.mz.phys_addr > s2->entry.mz.phys_addr; } #ifdef RTE_LIBRTE_IVSHMEM_DEBUG static void entry_dump(struct rte_ivshmem_metadata_entry *e) { RTE_LOG(DEBUG, EAL, "\tvirt: %p-%p\n", e->mz.addr, RTE_PTR_ADD(e->mz.addr, e->mz.len)); RTE_LOG(DEBUG, EAL, "\tphys: 0x%" PRIx64 "-0x%" PRIx64 "\n", e->mz.phys_addr, e->mz.phys_addr + e->mz.len); RTE_LOG(DEBUG, EAL, "\tio: 0x%" PRIx64 "-0x%" PRIx64 "\n", e->mz.ioremap_addr, e->mz.ioremap_addr + e->mz.len); RTE_LOG(DEBUG, EAL, "\tlen: 0x%" PRIx64 "\n", e->mz.len); RTE_LOG(DEBUG, EAL, "\toff: 0x%" PRIx64 "\n", e->offset); } #endif /* * Actual useful code */ /* read through metadata mapped from the IVSHMEM device */ static int read_metadata(char * path, int path_len, int fd, uint64_t flen) { struct rte_ivshmem_metadata metadata; struct rte_ivshmem_metadata_entry * entry; int idx, i; void * ptr; ptr = map_metadata(fd, flen); if (ptr == MAP_FAILED) return -1; metadata = *(struct rte_ivshmem_metadata*) (ptr); unmap_metadata(ptr); RTE_LOG(DEBUG, EAL, "Parsing metadata for \"%s\"\n", metadata.name); idx = ivshmem_config->segment_idx; for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_ENTRIES && idx <= RTE_MAX_MEMSEG; i++) { if (idx == RTE_MAX_MEMSEG) { RTE_LOG(ERR, EAL, "Not enough memory segments!\n"); return -1; } entry = &metadata.entry[i]; /* stop on uninitialized memzone */ if (entry->mz.len == 0) break; /* copy metadata entry */ memcpy(&ivshmem_config->segment[idx].entry, entry, sizeof(struct rte_ivshmem_metadata_entry)); /* copy path */ snprintf(ivshmem_config->segment[idx].path, path_len, "%s", path); idx++; } ivshmem_config->segment_idx = idx; return 0; } /* check through each segment and look for adjacent or overlapping ones. */ static int cleanup_segments(struct ivshmem_segment * ms, int tbl_len) { struct ivshmem_segment * s, * tmp; int i, j, concat, seg_adjacent, seg_overlapping; uint64_t start1, start2, end1, end2, p_start1, p_start2, i_start1, i_start2; qsort(ms, tbl_len, sizeof(struct ivshmem_segment), seg_compare); while (has_overlapping_segments(ms, tbl_len) || has_adjacent_segments(ms, tbl_len)) { for (i = 0; i < tbl_len; i++) { s = &ms[i]; concat = 0; for (j = i + 1; j < tbl_len; j++) { tmp = &ms[j]; /* check if this segment is overlapping with existing segment, * or is adjacent to existing segment */ seg_overlapping = overlap(&s->entry.mz, &tmp->entry.mz); seg_adjacent = adjacent(&s->entry.mz, &tmp->entry.mz); /* check if segments fully overlap or are fully adjacent */ if ((seg_adjacent == FULL) || (seg_overlapping == FULL)) { #ifdef RTE_LIBRTE_IVSHMEM_DEBUG RTE_LOG(DEBUG, EAL, "Concatenating segments\n"); RTE_LOG(DEBUG, EAL, "Segment %i:\n", i); entry_dump(&s->entry); RTE_LOG(DEBUG, EAL, "Segment %i:\n", j); entry_dump(&tmp->entry); #endif start1 = s->entry.mz.addr_64; start2 = tmp->entry.mz.addr_64; p_start1 = s->entry.mz.phys_addr; p_start2 = tmp->entry.mz.phys_addr; i_start1 = s->entry.mz.ioremap_addr; i_start2 = tmp->entry.mz.ioremap_addr; end1 = s->entry.mz.addr_64 + s->entry.mz.len; end2 = tmp->entry.mz.addr_64 + tmp->entry.mz.len; /* settle for minimum start address and maximum length */ s->entry.mz.addr_64 = RTE_MIN(start1, start2); s->entry.mz.phys_addr = RTE_MIN(p_start1, p_start2); s->entry.mz.ioremap_addr = RTE_MIN(i_start1, i_start2); s->entry.offset = RTE_MIN(s->entry.offset, tmp->entry.offset); s->entry.mz.len = RTE_MAX(end1, end2) - s->entry.mz.addr_64; concat = 1; #ifdef RTE_LIBRTE_IVSHMEM_DEBUG RTE_LOG(DEBUG, EAL, "Resulting segment:\n"); entry_dump(&s->entry); #endif } /* if segments not fully overlap, we have an error condition. * adjacent segments can coexist. */ else if (seg_overlapping > 0) { RTE_LOG(ERR, EAL, "Segments %i and %i overlap!\n", i, j); #ifdef RTE_LIBRTE_IVSHMEM_DEBUG RTE_LOG(DEBUG, EAL, "Segment %i:\n", i); entry_dump(&s->entry); RTE_LOG(DEBUG, EAL, "Segment %i:\n", j); entry_dump(&tmp->entry); #endif return -1; } if (concat) break; } /* if we concatenated, remove segment at j */ if (concat) { remove_segment(ms, tbl_len, j); tbl_len--; break; } } } return tbl_len; } static int create_shared_config(void) { char path[PATH_MAX]; int fd; /* build ivshmem config file path */ snprintf(path, sizeof(path), IVSHMEM_CONFIG_PATH, internal_config.hugefile_prefix); fd = open(path, O_CREAT | O_RDWR, 0600); if (fd < 0) { RTE_LOG(ERR, EAL, "Could not open %s: %s\n", path, strerror(errno)); return -1; } /* try ex-locking first - if the file is locked, we have a problem */ if (flock(fd, LOCK_EX | LOCK_NB) == -1) { RTE_LOG(ERR, EAL, "Locking %s failed: %s\n", path, strerror(errno)); close(fd); return -1; } if (ftruncate(fd, sizeof(struct ivshmem_shared_config)) < 0) { RTE_LOG(ERR, EAL, "ftruncate failed: %s\n", strerror(errno)); return -1; } ivshmem_config = mmap(NULL, sizeof(struct ivshmem_shared_config), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ivshmem_config == MAP_FAILED) return -1; memset(ivshmem_config, 0, sizeof(struct ivshmem_shared_config)); /* change the exclusive lock we got earlier to a shared lock */ if (flock(fd, LOCK_SH | LOCK_NB) == -1) { RTE_LOG(ERR, EAL, "Locking %s failed: %s \n", path, strerror(errno)); return -1; } close(fd); return 0; } /* open shared config file and, if present, map the config. * having no config file is not an error condition, as we later check if * ivshmem_config is NULL (if it is, that means nothing was mapped). */ static int open_shared_config(void) { char path[PATH_MAX]; int fd; /* build ivshmem config file path */ snprintf(path, sizeof(path), IVSHMEM_CONFIG_PATH, internal_config.hugefile_prefix); fd = open(path, O_RDONLY); /* if the file doesn't exist, just return success */ if (fd < 0 && errno == ENOENT) return 0; /* else we have an error condition */ else if (fd < 0) { RTE_LOG(ERR, EAL, "Could not open %s: %s\n", path, strerror(errno)); return -1; } /* try ex-locking first - if the lock *does* succeed, this means it's a * stray config file, so it should be deleted. */ if (flock(fd, LOCK_EX | LOCK_NB) != -1) { /* if we can't remove the file, something is wrong */ if (unlink(path) < 0) { RTE_LOG(ERR, EAL, "Could not remove %s: %s\n", path, strerror(errno)); return -1; } /* release the lock */ flock(fd, LOCK_UN); close(fd); /* return success as having a stray config file is equivalent to not * having config file at all. */ return 0; } ivshmem_config = mmap(NULL, sizeof(struct ivshmem_shared_config), PROT_READ, MAP_SHARED, fd, 0); if (ivshmem_config == MAP_FAILED) return -1; /* place a shared lock on config file */ if (flock(fd, LOCK_SH | LOCK_NB) == -1) { RTE_LOG(ERR, EAL, "Locking %s failed: %s \n", path, strerror(errno)); return -1; } close(fd); return 0; } /* * This function does the following: * * 1) Builds a table of ivshmem_segments with proper offset alignment * 2) Cleans up that table so that we don't have any overlapping or adjacent * memory segments * 3) Creates memsegs from this table and maps them into memory. */ static inline int map_all_segments(void) { struct ivshmem_segment ms_tbl[RTE_MAX_MEMSEG]; struct ivshmem_pci_device * pci_dev; struct rte_mem_config * mcfg; struct ivshmem_segment * seg; int fd, fd_zero; unsigned i, j; struct rte_memzone mz; struct rte_memseg ms; void * base_addr; uint64_t align, len; phys_addr_t ioremap_addr; ioremap_addr = 0; memset(ms_tbl, 0, sizeof(ms_tbl)); memset(&mz, 0, sizeof(struct rte_memzone)); memset(&ms, 0, sizeof(struct rte_memseg)); /* first, build a table of memsegs to map, to avoid failed mmaps due to * overlaps */ for (i = 0; i < ivshmem_config->segment_idx && i <= RTE_MAX_MEMSEG; i++) { if (i == RTE_MAX_MEMSEG) { RTE_LOG(ERR, EAL, "Too many segments requested!\n"); return -1; } seg = &ivshmem_config->segment[i]; /* copy segment to table */ memcpy(&ms_tbl[i], seg, sizeof(struct ivshmem_segment)); /* find ioremap addr */ for (j = 0; j < DIM(ivshmem_config->pci_devs); j++) { pci_dev = &ivshmem_config->pci_devs[j]; if (!strncmp(pci_dev->path, seg->path, sizeof(pci_dev->path))) { ioremap_addr = pci_dev->ioremap_addr; break; } } if (ioremap_addr == 0) { RTE_LOG(ERR, EAL, "Cannot find ioremap addr!\n"); return -1; } /* work out alignments */ align = seg->entry.mz.addr_64 - RTE_ALIGN_FLOOR(seg->entry.mz.addr_64, 0x1000); len = RTE_ALIGN_CEIL(seg->entry.mz.len + align, 0x1000); /* save original alignments */ ms_tbl[i].align = align; /* create a memory zone */ mz.addr_64 = seg->entry.mz.addr_64 - align; mz.len = len; mz.hugepage_sz = seg->entry.mz.hugepage_sz; mz.phys_addr = seg->entry.mz.phys_addr - align; /* find true physical address */ mz.ioremap_addr = ioremap_addr + seg->entry.offset - align; ms_tbl[i].entry.offset = seg->entry.offset - align; memcpy(&ms_tbl[i].entry.mz, &mz, sizeof(struct rte_memzone)); } /* clean up the segments */ memseg_idx = cleanup_segments(ms_tbl, ivshmem_config->segment_idx); if (memseg_idx < 0) return -1; mcfg = rte_eal_get_configuration()->mem_config; fd_zero = open("/dev/zero", O_RDWR); if (fd_zero < 0) { RTE_LOG(ERR, EAL, "Cannot open /dev/zero: %s\n", strerror(errno)); return -1; } /* create memsegs and put them into DPDK memory */ for (i = 0; i < (unsigned) memseg_idx; i++) { seg = &ms_tbl[i]; ms.addr_64 = seg->entry.mz.addr_64; ms.hugepage_sz = seg->entry.mz.hugepage_sz; ms.len = seg->entry.mz.len; ms.nchannel = rte_memory_get_nchannel(); ms.nrank = rte_memory_get_nrank(); ms.phys_addr = seg->entry.mz.phys_addr; ms.ioremap_addr = seg->entry.mz.ioremap_addr; ms.socket_id = seg->entry.mz.socket_id; base_addr = mmap(ms.addr, ms.len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_zero, 0); if (base_addr == MAP_FAILED || base_addr != ms.addr) { RTE_LOG(ERR, EAL, "Cannot map /dev/zero!\n"); return -1; } fd = open(seg->path, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", seg->path, strerror(errno)); return -1; } munmap(ms.addr, ms.len); base_addr = mmap(ms.addr, ms.len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, seg->entry.offset); if (base_addr == MAP_FAILED || base_addr != ms.addr) { RTE_LOG(ERR, EAL, "Cannot map segment into memory: " "expected %p got %p (%s)\n", ms.addr, base_addr, strerror(errno)); return -1; } RTE_LOG(DEBUG, EAL, "Memory segment mapped: %p (len %" PRIx64 ") at " "offset 0x%" PRIx64 "\n", ms.addr, ms.len, seg->entry.offset); /* put the pointers back into their real positions using original * alignment */ ms.addr_64 += seg->align; ms.phys_addr += seg->align; ms.ioremap_addr += seg->align; ms.len -= seg->align; /* at this point, the rest of DPDK memory is not initialized, so we * expect memsegs to be empty */ memcpy(&mcfg->memseg[i], &ms, sizeof(struct rte_memseg)); close(fd); RTE_LOG(DEBUG, EAL, "IVSHMEM segment found, size: 0x%lx\n", ms.len); } return 0; } /* this happens at a later stage, after general EAL memory initialization */ int rte_eal_ivshmem_obj_init(void) { struct rte_ring_list* ring_list = NULL; struct rte_mem_config * mcfg; struct ivshmem_segment * seg; struct rte_memzone * mz; struct rte_ring * r; struct rte_tailq_entry *te; unsigned i, ms, idx; uint64_t offset; /* secondary process would not need any object discovery - it'll all * already be in shared config */ if (rte_eal_process_type() != RTE_PROC_PRIMARY || ivshmem_config == NULL) return 0; /* check that we have an initialised ring tail queue */ ring_list = RTE_TAILQ_LOOKUP(RTE_TAILQ_RING_NAME, rte_ring_list); if (ring_list == NULL) { RTE_LOG(ERR, EAL, "No rte_ring tailq found!\n"); return -1; } mcfg = rte_eal_get_configuration()->mem_config; /* create memzones */ for (i = 0; i < ivshmem_config->segment_idx && i <= RTE_MAX_MEMZONE; i++) { seg = &ivshmem_config->segment[i]; /* add memzone */ if (mcfg->memzone_cnt == RTE_MAX_MEMZONE) { RTE_LOG(ERR, EAL, "No more memory zones available!\n"); return -1; } idx = mcfg->memzone_cnt; RTE_LOG(DEBUG, EAL, "Found memzone: '%s' at %p (len 0x%" PRIx64 ")\n", seg->entry.mz.name, seg->entry.mz.addr, seg->entry.mz.len); memcpy(&mcfg->memzone[idx], &seg->entry.mz, sizeof(struct rte_memzone)); /* find ioremap address */ for (ms = 0; ms <= RTE_MAX_MEMSEG; ms++) { if (ms == RTE_MAX_MEMSEG) { RTE_LOG(ERR, EAL, "Physical address of segment not found!\n"); return -1; } if (CONTAINS(mcfg->memseg[ms], mcfg->memzone[idx])) { offset = mcfg->memzone[idx].addr_64 - mcfg->memseg[ms].addr_64; mcfg->memzone[idx].ioremap_addr = mcfg->memseg[ms].ioremap_addr + offset; break; } } mcfg->memzone_cnt++; } rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find rings */ for (i = 0; i < mcfg->memzone_cnt; i++) { mz = &mcfg->memzone[i]; /* check if memzone has a ring prefix */ if (strncmp(mz->name, RTE_RING_MZ_PREFIX, sizeof(RTE_RING_MZ_PREFIX) - 1) != 0) continue; r = (struct rte_ring*) (mz->addr_64); te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n"); return -1; } te->data = (void *) r; TAILQ_INSERT_TAIL(ring_list, te, next); RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr); } rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); #ifdef RTE_LIBRTE_IVSHMEM_DEBUG rte_memzone_dump(stdout); rte_ring_list_dump(stdout); #endif return 0; } /* initialize ivshmem structures */ int rte_eal_ivshmem_init(void) { struct rte_pci_device * dev; struct rte_pci_resource * res; int fd, ret; char path[PATH_MAX]; /* initialize everything to 0 */ memset(path, 0, sizeof(path)); ivshmem_config = NULL; pagesz = getpagesize(); RTE_LOG(DEBUG, EAL, "Searching for IVSHMEM devices...\n"); if (rte_eal_process_type() == RTE_PROC_SECONDARY) { if (open_shared_config() < 0) { RTE_LOG(ERR, EAL, "Could not open IVSHMEM config!\n"); return -1; } } else { TAILQ_FOREACH(dev, &pci_device_list, next) { if (is_ivshmem_device(dev)) { /* IVSHMEM memory is always on BAR2 */ res = &dev->mem_resource[2]; /* if we don't have a BAR2 */ if (res->len == 0) continue; /* construct pci device path */ snprintf(path, sizeof(path), IVSHMEM_RESOURCE_PATH, dev->addr.domain, dev->addr.bus, dev->addr.devid, dev->addr.function); /* try to find memseg */ fd = open(path, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", path); return -1; } /* check if it's a DPDK IVSHMEM device */ ret = has_ivshmem_metadata(fd, res->len); /* is DPDK device */ if (ret == 1) { /* config file creation is deferred until the first * DPDK device is found. then, it has to be created * only once. */ if (ivshmem_config == NULL && create_shared_config() < 0) { RTE_LOG(ERR, EAL, "Could not create IVSHMEM config!\n"); close(fd); return -1; } if (read_metadata(path, sizeof(path), fd, res->len) < 0) { RTE_LOG(ERR, EAL, "Could not read metadata from" " device %02x:%02x.%x!\n", dev->addr.bus, dev->addr.devid, dev->addr.function); close(fd); return -1; } if (ivshmem_config->pci_devs_idx == RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS) { RTE_LOG(WARNING, EAL, "IVSHMEM PCI device limit exceeded. Increase " "CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS in " "your config file.\n"); break; } RTE_LOG(INFO, EAL, "Found IVSHMEM device %02x:%02x.%x\n", dev->addr.bus, dev->addr.devid, dev->addr.function); ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].ioremap_addr = res->phys_addr; snprintf(ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].path, sizeof(ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].path), "%s", path); ivshmem_config->pci_devs_idx++; } /* failed to read */ else if (ret < 0) { RTE_LOG(ERR, EAL, "Could not read IVSHMEM device: %s\n", strerror(errno)); close(fd); return -1; } /* not a DPDK device */ else RTE_LOG(DEBUG, EAL, "Skipping non-DPDK IVSHMEM device\n"); /* close the BAR fd */ close(fd); } } } /* ivshmem_config is not NULL only if config was created and/or mapped */ if (ivshmem_config) { if (map_all_segments() < 0) { RTE_LOG(ERR, EAL, "Mapping IVSHMEM segments failed!\n"); return -1; } } else { RTE_LOG(DEBUG, EAL, "No IVSHMEM configuration found! \n"); } return 0; } #endif ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_lcore.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_filesystem.h" #include "eal_thread.h" #define SYS_CPU_DIR "/sys/devices/system/cpu/cpu%u" #define CORE_ID_FILE "topology/core_id" #define NUMA_NODE_PATH "/sys/devices/system/node" /* Check if a cpu is present by the presence of the cpu information for it */ int eal_cpu_detected(unsigned lcore_id) { char path[PATH_MAX]; int len = snprintf(path, sizeof(path), SYS_CPU_DIR "/"CORE_ID_FILE, lcore_id); if (len <= 0 || (unsigned)len >= sizeof(path)) return 0; if (access(path, F_OK) != 0) return 0; return 1; } /* * Get CPU socket id (NUMA node) for a logical core. * * This searches each nodeX directories in /sys for the symlink for the given * lcore_id and returns the numa node where the lcore is found. If lcore is not * found on any numa node, returns zero. */ unsigned eal_cpu_socket_id(unsigned lcore_id) { unsigned socket; for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/node%u/cpu%u", NUMA_NODE_PATH, socket, lcore_id); if (access(path, F_OK) == 0) return socket; } return 0; } /* Get the cpu core id value from the /sys/.../cpuX core_id value */ unsigned eal_cpu_core_id(unsigned lcore_id) { char path[PATH_MAX]; unsigned long id; int len = snprintf(path, sizeof(path), SYS_CPU_DIR "/%s", lcore_id, CORE_ID_FILE); if (len <= 0 || (unsigned)len >= sizeof(path)) goto err; if (eal_parse_sysfs_value(path, &id) != 0) goto err; return (unsigned)id; err: RTE_LOG(ERR, EAL, "Error reading core id value from %s " "for lcore %u - assuming core 0\n", SYS_CPU_DIR, lcore_id); return 0; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_log.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" /* * default log function, used once mempool (hence log history) is * available */ static ssize_t console_log_write(__attribute__((unused)) void *c, const char *buf, size_t size) { char copybuf[BUFSIZ + 1]; ssize_t ret; uint32_t loglevel; /* add this log in history */ rte_log_add_in_history(buf, size); /* write on stdout */ ret = fwrite(buf, 1, size, stdout); fflush(stdout); /* truncate message if too big (should not happen) */ if (size > BUFSIZ) size = BUFSIZ; /* Syslog error levels are from 0 to 7, so subtract 1 to convert */ loglevel = rte_log_cur_msg_loglevel() - 1; memcpy(copybuf, buf, size); copybuf[size] = '\0'; /* write on syslog too */ syslog(loglevel, "%s", copybuf); return ret; } static cookie_io_functions_t console_log_func = { .write = console_log_write, }; /* * set the log to default function, called during eal init process, * once memzones are available. */ int rte_eal_log_init(const char *id, int facility) { FILE *log_stream; log_stream = fopencookie(NULL, "w+", console_log_func); if (log_stream == NULL) return -1; openlog(id, LOG_NDELAY | LOG_PID, facility); if (rte_eal_common_log_init(log_stream) < 0) return -1; return 0; } /* early logs */ /* * early log function, used during boot when mempool (hence log * history) is not available */ static ssize_t early_log_write(__attribute__((unused)) void *c, const char *buf, size_t size) { ssize_t ret; ret = fwrite(buf, size, 1, stdout); fflush(stdout); if (ret == 0) return -1; return ret; } static cookie_io_functions_t early_log_func = { .write = early_log_write, }; static FILE *early_log_stream; /* * init the log library, called by rte_eal_init() to enable early * logs */ int rte_eal_log_early_init(void) { early_log_stream = fopencookie(NULL, "w+", early_log_func); if (early_log_stream == NULL) { printf("Cannot configure early_log_stream\n"); return -1; } rte_openlog_stream(early_log_stream); return 0; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_memory.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* BSD LICENSE * * Copyright(c) 2013 6WIND. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include "eal_hugepages.h" /** * @file * Huge page mapping under linux * * To reserve a big contiguous amount of memory, we use the hugepage * feature of linux. For that, we need to have hugetlbfs mounted. This * code will create many files in this directory (one per page) and * map them in virtual memory. For each page, we will retrieve its * physical address and remap it in order to have a virtual contiguous * zone as well as a physical contiguous zone. */ static uint64_t baseaddr_offset; static unsigned proc_pagemap_readable; #define RANDOMIZE_VA_SPACE_FILE "/proc/sys/kernel/randomize_va_space" static void test_proc_pagemap_readable(void) { int fd = open("/proc/self/pagemap", O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open /proc/self/pagemap: %s. " "virt2phys address translation will not work\n", strerror(errno)); return; } /* Is readable */ close(fd); proc_pagemap_readable = 1; } /* Lock page in physical memory and prevent from swapping. */ int rte_mem_lock_page(const void *virt) { unsigned long virtual = (unsigned long)virt; int page_size = getpagesize(); unsigned long aligned = (virtual & ~ (page_size - 1)); return mlock((void*)aligned, page_size); } /* * Get physical address of any mapped virtual address in the current process. */ phys_addr_t rte_mem_virt2phy(const void *virtaddr) { int fd; uint64_t page, physaddr; unsigned long virt_pfn; int page_size; off_t offset; /* Cannot parse /proc/self/pagemap, no need to log errors everywhere */ if (!proc_pagemap_readable) return RTE_BAD_PHYS_ADDR; /* standard page size */ page_size = getpagesize(); fd = open("/proc/self/pagemap", O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): cannot open /proc/self/pagemap: %s\n", __func__, strerror(errno)); return RTE_BAD_PHYS_ADDR; } virt_pfn = (unsigned long)virtaddr / page_size; offset = sizeof(uint64_t) * virt_pfn; if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { RTE_LOG(ERR, EAL, "%s(): seek error in /proc/self/pagemap: %s\n", __func__, strerror(errno)); close(fd); return RTE_BAD_PHYS_ADDR; } if (read(fd, &page, sizeof(uint64_t)) < 0) { RTE_LOG(ERR, EAL, "%s(): cannot read /proc/self/pagemap: %s\n", __func__, strerror(errno)); close(fd); return RTE_BAD_PHYS_ADDR; } /* * the pfn (page frame number) are bits 0-54 (see * pagemap.txt in linux Documentation) */ physaddr = ((page & 0x7fffffffffffffULL) * page_size) + ((unsigned long)virtaddr % page_size); close(fd); return physaddr; } /* * For each hugepage in hugepg_tbl, fill the physaddr value. We find * it by browsing the /proc/self/pagemap special file. */ static int find_physaddrs(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi) { unsigned i; phys_addr_t addr; for (i = 0; i < hpi->num_pages[0]; i++) { addr = rte_mem_virt2phy(hugepg_tbl[i].orig_va); if (addr == RTE_BAD_PHYS_ADDR) return -1; hugepg_tbl[i].physaddr = addr; } return 0; } /* * Check whether address-space layout randomization is enabled in * the kernel. This is important for multi-process as it can prevent * two processes mapping data to the same virtual address * Returns: * 0 - address space randomization disabled * 1/2 - address space randomization enabled * negative error code on error */ static int aslr_enabled(void) { char c; int retval, fd = open(RANDOMIZE_VA_SPACE_FILE, O_RDONLY); if (fd < 0) return -errno; retval = read(fd, &c, 1); close(fd); if (retval < 0) return -errno; if (retval == 0) return -EIO; switch (c) { case '0' : return 0; case '1' : return 1; case '2' : return 2; default: return -EINVAL; } } /* * Try to mmap *size bytes in /dev/zero. If it is successful, return the * pointer to the mmap'd area and keep *size unmodified. Else, retry * with a smaller zone: decrease *size by hugepage_sz until it reaches * 0. In this case, return NULL. Note: this function returns an address * which is a multiple of hugepage size. */ static void * get_virtual_area(size_t *size, size_t hugepage_sz) { void *addr; int fd; long aligned_addr; if (internal_config.base_virtaddr != 0) { addr = (void*) (uintptr_t) (internal_config.base_virtaddr + baseaddr_offset); } else addr = NULL; RTE_LOG(DEBUG, EAL, "Ask a virtual area of 0x%zx bytes\n", *size); fd = open("/dev/zero", O_RDONLY); if (fd < 0){ RTE_LOG(ERR, EAL, "Cannot open /dev/zero\n"); return NULL; } do { addr = mmap(addr, (*size) + hugepage_sz, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) *size -= hugepage_sz; } while (addr == MAP_FAILED && *size > 0); if (addr == MAP_FAILED) { close(fd); RTE_LOG(ERR, EAL, "Cannot get a virtual area: %s\n", strerror(errno)); return NULL; } munmap(addr, (*size) + hugepage_sz); close(fd); /* align addr to a huge page size boundary */ aligned_addr = (long)addr; aligned_addr += (hugepage_sz - 1); aligned_addr &= (~(hugepage_sz - 1)); addr = (void *)(aligned_addr); RTE_LOG(DEBUG, EAL, "Virtual area found at %p (size = 0x%zx)\n", addr, *size); /* increment offset */ baseaddr_offset += *size; return addr; } /* * Mmap all hugepages of hugepage table: it first open a file in * hugetlbfs, then mmap() hugepage_sz data in it. If orig is set, the * virtual address is stored in hugepg_tbl[i].orig_va, else it is stored * in hugepg_tbl[i].final_va. The second mapping (when orig is 0) tries to * map continguous physical blocks in contiguous virtual blocks. */ static int map_all_hugepages(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi, int orig) { int fd; unsigned i; void *virtaddr; void *vma_addr = NULL; size_t vma_len = 0; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS RTE_SET_USED(vma_len); #endif for (i = 0; i < hpi->num_pages[0]; i++) { uint64_t hugepage_sz = hpi->hugepage_sz; if (orig) { hugepg_tbl[i].file_id = i; hugepg_tbl[i].size = hugepage_sz; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS eal_get_hugefile_temp_path(hugepg_tbl[i].filepath, sizeof(hugepg_tbl[i].filepath), hpi->hugedir, hugepg_tbl[i].file_id); #else eal_get_hugefile_path(hugepg_tbl[i].filepath, sizeof(hugepg_tbl[i].filepath), hpi->hugedir, hugepg_tbl[i].file_id); #endif hugepg_tbl[i].filepath[sizeof(hugepg_tbl[i].filepath) - 1] = '\0'; } #ifndef RTE_ARCH_64 /* for 32-bit systems, don't remap 1G and 16G pages, just reuse * original map address as final map address. */ else if ((hugepage_sz == RTE_PGSIZE_1G) || (hugepage_sz == RTE_PGSIZE_16G)) { hugepg_tbl[i].final_va = hugepg_tbl[i].orig_va; hugepg_tbl[i].orig_va = NULL; continue; } #endif #ifndef RTE_EAL_SINGLE_FILE_SEGMENTS else if (vma_len == 0) { unsigned j, num_pages; /* reserve a virtual area for next contiguous * physical block: count the number of * contiguous physical pages. */ for (j = i+1; j < hpi->num_pages[0] ; j++) { #ifdef RTE_ARCH_PPC_64 /* The physical addresses are sorted in * descending order on PPC64 */ if (hugepg_tbl[j].physaddr != hugepg_tbl[j-1].physaddr - hugepage_sz) break; #else if (hugepg_tbl[j].physaddr != hugepg_tbl[j-1].physaddr + hugepage_sz) break; #endif } num_pages = j - i; vma_len = num_pages * hugepage_sz; /* get the biggest virtual memory area up to * vma_len. If it fails, vma_addr is NULL, so * let the kernel provide the address. */ vma_addr = get_virtual_area(&vma_len, hpi->hugepage_sz); if (vma_addr == NULL) vma_len = hugepage_sz; } #endif /* try to create hugepage file */ fd = open(hugepg_tbl[i].filepath, O_CREAT | O_RDWR, 0755); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): open failed: %s\n", __func__, strerror(errno)); return -1; } virtaddr = mmap(vma_addr, hugepage_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (virtaddr == MAP_FAILED) { RTE_LOG(ERR, EAL, "%s(): mmap failed: %s\n", __func__, strerror(errno)); close(fd); return -1; } if (orig) { hugepg_tbl[i].orig_va = virtaddr; memset(virtaddr, 0, hugepage_sz); } else { hugepg_tbl[i].final_va = virtaddr; } /* set shared flock on the file. */ if (flock(fd, LOCK_SH | LOCK_NB) == -1) { RTE_LOG(ERR, EAL, "%s(): Locking file failed:%s \n", __func__, strerror(errno)); close(fd); return -1; } close(fd); vma_addr = (char *)vma_addr + hugepage_sz; vma_len -= hugepage_sz; } return 0; } #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS /* * Remaps all hugepages into single file segments */ static int remap_all_hugepages(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi) { int fd; unsigned i = 0, j, num_pages, page_idx = 0; void *vma_addr = NULL, *old_addr = NULL, *page_addr = NULL; size_t vma_len = 0; size_t hugepage_sz = hpi->hugepage_sz; size_t total_size, offset; char filepath[MAX_HUGEPAGE_PATH]; phys_addr_t physaddr; int socket; while (i < hpi->num_pages[0]) { #ifndef RTE_ARCH_64 /* for 32-bit systems, don't remap 1G pages and 16G pages, * just reuse original map address as final map address. */ if ((hugepage_sz == RTE_PGSIZE_1G) || (hugepage_sz == RTE_PGSIZE_16G)) { hugepg_tbl[i].final_va = hugepg_tbl[i].orig_va; hugepg_tbl[i].orig_va = NULL; i++; continue; } #endif /* reserve a virtual area for next contiguous * physical block: count the number of * contiguous physical pages. */ for (j = i+1; j < hpi->num_pages[0] ; j++) { #ifdef RTE_ARCH_PPC_64 /* The physical addresses are sorted in descending * order on PPC64 */ if (hugepg_tbl[j].physaddr != hugepg_tbl[j-1].physaddr - hugepage_sz) break; #else if (hugepg_tbl[j].physaddr != hugepg_tbl[j-1].physaddr + hugepage_sz) break; #endif } num_pages = j - i; vma_len = num_pages * hugepage_sz; socket = hugepg_tbl[i].socket_id; /* get the biggest virtual memory area up to * vma_len. If it fails, vma_addr is NULL, so * let the kernel provide the address. */ vma_addr = get_virtual_area(&vma_len, hpi->hugepage_sz); /* If we can't find a big enough virtual area, work out how many pages * we are going to get */ if (vma_addr == NULL) j = i + 1; else if (vma_len != num_pages * hugepage_sz) { num_pages = vma_len / hugepage_sz; j = i + num_pages; } hugepg_tbl[page_idx].file_id = page_idx; eal_get_hugefile_path(filepath, sizeof(filepath), hpi->hugedir, hugepg_tbl[page_idx].file_id); /* try to create hugepage file */ fd = open(filepath, O_CREAT | O_RDWR, 0755); if (fd < 0) { RTE_LOG(ERR, EAL, "%s(): open failed: %s\n", __func__, strerror(errno)); return -1; } total_size = 0; for (;i < j; i++) { /* unmap current segment */ if (total_size > 0) munmap(vma_addr, total_size); /* unmap original page */ munmap(hugepg_tbl[i].orig_va, hugepage_sz); unlink(hugepg_tbl[i].filepath); total_size += hugepage_sz; old_addr = vma_addr; /* map new, bigger segment */ vma_addr = mmap(vma_addr, total_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (vma_addr == MAP_FAILED || vma_addr != old_addr) { RTE_LOG(ERR, EAL, "%s(): mmap failed: %s\n", __func__, strerror(errno)); close(fd); return -1; } /* touch the page. this is needed because kernel postpones mapping * creation until the first page fault. with this, we pin down * the page and it is marked as used and gets into process' pagemap. */ for (offset = 0; offset < total_size; offset += hugepage_sz) *((volatile uint8_t*) RTE_PTR_ADD(vma_addr, offset)); } /* set shared flock on the file. */ if (flock(fd, LOCK_SH | LOCK_NB) == -1) { RTE_LOG(ERR, EAL, "%s(): Locking file failed:%s \n", __func__, strerror(errno)); close(fd); return -1; } snprintf(hugepg_tbl[page_idx].filepath, MAX_HUGEPAGE_PATH, "%s", filepath); physaddr = rte_mem_virt2phy(vma_addr); if (physaddr == RTE_BAD_PHYS_ADDR) return -1; hugepg_tbl[page_idx].final_va = vma_addr; hugepg_tbl[page_idx].physaddr = physaddr; hugepg_tbl[page_idx].repeated = num_pages; hugepg_tbl[page_idx].socket_id = socket; close(fd); /* verify the memory segment - that is, check that every VA corresponds * to the physical address we expect to see */ for (offset = 0; offset < vma_len; offset += hugepage_sz) { uint64_t expected_physaddr; expected_physaddr = hugepg_tbl[page_idx].physaddr + offset; page_addr = RTE_PTR_ADD(vma_addr, offset); physaddr = rte_mem_virt2phy(page_addr); if (physaddr != expected_physaddr) { RTE_LOG(ERR, EAL, "Segment sanity check failed: wrong physaddr " "at %p (offset 0x%" PRIx64 ": 0x%" PRIx64 " (expected 0x%" PRIx64 ")\n", page_addr, offset, physaddr, expected_physaddr); return -1; } } /* zero out the whole segment */ memset(hugepg_tbl[page_idx].final_va, 0, total_size); page_idx++; } /* zero out the rest */ memset(&hugepg_tbl[page_idx], 0, (hpi->num_pages[0] - page_idx) * sizeof(struct hugepage_file)); return page_idx; } #else/* RTE_EAL_SINGLE_FILE_SEGMENTS=n */ /* Unmap all hugepages from original mapping */ static int unmap_all_hugepages_orig(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi) { unsigned i; for (i = 0; i < hpi->num_pages[0]; i++) { if (hugepg_tbl[i].orig_va) { munmap(hugepg_tbl[i].orig_va, hpi->hugepage_sz); hugepg_tbl[i].orig_va = NULL; } } return 0; } #endif /* RTE_EAL_SINGLE_FILE_SEGMENTS */ /* * Parse /proc/self/numa_maps to get the NUMA socket ID for each huge * page. */ static int find_numasocket(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi) { int socket_id; char *end, *nodestr; unsigned i, hp_count = 0; uint64_t virt_addr; char buf[BUFSIZ]; char hugedir_str[PATH_MAX]; FILE *f; f = fopen("/proc/self/numa_maps", "r"); if (f == NULL) { RTE_LOG(NOTICE, EAL, "cannot open /proc/self/numa_maps," " consider that all memory is in socket_id 0\n"); return 0; } snprintf(hugedir_str, sizeof(hugedir_str), "%s/%s", hpi->hugedir, internal_config.hugefile_prefix); /* parse numa map */ while (fgets(buf, sizeof(buf), f) != NULL) { /* ignore non huge page */ if (strstr(buf, " huge ") == NULL && strstr(buf, hugedir_str) == NULL) continue; /* get zone addr */ virt_addr = strtoull(buf, &end, 16); if (virt_addr == 0 || end == buf) { RTE_LOG(ERR, EAL, "%s(): error in numa_maps parsing\n", __func__); goto error; } /* get node id (socket id) */ nodestr = strstr(buf, " N"); if (nodestr == NULL) { RTE_LOG(ERR, EAL, "%s(): error in numa_maps parsing\n", __func__); goto error; } nodestr += 2; end = strstr(nodestr, "="); if (end == NULL) { RTE_LOG(ERR, EAL, "%s(): error in numa_maps parsing\n", __func__); goto error; } end[0] = '\0'; end = NULL; socket_id = strtoul(nodestr, &end, 0); if ((nodestr[0] == '\0') || (end == NULL) || (*end != '\0')) { RTE_LOG(ERR, EAL, "%s(): error in numa_maps parsing\n", __func__); goto error; } /* if we find this page in our mappings, set socket_id */ for (i = 0; i < hpi->num_pages[0]; i++) { void *va = (void *)(unsigned long)virt_addr; if (hugepg_tbl[i].orig_va == va) { hugepg_tbl[i].socket_id = socket_id; hp_count++; } } } if (hp_count < hpi->num_pages[0]) goto error; fclose(f); return 0; error: fclose(f); return -1; } /* * Sort the hugepg_tbl by physical address (lower addresses first on x86, * higher address first on powerpc). We use a slow algorithm, but we won't * have millions of pages, and this is only done at init time. */ static int sort_by_physaddr(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi) { unsigned i, j; int compare_idx; uint64_t compare_addr; struct hugepage_file tmp; for (i = 0; i < hpi->num_pages[0]; i++) { compare_addr = 0; compare_idx = -1; /* * browse all entries starting at 'i', and find the * entry with the smallest addr */ for (j=i; j< hpi->num_pages[0]; j++) { if (compare_addr == 0 || #ifdef RTE_ARCH_PPC_64 hugepg_tbl[j].physaddr > compare_addr) { #else hugepg_tbl[j].physaddr < compare_addr) { #endif compare_addr = hugepg_tbl[j].physaddr; compare_idx = j; } } /* should not happen */ if (compare_idx == -1) { RTE_LOG(ERR, EAL, "%s(): error in physaddr sorting\n", __func__); return -1; } /* swap the 2 entries in the table */ memcpy(&tmp, &hugepg_tbl[compare_idx], sizeof(struct hugepage_file)); memcpy(&hugepg_tbl[compare_idx], &hugepg_tbl[i], sizeof(struct hugepage_file)); memcpy(&hugepg_tbl[i], &tmp, sizeof(struct hugepage_file)); } return 0; } /* * Uses mmap to create a shared memory area for storage of data * Used in this file to store the hugepage file map on disk */ static void * create_shared_memory(const char *filename, const size_t mem_size) { void *retval; int fd = open(filename, O_CREAT | O_RDWR, 0666); if (fd < 0) return NULL; if (ftruncate(fd, mem_size) < 0) { close(fd); return NULL; } retval = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); return retval; } /* * this copies *active* hugepages from one hugepage table to another. * destination is typically the shared memory. */ static int copy_hugepages_to_shared_mem(struct hugepage_file * dst, int dest_size, const struct hugepage_file * src, int src_size) { int src_pos, dst_pos = 0; for (src_pos = 0; src_pos < src_size; src_pos++) { if (src[src_pos].final_va != NULL) { /* error on overflow attempt */ if (dst_pos == dest_size) return -1; memcpy(&dst[dst_pos], &src[src_pos], sizeof(struct hugepage_file)); dst_pos++; } } return 0; } /* * unmaps hugepages that are not going to be used. since we originally allocate * ALL hugepages (not just those we need), additional unmapping needs to be done. */ static int unmap_unneeded_hugepages(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi, unsigned num_hp_info) { unsigned socket, size; int page, nrpages = 0; /* get total number of hugepages */ for (size = 0; size < num_hp_info; size++) for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) nrpages += internal_config.hugepage_info[size].num_pages[socket]; for (size = 0; size < num_hp_info; size++) { for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) { unsigned pages_found = 0; /* traverse until we have unmapped all the unused pages */ for (page = 0; page < nrpages; page++) { struct hugepage_file *hp = &hugepg_tbl[page]; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS /* if this page was already cleared */ if (hp->final_va == NULL) continue; #endif /* find a page that matches the criteria */ if ((hp->size == hpi[size].hugepage_sz) && (hp->socket_id == (int) socket)) { /* if we skipped enough pages, unmap the rest */ if (pages_found == hpi[size].num_pages[socket]) { uint64_t unmap_len; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS unmap_len = hp->size * hp->repeated; #else unmap_len = hp->size; #endif /* get start addr and len of the remaining segment */ munmap(hp->final_va, (size_t) unmap_len); hp->final_va = NULL; if (unlink(hp->filepath) == -1) { RTE_LOG(ERR, EAL, "%s(): Removing %s failed: %s\n", __func__, hp->filepath, strerror(errno)); return -1; } } #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS /* else, check how much do we need to map */ else { int nr_pg_left = hpi[size].num_pages[socket] - pages_found; /* if we need enough memory to fit into the segment */ if (hp->repeated <= nr_pg_left) { pages_found += hp->repeated; } /* truncate the segment */ else { uint64_t final_size = nr_pg_left * hp->size; uint64_t seg_size = hp->repeated * hp->size; void * unmap_va = RTE_PTR_ADD(hp->final_va, final_size); int fd; munmap(unmap_va, seg_size - final_size); fd = open(hp->filepath, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", hp->filepath, strerror(errno)); return -1; } if (ftruncate(fd, final_size) < 0) { RTE_LOG(ERR, EAL, "Cannot truncate %s: %s\n", hp->filepath, strerror(errno)); return -1; } close(fd); pages_found += nr_pg_left; hp->repeated = nr_pg_left; } } #else /* else, lock the page and skip */ else pages_found++; #endif } /* match page */ } /* foreach page */ } /* foreach socket */ } /* foreach pagesize */ return 0; } static inline uint64_t get_socket_mem_size(int socket) { uint64_t size = 0; unsigned i; for (i = 0; i < internal_config.num_hugepage_sizes; i++){ struct hugepage_info *hpi = &internal_config.hugepage_info[i]; if (hpi->hugedir != NULL) size += hpi->hugepage_sz * hpi->num_pages[socket]; } return size; } /* * This function is a NUMA-aware equivalent of calc_num_pages. * It takes in the list of hugepage sizes and the * number of pages thereof, and calculates the best number of * pages of each size to fulfill the request for ram */ static int calc_num_pages_per_socket(uint64_t * memory, struct hugepage_info *hp_info, struct hugepage_info *hp_used, unsigned num_hp_info) { unsigned socket, j, i = 0; unsigned requested, available; int total_num_pages = 0; uint64_t remaining_mem, cur_mem; uint64_t total_mem = internal_config.memory; if (num_hp_info == 0) return -1; /* if specific memory amounts per socket weren't requested */ if (internal_config.force_sockets == 0) { int cpu_per_socket[RTE_MAX_NUMA_NODES]; size_t default_size, total_size; unsigned lcore_id; /* Compute number of cores per socket */ memset(cpu_per_socket, 0, sizeof(cpu_per_socket)); RTE_LCORE_FOREACH(lcore_id) { cpu_per_socket[rte_lcore_to_socket_id(lcore_id)]++; } /* * Automatically spread requested memory amongst detected sockets according * to number of cores from cpu mask present on each socket */ total_size = internal_config.memory; for (socket = 0; socket < RTE_MAX_NUMA_NODES && total_size != 0; socket++) { /* Set memory amount per socket */ default_size = (internal_config.memory * cpu_per_socket[socket]) / rte_lcore_count(); /* Limit to maximum available memory on socket */ default_size = RTE_MIN(default_size, get_socket_mem_size(socket)); /* Update sizes */ memory[socket] = default_size; total_size -= default_size; } /* * If some memory is remaining, try to allocate it by getting all * available memory from sockets, one after the other */ for (socket = 0; socket < RTE_MAX_NUMA_NODES && total_size != 0; socket++) { /* take whatever is available */ default_size = RTE_MIN(get_socket_mem_size(socket) - memory[socket], total_size); /* Update sizes */ memory[socket] += default_size; total_size -= default_size; } } for (socket = 0; socket < RTE_MAX_NUMA_NODES && total_mem != 0; socket++) { /* skips if the memory on specific socket wasn't requested */ for (i = 0; i < num_hp_info && memory[socket] != 0; i++){ hp_used[i].hugedir = hp_info[i].hugedir; hp_used[i].num_pages[socket] = RTE_MIN( memory[socket] / hp_info[i].hugepage_sz, hp_info[i].num_pages[socket]); cur_mem = hp_used[i].num_pages[socket] * hp_used[i].hugepage_sz; memory[socket] -= cur_mem; total_mem -= cur_mem; total_num_pages += hp_used[i].num_pages[socket]; /* check if we have met all memory requests */ if (memory[socket] == 0) break; /* check if we have any more pages left at this size, if so * move on to next size */ if (hp_used[i].num_pages[socket] == hp_info[i].num_pages[socket]) continue; /* At this point we know that there are more pages available that are * bigger than the memory we want, so lets see if we can get enough * from other page sizes. */ remaining_mem = 0; for (j = i+1; j < num_hp_info; j++) remaining_mem += hp_info[j].hugepage_sz * hp_info[j].num_pages[socket]; /* is there enough other memory, if not allocate another page and quit */ if (remaining_mem < memory[socket]){ cur_mem = RTE_MIN(memory[socket], hp_info[i].hugepage_sz); memory[socket] -= cur_mem; total_mem -= cur_mem; hp_used[i].num_pages[socket]++; total_num_pages++; break; /* we are done with this socket*/ } } /* if we didn't satisfy all memory requirements per socket */ if (memory[socket] > 0) { /* to prevent icc errors */ requested = (unsigned) (internal_config.socket_mem[socket] / 0x100000); available = requested - ((unsigned) (memory[socket] / 0x100000)); RTE_LOG(ERR, EAL, "Not enough memory available on socket %u! " "Requested: %uMB, available: %uMB\n", socket, requested, available); return -1; } } /* if we didn't satisfy total memory requirements */ if (total_mem > 0) { requested = (unsigned) (internal_config.memory / 0x100000); available = requested - (unsigned) (total_mem / 0x100000); RTE_LOG(ERR, EAL, "Not enough memory available! Requested: %uMB," " available: %uMB\n", requested, available); return -1; } return total_num_pages; } /* * Prepare physical memory mapping: fill configuration structure with * these infos, return 0 on success. * 1. map N huge pages in separate files in hugetlbfs * 2. find associated physical addr * 3. find associated NUMA socket ID * 4. sort all huge pages by physical address * 5. remap these N huge pages in the correct order * 6. unmap the first mapping * 7. fill memsegs in configuration with contiguous zones */ int rte_eal_hugepage_init(void) { struct rte_mem_config *mcfg; struct hugepage_file *hugepage, *tmp_hp = NULL; struct hugepage_info used_hp[MAX_HUGEPAGE_SIZES]; uint64_t memory[RTE_MAX_NUMA_NODES]; unsigned hp_offset; int i, j, new_memseg; int nr_hugefiles, nr_hugepages = 0; void *addr; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS int new_pages_count[MAX_HUGEPAGE_SIZES]; #endif test_proc_pagemap_readable(); memset(used_hp, 0, sizeof(used_hp)); /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; /* hugetlbfs can be disabled */ if (internal_config.no_hugetlbfs) { addr = mmap(NULL, internal_config.memory, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if (addr == MAP_FAILED) { RTE_LOG(ERR, EAL, "%s: mmap() failed: %s\n", __func__, strerror(errno)); return -1; } mcfg->memseg[0].phys_addr = (phys_addr_t)(uintptr_t)addr; mcfg->memseg[0].addr = addr; mcfg->memseg[0].hugepage_sz = RTE_PGSIZE_4K; mcfg->memseg[0].len = internal_config.memory; mcfg->memseg[0].socket_id = 0; return 0; } /* check if app runs on Xen Dom0 */ if (internal_config.xen_dom0_support) { #ifdef RTE_LIBRTE_XEN_DOM0 /* use dom0_mm kernel driver to init memory */ if (rte_xen_dom0_memory_init() < 0) return -1; else return 0; #endif } /* calculate total number of hugepages available. at this point we haven't * yet started sorting them so they all are on socket 0 */ for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) { /* meanwhile, also initialize used_hp hugepage sizes in used_hp */ used_hp[i].hugepage_sz = internal_config.hugepage_info[i].hugepage_sz; nr_hugepages += internal_config.hugepage_info[i].num_pages[0]; } /* * allocate a memory area for hugepage table. * this isn't shared memory yet. due to the fact that we need some * processing done on these pages, shared memory will be created * at a later stage. */ tmp_hp = malloc(nr_hugepages * sizeof(struct hugepage_file)); if (tmp_hp == NULL) goto fail; memset(tmp_hp, 0, nr_hugepages * sizeof(struct hugepage_file)); hp_offset = 0; /* where we start the current page size entries */ /* map all hugepages and sort them */ for (i = 0; i < (int)internal_config.num_hugepage_sizes; i ++){ struct hugepage_info *hpi; /* * we don't yet mark hugepages as used at this stage, so * we just map all hugepages available to the system * all hugepages are still located on socket 0 */ hpi = &internal_config.hugepage_info[i]; if (hpi->num_pages[0] == 0) continue; /* map all hugepages available */ if (map_all_hugepages(&tmp_hp[hp_offset], hpi, 1) < 0){ RTE_LOG(DEBUG, EAL, "Failed to mmap %u MB hugepages\n", (unsigned)(hpi->hugepage_sz / 0x100000)); goto fail; } /* find physical addresses and sockets for each hugepage */ if (find_physaddrs(&tmp_hp[hp_offset], hpi) < 0){ RTE_LOG(DEBUG, EAL, "Failed to find phys addr for %u MB pages\n", (unsigned)(hpi->hugepage_sz / 0x100000)); goto fail; } if (find_numasocket(&tmp_hp[hp_offset], hpi) < 0){ RTE_LOG(DEBUG, EAL, "Failed to find NUMA socket for %u MB pages\n", (unsigned)(hpi->hugepage_sz / 0x100000)); goto fail; } if (sort_by_physaddr(&tmp_hp[hp_offset], hpi) < 0) goto fail; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS /* remap all hugepages into single file segments */ new_pages_count[i] = remap_all_hugepages(&tmp_hp[hp_offset], hpi); if (new_pages_count[i] < 0){ RTE_LOG(DEBUG, EAL, "Failed to remap %u MB pages\n", (unsigned)(hpi->hugepage_sz / 0x100000)); goto fail; } /* we have processed a num of hugepages of this size, so inc offset */ hp_offset += new_pages_count[i]; #else /* remap all hugepages */ if (map_all_hugepages(&tmp_hp[hp_offset], hpi, 0) < 0){ RTE_LOG(DEBUG, EAL, "Failed to remap %u MB pages\n", (unsigned)(hpi->hugepage_sz / 0x100000)); goto fail; } /* unmap original mappings */ if (unmap_all_hugepages_orig(&tmp_hp[hp_offset], hpi) < 0) goto fail; /* we have processed a num of hugepages of this size, so inc offset */ hp_offset += hpi->num_pages[0]; #endif } #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS nr_hugefiles = 0; for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) { nr_hugefiles += new_pages_count[i]; } #else nr_hugefiles = nr_hugepages; #endif /* clean out the numbers of pages */ for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) for (j = 0; j < RTE_MAX_NUMA_NODES; j++) internal_config.hugepage_info[i].num_pages[j] = 0; /* get hugepages for each socket */ for (i = 0; i < nr_hugefiles; i++) { int socket = tmp_hp[i].socket_id; /* find a hugepage info with right size and increment num_pages */ const int nb_hpsizes = RTE_MIN(MAX_HUGEPAGE_SIZES, (int)internal_config.num_hugepage_sizes); for (j = 0; j < nb_hpsizes; j++) { if (tmp_hp[i].size == internal_config.hugepage_info[j].hugepage_sz) { #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS internal_config.hugepage_info[j].num_pages[socket] += tmp_hp[i].repeated; #else internal_config.hugepage_info[j].num_pages[socket]++; #endif } } } /* make a copy of socket_mem, needed for number of pages calculation */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) memory[i] = internal_config.socket_mem[i]; /* calculate final number of pages */ nr_hugepages = calc_num_pages_per_socket(memory, internal_config.hugepage_info, used_hp, internal_config.num_hugepage_sizes); /* error if not enough memory available */ if (nr_hugepages < 0) goto fail; /* reporting in! */ for (i = 0; i < (int) internal_config.num_hugepage_sizes; i++) { for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { if (used_hp[i].num_pages[j] > 0) { RTE_LOG(DEBUG, EAL, "Requesting %u pages of size %uMB" " from socket %i\n", used_hp[i].num_pages[j], (unsigned) (used_hp[i].hugepage_sz / 0x100000), j); } } } /* create shared memory */ hugepage = create_shared_memory(eal_hugepage_info_path(), nr_hugefiles * sizeof(struct hugepage_file)); if (hugepage == NULL) { RTE_LOG(ERR, EAL, "Failed to create shared memory!\n"); goto fail; } memset(hugepage, 0, nr_hugefiles * sizeof(struct hugepage_file)); /* * unmap pages that we won't need (looks at used_hp). * also, sets final_va to NULL on pages that were unmapped. */ if (unmap_unneeded_hugepages(tmp_hp, used_hp, internal_config.num_hugepage_sizes) < 0) { RTE_LOG(ERR, EAL, "Unmapping and locking hugepages failed!\n"); goto fail; } /* * copy stuff from malloc'd hugepage* to the actual shared memory. * this procedure only copies those hugepages that have final_va * not NULL. has overflow protection. */ if (copy_hugepages_to_shared_mem(hugepage, nr_hugefiles, tmp_hp, nr_hugefiles) < 0) { RTE_LOG(ERR, EAL, "Copying tables to shared memory failed!\n"); goto fail; } /* free the temporary hugepage table */ free(tmp_hp); tmp_hp = NULL; /* find earliest free memseg - this is needed because in case of IVSHMEM, * segments might have already been initialized */ for (j = 0; j < RTE_MAX_MEMSEG; j++) if (mcfg->memseg[j].addr == NULL) { /* move to previous segment and exit loop */ j--; break; } for (i = 0; i < nr_hugefiles; i++) { new_memseg = 0; /* if this is a new section, create a new memseg */ if (i == 0) new_memseg = 1; else if (hugepage[i].socket_id != hugepage[i-1].socket_id) new_memseg = 1; else if (hugepage[i].size != hugepage[i-1].size) new_memseg = 1; #ifdef RTE_ARCH_PPC_64 /* On PPC64 architecture, the mmap always start from higher * virtual address to lower address. Here, both the physical * address and virtual address are in descending order */ else if ((hugepage[i-1].physaddr - hugepage[i].physaddr) != hugepage[i].size) new_memseg = 1; else if (((unsigned long)hugepage[i-1].final_va - (unsigned long)hugepage[i].final_va) != hugepage[i].size) new_memseg = 1; #else else if ((hugepage[i].physaddr - hugepage[i-1].physaddr) != hugepage[i].size) new_memseg = 1; else if (((unsigned long)hugepage[i].final_va - (unsigned long)hugepage[i-1].final_va) != hugepage[i].size) new_memseg = 1; #endif if (new_memseg) { j += 1; if (j == RTE_MAX_MEMSEG) break; mcfg->memseg[j].phys_addr = hugepage[i].physaddr; mcfg->memseg[j].addr = hugepage[i].final_va; #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS mcfg->memseg[j].len = hugepage[i].size * hugepage[i].repeated; #else mcfg->memseg[j].len = hugepage[i].size; #endif mcfg->memseg[j].socket_id = hugepage[i].socket_id; mcfg->memseg[j].hugepage_sz = hugepage[i].size; } /* continuation of previous memseg */ else { #ifdef RTE_ARCH_PPC_64 /* Use the phy and virt address of the last page as segment * address for IBM Power architecture */ mcfg->memseg[j].phys_addr = hugepage[i].physaddr; mcfg->memseg[j].addr = hugepage[i].final_va; #endif mcfg->memseg[j].len += mcfg->memseg[j].hugepage_sz; } hugepage[i].memseg_id = j; } if (i < nr_hugefiles) { RTE_LOG(ERR, EAL, "Can only reserve %d pages " "from %d requested\n" "Current %s=%d is not enough\n" "Please either increase it or request less amount " "of memory.\n", i, nr_hugefiles, RTE_STR(CONFIG_RTE_MAX_MEMSEG), RTE_MAX_MEMSEG); return -ENOMEM; } return 0; fail: if (tmp_hp) free(tmp_hp); return -1; } /* * uses fstat to report the size of a file on disk */ static off_t getFileSize(int fd) { struct stat st; if (fstat(fd, &st) < 0) return 0; return st.st_size; } /* * This creates the memory mappings in the secondary process to match that of * the server process. It goes through each memory segment in the DPDK runtime * configuration and finds the hugepages which form that segment, mapping them * in order to form a contiguous block in the virtual memory space */ int rte_eal_hugepage_attach(void) { const struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; const struct hugepage_file *hp = NULL; unsigned num_hp = 0; unsigned i, s = 0; /* s used to track the segment number */ off_t size; int fd, fd_zero = -1, fd_hugepage = -1; if (aslr_enabled() > 0) { RTE_LOG(WARNING, EAL, "WARNING: Address Space Layout Randomization " "(ASLR) is enabled in the kernel.\n"); RTE_LOG(WARNING, EAL, " This may cause issues with mapping memory " "into secondary processes\n"); } test_proc_pagemap_readable(); if (internal_config.xen_dom0_support) { #ifdef RTE_LIBRTE_XEN_DOM0 if (rte_xen_dom0_memory_attach() < 0) { RTE_LOG(ERR, EAL,"Failed to attach memory setments of primay " "process\n"); return -1; } return 0; #endif } fd_zero = open("/dev/zero", O_RDONLY); if (fd_zero < 0) { RTE_LOG(ERR, EAL, "Could not open /dev/zero\n"); goto error; } fd_hugepage = open(eal_hugepage_info_path(), O_RDONLY); if (fd_hugepage < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", eal_hugepage_info_path()); goto error; } /* map all segments into memory to make sure we get the addrs */ for (s = 0; s < RTE_MAX_MEMSEG; ++s) { void *base_addr; /* * the first memory segment with len==0 is the one that * follows the last valid segment. */ if (mcfg->memseg[s].len == 0) break; #ifdef RTE_LIBRTE_IVSHMEM /* * if segment has ioremap address set, it's an IVSHMEM segment and * doesn't need mapping as it was already mapped earlier */ if (mcfg->memseg[s].ioremap_addr != 0) continue; #endif /* * fdzero is mmapped to get a contiguous block of virtual * addresses of the appropriate memseg size. * use mmap to get identical addresses as the primary process. */ base_addr = mmap(mcfg->memseg[s].addr, mcfg->memseg[s].len, PROT_READ, MAP_PRIVATE, fd_zero, 0); if (base_addr == MAP_FAILED || base_addr != mcfg->memseg[s].addr) { RTE_LOG(ERR, EAL, "Could not mmap %llu bytes " "in /dev/zero to requested address [%p]: '%s'\n", (unsigned long long)mcfg->memseg[s].len, mcfg->memseg[s].addr, strerror(errno)); if (aslr_enabled() > 0) { RTE_LOG(ERR, EAL, "It is recommended to " "disable ASLR in the kernel " "and retry running both primary " "and secondary processes\n"); } goto error; } } size = getFileSize(fd_hugepage); hp = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd_hugepage, 0); if (hp == NULL) { RTE_LOG(ERR, EAL, "Could not mmap %s\n", eal_hugepage_info_path()); goto error; } num_hp = size / sizeof(struct hugepage_file); RTE_LOG(DEBUG, EAL, "Analysing %u files\n", num_hp); s = 0; while (s < RTE_MAX_MEMSEG && mcfg->memseg[s].len > 0){ void *addr, *base_addr; uintptr_t offset = 0; size_t mapping_size; #ifdef RTE_LIBRTE_IVSHMEM /* * if segment has ioremap address set, it's an IVSHMEM segment and * doesn't need mapping as it was already mapped earlier */ if (mcfg->memseg[s].ioremap_addr != 0) { s++; continue; } #endif /* * free previously mapped memory so we can map the * hugepages into the space */ base_addr = mcfg->memseg[s].addr; munmap(base_addr, mcfg->memseg[s].len); /* find the hugepages for this segment and map them * we don't need to worry about order, as the server sorted the * entries before it did the second mmap of them */ for (i = 0; i < num_hp && offset < mcfg->memseg[s].len; i++){ if (hp[i].memseg_id == (int)s){ fd = open(hp[i].filepath, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", hp[i].filepath); goto error; } #ifdef RTE_EAL_SINGLE_FILE_SEGMENTS mapping_size = hp[i].size * hp[i].repeated; #else mapping_size = hp[i].size; #endif addr = mmap(RTE_PTR_ADD(base_addr, offset), mapping_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); /* close file both on success and on failure */ if (addr == MAP_FAILED || addr != RTE_PTR_ADD(base_addr, offset)) { RTE_LOG(ERR, EAL, "Could not mmap %s\n", hp[i].filepath); goto error; } offset+=mapping_size; } } RTE_LOG(DEBUG, EAL, "Mapped segment %u of size 0x%llx\n", s, (unsigned long long)mcfg->memseg[s].len); s++; } /* unmap the hugepage config file, since we are done using it */ munmap((void *)(uintptr_t)hp, size); close(fd_zero); close(fd_hugepage); return 0; error: if (fd_zero >= 0) close(fd_zero); if (fd_hugepage >= 0) close(fd_hugepage); return -1; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_pci.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "eal_filesystem.h" #include "eal_private.h" #include "eal_pci_init.h" /** * @file * PCI probing under linux * * This code is used to simulate a PCI probe by parsing information in sysfs. * When a registered device matches a driver, it is then initialized with * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it). */ /* unbind kernel driver for this device */ int pci_unbind_kernel_driver(struct rte_pci_device *dev) { int n; FILE *f; char filename[PATH_MAX]; char buf[BUFSIZ]; struct rte_pci_addr *loc = &dev->addr; /* open /sys/bus/pci/devices/AAAA:BB:CC.D/driver */ snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/driver/unbind", loc->domain, loc->bus, loc->devid, loc->function); f = fopen(filename, "w"); if (f == NULL) /* device was not bound */ return 0; n = snprintf(buf, sizeof(buf), PCI_PRI_FMT "\n", loc->domain, loc->bus, loc->devid, loc->function); if ((n < 0) || (n >= (int)sizeof(buf))) { RTE_LOG(ERR, EAL, "%s(): snprintf failed\n", __func__); goto error; } if (fwrite(buf, n, 1, f) == 0) { RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__, filename); goto error; } fclose(f); return 0; error: fclose(f); return -1; } static int pci_get_kernel_driver_by_path(const char *filename, char *dri_name) { int count; char path[PATH_MAX]; char *name; if (!filename || !dri_name) return -1; count = readlink(filename, path, PATH_MAX); if (count >= PATH_MAX) return -1; /* For device does not have a driver */ if (count < 0) return 1; path[count] = '\0'; name = strrchr(path, '/'); if (name) { strncpy(dri_name, name + 1, strlen(name + 1) + 1); return 0; } return -1; } /* Map pci device */ int pci_map_device(struct rte_pci_device *dev) { int ret = -1; /* try mapping the NIC resources using VFIO if it exists */ switch (dev->kdrv) { case RTE_KDRV_VFIO: #ifdef VFIO_PRESENT if (pci_vfio_is_enabled()) ret = pci_vfio_map_resource(dev); #endif break; case RTE_KDRV_IGB_UIO: case RTE_KDRV_UIO_GENERIC: /* map resources for devices that use uio */ ret = pci_uio_map_resource(dev); break; default: RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver, skipped\n"); ret = 1; break; } return ret; } /* Unmap pci device */ void pci_unmap_device(struct rte_pci_device *dev) { /* try unmapping the NIC resources using VFIO if it exists */ switch (dev->kdrv) { case RTE_KDRV_VFIO: RTE_LOG(ERR, EAL, "Hotplug doesn't support vfio yet\n"); break; case RTE_KDRV_IGB_UIO: case RTE_KDRV_UIO_GENERIC: /* unmap resources for devices that use uio */ pci_uio_unmap_resource(dev); break; default: RTE_LOG(DEBUG, EAL, " Not managed by a supported kernel driver, skipped\n"); break; } } void * pci_find_max_end_va(void) { const struct rte_memseg *seg = rte_eal_get_physmem_layout(); const struct rte_memseg *last = seg; unsigned i = 0; for (i = 0; i < RTE_MAX_MEMSEG; i++, seg++) { if (seg->addr == NULL) break; if (seg->addr > last->addr) last = seg; } return RTE_PTR_ADD(last->addr, last->len); } /* parse the "resource" sysfs file */ static int pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev) { FILE *f; char buf[BUFSIZ]; union pci_resource_info { struct { char *phys_addr; char *end_addr; char *flags; }; char *ptrs[PCI_RESOURCE_FMT_NVAL]; } res_info; int i; uint64_t phys_addr, end_addr, flags; f = fopen(filename, "r"); if (f == NULL) { RTE_LOG(ERR, EAL, "Cannot open sysfs resource\n"); return -1; } for (i = 0; imem_resource[i].phys_addr = phys_addr; dev->mem_resource[i].len = end_addr - phys_addr + 1; /* not mapped for now */ dev->mem_resource[i].addr = NULL; } } fclose(f); return 0; error: fclose(f); return -1; } /* Scan one pci sysfs entry, and fill the devices list from it. */ static int pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, uint8_t devid, uint8_t function) { char filename[PATH_MAX]; unsigned long tmp; struct rte_pci_device *dev; char driver[PATH_MAX]; int ret; dev = malloc(sizeof(*dev)); if (dev == NULL) return -1; memset(dev, 0, sizeof(*dev)); dev->addr.domain = domain; dev->addr.bus = bus; dev->addr.devid = devid; dev->addr.function = function; /* get vendor id */ snprintf(filename, sizeof(filename), "%s/vendor", dirname); if (eal_parse_sysfs_value(filename, &tmp) < 0) { free(dev); return -1; } dev->id.vendor_id = (uint16_t)tmp; /* get device id */ snprintf(filename, sizeof(filename), "%s/device", dirname); if (eal_parse_sysfs_value(filename, &tmp) < 0) { free(dev); return -1; } dev->id.device_id = (uint16_t)tmp; /* get subsystem_vendor id */ snprintf(filename, sizeof(filename), "%s/subsystem_vendor", dirname); if (eal_parse_sysfs_value(filename, &tmp) < 0) { free(dev); return -1; } dev->id.subsystem_vendor_id = (uint16_t)tmp; /* get subsystem_device id */ snprintf(filename, sizeof(filename), "%s/subsystem_device", dirname); if (eal_parse_sysfs_value(filename, &tmp) < 0) { free(dev); return -1; } dev->id.subsystem_device_id = (uint16_t)tmp; /* get max_vfs */ dev->max_vfs = 0; snprintf(filename, sizeof(filename), "%s/max_vfs", dirname); if (!access(filename, F_OK) && eal_parse_sysfs_value(filename, &tmp) == 0) dev->max_vfs = (uint16_t)tmp; else { /* for non igb_uio driver, need kernel version >= 3.8 */ snprintf(filename, sizeof(filename), "%s/sriov_numvfs", dirname); if (!access(filename, F_OK) && eal_parse_sysfs_value(filename, &tmp) == 0) dev->max_vfs = (uint16_t)tmp; } /* get numa node */ snprintf(filename, sizeof(filename), "%s/numa_node", dirname); if (access(filename, R_OK) != 0) { /* if no NUMA support, set default to 0 */ dev->numa_node = 0; } else { if (eal_parse_sysfs_value(filename, &tmp) < 0) { free(dev); return -1; } dev->numa_node = tmp; } /* parse resources */ snprintf(filename, sizeof(filename), "%s/resource", dirname); if (pci_parse_sysfs_resource(filename, dev) < 0) { RTE_LOG(ERR, EAL, "%s(): cannot parse resource\n", __func__); free(dev); return -1; } /* parse driver */ snprintf(filename, sizeof(filename), "%s/driver", dirname); ret = pci_get_kernel_driver_by_path(filename, driver); if (ret < 0) { RTE_LOG(ERR, EAL, "Fail to get kernel driver\n"); free(dev); return -1; } if (!ret) { if (!strcmp(driver, "vfio-pci")) dev->kdrv = RTE_KDRV_VFIO; else if (!strcmp(driver, "igb_uio")) dev->kdrv = RTE_KDRV_IGB_UIO; else if (!strcmp(driver, "uio_pci_generic")) dev->kdrv = RTE_KDRV_UIO_GENERIC; else dev->kdrv = RTE_KDRV_UNKNOWN; } else dev->kdrv = RTE_KDRV_UNKNOWN; /* device is valid, add in list (sorted) */ if (TAILQ_EMPTY(&pci_device_list)) { TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } else { struct rte_pci_device *dev2; int ret; TAILQ_FOREACH(dev2, &pci_device_list, next) { ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr); if (ret > 0) continue; if (ret < 0) { TAILQ_INSERT_BEFORE(dev2, dev, next); } else { /* already registered */ dev2->kdrv = dev->kdrv; dev2->max_vfs = dev->max_vfs; memmove(dev2->mem_resource, dev->mem_resource, sizeof(dev->mem_resource)); free(dev); } return 0; } TAILQ_INSERT_TAIL(&pci_device_list, dev, next); } return 0; } /* * split up a pci address into its constituent parts. */ static int parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain, uint8_t *bus, uint8_t *devid, uint8_t *function) { /* first split on ':' */ union splitaddr { struct { char *domain; char *bus; char *devid; char *function; }; char *str[PCI_FMT_NVAL]; /* last element-separator is "." not ":" */ } splitaddr; char *buf_copy = strndup(buf, bufsize); if (buf_copy == NULL) return -1; if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':') != PCI_FMT_NVAL - 1) goto error; /* final split is on '.' between devid and function */ splitaddr.function = strchr(splitaddr.devid,'.'); if (splitaddr.function == NULL) goto error; *splitaddr.function++ = '\0'; /* now convert to int values */ errno = 0; *domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16); *bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16); *devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16); *function = (uint8_t)strtoul(splitaddr.function, NULL, 10); if (errno != 0) goto error; free(buf_copy); /* free the copy made with strdup */ return 0; error: free(buf_copy); return -1; } /* * Scan the content of the PCI bus, and the devices in the devices * list */ int rte_eal_pci_scan(void) { struct dirent *e; DIR *dir; char dirname[PATH_MAX]; uint16_t domain; uint8_t bus, devid, function; dir = opendir(SYSFS_PCI_DEVICES); if (dir == NULL) { RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n", __func__, strerror(errno)); return -1; } while ((e = readdir(dir)) != NULL) { if (e->d_name[0] == '.') continue; if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain, &bus, &devid, &function) != 0) continue; snprintf(dirname, sizeof(dirname), "%s/%s", SYSFS_PCI_DEVICES, e->d_name); if (pci_scan_one(dirname, domain, bus, devid, function) < 0) goto error; } closedir(dir); return 0; error: closedir(dir); return -1; } #ifdef RTE_PCI_CONFIG static int pci_config_extended_tag(struct rte_pci_device *dev) { struct rte_pci_addr *loc = &dev->addr; char filename[PATH_MAX]; char buf[BUFSIZ]; FILE *f; /* not configured, let it as is */ if (strncmp(RTE_PCI_EXTENDED_TAG, "on", 2) != 0 && strncmp(RTE_PCI_EXTENDED_TAG, "off", 3) != 0) return 0; snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/" "extended_tag", loc->domain, loc->bus, loc->devid, loc->function); f = fopen(filename, "rw+"); if (!f) return -1; fgets(buf, sizeof(buf), f); if (strncmp(RTE_PCI_EXTENDED_TAG, "on", 2) == 0) { /* enable Extended Tag*/ if (strncmp(buf, "on", 2) != 0) { fseek(f, 0, SEEK_SET); fputs("on", f); } } else { /* disable Extended Tag */ if (strncmp(buf, "off", 3) != 0) { fseek(f, 0, SEEK_SET); fputs("off", f); } } fclose(f); return 0; } static int pci_config_max_read_request_size(struct rte_pci_device *dev) { struct rte_pci_addr *loc = &dev->addr; char filename[PATH_MAX]; char buf[BUFSIZ], param[BUFSIZ]; FILE *f; /* size can be 128, 256, 512, 1024, 2048, 4096 */ uint32_t max_size = RTE_PCI_MAX_READ_REQUEST_SIZE; /* not configured, let it as is */ if (!max_size) return 0; snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/" "max_read_request_size", loc->domain, loc->bus, loc->devid, loc->function); f = fopen(filename, "rw+"); if (!f) return -1; fgets(buf, sizeof(buf), f); snprintf(param, sizeof(param), "%d", max_size); /* check if the size to be set is the same as current */ if (strcmp(buf, param) == 0) { fclose(f); return 0; } fseek(f, 0, SEEK_SET); fputs(param, f); fclose(f); return 0; } void pci_config_space_set(struct rte_pci_device *dev) { if (rte_eal_process_type() != RTE_PROC_PRIMARY) return; /* configure extended tag */ pci_config_extended_tag(dev); /* configure max read request size */ pci_config_max_read_request_size(dev); } #endif /* Read PCI config space. */ int rte_eal_pci_read_config(const struct rte_pci_device *device, void *buf, size_t len, off_t offset) { const struct rte_intr_handle *intr_handle = &device->intr_handle; switch (intr_handle->type) { case RTE_INTR_HANDLE_UIO: case RTE_INTR_HANDLE_UIO_INTX: return pci_uio_read_config(intr_handle, buf, len, offset); #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: case RTE_INTR_HANDLE_VFIO_MSI: case RTE_INTR_HANDLE_VFIO_LEGACY: return pci_vfio_read_config(intr_handle, buf, len, offset); #endif default: RTE_LOG(ERR, EAL, "Unknown handle type of fd %d\n", intr_handle->fd); return -1; } } /* Write PCI config space. */ int rte_eal_pci_write_config(const struct rte_pci_device *device, const void *buf, size_t len, off_t offset) { const struct rte_intr_handle *intr_handle = &device->intr_handle; switch (intr_handle->type) { case RTE_INTR_HANDLE_UIO: case RTE_INTR_HANDLE_UIO_INTX: return pci_uio_write_config(intr_handle, buf, len, offset); #ifdef VFIO_PRESENT case RTE_INTR_HANDLE_VFIO_MSIX: case RTE_INTR_HANDLE_VFIO_MSI: case RTE_INTR_HANDLE_VFIO_LEGACY: return pci_vfio_write_config(intr_handle, buf, len, offset); #endif default: RTE_LOG(ERR, EAL, "Unknown handle type of fd %d\n", intr_handle->fd); return -1; } } /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) { TAILQ_INIT(&pci_driver_list); TAILQ_INIT(&pci_device_list); /* for debug purposes, PCI can be disabled */ if (internal_config.no_pci) return 0; if (rte_eal_pci_scan() < 0) { RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__); return -1; } #ifdef VFIO_PRESENT pci_vfio_enable(); if (pci_vfio_is_enabled()) { /* if we are primary process, create a thread to communicate with * secondary processes. the thread will use a socket to wait for * requests from secondary process to send open file descriptors, * because VFIO does not allow multiple open descriptors on a group or * VFIO container. */ if (internal_config.process_type == RTE_PROC_PRIMARY && pci_vfio_mp_sync_setup() < 0) return -1; } #endif return 0; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_pci_init.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EAL_PCI_INIT_H_ #define EAL_PCI_INIT_H_ #include "eal_vfio.h" /* * Helper function to map PCI resources right after hugepages in virtual memory */ extern void *pci_map_addr; void *pci_find_max_end_va(void); int pci_uio_alloc_resource(struct rte_pci_device *dev, struct mapped_pci_resource **uio_res); void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res); int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx, struct mapped_pci_resource *uio_res, int map_idx); int pci_uio_read_config(const struct rte_intr_handle *intr_handle, void *buf, size_t len, off_t offs); int pci_uio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offs); #ifdef VFIO_PRESENT #define VFIO_MAX_GROUPS 64 int pci_vfio_enable(void); int pci_vfio_is_enabled(void); int pci_vfio_mp_sync_setup(void); /* access config space */ int pci_vfio_read_config(const struct rte_intr_handle *intr_handle, void *buf, size_t len, off_t offs); int pci_vfio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offs); /* map VFIO resource prototype */ int pci_vfio_map_resource(struct rte_pci_device *dev); int pci_vfio_get_group_fd(int iommu_group_fd); int pci_vfio_get_container_fd(void); /* * Function prototypes for VFIO multiprocess sync functions */ int vfio_mp_sync_send_request(int socket, int req); int vfio_mp_sync_receive_request(int socket); int vfio_mp_sync_send_fd(int socket, int fd); int vfio_mp_sync_receive_fd(int socket); int vfio_mp_sync_connect_to_primary(void); /* socket comm protocol definitions */ #define SOCKET_REQ_CONTAINER 0x100 #define SOCKET_REQ_GROUP 0x200 #define SOCKET_OK 0x0 #define SOCKET_NO_FD 0x1 #define SOCKET_ERR 0xFF /* * we don't need to store device fd's anywhere since they can be obtained from * the group fd via an ioctl() call. */ struct vfio_group { int group_no; int fd; }; struct vfio_config { int vfio_enabled; int vfio_container_fd; int vfio_container_has_dma; int vfio_group_idx; struct vfio_group vfio_groups[VFIO_MAX_GROUPS]; }; #endif #endif /* EAL_PCI_INIT_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_pci_uio.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_filesystem.h" #include "eal_pci_init.h" void *pci_map_addr = NULL; #define OFF_MAX ((uint64_t)(off_t)-1) int pci_uio_read_config(const struct rte_intr_handle *intr_handle, void *buf, size_t len, off_t offset) { return pread(intr_handle->uio_cfg_fd, buf, len, offset); } int pci_uio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offset) { return pwrite(intr_handle->uio_cfg_fd, buf, len, offset); } static int pci_uio_set_bus_master(int dev_fd) { uint16_t reg; int ret; ret = pread(dev_fd, ®, sizeof(reg), PCI_COMMAND); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read command from PCI config space!\n"); return -1; } /* return if bus mastering is already on */ if (reg & PCI_COMMAND_MASTER) return 0; reg |= PCI_COMMAND_MASTER; ret = pwrite(dev_fd, ®, sizeof(reg), PCI_COMMAND); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot write command to PCI config space!\n"); return -1; } return 0; } static int pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num) { FILE *f; char filename[PATH_MAX]; int ret; unsigned major, minor; dev_t dev; /* get the name of the sysfs file that contains the major and minor * of the uio device and read its content */ snprintf(filename, sizeof(filename), "%s/dev", sysfs_uio_path); f = fopen(filename, "r"); if (f == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot open sysfs to get major:minor\n", __func__); return -1; } ret = fscanf(f, "%u:%u", &major, &minor); if (ret != 2) { RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs to get major:minor\n", __func__); fclose(f); return -1; } fclose(f); /* create the char device "mknod /dev/uioX c major minor" */ snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); dev = makedev(major, minor); ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev); if (f == NULL) { RTE_LOG(ERR, EAL, "%s(): mknod() failed %s\n", __func__, strerror(errno)); return -1; } return ret; } /* * Return the uioX char device used for a pci device. On success, return * the UIO number and fill dstbuf string with the path of the device in * sysfs. On error, return a negative value. In this case dstbuf is * invalid. */ static int pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf, unsigned int buflen) { struct rte_pci_addr *loc = &dev->addr; unsigned int uio_num; struct dirent *e; DIR *dir; char dirname[PATH_MAX]; /* depending on kernel version, uio can be located in uio/uioX * or uio:uioX */ snprintf(dirname, sizeof(dirname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio", loc->domain, loc->bus, loc->devid, loc->function); dir = opendir(dirname); if (dir == NULL) { /* retry with the parent directory */ snprintf(dirname, sizeof(dirname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT, loc->domain, loc->bus, loc->devid, loc->function); dir = opendir(dirname); if (dir == NULL) { RTE_LOG(ERR, EAL, "Cannot opendir %s\n", dirname); return -1; } } /* take the first file starting with "uio" */ while ((e = readdir(dir)) != NULL) { /* format could be uio%d ...*/ int shortprefix_len = sizeof("uio") - 1; /* ... or uio:uio%d */ int longprefix_len = sizeof("uio:uio") - 1; char *endptr; if (strncmp(e->d_name, "uio", 3) != 0) continue; /* first try uio%d */ errno = 0; uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + shortprefix_len)) { snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num); break; } /* then try uio:uio%d */ errno = 0; uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10); if (errno == 0 && endptr != (e->d_name + longprefix_len)) { snprintf(dstbuf, buflen, "%s/uio:uio%u", dirname, uio_num); break; } } closedir(dir); /* No uio resource found */ if (e == NULL) return -1; /* create uio device if we've been asked to */ if (internal_config.create_uio_dev && pci_mknod_uio_dev(dstbuf, uio_num) < 0) RTE_LOG(WARNING, EAL, "Cannot create /dev/uio%u\n", uio_num); return uio_num; } void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res) { rte_free(uio_res); if (dev->intr_handle.uio_cfg_fd >= 0) { close(dev->intr_handle.uio_cfg_fd); dev->intr_handle.uio_cfg_fd = -1; } if (dev->intr_handle.fd) { close(dev->intr_handle.fd); dev->intr_handle.fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; } } int pci_uio_alloc_resource(struct rte_pci_device *dev, struct mapped_pci_resource **uio_res) { char dirname[PATH_MAX]; char cfgname[PATH_MAX]; char devname[PATH_MAX]; /* contains the /dev/uioX */ int uio_num; struct rte_pci_addr *loc; loc = &dev->addr; /* find uio resource */ uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname)); if (uio_num < 0) { RTE_LOG(WARNING, EAL, " "PCI_PRI_FMT" not managed by UIO driver, " "skipping\n", loc->domain, loc->bus, loc->devid, loc->function); return 1; } snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num); /* save fd if in primary process */ dev->intr_handle.fd = open(devname, O_RDWR); if (dev->intr_handle.fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); goto error; } snprintf(cfgname, sizeof(cfgname), "/sys/class/uio/uio%u/device/config", uio_num); dev->intr_handle.uio_cfg_fd = open(cfgname, O_RDWR); if (dev->intr_handle.uio_cfg_fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", cfgname, strerror(errno)); goto error; } if (dev->kdrv == RTE_KDRV_IGB_UIO) dev->intr_handle.type = RTE_INTR_HANDLE_UIO; else { dev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX; /* set bus master that is not done by uio_pci_generic */ if (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) { RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n"); goto error; } } /* allocate the mapping details for secondary processes*/ *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0); if (*uio_res == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot store uio mmap details\n", __func__); goto error; } snprintf((*uio_res)->path, sizeof((*uio_res)->path), "%s", devname); memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr)); return 0; error: pci_uio_free_resource(dev, *uio_res); return -1; } int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx, struct mapped_pci_resource *uio_res, int map_idx) { int fd; char devname[PATH_MAX]; /* contains the /dev/uioX */ void *mapaddr; struct rte_pci_addr *loc; struct pci_map *maps; loc = &dev->addr; maps = uio_res->maps; /* update devname for mmap */ snprintf(devname, sizeof(devname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%d", loc->domain, loc->bus, loc->devid, loc->function, res_idx); /* allocate memory to keep path */ maps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0); if (maps[map_idx].path == NULL) { RTE_LOG(ERR, EAL, "Cannot allocate memory for path: %s\n", strerror(errno)); return -1; } /* * open resource file, to mmap it */ fd = open(devname, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); goto error; } /* try mapping somewhere close to the end of hugepages */ if (pci_map_addr == NULL) pci_map_addr = pci_find_max_end_va(); mapaddr = pci_map_resource(pci_map_addr, fd, 0, (size_t)dev->mem_resource[res_idx].len, 0); close(fd); if (mapaddr == MAP_FAILED) goto error; pci_map_addr = RTE_PTR_ADD(mapaddr, (size_t)dev->mem_resource[res_idx].len); maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr; maps[map_idx].size = dev->mem_resource[res_idx].len; maps[map_idx].addr = mapaddr; maps[map_idx].offset = 0; strcpy(maps[map_idx].path, devname); dev->mem_resource[res_idx].addr = mapaddr; return 0; error: rte_free(maps[map_idx].path); return -1; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_pci_vfio.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_filesystem.h" #include "eal_pci_init.h" #include "eal_vfio.h" /** * @file * PCI probing under linux (VFIO version) * * This code tries to determine if the PCI device is bound to VFIO driver, * and initialize it (map BARs, set up interrupts) if that's the case. * * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to "y". */ #ifdef VFIO_PRESENT #define PAGE_SIZE (sysconf(_SC_PAGESIZE)) #define PAGE_MASK (~(PAGE_SIZE - 1)) static struct rte_tailq_elem rte_vfio_tailq = { .name = "VFIO_RESOURCE_LIST", }; EAL_REGISTER_TAILQ(rte_vfio_tailq) #define VFIO_DIR "/dev/vfio" #define VFIO_CONTAINER_PATH "/dev/vfio/vfio" #define VFIO_GROUP_FMT "/dev/vfio/%u" #define VFIO_GET_REGION_ADDR(x) ((uint64_t) x << 40ULL) /* per-process VFIO config */ static struct vfio_config vfio_cfg; int pci_vfio_read_config(const struct rte_intr_handle *intr_handle, void *buf, size_t len, off_t offs) { return pread64(intr_handle->vfio_dev_fd, buf, len, VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs); } int pci_vfio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offs) { return pwrite64(intr_handle->vfio_dev_fd, buf, len, VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs); } /* get PCI BAR number where MSI-X interrupts are */ static int pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset, uint32_t *msix_table_size) { int ret; uint32_t reg; uint16_t flags; uint8_t cap_id, cap_offset; /* read PCI capability pointer from config space */ ret = pread64(fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + PCI_CAPABILITY_LIST); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read capability pointer from PCI " "config space!\n"); return -1; } /* we need first byte */ cap_offset = reg & 0xFF; while (cap_offset) { /* read PCI capability ID */ ret = pread64(fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + cap_offset); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read capability ID from PCI " "config space!\n"); return -1; } /* we need first byte */ cap_id = reg & 0xFF; /* if we haven't reached MSI-X, check next capability */ if (cap_id != PCI_CAP_ID_MSIX) { ret = pread64(fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + cap_offset); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read capability pointer from PCI " "config space!\n"); return -1; } /* we need second byte */ cap_offset = (reg & 0xFF00) >> 8; continue; } /* else, read table offset */ else { /* table offset resides in the next 4 bytes */ ret = pread64(fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + cap_offset + 4); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read table offset from PCI config " "space!\n"); return -1; } ret = pread64(fd, &flags, sizeof(flags), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + cap_offset + 2); if (ret != sizeof(flags)) { RTE_LOG(ERR, EAL, "Cannot read table flags from PCI config " "space!\n"); return -1; } *msix_bar = reg & RTE_PCI_MSIX_TABLE_BIR; *msix_table_offset = reg & RTE_PCI_MSIX_TABLE_OFFSET; *msix_table_size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE)); return 0; } } return 0; } /* set PCI bus mastering */ static int pci_vfio_set_bus_master(int dev_fd) { uint16_t reg; int ret; ret = pread64(dev_fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + PCI_COMMAND); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot read command from PCI config space!\n"); return -1; } /* set the master bit */ reg |= PCI_COMMAND_MASTER; ret = pwrite64(dev_fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + PCI_COMMAND); if (ret != sizeof(reg)) { RTE_LOG(ERR, EAL, "Cannot write command to PCI config space!\n"); return -1; } return 0; } /* set up DMA mappings */ static int pci_vfio_setup_dma_maps(int vfio_container_fd) { const struct rte_memseg *ms = rte_eal_get_physmem_layout(); int i, ret; ret = ioctl(vfio_container_fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); if (ret) { RTE_LOG(ERR, EAL, " cannot set IOMMU type, " "error %i (%s)\n", errno, strerror(errno)); return -1; } /* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */ for (i = 0; i < RTE_MAX_MEMSEG; i++) { struct vfio_iommu_type1_dma_map dma_map; if (ms[i].addr == NULL) break; memset(&dma_map, 0, sizeof(dma_map)); dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map); dma_map.vaddr = ms[i].addr_64; dma_map.size = ms[i].len; dma_map.iova = ms[i].phys_addr; dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map); if (ret) { RTE_LOG(ERR, EAL, " cannot set up DMA remapping, " "error %i (%s)\n", errno, strerror(errno)); return -1; } } return 0; } /* set up interrupt support (but not enable interrupts) */ static int pci_vfio_setup_interrupts(struct rte_pci_device *dev, int vfio_dev_fd) { int i, ret, intr_idx; /* default to invalid index */ intr_idx = VFIO_PCI_NUM_IRQS; /* get interrupt type from internal config (MSI-X by default, can be * overriden from the command line */ switch (internal_config.vfio_intr_mode) { case RTE_INTR_MODE_MSIX: intr_idx = VFIO_PCI_MSIX_IRQ_INDEX; break; case RTE_INTR_MODE_MSI: intr_idx = VFIO_PCI_MSI_IRQ_INDEX; break; case RTE_INTR_MODE_LEGACY: intr_idx = VFIO_PCI_INTX_IRQ_INDEX; break; /* don't do anything if we want to automatically determine interrupt type */ case RTE_INTR_MODE_NONE: break; default: RTE_LOG(ERR, EAL, " unknown default interrupt type!\n"); return -1; } /* start from MSI-X interrupt type */ for (i = VFIO_PCI_MSIX_IRQ_INDEX; i >= 0; i--) { struct vfio_irq_info irq = { .argsz = sizeof(irq) }; int fd = -1; /* skip interrupt modes we don't want */ if (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE && i != intr_idx) continue; irq.index = i; ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq); if (ret < 0) { RTE_LOG(ERR, EAL, " cannot get IRQ info, " "error %i (%s)\n", errno, strerror(errno)); return -1; } /* if this vector cannot be used with eventfd, fail if we explicitly * specified interrupt type, otherwise continue */ if ((irq.flags & VFIO_IRQ_INFO_EVENTFD) == 0) { if (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE) { RTE_LOG(ERR, EAL, " interrupt vector does not support eventfd!\n"); return -1; } else continue; } /* set up an eventfd for interrupts */ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (fd < 0) { RTE_LOG(ERR, EAL, " cannot set up eventfd, " "error %i (%s)\n", errno, strerror(errno)); return -1; } dev->intr_handle.fd = fd; dev->intr_handle.vfio_dev_fd = vfio_dev_fd; switch (i) { case VFIO_PCI_MSIX_IRQ_INDEX: internal_config.vfio_intr_mode = RTE_INTR_MODE_MSIX; dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSIX; break; case VFIO_PCI_MSI_IRQ_INDEX: internal_config.vfio_intr_mode = RTE_INTR_MODE_MSI; dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSI; break; case VFIO_PCI_INTX_IRQ_INDEX: internal_config.vfio_intr_mode = RTE_INTR_MODE_LEGACY; dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_LEGACY; break; default: RTE_LOG(ERR, EAL, " unknown interrupt type!\n"); return -1; } return 0; } /* if we're here, we haven't found a suitable interrupt vector */ return -1; } /* open container fd or get an existing one */ int pci_vfio_get_container_fd(void) { int ret, vfio_container_fd; /* if we're in a primary process, try to open the container */ if (internal_config.process_type == RTE_PROC_PRIMARY) { vfio_container_fd = open(VFIO_CONTAINER_PATH, O_RDWR); if (vfio_container_fd < 0) { RTE_LOG(ERR, EAL, " cannot open VFIO container, " "error %i (%s)\n", errno, strerror(errno)); return -1; } /* check VFIO API version */ ret = ioctl(vfio_container_fd, VFIO_GET_API_VERSION); if (ret != VFIO_API_VERSION) { if (ret < 0) RTE_LOG(ERR, EAL, " could not get VFIO API version, " "error %i (%s)\n", errno, strerror(errno)); else RTE_LOG(ERR, EAL, " unsupported VFIO API version!\n"); close(vfio_container_fd); return -1; } /* check if we support IOMMU type 1 */ ret = ioctl(vfio_container_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU); if (ret != 1) { if (ret < 0) RTE_LOG(ERR, EAL, " could not get IOMMU type, " "error %i (%s)\n", errno, strerror(errno)); else RTE_LOG(ERR, EAL, " unsupported IOMMU type " "detected in VFIO\n"); close(vfio_container_fd); return -1; } return vfio_container_fd; } else { /* * if we're in a secondary process, request container fd from the * primary process via our socket */ int socket_fd; socket_fd = vfio_mp_sync_connect_to_primary(); if (socket_fd < 0) { RTE_LOG(ERR, EAL, " cannot connect to primary process!\n"); return -1; } if (vfio_mp_sync_send_request(socket_fd, SOCKET_REQ_CONTAINER) < 0) { RTE_LOG(ERR, EAL, " cannot request container fd!\n"); close(socket_fd); return -1; } vfio_container_fd = vfio_mp_sync_receive_fd(socket_fd); if (vfio_container_fd < 0) { RTE_LOG(ERR, EAL, " cannot get container fd!\n"); close(socket_fd); return -1; } close(socket_fd); return vfio_container_fd; } return -1; } /* open group fd or get an existing one */ int pci_vfio_get_group_fd(int iommu_group_no) { int i; int vfio_group_fd; char filename[PATH_MAX]; /* check if we already have the group descriptor open */ for (i = 0; i < vfio_cfg.vfio_group_idx; i++) if (vfio_cfg.vfio_groups[i].group_no == iommu_group_no) return vfio_cfg.vfio_groups[i].fd; /* if primary, try to open the group */ if (internal_config.process_type == RTE_PROC_PRIMARY) { snprintf(filename, sizeof(filename), VFIO_GROUP_FMT, iommu_group_no); vfio_group_fd = open(filename, O_RDWR); if (vfio_group_fd < 0) { /* if file not found, it's not an error */ if (errno != ENOENT) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", filename, strerror(errno)); return -1; } return 0; } /* if the fd is valid, create a new group for it */ if (vfio_cfg.vfio_group_idx == VFIO_MAX_GROUPS) { RTE_LOG(ERR, EAL, "Maximum number of VFIO groups reached!\n"); return -1; } vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].group_no = iommu_group_no; vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].fd = vfio_group_fd; return vfio_group_fd; } /* if we're in a secondary process, request group fd from the primary * process via our socket */ else { int socket_fd, ret; socket_fd = vfio_mp_sync_connect_to_primary(); if (socket_fd < 0) { RTE_LOG(ERR, EAL, " cannot connect to primary process!\n"); return -1; } if (vfio_mp_sync_send_request(socket_fd, SOCKET_REQ_GROUP) < 0) { RTE_LOG(ERR, EAL, " cannot request container fd!\n"); close(socket_fd); return -1; } if (vfio_mp_sync_send_request(socket_fd, iommu_group_no) < 0) { RTE_LOG(ERR, EAL, " cannot send group number!\n"); close(socket_fd); return -1; } ret = vfio_mp_sync_receive_request(socket_fd); switch (ret) { case SOCKET_NO_FD: close(socket_fd); return 0; case SOCKET_OK: vfio_group_fd = vfio_mp_sync_receive_fd(socket_fd); /* if we got the fd, return it */ if (vfio_group_fd > 0) { close(socket_fd); return vfio_group_fd; } /* fall-through on error */ default: RTE_LOG(ERR, EAL, " cannot get container fd!\n"); close(socket_fd); return -1; } } return -1; } /* parse IOMMU group number for a PCI device * returns -1 for errors, 0 for non-existent group */ static int pci_vfio_get_group_no(const char *pci_addr) { char linkname[PATH_MAX]; char filename[PATH_MAX]; char *tok[16], *group_tok, *end; int ret, iommu_group_no; memset(linkname, 0, sizeof(linkname)); memset(filename, 0, sizeof(filename)); /* try to find out IOMMU group for this device */ snprintf(linkname, sizeof(linkname), SYSFS_PCI_DEVICES "/%s/iommu_group", pci_addr); ret = readlink(linkname, filename, sizeof(filename)); /* if the link doesn't exist, no VFIO for us */ if (ret < 0) return 0; ret = rte_strsplit(filename, sizeof(filename), tok, RTE_DIM(tok), '/'); if (ret <= 0) { RTE_LOG(ERR, EAL, " %s cannot get IOMMU group\n", pci_addr); return -1; } /* IOMMU group is always the last token */ errno = 0; group_tok = tok[ret - 1]; end = group_tok; iommu_group_no = strtol(group_tok, &end, 10); if ((end != group_tok && *end != '\0') || errno != 0) { RTE_LOG(ERR, EAL, " %s error parsing IOMMU number!\n", pci_addr); return -1; } return iommu_group_no; } static void clear_current_group(void) { vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].group_no = 0; vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].fd = -1; } /* * map the PCI resources of a PCI device in virtual memory (VFIO version). * primary and secondary processes follow almost exactly the same path */ int pci_vfio_map_resource(struct rte_pci_device *dev) { struct vfio_group_status group_status = { .argsz = sizeof(group_status) }; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; int vfio_group_fd, vfio_dev_fd; int iommu_group_no; char pci_addr[PATH_MAX] = {0}; struct rte_pci_addr *loc = &dev->addr; int i, ret, msix_bar; struct mapped_pci_resource *vfio_res = NULL; struct mapped_pci_res_list *vfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list); struct pci_map *maps; uint32_t msix_table_offset = 0; uint32_t msix_table_size = 0; dev->intr_handle.fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; /* store PCI address string */ snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT, loc->domain, loc->bus, loc->devid, loc->function); /* get group number */ iommu_group_no = pci_vfio_get_group_no(pci_addr); /* if 0, group doesn't exist */ if (iommu_group_no == 0) { RTE_LOG(WARNING, EAL, " %s not managed by VFIO driver, skipping\n", pci_addr); return 1; } /* if negative, something failed */ else if (iommu_group_no < 0) return -1; /* get the actual group fd */ vfio_group_fd = pci_vfio_get_group_fd(iommu_group_no); if (vfio_group_fd < 0) return -1; /* store group fd */ vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].group_no = iommu_group_no; vfio_cfg.vfio_groups[vfio_cfg.vfio_group_idx].fd = vfio_group_fd; /* if group_fd == 0, that means the device isn't managed by VFIO */ if (vfio_group_fd == 0) { RTE_LOG(WARNING, EAL, " %s not managed by VFIO driver, skipping\n", pci_addr); /* we store 0 as group fd to distinguish between existing but * unbound VFIO groups, and groups that don't exist at all. */ vfio_cfg.vfio_group_idx++; return 1; } /* * at this point, we know at least one port on this device is bound to VFIO, * so we can proceed to try and set this particular port up */ /* check if the group is viable */ ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status); if (ret) { RTE_LOG(ERR, EAL, " %s cannot get group status, " "error %i (%s)\n", pci_addr, errno, strerror(errno)); close(vfio_group_fd); clear_current_group(); return -1; } else if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) { RTE_LOG(ERR, EAL, " %s VFIO group is not viable!\n", pci_addr); close(vfio_group_fd); clear_current_group(); return -1; } /* * at this point, we know that this group is viable (meaning, all devices * are either bound to VFIO or not bound to anything) */ /* check if group does not have a container yet */ if (!(group_status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET)) { /* add group to a container */ ret = ioctl(vfio_group_fd, VFIO_GROUP_SET_CONTAINER, &vfio_cfg.vfio_container_fd); if (ret) { RTE_LOG(ERR, EAL, " %s cannot add VFIO group to container, " "error %i (%s)\n", pci_addr, errno, strerror(errno)); close(vfio_group_fd); clear_current_group(); return -1; } /* * at this point we know that this group has been successfully * initialized, so we increment vfio_group_idx to indicate that we can * add new groups. */ vfio_cfg.vfio_group_idx++; } /* * set up DMA mappings for container * * needs to be done only once, only when at least one group is assigned to * a container and only in primary process */ if (internal_config.process_type == RTE_PROC_PRIMARY && vfio_cfg.vfio_container_has_dma == 0) { ret = pci_vfio_setup_dma_maps(vfio_cfg.vfio_container_fd); if (ret) { RTE_LOG(ERR, EAL, " %s DMA remapping failed, " "error %i (%s)\n", pci_addr, errno, strerror(errno)); return -1; } vfio_cfg.vfio_container_has_dma = 1; } /* get a file descriptor for the device */ vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, pci_addr); if (vfio_dev_fd < 0) { /* if we cannot get a device fd, this simply means that this * particular port is not bound to VFIO */ RTE_LOG(WARNING, EAL, " %s not managed by VFIO driver, skipping\n", pci_addr); return 1; } /* test and setup the device */ ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, &device_info); if (ret) { RTE_LOG(ERR, EAL, " %s cannot get device info, " "error %i (%s)\n", pci_addr, errno, strerror(errno)); close(vfio_dev_fd); return -1; } /* get MSI-X BAR, if any (we have to know where it is because we can't * easily mmap it when using VFIO) */ msix_bar = -1; ret = pci_vfio_get_msix_bar(vfio_dev_fd, &msix_bar, &msix_table_offset, &msix_table_size); if (ret < 0) { RTE_LOG(ERR, EAL, " %s cannot get MSI-X BAR number!\n", pci_addr); close(vfio_dev_fd); return -1; } /* if we're in a primary process, allocate vfio_res and get region info */ if (internal_config.process_type == RTE_PROC_PRIMARY) { vfio_res = rte_zmalloc("VFIO_RES", sizeof(*vfio_res), 0); if (vfio_res == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot store uio mmap details\n", __func__); close(vfio_dev_fd); return -1; } memcpy(&vfio_res->pci_addr, &dev->addr, sizeof(vfio_res->pci_addr)); /* get number of registers (up to BAR5) */ vfio_res->nb_maps = RTE_MIN((int) device_info.num_regions, VFIO_PCI_BAR5_REGION_INDEX + 1); } else { /* if we're in a secondary process, just find our tailq entry */ TAILQ_FOREACH(vfio_res, vfio_res_list, next) { if (memcmp(&vfio_res->pci_addr, &dev->addr, sizeof(dev->addr))) continue; break; } /* if we haven't found our tailq entry, something's wrong */ if (vfio_res == NULL) { RTE_LOG(ERR, EAL, " %s cannot find TAILQ entry for PCI device!\n", pci_addr); close(vfio_dev_fd); return -1; } } /* map BARs */ maps = vfio_res->maps; for (i = 0; i < (int) vfio_res->nb_maps; i++) { struct vfio_region_info reg = { .argsz = sizeof(reg) }; void *bar_addr; struct memreg { unsigned long offset, size; } memreg[2] = {}; reg.index = i; ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, ®); if (ret) { RTE_LOG(ERR, EAL, " %s cannot get device region info " "error %i (%s)\n", pci_addr, errno, strerror(errno)); close(vfio_dev_fd); if (internal_config.process_type == RTE_PROC_PRIMARY) rte_free(vfio_res); return -1; } /* skip non-mmapable BARs */ if ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0) continue; if (i == msix_bar) { /* * VFIO will not let us map the MSI-X table, * but we can map around it. */ uint32_t table_start = msix_table_offset; uint32_t table_end = table_start + msix_table_size; table_end = (table_end + ~PAGE_MASK) & PAGE_MASK; table_start &= PAGE_MASK; if (table_start == 0 && table_end >= reg.size) { /* Cannot map this BAR */ RTE_LOG(DEBUG, EAL, "Skipping BAR %d\n", i); continue; } else { memreg[0].offset = reg.offset; memreg[0].size = table_start; memreg[1].offset = table_end; memreg[1].size = reg.size - table_end; RTE_LOG(DEBUG, EAL, "Trying to map BAR %d that contains the MSI-X " "table. Trying offsets: " "0x%04lx:0x%04lx, 0x%04lx:0x%04lx\n", i, memreg[0].offset, memreg[0].size, memreg[1].offset, memreg[1].size); } } else { memreg[0].offset = reg.offset; memreg[0].size = reg.size; } /* try to figure out an address */ if (internal_config.process_type == RTE_PROC_PRIMARY) { /* try mapping somewhere close to the end of hugepages */ if (pci_map_addr == NULL) pci_map_addr = pci_find_max_end_va(); bar_addr = pci_map_addr; pci_map_addr = RTE_PTR_ADD(bar_addr, (size_t) reg.size); } else { bar_addr = maps[i].addr; } /* reserve the address using an inaccessible mapping */ bar_addr = mmap(bar_addr, reg.size, 0, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (bar_addr != MAP_FAILED) { void *map_addr = NULL; if (memreg[0].size) { /* actual map of first part */ map_addr = pci_map_resource(bar_addr, vfio_dev_fd, memreg[0].offset, memreg[0].size, MAP_FIXED); } /* if there's a second part, try to map it */ if (map_addr != MAP_FAILED && memreg[1].offset && memreg[1].size) { void *second_addr = RTE_PTR_ADD(bar_addr, memreg[1].offset); map_addr = pci_map_resource(second_addr, vfio_dev_fd, memreg[1].offset, memreg[1].size, MAP_FIXED); } if (map_addr == MAP_FAILED || !map_addr) { munmap(bar_addr, reg.size); bar_addr = MAP_FAILED; } } if (bar_addr == MAP_FAILED || (internal_config.process_type == RTE_PROC_SECONDARY && bar_addr != maps[i].addr)) { RTE_LOG(ERR, EAL, " %s mapping BAR%i failed: %s\n", pci_addr, i, strerror(errno)); close(vfio_dev_fd); if (internal_config.process_type == RTE_PROC_PRIMARY) rte_free(vfio_res); return -1; } maps[i].addr = bar_addr; maps[i].offset = reg.offset; maps[i].size = reg.size; maps[i].path = NULL; /* vfio doesn't have per-resource paths */ dev->mem_resource[i].addr = bar_addr; } /* if secondary process, do not set up interrupts */ if (internal_config.process_type == RTE_PROC_PRIMARY) { if (pci_vfio_setup_interrupts(dev, vfio_dev_fd) != 0) { RTE_LOG(ERR, EAL, " %s error setting up interrupts!\n", pci_addr); close(vfio_dev_fd); rte_free(vfio_res); return -1; } /* set bus mastering for the device */ if (pci_vfio_set_bus_master(vfio_dev_fd)) { RTE_LOG(ERR, EAL, " %s cannot set up bus mastering!\n", pci_addr); close(vfio_dev_fd); rte_free(vfio_res); return -1; } /* Reset the device */ ioctl(vfio_dev_fd, VFIO_DEVICE_RESET); } if (internal_config.process_type == RTE_PROC_PRIMARY) TAILQ_INSERT_TAIL(vfio_res_list, vfio_res, next); return 0; } int pci_vfio_enable(void) { /* initialize group list */ int i; int module_vfio_type1; for (i = 0; i < VFIO_MAX_GROUPS; i++) { vfio_cfg.vfio_groups[i].fd = -1; vfio_cfg.vfio_groups[i].group_no = -1; } module_vfio_type1 = rte_eal_check_module("vfio_iommu_type1"); /* return error directly */ if (module_vfio_type1 == -1) { RTE_LOG(INFO, EAL, "Could not get loaded module details!\n"); return -1; } /* return 0 if VFIO modules not loaded */ if (module_vfio_type1 == 0) { RTE_LOG(INFO, EAL, "VFIO modules not all loaded, " "skip VFIO support...\n"); return 0; } vfio_cfg.vfio_container_fd = pci_vfio_get_container_fd(); /* check if we have VFIO driver enabled */ if (vfio_cfg.vfio_container_fd != -1) vfio_cfg.vfio_enabled = 1; else RTE_LOG(NOTICE, EAL, "VFIO support could not be initialized\n"); return 0; } int pci_vfio_is_enabled(void) { return vfio_cfg.vfio_enabled; } #endif ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_pci_vfio_mp_sync.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* sys/un.h with __USE_MISC uses strlen, which is unsafe */ #ifdef __USE_MISC #define REMOVED_USE_MISC #undef __USE_MISC #endif #include /* make sure we redefine __USE_MISC only if it was previously undefined */ #ifdef REMOVED_USE_MISC #define __USE_MISC #undef REMOVED_USE_MISC #endif #include #include #include #include #include "eal_filesystem.h" #include "eal_pci_init.h" /** * @file * VFIO socket for communication between primary and secondary processes. * * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to "y". */ #ifdef VFIO_PRESENT #define SOCKET_PATH_FMT "%s/.%s_mp_socket" #define CMSGLEN (CMSG_LEN(sizeof(int))) #define FD_TO_CMSGHDR(fd, chdr) \ do {\ (chdr).cmsg_len = CMSGLEN;\ (chdr).cmsg_level = SOL_SOCKET;\ (chdr).cmsg_type = SCM_RIGHTS;\ memcpy((chdr).__cmsg_data, &(fd), sizeof(fd));\ } while (0) #define CMSGHDR_TO_FD(chdr, fd) \ memcpy(&(fd), (chdr).__cmsg_data, sizeof(fd)) static pthread_t socket_thread; static int mp_socket_fd; /* get socket path (/var/run if root, $HOME otherwise) */ static void get_socket_path(char *buffer, int bufsz) { const char *dir = "/var/run"; const char *home_dir = getenv("HOME"); if (getuid() != 0 && home_dir != NULL) dir = home_dir; /* use current prefix as file path */ snprintf(buffer, bufsz, SOCKET_PATH_FMT, dir, internal_config.hugefile_prefix); } /* * data flow for socket comm protocol: * 1. client sends SOCKET_REQ_CONTAINER or SOCKET_REQ_GROUP * 1a. in case of SOCKET_REQ_GROUP, client also then sends group number * 2. server receives message * 2a. in case of invalid group, SOCKET_ERR is sent back to client * 2b. in case of unbound group, SOCKET_NO_FD is sent back to client * 2c. in case of valid group, SOCKET_OK is sent and immediately followed by fd * * in case of any error, socket is closed. */ /* send a request, return -1 on error */ int vfio_mp_sync_send_request(int socket, int req) { struct msghdr hdr; struct iovec iov; int buf; int ret; memset(&hdr, 0, sizeof(hdr)); buf = req; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; iov.iov_base = (char *) &buf; iov.iov_len = sizeof(buf); ret = sendmsg(socket, &hdr, 0); if (ret < 0) return -1; return 0; } /* receive a request and return it */ int vfio_mp_sync_receive_request(int socket) { int buf; struct msghdr hdr; struct iovec iov; int ret, req; memset(&hdr, 0, sizeof(hdr)); buf = SOCKET_ERR; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; iov.iov_base = (char *) &buf; iov.iov_len = sizeof(buf); ret = recvmsg(socket, &hdr, 0); if (ret < 0) return -1; req = buf; return req; } /* send OK in message, fd in control message */ int vfio_mp_sync_send_fd(int socket, int fd) { int buf; struct msghdr hdr; struct cmsghdr *chdr; char chdr_buf[CMSGLEN]; struct iovec iov; int ret; chdr = (struct cmsghdr *) chdr_buf; memset(chdr, 0, sizeof(chdr_buf)); memset(&hdr, 0, sizeof(hdr)); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; iov.iov_base = (char *) &buf; iov.iov_len = sizeof(buf); hdr.msg_control = chdr; hdr.msg_controllen = CMSGLEN; buf = SOCKET_OK; FD_TO_CMSGHDR(fd, *chdr); ret = sendmsg(socket, &hdr, 0); if (ret < 0) return -1; return 0; } /* receive OK in message, fd in control message */ int vfio_mp_sync_receive_fd(int socket) { int buf; struct msghdr hdr; struct cmsghdr *chdr; char chdr_buf[CMSGLEN]; struct iovec iov; int ret, req, fd; buf = SOCKET_ERR; chdr = (struct cmsghdr *) chdr_buf; memset(chdr, 0, sizeof(chdr_buf)); memset(&hdr, 0, sizeof(hdr)); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; iov.iov_base = (char *) &buf; iov.iov_len = sizeof(buf); hdr.msg_control = chdr; hdr.msg_controllen = CMSGLEN; ret = recvmsg(socket, &hdr, 0); if (ret < 0) return -1; req = buf; if (req != SOCKET_OK) return -1; CMSGHDR_TO_FD(*chdr, fd); return fd; } /* connect socket_fd in secondary process to the primary process's socket */ int vfio_mp_sync_connect_to_primary(void) { struct sockaddr_un addr; socklen_t sockaddr_len; int socket_fd; /* set up a socket */ socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (socket_fd < 0) { RTE_LOG(ERR, EAL, "Failed to create socket!\n"); return -1; } get_socket_path(addr.sun_path, sizeof(addr.sun_path)); addr.sun_family = AF_UNIX; sockaddr_len = sizeof(struct sockaddr_un); if (connect(socket_fd, (struct sockaddr *) &addr, sockaddr_len) == 0) return socket_fd; /* if connect failed */ close(socket_fd); return -1; } /* * socket listening thread for primary process */ static __attribute__((noreturn)) void * pci_vfio_mp_sync_thread(void __rte_unused * arg) { int ret, fd, vfio_group_no; /* wait for requests on the socket */ for (;;) { int conn_sock; struct sockaddr_un addr; socklen_t sockaddr_len = sizeof(addr); /* this is a blocking call */ conn_sock = accept(mp_socket_fd, (struct sockaddr *) &addr, &sockaddr_len); /* just restart on error */ if (conn_sock == -1) continue; /* set socket to linger after close */ struct linger l; l.l_onoff = 1; l.l_linger = 60; setsockopt(conn_sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); ret = vfio_mp_sync_receive_request(conn_sock); switch (ret) { case SOCKET_REQ_CONTAINER: fd = pci_vfio_get_container_fd(); if (fd < 0) vfio_mp_sync_send_request(conn_sock, SOCKET_ERR); else vfio_mp_sync_send_fd(conn_sock, fd); break; case SOCKET_REQ_GROUP: /* wait for group number */ vfio_group_no = vfio_mp_sync_receive_request(conn_sock); if (vfio_group_no < 0) { close(conn_sock); continue; } fd = pci_vfio_get_group_fd(vfio_group_no); if (fd < 0) vfio_mp_sync_send_request(conn_sock, SOCKET_ERR); /* if VFIO group exists but isn't bound to VFIO driver */ else if (fd == 0) vfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD); /* if group exists and is bound to VFIO driver */ else { vfio_mp_sync_send_request(conn_sock, SOCKET_OK); vfio_mp_sync_send_fd(conn_sock, fd); } break; default: vfio_mp_sync_send_request(conn_sock, SOCKET_ERR); break; } close(conn_sock); } } static int vfio_mp_sync_socket_setup(void) { int ret, socket_fd; struct sockaddr_un addr; socklen_t sockaddr_len; /* set up a socket */ socket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (socket_fd < 0) { RTE_LOG(ERR, EAL, "Failed to create socket!\n"); return -1; } get_socket_path(addr.sun_path, sizeof(addr.sun_path)); addr.sun_family = AF_UNIX; sockaddr_len = sizeof(struct sockaddr_un); unlink(addr.sun_path); ret = bind(socket_fd, (struct sockaddr *) &addr, sockaddr_len); if (ret) { RTE_LOG(ERR, EAL, "Failed to bind socket: %s!\n", strerror(errno)); close(socket_fd); return -1; } ret = listen(socket_fd, 50); if (ret) { RTE_LOG(ERR, EAL, "Failed to listen: %s!\n", strerror(errno)); close(socket_fd); return -1; } /* save the socket in local configuration */ mp_socket_fd = socket_fd; return 0; } /* * set up a local socket and tell it to listen for incoming connections */ int pci_vfio_mp_sync_setup(void) { int ret; if (vfio_mp_sync_socket_setup() < 0) { RTE_LOG(ERR, EAL, "Failed to set up local socket!\n"); return -1; } ret = pthread_create(&socket_thread, NULL, pci_vfio_mp_sync_thread, NULL); if (ret) { RTE_LOG(ERR, EAL, "Failed to create thread for communication with " "secondary processes!\n"); close(mp_socket_fd); return -1; } return 0; } #endif ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_thread.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_thread.h" RTE_DEFINE_PER_LCORE(unsigned, _lcore_id) = LCORE_ID_ANY; RTE_DEFINE_PER_LCORE(unsigned, _socket_id) = (unsigned)SOCKET_ID_ANY; RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); /* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the * remote lcore switch in FINISHED state. */ int rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id) { int n; char c = 0; int m2s = lcore_config[slave_id].pipe_master2slave[1]; int s2m = lcore_config[slave_id].pipe_slave2master[0]; if (lcore_config[slave_id].state != WAIT) return -EBUSY; lcore_config[slave_id].f = f; lcore_config[slave_id].arg = arg; /* send message */ n = 0; while (n == 0 || (n < 0 && errno == EINTR)) n = write(m2s, &c, 1); if (n < 0) rte_panic("cannot write on configuration pipe\n"); /* wait ack */ do { n = read(s2m, &c, 1); } while (n < 0 && errno == EINTR); if (n <= 0) rte_panic("cannot read on configuration pipe\n"); return 0; } /* set affinity for current EAL thread */ static int eal_thread_set_affinity(void) { unsigned lcore_id = rte_lcore_id(); /* acquire system unique id */ rte_gettid(); /* update EAL thread core affinity */ return rte_thread_set_affinity(&lcore_config[lcore_id].cpuset); } void eal_thread_init_master(unsigned lcore_id) { /* set the lcore ID in per-lcore memory area */ RTE_PER_LCORE(_lcore_id) = lcore_id; /* set CPU affinity */ if (eal_thread_set_affinity() < 0) rte_panic("cannot set affinity\n"); } /* main loop of threads */ __attribute__((noreturn)) void * eal_thread_loop(__attribute__((unused)) void *arg) { char c; int n, ret; unsigned lcore_id; pthread_t thread_id; int m2s, s2m; char cpuset[RTE_CPU_AFFINITY_STR_LEN]; thread_id = pthread_self(); /* retrieve our lcore_id from the configuration structure */ RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (thread_id == lcore_config[lcore_id].thread_id) break; } if (lcore_id == RTE_MAX_LCORE) rte_panic("cannot retrieve lcore id\n"); m2s = lcore_config[lcore_id].pipe_master2slave[0]; s2m = lcore_config[lcore_id].pipe_slave2master[1]; /* set the lcore ID in per-lcore memory area */ RTE_PER_LCORE(_lcore_id) = lcore_id; /* set CPU affinity */ if (eal_thread_set_affinity() < 0) rte_panic("cannot set affinity\n"); ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN); RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%x;cpuset=[%s%s])\n", lcore_id, (int)thread_id, cpuset, ret == 0 ? "" : "..."); /* read on our pipe to get commands */ while (1) { void *fct_arg; /* wait command */ do { n = read(m2s, &c, 1); } while (n < 0 && errno == EINTR); if (n <= 0) rte_panic("cannot read on configuration pipe\n"); lcore_config[lcore_id].state = RUNNING; /* send ack */ n = 0; while (n == 0 || (n < 0 && errno == EINTR)) n = write(s2m, &c, 1); if (n < 0) rte_panic("cannot write on configuration pipe\n"); if (lcore_config[lcore_id].f == NULL) rte_panic("NULL function pointer\n"); /* call the function and store the return value */ fct_arg = lcore_config[lcore_id].arg; ret = lcore_config[lcore_id].f(fct_arg); lcore_config[lcore_id].ret = ret; rte_wmb(); lcore_config[lcore_id].state = FINISHED; } /* never reached */ /* pthread_exit(NULL); */ /* return NULL; */ } /* require calling thread tid by gettid() */ int rte_sys_gettid(void) { return (int)syscall(SYS_gettid); } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_timer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright(c) 2012-2013 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" enum timer_source eal_timer_source = EAL_TIMER_HPET; #ifdef RTE_LIBEAL_USE_HPET #define DEV_HPET "/dev/hpet" /* Maximum number of counters. */ #define HPET_TIMER_NUM 3 /* General capabilities register */ #define CLK_PERIOD_SHIFT 32 /* Clock period shift. */ #define CLK_PERIOD_MASK 0xffffffff00000000ULL /* Clock period mask. */ /** * HPET timer registers. From the Intel IA-PC HPET (High Precision Event * Timers) Specification. */ struct eal_hpet_regs { /* Memory-mapped, software visible registers */ uint64_t capabilities; /**< RO General Capabilities Register. */ uint64_t reserved0; /**< Reserved for future use. */ uint64_t config; /**< RW General Configuration Register. */ uint64_t reserved1; /**< Reserved for future use. */ uint64_t isr; /**< RW Clear General Interrupt Status. */ uint64_t reserved2[25]; /**< Reserved for future use. */ union { uint64_t counter; /**< RW Main Counter Value Register. */ struct { uint32_t counter_l; /**< RW Main Counter Low. */ uint32_t counter_h; /**< RW Main Counter High. */ }; }; uint64_t reserved3; /**< Reserved for future use. */ struct { uint64_t config; /**< RW Timer Config and Capability Reg. */ uint64_t comp; /**< RW Timer Comparator Value Register. */ uint64_t fsb; /**< RW FSB Interrupt Route Register. */ uint64_t reserved4; /**< Reserved for future use. */ } timers[HPET_TIMER_NUM]; /**< Set of HPET timers. */ }; /* Mmap'd hpet registers */ static volatile struct eal_hpet_regs *eal_hpet = NULL; /* Period at which the HPET counter increments in * femtoseconds (10^-15 seconds). */ static uint32_t eal_hpet_resolution_fs = 0; /* Frequency of the HPET counter in Hz */ static uint64_t eal_hpet_resolution_hz = 0; /* Incremented 4 times during one 32bits hpet full count */ static uint32_t eal_hpet_msb; static pthread_t msb_inc_thread_id; /* * This function runs on a specific thread to update a global variable * containing used to process MSB of the HPET (unfortunatelly, we need * this because hpet is 32 bits by default under linux). */ static void hpet_msb_inc(__attribute__((unused)) void *arg) { uint32_t t; while (1) { t = (eal_hpet->counter_l >> 30); if (t != (eal_hpet_msb & 3)) eal_hpet_msb ++; sleep(10); } } uint64_t rte_get_hpet_hz(void) { if(internal_config.no_hpet) rte_panic("Error, HPET called, but no HPET present\n"); return eal_hpet_resolution_hz; } uint64_t rte_get_hpet_cycles(void) { uint32_t t, msb; uint64_t ret; if(internal_config.no_hpet) rte_panic("Error, HPET called, but no HPET present\n"); t = eal_hpet->counter_l; msb = eal_hpet_msb; ret = (msb + 2 - (t >> 30)) / 4; ret <<= 32; ret += t; return ret; } #endif #ifdef RTE_LIBEAL_USE_HPET /* * Open and mmap /dev/hpet (high precision event timer) that will * provide our time reference. */ int rte_eal_hpet_init(int make_default) { int fd, ret; if (internal_config.no_hpet) { RTE_LOG(NOTICE, EAL, "HPET is disabled\n"); return -1; } fd = open(DEV_HPET, O_RDONLY); if (fd < 0) { RTE_LOG(ERR, EAL, "ERROR: Cannot open "DEV_HPET": %s!\n", strerror(errno)); internal_config.no_hpet = 1; return -1; } eal_hpet = mmap(NULL, 1024, PROT_READ, MAP_SHARED, fd, 0); if (eal_hpet == MAP_FAILED) { RTE_LOG(ERR, EAL, "ERROR: Cannot mmap "DEV_HPET"!\n" "Please enable CONFIG_HPET_MMAP in your kernel configuration " "to allow HPET support.\n" "To run without using HPET, set CONFIG_RTE_LIBEAL_USE_HPET=n " "in your build configuration or use '--no-hpet' EAL flag.\n"); close(fd); internal_config.no_hpet = 1; return -1; } close(fd); eal_hpet_resolution_fs = (uint32_t)((eal_hpet->capabilities & CLK_PERIOD_MASK) >> CLK_PERIOD_SHIFT); eal_hpet_resolution_hz = (1000ULL*1000ULL*1000ULL*1000ULL*1000ULL) / (uint64_t)eal_hpet_resolution_fs; RTE_LOG(INFO, EAL, "HPET frequency is ~%"PRIu64" kHz\n", eal_hpet_resolution_hz/1000); eal_hpet_msb = (eal_hpet->counter_l >> 30); /* create a thread that will increment a global variable for * msb (hpet is 32 bits by default under linux) */ ret = pthread_create(&msb_inc_thread_id, NULL, (void *(*)(void *))hpet_msb_inc, NULL); if (ret < 0) { RTE_LOG(ERR, EAL, "ERROR: Cannot create HPET timer thread!\n"); internal_config.no_hpet = 1; return -1; } if (make_default) eal_timer_source = EAL_TIMER_HPET; return 0; } #endif static void check_tsc_flags(void) { char line[512]; FILE *stream; stream = fopen("/proc/cpuinfo", "r"); if (!stream) { RTE_LOG(WARNING, EAL, "WARNING: Unable to open /proc/cpuinfo\n"); return; } while (fgets(line, sizeof line, stream)) { char *constant_tsc; char *nonstop_tsc; if (strncmp(line, "flags", 5) != 0) continue; constant_tsc = strstr(line, "constant_tsc"); nonstop_tsc = strstr(line, "nonstop_tsc"); if (!constant_tsc || !nonstop_tsc) RTE_LOG(WARNING, EAL, "WARNING: cpu flags " "constant_tsc=%s " "nonstop_tsc=%s " "-> using unreliable clock cycles !\n", constant_tsc ? "yes":"no", nonstop_tsc ? "yes":"no"); break; } fclose(stream); } uint64_t get_tsc_freq(void) { #ifdef CLOCK_MONOTONIC_RAW #define NS_PER_SEC 1E9 struct timespec sleeptime = {.tv_nsec = 5E8 }; /* 1/2 second */ struct timespec t_start, t_end; uint64_t tsc_hz; if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0) { uint64_t ns, end, start = rte_rdtsc(); nanosleep(&sleeptime,NULL); clock_gettime(CLOCK_MONOTONIC_RAW, &t_end); end = rte_rdtsc(); ns = ((t_end.tv_sec - t_start.tv_sec) * NS_PER_SEC); ns += (t_end.tv_nsec - t_start.tv_nsec); double secs = (double)ns/NS_PER_SEC; tsc_hz = (uint64_t)((end - start)/secs); return tsc_hz; } #endif return 0; } int rte_eal_timer_init(void) { eal_timer_source = EAL_TIMER_TSC; set_tsc_freq(); check_tsc_flags(); return 0; } ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_vfio.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef EAL_VFIO_H_ #define EAL_VFIO_H_ /* * determine if VFIO is present on the system */ #ifdef RTE_EAL_VFIO #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) #include #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) #define RTE_PCI_MSIX_TABLE_BIR 0x7 #define RTE_PCI_MSIX_TABLE_OFFSET 0xfffffff8 #define RTE_PCI_MSIX_FLAGS_QSIZE 0x07ff #else #define RTE_PCI_MSIX_TABLE_BIR PCI_MSIX_TABLE_BIR #define RTE_PCI_MSIX_TABLE_OFFSET PCI_MSIX_TABLE_OFFSET #define RTE_PCI_MSIX_FLAGS_QSIZE PCI_MSIX_FLAGS_QSIZE #endif #define VFIO_PRESENT #endif /* kernel version */ #endif /* RTE_EAL_VFIO */ #endif /* EAL_VFIO_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/eal/eal_xen_memory.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include #define PAGE_SIZE RTE_PGSIZE_4K #define DEFAUL_DOM0_NAME "dom0-mem" static int xen_fd = -1; static const char sys_dir_path[] = "/sys/kernel/mm/dom0-mm/memsize-mB"; /* * Try to mmap *size bytes in /dev/zero. If it is successful, return the * pointer to the mmap'd area and keep *size unmodified. Else, retry * with a smaller zone: decrease *size by mem_size until it reaches * 0. In this case, return NULL. Note: this function returns an address * which is a multiple of mem_size size. */ static void * xen_get_virtual_area(size_t *size, size_t mem_size) { void *addr; int fd; long aligned_addr; RTE_LOG(DEBUG, EAL, "Ask a virtual area of 0x%zu bytes\n", *size); fd = open("/dev/zero", O_RDONLY); if (fd < 0){ RTE_LOG(ERR, EAL, "Cannot open /dev/zero\n"); return NULL; } do { addr = mmap(NULL, (*size) + mem_size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) *size -= mem_size; } while (addr == MAP_FAILED && *size > 0); if (addr == MAP_FAILED) { close(fd); RTE_LOG(ERR, EAL, "Cannot get a virtual area\n"); return NULL; } munmap(addr, (*size) + mem_size); close(fd); /* align addr to a mem_size boundary */ aligned_addr = (uintptr_t)addr; aligned_addr = RTE_ALIGN_CEIL(aligned_addr, mem_size); addr = (void *)(aligned_addr); RTE_LOG(DEBUG, EAL, "Virtual area found at %p (size = 0x%zx)\n", addr, *size); return addr; } /** * Get memory size configuration from /sys/devices/virtual/misc/dom0_mm * /memsize-mB/memsize file, and the size unit is mB. */ static int get_xen_memory_size(void) { char path[PATH_MAX]; unsigned long mem_size = 0; static const char *file_name; file_name = "memsize"; snprintf(path, sizeof(path), "%s/%s", sys_dir_path, file_name); if (eal_parse_sysfs_value(path, &mem_size) < 0) return -1; if (mem_size == 0) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s was not" " configured.\n",sys_dir_path, file_name); if (mem_size % 2) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s must be" " even number.\n",sys_dir_path, file_name); if (mem_size > DOM0_CONFIG_MEMSIZE) rte_exit(EXIT_FAILURE,"XEN-DOM0:the %s/%s should not be larger" " than %d mB\n",sys_dir_path, file_name, DOM0_CONFIG_MEMSIZE); return mem_size; } /** * Based on physical address to caculate MFN in Xen Dom0. */ phys_addr_t rte_mem_phy2mch(uint32_t memseg_id, const phys_addr_t phy_addr) { int mfn_id; uint64_t mfn, mfn_offset; struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; struct rte_memseg *memseg = mcfg->memseg; mfn_id = (phy_addr - memseg[memseg_id].phys_addr) / RTE_PGSIZE_2M; /*the MFN is contiguous in 2M */ mfn_offset = (phy_addr - memseg[memseg_id].phys_addr) % RTE_PGSIZE_2M / PAGE_SIZE; mfn = mfn_offset + memseg[memseg_id].mfn[mfn_id]; /** return mechine address */ return (mfn * PAGE_SIZE + phy_addr % PAGE_SIZE); } int rte_xen_dom0_memory_init(void) { void *vir_addr, *vma_addr = NULL; int err, ret = 0; uint32_t i, requested, mem_size, memseg_idx, num_memseg = 0; size_t vma_len = 0; struct memory_info meminfo; struct memseg_info seginfo[RTE_MAX_MEMSEG]; int flags, page_size = getpagesize(); struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; struct rte_memseg *memseg = mcfg->memseg; uint64_t total_mem = internal_config.memory; memset(seginfo, 0, sizeof(seginfo)); memset(&meminfo, 0, sizeof(struct memory_info)); mem_size = get_xen_memory_size(); requested = (unsigned) (total_mem / 0x100000); if (requested > mem_size) /* if we didn't satisfy total memory requirements */ rte_exit(EXIT_FAILURE,"Not enough memory available! Requested: %uMB," " available: %uMB\n", requested, mem_size); else if (total_mem != 0) mem_size = requested; /* Check FD and open once */ if (xen_fd < 0) { xen_fd = open(DOM0_MM_DEV, O_RDWR); if (xen_fd < 0) { RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV); return -1; } } meminfo.size = mem_size; /* construct memory mangement name for Dom0 */ snprintf(meminfo.name, DOM0_NAME_MAX, "%s-%s", internal_config.hugefile_prefix, DEFAUL_DOM0_NAME); /* Notify kernel driver to allocate memory */ ret = ioctl(xen_fd, RTE_DOM0_IOCTL_PREPARE_MEMSEG, &meminfo); if (ret < 0) { RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memory\n"); err = -EIO; goto fail; } /* Get number of memory segment from driver */ ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_NUM_MEMSEG, &num_memseg); if (ret < 0) { RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg count.\n"); err = -EIO; goto fail; } if(num_memseg > RTE_MAX_MEMSEG){ RTE_LOG(ERR, EAL, "XEN DOM0: the memseg count %d is greater" " than max memseg %d.\n",num_memseg, RTE_MAX_MEMSEG); err = -EIO; goto fail; } /* get all memory segements information */ ret = ioctl(xen_fd, RTE_DOM0_IOCTL_GET_MEMSEG_INFO, seginfo); if (ret < 0) { RTE_LOG(ERR, EAL, "XEN DOM0:failed to get memseg info.\n"); err = -EIO; goto fail; } /* map all memory segments to contiguous user space */ for (memseg_idx = 0; memseg_idx < num_memseg; memseg_idx++) { vma_len = seginfo[memseg_idx].size; /** * get the biggest virtual memory area up to vma_len. If it fails, * vma_addr is NULL, so let the kernel provide the address. */ vma_addr = xen_get_virtual_area(&vma_len, RTE_PGSIZE_2M); if (vma_addr == NULL) { flags = MAP_SHARED; vma_len = RTE_PGSIZE_2M; } else flags = MAP_SHARED | MAP_FIXED; seginfo[memseg_idx].size = vma_len; vir_addr = mmap(vma_addr, seginfo[memseg_idx].size, PROT_READ|PROT_WRITE, flags, xen_fd, memseg_idx * page_size); if (vir_addr == MAP_FAILED) { RTE_LOG(ERR, EAL, "XEN DOM0:Could not mmap %s\n", DOM0_MM_DEV); err = -EIO; goto fail; } memseg[memseg_idx].addr = vir_addr; memseg[memseg_idx].phys_addr = page_size * seginfo[memseg_idx].pfn ; memseg[memseg_idx].len = seginfo[memseg_idx].size; for ( i = 0; i < seginfo[memseg_idx].size / RTE_PGSIZE_2M; i++) memseg[memseg_idx].mfn[i] = seginfo[memseg_idx].mfn[i]; /* MFNs are continuous in 2M, so assume that page size is 2M */ memseg[memseg_idx].hugepage_sz = RTE_PGSIZE_2M; memseg[memseg_idx].nchannel = mcfg->nchannel; memseg[memseg_idx].nrank = mcfg->nrank; /* NUMA is not suppoted in Xen Dom0, so only set socket 0*/ memseg[memseg_idx].socket_id = 0; } return 0; fail: if (xen_fd > 0) { close(xen_fd); xen_fd = -1; } return err; } /* * This creates the memory mappings in the secondary process to match that of * the server process. It goes through each memory segment in the DPDK runtime * configuration, mapping them in order to form a contiguous block in the * virtual memory space */ int rte_xen_dom0_memory_attach(void) { const struct rte_mem_config *mcfg; unsigned s = 0; /* s used to track the segment number */ int xen_fd = -1; int ret = -1; void *vir_addr; char name[DOM0_NAME_MAX] = {0}; int page_size = getpagesize(); mcfg = rte_eal_get_configuration()->mem_config; /* Check FD and open once */ if (xen_fd < 0) { xen_fd = open(DOM0_MM_DEV, O_RDWR); if (xen_fd < 0) { RTE_LOG(ERR, EAL, "Can not open %s\n",DOM0_MM_DEV); goto error; } } /* construct memory mangement name for Dom0 */ snprintf(name, DOM0_NAME_MAX, "%s-%s", internal_config.hugefile_prefix, DEFAUL_DOM0_NAME); /* attach to memory segments of primary process */ ret = ioctl(xen_fd, RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG, name); if (ret) { RTE_LOG(ERR, EAL,"attach memory segments fail.\n"); goto error; } /* map all segments into memory to make sure we get the addrs */ for (s = 0; s < RTE_MAX_MEMSEG; ++s) { /* * the first memory segment with len==0 is the one that * follows the last valid segment. */ if (mcfg->memseg[s].len == 0) break; vir_addr = mmap(mcfg->memseg[s].addr, mcfg->memseg[s].len, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, xen_fd, s * page_size); if (vir_addr == MAP_FAILED) { RTE_LOG(ERR, EAL, "Could not mmap %llu bytes " "in %s to requested address [%p]\n", (unsigned long long)mcfg->memseg[s].len, DOM0_MM_DEV, mcfg->memseg[s].addr); goto error; } } return 0; error: if (xen_fd >= 0) { close(xen_fd); xen_fd = -1; } return -1; } ================================================ FILE: lib/librte_eal/linuxapp/eal/include/exec-env/rte_dom0_common.h ================================================ /*- * This file is provided under a dual BSD/LGPLv2 license. When using or * redistributing this file, you may do so under either license. * * GNU LESSER GENERAL PUBLIC LICENSE * * Copyright(c) 2007-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation * * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _RTE_DOM0_COMMON_H_ #define _RTE_DOM0_COMMON_H_ #ifdef __KERNEL__ #include #endif #define DOM0_NAME_MAX 256 #define DOM0_MM_DEV "/dev/dom0_mm" #define DOM0_CONTIG_NUM_ORDER 9 /**< order of 2M */ #define DOM0_NUM_MEMSEG 512 /**< Maximum nb. of memory segment. */ #define DOM0_MEMBLOCK_SIZE 0x200000 /**< size of memory block(2M). */ #define DOM0_CONFIG_MEMSIZE 4096 /**< Maximum config memory size(4G). */ #define DOM0_NUM_MEMBLOCK (DOM0_CONFIG_MEMSIZE / 2) /**< Maximum nb. of 2M memory block. */ #define RTE_DOM0_IOCTL_PREPARE_MEMSEG _IOWR(0, 1 , struct memory_info) #define RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG _IOWR(0, 2 , char *) #define RTE_DOM0_IOCTL_GET_NUM_MEMSEG _IOWR(0, 3, int) #define RTE_DOM0_IOCTL_GET_MEMSEG_INFO _IOWR(0, 4, void *) /** * A structure used to store memory information. */ struct memory_info { char name[DOM0_NAME_MAX]; uint64_t size; }; /** * A structure used to store memory segment information. */ struct memseg_info { uint32_t idx; uint64_t pfn; uint64_t size; uint64_t mfn[DOM0_NUM_MEMBLOCK]; }; /** * A structure used to store memory block information. */ struct memblock_info { uint8_t exchange_flag; uint8_t used; uint64_t vir_addr; uint64_t pfn; uint64_t mfn; }; #endif /* _RTE_DOM0_COMMON_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_INTERRUPTS_H_ #error "don't include this file directly, please include generic " #endif #ifndef _RTE_LINUXAPP_INTERRUPTS_H_ #define _RTE_LINUXAPP_INTERRUPTS_H_ #define RTE_MAX_RXTX_INTR_VEC_ID 32 enum rte_intr_handle_type { RTE_INTR_HANDLE_UNKNOWN = 0, RTE_INTR_HANDLE_UIO, /**< uio device handle */ RTE_INTR_HANDLE_UIO_INTX, /**< uio generic handle */ RTE_INTR_HANDLE_VFIO_LEGACY, /**< vfio device handle (legacy) */ RTE_INTR_HANDLE_VFIO_MSI, /**< vfio device handle (MSI) */ RTE_INTR_HANDLE_VFIO_MSIX, /**< vfio device handle (MSIX) */ RTE_INTR_HANDLE_ALARM, /**< alarm handle */ RTE_INTR_HANDLE_MAX }; #define RTE_INTR_EVENT_ADD 1UL #define RTE_INTR_EVENT_DEL 2UL typedef void (*rte_intr_event_cb_t)(int fd, void *arg); struct rte_epoll_data { uint32_t event; /**< event type */ void *data; /**< User data */ rte_intr_event_cb_t cb_fun; /**< IN: callback fun */ void *cb_arg; /**< IN: callback arg */ }; enum { RTE_EPOLL_INVALID = 0, RTE_EPOLL_VALID, RTE_EPOLL_EXEC, }; /** interrupt epoll event obj, taken by epoll_event.ptr */ struct rte_epoll_event { volatile uint32_t status; /**< OUT: event status */ int fd; /**< OUT: event fd */ int epfd; /**< OUT: epoll instance the ev associated with */ struct rte_epoll_data epdata; }; /** Handle for interrupts. */ struct rte_intr_handle { union { int vfio_dev_fd; /**< VFIO device file descriptor */ int uio_cfg_fd; /**< UIO config file descriptor for uio_pci_generic */ }; int fd; /**< interrupt event file descriptor */ enum rte_intr_handle_type type; /**< handle type */ #ifdef RTE_NEXT_ABI uint32_t max_intr; /**< max interrupt requested */ uint32_t nb_efd; /**< number of available efd(event fd) */ int efds[RTE_MAX_RXTX_INTR_VEC_ID]; /**< intr vectors/efds mapping */ struct rte_epoll_event elist[RTE_MAX_RXTX_INTR_VEC_ID]; /**< intr vector epoll event */ int *intr_vec; /**< intr vector number array */ #endif }; #define RTE_EPOLL_PER_THREAD -1 /**< to hint using per thread epfd */ /** * It waits for events on the epoll instance. * * @param epfd * Epoll instance fd on which the caller wait for events. * @param events * Memory area contains the events that will be available for the caller. * @param maxevents * Up to maxevents are returned, must greater than zero. * @param timeout * Specifying a timeout of -1 causes a block indefinitely. * Specifying a timeout equal to zero cause to return immediately. * @return * - On success, returns the number of available event. * - On failure, a negative value. */ int rte_epoll_wait(int epfd, struct rte_epoll_event *events, int maxevents, int timeout); /** * It performs control operations on epoll instance referred by the epfd. * It requests that the operation op be performed for the target fd. * * @param epfd * Epoll instance fd on which the caller perform control operations. * @param op * The operation be performed for the target fd. * @param fd * The target fd on which the control ops perform. * @param event * Describes the object linked to the fd. * Note: The caller must take care the object deletion after CTL_DEL. * @return * - On success, zero. * - On failure, a negative value. */ int rte_epoll_ctl(int epfd, int op, int fd, struct rte_epoll_event *event); /** * The function returns the per thread epoll instance. * * @return * epfd the epoll instance referred to. */ int rte_intr_tls_epfd(void); /** * @param intr_handle * Pointer to the interrupt handle. * @param epfd * Epoll instance fd which the intr vector associated to. * @param op * The operation be performed for the vector. * Operation type of {ADD, DEL}. * @param vec * RX intr vector number added to the epoll instance wait list. * @param data * User raw data. * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_rx_ctl(struct rte_intr_handle *intr_handle, int epfd, int op, unsigned int vec, void *data); /** * It enables the packet I/O interrupt event if it's necessary. * It creates event fd for each interrupt vector when MSIX is used, * otherwise it multiplexes a single event fd. * * @param intr_handle * Pointer to the interrupt handle. * @param nb_vec * Number of interrupt vector trying to enable. * @return * - On success, zero. * - On failure, a negative value. */ int rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd); /** * It disables the packet I/O interrupt event. * It deletes registered eventfds and closes the open fds. * * @param intr_handle * Pointer to the interrupt handle. */ void rte_intr_efd_disable(struct rte_intr_handle *intr_handle); /** * The packet I/O interrupt on datapath is enabled or not. * * @param intr_handle * Pointer to the interrupt handle. */ int rte_intr_dp_is_en(struct rte_intr_handle *intr_handle); /** * The interrupt handle instance allows other causes or not. * Other causes stand for any none packet I/O interrupts. * * @param intr_handle * Pointer to the interrupt handle. */ int rte_intr_allow_others(struct rte_intr_handle *intr_handle); #endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h ================================================ /*- * This file is provided under a dual BSD/LGPLv2 license. When using or * redistributing this file, you may do so under either license. * * GNU LESSER GENERAL PUBLIC LICENSE * * Copyright(c) 2007-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * Contact Information: * Intel Corporation * * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _RTE_KNI_COMMON_H_ #define _RTE_KNI_COMMON_H_ #ifdef __KERNEL__ #include #endif /** * KNI name is part of memzone name. */ #define RTE_KNI_NAMESIZE 32 #ifndef RTE_CACHE_LINE_SIZE #define RTE_CACHE_LINE_SIZE 64 /**< Cache line size. */ #endif /* * Request id. */ enum rte_kni_req_id { RTE_KNI_REQ_UNKNOWN = 0, RTE_KNI_REQ_CHANGE_MTU, RTE_KNI_REQ_CFG_NETWORK_IF, RTE_KNI_REQ_MAX, }; /* * Structure for KNI request. */ struct rte_kni_request { uint32_t req_id; /**< Request id */ union { uint32_t new_mtu; /**< New MTU */ uint8_t if_up; /**< 1: interface up, 0: interface down */ }; int32_t result; /**< Result for processing request */ } __attribute__((__packed__)); /* * Fifo struct mapped in a shared memory. It describes a circular buffer FIFO * Write and read should wrap around. Fifo is empty when write == read * Writing should never overwrite the read position */ struct rte_kni_fifo { volatile unsigned write; /**< Next position to be written*/ volatile unsigned read; /**< Next position to be read */ unsigned len; /**< Circular buffer length */ unsigned elem_size; /**< Pointer size - for 32/64 bit OS */ void * volatile buffer[0]; /**< The buffer contains mbuf pointers */ }; /* * The kernel image of the rte_mbuf struct, with only the relevant fields. * Padding is necessary to assure the offsets of these fields */ struct rte_kni_mbuf { void *buf_addr __attribute__((__aligned__(RTE_CACHE_LINE_SIZE))); char pad0[10]; uint16_t data_off; /**< Start address of data in segment buffer. */ char pad1[4]; uint64_t ol_flags; /**< Offload features. */ #ifdef RTE_NEXT_ABI char pad2[4]; uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */ uint16_t data_len; /**< Amount of data in segment buffer. */ #else char pad2[2]; uint16_t data_len; /**< Amount of data in segment buffer. */ uint32_t pkt_len; /**< Total pkt len: sum of all segment data_len. */ #endif /* fields on second cache line */ char pad3[8] __attribute__((__aligned__(RTE_CACHE_LINE_SIZE))); void *pool; void *next; }; /* * Struct used to create a KNI device. Passed to the kernel in IOCTL call */ struct rte_kni_device_info { char name[RTE_KNI_NAMESIZE]; /**< Network device name for KNI */ phys_addr_t tx_phys; phys_addr_t rx_phys; phys_addr_t alloc_phys; phys_addr_t free_phys; /* Used by Ethtool */ phys_addr_t req_phys; phys_addr_t resp_phys; phys_addr_t sync_phys; void * sync_va; /* mbuf mempool */ void * mbuf_va; phys_addr_t mbuf_phys; /* PCI info */ uint16_t vendor_id; /**< Vendor ID or PCI_ANY_ID. */ uint16_t device_id; /**< Device ID or PCI_ANY_ID. */ uint8_t bus; /**< Device bus */ uint8_t devid; /**< Device ID */ uint8_t function; /**< Device function. */ uint16_t group_id; /**< Group ID */ uint32_t core_id; /**< core ID to bind for kernel thread */ uint8_t force_bind : 1; /**< Flag for kernel thread binding */ /* mbuf size */ unsigned mbuf_size; }; #define KNI_DEVICE "kni" #define RTE_KNI_IOCTL_TEST _IOWR(0, 1, int) #define RTE_KNI_IOCTL_CREATE _IOWR(0, 2, struct rte_kni_device_info) #define RTE_KNI_IOCTL_RELEASE _IOWR(0, 3, struct rte_kni_device_info) #endif /* _RTE_KNI_COMMON_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/igb_uio/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # module name and path # MODULE = igb_uio MODULE_PATH = drivers/net/igb_uio # # CFLAGS # MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=100 MODULE_CFLAGS += -I$(RTE_OUTPUT)/include MODULE_CFLAGS += -Winline -Wall -Werror MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h # # all source are stored in SRCS-y # SRCS-y := igb_uio.c include $(RTE_SDK)/mk/rte.module.mk ================================================ FILE: lib/librte_eal/linuxapp/igb_uio/compat.h ================================================ /* * Minimal wrappers to allow compiling igb_uio on older kernels. */ #ifndef RHEL_RELEASE_VERSION #define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) #define pci_cfg_access_lock pci_block_user_cfg_access #define pci_cfg_access_unlock pci_unblock_user_cfg_access #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) #define HAVE_PTE_MASK_PAGE_IOMAP #endif #ifndef PCI_MSIX_ENTRY_SIZE #define PCI_MSIX_ENTRY_SIZE 16 #define PCI_MSIX_ENTRY_LOWER_ADDR 0 #define PCI_MSIX_ENTRY_UPPER_ADDR 4 #define PCI_MSIX_ENTRY_DATA 8 #define PCI_MSIX_ENTRY_VECTOR_CTRL 12 #define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) && \ (!(defined(RHEL_RELEASE_CODE) && \ RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5, 9))) static int pci_num_vf(struct pci_dev *dev) { struct iov { int pos; int nres; u32 cap; u16 ctrl; u16 total; u16 initial; u16 nr_virtfn; } *iov = (struct iov *)dev->sriov; if (!dev->is_physfn) return 0; return iov->nr_virtfn; } #endif /* < 2.6.34 */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \ (!(defined(RHEL_RELEASE_CODE) && \ RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4))) #define kstrtoul strict_strtoul #endif /* < 2.6.39 */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) && \ (!(defined(RHEL_RELEASE_CODE) && \ RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 3))) /* Check if INTX works to control irq's. * Set's INTX_DISABLE flag and reads it back */ static bool pci_intx_mask_supported(struct pci_dev *pdev) { bool mask_supported = false; uint16_t orig, new; pci_block_user_cfg_access(pdev); pci_read_config_word(pdev, PCI_COMMAND, &orig); pci_write_config_word(pdev, PCI_COMMAND, orig ^ PCI_COMMAND_INTX_DISABLE); pci_read_config_word(pdev, PCI_COMMAND, &new); if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) { dev_err(&pdev->dev, "Command register changed from " "0x%x to 0x%x: driver or hardware bug?\n", orig, new); } else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) { mask_supported = true; pci_write_config_word(pdev, PCI_COMMAND, orig); } pci_unblock_user_cfg_access(pdev); return mask_supported; } static bool pci_check_and_mask_intx(struct pci_dev *pdev) { bool pending; uint32_t status; pci_block_user_cfg_access(pdev); pci_read_config_dword(pdev, PCI_COMMAND, &status); /* interrupt is not ours, goes to out */ pending = (((status >> 16) & PCI_STATUS_INTERRUPT) != 0); if (pending) { uint16_t old, new; old = status; if (status != 0) new = old & (~PCI_COMMAND_INTX_DISABLE); else new = old | PCI_COMMAND_INTX_DISABLE; if (old != new) pci_write_config_word(pdev, PCI_COMMAND, new); } pci_unblock_user_cfg_access(pdev); return pending; } #endif /* < 3.3.0 */ ================================================ FILE: lib/librte_eal/linuxapp/igb_uio/igb_uio.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include #include #include #include #include #include #ifdef CONFIG_XEN_DOM0 #include #endif #include #include "compat.h" #ifdef RTE_PCI_CONFIG #define PCI_SYS_FILE_BUF_SIZE 10 #define PCI_DEV_CAP_REG 0xA4 #define PCI_DEV_CTRL_REG 0xA8 #define PCI_DEV_CAP_EXT_TAG_MASK 0x20 #define PCI_DEV_CTRL_EXT_TAG_SHIFT 8 #define PCI_DEV_CTRL_EXT_TAG_MASK (1 << PCI_DEV_CTRL_EXT_TAG_SHIFT) #endif /** * A structure describing the private information for a uio device. */ struct rte_uio_pci_dev { struct uio_info info; struct pci_dev *pdev; enum rte_intr_mode mode; }; static char *intr_mode = NULL; static enum rte_intr_mode igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX; static inline struct rte_uio_pci_dev * igbuio_get_uio_pci_dev(struct uio_info *info) { return container_of(info, struct rte_uio_pci_dev, info); } /* sriov sysfs */ static ssize_t show_max_vfs(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, 10, "%u\n", pci_num_vf(container_of(dev, struct pci_dev, dev))); } static ssize_t store_max_vfs(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err = 0; unsigned long max_vfs; struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); if (0 != kstrtoul(buf, 0, &max_vfs)) return -EINVAL; if (0 == max_vfs) pci_disable_sriov(pdev); else if (0 == pci_num_vf(pdev)) err = pci_enable_sriov(pdev, max_vfs); else /* do nothing if change max_vfs number */ err = -EINVAL; return err ? err : count; } #ifdef RTE_PCI_CONFIG static ssize_t show_extended_tag(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev); uint32_t val = 0; pci_read_config_dword(pci_dev, PCI_DEV_CAP_REG, &val); if (!(val & PCI_DEV_CAP_EXT_TAG_MASK)) /* Not supported */ return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%s\n", "invalid"); val = 0; pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn, PCI_DEV_CTRL_REG, &val); return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%s\n", (val & PCI_DEV_CTRL_EXT_TAG_MASK) ? "on" : "off"); } static ssize_t store_extended_tag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev); uint32_t val = 0, enable; if (strncmp(buf, "on", 2) == 0) enable = 1; else if (strncmp(buf, "off", 3) == 0) enable = 0; else return -EINVAL; pci_cfg_access_lock(pci_dev); pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn, PCI_DEV_CAP_REG, &val); if (!(val & PCI_DEV_CAP_EXT_TAG_MASK)) { /* Not supported */ pci_cfg_access_unlock(pci_dev); return -EPERM; } val = 0; pci_bus_read_config_dword(pci_dev->bus, pci_dev->devfn, PCI_DEV_CTRL_REG, &val); if (enable) val |= PCI_DEV_CTRL_EXT_TAG_MASK; else val &= ~PCI_DEV_CTRL_EXT_TAG_MASK; pci_bus_write_config_dword(pci_dev->bus, pci_dev->devfn, PCI_DEV_CTRL_REG, val); pci_cfg_access_unlock(pci_dev); return count; } static ssize_t show_max_read_request_size(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev); int val = pcie_get_readrq(pci_dev); return snprintf(buf, PCI_SYS_FILE_BUF_SIZE, "%d\n", val); } static ssize_t store_max_read_request_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pci_dev *pci_dev = container_of(dev, struct pci_dev, dev); unsigned long size = 0; int ret; if (0 != kstrtoul(buf, 0, &size)) return -EINVAL; ret = pcie_set_readrq(pci_dev, (int)size); if (ret < 0) return ret; return count; } #endif static DEVICE_ATTR(max_vfs, S_IRUGO | S_IWUSR, show_max_vfs, store_max_vfs); #ifdef RTE_PCI_CONFIG static DEVICE_ATTR(extended_tag, S_IRUGO | S_IWUSR, show_extended_tag, store_extended_tag); static DEVICE_ATTR(max_read_request_size, S_IRUGO | S_IWUSR, show_max_read_request_size, store_max_read_request_size); #endif static struct attribute *dev_attrs[] = { &dev_attr_max_vfs.attr, #ifdef RTE_PCI_CONFIG &dev_attr_extended_tag.attr, &dev_attr_max_read_request_size.attr, #endif NULL, }; static const struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; /* * It masks the msix on/off of generating MSI-X messages. */ static void igbuio_msix_mask_irq(struct msi_desc *desc, int32_t state) { u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; if (state != 0) mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; else mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; if (mask_bits != desc->masked) { writel(mask_bits, desc->mask_base + offset); readl(desc->mask_base); desc->masked = mask_bits; } } /** * This is the irqcontrol callback to be registered to uio_info. * It can be used to disable/enable interrupt from user space processes. * * @param info * pointer to uio_info. * @param irq_state * state value. 1 to enable interrupt, 0 to disable interrupt. * * @return * - On success, 0. * - On failure, a negative value. */ static int igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state) { struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info); struct pci_dev *pdev = udev->pdev; pci_cfg_access_lock(pdev); if (udev->mode == RTE_INTR_MODE_LEGACY) pci_intx(pdev, !!irq_state); else if (udev->mode == RTE_INTR_MODE_MSIX) { struct msi_desc *desc; list_for_each_entry(desc, &pdev->msi_list, list) igbuio_msix_mask_irq(desc, irq_state); } pci_cfg_access_unlock(pdev); return 0; } /** * This is interrupt handler which will check if the interrupt is for the right device. * If yes, disable it here and will be enable later. */ static irqreturn_t igbuio_pci_irqhandler(int irq, struct uio_info *info) { struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info); /* Legacy mode need to mask in hardware */ if (udev->mode == RTE_INTR_MODE_LEGACY && !pci_check_and_mask_intx(udev->pdev)) return IRQ_NONE; /* Message signal mode, no share IRQ and automasked */ return IRQ_HANDLED; } #ifdef CONFIG_XEN_DOM0 static int igbuio_dom0_mmap_phys(struct uio_info *info, struct vm_area_struct *vma) { int idx; idx = (int)vma->vm_pgoff; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #ifdef HAVE_PTE_MASK_PAGE_IOMAP vma->vm_page_prot.pgprot |= _PAGE_IOMAP; #endif return remap_pfn_range(vma, vma->vm_start, info->mem[idx].addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); } /** * This is uio device mmap method which will use igbuio mmap for Xen * Dom0 environment. */ static int igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma) { int idx; if (vma->vm_pgoff >= MAX_UIO_MAPS) return -EINVAL; if (info->mem[vma->vm_pgoff].size == 0) return -EINVAL; idx = (int)vma->vm_pgoff; switch (info->mem[idx].memtype) { case UIO_MEM_PHYS: return igbuio_dom0_mmap_phys(info, vma); case UIO_MEM_LOGICAL: case UIO_MEM_VIRTUAL: default: return -EINVAL; } } #endif /* Remap pci resources described by bar #pci_bar in uio resource n. */ static int igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info, int n, int pci_bar, const char *name) { unsigned long addr, len; void *internal_addr; if (sizeof(info->mem) / sizeof(info->mem[0]) <= n) return -EINVAL; addr = pci_resource_start(dev, pci_bar); len = pci_resource_len(dev, pci_bar); if (addr == 0 || len == 0) return -1; internal_addr = ioremap(addr, len); if (internal_addr == NULL) return -1; info->mem[n].name = name; info->mem[n].addr = addr; info->mem[n].internal_addr = internal_addr; info->mem[n].size = len; info->mem[n].memtype = UIO_MEM_PHYS; return 0; } /* Get pci port io resources described by bar #pci_bar in uio resource n. */ static int igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info, int n, int pci_bar, const char *name) { unsigned long addr, len; if (sizeof(info->port) / sizeof(info->port[0]) <= n) return -EINVAL; addr = pci_resource_start(dev, pci_bar); len = pci_resource_len(dev, pci_bar); if (addr == 0 || len == 0) return -EINVAL; info->port[n].name = name; info->port[n].start = addr; info->port[n].size = len; info->port[n].porttype = UIO_PORT_X86; return 0; } /* Unmap previously ioremap'd resources */ static void igbuio_pci_release_iomem(struct uio_info *info) { int i; for (i = 0; i < MAX_UIO_MAPS; i++) { if (info->mem[i].internal_addr) iounmap(info->mem[i].internal_addr); } } static int igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info) { int i, iom, iop, ret; unsigned long flags; static const char *bar_names[PCI_STD_RESOURCE_END + 1] = { "BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5", }; iom = 0; iop = 0; for (i = 0; i != sizeof(bar_names) / sizeof(bar_names[0]); i++) { if (pci_resource_len(dev, i) != 0 && pci_resource_start(dev, i) != 0) { flags = pci_resource_flags(dev, i); if (flags & IORESOURCE_MEM) { ret = igbuio_pci_setup_iomem(dev, info, iom, i, bar_names[i]); if (ret != 0) return ret; iom++; } else if (flags & IORESOURCE_IO) { ret = igbuio_pci_setup_ioport(dev, info, iop, i, bar_names[i]); if (ret != 0) return ret; iop++; } } } return (iom != 0) ? ret : -ENOENT; } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) static int __devinit #else static int #endif igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct rte_uio_pci_dev *udev; struct msix_entry msix_entry; int err; udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL); if (!udev) return -ENOMEM; /* * enable device: ask low-level code to enable I/O and * memory */ err = pci_enable_device(dev); if (err != 0) { dev_err(&dev->dev, "Cannot enable PCI device\n"); goto fail_free; } /* * reserve device's PCI memory regions for use by this * module */ err = pci_request_regions(dev, "igb_uio"); if (err != 0) { dev_err(&dev->dev, "Cannot request regions\n"); goto fail_disable; } /* enable bus mastering on the device */ pci_set_master(dev); /* remap IO memory */ err = igbuio_setup_bars(dev, &udev->info); if (err != 0) goto fail_release_iomem; /* set 64-bit DMA mask */ err = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set DMA mask\n"); goto fail_release_iomem; } err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); if (err != 0) { dev_err(&dev->dev, "Cannot set consistent DMA mask\n"); goto fail_release_iomem; } /* fill uio infos */ udev->info.name = "igb_uio"; udev->info.version = "0.1"; udev->info.handler = igbuio_pci_irqhandler; udev->info.irqcontrol = igbuio_pci_irqcontrol; #ifdef CONFIG_XEN_DOM0 /* check if the driver run on Xen Dom0 */ if (xen_initial_domain()) udev->info.mmap = igbuio_dom0_pci_mmap; #endif udev->info.priv = udev; udev->pdev = dev; switch (igbuio_intr_mode_preferred) { case RTE_INTR_MODE_MSIX: /* Only 1 msi-x vector needed */ msix_entry.entry = 0; if (pci_enable_msix(dev, &msix_entry, 1) == 0) { dev_dbg(&dev->dev, "using MSI-X"); udev->info.irq = msix_entry.vector; udev->mode = RTE_INTR_MODE_MSIX; break; } /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(dev)) { dev_dbg(&dev->dev, "using INTX"); udev->info.irq_flags = IRQF_SHARED; udev->info.irq = dev->irq; udev->mode = RTE_INTR_MODE_LEGACY; break; } dev_notice(&dev->dev, "PCI INTX mask not supported\n"); /* fall back to no IRQ */ case RTE_INTR_MODE_NONE: udev->mode = RTE_INTR_MODE_NONE; udev->info.irq = 0; break; default: dev_err(&dev->dev, "invalid IRQ mode %u", igbuio_intr_mode_preferred); err = -EINVAL; goto fail_release_iomem; } err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp); if (err != 0) goto fail_release_iomem; /* register uio driver */ err = uio_register_device(&dev->dev, &udev->info); if (err != 0) goto fail_remove_group; pci_set_drvdata(dev, udev); dev_info(&dev->dev, "uio device registered with irq %lx\n", udev->info.irq); return 0; fail_remove_group: sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); fail_release_iomem: igbuio_pci_release_iomem(&udev->info); if (udev->mode == RTE_INTR_MODE_MSIX) pci_disable_msix(udev->pdev); pci_release_regions(dev); fail_disable: pci_disable_device(dev); fail_free: kfree(udev); return err; } static void igbuio_pci_remove(struct pci_dev *dev) { struct uio_info *info = pci_get_drvdata(dev); struct rte_uio_pci_dev *udev = igbuio_get_uio_pci_dev(info); if (info->priv == NULL) { pr_notice("Not igbuio device\n"); return; } sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); uio_unregister_device(info); igbuio_pci_release_iomem(info); if (udev->mode == RTE_INTR_MODE_MSIX) pci_disable_msix(dev); pci_release_regions(dev); pci_disable_device(dev); pci_set_drvdata(dev, NULL); kfree(info); } static int igbuio_config_intr_mode(char *intr_str) { if (!intr_str) { pr_info("Use MSIX interrupt by default\n"); return 0; } if (!strcmp(intr_str, RTE_INTR_MODE_MSIX_NAME)) { igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX; pr_info("Use MSIX interrupt\n"); } else if (!strcmp(intr_str, RTE_INTR_MODE_LEGACY_NAME)) { igbuio_intr_mode_preferred = RTE_INTR_MODE_LEGACY; pr_info("Use legacy interrupt\n"); } else { pr_info("Error: bad parameter - %s\n", intr_str); return -EINVAL; } return 0; } static struct pci_driver igbuio_pci_driver = { .name = "igb_uio", .id_table = NULL, .probe = igbuio_pci_probe, .remove = igbuio_pci_remove, }; static int __init igbuio_pci_init_module(void) { int ret; ret = igbuio_config_intr_mode(intr_mode); if (ret < 0) return ret; return pci_register_driver(&igbuio_pci_driver); } static void __exit igbuio_pci_exit_module(void) { pci_unregister_driver(&igbuio_pci_driver); } module_init(igbuio_pci_init_module); module_exit(igbuio_pci_exit_module); module_param(intr_mode, charp, S_IRUGO); MODULE_PARM_DESC(intr_mode, "igb_uio interrupt mode (default=msix):\n" " " RTE_INTR_MODE_MSIX_NAME " Use MSIX interrupt\n" " " RTE_INTR_MODE_LEGACY_NAME " Use Legacy interrupt\n" "\n"); MODULE_DESCRIPTION("UIO driver for Intel IGB PCI cards"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); ================================================ FILE: lib/librte_eal/linuxapp/kni/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # module name and path # MODULE = rte_kni # # CFLAGS # MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=50 MODULE_CFLAGS += -I$(RTE_OUTPUT)/include -I$(SRCDIR)/ethtool/ixgbe -I$(SRCDIR)/ethtool/igb MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h MODULE_CFLAGS += -Wall -Werror ifeq ($(shell test -f /proc/version_signature && lsb_release -si 2>/dev/null),Ubuntu) MODULE_CFLAGS += -DUBUNTU_RELEASE_CODE=$(shell lsb_release -sr | tr -d .) UBUNTU_KERNEL_CODE := $(shell cut -d' ' -f2 /proc/version_signature | \ cut -d'~' -f1 | cut -d- -f1,2 | tr .- $(comma)) MODULE_CFLAGS += -D"UBUNTU_KERNEL_CODE=UBUNTU_KERNEL_VERSION($(UBUNTU_KERNEL_CODE))" endif # this lib needs main eal DEPDIRS-y += lib/librte_eal/linuxapp/eal # # all source are stored in SRCS-y # SRCS-y := ethtool/ixgbe/ixgbe_main.c SRCS-y += ethtool/ixgbe/ixgbe_api.c SRCS-y += ethtool/ixgbe/ixgbe_common.c SRCS-y += ethtool/ixgbe/ixgbe_ethtool.c SRCS-y += ethtool/ixgbe/ixgbe_82599.c SRCS-y += ethtool/ixgbe/ixgbe_82598.c SRCS-y += ethtool/ixgbe/ixgbe_x540.c SRCS-y += ethtool/ixgbe/ixgbe_phy.c SRCS-y += ethtool/ixgbe/kcompat.c SRCS-y += ethtool/igb/e1000_82575.c SRCS-y += ethtool/igb/e1000_i210.c SRCS-y += ethtool/igb/e1000_api.c SRCS-y += ethtool/igb/e1000_mac.c SRCS-y += ethtool/igb/e1000_manage.c SRCS-y += ethtool/igb/e1000_mbx.c SRCS-y += ethtool/igb/e1000_nvm.c SRCS-y += ethtool/igb/e1000_phy.c SRCS-y += ethtool/igb/igb_ethtool.c SRCS-y += ethtool/igb/igb_hwmon.c SRCS-y += ethtool/igb/igb_main.c SRCS-y += ethtool/igb/igb_debugfs.c SRCS-y += ethtool/igb/igb_param.c SRCS-y += ethtool/igb/igb_procfs.c SRCS-y += ethtool/igb/igb_vmdq.c #SRCS-y += ethtool/igb/igb_ptp.c #SRCS-y += ethtool/igb/kcompat.c SRCS-y += kni_misc.c SRCS-y += kni_net.c SRCS-y += kni_ethtool.c SRCS-$(CONFIG_RTE_KNI_VHOST) += kni_vhost.c include $(RTE_SDK)/mk/rte.module.mk ================================================ FILE: lib/librte_eal/linuxapp/kni/compat.h ================================================ /* * Minimal wrappers to allow compiling kni on older kernels. */ #ifndef RHEL_RELEASE_VERSION #define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \ (!(defined(RHEL_RELEASE_CODE) && \ RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4))) #define kstrtoul strict_strtoul #endif /* < 2.6.39 */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) #define sk_sleep(s) (s)->sk_sleep #endif /* < 2.6.35 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) #define HAVE_IOV_ITER_MSGHDR #endif #if ( LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) ) #define HAVE_KIOCB_MSG_PARAM #endif /* < 4.1.0 */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/README ================================================ .. BSD LICENSE Copyright(c) 2010-2014 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Description In order to support ethtool in Kernel NIC Interface, the standard Linux kernel drivers of ixgbe/igb are needed to be reused here. ixgbe-3.9.17 is the version modified from in kernel NIC interface kernel module to support ixgbe NIC, and igb-3.4.8 is the version modified from in kernel NIC interface kernel module to support igb NIC. The source code package of ixgbe can be downloaded from sourceforge.net as below. http://sourceforge.net/projects/e1000/files/ixgbe%20stable/ Below source files are copied or modified from ixgbe. ixgbe_82598.h ixgbe_82599.c ixgbe_82599.h ixgbe_api.c ixgbe_api.h ixgbe_common.c ixgbe_common.h ixgbe_dcb.h ixgbe_ethtool.c ixgbe_fcoe.h ixgbe.h ixgbe_main.c ixgbe_mbx.h ixgbe_osdep.h ixgbe_phy.c ixgbe_phy.h ixgbe_sriov.h ixgbe_type.h kcompat.c kcompat.h The source code package of igb can be downloaded from sourceforge.net as below. http://sourceforge.net/projects/e1000/files/igb%20stable/ Below source files are copied or modified from igb. e1000_82575.c e1000_82575.h e1000_api.c e1000_api.h e1000_defines.h e1000_hw.h e1000_mac.c e1000_mac.h e1000_manage.c e1000_manage.h e1000_mbx.c e1000_mbx.h e1000_nvm.c e1000_nvm.h e1000_osdep.h e1000_phy.c e1000_phy.h e1000_regs.h igb_ethtool.c igb.h igb_main.c igb_param.c igb_procfs.c igb_regtest.h igb_sysfs.c igb_vmdq.c igb_vmdq.h kcompat.c kcompat_ethtool.c kcompat.h ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/COPYING ================================================ "This software program is licensed subject to the GNU General Public License (GPL). Version 2, June 1991, available at " GNU General Public License Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: * a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. * b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. * c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: * a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine- readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free software, and you are welcome to redistribute it under certain conditions; type 'show c' for details. The hypothetical commands 'show w' and 'show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than 'show w' and 'show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program 'Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* * 82575EB Gigabit Network Connection * 82575EB Gigabit Backplane Connection * 82575GB Gigabit Network Connection * 82576 Gigabit Network Connection * 82576 Quad Port Gigabit Mezzanine Adapter * 82580 Gigabit Network Connection * I350 Gigabit Network Connection */ #include "e1000_api.h" #include "e1000_i210.h" static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); static s32 e1000_init_mac_params_82575(struct e1000_hw *hw); static s32 e1000_acquire_phy_82575(struct e1000_hw *hw); static void e1000_release_phy_82575(struct e1000_hw *hw); static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw); static void e1000_release_nvm_82575(struct e1000_hw *hw); static s32 e1000_check_for_link_82575(struct e1000_hw *hw); static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw); static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); static s32 e1000_init_hw_82575(struct e1000_hw *hw); static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_reset_hw_82575(struct e1000_hw *hw); static s32 e1000_reset_hw_82580(struct e1000_hw *hw); static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data); static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active); static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active); static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active); static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); static s32 e1000_get_media_type_82575(struct e1000_hw *hw); static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw); static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data); static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); static s32 e1000_get_phy_id_82575(struct e1000_hw *hw); static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask); static bool e1000_sgmii_active_82575(struct e1000_hw *hw); static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); static void e1000_config_collision_dist_82575(struct e1000_hw *hw); static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw); static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw); static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw); static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw); static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset); static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset); static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw); static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw); static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value); static void e1000_clear_vfta_i350(struct e1000_hw *hw); static void e1000_i2c_start(struct e1000_hw *hw); static void e1000_i2c_stop(struct e1000_hw *hw); static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data); static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data); static s32 e1000_get_i2c_ack(struct e1000_hw *hw); static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data); static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data); static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data); static bool e1000_get_i2c_data(u32 *i2cctl); static const u16 e1000_82580_rxpbs_table[] = { 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; #define E1000_82580_RXPBS_TABLE_SIZE \ (sizeof(e1000_82580_rxpbs_table)/sizeof(u16)) /** * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO * @hw: pointer to the HW structure * * Called to determine if the I2C pins are being used for I2C or as an * external MDIO interface since the two options are mutually exclusive. **/ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) { u32 reg = 0; bool ext_mdio = false; DEBUGFUNC("e1000_sgmii_uses_mdio_82575"); switch (hw->mac.type) { case e1000_82575: case e1000_82576: reg = E1000_READ_REG(hw, E1000_MDIC); ext_mdio = !!(reg & E1000_MDIC_DEST); break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: reg = E1000_READ_REG(hw, E1000_MDICNFG); ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); break; default: break; } return ext_mdio; } /** * e1000_init_phy_params_82575 - Init PHY func ptrs. * @hw: pointer to the HW structure **/ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 ctrl_ext; DEBUGFUNC("e1000_init_phy_params_82575"); phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; } phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_82575; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; phy->ops.acquire = e1000_acquire_phy_82575; phy->ops.check_reset_block = e1000_check_reset_block_generic; phy->ops.commit = e1000_phy_sw_reset_generic; phy->ops.get_cfg_done = e1000_get_cfg_done_82575; phy->ops.release = e1000_release_phy_82575; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); if (e1000_sgmii_active_82575(hw)) { phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; ctrl_ext |= E1000_CTRL_I2C_ENA; } else { phy->ops.reset = e1000_phy_hw_reset_generic; ctrl_ext &= ~E1000_CTRL_I2C_ENA; } E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); e1000_reset_mdicnfg_82580(hw); if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; } else { switch (hw->mac.type) { case e1000_82580: case e1000_i350: case e1000_i354: phy->ops.read_reg = e1000_read_phy_reg_82580; phy->ops.write_reg = e1000_write_phy_reg_82580; break; case e1000_i210: case e1000_i211: phy->ops.read_reg = e1000_read_phy_reg_gs40g; phy->ops.write_reg = e1000_write_phy_reg_gs40g; break; default: phy->ops.read_reg = e1000_read_phy_reg_igp; phy->ops.write_reg = e1000_write_phy_reg_igp; } } /* Set phy->phy_addr and phy->id. */ ret_val = e1000_get_phy_id_82575(hw); /* Verify phy id and set remaining function pointers */ switch (phy->id) { case M88E1543_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1111_I_PHY_ID: phy->type = e1000_phy_m88; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.get_info = e1000_get_phy_info_m88; if (phy->id == I347AT4_E_PHY_ID || phy->id == M88E1112_E_PHY_ID || phy->id == M88E1340M_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; else if (phy->id == M88E1543_E_PHY_ID) phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; else phy->ops.get_cable_length = e1000_get_cable_length_m88; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; /* Check if this PHY is confgured for media swap. */ if (phy->id == M88E1112_E_PHY_ID) { u16 data; ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 2); if (ret_val) goto out; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_MAC_CTRL_1, &data); if (ret_val) goto out; data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; if (data == E1000_M88E1112_AUTO_COPPER_SGMII || data == E1000_M88E1112_AUTO_COPPER_BASEX) hw->mac.ops.check_for_link = e1000_check_for_link_media_swap; } break; case IGP03E1000_E_PHY_ID: case IGP04E1000_E_PHY_ID: phy->type = e1000_phy_igp_3; phy->ops.check_polarity = e1000_check_polarity_igp; phy->ops.get_info = e1000_get_phy_info_igp; phy->ops.get_cable_length = e1000_get_cable_length_igp_2; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; break; case I82580_I_PHY_ID: case I350_I_PHY_ID: phy->type = e1000_phy_82580; phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577; phy->ops.get_cable_length = e1000_get_cable_length_82577; phy->ops.get_info = e1000_get_phy_info_82577; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; break; case I210_I_PHY_ID: phy->type = e1000_phy_i210; phy->ops.check_polarity = e1000_check_polarity_m88; phy->ops.get_info = e1000_get_phy_info_m88; phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; break; default: ret_val = -E1000_ERR_PHY; goto out; } out: return ret_val; } /** * e1000_init_nvm_params_82575 - Init NVM func ptrs. * @hw: pointer to the HW structure **/ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u16 size; DEBUGFUNC("e1000_init_nvm_params_82575"); size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); /* * Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; /* Just in case size is out of range, cap it to the largest * EEPROM size supported */ if (size > 15) size = 15; nvm->word_size = 1 << size; if (hw->mac.type < e1000_i210) { nvm->opcode_bits = 8; nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: nvm->page_size = 8; nvm->address_bits = 8; break; default: nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } if (nvm->word_size == (1 << 15)) nvm->page_size = 128; nvm->type = e1000_nvm_eeprom_spi; } else { nvm->type = e1000_nvm_flash_hw; } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82575; nvm->ops.release = e1000_release_nvm_82575; if (nvm->word_size < (1 << 15)) nvm->ops.read = e1000_read_nvm_eerd; else nvm->ops.read = e1000_read_nvm_spi; nvm->ops.write = e1000_write_nvm_spi; nvm->ops.validate = e1000_validate_nvm_checksum_generic; nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_82575; /* override generic family function pointers for specific descendants */ switch (hw->mac.type) { case e1000_82580: nvm->ops.validate = e1000_validate_nvm_checksum_82580; nvm->ops.update = e1000_update_nvm_checksum_82580; break; case e1000_i350: //case e1000_i354: nvm->ops.validate = e1000_validate_nvm_checksum_i350; nvm->ops.update = e1000_update_nvm_checksum_i350; break; default: break; } return E1000_SUCCESS; } /** * e1000_init_mac_params_82575 - Init MAC func ptrs. * @hw: pointer to the HW structure **/ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; DEBUGFUNC("e1000_init_mac_params_82575"); /* Derives media type */ e1000_get_media_type_82575(hw); /* Set mta register count */ mac->mta_reg_count = 128; /* Set uta register count */ mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES_82575; if (mac->type == e1000_82576) mac->rar_entry_count = E1000_RAR_ENTRIES_82576; if (mac->type == e1000_82580) mac->rar_entry_count = E1000_RAR_ENTRIES_82580; if (mac->type == e1000_i350 || mac->type == e1000_i354) mac->rar_entry_count = E1000_RAR_ENTRIES_I350; /* Enable EEE default settings for EEE supported devices */ if (mac->type >= e1000_i350) dev_spec->eee_disable = false; /* Allow a single clear of the SW semaphore on I210 and newer */ if (mac->type >= e1000_i210) dev_spec->clear_semaphore_once = true; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* FWSM register */ mac->has_fwsm = true; /* ARC supported; valid only if manageability features are enabled. */ mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); /* Function pointers */ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ if (mac->type >= e1000_82580) mac->ops.reset_hw = e1000_reset_hw_82580; else mac->ops.reset_hw = e1000_reset_hw_82575; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82575; /* link setup */ mac->ops.setup_link = e1000_setup_link_generic; /* physical interface link setup */ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575; /* physical interface shutdown */ mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; /* physical interface power up */ mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* configure collision distance */ mac->ops.config_collision_dist = e1000_config_collision_dist_82575; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_i350; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_i350; } else { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_generic; /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; } if (hw->mac.type >= e1000_82580) mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_crossover_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ mac->ops.blink_led = e1000_blink_led_generic; /* setup LED */ mac->ops.setup_led = e1000_setup_led_generic; /* cleanup LED */ mac->ops.cleanup_led = e1000_cleanup_led_generic; /* turn on/off LED */ mac->ops.led_on = e1000_led_on_generic; mac->ops.led_off = e1000_led_off_generic; /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; /* get thermal sensor data */ mac->ops.get_thermal_sensor_data = e1000_get_thermal_sensor_data_generic; mac->ops.init_thermal_sensor_thresh = e1000_init_thermal_sensor_thresh_generic; /* acquire SW_FW sync */ mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; if (mac->type >= e1000_i210) { mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; } /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); return E1000_SUCCESS; } /** * e1000_init_function_pointers_82575 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_init_function_pointers_82575"); hw->mac.ops.init_params = e1000_init_mac_params_82575; hw->nvm.ops.init_params = e1000_init_nvm_params_82575; hw->phy.ops.init_params = e1000_init_phy_params_82575; hw->mbx.ops.init_params = e1000_init_mbx_params_pf; } /** * e1000_acquire_phy_82575 - Acquire rights to access PHY * @hw: pointer to the HW structure * * Acquire access rights to the correct PHY. **/ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) { u16 mask = E1000_SWFW_PHY0_SM; DEBUGFUNC("e1000_acquire_phy_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_SWFW_PHY2_SM; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; return hw->mac.ops.acquire_swfw_sync(hw, mask); } /** * e1000_release_phy_82575 - Release rights to access PHY * @hw: pointer to the HW structure * * A wrapper to release access rights to the correct PHY. **/ static void e1000_release_phy_82575(struct e1000_hw *hw) { u16 mask = E1000_SWFW_PHY0_SM; DEBUGFUNC("e1000_release_phy_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_SWFW_PHY2_SM; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; hw->mac.ops.release_swfw_sync(hw, mask); } /** * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the serial gigabit media independent * interface and stores the retrieved information in data. **/ static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %u is out of range\n", offset); goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_read_phy_reg_i2c(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset using the serial gigabit * media independent interface. **/ static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %d is out of range\n", offset); goto out; } ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_write_phy_reg_i2c(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_get_phy_id_82575 - Retrieve PHY addr and id * @hw: pointer to the HW structure * * Retrieves the PHY address and ID for both PHY's which do and do not use * sgmi interface. **/ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id; u32 ctrl_ext; u32 mdic; DEBUGFUNC("e1000_get_phy_id_82575"); /* i354 devices can have a PHY that needs an extra read for id */ if (hw->mac.type == e1000_i354) e1000_get_phy_id(hw); /* * For SGMII PHYs, we try the list of possible addresses until * we find one that works. For non-SGMII PHYs * (e.g. integrated copper PHYs), an address of 1 should * work. The result of this function should mean phy->phy_addr * and phy->id are set correctly. */ if (!e1000_sgmii_active_82575(hw)) { phy->addr = 1; ret_val = e1000_get_phy_id(hw); goto out; } if (e1000_sgmii_uses_mdio_82575(hw)) { switch (hw->mac.type) { case e1000_82575: case e1000_82576: mdic = E1000_READ_REG(hw, E1000_MDIC); mdic &= E1000_MDIC_PHY_MASK; phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: mdic = E1000_READ_REG(hw, E1000_MDICNFG); mdic &= E1000_MDICNFG_PHY_MASK; phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; break; default: ret_val = -E1000_ERR_PHY; goto out; break; } ret_val = e1000_get_phy_id(hw); goto out; } /* Power on sgmii phy if it is disabled */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); E1000_WRITE_FLUSH(hw); msec_delay(300); /* * The address field in the I2CCMD register is 3 bits and 0 is invalid. * Therefore, we need to test 1-7 */ for (phy->addr = 1; phy->addr < 8; phy->addr++) { ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); if (ret_val == E1000_SUCCESS) { DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", phy_id, phy->addr); /* * At the time of this writing, The M88 part is * the only supported SGMII PHY product. */ if (phy_id == M88_VENDOR) break; } else { DEBUGOUT1("PHY address %u was unreadable\n", phy->addr); } } /* A valid PHY type couldn't be found. */ if (phy->addr == 8) { phy->addr = 0; ret_val = -E1000_ERR_PHY; } else { ret_val = e1000_get_phy_id(hw); } /* restore previous sfp cage power state */ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); out: return ret_val; } /** * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset * @hw: pointer to the HW structure * * Resets the PHY using the serial gigabit media independent interface. **/ static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); /* * This isn't a true "hard" reset, but is the only reset * available to us at this time. */ DEBUGOUT("Soft resetting SGMII attached PHY...\n"); if (!(hw->phy.ops.write_reg)) goto out; /* * SFP documentation requires the following to configure the SPF module * to work on SGMII. No further documentation is given. */ ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); if (ret_val) goto out; ret_val = hw->phy.ops.commit(hw); out: return ret_val; } /** * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_82575"); if (!(hw->phy.ops.read_reg)) goto out; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) goto out; if (active) { data |= IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) goto out; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) goto out; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) goto out; } } out: return ret_val; } /** * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state * @hw: pointer to the HW structure * @active: true to enable LPLU, false to disable * * Sets the LPLU D0 state according to the active flag. When * activating LPLU this function also disables smart speed * and vice versa. LPLU will not be activated unless the * device autonegotiation advertisement meets standards of * either 10 or 10/100 or 10/100/1000 at all duplexes. * This is a function pointer entry point only called by * PHY setup routines. **/ static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); if (active) { data |= E1000_82580_PM_D0_LPLU; /* When LPLU is enabled, we should disable SmartSpeed */ data &= ~E1000_82580_PM_SPD; } else { data &= ~E1000_82580_PM_D0_LPLU; /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) data |= E1000_82580_PM_SPD; else if (phy->smart_speed == e1000_smart_speed_off) data &= ~E1000_82580_PM_SPD; } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); return ret_val; } /** * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); if (!active) { data &= ~E1000_82580_PM_D3_LPLU; /* * LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) data |= E1000_82580_PM_SPD; else if (phy->smart_speed == e1000_smart_speed_off) data &= ~E1000_82580_PM_SPD; } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= E1000_82580_PM_D3_LPLU; /* When LPLU is enabled, we should disable SmartSpeed */ data &= ~E1000_82580_PM_SPD; } E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); return ret_val; } /** * e1000_acquire_nvm_82575 - Request for access to EEPROM * @hw: pointer to the HW structure * * Acquire the necessary semaphores for exclusive access to the EEPROM. * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_82575"); ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); if (ret_val) goto out; /* * Check if there is some access * error this access may hook on */ if (hw->mac.type == e1000_i350) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT | E1000_EECD_TIMEOUT)) { /* Clear all access error flags */ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_ERROR_CLR); DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); } } if (hw->mac.type == e1000_82580) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & E1000_EECD_BLOCKED) { /* Clear access error flag */ E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_BLOCKED); DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); } } ret_val = e1000_acquire_nvm_generic(hw); if (ret_val) e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); out: return ret_val; } /** * e1000_release_nvm_82575 - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit, * then release the semaphores acquired. **/ static void e1000_release_nvm_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_82575"); e1000_release_nvm_generic(hw); e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); } /** * e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ DEBUGFUNC("e1000_acquire_swfw_sync_82575"); while (i < timeout) { if (e1000_get_hw_semaphore_generic(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } if (i == timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); out: return ret_val; } /** * e1000_release_swfw_sync_82575 - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; DEBUGFUNC("e1000_release_swfw_sync_82575"); while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); } /** * e1000_get_cfg_done_82575 - Read config done bit * @hw: pointer to the HW structure * * Read the management control register for the config done bit for * completion status. NOTE: silicon which is EEPROM-less will fail trying * to read the config done bit, so an error is *ONLY* logged and returns * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon * would not be able to be reset or change link. **/ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; s32 ret_val = E1000_SUCCESS; u32 mask = E1000_NVM_CFG_DONE_PORT_0; DEBUGFUNC("e1000_get_cfg_done_82575"); if (hw->bus.func == E1000_FUNC_1) mask = E1000_NVM_CFG_DONE_PORT_1; else if (hw->bus.func == E1000_FUNC_2) mask = E1000_NVM_CFG_DONE_PORT_2; else if (hw->bus.func == E1000_FUNC_3) mask = E1000_NVM_CFG_DONE_PORT_3; while (timeout) { if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) break; msec_delay(1); timeout--; } if (!timeout) DEBUGOUT("MNG configuration cycle has not completed.\n"); /* If EEPROM is not marked present, init the PHY manually */ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); return ret_val; } /** * e1000_get_link_up_info_82575 - Get link speed/duplex info * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * This is a wrapper function, if using the serial gigabit media independent * interface, use PCS to retrieve the link speed and duplex information. * Otherwise, use the generic function to get the link speed and duplex info. **/ static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex) { s32 ret_val; DEBUGFUNC("e1000_get_link_up_info_82575"); if (hw->phy.media_type != e1000_media_type_copper) ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, duplex); else ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); return ret_val; } /** * e1000_check_for_link_82575 - Check for link * @hw: pointer to the HW structure * * If sgmii is enabled, then use the pcs register to determine link, otherwise * use the generic interface for determining link. **/ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) { s32 ret_val; u16 speed, duplex; DEBUGFUNC("e1000_check_for_link_82575"); if (hw->phy.media_type != e1000_media_type_copper) { ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, &duplex); /* * Use this flag to determine if link needs to be checked or * not. If we have link clear the flag so that we do not * continue to check for link. */ hw->mac.get_link_status = !hw->mac.serdes_has_link; /* * Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); } else { ret_val = e1000_check_for_copper_link_generic(hw); } return ret_val; } /** * e1000_check_for_link_media_swap - Check which M88E1112 interface linked * @hw: pointer to the HW structure * * Poll the M88E1112 interfaces to see which interface achieved link. */ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; u8 port = 0; DEBUGFUNC("e1000_check_for_link_media_swap"); /* Check the copper medium. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); if (ret_val) return ret_val; if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_COPPER; /* Check the other medium. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); if (ret_val) return ret_val; if (data & E1000_M88E1112_STATUS_LINK) port = E1000_MEDIA_PORT_OTHER; /* Determine if a swap needs to happen. */ if (port && (hw->dev_spec._82575.media_port != port)) { hw->dev_spec._82575.media_port = port; hw->dev_spec._82575.media_changed = true; } else { ret_val = e1000_check_for_link_82575(hw); } return E1000_SUCCESS; } /** * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown * @hw: pointer to the HW structure **/ static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_power_up_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return; /* Enable PCS to turn on link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg |= E1000_PCS_CFG_PCS_EN; E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); /* Power up the laser */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* flush the write to verify completion */ E1000_WRITE_FLUSH(hw); msec_delay(1); } /** * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Using the physical coding sub-layer (PCS), retrieve the current speed and * duplex, then store the values in the pointers provided. **/ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex) { struct e1000_mac_info *mac = &hw->mac; u32 pcs; u32 status; DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); /* * Read the PCS Status register for link state. For non-copper mode, * the status register is not accurate. The PCS status register is * used instead. */ pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); /* * The link up bit determines when link is up on autoneg. */ if (pcs & E1000_PCS_LSTS_LINK_OK) { mac->serdes_has_link = true; /* Detect and store PCS speed */ if (pcs & E1000_PCS_LSTS_SPEED_1000) *speed = SPEED_1000; else if (pcs & E1000_PCS_LSTS_SPEED_100) *speed = SPEED_100; else *speed = SPEED_10; /* Detect and store PCS duplex */ if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) *duplex = FULL_DUPLEX; else *duplex = HALF_DUPLEX; /* Check if it is an I354 2.5Gb backplane connection. */ if (mac->type == e1000_i354) { status = E1000_READ_REG(hw, E1000_STATUS); if ((status & E1000_STATUS_2P5_SKU) && !(status & E1000_STATUS_2P5_SKU_OVER)) { *speed = SPEED_2500; *duplex = FULL_DUPLEX; DEBUGOUT("2500 Mbs, "); DEBUGOUT("Full Duplex\n"); } } } else { mac->serdes_has_link = false; *speed = 0; *duplex = 0; } return E1000_SUCCESS; } /** * e1000_shutdown_serdes_link_82575 - Remove link during power down * @hw: pointer to the HW structure * * In the case of serdes shut down sfp and PCS on driver unload * when management pass thru is not enabled. **/ void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) { u32 reg; DEBUGFUNC("e1000_shutdown_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return; if (!e1000_enable_mng_pass_thru(hw)) { /* Disable PCS to turn off link */ reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg &= ~E1000_PCS_CFG_PCS_EN; E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); /* shutdown the laser */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); reg |= E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); /* flush the write to verify completion */ E1000_WRITE_FLUSH(hw); msec_delay(1); } return; } /** * e1000_reset_hw_82575 - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. **/ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_reset_hw_82575"); /* * Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); /* set the completion timeout for interface */ ret_val = e1000_set_pcie_completion_timeout(hw); if (ret_val) DEBUGOUT("PCI-E Set completion timeout has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); ctrl = E1000_READ_REG(hw, E1000_CTRL); DEBUGOUT("Issuing a global reset to MAC\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { /* * When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ DEBUGOUT("Auto Read Done did not complete\n"); } /* If EEPROM is not present, run manual init scripts */ if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); return ret_val; } /** * e1000_init_hw_82575 - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. **/ static s32 e1000_init_hw_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; u16 i, rar_count = mac->rar_entry_count; DEBUGFUNC("e1000_init_hw_82575"); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); if (ret_val) { DEBUGOUT("Error initializing identification LED\n"); /* This is not fatal and we should not stop init due to this */ } /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); /* Setup the receive address */ e1000_init_rx_addrs_generic(hw, rar_count); /* Zero out the Multicast HASH table */ DEBUGOUT("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Zero out the Unicast HASH table */ DEBUGOUT("Zeroing the UTA\n"); for (i = 0; i < mac->uta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* Set the default MTU size */ hw->dev_spec._82575.mtu = 1500; /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_82575(hw); return ret_val; } /** * e1000_setup_copper_link_82575 - Configure copper link settings * @hw: pointer to the HW structure * * Configures the link for auto-neg or forced speed and duplex. Then we check * for link, once link is established calls to configure collision distance * and flow control are called. **/ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; u32 phpm_reg; DEBUGFUNC("e1000_setup_copper_link_82575"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SLU; ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Clear Go Link Disconnect bit on supported devices */ switch (hw->mac.type) { case e1000_82580: case e1000_i350: case e1000_i210: case e1000_i211: phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); phpm_reg &= ~E1000_82580_PM_GO_LINKD; E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); break; default: break; } ret_val = e1000_setup_serdes_link_82575(hw); if (ret_val) goto out; if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) { /* allow time for SFP cage time to power up phy */ msec_delay(300); ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); goto out; } } switch (hw->phy.type) { case e1000_phy_i210: case e1000_phy_m88: switch (hw->phy.id) { case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1543_E_PHY_ID: case I210_I_PHY_ID: ret_val = e1000_copper_link_setup_m88_gen2(hw); break; default: ret_val = e1000_copper_link_setup_m88(hw); break; } break; case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); break; case e1000_phy_82580: ret_val = e1000_copper_link_setup_82577(hw); break; default: ret_val = -E1000_ERR_PHY; break; } if (ret_val) goto out; ret_val = e1000_setup_copper_link_generic(hw); out: return ret_val; } /** * e1000_setup_serdes_link_82575 - Setup link for serdes * @hw: pointer to the HW structure * * Configure the physical coding sub-layer (PCS) link. The PCS link is * used on copper connections where the serialized gigabit media independent * interface (sgmii), or serdes fiber is being used. Configures the link * for auto-negotiation or forces speed/duplex. **/ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) { u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; DEBUGFUNC("e1000_setup_serdes_link_82575"); if ((hw->phy.media_type != e1000_media_type_internal_serdes) && !e1000_sgmii_active_82575(hw)) return ret_val; /* * On the 82575, SerDes loopback mode persists until it is * explicitly turned off or a power cycle is performed. A read to * the register does not indicate its status. Therefore, we ensure * loopback mode is disabled during initialization. */ E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); /* power on the sfp cage if present */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ctrl_reg |= E1000_CTRL_SLU; /* set both sw defined pins on 82575/82576*/ if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; reg = E1000_READ_REG(hw, E1000_PCS_LCTL); /* default pcs_autoneg to the same setting as mac autoneg */ pcs_autoneg = hw->mac.autoneg; switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { case E1000_CTRL_EXT_LINK_MODE_SGMII: /* sgmii mode lets the phy handle forcing speed/duplex */ pcs_autoneg = true; /* autoneg time out should be disabled for SGMII mode */ reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); break; case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: /* disable PCS autoneg and support parallel detect only */ pcs_autoneg = false; /* fall through to default case */ default: if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) pcs_autoneg = false; } /* * non-SGMII modes only supports a speed of 1000/Full for the * link so it is best to just force the MAC and let the pcs * link either autoneg or be forced to 1000/Full */ ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | E1000_CTRL_FD | E1000_CTRL_FRCDPX; /* set speed of 1000/Full if speed/duplex is forced */ reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; break; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); /* * New SerDes mode allows for forcing speed or autonegotiating speed * at 1gb. Autoneg should be default set by most drivers. This is the * mode that will be compatible with older link partners and switches. * However, both are supported by the hardware and some drivers/tools. */ reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ /* Disable force flow control for autoneg */ reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; /* Configure flow control advertisement for autoneg */ anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); switch (hw->fc.requested_mode) { case e1000_fc_full: case e1000_fc_rx_pause: anadv_reg |= E1000_TXCW_ASM_DIR; anadv_reg |= E1000_TXCW_PAUSE; break; case e1000_fc_tx_pause: anadv_reg |= E1000_TXCW_ASM_DIR; break; default: break; } E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ /* Force flow control for forced link */ reg |= E1000_PCS_LCTL_FORCE_FCTRL; DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) e1000_force_mac_fc_generic(hw); return ret_val; } /** * e1000_get_media_type_82575 - derives current media type. * @hw: pointer to the HW structure * * The media type is chosen reflecting few settings. * The following are taken into account: * - link mode set in the current port Init Control Word #3 * - current link mode settings in CSR register * - MDIO vs. I2C PHY control interface chosen * - SFP module media type **/ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) { struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; s32 ret_val = E1000_SUCCESS; u32 ctrl_ext = 0; u32 link_mode = 0; /* Set internal phy as default */ dev_spec->sgmii_active = false; dev_spec->module_plugged = false; /* Get CSR setting */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); /* extract link mode setting */ link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; switch (link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: hw->phy.media_type = e1000_media_type_internal_serdes; break; case E1000_CTRL_EXT_LINK_MODE_GMII: hw->phy.media_type = e1000_media_type_copper; break; case E1000_CTRL_EXT_LINK_MODE_SGMII: /* Get phy control interface type set (MDIO vs. I2C)*/ if (e1000_sgmii_uses_mdio_82575(hw)) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = true; break; } /* fall through for I2C based SGMII */ case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: /* read media type from SFP EEPROM */ ret_val = e1000_set_sfp_media_type_82575(hw); if ((ret_val != E1000_SUCCESS) || (hw->phy.media_type == e1000_media_type_unknown)) { /* * If media type was not identified then return media * type defined by the CTRL_EXT settings. */ hw->phy.media_type = e1000_media_type_internal_serdes; if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = true; } break; } /* do not change link mode for 100BaseFX */ if (dev_spec->eth_flags.e100_base_fx) break; /* change current link mode setting */ ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; if (hw->phy.media_type == e1000_media_type_copper) ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; else ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); break; } return ret_val; } /** * e1000_set_sfp_media_type_82575 - derives SFP module media type. * @hw: pointer to the HW structure * * The media type is chosen based on SFP module. * compatibility flags retrieved from SFP ID EEPROM. **/ static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) { s32 ret_val = E1000_ERR_CONFIG; u32 ctrl_ext = 0; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; u8 tranceiver_type = 0; s32 timeout = 3; /* Turn I2C interface ON and power on sfp cage */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); E1000_WRITE_FLUSH(hw); /* Read SFP module data */ while (timeout) { ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), &tranceiver_type); if (ret_val == E1000_SUCCESS) break; msec_delay(100); timeout--; } if (ret_val != E1000_SUCCESS) goto out; ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), (u8 *)eth_flags); if (ret_val != E1000_SUCCESS) goto out; /* Check if there is some SFP module plugged and powered */ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { dev_spec->module_plugged = true; if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { hw->phy.media_type = e1000_media_type_internal_serdes; } else if (eth_flags->e100_base_fx) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_internal_serdes; } else if (eth_flags->e1000_base_t) { dev_spec->sgmii_active = true; hw->phy.media_type = e1000_media_type_copper; } else { hw->phy.media_type = e1000_media_type_unknown; DEBUGOUT("PHY module has not been recognized\n"); goto out; } } else { hw->phy.media_type = e1000_media_type_unknown; } ret_val = E1000_SUCCESS; out: /* Restore I2C interface setting */ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); return ret_val; } /** * e1000_valid_led_default_82575 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_82575"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { switch (hw->phy.media_type) { case e1000_media_type_internal_serdes: *data = ID_LED_DEFAULT_82575_SERDES; break; case e1000_media_type_copper: default: *data = ID_LED_DEFAULT; break; } } out: return ret_val; } /** * e1000_sgmii_active_82575 - Return sgmii state * @hw: pointer to the HW structure * * 82575 silicon has a serialized gigabit media independent interface (sgmii) * which can be enabled for use in the embedded applications. Simply * return the current state of the sgmii interface. **/ static bool e1000_sgmii_active_82575(struct e1000_hw *hw) { struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; return dev_spec->sgmii_active; } /** * e1000_reset_init_script_82575 - Inits HW defaults after reset * @hw: pointer to the HW structure * * Inits recommended HW defaults after a reset when there is no EEPROM * detected. This is only for the 82575. **/ static s32 e1000_reset_init_script_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_reset_init_script_82575"); if (hw->mac.type == e1000_82575) { DEBUGOUT("Running reset init script for 82575\n"); /* SerDes configuration via SERDESCTRL */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); /* CCM configuration via CCMCTL register */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); /* PCIe lanes configuration */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); /* PCIe PLL Configuration */ e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); } return E1000_SUCCESS; } /** * e1000_read_mac_addr_82575 - Read device MAC address * @hw: pointer to the HW structure **/ static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_mac_addr_82575"); /* * If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) goto out; ret_val = e1000_read_mac_addr_generic(hw); out: return ret_val; } /** * e1000_config_collision_dist_82575 - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ static void e1000_config_collision_dist_82575(struct e1000_hw *hw) { u32 tctl_ext; DEBUGFUNC("e1000_config_collision_dist_82575"); tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT); tctl_ext &= ~E1000_TCTL_EXT_COLD; tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT; E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext); E1000_WRITE_FLUSH(hw); } /** * e1000_power_down_phy_copper_82575 - Remove link during PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/ static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; if (!(phy->ops.check_reset_block)) return; /* If the management interface is not enabled, then power down */ if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw))) e1000_power_down_phy_copper(hw); return; } /** * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters * @hw: pointer to the HW structure * * Clears the hardware counters by reading the counter registers. **/ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_82575"); e1000_clear_hw_cntrs_base_generic(hw); E1000_READ_REG(hw, E1000_PRC64); E1000_READ_REG(hw, E1000_PRC127); E1000_READ_REG(hw, E1000_PRC255); E1000_READ_REG(hw, E1000_PRC511); E1000_READ_REG(hw, E1000_PRC1023); E1000_READ_REG(hw, E1000_PRC1522); E1000_READ_REG(hw, E1000_PTC64); E1000_READ_REG(hw, E1000_PTC127); E1000_READ_REG(hw, E1000_PTC255); E1000_READ_REG(hw, E1000_PTC511); E1000_READ_REG(hw, E1000_PTC1023); E1000_READ_REG(hw, E1000_PTC1522); E1000_READ_REG(hw, E1000_ALGNERRC); E1000_READ_REG(hw, E1000_RXERRC); E1000_READ_REG(hw, E1000_TNCRS); E1000_READ_REG(hw, E1000_CEXTERR); E1000_READ_REG(hw, E1000_TSCTC); E1000_READ_REG(hw, E1000_TSCTFC); E1000_READ_REG(hw, E1000_MGTPRC); E1000_READ_REG(hw, E1000_MGTPDC); E1000_READ_REG(hw, E1000_MGTPTC); E1000_READ_REG(hw, E1000_IAC); E1000_READ_REG(hw, E1000_ICRXOC); E1000_READ_REG(hw, E1000_ICRXPTC); E1000_READ_REG(hw, E1000_ICRXATC); E1000_READ_REG(hw, E1000_ICTXPTC); E1000_READ_REG(hw, E1000_ICTXATC); E1000_READ_REG(hw, E1000_ICTXQEC); E1000_READ_REG(hw, E1000_ICTXQMTC); E1000_READ_REG(hw, E1000_ICRXDMTC); E1000_READ_REG(hw, E1000_CBTMPC); E1000_READ_REG(hw, E1000_HTDPMC); E1000_READ_REG(hw, E1000_CBRMPC); E1000_READ_REG(hw, E1000_RPTHC); E1000_READ_REG(hw, E1000_HGPTC); E1000_READ_REG(hw, E1000_HTCBDPC); E1000_READ_REG(hw, E1000_HGORCL); E1000_READ_REG(hw, E1000_HGORCH); E1000_READ_REG(hw, E1000_HGOTCL); E1000_READ_REG(hw, E1000_HGOTCH); E1000_READ_REG(hw, E1000_LENERRS); /* This register should not be read in copper configurations */ if ((hw->phy.media_type == e1000_media_type_internal_serdes) || e1000_sgmii_active_82575(hw)) E1000_READ_REG(hw, E1000_SCVPC); } /** * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable * @hw: pointer to the HW structure * * After rx enable if managability is enabled then there is likely some * bad data at the start of the fifo and possibly in the DMA fifo. This * function clears the fifos and flushes any packets that came in as rx was * being enabled. **/ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) { u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; int i, ms_wait; DEBUGFUNC("e1000_rx_fifo_workaround_82575"); if (hw->mac.type != e1000_82575 || !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) return; /* Disable all Rx queues */ for (i = 0; i < 4; i++) { rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); } /* Poll all queues to verify they have shut down */ for (ms_wait = 0; ms_wait < 10; ms_wait++) { msec_delay(1); rx_enabled = 0; for (i = 0; i < 4; i++) rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) break; } if (ms_wait == 10) DEBUGOUT("Queue disable timed out after 10ms\n"); /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all * incoming packets are rejected. Set enable and wait 2ms so that * any packet that was coming in as RCTL.EN was set is flushed */ rfctl = E1000_READ_REG(hw, E1000_RFCTL); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); rlpml = E1000_READ_REG(hw, E1000_RLPML); E1000_WRITE_REG(hw, E1000_RLPML, 0); rctl = E1000_READ_REG(hw, E1000_RCTL); temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); temp_rctl |= E1000_RCTL_LPE; E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); E1000_WRITE_FLUSH(hw); msec_delay(2); /* Enable Rx queues that were previously enabled and restore our * previous state */ for (i = 0; i < 4; i++) E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); E1000_WRITE_REG(hw, E1000_RCTL, rctl); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RLPML, rlpml); E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); /* Flush receive errors generated by workaround */ E1000_READ_REG(hw, E1000_ROC); E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_MPC); } /** * e1000_set_pcie_completion_timeout - set pci-e completion timeout * @hw: pointer to the HW structure * * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, * however the hardware default for these parts is 500us to 1ms which is less * than the 10ms recommended by the pci-e spec. To address this we need to * increase the value to either 10ms to 200ms for capability version 1 config, * or 16ms to 55ms for version 2. **/ static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) { u32 gcr = E1000_READ_REG(hw, E1000_GCR); s32 ret_val = E1000_SUCCESS; u16 pcie_devctl2; /* only take action if timeout value is defaulted to 0 */ if (gcr & E1000_GCR_CMPL_TMOUT_MASK) goto out; /* * if capababilities version is type 1 we can write the * timeout of 10ms to 200ms through the GCR register */ if (!(gcr & E1000_GCR_CAP_VER2)) { gcr |= E1000_GCR_CMPL_TMOUT_10ms; goto out; } /* * for version 2 capabilities we need to write the config space * directly in order to set the completion timeout value for * 16ms to 55ms */ ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, &pcie_devctl2); if (ret_val) goto out; pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, &pcie_devctl2); out: /* disable completion timeout resend */ gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; E1000_WRITE_REG(hw, E1000_GCR, gcr); return ret_val; } /** * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * @pf: Physical Function pool - do not set anti-spoofing for the PF * * enables/disables L2 switch anti-spoofing functionality. **/ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) { u32 reg_val, reg_offset; switch (hw->mac.type) { case e1000_82576: reg_offset = E1000_DTXSWC; break; case e1000_i350: case e1000_i354: reg_offset = E1000_TXSWC; break; default: return; } reg_val = E1000_READ_REG(hw, reg_offset); if (enable) { reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | E1000_DTXSWC_VLAN_SPOOF_MASK); /* The PF can spoof - it has to in order to * support emulation mode NICs */ reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); } else { reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | E1000_DTXSWC_VLAN_SPOOF_MASK); } E1000_WRITE_REG(hw, reg_offset, reg_val); } /** * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * * enables/disables L2 switch loopback functionality. **/ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) { u32 dtxswc; switch (hw->mac.type) { case e1000_82576: dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); if (enable) dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; else dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); break; case e1000_i350: case e1000_i354: dtxswc = E1000_READ_REG(hw, E1000_TXSWC); if (enable) dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; else dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); break; default: /* Currently no other hardware supports loopback */ break; } } /** * e1000_vmdq_set_replication_pf - enable or disable vmdq replication * @hw: pointer to the hardware struct * @enable: state to enter, either enabled or disabled * * enables/disables replication of packets across multiple pools. **/ void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) { u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); if (enable) vt_ctl |= E1000_VT_CTL_VM_REPL_EN; else vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); } /** * e1000_read_phy_reg_82580 - Read 82580 MDI control register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the MDI control register in the PHY at offset and stores the * information read to data. **/ static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_read_phy_reg_82580"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_read_phy_reg_mdic(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_write_phy_reg_82580 - Write 82580 MDI control register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write to register at offset * * Writes data to MDI control register in the PHY at offset. **/ static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; DEBUGFUNC("e1000_write_phy_reg_82580"); ret_val = hw->phy.ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_write_phy_reg_mdic(hw, offset, data); hw->phy.ops.release(hw); out: return ret_val; } /** * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits * @hw: pointer to the HW structure * * This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on * the values found in the EEPROM. This addresses an issue in which these * bits are not restored from EEPROM after reset. **/ static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 mdicnfg; u16 nvm_data = 0; DEBUGFUNC("e1000_reset_mdicnfg_82580"); if (hw->mac.type != e1000_82580) goto out; if (!e1000_sgmii_active_82575(hw)) goto out; ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); if (nvm_data & NVM_WORD24_EXT_MDIO) mdicnfg |= E1000_MDICNFG_EXT_MDIO; if (nvm_data & NVM_WORD24_COM_MDIO) mdicnfg |= E1000_MDICNFG_COM_MDIO; E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); out: return ret_val; } /** * e1000_reset_hw_82580 - Reset hardware * @hw: pointer to the HW structure * * This resets function or entire device (all ports, etc.) * to a known state. **/ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; /* BH SW mailbox bit in SW_FW_SYNC */ u16 swmbsw_mask = E1000_SW_SYNCH_MB; u32 ctrl; bool global_device_reset = hw->dev_spec._82575.global_device_reset; DEBUGFUNC("e1000_reset_hw_82580"); hw->dev_spec._82575.global_device_reset = false; /* 82580 does not reliably do global_device_reset due to hw errata */ if (hw->mac.type == e1000_82580) global_device_reset = false; /* Get current control state. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); /* * Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); if (ret_val) DEBUGOUT("PCI-E Master disable polling has failed.\n"); DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); E1000_WRITE_FLUSH(hw); msec_delay(10); /* Determine whether or not a global dev reset is requested */ if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) global_device_reset = false; if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET)) ctrl |= E1000_CTRL_DEV_RST; else ctrl |= E1000_CTRL_RST; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); /* Add delay to insure DEV_RST has time to complete */ if (global_device_reset) msec_delay(5); ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { /* * When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ DEBUGOUT("Auto Read Done did not complete\n"); } /* clear global device reset status bit */ E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); /* Clear any pending interrupt events. */ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); ret_val = e1000_reset_mdicnfg_82580(hw); if (ret_val) DEBUGOUT("Could not reset MDICNFG based on EEPROM\n"); /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); /* Release semaphore */ if (global_device_reset) hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); return ret_val; } /** * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size * @data: data received by reading RXPBS register * * The 82580 uses a table based approach for packet buffer allocation sizes. * This function converts the retrieved value into the correct table value * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 * 0x0 36 72 144 1 2 4 8 16 * 0x8 35 70 140 rsv rsv rsv rsv rsv */ u16 e1000_rxpbs_adjust_82580(u32 data) { u16 ret_val = 0; if (data < E1000_82580_RXPBS_TABLE_SIZE) ret_val = e1000_82580_rxpbs_table[data]; return ret_val; } /** * e1000_validate_nvm_checksum_with_offset - Validate EEPROM * checksum * @hw: pointer to the HW structure * @offset: offset in words of the checksum protected region * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) { s32 ret_val = E1000_SUCCESS; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_validate_nvm_checksum_with_offset"); for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); ret_val = -E1000_ERR_NVM; goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_with_offset - Update EEPROM * checksum * @hw: pointer to the HW structure * @offset: offset in words of the checksum protected region * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/ s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum_with_offset"); for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, &checksum); if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); out: return ret_val; } /** * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM section checksum by reading/adding each word of * the EEPROM and then verifies that the sum of the EEPROM is * equal to 0xBABA. **/ static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 eeprom_regions_count = 1; u16 j, nvm_data; u16 nvm_offset; DEBUGFUNC("e1000_validate_nvm_checksum_82580"); ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { /* if chekcsums compatibility bit is set validate checksums * for all 4 ports. */ eeprom_regions_count = 4; } for (j = 0; j < eeprom_regions_count; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_validate_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_82580 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM section checksums for all 4 ports by reading/adding * each word of the EEPROM up to the checksum. Then calculates the EEPROM * checksum and writes the value to the EEPROM. **/ static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) { s32 ret_val; u16 j, nvm_data; u16 nvm_offset; DEBUGFUNC("e1000_update_nvm_checksum_82580"); ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n"); goto out; } if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { /* set compatibility bit to validate checksums appropriately */ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n"); goto out; } } for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val) goto out; } out: return ret_val; } /** * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM section checksum by reading/adding each word of * the EEPROM and then verifies that the sum of the EEPROM is * equal to 0xBABA. **/ static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 j; u16 nvm_offset; DEBUGFUNC("e1000_validate_nvm_checksum_i350"); for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_validate_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * e1000_update_nvm_checksum_i350 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM section checksums for all 4 ports by reading/adding * each word of the EEPROM up to the checksum. Then calculates the EEPROM * checksum and writes the value to the EEPROM. **/ static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 j; u16 nvm_offset; DEBUGFUNC("e1000_update_nvm_checksum_i350"); for (j = 0; j < 4; j++) { nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); if (ret_val != E1000_SUCCESS) goto out; } out: return ret_val; } /** * __e1000_access_emi_reg - Read/write EMI register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: pointer to value to read/write from/to the EMI address * @read: boolean flag to indicate read or write **/ static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, u16 *data, bool read) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("__e1000_access_emi_reg"); ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); if (ret_val) return ret_val; if (read) ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); else ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); return ret_val; } /** * e1000_read_emi_reg - Read Extended Management Interface register * @hw: pointer to the HW structure * @addr: EMI address to program * @data: value to be read from the EMI address **/ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) { DEBUGFUNC("e1000_read_emi_reg"); return __e1000_access_emi_reg(hw, addr, data, true); } /** * e1000_set_eee_i350 - Enable/disable EEE support * @hw: pointer to the HW structure * * Enable/disable EEE based on setting in dev_spec structure. * **/ s32 e1000_set_eee_i350(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 ipcnfg, eeer; DEBUGFUNC("e1000_set_eee_i350"); if ((hw->mac.type < e1000_i350) || (hw->phy.media_type != e1000_media_type_copper)) goto out; ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); eeer = E1000_READ_REG(hw, E1000_EEER); /* enable or disable per user setting */ if (!(hw->dev_spec._82575.eee_disable)) { u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); /* This bit should not be set in normal operation. */ if (eee_su & E1000_EEE_SU_LPI_CLK_STP) DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); } E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); E1000_WRITE_REG(hw, E1000_EEER, eeer); E1000_READ_REG(hw, E1000_IPCNFG); E1000_READ_REG(hw, E1000_EEER); out: return ret_val; } /** * e1000_set_eee_i354 - Enable/disable EEE support * @hw: pointer to the HW structure * * Enable/disable EEE legacy mode based on setting in dev_spec structure. * **/ s32 e1000_set_eee_i354(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_set_eee_i354"); if ((hw->phy.media_type != e1000_media_type_copper) || ((phy->id != M88E1543_E_PHY_ID))) goto out; if (!hw->dev_spec._82575.eee_disable) { /* Switch to PHY page 18. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); if (ret_val) goto out; ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, &phy_data); if (ret_val) goto out; phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, phy_data); if (ret_val) goto out; /* Return the PHY to page 0. */ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); if (ret_val) goto out; /* Turn on EEE advertisement. */ ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, &phy_data); if (ret_val) goto out; phy_data |= E1000_EEE_ADV_100_SUPPORTED | E1000_EEE_ADV_1000_SUPPORTED; ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); } else { /* Turn off EEE advertisement. */ ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, &phy_data); if (ret_val) goto out; phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | E1000_EEE_ADV_1000_SUPPORTED); ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, E1000_EEE_ADV_DEV_I354, phy_data); } out: return ret_val; } /** * e1000_get_eee_status_i354 - Get EEE status * @hw: pointer to the HW structure * @status: EEE status * * Get EEE status by guessing based on whether Tx or Rx LPI indications have * been received. **/ s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_data; DEBUGFUNC("e1000_get_eee_status_i354"); /* Check if EEE is supported on this device. */ if ((hw->phy.media_type != e1000_media_type_copper) || ((phy->id != M88E1543_E_PHY_ID))) goto out; ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, E1000_PCS_STATUS_DEV_I354, &phy_data); if (ret_val) goto out; *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false; out: return ret_val; } /* Due to a hw errata, if the host tries to configure the VFTA register * while performing queries from the BMC or DMA, then the VFTA in some * cases won't be written. */ /** * e1000_clear_vfta_i350 - Clear VLAN filter table * @hw: pointer to the HW structure * * Clears the register array which contains the VLAN filter table by * setting all the values to 0. **/ void e1000_clear_vfta_i350(struct e1000_hw *hw) { u32 offset; int i; DEBUGFUNC("e1000_clear_vfta_350"); for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { for (i = 0; i < 10; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); E1000_WRITE_FLUSH(hw); } } /** * e1000_write_vfta_i350 - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: register offset in VLAN filter table * @value: register value written to VLAN filter table * * Writes value at the given offset in the register array which stores * the VLAN filter table. **/ void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) { int i; DEBUGFUNC("e1000_write_vfta_350"); for (i = 0; i < 10; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); } /** * e1000_set_i2c_bb - Enable I2C bit-bang * @hw: pointer to the HW structure * * Enable I2C bit-bang interface * **/ s32 e1000_set_i2c_bb(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 ctrl_ext, i2cparams; DEBUGFUNC("e1000_set_i2c_bb"); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_I2C_ENA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS); i2cparams |= E1000_I2CBB_EN; i2cparams |= E1000_I2C_DATA_OE_N; i2cparams |= E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams); E1000_WRITE_FLUSH(hw); return ret_val; } /** * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * * Performs byte read operation over I2C interface at * a specified device address. **/ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { s32 status = E1000_SUCCESS; u32 max_retry = 10; u32 retry = 1; u16 swfw_mask = 0; bool nack = true; DEBUGFUNC("e1000_read_i2c_byte_generic"); swfw_mask = E1000_SWFW_PHY0_SM; do { if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto read_byte_out; } e1000_i2c_start(hw); /* Device Address and write indication */ status = e1000_clock_out_i2c_byte(hw, dev_addr); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, byte_offset); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; e1000_i2c_start(hw); /* Device Address and read indication */ status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1)); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_in_i2c_byte(hw, data); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_bit(hw, nack); if (status != E1000_SUCCESS) goto fail; e1000_i2c_stop(hw); break; fail: hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(100); e1000_i2c_bus_clear(hw); retry++; if (retry < max_retry) DEBUGOUT("I2C byte read error - Retrying.\n"); else DEBUGOUT("I2C byte read error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); read_byte_out: return status; } /** * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * * Performs byte write operation over I2C interface at * a specified device address. **/ s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { s32 status = E1000_SUCCESS; u32 max_retry = 1; u32 retry = 0; u16 swfw_mask = 0; DEBUGFUNC("e1000_write_i2c_byte_generic"); swfw_mask = E1000_SWFW_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto write_byte_out; } do { e1000_i2c_start(hw); status = e1000_clock_out_i2c_byte(hw, dev_addr); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, byte_offset); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; status = e1000_clock_out_i2c_byte(hw, data); if (status != E1000_SUCCESS) goto fail; status = e1000_get_i2c_ack(hw); if (status != E1000_SUCCESS) goto fail; e1000_i2c_stop(hw); break; fail: e1000_i2c_bus_clear(hw); retry++; if (retry < max_retry) DEBUGOUT("I2C byte write error - Retrying.\n"); else DEBUGOUT("I2C byte write error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); write_byte_out: return status; } /** * e1000_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) **/ static void e1000_i2c_start(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_i2c_start"); /* Start condition must begin with data and clock high */ e1000_set_i2c_data(hw, &i2cctl, 1); e1000_raise_i2c_clk(hw, &i2cctl); /* Setup time for start condition (4.7us) */ usec_delay(E1000_I2C_T_SU_STA); e1000_set_i2c_data(hw, &i2cctl, 0); /* Hold time for start condition (4us) */ usec_delay(E1000_I2C_T_HD_STA); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); } /** * e1000_i2c_stop - Sets I2C stop condition * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) **/ static void e1000_i2c_stop(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_i2c_stop"); /* Stop condition must begin with data low and clock high */ e1000_set_i2c_data(hw, &i2cctl, 0); e1000_raise_i2c_clk(hw, &i2cctl); /* Setup time for stop condition (4us) */ usec_delay(E1000_I2C_T_SU_STO); e1000_set_i2c_data(hw, &i2cctl, 1); /* bus free time between stop and start (4.7us)*/ usec_delay(E1000_I2C_T_BUF); } /** * e1000_clock_in_i2c_byte - Clocks in one byte via I2C * @hw: pointer to hardware structure * @data: data byte to clock in * * Clocks in one byte data via I2C data/clock **/ static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data) { s32 i; bool bit = 0; DEBUGFUNC("e1000_clock_in_i2c_byte"); *data = 0; for (i = 7; i >= 0; i--) { e1000_clock_in_i2c_bit(hw, &bit); *data |= bit << i; } return E1000_SUCCESS; } /** * e1000_clock_out_i2c_byte - Clocks out one byte via I2C * @hw: pointer to hardware structure * @data: data byte clocked out * * Clocks out one byte data via I2C data/clock **/ static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data) { s32 status = E1000_SUCCESS; s32 i; u32 i2cctl; bool bit = 0; DEBUGFUNC("e1000_clock_out_i2c_byte"); for (i = 7; i >= 0; i--) { bit = (data >> i) & 0x1; status = e1000_clock_out_i2c_bit(hw, bit); if (status != E1000_SUCCESS) break; } /* Release SDA line (set high) */ i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); i2cctl |= E1000_I2C_DATA_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); E1000_WRITE_FLUSH(hw); return status; } /** * e1000_get_i2c_ack - Polls for I2C ACK * @hw: pointer to hardware structure * * Clocks in/out one bit via I2C data/clock **/ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; u32 i = 0; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 timeout = 10; bool ack = true; DEBUGFUNC("e1000_get_i2c_ack"); e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); /* Wait until SCL returns high */ for (i = 0; i < timeout; i++) { usec_delay(1); i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (i2cctl & E1000_I2C_CLK_IN) break; } if (!(i2cctl & E1000_I2C_CLK_IN)) return E1000_ERR_I2C; ack = e1000_get_i2c_data(&i2cctl); if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = E1000_ERR_I2C; } e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); return status; } /** * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock * @hw: pointer to hardware structure * @data: read data value * * Clocks in one bit via I2C data/clock **/ static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_clock_in_i2c_bit"); e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); *data = e1000_get_i2c_data(&i2cctl); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ usec_delay(E1000_I2C_T_LOW); return E1000_SUCCESS; } /** * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock * @hw: pointer to hardware structure * @data: data value to write * * Clocks out one bit via I2C data/clock **/ static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data) { s32 status; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); DEBUGFUNC("e1000_clock_out_i2c_bit"); status = e1000_set_i2c_data(hw, &i2cctl, data); if (status == E1000_SUCCESS) { e1000_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); e1000_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us. * This also takes care of the data hold time. */ usec_delay(E1000_I2C_T_LOW); } else { status = E1000_ERR_I2C; DEBUGOUT1("I2C data was not set to %X\n", data); } return status; } /** * e1000_raise_i2c_clk - Raises the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' **/ static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) { DEBUGFUNC("e1000_raise_i2c_clk"); *i2cctl |= E1000_I2C_CLK_OUT; *i2cctl &= ~E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* SCL rise time (1000ns) */ usec_delay(E1000_I2C_T_RISE); } /** * e1000_lower_i2c_clk - Lowers the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' **/ static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) { DEBUGFUNC("e1000_lower_i2c_clk"); *i2cctl &= ~E1000_I2C_CLK_OUT; *i2cctl &= ~E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* SCL fall time (300ns) */ usec_delay(E1000_I2C_T_FALL); } /** * e1000_set_i2c_data - Sets the I2C data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit **/ static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data) { s32 status = E1000_SUCCESS; DEBUGFUNC("e1000_set_i2c_data"); if (data) *i2cctl |= E1000_I2C_DATA_OUT; else *i2cctl &= ~E1000_I2C_DATA_OUT; *i2cctl &= ~E1000_I2C_DATA_OE_N; *i2cctl |= E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); E1000_WRITE_FLUSH(hw); /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA); *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (data != e1000_get_i2c_data(i2cctl)) { status = E1000_ERR_I2C; DEBUGOUT1("Error - I2C data was not set to %X.\n", data); } return status; } /** * e1000_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value **/ static bool e1000_get_i2c_data(u32 *i2cctl) { bool data; DEBUGFUNC("e1000_get_i2c_data"); if (*i2cctl & E1000_I2C_DATA_IN) data = 1; else data = 0; return data; } /** * e1000_i2c_bus_clear - Clears the I2C bus * @hw: pointer to hardware structure * * Clears the I2C bus by sending nine clock pulses. * Used when data line is stuck low. **/ void e1000_i2c_bus_clear(struct e1000_hw *hw) { u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 i; DEBUGFUNC("e1000_i2c_bus_clear"); e1000_i2c_start(hw); e1000_set_i2c_data(hw, &i2cctl, 1); for (i = 0; i < 9; i++) { e1000_raise_i2c_clk(hw, &i2cctl); /* Min high period of clock is 4us */ usec_delay(E1000_I2C_T_HIGH); e1000_lower_i2c_clk(hw, &i2cctl); /* Min low period of clock is 4.7us*/ usec_delay(E1000_I2C_T_LOW); } e1000_i2c_start(hw); /* Put the i2c bus back to default state */ e1000_i2c_stop(hw); } static const u8 e1000_emc_temp_data[4] = { E1000_EMC_INTERNAL_DATA, E1000_EMC_DIODE1_DATA, E1000_EMC_DIODE2_DATA, E1000_EMC_DIODE3_DATA }; static const u8 e1000_emc_therm_limit[4] = { E1000_EMC_INTERNAL_THERM_LIMIT, E1000_EMC_DIODE1_THERM_LIMIT, E1000_EMC_DIODE2_THERM_LIMIT, E1000_EMC_DIODE3_THERM_LIMIT }; /** * e1000_get_thermal_sensor_data_generic - Gathers thermal sensor data * @hw: pointer to hardware structure * * Updates the temperatures in mac.thermal_sensor_data **/ s32 e1000_get_thermal_sensor_data_generic(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 i; struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; DEBUGFUNC("e1000_get_thermal_sensor_data_generic"); if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) return E1000_NOT_IMPLEMENTED; data->sensor[0].temp = (E1000_READ_REG(hw, E1000_THMJT) & 0xFF); /* Return the internal sensor only if ETS is unsupported */ e1000_read_nvm(hw, NVM_ETS_CFG, 1, &ets_offset); if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) return status; e1000_read_nvm(hw, ets_offset, 1, &ets_cfg); if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) != NVM_ETS_TYPE_EMC) return E1000_NOT_IMPLEMENTED; num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); if (num_sensors > E1000_MAX_SENSORS) num_sensors = E1000_MAX_SENSORS; for (i = 1; i < num_sensors; i++) { e1000_read_nvm(hw, (ets_offset + i), 1, &ets_sensor); sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> NVM_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> NVM_ETS_DATA_LOC_SHIFT); if (sensor_location != 0) hw->phy.ops.read_i2c_byte(hw, e1000_emc_temp_data[sensor_index], E1000_I2C_THERMAL_SENSOR_ADDR, &data->sensor[i].temp); } return status; } /** * e1000_init_thermal_sensor_thresh_generic - Sets thermal sensor thresholds * @hw: pointer to hardware structure * * Sets the thermal sensor thresholds according to the NVM map * and save off the threshold and location values into mac.thermal_sensor_data **/ s32 e1000_init_thermal_sensor_thresh_generic(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 low_thresh_delta; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 therm_limit; u8 i; struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; DEBUGFUNC("e1000_init_thermal_sensor_thresh_generic"); if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0)) return E1000_NOT_IMPLEMENTED; memset(data, 0, sizeof(struct e1000_thermal_sensor_data)); data->sensor[0].location = 0x1; data->sensor[0].caution_thresh = (E1000_READ_REG(hw, E1000_THHIGHTC) & 0xFF); data->sensor[0].max_op_thresh = (E1000_READ_REG(hw, E1000_THLOWTC) & 0xFF); /* Return the internal sensor only if ETS is unsupported */ e1000_read_nvm(hw, NVM_ETS_CFG, 1, &ets_offset); if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) return status; e1000_read_nvm(hw, ets_offset, 1, &ets_cfg); if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT) != NVM_ETS_TYPE_EMC) return E1000_NOT_IMPLEMENTED; low_thresh_delta = ((ets_cfg & NVM_ETS_LTHRES_DELTA_MASK) >> NVM_ETS_LTHRES_DELTA_SHIFT); num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK); for (i = 1; i <= num_sensors; i++) { e1000_read_nvm(hw, (ets_offset + i), 1, &ets_sensor); sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >> NVM_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >> NVM_ETS_DATA_LOC_SHIFT); therm_limit = ets_sensor & NVM_ETS_DATA_HTHRESH_MASK; hw->phy.ops.write_i2c_byte(hw, e1000_emc_therm_limit[sensor_index], E1000_I2C_THERMAL_SENSOR_ADDR, therm_limit); if ((i < E1000_MAX_SENSORS) && (sensor_location != 0)) { data->sensor[i].location = sensor_location; data->sensor[i].caution_thresh = therm_limit; data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta; } } return status; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_82575.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_82575_H_ #define _E1000_82575_H_ #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ (ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_ON2)) /* * Receive Address Register Count * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * These entries are also used for MAC-based filtering. */ /* * For 82576, there are an additional set of RARs that begin at an offset * separate from the first set of RARs. */ #define E1000_RAR_ENTRIES_82575 16 #define E1000_RAR_ENTRIES_82576 24 #define E1000_RAR_ENTRIES_82580 24 #define E1000_RAR_ENTRIES_I350 32 #define E1000_SW_SYNCH_MB 0x00000100 #define E1000_STAT_DEV_RST_SET 0x00100000 #define E1000_CTRL_DEV_RST 0x20000000 struct e1000_adv_data_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { u32 data; struct { u32 datalen:16; /* Data buffer length */ u32 rsvd:4; u32 dtyp:4; /* Descriptor type */ u32 dcmd:8; /* Descriptor command */ } config; } lower; union { u32 data; struct { u32 status:4; /* Descriptor status */ u32 idx:4; u32 popts:6; /* Packet Options */ u32 paylen:18; /* Payload length */ } options; } upper; }; #define E1000_TXD_DTYP_ADV_C 0x2 /* Advanced Context Descriptor */ #define E1000_TXD_DTYP_ADV_D 0x3 /* Advanced Data Descriptor */ #define E1000_ADV_TXD_CMD_DEXT 0x20 /* Descriptor extension (0 = legacy) */ #define E1000_ADV_TUCMD_IPV4 0x2 /* IP Packet Type: 1=IPv4 */ #define E1000_ADV_TUCMD_IPV6 0x0 /* IP Packet Type: 0=IPv6 */ #define E1000_ADV_TUCMD_L4T_UDP 0x0 /* L4 Packet TYPE of UDP */ #define E1000_ADV_TUCMD_L4T_TCP 0x4 /* L4 Packet TYPE of TCP */ #define E1000_ADV_TUCMD_MKRREQ 0x10 /* Indicates markers are required */ #define E1000_ADV_DCMD_EOP 0x1 /* End of Packet */ #define E1000_ADV_DCMD_IFCS 0x2 /* Insert FCS (Ethernet CRC) */ #define E1000_ADV_DCMD_RS 0x8 /* Report Status */ #define E1000_ADV_DCMD_VLE 0x40 /* Add VLAN tag */ #define E1000_ADV_DCMD_TSE 0x80 /* TCP Seg enable */ /* Extended Device Control */ #define E1000_CTRL_EXT_NSICR 0x00000001 /* Disable Intr Clear all on read */ struct e1000_adv_context_desc { union { u32 ip_config; struct { u32 iplen:9; u32 maclen:7; u32 vlan_tag:16; } fields; } ip_setup; u32 seq_num; union { u64 l4_config; struct { u32 mkrloc:9; u32 tucmd:11; u32 dtyp:4; u32 adv:8; u32 rsvd:4; u32 idx:4; u32 l4len:8; u32 mss:16; } fields; } l4_setup; }; /* SRRCTL bit definitions */ #define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ #define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00 #define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ #define E1000_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000 #define E1000_SRRCTL_TIMESTAMP 0x40000000 #define E1000_SRRCTL_DROP_EN 0x80000000 #define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F #define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00 #define E1000_TX_HEAD_WB_ENABLE 0x1 #define E1000_TX_SEQNUM_WB_ENABLE 0x2 #define E1000_MRQC_ENABLE_RSS_4Q 0x00000002 #define E1000_MRQC_ENABLE_VMDQ 0x00000003 #define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005 #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 #define E1000_MRQC_ENABLE_RSS_8Q 0x00000002 #define E1000_VMRCTL_MIRROR_PORT_SHIFT 8 #define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << \ E1000_VMRCTL_MIRROR_PORT_SHIFT) #define E1000_VMRCTL_POOL_MIRROR_ENABLE (1 << 0) #define E1000_VMRCTL_UPLINK_MIRROR_ENABLE (1 << 1) #define E1000_VMRCTL_DOWNLINK_MIRROR_ENABLE (1 << 2) #define E1000_EICR_TX_QUEUE ( \ E1000_EICR_TX_QUEUE0 | \ E1000_EICR_TX_QUEUE1 | \ E1000_EICR_TX_QUEUE2 | \ E1000_EICR_TX_QUEUE3) #define E1000_EICR_RX_QUEUE ( \ E1000_EICR_RX_QUEUE0 | \ E1000_EICR_RX_QUEUE1 | \ E1000_EICR_RX_QUEUE2 | \ E1000_EICR_RX_QUEUE3) #define E1000_EIMS_RX_QUEUE E1000_EICR_RX_QUEUE #define E1000_EIMS_TX_QUEUE E1000_EICR_TX_QUEUE #define EIMS_ENABLE_MASK ( \ E1000_EIMS_RX_QUEUE | \ E1000_EIMS_TX_QUEUE | \ E1000_EIMS_TCP_TIMER | \ E1000_EIMS_OTHER) /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ #define E1000_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ #define E1000_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ #define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ #define E1000_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */ #define E1000_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */ #define E1000_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */ #define E1000_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */ #define E1000_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */ #define E1000_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */ #define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */ /* Receive Descriptor - Advanced */ union e1000_adv_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { __le32 data; struct { __le16 pkt_info; /*RSS type, Pkt type*/ /* Split Header, header buffer len */ __le16 hdr_info; } hs_rss; } lo_dword; union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; /* Packet length */ __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; #define E1000_RXDADV_RSSTYPE_MASK 0x0000000F #define E1000_RXDADV_RSSTYPE_SHIFT 12 #define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0 #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 #define E1000_RXDADV_SPLITHEADER_EN 0x00001000 #define E1000_RXDADV_SPH 0x8000 #define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */ #define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */ #define E1000_RXDADV_ERR_HBO 0x00800000 /* RSS Hash results */ #define E1000_RXDADV_RSSTYPE_NONE 0x00000000 #define E1000_RXDADV_RSSTYPE_IPV4_TCP 0x00000001 #define E1000_RXDADV_RSSTYPE_IPV4 0x00000002 #define E1000_RXDADV_RSSTYPE_IPV6_TCP 0x00000003 #define E1000_RXDADV_RSSTYPE_IPV6_EX 0x00000004 #define E1000_RXDADV_RSSTYPE_IPV6 0x00000005 #define E1000_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006 #define E1000_RXDADV_RSSTYPE_IPV4_UDP 0x00000007 #define E1000_RXDADV_RSSTYPE_IPV6_UDP 0x00000008 #define E1000_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 /* RSS Packet Types as indicated in the receive descriptor */ #define E1000_RXDADV_PKTTYPE_NONE 0x00000000 #define E1000_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */ #define E1000_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */ #define E1000_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */ #define E1000_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */ #define E1000_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ #define E1000_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ #define E1000_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define E1000_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ #define E1000_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ #define E1000_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ #define E1000_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ #define E1000_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ #define E1000_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ #define E1000_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ /* LinkSec results */ /* Security Processing bit Indication */ #define E1000_RXDADV_LNKSEC_STATUS_SECP 0x00020000 #define E1000_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 #define E1000_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 #define E1000_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 #define E1000_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 #define E1000_RXDADV_IPSEC_STATUS_SECP 0x00020000 #define E1000_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 #define E1000_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 #define E1000_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 #define E1000_RXDADV_IPSEC_ERROR_AUTHENTICATION_FAILED 0x18000000 /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { __le64 buffer_addr; /* Address of descriptor's data buf */ __le32 cmd_type_len; __le32 olinfo_status; } read; struct { __le64 rsvd; /* Reserved */ __le32 nxtseq_seed; __le32 status; } wb; }; /* Adv Transmit Descriptor Config Masks */ #define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */ #define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ #define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */ #define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */ #define E1000_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */ #define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */ #define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define E1000_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on pkt */ #define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp pkt */ #define E1000_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED prsnt in WB */ #define E1000_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ #define E1000_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ #define E1000_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ /* 1st & Last TSO-full iSCSI PDU*/ #define E1000_ADVTXD_POPTS_ISCO_FULL 0x00001800 #define E1000_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ /* Context descriptors */ struct e1000_adv_tx_context_desc { __le32 vlan_macip_lens; __le32 seqnum_seed; __le32 type_tucmd_mlhl; __le32 mss_l4len_idx; }; #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define E1000_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ #define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ #define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ #define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ #define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ #define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ /* IPSec Encrypt Enable for ESP */ #define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000 /* Req requires Markers and CRC */ #define E1000_ADVTXD_TUCMD_MKRREQ 0x00002000 #define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ /* Adv ctxt IPSec SA IDX mask */ #define E1000_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF /* Adv ctxt IPSec ESP len mask */ #define E1000_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF /* Additional Transmit Descriptor Control definitions */ #define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ #define E1000_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wbk flushing */ /* Tx Queue Arbitration Priority 0=low, 1=high */ #define E1000_TXDCTL_PRIORITY 0x08000000 /* Additional Receive Descriptor Control definitions */ #define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */ #define E1000_RXDCTL_SWFLSH 0x04000000 /* Rx Desc. wbk flushing */ /* Direct Cache Access (DCA) definitions */ #define E1000_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ #define E1000_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ #define E1000_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ #define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ #define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header ena */ #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload ena */ #define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx Desc Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ #define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ #define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ #define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ #define E1000_DCA_TXCTRL_CPUID_SHIFT_82576 24 /* Tx CPUID */ #define E1000_DCA_RXCTRL_CPUID_SHIFT_82576 24 /* Rx CPUID */ /* Additional interrupt register bit definitions */ #define E1000_ICR_LSECPNS 0x00000020 /* PN threshold - server */ #define E1000_IMS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ #define E1000_ICS_LSECPNS E1000_ICR_LSECPNS /* PN threshold - server */ /* ETQF register bit definitions */ #define E1000_ETQF_FILTER_ENABLE (1 << 26) #define E1000_ETQF_IMM_INT (1 << 29) #define E1000_ETQF_1588 (1 << 30) #define E1000_ETQF_QUEUE_ENABLE (1 << 31) /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters * here!! * * Current filters: * EAPOL 802.1x (0x888e): Filter 0 */ #define E1000_ETQF_FILTER_EAPOL 0 #define E1000_FTQF_VF_BP 0x00008000 #define E1000_FTQF_1588_TIME_STAMP 0x08000000 #define E1000_FTQF_MASK 0xF0000000 #define E1000_FTQF_MASK_PROTO_BP 0x10000000 #define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000 #define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000 #define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000 #define E1000_NVM_APME_82575 0x0400 #define MAX_NUM_VFS 7 #define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof cntrl */ #define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof cntrl */ #define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */ #define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8 #define E1000_DTXSWC_LLE_SHIFT 16 #define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */ /* Easy defines for setting default pool, would normally be left a zero */ #define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7 #define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT) /* Other useful VMD_CTL register defines */ #define E1000_VT_CTL_IGNORE_MAC (1 << 28) #define E1000_VT_CTL_DISABLE_DEF_POOL (1 << 29) #define E1000_VT_CTL_VM_REPL_EN (1 << 30) /* Per VM Offload register setup */ #define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */ #define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */ #define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */ #define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */ #define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */ #define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */ #define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */ #define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */ #define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ #define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */ #define E1000_VMOLR_VPE 0x00800000 /* VLAN promiscuous enable */ #define E1000_VMOLR_UPE 0x20000000 /* Unicast promisuous enable */ #define E1000_DVMOLR_HIDVLAN 0x20000000 /* Vlan hiding enable */ #define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */ #define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */ #define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */ #define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */ #define E1000_VLVF_ARRAY_SIZE 32 #define E1000_VLVF_VLANID_MASK 0x00000FFF #define E1000_VLVF_POOLSEL_SHIFT 12 #define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT) #define E1000_VLVF_LVLAN 0x00100000 #define E1000_VLVF_VLANID_ENABLE 0x80000000 #define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */ #define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */ #define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ #define E1000_IOVCTL 0x05BBC #define E1000_IOVCTL_REUSE_VFQ 0x00000001 #define E1000_RPLOLR_STRVLAN 0x40000000 #define E1000_RPLOLR_STRCRC 0x80000000 #define E1000_TCTL_EXT_COLD 0x000FFC00 #define E1000_TCTL_EXT_COLD_SHIFT 10 #define E1000_DTXCTL_8023LL 0x0004 #define E1000_DTXCTL_VLAN_ADDED 0x0008 #define E1000_DTXCTL_OOS_ENABLE 0x0010 #define E1000_DTXCTL_MDP_EN 0x0020 #define E1000_DTXCTL_SPOOF_INT 0x0040 #define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT (1 << 14) #define ALL_QUEUES 0xFFFF /* Rx packet buffer size defines */ #define E1000_RXPBS_SIZE_MASK_82576 0x0000007F void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable); void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf); void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable); s32 e1000_init_nvm_params_82575(struct e1000_hw *hw); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); s32 e1000_set_eee_i350(struct e1000_hw *); s32 e1000_set_eee_i354(struct e1000_hw *); s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *); #define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8 #define E1000_EMC_INTERNAL_DATA 0x00 #define E1000_EMC_INTERNAL_THERM_LIMIT 0x20 #define E1000_EMC_DIODE1_DATA 0x01 #define E1000_EMC_DIODE1_THERM_LIMIT 0x19 #define E1000_EMC_DIODE2_DATA 0x23 #define E1000_EMC_DIODE2_THERM_LIMIT 0x1A #define E1000_EMC_DIODE3_DATA 0x2A #define E1000_EMC_DIODE3_THERM_LIMIT 0x30 s32 e1000_get_thermal_sensor_data_generic(struct e1000_hw *hw); s32 e1000_init_thermal_sensor_thresh_generic(struct e1000_hw *hw); /* I2C SDA and SCL timing parameters for standard mode */ #define E1000_I2C_T_HD_STA 4 #define E1000_I2C_T_LOW 5 #define E1000_I2C_T_HIGH 4 #define E1000_I2C_T_SU_STA 5 #define E1000_I2C_T_HD_DATA 5 #define E1000_I2C_T_SU_DATA 1 #define E1000_I2C_T_RISE 1 #define E1000_I2C_T_FALL 1 #define E1000_I2C_T_SU_STO 4 #define E1000_I2C_T_BUF 5 s32 e1000_set_i2c_bb(struct e1000_hw *hw); s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); void e1000_i2c_bus_clear(struct e1000_hw *hw); #endif /* _E1000_82575_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_api.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" /** * e1000_init_mac_params - Initialize MAC function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the MAC * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_mac_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->mac.ops.init_params) { ret_val = hw->mac.ops.init_params(hw); if (ret_val) { DEBUGOUT("MAC Initialization Error\n"); goto out; } } else { DEBUGOUT("mac.init_mac_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_nvm_params - Initialize NVM function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the NVM * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_nvm_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->nvm.ops.init_params) { ret_val = hw->nvm.ops.init_params(hw); if (ret_val) { DEBUGOUT("NVM Initialization Error\n"); goto out; } } else { DEBUGOUT("nvm.init_nvm_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_phy_params - Initialize PHY function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the PHY * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_phy_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->phy.ops.init_params) { ret_val = hw->phy.ops.init_params(hw); if (ret_val) { DEBUGOUT("PHY Initialization Error\n"); goto out; } } else { DEBUGOUT("phy.init_phy_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_init_mbx_params - Initialize mailbox function pointers * @hw: pointer to the HW structure * * This function initializes the function pointers for the PHY * set of functions. Called by drivers or by e1000_setup_init_funcs. **/ s32 e1000_init_mbx_params(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; if (hw->mbx.ops.init_params) { ret_val = hw->mbx.ops.init_params(hw); if (ret_val) { DEBUGOUT("Mailbox Initialization Error\n"); goto out; } } else { DEBUGOUT("mbx.init_mbx_params was NULL\n"); ret_val = -E1000_ERR_CONFIG; } out: return ret_val; } /** * e1000_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * device ID stored in the hw structure. * MUST BE FIRST FUNCTION CALLED (explicitly or through * e1000_setup_init_funcs()). **/ s32 e1000_set_mac_type(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_set_mac_type"); switch (hw->device_id) { case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: mac->type = e1000_82575; break; case E1000_DEV_ID_82576: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: case E1000_DEV_ID_82576_NS: case E1000_DEV_ID_82576_NS_SERDES: case E1000_DEV_ID_82576_SERDES_QUAD: mac->type = e1000_82576; break; case E1000_DEV_ID_82580_COPPER: case E1000_DEV_ID_82580_FIBER: case E1000_DEV_ID_82580_SERDES: case E1000_DEV_ID_82580_SGMII: case E1000_DEV_ID_82580_COPPER_DUAL: case E1000_DEV_ID_82580_QUAD_FIBER: case E1000_DEV_ID_DH89XXCC_SGMII: case E1000_DEV_ID_DH89XXCC_SERDES: case E1000_DEV_ID_DH89XXCC_BACKPLANE: case E1000_DEV_ID_DH89XXCC_SFP: mac->type = e1000_82580; break; case E1000_DEV_ID_I350_COPPER: case E1000_DEV_ID_I350_FIBER: case E1000_DEV_ID_I350_SERDES: case E1000_DEV_ID_I350_SGMII: case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; case E1000_DEV_ID_I210_COPPER_FLASHLESS: case E1000_DEV_ID_I210_SERDES_FLASHLESS: case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: case E1000_DEV_ID_I210_FIBER: case E1000_DEV_ID_I210_SERDES: case E1000_DEV_ID_I210_SGMII: mac->type = e1000_i210; break; case E1000_DEV_ID_I211_COPPER: mac->type = e1000_i211; break; case E1000_DEV_ID_I354_BACKPLANE_1GBPS: case E1000_DEV_ID_I354_SGMII: case E1000_DEV_ID_I354_BACKPLANE_2_5GBPS: mac->type = e1000_i354; break; default: /* Should never have loaded on this device */ ret_val = -E1000_ERR_MAC_INIT; break; } return ret_val; } /** * e1000_setup_init_funcs - Initializes function pointers * @hw: pointer to the HW structure * @init_device: true will initialize the rest of the function pointers * getting the device ready for use. false will only set * MAC type and the function pointers for the other init * functions. Passing false will not generate any hardware * reads or writes. * * This function must be called by a driver in order to use the rest * of the 'shared' code files. Called by drivers only. **/ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) { s32 ret_val; /* Can't do much good without knowing the MAC type. */ ret_val = e1000_set_mac_type(hw); if (ret_val) { DEBUGOUT("ERROR: MAC type could not be set properly.\n"); goto out; } if (!hw->hw_addr) { DEBUGOUT("ERROR: Registers not mapped\n"); ret_val = -E1000_ERR_CONFIG; goto out; } /* * Init function pointers to generic implementations. We do this first * allowing a driver module to override it afterward. */ e1000_init_mac_ops_generic(hw); e1000_init_phy_ops_generic(hw); e1000_init_nvm_ops_generic(hw); e1000_init_mbx_ops_generic(hw); /* * Set up the init function pointers. These are functions within the * adapter family file that sets up function pointers for the rest of * the functions in that family. */ switch (hw->mac.type) { case e1000_82575: case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: e1000_init_function_pointers_82575(hw); break; case e1000_i210: case e1000_i211: e1000_init_function_pointers_i210(hw); break; default: DEBUGOUT("Hardware not supported\n"); ret_val = -E1000_ERR_CONFIG; break; } /* * Initialize the rest of the function pointers. These require some * register reads/writes in some cases. */ if (!(ret_val) && init_device) { ret_val = e1000_init_mac_params(hw); if (ret_val) goto out; ret_val = e1000_init_nvm_params(hw); if (ret_val) goto out; ret_val = e1000_init_phy_params(hw); if (ret_val) goto out; ret_val = e1000_init_mbx_params(hw); if (ret_val) goto out; } out: return ret_val; } /** * e1000_get_bus_info - Obtain bus information for adapter * @hw: pointer to the HW structure * * This will obtain information about the HW bus for which the * adapter is attached and stores it in the hw structure. This is a * function pointer entry point called by drivers. **/ s32 e1000_get_bus_info(struct e1000_hw *hw) { if (hw->mac.ops.get_bus_info) return hw->mac.ops.get_bus_info(hw); return E1000_SUCCESS; } /** * e1000_clear_vfta - Clear VLAN filter table * @hw: pointer to the HW structure * * This clears the VLAN filter table on the adapter. This is a function * pointer entry point called by drivers. **/ void e1000_clear_vfta(struct e1000_hw *hw) { if (hw->mac.ops.clear_vfta) hw->mac.ops.clear_vfta(hw); } /** * e1000_write_vfta - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: the 32-bit offset in which to write the value to. * @value: the 32-bit value to write at location offset. * * This writes a 32-bit value to a 32-bit offset in the VLAN filter * table. This is a function pointer entry point called by drivers. **/ void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) { if (hw->mac.ops.write_vfta) hw->mac.ops.write_vfta(hw, offset, value); } /** * e1000_update_mc_addr_list - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates the Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. **/ void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { if (hw->mac.ops.update_mc_addr_list) hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count); } /** * e1000_force_mac_fc - Force MAC flow control * @hw: pointer to the HW structure * * Force the MAC's flow control settings. Currently no func pointer exists * and all implementations are handled in the generic version of this * function. **/ s32 e1000_force_mac_fc(struct e1000_hw *hw) { return e1000_force_mac_fc_generic(hw); } /** * e1000_check_for_link - Check/Store link connection * @hw: pointer to the HW structure * * This checks the link condition of the adapter and stores the * results in the hw->mac structure. This is a function pointer entry * point called by drivers. **/ s32 e1000_check_for_link(struct e1000_hw *hw) { if (hw->mac.ops.check_for_link) return hw->mac.ops.check_for_link(hw); return -E1000_ERR_CONFIG; } /** * e1000_check_mng_mode - Check management mode * @hw: pointer to the HW structure * * This checks if the adapter has manageability enabled. * This is a function pointer entry point called by drivers. **/ bool e1000_check_mng_mode(struct e1000_hw *hw) { if (hw->mac.ops.check_mng_mode) return hw->mac.ops.check_mng_mode(hw); return false; } /** * e1000_mng_write_dhcp_info - Writes DHCP info to host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface * @length: size of the buffer * * Writes the DHCP information to the host interface. **/ s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) { return e1000_mng_write_dhcp_info_generic(hw, buffer, length); } /** * e1000_reset_hw - Reset hardware * @hw: pointer to the HW structure * * This resets the hardware into a known state. This is a function pointer * entry point called by drivers. **/ s32 e1000_reset_hw(struct e1000_hw *hw) { if (hw->mac.ops.reset_hw) return hw->mac.ops.reset_hw(hw); return -E1000_ERR_CONFIG; } /** * e1000_init_hw - Initialize hardware * @hw: pointer to the HW structure * * This inits the hardware readying it for operation. This is a function * pointer entry point called by drivers. **/ s32 e1000_init_hw(struct e1000_hw *hw) { if (hw->mac.ops.init_hw) return hw->mac.ops.init_hw(hw); return -E1000_ERR_CONFIG; } /** * e1000_setup_link - Configures link and flow control * @hw: pointer to the HW structure * * This configures link and flow control settings for the adapter. This * is a function pointer entry point called by drivers. While modules can * also call this, they probably call their own version of this function. **/ s32 e1000_setup_link(struct e1000_hw *hw) { if (hw->mac.ops.setup_link) return hw->mac.ops.setup_link(hw); return -E1000_ERR_CONFIG; } /** * e1000_get_speed_and_duplex - Returns current speed and duplex * @hw: pointer to the HW structure * @speed: pointer to a 16-bit value to store the speed * @duplex: pointer to a 16-bit value to store the duplex. * * This returns the speed and duplex of the adapter in the two 'out' * variables passed in. This is a function pointer entry point called * by drivers. **/ s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) { if (hw->mac.ops.get_link_up_info) return hw->mac.ops.get_link_up_info(hw, speed, duplex); return -E1000_ERR_CONFIG; } /** * e1000_setup_led - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. This is a function pointer entry * point called by drivers. **/ s32 e1000_setup_led(struct e1000_hw *hw) { if (hw->mac.ops.setup_led) return hw->mac.ops.setup_led(hw); return E1000_SUCCESS; } /** * e1000_cleanup_led - Restores SW controllable LED * @hw: pointer to the HW structure * * This restores the SW controllable LED to the value saved off by * e1000_setup_led. This is a function pointer entry point called by drivers. **/ s32 e1000_cleanup_led(struct e1000_hw *hw) { if (hw->mac.ops.cleanup_led) return hw->mac.ops.cleanup_led(hw); return E1000_SUCCESS; } /** * e1000_blink_led - Blink SW controllable LED * @hw: pointer to the HW structure * * This starts the adapter LED blinking. Request the LED to be setup first * and cleaned up after. This is a function pointer entry point called by * drivers. **/ s32 e1000_blink_led(struct e1000_hw *hw) { if (hw->mac.ops.blink_led) return hw->mac.ops.blink_led(hw); return E1000_SUCCESS; } /** * e1000_id_led_init - store LED configurations in SW * @hw: pointer to the HW structure * * Initializes the LED config in SW. This is a function pointer entry point * called by drivers. **/ s32 e1000_id_led_init(struct e1000_hw *hw) { if (hw->mac.ops.id_led_init) return hw->mac.ops.id_led_init(hw); return E1000_SUCCESS; } /** * e1000_led_on - Turn on SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED on. This is a function pointer entry point * called by drivers. **/ s32 e1000_led_on(struct e1000_hw *hw) { if (hw->mac.ops.led_on) return hw->mac.ops.led_on(hw); return E1000_SUCCESS; } /** * e1000_led_off - Turn off SW controllable LED * @hw: pointer to the HW structure * * Turns the SW defined LED off. This is a function pointer entry point * called by drivers. **/ s32 e1000_led_off(struct e1000_hw *hw) { if (hw->mac.ops.led_off) return hw->mac.ops.led_off(hw); return E1000_SUCCESS; } /** * e1000_reset_adaptive - Reset adaptive IFS * @hw: pointer to the HW structure * * Resets the adaptive IFS. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ void e1000_reset_adaptive(struct e1000_hw *hw) { e1000_reset_adaptive_generic(hw); } /** * e1000_update_adaptive - Update adaptive IFS * @hw: pointer to the HW structure * * Updates adapter IFS. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ void e1000_update_adaptive(struct e1000_hw *hw) { e1000_update_adaptive_generic(hw); } /** * e1000_disable_pcie_master - Disable PCI-Express master access * @hw: pointer to the HW structure * * Disables PCI-Express master access and verifies there are no pending * requests. Currently no func pointer exists and all implementations are * handled in the generic version of this function. **/ s32 e1000_disable_pcie_master(struct e1000_hw *hw) { return e1000_disable_pcie_master_generic(hw); } /** * e1000_config_collision_dist - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ void e1000_config_collision_dist(struct e1000_hw *hw) { if (hw->mac.ops.config_collision_dist) hw->mac.ops.config_collision_dist(hw); } /** * e1000_rar_set - Sets a receive address register * @hw: pointer to the HW structure * @addr: address to set the RAR to * @index: the RAR to set * * Sets a Receive Address Register (RAR) to the specified address. **/ void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) { if (hw->mac.ops.rar_set) hw->mac.ops.rar_set(hw, addr, index); } /** * e1000_validate_mdi_setting - Ensures valid MDI/MDIX SW state * @hw: pointer to the HW structure * * Ensures that the MDI/MDIX SW state is valid. **/ s32 e1000_validate_mdi_setting(struct e1000_hw *hw) { if (hw->mac.ops.validate_mdi_setting) return hw->mac.ops.validate_mdi_setting(hw); return E1000_SUCCESS; } /** * e1000_hash_mc_addr - Determines address location in multicast table * @hw: pointer to the HW structure * @mc_addr: Multicast address to hash. * * This hashes an address to determine its location in the multicast * table. Currently no func pointer exists and all implementations * are handled in the generic version of this function. **/ u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) { return e1000_hash_mc_addr_generic(hw, mc_addr); } /** * e1000_enable_tx_pkt_filtering - Enable packet filtering on TX * @hw: pointer to the HW structure * * Enables packet filtering on transmit packets if manageability is enabled * and host interface is enabled. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw) { return e1000_enable_tx_pkt_filtering_generic(hw); } /** * e1000_mng_host_if_write - Writes to the manageability host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface buffer * @length: size of the buffer * @offset: location in the buffer to write to * @sum: sum of the data (not checksum) * * This function writes the buffer content at the offset given on the host if. * It also does alignment considerations to do the writes in most efficient * way. Also fills up the sum of the buffer in *buffer parameter. **/ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { return e1000_mng_host_if_write_generic(hw, buffer, length, offset, sum); } /** * e1000_mng_write_cmd_header - Writes manageability command header * @hw: pointer to the HW structure * @hdr: pointer to the host interface command header * * Writes the command header after does the checksum calculation. **/ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { return e1000_mng_write_cmd_header_generic(hw, hdr); } /** * e1000_mng_enable_host_if - Checks host interface is enabled * @hw: pointer to the HW structure * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ s32 e1000_mng_enable_host_if(struct e1000_hw *hw) { return e1000_mng_enable_host_if_generic(hw); } /** * e1000_check_reset_block - Verifies PHY can be reset * @hw: pointer to the HW structure * * Checks if the PHY is in a state that can be reset or if manageability * has it tied up. This is a function pointer entry point called by drivers. **/ s32 e1000_check_reset_block(struct e1000_hw *hw) { if (hw->phy.ops.check_reset_block) return hw->phy.ops.check_reset_block(hw); return E1000_SUCCESS; } /** * e1000_read_phy_reg - Reads PHY register * @hw: pointer to the HW structure * @offset: the register to read * @data: the buffer to store the 16-bit read. * * Reads the PHY register and returns the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data) { if (hw->phy.ops.read_reg) return hw->phy.ops.read_reg(hw, offset, data); return E1000_SUCCESS; } /** * e1000_write_phy_reg - Writes PHY register * @hw: pointer to the HW structure * @offset: the register to write * @data: the value to write. * * Writes the PHY register at offset with the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data) { if (hw->phy.ops.write_reg) return hw->phy.ops.write_reg(hw, offset, data); return E1000_SUCCESS; } /** * e1000_release_phy - Generic release PHY * @hw: pointer to the HW structure * * Return if silicon family does not require a semaphore when accessing the * PHY. **/ void e1000_release_phy(struct e1000_hw *hw) { if (hw->phy.ops.release) hw->phy.ops.release(hw); } /** * e1000_acquire_phy - Generic acquire PHY * @hw: pointer to the HW structure * * Return success if silicon family does not require a semaphore when * accessing the PHY. **/ s32 e1000_acquire_phy(struct e1000_hw *hw) { if (hw->phy.ops.acquire) return hw->phy.ops.acquire(hw); return E1000_SUCCESS; } /** * e1000_read_kmrn_reg - Reads register using Kumeran interface * @hw: pointer to the HW structure * @offset: the register to read * @data: the location to store the 16-bit value read. * * Reads a register out of the Kumeran interface. Currently no func pointer * exists and all implementations are handled in the generic version of * this function. **/ s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) { return e1000_read_kmrn_reg_generic(hw, offset, data); } /** * e1000_write_kmrn_reg - Writes register using Kumeran interface * @hw: pointer to the HW structure * @offset: the register to write * @data: the value to write. * * Writes a register to the Kumeran interface. Currently no func pointer * exists and all implementations are handled in the generic version of * this function. **/ s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) { return e1000_write_kmrn_reg_generic(hw, offset, data); } /** * e1000_get_cable_length - Retrieves cable length estimation * @hw: pointer to the HW structure * * This function estimates the cable length and stores them in * hw->phy.min_length and hw->phy.max_length. This is a function pointer * entry point called by drivers. **/ s32 e1000_get_cable_length(struct e1000_hw *hw) { if (hw->phy.ops.get_cable_length) return hw->phy.ops.get_cable_length(hw); return E1000_SUCCESS; } /** * e1000_get_phy_info - Retrieves PHY information from registers * @hw: pointer to the HW structure * * This function gets some information from various PHY registers and * populates hw->phy values with it. This is a function pointer entry * point called by drivers. **/ s32 e1000_get_phy_info(struct e1000_hw *hw) { if (hw->phy.ops.get_info) return hw->phy.ops.get_info(hw); return E1000_SUCCESS; } /** * e1000_phy_hw_reset - Hard PHY reset * @hw: pointer to the HW structure * * Performs a hard PHY reset. This is a function pointer entry point called * by drivers. **/ s32 e1000_phy_hw_reset(struct e1000_hw *hw) { if (hw->phy.ops.reset) return hw->phy.ops.reset(hw); return E1000_SUCCESS; } /** * e1000_phy_commit - Soft PHY reset * @hw: pointer to the HW structure * * Performs a soft PHY reset on those that apply. This is a function pointer * entry point called by drivers. **/ s32 e1000_phy_commit(struct e1000_hw *hw) { if (hw->phy.ops.commit) return hw->phy.ops.commit(hw); return E1000_SUCCESS; } /** * e1000_set_d0_lplu_state - Sets low power link up state for D0 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D0 * and SmartSpeed is disabled when active is true, else clear lplu for D0 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. This is a function pointer entry point called by drivers. **/ s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) { if (hw->phy.ops.set_d0_lplu_state) return hw->phy.ops.set_d0_lplu_state(hw, active); return E1000_SUCCESS; } /** * e1000_set_d3_lplu_state - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. This is a function pointer entry point called by drivers. **/ s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) { if (hw->phy.ops.set_d3_lplu_state) return hw->phy.ops.set_d3_lplu_state(hw, active); return E1000_SUCCESS; } /** * e1000_read_mac_addr - Reads MAC address * @hw: pointer to the HW structure * * Reads the MAC address out of the adapter and stores it in the HW structure. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_mac_addr(struct e1000_hw *hw) { if (hw->mac.ops.read_mac_addr) return hw->mac.ops.read_mac_addr(hw); return e1000_read_mac_addr_generic(hw); } /** * e1000_read_pba_string - Read device part number string * @hw: pointer to the HW structure * @pba_num: pointer to device part number * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size) { return e1000_read_pba_string_generic(hw, pba_num, pba_num_size); } /** * e1000_read_pba_length - Read device part number string length * @hw: pointer to the HW structure * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number length from the EEPROM and * stores the value in pba_num. * Currently no func pointer exists and all implementations are handled in the * generic version of this function. **/ s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size) { return e1000_read_pba_length_generic(hw, pba_num_size); } /** * e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum * @hw: pointer to the HW structure * * Validates the NVM checksum is correct. This is a function pointer entry * point called by drivers. **/ s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) { if (hw->nvm.ops.validate) return hw->nvm.ops.validate(hw); return -E1000_ERR_CONFIG; } /** * e1000_update_nvm_checksum - Updates NVM (EEPROM) checksum * @hw: pointer to the HW structure * * Updates the NVM checksum. Currently no func pointer exists and all * implementations are handled in the generic version of this function. **/ s32 e1000_update_nvm_checksum(struct e1000_hw *hw) { if (hw->nvm.ops.update) return hw->nvm.ops.update(hw); return -E1000_ERR_CONFIG; } /** * e1000_reload_nvm - Reloads EEPROM * @hw: pointer to the HW structure * * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the * extended control register. **/ void e1000_reload_nvm(struct e1000_hw *hw) { if (hw->nvm.ops.reload) hw->nvm.ops.reload(hw); } /** * e1000_read_nvm - Reads NVM (EEPROM) * @hw: pointer to the HW structure * @offset: the word offset to read * @words: number of 16-bit words to read * @data: pointer to the properly sized buffer for the data. * * Reads 16-bit chunks of data from the NVM (EEPROM). This is a function * pointer entry point called by drivers. **/ s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { if (hw->nvm.ops.read) return hw->nvm.ops.read(hw, offset, words, data); return -E1000_ERR_CONFIG; } /** * e1000_write_nvm - Writes to NVM (EEPROM) * @hw: pointer to the HW structure * @offset: the word offset to read * @words: number of 16-bit words to write * @data: pointer to the properly sized buffer for the data. * * Writes 16-bit chunks of data to the NVM (EEPROM). This is a function * pointer entry point called by drivers. **/ s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { if (hw->nvm.ops.write) return hw->nvm.ops.write(hw, offset, words, data); return E1000_SUCCESS; } /** * e1000_write_8bit_ctrl_reg - Writes 8bit Control register * @hw: pointer to the HW structure * @reg: 32bit register offset * @offset: the register to write * @data: the value to write. * * Writes the PHY register at offset with the value in data. * This is a function pointer entry point called by drivers. **/ s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data) { return e1000_write_8bit_ctrl_reg_generic(hw, reg, offset, data); } /** * e1000_power_up_phy - Restores link in case of PHY power down * @hw: pointer to the HW structure * * The phy may be powered down to save power, to turn off link when the * driver is unloaded, or wake on lan is not enabled (among others). **/ void e1000_power_up_phy(struct e1000_hw *hw) { if (hw->phy.ops.power_up) hw->phy.ops.power_up(hw); e1000_setup_link(hw); } /** * e1000_power_down_phy - Power down PHY * @hw: pointer to the HW structure * * The phy may be powered down to save power, to turn off link when the * driver is unloaded, or wake on lan is not enabled (among others). **/ void e1000_power_down_phy(struct e1000_hw *hw) { if (hw->phy.ops.power_down) hw->phy.ops.power_down(hw); } /** * e1000_power_up_fiber_serdes_link - Power up serdes link * @hw: pointer to the HW structure * * Power on the optics and PCS. **/ void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw) { if (hw->mac.ops.power_up_serdes) hw->mac.ops.power_up_serdes(hw); } /** * e1000_shutdown_fiber_serdes_link - Remove link during power down * @hw: pointer to the HW structure * * Shutdown the optics and PCS on driver unload. **/ void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw) { if (hw->mac.ops.shutdown_serdes) hw->mac.ops.shutdown_serdes(hw); } /** * e1000_get_thermal_sensor_data - Gathers thermal sensor data * @hw: pointer to hardware structure * * Updates the temperatures in mac.thermal_sensor_data **/ s32 e1000_get_thermal_sensor_data(struct e1000_hw *hw) { if (hw->mac.ops.get_thermal_sensor_data) return hw->mac.ops.get_thermal_sensor_data(hw); return E1000_SUCCESS; } /** * e1000_init_thermal_sensor_thresh - Sets thermal sensor thresholds * @hw: pointer to hardware structure * * Sets the thermal sensor thresholds according to the NVM map **/ s32 e1000_init_thermal_sensor_thresh(struct e1000_hw *hw) { if (hw->mac.ops.init_thermal_sensor_thresh) return hw->mac.ops.init_thermal_sensor_thresh(hw); return E1000_SUCCESS; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_api.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_API_H_ #define _E1000_API_H_ #include "e1000_hw.h" extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); extern void e1000_rx_fifo_flush_82575(struct e1000_hw *hw); extern void e1000_init_function_pointers_vf(struct e1000_hw *hw); extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_init_function_pointers_i210(struct e1000_hw *hw); s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr); s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_init_mac_params(struct e1000_hw *hw); s32 e1000_init_nvm_params(struct e1000_hw *hw); s32 e1000_init_phy_params(struct e1000_hw *hw); s32 e1000_init_mbx_params(struct e1000_hw *hw); s32 e1000_get_bus_info(struct e1000_hw *hw); void e1000_clear_vfta(struct e1000_hw *hw); void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); s32 e1000_force_mac_fc(struct e1000_hw *hw); s32 e1000_check_for_link(struct e1000_hw *hw); s32 e1000_reset_hw(struct e1000_hw *hw); s32 e1000_init_hw(struct e1000_hw *hw); s32 e1000_setup_link(struct e1000_hw *hw); s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_disable_pcie_master(struct e1000_hw *hw); void e1000_config_collision_dist(struct e1000_hw *hw); void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); s32 e1000_setup_led(struct e1000_hw *hw); s32 e1000_cleanup_led(struct e1000_hw *hw); s32 e1000_check_reset_block(struct e1000_hw *hw); s32 e1000_blink_led(struct e1000_hw *hw); s32 e1000_led_on(struct e1000_hw *hw); s32 e1000_led_off(struct e1000_hw *hw); s32 e1000_id_led_init(struct e1000_hw *hw); void e1000_reset_adaptive(struct e1000_hw *hw); void e1000_update_adaptive(struct e1000_hw *hw); s32 e1000_get_cable_length(struct e1000_hw *hw); s32 e1000_validate_mdi_setting(struct e1000_hw *hw); s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_8bit_ctrl_reg(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); s32 e1000_get_phy_info(struct e1000_hw *hw); void e1000_release_phy(struct e1000_hw *hw); s32 e1000_acquire_phy(struct e1000_hw *hw); s32 e1000_phy_hw_reset(struct e1000_hw *hw); s32 e1000_phy_commit(struct e1000_hw *hw); void e1000_power_up_phy(struct e1000_hw *hw); void e1000_power_down_phy(struct e1000_hw *hw); s32 e1000_read_mac_addr(struct e1000_hw *hw); s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size); s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size); void e1000_reload_nvm(struct e1000_hw *hw); s32 e1000_update_nvm_checksum(struct e1000_hw *hw); s32 e1000_validate_nvm_checksum(struct e1000_hw *hw); s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); bool e1000_check_mng_mode(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); s32 e1000_mng_enable_host_if(struct e1000_hw *hw); s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum); s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); s32 e1000_get_thermal_sensor_data(struct e1000_hw *hw); s32 e1000_init_thermal_sensor_thresh(struct e1000_hw *hw); /* * TBI_ACCEPT macro definition: * * This macro requires: * adapter = a pointer to struct e1000_hw * status = the 8 bit status field of the Rx descriptor with EOP set * error = the 8 bit error field of the Rx descriptor with EOP set * length = the sum of all the length fields of the Rx descriptors that * make up the current frame * last_byte = the last byte of the frame DMAed by the hardware * max_frame_length = the maximum frame length we want to accept. * min_frame_length = the minimum frame length we want to accept. * * This macro is a conditional that should be used in the interrupt * handler's Rx processing routine when RxErrors have been detected. * * Typical use: * ... * if (TBI_ACCEPT) { * accept_frame = true; * e1000_tbi_adjust_stats(adapter, MacAddress); * frame_length--; * } else { * accept_frame = false; * } * ... */ /* The carrier extension symbol, as received by the NIC. */ #define CARRIER_EXTENSION 0x0F #define TBI_ACCEPT(a, status, errors, length, last_byte, \ min_frame_size, max_frame_size) \ (e1000_tbi_sbp_enabled_82543(a) && \ (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ ((last_byte) == CARRIER_EXTENSION) && \ (((status) & E1000_RXD_STAT_VP) ? \ (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \ ((length) <= (max_frame_size + 1))) : \ (((length) > min_frame_size) && \ ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) #ifndef E1000_MAX #define E1000_MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef E1000_DIVIDE_ROUND_UP #define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */ #endif #endif /* _E1000_API_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_defines.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_DEFINES_H_ #define _E1000_DEFINES_H_ /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 /* Definitions for power management and wakeup registers */ /* Wake Up Control */ #define E1000_WUC_APME 0x00000001 /* APM Enable */ #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ #define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ #define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ /* Wake Up Filter Control */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ #define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ #define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ /* Wake Up Status */ #define E1000_WUS_LNKC E1000_WUFC_LNKC #define E1000_WUS_MAG E1000_WUFC_MAG #define E1000_WUS_EX E1000_WUFC_EX #define E1000_WUS_MC E1000_WUFC_MC #define E1000_WUS_BC E1000_WUFC_BC /* Extended Device Control */ #define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* SW Definable Pin 4 data */ #define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* SW Definable Pin 6 data */ #define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* SW Definable Pin 3 data */ #define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ #define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ /* Physical Func Reset Done Indication */ #define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ #define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clk Gating */ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 /* Offset of the link mode field in Ctrl Ext register */ #define E1000_CTRL_EXT_LINK_MODE_OFFSET 22 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 #define E1000_CTRL_EXT_EIAME 0x01000000 #define E1000_CTRL_EXT_IRCA 0x00000001 #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_I2CCMD_REG_ADDR_SHIFT 16 #define E1000_I2CCMD_PHY_ADDR_SHIFT 24 #define E1000_I2CCMD_OPCODE_READ 0x08000000 #define E1000_I2CCMD_OPCODE_WRITE 0x00000000 #define E1000_I2CCMD_READY 0x20000000 #define E1000_I2CCMD_ERROR 0x80000000 #define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a)) #define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a)) #define E1000_MAX_SGMII_PHY_REG_ADDR 255 #define E1000_I2CCMD_PHY_TIMEOUT 200 #define E1000_IVAR_VALID 0x80 #define E1000_GPIE_NSICR 0x00000001 #define E1000_GPIE_MSIX_MODE 0x00000010 #define E1000_GPIE_EIAME 0x40000000 #define E1000_GPIE_PBA 0x80000000 /* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ #define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ #define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ #define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ #define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ #define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ #define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ #define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ #define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ #define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ #define E1000_RXDEXT_STATERR_LB 0x00040000 #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 #define E1000_RXDEXT_STATERR_SEQ 0x04000000 #define E1000_RXDEXT_STATERR_CXE 0x10000000 #define E1000_RXDEXT_STATERR_TCPE 0x20000000 #define E1000_RXDEXT_STATERR_IPE 0x40000000 #define E1000_RXDEXT_STATERR_RXE 0x80000000 /* mask to determine if packets should be dropped due to frame errors */ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ E1000_RXD_ERR_CE | \ E1000_RXD_ERR_SE | \ E1000_RXD_ERR_SEQ | \ E1000_RXD_ERR_CXE | \ E1000_RXD_ERR_RXE) /* Same mask, but for extended and packet split descriptors */ #define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ E1000_RXDEXT_STATERR_CE | \ E1000_RXDEXT_STATERR_SE | \ E1000_RXDEXT_STATERR_SEQ | \ E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) #define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 #define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 /* Management Control */ #define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ #define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ /* Enable MAC address filtering */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MNG packets to host memory */ #define E1000_MANC_EN_MNG2HOST 0x00200000 #define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */ #define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */ #define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */ #define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */ /* Receive Control */ #define E1000_RCTL_RST 0x00000001 /* Software reset */ #define E1000_RCTL_EN 0x00000002 /* enable */ #define E1000_RCTL_SBP 0x00000004 /* store bad packet */ #define E1000_RCTL_UPE 0x00000008 /* unicast promisc enable */ #define E1000_RCTL_MPE 0x00000010 /* multicast promisc enable */ #define E1000_RCTL_LPE 0x00000020 /* long packet enable */ #define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ #define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ #define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ #define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */ #define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */ #define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ #define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */ #define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */ #define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */ #define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ #define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ #define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ #define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ #define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ /* Use byte values for the following shift parameters * Usage: * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & * E1000_PSRCTL_BSIZE0_MASK) | * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & * E1000_PSRCTL_BSIZE1_MASK) | * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & * E1000_PSRCTL_BSIZE2_MASK) | * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; * E1000_PSRCTL_BSIZE3_MASK)) * where value0 = [128..16256], default=256 * value1 = [1024..64512], default=4096 * value2 = [0..64512], default=4096 * value3 = [0..64512], default=0 */ #define E1000_PSRCTL_BSIZE0_MASK 0x0000007F #define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 #define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 #define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 #define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ #define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ #define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ #define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ /* SWFW_SYNC Definitions */ #define E1000_SWFW_EEP_SM 0x01 #define E1000_SWFW_PHY0_SM 0x02 #define E1000_SWFW_PHY1_SM 0x04 #define E1000_SWFW_CSR_SM 0x08 #define E1000_SWFW_PHY2_SM 0x20 #define E1000_SWFW_PHY3_SM 0x40 #define E1000_SWFW_SW_MNG_SM 0x400 /* Device Control */ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ #define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ #define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */ #define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ #define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ #define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ #define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ #define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ #define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ #define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ #define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ #define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ #define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ #define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ #define E1000_CTRL_RST 0x04000000 /* Global reset */ #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ #define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ #define E1000_CONNSW_ENRGSRC 0x4 #define E1000_CONNSW_PHYSD 0x400 #define E1000_CONNSW_PHY_PDN 0x800 #define E1000_CONNSW_SERDESD 0x200 #define E1000_CONNSW_AUTOSENSE_CONF 0x2 #define E1000_CONNSW_AUTOSENSE_EN 0x1 #define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 #define E1000_PCS_LCTL_FSV_100 2 #define E1000_PCS_LCTL_FSV_1000 4 #define E1000_PCS_LCTL_FDV_FULL 8 #define E1000_PCS_LCTL_FSD 0x10 #define E1000_PCS_LCTL_FORCE_LINK 0x20 #define E1000_PCS_LCTL_FORCE_FCTRL 0x80 #define E1000_PCS_LCTL_AN_ENABLE 0x10000 #define E1000_PCS_LCTL_AN_RESTART 0x20000 #define E1000_PCS_LCTL_AN_TIMEOUT 0x40000 #define E1000_ENABLE_SERDES_LOOPBACK 0x0410 #define E1000_PCS_LSTS_LINK_OK 1 #define E1000_PCS_LSTS_SPEED_100 2 #define E1000_PCS_LSTS_SPEED_1000 4 #define E1000_PCS_LSTS_DUPLEX_FULL 8 #define E1000_PCS_LSTS_SYNK_OK 0x10 #define E1000_PCS_LSTS_AN_COMPLETE 0x10000 /* Device Status */ #define E1000_STATUS_FD 0x00000001 /* Duplex 0=half 1=full */ #define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ #define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ #define E1000_STATUS_FUNC_SHIFT 2 #define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ #define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ #define E1000_STATUS_SPEED_MASK 0x000000C0 #define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Compltn by NVM */ #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ #define E1000_STATUS_2P5_SKU 0x00001000 /* Val of 2.5GBE SKU strap */ #define E1000_STATUS_2P5_SKU_OVER 0x00002000 /* Val of 2.5GBE SKU Over */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 #define SPEED_2500 2500 #define HALF_DUPLEX 1 #define FULL_DUPLEX 2 #define ADVERTISE_10_HALF 0x0001 #define ADVERTISE_10_FULL 0x0002 #define ADVERTISE_100_HALF 0x0004 #define ADVERTISE_100_FULL 0x0008 #define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ #define ADVERTISE_1000_FULL 0x0020 /* 1000/H is not supported, nor spec-compliant. */ #define E1000_ALL_SPEED_DUPLEX ( \ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ADVERTISE_100_FULL | ADVERTISE_1000_FULL) #define E1000_ALL_NOT_GIG ( \ ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ ADVERTISE_100_FULL) #define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) #define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) #define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 #define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 #define E1000_LEDCTL_MODE_LED_ON 0xE #define E1000_LEDCTL_MODE_LED_OFF 0xF /* Transmit Descriptor bit definitions */ #define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ #define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ #define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ #define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ #define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ #define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ #define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ #define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ #define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ #define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ #define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ #define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ #define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ #define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ #define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ #define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ #define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ #define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ /* Transmit Control */ #define E1000_TCTL_EN 0x00000002 /* enable Tx */ #define E1000_TCTL_PSP 0x00000008 /* pad short packets */ #define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ #define E1000_TCTL_COLD 0x003ff000 /* collision distance */ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ /* Transmit Arbitration Count */ #define E1000_TARC0_ENABLE 0x00000400 /* Enable Tx Queue 0 */ /* SerDes Control */ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 #define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 /* Receive Checksum Control */ #define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ #define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ #define E1000_RFCTL_NFSW_DIS 0x00000040 #define E1000_RFCTL_NFSR_DIS 0x00000080 #define E1000_RFCTL_ACK_DIS 0x00001000 #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 #define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 #define E1000_RFCTL_LEF 0x00040000 /* Collision related configuration parameters */ #define E1000_COLLISION_THRESHOLD 15 #define E1000_CT_SHIFT 4 #define E1000_COLLISION_DISTANCE 63 #define E1000_COLD_SHIFT 12 /* Default values for the transmit IPG register */ #define DEFAULT_82543_TIPG_IPGT_FIBER 9 #define DEFAULT_82543_TIPG_IPGT_COPPER 8 #define E1000_TIPG_IPGT_MASK 0x000003FF #define DEFAULT_82543_TIPG_IPGR1 8 #define E1000_TIPG_IPGR1_SHIFT 10 #define DEFAULT_82543_TIPG_IPGR2 6 #define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 #define E1000_TIPG_IPGR2_SHIFT 20 /* Ethertype field values */ #define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ #define ETHERNET_FCS_SIZE 4 #define MAX_JUMBO_FRAME_SIZE 0x3F00 /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 #define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 #define E1000_PHY_CTRL_D0A_LPLU 0x00000002 #define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 #define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 #define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 #define E1000_KABGTXD_BGSQLBIAS 0x00050000 /* PBA constants */ #define E1000_PBA_8K 0x0008 /* 8KB */ #define E1000_PBA_10K 0x000A /* 10KB */ #define E1000_PBA_12K 0x000C /* 12KB */ #define E1000_PBA_14K 0x000E /* 14KB */ #define E1000_PBA_16K 0x0010 /* 16KB */ #define E1000_PBA_18K 0x0012 #define E1000_PBA_20K 0x0014 #define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 #define E1000_PBA_26K 0x001A #define E1000_PBA_30K 0x001E #define E1000_PBA_32K 0x0020 #define E1000_PBA_34K 0x0022 #define E1000_PBA_35K 0x0023 #define E1000_PBA_38K 0x0026 #define E1000_PBA_40K 0x0028 #define E1000_PBA_48K 0x0030 /* 48KB */ #define E1000_PBA_64K 0x0040 /* 64KB */ #define E1000_PBA_RXA_MASK 0xFFFF #define E1000_PBS_16K E1000_PBA_16K #define IFS_MAX 80 #define IFS_MIN 40 #define IFS_RATIO 4 #define IFS_STEP 10 #define MIN_NUM_XMITS 1000 /* SW Semaphore Register */ #define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ #define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ /* Interrupt Cause Read */ #define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ #define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ #define E1000_ICR_LSC 0x00000004 /* Link Status Change */ #define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ #define E1000_ICR_RXO 0x00000040 /* Rx overrun */ #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ #define E1000_ICR_VMMB 0x00000100 /* VM MB event */ #define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ #define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ #define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ #define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ #define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ #define E1000_ICR_TXD_LOW 0x00008000 #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 #define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ #define E1000_ICR_FER 0x00400000 /* Fatal Error */ #define E1000_ICR_THS 0x00800000 /* ICR.THS: Thermal Sensor Event*/ #define E1000_ICR_MDDET 0x10000000 /* Malicious Driver Detect */ /* Extended Interrupt Cause Read */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ #define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ #define E1000_EICR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ #define E1000_EICR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ #define E1000_EICR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ #define E1000_EICR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ #define E1000_EICR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ #define E1000_EICR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ #define E1000_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define E1000_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ /* TCP Timer */ #define E1000_TCPTIMER_KS 0x00000100 /* KickStart */ #define E1000_TCPTIMER_COUNT_ENABLE 0x00000200 /* Count Enable */ #define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ #define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ /* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXT0 = Receiver Timer Interrupt (ring 0) * o TXDW = Transmit Descriptor Written Back * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) * o RXSEQ = Receive Sequence Error * o LSC = Link Status Change */ #define IMS_ENABLE_MASK ( \ E1000_IMS_RXT0 | \ E1000_IMS_TXDW | \ E1000_IMS_RXDMT0 | \ E1000_IMS_RXSEQ | \ E1000_IMS_LSC) /* Interrupt Mask Set */ #define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */ #define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ #define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */ #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ #define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW #define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ #define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */ #define E1000_IMS_THS E1000_ICR_THS /* ICR.TS: Thermal Sensor Event*/ #define E1000_IMS_MDDET E1000_ICR_MDDET /* Malicious Driver Detect */ /* Extended Interrupt Mask Set */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ #define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ #define E1000_EIMS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ #define E1000_EIMS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ #define E1000_EIMS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ #define E1000_EIMS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ #define E1000_EIMS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ #define E1000_EIMS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ #define E1000_EIMS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ #define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ /* Extended Interrupt Cause Set */ #define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ #define E1000_EICS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */ #define E1000_EICS_RX_QUEUE2 E1000_EICR_RX_QUEUE2 /* Rx Queue 2 Interrupt */ #define E1000_EICS_RX_QUEUE3 E1000_EICR_RX_QUEUE3 /* Rx Queue 3 Interrupt */ #define E1000_EICS_TX_QUEUE0 E1000_EICR_TX_QUEUE0 /* Tx Queue 0 Interrupt */ #define E1000_EICS_TX_QUEUE1 E1000_EICR_TX_QUEUE1 /* Tx Queue 1 Interrupt */ #define E1000_EICS_TX_QUEUE2 E1000_EICR_TX_QUEUE2 /* Tx Queue 2 Interrupt */ #define E1000_EICS_TX_QUEUE3 E1000_EICR_TX_QUEUE3 /* Tx Queue 3 Interrupt */ #define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */ #define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ #define E1000_EITR_ITR_INT_MASK 0x0000FFFF /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ #define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */ #define E1000_EITR_INTERVAL 0x00007FFC /* Transmit Descriptor Control */ #define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ #define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ /* Enable the counting of descriptors still to be processed. */ #define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Flow Control Constants */ #define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 #define FLOW_CONTROL_TYPE 0x8808 /* 802.1q VLAN Packet Size */ #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ /* Receive Address * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * Technically, we have 16 spots. However, we reserve one of these spots * (RAR[15]) for our directed address used by controllers with * manageability enabled, allowing us room for 15 multicast addresses. */ #define E1000_RAR_ENTRIES 15 #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ #define E1000_RAL_MAC_ADDR_LEN 4 #define E1000_RAH_MAC_ADDR_LEN 2 #define E1000_RAH_QUEUE_MASK_82575 0x000C0000 #define E1000_RAH_POOL_1 0x00040000 /* Error Codes */ #define E1000_SUCCESS 0 #define E1000_ERR_NVM 1 #define E1000_ERR_PHY 2 #define E1000_ERR_CONFIG 3 #define E1000_ERR_PARAM 4 #define E1000_ERR_MAC_INIT 5 #define E1000_ERR_PHY_TYPE 6 #define E1000_ERR_RESET 9 #define E1000_ERR_MASTER_REQUESTS_PENDING 10 #define E1000_ERR_HOST_INTERFACE_COMMAND 11 #define E1000_BLK_PHY_RESET 12 #define E1000_ERR_SWFW_SYNC 13 #define E1000_NOT_IMPLEMENTED 14 #define E1000_ERR_MBX 15 #define E1000_ERR_INVALID_ARGUMENT 16 #define E1000_ERR_NO_SPACE 17 #define E1000_ERR_NVM_PBA_SECTION 18 #define E1000_ERR_I2C 19 #define E1000_ERR_INVM_VALUE_NOT_FOUND 20 /* Loop limit on how long we wait for auto-negotiation to complete */ #define FIBER_LINK_UP_LIMIT 50 #define COPPER_LINK_UP_LIMIT 10 #define PHY_AUTO_NEG_LIMIT 45 #define PHY_FORCE_LIMIT 20 /* Number of 100 microseconds we wait for PCI Express master disable */ #define MASTER_DISABLE_TIMEOUT 800 /* Number of milliseconds we wait for PHY configuration done after MAC reset */ #define PHY_CFG_TIMEOUT 100 /* Number of 2 milliseconds we wait for acquiring MDIO ownership. */ #define MDIO_OWNERSHIP_TIMEOUT 10 /* Number of milliseconds for NVM auto read done after MAC reset. */ #define AUTO_READ_DONE_TIMEOUT 10 /* Flow Control */ #define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ #define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ #define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ #define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ #define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ #define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ /* Receive Configuration Word */ #define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ #define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ #define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ #define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 #define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 #define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 #define E1000_TSYNCRXCTL_TYPE_ALL 0x08 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ #define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 #define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01 #define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE 0x02 #define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03 #define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04 #define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK 0x00000F00 #define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE 0x0000 #define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE 0x0100 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE 0x0200 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE 0x0300 #define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE 0x0800 #define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE 0x0900 #define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE 0x0A00 #define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE 0x0B00 #define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE 0x0C00 #define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 #define E1000_TIMINCA_16NS_SHIFT 24 #define E1000_TIMINCA_INCPERIOD_SHIFT 24 #define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF #define E1000_TSICR_TXTS 0x00000002 #define E1000_TSIM_TXTS 0x00000002 /* TUPLE Filtering Configuration */ #define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */ #define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */ #define E1000_TTQF_PROTOCOL_MASK 0xFF /* TTQF Protocol Mask */ /* TTQF TCP Bit, shift with E1000_TTQF_PROTOCOL SHIFT */ #define E1000_TTQF_PROTOCOL_TCP 0x0 /* TTQF UDP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ #define E1000_TTQF_PROTOCOL_UDP 0x1 /* TTQF SCTP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ #define E1000_TTQF_PROTOCOL_SCTP 0x2 #define E1000_TTQF_PROTOCOL_SHIFT 5 /* TTQF Protocol Shift */ #define E1000_TTQF_QUEUE_SHIFT 16 /* TTQF Queue Shfit */ #define E1000_TTQF_RX_QUEUE_MASK 0x70000 /* TTQF Queue Mask */ #define E1000_TTQF_MASK_ENABLE 0x10000000 /* TTQF Mask Enable Bit */ #define E1000_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */ #define E1000_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */ #define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */ #define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */ #define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */ #define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */ #define E1000_MDICNFG_PHY_MASK 0x03E00000 #define E1000_MDICNFG_PHY_SHIFT 21 #define E1000_MEDIA_PORT_COPPER 1 #define E1000_MEDIA_PORT_OTHER 2 #define E1000_M88E1112_AUTO_COPPER_SGMII 0x2 #define E1000_M88E1112_AUTO_COPPER_BASEX 0x3 #define E1000_M88E1112_STATUS_LINK 0x0004 /* Interface Link Bit */ #define E1000_M88E1112_MAC_CTRL_1 0x10 #define E1000_M88E1112_MAC_CTRL_1_MODE_MASK 0x0380 /* Mode Select */ #define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT 7 #define E1000_M88E1112_PAGE_ADDR 0x16 #define E1000_M88E1112_STATUS 0x01 #define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */ #define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */ #define E1000_THSTAT_HIGH_EVENT 0x00002000 /* High thermal threshold */ #define E1000_THSTAT_PWR_DOWN 0x00000001 /* Power Down Event */ #define E1000_THSTAT_LINK_THROTTLE 0x00000002 /* Link Spd Throttle Event */ /* I350 EEE defines */ #define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */ #define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */ #define E1000_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */ #define E1000_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */ #define E1000_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */ /* EEE status */ #define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ #define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */ #define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */ #define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */ #define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */ #define E1000_M88E1543_EEE_CTRL_1 0x0 #define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */ #define E1000_EEE_ADV_DEV_I354 7 #define E1000_EEE_ADV_ADDR_I354 60 #define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */ #define E1000_EEE_ADV_1000_SUPPORTED (1 << 2) /* 1000BaseT EEE Supported */ #define E1000_PCS_STATUS_DEV_I354 3 #define E1000_PCS_STATUS_ADDR_I354 1 #define E1000_PCS_STATUS_RX_LPI_RCVD 0x0400 #define E1000_PCS_STATUS_TX_LPI_RCVD 0x0800 #define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ #define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */ #define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */ /* PCI Express Control */ #define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 #define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 #define E1000_GCR_TXD_NO_SNOOP 0x00000008 #define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 #define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 #define E1000_GCR_CMPL_TMOUT_MASK 0x0000F000 #define E1000_GCR_CMPL_TMOUT_10ms 0x00001000 #define E1000_GCR_CMPL_TMOUT_RESEND 0x00010000 #define E1000_GCR_CAP_VER2 0x00040000 #define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ E1000_GCR_RXDSCW_NO_SNOOP | \ E1000_GCR_RXDSCR_NO_SNOOP | \ E1000_GCR_TXD_NO_SNOOP | \ E1000_GCR_TXDSCW_NO_SNOOP | \ E1000_GCR_TXDSCR_NO_SNOOP) #define E1000_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */ /* mPHY address control and data registers */ #define E1000_MPHY_ADDR_CTL 0x0024 /* Address Control Reg */ #define E1000_MPHY_ADDR_CTL_OFFSET_MASK 0xFFFF0000 #define E1000_MPHY_DATA 0x0E10 /* Data Register */ /* AFE CSR Offset for PCS CLK */ #define E1000_MPHY_PCS_CLK_REG_OFFSET 0x0004 /* Override for near end digital loopback. */ #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10 /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ #define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ #define MII_CR_POWER_DOWN 0x0800 /* Power down */ #define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ #define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ #define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ #define MII_CR_SPEED_1000 0x0040 #define MII_CR_SPEED_100 0x2000 #define MII_CR_SPEED_10 0x0000 /* PHY Status Register */ #define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ #define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ #define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ #define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ #define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ #define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ #define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ #define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ #define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ #define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ #define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ #define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ #define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ #define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ #define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ /* Autoneg Advertisement Register */ #define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ #define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ #define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ #define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ #define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ #define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ #define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ #define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ #define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ #define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ /* Link Partner Ability Register (Base Page) */ #define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ #define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP 10T Half Dplx Capable */ #define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP 10T Full Dplx Capable */ #define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP 100TX Half Dplx Capable */ #define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP 100TX Full Dplx Capable */ #define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ #define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ #define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asym Pause Direction bit */ #define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP detected Remote Fault */ #define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP rx'd link code word */ #define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ /* Autoneg Expansion Register */ #define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ #define NWAY_ER_PAGE_RXD 0x0002 /* LP 10T Half Dplx Capable */ #define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP 10T Full Dplx Capable */ #define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP 100TX Half Dplx Capable */ #define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP 100TX Full Dplx Capable */ /* 1000BASE-T Control Register */ #define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ #define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ #define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ /* 1=Repeater/switch device port 0=DTE device */ #define CR_1000T_REPEATER_DTE 0x0400 /* 1=Configure PHY as Master 0=Configure PHY as Slave */ #define CR_1000T_MS_VALUE 0x0800 /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ #define CR_1000T_MS_ENABLE 0x1000 #define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ #define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ #define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ #define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ #define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ /* 1000BASE-T Status Register */ #define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle err since last rd */ #define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asym pause direction bit */ #define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ #define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ #define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ #define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ #define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local Tx Master, 0=Slave */ #define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ #define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 /* PHY 1000 MII Register/Bit Definitions */ /* PHY Registers defined by IEEE */ #define PHY_CONTROL 0x00 /* Control Register */ #define PHY_STATUS 0x01 /* Status Register */ #define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ #define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ #define PHY_NEXT_PAGE_TX 0x07 /* Next Page Tx */ #define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ #define PHY_CONTROL_LB 0x4000 /* PHY Loopback bit */ /* NVM Control */ #define E1000_EECD_SK 0x00000001 /* NVM Clock */ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ #define E1000_EECD_DI 0x00000004 /* NVM Data In */ #define E1000_EECD_DO 0x00000008 /* NVM Data Out */ #define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ #define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ #define E1000_EECD_PRES 0x00000100 /* NVM Present */ #define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */ #define E1000_EECD_BLOCKED 0x00008000 /* Bit banging access blocked flag */ #define E1000_EECD_ABORT 0x00010000 /* NVM operation aborted flag */ #define E1000_EECD_TIMEOUT 0x00020000 /* NVM read operation timeout flag */ #define E1000_EECD_ERROR_CLR 0x00040000 /* NVM error status clear bit */ /* NVM Addressing bits based on type 0=small, 1=large */ #define E1000_EECD_ADDR_BITS 0x00000400 #define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ #define E1000_EECD_SIZE_EX_SHIFT 11 #define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ #define E1000_EECD_AUPDEN 0x00100000 /* Ena Auto FLASH update */ #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) #define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done */ #define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */ #define E1000_EECD_SEC1VAL_I210 0x02000000 /* Sector One Valid */ #define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ #define E1000_I210_FIFO_SEL_RX 0x00 #define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i)) #define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) #define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 #define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 #define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */ /* Secure FLASH mode requires removing MSb */ #define E1000_I210_FW_PTR_MASK 0x7FFF /* Firmware code revision field word offset*/ #define E1000_I210_FW_VER_OFFSET 328 #define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ #define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ #define E1000_NVM_RW_REG_START 1 /* Start operation */ #define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ #define E1000_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ #define E1000_NVM_POLL_READ 0 /* Flag for polling for read complete */ #define E1000_FLASH_UPDATES 2000 /* NVM Word Offsets */ #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_VERSION 0x0005 #define E1000_I210_NVM_FW_MODULE_PTR 0x0010 #define E1000_I350_NVM_FW_MODULE_PTR 0x0051 #define NVM_FUTURE_INIT_WORD1 0x0019 #define NVM_ETRACK_WORD 0x0042 #define NVM_ETRACK_HIWORD 0x0043 #define NVM_COMB_VER_OFF 0x0083 #define NVM_COMB_VER_PTR 0x003d /* NVM version defines */ #define NVM_MAJOR_MASK 0xF000 #define NVM_MINOR_MASK 0x0FF0 #define NVM_IMAGE_ID_MASK 0x000F #define NVM_COMB_VER_MASK 0x00FF #define NVM_MAJOR_SHIFT 12 #define NVM_MINOR_SHIFT 4 #define NVM_COMB_VER_SHFT 8 #define NVM_VER_INVALID 0xFFFF #define NVM_ETRACK_SHIFT 16 #define NVM_ETRACK_VALID 0x8000 #define NVM_NEW_DEC_MASK 0x0F00 #define NVM_HEX_CONV 16 #define NVM_HEX_TENS 10 /* FW version defines */ /* Offset of "Loader patch ptr" in Firmware Header */ #define E1000_I350_NVM_FW_LOADER_PATCH_PTR_OFFSET 0x01 /* Patch generation hour & minutes */ #define E1000_I350_NVM_FW_VER_WORD1_OFFSET 0x04 /* Patch generation month & day */ #define E1000_I350_NVM_FW_VER_WORD2_OFFSET 0x05 /* Patch generation year */ #define E1000_I350_NVM_FW_VER_WORD3_OFFSET 0x06 /* Patch major & minor numbers */ #define E1000_I350_NVM_FW_VER_WORD4_OFFSET 0x07 #define NVM_MAC_ADDR 0x0000 #define NVM_SUB_DEV_ID 0x000B #define NVM_SUB_VEN_ID 0x000C #define NVM_DEV_ID 0x000D #define NVM_VEN_ID 0x000E #define NVM_INIT_CTRL_2 0x000F #define NVM_INIT_CTRL_4 0x0013 #define NVM_LED_1_CFG 0x001C #define NVM_LED_0_2_CFG 0x001F #define NVM_COMPAT_VALID_CSUM 0x0001 #define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 #define NVM_ETS_CFG 0x003E #define NVM_ETS_LTHRES_DELTA_MASK 0x07C0 #define NVM_ETS_LTHRES_DELTA_SHIFT 6 #define NVM_ETS_TYPE_MASK 0x0038 #define NVM_ETS_TYPE_SHIFT 3 #define NVM_ETS_TYPE_EMC 0x000 #define NVM_ETS_NUM_SENSORS_MASK 0x0007 #define NVM_ETS_DATA_LOC_MASK 0x3C00 #define NVM_ETS_DATA_LOC_SHIFT 10 #define NVM_ETS_DATA_INDEX_MASK 0x0300 #define NVM_ETS_DATA_INDEX_SHIFT 8 #define NVM_ETS_DATA_HTHRESH_MASK 0x00FF #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_3GIO_3 0x001A #define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020 #define NVM_INIT_CONTROL3_PORT_A 0x0024 #define NVM_CFG 0x0012 #define NVM_ALT_MAC_ADDR_PTR 0x0037 #define NVM_CHECKSUM_REG 0x003F #define NVM_COMPATIBILITY_REG_3 0x0003 #define NVM_COMPATIBILITY_BIT_MASK 0x8000 #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ #define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */ #define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */ #define NVM_82580_LAN_FUNC_OFFSET(a) ((a) ? (0x40 + (0x40 * (a))) : 0) /* Mask bits for fields in Word 0x24 of the NVM */ #define NVM_WORD24_COM_MDIO 0x0008 /* MDIO interface shared */ #define NVM_WORD24_EXT_MDIO 0x0004 /* MDIO accesses routed extrnl */ /* Offset of Link Mode bits for 82575/82576 */ #define NVM_WORD24_LNK_MODE_OFFSET 8 /* Offset of Link Mode bits for 82580 up */ #define NVM_WORD24_82580_LNK_MODE_OFFSET 4 /* Mask bits for fields in Word 0x0f of the NVM */ #define NVM_WORD0F_PAUSE_MASK 0x3000 #define NVM_WORD0F_PAUSE 0x1000 #define NVM_WORD0F_ASM_DIR 0x2000 /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C /* Mask bits for fields in Word 0x03 of the EEPROM */ #define NVM_COMPAT_LOM 0x0800 /* length of string needed to store PBA number */ #define E1000_PBANUM_LENGTH 11 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA /* PBA (printed board assembly) number words */ #define NVM_PBA_OFFSET_0 8 #define NVM_PBA_OFFSET_1 9 #define NVM_PBA_PTR_GUARD 0xFAFA #define NVM_RESERVED_WORD 0xFFFF #define NVM_WORD_SIZE_BASE_SHIFT 6 /* NVM Commands - SPI */ #define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ #define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ #define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ #define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ #define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ #define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ /* SPI NVM Status Register */ #define NVM_STATUS_RDY_SPI 0x01 /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 #define ID_LED_RESERVED_FFFF 0xFFFF #define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ (ID_LED_OFF1_OFF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) #define ID_LED_DEF1_DEF2 0x1 #define ID_LED_DEF1_ON2 0x2 #define ID_LED_DEF1_OFF2 0x3 #define ID_LED_ON1_DEF2 0x4 #define ID_LED_ON1_ON2 0x5 #define ID_LED_ON1_OFF2 0x6 #define ID_LED_OFF1_DEF2 0x7 #define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_OFF2 0x9 #define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF #define IGP_ACTIVITY_LED_ENABLE 0x0300 #define IGP_LED3_MODE 0x07000000 /* PCI/PCI-X/PCI-EX Config space */ #define PCI_HEADER_TYPE_REGISTER 0x0E #define PCIE_LINK_STATUS 0x12 #define PCIE_DEVICE_CONTROL2 0x28 #define PCI_HEADER_TYPE_MULTIFUNC 0x80 #define PCIE_LINK_WIDTH_MASK 0x3F0 #define PCIE_LINK_WIDTH_SHIFT 4 #define PCIE_LINK_SPEED_MASK 0x0F #define PCIE_LINK_SPEED_2500 0x01 #define PCIE_LINK_SPEED_5000 0x02 #define PCIE_DEVICE_CONTROL2_16ms 0x0005 #ifndef ETH_ADDR_LEN #define ETH_ADDR_LEN 6 #endif #define PHY_REVISION_MASK 0xFFFFFFF0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_MULTI_PAGE_REG 0xF /* Bit definitions for valid PHY IDs. * I = Integrated * E = External */ #define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 #define IGP01E1000_I_PHY_ID 0x02A80380 #define M88E1111_I_PHY_ID 0x01410CC0 #define M88E1543_E_PHY_ID 0x01410EA0 #define M88E1112_E_PHY_ID 0x01410C90 #define I347AT4_E_PHY_ID 0x01410DC0 #define M88E1340M_E_PHY_ID 0x01410DF0 #define GG82563_E_PHY_ID 0x01410CA0 #define IGP03E1000_E_PHY_ID 0x02A80390 #define IFE_E_PHY_ID 0x02A80330 #define IFE_PLUS_E_PHY_ID 0x02A80320 #define IFE_C_E_PHY_ID 0x02A80310 #define I82580_I_PHY_ID 0x015403A0 #define I350_I_PHY_ID 0x015403B0 #define I210_I_PHY_ID 0x01410C00 #define IGP04E1000_E_PHY_ID 0x02A80391 #define M88_VENDOR 0x0141 /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Reg */ #define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Reg */ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Cntrl */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ #define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for pg number setting */ #define M88E1000_PHY_GEN_CONTROL 0x1E /* meaning depends on reg 29 */ /* M88E1000 PHY Specific Control Register */ #define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */ /* MDI Crossover Mode bits 6:5 Manual MDI configuration */ #define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ #define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* Auto crossover enabled all speeds */ #define M88E1000_PSCR_AUTO_X_MODE 0x0060 #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */ /* M88E1000 PHY Specific Status Register */ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ #define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ /* 0 = <50M * 1 = 50-80M * 2 = 80-110M * 3 = 110-140M * 4 = >140M */ #define M88E1000_PSSR_CABLE_LENGTH 0x0380 #define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ #define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ #define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 /* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 /* Number of times we will attempt to autonegotiate before downshifting if we * are the slave */ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ /* Intel I347AT4 Registers */ #define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */ #define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */ #define I347AT4_PAGE_SELECT 0x16 /* I347AT4 Extended PHY Specific Control Register */ /* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800 #define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000 #define I347AT4_PSCR_DOWNSHIFT_1X 0x0000 #define I347AT4_PSCR_DOWNSHIFT_2X 0x1000 #define I347AT4_PSCR_DOWNSHIFT_3X 0x2000 #define I347AT4_PSCR_DOWNSHIFT_4X 0x3000 #define I347AT4_PSCR_DOWNSHIFT_5X 0x4000 #define I347AT4_PSCR_DOWNSHIFT_6X 0x5000 #define I347AT4_PSCR_DOWNSHIFT_7X 0x6000 #define I347AT4_PSCR_DOWNSHIFT_8X 0x7000 /* I347AT4 PHY Cable Diagnostics Control */ #define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */ /* M88E1112 only registers */ #define M88E1112_VCT_DSP_DISTANCE 0x001A /* M88EC018 Rev 2 specific DownShift settings */ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 /* Bits... * 15-5: page * 4-0: register offset */ #define GG82563_PAGE_SHIFT 5 #define GG82563_REG(page, reg) \ (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) #define GG82563_MIN_ALT_REG 30 /* GG82563 Specific Registers */ #define GG82563_PHY_SPEC_CTRL GG82563_REG(0, 16) /* PHY Spec Cntrl */ #define GG82563_PHY_PAGE_SELECT GG82563_REG(0, 22) /* Page Select */ #define GG82563_PHY_SPEC_CTRL_2 GG82563_REG(0, 26) /* PHY Spec Cntrl2 */ #define GG82563_PHY_PAGE_SELECT_ALT GG82563_REG(0, 29) /* Alt Page Select */ /* MAC Specific Control Register */ #define GG82563_PHY_MAC_SPEC_CTRL GG82563_REG(2, 21) #define GG82563_PHY_DSP_DISTANCE GG82563_REG(5, 26) /* DSP Distance */ /* Page 193 - Port Control Registers */ /* Kumeran Mode Control */ #define GG82563_PHY_KMRN_MODE_CTRL GG82563_REG(193, 16) #define GG82563_PHY_PWR_MGMT_CTRL GG82563_REG(193, 20) /* Pwr Mgt Ctrl */ /* Page 194 - KMRN Registers */ #define GG82563_PHY_INBAND_CTRL GG82563_REG(194, 18) /* Inband Ctrl */ /* MDI Control */ #define E1000_MDIC_REG_MASK 0x001F0000 #define E1000_MDIC_REG_SHIFT 16 #define E1000_MDIC_PHY_MASK 0x03E00000 #define E1000_MDIC_PHY_SHIFT 21 #define E1000_MDIC_OP_WRITE 0x04000000 #define E1000_MDIC_OP_READ 0x08000000 #define E1000_MDIC_READY 0x10000000 #define E1000_MDIC_ERROR 0x40000000 #define E1000_MDIC_DEST 0x80000000 /* SerDes Control */ #define E1000_GEN_CTL_READY 0x80000000 #define E1000_GEN_CTL_ADDRESS_SHIFT 8 #define E1000_GEN_POLL_TIMEOUT 640 /* LinkSec register fields */ #define E1000_LSECTXCAP_SUM_MASK 0x00FF0000 #define E1000_LSECTXCAP_SUM_SHIFT 16 #define E1000_LSECRXCAP_SUM_MASK 0x00FF0000 #define E1000_LSECRXCAP_SUM_SHIFT 16 #define E1000_LSECTXCTRL_EN_MASK 0x00000003 #define E1000_LSECTXCTRL_DISABLE 0x0 #define E1000_LSECTXCTRL_AUTH 0x1 #define E1000_LSECTXCTRL_AUTH_ENCRYPT 0x2 #define E1000_LSECTXCTRL_AISCI 0x00000020 #define E1000_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 #define E1000_LSECTXCTRL_RSV_MASK 0x000000D8 #define E1000_LSECRXCTRL_EN_MASK 0x0000000C #define E1000_LSECRXCTRL_EN_SHIFT 2 #define E1000_LSECRXCTRL_DISABLE 0x0 #define E1000_LSECRXCTRL_CHECK 0x1 #define E1000_LSECRXCTRL_STRICT 0x2 #define E1000_LSECRXCTRL_DROP 0x3 #define E1000_LSECRXCTRL_PLSH 0x00000040 #define E1000_LSECRXCTRL_RP 0x00000080 #define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 /* Tx Rate-Scheduler Config fields */ #define E1000_RTTBCNRC_RS_ENA 0x80000000 #define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF #define E1000_RTTBCNRC_RF_INT_SHIFT 14 #define E1000_RTTBCNRC_RF_INT_MASK \ (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT) /* DMA Coalescing register fields */ /* DMA Coalescing Watchdog Timer */ #define E1000_DMACR_DMACWT_MASK 0x00003FFF /* DMA Coalescing Rx Threshold */ #define E1000_DMACR_DMACTHR_MASK 0x00FF0000 #define E1000_DMACR_DMACTHR_SHIFT 16 /* Lx when no PCIe transactions */ #define E1000_DMACR_DMAC_LX_MASK 0x30000000 #define E1000_DMACR_DMAC_LX_SHIFT 28 #define E1000_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */ /* DMA Coalescing BMC-to-OS Watchdog Enable */ #define E1000_DMACR_DC_BMC2OSW_EN 0x00008000 /* DMA Coalescing Transmit Threshold */ #define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF #define E1000_DMCTLX_TTLX_MASK 0x00000FFF /* Time to LX request */ /* Rx Traffic Rate Threshold */ #define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF /* Rx packet rate in current window */ #define E1000_DMCRTRH_LRPRCW 0x80000000 /* DMA Coal Rx Traffic Current Count */ #define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF /* Flow ctrl Rx Threshold High val */ #define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0 #define E1000_FCRTC_RTH_COAL_SHIFT 4 /* Lx power decision based on DMA coal */ #define E1000_PCIEMISC_LX_DECISION 0x00000080 #define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ #define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */ #define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */ /* Proxy Filter Control */ #define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */ #define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */ #define E1000_PROXYFC_MC 0x00000008 /* Directed MC Proxy */ #define E1000_PROXYFC_BC 0x00000010 /* Broadcast Proxy Enable */ #define E1000_PROXYFC_ARP_DIRECTED 0x00000020 /* Directed ARP Proxy Ena */ #define E1000_PROXYFC_IPV4 0x00000040 /* Directed IPv4 Enable */ #define E1000_PROXYFC_IPV6 0x00000080 /* Directed IPv6 Enable */ #define E1000_PROXYFC_NS 0x00000200 /* IPv6 Neighbor Solicitation */ #define E1000_PROXYFC_ARP 0x00000800 /* ARP Request Proxy Ena */ /* Proxy Status */ #define E1000_PROXYS_CLEAR 0xFFFFFFFF /* Clear */ /* Firmware Status */ #define E1000_FWSTS_FWRI 0x80000000 /* FW Reset Indication */ /* VF Control */ #define E1000_VTCTRL_RST 0x04000000 /* Reset VF */ #define E1000_STATUS_LAN_ID_MASK 0x00000000C /* Mask for Lan ID field */ /* Lan ID bit field offset in status register */ #define E1000_STATUS_LAN_ID_OFFSET 2 #define E1000_VFTA_ENTRIES 128 #ifndef E1000_UNUSEDARG #define E1000_UNUSEDARG #endif /* E1000_UNUSEDARG */ #endif /* _E1000_DEFINES_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_hw.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ #include "e1000_osdep.h" #include "e1000_regs.h" #include "e1000_defines.h" struct e1000_hw; #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526 #define E1000_DEV_ID_82576_NS 0x150A #define E1000_DEV_ID_82576_NS_SERDES 0x1518 #define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 #define E1000_DEV_ID_82580_COPPER 0x150E #define E1000_DEV_ID_82580_FIBER 0x150F #define E1000_DEV_ID_82580_SERDES 0x1510 #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 #define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 #define E1000_DEV_ID_I350_COPPER 0x1521 #define E1000_DEV_ID_I350_FIBER 0x1522 #define E1000_DEV_ID_I350_SERDES 0x1523 #define E1000_DEV_ID_I350_SGMII 0x1524 #define E1000_DEV_ID_I350_DA4 0x1546 #define E1000_DEV_ID_I210_COPPER 0x1533 #define E1000_DEV_ID_I210_COPPER_OEM1 0x1534 #define E1000_DEV_ID_I210_COPPER_IT 0x1535 #define E1000_DEV_ID_I210_FIBER 0x1536 #define E1000_DEV_ID_I210_SERDES 0x1537 #define E1000_DEV_ID_I210_SGMII 0x1538 #define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B #define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C #define E1000_DEV_ID_I211_COPPER 0x1539 #define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40 #define E1000_DEV_ID_I354_SGMII 0x1F41 #define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45 #define E1000_DEV_ID_DH89XXCC_SGMII 0x0438 #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C #define E1000_DEV_ID_DH89XXCC_SFP 0x0440 #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 #define E1000_REVISION_3 3 #define E1000_REVISION_4 4 #define E1000_FUNC_0 0 #define E1000_FUNC_1 1 #define E1000_FUNC_2 2 #define E1000_FUNC_3 3 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9 enum e1000_mac_type { e1000_undefined = 0, e1000_82575, e1000_82576, e1000_82580, e1000_i350, e1000_i354, e1000_i210, e1000_i211, e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ }; enum e1000_media_type { e1000_media_type_unknown = 0, e1000_media_type_copper = 1, e1000_media_type_fiber = 2, e1000_media_type_internal_serdes = 3, e1000_num_media_types }; enum e1000_nvm_type { e1000_nvm_unknown = 0, e1000_nvm_none, e1000_nvm_eeprom_spi, e1000_nvm_flash_hw, e1000_nvm_invm, e1000_nvm_flash_sw }; enum e1000_nvm_override { e1000_nvm_override_none = 0, e1000_nvm_override_spi_small, e1000_nvm_override_spi_large, }; enum e1000_phy_type { e1000_phy_unknown = 0, e1000_phy_none, e1000_phy_m88, e1000_phy_igp, e1000_phy_igp_2, e1000_phy_gg82563, e1000_phy_igp_3, e1000_phy_ife, e1000_phy_82580, e1000_phy_vf, e1000_phy_i210, }; enum e1000_bus_type { e1000_bus_type_unknown = 0, e1000_bus_type_pci, e1000_bus_type_pcix, e1000_bus_type_pci_express, e1000_bus_type_reserved }; enum e1000_bus_speed { e1000_bus_speed_unknown = 0, e1000_bus_speed_33, e1000_bus_speed_66, e1000_bus_speed_100, e1000_bus_speed_120, e1000_bus_speed_133, e1000_bus_speed_2500, e1000_bus_speed_5000, e1000_bus_speed_reserved }; enum e1000_bus_width { e1000_bus_width_unknown = 0, e1000_bus_width_pcie_x1, e1000_bus_width_pcie_x2, e1000_bus_width_pcie_x4 = 4, e1000_bus_width_pcie_x8 = 8, e1000_bus_width_32, e1000_bus_width_64, e1000_bus_width_reserved }; enum e1000_1000t_rx_status { e1000_1000t_rx_status_not_ok = 0, e1000_1000t_rx_status_ok, e1000_1000t_rx_status_undefined = 0xFF }; enum e1000_rev_polarity { e1000_rev_polarity_normal = 0, e1000_rev_polarity_reversed, e1000_rev_polarity_undefined = 0xFF }; enum e1000_fc_mode { e1000_fc_none = 0, e1000_fc_rx_pause, e1000_fc_tx_pause, e1000_fc_full, e1000_fc_default = 0xFF }; enum e1000_ms_type { e1000_ms_hw_default = 0, e1000_ms_force_master, e1000_ms_force_slave, e1000_ms_auto }; enum e1000_smart_speed { e1000_smart_speed_default = 0, e1000_smart_speed_on, e1000_smart_speed_off }; enum e1000_serdes_link_state { e1000_serdes_link_down = 0, e1000_serdes_link_autoneg_progress, e1000_serdes_link_autoneg_complete, e1000_serdes_link_forced_up }; #ifndef __le16 #define __le16 u16 #endif #ifndef __le32 #define __le32 u32 #endif #ifndef __le64 #define __le64 u64 #endif /* Receive Descriptor */ struct e1000_rx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ __le16 length; /* Length of data DMAed into data buffer */ __le16 csum; /* Packet checksum */ u8 status; /* Descriptor status */ u8 errors; /* Descriptor Errors */ __le16 special; }; /* Receive Descriptor - Extended */ union e1000_rx_desc_extended { struct { __le64 buffer_addr; __le64 reserved; } read; struct { struct { __le32 mrq; /* Multiple Rx Queues */ union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; #define MAX_PS_BUFFERS 4 /* Number of packet split data buffers (not including the header buffer) */ #define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) /* Receive Descriptor - Packet Split */ union e1000_rx_desc_packet_split { struct { /* one buffer for protocol header(s), three data buffers */ __le64 buffer_addr[MAX_PS_BUFFERS]; } read; struct { struct { __le32 mrq; /* Multiple Rx Queues */ union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length0; /* length of buffer 0 */ __le16 vlan; /* VLAN tag */ } middle; struct { __le16 header_status; /* length of buffers 1-3 */ __le16 length[PS_PAGE_BUFFERS]; } upper; __le64 reserved; } wb; /* writeback */ }; /* Transmit Descriptor */ struct e1000_tx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 cso; /* Checksum offset */ u8 cmd; /* Descriptor control */ } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 css; /* Checksum start */ __le16 special; } fields; } upper; }; /* Offload Context Descriptor */ struct e1000_context_desc { union { __le32 ip_config; struct { u8 ipcss; /* IP checksum start */ u8 ipcso; /* IP checksum offset */ __le16 ipcse; /* IP checksum end */ } ip_fields; } lower_setup; union { __le32 tcp_config; struct { u8 tucss; /* TCP checksum start */ u8 tucso; /* TCP checksum offset */ __le16 tucse; /* TCP checksum end */ } tcp_fields; } upper_setup; __le32 cmd_and_length; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 hdr_len; /* Header length */ __le16 mss; /* Maximum segment size */ } fields; } tcp_seg_setup; }; /* Offload data descriptor */ struct e1000_data_desc { __le64 buffer_addr; /* Address of the descriptor's buffer address */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 typ_len_ext; u8 cmd; } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 popts; /* Packet Options */ __le16 special; } fields; } upper; }; /* Statistics counters collected by the MAC */ struct e1000_hw_stats { u64 crcerrs; u64 algnerrc; u64 symerrs; u64 rxerrc; u64 mpc; u64 scc; u64 ecol; u64 mcc; u64 latecol; u64 colc; u64 dc; u64 tncrs; u64 sec; u64 cexterr; u64 rlec; u64 xonrxc; u64 xontxc; u64 xoffrxc; u64 xofftxc; u64 fcruc; u64 prc64; u64 prc127; u64 prc255; u64 prc511; u64 prc1023; u64 prc1522; u64 gprc; u64 bprc; u64 mprc; u64 gptc; u64 gorc; u64 gotc; u64 rnbc; u64 ruc; u64 rfc; u64 roc; u64 rjc; u64 mgprc; u64 mgpdc; u64 mgptc; u64 tor; u64 tot; u64 tpr; u64 tpt; u64 ptc64; u64 ptc127; u64 ptc255; u64 ptc511; u64 ptc1023; u64 ptc1522; u64 mptc; u64 bptc; u64 tsctc; u64 tsctfc; u64 iac; u64 icrxptc; u64 icrxatc; u64 ictxptc; u64 ictxatc; u64 ictxqec; u64 ictxqmtc; u64 icrxdmtc; u64 icrxoc; u64 cbtmpc; u64 htdpmc; u64 cbrdpc; u64 cbrmpc; u64 rpthc; u64 hgptc; u64 htcbdpc; u64 hgorc; u64 hgotc; u64 lenerrs; u64 scvpc; u64 hrmpc; u64 doosync; u64 o2bgptc; u64 o2bspc; u64 b2ospc; u64 b2ogprc; }; struct e1000_phy_stats { u32 idle_errors; u32 receive_errors; }; struct e1000_host_mng_dhcp_cookie { u32 signature; u8 status; u8 reserved0; u16 vlan_id; u32 reserved1; u16 reserved2; u8 reserved3; u8 checksum; }; /* Host Interface "Rev 1" */ struct e1000_host_command_header { u8 command_id; u8 command_length; u8 command_options; u8 checksum; }; #define E1000_HI_MAX_DATA_LENGTH 252 struct e1000_host_command_info { struct e1000_host_command_header command_header; u8 command_data[E1000_HI_MAX_DATA_LENGTH]; }; /* Host Interface "Rev 2" */ struct e1000_host_mng_command_header { u8 command_id; u8 checksum; u16 reserved1; u16 reserved2; u16 command_length; }; #define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 struct e1000_host_mng_command_info { struct e1000_host_mng_command_header command_header; u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; }; #include "e1000_mac.h" #include "e1000_phy.h" #include "e1000_nvm.h" #include "e1000_manage.h" #include "e1000_mbx.h" /* Function pointers for the MAC. */ struct e1000_mac_operations { s32 (*init_params)(struct e1000_hw *); s32 (*id_led_init)(struct e1000_hw *); s32 (*blink_led)(struct e1000_hw *); bool (*check_mng_mode)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); s32 (*cleanup_led)(struct e1000_hw *); void (*clear_hw_cntrs)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); s32 (*get_bus_info)(struct e1000_hw *); void (*set_lan_id)(struct e1000_hw *); s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); s32 (*led_on)(struct e1000_hw *); s32 (*led_off)(struct e1000_hw *); void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); void (*shutdown_serdes)(struct e1000_hw *); void (*power_up_serdes)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); s32 (*setup_physical_interface)(struct e1000_hw *); s32 (*setup_led)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); void (*config_collision_dist)(struct e1000_hw *); void (*rar_set)(struct e1000_hw *, u8*, u32); s32 (*read_mac_addr)(struct e1000_hw *); s32 (*validate_mdi_setting)(struct e1000_hw *); s32 (*get_thermal_sensor_data)(struct e1000_hw *); s32 (*init_thermal_sensor_thresh)(struct e1000_hw *); s32 (*acquire_swfw_sync)(struct e1000_hw *, u16); void (*release_swfw_sync)(struct e1000_hw *, u16); }; /* When to use various PHY register access functions: * * Func Caller * Function Does Does When to use * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * X_reg L,P,A n/a for simple PHY reg accesses * X_reg_locked P,A L for multiple accesses of different regs * on different pages * X_reg_page A L,P for multiple accesses of different regs * on the same page * * Where X=[read|write], L=locking, P=sets page, A=register access * */ struct e1000_phy_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); s32 (*check_polarity)(struct e1000_hw *); s32 (*check_reset_block)(struct e1000_hw *); s32 (*commit)(struct e1000_hw *); s32 (*force_speed_duplex)(struct e1000_hw *); s32 (*get_cfg_done)(struct e1000_hw *hw); s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_info)(struct e1000_hw *); s32 (*set_page)(struct e1000_hw *, u16); s32 (*read_reg)(struct e1000_hw *, u32, u16 *); s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *); void (*release)(struct e1000_hw *); s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); s32 (*write_reg)(struct e1000_hw *, u32, u16); s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); s32 (*write_reg_page)(struct e1000_hw *, u32, u16); void (*power_up)(struct e1000_hw *); void (*power_down)(struct e1000_hw *); s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *); s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8); }; /* Function pointers for the NVM. */ struct e1000_nvm_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); s32 (*read)(struct e1000_hw *, u16, u16, u16 *); void (*release)(struct e1000_hw *); void (*reload)(struct e1000_hw *); s32 (*update)(struct e1000_hw *); s32 (*valid_led_default)(struct e1000_hw *, u16 *); s32 (*validate)(struct e1000_hw *); s32 (*write)(struct e1000_hw *, u16, u16, u16 *); }; #define E1000_MAX_SENSORS 3 struct e1000_thermal_diode_data { u8 location; u8 temp; u8 caution_thresh; u8 max_op_thresh; }; struct e1000_thermal_sensor_data { struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS]; }; struct e1000_mac_info { struct e1000_mac_operations ops; u8 addr[ETH_ADDR_LEN]; u8 perm_addr[ETH_ADDR_LEN]; enum e1000_mac_type type; u32 collision_delta; u32 ledctl_default; u32 ledctl_mode1; u32 ledctl_mode2; u32 mc_filter_type; u32 tx_packet_delta; u32 txcw; u16 current_ifs_val; u16 ifs_max_val; u16 ifs_min_val; u16 ifs_ratio; u16 ifs_step_size; u16 mta_reg_count; u16 uta_reg_count; /* Maximum size of the MTA register table in all supported adapters */ #define MAX_MTA_REG 128 u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; u8 forced_speed_duplex; bool adaptive_ifs; bool has_fwsm; bool arc_subsystem_valid; bool asf_firmware_present; bool autoneg; bool autoneg_failed; bool get_link_status; bool in_ifs_mode; enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; struct e1000_thermal_sensor_data thermal_sensor_data; }; struct e1000_phy_info { struct e1000_phy_operations ops; enum e1000_phy_type type; enum e1000_1000t_rx_status local_rx; enum e1000_1000t_rx_status remote_rx; enum e1000_ms_type ms_type; enum e1000_ms_type original_ms_type; enum e1000_rev_polarity cable_polarity; enum e1000_smart_speed smart_speed; u32 addr; u32 id; u32 reset_delay_us; /* in usec */ u32 revision; enum e1000_media_type media_type; u16 autoneg_advertised; u16 autoneg_mask; u16 cable_length; u16 max_cable_length; u16 min_cable_length; u8 mdix; bool disable_polarity_correction; bool is_mdix; bool polarity_correction; bool reset_disable; bool speed_downgraded; bool autoneg_wait_to_complete; }; struct e1000_nvm_info { struct e1000_nvm_operations ops; enum e1000_nvm_type type; enum e1000_nvm_override override; u32 flash_bank_size; u32 flash_base_addr; u16 word_size; u16 delay_usec; u16 address_bits; u16 opcode_bits; u16 page_size; }; struct e1000_bus_info { enum e1000_bus_type type; enum e1000_bus_speed speed; enum e1000_bus_width width; u16 func; u16 pci_cmd_word; }; struct e1000_fc_info { u32 high_water; /* Flow control high-water mark */ u32 low_water; /* Flow control low-water mark */ u16 pause_time; /* Flow control pause timer */ u16 refresh_time; /* Flow control refresh timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ enum e1000_fc_mode current_mode; /* FC mode in effect */ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ }; struct e1000_mbx_operations { s32 (*init_params)(struct e1000_hw *hw); s32 (*read)(struct e1000_hw *, u32 *, u16, u16); s32 (*write)(struct e1000_hw *, u32 *, u16, u16); s32 (*read_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*write_posted)(struct e1000_hw *, u32 *, u16, u16); s32 (*check_for_msg)(struct e1000_hw *, u16); s32 (*check_for_ack)(struct e1000_hw *, u16); s32 (*check_for_rst)(struct e1000_hw *, u16); }; struct e1000_mbx_stats { u32 msgs_tx; u32 msgs_rx; u32 acks; u32 reqs; u32 rsts; }; struct e1000_mbx_info { struct e1000_mbx_operations ops; struct e1000_mbx_stats stats; u32 timeout; u32 usec_delay; u16 size; }; struct e1000_dev_spec_82575 { bool sgmii_active; bool global_device_reset; bool eee_disable; bool module_plugged; bool clear_semaphore_once; u32 mtu; struct sfp_e1000_flags eth_flags; u8 media_port; bool media_changed; }; struct e1000_dev_spec_vf { u32 vf_number; u32 v2p_mailbox; }; struct e1000_hw { void *back; u8 __iomem *hw_addr; u8 __iomem *flash_address; unsigned long io_base; struct e1000_mac_info mac; struct e1000_fc_info fc; struct e1000_phy_info phy; struct e1000_nvm_info nvm; struct e1000_bus_info bus; struct e1000_mbx_info mbx; struct e1000_host_mng_dhcp_cookie mng_cookie; union { struct e1000_dev_spec_82575 _82575; struct e1000_dev_spec_vf vf; } dev_spec; u16 device_id; u16 subsystem_vendor_id; u16 subsystem_device_id; u16 vendor_id; u8 revision_id; }; #include "e1000_82575.h" #include "e1000_i210.h" /* These functions must be implemented by drivers */ s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_i210.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); static void e1000_release_nvm_i210(struct e1000_hw *hw); static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data); /** * e1000_acquire_nvm_i210 - Request for access to EEPROM * @hw: pointer to the HW structure * * Acquire the necessary semaphores for exclusive access to the EEPROM. * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_acquire_nvm_i210"); ret_val = e1000_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); return ret_val; } /** * e1000_release_nvm_i210 - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit, * then release the semaphores acquired. **/ static void e1000_release_nvm_i210(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_i210"); e1000_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); } /** * e1000_acquire_swfw_sync_i210 - Acquire SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Acquire the SW/FW semaphore to access the PHY or NVM. The mask * will also specify which port we're acquiring the lock for. **/ s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 16; s32 ret_val = E1000_SUCCESS; s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ DEBUGFUNC("e1000_acquire_swfw_sync_i210"); while (i < timeout) { if (e1000_get_hw_semaphore_i210(hw)) { ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) * or other software thread using resource (swmask) */ e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } if (i == timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); ret_val = -E1000_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); out: return ret_val; } /** * e1000_release_swfw_sync_i210 - Release SW/FW semaphore * @hw: pointer to the HW structure * @mask: specifies which semaphore to acquire * * Release the SW/FW semaphore used to access the PHY or NVM. The mask * will also specify which port we're releasing the lock for. **/ void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) { u32 swfw_sync; DEBUGFUNC("e1000_release_swfw_sync_i210"); while (e1000_get_hw_semaphore_i210(hw) != E1000_SUCCESS) ; /* Empty */ swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); e1000_put_hw_semaphore_generic(hw); } /** * e1000_get_hw_semaphore_i210 - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) { u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_i210"); /* Get the SW semaphore */ while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == timeout) { /* In rare circumstances, the SW semaphore may already be held * unintentionally. Clear the semaphore once before giving up. */ if (hw->dev_spec._82575.clear_semaphore_once) { hw->dev_spec._82575.clear_semaphore_once = false; e1000_put_hw_semaphore_generic(hw); for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); } } /* If we do not have the semaphore here, we have to give up. */ if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the Shadow Ram to read * @words: number of words to read * @data: word read from the Shadow Ram * * Reads a 16 bit word from the Shadow Ram using the EERD register. * Uses necessary synchronization semaphores. **/ s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = E1000_SUCCESS; u16 i, count; DEBUGFUNC("e1000_read_nvm_srrd_i210"); /* We cannot hold synchronization semaphores for too long, * because of forceful takeover procedure. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? E1000_EERD_EEWR_MAX_COUNT : (words - i); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { status = e1000_read_nvm_eerd(hw, offset, count, data + i); hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } if (status != E1000_SUCCESS) break; } return status; } /** * e1000_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR * @hw: pointer to the HW structure * @offset: offset within the Shadow RAM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the Shadow RAM * * Writes data to Shadow RAM at offset using EEWR register. * * If e1000_update_nvm_checksum is not called after this function , the * data will not be committed to FLASH and also Shadow RAM will most likely * contain an invalid checksum. * * If error code is returned, data and Shadow RAM may be inconsistent - buffer * partially written. **/ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = E1000_SUCCESS; u16 i, count; DEBUGFUNC("e1000_write_nvm_srwr_i210"); /* We cannot hold synchronization semaphores for too long, * because of forceful takeover procedure. However it is more efficient * to write in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? E1000_EERD_EEWR_MAX_COUNT : (words - i); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { status = e1000_write_nvm_srwr(hw, offset, count, data + i); hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } if (status != E1000_SUCCESS) break; } return status; } /** * e1000_write_nvm_srwr - Write to Shadow Ram using EEWR * @hw: pointer to the HW structure * @offset: offset within the Shadow Ram to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the Shadow Ram * * Writes data to Shadow Ram at offset using EEWR register. * * If e1000_update_nvm_checksum is not called after this function , the * Shadow Ram will most likely contain an invalid checksum. **/ static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, k, eewr = 0; u32 attempts = 100000; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_nvm_srwr"); /* * A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } for (i = 0; i < words; i++) { eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | (data[i] << E1000_NVM_RW_REG_DATA) | E1000_NVM_RW_REG_START; E1000_WRITE_REG(hw, E1000_SRWR, eewr); for (k = 0; k < attempts; k++) { if (E1000_NVM_RW_REG_DONE & E1000_READ_REG(hw, E1000_SRWR)) { ret_val = E1000_SUCCESS; break; } usec_delay(5); } if (ret_val != E1000_SUCCESS) { DEBUGOUT("Shadow RAM write EEWR timed out\n"); break; } } out: return ret_val; } /** e1000_read_invm_word_i210 - Reads OTP * @hw: pointer to the HW structure * @address: the word address (aka eeprom offset) to read * @data: pointer to the data read * * Reads 16-bit words from the OTP. Return error when the word is not * stored in OTP. **/ static s32 e1000_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) { s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; u32 invm_dword; u16 i; u8 record_type, word_address; DEBUGFUNC("e1000_read_invm_word_i210"); for (i = 0; i < E1000_INVM_SIZE; i++) { invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); /* Get record type */ record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) break; if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); if (word_address == address) { *data = INVM_DWORD_TO_WORD_DATA(invm_dword); DEBUGOUT2("Read INVM Word 0x%02x = %x", address, *data); status = E1000_SUCCESS; break; } } } if (status != E1000_SUCCESS) DEBUGOUT1("Requested word 0x%02x not found in OTP\n", address); return status; } /** e1000_read_invm_i210 - Read invm wrapper function for I210/I211 * @hw: pointer to the HW structure * @address: the word address (aka eeprom offset) to read * @data: pointer to the data read * * Wrapper function to return data formerly found in the NVM. **/ static s32 e1000_read_invm_i210(struct e1000_hw *hw, u16 offset, u16 E1000_UNUSEDARG words, u16 *data) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_invm_i210"); /* Only the MAC addr is required to be present in the iNVM */ switch (offset) { case NVM_MAC_ADDR: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, &data[0]); ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+1, &data[1]); ret_val |= e1000_read_invm_word_i210(hw, (u8)offset+2, &data[2]); if (ret_val != E1000_SUCCESS) DEBUGOUT("MAC Addr not found in iNVM\n"); break; case NVM_INIT_CTRL_2: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_INIT_CTRL_2_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_INIT_CTRL_4: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_INIT_CTRL_4_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_LED_1_CFG: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_LED_1_CFG_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_LED_0_2_CFG: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = NVM_LED_0_2_CFG_DEFAULT_I211; ret_val = E1000_SUCCESS; } break; case NVM_ID_LED_SETTINGS: ret_val = e1000_read_invm_word_i210(hw, (u8)offset, data); if (ret_val != E1000_SUCCESS) { *data = ID_LED_RESERVED_FFFF; ret_val = E1000_SUCCESS; } break; case NVM_SUB_DEV_ID: *data = hw->subsystem_device_id; break; case NVM_SUB_VEN_ID: *data = hw->subsystem_vendor_id; break; case NVM_DEV_ID: *data = hw->device_id; break; case NVM_VEN_ID: *data = hw->vendor_id; break; default: DEBUGOUT1("NVM word 0x%02x is not mapped.\n", offset); *data = NVM_RESERVED_WORD; break; } return ret_val; } /** * e1000_read_invm_version - Reads iNVM version and image type * @hw: pointer to the HW structure * @invm_ver: version structure for the version read * * Reads iNVM version and image type. **/ s32 e1000_read_invm_version(struct e1000_hw *hw, struct e1000_fw_version *invm_ver) { u32 *record = NULL; u32 *next_record = NULL; u32 i = 0; u32 invm_dword = 0; u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE / E1000_INVM_RECORD_SIZE_IN_BYTES); u32 buffer[E1000_INVM_SIZE]; s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; u16 version = 0; DEBUGFUNC("e1000_read_invm_version"); /* Read iNVM memory */ for (i = 0; i < E1000_INVM_SIZE; i++) { invm_dword = E1000_READ_REG(hw, E1000_INVM_DATA_REG(i)); buffer[i] = invm_dword; } /* Read version number */ for (i = 1; i < invm_blocks; i++) { record = &buffer[invm_blocks - i]; next_record = &buffer[invm_blocks - i + 1]; /* Check if we have first version location used */ if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) { version = 0; status = E1000_SUCCESS; break; } /* Check if we have second version location used */ else if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) { version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; status = E1000_SUCCESS; break; } /* * Check if we have odd version location * used and it is the last one used */ else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) && ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) && (i != 1))) { version = (*next_record & E1000_INVM_VER_FIELD_TWO) >> 13; status = E1000_SUCCESS; break; } /* * Check if we have even version location * used and it is the last one used */ else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) && ((*record & 0x3) == 0)) { version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3; status = E1000_SUCCESS; break; } } if (status == E1000_SUCCESS) { invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK) >> E1000_INVM_MAJOR_SHIFT; invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK; } /* Read Image Type */ for (i = 1; i < invm_blocks; i++) { record = &buffer[invm_blocks - i]; next_record = &buffer[invm_blocks - i + 1]; /* Check if we have image type in first location used */ if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) { invm_ver->invm_img_type = 0; status = E1000_SUCCESS; break; } /* Check if we have image type in first location used */ else if ((((*record & 0x3) == 0) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) || ((((*record & 0x3) != 0) && (i != 1)))) { invm_ver->invm_img_type = (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23; status = E1000_SUCCESS; break; } } return status; } /** * e1000_validate_nvm_checksum_i210 - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw) { s32 status = E1000_SUCCESS; s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); DEBUGFUNC("e1000_validate_nvm_checksum_i210"); if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { /* * Replace the read function with semaphore grabbing with * the one that skips this for a while. * We have semaphore taken already here. */ read_op_ptr = hw->nvm.ops.read; hw->nvm.ops.read = e1000_read_nvm_eerd; status = e1000_validate_nvm_checksum_generic(hw); /* Revert original read operation. */ hw->nvm.ops.read = read_op_ptr; hw->nvm.ops.release(hw); } else { status = E1000_ERR_SWFW_SYNC; } return status; } /** * e1000_update_nvm_checksum_i210 - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. Next commit EEPROM data onto the Flash. **/ s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum_i210"); /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ ret_val = e1000_read_nvm_eerd(hw, 0, 1, &nvm_data); if (ret_val != E1000_SUCCESS) { DEBUGOUT("EEPROM read failed\n"); goto out; } if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { /* * Do not use hw->nvm.ops.write, hw->nvm.ops.read * because we do not want to take the synchronization * semaphores twice here. */ for (i = 0; i < NVM_CHECKSUM_REG; i++) { ret_val = e1000_read_nvm_eerd(hw, i, 1, &nvm_data); if (ret_val) { hw->nvm.ops.release(hw); DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = e1000_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val != E1000_SUCCESS) { hw->nvm.ops.release(hw); DEBUGOUT("NVM Write Error while updating checksum.\n"); goto out; } hw->nvm.ops.release(hw); ret_val = e1000_update_flash_i210(hw); } else { ret_val = E1000_ERR_SWFW_SYNC; } out: return ret_val; } /** * e1000_get_flash_presence_i210 - Check if flash device is detected. * @hw: pointer to the HW structure * **/ bool e1000_get_flash_presence_i210(struct e1000_hw *hw) { u32 eec = 0; bool ret_val = false; DEBUGFUNC("e1000_get_flash_presence_i210"); eec = E1000_READ_REG(hw, E1000_EECD); if (eec & E1000_EECD_FLASH_DETECTED_I210) ret_val = true; return ret_val; } /** * e1000_update_flash_i210 - Commit EEPROM to the flash * @hw: pointer to the HW structure * **/ s32 e1000_update_flash_i210(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u32 flup; DEBUGFUNC("e1000_update_flash_i210"); ret_val = e1000_pool_flash_update_done_i210(hw); if (ret_val == -E1000_ERR_NVM) { DEBUGOUT("Flash update time out\n"); goto out; } flup = E1000_READ_REG(hw, E1000_EECD) | E1000_EECD_FLUPD_I210; E1000_WRITE_REG(hw, E1000_EECD, flup); ret_val = e1000_pool_flash_update_done_i210(hw); if (ret_val == E1000_SUCCESS) DEBUGOUT("Flash update complete\n"); else DEBUGOUT("Flash update time out\n"); out: return ret_val; } /** * e1000_pool_flash_update_done_i210 - Pool FLUDONE status. * @hw: pointer to the HW structure * **/ s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw) { s32 ret_val = -E1000_ERR_NVM; u32 i, reg; DEBUGFUNC("e1000_pool_flash_update_done_i210"); for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { reg = E1000_READ_REG(hw, E1000_EECD); if (reg & E1000_EECD_FLUDONE_I210) { ret_val = E1000_SUCCESS; break; } usec_delay(5); } return ret_val; } /** * e1000_init_nvm_params_i210 - Initialize i210 NVM function pointers * @hw: pointer to the HW structure * * Initialize the i210/i211 NVM parameters and function pointers. **/ static s32 e1000_init_nvm_params_i210(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_params_i210"); ret_val = e1000_init_nvm_params_82575(hw); nvm->ops.acquire = e1000_acquire_nvm_i210; nvm->ops.release = e1000_release_nvm_i210; nvm->ops.valid_led_default = e1000_valid_led_default_i210; if (e1000_get_flash_presence_i210(hw)) { hw->nvm.type = e1000_nvm_flash_hw; nvm->ops.read = e1000_read_nvm_srrd_i210; nvm->ops.write = e1000_write_nvm_srwr_i210; nvm->ops.validate = e1000_validate_nvm_checksum_i210; nvm->ops.update = e1000_update_nvm_checksum_i210; } else { hw->nvm.type = e1000_nvm_invm; nvm->ops.read = e1000_read_invm_i210; nvm->ops.write = e1000_null_write_nvm; nvm->ops.validate = e1000_null_ops_generic; nvm->ops.update = e1000_null_ops_generic; } return ret_val; } /** * e1000_init_function_pointers_i210 - Init func ptrs. * @hw: pointer to the HW structure * * Called to initialize all function pointers and parameters. **/ void e1000_init_function_pointers_i210(struct e1000_hw *hw) { e1000_init_function_pointers_82575(hw); hw->nvm.ops.init_params = e1000_init_nvm_params_i210; return; } /** * e1000_valid_led_default_i210 - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ static s32 e1000_valid_led_default_i210(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_i210"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { switch (hw->phy.media_type) { case e1000_media_type_internal_serdes: *data = ID_LED_DEFAULT_I210_SERDES; break; case e1000_media_type_copper: default: *data = ID_LED_DEFAULT_I210; break; } } out: return ret_val; } /** * __e1000_access_xmdio_reg - Read/write XMDIO register * @hw: pointer to the HW structure * @address: XMDIO address to program * @dev_addr: device address to program * @data: pointer to value to read/write from/to the XMDIO address * @read: boolean flag to indicate read or write **/ static s32 __e1000_access_xmdio_reg(struct e1000_hw *hw, u16 address, u8 dev_addr, u16 *data, bool read) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("__e1000_access_xmdio_reg"); ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address); if (ret_val) return ret_val; ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA | dev_addr); if (ret_val) return ret_val; if (read) ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data); else ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data); if (ret_val) return ret_val; /* Recalibrate the device back to 0 */ ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0); if (ret_val) return ret_val; return ret_val; } /** * e1000_read_xmdio_reg - Read XMDIO register * @hw: pointer to the HW structure * @addr: XMDIO address to program * @dev_addr: device address to program * @data: value to be read from the EMI address **/ s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data) { DEBUGFUNC("e1000_read_xmdio_reg"); return __e1000_access_xmdio_reg(hw, addr, dev_addr, data, true); } /** * e1000_write_xmdio_reg - Write XMDIO register * @hw: pointer to the HW structure * @addr: XMDIO address to program * @dev_addr: device address to program * @data: value to be written to the XMDIO address **/ s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data) { DEBUGFUNC("e1000_read_xmdio_reg"); return __e1000_access_xmdio_reg(hw, addr, dev_addr, &data, false); } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_i210.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_I210_H_ #define _E1000_I210_H_ bool e1000_get_flash_presence_i210(struct e1000_hw *hw); s32 e1000_update_flash_i210(struct e1000_hw *hw); s32 e1000_update_nvm_checksum_i210(struct e1000_hw *hw); s32 e1000_validate_nvm_checksum_i210(struct e1000_hw *hw); s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_invm_version(struct e1000_hw *hw, struct e1000_fw_version *invm_ver); s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); s32 e1000_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data); s32 e1000_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data); #define E1000_STM_OPCODE 0xDB00 #define E1000_EEPROM_FLASH_SIZE_WORD 0x11 #define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \ (u8)((invm_dword) & 0x7) #define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \ (u8)(((invm_dword) & 0x0000FE00) >> 9) #define INVM_DWORD_TO_WORD_DATA(invm_dword) \ (u16)(((invm_dword) & 0xFFFF0000) >> 16) enum E1000_INVM_STRUCTURE_TYPE { E1000_INVM_UNINITIALIZED_STRUCTURE = 0x00, E1000_INVM_WORD_AUTOLOAD_STRUCTURE = 0x01, E1000_INVM_CSR_AUTOLOAD_STRUCTURE = 0x02, E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE = 0x03, E1000_INVM_RSA_KEY_SHA256_STRUCTURE = 0x04, E1000_INVM_INVALIDATED_STRUCTURE = 0x0F, }; #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 #define E1000_INVM_ULT_BYTES_SIZE 8 #define E1000_INVM_RECORD_SIZE_IN_BYTES 4 #define E1000_INVM_VER_FIELD_ONE 0x1FF8 #define E1000_INVM_VER_FIELD_TWO 0x7FE000 #define E1000_INVM_IMGTYPE_FIELD 0x1F800000 #define E1000_INVM_MAJOR_MASK 0x3F0 #define E1000_INVM_MINOR_MASK 0xF #define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_OFF2)) #define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_OFF1_ON2)) /* NVM offset defaults for I211 devices */ #define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 #define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 #define NVM_LED_1_CFG_DEFAULT_I211 0x0184 #define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_mac.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw); static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); static void e1000_config_collision_dist_generic(struct e1000_hw *hw); static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); /** * e1000_init_mac_ops_generic - Initialize MAC function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_mac_ops_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_init_mac_ops_generic"); /* General Setup */ mac->ops.init_params = e1000_null_ops_generic; mac->ops.init_hw = e1000_null_ops_generic; mac->ops.reset_hw = e1000_null_ops_generic; mac->ops.setup_physical_interface = e1000_null_ops_generic; mac->ops.get_bus_info = e1000_null_ops_generic; mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pcie; mac->ops.read_mac_addr = e1000_read_mac_addr_generic; mac->ops.config_collision_dist = e1000_config_collision_dist_generic; mac->ops.clear_hw_cntrs = e1000_null_mac_generic; /* LED */ mac->ops.cleanup_led = e1000_null_ops_generic; mac->ops.setup_led = e1000_null_ops_generic; mac->ops.blink_led = e1000_null_ops_generic; mac->ops.led_on = e1000_null_ops_generic; mac->ops.led_off = e1000_null_ops_generic; /* LINK */ mac->ops.setup_link = e1000_null_ops_generic; mac->ops.get_link_up_info = e1000_null_link_info; mac->ops.check_for_link = e1000_null_ops_generic; /* Management */ mac->ops.check_mng_mode = e1000_null_mng_mode; /* VLAN, MC, etc. */ mac->ops.update_mc_addr_list = e1000_null_update_mc; mac->ops.clear_vfta = e1000_null_mac_generic; mac->ops.write_vfta = e1000_null_write_vfta; mac->ops.rar_set = e1000_rar_set_generic; mac->ops.validate_mdi_setting = e1000_validate_mdi_setting_generic; } /** * e1000_null_ops_generic - No-op function, returns 0 * @hw: pointer to the HW structure **/ s32 e1000_null_ops_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_ops_generic"); return E1000_SUCCESS; } /** * e1000_null_mac_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_mac_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_mac_generic"); return; } /** * e1000_null_link_info - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_link_info(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG *s, u16 E1000_UNUSEDARG *d) { DEBUGFUNC("e1000_null_link_info"); return E1000_SUCCESS; } /** * e1000_null_mng_mode - No-op function, return false * @hw: pointer to the HW structure **/ bool e1000_null_mng_mode(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_mng_mode"); return false; } /** * e1000_null_update_mc - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_update_mc(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a) { DEBUGFUNC("e1000_null_update_mc"); return; } /** * e1000_null_write_vfta - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_write_vfta(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG a, u32 E1000_UNUSEDARG b) { DEBUGFUNC("e1000_null_write_vfta"); return; } /** * e1000_null_rar_set - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_rar_set(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG *h, u32 E1000_UNUSEDARG a) { DEBUGFUNC("e1000_null_rar_set"); return; } /** * e1000_get_bus_info_pcie_generic - Get PCIe bus information * @hw: pointer to the HW structure * * Determines and stores the system bus information for a particular * network interface. The following bus information is determined and stored: * bus speed, bus width, type (PCIe), and PCIe function. **/ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; s32 ret_val; u16 pcie_link_status; DEBUGFUNC("e1000_get_bus_info_pcie_generic"); bus->type = e1000_bus_type_pci_express; ret_val = e1000_read_pcie_cap_reg(hw, PCIE_LINK_STATUS, &pcie_link_status); if (ret_val) { bus->width = e1000_bus_width_unknown; bus->speed = e1000_bus_speed_unknown; } else { switch (pcie_link_status & PCIE_LINK_SPEED_MASK) { case PCIE_LINK_SPEED_2500: bus->speed = e1000_bus_speed_2500; break; case PCIE_LINK_SPEED_5000: bus->speed = e1000_bus_speed_5000; break; default: bus->speed = e1000_bus_speed_unknown; break; } bus->width = (enum e1000_bus_width)((pcie_link_status & PCIE_LINK_WIDTH_MASK) >> PCIE_LINK_WIDTH_SHIFT); } mac->ops.set_lan_id(hw); return E1000_SUCCESS; } /** * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices * * @hw: pointer to the HW structure * * Determines the LAN function id by reading memory-mapped registers * and swaps the port value if requested. **/ static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; u32 reg; /* The status register reports the correct function number * for the device regardless of function swap state. */ reg = E1000_READ_REG(hw, E1000_STATUS); bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; } /** * e1000_set_lan_id_single_port - Set LAN id for a single port device * @hw: pointer to the HW structure * * Sets the LAN function id to zero for a single port device. **/ void e1000_set_lan_id_single_port(struct e1000_hw *hw) { struct e1000_bus_info *bus = &hw->bus; bus->func = 0; } /** * e1000_clear_vfta_generic - Clear VLAN filter table * @hw: pointer to the HW structure * * Clears the register array which contains the VLAN filter table by * setting all the values to 0. **/ void e1000_clear_vfta_generic(struct e1000_hw *hw) { u32 offset; DEBUGFUNC("e1000_clear_vfta_generic"); for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); E1000_WRITE_FLUSH(hw); } } /** * e1000_write_vfta_generic - Write value to VLAN filter table * @hw: pointer to the HW structure * @offset: register offset in VLAN filter table * @value: register value written to VLAN filter table * * Writes value at the given offset in the register array which stores * the VLAN filter table. **/ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) { DEBUGFUNC("e1000_write_vfta_generic"); E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); E1000_WRITE_FLUSH(hw); } /** * e1000_init_rx_addrs_generic - Initialize receive address's * @hw: pointer to the HW structure * @rar_count: receive address registers * * Setup the receive address registers by setting the base receive address * register to the devices MAC address and clearing all the other receive * address registers to 0. **/ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) { u32 i; u8 mac_addr[ETH_ADDR_LEN] = {0}; DEBUGFUNC("e1000_init_rx_addrs_generic"); /* Setup the receive address */ DEBUGOUT("Programming MAC Address into RAR[0]\n"); hw->mac.ops.rar_set(hw, hw->mac.addr, 0); /* Zero out the other (rar_entry_count - 1) receive addresses */ DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1); for (i = 1; i < rar_count; i++) hw->mac.ops.rar_set(hw, mac_addr, i); } /** * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr * @hw: pointer to the HW structure * * Checks the nvm for an alternate MAC address. An alternate MAC address * can be setup by pre-boot software and must be treated like a permanent * address and must override the actual permanent MAC address. If an * alternate MAC address is found it is programmed into RAR0, replacing * the permanent address that was installed into RAR0 by the Si on reset. * This function will return SUCCESS unless it encounters an error while * reading the EEPROM. **/ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) { u32 i; s32 ret_val; u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ADDR_LEN]; DEBUGFUNC("e1000_check_alt_mac_addr_generic"); ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data); if (ret_val) return ret_val; /* Alternate MAC address is handled by the option ROM for 82580 * and newer. SW support not required. */ if (hw->mac.type >= e1000_82580) return E1000_SUCCESS; ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if ((nvm_alt_mac_addr_offset == 0xFFFF) || (nvm_alt_mac_addr_offset == 0x0000)) /* There is no Alternate MAC Address */ return E1000_SUCCESS; if (hw->bus.func == E1000_FUNC_1) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; if (hw->bus.func == E1000_FUNC_2) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN2; if (hw->bus.func == E1000_FUNC_3) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN3; for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = nvm_alt_mac_addr_offset + (i >> 1); ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } alt_mac_addr[i] = (u8)(nvm_data & 0xFF); alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); } /* if multicast bit is set, the alternate address will not be used */ if (alt_mac_addr[0] & 0x01) { DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n"); return E1000_SUCCESS; } /* We have a valid alternate MAC address, and we want to treat it the * same as the normal permanent MAC address stored by the HW into the * RAR. Do this by mapping this address into RAR0. */ hw->mac.ops.rar_set(hw, alt_mac_addr, 0); return E1000_SUCCESS; } /** * e1000_rar_set_generic - Set receive address register * @hw: pointer to the HW structure * @addr: pointer to the receive address * @index: receive address array register * * Sets the receive address array register at index to the address passed * in by addr. **/ static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) { u32 rar_low, rar_high; DEBUGFUNC("e1000_rar_set_generic"); /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* If MAC address zero, no need to set the AV bit */ if (rar_low || rar_high) rar_high |= E1000_RAH_AV; /* Some bridges will combine consecutive 32-bit writes into * a single burst write, which will malfunction on some parts. * The flushes avoid this. */ E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); E1000_WRITE_FLUSH(hw); } /** * e1000_hash_mc_addr_generic - Generate a multicast hash value * @hw: pointer to the HW structure * @mc_addr: pointer to a multicast address * * Generates a multicast address hash value which is used to determine * the multicast filter table array address and new table value. **/ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) { u32 hash_value, hash_mask; u8 bit_shift = 0; DEBUGFUNC("e1000_hash_mc_addr_generic"); /* Register count multiplied by bits per register */ hash_mask = (hw->mac.mta_reg_count * 32) - 1; /* For a mc_filter_type of 0, bit_shift is the number of left-shifts * where 0xFF would still fall within the hash mask. */ while (hash_mask >> bit_shift != 0xFF) bit_shift++; /* The portion of the address that is used for the hash table * is determined by the mc_filter_type setting. * The algorithm is such that there is a total of 8 bits of shifting. * The bit_shift for a mc_filter_type of 0 represents the number of * left-shifts where the MSB of mc_addr[5] would still fall within * the hash_mask. Case 0 does this exactly. Since there are a total * of 8 bits of shifting, then mc_addr[4] will shift right the * remaining number of bits. Thus 8 - bit_shift. The rest of the * cases are a variation of this algorithm...essentially raising the * number of bits to shift mc_addr[5] left, while still keeping the * 8-bit shifting total. * * For example, given the following Destination MAC Address and an * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), * we can see that the bit_shift for case 0 is 4. These are the hash * values resulting from each mc_filter_type... * [0] [1] [2] [3] [4] [5] * 01 AA 00 12 34 56 * LSB MSB * * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 */ switch (hw->mac.mc_filter_type) { default: case 0: break; case 1: bit_shift += 1; break; case 2: bit_shift += 2; break; case 3: bit_shift += 4; break; } hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | (((u16) mc_addr[5]) << bit_shift))); return hash_value; } /** * e1000_update_mc_addr_list_generic - Update Multicast addresses * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program * * Updates entire Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. **/ void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count) { u32 hash_value, hash_bit, hash_reg; int i; DEBUGFUNC("e1000_update_mc_addr_list_generic"); /* clear mta_shadow */ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); /* update mta_shadow from mc_addr_list */ for (i = 0; (u32) i < mc_addr_count; i++) { hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list); hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); hash_bit = hash_value & 0x1F; hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); mc_addr_list += (ETH_ADDR_LEN); } /* replace the entire MTA table */ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); E1000_WRITE_FLUSH(hw); } /** * e1000_clear_hw_cntrs_base_generic - Clear base hardware counters * @hw: pointer to the HW structure * * Clears the base hardware counters by reading the counter registers. **/ void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_clear_hw_cntrs_base_generic"); E1000_READ_REG(hw, E1000_CRCERRS); E1000_READ_REG(hw, E1000_SYMERRS); E1000_READ_REG(hw, E1000_MPC); E1000_READ_REG(hw, E1000_SCC); E1000_READ_REG(hw, E1000_ECOL); E1000_READ_REG(hw, E1000_MCC); E1000_READ_REG(hw, E1000_LATECOL); E1000_READ_REG(hw, E1000_COLC); E1000_READ_REG(hw, E1000_DC); E1000_READ_REG(hw, E1000_SEC); E1000_READ_REG(hw, E1000_RLEC); E1000_READ_REG(hw, E1000_XONRXC); E1000_READ_REG(hw, E1000_XONTXC); E1000_READ_REG(hw, E1000_XOFFRXC); E1000_READ_REG(hw, E1000_XOFFTXC); E1000_READ_REG(hw, E1000_FCRUC); E1000_READ_REG(hw, E1000_GPRC); E1000_READ_REG(hw, E1000_BPRC); E1000_READ_REG(hw, E1000_MPRC); E1000_READ_REG(hw, E1000_GPTC); E1000_READ_REG(hw, E1000_GORCL); E1000_READ_REG(hw, E1000_GORCH); E1000_READ_REG(hw, E1000_GOTCL); E1000_READ_REG(hw, E1000_GOTCH); E1000_READ_REG(hw, E1000_RNBC); E1000_READ_REG(hw, E1000_RUC); E1000_READ_REG(hw, E1000_RFC); E1000_READ_REG(hw, E1000_ROC); E1000_READ_REG(hw, E1000_RJC); E1000_READ_REG(hw, E1000_TORL); E1000_READ_REG(hw, E1000_TORH); E1000_READ_REG(hw, E1000_TOTL); E1000_READ_REG(hw, E1000_TOTH); E1000_READ_REG(hw, E1000_TPR); E1000_READ_REG(hw, E1000_TPT); E1000_READ_REG(hw, E1000_MPTC); E1000_READ_REG(hw, E1000_BPTC); } /** * e1000_check_for_copper_link_generic - Check for link (Copper) * @hw: pointer to the HW structure * * Checks to see of the link status of the hardware has changed. If a * change in link status has been detected, then we read the PHY registers * to get the current speed/duplex if link exists. **/ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; bool link; DEBUGFUNC("e1000_check_for_copper_link"); /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. */ if (!mac->get_link_status) return E1000_SUCCESS; /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) return E1000_SUCCESS; /* No link detected */ mac->get_link_status = false; /* Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) DEBUGOUT("Error configuring flow control\n"); return ret_val; } /** * e1000_check_for_fiber_link_generic - Check for link (Fiber) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw; u32 ctrl; u32 status; s32 ret_val; DEBUGFUNC("e1000_check_for_fiber_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also * need to give auto-negotiation time to complete, in case the cable * was just plugged in. The autoneg_failed flag does this. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) { mac->autoneg_failed = true; return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = true; } return E1000_SUCCESS; } /** * e1000_check_for_serdes_link_generic - Check for link (Serdes) * @hw: pointer to the HW structure * * Checks for link up on the hardware. If link is not up and we have * a signal, then we need to force link up. **/ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 rxcw; u32 ctrl; u32 status; s32 ret_val; DEBUGFUNC("e1000_check_for_serdes_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), and our link partner is not trying to * auto-negotiate with us (we are receiving idles or data), * we need to force link up. We also need to give auto-negotiation * time to complete. */ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { if (!mac->autoneg_failed) { mac->autoneg_failed = true; return E1000_SUCCESS; } DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); /* Disable auto-negotiation in the TXCW register */ E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); /* Force link-up and also force full-duplex. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Configure Flow Control after forcing link up. */ ret_val = e1000_config_fc_after_link_up_generic(hw); if (ret_val) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. */ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); mac->serdes_has_link = true; } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { /* If we force link for non-auto-negotiation switch, check * link status based on MAC synchronization for internal * serdes media type. */ /* SYNCH bit and IV bit are sticky. */ usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; DEBUGOUT("SERDES: Link up - forced.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - force failed.\n"); } } if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) { status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) { /* SYNCH bit and IV bit are sticky, so reread rxcw. */ usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if (rxcw & E1000_RXCW_SYNCH) { if (!(rxcw & E1000_RXCW_IV)) { mac->serdes_has_link = true; DEBUGOUT("SERDES: Link up - autoneg completed successfully.\n"); } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - invalid codewords detected in autoneg.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - no sync.\n"); } } else { mac->serdes_has_link = false; DEBUGOUT("SERDES: Link down - autoneg failed\n"); } } return E1000_SUCCESS; } /** * e1000_set_default_fc_generic - Set flow control default values * @hw: pointer to the HW structure * * Read the EEPROM for the default values for flow control and store the * values. **/ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) { s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_set_default_fc_generic"); /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or * disabling auto-negotiation, and the direction of the * SW defined pins. If there is no SW over-ride of the flow * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) hw->fc.requested_mode = e1000_fc_none; else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) hw->fc.requested_mode = e1000_fc_tx_pause; else hw->fc.requested_mode = e1000_fc_full; return E1000_SUCCESS; } /** * e1000_setup_link_generic - Setup flow control and link settings * @hw: pointer to the HW structure * * Determines which flow control settings to use, then configures flow * control. Calls the appropriate media-specific link configuration * function. Assuming the adapter has a valid link partner, a valid link * should be established. Assumes the hardware has previously been reset * and the transmitter and receiver are not enabled. **/ s32 e1000_setup_link_generic(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_setup_link_generic"); /* In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; /* If requested flow control is set to default, set flow control * based on the EEPROM flow control settings. */ if (hw->fc.requested_mode == e1000_fc_default) { ret_val = e1000_set_default_fc_generic(hw); if (ret_val) return ret_val; } /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); /* Call the necessary media_type subroutine to configure the link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) return ret_val; /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. */ DEBUGOUT("Initializing the Flow Control address, type and timer regs\n"); E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE); E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH); E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW); E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); return e1000_set_fc_watermarks_generic(hw); } /** * e1000_commit_fc_settings_generic - Configure flow control * @hw: pointer to the HW structure * * Write the flow control settings to the Transmit Config Word Register (TXCW) * base on the flow control settings in e1000_mac_info. **/ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 txcw; DEBUGFUNC("e1000_commit_fc_settings_generic"); /* Check for a software override of the flow control settings, and * setup the device accordingly. If auto-negotiation is enabled, then * software will have to set the "PAUSE" bits to the correct value in * the Transmit Config Word Register (TXCW) and re-start auto- * negotiation. However, if auto-negotiation is disabled, then * software will have to manually configure the two flow control enable * bits in the CTRL register. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we * do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. */ switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control completely disabled by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: /* Rx Flow control is enabled and Tx Flow control is disabled * by a software over-ride. Since there really isn't a way to * advertise that we are capable of Rx Pause ONLY, we will * advertise that we support both symmetric and asymmetric Rx * PAUSE. Later, we will disable the adapter's ability to send * PAUSE frames. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is disabled, * by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; break; } E1000_WRITE_REG(hw, E1000_TXCW, txcw); mac->txcw = txcw; return E1000_SUCCESS; } /** * e1000_poll_fiber_serdes_link_generic - Poll for link up * @hw: pointer to the HW structure * * Polls for link up by reading the status register, if link fails to come * up with auto-negotiation, then the link is forced if a signal is detected. **/ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; u32 i, status; s32 ret_val; DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); /* If we have a signal (the cable is plugged in, or assumed true for * serdes media) then poll for a "Link-Up" indication in the Device * Status Register. Time-out if a link isn't seen in 500 milliseconds * seconds (Auto-negotiation should complete in less than 500 * milliseconds even if the other end is doing it in SW). */ for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { msec_delay(10); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) break; } if (i == FIBER_LINK_UP_LIMIT) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); mac->autoneg_failed = true; /* AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the * link up if we detect a signal. This will allow us to * communicate with non-autonegotiating link partners. */ ret_val = mac->ops.check_for_link(hw); if (ret_val) { DEBUGOUT("Error while checking for link\n"); return ret_val; } mac->autoneg_failed = false; } else { mac->autoneg_failed = false; DEBUGOUT("Valid Link Found\n"); } return E1000_SUCCESS; } /** * e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes * @hw: pointer to the HW structure * * Configures collision distance and flow control for fiber and serdes * links. Upon successful setup, poll for link. **/ s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) { u32 ctrl; s32 ret_val; DEBUGFUNC("e1000_setup_fiber_serdes_link_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Take the link out of reset */ ctrl &= ~E1000_CTRL_LRST; hw->mac.ops.config_collision_dist(hw); ret_val = e1000_commit_fc_settings_generic(hw); if (ret_val) return ret_val; /* Since auto-negotiation is enabled, take the link out of reset (the * link will be in reset, because we previously reset the chip). This * will restart auto-negotiation. If auto-negotiation is successful * then the link-up status bit will be set and the flow control enable * bits (RFCE and TFCE) will be set according to their negotiated value. */ DEBUGOUT("Auto-negotiation enabled\n"); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); msec_delay(1); /* For these adapters, the SW definable pin 1 is set when the optics * detect a signal. If we have a signal, then poll for a "Link-Up" * indication. */ if (hw->phy.media_type == e1000_media_type_internal_serdes || (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) { ret_val = e1000_poll_fiber_serdes_link_generic(hw); } else { DEBUGOUT("No signal detected\n"); } return ret_val; } /** * e1000_config_collision_dist_generic - Configure collision distance * @hw: pointer to the HW structure * * Configures the collision distance to the default value and is used * during link setup. **/ static void e1000_config_collision_dist_generic(struct e1000_hw *hw) { u32 tctl; DEBUGFUNC("e1000_config_collision_dist_generic"); tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_COLD; tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_FLUSH(hw); } /** * e1000_set_fc_watermarks_generic - Set flow control high/low watermarks * @hw: pointer to the HW structure * * Sets the flow control high/low threshold (watermark) registers. If * flow control XON frame transmission is enabled, then set XON frame * transmission as well. **/ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) { u32 fcrtl = 0, fcrth = 0; DEBUGFUNC("e1000_set_fc_watermarks_generic"); /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ if (hw->fc.current_mode & e1000_fc_tx_pause) { /* We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of * XON frames. */ fcrtl = hw->fc.low_water; if (hw->fc.send_xon) fcrtl |= E1000_FCRTL_XONE; fcrth = hw->fc.high_water; } E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl); E1000_WRITE_REG(hw, E1000_FCRTH, fcrth); return E1000_SUCCESS; } /** * e1000_force_mac_fc_generic - Force the MAC's flow control settings * @hw: pointer to the HW structure * * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the * device control register to reflect the adapter settings. TFCE and RFCE * need to be explicitly set by software when a copper PHY is used because * autonegotiation is managed by the PHY rather than the MAC. Software must * also configure these bits when link is forced on a fiber connection. **/ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_force_mac_fc_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Because we didn't get link via the internal auto-negotiation * mechanism (we either forced link or we got link via PHY * auto-neg), we have to manually enable/disable transmit an * receive flow control. * * The "Case" statement below enables/disable flow control * according to the "hw->fc.current_mode" parameter. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause * frames but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames * frames but we do not receive pause frames). * 3: Both Rx and Tx flow control (symmetric) is enabled. * other: No other values should be possible at this point. */ DEBUGOUT1("hw->fc.current_mode = %u\n", hw->fc.current_mode); switch (hw->fc.current_mode) { case e1000_fc_none: ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); break; case e1000_fc_rx_pause: ctrl &= (~E1000_CTRL_TFCE); ctrl |= E1000_CTRL_RFCE; break; case e1000_fc_tx_pause: ctrl &= (~E1000_CTRL_RFCE); ctrl |= E1000_CTRL_TFCE; break; case e1000_fc_full: ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } E1000_WRITE_REG(hw, E1000_CTRL, ctrl); return E1000_SUCCESS; } /** * e1000_config_fc_after_link_up_generic - Configures flow control after link * @hw: pointer to the HW structure * * Checks the status of auto-negotiation after link up to ensure that the * speed and duplex were not forced. If the link needed to be forced, then * flow control needs to be forced also. If auto-negotiation is enabled * and did not fail, then we configure flow control based on our link * partner. **/ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; DEBUGFUNC("e1000_config_fc_after_link_up_generic"); /* Check for the case where we have fiber media and auto-neg failed * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ if (mac->autoneg_failed) { if (hw->phy.media_type == e1000_media_type_fiber || hw->phy.media_type == e1000_media_type_internal_serdes) ret_val = e1000_force_mac_fc_generic(hw); } else { if (hw->phy.media_type == e1000_media_type_copper) ret_val = e1000_force_mac_fc_generic(hw); } if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } /* Check for the case where we have copper media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); if (ret_val) return ret_val; if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { DEBUGOUT("Copper PHY and Auto Neg has not completed.\n"); return ret_val; } /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (Address 4) and the Auto_Negotiation Base * Page Ability Register (Address 5) to determine how * flow control was negotiated. */ ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg); if (ret_val) return ret_val; ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg); if (ret_val) return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base * Page Ability Register (Address 5) determine flow control * for both the PHY and the link partner. The following * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, * 1999, describes these PAUSE resolution bits and how flow * control is determined based upon these settings. * NOTE: DC = Don't Care * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution *-------|---------|-------|---------|-------------------- * 0 | 0 | DC | DC | e1000_fc_none * 0 | 1 | 0 | DC | e1000_fc_none * 0 | 1 | 1 | 0 | e1000_fc_none * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * 1 | 0 | 0 | DC | e1000_fc_none * 1 | DC | 1 | DC | e1000_fc_full * 1 | 1 | 0 | 0 | e1000_fc_none * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * * Are both PAUSE bits set to 1? If so, this implies * Symmetric Flow Control is enabled at both ends. The * ASM_DIR bits are irrelevant per the spec. * * For Symmetric Flow Control: * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | DC | 1 | DC | E1000_fc_full * */ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause */ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause */ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } else { /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } /* Now we need to do one last check... If we auto- * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); if (ret_val) { DEBUGOUT("Error getting link speed and duplex\n"); return ret_val; } if (duplex == HALF_DUPLEX) hw->fc.current_mode = e1000_fc_none; /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000_force_mac_fc_generic(hw); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } } /* Check for the case where we have SerDes media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_internal_serdes) && mac->autoneg) { /* Read the PCS_LSTS and check to see if AutoNeg * has completed. */ pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT); if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { DEBUGOUT("PCS Auto Neg has not completed.\n"); return ret_val; } /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (PCS_ANADV) and the Auto_Negotiation Base * Page Ability Register (PCS_LPAB) to determine how * flow control was negotiated. */ pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB); /* Two bits in the Auto Negotiation Advertisement Register * (PCS_ANADV) and two bits in the Auto Negotiation Base * Page Ability Register (PCS_LPAB) determine flow control * for both the PHY and the link partner. The following * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, * 1999, describes these PAUSE resolution bits and how flow * control is determined based upon these settings. * NOTE: DC = Don't Care * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution *-------|---------|-------|---------|-------------------- * 0 | 0 | DC | DC | e1000_fc_none * 0 | 1 | 0 | DC | e1000_fc_none * 0 | 1 | 1 | 0 | e1000_fc_none * 0 | 1 | 1 | 1 | e1000_fc_tx_pause * 1 | 0 | 0 | DC | e1000_fc_none * 1 | DC | 1 | DC | e1000_fc_full * 1 | 1 | 0 | 0 | e1000_fc_none * 1 | 1 | 0 | 1 | e1000_fc_rx_pause * * Are both PAUSE bits set to 1? If so, this implies * Symmetric Flow Control is enabled at both ends. The * ASM_DIR bits are irrelevant per the spec. * * For Symmetric Flow Control: * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | DC | 1 | DC | e1000_fc_full * */ if ((pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; DEBUGOUT("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 0 | 1 | 1 | 1 | e1000_fc_tx_pause */ else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_adv_reg & E1000_TXCW_ASM_DIR) && (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result *-------|---------|-------|---------|-------------------- * 1 | 1 | 0 | 1 | e1000_fc_rx_pause */ else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && (pcs_adv_reg & E1000_TXCW_ASM_DIR) && !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } else { /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL); pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg); ret_val = e1000_force_mac_fc_generic(hw); if (ret_val) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } } return E1000_SUCCESS; } /** * e1000_get_speed_and_duplex_copper_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Read the status register for the current speed/duplex and store the current * speed and duplex for copper connections. **/ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex) { u32 status; DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic"); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_SPEED_1000) { *speed = SPEED_1000; DEBUGOUT("1000 Mbs, "); } else if (status & E1000_STATUS_SPEED_100) { *speed = SPEED_100; DEBUGOUT("100 Mbs, "); } else { *speed = SPEED_10; DEBUGOUT("10 Mbs, "); } if (status & E1000_STATUS_FD) { *duplex = FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } else { *duplex = HALF_DUPLEX; DEBUGOUT("Half Duplex\n"); } return E1000_SUCCESS; } /** * e1000_get_speed_and_duplex_fiber_generic - Retrieve current speed/duplex * @hw: pointer to the HW structure * @speed: stores the current speed * @duplex: stores the current duplex * * Sets the speed and duplex to gigabit full duplex (the only possible option) * for fiber/serdes links. **/ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw E1000_UNUSEDARG *hw, u16 *speed, u16 *duplex) { DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic"); *speed = SPEED_1000; *duplex = FULL_DUPLEX; return E1000_SUCCESS; } /** * e1000_get_hw_semaphore_generic - Acquire hardware semaphore * @hw: pointer to the HW structure * * Acquire the HW semaphore to access the PHY or NVM **/ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_generic"); /* Get the SW semaphore */ while (i < timeout) { swsm = E1000_READ_REG(hw, E1000_SWSM); if (!(swsm & E1000_SWSM_SMBI)) break; usec_delay(50); i++; } if (i == timeout) { DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); return -E1000_ERR_NVM; } /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI); /* Semaphore acquired if bit latched */ if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI) break; usec_delay(50); } if (i == timeout) { /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_put_hw_semaphore_generic - Release hardware semaphore * @hw: pointer to the HW structure * * Release hardware semaphore used to access the PHY or NVM **/ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw) { u32 swsm; DEBUGFUNC("e1000_put_hw_semaphore_generic"); swsm = E1000_READ_REG(hw, E1000_SWSM); swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); E1000_WRITE_REG(hw, E1000_SWSM, swsm); } /** * e1000_get_auto_rd_done_generic - Check for auto read completion * @hw: pointer to the HW structure * * Check EEPROM for Auto Read done bit. **/ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw) { s32 i = 0; DEBUGFUNC("e1000_get_auto_rd_done_generic"); while (i < AUTO_READ_DONE_TIMEOUT) { if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_AUTO_RD) break; msec_delay(1); i++; } if (i == AUTO_READ_DONE_TIMEOUT) { DEBUGOUT("Auto read by HW from NVM has not completed.\n"); return -E1000_ERR_RESET; } return E1000_SUCCESS; } /** * e1000_valid_led_default_generic - Verify a valid default LED config * @hw: pointer to the HW structure * @data: pointer to the NVM (EEPROM) * * Read the EEPROM for the current default LED configuration. If the * LED configuration is not valid, set to a valid LED configuration. **/ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_valid_led_default_generic"); ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT; return E1000_SUCCESS; } /** * e1000_id_led_init_generic - * @hw: pointer to the HW structure * **/ s32 e1000_id_led_init_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val; const u32 ledctl_mask = 0x000000FF; const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; u16 data, i, temp; const u16 led_mask = 0x0F; DEBUGFUNC("e1000_id_led_init_generic"); ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) return ret_val; mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; mac->ledctl_mode2 = mac->ledctl_default; for (i = 0; i < 4; i++) { temp = (data >> (i << 2)) & led_mask; switch (temp) { case ID_LED_ON1_DEF2: case ID_LED_ON1_ON2: case ID_LED_ON1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_on << (i << 3); break; case ID_LED_OFF1_DEF2: case ID_LED_OFF1_ON2: case ID_LED_OFF1_OFF2: mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode1 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } switch (temp) { case ID_LED_DEF1_ON2: case ID_LED_ON1_ON2: case ID_LED_OFF1_ON2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_on << (i << 3); break; case ID_LED_DEF1_OFF2: case ID_LED_ON1_OFF2: case ID_LED_OFF1_OFF2: mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); mac->ledctl_mode2 |= ledctl_off << (i << 3); break; default: /* Do nothing */ break; } } return E1000_SUCCESS; } /** * e1000_setup_led_generic - Configures SW controllable LED * @hw: pointer to the HW structure * * This prepares the SW controllable LED for use and saves the current state * of the LED so it can be later restored. **/ s32 e1000_setup_led_generic(struct e1000_hw *hw) { u32 ledctl; DEBUGFUNC("e1000_setup_led_generic"); if (hw->mac.ops.setup_led != e1000_setup_led_generic) return -E1000_ERR_CONFIG; if (hw->phy.media_type == e1000_media_type_fiber) { ledctl = E1000_READ_REG(hw, E1000_LEDCTL); hw->mac.ledctl_default = ledctl; /* Turn off LED0 */ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED0_MODE_MASK); ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl); } else if (hw->phy.media_type == e1000_media_type_copper) { E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); } return E1000_SUCCESS; } /** * e1000_cleanup_led_generic - Set LED config to default operation * @hw: pointer to the HW structure * * Remove the current LED configuration and set the LED configuration * to the default value, saved from the EEPROM. **/ s32 e1000_cleanup_led_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_cleanup_led_generic"); E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); return E1000_SUCCESS; } /** * e1000_blink_led_generic - Blink LED * @hw: pointer to the HW structure * * Blink the LEDs which are set to be on. **/ s32 e1000_blink_led_generic(struct e1000_hw *hw) { u32 ledctl_blink = 0; u32 i; DEBUGFUNC("e1000_blink_led_generic"); if (hw->phy.media_type == e1000_media_type_fiber) { /* always blink LED0 for PCI-E fiber */ ledctl_blink = E1000_LEDCTL_LED0_BLINK | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { /* Set the blink bit for each LED that's "on" (0x0E) * (or "off" if inverted) in ledctl_mode2. The blink * logic in hardware only works when mode is set to "on" * so it must be changed accordingly when the mode is * "off" and inverted. */ ledctl_blink = hw->mac.ledctl_mode2; for (i = 0; i < 32; i += 8) { u32 mode = (hw->mac.ledctl_mode2 >> i) & E1000_LEDCTL_LED0_MODE_MASK; u32 led_default = hw->mac.ledctl_default >> i; if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && (mode == E1000_LEDCTL_MODE_LED_ON)) || ((led_default & E1000_LEDCTL_LED0_IVRT) && (mode == E1000_LEDCTL_MODE_LED_OFF))) { ledctl_blink &= ~(E1000_LEDCTL_LED0_MODE_MASK << i); ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_MODE_LED_ON) << i; } } } E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); return E1000_SUCCESS; } /** * e1000_led_on_generic - Turn LED on * @hw: pointer to the HW structure * * Turn LED on. **/ s32 e1000_led_on_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_led_on_generic"); switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); break; case e1000_media_type_copper: E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); break; default: break; } return E1000_SUCCESS; } /** * e1000_led_off_generic - Turn LED off * @hw: pointer to the HW structure * * Turn LED off. **/ s32 e1000_led_off_generic(struct e1000_hw *hw) { u32 ctrl; DEBUGFUNC("e1000_led_off_generic"); switch (hw->phy.media_type) { case e1000_media_type_fiber: ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); break; case e1000_media_type_copper: E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); break; default: break; } return E1000_SUCCESS; } /** * e1000_set_pcie_no_snoop_generic - Set PCI-express capabilities * @hw: pointer to the HW structure * @no_snoop: bitmap of snoop events * * Set the PCI-express register to snoop for events enabled in 'no_snoop'. **/ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop) { u32 gcr; DEBUGFUNC("e1000_set_pcie_no_snoop_generic"); if (no_snoop) { gcr = E1000_READ_REG(hw, E1000_GCR); gcr &= ~(PCIE_NO_SNOOP_ALL); gcr |= no_snoop; E1000_WRITE_REG(hw, E1000_GCR, gcr); } } /** * e1000_disable_pcie_master_generic - Disables PCI-express master access * @hw: pointer to the HW structure * * Returns E1000_SUCCESS if successful, else returns -10 * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused * the master requests to be disabled. * * Disables PCI-Express master access and verifies there are no pending * requests. **/ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw) { u32 ctrl; s32 timeout = MASTER_DISABLE_TIMEOUT; DEBUGFUNC("e1000_disable_pcie_master_generic"); ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); while (timeout) { if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) break; usec_delay(100); timeout--; } if (!timeout) { DEBUGOUT("Master requests are pending.\n"); return -E1000_ERR_MASTER_REQUESTS_PENDING; } return E1000_SUCCESS; } /** * e1000_reset_adaptive_generic - Reset Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Reset the Adaptive Interframe Spacing throttle to default values. **/ void e1000_reset_adaptive_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_reset_adaptive_generic"); if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); return; } mac->current_ifs_val = 0; mac->ifs_min_val = IFS_MIN; mac->ifs_max_val = IFS_MAX; mac->ifs_step_size = IFS_STEP; mac->ifs_ratio = IFS_RATIO; mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } /** * e1000_update_adaptive_generic - Update Adaptive Interframe Spacing * @hw: pointer to the HW structure * * Update the Adaptive Interframe Spacing Throttle value based on the * time between transmitted packets and time between collisions. **/ void e1000_update_adaptive_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; DEBUGFUNC("e1000_update_adaptive_generic"); if (!mac->adaptive_ifs) { DEBUGOUT("Not in Adaptive IFS mode!\n"); return; } if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { if (mac->tx_packet_delta > MIN_NUM_XMITS) { mac->in_ifs_mode = true; if (mac->current_ifs_val < mac->ifs_max_val) { if (!mac->current_ifs_val) mac->current_ifs_val = mac->ifs_min_val; else mac->current_ifs_val += mac->ifs_step_size; E1000_WRITE_REG(hw, E1000_AIT, mac->current_ifs_val); } } } else { if (mac->in_ifs_mode && (mac->tx_packet_delta <= MIN_NUM_XMITS)) { mac->current_ifs_val = 0; mac->in_ifs_mode = false; E1000_WRITE_REG(hw, E1000_AIT, 0); } } } /** * e1000_validate_mdi_setting_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * * Verify that when not using auto-negotiation that MDI/MDIx is correctly * set, which is forced to MDI mode only. **/ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) { DEBUGFUNC("e1000_validate_mdi_setting_generic"); if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) { DEBUGOUT("Invalid MDI setting detected\n"); hw->phy.mdix = 1; return -E1000_ERR_CONFIG; } return E1000_SUCCESS; } /** * e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings * @hw: pointer to the HW structure * * Validate the MDI/MDIx setting, allowing for auto-crossover during forced * operation. **/ s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic"); return E1000_SUCCESS; } /** * e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register * @hw: pointer to the HW structure * @reg: 32bit register offset such as E1000_SCTL * @offset: register offset to write to * @data: data to write at register offset * * Writes an address/data control type register. There are several of these * and they all have the format address << 8 | data and bit 31 is polled for * completion. **/ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data) { u32 i, regvalue = 0; DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic"); /* Set up the address and data */ regvalue = ((u32)data) | (offset << E1000_GEN_CTL_ADDRESS_SHIFT); E1000_WRITE_REG(hw, reg, regvalue); /* Poll the ready bit to see if the MDI read completed */ for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { usec_delay(5); regvalue = E1000_READ_REG(hw, reg); if (regvalue & E1000_GEN_CTL_READY) break; } if (!(regvalue & E1000_GEN_CTL_READY)) { DEBUGOUT1("Reg %08x did not indicate ready\n", reg); return -E1000_ERR_PHY; } return E1000_SUCCESS; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_mac.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_MAC_H_ #define _E1000_MAC_H_ void e1000_init_mac_ops_generic(struct e1000_hw *hw); void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d); bool e1000_null_mng_mode(struct e1000_hw *hw); void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a); void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b); void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a); s32 e1000_blink_led_generic(struct e1000_hw *hw); s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw); s32 e1000_cleanup_led_generic(struct e1000_hw *hw); s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw); s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw); s32 e1000_force_mac_fc_generic(struct e1000_hw *hw); s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw); s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw); void e1000_set_lan_id_single_port(struct e1000_hw *hw); s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw); s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw, u16 *speed, u16 *duplex); s32 e1000_id_led_init_generic(struct e1000_hw *hw); s32 e1000_led_on_generic(struct e1000_hw *hw); s32 e1000_led_off_generic(struct e1000_hw *hw); void e1000_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_setup_led_generic(struct e1000_hw *hw); s32 e1000_setup_link_generic(struct e1000_hw *hw); s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr); void e1000_clear_hw_cntrs_base_generic(struct e1000_hw *hw); void e1000_clear_vfta_generic(struct e1000_hw *hw); void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count); void e1000_put_hw_semaphore_generic(struct e1000_hw *hw); s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); void e1000_reset_adaptive_generic(struct e1000_hw *hw); void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop); void e1000_update_adaptive_generic(struct e1000_hw *hw); void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_manage.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" /** * e1000_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM * @length: size of EEPROM to calculate a checksum for * * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ u8 e1000_calculate_checksum(u8 *buffer, u32 length) { u32 i; u8 sum = 0; DEBUGFUNC("e1000_calculate_checksum"); if (!buffer) return 0; for (i = 0; i < length; i++) sum += buffer[i]; return (u8) (0 - sum); } /** * e1000_mng_enable_host_if_generic - Checks host interface is enabled * @hw: pointer to the HW structure * * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND * * This function checks whether the HOST IF is enabled for command operation * and also checks whether the previous command is completed. It busy waits * in case of previous command is not completed. **/ s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) { u32 hicr; u8 i; DEBUGFUNC("e1000_mng_enable_host_if_generic"); if (!hw->mac.arc_subsystem_valid) { DEBUGOUT("ARC subsystem not valid.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* check the previous command is completed */ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay_irq(1); } if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { DEBUGOUT("Previous command timeout failed .\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } return E1000_SUCCESS; } /** * e1000_check_mng_mode_generic - Generic check management mode * @hw: pointer to the HW structure * * Reads the firmware semaphore register and returns true (>0) if * manageability is enabled, else false (0). **/ bool e1000_check_mng_mode_generic(struct e1000_hw *hw) { u32 fwsm = E1000_READ_REG(hw, E1000_FWSM); DEBUGFUNC("e1000_check_mng_mode_generic"); return (fwsm & E1000_FWSM_MODE_MASK) == (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); } /** * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx * @hw: pointer to the HW structure * * Enables packet filtering on transmit packets if manageability is enabled * and host interface is enabled. **/ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) { struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; u32 *buffer = (u32 *)&hw->mng_cookie; u32 offset; s32 ret_val, hdr_csum, csum; u8 i, len; DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); hw->mac.tx_pkt_filtering = true; /* No manageability, no filtering */ if (!hw->mac.ops.check_mng_mode(hw)) { hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /* If we can't read from the host interface for whatever * reason, disable filtering. */ ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val != E1000_SUCCESS) { hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /* Read in the header. Length and offset are in dwords. */ len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; for (i = 0; i < len; i++) *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i); hdr_csum = hdr->checksum; hdr->checksum = 0; csum = e1000_calculate_checksum((u8 *)hdr, E1000_MNG_DHCP_COOKIE_LENGTH); /* If either the checksums or signature don't match, then * the cookie area isn't considered valid, in which case we * take the safe route of assuming Tx filtering is enabled. */ if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { hw->mac.tx_pkt_filtering = true; return hw->mac.tx_pkt_filtering; } /* Cookie area is valid, make the final check for filtering. */ if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) hw->mac.tx_pkt_filtering = false; return hw->mac.tx_pkt_filtering; } /** * e1000_mng_write_cmd_header_generic - Writes manageability command header * @hw: pointer to the HW structure * @hdr: pointer to the host interface command header * * Writes the command header after does the checksum calculation. **/ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { u16 i, length = sizeof(struct e1000_host_mng_command_header); DEBUGFUNC("e1000_mng_write_cmd_header_generic"); /* Write the whole command header structure with new checksum. */ hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); length >>= 2; /* Write the relevant command block into the ram area. */ for (i = 0; i < length; i++) { E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *) hdr + i)); E1000_WRITE_FLUSH(hw); } return E1000_SUCCESS; } /** * e1000_mng_host_if_write_generic - Write to the manageability host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface buffer * @length: size of the buffer * @offset: location in the buffer to write to * @sum: sum of the data (not checksum) * * This function writes the buffer content at the offset given on the host if. * It also does alignment considerations to do the writes in most efficient * way. Also fills up the sum of the buffer in *buffer parameter. **/ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { u8 *tmp; u8 *bufptr = buffer; u32 data = 0; u16 remaining, i, j, prev_bytes; DEBUGFUNC("e1000_mng_host_if_write_generic"); /* sum = only sum of the data and it is not checksum */ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) return -E1000_ERR_PARAM; tmp = (u8 *)&data; prev_bytes = offset & 0x3; offset >>= 2; if (prev_bytes) { data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); for (j = prev_bytes; j < sizeof(u32); j++) { *(tmp + j) = *bufptr++; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); length -= j - prev_bytes; offset++; } remaining = length & 0x3; length -= remaining; /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant command block into the * ram area. */ for (i = 0; i < length; i++) { for (j = 0; j < sizeof(u32); j++) { *(tmp + j) = *bufptr++; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); } if (remaining) { for (j = 0; j < sizeof(u32); j++) { if (j < remaining) *(tmp + j) = *bufptr++; else *(tmp + j) = 0; *sum += *(tmp + j); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); } return E1000_SUCCESS; } /** * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface * @hw: pointer to the HW structure * @buffer: pointer to the host interface * @length: size of the buffer * * Writes the DHCP information to the host interface. **/ s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length) { struct e1000_host_mng_command_header hdr; s32 ret_val; u32 hicr; DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; hdr.command_length = length; hdr.reserved1 = 0; hdr.reserved2 = 0; hdr.checksum = 0; /* Enable the host interface */ ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val) return ret_val; /* Populate the host interface with the contents of "buffer". */ ret_val = e1000_mng_host_if_write_generic(hw, buffer, length, sizeof(hdr), &(hdr.checksum)); if (ret_val) return ret_val; /* Write the manageability command header */ ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr); if (ret_val) return ret_val; /* Tell the ARC a new command is pending. */ hicr = E1000_READ_REG(hw, E1000_HICR); E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); return E1000_SUCCESS; } /** * e1000_enable_mng_pass_thru - Check if management passthrough is needed * @hw: pointer to the HW structure * * Verifies the hardware needs to leave interface enabled so that frames can * be directed to and from the management interface. **/ bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) { u32 manc; u32 fwsm, factps; DEBUGFUNC("e1000_enable_mng_pass_thru"); if (!hw->mac.asf_firmware_present) return false; manc = E1000_READ_REG(hw, E1000_MANC); if (!(manc & E1000_MANC_RCV_TCO_EN)) return false; if (hw->mac.has_fwsm) { fwsm = E1000_READ_REG(hw, E1000_FWSM); factps = E1000_READ_REG(hw, E1000_FACTPS); if (!(factps & E1000_FACTPS_MNGCG) && ((fwsm & E1000_FWSM_MODE_MASK) == (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) return true; } else if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) { return true; } return false; } /** * e1000_host_interface_command - Writes buffer to host interface * @hw: pointer to the HW structure * @buffer: contains a command to write * @length: the byte length of the buffer, must be multiple of 4 bytes * * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS * else returns E1000_ERR_HOST_INTERFACE_COMMAND. **/ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) { u32 hicr, i; DEBUGFUNC("e1000_host_interface_command"); if (!(hw->mac.arc_subsystem_valid)) { DEBUGOUT("Hardware doesn't support host interface command.\n"); return E1000_SUCCESS; } if (!hw->mac.asf_firmware_present) { DEBUGOUT("Firmware is not present.\n"); return E1000_SUCCESS; } if (length == 0 || length & 0x3 || length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) { DEBUGOUT("Buffer length failure.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < length; i++) E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *)buffer + i)); /* Setting this bit tells the ARC that a new command is pending. */ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay(1); } /* Check command successful completion. */ if (i == E1000_HI_COMMAND_TIMEOUT || (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) { DEBUGOUT("Command has failed with no status valid.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } for (i = 0; i < length; i++) *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i); return E1000_SUCCESS; } /** * e1000_load_firmware - Writes proxy FW code buffer to host interface * and execute. * @hw: pointer to the HW structure * @buffer: contains a firmware to write * @length: the byte length of the buffer, must be multiple of 4 bytes * * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND. **/ s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length) { u32 hicr, hibba, fwsm, icr, i; DEBUGFUNC("e1000_load_firmware"); if (hw->mac.type < e1000_i210) { DEBUGOUT("Hardware doesn't support loading FW by the driver\n"); return -E1000_ERR_CONFIG; } /* Check that the host interface is enabled. */ hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_EN)) { DEBUGOUT("E1000_HOST_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) { DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n"); return -E1000_ERR_CONFIG; } if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) { DEBUGOUT("Buffer length failure.\n"); return -E1000_ERR_INVALID_ARGUMENT; } /* Clear notification from ROM-FW by reading ICR register */ icr = E1000_READ_REG(hw, E1000_ICR_V2); /* Reset ROM-FW */ hicr = E1000_READ_REG(hw, E1000_HICR); hicr |= E1000_HICR_FW_RESET_ENABLE; E1000_WRITE_REG(hw, E1000_HICR, hicr); hicr |= E1000_HICR_FW_RESET; E1000_WRITE_REG(hw, E1000_HICR, hicr); E1000_WRITE_FLUSH(hw); /* Wait till MAC notifies about its readiness after ROM-FW reset */ for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) { icr = E1000_READ_REG(hw, E1000_ICR_V2); if (icr & E1000_ICR_MNG) break; msec_delay(1); } /* Check for timeout */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("FW reset failed.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Wait till MAC is ready to accept new FW code */ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { fwsm = E1000_READ_REG(hw, E1000_FWSM); if ((fwsm & E1000_FWSM_FW_VALID) && ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT == E1000_FWSM_HI_EN_ONLY_MODE)) break; msec_delay(1); } /* Check for timeout */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("FW reset failed.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } /* Calculate length in DWORDs */ length >>= 2; /* The device driver writes the relevant FW code block * into the ram area in DWORDs via 1kB ram addressing window. */ for (i = 0; i < length; i++) { if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) { /* Point to correct 1kB ram window */ hibba = E1000_HI_FW_BASE_ADDRESS + ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) * (i / E1000_HI_FW_BLOCK_DWORD_LENGTH)); E1000_WRITE_REG(hw, E1000_HIBBA, hibba); } E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i % E1000_HI_FW_BLOCK_DWORD_LENGTH, *((u32 *)buffer + i)); } /* Setting this bit tells the ARC that a new FW is ready to execute. */ hicr = E1000_READ_REG(hw, E1000_HICR); E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { hicr = E1000_READ_REG(hw, E1000_HICR); if (!(hicr & E1000_HICR_C)) break; msec_delay(1); } /* Check for successful FW start. */ if (i == E1000_HI_COMMAND_TIMEOUT) { DEBUGOUT("New FW did not start within timeout period.\n"); return -E1000_ERR_HOST_INTERFACE_COMMAND; } return E1000_SUCCESS; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_manage.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_MANAGE_H_ #define _E1000_MANAGE_H_ bool e1000_check_mng_mode_generic(struct e1000_hw *hw); bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw); s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw); s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum); s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr); s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, u16 length); bool e1000_enable_mng_pass_thru(struct e1000_hw *hw); u8 e1000_calculate_checksum(u8 *buffer, u32 length); s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length); s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length); enum e1000_mng_mode { e1000_mng_mode_none = 0, e1000_mng_mode_asf, e1000_mng_mode_pt, e1000_mng_mode_ipmi, e1000_mng_mode_host_if_only }; #define E1000_FACTPS_MNGCG 0x20000000 #define E1000_FWSM_MODE_MASK 0xE #define E1000_FWSM_MODE_SHIFT 1 #define E1000_FWSM_FW_VALID 0x00008000 #define E1000_FWSM_HI_EN_ONLY_MODE 0x4 #define E1000_MNG_IAMT_MODE 0x3 #define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 #define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 #define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 #define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 #define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 #define E1000_VFTA_ENTRY_SHIFT 5 #define E1000_VFTA_ENTRY_MASK 0x7F #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F #define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ #define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ #define E1000_HI_COMMAND_TIMEOUT 500 /* Process HI cmd limit */ #define E1000_HI_FW_BASE_ADDRESS 0x10000 #define E1000_HI_FW_MAX_LENGTH (64 * 1024) /* Num of bytes */ #define E1000_HI_FW_BLOCK_DWORD_LENGTH 256 /* Num of DWORDs per page */ #define E1000_HICR_MEMORY_BASE_EN 0x200 /* MB Enable bit - RO */ #define E1000_HICR_EN 0x01 /* Enable bit - RO */ /* Driver sets this bit when done to put command in RAM */ #define E1000_HICR_C 0x02 #define E1000_HICR_SV 0x04 /* Status Validity */ #define E1000_HICR_FW_RESET_ENABLE 0x40 #define E1000_HICR_FW_RESET 0x80 /* Intel(R) Active Management Technology signature */ #define E1000_IAMT_SIGNATURE 0x544D4149 #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_mbx.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_mbx.h" /** * e1000_null_mbx_check_for_flag - No-op function, return 0 * @hw: pointer to the HW structure **/ static s32 e1000_null_mbx_check_for_flag(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG mbx_id) { DEBUGFUNC("e1000_null_mbx_check_flag"); return E1000_SUCCESS; } /** * e1000_null_mbx_transact - No-op function, return 0 * @hw: pointer to the HW structure **/ static s32 e1000_null_mbx_transact(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG *msg, u16 E1000_UNUSEDARG size, u16 E1000_UNUSEDARG mbx_id) { DEBUGFUNC("e1000_null_mbx_rw_msg"); return E1000_SUCCESS; } /** * e1000_read_mbx - Reads a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to read * * returns SUCCESS if it successfully read message from buffer **/ s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_read_mbx"); /* limit read to size of mailbox */ if (size > mbx->size) size = mbx->size; if (mbx->ops.read) ret_val = mbx->ops.read(hw, msg, size, mbx_id); return ret_val; } /** * e1000_write_mbx - Write a message to the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer **/ s32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_mbx"); if (size > mbx->size) ret_val = -E1000_ERR_MBX; else if (mbx->ops.write) ret_val = mbx->ops.write(hw, msg, size, mbx_id); return ret_val; } /** * e1000_check_for_msg - checks to see if someone sent us mail * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_msg"); if (mbx->ops.check_for_msg) ret_val = mbx->ops.check_for_msg(hw, mbx_id); return ret_val; } /** * e1000_check_for_ack - checks to see if someone sent us ACK * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_ack"); if (mbx->ops.check_for_ack) ret_val = mbx->ops.check_for_ack(hw, mbx_id); return ret_val; } /** * e1000_check_for_rst - checks to see if other side has reset * @hw: pointer to the HW structure * @mbx_id: id of mailbox to check * * returns SUCCESS if the Status bit was found or else ERR_MBX **/ s32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_rst"); if (mbx->ops.check_for_rst) ret_val = mbx->ops.check_for_rst(hw, mbx_id); return ret_val; } /** * e1000_poll_for_msg - Wait for message notification * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification **/ static s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("e1000_poll_for_msg"); if (!countdown || !mbx->ops.check_for_msg) goto out; while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } /* if we failed, all future posted messages fail until reset */ if (!countdown) mbx->timeout = 0; out: return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; } /** * e1000_poll_for_ack - Wait for message acknowledgement * @hw: pointer to the HW structure * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message acknowledgement **/ static s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; int countdown = mbx->timeout; DEBUGFUNC("e1000_poll_for_ack"); if (!countdown || !mbx->ops.check_for_ack) goto out; while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { countdown--; if (!countdown) break; usec_delay(mbx->usec_delay); } /* if we failed, all future posted messages fail until reset */ if (!countdown) mbx->timeout = 0; out: return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; } /** * e1000_read_posted_mbx - Wait for message notification and receive message * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully received a message notification and * copied it into the receive buffer. **/ s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_read_posted_mbx"); if (!mbx->ops.read) goto out; ret_val = e1000_poll_for_msg(hw, mbx_id); /* if ack received read message, otherwise we timed out */ if (!ret_val) ret_val = mbx->ops.read(hw, msg, size, mbx_id); out: return ret_val; } /** * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @mbx_id: id of mailbox to write * * returns SUCCESS if it successfully copied message into the buffer and * received an ack to that message within delay * timeout period **/ s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { struct e1000_mbx_info *mbx = &hw->mbx; s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_write_posted_mbx"); /* exit if either we can't write or there isn't a defined timeout */ if (!mbx->ops.write || !mbx->timeout) goto out; /* send msg */ ret_val = mbx->ops.write(hw, msg, size, mbx_id); /* if msg sent wait until we receive an ack */ if (!ret_val) ret_val = e1000_poll_for_ack(hw, mbx_id); out: return ret_val; } /** * e1000_init_mbx_ops_generic - Initialize mbx function pointers * @hw: pointer to the HW structure * * Sets the function pointers to no-op functions **/ void e1000_init_mbx_ops_generic(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; mbx->ops.init_params = e1000_null_ops_generic; mbx->ops.read = e1000_null_mbx_transact; mbx->ops.write = e1000_null_mbx_transact; mbx->ops.check_for_msg = e1000_null_mbx_check_for_flag; mbx->ops.check_for_ack = e1000_null_mbx_check_for_flag; mbx->ops.check_for_rst = e1000_null_mbx_check_for_flag; mbx->ops.read_posted = e1000_read_posted_mbx; mbx->ops.write_posted = e1000_write_posted_mbx; } static s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask) { u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR); s32 ret_val = -E1000_ERR_MBX; if (mbvficr & mask) { ret_val = E1000_SUCCESS; E1000_WRITE_REG(hw, E1000_MBVFICR, mask); } return ret_val; } /** * e1000_check_for_msg_pf - checks to see if the VF has sent mail * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ static s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_msg_pf"); if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { ret_val = E1000_SUCCESS; hw->mbx.stats.reqs++; } return ret_val; } /** * e1000_check_for_ack_pf - checks to see if the VF has ACKed * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ static s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_ack_pf"); if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { ret_val = E1000_SUCCESS; hw->mbx.stats.acks++; } return ret_val; } /** * e1000_check_for_rst_pf - checks to see if the VF has reset * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ static s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) { u32 vflre = E1000_READ_REG(hw, E1000_VFLRE); s32 ret_val = -E1000_ERR_MBX; DEBUGFUNC("e1000_check_for_rst_pf"); if (vflre & (1 << vf_number)) { ret_val = E1000_SUCCESS; E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number)); hw->mbx.stats.rsts++; } return ret_val; } /** * e1000_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) { s32 ret_val = -E1000_ERR_MBX; u32 p2v_mailbox; DEBUGFUNC("e1000_obtain_mbx_lock_pf"); /* Take ownership of the buffer */ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number)); if (p2v_mailbox & E1000_P2VMAILBOX_PFU) ret_val = E1000_SUCCESS; return ret_val; } /** * e1000_write_mbx_pf - Places a message in the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * returns SUCCESS if it successfully copied message into the buffer **/ static s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("e1000_write_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_write; /* flush msg and acks as we are overwriting the message buffer */ e1000_check_for_msg_pf(hw, vf_number); e1000_check_for_ack_pf(hw, vf_number); /* copy the caller specified message to the mailbox memory buffer */ for (i = 0; i < size; i++) E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]); /* Interrupt VF to tell it a message has been sent and release buffer*/ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); /* update stats */ hw->mbx.stats.msgs_tx++; out_no_write: return ret_val; } /** * e1000_read_mbx_pf - Read a message from the mailbox * @hw: pointer to the HW structure * @msg: The message buffer * @size: Length of buffer * @vf_number: the VF index * * This function copies a message from the mailbox buffer to the caller's * memory buffer. The presumption is that the caller knows that there was * a message due to a VF request so no polling for message is needed. **/ static s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, u16 vf_number) { s32 ret_val; u16 i; DEBUGFUNC("e1000_read_mbx_pf"); /* lock the mailbox to prevent pf/vf race condition */ ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number); if (ret_val) goto out_no_read; /* copy the message to the mailbox memory buffer */ for (i = 0; i < size; i++) msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i); /* Acknowledge the message and release buffer */ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); /* update stats */ hw->mbx.stats.msgs_rx++; out_no_read: return ret_val; } /** * e1000_init_mbx_params_pf - set initial values for pf mailbox * @hw: pointer to the HW structure * * Initializes the hw->mbx struct to correct values for pf mailbox */ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw) { struct e1000_mbx_info *mbx = &hw->mbx; switch (hw->mac.type) { case e1000_82576: case e1000_i350: case e1000_i354: mbx->timeout = 0; mbx->usec_delay = 0; mbx->size = E1000_VFMAILBOX_SIZE; mbx->ops.read = e1000_read_mbx_pf; mbx->ops.write = e1000_write_mbx_pf; mbx->ops.read_posted = e1000_read_posted_mbx; mbx->ops.write_posted = e1000_write_posted_mbx; mbx->ops.check_for_msg = e1000_check_for_msg_pf; mbx->ops.check_for_ack = e1000_check_for_ack_pf; mbx->ops.check_for_rst = e1000_check_for_rst_pf; mbx->stats.msgs_tx = 0; mbx->stats.msgs_rx = 0; mbx->stats.reqs = 0; mbx->stats.acks = 0; mbx->stats.rsts = 0; default: return E1000_SUCCESS; } } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_mbx.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_MBX_H_ #define _E1000_MBX_H_ #include "e1000_api.h" #define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */ #define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ #define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ #define E1000_MBVFICR_VFREQ_MASK 0x000000FF /* bits for VF messages */ #define E1000_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ #define E1000_MBVFICR_VFACK_MASK 0x00FF0000 /* bits for VF acks */ #define E1000_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ #define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ /* If it's a E1000_VF_* msg then it originates in the VF and is sent to the * PF. The reverse is true if it is E1000_PF_*. * Message ACK's are the value or'd with 0xF0000000 */ /* Msgs below or'd with this are the ACK */ #define E1000_VT_MSGTYPE_ACK 0x80000000 /* Msgs below or'd with this are the NACK */ #define E1000_VT_MSGTYPE_NACK 0x40000000 /* Indicates that VF is still clear to send requests */ #define E1000_VT_MSGTYPE_CTS 0x20000000 #define E1000_VT_MSGINFO_SHIFT 16 /* bits 23:16 are used for extra info for certain messages */ #define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_RESET 0x01 /* VF requests reset */ #define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests to set MAC addr */ #define E1000_VF_SET_MULTICAST 0x03 /* VF requests to set MC addr */ #define E1000_VF_SET_MULTICAST_COUNT_MASK (0x1F << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_MULTICAST_OVERFLOW (0x80 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_VLAN 0x04 /* VF requests to set VLAN */ #define E1000_VF_SET_VLAN_ADD (0x01 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_LPE 0x05 /* reqs to set VMOLR.LPE */ #define E1000_VF_SET_PROMISC 0x06 /* reqs to clear VMOLR.ROPE/MPME*/ #define E1000_VF_SET_PROMISC_UNICAST (0x01 << E1000_VT_MSGINFO_SHIFT) #define E1000_VF_SET_PROMISC_MULTICAST (0x02 << E1000_VT_MSGINFO_SHIFT) #define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */ #define E1000_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define E1000_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ s32 e1000_read_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_write_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_read_posted_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_write_posted_mbx(struct e1000_hw *, u32 *, u16, u16); s32 e1000_check_for_msg(struct e1000_hw *, u16); s32 e1000_check_for_ack(struct e1000_hw *, u16); s32 e1000_check_for_rst(struct e1000_hw *, u16); void e1000_init_mbx_ops_generic(struct e1000_hw *hw); s32 e1000_init_mbx_params_pf(struct e1000_hw *); #endif /* _E1000_MBX_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_nvm.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" static void e1000_reload_nvm_generic(struct e1000_hw *hw); /** * e1000_init_nvm_ops_generic - Initialize NVM function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_nvm_ops_generic(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; DEBUGFUNC("e1000_init_nvm_ops_generic"); /* Initialize function pointers */ nvm->ops.init_params = e1000_null_ops_generic; nvm->ops.acquire = e1000_null_ops_generic; nvm->ops.read = e1000_null_read_nvm; nvm->ops.release = e1000_null_nvm_generic; nvm->ops.reload = e1000_reload_nvm_generic; nvm->ops.update = e1000_null_ops_generic; nvm->ops.valid_led_default = e1000_null_led_default; nvm->ops.validate = e1000_null_ops_generic; nvm->ops.write = e1000_null_write_nvm; } /** * e1000_null_nvm_read - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_read_nvm(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b, u16 E1000_UNUSEDARG *c) { DEBUGFUNC("e1000_null_read_nvm"); return E1000_SUCCESS; } /** * e1000_null_nvm_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_nvm_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_nvm_generic"); return; } /** * e1000_null_led_default - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_led_default(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_null_led_default"); return E1000_SUCCESS; } /** * e1000_null_write_nvm - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_write_nvm(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG a, u16 E1000_UNUSEDARG b, u16 E1000_UNUSEDARG *c) { DEBUGFUNC("e1000_null_write_nvm"); return E1000_SUCCESS; } /** * e1000_raise_eec_clk - Raise EEPROM clock * @hw: pointer to the HW structure * @eecd: pointer to the EEPROM * * Enable/Raise the EEPROM clock bit. **/ static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) { *eecd = *eecd | E1000_EECD_SK; E1000_WRITE_REG(hw, E1000_EECD, *eecd); E1000_WRITE_FLUSH(hw); usec_delay(hw->nvm.delay_usec); } /** * e1000_lower_eec_clk - Lower EEPROM clock * @hw: pointer to the HW structure * @eecd: pointer to the EEPROM * * Clear/Lower the EEPROM clock bit. **/ static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) { *eecd = *eecd & ~E1000_EECD_SK; E1000_WRITE_REG(hw, E1000_EECD, *eecd); E1000_WRITE_FLUSH(hw); usec_delay(hw->nvm.delay_usec); } /** * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM * @hw: pointer to the HW structure * @data: data to send to the EEPROM * @count: number of bits to shift out * * We need to shift 'count' bits out to the EEPROM. So, the value in the * "data" parameter will be shifted out to the EEPROM one bit at a time. * In order to do this, "data" must be broken down into bits. **/ static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u32 mask; DEBUGFUNC("e1000_shift_out_eec_bits"); mask = 0x01 << (count - 1); if (nvm->type == e1000_nvm_eeprom_spi) eecd |= E1000_EECD_DO; do { eecd &= ~E1000_EECD_DI; if (data & mask) eecd |= E1000_EECD_DI; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); e1000_raise_eec_clk(hw, &eecd); e1000_lower_eec_clk(hw, &eecd); mask >>= 1; } while (mask); eecd &= ~E1000_EECD_DI; E1000_WRITE_REG(hw, E1000_EECD, eecd); } /** * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM * @hw: pointer to the HW structure * @count: number of bits to shift in * * In order to read a register from the EEPROM, we need to shift 'count' bits * in from the EEPROM. Bits are "shifted in" by raising the clock input to * the EEPROM (setting the SK bit), and then reading the value of the data out * "DO" bit. During this "shifting in" process the data in "DI" bit should * always be clear. **/ static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) { u32 eecd; u32 i; u16 data; DEBUGFUNC("e1000_shift_in_eec_bits"); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); data = 0; for (i = 0; i < count; i++) { data <<= 1; e1000_raise_eec_clk(hw, &eecd); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~E1000_EECD_DI; if (eecd & E1000_EECD_DO) data |= 1; e1000_lower_eec_clk(hw, &eecd); } return data; } /** * e1000_poll_eerd_eewr_done - Poll for EEPROM read/write completion * @hw: pointer to the HW structure * @ee_reg: EEPROM flag for polling * * Polls the EEPROM status bit for either read or write completion based * upon the value of 'ee_reg'. **/ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) { u32 attempts = 100000; u32 i, reg = 0; DEBUGFUNC("e1000_poll_eerd_eewr_done"); for (i = 0; i < attempts; i++) { if (ee_reg == E1000_NVM_POLL_READ) reg = E1000_READ_REG(hw, E1000_EERD); else reg = E1000_READ_REG(hw, E1000_EEWR); if (reg & E1000_NVM_RW_REG_DONE) return E1000_SUCCESS; usec_delay(5); } return -E1000_ERR_NVM; } /** * e1000_acquire_nvm_generic - Generic request for access to EEPROM * @hw: pointer to the HW structure * * Set the EEPROM access request bit and wait for EEPROM access grant bit. * Return successful if access grant bit set, else clear the request for * EEPROM access and return -E1000_ERR_NVM (-1). **/ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); s32 timeout = E1000_NVM_GRANT_ATTEMPTS; DEBUGFUNC("e1000_acquire_nvm_generic"); E1000_WRITE_REG(hw, E1000_EECD, eecd | E1000_EECD_REQ); eecd = E1000_READ_REG(hw, E1000_EECD); while (timeout) { if (eecd & E1000_EECD_GNT) break; usec_delay(5); eecd = E1000_READ_REG(hw, E1000_EECD); timeout--; } if (!timeout) { eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, E1000_EECD, eecd); DEBUGOUT("Could not acquire NVM grant\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_standby_nvm - Return EEPROM to standby state * @hw: pointer to the HW structure * * Return the EEPROM to a standby state. **/ static void e1000_standby_nvm(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); DEBUGFUNC("e1000_standby_nvm"); if (nvm->type == e1000_nvm_eeprom_spi) { /* Toggle CS to flush commands */ eecd |= E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); eecd &= ~E1000_EECD_CS; E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(nvm->delay_usec); } } /** * e1000_stop_nvm - Terminate EEPROM command * @hw: pointer to the HW structure * * Terminates the current command by inverting the EEPROM's chip select pin. **/ static void e1000_stop_nvm(struct e1000_hw *hw) { u32 eecd; DEBUGFUNC("e1000_stop_nvm"); eecd = E1000_READ_REG(hw, E1000_EECD); if (hw->nvm.type == e1000_nvm_eeprom_spi) { /* Pull CS high */ eecd |= E1000_EECD_CS; e1000_lower_eec_clk(hw, &eecd); } } /** * e1000_release_nvm_generic - Release exclusive access to EEPROM * @hw: pointer to the HW structure * * Stop any current commands to the EEPROM and clear the EEPROM request bit. **/ void e1000_release_nvm_generic(struct e1000_hw *hw) { u32 eecd; DEBUGFUNC("e1000_release_nvm_generic"); e1000_stop_nvm(hw); eecd = E1000_READ_REG(hw, E1000_EECD); eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, E1000_EECD, eecd); } /** * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write * @hw: pointer to the HW structure * * Setups the EEPROM for reading and writing. **/ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); u8 spi_stat_reg; DEBUGFUNC("e1000_ready_nvm_eeprom"); if (nvm->type == e1000_nvm_eeprom_spi) { u16 timeout = NVM_MAX_RETRY_SPI; /* Clear SK and CS */ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); E1000_WRITE_REG(hw, E1000_EECD, eecd); E1000_WRITE_FLUSH(hw); usec_delay(1); /* Read "Status Register" repeatedly until the LSB is cleared. * The EEPROM will signal that the command has been completed * by clearing bit 0 of the internal status register. If it's * not cleared within 'timeout', then error out. */ while (timeout) { e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, hw->nvm.opcode_bits); spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) break; usec_delay(5); e1000_standby_nvm(hw); timeout--; } if (!timeout) { DEBUGOUT("SPI NVM Status error\n"); return -E1000_ERR_NVM; } } return E1000_SUCCESS; } /** * e1000_read_nvm_spi - Read EEPROM's using SPI * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM. **/ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i = 0; s32 ret_val; u16 word_in; u8 read_opcode = NVM_READ_OPCODE_SPI; DEBUGFUNC("e1000_read_nvm_spi"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; e1000_standby_nvm(hw); if ((nvm->address_bits == 8) && (offset >= 128)) read_opcode |= NVM_A8_OPCODE_SPI; /* Send the READ command (opcode + addr) */ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); /* Read the data. SPI NVMs increment the address with each byte * read and will roll over if reading beyond the end. This allows * us to read the whole NVM from any offset */ for (i = 0; i < words; i++) { word_in = e1000_shift_in_eec_bits(hw, 16); data[i] = (word_in >> 8) | (word_in << 8); } release: nvm->ops.release(hw); return ret_val; } /** * e1000_read_nvm_eerd - Reads EEPROM using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, eerd = 0; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_nvm_eerd"); /* A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } for (i = 0; i < words; i++) { eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + E1000_NVM_RW_REG_START; E1000_WRITE_REG(hw, E1000_EERD, eerd); ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); if (ret_val) break; data[i] = (E1000_READ_REG(hw, E1000_EERD) >> E1000_NVM_RW_REG_DATA); } return ret_val; } /** * e1000_write_nvm_spi - Write to EEPROM using SPI * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * Writes data to EEPROM at offset using SPI interface. * * If e1000_update_nvm_checksum is not called after this function , the * EEPROM will most likely contain an invalid checksum. **/ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val = -E1000_ERR_NVM; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_spi"); /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); return -E1000_ERR_NVM; } while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; ret_val = nvm->ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) { nvm->ops.release(hw); return ret_val; } e1000_standby_nvm(hw); /* Send the WRITE ENABLE command (8 bit opcode) */ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, nvm->opcode_bits); e1000_standby_nvm(hw); /* Some SPI eeproms use the 8th address bit embedded in the * opcode */ if ((nvm->address_bits == 8) && (offset >= 128)) write_opcode |= NVM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), nvm->address_bits); /* Loop to allow for up to whole page write of eeprom */ while (widx < words) { u16 word_out = data[widx]; word_out = (word_out >> 8) | (word_out << 8); e1000_shift_out_eec_bits(hw, word_out, 16); widx++; if ((((offset + widx) * 2) % nvm->page_size) == 0) { e1000_standby_nvm(hw); break; } } msec_delay(10); nvm->ops.release(hw); } return ret_val; } /** * e1000_read_pba_string_generic - Read device part number * @hw: pointer to the HW structure * @pba_num: pointer to device part number * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. **/ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size) { s32 ret_val; u16 nvm_data; u16 pba_ptr; u16 offset; u16 length; DEBUGFUNC("e1000_read_pba_string_generic"); if (pba_num == NULL) { DEBUGOUT("PBA string buffer was null\n"); return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } /* if nvm_data is not ptr guard the PBA must be in legacy format which * means pba_ptr is actually our second data word for the PBA number * and we can decode it into an ascii string */ if (nvm_data != NVM_PBA_PTR_GUARD) { DEBUGOUT("NVM PBA number is not stored as string\n"); /* make sure callers buffer is big enough to store the PBA */ if (pba_num_size < E1000_PBANUM_LENGTH) { DEBUGOUT("PBA string buffer too small\n"); return E1000_ERR_NO_SPACE; } /* extract hex string from data and pba_ptr */ pba_num[0] = (nvm_data >> 12) & 0xF; pba_num[1] = (nvm_data >> 8) & 0xF; pba_num[2] = (nvm_data >> 4) & 0xF; pba_num[3] = nvm_data & 0xF; pba_num[4] = (pba_ptr >> 12) & 0xF; pba_num[5] = (pba_ptr >> 8) & 0xF; pba_num[6] = '-'; pba_num[7] = 0; pba_num[8] = (pba_ptr >> 4) & 0xF; pba_num[9] = pba_ptr & 0xF; /* put a null character on the end of our string */ pba_num[10] = '\0'; /* switch all the data but the '-' to hex char */ for (offset = 0; offset < 10; offset++) { if (pba_num[offset] < 0xA) pba_num[offset] += '0'; else if (pba_num[offset] < 0x10) pba_num[offset] += 'A' - 0xA; } return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); return -E1000_ERR_NVM_PBA_SECTION; } /* check if pba_num buffer is big enough */ if (pba_num_size < (((u32)length * 2) - 1)) { DEBUGOUT("PBA string buffer too small\n"); return -E1000_ERR_NO_SPACE; } /* trim pba length from start of string */ pba_ptr++; length--; for (offset = 0; offset < length; offset++) { ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } pba_num[offset * 2] = (u8)(nvm_data >> 8); pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); } pba_num[offset * 2] = '\0'; return E1000_SUCCESS; } /** * e1000_read_pba_length_generic - Read device part number length * @hw: pointer to the HW structure * @pba_num_size: size of part number buffer * * Reads the product board assembly (PBA) number length from the EEPROM and * stores the value in pba_num_size. **/ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size) { s32 ret_val; u16 nvm_data; u16 pba_ptr; u16 length; DEBUGFUNC("e1000_read_pba_length_generic"); if (pba_num_size == NULL) { DEBUGOUT("PBA buffer size was null\n"); return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } /* if data is not ptr guard the PBA must be in legacy format */ if (nvm_data != NVM_PBA_PTR_GUARD) { *pba_num_size = E1000_PBANUM_LENGTH; return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); return -E1000_ERR_NVM_PBA_SECTION; } /* Convert from length in u16 values to u8 chars, add 1 for NULL, * and subtract 2 because length field is included in length. */ *pba_num_size = ((u32)length * 2) - 1; return E1000_SUCCESS; } /** * e1000_read_mac_addr_generic - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. * Since devices with two ports use the same EEPROM, we increment the * last bit in the MAC address for the second port. **/ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) { u32 rar_high; u32 rar_low; u16 i; rar_high = E1000_READ_REG(hw, E1000_RAH(0)); rar_low = E1000_READ_REG(hw, E1000_RAL(0)); for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; return E1000_SUCCESS; } /** * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_validate_nvm_checksum_generic"); for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); return ret_val; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); return -E1000_ERR_NVM; } return E1000_SUCCESS; } /** * e1000_update_nvm_checksum_generic - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) { s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum"); for (i = 0; i < NVM_CHECKSUM_REG; i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); return ret_val; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); return ret_val; } /** * e1000_reload_nvm_generic - Reloads EEPROM * @hw: pointer to the HW structure * * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the * extended control register. **/ static void e1000_reload_nvm_generic(struct e1000_hw *hw) { u32 ctrl_ext; DEBUGFUNC("e1000_reload_nvm_generic"); usec_delay(10); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_EE_RST; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw); } /** * e1000_get_fw_version - Get firmware version information * @hw: pointer to the HW structure * @fw_vers: pointer to output version structure * * unsupported/not present features return 0 in version structure **/ void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers) { u16 eeprom_verh, eeprom_verl, etrack_test, fw_version; u8 q, hval, rem, result; u16 comb_verh, comb_verl, comb_offset; memset(fw_vers, 0, sizeof(struct e1000_fw_version)); /* basic eeprom version numbers, bits used vary by part and by tool * used to create the nvm images */ /* Check which data format we have */ hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test); switch (hw->mac.type) { case e1000_i211: e1000_read_invm_version(hw, fw_vers); return; case e1000_82575: case e1000_82576: case e1000_82580: /* Use this format, unless EETRACK ID exists, * then use alternate format */ if ((etrack_test & NVM_MAJOR_MASK) != NVM_ETRACK_VALID) { hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK) >> NVM_MINOR_SHIFT; fw_vers->eep_build = (fw_version & NVM_IMAGE_ID_MASK); goto etrack_id; } break; case e1000_i210: if (!(e1000_get_flash_presence_i210(hw))) { e1000_read_invm_version(hw, fw_vers); return; } /* fall through */ case e1000_i350: case e1000_i354: /* find combo image version */ hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset); if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) { hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset + 1), 1, &comb_verh); hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset), 1, &comb_verl); /* get Option Rom version if it exists and is valid */ if ((comb_verh && comb_verl) && ((comb_verh != NVM_VER_INVALID) && (comb_verl != NVM_VER_INVALID))) { fw_vers->or_valid = true; fw_vers->or_major = comb_verl >> NVM_COMB_VER_SHFT; fw_vers->or_build = (comb_verl << NVM_COMB_VER_SHFT) | (comb_verh >> NVM_COMB_VER_SHFT); fw_vers->or_patch = comb_verh & NVM_COMB_VER_MASK; } } break; default: return; } hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version); fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT; /* check for old style version format in newer images*/ if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) { eeprom_verl = (fw_version & NVM_COMB_VER_MASK); } else { eeprom_verl = (fw_version & NVM_MINOR_MASK) >> NVM_MINOR_SHIFT; } /* Convert minor value to hex before assigning to output struct * Val to be converted will not be higher than 99, per tool output */ q = eeprom_verl / NVM_HEX_CONV; hval = q * NVM_HEX_TENS; rem = eeprom_verl % NVM_HEX_CONV; result = hval + rem; fw_vers->eep_minor = result; etrack_id: if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) { hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl); hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh); fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl; } return; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_nvm.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ struct e1000_fw_version { u32 etrack_id; u16 eep_major; u16 eep_minor; u16 eep_build; u8 invm_major; u8 invm_minor; u8 invm_img_type; bool or_valid; u16 or_major; u16 or_build; u16 or_patch; }; void e1000_init_nvm_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); void e1000_null_nvm_generic(struct e1000_hw *hw); s32 e1000_null_led_default(struct e1000_hw *hw, u16 *data); s32 e1000_null_write_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); s32 e1000_acquire_nvm_generic(struct e1000_hw *hw); s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size); s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size); s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data); s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw); s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw); void e1000_release_nvm_generic(struct e1000_hw *hw); void e1000_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers); #define E1000_STM_OPCODE 0xDB00 #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_osdep.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* glue for the OS independent part of e1000 * includes register access macros */ #ifndef _E1000_OSDEP_H_ #define _E1000_OSDEP_H_ #include #include #include #include #include #include "kcompat.h" #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wunused-function" #endif #define usec_delay(x) udelay(x) #define usec_delay_irq(x) udelay(x) #ifndef msec_delay #define msec_delay(x) do { \ /* Don't mdelay in interrupt context! */ \ if (in_interrupt()) \ BUG(); \ else \ msleep(x); \ } while (0) /* Some workarounds require millisecond delays and are run during interrupt * context. Most notably, when establishing link, the phy may need tweaking * but cannot process phy register reads/writes faster than millisecond * intervals...and we establish link due to a "link status change" interrupt. */ #define msec_delay_irq(x) mdelay(x) #endif #define PCI_COMMAND_REGISTER PCI_COMMAND #define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE #define ETH_ADDR_LEN ETH_ALEN #ifdef __BIG_ENDIAN #define E1000_BIG_ENDIAN __BIG_ENDIAN #endif #ifdef DEBUG #define DEBUGOUT(S) printk(KERN_DEBUG S) #define DEBUGOUT1(S, A...) printk(KERN_DEBUG S, ## A) #else #define DEBUGOUT(S) #define DEBUGOUT1(S, A...) #endif #ifdef DEBUG_FUNC #define DEBUGFUNC(F) DEBUGOUT(F "\n") #else #define DEBUGFUNC(F) #endif #define DEBUGOUT2 DEBUGOUT1 #define DEBUGOUT3 DEBUGOUT2 #define DEBUGOUT7 DEBUGOUT3 #define E1000_REGISTER(a, reg) reg #define E1000_WRITE_REG(a, reg, value) ( \ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg)))) #define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_REGISTER(a, reg))) #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ writel((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2)))) #define E1000_READ_REG_ARRAY(a, reg, offset) ( \ readl((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 2))) #define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY #define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY #define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ writew((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1)))) #define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ readw((a)->hw_addr + E1000_REGISTER(a, reg) + ((offset) << 1))) #define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ writeb((value), ((a)->hw_addr + E1000_REGISTER(a, reg) + (offset)))) #define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ readb((a)->hw_addr + E1000_REGISTER(a, reg) + (offset))) #define E1000_WRITE_REG_IO(a, reg, offset) do { \ outl(reg, ((a)->io_base)); \ outl(offset, ((a)->io_base + 4)); } while (0) #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, E1000_STATUS) #define E1000_WRITE_FLASH_REG(a, reg, value) ( \ writel((value), ((a)->flash_address + reg))) #define E1000_WRITE_FLASH_REG16(a, reg, value) ( \ writew((value), ((a)->flash_address + reg))) #define E1000_READ_FLASH_REG(a, reg) (readl((a)->flash_address + reg)) #define E1000_READ_FLASH_REG16(a, reg) (readw((a)->flash_address + reg)) #endif /* _E1000_OSDEP_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_phy.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "e1000_api.h" static s32 e1000_wait_autoneg(struct e1000_hw *hw); /* Cable length tables */ static const u16 e1000_m88_cable_length_table[] = { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_m88_cable_length_table) / \ sizeof(e1000_m88_cable_length_table[0])) static const u16 e1000_igp_2_cable_length_table[] = { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, 124}; #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ (sizeof(e1000_igp_2_cable_length_table) / \ sizeof(e1000_igp_2_cable_length_table[0])) /** * e1000_init_phy_ops_generic - Initialize PHY function pointers * @hw: pointer to the HW structure * * Setups up the function pointers to no-op functions **/ void e1000_init_phy_ops_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; DEBUGFUNC("e1000_init_phy_ops_generic"); /* Initialize function pointers */ phy->ops.init_params = e1000_null_ops_generic; phy->ops.acquire = e1000_null_ops_generic; phy->ops.check_polarity = e1000_null_ops_generic; phy->ops.check_reset_block = e1000_null_ops_generic; phy->ops.commit = e1000_null_ops_generic; phy->ops.force_speed_duplex = e1000_null_ops_generic; phy->ops.get_cfg_done = e1000_null_ops_generic; phy->ops.get_cable_length = e1000_null_ops_generic; phy->ops.get_info = e1000_null_ops_generic; phy->ops.set_page = e1000_null_set_page; phy->ops.read_reg = e1000_null_read_reg; phy->ops.read_reg_locked = e1000_null_read_reg; phy->ops.read_reg_page = e1000_null_read_reg; phy->ops.release = e1000_null_phy_generic; phy->ops.reset = e1000_null_ops_generic; phy->ops.set_d0_lplu_state = e1000_null_lplu_state; phy->ops.set_d3_lplu_state = e1000_null_lplu_state; phy->ops.write_reg = e1000_null_write_reg; phy->ops.write_reg_locked = e1000_null_write_reg; phy->ops.write_reg_page = e1000_null_write_reg; phy->ops.power_up = e1000_null_phy_generic; phy->ops.power_down = e1000_null_phy_generic; phy->ops.read_i2c_byte = e1000_read_i2c_byte_null; phy->ops.write_i2c_byte = e1000_write_i2c_byte_null; } /** * e1000_null_set_page - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw, u16 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_null_set_page"); return E1000_SUCCESS; } /** * e1000_null_read_reg - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_null_read_reg"); return E1000_SUCCESS; } /** * e1000_null_phy_generic - No-op function, return void * @hw: pointer to the HW structure **/ void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_null_phy_generic"); return; } /** * e1000_null_lplu_state - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw, bool E1000_UNUSEDARG active) { DEBUGFUNC("e1000_null_lplu_state"); return E1000_SUCCESS; } /** * e1000_null_write_reg - No-op function, return 0 * @hw: pointer to the HW structure **/ s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw, u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_null_write_reg"); return E1000_SUCCESS; } /** * e1000_read_i2c_byte_null - No-op function, return 0 * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: data value read * **/ s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG byte_offset, u8 E1000_UNUSEDARG dev_addr, u8 E1000_UNUSEDARG *data) { DEBUGFUNC("e1000_read_i2c_byte_null"); return E1000_SUCCESS; } /** * e1000_write_i2c_byte_null - No-op function, return 0 * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: data value to write * **/ s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw, u8 E1000_UNUSEDARG byte_offset, u8 E1000_UNUSEDARG dev_addr, u8 E1000_UNUSEDARG data) { DEBUGFUNC("e1000_write_i2c_byte_null"); return E1000_SUCCESS; } /** * e1000_check_reset_block_generic - Check if PHY reset is blocked * @hw: pointer to the HW structure * * Read the PHY management control register and check whether a PHY reset * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise * return E1000_BLK_PHY_RESET (12). **/ s32 e1000_check_reset_block_generic(struct e1000_hw *hw) { u32 manc; DEBUGFUNC("e1000_check_reset_block"); manc = E1000_READ_REG(hw, E1000_MANC); return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : E1000_SUCCESS; } /** * e1000_get_phy_id - Retrieve the PHY ID and revision * @hw: pointer to the HW structure * * Reads the PHY registers and stores the PHY ID and possibly the PHY * revision in the hardware structure. **/ s32 e1000_get_phy_id(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id; DEBUGFUNC("e1000_get_phy_id"); if (!phy->ops.read_reg) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) return ret_val; phy->id = (u32)(phy_id << 16); usec_delay(20); ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) return ret_val; phy->id |= (u32)(phy_id & PHY_REVISION_MASK); phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); return E1000_SUCCESS; } /** * e1000_phy_reset_dsp_generic - Reset PHY DSP * @hw: pointer to the HW structure * * Reset the digital signal processor. **/ s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) { s32 ret_val; DEBUGFUNC("e1000_phy_reset_dsp_generic"); if (!hw->phy.ops.write_reg) return E1000_SUCCESS; ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); if (ret_val) return ret_val; return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); } /** * e1000_read_phy_reg_mdic - Read MDI control register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the MDI control register in the PHY at offset and stores the * information read to data. **/ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) { struct e1000_phy_info *phy = &hw->phy; u32 i, mdic = 0; DEBUGFUNC("e1000_read_phy_reg_mdic"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); return -E1000_ERR_PARAM; } /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ mdic = ((offset << E1000_MDIC_REG_SHIFT) | (phy->addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_READ)); E1000_WRITE_REG(hw, E1000_MDIC, mdic); /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { usec_delay_irq(50); mdic = E1000_READ_REG(hw, E1000_MDIC); if (mdic & E1000_MDIC_READY) break; } if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Read did not complete\n"); return -E1000_ERR_PHY; } if (mdic & E1000_MDIC_ERROR) { DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n", offset, (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); return -E1000_ERR_PHY; } *data = (u16) mdic; return E1000_SUCCESS; } /** * e1000_write_phy_reg_mdic - Write MDI control register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write to register at offset * * Writes data to MDI control register in the PHY at offset. **/ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) { struct e1000_phy_info *phy = &hw->phy; u32 i, mdic = 0; DEBUGFUNC("e1000_write_phy_reg_mdic"); if (offset > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", offset); return -E1000_ERR_PARAM; } /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ mdic = (((u32)data) | (offset << E1000_MDIC_REG_SHIFT) | (phy->addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_WRITE)); E1000_WRITE_REG(hw, E1000_MDIC, mdic); /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { usec_delay_irq(50); mdic = E1000_READ_REG(hw, E1000_MDIC); if (mdic & E1000_MDIC_READY) break; } if (!(mdic & E1000_MDIC_READY)) { DEBUGOUT("MDI Write did not complete\n"); return -E1000_ERR_PHY; } if (mdic & E1000_MDIC_ERROR) { DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n", offset, (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_read_phy_reg_i2c - Read PHY register using i2c * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the i2c interface and stores the * retrieved information in data. **/ s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) { struct e1000_phy_info *phy = &hw->phy; u32 i, i2ccmd = 0; DEBUGFUNC("e1000_read_phy_reg_i2c"); /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | (E1000_I2CCMD_OPCODE_READ)); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) break; } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Read did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } /* Need to byte-swap the 16-bit value. */ *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); return E1000_SUCCESS; } /** * e1000_write_phy_reg_i2c - Write PHY register using i2c * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset using the i2c interface. **/ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) { struct e1000_phy_info *phy = &hw->phy; u32 i, i2ccmd = 0; u16 phy_data_swapped; DEBUGFUNC("e1000_write_phy_reg_i2c"); /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/ if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) { DEBUGOUT1("PHY I2C Address %d is out of range.\n", hw->phy.addr); return -E1000_ERR_CONFIG; } /* Swap the data bytes for the I2C interface */ phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_WRITE | phy_data_swapped); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) break; } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Write did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_read_sfp_data_byte - Reads SFP module data. * @hw: pointer to the HW structure * @offset: byte location offset to be read * @data: read data buffer pointer * * Reads one byte from SFP module data stored * in SFP resided EEPROM memory or SFP diagnostic area. * Function should be called with * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters * access **/ s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data) { u32 i = 0; u32 i2ccmd = 0; u32 data_local = 0; DEBUGFUNC("e1000_read_sfp_data_byte"); if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { DEBUGOUT("I2CCMD command address exceeds upper limit\n"); return -E1000_ERR_PHY; } /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing with the * EEPROM to retrieve the desired data. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_READ); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); /* Poll the ready bit to see if the I2C read completed */ for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); data_local = E1000_READ_REG(hw, E1000_I2CCMD); if (data_local & E1000_I2CCMD_READY) break; } if (!(data_local & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Read did not complete\n"); return -E1000_ERR_PHY; } if (data_local & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } *data = (u8) data_local & 0xFF; return E1000_SUCCESS; } /** * e1000_write_sfp_data_byte - Writes SFP module data. * @hw: pointer to the HW structure * @offset: byte location offset to write to * @data: data to write * * Writes one byte to SFP module data stored * in SFP resided EEPROM memory or SFP diagnostic area. * Function should be called with * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters * access **/ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) { u32 i = 0; u32 i2ccmd = 0; u32 data_local = 0; DEBUGFUNC("e1000_write_sfp_data_byte"); if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { DEBUGOUT("I2CCMD command address exceeds upper limit\n"); return -E1000_ERR_PHY; } /* The programming interface is 16 bits wide * so we need to read the whole word first * then update appropriate byte lane and write * the updated word back. */ /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing * with an EEPROM to write the data given. */ i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_READ); /* Set a command to read single word */ E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); /* Poll the ready bit to see if lastly * launched I2C operation completed */ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); if (i2ccmd & E1000_I2CCMD_READY) { /* Check if this is READ or WRITE phase */ if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) == E1000_I2CCMD_OPCODE_READ) { /* Write the selected byte * lane and update whole word */ data_local = i2ccmd & 0xFF00; data_local |= data; i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | E1000_I2CCMD_OPCODE_WRITE | data_local); E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); } else { break; } } } if (!(i2ccmd & E1000_I2CCMD_READY)) { DEBUGOUT("I2CCMD Write did not complete\n"); return -E1000_ERR_PHY; } if (i2ccmd & E1000_I2CCMD_ERROR) { DEBUGOUT("I2CCMD Error bit set\n"); return -E1000_ERR_PHY; } return E1000_SUCCESS; } /** * e1000_read_phy_reg_m88 - Read m88 PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore, if necessary, then reads the PHY register at offset * and storing the retrieved information in data. Release any acquired * semaphores before exiting. **/ s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; DEBUGFUNC("e1000_read_phy_reg_m88"); if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_m88 - Write m88 PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; DEBUGFUNC("e1000_write_phy_reg_m88"); if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); hw->phy.ops.release(hw); return ret_val; } /** * e1000_set_page_igp - Set page as on IGP-like PHY(s) * @hw: pointer to the HW structure * @page: page to set (shifted left when necessary) * * Sets PHY page required for PHY register access. Assumes semaphore is * already acquired. Note, this function sets phy.addr to 1 so the caller * must set it appropriately (if necessary) after this function returns. **/ s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) { DEBUGFUNC("e1000_set_page_igp"); DEBUGOUT1("Setting page 0x%x\n", page); hw->phy.addr = 1; return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); } /** * __e1000_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then reads the PHY register at offset * and stores the retrieved information in data. Release any acquired * semaphores before exiting. **/ static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, bool locked) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("__e1000_read_phy_reg_igp"); if (!locked) { if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } if (offset > MAX_PHY_MULTI_PAGE_REG) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (!ret_val) ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore then reads the PHY register at offset and stores the * retrieved information in data. * Release the acquired semaphore before exiting. **/ s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_igp(hw, offset, data, false); } /** * e1000_read_phy_reg_igp_locked - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset and stores the retrieved information * in data. Assumes semaphore already acquired. **/ s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_phy_reg_igp(hw, offset, data, true); } /** * e1000_write_phy_reg_igp - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, bool locked) { s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_phy_reg_igp"); if (!locked) { if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } if (offset > MAX_PHY_MULTI_PAGE_REG) ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); if (!ret_val) ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); if (!locked) hw->phy.ops.release(hw); return ret_val; } /** * e1000_write_phy_reg_igp - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_igp(hw, offset, data, false); } /** * e1000_write_phy_reg_igp_locked - Write igp PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Writes the data to PHY register at the offset. * Assumes semaphore already acquired. **/ s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_phy_reg_igp(hw, offset, data, true); } /** * __e1000_read_kmrn_reg - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then reads the PHY register at offset * using the kumeran interface. The information retrieved is stored in data. * Release any acquired semaphores before exiting. **/ static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, bool locked) { u32 kmrnctrlsta; DEBUGFUNC("__e1000_read_kmrn_reg"); if (!locked) { s32 ret_val = E1000_SUCCESS; if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); *data = (u16)kmrnctrlsta; if (!locked) hw->phy.ops.release(hw); return E1000_SUCCESS; } /** * e1000_read_kmrn_reg_generic - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Acquires semaphore then reads the PHY register at offset using the * kumeran interface. The information retrieved is stored in data. * Release the acquired semaphore before exiting. **/ s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, false); } /** * e1000_read_kmrn_reg_locked - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * * Reads the PHY register at offset using the kumeran interface. The * information retrieved is stored in data. * Assumes semaphore already acquired. **/ s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) { return __e1000_read_kmrn_reg(hw, offset, data, true); } /** * __e1000_write_kmrn_reg - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then write the data to PHY register * at the offset using the kumeran interface. Release any acquired semaphores * before exiting. **/ static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, bool locked) { u32 kmrnctrlsta; DEBUGFUNC("e1000_write_kmrn_reg_generic"); if (!locked) { s32 ret_val = E1000_SUCCESS; if (!hw->phy.ops.acquire) return E1000_SUCCESS; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | data; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); E1000_WRITE_FLUSH(hw); usec_delay(2); if (!locked) hw->phy.ops.release(hw); return E1000_SUCCESS; } /** * e1000_write_kmrn_reg_generic - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore then writes the data to the PHY register at the offset * using the kumeran interface. Release the acquired semaphore before exiting. **/ s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, false); } /** * e1000_write_kmrn_reg_locked - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Write the data to PHY register at the offset using the kumeran interface. * Assumes semaphore already acquired. **/ s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) { return __e1000_write_kmrn_reg(hw, offset, data, true); } /** * e1000_set_master_slave_mode - Setup PHY for Master/slave mode * @hw: pointer to the HW structure * * Sets up Master/slave mode **/ static s32 e1000_set_master_slave_mode(struct e1000_hw *hw) { s32 ret_val; u16 phy_data; /* Resolve Master/Slave mode */ ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data); if (ret_val) return ret_val; /* load defaults for future use */ hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ? ((phy_data & CR_1000T_MS_VALUE) ? e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; switch (hw->phy.ms_type) { case e1000_ms_force_master: phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); break; case e1000_ms_force_slave: phy_data |= CR_1000T_MS_ENABLE; phy_data &= ~(CR_1000T_MS_VALUE); break; case e1000_ms_auto: phy_data &= ~CR_1000T_MS_ENABLE; /* fall-through */ default: break; } return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data); } /** * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link * @hw: pointer to the HW structure * * Sets up Carrier-sense on Transmit and downshift values. **/ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) { s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_82577"); if (hw->phy.reset_disable) return E1000_SUCCESS; if (hw->phy.type == e1000_phy_82580) { ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); return ret_val; } } /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data); if (ret_val) return ret_val; phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; /* Enable downshift */ phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data); if (ret_val) return ret_val; /* Set MDI/MDIX mode */ ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data); if (ret_val) return ret_val; phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; /* Options: * 0 - Auto (default) * 1 - MDI mode * 2 - MDI-X mode */ switch (hw->phy.mdix) { case 1: break; case 2: phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; break; case 0: default: phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; break; } ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data); if (ret_val) return ret_val; return e1000_set_master_slave_mode(hw); } /** * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link * @hw: pointer to the HW structure * * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock * and downshift values are set also. **/ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_m88"); if (phy->reset_disable) return E1000_SUCCESS; /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (phy->mdix) { case 1: phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; break; case 2: phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; break; case 3: phy_data |= M88E1000_PSCR_AUTO_X_1000T; break; case 0: default: phy_data |= M88E1000_PSCR_AUTO_X_MODE; break; } /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; if (phy->revision < E1000_REVISION_4) { /* Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data |= M88E1000_EPSCR_TX_CLK_25; if ((phy->revision == E1000_REVISION_2) && (phy->id == M88E1111_I_PHY_ID)) { /* 82573L PHY - set the downshift counter to 5x. */ phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; } else { /* Configure Master and Slave downshift values */ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); } ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; } /* Commit the changes. */ ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } return E1000_SUCCESS; } /** * e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link * @hw: pointer to the HW structure * * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's. * Also enables and sets the downshift parameters. **/ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; DEBUGFUNC("e1000_copper_link_setup_m88_gen2"); if (phy->reset_disable) return E1000_SUCCESS; /* Enable CRS on Tx. This must be set for half-duplex operation. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode * 2 - MDI-X mode * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; switch (phy->mdix) { case 1: phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; break; case 2: phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; break; case 3: /* M88E1112 does not support this mode) */ if (phy->id != M88E1112_E_PHY_ID) { phy_data |= M88E1000_PSCR_AUTO_X_1000T; break; } case 0: default: phy_data |= M88E1000_PSCR_AUTO_X_MODE; break; } /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled * 1 - Enabled */ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; if (phy->disable_polarity_correction) phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; /* Enable downshift and setting it to X6 */ if (phy->id == M88E1543_E_PHY_ID) { phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } } phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK; phy_data |= I347AT4_PSCR_DOWNSHIFT_6X; phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; /* Commit the changes. */ ret_val = phy->ops.commit(hw); if (ret_val) { DEBUGOUT("Error committing the PHY changes\n"); return ret_val; } ret_val = e1000_set_master_slave_mode(hw); if (ret_val) return ret_val; return E1000_SUCCESS; } /** * e1000_copper_link_setup_igp - Setup igp PHY's for copper link * @hw: pointer to the HW structure * * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for * igp PHY's. **/ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_copper_link_setup_igp"); if (phy->reset_disable) return E1000_SUCCESS; ret_val = hw->phy.ops.reset(hw); if (ret_val) { DEBUGOUT("Error resetting the PHY.\n"); return ret_val; } /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid * timeout issues when LFS is enabled. */ msec_delay(100); /* disable lplu d0 during driver init */ if (hw->phy.ops.set_d0_lplu_state) { ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D0\n"); return ret_val; } } /* Configure mdi-mdix settings */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCR_AUTO_MDIX; switch (phy->mdix) { case 1: data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 2: data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; break; case 0: default: data |= IGP01E1000_PSCR_AUTO_MDIX; break; } ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); if (ret_val) return ret_val; /* set auto-master slave resolution settings */ if (hw->mac.autoneg) { /* when autonegotiation advertisement is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { /* Disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; /* Set auto Master/Slave resolution process */ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); if (ret_val) return ret_val; data &= ~CR_1000T_MS_ENABLE; ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); if (ret_val) return ret_val; } ret_val = e1000_set_master_slave_mode(hw); } return ret_val; } /** * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation * @hw: pointer to the HW structure * * Reads the MII auto-neg advertisement register and/or the 1000T control * register and if the PHY is already setup for auto-negotiation, then * return successful. Otherwise, setup advertisement and flow control to * the appropriate values for the wanted auto-negotiation. **/ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 mii_autoneg_adv_reg; u16 mii_1000t_ctrl_reg = 0; DEBUGFUNC("e1000_phy_setup_autoneg"); phy->autoneg_advertised &= phy->autoneg_mask; /* Read the MII Auto-Neg Advertisement Register (Address 4). */ ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); if (ret_val) return ret_val; if (phy->autoneg_mask & ADVERTISE_1000_FULL) { /* Read the MII 1000Base-T Control Register (Address 9). */ ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); if (ret_val) return ret_val; } /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for * autoneg_advertised software override. Since we can advertise * a plethora of combinations, we need to check each bit * individually. */ /* First we clear all the 10/100 mb speed bits in the Auto-Neg * Advertisement Register (Address 4) and the 1000 mb speed bits in * the 1000Base-T Control Register (Address 9). */ mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_10T_HD_CAPS); mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); /* Do we want to advertise 10 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_HALF) { DEBUGOUT("Advertise 10mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; } /* Do we want to advertise 10 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_10_FULL) { DEBUGOUT("Advertise 10mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; } /* Do we want to advertise 100 Mb Half Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_HALF) { DEBUGOUT("Advertise 100mb Half duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; } /* Do we want to advertise 100 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_100_FULL) { DEBUGOUT("Advertise 100mb Full duplex\n"); mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; } /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ if (phy->autoneg_advertised & ADVERTISE_1000_HALF) DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); /* Do we want to advertise 1000 Mb Full Duplex? */ if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { DEBUGOUT("Advertise 1000mb Full duplex\n"); mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; } /* Check for a software override of the flow control settings, and * setup the PHY advertisement registers accordingly. If * auto-negotiation is enabled, then software will have to set the * "PAUSE" bits to the correct value in the Auto-Negotiation * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- * negotiation. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames * but we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: No software override. The flow control configuration * in the EEPROM is used. */ switch (hw->fc.current_mode) { case e1000_fc_none: /* Flow control (Rx & Tx) is completely disabled by a * software over-ride. */ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_rx_pause: /* Rx Flow control is enabled, and Tx Flow control is * disabled, by a software over-ride. * * Since there really isn't a way to advertise that we are * capable of Rx Pause ONLY, we will advertise that we * support both symmetric and asymmetric Rx PAUSE. Later * (in e1000_config_fc_after_link_up) we will disable the * hw's ability to send PAUSE frames. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_tx_pause: /* Tx Flow control is enabled, and Rx Flow control is * disabled, by a software over-ride. */ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; case e1000_fc_full: /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; default: DEBUGOUT("Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); if (ret_val) return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); if (phy->autoneg_mask & ADVERTISE_1000_FULL) ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg); return ret_val; } /** * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link * @hw: pointer to the HW structure * * Performs initial bounds checking on autoneg advertisement parameter, then * configure to advertise the full capability. Setup the PHY to autoneg * and restart the negotiation process between the link partner. If * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. **/ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_ctrl; DEBUGFUNC("e1000_copper_link_autoneg"); /* Perform some bounds checking on the autoneg advertisement * parameter. */ phy->autoneg_advertised &= phy->autoneg_mask; /* If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ if (!phy->autoneg_advertised) phy->autoneg_advertised = phy->autoneg_mask; DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); ret_val = e1000_phy_setup_autoneg(hw); if (ret_val) { DEBUGOUT("Error Setting up Auto-Negotiation\n"); return ret_val; } DEBUGOUT("Restarting Auto-Neg\n"); /* Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) return ret_val; phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) return ret_val; /* Does the user want to wait for Auto-Neg to complete here, or * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { ret_val = e1000_wait_autoneg(hw); if (ret_val) { DEBUGOUT("Error while waiting for autoneg to complete\n"); return ret_val; } } hw->mac.get_link_status = true; return ret_val; } /** * e1000_setup_copper_link_generic - Configure copper link settings * @hw: pointer to the HW structure * * Calls the appropriate function to configure the link for auto-neg or forced * speed and duplex. Then we check for link, once link is established calls * to configure collision distance and flow control are called. If link is * not established, we return -E1000_ERR_PHY (-2). **/ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) { s32 ret_val; bool link; DEBUGFUNC("e1000_setup_copper_link_generic"); if (hw->mac.autoneg) { /* Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) return ret_val; } else { /* PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); ret_val = hw->phy.ops.force_speed_duplex(hw); if (ret_val) { DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } } /* Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, &link); if (ret_val) return ret_val; if (link) { DEBUGOUT("Valid link established!!!\n"); hw->mac.ops.config_collision_dist(hw); ret_val = e1000_config_fc_after_link_up_generic(hw); } else { DEBUGOUT("Unable to establish link!!!\n"); } return ret_val; } /** * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. Clears the * auto-crossover to force MDI manually. Waits for link and returns * successful if link up is successful, else -E1000_ERR_PHY (-2). **/ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); if (ret_val) return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); if (ret_val) return ret_val; DEBUGOUT1("IGP PSCR: %X\n", phy_data); usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); } return ret_val; } /** * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. Clears the * auto-crossover to force MDI manually. Resets the PHY to commit the * changes. If time expires while waiting for link up, we reset the DSP. * After reset, TX_CLK and CRS on Tx must be set. Return successful upon * successful completion, else return corresponding error code. **/ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); /* I210 and I211 devices support Auto-Crossover in forced operation. */ if (phy->type != e1000_phy_i210) { /* Clear Auto-Crossover to force MDI manually. M88E1000 * requires MDI forced whenever speed and duplex are forced. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; } DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; /* Reset the phy to commit changes. */ ret_val = hw->phy.ops.commit(hw); if (ret_val) return ret_val; if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) { bool reset_dsp = true; switch (hw->phy.id) { case I347AT4_E_PHY_ID: case M88E1340M_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1543_E_PHY_ID: case I210_I_PHY_ID: reset_dsp = false; break; default: if (hw->phy.type != e1000_phy_m88) reset_dsp = false; break; } if (!reset_dsp) { DEBUGOUT("Link taking longer than expected.\n"); } else { /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x001d); if (ret_val) return ret_val; ret_val = e1000_phy_reset_dsp_generic(hw); if (ret_val) return ret_val; } } /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; } if (hw->phy.type != e1000_phy_m88) return E1000_SUCCESS; if (hw->phy.id == I347AT4_E_PHY_ID || hw->phy.id == M88E1340M_E_PHY_ID || hw->phy.id == M88E1112_E_PHY_ID) return E1000_SUCCESS; if (hw->phy.id == I210_I_PHY_ID) return E1000_SUCCESS; if ((hw->phy.id == M88E1543_E_PHY_ID)) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; /* Resetting the phy means we need to re-force TX_CLK in the * Extended PHY Specific Control Register to 25MHz clock from * the reset value of 2.5MHz. */ phy_data |= M88E1000_EPSCR_TX_CLK_25; ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); if (ret_val) return ret_val; /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); return ret_val; } /** * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex * @hw: pointer to the HW structure * * Forces the speed and duplex settings of the PHY. * This is a function pointer entry point only called by * PHY setup routines. **/ s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_ife"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); if (ret_val) return ret_val; /* Disable MDI-X support for 10/100 */ ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); if (ret_val) return ret_val; data &= ~IFE_PMC_AUTO_MDIX; data &= ~IFE_PMC_FORCE_MDIX; ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); if (ret_val) return ret_val; DEBUGOUT1("IFE PMC: %X\n", data); usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; } return E1000_SUCCESS; } /** * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex * @hw: pointer to the HW structure * @phy_ctrl: pointer to current value of PHY_CONTROL * * Forces speed and duplex on the PHY by doing the following: disable flow * control, force speed/duplex on the MAC, disable auto speed detection, * disable auto-negotiation, configure duplex, configure speed, configure * the collision distance, write configuration to CTRL register. The * caller must write to the PHY_CONTROL register for these settings to * take affect. **/ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) { struct e1000_mac_info *mac = &hw->mac; u32 ctrl; DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); /* Turn off flow control when forcing speed/duplex */ hw->fc.current_mode = e1000_fc_none; /* Force speed/duplex on the mac */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); ctrl &= ~E1000_CTRL_SPD_SEL; /* Disable Auto Speed Detection */ ctrl &= ~E1000_CTRL_ASDE; /* Disable autoneg on the phy */ *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; /* Forcing Full or Half Duplex? */ if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { ctrl &= ~E1000_CTRL_FD; *phy_ctrl &= ~MII_CR_FULL_DUPLEX; DEBUGOUT("Half Duplex\n"); } else { ctrl |= E1000_CTRL_FD; *phy_ctrl |= MII_CR_FULL_DUPLEX; DEBUGOUT("Full Duplex\n"); } /* Forcing 10mb or 100mb? */ if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { ctrl |= E1000_CTRL_SPD_100; *phy_ctrl |= MII_CR_SPEED_100; *phy_ctrl &= ~MII_CR_SPEED_1000; DEBUGOUT("Forcing 100mb\n"); } else { ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); DEBUGOUT("Forcing 10mb\n"); } hw->mac.ops.config_collision_dist(hw); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); } /** * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 * @hw: pointer to the HW structure * @active: boolean used to enable/disable lplu * * Success returns 0, Failure returns 1 * * The low power link up (lplu) state is set to the power management level D3 * and SmartSpeed is disabled when active is true, else clear lplu for D3 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU * is used during Dx states where the power conservation is most important. * During driver activity, SmartSpeed should be enabled so performance is * maintained. **/ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_set_d3_lplu_state_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) return ret_val; if (!active) { data &= ~IGP02E1000_PM_D3_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. */ if (phy->smart_speed == e1000_smart_speed_on) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) return ret_val; } } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { data |= IGP02E1000_PM_D3_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) return ret_val; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); } return ret_val; } /** * e1000_check_downshift_generic - Checks whether a downshift in speed occurred * @hw: pointer to the HW structure * * Success returns 0, Failure returns 1 * * A downshift is detected by querying the PHY link health. **/ s32 e1000_check_downshift_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, offset, mask; DEBUGFUNC("e1000_check_downshift_generic"); switch (phy->type) { case e1000_phy_i210: case e1000_phy_m88: case e1000_phy_gg82563: offset = M88E1000_PHY_SPEC_STATUS; mask = M88E1000_PSSR_DOWNSHIFT; break; case e1000_phy_igp_2: case e1000_phy_igp_3: offset = IGP01E1000_PHY_LINK_HEALTH; mask = IGP01E1000_PLHR_SS_DOWNGRADE; break; default: /* speed downshift not supported */ phy->speed_downgraded = false; return E1000_SUCCESS; } ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->speed_downgraded = !!(phy_data & mask); return ret_val; } /** * e1000_check_polarity_m88 - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY specific status register. **/ s32 e1000_check_polarity_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_check_polarity_m88"); ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); if (!ret_val) phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_check_polarity_igp - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY port status register, and the * current speed (since there is no polarity at 100Mbps). **/ s32 e1000_check_polarity_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data, offset, mask; DEBUGFUNC("e1000_check_polarity_igp"); /* Polarity is determined based on the speed of * our connection. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) return ret_val; if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { offset = IGP01E1000_PHY_PCS_INIT_REG; mask = IGP01E1000_PHY_POLARITY_MASK; } else { /* This really only applies to 10Mbps since * there is no polarity for 100Mbps (always 0). */ offset = IGP01E1000_PHY_PORT_STATUS; mask = IGP01E1000_PSSR_POLARITY_REVERSED; } ret_val = phy->ops.read_reg(hw, offset, &data); if (!ret_val) phy->cable_polarity = ((data & mask) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_check_polarity_ife - Check cable polarity for IFE PHY * @hw: pointer to the HW structure * * Polarity is determined on the polarity reversal feature being enabled. **/ s32 e1000_check_polarity_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, offset, mask; DEBUGFUNC("e1000_check_polarity_ife"); /* Polarity is determined based on the reversal feature being enabled. */ if (phy->polarity_correction) { offset = IFE_PHY_EXTENDED_STATUS_CONTROL; mask = IFE_PESC_POLARITY_REVERSED; } else { offset = IFE_PHY_SPECIAL_CONTROL; mask = IFE_PSC_FORCE_POLARITY; } ret_val = phy->ops.read_reg(hw, offset, &phy_data); if (!ret_val) phy->cable_polarity = ((phy_data & mask) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_wait_autoneg - Wait for auto-neg completion * @hw: pointer to the HW structure * * Waits for auto-negotiation to complete or for the auto-negotiation time * limit to expire, which ever happens first. **/ static s32 e1000_wait_autoneg(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 i, phy_status; DEBUGFUNC("e1000_wait_autoneg"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_AUTONEG_COMPLETE) break; msec_delay(100); } /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation * has completed. */ return ret_val; } /** * e1000_phy_has_link_generic - Polls PHY for link * @hw: pointer to the HW structure * @iterations: number of times to poll for link * @usec_interval: delay between polling attempts * @success: pointer to whether polling was successful or not * * Polls the PHY status register for link, 'iterations' number of times. **/ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success) { s32 ret_val = E1000_SUCCESS; u16 i, phy_status; DEBUGFUNC("e1000_phy_has_link_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; for (i = 0; i < iterations; i++) { /* Some PHYs require the PHY_STATUS register to be read * twice due to the link bit being sticky. No harm doing * it across the board. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) /* If the first read fails, another entity may have * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ usec_delay(usec_interval); ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) break; if (usec_interval >= 1000) msec_delay_irq(usec_interval/1000); else usec_delay(usec_interval); } *success = (i < iterations); return ret_val; } /** * e1000_get_cable_length_m88 - Determine cable length for m88 PHY * @hw: pointer to the HW structure * * Reads the PHY specific status register to retrieve the cable length * information. The cable length is determined by averaging the minimum and * maximum values to get the "average" cable length. The m88 PHY has four * possible cable length values, which are: * Register Value Cable Length * 0 < 50 meters * 1 50 - 80 meters * 2 80 - 110 meters * 3 110 - 140 meters * 4 > 140 meters **/ s32 e1000_get_cable_length_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, index; DEBUGFUNC("e1000_get_cable_length_m88"); ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) return ret_val; index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) return -E1000_ERR_PHY; phy->min_cable_length = e1000_m88_cable_length_table[index]; phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; return E1000_SUCCESS; } s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, phy_data2, is_cm; u16 index, default_page; DEBUGFUNC("e1000_get_cable_length_m88_gen2"); switch (hw->phy.id) { case I210_I_PHY_ID: /* Get cable length from PHY Cable Diagnostics Control Reg */ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + (I347AT4_PCDL + phy->addr), &phy_data); if (ret_val) return ret_val; /* Check if the unit of cable length is meters or cm */ ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) + I347AT4_PCDC, &phy_data2); if (ret_val) return ret_val; is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); /* Populate the phy structure with cable length in meters */ phy->min_cable_length = phy_data / (is_cm ? 100 : 1); phy->max_cable_length = phy_data / (is_cm ? 100 : 1); phy->cable_length = phy_data / (is_cm ? 100 : 1); break; case M88E1543_E_PHY_ID: case M88E1340M_E_PHY_ID: case I347AT4_E_PHY_ID: /* Remember the original page select and set it to 7 */ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, &default_page); if (ret_val) return ret_val; ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07); if (ret_val) return ret_val; /* Get cable length from PHY Cable Diagnostics Control Reg */ ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr), &phy_data); if (ret_val) return ret_val; /* Check if the unit of cable length is meters or cm */ ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2); if (ret_val) return ret_val; is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT); /* Populate the phy structure with cable length in meters */ phy->min_cable_length = phy_data / (is_cm ? 100 : 1); phy->max_cable_length = phy_data / (is_cm ? 100 : 1); phy->cable_length = phy_data / (is_cm ? 100 : 1); /* Reset the page select to its original value */ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, default_page); if (ret_val) return ret_val; break; case M88E1112_E_PHY_ID: /* Remember the original page select and set it to 5 */ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, &default_page); if (ret_val) return ret_val; ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE, &phy_data); if (ret_val) return ret_val; index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT; if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) return -E1000_ERR_PHY; phy->min_cable_length = e1000_m88_cable_length_table[index]; phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; /* Reset the page select to its original value */ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, default_page); if (ret_val) return ret_val; break; default: return -E1000_ERR_PHY; } return ret_val; } /** * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY * @hw: pointer to the HW structure * * The automatic gain control (agc) normalizes the amplitude of the * received signal, adjusting for the attenuation produced by the * cable. By reading the AGC registers, which represent the * combination of coarse and fine gain value, the value can be put * into a lookup table to obtain the approximate cable length * for each channel. **/ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, i, agc_value = 0; u16 cur_agc_index, max_agc_index = 0; u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { IGP02E1000_PHY_AGC_A, IGP02E1000_PHY_AGC_B, IGP02E1000_PHY_AGC_C, IGP02E1000_PHY_AGC_D }; DEBUGFUNC("e1000_get_cable_length_igp_2"); /* Read the AGC registers for all channels */ for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); if (ret_val) return ret_val; /* Getting bits 15:9, which represent the combination of * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. */ cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & IGP02E1000_AGC_LENGTH_MASK); /* Array index bound check. */ if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || (cur_agc_index == 0)) return -E1000_ERR_PHY; /* Remove min & max AGC values from calculation. */ if (e1000_igp_2_cable_length_table[min_agc_index] > e1000_igp_2_cable_length_table[cur_agc_index]) min_agc_index = cur_agc_index; if (e1000_igp_2_cable_length_table[max_agc_index] < e1000_igp_2_cable_length_table[cur_agc_index]) max_agc_index = cur_agc_index; agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; } agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + e1000_igp_2_cable_length_table[max_agc_index]); agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); /* Calculate cable length with the error range of +/- 10 meters. */ phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ? (agc_value - IGP02E1000_AGC_RANGE) : 0); phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; return E1000_SUCCESS; } /** * e1000_get_phy_info_m88 - Retrieve PHY information * @hw: pointer to the HW structure * * Valid for only copper links. Read the PHY status register (sticky read) * to verify that link is up. Read the PHY special control register to * determine the polarity and 10base-T extended distance. Read the PHY * special status register to determine MDI/MDIx and current speed. If * speed is 1000, then determine cable length, local and remote receiver. **/ s32 e1000_get_phy_info_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_get_phy_info_m88"); if (phy->media_type != e1000_media_type_copper) { DEBUGOUT("Phy info is only valid for copper media\n"); return -E1000_ERR_CONFIG; } ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) return ret_val; phy->polarity_correction = !!(phy_data & M88E1000_PSCR_POLARITY_REVERSAL); ret_val = e1000_check_polarity_m88(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) return ret_val; phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX); if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); if (ret_val) return ret_val; phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { /* Set values to "undefined" */ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return ret_val; } /** * e1000_get_phy_info_igp - Retrieve igp PHY information * @hw: pointer to the HW structure * * Read PHY status to determine if link is up. If link is up, then * set/determine 10base-T extended distance and polarity correction. Read * PHY port status to determine MDI/MDIx and speed. Based on the speed, * determine on the cable length, local and remote receiver. **/ s32 e1000_get_phy_info_igp(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_igp"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } phy->polarity_correction = true; ret_val = e1000_check_polarity_igp(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX); if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { ret_val = phy->ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) return ret_val; phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return ret_val; } /** * e1000_get_phy_info_ife - Retrieves various IFE PHY states * @hw: pointer to the HW structure * * Populates "phy" structure with various feature states. **/ s32 e1000_get_phy_info_ife(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_ife"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data); if (ret_val) return ret_val; phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE); if (phy->polarity_correction) { ret_val = e1000_check_polarity_ife(hw); if (ret_val) return ret_val; } else { /* Polarity is forced */ phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); } ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS); /* The following parameters are undefined for 10/100 operation. */ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; return E1000_SUCCESS; } /** * e1000_phy_sw_reset_generic - PHY software reset * @hw: pointer to the HW structure * * Does a software reset of the PHY by reading the PHY control register and * setting/write the control register reset bit to the PHY. **/ s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw) { s32 ret_val; u16 phy_ctrl; DEBUGFUNC("e1000_phy_sw_reset_generic"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); if (ret_val) return ret_val; phy_ctrl |= MII_CR_RESET; ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); if (ret_val) return ret_val; usec_delay(1); return ret_val; } /** * e1000_phy_hw_reset_generic - PHY hardware reset * @hw: pointer to the HW structure * * Verify the reset block is not blocking us from resetting. Acquire * semaphore (if necessary) and read/set/write the device control reset * bit in the PHY. Wait the appropriate delay time for the device to * reset and release the semaphore (if necessary). **/ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u32 ctrl; DEBUGFUNC("e1000_phy_hw_reset_generic"); if (phy->ops.check_reset_block) { ret_val = phy->ops.check_reset_block(hw); if (ret_val) return E1000_SUCCESS; } ret_val = phy->ops.acquire(hw); if (ret_val) return ret_val; ctrl = E1000_READ_REG(hw, E1000_CTRL); E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); E1000_WRITE_FLUSH(hw); usec_delay(phy->reset_delay_us); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_FLUSH(hw); usec_delay(150); phy->ops.release(hw); return phy->ops.get_cfg_done(hw); } /** * e1000_get_cfg_done_generic - Generic configuration done * @hw: pointer to the HW structure * * Generic function to wait 10 milli-seconds for configuration to complete * and return success. **/ s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw) { DEBUGFUNC("e1000_get_cfg_done_generic"); msec_delay_irq(10); return E1000_SUCCESS; } /** * e1000_phy_init_script_igp3 - Inits the IGP3 PHY * @hw: pointer to the HW structure * * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. **/ s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) { DEBUGOUT("Running IGP 3 PHY init script\n"); /* PHY init IGP 3 */ /* Enable rise/fall, 10-mode work in class-A */ hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); /* Remove all caps from Replica path filter */ hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); /* Bias trimming for ADC, AFE and Driver (Default) */ hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); /* Increase Hybrid poly bias */ hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); /* Add 4% to Tx amplitude in Gig mode */ hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); /* Disable trimming (TTT) */ hw->phy.ops.write_reg(hw, 0x2011, 0x0000); /* Poly DC correction to 94.6% + 2% for all channels */ hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); /* ABS DC correction to 95.9% */ hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); /* BG temp curve trim */ hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); /* Increasing ADC OPAMP stage 1 currents to max */ hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); /* Force 1000 ( required for enabling PHY regs configuration) */ hw->phy.ops.write_reg(hw, 0x0000, 0x0140); /* Set upd_freq to 6 */ hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); /* Disable NPDFE */ hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); /* Disable adaptive fixed FFE (Default) */ hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); /* Enable FFE hysteresis */ hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); /* Fixed FFE for short cable lengths */ hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); /* Fixed FFE for medium cable lengths */ hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); /* Fixed FFE for long cable lengths */ hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); /* Enable Adaptive Clip Threshold */ hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); /* AHT reset limit to 1 */ hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); /* Set AHT master delay to 127 msec */ hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); /* Set scan bits for AHT */ hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); /* Set AHT Preset bits */ hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); /* Change integ_factor of channel A to 3 */ hw->phy.ops.write_reg(hw, 0x1895, 0x0003); /* Change prop_factor of channels BCD to 8 */ hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); /* Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); /* Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ hw->phy.ops.write_reg(hw, 0x0019, 0x008D); /* Enable restart AN on an1000_dis change */ hw->phy.ops.write_reg(hw, 0x001B, 0x2080); /* Enable wh_fifo read clock in 10/100 modes */ hw->phy.ops.write_reg(hw, 0x0014, 0x0045); /* Restart AN, Speed selection is 1000 */ hw->phy.ops.write_reg(hw, 0x0000, 0x1340); return E1000_SUCCESS; } /** * e1000_get_phy_type_from_id - Get PHY type from id * @phy_id: phy_id read from the phy * * Returns the phy type from the id. **/ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) { enum e1000_phy_type phy_type = e1000_phy_unknown; switch (phy_id) { case M88E1000_I_PHY_ID: case M88E1000_E_PHY_ID: case M88E1111_I_PHY_ID: case M88E1011_I_PHY_ID: case M88E1543_E_PHY_ID: case I347AT4_E_PHY_ID: case M88E1112_E_PHY_ID: case M88E1340M_E_PHY_ID: phy_type = e1000_phy_m88; break; case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ phy_type = e1000_phy_igp_2; break; case GG82563_E_PHY_ID: phy_type = e1000_phy_gg82563; break; case IGP03E1000_E_PHY_ID: phy_type = e1000_phy_igp_3; break; case IFE_E_PHY_ID: case IFE_PLUS_E_PHY_ID: case IFE_C_E_PHY_ID: phy_type = e1000_phy_ife; break; case I82580_I_PHY_ID: phy_type = e1000_phy_82580; break; case I210_I_PHY_ID: phy_type = e1000_phy_i210; break; default: phy_type = e1000_phy_unknown; break; } return phy_type; } /** * e1000_determine_phy_address - Determines PHY address. * @hw: pointer to the HW structure * * This uses a trial and error method to loop through possible PHY * addresses. It tests each by reading the PHY ID registers and * checking for a match. **/ s32 e1000_determine_phy_address(struct e1000_hw *hw) { u32 phy_addr = 0; u32 i; enum e1000_phy_type phy_type = e1000_phy_unknown; hw->phy.id = phy_type; for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { hw->phy.addr = phy_addr; i = 0; do { e1000_get_phy_id(hw); phy_type = e1000_get_phy_type_from_id(hw->phy.id); /* If phy_type is valid, break - we found our * PHY address */ if (phy_type != e1000_phy_unknown) return E1000_SUCCESS; msec_delay(1); i++; } while (i < 10); } return -E1000_ERR_PHY_TYPE; } /** * e1000_power_up_phy_copper - Restore copper link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, restore the link to previous * settings. **/ void e1000_power_up_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg &= ~MII_CR_POWER_DOWN; if (hw->phy.type == e1000_phy_i210) { hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); power_reg &= ~GS40G_CS_POWER_DOWN; hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); } /** * e1000_power_down_phy_copper - Restore copper link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, restore the link to previous * settings. **/ void e1000_power_down_phy_copper(struct e1000_hw *hw) { u16 mii_reg = 0; u16 power_reg = 0; /* The PHY will retain its settings across a power down/up cycle */ hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); mii_reg |= MII_CR_POWER_DOWN; /* i210 Phy requires an additional bit for power up/down */ if (hw->phy.type == e1000_phy_i210) { hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); power_reg |= GS40G_CS_POWER_DOWN; hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); } hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); msec_delay(1); } /** * e1000_check_polarity_82577 - Checks the polarity. * @hw: pointer to the HW structure * * Success returns 0, Failure returns -E1000_ERR_PHY (-2) * * Polarity is determined based on the PHY specific status register. **/ s32 e1000_check_polarity_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; DEBUGFUNC("e1000_check_polarity_82577"); ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); if (!ret_val) phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY) ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal); return ret_val; } /** * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY * @hw: pointer to the HW structure * * Calls the PHY setup function to force speed and duplex. **/ s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data; bool link; DEBUGFUNC("e1000_phy_force_speed_duplex_82577"); ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); if (ret_val) return ret_val; e1000_phy_force_speed_duplex_setup(hw, &phy_data); ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); if (ret_val) return ret_val; usec_delay(1); if (phy->autoneg_wait_to_complete) { DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n"); ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) return ret_val; if (!link) DEBUGOUT("Link taking longer than expected.\n"); /* Try once more */ ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); } return ret_val; } /** * e1000_get_phy_info_82577 - Retrieve I82577 PHY information * @hw: pointer to the HW structure * * Read PHY status to determine if link is up. If link is up, then * set/determine 10base-T extended distance and polarity correction. Read * PHY port status to determine MDI/MDIx and speed. Based on the speed, * determine on the cable length, local and remote receiver. **/ s32 e1000_get_phy_info_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 data; bool link; DEBUGFUNC("e1000_get_phy_info_82577"); ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) return ret_val; if (!link) { DEBUGOUT("Phy info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } phy->polarity_correction = true; ret_val = e1000_check_polarity_82577(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); if (ret_val) return ret_val; phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX); if ((data & I82577_PHY_STATUS2_SPEED_MASK) == I82577_PHY_STATUS2_SPEED_1000MBPS) { ret_val = hw->phy.ops.get_cable_length(hw); if (ret_val) return ret_val; ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); if (ret_val) return ret_val; phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; } else { phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; phy->local_rx = e1000_1000t_rx_status_undefined; phy->remote_rx = e1000_1000t_rx_status_undefined; } return E1000_SUCCESS; } /** * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY * @hw: pointer to the HW structure * * Reads the diagnostic status register and verifies result is valid before * placing it in the phy_cable_length field. **/ s32 e1000_get_cable_length_82577(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; u16 phy_data, length; DEBUGFUNC("e1000_get_cable_length_82577"); ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data); if (ret_val) return ret_val; length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >> I82577_DSTATUS_CABLE_LENGTH_SHIFT); if (length == E1000_CABLE_LENGTH_UNDEFINED) return -E1000_ERR_PHY; phy->cable_length = length; return E1000_SUCCESS; } /** * e1000_write_phy_reg_gs40g - Write GS40G PHY register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset * * Acquires semaphore, if necessary, then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data) { s32 ret_val; u16 page = offset >> GS40G_PAGE_SHIFT; DEBUGFUNC("e1000_write_phy_reg_gs40g"); offset = offset & GS40G_OFFSET_MASK; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); if (ret_val) goto release; ret_val = e1000_write_phy_reg_mdic(hw, offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_gs40g - Read GS40G PHY register * @hw: pointer to the HW structure * @offset: lower half is register offset to read to * upper half is page to use. * @data: data to read at register offset * * Acquires semaphore, if necessary, then reads the data in the PHY register * at the offset. Release any acquired semaphores before exiting. **/ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data) { s32 ret_val; u16 page = offset >> GS40G_PAGE_SHIFT; DEBUGFUNC("e1000_read_phy_reg_gs40g"); offset = offset & GS40G_OFFSET_MASK; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); if (ret_val) goto release; ret_val = e1000_read_phy_reg_mdic(hw, offset, data); release: hw->phy.ops.release(hw); return ret_val; } /** * e1000_read_phy_reg_mphy - Read mPHY control register * @hw: pointer to the HW structure * @address: address to be read * @data: pointer to the read data * * Reads the mPHY control register in the PHY at offset and stores the * information read to data. **/ s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data) { u32 mphy_ctrl = 0; bool locked = false; bool ready = false; DEBUGFUNC("e1000_read_phy_reg_mphy"); /* Check if mPHY is ready to read/write operations */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* Check if mPHY access is disabled and enable it if so */ mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) { locked = true; ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; mphy_ctrl |= E1000_MPHY_ENA_ACCESS; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); } /* Set the address that we want to read */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* We mask address, because we want to use only current lane */ mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK & ~E1000_MPHY_ADDRESS_FNC_OVERRIDE) | (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; *data = E1000_READ_REG(hw, E1000_MPHY_DATA); /* Disable access to mPHY if it was originally disabled */ if (locked) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); return E1000_SUCCESS; } /** * e1000_write_phy_reg_mphy - Write mPHY control register * @hw: pointer to the HW structure * @address: address to write to * @data: data to write to register at offset * @line_override: used when we want to use different line than default one * * Writes data to mPHY control register. **/ s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, bool line_override) { u32 mphy_ctrl = 0; bool locked = false; bool ready = false; DEBUGFUNC("e1000_write_phy_reg_mphy"); /* Check if mPHY is ready to read/write operations */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* Check if mPHY access is disabled and enable it if so */ mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) { locked = true; ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; mphy_ctrl |= E1000_MPHY_ENA_ACCESS; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); } /* Set the address that we want to read */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; /* We mask address, because we want to use only current lane */ if (line_override) mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE; else mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE; mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) | (address & E1000_MPHY_ADDRESS_MASK); E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl); /* Read data from the address */ ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_DATA, data); /* Disable access to mPHY if it was originally disabled */ if (locked) ready = e1000_is_mphy_ready(hw); if (!ready) return -E1000_ERR_PHY; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, E1000_MPHY_DIS_ACCESS); return E1000_SUCCESS; } /** * e1000_is_mphy_ready - Check if mPHY control register is not busy * @hw: pointer to the HW structure * * Returns mPHY control register status. **/ bool e1000_is_mphy_ready(struct e1000_hw *hw) { u16 retry_count = 0; u32 mphy_ctrl = 0; bool ready = false; while (retry_count < 2) { mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL); if (mphy_ctrl & E1000_MPHY_BUSY) { usec_delay(20); retry_count++; continue; } ready = true; break; } if (!ready) DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n"); return ready; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_phy.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_PHY_H_ #define _E1000_PHY_H_ void e1000_init_phy_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data); void e1000_null_phy_generic(struct e1000_hw *hw); s32 e1000_null_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_null_set_page(struct e1000_hw *hw, u16 data); s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 e1000_check_downshift_generic(struct e1000_hw *hw); s32 e1000_check_polarity_m88(struct e1000_hw *hw); s32 e1000_check_polarity_igp(struct e1000_hw *hw); s32 e1000_check_polarity_ife(struct e1000_hw *hw); s32 e1000_check_reset_block_generic(struct e1000_hw *hw); s32 e1000_copper_link_setup_igp(struct e1000_hw *hw); s32 e1000_copper_link_setup_m88(struct e1000_hw *hw); s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); s32 e1000_get_cable_length_m88(struct e1000_hw *hw); s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw); s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw); s32 e1000_get_cfg_done_generic(struct e1000_hw *hw); s32 e1000_get_phy_id(struct e1000_hw *hw); s32 e1000_get_phy_info_igp(struct e1000_hw *hw); s32 e1000_get_phy_info_m88(struct e1000_hw *hw); s32 e1000_get_phy_info_ife(struct e1000_hw *hw); s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw); void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id); s32 e1000_determine_phy_address(struct e1000_hw *hw); s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); void e1000_power_up_phy_copper(struct e1000_hw *hw); void e1000_power_down_phy_copper(struct e1000_hw *hw); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data); s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data); s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); s32 e1000_check_polarity_82577(struct e1000_hw *hw); s32 e1000_get_phy_info_82577(struct e1000_hw *hw); s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); s32 e1000_get_cable_length_82577(struct e1000_hw *hw); s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data); s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data, bool line_override); bool e1000_is_mphy_ready(struct e1000_hw *hw); #define E1000_MAX_PHY_ADDR 8 /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ #define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ #define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ #define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ #define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ #define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ #define IGP_PAGE_SHIFT 5 #define PHY_REG_MASK 0x1F /* GS40G - I210 PHY defines */ #define GS40G_PAGE_SELECT 0x16 #define GS40G_PAGE_SHIFT 16 #define GS40G_OFFSET_MASK 0xFFFF #define GS40G_PAGE_2 0x20000 #define GS40G_MAC_REG2 0x15 #define GS40G_MAC_LB 0x4140 #define GS40G_MAC_SPEED_1G 0X0006 #define GS40G_COPPER_SPEC 0x0010 #define GS40G_CS_POWER_DOWN 0x0002 #define HV_INTC_FC_PAGE_START 768 #define I82578_ADDR_REG 29 #define I82577_ADDR_REG 16 #define I82577_CFG_REG 22 #define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) #define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */ #define I82577_CTRL_REG 23 /* 82577 specific PHY registers */ #define I82577_PHY_CTRL_2 18 #define I82577_PHY_LBK_CTRL 19 #define I82577_PHY_STATUS_2 26 #define I82577_PHY_DIAG_STATUS 31 /* I82577 PHY Status 2 */ #define I82577_PHY_STATUS2_REV_POLARITY 0x0400 #define I82577_PHY_STATUS2_MDIX 0x0800 #define I82577_PHY_STATUS2_SPEED_MASK 0x0300 #define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 /* I82577 PHY Control 2 */ #define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 #define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 #define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 /* I82577 PHY Diagnostics Status */ #define I82577_DSTATUS_CABLE_LENGTH 0x03FC #define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 /* 82580 PHY Power Management */ #define E1000_82580_PHY_POWER_MGMT 0xE14 #define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ #define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ #define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ #define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ #define E1000_MPHY_DIS_ACCESS 0x80000000 /* disable_access bit */ #define E1000_MPHY_ENA_ACCESS 0x40000000 /* enable_access bit */ #define E1000_MPHY_BUSY 0x00010000 /* busy bit */ #define E1000_MPHY_ADDRESS_FNC_OVERRIDE 0x20000000 /* fnc_override bit */ #define E1000_MPHY_ADDRESS_MASK 0x0000FFFF /* address mask */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078 #define IGP01E1000_PSCR_AUTO_MDIX 0x1000 #define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ #define IGP01E1000_PSCFR_SMART_SPEED 0x0080 #define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ #define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ #define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ #define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 #define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 #define IGP01E1000_PSSR_MDIX 0x0800 #define IGP01E1000_PSSR_SPEED_MASK 0xC000 #define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 #define IGP02E1000_PHY_CHANNEL_NUM 4 #define IGP02E1000_PHY_AGC_A 0x11B1 #define IGP02E1000_PHY_AGC_B 0x12B1 #define IGP02E1000_PHY_AGC_C 0x14B1 #define IGP02E1000_PHY_AGC_D 0x18B1 #define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */ #define IGP02E1000_AGC_LENGTH_MASK 0x7F #define IGP02E1000_AGC_RANGE 15 #define E1000_CABLE_LENGTH_UNDEFINED 0xFF #define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 #define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 #define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ #define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */ #define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ /* IFE PHY Extended Status Control */ #define IFE_PESC_POLARITY_REVERSED 0x0100 /* IFE PHY Special Control */ #define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 #define IFE_PSC_FORCE_POLARITY 0x0020 /* IFE PHY Special Control and LED Control */ #define IFE_PSCL_PROBE_MODE 0x0020 #define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ #define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ /* IFE PHY MDIX Control */ #define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ #define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ #define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */ /* SFP modules ID memory locations */ #define E1000_SFF_IDENTIFIER_OFFSET 0x00 #define E1000_SFF_IDENTIFIER_SFF 0x02 #define E1000_SFF_IDENTIFIER_SFP 0x03 #define E1000_SFF_ETH_FLAGS_OFFSET 0x06 /* Flags for SFP modules compatible with ETH up to 1Gb */ struct sfp_e1000_flags { u8 e1000_base_sx:1; u8 e1000_base_lx:1; u8 e1000_base_cx:1; u8 e1000_base_t:1; u8 e100_base_lx:1; u8 e100_base_fx:1; u8 e10_base_bx10:1; u8 e10_base_px:1; }; /* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */ #define E1000_SFF_VENDOR_OUI_TYCO 0x00407600 #define E1000_SFF_VENDOR_OUI_FTL 0x00906500 #define E1000_SFF_VENDOR_OUI_AVAGO 0x00176A00 #define E1000_SFF_VENDOR_OUI_INTEL 0x001B2100 #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/e1000_regs.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _E1000_REGS_H_ #define _E1000_REGS_H_ #define E1000_CTRL 0x00000 /* Device Control - RW */ #define E1000_STATUS 0x00008 /* Device Status - RO */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_MDICNFG 0x00E04 /* MDI Config - RW */ #define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */ #define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */ #define E1000_EEPROM_PCIE_CTRL_WORD_2 0x28 /* EEPROM PCIe Ctrl Word 2 */ #define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */ #define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */ #define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */ #define E1000_MPHY_ADDR_CTRL 0x0024 /* GbE MPHY Address Control */ #define E1000_MPHY_DATA 0x0E10 /* GBE MPHY Data */ #define E1000_MPHY_STAT 0x0E0C /* GBE MPHY Statistics */ #define E1000_PPHY_CTRL 0x5b48 /* PCIe PHY Control */ #define E1000_I350_BARCTRL 0x5BFC /* BAR ctrl reg */ #define E1000_I350_DTXMXPKTSZ 0x355C /* Maximum sent packet size reg*/ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ #define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ #define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ #define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ #define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ #define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ #define E1000_RCTL 0x00100 /* Rx Control - RW */ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ #define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ #define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ #define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ #define E1000_EITR(_n) (0x01680 + (0x4 * (_n))) #define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */ #define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ #define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ #define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ #define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ #define E1000_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */ #define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */ #define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */ #define E1000_TCTL 0x00400 /* Tx Control - RW */ #define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ #define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ #define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ #define E1000_LEDCTL 0x00E00 /* LED Control - RW */ #define E1000_LEDMUX 0x08130 /* LED MUX Control */ #define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ #define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ #define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ #define E1000_FLOP 0x0103C /* FLASH Opcode Register */ #define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ #define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ #define E1000_I2CBB_EN 0x00000100 /* I2C - Bit Bang Enable */ #define E1000_I2C_CLK_OUT 0x00000200 /* I2C- Clock */ #define E1000_I2C_DATA_OUT 0x00000400 /* I2C- Data Out */ #define E1000_I2C_DATA_OE_N 0x00000800 /* I2C- Data Output Enable */ #define E1000_I2C_DATA_IN 0x00001000 /* I2C- Data In */ #define E1000_I2C_CLK_OE_N 0x00002000 /* I2C- Clock Output Enable */ #define E1000_I2C_CLK_IN 0x00004000 /* I2C- Clock In */ #define E1000_I2C_CLK_STRETCH_DIS 0x00008000 /* I2C- Dis Clk Stretching */ #define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ #define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ #define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ #define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ #define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ #define E1000_ICR_V2 0x01500 /* Intr Cause - new location - RC */ #define E1000_ICS_V2 0x01504 /* Intr Cause Set - new location - WO */ #define E1000_IMS_V2 0x01508 /* Intr Mask Set/Read - new location - RW */ #define E1000_IMC_V2 0x0150C /* Intr Mask Clear - new location - WO */ #define E1000_IAM_V2 0x01510 /* Intr Ack Auto Mask - new location - RW */ #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ #define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ #define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ #define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ #define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ #define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ #define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ /* Split and Replication Rx Control - RW */ #define E1000_RDPUMB 0x025CC /* DMA Rx Descriptor uC Mailbox - RW */ #define E1000_RDPUAD 0x025D0 /* DMA Rx Descriptor uC Addr Command - RW */ #define E1000_RDPUWD 0x025D4 /* DMA Rx Descriptor uC Data Write - RW */ #define E1000_RDPURD 0x025D8 /* DMA Rx Descriptor uC Data Read - RW */ #define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ #define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ #define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer Si - RW */ #define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */ #define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ #define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ #define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */ #define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */ #define E1000_SRWR 0x12018 /* Shadow Ram Write Register - RW */ #define E1000_I210_FLMNGCTL 0x12038 #define E1000_I210_FLMNGDATA 0x1203C #define E1000_I210_FLMNGCNT 0x12040 #define E1000_I210_FLSWCTL 0x12048 #define E1000_I210_FLSWDATA 0x1204C #define E1000_I210_FLSWCNT 0x12050 #define E1000_I210_FLA 0x1201C #define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n)) #define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */ /* QAV Tx mode control register */ #define E1000_I210_TQAVCTRL 0x3570 /* QAV Tx mode control register bitfields masks */ /* QAV enable */ #define E1000_TQAVCTRL_MODE (1 << 0) /* Fetching arbitration type */ #define E1000_TQAVCTRL_FETCH_ARB (1 << 4) /* Fetching timer enable */ #define E1000_TQAVCTRL_FETCH_TIMER_ENABLE (1 << 5) /* Launch arbitration type */ #define E1000_TQAVCTRL_LAUNCH_ARB (1 << 8) /* Launch timer enable */ #define E1000_TQAVCTRL_LAUNCH_TIMER_ENABLE (1 << 9) /* SP waits for SR enable */ #define E1000_TQAVCTRL_SP_WAIT_SR (1 << 10) /* Fetching timer correction */ #define E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET 16 #define E1000_TQAVCTRL_FETCH_TIMER_DELTA \ (0xFFFF << E1000_TQAVCTRL_FETCH_TIMER_DELTA_OFFSET) /* High credit registers where _n can be 0 or 1. */ #define E1000_I210_TQAVHC(_n) (0x300C + 0x40 * (_n)) /* Queues fetch arbitration priority control register */ #define E1000_I210_TQAVARBCTRL 0x3574 /* Queues priority masks where _n and _p can be 0-3. */ #define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n)) /* QAV Tx mode control registers where _n can be 0 or 1. */ #define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n)) /* QAV Tx mode control register bitfields masks */ #define E1000_TQAVCC_IDLE_SLOPE 0xFFFF /* Idle slope */ #define E1000_TQAVCC_KEEP_CREDITS (1 << 30) /* Keep credits opt enable */ #define E1000_TQAVCC_QUEUE_MODE (1 << 31) /* SP vs. SR Tx mode */ /* Good transmitted packets counter registers */ #define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n))) /* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */ #define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n)) #define E1000_MMDAC 13 /* MMD Access Control */ #define E1000_MMDAAD 14 /* MMD Access Address/Data */ /* Convenience macros * * Note: "_n" is the queue number of the register to be written to. * * Example usage: * E1000_RDBAL_REG(current_rx_queue) */ #define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ (0x0C000 + ((_n) * 0x40))) #define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ (0x0C004 + ((_n) * 0x40))) #define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ (0x0C008 + ((_n) * 0x40))) #define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \ (0x0C00C + ((_n) * 0x40))) #define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ (0x0C010 + ((_n) * 0x40))) #define E1000_RXCTL(_n) ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ (0x0C014 + ((_n) * 0x40))) #define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) #define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ (0x0C018 + ((_n) * 0x40))) #define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ (0x0C028 + ((_n) * 0x40))) #define E1000_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \ (0x0C030 + ((_n) * 0x40))) #define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ (0x0E000 + ((_n) * 0x40))) #define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ (0x0E004 + ((_n) * 0x40))) #define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ (0x0E008 + ((_n) * 0x40))) #define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ (0x0E010 + ((_n) * 0x40))) #define E1000_TXCTL(_n) ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ (0x0E014 + ((_n) * 0x40))) #define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) #define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ (0x0E028 + ((_n) * 0x40))) #define E1000_TDWBAL(_n) ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) : \ (0x0E038 + ((_n) * 0x40))) #define E1000_TDWBAH(_n) ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) : \ (0x0E03C + ((_n) * 0x40))) #define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) #define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ #define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ #define E1000_PSRTYPE(_i) (0x05480 + ((_i) * 4)) #define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ (0x054E0 + ((_i - 16) * 8))) #define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ (0x054E4 + ((_i - 16) * 8))) #define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) #define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) #define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8)) #define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4)) #define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4)) #define E1000_FFMT_REG(_i) (0x09000 + ((_i) * 8)) #define E1000_FFVT_REG(_i) (0x09800 + ((_i) * 8)) #define E1000_FFLT_REG(_i) (0x05F00 + ((_i) * 8)) #define E1000_PBSLAC 0x03100 /* Pkt Buffer Slave Access Control */ #define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) /* Pkt Buffer DWORD */ #define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ /* Same as TXPBS, renamed for newer Si - RW */ #define E1000_ITPBS 0x03404 #define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ #define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ #define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ #define E1000_TDPUMB 0x0357C /* DMA Tx Desc uC Mail Box - RW */ #define E1000_TDPUAD 0x03580 /* DMA Tx Desc uC Addr Command - RW */ #define E1000_TDPUWD 0x03584 /* DMA Tx Desc uC Data Write - RW */ #define E1000_TDPURD 0x03588 /* DMA Tx Desc uC Data Read - RW */ #define E1000_TDPUCTL 0x0358C /* DMA Tx Desc uC Control - RW */ #define E1000_DTXCTL 0x03590 /* DMA Tx Control - RW */ #define E1000_DTXTCPFLGL 0x0359C /* DMA Tx Control flag low - RW */ #define E1000_DTXTCPFLGH 0x035A0 /* DMA Tx Control flag high - RW */ /* DMA Tx Max Total Allow Size Reqs - RW */ #define E1000_DTXMXSZRQ 0x03540 #define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ #define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ #define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ #define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ #define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ #define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ #define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ #define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ #define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ #define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ #define E1000_COLC 0x04028 /* Collision Count - R/clr */ #define E1000_DC 0x04030 /* Defer Count - R/clr */ #define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ #define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ #define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ #define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ #define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ #define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ #define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ #define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ #define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ #define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ #define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ #define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ #define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ #define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ #define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ #define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ #define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ #define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ #define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ #define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ #define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ #define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ #define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ #define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ #define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ #define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ #define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ #define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ #define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ #define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ #define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ #define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ #define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ #define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ #define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ #define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ #define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ #define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ #define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ #define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ #define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ #define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ #define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ #define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ #define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ #define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ #define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ #define E1000_IAC 0x04100 /* Interrupt Assertion Count */ #define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ #define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ #define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ #define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ #define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ #define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ #define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ #define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ /* Virtualization statistical counters */ #define E1000_PFVFGPRC(_n) (0x010010 + (0x100 * (_n))) #define E1000_PFVFGPTC(_n) (0x010014 + (0x100 * (_n))) #define E1000_PFVFGORC(_n) (0x010018 + (0x100 * (_n))) #define E1000_PFVFGOTC(_n) (0x010034 + (0x100 * (_n))) #define E1000_PFVFMPRC(_n) (0x010038 + (0x100 * (_n))) #define E1000_PFVFGPRLBC(_n) (0x010040 + (0x100 * (_n))) #define E1000_PFVFGPTLBC(_n) (0x010044 + (0x100 * (_n))) #define E1000_PFVFGORLBC(_n) (0x010048 + (0x100 * (_n))) #define E1000_PFVFGOTLBC(_n) (0x010050 + (0x100 * (_n))) /* LinkSec */ #define E1000_LSECTXUT 0x04300 /* Tx Untagged Pkt Cnt */ #define E1000_LSECTXPKTE 0x04304 /* Encrypted Tx Pkts Cnt */ #define E1000_LSECTXPKTP 0x04308 /* Protected Tx Pkt Cnt */ #define E1000_LSECTXOCTE 0x0430C /* Encrypted Tx Octets Cnt */ #define E1000_LSECTXOCTP 0x04310 /* Protected Tx Octets Cnt */ #define E1000_LSECRXUT 0x04314 /* Untagged non-Strict Rx Pkt Cnt */ #define E1000_LSECRXOCTD 0x0431C /* Rx Octets Decrypted Count */ #define E1000_LSECRXOCTV 0x04320 /* Rx Octets Validated */ #define E1000_LSECRXBAD 0x04324 /* Rx Bad Tag */ #define E1000_LSECRXNOSCI 0x04328 /* Rx Packet No SCI Count */ #define E1000_LSECRXUNSCI 0x0432C /* Rx Packet Unknown SCI Count */ #define E1000_LSECRXUNCH 0x04330 /* Rx Unchecked Packets Count */ #define E1000_LSECRXDELAY 0x04340 /* Rx Delayed Packet Count */ #define E1000_LSECRXLATE 0x04350 /* Rx Late Packets Count */ #define E1000_LSECRXOK(_n) (0x04360 + (0x04 * (_n))) /* Rx Pkt OK Cnt */ #define E1000_LSECRXINV(_n) (0x04380 + (0x04 * (_n))) /* Rx Invalid Cnt */ #define E1000_LSECRXNV(_n) (0x043A0 + (0x04 * (_n))) /* Rx Not Valid Cnt */ #define E1000_LSECRXUNSA 0x043C0 /* Rx Unused SA Count */ #define E1000_LSECRXNUSA 0x043D0 /* Rx Not Using SA Count */ #define E1000_LSECTXCAP 0x0B000 /* Tx Capabilities Register - RO */ #define E1000_LSECRXCAP 0x0B300 /* Rx Capabilities Register - RO */ #define E1000_LSECTXCTRL 0x0B004 /* Tx Control - RW */ #define E1000_LSECRXCTRL 0x0B304 /* Rx Control - RW */ #define E1000_LSECTXSCL 0x0B008 /* Tx SCI Low - RW */ #define E1000_LSECTXSCH 0x0B00C /* Tx SCI High - RW */ #define E1000_LSECTXSA 0x0B010 /* Tx SA0 - RW */ #define E1000_LSECTXPN0 0x0B018 /* Tx SA PN 0 - RW */ #define E1000_LSECTXPN1 0x0B01C /* Tx SA PN 1 - RW */ #define E1000_LSECRXSCL 0x0B3D0 /* Rx SCI Low - RW */ #define E1000_LSECRXSCH 0x0B3E0 /* Rx SCI High - RW */ /* LinkSec Tx 128-bit Key 0 - WO */ #define E1000_LSECTXKEY0(_n) (0x0B020 + (0x04 * (_n))) /* LinkSec Tx 128-bit Key 1 - WO */ #define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) #define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* Rx SAs - RW */ #define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* Rx SAs - RW */ /* LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit * key - RW. */ #define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) #define E1000_SSVPC 0x041A0 /* Switch Security Violation Pkt Cnt */ #define E1000_IPSCTRL 0xB430 /* IpSec Control Register */ #define E1000_IPSRXCMD 0x0B408 /* IPSec Rx Command Register - RW */ #define E1000_IPSRXIDX 0x0B400 /* IPSec Rx Index - RW */ /* IPSec Rx IPv4/v6 Address - RW */ #define E1000_IPSRXIPADDR(_n) (0x0B420 + (0x04 * (_n))) /* IPSec Rx 128-bit Key - RW */ #define E1000_IPSRXKEY(_n) (0x0B410 + (0x04 * (_n))) #define E1000_IPSRXSALT 0x0B404 /* IPSec Rx Salt - RW */ #define E1000_IPSRXSPI 0x0B40C /* IPSec Rx SPI - RW */ /* IPSec Tx 128-bit Key - RW */ #define E1000_IPSTXKEY(_n) (0x0B460 + (0x04 * (_n))) #define E1000_IPSTXSALT 0x0B454 /* IPSec Tx Salt - RW */ #define E1000_IPSTXIDX 0x0B450 /* IPSec Tx SA IDX - RW */ #define E1000_PCS_CFG0 0x04200 /* PCS Configuration 0 - RW */ #define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ #define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ #define E1000_CBTMPC 0x0402C /* Circuit Breaker Tx Packet Count */ #define E1000_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ #define E1000_CBRDPC 0x04044 /* Circuit Breaker Rx Dropped Count */ #define E1000_CBRMPC 0x040FC /* Circuit Breaker Rx Packet Count */ #define E1000_RPTHC 0x04104 /* Rx Packets To Host */ #define E1000_HGPTC 0x04118 /* Host Good Packets Tx Count */ #define E1000_HTCBDPC 0x04124 /* Host Tx Circuit Breaker Dropped Count */ #define E1000_HGORCL 0x04128 /* Host Good Octets Received Count Low */ #define E1000_HGORCH 0x0412C /* Host Good Octets Received Count High */ #define E1000_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ #define E1000_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ #define E1000_LENERRS 0x04138 /* Length Errors Count */ #define E1000_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ #define E1000_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ #define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ #define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ #define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ #define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Pg - RW */ #define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ #define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ #define E1000_RFCTL 0x05008 /* Receive Filter Control*/ #define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ #define E1000_RA 0x05400 /* Receive Address - RW Array */ #define E1000_RA2 0x054E0 /* 2nd half of Rx address array - RW Array */ #define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ #define E1000_VT_CTL 0x0581C /* VMDq Control - RW */ #define E1000_CIAA 0x05B88 /* Config Indirect Access Address - RW */ #define E1000_CIAD 0x05B8C /* Config Indirect Access Data - RW */ #define E1000_VFQA0 0x0B000 /* VLAN Filter Queue Array 0 - RW Array */ #define E1000_VFQA1 0x0B200 /* VLAN Filter Queue Array 1 - RW Array */ #define E1000_WUC 0x05800 /* Wakeup Control - RW */ #define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ #define E1000_WUS 0x05810 /* Wakeup Status - RO */ #define E1000_MANC 0x05820 /* Management Control - RW */ #define E1000_IPAV 0x05838 /* IP Address Valid - RW */ #define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ #define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ #define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ #define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ #define E1000_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */ #define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ #define E1000_HOST_IF 0x08800 /* Host Interface */ #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ #define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ #define E1000_HIBBA 0x8F40 /* Host Interface Buffer Base Address */ /* Flexible Host Filter Table */ #define E1000_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Ext Flexible Host Filter Table */ #define E1000_FHFT_EXT(_n) (0x09A00 + ((_n) * 0x100)) #define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ #define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ /* Management Decision Filters */ #define E1000_MDEF(_n) (0x05890 + (4 * (_n))) #define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ #define E1000_CCMCTL 0x05B48 /* CCM Control Register */ #define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */ #define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */ #define E1000_GCR 0x05B00 /* PCI-Ex Control */ #define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ #define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ #define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ #define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ #define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ #define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ #define E1000_SWSM 0x05B50 /* SW Semaphore */ #define E1000_FWSM 0x05B54 /* FW Semaphore */ /* Driver-only SW semaphore (not used by BOOT agents) */ #define E1000_SWSM2 0x05B58 #define E1000_DCA_ID 0x05B70 /* DCA Requester ID Information - RO */ #define E1000_DCA_CTRL 0x05B74 /* DCA Control - RW */ #define E1000_UFUSE 0x05B78 /* UFUSE - RO */ #define E1000_FFLT_DBG 0x05F04 /* Debug Register */ #define E1000_HICR 0x08F00 /* Host Interface Control */ #define E1000_FWSTS 0x08F0C /* FW Status */ /* RSS registers */ #define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ #define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ #define E1000_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */ #define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/ #define E1000_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */ #define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */ #define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ #define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ #define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ /* VT Registers */ #define E1000_SWPBS 0x03004 /* Switch Packet Buffer Size - RW */ #define E1000_MBVFICR 0x00C80 /* Mailbox VF Cause - RWC */ #define E1000_MBVFIMR 0x00C84 /* Mailbox VF int Mask - RW */ #define E1000_VFLRE 0x00C88 /* VF Register Events - RWC */ #define E1000_VFRE 0x00C8C /* VF Receive Enables */ #define E1000_VFTE 0x00C90 /* VF Transmit Enables */ #define E1000_QDE 0x02408 /* Queue Drop Enable - RW */ #define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */ #define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */ #define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */ #define E1000_UTA 0x0A000 /* Unicast Table Array - RW */ #define E1000_IOVTCL 0x05BBC /* IOV Control Register */ #define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */ #define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */ #define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */ #define E1000_MDFB 0x03558 /* Malicious Driver free block */ #define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */ #define E1000_TXSWC 0x05ACC /* Tx Switch Control */ #define E1000_SCCRL 0x05DB0 /* Storm Control Control */ #define E1000_BSCTRH 0x05DB8 /* Broadcast Storm Control Threshold */ #define E1000_MSCTRH 0x05DBC /* Multicast Storm Control Threshold */ /* These act per VF so an array friendly macro is used */ #define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n))) #define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n))) #define E1000_VMBMEM(_n) (0x00800 + (64 * (_n))) #define E1000_VFVMBMEM(_n) (0x00800 + (_n)) #define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) /* VLAN Virtual Machine Filter - RW */ #define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) #define E1000_VMVIR(_n) (0x03700 + (4 * (_n))) #define E1000_DVMOLR(_n) (0x0C038 + (0x40 * (_n))) /* DMA VM offload */ #define E1000_VTCTRL(_n) (0x10000 + (0x100 * (_n))) /* VT Control */ #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ #define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ #define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */ #define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ #define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ #define E1000_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */ #define E1000_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */ #define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ #define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ #define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ #define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ #define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ /* Filtering Registers */ #define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ #define E1000_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */ #define E1000_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */ #define E1000_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */ #define E1000_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */ #define E1000_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */ #define E1000_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */ #define E1000_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */ #define E1000_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */ #define E1000_RTRPCS 0x2474 /* Rx packet plane control and status */ #define E1000_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */ #define E1000_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */ /* Tx Desc plane TC Rate-scheduler config */ #define E1000_RTTDTCRC(_n) (0x3610 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Config */ #define E1000_RTTPTCRC(_n) (0x3480 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Config */ #define E1000_RTRPTCRC(_n) (0x2480 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler Status */ #define E1000_RTTDTCRS(_n) (0x3630 + ((_n) * 4)) /* Tx Desc Plane TC Rate-Scheduler MMW */ #define E1000_RTTDTCRM(_n) (0x3650 + ((_n) * 4)) /* Tx Packet plane TC Rate-Scheduler Status */ #define E1000_RTTPTCRS(_n) (0x34A0 + ((_n) * 4)) /* Tx Packet plane TC Rate-scheduler MMW */ #define E1000_RTTPTCRM(_n) (0x34C0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler Status */ #define E1000_RTRPTCRS(_n) (0x24A0 + ((_n) * 4)) /* Rx Packet plane TC Rate-Scheduler MMW */ #define E1000_RTRPTCRM(_n) (0x24C0 + ((_n) * 4)) /* Tx Desc plane VM Rate-Scheduler MMW*/ #define E1000_RTTDVMRM(_n) (0x3670 + ((_n) * 4)) /* Tx BCN Rate-Scheduler MMW */ #define E1000_RTTBCNRM(_n) (0x3690 + ((_n) * 4)) #define E1000_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */ #define E1000_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */ #define E1000_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */ #define E1000_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */ #define E1000_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */ #define E1000_RTTBCNCR 0xB200 /* Tx BCN Control Register */ #define E1000_RTTBCNTG 0x35A4 /* Tx BCN Tagging */ #define E1000_RTTBCNCP 0xB208 /* Tx BCN Congestion point */ #define E1000_RTRBCNCR 0xB20C /* Rx BCN Control Register */ #define E1000_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */ #define E1000_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */ #define E1000_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */ #define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ #define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ /* DMA Coalescing registers */ #define E1000_DMACR 0x02508 /* Control Register */ #define E1000_DMCTXTH 0x03550 /* Transmit Threshold */ #define E1000_DMCTLX 0x02514 /* Time to Lx Request */ #define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */ #define E1000_DMCCNT 0x05DD4 /* Current Rx Count */ #define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */ #define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ /* PCIe Parity Status Register */ #define E1000_PCIEERRSTS 0x05BA8 #define E1000_PROXYS 0x5F64 /* Proxying Status */ #define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */ /* Thermal sensor configuration and status registers */ #define E1000_THMJT 0x08100 /* Junction Temperature */ #define E1000_THLOWTC 0x08104 /* Low Threshold Control */ #define E1000_THMIDTC 0x08108 /* Mid Threshold Control */ #define E1000_THHIGHTC 0x0810C /* High Threshold Control */ #define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ /* Energy Efficient Ethernet "EEE" registers */ #define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ #define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */ #define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/ #define E1000_EEE_SU 0x0E34 /* EEE Setup */ #define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */ #define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */ /* OS2BMC Registers */ #define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */ #define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */ #define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ #define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* Linux PRO/1000 Ethernet Driver main header file */ #ifndef _IGB_H_ #define _IGB_H_ #include #ifndef IGB_NO_LRO #include #endif #undef HAVE_HW_TIME_STAMP #ifdef HAVE_HW_TIME_STAMP #include #include #include #endif #ifdef SIOCETHTOOL #include #endif struct igb_adapter; #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) //#define IGB_DCA #endif #ifdef IGB_DCA #include #endif #include "kcompat.h" #ifdef HAVE_SCTP #include #endif #include "e1000_api.h" #include "e1000_82575.h" #include "e1000_manage.h" #include "e1000_mbx.h" #define IGB_ERR(args...) printk(KERN_ERR "igb: " args) #define PFX "igb: " #define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ __FUNCTION__ , ## args)) #ifdef HAVE_PTP_1588_CLOCK #include #include #include #endif /* HAVE_PTP_1588_CLOCK */ #ifdef HAVE_I2C_SUPPORT #include #include #endif /* HAVE_I2C_SUPPORT */ /* Interrupt defines */ #define IGB_START_ITR 648 /* ~6000 ints/sec */ #define IGB_4K_ITR 980 #define IGB_20K_ITR 196 #define IGB_70K_ITR 56 /* Interrupt modes, as used by the IntMode parameter */ #define IGB_INT_MODE_LEGACY 0 #define IGB_INT_MODE_MSI 1 #define IGB_INT_MODE_MSIX 2 /* TX/RX descriptor defines */ #define IGB_DEFAULT_TXD 256 #define IGB_DEFAULT_TX_WORK 128 #define IGB_MIN_TXD 80 #define IGB_MAX_TXD 4096 #define IGB_DEFAULT_RXD 256 #define IGB_MIN_RXD 80 #define IGB_MAX_RXD 4096 #define IGB_MIN_ITR_USECS 10 /* 100k irq/sec */ #define IGB_MAX_ITR_USECS 8191 /* 120 irq/sec */ #define NON_Q_VECTORS 1 #define MAX_Q_VECTORS 10 /* Transmit and receive queues */ #define IGB_MAX_RX_QUEUES 16 #define IGB_MAX_TX_QUEUES 16 #define IGB_MAX_VF_MC_ENTRIES 30 #define IGB_MAX_VF_FUNCTIONS 8 #define IGB_82576_VF_DEV_ID 0x10CA #define IGB_I350_VF_DEV_ID 0x1520 #define IGB_MAX_UTA_ENTRIES 128 #define MAX_EMULATION_MAC_ADDRS 16 #define OUI_LEN 3 #define IGB_MAX_VMDQ_QUEUES 8 struct vf_data_storage { unsigned char vf_mac_addresses[ETH_ALEN]; u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES]; u16 num_vf_mc_hashes; u16 default_vf_vlan_id; u16 vlans_enabled; unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN]; u32 uta_table_copy[IGB_MAX_UTA_ENTRIES]; u32 flags; unsigned long last_nack; #ifdef IFLA_VF_MAX u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; u16 tx_rate; #ifdef HAVE_VF_SPOOFCHK_CONFIGURE bool spoofchk_enabled; #endif #endif }; #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ #define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */ #define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */ #define IGB_VF_FLAG_PF_SET_MAC 0x00000008 /* PF has set MAC address */ /* RX descriptor control thresholds. * PTHRESH - MAC will consider prefetch if it has fewer than this number of * descriptors available in its onboard memory. * Setting this to 0 disables RX descriptor prefetch. * HTHRESH - MAC will only prefetch if there are at least this many descriptors * available in host memory. * If PTHRESH is 0, this should also be 0. * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back * descriptors until either it has this many to write back, or the * ITR timer expires. */ #define IGB_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8) #define IGB_RX_HTHRESH 8 #define IGB_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8) #define IGB_TX_HTHRESH 1 #define IGB_RX_WTHRESH ((hw->mac.type == e1000_82576 && \ adapter->msix_entries) ? 1 : 4) /* this is the size past which hardware will drop packets when setting LPE=0 */ #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 /* NOTE: netdev_alloc_skb reserves 16 bytes, NET_IP_ALIGN means we * reserve 2 more, and skb_shared_info adds an additional 384 more, * this adds roughly 448 bytes of extra data meaning the smallest * allocation we could have is 1K. * i.e. RXBUFFER_512 --> size-1024 slab */ /* Supported Rx Buffer Sizes */ #define IGB_RXBUFFER_256 256 #define IGB_RXBUFFER_2048 2048 #define IGB_RXBUFFER_16384 16384 #define IGB_RX_HDR_LEN IGB_RXBUFFER_256 #if MAX_SKB_FRAGS < 8 #define IGB_RX_BUFSZ ALIGN(MAX_JUMBO_FRAME_SIZE / MAX_SKB_FRAGS, 1024) #else #define IGB_RX_BUFSZ IGB_RXBUFFER_2048 #endif /* Packet Buffer allocations */ #define IGB_PBA_BYTES_SHIFT 0xA #define IGB_TX_HEAD_ADDR_SHIFT 7 #define IGB_PBA_TX_MASK 0xFFFF0000 #define IGB_FC_PAUSE_TIME 0x0680 /* 858 usec */ /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define IGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define IGB_EEPROM_APME 0x0400 #define AUTO_ALL_MODES 0 #ifndef IGB_MASTER_SLAVE /* Switch to override PHY master/slave setting */ #define IGB_MASTER_SLAVE e1000_ms_hw_default #endif #define IGB_MNG_VLAN_NONE -1 #ifndef IGB_NO_LRO #define IGB_LRO_MAX 32 /*Maximum number of LRO descriptors*/ struct igb_lro_stats { u32 flushed; u32 coal; }; /* * igb_lro_header - header format to be aggregated by LRO * @iph: IP header without options * @tcp: TCP header * @ts: Optional TCP timestamp data in TCP options * * This structure relies on the check above that verifies that the header * is IPv4 and does not contain any options. */ struct igb_lrohdr { struct iphdr iph; struct tcphdr th; __be32 ts[0]; }; struct igb_lro_list { struct sk_buff_head active; struct igb_lro_stats stats; }; #endif /* IGB_NO_LRO */ struct igb_cb { #ifndef IGB_NO_LRO #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT union { /* Union defining head/tail partner */ struct sk_buff *head; struct sk_buff *tail; }; #endif __be32 tsecr; /* timestamp echo response */ u32 tsval; /* timestamp value in host order */ u32 next_seq; /* next expected sequence number */ u16 free; /* 65521 minus total size */ u16 mss; /* size of data portion of packet */ u16 append_cnt; /* number of skb's appended */ #endif /* IGB_NO_LRO */ #ifdef HAVE_VLAN_RX_REGISTER u16 vid; /* VLAN tag */ #endif }; #define IGB_CB(skb) ((struct igb_cb *)(skb)->cb) enum igb_tx_flags { /* cmd_type flags */ IGB_TX_FLAGS_VLAN = 0x01, IGB_TX_FLAGS_TSO = 0x02, IGB_TX_FLAGS_TSTAMP = 0x04, /* olinfo flags */ IGB_TX_FLAGS_IPV4 = 0x10, IGB_TX_FLAGS_CSUM = 0x20, }; /* VLAN info */ #define IGB_TX_FLAGS_VLAN_MASK 0xffff0000 #define IGB_TX_FLAGS_VLAN_SHIFT 16 /* * The largest size we can write to the descriptor is 65535. In order to * maintain a power of two alignment we have to limit ourselves to 32K. */ #define IGB_MAX_TXD_PWR 15 #define IGB_MAX_DATA_PER_TXD (1 << IGB_MAX_TXD_PWR) /* Tx Descriptors needed, worst case */ #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGB_MAX_DATA_PER_TXD) #ifndef MAX_SKB_FRAGS #define DESC_NEEDED 4 #elif (MAX_SKB_FRAGS < 16) #define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4) #else #define DESC_NEEDED (MAX_SKB_FRAGS + 4) #endif /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct igb_tx_buffer { union e1000_adv_tx_desc *next_to_watch; unsigned long time_stamp; struct sk_buff *skb; unsigned int bytecount; u16 gso_segs; __be16 protocol; DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); u32 tx_flags; }; struct igb_rx_buffer { dma_addr_t dma; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT struct sk_buff *skb; #else struct page *page; u32 page_offset; #endif }; struct igb_tx_queue_stats { u64 packets; u64 bytes; u64 restart_queue; }; struct igb_rx_queue_stats { u64 packets; u64 bytes; u64 drops; u64 csum_err; u64 alloc_failed; u64 ipv4_packets; /* IPv4 headers processed */ u64 ipv4e_packets; /* IPv4E headers with extensions processed */ u64 ipv6_packets; /* IPv6 headers processed */ u64 ipv6e_packets; /* IPv6E headers with extensions processed */ u64 tcp_packets; /* TCP headers processed */ u64 udp_packets; /* UDP headers processed */ u64 sctp_packets; /* SCTP headers processed */ u64 nfs_packets; /* NFS headers processe */ }; struct igb_ring_container { struct igb_ring *ring; /* pointer to linked list of rings */ unsigned int total_bytes; /* total bytes processed this int */ unsigned int total_packets; /* total packets processed this int */ u16 work_limit; /* total work allowed per interrupt */ u8 count; /* total number of rings in vector */ u8 itr; /* current ITR setting for ring */ }; struct igb_ring { struct igb_q_vector *q_vector; /* backlink to q_vector */ struct net_device *netdev; /* back pointer to net_device */ struct device *dev; /* device for dma mapping */ union { /* array of buffer info structs */ struct igb_tx_buffer *tx_buffer_info; struct igb_rx_buffer *rx_buffer_info; }; #ifdef HAVE_PTP_1588_CLOCK unsigned long last_rx_timestamp; #endif /* HAVE_PTP_1588_CLOCK */ void *desc; /* descriptor ring memory */ unsigned long flags; /* ring specific flags */ void __iomem *tail; /* pointer to ring tail register */ dma_addr_t dma; /* phys address of the ring */ unsigned int size; /* length of desc. ring in bytes */ u16 count; /* number of desc. in the ring */ u8 queue_index; /* logical index of the ring*/ u8 reg_idx; /* physical index of the ring */ /* everything past this point are written often */ u16 next_to_clean; u16 next_to_use; u16 next_to_alloc; union { /* TX */ struct { struct igb_tx_queue_stats tx_stats; }; /* RX */ struct { struct igb_rx_queue_stats rx_stats; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT u16 rx_buffer_len; #else struct sk_buff *skb; #endif }; }; #ifdef CONFIG_IGB_VMDQ_NETDEV struct net_device *vmdq_netdev; int vqueue_index; /* queue index for virtual netdev */ #endif } ____cacheline_internodealigned_in_smp; struct igb_q_vector { struct igb_adapter *adapter; /* backlink */ int cpu; /* CPU for DCA */ u32 eims_value; /* EIMS mask value */ u16 itr_val; u8 set_itr; void __iomem *itr_register; struct igb_ring_container rx, tx; struct napi_struct napi; #ifndef IGB_NO_LRO struct igb_lro_list lrolist; /* LRO list for queue vector*/ #endif char name[IFNAMSIZ + 9]; #ifndef HAVE_NETDEV_NAPI_LIST struct net_device poll_dev; #endif /* for dynamic allocation of rings associated with this q_vector */ struct igb_ring ring[0] ____cacheline_internodealigned_in_smp; }; enum e1000_ring_flags_t { #ifndef HAVE_NDO_SET_FEATURES IGB_RING_FLAG_RX_CSUM, #endif IGB_RING_FLAG_RX_SCTP_CSUM, IGB_RING_FLAG_RX_LB_VLAN_BSWAP, IGB_RING_FLAG_TX_CTX_IDX, IGB_RING_FLAG_TX_DETECT_HANG, }; struct igb_mac_addr { u8 addr[ETH_ALEN]; u16 queue; u16 state; /* bitmask */ }; #define IGB_MAC_STATE_DEFAULT 0x1 #define IGB_MAC_STATE_MODIFIED 0x2 #define IGB_MAC_STATE_IN_USE 0x4 #define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS) #define IGB_RX_DESC(R, i) \ (&(((union e1000_adv_rx_desc *)((R)->desc))[i])) #define IGB_TX_DESC(R, i) \ (&(((union e1000_adv_tx_desc *)((R)->desc))[i])) #define IGB_TX_CTXTDESC(R, i) \ (&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i])) #ifdef CONFIG_IGB_VMDQ_NETDEV #define netdev_ring(ring) \ ((ring->vmdq_netdev ? ring->vmdq_netdev : ring->netdev)) #define ring_queue_index(ring) \ ((ring->vmdq_netdev ? ring->vqueue_index : ring->queue_index)) #else #define netdev_ring(ring) (ring->netdev) #define ring_queue_index(ring) (ring->queue_index) #endif /* CONFIG_IGB_VMDQ_NETDEV */ /* igb_test_staterr - tests bits within Rx descriptor status and error fields */ static inline __le32 igb_test_staterr(union e1000_adv_rx_desc *rx_desc, const u32 stat_err_bits) { return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits); } /* igb_desc_unused - calculate if we have unused descriptors */ static inline u16 igb_desc_unused(const struct igb_ring *ring) { u16 ntc = ring->next_to_clean; u16 ntu = ring->next_to_use; return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; } #ifdef CONFIG_BQL static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring) { return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); } #endif /* CONFIG_BQL */ // #ifdef EXT_THERMAL_SENSOR_SUPPORT // #ifdef IGB_PROCFS struct igb_therm_proc_data { struct e1000_hw *hw; struct e1000_thermal_diode_data *sensor_data; }; // #endif /* IGB_PROCFS */ // #endif /* EXT_THERMAL_SENSOR_SUPPORT */ #ifdef IGB_HWMON #define IGB_HWMON_TYPE_LOC 0 #define IGB_HWMON_TYPE_TEMP 1 #define IGB_HWMON_TYPE_CAUTION 2 #define IGB_HWMON_TYPE_MAX 3 struct hwmon_attr { struct device_attribute dev_attr; struct e1000_hw *hw; struct e1000_thermal_diode_data *sensor; char name[12]; }; struct hwmon_buff { struct device *device; struct hwmon_attr *hwmon_list; unsigned int n_hwmon; }; #endif /* IGB_HWMON */ /* board specific private data structure */ struct igb_adapter { #ifdef HAVE_VLAN_RX_REGISTER /* vlgrp must be first member of structure */ struct vlan_group *vlgrp; #else unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; #endif struct net_device *netdev; unsigned long state; unsigned int flags; unsigned int num_q_vectors; struct msix_entry *msix_entries; /* TX */ u16 tx_work_limit; u32 tx_timeout_count; int num_tx_queues; struct igb_ring *tx_ring[IGB_MAX_TX_QUEUES]; /* RX */ int num_rx_queues; struct igb_ring *rx_ring[IGB_MAX_RX_QUEUES]; struct timer_list watchdog_timer; struct timer_list dma_err_timer; struct timer_list phy_info_timer; u16 mng_vlan_id; u32 bd_number; u32 wol; u32 en_mng_pt; u16 link_speed; u16 link_duplex; u8 port_num; /* Interrupt Throttle Rate */ u32 rx_itr_setting; u32 tx_itr_setting; struct work_struct reset_task; struct work_struct watchdog_task; struct work_struct dma_err_task; bool fc_autoneg; u8 tx_timeout_factor; #ifdef DEBUG bool tx_hang_detected; bool disable_hw_reset; #endif u32 max_frame_size; /* OS defined structs */ struct pci_dev *pdev; #ifndef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats net_stats; #endif #ifndef IGB_NO_LRO struct igb_lro_stats lro_stats; #endif /* structs defined in e1000_hw.h */ struct e1000_hw hw; struct e1000_hw_stats stats; struct e1000_phy_info phy_info; struct e1000_phy_stats phy_stats; #ifdef ETHTOOL_TEST u32 test_icr; struct igb_ring test_tx_ring; struct igb_ring test_rx_ring; #endif int msg_enable; struct igb_q_vector *q_vector[MAX_Q_VECTORS]; u32 eims_enable_mask; u32 eims_other; /* to not mess up cache alignment, always add to the bottom */ u32 *config_space; u16 tx_ring_count; u16 rx_ring_count; struct vf_data_storage *vf_data; #ifdef IFLA_VF_MAX int vf_rate_link_speed; #endif u32 lli_port; u32 lli_size; unsigned int vfs_allocated_count; /* Malicious Driver Detection flag. Valid only when SR-IOV is enabled */ bool mdd; int int_mode; u32 rss_queues; u32 vmdq_pools; char fw_version[32]; u32 wvbr; struct igb_mac_addr *mac_table; #ifdef CONFIG_IGB_VMDQ_NETDEV struct net_device *vmdq_netdev[IGB_MAX_VMDQ_QUEUES]; #endif int vferr_refcount; int dmac; u32 *shadow_vfta; /* External Thermal Sensor support flag */ bool ets; #ifdef IGB_HWMON struct hwmon_buff igb_hwmon_buff; #else /* IGB_HWMON */ #ifdef IGB_PROCFS struct proc_dir_entry *eth_dir; struct proc_dir_entry *info_dir; struct proc_dir_entry *therm_dir[E1000_MAX_SENSORS]; struct igb_therm_proc_data therm_data[E1000_MAX_SENSORS]; bool old_lsc; #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ u32 etrack_id; #ifdef HAVE_PTP_1588_CLOCK struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_caps; struct delayed_work ptp_overflow_work; struct work_struct ptp_tx_work; struct sk_buff *ptp_tx_skb; unsigned long ptp_tx_start; unsigned long last_rx_ptp_check; spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; u32 tx_hwtstamp_timeouts; u32 rx_hwtstamp_cleared; #endif /* HAVE_PTP_1588_CLOCK */ #ifdef HAVE_I2C_SUPPORT struct i2c_algo_bit_data i2c_algo; struct i2c_adapter i2c_adap; struct i2c_client *i2c_client; #endif /* HAVE_I2C_SUPPORT */ unsigned long link_check_timeout; int devrc; int copper_tries; u16 eee_advert; }; #ifdef CONFIG_IGB_VMDQ_NETDEV struct igb_vmdq_adapter { #ifdef HAVE_VLAN_RX_REGISTER /* vlgrp must be first member of structure */ struct vlan_group *vlgrp; #else unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; #endif struct igb_adapter *real_adapter; struct net_device *vnetdev; struct net_device_stats net_stats; struct igb_ring *tx_ring; struct igb_ring *rx_ring; }; #endif #define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_DCA_ENABLED (1 << 1) #define IGB_FLAG_LLI_PUSH (1 << 2) #define IGB_FLAG_QUAD_PORT_A (1 << 3) #define IGB_FLAG_QUEUE_PAIRS (1 << 4) #define IGB_FLAG_EEE (1 << 5) #define IGB_FLAG_DMAC (1 << 6) #define IGB_FLAG_DETECT_BAD_DMA (1 << 7) #define IGB_FLAG_PTP (1 << 8) #define IGB_FLAG_RSS_FIELD_IPV4_UDP (1 << 9) #define IGB_FLAG_RSS_FIELD_IPV6_UDP (1 << 10) #define IGB_FLAG_WOL_SUPPORTED (1 << 11) #define IGB_FLAG_NEED_LINK_UPDATE (1 << 12) #define IGB_FLAG_LOOPBACK_ENABLE (1 << 13) #define IGB_FLAG_MEDIA_RESET (1 << 14) #define IGB_FLAG_MAS_ENABLE (1 << 15) /* Media Auto Sense */ #define IGB_MAS_ENABLE_0 0X0001 #define IGB_MAS_ENABLE_1 0X0002 #define IGB_MAS_ENABLE_2 0X0004 #define IGB_MAS_ENABLE_3 0X0008 #define IGB_MIN_TXPBSIZE 20408 #define IGB_TX_BUF_4096 4096 #define IGB_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coal Flush */ /* DMA Coalescing defines */ #define IGB_DMAC_DISABLE 0 #define IGB_DMAC_MIN 250 #define IGB_DMAC_500 500 #define IGB_DMAC_EN_DEFAULT 1000 #define IGB_DMAC_2000 2000 #define IGB_DMAC_3000 3000 #define IGB_DMAC_4000 4000 #define IGB_DMAC_5000 5000 #define IGB_DMAC_6000 6000 #define IGB_DMAC_7000 7000 #define IGB_DMAC_8000 8000 #define IGB_DMAC_9000 9000 #define IGB_DMAC_MAX 10000 #define IGB_82576_TSYNC_SHIFT 19 #define IGB_82580_TSYNC_SHIFT 24 #define IGB_TS_HDR_LEN 16 /* CEM Support */ #define FW_HDR_LEN 0x4 #define FW_CMD_DRV_INFO 0xDD #define FW_CMD_DRV_INFO_LEN 0x5 #define FW_CMD_RESERVED 0X0 #define FW_RESP_SUCCESS 0x1 #define FW_UNUSED_VER 0x0 #define FW_MAX_RETRIES 3 #define FW_STATUS_SUCCESS 0x1 #define FW_FAMILY_DRV_VER 0Xffffffff #define IGB_MAX_LINK_TRIES 20 struct e1000_fw_hdr { u8 cmd; u8 buf_len; union { u8 cmd_resv; u8 ret_status; } cmd_or_resp; u8 checksum; }; #pragma pack(push,1) struct e1000_fw_drv_info { struct e1000_fw_hdr hdr; u8 port_num; u32 drv_version; u16 pad; /* end spacing to ensure length is mult. of dword */ u8 pad2; /* end spacing to ensure length is mult. of dword2 */ }; #pragma pack(pop) enum e1000_state_t { __IGB_TESTING, __IGB_RESETTING, __IGB_DOWN }; extern char igb_driver_name[]; extern char igb_driver_version[]; extern int igb_up(struct igb_adapter *); extern void igb_down(struct igb_adapter *); extern void igb_reinit_locked(struct igb_adapter *); extern void igb_reset(struct igb_adapter *); extern int igb_set_spd_dplx(struct igb_adapter *, u16); extern int igb_setup_tx_resources(struct igb_ring *); extern int igb_setup_rx_resources(struct igb_ring *); extern void igb_free_tx_resources(struct igb_ring *); extern void igb_free_rx_resources(struct igb_ring *); extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *); extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *); extern void igb_setup_tctl(struct igb_adapter *); extern void igb_setup_rctl(struct igb_adapter *); extern netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *); extern void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_tx_buffer *); extern void igb_alloc_rx_buffers(struct igb_ring *, u16); extern void igb_clean_rx_ring(struct igb_ring *); extern void igb_update_stats(struct igb_adapter *); extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); extern void igb_check_options(struct igb_adapter *); extern void igb_power_up_link(struct igb_adapter *); #ifdef HAVE_PTP_1588_CLOCK extern void igb_ptp_init(struct igb_adapter *adapter); extern void igb_ptp_stop(struct igb_adapter *adapter); extern void igb_ptp_reset(struct igb_adapter *adapter); extern void igb_ptp_tx_work(struct work_struct *work); extern void igb_ptp_rx_hang(struct igb_adapter *adapter); extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va, struct sk_buff *skb); static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb); skb_pull(skb, IGB_TS_HDR_LEN); #endif return; } if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS)) igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb); /* Update the last_rx_timestamp timer in order to enable watchdog check * for error case of latched timestamp on a dropped packet. */ rx_ring->last_rx_timestamp = jiffies; } extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); #endif /* HAVE_PTP_1588_CLOCK */ #ifdef ETHTOOL_OPS_COMPAT extern int ethtool_ioctl(struct ifreq *); #endif extern int igb_write_mc_addr_list(struct net_device *netdev); extern int igb_add_mac_filter(struct igb_adapter *adapter, u8 *addr, u16 queue); extern int igb_del_mac_filter(struct igb_adapter *adapter, u8* addr, u16 queue); extern int igb_available_rars(struct igb_adapter *adapter); extern s32 igb_vlvf_set(struct igb_adapter *, u32, bool, u32); extern void igb_configure_vt_default_pool(struct igb_adapter *adapter); extern void igb_enable_vlan_tags(struct igb_adapter *adapter); #ifndef HAVE_VLAN_RX_REGISTER extern void igb_vlan_mode(struct net_device *, u32); #endif #define E1000_PCS_CFG_IGN_SD 1 #ifdef IGB_HWMON void igb_sysfs_exit(struct igb_adapter *adapter); int igb_sysfs_init(struct igb_adapter *adapter); #else #ifdef IGB_PROCFS int igb_procfs_init(struct igb_adapter* adapter); void igb_procfs_exit(struct igb_adapter* adapter); int igb_procfs_topdir_init(void); void igb_procfs_topdir_exit(void); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ #endif /* _IGB_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_debugfs.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "igb.h" ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_ethtool.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* ethtool support for igb */ #include #include #ifdef SIOCETHTOOL #include #ifdef CONFIG_PM_RUNTIME #include #endif /* CONFIG_PM_RUNTIME */ #include #include "igb.h" #include "igb_regtest.h" #include #ifdef ETHTOOL_GEEE #include #endif #ifdef ETHTOOL_OPS_COMPAT #include "kcompat_ethtool.c" #endif #ifdef ETHTOOL_GSTATS struct igb_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; int stat_offset; }; #define IGB_STAT(_name, _stat) { \ .stat_string = _name, \ .sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \ .stat_offset = offsetof(struct igb_adapter, _stat) \ } static const struct igb_stats igb_gstrings_stats[] = { IGB_STAT("rx_packets", stats.gprc), IGB_STAT("tx_packets", stats.gptc), IGB_STAT("rx_bytes", stats.gorc), IGB_STAT("tx_bytes", stats.gotc), IGB_STAT("rx_broadcast", stats.bprc), IGB_STAT("tx_broadcast", stats.bptc), IGB_STAT("rx_multicast", stats.mprc), IGB_STAT("tx_multicast", stats.mptc), IGB_STAT("multicast", stats.mprc), IGB_STAT("collisions", stats.colc), IGB_STAT("rx_crc_errors", stats.crcerrs), IGB_STAT("rx_no_buffer_count", stats.rnbc), IGB_STAT("rx_missed_errors", stats.mpc), IGB_STAT("tx_aborted_errors", stats.ecol), IGB_STAT("tx_carrier_errors", stats.tncrs), IGB_STAT("tx_window_errors", stats.latecol), IGB_STAT("tx_abort_late_coll", stats.latecol), IGB_STAT("tx_deferred_ok", stats.dc), IGB_STAT("tx_single_coll_ok", stats.scc), IGB_STAT("tx_multi_coll_ok", stats.mcc), IGB_STAT("tx_timeout_count", tx_timeout_count), IGB_STAT("rx_long_length_errors", stats.roc), IGB_STAT("rx_short_length_errors", stats.ruc), IGB_STAT("rx_align_errors", stats.algnerrc), IGB_STAT("tx_tcp_seg_good", stats.tsctc), IGB_STAT("tx_tcp_seg_failed", stats.tsctfc), IGB_STAT("rx_flow_control_xon", stats.xonrxc), IGB_STAT("rx_flow_control_xoff", stats.xoffrxc), IGB_STAT("tx_flow_control_xon", stats.xontxc), IGB_STAT("tx_flow_control_xoff", stats.xofftxc), IGB_STAT("rx_long_byte_count", stats.gorc), IGB_STAT("tx_dma_out_of_sync", stats.doosync), #ifndef IGB_NO_LRO IGB_STAT("lro_aggregated", lro_stats.coal), IGB_STAT("lro_flushed", lro_stats.flushed), #endif /* IGB_LRO */ IGB_STAT("tx_smbus", stats.mgptc), IGB_STAT("rx_smbus", stats.mgprc), IGB_STAT("dropped_smbus", stats.mgpdc), IGB_STAT("os2bmc_rx_by_bmc", stats.o2bgptc), IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc), IGB_STAT("os2bmc_tx_by_host", stats.o2bspc), IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc), #ifdef HAVE_PTP_1588_CLOCK IGB_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), IGB_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), #endif /* HAVE_PTP_1588_CLOCK */ }; #define IGB_NETDEV_STAT(_net_stat) { \ .stat_string = #_net_stat, \ .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ .stat_offset = offsetof(struct net_device_stats, _net_stat) \ } static const struct igb_stats igb_gstrings_net_stats[] = { IGB_NETDEV_STAT(rx_errors), IGB_NETDEV_STAT(tx_errors), IGB_NETDEV_STAT(tx_dropped), IGB_NETDEV_STAT(rx_length_errors), IGB_NETDEV_STAT(rx_over_errors), IGB_NETDEV_STAT(rx_frame_errors), IGB_NETDEV_STAT(rx_fifo_errors), IGB_NETDEV_STAT(tx_fifo_errors), IGB_NETDEV_STAT(tx_heartbeat_errors) }; #define IGB_GLOBAL_STATS_LEN ARRAY_SIZE(igb_gstrings_stats) #define IGB_NETDEV_STATS_LEN ARRAY_SIZE(igb_gstrings_net_stats) #define IGB_RX_QUEUE_STATS_LEN \ (sizeof(struct igb_rx_queue_stats) / sizeof(u64)) #define IGB_TX_QUEUE_STATS_LEN \ (sizeof(struct igb_tx_queue_stats) / sizeof(u64)) #define IGB_QUEUE_STATS_LEN \ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \ IGB_RX_QUEUE_STATS_LEN) + \ (((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues * \ IGB_TX_QUEUE_STATS_LEN)) #define IGB_STATS_LEN \ (IGB_GLOBAL_STATS_LEN + IGB_NETDEV_STATS_LEN + IGB_QUEUE_STATS_LEN) #endif /* ETHTOOL_GSTATS */ #ifdef ETHTOOL_TEST static const char igb_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "Interrupt test (offline)", "Loopback test (offline)", "Link test (on/offline)" }; #define IGB_TEST_LEN (sizeof(igb_gstrings_test) / ETH_GSTRING_LEN) #endif /* ETHTOOL_TEST */ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 status; if (hw->phy.media_type == e1000_media_type_copper) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full| SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_Pause); ecmd->advertising = ADVERTISED_TP; if (hw->mac.autoneg == 1) { ecmd->advertising |= ADVERTISED_Autoneg; /* the e1000 autoneg seems to match ethtool nicely */ ecmd->advertising |= hw->phy.autoneg_advertised; } ecmd->port = PORT_TP; ecmd->phy_address = hw->phy.addr; ecmd->transceiver = XCVR_INTERNAL; } else { ecmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full | SUPPORTED_FIBRE | SUPPORTED_Autoneg | SUPPORTED_Pause); if (hw->mac.type == e1000_i354) ecmd->supported |= (SUPPORTED_2500baseX_Full); ecmd->advertising = ADVERTISED_FIBRE; switch (adapter->link_speed) { case SPEED_2500: ecmd->advertising = ADVERTISED_2500baseX_Full; break; case SPEED_1000: ecmd->advertising = ADVERTISED_1000baseT_Full; break; case SPEED_100: ecmd->advertising = ADVERTISED_100baseT_Full; break; default: break; } if (hw->mac.autoneg == 1) ecmd->advertising |= ADVERTISED_Autoneg; ecmd->port = PORT_FIBRE; ecmd->transceiver = XCVR_EXTERNAL; } if (hw->mac.autoneg != 1) ecmd->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); if (hw->fc.requested_mode == e1000_fc_full) ecmd->advertising |= ADVERTISED_Pause; else if (hw->fc.requested_mode == e1000_fc_rx_pause) ecmd->advertising |= (ADVERTISED_Pause | ADVERTISED_Asym_Pause); else if (hw->fc.requested_mode == e1000_fc_tx_pause) ecmd->advertising |= ADVERTISED_Asym_Pause; else ecmd->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) { if ((hw->mac.type == e1000_i354) && (status & E1000_STATUS_2P5_SKU) && !(status & E1000_STATUS_2P5_SKU_OVER)) ecmd->speed = SPEED_2500; else if (status & E1000_STATUS_SPEED_1000) ecmd->speed = SPEED_1000; else if (status & E1000_STATUS_SPEED_100) ecmd->speed = SPEED_100; else ecmd->speed = SPEED_10; if ((status & E1000_STATUS_FD) || hw->phy.media_type != e1000_media_type_copper) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { ecmd->speed = -1; ecmd->duplex = -1; } if ((hw->phy.media_type == e1000_media_type_fiber) || hw->mac.autoneg) ecmd->autoneg = AUTONEG_ENABLE; else ecmd->autoneg = AUTONEG_DISABLE; #ifdef ETH_TP_MDI_X /* MDI-X => 2; MDI =>1; Invalid =>0 */ if (hw->phy.media_type == e1000_media_type_copper) ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; else ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; #ifdef ETH_TP_MDI_AUTO if (hw->phy.mdix == AUTO_ALL_MODES) ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; else ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; #endif #endif /* ETH_TP_MDI_X */ return 0; } static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; if (ecmd->duplex == DUPLEX_HALF) { if (!hw->dev_spec._82575.eee_disable) dev_info(pci_dev_to_dev(adapter->pdev), "EEE disabled: not supported with half duplex\n"); hw->dev_spec._82575.eee_disable = true; } else { if (hw->dev_spec._82575.eee_disable) dev_info(pci_dev_to_dev(adapter->pdev), "EEE enabled\n"); hw->dev_spec._82575.eee_disable = false; } /* When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ if (e1000_check_reset_block(hw)) { dev_err(pci_dev_to_dev(adapter->pdev), "Cannot change link " "characteristics when SoL/IDER is active.\n"); return -EINVAL; } #ifdef ETH_TP_MDI_AUTO /* * MDI setting is only allowed when autoneg enabled because * some hardware doesn't allow MDI setting when speed or * duplex is forced. */ if (ecmd->eth_tp_mdix_ctrl) { if (hw->phy.media_type != e1000_media_type_copper) return -EOPNOTSUPP; if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && (ecmd->autoneg != AUTONEG_ENABLE)) { dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); return -EINVAL; } } #endif /* ETH_TP_MDI_AUTO */ while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); if (ecmd->autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; if (hw->phy.media_type == e1000_media_type_fiber) { hw->phy.autoneg_advertised = ecmd->advertising | ADVERTISED_FIBRE | ADVERTISED_Autoneg; switch (adapter->link_speed) { case SPEED_2500: hw->phy.autoneg_advertised = ADVERTISED_2500baseX_Full; break; case SPEED_1000: hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full; break; case SPEED_100: hw->phy.autoneg_advertised = ADVERTISED_100baseT_Full; break; default: break; } } else { hw->phy.autoneg_advertised = ecmd->advertising | ADVERTISED_TP | ADVERTISED_Autoneg; } ecmd->advertising = hw->phy.autoneg_advertised; if (adapter->fc_autoneg) hw->fc.requested_mode = e1000_fc_default; } else { if (igb_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) { clear_bit(__IGB_RESETTING, &adapter->state); return -EINVAL; } } #ifdef ETH_TP_MDI_AUTO /* MDI-X => 2; MDI => 1; Auto => 3 */ if (ecmd->eth_tp_mdix_ctrl) { /* fix up the value for auto (3 => 0) as zero is mapped * internally to auto */ if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) hw->phy.mdix = AUTO_ALL_MODES; else hw->phy.mdix = ecmd->eth_tp_mdix_ctrl; } #endif /* ETH_TP_MDI_AUTO */ /* reset the link */ if (netif_running(adapter->netdev)) { igb_down(adapter); igb_up(adapter); } else igb_reset(adapter); clear_bit(__IGB_RESETTING, &adapter->state); return 0; } static u32 igb_get_link(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_mac_info *mac = &adapter->hw.mac; /* * If the link is not reported up to netdev, interrupts are disabled, * and so the physical link state may have changed since we last * looked. Set get_link_status to make sure that the true link * state is interrogated, rather than pulling a cached and possibly * stale link state from the driver. */ if (!netif_carrier_ok(netdev)) mac->get_link_status = 1; return igb_has_link(adapter); } static void igb_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); if (hw->fc.current_mode == e1000_fc_rx_pause) pause->rx_pause = 1; else if (hw->fc.current_mode == e1000_fc_tx_pause) pause->tx_pause = 1; else if (hw->fc.current_mode == e1000_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } } static int igb_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; int retval = 0; adapter->fc_autoneg = pause->autoneg; while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); if (adapter->fc_autoneg == AUTONEG_ENABLE) { hw->fc.requested_mode = e1000_fc_default; if (netif_running(adapter->netdev)) { igb_down(adapter); igb_up(adapter); } else { igb_reset(adapter); } } else { if (pause->rx_pause && pause->tx_pause) hw->fc.requested_mode = e1000_fc_full; else if (pause->rx_pause && !pause->tx_pause) hw->fc.requested_mode = e1000_fc_rx_pause; else if (!pause->rx_pause && pause->tx_pause) hw->fc.requested_mode = e1000_fc_tx_pause; else if (!pause->rx_pause && !pause->tx_pause) hw->fc.requested_mode = e1000_fc_none; hw->fc.current_mode = hw->fc.requested_mode; if (hw->phy.media_type == e1000_media_type_fiber) { retval = hw->mac.ops.setup_link(hw); /* implicit goto out */ } else { retval = e1000_force_mac_fc(hw); if (retval) goto out; e1000_set_fc_watermarks_generic(hw); } } out: clear_bit(__IGB_RESETTING, &adapter->state); return retval; } static u32 igb_get_msglevel(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); return adapter->msg_enable; } static void igb_set_msglevel(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); adapter->msg_enable = data; } static int igb_get_regs_len(struct net_device *netdev) { #define IGB_REGS_LEN 555 return IGB_REGS_LEN * sizeof(u32); } static void igb_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 *regs_buff = p; u8 i; memset(p, 0, IGB_REGS_LEN * sizeof(u32)); regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; /* General Registers */ regs_buff[0] = E1000_READ_REG(hw, E1000_CTRL); regs_buff[1] = E1000_READ_REG(hw, E1000_STATUS); regs_buff[2] = E1000_READ_REG(hw, E1000_CTRL_EXT); regs_buff[3] = E1000_READ_REG(hw, E1000_MDIC); regs_buff[4] = E1000_READ_REG(hw, E1000_SCTL); regs_buff[5] = E1000_READ_REG(hw, E1000_CONNSW); regs_buff[6] = E1000_READ_REG(hw, E1000_VET); regs_buff[7] = E1000_READ_REG(hw, E1000_LEDCTL); regs_buff[8] = E1000_READ_REG(hw, E1000_PBA); regs_buff[9] = E1000_READ_REG(hw, E1000_PBS); regs_buff[10] = E1000_READ_REG(hw, E1000_FRTIMER); regs_buff[11] = E1000_READ_REG(hw, E1000_TCPTIMER); /* NVM Register */ regs_buff[12] = E1000_READ_REG(hw, E1000_EECD); /* Interrupt */ /* Reading EICS for EICR because they read the * same but EICS does not clear on read */ regs_buff[13] = E1000_READ_REG(hw, E1000_EICS); regs_buff[14] = E1000_READ_REG(hw, E1000_EICS); regs_buff[15] = E1000_READ_REG(hw, E1000_EIMS); regs_buff[16] = E1000_READ_REG(hw, E1000_EIMC); regs_buff[17] = E1000_READ_REG(hw, E1000_EIAC); regs_buff[18] = E1000_READ_REG(hw, E1000_EIAM); /* Reading ICS for ICR because they read the * same but ICS does not clear on read */ regs_buff[19] = E1000_READ_REG(hw, E1000_ICS); regs_buff[20] = E1000_READ_REG(hw, E1000_ICS); regs_buff[21] = E1000_READ_REG(hw, E1000_IMS); regs_buff[22] = E1000_READ_REG(hw, E1000_IMC); regs_buff[23] = E1000_READ_REG(hw, E1000_IAC); regs_buff[24] = E1000_READ_REG(hw, E1000_IAM); regs_buff[25] = E1000_READ_REG(hw, E1000_IMIRVP); /* Flow Control */ regs_buff[26] = E1000_READ_REG(hw, E1000_FCAL); regs_buff[27] = E1000_READ_REG(hw, E1000_FCAH); regs_buff[28] = E1000_READ_REG(hw, E1000_FCTTV); regs_buff[29] = E1000_READ_REG(hw, E1000_FCRTL); regs_buff[30] = E1000_READ_REG(hw, E1000_FCRTH); regs_buff[31] = E1000_READ_REG(hw, E1000_FCRTV); /* Receive */ regs_buff[32] = E1000_READ_REG(hw, E1000_RCTL); regs_buff[33] = E1000_READ_REG(hw, E1000_RXCSUM); regs_buff[34] = E1000_READ_REG(hw, E1000_RLPML); regs_buff[35] = E1000_READ_REG(hw, E1000_RFCTL); regs_buff[36] = E1000_READ_REG(hw, E1000_MRQC); regs_buff[37] = E1000_READ_REG(hw, E1000_VT_CTL); /* Transmit */ regs_buff[38] = E1000_READ_REG(hw, E1000_TCTL); regs_buff[39] = E1000_READ_REG(hw, E1000_TCTL_EXT); regs_buff[40] = E1000_READ_REG(hw, E1000_TIPG); regs_buff[41] = E1000_READ_REG(hw, E1000_DTXCTL); /* Wake Up */ regs_buff[42] = E1000_READ_REG(hw, E1000_WUC); regs_buff[43] = E1000_READ_REG(hw, E1000_WUFC); regs_buff[44] = E1000_READ_REG(hw, E1000_WUS); regs_buff[45] = E1000_READ_REG(hw, E1000_IPAV); regs_buff[46] = E1000_READ_REG(hw, E1000_WUPL); /* MAC */ regs_buff[47] = E1000_READ_REG(hw, E1000_PCS_CFG0); regs_buff[48] = E1000_READ_REG(hw, E1000_PCS_LCTL); regs_buff[49] = E1000_READ_REG(hw, E1000_PCS_LSTAT); regs_buff[50] = E1000_READ_REG(hw, E1000_PCS_ANADV); regs_buff[51] = E1000_READ_REG(hw, E1000_PCS_LPAB); regs_buff[52] = E1000_READ_REG(hw, E1000_PCS_NPTX); regs_buff[53] = E1000_READ_REG(hw, E1000_PCS_LPABNP); /* Statistics */ regs_buff[54] = adapter->stats.crcerrs; regs_buff[55] = adapter->stats.algnerrc; regs_buff[56] = adapter->stats.symerrs; regs_buff[57] = adapter->stats.rxerrc; regs_buff[58] = adapter->stats.mpc; regs_buff[59] = adapter->stats.scc; regs_buff[60] = adapter->stats.ecol; regs_buff[61] = adapter->stats.mcc; regs_buff[62] = adapter->stats.latecol; regs_buff[63] = adapter->stats.colc; regs_buff[64] = adapter->stats.dc; regs_buff[65] = adapter->stats.tncrs; regs_buff[66] = adapter->stats.sec; regs_buff[67] = adapter->stats.htdpmc; regs_buff[68] = adapter->stats.rlec; regs_buff[69] = adapter->stats.xonrxc; regs_buff[70] = adapter->stats.xontxc; regs_buff[71] = adapter->stats.xoffrxc; regs_buff[72] = adapter->stats.xofftxc; regs_buff[73] = adapter->stats.fcruc; regs_buff[74] = adapter->stats.prc64; regs_buff[75] = adapter->stats.prc127; regs_buff[76] = adapter->stats.prc255; regs_buff[77] = adapter->stats.prc511; regs_buff[78] = adapter->stats.prc1023; regs_buff[79] = adapter->stats.prc1522; regs_buff[80] = adapter->stats.gprc; regs_buff[81] = adapter->stats.bprc; regs_buff[82] = adapter->stats.mprc; regs_buff[83] = adapter->stats.gptc; regs_buff[84] = adapter->stats.gorc; regs_buff[86] = adapter->stats.gotc; regs_buff[88] = adapter->stats.rnbc; regs_buff[89] = adapter->stats.ruc; regs_buff[90] = adapter->stats.rfc; regs_buff[91] = adapter->stats.roc; regs_buff[92] = adapter->stats.rjc; regs_buff[93] = adapter->stats.mgprc; regs_buff[94] = adapter->stats.mgpdc; regs_buff[95] = adapter->stats.mgptc; regs_buff[96] = adapter->stats.tor; regs_buff[98] = adapter->stats.tot; regs_buff[100] = adapter->stats.tpr; regs_buff[101] = adapter->stats.tpt; regs_buff[102] = adapter->stats.ptc64; regs_buff[103] = adapter->stats.ptc127; regs_buff[104] = adapter->stats.ptc255; regs_buff[105] = adapter->stats.ptc511; regs_buff[106] = adapter->stats.ptc1023; regs_buff[107] = adapter->stats.ptc1522; regs_buff[108] = adapter->stats.mptc; regs_buff[109] = adapter->stats.bptc; regs_buff[110] = adapter->stats.tsctc; regs_buff[111] = adapter->stats.iac; regs_buff[112] = adapter->stats.rpthc; regs_buff[113] = adapter->stats.hgptc; regs_buff[114] = adapter->stats.hgorc; regs_buff[116] = adapter->stats.hgotc; regs_buff[118] = adapter->stats.lenerrs; regs_buff[119] = adapter->stats.scvpc; regs_buff[120] = adapter->stats.hrmpc; for (i = 0; i < 4; i++) regs_buff[121 + i] = E1000_READ_REG(hw, E1000_SRRCTL(i)); for (i = 0; i < 4; i++) regs_buff[125 + i] = E1000_READ_REG(hw, E1000_PSRTYPE(i)); for (i = 0; i < 4; i++) regs_buff[129 + i] = E1000_READ_REG(hw, E1000_RDBAL(i)); for (i = 0; i < 4; i++) regs_buff[133 + i] = E1000_READ_REG(hw, E1000_RDBAH(i)); for (i = 0; i < 4; i++) regs_buff[137 + i] = E1000_READ_REG(hw, E1000_RDLEN(i)); for (i = 0; i < 4; i++) regs_buff[141 + i] = E1000_READ_REG(hw, E1000_RDH(i)); for (i = 0; i < 4; i++) regs_buff[145 + i] = E1000_READ_REG(hw, E1000_RDT(i)); for (i = 0; i < 4; i++) regs_buff[149 + i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); for (i = 0; i < 10; i++) regs_buff[153 + i] = E1000_READ_REG(hw, E1000_EITR(i)); for (i = 0; i < 8; i++) regs_buff[163 + i] = E1000_READ_REG(hw, E1000_IMIR(i)); for (i = 0; i < 8; i++) regs_buff[171 + i] = E1000_READ_REG(hw, E1000_IMIREXT(i)); for (i = 0; i < 16; i++) regs_buff[179 + i] = E1000_READ_REG(hw, E1000_RAL(i)); for (i = 0; i < 16; i++) regs_buff[195 + i] = E1000_READ_REG(hw, E1000_RAH(i)); for (i = 0; i < 4; i++) regs_buff[211 + i] = E1000_READ_REG(hw, E1000_TDBAL(i)); for (i = 0; i < 4; i++) regs_buff[215 + i] = E1000_READ_REG(hw, E1000_TDBAH(i)); for (i = 0; i < 4; i++) regs_buff[219 + i] = E1000_READ_REG(hw, E1000_TDLEN(i)); for (i = 0; i < 4; i++) regs_buff[223 + i] = E1000_READ_REG(hw, E1000_TDH(i)); for (i = 0; i < 4; i++) regs_buff[227 + i] = E1000_READ_REG(hw, E1000_TDT(i)); for (i = 0; i < 4; i++) regs_buff[231 + i] = E1000_READ_REG(hw, E1000_TXDCTL(i)); for (i = 0; i < 4; i++) regs_buff[235 + i] = E1000_READ_REG(hw, E1000_TDWBAL(i)); for (i = 0; i < 4; i++) regs_buff[239 + i] = E1000_READ_REG(hw, E1000_TDWBAH(i)); for (i = 0; i < 4; i++) regs_buff[243 + i] = E1000_READ_REG(hw, E1000_DCA_TXCTRL(i)); for (i = 0; i < 4; i++) regs_buff[247 + i] = E1000_READ_REG(hw, E1000_IP4AT_REG(i)); for (i = 0; i < 4; i++) regs_buff[251 + i] = E1000_READ_REG(hw, E1000_IP6AT_REG(i)); for (i = 0; i < 32; i++) regs_buff[255 + i] = E1000_READ_REG(hw, E1000_WUPM_REG(i)); for (i = 0; i < 128; i++) regs_buff[287 + i] = E1000_READ_REG(hw, E1000_FFMT_REG(i)); for (i = 0; i < 128; i++) regs_buff[415 + i] = E1000_READ_REG(hw, E1000_FFVT_REG(i)); for (i = 0; i < 4; i++) regs_buff[543 + i] = E1000_READ_REG(hw, E1000_FFLT_REG(i)); regs_buff[547] = E1000_READ_REG(hw, E1000_TDFH); regs_buff[548] = E1000_READ_REG(hw, E1000_TDFT); regs_buff[549] = E1000_READ_REG(hw, E1000_TDFHS); regs_buff[550] = E1000_READ_REG(hw, E1000_TDFPC); if (hw->mac.type > e1000_82580) { regs_buff[551] = adapter->stats.o2bgptc; regs_buff[552] = adapter->stats.b2ospc; regs_buff[553] = adapter->stats.o2bspc; regs_buff[554] = adapter->stats.b2ogprc; } } static int igb_get_eeprom_len(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); return adapter->hw.nvm.word_size * 2; } static int igb_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u16 *eeprom_buff; int first_word, last_word; int ret_val = 0; u16 i; if (eeprom->len == 0) return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; if (hw->nvm.type == e1000_nvm_eeprom_spi) ret_val = e1000_read_nvm(hw, first_word, last_word - first_word + 1, eeprom_buff); else { for (i = 0; i < last_word - first_word + 1; i++) { ret_val = e1000_read_nvm(hw, first_word + i, 1, &eeprom_buff[i]); if (ret_val) break; } } /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = le16_to_cpu(eeprom_buff[i]); memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); kfree(eeprom_buff); return ret_val; } static int igb_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u16 *eeprom_buff; void *ptr; int max_len, first_word, last_word, ret_val = 0; u16 i; if (eeprom->len == 0) return -EOPNOTSUPP; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; max_len = hw->nvm.word_size * 2; first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(max_len, GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; ptr = (void *)eeprom_buff; if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]); ptr++; } if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ ret_val = e1000_read_nvm(hw, last_word, 1, &eeprom_buff[last_word - first_word]); } /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) cpu_to_le16s(&eeprom_buff[i]); ret_val = e1000_write_nvm(hw, first_word, last_word - first_word + 1, eeprom_buff); /* Update the checksum if write succeeded. * and flush shadow RAM for 82573 controllers */ if (ret_val == 0) e1000_update_nvm_checksum(hw); kfree(eeprom_buff); return ret_val; } static void igb_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct igb_adapter *adapter = netdev_priv(netdev); strncpy(drvinfo->driver, igb_driver_name, sizeof(drvinfo->driver) - 1); strncpy(drvinfo->version, igb_driver_version, sizeof(drvinfo->version) - 1); strncpy(drvinfo->fw_version, adapter->fw_version, sizeof(drvinfo->fw_version) - 1); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info) -1); drvinfo->n_stats = IGB_STATS_LEN; drvinfo->testinfo_len = IGB_TEST_LEN; drvinfo->regdump_len = igb_get_regs_len(netdev); drvinfo->eedump_len = igb_get_eeprom_len(netdev); } static void igb_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct igb_adapter *adapter = netdev_priv(netdev); ring->rx_max_pending = IGB_MAX_RXD; ring->tx_max_pending = IGB_MAX_TXD; ring->rx_mini_max_pending = 0; ring->rx_jumbo_max_pending = 0; ring->rx_pending = adapter->rx_ring_count; ring->tx_pending = adapter->tx_ring_count; ring->rx_mini_pending = 0; ring->rx_jumbo_pending = 0; } static int igb_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct igb_adapter *adapter = netdev_priv(netdev); struct igb_ring *temp_ring; int i, err = 0; u16 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; new_rx_count = min(ring->rx_pending, (u32)IGB_MAX_RXD); new_rx_count = max(new_rx_count, (u16)IGB_MIN_RXD); new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); new_tx_count = min(ring->tx_pending, (u32)IGB_MAX_TXD); new_tx_count = max(new_tx_count, (u16)IGB_MIN_TXD); new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); if ((new_tx_count == adapter->tx_ring_count) && (new_rx_count == adapter->rx_ring_count)) { /* nothing to do */ return 0; } while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) adapter->tx_ring[i]->count = new_tx_count; for (i = 0; i < adapter->num_rx_queues; i++) adapter->rx_ring[i]->count = new_rx_count; adapter->tx_ring_count = new_tx_count; adapter->rx_ring_count = new_rx_count; goto clear_reset; } if (adapter->num_tx_queues > adapter->num_rx_queues) temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring)); else temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring)); if (!temp_ring) { err = -ENOMEM; goto clear_reset; } igb_down(adapter); /* * We can't just free everything and then setup again, * because the ISRs in MSI-X mode get passed pointers * to the tx and rx ring structs. */ if (new_tx_count != adapter->tx_ring_count) { for (i = 0; i < adapter->num_tx_queues; i++) { memcpy(&temp_ring[i], adapter->tx_ring[i], sizeof(struct igb_ring)); temp_ring[i].count = new_tx_count; err = igb_setup_tx_resources(&temp_ring[i]); if (err) { while (i) { i--; igb_free_tx_resources(&temp_ring[i]); } goto err_setup; } } for (i = 0; i < adapter->num_tx_queues; i++) { igb_free_tx_resources(adapter->tx_ring[i]); memcpy(adapter->tx_ring[i], &temp_ring[i], sizeof(struct igb_ring)); } adapter->tx_ring_count = new_tx_count; } if (new_rx_count != adapter->rx_ring_count) { for (i = 0; i < adapter->num_rx_queues; i++) { memcpy(&temp_ring[i], adapter->rx_ring[i], sizeof(struct igb_ring)); temp_ring[i].count = new_rx_count; err = igb_setup_rx_resources(&temp_ring[i]); if (err) { while (i) { i--; igb_free_rx_resources(&temp_ring[i]); } goto err_setup; } } for (i = 0; i < adapter->num_rx_queues; i++) { igb_free_rx_resources(adapter->rx_ring[i]); memcpy(adapter->rx_ring[i], &temp_ring[i], sizeof(struct igb_ring)); } adapter->rx_ring_count = new_rx_count; } err_setup: igb_up(adapter); vfree(temp_ring); clear_reset: clear_bit(__IGB_RESETTING, &adapter->state); return err; } static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, int reg, u32 mask, u32 write) { struct e1000_hw *hw = &adapter->hw; u32 pat, val; static const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { E1000_WRITE_REG(hw, reg, (_test[pat] & write)); val = E1000_READ_REG(hw, reg) & mask; if (val != (_test[pat] & write & mask)) { dev_err(pci_dev_to_dev(adapter->pdev), "pattern test reg %04X " "failed: got 0x%08X expected 0x%08X\n", E1000_REGISTER(hw, reg), val, (_test[pat] & write & mask)); *data = E1000_REGISTER(hw, reg); return 1; } } return 0; } static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, int reg, u32 mask, u32 write) { struct e1000_hw *hw = &adapter->hw; u32 val; E1000_WRITE_REG(hw, reg, write & mask); val = E1000_READ_REG(hw, reg); if ((write & mask) != (val & mask)) { dev_err(pci_dev_to_dev(adapter->pdev), "set/check reg %04X test failed:" " got 0x%08X expected 0x%08X\n", reg, (val & mask), (write & mask)); *data = E1000_REGISTER(hw, reg); return 1; } return 0; } #define REG_PATTERN_TEST(reg, mask, write) \ do { \ if (reg_pattern_test(adapter, data, reg, mask, write)) \ return 1; \ } while (0) #define REG_SET_AND_CHECK(reg, mask, write) \ do { \ if (reg_set_and_check(adapter, data, reg, mask, write)) \ return 1; \ } while (0) static int igb_reg_test(struct igb_adapter *adapter, u64 *data) { struct e1000_hw *hw = &adapter->hw; struct igb_reg_test *test; u32 value, before, after; u32 i, toggle; switch (adapter->hw.mac.type) { case e1000_i350: case e1000_i354: test = reg_test_i350; toggle = 0x7FEFF3FF; break; case e1000_i210: case e1000_i211: test = reg_test_i210; toggle = 0x7FEFF3FF; break; case e1000_82580: test = reg_test_82580; toggle = 0x7FEFF3FF; break; case e1000_82576: test = reg_test_82576; toggle = 0x7FFFF3FF; break; default: test = reg_test_82575; toggle = 0x7FFFF3FF; break; } /* Because the status register is such a special case, * we handle it separately from the rest of the register * tests. Some bits are read-only, some toggle, and some * are writable on newer MACs. */ before = E1000_READ_REG(hw, E1000_STATUS); value = (E1000_READ_REG(hw, E1000_STATUS) & toggle); E1000_WRITE_REG(hw, E1000_STATUS, toggle); after = E1000_READ_REG(hw, E1000_STATUS) & toggle; if (value != after) { dev_err(pci_dev_to_dev(adapter->pdev), "failed STATUS register test " "got: 0x%08X expected: 0x%08X\n", after, value); *data = 1; return 1; } /* restore previous status */ E1000_WRITE_REG(hw, E1000_STATUS, before); /* Perform the remainder of the register test, looping through * the test table until we either fail or reach the null entry. */ while (test->reg) { for (i = 0; i < test->array_len; i++) { switch (test->test_type) { case PATTERN_TEST: REG_PATTERN_TEST(test->reg + (i * test->reg_offset), test->mask, test->write); break; case SET_READ_TEST: REG_SET_AND_CHECK(test->reg + (i * test->reg_offset), test->mask, test->write); break; case WRITE_NO_TEST: writel(test->write, (adapter->hw.hw_addr + test->reg) + (i * test->reg_offset)); break; case TABLE32_TEST: REG_PATTERN_TEST(test->reg + (i * 4), test->mask, test->write); break; case TABLE64_TEST_LO: REG_PATTERN_TEST(test->reg + (i * 8), test->mask, test->write); break; case TABLE64_TEST_HI: REG_PATTERN_TEST((test->reg + 4) + (i * 8), test->mask, test->write); break; } } test++; } *data = 0; return 0; } static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) { *data = 0; /* Validate NVM checksum */ if (e1000_validate_nvm_checksum(&adapter->hw) < 0) *data = 2; return *data; } static irqreturn_t igb_test_intr(int irq, void *data) { struct igb_adapter *adapter = (struct igb_adapter *) data; struct e1000_hw *hw = &adapter->hw; adapter->test_icr |= E1000_READ_REG(hw, E1000_ICR); return IRQ_HANDLED; } static int igb_intr_test(struct igb_adapter *adapter, u64 *data) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; u32 mask, ics_mask, i = 0, shared_int = TRUE; u32 irq = adapter->pdev->irq; *data = 0; /* Hook up test interrupt handler just for this test */ if (adapter->msix_entries) { if (request_irq(adapter->msix_entries[0].vector, &igb_test_intr, 0, netdev->name, adapter)) { *data = 1; return -1; } } else if (adapter->flags & IGB_FLAG_HAS_MSI) { shared_int = FALSE; if (request_irq(irq, igb_test_intr, 0, netdev->name, adapter)) { *data = 1; return -1; } } else if (!request_irq(irq, igb_test_intr, IRQF_PROBE_SHARED, netdev->name, adapter)) { shared_int = FALSE; } else if (request_irq(irq, &igb_test_intr, IRQF_SHARED, netdev->name, adapter)) { *data = 1; return -1; } dev_info(pci_dev_to_dev(adapter->pdev), "testing %s interrupt\n", (shared_int ? "shared" : "unshared")); /* Disable all the interrupts */ E1000_WRITE_REG(hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); /* Define all writable bits for ICS */ switch (hw->mac.type) { case e1000_82575: ics_mask = 0x37F47EDD; break; case e1000_82576: ics_mask = 0x77D4FBFD; break; case e1000_82580: ics_mask = 0x77DCFED5; break; case e1000_i350: case e1000_i354: ics_mask = 0x77DCFED5; break; case e1000_i210: case e1000_i211: ics_mask = 0x774CFED5; break; default: ics_mask = 0x7FFFFFFF; break; } /* Test each interrupt */ for (; i < 31; i++) { /* Interrupt to test */ mask = 1 << i; if (!(mask & ics_mask)) continue; if (!shared_int) { /* Disable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; /* Flush any pending interrupts */ E1000_WRITE_REG(hw, E1000_ICR, ~0); E1000_WRITE_REG(hw, E1000_IMC, mask); E1000_WRITE_REG(hw, E1000_ICS, mask); E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); if (adapter->test_icr & mask) { *data = 3; break; } } /* Enable the interrupt to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was not posted to the bus, the * test failed. */ adapter->test_icr = 0; /* Flush any pending interrupts */ E1000_WRITE_REG(hw, E1000_ICR, ~0); E1000_WRITE_REG(hw, E1000_IMS, mask); E1000_WRITE_REG(hw, E1000_ICS, mask); E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); if (!(adapter->test_icr & mask)) { *data = 4; break; } if (!shared_int) { /* Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; /* Flush any pending interrupts */ E1000_WRITE_REG(hw, E1000_ICR, ~0); E1000_WRITE_REG(hw, E1000_IMC, ~mask); E1000_WRITE_REG(hw, E1000_ICS, ~mask); E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); if (adapter->test_icr & mask) { *data = 5; break; } } } /* Disable all the interrupts */ E1000_WRITE_REG(hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); /* Unhook test interrupt handler */ if (adapter->msix_entries) free_irq(adapter->msix_entries[0].vector, adapter); else free_irq(irq, adapter); return *data; } static void igb_free_desc_rings(struct igb_adapter *adapter) { igb_free_tx_resources(&adapter->test_tx_ring); igb_free_rx_resources(&adapter->test_rx_ring); } static int igb_setup_desc_rings(struct igb_adapter *adapter) { struct igb_ring *tx_ring = &adapter->test_tx_ring; struct igb_ring *rx_ring = &adapter->test_rx_ring; struct e1000_hw *hw = &adapter->hw; int ret_val; /* Setup Tx descriptor ring and Tx buffers */ tx_ring->count = IGB_DEFAULT_TXD; tx_ring->dev = pci_dev_to_dev(adapter->pdev); tx_ring->netdev = adapter->netdev; tx_ring->reg_idx = adapter->vfs_allocated_count; if (igb_setup_tx_resources(tx_ring)) { ret_val = 1; goto err_nomem; } igb_setup_tctl(adapter); igb_configure_tx_ring(adapter, tx_ring); /* Setup Rx descriptor ring and Rx buffers */ rx_ring->count = IGB_DEFAULT_RXD; rx_ring->dev = pci_dev_to_dev(adapter->pdev); rx_ring->netdev = adapter->netdev; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT rx_ring->rx_buffer_len = IGB_RX_HDR_LEN; #endif rx_ring->reg_idx = adapter->vfs_allocated_count; if (igb_setup_rx_resources(rx_ring)) { ret_val = 2; goto err_nomem; } /* set the default queue to queue 0 of PF */ E1000_WRITE_REG(hw, E1000_MRQC, adapter->vfs_allocated_count << 3); /* enable receive ring */ igb_setup_rctl(adapter); igb_configure_rx_ring(adapter, rx_ring); igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring)); return 0; err_nomem: igb_free_desc_rings(adapter); return ret_val; } static void igb_phy_disable_receiver(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; /* Write out to PHY registers 29 and 30 to disable the Receiver. */ e1000_write_phy_reg(hw, 29, 0x001F); e1000_write_phy_reg(hw, 30, 0x8FFC); e1000_write_phy_reg(hw, 29, 0x001A); e1000_write_phy_reg(hw, 30, 0x8FF0); } static int igb_integrated_phy_loopback(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 ctrl_reg = 0; hw->mac.autoneg = FALSE; if (hw->phy.type == e1000_phy_m88) { if (hw->phy.id != I210_I_PHY_ID) { /* Auto-MDI/MDIX Off */ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); /* reset to update Auto-MDI/MDIX */ e1000_write_phy_reg(hw, PHY_CONTROL, 0x9140); /* autoneg off */ e1000_write_phy_reg(hw, PHY_CONTROL, 0x8140); } else { /* force 1000, set loopback */ e1000_write_phy_reg(hw, I347AT4_PAGE_SELECT, 0); e1000_write_phy_reg(hw, PHY_CONTROL, 0x4140); } } else { /* enable MII loopback */ if (hw->phy.type == e1000_phy_82580) e1000_write_phy_reg(hw, I82577_PHY_LBK_CTRL, 0x8041); } /* force 1000, set loopback */ e1000_write_phy_reg(hw, PHY_CONTROL, 0x4140); /* Now set up the MAC to the same speed/duplex as the PHY. */ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ E1000_CTRL_FD | /* Force Duplex to FULL */ E1000_CTRL_SLU); /* Set link up enable bit */ if (hw->phy.type == e1000_phy_m88) ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); /* Disable the receiver on the PHY so when a cable is plugged in, the * PHY does not begin to autoneg when a cable is reconnected to the NIC. */ if (hw->phy.type == e1000_phy_m88) igb_phy_disable_receiver(adapter); mdelay(500); return 0; } static int igb_set_phy_loopback(struct igb_adapter *adapter) { return igb_integrated_phy_loopback(adapter); } static int igb_setup_loopback_test(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 reg; reg = E1000_READ_REG(hw, E1000_CTRL_EXT); /* use CTRL_EXT to identify link type as SGMII can appear as copper */ if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) { if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { /* Enable DH89xxCC MPHY for near end loopback */ reg = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTL); reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK) | E1000_MPHY_PCS_CLK_REG_OFFSET; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTL, reg); reg = E1000_READ_REG(hw, E1000_MPHY_DATA); reg |= E1000_MPHY_PCS_CLK_REG_DIGINELBEN; E1000_WRITE_REG(hw, E1000_MPHY_DATA, reg); } reg = E1000_READ_REG(hw, E1000_RCTL); reg |= E1000_RCTL_LBM_TCVR; E1000_WRITE_REG(hw, E1000_RCTL, reg); E1000_WRITE_REG(hw, E1000_SCTL, E1000_ENABLE_SERDES_LOOPBACK); reg = E1000_READ_REG(hw, E1000_CTRL); reg &= ~(E1000_CTRL_RFCE | E1000_CTRL_TFCE | E1000_CTRL_LRST); reg |= E1000_CTRL_SLU | E1000_CTRL_FD; E1000_WRITE_REG(hw, E1000_CTRL, reg); /* Unset switch control to serdes energy detect */ reg = E1000_READ_REG(hw, E1000_CONNSW); reg &= ~E1000_CONNSW_ENRGSRC; E1000_WRITE_REG(hw, E1000_CONNSW, reg); /* Unset sigdetect for SERDES loopback on * 82580 and newer devices */ if (hw->mac.type >= e1000_82580) { reg = E1000_READ_REG(hw, E1000_PCS_CFG0); reg |= E1000_PCS_CFG_IGN_SD; E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); } /* Set PCS register for forced speed */ reg = E1000_READ_REG(hw, E1000_PCS_LCTL); reg &= ~E1000_PCS_LCTL_AN_ENABLE; /* Disable Autoneg*/ reg |= E1000_PCS_LCTL_FLV_LINK_UP | /* Force link up */ E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ E1000_PCS_LCTL_FSD | /* Force Speed */ E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); return 0; } return igb_set_phy_loopback(adapter); } static void igb_loopback_cleanup(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 rctl; u16 phy_reg; if ((hw->device_id == E1000_DEV_ID_DH89XXCC_SGMII) || (hw->device_id == E1000_DEV_ID_DH89XXCC_SERDES) || (hw->device_id == E1000_DEV_ID_DH89XXCC_BACKPLANE) || (hw->device_id == E1000_DEV_ID_DH89XXCC_SFP)) { u32 reg; /* Disable near end loopback on DH89xxCC */ reg = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTL); reg = (reg & E1000_MPHY_ADDR_CTL_OFFSET_MASK ) | E1000_MPHY_PCS_CLK_REG_OFFSET; E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTL, reg); reg = E1000_READ_REG(hw, E1000_MPHY_DATA); reg &= ~E1000_MPHY_PCS_CLK_REG_DIGINELBEN; E1000_WRITE_REG(hw, E1000_MPHY_DATA, reg); } rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); E1000_WRITE_REG(hw, E1000_RCTL, rctl); hw->mac.autoneg = TRUE; e1000_read_phy_reg(hw, PHY_CONTROL, &phy_reg); if (phy_reg & MII_CR_LOOPBACK) { phy_reg &= ~MII_CR_LOOPBACK; if (hw->phy.type == I210_I_PHY_ID) e1000_write_phy_reg(hw, I347AT4_PAGE_SELECT, 0); e1000_write_phy_reg(hw, PHY_CONTROL, phy_reg); e1000_phy_commit(hw); } } static void igb_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size) { memset(skb->data, 0xFF, frame_size); frame_size /= 2; memset(&skb->data[frame_size], 0xAA, frame_size - 1); memset(&skb->data[frame_size + 10], 0xBE, 1); memset(&skb->data[frame_size + 12], 0xAF, 1); } static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer, unsigned int frame_size) { unsigned char *data; bool match = true; frame_size >>= 1; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT data = rx_buffer->skb->data; #else data = kmap(rx_buffer->page); #endif if (data[3] != 0xFF || data[frame_size + 10] != 0xBE || data[frame_size + 12] != 0xAF) match = false; #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT kunmap(rx_buffer->page); #endif return match; } static u16 igb_clean_test_rings(struct igb_ring *rx_ring, struct igb_ring *tx_ring, unsigned int size) { union e1000_adv_rx_desc *rx_desc; struct igb_rx_buffer *rx_buffer_info; struct igb_tx_buffer *tx_buffer_info; u16 rx_ntc, tx_ntc, count = 0; /* initialize next to clean and descriptor values */ rx_ntc = rx_ring->next_to_clean; tx_ntc = tx_ring->next_to_clean; rx_desc = IGB_RX_DESC(rx_ring, rx_ntc); while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) { /* check rx buffer */ rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc]; /* sync Rx buffer for CPU read */ dma_sync_single_for_cpu(rx_ring->dev, rx_buffer_info->dma, #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT IGB_RX_HDR_LEN, #else IGB_RX_BUFSZ, #endif DMA_FROM_DEVICE); /* verify contents of skb */ if (igb_check_lbtest_frame(rx_buffer_info, size)) count++; /* sync Rx buffer for device write */ dma_sync_single_for_device(rx_ring->dev, rx_buffer_info->dma, #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT IGB_RX_HDR_LEN, #else IGB_RX_BUFSZ, #endif DMA_FROM_DEVICE); /* unmap buffer on tx side */ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc]; igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); /* increment rx/tx next to clean counters */ rx_ntc++; if (rx_ntc == rx_ring->count) rx_ntc = 0; tx_ntc++; if (tx_ntc == tx_ring->count) tx_ntc = 0; /* fetch next descriptor */ rx_desc = IGB_RX_DESC(rx_ring, rx_ntc); } /* re-map buffers to ring, store next to clean values */ igb_alloc_rx_buffers(rx_ring, count); rx_ring->next_to_clean = rx_ntc; tx_ring->next_to_clean = tx_ntc; return count; } static int igb_run_loopback_test(struct igb_adapter *adapter) { struct igb_ring *tx_ring = &adapter->test_tx_ring; struct igb_ring *rx_ring = &adapter->test_rx_ring; u16 i, j, lc, good_cnt; int ret_val = 0; unsigned int size = IGB_RX_HDR_LEN; netdev_tx_t tx_ret_val; struct sk_buff *skb; /* allocate test skb */ skb = alloc_skb(size, GFP_KERNEL); if (!skb) return 11; /* place data into test skb */ igb_create_lbtest_frame(skb, size); skb_put(skb, size); /* * Calculate the loop count based on the largest descriptor ring * The idea is to wrap the largest ring a number of times using 64 * send/receive pairs during each loop */ if (rx_ring->count <= tx_ring->count) lc = ((tx_ring->count / 64) * 2) + 1; else lc = ((rx_ring->count / 64) * 2) + 1; for (j = 0; j <= lc; j++) { /* loop count loop */ /* reset count of good packets */ good_cnt = 0; /* place 64 packets on the transmit queue*/ for (i = 0; i < 64; i++) { skb_get(skb); tx_ret_val = igb_xmit_frame_ring(skb, tx_ring); if (tx_ret_val == NETDEV_TX_OK) good_cnt++; } if (good_cnt != 64) { ret_val = 12; break; } /* allow 200 milliseconds for packets to go from tx to rx */ msleep(200); good_cnt = igb_clean_test_rings(rx_ring, tx_ring, size); if (good_cnt != 64) { ret_val = 13; break; } } /* end loop count loop */ /* free the original skb */ kfree_skb(skb); return ret_val; } static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) { /* PHY loopback cannot be performed if SoL/IDER * sessions are active */ if (e1000_check_reset_block(&adapter->hw)) { dev_err(pci_dev_to_dev(adapter->pdev), "Cannot do PHY loopback test " "when SoL/IDER is active.\n"); *data = 0; goto out; } if (adapter->hw.mac.type == e1000_i354) { dev_info(&adapter->pdev->dev, "Loopback test not supported on i354.\n"); *data = 0; goto out; } *data = igb_setup_desc_rings(adapter); if (*data) goto out; *data = igb_setup_loopback_test(adapter); if (*data) goto err_loopback; *data = igb_run_loopback_test(adapter); igb_loopback_cleanup(adapter); err_loopback: igb_free_desc_rings(adapter); out: return *data; } static int igb_link_test(struct igb_adapter *adapter, u64 *data) { u32 link; int i, time; *data = 0; time = 0; if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { int i = 0; adapter->hw.mac.serdes_has_link = FALSE; /* On some blade server designs, link establishment * could take as long as 2-3 minutes */ do { e1000_check_for_link(&adapter->hw); if (adapter->hw.mac.serdes_has_link) goto out; msleep(20); } while (i++ < 3750); *data = 1; } else { for (i=0; i < IGB_MAX_LINK_TRIES; i++) { link = igb_has_link(adapter); if (link) goto out; else { time++; msleep(1000); } } if (!link) *data = 1; } out: return *data; } static void igb_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) { struct igb_adapter *adapter = netdev_priv(netdev); u16 autoneg_advertised; u8 forced_speed_duplex, autoneg; bool if_running = netif_running(netdev); set_bit(__IGB_TESTING, &adapter->state); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ /* save speed, duplex, autoneg settings */ autoneg_advertised = adapter->hw.phy.autoneg_advertised; forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; autoneg = adapter->hw.mac.autoneg; dev_info(pci_dev_to_dev(adapter->pdev), "offline testing starting\n"); /* power up link for link test */ igb_power_up_link(adapter); /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ if (igb_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; if (if_running) /* indicate we're in test mode */ dev_close(netdev); else igb_reset(adapter); if (igb_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; igb_reset(adapter); if (igb_eeprom_test(adapter, &data[1])) eth_test->flags |= ETH_TEST_FL_FAILED; igb_reset(adapter); if (igb_intr_test(adapter, &data[2])) eth_test->flags |= ETH_TEST_FL_FAILED; igb_reset(adapter); /* power up link for loopback test */ igb_power_up_link(adapter); if (igb_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; /* restore speed, duplex, autoneg settings */ adapter->hw.phy.autoneg_advertised = autoneg_advertised; adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; adapter->hw.mac.autoneg = autoneg; /* force this routine to wait until autoneg complete/timeout */ adapter->hw.phy.autoneg_wait_to_complete = TRUE; igb_reset(adapter); adapter->hw.phy.autoneg_wait_to_complete = FALSE; clear_bit(__IGB_TESTING, &adapter->state); if (if_running) dev_open(netdev); } else { dev_info(pci_dev_to_dev(adapter->pdev), "online testing starting\n"); /* PHY is powered down when interface is down */ if (if_running && igb_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; else data[4] = 0; /* Online tests aren't run; pass by default */ data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; clear_bit(__IGB_TESTING, &adapter->state); } msleep_interruptible(4 * 1000); } static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC | WAKE_PHY; wol->wolopts = 0; if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) return; /* apply any specific unsupported masks here */ switch (adapter->hw.device_id) { default: break; } if (adapter->wol & E1000_WUFC_EX) wol->wolopts |= WAKE_UCAST; if (adapter->wol & E1000_WUFC_MC) wol->wolopts |= WAKE_MCAST; if (adapter->wol & E1000_WUFC_BC) wol->wolopts |= WAKE_BCAST; if (adapter->wol & E1000_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; if (adapter->wol & E1000_WUFC_LNKC) wol->wolopts |= WAKE_PHY; } static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED)) return wol->wolopts ? -EOPNOTSUPP : 0; /* these settings will always override what we currently have */ adapter->wol = 0; if (wol->wolopts & WAKE_UCAST) adapter->wol |= E1000_WUFC_EX; if (wol->wolopts & WAKE_MCAST) adapter->wol |= E1000_WUFC_MC; if (wol->wolopts & WAKE_BCAST) adapter->wol |= E1000_WUFC_BC; if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; if (wol->wolopts & WAKE_PHY) adapter->wol |= E1000_WUFC_LNKC; device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); return 0; } /* bit defines for adapter->led_status */ #ifdef HAVE_ETHTOOL_SET_PHYS_ID static int igb_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; switch (state) { case ETHTOOL_ID_ACTIVE: e1000_blink_led(hw); return 2; case ETHTOOL_ID_ON: e1000_led_on(hw); break; case ETHTOOL_ID_OFF: e1000_led_off(hw); break; case ETHTOOL_ID_INACTIVE: e1000_led_off(hw); e1000_cleanup_led(hw); break; } return 0; } #else static int igb_phys_id(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; unsigned long timeout; timeout = data * 1000; /* * msleep_interruptable only accepts unsigned int so we are limited * in how long a duration we can wait */ if (!timeout || timeout > UINT_MAX) timeout = UINT_MAX; e1000_blink_led(hw); msleep_interruptible(timeout); e1000_led_off(hw); e1000_cleanup_led(hw); return 0; } #endif /* HAVE_ETHTOOL_SET_PHYS_ID */ static int igb_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct igb_adapter *adapter = netdev_priv(netdev); int i; if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) || ((ec->rx_coalesce_usecs > 3) && (ec->rx_coalesce_usecs < IGB_MIN_ITR_USECS)) || (ec->rx_coalesce_usecs == 2)) { printk("set_coalesce:invalid parameter.."); return -EINVAL; } if ((ec->tx_coalesce_usecs > IGB_MAX_ITR_USECS) || ((ec->tx_coalesce_usecs > 3) && (ec->tx_coalesce_usecs < IGB_MIN_ITR_USECS)) || (ec->tx_coalesce_usecs == 2)) return -EINVAL; if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs) return -EINVAL; if (ec->tx_max_coalesced_frames_irq) adapter->tx_work_limit = ec->tx_max_coalesced_frames_irq; /* If ITR is disabled, disable DMAC */ if (ec->rx_coalesce_usecs == 0) { adapter->dmac = IGB_DMAC_DISABLE; } /* convert to rate of irq's per second */ if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) adapter->rx_itr_setting = ec->rx_coalesce_usecs; else adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; /* convert to rate of irq's per second */ if (adapter->flags & IGB_FLAG_QUEUE_PAIRS) adapter->tx_itr_setting = adapter->rx_itr_setting; else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3) adapter->tx_itr_setting = ec->tx_coalesce_usecs; else adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; q_vector->tx.work_limit = adapter->tx_work_limit; if (q_vector->rx.ring) q_vector->itr_val = adapter->rx_itr_setting; else q_vector->itr_val = adapter->tx_itr_setting; if (q_vector->itr_val && q_vector->itr_val <= 3) q_vector->itr_val = IGB_START_ITR; q_vector->set_itr = 1; } return 0; } static int igb_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct igb_adapter *adapter = netdev_priv(netdev); if (adapter->rx_itr_setting <= 3) ec->rx_coalesce_usecs = adapter->rx_itr_setting; else ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit; if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) { if (adapter->tx_itr_setting <= 3) ec->tx_coalesce_usecs = adapter->tx_itr_setting; else ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; } return 0; } static int igb_nway_reset(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); if (netif_running(netdev)) igb_reinit_locked(adapter); return 0; } #ifdef HAVE_ETHTOOL_GET_SSET_COUNT static int igb_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_STATS: return IGB_STATS_LEN; case ETH_SS_TEST: return IGB_TEST_LEN; default: return -ENOTSUPP; } } #else static int igb_get_stats_count(struct net_device *netdev) { return IGB_STATS_LEN; } static int igb_diag_test_count(struct net_device *netdev) { return IGB_TEST_LEN; } #endif static void igb_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct igb_adapter *adapter = netdev_priv(netdev); #ifdef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats *net_stats = &netdev->stats; #else struct net_device_stats *net_stats = &adapter->net_stats; #endif u64 *queue_stat; int i, j, k; char *p; igb_update_stats(adapter); for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { p = (char *)adapter + igb_gstrings_stats[i].stat_offset; data[i] = (igb_gstrings_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < IGB_NETDEV_STATS_LEN; j++, i++) { p = (char *)net_stats + igb_gstrings_net_stats[j].stat_offset; data[i] = (igb_gstrings_net_stats[j].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats; for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++) data[i] = queue_stat[k]; } for (j = 0; j < adapter->num_rx_queues; j++) { queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats; for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++) data[i] = queue_stat[k]; } } static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { struct igb_adapter *adapter = netdev_priv(netdev); u8 *p = data; int i; switch (stringset) { case ETH_SS_TEST: memcpy(data, *igb_gstrings_test, IGB_TEST_LEN*ETH_GSTRING_LEN); break; case ETH_SS_STATS: for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { memcpy(p, igb_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) { memcpy(p, igb_gstrings_net_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } for (i = 0; i < adapter->num_tx_queues; i++) { sprintf(p, "tx_queue_%u_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "tx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; sprintf(p, "tx_queue_%u_restart", i); p += ETH_GSTRING_LEN; } for (i = 0; i < adapter->num_rx_queues; i++) { sprintf(p, "rx_queue_%u_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_drops", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_csum_err", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_alloc_failed", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_ipv4_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_ipv4e_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_ipv6_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_ipv6e_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_tcp_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_udp_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_sctp_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_nfs_packets", i); p += ETH_GSTRING_LEN; } /* BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */ break; } } #ifdef HAVE_ETHTOOL_GET_TS_INFO static int igb_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { struct igb_adapter *adapter = netdev_priv(dev); switch (adapter->hw.mac.type) { #ifdef HAVE_PTP_1588_CLOCK case e1000_82575: info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE; return 0; case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; if (adapter->ptp_clock) info->phc_index = ptp_clock_index(adapter->ptp_clock); else info->phc_index = -1; info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); info->rx_filters = 1 << HWTSTAMP_FILTER_NONE; /* 82576 does not support timestamping all packets. */ if (adapter->hw.mac.type >= e1000_82580) info->rx_filters |= 1 << HWTSTAMP_FILTER_ALL; else info->rx_filters |= (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); return 0; #endif /* HAVE_PTP_1588_CLOCK */ default: return -EOPNOTSUPP; } } #endif /* HAVE_ETHTOOL_GET_TS_INFO */ #ifdef CONFIG_PM_RUNTIME static int igb_ethtool_begin(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); pm_runtime_get_sync(&adapter->pdev->dev); return 0; } static void igb_ethtool_complete(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); pm_runtime_put(&adapter->pdev->dev); } #endif /* CONFIG_PM_RUNTIME */ #ifndef HAVE_NDO_SET_FEATURES static u32 igb_get_rx_csum(struct net_device *netdev) { return !!(netdev->features & NETIF_F_RXCSUM); } static int igb_set_rx_csum(struct net_device *netdev, u32 data) { const u32 feature_list = NETIF_F_RXCSUM; if (data) netdev->features |= feature_list; else netdev->features &= ~feature_list; return 0; } static int igb_set_tx_csum(struct net_device *netdev, u32 data) { struct igb_adapter *adapter = netdev_priv(netdev); #ifdef NETIF_F_IPV6_CSUM u32 feature_list = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; #else u32 feature_list = NETIF_F_IP_CSUM; #endif if (adapter->hw.mac.type >= e1000_82576) feature_list |= NETIF_F_SCTP_CSUM; if (data) netdev->features |= feature_list; else netdev->features &= ~feature_list; return 0; } #ifdef NETIF_F_TSO static int igb_set_tso(struct net_device *netdev, u32 data) { #ifdef NETIF_F_TSO6 const u32 feature_list = NETIF_F_TSO | NETIF_F_TSO6; #else const u32 feature_list = NETIF_F_TSO; #endif if (data) netdev->features |= feature_list; else netdev->features &= ~feature_list; #ifndef HAVE_NETDEV_VLAN_FEATURES if (!data) { struct igb_adapter *adapter = netdev_priv(netdev); struct net_device *v_netdev; int i; /* disable TSO on all VLANs if they're present */ if (!adapter->vlgrp) goto tso_out; for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { v_netdev = vlan_group_get_device(adapter->vlgrp, i); if (!v_netdev) continue; v_netdev->features &= ~feature_list; vlan_group_set_device(adapter->vlgrp, i, v_netdev); } } tso_out: #endif /* HAVE_NETDEV_VLAN_FEATURES */ return 0; } #endif /* NETIF_F_TSO */ #ifdef ETHTOOL_GFLAGS static int igb_set_flags(struct net_device *netdev, u32 data) { u32 supported_flags = ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_RXHASH; #ifndef HAVE_VLAN_RX_REGISTER u32 changed = netdev->features ^ data; #endif int rc; #ifndef IGB_NO_LRO supported_flags |= ETH_FLAG_LRO; #endif /* * Since there is no support for separate tx vlan accel * enabled make sure tx flag is cleared if rx is. */ if (!(data & ETH_FLAG_RXVLAN)) data &= ~ETH_FLAG_TXVLAN; rc = ethtool_op_set_flags(netdev, data, supported_flags); if (rc) return rc; #ifndef HAVE_VLAN_RX_REGISTER if (changed & ETH_FLAG_RXVLAN) igb_vlan_mode(netdev, data); #endif return 0; } #endif /* ETHTOOL_GFLAGS */ #endif /* HAVE_NDO_SET_FEATURES */ #ifdef ETHTOOL_SADV_COAL static int igb_set_adv_coal(struct net_device *netdev, struct ethtool_value *edata) { struct igb_adapter *adapter = netdev_priv(netdev); switch (edata->data) { case IGB_DMAC_DISABLE: adapter->dmac = edata->data; break; case IGB_DMAC_MIN: adapter->dmac = edata->data; break; case IGB_DMAC_500: adapter->dmac = edata->data; break; case IGB_DMAC_EN_DEFAULT: adapter->dmac = edata->data; break; case IGB_DMAC_2000: adapter->dmac = edata->data; break; case IGB_DMAC_3000: adapter->dmac = edata->data; break; case IGB_DMAC_4000: adapter->dmac = edata->data; break; case IGB_DMAC_5000: adapter->dmac = edata->data; break; case IGB_DMAC_6000: adapter->dmac = edata->data; break; case IGB_DMAC_7000: adapter->dmac = edata->data; break; case IGB_DMAC_8000: adapter->dmac = edata->data; break; case IGB_DMAC_9000: adapter->dmac = edata->data; break; case IGB_DMAC_MAX: adapter->dmac = edata->data; break; default: adapter->dmac = IGB_DMAC_DISABLE; printk("set_dmac: invalid setting, setting DMAC to %d\n", adapter->dmac); } printk("%s: setting DMAC to %d\n", netdev->name, adapter->dmac); return 0; } #endif /* ETHTOOL_SADV_COAL */ #ifdef ETHTOOL_GADV_COAL static void igb_get_dmac(struct net_device *netdev, struct ethtool_value *edata) { struct igb_adapter *adapter = netdev_priv(netdev); edata->data = adapter->dmac; return; } #endif #ifdef ETHTOOL_GEEE static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 ret_val; u16 phy_data; if ((hw->mac.type < e1000_i350) || (hw->phy.media_type != e1000_media_type_copper)) return -EOPNOTSUPP; edata->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full); if (!hw->dev_spec._82575.eee_disable) edata->advertised = mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert); /* The IPCNFG and EEER registers are not supported on I354. */ if (hw->mac.type == e1000_i354) { e1000_get_eee_status_i354(hw, (bool *)&edata->eee_active); } else { u32 eeer; eeer = E1000_READ_REG(hw, E1000_EEER); /* EEE status on negotiated link */ if (eeer & E1000_EEER_EEE_NEG) edata->eee_active = true; if (eeer & E1000_EEER_TX_LPI_EN) edata->tx_lpi_enabled = true; } /* EEE Link Partner Advertised */ switch (hw->mac.type) { case e1000_i350: ret_val = e1000_read_emi_reg(hw, E1000_EEE_LP_ADV_ADDR_I350, &phy_data); if (ret_val) return -ENODATA; edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data); break; case e1000_i354: case e1000_i210: case e1000_i211: ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_LP_ADV_ADDR_I210, E1000_EEE_LP_ADV_DEV_I210, &phy_data); if (ret_val) return -ENODATA; edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data); break; default: break; } edata->eee_enabled = !hw->dev_spec._82575.eee_disable; if ((hw->mac.type == e1000_i354) && (edata->eee_enabled)) edata->tx_lpi_enabled = true; /* * report correct negotiated EEE status for devices that * wrongly report EEE at half-duplex */ if (adapter->link_duplex == HALF_DUPLEX) { edata->eee_enabled = false; edata->eee_active = false; edata->tx_lpi_enabled = false; edata->advertised &= ~edata->advertised; } return 0; } #endif #ifdef ETHTOOL_SEEE static int igb_set_eee(struct net_device *netdev, struct ethtool_eee *edata) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct ethtool_eee eee_curr; s32 ret_val; if ((hw->mac.type < e1000_i350) || (hw->phy.media_type != e1000_media_type_copper)) return -EOPNOTSUPP; ret_val = igb_get_eee(netdev, &eee_curr); if (ret_val) return ret_val; if (eee_curr.eee_enabled) { if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) { dev_err(pci_dev_to_dev(adapter->pdev), "Setting EEE tx-lpi is not supported\n"); return -EINVAL; } /* Tx LPI time is not implemented currently */ if (edata->tx_lpi_timer) { dev_err(pci_dev_to_dev(adapter->pdev), "Setting EEE Tx LPI timer is not supported\n"); return -EINVAL; } if (edata->advertised & ~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) { dev_err(pci_dev_to_dev(adapter->pdev), "EEE Advertisement supports only 100Tx and or 100T full duplex\n"); return -EINVAL; } } else if (!edata->eee_enabled) { dev_err(pci_dev_to_dev(adapter->pdev), "Setting EEE options is not supported with EEE disabled\n"); return -EINVAL; } adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) { hw->dev_spec._82575.eee_disable = !edata->eee_enabled; /* reset link */ if (netif_running(netdev)) igb_reinit_locked(adapter); else igb_reset(adapter); } return 0; } #endif /* ETHTOOL_SEEE */ #ifdef ETHTOOL_GRXRINGS static int igb_get_rss_hash_opts(struct igb_adapter *adapter, struct ethtool_rxnfc *cmd) { cmd->data = 0; /* Report default options for RSS on igb */ switch (cmd->flow_type) { case TCP_V4_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case UDP_V4_FLOW: if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: case IPV4_FLOW: cmd->data |= RXH_IP_SRC | RXH_IP_DST; break; case TCP_V6_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case UDP_V6_FLOW: if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: case IPV6_FLOW: cmd->data |= RXH_IP_SRC | RXH_IP_DST; break; default: return -EINVAL; } return 0; } static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, #ifdef HAVE_ETHTOOL_GET_RXNFC_VOID_RULE_LOCS void *rule_locs) #else u32 *rule_locs) #endif { struct igb_adapter *adapter = netdev_priv(dev); int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_GRXRINGS: cmd->data = adapter->num_rx_queues; ret = 0; break; case ETHTOOL_GRXFH: ret = igb_get_rss_hash_opts(adapter, cmd); break; default: break; } return ret; } #define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \ IGB_FLAG_RSS_FIELD_IPV6_UDP) static int igb_set_rss_hash_opt(struct igb_adapter *adapter, struct ethtool_rxnfc *nfc) { u32 flags = adapter->flags; /* * RSS does not support anything other than hashing * to queues on src and dst IPs and ports */ if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) return -EINVAL; switch (nfc->flow_type) { case TCP_V4_FLOW: case TCP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || !(nfc->data & RXH_L4_B_0_1) || !(nfc->data & RXH_L4_B_2_3)) return -EINVAL; break; case UDP_V4_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) return -EINVAL; switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP; break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP; break; default: return -EINVAL; } break; case UDP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) return -EINVAL; switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP; break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP; break; default: return -EINVAL; } break; case AH_ESP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: case SCTP_V4_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: case SCTP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || (nfc->data & RXH_L4_B_0_1) || (nfc->data & RXH_L4_B_2_3)) return -EINVAL; break; default: return -EINVAL; } /* if we changed something we need to update flags */ if (flags != adapter->flags) { struct e1000_hw *hw = &adapter->hw; u32 mrqc = E1000_READ_REG(hw, E1000_MRQC); if ((flags & UDP_RSS_FLAGS) && !(adapter->flags & UDP_RSS_FLAGS)) DPRINTK(DRV, WARNING, "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n"); adapter->flags = flags; /* Perform hash on these packet types */ mrqc |= E1000_MRQC_RSS_FIELD_IPV4 | E1000_MRQC_RSS_FIELD_IPV4_TCP | E1000_MRQC_RSS_FIELD_IPV6 | E1000_MRQC_RSS_FIELD_IPV6_TCP; mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP | E1000_MRQC_RSS_FIELD_IPV6_UDP); if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } return 0; } static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct igb_adapter *adapter = netdev_priv(dev); int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_SRXFH: ret = igb_set_rss_hash_opt(adapter, cmd); break; default: break; } return ret; } #endif /* ETHTOOL_GRXRINGS */ static const struct ethtool_ops igb_ethtool_ops = { .get_settings = igb_get_settings, .set_settings = igb_set_settings, .get_drvinfo = igb_get_drvinfo, .get_regs_len = igb_get_regs_len, .get_regs = igb_get_regs, .get_wol = igb_get_wol, .set_wol = igb_set_wol, .get_msglevel = igb_get_msglevel, .set_msglevel = igb_set_msglevel, .nway_reset = igb_nway_reset, .get_link = igb_get_link, .get_eeprom_len = igb_get_eeprom_len, .get_eeprom = igb_get_eeprom, .set_eeprom = igb_set_eeprom, .get_ringparam = igb_get_ringparam, .set_ringparam = igb_set_ringparam, .get_pauseparam = igb_get_pauseparam, .set_pauseparam = igb_set_pauseparam, .self_test = igb_diag_test, .get_strings = igb_get_strings, #ifndef HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT #ifdef HAVE_ETHTOOL_SET_PHYS_ID .set_phys_id = igb_set_phys_id, #else .phys_id = igb_phys_id, #endif /* HAVE_ETHTOOL_SET_PHYS_ID */ #endif /* HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT */ #ifdef HAVE_ETHTOOL_GET_SSET_COUNT .get_sset_count = igb_get_sset_count, #else .get_stats_count = igb_get_stats_count, .self_test_count = igb_diag_test_count, #endif .get_ethtool_stats = igb_get_ethtool_stats, #ifdef HAVE_ETHTOOL_GET_PERM_ADDR .get_perm_addr = ethtool_op_get_perm_addr, #endif .get_coalesce = igb_get_coalesce, .set_coalesce = igb_set_coalesce, #ifndef HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT #ifdef HAVE_ETHTOOL_GET_TS_INFO .get_ts_info = igb_get_ts_info, #endif /* HAVE_ETHTOOL_GET_TS_INFO */ #endif /* HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT */ #ifdef CONFIG_PM_RUNTIME .begin = igb_ethtool_begin, .complete = igb_ethtool_complete, #endif /* CONFIG_PM_RUNTIME */ #ifndef HAVE_NDO_SET_FEATURES .get_rx_csum = igb_get_rx_csum, .set_rx_csum = igb_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = igb_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = igb_set_tso, #endif #ifdef ETHTOOL_GFLAGS .get_flags = ethtool_op_get_flags, .set_flags = igb_set_flags, #endif /* ETHTOOL_GFLAGS */ #endif /* HAVE_NDO_SET_FEATURES */ #ifdef ETHTOOL_GADV_COAL .get_advcoal = igb_get_adv_coal, .set_advcoal = igb_set_dmac_coal, #endif /* ETHTOOL_GADV_COAL */ #ifndef HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT #ifdef ETHTOOL_GEEE .get_eee = igb_get_eee, #endif #ifdef ETHTOOL_SEEE .set_eee = igb_set_eee, #endif #endif /* HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT */ #ifdef ETHTOOL_GRXRINGS .get_rxnfc = igb_get_rxnfc, .set_rxnfc = igb_set_rxnfc, #endif }; #ifdef HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT static const struct ethtool_ops_ext igb_ethtool_ops_ext = { .size = sizeof(struct ethtool_ops_ext), .get_ts_info = igb_get_ts_info, .set_phys_id = igb_set_phys_id, .get_eee = igb_get_eee, .set_eee = igb_set_eee, }; void igb_set_ethtool_ops(struct net_device *netdev) { SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops); set_ethtool_ops_ext(netdev, &igb_ethtool_ops_ext); } #else void igb_set_ethtool_ops(struct net_device *netdev) { /* have to "undeclare" const on this struct to remove warnings */ SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igb_ethtool_ops); } #endif /* HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT */ #endif /* SIOCETHTOOL */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_hwmon.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "igb.h" #include "e1000_82575.h" #include "e1000_hw.h" #ifdef IGB_HWMON #include #include #include #include #include #include #include #include #ifdef HAVE_I2C_SUPPORT static struct i2c_board_info i350_sensor_info = { I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)), }; #endif /* HAVE_I2C_SUPPORT */ /* hwmon callback functions */ static ssize_t igb_hwmon_show_location(struct device *dev, struct device_attribute *attr, char *buf) { struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, dev_attr); return sprintf(buf, "loc%u\n", igb_attr->sensor->location); } static ssize_t igb_hwmon_show_temp(struct device *dev, struct device_attribute *attr, char *buf) { struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, dev_attr); unsigned int value; /* reset the temp field */ igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw); value = igb_attr->sensor->temp; /* display millidegree */ value *= 1000; return sprintf(buf, "%u\n", value); } static ssize_t igb_hwmon_show_cautionthresh(struct device *dev, struct device_attribute *attr, char *buf) { struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, dev_attr); unsigned int value = igb_attr->sensor->caution_thresh; /* display millidegree */ value *= 1000; return sprintf(buf, "%u\n", value); } static ssize_t igb_hwmon_show_maxopthresh(struct device *dev, struct device_attribute *attr, char *buf) { struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr, dev_attr); unsigned int value = igb_attr->sensor->max_op_thresh; /* display millidegree */ value *= 1000; return sprintf(buf, "%u\n", value); } /* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. * @ adapter: pointer to the adapter structure * @ offset: offset in the eeprom sensor data table * @ type: type of sensor data to display * * For each file we want in hwmon's sysfs interface we need a device_attribute * This is included in our hwmon_attr struct that contains the references to * the data structures we need to get the data to display. */ static int igb_add_hwmon_attr(struct igb_adapter *adapter, unsigned int offset, int type) { int rc; unsigned int n_attr; struct hwmon_attr *igb_attr; n_attr = adapter->igb_hwmon_buff.n_hwmon; igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr]; switch (type) { case IGB_HWMON_TYPE_LOC: igb_attr->dev_attr.show = igb_hwmon_show_location; snprintf(igb_attr->name, sizeof(igb_attr->name), "temp%u_label", offset); break; case IGB_HWMON_TYPE_TEMP: igb_attr->dev_attr.show = igb_hwmon_show_temp; snprintf(igb_attr->name, sizeof(igb_attr->name), "temp%u_input", offset); break; case IGB_HWMON_TYPE_CAUTION: igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh; snprintf(igb_attr->name, sizeof(igb_attr->name), "temp%u_max", offset); break; case IGB_HWMON_TYPE_MAX: igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh; snprintf(igb_attr->name, sizeof(igb_attr->name), "temp%u_crit", offset); break; default: rc = -EPERM; return rc; } /* These always the same regardless of type */ igb_attr->sensor = &adapter->hw.mac.thermal_sensor_data.sensor[offset]; igb_attr->hw = &adapter->hw; igb_attr->dev_attr.store = NULL; igb_attr->dev_attr.attr.mode = S_IRUGO; igb_attr->dev_attr.attr.name = igb_attr->name; sysfs_attr_init(&igb_attr->dev_attr.attr); rc = device_create_file(&adapter->pdev->dev, &igb_attr->dev_attr); if (rc == 0) ++adapter->igb_hwmon_buff.n_hwmon; return rc; } static void igb_sysfs_del_adapter(struct igb_adapter *adapter) { int i; if (adapter == NULL) return; for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) { device_remove_file(&adapter->pdev->dev, &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr); } kfree(adapter->igb_hwmon_buff.hwmon_list); if (adapter->igb_hwmon_buff.device) hwmon_device_unregister(adapter->igb_hwmon_buff.device); } /* called from igb_main.c */ void igb_sysfs_exit(struct igb_adapter *adapter) { igb_sysfs_del_adapter(adapter); } /* called from igb_main.c */ int igb_sysfs_init(struct igb_adapter *adapter) { struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff; unsigned int i; int n_attrs; int rc = 0; #ifdef HAVE_I2C_SUPPORT struct i2c_client *client = NULL; #endif /* HAVE_I2C_SUPPORT */ /* If this method isn't defined we don't support thermals */ if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) goto exit; /* Don't create thermal hwmon interface if no sensors present */ rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)); if (rc) goto exit; #ifdef HAVE_I2C_SUPPORT /* init i2c_client */ client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); if (client == NULL) { dev_info(&adapter->pdev->dev, "Failed to create new i2c device..\n"); goto exit; } adapter->i2c_client = client; #endif /* HAVE_I2C_SUPPORT */ /* Allocation space for max attributes * max num sensors * values (loc, temp, max, caution) */ n_attrs = E1000_MAX_SENSORS * 4; igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr), GFP_KERNEL); if (!igb_hwmon->hwmon_list) { rc = -ENOMEM; goto err; } igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev); if (IS_ERR(igb_hwmon->device)) { rc = PTR_ERR(igb_hwmon->device); goto err; } for (i = 0; i < E1000_MAX_SENSORS; i++) { /* Only create hwmon sysfs entries for sensors that have * meaningful data. */ if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) continue; /* Bail if any hwmon attr struct fails to initialize */ rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION); rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC); rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP); rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX); if (rc) goto err; } goto exit; err: igb_sysfs_del_adapter(adapter); exit: return rc; } #endif /* IGB_HWMON */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_main.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include #include #include #include #include #include #include #ifdef NETIF_F_TSO #include #ifdef NETIF_F_TSO6 #include #include #endif #endif #ifdef SIOCGMIIPHY #include #endif #ifdef SIOCETHTOOL #include #endif #include #ifdef CONFIG_PM_RUNTIME #include #endif /* CONFIG_PM_RUNTIME */ #include #include "igb.h" #include "igb_vmdq.h" #include #if defined(DEBUG) || defined (DEBUG_DUMP) || defined (DEBUG_ICR) || defined(DEBUG_ITR) #define DRV_DEBUG "_debug" #else #define DRV_DEBUG #endif #define DRV_HW_PERF #define VERSION_SUFFIX #define MAJ 5 #define MIN 0 #define BUILD 6 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." __stringify(BUILD) VERSION_SUFFIX DRV_DEBUG DRV_HW_PERF char igb_driver_name[] = "igb"; char igb_driver_version[] = DRV_VERSION; static const char igb_driver_string[] = "Intel(R) Gigabit Ethernet Network Driver"; static const char igb_copyright[] = "Copyright (c) 2007-2013 Intel Corporation."; static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER_FLASHLESS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES_FLASHLESS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES) }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER) }, /* required last entry */ {0, } }; //MODULE_DEVICE_TABLE(pci, igb_pci_tbl); static void igb_set_sriov_capability(struct igb_adapter *adapter) __attribute__((__unused__)); void igb_reset(struct igb_adapter *); static int igb_setup_all_tx_resources(struct igb_adapter *); static int igb_setup_all_rx_resources(struct igb_adapter *); static void igb_free_all_tx_resources(struct igb_adapter *); static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); void igb_update_stats(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit igb_remove(struct pci_dev *pdev); static int igb_sw_init(struct igb_adapter *); static int igb_open(struct net_device *); static int igb_close(struct net_device *); static void igb_configure(struct igb_adapter *); static void igb_configure_tx(struct igb_adapter *); static void igb_configure_rx(struct igb_adapter *); static void igb_clean_all_tx_rings(struct igb_adapter *); static void igb_clean_all_rx_rings(struct igb_adapter *); static void igb_clean_tx_ring(struct igb_ring *); static void igb_set_rx_mode(struct net_device *); static void igb_update_phy_info(unsigned long); static void igb_watchdog(unsigned long); static void igb_watchdog_task(struct work_struct *); static void igb_dma_err_task(struct work_struct *); static void igb_dma_err_timer(unsigned long data); static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *); static struct net_device_stats *igb_get_stats(struct net_device *); static int igb_change_mtu(struct net_device *, int); void igb_full_sync_mac_table(struct igb_adapter *adapter); static int igb_set_mac(struct net_device *, void *); static void igb_set_uta(struct igb_adapter *adapter); static irqreturn_t igb_intr(int irq, void *); static irqreturn_t igb_intr_msi(int irq, void *); static irqreturn_t igb_msix_other(int irq, void *); static irqreturn_t igb_msix_ring(int irq, void *); #ifdef IGB_DCA static void igb_update_dca(struct igb_q_vector *); static void igb_setup_dca(struct igb_adapter *); #endif /* IGB_DCA */ static int igb_poll(struct napi_struct *, int); static bool igb_clean_tx_irq(struct igb_q_vector *); static bool igb_clean_rx_irq(struct igb_q_vector *, int); static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); static void igb_reset_task(struct work_struct *); #ifdef HAVE_VLAN_RX_REGISTER static void igb_vlan_mode(struct net_device *, struct vlan_group *); #endif #ifdef HAVE_VLAN_PROTOCOL static int igb_vlan_rx_add_vid(struct net_device *, __be16 proto, u16); static int igb_vlan_rx_kill_vid(struct net_device *, __be16 proto, u16); #elif defined HAVE_INT_NDO_VLAN_RX_ADD_VID #ifdef NETIF_F_HW_VLAN_CTAG_RX static int igb_vlan_rx_add_vid(struct net_device *, __always_unused __be16 proto, u16); static int igb_vlan_rx_kill_vid(struct net_device *, __always_unused __be16 proto, u16); #else static int igb_vlan_rx_add_vid(struct net_device *, u16); static int igb_vlan_rx_kill_vid(struct net_device *, u16); #endif #else static void igb_vlan_rx_add_vid(struct net_device *, u16); static void igb_vlan_rx_kill_vid(struct net_device *, u16); #endif static void igb_restore_vlan(struct igb_adapter *); void igb_rar_set(struct igb_adapter *adapter, u32 index); static void igb_ping_all_vfs(struct igb_adapter *); static void igb_msg_task(struct igb_adapter *); static void igb_vmm_control(struct igb_adapter *); static int igb_set_vf_mac(struct igb_adapter *, int, unsigned char *); static void igb_restore_vf_multicasts(struct igb_adapter *adapter); static void igb_process_mdd_event(struct igb_adapter *); #ifdef IFLA_VF_MAX static int igb_ndo_set_vf_mac( struct net_device *netdev, int vf, u8 *mac); static int igb_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos); #ifdef HAVE_VF_SPOOFCHK_CONFIGURE static int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); #endif #ifdef HAVE_VF_MIN_MAX_TXRATE static int igb_ndo_set_vf_bw(struct net_device *, int, int, int); #else /* HAVE_VF_MIN_MAX_TXRATE */ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); #endif /* HAVE_VF_MIN_MAX_TXRATE */ static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); static void igb_check_vf_rate_limit(struct igb_adapter *); #endif static int igb_vf_configure(struct igb_adapter *adapter, int vf); #ifdef CONFIG_PM #ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_suspend(struct device *dev); static int igb_resume(struct device *dev); #ifdef CONFIG_PM_RUNTIME static int igb_runtime_suspend(struct device *dev); static int igb_runtime_resume(struct device *dev); static int igb_runtime_idle(struct device *dev); #endif /* CONFIG_PM_RUNTIME */ static const struct dev_pm_ops igb_pm_ops = { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) .suspend = igb_suspend, .resume = igb_resume, .freeze = igb_suspend, .thaw = igb_resume, .poweroff = igb_suspend, .restore = igb_resume, #ifdef CONFIG_PM_RUNTIME .runtime_suspend = igb_runtime_suspend, .runtime_resume = igb_runtime_resume, .runtime_idle = igb_runtime_idle, #endif #else /* Linux >= 2.6.34 */ SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) #ifdef CONFIG_PM_RUNTIME SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, igb_runtime_idle) #endif /* CONFIG_PM_RUNTIME */ #endif /* Linux version */ }; #else static int igb_suspend(struct pci_dev *pdev, pm_message_t state); static int igb_resume(struct pci_dev *pdev); #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ #endif /* CONFIG_PM */ #ifndef USE_REBOOT_NOTIFIER static void igb_shutdown(struct pci_dev *); #else static int igb_notify_reboot(struct notifier_block *, unsigned long, void *); static struct notifier_block igb_notifier_reboot = { .notifier_call = igb_notify_reboot, .next = NULL, .priority = 0 }; #endif #ifdef IGB_DCA static int igb_notify_dca(struct notifier_block *, unsigned long, void *); static struct notifier_block dca_notifier = { .notifier_call = igb_notify_dca, .next = NULL, .priority = 0 }; #endif #ifdef CONFIG_NET_POLL_CONTROLLER /* for netdump / net console */ static void igb_netpoll(struct net_device *); #endif #ifdef HAVE_PCI_ERS static pci_ers_result_t igb_io_error_detected(struct pci_dev *, pci_channel_state_t); static pci_ers_result_t igb_io_slot_reset(struct pci_dev *); static void igb_io_resume(struct pci_dev *); static struct pci_error_handlers igb_err_handler = { .error_detected = igb_io_error_detected, .slot_reset = igb_io_slot_reset, .resume = igb_io_resume, }; #endif static void igb_init_fw(struct igb_adapter *adapter); static void igb_init_dmac(struct igb_adapter *adapter, u32 pba); static struct pci_driver igb_driver = { .name = igb_driver_name, .id_table = igb_pci_tbl, .probe = igb_probe, .remove = __devexit_p(igb_remove), #ifdef CONFIG_PM #ifdef HAVE_SYSTEM_SLEEP_PM_OPS .driver.pm = &igb_pm_ops, #else .suspend = igb_suspend, .resume = igb_resume, #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ #endif /* CONFIG_PM */ #ifndef USE_REBOOT_NOTIFIER .shutdown = igb_shutdown, #endif #ifdef HAVE_PCI_ERS .err_handler = &igb_err_handler #endif }; //MODULE_AUTHOR("Intel Corporation, "); //MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); //MODULE_LICENSE("GPL"); //MODULE_VERSION(DRV_VERSION); static void igb_vfta_set(struct igb_adapter *adapter, u32 vid, bool add) { struct e1000_hw *hw = &adapter->hw; struct e1000_host_mng_dhcp_cookie *mng_cookie = &hw->mng_cookie; u32 index = (vid >> E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; u32 mask = 1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK); u32 vfta; /* * if this is the management vlan the only option is to add it in so * that the management pass through will continue to work */ if ((mng_cookie->status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && (vid == mng_cookie->vlan_id)) add = TRUE; vfta = adapter->shadow_vfta[index]; if (add) vfta |= mask; else vfta &= ~mask; e1000_write_vfta(hw, index, vfta); adapter->shadow_vfta[index] = vfta; } static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; //module_param(debug, int, 0); //MODULE_PARM_DESC(debug, "Debug level (0=none, ..., 16=all)"); /** * igb_init_module - Driver Registration Routine * * igb_init_module is the first routine called when the driver is * loaded. All it does is register with the PCI subsystem. **/ static int __init igb_init_module(void) { int ret; printk(KERN_INFO "%s - version %s\n", igb_driver_string, igb_driver_version); printk(KERN_INFO "%s\n", igb_copyright); #ifdef IGB_HWMON /* only use IGB_PROCFS if IGB_HWMON is not defined */ #else #ifdef IGB_PROCFS if (igb_procfs_topdir_init()) printk(KERN_INFO "Procfs failed to initialize topdir\n"); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ #ifdef IGB_DCA dca_register_notify(&dca_notifier); #endif ret = pci_register_driver(&igb_driver); #ifdef USE_REBOOT_NOTIFIER if (ret >= 0) { register_reboot_notifier(&igb_notifier_reboot); } #endif return ret; } #undef module_init #define module_init(x) static int x(void) __attribute__((__unused__)); module_init(igb_init_module); /** * igb_exit_module - Driver Exit Cleanup Routine * * igb_exit_module is called just before the driver is removed * from memory. **/ static void __exit igb_exit_module(void) { #ifdef IGB_DCA dca_unregister_notify(&dca_notifier); #endif #ifdef USE_REBOOT_NOTIFIER unregister_reboot_notifier(&igb_notifier_reboot); #endif pci_unregister_driver(&igb_driver); #ifdef IGB_HWMON /* only compile IGB_PROCFS if IGB_HWMON is not defined */ #else #ifdef IGB_PROCFS igb_procfs_topdir_exit(); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ } #undef module_exit #define module_exit(x) static void x(void) __attribute__((__unused__)); module_exit(igb_exit_module); #define Q_IDX_82576(i) (((i & 0x1) << 3) + (i >> 1)) /** * igb_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize * * Once we know the feature-set enabled for the device, we'll cache * the register offset the descriptor ring is assigned to. **/ static void igb_cache_ring_register(struct igb_adapter *adapter) { int i = 0, j = 0; u32 rbase_offset = adapter->vfs_allocated_count; switch (adapter->hw.mac.type) { case e1000_82576: /* The queues are allocated for virtualization such that VF 0 * is allocated queues 0 and 8, VF 1 queues 1 and 9, etc. * In order to avoid collision we start at the first free queue * and continue consuming queues in the same sequence */ if ((adapter->rss_queues > 1) && adapter->vmdq_pools) { for (; i < adapter->rss_queues; i++) adapter->rx_ring[i]->reg_idx = rbase_offset + Q_IDX_82576(i); } case e1000_82575: case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: default: for (; i < adapter->num_rx_queues; i++) adapter->rx_ring[i]->reg_idx = rbase_offset + i; for (; j < adapter->num_tx_queues; j++) adapter->tx_ring[j]->reg_idx = rbase_offset + j; break; } } static void igb_configure_lli(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u16 port; /* LLI should only be enabled for MSI-X or MSI interrupts */ if (!adapter->msix_entries && !(adapter->flags & IGB_FLAG_HAS_MSI)) return; if (adapter->lli_port) { /* use filter 0 for port */ port = htons((u16)adapter->lli_port); E1000_WRITE_REG(hw, E1000_IMIR(0), (port | E1000_IMIR_PORT_IM_EN)); E1000_WRITE_REG(hw, E1000_IMIREXT(0), (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); } if (adapter->flags & IGB_FLAG_LLI_PUSH) { /* use filter 1 for push flag */ E1000_WRITE_REG(hw, E1000_IMIR(1), (E1000_IMIR_PORT_BP | E1000_IMIR_PORT_IM_EN)); E1000_WRITE_REG(hw, E1000_IMIREXT(1), (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_PSH)); } if (adapter->lli_size) { /* use filter 2 for size */ E1000_WRITE_REG(hw, E1000_IMIR(2), (E1000_IMIR_PORT_BP | E1000_IMIR_PORT_IM_EN)); E1000_WRITE_REG(hw, E1000_IMIREXT(2), (adapter->lli_size | E1000_IMIREXT_CTRL_BP)); } } /** * igb_write_ivar - configure ivar for given MSI-X vector * @hw: pointer to the HW structure * @msix_vector: vector number we are allocating to a given ring * @index: row index of IVAR register to write within IVAR table * @offset: column offset of in IVAR, should be multiple of 8 * * This function is intended to handle the writing of the IVAR register * for adapters 82576 and newer. The IVAR table consists of 2 columns, * each containing an cause allocation for an Rx and Tx ring, and a * variable number of rows depending on the number of queues supported. **/ static void igb_write_ivar(struct e1000_hw *hw, int msix_vector, int index, int offset) { u32 ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); /* clear any bits that are currently set */ ivar &= ~((u32)0xFF << offset); /* write vector and valid bit */ ivar |= (msix_vector | E1000_IVAR_VALID) << offset; E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); } #define IGB_N0_QUEUE -1 static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) { struct igb_adapter *adapter = q_vector->adapter; struct e1000_hw *hw = &adapter->hw; int rx_queue = IGB_N0_QUEUE; int tx_queue = IGB_N0_QUEUE; u32 msixbm = 0; if (q_vector->rx.ring) rx_queue = q_vector->rx.ring->reg_idx; if (q_vector->tx.ring) tx_queue = q_vector->tx.ring->reg_idx; switch (hw->mac.type) { case e1000_82575: /* The 82575 assigns vectors using a bitmask, which matches the bitmask for the EICR/EIMS/EIMC registers. To assign one or more queues to a vector, we write the appropriate bits into the MSIXBM register for that vector. */ if (rx_queue > IGB_N0_QUEUE) msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; if (tx_queue > IGB_N0_QUEUE) msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue; if (!adapter->msix_entries && msix_vector == 0) msixbm |= E1000_EIMS_OTHER; E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), msix_vector, msixbm); q_vector->eims_value = msixbm; break; case e1000_82576: /* * 82576 uses a table that essentially consists of 2 columns * with 8 rows. The ordering is column-major so we use the * lower 3 bits as the row index, and the 4th bit as the * column offset. */ if (rx_queue > IGB_N0_QUEUE) igb_write_ivar(hw, msix_vector, rx_queue & 0x7, (rx_queue & 0x8) << 1); if (tx_queue > IGB_N0_QUEUE) igb_write_ivar(hw, msix_vector, tx_queue & 0x7, ((tx_queue & 0x8) << 1) + 8); q_vector->eims_value = 1 << msix_vector; break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: /* * On 82580 and newer adapters the scheme is similar to 82576 * however instead of ordering column-major we have things * ordered row-major. So we traverse the table by using * bit 0 as the column offset, and the remaining bits as the * row index. */ if (rx_queue > IGB_N0_QUEUE) igb_write_ivar(hw, msix_vector, rx_queue >> 1, (rx_queue & 0x1) << 4); if (tx_queue > IGB_N0_QUEUE) igb_write_ivar(hw, msix_vector, tx_queue >> 1, ((tx_queue & 0x1) << 4) + 8); q_vector->eims_value = 1 << msix_vector; break; default: BUG(); break; } /* add q_vector eims value to global eims_enable_mask */ adapter->eims_enable_mask |= q_vector->eims_value; /* configure q_vector to set itr on first interrupt */ q_vector->set_itr = 1; } /** * igb_configure_msix - Configure MSI-X hardware * * igb_configure_msix sets up the hardware to properly * generate MSI-X interrupts. **/ static void igb_configure_msix(struct igb_adapter *adapter) { u32 tmp; int i, vector = 0; struct e1000_hw *hw = &adapter->hw; adapter->eims_enable_mask = 0; /* set vector for other causes, i.e. link changes */ switch (hw->mac.type) { case e1000_82575: tmp = E1000_READ_REG(hw, E1000_CTRL_EXT); /* enable MSI-X PBA support*/ tmp |= E1000_CTRL_EXT_PBA_CLR; /* Auto-Mask interrupts upon ICR read. */ tmp |= E1000_CTRL_EXT_EIAME; tmp |= E1000_CTRL_EXT_IRCA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, tmp); /* enable msix_other interrupt */ E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0), vector++, E1000_EIMS_OTHER); adapter->eims_other = E1000_EIMS_OTHER; break; case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: /* Turn on MSI-X capability first, or our settings * won't stick. And it will take days to debug. */ E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE | E1000_GPIE_PBA | E1000_GPIE_EIAME | E1000_GPIE_NSICR); /* enable msix_other interrupt */ adapter->eims_other = 1 << vector; tmp = (vector++ | E1000_IVAR_VALID) << 8; E1000_WRITE_REG(hw, E1000_IVAR_MISC, tmp); break; default: /* do nothing, since nothing else supports MSI-X */ break; } /* switch (hw->mac.type) */ adapter->eims_enable_mask |= adapter->eims_other; for (i = 0; i < adapter->num_q_vectors; i++) igb_assign_vector(adapter->q_vector[i], vector++); E1000_WRITE_FLUSH(hw); } /** * igb_request_msix - Initialize MSI-X interrupts * * igb_request_msix allocates MSI-X vectors and requests interrupts from the * kernel. **/ static int igb_request_msix(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, &igb_msix_other, 0, netdev->name, adapter); if (err) goto err_out; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; vector++; q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); if (q_vector->rx.ring && q_vector->tx.ring) sprintf(q_vector->name, "%s-TxRx-%u", netdev->name, q_vector->rx.ring->queue_index); else if (q_vector->tx.ring) sprintf(q_vector->name, "%s-tx-%u", netdev->name, q_vector->tx.ring->queue_index); else if (q_vector->rx.ring) sprintf(q_vector->name, "%s-rx-%u", netdev->name, q_vector->rx.ring->queue_index); else sprintf(q_vector->name, "%s-unused", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, igb_msix_ring, 0, q_vector->name, q_vector); if (err) goto err_free; } igb_configure_msix(adapter); return 0; err_free: /* free already assigned IRQs */ free_irq(adapter->msix_entries[free_vector++].vector, adapter); vector--; for (i = 0; i < vector; i++) { free_irq(adapter->msix_entries[free_vector++].vector, adapter->q_vector[i]); } err_out: return err; } static void igb_reset_interrupt_capability(struct igb_adapter *adapter) { if (adapter->msix_entries) { pci_disable_msix(adapter->pdev); kfree(adapter->msix_entries); adapter->msix_entries = NULL; } else if (adapter->flags & IGB_FLAG_HAS_MSI) { pci_disable_msi(adapter->pdev); } } /** * igb_free_q_vector - Free memory allocated for specific interrupt vector * @adapter: board private structure to initialize * @v_idx: Index of vector to be freed * * This function frees the memory allocated to the q_vector. In addition if * NAPI is enabled it will delete any references to the NAPI struct prior * to freeing the q_vector. **/ static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx) { struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; if (q_vector->tx.ring) adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; if (q_vector->rx.ring) adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL; adapter->q_vector[v_idx] = NULL; netif_napi_del(&q_vector->napi); #ifndef IGB_NO_LRO __skb_queue_purge(&q_vector->lrolist.active); #endif kfree(q_vector); } /** * igb_free_q_vectors - Free memory allocated for interrupt vectors * @adapter: board private structure to initialize * * This function frees the memory allocated to the q_vectors. In addition if * NAPI is enabled it will delete any references to the NAPI struct prior * to freeing the q_vector. **/ static void igb_free_q_vectors(struct igb_adapter *adapter) { int v_idx = adapter->num_q_vectors; adapter->num_tx_queues = 0; adapter->num_rx_queues = 0; adapter->num_q_vectors = 0; while (v_idx--) igb_free_q_vector(adapter, v_idx); } /** * igb_clear_interrupt_scheme - reset the device to a state of no interrupts * * This function resets the device so that it has 0 rx queues, tx queues, and * MSI-X interrupts allocated. */ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter) { igb_free_q_vectors(adapter); igb_reset_interrupt_capability(adapter); } /** * igb_process_mdd_event * @adapter - board private structure * * Identify a malicious VF, disable the VF TX/RX queues and log a message. */ static void igb_process_mdd_event(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 lvmmc, vfte, vfre, mdfb; u8 vf_queue; lvmmc = E1000_READ_REG(hw, E1000_LVMMC); vf_queue = lvmmc >> 29; /* VF index cannot be bigger or equal to VFs allocated */ if (vf_queue >= adapter->vfs_allocated_count) return; netdev_info(adapter->netdev, "VF %d misbehaved. VF queues are disabled. " "VM misbehavior code is 0x%x\n", vf_queue, lvmmc); /* Disable VFTE and VFRE related bits */ vfte = E1000_READ_REG(hw, E1000_VFTE); vfte &= ~(1 << vf_queue); E1000_WRITE_REG(hw, E1000_VFTE, vfte); vfre = E1000_READ_REG(hw, E1000_VFRE); vfre &= ~(1 << vf_queue); E1000_WRITE_REG(hw, E1000_VFRE, vfre); /* Disable MDFB related bit. Clear on write */ mdfb = E1000_READ_REG(hw, E1000_MDFB); mdfb |= (1 << vf_queue); E1000_WRITE_REG(hw, E1000_MDFB, mdfb); /* Reset the specific VF */ E1000_WRITE_REG(hw, E1000_VTCTRL(vf_queue), E1000_VTCTRL_RST); } /** * igb_disable_mdd * @adapter - board private structure * * Disable MDD behavior in the HW **/ static void igb_disable_mdd(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 reg; if ((hw->mac.type != e1000_i350) || (hw->mac.type != e1000_i354)) return; reg = E1000_READ_REG(hw, E1000_DTXCTL); reg &= (~E1000_DTXCTL_MDP_EN); E1000_WRITE_REG(hw, E1000_DTXCTL, reg); } /** * igb_enable_mdd * @adapter - board private structure * * Enable the HW to detect malicious driver and sends an interrupt to * the driver. **/ static void igb_enable_mdd(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 reg; /* Only available on i350 device */ if (hw->mac.type != e1000_i350) return; reg = E1000_READ_REG(hw, E1000_DTXCTL); reg |= E1000_DTXCTL_MDP_EN; E1000_WRITE_REG(hw, E1000_DTXCTL, reg); } /** * igb_reset_sriov_capability - disable SR-IOV if enabled * * Attempt to disable single root IO virtualization capabilites present in the * kernel. **/ static void igb_reset_sriov_capability(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; /* reclaim resources allocated to VFs */ if (adapter->vf_data) { if (!pci_vfs_assigned(pdev)) { /* * disable iov and allow time for transactions to * clear */ pci_disable_sriov(pdev); msleep(500); dev_info(pci_dev_to_dev(pdev), "IOV Disabled\n"); } else { dev_info(pci_dev_to_dev(pdev), "IOV Not Disabled\n " "VF(s) are assigned to guests!\n"); } /* Disable Malicious Driver Detection */ igb_disable_mdd(adapter); /* free vf data storage */ kfree(adapter->vf_data); adapter->vf_data = NULL; /* switch rings back to PF ownership */ E1000_WRITE_REG(hw, E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ); E1000_WRITE_FLUSH(hw); msleep(100); } adapter->vfs_allocated_count = 0; } /** * igb_set_sriov_capability - setup SR-IOV if supported * * Attempt to enable single root IO virtualization capabilites present in the * kernel. **/ static void igb_set_sriov_capability(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; int old_vfs = 0; int i; old_vfs = pci_num_vf(pdev); if (old_vfs) { dev_info(pci_dev_to_dev(pdev), "%d pre-allocated VFs found - override " "max_vfs setting of %d\n", old_vfs, adapter->vfs_allocated_count); adapter->vfs_allocated_count = old_vfs; } /* no VFs requested, do nothing */ if (!adapter->vfs_allocated_count) return; /* allocate vf data storage */ adapter->vf_data = kcalloc(adapter->vfs_allocated_count, sizeof(struct vf_data_storage), GFP_KERNEL); if (adapter->vf_data) { if (!old_vfs) { if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) goto err_out; } for (i = 0; i < adapter->vfs_allocated_count; i++) igb_vf_configure(adapter, i); switch (adapter->hw.mac.type) { case e1000_82576: case e1000_i350: /* Enable VM to VM loopback by default */ adapter->flags |= IGB_FLAG_LOOPBACK_ENABLE; break; default: /* Currently no other hardware supports loopback */ break; } /* DMA Coalescing is not supported in IOV mode. */ if (adapter->hw.mac.type >= e1000_i350) adapter->dmac = IGB_DMAC_DISABLE; if (adapter->hw.mac.type < e1000_i350) adapter->flags |= IGB_FLAG_DETECT_BAD_DMA; return; } err_out: kfree(adapter->vf_data); adapter->vf_data = NULL; adapter->vfs_allocated_count = 0; dev_warn(pci_dev_to_dev(pdev), "Failed to initialize SR-IOV virtualization\n"); } /** * igb_set_interrupt_capability - set MSI or MSI-X if supported * * Attempt to configure interrupts using the best available * capabilities of the hardware and kernel. **/ static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) { struct pci_dev *pdev = adapter->pdev; int err; int numvecs, i; if (!msix) adapter->int_mode = IGB_INT_MODE_MSI; /* Number of supported queues. */ adapter->num_rx_queues = adapter->rss_queues; if (adapter->vmdq_pools > 1) adapter->num_rx_queues += adapter->vmdq_pools - 1; #ifdef HAVE_TX_MQ if (adapter->vmdq_pools) adapter->num_tx_queues = adapter->vmdq_pools; else adapter->num_tx_queues = adapter->num_rx_queues; #else adapter->num_tx_queues = max_t(u32, 1, adapter->vmdq_pools); #endif switch (adapter->int_mode) { case IGB_INT_MODE_MSIX: /* start with one vector for every rx queue */ numvecs = adapter->num_rx_queues; /* if tx handler is separate add 1 for every tx queue */ if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) numvecs += adapter->num_tx_queues; /* store the number of vectors reserved for queues */ adapter->num_q_vectors = numvecs; /* add 1 vector for link status interrupts */ numvecs++; adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry), GFP_KERNEL); if (adapter->msix_entries) { for (i = 0; i < numvecs; i++) adapter->msix_entries[i].entry = i; err = pci_enable_msix(pdev, adapter->msix_entries, numvecs); if (err == 0) break; } /* MSI-X failed, so fall through and try MSI */ dev_warn(pci_dev_to_dev(pdev), "Failed to initialize MSI-X interrupts. " "Falling back to MSI interrupts.\n"); igb_reset_interrupt_capability(adapter); case IGB_INT_MODE_MSI: if (!pci_enable_msi(pdev)) adapter->flags |= IGB_FLAG_HAS_MSI; else dev_warn(pci_dev_to_dev(pdev), "Failed to initialize MSI " "interrupts. Falling back to legacy " "interrupts.\n"); /* Fall through */ case IGB_INT_MODE_LEGACY: /* disable advanced features and set number of queues to 1 */ igb_reset_sriov_capability(adapter); adapter->vmdq_pools = 0; adapter->rss_queues = 1; adapter->flags |= IGB_FLAG_QUEUE_PAIRS; adapter->num_rx_queues = 1; adapter->num_tx_queues = 1; adapter->num_q_vectors = 1; /* Don't do anything; this is system default */ break; } } static void igb_add_ring(struct igb_ring *ring, struct igb_ring_container *head) { head->ring = ring; head->count++; } /** * igb_alloc_q_vector - Allocate memory for a single interrupt vector * @adapter: board private structure to initialize * @v_count: q_vectors allocated on adapter, used for ring interleaving * @v_idx: index of vector in adapter struct * @txr_count: total number of Tx rings to allocate * @txr_idx: index of first Tx ring to allocate * @rxr_count: total number of Rx rings to allocate * @rxr_idx: index of first Rx ring to allocate * * We allocate one q_vector. If allocation fails we return -ENOMEM. **/ static int igb_alloc_q_vector(struct igb_adapter *adapter, unsigned int v_count, unsigned int v_idx, unsigned int txr_count, unsigned int txr_idx, unsigned int rxr_count, unsigned int rxr_idx) { struct igb_q_vector *q_vector; struct igb_ring *ring; int ring_count, size; /* igb only supports 1 Tx and/or 1 Rx queue per vector */ if (txr_count > 1 || rxr_count > 1) return -ENOMEM; ring_count = txr_count + rxr_count; size = sizeof(struct igb_q_vector) + (sizeof(struct igb_ring) * ring_count); /* allocate q_vector and rings */ q_vector = kzalloc(size, GFP_KERNEL); if (!q_vector) return -ENOMEM; #ifndef IGB_NO_LRO /* initialize LRO */ __skb_queue_head_init(&q_vector->lrolist.active); #endif /* initialize NAPI */ netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); /* tie q_vector and adapter together */ adapter->q_vector[v_idx] = q_vector; q_vector->adapter = adapter; /* initialize work limits */ q_vector->tx.work_limit = adapter->tx_work_limit; /* initialize ITR configuration */ q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0); q_vector->itr_val = IGB_START_ITR; /* initialize pointer to rings */ ring = q_vector->ring; /* intialize ITR */ if (rxr_count) { /* rx or rx/tx vector */ if (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3) q_vector->itr_val = adapter->rx_itr_setting; } else { /* tx only vector */ if (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3) q_vector->itr_val = adapter->tx_itr_setting; } if (txr_count) { /* assign generic ring traits */ ring->dev = &adapter->pdev->dev; ring->netdev = adapter->netdev; /* configure backlink on ring */ ring->q_vector = q_vector; /* update q_vector Tx values */ igb_add_ring(ring, &q_vector->tx); /* For 82575, context index must be unique per ring. */ if (adapter->hw.mac.type == e1000_82575) set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags); /* apply Tx specific ring traits */ ring->count = adapter->tx_ring_count; ring->queue_index = txr_idx; /* assign ring to adapter */ adapter->tx_ring[txr_idx] = ring; /* push pointer to next ring */ ring++; } if (rxr_count) { /* assign generic ring traits */ ring->dev = &adapter->pdev->dev; ring->netdev = adapter->netdev; /* configure backlink on ring */ ring->q_vector = q_vector; /* update q_vector Rx values */ igb_add_ring(ring, &q_vector->rx); #ifndef HAVE_NDO_SET_FEATURES /* enable rx checksum */ set_bit(IGB_RING_FLAG_RX_CSUM, &ring->flags); #endif /* set flag indicating ring supports SCTP checksum offload */ if (adapter->hw.mac.type >= e1000_82576) set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); if ((adapter->hw.mac.type == e1000_i350) || (adapter->hw.mac.type == e1000_i354)) set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); /* apply Rx specific ring traits */ ring->count = adapter->rx_ring_count; ring->queue_index = rxr_idx; /* assign ring to adapter */ adapter->rx_ring[rxr_idx] = ring; } return 0; } /** * igb_alloc_q_vectors - Allocate memory for interrupt vectors * @adapter: board private structure to initialize * * We allocate one q_vector per queue interrupt. If allocation fails we * return -ENOMEM. **/ static int igb_alloc_q_vectors(struct igb_adapter *adapter) { int q_vectors = adapter->num_q_vectors; int rxr_remaining = adapter->num_rx_queues; int txr_remaining = adapter->num_tx_queues; int rxr_idx = 0, txr_idx = 0, v_idx = 0; int err; if (q_vectors >= (rxr_remaining + txr_remaining)) { for (; rxr_remaining; v_idx++) { err = igb_alloc_q_vector(adapter, q_vectors, v_idx, 0, 0, 1, rxr_idx); if (err) goto err_out; /* update counts and index */ rxr_remaining--; rxr_idx++; } } for (; v_idx < q_vectors; v_idx++) { int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx); int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx); err = igb_alloc_q_vector(adapter, q_vectors, v_idx, tqpv, txr_idx, rqpv, rxr_idx); if (err) goto err_out; /* update counts and index */ rxr_remaining -= rqpv; txr_remaining -= tqpv; rxr_idx++; txr_idx++; } return 0; err_out: adapter->num_tx_queues = 0; adapter->num_rx_queues = 0; adapter->num_q_vectors = 0; while (v_idx--) igb_free_q_vector(adapter, v_idx); return -ENOMEM; } /** * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors * * This function initializes the interrupts and allocates all of the queues. **/ static int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix) { struct pci_dev *pdev = adapter->pdev; int err; igb_set_interrupt_capability(adapter, msix); err = igb_alloc_q_vectors(adapter); if (err) { dev_err(pci_dev_to_dev(pdev), "Unable to allocate memory for vectors\n"); goto err_alloc_q_vectors; } igb_cache_ring_register(adapter); return 0; err_alloc_q_vectors: igb_reset_interrupt_capability(adapter); return err; } /** * igb_request_irq - initialize interrupts * * Attempts to configure interrupts using the best available * capabilities of the hardware and kernel. **/ static int igb_request_irq(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; int err = 0; if (adapter->msix_entries) { err = igb_request_msix(adapter); if (!err) goto request_done; /* fall back to MSI */ igb_free_all_tx_resources(adapter); igb_free_all_rx_resources(adapter); igb_clear_interrupt_scheme(adapter); igb_reset_sriov_capability(adapter); err = igb_init_interrupt_scheme(adapter, false); if (err) goto request_done; igb_setup_all_tx_resources(adapter); igb_setup_all_rx_resources(adapter); igb_configure(adapter); } igb_assign_vector(adapter->q_vector[0], 0); if (adapter->flags & IGB_FLAG_HAS_MSI) { err = request_irq(pdev->irq, &igb_intr_msi, 0, netdev->name, adapter); if (!err) goto request_done; /* fall back to legacy interrupts */ igb_reset_interrupt_capability(adapter); adapter->flags &= ~IGB_FLAG_HAS_MSI; } err = request_irq(pdev->irq, &igb_intr, IRQF_SHARED, netdev->name, adapter); if (err) dev_err(pci_dev_to_dev(pdev), "Error %d getting interrupt\n", err); request_done: return err; } static void igb_free_irq(struct igb_adapter *adapter) { if (adapter->msix_entries) { int vector = 0, i; free_irq(adapter->msix_entries[vector++].vector, adapter); for (i = 0; i < adapter->num_q_vectors; i++) free_irq(adapter->msix_entries[vector++].vector, adapter->q_vector[i]); } else { free_irq(adapter->pdev->irq, adapter); } } /** * igb_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure **/ static void igb_irq_disable(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; /* * we need to be careful when disabling interrupts. The VFs are also * mapped into these registers and so clearing the bits can cause * issues on the VF drivers so we only need to clear what we set */ if (adapter->msix_entries) { u32 regval = E1000_READ_REG(hw, E1000_EIAM); E1000_WRITE_REG(hw, E1000_EIAM, regval & ~adapter->eims_enable_mask); E1000_WRITE_REG(hw, E1000_EIMC, adapter->eims_enable_mask); regval = E1000_READ_REG(hw, E1000_EIAC); E1000_WRITE_REG(hw, E1000_EIAC, regval & ~adapter->eims_enable_mask); } E1000_WRITE_REG(hw, E1000_IAM, 0); E1000_WRITE_REG(hw, E1000_IMC, ~0); E1000_WRITE_FLUSH(hw); if (adapter->msix_entries) { int vector = 0, i; synchronize_irq(adapter->msix_entries[vector++].vector); for (i = 0; i < adapter->num_q_vectors; i++) synchronize_irq(adapter->msix_entries[vector++].vector); } else { synchronize_irq(adapter->pdev->irq); } } /** * igb_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/ static void igb_irq_enable(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; if (adapter->msix_entries) { u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_DRSTA; u32 regval = E1000_READ_REG(hw, E1000_EIAC); E1000_WRITE_REG(hw, E1000_EIAC, regval | adapter->eims_enable_mask); regval = E1000_READ_REG(hw, E1000_EIAM); E1000_WRITE_REG(hw, E1000_EIAM, regval | adapter->eims_enable_mask); E1000_WRITE_REG(hw, E1000_EIMS, adapter->eims_enable_mask); if (adapter->vfs_allocated_count) { E1000_WRITE_REG(hw, E1000_MBVFIMR, 0xFF); ims |= E1000_IMS_VMMB; if (adapter->mdd) if ((adapter->hw.mac.type == e1000_i350) || (adapter->hw.mac.type == e1000_i354)) ims |= E1000_IMS_MDDET; } E1000_WRITE_REG(hw, E1000_IMS, ims); } else { E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK | E1000_IMS_DRSTA); E1000_WRITE_REG(hw, E1000_IAM, IMS_ENABLE_MASK | E1000_IMS_DRSTA); } } static void igb_update_mng_vlan(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u16 vid = adapter->hw.mng_cookie.vlan_id; u16 old_vid = adapter->mng_vlan_id; if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { /* add VID to filter table */ igb_vfta_set(adapter, vid, TRUE); adapter->mng_vlan_id = vid; } else { adapter->mng_vlan_id = IGB_MNG_VLAN_NONE; } if ((old_vid != (u16)IGB_MNG_VLAN_NONE) && (vid != old_vid) && #ifdef HAVE_VLAN_RX_REGISTER !vlan_group_get_device(adapter->vlgrp, old_vid)) { #else !test_bit(old_vid, adapter->active_vlans)) { #endif /* remove VID from filter table */ igb_vfta_set(adapter, old_vid, FALSE); } } /** * igb_release_hw_control - release control of the h/w to f/w * @adapter: address of board private structure * * igb_release_hw_control resets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. * **/ static void igb_release_hw_control(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 ctrl_ext; /* Let firmware take over control of h/w */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); } /** * igb_get_hw_control - get control of the h/w from f/w * @adapter: address of board private structure * * igb_get_hw_control sets CTRL_EXT:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that * the driver is loaded. * **/ static void igb_get_hw_control(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 ctrl_ext; /* Let firmware know the driver has taken over */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); } /** * igb_configure - configure the hardware for RX and TX * @adapter: private board structure **/ static void igb_configure(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; int i; igb_get_hw_control(adapter); igb_set_rx_mode(netdev); igb_restore_vlan(adapter); igb_setup_tctl(adapter); igb_setup_mrqc(adapter); igb_setup_rctl(adapter); igb_configure_tx(adapter); igb_configure_rx(adapter); e1000_rx_fifo_flush_82575(&adapter->hw); #ifdef CONFIG_NETDEVICES_MULTIQUEUE if (adapter->num_tx_queues > 1) netdev->features |= NETIF_F_MULTI_QUEUE; else netdev->features &= ~NETIF_F_MULTI_QUEUE; #endif /* call igb_desc_unused which always leaves * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ for (i = 0; i < adapter->num_rx_queues; i++) { struct igb_ring *ring = adapter->rx_ring[i]; igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); } } /** * igb_power_up_link - Power up the phy/serdes link * @adapter: address of board private structure **/ void igb_power_up_link(struct igb_adapter *adapter) { e1000_phy_hw_reset(&adapter->hw); if (adapter->hw.phy.media_type == e1000_media_type_copper) e1000_power_up_phy(&adapter->hw); else e1000_power_up_fiber_serdes_link(&adapter->hw); } /** * igb_power_down_link - Power down the phy/serdes link * @adapter: address of board private structure */ static void igb_power_down_link(struct igb_adapter *adapter) { if (adapter->hw.phy.media_type == e1000_media_type_copper) e1000_power_down_phy(&adapter->hw); else e1000_shutdown_fiber_serdes_link(&adapter->hw); } /* Detect and switch function for Media Auto Sense */ static void igb_check_swap_media(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 ctrl_ext, connsw; bool swap_now = false; bool link; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); connsw = E1000_READ_REG(hw, E1000_CONNSW); link = igb_has_link(adapter); /* need to live swap if current media is copper and we have fiber/serdes * to go to. */ if ((hw->phy.media_type == e1000_media_type_copper) && (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) { swap_now = true; } else if (!(connsw & E1000_CONNSW_SERDESD)) { /* copper signal takes time to appear */ if (adapter->copper_tries < 2) { adapter->copper_tries++; connsw |= E1000_CONNSW_AUTOSENSE_CONF; E1000_WRITE_REG(hw, E1000_CONNSW, connsw); return; } else { adapter->copper_tries = 0; if ((connsw & E1000_CONNSW_PHYSD) && (!(connsw & E1000_CONNSW_PHY_PDN))) { swap_now = true; connsw &= ~E1000_CONNSW_AUTOSENSE_CONF; E1000_WRITE_REG(hw, E1000_CONNSW, connsw); } } } if (swap_now) { switch (hw->phy.media_type) { case e1000_media_type_copper: dev_info(pci_dev_to_dev(adapter->pdev), "%s:MAS: changing media to fiber/serdes\n", adapter->netdev->name); ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; adapter->flags |= IGB_FLAG_MEDIA_RESET; adapter->copper_tries = 0; break; case e1000_media_type_internal_serdes: case e1000_media_type_fiber: dev_info(pci_dev_to_dev(adapter->pdev), "%s:MAS: changing media to copper\n", adapter->netdev->name); ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; adapter->flags |= IGB_FLAG_MEDIA_RESET; break; default: /* shouldn't get here during regular operation */ dev_err(pci_dev_to_dev(adapter->pdev), "%s:AMS: Invalid media type found, returning\n", adapter->netdev->name); break; } E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } } #ifdef HAVE_I2C_SUPPORT /* igb_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value */ static int igb_get_i2c_data(void *data) { struct igb_adapter *adapter = (struct igb_adapter *)data; struct e1000_hw *hw = &adapter->hw; s32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); return ((i2cctl & E1000_I2C_DATA_IN) != 0); } /* igb_set_i2c_data - Sets the I2C data bit * @data: pointer to hardware structure * @state: I2C data value (0 or 1) to set * * Sets the I2C data bit */ static void igb_set_i2c_data(void *data, int state) { struct igb_adapter *adapter = (struct igb_adapter *)data; struct e1000_hw *hw = &adapter->hw; s32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (state) i2cctl |= E1000_I2C_DATA_OUT; else i2cctl &= ~E1000_I2C_DATA_OUT; i2cctl &= ~E1000_I2C_DATA_OE_N; i2cctl |= E1000_I2C_CLK_OE_N; E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); E1000_WRITE_FLUSH(hw); } /* igb_set_i2c_clk - Sets the I2C SCL clock * @data: pointer to hardware structure * @state: state to set clock * * Sets the I2C clock line to state */ static void igb_set_i2c_clk(void *data, int state) { struct igb_adapter *adapter = (struct igb_adapter *)data; struct e1000_hw *hw = &adapter->hw; s32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); if (state) { i2cctl |= E1000_I2C_CLK_OUT; i2cctl &= ~E1000_I2C_CLK_OE_N; } else { i2cctl &= ~E1000_I2C_CLK_OUT; i2cctl &= ~E1000_I2C_CLK_OE_N; } E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); E1000_WRITE_FLUSH(hw); } /* igb_get_i2c_clk - Gets the I2C SCL clock state * @data: pointer to hardware structure * * Gets the I2C clock state */ static int igb_get_i2c_clk(void *data) { struct igb_adapter *adapter = (struct igb_adapter *)data; struct e1000_hw *hw = &adapter->hw; s32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); return ((i2cctl & E1000_I2C_CLK_IN) != 0); } static const struct i2c_algo_bit_data igb_i2c_algo = { .setsda = igb_set_i2c_data, .setscl = igb_set_i2c_clk, .getsda = igb_get_i2c_data, .getscl = igb_get_i2c_clk, .udelay = 5, .timeout = 20, }; /* igb_init_i2c - Init I2C interface * @adapter: pointer to adapter structure * */ static s32 igb_init_i2c(struct igb_adapter *adapter) { s32 status = E1000_SUCCESS; /* I2C interface supported on i350 devices */ if (adapter->hw.mac.type != e1000_i350) return E1000_SUCCESS; /* Initialize the i2c bus which is controlled by the registers. * This bus will use the i2c_algo_bit structue that implements * the protocol through toggling of the 4 bits in the register. */ adapter->i2c_adap.owner = THIS_MODULE; adapter->i2c_algo = igb_i2c_algo; adapter->i2c_algo.data = adapter; adapter->i2c_adap.algo_data = &adapter->i2c_algo; adapter->i2c_adap.dev.parent = &adapter->pdev->dev; strlcpy(adapter->i2c_adap.name, "igb BB", sizeof(adapter->i2c_adap.name)); status = i2c_bit_add_bus(&adapter->i2c_adap); return status; } #endif /* HAVE_I2C_SUPPORT */ /** * igb_up - Open the interface and prepare it to handle traffic * @adapter: board private structure **/ int igb_up(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; /* hardware has been reset, we need to reload some things */ igb_configure(adapter); clear_bit(__IGB_DOWN, &adapter->state); for (i = 0; i < adapter->num_q_vectors; i++) napi_enable(&(adapter->q_vector[i]->napi)); if (adapter->msix_entries) igb_configure_msix(adapter); else igb_assign_vector(adapter->q_vector[0], 0); igb_configure_lli(adapter); /* Clear any pending interrupts. */ E1000_READ_REG(hw, E1000_ICR); igb_irq_enable(adapter); /* notify VFs that reset has been completed */ if (adapter->vfs_allocated_count) { u32 reg_data = E1000_READ_REG(hw, E1000_CTRL_EXT); reg_data |= E1000_CTRL_EXT_PFRSTD; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg_data); } netif_tx_start_all_queues(adapter->netdev); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) schedule_work(&adapter->dma_err_task); /* start the watchdog. */ hw->mac.get_link_status = 1; schedule_work(&adapter->watchdog_task); if ((adapter->flags & IGB_FLAG_EEE) && (!hw->dev_spec._82575.eee_disable)) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; return 0; } void igb_down(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; u32 tctl, rctl; int i; /* signal that we're down so the interrupt handler does not * reschedule our watchdog timer */ set_bit(__IGB_DOWN, &adapter->state); /* disable receives in the hardware */ rctl = E1000_READ_REG(hw, E1000_RCTL); E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); /* flush and sleep below */ netif_tx_stop_all_queues(netdev); /* disable transmits in the hardware */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_EN; E1000_WRITE_REG(hw, E1000_TCTL, tctl); /* flush both disables and wait for them to finish */ E1000_WRITE_FLUSH(hw); usleep_range(10000, 20000); for (i = 0; i < adapter->num_q_vectors; i++) napi_disable(&(adapter->q_vector[i]->napi)); igb_irq_disable(adapter); adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; del_timer_sync(&adapter->watchdog_timer); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) del_timer_sync(&adapter->dma_err_timer); del_timer_sync(&adapter->phy_info_timer); netif_carrier_off(netdev); /* record the stats before reset*/ igb_update_stats(adapter); adapter->link_speed = 0; adapter->link_duplex = 0; #ifdef HAVE_PCI_ERS if (!pci_channel_offline(adapter->pdev)) igb_reset(adapter); #else igb_reset(adapter); #endif igb_clean_all_tx_rings(adapter); igb_clean_all_rx_rings(adapter); #ifdef IGB_DCA /* since we reset the hardware DCA settings were cleared */ igb_setup_dca(adapter); #endif } void igb_reinit_locked(struct igb_adapter *adapter) { WARN_ON(in_interrupt()); while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); igb_down(adapter); igb_up(adapter); clear_bit(__IGB_RESETTING, &adapter->state); } /** * igb_enable_mas - Media Autosense re-enable after swap * * @adapter: adapter struct **/ static s32 igb_enable_mas(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 connsw; s32 ret_val = E1000_SUCCESS; connsw = E1000_READ_REG(hw, E1000_CONNSW); if (hw->phy.media_type == e1000_media_type_copper) { /* configure for SerDes media detect */ if (!(connsw & E1000_CONNSW_SERDESD)) { connsw |= E1000_CONNSW_ENRGSRC; connsw |= E1000_CONNSW_AUTOSENSE_EN; E1000_WRITE_REG(hw, E1000_CONNSW, connsw); E1000_WRITE_FLUSH(hw); } else if (connsw & E1000_CONNSW_SERDESD) { /* already SerDes, no need to enable anything */ return ret_val; } else { dev_info(pci_dev_to_dev(adapter->pdev), "%s:MAS: Unable to configure feature, disabling..\n", adapter->netdev->name); adapter->flags &= ~IGB_FLAG_MAS_ENABLE; } } return ret_val; } void igb_reset(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; struct e1000_mac_info *mac = &hw->mac; struct e1000_fc_info *fc = &hw->fc; u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ switch (mac->type) { case e1000_i350: case e1000_82580: case e1000_i354: pba = E1000_READ_REG(hw, E1000_RXPBS); pba = e1000_rxpbs_adjust_82580(pba); break; case e1000_82576: pba = E1000_READ_REG(hw, E1000_RXPBS); pba &= E1000_RXPBS_SIZE_MASK_82576; break; case e1000_82575: case e1000_i210: case e1000_i211: default: pba = E1000_PBA_34K; break; } if ((adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) && (mac->type < e1000_82576)) { /* adjust PBA for jumbo frames */ E1000_WRITE_REG(hw, E1000_PBA, pba); /* To maintain wire speed transmits, the Tx FIFO should be * large enough to accommodate two full transmit packets, * rounded up to the next 1KB and expressed in KB. Likewise, * the Rx FIFO should be large enough to accommodate at least * one full receive packet and is similarly rounded up and * expressed in KB. */ pba = E1000_READ_REG(hw, E1000_PBA); /* upper 16 bits has Tx packet buffer allocation size in KB */ tx_space = pba >> 16; /* lower 16 bits has Rx packet buffer allocation size in KB */ pba &= 0xffff; /* the tx fifo also stores 16 bytes of information about the tx * but don't include ethernet FCS because hardware appends it */ min_tx_space = (adapter->max_frame_size + sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN) * 2; min_tx_space = ALIGN(min_tx_space, 1024); min_tx_space >>= 10; /* software strips receive CRC, so leave room for it */ min_rx_space = adapter->max_frame_size; min_rx_space = ALIGN(min_rx_space, 1024); min_rx_space >>= 10; /* If current Tx allocation is less than the min Tx FIFO size, * and the min Tx FIFO size is less than the current Rx FIFO * allocation, take space away from current Rx allocation */ if (tx_space < min_tx_space && ((min_tx_space - tx_space) < pba)) { pba = pba - (min_tx_space - tx_space); /* if short on rx space, rx wins and must trump tx * adjustment */ if (pba < min_rx_space) pba = min_rx_space; } E1000_WRITE_REG(hw, E1000_PBA, pba); } /* flow control settings */ /* The high water mark must be low enough to fit one full frame * (or the size used for early receive) above it in the Rx FIFO. * Set it to the lower of: * - 90% of the Rx FIFO size, or * - the full Rx FIFO size minus one full frame */ hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - 2 * adapter->max_frame_size)); fc->high_water = hwm & 0xFFFFFFF0; /* 16-byte granularity */ fc->low_water = fc->high_water - 16; fc->pause_time = 0xFFFF; fc->send_xon = 1; fc->current_mode = fc->requested_mode; /* disable receive for all VFs and wait one second */ if (adapter->vfs_allocated_count) { int i; /* * Clear all flags except indication that the PF has set * the VF MAC addresses administratively */ for (i = 0 ; i < adapter->vfs_allocated_count; i++) adapter->vf_data[i].flags &= IGB_VF_FLAG_PF_SET_MAC; /* ping all the active vfs to let them know we are going down */ igb_ping_all_vfs(adapter); /* disable transmits and receives */ E1000_WRITE_REG(hw, E1000_VFRE, 0); E1000_WRITE_REG(hw, E1000_VFTE, 0); } /* Allow time for pending master requests to run */ e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); if (adapter->flags & IGB_FLAG_MEDIA_RESET) { e1000_setup_init_funcs(hw, TRUE); igb_check_options(adapter); e1000_get_bus_info(hw); adapter->flags &= ~IGB_FLAG_MEDIA_RESET; } if (adapter->flags & IGB_FLAG_MAS_ENABLE) { if (igb_enable_mas(adapter)) dev_err(pci_dev_to_dev(pdev), "Error enabling Media Auto Sense\n"); } if (e1000_init_hw(hw)) dev_err(pci_dev_to_dev(pdev), "Hardware Error\n"); /* * Flow control settings reset on hardware reset, so guarantee flow * control is off when forcing speed. */ if (!hw->mac.autoneg) e1000_force_mac_fc(hw); igb_init_dmac(adapter, pba); /* Re-initialize the thermal sensor on i350 devices. */ if (mac->type == e1000_i350 && hw->bus.func == 0) { /* * If present, re-initialize the external thermal sensor * interface. */ if (adapter->ets) e1000_set_i2c_bb(hw); e1000_init_thermal_sensor_thresh(hw); } /*Re-establish EEE setting */ if (hw->phy.media_type == e1000_media_type_copper) { switch (mac->type) { case e1000_i350: case e1000_i210: case e1000_i211: e1000_set_eee_i350(hw); break; case e1000_i354: e1000_set_eee_i354(hw); break; default: break; } } if (!netif_running(adapter->netdev)) igb_power_down_link(adapter); igb_update_mng_vlan(adapter); /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ E1000_WRITE_REG(hw, E1000_VET, ETHERNET_IEEE_VLAN_TYPE); #ifdef HAVE_PTP_1588_CLOCK /* Re-enable PTP, where applicable. */ igb_ptp_reset(adapter); #endif /* HAVE_PTP_1588_CLOCK */ e1000_get_phy_info(hw); adapter->devrc++; } #ifdef HAVE_NDO_SET_FEATURES static kni_netdev_features_t igb_fix_features(struct net_device *netdev, kni_netdev_features_t features) { /* * Since there is no support for separate tx vlan accel * enabled make sure tx flag is cleared if rx is. */ #ifdef NETIF_F_HW_VLAN_CTAG_RX if (!(features & NETIF_F_HW_VLAN_CTAG_RX)) features &= ~NETIF_F_HW_VLAN_CTAG_TX; #else if (!(features & NETIF_F_HW_VLAN_RX)) features &= ~NETIF_F_HW_VLAN_TX; #endif /* If Rx checksum is disabled, then LRO should also be disabled */ if (!(features & NETIF_F_RXCSUM)) features &= ~NETIF_F_LRO; return features; } static int igb_set_features(struct net_device *netdev, kni_netdev_features_t features) { u32 changed = netdev->features ^ features; #ifdef NETIF_F_HW_VLAN_CTAG_RX if (changed & NETIF_F_HW_VLAN_CTAG_RX) #else if (changed & NETIF_F_HW_VLAN_RX) #endif igb_vlan_mode(netdev, features); return 0; } #ifdef NTF_SELF #ifdef USE_CONST_DEV_UC_CHAR static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, #ifdef HAVE_NDO_FDB_ADD_VID u16 vid, #endif u16 flags) #else static int igb_ndo_fdb_add(struct ndmsg *ndm, struct net_device *dev, unsigned char *addr, u16 flags) #endif { struct igb_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; int err; if (!(adapter->vfs_allocated_count)) return -EOPNOTSUPP; /* Hardware does not support aging addresses so if a * ndm_state is given only allow permanent addresses */ if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) { pr_info("%s: FDB only supports static addresses\n", igb_driver_name); return -EINVAL; } if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { u32 rar_uc_entries = hw->mac.rar_entry_count - (adapter->vfs_allocated_count + 1); if (netdev_uc_count(dev) < rar_uc_entries) err = dev_uc_add_excl(dev, addr); else err = -ENOMEM; } else if (is_multicast_ether_addr(addr)) { err = dev_mc_add_excl(dev, addr); } else { err = -EINVAL; } /* Only return duplicate errors if NLM_F_EXCL is set */ if (err == -EEXIST && !(flags & NLM_F_EXCL)) err = 0; return err; } #ifndef USE_DEFAULT_FDB_DEL_DUMP #ifdef USE_CONST_DEV_UC_CHAR static int igb_ndo_fdb_del(struct ndmsg *ndm, struct net_device *dev, const unsigned char *addr) #else static int igb_ndo_fdb_del(struct ndmsg *ndm, struct net_device *dev, unsigned char *addr) #endif { struct igb_adapter *adapter = netdev_priv(dev); int err = -EOPNOTSUPP; if (ndm->ndm_state & NUD_PERMANENT) { pr_info("%s: FDB only supports static addresses\n", igb_driver_name); return -EINVAL; } if (adapter->vfs_allocated_count) { if (is_unicast_ether_addr(addr)) err = dev_uc_del(dev, addr); else if (is_multicast_ether_addr(addr)) err = dev_mc_del(dev, addr); else err = -EINVAL; } return err; } static int igb_ndo_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, int idx) { struct igb_adapter *adapter = netdev_priv(dev); if (adapter->vfs_allocated_count) idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); return idx; } #endif /* USE_DEFAULT_FDB_DEL_DUMP */ #ifdef HAVE_BRIDGE_ATTRIBS #ifdef HAVE_NDO_BRIDGE_SET_DEL_LINK_FLAGS static int igb_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags) #else static int igb_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh) #endif /* HAVE_NDO_BRIDGE_SET_DEL_LINK_FLAGS */ { struct igb_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; struct nlattr *attr, *br_spec; int rem; if (!(adapter->vfs_allocated_count)) return -EOPNOTSUPP; switch (adapter->hw.mac.type) { case e1000_82576: case e1000_i350: case e1000_i354: break; default: return -EOPNOTSUPP; } br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); nla_for_each_nested(attr, br_spec, rem) { __u16 mode; if (nla_type(attr) != IFLA_BRIDGE_MODE) continue; mode = nla_get_u16(attr); if (mode == BRIDGE_MODE_VEPA) { e1000_vmdq_set_loopback_pf(hw, 0); adapter->flags &= ~IGB_FLAG_LOOPBACK_ENABLE; } else if (mode == BRIDGE_MODE_VEB) { e1000_vmdq_set_loopback_pf(hw, 1); adapter->flags |= IGB_FLAG_LOOPBACK_ENABLE; } else return -EINVAL; netdev_info(adapter->netdev, "enabling bridge mode: %s\n", mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB"); } return 0; } #ifdef HAVE_BRIDGE_FILTER #ifdef HAVE_NDO_BRIDGE_GETLINK_FILTER_MASK static int igb_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask, int nlflags) #else static int igb_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask) #endif /* HAVE_NDO_BRIDGE_GETLINK_FILTER_MASK */ #else static int igb_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev) #endif { struct igb_adapter *adapter = netdev_priv(dev); u16 mode; if (!(adapter->vfs_allocated_count)) return -EOPNOTSUPP; if (adapter->flags & IGB_FLAG_LOOPBACK_ENABLE) mode = BRIDGE_MODE_VEB; else mode = BRIDGE_MODE_VEPA; #ifdef HAVE_NDO_FDB_ADD_VID #ifdef HAVE_NDO_BRIDGE_GETLINK_FILTER_MASK return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0, nlflags); #else return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode, 0, 0); #endif /* HAVE_NDO_BRIDGE_GETLINK_FILTER_MASK */ #else return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode); #endif /* HAVE_NDO_FDB_ADD_VID */ } #endif /* HAVE_BRIDGE_ATTRIBS */ #endif /* NTF_SELF */ #endif /* HAVE_NDO_SET_FEATURES */ #ifdef HAVE_NET_DEVICE_OPS static const struct net_device_ops igb_netdev_ops = { .ndo_open = igb_open, .ndo_stop = igb_close, .ndo_start_xmit = igb_xmit_frame, .ndo_get_stats = igb_get_stats, .ndo_set_rx_mode = igb_set_rx_mode, .ndo_set_mac_address = igb_set_mac, .ndo_change_mtu = igb_change_mtu, .ndo_do_ioctl = igb_ioctl, .ndo_tx_timeout = igb_tx_timeout, .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, #ifdef IFLA_VF_MAX .ndo_set_vf_mac = igb_ndo_set_vf_mac, .ndo_set_vf_vlan = igb_ndo_set_vf_vlan, #ifdef HAVE_VF_MIN_MAX_TXRATE .ndo_set_vf_rate = igb_ndo_set_vf_bw, #else /* HAVE_VF_MIN_MAX_TXRATE */ .ndo_set_vf_tx_rate = igb_ndo_set_vf_bw, #endif /* HAVE_VF_MIN_MAX_TXRATE */ .ndo_get_vf_config = igb_ndo_get_vf_config, #ifdef HAVE_VF_SPOOFCHK_CONFIGURE .ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk, #endif /* HAVE_VF_SPOOFCHK_CONFIGURE */ #endif /* IFLA_VF_MAX */ #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = igb_netpoll, #endif #ifdef HAVE_NDO_SET_FEATURES .ndo_fix_features = igb_fix_features, .ndo_set_features = igb_set_features, #endif #ifdef HAVE_VLAN_RX_REGISTER .ndo_vlan_rx_register = igb_vlan_mode, #endif #ifndef HAVE_RHEL6_NETDEV_OPS_EXT_FDB #ifdef NTF_SELF .ndo_fdb_add = igb_ndo_fdb_add, #ifndef USE_DEFAULT_FDB_DEL_DUMP .ndo_fdb_del = igb_ndo_fdb_del, .ndo_fdb_dump = igb_ndo_fdb_dump, #endif #endif /* ! HAVE_RHEL6_NETDEV_OPS_EXT_FDB */ #ifdef HAVE_BRIDGE_ATTRIBS .ndo_bridge_setlink = igb_ndo_bridge_setlink, .ndo_bridge_getlink = igb_ndo_bridge_getlink, #endif /* HAVE_BRIDGE_ATTRIBS */ #endif }; #ifdef CONFIG_IGB_VMDQ_NETDEV static const struct net_device_ops igb_vmdq_ops = { .ndo_open = &igb_vmdq_open, .ndo_stop = &igb_vmdq_close, .ndo_start_xmit = &igb_vmdq_xmit_frame, .ndo_get_stats = &igb_vmdq_get_stats, .ndo_set_rx_mode = &igb_vmdq_set_rx_mode, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = &igb_vmdq_set_mac, .ndo_change_mtu = &igb_vmdq_change_mtu, .ndo_tx_timeout = &igb_vmdq_tx_timeout, .ndo_vlan_rx_register = &igb_vmdq_vlan_rx_register, .ndo_vlan_rx_add_vid = &igb_vmdq_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = &igb_vmdq_vlan_rx_kill_vid, }; #endif /* CONFIG_IGB_VMDQ_NETDEV */ #endif /* HAVE_NET_DEVICE_OPS */ #ifdef CONFIG_IGB_VMDQ_NETDEV void igb_assign_vmdq_netdev_ops(struct net_device *vnetdev) { #ifdef HAVE_NET_DEVICE_OPS vnetdev->netdev_ops = &igb_vmdq_ops; #else dev->open = &igb_vmdq_open; dev->stop = &igb_vmdq_close; dev->hard_start_xmit = &igb_vmdq_xmit_frame; dev->get_stats = &igb_vmdq_get_stats; #ifdef HAVE_SET_RX_MODE dev->set_rx_mode = &igb_vmdq_set_rx_mode; #endif dev->set_multicast_list = &igb_vmdq_set_rx_mode; dev->set_mac_address = &igb_vmdq_set_mac; dev->change_mtu = &igb_vmdq_change_mtu; #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = &igb_vmdq_tx_timeout; #endif #if defined(NETIF_F_HW_VLAN_TX) || defined(NETIF_F_HW_VLAN_CTAG_TX) dev->vlan_rx_register = &igb_vmdq_vlan_rx_register; dev->vlan_rx_add_vid = &igb_vmdq_vlan_rx_add_vid; dev->vlan_rx_kill_vid = &igb_vmdq_vlan_rx_kill_vid; #endif #endif igb_vmdq_set_ethtool_ops(vnetdev); vnetdev->watchdog_timeo = 5 * HZ; } int igb_init_vmdq_netdevs(struct igb_adapter *adapter) { int pool, err = 0, base_queue; struct net_device *vnetdev; struct igb_vmdq_adapter *vmdq_adapter; for (pool = 1; pool < adapter->vmdq_pools; pool++) { int qpp = (!adapter->rss_queues ? 1 : adapter->rss_queues); base_queue = pool * qpp; vnetdev = alloc_etherdev(sizeof(struct igb_vmdq_adapter)); if (!vnetdev) { err = -ENOMEM; break; } vmdq_adapter = netdev_priv(vnetdev); vmdq_adapter->vnetdev = vnetdev; vmdq_adapter->real_adapter = adapter; vmdq_adapter->rx_ring = adapter->rx_ring[base_queue]; vmdq_adapter->tx_ring = adapter->tx_ring[base_queue]; igb_assign_vmdq_netdev_ops(vnetdev); snprintf(vnetdev->name, IFNAMSIZ, "%sv%d", adapter->netdev->name, pool); vnetdev->features = adapter->netdev->features; #ifdef HAVE_NETDEV_VLAN_FEATURES vnetdev->vlan_features = adapter->netdev->vlan_features; #endif adapter->vmdq_netdev[pool-1] = vnetdev; err = register_netdev(vnetdev); if (err) break; } return err; } int igb_remove_vmdq_netdevs(struct igb_adapter *adapter) { int pool, err = 0; for (pool = 1; pool < adapter->vmdq_pools; pool++) { unregister_netdev(adapter->vmdq_netdev[pool-1]); free_netdev(adapter->vmdq_netdev[pool-1]); adapter->vmdq_netdev[pool-1] = NULL; } return err; } #endif /* CONFIG_IGB_VMDQ_NETDEV */ /** * igb_set_fw_version - Configure version string for ethtool * @adapter: adapter struct * **/ static void igb_set_fw_version(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct e1000_fw_version fw; e1000_get_fw_version(hw, &fw); switch (hw->mac.type) { case e1000_i210: case e1000_i211: if (!(e1000_get_flash_presence_i210(hw))) { snprintf(adapter->fw_version, sizeof(adapter->fw_version), "%2d.%2d-%d", fw.invm_major, fw.invm_minor, fw.invm_img_type); break; } /* fall through */ default: /* if option rom is valid, display its version too*/ if (fw.or_valid) { snprintf(adapter->fw_version, sizeof(adapter->fw_version), "%d.%d, 0x%08x, %d.%d.%d", fw.eep_major, fw.eep_minor, fw.etrack_id, fw.or_major, fw.or_build, fw.or_patch); /* no option rom */ } else { if (fw.etrack_id != 0X0000) { snprintf(adapter->fw_version, sizeof(adapter->fw_version), "%d.%d, 0x%08x", fw.eep_major, fw.eep_minor, fw.etrack_id); } else { snprintf(adapter->fw_version, sizeof(adapter->fw_version), "%d.%d.%d", fw.eep_major, fw.eep_minor, fw.eep_build); } } break; } return; } /** * igb_init_mas - init Media Autosense feature if enabled in the NVM * * @adapter: adapter struct **/ static void igb_init_mas(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u16 eeprom_data; e1000_read_nvm(hw, NVM_COMPAT, 1, &eeprom_data); switch (hw->bus.func) { case E1000_FUNC_0: if (eeprom_data & IGB_MAS_ENABLE_0) adapter->flags |= IGB_FLAG_MAS_ENABLE; break; case E1000_FUNC_1: if (eeprom_data & IGB_MAS_ENABLE_1) adapter->flags |= IGB_FLAG_MAS_ENABLE; break; case E1000_FUNC_2: if (eeprom_data & IGB_MAS_ENABLE_2) adapter->flags |= IGB_FLAG_MAS_ENABLE; break; case E1000_FUNC_3: if (eeprom_data & IGB_MAS_ENABLE_3) adapter->flags |= IGB_FLAG_MAS_ENABLE; break; default: /* Shouldn't get here */ dev_err(pci_dev_to_dev(adapter->pdev), "%s:AMS: Invalid port configuration, returning\n", adapter->netdev->name); break; } } /** * igb_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in igb_pci_tbl * * Returns 0 on success, negative on failure * * igb_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ static int __devinit igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *netdev; struct igb_adapter *adapter; struct e1000_hw *hw; u16 eeprom_data = 0; u8 pba_str[E1000_PBANUM_LENGTH]; s32 ret_val; static int global_quad_port_a; /* global quad port a indication */ int i, err, pci_using_dac; static int cards_found; err = pci_enable_device_mem(pdev); if (err) return err; pci_using_dac = 0; err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)); if (!err) { err = dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)); if (!err) pci_using_dac = 1; } else { err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); if (err) { err = dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); if (err) { IGB_ERR("No usable DMA configuration, " "aborting\n"); goto err_dma; } } } #ifndef HAVE_ASPM_QUIRKS /* 82575 requires that the pci-e link partner disable the L0s state */ switch (pdev->device) { case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); default: break; } #endif /* HAVE_ASPM_QUIRKS */ err = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), igb_driver_name); if (err) goto err_pci_reg; pci_enable_pcie_error_reporting(pdev); pci_set_master(pdev); err = -ENOMEM; #ifdef HAVE_TX_MQ netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), IGB_MAX_TX_QUEUES); #else netdev = alloc_etherdev(sizeof(struct igb_adapter)); #endif /* HAVE_TX_MQ */ if (!netdev) goto err_alloc_etherdev; SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; adapter->port_num = hw->bus.func; adapter->msg_enable = (1 << debug) - 1; #ifdef HAVE_PCI_ERS err = pci_save_state(pdev); if (err) goto err_ioremap; #endif err = -EIO; hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!hw->hw_addr) goto err_ioremap; #ifdef HAVE_NET_DEVICE_OPS netdev->netdev_ops = &igb_netdev_ops; #else /* HAVE_NET_DEVICE_OPS */ netdev->open = &igb_open; netdev->stop = &igb_close; netdev->get_stats = &igb_get_stats; #ifdef HAVE_SET_RX_MODE netdev->set_rx_mode = &igb_set_rx_mode; #endif netdev->set_multicast_list = &igb_set_rx_mode; netdev->set_mac_address = &igb_set_mac; netdev->change_mtu = &igb_change_mtu; netdev->do_ioctl = &igb_ioctl; #ifdef HAVE_TX_TIMEOUT netdev->tx_timeout = &igb_tx_timeout; #endif netdev->vlan_rx_register = igb_vlan_mode; netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = igb_vlan_rx_kill_vid; #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = igb_netpoll; #endif netdev->hard_start_xmit = &igb_xmit_frame; #endif /* HAVE_NET_DEVICE_OPS */ igb_set_ethtool_ops(netdev); #ifdef HAVE_TX_TIMEOUT netdev->watchdog_timeo = 5 * HZ; #endif strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); adapter->bd_number = cards_found; /* setup the private structure */ err = igb_sw_init(adapter); if (err) goto err_sw_init; e1000_get_bus_info(hw); hw->phy.autoneg_wait_to_complete = FALSE; hw->mac.adaptive_ifs = FALSE; /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { hw->phy.mdix = AUTO_ALL_MODES; hw->phy.disable_polarity_correction = FALSE; hw->phy.ms_type = e1000_ms_hw_default; } if (e1000_check_reset_block(hw)) dev_info(pci_dev_to_dev(pdev), "PHY reset is blocked due to SOL/IDER session.\n"); /* * features is initialized to 0 in allocation, it might have bits * set by igb_sw_init so we should use an or instead of an * assignment. */ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | #ifdef NETIF_F_IPV6_CSUM NETIF_F_IPV6_CSUM | #endif #ifdef NETIF_F_TSO NETIF_F_TSO | #ifdef NETIF_F_TSO6 NETIF_F_TSO6 | #endif #endif /* NETIF_F_TSO */ #ifdef NETIF_F_RXHASH NETIF_F_RXHASH | #endif NETIF_F_RXCSUM | #ifdef NETIF_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; #else NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX; #endif if (hw->mac.type >= e1000_82576) netdev->features |= NETIF_F_SCTP_CSUM; #ifdef HAVE_NDO_SET_FEATURES /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; #ifndef IGB_NO_LRO /* give us the option of enabling LRO later */ netdev->hw_features |= NETIF_F_LRO; #endif #else #ifdef NETIF_F_GRO /* this is only needed on kernels prior to 2.6.39 */ netdev->features |= NETIF_F_GRO; #endif #endif /* set this bit last since it cannot be part of hw_features */ #ifdef NETIF_F_HW_VLAN_CTAG_FILTER netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; #else netdev->features |= NETIF_F_HW_VLAN_FILTER; #endif #ifdef HAVE_NETDEV_VLAN_FEATURES netdev->vlan_features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG; #endif if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); #ifdef DEBUG if (adapter->dmac != IGB_DMAC_DISABLE) printk("%s: DMA Coalescing is enabled..\n", netdev->name); #endif /* before reading the NVM, reset the controller to put the device in a * known good starting state */ e1000_reset_hw(hw); /* make sure the NVM is good */ if (e1000_validate_nvm_checksum(hw) < 0) { dev_err(pci_dev_to_dev(pdev), "The NVM Checksum Is Not" " Valid\n"); err = -EIO; goto err_eeprom; } /* copy the MAC address out of the NVM */ if (e1000_read_mac_addr(hw)) dev_err(pci_dev_to_dev(pdev), "NVM Read Error\n"); memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); #ifdef ETHTOOL_GPERMADDR memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { #else if (!is_valid_ether_addr(netdev->dev_addr)) { #endif dev_err(pci_dev_to_dev(pdev), "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; } memcpy(&adapter->mac_table[0].addr, hw->mac.addr, netdev->addr_len); adapter->mac_table[0].queue = adapter->vfs_allocated_count; adapter->mac_table[0].state = (IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE); igb_rar_set(adapter, 0); /* get firmware version for ethtool -i */ igb_set_fw_version(adapter); /* Check if Media Autosense is enabled */ if (hw->mac.type == e1000_82580) igb_init_mas(adapter); setup_timer(&adapter->watchdog_timer, &igb_watchdog, (unsigned long) adapter); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) setup_timer(&adapter->dma_err_timer, &igb_dma_err_timer, (unsigned long) adapter); setup_timer(&adapter->phy_info_timer, &igb_update_phy_info, (unsigned long) adapter); INIT_WORK(&adapter->reset_task, igb_reset_task); INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) INIT_WORK(&adapter->dma_err_task, igb_dma_err_task); /* Initialize link properties that are user-changeable */ adapter->fc_autoneg = true; hw->mac.autoneg = true; hw->phy.autoneg_advertised = 0x2f; hw->fc.requested_mode = e1000_fc_default; hw->fc.current_mode = e1000_fc_default; e1000_validate_mdi_setting(hw); /* By default, support wake on port A */ if (hw->bus.func == 0) adapter->flags |= IGB_FLAG_WOL_SUPPORTED; /* Check the NVM for wake support for non-port A ports */ if (hw->mac.type >= e1000_82580) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &eeprom_data); else if (hw->bus.func == 1) e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); if (eeprom_data & IGB_EEPROM_APME) adapter->flags |= IGB_FLAG_WOL_SUPPORTED; /* now that we have the eeprom settings, apply the special cases where * the eeprom may be wrong or the board simply won't support wake on * lan on a particular port */ switch (pdev->device) { case E1000_DEV_ID_82575GB_QUAD_COPPER: adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: /* Wake events only supported on port A for dual fiber * regardless of eeprom setting */ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; else adapter->flags |= IGB_FLAG_QUAD_PORT_A; /* Reset for multiple quad port adapters */ if (++global_quad_port_a == 4) global_quad_port_a = 0; break; default: /* If the device can't wake, don't set software support */ if (!device_can_wakeup(&adapter->pdev->dev)) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; } /* initialize the wol settings based on the eeprom settings */ if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) adapter->wol |= E1000_WUFC_MAG; /* Some vendors want WoL disabled by default, but still supported */ if ((hw->mac.type == e1000_i350) && (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { adapter->flags |= IGB_FLAG_WOL_SUPPORTED; adapter->wol = 0; } device_set_wakeup_enable(pci_dev_to_dev(adapter->pdev), adapter->flags & IGB_FLAG_WOL_SUPPORTED); /* reset the hardware with the new settings */ igb_reset(adapter); adapter->devrc = 0; #ifdef HAVE_I2C_SUPPORT /* Init the I2C interface */ err = igb_init_i2c(adapter); if (err) { dev_err(&pdev->dev, "failed to init i2c interface\n"); goto err_eeprom; } #endif /* HAVE_I2C_SUPPORT */ /* let the f/w know that the h/w is now under the control of the * driver. */ igb_get_hw_control(adapter); strncpy(netdev->name, "eth%d", IFNAMSIZ); err = register_netdev(netdev); if (err) goto err_register; #ifdef CONFIG_IGB_VMDQ_NETDEV err = igb_init_vmdq_netdevs(adapter); if (err) goto err_register; #endif /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); #ifdef IGB_DCA if (dca_add_requester(&pdev->dev) == E1000_SUCCESS) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(pci_dev_to_dev(pdev), "DCA enabled\n"); igb_setup_dca(adapter); } #endif #ifdef HAVE_PTP_1588_CLOCK /* do hw tstamp init after resetting */ igb_ptp_init(adapter); #endif /* HAVE_PTP_1588_CLOCK */ dev_info(pci_dev_to_dev(pdev), "Intel(R) Gigabit Ethernet Network Connection\n"); /* print bus type/speed/width info */ dev_info(pci_dev_to_dev(pdev), "%s: (PCIe:%s:%s) ", netdev->name, ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5GT/s" : (hw->bus.speed == e1000_bus_speed_5000) ? "5.0GT/s" : (hw->mac.type == e1000_i354) ? "integrated" : "unknown"), ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" : (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" : (hw->mac.type == e1000_i354) ? "integrated" : "unknown")); dev_info(pci_dev_to_dev(pdev), "%s: MAC: ", netdev->name); for (i = 0; i < 6; i++) printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':'); ret_val = e1000_read_pba_string(hw, pba_str, E1000_PBANUM_LENGTH); if (ret_val) strncpy(pba_str, "Unknown", sizeof(pba_str) - 1); dev_info(pci_dev_to_dev(pdev), "%s: PBA No: %s\n", netdev->name, pba_str); /* Initialize the thermal sensor on i350 devices. */ if (hw->mac.type == e1000_i350) { if (hw->bus.func == 0) { u16 ets_word; /* * Read the NVM to determine if this i350 device * supports an external thermal sensor. */ e1000_read_nvm(hw, NVM_ETS_CFG, 1, &ets_word); if (ets_word != 0x0000 && ets_word != 0xFFFF) adapter->ets = true; else adapter->ets = false; } #ifdef IGB_HWMON igb_sysfs_init(adapter); #else #ifdef IGB_PROCFS igb_procfs_init(adapter); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ } else { adapter->ets = false; } if (hw->phy.media_type == e1000_media_type_copper) { switch (hw->mac.type) { case e1000_i350: case e1000_i210: case e1000_i211: /* Enable EEE for internal copper PHY devices */ err = e1000_set_eee_i350(hw); if ((!err) && (adapter->flags & IGB_FLAG_EEE)) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; break; case e1000_i354: if ((E1000_READ_REG(hw, E1000_CTRL_EXT)) & (E1000_CTRL_EXT_LINK_MODE_SGMII)) { err = e1000_set_eee_i354(hw); if ((!err) && (adapter->flags & IGB_FLAG_EEE)) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; } break; default: break; } } /* send driver version info to firmware */ if (hw->mac.type >= e1000_i350) igb_init_fw(adapter); #ifndef IGB_NO_LRO if (netdev->features & NETIF_F_LRO) dev_info(pci_dev_to_dev(pdev), "Internal LRO is enabled \n"); else dev_info(pci_dev_to_dev(pdev), "LRO is disabled \n"); #endif dev_info(pci_dev_to_dev(pdev), "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", adapter->msix_entries ? "MSI-X" : (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", adapter->num_rx_queues, adapter->num_tx_queues); cards_found++; pm_runtime_put_noidle(&pdev->dev); return 0; err_register: igb_release_hw_control(adapter); #ifdef HAVE_I2C_SUPPORT memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); #endif /* HAVE_I2C_SUPPORT */ err_eeprom: if (!e1000_check_reset_block(hw)) e1000_phy_hw_reset(hw); if (hw->flash_address) iounmap(hw->flash_address); err_sw_init: igb_clear_interrupt_scheme(adapter); igb_reset_sriov_capability(adapter); iounmap(hw->hw_addr); err_ioremap: free_netdev(netdev); err_alloc_etherdev: pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); err_pci_reg: err_dma: pci_disable_device(pdev); return err; } #ifdef HAVE_I2C_SUPPORT /* * igb_remove_i2c - Cleanup I2C interface * @adapter: pointer to adapter structure * */ static void igb_remove_i2c(struct igb_adapter *adapter) { /* free the adapter bus structure */ i2c_del_adapter(&adapter->i2c_adap); } #endif /* HAVE_I2C_SUPPORT */ /** * igb_remove - Device Removal Routine * @pdev: PCI device information struct * * igb_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. The could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory. **/ static void __devexit igb_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pm_runtime_get_noresume(&pdev->dev); #ifdef HAVE_I2C_SUPPORT igb_remove_i2c(adapter); #endif /* HAVE_I2C_SUPPORT */ #ifdef HAVE_PTP_1588_CLOCK igb_ptp_stop(adapter); #endif /* HAVE_PTP_1588_CLOCK */ /* flush_scheduled work may reschedule our watchdog task, so * explicitly disable watchdog tasks from being rescheduled */ set_bit(__IGB_DOWN, &adapter->state); del_timer_sync(&adapter->watchdog_timer); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) del_timer_sync(&adapter->dma_err_timer); del_timer_sync(&adapter->phy_info_timer); flush_scheduled_work(); #ifdef IGB_DCA if (adapter->flags & IGB_FLAG_DCA_ENABLED) { dev_info(pci_dev_to_dev(pdev), "DCA disabled\n"); dca_remove_requester(&pdev->dev); adapter->flags &= ~IGB_FLAG_DCA_ENABLED; E1000_WRITE_REG(hw, E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_DISABLE); } #endif /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ igb_release_hw_control(adapter); unregister_netdev(netdev); #ifdef CONFIG_IGB_VMDQ_NETDEV igb_remove_vmdq_netdevs(adapter); #endif igb_clear_interrupt_scheme(adapter); igb_reset_sriov_capability(adapter); iounmap(hw->hw_addr); if (hw->flash_address) iounmap(hw->flash_address); pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); #ifdef IGB_HWMON igb_sysfs_exit(adapter); #else #ifdef IGB_PROCFS igb_procfs_exit(adapter); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ kfree(adapter->mac_table); kfree(adapter->shadow_vfta); free_netdev(netdev); pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); } /** * igb_sw_init - Initialize general software structures (struct igb_adapter) * @adapter: board private structure to initialize * * igb_sw_init initializes the Adapter private data structure. * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ static int igb_sw_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; /* PCI config space info */ hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_device_id = pdev->subsystem_device; pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); /* set default ring sizes */ adapter->tx_ring_count = IGB_DEFAULT_TXD; adapter->rx_ring_count = IGB_DEFAULT_RXD; /* set default work limits */ adapter->tx_work_limit = IGB_DEFAULT_TX_WORK; adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; /* Initialize the hardware-specific values */ if (e1000_setup_init_funcs(hw, TRUE)) { dev_err(pci_dev_to_dev(pdev), "Hardware Initialization Failure\n"); return -EIO; } adapter->mac_table = kzalloc(sizeof(struct igb_mac_addr) * hw->mac.rar_entry_count, GFP_ATOMIC); /* Setup and initialize a copy of the hw vlan table array */ adapter->shadow_vfta = kzalloc(sizeof(u32) * E1000_VFTA_ENTRIES, GFP_ATOMIC); #ifdef NO_KNI /* These calls may decrease the number of queues */ if (hw->mac.type < e1000_i210) { igb_set_sriov_capability(adapter); } if (igb_init_interrupt_scheme(adapter, true)) { dev_err(pci_dev_to_dev(pdev), "Unable to allocate memory for queues\n"); return -ENOMEM; } /* Explicitly disable IRQ since the NIC can be in any state. */ igb_irq_disable(adapter); set_bit(__IGB_DOWN, &adapter->state); #endif return 0; } /** * igb_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ static int __igb_open(struct net_device *netdev, bool resuming) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; #ifdef CONFIG_PM_RUNTIME struct pci_dev *pdev = adapter->pdev; #endif /* CONFIG_PM_RUNTIME */ int err; int i; /* disallow open during test */ if (test_bit(__IGB_TESTING, &adapter->state)) { WARN_ON(resuming); return -EBUSY; } #ifdef CONFIG_PM_RUNTIME if (!resuming) pm_runtime_get_sync(&pdev->dev); #endif /* CONFIG_PM_RUNTIME */ netif_carrier_off(netdev); /* allocate transmit descriptors */ err = igb_setup_all_tx_resources(adapter); if (err) goto err_setup_tx; /* allocate receive descriptors */ err = igb_setup_all_rx_resources(adapter); if (err) goto err_setup_rx; igb_power_up_link(adapter); /* before we allocate an interrupt, we must be ready to handle it. * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt * as soon as we call pci_request_irq, so we have to setup our * clean_rx handler before we do so. */ igb_configure(adapter); err = igb_request_irq(adapter); if (err) goto err_req_irq; /* Notify the stack of the actual queue counts. */ netif_set_real_num_tx_queues(netdev, adapter->vmdq_pools ? 1 : adapter->num_tx_queues); err = netif_set_real_num_rx_queues(netdev, adapter->vmdq_pools ? 1 : adapter->num_rx_queues); if (err) goto err_set_queues; /* From here on the code is the same as igb_up() */ clear_bit(__IGB_DOWN, &adapter->state); for (i = 0; i < adapter->num_q_vectors; i++) napi_enable(&(adapter->q_vector[i]->napi)); igb_configure_lli(adapter); /* Clear any pending interrupts. */ E1000_READ_REG(hw, E1000_ICR); igb_irq_enable(adapter); /* notify VFs that reset has been completed */ if (adapter->vfs_allocated_count) { u32 reg_data = E1000_READ_REG(hw, E1000_CTRL_EXT); reg_data |= E1000_CTRL_EXT_PFRSTD; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg_data); } netif_tx_start_all_queues(netdev); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) schedule_work(&adapter->dma_err_task); /* start the watchdog. */ hw->mac.get_link_status = 1; schedule_work(&adapter->watchdog_task); return E1000_SUCCESS; err_set_queues: igb_free_irq(adapter); err_req_irq: igb_release_hw_control(adapter); igb_power_down_link(adapter); igb_free_all_rx_resources(adapter); err_setup_rx: igb_free_all_tx_resources(adapter); err_setup_tx: igb_reset(adapter); #ifdef CONFIG_PM_RUNTIME if (!resuming) pm_runtime_put(&pdev->dev); #endif /* CONFIG_PM_RUNTIME */ return err; } static int igb_open(struct net_device *netdev) { return __igb_open(netdev, false); } /** * igb_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the driver's control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ static int __igb_close(struct net_device *netdev, bool suspending) { struct igb_adapter *adapter = netdev_priv(netdev); #ifdef CONFIG_PM_RUNTIME struct pci_dev *pdev = adapter->pdev; #endif /* CONFIG_PM_RUNTIME */ WARN_ON(test_bit(__IGB_RESETTING, &adapter->state)); #ifdef CONFIG_PM_RUNTIME if (!suspending) pm_runtime_get_sync(&pdev->dev); #endif /* CONFIG_PM_RUNTIME */ igb_down(adapter); igb_release_hw_control(adapter); igb_free_irq(adapter); igb_free_all_tx_resources(adapter); igb_free_all_rx_resources(adapter); #ifdef CONFIG_PM_RUNTIME if (!suspending) pm_runtime_put_sync(&pdev->dev); #endif /* CONFIG_PM_RUNTIME */ return 0; } static int igb_close(struct net_device *netdev) { return __igb_close(netdev, false); } /** * igb_setup_tx_resources - allocate Tx resources (Descriptors) * @tx_ring: tx descriptor ring (for a specific queue) to setup * * Return 0 on success, negative on failure **/ int igb_setup_tx_resources(struct igb_ring *tx_ring) { struct device *dev = tx_ring->dev; int size; size = sizeof(struct igb_tx_buffer) * tx_ring->count; tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) goto err; tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; return 0; err: vfree(tx_ring->tx_buffer_info); dev_err(dev, "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; } /** * igb_setup_all_tx_resources - wrapper to allocate Tx resources * (Descriptors) for all queues * @adapter: board private structure * * Return 0 on success, negative on failure **/ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { err = igb_setup_tx_resources(adapter->tx_ring[i]); if (err) { dev_err(pci_dev_to_dev(pdev), "Allocation for Tx Queue %u failed\n", i); for (i--; i >= 0; i--) igb_free_tx_resources(adapter->tx_ring[i]); break; } } return err; } /** * igb_setup_tctl - configure the transmit control registers * @adapter: Board private structure **/ void igb_setup_tctl(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 tctl; /* disable queue 0 which is enabled by default on 82575 and 82576 */ E1000_WRITE_REG(hw, E1000_TXDCTL(0), 0); /* Program the Transmit Control Register */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); e1000_config_collision_dist(hw); /* Enable transmits */ tctl |= E1000_TCTL_EN; E1000_WRITE_REG(hw, E1000_TCTL, tctl); } static u32 igb_tx_wthresh(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; switch (hw->mac.type) { case e1000_i354: return 4; case e1000_82576: if (adapter->msix_entries) return 1; default: break; } return 16; } /** * igb_configure_tx_ring - Configure transmit ring after Reset * @adapter: board private structure * @ring: tx ring to configure * * Configure a transmit ring after a reset. **/ void igb_configure_tx_ring(struct igb_adapter *adapter, struct igb_ring *ring) { struct e1000_hw *hw = &adapter->hw; u32 txdctl = 0; u64 tdba = ring->dma; int reg_idx = ring->reg_idx; /* disable the queue */ E1000_WRITE_REG(hw, E1000_TXDCTL(reg_idx), 0); E1000_WRITE_FLUSH(hw); mdelay(10); E1000_WRITE_REG(hw, E1000_TDLEN(reg_idx), ring->count * sizeof(union e1000_adv_tx_desc)); E1000_WRITE_REG(hw, E1000_TDBAL(reg_idx), tdba & 0x00000000ffffffffULL); E1000_WRITE_REG(hw, E1000_TDBAH(reg_idx), tdba >> 32); ring->tail = hw->hw_addr + E1000_TDT(reg_idx); E1000_WRITE_REG(hw, E1000_TDH(reg_idx), 0); writel(0, ring->tail); txdctl |= IGB_TX_PTHRESH; txdctl |= IGB_TX_HTHRESH << 8; txdctl |= igb_tx_wthresh(adapter) << 16; txdctl |= E1000_TXDCTL_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_TXDCTL(reg_idx), txdctl); } /** * igb_configure_tx - Configure transmit Unit after Reset * @adapter: board private structure * * Configure the Tx unit of the MAC after a reset. **/ static void igb_configure_tx(struct igb_adapter *adapter) { int i; for (i = 0; i < adapter->num_tx_queues; i++) igb_configure_tx_ring(adapter, adapter->tx_ring[i]); } /** * igb_setup_rx_resources - allocate Rx resources (Descriptors) * @rx_ring: rx descriptor ring (for a specific queue) to setup * * Returns 0 on success, negative on failure **/ int igb_setup_rx_resources(struct igb_ring *rx_ring) { struct device *dev = rx_ring->dev; int size, desc_len; size = sizeof(struct igb_rx_buffer) * rx_ring->count; rx_ring->rx_buffer_info = vzalloc(size); if (!rx_ring->rx_buffer_info) goto err; desc_len = sizeof(union e1000_adv_rx_desc); /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * desc_len; rx_ring->size = ALIGN(rx_ring->size, 4096); rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) goto err; rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; return 0; err: vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; dev_err(dev, "Unable to allocate memory for the receive descriptor" " ring\n"); return -ENOMEM; } /** * igb_setup_all_rx_resources - wrapper to allocate Rx resources * (Descriptors) for all queues * @adapter: board private structure * * Return 0 on success, negative on failure **/ static int igb_setup_all_rx_resources(struct igb_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { err = igb_setup_rx_resources(adapter->rx_ring[i]); if (err) { dev_err(pci_dev_to_dev(pdev), "Allocation for Rx Queue %u failed\n", i); for (i--; i >= 0; i--) igb_free_rx_resources(adapter->rx_ring[i]); break; } } return err; } /** * igb_setup_mrqc - configure the multiple receive queue control registers * @adapter: Board private structure **/ static void igb_setup_mrqc(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 mrqc, rxcsum; u32 j, num_rx_queues, shift = 0, shift2 = 0; static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741, 0xB08FA343, 0xCB2BCAD0, 0xB4307BAE, 0xA32DCB77, 0x0CF23080, 0x3BB7426A, 0xFA01ACBE }; /* Fill out hash function seeds */ for (j = 0; j < 10; j++) E1000_WRITE_REG(hw, E1000_RSSRK(j), rsskey[j]); num_rx_queues = adapter->rss_queues; /* 82575 and 82576 supports 2 RSS queues for VMDq */ switch (hw->mac.type) { case e1000_82575: if (adapter->vmdq_pools) { shift = 2; shift2 = 6; break; } shift = 6; break; case e1000_82576: /* 82576 supports 2 RSS queues for SR-IOV */ if (adapter->vfs_allocated_count || adapter->vmdq_pools) { shift = 3; num_rx_queues = 2; } break; default: break; } /* * Populate the redirection table 4 entries at a time. To do this * we are generating the results for n and n+2 and then interleaving * those with the results with n+1 and n+3. */ for (j = 0; j < 32; j++) { /* first pass generates n and n+2 */ u32 base = ((j * 0x00040004) + 0x00020000) * num_rx_queues; u32 reta = (base & 0x07800780) >> (7 - shift); /* second pass generates n+1 and n+3 */ base += 0x00010001 * num_rx_queues; reta |= (base & 0x07800780) << (1 + shift); /* generate 2nd table for 82575 based parts */ if (shift2) reta |= (0x01010101 * num_rx_queues) << shift2; E1000_WRITE_REG(hw, E1000_RETA(j), reta); } /* * Disable raw packet checksumming so that RSS hash is placed in * descriptor on writeback. No need to enable TCP/UDP/IP checksum * offloads as they are enabled by default */ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); rxcsum |= E1000_RXCSUM_PCSD; if (adapter->hw.mac.type >= e1000_82576) /* Enable Receive Checksum Offload for SCTP */ rxcsum |= E1000_RXCSUM_CRCOFL; /* Don't need to set TUOFL or IPOFL, they default to 1 */ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* Generate RSS hash based on packet types, TCP/UDP * port numbers and/or IPv4/v6 src and dst addresses */ mrqc = E1000_MRQC_RSS_FIELD_IPV4 | E1000_MRQC_RSS_FIELD_IPV4_TCP | E1000_MRQC_RSS_FIELD_IPV6 | E1000_MRQC_RSS_FIELD_IPV6_TCP | E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP; if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP) mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP; /* If VMDq is enabled then we set the appropriate mode for that, else * we default to RSS so that an RSS hash is calculated per packet even * if we are only using one queue */ if (adapter->vfs_allocated_count || adapter->vmdq_pools) { if (hw->mac.type > e1000_82575) { /* Set the default pool for the PF's first queue */ u32 vtctl = E1000_READ_REG(hw, E1000_VT_CTL); vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK | E1000_VT_CTL_DISABLE_DEF_POOL); vtctl |= adapter->vfs_allocated_count << E1000_VT_CTL_DEFAULT_POOL_SHIFT; E1000_WRITE_REG(hw, E1000_VT_CTL, vtctl); } else if (adapter->rss_queues > 1) { /* set default queue for pool 1 to queue 2 */ E1000_WRITE_REG(hw, E1000_VT_CTL, adapter->rss_queues << 7); } if (adapter->rss_queues > 1) mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_2Q; else mrqc |= E1000_MRQC_ENABLE_VMDQ; } else { mrqc |= E1000_MRQC_ENABLE_RSS_4Q; } igb_vmm_control(adapter); E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } /** * igb_setup_rctl - configure the receive control registers * @adapter: Board private structure **/ void igb_setup_rctl(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 rctl; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF | (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT); /* * enable stripping of CRC. It's unlikely this will break BMC * redirection as it did with e1000. Newer features require * that the HW strips the CRC. */ rctl |= E1000_RCTL_SECRC; /* disable store bad packets and clear size bits. */ rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); /* enable LPE to prevent packets larger than max_frame_size */ rctl |= E1000_RCTL_LPE; /* disable queue 0 to prevent tail write w/o re-config */ E1000_WRITE_REG(hw, E1000_RXDCTL(0), 0); /* Attention!!! For SR-IOV PF driver operations you must enable * queue drop for all VF and PF queues to prevent head of line blocking * if an un-trusted VF does not provide descriptors to hardware. */ if (adapter->vfs_allocated_count) { /* set all queue drop enable bits */ E1000_WRITE_REG(hw, E1000_QDE, ALL_QUEUES); } E1000_WRITE_REG(hw, E1000_RCTL, rctl); } static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, int vfn) { struct e1000_hw *hw = &adapter->hw; u32 vmolr; /* if it isn't the PF check to see if VFs are enabled and * increase the size to support vlan tags */ if (vfn < adapter->vfs_allocated_count && adapter->vf_data[vfn].vlans_enabled) size += VLAN_HLEN; #ifdef CONFIG_IGB_VMDQ_NETDEV if (vfn >= adapter->vfs_allocated_count) { int queue = vfn - adapter->vfs_allocated_count; struct igb_vmdq_adapter *vadapter; vadapter = netdev_priv(adapter->vmdq_netdev[queue-1]); if (vadapter->vlgrp) size += VLAN_HLEN; } #endif vmolr = E1000_READ_REG(hw, E1000_VMOLR(vfn)); vmolr &= ~E1000_VMOLR_RLPML_MASK; vmolr |= size | E1000_VMOLR_LPE; E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); return 0; } /** * igb_rlpml_set - set maximum receive packet size * @adapter: board private structure * * Configure maximum receivable packet size. **/ static void igb_rlpml_set(struct igb_adapter *adapter) { u32 max_frame_size = adapter->max_frame_size; struct e1000_hw *hw = &adapter->hw; u16 pf_id = adapter->vfs_allocated_count; if (adapter->vmdq_pools && hw->mac.type != e1000_82575) { int i; for (i = 0; i < adapter->vmdq_pools; i++) igb_set_vf_rlpml(adapter, max_frame_size, pf_id + i); /* * If we're in VMDQ or SR-IOV mode, then set global RLPML * to our max jumbo frame size, in case we need to enable * jumbo frames on one of the rings later. * This will not pass over-length frames into the default * queue because it's gated by the VMOLR.RLPML. */ max_frame_size = MAX_JUMBO_FRAME_SIZE; } /* Set VF RLPML for the PF device. */ if (adapter->vfs_allocated_count) igb_set_vf_rlpml(adapter, max_frame_size, pf_id); E1000_WRITE_REG(hw, E1000_RLPML, max_frame_size); } static inline void igb_set_vf_vlan_strip(struct igb_adapter *adapter, int vfn, bool enable) { struct e1000_hw *hw = &adapter->hw; u32 val; void __iomem *reg; if (hw->mac.type < e1000_82576) return; if (hw->mac.type == e1000_i350) reg = hw->hw_addr + E1000_DVMOLR(vfn); else reg = hw->hw_addr + E1000_VMOLR(vfn); val = readl(reg); if (enable) val |= E1000_VMOLR_STRVLAN; else val &= ~(E1000_VMOLR_STRVLAN); writel(val, reg); } static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn, bool aupe) { struct e1000_hw *hw = &adapter->hw; u32 vmolr; /* * This register exists only on 82576 and newer so if we are older then * we should exit and do nothing */ if (hw->mac.type < e1000_82576) return; vmolr = E1000_READ_REG(hw, E1000_VMOLR(vfn)); if (aupe) vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ else vmolr &= ~(E1000_VMOLR_AUPE); /* Tagged packets ONLY */ /* clear all bits that might not be set */ vmolr &= ~E1000_VMOLR_RSSE; if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count) vmolr |= E1000_VMOLR_RSSE; /* enable RSS */ vmolr |= E1000_VMOLR_BAM; /* Accept broadcast */ vmolr |= E1000_VMOLR_LPE; /* Accept long packets */ E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); } /** * igb_configure_rx_ring - Configure a receive ring after Reset * @adapter: board private structure * @ring: receive ring to be configured * * Configure the Rx unit of the MAC after a reset. **/ void igb_configure_rx_ring(struct igb_adapter *adapter, struct igb_ring *ring) { struct e1000_hw *hw = &adapter->hw; u64 rdba = ring->dma; int reg_idx = ring->reg_idx; u32 srrctl = 0, rxdctl = 0; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT /* * RLPML prevents us from receiving a frame larger than max_frame so * it is safe to just set the rx_buffer_len to max_frame without the * risk of an skb over panic. */ ring->rx_buffer_len = max_t(u32, adapter->max_frame_size, MAXIMUM_ETHERNET_VLAN_SIZE); #endif /* disable the queue */ E1000_WRITE_REG(hw, E1000_RXDCTL(reg_idx), 0); /* Set DMA base address registers */ E1000_WRITE_REG(hw, E1000_RDBAL(reg_idx), rdba & 0x00000000ffffffffULL); E1000_WRITE_REG(hw, E1000_RDBAH(reg_idx), rdba >> 32); E1000_WRITE_REG(hw, E1000_RDLEN(reg_idx), ring->count * sizeof(union e1000_adv_rx_desc)); /* initialize head and tail */ ring->tail = hw->hw_addr + E1000_RDT(reg_idx); E1000_WRITE_REG(hw, E1000_RDH(reg_idx), 0); writel(0, ring->tail); /* reset next-to- use/clean to place SW in sync with hardwdare */ ring->next_to_clean = 0; ring->next_to_use = 0; #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT ring->next_to_alloc = 0; #endif /* set descriptor configuration */ #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT; #else /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ srrctl = ALIGN(ring->rx_buffer_len, 1024) >> E1000_SRRCTL_BSIZEPKT_SHIFT; #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; #ifdef HAVE_PTP_1588_CLOCK if (hw->mac.type >= e1000_82580) srrctl |= E1000_SRRCTL_TIMESTAMP; #endif /* HAVE_PTP_1588_CLOCK */ /* * We should set the drop enable bit if: * SR-IOV is enabled * or * Flow Control is disabled and number of RX queues > 1 * * This allows us to avoid head of line blocking for security * and performance reasons. */ if (adapter->vfs_allocated_count || (adapter->num_rx_queues > 1 && (hw->fc.requested_mode == e1000_fc_none || hw->fc.requested_mode == e1000_fc_rx_pause))) srrctl |= E1000_SRRCTL_DROP_EN; E1000_WRITE_REG(hw, E1000_SRRCTL(reg_idx), srrctl); /* set filtering for VMDQ pools */ igb_set_vmolr(adapter, reg_idx & 0x7, true); rxdctl |= IGB_RX_PTHRESH; rxdctl |= IGB_RX_HTHRESH << 8; rxdctl |= IGB_RX_WTHRESH << 16; /* enable receive descriptor fetching */ rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; E1000_WRITE_REG(hw, E1000_RXDCTL(reg_idx), rxdctl); } /** * igb_configure_rx - Configure receive Unit after Reset * @adapter: board private structure * * Configure the Rx unit of the MAC after a reset. **/ static void igb_configure_rx(struct igb_adapter *adapter) { int i; /* set UTA to appropriate mode */ igb_set_uta(adapter); igb_full_sync_mac_table(adapter); /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) igb_configure_rx_ring(adapter, adapter->rx_ring[i]); } /** * igb_free_tx_resources - Free Tx Resources per Queue * @tx_ring: Tx descriptor ring for a specific queue * * Free all transmit software resources **/ void igb_free_tx_resources(struct igb_ring *tx_ring) { igb_clean_tx_ring(tx_ring); vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; /* if not set, then don't free */ if (!tx_ring->desc) return; dma_free_coherent(tx_ring->dev, tx_ring->size, tx_ring->desc, tx_ring->dma); tx_ring->desc = NULL; } /** * igb_free_all_tx_resources - Free Tx Resources for All Queues * @adapter: board private structure * * Free all transmit software resources **/ static void igb_free_all_tx_resources(struct igb_adapter *adapter) { int i; for (i = 0; i < adapter->num_tx_queues; i++) igb_free_tx_resources(adapter->tx_ring[i]); } void igb_unmap_and_free_tx_resource(struct igb_ring *ring, struct igb_tx_buffer *tx_buffer) { if (tx_buffer->skb) { dev_kfree_skb_any(tx_buffer->skb); if (dma_unmap_len(tx_buffer, len)) dma_unmap_single(ring->dev, dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); } else if (dma_unmap_len(tx_buffer, len)) { dma_unmap_page(ring->dev, dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); } tx_buffer->next_to_watch = NULL; tx_buffer->skb = NULL; dma_unmap_len_set(tx_buffer, len, 0); /* buffer_info must be completely set up in the transmit path */ } /** * igb_clean_tx_ring - Free Tx Buffers * @tx_ring: ring to be cleaned **/ static void igb_clean_tx_ring(struct igb_ring *tx_ring) { struct igb_tx_buffer *buffer_info; unsigned long size; u16 i; if (!tx_ring->tx_buffer_info) return; /* Free all the Tx ring sk_buffs */ for (i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->tx_buffer_info[i]; igb_unmap_and_free_tx_resource(tx_ring, buffer_info); } netdev_tx_reset_queue(txring_txq(tx_ring)); size = sizeof(struct igb_tx_buffer) * tx_ring->count; memset(tx_ring->tx_buffer_info, 0, size); /* Zero out the descriptor ring */ memset(tx_ring->desc, 0, tx_ring->size); tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; } /** * igb_clean_all_tx_rings - Free Tx Buffers for all queues * @adapter: board private structure **/ static void igb_clean_all_tx_rings(struct igb_adapter *adapter) { int i; for (i = 0; i < adapter->num_tx_queues; i++) igb_clean_tx_ring(adapter->tx_ring[i]); } /** * igb_free_rx_resources - Free Rx Resources * @rx_ring: ring to clean the resources from * * Free all receive software resources **/ void igb_free_rx_resources(struct igb_ring *rx_ring) { igb_clean_rx_ring(rx_ring); vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; /* if not set, then don't free */ if (!rx_ring->desc) return; dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; } /** * igb_free_all_rx_resources - Free Rx Resources for All Queues * @adapter: board private structure * * Free all receive software resources **/ static void igb_free_all_rx_resources(struct igb_adapter *adapter) { int i; for (i = 0; i < adapter->num_rx_queues; i++) igb_free_rx_resources(adapter->rx_ring[i]); } /** * igb_clean_rx_ring - Free Rx Buffers per Queue * @rx_ring: ring to free buffers from **/ void igb_clean_rx_ring(struct igb_ring *rx_ring) { unsigned long size; u16 i; if (!rx_ring->rx_buffer_info) return; #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT if (rx_ring->skb) dev_kfree_skb(rx_ring->skb); rx_ring->skb = NULL; #endif /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i]; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT if (buffer_info->dma) { dma_unmap_single(rx_ring->dev, buffer_info->dma, rx_ring->rx_buffer_len, DMA_FROM_DEVICE); buffer_info->dma = 0; } if (buffer_info->skb) { dev_kfree_skb(buffer_info->skb); buffer_info->skb = NULL; } #else if (!buffer_info->page) continue; dma_unmap_page(rx_ring->dev, buffer_info->dma, PAGE_SIZE, DMA_FROM_DEVICE); __free_page(buffer_info->page); buffer_info->page = NULL; #endif } size = sizeof(struct igb_rx_buffer) * rx_ring->count; memset(rx_ring->rx_buffer_info, 0, size); /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; } /** * igb_clean_all_rx_rings - Free Rx Buffers for all queues * @adapter: board private structure **/ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) { int i; for (i = 0; i < adapter->num_rx_queues; i++) igb_clean_rx_ring(adapter->rx_ring[i]); } /** * igb_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure **/ static int igb_set_mac(struct net_device *netdev, void *p) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; igb_del_mac_filter(adapter, hw->mac.addr, adapter->vfs_allocated_count); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); /* set the correct pool for the new PF MAC address in entry 0 */ return igb_add_mac_filter(adapter, hw->mac.addr, adapter->vfs_allocated_count); } /** * igb_write_mc_addr_list - write multicast addresses to MTA * @netdev: network interface device structure * * Writes multicast address list to the MTA hash table. * Returns: -ENOMEM on failure * 0 on no addresses written * X on writing X addresses to MTA **/ int igb_write_mc_addr_list(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; #ifdef NETDEV_HW_ADDR_T_MULTICAST struct netdev_hw_addr *ha; #else struct dev_mc_list *ha; #endif u8 *mta_list; int i, count; #ifdef CONFIG_IGB_VMDQ_NETDEV int vm; #endif count = netdev_mc_count(netdev); #ifdef CONFIG_IGB_VMDQ_NETDEV for (vm = 1; vm < adapter->vmdq_pools; vm++) { if (!adapter->vmdq_netdev[vm]) break; if (!netif_running(adapter->vmdq_netdev[vm])) continue; count += netdev_mc_count(adapter->vmdq_netdev[vm]); } #endif if (!count) { e1000_update_mc_addr_list(hw, NULL, 0); return 0; } mta_list = kzalloc(count * 6, GFP_ATOMIC); if (!mta_list) return -ENOMEM; /* The shared function expects a packed array of only addresses. */ i = 0; netdev_for_each_mc_addr(ha, netdev) #ifdef NETDEV_HW_ADDR_T_MULTICAST memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); #else memcpy(mta_list + (i++ * ETH_ALEN), ha->dmi_addr, ETH_ALEN); #endif #ifdef CONFIG_IGB_VMDQ_NETDEV for (vm = 1; vm < adapter->vmdq_pools; vm++) { if (!adapter->vmdq_netdev[vm]) break; if (!netif_running(adapter->vmdq_netdev[vm]) || !netdev_mc_count(adapter->vmdq_netdev[vm])) continue; netdev_for_each_mc_addr(ha, adapter->vmdq_netdev[vm]) #ifdef NETDEV_HW_ADDR_T_MULTICAST memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); #else memcpy(mta_list + (i++ * ETH_ALEN), ha->dmi_addr, ETH_ALEN); #endif } #endif e1000_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); return count; } void igb_rar_set(struct igb_adapter *adapter, u32 index) { u32 rar_low, rar_high; struct e1000_hw *hw = &adapter->hw; u8 *addr = adapter->mac_table[index].addr; /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); /* Indicate to hardware the Address is Valid. */ if (adapter->mac_table[index].state & IGB_MAC_STATE_IN_USE) rar_high |= E1000_RAH_AV; if (hw->mac.type == e1000_82575) rar_high |= E1000_RAH_POOL_1 * adapter->mac_table[index].queue; else rar_high |= E1000_RAH_POOL_1 << adapter->mac_table[index].queue; E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); E1000_WRITE_FLUSH(hw); } void igb_full_sync_mac_table(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; for (i = 0; i < hw->mac.rar_entry_count; i++) { igb_rar_set(adapter, i); } } void igb_sync_mac_table(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; for (i = 0; i < hw->mac.rar_entry_count; i++) { if (adapter->mac_table[i].state & IGB_MAC_STATE_MODIFIED) igb_rar_set(adapter, i); adapter->mac_table[i].state &= ~(IGB_MAC_STATE_MODIFIED); } } int igb_available_rars(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i, count = 0; for (i = 0; i < hw->mac.rar_entry_count; i++) { if (adapter->mac_table[i].state == 0) count++; } return count; } #ifdef HAVE_SET_RX_MODE /** * igb_write_uc_addr_list - write unicast addresses to RAR table * @netdev: network interface device structure * * Writes unicast address list to the RAR table. * Returns: -ENOMEM on failure/insufficient address space * 0 on no addresses written * X on writing X addresses to the RAR table **/ static int igb_write_uc_addr_list(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); unsigned int vfn = adapter->vfs_allocated_count; int count = 0; /* return ENOMEM indicating insufficient memory for addresses */ if (netdev_uc_count(netdev) > igb_available_rars(adapter)) return -ENOMEM; if (!netdev_uc_empty(netdev)) { #ifdef NETDEV_HW_ADDR_T_UNICAST struct netdev_hw_addr *ha; #else struct dev_mc_list *ha; #endif netdev_for_each_uc_addr(ha, netdev) { #ifdef NETDEV_HW_ADDR_T_UNICAST igb_del_mac_filter(adapter, ha->addr, vfn); igb_add_mac_filter(adapter, ha->addr, vfn); #else igb_del_mac_filter(adapter, ha->da_addr, vfn); igb_add_mac_filter(adapter, ha->da_addr, vfn); #endif count++; } } return count; } #endif /* HAVE_SET_RX_MODE */ /** * igb_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set * @netdev: network interface device structure * * The set_rx_mode entry point is called whenever the unicast or multicast * address lists or the network interface flags are updated. This routine is * responsible for configuring the hardware for proper unicast, multicast, * promiscuous mode, and all-multi behavior. **/ static void igb_set_rx_mode(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; unsigned int vfn = adapter->vfs_allocated_count; u32 rctl, vmolr = 0; int count; /* Check for Promiscuous and All Multicast modes */ rctl = E1000_READ_REG(hw, E1000_RCTL); /* clear the effected bits */ rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE); if (netdev->flags & IFF_PROMISC) { rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); /* retain VLAN HW filtering if in VT mode */ if (adapter->vfs_allocated_count || adapter->vmdq_pools) rctl |= E1000_RCTL_VFE; } else { if (netdev->flags & IFF_ALLMULTI) { rctl |= E1000_RCTL_MPE; vmolr |= E1000_VMOLR_MPME; } else { /* * Write addresses to the MTA, if the attempt fails * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ count = igb_write_mc_addr_list(netdev); if (count < 0) { rctl |= E1000_RCTL_MPE; vmolr |= E1000_VMOLR_MPME; } else if (count) { vmolr |= E1000_VMOLR_ROMPE; } } #ifdef HAVE_SET_RX_MODE /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable * unicast promiscuous mode */ count = igb_write_uc_addr_list(netdev); if (count < 0) { rctl |= E1000_RCTL_UPE; vmolr |= E1000_VMOLR_ROPE; } #endif /* HAVE_SET_RX_MODE */ rctl |= E1000_RCTL_VFE; } E1000_WRITE_REG(hw, E1000_RCTL, rctl); /* * In order to support SR-IOV and eventually VMDq it is necessary to set * the VMOLR to enable the appropriate modes. Without this workaround * we will have issues with VLAN tag stripping not being done for frames * that are only arriving because we are the default pool */ if (hw->mac.type < e1000_82576) return; vmolr |= E1000_READ_REG(hw, E1000_VMOLR(vfn)) & ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE); E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); igb_restore_vf_multicasts(adapter); } static void igb_check_wvbr(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 wvbr = 0; switch (hw->mac.type) { case e1000_82576: case e1000_i350: if (!(wvbr = E1000_READ_REG(hw, E1000_WVBR))) return; break; default: break; } adapter->wvbr |= wvbr; } #define IGB_STAGGERED_QUEUE_OFFSET 8 static void igb_spoof_check(struct igb_adapter *adapter) { int j; if (!adapter->wvbr) return; switch (adapter->hw.mac.type) { case e1000_82576: for (j = 0; j < adapter->vfs_allocated_count; j++) { if (adapter->wvbr & (1 << j) || adapter->wvbr & (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))) { DPRINTK(DRV, WARNING, "Spoof event(s) detected on VF %d\n", j); adapter->wvbr &= ~((1 << j) | (1 << (j + IGB_STAGGERED_QUEUE_OFFSET))); } } break; case e1000_i350: for (j = 0; j < adapter->vfs_allocated_count; j++) { if (adapter->wvbr & (1 << j)) { DPRINTK(DRV, WARNING, "Spoof event(s) detected on VF %d\n", j); adapter->wvbr &= ~(1 << j); } } break; default: break; } } /* Need to wait a few seconds after link up to get diagnostic information from * the phy */ static void igb_update_phy_info(unsigned long data) { struct igb_adapter *adapter = (struct igb_adapter *) data; e1000_get_phy_info(&adapter->hw); } /** * igb_has_link - check shared code for link and determine up/down * @adapter: pointer to driver private info **/ bool igb_has_link(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; bool link_active = FALSE; /* get_link_status is set on LSC (link status) interrupt or * rx sequence error interrupt. get_link_status will stay * false until the e1000_check_for_link establishes link * for copper adapters ONLY */ switch (hw->phy.media_type) { case e1000_media_type_copper: if (!hw->mac.get_link_status) return true; case e1000_media_type_internal_serdes: e1000_check_for_link(hw); link_active = !hw->mac.get_link_status; break; case e1000_media_type_unknown: default: break; } if (((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) && (hw->phy.id == I210_I_PHY_ID)) { if (!netif_carrier_ok(adapter->netdev)) { adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; } else if (!(adapter->flags & IGB_FLAG_NEED_LINK_UPDATE)) { adapter->flags |= IGB_FLAG_NEED_LINK_UPDATE; adapter->link_check_timeout = jiffies; } } return link_active; } /** * igb_watchdog - Timer Call-back * @data: pointer to adapter cast into an unsigned long **/ static void igb_watchdog(unsigned long data) { struct igb_adapter *adapter = (struct igb_adapter *)data; /* Do the rest outside of interrupt context */ schedule_work(&adapter->watchdog_task); } static void igb_watchdog_task(struct work_struct *work) { struct igb_adapter *adapter = container_of(work, struct igb_adapter, watchdog_task); struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; u32 link; int i; u32 thstat, ctrl_ext; u32 connsw; link = igb_has_link(adapter); /* Force link down if we have fiber to swap to */ if (adapter->flags & IGB_FLAG_MAS_ENABLE) { if (hw->phy.media_type == e1000_media_type_copper) { connsw = E1000_READ_REG(hw, E1000_CONNSW); if (!(connsw & E1000_CONNSW_AUTOSENSE_EN)) link = 0; } } if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; else link = FALSE; } if (link) { /* Perform a reset if the media type changed. */ if (hw->dev_spec._82575.media_changed) { hw->dev_spec._82575.media_changed = false; adapter->flags |= IGB_FLAG_MEDIA_RESET; igb_reset(adapter); } /* Cancel scheduled suspend requests. */ pm_runtime_resume(netdev->dev.parent); if (!netif_carrier_ok(netdev)) { u32 ctrl; e1000_get_speed_and_duplex(hw, &adapter->link_speed, &adapter->link_duplex); ctrl = E1000_READ_REG(hw, E1000_CTRL); /* Links status message must follow this format */ printk(KERN_INFO "igb: %s NIC Link is Up %d Mbps %s, " "Flow Control: %s\n", netdev->name, adapter->link_speed, adapter->link_duplex == FULL_DUPLEX ? "Full Duplex" : "Half Duplex", ((ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE)) ? "RX/TX": ((ctrl & E1000_CTRL_RFCE) ? "RX" : ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None"))); /* adjust timeout factor according to speed/duplex */ adapter->tx_timeout_factor = 1; switch (adapter->link_speed) { case SPEED_10: adapter->tx_timeout_factor = 14; break; case SPEED_100: /* maybe add some timeout factor ? */ break; default: break; } netif_carrier_on(netdev); netif_tx_wake_all_queues(netdev); igb_ping_all_vfs(adapter); #ifdef IFLA_VF_MAX igb_check_vf_rate_limit(adapter); #endif /* IFLA_VF_MAX */ /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); } } else { if (netif_carrier_ok(netdev)) { adapter->link_speed = 0; adapter->link_duplex = 0; /* check for thermal sensor event on i350 */ if (hw->mac.type == e1000_i350) { thstat = E1000_READ_REG(hw, E1000_THSTAT); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); if ((hw->phy.media_type == e1000_media_type_copper) && !(ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII)) { if (thstat & E1000_THSTAT_PWR_DOWN) { printk(KERN_ERR "igb: %s The " "network adapter was stopped " "because it overheated.\n", netdev->name); } if (thstat & E1000_THSTAT_LINK_THROTTLE) { printk(KERN_INFO "igb: %s The network " "adapter supported " "link speed " "was downshifted " "because it " "overheated.\n", netdev->name); } } } /* Links status message must follow this format */ printk(KERN_INFO "igb: %s NIC Link is Down\n", netdev->name); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); igb_ping_all_vfs(adapter); /* link state has changed, schedule phy info update */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); /* link is down, time to check for alternate media */ if (adapter->flags & IGB_FLAG_MAS_ENABLE) { igb_check_swap_media(adapter); if (adapter->flags & IGB_FLAG_MEDIA_RESET) { schedule_work(&adapter->reset_task); /* return immediately */ return; } } pm_schedule_suspend(netdev->dev.parent, MSEC_PER_SEC * 5); /* also check for alternate media here */ } else if (!netif_carrier_ok(netdev) && (adapter->flags & IGB_FLAG_MAS_ENABLE)) { hw->mac.ops.power_up_serdes(hw); igb_check_swap_media(adapter); if (adapter->flags & IGB_FLAG_MEDIA_RESET) { schedule_work(&adapter->reset_task); /* return immediately */ return; } } } igb_update_stats(adapter); for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; if (!netif_carrier_ok(netdev)) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. * (Do the reset outside of interrupt context). */ if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); /* return immediately since reset is imminent */ return; } } /* Force detection of hung controller every watchdog period */ set_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); } /* Cause software interrupt to ensure rx ring is cleaned */ if (adapter->msix_entries) { u32 eics = 0; for (i = 0; i < adapter->num_q_vectors; i++) eics |= adapter->q_vector[i]->eims_value; E1000_WRITE_REG(hw, E1000_EICS, eics); } else { E1000_WRITE_REG(hw, E1000_ICS, E1000_ICS_RXDMT0); } igb_spoof_check(adapter); /* Reset the timer */ if (!test_bit(__IGB_DOWN, &adapter->state)) { if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + HZ)); else mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); } } static void igb_dma_err_task(struct work_struct *work) { struct igb_adapter *adapter = container_of(work, struct igb_adapter, dma_err_task); int vf; struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; u32 hgptc; u32 ciaa, ciad; hgptc = E1000_READ_REG(hw, E1000_HGPTC); if (hgptc) /* If incrementing then no need for the check below */ goto dma_timer_reset; /* * Check to see if a bad DMA write target from an errant or * malicious VF has caused a PCIe error. If so then we can * issue a VFLR to the offending VF(s) and then resume without * requesting a full slot reset. */ for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { ciaa = (vf << 16) | 0x80000000; /* 32 bit read so align, we really want status at offset 6 */ ciaa |= PCI_COMMAND; E1000_WRITE_REG(hw, E1000_CIAA, ciaa); ciad = E1000_READ_REG(hw, E1000_CIAD); ciaa &= 0x7FFFFFFF; /* disable debug mode asap after reading data */ E1000_WRITE_REG(hw, E1000_CIAA, ciaa); /* Get the upper 16 bits which will be the PCI status reg */ ciad >>= 16; if (ciad & (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR)) { netdev_err(netdev, "VF %d suffered error\n", vf); /* Issue VFLR */ ciaa = (vf << 16) | 0x80000000; ciaa |= 0xA8; E1000_WRITE_REG(hw, E1000_CIAA, ciaa); ciad = 0x00008000; /* VFLR */ E1000_WRITE_REG(hw, E1000_CIAD, ciad); ciaa &= 0x7FFFFFFF; E1000_WRITE_REG(hw, E1000_CIAA, ciaa); } } dma_timer_reset: /* Reset the timer */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->dma_err_timer, round_jiffies(jiffies + HZ / 10)); } /** * igb_dma_err_timer - Timer Call-back * @data: pointer to adapter cast into an unsigned long **/ static void igb_dma_err_timer(unsigned long data) { struct igb_adapter *adapter = (struct igb_adapter *)data; /* Do the rest outside of interrupt context */ schedule_work(&adapter->dma_err_task); } enum latency_range { lowest_latency = 0, low_latency = 1, bulk_latency = 2, latency_invalid = 255 }; /** * igb_update_ring_itr - update the dynamic ITR value based on packet size * * Stores a new ITR value based on strictly on packet size. This * algorithm is less sophisticated than that used in igb_update_itr, * due to the difficulty of synchronizing statistics across multiple * receive rings. The divisors and thresholds used by this function * were determined based on theoretical maximum wire speed and testing * data, in order to minimize response time while increasing bulk * throughput. * This functionality is controlled by the InterruptThrottleRate module * parameter (see igb_param.c) * NOTE: This function is called only when operating in a multiqueue * receive environment. * @q_vector: pointer to q_vector **/ static void igb_update_ring_itr(struct igb_q_vector *q_vector) { int new_val = q_vector->itr_val; int avg_wire_size = 0; struct igb_adapter *adapter = q_vector->adapter; unsigned int packets; /* For non-gigabit speeds, just fix the interrupt rate at 4000 * ints/sec - ITR timer value of 120 ticks. */ switch (adapter->link_speed) { case SPEED_10: case SPEED_100: new_val = IGB_4K_ITR; goto set_itr_val; default: break; } packets = q_vector->rx.total_packets; if (packets) avg_wire_size = q_vector->rx.total_bytes / packets; packets = q_vector->tx.total_packets; if (packets) avg_wire_size = max_t(u32, avg_wire_size, q_vector->tx.total_bytes / packets); /* if avg_wire_size isn't set no work was done */ if (!avg_wire_size) goto clear_counts; /* Add 24 bytes to size to account for CRC, preamble, and gap */ avg_wire_size += 24; /* Don't starve jumbo frames */ avg_wire_size = min(avg_wire_size, 3000); /* Give a little boost to mid-size frames */ if ((avg_wire_size > 300) && (avg_wire_size < 1200)) new_val = avg_wire_size / 3; else new_val = avg_wire_size / 2; /* conservative mode (itr 3) eliminates the lowest_latency setting */ if (new_val < IGB_20K_ITR && ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) new_val = IGB_20K_ITR; set_itr_val: if (new_val != q_vector->itr_val) { q_vector->itr_val = new_val; q_vector->set_itr = 1; } clear_counts: q_vector->rx.total_bytes = 0; q_vector->rx.total_packets = 0; q_vector->tx.total_bytes = 0; q_vector->tx.total_packets = 0; } /** * igb_update_itr - update the dynamic ITR value based on statistics * Stores a new ITR value based on packets and byte * counts during the last interrupt. The advantage of per interrupt * computation is faster updates and more accurate ITR for the current * traffic pattern. Constants in this function were computed * based on theoretical maximum wire speed and thresholds were set based * on testing data as well as attempting to minimize response time * while increasing bulk throughput. * this functionality is controlled by the InterruptThrottleRate module * parameter (see igb_param.c) * NOTE: These calculations are only valid when operating in a single- * queue environment. * @q_vector: pointer to q_vector * @ring_container: ring info to update the itr for **/ static void igb_update_itr(struct igb_q_vector *q_vector, struct igb_ring_container *ring_container) { unsigned int packets = ring_container->total_packets; unsigned int bytes = ring_container->total_bytes; u8 itrval = ring_container->itr; /* no packets, exit with status unchanged */ if (packets == 0) return; switch (itrval) { case lowest_latency: /* handle TSO and jumbo frames */ if (bytes/packets > 8000) itrval = bulk_latency; else if ((packets < 5) && (bytes > 512)) itrval = low_latency; break; case low_latency: /* 50 usec aka 20000 ints/s */ if (bytes > 10000) { /* this if handles the TSO accounting */ if (bytes/packets > 8000) { itrval = bulk_latency; } else if ((packets < 10) || ((bytes/packets) > 1200)) { itrval = bulk_latency; } else if ((packets > 35)) { itrval = lowest_latency; } } else if (bytes/packets > 2000) { itrval = bulk_latency; } else if (packets <= 2 && bytes < 512) { itrval = lowest_latency; } break; case bulk_latency: /* 250 usec aka 4000 ints/s */ if (bytes > 25000) { if (packets > 35) itrval = low_latency; } else if (bytes < 1500) { itrval = low_latency; } break; } /* clear work counters since we have the values we need */ ring_container->total_bytes = 0; ring_container->total_packets = 0; /* write updated itr to ring container */ ring_container->itr = itrval; } static void igb_set_itr(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; u32 new_itr = q_vector->itr_val; u8 current_itr = 0; /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ switch (adapter->link_speed) { case SPEED_10: case SPEED_100: current_itr = 0; new_itr = IGB_4K_ITR; goto set_itr_now; default: break; } igb_update_itr(q_vector, &q_vector->tx); igb_update_itr(q_vector, &q_vector->rx); current_itr = max(q_vector->rx.itr, q_vector->tx.itr); /* conservative mode (itr 3) eliminates the lowest_latency setting */ if (current_itr == lowest_latency && ((q_vector->rx.ring && adapter->rx_itr_setting == 3) || (!q_vector->rx.ring && adapter->tx_itr_setting == 3))) current_itr = low_latency; switch (current_itr) { /* counts and packets in update_itr are dependent on these numbers */ case lowest_latency: new_itr = IGB_70K_ITR; /* 70,000 ints/sec */ break; case low_latency: new_itr = IGB_20K_ITR; /* 20,000 ints/sec */ break; case bulk_latency: new_itr = IGB_4K_ITR; /* 4,000 ints/sec */ break; default: break; } set_itr_now: if (new_itr != q_vector->itr_val) { /* this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is * increasing */ new_itr = new_itr > q_vector->itr_val ? max((new_itr * q_vector->itr_val) / (new_itr + (q_vector->itr_val >> 2)), new_itr) : new_itr; /* Don't write the value here; it resets the adapter's * internal timer, and causes us to delay far longer than * we should between interrupts. Instead, we write the ITR * value at the beginning of the next interrupt so the timing * ends up being correct. */ q_vector->itr_val = new_itr; q_vector->set_itr = 1; } } void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens, u32 type_tucmd, u32 mss_l4len_idx) { struct e1000_adv_tx_context_desc *context_desc; u16 i = tx_ring->next_to_use; context_desc = IGB_TX_CTXTDESC(tx_ring, i); i++; tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; /* set bits to identify this as an advanced context descriptor */ type_tucmd |= E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT; /* For 82575, context index must be unique per ring. */ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) mss_l4len_idx |= tx_ring->reg_idx << 4; context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); context_desc->seqnum_seed = 0; context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); } static int igb_tso(struct igb_ring *tx_ring, struct igb_tx_buffer *first, u8 *hdr_len) { #ifdef NETIF_F_TSO struct sk_buff *skb = first->skb; u32 vlan_macip_lens, type_tucmd; u32 mss_l4len_idx, l4len; if (skb->ip_summed != CHECKSUM_PARTIAL) return 0; if (!skb_is_gso(skb)) #endif /* NETIF_F_TSO */ return 0; #ifdef NETIF_F_TSO if (skb_header_cloned(skb)) { int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (err) return err; } /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP; if (first->protocol == __constant_htons(ETH_P_IP)) { struct iphdr *iph = ip_hdr(skb); iph->tot_len = 0; iph->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 0, IPPROTO_TCP, 0); type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; first->tx_flags |= IGB_TX_FLAGS_TSO | IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_IPV4; #ifdef NETIF_F_TSO6 } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0); first->tx_flags |= IGB_TX_FLAGS_TSO | IGB_TX_FLAGS_CSUM; #endif } /* compute header lengths */ l4len = tcp_hdrlen(skb); *hdr_len = skb_transport_offset(skb) + l4len; /* update gso size and bytecount with header size */ first->gso_segs = skb_shinfo(skb)->gso_segs; first->bytecount += (first->gso_segs - 1) * *hdr_len; /* MSS L4LEN IDX */ mss_l4len_idx = l4len << E1000_ADVTXD_L4LEN_SHIFT; mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT; /* VLAN MACLEN IPLEN */ vlan_macip_lens = skb_network_header_len(skb); vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); return 1; #endif /* NETIF_F_TSO */ } static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) { struct sk_buff *skb = first->skb; u32 vlan_macip_lens = 0; u32 mss_l4len_idx = 0; u32 type_tucmd = 0; if (skb->ip_summed != CHECKSUM_PARTIAL) { if (!(first->tx_flags & IGB_TX_FLAGS_VLAN)) return; } else { u8 nexthdr = 0; switch (first->protocol) { case __constant_htons(ETH_P_IP): vlan_macip_lens |= skb_network_header_len(skb); type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; nexthdr = ip_hdr(skb)->protocol; break; #ifdef NETIF_F_IPV6_CSUM case __constant_htons(ETH_P_IPV6): vlan_macip_lens |= skb_network_header_len(skb); nexthdr = ipv6_hdr(skb)->nexthdr; break; #endif default: if (unlikely(net_ratelimit())) { dev_warn(tx_ring->dev, "partial checksum but proto=%x!\n", first->protocol); } break; } switch (nexthdr) { case IPPROTO_TCP: type_tucmd |= E1000_ADVTXD_TUCMD_L4T_TCP; mss_l4len_idx = tcp_hdrlen(skb) << E1000_ADVTXD_L4LEN_SHIFT; break; #ifdef HAVE_SCTP case IPPROTO_SCTP: type_tucmd |= E1000_ADVTXD_TUCMD_L4T_SCTP; mss_l4len_idx = sizeof(struct sctphdr) << E1000_ADVTXD_L4LEN_SHIFT; break; #endif case IPPROTO_UDP: mss_l4len_idx = sizeof(struct udphdr) << E1000_ADVTXD_L4LEN_SHIFT; break; default: if (unlikely(net_ratelimit())) { dev_warn(tx_ring->dev, "partial checksum but l4 proto=%x!\n", nexthdr); } break; } /* update TX checksum flag */ first->tx_flags |= IGB_TX_FLAGS_CSUM; } vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT; vlan_macip_lens |= first->tx_flags & IGB_TX_FLAGS_VLAN_MASK; igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx); } #define IGB_SET_FLAG(_input, _flag, _result) \ ((_flag <= _result) ? \ ((u32)(_input & _flag) * (_result / _flag)) : \ ((u32)(_input & _flag) / (_flag / _result))) static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags) { /* set type for advanced descriptor with frame checksum insertion */ u32 cmd_type = E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DCMD_IFCS; /* set HW vlan bit if vlan is present */ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN, (E1000_ADVTXD_DCMD_VLE)); /* set segmentation bits for TSO */ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO, (E1000_ADVTXD_DCMD_TSE)); /* set timestamp bit if present */ cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP, (E1000_ADVTXD_MAC_TSTAMP)); return cmd_type; } static void igb_tx_olinfo_status(struct igb_ring *tx_ring, union e1000_adv_tx_desc *tx_desc, u32 tx_flags, unsigned int paylen) { u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT; /* 82575 requires a unique index per ring */ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) olinfo_status |= tx_ring->reg_idx << 4; /* insert L4 checksum */ olinfo_status |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_CSUM, (E1000_TXD_POPTS_TXSM << 8)); /* insert IPv4 checksum */ olinfo_status |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_IPV4, (E1000_TXD_POPTS_IXSM << 8)); tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); } static void igb_tx_map(struct igb_ring *tx_ring, struct igb_tx_buffer *first, const u8 hdr_len) { struct sk_buff *skb = first->skb; struct igb_tx_buffer *tx_buffer; union e1000_adv_tx_desc *tx_desc; struct skb_frag_struct *frag; dma_addr_t dma; unsigned int data_len, size; u32 tx_flags = first->tx_flags; u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); u16 i = tx_ring->next_to_use; tx_desc = IGB_TX_DESC(tx_ring, i); igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len); size = skb_headlen(skb); data_len = skb->data_len; dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); tx_buffer = first; for (frag = &skb_shinfo(skb)->frags[0];; frag++) { if (dma_mapping_error(tx_ring->dev, dma)) goto dma_error; /* record length, and DMA address */ dma_unmap_len_set(tx_buffer, len, size); dma_unmap_addr_set(tx_buffer, dma, dma); tx_desc->read.buffer_addr = cpu_to_le64(dma); while (unlikely(size > IGB_MAX_DATA_PER_TXD)) { tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD); i++; tx_desc++; if (i == tx_ring->count) { tx_desc = IGB_TX_DESC(tx_ring, 0); i = 0; } tx_desc->read.olinfo_status = 0; dma += IGB_MAX_DATA_PER_TXD; size -= IGB_MAX_DATA_PER_TXD; tx_desc->read.buffer_addr = cpu_to_le64(dma); } if (likely(!data_len)) break; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size); i++; tx_desc++; if (i == tx_ring->count) { tx_desc = IGB_TX_DESC(tx_ring, 0); i = 0; } tx_desc->read.olinfo_status = 0; size = skb_frag_size(frag); data_len -= size; dma = skb_frag_dma_map(tx_ring->dev, frag, 0, size, DMA_TO_DEVICE); tx_buffer = &tx_ring->tx_buffer_info[i]; } /* write last descriptor with RS and EOP bits */ cmd_type |= size | IGB_TXD_DCMD; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); /* set the timestamp */ first->time_stamp = jiffies; /* * Force memory writes to complete before letting h/w know there * are new descriptors to fetch. (Only applicable for weak-ordered * memory model archs, such as IA-64). * * We also need this memory barrier to make certain all of the * status bits have been updated before next_to_watch is written. */ wmb(); /* set next_to_watch value indicating a packet is present */ first->next_to_watch = tx_desc; i++; if (i == tx_ring->count) i = 0; tx_ring->next_to_use = i; writel(i, tx_ring->tail); /* we need this if more than one processor can write to our tail * at a time, it syncronizes IO on IA64/Altix systems */ mmiowb(); return; dma_error: dev_err(tx_ring->dev, "TX DMA map failed\n"); /* clear dma mappings for failed tx_buffer_info map */ for (;;) { tx_buffer = &tx_ring->tx_buffer_info[i]; igb_unmap_and_free_tx_resource(tx_ring, tx_buffer); if (tx_buffer == first) break; if (i == 0) i = tx_ring->count; i--; } tx_ring->next_to_use = i; } static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) { struct net_device *netdev = netdev_ring(tx_ring); if (netif_is_multiqueue(netdev)) netif_stop_subqueue(netdev, ring_queue_index(tx_ring)); else netif_stop_queue(netdev); /* Herbert's original patch had: * smp_mb__after_netif_stop_queue(); * but since that doesn't exist yet, just open code it. */ smp_mb(); /* We need to check again in a case another CPU has just * made room available. */ if (igb_desc_unused(tx_ring) < size) return -EBUSY; /* A reprieve! */ if (netif_is_multiqueue(netdev)) netif_wake_subqueue(netdev, ring_queue_index(tx_ring)); else netif_wake_queue(netdev); tx_ring->tx_stats.restart_queue++; return 0; } static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) { if (igb_desc_unused(tx_ring) >= size) return 0; return __igb_maybe_stop_tx(tx_ring, size); } netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb, struct igb_ring *tx_ring) { struct igb_tx_buffer *first; int tso; u32 tx_flags = 0; #if PAGE_SIZE > IGB_MAX_DATA_PER_TXD unsigned short f; #endif u16 count = TXD_USE_COUNT(skb_headlen(skb)); __be16 protocol = vlan_get_protocol(skb); u8 hdr_len = 0; /* * need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD, * + 2 desc gap to keep tail from touching head, * + 1 desc for context descriptor, * otherwise try next time */ #if PAGE_SIZE > IGB_MAX_DATA_PER_TXD for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); #else count += skb_shinfo(skb)->nr_frags; #endif if (igb_maybe_stop_tx(tx_ring, count + 3)) { /* this is a hard error */ return NETDEV_TX_BUSY; } /* record the location of the first descriptor for this packet */ first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; first->skb = skb; first->bytecount = skb->len; first->gso_segs = 1; skb_tx_timestamp(skb); #ifdef HAVE_PTP_1588_CLOCK if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); if (!adapter->ptp_tx_skb) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; tx_flags |= IGB_TX_FLAGS_TSTAMP; adapter->ptp_tx_skb = skb_get(skb); adapter->ptp_tx_start = jiffies; if (adapter->hw.mac.type == e1000_82576) schedule_work(&adapter->ptp_tx_work); } } #endif /* HAVE_PTP_1588_CLOCK */ if (vlan_tx_tag_present(skb)) { tx_flags |= IGB_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT); } /* record initial flags and protocol */ first->tx_flags = tx_flags; first->protocol = protocol; tso = igb_tso(tx_ring, first, &hdr_len); if (tso < 0) goto out_drop; else if (!tso) igb_tx_csum(tx_ring, first); igb_tx_map(tx_ring, first, hdr_len); #ifndef HAVE_TRANS_START_IN_QUEUE netdev_ring(tx_ring)->trans_start = jiffies; #endif /* Make sure there is space in the ring for the next send. */ igb_maybe_stop_tx(tx_ring, DESC_NEEDED); return NETDEV_TX_OK; out_drop: igb_unmap_and_free_tx_resource(tx_ring, first); return NETDEV_TX_OK; } #ifdef HAVE_TX_MQ static inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter, struct sk_buff *skb) { unsigned int r_idx = skb->queue_mapping; if (r_idx >= adapter->num_tx_queues) r_idx = r_idx % adapter->num_tx_queues; return adapter->tx_ring[r_idx]; } #else #define igb_tx_queue_mapping(_adapter, _skb) (_adapter)->tx_ring[0] #endif static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); if (test_bit(__IGB_DOWN, &adapter->state)) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; } if (skb->len <= 0) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; } /* * The minimum packet size with TCTL.PSP set is 17 so pad the skb * in order to meet this minimum size requirement. */ if (skb->len < 17) { if (skb_padto(skb, 17)) return NETDEV_TX_OK; skb->len = 17; } return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb)); } /** * igb_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/ static void igb_tx_timeout(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; /* Do the reset outside of interrupt context */ adapter->tx_timeout_count++; if (hw->mac.type >= e1000_82580) hw->dev_spec._82575.global_device_reset = true; schedule_work(&adapter->reset_task); E1000_WRITE_REG(hw, E1000_EICS, (adapter->eims_enable_mask & ~adapter->eims_other)); } static void igb_reset_task(struct work_struct *work) { struct igb_adapter *adapter; adapter = container_of(work, struct igb_adapter, reset_task); igb_reinit_locked(adapter); } /** * igb_get_stats - Get System Network Statistics * @netdev: network interface device structure * * Returns the address of the device statistics structure. * The statistics are updated here and also from the timer callback. **/ static struct net_device_stats *igb_get_stats(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); if (!test_bit(__IGB_RESETTING, &adapter->state)) igb_update_stats(adapter); #ifdef HAVE_NETDEV_STATS_IN_NETDEV /* only return the current stats */ return &netdev->stats; #else /* only return the current stats */ return &adapter->net_stats; #endif /* HAVE_NETDEV_STATS_IN_NETDEV */ } /** * igb_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure **/ static int igb_change_mtu(struct net_device *netdev, int new_mtu) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { dev_err(pci_dev_to_dev(pdev), "Invalid MTU setting\n"); return -EINVAL; } #define MAX_STD_JUMBO_FRAME_SIZE 9238 if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) { dev_err(pci_dev_to_dev(pdev), "MTU > 9216 not supported.\n"); return -EINVAL; } /* adjust max frame to be at least the size of a standard frame */ if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) usleep_range(1000, 2000); /* igb_down has a dependency on max_frame_size */ adapter->max_frame_size = max_frame; if (netif_running(netdev)) igb_down(adapter); dev_info(pci_dev_to_dev(pdev), "changing MTU from %d to %d\n", netdev->mtu, new_mtu); netdev->mtu = new_mtu; hw->dev_spec._82575.mtu = new_mtu; if (netif_running(netdev)) igb_up(adapter); else igb_reset(adapter); clear_bit(__IGB_RESETTING, &adapter->state); return 0; } /** * igb_update_stats - Update the board statistics counters * @adapter: board private structure **/ void igb_update_stats(struct igb_adapter *adapter) { #ifdef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats *net_stats = &adapter->netdev->stats; #else struct net_device_stats *net_stats = &adapter->net_stats; #endif /* HAVE_NETDEV_STATS_IN_NETDEV */ struct e1000_hw *hw = &adapter->hw; #ifdef HAVE_PCI_ERS struct pci_dev *pdev = adapter->pdev; #endif u32 reg, mpc; u16 phy_tmp; int i; u64 bytes, packets; #ifndef IGB_NO_LRO u32 flushed = 0, coal = 0; struct igb_q_vector *q_vector; #endif #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF /* * Prevent stats update while adapter is being reset, or if the pci * connection is down. */ if (adapter->link_speed == 0) return; #ifdef HAVE_PCI_ERS if (pci_channel_offline(pdev)) return; #endif #ifndef IGB_NO_LRO for (i = 0; i < adapter->num_q_vectors; i++) { q_vector = adapter->q_vector[i]; if (!q_vector) continue; flushed += q_vector->lrolist.stats.flushed; coal += q_vector->lrolist.stats.coal; } adapter->lro_stats.flushed = flushed; adapter->lro_stats.coal = coal; #endif bytes = 0; packets = 0; for (i = 0; i < adapter->num_rx_queues; i++) { u32 rqdpc_tmp = E1000_READ_REG(hw, E1000_RQDPC(i)) & 0x0FFF; struct igb_ring *ring = adapter->rx_ring[i]; ring->rx_stats.drops += rqdpc_tmp; net_stats->rx_fifo_errors += rqdpc_tmp; #ifdef CONFIG_IGB_VMDQ_NETDEV if (!ring->vmdq_netdev) { bytes += ring->rx_stats.bytes; packets += ring->rx_stats.packets; } #else bytes += ring->rx_stats.bytes; packets += ring->rx_stats.packets; #endif } net_stats->rx_bytes = bytes; net_stats->rx_packets = packets; bytes = 0; packets = 0; for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *ring = adapter->tx_ring[i]; #ifdef CONFIG_IGB_VMDQ_NETDEV if (!ring->vmdq_netdev) { bytes += ring->tx_stats.bytes; packets += ring->tx_stats.packets; } #else bytes += ring->tx_stats.bytes; packets += ring->tx_stats.packets; #endif } net_stats->tx_bytes = bytes; net_stats->tx_packets = packets; /* read stats registers */ adapter->stats.crcerrs += E1000_READ_REG(hw, E1000_CRCERRS); adapter->stats.gprc += E1000_READ_REG(hw, E1000_GPRC); adapter->stats.gorc += E1000_READ_REG(hw, E1000_GORCL); E1000_READ_REG(hw, E1000_GORCH); /* clear GORCL */ adapter->stats.bprc += E1000_READ_REG(hw, E1000_BPRC); adapter->stats.mprc += E1000_READ_REG(hw, E1000_MPRC); adapter->stats.roc += E1000_READ_REG(hw, E1000_ROC); adapter->stats.prc64 += E1000_READ_REG(hw, E1000_PRC64); adapter->stats.prc127 += E1000_READ_REG(hw, E1000_PRC127); adapter->stats.prc255 += E1000_READ_REG(hw, E1000_PRC255); adapter->stats.prc511 += E1000_READ_REG(hw, E1000_PRC511); adapter->stats.prc1023 += E1000_READ_REG(hw, E1000_PRC1023); adapter->stats.prc1522 += E1000_READ_REG(hw, E1000_PRC1522); adapter->stats.symerrs += E1000_READ_REG(hw, E1000_SYMERRS); adapter->stats.sec += E1000_READ_REG(hw, E1000_SEC); mpc = E1000_READ_REG(hw, E1000_MPC); adapter->stats.mpc += mpc; net_stats->rx_fifo_errors += mpc; adapter->stats.scc += E1000_READ_REG(hw, E1000_SCC); adapter->stats.ecol += E1000_READ_REG(hw, E1000_ECOL); adapter->stats.mcc += E1000_READ_REG(hw, E1000_MCC); adapter->stats.latecol += E1000_READ_REG(hw, E1000_LATECOL); adapter->stats.dc += E1000_READ_REG(hw, E1000_DC); adapter->stats.rlec += E1000_READ_REG(hw, E1000_RLEC); adapter->stats.xonrxc += E1000_READ_REG(hw, E1000_XONRXC); adapter->stats.xontxc += E1000_READ_REG(hw, E1000_XONTXC); adapter->stats.xoffrxc += E1000_READ_REG(hw, E1000_XOFFRXC); adapter->stats.xofftxc += E1000_READ_REG(hw, E1000_XOFFTXC); adapter->stats.fcruc += E1000_READ_REG(hw, E1000_FCRUC); adapter->stats.gptc += E1000_READ_REG(hw, E1000_GPTC); adapter->stats.gotc += E1000_READ_REG(hw, E1000_GOTCL); E1000_READ_REG(hw, E1000_GOTCH); /* clear GOTCL */ adapter->stats.rnbc += E1000_READ_REG(hw, E1000_RNBC); adapter->stats.ruc += E1000_READ_REG(hw, E1000_RUC); adapter->stats.rfc += E1000_READ_REG(hw, E1000_RFC); adapter->stats.rjc += E1000_READ_REG(hw, E1000_RJC); adapter->stats.tor += E1000_READ_REG(hw, E1000_TORH); adapter->stats.tot += E1000_READ_REG(hw, E1000_TOTH); adapter->stats.tpr += E1000_READ_REG(hw, E1000_TPR); adapter->stats.ptc64 += E1000_READ_REG(hw, E1000_PTC64); adapter->stats.ptc127 += E1000_READ_REG(hw, E1000_PTC127); adapter->stats.ptc255 += E1000_READ_REG(hw, E1000_PTC255); adapter->stats.ptc511 += E1000_READ_REG(hw, E1000_PTC511); adapter->stats.ptc1023 += E1000_READ_REG(hw, E1000_PTC1023); adapter->stats.ptc1522 += E1000_READ_REG(hw, E1000_PTC1522); adapter->stats.mptc += E1000_READ_REG(hw, E1000_MPTC); adapter->stats.bptc += E1000_READ_REG(hw, E1000_BPTC); adapter->stats.tpt += E1000_READ_REG(hw, E1000_TPT); adapter->stats.colc += E1000_READ_REG(hw, E1000_COLC); adapter->stats.algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC); /* read internal phy sepecific stats */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { adapter->stats.rxerrc += E1000_READ_REG(hw, E1000_RXERRC); /* this stat has invalid values on i210/i211 */ if ((hw->mac.type != e1000_i210) && (hw->mac.type != e1000_i211)) adapter->stats.tncrs += E1000_READ_REG(hw, E1000_TNCRS); } adapter->stats.tsctc += E1000_READ_REG(hw, E1000_TSCTC); adapter->stats.tsctfc += E1000_READ_REG(hw, E1000_TSCTFC); adapter->stats.iac += E1000_READ_REG(hw, E1000_IAC); adapter->stats.icrxoc += E1000_READ_REG(hw, E1000_ICRXOC); adapter->stats.icrxptc += E1000_READ_REG(hw, E1000_ICRXPTC); adapter->stats.icrxatc += E1000_READ_REG(hw, E1000_ICRXATC); adapter->stats.ictxptc += E1000_READ_REG(hw, E1000_ICTXPTC); adapter->stats.ictxatc += E1000_READ_REG(hw, E1000_ICTXATC); adapter->stats.ictxqec += E1000_READ_REG(hw, E1000_ICTXQEC); adapter->stats.ictxqmtc += E1000_READ_REG(hw, E1000_ICTXQMTC); adapter->stats.icrxdmtc += E1000_READ_REG(hw, E1000_ICRXDMTC); /* Fill out the OS statistics structure */ net_stats->multicast = adapter->stats.mprc; net_stats->collisions = adapter->stats.colc; /* Rx Errors */ /* RLEC on some newer hardware can be incorrect so build * our own version based on RUC and ROC */ net_stats->rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; net_stats->rx_length_errors = adapter->stats.ruc + adapter->stats.roc; net_stats->rx_crc_errors = adapter->stats.crcerrs; net_stats->rx_frame_errors = adapter->stats.algnerrc; net_stats->rx_missed_errors = adapter->stats.mpc; /* Tx Errors */ net_stats->tx_errors = adapter->stats.ecol + adapter->stats.latecol; net_stats->tx_aborted_errors = adapter->stats.ecol; net_stats->tx_window_errors = adapter->stats.latecol; net_stats->tx_carrier_errors = adapter->stats.tncrs; /* Tx Dropped needs to be maintained elsewhere */ /* Phy Stats */ if (hw->phy.media_type == e1000_media_type_copper) { if ((adapter->link_speed == SPEED_1000) && (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; adapter->phy_stats.idle_errors += phy_tmp; } } /* Management Stats */ adapter->stats.mgptc += E1000_READ_REG(hw, E1000_MGTPTC); adapter->stats.mgprc += E1000_READ_REG(hw, E1000_MGTPRC); if (hw->mac.type > e1000_82580) { adapter->stats.o2bgptc += E1000_READ_REG(hw, E1000_O2BGPTC); adapter->stats.o2bspc += E1000_READ_REG(hw, E1000_O2BSPC); adapter->stats.b2ospc += E1000_READ_REG(hw, E1000_B2OSPC); adapter->stats.b2ogprc += E1000_READ_REG(hw, E1000_B2OGPRC); } } static irqreturn_t igb_msix_other(int irq, void *data) { struct igb_adapter *adapter = data; struct e1000_hw *hw = &adapter->hw; u32 icr = E1000_READ_REG(hw, E1000_ICR); /* reading ICR causes bit 31 of EICR to be cleared */ if (icr & E1000_ICR_DRSTA) schedule_work(&adapter->reset_task); if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; /* The DMA Out of Sync is also indication of a spoof event * in IOV mode. Check the Wrong VM Behavior register to * see if it is really a spoof event. */ igb_check_wvbr(adapter); } /* Check for a mailbox event */ if (icr & E1000_ICR_VMMB) igb_msg_task(adapter); if (icr & E1000_ICR_LSC) { hw->mac.get_link_status = 1; /* guard against interrupt when we're going down */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); } #ifdef HAVE_PTP_1588_CLOCK if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); if (tsicr & E1000_TSICR_TXTS) { /* acknowledge the interrupt */ E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ schedule_work(&adapter->ptp_tx_work); } } #endif /* HAVE_PTP_1588_CLOCK */ /* Check for MDD event */ if (icr & E1000_ICR_MDDET) igb_process_mdd_event(adapter); E1000_WRITE_REG(hw, E1000_EIMS, adapter->eims_other); return IRQ_HANDLED; } static void igb_write_itr(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; u32 itr_val = q_vector->itr_val & 0x7FFC; if (!q_vector->set_itr) return; if (!itr_val) itr_val = 0x4; if (adapter->hw.mac.type == e1000_82575) itr_val |= itr_val << 16; else itr_val |= E1000_EITR_CNT_IGNR; writel(itr_val, q_vector->itr_register); q_vector->set_itr = 0; } static irqreturn_t igb_msix_ring(int irq, void *data) { struct igb_q_vector *q_vector = data; /* Write the ITR value calculated from the previous interrupt. */ igb_write_itr(q_vector); napi_schedule(&q_vector->napi); return IRQ_HANDLED; } #ifdef IGB_DCA static void igb_update_tx_dca(struct igb_adapter *adapter, struct igb_ring *tx_ring, int cpu) { struct e1000_hw *hw = &adapter->hw; u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); if (hw->mac.type != e1000_82575) txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT_82576; /* * We can enable relaxed ordering for reads, but not writes when * DCA is enabled. This is due to a known issue in some chipsets * which will cause the DCA tag to be cleared. */ txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN | E1000_DCA_TXCTRL_DATA_RRO_EN | E1000_DCA_TXCTRL_DESC_DCA_EN; E1000_WRITE_REG(hw, E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl); } static void igb_update_rx_dca(struct igb_adapter *adapter, struct igb_ring *rx_ring, int cpu) { struct e1000_hw *hw = &adapter->hw; u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu); if (hw->mac.type != e1000_82575) rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT_82576; /* * We can enable relaxed ordering for reads, but not writes when * DCA is enabled. This is due to a known issue in some chipsets * which will cause the DCA tag to be cleared. */ rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN | E1000_DCA_RXCTRL_DESC_DCA_EN; E1000_WRITE_REG(hw, E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl); } static void igb_update_dca(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; int cpu = get_cpu(); if (q_vector->cpu == cpu) goto out_no_update; if (q_vector->tx.ring) igb_update_tx_dca(adapter, q_vector->tx.ring, cpu); if (q_vector->rx.ring) igb_update_rx_dca(adapter, q_vector->rx.ring, cpu); q_vector->cpu = cpu; out_no_update: put_cpu(); } static void igb_setup_dca(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; if (!(adapter->flags & IGB_FLAG_DCA_ENABLED)) return; /* Always use CB2 mode, difference is masked in the CB driver. */ E1000_WRITE_REG(hw, E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); for (i = 0; i < adapter->num_q_vectors; i++) { adapter->q_vector[i]->cpu = -1; igb_update_dca(adapter->q_vector[i]); } } static int __igb_notify_dca(struct device *dev, void *data) { struct net_device *netdev = dev_get_drvdata(dev); struct igb_adapter *adapter = netdev_priv(netdev); struct pci_dev *pdev = adapter->pdev; struct e1000_hw *hw = &adapter->hw; unsigned long event = *(unsigned long *)data; switch (event) { case DCA_PROVIDER_ADD: /* if already enabled, don't do it again */ if (adapter->flags & IGB_FLAG_DCA_ENABLED) break; if (dca_add_requester(dev) == E1000_SUCCESS) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(pci_dev_to_dev(pdev), "DCA enabled\n"); igb_setup_dca(adapter); break; } /* Fall Through since DCA is disabled. */ case DCA_PROVIDER_REMOVE: if (adapter->flags & IGB_FLAG_DCA_ENABLED) { /* without this a class_device is left * hanging around in the sysfs model */ dca_remove_requester(dev); dev_info(pci_dev_to_dev(pdev), "DCA disabled\n"); adapter->flags &= ~IGB_FLAG_DCA_ENABLED; E1000_WRITE_REG(hw, E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_DISABLE); } break; } return E1000_SUCCESS; } static int igb_notify_dca(struct notifier_block *nb, unsigned long event, void *p) { int ret_val; ret_val = driver_for_each_device(&igb_driver.driver, NULL, &event, __igb_notify_dca); return ret_val ? NOTIFY_BAD : NOTIFY_DONE; } #endif /* IGB_DCA */ static int igb_vf_configure(struct igb_adapter *adapter, int vf) { unsigned char mac_addr[ETH_ALEN]; random_ether_addr(mac_addr); igb_set_vf_mac(adapter, vf, mac_addr); #ifdef IFLA_VF_MAX #ifdef HAVE_VF_SPOOFCHK_CONFIGURE /* By default spoof check is enabled for all VFs */ adapter->vf_data[vf].spoofchk_enabled = true; #endif #endif return true; } static void igb_ping_all_vfs(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 ping; int i; for (i = 0 ; i < adapter->vfs_allocated_count; i++) { ping = E1000_PF_CONTROL_MSG; if (adapter->vf_data[i].flags & IGB_VF_FLAG_CTS) ping |= E1000_VT_MSGTYPE_CTS; e1000_write_mbx(hw, &ping, 1, i); } } /** * igb_mta_set_ - Set multicast filter table address * @adapter: pointer to the adapter structure * @hash_value: determines the MTA register and bit to set * * The multicast table address is a register array of 32-bit registers. * The hash_value is used to determine what register the bit is in, the * current value is read, the new bit is OR'd in and the new value is * written back into the register. **/ void igb_mta_set(struct igb_adapter *adapter, u32 hash_value) { struct e1000_hw *hw = &adapter->hw; u32 hash_bit, hash_reg, mta; /* * The MTA is a register array of 32-bit registers. It is * treated like an array of (32*mta_reg_count) bits. We want to * set bit BitArray[hash_value]. So we figure out what register * the bit is in, read it, OR in the new bit, then write * back the new value. The (hw->mac.mta_reg_count - 1) serves as a * mask to bits 31:5 of the hash value which gives us the * register we're modifying. The hash bit within that register * is determined by the lower 5 bits of the hash value. */ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); hash_bit = hash_value & 0x1F; mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg); mta |= (1 << hash_bit); E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta); E1000_WRITE_FLUSH(hw); } static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) { struct e1000_hw *hw = &adapter->hw; u32 vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); struct vf_data_storage *vf_data = &adapter->vf_data[vf]; vf_data->flags &= ~(IGB_VF_FLAG_UNI_PROMISC | IGB_VF_FLAG_MULTI_PROMISC); vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); #ifdef IGB_ENABLE_VF_PROMISC if (*msgbuf & E1000_VF_SET_PROMISC_UNICAST) { vmolr |= E1000_VMOLR_ROPE; vf_data->flags |= IGB_VF_FLAG_UNI_PROMISC; *msgbuf &= ~E1000_VF_SET_PROMISC_UNICAST; } #endif if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) { vmolr |= E1000_VMOLR_MPME; vf_data->flags |= IGB_VF_FLAG_MULTI_PROMISC; *msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST; } else { /* * if we have hashes and we are clearing a multicast promisc * flag we need to write the hashes to the MTA as this step * was previously skipped */ if (vf_data->num_vf_mc_hashes > 30) { vmolr |= E1000_VMOLR_MPME; } else if (vf_data->num_vf_mc_hashes) { int j; vmolr |= E1000_VMOLR_ROMPE; for (j = 0; j < vf_data->num_vf_mc_hashes; j++) igb_mta_set(adapter, vf_data->vf_mc_hashes[j]); } } E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); /* there are flags left unprocessed, likely not supported */ if (*msgbuf & E1000_VT_MSGINFO_MASK) return -EINVAL; return 0; } static int igb_set_vf_multicasts(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) { int n = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; u16 *hash_list = (u16 *)&msgbuf[1]; struct vf_data_storage *vf_data = &adapter->vf_data[vf]; int i; /* salt away the number of multicast addresses assigned * to this VF for later use to restore when the PF multi cast * list changes */ vf_data->num_vf_mc_hashes = n; /* only up to 30 hash values supported */ if (n > 30) n = 30; /* store the hashes for later use */ for (i = 0; i < n; i++) vf_data->vf_mc_hashes[i] = hash_list[i]; /* Flush and reset the mta with the new values */ igb_set_rx_mode(adapter->netdev); return 0; } static void igb_restore_vf_multicasts(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct vf_data_storage *vf_data; int i, j; for (i = 0; i < adapter->vfs_allocated_count; i++) { u32 vmolr = E1000_READ_REG(hw, E1000_VMOLR(i)); vmolr &= ~(E1000_VMOLR_ROMPE | E1000_VMOLR_MPME); vf_data = &adapter->vf_data[i]; if ((vf_data->num_vf_mc_hashes > 30) || (vf_data->flags & IGB_VF_FLAG_MULTI_PROMISC)) { vmolr |= E1000_VMOLR_MPME; } else if (vf_data->num_vf_mc_hashes) { vmolr |= E1000_VMOLR_ROMPE; for (j = 0; j < vf_data->num_vf_mc_hashes; j++) igb_mta_set(adapter, vf_data->vf_mc_hashes[j]); } E1000_WRITE_REG(hw, E1000_VMOLR(i), vmolr); } } static void igb_clear_vf_vfta(struct igb_adapter *adapter, u32 vf) { struct e1000_hw *hw = &adapter->hw; u32 pool_mask, reg, vid; u16 vlan_default; int i; pool_mask = 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); /* Find the vlan filter for this id */ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { reg = E1000_READ_REG(hw, E1000_VLVF(i)); /* remove the vf from the pool */ reg &= ~pool_mask; /* if pool is empty then remove entry from vfta */ if (!(reg & E1000_VLVF_POOLSEL_MASK) && (reg & E1000_VLVF_VLANID_ENABLE)) { reg = 0; vid = reg & E1000_VLVF_VLANID_MASK; igb_vfta_set(adapter, vid, FALSE); } E1000_WRITE_REG(hw, E1000_VLVF(i), reg); } adapter->vf_data[vf].vlans_enabled = 0; vlan_default = adapter->vf_data[vf].default_vf_vlan_id; if (vlan_default) igb_vlvf_set(adapter, vlan_default, true, vf); } s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) { struct e1000_hw *hw = &adapter->hw; u32 reg, i; /* The vlvf table only exists on 82576 hardware and newer */ if (hw->mac.type < e1000_82576) return -1; /* we only need to do this if VMDq is enabled */ if (!adapter->vmdq_pools) return -1; /* Find the vlan filter for this id */ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { reg = E1000_READ_REG(hw, E1000_VLVF(i)); if ((reg & E1000_VLVF_VLANID_ENABLE) && vid == (reg & E1000_VLVF_VLANID_MASK)) break; } if (add) { if (i == E1000_VLVF_ARRAY_SIZE) { /* Did not find a matching VLAN ID entry that was * enabled. Search for a free filter entry, i.e. * one without the enable bit set */ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { reg = E1000_READ_REG(hw, E1000_VLVF(i)); if (!(reg & E1000_VLVF_VLANID_ENABLE)) break; } } if (i < E1000_VLVF_ARRAY_SIZE) { /* Found an enabled/available entry */ reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT + vf); /* if !enabled we need to set this up in vfta */ if (!(reg & E1000_VLVF_VLANID_ENABLE)) { /* add VID to filter table */ igb_vfta_set(adapter, vid, TRUE); reg |= E1000_VLVF_VLANID_ENABLE; } reg &= ~E1000_VLVF_VLANID_MASK; reg |= vid; E1000_WRITE_REG(hw, E1000_VLVF(i), reg); /* do not modify RLPML for PF devices */ if (vf >= adapter->vfs_allocated_count) return E1000_SUCCESS; if (!adapter->vf_data[vf].vlans_enabled) { u32 size; reg = E1000_READ_REG(hw, E1000_VMOLR(vf)); size = reg & E1000_VMOLR_RLPML_MASK; size += 4; reg &= ~E1000_VMOLR_RLPML_MASK; reg |= size; E1000_WRITE_REG(hw, E1000_VMOLR(vf), reg); } adapter->vf_data[vf].vlans_enabled++; } } else { if (i < E1000_VLVF_ARRAY_SIZE) { /* remove vf from the pool */ reg &= ~(1 << (E1000_VLVF_POOLSEL_SHIFT + vf)); /* if pool is empty then remove entry from vfta */ if (!(reg & E1000_VLVF_POOLSEL_MASK)) { reg = 0; igb_vfta_set(adapter, vid, FALSE); } E1000_WRITE_REG(hw, E1000_VLVF(i), reg); /* do not modify RLPML for PF devices */ if (vf >= adapter->vfs_allocated_count) return E1000_SUCCESS; adapter->vf_data[vf].vlans_enabled--; if (!adapter->vf_data[vf].vlans_enabled) { u32 size; reg = E1000_READ_REG(hw, E1000_VMOLR(vf)); size = reg & E1000_VMOLR_RLPML_MASK; size -= 4; reg &= ~E1000_VMOLR_RLPML_MASK; reg |= size; E1000_WRITE_REG(hw, E1000_VMOLR(vf), reg); } } } return E1000_SUCCESS; } #ifdef IFLA_VF_MAX static void igb_set_vmvir(struct igb_adapter *adapter, u32 vid, u32 vf) { struct e1000_hw *hw = &adapter->hw; if (vid) E1000_WRITE_REG(hw, E1000_VMVIR(vf), (vid | E1000_VMVIR_VLANA_DEFAULT)); else E1000_WRITE_REG(hw, E1000_VMVIR(vf), 0); } static int igb_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) { int err = 0; struct igb_adapter *adapter = netdev_priv(netdev); /* VLAN IDs accepted range 0-4094 */ if ((vf >= adapter->vfs_allocated_count) || (vlan > VLAN_VID_MASK-1) || (qos > 7)) return -EINVAL; if (vlan || qos) { err = igb_vlvf_set(adapter, vlan, !!vlan, vf); if (err) goto out; igb_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); igb_set_vmolr(adapter, vf, !vlan); adapter->vf_data[vf].pf_vlan = vlan; adapter->vf_data[vf].pf_qos = qos; igb_set_vf_vlan_strip(adapter, vf, true); dev_info(&adapter->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); if (test_bit(__IGB_DOWN, &adapter->state)) { dev_warn(&adapter->pdev->dev, "The VF VLAN has been set," " but the PF device is not up.\n"); dev_warn(&adapter->pdev->dev, "Bring the PF device up before" " attempting to use the VF device.\n"); } } else { if (adapter->vf_data[vf].pf_vlan) dev_info(&adapter->pdev->dev, "Clearing VLAN on VF %d\n", vf); igb_vlvf_set(adapter, adapter->vf_data[vf].pf_vlan, false, vf); igb_set_vmvir(adapter, vlan, vf); igb_set_vmolr(adapter, vf, true); igb_set_vf_vlan_strip(adapter, vf, false); adapter->vf_data[vf].pf_vlan = 0; adapter->vf_data[vf].pf_qos = 0; } out: return err; } #ifdef HAVE_VF_SPOOFCHK_CONFIGURE static int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 dtxswc, reg_offset; if (!adapter->vfs_allocated_count) return -EOPNOTSUPP; if (vf >= adapter->vfs_allocated_count) return -EINVAL; reg_offset = (hw->mac.type == e1000_82576) ? E1000_DTXSWC : E1000_TXSWC; dtxswc = E1000_READ_REG(hw, reg_offset); if (setting) dtxswc |= ((1 << vf) | (1 << (vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT))); else dtxswc &= ~((1 << vf) | (1 << (vf + E1000_DTXSWC_VLAN_SPOOF_SHIFT))); E1000_WRITE_REG(hw, reg_offset, dtxswc); adapter->vf_data[vf].spoofchk_enabled = setting; return E1000_SUCCESS; } #endif /* HAVE_VF_SPOOFCHK_CONFIGURE */ #endif /* IFLA_VF_MAX */ static int igb_find_vlvf_entry(struct igb_adapter *adapter, int vid) { struct e1000_hw *hw = &adapter->hw; int i; u32 reg; /* Find the vlan filter for this id */ for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) { reg = E1000_READ_REG(hw, E1000_VLVF(i)); if ((reg & E1000_VLVF_VLANID_ENABLE) && vid == (reg & E1000_VLVF_VLANID_MASK)) break; } if (i >= E1000_VLVF_ARRAY_SIZE) i = -1; return i; } static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) { struct e1000_hw *hw = &adapter->hw; int add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> E1000_VT_MSGINFO_SHIFT; int vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); int err = 0; if (vid) igb_set_vf_vlan_strip(adapter, vf, true); else igb_set_vf_vlan_strip(adapter, vf, false); /* If in promiscuous mode we need to make sure the PF also has * the VLAN filter set. */ if (add && (adapter->netdev->flags & IFF_PROMISC)) err = igb_vlvf_set(adapter, vid, add, adapter->vfs_allocated_count); if (err) goto out; err = igb_vlvf_set(adapter, vid, add, vf); if (err) goto out; /* Go through all the checks to see if the VLAN filter should * be wiped completely. */ if (!add && (adapter->netdev->flags & IFF_PROMISC)) { u32 vlvf, bits; int regndx = igb_find_vlvf_entry(adapter, vid); if (regndx < 0) goto out; /* See if any other pools are set for this VLAN filter * entry other than the PF. */ vlvf = bits = E1000_READ_REG(hw, E1000_VLVF(regndx)); bits &= 1 << (E1000_VLVF_POOLSEL_SHIFT + adapter->vfs_allocated_count); /* If the filter was removed then ensure PF pool bit * is cleared if the PF only added itself to the pool * because the PF is in promiscuous mode. */ if ((vlvf & VLAN_VID_MASK) == vid && #ifndef HAVE_VLAN_RX_REGISTER !test_bit(vid, adapter->active_vlans) && #endif !bits) igb_vlvf_set(adapter, vid, add, adapter->vfs_allocated_count); } out: return err; } static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) { struct e1000_hw *hw = &adapter->hw; /* clear flags except flag that the PF has set the MAC */ adapter->vf_data[vf].flags &= IGB_VF_FLAG_PF_SET_MAC; adapter->vf_data[vf].last_nack = jiffies; /* reset offloads to defaults */ igb_set_vmolr(adapter, vf, true); /* reset vlans for device */ igb_clear_vf_vfta(adapter, vf); #ifdef IFLA_VF_MAX if (adapter->vf_data[vf].pf_vlan) igb_ndo_set_vf_vlan(adapter->netdev, vf, adapter->vf_data[vf].pf_vlan, adapter->vf_data[vf].pf_qos); else igb_clear_vf_vfta(adapter, vf); #endif /* reset multicast table array for vf */ adapter->vf_data[vf].num_vf_mc_hashes = 0; /* Flush and reset the mta with the new values */ igb_set_rx_mode(adapter->netdev); /* * Reset the VFs TDWBAL and TDWBAH registers which are not * cleared by a VFLR */ E1000_WRITE_REG(hw, E1000_TDWBAH(vf), 0); E1000_WRITE_REG(hw, E1000_TDWBAL(vf), 0); if (hw->mac.type == e1000_82576) { E1000_WRITE_REG(hw, E1000_TDWBAH(IGB_MAX_VF_FUNCTIONS + vf), 0); E1000_WRITE_REG(hw, E1000_TDWBAL(IGB_MAX_VF_FUNCTIONS + vf), 0); } } static void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) { unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; /* generate a new mac address as we were hotplug removed/added */ if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) random_ether_addr(vf_mac); /* process remaining reset events */ igb_vf_reset(adapter, vf); } static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf) { struct e1000_hw *hw = &adapter->hw; unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; u32 reg, msgbuf[3]; u8 *addr = (u8 *)(&msgbuf[1]); /* process all the same items cleared in a function level reset */ igb_vf_reset(adapter, vf); /* set vf mac address */ igb_del_mac_filter(adapter, vf_mac, vf); igb_add_mac_filter(adapter, vf_mac, vf); /* enable transmit and receive for vf */ reg = E1000_READ_REG(hw, E1000_VFTE); E1000_WRITE_REG(hw, E1000_VFTE, reg | (1 << vf)); reg = E1000_READ_REG(hw, E1000_VFRE); E1000_WRITE_REG(hw, E1000_VFRE, reg | (1 << vf)); adapter->vf_data[vf].flags |= IGB_VF_FLAG_CTS; /* reply to reset with ack and vf mac address */ msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; memcpy(addr, vf_mac, 6); e1000_write_mbx(hw, msgbuf, 3, vf); } static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf) { /* * The VF MAC Address is stored in a packed array of bytes * starting at the second 32 bit word of the msg array */ unsigned char *addr = (unsigned char *)&msg[1]; int err = -1; if (is_valid_ether_addr(addr)) err = igb_set_vf_mac(adapter, vf, addr); return err; } static void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf) { struct e1000_hw *hw = &adapter->hw; struct vf_data_storage *vf_data = &adapter->vf_data[vf]; u32 msg = E1000_VT_MSGTYPE_NACK; /* if device isn't clear to send it shouldn't be reading either */ if (!(vf_data->flags & IGB_VF_FLAG_CTS) && time_after(jiffies, vf_data->last_nack + (2 * HZ))) { e1000_write_mbx(hw, &msg, 1, vf); vf_data->last_nack = jiffies; } } static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) { struct pci_dev *pdev = adapter->pdev; u32 msgbuf[E1000_VFMAILBOX_SIZE]; struct e1000_hw *hw = &adapter->hw; struct vf_data_storage *vf_data = &adapter->vf_data[vf]; s32 retval; retval = e1000_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf); if (retval) { dev_err(pci_dev_to_dev(pdev), "Error receiving message from VF\n"); return; } /* this is a message we already processed, do nothing */ if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) return; /* * until the vf completes a reset it should not be * allowed to start any configuration. */ if (msgbuf[0] == E1000_VF_RESET) { igb_vf_reset_msg(adapter, vf); return; } if (!(vf_data->flags & IGB_VF_FLAG_CTS)) { msgbuf[0] = E1000_VT_MSGTYPE_NACK; if (time_after(jiffies, vf_data->last_nack + (2 * HZ))) { e1000_write_mbx(hw, msgbuf, 1, vf); vf_data->last_nack = jiffies; } return; } switch ((msgbuf[0] & 0xFFFF)) { case E1000_VF_SET_MAC_ADDR: retval = -EINVAL; #ifndef IGB_DISABLE_VF_MAC_SET if (!(vf_data->flags & IGB_VF_FLAG_PF_SET_MAC)) retval = igb_set_vf_mac_addr(adapter, msgbuf, vf); else DPRINTK(DRV, INFO, "VF %d attempted to override administratively " "set MAC address\nReload the VF driver to " "resume operations\n", vf); #endif break; case E1000_VF_SET_PROMISC: retval = igb_set_vf_promisc(adapter, msgbuf, vf); break; case E1000_VF_SET_MULTICAST: retval = igb_set_vf_multicasts(adapter, msgbuf, vf); break; case E1000_VF_SET_LPE: retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); break; case E1000_VF_SET_VLAN: retval = -1; #ifdef IFLA_VF_MAX if (vf_data->pf_vlan) DPRINTK(DRV, INFO, "VF %d attempted to override administratively " "set VLAN tag\nReload the VF driver to " "resume operations\n", vf); else #endif retval = igb_set_vf_vlan(adapter, msgbuf, vf); break; default: dev_err(pci_dev_to_dev(pdev), "Unhandled Msg %08x\n", msgbuf[0]); retval = -E1000_ERR_MBX; break; } /* notify the VF of the results of what it sent us */ if (retval) msgbuf[0] |= E1000_VT_MSGTYPE_NACK; else msgbuf[0] |= E1000_VT_MSGTYPE_ACK; msgbuf[0] |= E1000_VT_MSGTYPE_CTS; e1000_write_mbx(hw, msgbuf, 1, vf); } static void igb_msg_task(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; u32 vf; for (vf = 0; vf < adapter->vfs_allocated_count; vf++) { /* process any reset requests */ if (!e1000_check_for_rst(hw, vf)) igb_vf_reset_event(adapter, vf); /* process any messages pending */ if (!e1000_check_for_msg(hw, vf)) igb_rcv_msg_from_vf(adapter, vf); /* process any acks */ if (!e1000_check_for_ack(hw, vf)) igb_rcv_ack_from_vf(adapter, vf); } } /** * igb_set_uta - Set unicast filter table address * @adapter: board private structure * * The unicast table address is a register array of 32-bit registers. * The table is meant to be used in a way similar to how the MTA is used * however due to certain limitations in the hardware it is necessary to * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous * enable bit to allow vlan tag stripping when promiscuous mode is enabled **/ static void igb_set_uta(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; /* The UTA table only exists on 82576 hardware and newer */ if (hw->mac.type < e1000_82576) return; /* we only need to do this if VMDq is enabled */ if (!adapter->vmdq_pools) return; for (i = 0; i < hw->mac.uta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, ~0); } /** * igb_intr_msi - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure **/ static irqreturn_t igb_intr_msi(int irq, void *data) { struct igb_adapter *adapter = data; struct igb_q_vector *q_vector = adapter->q_vector[0]; struct e1000_hw *hw = &adapter->hw; /* read ICR disables interrupts using IAM */ u32 icr = E1000_READ_REG(hw, E1000_ICR); igb_write_itr(q_vector); if (icr & E1000_ICR_DRSTA) schedule_work(&adapter->reset_task); if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; } if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { hw->mac.get_link_status = 1; if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); } #ifdef HAVE_PTP_1588_CLOCK if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); if (tsicr & E1000_TSICR_TXTS) { /* acknowledge the interrupt */ E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ schedule_work(&adapter->ptp_tx_work); } } #endif /* HAVE_PTP_1588_CLOCK */ napi_schedule(&q_vector->napi); return IRQ_HANDLED; } /** * igb_intr - Legacy Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure **/ static irqreturn_t igb_intr(int irq, void *data) { struct igb_adapter *adapter = data; struct igb_q_vector *q_vector = adapter->q_vector[0]; struct e1000_hw *hw = &adapter->hw; /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No * need for the IMC write */ u32 icr = E1000_READ_REG(hw, E1000_ICR); /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is * not set, then the adapter didn't send an interrupt */ if (!(icr & E1000_ICR_INT_ASSERTED)) return IRQ_NONE; igb_write_itr(q_vector); if (icr & E1000_ICR_DRSTA) schedule_work(&adapter->reset_task); if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; } if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { hw->mac.get_link_status = 1; /* guard against interrupt when we're going down */ if (!test_bit(__IGB_DOWN, &adapter->state)) mod_timer(&adapter->watchdog_timer, jiffies + 1); } #ifdef HAVE_PTP_1588_CLOCK if (icr & E1000_ICR_TS) { u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); if (tsicr & E1000_TSICR_TXTS) { /* acknowledge the interrupt */ E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ schedule_work(&adapter->ptp_tx_work); } } #endif /* HAVE_PTP_1588_CLOCK */ napi_schedule(&q_vector->napi); return IRQ_HANDLED; } void igb_ring_irq_enable(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; struct e1000_hw *hw = &adapter->hw; if ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) || (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) { if ((adapter->num_q_vectors == 1) && !adapter->vf_data) igb_set_itr(q_vector); else igb_update_ring_itr(q_vector); } if (!test_bit(__IGB_DOWN, &adapter->state)) { if (adapter->msix_entries) E1000_WRITE_REG(hw, E1000_EIMS, q_vector->eims_value); else igb_irq_enable(adapter); } } /** * igb_poll - NAPI Rx polling callback * @napi: napi polling structure * @budget: count of how many packets we should handle **/ static int igb_poll(struct napi_struct *napi, int budget) { struct igb_q_vector *q_vector = container_of(napi, struct igb_q_vector, napi); bool clean_complete = true; #ifdef IGB_DCA if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED) igb_update_dca(q_vector); #endif if (q_vector->tx.ring) clean_complete = igb_clean_tx_irq(q_vector); if (q_vector->rx.ring) clean_complete &= igb_clean_rx_irq(q_vector, budget); #ifndef HAVE_NETDEV_NAPI_LIST /* if netdev is disabled we need to stop polling */ if (!netif_running(q_vector->adapter->netdev)) clean_complete = true; #endif /* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget; /* If not enough Rx work done, exit the polling mode */ napi_complete(napi); igb_ring_irq_enable(q_vector); return 0; } /** * igb_clean_tx_irq - Reclaim resources after transmit completes * @q_vector: pointer to q_vector containing needed info * returns TRUE if ring is completely cleaned **/ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) { struct igb_adapter *adapter = q_vector->adapter; struct igb_ring *tx_ring = q_vector->tx.ring; struct igb_tx_buffer *tx_buffer; union e1000_adv_tx_desc *tx_desc; unsigned int total_bytes = 0, total_packets = 0; unsigned int budget = q_vector->tx.work_limit; unsigned int i = tx_ring->next_to_clean; if (test_bit(__IGB_DOWN, &adapter->state)) return true; tx_buffer = &tx_ring->tx_buffer_info[i]; tx_desc = IGB_TX_DESC(tx_ring, i); i -= tx_ring->count; do { union e1000_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; /* if next_to_watch is not set then there is no work pending */ if (!eop_desc) break; /* prevent any other reads prior to eop_desc */ read_barrier_depends(); /* if DD is not set pending work has not been completed */ if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) break; /* clear next_to_watch to prevent false hangs */ tx_buffer->next_to_watch = NULL; /* update the statistics for this packet */ total_bytes += tx_buffer->bytecount; total_packets += tx_buffer->gso_segs; /* free the skb */ dev_kfree_skb_any(tx_buffer->skb); /* unmap skb header data */ dma_unmap_single(tx_ring->dev, dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); /* clear tx_buffer data */ tx_buffer->skb = NULL; dma_unmap_len_set(tx_buffer, len, 0); /* clear last DMA location and unmap remaining buffers */ while (tx_desc != eop_desc) { tx_buffer++; tx_desc++; i++; if (unlikely(!i)) { i -= tx_ring->count; tx_buffer = tx_ring->tx_buffer_info; tx_desc = IGB_TX_DESC(tx_ring, 0); } /* unmap any remaining paged data */ if (dma_unmap_len(tx_buffer, len)) { dma_unmap_page(tx_ring->dev, dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); dma_unmap_len_set(tx_buffer, len, 0); } } /* move us one more past the eop_desc for start of next pkt */ tx_buffer++; tx_desc++; i++; if (unlikely(!i)) { i -= tx_ring->count; tx_buffer = tx_ring->tx_buffer_info; tx_desc = IGB_TX_DESC(tx_ring, 0); } /* issue prefetch for next Tx descriptor */ prefetch(tx_desc); /* update budget accounting */ budget--; } while (likely(budget)); netdev_tx_completed_queue(txring_txq(tx_ring), total_packets, total_bytes); i += tx_ring->count; tx_ring->next_to_clean = i; tx_ring->tx_stats.bytes += total_bytes; tx_ring->tx_stats.packets += total_packets; q_vector->tx.total_bytes += total_bytes; q_vector->tx.total_packets += total_packets; #ifdef DEBUG if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags) && !(adapter->disable_hw_reset && adapter->tx_hang_detected)) { #else if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { #endif struct e1000_hw *hw = &adapter->hw; /* Detect a transmit hang in hardware, this serializes the * check with the clearing of time_stamp and movement of i */ clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); if (tx_buffer->next_to_watch && time_after(jiffies, tx_buffer->time_stamp + (adapter->tx_timeout_factor * HZ)) && !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_TXOFF)) { /* detected Tx unit hang */ #ifdef DEBUG adapter->tx_hang_detected = TRUE; if (adapter->disable_hw_reset) { DPRINTK(DRV, WARNING, "Deactivating netdev watchdog timer\n"); if (del_timer(&netdev_ring(tx_ring)->watchdog_timer)) dev_put(netdev_ring(tx_ring)); #ifndef HAVE_NET_DEVICE_OPS netdev_ring(tx_ring)->tx_timeout = NULL; #endif } #endif /* DEBUG */ dev_err(tx_ring->dev, "Detected Tx Unit Hang\n" " Tx Queue <%d>\n" " TDH <%x>\n" " TDT <%x>\n" " next_to_use <%x>\n" " next_to_clean <%x>\n" "buffer_info[next_to_clean]\n" " time_stamp <%lx>\n" " next_to_watch <%p>\n" " jiffies <%lx>\n" " desc.status <%x>\n", tx_ring->queue_index, E1000_READ_REG(hw, E1000_TDH(tx_ring->reg_idx)), readl(tx_ring->tail), tx_ring->next_to_use, tx_ring->next_to_clean, tx_buffer->time_stamp, tx_buffer->next_to_watch, jiffies, tx_buffer->next_to_watch->wb.status); if (netif_is_multiqueue(netdev_ring(tx_ring))) netif_stop_subqueue(netdev_ring(tx_ring), ring_queue_index(tx_ring)); else netif_stop_queue(netdev_ring(tx_ring)); /* we are about to reset, no point in enabling stuff */ return true; } } #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) if (unlikely(total_packets && netif_carrier_ok(netdev_ring(tx_ring)) && igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. */ smp_mb(); if (netif_is_multiqueue(netdev_ring(tx_ring))) { if (__netif_subqueue_stopped(netdev_ring(tx_ring), ring_queue_index(tx_ring)) && !(test_bit(__IGB_DOWN, &adapter->state))) { netif_wake_subqueue(netdev_ring(tx_ring), ring_queue_index(tx_ring)); tx_ring->tx_stats.restart_queue++; } } else { if (netif_queue_stopped(netdev_ring(tx_ring)) && !(test_bit(__IGB_DOWN, &adapter->state))) { netif_wake_queue(netdev_ring(tx_ring)); tx_ring->tx_stats.restart_queue++; } } } return !!budget; } #ifdef HAVE_VLAN_RX_REGISTER /** * igb_receive_skb - helper function to handle rx indications * @q_vector: structure containing interrupt and ring information * @skb: packet to send up **/ static void igb_receive_skb(struct igb_q_vector *q_vector, struct sk_buff *skb) { struct vlan_group **vlgrp = netdev_priv(skb->dev); if (IGB_CB(skb)->vid) { if (*vlgrp) { vlan_gro_receive(&q_vector->napi, *vlgrp, IGB_CB(skb)->vid, skb); } else { dev_kfree_skb_any(skb); } } else { napi_gro_receive(&q_vector->napi, skb); } } #endif /* HAVE_VLAN_RX_REGISTER */ #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT /** * igb_reuse_rx_page - page flip buffer and store it back on the ring * @rx_ring: rx descriptor ring to store buffers on * @old_buff: donor buffer to have page reused * * Synchronizes page for reuse by the adapter **/ static void igb_reuse_rx_page(struct igb_ring *rx_ring, struct igb_rx_buffer *old_buff) { struct igb_rx_buffer *new_buff; u16 nta = rx_ring->next_to_alloc; new_buff = &rx_ring->rx_buffer_info[nta]; /* update, and store next to alloc */ nta++; rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; /* transfer page from old buffer to new buffer */ memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer)); /* sync the buffer for use by the device */ dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma, old_buff->page_offset, IGB_RX_BUFSZ, DMA_FROM_DEVICE); } static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer, struct page *page, unsigned int truesize) { /* avoid re-using remote pages */ if (unlikely(page_to_nid(page) != numa_node_id())) return false; #if (PAGE_SIZE < 8192) /* if we are only owner of page we can reuse it */ if (unlikely(page_count(page) != 1)) return false; /* flip page offset to other buffer */ rx_buffer->page_offset ^= IGB_RX_BUFSZ; #else /* move offset up to the next cache line */ rx_buffer->page_offset += truesize; if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ)) return false; #endif /* bump ref count on page before it is given to the stack */ get_page(page); return true; } /** * igb_add_rx_frag - Add contents of Rx buffer to sk_buff * @rx_ring: rx descriptor ring to transact packets on * @rx_buffer: buffer containing page to add * @rx_desc: descriptor containing length of buffer written by hardware * @skb: sk_buff to place the data into * * This function will add the data contained in rx_buffer->page to the skb. * This is done either through a direct copy if the data in the buffer is * less than the skb header size, otherwise it will just attach the page as * a frag to the skb. * * The function will then update the page offset if necessary and return * true if the buffer can be reused by the adapter. **/ static bool igb_add_rx_frag(struct igb_ring *rx_ring, struct igb_rx_buffer *rx_buffer, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct page *page = rx_buffer->page; unsigned int size = le16_to_cpu(rx_desc->wb.upper.length); #if (PAGE_SIZE < 8192) unsigned int truesize = IGB_RX_BUFSZ; #else unsigned int truesize = ALIGN(size, L1_CACHE_BYTES); #endif if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) { unsigned char *va = page_address(page) + rx_buffer->page_offset; #ifdef HAVE_PTP_1588_CLOCK if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); va += IGB_TS_HDR_LEN; size -= IGB_TS_HDR_LEN; } #endif /* HAVE_PTP_1588_CLOCK */ memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); /* we can reuse buffer as-is, just make sure it is local */ if (likely(page_to_nid(page) == numa_node_id())) return true; /* this page cannot be reused so discard it */ put_page(page); return false; } skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, rx_buffer->page_offset, size, truesize); return igb_can_reuse_rx_page(rx_buffer, page, truesize); } static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct igb_rx_buffer *rx_buffer; struct page *page; rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; page = rx_buffer->page; prefetchw(page); if (likely(!skb)) { void *page_addr = page_address(page) + rx_buffer->page_offset; /* prefetch first cache line of first page */ prefetch(page_addr); #if L1_CACHE_BYTES < 128 prefetch(page_addr + L1_CACHE_BYTES); #endif /* allocate a skb to store the frags */ skb = netdev_alloc_skb_ip_align(rx_ring->netdev, IGB_RX_HDR_LEN); if (unlikely(!skb)) { rx_ring->rx_stats.alloc_failed++; return NULL; } /* * we will be copying header into skb->data in * pskb_may_pull so it is in our interest to prefetch * it now to avoid a possible cache miss */ prefetchw(skb->data); } /* we are reusing so sync this buffer for CPU use */ dma_sync_single_range_for_cpu(rx_ring->dev, rx_buffer->dma, rx_buffer->page_offset, IGB_RX_BUFSZ, DMA_FROM_DEVICE); /* pull page into skb */ if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) { /* hand second half of page back to the ring */ igb_reuse_rx_page(rx_ring, rx_buffer); } else { /* we are not reusing the buffer so unmap it */ dma_unmap_page(rx_ring->dev, rx_buffer->dma, PAGE_SIZE, DMA_FROM_DEVICE); } /* clear contents of rx_buffer */ rx_buffer->page = NULL; return skb; } #endif static inline void igb_rx_checksum(struct igb_ring *ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { skb_checksum_none_assert(skb); /* Ignore Checksum bit is set */ if (igb_test_staterr(rx_desc, E1000_RXD_STAT_IXSM)) return; /* Rx checksum disabled via ethtool */ if (!(netdev_ring(ring)->features & NETIF_F_RXCSUM)) return; /* TCP/UDP checksum error bit is set */ if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) { /* * work around errata with sctp packets where the TCPE aka * L4E bit is set incorrectly on 64 byte (60 byte w/o crc) * packets, (aka let the stack check the crc32c) */ if (!((skb->len == 60) && test_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags))) ring->rx_stats.csum_err++; /* let the stack verify checksum errors */ return; } /* It must be a TCP or UDP packet with a valid checksum */ if (igb_test_staterr(rx_desc, E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) skb->ip_summed = CHECKSUM_UNNECESSARY; } #ifdef NETIF_F_RXHASH static inline void igb_rx_hash(struct igb_ring *ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { if (netdev_ring(ring)->features & NETIF_F_RXHASH) skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), PKT_HASH_TYPE_L3); } #endif #ifndef IGB_NO_LRO #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT /** * igb_merge_active_tail - merge active tail into lro skb * @tail: pointer to active tail in frag_list * * This function merges the length and data of an active tail into the * skb containing the frag_list. It resets the tail's pointer to the head, * but it leaves the heads pointer to tail intact. **/ static inline struct sk_buff *igb_merge_active_tail(struct sk_buff *tail) { struct sk_buff *head = IGB_CB(tail)->head; if (!head) return tail; head->len += tail->len; head->data_len += tail->len; head->truesize += tail->len; IGB_CB(tail)->head = NULL; return head; } /** * igb_add_active_tail - adds an active tail into the skb frag_list * @head: pointer to the start of the skb * @tail: pointer to active tail to add to frag_list * * This function adds an active tail to the end of the frag list. This tail * will still be receiving data so we cannot yet ad it's stats to the main * skb. That is done via igb_merge_active_tail. **/ static inline void igb_add_active_tail(struct sk_buff *head, struct sk_buff *tail) { struct sk_buff *old_tail = IGB_CB(head)->tail; if (old_tail) { igb_merge_active_tail(old_tail); old_tail->next = tail; } else { skb_shinfo(head)->frag_list = tail; } IGB_CB(tail)->head = head; IGB_CB(head)->tail = tail; IGB_CB(head)->append_cnt++; } /** * igb_close_active_frag_list - cleanup pointers on a frag_list skb * @head: pointer to head of an active frag list * * This function will clear the frag_tail_tracker pointer on an active * frag_list and returns true if the pointer was actually set **/ static inline bool igb_close_active_frag_list(struct sk_buff *head) { struct sk_buff *tail = IGB_CB(head)->tail; if (!tail) return false; igb_merge_active_tail(tail); IGB_CB(head)->tail = NULL; return true; } #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ /** * igb_can_lro - returns true if packet is TCP/IPV4 and LRO is enabled * @adapter: board private structure * @rx_desc: pointer to the rx descriptor * @skb: pointer to the skb to be merged * **/ static inline bool igb_can_lro(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct iphdr *iph = (struct iphdr *)skb->data; __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; /* verify hardware indicates this is IPv4/TCP */ if((!(pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_TCP)) || !(pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_IPV4)))) return false; /* .. and LRO is enabled */ if (!(netdev_ring(rx_ring)->features & NETIF_F_LRO)) return false; /* .. and we are not in promiscuous mode */ if (netdev_ring(rx_ring)->flags & IFF_PROMISC) return false; /* .. and the header is large enough for us to read IP/TCP fields */ if (!pskb_may_pull(skb, sizeof(struct igb_lrohdr))) return false; /* .. and there are no VLANs on packet */ if (skb->protocol != __constant_htons(ETH_P_IP)) return false; /* .. and we are version 4 with no options */ if (*(u8 *)iph != 0x45) return false; /* .. and the packet is not fragmented */ if (iph->frag_off & htons(IP_MF | IP_OFFSET)) return false; /* .. and that next header is TCP */ if (iph->protocol != IPPROTO_TCP) return false; return true; } static inline struct igb_lrohdr *igb_lro_hdr(struct sk_buff *skb) { return (struct igb_lrohdr *)skb->data; } /** * igb_lro_flush - Indicate packets to upper layer. * * Update IP and TCP header part of head skb if more than one * skb's chained and indicate packets to upper layer. **/ static void igb_lro_flush(struct igb_q_vector *q_vector, struct sk_buff *skb) { struct igb_lro_list *lrolist = &q_vector->lrolist; __skb_unlink(skb, &lrolist->active); if (IGB_CB(skb)->append_cnt) { struct igb_lrohdr *lroh = igb_lro_hdr(skb); #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT /* close any active lro contexts */ igb_close_active_frag_list(skb); #endif /* incorporate ip header and re-calculate checksum */ lroh->iph.tot_len = ntohs(skb->len); lroh->iph.check = 0; /* header length is 5 since we know no options exist */ lroh->iph.check = ip_fast_csum((u8 *)lroh, 5); /* clear TCP checksum to indicate we are an LRO frame */ lroh->th.check = 0; /* incorporate latest timestamp into the tcp header */ if (IGB_CB(skb)->tsecr) { lroh->ts[2] = IGB_CB(skb)->tsecr; lroh->ts[1] = htonl(IGB_CB(skb)->tsval); } #ifdef NETIF_F_GSO skb_shinfo(skb)->gso_size = IGB_CB(skb)->mss; skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; #endif } #ifdef HAVE_VLAN_RX_REGISTER igb_receive_skb(q_vector, skb); #else napi_gro_receive(&q_vector->napi, skb); #endif lrolist->stats.flushed++; } static void igb_lro_flush_all(struct igb_q_vector *q_vector) { struct igb_lro_list *lrolist = &q_vector->lrolist; struct sk_buff *skb, *tmp; skb_queue_reverse_walk_safe(&lrolist->active, skb, tmp) igb_lro_flush(q_vector, skb); } /* * igb_lro_header_ok - Main LRO function. **/ static void igb_lro_header_ok(struct sk_buff *skb) { struct igb_lrohdr *lroh = igb_lro_hdr(skb); u16 opt_bytes, data_len; #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT IGB_CB(skb)->tail = NULL; #endif IGB_CB(skb)->tsecr = 0; IGB_CB(skb)->append_cnt = 0; IGB_CB(skb)->mss = 0; /* ensure that the checksum is valid */ if (skb->ip_summed != CHECKSUM_UNNECESSARY) return; /* If we see CE codepoint in IP header, packet is not mergeable */ if (INET_ECN_is_ce(ipv4_get_dsfield(&lroh->iph))) return; /* ensure no bits set besides ack or psh */ if (lroh->th.fin || lroh->th.syn || lroh->th.rst || lroh->th.urg || lroh->th.ece || lroh->th.cwr || !lroh->th.ack) return; /* store the total packet length */ data_len = ntohs(lroh->iph.tot_len); /* remove any padding from the end of the skb */ __pskb_trim(skb, data_len); /* remove header length from data length */ data_len -= sizeof(struct igb_lrohdr); /* * check for timestamps. Since the only option we handle are timestamps, * we only have to handle the simple case of aligned timestamps */ opt_bytes = (lroh->th.doff << 2) - sizeof(struct tcphdr); if (opt_bytes != 0) { if ((opt_bytes != TCPOLEN_TSTAMP_ALIGNED) || !pskb_may_pull(skb, sizeof(struct igb_lrohdr) + TCPOLEN_TSTAMP_ALIGNED) || (lroh->ts[0] != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) || (lroh->ts[2] == 0)) { return; } IGB_CB(skb)->tsval = ntohl(lroh->ts[1]); IGB_CB(skb)->tsecr = lroh->ts[2]; data_len -= TCPOLEN_TSTAMP_ALIGNED; } /* record data_len as mss for the packet */ IGB_CB(skb)->mss = data_len; IGB_CB(skb)->next_seq = ntohl(lroh->th.seq); } #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT static void igb_merge_frags(struct sk_buff *lro_skb, struct sk_buff *new_skb) { struct skb_shared_info *sh_info; struct skb_shared_info *new_skb_info; unsigned int data_len; sh_info = skb_shinfo(lro_skb); new_skb_info = skb_shinfo(new_skb); /* copy frags into the last skb */ memcpy(sh_info->frags + sh_info->nr_frags, new_skb_info->frags, new_skb_info->nr_frags * sizeof(skb_frag_t)); /* copy size data over */ sh_info->nr_frags += new_skb_info->nr_frags; data_len = IGB_CB(new_skb)->mss; lro_skb->len += data_len; lro_skb->data_len += data_len; lro_skb->truesize += data_len; /* wipe record of data from new_skb */ new_skb_info->nr_frags = 0; new_skb->len = new_skb->data_len = 0; dev_kfree_skb_any(new_skb); } #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ /** * igb_lro_receive - if able, queue skb into lro chain * @q_vector: structure containing interrupt and ring information * @new_skb: pointer to current skb being checked * * Checks whether the skb given is eligible for LRO and if that's * fine chains it to the existing lro_skb based on flowid. If an LRO for * the flow doesn't exist create one. **/ static void igb_lro_receive(struct igb_q_vector *q_vector, struct sk_buff *new_skb) { struct sk_buff *lro_skb; struct igb_lro_list *lrolist = &q_vector->lrolist; struct igb_lrohdr *lroh = igb_lro_hdr(new_skb); __be32 saddr = lroh->iph.saddr; __be32 daddr = lroh->iph.daddr; __be32 tcp_ports = *(__be32 *)&lroh->th; u16 data_len; #ifdef HAVE_VLAN_RX_REGISTER u16 vid = IGB_CB(new_skb)->vid; #else u16 vid = new_skb->vlan_tci; #endif igb_lro_header_ok(new_skb); /* * we have a packet that might be eligible for LRO, * so see if it matches anything we might expect */ skb_queue_walk(&lrolist->active, lro_skb) { if (*(__be32 *)&igb_lro_hdr(lro_skb)->th != tcp_ports || igb_lro_hdr(lro_skb)->iph.saddr != saddr || igb_lro_hdr(lro_skb)->iph.daddr != daddr) continue; #ifdef HAVE_VLAN_RX_REGISTER if (IGB_CB(lro_skb)->vid != vid) #else if (lro_skb->vlan_tci != vid) #endif continue; /* out of order packet */ if (IGB_CB(lro_skb)->next_seq != IGB_CB(new_skb)->next_seq) { igb_lro_flush(q_vector, lro_skb); IGB_CB(new_skb)->mss = 0; break; } /* TCP timestamp options have changed */ if (!IGB_CB(lro_skb)->tsecr != !IGB_CB(new_skb)->tsecr) { igb_lro_flush(q_vector, lro_skb); break; } /* make sure timestamp values are increasing */ if (IGB_CB(lro_skb)->tsecr && IGB_CB(lro_skb)->tsval > IGB_CB(new_skb)->tsval) { igb_lro_flush(q_vector, lro_skb); IGB_CB(new_skb)->mss = 0; break; } data_len = IGB_CB(new_skb)->mss; /* Check for all of the above below * malformed header * no tcp data * resultant packet would be too large * new skb is larger than our current mss * data would remain in header * we would consume more frags then the sk_buff contains * ack sequence numbers changed * window size has changed */ if (data_len == 0 || data_len > IGB_CB(lro_skb)->mss || data_len > IGB_CB(lro_skb)->free || #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT data_len != new_skb->data_len || skb_shinfo(new_skb)->nr_frags >= (MAX_SKB_FRAGS - skb_shinfo(lro_skb)->nr_frags) || #endif igb_lro_hdr(lro_skb)->th.ack_seq != lroh->th.ack_seq || igb_lro_hdr(lro_skb)->th.window != lroh->th.window) { igb_lro_flush(q_vector, lro_skb); break; } /* Remove IP and TCP header*/ skb_pull(new_skb, new_skb->len - data_len); /* update timestamp and timestamp echo response */ IGB_CB(lro_skb)->tsval = IGB_CB(new_skb)->tsval; IGB_CB(lro_skb)->tsecr = IGB_CB(new_skb)->tsecr; /* update sequence and free space */ IGB_CB(lro_skb)->next_seq += data_len; IGB_CB(lro_skb)->free -= data_len; /* update append_cnt */ IGB_CB(lro_skb)->append_cnt++; #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT /* if header is empty pull pages into current skb */ igb_merge_frags(lro_skb, new_skb); #else /* chain this new skb in frag_list */ igb_add_active_tail(lro_skb, new_skb); #endif if ((data_len < IGB_CB(lro_skb)->mss) || lroh->th.psh || skb_shinfo(lro_skb)->nr_frags == MAX_SKB_FRAGS) { igb_lro_hdr(lro_skb)->th.psh |= lroh->th.psh; igb_lro_flush(q_vector, lro_skb); } lrolist->stats.coal++; return; } if (IGB_CB(new_skb)->mss && !lroh->th.psh) { /* if we are at capacity flush the tail */ if (skb_queue_len(&lrolist->active) >= IGB_LRO_MAX) { lro_skb = skb_peek_tail(&lrolist->active); if (lro_skb) igb_lro_flush(q_vector, lro_skb); } /* update sequence and free space */ IGB_CB(new_skb)->next_seq += IGB_CB(new_skb)->mss; IGB_CB(new_skb)->free = 65521 - new_skb->len; /* .. and insert at the front of the active list */ __skb_queue_head(&lrolist->active, new_skb); lrolist->stats.coal++; return; } /* packet not handled by any of the above, pass it to the stack */ #ifdef HAVE_VLAN_RX_REGISTER igb_receive_skb(q_vector, new_skb); #else napi_gro_receive(&q_vector->napi, new_skb); #endif } #endif /* IGB_NO_LRO */ /** * igb_process_skb_fields - Populate skb header fields from Rx descriptor * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being populated * * This function checks the ring, descriptor, and packet information in * order to populate the hash, checksum, VLAN, timestamp, protocol, and * other fields within the skb. **/ static void igb_process_skb_fields(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct net_device *dev = rx_ring->netdev; __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; #ifdef NETIF_F_RXHASH igb_rx_hash(rx_ring, rx_desc, skb); #endif igb_rx_checksum(rx_ring, rx_desc, skb); /* update packet type stats */ if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_IPV4)) rx_ring->rx_stats.ipv4_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_IPV4_EX)) rx_ring->rx_stats.ipv4e_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_IPV6)) rx_ring->rx_stats.ipv6_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_IPV6_EX)) rx_ring->rx_stats.ipv6e_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_TCP)) rx_ring->rx_stats.tcp_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_UDP)) rx_ring->rx_stats.udp_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_SCTP)) rx_ring->rx_stats.sctp_packets++; else if (pkt_info & cpu_to_le16(E1000_RXDADV_PKTTYPE_NFS)) rx_ring->rx_stats.nfs_packets++; #ifdef HAVE_PTP_1588_CLOCK igb_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); #endif /* HAVE_PTP_1588_CLOCK */ #ifdef NETIF_F_HW_VLAN_CTAG_RX if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && #else if ((dev->features & NETIF_F_HW_VLAN_RX) && #endif igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { u16 vid = 0; if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) vid = be16_to_cpu(rx_desc->wb.upper.vlan); else vid = le16_to_cpu(rx_desc->wb.upper.vlan); #ifdef HAVE_VLAN_RX_REGISTER IGB_CB(skb)->vid = vid; } else { IGB_CB(skb)->vid = 0; #else #ifdef HAVE_VLAN_PROTOCOL __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); #else __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); #endif #endif } skb_record_rx_queue(skb, rx_ring->queue_index); skb->protocol = eth_type_trans(skb, dev); } /** * igb_is_non_eop - process handling of non-EOP buffers * @rx_ring: Rx ring being processed * @rx_desc: Rx descriptor for current buffer * * This function updates next to clean. If the buffer is an EOP buffer * this function exits returning false, otherwise it will place the * sk_buff in the next buffer to be chained and return true indicating * that this is in fact a non-EOP buffer. **/ static bool igb_is_non_eop(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc) { u32 ntc = rx_ring->next_to_clean + 1; /* fetch, update, and store next to clean */ ntc = (ntc < rx_ring->count) ? ntc : 0; rx_ring->next_to_clean = ntc; prefetch(IGB_RX_DESC(rx_ring, ntc)); if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))) return false; return true; } #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT /* igb_clean_rx_irq -- * legacy */ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) { struct igb_ring *rx_ring = q_vector->rx.ring; unsigned int total_bytes = 0, total_packets = 0; u16 cleaned_count = igb_desc_unused(rx_ring); do { struct igb_rx_buffer *rx_buffer; union e1000_adv_rx_desc *rx_desc; struct sk_buff *skb; u16 ntc; /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { igb_alloc_rx_buffers(rx_ring, cleaned_count); cleaned_count = 0; } ntc = rx_ring->next_to_clean; rx_desc = IGB_RX_DESC(rx_ring, ntc); rx_buffer = &rx_ring->rx_buffer_info[ntc]; if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) break; /* * This memory barrier is needed to keep us from reading * any other fields out of the rx_desc until we know the * RXD_STAT_DD bit is set */ rmb(); skb = rx_buffer->skb; prefetch(skb->data); /* pull the header of the skb in */ __skb_put(skb, le16_to_cpu(rx_desc->wb.upper.length)); /* clear skb reference in buffer info structure */ rx_buffer->skb = NULL; cleaned_count++; BUG_ON(igb_is_non_eop(rx_ring, rx_desc)); dma_unmap_single(rx_ring->dev, rx_buffer->dma, rx_ring->rx_buffer_len, DMA_FROM_DEVICE); rx_buffer->dma = 0; if (igb_test_staterr(rx_desc, E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { dev_kfree_skb_any(skb); continue; } total_bytes += skb->len; /* populate checksum, timestamp, VLAN, and protocol */ igb_process_skb_fields(rx_ring, rx_desc, skb); #ifndef IGB_NO_LRO if (igb_can_lro(rx_ring, rx_desc, skb)) igb_lro_receive(q_vector, skb); else #endif #ifdef HAVE_VLAN_RX_REGISTER igb_receive_skb(q_vector, skb); #else napi_gro_receive(&q_vector->napi, skb); #endif #ifndef NETIF_F_GRO netdev_ring(rx_ring)->last_rx = jiffies; #endif /* update budget accounting */ total_packets++; } while (likely(total_packets < budget)); rx_ring->rx_stats.packets += total_packets; rx_ring->rx_stats.bytes += total_bytes; q_vector->rx.total_packets += total_packets; q_vector->rx.total_bytes += total_bytes; if (cleaned_count) igb_alloc_rx_buffers(rx_ring, cleaned_count); #ifndef IGB_NO_LRO igb_lro_flush_all(q_vector); #endif /* IGB_NO_LRO */ return (total_packets < budget); } #else /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ /** * igb_get_headlen - determine size of header for LRO/GRO * @data: pointer to the start of the headers * @max_len: total length of section to find headers in * * This function is meant to determine the length of headers that will * be recognized by hardware for LRO, and GRO offloads. The main * motivation of doing this is to only perform one pull for IPv4 TCP * packets so that we can do basic things like calculating the gso_size * based on the average data per packet. **/ static unsigned int igb_get_headlen(unsigned char *data, unsigned int max_len) { union { unsigned char *network; /* l2 headers */ struct ethhdr *eth; struct vlan_hdr *vlan; /* l3 headers */ struct iphdr *ipv4; struct ipv6hdr *ipv6; } hdr; __be16 protocol; u8 nexthdr = 0; /* default to not TCP */ u8 hlen; /* this should never happen, but better safe than sorry */ if (max_len < ETH_HLEN) return max_len; /* initialize network frame pointer */ hdr.network = data; /* set first protocol and move network header forward */ protocol = hdr.eth->h_proto; hdr.network += ETH_HLEN; /* handle any vlan tag if present */ if (protocol == __constant_htons(ETH_P_8021Q)) { if ((hdr.network - data) > (max_len - VLAN_HLEN)) return max_len; protocol = hdr.vlan->h_vlan_encapsulated_proto; hdr.network += VLAN_HLEN; } /* handle L3 protocols */ if (protocol == __constant_htons(ETH_P_IP)) { if ((hdr.network - data) > (max_len - sizeof(struct iphdr))) return max_len; /* access ihl as a u8 to avoid unaligned access on ia64 */ hlen = (hdr.network[0] & 0x0F) << 2; /* verify hlen meets minimum size requirements */ if (hlen < sizeof(struct iphdr)) return hdr.network - data; /* record next protocol if header is present */ if (!(hdr.ipv4->frag_off & htons(IP_OFFSET))) nexthdr = hdr.ipv4->protocol; #ifdef NETIF_F_TSO6 } else if (protocol == __constant_htons(ETH_P_IPV6)) { if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) return max_len; /* record next protocol */ nexthdr = hdr.ipv6->nexthdr; hlen = sizeof(struct ipv6hdr); #endif /* NETIF_F_TSO6 */ } else { return hdr.network - data; } /* relocate pointer to start of L4 header */ hdr.network += hlen; /* finally sort out TCP */ if (nexthdr == IPPROTO_TCP) { if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) return max_len; /* access doff as a u8 to avoid unaligned access on ia64 */ hlen = (hdr.network[12] & 0xF0) >> 2; /* verify hlen meets minimum size requirements */ if (hlen < sizeof(struct tcphdr)) return hdr.network - data; hdr.network += hlen; } else if (nexthdr == IPPROTO_UDP) { if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) return max_len; hdr.network += sizeof(struct udphdr); } /* * If everything has gone correctly hdr.network should be the * data section of the packet and will be the end of the header. * If not then it probably represents the end of the last recognized * header. */ if ((hdr.network - data) < max_len) return hdr.network - data; else return max_len; } /** * igb_pull_tail - igb specific version of skb_pull_tail * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being adjusted * * This function is an igb specific version of __pskb_pull_tail. The * main difference between this version and the original function is that * this function can make several assumptions about the state of things * that allow for significant optimizations versus the standard function. * As a result we can do things like drop a frag and maintain an accurate * truesize for the skb. */ static void igb_pull_tail(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; unsigned char *va; unsigned int pull_len; /* * it is valid to use page_address instead of kmap since we are * working with pages allocated out of the lomem pool per * alloc_page(GFP_ATOMIC) */ va = skb_frag_address(frag); #ifdef HAVE_PTP_1588_CLOCK if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { /* retrieve timestamp from buffer */ igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb); /* update pointers to remove timestamp header */ skb_frag_size_sub(frag, IGB_TS_HDR_LEN); frag->page_offset += IGB_TS_HDR_LEN; skb->data_len -= IGB_TS_HDR_LEN; skb->len -= IGB_TS_HDR_LEN; /* move va to start of packet data */ va += IGB_TS_HDR_LEN; } #endif /* HAVE_PTP_1588_CLOCK */ /* * we need the header to contain the greater of either ETH_HLEN or * 60 bytes if the skb->len is less than 60 for skb_pad. */ pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN); /* align pull length to size of long to optimize memcpy performance */ skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); /* update all of the pointers */ skb_frag_size_sub(frag, pull_len); frag->page_offset += pull_len; skb->data_len -= pull_len; skb->tail += pull_len; } /** * igb_cleanup_headers - Correct corrupted or empty headers * @rx_ring: rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being fixed * * Address the case where we are pulling data in on pages only * and as such no data is present in the skb header. * * In addition if skb is not at least 60 bytes we need to pad it so that * it is large enough to qualify as a valid Ethernet frame. * * Returns true if an error was encountered and skb was freed. **/ static bool igb_cleanup_headers(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { if (unlikely((igb_test_staterr(rx_desc, E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { struct net_device *netdev = rx_ring->netdev; if (!(netdev->features & NETIF_F_RXALL)) { dev_kfree_skb_any(skb); return true; } } /* place header in linear portion of buffer */ if (skb_is_nonlinear(skb)) igb_pull_tail(rx_ring, rx_desc, skb); /* if skb_pad returns an error the skb was freed */ if (unlikely(skb->len < 60)) { int pad_len = 60 - skb->len; if (skb_pad(skb, pad_len)) return true; __skb_put(skb, pad_len); } return false; } /* igb_clean_rx_irq -- * packet split */ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) { struct igb_ring *rx_ring = q_vector->rx.ring; struct sk_buff *skb = rx_ring->skb; unsigned int total_bytes = 0, total_packets = 0; u16 cleaned_count = igb_desc_unused(rx_ring); do { union e1000_adv_rx_desc *rx_desc; /* return some buffers to hardware, one at a time is too slow */ if (cleaned_count >= IGB_RX_BUFFER_WRITE) { igb_alloc_rx_buffers(rx_ring, cleaned_count); cleaned_count = 0; } rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean); if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) break; /* * This memory barrier is needed to keep us from reading * any other fields out of the rx_desc until we know the * RXD_STAT_DD bit is set */ rmb(); /* retrieve a buffer from the ring */ skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb); /* exit if we failed to retrieve a buffer */ if (!skb) break; cleaned_count++; /* fetch next buffer in frame if non-eop */ if (igb_is_non_eop(rx_ring, rx_desc)) continue; /* verify the packet layout is correct */ if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { skb = NULL; continue; } /* probably a little skewed due to removing CRC */ total_bytes += skb->len; /* populate checksum, timestamp, VLAN, and protocol */ igb_process_skb_fields(rx_ring, rx_desc, skb); #ifndef IGB_NO_LRO if (igb_can_lro(rx_ring, rx_desc, skb)) igb_lro_receive(q_vector, skb); else #endif #ifdef HAVE_VLAN_RX_REGISTER igb_receive_skb(q_vector, skb); #else napi_gro_receive(&q_vector->napi, skb); #endif #ifndef NETIF_F_GRO netdev_ring(rx_ring)->last_rx = jiffies; #endif /* reset skb pointer */ skb = NULL; /* update budget accounting */ total_packets++; } while (likely(total_packets < budget)); /* place incomplete frames back on ring for completion */ rx_ring->skb = skb; rx_ring->rx_stats.packets += total_packets; rx_ring->rx_stats.bytes += total_bytes; q_vector->rx.total_packets += total_packets; q_vector->rx.total_bytes += total_bytes; if (cleaned_count) igb_alloc_rx_buffers(rx_ring, cleaned_count); #ifndef IGB_NO_LRO igb_lro_flush_all(q_vector); #endif /* IGB_NO_LRO */ return (total_packets < budget); } #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring, struct igb_rx_buffer *bi) { struct sk_buff *skb = bi->skb; dma_addr_t dma = bi->dma; if (dma) return true; if (likely(!skb)) { skb = netdev_alloc_skb_ip_align(netdev_ring(rx_ring), rx_ring->rx_buffer_len); bi->skb = skb; if (!skb) { rx_ring->rx_stats.alloc_failed++; return false; } /* initialize skb for ring */ skb_record_rx_queue(skb, ring_queue_index(rx_ring)); } dma = dma_map_single(rx_ring->dev, skb->data, rx_ring->rx_buffer_len, DMA_FROM_DEVICE); /* if mapping failed free memory back to system since * there isn't much point in holding memory we can't use */ if (dma_mapping_error(rx_ring->dev, dma)) { dev_kfree_skb_any(skb); bi->skb = NULL; rx_ring->rx_stats.alloc_failed++; return false; } bi->dma = dma; return true; } #else /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, struct igb_rx_buffer *bi) { struct page *page = bi->page; dma_addr_t dma; /* since we are recycling buffers we should seldom need to alloc */ if (likely(page)) return true; /* alloc new page for storage */ page = alloc_page(GFP_ATOMIC | __GFP_COLD); if (unlikely(!page)) { rx_ring->rx_stats.alloc_failed++; return false; } /* map page for use */ dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); /* * if mapping failed free memory back to system since * there isn't much point in holding memory we can't use */ if (dma_mapping_error(rx_ring->dev, dma)) { __free_page(page); rx_ring->rx_stats.alloc_failed++; return false; } bi->dma = dma; bi->page = page; bi->page_offset = 0; return true; } #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ /** * igb_alloc_rx_buffers - Replace used receive buffers; packet split * @adapter: address of board private structure **/ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count) { union e1000_adv_rx_desc *rx_desc; struct igb_rx_buffer *bi; u16 i = rx_ring->next_to_use; /* nothing to do */ if (!cleaned_count) return; rx_desc = IGB_RX_DESC(rx_ring, i); bi = &rx_ring->rx_buffer_info[i]; i -= rx_ring->count; do { #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT if (!igb_alloc_mapped_skb(rx_ring, bi)) #else if (!igb_alloc_mapped_page(rx_ring, bi)) #endif /* CONFIG_IGB_DISABLE_PACKET_SPLIT */ break; /* * Refresh the desc even if buffer_addrs didn't change * because each write-back erases this info. */ #ifdef CONFIG_IGB_DISABLE_PACKET_SPLIT rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); #else rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); #endif rx_desc++; bi++; i++; if (unlikely(!i)) { rx_desc = IGB_RX_DESC(rx_ring, 0); bi = rx_ring->rx_buffer_info; i -= rx_ring->count; } /* clear the hdr_addr for the next_to_use descriptor */ rx_desc->read.hdr_addr = 0; cleaned_count--; } while (cleaned_count); i += rx_ring->count; if (rx_ring->next_to_use != i) { /* record the next descriptor to use */ rx_ring->next_to_use = i; #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT /* update next to alloc since we have filled the ring */ rx_ring->next_to_alloc = i; #endif /* * Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, * such as IA-64). */ wmb(); writel(i, rx_ring->tail); } } #ifdef SIOCGMIIPHY /** * igb_mii_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct igb_adapter *adapter = netdev_priv(netdev); struct mii_ioctl_data *data = if_mii(ifr); if (adapter->hw.phy.media_type != e1000_media_type_copper) return -EOPNOTSUPP; switch (cmd) { case SIOCGMIIPHY: data->phy_id = adapter->hw.phy.addr; break; case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, &data->val_out)) return -EIO; break; case SIOCSMIIREG: default: return -EOPNOTSUPP; } return E1000_SUCCESS; } #endif /** * igb_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { #ifdef SIOCGMIIPHY case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: return igb_mii_ioctl(netdev, ifr, cmd); #endif #ifdef HAVE_PTP_1588_CLOCK case SIOCSHWTSTAMP: return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd); #endif /* HAVE_PTP_1588_CLOCK */ #ifdef ETHTOOL_OPS_COMPAT case SIOCETHTOOL: return ethtool_ioctl(ifr); #endif default: return -EOPNOTSUPP; } } s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { struct igb_adapter *adapter = hw->back; u16 cap_offset; cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); if (!cap_offset) return -E1000_ERR_CONFIG; pci_read_config_word(adapter->pdev, cap_offset + reg, value); return E1000_SUCCESS; } s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value) { struct igb_adapter *adapter = hw->back; u16 cap_offset; cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); if (!cap_offset) return -E1000_ERR_CONFIG; pci_write_config_word(adapter->pdev, cap_offset + reg, *value); return E1000_SUCCESS; } #ifdef HAVE_VLAN_RX_REGISTER static void igb_vlan_mode(struct net_device *netdev, struct vlan_group *vlgrp) #else void igb_vlan_mode(struct net_device *netdev, u32 features) #endif { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 ctrl, rctl; int i; #ifdef HAVE_VLAN_RX_REGISTER bool enable = !!vlgrp; igb_irq_disable(adapter); adapter->vlgrp = vlgrp; if (!test_bit(__IGB_DOWN, &adapter->state)) igb_irq_enable(adapter); #else #ifdef NETIF_F_HW_VLAN_CTAG_RX bool enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX); #else bool enable = !!(features & NETIF_F_HW_VLAN_RX); #endif #endif if (enable) { /* enable VLAN tag insert/strip */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl |= E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Disable CFI check */ rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~E1000_RCTL_CFIEN; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } else { /* disable VLAN tag insert/strip */ ctrl = E1000_READ_REG(hw, E1000_CTRL); ctrl &= ~E1000_CTRL_VME; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); } #ifndef CONFIG_IGB_VMDQ_NETDEV for (i = 0; i < adapter->vmdq_pools; i++) { igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count + i, enable); } #else igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count, enable); for (i = 1; i < adapter->vmdq_pools; i++) { #ifdef HAVE_VLAN_RX_REGISTER struct igb_vmdq_adapter *vadapter; vadapter = netdev_priv(adapter->vmdq_netdev[i-1]); enable = !!vadapter->vlgrp; #else struct net_device *vnetdev; vnetdev = adapter->vmdq_netdev[i-1]; #ifdef NETIF_F_HW_VLAN_CTAG_RX enable = !!(vnetdev->features & NETIF_F_HW_VLAN_CTAG_RX); #else enable = !!(vnetdev->features & NETIF_F_HW_VLAN_RX); #endif #endif igb_set_vf_vlan_strip(adapter, adapter->vfs_allocated_count + i, enable); } #endif igb_rlpml_set(adapter); } #ifdef HAVE_VLAN_PROTOCOL static int igb_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) #elif defined HAVE_INT_NDO_VLAN_RX_ADD_VID #ifdef NETIF_F_HW_VLAN_CTAG_RX static int igb_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) #else static int igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) #endif #else static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) #endif { struct igb_adapter *adapter = netdev_priv(netdev); int pf_id = adapter->vfs_allocated_count; /* attempt to add filter to vlvf array */ igb_vlvf_set(adapter, vid, TRUE, pf_id); /* add the filter since PF can receive vlans w/o entry in vlvf */ igb_vfta_set(adapter, vid, TRUE); #ifndef HAVE_NETDEV_VLAN_FEATURES /* Copy feature flags from netdev to the vlan netdev for this vid. * This allows things like TSO to bubble down to our vlan device. * There is no need to update netdev for vlan 0 (DCB), since it * wouldn't has v_netdev. */ if (adapter->vlgrp) { struct vlan_group *vlgrp = adapter->vlgrp; struct net_device *v_netdev = vlan_group_get_device(vlgrp, vid); if (v_netdev) { v_netdev->features |= netdev->features; vlan_group_set_device(vlgrp, vid, v_netdev); } } #endif #ifndef HAVE_VLAN_RX_REGISTER set_bit(vid, adapter->active_vlans); #endif #ifdef HAVE_INT_NDO_VLAN_RX_ADD_VID return 0; #endif } #ifdef HAVE_VLAN_PROTOCOL static int igb_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) #elif defined HAVE_INT_NDO_VLAN_RX_ADD_VID #ifdef NETIF_F_HW_VLAN_CTAG_RX static int igb_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) #else static int igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) #endif #else static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) #endif { struct igb_adapter *adapter = netdev_priv(netdev); int pf_id = adapter->vfs_allocated_count; s32 err; #ifdef HAVE_VLAN_RX_REGISTER igb_irq_disable(adapter); vlan_group_set_device(adapter->vlgrp, vid, NULL); if (!test_bit(__IGB_DOWN, &adapter->state)) igb_irq_enable(adapter); #endif /* HAVE_VLAN_RX_REGISTER */ /* remove vlan from VLVF table array */ err = igb_vlvf_set(adapter, vid, FALSE, pf_id); /* if vid was not present in VLVF just remove it from table */ if (err) igb_vfta_set(adapter, vid, FALSE); #ifndef HAVE_VLAN_RX_REGISTER clear_bit(vid, adapter->active_vlans); #endif #ifdef HAVE_INT_NDO_VLAN_RX_ADD_VID return 0; #endif } static void igb_restore_vlan(struct igb_adapter *adapter) { #ifdef HAVE_VLAN_RX_REGISTER igb_vlan_mode(adapter->netdev, adapter->vlgrp); if (adapter->vlgrp) { u16 vid; for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; #ifdef NETIF_F_HW_VLAN_CTAG_RX igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); #else igb_vlan_rx_add_vid(adapter->netdev, vid); #endif } } #else u16 vid; igb_vlan_mode(adapter->netdev, adapter->netdev->features); for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) #ifdef NETIF_F_HW_VLAN_CTAG_RX igb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); #else igb_vlan_rx_add_vid(adapter->netdev, vid); #endif #endif } int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx) { struct pci_dev *pdev = adapter->pdev; struct e1000_mac_info *mac = &adapter->hw.mac; mac->autoneg = 0; /* SerDes device's does not support 10Mbps Full/duplex * and 100Mbps Half duplex */ if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) { switch (spddplx) { case SPEED_10 + DUPLEX_HALF: case SPEED_10 + DUPLEX_FULL: case SPEED_100 + DUPLEX_HALF: dev_err(pci_dev_to_dev(pdev), "Unsupported Speed/Duplex configuration\n"); return -EINVAL; default: break; } } switch (spddplx) { case SPEED_10 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_10_HALF; break; case SPEED_10 + DUPLEX_FULL: mac->forced_speed_duplex = ADVERTISE_10_FULL; break; case SPEED_100 + DUPLEX_HALF: mac->forced_speed_duplex = ADVERTISE_100_HALF; break; case SPEED_100 + DUPLEX_FULL: mac->forced_speed_duplex = ADVERTISE_100_FULL; break; case SPEED_1000 + DUPLEX_FULL: mac->autoneg = 1; adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: dev_err(pci_dev_to_dev(pdev), "Unsupported Speed/Duplex configuration\n"); return -EINVAL; } /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ adapter->hw.phy.mdix = AUTO_ALL_MODES; return 0; } static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, bool runtime) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 ctrl, rctl, status; u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; #ifdef CONFIG_PM int retval = 0; #endif netif_device_detach(netdev); status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) wufc &= ~E1000_WUFC_LNKC; if (netif_running(netdev)) __igb_close(netdev, true); igb_clear_interrupt_scheme(adapter); #ifdef CONFIG_PM retval = pci_save_state(pdev); if (retval) return retval; #endif if (wufc) { igb_setup_rctl(adapter); igb_set_rx_mode(netdev); /* turn on all-multi mode if wake on multicast is enabled */ if (wufc & E1000_WUFC_MC) { rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_MPE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } ctrl = E1000_READ_REG(hw, E1000_CTRL); /* phy power management enable */ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 ctrl |= E1000_CTRL_ADVD3WUC; E1000_WRITE_REG(hw, E1000_CTRL, ctrl); /* Allow time for pending master requests to run */ e1000_disable_pcie_master(hw); E1000_WRITE_REG(hw, E1000_WUC, E1000_WUC_PME_EN); E1000_WRITE_REG(hw, E1000_WUFC, wufc); } else { E1000_WRITE_REG(hw, E1000_WUC, 0); E1000_WRITE_REG(hw, E1000_WUFC, 0); } *enable_wake = wufc || adapter->en_mng_pt; if (!*enable_wake) igb_power_down_link(adapter); else igb_power_up_link(adapter); /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ igb_release_hw_control(adapter); pci_disable_device(pdev); return 0; } #ifdef CONFIG_PM #ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_suspend(struct device *dev) #else static int igb_suspend(struct pci_dev *pdev, pm_message_t state) #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ { #ifdef HAVE_SYSTEM_SLEEP_PM_OPS struct pci_dev *pdev = to_pci_dev(dev); #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ int retval; bool wake; retval = __igb_shutdown(pdev, &wake, 0); if (retval) return retval; if (wake) { pci_prepare_to_sleep(pdev); } else { pci_wake_from_d3(pdev, false); pci_set_power_state(pdev, PCI_D3hot); } return 0; } #ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_resume(struct device *dev) #else static int igb_resume(struct pci_dev *pdev) #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ { #ifdef HAVE_SYSTEM_SLEEP_PM_OPS struct pci_dev *pdev = to_pci_dev(dev); #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; u32 err; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_save_state(pdev); err = pci_enable_device_mem(pdev); if (err) { dev_err(pci_dev_to_dev(pdev), "igb: Cannot enable PCI device from suspend\n"); return err; } pci_set_master(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); if (igb_init_interrupt_scheme(adapter, true)) { dev_err(pci_dev_to_dev(pdev), "Unable to allocate memory for queues\n"); return -ENOMEM; } igb_reset(adapter); /* let the f/w know that the h/w is now under the control of the * driver. */ igb_get_hw_control(adapter); E1000_WRITE_REG(hw, E1000_WUS, ~0); if (netdev->flags & IFF_UP) { rtnl_lock(); err = __igb_open(netdev, true); rtnl_unlock(); if (err) return err; } netif_device_attach(netdev); return 0; } #ifdef CONFIG_PM_RUNTIME #ifdef HAVE_SYSTEM_SLEEP_PM_OPS static int igb_runtime_idle(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); if (!igb_has_link(adapter)) pm_schedule_suspend(dev, MSEC_PER_SEC * 5); return -EBUSY; } static int igb_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); int retval; bool wake; retval = __igb_shutdown(pdev, &wake, 1); if (retval) return retval; if (wake) { pci_prepare_to_sleep(pdev); } else { pci_wake_from_d3(pdev, false); pci_set_power_state(pdev, PCI_D3hot); } return 0; } static int igb_runtime_resume(struct device *dev) { return igb_resume(dev); } #endif /* HAVE_SYSTEM_SLEEP_PM_OPS */ #endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM */ #ifdef USE_REBOOT_NOTIFIER /* only want to do this for 2.4 kernels? */ static int igb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) { struct pci_dev *pdev = NULL; bool wake; switch (event) { case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { if (pci_dev_driver(pdev) == &igb_driver) { __igb_shutdown(pdev, &wake, 0); if (event == SYS_POWER_OFF) { pci_wake_from_d3(pdev, wake); pci_set_power_state(pdev, PCI_D3hot); } } } } return NOTIFY_DONE; } #else static void igb_shutdown(struct pci_dev *pdev) { bool wake = false; __igb_shutdown(pdev, &wake, 0); if (system_state == SYSTEM_POWER_OFF) { pci_wake_from_d3(pdev, wake); pci_set_power_state(pdev, PCI_D3hot); } } #endif /* USE_REBOOT_NOTIFIER */ #ifdef CONFIG_NET_POLL_CONTROLLER /* * Polling 'interrupt' - used by things like netconsole to send skbs * without having to re-enable interrupts. It's not called while * the interrupt routine is executing. */ static void igb_netpoll(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct igb_q_vector *q_vector; int i; for (i = 0; i < adapter->num_q_vectors; i++) { q_vector = adapter->q_vector[i]; if (adapter->msix_entries) E1000_WRITE_REG(hw, E1000_EIMC, q_vector->eims_value); else igb_irq_disable(adapter); napi_schedule(&q_vector->napi); } } #endif /* CONFIG_NET_POLL_CONTROLLER */ #ifdef HAVE_PCI_ERS #define E1000_DEV_ID_82576_VF 0x10CA /** * igb_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device * @state: The current pci connection state * * This function is called after a PCI bus error affecting * this device has been detected. */ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); #ifdef CONFIG_PCI_IOV__UNUSED struct pci_dev *bdev, *vfdev; u32 dw0, dw1, dw2, dw3; int vf, pos; u16 req_id, pf_func; if (!(adapter->flags & IGB_FLAG_DETECT_BAD_DMA)) goto skip_bad_vf_detection; bdev = pdev->bus->self; while (bdev && (pci_pcie_type(bdev) != PCI_EXP_TYPE_ROOT_PORT)) bdev = bdev->bus->self; if (!bdev) goto skip_bad_vf_detection; pos = pci_find_ext_capability(bdev, PCI_EXT_CAP_ID_ERR); if (!pos) goto skip_bad_vf_detection; pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG, &dw0); pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 4, &dw1); pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 8, &dw2); pci_read_config_dword(bdev, pos + PCI_ERR_HEADER_LOG + 12, &dw3); req_id = dw1 >> 16; /* On the 82576 if bit 7 of the requestor ID is set then it's a VF */ if (!(req_id & 0x0080)) goto skip_bad_vf_detection; pf_func = req_id & 0x01; if ((pf_func & 1) == (pdev->devfn & 1)) { vf = (req_id & 0x7F) >> 1; dev_err(pci_dev_to_dev(pdev), "VF %d has caused a PCIe error\n", vf); dev_err(pci_dev_to_dev(pdev), "TLP: dw0: %8.8x\tdw1: %8.8x\tdw2: " "%8.8x\tdw3: %8.8x\n", dw0, dw1, dw2, dw3); /* Find the pci device of the offending VF */ vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF, NULL); while (vfdev) { if (vfdev->devfn == (req_id & 0xFF)) break; vfdev = pci_get_device(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF, vfdev); } /* * There's a slim chance the VF could have been hot plugged, * so if it is no longer present we don't need to issue the * VFLR. Just clean up the AER in that case. */ if (vfdev) { dev_err(pci_dev_to_dev(pdev), "Issuing VFLR to VF %d\n", vf); pci_write_config_dword(vfdev, 0xA8, 0x00008000); } pci_cleanup_aer_uncorrect_error_status(pdev); } /* * Even though the error may have occurred on the other port * we still need to increment the vf error reference count for * both ports because the I/O resume function will be called * for both of them. */ adapter->vferr_refcount++; return PCI_ERS_RESULT_RECOVERED; skip_bad_vf_detection: #endif /* CONFIG_PCI_IOV */ netif_device_detach(netdev); if (state == pci_channel_io_perm_failure) return PCI_ERS_RESULT_DISCONNECT; if (netif_running(netdev)) igb_down(adapter); pci_disable_device(pdev); /* Request a slot slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } /** * igb_io_slot_reset - called after the pci bus has been reset. * @pdev: Pointer to PCI device * * Restart the card from scratch, as if from a cold-boot. Implementation * resembles the first-half of the igb_resume routine. */ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pci_ers_result_t result; if (pci_enable_device_mem(pdev)) { dev_err(pci_dev_to_dev(pdev), "Cannot re-enable PCI device after reset.\n"); result = PCI_ERS_RESULT_DISCONNECT; } else { pci_set_master(pdev); pci_restore_state(pdev); pci_save_state(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); schedule_work(&adapter->reset_task); E1000_WRITE_REG(hw, E1000_WUS, ~0); result = PCI_ERS_RESULT_RECOVERED; } pci_cleanup_aer_uncorrect_error_status(pdev); return result; } /** * igb_io_resume - called when traffic can start flowing again. * @pdev: Pointer to PCI device * * This callback is called when the error recovery driver tells us that * its OK to resume normal operation. Implementation resembles the * second-half of the igb_resume routine. */ static void igb_io_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); if (adapter->vferr_refcount) { dev_info(pci_dev_to_dev(pdev), "Resuming after VF err\n"); adapter->vferr_refcount--; return; } if (netif_running(netdev)) { if (igb_up(adapter)) { dev_err(pci_dev_to_dev(pdev), "igb_up failed after reset\n"); return; } } netif_device_attach(netdev); /* let the f/w know that the h/w is now under the control of the * driver. */ igb_get_hw_control(adapter); } #endif /* HAVE_PCI_ERS */ int igb_add_mac_filter(struct igb_adapter *adapter, u8 *addr, u16 queue) { struct e1000_hw *hw = &adapter->hw; int i; if (is_zero_ether_addr(addr)) return 0; for (i = 0; i < hw->mac.rar_entry_count; i++) { if (adapter->mac_table[i].state & IGB_MAC_STATE_IN_USE) continue; adapter->mac_table[i].state = (IGB_MAC_STATE_MODIFIED | IGB_MAC_STATE_IN_USE); memcpy(adapter->mac_table[i].addr, addr, ETH_ALEN); adapter->mac_table[i].queue = queue; igb_sync_mac_table(adapter); return 0; } return -ENOMEM; } int igb_del_mac_filter(struct igb_adapter *adapter, u8* addr, u16 queue) { /* search table for addr, if found, set to 0 and sync */ int i; struct e1000_hw *hw = &adapter->hw; if (is_zero_ether_addr(addr)) return 0; for (i = 0; i < hw->mac.rar_entry_count; i++) { if (ether_addr_equal(addr, adapter->mac_table[i].addr) && adapter->mac_table[i].queue == queue) { adapter->mac_table[i].state = IGB_MAC_STATE_MODIFIED; memset(adapter->mac_table[i].addr, 0, ETH_ALEN); adapter->mac_table[i].queue = 0; igb_sync_mac_table(adapter); return 0; } } return -ENOMEM; } static int igb_set_vf_mac(struct igb_adapter *adapter, int vf, unsigned char *mac_addr) { igb_del_mac_filter(adapter, adapter->vf_data[vf].vf_mac_addresses, vf); memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, ETH_ALEN); igb_add_mac_filter(adapter, mac_addr, vf); return 0; } #ifdef IFLA_VF_MAX static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) { struct igb_adapter *adapter = netdev_priv(netdev); if (!is_valid_ether_addr(mac) || (vf >= adapter->vfs_allocated_count)) return -EINVAL; adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf); dev_info(&adapter->pdev->dev, "Reload the VF driver to make this" " change effective.\n"); if (test_bit(__IGB_DOWN, &adapter->state)) { dev_warn(&adapter->pdev->dev, "The VF MAC address has been set," " but the PF device is not up.\n"); dev_warn(&adapter->pdev->dev, "Bring the PF device up before" " attempting to use the VF device.\n"); } return igb_set_vf_mac(adapter, vf, mac); } static int igb_link_mbps(int internal_link_speed) { switch (internal_link_speed) { case SPEED_100: return 100; case SPEED_1000: return 1000; case SPEED_2500: return 2500; default: return 0; } } static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate, int link_speed) { int rf_dec, rf_int; u32 bcnrc_val; if (tx_rate != 0) { /* Calculate the rate factor values to set */ rf_int = link_speed / tx_rate; rf_dec = (link_speed - (rf_int * tx_rate)); rf_dec = (rf_dec * (1<vf_rate_link_speed == 0) || (adapter->hw.mac.type != e1000_82576)) return; actual_link_speed = igb_link_mbps(adapter->link_speed); if (actual_link_speed != adapter->vf_rate_link_speed) { reset_rate = true; adapter->vf_rate_link_speed = 0; dev_info(&adapter->pdev->dev, "Link speed has been changed. VF Transmit rate is disabled\n"); } for (i = 0; i < adapter->vfs_allocated_count; i++) { if (reset_rate) adapter->vf_data[i].tx_rate = 0; igb_set_vf_rate_limit(&adapter->hw, i, adapter->vf_data[i].tx_rate, actual_link_speed); } } #ifdef HAVE_VF_MIN_MAX_TXRATE static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int tx_rate) #else /* HAVE_VF_MIN_MAX_TXRATE */ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) #endif /* HAVE_VF_MIN_MAX_TXRATE */ { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; int actual_link_speed; if (hw->mac.type != e1000_82576) return -EOPNOTSUPP; #ifdef HAVE_VF_MIN_MAX_TXRATE if (min_tx_rate) return -EINVAL; #endif /* HAVE_VF_MIN_MAX_TXRATE */ actual_link_speed = igb_link_mbps(adapter->link_speed); if ((vf >= adapter->vfs_allocated_count) || (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) || (tx_rate < 0) || (tx_rate > actual_link_speed)) return -EINVAL; adapter->vf_rate_link_speed = actual_link_speed; adapter->vf_data[vf].tx_rate = (u16)tx_rate; igb_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed); return 0; } static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) { struct igb_adapter *adapter = netdev_priv(netdev); if (vf >= adapter->vfs_allocated_count) return -EINVAL; ivi->vf = vf; memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); #ifdef HAVE_VF_MIN_MAX_TXRATE ivi->max_tx_rate = adapter->vf_data[vf].tx_rate; ivi->min_tx_rate = 0; #else /* HAVE_VF_MIN_MAX_TXRATE */ ivi->tx_rate = adapter->vf_data[vf].tx_rate; #endif /* HAVE_VF_MIN_MAX_TXRATE */ ivi->vlan = adapter->vf_data[vf].pf_vlan; ivi->qos = adapter->vf_data[vf].pf_qos; #ifdef HAVE_VF_SPOOFCHK_CONFIGURE ivi->spoofchk = adapter->vf_data[vf].spoofchk_enabled; #endif return 0; } #endif static void igb_vmm_control(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int count; u32 reg; switch (hw->mac.type) { case e1000_82575: default: /* replication is not supported for 82575 */ return; case e1000_82576: /* notify HW that the MAC is adding vlan tags */ reg = E1000_READ_REG(hw, E1000_DTXCTL); reg |= (E1000_DTXCTL_VLAN_ADDED | E1000_DTXCTL_SPOOF_INT); E1000_WRITE_REG(hw, E1000_DTXCTL, reg); case e1000_82580: /* enable replication vlan tag stripping */ reg = E1000_READ_REG(hw, E1000_RPLOLR); reg |= E1000_RPLOLR_STRVLAN; E1000_WRITE_REG(hw, E1000_RPLOLR, reg); case e1000_i350: case e1000_i354: /* none of the above registers are supported by i350 */ break; } /* Enable Malicious Driver Detection */ if ((adapter->vfs_allocated_count) && (adapter->mdd)) { if (hw->mac.type == e1000_i350) igb_enable_mdd(adapter); } /* enable replication and loopback support */ count = adapter->vfs_allocated_count || adapter->vmdq_pools; if (adapter->flags & IGB_FLAG_LOOPBACK_ENABLE && count) e1000_vmdq_set_loopback_pf(hw, 1); e1000_vmdq_set_anti_spoofing_pf(hw, adapter->vfs_allocated_count || adapter->vmdq_pools, adapter->vfs_allocated_count); e1000_vmdq_set_replication_pf(hw, adapter->vfs_allocated_count || adapter->vmdq_pools); } static void igb_init_fw(struct igb_adapter *adapter) { struct e1000_fw_drv_info fw_cmd; struct e1000_hw *hw = &adapter->hw; int i; u16 mask; if (hw->mac.type == e1000_i210) mask = E1000_SWFW_EEP_SM; else mask = E1000_SWFW_PHY0_SM; /* i211 parts do not support this feature */ if (hw->mac.type == e1000_i211) hw->mac.arc_subsystem_valid = false; if (!hw->mac.ops.acquire_swfw_sync(hw, mask)) { for (i = 0; i <= FW_MAX_RETRIES; i++) { E1000_WRITE_REG(hw, E1000_FWSTS, E1000_FWSTS_FWRI); fw_cmd.hdr.cmd = FW_CMD_DRV_INFO; fw_cmd.hdr.buf_len = FW_CMD_DRV_INFO_LEN; fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CMD_RESERVED; fw_cmd.port_num = hw->bus.func; fw_cmd.drv_version = FW_FAMILY_DRV_VER; fw_cmd.hdr.checksum = 0; fw_cmd.hdr.checksum = e1000_calculate_checksum((u8 *)&fw_cmd, (FW_HDR_LEN + fw_cmd.hdr.buf_len)); e1000_host_interface_command(hw, (u8*)&fw_cmd, sizeof(fw_cmd)); if (fw_cmd.hdr.cmd_or_resp.ret_status == FW_STATUS_SUCCESS) break; } } else dev_warn(pci_dev_to_dev(adapter->pdev), "Unable to get semaphore, firmware init failed.\n"); hw->mac.ops.release_swfw_sync(hw, mask); } static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) { struct e1000_hw *hw = &adapter->hw; u32 dmac_thr; u16 hwm; u32 status; if (hw->mac.type == e1000_i211) return; if (hw->mac.type > e1000_82580) { if (adapter->dmac != IGB_DMAC_DISABLE) { u32 reg; /* force threshold to 0. */ E1000_WRITE_REG(hw, E1000_DMCTXTH, 0); /* * DMA Coalescing high water mark needs to be greater * than the Rx threshold. Set hwm to PBA - max frame * size in 16B units, capping it at PBA - 6KB. */ hwm = 64 * pba - adapter->max_frame_size / 16; if (hwm < 64 * (pba - 6)) hwm = 64 * (pba - 6); reg = E1000_READ_REG(hw, E1000_FCRTC); reg &= ~E1000_FCRTC_RTH_COAL_MASK; reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT) & E1000_FCRTC_RTH_COAL_MASK); E1000_WRITE_REG(hw, E1000_FCRTC, reg); /* * Set the DMA Coalescing Rx threshold to PBA - 2 * max * frame size, capping it at PBA - 10KB. */ dmac_thr = pba - adapter->max_frame_size / 512; if (dmac_thr < pba - 10) dmac_thr = pba - 10; reg = E1000_READ_REG(hw, E1000_DMACR); reg &= ~E1000_DMACR_DMACTHR_MASK; reg |= ((dmac_thr << E1000_DMACR_DMACTHR_SHIFT) & E1000_DMACR_DMACTHR_MASK); /* transition to L0x or L1 if available..*/ reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK); /* Check if status is 2.5Gb backplane connection * before configuration of watchdog timer, which is * in msec values in 12.8usec intervals * watchdog timer= msec values in 32usec intervals * for non 2.5Gb connection */ if (hw->mac.type == e1000_i354) { status = E1000_READ_REG(hw, E1000_STATUS); if ((status & E1000_STATUS_2P5_SKU) && (!(status & E1000_STATUS_2P5_SKU_OVER))) reg |= ((adapter->dmac * 5) >> 6); else reg |= ((adapter->dmac) >> 5); } else { reg |= ((adapter->dmac) >> 5); } /* * Disable BMC-to-OS Watchdog enable * on devices that support OS-to-BMC */ if (hw->mac.type != e1000_i354) reg &= ~E1000_DMACR_DC_BMC2OSW_EN; E1000_WRITE_REG(hw, E1000_DMACR, reg); /* no lower threshold to disable coalescing(smart fifb)-UTRESH=0*/ E1000_WRITE_REG(hw, E1000_DMCRTRH, 0); /* This sets the time to wait before requesting * transition to low power state to number of usecs * needed to receive 1 512 byte frame at gigabit * line rate. On i350 device, time to make transition * to Lx state is delayed by 4 usec with flush disable * bit set to avoid losing mailbox interrupts */ reg = E1000_READ_REG(hw, E1000_DMCTLX); if (hw->mac.type == e1000_i350) reg |= IGB_DMCTLX_DCFLUSH_DIS; /* in 2.5Gb connection, TTLX unit is 0.4 usec * which is 0x4*2 = 0xA. But delay is still 4 usec */ if (hw->mac.type == e1000_i354) { status = E1000_READ_REG(hw, E1000_STATUS); if ((status & E1000_STATUS_2P5_SKU) && (!(status & E1000_STATUS_2P5_SKU_OVER))) reg |= 0xA; else reg |= 0x4; } else { reg |= 0x4; } E1000_WRITE_REG(hw, E1000_DMCTLX, reg); /* free space in tx packet buffer to wake from DMA coal */ E1000_WRITE_REG(hw, E1000_DMCTXTH, (IGB_MIN_TXPBSIZE - (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6); /* make low power state decision controlled by DMA coal */ reg = E1000_READ_REG(hw, E1000_PCIEMISC); reg &= ~E1000_PCIEMISC_LX_DECISION; E1000_WRITE_REG(hw, E1000_PCIEMISC, reg); } /* endif adapter->dmac is not disabled */ } else if (hw->mac.type == e1000_82580) { u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC); E1000_WRITE_REG(hw, E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); E1000_WRITE_REG(hw, E1000_DMACR, 0); } } #ifdef HAVE_I2C_SUPPORT /* igb_read_i2c_byte - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: device address * @data: value read * * Performs byte read operation over I2C interface at * a specified device address. */ s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); struct i2c_client *this_client = adapter->i2c_client; s32 status; u16 swfw_mask = 0; if (!this_client) return E1000_ERR_I2C; swfw_mask = E1000_SWFW_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) return E1000_ERR_SWFW_SYNC; status = i2c_smbus_read_byte_data(this_client, byte_offset); hw->mac.ops.release_swfw_sync(hw, swfw_mask); if (status < 0) return E1000_ERR_I2C; else { *data = status; return E1000_SUCCESS; } } /* igb_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: device address * @data: value to write * * Performs byte write operation over I2C interface at * a specified device address. */ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); struct i2c_client *this_client = adapter->i2c_client; s32 status; u16 swfw_mask = E1000_SWFW_PHY0_SM; if (!this_client) return E1000_ERR_I2C; if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) return E1000_ERR_SWFW_SYNC; status = i2c_smbus_write_byte_data(this_client, byte_offset, data); hw->mac.ops.release_swfw_sync(hw, swfw_mask); if (status) return E1000_ERR_I2C; else return E1000_SUCCESS; } #endif /* HAVE_I2C_SUPPORT */ /* igb_main.c */ /** * igb_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in igb_pci_tbl * * Returns 0 on success, negative on failure * * igb_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ int igb_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev) { struct net_device *netdev; struct igb_adapter *adapter; struct e1000_hw *hw; u16 eeprom_data = 0; u8 pba_str[E1000_PBANUM_LENGTH]; s32 ret_val; static int global_quad_port_a; /* global quad port a indication */ int i, err, pci_using_dac = 0; static int cards_found; err = pci_enable_device_mem(pdev); if (err) return err; #ifdef NO_KNI pci_using_dac = 0; err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)); if (!err) { err = dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(64)); if (!err) pci_using_dac = 1; } else { err = dma_set_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); if (err) { err = dma_set_coherent_mask(pci_dev_to_dev(pdev), DMA_BIT_MASK(32)); if (err) { IGB_ERR("No usable DMA configuration, " "aborting\n"); goto err_dma; } } } #ifndef HAVE_ASPM_QUIRKS /* 82575 requires that the pci-e link partner disable the L0s state */ switch (pdev->device) { case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); default: break; } #endif /* HAVE_ASPM_QUIRKS */ err = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), igb_driver_name); if (err) goto err_pci_reg; pci_enable_pcie_error_reporting(pdev); pci_set_master(pdev); err = -ENOMEM; #endif /* NO_KNI */ #ifdef HAVE_TX_MQ netdev = alloc_etherdev_mq(sizeof(struct igb_adapter), IGB_MAX_TX_QUEUES); #else netdev = alloc_etherdev(sizeof(struct igb_adapter)); #endif /* HAVE_TX_MQ */ if (!netdev) goto err_alloc_etherdev; SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &pdev->dev); //pci_set_drvdata(pdev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; adapter->port_num = hw->bus.func; adapter->msg_enable = (1 << debug) - 1; #ifdef HAVE_PCI_ERS err = pci_save_state(pdev); if (err) goto err_ioremap; #endif err = -EIO; hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!hw->hw_addr) goto err_ioremap; #ifdef HAVE_NET_DEVICE_OPS netdev->netdev_ops = &igb_netdev_ops; #else /* HAVE_NET_DEVICE_OPS */ netdev->open = &igb_open; netdev->stop = &igb_close; netdev->get_stats = &igb_get_stats; #ifdef HAVE_SET_RX_MODE netdev->set_rx_mode = &igb_set_rx_mode; #endif netdev->set_multicast_list = &igb_set_rx_mode; netdev->set_mac_address = &igb_set_mac; netdev->change_mtu = &igb_change_mtu; netdev->do_ioctl = &igb_ioctl; #ifdef HAVE_TX_TIMEOUT netdev->tx_timeout = &igb_tx_timeout; #endif netdev->vlan_rx_register = igb_vlan_mode; netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = igb_vlan_rx_kill_vid; #ifdef CONFIG_NET_POLL_CONTROLLER netdev->poll_controller = igb_netpoll; #endif netdev->hard_start_xmit = &igb_xmit_frame; #endif /* HAVE_NET_DEVICE_OPS */ igb_set_ethtool_ops(netdev); #ifdef HAVE_TX_TIMEOUT netdev->watchdog_timeo = 5 * HZ; #endif strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); adapter->bd_number = cards_found; /* setup the private structure */ err = igb_sw_init(adapter); if (err) goto err_sw_init; e1000_get_bus_info(hw); hw->phy.autoneg_wait_to_complete = FALSE; hw->mac.adaptive_ifs = FALSE; /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { hw->phy.mdix = AUTO_ALL_MODES; hw->phy.disable_polarity_correction = FALSE; hw->phy.ms_type = e1000_ms_hw_default; } if (e1000_check_reset_block(hw)) dev_info(pci_dev_to_dev(pdev), "PHY reset is blocked due to SOL/IDER session.\n"); /* * features is initialized to 0 in allocation, it might have bits * set by igb_sw_init so we should use an or instead of an * assignment. */ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | #ifdef NETIF_F_IPV6_CSUM NETIF_F_IPV6_CSUM | #endif #ifdef NETIF_F_TSO NETIF_F_TSO | #ifdef NETIF_F_TSO6 NETIF_F_TSO6 | #endif #endif /* NETIF_F_TSO */ #ifdef NETIF_F_RXHASH NETIF_F_RXHASH | #endif NETIF_F_RXCSUM | #ifdef NETIF_F_HW_VLAN_CTAG_RX NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; #else NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX; #endif if (hw->mac.type >= e1000_82576) netdev->features |= NETIF_F_SCTP_CSUM; #ifdef HAVE_NDO_SET_FEATURES /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; #ifndef IGB_NO_LRO /* give us the option of enabling LRO later */ netdev->hw_features |= NETIF_F_LRO; #endif #else #ifdef NETIF_F_GRO /* this is only needed on kernels prior to 2.6.39 */ netdev->features |= NETIF_F_GRO; #endif #endif /* set this bit last since it cannot be part of hw_features */ #ifdef NETIF_F_HW_VLAN_CTAG_FILTER netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; #else netdev->features |= NETIF_F_HW_VLAN_FILTER; #endif #ifdef HAVE_NETDEV_VLAN_FEATURES netdev->vlan_features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG; #endif if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; #ifdef NO_KNI adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); #ifdef DEBUG if (adapter->dmac != IGB_DMAC_DISABLE) printk("%s: DMA Coalescing is enabled..\n", netdev->name); #endif /* before reading the NVM, reset the controller to put the device in a * known good starting state */ e1000_reset_hw(hw); #endif /* NO_KNI */ /* make sure the NVM is good */ if (e1000_validate_nvm_checksum(hw) < 0) { dev_err(pci_dev_to_dev(pdev), "The NVM Checksum Is Not" " Valid\n"); err = -EIO; goto err_eeprom; } /* copy the MAC address out of the NVM */ if (e1000_read_mac_addr(hw)) dev_err(pci_dev_to_dev(pdev), "NVM Read Error\n"); memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len); #ifdef ETHTOOL_GPERMADDR memcpy(netdev->perm_addr, hw->mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { #else if (!is_valid_ether_addr(netdev->dev_addr)) { #endif dev_err(pci_dev_to_dev(pdev), "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; } memcpy(&adapter->mac_table[0].addr, hw->mac.addr, netdev->addr_len); adapter->mac_table[0].queue = adapter->vfs_allocated_count; adapter->mac_table[0].state = (IGB_MAC_STATE_DEFAULT | IGB_MAC_STATE_IN_USE); igb_rar_set(adapter, 0); /* get firmware version for ethtool -i */ igb_set_fw_version(adapter); /* Check if Media Autosense is enabled */ if (hw->mac.type == e1000_82580) igb_init_mas(adapter); #ifdef NO_KNI setup_timer(&adapter->watchdog_timer, &igb_watchdog, (unsigned long) adapter); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) setup_timer(&adapter->dma_err_timer, &igb_dma_err_timer, (unsigned long) adapter); setup_timer(&adapter->phy_info_timer, &igb_update_phy_info, (unsigned long) adapter); INIT_WORK(&adapter->reset_task, igb_reset_task); INIT_WORK(&adapter->watchdog_task, igb_watchdog_task); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) INIT_WORK(&adapter->dma_err_task, igb_dma_err_task); #endif /* Initialize link properties that are user-changeable */ adapter->fc_autoneg = true; hw->mac.autoneg = true; hw->phy.autoneg_advertised = 0x2f; hw->fc.requested_mode = e1000_fc_default; hw->fc.current_mode = e1000_fc_default; e1000_validate_mdi_setting(hw); /* By default, support wake on port A */ if (hw->bus.func == 0) adapter->flags |= IGB_FLAG_WOL_SUPPORTED; /* Check the NVM for wake support for non-port A ports */ if (hw->mac.type >= e1000_82580) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, &eeprom_data); else if (hw->bus.func == 1) e1000_read_nvm(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); if (eeprom_data & IGB_EEPROM_APME) adapter->flags |= IGB_FLAG_WOL_SUPPORTED; /* now that we have the eeprom settings, apply the special cases where * the eeprom may be wrong or the board simply won't support wake on * lan on a particular port */ switch (pdev->device) { case E1000_DEV_ID_82575GB_QUAD_COPPER: adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: /* Wake events only supported on port A for dual fiber * regardless of eeprom setting */ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_QUAD_COPPER_ET2: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; else adapter->flags |= IGB_FLAG_QUAD_PORT_A; /* Reset for multiple quad port adapters */ if (++global_quad_port_a == 4) global_quad_port_a = 0; break; default: /* If the device can't wake, don't set software support */ if (!device_can_wakeup(&adapter->pdev->dev)) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; } /* initialize the wol settings based on the eeprom settings */ if (adapter->flags & IGB_FLAG_WOL_SUPPORTED) adapter->wol |= E1000_WUFC_MAG; /* Some vendors want WoL disabled by default, but still supported */ if ((hw->mac.type == e1000_i350) && (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) { adapter->flags |= IGB_FLAG_WOL_SUPPORTED; adapter->wol = 0; } #ifdef NO_KNI device_set_wakeup_enable(pci_dev_to_dev(adapter->pdev), adapter->flags & IGB_FLAG_WOL_SUPPORTED); /* reset the hardware with the new settings */ igb_reset(adapter); adapter->devrc = 0; #ifdef HAVE_I2C_SUPPORT /* Init the I2C interface */ err = igb_init_i2c(adapter); if (err) { dev_err(&pdev->dev, "failed to init i2c interface\n"); goto err_eeprom; } #endif /* HAVE_I2C_SUPPORT */ /* let the f/w know that the h/w is now under the control of the * driver. */ igb_get_hw_control(adapter); strncpy(netdev->name, "eth%d", IFNAMSIZ); err = register_netdev(netdev); if (err) goto err_register; #ifdef CONFIG_IGB_VMDQ_NETDEV err = igb_init_vmdq_netdevs(adapter); if (err) goto err_register; #endif /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); #ifdef IGB_DCA if (dca_add_requester(&pdev->dev) == E1000_SUCCESS) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(pci_dev_to_dev(pdev), "DCA enabled\n"); igb_setup_dca(adapter); } #endif #ifdef HAVE_PTP_1588_CLOCK /* do hw tstamp init after resetting */ igb_ptp_init(adapter); #endif /* HAVE_PTP_1588_CLOCK */ #endif /* NO_KNI */ dev_info(pci_dev_to_dev(pdev), "Intel(R) Gigabit Ethernet Network Connection\n"); /* print bus type/speed/width info */ dev_info(pci_dev_to_dev(pdev), "%s: (PCIe:%s:%s) ", netdev->name, ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5GT/s" : (hw->bus.speed == e1000_bus_speed_5000) ? "5.0GT/s" : (hw->mac.type == e1000_i354) ? "integrated" : "unknown"), ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" : (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" : (hw->mac.type == e1000_i354) ? "integrated" : "unknown")); dev_info(pci_dev_to_dev(pdev), "%s: MAC: ", netdev->name); for (i = 0; i < 6; i++) printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':'); ret_val = e1000_read_pba_string(hw, pba_str, E1000_PBANUM_LENGTH); if (ret_val) strncpy(pba_str, "Unknown", sizeof(pba_str) - 1); dev_info(pci_dev_to_dev(pdev), "%s: PBA No: %s\n", netdev->name, pba_str); /* Initialize the thermal sensor on i350 devices. */ if (hw->mac.type == e1000_i350) { if (hw->bus.func == 0) { u16 ets_word; /* * Read the NVM to determine if this i350 device * supports an external thermal sensor. */ e1000_read_nvm(hw, NVM_ETS_CFG, 1, &ets_word); if (ets_word != 0x0000 && ets_word != 0xFFFF) adapter->ets = true; else adapter->ets = false; } #ifdef NO_KNI #ifdef IGB_HWMON igb_sysfs_init(adapter); #else #ifdef IGB_PROCFS igb_procfs_init(adapter); #endif /* IGB_PROCFS */ #endif /* IGB_HWMON */ #endif /* NO_KNI */ } else { adapter->ets = false; } if (hw->phy.media_type == e1000_media_type_copper) { switch (hw->mac.type) { case e1000_i350: case e1000_i210: case e1000_i211: /* Enable EEE for internal copper PHY devices */ err = e1000_set_eee_i350(hw); if ((!err) && (adapter->flags & IGB_FLAG_EEE)) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; break; case e1000_i354: if ((E1000_READ_REG(hw, E1000_CTRL_EXT)) & (E1000_CTRL_EXT_LINK_MODE_SGMII)) { err = e1000_set_eee_i354(hw); if ((!err) && (adapter->flags & IGB_FLAG_EEE)) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; } break; default: break; } } /* send driver version info to firmware */ if (hw->mac.type >= e1000_i350) igb_init_fw(adapter); #ifndef IGB_NO_LRO if (netdev->features & NETIF_F_LRO) dev_info(pci_dev_to_dev(pdev), "Internal LRO is enabled \n"); else dev_info(pci_dev_to_dev(pdev), "LRO is disabled \n"); #endif dev_info(pci_dev_to_dev(pdev), "Using %s interrupts. %d rx queue(s), %d tx queue(s)\n", adapter->msix_entries ? "MSI-X" : (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", adapter->num_rx_queues, adapter->num_tx_queues); cards_found++; *lad_dev = netdev; pm_runtime_put_noidle(&pdev->dev); return 0; //err_register: // igb_release_hw_control(adapter); #ifdef HAVE_I2C_SUPPORT memset(&adapter->i2c_adap, 0, sizeof(adapter->i2c_adap)); #endif /* HAVE_I2C_SUPPORT */ err_eeprom: // if (!e1000_check_reset_block(hw)) // e1000_phy_hw_reset(hw); if (hw->flash_address) iounmap(hw->flash_address); err_sw_init: // igb_clear_interrupt_scheme(adapter); // igb_reset_sriov_capability(adapter); iounmap(hw->hw_addr); err_ioremap: free_netdev(netdev); err_alloc_etherdev: // pci_release_selected_regions(pdev, // pci_select_bars(pdev, IORESOURCE_MEM)); //err_pci_reg: //err_dma: pci_disable_device(pdev); return err; } void igb_kni_remove(struct pci_dev *pdev) { pci_disable_device(pdev); } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_param.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include #include "igb.h" /* This is the only thing that needs to be changed to adjust the * maximum number of ports that the driver can manage. */ #define IGB_MAX_NIC 32 #define OPTION_UNSET -1 #define OPTION_DISABLED 0 #define OPTION_ENABLED 1 #define MAX_NUM_LIST_OPTS 15 /* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */ #define IGB_PARAM_INIT { [0 ... IGB_MAX_NIC] = OPTION_UNSET } #ifndef module_param_array /* Module Parameters are always initialized to -1, so that the driver * can tell the difference between no user specified value or the * user asking for the default value. * The true default values are loaded in when igb_check_options is called. * * This is a GCC extension to ANSI C. * See the item "Labeled Elements in Initializers" in the section * "Extensions to the C Language Family" of the GCC documentation. */ #define IGB_PARAM(X, desc) \ static const int X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \ MODULE_PARM(X, "1-" __MODULE_STRING(IGB_MAX_NIC) "i"); \ MODULE_PARM_DESC(X, desc); #else #define IGB_PARAM(X, desc) \ static int X[IGB_MAX_NIC+1] = IGB_PARAM_INIT; \ static unsigned int num_##X; \ module_param_array_named(X, X, int, &num_##X, 0); \ MODULE_PARM_DESC(X, desc); #endif /* Interrupt Throttle Rate (interrupts/sec) * * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) */ IGB_PARAM(InterruptThrottleRate, "Maximum interrupts per second, per vector, (max 100000), default 3=adaptive"); #define DEFAULT_ITR 3 #define MAX_ITR 100000 /* #define MIN_ITR 120 */ #define MIN_ITR 0 /* IntMode (Interrupt Mode) * * Valid Range: 0 - 2 * * Default Value: 2 (MSI-X) */ IGB_PARAM(IntMode, "Change Interrupt Mode (0=Legacy, 1=MSI, 2=MSI-X), default 2"); #define MAX_INTMODE IGB_INT_MODE_MSIX #define MIN_INTMODE IGB_INT_MODE_LEGACY IGB_PARAM(Node, "set the starting node to allocate memory on, default -1"); /* LLIPort (Low Latency Interrupt TCP Port) * * Valid Range: 0 - 65535 * * Default Value: 0 (disabled) */ IGB_PARAM(LLIPort, "Low Latency Interrupt TCP Port (0-65535), default 0=off"); #define DEFAULT_LLIPORT 0 #define MAX_LLIPORT 0xFFFF #define MIN_LLIPORT 0 /* LLIPush (Low Latency Interrupt on TCP Push flag) * * Valid Range: 0, 1 * * Default Value: 0 (disabled) */ IGB_PARAM(LLIPush, "Low Latency Interrupt on TCP Push flag (0,1), default 0=off"); #define DEFAULT_LLIPUSH 0 #define MAX_LLIPUSH 1 #define MIN_LLIPUSH 0 /* LLISize (Low Latency Interrupt on Packet Size) * * Valid Range: 0 - 1500 * * Default Value: 0 (disabled) */ IGB_PARAM(LLISize, "Low Latency Interrupt on Packet Size (0-1500), default 0=off"); #define DEFAULT_LLISIZE 0 #define MAX_LLISIZE 1500 #define MIN_LLISIZE 0 /* RSS (Enable RSS multiqueue receive) * * Valid Range: 0 - 8 * * Default Value: 1 */ IGB_PARAM(RSS, "Number of Receive-Side Scaling Descriptor Queues (0-8), default 1, 0=number of cpus"); #define DEFAULT_RSS 1 #define MAX_RSS 8 #define MIN_RSS 0 /* VMDQ (Enable VMDq multiqueue receive) * * Valid Range: 0 - 8 * * Default Value: 0 */ IGB_PARAM(VMDQ, "Number of Virtual Machine Device Queues: 0-1 = disable, 2-8 enable, default 0"); #define DEFAULT_VMDQ 0 #define MAX_VMDQ MAX_RSS #define MIN_VMDQ 0 /* max_vfs (Enable SR-IOV VF devices) * * Valid Range: 0 - 7 * * Default Value: 0 */ IGB_PARAM(max_vfs, "Number of Virtual Functions: 0 = disable, 1-7 enable, default 0"); #define DEFAULT_SRIOV 0 #define MAX_SRIOV 7 #define MIN_SRIOV 0 /* MDD (Enable Malicious Driver Detection) * * Only available when SR-IOV is enabled - max_vfs is greater than 0 * * Valid Range: 0, 1 * * Default Value: 1 */ IGB_PARAM(MDD, "Malicious Driver Detection (0/1), default 1 = enabled. " "Only available when max_vfs is greater than 0"); #ifdef DEBUG /* Disable Hardware Reset on Tx Hang * * Valid Range: 0, 1 * * Default Value: 0 (disabled, i.e. h/w will reset) */ IGB_PARAM(DisableHwReset, "Disable reset of hardware on Tx hang"); /* Dump Transmit and Receive buffers * * Valid Range: 0, 1 * * Default Value: 0 */ IGB_PARAM(DumpBuffers, "Dump Tx/Rx buffers on Tx hang or by request"); #endif /* DEBUG */ /* QueuePairs (Enable TX/RX queue pairs for interrupt handling) * * Valid Range: 0 - 1 * * Default Value: 1 */ IGB_PARAM(QueuePairs, "Enable Tx/Rx queue pairs for interrupt handling (0,1), default 1=on"); #define DEFAULT_QUEUE_PAIRS 1 #define MAX_QUEUE_PAIRS 1 #define MIN_QUEUE_PAIRS 0 /* Enable/disable EEE (a.k.a. IEEE802.3az) * * Valid Range: 0, 1 * * Default Value: 1 */ IGB_PARAM(EEE, "Enable/disable on parts that support the feature"); /* Enable/disable DMA Coalescing * * Valid Values: 0(off), 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, * 9000, 10000(msec), 250(usec), 500(usec) * * Default Value: 0 */ IGB_PARAM(DMAC, "Disable or set latency for DMA Coalescing ((0=off, 1000-10000(msec), 250, 500 (usec))"); #ifndef IGB_NO_LRO /* Enable/disable Large Receive Offload * * Valid Values: 0(off), 1(on) * * Default Value: 0 */ IGB_PARAM(LRO, "Large Receive Offload (0,1), default 0=off"); #endif struct igb_opt_list { int i; char *str; }; struct igb_option { enum { enable_option, range_option, list_option } type; const char *name; const char *err; int def; union { struct { /* range_option info */ int min; int max; } r; struct { /* list_option info */ int nr; struct igb_opt_list *p; } l; } arg; }; static int igb_validate_option(unsigned int *value, struct igb_option *opt, struct igb_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; return 0; } switch (opt->type) { case enable_option: switch (*value) { case OPTION_ENABLED: DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name); return 0; case OPTION_DISABLED: DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name); return 0; } break; case range_option: if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { DPRINTK(PROBE, INFO, "%s set to %d\n", opt->name, *value); return 0; } break; case list_option: { int i; struct igb_opt_list *ent; for (i = 0; i < opt->arg.l.nr; i++) { ent = &opt->arg.l.p[i]; if (*value == ent->i) { if (ent->str[0] != '\0') DPRINTK(PROBE, INFO, "%s\n", ent->str); return 0; } } } break; default: BUG(); } DPRINTK(PROBE, INFO, "Invalid %s value specified (%d) %s\n", opt->name, *value, opt->err); *value = opt->def; return -1; } /** * igb_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * * This routine checks all command line parameters for valid user * input. If an invalid value is given, or if no user specified * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. **/ void igb_check_options(struct igb_adapter *adapter) { int bd = adapter->bd_number; struct e1000_hw *hw = &adapter->hw; if (bd >= IGB_MAX_NIC) { DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%d\n", bd); DPRINTK(PROBE, NOTICE, "Using defaults for all values\n"); #ifndef module_param_array bd = IGB_MAX_NIC; #endif } { /* Interrupt Throttling Rate */ struct igb_option opt = { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " __MODULE_STRING(DEFAULT_ITR), .def = DEFAULT_ITR, .arg = { .r = { .min = MIN_ITR, .max = MAX_ITR } } }; #ifdef module_param_array if (num_InterruptThrottleRate > bd) { #endif unsigned int itr = InterruptThrottleRate[bd]; switch (itr) { case 0: DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); if (hw->mac.type >= e1000_i350) adapter->dmac = IGB_DMAC_DISABLE; adapter->rx_itr_setting = itr; break; case 1: DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name); adapter->rx_itr_setting = itr; break; case 3: DPRINTK(PROBE, INFO, "%s set to dynamic conservative mode\n", opt.name); adapter->rx_itr_setting = itr; break; default: igb_validate_option(&itr, &opt, adapter); /* Save the setting, because the dynamic bits * change itr. In case of invalid user value, * default to conservative mode, else need to * clear the lower two bits because they are * used as control */ if (itr == 3) { adapter->rx_itr_setting = itr; } else { adapter->rx_itr_setting = 1000000000 / (itr * 256); adapter->rx_itr_setting &= ~3; } break; } #ifdef module_param_array } else { adapter->rx_itr_setting = opt.def; } #endif adapter->tx_itr_setting = adapter->rx_itr_setting; } { /* Interrupt Mode */ struct igb_option opt = { .type = range_option, .name = "Interrupt Mode", .err = "defaulting to 2 (MSI-X)", .def = IGB_INT_MODE_MSIX, .arg = { .r = { .min = MIN_INTMODE, .max = MAX_INTMODE } } }; #ifdef module_param_array if (num_IntMode > bd) { #endif unsigned int int_mode = IntMode[bd]; igb_validate_option(&int_mode, &opt, adapter); adapter->int_mode = int_mode; #ifdef module_param_array } else { adapter->int_mode = opt.def; } #endif } { /* Low Latency Interrupt TCP Port */ struct igb_option opt = { .type = range_option, .name = "Low Latency Interrupt TCP Port", .err = "using default of " __MODULE_STRING(DEFAULT_LLIPORT), .def = DEFAULT_LLIPORT, .arg = { .r = { .min = MIN_LLIPORT, .max = MAX_LLIPORT } } }; #ifdef module_param_array if (num_LLIPort > bd) { #endif adapter->lli_port = LLIPort[bd]; if (adapter->lli_port) { igb_validate_option(&adapter->lli_port, &opt, adapter); } else { DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); } #ifdef module_param_array } else { adapter->lli_port = opt.def; } #endif } { /* Low Latency Interrupt on Packet Size */ struct igb_option opt = { .type = range_option, .name = "Low Latency Interrupt on Packet Size", .err = "using default of " __MODULE_STRING(DEFAULT_LLISIZE), .def = DEFAULT_LLISIZE, .arg = { .r = { .min = MIN_LLISIZE, .max = MAX_LLISIZE } } }; #ifdef module_param_array if (num_LLISize > bd) { #endif adapter->lli_size = LLISize[bd]; if (adapter->lli_size) { igb_validate_option(&adapter->lli_size, &opt, adapter); } else { DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); } #ifdef module_param_array } else { adapter->lli_size = opt.def; } #endif } { /* Low Latency Interrupt on TCP Push flag */ struct igb_option opt = { .type = enable_option, .name = "Low Latency Interrupt on TCP Push flag", .err = "defaulting to Disabled", .def = OPTION_DISABLED }; #ifdef module_param_array if (num_LLIPush > bd) { #endif unsigned int lli_push = LLIPush[bd]; igb_validate_option(&lli_push, &opt, adapter); adapter->flags |= lli_push ? IGB_FLAG_LLI_PUSH : 0; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_LLI_PUSH : 0; } #endif } { /* SRIOV - Enable SR-IOV VF devices */ struct igb_option opt = { .type = range_option, .name = "max_vfs - SR-IOV VF devices", .err = "using default of " __MODULE_STRING(DEFAULT_SRIOV), .def = DEFAULT_SRIOV, .arg = { .r = { .min = MIN_SRIOV, .max = MAX_SRIOV } } }; #ifdef module_param_array if (num_max_vfs > bd) { #endif adapter->vfs_allocated_count = max_vfs[bd]; igb_validate_option(&adapter->vfs_allocated_count, &opt, adapter); #ifdef module_param_array } else { adapter->vfs_allocated_count = opt.def; } #endif if (adapter->vfs_allocated_count) { switch (hw->mac.type) { case e1000_82575: case e1000_82580: case e1000_i210: case e1000_i211: case e1000_i354: adapter->vfs_allocated_count = 0; DPRINTK(PROBE, INFO, "SR-IOV option max_vfs not supported.\n"); default: break; } } } { /* VMDQ - Enable VMDq multiqueue receive */ struct igb_option opt = { .type = range_option, .name = "VMDQ - VMDq multiqueue queue count", .err = "using default of " __MODULE_STRING(DEFAULT_VMDQ), .def = DEFAULT_VMDQ, .arg = { .r = { .min = MIN_VMDQ, .max = (MAX_VMDQ - adapter->vfs_allocated_count) } } }; if ((hw->mac.type != e1000_i210) || (hw->mac.type != e1000_i211)) { #ifdef module_param_array if (num_VMDQ > bd) { #endif adapter->vmdq_pools = (VMDQ[bd] == 1 ? 0 : VMDQ[bd]); if (adapter->vfs_allocated_count && !adapter->vmdq_pools) { DPRINTK(PROBE, INFO, "Enabling SR-IOV requires VMDq be set to at least 1\n"); adapter->vmdq_pools = 1; } igb_validate_option(&adapter->vmdq_pools, &opt, adapter); #ifdef module_param_array } else { if (!adapter->vfs_allocated_count) adapter->vmdq_pools = (opt.def == 1 ? 0 : opt.def); else adapter->vmdq_pools = 1; } #endif #ifdef CONFIG_IGB_VMDQ_NETDEV if (hw->mac.type == e1000_82575 && adapter->vmdq_pools) { DPRINTK(PROBE, INFO, "VMDq not supported on this part.\n"); adapter->vmdq_pools = 0; } #endif } else { DPRINTK(PROBE, INFO, "VMDq option is not supported.\n"); adapter->vmdq_pools = opt.def; } } { /* RSS - Enable RSS multiqueue receives */ struct igb_option opt = { .type = range_option, .name = "RSS - RSS multiqueue receive count", .err = "using default of " __MODULE_STRING(DEFAULT_RSS), .def = DEFAULT_RSS, .arg = { .r = { .min = MIN_RSS, .max = MAX_RSS } } }; switch (hw->mac.type) { case e1000_82575: #ifndef CONFIG_IGB_VMDQ_NETDEV if (!!adapter->vmdq_pools) { if (adapter->vmdq_pools <= 2) { if (adapter->vmdq_pools == 2) opt.arg.r.max = 3; } else { opt.arg.r.max = 1; } } else { opt.arg.r.max = 4; } #else opt.arg.r.max = !!adapter->vmdq_pools ? 1 : 4; #endif /* CONFIG_IGB_VMDQ_NETDEV */ break; case e1000_i210: opt.arg.r.max = 4; break; case e1000_i211: opt.arg.r.max = 2; break; case e1000_82576: #ifndef CONFIG_IGB_VMDQ_NETDEV if (!!adapter->vmdq_pools) opt.arg.r.max = 2; break; #endif /* CONFIG_IGB_VMDQ_NETDEV */ case e1000_82580: case e1000_i350: case e1000_i354: default: if (!!adapter->vmdq_pools) opt.arg.r.max = 1; break; } if (adapter->int_mode != IGB_INT_MODE_MSIX) { DPRINTK(PROBE, INFO, "RSS is not supported when in MSI/Legacy Interrupt mode, %s\n", opt.err); opt.arg.r.max = 1; } #ifdef module_param_array if (num_RSS > bd) { #endif adapter->rss_queues = RSS[bd]; switch (adapter->rss_queues) { case 1: break; default: igb_validate_option(&adapter->rss_queues, &opt, adapter); if (adapter->rss_queues) break; case 0: adapter->rss_queues = min_t(u32, opt.arg.r.max, num_online_cpus()); break; } #ifdef module_param_array } else { adapter->rss_queues = opt.def; } #endif } { /* QueuePairs - Enable Tx/Rx queue pairs for interrupt handling */ struct igb_option opt = { .type = enable_option, .name = "QueuePairs - Tx/Rx queue pairs for interrupt handling", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; #ifdef module_param_array if (num_QueuePairs > bd) { #endif unsigned int qp = QueuePairs[bd]; /* * We must enable queue pairs if the number of queues * exceeds the number of available interrupts. We are * limited to 10, or 3 per unallocated vf. On I210 and * I211 devices, we are limited to 5 interrupts. * However, since I211 only supports 2 queues, we do not * need to check and override the user option. */ if (qp == OPTION_DISABLED) { if (adapter->rss_queues > 4) qp = OPTION_ENABLED; if (adapter->vmdq_pools > 4) qp = OPTION_ENABLED; if (adapter->rss_queues > 1 && (adapter->vmdq_pools > 3 || adapter->vfs_allocated_count > 6)) qp = OPTION_ENABLED; if (hw->mac.type == e1000_i210 && adapter->rss_queues > 2) qp = OPTION_ENABLED; if (qp == OPTION_ENABLED) DPRINTK(PROBE, INFO, "Number of queues exceeds available interrupts, %s\n", opt.err); } igb_validate_option(&qp, &opt, adapter); adapter->flags |= qp ? IGB_FLAG_QUEUE_PAIRS : 0; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_QUEUE_PAIRS : 0; } #endif } { /* EEE - Enable EEE for capable adapters */ if (hw->mac.type >= e1000_i350) { struct igb_option opt = { .type = enable_option, .name = "EEE Support", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; #ifdef module_param_array if (num_EEE > bd) { #endif unsigned int eee = EEE[bd]; igb_validate_option(&eee, &opt, adapter); adapter->flags |= eee ? IGB_FLAG_EEE : 0; if (eee) hw->dev_spec._82575.eee_disable = false; else hw->dev_spec._82575.eee_disable = true; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_EEE : 0; if (adapter->flags & IGB_FLAG_EEE) hw->dev_spec._82575.eee_disable = false; else hw->dev_spec._82575.eee_disable = true; } #endif } } { /* DMAC - Enable DMA Coalescing for capable adapters */ if (hw->mac.type >= e1000_i350) { struct igb_opt_list list [] = { { IGB_DMAC_DISABLE, "DMAC Disable"}, { IGB_DMAC_MIN, "DMAC 250 usec"}, { IGB_DMAC_500, "DMAC 500 usec"}, { IGB_DMAC_EN_DEFAULT, "DMAC 1000 usec"}, { IGB_DMAC_2000, "DMAC 2000 usec"}, { IGB_DMAC_3000, "DMAC 3000 usec"}, { IGB_DMAC_4000, "DMAC 4000 usec"}, { IGB_DMAC_5000, "DMAC 5000 usec"}, { IGB_DMAC_6000, "DMAC 6000 usec"}, { IGB_DMAC_7000, "DMAC 7000 usec"}, { IGB_DMAC_8000, "DMAC 8000 usec"}, { IGB_DMAC_9000, "DMAC 9000 usec"}, { IGB_DMAC_MAX, "DMAC 10000 usec"} }; struct igb_option opt = { .type = list_option, .name = "DMA Coalescing", .err = "using default of "__MODULE_STRING(IGB_DMAC_DISABLE), .def = IGB_DMAC_DISABLE, .arg = { .l = { .nr = 13, .p = list } } }; #ifdef module_param_array if (num_DMAC > bd) { #endif unsigned int dmac = DMAC[bd]; if (adapter->rx_itr_setting == IGB_DMAC_DISABLE) dmac = IGB_DMAC_DISABLE; igb_validate_option(&dmac, &opt, adapter); switch (dmac) { case IGB_DMAC_DISABLE: adapter->dmac = dmac; break; case IGB_DMAC_MIN: adapter->dmac = dmac; break; case IGB_DMAC_500: adapter->dmac = dmac; break; case IGB_DMAC_EN_DEFAULT: adapter->dmac = dmac; break; case IGB_DMAC_2000: adapter->dmac = dmac; break; case IGB_DMAC_3000: adapter->dmac = dmac; break; case IGB_DMAC_4000: adapter->dmac = dmac; break; case IGB_DMAC_5000: adapter->dmac = dmac; break; case IGB_DMAC_6000: adapter->dmac = dmac; break; case IGB_DMAC_7000: adapter->dmac = dmac; break; case IGB_DMAC_8000: adapter->dmac = dmac; break; case IGB_DMAC_9000: adapter->dmac = dmac; break; case IGB_DMAC_MAX: adapter->dmac = dmac; break; default: adapter->dmac = opt.def; DPRINTK(PROBE, INFO, "Invalid DMAC setting, " "resetting DMAC to %d\n", opt.def); } #ifdef module_param_array } else adapter->dmac = opt.def; #endif } } #ifndef IGB_NO_LRO { /* LRO - Enable Large Receive Offload */ struct igb_option opt = { .type = enable_option, .name = "LRO - Large Receive Offload", .err = "defaulting to Disabled", .def = OPTION_DISABLED }; struct net_device *netdev = adapter->netdev; #ifdef module_param_array if (num_LRO > bd) { #endif unsigned int lro = LRO[bd]; igb_validate_option(&lro, &opt, adapter); netdev->features |= lro ? NETIF_F_LRO : 0; #ifdef module_param_array } else if (opt.def == OPTION_ENABLED) { netdev->features |= NETIF_F_LRO; } #endif } #endif /* IGB_NO_LRO */ { /* MDD - Enable Malicious Driver Detection. Only available when SR-IOV is enabled. */ struct igb_option opt = { .type = enable_option, .name = "Malicious Driver Detection", .err = "defaulting to 1", .def = OPTION_ENABLED, .arg = { .r = { .min = OPTION_DISABLED, .max = OPTION_ENABLED } } }; #ifdef module_param_array if (num_MDD > bd) { #endif adapter->mdd = MDD[bd]; igb_validate_option((uint *)&adapter->mdd, &opt, adapter); #ifdef module_param_array } else { adapter->mdd = opt.def; } #endif } } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_procfs.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "igb.h" #include "e1000_82575.h" #include "e1000_hw.h" #ifdef IGB_PROCFS #ifndef IGB_HWMON #include #include #include #include #include static struct proc_dir_entry *igb_top_dir = NULL; bool igb_thermal_present(struct igb_adapter *adapter) { s32 status; struct e1000_hw *hw; if (adapter == NULL) return false; hw = &adapter->hw; /* * Only set I2C bit-bang mode if an external thermal sensor is * supported on this device. */ if (adapter->ets) { status = e1000_set_i2c_bb(hw); if (status != E1000_SUCCESS) return false; } status = hw->mac.ops.init_thermal_sensor_thresh(hw); if (status != E1000_SUCCESS) return false; return true; } static int igb_macburn(char *page, char **start, off_t off, int count, int *eof, void *data) { struct e1000_hw *hw; struct igb_adapter *adapter = (struct igb_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); hw = &adapter->hw; if (hw == NULL) return snprintf(page, count, "error: no hw data\n"); return snprintf(page, count, "0x%02X%02X%02X%02X%02X%02X\n", (unsigned int)hw->mac.perm_addr[0], (unsigned int)hw->mac.perm_addr[1], (unsigned int)hw->mac.perm_addr[2], (unsigned int)hw->mac.perm_addr[3], (unsigned int)hw->mac.perm_addr[4], (unsigned int)hw->mac.perm_addr[5]); } static int igb_macadmn(char *page, char **start, off_t off, int count, int *eof, void *data) { struct e1000_hw *hw; struct igb_adapter *adapter = (struct igb_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); hw = &adapter->hw; if (hw == NULL) return snprintf(page, count, "error: no hw data\n"); return snprintf(page, count, "0x%02X%02X%02X%02X%02X%02X\n", (unsigned int)hw->mac.addr[0], (unsigned int)hw->mac.addr[1], (unsigned int)hw->mac.addr[2], (unsigned int)hw->mac.addr[3], (unsigned int)hw->mac.addr[4], (unsigned int)hw->mac.addr[5]); } static int igb_numeports(char *page, char **start, off_t off, int count, int *eof, void *data) { struct e1000_hw *hw; int ports; struct igb_adapter *adapter = (struct igb_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); hw = &adapter->hw; if (hw == NULL) return snprintf(page, count, "error: no hw data\n"); ports = 4; return snprintf(page, count, "%d\n", ports); } static int igb_porttype(char *page, char **start, off_t off, int count, int *eof, void *data) { struct igb_adapter *adapter = (struct igb_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); return snprintf(page, count, "%d\n", test_bit(__IGB_DOWN, &adapter->state)); } static int igb_therm_location(char *page, char **start, off_t off, int count, int *eof, void *data) { struct igb_therm_proc_data *therm_data = (struct igb_therm_proc_data *)data; if (therm_data == NULL) return snprintf(page, count, "error: no therm_data\n"); return snprintf(page, count, "%d\n", therm_data->sensor_data->location); } static int igb_therm_maxopthresh(char *page, char **start, off_t off, int count, int *eof, void *data) { struct igb_therm_proc_data *therm_data = (struct igb_therm_proc_data *)data; if (therm_data == NULL) return snprintf(page, count, "error: no therm_data\n"); return snprintf(page, count, "%d\n", therm_data->sensor_data->max_op_thresh); } static int igb_therm_cautionthresh(char *page, char **start, off_t off, int count, int *eof, void *data) { struct igb_therm_proc_data *therm_data = (struct igb_therm_proc_data *)data; if (therm_data == NULL) return snprintf(page, count, "error: no therm_data\n"); return snprintf(page, count, "%d\n", therm_data->sensor_data->caution_thresh); } static int igb_therm_temp(char *page, char **start, off_t off, int count, int *eof, void *data) { s32 status; struct igb_therm_proc_data *therm_data = (struct igb_therm_proc_data *)data; if (therm_data == NULL) return snprintf(page, count, "error: no therm_data\n"); status = e1000_get_thermal_sensor_data(therm_data->hw); if (status != E1000_SUCCESS) snprintf(page, count, "error: status %d returned\n", status); return snprintf(page, count, "%d\n", therm_data->sensor_data->temp); } struct igb_proc_type{ char name[32]; int (*read)(char*, char**, off_t, int, int*, void*); }; struct igb_proc_type igb_proc_entries[] = { {"numeports", &igb_numeports}, {"porttype", &igb_porttype}, {"macburn", &igb_macburn}, {"macadmn", &igb_macadmn}, {"", NULL} }; struct igb_proc_type igb_internal_entries[] = { {"location", &igb_therm_location}, {"temp", &igb_therm_temp}, {"cautionthresh", &igb_therm_cautionthresh}, {"maxopthresh", &igb_therm_maxopthresh}, {"", NULL} }; void igb_del_proc_entries(struct igb_adapter *adapter) { int index, i; char buf[16]; /* much larger than the sensor number will ever be */ if (igb_top_dir == NULL) return; for (i = 0; i < E1000_MAX_SENSORS; i++) { if (adapter->therm_dir[i] == NULL) continue; for (index = 0; ; index++) { if (igb_internal_entries[index].read == NULL) break; remove_proc_entry(igb_internal_entries[index].name, adapter->therm_dir[i]); } snprintf(buf, sizeof(buf), "sensor_%d", i); remove_proc_entry(buf, adapter->info_dir); } if (adapter->info_dir != NULL) { for (index = 0; ; index++) { if (igb_proc_entries[index].read == NULL) break; remove_proc_entry(igb_proc_entries[index].name, adapter->info_dir); } remove_proc_entry("info", adapter->eth_dir); } if (adapter->eth_dir != NULL) remove_proc_entry(pci_name(adapter->pdev), igb_top_dir); } /* called from igb_main.c */ void igb_procfs_exit(struct igb_adapter *adapter) { igb_del_proc_entries(adapter); } int igb_procfs_topdir_init(void) { igb_top_dir = proc_mkdir("driver/igb", NULL); if (igb_top_dir == NULL) return -ENOMEM; return 0; } void igb_procfs_topdir_exit(void) { remove_proc_entry("driver/igb", NULL); } /* called from igb_main.c */ int igb_procfs_init(struct igb_adapter *adapter) { int rc = 0; int i; int index; char buf[16]; /* much larger than the sensor number will ever be */ adapter->eth_dir = NULL; adapter->info_dir = NULL; for (i = 0; i < E1000_MAX_SENSORS; i++) adapter->therm_dir[i] = NULL; if ( igb_top_dir == NULL ) { rc = -ENOMEM; goto fail; } adapter->eth_dir = proc_mkdir(pci_name(adapter->pdev), igb_top_dir); if (adapter->eth_dir == NULL) { rc = -ENOMEM; goto fail; } adapter->info_dir = proc_mkdir("info", adapter->eth_dir); if (adapter->info_dir == NULL) { rc = -ENOMEM; goto fail; } for (index = 0; ; index++) { if (igb_proc_entries[index].read == NULL) { break; } if (!(create_proc_read_entry(igb_proc_entries[index].name, 0444, adapter->info_dir, igb_proc_entries[index].read, adapter))) { rc = -ENOMEM; goto fail; } } if (igb_thermal_present(adapter) == false) goto exit; for (i = 0; i < E1000_MAX_SENSORS; i++) { if (adapter->hw.mac.thermal_sensor_data.sensor[i].location== 0) continue; snprintf(buf, sizeof(buf), "sensor_%d", i); adapter->therm_dir[i] = proc_mkdir(buf, adapter->info_dir); if (adapter->therm_dir[i] == NULL) { rc = -ENOMEM; goto fail; } for (index = 0; ; index++) { if (igb_internal_entries[index].read == NULL) break; /* * therm_data struct contains pointer the read func * will be needing */ adapter->therm_data[i].hw = &adapter->hw; adapter->therm_data[i].sensor_data = &adapter->hw.mac.thermal_sensor_data.sensor[i]; if (!(create_proc_read_entry( igb_internal_entries[index].name, 0444, adapter->therm_dir[i], igb_internal_entries[index].read, &adapter->therm_data[i]))) { rc = -ENOMEM; goto fail; } } } goto exit; fail: igb_del_proc_entries(adapter); exit: return rc; } #endif /* !IGB_HWMON */ #endif /* IGB_PROCFS */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_ptp.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /****************************************************************************** Copyright(c) 2011 Richard Cochran for some of the 82576 and 82580 code ******************************************************************************/ #include "igb.h" #include #include #include #include #define INCVALUE_MASK 0x7fffffff #define ISGN 0x80000000 /* * The 82580 timesync updates the system timer every 8ns by 8ns, * and this update value cannot be reprogrammed. * * Neither the 82576 nor the 82580 offer registers wide enough to hold * nanoseconds time values for very long. For the 82580, SYSTIM always * counts nanoseconds, but the upper 24 bits are not available. The * frequency is adjusted by changing the 32 bit fractional nanoseconds * register, TIMINCA. * * For the 82576, the SYSTIM register time unit is affect by the * choice of the 24 bit TININCA:IV (incvalue) field. Five bits of this * field are needed to provide the nominal 16 nanosecond period, * leaving 19 bits for fractional nanoseconds. * * We scale the NIC clock cycle by a large factor so that relatively * small clock corrections can be added or subtracted at each clock * tick. The drawbacks of a large factor are a) that the clock * register overflows more quickly (not such a big deal) and b) that * the increment per tick has to fit into 24 bits. As a result we * need to use a shift of 19 so we can fit a value of 16 into the * TIMINCA register. * * * SYSTIMH SYSTIML * +--------------+ +---+---+------+ * 82576 | 32 | | 8 | 5 | 19 | * +--------------+ +---+---+------+ * \________ 45 bits _______/ fract * * +----------+---+ +--------------+ * 82580 | 24 | 8 | | 32 | * +----------+---+ +--------------+ * reserved \______ 40 bits _____/ * * * The 45 bit 82576 SYSTIM overflows every * 2^45 * 10^-9 / 3600 = 9.77 hours. * * The 40 bit 82580 SYSTIM overflows every * 2^40 * 10^-9 / 60 = 18.3 minutes. */ #define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) #define IGB_PTP_TX_TIMEOUT (HZ * 15) #define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT) #define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1) #define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT) #define IGB_NBITS_82580 40 /* * SYSTIM read access for the 82576 */ static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc) { struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); struct e1000_hw *hw = &igb->hw; u64 val; u32 lo, hi; lo = E1000_READ_REG(hw, E1000_SYSTIML); hi = E1000_READ_REG(hw, E1000_SYSTIMH); val = ((u64) hi) << 32; val |= lo; return val; } /* * SYSTIM read access for the 82580 */ static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc) { struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc); struct e1000_hw *hw = &igb->hw; u64 val; u32 lo, hi; /* The timestamp latches on lowest register read. For the 82580 * the lowest register is SYSTIMR instead of SYSTIML. However we only * need to provide nanosecond resolution, so we just ignore it. */ E1000_READ_REG(hw, E1000_SYSTIMR); lo = E1000_READ_REG(hw, E1000_SYSTIML); hi = E1000_READ_REG(hw, E1000_SYSTIMH); val = ((u64) hi) << 32; val |= lo; return val; } /* * SYSTIM read access for I210/I211 */ static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts) { struct e1000_hw *hw = &adapter->hw; u32 sec, nsec; /* The timestamp latches on lowest register read. For I210/I211, the * lowest register is SYSTIMR. Since we only need to provide nanosecond * resolution, we can ignore it. */ E1000_READ_REG(hw, E1000_SYSTIMR); nsec = E1000_READ_REG(hw, E1000_SYSTIML); sec = E1000_READ_REG(hw, E1000_SYSTIMH); ts->tv_sec = sec; ts->tv_nsec = nsec; } static void igb_ptp_write_i210(struct igb_adapter *adapter, const struct timespec *ts) { struct e1000_hw *hw = &adapter->hw; /* * Writing the SYSTIMR register is not necessary as it only provides * sub-nanosecond resolution. */ E1000_WRITE_REG(hw, E1000_SYSTIML, ts->tv_nsec); E1000_WRITE_REG(hw, E1000_SYSTIMH, ts->tv_sec); } /** * igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp * @adapter: board private structure * @hwtstamps: timestamp structure to update * @systim: unsigned 64bit system time value. * * We need to convert the system time value stored in the RX/TXSTMP registers * into a hwtstamp which can be used by the upper level timestamping functions. * * The 'tmreg_lock' spinlock is used to protect the consistency of the * system time value. This is needed because reading the 64 bit time * value involves reading two (or three) 32 bit registers. The first * read latches the value. Ditto for writing. * * In addition, here have extended the system time with an overflow * counter in software. **/ static void igb_ptp_systim_to_hwtstamp(struct igb_adapter *adapter, struct skb_shared_hwtstamps *hwtstamps, u64 systim) { unsigned long flags; u64 ns; switch (adapter->hw.mac.type) { case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_cyc2time(&adapter->tc, systim); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); memset(hwtstamps, 0, sizeof(*hwtstamps)); hwtstamps->hwtstamp = ns_to_ktime(ns); break; case e1000_i210: case e1000_i211: memset(hwtstamps, 0, sizeof(*hwtstamps)); /* Upper 32 bits contain s, lower 32 bits contain ns. */ hwtstamps->hwtstamp = ktime_set(systim >> 32, systim & 0xFFFFFFFF); break; default: break; } } /* * PTP clock operations */ static int igb_ptp_adjfreq_82576(struct ptp_clock_info *ptp, s32 ppb) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); struct e1000_hw *hw = &igb->hw; int neg_adj = 0; u64 rate; u32 incvalue; if (ppb < 0) { neg_adj = 1; ppb = -ppb; } rate = ppb; rate <<= 14; rate = div_u64(rate, 1953125); incvalue = 16 << IGB_82576_TSYNC_SHIFT; if (neg_adj) incvalue -= rate; else incvalue += rate; E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | (incvalue & INCVALUE_82576_MASK)); return 0; } static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); struct e1000_hw *hw = &igb->hw; int neg_adj = 0; u64 rate; u32 inca; if (ppb < 0) { neg_adj = 1; ppb = -ppb; } rate = ppb; rate <<= 26; rate = div_u64(rate, 1953125); /* At 2.5G speeds, the TIMINCA register on I354 updates the clock 2.5x * as quickly. Account for this by dividing the adjustment by 2.5. */ if (hw->mac.type == e1000_i354) { u32 status = E1000_READ_REG(hw, E1000_STATUS); if ((status & E1000_STATUS_2P5_SKU) && !(status & E1000_STATUS_2P5_SKU_OVER)) { rate <<= 1; rate = div_u64(rate, 5); } } inca = rate & INCVALUE_MASK; if (neg_adj) inca |= ISGN; E1000_WRITE_REG(hw, E1000_TIMINCA, inca); return 0; } static int igb_ptp_adjtime_82576(struct ptp_clock_info *ptp, s64 delta) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; s64 now; spin_lock_irqsave(&igb->tmreg_lock, flags); now = timecounter_read(&igb->tc); now += delta; timecounter_init(&igb->tc, &igb->cc, now); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; struct timespec now, then = ns_to_timespec(delta); spin_lock_irqsave(&igb->tmreg_lock, flags); igb_ptp_read_i210(igb, &now); now = timespec_add(now, then); igb_ptp_write_i210(igb, (const struct timespec *)&now); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } static int igb_ptp_gettime_82576(struct ptp_clock_info *ptp, struct timespec *ts) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; u64 ns; u32 remainder; spin_lock_irqsave(&igb->tmreg_lock, flags); ns = timecounter_read(&igb->tc); spin_unlock_irqrestore(&igb->tmreg_lock, flags); ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); ts->tv_nsec = remainder; return 0; } static int igb_ptp_gettime_i210(struct ptp_clock_info *ptp, struct timespec *ts) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; spin_lock_irqsave(&igb->tmreg_lock, flags); igb_ptp_read_i210(igb, ts); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, const struct timespec *ts) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; u64 ns; ns = ts->tv_sec * 1000000000ULL; ns += ts->tv_nsec; spin_lock_irqsave(&igb->tmreg_lock, flags); timecounter_init(&igb->tc, &igb->cc, ns); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, const struct timespec *ts) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; spin_lock_irqsave(&igb->tmreg_lock, flags); igb_ptp_write_i210(igb, ts); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } static int igb_ptp_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { return -EOPNOTSUPP; } /** * igb_ptp_tx_work * @work: pointer to work struct * * This work function polls the TSYNCTXCTL valid bit to determine when a * timestamp has been taken for the current stored skb. */ void igb_ptp_tx_work(struct work_struct *work) { struct igb_adapter *adapter = container_of(work, struct igb_adapter, ptp_tx_work); struct e1000_hw *hw = &adapter->hw; u32 tsynctxctl; if (!adapter->ptp_tx_skb) return; if (time_is_before_jiffies(adapter->ptp_tx_start + IGB_PTP_TX_TIMEOUT)) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; adapter->tx_hwtstamp_timeouts++; dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); return; } tsynctxctl = E1000_READ_REG(hw, E1000_TSYNCTXCTL); if (tsynctxctl & E1000_TSYNCTXCTL_VALID) igb_ptp_tx_hwtstamp(adapter); else /* reschedule to check later */ schedule_work(&adapter->ptp_tx_work); } static void igb_ptp_overflow_check(struct work_struct *work) { struct igb_adapter *igb = container_of(work, struct igb_adapter, ptp_overflow_work.work); struct timespec ts; igb->ptp_caps.gettime(&igb->ptp_caps, &ts); pr_debug("igb overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); schedule_delayed_work(&igb->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); } /** * igb_ptp_rx_hang - detect error case when Rx timestamp registers latched * @adapter: private network adapter structure * * This watchdog task is scheduled to detect error case where hardware has * dropped an Rx packet that was timestamped when the ring is full. The * particular error is rare but leaves the device in a state unable to timestamp * any future packets. */ void igb_ptp_rx_hang(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct igb_ring *rx_ring; u32 tsyncrxctl = E1000_READ_REG(hw, E1000_TSYNCRXCTL); unsigned long rx_event; int n; if (hw->mac.type != e1000_82576) return; /* If we don't have a valid timestamp in the registers, just update the * timeout counter and exit */ if (!(tsyncrxctl & E1000_TSYNCRXCTL_VALID)) { adapter->last_rx_ptp_check = jiffies; return; } /* Determine the most recent watchdog or rx_timestamp event */ rx_event = adapter->last_rx_ptp_check; for (n = 0; n < adapter->num_rx_queues; n++) { rx_ring = adapter->rx_ring[n]; if (time_after(rx_ring->last_rx_timestamp, rx_event)) rx_event = rx_ring->last_rx_timestamp; } /* Only need to read the high RXSTMP register to clear the lock */ if (time_is_before_jiffies(rx_event + 5 * HZ)) { E1000_READ_REG(hw, E1000_RXSTMPH); adapter->last_rx_ptp_check = jiffies; adapter->rx_hwtstamp_cleared++; dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang"); } } /** * igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp * @adapter: Board private structure. * * If we were asked to do hardware stamping and such a time stamp is * available, then it must have been for this skb here because we only * allow only one such packet into the queue. */ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct skb_shared_hwtstamps shhwtstamps; u64 regval; regval = E1000_READ_REG(hw, E1000_TXSTMPL); regval |= (u64)E1000_READ_REG(hw, E1000_TXSTMPH) << 32; igb_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval); skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; } /** * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp * @q_vector: Pointer to interrupt specific structure * @va: Pointer to address containing Rx buffer * @skb: Buffer containing timestamp and packet * * This function is meant to retrieve a timestamp from the first buffer of an * incoming frame. The value is stored in little endian format starting on * byte 8. */ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va, struct sk_buff *skb) { __le64 *regval = (__le64 *)va; /* * The timestamp is recorded in little endian format. * DWORD: 0 1 2 3 * Field: Reserved Reserved SYSTIML SYSTIMH */ igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb), le64_to_cpu(regval[1])); } /** * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register * @q_vector: Pointer to interrupt specific structure * @skb: Buffer containing timestamp and packet * * This function is meant to retrieve a timestamp from the internal registers * of the adapter and store it in the skb. */ void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb) { struct igb_adapter *adapter = q_vector->adapter; struct e1000_hw *hw = &adapter->hw; u64 regval; /* * If this bit is set, then the RX registers contain the time stamp. No * other packet will be time stamped until we read these registers, so * read the registers to make them available again. Because only one * packet can be time stamped at a time, we know that the register * values must belong to this one here and therefore we don't need to * compare any of the additional attributes stored for it. * * If nothing went wrong, then it should have a shared tx_flags that we * can turn into a skb_shared_hwtstamps. */ if (!(E1000_READ_REG(hw, E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) return; regval = E1000_READ_REG(hw, E1000_RXSTMPL); regval |= (u64)E1000_READ_REG(hw, E1000_RXSTMPH) << 32; igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); } /** * igb_ptp_hwtstamp_ioctl - control hardware time stamping * @netdev: * @ifreq: * @cmd: * * Outgoing time stamping can be enabled and disabled. Play nice and * disable it when requested, although it shouldn't case any overhead * when no packet needs it. At most one packet in the queue may be * marked for time stamping, otherwise it would be impossible to tell * for sure to which packet the hardware time stamp belongs. * * Incoming time stamping has to be configured via the hardware * filters. Not all combinations are supported, in particular event * type has to be specified. Matching the kind of event packet is * not supported, with the exception of "all V2 events regardless of * level 2 or 4". * **/ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; struct hwtstamp_config config; u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; u32 tsync_rx_cfg = 0; bool is_l4 = false; bool is_l2 = false; u32 regval; if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; /* reserved for future extensions */ if (config.flags) return -EINVAL; switch (config.tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; case HWTSTAMP_TX_ON: break; default: return -ERANGE; } switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; is_l2 = true; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_ALL: /* * 82576 cannot timestamp all packets, which it needs to do to * support both V1 Sync and Delay_Req messages */ if (hw->mac.type != e1000_82576) { tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; config.rx_filter = HWTSTAMP_FILTER_ALL; break; } /* fall through */ default: config.rx_filter = HWTSTAMP_FILTER_NONE; return -ERANGE; } if (hw->mac.type == e1000_82575) { if (tsync_rx_ctl | tsync_tx_ctl) return -EINVAL; return 0; } /* * Per-packet timestamping only works if all packets are * timestamped, so enable timestamping in all packets as * long as one rx filter was configured. */ if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; config.rx_filter = HWTSTAMP_FILTER_ALL; is_l2 = true; is_l4 = true; if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { regval = E1000_READ_REG(hw, E1000_RXPBS); regval |= E1000_RXPBS_CFG_TS_EN; E1000_WRITE_REG(hw, E1000_RXPBS, regval); } } /* enable/disable TX */ regval = E1000_READ_REG(hw, E1000_TSYNCTXCTL); regval &= ~E1000_TSYNCTXCTL_ENABLED; regval |= tsync_tx_ctl; E1000_WRITE_REG(hw, E1000_TSYNCTXCTL, regval); /* enable/disable RX */ regval = E1000_READ_REG(hw, E1000_TSYNCRXCTL); regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); regval |= tsync_rx_ctl; E1000_WRITE_REG(hw, E1000_TSYNCRXCTL, regval); /* define which PTP packets are time stamped */ E1000_WRITE_REG(hw, E1000_TSYNCRXCFG, tsync_rx_cfg); /* define ethertype filter for timestamped packets */ if (is_l2) E1000_WRITE_REG(hw, E1000_ETQF(3), (E1000_ETQF_FILTER_ENABLE | /* enable filter */ E1000_ETQF_1588 | /* enable timestamping */ ETH_P_1588)); /* 1588 eth protocol type */ else E1000_WRITE_REG(hw, E1000_ETQF(3), 0); /* L4 Queue Filter[3]: filter by destination port and protocol */ if (is_l4) { u32 ftqf = (IPPROTO_UDP /* UDP */ | E1000_FTQF_VF_BP /* VF not compared */ | E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */ | E1000_FTQF_MASK); /* mask all inputs */ ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */ E1000_WRITE_REG(hw, E1000_IMIR(3), htons(PTP_EV_PORT)); E1000_WRITE_REG(hw, E1000_IMIREXT(3), (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP)); if (hw->mac.type == e1000_82576) { /* enable source port check */ E1000_WRITE_REG(hw, E1000_SPQF(3), htons(PTP_EV_PORT)); ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP; } E1000_WRITE_REG(hw, E1000_FTQF(3), ftqf); } else { E1000_WRITE_REG(hw, E1000_FTQF(3), E1000_FTQF_MASK); } E1000_WRITE_FLUSH(hw); /* clear TX/RX time stamp registers, just to be sure */ regval = E1000_READ_REG(hw, E1000_TXSTMPL); regval = E1000_READ_REG(hw, E1000_TXSTMPH); regval = E1000_READ_REG(hw, E1000_RXSTMPL); regval = E1000_READ_REG(hw, E1000_RXSTMPH); return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; } void igb_ptp_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; switch (hw->mac.type) { case e1000_82576: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 999999881; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_enable; adapter->cc.read = igb_ptp_read_82576; adapter->cc.mask = CLOCKSOURCE_MASK(64); adapter->cc.mult = 1; adapter->cc.shift = IGB_82576_TSYNC_SHIFT; /* Dial the nominal frequency. */ E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i350: case e1000_i354: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576; adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; adapter->ptp_caps.enable = igb_ptp_enable; adapter->cc.read = igb_ptp_read_82580; adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); adapter->cc.mult = 1; adapter->cc.shift = 0; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; case e1000_i210: case e1000_i211: snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = 0; adapter->ptp_caps.pps = 0; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; adapter->ptp_caps.gettime = igb_ptp_gettime_i210; adapter->ptp_caps.settime = igb_ptp_settime_i210; adapter->ptp_caps.enable = igb_ptp_enable; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; default: adapter->ptp_clock = NULL; return; } E1000_WRITE_FLUSH(hw); spin_lock_init(&adapter->tmreg_lock); INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work); /* Initialize the clock and overflow work for devices that need it. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec ts = ktime_to_timespec(ktime_get_real()); igb_ptp_settime_i210(&adapter->ptp_caps, &ts); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); INIT_DELAYED_WORK(&adapter->ptp_overflow_work, igb_ptp_overflow_check); schedule_delayed_work(&adapter->ptp_overflow_work, IGB_SYSTIM_OVERFLOW_PERIOD); } /* Initialize the time sync interrupts for devices that support it. */ if (hw->mac.type >= e1000_82580) { E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); } adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps, &adapter->pdev->dev); if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n"); } else { dev_info(&adapter->pdev->dev, "added PHC on %s\n", adapter->netdev->name); adapter->flags |= IGB_FLAG_PTP; } } /** * igb_ptp_stop - Disable PTP device and stop the overflow check. * @adapter: Board private structure. * * This function stops the PTP support and cancels the delayed work. **/ void igb_ptp_stop(struct igb_adapter *adapter) { switch (adapter->hw.mac.type) { case e1000_82576: case e1000_82580: case e1000_i350: case e1000_i354: cancel_delayed_work_sync(&adapter->ptp_overflow_work); break; case e1000_i210: case e1000_i211: /* No delayed work to cancel. */ break; default: return; } cancel_work_sync(&adapter->ptp_tx_work); if (adapter->ptp_tx_skb) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; } if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); dev_info(&adapter->pdev->dev, "removed PHC on %s\n", adapter->netdev->name); adapter->flags &= ~IGB_FLAG_PTP; } } /** * igb_ptp_reset - Re-enable the adapter for PTP following a reset. * @adapter: Board private structure. * * This function handles the reset work required to re-enable the PTP device. **/ void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; if (!(adapter->flags & IGB_FLAG_PTP)) return; switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ E1000_WRITE_REG(hw, E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576); break; case e1000_82580: case e1000_i350: case e1000_i354: case e1000_i210: case e1000_i211: /* Enable the timer functions and interrupts. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ return; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec ts = ktime_to_timespec(ktime_get_real()); igb_ptp_settime_i210(&adapter->ptp_caps, &ts); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_regtest.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* ethtool register test data */ struct igb_reg_test { u16 reg; u16 reg_offset; u16 array_len; u16 test_type; u32 mask; u32 write; }; /* In the hardware, registers are laid out either singly, in arrays * spaced 0x100 bytes apart, or in contiguous tables. We assume * most tests take place on arrays or single registers (handled * as a single-element array) and special-case the tables. * Table tests are always pattern tests. * * We also make provision for some required setup steps by specifying * registers to be written without any read-back testing. */ #define PATTERN_TEST 1 #define SET_READ_TEST 2 #define WRITE_NO_TEST 3 #define TABLE32_TEST 4 #define TABLE64_TEST_LO 5 #define TABLE64_TEST_HI 6 /* i210 reg test */ static struct igb_reg_test reg_test_i210[] = { { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, /* RDH is read-only for i210, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RA, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA, 0, 16, TABLE64_TEST_HI, 0x900FFFFF, 0xFFFFFFFF }, { E1000_MTA, 0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; /* i350 reg test */ static struct igb_reg_test reg_test_i350[] = { { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, /* VET is readonly on i350 */ { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { E1000_RDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, /* RDH is read-only for i350, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { E1000_TDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RA, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA, 0, 16, TABLE64_TEST_HI, 0xC3FFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 16, TABLE64_TEST_HI, 0xC3FFFFFF, 0xFFFFFFFF }, { E1000_MTA, 0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; /* 82580 reg test */ static struct igb_reg_test reg_test_82580[] = { { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_RDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, /* RDH is read-only for 82580, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_TDBAL(4), 0x40, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(4), 0x40, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(4), 0x40, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_TDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TDT(4), 0x40, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RA, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA, 0, 16, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 8, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 8, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF }, { E1000_MTA, 0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; /* 82576 reg test */ static struct igb_reg_test reg_test_82576[] = { { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_RDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, /* Enable all queues before testing. */ { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, /* RDH is read-only for 82576, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RDT(4), 0x40, 12, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, 0 }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_TDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RA, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA, 0, 16, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 8, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA2, 0, 8, TABLE64_TEST_HI, 0x83FFFFFF, 0xFFFFFFFF }, { E1000_MTA, 0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; /* 82575 register test */ static struct igb_reg_test reg_test_82575[] = { { E1000_FCAL, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_FCAH, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_FCT, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, { E1000_VET, 0x100, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, /* Enable all four RX queues before testing. */ { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, /* RDH is read-only for 82575, only test RDT. */ { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0x003FFFFB }, { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB3FE, 0xFFFFFFFF }, { E1000_TCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, { E1000_TXCW, 0x100, 1, PATTERN_TEST, 0xC000FFFF, 0x0000FFFF }, { E1000_RA, 0, 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { E1000_RA, 0, 16, TABLE64_TEST_HI, 0x800FFFFF, 0xFFFFFFFF }, { E1000_MTA, 0, 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_vmdq.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include #include "igb.h" #include "igb_vmdq.h" #include #ifdef CONFIG_IGB_VMDQ_NETDEV int igb_vmdq_open(struct net_device *dev) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; struct net_device *main_netdev = adapter->netdev; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; if (test_bit(__IGB_DOWN, &adapter->state)) { DPRINTK(DRV, WARNING, "Open %s before opening this device.\n", main_netdev->name); return -EAGAIN; } netif_carrier_off(dev); vadapter->tx_ring->vmdq_netdev = dev; vadapter->rx_ring->vmdq_netdev = dev; if (is_valid_ether_addr(dev->dev_addr)) { igb_del_mac_filter(adapter, dev->dev_addr, hw_queue); igb_add_mac_filter(adapter, dev->dev_addr, hw_queue); } netif_carrier_on(dev); return 0; } int igb_vmdq_close(struct net_device *dev) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; netif_carrier_off(dev); igb_del_mac_filter(adapter, dev->dev_addr, hw_queue); vadapter->tx_ring->vmdq_netdev = NULL; vadapter->rx_ring->vmdq_netdev = NULL; return 0; } netdev_tx_t igb_vmdq_xmit_frame(struct sk_buff *skb, struct net_device *dev) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); return igb_xmit_frame_ring(skb, vadapter->tx_ring); } struct net_device_stats *igb_vmdq_get_stats(struct net_device *dev) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; struct e1000_hw *hw = &adapter->hw; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; vadapter->net_stats.rx_packets += E1000_READ_REG(hw, E1000_PFVFGPRC(hw_queue)); E1000_WRITE_REG(hw, E1000_PFVFGPRC(hw_queue), 0); vadapter->net_stats.tx_packets += E1000_READ_REG(hw, E1000_PFVFGPTC(hw_queue)); E1000_WRITE_REG(hw, E1000_PFVFGPTC(hw_queue), 0); vadapter->net_stats.rx_bytes += E1000_READ_REG(hw, E1000_PFVFGORC(hw_queue)); E1000_WRITE_REG(hw, E1000_PFVFGORC(hw_queue), 0); vadapter->net_stats.tx_bytes += E1000_READ_REG(hw, E1000_PFVFGOTC(hw_queue)); E1000_WRITE_REG(hw, E1000_PFVFGOTC(hw_queue), 0); vadapter->net_stats.multicast += E1000_READ_REG(hw, E1000_PFVFMPRC(hw_queue)); E1000_WRITE_REG(hw, E1000_PFVFMPRC(hw_queue), 0); /* only return the current stats */ return &vadapter->net_stats; } /** * igb_write_vm_addr_list - write unicast addresses to RAR table * @netdev: network interface device structure * * Writes unicast address list to the RAR table. * Returns: -ENOMEM on failure/insufficient address space * 0 on no addresses written * X on writing X addresses to the RAR table **/ static int igb_write_vm_addr_list(struct net_device *netdev) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_adapter *adapter = vadapter->real_adapter; int count = 0; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; /* return ENOMEM indicating insufficient memory for addresses */ if (netdev_uc_count(netdev) > igb_available_rars(adapter)) return -ENOMEM; if (!netdev_uc_empty(netdev)) { #ifdef NETDEV_HW_ADDR_T_UNICAST struct netdev_hw_addr *ha; #else struct dev_mc_list *ha; #endif netdev_for_each_uc_addr(ha, netdev) { #ifdef NETDEV_HW_ADDR_T_UNICAST igb_del_mac_filter(adapter, ha->addr, hw_queue); igb_add_mac_filter(adapter, ha->addr, hw_queue); #else igb_del_mac_filter(adapter, ha->da_addr, hw_queue); igb_add_mac_filter(adapter, ha->da_addr, hw_queue); #endif count++; } } return count; } #define E1000_VMOLR_UPE 0x20000000 /* Unicast promiscuous mode */ void igb_vmdq_set_rx_mode(struct net_device *dev) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; struct e1000_hw *hw = &adapter->hw; u32 vmolr, rctl; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; /* Check for Promiscuous and All Multicast modes */ vmolr = E1000_READ_REG(hw, E1000_VMOLR(hw_queue)); /* clear the affected bits */ vmolr &= ~(E1000_VMOLR_UPE | E1000_VMOLR_MPME | E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE); if (dev->flags & IFF_PROMISC) { vmolr |= E1000_VMOLR_UPE; rctl = E1000_READ_REG(hw, E1000_RCTL); rctl |= E1000_RCTL_UPE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); } else { rctl = E1000_READ_REG(hw, E1000_RCTL); rctl &= ~E1000_RCTL_UPE; E1000_WRITE_REG(hw, E1000_RCTL, rctl); if (dev->flags & IFF_ALLMULTI) { vmolr |= E1000_VMOLR_MPME; } else { /* * Write addresses to the MTA, if the attempt fails * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ if (igb_write_mc_addr_list(adapter->netdev) != 0) vmolr |= E1000_VMOLR_ROMPE; } #ifdef HAVE_SET_RX_MODE /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable * unicast promiscuous mode */ if (igb_write_vm_addr_list(dev) < 0) vmolr |= E1000_VMOLR_UPE; #endif } E1000_WRITE_REG(hw, E1000_VMOLR(hw_queue), vmolr); return; } int igb_vmdq_set_mac(struct net_device *dev, void *p) { struct sockaddr *addr = p; struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; igb_del_mac_filter(adapter, dev->dev_addr, hw_queue); memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); return igb_add_mac_filter(adapter, dev->dev_addr, hw_queue); } int igb_vmdq_change_mtu(struct net_device *dev, int new_mtu) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; if (adapter->netdev->mtu < new_mtu) { DPRINTK(PROBE, INFO, "Set MTU on %s to >= %d " "before changing MTU on %s\n", adapter->netdev->name, new_mtu, dev->name); return -EINVAL; } dev->mtu = new_mtu; return 0; } void igb_vmdq_tx_timeout(struct net_device *dev) { return; } void igb_vmdq_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; struct e1000_hw *hw = &adapter->hw; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; vadapter->vlgrp = grp; igb_enable_vlan_tags(adapter); E1000_WRITE_REG(hw, E1000_VMVIR(hw_queue), 0); return; } void igb_vmdq_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; #ifndef HAVE_NETDEV_VLAN_FEATURES struct net_device *v_netdev; #endif int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; /* attempt to add filter to vlvf array */ igb_vlvf_set(adapter, vid, TRUE, hw_queue); #ifndef HAVE_NETDEV_VLAN_FEATURES /* Copy feature flags from netdev to the vlan netdev for this vid. * This allows things like TSO to bubble down to our vlan device. */ v_netdev = vlan_group_get_device(vadapter->vlgrp, vid); v_netdev->features |= adapter->netdev->features; vlan_group_set_device(vadapter->vlgrp, vid, v_netdev); #endif return; } void igb_vmdq_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct igb_vmdq_adapter *vadapter = netdev_priv(dev); struct igb_adapter *adapter = vadapter->real_adapter; int hw_queue = vadapter->rx_ring->queue_index + adapter->vfs_allocated_count; vlan_group_set_device(vadapter->vlgrp, vid, NULL); /* remove vlan from VLVF table array */ igb_vlvf_set(adapter, vid, FALSE, hw_queue); return; } static int igb_vmdq_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_adapter *adapter = vadapter->real_adapter; struct e1000_hw *hw = &adapter->hw; u32 status; if (hw->phy.media_type == e1000_media_type_copper) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full| SUPPORTED_Autoneg | SUPPORTED_TP); ecmd->advertising = ADVERTISED_TP; if (hw->mac.autoneg == 1) { ecmd->advertising |= ADVERTISED_Autoneg; /* the e1000 autoneg seems to match ethtool nicely */ ecmd->advertising |= hw->phy.autoneg_advertised; } ecmd->port = PORT_TP; ecmd->phy_address = hw->phy.addr; } else { ecmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | SUPPORTED_Autoneg); ecmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE | ADVERTISED_Autoneg); ecmd->port = PORT_FIBRE; } ecmd->transceiver = XCVR_INTERNAL; status = E1000_READ_REG(hw, E1000_STATUS); if (status & E1000_STATUS_LU) { if ((status & E1000_STATUS_SPEED_1000) || hw->phy.media_type != e1000_media_type_copper) ecmd->speed = SPEED_1000; else if (status & E1000_STATUS_SPEED_100) ecmd->speed = SPEED_100; else ecmd->speed = SPEED_10; if ((status & E1000_STATUS_FD) || hw->phy.media_type != e1000_media_type_copper) ecmd->duplex = DUPLEX_FULL; else ecmd->duplex = DUPLEX_HALF; } else { ecmd->speed = -1; ecmd->duplex = -1; } ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; return 0; } static u32 igb_vmdq_get_msglevel(struct net_device *netdev) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_adapter *adapter = vadapter->real_adapter; return adapter->msg_enable; } static void igb_vmdq_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_adapter *adapter = vadapter->real_adapter; struct net_device *main_netdev = adapter->netdev; strncpy(drvinfo->driver, igb_driver_name, 32); strncpy(drvinfo->version, igb_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 4); snprintf(drvinfo->bus_info, 32, "%s VMDQ %d", main_netdev->name, vadapter->rx_ring->queue_index); drvinfo->n_stats = 0; drvinfo->testinfo_len = 0; drvinfo->regdump_len = 0; } static void igb_vmdq_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_ring *tx_ring = vadapter->tx_ring; struct igb_ring *rx_ring = vadapter->rx_ring; ring->rx_max_pending = IGB_MAX_RXD; ring->tx_max_pending = IGB_MAX_TXD; ring->rx_mini_max_pending = 0; ring->rx_jumbo_max_pending = 0; ring->rx_pending = rx_ring->count; ring->tx_pending = tx_ring->count; ring->rx_mini_pending = 0; ring->rx_jumbo_pending = 0; } static u32 igb_vmdq_get_rx_csum(struct net_device *netdev) { struct igb_vmdq_adapter *vadapter = netdev_priv(netdev); struct igb_adapter *adapter = vadapter->real_adapter; return test_bit(IGB_RING_FLAG_RX_CSUM, &adapter->rx_ring[0]->flags); } static struct ethtool_ops igb_vmdq_ethtool_ops = { .get_settings = igb_vmdq_get_settings, .get_drvinfo = igb_vmdq_get_drvinfo, .get_link = ethtool_op_get_link, .get_ringparam = igb_vmdq_get_ringparam, .get_rx_csum = igb_vmdq_get_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_msglevel = igb_vmdq_get_msglevel, #ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, #endif #ifdef HAVE_ETHTOOL_GET_PERM_ADDR .get_perm_addr = ethtool_op_get_perm_addr, #endif }; void igb_vmdq_set_ethtool_ops(struct net_device *netdev) { SET_ETHTOOL_OPS(netdev, &igb_vmdq_ethtool_ops); } #endif /* CONFIG_IGB_VMDQ_NETDEV */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/igb_vmdq.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IGB_VMDQ_H_ #define _IGB_VMDQ_H_ #ifdef CONFIG_IGB_VMDQ_NETDEV int igb_vmdq_open(struct net_device *dev); int igb_vmdq_close(struct net_device *dev); netdev_tx_t igb_vmdq_xmit_frame(struct sk_buff *skb, struct net_device *dev); struct net_device_stats *igb_vmdq_get_stats(struct net_device *dev); void igb_vmdq_set_rx_mode(struct net_device *dev); int igb_vmdq_set_mac(struct net_device *dev, void *addr); int igb_vmdq_change_mtu(struct net_device *dev, int new_mtu); void igb_vmdq_tx_timeout(struct net_device *dev); void igb_vmdq_vlan_rx_register(struct net_device *dev, struct vlan_group *grp); void igb_vmdq_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); void igb_vmdq_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); void igb_vmdq_set_ethtool_ops(struct net_device *netdev); #endif /* CONFIG_IGB_VMDQ_NETDEV */ #endif /* _IGB_VMDQ_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "igb.h" #include "kcompat.h" /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) ) /* From lib/vsprintf.c */ #include static int skip_atoi(const char **s) { int i=0; while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #define _kc_ZEROPAD 1 /* pad with zero */ #define _kc_SIGN 2 /* unsigned/signed long */ #define _kc_PLUS 4 /* show plus */ #define _kc_SPACE 8 /* space if plus */ #define _kc_LEFT 16 /* left justified */ #define _kc_SPECIAL 32 /* 0x */ #define _kc_LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; digits = (type & _kc_LARGE) ? large_digits : small_digits; if (type & _kc_LEFT) type &= ~_kc_ZEROPAD; if (base < 2 || base > 36) return 0; c = (type & _kc_ZEROPAD) ? '0' : ' '; sign = 0; if (type & _kc_SIGN) { if (num < 0) { sign = '-'; num = -num; size--; } else if (type & _kc_PLUS) { sign = '+'; size--; } else if (type & _kc_SPACE) { sign = ' '; size--; } } if (type & _kc_SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(_kc_ZEROPAD+_kc_LEFT))) { while(size-->0) { if (buf <= end) *buf = ' '; ++buf; } } if (sign) { if (buf <= end) *buf = sign; ++buf; } if (type & _kc_SPECIAL) { if (base==8) { if (buf <= end) *buf = '0'; ++buf; } else if (base==16) { if (buf <= end) *buf = '0'; ++buf; if (buf <= end) *buf = digits[33]; ++buf; } } if (!(type & _kc_LEFT)) { while (size-- > 0) { if (buf <= end) *buf = c; ++buf; } } while (i < precision--) { if (buf <= end) *buf = '0'; ++buf; } while (i-- > 0) { if (buf <= end) *buf = tmp[i]; ++buf; } while (size-- > 0) { if (buf <= end) *buf = ' '; ++buf; } return buf; } int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { int len; unsigned long long num; int i, base; char *str, *end, c; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ /* 'z' changed to 'Z' --davidm 1/25/99 */ str = buf; end = buf + size - 1; if (end < buf - 1) { end = ((void *) -1); size = end - buf + 1; } for (; *fmt ; ++fmt) { if (*fmt != '%') { if (str <= end) *str = *fmt; ++str; continue; } /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= _kc_LEFT; goto repeat; case '+': flags |= _kc_PLUS; goto repeat; case ' ': flags |= _kc_SPACE; goto repeat; case '#': flags |= _kc_SPECIAL; goto repeat; case '0': flags |= _kc_ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (isdigit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= _kc_LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (isdigit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { qualifier = *fmt; ++fmt; } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & _kc_LEFT)) { while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } } c = (unsigned char) va_arg(args, int); if (str <= end) *str = c; ++str; while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } continue; case 's': s = va_arg(args, char *); if (!s) s = ""; len = strnlen(s, precision); if (!(flags & _kc_LEFT)) { while (len < field_width--) { if (str <= end) *str = ' '; ++str; } } for (i = 0; i < len; ++i) { if (str <= end) *str = *s; ++str; ++s; } while (len < field_width--) { if (str <= end) *str = ' '; ++str; } continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= _kc_ZEROPAD; } str = number(str, end, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); continue; case 'n': /* FIXME: * What does C99 say about the overflow case here? */ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else if (qualifier == 'Z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } continue; case '%': if (str <= end) *str = '%'; ++str; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= _kc_LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= _kc_SIGN; case 'u': break; default: if (str <= end) *str = '%'; ++str; if (*fmt) { if (str <= end) *str = *fmt; ++str; } else { --fmt; } continue; } if (qualifier == 'L') num = va_arg(args, long long); else if (qualifier == 'l') { num = va_arg(args, unsigned long); if (flags & _kc_SIGN) num = (signed long) num; } else if (qualifier == 'Z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & _kc_SIGN) num = (signed short) num; } else { num = va_arg(args, unsigned int); if (flags & _kc_SIGN) num = (signed int) num; } str = number(str, end, num, base, field_width, precision, flags); } if (str <= end) *str = '\0'; else if (size > 0) /* don't write out a null byte if the buf size is zero */ *end = '\0'; /* the trailing null byte doesn't count towards the total * ++str; */ return str-buf; } int _kc_snprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = _kc_vsnprintf(buf,size,fmt,args); va_end(args); return i; } #endif /* < 2.4.8 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) /**************************************/ /* PCI DMA MAPPING */ #if defined(CONFIG_HIGHMEM) #ifndef PCI_DRAM_OFFSET #define PCI_DRAM_OFFSET 0 #endif u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) { return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + PCI_DRAM_OFFSET); } #else /* CONFIG_HIGHMEM */ u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) { return pci_map_single(dev, (void *)page_address(page) + offset, size, direction); } #endif /* CONFIG_HIGHMEM */ void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction) { return pci_unmap_single(dev, dma_addr, size, direction); } #endif /* 2.4.13 => 2.4.3 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) /**************************************/ /* PCI DRIVER API */ int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) { if (!pci_dma_supported(dev, mask)) return -EIO; dev->dma_mask = mask; return 0; } int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) { int i; for (i = 0; i < 6; i++) { if (pci_resource_len(dev, i) == 0) continue; if (pci_resource_flags(dev, i) & IORESOURCE_IO) { if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { pci_release_regions(dev); return -EBUSY; } } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { pci_release_regions(dev); return -EBUSY; } } } return 0; } void _kc_pci_release_regions(struct pci_dev *dev) { int i; for (i = 0; i < 6; i++) { if (pci_resource_len(dev, i) == 0) continue; if (pci_resource_flags(dev, i) & IORESOURCE_IO) release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); } } /**************************************/ /* NETWORK DRIVER API */ struct net_device * _kc_alloc_etherdev(int sizeof_priv) { struct net_device *dev; int alloc_size; alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; dev = kzalloc(alloc_size, GFP_KERNEL); if (!dev) return NULL; if (sizeof_priv) dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); dev->name[0] = '\0'; ether_setup(dev); return dev; } int _kc_is_valid_ether_addr(u8 *addr) { const char zaddr[6] = { 0, }; return !(addr[0] & 1) && memcmp(addr, zaddr, 6); } #endif /* 2.4.3 => 2.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) int _kc_pci_set_power_state(struct pci_dev *dev, int state) { return 0; } int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) { return 0; } #endif /* 2.4.6 => 2.4.3 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; frag->page = page; frag->page_offset = off; frag->size = size; skb_shinfo(skb)->nr_frags = i + 1; } /* * Original Copyright: * find_next_bit.c: fallback find next bit implementation * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) */ /** * find_next_bit - find the next set bit in a memory region * @addr: The address to base the search on * @offset: The bitnumber to start searching at * @size: The maximum size to search */ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; if (offset >= size) return size; size -= result; offset %= BITS_PER_LONG; if (offset) { tmp = *(p++); tmp &= (~0UL << offset); if (size < BITS_PER_LONG) goto found_first; if (tmp) goto found_middle; size -= BITS_PER_LONG; result += BITS_PER_LONG; } while (size & ~(BITS_PER_LONG-1)) { if ((tmp = *(p++))) goto found_middle; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = *p; found_first: tmp &= (~0UL >> (BITS_PER_LONG - size)); if (tmp == 0UL) /* Are any bits set? */ return result + size; /* Nope. */ found_middle: return result + ffs(tmp); } size_t _kc_strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } #ifndef do_div #if BITS_PER_LONG == 32 uint32_t __attribute__((weak)) _kc__div64_32(uint64_t *n, uint32_t base) { uint64_t rem = *n; uint64_t b = base; uint64_t res, d = 1; uint32_t high = rem >> 32; /* Reduce the thing a bit first */ res = 0; if (high >= base) { high /= base; res = (uint64_t) high << 32; rem -= (uint64_t) (high*base) << 32; } while ((int64_t)b > 0 && b < rem) { b = b+b; d = d+d; } do { if (rem >= b) { rem -= b; res += d; } b >>= 1; d >>= 1; } while (d); *n = res; return rem; } #endif /* BITS_PER_LONG == 32 */ #endif /* do_div */ #endif /* 2.6.0 => 2.4.6 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) int _kc_scnprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = vsnprintf(buf, size, fmt, args); va_end(args); return (i >= size) ? (size - 1) : i; } #endif /* < 2.6.4 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES) = {1}; #endif /* < 2.6.10 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) char *_kc_kstrdup(const char *s, unsigned int gfp) { size_t len; char *buf; if (!s) return NULL; len = strlen(s) + 1; buf = kmalloc(len, gfp); if (buf) memcpy(buf, s, len); return buf; } #endif /* < 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) void *_kc_kzalloc(size_t size, int flags) { void *ret = kmalloc(size, flags); if (ret) memset(ret, 0, size); return ret; } #endif /* <= 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) int _kc_skb_pad(struct sk_buff *skb, int pad) { int ntail; /* If the skbuff is non linear tailroom is always zero.. */ if(!skb_cloned(skb) && skb_tailroom(skb) >= pad) { memset(skb->data+skb->len, 0, pad); return 0; } ntail = skb->data_len + pad - (skb->end - skb->tail); if (likely(skb_cloned(skb) || ntail > 0)) { if (pskb_expand_head(skb, 0, ntail, GFP_ATOMIC)); goto free_skb; } #ifdef MAX_SKB_FRAGS if (skb_is_nonlinear(skb) && !__pskb_pull_tail(skb, skb->data_len)) goto free_skb; #endif memset(skb->data + skb->len, 0, pad); return 0; free_skb: kfree_skb(skb); return -ENOMEM; } #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4))) int _kc_pci_save_state(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct adapter_struct *adapter = netdev_priv(netdev); int size = PCI_CONFIG_SPACE_LEN, i; u16 pcie_cap_offset, pcie_link_status; #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) /* no ->dev for 2.4 kernels */ WARN_ON(pdev->dev.driver_data == NULL); #endif pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (pcie_cap_offset) { if (!pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) size = PCIE_CONFIG_SPACE_LEN; } pci_config_space_ich8lan(); #ifdef HAVE_PCI_ERS if (adapter->config_space == NULL) #else WARN_ON(adapter->config_space != NULL); #endif adapter->config_space = kmalloc(size, GFP_KERNEL); if (!adapter->config_space) { printk(KERN_ERR "Out of memory in pci_save_state\n"); return -ENOMEM; } for (i = 0; i < (size / 4); i++) pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); return 0; } void _kc_pci_restore_state(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); struct adapter_struct *adapter = netdev_priv(netdev); int size = PCI_CONFIG_SPACE_LEN, i; u16 pcie_cap_offset; u16 pcie_link_status; if (adapter->config_space != NULL) { pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (pcie_cap_offset && !pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) size = PCIE_CONFIG_SPACE_LEN; pci_config_space_ich8lan(); for (i = 0; i < (size / 4); i++) pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); #ifndef HAVE_PCI_ERS kfree(adapter->config_space); adapter->config_space = NULL; #endif } } #endif /* !(RHEL_RELEASE_CODE >= RHEL 5.4) */ #ifdef HAVE_PCI_ERS void _kc_free_netdev(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); if (adapter->config_space != NULL) kfree(adapter->config_space); #ifdef CONFIG_SYSFS if (netdev->reg_state == NETREG_UNINITIALIZED) { kfree((char *)netdev - netdev->padded); } else { BUG_ON(netdev->reg_state != NETREG_UNREGISTERED); netdev->reg_state = NETREG_RELEASED; class_device_put(&netdev->class_dev); } #else kfree((char *)netdev - netdev->padded); #endif } #endif void *_kc_kmemdup(const void *src, size_t len, unsigned gfp) { void *p; p = kzalloc(len, gfp); if (p) memcpy(p, src, len); return p; } #endif /* <= 2.6.19 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) struct pci_dev *_kc_netdev_to_pdev(struct net_device *netdev) { return ((struct adapter_struct *)netdev_priv(netdev))->pdev; } #endif /* < 2.6.21 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) /* hexdump code taken from lib/hexdump.c */ static void _kc_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, unsigned char *linebuf, size_t linebuflen, bool ascii) { const u8 *ptr = buf; u8 ch; int j, lx = 0; int ascii_column; if (rowsize != 16 && rowsize != 32) rowsize = 16; if (!len) goto nil; if (len > rowsize) /* limit to one line at a time */ len = rowsize; if ((len % groupsize) != 0) /* no mixed size output */ groupsize = 1; switch (groupsize) { case 8: { const u64 *ptr8 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%16.16llx", j ? " " : "", (unsigned long long)*(ptr8 + j)); ascii_column = 17 * ngroups + 2; break; } case 4: { const u32 *ptr4 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%8.8x", j ? " " : "", *(ptr4 + j)); ascii_column = 9 * ngroups + 2; break; } case 2: { const u16 *ptr2 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%4.4x", j ? " " : "", *(ptr2 + j)); ascii_column = 5 * ngroups + 2; break; } default: for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) { ch = ptr[j]; linebuf[lx++] = hex_asc(ch >> 4); linebuf[lx++] = hex_asc(ch & 0x0f); linebuf[lx++] = ' '; } if (j) lx--; ascii_column = 3 * rowsize + 2; break; } if (!ascii) goto nil; while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) linebuf[lx++] = ' '; for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j] : '.'; nil: linebuf[lx++] = '\0'; } void _kc_print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii) { const u8 *ptr = buf; int i, linelen, remaining = len; unsigned char linebuf[200]; if (rowsize != 16 && rowsize != 32) rowsize = 16; for (i = 0; i < len; i += rowsize) { linelen = min(remaining, rowsize); remaining -= rowsize; _kc_hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, linebuf, sizeof(linebuf), ascii); switch (prefix_type) { case DUMP_PREFIX_ADDRESS: printk("%s%s%*p: %s\n", level, prefix_str, (int)(2 * sizeof(void *)), ptr + i, linebuf); break; case DUMP_PREFIX_OFFSET: printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf); break; default: printk("%s%s%s\n", level, prefix_str, linebuf); break; } } } #ifdef HAVE_I2C_SUPPORT struct i2c_client * _kc_i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) { struct i2c_client *client; int status; client = kzalloc(sizeof *client, GFP_KERNEL); if (!client) return NULL; client->adapter = adap; client->dev.platform_data = info->platform_data; client->flags = info->flags; client->addr = info->addr; strlcpy(client->name, info->type, sizeof(client->name)); /* Check for address business */ status = i2c_check_addr(adap, client->addr); if (status) goto out_err; client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; status = i2c_attach_client(client); if (status) goto out_err; dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", client->name, dev_name(&client->dev)); return client; out_err: dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, status); kfree(client); return NULL; } #endif /* HAVE_I2C_SUPPORT */ #endif /* < 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) #ifdef NAPI struct net_device *napi_to_poll_dev(const struct napi_struct *napi) { struct adapter_q_vector *q_vector = container_of(napi, struct adapter_q_vector, napi); return &q_vector->poll_dev; } int __kc_adapter_clean(struct net_device *netdev, int *budget) { int work_done; int work_to_do = min(*budget, netdev->quota); /* kcompat.h netif_napi_add puts napi struct in "fake netdev->priv" */ struct napi_struct *napi = netdev->priv; work_done = napi->poll(napi, work_to_do); *budget -= work_done; netdev->quota -= work_done; return (work_done >= work_to_do) ? 1 : 0; } #endif /* NAPI */ #endif /* <= 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) void _kc_pci_disable_link_state(struct pci_dev *pdev, int state) { struct pci_dev *parent = pdev->bus->self; u16 link_state; int pos; if (!parent) return; pos = pci_find_capability(parent, PCI_CAP_ID_EXP); if (pos) { pci_read_config_word(parent, pos + PCI_EXP_LNKCTL, &link_state); link_state &= ~state; pci_write_config_word(parent, pos + PCI_EXP_LNKCTL, link_state); } } #endif /* < 2.6.26 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) #ifdef HAVE_TX_MQ void _kc_netif_tx_stop_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_stop_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_stop_subqueue(netdev, i); } void _kc_netif_tx_wake_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_wake_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_wake_subqueue(netdev, i); } void _kc_netif_tx_start_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_start_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_start_subqueue(netdev, i); } #endif /* HAVE_TX_MQ */ #ifndef __WARN_printf void __kc_warn_slowpath(const char *file, int line, const char *fmt, ...) { va_list args; printk(KERN_WARNING "------------[ cut here ]------------\n"); printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, line); va_start(args, fmt); vprintk(fmt, args); va_end(args); dump_stack(); } #endif /* __WARN_printf */ #endif /* < 2.6.27 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) int _kc_pci_prepare_to_sleep(struct pci_dev *dev) { pci_power_t target_state; int error; target_state = pci_choose_state(dev, PMSG_SUSPEND); pci_enable_wake(dev, target_state, true); error = pci_set_power_state(dev, target_state); if (error) pci_enable_wake(dev, target_state, false); return error; } int _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable) { int err; err = pci_enable_wake(dev, PCI_D3cold, enable); if (err) goto out; err = pci_enable_wake(dev, PCI_D3hot, enable); out: return err; } #endif /* < 2.6.28 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) static void __kc_pci_set_master(struct pci_dev *pdev, bool enable) { u16 old_cmd, cmd; pci_read_config_word(pdev, PCI_COMMAND, &old_cmd); if (enable) cmd = old_cmd | PCI_COMMAND_MASTER; else cmd = old_cmd & ~PCI_COMMAND_MASTER; if (cmd != old_cmd) { dev_dbg(pci_dev_to_dev(pdev), "%s bus mastering\n", enable ? "enabling" : "disabling"); pci_write_config_word(pdev, PCI_COMMAND, cmd); } #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) ) pdev->is_busmaster = enable; #endif } void _kc_pci_clear_master(struct pci_dev *dev) { __kc_pci_set_master(dev, false); } #endif /* < 2.6.29 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ) #if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) int _kc_pci_num_vf(struct pci_dev *dev) { int num_vf = 0; #ifdef CONFIG_PCI_IOV struct pci_dev *vfdev; /* loop through all ethernet devices starting at PF dev */ vfdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, NULL); while (vfdev) { if (vfdev->is_virtfn && vfdev->physfn == dev) num_vf++; vfdev = pci_get_class(PCI_CLASS_NETWORK_ETHERNET << 8, vfdev); } #endif return num_vf; } #endif /* RHEL_RELEASE_CODE */ #endif /* < 2.6.34 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) #ifdef HAVE_TX_MQ #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0))) #ifndef CONFIG_NETDEVICES_MULTIQUEUE void _kc_netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) { unsigned int real_num = dev->real_num_tx_queues; struct Qdisc *qdisc; int i; if (unlikely(txq > dev->num_tx_queues)) ; else if (txq > real_num) dev->real_num_tx_queues = txq; else if ( txq < real_num) { dev->real_num_tx_queues = txq; for (i = txq; i < dev->num_tx_queues; i++) { qdisc = netdev_get_tx_queue(dev, i)->qdisc; if (qdisc) { spin_lock_bh(qdisc_lock(qdisc)); qdisc_reset(qdisc); spin_unlock_bh(qdisc_lock(qdisc)); } } } } #endif /* CONFIG_NETDEVICES_MULTIQUEUE */ #endif /* !(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) */ #endif /* HAVE_TX_MQ */ ssize_t _kc_simple_write_to_buffer(void *to, size_t available, loff_t *ppos, const void __user *from, size_t count) { loff_t pos = *ppos; size_t res; if (pos < 0) return -EINVAL; if (pos >= available || !count) return 0; if (count > available - pos) count = available - pos; res = copy_from_user(to + pos, from, count); if (res == count) return -EFAULT; count -= res; *ppos = pos + count; return count; } #endif /* < 2.6.35 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ) static const u32 _kc_flags_dup_features = (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH); u32 _kc_ethtool_op_get_flags(struct net_device *dev) { return dev->features & _kc_flags_dup_features; } int _kc_ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) { if (data & ~supported) return -EINVAL; dev->features = ((dev->features & ~_kc_flags_dup_features) | (data & _kc_flags_dup_features)); return 0; } #endif /* < 2.6.36 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) ) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0))) #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)) */ #endif /* < 2.6.39 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ) void _kc_skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size, unsigned int truesize) { skb_fill_page_desc(skb, i, page, off, size); skb->len += size; skb->data_len += size; skb->truesize += truesize; } int _kc_simple_open(struct inode *inode, struct file *file) { if (inode->i_private) file->private_data = inode->i_private; return 0; } #endif /* < 3.4.0 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) ) #if !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) && \ !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,5)) static inline int __kc_pcie_cap_version(struct pci_dev *dev) { int pos; u16 reg16; pos = pci_find_capability(dev, PCI_CAP_ID_EXP); if (!pos) return 0; pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); return reg16 & PCI_EXP_FLAGS_VERS; } static inline bool __kc_pcie_cap_has_devctl(const struct pci_dev __always_unused *dev) { return true; } static inline bool __kc_pcie_cap_has_lnkctl(struct pci_dev *dev) { int type = pci_pcie_type(dev); return __kc_pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_ENDPOINT || type == PCI_EXP_TYPE_LEG_END; } static inline bool __kc_pcie_cap_has_sltctl(struct pci_dev *dev) { int type = pci_pcie_type(dev); int pos; u16 pcie_flags_reg; pos = pci_find_capability(dev, PCI_CAP_ID_EXP); if (!pos) return 0; pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &pcie_flags_reg); return __kc_pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT || (type == PCI_EXP_TYPE_DOWNSTREAM && pcie_flags_reg & PCI_EXP_FLAGS_SLOT); } static inline bool __kc_pcie_cap_has_rtctl(struct pci_dev *dev) { int type = pci_pcie_type(dev); return __kc_pcie_cap_version(dev) > 1 || type == PCI_EXP_TYPE_ROOT_PORT || type == PCI_EXP_TYPE_RC_EC; } static bool __kc_pcie_capability_reg_implemented(struct pci_dev *dev, int pos) { if (!pci_is_pcie(dev)) return false; switch (pos) { case PCI_EXP_FLAGS_TYPE: return true; case PCI_EXP_DEVCAP: case PCI_EXP_DEVCTL: case PCI_EXP_DEVSTA: return __kc_pcie_cap_has_devctl(dev); case PCI_EXP_LNKCAP: case PCI_EXP_LNKCTL: case PCI_EXP_LNKSTA: return __kc_pcie_cap_has_lnkctl(dev); case PCI_EXP_SLTCAP: case PCI_EXP_SLTCTL: case PCI_EXP_SLTSTA: return __kc_pcie_cap_has_sltctl(dev); case PCI_EXP_RTCTL: case PCI_EXP_RTCAP: case PCI_EXP_RTSTA: return __kc_pcie_cap_has_rtctl(dev); case PCI_EXP_DEVCAP2: case PCI_EXP_DEVCTL2: case PCI_EXP_LNKCAP2: case PCI_EXP_LNKCTL2: case PCI_EXP_LNKSTA2: return __kc_pcie_cap_version(dev) > 1; default: return false; } } /* * Note that these accessor functions are only for the "PCI Express * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) */ int __kc_pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) { int ret; *val = 0; if (pos & 1) return -EINVAL; if (__kc_pcie_capability_reg_implemented(dev, pos)) { ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); /* * Reset *val to 0 if pci_read_config_word() fails, it may * have been written as 0xFFFF if hardware error happens * during pci_read_config_word(). */ if (ret) *val = 0; return ret; } /* * For Functions that do not implement the Slot Capabilities, * Slot Status, and Slot Control registers, these spaces must * be hardwired to 0b, with the exception of the Presence Detect * State bit in the Slot Status register of Downstream Ports, * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8) */ if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA && pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { *val = PCI_EXP_SLTSTA_PDS; } return 0; } int __kc_pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) { if (pos & 1) return -EINVAL; if (!__kc_pcie_capability_reg_implemented(dev, pos)) return 0; return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); } int __kc_pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, u16 clear, u16 set) { int ret; u16 val; ret = __kc_pcie_capability_read_word(dev, pos, &val); if (!ret) { val &= ~clear; val |= set; ret = __kc_pcie_capability_write_word(dev, pos, val); } return ret; } #endif /* !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) && \ !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,5)) */ #endif /* < 3.7.0 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) ) #endif /* 3.9.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #ifdef CONFIG_PCI_IOV int __kc_pci_vfs_assigned(struct pci_dev *dev) { unsigned int vfs_assigned = 0; #ifdef HAVE_PCI_DEV_FLAGS_ASSIGNED int pos; struct pci_dev *vfdev; unsigned short dev_id; /* only search if we are a PF */ if (!dev->is_physfn) return 0; /* find SR-IOV capability */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); if (!pos) return 0; /* * determine the device ID for the VFs, the vendor ID will be the * same as the PF so there is no need to check for that one */ pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &dev_id); /* loop through all the VFs to see if we own any that are assigned */ vfdev = pci_get_device(dev->vendor, dev_id, NULL); while (vfdev) { /* * It is considered assigned if it is a virtual function with * our dev as the physical function and the assigned bit is set */ if (vfdev->is_virtfn && (vfdev->physfn == dev) && (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)) vfs_assigned++; vfdev = pci_get_device(dev->vendor, dev_id, vfdev); } #endif /* HAVE_PCI_DEV_FLAGS_ASSIGNED */ return vfs_assigned; } #endif /* CONFIG_PCI_IOV */ #endif /* 3.10.0 */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _KCOMPAT_H_ #define _KCOMPAT_H_ #ifndef LINUX_VERSION_CODE #include #else #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* NAPI enable/disable flags here */ #define NAPI #define adapter_struct igb_adapter #define adapter_q_vector igb_q_vector #define NAPI /* and finally set defines so that the code sees the changes */ #ifdef NAPI #else #endif /* NAPI */ /* packet split disable/enable */ #ifdef DISABLE_PACKET_SPLIT #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT #define CONFIG_IGB_DISABLE_PACKET_SPLIT #endif #endif /* DISABLE_PACKET_SPLIT */ /* MSI compatibility code for all kernels and drivers */ #ifdef DISABLE_PCI_MSI #undef CONFIG_PCI_MSI #endif #ifndef CONFIG_PCI_MSI #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) struct msix_entry { u16 vector; /* kernel uses to write allocated vector */ u16 entry; /* driver uses to specify entry, OS writes */ }; #endif #undef pci_enable_msi #define pci_enable_msi(a) -ENOTSUPP #undef pci_disable_msi #define pci_disable_msi(a) do {} while (0) #undef pci_enable_msix #define pci_enable_msix(a, b, c) -ENOTSUPP #undef pci_disable_msix #define pci_disable_msix(a) do {} while (0) #define msi_remove_pci_irq_vectors(a) do {} while (0) #endif /* CONFIG_PCI_MSI */ #ifdef DISABLE_PM #undef CONFIG_PM #endif #ifdef DISABLE_NET_POLL_CONTROLLER #undef CONFIG_NET_POLL_CONTROLLER #endif #ifndef PMSG_SUSPEND #define PMSG_SUSPEND 3 #endif /* generic boolean compatibility */ #undef TRUE #undef FALSE #define TRUE true #define FALSE false #ifdef GCC_VERSION #if ( GCC_VERSION < 3000 ) #define _Bool char #endif #else #define _Bool char #endif /* kernels less than 2.4.14 don't have this */ #ifndef ETH_P_8021Q #define ETH_P_8021Q 0x8100 #endif #ifndef module_param #define module_param(v,t,p) MODULE_PARM(v, "i"); #endif #ifndef DMA_64BIT_MASK #define DMA_64BIT_MASK 0xffffffffffffffffULL #endif #ifndef DMA_32BIT_MASK #define DMA_32BIT_MASK 0x00000000ffffffffULL #endif #ifndef PCI_CAP_ID_EXP #define PCI_CAP_ID_EXP 0x10 #endif #ifndef PCIE_LINK_STATE_L0S #define PCIE_LINK_STATE_L0S 1 #endif #ifndef PCIE_LINK_STATE_L1 #define PCIE_LINK_STATE_L1 2 #endif #ifndef mmiowb #ifdef CONFIG_IA64 #define mmiowb() asm volatile ("mf.a" ::: "memory") #else #define mmiowb() #endif #endif #ifndef SET_NETDEV_DEV #define SET_NETDEV_DEV(net, pdev) #endif #if !defined(HAVE_FREE_NETDEV) && ( LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ) #define free_netdev(x) kfree(x) #endif #ifdef HAVE_POLL_CONTROLLER #define CONFIG_NET_POLL_CONTROLLER #endif #ifndef SKB_DATAREF_SHIFT /* if we do not have the infrastructure to detect if skb_header is cloned just return false in all cases */ #define skb_header_cloned(x) 0 #endif #ifndef NETIF_F_GSO #define gso_size tso_size #define gso_segs tso_segs #endif #ifndef NETIF_F_GRO #define vlan_gro_receive(_napi, _vlgrp, _vlan, _skb) \ vlan_hwaccel_receive_skb(_skb, _vlgrp, _vlan) #define napi_gro_receive(_napi, _skb) netif_receive_skb(_skb) #endif #ifndef NETIF_F_SCTP_CSUM #define NETIF_F_SCTP_CSUM 0 #endif #ifndef NETIF_F_LRO #define NETIF_F_LRO (1 << 15) #endif #ifndef NETIF_F_NTUPLE #define NETIF_F_NTUPLE (1 << 27) #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #ifndef CHECKSUM_PARTIAL #define CHECKSUM_PARTIAL CHECKSUM_HW #define CHECKSUM_COMPLETE CHECKSUM_HW #endif #ifndef __read_mostly #define __read_mostly #endif #ifndef MII_RESV1 #define MII_RESV1 0x17 /* Reserved... */ #endif #ifndef unlikely #define unlikely(_x) _x #define likely(_x) _x #endif #ifndef WARN_ON #define WARN_ON(x) #endif #ifndef PCI_DEVICE #define PCI_DEVICE(vend,dev) \ .vendor = (vend), .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID #endif #ifndef node_online #define node_online(node) ((node) == 0) #endif #ifndef num_online_cpus #define num_online_cpus() smp_num_cpus #endif #ifndef cpu_online #define cpu_online(cpuid) test_bit((cpuid), &cpu_online_map) #endif #ifndef _LINUX_RANDOM_H #include #endif #ifndef DECLARE_BITMAP #ifndef BITS_TO_LONGS #define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) #endif #define DECLARE_BITMAP(name,bits) long name[BITS_TO_LONGS(bits)] #endif #ifndef VLAN_HLEN #define VLAN_HLEN 4 #endif #ifndef VLAN_ETH_HLEN #define VLAN_ETH_HLEN 18 #endif #ifndef VLAN_ETH_FRAME_LEN #define VLAN_ETH_FRAME_LEN 1518 #endif #if !defined(IXGBE_DCA) && !defined(IGB_DCA) #define dca_get_tag(b) 0 #define dca_add_requester(a) -1 #define dca_remove_requester(b) do { } while(0) #define DCA_PROVIDER_ADD 0x0001 #define DCA_PROVIDER_REMOVE 0x0002 #endif #ifndef DCA_GET_TAG_TWO_ARGS #define dca3_get_tag(a,b) dca_get_tag(b) #endif #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #if defined(__i386__) || defined(__x86_64__) #define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #endif #endif /* taken from 2.6.24 definition in linux/kernel.h */ #ifndef IS_ALIGNED #define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) #endif #ifdef IS_ENABLED #undef IS_ENABLED #undef __ARG_PLACEHOLDER_1 #undef config_enabled #undef _config_enabled #undef __config_enabled #undef ___config_enabled #endif #define __ARG_PLACEHOLDER_1 0, #define config_enabled(cfg) _config_enabled(cfg) #define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value) #define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0) #define ___config_enabled(__ignored, val, ...) val #define IS_ENABLED(option) \ (config_enabled(option) || config_enabled(option##_MODULE)) #if !defined(NETIF_F_HW_VLAN_TX) && !defined(NETIF_F_HW_VLAN_CTAG_TX) struct _kc_vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; __be16 h_vlan_proto; __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; #define vlan_ethhdr _kc_vlan_ethhdr struct _kc_vlan_hdr { __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; #define vlan_hdr _kc_vlan_hdr #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #define vlan_tx_tag_present(_skb) 0 #define vlan_tx_tag_get(_skb) 0 #endif #endif /* NETIF_F_HW_VLAN_TX && NETIF_F_HW_VLAN_CTAG_TX */ #ifndef VLAN_PRIO_SHIFT #define VLAN_PRIO_SHIFT 13 #endif #ifndef __GFP_COLD #define __GFP_COLD 0 #endif #ifndef __GFP_COMP #define __GFP_COMP 0 #endif /*****************************************************************************/ /* Installations with ethtool version without eeprom, adapter id, or statistics * support */ #ifndef ETH_GSTRING_LEN #define ETH_GSTRING_LEN 32 #endif #ifndef ETHTOOL_GSTATS #define ETHTOOL_GSTATS 0x1d #undef ethtool_drvinfo #define ethtool_drvinfo k_ethtool_drvinfo struct k_ethtool_drvinfo { u32 cmd; char driver[32]; char version[32]; char fw_version[32]; char bus_info[32]; char reserved1[32]; char reserved2[16]; u32 n_stats; u32 testinfo_len; u32 eedump_len; u32 regdump_len; }; struct ethtool_stats { u32 cmd; u32 n_stats; u64 data[0]; }; #endif /* ETHTOOL_GSTATS */ #ifndef ETHTOOL_PHYS_ID #define ETHTOOL_PHYS_ID 0x1c #endif /* ETHTOOL_PHYS_ID */ #ifndef ETHTOOL_GSTRINGS #define ETHTOOL_GSTRINGS 0x1b enum ethtool_stringset { ETH_SS_TEST = 0, ETH_SS_STATS, }; struct ethtool_gstrings { u32 cmd; /* ETHTOOL_GSTRINGS */ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ u32 len; /* number of strings in the string set */ u8 data[0]; }; #endif /* ETHTOOL_GSTRINGS */ #ifndef ETHTOOL_TEST #define ETHTOOL_TEST 0x1a enum ethtool_test_flags { ETH_TEST_FL_OFFLINE = (1 << 0), ETH_TEST_FL_FAILED = (1 << 1), }; struct ethtool_test { u32 cmd; u32 flags; u32 reserved; u32 len; u64 data[0]; }; #endif /* ETHTOOL_TEST */ #ifndef ETHTOOL_GEEPROM #define ETHTOOL_GEEPROM 0xb #undef ETHTOOL_GREGS struct ethtool_eeprom { u32 cmd; u32 magic; u32 offset; u32 len; u8 data[0]; }; struct ethtool_value { u32 cmd; u32 data; }; #endif /* ETHTOOL_GEEPROM */ #ifndef ETHTOOL_GLINK #define ETHTOOL_GLINK 0xa #endif /* ETHTOOL_GLINK */ #ifndef ETHTOOL_GWOL #define ETHTOOL_GWOL 0x5 #define ETHTOOL_SWOL 0x6 #define SOPASS_MAX 6 struct ethtool_wolinfo { u32 cmd; u32 supported; u32 wolopts; u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ }; #endif /* ETHTOOL_GWOL */ #ifndef ETHTOOL_GREGS #define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ #define ethtool_regs _kc_ethtool_regs /* for passing big chunks of data */ struct _kc_ethtool_regs { u32 cmd; u32 version; /* driver-specific, indicates different chips/revs */ u32 len; /* bytes */ u8 data[0]; }; #endif /* ETHTOOL_GREGS */ #ifndef ETHTOOL_GMSGLVL #define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ #endif #ifndef ETHTOOL_SMSGLVL #define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ #endif #ifndef ETHTOOL_NWAY_RST #define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ #endif #ifndef ETHTOOL_GLINK #define ETHTOOL_GLINK 0x0000000a /* Get link status */ #endif #ifndef ETHTOOL_GEEPROM #define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ #endif #ifndef ETHTOOL_SEEPROM #define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ #endif #ifndef ETHTOOL_GCOALESCE #define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ /* for configuring coalescing parameters of chip */ #define ethtool_coalesce _kc_ethtool_coalesce struct _kc_ethtool_coalesce { u32 cmd; /* ETHTOOL_{G,S}COALESCE */ /* How many usecs to delay an RX interrupt after * a packet arrives. If 0, only rx_max_coalesced_frames * is used. */ u32 rx_coalesce_usecs; /* How many packets to delay an RX interrupt after * a packet arrives. If 0, only rx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause RX interrupts to never be * generated. */ u32 rx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being serviced by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 rx_coalesce_usecs_irq; u32 rx_max_coalesced_frames_irq; /* How many usecs to delay a TX interrupt after * a packet is sent. If 0, only tx_max_coalesced_frames * is used. */ u32 tx_coalesce_usecs; /* How many packets to delay a TX interrupt after * a packet is sent. If 0, only tx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause TX interrupts to never be * generated. */ u32 tx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being serviced by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 tx_coalesce_usecs_irq; u32 tx_max_coalesced_frames_irq; /* How many usecs to delay in-memory statistics * block updates. Some drivers do not have an in-memory * statistic block, and in such cases this value is ignored. * This value must not be zero. */ u32 stats_block_coalesce_usecs; /* Adaptive RX/TX coalescing is an algorithm implemented by * some drivers to improve latency under low packet rates and * improve throughput under high packet rates. Some drivers * only implement one of RX or TX adaptive coalescing. Anything * not implemented by the driver causes these values to be * silently ignored. */ u32 use_adaptive_rx_coalesce; u32 use_adaptive_tx_coalesce; /* When the packet rate (measured in packets per second) * is below pkt_rate_low, the {rx,tx}_*_low parameters are * used. */ u32 pkt_rate_low; u32 rx_coalesce_usecs_low; u32 rx_max_coalesced_frames_low; u32 tx_coalesce_usecs_low; u32 tx_max_coalesced_frames_low; /* When the packet rate is below pkt_rate_high but above * pkt_rate_low (both measured in packets per second) the * normal {rx,tx}_* coalescing parameters are used. */ /* When the packet rate is (measured in packets per second) * is above pkt_rate_high, the {rx,tx}_*_high parameters are * used. */ u32 pkt_rate_high; u32 rx_coalesce_usecs_high; u32 rx_max_coalesced_frames_high; u32 tx_coalesce_usecs_high; u32 tx_max_coalesced_frames_high; /* How often to do adaptive coalescing packet rate sampling, * measured in seconds. Must not be zero. */ u32 rate_sample_interval; }; #endif /* ETHTOOL_GCOALESCE */ #ifndef ETHTOOL_SCOALESCE #define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ #endif #ifndef ETHTOOL_GRINGPARAM #define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ /* for configuring RX/TX ring parameters */ #define ethtool_ringparam _kc_ethtool_ringparam struct _kc_ethtool_ringparam { u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ /* Read only attributes. These indicate the maximum number * of pending RX/TX ring entries the driver will allow the * user to set. */ u32 rx_max_pending; u32 rx_mini_max_pending; u32 rx_jumbo_max_pending; u32 tx_max_pending; /* Values changeable by the user. The valid values are * in the range 1 to the "*_max_pending" counterpart above. */ u32 rx_pending; u32 rx_mini_pending; u32 rx_jumbo_pending; u32 tx_pending; }; #endif /* ETHTOOL_GRINGPARAM */ #ifndef ETHTOOL_SRINGPARAM #define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ #endif #ifndef ETHTOOL_GPAUSEPARAM #define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ /* for configuring link flow control parameters */ #define ethtool_pauseparam _kc_ethtool_pauseparam struct _kc_ethtool_pauseparam { u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg * being true) the user may set 'autoneg' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. * * If 'autoneg' is zero or the link is not being auto-negotiated, * then {rx,tx}_pause force the driver to use/not-use pause * flow control. */ u32 autoneg; u32 rx_pause; u32 tx_pause; }; #endif /* ETHTOOL_GPAUSEPARAM */ #ifndef ETHTOOL_SPAUSEPARAM #define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ #endif #ifndef ETHTOOL_GRXCSUM #define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_SRXCSUM #define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_GTXCSUM #define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_STXCSUM #define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_GSG #define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable * (ethtool_value) */ #endif #ifndef ETHTOOL_SSG #define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable * (ethtool_value). */ #endif #ifndef ETHTOOL_TEST #define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ #endif #ifndef ETHTOOL_GSTRINGS #define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ #endif #ifndef ETHTOOL_PHYS_ID #define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ #endif #ifndef ETHTOOL_GSTATS #define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ #endif #ifndef ETHTOOL_GTSO #define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ #endif #ifndef ETHTOOL_STSO #define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ #endif #ifndef ETHTOOL_BUSINFO_LEN #define ETHTOOL_BUSINFO_LEN 32 #endif #ifndef RHEL_RELEASE_VERSION #define RHEL_RELEASE_VERSION(a,b) (((a) << 8) + (b)) #endif #ifndef AX_RELEASE_VERSION #define AX_RELEASE_VERSION(a,b) (((a) << 8) + (b)) #endif #ifndef AX_RELEASE_CODE #define AX_RELEASE_CODE 0 #endif #if (AX_RELEASE_CODE && AX_RELEASE_CODE == AX_RELEASE_VERSION(3,0)) #define RHEL_RELEASE_CODE RHEL_RELEASE_VERSION(5,0) #elif (AX_RELEASE_CODE && AX_RELEASE_CODE == AX_RELEASE_VERSION(3,1)) #define RHEL_RELEASE_CODE RHEL_RELEASE_VERSION(5,1) #elif (AX_RELEASE_CODE && AX_RELEASE_CODE == AX_RELEASE_VERSION(3,2)) #define RHEL_RELEASE_CODE RHEL_RELEASE_VERSION(5,3) #endif #ifndef RHEL_RELEASE_CODE /* NOTE: RHEL_RELEASE_* introduced in RHEL4.5 */ #define RHEL_RELEASE_CODE 0 #endif /* SuSE version macro is the same as Linux kernel version */ #ifndef SLE_VERSION #define SLE_VERSION(a,b,c) KERNEL_VERSION(a,b,c) #endif #ifdef CONFIG_SUSE_KERNEL #if ( LINUX_VERSION_CODE == KERNEL_VERSION(2,6,27) ) /* SLES11 GA is 2.6.27 based */ #define SLE_VERSION_CODE SLE_VERSION(11,0,0) #elif ( LINUX_VERSION_CODE == KERNEL_VERSION(2,6,32) ) /* SLES11 SP1 is 2.6.32 based */ #define SLE_VERSION_CODE SLE_VERSION(11,1,0) #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,61)) && \ (LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0))) /* SLES11 SP3 is at least 3.0.61+ based */ #define SLE_VERSION_CODE SLE_VERSION(11,3,0) #elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,28) ) /* SLES12 is at least 3.12.28+ based */ #define SLE_VERSION_CODE SLE_VERSION(12,0,0) #endif /* LINUX_VERSION_CODE == KERNEL_VERSION(x,y,z) */ #endif /* CONFIG_SUSE_KERNEL */ #ifndef SLE_VERSION_CODE #define SLE_VERSION_CODE 0 #endif /* SLE_VERSION_CODE */ /* Ubuntu release and kernel codes must be specified from Makefile */ #ifndef UBUNTU_RELEASE_VERSION #define UBUNTU_RELEASE_VERSION(a,b) (((a) * 100) + (b)) #endif #ifndef UBUNTU_KERNEL_VERSION #define UBUNTU_KERNEL_VERSION(a,b,c,abi,upload) (((a) << 40) + ((b) << 32) + ((c) << 24) + ((abi) << 8) + (upload)) #endif #ifndef UBUNTU_RELEASE_CODE #define UBUNTU_RELEASE_CODE 0 #endif #ifndef UBUNTU_KERNEL_CODE #define UBUNTU_KERNEL_CODE 0 #endif #ifdef __KLOCWORK__ #ifdef ARRAY_SIZE #undef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #endif /* __KLOCWORK__ */ /*****************************************************************************/ /* 2.4.3 => 2.4.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) /**************************************/ /* PCI DRIVER API */ #ifndef pci_set_dma_mask #define pci_set_dma_mask _kc_pci_set_dma_mask extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); #endif #ifndef pci_request_regions #define pci_request_regions _kc_pci_request_regions extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); #endif #ifndef pci_release_regions #define pci_release_regions _kc_pci_release_regions extern void _kc_pci_release_regions(struct pci_dev *pdev); #endif /**************************************/ /* NETWORK DRIVER API */ #ifndef alloc_etherdev #define alloc_etherdev _kc_alloc_etherdev extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); #endif #ifndef is_valid_ether_addr #define is_valid_ether_addr _kc_is_valid_ether_addr extern int _kc_is_valid_ether_addr(u8 *addr); #endif /**************************************/ /* MISCELLANEOUS */ #ifndef INIT_TQUEUE #define INIT_TQUEUE(_tq, _routine, _data) \ do { \ INIT_LIST_HEAD(&(_tq)->list); \ (_tq)->sync = 0; \ (_tq)->routine = _routine; \ (_tq)->data = _data; \ } while (0) #endif #endif /* 2.4.3 => 2.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) ) /* Generic MII registers. */ #define MII_BMCR 0x00 /* Basic mode control register */ #define MII_BMSR 0x01 /* Basic mode status register */ #define MII_PHYSID1 0x02 /* PHYS ID 1 */ #define MII_PHYSID2 0x03 /* PHYS ID 2 */ #define MII_ADVERTISE 0x04 /* Advertisement control reg */ #define MII_LPA 0x05 /* Link partner ability reg */ #define MII_EXPANSION 0x06 /* Expansion register */ /* Basic mode control register. */ #define BMCR_FULLDPLX 0x0100 /* Full duplex */ #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ /* Basic mode status register. */ #define BMSR_ERCAP 0x0001 /* Ext-reg capability */ #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ #define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ /* Advertisement control register. */ #define ADVERTISE_CSMA 0x0001 /* Only selector supported */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ ADVERTISE_100HALF | ADVERTISE_100FULL) /* Expansion register for auto-negotiation. */ #define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ #endif /*****************************************************************************/ /* 2.4.6 => 2.4.3 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) #ifndef pci_set_power_state #define pci_set_power_state _kc_pci_set_power_state extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); #endif #ifndef pci_enable_wake #define pci_enable_wake _kc_pci_enable_wake extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); #endif #ifndef pci_disable_device #define pci_disable_device _kc_pci_disable_device extern void _kc_pci_disable_device(struct pci_dev *pdev); #endif /* PCI PM entry point syntax changed, so don't support suspend/resume */ #undef CONFIG_PM #endif /* 2.4.6 => 2.4.3 */ #ifndef HAVE_PCI_SET_MWI #define pci_set_mwi(X) pci_write_config_word(X, \ PCI_COMMAND, adapter->hw.bus.pci_cmd_word | \ PCI_COMMAND_INVALIDATE); #define pci_clear_mwi(X) pci_write_config_word(X, \ PCI_COMMAND, adapter->hw.bus.pci_cmd_word & \ ~PCI_COMMAND_INVALIDATE); #endif /*****************************************************************************/ /* 2.4.10 => 2.4.9 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) /**************************************/ /* MODULE API */ #ifndef MODULE_LICENSE #define MODULE_LICENSE(X) #endif /**************************************/ /* OTHER */ #undef min #define min(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? _x : _y; }) #undef max #define max(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? _x : _y; }) #define min_t(type,x,y) ({ \ type _x = (x); \ type _y = (y); \ _x < _y ? _x : _y; }) #define max_t(type,x,y) ({ \ type _x = (x); \ type _y = (y); \ _x > _y ? _x : _y; }) #ifndef list_for_each_safe #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) #endif #ifndef ____cacheline_aligned_in_smp #ifdef CONFIG_SMP #define ____cacheline_aligned_in_smp ____cacheline_aligned #else #define ____cacheline_aligned_in_smp #endif /* CONFIG_SMP */ #endif #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) ) extern int _kc_snprintf(char * buf, size_t size, const char *fmt, ...); #define snprintf(buf, size, fmt, args...) _kc_snprintf(buf, size, fmt, ##args) extern int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args); #define vsnprintf(buf, size, fmt, args) _kc_vsnprintf(buf, size, fmt, args) #else /* 2.4.8 => 2.4.9 */ extern int snprintf(char * buf, size_t size, const char *fmt, ...); extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); #endif #endif /* 2.4.10 -> 2.4.6 */ /*****************************************************************************/ /* 2.4.12 => 2.4.10 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12) ) #ifndef HAVE_NETIF_MSG #define HAVE_NETIF_MSG 1 enum { NETIF_MSG_DRV = 0x0001, NETIF_MSG_PROBE = 0x0002, NETIF_MSG_LINK = 0x0004, NETIF_MSG_TIMER = 0x0008, NETIF_MSG_IFDOWN = 0x0010, NETIF_MSG_IFUP = 0x0020, NETIF_MSG_RX_ERR = 0x0040, NETIF_MSG_TX_ERR = 0x0080, NETIF_MSG_TX_QUEUED = 0x0100, NETIF_MSG_INTR = 0x0200, NETIF_MSG_TX_DONE = 0x0400, NETIF_MSG_RX_STATUS = 0x0800, NETIF_MSG_PKTDATA = 0x1000, NETIF_MSG_HW = 0x2000, NETIF_MSG_WOL = 0x4000, }; #define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV) #define netif_msg_probe(p) ((p)->msg_enable & NETIF_MSG_PROBE) #define netif_msg_link(p) ((p)->msg_enable & NETIF_MSG_LINK) #define netif_msg_timer(p) ((p)->msg_enable & NETIF_MSG_TIMER) #define netif_msg_ifdown(p) ((p)->msg_enable & NETIF_MSG_IFDOWN) #define netif_msg_ifup(p) ((p)->msg_enable & NETIF_MSG_IFUP) #define netif_msg_rx_err(p) ((p)->msg_enable & NETIF_MSG_RX_ERR) #define netif_msg_tx_err(p) ((p)->msg_enable & NETIF_MSG_TX_ERR) #define netif_msg_tx_queued(p) ((p)->msg_enable & NETIF_MSG_TX_QUEUED) #define netif_msg_intr(p) ((p)->msg_enable & NETIF_MSG_INTR) #define netif_msg_tx_done(p) ((p)->msg_enable & NETIF_MSG_TX_DONE) #define netif_msg_rx_status(p) ((p)->msg_enable & NETIF_MSG_RX_STATUS) #define netif_msg_pktdata(p) ((p)->msg_enable & NETIF_MSG_PKTDATA) #endif /* !HAVE_NETIF_MSG */ #endif /* 2.4.12 => 2.4.10 */ /*****************************************************************************/ /* 2.4.13 => 2.4.12 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) /**************************************/ /* PCI DMA MAPPING */ #ifndef virt_to_page #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) #endif #ifndef pci_map_page #define pci_map_page _kc_pci_map_page extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); #endif #ifndef pci_unmap_page #define pci_unmap_page _kc_pci_unmap_page extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); #endif /* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ #undef DMA_32BIT_MASK #define DMA_32BIT_MASK 0xffffffff #undef DMA_64BIT_MASK #define DMA_64BIT_MASK 0xffffffff /**************************************/ /* OTHER */ #ifndef cpu_relax #define cpu_relax() rep_nop() #endif struct vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; unsigned short h_vlan_proto; unsigned short h_vlan_TCI; unsigned short h_vlan_encapsulated_proto; }; #endif /* 2.4.13 => 2.4.12 */ /*****************************************************************************/ /* 2.4.17 => 2.4.12 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) #ifndef __devexit_p #define __devexit_p(x) &(x) #endif #else /* For Kernel 3.8 these are not defined - so undefine all */ #undef __devexit_p #undef __devexit #undef __devinit #undef __devinitdata #define __devexit_p(x) &(x) #define __devexit #define __devinit #define __devinitdata #endif /* 2.4.17 => 2.4.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) ) #define NETIF_MSG_HW 0x2000 #define NETIF_MSG_WOL 0x4000 #ifndef netif_msg_hw #define netif_msg_hw(p) ((p)->msg_enable & NETIF_MSG_HW) #endif #ifndef netif_msg_wol #define netif_msg_wol(p) ((p)->msg_enable & NETIF_MSG_WOL) #endif #endif /* 2.4.18 */ /*****************************************************************************/ /*****************************************************************************/ /* 2.4.20 => 2.4.19 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) /* we won't support NAPI on less than 2.4.20 */ #ifdef NAPI #undef NAPI #endif #endif /* 2.4.20 => 2.4.19 */ /*****************************************************************************/ /* 2.4.22 => 2.4.17 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) #define pci_name(x) ((x)->slot_name) #ifndef SUPPORTED_10000baseT_Full #define SUPPORTED_10000baseT_Full (1 << 12) #endif #ifndef ADVERTISED_10000baseT_Full #define ADVERTISED_10000baseT_Full (1 << 12) #endif #endif /*****************************************************************************/ /* 2.4.22 => 2.4.17 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) #ifndef IGB_NO_LRO #define IGB_NO_LRO #endif #endif /*****************************************************************************/ /*****************************************************************************/ /* 2.4.23 => 2.4.22 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) /*****************************************************************************/ #ifdef NAPI #ifndef netif_poll_disable #define netif_poll_disable(x) _kc_netif_poll_disable(x) static inline void _kc_netif_poll_disable(struct net_device *netdev) { while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { /* No hurry */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } } #endif #ifndef netif_poll_enable #define netif_poll_enable(x) _kc_netif_poll_enable(x) static inline void _kc_netif_poll_enable(struct net_device *netdev) { clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); } #endif #endif /* NAPI */ #ifndef netif_tx_disable #define netif_tx_disable(x) _kc_netif_tx_disable(x) static inline void _kc_netif_tx_disable(struct net_device *dev) { spin_lock_bh(&dev->xmit_lock); netif_stop_queue(dev); spin_unlock_bh(&dev->xmit_lock); } #endif #else /* 2.4.23 => 2.4.22 */ #define HAVE_SCTP #endif /* 2.4.23 => 2.4.22 */ /*****************************************************************************/ /* 2.6.4 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) #define ETHTOOL_OPS_COMPAT #endif /* 2.6.4 => 2.6.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) #define __user #endif /* < 2.4.27 */ /*****************************************************************************/ /* 2.5.71 => 2.4.x */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) #define sk_protocol protocol #define pci_get_device pci_find_device #endif /* 2.5.70 => 2.4.x */ /*****************************************************************************/ /* < 2.4.27 or 2.6.0 <= 2.6.5 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) #ifndef netif_msg_init #define netif_msg_init _kc_netif_msg_init static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) { /* use default */ if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) return default_msg_enable_bits; if (debug_value == 0) /* no output */ return 0; /* set low N bits */ return (1 << debug_value) -1; } #endif #endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ /*****************************************************************************/ #if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) #define netdev_priv(x) x->priv #endif /*****************************************************************************/ /* <= 2.5.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) #include #undef pci_register_driver #define pci_register_driver pci_module_init /* * Most of the dma compat code is copied/modifed from the 2.4.37 * /include/linux/libata-compat.h header file */ /* These definitions mirror those in pci.h, so they can be used * interchangeably with their PCI_ counterparts */ enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, DMA_FROM_DEVICE = 2, DMA_NONE = 3, }; struct device { struct pci_dev pdev; }; static inline struct pci_dev *to_pci_dev (struct device *dev) { return (struct pci_dev *) dev; } static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { return (struct device *) pdev; } #define pdev_printk(lvl, pdev, fmt, args...) \ printk("%s %s: " fmt, lvl, pci_name(pdev), ## args) #define dev_err(dev, fmt, args...) \ pdev_printk(KERN_ERR, to_pci_dev(dev), fmt, ## args) #define dev_info(dev, fmt, args...) \ pdev_printk(KERN_INFO, to_pci_dev(dev), fmt, ## args) #define dev_warn(dev, fmt, args...) \ pdev_printk(KERN_WARNING, to_pci_dev(dev), fmt, ## args) #define dev_notice(dev, fmt, args...) \ pdev_printk(KERN_NOTICE, to_pci_dev(dev), fmt, ## args) #define dev_dbg(dev, fmt, args...) \ pdev_printk(KERN_DEBUG, to_pci_dev(dev), fmt, ## args) /* NOTE: dangerous! we ignore the 'gfp' argument */ #define dma_alloc_coherent(dev,sz,dma,gfp) \ pci_alloc_consistent(to_pci_dev(dev),(sz),(dma)) #define dma_free_coherent(dev,sz,addr,dma_addr) \ pci_free_consistent(to_pci_dev(dev),(sz),(addr),(dma_addr)) #define dma_map_page(dev,a,b,c,d) \ pci_map_page(to_pci_dev(dev),(a),(b),(c),(d)) #define dma_unmap_page(dev,a,b,c) \ pci_unmap_page(to_pci_dev(dev),(a),(b),(c)) #define dma_map_single(dev,a,b,c) \ pci_map_single(to_pci_dev(dev),(a),(b),(c)) #define dma_unmap_single(dev,a,b,c) \ pci_unmap_single(to_pci_dev(dev),(a),(b),(c)) #define dma_map_sg(dev, sg, nents, dir) \ pci_map_sg(to_pci_dev(dev), (sg), (nents), (dir) #define dma_unmap_sg(dev, sg, nents, dir) \ pci_unmap_sg(to_pci_dev(dev), (sg), (nents), (dir) #define dma_sync_single(dev,a,b,c) \ pci_dma_sync_single(to_pci_dev(dev),(a),(b),(c)) /* for range just sync everything, that's all the pci API can do */ #define dma_sync_single_range(dev,addr,off,sz,dir) \ pci_dma_sync_single(to_pci_dev(dev),(addr),(off)+(sz),(dir)) #define dma_set_mask(dev,mask) \ pci_set_dma_mask(to_pci_dev(dev),(mask)) /* hlist_* code - double linked lists */ struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; if (next) next->pprev = pprev; } static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); n->next = NULL; n->pprev = NULL; } static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; h->first = n; n->pprev = &h->first; } static inline int hlist_empty(const struct hlist_head *h) { return !h->first; } #define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) static inline void INIT_HLIST_NODE(struct hlist_node *h) { h->next = NULL; h->pprev = NULL; } #ifndef might_sleep #define might_sleep() #endif #else static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { return &pdev->dev; } #endif /* <= 2.5.0 */ /*****************************************************************************/ /* 2.5.28 => 2.4.23 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) #include #define work_struct tq_struct #undef INIT_WORK #define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) #undef container_of #define container_of list_entry #define schedule_work schedule_task #define flush_scheduled_work flush_scheduled_tasks #define cancel_work_sync(x) flush_scheduled_work() #endif /* 2.5.28 => 2.4.17 */ /*****************************************************************************/ /* 2.6.0 => 2.5.28 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) #ifndef read_barrier_depends #define read_barrier_depends() rmb() #endif #undef get_cpu #define get_cpu() smp_processor_id() #undef put_cpu #define put_cpu() do { } while(0) #define MODULE_INFO(version, _version) #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT #define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 #endif #ifndef CONFIG_IGB_DISABLE_PACKET_SPLIT #define CONFIG_IGB_DISABLE_PACKET_SPLIT 1 #endif #define dma_set_coherent_mask(dev,mask) 1 #undef dev_put #define dev_put(dev) __dev_put(dev) #ifndef skb_fill_page_desc #define skb_fill_page_desc _kc_skb_fill_page_desc extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); #endif #undef ALIGN #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) #ifndef page_count #define page_count(p) atomic_read(&(p)->count) #endif #ifdef MAX_NUMNODES #undef MAX_NUMNODES #endif #define MAX_NUMNODES 1 /* find_first_bit and find_next bit are not defined for most * 2.4 kernels (except for the redhat 2.4.21 kernels */ #include #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) #undef find_next_bit #define find_next_bit _kc_find_next_bit extern unsigned long _kc_find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) #ifndef netdev_name static inline const char *_kc_netdev_name(const struct net_device *dev) { if (strchr(dev->name, '%')) return "(unregistered net_device)"; return dev->name; } #define netdev_name(netdev) _kc_netdev_name(netdev) #endif /* netdev_name */ #ifndef strlcpy #define strlcpy _kc_strlcpy extern size_t _kc_strlcpy(char *dest, const char *src, size_t size); #endif /* strlcpy */ #ifndef do_div #if BITS_PER_LONG == 64 # define do_div(n,base) ({ \ uint32_t __base = (base); \ uint32_t __rem; \ __rem = ((uint64_t)(n)) % __base; \ (n) = ((uint64_t)(n)) / __base; \ __rem; \ }) #elif BITS_PER_LONG == 32 extern uint32_t _kc__div64_32(uint64_t *dividend, uint32_t divisor); # define do_div(n,base) ({ \ uint32_t __base = (base); \ uint32_t __rem; \ if (likely(((n) >> 32) == 0)) { \ __rem = (uint32_t)(n) % __base; \ (n) = (uint32_t)(n) / __base; \ } else \ __rem = _kc__div64_32(&(n), __base); \ __rem; \ }) #else /* BITS_PER_LONG == ?? */ # error do_div() does not yet support the C64 #endif /* BITS_PER_LONG */ #endif /* do_div */ #ifndef NSEC_PER_SEC #define NSEC_PER_SEC 1000000000L #endif #undef HAVE_I2C_SUPPORT #else /* 2.6.0 */ #if IS_ENABLED(CONFIG_I2C_ALGOBIT) && \ (RHEL_RELEASE_CODE && (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,9))) #define HAVE_I2C_SUPPORT #endif /* IS_ENABLED(CONFIG_I2C_ALGOBIT) */ #endif /* 2.6.0 => 2.5.28 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ) #define dma_pool pci_pool #define dma_pool_destroy pci_pool_destroy #define dma_pool_alloc pci_pool_alloc #define dma_pool_free pci_pool_free #define dma_pool_create(name,dev,size,align,allocation) \ pci_pool_create((name),to_pci_dev(dev),(size),(align),(allocation)) #endif /* < 2.6.3 */ /*****************************************************************************/ /* 2.6.4 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) #define MODULE_VERSION(_version) MODULE_INFO(version, _version) #endif /* 2.6.4 => 2.6.0 */ /*****************************************************************************/ /* 2.6.5 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) #define dma_sync_single_for_cpu dma_sync_single #define dma_sync_single_for_device dma_sync_single #define dma_sync_single_range_for_cpu dma_sync_single_range #define dma_sync_single_range_for_device dma_sync_single_range #ifndef pci_dma_mapping_error #define pci_dma_mapping_error _kc_pci_dma_mapping_error static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) { return dma_addr == 0; } #endif #endif /* 2.6.5 => 2.6.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) extern int _kc_scnprintf(char * buf, size_t size, const char *fmt, ...); #define scnprintf(buf, size, fmt, args...) _kc_scnprintf(buf, size, fmt, ##args) #endif /* < 2.6.4 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6) ) /* taken from 2.6 include/linux/bitmap.h */ #undef bitmap_zero #define bitmap_zero _kc_bitmap_zero static inline void _kc_bitmap_zero(unsigned long *dst, int nbits) { if (nbits <= BITS_PER_LONG) *dst = 0UL; else { int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); memset(dst, 0, len); } } #define random_ether_addr _kc_random_ether_addr static inline void _kc_random_ether_addr(u8 *addr) { get_random_bytes(addr, ETH_ALEN); addr[0] &= 0xfe; /* clear multicast */ addr[0] |= 0x02; /* set local assignment */ } #define page_to_nid(x) 0 #endif /* < 2.6.6 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) #undef if_mii #define if_mii _kc_if_mii static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) { return (struct mii_ioctl_data *) &rq->ifr_ifru; } #ifndef __force #define __force #endif #endif /* < 2.6.7 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) #ifndef PCI_EXP_DEVCTL #define PCI_EXP_DEVCTL 8 #endif #ifndef PCI_EXP_DEVCTL_CERE #define PCI_EXP_DEVCTL_CERE 0x0001 #endif #define PCI_EXP_FLAGS 2 /* Capabilities register */ #define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */ #define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */ #define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */ #define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */ #define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ #define PCI_EXP_DEVCAP 4 /* Device capabilities */ #define PCI_EXP_DEVSTA 10 /* Device Status */ #define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ schedule_timeout((x * HZ)/1000 + 2); \ } while (0) #endif /* < 2.6.8 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) #include #define __iomem #ifndef kcalloc #define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) extern void *_kc_kzalloc(size_t size, int flags); #endif #define MSEC_PER_SEC 1000L static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) { #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) return (MSEC_PER_SEC / HZ) * j; #elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); #else return (j * MSEC_PER_SEC) / HZ; #endif } static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) { if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) return MAX_JIFFY_OFFSET; #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); #elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) return m * (HZ / MSEC_PER_SEC); #else return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; #endif } #define msleep_interruptible _kc_msleep_interruptible static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) { unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; while (timeout && !signal_pending(current)) { __set_current_state(TASK_INTERRUPTIBLE); timeout = schedule_timeout(timeout); } return _kc_jiffies_to_msecs(timeout); } /* Basic mode control register. */ #define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ #ifndef __le16 #define __le16 u16 #endif #ifndef __le32 #define __le32 u32 #endif #ifndef __le64 #define __le64 u64 #endif #ifndef __be16 #define __be16 u16 #endif #ifndef __be32 #define __be32 u32 #endif #ifndef __be64 #define __be64 u64 #endif static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) { return (struct vlan_ethhdr *)skb->mac.raw; } /* Wake-On-Lan options. */ #define WAKE_PHY (1 << 0) #define WAKE_UCAST (1 << 1) #define WAKE_MCAST (1 << 2) #define WAKE_BCAST (1 << 3) #define WAKE_ARP (1 << 4) #define WAKE_MAGIC (1 << 5) #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ #define skb_header_pointer _kc_skb_header_pointer static inline void *_kc_skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) { int hlen = skb_headlen(skb); if (hlen - offset >= len) return skb->data + offset; #ifdef MAX_SKB_FRAGS if (skb_copy_bits(skb, offset, buffer, len) < 0) return NULL; return buffer; #else return NULL; #endif #ifndef NETDEV_TX_OK #define NETDEV_TX_OK 0 #endif #ifndef NETDEV_TX_BUSY #define NETDEV_TX_BUSY 1 #endif #ifndef NETDEV_TX_LOCKED #define NETDEV_TX_LOCKED -1 #endif } #ifndef __bitwise #define __bitwise #endif #endif /* < 2.6.9 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) #ifdef module_param_array_named #undef module_param_array_named #define module_param_array_named(name, array, type, nump, perm) \ static struct kparam_array __param_arr_##name \ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ sizeof(array[0]), array }; \ module_param_call(name, param_array_set, param_array_get, \ &__param_arr_##name, perm) #endif /* module_param_array_named */ /* * num_online is broken for all < 2.6.10 kernels. This is needed to support * Node module parameter of ixgbe. */ #undef num_online_nodes #define num_online_nodes(n) 1 extern DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES); #undef node_online_map #define node_online_map _kcompat_node_online_map #define pci_get_class pci_find_class #endif /* < 2.6.10 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) #define PCI_D0 0 #define PCI_D1 1 #define PCI_D2 2 #define PCI_D3hot 3 #define PCI_D3cold 4 typedef int pci_power_t; #define pci_choose_state(pdev,state) state #define PMSG_SUSPEND 3 #define PCI_EXP_LNKCTL 16 #undef NETIF_F_LLTX #ifndef ARCH_HAS_PREFETCH #define prefetch(X) #endif #ifndef NET_IP_ALIGN #define NET_IP_ALIGN 2 #endif #define KC_USEC_PER_SEC 1000000L #define usecs_to_jiffies _kc_usecs_to_jiffies static inline unsigned int _kc_jiffies_to_usecs(const unsigned long j) { #if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) return (KC_USEC_PER_SEC / HZ) * j; #elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) return (j + (HZ / KC_USEC_PER_SEC) - 1)/(HZ / KC_USEC_PER_SEC); #else return (j * KC_USEC_PER_SEC) / HZ; #endif } static inline unsigned long _kc_usecs_to_jiffies(const unsigned int m) { if (m > _kc_jiffies_to_usecs(MAX_JIFFY_OFFSET)) return MAX_JIFFY_OFFSET; #if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) return (m + (KC_USEC_PER_SEC / HZ) - 1) / (KC_USEC_PER_SEC / HZ); #elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) return m * (HZ / KC_USEC_PER_SEC); #else return (m * HZ + KC_USEC_PER_SEC - 1) / KC_USEC_PER_SEC; #endif } #define PCI_EXP_LNKCAP 12 /* Link Capabilities */ #define PCI_EXP_LNKSTA 18 /* Link Status */ #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ #define PCI_EXP_SLTCTL 24 /* Slot Control */ #define PCI_EXP_SLTSTA 26 /* Slot Status */ #define PCI_EXP_RTCTL 28 /* Root Control */ #define PCI_EXP_RTCAP 30 /* Root Capabilities */ #define PCI_EXP_RTSTA 32 /* Root Status */ #endif /* < 2.6.11 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) #include #define USE_REBOOT_NOTIFIER /* Generic MII registers. */ #define MII_CTRL1000 0x09 /* 1000BASE-T control */ #define MII_STAT1000 0x0a /* 1000BASE-T status */ /* Advertisement control register. */ #define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ #define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ /* Link partner ability register. */ #define LPA_PAUSE_CAP 0x0400 /* Can pause */ #define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */ /* 1000BASE-T Control register */ #define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ #define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */ /* 1000BASE-T Status register */ #define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */ #define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */ #ifndef is_zero_ether_addr #define is_zero_ether_addr _kc_is_zero_ether_addr static inline int _kc_is_zero_ether_addr(const u8 *addr) { return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); } #endif /* is_zero_ether_addr */ #ifndef is_multicast_ether_addr #define is_multicast_ether_addr _kc_is_multicast_ether_addr static inline int _kc_is_multicast_ether_addr(const u8 *addr) { return addr[0] & 0x01; } #endif /* is_multicast_ether_addr */ #endif /* < 2.6.12 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) #ifndef kstrdup #define kstrdup _kc_kstrdup extern char *_kc_kstrdup(const char *s, unsigned int gfp); #endif #endif /* < 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) #define pm_message_t u32 #ifndef kzalloc #define kzalloc _kc_kzalloc extern void *_kc_kzalloc(size_t size, int flags); #endif /* Generic MII registers. */ #define MII_ESTATUS 0x0f /* Extended Status */ /* Basic mode status register. */ #define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ /* Extended status register. */ #define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ #define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ #define SUPPORTED_Pause (1 << 13) #define SUPPORTED_Asym_Pause (1 << 14) #define ADVERTISED_Pause (1 << 13) #define ADVERTISED_Asym_Pause (1 << 14) #if (!(RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,3)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0)))) #if ((LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9)) && !defined(gfp_t)) #define gfp_t unsigned #else typedef unsigned gfp_t; #endif #endif /* !RHEL4.3->RHEL5.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) ) #ifdef CONFIG_X86_64 #define dma_sync_single_range_for_cpu(dev, addr, off, sz, dir) \ dma_sync_single_for_cpu((dev), (addr), (off) + (sz), (dir)) #define dma_sync_single_range_for_device(dev, addr, off, sz, dir) \ dma_sync_single_for_device((dev), (addr), (off) + (sz), (dir)) #endif #endif #endif /* < 2.6.14 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) ) #ifndef vmalloc_node #define vmalloc_node(a,b) vmalloc(a) #endif /* vmalloc_node*/ #define setup_timer(_timer, _function, _data) \ do { \ (_timer)->function = _function; \ (_timer)->data = _data; \ init_timer(_timer); \ } while (0) #ifndef device_can_wakeup #define device_can_wakeup(dev) (1) #endif #ifndef device_set_wakeup_enable #define device_set_wakeup_enable(dev, val) do{}while(0) #endif #ifndef device_init_wakeup #define device_init_wakeup(dev,val) do {} while (0) #endif static inline unsigned _kc_compare_ether_addr(const u8 *addr1, const u8 *addr2) { const u16 *a = (const u16 *) addr1; const u16 *b = (const u16 *) addr2; return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; } #undef compare_ether_addr #define compare_ether_addr(addr1, addr2) _kc_compare_ether_addr(addr1, addr2) #endif /* < 2.6.15 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) #undef DEFINE_MUTEX #define DEFINE_MUTEX(x) DECLARE_MUTEX(x) #define mutex_lock(x) down_interruptible(x) #define mutex_unlock(x) up(x) #ifndef ____cacheline_internodealigned_in_smp #ifdef CONFIG_SMP #define ____cacheline_internodealigned_in_smp ____cacheline_aligned_in_smp #else #define ____cacheline_internodealigned_in_smp #endif /* CONFIG_SMP */ #endif /* ____cacheline_internodealigned_in_smp */ #undef HAVE_PCI_ERS #else /* 2.6.16 and above */ #undef HAVE_PCI_ERS #define HAVE_PCI_ERS #if ( SLE_VERSION_CODE && SLE_VERSION_CODE == SLE_VERSION(10,4,0) ) #ifdef device_can_wakeup #undef device_can_wakeup #endif /* device_can_wakeup */ #define device_can_wakeup(dev) 1 #endif /* SLE_VERSION(10,4,0) */ #endif /* < 2.6.16 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) ) #ifndef dev_notice #define dev_notice(dev, fmt, args...) \ dev_printk(KERN_NOTICE, dev, fmt, ## args) #endif #ifndef first_online_node #define first_online_node 0 #endif #ifndef NET_SKB_PAD #define NET_SKB_PAD 16 #endif #endif /* < 2.6.17 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) #ifndef IRQ_HANDLED #define irqreturn_t void #define IRQ_HANDLED #define IRQ_NONE #endif #ifndef IRQF_PROBE_SHARED #ifdef SA_PROBEIRQ #define IRQF_PROBE_SHARED SA_PROBEIRQ #else #define IRQF_PROBE_SHARED 0 #endif #endif #ifndef IRQF_SHARED #define IRQF_SHARED SA_SHIRQ #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #ifndef FIELD_SIZEOF #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #endif #ifndef skb_is_gso #ifdef NETIF_F_TSO #define skb_is_gso _kc_skb_is_gso static inline int _kc_skb_is_gso(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_size; } #else #define skb_is_gso(a) 0 #endif #endif #ifndef resource_size_t #define resource_size_t unsigned long #endif #ifdef skb_pad #undef skb_pad #endif #define skb_pad(x,y) _kc_skb_pad(x, y) int _kc_skb_pad(struct sk_buff *skb, int pad); #ifdef skb_padto #undef skb_padto #endif #define skb_padto(x,y) _kc_skb_padto(x, y) static inline int _kc_skb_padto(struct sk_buff *skb, unsigned int len) { unsigned int size = skb->len; if(likely(size >= len)) return 0; return _kc_skb_pad(skb, len - size); } #ifndef DECLARE_PCI_UNMAP_ADDR #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ u32 LEN_NAME #define pci_unmap_addr(PTR, ADDR_NAME) \ ((PTR)->ADDR_NAME) #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ (((PTR)->ADDR_NAME) = (VAL)) #define pci_unmap_len(PTR, LEN_NAME) \ ((PTR)->LEN_NAME) #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ (((PTR)->LEN_NAME) = (VAL)) #endif /* DECLARE_PCI_UNMAP_ADDR */ #endif /* < 2.6.18 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,0))) #define i_private u.generic_ip #endif /* >= RHEL 5.0 */ #ifndef DIV_ROUND_UP #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #endif #ifndef __ALIGN_MASK #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #endif #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) #if (!((RHEL_RELEASE_CODE && \ ((RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) && \ RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0)) || \ (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,0)))))) typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); #endif #if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) #undef CONFIG_INET_LRO #undef CONFIG_INET_LRO_MODULE #ifdef IXGBE_FCOE #undef CONFIG_FCOE #undef CONFIG_FCOE_MODULE #endif /* IXGBE_FCOE */ #endif typedef irqreturn_t (*new_handler_t)(int, void*); static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) #else /* 2.4.x */ typedef void (*irq_handler_t)(int, void*, struct pt_regs *); typedef void (*new_handler_t)(int, void*); static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) #endif /* >= 2.5.x */ { irq_handler_t new_handler = (irq_handler_t) handler; return request_irq(irq, new_handler, flags, devname, dev_id); } #undef request_irq #define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) #define irq_handler_t new_handler_t /* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4))) #define PCIE_CONFIG_SPACE_LEN 256 #define PCI_CONFIG_SPACE_LEN 64 #define PCIE_LINK_STATUS 0x12 #define pci_config_space_ich8lan() do {} while(0) #undef pci_save_state extern int _kc_pci_save_state(struct pci_dev *); #define pci_save_state(pdev) _kc_pci_save_state(pdev) #undef pci_restore_state extern void _kc_pci_restore_state(struct pci_dev *); #define pci_restore_state(pdev) _kc_pci_restore_state(pdev) #endif /* !(RHEL_RELEASE_CODE >= RHEL 5.4) */ #ifdef HAVE_PCI_ERS #undef free_netdev extern void _kc_free_netdev(struct net_device *); #define free_netdev(netdev) _kc_free_netdev(netdev) #endif static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) { return 0; } #define pci_disable_pcie_error_reporting(dev) do {} while (0) #define pci_cleanup_aer_uncorrect_error_status(dev) do {} while (0) extern void *_kc_kmemdup(const void *src, size_t len, unsigned gfp); #define kmemdup(src, len, gfp) _kc_kmemdup(src, len, gfp) #ifndef bool #define bool _Bool #define true 1 #define false 0 #endif #else /* 2.6.19 */ #include #include #endif /* < 2.6.19 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) #undef INIT_WORK #define INIT_WORK(_work, _func) \ do { \ INIT_LIST_HEAD(&(_work)->entry); \ (_work)->pending = 0; \ (_work)->func = (void (*)(void *))_func; \ (_work)->data = _work; \ init_timer(&(_work)->timer); \ } while (0) #endif #ifndef PCI_VDEVICE #define PCI_VDEVICE(ven, dev) \ PCI_VENDOR_ID_##ven, (dev), \ PCI_ANY_ID, PCI_ANY_ID, 0, 0 #endif #ifndef PCI_VENDOR_ID_INTEL #define PCI_VENDOR_ID_INTEL 0x8086 #endif #ifndef round_jiffies #define round_jiffies(x) x #endif #define csum_offset csum #define HAVE_EARLY_VMALLOC_NODE #define dev_to_node(dev) -1 #undef set_dev_node /* remove compiler warning with b=b, for unused variable */ #define set_dev_node(a, b) do { (b) = (b); } while(0) #if (!(RHEL_RELEASE_CODE && \ (((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(4,7)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0))) || \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,6)))) && \ !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(10,2,0))) typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __wsum; #endif #if (!(RHEL_RELEASE_CODE && \ (((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(4,7)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0))) || \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4)))) && \ !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(10,2,0))) static inline __wsum csum_unfold(__sum16 n) { return (__force __wsum)n; } #endif #else /* < 2.6.20 */ #define HAVE_DEVICE_NUMA_NODE #endif /* < 2.6.20 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) #define to_net_dev(class) container_of(class, struct net_device, class_dev) #define NETDEV_CLASS_DEV #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5))) #define vlan_group_get_device(vg, id) (vg->vlan_devices[id]) #define vlan_group_set_device(vg, id, dev) \ do { \ if (vg) vg->vlan_devices[id] = dev; \ } while (0) #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5)) */ #define pci_channel_offline(pdev) (pdev->error_state && \ pdev->error_state != pci_channel_io_normal) #define pci_request_selected_regions(pdev, bars, name) \ pci_request_regions(pdev, name) #define pci_release_selected_regions(pdev, bars) pci_release_regions(pdev); #ifndef __aligned #define __aligned(x) __attribute__((aligned(x))) #endif extern struct pci_dev *_kc_netdev_to_pdev(struct net_device *netdev); #define netdev_to_dev(netdev) \ pci_dev_to_dev(_kc_netdev_to_pdev(netdev)) #else static inline struct device *netdev_to_dev(struct net_device *netdev) { return &netdev->dev; } #endif /* < 2.6.21 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) #define tcp_hdr(skb) (skb->h.th) #define tcp_hdrlen(skb) (skb->h.th->doff << 2) #define skb_transport_offset(skb) (skb->h.raw - skb->data) #define skb_transport_header(skb) (skb->h.raw) #define ipv6_hdr(skb) (skb->nh.ipv6h) #define ip_hdr(skb) (skb->nh.iph) #define skb_network_offset(skb) (skb->nh.raw - skb->data) #define skb_network_header(skb) (skb->nh.raw) #define skb_tail_pointer(skb) skb->tail #define skb_reset_tail_pointer(skb) \ do { \ skb->tail = skb->data; \ } while (0) #define skb_set_tail_pointer(skb, offset) \ do { \ skb->tail = skb->data + offset; \ } while (0) #define skb_copy_to_linear_data(skb, from, len) \ memcpy(skb->data, from, len) #define skb_copy_to_linear_data_offset(skb, offset, from, len) \ memcpy(skb->data + offset, from, len) #define skb_network_header_len(skb) (skb->h.raw - skb->nh.raw) #define pci_register_driver pci_module_init #define skb_mac_header(skb) skb->mac.raw #ifdef NETIF_F_MULTI_QUEUE #ifndef alloc_etherdev_mq #define alloc_etherdev_mq(_a, _b) alloc_etherdev(_a) #endif #endif /* NETIF_F_MULTI_QUEUE */ #ifndef ETH_FCS_LEN #define ETH_FCS_LEN 4 #endif #define cancel_work_sync(x) flush_scheduled_work() #ifndef udp_hdr #define udp_hdr _udp_hdr static inline struct udphdr *_udp_hdr(const struct sk_buff *skb) { return (struct udphdr *)skb_transport_header(skb); } #endif #ifdef cpu_to_be16 #undef cpu_to_be16 #endif #define cpu_to_be16(x) __constant_htons(x) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,1))) enum { DUMP_PREFIX_NONE, DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,1)) */ #ifndef hex_asc #define hex_asc(x) "0123456789abcdef"[x] #endif #include extern void _kc_print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii); #define print_hex_dump(lvl, s, t, r, g, b, l, a) \ _kc_print_hex_dump(lvl, s, t, r, g, b, l, a) #ifndef ADVERTISED_2500baseX_Full #define ADVERTISED_2500baseX_Full (1 << 15) #endif #ifndef SUPPORTED_2500baseX_Full #define SUPPORTED_2500baseX_Full (1 << 15) #endif #ifdef HAVE_I2C_SUPPORT #include #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5))) struct i2c_board_info { char driver_name[KOBJ_NAME_LEN]; char type[I2C_NAME_SIZE]; unsigned short flags; unsigned short addr; void *platform_data; }; #define I2C_BOARD_INFO(driver, dev_addr) .driver_name = (driver),\ .addr = (dev_addr) #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5)) */ #define i2c_new_device(adap, info) _kc_i2c_new_device(adap, info) extern struct i2c_client * _kc_i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); #endif /* HAVE_I2C_SUPPORT */ #else /* 2.6.22 */ #define ETH_TYPE_TRANS_SETS_DEV #define HAVE_NETDEV_STATS_IN_NETDEV #endif /* < 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) ) #undef SET_MODULE_OWNER #define SET_MODULE_OWNER(dev) do { } while (0) #endif /* > 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) #define netif_subqueue_stopped(_a, _b) 0 #ifndef PTR_ALIGN #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) #endif #ifndef CONFIG_PM_SLEEP #define CONFIG_PM_SLEEP CONFIG_PM #endif #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) ) #define HAVE_ETHTOOL_GET_PERM_ADDR #endif /* 2.6.14 through 2.6.22 */ #endif /* < 2.6.23 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) #ifndef ETH_FLAG_LRO #define ETH_FLAG_LRO NETIF_F_LRO #endif /* if GRO is supported then the napi struct must already exist */ #ifndef NETIF_F_GRO /* NAPI API changes in 2.6.24 break everything */ struct napi_struct { /* used to look up the real NAPI polling routine */ int (*poll)(struct napi_struct *, int); struct net_device *dev; int weight; }; #endif #ifdef NAPI extern int __kc_adapter_clean(struct net_device *, int *); extern struct net_device *napi_to_poll_dev(const struct napi_struct *napi); #define netif_napi_add(_netdev, _napi, _poll, _weight) \ do { \ struct napi_struct *__napi = (_napi); \ struct net_device *poll_dev = napi_to_poll_dev(__napi); \ poll_dev->poll = &(__kc_adapter_clean); \ poll_dev->priv = (_napi); \ poll_dev->weight = (_weight); \ set_bit(__LINK_STATE_RX_SCHED, &poll_dev->state); \ set_bit(__LINK_STATE_START, &poll_dev->state);\ dev_hold(poll_dev); \ __napi->poll = &(_poll); \ __napi->weight = (_weight); \ __napi->dev = (_netdev); \ } while (0) #define netif_napi_del(_napi) \ do { \ struct net_device *poll_dev = napi_to_poll_dev(_napi); \ WARN_ON(!test_bit(__LINK_STATE_RX_SCHED, &poll_dev->state)); \ dev_put(poll_dev); \ memset(poll_dev, 0, sizeof(struct net_device));\ } while (0) #define napi_schedule_prep(_napi) \ (netif_running((_napi)->dev) && netif_rx_schedule_prep(napi_to_poll_dev(_napi))) #define napi_schedule(_napi) \ do { \ if (napi_schedule_prep(_napi)) \ __netif_rx_schedule(napi_to_poll_dev(_napi)); \ } while (0) #define napi_enable(_napi) netif_poll_enable(napi_to_poll_dev(_napi)) #define napi_disable(_napi) netif_poll_disable(napi_to_poll_dev(_napi)) #ifdef CONFIG_SMP static inline void napi_synchronize(const struct napi_struct *n) { struct net_device *dev = napi_to_poll_dev(n); while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) { /* No hurry. */ msleep(1); } } #else #define napi_synchronize(n) barrier() #endif /* CONFIG_SMP */ #define __napi_schedule(_napi) __netif_rx_schedule(napi_to_poll_dev(_napi)) #ifndef NETIF_F_GRO #define napi_complete(_napi) netif_rx_complete(napi_to_poll_dev(_napi)) #else #define napi_complete(_napi) \ do { \ napi_gro_flush(_napi); \ netif_rx_complete(napi_to_poll_dev(_napi)); \ } while (0) #endif /* NETIF_F_GRO */ #else /* NAPI */ #define netif_napi_add(_netdev, _napi, _poll, _weight) \ do { \ struct napi_struct *__napi = _napi; \ _netdev->poll = &(_poll); \ _netdev->weight = (_weight); \ __napi->poll = &(_poll); \ __napi->weight = (_weight); \ __napi->dev = (_netdev); \ } while (0) #define netif_napi_del(_a) do {} while (0) #endif /* NAPI */ #undef dev_get_by_name #define dev_get_by_name(_a, _b) dev_get_by_name(_b) #define __netif_subqueue_stopped(_a, _b) netif_subqueue_stopped(_a, _b) #ifndef DMA_BIT_MASK #define DMA_BIT_MASK(n) (((n) == 64) ? DMA_64BIT_MASK : ((1ULL<<(n))-1)) #endif #ifdef NETIF_F_TSO6 #define skb_is_gso_v6 _kc_skb_is_gso_v6 static inline int _kc_skb_is_gso_v6(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; } #endif /* NETIF_F_TSO6 */ #ifndef KERN_CONT #define KERN_CONT "" #endif #ifndef pr_err #define pr_err(fmt, arg...) \ printk(KERN_ERR fmt, ##arg) #endif #else /* < 2.6.24 */ #define HAVE_ETHTOOL_GET_SSET_COUNT #define HAVE_NETDEV_NAPI_LIST #endif /* < 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) ) #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ) #include #else /* >= 3.2.0 */ #include #endif /* else >= 3.2.0 */ #endif /* > 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ) #define PM_QOS_CPU_DMA_LATENCY 1 #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ) #include #define PM_QOS_DEFAULT_VALUE INFINITE_LATENCY #define pm_qos_add_requirement(pm_qos_class, name, value) \ set_acceptable_latency(name, value) #define pm_qos_remove_requirement(pm_qos_class, name) \ remove_acceptable_latency(name) #define pm_qos_update_requirement(pm_qos_class, name, value) \ modify_acceptable_latency(name, value) #else #define PM_QOS_DEFAULT_VALUE -1 #define pm_qos_add_requirement(pm_qos_class, name, value) #define pm_qos_remove_requirement(pm_qos_class, name) #define pm_qos_update_requirement(pm_qos_class, name, value) { \ if (value != PM_QOS_DEFAULT_VALUE) { \ printk(KERN_WARNING "%s: unable to set PM QoS requirement\n", \ pci_name(adapter->pdev)); \ } \ } #endif /* > 2.6.18 */ #define pci_enable_device_mem(pdev) pci_enable_device(pdev) #ifndef DEFINE_PCI_DEVICE_TABLE #define DEFINE_PCI_DEVICE_TABLE(_table) struct pci_device_id _table[] #endif /* DEFINE_PCI_DEVICE_TABLE */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) #ifndef IGB_PROCFS #define IGB_PROCFS #endif /* IGB_PROCFS */ #endif /* >= 2.6.0 */ #else /* < 2.6.25 */ #if IS_ENABLED(CONFIG_HWMON) #ifndef IGB_HWMON #define IGB_HWMON #endif /* IGB_HWMON */ #endif /* CONFIG_HWMON */ #endif /* < 2.6.25 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) #ifndef clamp_t #define clamp_t(type, val, min, max) ({ \ type __val = (val); \ type __min = (min); \ type __max = (max); \ __val = __val < __min ? __min : __val; \ __val > __max ? __max : __val; }) #endif /* clamp_t */ #undef kzalloc_node #define kzalloc_node(_size, _flags, _node) kzalloc(_size, _flags) extern void _kc_pci_disable_link_state(struct pci_dev *dev, int state); #define pci_disable_link_state(p, s) _kc_pci_disable_link_state(p, s) #else /* < 2.6.26 */ #include #define HAVE_NETDEV_VLAN_FEATURES #ifndef PCI_EXP_LNKCAP_ASPMS #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ #endif /* PCI_EXP_LNKCAP_ASPMS */ #endif /* < 2.6.26 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) static inline void _kc_ethtool_cmd_speed_set(struct ethtool_cmd *ep, __u32 speed) { ep->speed = (__u16)speed; /* ep->speed_hi = (__u16)(speed >> 16); */ } #define ethtool_cmd_speed_set _kc_ethtool_cmd_speed_set static inline __u32 _kc_ethtool_cmd_speed(struct ethtool_cmd *ep) { /* no speed_hi before 2.6.27, and probably no need for it yet */ return (__u32)ep->speed; } #define ethtool_cmd_speed _kc_ethtool_cmd_speed #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) ) #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) && defined(CONFIG_PM)) #define ANCIENT_PM 1 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)) && \ (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) && \ defined(CONFIG_PM_SLEEP)) #define NEWER_PM 1 #endif #if defined(ANCIENT_PM) || defined(NEWER_PM) #undef device_set_wakeup_enable #define device_set_wakeup_enable(dev, val) \ do { \ u16 pmc = 0; \ int pm = pci_find_capability(adapter->pdev, PCI_CAP_ID_PM); \ if (pm) { \ pci_read_config_word(adapter->pdev, pm + PCI_PM_PMC, \ &pmc); \ } \ (dev)->power.can_wakeup = !!(pmc >> 11); \ (dev)->power.should_wakeup = (val && (pmc >> 11)); \ } while (0) #endif /* 2.6.15-2.6.22 and CONFIG_PM or 2.6.23-2.6.25 and CONFIG_PM_SLEEP */ #endif /* 2.6.15 through 2.6.27 */ #ifndef netif_napi_del #define netif_napi_del(_a) do {} while (0) #ifdef NAPI #ifdef CONFIG_NETPOLL #undef netif_napi_del #define netif_napi_del(_a) list_del(&(_a)->dev_list); #endif #endif #endif /* netif_napi_del */ #ifdef dma_mapping_error #undef dma_mapping_error #endif #define dma_mapping_error(dev, dma_addr) pci_dma_mapping_error(dma_addr) #ifdef CONFIG_NETDEVICES_MULTIQUEUE #define HAVE_TX_MQ #endif #ifdef HAVE_TX_MQ extern void _kc_netif_tx_stop_all_queues(struct net_device *); extern void _kc_netif_tx_wake_all_queues(struct net_device *); extern void _kc_netif_tx_start_all_queues(struct net_device *); #define netif_tx_stop_all_queues(a) _kc_netif_tx_stop_all_queues(a) #define netif_tx_wake_all_queues(a) _kc_netif_tx_wake_all_queues(a) #define netif_tx_start_all_queues(a) _kc_netif_tx_start_all_queues(a) #undef netif_stop_subqueue #define netif_stop_subqueue(_ndev,_qi) do { \ if (netif_is_multiqueue((_ndev))) \ netif_stop_subqueue((_ndev), (_qi)); \ else \ netif_stop_queue((_ndev)); \ } while (0) #undef netif_start_subqueue #define netif_start_subqueue(_ndev,_qi) do { \ if (netif_is_multiqueue((_ndev))) \ netif_start_subqueue((_ndev), (_qi)); \ else \ netif_start_queue((_ndev)); \ } while (0) #else /* HAVE_TX_MQ */ #define netif_tx_stop_all_queues(a) netif_stop_queue(a) #define netif_tx_wake_all_queues(a) netif_wake_queue(a) #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) ) #define netif_tx_start_all_queues(a) netif_start_queue(a) #else #define netif_tx_start_all_queues(a) do {} while (0) #endif #define netif_stop_subqueue(_ndev,_qi) netif_stop_queue((_ndev)) #define netif_start_subqueue(_ndev,_qi) netif_start_queue((_ndev)) #endif /* HAVE_TX_MQ */ #ifndef NETIF_F_MULTI_QUEUE #define NETIF_F_MULTI_QUEUE 0 #define netif_is_multiqueue(a) 0 #define netif_wake_subqueue(a, b) #endif /* NETIF_F_MULTI_QUEUE */ #ifndef __WARN_printf extern void __kc_warn_slowpath(const char *file, const int line, const char *fmt, ...) __attribute__((format(printf, 3, 4))); #define __WARN_printf(arg...) __kc_warn_slowpath(__FILE__, __LINE__, arg) #endif /* __WARN_printf */ #ifndef WARN #define WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ __WARN_printf(format); \ unlikely(__ret_warn_on); \ }) #endif /* WARN */ #undef HAVE_IXGBE_DEBUG_FS #undef HAVE_IGB_DEBUG_FS #else /* < 2.6.27 */ #define HAVE_TX_MQ #define HAVE_NETDEV_SELECT_QUEUE #ifdef CONFIG_DEBUG_FS #define HAVE_IXGBE_DEBUG_FS #define HAVE_IGB_DEBUG_FS #endif /* CONFIG_DEBUG_FS */ #endif /* < 2.6.27 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) #define pci_ioremap_bar(pdev, bar) ioremap(pci_resource_start(pdev, bar), \ pci_resource_len(pdev, bar)) #define pci_wake_from_d3 _kc_pci_wake_from_d3 #define pci_prepare_to_sleep _kc_pci_prepare_to_sleep extern int _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable); extern int _kc_pci_prepare_to_sleep(struct pci_dev *dev); #define netdev_alloc_page(a) alloc_page(GFP_ATOMIC) #ifndef __skb_queue_head_init static inline void __kc_skb_queue_head_init(struct sk_buff_head *list) { list->prev = list->next = (struct sk_buff *)list; list->qlen = 0; } #define __skb_queue_head_init(_q) __kc_skb_queue_head_init(_q) #endif #define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ #endif /* < 2.6.28 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) #ifndef swap #define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) #endif #define pci_request_selected_regions_exclusive(pdev, bars, name) \ pci_request_selected_regions(pdev, bars, name) #ifndef CONFIG_NR_CPUS #define CONFIG_NR_CPUS 1 #endif /* CONFIG_NR_CPUS */ #ifndef pcie_aspm_enabled #define pcie_aspm_enabled() (1) #endif /* pcie_aspm_enabled */ #define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */ #ifndef pci_clear_master extern void _kc_pci_clear_master(struct pci_dev *dev); #define pci_clear_master(dev) _kc_pci_clear_master(dev) #endif #ifndef PCI_EXP_LNKCTL_ASPMC #define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */ #endif #else /* < 2.6.29 */ #ifndef HAVE_NET_DEVICE_OPS #define HAVE_NET_DEVICE_OPS #endif #ifdef CONFIG_DCB #define HAVE_PFC_MODE_ENABLE #endif /* CONFIG_DCB */ #endif /* < 2.6.29 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) #define skb_rx_queue_recorded(a) false #define skb_get_rx_queue(a) 0 #define skb_record_rx_queue(a, b) do {} while (0) #define skb_tx_hash(n, s) ___kc_skb_tx_hash((n), (s), (n)->real_num_tx_queues) #ifndef CONFIG_PCI_IOV #undef pci_enable_sriov #define pci_enable_sriov(a, b) -ENOTSUPP #undef pci_disable_sriov #define pci_disable_sriov(a) do {} while (0) #endif /* CONFIG_PCI_IOV */ #ifndef pr_cont #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) #endif /* pr_cont */ static inline void _kc_synchronize_irq(unsigned int a) { #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) synchronize_irq(); #else /* < 2.5.28 */ synchronize_irq(a); #endif /* < 2.5.28 */ } #undef synchronize_irq #define synchronize_irq(a) _kc_synchronize_irq(a) #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #else /* < 2.6.30 */ #define HAVE_ASPM_QUIRKS #endif /* < 2.6.30 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) ) #define ETH_P_1588 0x88F7 #define ETH_P_FIP 0x8914 #ifndef netdev_uc_count #define netdev_uc_count(dev) ((dev)->uc_count) #endif #ifndef netdev_for_each_uc_addr #define netdev_for_each_uc_addr(uclist, dev) \ for (uclist = dev->uc_list; uclist; uclist = uclist->next) #endif #ifndef PORT_OTHER #define PORT_OTHER 0xff #endif #ifndef MDIO_PHY_ID_PRTAD #define MDIO_PHY_ID_PRTAD 0x03e0 #endif #ifndef MDIO_PHY_ID_DEVAD #define MDIO_PHY_ID_DEVAD 0x001f #endif #ifndef skb_dst #define skb_dst(s) ((s)->dst) #endif #ifndef SUPPORTED_1000baseKX_Full #define SUPPORTED_1000baseKX_Full (1 << 17) #endif #ifndef SUPPORTED_10000baseKX4_Full #define SUPPORTED_10000baseKX4_Full (1 << 18) #endif #ifndef SUPPORTED_10000baseKR_Full #define SUPPORTED_10000baseKR_Full (1 << 19) #endif #ifndef ADVERTISED_1000baseKX_Full #define ADVERTISED_1000baseKX_Full (1 << 17) #endif #ifndef ADVERTISED_10000baseKX4_Full #define ADVERTISED_10000baseKX4_Full (1 << 18) #endif #ifndef ADVERTISED_10000baseKR_Full #define ADVERTISED_10000baseKR_Full (1 << 19) #endif #else /* < 2.6.31 */ #ifndef HAVE_NETDEV_STORAGE_ADDRESS #define HAVE_NETDEV_STORAGE_ADDRESS #endif #ifndef HAVE_NETDEV_HW_ADDR #define HAVE_NETDEV_HW_ADDR #endif #ifndef HAVE_TRANS_START_IN_QUEUE #define HAVE_TRANS_START_IN_QUEUE #endif #ifndef HAVE_INCLUDE_LINUX_MDIO_H #define HAVE_INCLUDE_LINUX_MDIO_H #endif #endif /* < 2.6.31 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) ) #undef netdev_tx_t #define netdev_tx_t int #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef NETIF_F_FCOE_MTU #define NETIF_F_FCOE_MTU (1 << 26) #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) static inline int _kc_pm_runtime_get_sync() { return 1; } #define pm_runtime_get_sync(dev) _kc_pm_runtime_get_sync() #else /* 2.6.0 => 2.6.32 */ static inline int _kc_pm_runtime_get_sync(struct device *dev) { return 1; } #ifndef pm_runtime_get_sync #define pm_runtime_get_sync(dev) _kc_pm_runtime_get_sync(dev) #endif #endif /* 2.6.0 => 2.6.32 */ #ifndef pm_runtime_put #define pm_runtime_put(dev) do {} while (0) #endif #ifndef pm_runtime_put_sync #define pm_runtime_put_sync(dev) do {} while (0) #endif #ifndef pm_runtime_resume #define pm_runtime_resume(dev) do {} while (0) #endif #ifndef pm_schedule_suspend #define pm_schedule_suspend(dev, t) do {} while (0) #endif #ifndef pm_runtime_set_suspended #define pm_runtime_set_suspended(dev) do {} while (0) #endif #ifndef pm_runtime_disable #define pm_runtime_disable(dev) do {} while (0) #endif #ifndef pm_runtime_put_noidle #define pm_runtime_put_noidle(dev) do {} while (0) #endif #ifndef pm_runtime_set_active #define pm_runtime_set_active(dev) do {} while (0) #endif #ifndef pm_runtime_enable #define pm_runtime_enable(dev) do {} while (0) #endif #ifndef pm_runtime_get_noresume #define pm_runtime_get_noresume(dev) do {} while (0) #endif #else /* < 2.6.32 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_ENABLE #define HAVE_NETDEV_OPS_FCOE_ENABLE #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #ifdef CONFIG_DCB #ifndef HAVE_DCBNL_OPS_GETAPP #define HAVE_DCBNL_OPS_GETAPP #endif #endif /* CONFIG_DCB */ #include /* IOV bad DMA target work arounds require at least this kernel rev support */ #define HAVE_PCIE_TYPE #endif /* < 2.6.32 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) ) #ifndef pci_pcie_cap #define pci_pcie_cap(pdev) pci_find_capability(pdev, PCI_CAP_ID_EXP) #endif #ifndef IPV4_FLOW #define IPV4_FLOW 0x10 #endif /* IPV4_FLOW */ #ifndef IPV6_FLOW #define IPV6_FLOW 0x11 #endif /* IPV6_FLOW */ /* Features back-ported to RHEL6 or SLES11 SP1 after 2.6.32 */ #if ( (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) || \ (SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,1,0)) ) #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_GETWWN #define HAVE_NETDEV_OPS_FCOE_GETWWN #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #endif /* RHEL6 or SLES11 SP1 */ #ifndef __percpu #define __percpu #endif /* __percpu */ #ifndef PORT_DA #define PORT_DA PORT_OTHER #endif #ifndef PORT_NONE #define PORT_NONE PORT_OTHER #endif #if ((RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,3)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)))) #if !defined(CONFIG_X86_32) && !defined(CONFIG_NEED_DMA_MAP_STATE) #undef DEFINE_DMA_UNMAP_ADDR #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME #undef DEFINE_DMA_UNMAP_LEN #define DEFINE_DMA_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME #undef dma_unmap_addr #define dma_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME) #undef dma_unmap_addr_set #define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL)) #undef dma_unmap_len #define dma_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME) #undef dma_unmap_len_set #define dma_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL)) #endif /* CONFIG_X86_64 && !CONFIG_NEED_DMA_MAP_STATE */ #endif /* RHEL_RELEASE_CODE */ #if (!(RHEL_RELEASE_CODE && \ (((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,8)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0))) || \ ((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,1)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)))))) static inline bool pci_is_pcie(struct pci_dev *dev) { return !!pci_pcie_cap(dev); } #endif /* RHEL_RELEASE_CODE */ #ifndef __always_unused #define __always_unused __attribute__((__unused__)) #endif #ifndef __maybe_unused #define __maybe_unused __attribute__((__unused__)) #endif #if (!(RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,2)))) #define sk_tx_queue_get(_sk) (-1) #define sk_tx_queue_set(_sk, _tx_queue) do {} while(0) #endif /* !(RHEL >= 6.2) */ #if (RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,4)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0))) #define HAVE_RHEL6_ETHTOOL_OPS_EXT_STRUCT #define HAVE_ETHTOOL_SET_PHYS_ID #define HAVE_ETHTOOL_GET_TS_INFO #endif /* RHEL >= 6.4 && RHEL < 7.0 */ #if (RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,5)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0))) #define HAVE_RHEL6_NETDEV_OPS_EXT_FDB #endif /* RHEL >= 6.5 && RHEL < 7.0 */ #else /* < 2.6.33 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_GETWWN #define HAVE_NETDEV_OPS_FCOE_GETWWN #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #endif /* < 2.6.33 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ) #if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) #ifndef pci_num_vf #define pci_num_vf(pdev) _kc_pci_num_vf(pdev) extern int _kc_pci_num_vf(struct pci_dev *dev); #endif #endif /* RHEL_RELEASE_CODE */ #ifndef ETH_FLAG_NTUPLE #define ETH_FLAG_NTUPLE NETIF_F_NTUPLE #endif #ifndef netdev_mc_count #define netdev_mc_count(dev) ((dev)->mc_count) #endif #ifndef netdev_mc_empty #define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) #endif #ifndef netdev_for_each_mc_addr #define netdev_for_each_mc_addr(mclist, dev) \ for (mclist = dev->mc_list; mclist; mclist = mclist->next) #endif #ifndef netdev_uc_count #define netdev_uc_count(dev) ((dev)->uc.count) #endif #ifndef netdev_uc_empty #define netdev_uc_empty(dev) (netdev_uc_count(dev) == 0) #endif #ifndef netdev_for_each_uc_addr #define netdev_for_each_uc_addr(ha, dev) \ list_for_each_entry(ha, &dev->uc.list, list) #endif #ifndef dma_set_coherent_mask #define dma_set_coherent_mask(dev,mask) \ pci_set_consistent_dma_mask(to_pci_dev(dev),(mask)) #endif #ifndef pci_dev_run_wake #define pci_dev_run_wake(pdev) (0) #endif /* netdev logging taken from include/linux/netdevice.h */ #ifndef netdev_name static inline const char *_kc_netdev_name(const struct net_device *dev) { if (dev->reg_state != NETREG_REGISTERED) return "(unregistered net_device)"; return dev->name; } #define netdev_name(netdev) _kc_netdev_name(netdev) #endif /* netdev_name */ #undef netdev_printk #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) #define netdev_printk(level, netdev, format, args...) \ do { \ struct pci_dev *pdev = _kc_netdev_to_pdev(netdev); \ printk(level "%s: " format, pci_name(pdev), ##args); \ } while(0) #elif ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) #define netdev_printk(level, netdev, format, args...) \ do { \ struct pci_dev *pdev = _kc_netdev_to_pdev(netdev); \ struct device *dev = pci_dev_to_dev(pdev); \ dev_printk(level, dev, "%s: " format, \ netdev_name(netdev), ##args); \ } while(0) #else /* 2.6.21 => 2.6.34 */ #define netdev_printk(level, netdev, format, args...) \ dev_printk(level, (netdev)->dev.parent, \ "%s: " format, \ netdev_name(netdev), ##args) #endif /* <2.6.0 <2.6.21 <2.6.34 */ #undef netdev_emerg #define netdev_emerg(dev, format, args...) \ netdev_printk(KERN_EMERG, dev, format, ##args) #undef netdev_alert #define netdev_alert(dev, format, args...) \ netdev_printk(KERN_ALERT, dev, format, ##args) #undef netdev_crit #define netdev_crit(dev, format, args...) \ netdev_printk(KERN_CRIT, dev, format, ##args) #undef netdev_err #define netdev_err(dev, format, args...) \ netdev_printk(KERN_ERR, dev, format, ##args) #undef netdev_warn #define netdev_warn(dev, format, args...) \ netdev_printk(KERN_WARNING, dev, format, ##args) #undef netdev_notice #define netdev_notice(dev, format, args...) \ netdev_printk(KERN_NOTICE, dev, format, ##args) #undef netdev_info #define netdev_info(dev, format, args...) \ netdev_printk(KERN_INFO, dev, format, ##args) #undef netdev_dbg #if defined(DEBUG) #define netdev_dbg(__dev, format, args...) \ netdev_printk(KERN_DEBUG, __dev, format, ##args) #elif defined(CONFIG_DYNAMIC_DEBUG) #define netdev_dbg(__dev, format, args...) \ do { \ dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ netdev_name(__dev), ##args); \ } while (0) #else /* DEBUG */ #define netdev_dbg(__dev, format, args...) \ ({ \ if (0) \ netdev_printk(KERN_DEBUG, __dev, format, ##args); \ 0; \ }) #endif /* DEBUG */ #undef netif_printk #define netif_printk(priv, type, level, dev, fmt, args...) \ do { \ if (netif_msg_##type(priv)) \ netdev_printk(level, (dev), fmt, ##args); \ } while (0) #undef netif_emerg #define netif_emerg(priv, type, dev, fmt, args...) \ netif_level(emerg, priv, type, dev, fmt, ##args) #undef netif_alert #define netif_alert(priv, type, dev, fmt, args...) \ netif_level(alert, priv, type, dev, fmt, ##args) #undef netif_crit #define netif_crit(priv, type, dev, fmt, args...) \ netif_level(crit, priv, type, dev, fmt, ##args) #undef netif_err #define netif_err(priv, type, dev, fmt, args...) \ netif_level(err, priv, type, dev, fmt, ##args) #undef netif_warn #define netif_warn(priv, type, dev, fmt, args...) \ netif_level(warn, priv, type, dev, fmt, ##args) #undef netif_notice #define netif_notice(priv, type, dev, fmt, args...) \ netif_level(notice, priv, type, dev, fmt, ##args) #undef netif_info #define netif_info(priv, type, dev, fmt, args...) \ netif_level(info, priv, type, dev, fmt, ##args) #undef netif_dbg #define netif_dbg(priv, type, dev, fmt, args...) \ netif_level(dbg, priv, type, dev, fmt, ##args) #ifdef SET_SYSTEM_SLEEP_PM_OPS #define HAVE_SYSTEM_SLEEP_PM_OPS #endif #ifndef for_each_set_bit #define for_each_set_bit(bit, addr, size) \ for ((bit) = find_first_bit((addr), (size)); \ (bit) < (size); \ (bit) = find_next_bit((addr), (size), (bit) + 1)) #endif /* for_each_set_bit */ #ifndef DEFINE_DMA_UNMAP_ADDR #define DEFINE_DMA_UNMAP_ADDR DECLARE_PCI_UNMAP_ADDR #define DEFINE_DMA_UNMAP_LEN DECLARE_PCI_UNMAP_LEN #define dma_unmap_addr pci_unmap_addr #define dma_unmap_addr_set pci_unmap_addr_set #define dma_unmap_len pci_unmap_len #define dma_unmap_len_set pci_unmap_len_set #endif /* DEFINE_DMA_UNMAP_ADDR */ #if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,3)) #ifdef IGB_HWMON #ifdef CONFIG_DEBUG_LOCK_ALLOC #define sysfs_attr_init(attr) \ do { \ static struct lock_class_key __key; \ (attr)->key = &__key; \ } while (0) #else #define sysfs_attr_init(attr) do {} while (0) #endif /* CONFIG_DEBUG_LOCK_ALLOC */ #endif /* IGB_HWMON */ #endif /* RHEL_RELEASE_CODE */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) static inline bool _kc_pm_runtime_suspended() { return false; } #define pm_runtime_suspended(dev) _kc_pm_runtime_suspended() #else /* 2.6.0 => 2.6.34 */ static inline bool _kc_pm_runtime_suspended(struct device *dev) { return false; } #ifndef pm_runtime_suspended #define pm_runtime_suspended(dev) _kc_pm_runtime_suspended(dev) #endif #endif /* 2.6.0 => 2.6.34 */ #else /* < 2.6.34 */ #define HAVE_SYSTEM_SLEEP_PM_OPS #ifndef HAVE_SET_RX_MODE #define HAVE_SET_RX_MODE #endif #endif /* < 2.6.34 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) ssize_t _kc_simple_write_to_buffer(void *to, size_t available, loff_t *ppos, const void __user *from, size_t count); #define simple_write_to_buffer _kc_simple_write_to_buffer #ifndef numa_node_id #define numa_node_id() 0 #endif #ifdef HAVE_TX_MQ #include #ifndef CONFIG_NETDEVICES_MULTIQUEUE #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0))) void _kc_netif_set_real_num_tx_queues(struct net_device *, unsigned int); #define netif_set_real_num_tx_queues _kc_netif_set_real_num_tx_queues #endif /* !(RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) */ #else /* CONFIG_NETDEVICES_MULTI_QUEUE */ #define netif_set_real_num_tx_queues(_netdev, _count) \ do { \ (_netdev)->egress_subqueue_count = _count; \ } while (0) #endif /* CONFIG_NETDEVICES_MULTI_QUEUE */ #else /* HAVE_TX_MQ */ #define netif_set_real_num_tx_queues(_netdev, _count) do {} while(0) #endif /* HAVE_TX_MQ */ #ifndef ETH_FLAG_RXHASH #define ETH_FLAG_RXHASH (1<<28) #endif /* ETH_FLAG_RXHASH */ #if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) #define HAVE_IRQ_AFFINITY_HINT #endif #else /* < 2.6.35 */ #define HAVE_PM_QOS_REQUEST_LIST #define HAVE_IRQ_AFFINITY_HINT #endif /* < 2.6.35 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ) extern int _kc_ethtool_op_set_flags(struct net_device *, u32, u32); #define ethtool_op_set_flags _kc_ethtool_op_set_flags extern u32 _kc_ethtool_op_get_flags(struct net_device *); #define ethtool_op_get_flags _kc_ethtool_op_get_flags #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #ifdef NET_IP_ALIGN #undef NET_IP_ALIGN #endif #define NET_IP_ALIGN 0 #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ #ifdef NET_SKB_PAD #undef NET_SKB_PAD #endif #if (L1_CACHE_BYTES > 32) #define NET_SKB_PAD L1_CACHE_BYTES #else #define NET_SKB_PAD 32 #endif static inline struct sk_buff *_kc_netdev_alloc_skb_ip_align(struct net_device *dev, unsigned int length) { struct sk_buff *skb; skb = alloc_skb(length + NET_SKB_PAD + NET_IP_ALIGN, GFP_ATOMIC); if (skb) { #if (NET_IP_ALIGN + NET_SKB_PAD) skb_reserve(skb, NET_IP_ALIGN + NET_SKB_PAD); #endif skb->dev = dev; } return skb; } #ifdef netdev_alloc_skb_ip_align #undef netdev_alloc_skb_ip_align #endif #define netdev_alloc_skb_ip_align(n, l) _kc_netdev_alloc_skb_ip_align(n, l) #undef netif_level #define netif_level(level, priv, type, dev, fmt, args...) \ do { \ if (netif_msg_##type(priv)) \ netdev_##level(dev, fmt, ##args); \ } while (0) #undef usleep_range #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000)) #define u64_stats_update_begin(a) do { } while(0) #define u64_stats_update_end(a) do { } while(0) #define u64_stats_fetch_begin(a) do { } while(0) #define u64_stats_fetch_retry_bh(a) (0) #define u64_stats_fetch_begin_bh(a) (0) #if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,1)) #define HAVE_8021P_SUPPORT #endif #else /* < 2.6.36 */ #define HAVE_PM_QOS_REQUEST_ACTIVE #define HAVE_8021P_SUPPORT #define HAVE_NDO_GET_STATS64 #endif /* < 2.6.36 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ) #ifndef netif_set_real_num_rx_queues static inline int __kc_netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq) { return 0; } #define netif_set_real_num_rx_queues(dev, rxq) \ __kc_netif_set_real_num_rx_queues((dev), (rxq)) #endif #ifndef ETHTOOL_RXNTUPLE_ACTION_CLEAR #define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) #endif #ifndef VLAN_N_VID #define VLAN_N_VID VLAN_GROUP_ARRAY_LEN #endif /* VLAN_N_VID */ #ifndef ETH_FLAG_TXVLAN #define ETH_FLAG_TXVLAN (1 << 7) #endif /* ETH_FLAG_TXVLAN */ #ifndef ETH_FLAG_RXVLAN #define ETH_FLAG_RXVLAN (1 << 8) #endif /* ETH_FLAG_RXVLAN */ static inline void _kc_skb_checksum_none_assert(struct sk_buff *skb) { WARN_ON(skb->ip_summed != CHECKSUM_NONE); } #define skb_checksum_none_assert(skb) _kc_skb_checksum_none_assert(skb) static inline void *_kc_vzalloc_node(unsigned long size, int node) { void *addr = vmalloc_node(size, node); if (addr) memset(addr, 0, size); return addr; } #define vzalloc_node(_size, _node) _kc_vzalloc_node(_size, _node) static inline void *_kc_vzalloc(unsigned long size) { void *addr = vmalloc(size); if (addr) memset(addr, 0, size); return addr; } #define vzalloc(_size) _kc_vzalloc(_size) #ifndef vlan_get_protocol static inline __be16 __kc_vlan_get_protocol(const struct sk_buff *skb) { if (vlan_tx_tag_present(skb) || skb->protocol != cpu_to_be16(ETH_P_8021Q)) return skb->protocol; if (skb_headlen(skb) < sizeof(struct vlan_ethhdr)) return 0; return ((struct vlan_ethhdr*)skb->data)->h_vlan_encapsulated_proto; } #define vlan_get_protocol(_skb) __kc_vlan_get_protocol(_skb) #endif #ifdef HAVE_HW_TIME_STAMP #define SKBTX_HW_TSTAMP (1 << 0) #define SKBTX_IN_PROGRESS (1 << 2) #define SKB_SHARED_TX_IS_UNION #endif #ifndef device_wakeup_enable #define device_wakeup_enable(dev) device_set_wakeup_enable(dev, true) #endif #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,18) ) #ifndef HAVE_VLAN_RX_REGISTER #define HAVE_VLAN_RX_REGISTER #endif #endif /* > 2.4.18 */ #endif /* < 2.6.37 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) ) #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) #define skb_checksum_start_offset(skb) skb_transport_offset(skb) #else /* 2.6.22 -> 2.6.37 */ static inline int _kc_skb_checksum_start_offset(const struct sk_buff *skb) { return skb->csum_start - skb_headroom(skb); } #define skb_checksum_start_offset(skb) _kc_skb_checksum_start_offset(skb) #endif /* 2.6.22 -> 2.6.37 */ #ifdef CONFIG_DCB #ifndef IEEE_8021QAZ_MAX_TCS #define IEEE_8021QAZ_MAX_TCS 8 #endif #ifndef DCB_CAP_DCBX_HOST #define DCB_CAP_DCBX_HOST 0x01 #endif #ifndef DCB_CAP_DCBX_LLD_MANAGED #define DCB_CAP_DCBX_LLD_MANAGED 0x02 #endif #ifndef DCB_CAP_DCBX_VER_CEE #define DCB_CAP_DCBX_VER_CEE 0x04 #endif #ifndef DCB_CAP_DCBX_VER_IEEE #define DCB_CAP_DCBX_VER_IEEE 0x08 #endif #ifndef DCB_CAP_DCBX_STATIC #define DCB_CAP_DCBX_STATIC 0x10 #endif #endif /* CONFIG_DCB */ #if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,2)) #define CONFIG_XPS #endif /* RHEL_RELEASE_VERSION(6,2) */ #endif /* < 2.6.38 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) ) #ifndef NETIF_F_RXCSUM #define NETIF_F_RXCSUM (1 << 29) #endif #ifndef skb_queue_reverse_walk_safe #define skb_queue_reverse_walk_safe(queue, skb, tmp) \ for (skb = (queue)->prev, tmp = skb->prev; \ skb != (struct sk_buff *)(queue); \ skb = tmp, tmp = skb->prev) #endif #else /* < 2.6.39 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_DDP_TARGET #define HAVE_NETDEV_OPS_FCOE_DDP_TARGET #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #ifndef HAVE_MQPRIO #define HAVE_MQPRIO #endif #ifndef HAVE_SETUP_TC #define HAVE_SETUP_TC #endif #ifdef CONFIG_DCB #ifndef HAVE_DCBNL_IEEE #define HAVE_DCBNL_IEEE #endif #endif /* CONFIG_DCB */ #ifndef HAVE_NDO_SET_FEATURES #define HAVE_NDO_SET_FEATURES #endif #endif /* < 2.6.39 */ /*****************************************************************************/ /* use < 2.6.40 because of a Fedora 15 kernel update where they * updated the kernel version to 2.6.40.x and they back-ported 3.0 features * like set_phys_id for ethtool. */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,40) ) #ifdef ETHTOOL_GRXRINGS #ifndef FLOW_EXT #define FLOW_EXT 0x80000000 union _kc_ethtool_flow_union { struct ethtool_tcpip4_spec tcp_ip4_spec; struct ethtool_usrip4_spec usr_ip4_spec; __u8 hdata[60]; }; struct _kc_ethtool_flow_ext { __be16 vlan_etype; __be16 vlan_tci; __be32 data[2]; }; struct _kc_ethtool_rx_flow_spec { __u32 flow_type; union _kc_ethtool_flow_union h_u; struct _kc_ethtool_flow_ext h_ext; union _kc_ethtool_flow_union m_u; struct _kc_ethtool_flow_ext m_ext; __u64 ring_cookie; __u32 location; }; #define ethtool_rx_flow_spec _kc_ethtool_rx_flow_spec #endif /* FLOW_EXT */ #endif #define pci_disable_link_state_locked pci_disable_link_state #ifndef PCI_LTR_VALUE_MASK #define PCI_LTR_VALUE_MASK 0x000003ff #endif #ifndef PCI_LTR_SCALE_MASK #define PCI_LTR_SCALE_MASK 0x00001c00 #endif #ifndef PCI_LTR_SCALE_SHIFT #define PCI_LTR_SCALE_SHIFT 10 #endif #else /* < 2.6.40 */ #define HAVE_ETHTOOL_SET_PHYS_ID #endif /* < 2.6.40 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) ) #define USE_LEGACY_PM_SUPPORT #endif /* < 3.0.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ) #ifndef __netdev_alloc_skb_ip_align #define __netdev_alloc_skb_ip_align(d,l,_g) netdev_alloc_skb_ip_align(d,l) #endif /* __netdev_alloc_skb_ip_align */ #define dcb_ieee_setapp(dev, app) dcb_setapp(dev, app) #define dcb_ieee_delapp(dev, app) 0 #define dcb_ieee_getapp_mask(dev, app) (1 << app->priority) /* 1000BASE-T Control register */ #define CTL1000_AS_MASTER 0x0800 #define CTL1000_ENABLE_MASTER 0x1000 #else /* < 3.1.0 */ #ifndef HAVE_DCBNL_IEEE_DELAPP #define HAVE_DCBNL_IEEE_DELAPP #endif #endif /* < 3.1.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ) #ifdef ETHTOOL_GRXRINGS #define HAVE_ETHTOOL_GET_RXNFC_VOID_RULE_LOCS #endif /* ETHTOOL_GRXRINGS */ #ifndef skb_frag_size #define skb_frag_size(frag) _kc_skb_frag_size(frag) static inline unsigned int _kc_skb_frag_size(const skb_frag_t *frag) { return frag->size; } #endif /* skb_frag_size */ #ifndef skb_frag_size_sub #define skb_frag_size_sub(frag, delta) _kc_skb_frag_size_sub(frag, delta) static inline void _kc_skb_frag_size_sub(skb_frag_t *frag, int delta) { frag->size -= delta; } #endif /* skb_frag_size_sub */ #ifndef skb_frag_page #define skb_frag_page(frag) _kc_skb_frag_page(frag) static inline struct page *_kc_skb_frag_page(const skb_frag_t *frag) { return frag->page; } #endif /* skb_frag_page */ #ifndef skb_frag_address #define skb_frag_address(frag) _kc_skb_frag_address(frag) static inline void *_kc_skb_frag_address(const skb_frag_t *frag) { return page_address(skb_frag_page(frag)) + frag->page_offset; } #endif /* skb_frag_address */ #ifndef skb_frag_dma_map #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) #include #endif #define skb_frag_dma_map(dev,frag,offset,size,dir) \ _kc_skb_frag_dma_map(dev,frag,offset,size,dir) static inline dma_addr_t _kc_skb_frag_dma_map(struct device *dev, const skb_frag_t *frag, size_t offset, size_t size, enum dma_data_direction dir) { return dma_map_page(dev, skb_frag_page(frag), frag->page_offset + offset, size, dir); } #endif /* skb_frag_dma_map */ #ifndef __skb_frag_unref #define __skb_frag_unref(frag) __kc_skb_frag_unref(frag) static inline void __kc_skb_frag_unref(skb_frag_t *frag) { put_page(skb_frag_page(frag)); } #endif /* __skb_frag_unref */ #ifndef SPEED_UNKNOWN #define SPEED_UNKNOWN -1 #endif #ifndef DUPLEX_UNKNOWN #define DUPLEX_UNKNOWN 0xff #endif #if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,3)) #ifndef HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_PCI_DEV_FLAGS_ASSIGNED #endif #endif #else /* < 3.2.0 */ #ifndef HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_VF_SPOOFCHK_CONFIGURE #endif #endif /* < 3.2.0 */ #if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE == RHEL_RELEASE_VERSION(6,2)) #undef ixgbe_get_netdev_tc_txq #define ixgbe_get_netdev_tc_txq(dev, tc) (&netdev_extended(dev)->qos_data.tc_to_txq[tc]) #endif /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ) typedef u32 kni_netdev_features_t; #undef PCI_EXP_TYPE_RC_EC #define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */ #ifndef CONFIG_BQL #define netdev_tx_completed_queue(_q, _p, _b) do {} while (0) #define netdev_completed_queue(_n, _p, _b) do {} while (0) #define netdev_tx_sent_queue(_q, _b) do {} while (0) #define netdev_sent_queue(_n, _b) do {} while (0) #define netdev_tx_reset_queue(_q) do {} while (0) #define netdev_reset_queue(_n) do {} while (0) #endif #else /* ! < 3.3.0 */ typedef netdev_features_t kni_netdev_features_t; #define HAVE_INT_NDO_VLAN_RX_ADD_VID #ifdef ETHTOOL_SRXNTUPLE #undef ETHTOOL_SRXNTUPLE #endif #endif /* < 3.3.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ) #ifndef NETIF_F_RXFCS #define NETIF_F_RXFCS 0 #endif /* NETIF_F_RXFCS */ #ifndef NETIF_F_RXALL #define NETIF_F_RXALL 0 #endif /* NETIF_F_RXALL */ #if !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) #define NUMTCS_RETURNS_U8 int _kc_simple_open(struct inode *inode, struct file *file); #define simple_open _kc_simple_open #endif /* !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) */ #ifndef skb_add_rx_frag #define skb_add_rx_frag _kc_skb_add_rx_frag extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int, unsigned int); #endif #ifdef NET_ADDR_RANDOM #define eth_hw_addr_random(N) do { \ random_ether_addr(N->dev_addr); \ N->addr_assign_type |= NET_ADDR_RANDOM; \ } while (0) #else /* NET_ADDR_RANDOM */ #define eth_hw_addr_random(N) random_ether_addr(N->dev_addr) #endif /* NET_ADDR_RANDOM */ #else /* < 3.4.0 */ #include #endif /* >= 3.4.0 */ /*****************************************************************************/ #if defined(E1000E_PTP) || defined(IGB_PTP) || defined(IXGBE_PTP) || defined(I40E_PTP) #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) ) && IS_ENABLED(CONFIG_PTP_1588_CLOCK) #define HAVE_PTP_1588_CLOCK #else #error Cannot enable PTP Hardware Clock support due to a pre-3.0 kernel version or CONFIG_PTP_1588_CLOCK not enabled in the kernel #endif /* > 3.0.0 && IS_ENABLED(CONFIG_PTP_1588_CLOCK) */ #endif /* E1000E_PTP || IGB_PTP || IXGBE_PTP || I40E_PTP */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ) #define skb_tx_timestamp(skb) do {} while (0) static inline bool __kc_ether_addr_equal(const u8 *addr1, const u8 *addr2) { return !compare_ether_addr(addr1, addr2); } #define ether_addr_equal(_addr1, _addr2) __kc_ether_addr_equal((_addr1),(_addr2)) #else #define HAVE_FDB_OPS #define HAVE_ETHTOOL_GET_TS_INFO #endif /* < 3.5.0 */ /*****************************************************************************/ #include #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) ) #define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ #ifndef MDIO_EEE_100TX #define MDIO_EEE_100TX 0x0002 /* 100TX EEE cap */ #endif #ifndef MDIO_EEE_1000T #define MDIO_EEE_1000T 0x0004 /* 1000T EEE cap */ #endif #ifndef MDIO_EEE_10GT #define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */ #endif #ifndef MDIO_EEE_1000KX #define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */ #endif #ifndef MDIO_EEE_10GKX4 #define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */ #endif #ifndef MDIO_EEE_10GKR #define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */ #endif #endif /* < 3.6.0 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) ) #ifndef ADVERTISED_40000baseKR4_Full /* these defines were all added in one commit, so should be safe * to trigger activiation on one define */ #define SUPPORTED_40000baseKR4_Full (1 << 23) #define SUPPORTED_40000baseCR4_Full (1 << 24) #define SUPPORTED_40000baseSR4_Full (1 << 25) #define SUPPORTED_40000baseLR4_Full (1 << 26) #define ADVERTISED_40000baseKR4_Full (1 << 23) #define ADVERTISED_40000baseCR4_Full (1 << 24) #define ADVERTISED_40000baseSR4_Full (1 << 25) #define ADVERTISED_40000baseLR4_Full (1 << 26) #endif /** * mmd_eee_cap_to_ethtool_sup_t * @eee_cap: value of the MMD EEE Capability register * * A small helper function that translates MMD EEE Capability (3.20) bits * to ethtool supported settings. */ static inline u32 __kc_mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap) { u32 supported = 0; if (eee_cap & MDIO_EEE_100TX) supported |= SUPPORTED_100baseT_Full; if (eee_cap & MDIO_EEE_1000T) supported |= SUPPORTED_1000baseT_Full; if (eee_cap & MDIO_EEE_10GT) supported |= SUPPORTED_10000baseT_Full; if (eee_cap & MDIO_EEE_1000KX) supported |= SUPPORTED_1000baseKX_Full; if (eee_cap & MDIO_EEE_10GKX4) supported |= SUPPORTED_10000baseKX4_Full; if (eee_cap & MDIO_EEE_10GKR) supported |= SUPPORTED_10000baseKR_Full; return supported; } #define mmd_eee_cap_to_ethtool_sup_t(eee_cap) \ __kc_mmd_eee_cap_to_ethtool_sup_t(eee_cap) /** * mmd_eee_adv_to_ethtool_adv_t * @eee_adv: value of the MMD EEE Advertisement/Link Partner Ability registers * * A small helper function that translates the MMD EEE Advertisement (7.60) * and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement * settings. */ static inline u32 __kc_mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv) { u32 adv = 0; if (eee_adv & MDIO_EEE_100TX) adv |= ADVERTISED_100baseT_Full; if (eee_adv & MDIO_EEE_1000T) adv |= ADVERTISED_1000baseT_Full; if (eee_adv & MDIO_EEE_10GT) adv |= ADVERTISED_10000baseT_Full; if (eee_adv & MDIO_EEE_1000KX) adv |= ADVERTISED_1000baseKX_Full; if (eee_adv & MDIO_EEE_10GKX4) adv |= ADVERTISED_10000baseKX4_Full; if (eee_adv & MDIO_EEE_10GKR) adv |= ADVERTISED_10000baseKR_Full; return adv; } #define mmd_eee_adv_to_ethtool_adv_t(eee_adv) \ __kc_mmd_eee_adv_to_ethtool_adv_t(eee_adv) /** * ethtool_adv_to_mmd_eee_adv_t * @adv: the ethtool advertisement settings * * A small helper function that translates ethtool advertisement settings * to EEE advertisements for the MMD EEE Advertisement (7.60) and * MMD EEE Link Partner Ability (7.61) registers. */ static inline u16 __kc_ethtool_adv_to_mmd_eee_adv_t(u32 adv) { u16 reg = 0; if (adv & ADVERTISED_100baseT_Full) reg |= MDIO_EEE_100TX; if (adv & ADVERTISED_1000baseT_Full) reg |= MDIO_EEE_1000T; if (adv & ADVERTISED_10000baseT_Full) reg |= MDIO_EEE_10GT; if (adv & ADVERTISED_1000baseKX_Full) reg |= MDIO_EEE_1000KX; if (adv & ADVERTISED_10000baseKX4_Full) reg |= MDIO_EEE_10GKX4; if (adv & ADVERTISED_10000baseKR_Full) reg |= MDIO_EEE_10GKR; return reg; } #define ethtool_adv_to_mmd_eee_adv_t(adv) \ __kc_ethtool_adv_to_mmd_eee_adv_t(adv) #ifndef pci_pcie_type #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) static inline u8 pci_pcie_type(struct pci_dev *pdev) { int pos; u16 reg16; pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (!pos) BUG(); pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); return (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; } #else /* < 2.6.24 */ #define pci_pcie_type(x) (x)->pcie_type #endif /* < 2.6.24 */ #endif /* pci_pcie_type */ #define ptp_clock_register(caps, args...) ptp_clock_register(caps) #ifndef PCI_EXP_LNKSTA2 int __kc_pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); #define pcie_capability_read_word(d,p,v) __kc_pcie_capability_read_word(d,p,v) int __kc_pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val); #define pcie_capability_write_word(d,p,v) __kc_pcie_capability_write_word(d,p,v) int __kc_pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, u16 clear, u16 set); #define pcie_capability_clear_and_set_word(d,p,c,s) \ __kc_pcie_capability_clear_and_set_word(d,p,c,s) #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos, u16 clear) { return __kc_pcie_capability_clear_and_set_word(dev, pos, clear, 0); } #endif /* !PCI_EXP_LNKSTA2 */ #if (SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) #define USE_CONST_DEV_UC_CHAR #endif #else /* >= 3.7.0 */ #define HAVE_CONST_STRUCT_PCI_ERROR_HANDLERS #define USE_CONST_DEV_UC_CHAR #endif /* >= 3.7.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) ) #ifndef PCI_EXP_LNKCTL_ASPM_L0S #define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */ #endif #ifndef PCI_EXP_LNKCTL_ASPM_L1 #define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */ #endif #define HAVE_CONFIG_HOTPLUG /* Reserved Ethernet Addresses per IEEE 802.1Q */ static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; #if !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) &&\ !(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,5)) static inline bool is_link_local_ether_addr(const u8 *addr) { __be16 *a = (__be16 *)addr; static const __be16 *b = (const __be16 *)eth_reserved_addr_base; static const __be16 m = cpu_to_be16(0xfff0); return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0; } #endif /* !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,3,0)) */ #else /* >= 3.8.0 */ #ifndef __devinit #define __devinit #define HAVE_ENCAP_CSUM_OFFLOAD #endif #ifndef __devinitdata #define __devinitdata #endif #ifndef __devexit #define __devexit #endif #ifndef __devexit_p #define __devexit_p #endif #ifndef HAVE_SRIOV_CONFIGURE #define HAVE_SRIOV_CONFIGURE #endif #define HAVE_BRIDGE_ATTRIBS #ifndef BRIDGE_MODE_VEB #define BRIDGE_MODE_VEB 0 /* Default loopback mode */ #endif /* BRIDGE_MODE_VEB */ #ifndef BRIDGE_MODE_VEPA #define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ #endif /* BRIDGE_MODE_VEPA */ #endif /* >= 3.8.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) ) #undef hlist_entry #define hlist_entry(ptr, type, member) container_of(ptr,type,member) #undef hlist_entry_safe #define hlist_entry_safe(ptr, type, member) \ (ptr) ? hlist_entry(ptr, type, member) : NULL #undef hlist_for_each_entry #define hlist_for_each_entry(pos, head, member) \ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \ pos; \ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) #undef hlist_for_each_entry_safe #define hlist_for_each_entry_safe(pos, n, head, member) \ for (pos = hlist_entry_safe((head)->first, typeof(*pos), member); \ pos && ({ n = pos->member.next; 1; }); \ pos = hlist_entry_safe(n, typeof(*pos), member)) #ifdef CONFIG_XPS extern int __kc_netif_set_xps_queue(struct net_device *, struct cpumask *, u16); #define netif_set_xps_queue(_dev, _mask, _idx) __kc_netif_set_xps_queue((_dev), (_mask), (_idx)) #else /* CONFIG_XPS */ #define netif_set_xps_queue(_dev, _mask, _idx) do {} while (0) #endif /* CONFIG_XPS */ #ifdef HAVE_NETDEV_SELECT_QUEUE #define _kc_hashrnd 0xd631614b /* not so random hash salt */ extern u16 __kc_netdev_pick_tx(struct net_device *dev, struct sk_buff *skb); #define __netdev_pick_tx __kc_netdev_pick_tx #endif /* HAVE_NETDEV_SELECT_QUEUE */ #else #define HAVE_BRIDGE_FILTER #define USE_DEFAULT_FDB_DEL_DUMP #endif /* < 3.9.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #ifdef CONFIG_PCI_IOV extern int __kc_pci_vfs_assigned(struct pci_dev *dev); #else static inline int __kc_pci_vfs_assigned(struct pci_dev *dev) { return 0; } #endif #define pci_vfs_assigned(dev) __kc_pci_vfs_assigned(dev) #ifndef VLAN_TX_COOKIE_MAGIC static inline struct sk_buff *__kc__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci) { #ifdef VLAN_TAG_PRESENT vlan_tci |= VLAN_TAG_PRESENT; #endif skb->vlan_tci = vlan_tci; return skb; } #define __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci) \ __kc__vlan_hwaccel_put_tag(skb, vlan_tci) #endif #else /* >= 3.10.0 */ #define HAVE_ENCAP_TSO_OFFLOAD #endif /* >= 3.10.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) ) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,6))) #if (!(UBUNTU_KERNEL_CODE >= UBUNTU_KERNEL_VERSION(3,13,0,30,54) \ && (UBUNTU_RELEASE_CODE == UBUNTU_RELEASE_VERSION(12,4) \ || UBUNTU_RELEASE_CODE == UBUNTU_RELEASE_VERSION(14,4)))) #if (!(SLE_VERSION_CODE == SLE_VERSION(12,0,0))) #ifdef NETIF_F_RXHASH #define PKT_HASH_TYPE_L3 0 static inline void skb_set_hash(struct sk_buff *skb, __u32 hash, __always_unused int type) { skb->rxhash = hash; } #endif /* NETIF_F_RXHASH */ #endif /* < SLES12 */ #endif /* < 3.13.0-30.54 (Ubuntu 14.04) */ #endif /* < RHEL7 */ #endif /* < 3.14.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) ) #define SET_ETHTOOL_OPS(netdev, ops) ((netdev)->ethtool_ops = (ops)) #define HAVE_VF_MIN_MAX_TXRATE 1 #endif /* >= 3.16.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) ) #define HAVE_NDO_FDB_ADD_VID #endif /* >= 3.19.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) ) /* vlan_tx_xx functions got renamed to skb_vlan */ #define vlan_tx_tag_get skb_vlan_tag_get #define vlan_tx_tag_present skb_vlan_tag_present #define HAVE_NDO_BRIDGE_SET_DEL_LINK_FLAGS #endif /* 4.0.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) ) /* ndo_bridge_getlink adds new nlflags parameter */ #define HAVE_NDO_BRIDGE_GETLINK_FILTER_MASK #endif /* >= 4.1.0 */ #endif /* _KCOMPAT_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat_ethtool.c ================================================ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver Copyright(c) 2007-2013 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* * net/core/ethtool.c - Ethtool ioctl handler * Copyright (c) 2003 Matthew Wilcox * * This file is where we call all the ethtool_ops commands to get * the information ethtool needs. We fall back to calling do_ioctl() * for drivers which haven't been converted to ethtool_ops yet. * * It's GPL, stupid. * * Modification by sfeldma@pobox.com to work as backward compat * solution for pre-ethtool_ops kernels. * - copied struct ethtool_ops from ethtool.h * - defined SET_ETHTOOL_OPS * - put in some #ifndef NETIF_F_xxx wrappers * - changes refs to dev->ethtool_ops to ethtool_ops * - changed dev_ethtool to ethtool_ioctl * - remove EXPORT_SYMBOL()s * - added _kc_ prefix in built-in ethtool_op_xxx ops. */ #include #include #include #include #include #include #include #include "kcompat.h" #undef SUPPORTED_10000baseT_Full #define SUPPORTED_10000baseT_Full (1 << 12) #undef ADVERTISED_10000baseT_Full #define ADVERTISED_10000baseT_Full (1 << 12) #undef SPEED_10000 #define SPEED_10000 10000 #undef ethtool_ops #define ethtool_ops _kc_ethtool_ops struct _kc_ethtool_ops { int (*get_settings)(struct net_device *, struct ethtool_cmd *); int (*set_settings)(struct net_device *, struct ethtool_cmd *); void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); int (*get_regs_len)(struct net_device *); void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); u32 (*get_msglevel)(struct net_device *); void (*set_msglevel)(struct net_device *, u32); int (*nway_reset)(struct net_device *); u32 (*get_link)(struct net_device *); int (*get_eeprom_len)(struct net_device *); int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); void (*get_pauseparam)(struct net_device *, struct ethtool_pauseparam*); int (*set_pauseparam)(struct net_device *, struct ethtool_pauseparam*); u32 (*get_rx_csum)(struct net_device *); int (*set_rx_csum)(struct net_device *, u32); u32 (*get_tx_csum)(struct net_device *); int (*set_tx_csum)(struct net_device *, u32); u32 (*get_sg)(struct net_device *); int (*set_sg)(struct net_device *, u32); u32 (*get_tso)(struct net_device *); int (*set_tso)(struct net_device *, u32); int (*self_test_count)(struct net_device *); void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); void (*get_strings)(struct net_device *, u32 stringset, u8 *); int (*phys_id)(struct net_device *, u32); int (*get_stats_count)(struct net_device *); void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *); } *ethtool_ops = NULL; #undef SET_ETHTOOL_OPS #define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) /* * Some useful ethtool_ops methods that are device independent. If we find that * all drivers want to do the same thing here, we can turn these into dev_() * function calls. */ #undef ethtool_op_get_link #define ethtool_op_get_link _kc_ethtool_op_get_link u32 _kc_ethtool_op_get_link(struct net_device *dev) { return netif_carrier_ok(dev) ? 1 : 0; } #undef ethtool_op_get_tx_csum #define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev) { #ifdef NETIF_F_IP_CSUM return (dev->features & NETIF_F_IP_CSUM) != 0; #else return 0; #endif } #undef ethtool_op_set_tx_csum #define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) { #ifdef NETIF_F_IP_CSUM if (data) #ifdef NETIF_F_IPV6_CSUM dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); else dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); #else dev->features |= NETIF_F_IP_CSUM; else dev->features &= ~NETIF_F_IP_CSUM; #endif #endif return 0; } #undef ethtool_op_get_sg #define ethtool_op_get_sg _kc_ethtool_op_get_sg u32 _kc_ethtool_op_get_sg(struct net_device *dev) { #ifdef NETIF_F_SG return (dev->features & NETIF_F_SG) != 0; #else return 0; #endif } #undef ethtool_op_set_sg #define ethtool_op_set_sg _kc_ethtool_op_set_sg int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) { #ifdef NETIF_F_SG if (data) dev->features |= NETIF_F_SG; else dev->features &= ~NETIF_F_SG; #endif return 0; } #undef ethtool_op_get_tso #define ethtool_op_get_tso _kc_ethtool_op_get_tso u32 _kc_ethtool_op_get_tso(struct net_device *dev) { #ifdef NETIF_F_TSO return (dev->features & NETIF_F_TSO) != 0; #else return 0; #endif } #undef ethtool_op_set_tso #define ethtool_op_set_tso _kc_ethtool_op_set_tso int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data) { #ifdef NETIF_F_TSO if (data) dev->features |= NETIF_F_TSO; else dev->features &= ~NETIF_F_TSO; #endif return 0; } /* Handlers for each ethtool command */ static int ethtool_get_settings(struct net_device *dev, void *useraddr) { struct ethtool_cmd cmd = { ETHTOOL_GSET }; int err; if (!ethtool_ops->get_settings) return -EOPNOTSUPP; err = ethtool_ops->get_settings(dev, &cmd); if (err < 0) return err; if (copy_to_user(useraddr, &cmd, sizeof(cmd))) return -EFAULT; return 0; } static int ethtool_set_settings(struct net_device *dev, void *useraddr) { struct ethtool_cmd cmd; if (!ethtool_ops->set_settings) return -EOPNOTSUPP; if (copy_from_user(&cmd, useraddr, sizeof(cmd))) return -EFAULT; return ethtool_ops->set_settings(dev, &cmd); } static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) { struct ethtool_drvinfo info; struct ethtool_ops *ops = ethtool_ops; if (!ops->get_drvinfo) return -EOPNOTSUPP; memset(&info, 0, sizeof(info)); info.cmd = ETHTOOL_GDRVINFO; ops->get_drvinfo(dev, &info); if (ops->self_test_count) info.testinfo_len = ops->self_test_count(dev); if (ops->get_stats_count) info.n_stats = ops->get_stats_count(dev); if (ops->get_regs_len) info.regdump_len = ops->get_regs_len(dev); if (ops->get_eeprom_len) info.eedump_len = ops->get_eeprom_len(dev); if (copy_to_user(useraddr, &info, sizeof(info))) return -EFAULT; return 0; } static int ethtool_get_regs(struct net_device *dev, char *useraddr) { struct ethtool_regs regs; struct ethtool_ops *ops = ethtool_ops; void *regbuf; int reglen, ret; if (!ops->get_regs || !ops->get_regs_len) return -EOPNOTSUPP; if (copy_from_user(®s, useraddr, sizeof(regs))) return -EFAULT; reglen = ops->get_regs_len(dev); if (regs.len > reglen) regs.len = reglen; regbuf = kmalloc(reglen, GFP_USER); if (!regbuf) return -ENOMEM; ops->get_regs(dev, ®s, regbuf); ret = -EFAULT; if (copy_to_user(useraddr, ®s, sizeof(regs))) goto out; useraddr += offsetof(struct ethtool_regs, data); if (copy_to_user(useraddr, regbuf, reglen)) goto out; ret = 0; out: kfree(regbuf); return ret; } static int ethtool_get_wol(struct net_device *dev, char *useraddr) { struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; if (!ethtool_ops->get_wol) return -EOPNOTSUPP; ethtool_ops->get_wol(dev, &wol); if (copy_to_user(useraddr, &wol, sizeof(wol))) return -EFAULT; return 0; } static int ethtool_set_wol(struct net_device *dev, char *useraddr) { struct ethtool_wolinfo wol; if (!ethtool_ops->set_wol) return -EOPNOTSUPP; if (copy_from_user(&wol, useraddr, sizeof(wol))) return -EFAULT; return ethtool_ops->set_wol(dev, &wol); } static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) { struct ethtool_value edata = { ETHTOOL_GMSGLVL }; if (!ethtool_ops->get_msglevel) return -EOPNOTSUPP; edata.data = ethtool_ops->get_msglevel(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) { struct ethtool_value edata; if (!ethtool_ops->set_msglevel) return -EOPNOTSUPP; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; ethtool_ops->set_msglevel(dev, edata.data); return 0; } static int ethtool_nway_reset(struct net_device *dev) { if (!ethtool_ops->nway_reset) return -EOPNOTSUPP; return ethtool_ops->nway_reset(dev); } static int ethtool_get_link(struct net_device *dev, void *useraddr) { struct ethtool_value edata = { ETHTOOL_GLINK }; if (!ethtool_ops->get_link) return -EOPNOTSUPP; edata.data = ethtool_ops->get_link(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) { struct ethtool_eeprom eeprom; struct ethtool_ops *ops = ethtool_ops; u8 *data; int ret; if (!ops->get_eeprom || !ops->get_eeprom_len) return -EOPNOTSUPP; if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) return -EFAULT; /* Check for wrap and zero */ if (eeprom.offset + eeprom.len <= eeprom.offset) return -EINVAL; /* Check for exceeding total eeprom len */ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) return -EINVAL; data = kmalloc(eeprom.len, GFP_USER); if (!data) return -ENOMEM; ret = -EFAULT; if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) goto out; ret = ops->get_eeprom(dev, &eeprom, data); if (ret) goto out; ret = -EFAULT; if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) goto out; if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) goto out; ret = 0; out: kfree(data); return ret; } static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) { struct ethtool_eeprom eeprom; struct ethtool_ops *ops = ethtool_ops; u8 *data; int ret; if (!ops->set_eeprom || !ops->get_eeprom_len) return -EOPNOTSUPP; if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) return -EFAULT; /* Check for wrap and zero */ if (eeprom.offset + eeprom.len <= eeprom.offset) return -EINVAL; /* Check for exceeding total eeprom len */ if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) return -EINVAL; data = kmalloc(eeprom.len, GFP_USER); if (!data) return -ENOMEM; ret = -EFAULT; if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) goto out; ret = ops->set_eeprom(dev, &eeprom, data); if (ret) goto out; if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) ret = -EFAULT; out: kfree(data); return ret; } static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) { struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; if (!ethtool_ops->get_coalesce) return -EOPNOTSUPP; ethtool_ops->get_coalesce(dev, &coalesce); if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) return -EFAULT; return 0; } static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) { struct ethtool_coalesce coalesce; if (!ethtool_ops->get_coalesce) return -EOPNOTSUPP; if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) return -EFAULT; return ethtool_ops->set_coalesce(dev, &coalesce); } static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) { struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; if (!ethtool_ops->get_ringparam) return -EOPNOTSUPP; ethtool_ops->get_ringparam(dev, &ringparam); if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) return -EFAULT; return 0; } static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) { struct ethtool_ringparam ringparam; if (!ethtool_ops->get_ringparam) return -EOPNOTSUPP; if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) return -EFAULT; return ethtool_ops->set_ringparam(dev, &ringparam); } static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) { struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; if (!ethtool_ops->get_pauseparam) return -EOPNOTSUPP; ethtool_ops->get_pauseparam(dev, &pauseparam); if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) return -EFAULT; return 0; } static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) { struct ethtool_pauseparam pauseparam; if (!ethtool_ops->get_pauseparam) return -EOPNOTSUPP; if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) return -EFAULT; return ethtool_ops->set_pauseparam(dev, &pauseparam); } static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) { struct ethtool_value edata = { ETHTOOL_GRXCSUM }; if (!ethtool_ops->get_rx_csum) return -EOPNOTSUPP; edata.data = ethtool_ops->get_rx_csum(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) { struct ethtool_value edata; if (!ethtool_ops->set_rx_csum) return -EOPNOTSUPP; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; ethtool_ops->set_rx_csum(dev, edata.data); return 0; } static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) { struct ethtool_value edata = { ETHTOOL_GTXCSUM }; if (!ethtool_ops->get_tx_csum) return -EOPNOTSUPP; edata.data = ethtool_ops->get_tx_csum(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) { struct ethtool_value edata; if (!ethtool_ops->set_tx_csum) return -EOPNOTSUPP; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; return ethtool_ops->set_tx_csum(dev, edata.data); } static int ethtool_get_sg(struct net_device *dev, char *useraddr) { struct ethtool_value edata = { ETHTOOL_GSG }; if (!ethtool_ops->get_sg) return -EOPNOTSUPP; edata.data = ethtool_ops->get_sg(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_set_sg(struct net_device *dev, char *useraddr) { struct ethtool_value edata; if (!ethtool_ops->set_sg) return -EOPNOTSUPP; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; return ethtool_ops->set_sg(dev, edata.data); } static int ethtool_get_tso(struct net_device *dev, char *useraddr) { struct ethtool_value edata = { ETHTOOL_GTSO }; if (!ethtool_ops->get_tso) return -EOPNOTSUPP; edata.data = ethtool_ops->get_tso(dev); if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } static int ethtool_set_tso(struct net_device *dev, char *useraddr) { struct ethtool_value edata; if (!ethtool_ops->set_tso) return -EOPNOTSUPP; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; return ethtool_ops->set_tso(dev, edata.data); } static int ethtool_self_test(struct net_device *dev, char *useraddr) { struct ethtool_test test; struct ethtool_ops *ops = ethtool_ops; u64 *data; int ret; if (!ops->self_test || !ops->self_test_count) return -EOPNOTSUPP; if (copy_from_user(&test, useraddr, sizeof(test))) return -EFAULT; test.len = ops->self_test_count(dev); data = kmalloc(test.len * sizeof(u64), GFP_USER); if (!data) return -ENOMEM; ops->self_test(dev, &test, data); ret = -EFAULT; if (copy_to_user(useraddr, &test, sizeof(test))) goto out; useraddr += sizeof(test); if (copy_to_user(useraddr, data, test.len * sizeof(u64))) goto out; ret = 0; out: kfree(data); return ret; } static int ethtool_get_strings(struct net_device *dev, void *useraddr) { struct ethtool_gstrings gstrings; struct ethtool_ops *ops = ethtool_ops; u8 *data; int ret; if (!ops->get_strings) return -EOPNOTSUPP; if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) return -EFAULT; switch (gstrings.string_set) { case ETH_SS_TEST: if (!ops->self_test_count) return -EOPNOTSUPP; gstrings.len = ops->self_test_count(dev); break; case ETH_SS_STATS: if (!ops->get_stats_count) return -EOPNOTSUPP; gstrings.len = ops->get_stats_count(dev); break; default: return -EINVAL; } data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); if (!data) return -ENOMEM; ops->get_strings(dev, gstrings.string_set, data); ret = -EFAULT; if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) goto out; useraddr += sizeof(gstrings); if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) goto out; ret = 0; out: kfree(data); return ret; } static int ethtool_phys_id(struct net_device *dev, void *useraddr) { struct ethtool_value id; if (!ethtool_ops->phys_id) return -EOPNOTSUPP; if (copy_from_user(&id, useraddr, sizeof(id))) return -EFAULT; return ethtool_ops->phys_id(dev, id.data); } static int ethtool_get_stats(struct net_device *dev, void *useraddr) { struct ethtool_stats stats; struct ethtool_ops *ops = ethtool_ops; u64 *data; int ret; if (!ops->get_ethtool_stats || !ops->get_stats_count) return -EOPNOTSUPP; if (copy_from_user(&stats, useraddr, sizeof(stats))) return -EFAULT; stats.n_stats = ops->get_stats_count(dev); data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); if (!data) return -ENOMEM; ops->get_ethtool_stats(dev, &stats, data); ret = -EFAULT; if (copy_to_user(useraddr, &stats, sizeof(stats))) goto out; useraddr += sizeof(stats); if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) goto out; ret = 0; out: kfree(data); return ret; } /* The main entry point in this file. Called from net/core/dev.c */ #define ETHTOOL_OPS_COMPAT int ethtool_ioctl(struct ifreq *ifr) { struct net_device *dev = __dev_get_by_name(ifr->ifr_name); void *useraddr = (void *) ifr->ifr_data; u32 ethcmd; /* * XXX: This can be pushed down into the ethtool_* handlers that * need it. Keep existing behavior for the moment. */ if (!capable(CAP_NET_ADMIN)) return -EPERM; if (!dev || !netif_device_present(dev)) return -ENODEV; if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) return -EFAULT; switch (ethcmd) { case ETHTOOL_GSET: return ethtool_get_settings(dev, useraddr); case ETHTOOL_SSET: return ethtool_set_settings(dev, useraddr); case ETHTOOL_GDRVINFO: return ethtool_get_drvinfo(dev, useraddr); case ETHTOOL_GREGS: return ethtool_get_regs(dev, useraddr); case ETHTOOL_GWOL: return ethtool_get_wol(dev, useraddr); case ETHTOOL_SWOL: return ethtool_set_wol(dev, useraddr); case ETHTOOL_GMSGLVL: return ethtool_get_msglevel(dev, useraddr); case ETHTOOL_SMSGLVL: return ethtool_set_msglevel(dev, useraddr); case ETHTOOL_NWAY_RST: return ethtool_nway_reset(dev); case ETHTOOL_GLINK: return ethtool_get_link(dev, useraddr); case ETHTOOL_GEEPROM: return ethtool_get_eeprom(dev, useraddr); case ETHTOOL_SEEPROM: return ethtool_set_eeprom(dev, useraddr); case ETHTOOL_GCOALESCE: return ethtool_get_coalesce(dev, useraddr); case ETHTOOL_SCOALESCE: return ethtool_set_coalesce(dev, useraddr); case ETHTOOL_GRINGPARAM: return ethtool_get_ringparam(dev, useraddr); case ETHTOOL_SRINGPARAM: return ethtool_set_ringparam(dev, useraddr); case ETHTOOL_GPAUSEPARAM: return ethtool_get_pauseparam(dev, useraddr); case ETHTOOL_SPAUSEPARAM: return ethtool_set_pauseparam(dev, useraddr); case ETHTOOL_GRXCSUM: return ethtool_get_rx_csum(dev, useraddr); case ETHTOOL_SRXCSUM: return ethtool_set_rx_csum(dev, useraddr); case ETHTOOL_GTXCSUM: return ethtool_get_tx_csum(dev, useraddr); case ETHTOOL_STXCSUM: return ethtool_set_tx_csum(dev, useraddr); case ETHTOOL_GSG: return ethtool_get_sg(dev, useraddr); case ETHTOOL_SSG: return ethtool_set_sg(dev, useraddr); case ETHTOOL_GTSO: return ethtool_get_tso(dev, useraddr); case ETHTOOL_STSO: return ethtool_set_tso(dev, useraddr); case ETHTOOL_TEST: return ethtool_self_test(dev, useraddr); case ETHTOOL_GSTRINGS: return ethtool_get_strings(dev, useraddr); case ETHTOOL_PHYS_ID: return ethtool_phys_id(dev, useraddr); case ETHTOOL_GSTATS: return ethtool_get_stats(dev, useraddr); default: return -EOPNOTSUPP; } return -EOPNOTSUPP; } #define mii_if_info _kc_mii_if_info struct _kc_mii_if_info { int phy_id; int advertising; int phy_id_mask; int reg_num_mask; unsigned int full_duplex : 1; /* is full duplex? */ unsigned int force_media : 1; /* is autoneg. disabled? */ struct net_device *dev; int (*mdio_read) (struct net_device *dev, int phy_id, int location); void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val); }; struct ethtool_cmd; struct mii_ioctl_data; #undef mii_link_ok #define mii_link_ok _kc_mii_link_ok #undef mii_nway_restart #define mii_nway_restart _kc_mii_nway_restart #undef mii_ethtool_gset #define mii_ethtool_gset _kc_mii_ethtool_gset #undef mii_ethtool_sset #define mii_ethtool_sset _kc_mii_ethtool_sset #undef mii_check_link #define mii_check_link _kc_mii_check_link extern int _kc_mii_link_ok (struct mii_if_info *mii); extern int _kc_mii_nway_restart (struct mii_if_info *mii); extern int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); extern int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd); extern void _kc_mii_check_link (struct mii_if_info *mii); #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) ) #undef generic_mii_ioctl #define generic_mii_ioctl _kc_generic_mii_ioctl extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, struct mii_ioctl_data *mii_data, int cmd, unsigned int *duplex_changed); #endif /* > 2.4.6 */ struct _kc_pci_dev_ext { struct pci_dev *dev; void *pci_drvdata; struct pci_driver *driver; }; struct _kc_net_dev_ext { struct net_device *dev; unsigned int carrier; }; /**************************************/ /* mii support */ int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { struct net_device *dev = mii->dev; u32 advert, bmcr, lpa, nego; ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); /* only supports twisted-pair */ ecmd->port = PORT_MII; /* only supports internal transceiver */ ecmd->transceiver = XCVR_INTERNAL; /* this isn't fully supported at higher layers */ ecmd->phy_address = mii->phy_id; ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); if (advert & ADVERTISE_10HALF) ecmd->advertising |= ADVERTISED_10baseT_Half; if (advert & ADVERTISE_10FULL) ecmd->advertising |= ADVERTISED_10baseT_Full; if (advert & ADVERTISE_100HALF) ecmd->advertising |= ADVERTISED_100baseT_Half; if (advert & ADVERTISE_100FULL) ecmd->advertising |= ADVERTISED_100baseT_Full; bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA); if (bmcr & BMCR_ANENABLE) { ecmd->advertising |= ADVERTISED_Autoneg; ecmd->autoneg = AUTONEG_ENABLE; nego = mii_nway_result(advert & lpa); if (nego == LPA_100FULL || nego == LPA_100HALF) ecmd->speed = SPEED_100; else ecmd->speed = SPEED_10; if (nego == LPA_100FULL || nego == LPA_10FULL) { ecmd->duplex = DUPLEX_FULL; mii->full_duplex = 1; } else { ecmd->duplex = DUPLEX_HALF; mii->full_duplex = 0; } } else { ecmd->autoneg = AUTONEG_DISABLE; ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10; ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; } /* ignore maxtxpkt, maxrxpkt for now */ return 0; } int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { struct net_device *dev = mii->dev; if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) return -EINVAL; if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) return -EINVAL; if (ecmd->port != PORT_MII) return -EINVAL; if (ecmd->transceiver != XCVR_INTERNAL) return -EINVAL; if (ecmd->phy_address != mii->phy_id) return -EINVAL; if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) return -EINVAL; /* ignore supported, maxtxpkt, maxrxpkt */ if (ecmd->autoneg == AUTONEG_ENABLE) { u32 bmcr, advert, tmp; if ((ecmd->advertising & (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full)) == 0) return -EINVAL; /* advertise only what has been requested */ advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); if (ADVERTISED_10baseT_Half) tmp |= ADVERTISE_10HALF; if (ADVERTISED_10baseT_Full) tmp |= ADVERTISE_10FULL; if (ADVERTISED_100baseT_Half) tmp |= ADVERTISE_100HALF; if (ADVERTISED_100baseT_Full) tmp |= ADVERTISE_100FULL; if (advert != tmp) { mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); mii->advertising = tmp; } /* turn on autonegotiation, and force a renegotiate */ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); mii->force_media = 0; } else { u32 bmcr, tmp; /* turn off auto negotiation, set speed and duplexity */ bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX); if (ecmd->speed == SPEED_100) tmp |= BMCR_SPEED100; if (ecmd->duplex == DUPLEX_FULL) { tmp |= BMCR_FULLDPLX; mii->full_duplex = 1; } else mii->full_duplex = 0; if (bmcr != tmp) mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); mii->force_media = 1; } return 0; } int _kc_mii_link_ok (struct mii_if_info *mii) { /* first, a dummy read, needed to latch some MII phys */ mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) return 1; return 0; } int _kc_mii_nway_restart (struct mii_if_info *mii) { int bmcr; int r = -EINVAL; /* if autoneg is off, it's an error */ bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); if (bmcr & BMCR_ANENABLE) { bmcr |= BMCR_ANRESTART; mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); r = 0; } return r; } void _kc_mii_check_link (struct mii_if_info *mii) { int cur_link = mii_link_ok(mii); int prev_link = netif_carrier_ok(mii->dev); if (cur_link && !prev_link) netif_carrier_on(mii->dev); else if (prev_link && !cur_link) netif_carrier_off(mii->dev); } #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) ) int _kc_generic_mii_ioctl(struct mii_if_info *mii_if, struct mii_ioctl_data *mii_data, int cmd, unsigned int *duplex_chg_out) { int rc = 0; unsigned int duplex_changed = 0; if (duplex_chg_out) *duplex_chg_out = 0; mii_data->phy_id &= mii_if->phy_id_mask; mii_data->reg_num &= mii_if->reg_num_mask; switch(cmd) { case SIOCDEVPRIVATE: /* binary compat, remove in 2.5 */ case SIOCGMIIPHY: mii_data->phy_id = mii_if->phy_id; /* fall through */ case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */ case SIOCGMIIREG: mii_data->val_out = mii_if->mdio_read(mii_if->dev, mii_data->phy_id, mii_data->reg_num); break; case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */ case SIOCSMIIREG: { u16 val = mii_data->val_in; if (!capable(CAP_NET_ADMIN)) return -EPERM; if (mii_data->phy_id == mii_if->phy_id) { switch(mii_data->reg_num) { case MII_BMCR: { unsigned int new_duplex = 0; if (val & (BMCR_RESET|BMCR_ANENABLE)) mii_if->force_media = 0; else mii_if->force_media = 1; if (mii_if->force_media && (val & BMCR_FULLDPLX)) new_duplex = 1; if (mii_if->full_duplex != new_duplex) { duplex_changed = 1; mii_if->full_duplex = new_duplex; } break; } case MII_ADVERTISE: mii_if->advertising = val; break; default: /* do nothing */ break; } } mii_if->mdio_write(mii_if->dev, mii_data->phy_id, mii_data->reg_num, val); break; } default: rc = -EOPNOTSUPP; break; } if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) *duplex_chg_out = 1; return rc; } #endif /* > 2.4.6 */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/COPYING ================================================ "This software program is licensed subject to the GNU General Public License (GPL). Version 2, June 1991, available at " GNU General Public License Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: * a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. * b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. * c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: * a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine- readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, * c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free software, and you are welcome to redistribute it under certain conditions; type 'show c' for details. The hypothetical commands 'show w' and 'show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than 'show w' and 'show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program 'Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_H_ #define _IXGBE_H_ #ifndef IXGBE_NO_LRO #include #endif #include #include #ifdef HAVE_IRQ_AFFINITY_HINT #include #endif /* HAVE_IRQ_AFFINITY_HINT */ #include #ifdef SIOCETHTOOL #include #endif #ifdef NETIF_F_HW_VLAN_TX #include #endif #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) #define IXGBE_DCA #include #endif #include "ixgbe_dcb.h" #include "kcompat.h" #ifdef HAVE_SCTP #include #endif #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #define IXGBE_FCOE #include "ixgbe_fcoe.h" #endif /* CONFIG_FCOE or CONFIG_FCOE_MODULE */ #if defined(CONFIG_PTP_1588_CLOCK) || defined(CONFIG_PTP_1588_CLOCK_MODULE) #define HAVE_IXGBE_PTP #endif #include "ixgbe_api.h" #define PFX "ixgbe: " #define DPRINTK(nlevel, klevel, fmt, args...) \ ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ __func__ , ## args))) /* TX/RX descriptor defines */ #define IXGBE_DEFAULT_TXD 512 #define IXGBE_DEFAULT_TX_WORK 256 #define IXGBE_MAX_TXD 4096 #define IXGBE_MIN_TXD 64 #define IXGBE_DEFAULT_RXD 512 #define IXGBE_DEFAULT_RX_WORK 256 #define IXGBE_MAX_RXD 4096 #define IXGBE_MIN_RXD 64 /* flow control */ #define IXGBE_MIN_FCRTL 0x40 #define IXGBE_MAX_FCRTL 0x7FF80 #define IXGBE_MIN_FCRTH 0x600 #define IXGBE_MAX_FCRTH 0x7FFF0 #define IXGBE_DEFAULT_FCPAUSE 0xFFFF #define IXGBE_MIN_FCPAUSE 0 #define IXGBE_MAX_FCPAUSE 0xFFFF /* Supported Rx Buffer Sizes */ #define IXGBE_RXBUFFER_512 512 /* Used for packet split */ #ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT #define IXGBE_RXBUFFER_1536 1536 #define IXGBE_RXBUFFER_2K 2048 #define IXGBE_RXBUFFER_3K 3072 #define IXGBE_RXBUFFER_4K 4096 #define IXGBE_RXBUFFER_7K 7168 #define IXGBE_RXBUFFER_8K 8192 #define IXGBE_RXBUFFER_15K 15360 #endif /* CONFIG_IXGBE_DISABLE_PACKET_SPLIT */ #define IXGBE_MAX_RXBUFFER 16384 /* largest size for single descriptor */ /* * NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN mans we * reserve 2 more, and skb_shared_info adds an additional 384 bytes more, * this adds up to 512 bytes of extra data meaning the smallest allocation * we could have is 1K. * i.e. RXBUFFER_512 --> size-1024 slab */ #define IXGBE_RX_HDR_SIZE IXGBE_RXBUFFER_512 #define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define IXGBE_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define IXGBE_TX_FLAGS_CSUM (u32)(1) #define IXGBE_TX_FLAGS_HW_VLAN (u32)(1 << 1) #define IXGBE_TX_FLAGS_SW_VLAN (u32)(1 << 2) #define IXGBE_TX_FLAGS_TSO (u32)(1 << 3) #define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 4) #define IXGBE_TX_FLAGS_FCOE (u32)(1 << 5) #define IXGBE_TX_FLAGS_FSO (u32)(1 << 6) #define IXGBE_TX_FLAGS_TXSW (u32)(1 << 7) #define IXGBE_TX_FLAGS_TSTAMP (u32)(1 << 8) #define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000 #define IXGBE_TX_FLAGS_VLAN_PRIO_SHIFT 29 #define IXGBE_TX_FLAGS_VLAN_SHIFT 16 #define IXGBE_MAX_RX_DESC_POLL 10 #define IXGBE_MAX_VF_MC_ENTRIES 30 #define IXGBE_MAX_VF_FUNCTIONS 64 #define IXGBE_MAX_VFTA_ENTRIES 128 #define MAX_EMULATION_MAC_ADDRS 16 #define IXGBE_MAX_PF_MACVLANS 15 #define IXGBE_82599_VF_DEVICE_ID 0x10ED #define IXGBE_X540_VF_DEVICE_ID 0x1515 #ifdef CONFIG_PCI_IOV #define VMDQ_P(p) ((p) + adapter->num_vfs) #else #define VMDQ_P(p) (p) #endif #define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \ { \ u32 current_counter = IXGBE_READ_REG(hw, reg); \ if (current_counter < last_counter) \ counter += 0x100000000LL; \ last_counter = current_counter; \ counter &= 0xFFFFFFFF00000000LL; \ counter |= current_counter; \ } #define UPDATE_VF_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \ { \ u64 current_counter_lsb = IXGBE_READ_REG(hw, reg_lsb); \ u64 current_counter_msb = IXGBE_READ_REG(hw, reg_msb); \ u64 current_counter = (current_counter_msb << 32) | \ current_counter_lsb; \ if (current_counter < last_counter) \ counter += 0x1000000000LL; \ last_counter = current_counter; \ counter &= 0xFFFFFFF000000000LL; \ counter |= current_counter; \ } struct vf_stats { u64 gprc; u64 gorc; u64 gptc; u64 gotc; u64 mprc; }; struct vf_data_storage { unsigned char vf_mac_addresses[ETH_ALEN]; u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES]; u16 num_vf_mc_hashes; u16 default_vf_vlan_id; u16 vlans_enabled; bool clear_to_send; struct vf_stats vfstats; struct vf_stats last_vfstats; struct vf_stats saved_rst_vfstats; bool pf_set_mac; u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_qos; u16 tx_rate; u16 vlan_count; u8 spoofchk_enabled; struct pci_dev *vfdev; }; struct vf_macvlans { struct list_head l; int vf; bool free; bool is_macvlan; u8 vf_macvlan[ETH_ALEN]; }; #ifndef IXGBE_NO_LRO #define IXGBE_LRO_MAX 32 /*Maximum number of LRO descriptors*/ #define IXGBE_LRO_GLOBAL 10 struct ixgbe_lro_stats { u32 flushed; u32 coal; }; /* * ixgbe_lro_header - header format to be aggregated by LRO * @iph: IP header without options * @tcp: TCP header * @ts: Optional TCP timestamp data in TCP options * * This structure relies on the check above that verifies that the header * is IPv4 and does not contain any options. */ struct ixgbe_lrohdr { struct iphdr iph; struct tcphdr th; __be32 ts[0]; }; struct ixgbe_lro_list { struct sk_buff_head active; struct ixgbe_lro_stats stats; }; #endif /* IXGBE_NO_LRO */ #define IXGBE_MAX_TXD_PWR 14 #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) /* Tx Descriptors needed, worst case */ #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD) #ifdef MAX_SKB_FRAGS #define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4) #else #define DESC_NEEDED 4 #endif /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer { union ixgbe_adv_tx_desc *next_to_watch; unsigned long time_stamp; struct sk_buff *skb; unsigned int bytecount; unsigned short gso_segs; __be16 protocol; DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); u32 tx_flags; }; struct ixgbe_rx_buffer { struct sk_buff *skb; dma_addr_t dma; #ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT struct page *page; unsigned int page_offset; #endif }; struct ixgbe_queue_stats { u64 packets; u64 bytes; }; struct ixgbe_tx_queue_stats { u64 restart_queue; u64 tx_busy; u64 tx_done_old; }; struct ixgbe_rx_queue_stats { u64 rsc_count; u64 rsc_flush; u64 non_eop_descs; u64 alloc_rx_page_failed; u64 alloc_rx_buff_failed; u64 csum_err; }; enum ixgbe_ring_state_t { __IXGBE_TX_FDIR_INIT_DONE, __IXGBE_TX_DETECT_HANG, __IXGBE_HANG_CHECK_ARMED, __IXGBE_RX_RSC_ENABLED, #ifndef HAVE_NDO_SET_FEATURES __IXGBE_RX_CSUM_ENABLED, #endif __IXGBE_RX_CSUM_UDP_ZERO_ERR, #ifdef IXGBE_FCOE __IXGBE_RX_FCOE_BUFSZ, #endif }; #define check_for_tx_hang(ring) \ test_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) #define set_check_for_tx_hang(ring) \ set_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) #define clear_check_for_tx_hang(ring) \ clear_bit(__IXGBE_TX_DETECT_HANG, &(ring)->state) #ifndef IXGBE_NO_HW_RSC #define ring_is_rsc_enabled(ring) \ test_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) #else #define ring_is_rsc_enabled(ring) false #endif #define set_ring_rsc_enabled(ring) \ set_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) #define clear_ring_rsc_enabled(ring) \ clear_bit(__IXGBE_RX_RSC_ENABLED, &(ring)->state) #define netdev_ring(ring) (ring->netdev) #define ring_queue_index(ring) (ring->queue_index) struct ixgbe_ring { struct ixgbe_ring *next; /* pointer to next ring in q_vector */ struct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */ struct net_device *netdev; /* netdev ring belongs to */ struct device *dev; /* device for DMA mapping */ void *desc; /* descriptor ring memory */ union { struct ixgbe_tx_buffer *tx_buffer_info; struct ixgbe_rx_buffer *rx_buffer_info; }; unsigned long state; u8 __iomem *tail; dma_addr_t dma; /* phys. address of descriptor ring */ unsigned int size; /* length in bytes */ u16 count; /* amount of descriptors */ u8 queue_index; /* needed for multiqueue queue management */ u8 reg_idx; /* holds the special value that gets * the hardware register offset * associated with this ring, which is * different for DCB and RSS modes */ u16 next_to_use; u16 next_to_clean; union { #ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT u16 rx_buf_len; #else u16 next_to_alloc; #endif struct { u8 atr_sample_rate; u8 atr_count; }; }; u8 dcb_tc; struct ixgbe_queue_stats stats; union { struct ixgbe_tx_queue_stats tx_stats; struct ixgbe_rx_queue_stats rx_stats; }; } ____cacheline_internodealigned_in_smp; enum ixgbe_ring_f_enum { RING_F_NONE = 0, RING_F_VMDQ, /* SR-IOV uses the same ring feature */ RING_F_RSS, RING_F_FDIR, #ifdef IXGBE_FCOE RING_F_FCOE, #endif /* IXGBE_FCOE */ RING_F_ARRAY_SIZE /* must be last in enum set */ }; #define IXGBE_MAX_DCB_INDICES 8 #define IXGBE_MAX_RSS_INDICES 16 #define IXGBE_MAX_VMDQ_INDICES 64 #define IXGBE_MAX_FDIR_INDICES 64 #ifdef IXGBE_FCOE #define IXGBE_MAX_FCOE_INDICES 8 #define MAX_RX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES) #define MAX_TX_QUEUES (IXGBE_MAX_FDIR_INDICES + IXGBE_MAX_FCOE_INDICES) #else #define MAX_RX_QUEUES IXGBE_MAX_FDIR_INDICES #define MAX_TX_QUEUES IXGBE_MAX_FDIR_INDICES #endif /* IXGBE_FCOE */ struct ixgbe_ring_feature { int indices; int mask; }; #ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT /* * FCoE requires that all Rx buffers be over 2200 bytes in length. Since * this is twice the size of a half page we need to double the page order * for FCoE enabled Rx queues. */ #if defined(IXGBE_FCOE) && (PAGE_SIZE < 8192) static inline unsigned int ixgbe_rx_pg_order(struct ixgbe_ring *ring) { return test_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state) ? 1 : 0; } #else #define ixgbe_rx_pg_order(_ring) 0 #endif #define ixgbe_rx_pg_size(_ring) (PAGE_SIZE << ixgbe_rx_pg_order(_ring)) #define ixgbe_rx_bufsz(_ring) ((PAGE_SIZE / 2) << ixgbe_rx_pg_order(_ring)) #endif struct ixgbe_ring_container { struct ixgbe_ring *ring; /* pointer to linked list of rings */ unsigned int total_bytes; /* total bytes processed this int */ unsigned int total_packets; /* total packets processed this int */ u16 work_limit; /* total work allowed per interrupt */ u8 count; /* total number of rings in vector */ u8 itr; /* current ITR setting for ring */ }; /* iterator for handling rings in ring container */ #define ixgbe_for_each_ring(pos, head) \ for (pos = (head).ring; pos != NULL; pos = pos->next) #define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \ ? 8 : 1) #define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS /* MAX_MSIX_Q_VECTORS of these are allocated, * but we only use one per queue-specific vector. */ struct ixgbe_q_vector { struct ixgbe_adapter *adapter; int cpu; /* CPU for DCA */ u16 v_idx; /* index of q_vector within array, also used for * finding the bit in EICR and friends that * represents the vector for this ring */ u16 itr; /* Interrupt throttle rate written to EITR */ struct ixgbe_ring_container rx, tx; #ifdef CONFIG_IXGBE_NAPI struct napi_struct napi; #endif #ifndef HAVE_NETDEV_NAPI_LIST struct net_device poll_dev; #endif #ifdef HAVE_IRQ_AFFINITY_HINT cpumask_t affinity_mask; #endif #ifndef IXGBE_NO_LRO struct ixgbe_lro_list lrolist; /* LRO list for queue vector*/ #endif int numa_node; char name[IFNAMSIZ + 9]; /* for dynamic allocation of rings associated with this q_vector */ struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp; }; /* * microsecond values for various ITR rates shifted by 2 to fit itr register * with the first 3 bits reserved 0 */ #define IXGBE_MIN_RSC_ITR 24 #define IXGBE_100K_ITR 40 #define IXGBE_20K_ITR 200 #define IXGBE_16K_ITR 248 #define IXGBE_10K_ITR 400 #define IXGBE_8K_ITR 500 /* ixgbe_test_staterr - tests bits in Rx descriptor status and error fields */ static inline __le32 ixgbe_test_staterr(union ixgbe_adv_rx_desc *rx_desc, const u32 stat_err_bits) { return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits); } /* ixgbe_desc_unused - calculate if we have unused descriptors */ static inline u16 ixgbe_desc_unused(struct ixgbe_ring *ring) { u16 ntc = ring->next_to_clean; u16 ntu = ring->next_to_use; return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1; } #define IXGBE_RX_DESC(R, i) \ (&(((union ixgbe_adv_rx_desc *)((R)->desc))[i])) #define IXGBE_TX_DESC(R, i) \ (&(((union ixgbe_adv_tx_desc *)((R)->desc))[i])) #define IXGBE_TX_CTXTDESC(R, i) \ (&(((struct ixgbe_adv_tx_context_desc *)((R)->desc))[i])) #define IXGBE_MAX_JUMBO_FRAME_SIZE 16128 #ifdef IXGBE_FCOE /* use 3K as the baby jumbo frame size for FCoE */ #define IXGBE_FCOE_JUMBO_FRAME_SIZE 3072 #endif /* IXGBE_FCOE */ #define TCP_TIMER_VECTOR 0 #define OTHER_VECTOR 1 #define NON_Q_VECTORS (OTHER_VECTOR + TCP_TIMER_VECTOR) #define IXGBE_MAX_MSIX_Q_VECTORS_82599 64 #define IXGBE_MAX_MSIX_Q_VECTORS_82598 16 struct ixgbe_mac_addr { u8 addr[ETH_ALEN]; u16 queue; u16 state; /* bitmask */ }; #define IXGBE_MAC_STATE_DEFAULT 0x1 #define IXGBE_MAC_STATE_MODIFIED 0x2 #define IXGBE_MAC_STATE_IN_USE 0x4 #ifdef IXGBE_PROCFS struct ixgbe_therm_proc_data { struct ixgbe_hw *hw; struct ixgbe_thermal_diode_data *sensor_data; }; #endif /* IXGBE_PROCFS */ /* * Only for array allocations in our adapter struct. On 82598, there will be * unused entries in the array, but that's not a big deal. Also, in 82599, * we can actually assign 64 queue vectors based on our extended-extended * interrupt registers. This is different than 82598, which is limited to 16. */ #define MAX_MSIX_Q_VECTORS IXGBE_MAX_MSIX_Q_VECTORS_82599 #define MAX_MSIX_COUNT IXGBE_MAX_MSIX_VECTORS_82599 #define MIN_MSIX_Q_VECTORS 1 #define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS) /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) /* board specific private data structure */ struct ixgbe_adapter { #ifdef NETIF_F_HW_VLAN_TX #ifdef HAVE_VLAN_RX_REGISTER struct vlan_group *vlgrp; /* must be first, see ixgbe_receive_skb */ #else unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; #endif #endif /* NETIF_F_HW_VLAN_TX */ /* OS defined structs */ struct net_device *netdev; struct pci_dev *pdev; unsigned long state; /* Some features need tri-state capability, * thus the additional *_CAPABLE flags. */ u32 flags; #define IXGBE_FLAG_MSI_CAPABLE (u32)(1 << 0) #define IXGBE_FLAG_MSI_ENABLED (u32)(1 << 1) #define IXGBE_FLAG_MSIX_CAPABLE (u32)(1 << 2) #define IXGBE_FLAG_MSIX_ENABLED (u32)(1 << 3) #ifndef IXGBE_NO_LLI #define IXGBE_FLAG_LLI_PUSH (u32)(1 << 4) #endif #define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 8) #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) #define IXGBE_FLAG_DCA_ENABLED (u32)(1 << 9) #define IXGBE_FLAG_DCA_CAPABLE (u32)(1 << 10) #define IXGBE_FLAG_DCA_ENABLED_DATA (u32)(1 << 11) #else #define IXGBE_FLAG_DCA_ENABLED (u32)0 #define IXGBE_FLAG_DCA_CAPABLE (u32)0 #define IXGBE_FLAG_DCA_ENABLED_DATA (u32)0 #endif #define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 12) #define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 13) #define IXGBE_FLAG_DCB_CAPABLE (u32)(1 << 14) #define IXGBE_FLAG_RSS_ENABLED (u32)(1 << 15) #define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 16) #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 18) #define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 19) #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 20) #define IXGBE_FLAG_NEED_LINK_CONFIG (u32)(1 << 21) #define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 22) #define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 23) #ifdef IXGBE_FCOE #define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 24) #define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 25) #endif /* IXGBE_FCOE */ #define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 26) #define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 27) #define IXGBE_FLAG_SRIOV_REPLICATION_ENABLE (u32)(1 << 28) #define IXGBE_FLAG_SRIOV_L2SWITCH_ENABLE (u32)(1 << 29) #define IXGBE_FLAG_SRIOV_L2LOOPBACK_ENABLE (u32)(1 << 30) #define IXGBE_FLAG_RX_BB_CAPABLE (u32)(1 << 31) u32 flags2; #ifndef IXGBE_NO_HW_RSC #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) #define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) #else #define IXGBE_FLAG2_RSC_CAPABLE 0 #define IXGBE_FLAG2_RSC_ENABLED 0 #endif #define IXGBE_FLAG2_VMDQ_DEFAULT_OVERRIDE (u32)(1 << 2) #define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 4) #define IXGBE_FLAG2_TEMP_SENSOR_EVENT (u32)(1 << 5) #define IXGBE_FLAG2_SEARCH_FOR_SFP (u32)(1 << 6) #define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 7) #define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 8) #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 9) #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 10) #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 11) #define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED (u32)(1 << 12) /* Tx fast path data */ int num_tx_queues; u16 tx_itr_setting; u16 tx_work_limit; /* Rx fast path data */ int num_rx_queues; u16 rx_itr_setting; u16 rx_work_limit; /* TX */ struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; u64 restart_queue; u64 lsc_int; u32 tx_timeout_count; /* RX */ struct ixgbe_ring *rx_ring[MAX_RX_QUEUES]; int num_rx_pools; /* == num_rx_queues in 82598 */ int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */ u64 hw_csum_rx_error; u64 hw_rx_no_dma_resources; u64 rsc_total_count; u64 rsc_total_flush; u64 non_eop_descs; #ifndef CONFIG_IXGBE_NAPI u64 rx_dropped_backlog; /* count drops from rx intr handler */ #endif u32 alloc_rx_page_failed; u32 alloc_rx_buff_failed; struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; #ifdef HAVE_DCBNL_IEEE struct ieee_pfc *ixgbe_ieee_pfc; struct ieee_ets *ixgbe_ieee_ets; #endif struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg; u8 dcb_set_bitmap; u8 dcbx_cap; #ifndef HAVE_MQPRIO u8 tc; #endif enum ixgbe_fc_mode last_lfc_mode; int num_msix_vectors; int max_msix_q_vectors; /* true count of q_vectors for device */ struct ixgbe_ring_feature ring_feature[RING_F_ARRAY_SIZE]; struct msix_entry *msix_entries; #ifndef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats net_stats; #endif #ifndef IXGBE_NO_LRO struct ixgbe_lro_stats lro_stats; #endif #ifdef ETHTOOL_TEST u32 test_icr; struct ixgbe_ring test_tx_ring; struct ixgbe_ring test_rx_ring; #endif /* structs defined in ixgbe_hw.h */ struct ixgbe_hw hw; u16 msg_enable; struct ixgbe_hw_stats stats; #ifndef IXGBE_NO_LLI u32 lli_port; u32 lli_size; u32 lli_etype; u32 lli_vlan_pri; #endif /* IXGBE_NO_LLI */ u32 *config_space; u64 tx_busy; unsigned int tx_ring_count; unsigned int rx_ring_count; u32 link_speed; bool link_up; unsigned long link_check_timeout; struct timer_list service_timer; struct work_struct service_task; struct hlist_head fdir_filter_list; unsigned long fdir_overflow; /* number of times ATR was backed off */ union ixgbe_atr_input fdir_mask; int fdir_filter_count; u32 fdir_pballoc; u32 atr_sample_rate; spinlock_t fdir_perfect_lock; #ifdef IXGBE_FCOE struct ixgbe_fcoe fcoe; #endif /* IXGBE_FCOE */ u32 wol; u16 bd_number; char eeprom_id[32]; u16 eeprom_cap; bool netdev_registered; u32 interrupt_event; #ifdef HAVE_ETHTOOL_SET_PHYS_ID u32 led_reg; #endif DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); unsigned int num_vfs; struct vf_data_storage *vfinfo; int vf_rate_link_speed; struct vf_macvlans vf_mvs; struct vf_macvlans *mv_list; #ifdef CONFIG_PCI_IOV u32 timer_event_accumulator; u32 vferr_refcount; #endif struct ixgbe_mac_addr *mac_table; #ifdef IXGBE_SYSFS struct kobject *info_kobj; struct kobject *therm_kobj[IXGBE_MAX_SENSORS]; #else /* IXGBE_SYSFS */ #ifdef IXGBE_PROCFS struct proc_dir_entry *eth_dir; struct proc_dir_entry *info_dir; struct proc_dir_entry *therm_dir[IXGBE_MAX_SENSORS]; struct ixgbe_therm_proc_data therm_data[IXGBE_MAX_SENSORS]; #endif /* IXGBE_PROCFS */ #endif /* IXGBE_SYSFS */ }; struct ixgbe_fdir_filter { struct hlist_node fdir_node; union ixgbe_atr_input filter; u16 sw_idx; u16 action; }; enum ixgbe_state_t { __IXGBE_TESTING, __IXGBE_RESETTING, __IXGBE_DOWN, __IXGBE_SERVICE_SCHED, __IXGBE_IN_SFP_INIT, }; struct ixgbe_cb { #ifdef CONFIG_IXGBE_DISABLE_PACKET_SPLIT union { /* Union defining head/tail partner */ struct sk_buff *head; struct sk_buff *tail; }; #endif dma_addr_t dma; #ifndef IXGBE_NO_LRO __be32 tsecr; /* timestamp echo response */ u32 tsval; /* timestamp value in host order */ u32 next_seq; /* next expected sequence number */ u16 free; /* 65521 minus total size */ u16 mss; /* size of data portion of packet */ #endif /* IXGBE_NO_LRO */ #ifdef HAVE_VLAN_RX_REGISTER u16 vid; /* VLAN tag */ #endif u16 append_cnt; /* number of skb's appended */ #ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT bool page_released; #endif }; #define IXGBE_CB(skb) ((struct ixgbe_cb *)(skb)->cb) #ifdef IXGBE_SYSFS void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter); int ixgbe_sysfs_init(struct ixgbe_adapter *adapter); #endif /* IXGBE_SYSFS */ #ifdef IXGBE_PROCFS void ixgbe_procfs_exit(struct ixgbe_adapter *adapter); int ixgbe_procfs_init(struct ixgbe_adapter *adapter); int ixgbe_procfs_topdir_init(void); void ixgbe_procfs_topdir_exit(void); #endif /* IXGBE_PROCFS */ extern struct dcbnl_rtnl_ops dcbnl_ops; extern int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max); extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index); /* needed by ixgbe_main.c */ extern int ixgbe_validate_mac_addr(u8 *mc_addr); extern void ixgbe_check_options(struct ixgbe_adapter *adapter); extern void ixgbe_assign_netdev_ops(struct net_device *netdev); /* needed by ixgbe_ethtool.c */ extern char ixgbe_driver_name[]; extern const char ixgbe_driver_version[]; extern void ixgbe_up(struct ixgbe_adapter *adapter); extern void ixgbe_down(struct ixgbe_adapter *adapter); extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); extern void ixgbe_reset(struct ixgbe_adapter *adapter); extern void ixgbe_set_ethtool_ops(struct net_device *netdev); extern int ixgbe_setup_rx_resources(struct ixgbe_ring *); extern int ixgbe_setup_tx_resources(struct ixgbe_ring *); extern void ixgbe_free_rx_resources(struct ixgbe_ring *); extern void ixgbe_free_tx_resources(struct ixgbe_ring *); extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter); extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter); extern bool ixgbe_is_ixgbe(struct pci_dev *pcidev); extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, struct ixgbe_adapter *, struct ixgbe_ring *); extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *, struct ixgbe_tx_buffer *); extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16); extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *); extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter, struct ixgbe_ring *); extern void ixgbe_set_rx_mode(struct net_device *netdev); extern int ixgbe_write_mc_addr_list(struct net_device *netdev); extern int ixgbe_setup_tc(struct net_device *dev, u8 tc); #ifdef IXGBE_FCOE extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32); #endif /* IXGBE_FCOE */ extern void ixgbe_do_reset(struct net_device *netdev); extern void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector); extern void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter, struct ixgbe_ring *); extern void ixgbe_vlan_stripping_enable(struct ixgbe_adapter *adapter); extern void ixgbe_vlan_stripping_disable(struct ixgbe_adapter *adapter); #ifdef ETHTOOL_OPS_COMPAT extern int ethtool_ioctl(struct ifreq *ifr); #endif #ifdef IXGBE_FCOE extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first, u8 *hdr_len); extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb); extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, struct scatterlist *sgl, unsigned int sgc); #ifdef HAVE_NETDEV_OPS_FCOE_DDP_TARGET extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, struct scatterlist *sgl, unsigned int sgc); #endif /* HAVE_NETDEV_OPS_FCOE_DDP_TARGET */ extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid); #ifdef HAVE_NETDEV_OPS_FCOE_ENABLE extern int ixgbe_fcoe_enable(struct net_device *netdev); extern int ixgbe_fcoe_disable(struct net_device *netdev); #endif /* HAVE_NETDEV_OPS_FCOE_ENABLE */ #ifdef CONFIG_DCB #ifdef HAVE_DCBNL_OPS_GETAPP extern u8 ixgbe_fcoe_getapp(struct net_device *netdev); #endif /* HAVE_DCBNL_OPS_GETAPP */ extern u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up); #endif /* CONFIG_DCB */ #ifdef HAVE_NETDEV_OPS_FCOE_GETWWN extern int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type); #endif #endif /* IXGBE_FCOE */ #ifdef CONFIG_DCB #ifdef HAVE_DCBNL_IEEE s32 ixgbe_dcb_hw_ets(struct ixgbe_hw *hw, struct ieee_ets *ets, int max_frame); #endif /* HAVE_DCBNL_IEEE */ #endif /* CONFIG_DCB */ extern void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring); extern int ixgbe_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd); extern int ixgbe_write_uc_addr_list(struct ixgbe_adapter *adapter, struct net_device *netdev, unsigned int vfn); extern void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter); extern int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue); extern int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue); extern int ixgbe_available_rars(struct ixgbe_adapter *adapter); #ifndef HAVE_VLAN_RX_REGISTER extern void ixgbe_vlan_mode(struct net_device *, u32); #endif #ifndef ixgbe_get_netdev_tc_txq #define ixgbe_get_netdev_tc_txq(dev, tc) (&dev->tc_to_txq[tc]) #endif extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter); #endif /* _IXGBE_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_82598.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_82598.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw); static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy); /** * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout * @hw: pointer to the HW structure * * The defaults for 82598 should be in the range of 50us to 50ms, * however the hardware default for these parts is 500us to 1ms which is less * than the 10ms recommended by the pci-e spec. To address this we need to * increase the value to either 10ms to 250ms for capability version 1 config, * or 16ms to 55ms for version 2. **/ void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) { u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); u16 pcie_devctl2; /* only take action if timeout value is defaulted to 0 */ if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) goto out; /* * if capababilities version is type 1 we can write the * timeout of 10ms to 250ms through the GCR register */ if (!(gcr & IXGBE_GCR_CAP_VER2)) { gcr |= IXGBE_GCR_CMPL_TMOUT_10ms; goto out; } /* * for version 2 capabilities we need to write the config space * directly in order to set the completion timeout value for * 16ms to 55ms */ pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); out: /* disable completion timeout resend */ gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND; IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr); } /** * ixgbe_init_ops_82598 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for 82598. * Does not touch the hardware. **/ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* PHY */ phy->ops.init = &ixgbe_init_phy_ops_82598; /* MAC */ mac->ops.start_hw = &ixgbe_start_hw_82598; mac->ops.reset_hw = &ixgbe_reset_hw_82598; mac->ops.get_media_type = &ixgbe_get_media_type_82598; mac->ops.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598; mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82598; mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82598; mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie_82598; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = &ixgbe_set_vmdq_82598; mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82598; mac->ops.set_vfta = &ixgbe_set_vfta_82598; mac->ops.set_vlvf = NULL; mac->ops.clear_vfta = &ixgbe_clear_vfta_82598; /* Flow Control */ mac->ops.fc_enable = &ixgbe_fc_enable_82598; mac->mcft_size = 128; mac->vft_size = 128; mac->num_rar_entries = 16; mac->rx_pb_size = 512; mac->max_tx_queues = 32; mac->max_rx_queues = 64; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); /* SFP+ Module */ phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598; /* Link */ mac->ops.check_link = &ixgbe_check_mac_link_82598; mac->ops.setup_link = &ixgbe_setup_mac_link_82598; mac->ops.flap_tx_laser = NULL; mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82598; mac->ops.setup_rxpba = &ixgbe_set_rxpba_82598; /* Manageability interface */ mac->ops.set_fw_drv_ver = NULL; return ret_val; } /** * ixgbe_init_phy_ops_82598 - PHY/SFP specific init * @hw: pointer to hardware structure * * Initialize any function pointers that were not able to be * set during init_shared_code because the PHY/SFP type was * not known. Perform the SFP init if necessary. * **/ s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val = 0; u16 list_offset, data_offset; /* Identify the PHY */ phy->ops.identify(hw); /* Overwrite the link function pointers if copper PHY */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82598; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; case ixgbe_phy_nl: phy->ops.reset = &ixgbe_reset_phy_nl; /* Call SFP+ identify routine to get the SFP+ module type */ ret_val = phy->ops.identify_sfp(hw); if (ret_val != 0) goto out; else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } /* Check to see if SFP+ module is supported */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != 0) { ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } break; default: break; } out: return ret_val; } /** * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function. * Disables relaxed ordering Then set pcie completion timeout * **/ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) { u32 regval; u32 i; s32 ret_val = 0; ret_val = ixgbe_start_hw_generic(hw); /* Disable relaxed ordering */ for (i = 0; ((i < hw->mac.max_tx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); } for (i = 0; ((i < hw->mac.max_rx_queues) && (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } /* set the completion timeout for interface */ if (ret_val == 0) ixgbe_set_pcie_completion_timeout(hw); return ret_val; } /** * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the link capabilities by reading the AUTOC register. **/ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = 0; u32 autoc = 0; /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not been * stored, use the current register value. */ if (hw->mac.orig_link_settings_stored) autoc = hw->mac.orig_autoc; else autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; default: status = IXGBE_ERR_LINK_SETUP; break; } return status; } /** * ixgbe_get_media_type_82598 - Determines media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; /* Detect if there is a copper PHY attached. */ switch (hw->phy.type) { case ixgbe_phy_cu_unknown: case ixgbe_phy_tn: media_type = ixgbe_media_type_copper; goto out; default: break; } /* Media type for I82598 is based on device ID */ switch (hw->device_id) { case IXGBE_DEV_ID_82598: case IXGBE_DEV_ID_82598_BX: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: media_type = ixgbe_media_type_cx4; break; case IXGBE_DEV_ID_82598AT: case IXGBE_DEV_ID_82598AT2: media_type = ixgbe_media_type_copper; break; default: media_type = ixgbe_media_type_unknown; break; } out: return media_type; } /** * ixgbe_fc_enable_82598 - Enable flow control * @hw: pointer to hardware structure * * Enable flow control according to the current settings. **/ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw) { s32 ret_val = 0; u32 fctrl_reg; u32 rmcs_reg; u32 reg; u32 fcrtl, fcrth; u32 link_speed = 0; int i; bool link_up; /* Validate the water mark configuration */ if (!hw->fc.pause_time) { ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* Low water mark of zero causes XOFF floods */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { if (!hw->fc.low_water[i] || hw->fc.low_water[i] >= hw->fc.high_water[i]) { hw_dbg(hw, "Invalid water mark configuration\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } } } /* * On 82598 having Rx FC on causes resets while doing 1G * so if it's on turn it off once we know link_speed. For * more details see 82598 Specification update. */ hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up && link_speed == IXGBE_LINK_SPEED_1GB_FULL) { switch (hw->fc.requested_mode) { case ixgbe_fc_full: hw->fc.requested_mode = ixgbe_fc_tx_pause; break; case ixgbe_fc_rx_pause: hw->fc.requested_mode = ixgbe_fc_none; break; default: /* no change */ break; } } /* Negotiate the fc mode to use */ ixgbe_fc_autoneg(hw); /* Disable any previous flow control settings */ fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE); rmcs_reg = IXGBE_READ_REG(hw, IXGBE_RMCS); rmcs_reg &= ~(IXGBE_RMCS_TFCE_PRIORITY | IXGBE_RMCS_TFCE_802_3X); /* * The possible values of fc.current_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.current_mode) { case ixgbe_fc_none: /* * Flow control is disabled by software override or autoneg. * The code below will actually disable it in the HW. */ break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ fctrl_reg |= IXGBE_FCTRL_RFCE; break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ fctrl_reg |= IXGBE_FCTRL_RFCE; rmcs_reg |= IXGBE_RMCS_TFCE_802_3X; break; default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } /* Set 802.3x based flow control settings. */ fctrl_reg |= IXGBE_FCTRL_DPF; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg); IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg); /* Set up and enable Rx high/low water mark thresholds, enable XON. */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), fcrtl); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), fcrth); } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), 0); } } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time * 0x00010001; for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); out: return ret_val; } /** * ixgbe_start_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = 0; /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { links_reg = 0; /* Just in case Autoneg time = 0 */ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msleep(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; hw_dbg(hw, "Autonegotiation did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msleep(50); return status; } /** * ixgbe_validate_link_ready - Function looks for phy link * @hw: pointer to hardware structure * * Function indicates success when phy link is available. If phy is not ready * within 5 seconds of MAC indicating link, the function returns error. **/ static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw) { u32 timeout; u16 an_reg; if (hw->device_id != IXGBE_DEV_ID_82598AT2) return 0; for (timeout = 0; timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &an_reg); if ((an_reg & IXGBE_MII_AUTONEG_COMPLETE) && (an_reg & IXGBE_MII_AUTONEG_LINK_UP)) break; msleep(100); } if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) { hw_dbg(hw, "Link was indicated but link is down\n"); return IXGBE_ERR_LINK_SETUP; } return 0; } /** * ixgbe_check_mac_link_82598 - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise * @link_up_wait_to_complete: bool used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { u32 links_reg; u32 i; u16 link_reg, adapt_comp_reg; /* * SERDES PHY requires us to read link status from undocumented * register 0xC79F. Bit 0 set indicates link is up/ready; clear * indicates link down. OxC00C is read to check that the XAUI lanes * are active. Bit 0 clear indicates active; set indicates inactive. */ if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) { *link_up = true; break; } else { *link_up = false; } msleep(100); hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg); hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); } } else { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) *link_up = true; else *link_up = false; } if (*link_up == false) goto out; } links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = true; break; } else { *link_up = false; } msleep(100); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); } } else { if (links_reg & IXGBE_LINKS_UP) *link_up = true; else *link_up = false; } if (links_reg & IXGBE_LINKS_SPEED) *speed = IXGBE_LINK_SPEED_10GB_FULL; else *speed = IXGBE_LINK_SPEED_1GB_FULL; if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == true) && (ixgbe_validate_link_ready(hw) != 0)) *link_up = false; out: return 0; } /** * ixgbe_setup_mac_link_82598 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = 0; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc = curr_autoc; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; /* Check to see if speed passed in is supported. */ ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); speed &= link_capabilities; if (speed == IXGBE_LINK_SPEED_UNKNOWN) status = IXGBE_ERR_LINK_SETUP; /* Set KX4/KX support according to speed requested */ else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN || link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) { autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK; if (speed & IXGBE_LINK_SPEED_10GB_FULL) autoc |= IXGBE_AUTOC_KX4_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; if (autoc != curr_autoc) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } if (status == 0) { /* * Setup and restart the link based on the new values in * ixgbe_hw This will write the AUTOC register based on the new * stored values */ status = ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); } return status; } /** * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true if waiting is needed to complete * * Sets the link speed in the AUTOC register in the MAC and restarts link. **/ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); return status; } /** * ixgbe_reset_hw_82598 - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) { s32 status = 0; s32 phy_status = 0; u32 ctrl; u32 gheccr; u32 i; u32 autoc; u8 analog_val; /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != 0) goto reset_hw_out; /* * Power up the Atlas Tx lanes if they are currently powered down. * Atlas Tx lanes are powered down for MAC loopback tests, but * they are not automatically restored on reset. */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { /* Enable Tx Atlas so packets can be transmitted again */ hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); hw->mac.ops.read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; hw->mac.ops.write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); } /* Reset PHY */ if (hw->phy.reset_disable == false) { /* PHY ops must be identified and initialized prior to reset */ /* Init PHY and function pointers, perform SFP setup */ phy_status = hw->phy.ops.init(hw); if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT) goto mac_reset_top; hw->phy.ops.reset(hw); } mac_reset_top: /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST; IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { udelay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST)) break; } if (ctrl & IXGBE_CTRL_RST) { status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "Reset polling failed to complete.\n"); } msleep(50); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* * Store the original AUTOC value if it has not been * stored off yet. Otherwise restore the stored original * AUTOC value since the reset operation sets back to deaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.orig_link_settings_stored == false) { hw->mac.orig_autoc = autoc; hw->mac.orig_link_settings_stored = true; } else if (autoc != hw->mac.orig_autoc) { IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc); } /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ hw->mac.ops.init_rx_addrs(hw); reset_hw_out: if (phy_status != 0) status = phy_status; return status; } /** * ixgbe_set_vmdq_82598 - Associate a VMDq set index with a rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq set index **/ s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); rar_high &= ~IXGBE_RAH_VIND_MASK; rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); return 0; } /** * ixgbe_clear_vmdq_82598 - Disassociate a VMDq set index from an rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq clear index (not used in 82598, but elsewhere) **/ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); if (rar_high & IXGBE_RAH_VIND_MASK) { rar_high &= ~IXGBE_RAH_VIND_MASK; IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high); } return 0; } /** * ixgbe_set_vfta_82598 - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFTA * @vlan_on: boolean flag to turn on/off VLAN in VFTA * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { u32 regindex; u32 bitindex; u32 bits; u32 vftabyte; if (vlan > 4095) return IXGBE_ERR_PARAM; /* Determine 32-bit word position in array */ regindex = (vlan >> 5) & 0x7F; /* upper seven bits */ /* Determine the location of the (VMD) queue index */ vftabyte = ((vlan >> 3) & 0x03); /* bits (4:3) indicating byte array */ bitindex = (vlan & 0x7) << 2; /* lower 3 bits indicate nibble */ /* Set the nibble for VMD queue index */ bits = IXGBE_READ_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex)); bits &= (~(0x0F << bitindex)); bits |= (vind << bitindex); IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vftabyte, regindex), bits); /* Determine the location of the bit for this VLAN id */ bitindex = vlan & 0x1F; /* lower five bits */ bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); if (vlan_on) /* Turn on this VLAN id */ bits |= (1 << bitindex); else /* Turn off this VLAN id */ bits &= ~(1 << bitindex); IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); return 0; } /** * ixgbe_clear_vfta_82598 - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw) { u32 offset; u32 vlanbyte; for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (vlanbyte = 0; vlanbyte < 4; vlanbyte++) for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTAVIND(vlanbyte, offset), 0); return 0; } /** * ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs read operation to Atlas analog register specified. **/ s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 atlas_ctl; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); udelay(10); atlas_ctl = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); *val = (u8)atlas_ctl; return 0; } /** * ixgbe_write_analog_reg8_82598 - Writes 8 bit Atlas analog register * @hw: pointer to hardware structure * @reg: atlas register to write * @val: value to write * * Performs write operation to Atlas analog register specified. **/ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 atlas_ctl; atlas_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); IXGBE_WRITE_FLUSH(hw); udelay(10); return 0; } /** * ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface. * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs 8 byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { s32 status = 0; u16 sfp_addr = 0; u16 sfp_data = 0; u16 sfp_stat = 0; u32 i; if (hw->phy.type == ixgbe_phy_nl) { /* * NetLogic phy SDA/SCL registers are at addresses 0xC30A to * 0xC30D. These registers are used to talk to the SFP+ * module's EEPROM through the SDA/SCL (I2C) interface. */ sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset; sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK); hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR, IXGBE_MDIO_PMA_PMD_DEV_TYPE, sfp_addr); /* Poll status */ for (i = 0; i < 100; i++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_stat); sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK; if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS) break; msleep(10); } if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) { hw_dbg(hw, "EEPROM read did not pass.\n"); status = IXGBE_ERR_SFP_NOT_PRESENT; goto out; } /* Read data */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data); *eeprom_data = (u8)(sfp_data >> 8); } else { status = IXGBE_ERR_PHY; goto out; } out: return status; } /** * ixgbe_get_supported_physical_layer_82598 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; hw->phy.ops.identify(hw); /* Copper PHY must be checked before AUTOC LMS to determine correct * physical layer because 10GBase-T PHYs use LMS = KX4/KX */ switch (hw->phy.type) { case ixgbe_phy_tn: case ixgbe_phy_cu_unknown: hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; default: break; } switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_AN: case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: if (pma_pmd_1g == IXGBE_AUTOC_1G_KX) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX; else physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; else /* XAUI */ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: if (autoc & IXGBE_AUTOC_KX_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; if (autoc & IXGBE_AUTOC_KX4_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; break; default: break; } if (hw->phy.type == ixgbe_phy_nl) { hw->phy.ops.identify_sfp(hw); switch (hw->phy.sfp_type) { case ixgbe_sfp_type_da_cu: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case ixgbe_sfp_type_sr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; break; case ixgbe_sfp_type_lr: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; default: physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; break; } } switch (hw->device_id) { case IXGBE_DEV_ID_82598_DA_DUAL_PORT: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; break; case IXGBE_DEV_ID_82598EB_XF_LR: physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; break; default: break; } out: return physical_layer; } /** * ixgbe_set_lan_id_multi_port_pcie_82598 - Set LAN id for PCIe multiple * port devices. * @hw: pointer to the HW structure * * Calls common function and corrects issue with some single port devices * that enable LAN1 but not LAN0. **/ void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw) { struct ixgbe_bus_info *bus = &hw->bus; u16 pci_gen = 0; u16 pci_ctrl2 = 0; ixgbe_set_lan_id_multi_port_pcie(hw); /* check if LAN0 is disabled */ hw->eeprom.ops.read(hw, IXGBE_PCIE_GENERAL_PTR, &pci_gen); if ((pci_gen != 0) && (pci_gen != 0xFFFF)) { hw->eeprom.ops.read(hw, pci_gen + IXGBE_PCIE_CTRL2, &pci_ctrl2); /* if LAN0 is completely disabled force function to 0 */ if ((pci_ctrl2 & IXGBE_PCIE_CTRL2_LAN_DISABLE) && !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DISABLE_SELECT) && !(pci_ctrl2 & IXGBE_PCIE_CTRL2_DUMMY_ENABLE)) { bus->func = 0; } } } /** * ixgbe_set_rxpba_82598 - Initialize RX packet buffer * @hw: pointer to hardware structure * @num_pb: number of packet buffers to allocate * @headroom: reserve n KB of headroom * @strategy: packet buffer allocation strategy **/ static void ixgbe_set_rxpba_82598(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy) { u32 rxpktsize = IXGBE_RXPBSIZE_64KB; u8 i = 0; if (!num_pb) return; /* Setup Rx packet buffer sizes */ switch (strategy) { case PBA_STRATEGY_WEIGHTED: /* Setup the first four at 80KB */ rxpktsize = IXGBE_RXPBSIZE_80KB; for (; i < 4; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); /* Setup the last four at 48KB...don't re-init i */ rxpktsize = IXGBE_RXPBSIZE_48KB; /* Fall Through */ case PBA_STRATEGY_EQUAL: default: /* Divide the remaining Rx packet buffer evenly among the TCs */ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); break; } /* Setup Tx packet buffer sizes */ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), IXGBE_TXPBSIZE_40KB); return; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_82598.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_82598_H_ #define _IXGBE_82598_H_ u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw); s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw); s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw); void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw); #endif /* _IXGBE_82598_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_82599.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_type.h" #include "ixgbe_82599.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, u16 offset, u16 *data); static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; /* enable the laser control functions for SFP+ fiber */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) { mac->ops.disable_tx_laser = &ixgbe_disable_tx_laser_multispeed_fiber; mac->ops.enable_tx_laser = &ixgbe_enable_tx_laser_multispeed_fiber; mac->ops.flap_tx_laser = &ixgbe_flap_tx_laser_multispeed_fiber; } else { mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; } if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; } else { if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) && (hw->phy.smart_speed == ixgbe_smart_speed_auto || hw->phy.smart_speed == ixgbe_smart_speed_on) && !ixgbe_verify_lesm_fw_enabled_82599(hw)) { mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed; } else { mac->ops.setup_link = &ixgbe_setup_mac_link_82599; } } } /** * ixgbe_init_phy_ops_82599 - PHY/SFP specific init * @hw: pointer to hardware structure * * Initialize any function pointers that were not able to be * set during init_shared_code because the PHY/SFP type was * not known. Perform the SFP init if necessary. * **/ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val = 0; u32 esdp; if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) { /* Store flag indicating I2C bus access control unit. */ hw->phy.qsfp_shared_i2c_bus = TRUE; /* Initialize access to QSFP+ I2C bus */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0_DIR; esdp &= ~IXGBE_ESDP_SDP1_DIR; esdp &= ~IXGBE_ESDP_SDP0; esdp &= ~IXGBE_ESDP_SDP0_NATIVE; esdp &= ~IXGBE_ESDP_SDP1_NATIVE; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599; phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599; } /* Identify the PHY or SFP module */ ret_val = phy->ops.identify(hw); if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) goto init_phy_ops_out; /* Setup function pointers based on detected SFP module and speeds */ ixgbe_init_mac_link_ops_82599(hw); if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) hw->phy.ops.reset = NULL; /* If copper media, overwrite with copper function pointers */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82599; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } /* Set necessary function pointers based on phy type */ switch (hw->phy.type) { case ixgbe_phy_tn: phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; default: break; } init_phy_ops_out: return ret_val; } s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw) { s32 ret_val = 0; u32 reg_anlp1 = 0; u32 i = 0; u16 list_offset, data_offset, data_value; if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) { ixgbe_init_mac_link_ops_82599(hw); hw->phy.ops.reset = NULL; ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != 0) goto setup_sfp_out; /* PHY config will finish before releasing the semaphore */ ret_val = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); if (ret_val != 0) { ret_val = IXGBE_ERR_SWFW_SYNC; goto setup_sfp_out; } hw->eeprom.ops.read(hw, ++data_offset, &data_value); while (data_value != 0xffff) { IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value); IXGBE_WRITE_FLUSH(hw); hw->eeprom.ops.read(hw, ++data_offset, &data_value); } /* Release the semaphore */ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM); /* Delay obtaining semaphore again to allow FW access */ msleep(hw->eeprom.semaphore_delay); /* Now restart DSP by setting Restart_AN and clearing LMS */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw, IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) | IXGBE_AUTOC_AN_RESTART)); /* Wait for AN to leave state 0 */ for (i = 0; i < 10; i++) { msleep(4); reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1); if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK) break; } if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) { hw_dbg(hw, "sfp module setup not complete\n"); ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE; goto setup_sfp_out; } /* Restart DSP by setting Restart_AN and return to SFI mode */ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw, IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL | IXGBE_AUTOC_AN_RESTART)); } setup_sfp_out: return ret_val; } /** * ixgbe_init_ops_82599 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for 82599. * Does not touch the hardware. **/ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* PHY */ phy->ops.identify = &ixgbe_identify_phy_82599; phy->ops.init = &ixgbe_init_phy_ops_82599; /* MAC */ mac->ops.reset_hw = &ixgbe_reset_hw_82599; mac->ops.get_media_type = &ixgbe_get_media_type_82599; mac->ops.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82599; mac->ops.disable_sec_rx_path = &ixgbe_disable_sec_rx_path_generic; mac->ops.enable_sec_rx_path = &ixgbe_enable_sec_rx_path_generic; mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_82599; mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599; mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599; mac->ops.start_hw = &ixgbe_start_hw_82599; mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic; mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = &ixgbe_get_device_caps_generic; mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic; mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = &ixgbe_set_vmdq_generic; mac->ops.set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic; mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic; mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; mac->ops.set_vfta = &ixgbe_set_vfta_generic; mac->ops.set_vlvf = &ixgbe_set_vlvf_generic; mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic; mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599; mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing; mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing; /* Link */ mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599; mac->ops.check_link = &ixgbe_check_mac_link_generic; mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic; ixgbe_init_mac_link_ops_82599(hw); mac->mcft_size = 128; mac->vft_size = 128; mac->num_rar_entries = 128; mac->rx_pb_size = 512; mac->max_tx_queues = 128; mac->max_rx_queues = 128; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & IXGBE_FWSM_MODE_MASK) ? true : false; //hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; /* EEPROM */ eeprom->ops.read = &ixgbe_read_eeprom_82599; eeprom->ops.read_buffer = &ixgbe_read_eeprom_buffer_82599; /* Manageability interface */ mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic; mac->ops.get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic; mac->ops.init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic; return ret_val; } /** * ixgbe_get_link_capabilities_82599 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @negotiation: true when autoneg or autotry is enabled * * Determines the link capabilities by reading the AUTOC register. **/ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *negotiation) { s32 status = 0; u32 autoc = 0; /* Check if 1G SFP module. */ if (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { *speed = IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; goto out; } /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not * been stored, use the current register values. */ if (hw->mac.orig_link_settings_stored) autoc = hw->mac.orig_autoc; else autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *negotiation = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *negotiation = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; case IXGBE_AUTOC_LMS_10G_SERIAL: *speed = IXGBE_LINK_SPEED_10GB_FULL; *negotiation = false; break; case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII: *speed = IXGBE_LINK_SPEED_100_FULL; if (autoc & IXGBE_AUTOC_KR_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; break; case IXGBE_AUTOC_LMS_SGMII_1G_100M: *speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL; *negotiation = false; break; default: status = IXGBE_ERR_LINK_SETUP; goto out; break; } if (hw->phy.multispeed_fiber) { *speed |= IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; *negotiation = true; } out: return status; } /** * ixgbe_get_media_type_82599 - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) { enum ixgbe_media_type media_type; /* Detect if there is a copper PHY attached. */ switch (hw->phy.type) { case ixgbe_phy_cu_unknown: case ixgbe_phy_tn: media_type = ixgbe_media_type_copper; goto out; default: break; } switch (hw->device_id) { case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_SFP_SF2: case IXGBE_DEV_ID_82599EN_SFP: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: media_type = ixgbe_media_type_cx4; break; case IXGBE_DEV_ID_82599_T3_LOM: media_type = ixgbe_media_type_copper; break; case IXGBE_DEV_ID_82599_LS: media_type = ixgbe_media_type_fiber_lco; break; case IXGBE_DEV_ID_82599_QSFP_SF_QP: media_type = ixgbe_media_type_fiber_qsfp; break; default: media_type = ixgbe_media_type_unknown; break; } out: return media_type; } /** * ixgbe_start_mac_link_82599 - Setup MAC link settings * @hw: pointer to hardware structure * @autoneg_wait_to_complete: true when waiting for completion is needed * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. **/ s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg = 0; u32 i; s32 status = 0; /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msleep(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; hw_dbg(hw, "Autoneg did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msleep(50); return status; } /** * ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser * @hw: pointer to hardware structure * * The base drivers may require better control over SFP+ module * PHY states. This includes selectively shutting down the Tx * laser on the PHY, effectively halting physical link. **/ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); /* Disable tx laser; allow 100us to go dark per spec */ esdp_reg |= IXGBE_ESDP_SDP3; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); udelay(100); } /** * ixgbe_enable_tx_laser_multispeed_fiber - Enable Tx laser * @hw: pointer to hardware structure * * The base drivers may require better control over SFP+ module * PHY states. This includes selectively turning on the Tx * laser on the PHY, effectively starting physical link. **/ void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); /* Enable tx laser; allow 100ms to light up */ esdp_reg &= ~IXGBE_ESDP_SDP3; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); msleep(100); } /** * ixgbe_flap_tx_laser_multispeed_fiber - Flap Tx laser * @hw: pointer to hardware structure * * When the driver changes the link speeds that it can support, * it sets autotry_restart to true to indicate that we need to * initiate a new autotry session with the link partner. To do * so, we set the speed then disable and re-enable the tx laser, to * alert the link partner that it also needs to restart autotry on its * end. This is consistent with true clause 37 autoneg, which also * involves a loss of signal. **/ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { if (hw->mac.autotry_restart) { ixgbe_disable_tx_laser_multispeed_fiber(hw); ixgbe_enable_tx_laser_multispeed_fiber(hw); hw->mac.autotry_restart = false; } } /** * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = 0; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; u32 speedcnt = 0; u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); u32 i = 0; bool link_up = false; bool negotiation; /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation); if (status != 0) return status; speed &= link_speed; /* * Try each speed one by one, highest priority first. We do this in * software because 10gb fiber doesn't support speed autonegotiation. */ if (speed & IXGBE_LINK_SPEED_10GB_FULL) { speedcnt++; highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) return status; if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; /* Set the module link speed */ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); /* Allow module to change analog characteristics (1G->10G) */ msleep(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg, autoneg_wait_to_complete); if (status != 0) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* * Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted. 82599 uses the same timing for 10g SFI. */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msleep(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) return status; if (link_up) goto out; } } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { speedcnt++; if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) return status; if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; /* Set the module link speed */ esdp_reg &= ~IXGBE_ESDP_SDP5; esdp_reg |= IXGBE_ESDP_SDP5_DIR; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); IXGBE_WRITE_FLUSH(hw); /* Allow module to change analog characteristics (10G->1G) */ msleep(40); status = ixgbe_setup_mac_link_82599(hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg, autoneg_wait_to_complete); if (status != 0) return status; /* Flap the tx laser if it has not already been done */ ixgbe_flap_tx_laser(hw); /* Wait for the link partner to also set speed */ msleep(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) return status; if (link_up) goto out; } /* * We didn't get link. Configure back to the highest speed we tried, * (if there was more than one). We call ourselves back with just the * single highest speed that the user requested. */ if (speedcnt > 1) status = ixgbe_setup_mac_link_multispeed_fiber(hw, highest_link_speed, autoneg, autoneg_wait_to_complete); out: /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; return status; } /** * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Implements the Intel SmartSpeed algorithm. **/ s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = 0; ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; s32 i, j; bool link_up = false; u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); /* Set autoneg_advertised value based on input link speed */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (speed & IXGBE_LINK_SPEED_100_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; /* * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the * autoneg advertisement if link is unable to be established at the * highest negotiated rate. This can sometimes happen due to integrity * issues with the physical media connection. */ /* First, try to get link with full advertisement */ hw->phy.smart_speed_active = false; for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) { status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, autoneg_wait_to_complete); if (status != 0) goto out; /* * Wait for the controller to acquire link. Per IEEE 802.3ap, * Section 73.10.2, we may have to wait up to 500ms if KR is * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per * Table 9 in the AN MAS. */ for (i = 0; i < 5; i++) { msleep(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) goto out; if (link_up) goto out; } } /* * We didn't get link. If we advertised KR plus one of KX4/KX * (or BX4/BX), then disable KR and try again. */ if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) || ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0)) goto out; /* Turn SmartSpeed on to disable KR support */ hw->phy.smart_speed_active = true; status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, autoneg_wait_to_complete); if (status != 0) goto out; /* * Wait for the controller to acquire link. 600ms will allow for * the AN link_fail_inhibit_timer as well for multiple cycles of * parallel detect, both 10g and 1g. This allows for the maximum * connect attempts as defined in the AN MAS table 73-7. */ for (i = 0; i < 6; i++) { msleep(100); /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != 0) goto out; if (link_up) goto out; } /* We didn't get link. Turn SmartSpeed back off. */ hw->phy.smart_speed_active = false; status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, autoneg_wait_to_complete); out: if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL)) hw_dbg(hw, "Smartspeed has downgraded the link speed " "from the maximum advertised\n"); return status; } /** * ixgbe_setup_mac_link_82599 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed * * Set the link speed in the AUTOC register and restarts link. **/ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = 0; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); u32 start_autoc = autoc; u32 orig_autoc = 0; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; u32 links_reg = 0; u32 i; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; /* Check to see if speed passed in is supported. */ status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); if (status != 0) goto out; speed &= link_capabilities; if (speed == IXGBE_LINK_SPEED_UNKNOWN) { status = IXGBE_ERR_LINK_SETUP; goto out; } /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/ if (hw->mac.orig_link_settings_stored) orig_autoc = hw->mac.orig_autoc; else orig_autoc = autoc; if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { /* Set KX4/KX/KR support according to speed requested */ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); if (speed & IXGBE_LINK_SPEED_10GB_FULL) if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && (hw->phy.smart_speed_active == false)) autoc |= IXGBE_AUTOC_KR_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN || link_mode == IXGBE_AUTOC_LMS_1G_AN)) { /* Switch from 1G SFI to 10G SFI if requested */ if ((speed == IXGBE_LINK_SPEED_10GB_FULL) && (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) { autoc &= ~IXGBE_AUTOC_LMS_MASK; autoc |= IXGBE_AUTOC_LMS_10G_SERIAL; } } else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) && (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) { /* Switch from 10G SFI to 1G SFI if requested */ if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) { autoc &= ~IXGBE_AUTOC_LMS_MASK; if (autoneg) autoc |= IXGBE_AUTOC_LMS_1G_AN; else autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN; } } if (autoc != start_autoc) { /* Restart link */ autoc |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); /* Only poll for autoneg to complete if specified to do so */ if (autoneg_wait_to_complete) { if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN || link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) { for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) { links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_KX_AN_COMP) break; msleep(100); } if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) { status = IXGBE_ERR_AUTONEG_NOT_COMPLETE; hw_dbg(hw, "Autoneg did not complete.\n"); } } } /* Add delay to filter out noises during initial link setup */ msleep(50); } out: return status; } /** * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true if waiting is needed to complete * * Restarts link on PHY and MAC based on settings passed in. **/ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete); return status; } /** * ixgbe_reset_hw_82599 - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, perform a PHY reset, and perform a link (MAC) * reset. **/ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) { // ixgbe_link_speed link_speed; s32 status = 0; // u32 ctrl, i, autoc, autoc2; // bool link_up = false; #if 0 /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != 0) goto reset_hw_out; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); /* PHY ops must be identified and initialized prior to reset */ /* Identify PHY and related function pointers */ status = hw->phy.ops.init(hw); if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; /* Setup SFP module if there is one present. */ if (hw->phy.sfp_setup_needed) { status = hw->mac.ops.setup_sfp(hw); hw->phy.sfp_setup_needed = false; } if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) goto reset_hw_out; /* Reset PHY */ if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL) hw->phy.ops.reset(hw); mac_reset_top: /* * Issue global reset to the MAC. Needs to be SW reset if link is up. * If link reset is used when link is up, it might reset the PHY when * mng is using it. If link is down or the flag to force full link * reset is set, then perform link reset. */ ctrl = IXGBE_CTRL_LNK_RST; if (!hw->force_full_reset) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); if (link_up) ctrl = IXGBE_CTRL_RST; } ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { udelay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "Reset polling failed to complete.\n"); } msleep(50); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* * Store the original AUTOC/AUTOC2 values if they have not been * stored off yet. Otherwise restore the stored original * values since the reset operation sets back to defaults. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); if (hw->mac.orig_link_settings_stored == false) { hw->mac.orig_autoc = autoc; hw->mac.orig_autoc2 = autoc2; hw->mac.orig_link_settings_stored = true; } else { if (autoc != hw->mac.orig_autoc) IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc | IXGBE_AUTOC_AN_RESTART)); if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) != (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) { autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK; autoc2 |= (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK); IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2); } } #endif /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); /* Save the SAN MAC RAR index */ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; /* Reserve the last RAR for the SAN MAC address */ hw->mac.num_rar_entries--; } /* Store the alternative WWNN/WWPN prefix */ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, &hw->mac.wwpn_prefix); //reset_hw_out: return status; } /** * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. * @hw: pointer to hardware structure **/ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) { int i; u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; /* * Before starting reinitialization process, * FDIRCMD.CMD must be zero. */ for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { if (!(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & IXGBE_FDIRCMD_CMD_MASK)) break; udelay(10); } if (i >= IXGBE_FDIRCMD_CMD_POLL) { hw_dbg(hw, "Flow Director previous command isn't complete, " "aborting table re-initialization.\n"); return IXGBE_ERR_FDIR_REINIT_FAILED; } IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0); IXGBE_WRITE_FLUSH(hw); /* * 82599 adapters flow director init flow cannot be restarted, * Workaround 82599 silicon errata by performing the following steps * before re-writing the FDIRCTRL control register with the same value. * - write 1 to bit 8 of FDIRCMD register & * - write 0 to bit 8 of FDIRCMD register */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) | IXGBE_FDIRCMD_CLEARHT)); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, (IXGBE_READ_REG(hw, IXGBE_FDIRCMD) & ~IXGBE_FDIRCMD_CLEARHT)); IXGBE_WRITE_FLUSH(hw); /* * Clear FDIR Hash register to clear any leftover hashes * waiting to be programmed. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, 0x00); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); IXGBE_WRITE_FLUSH(hw); /* Poll init-done after we write FDIRCTRL register */ for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; udelay(10); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) { hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); return IXGBE_ERR_FDIR_REINIT_FAILED; } /* Clear FDIR statistics registers (read to clear) */ IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT); IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); IXGBE_READ_REG(hw, IXGBE_FDIRMISS); IXGBE_READ_REG(hw, IXGBE_FDIRLEN); return 0; } /** * ixgbe_fdir_enable_82599 - Initialize Flow Director control registers * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register **/ static void ixgbe_fdir_enable_82599(struct ixgbe_hw *hw, u32 fdirctrl) { int i; /* Prime the keys for hashing */ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY); IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY); /* * Poll init-done after we write the register. Estimated times: * 10G: PBALLOC = 11b, timing is 60us * 1G: PBALLOC = 11b, timing is 600us * 100M: PBALLOC = 11b, timing is 6ms * * Multiple these timings by 4 if under full Rx load * * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for * 1 msec per poll time. If we're at line rate and drop to 100M, then * this might not finish in our poll time, but we can live with that * for now. */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); IXGBE_WRITE_FLUSH(hw); for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; msleep(1); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) hw_dbg(hw, "Flow Director poll time exceeded!\n"); } /** * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register, initially * contains just the value of the Rx packet buffer allocation **/ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl) { /* * Continue setup of fdirctrl register bits: * Move the flexible bytes to use the ethertype - shift 6 words * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 filters are left */ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); /* write hashes and fdirctrl register, poll for completion */ ixgbe_fdir_enable_82599(hw, fdirctrl); return 0; } /** * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters * @hw: pointer to hardware structure * @fdirctrl: value to write to flow director control register, initially * contains just the value of the Rx packet buffer allocation **/ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl) { /* * Continue setup of fdirctrl register bits: * Turn perfect match filtering on * Report hash in RSS field of Rx wb descriptor * Initialize the drop queue * Move the flexible bytes to use the ethertype - shift 6 words * Set the maximum length per hash bucket to 0xA filters * Send interrupt when 64 (0x4 * 16) filters are left */ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH | IXGBE_FDIRCTRL_REPORT_STATUS | (IXGBE_FDIR_DROP_QUEUE << IXGBE_FDIRCTRL_DROP_Q_SHIFT) | (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) | (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); /* write hashes and fdirctrl register, poll for completion */ ixgbe_fdir_enable_82599(hw, fdirctrl); return 0; } /* * These defines allow us to quickly generate all of the necessary instructions * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION * for values 0 through 15 */ #define IXGBE_ATR_COMMON_HASH_KEY \ (IXGBE_ATR_BUCKET_HASH_KEY & IXGBE_ATR_SIGNATURE_HASH_KEY) #define IXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \ common_hash ^= lo_hash_dword >> n; \ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ bucket_hash ^= lo_hash_dword >> n; \ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \ sig_hash ^= lo_hash_dword << (16 - n); \ if (IXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \ common_hash ^= hi_hash_dword >> n; \ else if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ bucket_hash ^= hi_hash_dword >> n; \ else if (IXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \ sig_hash ^= hi_hash_dword << (16 - n); \ } while (0); /** * ixgbe_atr_compute_sig_hash_82599 - Compute the signature hash * @stream: input bitstream to compute the hash on * * This function is almost identical to the function above but contains * several optomizations such as unwinding all of the loops, letting the * compiler work out all of the conditional ifs since the keys are static * defines, and computing two keys at once since the hashed dword stream * will be the same for both keys. **/ u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common) { u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; u32 sig_hash = 0, bucket_hash = 0, common_hash = 0; /* record the flow_vm_vlan bits as they are a key part to the hash */ flow_vm_vlan = IXGBE_NTOHL(input.dword); /* generate common hash dword */ hi_hash_dword = IXGBE_NTOHL(common.dword); /* low dword is word swapped version of common */ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); /* apply flow ID/VM pool/VLAN ID bits to hash words */ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); /* Process bits 0 and 16 */ IXGBE_COMPUTE_SIG_HASH_ITERATION(0); /* * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to * delay this because bit 0 of the stream should not be processed * so we do not add the vlan until after bit 0 was processed */ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); /* Process remaining 30 bit of the key */ IXGBE_COMPUTE_SIG_HASH_ITERATION(1); IXGBE_COMPUTE_SIG_HASH_ITERATION(2); IXGBE_COMPUTE_SIG_HASH_ITERATION(3); IXGBE_COMPUTE_SIG_HASH_ITERATION(4); IXGBE_COMPUTE_SIG_HASH_ITERATION(5); IXGBE_COMPUTE_SIG_HASH_ITERATION(6); IXGBE_COMPUTE_SIG_HASH_ITERATION(7); IXGBE_COMPUTE_SIG_HASH_ITERATION(8); IXGBE_COMPUTE_SIG_HASH_ITERATION(9); IXGBE_COMPUTE_SIG_HASH_ITERATION(10); IXGBE_COMPUTE_SIG_HASH_ITERATION(11); IXGBE_COMPUTE_SIG_HASH_ITERATION(12); IXGBE_COMPUTE_SIG_HASH_ITERATION(13); IXGBE_COMPUTE_SIG_HASH_ITERATION(14); IXGBE_COMPUTE_SIG_HASH_ITERATION(15); /* combine common_hash result with signature and bucket hashes */ bucket_hash ^= common_hash; bucket_hash &= IXGBE_ATR_HASH_MASK; sig_hash ^= common_hash << 16; sig_hash &= IXGBE_ATR_HASH_MASK << 16; /* return completed signature hash */ return sig_hash ^ bucket_hash; } /** * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter * @hw: pointer to hardware structure * @input: unique input dword * @common: compressed common input dword * @queue: queue index to direct traffic to **/ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common, u8 queue) { u64 fdirhashcmd; u32 fdircmd; /* * Get the flow_type in order to program FDIRCMD properly * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */ switch (input.formatted.flow_type) { case IXGBE_ATR_FLOW_TYPE_TCPV4: case IXGBE_ATR_FLOW_TYPE_UDPV4: case IXGBE_ATR_FLOW_TYPE_SCTPV4: case IXGBE_ATR_FLOW_TYPE_TCPV6: case IXGBE_ATR_FLOW_TYPE_UDPV6: case IXGBE_ATR_FLOW_TYPE_SCTPV6: break; default: hw_dbg(hw, " Error on flow type input\n"); return IXGBE_ERR_CONFIG; } /* configure FDIRCMD register */ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; /* * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH. */ fdirhashcmd = (u64)fdircmd << 32; fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common); IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd); hw_dbg(hw, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd); return 0; } #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ do { \ u32 n = (_n); \ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ bucket_hash ^= lo_hash_dword >> n; \ if (IXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ bucket_hash ^= hi_hash_dword >> n; \ } while (0); /** * ixgbe_atr_compute_perfect_hash_82599 - Compute the perfect filter hash * @atr_input: input bitstream to compute the hash on * @input_mask: mask for the input bitstream * * This function serves two main purposes. First it applys the input_mask * to the atr_input resulting in a cleaned up atr_input data stream. * Secondly it computes the hash and stores it in the bkt_hash field at * the end of the input byte stream. This way it will be available for * future use without needing to recompute the hash. **/ void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *input_mask) { u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; u32 bucket_hash = 0; /* Apply masks to input data */ input->dword_stream[0] &= input_mask->dword_stream[0]; input->dword_stream[1] &= input_mask->dword_stream[1]; input->dword_stream[2] &= input_mask->dword_stream[2]; input->dword_stream[3] &= input_mask->dword_stream[3]; input->dword_stream[4] &= input_mask->dword_stream[4]; input->dword_stream[5] &= input_mask->dword_stream[5]; input->dword_stream[6] &= input_mask->dword_stream[6]; input->dword_stream[7] &= input_mask->dword_stream[7]; input->dword_stream[8] &= input_mask->dword_stream[8]; input->dword_stream[9] &= input_mask->dword_stream[9]; input->dword_stream[10] &= input_mask->dword_stream[10]; /* record the flow_vm_vlan bits as they are a key part to the hash */ flow_vm_vlan = IXGBE_NTOHL(input->dword_stream[0]); /* generate common hash dword */ hi_hash_dword = IXGBE_NTOHL(input->dword_stream[1] ^ input->dword_stream[2] ^ input->dword_stream[3] ^ input->dword_stream[4] ^ input->dword_stream[5] ^ input->dword_stream[6] ^ input->dword_stream[7] ^ input->dword_stream[8] ^ input->dword_stream[9] ^ input->dword_stream[10]); /* low dword is word swapped version of common */ lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); /* apply flow ID/VM pool/VLAN ID bits to hash words */ hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); /* Process bits 0 and 16 */ IXGBE_COMPUTE_BKT_HASH_ITERATION(0); /* * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to * delay this because bit 0 of the stream should not be processed * so we do not add the vlan until after bit 0 was processed */ lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); /* Process remaining 30 bit of the key */ IXGBE_COMPUTE_BKT_HASH_ITERATION(1); IXGBE_COMPUTE_BKT_HASH_ITERATION(2); IXGBE_COMPUTE_BKT_HASH_ITERATION(3); IXGBE_COMPUTE_BKT_HASH_ITERATION(4); IXGBE_COMPUTE_BKT_HASH_ITERATION(5); IXGBE_COMPUTE_BKT_HASH_ITERATION(6); IXGBE_COMPUTE_BKT_HASH_ITERATION(7); IXGBE_COMPUTE_BKT_HASH_ITERATION(8); IXGBE_COMPUTE_BKT_HASH_ITERATION(9); IXGBE_COMPUTE_BKT_HASH_ITERATION(10); IXGBE_COMPUTE_BKT_HASH_ITERATION(11); IXGBE_COMPUTE_BKT_HASH_ITERATION(12); IXGBE_COMPUTE_BKT_HASH_ITERATION(13); IXGBE_COMPUTE_BKT_HASH_ITERATION(14); IXGBE_COMPUTE_BKT_HASH_ITERATION(15); /* * Limit hash to 13 bits since max bucket count is 8K. * Store result at the end of the input stream. */ input->formatted.bkt_hash = bucket_hash & 0x1FFF; } /** * ixgbe_get_fdirtcpm_82599 - generate a tcp port from atr_input_masks * @input_mask: mask to be bit swapped * * The source and destination port masks for flow director are bit swapped * in that bit 15 effects bit 0, 14 effects 1, 13, 2 etc. In order to * generate a correctly swapped value we need to bit swap the mask and that * is what is accomplished by this function. **/ static u32 ixgbe_get_fdirtcpm_82599(union ixgbe_atr_input *input_mask) { u32 mask = IXGBE_NTOHS(input_mask->formatted.dst_port); mask <<= IXGBE_FDIRTCPM_DPORTM_SHIFT; mask |= IXGBE_NTOHS(input_mask->formatted.src_port); mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); } /* * These two macros are meant to address the fact that we have registers * that are either all or in part big-endian. As a result on big-endian * systems we will end up byte swapping the value to little-endian before * it is byte swapped again and written to the hardware in the original * big-endian format. */ #define IXGBE_STORE_AS_BE32(_value) \ (((u32)(_value) >> 24) | (((u32)(_value) & 0x00FF0000) >> 8) | \ (((u32)(_value) & 0x0000FF00) << 8) | ((u32)(_value) << 24)) #define IXGBE_WRITE_REG_BE32(a, reg, value) \ IXGBE_WRITE_REG((a), (reg), IXGBE_STORE_AS_BE32(IXGBE_NTOHL(value))) #define IXGBE_STORE_AS_BE16(_value) \ IXGBE_NTOHS(((u16)(_value) >> 8) | ((u16)(_value) << 8)) s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input_mask) { /* mask IPv6 since it is currently not supported */ u32 fdirm = IXGBE_FDIRM_DIPv6; u32 fdirtcpm; /* * Program the relevant mask registers. If src/dst_port or src/dst_addr * are zero, then assume a full mask for that field. Also assume that * a VLAN of 0 is unspecified, so mask that out as well. L4type * cannot be masked out in this implementation. * * This also assumes IPv4 only. IPv6 masking isn't supported at this * point in time. */ /* verify bucket hash is cleared on hash generation */ if (input_mask->formatted.bkt_hash) hw_dbg(hw, " bucket hash should always be 0 in mask\n"); /* Program FDIRM and verify partial masks */ switch (input_mask->formatted.vm_pool & 0x7F) { case 0x0: fdirm |= IXGBE_FDIRM_POOL; case 0x7F: break; default: hw_dbg(hw, " Error on vm pool mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) { case 0x0: fdirm |= IXGBE_FDIRM_L4P; if (input_mask->formatted.dst_port || input_mask->formatted.src_port) { hw_dbg(hw, " Error on src/dst port mask\n"); return IXGBE_ERR_CONFIG; } case IXGBE_ATR_L4TYPE_MASK: break; default: hw_dbg(hw, " Error on flow type mask\n"); return IXGBE_ERR_CONFIG; } switch (IXGBE_NTOHS(input_mask->formatted.vlan_id) & 0xEFFF) { case 0x0000: /* mask VLAN ID, fall through to mask VLAN priority */ fdirm |= IXGBE_FDIRM_VLANID; case 0x0FFF: /* mask VLAN priority */ fdirm |= IXGBE_FDIRM_VLANP; break; case 0xE000: /* mask VLAN ID only, fall through */ fdirm |= IXGBE_FDIRM_VLANID; case 0xEFFF: /* no VLAN fields masked */ break; default: hw_dbg(hw, " Error on VLAN mask\n"); return IXGBE_ERR_CONFIG; } switch (input_mask->formatted.flex_bytes & 0xFFFF) { case 0x0000: /* Mask Flex Bytes, fall through */ fdirm |= IXGBE_FDIRM_FLEX; case 0xFFFF: break; default: hw_dbg(hw, " Error on flexible byte mask\n"); return IXGBE_ERR_CONFIG; } /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); /* store the TCP/UDP port masks, bit reversed from port layout */ fdirtcpm = ixgbe_get_fdirtcpm_82599(input_mask); /* write both the same so that UDP and TCP use the same mask */ IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); /* store source and destination IP masks (big-enian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, ~input_mask->formatted.src_ip[0]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M, ~input_mask->formatted.dst_ip[0]); return 0; } s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id, u8 queue) { u32 fdirport, fdirvlan, fdirhash, fdircmd; /* currently IPv6 is not supported, must be programmed with 0 */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(0), input->formatted.src_ip[0]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(1), input->formatted.src_ip[1]); IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIPv6(2), input->formatted.src_ip[2]); /* record the source address (big-endian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]); /* record the first 32 bits of the destination address (big-endian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]); /* record source and destination port (little-endian)*/ fdirport = IXGBE_NTOHS(input->formatted.dst_port); fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT; fdirport |= IXGBE_NTOHS(input->formatted.src_port); IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport); /* record vlan (little-endian) and flex_bytes(big-endian) */ fdirvlan = IXGBE_STORE_AS_BE16(input->formatted.flex_bytes); fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT; fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id); IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan); /* configure FDIRHASH register */ fdirhash = input->formatted.bkt_hash; fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* * flush all previous writes to make certain registers are * programmed prior to issuing the command */ IXGBE_WRITE_FLUSH(hw); /* configure FDIRCMD register */ fdircmd = IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE | IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; if (queue == IXGBE_FDIR_DROP_QUEUE) fdircmd |= IXGBE_FDIRCMD_DROP; fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; fdircmd |= (u32)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; fdircmd |= (u32)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); return 0; } s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id) { u32 fdirhash; u32 fdircmd = 0; u32 retry_count; s32 err = 0; /* configure FDIRHASH register */ fdirhash = input->formatted.bkt_hash; fdirhash |= soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); /* flush hash to HW */ IXGBE_WRITE_FLUSH(hw); /* Query if filter is present */ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT); for (retry_count = 10; retry_count; retry_count--) { /* allow 10us for query to process */ udelay(10); /* verify query completed successfully */ fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD); if (!(fdircmd & IXGBE_FDIRCMD_CMD_MASK)) break; } if (!retry_count) err = IXGBE_ERR_FDIR_REINIT_FAILED; /* if filter exists in hardware then remove it */ if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) { IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_REMOVE_FLOW); } return err; } /** * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter * @hw: pointer to hardware structure * @input: input bitstream * @input_mask: mask for the input bitstream * @soft_id: software index for the filters * @queue: queue index to direct traffic to * * Note that the caller to this function must lock before calling, since the * hardware writes must be protected from one another. **/ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, union ixgbe_atr_input *input_mask, u16 soft_id, u8 queue) { s32 err = IXGBE_ERR_CONFIG; /* * Check flow_type formatting, and bail out before we touch the hardware * if there's a configuration issue */ switch (input->formatted.flow_type) { case IXGBE_ATR_FLOW_TYPE_IPV4: input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK; if (input->formatted.dst_port || input->formatted.src_port) { hw_dbg(hw, " Error on src/dst port\n"); return IXGBE_ERR_CONFIG; } break; case IXGBE_ATR_FLOW_TYPE_SCTPV4: if (input->formatted.dst_port || input->formatted.src_port) { hw_dbg(hw, " Error on src/dst port\n"); return IXGBE_ERR_CONFIG; } case IXGBE_ATR_FLOW_TYPE_TCPV4: case IXGBE_ATR_FLOW_TYPE_UDPV4: input_mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK | IXGBE_ATR_L4TYPE_MASK; break; default: hw_dbg(hw, " Error on flow type input\n"); return err; } /* program input mask into the HW */ err = ixgbe_fdir_set_input_mask_82599(hw, input_mask); if (err) return err; /* apply mask and compute/store hash */ ixgbe_atr_compute_perfect_hash_82599(input, input_mask); /* program filters to filter memory */ return ixgbe_fdir_write_perfect_filter_82599(hw, input, soft_id, queue); } /** * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs read operation to Omer analog register specified. **/ s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val) { u32 core_ctl; IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); udelay(10); core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL); *val = (u8)core_ctl; return 0; } /** * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register * @hw: pointer to hardware structure * @reg: atlas register to write * @val: value to write * * Performs write operation to Omer analog register specified. **/ s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val) { u32 core_ctl; core_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl); IXGBE_WRITE_FLUSH(hw); udelay(10); return 0; } /** * ixgbe_start_hw_82599 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function * and the generation start_hw function. * Then performs revision-specific operations, if any. **/ s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw) { s32 ret_val = 0; ret_val = ixgbe_start_hw_generic(hw); if (ret_val != 0) goto out; ret_val = ixgbe_start_hw_gen2(hw); if (ret_val != 0) goto out; /* We need to run link autotry after the driver loads */ hw->mac.autotry_restart = true; if (ret_val == 0) ret_val = ixgbe_verify_fw_version_82599(hw); out: return ret_val; } /** * ixgbe_identify_phy_82599 - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. * If PHY already detected, maintains current PHY type in hw struct, * otherwise executes the PHY detection routine. **/ s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; /* Detect PHY if not unknown - returns success if already detected. */ status = ixgbe_identify_phy_generic(hw); if (status != 0) { /* 82599 10GBASE-T requires an external PHY */ if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) goto out; else status = ixgbe_identify_module_generic(hw); } /* Set PHY type none if no PHY detected */ if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.type = ixgbe_phy_none; status = 0; } /* Return error if SFP module has been detected but is not supported */ if (hw->phy.type == ixgbe_phy_sfp_unsupported) status = IXGBE_ERR_SFP_NOT_SUPPORTED; out: return status; } /** * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2); u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK; u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; u8 comp_codes_10g = 0; u8 comp_codes_1g = 0; hw->phy.ops.identify(hw); switch (hw->phy.type) { case ixgbe_phy_tn: case ixgbe_phy_cu_unknown: hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; goto out; default: break; } switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_AN: case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) { physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX | IXGBE_PHYSICAL_LAYER_1000BASE_BX; goto out; } else /* SFI mode so read SFP module */ goto sfp_check; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4; else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4; else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_XAUI) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_XAUI; goto out; break; case IXGBE_AUTOC_LMS_10G_SERIAL: if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) { physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR; goto out; } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) goto sfp_check; break; case IXGBE_AUTOC_LMS_KX4_KX_KR: case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN: if (autoc & IXGBE_AUTOC_KX_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX; if (autoc & IXGBE_AUTOC_KX4_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4; if (autoc & IXGBE_AUTOC_KR_SUPP) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR; goto out; break; default: goto out; break; } sfp_check: /* SFP check must be done last since DA modules are sometimes used to * test KR mode - we need to id KR mode correctly before SFP module. * Call identify_sfp because the pluggable module may have changed */ hw->phy.ops.identify_sfp(hw); if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) goto out; switch (hw->phy.type) { case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; break; case ixgbe_phy_sfp_ftl_active: case ixgbe_phy_sfp_active_unknown: physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; break; case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T; else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_SX; break; default: break; } out: return physical_layer; } /** * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599 * @hw: pointer to hardware structure * @regval: register value to write to RXCTRL * * Enables the Rx DMA unit for 82599 **/ s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval) { /* * Workaround for 82599 silicon errata when enabling the Rx datapath. * If traffic is incoming before we enable the Rx unit, it could hang * the Rx DMA unit. Therefore, make sure the security engine is * completely disabled prior to enabling the Rx unit. */ hw->mac.ops.disable_sec_rx_path(hw); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); hw->mac.ops.enable_sec_rx_path(hw); return 0; } /** * ixgbe_verify_fw_version_82599 - verify fw version for 82599 * @hw: pointer to hardware structure * * Verifies that installed the firmware version is 0.6 or higher * for SFI devices. All 82599 SFI devices should have version 0.6 or higher. * * Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or * if the FW version is not supported. **/ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM_VERSION; u16 fw_offset, fw_ptp_cfg_offset; u16 fw_version = 0; /* firmware check is only necessary for SFI devices */ if (hw->phy.media_type != ixgbe_media_type_fiber) { status = 0; goto fw_version_out; } /* get the offset to the Firmware Module block */ hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); if ((fw_offset == 0) || (fw_offset == 0xFFFF)) goto fw_version_out; /* get the offset to the Pass Through Patch Configuration block */ hw->eeprom.ops.read(hw, (fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR), &fw_ptp_cfg_offset); if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF)) goto fw_version_out; /* get the firmware version */ hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4), &fw_version); if (fw_version > 0x5) status = 0; fw_version_out: return status; } /** * ixgbe_verify_lesm_fw_enabled_82599 - Checks LESM FW module state. * @hw: pointer to hardware structure * * Returns true if the LESM FW module is present and enabled. Otherwise * returns false. Smart Speed must be disabled if LESM FW module is enabled. **/ bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw) { bool lesm_enabled = false; u16 fw_offset, fw_lesm_param_offset, fw_lesm_state; s32 status; /* get the offset to the Firmware Module block */ status = hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset); if ((status != 0) || (fw_offset == 0) || (fw_offset == 0xFFFF)) goto out; /* get the offset to the LESM Parameters block */ status = hw->eeprom.ops.read(hw, (fw_offset + IXGBE_FW_LESM_PARAMETERS_PTR), &fw_lesm_param_offset); if ((status != 0) || (fw_lesm_param_offset == 0) || (fw_lesm_param_offset == 0xFFFF)) goto out; /* get the lesm state word */ status = hw->eeprom.ops.read(hw, (fw_lesm_param_offset + IXGBE_FW_LESM_STATE_1), &fw_lesm_state); if ((status == 0) && (fw_lesm_state & IXGBE_FW_LESM_STATE_ENABLED)) lesm_enabled = true; out: return lesm_enabled; } /** * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using * fastest available method * * @hw: pointer to hardware structure * @offset: offset of word in EEPROM to read * @words: number of words * @data: word(s) read from the EEPROM * * Retrieves 16 bit word(s) read from EEPROM **/ static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val = IXGBE_ERR_CONFIG; /* * If EEPROM is detected and can be addressed using 14 bits, * use EERD otherwise use bit bang */ if ((eeprom->type == ixgbe_eeprom_spi) && (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR)) ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words, data); else ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset, words, data); return ret_val; } /** * ixgbe_read_eeprom_82599 - Read EEPROM word using * fastest available method * * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM **/ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, u16 offset, u16 *data) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val = IXGBE_ERR_CONFIG; /* * If EEPROM is detected and can be addressed using 14 bits, * use EERD otherwise use bit bang */ if ((eeprom->type == ixgbe_eeprom_spi) && (offset <= IXGBE_EERD_MAX_ADDR)) ret_val = ixgbe_read_eerd_generic(hw, offset, data); else ret_val = ixgbe_read_eeprom_bit_bang_generic(hw, offset, data); return ret_val; } /** * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { u32 esdp; s32 status; s32 timeout = 200; if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Acquire I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); while (timeout) { esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) break; msleep(5); timeout--; } if (!timeout) { hw_dbg(hw, "Driver can't access resource," " acquiring I2C bus timeout.\n"); status = IXGBE_ERR_I2C; goto release_i2c_access; } } status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data); release_i2c_access: if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Release I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp &= ~IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } return status; } /** * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { u32 esdp; s32 status; s32 timeout = 200; if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Acquire I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp |= IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); while (timeout) { esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); if (esdp & IXGBE_ESDP_SDP1) break; msleep(5); timeout--; } if (!timeout) { hw_dbg(hw, "Driver can't access resource," " acquiring I2C bus timeout.\n"); status = IXGBE_ERR_I2C; goto release_i2c_access; } } status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data); release_i2c_access: if (hw->phy.qsfp_shared_i2c_bus == TRUE) { /* Release I2C bus ownership. */ esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); esdp &= ~IXGBE_ESDP_SDP0; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_FLUSH(hw); } return status; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_82599.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_82599_H_ #define _IXGBE_82599_H_ s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw); void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval); bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); #endif /* _IXGBE_82599_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_api.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_common.h" /** * ixgbe_init_shared_code - Initialize the shared code * @hw: pointer to hardware structure * * This will assign function pointers and assign the MAC type and PHY code. * Does not touch the hardware. This function must be called prior to any * other function in the shared code. The ixgbe_hw structure should be * memset to 0 prior to calling this function. The following fields in * hw structure should be filled in prior to calling this function: * hw_addr, back, device_id, vendor_id, subsystem_device_id, * subsystem_vendor_id, and revision_id **/ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw) { s32 status; /* * Set the mac type */ ixgbe_set_mac_type(hw); switch (hw->mac.type) { case ixgbe_mac_82598EB: status = ixgbe_init_ops_82598(hw); break; case ixgbe_mac_82599EB: status = ixgbe_init_ops_82599(hw); break; case ixgbe_mac_X540: status = ixgbe_init_ops_X540(hw); break; default: status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } return status; } /** * ixgbe_set_mac_type - Sets MAC type * @hw: pointer to the HW structure * * This function sets the mac type of the adapter based on the * vendor ID and device ID stored in the hw structure. **/ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw) { s32 ret_val = 0; if (hw->vendor_id == IXGBE_INTEL_VENDOR_ID) { switch (hw->device_id) { case IXGBE_DEV_ID_82598: case IXGBE_DEV_ID_82598_BX: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AT: case IXGBE_DEV_ID_82598AT2: case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: hw->mac.type = ixgbe_mac_82598EB; break; case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_XAUI_LOM: case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_SFP: case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_SFP_SF2: case IXGBE_DEV_ID_82599_QSFP_SF_QP: case IXGBE_DEV_ID_82599EN_SFP: case IXGBE_DEV_ID_82599_CX4: case IXGBE_DEV_ID_82599_LS: case IXGBE_DEV_ID_82599_T3_LOM: hw->mac.type = ixgbe_mac_82599EB; break; case IXGBE_DEV_ID_X540T: hw->mac.type = ixgbe_mac_X540; break; default: ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } } else { ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; } hw_dbg(hw, "ixgbe_set_mac_type found mac: %d, returns: %d\n", hw->mac.type, ret_val); return ret_val; } /** * ixgbe_init_hw - Initialize the hardware * @hw: pointer to hardware structure * * Initialize the hardware by resetting and then starting the hardware **/ s32 ixgbe_init_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_reset_hw - Performs a hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks and * clears all interrupts, performs a PHY reset, and performs a MAC reset **/ s32 ixgbe_reset_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.reset_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_start_hw - Prepares hardware for Rx/Tx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, * clears all on chip counters, initializes receive address registers, * multicast table, VLAN filter table, calls routine to setup link and * flow control settings, and leaves transmit and receive units disabled * and uninitialized. **/ s32 ixgbe_start_hw(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.start_hw, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_hw_cntrs - Clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/ s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.clear_hw_cntrs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_media_type - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_media_type, (hw), ixgbe_media_type_unknown); } /** * ixgbe_get_mac_addr - Get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * * Reads the adapter's MAC address from the first Receive Address Register * (RAR0) A reset of the adapter must have been performed prior to calling * this function in order for the MAC address to have been loaded from the * EEPROM into RAR0 **/ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.get_mac_addr, (hw, mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_san_mac_addr - Get SAN MAC address * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Reads the SAN MAC address from the EEPROM, if it's available. This is * per-port, so set_lan_id() must be called before reading the addresses. **/ s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.get_san_mac_addr, (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_san_mac_addr - Write a SAN MAC address * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Writes A SAN MAC address to the EEPROM. **/ s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr) { return ixgbe_call_func(hw, hw->mac.ops.set_san_mac_addr, (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_device_caps - Get additional device capabilities * @hw: pointer to hardware structure * @device_caps: the EEPROM word for device capabilities * * Reads the extra device capabilities from the EEPROM **/ s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps) { return ixgbe_call_func(hw, hw->mac.ops.get_device_caps, (hw, device_caps), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from the EEPROM * @hw: pointer to hardware structure * @wwnn_prefix: the alternative WWNN prefix * @wwpn_prefix: the alternative WWPN prefix * * This function will read the EEPROM from the alternative SAN MAC address * block to check the support for the alternative WWNN/WWPN prefix support. **/ s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix) { return ixgbe_call_func(hw, hw->mac.ops.get_wwn_prefix, (hw, wwnn_prefix, wwpn_prefix), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_fcoe_boot_status - Get FCOE boot status from EEPROM * @hw: pointer to hardware structure * @bs: the fcoe boot status * * This function will read the FCOE boot status from the iSCSI FCOE block **/ s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs) { return ixgbe_call_func(hw, hw->mac.ops.get_fcoe_boot_status, (hw, bs), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_bus_info - Set PCI bus info * @hw: pointer to hardware structure * * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure **/ s32 ixgbe_get_bus_info(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_bus_info, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_num_of_tx_queues - Get Tx queues * @hw: pointer to hardware structure * * Returns the number of transmit queues for the given adapter. **/ u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw) { return hw->mac.max_tx_queues; } /** * ixgbe_get_num_of_rx_queues - Get Rx queues * @hw: pointer to hardware structure * * Returns the number of receive queues for the given adapter. **/ u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw) { return hw->mac.max_rx_queues; } /** * ixgbe_stop_adapter - Disable Rx/Tx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ s32 ixgbe_stop_adapter(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.stop_adapter, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_pba_string - Reads part number string from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number string from the EEPROM * @pba_num_size: part number string buffer length * * Reads the part number string from the EEPROM. **/ s32 ixgbe_read_pba_string(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size) { return ixgbe_read_pba_string_generic(hw, pba_num, pba_num_size); } /** * ixgbe_identify_phy - Get PHY type * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ s32 ixgbe_identify_phy(struct ixgbe_hw *hw) { s32 status = 0; if (hw->phy.type == ixgbe_phy_unknown) { status = ixgbe_call_func(hw, hw->phy.ops.identify, (hw), IXGBE_NOT_IMPLEMENTED); } return status; } /** * ixgbe_reset_phy - Perform a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy(struct ixgbe_hw *hw) { s32 status = 0; if (hw->phy.type == ixgbe_phy_unknown) { if (ixgbe_identify_phy(hw) != 0) status = IXGBE_ERR_PHY; } if (status == 0) { status = ixgbe_call_func(hw, hw->phy.ops.reset, (hw), IXGBE_NOT_IMPLEMENTED); } return status; } /** * ixgbe_get_phy_firmware_version - * @hw: pointer to hardware structure * @firmware_version: pointer to firmware version **/ s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status = 0; status = ixgbe_call_func(hw, hw->phy.ops.get_firmware_version, (hw, firmware_version), IXGBE_NOT_IMPLEMENTED); return status; } /** * ixgbe_read_phy_reg - Read PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register * * Reads a value from a specified PHY register **/ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); return ixgbe_call_func(hw, hw->phy.ops.read_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_phy_reg - Write PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @phy_data: Data to write to the PHY register * * Writes a value to specified PHY register **/ s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); return ixgbe_call_func(hw, hw->phy.ops.write_reg, (hw, reg_addr, device_type, phy_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_phy_link - Restart PHY autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->phy.ops.setup_link, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_check_phy_link - Determine link and speed status * @hw: pointer to hardware structure * * Reads a PHY register to determine if link is up and the current speed for * the PHY. **/ s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up) { return ixgbe_call_func(hw, hw->phy.ops.check_link, (hw, speed, link_up), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_setup_phy_link_speed - Set auto advertise * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * * Sets the auto advertised capabilities **/ s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { return ixgbe_call_func(hw, hw->phy.ops.setup_link_speed, (hw, speed, autoneg, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_check_link - Get link and speed status * @hw: pointer to hardware structure * * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { return ixgbe_call_func(hw, hw->mac.ops.check_link, (hw, speed, link_up, link_up_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_tx_laser - Disable Tx laser * @hw: pointer to hardware structure * * If the driver needs to disable the laser on SFI optics. **/ void ixgbe_disable_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); } /** * ixgbe_enable_tx_laser - Enable Tx laser * @hw: pointer to hardware structure * * If the driver needs to enable the laser on SFI optics. **/ void ixgbe_enable_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.enable_tx_laser) hw->mac.ops.enable_tx_laser(hw); } /** * ixgbe_flap_tx_laser - flap Tx laser to start autotry process * @hw: pointer to hardware structure * * When the driver changes the link speeds that it can support then * flap the tx laser to alert the link partner to start autotry * process on its end. **/ void ixgbe_flap_tx_laser(struct ixgbe_hw *hw) { if (hw->mac.ops.flap_tx_laser) hw->mac.ops.flap_tx_laser(hw); } /** * ixgbe_setup_link - Set link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * * Configures link settings. Restarts the link. * Performs autonegotiation if needed. **/ s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw, speed, autoneg, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_link_capabilities - Returns link capabilities * @hw: pointer to hardware structure * * Determines the link capabilities of the current configuration. **/ s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { return ixgbe_call_func(hw, hw->mac.ops.get_link_capabilities, (hw, speed, autoneg), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_led_on - Turn on LEDs * @hw: pointer to hardware structure * @index: led number to turn on * * Turns on the software controllable LEDs. **/ s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.led_on, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_led_off - Turn off LEDs * @hw: pointer to hardware structure * @index: led number to turn off * * Turns off the software controllable LEDs. **/ s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.led_off, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_blink_led_start - Blink LEDs * @hw: pointer to hardware structure * @index: led number to blink * * Blink LED based on index. **/ s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.blink_led_start, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_blink_led_stop - Stop blinking LEDs * @hw: pointer to hardware structure * * Stop blinking LED based on index. **/ s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.blink_led_stop, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_eeprom_params - Initialize EEPROM parameters * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->eeprom.ops.init_params, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_eeprom - Write word to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word to be written to the EEPROM * * Writes 16 bit value to EEPROM. If ixgbe_eeprom_update_checksum is not * called after this function, the EEPROM will most likely contain an * invalid checksum. **/ s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data) { return ixgbe_call_func(hw, hw->eeprom.ops.write, (hw, offset, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_eeprom_buffer - Write word(s) to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word(s) to be written to the EEPROM * @words: number of words * * Writes 16 bit word(s) to EEPROM. If ixgbe_eeprom_update_checksum is not * called after this function, the EEPROM will most likely contain an * invalid checksum. **/ s32 ixgbe_write_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.write_buffer, (hw, offset, words, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_eeprom - Read word from EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit value from EEPROM * * Reads 16 bit value from EEPROM **/ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.read, (hw, offset, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_eeprom_buffer - Read word(s) from EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit word(s) from EEPROM * @words: number of words * * Reads 16 bit word(s) from EEPROM **/ s32 ixgbe_read_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { return ixgbe_call_func(hw, hw->eeprom.ops.read_buffer, (hw, offset, words, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_validate_eeprom_checksum - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum **/ s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val) { return ixgbe_call_func(hw, hw->eeprom.ops.validate_checksum, (hw, checksum_val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_eeprom_update_checksum - Updates the EEPROM checksum * @hw: pointer to hardware structure **/ s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->eeprom.ops.update_checksum, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_insert_mac_addr - Find a RAR for this mac address * @hw: pointer to hardware structure * @addr: Address to put into receive address register * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or * finds the rar that it is aleady in; adds to the pool list **/ s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.insert_mac_addr, (hw, addr, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_rar - Set Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: VMDq "set" * @enable_addr: set flag that address is active * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { return ixgbe_call_func(hw, hw->mac.ops.set_rar, (hw, index, addr, vmdq, enable_addr), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_rar - Clear Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index) { return ixgbe_call_func(hw, hw->mac.ops.clear_rar, (hw, index), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vmdq - Associate a VMDq index with a receive address * @hw: pointer to hardware structure * @rar: receive address register index to associate with VMDq index * @vmdq: VMDq set or pool index **/ s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.set_vmdq, (hw, rar, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vmdq_san_mac - Associate VMDq index 127 with a receive address * @hw: pointer to hardware structure * @vmdq: VMDq default pool index **/ s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.set_vmdq_san_mac, (hw, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_vmdq - Disassociate a VMDq index from a receive address * @hw: pointer to hardware structure * @rar: receive address register index to disassociate with VMDq index * @vmdq: VMDq set or pool index **/ s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { return ixgbe_call_func(hw, hw->mac.ops.clear_vmdq, (hw, rar, vmdq), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_rx_addrs - Initializes receive address filters. * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_rx_addrs, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_num_rx_addrs - Returns the number of RAR entries. * @hw: pointer to hardware structure **/ u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw) { return hw->mac.num_rar_entries; } /** * ixgbe_update_uc_addr_list - Updates the MAC's list of secondary addresses * @hw: pointer to hardware structure * @addr_list: the list of new multicast addresses * @addr_count: number of addresses * @func: iterator function to walk the multicast address list * * The given list replaces any existing list. Clears the secondary addrs from * receive address registers. Uses unused receive address registers for the * first secondary addresses, and falls back to promiscuous mode as needed. **/ s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func) { return ixgbe_call_func(hw, hw->mac.ops.update_uc_addr_list, (hw, addr_list, addr_count, func), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_update_mc_addr_list - Updates the MAC's list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @func: iterator function to walk the multicast address list * * The given list replaces any existing list. Clears the MC addrs from receive * address registers and the multicast table. Uses unused receive address * registers for the first multicast addresses, and hashes the rest into the * multicast table. **/ s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear) { return ixgbe_call_func(hw, hw->mac.ops.update_mc_addr_list, (hw, mc_addr_list, mc_addr_count, func, clear), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_enable_mc - Enable multicast address in RAR * @hw: pointer to hardware structure * * Enables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_enable_mc(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.enable_mc, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_mc - Disable multicast address in RAR * @hw: pointer to hardware structure * * Disables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_disable_mc(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.disable_mc, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_clear_vfta - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.clear_vfta, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vfta - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFTA * @vlan_on: boolean flag to turn on/off VLAN in VFTA * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { return ixgbe_call_func(hw, hw->mac.ops.set_vfta, (hw, vlan, vind, vlan_on), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_vlvf - Set VLAN Pool Filter * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * @vfta_changed: pointer to boolean flag which indicates whether VFTA * should be changed * * Turn on/off specified bit in VLVF table. **/ s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed) { return ixgbe_call_func(hw, hw->mac.ops.set_vlvf, (hw, vlan, vind, vlan_on, vfta_changed), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_fc_enable - Enable flow control * @hw: pointer to hardware structure * * Configures the flow control settings based on SW configuration. **/ s32 ixgbe_fc_enable(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.fc_enable, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_set_fw_drv_ver - Try to send the driver version number FW * @hw: pointer to hardware structure * @maj: driver major number to be sent to firmware * @min: driver minor number to be sent to firmware * @build: driver build number to be sent to firmware * @ver: driver version number to be sent to firmware **/ s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver) { return ixgbe_call_func(hw, hw->mac.ops.set_fw_drv_ver, (hw, maj, min, build, ver), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data * @hw: pointer to hardware structure * * Updates the temperatures in mac.thermal_sensor_data **/ s32 ixgbe_get_thermal_sensor_data(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_thermal_sensor_data, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_thermal_sensor_thresh - Inits thermal sensor thresholds * @hw: pointer to hardware structure * * Inits the thermal sensor thresholds according to the NVM map **/ s32 ixgbe_init_thermal_sensor_thresh(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_thermal_sensor_thresh, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_analog_reg8 - Reads 8 bit analog register * @hw: pointer to hardware structure * @reg: analog register to read * @val: read value * * Performs write operation to analog register specified. **/ s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val) { return ixgbe_call_func(hw, hw->mac.ops.read_analog_reg8, (hw, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_analog_reg8 - Writes 8 bit analog register * @hw: pointer to hardware structure * @reg: analog register to write * @val: value to write * * Performs write operation to Atlas analog register specified. **/ s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val) { return ixgbe_call_func(hw, hw->mac.ops.write_analog_reg8, (hw, reg, val), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_init_uta_tables - Initializes Unicast Table Arrays. * @hw: pointer to hardware structure * * Initializes the Unicast Table Arrays to zero on device load. This * is part of the Rx init addr execution path. **/ s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.init_uta_tables, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_byte - Reads 8 bit word over I2C at specified device address * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_byte, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface * at a specified device address. **/ s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_byte, (hw, byte_offset, dev_addr, data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to write * @eeprom_data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data) { return ixgbe_call_func(hw, hw->phy.ops.write_i2c_eeprom, (hw, byte_offset, eeprom_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_read_i2c_eeprom - Reads 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { return ixgbe_call_func(hw, hw->phy.ops.read_i2c_eeprom, (hw, byte_offset, eeprom_data), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_get_supported_physical_layer - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.get_supported_physical_layer, (hw), IXGBE_PHYSICAL_LAYER_UNKNOWN); } /** * ixgbe_enable_rx_dma - Enables Rx DMA unit, dependent on device specifics * @hw: pointer to hardware structure * @regval: bitfield to write to the Rx DMA register * * Enables the Rx DMA unit of the device. **/ s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval) { return ixgbe_call_func(hw, hw->mac.ops.enable_rx_dma, (hw, regval), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_disable_sec_rx_path - Stops the receive data path * @hw: pointer to hardware structure * * Stops the receive data path. **/ s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.disable_sec_rx_path, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_enable_sec_rx_path - Enables the receive data path * @hw: pointer to hardware structure * * Enables the receive data path. **/ s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw) { return ixgbe_call_func(hw, hw->mac.ops.enable_sec_rx_path, (hw), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_acquire_swfw_semaphore - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore through SW_FW_SYNC register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask) { return ixgbe_call_func(hw, hw->mac.ops.acquire_swfw_sync, (hw, mask), IXGBE_NOT_IMPLEMENTED); } /** * ixgbe_release_swfw_semaphore - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through SW_FW_SYNC register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask) { if (hw->mac.ops.release_swfw_sync) hw->mac.ops.release_swfw_sync(hw, mask); } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_api.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_API_H_ #define _IXGBE_API_H_ #include "ixgbe_type.h" s32 ixgbe_init_shared_code(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw); extern s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw); s32 ixgbe_set_mac_type(struct ixgbe_hw *hw); s32 ixgbe_init_hw(struct ixgbe_hw *hw); s32 ixgbe_reset_hw(struct ixgbe_hw *hw); s32 ixgbe_start_hw(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs(struct ixgbe_hw *hw); enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw); s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_get_bus_info(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_tx_queues(struct ixgbe_hw *hw); u32 ixgbe_get_num_of_rx_queues(struct ixgbe_hw *hw); s32 ixgbe_stop_adapter(struct ixgbe_hw *hw); s32 ixgbe_read_pba_string(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size); s32 ixgbe_identify_phy(struct ixgbe_hw *hw); s32 ixgbe_reset_phy(struct ixgbe_hw *hw); s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_setup_phy_link(struct ixgbe_hw *hw); s32 ixgbe_check_phy_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); void ixgbe_disable_tx_laser(struct ixgbe_hw *hw); void ixgbe_enable_tx_laser(struct ixgbe_hw *hw); void ixgbe_flap_tx_laser(struct ixgbe_hw *hw); s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); s32 ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); s32 ixgbe_led_on(struct ixgbe_hw *hw, u32 index); s32 ixgbe_led_off(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_start(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_buffer(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw); s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index); s32 ixgbe_set_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vmdq_san_mac(struct ixgbe_hw *hw, u32 vmdq); s32 ixgbe_clear_vmdq(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_init_rx_addrs(struct ixgbe_hw *hw); u32 ixgbe_get_num_rx_addrs(struct ixgbe_hw *hw); s32 ixgbe_update_uc_addr_list(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear); void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq); s32 ixgbe_enable_mc(struct ixgbe_hw *hw); s32 ixgbe_disable_mc(struct ixgbe_hw *hw); s32 ixgbe_clear_vfta(struct ixgbe_hw *hw); s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed); s32 ixgbe_fc_enable(struct ixgbe_hw *hw); s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver); s32 ixgbe_get_thermal_sensor_data(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh(struct ixgbe_hw *hw); void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr); s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_read_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_disable_sec_rx_path(struct ixgbe_hw *hw); s32 ixgbe_enable_sec_rx_path(struct ixgbe_hw *hw); s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl); s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl); s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common, u8 queue); s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input_mask); s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id, u8 queue); s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u16 soft_id); s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, union ixgbe_atr_input *mask, u16 soft_id, u8 queue); void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, union ixgbe_atr_input *mask); u32 ixgbe_atr_compute_sig_hash_82599(union ixgbe_atr_hash_dword input, union ixgbe_atr_hash_dword common); s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix); s32 ixgbe_get_fcoe_boot_status(struct ixgbe_hw *hw, u16 *bs); #endif /* _IXGBE_API_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_common.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_common.h" #include "ixgbe_phy.h" #include "ixgbe_api.h" static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw); static void ixgbe_standby_eeprom(struct ixgbe_hw *hw); static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, u16 count); static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count); static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec); static void ixgbe_release_eeprom(struct ixgbe_hw *hw); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset); static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, u16 offset); /** * ixgbe_init_ops_generic - Inits function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; struct ixgbe_mac_info *mac = &hw->mac; u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* EEPROM */ eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ if (eec & IXGBE_EEC_PRES) { eeprom->ops.read = &ixgbe_read_eerd_generic; eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_generic; } else { eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; eeprom->ops.read_buffer = &ixgbe_read_eeprom_buffer_bit_bang_generic; } eeprom->ops.write = &ixgbe_write_eeprom_generic; eeprom->ops.write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic; eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_generic; eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic; eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic; /* MAC */ mac->ops.init_hw = &ixgbe_init_hw_generic; mac->ops.reset_hw = NULL; mac->ops.start_hw = &ixgbe_start_hw_generic; mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic; mac->ops.get_media_type = NULL; mac->ops.get_supported_physical_layer = NULL; mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic; mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic; mac->ops.stop_adapter = &ixgbe_stop_adapter_generic; mac->ops.get_bus_info = &ixgbe_get_bus_info_generic; mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie; mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync; mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync; /* LEDs */ mac->ops.led_on = &ixgbe_led_on_generic; mac->ops.led_off = &ixgbe_led_off_generic; mac->ops.blink_led_start = &ixgbe_blink_led_start_generic; mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic; /* RAR, Multicast, VLAN */ mac->ops.set_rar = &ixgbe_set_rar_generic; mac->ops.clear_rar = &ixgbe_clear_rar_generic; mac->ops.insert_mac_addr = NULL; mac->ops.set_vmdq = NULL; mac->ops.clear_vmdq = NULL; mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic; mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic; mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic; mac->ops.enable_mc = &ixgbe_enable_mc_generic; mac->ops.disable_mc = &ixgbe_disable_mc_generic; mac->ops.clear_vfta = NULL; mac->ops.set_vfta = NULL; mac->ops.set_vlvf = NULL; mac->ops.init_uta_tables = NULL; /* Flow Control */ mac->ops.fc_enable = &ixgbe_fc_enable_generic; /* Link */ mac->ops.get_link_capabilities = NULL; mac->ops.setup_link = NULL; mac->ops.check_link = NULL; return 0; } /** * ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow * control * @hw: pointer to hardware structure * * There are several phys that do not support autoneg flow control. This * function check the device id to see if the associated phy supports * autoneg flow control. **/ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) { switch (hw->device_id) { case IXGBE_DEV_ID_X540T: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; default: return IXGBE_ERR_FC_NOT_SUPPORTED; } } /** * ixgbe_setup_fc - Set up flow control * @hw: pointer to hardware structure * * Called at init time to set up flow control. **/ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw) { s32 ret_val = 0; u32 reg = 0, reg_bp = 0; u16 reg_cu = 0; /* * Validate the requested mode. Strict IEEE mode does not allow * ixgbe_fc_rx_pause because it will cause us to fail at UNH. */ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* * 10gig parts do not have a word in the EEPROM to determine the * default flow control setting, so we explicitly set it to full. */ if (hw->fc.requested_mode == ixgbe_fc_default) hw->fc.requested_mode = ixgbe_fc_full; /* * Set up the 1G and 10G flow control advertisement registers so the * HW will be able to do fc autoneg once the cable is plugged in. If * we link at 10G, the 1G advertisement is harmless and vice versa. */ switch (hw->phy.media_type) { case ixgbe_media_type_fiber: case ixgbe_media_type_backplane: reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC); break; case ixgbe_media_type_copper: hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu); break; default: break; } /* * The possible values of fc.requested_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.requested_mode) { case ixgbe_fc_none: /* Flow control completely disabled by software override. */ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE); if (hw->phy.media_type == ixgbe_media_type_backplane) reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); else if (hw->phy.media_type == ixgbe_media_type_copper) reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE); break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ reg |= IXGBE_PCS1GANA_ASM_PAUSE; reg &= ~IXGBE_PCS1GANA_SYM_PAUSE; if (hw->phy.media_type == ixgbe_media_type_backplane) { reg_bp |= IXGBE_AUTOC_ASM_PAUSE; reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE; } else if (hw->phy.media_type == ixgbe_media_type_copper) { reg_cu |= IXGBE_TAF_ASM_PAUSE; reg_cu &= ~IXGBE_TAF_SYM_PAUSE; } break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE, as such we fall * through to the fc_full statement. Later, we will * disable the adapter's ability to send PAUSE frames. */ case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE; if (hw->phy.media_type == ixgbe_media_type_backplane) reg_bp |= IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE; else if (hw->phy.media_type == ixgbe_media_type_copper) reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE; break; default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } if (hw->mac.type != ixgbe_mac_X540) { /* * Enable auto-negotiation between the MAC & PHY; * the MAC will advertise clause 37 flow control. */ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); /* Disable AN timeout */ if (hw->fc.strict_ieee) reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg); } /* * AUTOC restart handles negotiation of 1G and 10G on backplane * and copper. There is no need to set the PCS1GCTL register. * */ if (hw->phy.media_type == ixgbe_media_type_backplane) { reg_bp |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp); } else if ((hw->phy.media_type == ixgbe_media_type_copper) && (ixgbe_device_supports_autoneg_fc(hw) == 0)) { hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu); } hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); out: return ret_val; } /** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) { s32 ret_val; u32 ctrl_ext; /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* PHY ops initialization must be done in reset_hw() */ /* Clear the VLAN filter table */ hw->mac.ops.clear_vfta(hw); /* Clear statistics registers */ hw->mac.ops.clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); /* Setup flow control */ ret_val = ixgbe_setup_fc(hw); if (ret_val != 0) goto out; /* Clear adapter stopped flag */ hw->adapter_stopped = false; out: return ret_val; } /** * ixgbe_start_hw_gen2 - Init sequence for common device family * @hw: pointer to hw structure * * Performs the init sequence common to the second generation * of 10 GbE devices. * Devices in the second generation: * 82599 * X540 **/ s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) { u32 i; u32 regval; /* Clear the rate limiters */ for (i = 0; i < hw->mac.max_tx_queues; i++) { IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); } IXGBE_WRITE_FLUSH(hw); /* Disable relaxed ordering */ for (i = 0; i < hw->mac.max_tx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); } for (i = 0; i < hw->mac.max_rx_queues; i++) { regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | IXGBE_DCA_RXCTRL_HEAD_WRO_EN); IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); } return 0; } /** * ixgbe_init_hw_generic - Generic hardware initialization * @hw: pointer to hardware structure * * Initialize the hardware by resetting the hardware, filling the bus info * structure and media type, clears all on chip counters, initializes receive * address registers, multicast table, VLAN filter table, calls routine to set * up link and flow control settings, and leaves transmit and receive units * disabled and uninitialized **/ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw) { s32 status; /* Reset the hardware */ status = hw->mac.ops.reset_hw(hw); if (status == 0) { /* Start the HW */ status = hw->mac.ops.start_hw(hw); } return status; } /** * ixgbe_clear_hw_cntrs_generic - Generic clear hardware counters * @hw: pointer to hardware structure * * Clears all hardware statistics counters by reading them from the hardware * Statistics counters are clear on read. **/ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) { u16 i = 0; IXGBE_READ_REG(hw, IXGBE_CRCERRS); IXGBE_READ_REG(hw, IXGBE_ILLERRC); IXGBE_READ_REG(hw, IXGBE_ERRBC); IXGBE_READ_REG(hw, IXGBE_MSPDC); for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_MPC(i)); IXGBE_READ_REG(hw, IXGBE_MLFC); IXGBE_READ_REG(hw, IXGBE_MRFC); IXGBE_READ_REG(hw, IXGBE_RLEC); IXGBE_READ_REG(hw, IXGBE_LXONTXC); IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); } else { IXGBE_READ_REG(hw, IXGBE_LXONRXC); IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); } for (i = 0; i < 8; i++) { IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); } else { IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); } } if (hw->mac.type >= ixgbe_mac_82599EB) for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i)); IXGBE_READ_REG(hw, IXGBE_PRC64); IXGBE_READ_REG(hw, IXGBE_PRC127); IXGBE_READ_REG(hw, IXGBE_PRC255); IXGBE_READ_REG(hw, IXGBE_PRC511); IXGBE_READ_REG(hw, IXGBE_PRC1023); IXGBE_READ_REG(hw, IXGBE_PRC1522); IXGBE_READ_REG(hw, IXGBE_GPRC); IXGBE_READ_REG(hw, IXGBE_BPRC); IXGBE_READ_REG(hw, IXGBE_MPRC); IXGBE_READ_REG(hw, IXGBE_GPTC); IXGBE_READ_REG(hw, IXGBE_GORCL); IXGBE_READ_REG(hw, IXGBE_GORCH); IXGBE_READ_REG(hw, IXGBE_GOTCL); IXGBE_READ_REG(hw, IXGBE_GOTCH); if (hw->mac.type == ixgbe_mac_82598EB) for (i = 0; i < 8; i++) IXGBE_READ_REG(hw, IXGBE_RNBC(i)); IXGBE_READ_REG(hw, IXGBE_RUC); IXGBE_READ_REG(hw, IXGBE_RFC); IXGBE_READ_REG(hw, IXGBE_ROC); IXGBE_READ_REG(hw, IXGBE_RJC); IXGBE_READ_REG(hw, IXGBE_MNGPRC); IXGBE_READ_REG(hw, IXGBE_MNGPDC); IXGBE_READ_REG(hw, IXGBE_MNGPTC); IXGBE_READ_REG(hw, IXGBE_TORL); IXGBE_READ_REG(hw, IXGBE_TORH); IXGBE_READ_REG(hw, IXGBE_TPR); IXGBE_READ_REG(hw, IXGBE_TPT); IXGBE_READ_REG(hw, IXGBE_PTC64); IXGBE_READ_REG(hw, IXGBE_PTC127); IXGBE_READ_REG(hw, IXGBE_PTC255); IXGBE_READ_REG(hw, IXGBE_PTC511); IXGBE_READ_REG(hw, IXGBE_PTC1023); IXGBE_READ_REG(hw, IXGBE_PTC1522); IXGBE_READ_REG(hw, IXGBE_MPTC); IXGBE_READ_REG(hw, IXGBE_BPTC); for (i = 0; i < 16; i++) { IXGBE_READ_REG(hw, IXGBE_QPRC(i)); IXGBE_READ_REG(hw, IXGBE_QPTC(i)); if (hw->mac.type >= ixgbe_mac_82599EB) { IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); } else { IXGBE_READ_REG(hw, IXGBE_QBRC(i)); IXGBE_READ_REG(hw, IXGBE_QBTC(i)); } } if (hw->mac.type == ixgbe_mac_X540) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, IXGBE_MDIO_PCS_DEV_TYPE, &i); hw->phy.ops.read_reg(hw, IXGBE_LDPCECH, IXGBE_MDIO_PCS_DEV_TYPE, &i); } return 0; } /** * ixgbe_read_pba_string_generic - Reads part number string from EEPROM * @hw: pointer to hardware structure * @pba_num: stores the part number string from the EEPROM * @pba_num_size: part number string buffer length * * Reads the part number string from the EEPROM. **/ s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size) { s32 ret_val; u16 data; u16 pba_ptr; u16 offset; u16 length; if (pba_num == NULL) { hw_dbg(hw, "PBA string buffer was null\n"); return IXGBE_ERR_INVALID_ARGUMENT; } ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } /* * if data is not ptr guard the PBA must be in legacy format which * means pba_ptr is actually our second data word for the PBA number * and we can decode it into an ascii string */ if (data != IXGBE_PBANUM_PTR_GUARD) { hw_dbg(hw, "NVM PBA number is not stored as string\n"); /* we will need 11 characters to store the PBA */ if (pba_num_size < 11) { hw_dbg(hw, "PBA string buffer too small\n"); return IXGBE_ERR_NO_SPACE; } /* extract hex string from data and pba_ptr */ pba_num[0] = (data >> 12) & 0xF; pba_num[1] = (data >> 8) & 0xF; pba_num[2] = (data >> 4) & 0xF; pba_num[3] = data & 0xF; pba_num[4] = (pba_ptr >> 12) & 0xF; pba_num[5] = (pba_ptr >> 8) & 0xF; pba_num[6] = '-'; pba_num[7] = 0; pba_num[8] = (pba_ptr >> 4) & 0xF; pba_num[9] = pba_ptr & 0xF; /* put a null character on the end of our string */ pba_num[10] = '\0'; /* switch all the data but the '-' to hex char */ for (offset = 0; offset < 10; offset++) { if (pba_num[offset] < 0xA) pba_num[offset] += '0'; else if (pba_num[offset] < 0x10) pba_num[offset] += 'A' - 0xA; } return 0; } ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } if (length == 0xFFFF || length == 0) { hw_dbg(hw, "NVM PBA number section invalid length\n"); return IXGBE_ERR_PBA_SECTION; } /* check if pba_num buffer is big enough */ if (pba_num_size < (((u32)length * 2) - 1)) { hw_dbg(hw, "PBA string buffer too small\n"); return IXGBE_ERR_NO_SPACE; } /* trim pba length from start of string */ pba_ptr++; length--; for (offset = 0; offset < length; offset++) { ret_val = hw->eeprom.ops.read(hw, pba_ptr + offset, &data); if (ret_val) { hw_dbg(hw, "NVM Read Error\n"); return ret_val; } pba_num[offset * 2] = (u8)(data >> 8); pba_num[(offset * 2) + 1] = (u8)(data & 0xFF); } pba_num[offset * 2] = '\0'; return 0; } /** * ixgbe_get_mac_addr_generic - Generic get MAC address * @hw: pointer to hardware structure * @mac_addr: Adapter MAC address * * Reads the adapter's MAC address from first Receive Address Register (RAR0) * A reset of the adapter must be performed prior to calling this function * in order for the MAC address to have been loaded from the EEPROM into RAR0 **/ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr) { u32 rar_high; u32 rar_low; u16 i; rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); for (i = 0; i < 4; i++) mac_addr[i] = (u8)(rar_low >> (i*8)); for (i = 0; i < 2; i++) mac_addr[i+4] = (u8)(rar_high >> (i*8)); return 0; } /** * ixgbe_get_bus_info_generic - Generic set PCI bus info * @hw: pointer to hardware structure * * Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure **/ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; u16 link_status; hw->bus.type = ixgbe_bus_type_pci_express; /* Get the negotiated link width and speed from PCI config space */ link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS); switch (link_status & IXGBE_PCI_LINK_WIDTH) { case IXGBE_PCI_LINK_WIDTH_1: hw->bus.width = ixgbe_bus_width_pcie_x1; break; case IXGBE_PCI_LINK_WIDTH_2: hw->bus.width = ixgbe_bus_width_pcie_x2; break; case IXGBE_PCI_LINK_WIDTH_4: hw->bus.width = ixgbe_bus_width_pcie_x4; break; case IXGBE_PCI_LINK_WIDTH_8: hw->bus.width = ixgbe_bus_width_pcie_x8; break; default: hw->bus.width = ixgbe_bus_width_unknown; break; } switch (link_status & IXGBE_PCI_LINK_SPEED) { case IXGBE_PCI_LINK_SPEED_2500: hw->bus.speed = ixgbe_bus_speed_2500; break; case IXGBE_PCI_LINK_SPEED_5000: hw->bus.speed = ixgbe_bus_speed_5000; break; case IXGBE_PCI_LINK_SPEED_8000: hw->bus.speed = ixgbe_bus_speed_8000; break; default: hw->bus.speed = ixgbe_bus_speed_unknown; break; } mac->ops.set_lan_id(hw); return 0; } /** * ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices * @hw: pointer to the HW structure * * Determines the LAN function id by reading memory-mapped registers * and swaps the port value if requested. **/ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw) { struct ixgbe_bus_info *bus = &hw->bus; u32 reg; reg = IXGBE_READ_REG(hw, IXGBE_STATUS); bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; bus->lan_id = bus->func; /* check for a port swap */ reg = IXGBE_READ_REG(hw, IXGBE_FACTPS); if (reg & IXGBE_FACTPS_LFS) bus->func ^= 0x1; } /** * ixgbe_stop_adapter_generic - Generic stop Tx/Rx units * @hw: pointer to hardware structure * * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, * disables transmit and receive units. The adapter_stopped flag is used by * the shared code and drivers to determine if the adapter is in a stopped * state and should not touch the hardware. **/ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) { u32 reg_val; u16 i; /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware */ hw->adapter_stopped = true; /* Disable the receive unit */ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0); /* Clear interrupt mask to stop interrupts from being generated */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); /* Clear any pending interrupts, flush previous writes */ IXGBE_READ_REG(hw, IXGBE_EICR); /* Disable the transmit unit. Each queue must be disabled. */ for (i = 0; i < hw->mac.max_tx_queues; i++) IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH); /* Disable the receive unit by stopping each queue */ for (i = 0; i < hw->mac.max_rx_queues; i++) { reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); reg_val &= ~IXGBE_RXDCTL_ENABLE; reg_val |= IXGBE_RXDCTL_SWFLSH; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val); } /* flush all queues disables */ IXGBE_WRITE_FLUSH(hw); msleep(2); /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests */ return ixgbe_disable_pcie_master(hw); } /** * ixgbe_led_on_generic - Turns on the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn on **/ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* To turn on the LED, set mode to ON. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_led_off_generic - Turns off the software controllable LEDs. * @hw: pointer to hardware structure * @index: led number to turn off **/ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index) { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* To turn off the LED, set mode to OFF. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_init_eeprom_params_generic - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; /* Set default semaphore delay to 10ms which is a well * tested value */ eeprom->semaphore_delay = 10; /* Clear EEPROM page size, it will be initialized as needed */ eeprom->word_page_size = 0; /* * Check for EEPROM present first. * If not present leave as none */ eec = IXGBE_READ_REG(hw, IXGBE_EEC); if (eec & IXGBE_EEC_PRES) { eeprom->type = ixgbe_eeprom_spi; /* * SPI EEPROM is assumed here. This code would need to * change if a future EEPROM is not SPI. */ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) eeprom->address_bits = 16; else eeprom->address_bits = 8; hw_dbg(hw, "Eeprom params: type = %d, size = %d, address bits: " "%d\n", eeprom->type, eeprom->word_size, eeprom->address_bits); } return 0; } /** * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to write * @words: number of word(s) * @data: 16 bit word(s) to write to EEPROM * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = 0; u16 i, count; hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } /* * The EEPROM page size cannot be queried from the chip. We do lazy * initialization. It is worth to do that when we write large buffer. */ if ((hw->eeprom.word_page_size == 0) && (words > IXGBE_EEPROM_PAGE_SIZE_MAX)) ixgbe_detect_eeprom_page_size_generic(hw, offset); /* * We cannot hold synchronization semaphores for too long * to avoid other entity starvation. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i, count, &data[i]); if (status != 0) break; } out: return status; } /** * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @words: number of word(s) * @data: 16 bit word(s) to be written to the EEPROM * * If ixgbe_eeprom_update_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status; u16 word; u16 page_size; u16 i; u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; /* Prepare the EEPROM for writing */ status = ixgbe_acquire_eeprom(hw); if (status == 0) { if (ixgbe_ready_eeprom(hw) != 0) { ixgbe_release_eeprom(hw); status = IXGBE_ERR_EEPROM; } } if (status == 0) { for (i = 0; i < words; i++) { ixgbe_standby_eeprom(hw); /* Send the WRITE ENABLE command (8 bit opcode ) */ ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI, IXGBE_EEPROM_OPCODE_BITS); ixgbe_standby_eeprom(hw); /* * Some SPI eeproms use the 8th address bit embedded * in the opcode */ if ((hw->eeprom.address_bits == 8) && ((offset + i) >= 128)) write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, write_opcode, IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), hw->eeprom.address_bits); page_size = hw->eeprom.word_page_size; /* Send the data in burst via SPI*/ do { word = data[i]; word = (word >> 8) | (word << 8); ixgbe_shift_out_eeprom_bits(hw, word, 16); if (page_size == 0) break; /* do not wrap around page */ if (((offset + i) & (page_size - 1)) == (page_size - 1)) break; } while (++i < words); ixgbe_standby_eeprom(hw); msleep(10); } /* Done with writing - release the EEPROM */ ixgbe_release_eeprom(hw); } return status; } /** * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be written to * @data: 16 bit word to be written to the EEPROM * * If ixgbe_eeprom_update_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. **/ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status; hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data); out: return status; } /** * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit words(s) from EEPROM * @words: number of word(s) * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = 0; u16 i, count; hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset + words > hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } /* * We cannot hold synchronization semaphores for too long * to avoid other entity starvation. However it is more efficient * to read in bursts than synchronizing access for each word. */ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) { count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ? IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i); status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i, count, &data[i]); if (status != 0) break; } out: return status; } /** * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @words: number of word(s) * @data: read 16 bit word(s) from EEPROM * * Reads 16 bit word(s) from EEPROM through bit-bang method **/ static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status; u16 word_in; u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; u16 i; /* Prepare the EEPROM for reading */ status = ixgbe_acquire_eeprom(hw); if (status == 0) { if (ixgbe_ready_eeprom(hw) != 0) { ixgbe_release_eeprom(hw); status = IXGBE_ERR_EEPROM; } } if (status == 0) { for (i = 0; i < words; i++) { ixgbe_standby_eeprom(hw); /* * Some SPI eeproms use the 8th address bit embedded * in the opcode */ if ((hw->eeprom.address_bits == 8) && ((offset + i) >= 128)) read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI; /* Send the READ command (opcode + addr) */ ixgbe_shift_out_eeprom_bits(hw, read_opcode, IXGBE_EEPROM_OPCODE_BITS); ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2), hw->eeprom.address_bits); /* Read the data. */ word_in = ixgbe_shift_in_eeprom_bits(hw, 16); data[i] = (word_in >> 8) | (word_in << 8); } /* End this read operation */ ixgbe_release_eeprom(hw); } return status; } /** * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be read * @data: read 16 bit value from EEPROM * * Reads 16 bit value from EEPROM through bit-bang method **/ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status; hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); out: return status; } /** * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @words: number of word(s) * @data: 16 bit word(s) from the EEPROM * * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { u32 eerd; s32 status = 0; u32 i; hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } for (i = 0; i < words; i++) { eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) + IXGBE_EEPROM_RW_REG_START; IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); if (status == 0) { data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >> IXGBE_EEPROM_RW_REG_DATA); } else { hw_dbg(hw, "Eeprom read timed out\n"); goto out; } } out: return status; } /** * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size * @hw: pointer to hardware structure * @offset: offset within the EEPROM to be used as a scratch pad * * Discover EEPROM page size by writing marching data at given offset. * This function is called only when we are writing a new large buffer * at given offset so the data would be overwritten anyway. **/ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, u16 offset) { u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX]; s32 status = 0; u16 i; for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++) data[i] = i; hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX; status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, IXGBE_EEPROM_PAGE_SIZE_MAX, data); hw->eeprom.word_page_size = 0; if (status != 0) goto out; status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data); if (status != 0) goto out; /* * When writing in burst more than the actual page size * EEPROM address wraps around current page. */ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; hw_dbg(hw, "Detected EEPROM page size = %d words.", hw->eeprom.word_page_size); out: return status; } /** * ixgbe_read_eerd_generic - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data); } /** * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @words: number of word(s) * @data: word(s) write to the EEPROM * * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { u32 eewr; s32 status = 0; u16 i; hw->eeprom.ops.init_params(hw); if (words == 0) { status = IXGBE_ERR_INVALID_ARGUMENT; goto out; } if (offset >= hw->eeprom.word_size) { status = IXGBE_ERR_EEPROM; goto out; } for (i = 0; i < words; i++) { eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) | (data[i] << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START; status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); if (status != 0) { hw_dbg(hw, "Eeprom write EEWR timed out\n"); goto out; } IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr); status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE); if (status != 0) { hw_dbg(hw, "Eeprom write EEWR timed out\n"); goto out; } } out: return status; } /** * ixgbe_write_eewr_generic - Write EEPROM word using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data) { return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data); } /** * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure * @ee_reg: EEPROM flag for polling * * Polls the status bit (bit 1) of the EERD or EEWR to determine when the * read or write is done respectively. **/ s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { if (ee_reg == IXGBE_NVM_POLL_READ) reg = IXGBE_READ_REG(hw, IXGBE_EERD); else reg = IXGBE_READ_REG(hw, IXGBE_EEWR); if (reg & IXGBE_EEPROM_RW_REG_DONE) { status = 0; break; } udelay(5); } return status; } /** * ixgbe_acquire_eeprom - Acquire EEPROM using bit-bang * @hw: pointer to hardware structure * * Prepares EEPROM for access using bit-bang method. This function should * be called before issuing a command to the EEPROM. **/ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw) { s32 status = 0; u32 eec; u32 i; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0) status = IXGBE_ERR_SWFW_SYNC; if (status == 0) { eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Request EEPROM Access */ eec |= IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) { eec = IXGBE_READ_REG(hw, IXGBE_EEC); if (eec & IXGBE_EEC_GNT) break; udelay(5); } /* Release if grant not acquired */ if (!(eec & IXGBE_EEC_GNT)) { eec &= ~IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); hw_dbg(hw, "Could not acquire EEPROM grant\n"); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); status = IXGBE_ERR_EEPROM; } /* Setup EEPROM for Read/Write */ if (status == 0) { /* Clear CS and SK */ eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK); IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); udelay(1); } } return status; } /** * ixgbe_get_eeprom_semaphore - Get hardware semaphore * @hw: pointer to hardware structure * * Sets the hardware semaphores so EEPROM access can occur for bit-bang method **/ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM; u32 timeout = 2000; u32 i; u32 swsm; /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) { status = 0; break; } udelay(50); } if (i == timeout) { hw_dbg(hw, "Driver can't access the Eeprom - SMBI Semaphore " "not granted.\n"); /* * this release is particularly important because our attempts * above to get the semaphore may have succeeded, and if there * was a timeout, we should unconditionally clear the semaphore * bits to free the driver to make progress */ ixgbe_release_eeprom_semaphore(hw); udelay(50); /* * one last try * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) status = 0; } /* Now get the semaphore between SW/FW through the SWESMBI bit */ if (status == 0) { for (i = 0; i < timeout; i++) { swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Set the SW EEPROM semaphore bit to request access */ swsm |= IXGBE_SWSM_SWESMBI; IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); /* * If we set the bit successfully then we got the * semaphore. */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (swsm & IXGBE_SWSM_SWESMBI) break; udelay(50); } /* * Release semaphores and return error if SW EEPROM semaphore * was not granted because we don't have access to the EEPROM */ if (i >= timeout) { hw_dbg(hw, "SWESMBI Software EEPROM semaphore " "not granted.\n"); ixgbe_release_eeprom_semaphore(hw); status = IXGBE_ERR_EEPROM; } } else { hw_dbg(hw, "Software semaphore SMBI between device drivers " "not granted.\n"); } return status; } /** * ixgbe_release_eeprom_semaphore - Release hardware semaphore * @hw: pointer to hardware structure * * This function clears hardware semaphore bits. **/ static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw) { u32 swsm; swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ swsm &= ~(IXGBE_SWSM_SWESMBI | IXGBE_SWSM_SMBI); IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_ready_eeprom - Polls for EEPROM ready * @hw: pointer to hardware structure **/ static s32 ixgbe_ready_eeprom(struct ixgbe_hw *hw) { s32 status = 0; u16 i; u8 spi_stat_reg; /* * Read "Status Register" repeatedly until the LSB is cleared. The * EEPROM will signal that the command has been completed by clearing * bit 0 of the internal status register. If it's not cleared within * 5 milliseconds, then error out. */ for (i = 0; i < IXGBE_EEPROM_MAX_RETRY_SPI; i += 5) { ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_RDSR_OPCODE_SPI, IXGBE_EEPROM_OPCODE_BITS); spi_stat_reg = (u8)ixgbe_shift_in_eeprom_bits(hw, 8); if (!(spi_stat_reg & IXGBE_EEPROM_STATUS_RDY_SPI)) break; udelay(5); ixgbe_standby_eeprom(hw); }; /* * On some parts, SPI write time could vary from 0-20mSec on 3.3V * devices (and only 0-5mSec on 5V devices) */ if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) { hw_dbg(hw, "SPI EEPROM Status error\n"); status = IXGBE_ERR_EEPROM; } return status; } /** * ixgbe_standby_eeprom - Returns EEPROM to a "standby" state * @hw: pointer to hardware structure **/ static void ixgbe_standby_eeprom(struct ixgbe_hw *hw) { u32 eec; eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Toggle CS to flush commands */ eec |= IXGBE_EEC_CS; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); udelay(1); eec &= ~IXGBE_EEC_CS; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); udelay(1); } /** * ixgbe_shift_out_eeprom_bits - Shift data bits out to the EEPROM. * @hw: pointer to hardware structure * @data: data to send to the EEPROM * @count: number of bits to shift out **/ static void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data, u16 count) { u32 eec; u32 mask; u32 i; eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* * Mask is used to shift "count" bits of "data" out to the EEPROM * one bit at a time. Determine the starting bit based on count */ mask = 0x01 << (count - 1); for (i = 0; i < count; i++) { /* * A "1" is shifted out to the EEPROM by setting bit "DI" to a * "1", and then raising and then lowering the clock (the SK * bit controls the clock input to the EEPROM). A "0" is * shifted out to the EEPROM by setting "DI" to "0" and then * raising and then lowering the clock. */ if (data & mask) eec |= IXGBE_EEC_DI; else eec &= ~IXGBE_EEC_DI; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); udelay(1); ixgbe_raise_eeprom_clk(hw, &eec); ixgbe_lower_eeprom_clk(hw, &eec); /* * Shift mask to signify next bit of data to shift in to the * EEPROM */ mask = mask >> 1; }; /* We leave the "DI" bit set to "0" when we leave this routine. */ eec &= ~IXGBE_EEC_DI; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_shift_in_eeprom_bits - Shift data bits in from the EEPROM * @hw: pointer to hardware structure **/ static u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count) { u32 eec; u32 i; u16 data = 0; /* * In order to read a register from the EEPROM, we need to shift * 'count' bits in from the EEPROM. Bits are "shifted in" by raising * the clock input to the EEPROM (setting the SK bit), and then reading * the value of the "DO" bit. During this "shifting in" process the * "DI" bit should always be clear. */ eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI); for (i = 0; i < count; i++) { data = data << 1; ixgbe_raise_eeprom_clk(hw, &eec); eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec &= ~(IXGBE_EEC_DI); if (eec & IXGBE_EEC_DO) data |= 1; ixgbe_lower_eeprom_clk(hw, &eec); } return data; } /** * ixgbe_raise_eeprom_clk - Raises the EEPROM's clock input. * @hw: pointer to hardware structure * @eec: EEC register's current value **/ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { /* * Raise the clock input to the EEPROM * (setting the SK bit), then delay */ *eec = *eec | IXGBE_EEC_SK; IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); IXGBE_WRITE_FLUSH(hw); udelay(1); } /** * ixgbe_lower_eeprom_clk - Lowers the EEPROM's clock input. * @hw: pointer to hardware structure * @eecd: EECD's current value **/ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { /* * Lower the clock input to the EEPROM (clearing the SK bit), then * delay */ *eec = *eec & ~IXGBE_EEC_SK; IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec); IXGBE_WRITE_FLUSH(hw); udelay(1); } /** * ixgbe_release_eeprom - Release EEPROM, release semaphores * @hw: pointer to hardware structure **/ static void ixgbe_release_eeprom(struct ixgbe_hw *hw) { u32 eec; eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec |= IXGBE_EEC_CS; /* Pull CS high */ eec &= ~IXGBE_EEC_SK; /* Lower SCK */ IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); IXGBE_WRITE_FLUSH(hw); udelay(1); /* Stop requesting EEPROM access */ eec &= ~IXGBE_EEC_REQ; IXGBE_WRITE_REG(hw, IXGBE_EEC, eec); hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); /* Delay before attempt to obtain semaphore again to allow FW access */ msleep(hw->eeprom.semaphore_delay); } /** * ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum * @hw: pointer to hardware structure **/ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw) { u16 i; u16 j; u16 checksum = 0; u16 length = 0; u16 pointer = 0; u16 word = 0; /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { if (hw->eeprom.ops.read(hw, i, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } checksum += word; } /* Include all data from pointers except for the fw pointer */ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { hw->eeprom.ops.read(hw, i, &pointer); /* Make sure the pointer seems valid */ if (pointer != 0xFFFF && pointer != 0) { hw->eeprom.ops.read(hw, pointer, &length); if (length != 0xFFFF && length != 0) { for (j = pointer+1; j <= pointer+length; j++) { hw->eeprom.ops.read(hw, j, &word); checksum += word; } } } } checksum = (u16)IXGBE_EEPROM_SUM - checksum; return checksum; } /** * ixgbe_validate_eeprom_checksum_generic - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val) { s32 status; u16 checksum; u16 read_checksum = 0; /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == 0) { checksum = hw->eeprom.ops.calc_checksum(hw); hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); /* * Verify read checksum from EEPROM is the same as * calculated checksum */ if (read_checksum != checksum) status = IXGBE_ERR_EEPROM_CHECKSUM; /* If the user cares, return the calculated checksum */ if (checksum_val) *checksum_val = checksum; } else { hw_dbg(hw, "EEPROM read failed\n"); } return status; } /** * ixgbe_update_eeprom_checksum_generic - Updates the EEPROM checksum * @hw: pointer to hardware structure **/ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw) { s32 status; u16 checksum; /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status == 0) { checksum = hw->eeprom.ops.calc_checksum(hw); status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum); } else { hw_dbg(hw, "EEPROM read failed\n"); } return status; } /** * ixgbe_validate_mac_addr - Validate MAC address * @mac_addr: pointer to MAC address. * * Tests a MAC address to ensure it is a valid Individual Address **/ s32 ixgbe_validate_mac_addr(u8 *mac_addr) { s32 status = 0; /* Make sure it is not a multicast address */ if (IXGBE_IS_MULTICAST(mac_addr)) { hw_dbg(hw, "MAC address is multicast\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; /* Not a broadcast address */ } else if (IXGBE_IS_BROADCAST(mac_addr)) { hw_dbg(hw, "MAC address is broadcast\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; /* Reject the zero address */ } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { hw_dbg(hw, "MAC address is all zeros\n"); status = IXGBE_ERR_INVALID_MAC_ADDR; } return status; } /** * ixgbe_set_rar_generic - Set Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * @addr: Address to put into receive address register * @vmdq: VMDq "set" or "pool" index * @enable_addr: set flag that address is active * * Puts an ethernet address into a receive address register. **/ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (index >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", index); return IXGBE_ERR_INVALID_ARGUMENT; } /* setup VMDq pool selection before this RAR gets enabled */ hw->mac.ops.set_vmdq(hw, index, vmdq); /* * HW expects these in little endian so we reverse the byte * order from network order (big endian) to little endian */ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part * of the address and the address valid bit. */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; } /** * ixgbe_clear_rar_generic - Remove Rx address register * @hw: pointer to hardware structure * @index: Receive address register to write * * Clears an ethernet address from a receive address register. **/ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) { u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (index >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", index); return IXGBE_ERR_INVALID_ARGUMENT; } /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part * of the address and the address valid bit. */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); /* clear VMDq pool/queue selection for this RAR */ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); return 0; } /** * ixgbe_init_rx_addrs_generic - Initializes receive address filters. * @hw: pointer to hardware structure * * Places the MAC address in receive address register 0 and clears the rest * of the receive address registers. Clears the multicast table. Assumes * the receiver is in reset when the routine is called. **/ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) { u32 i; u32 rar_entries = hw->mac.num_rar_entries; /* * If the current mac address is valid, assume it is a software override * to the permanent address. * Otherwise, use the permanent address from the eeprom. */ if (ixgbe_validate_mac_addr(hw->mac.addr) == IXGBE_ERR_INVALID_MAC_ADDR) { /* Get the MAC address from the RAR0 for later reference */ hw->mac.ops.get_mac_addr(hw, hw->mac.addr); hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ", hw->mac.addr[0], hw->mac.addr[1], hw->mac.addr[2]); hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], hw->mac.addr[4], hw->mac.addr[5]); } else { /* Setup the receive address. */ hw_dbg(hw, "Overriding MAC Address in RAR[0]\n"); hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ", hw->mac.addr[0], hw->mac.addr[1], hw->mac.addr[2]); hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], hw->mac.addr[4], hw->mac.addr[5]); hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); /* clear VMDq pool/queue selection for RAR 0 */ hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL); } hw->addr_ctrl.overflow_promisc = 0; hw->addr_ctrl.rar_used_count = 1; /* Zero out the other receive addresses. */ hw_dbg(hw, "Clearing RAR[1-%d]\n", rar_entries - 1); for (i = 1; i < rar_entries; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); } /* Clear the MTA */ hw->addr_ctrl.mta_in_use = 0; IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); hw_dbg(hw, " Clearing MTA\n"); for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0); ixgbe_init_uta_tables(hw); return 0; } /** * ixgbe_add_uc_addr - Adds a secondary unicast address. * @hw: pointer to hardware structure * @addr: new address * * Adds it to unused receive address register or goes into promiscuous mode. **/ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { u32 rar_entries = hw->mac.num_rar_entries; u32 rar; hw_dbg(hw, " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); /* * Place this address in the RAR if there is room, * else put the controller into promiscuous mode */ if (hw->addr_ctrl.rar_used_count < rar_entries) { rar = hw->addr_ctrl.rar_used_count; hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar); hw->addr_ctrl.rar_used_count++; } else { hw->addr_ctrl.overflow_promisc++; } hw_dbg(hw, "ixgbe_add_uc_addr Complete\n"); } /** * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses * @hw: pointer to hardware structure * @addr_list: the list of new addresses * @addr_count: number of addresses * @next: iterator function to walk the address list * * The given list replaces any existing list. Clears the secondary addrs from * receive address registers. Uses unused receive address registers for the * first secondary addresses, and falls back to promiscuous mode as needed. * * Drivers using secondary unicast addresses must set user_set_promisc when * manually putting the device into promiscuous mode. **/ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr next) { u8 *addr; u32 i; u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; u32 uc_addr_in_use; u32 fctrl; u32 vmdq; /* * Clear accounting of old secondary address list, * don't count RAR[0] */ uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; hw->addr_ctrl.rar_used_count -= uc_addr_in_use; hw->addr_ctrl.overflow_promisc = 0; /* Zero out the other receive addresses */ hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use+1); for (i = 0; i < uc_addr_in_use; i++) { IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0); IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0); } /* Add the new addresses */ for (i = 0; i < addr_count; i++) { hw_dbg(hw, " Adding the secondary addresses:\n"); addr = next(hw, &addr_list, &vmdq); ixgbe_add_uc_addr(hw, addr, vmdq); } if (hw->addr_ctrl.overflow_promisc) { /* enable promisc if not already in overflow or set by user */ if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { hw_dbg(hw, " Entering address overflow promisc mode\n"); fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl |= IXGBE_FCTRL_UPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } } else { /* only disable if set by overflow, not by user */ if (old_promisc_setting && !hw->addr_ctrl.user_set_promisc) { hw_dbg(hw, " Leaving address overflow promisc mode\n"); fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl &= ~IXGBE_FCTRL_UPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } } hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n"); return 0; } /** * ixgbe_mta_vector - Determines bit-vector in multicast table to set * @hw: pointer to hardware structure * @mc_addr: the multicast address * * Extracts the 12 bits, from a multicast address, to determine which * bit-vector to set in the multicast table. The hardware uses 12 bits, from * incoming rx multicast addresses, to determine the bit-vector to check in * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set * by the MO field of the MCSTCTRL. The MO field is set during initialization * to mc_filter_type. **/ static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector = 0; switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); break; case 1: /* use bits [46:35] of the address */ vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); break; case 2: /* use bits [45:34] of the address */ vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); break; case 3: /* use bits [43:32] of the address */ vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); break; default: /* Invalid mc_filter_type */ hw_dbg(hw, "MC filter type param set incorrectly\n"); break; } /* vector can only be 12-bits or boundary will be exceeded */ vector &= 0xFFF; return vector; } /** * ixgbe_set_mta - Set bit-vector in multicast table * @hw: pointer to hardware structure * @hash_value: Multicast address hash value * * Sets the bit-vector in the multicast table. **/ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) { u32 vector; u32 vector_bit; u32 vector_reg; hw->addr_ctrl.mta_in_use++; vector = ixgbe_mta_vector(hw, mc_addr); hw_dbg(hw, " bit-vector = 0x%03X\n", vector); /* * The MTA is a register array of 128 32-bit registers. It is treated * like an array of 4096 bits. We want to set bit * BitArray[vector_value]. So we figure out what register the bit is * in, read it, OR in the new bit, then write back the new value. The * register is determined by the upper 7 bits of the vector value and * the bit within that register are determined by the lower 5 bits of * the value. */ vector_reg = (vector >> 5) & 0x7F; vector_bit = vector & 0x1F; hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit); } /** * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses * @mc_addr_count: number of addresses * @next: iterator function to walk the multicast address list * @clear: flag, when set clears the table beforehand * * When the clear flag is set, the given list replaces any existing list. * Hashes the given addresses into the multicast table. **/ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr next, bool clear) { u32 i; u32 vmdq; /* * Set the new number of MC addresses that we are being requested to * use. */ hw->addr_ctrl.num_mc_addrs = mc_addr_count; hw->addr_ctrl.mta_in_use = 0; /* Clear mta_shadow */ if (clear) { hw_dbg(hw, " Clearing MTA\n"); memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); } /* Update mta_shadow */ for (i = 0; i < mc_addr_count; i++) { hw_dbg(hw, " Adding the multicast addresses:\n"); ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); } /* Enable mta */ for (i = 0; i < hw->mac.mcft_size; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i, hw->mac.mta_shadow[i]); if (hw->addr_ctrl.mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); hw_dbg(hw, "ixgbe_update_mc_addr_list_generic Complete\n"); return 0; } /** * ixgbe_enable_mc_generic - Enable multicast address in RAR * @hw: pointer to hardware structure * * Enables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); return 0; } /** * ixgbe_disable_mc_generic - Disable multicast address in RAR * @hw: pointer to hardware structure * * Disables multicast address in RAR and the use of the multicast hash table. **/ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw) { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); return 0; } /** * ixgbe_fc_enable_generic - Enable flow control * @hw: pointer to hardware structure * * Enable flow control according to the current settings. **/ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) { s32 ret_val = 0; u32 mflcn_reg, fccfg_reg; u32 reg; u32 fcrtl, fcrth; int i; /* Validate the water mark configuration */ if (!hw->fc.pause_time) { ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } /* Low water mark of zero causes XOFF floods */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { if (!hw->fc.low_water[i] || hw->fc.low_water[i] >= hw->fc.high_water[i]) { hw_dbg(hw, "Invalid water mark configuration\n"); ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; goto out; } } } /* Negotiate the fc mode to use */ ixgbe_fc_autoneg(hw); /* Disable any previous flow control settings */ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE); fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG); fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY); /* * The possible values of fc.current_mode are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames, * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but * we do not support receiving pause frames). * 3: Both Rx and Tx flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.current_mode) { case ixgbe_fc_none: /* * Flow control is disabled by software override or autoneg. * The code below will actually disable it in the HW. */ break; case ixgbe_fc_rx_pause: /* * Rx Flow control is enabled and Tx Flow control is * disabled by software override. Since there really * isn't a way to advertise that we are capable of RX * Pause ONLY, we will advertise that we support both * symmetric and asymmetric Rx PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. */ mflcn_reg |= IXGBE_MFLCN_RFCE; break; case ixgbe_fc_tx_pause: /* * Tx Flow control is enabled, and Rx Flow control is * disabled by software override. */ fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; break; case ixgbe_fc_full: /* Flow control (both Rx and Tx) is enabled by SW override. */ mflcn_reg |= IXGBE_MFLCN_RFCE; fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X; break; default: hw_dbg(hw, "Flow control param set incorrectly\n"); ret_val = IXGBE_ERR_CONFIG; goto out; break; } /* Set 802.3x based flow control settings. */ mflcn_reg |= IXGBE_MFLCN_DPF; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg); IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg); /* Set up and enable Rx high/low water mark thresholds, enable XON. */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { if ((hw->fc.current_mode & ixgbe_fc_tx_pause) && hw->fc.high_water[i]) { fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN; } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark * to the maximum FCRTH value. This allows the Tx * switch to function even under heavy Rx workloads. */ fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time * 0x00010001; for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); out: return ret_val; } /** * ixgbe_negotiate_fc - Negotiate flow control * @hw: pointer to hardware structure * @adv_reg: flow control advertised settings * @lp_reg: link partner's flow control settings * @adv_sym: symmetric pause bit in advertisement * @adv_asm: asymmetric pause bit in advertisement * @lp_sym: symmetric pause bit in link partner advertisement * @lp_asm: asymmetric pause bit in link partner advertisement * * Find the intersection between advertised settings and link partner's * advertised settings **/ static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg, u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm) { if ((!(adv_reg)) || (!(lp_reg))) return IXGBE_ERR_FC_NOT_NEGOTIATED; if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) { /* * Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise RX * ONLY. Hence, we must now check to see if we need to * turn OFF the TRANSMISSION of PAUSE frames. */ if (hw->fc.requested_mode == ixgbe_fc_full) { hw->fc.current_mode = ixgbe_fc_full; hw_dbg(hw, "Flow Control = FULL.\n"); } else { hw->fc.current_mode = ixgbe_fc_rx_pause; hw_dbg(hw, "Flow Control=RX PAUSE frames only\n"); } } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) && (lp_reg & lp_sym) && (lp_reg & lp_asm)) { hw->fc.current_mode = ixgbe_fc_tx_pause; hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n"); } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) && !(lp_reg & lp_sym) && (lp_reg & lp_asm)) { hw->fc.current_mode = ixgbe_fc_rx_pause; hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n"); } else { hw->fc.current_mode = ixgbe_fc_none; hw_dbg(hw, "Flow Control = NONE.\n"); } return 0; } /** * ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber * @hw: pointer to hardware structure * * Enable flow control according on 1 gig fiber. **/ static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw) { u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; /* * On multispeed fiber at 1g, bail out if * - link is up but AN did not complete, or if * - link is up and AN completed but timed out */ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) goto out; pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); ret_val = ixgbe_negotiate_fc(hw, pcs_anadv_reg, pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE, IXGBE_PCS1GANA_ASM_PAUSE, IXGBE_PCS1GANA_SYM_PAUSE, IXGBE_PCS1GANA_ASM_PAUSE); out: return ret_val; } /** * ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37 * @hw: pointer to hardware structure * * Enable flow control according to IEEE clause 37. **/ static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw) { u32 links2, anlp1_reg, autoc_reg, links; s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; /* * On backplane, bail out if * - backplane autoneg was not completed, or if * - we are 82599 and link partner is not AN enabled */ links = IXGBE_READ_REG(hw, IXGBE_LINKS); if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) goto out; if (hw->mac.type == ixgbe_mac_82599EB) { links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) goto out; } /* * Read the 10g AN autoc and LP ability registers and resolve * local flow control settings accordingly */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); ret_val = ixgbe_negotiate_fc(hw, autoc_reg, anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE, IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE); out: return ret_val; } /** * ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37 * @hw: pointer to hardware structure * * Enable flow control according to IEEE clause 37. **/ static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw) { u16 technology_ability_reg = 0; u16 lp_technology_ability_reg = 0; hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &technology_ability_reg); hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_LP, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &lp_technology_ability_reg); return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg, (u32)lp_technology_ability_reg, IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE, IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE); } /** * ixgbe_fc_autoneg - Configure flow control * @hw: pointer to hardware structure * * Compares our advertised flow control capabilities to those advertised by * our link partner, and determines the proper flow control mode to use. **/ void ixgbe_fc_autoneg(struct ixgbe_hw *hw) { s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED; ixgbe_link_speed speed; bool link_up; /* * AN should have completed when the cable was plugged in. * Look for reasons to bail out. Bail out if: * - FC autoneg is disabled, or if * - link is not up. */ if (hw->fc.disable_fc_autoneg) goto out; hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) goto out; switch (hw->phy.media_type) { /* Autoneg flow control on fiber adapters */ case ixgbe_media_type_fiber: if (speed == IXGBE_LINK_SPEED_1GB_FULL) ret_val = ixgbe_fc_autoneg_fiber(hw); break; /* Autoneg flow control on backplane adapters */ case ixgbe_media_type_backplane: ret_val = ixgbe_fc_autoneg_backplane(hw); break; /* Autoneg flow control on copper adapters */ case ixgbe_media_type_copper: if (ixgbe_device_supports_autoneg_fc(hw) == 0) ret_val = ixgbe_fc_autoneg_copper(hw); break; default: break; } out: if (ret_val == 0) { hw->fc.fc_was_autonegged = true; } else { hw->fc.fc_was_autonegged = false; hw->fc.current_mode = hw->fc.requested_mode; } } /** * ixgbe_disable_pcie_master - Disable PCI-express master access * @hw: pointer to hardware structure * * Disables PCI-Express master access and verifies there are no pending * requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable * bit hasn't caused the master requests to be disabled, else 0 * is returned signifying master requests disabled. **/ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) { s32 status = 0; u32 i; /* Always set this bit to ensure any future transactions are blocked */ IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS); /* Exit if master requets are blocked */ if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) goto out; /* Poll for master request bit to clear */ for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { udelay(100); if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) goto out; } /* * Two consecutive resets are required via CTRL.RST per datasheet * 5.2.5.3.2 Master Disable. We set a flag to inform the reset routine * of this need. The first reset prevents new master requests from * being issued by our device. We then must wait 1usec or more for any * remaining completions from the PCIe bus to trickle in, and then reset * again to clear out any effects they may have had on our device. */ hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n"); hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. */ for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) { udelay(100); if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING)) goto out; } hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n"); status = IXGBE_ERR_MASTER_REQUESTS_PENDING; out: return status; } /** * ixgbe_acquire_swfw_sync - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore through the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask) { u32 gssr; u32 swmask = mask; u32 fwmask = mask << 5; s32 timeout = 200; while (timeout) { /* * SW EEPROM semaphore bit is used for access to all * SW_FW_SYNC/GSSR bits (not just EEPROM) */ if (ixgbe_get_eeprom_semaphore(hw)) return IXGBE_ERR_SWFW_SYNC; gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); if (!(gssr & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) or other software * thread currently using resource (swmask) */ ixgbe_release_eeprom_semaphore(hw); msleep(5); timeout--; } if (!timeout) { hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n"); return IXGBE_ERR_SWFW_SYNC; } gssr |= swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw); return 0; } /** * ixgbe_release_swfw_sync - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through the GSSR register for the specified * function (CSR, PHY0, PHY1, EEPROM, Flash) **/ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask) { u32 gssr; u32 swmask = mask; ixgbe_get_eeprom_semaphore(hw); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); gssr &= ~swmask; IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr); ixgbe_release_eeprom_semaphore(hw); } /** * ixgbe_disable_sec_rx_path_generic - Stops the receive data path * @hw: pointer to hardware structure * * Stops the receive data path and waits for the HW to internally empty * the Rx security block **/ s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw) { #define IXGBE_MAX_SECRX_POLL 40 int i; int secrxreg; secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); secrxreg |= IXGBE_SECRXCTRL_RX_DIS; IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) { secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT); if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY) break; else /* Use interrupt-safe sleep just in case */ udelay(1000); } /* For informational purposes only */ if (i >= IXGBE_MAX_SECRX_POLL) hw_dbg(hw, "Rx unit being enabled before security " "path fully disabled. Continuing with init.\n"); return 0; } /** * ixgbe_enable_sec_rx_path_generic - Enables the receive data path * @hw: pointer to hardware structure * * Enables the receive data path. **/ s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw) { int secrxreg; secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL); secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS; IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit * @hw: pointer to hardware structure * @regval: register value to write to RXCTRL * * Enables the Rx DMA unit **/ s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) { IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); return 0; } /** * ixgbe_blink_led_start_generic - Blink LED based on index. * @hw: pointer to hardware structure * @index: led number to blink **/ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index) { ixgbe_link_speed speed = 0; bool link_up = 0; u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); /* * Link must be up to auto-blink the LEDs; * Force it if link is down. */ hw->mac.ops.check_link(hw, &speed, &link_up, false); if (!link_up) { autoc_reg |= IXGBE_AUTOC_AN_RESTART; autoc_reg |= IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); IXGBE_WRITE_FLUSH(hw); msleep(10); } led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_blink_led_stop_generic - Stop blinking LED based on index. * @hw: pointer to hardware structure * @index: led number to stop blinking **/ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index) { u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg &= ~IXGBE_LED_BLINK(index); led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM * @hw: pointer to hardware structure * @san_mac_offset: SAN MAC address offset * * This function will read the EEPROM location for the SAN MAC address * pointer, and returns the value at that location. This is used in both * get and set mac_addr routines. **/ static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset) { /* * First read the EEPROM pointer to see if the MAC addresses are * available. */ hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); return 0; } /** * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Reads the SAN MAC address from the EEPROM, if it's available. This is * per-port, so set_lan_id() must be called before reading the addresses. * set_lan_id() is called by identify_sfp(), but this cannot be relied * upon for non-SFP connections, so we must call it here. **/ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) { u16 san_mac_data, san_mac_offset; u8 i; /* * First read the EEPROM pointer to see if the MAC addresses are * available. If they're not, no point in calling set_lan_id() here. */ ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { /* * No addresses available in this EEPROM. It's not an * error though, so just wipe the local address and return. */ for (i = 0; i < 6; i++) san_mac_addr[i] = 0xFF; goto san_mac_addr_out; } /* make sure we know which port we need to program */ hw->mac.ops.set_lan_id(hw); /* apply the port offset to the address offset */ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); for (i = 0; i < 3; i++) { hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); san_mac_addr[i * 2] = (u8)(san_mac_data); san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); san_mac_offset++; } san_mac_addr_out: return 0; } /** * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM * @hw: pointer to hardware structure * @san_mac_addr: SAN MAC address * * Write a SAN MAC address to the EEPROM. **/ s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) { s32 status = 0; u16 san_mac_data, san_mac_offset; u8 i; /* Look for SAN mac address pointer. If not defined, return */ ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { status = IXGBE_ERR_NO_SAN_ADDR_PTR; goto san_mac_addr_out; } /* Make sure we know which port we need to write */ hw->mac.ops.set_lan_id(hw); /* Apply the port offset to the address offset */ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); for (i = 0; i < 3; i++) { san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); san_mac_data |= (u16)(san_mac_addr[i * 2]); hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); san_mac_offset++; } san_mac_addr_out: return status; } /** * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count * @hw: pointer to hardware structure * * Read PCIe configuration space, and get the MSI-X vector count from * the capabilities table. **/ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) { u16 msix_count = 1; u16 max_msix_count; u16 pcie_offset; switch (hw->mac.type) { case ixgbe_mac_82598EB: pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598; break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; break; default: return msix_count; } msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset); msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; /* MSI-X count is zero-based in HW */ msix_count++; if (msix_count > max_msix_count) msix_count = max_msix_count; return msix_count; } /** * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address * @hw: pointer to hardware structure * @addr: Address to put into receive address register * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or * finds the rar that it is aleady in; adds to the pool list **/ s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; u32 first_empty_rar = NO_EMPTY_RAR_FOUND; u32 rar; u32 rar_low, rar_high; u32 addr_low, addr_high; /* swap bytes for HW little endian */ addr_low = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24); addr_high = addr[4] | (addr[5] << 8); /* * Either find the mac_id in rar or find the first empty space. * rar_highwater points to just after the highest currently used * rar in order to shorten the search. It grows when we add a new * rar to the top. */ for (rar = 0; rar < hw->mac.rar_highwater; rar++) { rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); if (((IXGBE_RAH_AV & rar_high) == 0) && first_empty_rar == NO_EMPTY_RAR_FOUND) { first_empty_rar = rar; } else if ((rar_high & 0xFFFF) == addr_high) { rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); if (rar_low == addr_low) break; /* found it already in the rars */ } } if (rar < hw->mac.rar_highwater) { /* already there so just add to the pool bits */ ixgbe_set_vmdq(hw, rar, vmdq); } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { /* stick it into first empty RAR slot we found */ rar = first_empty_rar; ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); } else if (rar == hw->mac.rar_highwater) { /* add it to the top of the list and inc the highwater mark */ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); hw->mac.rar_highwater++; } else if (rar >= hw->mac.num_rar_entries) { return IXGBE_ERR_INVALID_MAC_ADDR; } /* * If we found rar[0], make sure the default pool bit (we use pool 0) * remains cleared to be sure default pool packets will get delivered */ if (rar == 0) ixgbe_clear_vmdq(hw, rar, 0); return rar; } /** * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address * @hw: pointer to hardware struct * @rar: receive address register index to disassociate * @vmdq: VMDq pool index to remove from the rar **/ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 mpsar_lo, mpsar_hi; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); if (!mpsar_lo && !mpsar_hi) goto done; if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { if (mpsar_lo) { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); mpsar_lo = 0; } if (mpsar_hi) { IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); mpsar_hi = 0; } } else if (vmdq < 32) { mpsar_lo &= ~(1 << vmdq); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); } else { mpsar_hi &= ~(1 << (vmdq - 32)); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); } /* was that the last pool using this rar? */ if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) hw->mac.ops.clear_rar(hw, rar); done: return 0; } /** * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address * @hw: pointer to hardware struct * @rar: receive address register index to associate with a VMDq index * @vmdq: VMDq pool index **/ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) { u32 mpsar; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (rar >= rar_entries) { hw_dbg(hw, "RAR index %d is out of range.\n", rar); return IXGBE_ERR_INVALID_ARGUMENT; } if (vmdq < 32) { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); mpsar |= 1 << vmdq; IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); } else { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); mpsar |= 1 << (vmdq - 32); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); } return 0; } /** * This function should only be involved in the IOV mode. * In IOV mode, Default pool is next pool after the number of * VFs advertized and not 0. * MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index] * * ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address * @hw: pointer to hardware struct * @vmdq: VMDq pool index **/ s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq) { u32 mpsar; u32 rar = hw->mac.san_mac_rar_index; if (vmdq < 32) { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); mpsar |= 1 << vmdq; IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); } else { mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); mpsar |= 1 << (vmdq - 32); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); } return 0; } /** * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array * @hw: pointer to hardware structure **/ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) { int i; hw_dbg(hw, " Clearing UTA\n"); for (i = 0; i < 128; i++) IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); return 0; } /** * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * * return the VLVF index where this VLAN id should be placed * **/ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) { u32 bits = 0; u32 first_empty_slot = 0; s32 regindex; /* short cut the special case */ if (vlan == 0) return 0; /* * Search for the vlan id in the VLVF entries. Save off the first empty * slot found along the way */ for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); if (!bits && !(first_empty_slot)) first_empty_slot = regindex; else if ((bits & 0x0FFF) == vlan) break; } /* * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan * in the VLVF. Else use the first empty VLVF register for this * vlan id. */ if (regindex >= IXGBE_VLVF_ENTRIES) { if (first_empty_slot) regindex = first_empty_slot; else { hw_dbg(hw, "No space in VLVF.\n"); regindex = IXGBE_ERR_NO_SPACE; } } return regindex; } /** * ixgbe_set_vfta_generic - Set VLAN filter table * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * * Turn on/off specified VLAN in the VLAN filter table. **/ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { s32 regindex; u32 bitindex; u32 vfta; u32 targetbit; s32 ret_val = 0; bool vfta_changed = false; if (vlan > 4095) return IXGBE_ERR_PARAM; /* * this is a 2 part operation - first the VFTA, then the * VLVF and VLVFB if VT Mode is set * We don't write the VFTA until we know the VLVF part succeeded. */ /* Part 1 * The VFTA is a bitstring made up of 128 32-bit registers * that enable the particular VLAN id, much like the MTA: * bits[11-5]: which register * bits[4-0]: which bit in the register */ regindex = (vlan >> 5) & 0x7F; bitindex = vlan & 0x1F; targetbit = (1 << bitindex); vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); if (vlan_on) { if (!(vfta & targetbit)) { vfta |= targetbit; vfta_changed = true; } } else { if ((vfta & targetbit)) { vfta &= ~targetbit; vfta_changed = true; } } /* Part 2 * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF */ ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_changed); if (ret_val != 0) return ret_val; if (vfta_changed) IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta); return 0; } /** * ixgbe_set_vlvf_generic - Set VLAN Pool Filter * @hw: pointer to hardware structure * @vlan: VLAN id to write to VLAN filter * @vind: VMDq output index that maps queue to VLAN id in VFVFB * @vlan_on: boolean flag to turn on/off VLAN in VFVF * @vfta_changed: pointer to boolean flag which indicates whether VFTA * should be changed * * Turn on/off specified bit in VLVF table. **/ s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed) { u32 vt; if (vlan > 4095) return IXGBE_ERR_PARAM; /* If VT Mode is set * Either vlan_on * make sure the vlan is in VLVF * set the vind bit in the matching VLVFB * Or !vlan_on * clear the pool bit and possibly the vind */ vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); if (vt & IXGBE_VT_CTL_VT_ENABLE) { s32 vlvf_index; u32 bits; vlvf_index = ixgbe_find_vlvf_slot(hw, vlan); if (vlvf_index < 0) return vlvf_index; if (vlan_on) { /* set the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); bits |= (1 << vind); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2), bits); } else { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); bits |= (1 << (vind - 32)); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1), bits); } } else { /* clear the pool bit */ if (vind < 32) { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); bits &= ~(1 << vind); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2), bits); bits |= IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); } else { bits = IXGBE_READ_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1)); bits &= ~(1 << (vind - 32)); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((vlvf_index * 2) + 1), bits); bits |= IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2)); } } /* * If there are still bits set in the VLVFB registers * for the VLAN ID indicated we need to see if the * caller is requesting that we clear the VFTA entry bit. * If the caller has requested that we clear the VFTA * entry bit but there are still pools/VFs using this VLAN * ID entry then ignore the request. We're not worried * about the case where we're turning the VFTA VLAN ID * entry bit on, only when requested to turn it off as * there may be multiple pools and/or VFs using the * VLAN ID entry. In that case we cannot clear the * VFTA bit until all pools/VFs using that VLAN ID have also * been cleared. This will be indicated by "bits" being * zero. */ if (bits) { IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), (IXGBE_VLVF_VIEN | vlan)); if ((!vlan_on) && (vfta_changed != NULL)) { /* someone wants to clear the vfta entry * but some pools/VFs are still using it. * Ignore it. */ *vfta_changed = false; } } else IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); } return 0; } /** * ixgbe_clear_vfta_generic - Clear VLAN filter table * @hw: pointer to hardware structure * * Clears the VLAN filer table, and the VMDq index associated with the filter **/ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) { u32 offset; for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0); IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0); } return 0; } /** * ixgbe_check_mac_link_generic - Determine link and speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true when link is up * @link_up_wait_to_complete: bool used to wait for link up or not * * Reads the links register to determine if link is up and the current speed **/ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete) { u32 links_reg, links_orig; u32 i; /* clear the old state */ links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_orig != links_reg) { hw_dbg(hw, "LINKS changed from %08X to %08X\n", links_orig, links_reg); } if (link_up_wait_to_complete) { for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = true; break; } else { *link_up = false; } msleep(100); links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); } } else { if (links_reg & IXGBE_LINKS_UP) *link_up = true; else *link_up = false; } if ((links_reg & IXGBE_LINKS_SPEED_82599) == IXGBE_LINKS_SPEED_10G_82599) *speed = IXGBE_LINK_SPEED_10GB_FULL; else if ((links_reg & IXGBE_LINKS_SPEED_82599) == IXGBE_LINKS_SPEED_1G_82599) *speed = IXGBE_LINK_SPEED_1GB_FULL; else if ((links_reg & IXGBE_LINKS_SPEED_82599) == IXGBE_LINKS_SPEED_100_82599) *speed = IXGBE_LINK_SPEED_100_FULL; else *speed = IXGBE_LINK_SPEED_UNKNOWN; return 0; } /** * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from * the EEPROM * @hw: pointer to hardware structure * @wwnn_prefix: the alternative WWNN prefix * @wwpn_prefix: the alternative WWPN prefix * * This function will read the EEPROM from the alternative SAN MAC address * block to check the support for the alternative WWNN/WWPN prefix support. **/ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix) { u16 offset, caps; u16 alt_san_mac_blk_offset; /* clear output first */ *wwnn_prefix = 0xFFFF; *wwpn_prefix = 0xFFFF; /* check if alternative SAN MAC is supported */ hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, &alt_san_mac_blk_offset); if ((alt_san_mac_blk_offset == 0) || (alt_san_mac_blk_offset == 0xFFFF)) goto wwn_prefix_out; /* check capability in alternative san mac address block */ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; hw->eeprom.ops.read(hw, offset, &caps); if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) goto wwn_prefix_out; /* get the corresponding prefix for WWNN/WWPN */ offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; hw->eeprom.ops.read(hw, offset, wwnn_prefix); offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; hw->eeprom.ops.read(hw, offset, wwpn_prefix); wwn_prefix_out: return 0; } /** * ixgbe_get_fcoe_boot_status_generic - Get FCOE boot status from EEPROM * @hw: pointer to hardware structure * @bs: the fcoe boot status * * This function will read the FCOE boot status from the iSCSI FCOE block **/ s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs) { u16 offset, caps, flags; s32 status; /* clear output first */ *bs = ixgbe_fcoe_bootstatus_unavailable; /* check if FCOE IBA block is present */ offset = IXGBE_FCOE_IBA_CAPS_BLK_PTR; status = hw->eeprom.ops.read(hw, offset, &caps); if (status != 0) goto out; if (!(caps & IXGBE_FCOE_IBA_CAPS_FCOE)) goto out; /* check if iSCSI FCOE block is populated */ status = hw->eeprom.ops.read(hw, IXGBE_ISCSI_FCOE_BLK_PTR, &offset); if (status != 0) goto out; if ((offset == 0) || (offset == 0xFFFF)) goto out; /* read fcoe flags in iSCSI FCOE block */ offset = offset + IXGBE_ISCSI_FCOE_FLAGS_OFFSET; status = hw->eeprom.ops.read(hw, offset, &flags); if (status != 0) goto out; if (flags & IXGBE_ISCSI_FCOE_FLAGS_ENABLE) *bs = ixgbe_fcoe_bootstatus_enabled; else *bs = ixgbe_fcoe_bootstatus_disabled; out: return status; } /** * ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for anti-spoofing * @pf: Physical Function pool - do not enable anti-spoofing for the PF * **/ void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf) { int j; int pf_target_reg = pf >> 3; int pf_target_shift = pf % 8; u32 pfvfspoof = 0; if (hw->mac.type == ixgbe_mac_82598EB) return; if (enable) pfvfspoof = IXGBE_SPOOF_MACAS_MASK; /* * PFVFSPOOF register array is size 8 with 8 bits assigned to * MAC anti-spoof enables in each register array element. */ for (j = 0; j < IXGBE_PFVFSPOOF_REG_COUNT; j++) IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof); /* If not enabling anti-spoofing then done */ if (!enable) return; /* * The PF should be allowed to spoof so that it can support * emulation mode NICs. Reset the bit assigned to the PF */ pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg)); pfvfspoof ^= (1 << pf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg), pfvfspoof); } /** * ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing * @hw: pointer to hardware structure * @enable: enable or disable switch for VLAN anti-spoofing * @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing * **/ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf) { int vf_target_reg = vf >> 3; int vf_target_shift = vf % 8 + IXGBE_SPOOF_VLANAS_SHIFT; u32 pfvfspoof; if (hw->mac.type == ixgbe_mac_82598EB) return; pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); if (enable) pfvfspoof |= (1 << vf_target_shift); else pfvfspoof &= ~(1 << vf_target_shift); IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } /** * ixgbe_get_device_caps_generic - Get additional device capabilities * @hw: pointer to hardware structure * @device_caps: the EEPROM word with the extra device capabilities * * This function will read the EEPROM location for the device capabilities, * and return the word through device_caps. **/ s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps) { hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); return 0; } /** * ixgbe_calculate_checksum - Calculate checksum for buffer * @buffer: pointer to EEPROM * @length: size of EEPROM to calculate a checksum for * Calculates the checksum for some buffer on a specified length. The * checksum calculated is returned. **/ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) { u32 i; u8 sum = 0; if (!buffer) return 0; for (i = 0; i < length; i++) sum += buffer[i]; return (u8) (0 - sum); } /** * ixgbe_host_interface_command - Issue command to manageability block * @hw: pointer to the HW structure * @buffer: contains the command to write and where the return status will * be placed * @length: length of buffer, must be multiple of 4 bytes * * Communicates with the manageability block. On success return 0 * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. **/ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, u32 length) { u32 hicr, i, bi; u32 hdr_size = sizeof(struct ixgbe_hic_hdr); u8 buf_len, dword_len; s32 ret_val = 0; if (length == 0 || length & 0x3 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { hw_dbg(hw, "Buffer length failure.\n"); ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Check that the host interface is enabled. */ hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if ((hicr & IXGBE_HICR_EN) == 0) { hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n"); ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Calculate length in DWORDs */ dword_len = length >> 2; /* * The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < dword_len; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, i, IXGBE_CPU_TO_LE32(buffer[i])); /* Setting this bit tells the ARC that a new command is pending. */ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) { hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if (!(hicr & IXGBE_HICR_C)) break; msleep(1); } /* Check command successful completion. */ if (i == IXGBE_HI_COMMAND_TIMEOUT || (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) { hw_dbg(hw, "Command has failed with no status valid.\n"); ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Calculate length in DWORDs */ dword_len = hdr_size >> 2; /* first pull in the header so we know the buffer length */ for (bi = 0; bi < dword_len; bi++) { buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); IXGBE_LE32_TO_CPUS(&buffer[bi]); } /* If there is any thing in data position pull it in */ buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; if (buf_len == 0) goto out; if (length < (buf_len + hdr_size)) { hw_dbg(hw, "Buffer not large enough for reply message.\n"); ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; goto out; } /* Calculate length in DWORDs, add 3 for odd lengths */ dword_len = (buf_len + 3) >> 2; /* Pull in the rest of the buffer (bi is where we left off)*/ for (; bi <= dword_len; bi++) { buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi); IXGBE_LE32_TO_CPUS(&buffer[bi]); } out: return ret_val; } /** * ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware * @hw: pointer to the HW structure * @maj: driver version major number * @min: driver version minor number * @build: driver version build number * @sub: driver version sub build number * * Sends driver version number to firmware through the manageability * block. On success return 0 * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. **/ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 sub) { struct ixgbe_hic_drv_info fw_cmd; int i; s32 ret_val = 0; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) { ret_val = IXGBE_ERR_SWFW_SYNC; goto out; } fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; fw_cmd.port_num = (u8)hw->bus.func; fw_cmd.ver_maj = maj; fw_cmd.ver_min = min; fw_cmd.ver_build = build; fw_cmd.ver_sub = sub; fw_cmd.hdr.checksum = 0; fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd, (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); fw_cmd.pad = 0; fw_cmd.pad2 = 0; for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, sizeof(fw_cmd)); if (ret_val != 0) continue; if (fw_cmd.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) ret_val = 0; else ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND; break; } hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM); out: return ret_val; } /** * ixgbe_set_rxpba_generic - Initialize Rx packet buffer * @hw: pointer to hardware structure * @num_pb: number of packet buffers to allocate * @headroom: reserve n KB of headroom * @strategy: packet buffer allocation strategy **/ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy) { u32 pbsize = hw->mac.rx_pb_size; int i = 0; u32 rxpktsize, txpktsize, txpbthresh; /* Reserve headroom */ pbsize -= headroom; if (!num_pb) num_pb = 1; /* Divide remaining packet buffer space amongst the number of packet * buffers requested using supplied strategy. */ switch (strategy) { case PBA_STRATEGY_WEIGHTED: /* ixgbe_dcb_pba_80_48 strategy weight first half of packet * buffer with 5/8 of the packet buffer space. */ rxpktsize = (pbsize * 5) / (num_pb * 4); pbsize -= rxpktsize * (num_pb / 2); rxpktsize <<= IXGBE_RXPBSIZE_SHIFT; for (; i < (num_pb / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); /* Fall through to configure remaining packet buffers */ case PBA_STRATEGY_EQUAL: rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT; for (; i < num_pb; i++) IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize); break; default: break; } /* Only support an equally distributed Tx packet buffer strategy. */ txpktsize = IXGBE_TXPBSIZE_MAX / num_pb; txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX; for (i = 0; i < num_pb; i++) { IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh); } /* Clear unused TCs, if any, to zero buffer size*/ for (; i < IXGBE_MAX_PB; i++) { IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); } } /** * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo * @hw: pointer to the hardware structure * * The 82599 and x540 MACs can experience issues if TX work is still pending * when a reset occurs. This function prevents this by flushing the PCIe * buffers on the system. **/ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) { u32 gcr_ext, hlreg0; /* * If double reset is not requested then all transactions should * already be clear and as such there is no work to do */ if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED)) return; /* * Set loopback enable to prevent any transmits from being sent * should the link come up. This assumes that the RXCTRL.RXEN bit * has already been cleared. */ hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK); /* initiate cleaning flow for buffers in the PCIe transaction layer */ gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR); /* Flush all writes and allow 20usec for all transactions to clear */ IXGBE_WRITE_FLUSH(hw); udelay(20); /* restore previous register values */ IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); } static const u8 ixgbe_emc_temp_data[4] = { IXGBE_EMC_INTERNAL_DATA, IXGBE_EMC_DIODE1_DATA, IXGBE_EMC_DIODE2_DATA, IXGBE_EMC_DIODE3_DATA }; static const u8 ixgbe_emc_therm_limit[4] = { IXGBE_EMC_INTERNAL_THERM_LIMIT, IXGBE_EMC_DIODE1_THERM_LIMIT, IXGBE_EMC_DIODE2_THERM_LIMIT, IXGBE_EMC_DIODE3_THERM_LIMIT }; /** * ixgbe_get_thermal_sensor_data - Gathers thermal sensor data * @hw: pointer to hardware structure * @data: pointer to the thermal sensor data structure * * Returns the thermal sensor data structure **/ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw) { s32 status = 0; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 i; struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; /* Only support thermal sensors attached to 82599 physical port 0 */ if ((hw->mac.type != ixgbe_mac_82599EB) || (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) { status = IXGBE_NOT_IMPLEMENTED; goto out; } status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset); if (status) goto out; if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) { status = IXGBE_NOT_IMPLEMENTED; goto out; } status = hw->eeprom.ops.read(hw, ets_offset, &ets_cfg); if (status) goto out; if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) != IXGBE_ETS_TYPE_EMC) { status = IXGBE_NOT_IMPLEMENTED; goto out; } num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); if (num_sensors > IXGBE_MAX_SENSORS) num_sensors = IXGBE_MAX_SENSORS; for (i = 0; i < num_sensors; i++) { status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor); if (status) goto out; sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> IXGBE_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> IXGBE_ETS_DATA_LOC_SHIFT); if (sensor_location != 0) { status = hw->phy.ops.read_i2c_byte(hw, ixgbe_emc_temp_data[sensor_index], IXGBE_I2C_THERMAL_SENSOR_ADDR, &data->sensor[i].temp); if (status) goto out; } } out: return status; } /** * ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds * @hw: pointer to hardware structure * * Inits the thermal sensor thresholds according to the NVM map * and save off the threshold and location values into mac.thermal_sensor_data **/ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw) { s32 status = 0; u16 ets_offset; u16 ets_cfg; u16 ets_sensor; u8 low_thresh_delta; u8 num_sensors; u8 sensor_index; u8 sensor_location; u8 therm_limit; u8 i; struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data; memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data)); /* Only support thermal sensors attached to 82599 physical port 0 */ if ((hw->mac.type != ixgbe_mac_82599EB) || (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) return IXGBE_NOT_IMPLEMENTED; hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset); if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) return IXGBE_NOT_IMPLEMENTED; hw->eeprom.ops.read(hw, ets_offset, &ets_cfg); if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT) != IXGBE_ETS_TYPE_EMC) return IXGBE_NOT_IMPLEMENTED; low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >> IXGBE_ETS_LTHRES_DELTA_SHIFT); num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK); for (i = 0; i < num_sensors; i++) { hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor); sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >> IXGBE_ETS_DATA_INDEX_SHIFT); sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >> IXGBE_ETS_DATA_LOC_SHIFT); therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK; hw->phy.ops.write_i2c_byte(hw, ixgbe_emc_therm_limit[sensor_index], IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit); if ((i < IXGBE_MAX_SENSORS) && (sensor_location != 0)) { data->sensor[i].location = sensor_location; data->sensor[i].caution_thresh = therm_limit; data->sensor[i].max_op_thresh = therm_limit - low_thresh_delta; } } return status; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_common.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_COMMON_H_ #define _IXGBE_COMMON_H_ #include "ixgbe_type.h" u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw); s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw); s32 ixgbe_read_pba_string_generic(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size); s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr); s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw); s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw); s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw); s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func, bool clear); s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw); void ixgbe_fc_autoneg(struct ixgbe_hw *hw); s32 ixgbe_validate_mac_addr(u8 *mac_addr); s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq); s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw); s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on); s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on, bool *vfta_changed); s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan); s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix); s32 ixgbe_get_fcoe_boot_status_generic(struct ixgbe_hw *hw, u16 *bs); void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf); void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom, int strategy); s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build, u8 ver); void ixgbe_clear_tx_pending(struct ixgbe_hw *hw); #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 #define IXGBE_EMC_INTERNAL_DATA 0x00 #define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20 #define IXGBE_EMC_DIODE1_DATA 0x01 #define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19 #define IXGBE_EMC_DIODE2_DATA 0x23 #define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A #define IXGBE_EMC_DIODE3_DATA 0x2A #define IXGBE_EMC_DIODE3_THERM_LIMIT 0x30 s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw); #endif /* IXGBE_COMMON */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_dcb.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_DCB_H_ #define _IXGBE_DCB_H_ #include "ixgbe_type.h" /* DCB defines */ /* DCB credit calculation defines */ #define IXGBE_DCB_CREDIT_QUANTUM 64 #define IXGBE_DCB_MAX_CREDIT_REFILL 200 /* 200 * 64B = 12800B */ #define IXGBE_DCB_MAX_TSO_SIZE (32 * 1024) /* Max TSO pkt size in DCB*/ #define IXGBE_DCB_MAX_CREDIT (2 * IXGBE_DCB_MAX_CREDIT_REFILL) /* 513 for 32KB TSO packet */ #define IXGBE_DCB_MIN_TSO_CREDIT \ ((IXGBE_DCB_MAX_TSO_SIZE / IXGBE_DCB_CREDIT_QUANTUM) + 1) /* DCB configuration defines */ #define IXGBE_DCB_MAX_USER_PRIORITY 8 #define IXGBE_DCB_MAX_BW_GROUP 8 #define IXGBE_DCB_BW_PERCENT 100 #define IXGBE_DCB_TX_CONFIG 0 #define IXGBE_DCB_RX_CONFIG 1 /* DCB capability defines */ #define IXGBE_DCB_PG_SUPPORT 0x00000001 #define IXGBE_DCB_PFC_SUPPORT 0x00000002 #define IXGBE_DCB_BCN_SUPPORT 0x00000004 #define IXGBE_DCB_UP2TC_SUPPORT 0x00000008 #define IXGBE_DCB_GSP_SUPPORT 0x00000010 struct ixgbe_dcb_support { u32 capabilities; /* DCB capabilities */ /* Each bit represents a number of TCs configurable in the hw. * If 8 traffic classes can be configured, the value is 0x80. */ u8 traffic_classes; u8 pfc_traffic_classes; }; enum ixgbe_dcb_tsa { ixgbe_dcb_tsa_ets = 0, ixgbe_dcb_tsa_group_strict_cee, ixgbe_dcb_tsa_strict }; /* Traffic class bandwidth allocation per direction */ struct ixgbe_dcb_tc_path { u8 bwg_id; /* Bandwidth Group (BWG) ID */ u8 bwg_percent; /* % of BWG's bandwidth */ u8 link_percent; /* % of link bandwidth */ u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */ u16 data_credits_refill; /* Credit refill amount in 64B granularity */ u16 data_credits_max; /* Max credits for a configured packet buffer * in 64B granularity.*/ enum ixgbe_dcb_tsa tsa; /* Link or Group Strict Priority */ }; enum ixgbe_dcb_pfc { ixgbe_dcb_pfc_disabled = 0, ixgbe_dcb_pfc_enabled, ixgbe_dcb_pfc_enabled_txonly, ixgbe_dcb_pfc_enabled_rxonly }; /* Traffic class configuration */ struct ixgbe_dcb_tc_config { struct ixgbe_dcb_tc_path path[2]; /* One each for Tx/Rx */ enum ixgbe_dcb_pfc pfc; /* Class based flow control setting */ u16 desc_credits_max; /* For Tx Descriptor arbitration */ u8 tc; /* Traffic class (TC) */ }; enum ixgbe_dcb_pba { /* PBA[0-7] each use 64KB FIFO */ ixgbe_dcb_pba_equal = PBA_STRATEGY_EQUAL, /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */ ixgbe_dcb_pba_80_48 = PBA_STRATEGY_WEIGHTED }; struct ixgbe_dcb_num_tcs { u8 pg_tcs; u8 pfc_tcs; }; struct ixgbe_dcb_config { struct ixgbe_dcb_tc_config tc_config[IXGBE_DCB_MAX_TRAFFIC_CLASS]; struct ixgbe_dcb_support support; struct ixgbe_dcb_num_tcs num_tcs; u8 bw_percentage[2][IXGBE_DCB_MAX_BW_GROUP]; /* One each for Tx/Rx */ bool pfc_mode_enable; bool round_robin_enable; enum ixgbe_dcb_pba rx_pba_cfg; u32 dcb_cfg_version; /* Not used...OS-specific? */ u32 link_speed; /* For bandwidth allocation validation purpose */ bool vt_mode; }; /* DCB driver APIs */ /* DCB rule checking */ s32 ixgbe_dcb_check_config_cee(struct ixgbe_dcb_config *); /* DCB credits calculation */ s32 ixgbe_dcb_calculate_tc_credits(u8 *, u16 *, u16 *, int); s32 ixgbe_dcb_calculate_tc_credits_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *, u32, u8); /* DCB PFC */ s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, u8, u8 *); s32 ixgbe_dcb_config_pfc_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); /* DCB stats */ s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *); s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8); /* DCB config arbiters */ s32 ixgbe_dcb_config_tx_desc_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_config_tx_data_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); s32 ixgbe_dcb_config_rx_arbiter_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); /* DCB unpack routines */ void ixgbe_dcb_unpack_pfc_cee(struct ixgbe_dcb_config *, u8 *, u8 *); void ixgbe_dcb_unpack_refill_cee(struct ixgbe_dcb_config *, int, u16 *); void ixgbe_dcb_unpack_max_cee(struct ixgbe_dcb_config *, u16 *); void ixgbe_dcb_unpack_bwgid_cee(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_tsa_cee(struct ixgbe_dcb_config *, int, u8 *); void ixgbe_dcb_unpack_map_cee(struct ixgbe_dcb_config *, int, u8 *); /* DCB initialization */ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, u16 *, u16 *, u8 *, u8 *, u8 *); s32 ixgbe_dcb_hw_config_cee(struct ixgbe_hw *, struct ixgbe_dcb_config *); #endif /* _IXGBE_DCB_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_ethtool.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* ethtool support for ixgbe */ #include #include #include #include #include #include #include #ifdef SIOCETHTOOL #include #include "ixgbe.h" #ifndef ETH_GSTRING_LEN #define ETH_GSTRING_LEN 32 #endif #define IXGBE_ALL_RAR_ENTRIES 16 #ifdef ETHTOOL_OPS_COMPAT #include "kcompat_ethtool.c" #endif #ifdef ETHTOOL_GSTATS struct ixgbe_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; int stat_offset; }; #define IXGBE_NETDEV_STAT(_net_stat) { \ .stat_string = #_net_stat, \ .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \ .stat_offset = offsetof(struct net_device_stats, _net_stat) \ } static const struct ixgbe_stats ixgbe_gstrings_net_stats[] = { IXGBE_NETDEV_STAT(rx_packets), IXGBE_NETDEV_STAT(tx_packets), IXGBE_NETDEV_STAT(rx_bytes), IXGBE_NETDEV_STAT(tx_bytes), IXGBE_NETDEV_STAT(rx_errors), IXGBE_NETDEV_STAT(tx_errors), IXGBE_NETDEV_STAT(rx_dropped), IXGBE_NETDEV_STAT(tx_dropped), IXGBE_NETDEV_STAT(multicast), IXGBE_NETDEV_STAT(collisions), IXGBE_NETDEV_STAT(rx_over_errors), IXGBE_NETDEV_STAT(rx_crc_errors), IXGBE_NETDEV_STAT(rx_frame_errors), IXGBE_NETDEV_STAT(rx_fifo_errors), IXGBE_NETDEV_STAT(rx_missed_errors), IXGBE_NETDEV_STAT(tx_aborted_errors), IXGBE_NETDEV_STAT(tx_carrier_errors), IXGBE_NETDEV_STAT(tx_fifo_errors), IXGBE_NETDEV_STAT(tx_heartbeat_errors), }; #define IXGBE_STAT(_name, _stat) { \ .stat_string = _name, \ .sizeof_stat = FIELD_SIZEOF(struct ixgbe_adapter, _stat), \ .stat_offset = offsetof(struct ixgbe_adapter, _stat) \ } static struct ixgbe_stats ixgbe_gstrings_stats[] = { IXGBE_STAT("rx_pkts_nic", stats.gprc), IXGBE_STAT("tx_pkts_nic", stats.gptc), IXGBE_STAT("rx_bytes_nic", stats.gorc), IXGBE_STAT("tx_bytes_nic", stats.gotc), IXGBE_STAT("lsc_int", lsc_int), IXGBE_STAT("tx_busy", tx_busy), IXGBE_STAT("non_eop_descs", non_eop_descs), #ifndef CONFIG_IXGBE_NAPI IXGBE_STAT("rx_dropped_backlog", rx_dropped_backlog), #endif IXGBE_STAT("broadcast", stats.bprc), IXGBE_STAT("rx_no_buffer_count", stats.rnbc[0]) , IXGBE_STAT("tx_timeout_count", tx_timeout_count), IXGBE_STAT("tx_restart_queue", restart_queue), IXGBE_STAT("rx_long_length_errors", stats.roc), IXGBE_STAT("rx_short_length_errors", stats.ruc), IXGBE_STAT("tx_flow_control_xon", stats.lxontxc), IXGBE_STAT("rx_flow_control_xon", stats.lxonrxc), IXGBE_STAT("tx_flow_control_xoff", stats.lxofftxc), IXGBE_STAT("rx_flow_control_xoff", stats.lxoffrxc), IXGBE_STAT("rx_csum_offload_errors", hw_csum_rx_error), IXGBE_STAT("alloc_rx_page_failed", alloc_rx_page_failed), IXGBE_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed), #ifndef IXGBE_NO_LRO IXGBE_STAT("lro_aggregated", lro_stats.coal), IXGBE_STAT("lro_flushed", lro_stats.flushed), #endif /* IXGBE_NO_LRO */ IXGBE_STAT("rx_no_dma_resources", hw_rx_no_dma_resources), IXGBE_STAT("hw_rsc_aggregated", rsc_total_count), IXGBE_STAT("hw_rsc_flushed", rsc_total_flush), #ifdef HAVE_TX_MQ IXGBE_STAT("fdir_match", stats.fdirmatch), IXGBE_STAT("fdir_miss", stats.fdirmiss), IXGBE_STAT("fdir_overflow", fdir_overflow), #endif /* HAVE_TX_MQ */ #ifdef IXGBE_FCOE IXGBE_STAT("fcoe_bad_fccrc", stats.fccrc), IXGBE_STAT("fcoe_last_errors", stats.fclast), IXGBE_STAT("rx_fcoe_dropped", stats.fcoerpdc), IXGBE_STAT("rx_fcoe_packets", stats.fcoeprc), IXGBE_STAT("rx_fcoe_dwords", stats.fcoedwrc), IXGBE_STAT("fcoe_noddp", stats.fcoe_noddp), IXGBE_STAT("fcoe_noddp_ext_buff", stats.fcoe_noddp_ext_buff), IXGBE_STAT("tx_fcoe_packets", stats.fcoeptc), IXGBE_STAT("tx_fcoe_dwords", stats.fcoedwtc), #endif /* IXGBE_FCOE */ IXGBE_STAT("os2bmc_rx_by_bmc", stats.o2bgptc), IXGBE_STAT("os2bmc_tx_by_bmc", stats.b2ospc), IXGBE_STAT("os2bmc_tx_by_host", stats.o2bspc), IXGBE_STAT("os2bmc_rx_by_host", stats.b2ogprc), }; #define IXGBE_QUEUE_STATS_LEN \ ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \ ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \ (sizeof(struct ixgbe_queue_stats) / sizeof(u64))) #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) #define IXGBE_NETDEV_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_net_stats) #define IXGBE_PB_STATS_LEN ( \ (((struct ixgbe_adapter *)netdev_priv(netdev))->flags & \ IXGBE_FLAG_DCB_ENABLED) ? \ (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \ sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \ sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \ sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \ / sizeof(u64) : 0) #define IXGBE_VF_STATS_LEN \ ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_vfs) * \ (sizeof(struct vf_stats) / sizeof(u64))) #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \ IXGBE_NETDEV_STATS_LEN + \ IXGBE_PB_STATS_LEN + \ IXGBE_QUEUE_STATS_LEN + \ IXGBE_VF_STATS_LEN) #endif /* ETHTOOL_GSTATS */ #ifdef ETHTOOL_TEST static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { "Register test (offline)", "Eeprom test (offline)", "Interrupt test (offline)", "Loopback test (offline)", "Link test (on/offline)" }; #define IXGBE_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) #endif /* ETHTOOL_TEST */ int ixgbe_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = 0; bool link_up; ecmd->supported = SUPPORTED_10000baseT_Full; ecmd->autoneg = AUTONEG_ENABLE; ecmd->transceiver = XCVR_EXTERNAL; if ((hw->phy.media_type == ixgbe_media_type_copper) || (hw->phy.multispeed_fiber)) { ecmd->supported |= (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg); switch (hw->mac.type) { case ixgbe_mac_X540: ecmd->supported |= SUPPORTED_100baseT_Full; break; default: break; } ecmd->advertising = ADVERTISED_Autoneg; if (hw->phy.autoneg_advertised) { if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) ecmd->advertising |= ADVERTISED_100baseT_Full; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) ecmd->advertising |= ADVERTISED_10000baseT_Full; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) ecmd->advertising |= ADVERTISED_1000baseT_Full; } else { /* * Default advertised modes in case * phy.autoneg_advertised isn't set. */ ecmd->advertising |= (ADVERTISED_10000baseT_Full | ADVERTISED_1000baseT_Full); if (hw->mac.type == ixgbe_mac_X540) ecmd->advertising |= ADVERTISED_100baseT_Full; } if (hw->phy.media_type == ixgbe_media_type_copper) { ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; } else { ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; ecmd->port = PORT_FIBRE; } } else if (hw->phy.media_type == ixgbe_media_type_backplane) { /* Set as FIBRE until SERDES defined in kernel */ if (hw->device_id == IXGBE_DEV_ID_82598_BX) { ecmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; } else if ((hw->device_id == IXGBE_DEV_ID_82599_COMBO_BACKPLANE) || (hw->device_id == IXGBE_DEV_ID_82599_KX4_MEZZ)) { ecmd->supported |= (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE); ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; } else { ecmd->supported |= (SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; } } else { ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; } #ifdef HAVE_ETHTOOL_SFP_DISPLAY_PORT /* Get PHY type */ switch (adapter->hw.phy.type) { case ixgbe_phy_tn: case ixgbe_phy_aq: case ixgbe_phy_cu_unknown: /* Copper 10G-BASET */ ecmd->port = PORT_TP; break; case ixgbe_phy_qt: ecmd->port = PORT_FIBRE; break; case ixgbe_phy_nl: case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: switch (adapter->hw.phy.sfp_type) { /* SFP+ devices, further checking needed */ case ixgbe_sfp_type_da_cu: case ixgbe_sfp_type_da_cu_core0: case ixgbe_sfp_type_da_cu_core1: ecmd->port = PORT_DA; break; case ixgbe_sfp_type_sr: case ixgbe_sfp_type_lr: case ixgbe_sfp_type_srlr_core0: case ixgbe_sfp_type_srlr_core1: ecmd->port = PORT_FIBRE; break; case ixgbe_sfp_type_not_present: ecmd->port = PORT_NONE; break; case ixgbe_sfp_type_1g_cu_core0: case ixgbe_sfp_type_1g_cu_core1: ecmd->port = PORT_TP; ecmd->supported = SUPPORTED_TP; ecmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_TP); break; case ixgbe_sfp_type_1g_sx_core0: case ixgbe_sfp_type_1g_sx_core1: ecmd->port = PORT_FIBRE; ecmd->supported = SUPPORTED_FIBRE; ecmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_FIBRE); break; case ixgbe_sfp_type_unknown: default: ecmd->port = PORT_OTHER; break; } break; case ixgbe_phy_xaui: ecmd->port = PORT_NONE; break; case ixgbe_phy_unknown: case ixgbe_phy_generic: case ixgbe_phy_sfp_unsupported: default: ecmd->port = PORT_OTHER; break; } #endif if (!in_interrupt()) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); } else { /* * this case is a special workaround for RHEL5 bonding * that calls this routine from interrupt context */ link_speed = adapter->link_speed; link_up = adapter->link_up; } if (link_up) { switch (link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: ecmd->speed = SPEED_10000; break; case IXGBE_LINK_SPEED_1GB_FULL: ecmd->speed = SPEED_1000; break; case IXGBE_LINK_SPEED_100_FULL: ecmd->speed = SPEED_100; break; default: break; } ecmd->duplex = DUPLEX_FULL; } else { ecmd->speed = -1; ecmd->duplex = -1; } return 0; } static int ixgbe_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 advertised, old; s32 err = 0; if ((hw->phy.media_type == ixgbe_media_type_copper) || (hw->phy.multispeed_fiber)) { /* * this function does not support duplex forcing, but can * limit the advertising of the adapter to the specified speed */ if (ecmd->autoneg == AUTONEG_DISABLE) return -EINVAL; if (ecmd->advertising & ~ecmd->supported) return -EINVAL; old = hw->phy.autoneg_advertised; advertised = 0; if (ecmd->advertising & ADVERTISED_10000baseT_Full) advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (ecmd->advertising & ADVERTISED_1000baseT_Full) advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (ecmd->advertising & ADVERTISED_100baseT_Full) advertised |= IXGBE_LINK_SPEED_100_FULL; if (old == advertised) return err; /* this sets the link speed and restarts auto-neg */ hw->mac.autotry_restart = true; err = hw->mac.ops.setup_link(hw, advertised, true, true); if (err) { e_info(probe, "setup link failed with code %d\n", err); hw->mac.ops.setup_link(hw, old, true, true); } } return err; } static void ixgbe_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; if (hw->fc.disable_fc_autoneg) pause->autoneg = 0; else pause->autoneg = 1; if (hw->fc.current_mode == ixgbe_fc_rx_pause) { pause->rx_pause = 1; } else if (hw->fc.current_mode == ixgbe_fc_tx_pause) { pause->tx_pause = 1; } else if (hw->fc.current_mode == ixgbe_fc_full) { pause->rx_pause = 1; pause->tx_pause = 1; } } static int ixgbe_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_fc_info fc = hw->fc; /* 82598 does no support link flow control with DCB enabled */ if ((hw->mac.type == ixgbe_mac_82598EB) && (adapter->flags & IXGBE_FLAG_DCB_ENABLED)) return -EINVAL; fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE); if ((pause->rx_pause && pause->tx_pause) || pause->autoneg) fc.requested_mode = ixgbe_fc_full; else if (pause->rx_pause) fc.requested_mode = ixgbe_fc_rx_pause; else if (pause->tx_pause) fc.requested_mode = ixgbe_fc_tx_pause; else fc.requested_mode = ixgbe_fc_none; /* if the thing changed then we'll update and use new autoneg */ if (memcmp(&fc, &hw->fc, sizeof(struct ixgbe_fc_info))) { hw->fc = fc; if (netif_running(netdev)) ixgbe_reinit_locked(adapter); else ixgbe_reset(adapter); } return 0; } static u32 ixgbe_get_msglevel(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); return adapter->msg_enable; } static void ixgbe_set_msglevel(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); adapter->msg_enable = data; } static int ixgbe_get_regs_len(struct net_device *netdev) { #define IXGBE_REGS_LEN 1129 return IXGBE_REGS_LEN * sizeof(u32); } #define IXGBE_GET_STAT(_A_, _R_) (_A_->stats._R_) static void ixgbe_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 *regs_buff = p; u8 i; printk(KERN_DEBUG "ixgbe_get_regs_1\n"); memset(p, 0, IXGBE_REGS_LEN * sizeof(u32)); printk(KERN_DEBUG "ixgbe_get_regs_2 0x%p\n", hw->hw_addr); regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id; /* General Registers */ regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_CTRL); printk(KERN_DEBUG "ixgbe_get_regs_3\n"); regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_STATUS); regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_ESDP); regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_EODSDP); regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_LEDCTL); regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_FRTIMER); regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_TCPTIMER); printk(KERN_DEBUG "ixgbe_get_regs_4\n"); /* NVM Register */ regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_EEC); regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_EERD); regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_FLA); regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_EEMNGCTL); regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_EEMNGDATA); regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_FLMNGCTL); regs_buff[14] = IXGBE_READ_REG(hw, IXGBE_FLMNGDATA); regs_buff[15] = IXGBE_READ_REG(hw, IXGBE_FLMNGCNT); regs_buff[16] = IXGBE_READ_REG(hw, IXGBE_FLOP); regs_buff[17] = IXGBE_READ_REG(hw, IXGBE_GRC); /* Interrupt */ /* don't read EICR because it can clear interrupt causes, instead * read EICS which is a shadow but doesn't clear EICR */ regs_buff[18] = IXGBE_READ_REG(hw, IXGBE_EICS); regs_buff[19] = IXGBE_READ_REG(hw, IXGBE_EICS); regs_buff[20] = IXGBE_READ_REG(hw, IXGBE_EIMS); regs_buff[21] = IXGBE_READ_REG(hw, IXGBE_EIMC); regs_buff[22] = IXGBE_READ_REG(hw, IXGBE_EIAC); regs_buff[23] = IXGBE_READ_REG(hw, IXGBE_EIAM); regs_buff[24] = IXGBE_READ_REG(hw, IXGBE_EITR(0)); regs_buff[25] = IXGBE_READ_REG(hw, IXGBE_IVAR(0)); regs_buff[26] = IXGBE_READ_REG(hw, IXGBE_MSIXT); regs_buff[27] = IXGBE_READ_REG(hw, IXGBE_MSIXPBA); regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_PBACL(0)); regs_buff[29] = IXGBE_READ_REG(hw, IXGBE_GPIE); /* Flow Control */ regs_buff[30] = IXGBE_READ_REG(hw, IXGBE_PFCTOP); regs_buff[31] = IXGBE_READ_REG(hw, IXGBE_FCTTV(0)); regs_buff[32] = IXGBE_READ_REG(hw, IXGBE_FCTTV(1)); regs_buff[33] = IXGBE_READ_REG(hw, IXGBE_FCTTV(2)); regs_buff[34] = IXGBE_READ_REG(hw, IXGBE_FCTTV(3)); for (i = 0; i < 8; i++) { switch (hw->mac.type) { case ixgbe_mac_82598EB: regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL(i)); regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH(i)); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i)); regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i)); break; default: break; } } regs_buff[51] = IXGBE_READ_REG(hw, IXGBE_FCRTV); regs_buff[52] = IXGBE_READ_REG(hw, IXGBE_TFCS); /* Receive DMA */ for (i = 0; i < 64; i++) regs_buff[53 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAL(i)); for (i = 0; i < 64; i++) regs_buff[117 + i] = IXGBE_READ_REG(hw, IXGBE_RDBAH(i)); for (i = 0; i < 64; i++) regs_buff[181 + i] = IXGBE_READ_REG(hw, IXGBE_RDLEN(i)); for (i = 0; i < 64; i++) regs_buff[245 + i] = IXGBE_READ_REG(hw, IXGBE_RDH(i)); for (i = 0; i < 64; i++) regs_buff[309 + i] = IXGBE_READ_REG(hw, IXGBE_RDT(i)); for (i = 0; i < 64; i++) regs_buff[373 + i] = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)); for (i = 0; i < 16; i++) regs_buff[437 + i] = IXGBE_READ_REG(hw, IXGBE_SRRCTL(i)); for (i = 0; i < 16; i++) regs_buff[453 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); regs_buff[469] = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); for (i = 0; i < 8; i++) regs_buff[470 + i] = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)); regs_buff[478] = IXGBE_READ_REG(hw, IXGBE_RXCTRL); regs_buff[479] = IXGBE_READ_REG(hw, IXGBE_DROPEN); /* Receive */ regs_buff[480] = IXGBE_READ_REG(hw, IXGBE_RXCSUM); regs_buff[481] = IXGBE_READ_REG(hw, IXGBE_RFCTL); for (i = 0; i < 16; i++) regs_buff[482 + i] = IXGBE_READ_REG(hw, IXGBE_RAL(i)); for (i = 0; i < 16; i++) regs_buff[498 + i] = IXGBE_READ_REG(hw, IXGBE_RAH(i)); regs_buff[514] = IXGBE_READ_REG(hw, IXGBE_PSRTYPE(0)); regs_buff[515] = IXGBE_READ_REG(hw, IXGBE_FCTRL); regs_buff[516] = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); regs_buff[517] = IXGBE_READ_REG(hw, IXGBE_MCSTCTRL); regs_buff[518] = IXGBE_READ_REG(hw, IXGBE_MRQC); regs_buff[519] = IXGBE_READ_REG(hw, IXGBE_VMD_CTL); for (i = 0; i < 8; i++) regs_buff[520 + i] = IXGBE_READ_REG(hw, IXGBE_IMIR(i)); for (i = 0; i < 8; i++) regs_buff[528 + i] = IXGBE_READ_REG(hw, IXGBE_IMIREXT(i)); regs_buff[536] = IXGBE_READ_REG(hw, IXGBE_IMIRVP); /* Transmit */ for (i = 0; i < 32; i++) regs_buff[537 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAL(i)); for (i = 0; i < 32; i++) regs_buff[569 + i] = IXGBE_READ_REG(hw, IXGBE_TDBAH(i)); for (i = 0; i < 32; i++) regs_buff[601 + i] = IXGBE_READ_REG(hw, IXGBE_TDLEN(i)); for (i = 0; i < 32; i++) regs_buff[633 + i] = IXGBE_READ_REG(hw, IXGBE_TDH(i)); for (i = 0; i < 32; i++) regs_buff[665 + i] = IXGBE_READ_REG(hw, IXGBE_TDT(i)); for (i = 0; i < 32; i++) regs_buff[697 + i] = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i)); for (i = 0; i < 32; i++) regs_buff[729 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAL(i)); for (i = 0; i < 32; i++) regs_buff[761 + i] = IXGBE_READ_REG(hw, IXGBE_TDWBAH(i)); regs_buff[793] = IXGBE_READ_REG(hw, IXGBE_DTXCTL); for (i = 0; i < 16; i++) regs_buff[794 + i] = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); regs_buff[810] = IXGBE_READ_REG(hw, IXGBE_TIPG); for (i = 0; i < 8; i++) regs_buff[811 + i] = IXGBE_READ_REG(hw, IXGBE_TXPBSIZE(i)); regs_buff[819] = IXGBE_READ_REG(hw, IXGBE_MNGTXMAP); /* Wake Up */ regs_buff[820] = IXGBE_READ_REG(hw, IXGBE_WUC); regs_buff[821] = IXGBE_READ_REG(hw, IXGBE_WUFC); regs_buff[822] = IXGBE_READ_REG(hw, IXGBE_WUS); regs_buff[823] = IXGBE_READ_REG(hw, IXGBE_IPAV); regs_buff[824] = IXGBE_READ_REG(hw, IXGBE_IP4AT); regs_buff[825] = IXGBE_READ_REG(hw, IXGBE_IP6AT); regs_buff[826] = IXGBE_READ_REG(hw, IXGBE_WUPL); regs_buff[827] = IXGBE_READ_REG(hw, IXGBE_WUPM); regs_buff[828] = IXGBE_READ_REG(hw, IXGBE_FHFT(0)); /* DCB */ regs_buff[829] = IXGBE_READ_REG(hw, IXGBE_RMCS); regs_buff[830] = IXGBE_READ_REG(hw, IXGBE_DPMCS); regs_buff[831] = IXGBE_READ_REG(hw, IXGBE_PDPMCS); regs_buff[832] = IXGBE_READ_REG(hw, IXGBE_RUPPBMR); for (i = 0; i < 8; i++) regs_buff[833 + i] = IXGBE_READ_REG(hw, IXGBE_RT2CR(i)); for (i = 0; i < 8; i++) regs_buff[841 + i] = IXGBE_READ_REG(hw, IXGBE_RT2SR(i)); for (i = 0; i < 8; i++) regs_buff[849 + i] = IXGBE_READ_REG(hw, IXGBE_TDTQ2TCCR(i)); for (i = 0; i < 8; i++) regs_buff[857 + i] = IXGBE_READ_REG(hw, IXGBE_TDTQ2TCSR(i)); for (i = 0; i < 8; i++) regs_buff[865 + i] = IXGBE_READ_REG(hw, IXGBE_TDPT2TCCR(i)); for (i = 0; i < 8; i++) regs_buff[873 + i] = IXGBE_READ_REG(hw, IXGBE_TDPT2TCSR(i)); /* Statistics */ regs_buff[881] = IXGBE_GET_STAT(adapter, crcerrs); regs_buff[882] = IXGBE_GET_STAT(adapter, illerrc); regs_buff[883] = IXGBE_GET_STAT(adapter, errbc); regs_buff[884] = IXGBE_GET_STAT(adapter, mspdc); for (i = 0; i < 8; i++) regs_buff[885 + i] = IXGBE_GET_STAT(adapter, mpc[i]); regs_buff[893] = IXGBE_GET_STAT(adapter, mlfc); regs_buff[894] = IXGBE_GET_STAT(adapter, mrfc); regs_buff[895] = IXGBE_GET_STAT(adapter, rlec); regs_buff[896] = IXGBE_GET_STAT(adapter, lxontxc); regs_buff[897] = IXGBE_GET_STAT(adapter, lxonrxc); regs_buff[898] = IXGBE_GET_STAT(adapter, lxofftxc); regs_buff[899] = IXGBE_GET_STAT(adapter, lxoffrxc); for (i = 0; i < 8; i++) regs_buff[900 + i] = IXGBE_GET_STAT(adapter, pxontxc[i]); for (i = 0; i < 8; i++) regs_buff[908 + i] = IXGBE_GET_STAT(adapter, pxonrxc[i]); for (i = 0; i < 8; i++) regs_buff[916 + i] = IXGBE_GET_STAT(adapter, pxofftxc[i]); for (i = 0; i < 8; i++) regs_buff[924 + i] = IXGBE_GET_STAT(adapter, pxoffrxc[i]); regs_buff[932] = IXGBE_GET_STAT(adapter, prc64); regs_buff[933] = IXGBE_GET_STAT(adapter, prc127); regs_buff[934] = IXGBE_GET_STAT(adapter, prc255); regs_buff[935] = IXGBE_GET_STAT(adapter, prc511); regs_buff[936] = IXGBE_GET_STAT(adapter, prc1023); regs_buff[937] = IXGBE_GET_STAT(adapter, prc1522); regs_buff[938] = IXGBE_GET_STAT(adapter, gprc); regs_buff[939] = IXGBE_GET_STAT(adapter, bprc); regs_buff[940] = IXGBE_GET_STAT(adapter, mprc); regs_buff[941] = IXGBE_GET_STAT(adapter, gptc); regs_buff[942] = IXGBE_GET_STAT(adapter, gorc); regs_buff[944] = IXGBE_GET_STAT(adapter, gotc); for (i = 0; i < 8; i++) regs_buff[946 + i] = IXGBE_GET_STAT(adapter, rnbc[i]); regs_buff[954] = IXGBE_GET_STAT(adapter, ruc); regs_buff[955] = IXGBE_GET_STAT(adapter, rfc); regs_buff[956] = IXGBE_GET_STAT(adapter, roc); regs_buff[957] = IXGBE_GET_STAT(adapter, rjc); regs_buff[958] = IXGBE_GET_STAT(adapter, mngprc); regs_buff[959] = IXGBE_GET_STAT(adapter, mngpdc); regs_buff[960] = IXGBE_GET_STAT(adapter, mngptc); regs_buff[961] = IXGBE_GET_STAT(adapter, tor); regs_buff[963] = IXGBE_GET_STAT(adapter, tpr); regs_buff[964] = IXGBE_GET_STAT(adapter, tpt); regs_buff[965] = IXGBE_GET_STAT(adapter, ptc64); regs_buff[966] = IXGBE_GET_STAT(adapter, ptc127); regs_buff[967] = IXGBE_GET_STAT(adapter, ptc255); regs_buff[968] = IXGBE_GET_STAT(adapter, ptc511); regs_buff[969] = IXGBE_GET_STAT(adapter, ptc1023); regs_buff[970] = IXGBE_GET_STAT(adapter, ptc1522); regs_buff[971] = IXGBE_GET_STAT(adapter, mptc); regs_buff[972] = IXGBE_GET_STAT(adapter, bptc); regs_buff[973] = IXGBE_GET_STAT(adapter, xec); for (i = 0; i < 16; i++) regs_buff[974 + i] = IXGBE_GET_STAT(adapter, qprc[i]); for (i = 0; i < 16; i++) regs_buff[990 + i] = IXGBE_GET_STAT(adapter, qptc[i]); for (i = 0; i < 16; i++) regs_buff[1006 + i] = IXGBE_GET_STAT(adapter, qbrc[i]); for (i = 0; i < 16; i++) regs_buff[1022 + i] = IXGBE_GET_STAT(adapter, qbtc[i]); /* MAC */ regs_buff[1038] = IXGBE_READ_REG(hw, IXGBE_PCS1GCFIG); regs_buff[1039] = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); regs_buff[1040] = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); regs_buff[1041] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG0); regs_buff[1042] = IXGBE_READ_REG(hw, IXGBE_PCS1GDBG1); regs_buff[1043] = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); regs_buff[1044] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); regs_buff[1045] = IXGBE_READ_REG(hw, IXGBE_PCS1GANNP); regs_buff[1046] = IXGBE_READ_REG(hw, IXGBE_PCS1GANLPNP); regs_buff[1047] = IXGBE_READ_REG(hw, IXGBE_HLREG0); regs_buff[1048] = IXGBE_READ_REG(hw, IXGBE_HLREG1); regs_buff[1049] = IXGBE_READ_REG(hw, IXGBE_PAP); regs_buff[1050] = IXGBE_READ_REG(hw, IXGBE_MACA); regs_buff[1051] = IXGBE_READ_REG(hw, IXGBE_APAE); regs_buff[1052] = IXGBE_READ_REG(hw, IXGBE_ARD); regs_buff[1053] = IXGBE_READ_REG(hw, IXGBE_AIS); regs_buff[1054] = IXGBE_READ_REG(hw, IXGBE_MSCA); regs_buff[1055] = IXGBE_READ_REG(hw, IXGBE_MSRWD); regs_buff[1056] = IXGBE_READ_REG(hw, IXGBE_MLADD); regs_buff[1057] = IXGBE_READ_REG(hw, IXGBE_MHADD); regs_buff[1058] = IXGBE_READ_REG(hw, IXGBE_TREG); regs_buff[1059] = IXGBE_READ_REG(hw, IXGBE_PCSS1); regs_buff[1060] = IXGBE_READ_REG(hw, IXGBE_PCSS2); regs_buff[1061] = IXGBE_READ_REG(hw, IXGBE_XPCSS); regs_buff[1062] = IXGBE_READ_REG(hw, IXGBE_SERDESC); regs_buff[1063] = IXGBE_READ_REG(hw, IXGBE_MACS); regs_buff[1064] = IXGBE_READ_REG(hw, IXGBE_AUTOC); regs_buff[1065] = IXGBE_READ_REG(hw, IXGBE_LINKS); regs_buff[1066] = IXGBE_READ_REG(hw, IXGBE_AUTOC2); regs_buff[1067] = IXGBE_READ_REG(hw, IXGBE_AUTOC3); regs_buff[1068] = IXGBE_READ_REG(hw, IXGBE_ANLP1); regs_buff[1069] = IXGBE_READ_REG(hw, IXGBE_ANLP2); regs_buff[1070] = IXGBE_READ_REG(hw, IXGBE_ATLASCTL); /* Diagnostic */ regs_buff[1071] = IXGBE_READ_REG(hw, IXGBE_RDSTATCTL); for (i = 0; i < 8; i++) regs_buff[1072 + i] = IXGBE_READ_REG(hw, IXGBE_RDSTAT(i)); regs_buff[1080] = IXGBE_READ_REG(hw, IXGBE_RDHMPN); for (i = 0; i < 4; i++) regs_buff[1081 + i] = IXGBE_READ_REG(hw, IXGBE_RIC_DW(i)); regs_buff[1085] = IXGBE_READ_REG(hw, IXGBE_RDPROBE); regs_buff[1086] = IXGBE_READ_REG(hw, IXGBE_TDSTATCTL); for (i = 0; i < 8; i++) regs_buff[1087 + i] = IXGBE_READ_REG(hw, IXGBE_TDSTAT(i)); regs_buff[1095] = IXGBE_READ_REG(hw, IXGBE_TDHMPN); for (i = 0; i < 4; i++) regs_buff[1096 + i] = IXGBE_READ_REG(hw, IXGBE_TIC_DW(i)); regs_buff[1100] = IXGBE_READ_REG(hw, IXGBE_TDPROBE); regs_buff[1101] = IXGBE_READ_REG(hw, IXGBE_TXBUFCTRL); regs_buff[1102] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA0); regs_buff[1103] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA1); regs_buff[1104] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA2); regs_buff[1105] = IXGBE_READ_REG(hw, IXGBE_TXBUFDATA3); regs_buff[1106] = IXGBE_READ_REG(hw, IXGBE_RXBUFCTRL); regs_buff[1107] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA0); regs_buff[1108] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA1); regs_buff[1109] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA2); regs_buff[1110] = IXGBE_READ_REG(hw, IXGBE_RXBUFDATA3); for (i = 0; i < 8; i++) regs_buff[1111 + i] = IXGBE_READ_REG(hw, IXGBE_PCIE_DIAG(i)); regs_buff[1119] = IXGBE_READ_REG(hw, IXGBE_RFVAL); regs_buff[1120] = IXGBE_READ_REG(hw, IXGBE_MDFTC1); regs_buff[1121] = IXGBE_READ_REG(hw, IXGBE_MDFTC2); regs_buff[1122] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO1); regs_buff[1123] = IXGBE_READ_REG(hw, IXGBE_MDFTFIFO2); regs_buff[1124] = IXGBE_READ_REG(hw, IXGBE_MDFTS); regs_buff[1125] = IXGBE_READ_REG(hw, IXGBE_PCIEECCCTL); regs_buff[1126] = IXGBE_READ_REG(hw, IXGBE_PBTXECC); regs_buff[1127] = IXGBE_READ_REG(hw, IXGBE_PBRXECC); /* 82599 X540 specific registers */ regs_buff[1128] = IXGBE_READ_REG(hw, IXGBE_MFLCN); } static int ixgbe_get_eeprom_len(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); return adapter->hw.eeprom.word_size * 2; } static int ixgbe_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u16 *eeprom_buff; int first_word, last_word, eeprom_len; int ret_val = 0; u16 i; if (eeprom->len == 0) return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_len = last_word - first_word + 1; eeprom_buff = kmalloc(sizeof(u16) * eeprom_len, GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; ret_val = ixgbe_read_eeprom_buffer(hw, first_word, eeprom_len, eeprom_buff); /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < eeprom_len; i++) le16_to_cpus(&eeprom_buff[i]); memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); kfree(eeprom_buff); return ret_val; } static int ixgbe_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u16 *eeprom_buff; void *ptr; int max_len, first_word, last_word, ret_val = 0; u16 i; if (eeprom->len == 0) return -EINVAL; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EINVAL; max_len = hw->eeprom.word_size * 2; first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; eeprom_buff = kmalloc(max_len, GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; ptr = eeprom_buff; if (eeprom->offset & 1) { /* * need read/modify/write of first changed EEPROM word * only the second byte of the word is being modified */ ret_val = ixgbe_read_eeprom(hw, first_word, &eeprom_buff[0]); if (ret_val) goto err; ptr++; } if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* * need read/modify/write of last changed EEPROM word * only the first byte of the word is being modified */ ret_val = ixgbe_read_eeprom(hw, last_word, &eeprom_buff[last_word - first_word]); if (ret_val) goto err; } /* Device's eeprom is always little-endian, word addressable */ for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) cpu_to_le16s(&eeprom_buff[i]); ret_val = ixgbe_write_eeprom_buffer(hw, first_word, last_word - first_word + 1, eeprom_buff); /* Update the checksum */ if (ret_val == 0) ixgbe_update_eeprom_checksum(hw); err: kfree(eeprom_buff); return ret_val; } static void ixgbe_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct ixgbe_adapter *adapter = netdev_priv(netdev); strlcpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, ixgbe_driver_version, sizeof(drvinfo->version)); strlcpy(drvinfo->fw_version, adapter->eeprom_id, sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); drvinfo->n_stats = IXGBE_STATS_LEN; drvinfo->testinfo_len = IXGBE_TEST_LEN; drvinfo->regdump_len = ixgbe_get_regs_len(netdev); } static void ixgbe_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); ring->rx_max_pending = IXGBE_MAX_RXD; ring->tx_max_pending = IXGBE_MAX_TXD; ring->rx_mini_max_pending = 0; ring->rx_jumbo_max_pending = 0; ring->rx_pending = adapter->rx_ring_count; ring->tx_pending = adapter->tx_ring_count; ring->rx_mini_pending = 0; ring->rx_jumbo_pending = 0; } static int ixgbe_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *tx_ring = NULL, *rx_ring = NULL; u32 new_rx_count, new_tx_count; int i, err = 0; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) return -EINVAL; new_tx_count = clamp_t(u32, ring->tx_pending, IXGBE_MIN_TXD, IXGBE_MAX_TXD); new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); new_rx_count = clamp_t(u32, ring->rx_pending, IXGBE_MIN_RXD, IXGBE_MAX_RXD); new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); /* if nothing to do return success */ if ((new_tx_count == adapter->tx_ring_count) && (new_rx_count == adapter->rx_ring_count)) return 0; while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) usleep_range(1000, 2000); if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) adapter->tx_ring[i]->count = new_tx_count; for (i = 0; i < adapter->num_rx_queues; i++) adapter->rx_ring[i]->count = new_rx_count; adapter->tx_ring_count = new_tx_count; adapter->rx_ring_count = new_rx_count; goto clear_reset; } /* alloc updated Tx resources */ if (new_tx_count != adapter->tx_ring_count) { tx_ring = vmalloc(adapter->num_tx_queues * sizeof(*tx_ring)); if (!tx_ring) { err = -ENOMEM; goto clear_reset; } for (i = 0; i < adapter->num_tx_queues; i++) { /* clone ring and setup updated count */ tx_ring[i] = *adapter->tx_ring[i]; tx_ring[i].count = new_tx_count; err = ixgbe_setup_tx_resources(&tx_ring[i]); if (err) { while (i) { i--; ixgbe_free_tx_resources(&tx_ring[i]); } vfree(tx_ring); tx_ring = NULL; goto clear_reset; } } } /* alloc updated Rx resources */ if (new_rx_count != adapter->rx_ring_count) { rx_ring = vmalloc(adapter->num_rx_queues * sizeof(*rx_ring)); if (!rx_ring) { err = -ENOMEM; goto clear_reset; } for (i = 0; i < adapter->num_rx_queues; i++) { /* clone ring and setup updated count */ rx_ring[i] = *adapter->rx_ring[i]; rx_ring[i].count = new_rx_count; err = ixgbe_setup_rx_resources(&rx_ring[i]); if (err) { while (i) { i--; ixgbe_free_rx_resources(&rx_ring[i]); } vfree(rx_ring); rx_ring = NULL; goto clear_reset; } } } /* bring interface down to prepare for update */ ixgbe_down(adapter); /* Tx */ if (tx_ring) { for (i = 0; i < adapter->num_tx_queues; i++) { ixgbe_free_tx_resources(adapter->tx_ring[i]); *adapter->tx_ring[i] = tx_ring[i]; } adapter->tx_ring_count = new_tx_count; vfree(tx_ring); tx_ring = NULL; } /* Rx */ if (rx_ring) { for (i = 0; i < adapter->num_rx_queues; i++) { ixgbe_free_rx_resources(adapter->rx_ring[i]); *adapter->rx_ring[i] = rx_ring[i]; } adapter->rx_ring_count = new_rx_count; vfree(rx_ring); rx_ring = NULL; } /* restore interface using new values */ ixgbe_up(adapter); clear_reset: /* free Tx resources if Rx error is encountered */ if (tx_ring) { for (i = 0; i < adapter->num_tx_queues; i++) ixgbe_free_tx_resources(&tx_ring[i]); vfree(tx_ring); } clear_bit(__IXGBE_RESETTING, &adapter->state); return err; } #ifndef HAVE_ETHTOOL_GET_SSET_COUNT static int ixgbe_get_stats_count(struct net_device *netdev) { return IXGBE_STATS_LEN; } #else /* HAVE_ETHTOOL_GET_SSET_COUNT */ static int ixgbe_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_TEST: return IXGBE_TEST_LEN; case ETH_SS_STATS: return IXGBE_STATS_LEN; default: return -EOPNOTSUPP; } } #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */ static void ixgbe_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); #ifdef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats *net_stats = &netdev->stats; #else struct net_device_stats *net_stats = &adapter->net_stats; #endif u64 *queue_stat; int stat_count = sizeof(struct ixgbe_queue_stats) / sizeof(u64); int i, j, k; char *p; printk(KERN_DEBUG "ixgbe_stats 0\n"); ixgbe_update_stats(adapter); printk(KERN_DEBUG "ixgbe_stats 1\n"); for (i = 0; i < IXGBE_NETDEV_STATS_LEN; i++) { p = (char *)net_stats + ixgbe_gstrings_net_stats[i].stat_offset; data[i] = (ixgbe_gstrings_net_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < IXGBE_GLOBAL_STATS_LEN; j++, i++) { p = (char *)adapter + ixgbe_gstrings_stats[j].stat_offset; data[i] = (ixgbe_gstrings_stats[j].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } printk(KERN_DEBUG "ixgbe_stats 2\n"); #ifdef NO_VNIC for (j = 0; j < adapter->num_tx_queues; j++) { queue_stat = (u64 *)&adapter->tx_ring[j]->stats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; i += k; } for (j = 0; j < adapter->num_rx_queues; j++) { queue_stat = (u64 *)&adapter->rx_ring[j]->stats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; i += k; } printk(KERN_DEBUG "ixgbe_stats 3\n"); #endif if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) { data[i++] = adapter->stats.pxontxc[j]; data[i++] = adapter->stats.pxofftxc[j]; } for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) { data[i++] = adapter->stats.pxonrxc[j]; data[i++] = adapter->stats.pxoffrxc[j]; } } printk(KERN_DEBUG "ixgbe_stats 4\n"); stat_count = sizeof(struct vf_stats) / sizeof(u64); for (j = 0; j < adapter->num_vfs; j++) { queue_stat = (u64 *)&adapter->vfinfo[j].vfstats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; queue_stat = (u64 *)&adapter->vfinfo[j].saved_rst_vfstats; for (k = 0; k < stat_count; k++) data[i + k] += queue_stat[k]; i += k; } } static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); char *p = (char *)data; int i; switch (stringset) { case ETH_SS_TEST: memcpy(data, *ixgbe_gstrings_test, IXGBE_TEST_LEN * ETH_GSTRING_LEN); break; case ETH_SS_STATS: for (i = 0; i < IXGBE_NETDEV_STATS_LEN; i++) { memcpy(p, ixgbe_gstrings_net_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { memcpy(p, ixgbe_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } for (i = 0; i < adapter->num_tx_queues; i++) { sprintf(p, "tx_queue_%u_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "tx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; } for (i = 0; i < adapter->num_rx_queues; i++) { sprintf(p, "rx_queue_%u_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; } if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { sprintf(p, "tx_pb_%u_pxon", i); p += ETH_GSTRING_LEN; sprintf(p, "tx_pb_%u_pxoff", i); p += ETH_GSTRING_LEN; } for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) { sprintf(p, "rx_pb_%u_pxon", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_pb_%u_pxoff", i); p += ETH_GSTRING_LEN; } } for (i = 0; i < adapter->num_vfs; i++) { sprintf(p, "VF %d Rx Packets", i); p += ETH_GSTRING_LEN; sprintf(p, "VF %d Rx Bytes", i); p += ETH_GSTRING_LEN; sprintf(p, "VF %d Tx Packets", i); p += ETH_GSTRING_LEN; sprintf(p, "VF %d Tx Bytes", i); p += ETH_GSTRING_LEN; sprintf(p, "VF %d MC Packets", i); p += ETH_GSTRING_LEN; } /* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */ break; } } static int ixgbe_link_test(struct ixgbe_adapter *adapter, u64 *data) { struct ixgbe_hw *hw = &adapter->hw; bool link_up; u32 link_speed = 0; *data = 0; hw->mac.ops.check_link(hw, &link_speed, &link_up, true); if (link_up) return *data; else *data = 1; return *data; } /* ethtool register test data */ struct ixgbe_reg_test { u16 reg; u8 array_len; u8 test_type; u32 mask; u32 write; }; /* In the hardware, registers are laid out either singly, in arrays * spaced 0x40 bytes apart, or in contiguous tables. We assume * most tests take place on arrays or single registers (handled * as a single-element array) and special-case the tables. * Table tests are always pattern tests. * * We also make provision for some required setup steps by specifying * registers to be written without any read-back testing. */ #define PATTERN_TEST 1 #define SET_READ_TEST 2 #define WRITE_NO_TEST 3 #define TABLE32_TEST 4 #define TABLE64_TEST_LO 5 #define TABLE64_TEST_HI 6 /* default 82599 register test */ static struct ixgbe_reg_test reg_test_82599[] = { { IXGBE_FCRTL_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_FCRTH_82599(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000001, 0x00000001 }, { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x8001FFFF, 0x800CFFFF }, { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; /* default 82598 register test */ static struct ixgbe_reg_test reg_test_82598[] = { { IXGBE_FCRTL(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_PFCTOP, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_VLNCTRL, 1, PATTERN_TEST, 0x00000000, 0x00000000 }, { IXGBE_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { IXGBE_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, /* Enable all four RX queues before testing. */ { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, /* RDH is read-only for 82598, only test RDT. */ { IXGBE_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, { IXGBE_RXDCTL(0), 4, WRITE_NO_TEST, 0, 0 }, { IXGBE_FCRTH(0), 1, PATTERN_TEST, 0x8007FFF0, 0x8007FFF0 }, { IXGBE_FCTTV(0), 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_TIPG, 1, PATTERN_TEST, 0x000000FF, 0x000000FF }, { IXGBE_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, { IXGBE_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, { IXGBE_RXCTRL, 1, SET_READ_TEST, 0x00000003, 0x00000003 }, { IXGBE_DTXCTL, 1, SET_READ_TEST, 0x00000005, 0x00000005 }, { IXGBE_RAL(0), 16, TABLE64_TEST_LO, 0xFFFFFFFF, 0xFFFFFFFF }, { IXGBE_RAL(0), 16, TABLE64_TEST_HI, 0x800CFFFF, 0x800CFFFF }, { IXGBE_MTA(0), 128, TABLE32_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, { 0, 0, 0, 0 } }; #define REG_PATTERN_TEST(R, M, W) \ { \ u32 pat, val, before; \ const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { \ before = readl(adapter->hw.hw_addr + R); \ writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ val = readl(adapter->hw.hw_addr + R); \ if (val != (_test[pat] & W & M)) { \ e_err(drv, "pattern test reg %04X failed: got " \ "0x%08X expected 0x%08X\n", \ R, val, (_test[pat] & W & M)); \ *data = R; \ writel(before, adapter->hw.hw_addr + R); \ return 1; \ } \ writel(before, adapter->hw.hw_addr + R); \ } \ } #define REG_SET_AND_CHECK(R, M, W) \ { \ u32 val, before; \ before = readl(adapter->hw.hw_addr + R); \ writel((W & M), (adapter->hw.hw_addr + R)); \ val = readl(adapter->hw.hw_addr + R); \ if ((W & M) != (val & M)) { \ e_err(drv, "set/check reg %04X test failed: got 0x%08X " \ "expected 0x%08X\n", R, (val & M), (W & M)); \ *data = R; \ writel(before, (adapter->hw.hw_addr + R)); \ return 1; \ } \ writel(before, (adapter->hw.hw_addr + R)); \ } static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data) { struct ixgbe_reg_test *test; u32 value, status_before, status_after; u32 i, toggle; switch (adapter->hw.mac.type) { case ixgbe_mac_82598EB: toggle = 0x7FFFF3FF; test = reg_test_82598; break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: toggle = 0x7FFFF30F; test = reg_test_82599; break; default: *data = 1; return 1; break; } /* * Because the status register is such a special case, * we handle it separately from the rest of the register * tests. Some bits are read-only, some toggle, and some * are writeable on newer MACs. */ status_before = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS); value = (IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle); IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, toggle); status_after = IXGBE_READ_REG(&adapter->hw, IXGBE_STATUS) & toggle; if (value != status_after) { e_err(drv, "failed STATUS register test got: " "0x%08X expected: 0x%08X\n", status_after, value); *data = 1; return 1; } /* restore previous status */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_STATUS, status_before); /* * Perform the remainder of the register test, looping through * the test table until we either fail or reach the null entry. */ while (test->reg) { for (i = 0; i < test->array_len; i++) { switch (test->test_type) { case PATTERN_TEST: REG_PATTERN_TEST(test->reg + (i * 0x40), test->mask, test->write); break; case SET_READ_TEST: REG_SET_AND_CHECK(test->reg + (i * 0x40), test->mask, test->write); break; case WRITE_NO_TEST: writel(test->write, (adapter->hw.hw_addr + test->reg) + (i * 0x40)); break; case TABLE32_TEST: REG_PATTERN_TEST(test->reg + (i * 4), test->mask, test->write); break; case TABLE64_TEST_LO: REG_PATTERN_TEST(test->reg + (i * 8), test->mask, test->write); break; case TABLE64_TEST_HI: REG_PATTERN_TEST((test->reg + 4) + (i * 8), test->mask, test->write); break; } } test++; } *data = 0; return 0; } static int ixgbe_eeprom_test(struct ixgbe_adapter *adapter, u64 *data) { if (ixgbe_validate_eeprom_checksum(&adapter->hw, NULL)) *data = 1; else *data = 0; return *data; } static irqreturn_t ixgbe_test_intr(int irq, void *data) { struct net_device *netdev = (struct net_device *) data; struct ixgbe_adapter *adapter = netdev_priv(netdev); adapter->test_icr |= IXGBE_READ_REG(&adapter->hw, IXGBE_EICR); return IRQ_HANDLED; } static int ixgbe_intr_test(struct ixgbe_adapter *adapter, u64 *data) { struct net_device *netdev = adapter->netdev; u32 mask, i = 0, shared_int = true; u32 irq = adapter->pdev->irq; *data = 0; /* Hook up test interrupt handler just for this test */ if (adapter->msix_entries) { /* NOTE: we don't test MSI-X interrupts here, yet */ return 0; } else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { shared_int = false; if (request_irq(irq, &ixgbe_test_intr, 0, netdev->name, netdev)) { *data = 1; return -1; } } else if (!request_irq(irq, &ixgbe_test_intr, IRQF_PROBE_SHARED, netdev->name, netdev)) { shared_int = false; } else if (request_irq(irq, &ixgbe_test_intr, IRQF_SHARED, netdev->name, netdev)) { *data = 1; return -1; } e_info(hw, "testing %s interrupt\n", (shared_int ? "shared" : "unshared")); /* Disable all the interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); IXGBE_WRITE_FLUSH(&adapter->hw); usleep_range(10000, 20000); /* Test each interrupt */ for (; i < 10; i++) { /* Interrupt to test */ mask = 1 << i; if (!shared_int) { /* * Disable the interrupts to be reported in * the cause register and then force the same * interrupt and see if one gets posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~mask & 0x00007FFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, ~mask & 0x00007FFF); IXGBE_WRITE_FLUSH(&adapter->hw); usleep_range(10000, 20000); if (adapter->test_icr & mask) { *data = 3; break; } } /* * Enable the interrupt to be reported in the cause * register and then force the same interrupt and see * if one gets posted. If an interrupt was not posted * to the bus, the test failed. */ adapter->test_icr = 0; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, mask); IXGBE_WRITE_FLUSH(&adapter->hw); usleep_range(10000, 20000); if (!(adapter->test_icr & mask)) { *data = 4; break; } if (!shared_int) { /* * Disable the other interrupts to be reported in * the cause register and then force the other * interrupts and see if any get posted. If * an interrupt was posted to the bus, the * test failed. */ adapter->test_icr = 0; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~mask & 0x00007FFF); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, ~mask & 0x00007FFF); IXGBE_WRITE_FLUSH(&adapter->hw); usleep_range(10000, 20000); if (adapter->test_icr) { *data = 5; break; } } } /* Disable all the interrupts */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFFFFFF); IXGBE_WRITE_FLUSH(&adapter->hw); usleep_range(10000, 20000); /* Unhook test interrupt handler */ free_irq(irq, netdev); return *data; } static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 reg_data; /* X540 needs to set the MACC.FLU bit to force link up */ if (adapter->hw.mac.type == ixgbe_mac_X540) { reg_data = IXGBE_READ_REG(hw, IXGBE_MACC); reg_data |= IXGBE_MACC_FLU; IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data); } /* right now we only support MAC loopback in the driver */ reg_data = IXGBE_READ_REG(hw, IXGBE_HLREG0); /* Setup MAC loopback */ reg_data |= IXGBE_HLREG0_LPBK; IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_data); reg_data = IXGBE_READ_REG(hw, IXGBE_FCTRL); reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_data); reg_data = IXGBE_READ_REG(hw, IXGBE_AUTOC); reg_data &= ~IXGBE_AUTOC_LMS_MASK; reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_data); IXGBE_WRITE_FLUSH(hw); usleep_range(10000, 20000); /* Disable Atlas Tx lanes; re-enabled in reset path */ if (hw->mac.type == ixgbe_mac_82598EB) { u8 atlas; ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &atlas); atlas |= IXGBE_ATLAS_PDN_TX_REG_EN; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, atlas); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &atlas); atlas |= IXGBE_ATLAS_PDN_TX_10G_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, atlas); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &atlas); atlas |= IXGBE_ATLAS_PDN_TX_1G_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, atlas); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &atlas); atlas |= IXGBE_ATLAS_PDN_TX_AN_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, atlas); } return 0; } static void ixgbe_loopback_cleanup(struct ixgbe_adapter *adapter) { u32 reg_data; reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); reg_data &= ~IXGBE_HLREG0_LPBK; IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); } static int ixgbe_loopback_test(struct ixgbe_adapter *adapter, u64 *data) { //*data = ixgbe_setup_desc_rings(adapter); //if (*data) // goto out; *data = ixgbe_setup_loopback_test(adapter); if (*data) goto err_loopback; //*data = ixgbe_run_loopback_test(adapter); ixgbe_loopback_cleanup(adapter); err_loopback: //ixgbe_free_desc_rings(adapter); //out: return *data; } #ifndef HAVE_ETHTOOL_GET_SSET_COUNT static int ixgbe_diag_test_count(struct net_device *netdev) { return IXGBE_TEST_LEN; } #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */ static void ixgbe_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); bool if_running = netif_running(netdev); set_bit(__IXGBE_TESTING, &adapter->state); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ e_info(hw, "offline testing starting\n"); /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ if (ixgbe_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { int i; for (i = 0; i < adapter->num_vfs; i++) { if (adapter->vfinfo[i].clear_to_send) { e_warn(drv, "Please take active VFS " "offline and restart the " "adapter before running NIC " "diagnostics\n"); data[0] = 1; data[1] = 1; data[2] = 1; data[3] = 1; eth_test->flags |= ETH_TEST_FL_FAILED; clear_bit(__IXGBE_TESTING, &adapter->state); goto skip_ol_tests; } } } if (if_running) /* indicate we're in test mode */ dev_close(netdev); else ixgbe_reset(adapter); e_info(hw, "register testing starting\n"); if (ixgbe_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; ixgbe_reset(adapter); e_info(hw, "eeprom testing starting\n"); if (ixgbe_eeprom_test(adapter, &data[1])) eth_test->flags |= ETH_TEST_FL_FAILED; ixgbe_reset(adapter); e_info(hw, "interrupt testing starting\n"); if (ixgbe_intr_test(adapter, &data[2])) eth_test->flags |= ETH_TEST_FL_FAILED; /* If SRIOV or VMDq is enabled then skip MAC * loopback diagnostic. */ if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { e_info(hw, "skip MAC loopback diagnostic in VT mode\n"); data[3] = 0; goto skip_loopback; } ixgbe_reset(adapter); e_info(hw, "loopback testing starting\n"); if (ixgbe_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; skip_loopback: ixgbe_reset(adapter); clear_bit(__IXGBE_TESTING, &adapter->state); if (if_running) dev_open(netdev); } else { e_info(hw, "online testing starting\n"); /* Online tests */ if (ixgbe_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; /* Online tests aren't run; pass by default */ data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; clear_bit(__IXGBE_TESTING, &adapter->state); } skip_ol_tests: msleep_interruptible(4 * 1000); } static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, struct ethtool_wolinfo *wol) { struct ixgbe_hw *hw = &adapter->hw; int retval = 1; u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK; /* WOL not supported except for the following */ switch (hw->device_id) { case IXGBE_DEV_ID_82599_SFP: /* Only these subdevice could supports WOL */ switch (hw->subsystem_device_id) { case IXGBE_SUBDEV_ID_82599_560FLR: /* only support first port */ if (hw->bus.func != 0) { wol->supported = 0; break; } case IXGBE_SUBDEV_ID_82599_SFP: retval = 0; break; default: wol->supported = 0; break; } break; case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: /* All except this subdevice support WOL */ if (hw->subsystem_device_id == IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) { wol->supported = 0; break; } retval = 0; break; case IXGBE_DEV_ID_82599_KX4: retval = 0; break; case IXGBE_DEV_ID_X540T: /* check eeprom to see if enabled wol */ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && (hw->bus.func == 0))) { retval = 0; break; } /* All others not supported */ wol->supported = 0; break; default: wol->supported = 0; } return retval; } static void ixgbe_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct ixgbe_adapter *adapter = netdev_priv(netdev); wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; wol->wolopts = 0; if (ixgbe_wol_exclusion(adapter, wol) || !device_can_wakeup(&adapter->pdev->dev)) return; if (adapter->wol & IXGBE_WUFC_EX) wol->wolopts |= WAKE_UCAST; if (adapter->wol & IXGBE_WUFC_MC) wol->wolopts |= WAKE_MCAST; if (adapter->wol & IXGBE_WUFC_BC) wol->wolopts |= WAKE_BCAST; if (adapter->wol & IXGBE_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; } static int ixgbe_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct ixgbe_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; if (ixgbe_wol_exclusion(adapter, wol)) return wol->wolopts ? -EOPNOTSUPP : 0; adapter->wol = 0; if (wol->wolopts & WAKE_UCAST) adapter->wol |= IXGBE_WUFC_EX; if (wol->wolopts & WAKE_MCAST) adapter->wol |= IXGBE_WUFC_MC; if (wol->wolopts & WAKE_BCAST) adapter->wol |= IXGBE_WUFC_BC; if (wol->wolopts & WAKE_MAGIC) adapter->wol |= IXGBE_WUFC_MAG; device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); return 0; } static int ixgbe_nway_reset(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); if (netif_running(netdev)) ixgbe_reinit_locked(adapter); return 0; } #ifdef HAVE_ETHTOOL_SET_PHYS_ID static int ixgbe_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; switch (state) { case ETHTOOL_ID_ACTIVE: adapter->led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); return 2; case ETHTOOL_ID_ON: hw->mac.ops.led_on(hw, IXGBE_LED_ON); break; case ETHTOOL_ID_OFF: hw->mac.ops.led_off(hw, IXGBE_LED_ON); break; case ETHTOOL_ID_INACTIVE: /* Restore LED settings */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_LEDCTL, adapter->led_reg); break; } return 0; } #else static int ixgbe_phys_id(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); u32 i; if (!data || data > 300) data = 300; for (i = 0; i < (data * 1000); i += 400) { ixgbe_led_on(hw, IXGBE_LED_ON); msleep_interruptible(200); ixgbe_led_off(hw, IXGBE_LED_ON); msleep_interruptible(200); } /* Restore LED settings */ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg); return 0; } #endif /* HAVE_ETHTOOL_SET_PHYS_ID */ static int ixgbe_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { struct ixgbe_adapter *adapter = netdev_priv(netdev); ec->tx_max_coalesced_frames_irq = adapter->tx_work_limit; #ifndef CONFIG_IXGBE_NAPI ec->rx_max_coalesced_frames_irq = adapter->rx_work_limit; #endif /* CONFIG_IXGBE_NAPI */ /* only valid if in constant ITR mode */ if (adapter->rx_itr_setting <= 1) ec->rx_coalesce_usecs = adapter->rx_itr_setting; else ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; /* if in mixed tx/rx queues per vector mode, report only rx settings */ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) return 0; /* only valid if in constant ITR mode */ if (adapter->tx_itr_setting <= 1) ec->tx_coalesce_usecs = adapter->tx_itr_setting; else ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; return 0; } /* * this function must be called before setting the new value of * rx_itr_setting */ #ifdef NO_VNIC static bool ixgbe_update_rsc(struct ixgbe_adapter *adapter) { struct net_device *netdev = adapter->netdev; /* nothing to do if LRO or RSC are not enabled */ if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) || !(netdev->features & NETIF_F_LRO)) return false; /* check the feature flag value and enable RSC if necessary */ if (adapter->rx_itr_setting == 1 || adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR) { if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) { adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; e_info(probe, "rx-usecs value high enough " "to re-enable RSC\n"); return true; } /* if interrupt rate is too high then disable RSC */ } else if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; #ifdef IXGBE_NO_LRO e_info(probe, "rx-usecs set too low, disabling RSC\n"); #else e_info(probe, "rx-usecs set too low, " "falling back to software LRO\n"); #endif return true; } return false; } #endif static int ixgbe_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { #ifdef NO_VNIC struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_q_vector *q_vector; int i; int num_vectors; u16 tx_itr_param, rx_itr_param; bool need_reset = false; /* don't accept tx specific changes if we've got mixed RxTx vectors */ if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count && ec->tx_coalesce_usecs) return -EINVAL; if (ec->tx_max_coalesced_frames_irq) adapter->tx_work_limit = ec->tx_max_coalesced_frames_irq; #ifndef CONFIG_IXGBE_NAPI if (ec->rx_max_coalesced_frames_irq) adapter->rx_work_limit = ec->rx_max_coalesced_frames_irq; #endif if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) || (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2))) return -EINVAL; if (ec->rx_coalesce_usecs > 1) adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; else adapter->rx_itr_setting = ec->rx_coalesce_usecs; if (adapter->rx_itr_setting == 1) rx_itr_param = IXGBE_20K_ITR; else rx_itr_param = adapter->rx_itr_setting; if (ec->tx_coalesce_usecs > 1) adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; else adapter->tx_itr_setting = ec->tx_coalesce_usecs; if (adapter->tx_itr_setting == 1) tx_itr_param = IXGBE_10K_ITR; else tx_itr_param = adapter->tx_itr_setting; /* check the old value and enable RSC if necessary */ need_reset = ixgbe_update_rsc(adapter); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; else num_vectors = 1; for (i = 0; i < num_vectors; i++) { q_vector = adapter->q_vector[i]; q_vector->tx.work_limit = adapter->tx_work_limit; q_vector->rx.work_limit = adapter->rx_work_limit; if (q_vector->tx.count && !q_vector->rx.count) /* tx only */ q_vector->itr = tx_itr_param; else /* rx only or mixed */ q_vector->itr = rx_itr_param; ixgbe_write_eitr(q_vector); } /* * do reset here at the end to make sure EITR==0 case is handled * correctly w.r.t stopping tx, and changing TXDCTL.WTHRESH settings * also locks in RSC enable/disable which requires reset */ if (need_reset) ixgbe_do_reset(netdev); #endif return 0; } #ifndef HAVE_NDO_SET_FEATURES static u32 ixgbe_get_rx_csum(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *ring = adapter->rx_ring[0]; return test_bit(__IXGBE_RX_CSUM_ENABLED, &ring->state); } static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); int i; for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *ring = adapter->rx_ring[i]; if (data) set_bit(__IXGBE_RX_CSUM_ENABLED, &ring->state); else clear_bit(__IXGBE_RX_CSUM_ENABLED, &ring->state); } /* LRO and RSC both depend on RX checksum to function */ if (!data && (netdev->features & NETIF_F_LRO)) { netdev->features &= ~NETIF_F_LRO; if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; ixgbe_do_reset(netdev); } } return 0; } static u32 ixgbe_get_tx_csum(struct net_device *netdev) { return (netdev->features & NETIF_F_IP_CSUM) != 0; } static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); u32 feature_list; #ifdef NETIF_F_IPV6_CSUM feature_list = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; #else feature_list = NETIF_F_IP_CSUM; #endif switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: feature_list |= NETIF_F_SCTP_CSUM; break; default: break; } if (data) netdev->features |= feature_list; else netdev->features &= ~feature_list; return 0; } #ifdef NETIF_F_TSO static int ixgbe_set_tso(struct net_device *netdev, u32 data) { if (data) { netdev->features |= NETIF_F_TSO; #ifdef NETIF_F_TSO6 netdev->features |= NETIF_F_TSO6; #endif } else { #ifndef HAVE_NETDEV_VLAN_FEATURES #ifdef NETIF_F_HW_VLAN_TX struct ixgbe_adapter *adapter = netdev_priv(netdev); /* disable TSO on all VLANs if they're present */ if (adapter->vlgrp) { int i; struct net_device *v_netdev; for (i = 0; i < VLAN_N_VID; i++) { v_netdev = vlan_group_get_device(adapter->vlgrp, i); if (v_netdev) { v_netdev->features &= ~NETIF_F_TSO; #ifdef NETIF_F_TSO6 v_netdev->features &= ~NETIF_F_TSO6; #endif vlan_group_set_device(adapter->vlgrp, i, v_netdev); } } } #endif #endif /* HAVE_NETDEV_VLAN_FEATURES */ netdev->features &= ~NETIF_F_TSO; #ifdef NETIF_F_TSO6 netdev->features &= ~NETIF_F_TSO6; #endif } return 0; } #endif /* NETIF_F_TSO */ #ifdef ETHTOOL_GFLAGS static int ixgbe_set_flags(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); u32 supported_flags = ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN; u32 changed = netdev->features ^ data; bool need_reset = false; int rc; #ifndef HAVE_VLAN_RX_REGISTER if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) && !(data & ETH_FLAG_RXVLAN)) return -EINVAL; #endif #ifdef NETIF_F_RXHASH if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) supported_flags |= ETH_FLAG_RXHASH; #endif #ifdef IXGBE_NO_LRO if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) #endif supported_flags |= ETH_FLAG_LRO; #ifdef ETHTOOL_GRXRINGS switch (adapter->hw.mac.type) { case ixgbe_mac_X540: case ixgbe_mac_82599EB: supported_flags |= ETH_FLAG_NTUPLE; default: break; } #endif rc = ethtool_op_set_flags(netdev, data, supported_flags); if (rc) return rc; #ifndef HAVE_VLAN_RX_REGISTER if (changed & ETH_FLAG_RXVLAN) ixgbe_vlan_mode(netdev, netdev->features); #endif /* if state changes we need to update adapter->flags and reset */ if (!(netdev->features & NETIF_F_LRO)) { if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) need_reset = true; adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; } else if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) && !(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) { if (adapter->rx_itr_setting == 1 || adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR) { adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; need_reset = true; } else if (changed & ETH_FLAG_LRO) { #ifdef IXGBE_NO_LRO e_info(probe, "rx-usecs set too low, " "disabling RSC\n"); #else e_info(probe, "rx-usecs set too low, " "falling back to software LRO\n"); #endif } } #ifdef ETHTOOL_GRXRINGS /* * Check if Flow Director n-tuple support was enabled or disabled. If * the state changed, we need to reset. */ if (!(netdev->features & NETIF_F_NTUPLE)) { if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) { /* turn off Flow Director, set ATR and reset */ if ((adapter->flags & IXGBE_FLAG_RSS_ENABLED) && !(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; need_reset = true; } adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; } else if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) { /* turn off ATR, enable perfect filters and reset */ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; need_reset = true; } #endif /* ETHTOOL_GRXRINGS */ if (need_reset) ixgbe_do_reset(netdev); return 0; } #endif /* ETHTOOL_GFLAGS */ #endif /* HAVE_NDO_SET_FEATURES */ #ifdef ETHTOOL_GRXRINGS static int ixgbe_get_ethtool_fdir_entry(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd) { union ixgbe_atr_input *mask = &adapter->fdir_mask; struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; struct hlist_node *node, *node2; struct ixgbe_fdir_filter *rule = NULL; /* report total rule count */ cmd->data = (1024 << adapter->fdir_pballoc) - 2; hlist_for_each_entry_safe(rule, node, node2, &adapter->fdir_filter_list, fdir_node) { if (fsp->location <= rule->sw_idx) break; } if (!rule || fsp->location != rule->sw_idx) return -EINVAL; /* fill out the flow spec entry */ /* set flow type field */ switch (rule->filter.formatted.flow_type) { case IXGBE_ATR_FLOW_TYPE_TCPV4: fsp->flow_type = TCP_V4_FLOW; break; case IXGBE_ATR_FLOW_TYPE_UDPV4: fsp->flow_type = UDP_V4_FLOW; break; case IXGBE_ATR_FLOW_TYPE_SCTPV4: fsp->flow_type = SCTP_V4_FLOW; break; case IXGBE_ATR_FLOW_TYPE_IPV4: fsp->flow_type = IP_USER_FLOW; fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4; fsp->h_u.usr_ip4_spec.proto = 0; fsp->m_u.usr_ip4_spec.proto = 0; break; default: return -EINVAL; } fsp->h_u.tcp_ip4_spec.psrc = rule->filter.formatted.src_port; fsp->m_u.tcp_ip4_spec.psrc = mask->formatted.src_port; fsp->h_u.tcp_ip4_spec.pdst = rule->filter.formatted.dst_port; fsp->m_u.tcp_ip4_spec.pdst = mask->formatted.dst_port; fsp->h_u.tcp_ip4_spec.ip4src = rule->filter.formatted.src_ip[0]; fsp->m_u.tcp_ip4_spec.ip4src = mask->formatted.src_ip[0]; fsp->h_u.tcp_ip4_spec.ip4dst = rule->filter.formatted.dst_ip[0]; fsp->m_u.tcp_ip4_spec.ip4dst = mask->formatted.dst_ip[0]; fsp->h_ext.vlan_tci = rule->filter.formatted.vlan_id; fsp->m_ext.vlan_tci = mask->formatted.vlan_id; fsp->h_ext.vlan_etype = rule->filter.formatted.flex_bytes; fsp->m_ext.vlan_etype = mask->formatted.flex_bytes; fsp->h_ext.data[1] = htonl(rule->filter.formatted.vm_pool); fsp->m_ext.data[1] = htonl(mask->formatted.vm_pool); fsp->flow_type |= FLOW_EXT; /* record action */ if (rule->action == IXGBE_FDIR_DROP_QUEUE) fsp->ring_cookie = RX_CLS_FLOW_DISC; else fsp->ring_cookie = rule->action; return 0; } static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd, u32 *rule_locs) { struct hlist_node *node, *node2; struct ixgbe_fdir_filter *rule; int cnt = 0; /* report total rule count */ cmd->data = (1024 << adapter->fdir_pballoc) - 2; hlist_for_each_entry_safe(rule, node, node2, &adapter->fdir_filter_list, fdir_node) { if (cnt == cmd->rule_cnt) return -EMSGSIZE; rule_locs[cnt] = rule->sw_idx; cnt++; } cmd->rule_cnt = cnt; return 0; } static int ixgbe_get_rss_hash_opts(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd) { cmd->data = 0; /* if RSS is disabled then report no hashing */ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) return 0; /* Report default options for RSS on ixgbe */ switch (cmd->flow_type) { case TCP_V4_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case UDP_V4_FLOW: if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: case IPV4_FLOW: cmd->data |= RXH_IP_SRC | RXH_IP_DST; break; case TCP_V6_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case UDP_V6_FLOW: if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: case IPV6_FLOW: cmd->data |= RXH_IP_SRC | RXH_IP_DST; break; default: return -EINVAL; } return 0; } static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, #ifdef HAVE_ETHTOOL_GET_RXNFC_VOID_RULE_LOCS void *rule_locs) #else u32 *rule_locs) #endif { struct ixgbe_adapter *adapter = netdev_priv(dev); int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_GRXRINGS: cmd->data = adapter->num_rx_queues; ret = 0; break; case ETHTOOL_GRXCLSRLCNT: cmd->rule_cnt = adapter->fdir_filter_count; ret = 0; break; case ETHTOOL_GRXCLSRULE: ret = ixgbe_get_ethtool_fdir_entry(adapter, cmd); break; case ETHTOOL_GRXCLSRLALL: ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, (u32 *)rule_locs); break; case ETHTOOL_GRXFH: ret = ixgbe_get_rss_hash_opts(adapter, cmd); break; default: break; } return ret; } static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter, struct ixgbe_fdir_filter *input, u16 sw_idx) { struct ixgbe_hw *hw = &adapter->hw; struct hlist_node *node, *node2, *parent; struct ixgbe_fdir_filter *rule; int err = -EINVAL; parent = NULL; rule = NULL; hlist_for_each_entry_safe(rule, node, node2, &adapter->fdir_filter_list, fdir_node) { /* hash found, or no matching entry */ if (rule->sw_idx >= sw_idx) break; parent = node; } /* if there is an old rule occupying our place remove it */ if (rule && (rule->sw_idx == sw_idx)) { if (!input || (rule->filter.formatted.bkt_hash != input->filter.formatted.bkt_hash)) { err = ixgbe_fdir_erase_perfect_filter_82599(hw, &rule->filter, sw_idx); } hlist_del(&rule->fdir_node); kfree(rule); adapter->fdir_filter_count--; } /* * If no input this was a delete, err should be 0 if a rule was * successfully found and removed from the list else -EINVAL */ if (!input) return err; /* initialize node and set software index */ INIT_HLIST_NODE(&input->fdir_node); /* add filter to the list */ if (parent) hlist_add_after(parent, &input->fdir_node); else hlist_add_head(&input->fdir_node, &adapter->fdir_filter_list); /* update counts */ adapter->fdir_filter_count++; return 0; } static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp, u8 *flow_type) { switch (fsp->flow_type & ~FLOW_EXT) { case TCP_V4_FLOW: *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; break; case UDP_V4_FLOW: *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; break; case SCTP_V4_FLOW: *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; break; case IP_USER_FLOW: switch (fsp->h_u.usr_ip4_spec.proto) { case IPPROTO_TCP: *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; break; case IPPROTO_UDP: *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; break; case IPPROTO_SCTP: *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; break; case 0: if (!fsp->m_u.usr_ip4_spec.proto) { *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4; break; } default: return 0; } break; default: return 0; } return 1; } static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd) { struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_fdir_filter *input; union ixgbe_atr_input mask; int err; if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) return -EOPNOTSUPP; /* * Don't allow programming if the action is a queue greater than * the number of online Rx queues. */ if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) && (fsp->ring_cookie >= adapter->num_rx_queues)) return -EINVAL; /* Don't allow indexes to exist outside of available space */ if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) { e_err(drv, "Location out of range\n"); return -EINVAL; } input = kzalloc(sizeof(*input), GFP_ATOMIC); if (!input) return -ENOMEM; memset(&mask, 0, sizeof(union ixgbe_atr_input)); /* set SW index */ input->sw_idx = fsp->location; /* record flow type */ if (!ixgbe_flowspec_to_flow_type(fsp, &input->filter.formatted.flow_type)) { e_err(drv, "Unrecognized flow type\n"); goto err_out; } mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK | IXGBE_ATR_L4TYPE_MASK; if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4) mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK; /* Copy input into formatted structures */ input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src; mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src; input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst; mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst; input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc; mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc; input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst; mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst; if (fsp->flow_type & FLOW_EXT) { input->filter.formatted.vm_pool = (unsigned char)ntohl(fsp->h_ext.data[1]); mask.formatted.vm_pool = (unsigned char)ntohl(fsp->m_ext.data[1]); input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci; mask.formatted.vlan_id = fsp->m_ext.vlan_tci; input->filter.formatted.flex_bytes = fsp->h_ext.vlan_etype; mask.formatted.flex_bytes = fsp->m_ext.vlan_etype; } /* determine if we need to drop or route the packet */ if (fsp->ring_cookie == RX_CLS_FLOW_DISC) input->action = IXGBE_FDIR_DROP_QUEUE; else input->action = fsp->ring_cookie; spin_lock(&adapter->fdir_perfect_lock); if (hlist_empty(&adapter->fdir_filter_list)) { /* save mask and program input mask into HW */ memcpy(&adapter->fdir_mask, &mask, sizeof(mask)); err = ixgbe_fdir_set_input_mask_82599(hw, &mask); if (err) { e_err(drv, "Error writing mask\n"); goto err_out_w_lock; } } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) { e_err(drv, "Only one mask supported per port\n"); goto err_out_w_lock; } /* apply mask and compute/store hash */ ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask); /* program filters to filter memory */ err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter, input->sw_idx, (input->action == IXGBE_FDIR_DROP_QUEUE) ? IXGBE_FDIR_DROP_QUEUE : adapter->rx_ring[input->action]->reg_idx); if (err) goto err_out_w_lock; ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); spin_unlock(&adapter->fdir_perfect_lock); kfree(input); return err; err_out_w_lock: spin_unlock(&adapter->fdir_perfect_lock); err_out: kfree(input); return -EINVAL; } static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *cmd) { struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; int err; spin_lock(&adapter->fdir_perfect_lock); err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, (u16)(fsp->location)); spin_unlock(&adapter->fdir_perfect_lock); return err; } #ifdef ETHTOOL_SRXNTUPLE /* * We need to keep this around for kernels 2.6.33 - 2.6.39 in order to avoid * a null pointer dereference as it was assumend if the NETIF_F_NTUPLE flag * was defined that this function was present. */ static int ixgbe_set_rx_ntuple(struct net_device *dev, struct ethtool_rx_ntuple *cmd) { return -EOPNOTSUPP; } #endif #define UDP_RSS_FLAGS (IXGBE_FLAG2_RSS_FIELD_IPV4_UDP | \ IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) static int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter, struct ethtool_rxnfc *nfc) { u32 flags2 = adapter->flags2; /* * RSS does not support anything other than hashing * to queues on src and dst IPs and ports */ if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)) return -EINVAL; switch (nfc->flow_type) { case TCP_V4_FLOW: case TCP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || !(nfc->data & RXH_L4_B_0_1) || !(nfc->data & RXH_L4_B_2_3)) return -EINVAL; break; case UDP_V4_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) return -EINVAL; switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV4_UDP; break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV4_UDP; break; default: return -EINVAL; } break; case UDP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST)) return -EINVAL; switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV6_UDP; break; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV6_UDP; break; default: return -EINVAL; } break; case AH_ESP_V4_FLOW: case AH_V4_FLOW: case ESP_V4_FLOW: case SCTP_V4_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: case ESP_V6_FLOW: case SCTP_V6_FLOW: if (!(nfc->data & RXH_IP_SRC) || !(nfc->data & RXH_IP_DST) || (nfc->data & RXH_L4_B_0_1) || (nfc->data & RXH_L4_B_2_3)) return -EINVAL; break; default: return -EINVAL; } /* if we changed something we need to update flags */ if (flags2 != adapter->flags2) { struct ixgbe_hw *hw = &adapter->hw; u32 mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); if ((flags2 & UDP_RSS_FLAGS) && !(adapter->flags2 & UDP_RSS_FLAGS)) e_warn(drv, "enabling UDP RSS: fragmented packets" " may arrive out of order to the stack above\n"); adapter->flags2 = flags2; /* Perform hash on these packet types */ mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4 | IXGBE_MRQC_RSS_FIELD_IPV4_TCP | IXGBE_MRQC_RSS_FIELD_IPV6 | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; mrqc &= ~(IXGBE_MRQC_RSS_FIELD_IPV4_UDP | IXGBE_MRQC_RSS_FIELD_IPV6_UDP); if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } return 0; } static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) { struct ixgbe_adapter *adapter = netdev_priv(dev); int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_SRXCLSRLINS: ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd); break; case ETHTOOL_SRXCLSRLDEL: ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd); break; case ETHTOOL_SRXFH: ret = ixgbe_set_rss_hash_opt(adapter, cmd); break; default: break; } return ret; } #endif /* ETHTOOL_GRXRINGS */ //static struct ethtool_ops ixgbe_ethtool_ops = { .get_settings = ixgbe_get_settings, .set_settings = ixgbe_set_settings, .get_drvinfo = ixgbe_get_drvinfo, .get_regs_len = ixgbe_get_regs_len, .get_regs = ixgbe_get_regs, .get_wol = ixgbe_get_wol, .set_wol = ixgbe_set_wol, .nway_reset = ixgbe_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = ixgbe_get_eeprom_len, .get_eeprom = ixgbe_get_eeprom, .set_eeprom = ixgbe_set_eeprom, .get_ringparam = ixgbe_get_ringparam, .set_ringparam = ixgbe_set_ringparam, .get_pauseparam = ixgbe_get_pauseparam, .set_pauseparam = ixgbe_set_pauseparam, .get_msglevel = ixgbe_get_msglevel, .set_msglevel = ixgbe_set_msglevel, #ifndef HAVE_ETHTOOL_GET_SSET_COUNT .self_test_count = ixgbe_diag_test_count, #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */ .self_test = ixgbe_diag_test, .get_strings = ixgbe_get_strings, #ifdef HAVE_ETHTOOL_SET_PHYS_ID .set_phys_id = ixgbe_set_phys_id, #else .phys_id = ixgbe_phys_id, #endif /* HAVE_ETHTOOL_SET_PHYS_ID */ #ifndef HAVE_ETHTOOL_GET_SSET_COUNT .get_stats_count = ixgbe_get_stats_count, #else /* HAVE_ETHTOOL_GET_SSET_COUNT */ .get_sset_count = ixgbe_get_sset_count, #endif /* HAVE_ETHTOOL_GET_SSET_COUNT */ .get_ethtool_stats = ixgbe_get_ethtool_stats, #ifdef HAVE_ETHTOOL_GET_PERM_ADDR .get_perm_addr = ethtool_op_get_perm_addr, #endif .get_coalesce = ixgbe_get_coalesce, .set_coalesce = ixgbe_set_coalesce, #ifndef HAVE_NDO_SET_FEATURES .get_rx_csum = ixgbe_get_rx_csum, .set_rx_csum = ixgbe_set_rx_csum, .get_tx_csum = ixgbe_get_tx_csum, .set_tx_csum = ixgbe_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ixgbe_set_tso, #endif #ifdef ETHTOOL_GFLAGS .get_flags = ethtool_op_get_flags, .set_flags = ixgbe_set_flags, #endif #endif /* HAVE_NDO_SET_FEATURES */ #ifdef ETHTOOL_GRXRINGS .get_rxnfc = ixgbe_get_rxnfc, .set_rxnfc = ixgbe_set_rxnfc, #ifdef ETHTOOL_SRXNTUPLE .set_rx_ntuple = ixgbe_set_rx_ntuple, #endif #endif }; void ixgbe_set_ethtool_ops(struct net_device *netdev) { SET_ETHTOOL_OPS(netdev, &ixgbe_ethtool_ops); } #endif /* SIOCETHTOOL */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_fcoe.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_FCOE_H #define _IXGBE_FCOE_H #ifdef IXGBE_FCOE #include #include /* shift bits within STAT fo FCSTAT */ #define IXGBE_RXDADV_FCSTAT_SHIFT 4 /* ddp user buffer */ #define IXGBE_BUFFCNT_MAX 256 /* 8 bits bufcnt */ #define IXGBE_FCPTR_ALIGN 16 #define IXGBE_FCPTR_MAX (IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t)) #define IXGBE_FCBUFF_4KB 0x0 #define IXGBE_FCBUFF_8KB 0x1 #define IXGBE_FCBUFF_16KB 0x2 #define IXGBE_FCBUFF_64KB 0x3 #define IXGBE_FCBUFF_MAX 65536 /* 64KB max */ #define IXGBE_FCBUFF_MIN 4096 /* 4KB min */ #define IXGBE_FCOE_DDP_MAX 512 /* 9 bits xid */ /* Default traffic class to use for FCoE */ #define IXGBE_FCOE_DEFTC 3 /* fcerr */ #define IXGBE_FCERR_BADCRC 0x00100000 #define IXGBE_FCERR_EOFSOF 0x00200000 #define IXGBE_FCERR_NOFIRST 0x00300000 #define IXGBE_FCERR_OOOSEQ 0x00400000 #define IXGBE_FCERR_NODMA 0x00500000 #define IXGBE_FCERR_PKTLOST 0x00600000 /* FCoE DDP for target mode */ #define __IXGBE_FCOE_TARGET 1 struct ixgbe_fcoe_ddp { int len; u32 err; unsigned int sgc; struct scatterlist *sgl; dma_addr_t udp; u64 *udl; struct pci_pool *pool; }; struct ixgbe_fcoe { struct pci_pool **pool; atomic_t refcnt; spinlock_t lock; struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX]; unsigned char *extra_ddp_buffer; dma_addr_t extra_ddp_buffer_dma; u64 __percpu *pcpu_noddp; u64 __percpu *pcpu_noddp_ext_buff; unsigned long mode; u8 tc; u8 up; u8 up_set; }; #endif /* IXGBE_FCOE */ #endif /* _IXGBE_FCOE_H */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_main.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /****************************************************************************** Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code ******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SCTP #include #endif #include #include #ifdef NETIF_F_TSO #include #ifdef NETIF_F_TSO6 #include #endif #endif #ifdef SIOCETHTOOL #include #endif #include "ixgbe.h" #undef CONFIG_DCA #undef CONFIG_DCA_MODULE char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; #define DRV_HW_PERF #ifndef CONFIG_IXGBE_NAPI #define DRIVERNAPI #else #define DRIVERNAPI "-NAPI" #endif #define FPGA #define VMDQ_TAG #define MAJ 3 #define MIN 9 #define BUILD 17 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) DRIVERNAPI DRV_HW_PERF FPGA VMDQ_TAG const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2012 Intel Corporation."; /* ixgbe_pci_tbl - PCI Device ID Table * * Wildcard entries (PCI_ANY_ID) should come last * Last entry must be all 0s * * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP)}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_QSFP_SF_QP)}, /* required last entry */ {0, } }; #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) static int ixgbe_notify_dca(struct notifier_block *, unsigned long event, void *p); static struct notifier_block dca_notifier = { .notifier_call = ixgbe_notify_dca, .next = NULL, .priority = 0 }; #endif MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); #define DEFAULT_DEBUG_LEVEL_SHIFT 3 static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter) { u32 ctrl_ext; /* Let firmware take over control of h/w */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); } #ifdef NO_VNIC static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) { u32 ctrl_ext; /* Let firmware know the driver has taken over */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); } #endif static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw_stats *hwstats = &adapter->stats; int i; u32 data; if ((hw->fc.current_mode != ixgbe_fc_full) && (hw->fc.current_mode != ixgbe_fc_rx_pause)) return; switch (hw->mac.type) { case ixgbe_mac_82598EB: data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); break; default: data = IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT); } hwstats->lxoffrxc += data; /* refill credits (no tx hang) if we received xoff */ if (!data) return; for (i = 0; i < adapter->num_tx_queues; i++) clear_bit(__IXGBE_HANG_CHECK_ARMED, &adapter->tx_ring[i]->state); } static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw_stats *hwstats = &adapter->stats; u32 xoff[8] = {0}; int i; bool pfc_en = adapter->dcb_cfg.pfc_mode_enable; #ifdef HAVE_DCBNL_IEEE if (adapter->ixgbe_ieee_pfc) pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en); #endif if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) || !pfc_en) { ixgbe_update_xoff_rx_lfc(adapter); return; } /* update stats for each tc, only valid with PFC enabled */ for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { switch (hw->mac.type) { case ixgbe_mac_82598EB: xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i)); break; default: xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i)); } hwstats->pxoffrxc[i] += xoff[i]; } /* disarm tx queues that have received xoff frames */ for (i = 0; i < adapter->num_tx_queues; i++) { struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; u8 tc = tx_ring->dcb_tc; if ((tc <= 7) && (xoff[tc])) clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state); } } #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 #ifdef HAVE_8021P_SUPPORT /** * ixgbe_vlan_stripping_disable - helper to disable vlan tag stripping * @adapter: driver data */ void ixgbe_vlan_stripping_disable(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 vlnctrl; int i; /* leave vlan tag stripping enabled for DCB */ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) return; switch (hw->mac.type) { case ixgbe_mac_82598EB: vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlnctrl &= ~IXGBE_VLNCTRL_VME; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: for (i = 0; i < adapter->num_rx_queues; i++) { u8 reg_idx = adapter->rx_ring[i]->reg_idx; vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); vlnctrl &= ~IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), vlnctrl); } break; default: break; } } #endif /** * ixgbe_vlan_stripping_enable - helper to enable vlan tag stripping * @adapter: driver data */ void ixgbe_vlan_stripping_enable(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 vlnctrl; int i; switch (hw->mac.type) { case ixgbe_mac_82598EB: vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); vlnctrl |= IXGBE_VLNCTRL_VME; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: for (i = 0; i < adapter->num_rx_queues; i++) { u8 reg_idx = adapter->rx_ring[i]->reg_idx; vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx)); vlnctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), vlnctrl); } break; default: break; } } #ifdef HAVE_VLAN_RX_REGISTER void ixgbe_vlan_mode(struct net_device *netdev, struct vlan_group *grp) #else void ixgbe_vlan_mode(struct net_device *netdev, u32 features) #endif { struct ixgbe_adapter *adapter = netdev_priv(netdev); #ifdef HAVE_8021P_SUPPORT bool enable; #endif #ifdef HAVE_VLAN_RX_REGISTER //if (!test_bit(__IXGBE_DOWN, &adapter->state)) // ixgbe_irq_disable(adapter); adapter->vlgrp = grp; //if (!test_bit(__IXGBE_DOWN, &adapter->state)) // ixgbe_irq_enable(adapter, true, true); #endif #ifdef HAVE_8021P_SUPPORT #ifdef HAVE_VLAN_RX_REGISTER enable = (grp || (adapter->flags & IXGBE_FLAG_DCB_ENABLED)); #else enable = !!(features & NETIF_F_HW_VLAN_RX); #endif if (enable) /* enable VLAN tag insert/strip */ ixgbe_vlan_stripping_enable(adapter); else /* disable VLAN tag insert/strip */ ixgbe_vlan_stripping_disable(adapter); #endif } static u8 *ixgbe_addr_list_itr(struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq) { #ifdef NETDEV_HW_ADDR_T_MULTICAST struct netdev_hw_addr *mc_ptr; #else struct dev_mc_list *mc_ptr; #endif struct ixgbe_adapter *adapter = hw->back; u8 *addr = *mc_addr_ptr; *vmdq = adapter->num_vfs; #ifdef NETDEV_HW_ADDR_T_MULTICAST mc_ptr = container_of(addr, struct netdev_hw_addr, addr[0]); if (mc_ptr->list.next) { struct netdev_hw_addr *ha; ha = list_entry(mc_ptr->list.next, struct netdev_hw_addr, list); *mc_addr_ptr = ha->addr; } #else mc_ptr = container_of(addr, struct dev_mc_list, dmi_addr[0]); if (mc_ptr->next) *mc_addr_ptr = mc_ptr->next->dmi_addr; #endif else *mc_addr_ptr = NULL; return addr; } /** * ixgbe_write_mc_addr_list - write multicast addresses to MTA * @netdev: network interface device structure * * Writes multicast address list to the MTA hash table. * Returns: -ENOMEM on failure * 0 on no addresses written * X on writing X addresses to MTA **/ int ixgbe_write_mc_addr_list(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; #ifdef NETDEV_HW_ADDR_T_MULTICAST struct netdev_hw_addr *ha; #endif u8 *addr_list = NULL; int addr_count = 0; if (!hw->mac.ops.update_mc_addr_list) return -ENOMEM; if (!netif_running(netdev)) return 0; hw->mac.ops.update_mc_addr_list(hw, NULL, 0, ixgbe_addr_list_itr, true); if (!netdev_mc_empty(netdev)) { #ifdef NETDEV_HW_ADDR_T_MULTICAST ha = list_first_entry(&netdev->mc.list, struct netdev_hw_addr, list); addr_list = ha->addr; #else addr_list = netdev->mc_list->dmi_addr; #endif addr_count = netdev_mc_count(netdev); hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count, ixgbe_addr_list_itr, false); } #ifdef CONFIG_PCI_IOV //ixgbe_restore_vf_multicasts(adapter); #endif return addr_count; } void ixgbe_full_sync_mac_table(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int i; for (i = 0; i < hw->mac.num_rar_entries; i++) { if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) { hw->mac.ops.set_rar(hw, i, adapter->mac_table[i].addr, adapter->mac_table[i].queue, IXGBE_RAH_AV); } else { hw->mac.ops.clear_rar(hw, i); } } } void ixgbe_sync_mac_table(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int i; for (i = 0; i < hw->mac.num_rar_entries; i++) { if (adapter->mac_table[i].state & IXGBE_MAC_STATE_MODIFIED) { if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) { hw->mac.ops.set_rar(hw, i, adapter->mac_table[i].addr, adapter->mac_table[i].queue, IXGBE_RAH_AV); } else { hw->mac.ops.clear_rar(hw, i); } adapter->mac_table[i].state &= ~(IXGBE_MAC_STATE_MODIFIED); } } } int ixgbe_available_rars(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int i, count = 0; for (i = 0; i < hw->mac.num_rar_entries; i++) { if (adapter->mac_table[i].state == 0) count++; } return count; } int ixgbe_add_mac_filter(struct ixgbe_adapter *adapter, u8 *addr, u16 queue) { struct ixgbe_hw *hw = &adapter->hw; int i; if (is_zero_ether_addr(addr)) return 0; for (i = 0; i < hw->mac.num_rar_entries; i++) { if (adapter->mac_table[i].state & IXGBE_MAC_STATE_IN_USE) continue; adapter->mac_table[i].state |= (IXGBE_MAC_STATE_MODIFIED | IXGBE_MAC_STATE_IN_USE); memcpy(adapter->mac_table[i].addr, addr, ETH_ALEN); adapter->mac_table[i].queue = queue; ixgbe_sync_mac_table(adapter); return i; } return -ENOMEM; } void ixgbe_flush_sw_mac_table(struct ixgbe_adapter *adapter) { int i; struct ixgbe_hw *hw = &adapter->hw; for (i = 0; i < hw->mac.num_rar_entries; i++) { adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; memset(adapter->mac_table[i].addr, 0, ETH_ALEN); adapter->mac_table[i].queue = 0; } ixgbe_sync_mac_table(adapter); } void ixgbe_del_mac_filter_by_index(struct ixgbe_adapter *adapter, int index) { adapter->mac_table[index].state |= IXGBE_MAC_STATE_MODIFIED; adapter->mac_table[index].state &= ~IXGBE_MAC_STATE_IN_USE; memset(adapter->mac_table[index].addr, 0, ETH_ALEN); adapter->mac_table[index].queue = 0; ixgbe_sync_mac_table(adapter); } int ixgbe_del_mac_filter(struct ixgbe_adapter *adapter, u8* addr, u16 queue) { /* search table for addr, if found, set to 0 and sync */ int i; struct ixgbe_hw *hw = &adapter->hw; if (is_zero_ether_addr(addr)) return 0; for (i = 0; i < hw->mac.num_rar_entries; i++) { if (ether_addr_equal(addr, adapter->mac_table[i].addr) && adapter->mac_table[i].queue == queue) { adapter->mac_table[i].state |= IXGBE_MAC_STATE_MODIFIED; adapter->mac_table[i].state &= ~IXGBE_MAC_STATE_IN_USE; memset(adapter->mac_table[i].addr, 0, ETH_ALEN); adapter->mac_table[i].queue = 0; ixgbe_sync_mac_table(adapter); return 0; } } return -ENOMEM; } #ifdef HAVE_SET_RX_MODE /** * ixgbe_write_uc_addr_list - write unicast addresses to RAR table * @netdev: network interface device structure * * Writes unicast address list to the RAR table. * Returns: -ENOMEM on failure/insufficient address space * 0 on no addresses written * X on writing X addresses to the RAR table **/ int ixgbe_write_uc_addr_list(struct ixgbe_adapter *adapter, struct net_device *netdev, unsigned int vfn) { int count = 0; /* return ENOMEM indicating insufficient memory for addresses */ if (netdev_uc_count(netdev) > ixgbe_available_rars(adapter)) return -ENOMEM; if (!netdev_uc_empty(netdev)) { #ifdef NETDEV_HW_ADDR_T_UNICAST struct netdev_hw_addr *ha; #else struct dev_mc_list *ha; #endif netdev_for_each_uc_addr(ha, netdev) { #ifdef NETDEV_HW_ADDR_T_UNICAST ixgbe_del_mac_filter(adapter, ha->addr, (u16)vfn); ixgbe_add_mac_filter(adapter, ha->addr, (u16)vfn); #else ixgbe_del_mac_filter(adapter, ha->da_addr, (u16)vfn); ixgbe_add_mac_filter(adapter, ha->da_addr, (u16)vfn); #endif count++; } } return count; } #endif /** * ixgbe_set_rx_mode - Unicast, Multicast and Promiscuous mode set * @netdev: network interface device structure * * The set_rx_method entry point is called whenever the unicast/multicast * address list or the network interface flags are updated. This routine is * responsible for configuring the hardware for proper unicast, multicast and * promiscuous mode. **/ void ixgbe_set_rx_mode(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE; u32 vlnctrl; int count; /* Check for Promiscuous and All Multicast modes */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); /* set all bits that we expect to always be set */ fctrl |= IXGBE_FCTRL_BAM; fctrl |= IXGBE_FCTRL_DPF; /* discard pause frames when FC enabled */ fctrl |= IXGBE_FCTRL_PMCF; /* clear the bits we are changing the status of */ fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN); if (netdev->flags & IFF_PROMISC) { hw->addr_ctrl.user_set_promisc = true; fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); vmolr |= IXGBE_VMOLR_MPE; } else { if (netdev->flags & IFF_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; vmolr |= IXGBE_VMOLR_MPE; } else { /* * Write addresses to the MTA, if the attempt fails * then we should just turn on promiscuous mode so * that we can at least receive multicast traffic */ count = ixgbe_write_mc_addr_list(netdev); if (count < 0) { fctrl |= IXGBE_FCTRL_MPE; vmolr |= IXGBE_VMOLR_MPE; } else if (count) { vmolr |= IXGBE_VMOLR_ROMPE; } } #ifdef NETIF_F_HW_VLAN_TX /* enable hardware vlan filtering */ vlnctrl |= IXGBE_VLNCTRL_VFE; #endif hw->addr_ctrl.user_set_promisc = false; #ifdef HAVE_SET_RX_MODE /* * Write addresses to available RAR registers, if there is not * sufficient space to store all the addresses then enable * unicast promiscuous mode */ count = ixgbe_write_uc_addr_list(adapter, netdev, adapter->num_vfs); if (count < 0) { fctrl |= IXGBE_FCTRL_UPE; vmolr |= IXGBE_VMOLR_ROPE; } #endif } if (hw->mac.type != ixgbe_mac_82598EB) { vmolr |= IXGBE_READ_REG(hw, IXGBE_VMOLR(adapter->num_vfs)) & ~(IXGBE_VMOLR_MPE | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_ROPE); IXGBE_WRITE_REG(hw, IXGBE_VMOLR(adapter->num_vfs), vmolr); } IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); } /* Additional bittime to account for IXGBE framing */ #define IXGBE_ETH_FRAMING 20 /* * ixgbe_hpbthresh - calculate high water mark for flow control * * @adapter: board private structure to calculate for * @pb - packet buffer to calculate */ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb) { struct ixgbe_hw *hw = &adapter->hw; struct net_device *dev = adapter->netdev; int link, tc, kb, marker; u32 dv_id, rx_pba; /* Calculate max LAN frame size */ tc = link = dev->mtu + ETH_HLEN + ETH_FCS_LEN + IXGBE_ETH_FRAMING; #ifdef IXGBE_FCOE /* FCoE traffic class uses FCOE jumbo frames */ if (dev->features & NETIF_F_FCOE_MTU) { int fcoe_pb = 0; fcoe_pb = netdev_get_prio_tc_map(dev, adapter->fcoe.up); if (fcoe_pb == pb && tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) tc = IXGBE_FCOE_JUMBO_FRAME_SIZE; } #endif /* Calculate delay value for device */ switch (hw->mac.type) { case ixgbe_mac_X540: dv_id = IXGBE_DV_X540(link, tc); break; default: dv_id = IXGBE_DV(link, tc); break; } /* Loopback switch introduces additional latency */ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) dv_id += IXGBE_B2BT(tc); /* Delay value is calculated in bit times convert to KB */ kb = IXGBE_BT2KB(dv_id); rx_pba = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(pb)) >> 10; marker = rx_pba - kb; /* It is possible that the packet buffer is not large enough * to provide required headroom. In this case throw an error * to user and a do the best we can. */ if (marker < 0) { e_warn(drv, "Packet Buffer(%i) can not provide enough" "headroom to suppport flow control." "Decrease MTU or number of traffic classes\n", pb); marker = tc + 1; } return marker; } /* * ixgbe_lpbthresh - calculate low water mark for for flow control * * @adapter: board private structure to calculate for * @pb - packet buffer to calculate */ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb) { struct ixgbe_hw *hw = &adapter->hw; struct net_device *dev = adapter->netdev; int tc; u32 dv_id; /* Calculate max LAN frame size */ tc = dev->mtu + ETH_HLEN + ETH_FCS_LEN; #ifdef IXGBE_FCOE /* FCoE traffic class uses FCOE jumbo frames */ if (dev->features & NETIF_F_FCOE_MTU) { int fcoe_pb = 0; fcoe_pb = netdev_get_prio_tc_map(dev, adapter->fcoe.up); if (fcoe_pb == pb && tc < IXGBE_FCOE_JUMBO_FRAME_SIZE) tc = IXGBE_FCOE_JUMBO_FRAME_SIZE; } #endif /* Calculate delay value for device */ switch (hw->mac.type) { case ixgbe_mac_X540: dv_id = IXGBE_LOW_DV_X540(tc); break; default: dv_id = IXGBE_LOW_DV(tc); break; } /* Delay value is calculated in bit times convert to KB */ return IXGBE_BT2KB(dv_id); } /* * ixgbe_pbthresh_setup - calculate and setup high low water marks */ static void ixgbe_pbthresh_setup(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int num_tc = netdev_get_num_tc(adapter->netdev); int i; if (!num_tc) num_tc = 1; if (num_tc > IXGBE_DCB_MAX_TRAFFIC_CLASS) num_tc = IXGBE_DCB_MAX_TRAFFIC_CLASS; for (i = 0; i < num_tc; i++) { hw->fc.high_water[i] = ixgbe_hpbthresh(adapter, i); hw->fc.low_water[i] = ixgbe_lpbthresh(adapter, i); /* Low water marks must not be larger than high water marks */ if (hw->fc.low_water[i] > hw->fc.high_water[i]) hw->fc.low_water[i] = 0; } for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) hw->fc.high_water[i] = 0; } #ifdef NO_VNIC static void ixgbe_configure(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; ixgbe_configure_pb(adapter); ixgbe_configure_dcb(adapter); ixgbe_set_rx_mode(adapter->netdev); #ifdef NETIF_F_HW_VLAN_TX ixgbe_restore_vlan(adapter); #endif #ifdef IXGBE_FCOE if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) ixgbe_configure_fcoe(adapter); #endif /* IXGBE_FCOE */ if (adapter->hw.mac.type != ixgbe_mac_82598EB) hw->mac.ops.disable_sec_rx_path(hw); if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { ixgbe_init_fdir_signature_82599(&adapter->hw, adapter->fdir_pballoc); } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) { ixgbe_init_fdir_perfect_82599(&adapter->hw, adapter->fdir_pballoc); ixgbe_fdir_filter_restore(adapter); } if (adapter->hw.mac.type != ixgbe_mac_82598EB) hw->mac.ops.enable_sec_rx_path(hw); ixgbe_configure_virtualization(adapter); ixgbe_configure_tx(adapter); ixgbe_configure_rx(adapter); } #endif static bool ixgbe_is_sfp(struct ixgbe_hw *hw) { switch (hw->phy.type) { case ixgbe_phy_sfp_avago: case ixgbe_phy_sfp_ftl: case ixgbe_phy_sfp_intel: case ixgbe_phy_sfp_unknown: case ixgbe_phy_sfp_passive_tyco: case ixgbe_phy_sfp_passive_unknown: case ixgbe_phy_sfp_active_unknown: case ixgbe_phy_sfp_ftl_active: return true; case ixgbe_phy_nl: if (hw->mac.type == ixgbe_mac_82598EB) return true; default: return false; } } /** * ixgbe_clear_vf_stats_counters - Clear out VF stats after reset * @adapter: board private structure * * On a reset we need to clear out the VF stats or accounting gets * messed up because they're not clear on read. **/ void ixgbe_clear_vf_stats_counters(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int i; for (i = 0; i < adapter->num_vfs; i++) { adapter->vfinfo[i].last_vfstats.gprc = IXGBE_READ_REG(hw, IXGBE_PVFGPRC(i)); adapter->vfinfo[i].saved_rst_vfstats.gprc += adapter->vfinfo[i].vfstats.gprc; adapter->vfinfo[i].vfstats.gprc = 0; adapter->vfinfo[i].last_vfstats.gptc = IXGBE_READ_REG(hw, IXGBE_PVFGPTC(i)); adapter->vfinfo[i].saved_rst_vfstats.gptc += adapter->vfinfo[i].vfstats.gptc; adapter->vfinfo[i].vfstats.gptc = 0; adapter->vfinfo[i].last_vfstats.gorc = IXGBE_READ_REG(hw, IXGBE_PVFGORC_LSB(i)); adapter->vfinfo[i].saved_rst_vfstats.gorc += adapter->vfinfo[i].vfstats.gorc; adapter->vfinfo[i].vfstats.gorc = 0; adapter->vfinfo[i].last_vfstats.gotc = IXGBE_READ_REG(hw, IXGBE_PVFGOTC_LSB(i)); adapter->vfinfo[i].saved_rst_vfstats.gotc += adapter->vfinfo[i].vfstats.gotc; adapter->vfinfo[i].vfstats.gotc = 0; adapter->vfinfo[i].last_vfstats.mprc = IXGBE_READ_REG(hw, IXGBE_PVFMPRC(i)); adapter->vfinfo[i].saved_rst_vfstats.mprc += adapter->vfinfo[i].vfstats.mprc; adapter->vfinfo[i].vfstats.mprc = 0; } } void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) { #ifdef NO_VNIC WARN_ON(in_interrupt()); /* put off any impending NetWatchDogTimeout */ adapter->netdev->trans_start = jiffies; while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) usleep_range(1000, 2000); ixgbe_down(adapter); /* * If SR-IOV enabled then wait a bit before bringing the adapter * back up to give the VFs time to respond to the reset. The * two second wait is based upon the watchdog timer cycle in * the VF driver. */ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) msleep(2000); ixgbe_up(adapter); clear_bit(__IXGBE_RESETTING, &adapter->state); #endif } void ixgbe_up(struct ixgbe_adapter *adapter) { /* hardware has been reset, we need to reload some things */ //ixgbe_configure(adapter); //ixgbe_up_complete(adapter); } void ixgbe_reset(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; int err; /* lock SFP init bit to prevent race conditions with the watchdog */ while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) usleep_range(1000, 2000); /* clear all SFP and link config related flags while holding SFP_INIT */ adapter->flags2 &= ~(IXGBE_FLAG2_SEARCH_FOR_SFP | IXGBE_FLAG2_SFP_NEEDS_RESET); adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; err = hw->mac.ops.init_hw(hw); switch (err) { case 0: case IXGBE_ERR_SFP_NOT_PRESENT: case IXGBE_ERR_SFP_NOT_SUPPORTED: break; case IXGBE_ERR_MASTER_REQUESTS_PENDING: e_dev_err("master disable timed out\n"); break; case IXGBE_ERR_EEPROM_VERSION: /* We are running on a pre-production device, log a warning */ e_dev_warn("This device is a pre-production adapter/LOM. " "Please be aware there may be issues associated " "with your hardware. If you are experiencing " "problems please contact your Intel or hardware " "representative who provided you with this " "hardware.\n"); break; default: e_dev_err("Hardware Error: %d\n", err); } clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state); ixgbe_flush_sw_mac_table(adapter); memcpy(&adapter->mac_table[0].addr, hw->mac.perm_addr, netdev->addr_len); adapter->mac_table[0].queue = adapter->num_vfs; adapter->mac_table[0].state = (IXGBE_MAC_STATE_DEFAULT | IXGBE_MAC_STATE_IN_USE); hw->mac.ops.set_rar(hw, 0, adapter->mac_table[0].addr, adapter->mac_table[0].queue, IXGBE_RAH_AV); } void ixgbe_down(struct ixgbe_adapter *adapter) { #ifdef NO_VNIC struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; u32 rxctrl; int i; /* signal that we are down to the interrupt handler */ set_bit(__IXGBE_DOWN, &adapter->state); /* disable receives */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); /* disable all enabled rx queues */ for (i = 0; i < adapter->num_rx_queues; i++) /* this call also flushes the previous write */ ixgbe_disable_rx_queue(adapter, adapter->rx_ring[i]); usleep_range(10000, 20000); netif_tx_stop_all_queues(netdev); /* call carrier off first to avoid false dev_watchdog timeouts */ netif_carrier_off(netdev); netif_tx_disable(netdev); ixgbe_irq_disable(adapter); ixgbe_napi_disable_all(adapter); adapter->flags2 &= ~(IXGBE_FLAG2_FDIR_REQUIRES_REINIT | IXGBE_FLAG2_RESET_REQUESTED); adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; del_timer_sync(&adapter->service_timer); if (adapter->num_vfs) { /* Clear EITR Select mapping */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0); /* Mark all the VFs as inactive */ for (i = 0 ; i < adapter->num_vfs; i++) adapter->vfinfo[i].clear_to_send = 0; /* ping all the active vfs to let them know we are going down */ ixgbe_ping_all_vfs(adapter); /* Disable all VFTE/VFRE TX/RX */ ixgbe_disable_tx_rx(adapter); } /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { u8 reg_idx = adapter->tx_ring[i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); } /* Disable the Tx DMA engine on 82599 and X540 */ switch (hw->mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & ~IXGBE_DMATXCTL_TE)); break; default: break; } #ifdef HAVE_PCI_ERS if (!pci_channel_offline(adapter->pdev)) #endif ixgbe_reset(adapter); /* power down the optics */ if ((hw->phy.multispeed_fiber) || ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) && (hw->mac.type == ixgbe_mac_82599EB))) ixgbe_disable_tx_laser(hw); ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) /* since we reset the hardware DCA settings were cleared */ ixgbe_setup_dca(adapter); #endif #endif /* NO_VNIC */ } #ifndef NO_VNIC #undef IXGBE_FCOE /* Artificial max queue cap per traffic class in DCB mode */ #define DCB_QUEUE_CAP 8 /** * ixgbe_set_dcb_queues: Allocate queues for a DCB-enabled device * @adapter: board private structure to initialize * * When DCB (Data Center Bridging) is enabled, allocate queues for * each traffic class. If multiqueue isn't available,then abort DCB * initialization. * * This function handles all combinations of DCB, RSS, and FCoE. * **/ static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) { int tcs; #ifdef HAVE_MQPRIO int rss_i, i, offset = 0; struct net_device *dev = adapter->netdev; /* Map queue offset and counts onto allocated tx queues */ tcs = netdev_get_num_tc(dev); if (!tcs) return false; rss_i = min_t(int, dev->num_tx_queues / tcs, num_online_cpus()); if (rss_i > DCB_QUEUE_CAP) rss_i = DCB_QUEUE_CAP; for (i = 0; i < tcs; i++) { netdev_set_tc_queue(dev, i, rss_i, offset); offset += rss_i; } adapter->num_tx_queues = rss_i * tcs; adapter->num_rx_queues = rss_i * tcs; #ifdef IXGBE_FCOE /* FCoE enabled queues require special configuration indexed * by feature specific indices and mask. Here we map FCoE * indices onto the DCB queue pairs allowing FCoE to own * configuration later. */ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { struct ixgbe_ring_feature *f; int tc; u8 prio_tc[IXGBE_DCB_MAX_USER_PRIORITY] = {0}; ixgbe_dcb_unpack_map_cee(&adapter->dcb_cfg, IXGBE_DCB_TX_CONFIG, prio_tc); tc = prio_tc[adapter->fcoe.up]; f = &adapter->ring_feature[RING_F_FCOE]; f->indices = min_t(int, rss_i, f->indices); f->mask = rss_i * tc; } #endif /* IXGBE_FCOE */ #else if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED)) return false; /* Enable one Queue per traffic class */ tcs = adapter->tc; if (!tcs) return false; #ifdef IXGBE_FCOE if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { struct ixgbe_ring_feature *f; int tc = netdev_get_prio_tc_map(adapter->netdev, adapter->fcoe.up); f = &adapter->ring_feature[RING_F_FCOE]; /* * We have max 8 queues for FCoE, where 8 the is * FCoE redirection table size. We must also share * ring resources with network traffic so if FCoE TC is * 4 or greater and we are in 8 TC mode we can only use * 7 queues. */ if ((tcs > 4) && (tc >= 4) && (f->indices > 7)) f->indices = 7; f->indices = min_t(int, num_online_cpus(), f->indices); f->mask = tcs; adapter->num_rx_queues = f->indices + tcs; adapter->num_tx_queues = f->indices + tcs; return true; } #endif /* IXGBE_FCOE */ adapter->num_rx_queues = tcs; adapter->num_tx_queues = tcs; #endif /* HAVE_MQ */ return true; } /** * ixgbe_set_vmdq_queues: Allocate queues for VMDq devices * @adapter: board private structure to initialize * * When VMDq (Virtual Machine Devices queue) is enabled, allocate queues * and VM pools where appropriate. If RSS is available, then also try and * enable RSS and map accordingly. * **/ static bool ixgbe_set_vmdq_queues(struct ixgbe_adapter *adapter) { int vmdq_i = adapter->ring_feature[RING_F_VMDQ].indices; int vmdq_m = 0; int rss_i = adapter->ring_feature[RING_F_RSS].indices; unsigned long i; int rss_shift; bool ret = false; switch (adapter->flags & (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) { case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED): switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: vmdq_i = min((int)IXGBE_MAX_VMDQ_INDICES, vmdq_i); if (vmdq_i > 32) rss_i = 2; else rss_i = 4; i = rss_i; rss_shift = find_first_bit(&i, sizeof(i) * 8); vmdq_m = ((IXGBE_MAX_VMDQ_INDICES - 1) << rss_shift) & (MAX_RX_QUEUES - 1); break; default: break; } adapter->num_rx_queues = vmdq_i * rss_i; adapter->num_tx_queues = min((int)MAX_TX_QUEUES, vmdq_i * rss_i); ret = true; break; case (IXGBE_FLAG_VMDQ_ENABLED): switch (adapter->hw.mac.type) { case ixgbe_mac_82598EB: vmdq_m = (IXGBE_MAX_VMDQ_INDICES - 1); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: vmdq_m = (IXGBE_MAX_VMDQ_INDICES - 1) << 1; break; default: break; } adapter->num_rx_queues = vmdq_i; adapter->num_tx_queues = vmdq_i; ret = true; break; default: ret = false; goto vmdq_queues_out; } if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) { adapter->num_rx_pools = vmdq_i; adapter->num_rx_queues_per_pool = adapter->num_rx_queues / vmdq_i; } else { adapter->num_rx_pools = adapter->num_rx_queues; adapter->num_rx_queues_per_pool = 1; } /* save the mask for later use */ adapter->ring_feature[RING_F_VMDQ].mask = vmdq_m; vmdq_queues_out: return ret; } /** * ixgbe_set_rss_queues: Allocate queues for RSS * @adapter: board private structure to initialize * * This is our "base" multiqueue mode. RSS (Receive Side Scaling) will try * to allocate one Rx queue per CPU, and if available, one Tx queue per CPU. * **/ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) { struct ixgbe_ring_feature *f; if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) { adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; return false; } /* set mask for 16 queue limit of RSS */ f = &adapter->ring_feature[RING_F_RSS]; f->mask = 0xF; /* * Use Flow Director in addition to RSS to ensure the best * distribution of flows across cores, even when an FDIR flow * isn't matched. */ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { f = &adapter->ring_feature[RING_F_FDIR]; f->indices = min_t(int, num_online_cpus(), f->indices); f->mask = 0; } adapter->num_rx_queues = f->indices; #ifdef HAVE_TX_MQ adapter->num_tx_queues = f->indices; #endif return true; } #ifdef IXGBE_FCOE /** * ixgbe_set_fcoe_queues: Allocate queues for Fiber Channel over Ethernet (FCoE) * @adapter: board private structure to initialize * * FCoE RX FCRETA can use up to 8 rx queues for up to 8 different exchanges. * The ring feature mask is not used as a mask for FCoE, as it can take any 8 * rx queues out of the max number of rx queues, instead, it is used as the * index of the first rx queue used by FCoE. * **/ static bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) { struct ixgbe_ring_feature *f; if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) return false; ixgbe_set_rss_queues(adapter); f = &adapter->ring_feature[RING_F_FCOE]; f->indices = min_t(int, num_online_cpus(), f->indices); /* adding FCoE queues */ f->mask = adapter->num_rx_queues; adapter->num_rx_queues += f->indices; adapter->num_tx_queues += f->indices; return true; } #endif /* IXGBE_FCOE */ /* * ixgbe_set_num_queues: Allocate queues for device, feature dependent * @adapter: board private structure to initialize * * This is the top level queue allocation routine. The order here is very * important, starting with the "most" number of features turned on at once, * and ending with the smallest set of features. This way large combinations * can be allocated if they're turned on, and smaller combinations are the * fallthrough conditions. * **/ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) { /* Start with base case */ adapter->num_rx_queues = 1; adapter->num_tx_queues = 1; adapter->num_rx_pools = adapter->num_rx_queues; adapter->num_rx_queues_per_pool = 1; if (ixgbe_set_vmdq_queues(adapter)) return; if (ixgbe_set_dcb_queues(adapter)) return; #ifdef IXGBE_FCOE if (ixgbe_set_fcoe_queues(adapter)) return; #endif /* IXGBE_FCOE */ ixgbe_set_rss_queues(adapter); } #endif /** * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter) * @adapter: board private structure to initialize * * ixgbe_sw_init initializes the Adapter private data structure. * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; int err; /* PCI config space info */ hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); hw->subsystem_vendor_id = pdev->subsystem_vendor; hw->subsystem_device_id = pdev->subsystem_device; err = ixgbe_init_shared_code(hw); if (err) { e_err(probe, "init_shared_code failed: %d\n", err); goto out; } adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) * hw->mac.num_rar_entries, GFP_ATOMIC); /* Set capability flags */ switch (hw->mac.type) { case ixgbe_mac_82598EB: adapter->flags |= IXGBE_FLAG_MSI_CAPABLE | IXGBE_FLAG_MSIX_CAPABLE | IXGBE_FLAG_MQ_CAPABLE | IXGBE_FLAG_RSS_CAPABLE; adapter->flags |= IXGBE_FLAG_DCB_CAPABLE; #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) adapter->flags |= IXGBE_FLAG_DCA_CAPABLE; #endif adapter->flags &= ~IXGBE_FLAG_SRIOV_CAPABLE; adapter->flags2 &= ~IXGBE_FLAG2_RSC_CAPABLE; if (hw->device_id == IXGBE_DEV_ID_82598AT) adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; adapter->max_msix_q_vectors = IXGBE_MAX_MSIX_Q_VECTORS_82598; break; case ixgbe_mac_X540: adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; case ixgbe_mac_82599EB: adapter->flags |= IXGBE_FLAG_MSI_CAPABLE | IXGBE_FLAG_MSIX_CAPABLE | IXGBE_FLAG_MQ_CAPABLE | IXGBE_FLAG_RSS_CAPABLE; adapter->flags |= IXGBE_FLAG_DCB_CAPABLE; #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) adapter->flags |= IXGBE_FLAG_DCA_CAPABLE; #endif adapter->flags |= IXGBE_FLAG_SRIOV_CAPABLE; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; #ifdef IXGBE_FCOE adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE; adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; adapter->ring_feature[RING_F_FCOE].indices = 0; #ifdef CONFIG_DCB /* Default traffic class to use for FCoE */ adapter->fcoe.tc = IXGBE_FCOE_DEFTC; adapter->fcoe.up = IXGBE_FCOE_DEFTC; adapter->fcoe.up_set = IXGBE_FCOE_DEFTC; #endif #endif if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM) adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; #ifndef IXGBE_NO_SMART_SPEED hw->phy.smart_speed = ixgbe_smart_speed_on; #else hw->phy.smart_speed = ixgbe_smart_speed_off; #endif adapter->max_msix_q_vectors = IXGBE_MAX_MSIX_Q_VECTORS_82599; default: break; } /* n-tuple support exists, always init our spinlock */ //spin_lock_init(&adapter->fdir_perfect_lock); if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE) { int j; struct ixgbe_dcb_tc_config *tc; int dcb_i = IXGBE_DCB_MAX_TRAFFIC_CLASS; adapter->dcb_cfg.num_tcs.pg_tcs = dcb_i; adapter->dcb_cfg.num_tcs.pfc_tcs = dcb_i; for (j = 0; j < dcb_i; j++) { tc = &adapter->dcb_cfg.tc_config[j]; tc->path[IXGBE_DCB_TX_CONFIG].bwg_id = 0; tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = 100 / dcb_i; tc->path[IXGBE_DCB_RX_CONFIG].bwg_id = 0; tc->path[IXGBE_DCB_RX_CONFIG].bwg_percent = 100 / dcb_i; tc->pfc = ixgbe_dcb_pfc_disabled; if (j == 0) { /* total of all TCs bandwidth needs to be 100 */ tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent += 100 % dcb_i; tc->path[IXGBE_DCB_RX_CONFIG].bwg_percent += 100 % dcb_i; } } /* Initialize default user to priority mapping, UPx->TC0 */ tc = &adapter->dcb_cfg.tc_config[0]; tc->path[IXGBE_DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF; tc->path[IXGBE_DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF; adapter->dcb_cfg.bw_percentage[IXGBE_DCB_TX_CONFIG][0] = 100; adapter->dcb_cfg.bw_percentage[IXGBE_DCB_RX_CONFIG][0] = 100; adapter->dcb_cfg.rx_pba_cfg = ixgbe_dcb_pba_equal; adapter->dcb_cfg.pfc_mode_enable = false; adapter->dcb_cfg.round_robin_enable = false; adapter->dcb_set_bitmap = 0x00; #ifdef CONFIG_DCB adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE; #endif /* CONFIG_DCB */ if (hw->mac.type == ixgbe_mac_X540) { adapter->dcb_cfg.num_tcs.pg_tcs = 4; adapter->dcb_cfg.num_tcs.pfc_tcs = 4; } } #ifdef CONFIG_DCB /* XXX does this need to be initialized even w/o DCB? */ //memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, // sizeof(adapter->temp_dcb_cfg)); #endif //if (hw->mac.type == ixgbe_mac_82599EB || // hw->mac.type == ixgbe_mac_X540) // hw->mbx.ops.init_params(hw); /* default flow control settings */ hw->fc.requested_mode = ixgbe_fc_full; hw->fc.current_mode = ixgbe_fc_full; /* init for ethtool output */ adapter->last_lfc_mode = hw->fc.current_mode; ixgbe_pbthresh_setup(adapter); hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE; hw->fc.send_xon = true; hw->fc.disable_fc_autoneg = false; /* set default ring sizes */ adapter->tx_ring_count = IXGBE_DEFAULT_TXD; adapter->rx_ring_count = IXGBE_DEFAULT_RXD; /* set default work limits */ adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK; adapter->rx_work_limit = IXGBE_DEFAULT_RX_WORK; set_bit(__IXGBE_DOWN, &adapter->state); out: return err; } /** * ixgbe_setup_tx_resources - allocate Tx resources (Descriptors) * @tx_ring: tx descriptor ring (for a specific queue) to setup * * Return 0 on success, negative on failure **/ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring) { struct device *dev = tx_ring->dev; //int orig_node = dev_to_node(dev); int numa_node = -1; int size; size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; if (tx_ring->q_vector) numa_node = tx_ring->q_vector->numa_node; tx_ring->tx_buffer_info = vzalloc_node(size, numa_node); if (!tx_ring->tx_buffer_info) tx_ring->tx_buffer_info = vzalloc(size); if (!tx_ring->tx_buffer_info) goto err; /* round up to nearest 4K */ tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); tx_ring->size = ALIGN(tx_ring->size, 4096); //set_dev_node(dev, numa_node); //tx_ring->desc = dma_alloc_coherent(dev, // tx_ring->size, // &tx_ring->dma, // GFP_KERNEL); //set_dev_node(dev, orig_node); //if (!tx_ring->desc) // tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size, // &tx_ring->dma, GFP_KERNEL); //if (!tx_ring->desc) // goto err; return 0; err: vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; dev_err(dev, "Unable to allocate memory for the Tx descriptor ring\n"); return -ENOMEM; } /** * ixgbe_setup_all_tx_resources - allocate all queues Tx resources * @adapter: board private structure * * If this function returns with an error, then it's possible one or * more of the rings is populated (while the rest are not). It is the * callers duty to clean those orphaned rings. * * Return 0 on success, negative on failure **/ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { err = ixgbe_setup_tx_resources(adapter->tx_ring[i]); if (!err) continue; e_err(probe, "Allocation for Tx Queue %u failed\n", i); break; } return err; } /** * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors) * @rx_ring: rx descriptor ring (for a specific queue) to setup * * Returns 0 on success, negative on failure **/ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring) { struct device *dev = rx_ring->dev; //int orig_node = dev_to_node(dev); int numa_node = -1; int size; size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count; if (rx_ring->q_vector) numa_node = rx_ring->q_vector->numa_node; rx_ring->rx_buffer_info = vzalloc_node(size, numa_node); if (!rx_ring->rx_buffer_info) rx_ring->rx_buffer_info = vzalloc(size); if (!rx_ring->rx_buffer_info) goto err; /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); rx_ring->size = ALIGN(rx_ring->size, 4096); #ifdef NO_VNIC set_dev_node(dev, numa_node); rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); set_dev_node(dev, orig_node); if (!rx_ring->desc) rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) goto err; #ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT ixgbe_init_rx_page_offset(rx_ring); #endif #endif /* NO_VNIC */ return 0; err: vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; dev_err(dev, "Unable to allocate memory for the Rx descriptor ring\n"); return -ENOMEM; } /** * ixgbe_setup_all_rx_resources - allocate all queues Rx resources * @adapter: board private structure * * If this function returns with an error, then it's possible one or * more of the rings is populated (while the rest are not). It is the * callers duty to clean those orphaned rings. * * Return 0 on success, negative on failure **/ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { err = ixgbe_setup_rx_resources(adapter->rx_ring[i]); if (!err) continue; e_err(probe, "Allocation for Rx Queue %u failed\n", i); break; } return err; } /** * ixgbe_free_tx_resources - Free Tx Resources per Queue * @tx_ring: Tx descriptor ring for a specific queue * * Free all transmit software resources **/ void ixgbe_free_tx_resources(struct ixgbe_ring *tx_ring) { //ixgbe_clean_tx_ring(tx_ring); vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; /* if not set, then don't free */ if (!tx_ring->desc) return; //dma_free_coherent(tx_ring->dev, tx_ring->size, // tx_ring->desc, tx_ring->dma); tx_ring->desc = NULL; } /** * ixgbe_free_all_tx_resources - Free Tx Resources for All Queues * @adapter: board private structure * * Free all transmit software resources **/ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) { int i; for (i = 0; i < adapter->num_tx_queues; i++) if (adapter->tx_ring[i]->desc) ixgbe_free_tx_resources(adapter->tx_ring[i]); } /** * ixgbe_free_rx_resources - Free Rx Resources * @rx_ring: ring to clean the resources from * * Free all receive software resources **/ void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring) { //ixgbe_clean_rx_ring(rx_ring); vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; /* if not set, then don't free */ if (!rx_ring->desc) return; //dma_free_coherent(rx_ring->dev, rx_ring->size, // rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL; } /** * ixgbe_free_all_rx_resources - Free Rx Resources for All Queues * @adapter: board private structure * * Free all receive software resources **/ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) { int i; for (i = 0; i < adapter->num_rx_queues; i++) if (adapter->rx_ring[i]->desc) ixgbe_free_rx_resources(adapter->rx_ring[i]); } /** * ixgbe_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ //static int ixgbe_open(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); int err; /* disallow open during test */ if (test_bit(__IXGBE_TESTING, &adapter->state)) return -EBUSY; netif_carrier_off(netdev); /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); if (err) goto err_setup_tx; /* allocate receive descriptors */ err = ixgbe_setup_all_rx_resources(adapter); if (err) goto err_setup_rx; #ifdef NO_VNIC ixgbe_configure(adapter); err = ixgbe_request_irq(adapter); if (err) goto err_req_irq; ixgbe_up_complete(adapter); err_req_irq: #else return 0; #endif err_setup_rx: ixgbe_free_all_rx_resources(adapter); err_setup_tx: ixgbe_free_all_tx_resources(adapter); ixgbe_reset(adapter); return err; } /** * ixgbe_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the drivers control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ //static int ixgbe_close(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); //ixgbe_down(adapter); //ixgbe_free_irq(adapter); //ixgbe_fdir_filter_exit(adapter); //ixgbe_free_all_tx_resources(adapter); //ixgbe_free_all_rx_resources(adapter); ixgbe_release_hw_control(adapter); return 0; } /** * ixgbe_get_stats - Get System Network Statistics * @netdev: network interface device structure * * Returns the address of the device statistics structure. * The statistics are actually updated from the timer callback. **/ //static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); /* update the stats data */ ixgbe_update_stats(adapter); #ifdef HAVE_NETDEV_STATS_IN_NETDEV /* only return the current stats */ return &netdev->stats; #else /* only return the current stats */ return &adapter->net_stats; #endif /* HAVE_NETDEV_STATS_IN_NETDEV */ } /** * ixgbe_update_stats - Update the board statistics counters. * @adapter: board private structure **/ void ixgbe_update_stats(struct ixgbe_adapter *adapter) { #ifdef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats *net_stats = &adapter->netdev->stats; #else struct net_device_stats *net_stats = &adapter->net_stats; #endif /* HAVE_NETDEV_STATS_IN_NETDEV */ struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw_stats *hwstats = &adapter->stats; u64 total_mpc = 0; u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; u64 non_eop_descs = 0, restart_queue = 0, tx_busy = 0; u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0; u64 bytes = 0, packets = 0, hw_csum_rx_error = 0; #ifndef IXGBE_NO_LRO u32 flushed = 0, coal = 0; int num_q_vectors = 1; #endif #ifdef IXGBE_FCOE struct ixgbe_fcoe *fcoe = &adapter->fcoe; unsigned int cpu; u64 fcoe_noddp_counts_sum = 0, fcoe_noddp_ext_buff_counts_sum = 0; #endif /* IXGBE_FCOE */ printk(KERN_DEBUG "ixgbe_update_stats, tx_queues=%d, rx_queues=%d\n", adapter->num_tx_queues, adapter->num_rx_queues); if (test_bit(__IXGBE_DOWN, &adapter->state) || test_bit(__IXGBE_RESETTING, &adapter->state)) return; #ifndef IXGBE_NO_LRO if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; #endif if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { u64 rsc_count = 0; u64 rsc_flush = 0; for (i = 0; i < adapter->num_rx_queues; i++) { rsc_count += adapter->rx_ring[i]->rx_stats.rsc_count; rsc_flush += adapter->rx_ring[i]->rx_stats.rsc_flush; } adapter->rsc_total_count = rsc_count; adapter->rsc_total_flush = rsc_flush; } #ifndef IXGBE_NO_LRO for (i = 0; i < num_q_vectors; i++) { struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; if (!q_vector) continue; flushed += q_vector->lrolist.stats.flushed; coal += q_vector->lrolist.stats.coal; } adapter->lro_stats.flushed = flushed; adapter->lro_stats.coal = coal; #endif for (i = 0; i < adapter->num_rx_queues; i++) { struct ixgbe_ring *rx_ring = adapter->rx_ring[i]; non_eop_descs += rx_ring->rx_stats.non_eop_descs; alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed; alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed; hw_csum_rx_error += rx_ring->rx_stats.csum_err; bytes += rx_ring->stats.bytes; packets += rx_ring->stats.packets; } adapter->non_eop_descs = non_eop_descs; adapter->alloc_rx_page_failed = alloc_rx_page_failed; adapter->alloc_rx_buff_failed = alloc_rx_buff_failed; adapter->hw_csum_rx_error = hw_csum_rx_error; net_stats->rx_bytes = bytes; net_stats->rx_packets = packets; bytes = 0; packets = 0; /* gather some stats to the adapter struct that are per queue */ for (i = 0; i < adapter->num_tx_queues; i++) { struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; restart_queue += tx_ring->tx_stats.restart_queue; tx_busy += tx_ring->tx_stats.tx_busy; bytes += tx_ring->stats.bytes; packets += tx_ring->stats.packets; } adapter->restart_queue = restart_queue; adapter->tx_busy = tx_busy; net_stats->tx_bytes = bytes; net_stats->tx_packets = packets; hwstats->crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); /* 8 register reads */ for (i = 0; i < 8; i++) { /* for packet buffers not used, the register should read 0 */ mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i)); missed_rx += mpc; hwstats->mpc[i] += mpc; total_mpc += hwstats->mpc[i]; hwstats->pxontxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i)); hwstats->pxofftxc[i] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i)); switch (hw->mac.type) { case ixgbe_mac_82598EB: hwstats->rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i)); hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i)); hwstats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXC(i)); break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: hwstats->pxonrxc[i] += IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i)); break; default: break; } } /*16 register reads */ for (i = 0; i < 16; i++) { hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i)); hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i)); if ((hw->mac.type == ixgbe_mac_82599EB) || (hw->mac.type == ixgbe_mac_X540)) { hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */ hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i)); IXGBE_READ_REG(hw, IXGBE_QBRC_H(i)); /* to clear */ } } hwstats->gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); /* work around hardware counting issue */ hwstats->gprc -= missed_rx; ixgbe_update_xoff_received(adapter); /* 82598 hardware only has a 32 bit counter in the high register */ switch (hw->mac.type) { case ixgbe_mac_82598EB: hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORH); break; case ixgbe_mac_X540: /* OS2BMC stats are X540 only*/ hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC); hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC); hwstats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC); hwstats->b2ogprc += IXGBE_READ_REG(hw, IXGBE_B2OGPRC); case ixgbe_mac_82599EB: for (i = 0; i < 16; i++) adapter->hw_rx_no_dma_resources += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); hwstats->gorc += IXGBE_READ_REG(hw, IXGBE_GORCL); IXGBE_READ_REG(hw, IXGBE_GORCH); /* to clear */ hwstats->gotc += IXGBE_READ_REG(hw, IXGBE_GOTCL); IXGBE_READ_REG(hw, IXGBE_GOTCH); /* to clear */ hwstats->tor += IXGBE_READ_REG(hw, IXGBE_TORL); IXGBE_READ_REG(hw, IXGBE_TORH); /* to clear */ hwstats->lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT); #ifdef HAVE_TX_MQ hwstats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH); hwstats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS); #endif /* HAVE_TX_MQ */ #ifdef IXGBE_FCOE hwstats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC); hwstats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST); hwstats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC); hwstats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC); hwstats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC); hwstats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC); hwstats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC); /* Add up per cpu counters for total ddp aloc fail */ if (fcoe && fcoe->pcpu_noddp && fcoe->pcpu_noddp_ext_buff) { for_each_possible_cpu(cpu) { fcoe_noddp_counts_sum += *per_cpu_ptr(fcoe->pcpu_noddp, cpu); fcoe_noddp_ext_buff_counts_sum += *per_cpu_ptr(fcoe-> pcpu_noddp_ext_buff, cpu); } } hwstats->fcoe_noddp = fcoe_noddp_counts_sum; hwstats->fcoe_noddp_ext_buff = fcoe_noddp_ext_buff_counts_sum; #endif /* IXGBE_FCOE */ break; default: break; } bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); hwstats->bprc += bprc; hwstats->mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); if (hw->mac.type == ixgbe_mac_82598EB) hwstats->mprc -= bprc; hwstats->roc += IXGBE_READ_REG(hw, IXGBE_ROC); hwstats->prc64 += IXGBE_READ_REG(hw, IXGBE_PRC64); hwstats->prc127 += IXGBE_READ_REG(hw, IXGBE_PRC127); hwstats->prc255 += IXGBE_READ_REG(hw, IXGBE_PRC255); hwstats->prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); hwstats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); hwstats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); hwstats->rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); hwstats->lxontxc += lxon; lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); hwstats->lxofftxc += lxoff; hwstats->gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); hwstats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); /* * 82598 errata - tx of flow control packets is included in tx counters */ xon_off_tot = lxon + lxoff; hwstats->gptc -= xon_off_tot; hwstats->mptc -= xon_off_tot; hwstats->gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN)); hwstats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC); hwstats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC); hwstats->rjc += IXGBE_READ_REG(hw, IXGBE_RJC); hwstats->tpr += IXGBE_READ_REG(hw, IXGBE_TPR); hwstats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); hwstats->ptc64 -= xon_off_tot; hwstats->ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); hwstats->ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); hwstats->ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); hwstats->ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); hwstats->ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); hwstats->bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); /* Fill out the OS statistics structure */ net_stats->multicast = hwstats->mprc; /* Rx Errors */ net_stats->rx_errors = hwstats->crcerrs + hwstats->rlec; net_stats->rx_dropped = 0; net_stats->rx_length_errors = hwstats->rlec; net_stats->rx_crc_errors = hwstats->crcerrs; net_stats->rx_missed_errors = total_mpc; /* * VF Stats Collection - skip while resetting because these * are not clear on read and otherwise you'll sometimes get * crazy values. */ if (!test_bit(__IXGBE_RESETTING, &adapter->state)) { for (i = 0; i < adapter->num_vfs; i++) { UPDATE_VF_COUNTER_32bit(IXGBE_PVFGPRC(i), \ adapter->vfinfo[i].last_vfstats.gprc, \ adapter->vfinfo[i].vfstats.gprc); UPDATE_VF_COUNTER_32bit(IXGBE_PVFGPTC(i), \ adapter->vfinfo[i].last_vfstats.gptc, \ adapter->vfinfo[i].vfstats.gptc); UPDATE_VF_COUNTER_36bit(IXGBE_PVFGORC_LSB(i), \ IXGBE_PVFGORC_MSB(i), \ adapter->vfinfo[i].last_vfstats.gorc, \ adapter->vfinfo[i].vfstats.gorc); UPDATE_VF_COUNTER_36bit(IXGBE_PVFGOTC_LSB(i), \ IXGBE_PVFGOTC_MSB(i), \ adapter->vfinfo[i].last_vfstats.gotc, \ adapter->vfinfo[i].vfstats.gotc); UPDATE_VF_COUNTER_32bit(IXGBE_PVFMPRC(i), \ adapter->vfinfo[i].last_vfstats.mprc, \ adapter->vfinfo[i].vfstats.mprc); } } } #ifdef NO_VNIC /** * ixgbe_watchdog_update_link - update the link status * @adapter - pointer to the device adapter structure * @link_speed - pointer to a u32 to store the link_speed **/ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = adapter->link_speed; bool link_up = adapter->link_up; bool pfc_en = adapter->dcb_cfg.pfc_mode_enable; if (!(adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)) return; if (hw->mac.ops.check_link) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); } else { /* always assume link is up, if no check link function */ link_speed = IXGBE_LINK_SPEED_10GB_FULL; link_up = true; } #ifdef HAVE_DCBNL_IEEE if (adapter->ixgbe_ieee_pfc) pfc_en |= !!(adapter->ixgbe_ieee_pfc->pfc_en); #endif if (link_up && !((adapter->flags & IXGBE_FLAG_DCB_ENABLED) && pfc_en)) { hw->mac.ops.fc_enable(hw); //ixgbe_set_rx_drop_en(adapter); } if (link_up || time_after(jiffies, (adapter->link_check_timeout + IXGBE_TRY_LINK_TIMEOUT))) { adapter->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE; IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMC_LSC); IXGBE_WRITE_FLUSH(hw); } adapter->link_up = link_up; adapter->link_speed = link_speed; } #endif #ifdef NO_VNIC /** * ixgbe_service_task - manages and runs subtasks * @work: pointer to work_struct containing our data **/ static void ixgbe_service_task(struct work_struct *work) { //struct ixgbe_adapter *adapter = container_of(work, // struct ixgbe_adapter, // service_task); //ixgbe_reset_subtask(adapter); //ixgbe_sfp_detection_subtask(adapter); //ixgbe_sfp_link_config_subtask(adapter); //ixgbe_check_overtemp_subtask(adapter); //ixgbe_watchdog_subtask(adapter); #ifdef HAVE_TX_MQ //ixgbe_fdir_reinit_subtask(adapter); #endif //ixgbe_check_hang_subtask(adapter); //ixgbe_service_event_complete(adapter); } #define IXGBE_TXD_CMD (IXGBE_TXD_CMD_EOP | \ IXGBE_TXD_CMD_RS) /** * ixgbe_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure **/ static int ixgbe_set_mac(struct net_device *netdev, void *p) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; struct sockaddr *addr = p; int ret; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; ixgbe_del_mac_filter(adapter, hw->mac.addr, adapter->num_vfs); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); /* set the correct pool for the new PF MAC address in entry 0 */ ret = ixgbe_add_mac_filter(adapter, hw->mac.addr, adapter->num_vfs); return (ret > 0 ? 0 : ret); } /** * ixgbe_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { #ifdef ETHTOOL_OPS_COMPAT case SIOCETHTOOL: return ethtool_ioctl(ifr); #endif default: return -EOPNOTSUPP; } } #endif /* NO_VNIC */ void ixgbe_do_reset(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); if (netif_running(netdev)) ixgbe_reinit_locked(adapter); else ixgbe_reset(adapter); } /** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in ixgbe_pci_tbl * * Returns 0 on success, negative on failure * * ixgbe_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/ //static int ixgbe_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev) { size_t count; struct net_device *netdev; struct ixgbe_adapter *adapter = NULL; struct ixgbe_hw *hw = NULL; static int cards_found; int i, err; u16 offset; u16 eeprom_verh, eeprom_verl, eeprom_cfg_blkh, eeprom_cfg_blkl; u32 etrack_id; u16 build, major, patch; char *info_string, *i_s_var; u8 part_str[IXGBE_PBANUM_LENGTH]; enum ixgbe_mac_type mac_type = ixgbe_mac_unknown; #ifdef HAVE_TX_MQ unsigned int indices = num_possible_cpus(); #endif /* HAVE_TX_MQ */ #ifdef IXGBE_FCOE u16 device_caps; #endif u16 wol_cap; err = pci_enable_device_mem(pdev); if (err) return err; #ifdef NO_VNIC err = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), ixgbe_driver_name); if (err) { dev_err(pci_dev_to_dev(pdev), "pci_request_selected_regions failed 0x%x\n", err); goto err_pci_reg; } #endif /* * The mac_type is needed before we have the adapter is set up * so rather than maintain two devID -> MAC tables we dummy up * an ixgbe_hw stuct and use ixgbe_set_mac_type. */ hw = vmalloc(sizeof(struct ixgbe_hw)); if (!hw) { pr_info("Unable to allocate memory for early mac " "check\n"); } else { hw->vendor_id = pdev->vendor; hw->device_id = pdev->device; ixgbe_set_mac_type(hw); mac_type = hw->mac.type; vfree(hw); } #ifdef NO_VNIC /* * Workaround of Silicon errata on 82598. Disable LOs in the PCI switch * port to which the 82598 is connected to prevent duplicate * completions caused by LOs. We need the mac type so that we only * do this on 82598 devices, ixgbe_set_mac_type does this for us if * we set it's device ID. */ if (mac_type == ixgbe_mac_82598EB) pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); pci_enable_pcie_error_reporting(pdev); pci_set_master(pdev); #endif #ifdef HAVE_TX_MQ #ifdef CONFIG_DCB #ifdef HAVE_MQPRIO indices *= IXGBE_DCB_MAX_TRAFFIC_CLASS; #else indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES); #endif /* HAVE_MQPRIO */ #endif /* CONFIG_DCB */ if (mac_type == ixgbe_mac_82598EB) indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES); else indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES); #ifdef IXGBE_FCOE indices += min_t(unsigned int, num_possible_cpus(), IXGBE_MAX_FCOE_INDICES); #endif netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices); #else /* HAVE_TX_MQ */ netdev = alloc_etherdev(sizeof(struct ixgbe_adapter)); #endif /* HAVE_TX_MQ */ if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; } SET_NETDEV_DEV(netdev, &pdev->dev); adapter = netdev_priv(netdev); //pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; adapter->pdev = pdev; hw = &adapter->hw; hw->back = adapter; adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; #ifdef HAVE_PCI_ERS /* * call save state here in standalone driver because it relies on * adapter struct to exist, and needs to call netdev_priv */ pci_save_state(pdev); #endif hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!hw->hw_addr) { err = -EIO; goto err_ioremap; } //ixgbe_assign_netdev_ops(netdev); ixgbe_set_ethtool_ops(netdev); strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); adapter->bd_number = cards_found; /* setup the private structure */ err = ixgbe_sw_init(adapter); if (err) goto err_sw_init; /* Make it possible the adapter to be woken up via WOL */ switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); break; default: break; } /* * check_options must be called before setup_link to set up * hw->fc completely */ //ixgbe_check_options(adapter); #ifndef NO_VNIC /* reset_hw fills in the perm_addr as well */ hw->phy.reset_if_overtemp = true; err = hw->mac.ops.reset_hw(hw); hw->phy.reset_if_overtemp = false; if (err == IXGBE_ERR_SFP_NOT_PRESENT && hw->mac.type == ixgbe_mac_82598EB) { err = 0; } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { e_dev_err("failed to load because an unsupported SFP+ " "module type was detected.\n"); e_dev_err("Reload the driver after installing a supported " "module.\n"); goto err_sw_init; } else if (err) { e_dev_err("HW Init failed: %d\n", err); goto err_sw_init; } #endif //if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) // ixgbe_probe_vf(adapter); #ifdef MAX_SKB_FRAGS netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; #ifdef NETIF_F_IPV6_CSUM netdev->features |= NETIF_F_IPV6_CSUM; #endif #ifdef NETIF_F_HW_VLAN_TX netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif #ifdef NETIF_F_TSO netdev->features |= NETIF_F_TSO; #endif /* NETIF_F_TSO */ #ifdef NETIF_F_TSO6 netdev->features |= NETIF_F_TSO6; #endif /* NETIF_F_TSO6 */ #ifdef NETIF_F_RXHASH netdev->features |= NETIF_F_RXHASH; #endif /* NETIF_F_RXHASH */ #ifdef HAVE_NDO_SET_FEATURES netdev->features |= NETIF_F_RXCSUM; /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; /* give us the option of enabling RSC/LRO later */ #ifdef IXGBE_NO_LRO if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) #endif netdev->hw_features |= NETIF_F_LRO; #else #ifdef NETIF_F_GRO /* this is only needed on kernels prior to 2.6.39 */ netdev->features |= NETIF_F_GRO; #endif /* NETIF_F_GRO */ #endif #ifdef NETIF_F_HW_VLAN_TX /* set this bit last since it cannot be part of hw_features */ netdev->features |= NETIF_F_HW_VLAN_FILTER; #endif switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: netdev->features |= NETIF_F_SCTP_CSUM; #ifdef HAVE_NDO_SET_FEATURES netdev->hw_features |= NETIF_F_SCTP_CSUM | NETIF_F_NTUPLE; #endif break; default: break; } #ifdef HAVE_NETDEV_VLAN_FEATURES netdev->vlan_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6; #endif /* HAVE_NETDEV_VLAN_FEATURES */ /* * If perfect filters were enabled in check_options(), enable them * on the netdevice too. */ if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) netdev->features |= NETIF_F_NTUPLE; if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED) { adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; /* clear n-tuple support in the netdev unconditionally */ netdev->features &= ~NETIF_F_NTUPLE; } #ifdef NETIF_F_RXHASH if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) netdev->features &= ~NETIF_F_RXHASH; #endif /* NETIF_F_RXHASH */ if (netdev->features & NETIF_F_LRO) { if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) && ((adapter->rx_itr_setting == 1) || (adapter->rx_itr_setting > IXGBE_MIN_RSC_ITR))) { adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; } else if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) { #ifdef IXGBE_NO_LRO e_info(probe, "InterruptThrottleRate set too high, " "disabling RSC\n"); #else e_info(probe, "InterruptThrottleRate set too high, " "falling back to software LRO\n"); #endif } } #ifdef CONFIG_DCB //netdev->dcbnl_ops = &dcbnl_ops; #endif #ifdef IXGBE_FCOE #ifdef NETIF_F_FSO if (adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) { ixgbe_get_device_caps(hw, &device_caps); if (device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS) { adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE; e_info(probe, "FCoE offload feature is not available. " "Disabling FCoE offload feature\n"); } #ifndef HAVE_NETDEV_OPS_FCOE_ENABLE else { adapter->flags |= IXGBE_FLAG_FCOE_ENABLED; adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE; netdev->features |= NETIF_F_FSO | NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU; netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1; } #endif /* HAVE_NETDEV_OPS_FCOE_ENABLE */ #ifdef HAVE_NETDEV_VLAN_FEATURES netdev->vlan_features |= NETIF_F_FSO | NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU; #endif /* HAVE_NETDEV_VLAN_FEATURES */ } #endif /* NETIF_F_FSO */ #endif /* IXGBE_FCOE */ #endif /* MAX_SKB_FRAGS */ /* make sure the EEPROM is good */ if (hw->eeprom.ops.validate_checksum && (hw->eeprom.ops.validate_checksum(hw, NULL) < 0)) { e_dev_err("The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_sw_init; } memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len); #ifdef ETHTOOL_GPERMADDR memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len); if (ixgbe_validate_mac_addr(netdev->perm_addr)) { e_dev_err("invalid MAC address\n"); err = -EIO; goto err_sw_init; } #else if (ixgbe_validate_mac_addr(netdev->dev_addr)) { e_dev_err("invalid MAC address\n"); err = -EIO; goto err_sw_init; } #endif memcpy(&adapter->mac_table[0].addr, hw->mac.perm_addr, netdev->addr_len); adapter->mac_table[0].queue = adapter->num_vfs; adapter->mac_table[0].state = (IXGBE_MAC_STATE_DEFAULT | IXGBE_MAC_STATE_IN_USE); hw->mac.ops.set_rar(hw, 0, adapter->mac_table[0].addr, adapter->mac_table[0].queue, IXGBE_RAH_AV); //setup_timer(&adapter->service_timer, &ixgbe_service_timer, // (unsigned long) adapter); //INIT_WORK(&adapter->service_task, ixgbe_service_task); //clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); //err = ixgbe_init_interrupt_scheme(adapter); //if (err) // goto err_sw_init; //adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; ixgbe_set_num_queues(adapter); adapter->wol = 0; /* WOL not supported for all but the following */ switch (pdev->device) { case IXGBE_DEV_ID_82599_SFP: /* Only these subdevice supports WOL */ switch (pdev->subsystem_device) { case IXGBE_SUBDEV_ID_82599_560FLR: /* only support first port */ if (hw->bus.func != 0) break; case IXGBE_SUBDEV_ID_82599_SFP: adapter->wol = IXGBE_WUFC_MAG; break; } break; case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: /* All except this subdevice support WOL */ if (pdev->subsystem_device != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ) adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_82599_KX4: adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_X540T: /* Check eeprom to see if it is enabled */ ixgbe_read_eeprom(hw, 0x2c, &adapter->eeprom_cap); wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK; if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && (hw->bus.func == 0))) adapter->wol = IXGBE_WUFC_MAG; break; } //device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); /* * Save off EEPROM version number and Option Rom version which * together make a unique identify for the eeprom */ ixgbe_read_eeprom(hw, 0x2e, &eeprom_verh); ixgbe_read_eeprom(hw, 0x2d, &eeprom_verl); etrack_id = (eeprom_verh << 16) | eeprom_verl; ixgbe_read_eeprom(hw, 0x17, &offset); /* Make sure offset to SCSI block is valid */ if (!(offset == 0x0) && !(offset == 0xffff)) { ixgbe_read_eeprom(hw, offset + 0x84, &eeprom_cfg_blkh); ixgbe_read_eeprom(hw, offset + 0x83, &eeprom_cfg_blkl); /* Only display Option Rom if exist */ if (eeprom_cfg_blkl && eeprom_cfg_blkh) { major = eeprom_cfg_blkl >> 8; build = (eeprom_cfg_blkl << 8) | (eeprom_cfg_blkh >> 8); patch = eeprom_cfg_blkh & 0x00ff; snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id), "0x%08x, %d.%d.%d", etrack_id, major, build, patch); } else { snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id), "0x%08x", etrack_id); } } else { snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id), "0x%08x", etrack_id); } /* reset the hardware with the new settings */ err = hw->mac.ops.start_hw(hw); if (err == IXGBE_ERR_EEPROM_VERSION) { /* We are running on a pre-production device, log a warning */ e_dev_warn("This device is a pre-production adapter/LOM. " "Please be aware there may be issues associated " "with your hardware. If you are experiencing " "problems please contact your Intel or hardware " "representative who provided you with this " "hardware.\n"); } /* pick up the PCI bus settings for reporting later */ if (hw->mac.ops.get_bus_info) hw->mac.ops.get_bus_info(hw); strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); *lad_dev = netdev; adapter->netdev_registered = true; #ifdef NO_VNIC /* power down the optics */ if ((hw->phy.multispeed_fiber) || ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) && (hw->mac.type == ixgbe_mac_82599EB))) ixgbe_disable_tx_laser(hw); /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); /* keep stopping all the transmit queues for older kernels */ netif_tx_stop_all_queues(netdev); #endif /* print all messages at the end so that we use our eth%d name */ /* print bus type/speed/width info */ e_dev_info("(PCI Express:%s:%s) ", (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" : hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" : "Unknown"), (hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" : hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" : hw->bus.width == ixgbe_bus_width_pcie_x1 ? "Width x1" : "Unknown")); /* print the MAC address */ for (i = 0; i < 6; i++) pr_cont("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':'); /* First try to read PBA as a string */ err = ixgbe_read_pba_string(hw, part_str, IXGBE_PBANUM_LENGTH); if (err) strlcpy(part_str, "Unknown", sizeof(part_str)); if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present) e_info(probe, "MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n", hw->mac.type, hw->phy.type, hw->phy.sfp_type, part_str); else e_info(probe, "MAC: %d, PHY: %d, PBA No: %s\n", hw->mac.type, hw->phy.type, part_str); if (((hw->bus.speed == ixgbe_bus_speed_2500) && (hw->bus.width <= ixgbe_bus_width_pcie_x4)) || (hw->bus.width <= ixgbe_bus_width_pcie_x2)) { e_dev_warn("PCI-Express bandwidth available for this " "card is not sufficient for optimal " "performance.\n"); e_dev_warn("For optimal performance a x8 PCI-Express " "slot is required.\n"); } #define INFO_STRING_LEN 255 info_string = kzalloc(INFO_STRING_LEN, GFP_KERNEL); if (!info_string) { e_err(probe, "allocation for info string failed\n"); goto no_info_string; } count = 0; i_s_var = info_string; count += snprintf(i_s_var, INFO_STRING_LEN, "Enabled Features: "); i_s_var = info_string + count; count += snprintf(i_s_var, (INFO_STRING_LEN - count), "RxQ: %d TxQ: %d ", adapter->num_rx_queues, adapter->num_tx_queues); i_s_var = info_string + count; #ifdef IXGBE_FCOE if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "FCoE "); i_s_var = info_string + count; } #endif if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "FdirHash "); i_s_var = info_string + count; } if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "FdirPerfect "); i_s_var = info_string + count; } if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "DCB "); i_s_var = info_string + count; } if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "RSS "); i_s_var = info_string + count; } if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "DCA "); i_s_var = info_string + count; } if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "RSC "); i_s_var = info_string + count; } #ifndef IXGBE_NO_LRO else if (netdev->features & NETIF_F_LRO) { count += snprintf(i_s_var, INFO_STRING_LEN - count, "LRO "); i_s_var = info_string + count; } #endif BUG_ON(i_s_var > (info_string + INFO_STRING_LEN)); /* end features printing */ e_info(probe, "%s\n", info_string); kfree(info_string); no_info_string: /* firmware requires blank driver version */ ixgbe_set_fw_drv_ver(hw, 0xFF, 0xFF, 0xFF, 0xFF); #if defined(HAVE_NETDEV_STORAGE_ADDRESS) && defined(NETDEV_HW_ADDR_T_SAN) /* add san mac addr to netdev */ //ixgbe_add_sanmac_netdev(netdev); #endif /* (HAVE_NETDEV_STORAGE_ADDRESS) && (NETDEV_HW_ADDR_T_SAN) */ e_info(probe, "Intel(R) 10 Gigabit Network Connection\n"); cards_found++; #ifdef IXGBE_SYSFS //if (ixgbe_sysfs_init(adapter)) // e_err(probe, "failed to allocate sysfs resources\n"); #else #ifdef IXGBE_PROCFS //if (ixgbe_procfs_init(adapter)) // e_err(probe, "failed to allocate procfs resources\n"); #endif /* IXGBE_PROCFS */ #endif /* IXGBE_SYSFS */ return 0; //err_register: //ixgbe_clear_interrupt_scheme(adapter); //ixgbe_release_hw_control(adapter); err_sw_init: adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; if (adapter->mac_table) kfree(adapter->mac_table); iounmap(hw->hw_addr); err_ioremap: free_netdev(netdev); err_alloc_etherdev: //pci_release_selected_regions(pdev, // pci_select_bars(pdev, IORESOURCE_MEM)); //err_pci_reg: //err_dma: pci_disable_device(pdev); return err; } /** * ixgbe_remove - Device Removal Routine * @pdev: PCI device information struct * * ixgbe_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. The could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory. **/ void ixgbe_kni_remove(struct pci_dev *pdev) { pci_disable_device(pdev); } u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg) { u16 value; struct ixgbe_adapter *adapter = hw->back; pci_read_config_word(adapter->pdev, reg, &value); return value; } void ixgbe_write_pci_cfg_word(struct ixgbe_hw *hw, u32 reg, u16 value) { struct ixgbe_adapter *adapter = hw->back; pci_write_config_word(adapter->pdev, reg, value); } void ewarn(struct ixgbe_hw *hw, const char *st, u32 status) { struct ixgbe_adapter *adapter = hw->back; netif_warn(adapter, drv, adapter->netdev, "%s", st); } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_mbx.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_MBX_H_ #define _IXGBE_MBX_H_ #include "ixgbe_type.h" #define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ #define IXGBE_ERR_MBX -100 #define IXGBE_VFMAILBOX 0x002FC #define IXGBE_VFMBMEM 0x00200 /* Define mailbox register bits */ #define IXGBE_VFMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ #define IXGBE_VFMAILBOX_ACK 0x00000002 /* Ack PF message received */ #define IXGBE_VFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define IXGBE_VFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define IXGBE_VFMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ #define IXGBE_VFMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ #define IXGBE_VFMAILBOX_RSTI 0x00000040 /* PF has reset indication */ #define IXGBE_VFMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */ #define IXGBE_VFMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */ #define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */ #define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ #define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ #define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ #define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ #define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ #define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ #define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ #define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ /* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the * PF. The reverse is true if it is IXGBE_PF_*. * Message ACK's are the value or'd with 0xF0000000 */ #define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with * this are the ACK */ #define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with * this are the NACK */ #define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still * clear to send requests */ #define IXGBE_VT_MSGINFO_SHIFT 16 /* bits 23:16 are used for extra info for certain messages */ #define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) #define IXGBE_VF_RESET 0x01 /* VF requests reset */ #define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ #define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 /* word in permanent address message with the current multicast type */ #define IXGBE_VF_MC_TYPE_WORD 3 #define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */ #define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ #define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16); s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); void ixgbe_init_mbx_params_vf(struct ixgbe_hw *); void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); #endif /* _IXGBE_MBX_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_osdep.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ /* glue for the OS independent part of ixgbe * includes register access macros */ #ifndef _IXGBE_OSDEP_H_ #define _IXGBE_OSDEP_H_ #include #include #include #include #include #include "kcompat.h" #ifndef msleep #define msleep(x) do { if (in_interrupt()) { \ /* Don't mdelay in interrupt context! */ \ BUG(); \ } else { \ msleep(x); \ } } while (0) #endif #undef ASSERT #ifdef DBG #define hw_dbg(hw, S, A...) printk(KERN_DEBUG S, ## A) #else #define hw_dbg(hw, S, A...) do {} while (0) #endif #define e_dev_info(format, arg...) \ dev_info(pci_dev_to_dev(adapter->pdev), format, ## arg) #define e_dev_warn(format, arg...) \ dev_warn(pci_dev_to_dev(adapter->pdev), format, ## arg) #define e_dev_err(format, arg...) \ dev_err(pci_dev_to_dev(adapter->pdev), format, ## arg) #define e_dev_notice(format, arg...) \ dev_notice(pci_dev_to_dev(adapter->pdev), format, ## arg) #define e_info(msglvl, format, arg...) \ netif_info(adapter, msglvl, adapter->netdev, format, ## arg) #define e_err(msglvl, format, arg...) \ netif_err(adapter, msglvl, adapter->netdev, format, ## arg) #define e_warn(msglvl, format, arg...) \ netif_warn(adapter, msglvl, adapter->netdev, format, ## arg) #define e_crit(msglvl, format, arg...) \ netif_crit(adapter, msglvl, adapter->netdev, format, ## arg) #ifdef DBG #define IXGBE_WRITE_REG(a, reg, value) do {\ switch (reg) { \ case IXGBE_EIMS: \ case IXGBE_EIMC: \ case IXGBE_EIAM: \ case IXGBE_EIAC: \ case IXGBE_EICR: \ case IXGBE_EICS: \ printk("%s: Reg - 0x%05X, value - 0x%08X\n", __func__, \ reg, (u32)(value)); \ default: \ break; \ } \ writel((value), ((a)->hw_addr + (reg))); \ } while (0) #else #define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg))) #endif #define IXGBE_READ_REG(a, reg) readl((a)->hw_addr + (reg)) #define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) ( \ writel((value), ((a)->hw_addr + (reg) + ((offset) << 2)))) #define IXGBE_READ_REG_ARRAY(a, reg, offset) ( \ readl((a)->hw_addr + (reg) + ((offset) << 2))) #ifndef writeq #define writeq(val, addr) do { writel((u32) (val), addr); \ writel((u32) (val >> 32), (addr + 4)); \ } while (0); #endif #define IXGBE_WRITE_REG64(a, reg, value) writeq((value), ((a)->hw_addr + (reg))) #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS) struct ixgbe_hw; extern u16 ixgbe_read_pci_cfg_word(struct ixgbe_hw *hw, u32 reg); extern void ixgbe_write_pci_cfg_word(struct ixgbe_hw *hw, u32 reg, u16 value); extern void ewarn(struct ixgbe_hw *hw, const char *str, u32 status); #define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg_word #define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg_word #define IXGBE_EEPROM_GRANT_ATTEMPS 100 #define IXGBE_HTONL(_i) htonl(_i) #define IXGBE_NTOHL(_i) ntohl(_i) #define IXGBE_NTOHS(_i) ntohs(_i) #define IXGBE_CPU_TO_LE32(_i) cpu_to_le32(_i) #define IXGBE_LE32_TO_CPUS(_i) le32_to_cpus(_i) #define EWARN(H, W, S) ewarn(H, W, S) #endif /* _IXGBE_OSDEP_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_phy.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" static void ixgbe_i2c_start(struct ixgbe_hw *hw); static void ixgbe_i2c_stop(struct ixgbe_hw *hw); static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data); static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data); static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw); static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data); static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data); static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl); static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data); static bool ixgbe_get_i2c_data(u32 *i2cctl); /** * ixgbe_init_phy_ops_generic - Inits PHY function ptrs * @hw: pointer to the hardware structure * * Initialize the function pointers. **/ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw) { struct ixgbe_phy_info *phy = &hw->phy; /* PHY */ phy->ops.identify = &ixgbe_identify_phy_generic; phy->ops.reset = &ixgbe_reset_phy_generic; phy->ops.read_reg = &ixgbe_read_phy_reg_generic; phy->ops.write_reg = &ixgbe_write_phy_reg_generic; phy->ops.setup_link = &ixgbe_setup_phy_link_generic; phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic; phy->ops.check_link = NULL; phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic; phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic; phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic; phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic; phy->ops.write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic; phy->ops.i2c_bus_clear = &ixgbe_i2c_bus_clear; phy->ops.identify_sfp = &ixgbe_identify_module_generic; phy->sfp_type = ixgbe_sfp_type_unknown; phy->ops.check_overtemp = &ixgbe_tn_check_overtemp; return 0; } /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure * * Determines the physical layer module found on the current adapter. **/ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 phy_addr; u16 ext_ability = 0; if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { if (ixgbe_validate_phy_addr(hw, phy_addr)) { hw->phy.addr = phy_addr; ixgbe_get_phy_id(hw); hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id); if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & (IXGBE_MDIO_PHY_10GBASET_ABILITY | IXGBE_MDIO_PHY_1000BASET_ABILITY)) hw->phy.type = ixgbe_phy_cu_unknown; else hw->phy.type = ixgbe_phy_generic; } status = 0; break; } } /* clear value if nothing found */ if (status != 0) hw->phy.addr = 0; } else { status = 0; } return status; } /** * ixgbe_validate_phy_addr - Determines phy address is valid * @hw: pointer to hardware structure * **/ bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr) { u16 phy_id = 0; bool valid = false; hw->phy.addr = phy_addr; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); if (phy_id != 0xFFFF && phy_id != 0x0) valid = true; return valid; } /** * ixgbe_get_phy_id - Get the phy type * @hw: pointer to hardware structure * **/ s32 ixgbe_get_phy_id(struct ixgbe_hw *hw) { u32 status; u16 phy_id_high = 0; u16 phy_id_low = 0; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_high); if (status == 0) { hw->phy.id = (u32)(phy_id_high << 16); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_LOW, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_low); hw->phy.id |= (u32)(phy_id_low & IXGBE_PHY_REVISION_MASK); hw->phy.revision = (u32)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); } return status; } /** * ixgbe_get_phy_type_from_id - Get the phy type * @hw: pointer to hardware structure * **/ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) { enum ixgbe_phy_type phy_type; switch (phy_id) { case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; break; case X540_PHY_ID: phy_type = ixgbe_phy_aq; break; case QT2022_PHY_ID: phy_type = ixgbe_phy_qt; break; case ATH_PHY_ID: phy_type = ixgbe_phy_nl; break; default: phy_type = ixgbe_phy_unknown; break; } hw_dbg(hw, "phy type found is %d\n", phy_type); return phy_type; } /** * ixgbe_reset_phy_generic - Performs a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) { u32 i; u16 ctrl = 0; s32 status = 0; if (hw->phy.type == ixgbe_phy_unknown) status = ixgbe_identify_phy_generic(hw); if (status != 0 || hw->phy.type == ixgbe_phy_none) goto out; /* Don't reset PHY if it's shut down due to overtemp. */ if (!hw->phy.reset_if_overtemp && (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw))) goto out; /* * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY */ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, IXGBE_MDIO_PHY_XS_RESET); /* * Poll for reset bit to self-clear indicating reset is complete. * Some PHYs could take up to 3 seconds to complete and need about * 1.7 usec delay after the reset is complete. */ for (i = 0; i < 30; i++) { msleep(100); hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl); if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET)) { udelay(2); break; } } if (ctrl & IXGBE_MDIO_PHY_XS_RESET) { status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "PHY reset polling failed to complete.\n"); } out: return status; } /** * ixgbe_read_phy_reg_generic - Reads a value from a specified PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit address of PHY register to read * @phy_data: Pointer to read data from PHY register **/ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data) { u32 command; u32 i; u32 data; s32 status = 0; u16 gssr; if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else gssr = IXGBE_GSSR_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0) status = IXGBE_ERR_SWFW_SYNC; if (status == 0) { /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle completed. * The MDI Command bit will clear when the operation is * complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { hw_dbg(hw, "PHY address command did not complete.\n"); status = IXGBE_ERR_PHY; } if (status == 0) { /* * Address cycle complete, setup and write the read * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle * completed. The MDI Command bit will clear when the * operation is complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { hw_dbg(hw, "PHY read command didn't complete\n"); status = IXGBE_ERR_PHY; } else { /* * Read operation is complete. Get the data * from MSRWD */ data = IXGBE_READ_REG(hw, IXGBE_MSRWD); data >>= IXGBE_MSRWD_READ_DATA_SHIFT; *phy_data = (u16)(data); } } hw->mac.ops.release_swfw_sync(hw, gssr); } return status; } /** * ixgbe_write_phy_reg_generic - Writes a value to specified PHY register * @hw: pointer to hardware structure * @reg_addr: 32 bit PHY register to write * @device_type: 5 bit device type * @phy_data: Data to write to the PHY register **/ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data) { u32 command; u32 i; s32 status = 0; u16 gssr; if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else gssr = IXGBE_GSSR_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0) status = IXGBE_ERR_SWFW_SYNC; if (status == 0) { /* Put the data in the MDI single read and write data register*/ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); /* Setup and write the address cycle command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle completed. * The MDI Command bit will clear when the operation is * complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { hw_dbg(hw, "PHY address cmd didn't complete\n"); status = IXGBE_ERR_PHY; } if (status == 0) { /* * Address cycle complete, setup and write the write * command */ command = ((reg_addr << IXGBE_MSCA_NP_ADDR_SHIFT) | (device_type << IXGBE_MSCA_DEV_TYPE_SHIFT) | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | (IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND)); IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); /* * Check every 10 usec to see if the address cycle * completed. The MDI Command bit will clear when the * operation is complete */ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { udelay(10); command = IXGBE_READ_REG(hw, IXGBE_MSCA); if ((command & IXGBE_MSCA_MDI_COMMAND) == 0) break; } if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) { hw_dbg(hw, "PHY address cmd didn't complete\n"); status = IXGBE_ERR_PHY; } } hw->mac.ops.release_swfw_sync(hw, gssr); } return status; } /** * ixgbe_setup_phy_link_generic - Set and restart autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) { s32 status = 0; u32 time_out; u32 max_time_out = 10; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; bool autoneg = false; ixgbe_link_speed speed; ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); if (speed & IXGBE_LINK_SPEED_10GB_FULL) { /* Set or unset auto-negotiation 10G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { /* Set or unset auto-negotiation 1G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_100_FULL) { /* Set or unset auto-negotiation 100M advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~(IXGBE_MII_100BASE_T_ADVERTISE | IXGBE_MII_100BASE_T_ADVERTISE_HALF); if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } /* Restart PHY autonegotiation and wait for completion */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg |= IXGBE_MII_RESTART; hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); /* Wait for autonegotiation to finish */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); /* Restart PHY autonegotiation and wait for completion */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) break; } if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out"); } return status; } /** * ixgbe_setup_phy_link_speed_generic - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled **/ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { /* * Clear autoneg_advertised and set new values based on input link * speed. */ hw->phy.autoneg_advertised = 0; if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; if (speed & IXGBE_LINK_SPEED_100_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; /* Setup link based on the new speed settings */ hw->phy.ops.setup_link(hw); return 0; } /** * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the link capabilities by reading the AUTOC register. **/ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = IXGBE_ERR_LINK_SETUP; u16 speed_ability; *speed = 0; *autoneg = true; status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &speed_ability); if (status == 0) { if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) *speed |= IXGBE_LINK_SPEED_1GB_FULL; if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M) *speed |= IXGBE_LINK_SPEED_100_FULL; } return status; } /** * ixgbe_check_phy_link_tnx - Determine link and speed status * @hw: pointer to hardware structure * * Reads the VS1 register to determine if link is up and the current speed for * the PHY. **/ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up) { s32 status = 0; u32 time_out; u32 max_time_out = 10; u16 phy_link = 0; u16 phy_speed = 0; u16 phy_data = 0; /* Initialize speed and link to default case */ *link_up = false; *speed = IXGBE_LINK_SPEED_10GB_FULL; /* * Check current speed and link status of the PHY register. * This is a vendor specific register and may have to * be changed for other copper PHYs. */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); phy_link = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; phy_speed = phy_data & IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { *link_up = true; if (phy_speed == IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) *speed = IXGBE_LINK_SPEED_1GB_FULL; break; } } return status; } /** * ixgbe_setup_phy_link_tnx - Set and restart autoneg * @hw: pointer to hardware structure * * Restart autonegotiation and PHY and waits for completion. **/ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) { s32 status = 0; u32 time_out; u32 max_time_out = 10; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; bool autoneg = false; ixgbe_link_speed speed; ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); if (speed & IXGBE_LINK_SPEED_10GB_FULL) { /* Set or unset auto-negotiation 10G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_1GB_FULL) { /* Set or unset auto-negotiation 1G advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } if (speed & IXGBE_LINK_SPEED_100_FULL) { /* Set or unset auto-negotiation 100M advertisement */ hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); } /* Restart PHY autonegotiation and wait for completion */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg |= IXGBE_MII_RESTART; hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); /* Wait for autonegotiation to finish */ for (time_out = 0; time_out < max_time_out; time_out++) { udelay(10); /* Restart PHY autonegotiation and wait for completion */ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) break; } if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out"); } return status; } /** * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version **/ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status = 0; status = hw->phy.ops.read_reg(hw, TNX_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); return status; } /** * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version **/ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version) { s32 status = 0; status = hw->phy.ops.read_reg(hw, AQ_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); return status; } /** * ixgbe_reset_phy_nl - Performs a PHY reset * @hw: pointer to hardware structure **/ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw) { u16 phy_offset, control, eword, edata, block_crc; bool end_data = false; u16 list_offset, data_offset; u16 phy_data = 0; s32 ret_val = 0; u32 i; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); /* reset the PHY and poll for completion */ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, (phy_data | IXGBE_MDIO_PHY_XS_RESET)); for (i = 0; i < 100; i++) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0) break; msleep(10); } if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) { hw_dbg(hw, "PHY reset did not complete.\n"); ret_val = IXGBE_ERR_PHY; goto out; } /* Get init offsets */ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset, &data_offset); if (ret_val != 0) goto out; ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc); data_offset++; while (!end_data) { /* * Read control word from PHY init contents offset */ ret_val = hw->eeprom.ops.read(hw, data_offset, &eword); control = (eword & IXGBE_CONTROL_MASK_NL) >> IXGBE_CONTROL_SHIFT_NL; edata = eword & IXGBE_DATA_MASK_NL; switch (control) { case IXGBE_DELAY_NL: data_offset++; hw_dbg(hw, "DELAY: %d MS\n", edata); msleep(edata); break; case IXGBE_DATA_NL: hw_dbg(hw, "DATA:\n"); data_offset++; hw->eeprom.ops.read(hw, data_offset++, &phy_offset); for (i = 0; i < edata; i++) { hw->eeprom.ops.read(hw, data_offset, &eword); hw->phy.ops.write_reg(hw, phy_offset, IXGBE_TWINAX_DEV, eword); hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword, phy_offset); data_offset++; phy_offset++; } break; case IXGBE_CONTROL_NL: data_offset++; hw_dbg(hw, "CONTROL:\n"); if (edata == IXGBE_CONTROL_EOL_NL) { hw_dbg(hw, "EOL\n"); end_data = true; } else if (edata == IXGBE_CONTROL_SOL_NL) { hw_dbg(hw, "SOL\n"); } else { hw_dbg(hw, "Bad control value\n"); ret_val = IXGBE_ERR_PHY; goto out; } break; default: hw_dbg(hw, "Bad control type\n"); ret_val = IXGBE_ERR_PHY; goto out; } } out: return ret_val; } /** * ixgbe_identify_module_generic - Identifies module type * @hw: pointer to hardware structure * * Determines HW type and calls appropriate function. **/ s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_SFP_NOT_PRESENT; switch (hw->mac.ops.get_media_type(hw)) { case ixgbe_media_type_fiber: status = ixgbe_identify_sfp_module_generic(hw); break; case ixgbe_media_type_fiber_qsfp: status = ixgbe_identify_qsfp_module_generic(hw); break; default: hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; break; } return status; } /** * ixgbe_identify_sfp_module_generic - Identifies SFP modules * @hw: pointer to hardware structure * * Searches for and identifies the SFP module and assigns appropriate PHY type. **/ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; u32 vendor_oui = 0; enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; u8 identifier = 0; u8 comp_codes_1g = 0; u8 comp_codes_10g = 0; u8 oui_bytes[3] = {0, 0, 0}; u8 cable_tech = 0; u8 cable_spec = 0; u16 enforce_sfp = 0; if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; goto out; } status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &identifier); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; /* LAN ID is needed for sfp_type determination */ hw->mac.ops.set_lan_id(hw); if (identifier != IXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } else { status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY, &cable_tech); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; /* ID Module * ========= * 0 SFP_DA_CU * 1 SFP_SR * 2 SFP_LR * 3 SFP_DA_CORE0 - 82599-specific * 4 SFP_DA_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific * 7 SFP_act_lmt_DA_CORE0 - 82599-specific * 8 SFP_act_lmt_DA_CORE1 - 82599-specific * 9 SFP_1g_cu_CORE0 - 82599-specific * 10 SFP_1g_cu_CORE1 - 82599-specific * 11 SFP_1g_sx_CORE0 - 82599-specific * 12 SFP_1g_sx_CORE1 - 82599-specific */ if (hw->mac.type == ixgbe_mac_82598EB) { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.sfp_type = ixgbe_sfp_type_da_cu; else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) hw->phy.sfp_type = ixgbe_sfp_type_sr; else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) hw->phy.sfp_type = ixgbe_sfp_type_lr; else hw->phy.sfp_type = ixgbe_sfp_type_unknown; } else if (hw->mac.type == ixgbe_mac_82599EB) { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1; } else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) { hw->phy.ops.read_i2c_eeprom( hw, IXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (cable_spec & IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core0; else hw->phy.sfp_type = ixgbe_sfp_type_da_act_lmt_core1; } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; } } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | IXGBE_SFF_10GBASELR_CAPABLE)) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0; else hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1; } else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_1g_cu_core0; else hw->phy.sfp_type = ixgbe_sfp_type_1g_cu_core1; } else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = ixgbe_sfp_type_1g_sx_core0; else hw->phy.sfp_type = ixgbe_sfp_type_1g_sx_core1; } else { hw->phy.sfp_type = ixgbe_sfp_type_unknown; } } if (hw->phy.sfp_type != stored_sfp_type) hw->phy.sfp_setup_needed = true; /* Determine if the SFP+ PHY is dual speed or not. */ hw->phy.multispeed_fiber = false; if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) hw->phy.multispeed_fiber = true; /* Determine PHY vendor */ if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = identifier; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE0, &oui_bytes[0]); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE1, &oui_bytes[1]); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_VENDOR_OUI_BYTE2, &oui_bytes[2]); if (status == IXGBE_ERR_SWFW_SYNC || status == IXGBE_ERR_I2C || status == IXGBE_ERR_SFP_NOT_PRESENT) goto err_read_i2c_eeprom; vendor_oui = ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) | (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) | (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT)); switch (vendor_oui) { case IXGBE_SFF_VENDOR_OUI_TYCO: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_passive_tyco; break; case IXGBE_SFF_VENDOR_OUI_FTL: if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_ftl_active; else hw->phy.type = ixgbe_phy_sfp_ftl; break; case IXGBE_SFF_VENDOR_OUI_AVAGO: hw->phy.type = ixgbe_phy_sfp_avago; break; case IXGBE_SFF_VENDOR_OUI_INTEL: hw->phy.type = ixgbe_phy_sfp_intel; break; default: if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_passive_unknown; else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) hw->phy.type = ixgbe_phy_sfp_active_unknown; else hw->phy.type = ixgbe_phy_sfp_unknown; break; } } /* Allow any DA cable vendor */ if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE | IXGBE_SFF_DA_ACTIVE_CABLE)) { status = 0; goto out; } /* Verify supported 1G SFP modules */ if (comp_codes_10g == 0 && !(hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1 || hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) { hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; goto out; } /* Anything else 82598-based is supported */ if (hw->mac.type == ixgbe_mac_82598EB) { status = 0; goto out; } ixgbe_get_device_caps(hw, &enforce_sfp); if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) && !((hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0) || (hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core1) || (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0) || (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1))) { /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = 0; } else { if (hw->allow_unsupported_sfp == true) { EWARN(hw, "WARNING: Intel (R) Network " "Connections are quality tested " "using Intel (R) Ethernet Optics." " Using untested modules is not " "supported and may cause unstable" " operation or damage to the " "module or the adapter. Intel " "Corporation is not responsible " "for any harm caused by using " "untested modules.\n", status); status = 0; } else { hw_dbg(hw, "SFP+ module not supported\n"); hw->phy.type = ixgbe_phy_sfp_unsupported; status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } } else { status = 0; } } out: return status; err_read_i2c_eeprom: hw->phy.sfp_type = ixgbe_sfp_type_not_present; if (hw->phy.type != ixgbe_phy_nl) { hw->phy.id = 0; hw->phy.type = ixgbe_phy_unknown; } return IXGBE_ERR_SFP_NOT_PRESENT; } /** * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules * @hw: pointer to hardware structure * * Searches for and identifies the QSFP module and assigns appropriate PHY type **/ s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw) { s32 status = 0; if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; } return status; } /** * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence * @hw: pointer to hardware structure * @list_offset: offset to the SFP ID list * @data_offset: offset to the SFP data block * * Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if * so it returns the offsets to the phy init sequence block. **/ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset) { u16 sfp_id; u16 sfp_type = hw->phy.sfp_type; if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) return IXGBE_ERR_SFP_NOT_SUPPORTED; if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) return IXGBE_ERR_SFP_NOT_PRESENT; if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) && (hw->phy.sfp_type == ixgbe_sfp_type_da_cu)) return IXGBE_ERR_SFP_NOT_SUPPORTED; /* * Limiting active cables and 1G Phys must be initialized as * SR modules */ if (sfp_type == ixgbe_sfp_type_da_act_lmt_core0 || sfp_type == ixgbe_sfp_type_1g_cu_core0 || sfp_type == ixgbe_sfp_type_1g_sx_core0) sfp_type = ixgbe_sfp_type_srlr_core0; else if (sfp_type == ixgbe_sfp_type_da_act_lmt_core1 || sfp_type == ixgbe_sfp_type_1g_cu_core1 || sfp_type == ixgbe_sfp_type_1g_sx_core1) sfp_type = ixgbe_sfp_type_srlr_core1; /* Read offset to PHY init contents */ hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset); if ((!*list_offset) || (*list_offset == 0xFFFF)) return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT; /* Shift offset to first ID word */ (*list_offset)++; /* * Find the matching SFP ID in the EEPROM * and program the init sequence */ hw->eeprom.ops.read(hw, *list_offset, &sfp_id); while (sfp_id != IXGBE_PHY_INIT_END_NL) { if (sfp_id == sfp_type) { (*list_offset)++; hw->eeprom.ops.read(hw, *list_offset, data_offset); if ((!*data_offset) || (*data_offset == 0xFFFF)) { hw_dbg(hw, "SFP+ module not supported\n"); return IXGBE_ERR_SFP_NOT_SUPPORTED; } else { break; } } else { (*list_offset) += 2; if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id)) return IXGBE_ERR_PHY; } } if (sfp_id == IXGBE_PHY_INIT_END_NL) { hw_dbg(hw, "No matching SFP+ module found\n"); return IXGBE_ERR_SFP_NOT_SUPPORTED; } return 0; } /** * ixgbe_read_i2c_eeprom_generic - Reads 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to read * @eeprom_data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data) { return hw->phy.ops.read_i2c_byte(hw, byte_offset, IXGBE_I2C_EEPROM_DEV_ADDR, eeprom_data); } /** * ixgbe_write_i2c_eeprom_generic - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure * @byte_offset: EEPROM byte offset to write * @eeprom_data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface. **/ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data) { return hw->phy.ops.write_i2c_byte(hw, byte_offset, IXGBE_I2C_EEPROM_DEV_ADDR, eeprom_data); } /** * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { s32 status = 0; u32 max_retry = 10; u32 retry = 0; u16 swfw_mask = 0; bool nack = 1; *data = 0; if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) swfw_mask = IXGBE_GSSR_PHY1_SM; else swfw_mask = IXGBE_GSSR_PHY0_SM; do { if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) { status = IXGBE_ERR_SWFW_SYNC; goto read_byte_out; } ixgbe_i2c_start(hw); /* Device Address and write indication */ status = ixgbe_clock_out_i2c_byte(hw, dev_addr); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; status = ixgbe_clock_out_i2c_byte(hw, byte_offset); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; ixgbe_i2c_start(hw); /* Device Address and read indication */ status = ixgbe_clock_out_i2c_byte(hw, (dev_addr | 0x1)); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; status = ixgbe_clock_in_i2c_byte(hw, data); if (status != 0) goto fail; status = ixgbe_clock_out_i2c_bit(hw, nack); if (status != 0) goto fail; ixgbe_i2c_stop(hw); break; fail: hw->mac.ops.release_swfw_sync(hw, swfw_mask); msleep(100); ixgbe_i2c_bus_clear(hw); retry++; if (retry < max_retry) hw_dbg(hw, "I2C byte read error - Retrying.\n"); else hw_dbg(hw, "I2C byte read error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); read_byte_out: return status; } /** * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data) { s32 status = 0; u32 max_retry = 1; u32 retry = 0; u16 swfw_mask = 0; if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) swfw_mask = IXGBE_GSSR_PHY1_SM; else swfw_mask = IXGBE_GSSR_PHY0_SM; if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) { status = IXGBE_ERR_SWFW_SYNC; goto write_byte_out; } do { ixgbe_i2c_start(hw); status = ixgbe_clock_out_i2c_byte(hw, dev_addr); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; status = ixgbe_clock_out_i2c_byte(hw, byte_offset); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; status = ixgbe_clock_out_i2c_byte(hw, data); if (status != 0) goto fail; status = ixgbe_get_i2c_ack(hw); if (status != 0) goto fail; ixgbe_i2c_stop(hw); break; fail: ixgbe_i2c_bus_clear(hw); retry++; if (retry < max_retry) hw_dbg(hw, "I2C byte write error - Retrying.\n"); else hw_dbg(hw, "I2C byte write error.\n"); } while (retry < max_retry); hw->mac.ops.release_swfw_sync(hw, swfw_mask); write_byte_out: return status; } /** * ixgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) **/ static void ixgbe_i2c_start(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); /* Start condition must begin with data and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 1); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Setup time for start condition (4.7us) */ udelay(IXGBE_I2C_T_SU_STA); ixgbe_set_i2c_data(hw, &i2cctl, 0); /* Hold time for start condition (4us) */ udelay(IXGBE_I2C_T_HD_STA); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ udelay(IXGBE_I2C_T_LOW); } /** * ixgbe_i2c_stop - Sets I2C stop condition * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) **/ static void ixgbe_i2c_stop(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); /* Stop condition must begin with data low and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 0); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Setup time for stop condition (4us) */ udelay(IXGBE_I2C_T_SU_STO); ixgbe_set_i2c_data(hw, &i2cctl, 1); /* bus free time between stop and start (4.7us)*/ udelay(IXGBE_I2C_T_BUF); } /** * ixgbe_clock_in_i2c_byte - Clocks in one byte via I2C * @hw: pointer to hardware structure * @data: data byte to clock in * * Clocks in one byte data via I2C data/clock **/ static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data) { s32 i; bool bit = 0; for (i = 7; i >= 0; i--) { ixgbe_clock_in_i2c_bit(hw, &bit); *data |= bit << i; } return 0; } /** * ixgbe_clock_out_i2c_byte - Clocks out one byte via I2C * @hw: pointer to hardware structure * @data: data byte clocked out * * Clocks out one byte data via I2C data/clock **/ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) { s32 status = 0; s32 i; u32 i2cctl; bool bit = 0; for (i = 7; i >= 0; i--) { bit = (data >> i) & 0x1; status = ixgbe_clock_out_i2c_bit(hw, bit); if (status != 0) break; } /* Release SDA line (set high) */ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); i2cctl |= IXGBE_I2C_DATA_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, i2cctl); IXGBE_WRITE_FLUSH(hw); return status; } /** * ixgbe_get_i2c_ack - Polls for I2C ACK * @hw: pointer to hardware structure * * Clocks in/out one bit via I2C data/clock **/ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) { s32 status = 0; u32 i = 0; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); u32 timeout = 10; bool ack = 1; ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); /* Poll for ACK. Note that ACK in I2C spec is * transition from 1 to 0 */ for (i = 0; i < timeout; i++) { i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); ack = ixgbe_get_i2c_data(&i2cctl); udelay(1); if (ack == 0) break; } if (ack == 1) { hw_dbg(hw, "I2C ack was not received.\n"); status = IXGBE_ERR_I2C; } ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ udelay(IXGBE_I2C_T_LOW); return status; } /** * ixgbe_clock_in_i2c_bit - Clocks in one bit via I2C data/clock * @hw: pointer to hardware structure * @data: read data value * * Clocks in one bit via I2C data/clock **/ static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); *data = ixgbe_get_i2c_data(&i2cctl); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us */ udelay(IXGBE_I2C_T_LOW); return 0; } /** * ixgbe_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock * @hw: pointer to hardware structure * @data: data value to write * * Clocks out one bit via I2C data/clock **/ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) { s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); status = ixgbe_set_i2c_data(hw, &i2cctl, data); if (status == 0) { ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Minimum low period of clock is 4.7 us. * This also takes care of the data hold time. */ udelay(IXGBE_I2C_T_LOW); } else { status = IXGBE_ERR_I2C; hw_dbg(hw, "I2C data was not set to %X\n", data); } return status; } /** * ixgbe_raise_i2c_clk - Raises the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' **/ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { u32 i = 0; u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT; u32 i2cctl_r = 0; for (i = 0; i < timeout; i++) { *i2cctl |= IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL rise time (1000ns) */ udelay(IXGBE_I2C_T_RISE); i2cctl_r = IXGBE_READ_REG(hw, IXGBE_I2CCTL); if (i2cctl_r & IXGBE_I2C_CLK_IN) break; } } /** * ixgbe_lower_i2c_clk - Lowers the I2C SCL clock * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' **/ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { *i2cctl &= ~IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); IXGBE_WRITE_FLUSH(hw); /* SCL fall time (300ns) */ udelay(IXGBE_I2C_T_FALL); } /** * ixgbe_set_i2c_data - Sets the I2C data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit **/ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { s32 status = 0; if (data) *i2cctl |= IXGBE_I2C_DATA_OUT; else *i2cctl &= ~IXGBE_I2C_DATA_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); IXGBE_WRITE_FLUSH(hw); /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA); /* Verify data was set correctly */ *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); if (data != ixgbe_get_i2c_data(i2cctl)) { status = IXGBE_ERR_I2C; hw_dbg(hw, "Error - I2C data was not set to %X.\n", data); } return status; } /** * ixgbe_get_i2c_data - Reads the I2C SDA data bit * @hw: pointer to hardware structure * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value **/ static bool ixgbe_get_i2c_data(u32 *i2cctl) { bool data; if (*i2cctl & IXGBE_I2C_DATA_IN) data = 1; else data = 0; return data; } /** * ixgbe_i2c_bus_clear - Clears the I2C bus * @hw: pointer to hardware structure * * Clears the I2C bus by sending nine clock pulses. * Used when data line is stuck low. **/ void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); u32 i; ixgbe_i2c_start(hw); ixgbe_set_i2c_data(hw, &i2cctl, 1); for (i = 0; i < 9; i++) { ixgbe_raise_i2c_clk(hw, &i2cctl); /* Min high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); ixgbe_lower_i2c_clk(hw, &i2cctl); /* Min low period of clock is 4.7us*/ udelay(IXGBE_I2C_T_LOW); } ixgbe_i2c_start(hw); /* Put the i2c bus back to default state */ ixgbe_i2c_stop(hw); } /** * ixgbe_tn_check_overtemp - Checks if an overtemp occurred. * @hw: pointer to hardware structure * * Checks if the LASI temp alarm status was triggered due to overtemp **/ s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) { s32 status = 0; u16 phy_data = 0; if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM) goto out; /* Check that the LASI temp alarm status was triggered */ hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_data); if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM)) goto out; status = IXGBE_ERR_OVERTEMP; out: return status; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_phy.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_PHY_H_ #define _IXGBE_PHY_H_ #include "ixgbe_type.h" #define IXGBE_I2C_EEPROM_DEV_ADDR 0xA0 /* EEPROM byte offsets */ #define IXGBE_SFF_IDENTIFIER 0x0 #define IXGBE_SFF_IDENTIFIER_SFP 0x3 #define IXGBE_SFF_VENDOR_OUI_BYTE0 0x25 #define IXGBE_SFF_VENDOR_OUI_BYTE1 0x26 #define IXGBE_SFF_VENDOR_OUI_BYTE2 0x27 #define IXGBE_SFF_1GBE_COMP_CODES 0x6 #define IXGBE_SFF_10GBE_COMP_CODES 0x3 #define IXGBE_SFF_CABLE_TECHNOLOGY 0x8 #define IXGBE_SFF_CABLE_SPEC_COMP 0x3C /* Bitmasks */ #define IXGBE_SFF_DA_PASSIVE_CABLE 0x4 #define IXGBE_SFF_DA_ACTIVE_CABLE 0x8 #define IXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define IXGBE_SFF_1GBASESX_CAPABLE 0x1 #define IXGBE_SFF_1GBASELX_CAPABLE 0x2 #define IXGBE_SFF_1GBASET_CAPABLE 0x8 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 #define IXGBE_I2C_EEPROM_READ_MASK 0x100 #define IXGBE_I2C_EEPROM_STATUS_MASK 0x3 #define IXGBE_I2C_EEPROM_STATUS_NO_OPERATION 0x0 #define IXGBE_I2C_EEPROM_STATUS_PASS 0x1 #define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 /* Flow control defines */ #define IXGBE_TAF_SYM_PAUSE 0x400 #define IXGBE_TAF_ASM_PAUSE 0x800 /* Bit-shift macros */ #define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 24 #define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 16 #define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 8 /* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */ #define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600 #define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500 #define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00 #define IXGBE_SFF_VENDOR_OUI_INTEL 0x001B2100 /* I2C SDA and SCL timing parameters for standard mode */ #define IXGBE_I2C_T_HD_STA 4 #define IXGBE_I2C_T_LOW 5 #define IXGBE_I2C_T_HIGH 4 #define IXGBE_I2C_T_SU_STA 5 #define IXGBE_I2C_T_HD_DATA 5 #define IXGBE_I2C_T_SU_DATA 1 #define IXGBE_I2C_T_RISE 1 #define IXGBE_I2C_T_FALL 1 #define IXGBE_I2C_T_SU_STO 4 #define IXGBE_I2C_T_BUF 5 #define IXGBE_TN_LASI_STATUS_REG 0x9005 #define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008 s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); bool ixgbe_validate_phy_addr(struct ixgbe_hw *hw, u32 phy_addr); enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id); s32 ixgbe_get_phy_id(struct ixgbe_hw *hw); s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw); s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw); s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 *phy_data); s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type, u16 phy_data); s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw); s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); /* PHY specific */ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw); s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw); s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw); s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw); s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, u16 *list_offset, u16 *data_offset); s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw); #endif /* _IXGBE_PHY_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_sriov.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_SRIOV_H_ #define _IXGBE_SRIOV_H_ int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, int entries, u16 *hash_list, u32 vf); void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter); int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf); void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe); void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf); void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf); void ixgbe_msg_task(struct ixgbe_adapter *adapter); int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, int vf, unsigned char *mac_addr); void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter); void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); #ifdef IFLA_VF_MAX int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac); int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan, u8 qos); int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); #ifdef HAVE_VF_SPOOFCHK_CONFIGURE int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); #endif int ixgbe_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); #endif void ixgbe_disable_sriov(struct ixgbe_adapter *adapter); #ifdef CONFIG_PCI_IOV int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); void ixgbe_enable_sriov(struct ixgbe_adapter *adapter); #endif int ixgbe_check_vf_assignment(struct ixgbe_adapter *adapter); #ifdef IFLA_VF_MAX void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); #endif /* IFLA_VF_MAX */ void ixgbe_dump_registers(struct ixgbe_adapter *adapter); /* * These are defined in ixgbe_type.h on behalf of the VF driver * but we need them here unwrapped for the PF driver. */ #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_X540_VF 0x1515 #endif /* _IXGBE_SRIOV_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_type.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_TYPE_H_ #define _IXGBE_TYPE_H_ #include "ixgbe_osdep.h" /* Vendor ID */ #define IXGBE_INTEL_VENDOR_ID 0x8086 /* Device IDs */ #define IXGBE_DEV_ID_82598 0x10B6 #define IXGBE_DEV_ID_82598_BX 0x1508 #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT 0x10C8 #define IXGBE_DEV_ID_82598AT2 0x150B #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC #define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1 #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 #define IXGBE_DEV_ID_82599_KR 0x1517 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0 #define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A #define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_SFP_SF2 0x154D #define IXGBE_DEV_ID_82599_QSFP_SF_QP 0x1558 #define IXGBE_DEV_ID_82599EN_SFP 0x1557 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_T3_LOM 0x151C #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 /* General Registers */ #define IXGBE_CTRL 0x00000 #define IXGBE_STATUS 0x00008 #define IXGBE_CTRL_EXT 0x00018 #define IXGBE_ESDP 0x00020 #define IXGBE_EODSDP 0x00028 #define IXGBE_I2CCTL 0x00028 #define IXGBE_PHY_GPIO 0x00028 #define IXGBE_MAC_GPIO 0x00030 #define IXGBE_PHYINT_STATUS0 0x00100 #define IXGBE_PHYINT_STATUS1 0x00104 #define IXGBE_PHYINT_STATUS2 0x00108 #define IXGBE_LEDCTL 0x00200 #define IXGBE_FRTIMER 0x00048 #define IXGBE_TCPTIMER 0x0004C #define IXGBE_CORESPARE 0x00600 #define IXGBE_EXVET 0x05078 /* NVM Registers */ #define IXGBE_EEC 0x10010 #define IXGBE_EERD 0x10014 #define IXGBE_EEWR 0x10018 #define IXGBE_FLA 0x1001C #define IXGBE_EEMNGCTL 0x10110 #define IXGBE_EEMNGDATA 0x10114 #define IXGBE_FLMNGCTL 0x10118 #define IXGBE_FLMNGDATA 0x1011C #define IXGBE_FLMNGCNT 0x10120 #define IXGBE_FLOP 0x1013C #define IXGBE_GRC 0x10200 #define IXGBE_SRAMREL 0x10210 #define IXGBE_PHYDBG 0x10218 /* General Receive Control */ #define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */ #define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */ #define IXGBE_VPDDIAG0 0x10204 #define IXGBE_VPDDIAG1 0x10208 /* I2CCTL Bit Masks */ #define IXGBE_I2C_CLK_IN 0x00000001 #define IXGBE_I2C_CLK_OUT 0x00000002 #define IXGBE_I2C_DATA_IN 0x00000004 #define IXGBE_I2C_DATA_OUT 0x00000008 #define IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT 500 #define IXGBE_I2C_THERMAL_SENSOR_ADDR 0xF8 #define IXGBE_EMC_INTERNAL_DATA 0x00 #define IXGBE_EMC_INTERNAL_THERM_LIMIT 0x20 #define IXGBE_EMC_DIODE1_DATA 0x01 #define IXGBE_EMC_DIODE1_THERM_LIMIT 0x19 #define IXGBE_EMC_DIODE2_DATA 0x23 #define IXGBE_EMC_DIODE2_THERM_LIMIT 0x1A #define IXGBE_MAX_SENSORS 3 struct ixgbe_thermal_diode_data { u8 location; u8 temp; u8 caution_thresh; u8 max_op_thresh; }; struct ixgbe_thermal_sensor_data { struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS]; }; /* Interrupt Registers */ #define IXGBE_EICR 0x00800 #define IXGBE_EICS 0x00808 #define IXGBE_EIMS 0x00880 #define IXGBE_EIMC 0x00888 #define IXGBE_EIAC 0x00810 #define IXGBE_EIAM 0x00890 #define IXGBE_EICS_EX(_i) (0x00A90 + (_i) * 4) #define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4) #define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4) #define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4) /* 82599 EITR is only 12 bits, with the lower 3 always zero */ /* * 82598 EITR is 16 bits but set the limits based on the max * supported by all ixgbe hardware */ #define IXGBE_MAX_INT_RATE 488281 #define IXGBE_MIN_INT_RATE 956 #define IXGBE_MAX_EITR 0x00000FF8 #define IXGBE_MIN_EITR 8 #define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : \ (0x012300 + (((_i) - 24) * 4))) #define IXGBE_EITR_ITR_INT_MASK 0x00000FF8 #define IXGBE_EITR_LLI_MOD 0x00008000 #define IXGBE_EITR_CNT_WDIS 0x80000000 #define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */ #define IXGBE_IVAR_MISC 0x00A00 /* misc MSI-X interrupt causes */ #define IXGBE_EITRSEL 0x00894 #define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */ #define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */ #define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4))) #define IXGBE_GPIE 0x00898 /* Flow Control Registers */ #define IXGBE_FCADBUL 0x03210 #define IXGBE_FCADBUH 0x03214 #define IXGBE_FCAMACL 0x04328 #define IXGBE_FCAMACH 0x0432C #define IXGBE_FCRTH_82599(_i) (0x03260 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_FCRTL_82599(_i) (0x03220 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_PFCTOP 0x03008 #define IXGBE_FCTTV(_i) (0x03200 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_FCRTL(_i) (0x03220 + ((_i) * 8)) /* 8 of these (0-7) */ #define IXGBE_FCRTH(_i) (0x03260 + ((_i) * 8)) /* 8 of these (0-7) */ #define IXGBE_FCRTV 0x032A0 #define IXGBE_FCCFG 0x03D00 #define IXGBE_TFCS 0x0CE00 /* Receive DMA Registers */ #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \ (0x0D000 + (((_i) - 64) * 0x40))) #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \ (0x0D004 + (((_i) - 64) * 0x40))) #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \ (0x0D008 + (((_i) - 64) * 0x40))) #define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \ (0x0D010 + (((_i) - 64) * 0x40))) #define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \ (0x0D018 + (((_i) - 64) * 0x40))) #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \ (0x0D028 + (((_i) - 64) * 0x40))) #define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \ (0x0D02C + (((_i) - 64) * 0x40))) #define IXGBE_RSCDBU 0x03028 #define IXGBE_RDDCC 0x02F20 #define IXGBE_RXMEMWRAP 0x03190 #define IXGBE_STARCTRL 0x03024 /* * Split and Replication Receive Control Registers * 00-15 : 0x02100 + n*4 * 16-64 : 0x01014 + n*0x40 * 64-127: 0x0D014 + (n-64)*0x40 */ #define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \ (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \ (0x0D014 + (((_i) - 64) * 0x40)))) /* * Rx DCA Control Register: * 00-15 : 0x02200 + n*4 * 16-64 : 0x0100C + n*0x40 * 64-127: 0x0D00C + (n-64)*0x40 */ #define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \ (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \ (0x0D00C + (((_i) - 64) * 0x40)))) #define IXGBE_RDRXCTL 0x02F00 #define IXGBE_RDRXCTL_RSC_PUSH 0x80 /* 8 of these 0x03C00 - 0x03C1C */ #define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4)) #define IXGBE_RXCTRL 0x03000 #define IXGBE_DROPEN 0x03D04 #define IXGBE_RXPBSIZE_SHIFT 10 /* Receive Registers */ #define IXGBE_RXCSUM 0x05000 #define IXGBE_RFCTL 0x05008 #define IXGBE_DRECCCTL 0x02F08 #define IXGBE_DRECCCTL_DISABLE 0 #define IXGBE_DRECCCTL2 0x02F8C /* Multicast Table Array - 128 entries */ #define IXGBE_MTA(_i) (0x05200 + ((_i) * 4)) #define IXGBE_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ (0x0A200 + ((_i) * 8))) #define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ (0x0A204 + ((_i) * 8))) #define IXGBE_MPSAR_LO(_i) (0x0A600 + ((_i) * 8)) #define IXGBE_MPSAR_HI(_i) (0x0A604 + ((_i) * 8)) /* Packet split receive type */ #define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : \ (0x0EA00 + ((_i) * 4))) /* array of 4096 1-bit vlan filters */ #define IXGBE_VFTA(_i) (0x0A000 + ((_i) * 4)) /*array of 4096 4-bit vlan vmdq indices */ #define IXGBE_VFTAVIND(_j, _i) (0x0A200 + ((_j) * 0x200) + ((_i) * 4)) #define IXGBE_FCTRL 0x05080 #define IXGBE_VLNCTRL 0x05088 #define IXGBE_MCSTCTRL 0x05090 #define IXGBE_MRQC 0x05818 #define IXGBE_SAQF(_i) (0x0E000 + ((_i) * 4)) /* Source Address Queue Filter */ #define IXGBE_DAQF(_i) (0x0E200 + ((_i) * 4)) /* Dest. Address Queue Filter */ #define IXGBE_SDPQF(_i) (0x0E400 + ((_i) * 4)) /* Src Dest. Addr Queue Filter */ #define IXGBE_FTQF(_i) (0x0E600 + ((_i) * 4)) /* Five Tuple Queue Filter */ #define IXGBE_ETQF(_i) (0x05128 + ((_i) * 4)) /* EType Queue Filter */ #define IXGBE_ETQS(_i) (0x0EC00 + ((_i) * 4)) /* EType Queue Select */ #define IXGBE_SYNQF 0x0EC30 /* SYN Packet Queue Filter */ #define IXGBE_RQTC 0x0EC70 #define IXGBE_MTQC 0x08120 #define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */ #define IXGBE_VMVIR(_i) (0x08000 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_VT_CTL 0x051B0 #define IXGBE_PFMAILBOX(_i) (0x04B00 + (4 * (_i))) /* 64 total */ /* 64 Mailboxes, 16 DW each */ #define IXGBE_PFMBMEM(_i) (0x13000 + (64 * (_i))) #define IXGBE_PFMBICR(_i) (0x00710 + (4 * (_i))) /* 4 total */ #define IXGBE_PFMBIMR(_i) (0x00720 + (4 * (_i))) /* 4 total */ #define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) #define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) #define IXGBE_VMECM(_i) (0x08790 + ((_i) * 4)) #define IXGBE_QDE 0x2F04 #define IXGBE_VMTXSW(_i) (0x05180 + ((_i) * 4)) /* 2 total */ #define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */ #define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4)) #define IXGBE_MRCTL(_i) (0x0F600 + ((_i) * 4)) #define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4)) #define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4)) #define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/ #define IXGBE_RXFECCERR0 0x051B8 #define IXGBE_LLITHRESH 0x0EC90 #define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_IMIRVP 0x05AC0 #define IXGBE_VMD_CTL 0x0581C #define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */ #define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */ /* Flow Director registers */ #define IXGBE_FDIRCTRL 0x0EE00 #define IXGBE_FDIRHKEY 0x0EE68 #define IXGBE_FDIRSKEY 0x0EE6C #define IXGBE_FDIRDIP4M 0x0EE3C #define IXGBE_FDIRSIP4M 0x0EE40 #define IXGBE_FDIRTCPM 0x0EE44 #define IXGBE_FDIRUDPM 0x0EE48 #define IXGBE_FDIRIP6M 0x0EE74 #define IXGBE_FDIRM 0x0EE70 /* Flow Director Stats registers */ #define IXGBE_FDIRFREE 0x0EE38 #define IXGBE_FDIRLEN 0x0EE4C #define IXGBE_FDIRUSTAT 0x0EE50 #define IXGBE_FDIRFSTAT 0x0EE54 #define IXGBE_FDIRMATCH 0x0EE58 #define IXGBE_FDIRMISS 0x0EE5C /* Flow Director Programming registers */ #define IXGBE_FDIRSIPv6(_i) (0x0EE0C + ((_i) * 4)) /* 3 of these (0-2) */ #define IXGBE_FDIRIPSA 0x0EE18 #define IXGBE_FDIRIPDA 0x0EE1C #define IXGBE_FDIRPORT 0x0EE20 #define IXGBE_FDIRVLAN 0x0EE24 #define IXGBE_FDIRHASH 0x0EE28 #define IXGBE_FDIRCMD 0x0EE2C /* Transmit DMA registers */ #define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of them (0-31)*/ #define IXGBE_TDBAH(_i) (0x06004 + ((_i) * 0x40)) #define IXGBE_TDLEN(_i) (0x06008 + ((_i) * 0x40)) #define IXGBE_TDH(_i) (0x06010 + ((_i) * 0x40)) #define IXGBE_TDT(_i) (0x06018 + ((_i) * 0x40)) #define IXGBE_TXDCTL(_i) (0x06028 + ((_i) * 0x40)) #define IXGBE_TDWBAL(_i) (0x06038 + ((_i) * 0x40)) #define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40)) #define IXGBE_DTXCTL 0x07E00 #define IXGBE_DMATXCTL 0x04A80 #define IXGBE_PFVFSPOOF(_i) (0x08200 + ((_i) * 4)) /* 8 of these 0 - 7 */ #define IXGBE_PFDTXGSWC 0x08220 #define IXGBE_DTXMXSZRQ 0x08100 #define IXGBE_DTXTCPFLGL 0x04A88 #define IXGBE_DTXTCPFLGH 0x04A8C #define IXGBE_LBDRPEN 0x0CA00 #define IXGBE_TXPBTHRESH(_i) (0x04950 + ((_i) * 4)) /* 8 of these 0 - 7 */ #define IXGBE_DMATXCTL_TE 0x1 /* Transmit Enable */ #define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */ #define IXGBE_DMATXCTL_GDV 0x8 /* Global Double VLAN */ #define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */ #define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */ /* Anti-spoofing defines */ #define IXGBE_SPOOF_MACAS_MASK 0xFF #define IXGBE_SPOOF_VLANAS_MASK 0xFF00 #define IXGBE_SPOOF_VLANAS_SHIFT 8 #define IXGBE_PFVFSPOOF_REG_COUNT 8 /* 16 of these (0-15) */ #define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* Tx DCA Control register : 128 of these (0-127) */ #define IXGBE_DCA_TXCTRL_82599(_i) (0x0600C + ((_i) * 0x40)) #define IXGBE_TIPG 0x0CB00 #define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) * 4)) /* 8 of these */ #define IXGBE_MNGTXMAP 0x0CD10 #define IXGBE_TIPG_FIBER_DEFAULT 3 #define IXGBE_TXPBSIZE_SHIFT 10 /* Wake up registers */ #define IXGBE_WUC 0x05800 #define IXGBE_WUFC 0x05808 #define IXGBE_WUS 0x05810 #define IXGBE_IPAV 0x05838 #define IXGBE_IP4AT 0x05840 /* IPv4 table 0x5840-0x5858 */ #define IXGBE_IP6AT 0x05880 /* IPv6 table 0x5880-0x588F */ #define IXGBE_WUPL 0x05900 #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ #define IXGBE_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flex host filter table */ /* Ext Flexible Host Filter Table */ #define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX 4 #define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 /* Each Flexible Filter is at most 128 (0x80) bytes in length */ #define IXGBE_FLEXIBLE_FILTER_SIZE_MAX 128 #define IXGBE_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */ #define IXGBE_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */ /* Definitions for power management and wakeup registers */ /* Wake Up Control */ #define IXGBE_WUC_PME_EN 0x00000002 /* PME Enable */ #define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */ #define IXGBE_WUC_WKEN 0x00000010 /* Enable PE_WAKE_N pin assertion */ /* Wake Up Filter Control */ #define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ #define IXGBE_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ #define IXGBE_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ #define IXGBE_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ #define IXGBE_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define IXGBE_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define IXGBE_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define IXGBE_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ #define IXGBE_WUFC_MNG 0x00000100 /* Directed Mgmt Packet Wakeup Enable */ #define IXGBE_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define IXGBE_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define IXGBE_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ #define IXGBE_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ #define IXGBE_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ #define IXGBE_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ #define IXGBE_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ #define IXGBE_WUFC_FLX_FILTERS 0x000F0000 /* Mask for 4 flex filters */ /* Mask for Ext. flex filters */ #define IXGBE_WUFC_EXT_FLX_FILTERS 0x00300000 #define IXGBE_WUFC_ALL_FILTERS 0x003F00FF /* Mask for all wakeup filters */ #define IXGBE_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ /* Wake Up Status */ #define IXGBE_WUS_LNKC IXGBE_WUFC_LNKC #define IXGBE_WUS_MAG IXGBE_WUFC_MAG #define IXGBE_WUS_EX IXGBE_WUFC_EX #define IXGBE_WUS_MC IXGBE_WUFC_MC #define IXGBE_WUS_BC IXGBE_WUFC_BC #define IXGBE_WUS_ARP IXGBE_WUFC_ARP #define IXGBE_WUS_IPV4 IXGBE_WUFC_IPV4 #define IXGBE_WUS_IPV6 IXGBE_WUFC_IPV6 #define IXGBE_WUS_MNG IXGBE_WUFC_MNG #define IXGBE_WUS_FLX0 IXGBE_WUFC_FLX0 #define IXGBE_WUS_FLX1 IXGBE_WUFC_FLX1 #define IXGBE_WUS_FLX2 IXGBE_WUFC_FLX2 #define IXGBE_WUS_FLX3 IXGBE_WUFC_FLX3 #define IXGBE_WUS_FLX4 IXGBE_WUFC_FLX4 #define IXGBE_WUS_FLX5 IXGBE_WUFC_FLX5 #define IXGBE_WUS_FLX_FILTERS IXGBE_WUFC_FLX_FILTERS /* Wake Up Packet Length */ #define IXGBE_WUPL_LENGTH_MASK 0xFFFF /* DCB registers */ #define IXGBE_DCB_MAX_TRAFFIC_CLASS 8 #define IXGBE_RMCS 0x03D00 #define IXGBE_DPMCS 0x07F40 #define IXGBE_PDPMCS 0x0CD00 #define IXGBE_RUPPBMR 0x050A0 #define IXGBE_RT2CR(_i) (0x03C20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RT2SR(_i) (0x03C40 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDTQ2TCCR(_i) (0x0602C + ((_i) * 0x40)) /* 8 of these (0-7) */ #define IXGBE_TDTQ2TCSR(_i) (0x0622C + ((_i) * 0x40)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCCR(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ /* Security Control Registers */ #define IXGBE_SECTXCTRL 0x08800 #define IXGBE_SECTXSTAT 0x08804 #define IXGBE_SECTXBUFFAF 0x08808 #define IXGBE_SECTXMINIFG 0x08810 #define IXGBE_SECRXCTRL 0x08D00 #define IXGBE_SECRXSTAT 0x08D04 /* Security Bit Fields and Masks */ #define IXGBE_SECTXCTRL_SECTX_DIS 0x00000001 #define IXGBE_SECTXCTRL_TX_DIS 0x00000002 #define IXGBE_SECTXCTRL_STORE_FORWARD 0x00000004 #define IXGBE_SECTXSTAT_SECTX_RDY 0x00000001 #define IXGBE_SECTXSTAT_ECC_TXERR 0x00000002 #define IXGBE_SECRXCTRL_SECRX_DIS 0x00000001 #define IXGBE_SECRXCTRL_RX_DIS 0x00000002 #define IXGBE_SECRXSTAT_SECRX_RDY 0x00000001 #define IXGBE_SECRXSTAT_ECC_RXERR 0x00000002 /* LinkSec (MacSec) Registers */ #define IXGBE_LSECTXCAP 0x08A00 #define IXGBE_LSECRXCAP 0x08F00 #define IXGBE_LSECTXCTRL 0x08A04 #define IXGBE_LSECTXSCL 0x08A08 /* SCI Low */ #define IXGBE_LSECTXSCH 0x08A0C /* SCI High */ #define IXGBE_LSECTXSA 0x08A10 #define IXGBE_LSECTXPN0 0x08A14 #define IXGBE_LSECTXPN1 0x08A18 #define IXGBE_LSECTXKEY0(_n) (0x08A1C + (4 * (_n))) /* 4 of these (0-3) */ #define IXGBE_LSECTXKEY1(_n) (0x08A2C + (4 * (_n))) /* 4 of these (0-3) */ #define IXGBE_LSECRXCTRL 0x08F04 #define IXGBE_LSECRXSCL 0x08F08 #define IXGBE_LSECRXSCH 0x08F0C #define IXGBE_LSECRXSA(_i) (0x08F10 + (4 * (_i))) /* 2 of these (0-1) */ #define IXGBE_LSECRXPN(_i) (0x08F18 + (4 * (_i))) /* 2 of these (0-1) */ #define IXGBE_LSECRXKEY(_n, _m) (0x08F20 + ((0x10 * (_n)) + (4 * (_m)))) #define IXGBE_LSECTXUT 0x08A3C /* OutPktsUntagged */ #define IXGBE_LSECTXPKTE 0x08A40 /* OutPktsEncrypted */ #define IXGBE_LSECTXPKTP 0x08A44 /* OutPktsProtected */ #define IXGBE_LSECTXOCTE 0x08A48 /* OutOctetsEncrypted */ #define IXGBE_LSECTXOCTP 0x08A4C /* OutOctetsProtected */ #define IXGBE_LSECRXUT 0x08F40 /* InPktsUntagged/InPktsNoTag */ #define IXGBE_LSECRXOCTD 0x08F44 /* InOctetsDecrypted */ #define IXGBE_LSECRXOCTV 0x08F48 /* InOctetsValidated */ #define IXGBE_LSECRXBAD 0x08F4C /* InPktsBadTag */ #define IXGBE_LSECRXNOSCI 0x08F50 /* InPktsNoSci */ #define IXGBE_LSECRXUNSCI 0x08F54 /* InPktsUnknownSci */ #define IXGBE_LSECRXUNCH 0x08F58 /* InPktsUnchecked */ #define IXGBE_LSECRXDELAY 0x08F5C /* InPktsDelayed */ #define IXGBE_LSECRXLATE 0x08F60 /* InPktsLate */ #define IXGBE_LSECRXOK(_n) (0x08F64 + (0x04 * (_n))) /* InPktsOk */ #define IXGBE_LSECRXINV(_n) (0x08F6C + (0x04 * (_n))) /* InPktsInvalid */ #define IXGBE_LSECRXNV(_n) (0x08F74 + (0x04 * (_n))) /* InPktsNotValid */ #define IXGBE_LSECRXUNSA 0x08F7C /* InPktsUnusedSa */ #define IXGBE_LSECRXNUSA 0x08F80 /* InPktsNotUsingSa */ /* LinkSec (MacSec) Bit Fields and Masks */ #define IXGBE_LSECTXCAP_SUM_MASK 0x00FF0000 #define IXGBE_LSECTXCAP_SUM_SHIFT 16 #define IXGBE_LSECRXCAP_SUM_MASK 0x00FF0000 #define IXGBE_LSECRXCAP_SUM_SHIFT 16 #define IXGBE_LSECTXCTRL_EN_MASK 0x00000003 #define IXGBE_LSECTXCTRL_DISABLE 0x0 #define IXGBE_LSECTXCTRL_AUTH 0x1 #define IXGBE_LSECTXCTRL_AUTH_ENCRYPT 0x2 #define IXGBE_LSECTXCTRL_AISCI 0x00000020 #define IXGBE_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00 #define IXGBE_LSECTXCTRL_RSV_MASK 0x000000D8 #define IXGBE_LSECRXCTRL_EN_MASK 0x0000000C #define IXGBE_LSECRXCTRL_EN_SHIFT 2 #define IXGBE_LSECRXCTRL_DISABLE 0x0 #define IXGBE_LSECRXCTRL_CHECK 0x1 #define IXGBE_LSECRXCTRL_STRICT 0x2 #define IXGBE_LSECRXCTRL_DROP 0x3 #define IXGBE_LSECRXCTRL_PLSH 0x00000040 #define IXGBE_LSECRXCTRL_RP 0x00000080 #define IXGBE_LSECRXCTRL_RSV_MASK 0xFFFFFF33 /* IpSec Registers */ #define IXGBE_IPSTXIDX 0x08900 #define IXGBE_IPSTXSALT 0x08904 #define IXGBE_IPSTXKEY(_i) (0x08908 + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXIDX 0x08E00 #define IXGBE_IPSRXIPADDR(_i) (0x08E04 + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXSPI 0x08E14 #define IXGBE_IPSRXIPIDX 0x08E18 #define IXGBE_IPSRXKEY(_i) (0x08E1C + (4 * (_i))) /* 4 of these (0-3) */ #define IXGBE_IPSRXSALT 0x08E2C #define IXGBE_IPSRXMOD 0x08E30 #define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4 /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 #define IXGBE_RTTDCS_ARBDIS 0x00000040 /* DCB arbiter disable */ #define IXGBE_RTTPCS 0x0CD00 #define IXGBE_RTRUP2TC 0x03020 #define IXGBE_RTTUP2TC 0x0C800 #define IXGBE_RTRPT4C(_i) (0x02140 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_TXLLQ(_i) (0x082E0 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_RTRPT4S(_i) (0x02160 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2C(_i) (0x04910 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDT2S(_i) (0x04930 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTPT2C(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTPT2S(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_RTTDQSEL 0x04904 #define IXGBE_RTTDT1C 0x04908 #define IXGBE_RTTDT1S 0x0490C #define IXGBE_RTTDTECC 0x04990 #define IXGBE_RTTDTECC_NO_BCN 0x00000100 #define IXGBE_RTTBCNRC 0x04984 #define IXGBE_RTTBCNRC_RS_ENA 0x80000000 #define IXGBE_RTTBCNRC_RF_DEC_MASK 0x00003FFF #define IXGBE_RTTBCNRC_RF_INT_SHIFT 14 #define IXGBE_RTTBCNRC_RF_INT_MASK \ (IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT) #define IXGBE_RTTBCNRM 0x04980 /* FCoE DMA Context Registers */ #define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */ #define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */ #define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */ #define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */ #define IXGBE_FCINVST0 0x03FC0 /* FC Invalid DMA Context Status Reg 0*/ #define IXGBE_FCINVST(_i) (IXGBE_FCINVST0 + ((_i) * 4)) #define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */ #define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */ #define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */ #define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */ #define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */ #define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3 #define IXGBE_FCBUFF_BUFFCNT_SHIFT 8 #define IXGBE_FCBUFF_OFFSET_SHIFT 16 #define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */ #define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */ #define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */ #define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */ #define IXGBE_FCDMARW_LASTSIZE_SHIFT 16 /* FCoE SOF/EOF */ #define IXGBE_TEOFF 0x04A94 /* Tx FC EOF */ #define IXGBE_TSOFF 0x04A98 /* Tx FC SOF */ #define IXGBE_REOFF 0x05158 /* Rx FC EOF */ #define IXGBE_RSOFF 0x051F8 /* Rx FC SOF */ /* FCoE Filter Context Registers */ #define IXGBE_FCFLT 0x05108 /* FC FLT Context */ #define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */ #define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */ #define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */ #define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */ #define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */ #define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */ #define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */ #define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */ #define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */ /* FCoE Receive Control */ #define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */ #define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */ #define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */ #define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */ #define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */ #define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */ #define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */ #define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */ #define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */ #define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */ #define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8 /* FCoE Redirection */ #define IXGBE_FCRECTL 0x0ED00 /* FC Redirection Control */ #define IXGBE_FCRETA0 0x0ED10 /* FC Redirection Table 0 */ #define IXGBE_FCRETA(_i) (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */ #define IXGBE_FCRECTL_ENA 0x1 /* FCoE Redir Table Enable */ #define IXGBE_FCRETASEL_ENA 0x2 /* FCoE FCRETASEL bit */ #define IXGBE_FCRETA_SIZE 8 /* Max entries in FCRETA */ #define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */ /* Stats registers */ #define IXGBE_CRCERRS 0x04000 #define IXGBE_ILLERRC 0x04004 #define IXGBE_ERRBC 0x04008 #define IXGBE_MSPDC 0x04010 #define IXGBE_MPC(_i) (0x03FA0 + ((_i) * 4)) /* 8 of these 3FA0-3FBC*/ #define IXGBE_MLFC 0x04034 #define IXGBE_MRFC 0x04038 #define IXGBE_RLEC 0x04040 #define IXGBE_LXONTXC 0x03F60 #define IXGBE_LXONRXC 0x0CF60 #define IXGBE_LXOFFTXC 0x03F68 #define IXGBE_LXOFFRXC 0x0CF68 #define IXGBE_LXONRXCNT 0x041A4 #define IXGBE_LXOFFRXCNT 0x041A8 #define IXGBE_PXONRXCNT(_i) (0x04140 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXOFFRXCNT(_i) (0x04160 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXON2OFFCNT(_i) (0x03240 + ((_i) * 4)) /* 8 of these */ #define IXGBE_PXONTXC(_i) (0x03F00 + ((_i) * 4)) /* 8 of these 3F00-3F1C*/ #define IXGBE_PXONRXC(_i) (0x0CF00 + ((_i) * 4)) /* 8 of these CF00-CF1C*/ #define IXGBE_PXOFFTXC(_i) (0x03F20 + ((_i) * 4)) /* 8 of these 3F20-3F3C*/ #define IXGBE_PXOFFRXC(_i) (0x0CF20 + ((_i) * 4)) /* 8 of these CF20-CF3C*/ #define IXGBE_PRC64 0x0405C #define IXGBE_PRC127 0x04060 #define IXGBE_PRC255 0x04064 #define IXGBE_PRC511 0x04068 #define IXGBE_PRC1023 0x0406C #define IXGBE_PRC1522 0x04070 #define IXGBE_GPRC 0x04074 #define IXGBE_BPRC 0x04078 #define IXGBE_MPRC 0x0407C #define IXGBE_GPTC 0x04080 #define IXGBE_GORCL 0x04088 #define IXGBE_GORCH 0x0408C #define IXGBE_GOTCL 0x04090 #define IXGBE_GOTCH 0x04094 #define IXGBE_RNBC(_i) (0x03FC0 + ((_i) * 4)) /* 8 of these 3FC0-3FDC*/ #define IXGBE_RUC 0x040A4 #define IXGBE_RFC 0x040A8 #define IXGBE_ROC 0x040AC #define IXGBE_RJC 0x040B0 #define IXGBE_MNGPRC 0x040B4 #define IXGBE_MNGPDC 0x040B8 #define IXGBE_MNGPTC 0x0CF90 #define IXGBE_TORL 0x040C0 #define IXGBE_TORH 0x040C4 #define IXGBE_TPR 0x040D0 #define IXGBE_TPT 0x040D4 #define IXGBE_PTC64 0x040D8 #define IXGBE_PTC127 0x040DC #define IXGBE_PTC255 0x040E0 #define IXGBE_PTC511 0x040E4 #define IXGBE_PTC1023 0x040E8 #define IXGBE_PTC1522 0x040EC #define IXGBE_MPTC 0x040F0 #define IXGBE_BPTC 0x040F4 #define IXGBE_XEC 0x04120 #define IXGBE_SSVPC 0x08780 #define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4)) #define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : \ (0x08600 + ((_i) * 4))) #define IXGBE_TQSM(_i) (0x08600 + ((_i) * 4)) #define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC_L(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBRC_H(_i) (0x01038 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */ #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */ #define IXGBE_FCCRC 0x05118 /* Num of Good Eth CRC w/ Bad FC CRC */ #define IXGBE_FCOERPDC 0x0241C /* FCoE Rx Packets Dropped Count */ #define IXGBE_FCLAST 0x02424 /* FCoE Last Error Count */ #define IXGBE_FCOEPRC 0x02428 /* Number of FCoE Packets Received */ #define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */ #define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */ #define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */ #define IXGBE_FCCRC_CNT_MASK 0x0000FFFF /* CRC_CNT: bit 0 - 15 */ #define IXGBE_FCLAST_CNT_MASK 0x0000FFFF /* Last_CNT: bit 0 - 15 */ #define IXGBE_O2BGPTC 0x041C4 #define IXGBE_O2BSPC 0x087B0 #define IXGBE_B2OSPC 0x041C0 #define IXGBE_B2OGPRC 0x02F90 #define IXGBE_BUPRC 0x04180 #define IXGBE_BMPRC 0x04184 #define IXGBE_BBPRC 0x04188 #define IXGBE_BUPTC 0x0418C #define IXGBE_BMPTC 0x04190 #define IXGBE_BBPTC 0x04194 #define IXGBE_BCRCERRS 0x04198 #define IXGBE_BXONRXC 0x0419C #define IXGBE_BXOFFRXC 0x041E0 #define IXGBE_BXONTXC 0x041E4 #define IXGBE_BXOFFTXC 0x041E8 #define IXGBE_PCRC8ECL 0x0E810 #define IXGBE_PCRC8ECH 0x0E811 #define IXGBE_PCRC8ECH_MASK 0x1F #define IXGBE_LDPCECL 0x0E820 #define IXGBE_LDPCECH 0x0E821 /* Management */ #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MFUTP(_i) (0x05030 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MANC 0x05820 #define IXGBE_MFVAL 0x05824 #define IXGBE_MANC2H 0x05860 #define IXGBE_MDEF(_i) (0x05890 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_MIPAF 0x058B0 #define IXGBE_MMAL(_i) (0x05910 + ((_i) * 8)) /* 4 of these (0-3) */ #define IXGBE_MMAH(_i) (0x05914 + ((_i) * 8)) /* 4 of these (0-3) */ #define IXGBE_FTFT 0x09400 /* 0x9400-0x97FC */ #define IXGBE_METF(_i) (0x05190 + ((_i) * 4)) /* 4 of these (0-3) */ #define IXGBE_MDEF_EXT(_i) (0x05160 + ((_i) * 4)) /* 8 of these (0-7) */ #define IXGBE_LSWFW 0x15014 #define IXGBE_BMCIP(_i) (0x05050 + ((_i) * 4)) /* 0x5050-0x505C */ #define IXGBE_BMCIPVAL 0x05060 #define IXGBE_BMCIP_IPADDR_TYPE 0x00000001 #define IXGBE_BMCIP_IPADDR_VALID 0x00000002 /* Management Bit Fields and Masks */ #define IXGBE_MANC_EN_BMC2OS 0x10000000 /* Ena BMC2OS and OS2BMC traffic */ #define IXGBE_MANC_EN_BMC2OS_SHIFT 28 /* Firmware Semaphore Register */ #define IXGBE_FWSM_MODE_MASK 0xE /* ARC Subsystem registers */ #define IXGBE_HICR 0x15F00 #define IXGBE_FWSTS 0x15F0C #define IXGBE_HSMC0R 0x15F04 #define IXGBE_HSMC1R 0x15F08 #define IXGBE_SWSR 0x15F10 #define IXGBE_HFDR 0x15FE8 #define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */ #define IXGBE_HICR_EN 0x01 /* Enable bit - RO */ /* Driver sets this bit when done to put command in RAM */ #define IXGBE_HICR_C 0x02 #define IXGBE_HICR_SV 0x04 /* Status Validity */ #define IXGBE_HICR_FW_RESET_ENABLE 0x40 #define IXGBE_HICR_FW_RESET 0x80 /* PCI-E registers */ #define IXGBE_GCR 0x11000 #define IXGBE_GTV 0x11004 #define IXGBE_FUNCTAG 0x11008 #define IXGBE_GLT 0x1100C #define IXGBE_PCIEPIPEADR 0x11004 #define IXGBE_PCIEPIPEDAT 0x11008 #define IXGBE_GSCL_1 0x11010 #define IXGBE_GSCL_2 0x11014 #define IXGBE_GSCL_3 0x11018 #define IXGBE_GSCL_4 0x1101C #define IXGBE_GSCN_0 0x11020 #define IXGBE_GSCN_1 0x11024 #define IXGBE_GSCN_2 0x11028 #define IXGBE_GSCN_3 0x1102C #define IXGBE_FACTPS 0x10150 #define IXGBE_PCIEANACTL 0x11040 #define IXGBE_SWSM 0x10140 #define IXGBE_FWSM 0x10148 #define IXGBE_GSSR 0x10160 #define IXGBE_MREVID 0x11064 #define IXGBE_DCA_ID 0x11070 #define IXGBE_DCA_CTRL 0x11074 #define IXGBE_SWFW_SYNC IXGBE_GSSR /* PCI-E registers 82599-Specific */ #define IXGBE_GCR_EXT 0x11050 #define IXGBE_GSCL_5_82599 0x11030 #define IXGBE_GSCL_6_82599 0x11034 #define IXGBE_GSCL_7_82599 0x11038 #define IXGBE_GSCL_8_82599 0x1103C #define IXGBE_PHYADR_82599 0x11040 #define IXGBE_PHYDAT_82599 0x11044 #define IXGBE_PHYCTL_82599 0x11048 #define IXGBE_PBACLR_82599 0x11068 #define IXGBE_CIAA_82599 0x11088 #define IXGBE_CIAD_82599 0x1108C #define IXGBE_PICAUSE 0x110B0 #define IXGBE_PIENA 0x110B8 #define IXGBE_CDQ_MBR_82599 0x110B4 #define IXGBE_PCIESPARE 0x110BC #define IXGBE_MISC_REG_82599 0x110F0 #define IXGBE_ECC_CTRL_0_82599 0x11100 #define IXGBE_ECC_CTRL_1_82599 0x11104 #define IXGBE_ECC_STATUS_82599 0x110E0 #define IXGBE_BAR_CTRL_82599 0x110F4 /* PCI Express Control */ #define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000 #define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000 #define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 #define IXGBE_GCR_CAP_VER2 0x00040000 #define IXGBE_GCR_EXT_MSIX_EN 0x80000000 #define IXGBE_GCR_EXT_BUFFERS_CLEAR 0x40000000 #define IXGBE_GCR_EXT_VT_MODE_16 0x00000001 #define IXGBE_GCR_EXT_VT_MODE_32 0x00000002 #define IXGBE_GCR_EXT_VT_MODE_64 0x00000003 #define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ IXGBE_GCR_EXT_VT_MODE_64) /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ #define IXGBE_RXSTMPL 0x051E8 /* Rx timestamp Low - RO */ #define IXGBE_RXSTMPH 0x051A4 /* Rx timestamp High - RO */ #define IXGBE_RXSATRL 0x051A0 /* Rx timestamp attribute low - RO */ #define IXGBE_RXSATRH 0x051A8 /* Rx timestamp attribute high - RO */ #define IXGBE_RXMTRL 0x05120 /* RX message type register low - RW */ #define IXGBE_TXSTMPL 0x08C04 /* Tx timestamp value Low - RO */ #define IXGBE_TXSTMPH 0x08C08 /* Tx timestamp value High - RO */ #define IXGBE_SYSTIML 0x08C0C /* System time register Low - RO */ #define IXGBE_SYSTIMH 0x08C10 /* System time register High - RO */ #define IXGBE_TIMINCA 0x08C14 /* Increment attributes register - RW */ #define IXGBE_TIMADJL 0x08C18 /* Time Adjustment Offset register Low - RW */ #define IXGBE_TIMADJH 0x08C1C /* Time Adjustment Offset register High - RW */ #define IXGBE_TSAUXC 0x08C20 /* TimeSync Auxiliary Control register - RW */ #define IXGBE_TRGTTIML0 0x08C24 /* Target Time Register 0 Low - RW */ #define IXGBE_TRGTTIMH0 0x08C28 /* Target Time Register 0 High - RW */ #define IXGBE_TRGTTIML1 0x08C2C /* Target Time Register 1 Low - RW */ #define IXGBE_TRGTTIMH1 0x08C30 /* Target Time Register 1 High - RW */ #define IXGBE_FREQOUT0 0x08C34 /* Frequency Out 0 Control register - RW */ #define IXGBE_FREQOUT1 0x08C38 /* Frequency Out 1 Control register - RW */ #define IXGBE_AUXSTMPL0 0x08C3C /* Auxiliary Time Stamp 0 register Low - RO */ #define IXGBE_AUXSTMPH0 0x08C40 /* Auxiliary Time Stamp 0 register High - RO */ #define IXGBE_AUXSTMPL1 0x08C44 /* Auxiliary Time Stamp 1 register Low - RO */ #define IXGBE_AUXSTMPH1 0x08C48 /* Auxiliary Time Stamp 1 register High - RO */ /* Diagnostic Registers */ #define IXGBE_RDSTATCTL 0x02C20 #define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */ #define IXGBE_RDHMPN 0x02F08 #define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4)) #define IXGBE_RDPROBE 0x02F20 #define IXGBE_RDMAM 0x02F30 #define IXGBE_RDMAD 0x02F34 #define IXGBE_TDSTATCTL 0x07C20 #define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */ #define IXGBE_TDHMPN 0x07F08 #define IXGBE_TDHMPN2 0x082FC #define IXGBE_TXDESCIC 0x082CC #define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4)) #define IXGBE_TIC_DW2(_i) (0x082B0 + ((_i) * 4)) #define IXGBE_TDPROBE 0x07F20 #define IXGBE_TXBUFCTRL 0x0C600 #define IXGBE_TXBUFDATA0 0x0C610 #define IXGBE_TXBUFDATA1 0x0C614 #define IXGBE_TXBUFDATA2 0x0C618 #define IXGBE_TXBUFDATA3 0x0C61C #define IXGBE_RXBUFCTRL 0x03600 #define IXGBE_RXBUFDATA0 0x03610 #define IXGBE_RXBUFDATA1 0x03614 #define IXGBE_RXBUFDATA2 0x03618 #define IXGBE_RXBUFDATA3 0x0361C #define IXGBE_PCIE_DIAG(_i) (0x11090 + ((_i) * 4)) /* 8 of these */ #define IXGBE_RFVAL 0x050A4 #define IXGBE_MDFTC1 0x042B8 #define IXGBE_MDFTC2 0x042C0 #define IXGBE_MDFTFIFO1 0x042C4 #define IXGBE_MDFTFIFO2 0x042C8 #define IXGBE_MDFTS 0x042CC #define IXGBE_RXDATAWRPTR(_i) (0x03700 + ((_i) * 4)) /* 8 of these 3700-370C*/ #define IXGBE_RXDESCWRPTR(_i) (0x03710 + ((_i) * 4)) /* 8 of these 3710-371C*/ #define IXGBE_RXDATARDPTR(_i) (0x03720 + ((_i) * 4)) /* 8 of these 3720-372C*/ #define IXGBE_RXDESCRDPTR(_i) (0x03730 + ((_i) * 4)) /* 8 of these 3730-373C*/ #define IXGBE_TXDATAWRPTR(_i) (0x0C700 + ((_i) * 4)) /* 8 of these C700-C70C*/ #define IXGBE_TXDESCWRPTR(_i) (0x0C710 + ((_i) * 4)) /* 8 of these C710-C71C*/ #define IXGBE_TXDATARDPTR(_i) (0x0C720 + ((_i) * 4)) /* 8 of these C720-C72C*/ #define IXGBE_TXDESCRDPTR(_i) (0x0C730 + ((_i) * 4)) /* 8 of these C730-C73C*/ #define IXGBE_PCIEECCCTL 0x1106C #define IXGBE_RXWRPTR(_i) (0x03100 + ((_i) * 4)) /* 8 of these 3100-310C*/ #define IXGBE_RXUSED(_i) (0x03120 + ((_i) * 4)) /* 8 of these 3120-312C*/ #define IXGBE_RXRDPTR(_i) (0x03140 + ((_i) * 4)) /* 8 of these 3140-314C*/ #define IXGBE_RXRDWRPTR(_i) (0x03160 + ((_i) * 4)) /* 8 of these 3160-310C*/ #define IXGBE_TXWRPTR(_i) (0x0C100 + ((_i) * 4)) /* 8 of these C100-C10C*/ #define IXGBE_TXUSED(_i) (0x0C120 + ((_i) * 4)) /* 8 of these C120-C12C*/ #define IXGBE_TXRDPTR(_i) (0x0C140 + ((_i) * 4)) /* 8 of these C140-C14C*/ #define IXGBE_TXRDWRPTR(_i) (0x0C160 + ((_i) * 4)) /* 8 of these C160-C10C*/ #define IXGBE_PCIEECCCTL0 0x11100 #define IXGBE_PCIEECCCTL1 0x11104 #define IXGBE_RXDBUECC 0x03F70 #define IXGBE_TXDBUECC 0x0CF70 #define IXGBE_RXDBUEST 0x03F74 #define IXGBE_TXDBUEST 0x0CF74 #define IXGBE_PBTXECC 0x0C300 #define IXGBE_PBRXECC 0x03300 #define IXGBE_GHECCR 0x110B0 /* MAC Registers */ #define IXGBE_PCS1GCFIG 0x04200 #define IXGBE_PCS1GLCTL 0x04208 #define IXGBE_PCS1GLSTA 0x0420C #define IXGBE_PCS1GDBG0 0x04210 #define IXGBE_PCS1GDBG1 0x04214 #define IXGBE_PCS1GANA 0x04218 #define IXGBE_PCS1GANLP 0x0421C #define IXGBE_PCS1GANNP 0x04220 #define IXGBE_PCS1GANLPNP 0x04224 #define IXGBE_HLREG0 0x04240 #define IXGBE_HLREG1 0x04244 #define IXGBE_PAP 0x04248 #define IXGBE_MACA 0x0424C #define IXGBE_APAE 0x04250 #define IXGBE_ARD 0x04254 #define IXGBE_AIS 0x04258 #define IXGBE_MSCA 0x0425C #define IXGBE_MSRWD 0x04260 #define IXGBE_MLADD 0x04264 #define IXGBE_MHADD 0x04268 #define IXGBE_MAXFRS 0x04268 #define IXGBE_TREG 0x0426C #define IXGBE_PCSS1 0x04288 #define IXGBE_PCSS2 0x0428C #define IXGBE_XPCSS 0x04290 #define IXGBE_MFLCN 0x04294 #define IXGBE_SERDESC 0x04298 #define IXGBE_MACS 0x0429C #define IXGBE_AUTOC 0x042A0 #define IXGBE_LINKS 0x042A4 #define IXGBE_LINKS2 0x04324 #define IXGBE_AUTOC2 0x042A8 #define IXGBE_AUTOC3 0x042AC #define IXGBE_ANLP1 0x042B0 #define IXGBE_ANLP2 0x042B4 #define IXGBE_MACC 0x04330 #define IXGBE_ATLASCTL 0x04800 #define IXGBE_MMNGC 0x042D0 #define IXGBE_ANLPNP1 0x042D4 #define IXGBE_ANLPNP2 0x042D8 #define IXGBE_KRPCSFC 0x042E0 #define IXGBE_KRPCSS 0x042E4 #define IXGBE_FECS1 0x042E8 #define IXGBE_FECS2 0x042EC #define IXGBE_SMADARCTL 0x14F10 #define IXGBE_MPVC 0x04318 #define IXGBE_SGMIIC 0x04314 /* Statistics Registers */ #define IXGBE_RXNFGPC 0x041B0 #define IXGBE_RXNFGBCL 0x041B4 #define IXGBE_RXNFGBCH 0x041B8 #define IXGBE_RXDGPC 0x02F50 #define IXGBE_RXDGBCL 0x02F54 #define IXGBE_RXDGBCH 0x02F58 #define IXGBE_RXDDGPC 0x02F5C #define IXGBE_RXDDGBCL 0x02F60 #define IXGBE_RXDDGBCH 0x02F64 #define IXGBE_RXLPBKGPC 0x02F68 #define IXGBE_RXLPBKGBCL 0x02F6C #define IXGBE_RXLPBKGBCH 0x02F70 #define IXGBE_RXDLPBKGPC 0x02F74 #define IXGBE_RXDLPBKGBCL 0x02F78 #define IXGBE_RXDLPBKGBCH 0x02F7C #define IXGBE_TXDGPC 0x087A0 #define IXGBE_TXDGBCL 0x087A4 #define IXGBE_TXDGBCH 0x087A8 #define IXGBE_RXDSTATCTRL 0x02F40 /* Copper Pond 2 link timeout */ #define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50 /* Omer CORECTL */ #define IXGBE_CORECTL 0x014F00 /* BARCTRL */ #define IXGBE_BARCTRL 0x110F4 #define IXGBE_BARCTRL_FLSIZE 0x0700 #define IXGBE_BARCTRL_FLSIZE_SHIFT 8 #define IXGBE_BARCTRL_CSRSIZE 0x2000 /* RSCCTL Bit Masks */ #define IXGBE_RSCCTL_RSCEN 0x01 #define IXGBE_RSCCTL_MAXDESC_1 0x00 #define IXGBE_RSCCTL_MAXDESC_4 0x04 #define IXGBE_RSCCTL_MAXDESC_8 0x08 #define IXGBE_RSCCTL_MAXDESC_16 0x0C /* RSCDBU Bit Masks */ #define IXGBE_RSCDBU_RSCSMALDIS_MASK 0x0000007F #define IXGBE_RSCDBU_RSCACKDIS 0x00000080 /* RDRXCTL Bit Masks */ #define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min THLD Size */ #define IXGBE_RDRXCTL_CRCSTRIP 0x00000002 /* CRC Strip */ #define IXGBE_RDRXCTL_MVMEN 0x00000020 #define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */ #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ #define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */ #define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disabl RSC compl on LLI */ #define IXGBE_RDRXCTL_RSCACKC 0x02000000 /* must set 1 when RSC ena */ #define IXGBE_RDRXCTL_FCOE_WRFIX 0x04000000 /* must set 1 when RSC ena */ /* RQTC Bit Masks and Shifts */ #define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4) #define IXGBE_RQTC_TC0_MASK (0x7 << 0) #define IXGBE_RQTC_TC1_MASK (0x7 << 4) #define IXGBE_RQTC_TC2_MASK (0x7 << 8) #define IXGBE_RQTC_TC3_MASK (0x7 << 12) #define IXGBE_RQTC_TC4_MASK (0x7 << 16) #define IXGBE_RQTC_TC5_MASK (0x7 << 20) #define IXGBE_RQTC_TC6_MASK (0x7 << 24) #define IXGBE_RQTC_TC7_MASK (0x7 << 28) /* PSRTYPE.RQPL Bit masks and shift */ #define IXGBE_PSRTYPE_RQPL_MASK 0x7 #define IXGBE_PSRTYPE_RQPL_SHIFT 29 /* CTRL Bit Masks */ #define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */ #define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */ #define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */ #define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST) /* FACTPS */ #define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */ /* MHADD Bit Masks */ #define IXGBE_MHADD_MFS_MASK 0xFFFF0000 #define IXGBE_MHADD_MFS_SHIFT 16 /* Extended Device Control */ #define IXGBE_CTRL_EXT_PFRSTD 0x00004000 /* Physical Function Reset Done */ #define IXGBE_CTRL_EXT_NS_DIS 0x00010000 /* No Snoop disable */ #define IXGBE_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ #define IXGBE_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ /* Direct Cache Access (DCA) definitions */ #define IXGBE_DCA_CTRL_DCA_ENABLE 0x00000000 /* DCA Enable */ #define IXGBE_DCA_CTRL_DCA_DISABLE 0x00000001 /* DCA Disable */ #define IXGBE_DCA_CTRL_DCA_MODE_CB1 0x00 /* DCA Mode CB1 */ #define IXGBE_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */ #define IXGBE_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_MASK_82599 0xFF000000 /* Rx CPUID Mask */ #define IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599 24 /* Rx CPUID Shift */ #define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* Rx Desc enable */ #define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* Rx Desc header ena */ #define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* Rx Desc payload ena */ #define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* Rx rd Desc Relax Order */ #define IXGBE_DCA_RXCTRL_DATA_WRO_EN (1 << 13) /* Rx wr data Relax Order */ #define IXGBE_DCA_RXCTRL_HEAD_WRO_EN (1 << 15) /* Rx wr header RO */ #define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_MASK_82599 0xFF000000 /* Tx CPUID Mask */ #define IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599 24 /* Tx CPUID Shift */ #define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ #define IXGBE_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define IXGBE_DCA_TXCTRL_DESC_WRO_EN (1 << 11) /* Tx Desc writeback RO bit */ #define IXGBE_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ #define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */ /* MSCA Bit Masks */ #define IXGBE_MSCA_NP_ADDR_MASK 0x0000FFFF /* MDI Addr (new prot) */ #define IXGBE_MSCA_NP_ADDR_SHIFT 0 #define IXGBE_MSCA_DEV_TYPE_MASK 0x001F0000 /* Dev Type (new prot) */ #define IXGBE_MSCA_DEV_TYPE_SHIFT 16 /* Register Address (old prot */ #define IXGBE_MSCA_PHY_ADDR_MASK 0x03E00000 /* PHY Address mask */ #define IXGBE_MSCA_PHY_ADDR_SHIFT 21 /* PHY Address shift*/ #define IXGBE_MSCA_OP_CODE_MASK 0x0C000000 /* OP CODE mask */ #define IXGBE_MSCA_OP_CODE_SHIFT 26 /* OP CODE shift */ #define IXGBE_MSCA_ADDR_CYCLE 0x00000000 /* OP CODE 00 (addr cycle) */ #define IXGBE_MSCA_WRITE 0x04000000 /* OP CODE 01 (wr) */ #define IXGBE_MSCA_READ 0x0C000000 /* OP CODE 11 (rd) */ #define IXGBE_MSCA_READ_AUTOINC 0x08000000 /* OP CODE 10 (rd auto inc)*/ #define IXGBE_MSCA_ST_CODE_MASK 0x30000000 /* ST Code mask */ #define IXGBE_MSCA_ST_CODE_SHIFT 28 /* ST Code shift */ #define IXGBE_MSCA_NEW_PROTOCOL 0x00000000 /* ST CODE 00 (new prot) */ #define IXGBE_MSCA_OLD_PROTOCOL 0x10000000 /* ST CODE 01 (old prot) */ #define IXGBE_MSCA_MDI_COMMAND 0x40000000 /* Initiate MDI command */ #define IXGBE_MSCA_MDI_IN_PROG_EN 0x80000000 /* MDI in progress ena */ /* MSRWD bit masks */ #define IXGBE_MSRWD_WRITE_DATA_MASK 0x0000FFFF #define IXGBE_MSRWD_WRITE_DATA_SHIFT 0 #define IXGBE_MSRWD_READ_DATA_MASK 0xFFFF0000 #define IXGBE_MSRWD_READ_DATA_SHIFT 16 /* Atlas registers */ #define IXGBE_ATLAS_PDN_LPBK 0x24 #define IXGBE_ATLAS_PDN_10G 0xB #define IXGBE_ATLAS_PDN_1G 0xC #define IXGBE_ATLAS_PDN_AN 0xD /* Atlas bit masks */ #define IXGBE_ATLASCTL_WRITE_CMD 0x00010000 #define IXGBE_ATLAS_PDN_TX_REG_EN 0x10 #define IXGBE_ATLAS_PDN_TX_10G_QL_ALL 0xF0 #define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0 #define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0 /* Omer bit masks */ #define IXGBE_CORECTL_WRITE_CMD 0x00010000 /* Device Type definitions for new protocol MDIO commands */ #define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1 #define IXGBE_MDIO_PCS_DEV_TYPE 0x3 #define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4 #define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */ #define IXGBE_TWINAX_DEV 1 #define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL 0x0 /* VS1 Ctrl Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS 0x1 /* VS1 Status Reg */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS 0x0008 /* 1 = Link Up */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0-10G, 1-1G */ #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED 0x0018 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED 0x0010 #define IXGBE_MDIO_AUTO_NEG_CONTROL 0x0 /* AUTO_NEG Control Reg */ #define IXGBE_MDIO_AUTO_NEG_STATUS 0x1 /* AUTO_NEG Status Reg */ #define IXGBE_MDIO_AUTO_NEG_ADVT 0x10 /* AUTO_NEG Advt Reg */ #define IXGBE_MDIO_AUTO_NEG_LP 0x13 /* AUTO_NEG LP Status Reg */ #define IXGBE_MDIO_PHY_XS_CONTROL 0x0 /* PHY_XS Control Reg */ #define IXGBE_MDIO_PHY_XS_RESET 0x8000 /* PHY_XS Reset */ #define IXGBE_MDIO_PHY_ID_HIGH 0x2 /* PHY ID High Reg*/ #define IXGBE_MDIO_PHY_ID_LOW 0x3 /* PHY ID Low Reg*/ #define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */ #define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */ #define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */ #define IXGBE_MDIO_PHY_SPEED_100M 0x0020 /* 100M capable */ #define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */ #define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */ #define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */ #define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */ #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE 0x0800 /* Set low power mode */ #define IXGBE_MDIO_PMA_PMD_CONTROL_ADDR 0x0000 /* PMA/PMD Control Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ /* MII clause 22/28 definitions */ #define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 #define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */ #define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ #define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ #define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */ #define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12*/ #define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/ #define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/ #define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */ #define IXGBE_MII_100BASE_T_ADVERTISE_HALF 0x0080 /* half duplex, bit:7 */ #define IXGBE_MII_RESTART 0x200 #define IXGBE_MII_AUTONEG_COMPLETE 0x20 #define IXGBE_MII_AUTONEG_LINK_UP 0x04 #define IXGBE_MII_AUTONEG_REG 0x0 #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 #define IXGBE_MAX_PHY_ADDR 32 /* PHY IDs*/ #define TN1010_PHY_ID 0x00A19410 #define TNX_FW_REV 0xB #define X540_PHY_ID 0x01540200 #define AQ_FW_REV 0x20 #define QT2022_PHY_ID 0x0043A400 #define ATH_PHY_ID 0x03429050 /* PHY Types */ #define IXGBE_M88E1145_E_PHY_ID 0x01410CD0 /* Special PHY Init Routine */ #define IXGBE_PHY_INIT_OFFSET_NL 0x002B #define IXGBE_PHY_INIT_END_NL 0xFFFF #define IXGBE_CONTROL_MASK_NL 0xF000 #define IXGBE_DATA_MASK_NL 0x0FFF #define IXGBE_CONTROL_SHIFT_NL 12 #define IXGBE_DELAY_NL 0 #define IXGBE_DATA_NL 1 #define IXGBE_CONTROL_NL 0x000F #define IXGBE_CONTROL_EOL_NL 0x0FFF #define IXGBE_CONTROL_SOL_NL 0x0000 /* General purpose Interrupt Enable */ #define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */ #define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */ #define IXGBE_SDP2_GPIEN 0x00000004 /* SDP2 */ #define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */ #define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */ #define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */ #define IXGBE_GPIE_EIAME 0x40000000 #define IXGBE_GPIE_PBA_SUPPORT 0x80000000 #define IXGBE_GPIE_RSC_DELAY_SHIFT 11 #define IXGBE_GPIE_VTMODE_MASK 0x0000C000 /* VT Mode Mask */ #define IXGBE_GPIE_VTMODE_16 0x00004000 /* 16 VFs 8 queues per VF */ #define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */ #define IXGBE_GPIE_VTMODE_64 0x0000C000 /* 64 VFs 2 queues per VF */ /* Packet Buffer Initialization */ #define IXGBE_MAX_PACKET_BUFFERS 8 #define IXGBE_TXPBSIZE_20KB 0x00005000 /* 20KB Packet Buffer */ #define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */ #define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */ #define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */ #define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */ #define IXGBE_RXPBSIZE_128KB 0x00020000 /* 128KB Packet Buffer */ #define IXGBE_RXPBSIZE_MAX 0x00080000 /* 512KB Packet Buffer */ #define IXGBE_TXPBSIZE_MAX 0x00028000 /* 160KB Packet Buffer */ #define IXGBE_TXPKT_SIZE_MAX 0xA /* Max Tx Packet size */ #define IXGBE_MAX_PB 8 /* Packet buffer allocation strategies */ enum { PBA_STRATEGY_EQUAL = 0, /* Distribute PB space equally */ #define PBA_STRATEGY_EQUAL PBA_STRATEGY_EQUAL PBA_STRATEGY_WEIGHTED = 1, /* Weight front half of TCs */ #define PBA_STRATEGY_WEIGHTED PBA_STRATEGY_WEIGHTED }; /* Transmit Flow Control status */ #define IXGBE_TFCS_TXOFF 0x00000001 #define IXGBE_TFCS_TXOFF0 0x00000100 #define IXGBE_TFCS_TXOFF1 0x00000200 #define IXGBE_TFCS_TXOFF2 0x00000400 #define IXGBE_TFCS_TXOFF3 0x00000800 #define IXGBE_TFCS_TXOFF4 0x00001000 #define IXGBE_TFCS_TXOFF5 0x00002000 #define IXGBE_TFCS_TXOFF6 0x00004000 #define IXGBE_TFCS_TXOFF7 0x00008000 /* TCP Timer */ #define IXGBE_TCPTIMER_KS 0x00000100 #define IXGBE_TCPTIMER_COUNT_ENABLE 0x00000200 #define IXGBE_TCPTIMER_COUNT_FINISH 0x00000400 #define IXGBE_TCPTIMER_LOOP 0x00000800 #define IXGBE_TCPTIMER_DURATION_MASK 0x000000FF /* HLREG0 Bit Masks */ #define IXGBE_HLREG0_TXCRCEN 0x00000001 /* bit 0 */ #define IXGBE_HLREG0_RXCRCSTRP 0x00000002 /* bit 1 */ #define IXGBE_HLREG0_JUMBOEN 0x00000004 /* bit 2 */ #define IXGBE_HLREG0_TXPADEN 0x00000400 /* bit 10 */ #define IXGBE_HLREG0_TXPAUSEEN 0x00001000 /* bit 12 */ #define IXGBE_HLREG0_RXPAUSEEN 0x00004000 /* bit 14 */ #define IXGBE_HLREG0_LPBK 0x00008000 /* bit 15 */ #define IXGBE_HLREG0_MDCSPD 0x00010000 /* bit 16 */ #define IXGBE_HLREG0_CONTMDC 0x00020000 /* bit 17 */ #define IXGBE_HLREG0_CTRLFLTR 0x00040000 /* bit 18 */ #define IXGBE_HLREG0_PREPEND 0x00F00000 /* bits 20-23 */ #define IXGBE_HLREG0_PRIPAUSEEN 0x01000000 /* bit 24 */ #define IXGBE_HLREG0_RXPAUSERECDA 0x06000000 /* bits 25-26 */ #define IXGBE_HLREG0_RXLNGTHERREN 0x08000000 /* bit 27 */ #define IXGBE_HLREG0_RXPADSTRIPEN 0x10000000 /* bit 28 */ /* VMD_CTL bitmasks */ #define IXGBE_VMD_CTL_VMDQ_EN 0x00000001 #define IXGBE_VMD_CTL_VMDQ_FILTER 0x00000002 /* VT_CTL bitmasks */ #define IXGBE_VT_CTL_DIS_DEFPL 0x20000000 /* disable default pool */ #define IXGBE_VT_CTL_REPLEN 0x40000000 /* replication enabled */ #define IXGBE_VT_CTL_VT_ENABLE 0x00000001 /* Enable VT Mode */ #define IXGBE_VT_CTL_POOL_SHIFT 7 #define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT) /* VMOLR bitmasks */ #define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */ #define IXGBE_VMOLR_ROMPE 0x02000000 /* accept packets in MTA tbl */ #define IXGBE_VMOLR_ROPE 0x04000000 /* accept packets in UC tbl */ #define IXGBE_VMOLR_BAM 0x08000000 /* accept broadcast packets */ #define IXGBE_VMOLR_MPE 0x10000000 /* multicast promiscuous */ /* VFRE bitmask */ #define IXGBE_VFRE_ENABLE_ALL 0xFFFFFFFF #define IXGBE_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ /* RDHMPN and TDHMPN bitmasks */ #define IXGBE_RDHMPN_RDICADDR 0x007FF800 #define IXGBE_RDHMPN_RDICRDREQ 0x00800000 #define IXGBE_RDHMPN_RDICADDR_SHIFT 11 #define IXGBE_TDHMPN_TDICADDR 0x003FF800 #define IXGBE_TDHMPN_TDICRDREQ 0x00800000 #define IXGBE_TDHMPN_TDICADDR_SHIFT 11 #define IXGBE_RDMAM_MEM_SEL_SHIFT 13 #define IXGBE_RDMAM_DWORD_SHIFT 9 #define IXGBE_RDMAM_DESC_COMP_FIFO 1 #define IXGBE_RDMAM_DFC_CMD_FIFO 2 #define IXGBE_RDMAM_RSC_HEADER_ADDR 3 #define IXGBE_RDMAM_TCN_STATUS_RAM 4 #define IXGBE_RDMAM_WB_COLL_FIFO 5 #define IXGBE_RDMAM_QSC_CNT_RAM 6 #define IXGBE_RDMAM_QSC_FCOE_RAM 7 #define IXGBE_RDMAM_QSC_QUEUE_CNT 8 #define IXGBE_RDMAM_QSC_QUEUE_RAM 0xA #define IXGBE_RDMAM_QSC_RSC_RAM 0xB #define IXGBE_RDMAM_DESC_COM_FIFO_RANGE 135 #define IXGBE_RDMAM_DESC_COM_FIFO_COUNT 4 #define IXGBE_RDMAM_DFC_CMD_FIFO_RANGE 48 #define IXGBE_RDMAM_DFC_CMD_FIFO_COUNT 7 #define IXGBE_RDMAM_RSC_HEADER_ADDR_RANGE 32 #define IXGBE_RDMAM_RSC_HEADER_ADDR_COUNT 4 #define IXGBE_RDMAM_TCN_STATUS_RAM_RANGE 256 #define IXGBE_RDMAM_TCN_STATUS_RAM_COUNT 9 #define IXGBE_RDMAM_WB_COLL_FIFO_RANGE 8 #define IXGBE_RDMAM_WB_COLL_FIFO_COUNT 4 #define IXGBE_RDMAM_QSC_CNT_RAM_RANGE 64 #define IXGBE_RDMAM_QSC_CNT_RAM_COUNT 4 #define IXGBE_RDMAM_QSC_FCOE_RAM_RANGE 512 #define IXGBE_RDMAM_QSC_FCOE_RAM_COUNT 5 #define IXGBE_RDMAM_QSC_QUEUE_CNT_RANGE 32 #define IXGBE_RDMAM_QSC_QUEUE_CNT_COUNT 4 #define IXGBE_RDMAM_QSC_QUEUE_RAM_RANGE 128 #define IXGBE_RDMAM_QSC_QUEUE_RAM_COUNT 8 #define IXGBE_RDMAM_QSC_RSC_RAM_RANGE 32 #define IXGBE_RDMAM_QSC_RSC_RAM_COUNT 8 #define IXGBE_TXDESCIC_READY 0x80000000 /* Receive Checksum Control */ #define IXGBE_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define IXGBE_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* FCRTL Bit Masks */ #define IXGBE_FCRTL_XONE 0x80000000 /* XON enable */ #define IXGBE_FCRTH_FCEN 0x80000000 /* Packet buffer fc enable */ /* PAP bit masks*/ #define IXGBE_PAP_TXPAUSECNT_MASK 0x0000FFFF /* Pause counter mask */ /* RMCS Bit Masks */ #define IXGBE_RMCS_RRM 0x00000002 /* Rx Recycle Mode enable */ /* Receive Arbitration Control: 0 Round Robin, 1 DFP */ #define IXGBE_RMCS_RAC 0x00000004 /* Deficit Fixed Prio ena */ #define IXGBE_RMCS_DFP IXGBE_RMCS_RAC #define IXGBE_RMCS_TFCE_802_3X 0x00000008 /* Tx Priority FC ena */ #define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority FC ena */ #define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */ /* FCCFG Bit Masks */ #define IXGBE_FCCFG_TFCE_802_3X 0x00000008 /* Tx link FC enable */ #define IXGBE_FCCFG_TFCE_PRIORITY 0x00000010 /* Tx priority FC enable */ /* Interrupt register bitmasks */ /* Extended Interrupt Cause Read */ #define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ #define IXGBE_EICR_FLOW_DIR 0x00010000 /* FDir Exception */ #define IXGBE_EICR_RX_MISS 0x00020000 /* Packet Buffer Overrun */ #define IXGBE_EICR_PCI 0x00040000 /* PCI Exception */ #define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */ #define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */ #define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */ #define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */ #define IXGBE_EICR_TS 0x00800000 /* Thermal Sensor Event */ #define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */ #define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */ #define IXGBE_EICR_GPI_SDP2 0x04000000 /* Gen Purpose Interrupt on SDP2 */ #define IXGBE_EICR_ECC 0x10000000 /* ECC Error */ #define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */ #define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */ #define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */ #define IXGBE_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ /* Extended Interrupt Cause Set */ #define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EICS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EICS_RX_MISS IXGBE_EICR_RX_MISS /* Pkt Buffer Overrun */ #define IXGBE_EICS_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EICS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EICS_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */ #define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ /* Extended Interrupt Mask Set */ #define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EIMS_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */ #define IXGBE_EIMS_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EIMS_TS IXGBE_EICR_TS /* Thermal Sensor Event */ #define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EIMS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EIMS_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */ #define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ /* Extended Interrupt Mask Clear */ #define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ #define IXGBE_EIMC_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */ #define IXGBE_EIMC_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */ #define IXGBE_EIMC_PCI IXGBE_EICR_PCI /* PCI Exception */ #define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ #define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */ #define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */ #define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */ #define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */ #define IXGBE_EIMC_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */ #define IXGBE_EIMC_ECC IXGBE_EICR_ECC /* ECC Error */ #define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */ #define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ #define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ #define IXGBE_EIMS_ENABLE_MASK ( \ IXGBE_EIMS_RTX_QUEUE | \ IXGBE_EIMS_LSC | \ IXGBE_EIMS_TCP_TIMER | \ IXGBE_EIMS_OTHER) /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */ #define IXGBE_IMIR_PORT_IM_EN 0x00010000 /* TCP port enable */ #define IXGBE_IMIR_PORT_BP 0x00020000 /* TCP port check bypass */ #define IXGBE_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */ #define IXGBE_IMIREXT_CTRL_URG 0x00002000 /* Check URG bit in header */ #define IXGBE_IMIREXT_CTRL_ACK 0x00004000 /* Check ACK bit in header */ #define IXGBE_IMIREXT_CTRL_PSH 0x00008000 /* Check PSH bit in header */ #define IXGBE_IMIREXT_CTRL_RST 0x00010000 /* Check RST bit in header */ #define IXGBE_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */ #define IXGBE_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */ #define IXGBE_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of control bits */ #define IXGBE_IMIR_SIZE_BP_82599 0x00001000 /* Packet size bypass */ #define IXGBE_IMIR_CTRL_URG_82599 0x00002000 /* Check URG bit in header */ #define IXGBE_IMIR_CTRL_ACK_82599 0x00004000 /* Check ACK bit in header */ #define IXGBE_IMIR_CTRL_PSH_82599 0x00008000 /* Check PSH bit in header */ #define IXGBE_IMIR_CTRL_RST_82599 0x00010000 /* Check RST bit in header */ #define IXGBE_IMIR_CTRL_SYN_82599 0x00020000 /* Check SYN bit in header */ #define IXGBE_IMIR_CTRL_FIN_82599 0x00040000 /* Check FIN bit in header */ #define IXGBE_IMIR_CTRL_BP_82599 0x00080000 /* Bypass chk of ctrl bits */ #define IXGBE_IMIR_LLI_EN_82599 0x00100000 /* Enables low latency Int */ #define IXGBE_IMIR_RX_QUEUE_MASK_82599 0x0000007F /* Rx Queue Mask */ #define IXGBE_IMIR_RX_QUEUE_SHIFT_82599 21 /* Rx Queue Shift */ #define IXGBE_IMIRVP_PRIORITY_MASK 0x00000007 /* VLAN priority mask */ #define IXGBE_IMIRVP_PRIORITY_EN 0x00000008 /* VLAN priority enable */ #define IXGBE_MAX_FTQF_FILTERS 128 #define IXGBE_FTQF_PROTOCOL_MASK 0x00000003 #define IXGBE_FTQF_PROTOCOL_TCP 0x00000000 #define IXGBE_FTQF_PROTOCOL_UDP 0x00000001 #define IXGBE_FTQF_PROTOCOL_SCTP 2 #define IXGBE_FTQF_PRIORITY_MASK 0x00000007 #define IXGBE_FTQF_PRIORITY_SHIFT 2 #define IXGBE_FTQF_POOL_MASK 0x0000003F #define IXGBE_FTQF_POOL_SHIFT 8 #define IXGBE_FTQF_5TUPLE_MASK_MASK 0x0000001F #define IXGBE_FTQF_5TUPLE_MASK_SHIFT 25 #define IXGBE_FTQF_SOURCE_ADDR_MASK 0x1E #define IXGBE_FTQF_DEST_ADDR_MASK 0x1D #define IXGBE_FTQF_SOURCE_PORT_MASK 0x1B #define IXGBE_FTQF_DEST_PORT_MASK 0x17 #define IXGBE_FTQF_PROTOCOL_COMP_MASK 0x0F #define IXGBE_FTQF_POOL_MASK_EN 0x40000000 #define IXGBE_FTQF_QUEUE_ENABLE 0x80000000 /* Interrupt clear mask */ #define IXGBE_IRQ_CLEAR_MASK 0xFFFFFFFF /* Interrupt Vector Allocation Registers */ #define IXGBE_IVAR_REG_NUM 25 #define IXGBE_IVAR_REG_NUM_82599 64 #define IXGBE_IVAR_TXRX_ENTRY 96 #define IXGBE_IVAR_RX_ENTRY 64 #define IXGBE_IVAR_RX_QUEUE(_i) (0 + (_i)) #define IXGBE_IVAR_TX_QUEUE(_i) (64 + (_i)) #define IXGBE_IVAR_TX_ENTRY 32 #define IXGBE_IVAR_TCP_TIMER_INDEX 96 /* 0 based index */ #define IXGBE_IVAR_OTHER_CAUSES_INDEX 97 /* 0 based index */ #define IXGBE_MSIX_VECTOR(_i) (0 + (_i)) #define IXGBE_IVAR_ALLOC_VAL 0x80 /* Interrupt Allocation valid */ /* ETYPE Queue Filter/Select Bit Masks */ #define IXGBE_MAX_ETQF_FILTERS 8 #define IXGBE_ETQF_FCOE 0x08000000 /* bit 27 */ #define IXGBE_ETQF_BCN 0x10000000 /* bit 28 */ #define IXGBE_ETQF_1588 0x40000000 /* bit 30 */ #define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */ #define IXGBE_ETQF_POOL_ENABLE (1 << 26) /* bit 26 */ #define IXGBE_ETQS_RX_QUEUE 0x007F0000 /* bits 22:16 */ #define IXGBE_ETQS_RX_QUEUE_SHIFT 16 #define IXGBE_ETQS_LLI 0x20000000 /* bit 29 */ #define IXGBE_ETQS_QUEUE_EN 0x80000000 /* bit 31 */ /* * ETQF filter list: one static filter per filter consumer. This is * to avoid filter collisions later. Add new filters * here!! * * Current filters: * EAPOL 802.1x (0x888e): Filter 0 * FCoE (0x8906): Filter 2 * 1588 (0x88f7): Filter 3 * FIP (0x8914): Filter 4 */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_FCOE 2 #define IXGBE_ETQF_FILTER_1588 3 #define IXGBE_ETQF_FILTER_FIP 4 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ #define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */ #define IXGBE_VLNCTRL_CFIEN 0x20000000 /* bit 29 */ #define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */ #define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */ /* VLAN pool filtering masks */ #define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */ #define IXGBE_VLVF_ENTRIES 64 #define IXGBE_VLVF_VLANID_MASK 0x00000FFF /* Per VF Port VLAN insertion rules */ #define IXGBE_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */ #define IXGBE_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */ #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ /* STATUS Bit Masks */ #define IXGBE_STATUS_LAN_ID 0x0000000C /* LAN ID */ #define IXGBE_STATUS_LAN_ID_SHIFT 2 /* LAN ID Shift*/ #define IXGBE_STATUS_GIO 0x00080000 /* GIO Master Ena Status */ #define IXGBE_STATUS_LAN_ID_0 0x00000000 /* LAN ID 0 */ #define IXGBE_STATUS_LAN_ID_1 0x00000004 /* LAN ID 1 */ /* ESDP Bit Masks */ #define IXGBE_ESDP_SDP0 0x00000001 /* SDP0 Data Value */ #define IXGBE_ESDP_SDP1 0x00000002 /* SDP1 Data Value */ #define IXGBE_ESDP_SDP2 0x00000004 /* SDP2 Data Value */ #define IXGBE_ESDP_SDP3 0x00000008 /* SDP3 Data Value */ #define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */ #define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */ #define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */ #define IXGBE_ESDP_SDP0_DIR 0x00000100 /* SDP0 IO direction */ #define IXGBE_ESDP_SDP1_DIR 0x00000200 /* SDP1 IO direction */ #define IXGBE_ESDP_SDP4_DIR 0x00001000 /* SDP4 IO direction */ #define IXGBE_ESDP_SDP5_DIR 0x00002000 /* SDP5 IO direction */ #define IXGBE_ESDP_SDP0_NATIVE 0x00010000 /* SDP0 IO mode */ #define IXGBE_ESDP_SDP1_NATIVE 0x00020000 /* SDP1 IO mode */ /* LEDCTL Bit Masks */ #define IXGBE_LED_IVRT_BASE 0x00000040 #define IXGBE_LED_BLINK_BASE 0x00000080 #define IXGBE_LED_MODE_MASK_BASE 0x0000000F #define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i))) #define IXGBE_LED_MODE_SHIFT(_i) (8*(_i)) #define IXGBE_LED_IVRT(_i) IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i) #define IXGBE_LED_BLINK(_i) IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i) #define IXGBE_LED_MODE_MASK(_i) IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i) /* LED modes */ #define IXGBE_LED_LINK_UP 0x0 #define IXGBE_LED_LINK_10G 0x1 #define IXGBE_LED_MAC 0x2 #define IXGBE_LED_FILTER 0x3 #define IXGBE_LED_LINK_ACTIVE 0x4 #define IXGBE_LED_LINK_1G 0x5 #define IXGBE_LED_ON 0xE #define IXGBE_LED_OFF 0xF /* AUTOC Bit Masks */ #define IXGBE_AUTOC_KX4_KX_SUPP_MASK 0xC0000000 #define IXGBE_AUTOC_KX4_SUPP 0x80000000 #define IXGBE_AUTOC_KX_SUPP 0x40000000 #define IXGBE_AUTOC_PAUSE 0x30000000 #define IXGBE_AUTOC_ASM_PAUSE 0x20000000 #define IXGBE_AUTOC_SYM_PAUSE 0x10000000 #define IXGBE_AUTOC_RF 0x08000000 #define IXGBE_AUTOC_PD_TMR 0x06000000 #define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000 #define IXGBE_AUTOC_AN_RX_DRIFT 0x00800000 #define IXGBE_AUTOC_AN_RX_ALIGN 0x007C0000 #define IXGBE_AUTOC_FECA 0x00040000 #define IXGBE_AUTOC_FECR 0x00020000 #define IXGBE_AUTOC_KR_SUPP 0x00010000 #define IXGBE_AUTOC_AN_RESTART 0x00001000 #define IXGBE_AUTOC_FLU 0x00000001 #define IXGBE_AUTOC_LMS_SHIFT 13 #define IXGBE_AUTOC_LMS_10G_SERIAL (0x3 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR (0x4 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_SGMII_1G_100M (0x5 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII (0x7 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_1G_AN (0x2 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_AN (0x4 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT) #define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_PMA_PMD_MASK 0x00000200 #define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9 #define IXGBE_AUTOC_10G_PMA_PMD_MASK 0x00000180 #define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7 #define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_10G_KX4 (0x1 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_10G_CX4 (0x2 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_BX (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_KX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_SFI (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC_1G_KX_BX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_UPPER_MASK 0xFFFF0000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK 0x00030000 #define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT 16 #define IXGBE_AUTOC2_10G_KR (0x0 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT) #define IXGBE_MACC_FLU 0x00000001 #define IXGBE_MACC_FSV_10G 0x00030000 #define IXGBE_MACC_FS 0x00040000 #define IXGBE_MAC_RX2TX_LPBK 0x00000002 /* LINKS Bit Masks */ #define IXGBE_LINKS_KX_AN_COMP 0x80000000 #define IXGBE_LINKS_UP 0x40000000 #define IXGBE_LINKS_SPEED 0x20000000 #define IXGBE_LINKS_MODE 0x18000000 #define IXGBE_LINKS_RX_MODE 0x06000000 #define IXGBE_LINKS_TX_MODE 0x01800000 #define IXGBE_LINKS_XGXS_EN 0x00400000 #define IXGBE_LINKS_SGMII_EN 0x02000000 #define IXGBE_LINKS_PCS_1G_EN 0x00200000 #define IXGBE_LINKS_1G_AN_EN 0x00100000 #define IXGBE_LINKS_KX_AN_IDLE 0x00080000 #define IXGBE_LINKS_1G_SYNC 0x00040000 #define IXGBE_LINKS_10G_ALIGN 0x00020000 #define IXGBE_LINKS_10G_LANE_SYNC 0x00017000 #define IXGBE_LINKS_TL_FAULT 0x00001000 #define IXGBE_LINKS_SIGNAL 0x00000F00 #define IXGBE_LINKS_SPEED_82599 0x30000000 #define IXGBE_LINKS_SPEED_10G_82599 0x30000000 #define IXGBE_LINKS_SPEED_1G_82599 0x20000000 #define IXGBE_LINKS_SPEED_100_82599 0x10000000 #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ #define IXGBE_LINKS2_AN_SUPPORTED 0x00000040 /* PCS1GLSTA Bit Masks */ #define IXGBE_PCS1GLSTA_LINK_OK 1 #define IXGBE_PCS1GLSTA_SYNK_OK 0x10 #define IXGBE_PCS1GLSTA_AN_COMPLETE 0x10000 #define IXGBE_PCS1GLSTA_AN_PAGE_RX 0x20000 #define IXGBE_PCS1GLSTA_AN_TIMED_OUT 0x40000 #define IXGBE_PCS1GLSTA_AN_REMOTE_FAULT 0x80000 #define IXGBE_PCS1GLSTA_AN_ERROR_RWS 0x100000 #define IXGBE_PCS1GANA_SYM_PAUSE 0x80 #define IXGBE_PCS1GANA_ASM_PAUSE 0x100 /* PCS1GLCTL Bit Masks */ #define IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN 0x00040000 /* PCS 1G autoneg to en */ #define IXGBE_PCS1GLCTL_FLV_LINK_UP 1 #define IXGBE_PCS1GLCTL_FORCE_LINK 0x20 #define IXGBE_PCS1GLCTL_LOW_LINK_LATCH 0x40 #define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 #define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 /* ANLP1 Bit Masks */ #define IXGBE_ANLP1_PAUSE 0x0C00 #define IXGBE_ANLP1_SYM_PAUSE 0x0400 #define IXGBE_ANLP1_ASM_PAUSE 0x0800 #define IXGBE_ANLP1_AN_STATE_MASK 0x000f0000 /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define IXGBE_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ #define IXGBE_SWFW_REGSMP 0x80000000 /* Register Semaphore bit 31 */ /* SW_FW_SYNC/GSSR definitions */ #define IXGBE_GSSR_EEP_SM 0x0001 #define IXGBE_GSSR_PHY0_SM 0x0002 #define IXGBE_GSSR_PHY1_SM 0x0004 #define IXGBE_GSSR_MAC_CSR_SM 0x0008 #define IXGBE_GSSR_FLASH_SM 0x0010 #define IXGBE_GSSR_SW_MNG_SM 0x0400 /* FW Status register bitmask */ #define IXGBE_FWSTS_FWRI 0x00000200 /* Firmware Reset Indication */ /* EEC Register */ #define IXGBE_EEC_SK 0x00000001 /* EEPROM Clock */ #define IXGBE_EEC_CS 0x00000002 /* EEPROM Chip Select */ #define IXGBE_EEC_DI 0x00000004 /* EEPROM Data In */ #define IXGBE_EEC_DO 0x00000008 /* EEPROM Data Out */ #define IXGBE_EEC_FWE_MASK 0x00000030 /* FLASH Write Enable */ #define IXGBE_EEC_FWE_DIS 0x00000010 /* Disable FLASH writes */ #define IXGBE_EEC_FWE_EN 0x00000020 /* Enable FLASH writes */ #define IXGBE_EEC_FWE_SHIFT 4 #define IXGBE_EEC_REQ 0x00000040 /* EEPROM Access Request */ #define IXGBE_EEC_GNT 0x00000080 /* EEPROM Access Grant */ #define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */ #define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */ #define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */ #define IXGBE_EEC_SEC1VAL 0x02000000 /* Sector 1 Valid */ #define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 #define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */ #define IXGBE_EERD_MAX_ADDR 0x00003FFF /* EERD alows 14 bits for addr. */ #define IXGBE_EEC_SIZE_SHIFT 11 #define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 #define IXGBE_EEPROM_OPCODE_BITS 8 /* Part Number String Length */ #define IXGBE_PBANUM_LENGTH 11 /* Checksum and EEPROM pointers */ #define IXGBE_PBANUM_PTR_GUARD 0xFAFA #define IXGBE_EEPROM_CHECKSUM 0x3F #define IXGBE_EEPROM_SUM 0xBABA #define IXGBE_PCIE_ANALOG_PTR 0x03 #define IXGBE_ATLAS0_CONFIG_PTR 0x04 #define IXGBE_PHY_PTR 0x04 #define IXGBE_ATLAS1_CONFIG_PTR 0x05 #define IXGBE_OPTION_ROM_PTR 0x05 #define IXGBE_PCIE_GENERAL_PTR 0x06 #define IXGBE_PCIE_CONFIG0_PTR 0x07 #define IXGBE_PCIE_CONFIG1_PTR 0x08 #define IXGBE_CORE0_PTR 0x09 #define IXGBE_CORE1_PTR 0x0A #define IXGBE_MAC0_PTR 0x0B #define IXGBE_MAC1_PTR 0x0C #define IXGBE_CSR0_CONFIG_PTR 0x0D #define IXGBE_CSR1_CONFIG_PTR 0x0E #define IXGBE_FW_PTR 0x0F #define IXGBE_PBANUM0_PTR 0x15 #define IXGBE_PBANUM1_PTR 0x16 #define IXGBE_ALT_MAC_ADDR_PTR 0x37 #define IXGBE_FREE_SPACE_PTR 0X3E /* External Thermal Sensor Config */ #define IXGBE_ETS_CFG 0x26 #define IXGBE_ETS_LTHRES_DELTA_MASK 0x07C0 #define IXGBE_ETS_LTHRES_DELTA_SHIFT 6 #define IXGBE_ETS_TYPE_MASK 0x0038 #define IXGBE_ETS_TYPE_SHIFT 3 #define IXGBE_ETS_TYPE_EMC 0x000 #define IXGBE_ETS_NUM_SENSORS_MASK 0x0007 #define IXGBE_ETS_DATA_LOC_MASK 0x3C00 #define IXGBE_ETS_DATA_LOC_SHIFT 10 #define IXGBE_ETS_DATA_INDEX_MASK 0x0300 #define IXGBE_ETS_DATA_INDEX_SHIFT 8 #define IXGBE_ETS_DATA_HTHRESH_MASK 0x00FF #define IXGBE_SAN_MAC_ADDR_PTR 0x28 #define IXGBE_DEVICE_CAPS 0x2C #define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11 #define IXGBE_PCIE_MSIX_82599_CAPS 0x72 #define IXGBE_MAX_MSIX_VECTORS_82599 0x40 #define IXGBE_PCIE_MSIX_82598_CAPS 0x62 #define IXGBE_MAX_MSIX_VECTORS_82598 0x13 /* MSI-X capability fields masks */ #define IXGBE_PCIE_MSIX_TBL_SZ_MASK 0x7FF /* Legacy EEPROM word offsets */ #define IXGBE_ISCSI_BOOT_CAPS 0x0033 #define IXGBE_ISCSI_SETUP_PORT_0 0x0030 #define IXGBE_ISCSI_SETUP_PORT_1 0x0034 /* EEPROM Commands - SPI */ #define IXGBE_EEPROM_MAX_RETRY_SPI 5000 /* Max wait 5ms for RDY signal */ #define IXGBE_EEPROM_STATUS_RDY_SPI 0x01 #define IXGBE_EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ #define IXGBE_EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ #define IXGBE_EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = addr bit-8 */ #define IXGBE_EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Ena latch */ /* EEPROM reset Write Enable latch */ #define IXGBE_EEPROM_WRDI_OPCODE_SPI 0x04 #define IXGBE_EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status reg */ #define IXGBE_EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status reg */ #define IXGBE_EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */ #define IXGBE_EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */ #define IXGBE_EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ /* EEPROM Read Register */ #define IXGBE_EEPROM_RW_REG_DATA 16 /* data offset in EEPROM read reg */ #define IXGBE_EEPROM_RW_REG_DONE 2 /* Offset to READ done bit */ #define IXGBE_EEPROM_RW_REG_START 1 /* First bit to start operation */ #define IXGBE_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ #define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for wr complete */ #define IXGBE_NVM_POLL_READ 0 /* Flag for polling for rd complete */ #define IXGBE_ETH_LENGTH_OF_ADDRESS 6 #define IXGBE_EEPROM_PAGE_SIZE_MAX 128 #define IXGBE_EEPROM_RD_BUFFER_MAX_COUNT 512 /* words rd in burst */ #define IXGBE_EEPROM_WR_BUFFER_MAX_COUNT 256 /* words wr in burst */ #ifndef IXGBE_EEPROM_GRANT_ATTEMPTS #define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM attempts to gain grant */ #endif #ifndef IXGBE_EERD_EEWR_ATTEMPTS /* Number of 5 microseconds we wait for EERD read and * EERW write to complete */ #define IXGBE_EERD_EEWR_ATTEMPTS 100000 #endif #ifndef IXGBE_FLUDONE_ATTEMPTS /* # attempts we wait for flush update to complete */ #define IXGBE_FLUDONE_ATTEMPTS 20000 #endif #define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */ #define IXGBE_PCIE_CTRL2_DUMMY_ENABLE 0x8 /* Dummy Function Enable */ #define IXGBE_PCIE_CTRL2_LAN_DISABLE 0x2 /* LAN PCI Disable */ #define IXGBE_PCIE_CTRL2_DISABLE_SELECT 0x1 /* LAN Disable Select */ #define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET 0x0 #define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3 #define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1 #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 #define IXGBE_FW_LESM_PARAMETERS_PTR 0x2 #define IXGBE_FW_LESM_STATE_1 0x1 #define IXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */ #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_FW_PATCH_VERSION_4 0x7 #define IXGBE_FCOE_IBA_CAPS_BLK_PTR 0x33 /* iSCSI/FCOE block */ #define IXGBE_FCOE_IBA_CAPS_FCOE 0x20 /* FCOE flags */ #define IXGBE_ISCSI_FCOE_BLK_PTR 0x17 /* iSCSI/FCOE block */ #define IXGBE_ISCSI_FCOE_FLAGS_OFFSET 0x0 /* FCOE flags */ #define IXGBE_ISCSI_FCOE_FLAGS_ENABLE 0x1 /* FCOE flags enable bit */ #define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt SAN MAC capability */ #define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt SAN MAC 0 offset */ #define IXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt SAN MAC 1 offset */ #define IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt WWNN prefix offset */ #define IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt WWPN prefix offset */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt SAN MAC exists */ #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt WWN base exists */ #define IXGBE_DEVICE_CAPS_WOL_PORT0_1 0x4 /* WoL supported on ports 0 & 1 */ #define IXGBE_DEVICE_CAPS_WOL_PORT0 0x8 /* WoL supported on port 0 */ #define IXGBE_DEVICE_CAPS_WOL_MASK 0xC /* Mask for WoL capabilities */ /* PCI Bus Info */ #define IXGBE_PCI_DEVICE_STATUS 0xAA #define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020 #define IXGBE_PCI_LINK_STATUS 0xB2 #define IXGBE_PCI_DEVICE_CONTROL2 0xC8 #define IXGBE_PCI_LINK_WIDTH 0x3F0 #define IXGBE_PCI_LINK_WIDTH_1 0x10 #define IXGBE_PCI_LINK_WIDTH_2 0x20 #define IXGBE_PCI_LINK_WIDTH_4 0x40 #define IXGBE_PCI_LINK_WIDTH_8 0x80 #define IXGBE_PCI_LINK_SPEED 0xF #define IXGBE_PCI_LINK_SPEED_2500 0x1 #define IXGBE_PCI_LINK_SPEED_5000 0x2 #define IXGBE_PCI_LINK_SPEED_8000 0x3 #define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80 #define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005 /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 /* Check whether address is multicast. This is little-endian specific check.*/ #define IXGBE_IS_MULTICAST(Address) \ (bool)(((u8 *)(Address))[0] & ((u8)0x01)) /* Check whether an address is broadcast. */ #define IXGBE_IS_BROADCAST(Address) \ ((((u8 *)(Address))[0] == ((u8)0xff)) && \ (((u8 *)(Address))[1] == ((u8)0xff))) /* RAH */ #define IXGBE_RAH_VIND_MASK 0x003C0000 #define IXGBE_RAH_VIND_SHIFT 18 #define IXGBE_RAH_AV 0x80000000 #define IXGBE_CLEAR_VMDQ_ALL 0xFFFFFFFF /* Header split receive */ #define IXGBE_RFCTL_ISCSI_DIS 0x00000001 #define IXGBE_RFCTL_ISCSI_DWC_MASK 0x0000003E #define IXGBE_RFCTL_ISCSI_DWC_SHIFT 1 #define IXGBE_RFCTL_RSC_DIS 0x00000010 #define IXGBE_RFCTL_NFSW_DIS 0x00000040 #define IXGBE_RFCTL_NFSR_DIS 0x00000080 #define IXGBE_RFCTL_NFS_VER_MASK 0x00000300 #define IXGBE_RFCTL_NFS_VER_SHIFT 8 #define IXGBE_RFCTL_NFS_VER_2 0 #define IXGBE_RFCTL_NFS_VER_3 1 #define IXGBE_RFCTL_NFS_VER_4 2 #define IXGBE_RFCTL_IPV6_DIS 0x00000400 #define IXGBE_RFCTL_IPV6_XSUM_DIS 0x00000800 #define IXGBE_RFCTL_IPFRSP_DIS 0x00004000 #define IXGBE_RFCTL_IPV6_EX_DIS 0x00010000 #define IXGBE_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 /* Transmit Config masks */ #define IXGBE_TXDCTL_ENABLE 0x02000000 /* Ena specific Tx Queue */ #define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. wr-bk flushing */ #define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ /* Enable short packet padding to 64 bytes */ #define IXGBE_TX_PAD_ENABLE 0x00000400 #define IXGBE_JUMBO_FRAME_ENABLE 0x00000004 /* Allow jumbo frames */ /* This allows for 16K packets + 4k for vlan */ #define IXGBE_MAX_FRAME_SZ 0x40040000 #define IXGBE_TDWBAL_HEAD_WB_ENABLE 0x1 /* Tx head write-back enable */ #define IXGBE_TDWBAL_SEQNUM_WB_ENABLE 0x2 /* Tx seq# write-back enable */ /* Receive Config masks */ #define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */ #define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Desc Monitor Bypass */ #define IXGBE_RXDCTL_ENABLE 0x02000000 /* Ena specific Rx Queue */ #define IXGBE_RXDCTL_SWFLSH 0x04000000 /* Rx Desc wr-bk flushing */ #define IXGBE_RXDCTL_RLPMLMASK 0x00003FFF /* X540 supported only */ #define IXGBE_RXDCTL_RLPML_EN 0x00008000 #define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */ #define IXGBE_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define IXGBE_TSYNCTXCTL_ENABLED 0x00000010 /* Tx timestamping enabled */ #define IXGBE_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ #define IXGBE_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ #define IXGBE_TSYNCRXCTL_TYPE_L2_V2 0x00 #define IXGBE_TSYNCRXCTL_TYPE_L4_V1 0x02 #define IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 #define IXGBE_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define IXGBE_TSYNCRXCTL_ENABLED 0x00000010 /* Rx Timestamping enabled */ #define IXGBE_RXMTRL_V1_CTRLT_MASK 0x000000FF #define IXGBE_RXMTRL_V1_SYNC_MSG 0x00 #define IXGBE_RXMTRL_V1_DELAY_REQ_MSG 0x01 #define IXGBE_RXMTRL_V1_FOLLOWUP_MSG 0x02 #define IXGBE_RXMTRL_V1_DELAY_RESP_MSG 0x03 #define IXGBE_RXMTRL_V1_MGMT_MSG 0x04 #define IXGBE_RXMTRL_V2_MSGID_MASK 0x0000FF00 #define IXGBE_RXMTRL_V2_SYNC_MSG 0x0000 #define IXGBE_RXMTRL_V2_DELAY_REQ_MSG 0x0100 #define IXGBE_RXMTRL_V2_PDELAY_REQ_MSG 0x0200 #define IXGBE_RXMTRL_V2_PDELAY_RESP_MSG 0x0300 #define IXGBE_RXMTRL_V2_FOLLOWUP_MSG 0x0800 #define IXGBE_RXMTRL_V2_DELAY_RESP_MSG 0x0900 #define IXGBE_RXMTRL_V2_PDELAY_FOLLOWUP_MSG 0x0A00 #define IXGBE_RXMTRL_V2_ANNOUNCE_MSG 0x0B00 #define IXGBE_RXMTRL_V2_SIGNALLING_MSG 0x0C00 #define IXGBE_RXMTRL_V2_MGMT_MSG 0x0D00 #define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */ #define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/ #define IXGBE_FCTRL_UPE 0x00000200 /* Unicast Promiscuous Ena */ #define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */ #define IXGBE_FCTRL_PMCF 0x00001000 /* Pass MAC Control Frames */ #define IXGBE_FCTRL_DPF 0x00002000 /* Discard Pause Frame */ /* Receive Priority Flow Control Enable */ #define IXGBE_FCTRL_RPFCE 0x00004000 #define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */ #define IXGBE_MFLCN_PMCF 0x00000001 /* Pass MAC Control Frames */ #define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */ #define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */ #define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */ #define IXGBE_MFLCN_RPFCE_MASK 0x00000FF4 /* Rx Priority FC bitmap mask */ #define IXGBE_MFLCN_RPFCE_SHIFT 4 /* Rx Priority FC bitmap shift */ /* Multiple Receive Queue Control */ #define IXGBE_MRQC_RSSEN 0x00000001 /* RSS Enable */ #define IXGBE_MRQC_MRQE_MASK 0xF /* Bits 3:0 */ #define IXGBE_MRQC_RT8TCEN 0x00000002 /* 8 TC no RSS */ #define IXGBE_MRQC_RT4TCEN 0x00000003 /* 4 TC no RSS */ #define IXGBE_MRQC_RTRSS8TCEN 0x00000004 /* 8 TC w/ RSS */ #define IXGBE_MRQC_RTRSS4TCEN 0x00000005 /* 4 TC w/ RSS */ #define IXGBE_MRQC_VMDQEN 0x00000008 /* VMDq2 64 pools no RSS */ #define IXGBE_MRQC_VMDQRSS32EN 0x0000000A /* VMDq2 32 pools w/ RSS */ #define IXGBE_MRQC_VMDQRSS64EN 0x0000000B /* VMDq2 64 pools w/ RSS */ #define IXGBE_MRQC_VMDQRT8TCEN 0x0000000C /* VMDq2/RT 16 pool 8 TC */ #define IXGBE_MRQC_VMDQRT4TCEN 0x0000000D /* VMDq2/RT 32 pool 4 TC */ #define IXGBE_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define IXGBE_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define IXGBE_MRQC_RSS_FIELD_IPV4 0x00020000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP 0x00040000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX 0x00080000 #define IXGBE_MRQC_RSS_FIELD_IPV6 0x00100000 #define IXGBE_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define IXGBE_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define IXGBE_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000 #define IXGBE_MRQC_L3L4TXSWEN 0x00008000 /* Queue Drop Enable */ #define IXGBE_QDE_ENABLE 0x00000001 #define IXGBE_QDE_IDX_MASK 0x00007F00 #define IXGBE_QDE_IDX_SHIFT 8 #define IXGBE_QDE_WRITE 0x00010000 #define IXGBE_QDE_READ 0x00020000 #define IXGBE_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ #define IXGBE_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ #define IXGBE_TXD_CMD_EOP 0x01000000 /* End of Packet */ #define IXGBE_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ #define IXGBE_TXD_CMD_IC 0x04000000 /* Insert Checksum */ #define IXGBE_TXD_CMD_RS 0x08000000 /* Report Status */ #define IXGBE_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */ #define IXGBE_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ #define IXGBE_TXD_STAT_DD 0x00000001 /* Descriptor Done */ #define IXGBE_RXDADV_IPSEC_STATUS_SECP 0x00020000 #define IXGBE_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000 #define IXGBE_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000 #define IXGBE_RXDADV_IPSEC_ERROR_AUTH_FAILED 0x18000000 #define IXGBE_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000 /* Multiple Transmit Queue Command Register */ #define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */ #define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */ #define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */ #define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */ #define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */ #define IXGBE_MTQC_4TC_4TQ 0x8 /* 4 TC if RT_ENA and VT_ENA */ #define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */ /* Receive Descriptor bit definitions */ #define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */ #define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */ #define IXGBE_RXD_STAT_FLM 0x04 /* FDir Match */ #define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ #define IXGBE_RXDADV_NEXTP_MASK 0x000FFFF0 /* Next Descriptor Index */ #define IXGBE_RXDADV_NEXTP_SHIFT 0x00000004 #define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ #define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */ #define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ #define IXGBE_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ #define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */ #define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ #define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ #define IXGBE_RXD_STAT_LLINT 0x800 /* Pkt caused Low Latency Interrupt */ #define IXGBE_RXD_STAT_TS 0x10000 /* Time Stamp */ #define IXGBE_RXD_STAT_SECP 0x20000 /* Security Processing */ #define IXGBE_RXD_STAT_LB 0x40000 /* Loopback Status */ #define IXGBE_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ #define IXGBE_RXD_ERR_CE 0x01 /* CRC Error */ #define IXGBE_RXD_ERR_LE 0x02 /* Length Error */ #define IXGBE_RXD_ERR_PE 0x08 /* Packet Error */ #define IXGBE_RXD_ERR_OSE 0x10 /* Oversize Error */ #define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */ #define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */ #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ #define IXGBE_RXDADV_ERR_RXE 0x20000000 /* Any MAC Error */ #define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */ #define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ #define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */ #define IXGBE_RXDADV_ERR_FDIR_DROP 0x00200000 /* FDIR Drop error */ #define IXGBE_RXDADV_ERR_FDIR_COLL 0x00400000 /* FDIR Collision error */ #define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ #define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ #define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ #define IXGBE_RXDADV_ERR_PE 0x08000000 /* Packet Error */ #define IXGBE_RXDADV_ERR_OSE 0x10000000 /* Oversize Error */ #define IXGBE_RXDADV_ERR_USE 0x20000000 /* Undersize Error */ #define IXGBE_RXDADV_ERR_TCPE 0x40000000 /* TCP/UDP Checksum Error */ #define IXGBE_RXDADV_ERR_IPE 0x80000000 /* IP Checksum Error */ #define IXGBE_RXD_VLAN_ID_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ #define IXGBE_RXD_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ #define IXGBE_RXD_PRI_SHIFT 13 #define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */ #define IXGBE_RXD_CFI_SHIFT 12 #define IXGBE_RXDADV_STAT_DD IXGBE_RXD_STAT_DD /* Done */ #define IXGBE_RXDADV_STAT_EOP IXGBE_RXD_STAT_EOP /* End of Packet */ #define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */ #define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */ #define IXGBE_RXDADV_STAT_MASK 0x000fffff /* Stat/NEXTP: bit 0-19 */ #define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */ #define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */ #define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */ #define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */ #define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */ #define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */ #define IXGBE_RXDADV_STAT_TS 0x00010000 /* IEEE1588 Time Stamp */ /* PSRTYPE bit definitions */ #define IXGBE_PSRTYPE_TCPHDR 0x00000010 #define IXGBE_PSRTYPE_UDPHDR 0x00000020 #define IXGBE_PSRTYPE_IPV4HDR 0x00000100 #define IXGBE_PSRTYPE_IPV6HDR 0x00000200 #define IXGBE_PSRTYPE_L2HDR 0x00001000 /* SRRCTL bit definitions */ #define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ #define IXGBE_SRRCTL_RDMTS_SHIFT 22 #define IXGBE_SRRCTL_RDMTS_MASK 0x01C00000 #define IXGBE_SRRCTL_DROP_EN 0x10000000 #define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F #define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 #define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 #define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 #define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 #define IXGBE_RXDPS_HDRSTAT_HDRSP 0x00008000 #define IXGBE_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF #define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F #define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0 #define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0 #define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0 #define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 #define IXGBE_RXDADV_RSCCNT_SHIFT 17 #define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5 #define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000 #define IXGBE_RXDADV_SPH 0x8000 /* RSS Hash results */ #define IXGBE_RXDADV_RSSTYPE_NONE 0x00000000 #define IXGBE_RXDADV_RSSTYPE_IPV4_TCP 0x00000001 #define IXGBE_RXDADV_RSSTYPE_IPV4 0x00000002 #define IXGBE_RXDADV_RSSTYPE_IPV6_TCP 0x00000003 #define IXGBE_RXDADV_RSSTYPE_IPV6_EX 0x00000004 #define IXGBE_RXDADV_RSSTYPE_IPV6 0x00000005 #define IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006 #define IXGBE_RXDADV_RSSTYPE_IPV4_UDP 0x00000007 #define IXGBE_RXDADV_RSSTYPE_IPV6_UDP 0x00000008 #define IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009 /* RSS Packet Types as indicated in the receive descriptor. */ #define IXGBE_RXDADV_PKTTYPE_NONE 0x00000000 #define IXGBE_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPv4 hdr present */ #define IXGBE_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPv4 hdr + extensions */ #define IXGBE_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPv6 hdr present */ #define IXGBE_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPv6 hdr + extensions */ #define IXGBE_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */ #define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ #define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ #define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ #define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ #define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ #define IXGBE_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ #define IXGBE_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */ #define IXGBE_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */ #define IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */ /* Security Processing bit Indication */ #define IXGBE_RXDADV_LNKSEC_STATUS_SECP 0x00020000 #define IXGBE_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000 #define IXGBE_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000 #define IXGBE_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000 #define IXGBE_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000 /* Masks to determine if packets should be dropped due to frame errors */ #define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \ IXGBE_RXD_ERR_CE | \ IXGBE_RXD_ERR_LE | \ IXGBE_RXD_ERR_PE | \ IXGBE_RXD_ERR_OSE | \ IXGBE_RXD_ERR_USE) #define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \ IXGBE_RXDADV_ERR_CE | \ IXGBE_RXDADV_ERR_LE | \ IXGBE_RXDADV_ERR_PE | \ IXGBE_RXDADV_ERR_OSE | \ IXGBE_RXDADV_ERR_USE) #define IXGBE_RXDADV_ERR_FRAME_ERR_MASK_82599 IXGBE_RXDADV_ERR_RXE /* Multicast bit mask */ #define IXGBE_MCSTCTRL_MFE 0x4 /* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8 #define IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE 8 #define IXGBE_REQ_TX_BUFFER_GRANULARITY 1024 /* Vlan-specific macros */ #define IXGBE_RX_DESC_SPECIAL_VLAN_MASK 0x0FFF /* VLAN ID in lower 12 bits */ #define IXGBE_RX_DESC_SPECIAL_PRI_MASK 0xE000 /* Priority in upper 3 bits */ #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */ #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT /* SR-IOV specific macros */ #define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4) #define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4)) #define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) #define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4)) /* Translated register #defines */ #define IXGBE_PVFCTRL(P) (0x00300 + (4 * (P))) #define IXGBE_PVFSTATUS(P) (0x00008 + (0 * (P))) #define IXGBE_PVFLINKS(P) (0x042A4 + (0 * (P))) #define IXGBE_PVFRTIMER(P) (0x00048 + (0 * (P))) #define IXGBE_PVFMAILBOX(P) (0x04C00 + (4 * (P))) #define IXGBE_PVFRXMEMWRAP(P) (0x03190 + (0 * (P))) #define IXGBE_PVTEICR(P) (0x00B00 + (4 * (P))) #define IXGBE_PVTEICS(P) (0x00C00 + (4 * (P))) #define IXGBE_PVTEIMS(P) (0x00D00 + (4 * (P))) #define IXGBE_PVTEIMC(P) (0x00E00 + (4 * (P))) #define IXGBE_PVTEIAC(P) (0x00F00 + (4 * (P))) #define IXGBE_PVTEIAM(P) (0x04D00 + (4 * (P))) #define IXGBE_PVTEITR(P) (((P) < 24) ? (0x00820 + ((P) * 4)) : \ (0x012300 + (((P) - 24) * 4))) #define IXGBE_PVTIVAR(P) (0x12500 + (4 * (P))) #define IXGBE_PVTIVAR_MISC(P) (0x04E00 + (4 * (P))) #define IXGBE_PVTRSCINT(P) (0x12000 + (4 * (P))) #define IXGBE_VFPBACL(P) (0x110C8 + (4 * (P))) #define IXGBE_PVFRDBAL(P) ((P < 64) ? (0x01000 + (0x40 * (P))) \ : (0x0D000 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDBAH(P) ((P < 64) ? (0x01004 + (0x40 * (P))) \ : (0x0D004 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDLEN(P) ((P < 64) ? (0x01008 + (0x40 * (P))) \ : (0x0D008 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDH(P) ((P < 64) ? (0x01010 + (0x40 * (P))) \ : (0x0D010 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRDT(P) ((P < 64) ? (0x01018 + (0x40 * (P))) \ : (0x0D018 + (0x40 * ((P) - 64)))) #define IXGBE_PVFRXDCTL(P) ((P < 64) ? (0x01028 + (0x40 * (P))) \ : (0x0D028 + (0x40 * ((P) - 64)))) #define IXGBE_PVFSRRCTL(P) ((P < 64) ? (0x01014 + (0x40 * (P))) \ : (0x0D014 + (0x40 * ((P) - 64)))) #define IXGBE_PVFPSRTYPE(P) (0x0EA00 + (4 * (P))) #define IXGBE_PVFTDBAL(P) (0x06000 + (0x40 * (P))) #define IXGBE_PVFTDBAH(P) (0x06004 + (0x40 * (P))) #define IXGBE_PVFTTDLEN(P) (0x06008 + (0x40 * (P))) #define IXGBE_PVFTDH(P) (0x06010 + (0x40 * (P))) #define IXGBE_PVFTDT(P) (0x06018 + (0x40 * (P))) #define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P))) #define IXGBE_PVFTDWBAL(P) (0x06038 + (0x40 * (P))) #define IXGBE_PVFTDWBAH(P) (0x0603C + (0x40 * (P))) #define IXGBE_PVFDCA_RXCTRL(P) (((P) < 64) ? (0x0100C + (0x40 * (P))) \ : (0x0D00C + (0x40 * ((P) - 64)))) #define IXGBE_PVFDCA_TXCTRL(P) (0x0600C + (0x40 * (P))) #define IXGBE_PVFGPRC(x) (0x0101C + (0x40 * (x))) #define IXGBE_PVFGPTC(x) (0x08300 + (0x04 * (x))) #define IXGBE_PVFGORC_LSB(x) (0x01020 + (0x40 * (x))) #define IXGBE_PVFGORC_MSB(x) (0x0D020 + (0x40 * (x))) #define IXGBE_PVFGOTC_LSB(x) (0x08400 + (0x08 * (x))) #define IXGBE_PVFGOTC_MSB(x) (0x08404 + (0x08 * (x))) #define IXGBE_PVFMPRC(x) (0x0D01C + (0x40 * (x))) #define IXGBE_PVFTDWBALn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDWBAL((q_per_pool)*(vf_number) + (vf_q_index))) #define IXGBE_PVFTDWBAHn(q_per_pool, vf_number, vf_q_index) \ (IXGBE_PVFTDWBAH((q_per_pool)*(vf_number) + (vf_q_index))) /* Little Endian defines */ #ifndef __le16 #define __le16 u16 #endif #ifndef __le32 #define __le32 u32 #endif #ifndef __le64 #define __le64 u64 #endif #ifndef __be16 /* Big Endian defines */ #define __be16 u16 #define __be32 u32 #define __be64 u64 #endif enum ixgbe_fdir_pballoc_type { IXGBE_FDIR_PBALLOC_NONE = 0, IXGBE_FDIR_PBALLOC_64K = 1, IXGBE_FDIR_PBALLOC_128K = 2, IXGBE_FDIR_PBALLOC_256K = 3, }; /* Flow Director register values */ #define IXGBE_FDIRCTRL_PBALLOC_64K 0x00000001 #define IXGBE_FDIRCTRL_PBALLOC_128K 0x00000002 #define IXGBE_FDIRCTRL_PBALLOC_256K 0x00000003 #define IXGBE_FDIRCTRL_INIT_DONE 0x00000008 #define IXGBE_FDIRCTRL_PERFECT_MATCH 0x00000010 #define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020 #define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080 #define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8 #define IXGBE_FDIRCTRL_FLEX_SHIFT 16 #define IXGBE_FDIRCTRL_SEARCHLIM 0x00800000 #define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT 24 #define IXGBE_FDIRCTRL_FULL_THRESH_MASK 0xF0000000 #define IXGBE_FDIRCTRL_FULL_THRESH_SHIFT 28 #define IXGBE_FDIRTCPM_DPORTM_SHIFT 16 #define IXGBE_FDIRUDPM_DPORTM_SHIFT 16 #define IXGBE_FDIRIP6M_DIPM_SHIFT 16 #define IXGBE_FDIRM_VLANID 0x00000001 #define IXGBE_FDIRM_VLANP 0x00000002 #define IXGBE_FDIRM_POOL 0x00000004 #define IXGBE_FDIRM_L4P 0x00000008 #define IXGBE_FDIRM_FLEX 0x00000010 #define IXGBE_FDIRM_DIPv6 0x00000020 #define IXGBE_FDIRFREE_FREE_MASK 0xFFFF #define IXGBE_FDIRFREE_FREE_SHIFT 0 #define IXGBE_FDIRFREE_COLL_MASK 0x7FFF0000 #define IXGBE_FDIRFREE_COLL_SHIFT 16 #define IXGBE_FDIRLEN_MAXLEN_MASK 0x3F #define IXGBE_FDIRLEN_MAXLEN_SHIFT 0 #define IXGBE_FDIRLEN_MAXHASH_MASK 0x7FFF0000 #define IXGBE_FDIRLEN_MAXHASH_SHIFT 16 #define IXGBE_FDIRUSTAT_ADD_MASK 0xFFFF #define IXGBE_FDIRUSTAT_ADD_SHIFT 0 #define IXGBE_FDIRUSTAT_REMOVE_MASK 0xFFFF0000 #define IXGBE_FDIRUSTAT_REMOVE_SHIFT 16 #define IXGBE_FDIRFSTAT_FADD_MASK 0x00FF #define IXGBE_FDIRFSTAT_FADD_SHIFT 0 #define IXGBE_FDIRFSTAT_FREMOVE_MASK 0xFF00 #define IXGBE_FDIRFSTAT_FREMOVE_SHIFT 8 #define IXGBE_FDIRPORT_DESTINATION_SHIFT 16 #define IXGBE_FDIRVLAN_FLEX_SHIFT 16 #define IXGBE_FDIRHASH_BUCKET_VALID_SHIFT 15 #define IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT 16 #define IXGBE_FDIRCMD_CMD_MASK 0x00000003 #define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001 #define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002 #define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003 #define IXGBE_FDIRCMD_FILTER_VALID 0x00000004 #define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008 #define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010 #define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020 #define IXGBE_FDIRCMD_L4TYPE_TCP 0x00000040 #define IXGBE_FDIRCMD_L4TYPE_SCTP 0x00000060 #define IXGBE_FDIRCMD_IPV6 0x00000080 #define IXGBE_FDIRCMD_CLEARHT 0x00000100 #define IXGBE_FDIRCMD_DROP 0x00000200 #define IXGBE_FDIRCMD_INT 0x00000400 #define IXGBE_FDIRCMD_LAST 0x00000800 #define IXGBE_FDIRCMD_COLLISION 0x00001000 #define IXGBE_FDIRCMD_QUEUE_EN 0x00008000 #define IXGBE_FDIRCMD_FLOW_TYPE_SHIFT 5 #define IXGBE_FDIRCMD_RX_QUEUE_SHIFT 16 #define IXGBE_FDIRCMD_VT_POOL_SHIFT 24 #define IXGBE_FDIR_INIT_DONE_POLL 10 #define IXGBE_FDIRCMD_CMD_POLL 10 #define IXGBE_FDIR_DROP_QUEUE 127 #define IXGBE_STATUS_OVERHEATING_BIT 20 /* STATUS overtemp bit num */ /* Manageablility Host Interface defines */ #define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */ #define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */ #define IXGBE_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */ /* CEM Support */ #define FW_CEM_HDR_LEN 0x4 #define FW_CEM_CMD_DRIVER_INFO 0xDD #define FW_CEM_CMD_DRIVER_INFO_LEN 0x5 #define FW_CEM_CMD_RESERVED 0X0 #define FW_CEM_UNUSED_VER 0x0 #define FW_CEM_MAX_RETRIES 3 #define FW_CEM_RESP_STATUS_SUCCESS 0x1 /* Host Interface Command Structures */ struct ixgbe_hic_hdr { u8 cmd; u8 buf_len; union { u8 cmd_resv; u8 ret_status; } cmd_or_resp; u8 checksum; }; struct ixgbe_hic_drv_info { struct ixgbe_hic_hdr hdr; u8 port_num; u8 ver_sub; u8 ver_build; u8 ver_min; u8 ver_maj; u8 pad; /* end spacing to ensure length is mult. of dword */ u16 pad2; /* end spacing to ensure length is mult. of dword2 */ }; /* Transmit Descriptor - Legacy */ struct ixgbe_legacy_tx_desc { u64 buffer_addr; /* Address of the descriptor's data buffer */ union { __le32 data; struct { __le16 length; /* Data buffer length */ u8 cso; /* Checksum offset */ u8 cmd; /* Descriptor control */ } flags; } lower; union { __le32 data; struct { u8 status; /* Descriptor status */ u8 css; /* Checksum start */ __le16 vlan; } fields; } upper; }; /* Transmit Descriptor - Advanced */ union ixgbe_adv_tx_desc { struct { __le64 buffer_addr; /* Address of descriptor's data buf */ __le32 cmd_type_len; __le32 olinfo_status; } read; struct { __le64 rsvd; /* Reserved */ __le32 nxtseq_seed; __le32 status; } wb; }; /* Receive Descriptor - Legacy */ struct ixgbe_legacy_rx_desc { __le64 buffer_addr; /* Address of the descriptor's data buffer */ __le16 length; /* Length of data DMAed into data buffer */ __le16 csum; /* Packet checksum */ u8 status; /* Descriptor status */ u8 errors; /* Descriptor Errors */ __le16 vlan; }; /* Receive Descriptor - Advanced */ union ixgbe_adv_rx_desc { struct { __le64 pkt_addr; /* Packet buffer address */ __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { __le32 data; struct { __le16 pkt_info; /* RSS, Pkt type */ __le16 hdr_info; /* Splithdr, hdrlen */ } hs_rss; } lo_dword; union { __le32 rss; /* RSS Hash */ struct { __le16 ip_id; /* IP id */ __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { __le32 status_error; /* ext status/error */ __le16 length; /* Packet length */ __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; /* Context descriptors */ struct ixgbe_adv_tx_context_desc { __le32 vlan_macip_lens; __le32 seqnum_seed; __le32 type_tucmd_mlhl; __le32 mss_l4len_idx; }; /* Adv Transmit Descriptor Config Masks */ #define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */ #define IXGBE_ADVTXD_MAC_LINKSEC 0x00040000 /* Insert LinkSec */ #define IXGBE_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 time stamp */ #define IXGBE_ADVTXD_IPSEC_SA_INDEX_MASK 0x000003FF /* IPSec SA index */ #define IXGBE_ADVTXD_IPSEC_ESP_LEN_MASK 0x000001FF /* IPSec ESP length */ #define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */ #define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Adv Context Desc */ #define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Adv Data Descriptor */ #define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */ #define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */ #define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */ #define IXGBE_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */ #define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext 1=Adv */ #define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE /* VLAN pkt enable */ #define IXGBE_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ #define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD /* Descriptor Done */ #define IXGBE_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED pres in WB */ #define IXGBE_ADVTXD_STAT_RSV 0x0000000C /* STA Reserved */ #define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ #define IXGBE_ADVTXD_CC 0x00000080 /* Check Context */ #define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */ #define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \ IXGBE_ADVTXD_POPTS_SHIFT) #define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \ IXGBE_ADVTXD_POPTS_SHIFT) #define IXGBE_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */ /* 1st&Last TSO-full iSCSI PDU */ #define IXGBE_ADVTXD_POPTS_ISCO_FULL 0x00001800 #define IXGBE_ADVTXD_POPTS_RSV 0x00002000 /* POPTS Reserved */ #define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ #define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ #define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ #define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ #define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ #define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ #define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ #define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ #define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /* req Markers and CRC */ #define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */ #define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */ #define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */ #define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */ #define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */ #define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */ #define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */ #define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation End */ #define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation Start */ #define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */ #define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */ #define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */ #define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */ #define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ #define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ /* Autonegotiation advertised speeds */ typedef u32 ixgbe_autoneg_advertised; /* Link speed */ typedef u32 ixgbe_link_speed; #define IXGBE_LINK_SPEED_UNKNOWN 0 #define IXGBE_LINK_SPEED_100_FULL 0x0008 #define IXGBE_LINK_SPEED_1GB_FULL 0x0020 #define IXGBE_LINK_SPEED_10GB_FULL 0x0080 #define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) #define IXGBE_LINK_SPEED_82599_AUTONEG (IXGBE_LINK_SPEED_100_FULL | \ IXGBE_LINK_SPEED_1GB_FULL | \ IXGBE_LINK_SPEED_10GB_FULL) /* Physical layer type */ typedef u32 ixgbe_physical_layer; #define IXGBE_PHYSICAL_LAYER_UNKNOWN 0 #define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001 #define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002 #define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004 #define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008 #define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010 #define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020 #define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x0040 #define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x0080 #define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100 #define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200 #define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400 #define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800 #define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x1000 #define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x2000 #define IXGBE_PHYSICAL_LAYER_1000BASE_SX 0x4000 /* Flow Control Data Sheet defined values * Calculation and defines taken from 802.1bb Annex O */ /* BitTimes (BT) conversion */ #define IXGBE_BT2KB(BT) ((BT + (8 * 1024 - 1)) / (8 * 1024)) #define IXGBE_B2BT(BT) (BT * 8) /* Calculate Delay to respond to PFC */ #define IXGBE_PFC_D 672 /* Calculate Cable Delay */ #define IXGBE_CABLE_DC 5556 /* Delay Copper */ #define IXGBE_CABLE_DO 5000 /* Delay Optical */ /* Calculate Interface Delay X540 */ #define IXGBE_PHY_DC 25600 /* Delay 10G BASET */ #define IXGBE_MAC_DC 8192 /* Delay Copper XAUI interface */ #define IXGBE_XAUI_DC (2 * 2048) /* Delay Copper Phy */ #define IXGBE_ID_X540 (IXGBE_MAC_DC + IXGBE_XAUI_DC + IXGBE_PHY_DC) /* Calculate Interface Delay 82598, 82599 */ #define IXGBE_PHY_D 12800 #define IXGBE_MAC_D 4096 #define IXGBE_XAUI_D (2 * 1024) #define IXGBE_ID (IXGBE_MAC_D + IXGBE_XAUI_D + IXGBE_PHY_D) /* Calculate Delay incurred from higher layer */ #define IXGBE_HD 6144 /* Calculate PCI Bus delay for low thresholds */ #define IXGBE_PCI_DELAY 10000 /* Calculate X540 delay value in bit times */ #define IXGBE_DV_X540(_max_frame_link, _max_frame_tc) \ ((36 * \ (IXGBE_B2BT(_max_frame_link) + \ IXGBE_PFC_D + \ (2 * IXGBE_CABLE_DC) + \ (2 * IXGBE_ID_X540) + \ IXGBE_HD) / 25 + 1) + \ 2 * IXGBE_B2BT(_max_frame_tc)) /* Calculate 82599, 82598 delay value in bit times */ #define IXGBE_DV(_max_frame_link, _max_frame_tc) \ ((36 * \ (IXGBE_B2BT(_max_frame_link) + \ IXGBE_PFC_D + \ (2 * IXGBE_CABLE_DC) + \ (2 * IXGBE_ID) + \ IXGBE_HD) / 25 + 1) + \ 2 * IXGBE_B2BT(_max_frame_tc)) /* Calculate low threshold delay values */ #define IXGBE_LOW_DV_X540(_max_frame_tc) \ (2 * IXGBE_B2BT(_max_frame_tc) + \ (36 * IXGBE_PCI_DELAY / 25) + 1) #define IXGBE_LOW_DV(_max_frame_tc) \ (2 * IXGBE_LOW_DV_X540(_max_frame_tc)) /* Software ATR hash keys */ #define IXGBE_ATR_BUCKET_HASH_KEY 0x3DAD14E2 #define IXGBE_ATR_SIGNATURE_HASH_KEY 0x174D3614 /* Software ATR input stream values and masks */ #define IXGBE_ATR_HASH_MASK 0x7fff #define IXGBE_ATR_L4TYPE_MASK 0x3 #define IXGBE_ATR_L4TYPE_UDP 0x1 #define IXGBE_ATR_L4TYPE_TCP 0x2 #define IXGBE_ATR_L4TYPE_SCTP 0x3 #define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4 enum ixgbe_atr_flow_type { IXGBE_ATR_FLOW_TYPE_IPV4 = 0x0, IXGBE_ATR_FLOW_TYPE_UDPV4 = 0x1, IXGBE_ATR_FLOW_TYPE_TCPV4 = 0x2, IXGBE_ATR_FLOW_TYPE_SCTPV4 = 0x3, IXGBE_ATR_FLOW_TYPE_IPV6 = 0x4, IXGBE_ATR_FLOW_TYPE_UDPV6 = 0x5, IXGBE_ATR_FLOW_TYPE_TCPV6 = 0x6, IXGBE_ATR_FLOW_TYPE_SCTPV6 = 0x7, }; /* Flow Director ATR input struct. */ union ixgbe_atr_input { /* * Byte layout in order, all values with MSB first: * * vm_pool - 1 byte * flow_type - 1 byte * vlan_id - 2 bytes * src_ip - 16 bytes * dst_ip - 16 bytes * src_port - 2 bytes * dst_port - 2 bytes * flex_bytes - 2 bytes * bkt_hash - 2 bytes */ struct { u8 vm_pool; u8 flow_type; __be16 vlan_id; __be32 dst_ip[4]; __be32 src_ip[4]; __be16 src_port; __be16 dst_port; __be16 flex_bytes; __be16 bkt_hash; } formatted; __be32 dword_stream[11]; }; /* Flow Director compressed ATR hash input struct */ union ixgbe_atr_hash_dword { struct { u8 vm_pool; u8 flow_type; __be16 vlan_id; } formatted; __be32 ip; struct { __be16 src; __be16 dst; } port; __be16 flex_bytes; __be32 dword; }; /* * Unavailable: The FCoE Boot Option ROM is not present in the flash. * Disabled: Present; boot order is not set for any targets on the port. * Enabled: Present; boot order is set for at least one target on the port. */ enum ixgbe_fcoe_boot_status { ixgbe_fcoe_bootstatus_disabled = 0, ixgbe_fcoe_bootstatus_enabled = 1, ixgbe_fcoe_bootstatus_unavailable = 0xFFFF }; enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, ixgbe_flash, ixgbe_eeprom_none /* No NVM support */ }; enum ixgbe_mac_type { ixgbe_mac_unknown = 0, ixgbe_mac_82598EB, ixgbe_mac_82599EB, ixgbe_mac_X540, ixgbe_num_macs }; enum ixgbe_phy_type { ixgbe_phy_unknown = 0, ixgbe_phy_none, ixgbe_phy_tn, ixgbe_phy_aq, ixgbe_phy_cu_unknown, ixgbe_phy_qt, ixgbe_phy_xaui, ixgbe_phy_nl, ixgbe_phy_sfp_passive_tyco, ixgbe_phy_sfp_passive_unknown, ixgbe_phy_sfp_active_unknown, ixgbe_phy_sfp_avago, ixgbe_phy_sfp_ftl, ixgbe_phy_sfp_ftl_active, ixgbe_phy_sfp_unknown, ixgbe_phy_sfp_intel, ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/ ixgbe_phy_generic }; /* * SFP+ module type IDs: * * ID Module Type * ============= * 0 SFP_DA_CU * 1 SFP_SR * 2 SFP_LR * 3 SFP_DA_CU_CORE0 - 82599-specific * 4 SFP_DA_CU_CORE1 - 82599-specific * 5 SFP_SR/LR_CORE0 - 82599-specific * 6 SFP_SR/LR_CORE1 - 82599-specific */ enum ixgbe_sfp_type { ixgbe_sfp_type_da_cu = 0, ixgbe_sfp_type_sr = 1, ixgbe_sfp_type_lr = 2, ixgbe_sfp_type_da_cu_core0 = 3, ixgbe_sfp_type_da_cu_core1 = 4, ixgbe_sfp_type_srlr_core0 = 5, ixgbe_sfp_type_srlr_core1 = 6, ixgbe_sfp_type_da_act_lmt_core0 = 7, ixgbe_sfp_type_da_act_lmt_core1 = 8, ixgbe_sfp_type_1g_cu_core0 = 9, ixgbe_sfp_type_1g_cu_core1 = 10, ixgbe_sfp_type_1g_sx_core0 = 11, ixgbe_sfp_type_1g_sx_core1 = 12, ixgbe_sfp_type_not_present = 0xFFFE, ixgbe_sfp_type_unknown = 0xFFFF }; enum ixgbe_media_type { ixgbe_media_type_unknown = 0, ixgbe_media_type_fiber, ixgbe_media_type_fiber_qsfp, ixgbe_media_type_fiber_lco, ixgbe_media_type_copper, ixgbe_media_type_backplane, ixgbe_media_type_cx4, ixgbe_media_type_virtual }; /* Flow Control Settings */ enum ixgbe_fc_mode { ixgbe_fc_none = 0, ixgbe_fc_rx_pause, ixgbe_fc_tx_pause, ixgbe_fc_full, ixgbe_fc_default }; /* Smart Speed Settings */ #define IXGBE_SMARTSPEED_MAX_RETRIES 3 enum ixgbe_smart_speed { ixgbe_smart_speed_auto = 0, ixgbe_smart_speed_on, ixgbe_smart_speed_off }; /* PCI bus types */ enum ixgbe_bus_type { ixgbe_bus_type_unknown = 0, ixgbe_bus_type_pci, ixgbe_bus_type_pcix, ixgbe_bus_type_pci_express, ixgbe_bus_type_reserved }; /* PCI bus speeds */ enum ixgbe_bus_speed { ixgbe_bus_speed_unknown = 0, ixgbe_bus_speed_33 = 33, ixgbe_bus_speed_66 = 66, ixgbe_bus_speed_100 = 100, ixgbe_bus_speed_120 = 120, ixgbe_bus_speed_133 = 133, ixgbe_bus_speed_2500 = 2500, ixgbe_bus_speed_5000 = 5000, ixgbe_bus_speed_8000 = 8000, ixgbe_bus_speed_reserved }; /* PCI bus widths */ enum ixgbe_bus_width { ixgbe_bus_width_unknown = 0, ixgbe_bus_width_pcie_x1 = 1, ixgbe_bus_width_pcie_x2 = 2, ixgbe_bus_width_pcie_x4 = 4, ixgbe_bus_width_pcie_x8 = 8, ixgbe_bus_width_32 = 32, ixgbe_bus_width_64 = 64, ixgbe_bus_width_reserved }; struct ixgbe_addr_filter_info { u32 num_mc_addrs; u32 rar_used_count; u32 mta_in_use; u32 overflow_promisc; bool user_set_promisc; }; /* Bus parameters */ struct ixgbe_bus_info { enum ixgbe_bus_speed speed; enum ixgbe_bus_width width; enum ixgbe_bus_type type; u16 func; u16 lan_id; }; /* Flow control parameters */ struct ixgbe_fc_info { u32 high_water[IXGBE_DCB_MAX_TRAFFIC_CLASS]; /* Flow Ctrl High-water */ u32 low_water[IXGBE_DCB_MAX_TRAFFIC_CLASS]; /* Flow Ctrl Low-water */ u16 pause_time; /* Flow Control Pause timer */ bool send_xon; /* Flow control send XON */ bool strict_ieee; /* Strict IEEE mode */ bool disable_fc_autoneg; /* Do not autonegotiate FC */ bool fc_was_autonegged; /* Is current_mode the result of autonegging? */ enum ixgbe_fc_mode current_mode; /* FC mode in effect */ enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */ }; /* Statistics counters collected by the MAC */ struct ixgbe_hw_stats { u64 crcerrs; u64 illerrc; u64 errbc; u64 mspdc; u64 mpctotal; u64 mpc[8]; u64 mlfc; u64 mrfc; u64 rlec; u64 lxontxc; u64 lxonrxc; u64 lxofftxc; u64 lxoffrxc; u64 pxontxc[8]; u64 pxonrxc[8]; u64 pxofftxc[8]; u64 pxoffrxc[8]; u64 prc64; u64 prc127; u64 prc255; u64 prc511; u64 prc1023; u64 prc1522; u64 gprc; u64 bprc; u64 mprc; u64 gptc; u64 gorc; u64 gotc; u64 rnbc[8]; u64 ruc; u64 rfc; u64 roc; u64 rjc; u64 mngprc; u64 mngpdc; u64 mngptc; u64 tor; u64 tpr; u64 tpt; u64 ptc64; u64 ptc127; u64 ptc255; u64 ptc511; u64 ptc1023; u64 ptc1522; u64 mptc; u64 bptc; u64 xec; u64 qprc[16]; u64 qptc[16]; u64 qbrc[16]; u64 qbtc[16]; u64 qprdc[16]; u64 pxon2offc[8]; u64 fdirustat_add; u64 fdirustat_remove; u64 fdirfstat_fadd; u64 fdirfstat_fremove; u64 fdirmatch; u64 fdirmiss; u64 fccrc; u64 fclast; u64 fcoerpdc; u64 fcoeprc; u64 fcoeptc; u64 fcoedwrc; u64 fcoedwtc; u64 fcoe_noddp; u64 fcoe_noddp_ext_buff; u64 ldpcec; u64 pcrc8ec; u64 b2ospc; u64 b2ogprc; u64 o2bgptc; u64 o2bspc; }; /* forward declaration */ struct ixgbe_hw; /* iterator type for walking multicast address lists */ typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq); /* Function pointer table */ struct ixgbe_eeprom_operations { s32 (*init_params)(struct ixgbe_hw *); s32 (*read)(struct ixgbe_hw *, u16, u16 *); s32 (*read_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*write)(struct ixgbe_hw *, u16, u16); s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *); s32 (*validate_checksum)(struct ixgbe_hw *, u16 *); s32 (*update_checksum)(struct ixgbe_hw *); u16 (*calc_checksum)(struct ixgbe_hw *); }; struct ixgbe_mac_operations { s32 (*init_hw)(struct ixgbe_hw *); s32 (*reset_hw)(struct ixgbe_hw *); s32 (*start_hw)(struct ixgbe_hw *); s32 (*clear_hw_cntrs)(struct ixgbe_hw *); enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); u32 (*get_supported_physical_layer)(struct ixgbe_hw *); s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); s32 (*get_wwn_prefix)(struct ixgbe_hw *, u16 *, u16 *); s32 (*get_fcoe_boot_status)(struct ixgbe_hw *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*); s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8); s32 (*setup_sfp)(struct ixgbe_hw *); s32 (*enable_rx_dma)(struct ixgbe_hw *, u32); s32 (*disable_sec_rx_path)(struct ixgbe_hw *); s32 (*enable_sec_rx_path)(struct ixgbe_hw *); s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u16); void (*release_swfw_sync)(struct ixgbe_hw *, u16); /* Link */ void (*disable_tx_laser)(struct ixgbe_hw *); void (*enable_tx_laser)(struct ixgbe_hw *); void (*flap_tx_laser)(struct ixgbe_hw *); s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); /* Packet Buffer manipulation */ void (*setup_rxpba)(struct ixgbe_hw *, int, u32, int); /* LED */ s32 (*led_on)(struct ixgbe_hw *, u32); s32 (*led_off)(struct ixgbe_hw *, u32); s32 (*blink_led_start)(struct ixgbe_hw *, u32); s32 (*blink_led_stop)(struct ixgbe_hw *, u32); /* RAR, Multicast, VLAN */ s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32); s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *); s32 (*clear_rar)(struct ixgbe_hw *, u32); s32 (*insert_mac_addr)(struct ixgbe_hw *, u8 *, u32); s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*set_vmdq_san_mac)(struct ixgbe_hw *, u32); s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*init_rx_addrs)(struct ixgbe_hw *); s32 (*update_uc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr); s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr, bool clear); s32 (*enable_mc)(struct ixgbe_hw *); s32 (*disable_mc)(struct ixgbe_hw *); s32 (*clear_vfta)(struct ixgbe_hw *); s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool); s32 (*set_vlvf)(struct ixgbe_hw *, u32, u32, bool, bool *); s32 (*init_uta_tables)(struct ixgbe_hw *); void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int); void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int); /* Flow Control */ s32 (*fc_enable)(struct ixgbe_hw *); /* Manageability interface */ s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8); s32 (*get_thermal_sensor_data)(struct ixgbe_hw *); s32 (*init_thermal_sensor_thresh)(struct ixgbe_hw *hw); }; struct ixgbe_phy_operations { s32 (*identify)(struct ixgbe_hw *); s32 (*identify_sfp)(struct ixgbe_hw *); s32 (*init)(struct ixgbe_hw *); s32 (*reset)(struct ixgbe_hw *); s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *); s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16); s32 (*setup_link)(struct ixgbe_hw *); s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *); s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *); s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); void (*i2c_bus_clear)(struct ixgbe_hw *); s32 (*check_overtemp)(struct ixgbe_hw *); }; struct ixgbe_eeprom_info { struct ixgbe_eeprom_operations ops; enum ixgbe_eeprom_type type; u32 semaphore_delay; u16 word_size; u16 address_bits; u16 word_page_size; }; #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01 struct ixgbe_mac_info { struct ixgbe_mac_operations ops; enum ixgbe_mac_type type; u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; /* prefix for World Wide Node Name (WWNN) */ u16 wwnn_prefix; /* prefix for World Wide Port Name (WWPN) */ u16 wwpn_prefix; #define IXGBE_MAX_MTA 128 u32 mta_shadow[IXGBE_MAX_MTA]; s32 mc_filter_type; u32 mcft_size; u32 vft_size; u32 num_rar_entries; u32 rar_highwater; u32 rx_pb_size; u32 max_tx_queues; u32 max_rx_queues; u32 orig_autoc; u8 san_mac_rar_index; u32 orig_autoc2; u16 max_msix_vectors; bool arc_subsystem_valid; bool orig_link_settings_stored; bool autotry_restart; u8 flags; struct ixgbe_thermal_sensor_data thermal_sensor_data; }; struct ixgbe_phy_info { struct ixgbe_phy_operations ops; enum ixgbe_phy_type type; u32 addr; u32 id; enum ixgbe_sfp_type sfp_type; bool sfp_setup_needed; u32 revision; enum ixgbe_media_type media_type; bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; enum ixgbe_smart_speed smart_speed; bool smart_speed_active; bool multispeed_fiber; bool reset_if_overtemp; bool qsfp_shared_i2c_bus; }; #include "ixgbe_mbx.h" struct ixgbe_mbx_operations { void (*init_params)(struct ixgbe_hw *hw); s32 (*read)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*write)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16); s32 (*check_for_msg)(struct ixgbe_hw *, u16); s32 (*check_for_ack)(struct ixgbe_hw *, u16); s32 (*check_for_rst)(struct ixgbe_hw *, u16); }; struct ixgbe_mbx_stats { u32 msgs_tx; u32 msgs_rx; u32 acks; u32 reqs; u32 rsts; }; struct ixgbe_mbx_info { struct ixgbe_mbx_operations ops; struct ixgbe_mbx_stats stats; u32 timeout; u32 udelay; u32 v2p_mailbox; u16 size; }; struct ixgbe_hw { u8 __iomem *hw_addr; void *back; struct ixgbe_mac_info mac; struct ixgbe_addr_filter_info addr_ctrl; struct ixgbe_fc_info fc; struct ixgbe_phy_info phy; struct ixgbe_eeprom_info eeprom; struct ixgbe_bus_info bus; struct ixgbe_mbx_info mbx; u16 device_id; u16 vendor_id; u16 subsystem_device_id; u16 subsystem_vendor_id; u8 revision_id; bool adapter_stopped; bool force_full_reset; bool allow_unsupported_sfp; }; #define ixgbe_call_func(hw, func, params, error) \ (func != NULL) ? func params : error /* Error Codes */ #define IXGBE_ERR_EEPROM -1 #define IXGBE_ERR_EEPROM_CHECKSUM -2 #define IXGBE_ERR_PHY -3 #define IXGBE_ERR_CONFIG -4 #define IXGBE_ERR_PARAM -5 #define IXGBE_ERR_MAC_TYPE -6 #define IXGBE_ERR_UNKNOWN_PHY -7 #define IXGBE_ERR_LINK_SETUP -8 #define IXGBE_ERR_ADAPTER_STOPPED -9 #define IXGBE_ERR_INVALID_MAC_ADDR -10 #define IXGBE_ERR_DEVICE_NOT_SUPPORTED -11 #define IXGBE_ERR_MASTER_REQUESTS_PENDING -12 #define IXGBE_ERR_INVALID_LINK_SETTINGS -13 #define IXGBE_ERR_AUTONEG_NOT_COMPLETE -14 #define IXGBE_ERR_RESET_FAILED -15 #define IXGBE_ERR_SWFW_SYNC -16 #define IXGBE_ERR_PHY_ADDR_INVALID -17 #define IXGBE_ERR_I2C -18 #define IXGBE_ERR_SFP_NOT_SUPPORTED -19 #define IXGBE_ERR_SFP_NOT_PRESENT -20 #define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT -21 #define IXGBE_ERR_NO_SAN_ADDR_PTR -22 #define IXGBE_ERR_FDIR_REINIT_FAILED -23 #define IXGBE_ERR_EEPROM_VERSION -24 #define IXGBE_ERR_NO_SPACE -25 #define IXGBE_ERR_OVERTEMP -26 #define IXGBE_ERR_FC_NOT_NEGOTIATED -27 #define IXGBE_ERR_FC_NOT_SUPPORTED -28 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30 #define IXGBE_ERR_PBA_SECTION -31 #define IXGBE_ERR_INVALID_ARGUMENT -32 #define IXGBE_ERR_HOST_INTERFACE_COMMAND -33 #define IXGBE_ERR_OUT_OF_MEM -34 #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #define UNREFERENCED_XPARAMETER #endif /* _IXGBE_TYPE_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_x540.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe_x540.h" #include "ixgbe_type.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw); static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw); static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw); static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw); /** * ixgbe_init_ops_X540 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * * Initialize the function pointers and assign the MAC type for X540. * Does not touch the hardware. **/ s32 ixgbe_init_ops_X540(struct ixgbe_hw *hw) { struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; struct ixgbe_eeprom_info *eeprom = &hw->eeprom; s32 ret_val; ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* EEPROM */ eeprom->ops.init_params = &ixgbe_init_eeprom_params_X540; eeprom->ops.read = &ixgbe_read_eerd_X540; eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_X540; eeprom->ops.write = &ixgbe_write_eewr_X540; eeprom->ops.write_buffer = &ixgbe_write_eewr_buffer_X540; eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X540; eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X540; eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X540; /* PHY */ phy->ops.init = &ixgbe_init_phy_ops_generic; phy->ops.reset = NULL; /* MAC */ mac->ops.reset_hw = &ixgbe_reset_hw_X540; mac->ops.get_media_type = &ixgbe_get_media_type_X540; mac->ops.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_X540; mac->ops.read_analog_reg8 = NULL; mac->ops.write_analog_reg8 = NULL; mac->ops.start_hw = &ixgbe_start_hw_X540; mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic; mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = &ixgbe_get_device_caps_generic; mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic; mac->ops.get_fcoe_boot_status = &ixgbe_get_fcoe_boot_status_generic; mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540; mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync_X540; mac->ops.disable_sec_rx_path = &ixgbe_disable_sec_rx_path_generic; mac->ops.enable_sec_rx_path = &ixgbe_enable_sec_rx_path_generic; /* RAR, Multicast, VLAN */ mac->ops.set_vmdq = &ixgbe_set_vmdq_generic; mac->ops.set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic; mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic; mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; mac->ops.set_vfta = &ixgbe_set_vfta_generic; mac->ops.set_vlvf = &ixgbe_set_vlvf_generic; mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic; mac->ops.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing; mac->ops.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing; /* Link */ mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; mac->ops.setup_link = &ixgbe_setup_mac_link_X540; mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic; mac->ops.check_link = &ixgbe_check_mac_link_generic; mac->mcft_size = 128; mac->vft_size = 128; mac->num_rar_entries = 128; mac->rx_pb_size = 384; mac->max_tx_queues = 128; mac->max_rx_queues = 128; mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); /* * FWSM register * ARC supported; valid only if manageability features are * enabled. */ mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) & IXGBE_FWSM_MODE_MASK) ? true : false; //hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; /* LEDs */ mac->ops.blink_led_start = ixgbe_blink_led_start_X540; mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540; /* Manageability interface */ mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic; return ret_val; } /** * ixgbe_get_link_capabilities_X540 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: true when autoneg or autotry is enabled * * Determines the link capabilities by reading the AUTOC register. **/ s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { ixgbe_get_copper_link_capabilities_generic(hw, speed, autoneg); return 0; } /** * ixgbe_get_media_type_X540 - Get media type * @hw: pointer to hardware structure * * Returns the media type (fiber, copper, backplane) **/ enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw) { return ixgbe_media_type_copper; } /** * ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true when waiting for completion is needed **/ s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { return hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); } /** * ixgbe_reset_hw_X540 - Perform hardware reset * @hw: pointer to hardware structure * * Resets the hardware by resetting the transmit and receive units, masks * and clears all interrupts, and perform a reset. **/ s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) { s32 status = 0; /* * Userland DPDK takes the ownershiop of device * Kernel driver here used as the simple path for ethtool only * Won't real reset device anyway */ #if 0 u32 ctrl, i; /* Call adapter stop to disable tx/rx and clear interrupts */ status = hw->mac.ops.stop_adapter(hw); if (status != 0) goto reset_hw_out; /* flush pending Tx transactions */ ixgbe_clear_tx_pending(hw); mac_reset_top: ctrl = IXGBE_CTRL_RST; ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { udelay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST_MASK)) break; } if (ctrl & IXGBE_CTRL_RST_MASK) { status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "Reset polling failed to complete.\n"); } msleep(100); /* * Double resets are required for recovery from certain error * conditions. Between resets, it is necessary to stall to allow time * for any pending HW events to complete. */ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; goto mac_reset_top; } /* Set the Rx packet buffer size. */ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT); #endif /* Store the permanent mac address */ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ hw->mac.num_rar_entries = 128; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); /* Add the SAN MAC address to the RAR only if it's a valid address */ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) { hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1, hw->mac.san_addr, 0, IXGBE_RAH_AV); /* Save the SAN MAC RAR index */ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1; /* Reserve the last RAR for the SAN MAC address */ hw->mac.num_rar_entries--; } /* Store the alternative WWNN/WWPN prefix */ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, &hw->mac.wwpn_prefix); //reset_hw_out: return status; } /** * ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware using the generic start_hw function * and the generation start_hw function. * Then performs revision-specific operations, if any. **/ s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw) { s32 ret_val = 0; ret_val = ixgbe_start_hw_generic(hw); if (ret_val != 0) goto out; ret_val = ixgbe_start_hw_gen2(hw); out: return ret_val; } /** * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type * @hw: pointer to hardware structure * * Determines physical layer capabilities of the current configuration. **/ u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw) { u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; u16 ext_ability = 0; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY) physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX; return physical_layer; } /** * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->semaphore_delay = 10; eeprom->type = ixgbe_flash; eec = IXGBE_READ_REG(hw, IXGBE_EEC); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); } return 0; } /** * ixgbe_read_eerd_X540- Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data) { s32 status = 0; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) status = ixgbe_read_eerd_generic(hw, offset, data); else status = IXGBE_ERR_SWFW_SYNC; hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_read_eerd_buffer_X540- Read EEPROM word(s) using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @words: number of words * @data: word(s) read from the EEPROM * * Reads a 16 bit word(s) from the EEPROM using the EERD register. **/ s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = 0; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) status = ixgbe_read_eerd_buffer_generic(hw, offset, words, data); else status = IXGBE_ERR_SWFW_SYNC; hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @data: word write to the EEPROM * * Write a 16 bit word to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data) { s32 status = 0; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) status = ixgbe_write_eewr_generic(hw, offset, data); else status = IXGBE_ERR_SWFW_SYNC; hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to write * @words: number of words * @data: word(s) write to the EEPROM * * Write a 16 bit word(s) to the EEPROM using the EEWR register. **/ s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data) { s32 status = 0; if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) status = ixgbe_write_eewr_buffer_generic(hw, offset, words, data); else status = IXGBE_ERR_SWFW_SYNC; hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum * * This function does not use synchronization for EERD and EEWR. It can * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540. * * @hw: pointer to hardware structure **/ u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw) { u16 i; u16 j; u16 checksum = 0; u16 length = 0; u16 pointer = 0; u16 word = 0; /* * Do not use hw->eeprom.ops.read because we do not want to take * the synchronization semaphores here. Instead use * ixgbe_read_eerd_generic */ /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { if (ixgbe_read_eerd_generic(hw, i, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } checksum += word; } /* * Include all data from pointers 0x3, 0x6-0xE. This excludes the * FW, PHY module, and PCIe Expansion/Option ROM pointers. */ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) { if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) continue; if (ixgbe_read_eerd_generic(hw, i, &pointer) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } /* Skip pointer section if the pointer is invalid. */ if (pointer == 0xFFFF || pointer == 0 || pointer >= hw->eeprom.word_size) continue; if (ixgbe_read_eerd_generic(hw, pointer, &length) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } /* Skip pointer section if length is invalid. */ if (length == 0xFFFF || length == 0 || (pointer + length) >= hw->eeprom.word_size) continue; for (j = pointer+1; j <= pointer+length; j++) { if (ixgbe_read_eerd_generic(hw, j, &word) != 0) { hw_dbg(hw, "EEPROM read failed\n"); break; } checksum += word; } } checksum = (u16)IXGBE_EEPROM_SUM - checksum; return checksum; } /** * ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum * @hw: pointer to hardware structure * @checksum_val: calculated checksum * * Performs checksum calculation and validates the EEPROM checksum. If the * caller does not need checksum_val, the value can be NULL. **/ s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, u16 *checksum_val) { s32 status; u16 checksum; u16 read_checksum = 0; /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status != 0) { hw_dbg(hw, "EEPROM read failed\n"); goto out; } if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { checksum = hw->eeprom.ops.calc_checksum(hw); /* * Do not use hw->eeprom.ops.read because we do not want to take * the synchronization semaphores twice here. */ ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum); /* * Verify read checksum from EEPROM is the same as * calculated checksum */ if (read_checksum != checksum) status = IXGBE_ERR_EEPROM_CHECKSUM; /* If the user cares, return the calculated checksum */ if (checksum_val) *checksum_val = checksum; } else { status = IXGBE_ERR_SWFW_SYNC; } hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); out: return status; } /** * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash * @hw: pointer to hardware structure * * After writing EEPROM to shadow RAM using EEWR register, software calculates * checksum and updates the EEPROM and instructs the hardware to update * the flash. **/ s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) { s32 status; u16 checksum; /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every * EEPROM read fails */ status = hw->eeprom.ops.read(hw, 0, &checksum); if (status != 0) hw_dbg(hw, "EEPROM read failed\n"); if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { checksum = hw->eeprom.ops.calc_checksum(hw); /* * Do not use hw->eeprom.ops.write because we do not want to * take the synchronization semaphores twice here. */ status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM, checksum); if (status == 0) status = ixgbe_update_flash_X540(hw); else status = IXGBE_ERR_SWFW_SYNC; } hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); return status; } /** * ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device * @hw: pointer to hardware structure * * Set FLUP (bit 23) of the EEC register to instruct Hardware to copy * EEPROM from shadow RAM to the flash device. **/ static s32 ixgbe_update_flash_X540(struct ixgbe_hw *hw) { u32 flup; s32 status = IXGBE_ERR_EEPROM; status = ixgbe_poll_flash_update_done_X540(hw); if (status == IXGBE_ERR_EEPROM) { hw_dbg(hw, "Flash update time out\n"); goto out; } flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP; IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); status = ixgbe_poll_flash_update_done_X540(hw); if (status == 0) hw_dbg(hw, "Flash update complete\n"); else hw_dbg(hw, "Flash update time out\n"); if (hw->revision_id == 0) { flup = IXGBE_READ_REG(hw, IXGBE_EEC); if (flup & IXGBE_EEC_SEC1VAL) { flup |= IXGBE_EEC_FLUP; IXGBE_WRITE_REG(hw, IXGBE_EEC, flup); } status = ixgbe_poll_flash_update_done_X540(hw); if (status == 0) hw_dbg(hw, "Flash update complete\n"); else hw_dbg(hw, "Flash update time out\n"); } out: return status; } /** * ixgbe_poll_flash_update_done_X540 - Poll flash update status * @hw: pointer to hardware structure * * Polls the FLUDONE (bit 26) of the EEC Register to determine when the * flash update is done. **/ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) { reg = IXGBE_READ_REG(hw, IXGBE_EEC); if (reg & IXGBE_EEC_FLUDONE) { status = 0; break; } udelay(5); } return status; } /** * ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to acquire * * Acquires the SWFW semaphore thought the SW_FW_SYNC register for * the specified function (CSR, PHY0, PHY1, NVM, Flash) **/ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; u32 fwmask = mask << 5; u32 hwmask = 0; u32 timeout = 200; u32 i; s32 ret_val = 0; if (swmask == IXGBE_GSSR_EEP_SM) hwmask = IXGBE_GSSR_FLASH_SM; /* SW only mask doesn't have FW bit pair */ if (swmask == IXGBE_GSSR_SW_MNG_SM) fwmask = 0; for (i = 0; i < timeout; i++) { /* * SW NVM semaphore bit is used for access to all * SW_FW_SYNC bits (not just NVM) */ if (ixgbe_get_swfw_sync_semaphore(hw)) { ret_val = IXGBE_ERR_SWFW_SYNC; goto out; } swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (!(swfw_sync & (fwmask | swmask | hwmask))) { swfw_sync |= swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msleep(5); goto out; } else { /* * Firmware currently using resource (fwmask), hardware * currently using resource (hwmask), or other software * thread currently using resource (swmask) */ ixgbe_release_swfw_sync_semaphore(hw); msleep(5); } } /* Failed to get SW only semaphore */ if (swmask == IXGBE_GSSR_SW_MNG_SM) { ret_val = IXGBE_ERR_SWFW_SYNC; goto out; } /* If the resource is not released by the FW/HW the SW can assume that * the FW/HW malfunctions. In that case the SW should sets the SW bit(s) * of the requested resource(s) while ignoring the corresponding FW/HW * bits in the SW_FW_SYNC register. */ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (swfw_sync & (fwmask | hwmask)) { if (ixgbe_get_swfw_sync_semaphore(hw)) { ret_val = IXGBE_ERR_SWFW_SYNC; goto out; } swfw_sync |= swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msleep(5); } out: return ret_val; } /** * ixgbe_release_swfw_sync_X540 - Release SWFW semaphore * @hw: pointer to hardware structure * @mask: Mask to specify which semaphore to release * * Releases the SWFW semaphore through the SW_FW_SYNC register * for the specified function (CSR, PHY0, PHY1, EVM, Flash) **/ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask) { u32 swfw_sync; u32 swmask = mask; ixgbe_get_swfw_sync_semaphore(hw); swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); swfw_sync &= ~swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); msleep(5); } /** * ixgbe_get_nvm_semaphore - Get hardware semaphore * @hw: pointer to hardware structure * * Sets the hardware semaphores so SW/FW can gain control of shared resources **/ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) { s32 status = IXGBE_ERR_EEPROM; u32 timeout = 2000; u32 i; u32 swsm; /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* * If the SMBI bit is 0 when we read it, then the bit will be * set and we have the semaphore */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); if (!(swsm & IXGBE_SWSM_SMBI)) { status = 0; break; } udelay(50); } /* Now get the semaphore between SW/FW through the REGSMP bit */ if (status == 0) { for (i = 0; i < timeout; i++) { swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); if (!(swsm & IXGBE_SWFW_REGSMP)) break; udelay(50); } /* * Release semaphores and return error if SW NVM semaphore * was not granted because we don't have access to the EEPROM */ if (i >= timeout) { hw_dbg(hw, "REGSMP Software NVM semaphore not " "granted.\n"); ixgbe_release_swfw_sync_semaphore(hw); status = IXGBE_ERR_EEPROM; } } else { hw_dbg(hw, "Software semaphore SMBI between device drivers " "not granted.\n"); } return status; } /** * ixgbe_release_nvm_semaphore - Release hardware semaphore * @hw: pointer to hardware structure * * This function clears hardware semaphore bits. **/ static void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw) { u32 swsm; /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); swsm &= ~IXGBE_SWSM_SMBI; IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm); swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC); swsm &= ~IXGBE_SWFW_REGSMP; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm); IXGBE_WRITE_FLUSH(hw); } /** * ixgbe_blink_led_start_X540 - Blink LED based on index. * @hw: pointer to hardware structure * @index: led number to blink * * Devices that implement the version 2 interface: * X540 **/ s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index) { u32 macc_reg; u32 ledctl_reg; ixgbe_link_speed speed; bool link_up; /* * Link should be up in order for the blink bit in the LED control * register to work. Force link and speed in the MAC if link is down. * This will be reversed when we stop the blinking. */ hw->mac.ops.check_link(hw, &speed, &link_up, false); if (link_up == false) { macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS; IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); } /* Set the LED to LINK_UP + BLINK. */ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); ledctl_reg |= IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); IXGBE_WRITE_FLUSH(hw); return 0; } /** * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index. * @hw: pointer to hardware structure * @index: led number to stop blinking * * Devices that implement the version 2 interface: * X540 **/ s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index) { u32 macc_reg; u32 ledctl_reg; /* Restore the LED to its default value. */ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); ledctl_reg &= ~IXGBE_LED_MODE_MASK(index); ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index); ledctl_reg &= ~IXGBE_LED_BLINK(index); IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg); /* Unforce link and speed in the MAC. */ macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC); macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS); IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg); IXGBE_WRITE_FLUSH(hw); return 0; } ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/ixgbe_x540.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _IXGBE_X540_H_ #define _IXGBE_X540_H_ #include "ixgbe_type.h" s32 ixgbe_get_link_capabilities_X540(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw); s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool link_up_wait_to_complete); s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw); s32 ixgbe_start_hw_X540(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw); s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw); s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data); s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw, u16 offset, u16 words, u16 *data); s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw); s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, u16 *checksum_val); u16 ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw); s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index); #endif /* _IXGBE_X540_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/kcompat.c ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #include "ixgbe.h" #include "kcompat.h" /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) ) /* From lib/vsprintf.c */ #include static int skip_atoi(const char **s) { int i=0; while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #define _kc_ZEROPAD 1 /* pad with zero */ #define _kc_SIGN 2 /* unsigned/signed long */ #define _kc_PLUS 4 /* show plus */ #define _kc_SPACE 8 /* space if plus */ #define _kc_LEFT 16 /* left justified */ #define _kc_SPECIAL 32 /* 0x */ #define _kc_LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; digits = (type & _kc_LARGE) ? large_digits : small_digits; if (type & _kc_LEFT) type &= ~_kc_ZEROPAD; if (base < 2 || base > 36) return 0; c = (type & _kc_ZEROPAD) ? '0' : ' '; sign = 0; if (type & _kc_SIGN) { if (num < 0) { sign = '-'; num = -num; size--; } else if (type & _kc_PLUS) { sign = '+'; size--; } else if (type & _kc_SPACE) { sign = ' '; size--; } } if (type & _kc_SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(_kc_ZEROPAD+_kc_LEFT))) { while(size-->0) { if (buf <= end) *buf = ' '; ++buf; } } if (sign) { if (buf <= end) *buf = sign; ++buf; } if (type & _kc_SPECIAL) { if (base==8) { if (buf <= end) *buf = '0'; ++buf; } else if (base==16) { if (buf <= end) *buf = '0'; ++buf; if (buf <= end) *buf = digits[33]; ++buf; } } if (!(type & _kc_LEFT)) { while (size-- > 0) { if (buf <= end) *buf = c; ++buf; } } while (i < precision--) { if (buf <= end) *buf = '0'; ++buf; } while (i-- > 0) { if (buf <= end) *buf = tmp[i]; ++buf; } while (size-- > 0) { if (buf <= end) *buf = ' '; ++buf; } return buf; } int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { int len; unsigned long long num; int i, base; char *str, *end, c; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ /* 'z' changed to 'Z' --davidm 1/25/99 */ str = buf; end = buf + size - 1; if (end < buf - 1) { end = ((void *) -1); size = end - buf + 1; } for (; *fmt ; ++fmt) { if (*fmt != '%') { if (str <= end) *str = *fmt; ++str; continue; } /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= _kc_LEFT; goto repeat; case '+': flags |= _kc_PLUS; goto repeat; case ' ': flags |= _kc_SPACE; goto repeat; case '#': flags |= _kc_SPECIAL; goto repeat; case '0': flags |= _kc_ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (isdigit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= _kc_LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (isdigit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { qualifier = *fmt; ++fmt; } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & _kc_LEFT)) { while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } } c = (unsigned char) va_arg(args, int); if (str <= end) *str = c; ++str; while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } continue; case 's': s = va_arg(args, char *); if (!s) s = ""; len = strnlen(s, precision); if (!(flags & _kc_LEFT)) { while (len < field_width--) { if (str <= end) *str = ' '; ++str; } } for (i = 0; i < len; ++i) { if (str <= end) *str = *s; ++str; ++s; } while (len < field_width--) { if (str <= end) *str = ' '; ++str; } continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= _kc_ZEROPAD; } str = number(str, end, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); continue; case 'n': /* FIXME: * What does C99 say about the overflow case here? */ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else if (qualifier == 'Z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } continue; case '%': if (str <= end) *str = '%'; ++str; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= _kc_LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= _kc_SIGN; case 'u': break; default: if (str <= end) *str = '%'; ++str; if (*fmt) { if (str <= end) *str = *fmt; ++str; } else { --fmt; } continue; } if (qualifier == 'L') num = va_arg(args, long long); else if (qualifier == 'l') { num = va_arg(args, unsigned long); if (flags & _kc_SIGN) num = (signed long) num; } else if (qualifier == 'Z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & _kc_SIGN) num = (signed short) num; } else { num = va_arg(args, unsigned int); if (flags & _kc_SIGN) num = (signed int) num; } str = number(str, end, num, base, field_width, precision, flags); } if (str <= end) *str = '\0'; else if (size > 0) /* don't write out a null byte if the buf size is zero */ *end = '\0'; /* the trailing null byte doesn't count towards the total * ++str; */ return str-buf; } int _kc_snprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = _kc_vsnprintf(buf,size,fmt,args); va_end(args); return i; } #endif /* < 2.4.8 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #ifdef CONFIG_PCI_IOV int __kc_pci_vfs_assigned(struct pci_dev *dev) { unsigned int vfs_assigned = 0; #ifdef HAVE_PCI_DEV_FLAGS_ASSIGNED int pos; struct pci_dev *vfdev; unsigned short dev_id; /* only search if we are a PF */ if (!dev->is_physfn) return 0; /* find SR-IOV capability */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); if (!pos) return 0; /* * * determine the device ID for the VFs, the vendor ID will be the * * same as the PF so there is no need to check for that one * */ pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &dev_id); /* loop through all the VFs to see if we own any that are assigned */ vfdev = pci_get_device(dev->vendor, dev_id, NULL); while (vfdev) { /* * * It is considered assigned if it is a virtual function with * * our dev as the physical function and the assigned bit is set * */ if (vfdev->is_virtfn && (vfdev->physfn == dev) && (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED)) vfs_assigned++; vfdev = pci_get_device(dev->vendor, dev_id, vfdev); } #endif /* HAVE_PCI_DEV_FLAGS_ASSIGNED */ return vfs_assigned; } #endif /* CONFIG_PCI_IOV */ #endif /* 3.10.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) /**************************************/ /* PCI DMA MAPPING */ #if defined(CONFIG_HIGHMEM) #ifndef PCI_DRAM_OFFSET #define PCI_DRAM_OFFSET 0 #endif u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) { return (((u64) (page - mem_map) << PAGE_SHIFT) + offset + PCI_DRAM_OFFSET); } #else /* CONFIG_HIGHMEM */ u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction) { return pci_map_single(dev, (void *)page_address(page) + offset, size, direction); } #endif /* CONFIG_HIGHMEM */ void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction) { return pci_unmap_single(dev, dma_addr, size, direction); } #endif /* 2.4.13 => 2.4.3 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) /**************************************/ /* PCI DRIVER API */ int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask) { if (!pci_dma_supported(dev, mask)) return -EIO; dev->dma_mask = mask; return 0; } int _kc_pci_request_regions(struct pci_dev *dev, char *res_name) { int i; for (i = 0; i < 6; i++) { if (pci_resource_len(dev, i) == 0) continue; if (pci_resource_flags(dev, i) & IORESOURCE_IO) { if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { pci_release_regions(dev); return -EBUSY; } } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) { if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) { pci_release_regions(dev); return -EBUSY; } } } return 0; } void _kc_pci_release_regions(struct pci_dev *dev) { int i; for (i = 0; i < 6; i++) { if (pci_resource_len(dev, i) == 0) continue; if (pci_resource_flags(dev, i) & IORESOURCE_IO) release_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i)); } } /**************************************/ /* NETWORK DRIVER API */ struct net_device * _kc_alloc_etherdev(int sizeof_priv) { struct net_device *dev; int alloc_size; alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31; dev = kzalloc(alloc_size, GFP_KERNEL); if (!dev) return NULL; if (sizeof_priv) dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31); dev->name[0] = '\0'; ether_setup(dev); return dev; } int _kc_is_valid_ether_addr(u8 *addr) { const char zaddr[6] = { 0, }; return !(addr[0] & 1) && memcmp(addr, zaddr, 6); } #endif /* 2.4.3 => 2.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) int _kc_pci_set_power_state(struct pci_dev *dev, int state) { return 0; } int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable) { return 0; } #endif /* 2.4.6 => 2.4.3 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; frag->page = page; frag->page_offset = off; frag->size = size; skb_shinfo(skb)->nr_frags = i + 1; } /* * Original Copyright: * find_next_bit.c: fallback find next bit implementation * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) */ /** * find_next_bit - find the next set bit in a memory region * @addr: The address to base the search on * @offset: The bitnumber to start searching at * @size: The maximum size to search */ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; if (offset >= size) return size; size -= result; offset %= BITS_PER_LONG; if (offset) { tmp = *(p++); tmp &= (~0UL << offset); if (size < BITS_PER_LONG) goto found_first; if (tmp) goto found_middle; size -= BITS_PER_LONG; result += BITS_PER_LONG; } while (size & ~(BITS_PER_LONG-1)) { if ((tmp = *(p++))) goto found_middle; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = *p; found_first: tmp &= (~0UL >> (BITS_PER_LONG - size)); if (tmp == 0UL) /* Are any bits set? */ return result + size; /* Nope. */ found_middle: return result + ffs(tmp); } size_t _kc_strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } #endif /* 2.6.0 => 2.4.6 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) int _kc_scnprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = vsnprintf(buf, size, fmt, args); va_end(args); return (i >= size) ? (size - 1) : i; } #endif /* < 2.6.4 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES) = {1}; #endif /* < 2.6.10 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) char *_kc_kstrdup(const char *s, unsigned int gfp) { size_t len; char *buf; if (!s) return NULL; len = strlen(s) + 1; buf = kmalloc(len, gfp); if (buf) memcpy(buf, s, len); return buf; } #endif /* < 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) void *_kc_kzalloc(size_t size, int flags) { void *ret = kmalloc(size, flags); if (ret) memset(ret, 0, size); return ret; } #endif /* <= 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) int _kc_skb_pad(struct sk_buff *skb, int pad) { int ntail; /* If the skbuff is non linear tailroom is always zero.. */ if(!skb_cloned(skb) && skb_tailroom(skb) >= pad) { memset(skb->data+skb->len, 0, pad); return 0; } ntail = skb->data_len + pad - (skb->end - skb->tail); if (likely(skb_cloned(skb) || ntail > 0)) { if (pskb_expand_head(skb, 0, ntail, GFP_ATOMIC)); goto free_skb; } #ifdef MAX_SKB_FRAGS if (skb_is_nonlinear(skb) && !__pskb_pull_tail(skb, skb->data_len)) goto free_skb; #endif memset(skb->data + skb->len, 0, pad); return 0; free_skb: kfree_skb(skb); return -ENOMEM; } #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4))) int _kc_pci_save_state(struct pci_dev *pdev) { struct adapter_struct *adapter = pci_get_drvdata(pdev); int size = PCI_CONFIG_SPACE_LEN, i; u16 pcie_cap_offset, pcie_link_status; #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) /* no ->dev for 2.4 kernels */ WARN_ON(pdev->dev.driver_data == NULL); #endif pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (pcie_cap_offset) { if (!pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) size = PCIE_CONFIG_SPACE_LEN; } pci_config_space_ich8lan(); #ifdef HAVE_PCI_ERS if (adapter->config_space == NULL) #else WARN_ON(adapter->config_space != NULL); #endif adapter->config_space = kmalloc(size, GFP_KERNEL); if (!adapter->config_space) { printk(KERN_ERR "Out of memory in pci_save_state\n"); return -ENOMEM; } for (i = 0; i < (size / 4); i++) pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]); return 0; } void _kc_pci_restore_state(struct pci_dev *pdev) { struct adapter_struct *adapter = pci_get_drvdata(pdev); int size = PCI_CONFIG_SPACE_LEN, i; u16 pcie_cap_offset; u16 pcie_link_status; if (adapter->config_space != NULL) { pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (pcie_cap_offset && !pci_read_config_word(pdev, pcie_cap_offset + PCIE_LINK_STATUS, &pcie_link_status)) size = PCIE_CONFIG_SPACE_LEN; pci_config_space_ich8lan(); for (i = 0; i < (size / 4); i++) pci_write_config_dword(pdev, i * 4, adapter->config_space[i]); #ifndef HAVE_PCI_ERS kfree(adapter->config_space); adapter->config_space = NULL; #endif } } #endif /* !(RHEL_RELEASE_CODE >= RHEL 5.4) */ #ifdef HAVE_PCI_ERS void _kc_free_netdev(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); if (adapter->config_space != NULL) kfree(adapter->config_space); #ifdef CONFIG_SYSFS if (netdev->reg_state == NETREG_UNINITIALIZED) { kfree((char *)netdev - netdev->padded); } else { BUG_ON(netdev->reg_state != NETREG_UNREGISTERED); netdev->reg_state = NETREG_RELEASED; class_device_put(&netdev->class_dev); } #else kfree((char *)netdev - netdev->padded); #endif } #endif void *_kc_kmemdup(const void *src, size_t len, unsigned gfp) { void *p; p = kzalloc(len, gfp); if (p) memcpy(p, src, len); return p; } #endif /* <= 2.6.19 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) /* hexdump code taken from lib/hexdump.c */ static void _kc_hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, unsigned char *linebuf, size_t linebuflen, bool ascii) { const u8 *ptr = buf; u8 ch; int j, lx = 0; int ascii_column; if (rowsize != 16 && rowsize != 32) rowsize = 16; if (!len) goto nil; if (len > rowsize) /* limit to one line at a time */ len = rowsize; if ((len % groupsize) != 0) /* no mixed size output */ groupsize = 1; switch (groupsize) { case 8: { const u64 *ptr8 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%16.16llx", j ? " " : "", (unsigned long long)*(ptr8 + j)); ascii_column = 17 * ngroups + 2; break; } case 4: { const u32 *ptr4 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%8.8x", j ? " " : "", *(ptr4 + j)); ascii_column = 9 * ngroups + 2; break; } case 2: { const u16 *ptr2 = buf; int ngroups = len / groupsize; for (j = 0; j < ngroups; j++) lx += scnprintf((char *)(linebuf + lx), linebuflen - lx, "%s%4.4x", j ? " " : "", *(ptr2 + j)); ascii_column = 5 * ngroups + 2; break; } default: for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) { ch = ptr[j]; linebuf[lx++] = hex_asc(ch >> 4); linebuf[lx++] = hex_asc(ch & 0x0f); linebuf[lx++] = ' '; } if (j) lx--; ascii_column = 3 * rowsize + 2; break; } if (!ascii) goto nil; while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) linebuf[lx++] = ' '; for (j = 0; (j < len) && (lx + 2) < linebuflen; j++) linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j] : '.'; nil: linebuf[lx++] = '\0'; } void _kc_print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii) { const u8 *ptr = buf; int i, linelen, remaining = len; unsigned char linebuf[200]; if (rowsize != 16 && rowsize != 32) rowsize = 16; for (i = 0; i < len; i += rowsize) { linelen = min(remaining, rowsize); remaining -= rowsize; _kc_hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize, linebuf, sizeof(linebuf), ascii); switch (prefix_type) { case DUMP_PREFIX_ADDRESS: printk("%s%s%*p: %s\n", level, prefix_str, (int)(2 * sizeof(void *)), ptr + i, linebuf); break; case DUMP_PREFIX_OFFSET: printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf); break; default: printk("%s%s%s\n", level, prefix_str, linebuf); break; } } } #endif /* < 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) int ixgbe_dcb_netlink_register(void) { return 0; } int ixgbe_dcb_netlink_unregister(void) { return 0; } int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max) { return 0; } #endif /* < 2.6.23 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) #ifdef NAPI struct net_device *napi_to_poll_dev(struct napi_struct *napi) { struct adapter_q_vector *q_vector = container_of(napi, struct adapter_q_vector, napi); return &q_vector->poll_dev; } int __kc_adapter_clean(struct net_device *netdev, int *budget) { int work_done; int work_to_do = min(*budget, netdev->quota); /* kcompat.h netif_napi_add puts napi struct in "fake netdev->priv" */ struct napi_struct *napi = netdev->priv; work_done = napi->poll(napi, work_to_do); *budget -= work_done; netdev->quota -= work_done; return (work_done >= work_to_do) ? 1 : 0; } #endif /* NAPI */ #endif /* <= 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) void _kc_pci_disable_link_state(struct pci_dev *pdev, int state) { struct pci_dev *parent = pdev->bus->self; u16 link_state; int pos; if (!parent) return; pos = pci_find_capability(parent, PCI_CAP_ID_EXP); if (pos) { pci_read_config_word(parent, pos + PCI_EXP_LNKCTL, &link_state); link_state &= ~state; pci_write_config_word(parent, pos + PCI_EXP_LNKCTL, link_state); } } #endif /* < 2.6.26 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) #ifdef HAVE_TX_MQ void _kc_netif_tx_stop_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_stop_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_stop_subqueue(netdev, i); } void _kc_netif_tx_wake_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_wake_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_wake_subqueue(netdev, i); } void _kc_netif_tx_start_all_queues(struct net_device *netdev) { struct adapter_struct *adapter = netdev_priv(netdev); int i; netif_start_queue(netdev); if (netif_is_multiqueue(netdev)) for (i = 0; i < adapter->num_tx_queues; i++) netif_start_subqueue(netdev, i); } #endif /* HAVE_TX_MQ */ #ifndef __WARN_printf void __kc_warn_slowpath(const char *file, int line, const char *fmt, ...) { va_list args; printk(KERN_WARNING "------------[ cut here ]------------\n"); printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, line); va_start(args, fmt); vprintk(fmt, args); va_end(args); dump_stack(); } #endif /* __WARN_printf */ #endif /* < 2.6.27 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) int _kc_pci_prepare_to_sleep(struct pci_dev *dev) { pci_power_t target_state; int error; target_state = pci_choose_state(dev, PMSG_SUSPEND); pci_enable_wake(dev, target_state, true); error = pci_set_power_state(dev, target_state); if (error) pci_enable_wake(dev, target_state, false); return error; } int _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable) { int err; err = pci_enable_wake(dev, PCI_D3cold, enable); if (err) goto out; err = pci_enable_wake(dev, PCI_D3hot, enable); out: return err; } #endif /* < 2.6.28 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ) void _kc_skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, int size) { skb_fill_page_desc(skb, i, page, off, size); skb->len += size; skb->data_len += size; skb->truesize += size; } #endif /* < 3.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) #ifdef HAVE_NETDEV_SELECT_QUEUE #include static u32 _kc_simple_tx_hashrnd; static u32 _kc_simple_tx_hashrnd_initialized; u16 _kc_skb_tx_hash(struct net_device *dev, struct sk_buff *skb) { u32 addr1, addr2, ports; u32 hash, ihl; u8 ip_proto = 0; if (unlikely(!_kc_simple_tx_hashrnd_initialized)) { get_random_bytes(&_kc_simple_tx_hashrnd, 4); _kc_simple_tx_hashrnd_initialized = 1; } switch (skb->protocol) { case htons(ETH_P_IP): if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl; break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): ip_proto = ipv6_hdr(skb)->nexthdr; addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; ihl = (40 >> 2); break; #endif default: return 0; } switch (ip_proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_DCCP: case IPPROTO_ESP: case IPPROTO_AH: case IPPROTO_SCTP: case IPPROTO_UDPLITE: ports = *((u32 *) (skb_network_header(skb) + (ihl * 4))); break; default: ports = 0; break; } hash = jhash_3words(addr1, addr2, ports, _kc_simple_tx_hashrnd); return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); } #endif /* HAVE_NETDEV_SELECT_QUEUE */ #endif /* < 2.6.30 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) #ifdef HAVE_TX_MQ #ifndef CONFIG_NETDEVICES_MULTIQUEUE void _kc_netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) { unsigned int real_num = dev->real_num_tx_queues; struct Qdisc *qdisc; int i; if (unlikely(txq > dev->num_tx_queues)) ; else if (txq > real_num) dev->real_num_tx_queues = txq; else if ( txq < real_num) { dev->real_num_tx_queues = txq; for (i = txq; i < dev->num_tx_queues; i++) { qdisc = netdev_get_tx_queue(dev, i)->qdisc; if (qdisc) { spin_lock_bh(qdisc_lock(qdisc)); qdisc_reset(qdisc); spin_unlock_bh(qdisc_lock(qdisc)); } } } } #endif /* CONFIG_NETDEVICES_MULTIQUEUE */ #endif /* HAVE_TX_MQ */ #endif /* < 2.6.35 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ) static const u32 _kc_flags_dup_features = (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH); u32 _kc_ethtool_op_get_flags(struct net_device *dev) { return dev->features & _kc_flags_dup_features; } int _kc_ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) { if (data & ~supported) return -EINVAL; dev->features = ((dev->features & ~_kc_flags_dup_features) | (data & _kc_flags_dup_features)); return 0; } #endif /* < 2.6.36 */ /******************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) ) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0))) u8 _kc_netdev_get_num_tc(struct net_device *dev) { struct adapter_struct *kc_adapter = netdev_priv(dev); if (kc_adapter->flags & IXGBE_FLAG_DCB_ENABLED) return kc_adapter->tc; else return 0; } u8 _kc_netdev_get_prio_tc_map(struct net_device *dev, u8 up) { struct adapter_struct *kc_adapter = netdev_priv(dev); int tc; u8 map; for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { map = kc_adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap; if (map & (1 << up)) return tc; } return 0; } #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)) */ #endif /* < 2.6.39 */ ================================================ FILE: lib/librte_eal/linuxapp/kni/ethtool/ixgbe/kcompat.h ================================================ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver Copyright(c) 1999 - 2012 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: e1000-devel Mailing List Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 *******************************************************************************/ #ifndef _KCOMPAT_H_ #define _KCOMPAT_H_ #ifndef LINUX_VERSION_CODE #include #else #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* NAPI enable/disable flags here */ /* enable NAPI for ixgbe by default */ #undef CONFIG_IXGBE_NAPI #define CONFIG_IXGBE_NAPI #define NAPI #ifdef CONFIG_IXGBE_NAPI #undef NAPI #define NAPI #endif /* CONFIG_IXGBE_NAPI */ #ifdef IXGBE_NAPI #undef NAPI #define NAPI #endif /* IXGBE_NAPI */ #ifdef IXGBE_NO_NAPI #undef NAPI #endif /* IXGBE_NO_NAPI */ #define adapter_struct ixgbe_adapter #define adapter_q_vector ixgbe_q_vector /* and finally set defines so that the code sees the changes */ #ifdef NAPI #ifndef CONFIG_IXGBE_NAPI #define CONFIG_IXGBE_NAPI #endif #else #undef CONFIG_IXGBE_NAPI #endif /* NAPI */ /* packet split disable/enable */ #ifdef DISABLE_PACKET_SPLIT #ifndef CONFIG_IXGBE_DISABLE_PACKET_SPLIT #define CONFIG_IXGBE_DISABLE_PACKET_SPLIT #endif #endif /* DISABLE_PACKET_SPLIT */ /* MSI compatibility code for all kernels and drivers */ #ifdef DISABLE_PCI_MSI #undef CONFIG_PCI_MSI #endif #ifndef CONFIG_PCI_MSI #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) struct msix_entry { u16 vector; /* kernel uses to write allocated vector */ u16 entry; /* driver uses to specify entry, OS writes */ }; #endif #undef pci_enable_msi #define pci_enable_msi(a) -ENOTSUPP #undef pci_disable_msi #define pci_disable_msi(a) do {} while (0) #undef pci_enable_msix #define pci_enable_msix(a, b, c) -ENOTSUPP #undef pci_disable_msix #define pci_disable_msix(a) do {} while (0) #define msi_remove_pci_irq_vectors(a) do {} while (0) #endif /* CONFIG_PCI_MSI */ #ifdef DISABLE_PM #undef CONFIG_PM #endif #ifdef DISABLE_NET_POLL_CONTROLLER #undef CONFIG_NET_POLL_CONTROLLER #endif #ifndef PMSG_SUSPEND #define PMSG_SUSPEND 3 #endif /* generic boolean compatibility */ #undef TRUE #undef FALSE #define TRUE true #define FALSE false #ifdef GCC_VERSION #if ( GCC_VERSION < 3000 ) #define _Bool char #endif #else #define _Bool char #endif /* kernels less than 2.4.14 don't have this */ #ifndef ETH_P_8021Q #define ETH_P_8021Q 0x8100 #endif #ifndef module_param #define module_param(v,t,p) MODULE_PARM(v, "i"); #endif #ifndef DMA_64BIT_MASK #define DMA_64BIT_MASK 0xffffffffffffffffULL #endif #ifndef DMA_32BIT_MASK #define DMA_32BIT_MASK 0x00000000ffffffffULL #endif #ifndef PCI_CAP_ID_EXP #define PCI_CAP_ID_EXP 0x10 #endif #ifndef PCIE_LINK_STATE_L0S #define PCIE_LINK_STATE_L0S 1 #endif #ifndef PCIE_LINK_STATE_L1 #define PCIE_LINK_STATE_L1 2 #endif #ifndef mmiowb #ifdef CONFIG_IA64 #define mmiowb() asm volatile ("mf.a" ::: "memory") #else #define mmiowb() #endif #endif #ifndef SET_NETDEV_DEV #define SET_NETDEV_DEV(net, pdev) #endif #if !defined(HAVE_FREE_NETDEV) && ( LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ) #define free_netdev(x) kfree(x) #endif #ifdef HAVE_POLL_CONTROLLER #define CONFIG_NET_POLL_CONTROLLER #endif #ifndef SKB_DATAREF_SHIFT /* if we do not have the infrastructure to detect if skb_header is cloned just return false in all cases */ #define skb_header_cloned(x) 0 #endif #ifndef NETIF_F_GSO #define gso_size tso_size #define gso_segs tso_segs #endif #ifndef NETIF_F_GRO #define vlan_gro_receive(_napi, _vlgrp, _vlan, _skb) \ vlan_hwaccel_receive_skb(_skb, _vlgrp, _vlan) #define napi_gro_receive(_napi, _skb) netif_receive_skb(_skb) #endif #ifndef NETIF_F_SCTP_CSUM #define NETIF_F_SCTP_CSUM 0 #endif #ifndef NETIF_F_LRO #define NETIF_F_LRO (1 << 15) #endif #ifndef NETIF_F_NTUPLE #define NETIF_F_NTUPLE (1 << 27) #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #ifndef CHECKSUM_PARTIAL #define CHECKSUM_PARTIAL CHECKSUM_HW #define CHECKSUM_COMPLETE CHECKSUM_HW #endif #ifndef __read_mostly #define __read_mostly #endif #ifndef MII_RESV1 #define MII_RESV1 0x17 /* Reserved... */ #endif #ifndef unlikely #define unlikely(_x) _x #define likely(_x) _x #endif #ifndef WARN_ON #define WARN_ON(x) #endif #ifndef PCI_DEVICE #define PCI_DEVICE(vend,dev) \ .vendor = (vend), .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID #endif #ifndef node_online #define node_online(node) ((node) == 0) #endif #ifndef num_online_cpus #define num_online_cpus() smp_num_cpus #endif #ifndef cpu_online #define cpu_online(cpuid) test_bit((cpuid), &cpu_online_map) #endif #ifndef _LINUX_RANDOM_H #include #endif #ifndef DECLARE_BITMAP #ifndef BITS_TO_LONGS #define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) #endif #define DECLARE_BITMAP(name,bits) long name[BITS_TO_LONGS(bits)] #endif #ifndef VLAN_HLEN #define VLAN_HLEN 4 #endif #ifndef VLAN_ETH_HLEN #define VLAN_ETH_HLEN 18 #endif #ifndef VLAN_ETH_FRAME_LEN #define VLAN_ETH_FRAME_LEN 1518 #endif #if !defined(IXGBE_DCA) && !defined(IGB_DCA) #define dca_get_tag(b) 0 #define dca_add_requester(a) -1 #define dca_remove_requester(b) do { } while(0) #define DCA_PROVIDER_ADD 0x0001 #define DCA_PROVIDER_REMOVE 0x0002 #endif #ifndef DCA_GET_TAG_TWO_ARGS #define dca3_get_tag(a,b) dca_get_tag(b) #endif #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #if defined(__i386__) || defined(__x86_64__) #define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #endif #endif /* taken from 2.6.24 definition in linux/kernel.h */ #ifndef IS_ALIGNED #define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) #endif #ifndef NETIF_F_HW_VLAN_TX struct _kc_vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; __be16 h_vlan_proto; __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; #define vlan_ethhdr _kc_vlan_ethhdr struct _kc_vlan_hdr { __be16 h_vlan_TCI; __be16 h_vlan_encapsulated_proto; }; #define vlan_hdr _kc_vlan_hdr #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #define vlan_tx_tag_present(_skb) 0 #define vlan_tx_tag_get(_skb) 0 #endif #endif #ifndef VLAN_PRIO_SHIFT #define VLAN_PRIO_SHIFT 13 #endif #ifndef __GFP_COLD #define __GFP_COLD 0 #endif /*****************************************************************************/ /* Installations with ethtool version without eeprom, adapter id, or statistics * support */ #ifndef ETH_GSTRING_LEN #define ETH_GSTRING_LEN 32 #endif #ifndef ETHTOOL_GSTATS #define ETHTOOL_GSTATS 0x1d #undef ethtool_drvinfo #define ethtool_drvinfo k_ethtool_drvinfo struct k_ethtool_drvinfo { u32 cmd; char driver[32]; char version[32]; char fw_version[32]; char bus_info[32]; char reserved1[32]; char reserved2[16]; u32 n_stats; u32 testinfo_len; u32 eedump_len; u32 regdump_len; }; struct ethtool_stats { u32 cmd; u32 n_stats; u64 data[0]; }; #endif /* ETHTOOL_GSTATS */ #ifndef ETHTOOL_PHYS_ID #define ETHTOOL_PHYS_ID 0x1c #endif /* ETHTOOL_PHYS_ID */ #ifndef ETHTOOL_GSTRINGS #define ETHTOOL_GSTRINGS 0x1b enum ethtool_stringset { ETH_SS_TEST = 0, ETH_SS_STATS, }; struct ethtool_gstrings { u32 cmd; /* ETHTOOL_GSTRINGS */ u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ u32 len; /* number of strings in the string set */ u8 data[0]; }; #endif /* ETHTOOL_GSTRINGS */ #ifndef ETHTOOL_TEST #define ETHTOOL_TEST 0x1a enum ethtool_test_flags { ETH_TEST_FL_OFFLINE = (1 << 0), ETH_TEST_FL_FAILED = (1 << 1), }; struct ethtool_test { u32 cmd; u32 flags; u32 reserved; u32 len; u64 data[0]; }; #endif /* ETHTOOL_TEST */ #ifndef ETHTOOL_GEEPROM #define ETHTOOL_GEEPROM 0xb #undef ETHTOOL_GREGS struct ethtool_eeprom { u32 cmd; u32 magic; u32 offset; u32 len; u8 data[0]; }; struct ethtool_value { u32 cmd; u32 data; }; #endif /* ETHTOOL_GEEPROM */ #ifndef ETHTOOL_GLINK #define ETHTOOL_GLINK 0xa #endif /* ETHTOOL_GLINK */ #ifndef ETHTOOL_GWOL #define ETHTOOL_GWOL 0x5 #define ETHTOOL_SWOL 0x6 #define SOPASS_MAX 6 struct ethtool_wolinfo { u32 cmd; u32 supported; u32 wolopts; u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ }; #endif /* ETHTOOL_GWOL */ #ifndef ETHTOOL_GREGS #define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ #define ethtool_regs _kc_ethtool_regs /* for passing big chunks of data */ struct _kc_ethtool_regs { u32 cmd; u32 version; /* driver-specific, indicates different chips/revs */ u32 len; /* bytes */ u8 data[0]; }; #endif /* ETHTOOL_GREGS */ #ifndef ETHTOOL_GMSGLVL #define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ #endif #ifndef ETHTOOL_SMSGLVL #define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ #endif #ifndef ETHTOOL_NWAY_RST #define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ #endif #ifndef ETHTOOL_GLINK #define ETHTOOL_GLINK 0x0000000a /* Get link status */ #endif #ifndef ETHTOOL_GEEPROM #define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ #endif #ifndef ETHTOOL_SEEPROM #define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ #endif #ifndef ETHTOOL_GCOALESCE #define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ /* for configuring coalescing parameters of chip */ #define ethtool_coalesce _kc_ethtool_coalesce struct _kc_ethtool_coalesce { u32 cmd; /* ETHTOOL_{G,S}COALESCE */ /* How many usecs to delay an RX interrupt after * a packet arrives. If 0, only rx_max_coalesced_frames * is used. */ u32 rx_coalesce_usecs; /* How many packets to delay an RX interrupt after * a packet arrives. If 0, only rx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause RX interrupts to never be * generated. */ u32 rx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being serviced by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 rx_coalesce_usecs_irq; u32 rx_max_coalesced_frames_irq; /* How many usecs to delay a TX interrupt after * a packet is sent. If 0, only tx_max_coalesced_frames * is used. */ u32 tx_coalesce_usecs; /* How many packets to delay a TX interrupt after * a packet is sent. If 0, only tx_coalesce_usecs is * used. It is illegal to set both usecs and max frames * to zero as this would cause TX interrupts to never be * generated. */ u32 tx_max_coalesced_frames; /* Same as above two parameters, except that these values * apply while an IRQ is being serviced by the host. Not * all cards support this feature and the values are ignored * in that case. */ u32 tx_coalesce_usecs_irq; u32 tx_max_coalesced_frames_irq; /* How many usecs to delay in-memory statistics * block updates. Some drivers do not have an in-memory * statistic block, and in such cases this value is ignored. * This value must not be zero. */ u32 stats_block_coalesce_usecs; /* Adaptive RX/TX coalescing is an algorithm implemented by * some drivers to improve latency under low packet rates and * improve throughput under high packet rates. Some drivers * only implement one of RX or TX adaptive coalescing. Anything * not implemented by the driver causes these values to be * silently ignored. */ u32 use_adaptive_rx_coalesce; u32 use_adaptive_tx_coalesce; /* When the packet rate (measured in packets per second) * is below pkt_rate_low, the {rx,tx}_*_low parameters are * used. */ u32 pkt_rate_low; u32 rx_coalesce_usecs_low; u32 rx_max_coalesced_frames_low; u32 tx_coalesce_usecs_low; u32 tx_max_coalesced_frames_low; /* When the packet rate is below pkt_rate_high but above * pkt_rate_low (both measured in packets per second) the * normal {rx,tx}_* coalescing parameters are used. */ /* When the packet rate is (measured in packets per second) * is above pkt_rate_high, the {rx,tx}_*_high parameters are * used. */ u32 pkt_rate_high; u32 rx_coalesce_usecs_high; u32 rx_max_coalesced_frames_high; u32 tx_coalesce_usecs_high; u32 tx_max_coalesced_frames_high; /* How often to do adaptive coalescing packet rate sampling, * measured in seconds. Must not be zero. */ u32 rate_sample_interval; }; #endif /* ETHTOOL_GCOALESCE */ #ifndef ETHTOOL_SCOALESCE #define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ #endif #ifndef ETHTOOL_GRINGPARAM #define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ /* for configuring RX/TX ring parameters */ #define ethtool_ringparam _kc_ethtool_ringparam struct _kc_ethtool_ringparam { u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ /* Read only attributes. These indicate the maximum number * of pending RX/TX ring entries the driver will allow the * user to set. */ u32 rx_max_pending; u32 rx_mini_max_pending; u32 rx_jumbo_max_pending; u32 tx_max_pending; /* Values changeable by the user. The valid values are * in the range 1 to the "*_max_pending" counterpart above. */ u32 rx_pending; u32 rx_mini_pending; u32 rx_jumbo_pending; u32 tx_pending; }; #endif /* ETHTOOL_GRINGPARAM */ #ifndef ETHTOOL_SRINGPARAM #define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ #endif #ifndef ETHTOOL_GPAUSEPARAM #define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ /* for configuring link flow control parameters */ #define ethtool_pauseparam _kc_ethtool_pauseparam struct _kc_ethtool_pauseparam { u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ /* If the link is being auto-negotiated (via ethtool_cmd.autoneg * being true) the user may set 'autoneg' here non-zero to have the * pause parameters be auto-negotiated too. In such a case, the * {rx,tx}_pause values below determine what capabilities are * advertised. * * If 'autoneg' is zero or the link is not being auto-negotiated, * then {rx,tx}_pause force the driver to use/not-use pause * flow control. */ u32 autoneg; u32 rx_pause; u32 tx_pause; }; #endif /* ETHTOOL_GPAUSEPARAM */ #ifndef ETHTOOL_SPAUSEPARAM #define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ #endif #ifndef ETHTOOL_GRXCSUM #define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_SRXCSUM #define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_GTXCSUM #define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_STXCSUM #define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ #endif #ifndef ETHTOOL_GSG #define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable * (ethtool_value) */ #endif #ifndef ETHTOOL_SSG #define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable * (ethtool_value). */ #endif #ifndef ETHTOOL_TEST #define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ #endif #ifndef ETHTOOL_GSTRINGS #define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ #endif #ifndef ETHTOOL_PHYS_ID #define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ #endif #ifndef ETHTOOL_GSTATS #define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ #endif #ifndef ETHTOOL_GTSO #define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ #endif #ifndef ETHTOOL_STSO #define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ #endif #ifndef ETHTOOL_BUSINFO_LEN #define ETHTOOL_BUSINFO_LEN 32 #endif #ifndef RHEL_RELEASE_CODE /* NOTE: RHEL_RELEASE_* introduced in RHEL4.5 */ #define RHEL_RELEASE_CODE 0 #endif #ifndef RHEL_RELEASE_VERSION #define RHEL_RELEASE_VERSION(a,b) (((a) << 8) + (b)) #endif #ifndef AX_RELEASE_CODE #define AX_RELEASE_CODE 0 #endif #ifndef AX_RELEASE_VERSION #define AX_RELEASE_VERSION(a,b) (((a) << 8) + (b)) #endif /* SuSE version macro is the same as Linux kernel version */ #ifndef SLE_VERSION #define SLE_VERSION(a,b,c) KERNEL_VERSION(a,b,c) #endif #ifndef SLE_VERSION_CODE #ifdef CONFIG_SUSE_KERNEL /* SLES11 GA is 2.6.27 based */ #if ( LINUX_VERSION_CODE == KERNEL_VERSION(2,6,27) ) #define SLE_VERSION_CODE SLE_VERSION(11,0,0) #elif ( LINUX_VERSION_CODE == KERNEL_VERSION(2,6,32) ) /* SLES11 SP1 is 2.6.32 based */ #define SLE_VERSION_CODE SLE_VERSION(11,1,0) #else #define SLE_VERSION_CODE 0 #endif #else /* CONFIG_SUSE_KERNEL */ #define SLE_VERSION_CODE 0 #endif /* CONFIG_SUSE_KERNEL */ #endif /* SLE_VERSION_CODE */ #ifdef __KLOCWORK__ #ifdef ARRAY_SIZE #undef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #endif /* __KLOCWORK__ */ /*****************************************************************************/ /* 2.4.3 => 2.4.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) ) /**************************************/ /* PCI DRIVER API */ #ifndef pci_set_dma_mask #define pci_set_dma_mask _kc_pci_set_dma_mask extern int _kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask); #endif #ifndef pci_request_regions #define pci_request_regions _kc_pci_request_regions extern int _kc_pci_request_regions(struct pci_dev *pdev, char *res_name); #endif #ifndef pci_release_regions #define pci_release_regions _kc_pci_release_regions extern void _kc_pci_release_regions(struct pci_dev *pdev); #endif /**************************************/ /* NETWORK DRIVER API */ #ifndef alloc_etherdev #define alloc_etherdev _kc_alloc_etherdev extern struct net_device * _kc_alloc_etherdev(int sizeof_priv); #endif #ifndef is_valid_ether_addr #define is_valid_ether_addr _kc_is_valid_ether_addr extern int _kc_is_valid_ether_addr(u8 *addr); #endif /**************************************/ /* MISCELLANEOUS */ #ifndef INIT_TQUEUE #define INIT_TQUEUE(_tq, _routine, _data) \ do { \ INIT_LIST_HEAD(&(_tq)->list); \ (_tq)->sync = 0; \ (_tq)->routine = _routine; \ (_tq)->data = _data; \ } while (0) #endif #endif /* 2.4.3 => 2.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) ) /* Generic MII registers. */ #define MII_BMCR 0x00 /* Basic mode control register */ #define MII_BMSR 0x01 /* Basic mode status register */ #define MII_PHYSID1 0x02 /* PHYS ID 1 */ #define MII_PHYSID2 0x03 /* PHYS ID 2 */ #define MII_ADVERTISE 0x04 /* Advertisement control reg */ #define MII_LPA 0x05 /* Link partner ability reg */ #define MII_EXPANSION 0x06 /* Expansion register */ /* Basic mode control register. */ #define BMCR_FULLDPLX 0x0100 /* Full duplex */ #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ /* Basic mode status register. */ #define BMSR_ERCAP 0x0001 /* Ext-reg capability */ #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ #define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ /* Advertisement control register. */ #define ADVERTISE_CSMA 0x0001 /* Only selector supported */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ ADVERTISE_100HALF | ADVERTISE_100FULL) /* Expansion register for auto-negotiation. */ #define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */ #endif /*****************************************************************************/ /* 2.4.6 => 2.4.3 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) ) #ifndef pci_set_power_state #define pci_set_power_state _kc_pci_set_power_state extern int _kc_pci_set_power_state(struct pci_dev *dev, int state); #endif #ifndef pci_enable_wake #define pci_enable_wake _kc_pci_enable_wake extern int _kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable); #endif #ifndef pci_disable_device #define pci_disable_device _kc_pci_disable_device extern void _kc_pci_disable_device(struct pci_dev *pdev); #endif /* PCI PM entry point syntax changed, so don't support suspend/resume */ #undef CONFIG_PM #endif /* 2.4.6 => 2.4.3 */ #ifndef HAVE_PCI_SET_MWI #define pci_set_mwi(X) pci_write_config_word(X, \ PCI_COMMAND, adapter->hw.bus.pci_cmd_word | \ PCI_COMMAND_INVALIDATE); #define pci_clear_mwi(X) pci_write_config_word(X, \ PCI_COMMAND, adapter->hw.bus.pci_cmd_word & \ ~PCI_COMMAND_INVALIDATE); #endif /*****************************************************************************/ /* 2.4.10 => 2.4.9 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10) ) /**************************************/ /* MODULE API */ #ifndef MODULE_LICENSE #define MODULE_LICENSE(X) #endif /**************************************/ /* OTHER */ #undef min #define min(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? _x : _y; }) #undef max #define max(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? _x : _y; }) #define min_t(type,x,y) ({ \ type _x = (x); \ type _y = (y); \ _x < _y ? _x : _y; }) #define max_t(type,x,y) ({ \ type _x = (x); \ type _y = (y); \ _x > _y ? _x : _y; }) #ifndef list_for_each_safe #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) #endif #ifndef ____cacheline_aligned_in_smp #ifdef CONFIG_SMP #define ____cacheline_aligned_in_smp ____cacheline_aligned #else #define ____cacheline_aligned_in_smp #endif /* CONFIG_SMP */ #endif #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) ) extern int _kc_snprintf(char * buf, size_t size, const char *fmt, ...); #define snprintf(buf, size, fmt, args...) _kc_snprintf(buf, size, fmt, ##args) extern int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args); #define vsnprintf(buf, size, fmt, args) _kc_vsnprintf(buf, size, fmt, args) #else /* 2.4.8 => 2.4.9 */ extern int snprintf(char * buf, size_t size, const char *fmt, ...); extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); #endif #endif /* 2.4.10 -> 2.4.6 */ /*****************************************************************************/ /* 2.4.12 => 2.4.10 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,12) ) #ifndef HAVE_NETIF_MSG #define HAVE_NETIF_MSG 1 enum { NETIF_MSG_DRV = 0x0001, NETIF_MSG_PROBE = 0x0002, NETIF_MSG_LINK = 0x0004, NETIF_MSG_TIMER = 0x0008, NETIF_MSG_IFDOWN = 0x0010, NETIF_MSG_IFUP = 0x0020, NETIF_MSG_RX_ERR = 0x0040, NETIF_MSG_TX_ERR = 0x0080, NETIF_MSG_TX_QUEUED = 0x0100, NETIF_MSG_INTR = 0x0200, NETIF_MSG_TX_DONE = 0x0400, NETIF_MSG_RX_STATUS = 0x0800, NETIF_MSG_PKTDATA = 0x1000, NETIF_MSG_HW = 0x2000, NETIF_MSG_WOL = 0x4000, }; #define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV) #define netif_msg_probe(p) ((p)->msg_enable & NETIF_MSG_PROBE) #define netif_msg_link(p) ((p)->msg_enable & NETIF_MSG_LINK) #define netif_msg_timer(p) ((p)->msg_enable & NETIF_MSG_TIMER) #define netif_msg_ifdown(p) ((p)->msg_enable & NETIF_MSG_IFDOWN) #define netif_msg_ifup(p) ((p)->msg_enable & NETIF_MSG_IFUP) #define netif_msg_rx_err(p) ((p)->msg_enable & NETIF_MSG_RX_ERR) #define netif_msg_tx_err(p) ((p)->msg_enable & NETIF_MSG_TX_ERR) #define netif_msg_tx_queued(p) ((p)->msg_enable & NETIF_MSG_TX_QUEUED) #define netif_msg_intr(p) ((p)->msg_enable & NETIF_MSG_INTR) #define netif_msg_tx_done(p) ((p)->msg_enable & NETIF_MSG_TX_DONE) #define netif_msg_rx_status(p) ((p)->msg_enable & NETIF_MSG_RX_STATUS) #define netif_msg_pktdata(p) ((p)->msg_enable & NETIF_MSG_PKTDATA) #endif /* !HAVE_NETIF_MSG */ #endif /* 2.4.12 => 2.4.10 */ /*****************************************************************************/ /* 2.4.13 => 2.4.12 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) ) /**************************************/ /* PCI DMA MAPPING */ #ifndef virt_to_page #define virt_to_page(v) (mem_map + (virt_to_phys(v) >> PAGE_SHIFT)) #endif #ifndef pci_map_page #define pci_map_page _kc_pci_map_page extern u64 _kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset, size_t size, int direction); #endif #ifndef pci_unmap_page #define pci_unmap_page _kc_pci_unmap_page extern void _kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size, int direction); #endif /* pci_set_dma_mask takes dma_addr_t, which is only 32-bits prior to 2.4.13 */ #undef DMA_32BIT_MASK #define DMA_32BIT_MASK 0xffffffff #undef DMA_64BIT_MASK #define DMA_64BIT_MASK 0xffffffff /**************************************/ /* OTHER */ #ifndef cpu_relax #define cpu_relax() rep_nop() #endif struct vlan_ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; unsigned short h_vlan_proto; unsigned short h_vlan_TCI; unsigned short h_vlan_encapsulated_proto; }; #endif /* 2.4.13 => 2.4.12 */ /*****************************************************************************/ /* 2.4.17 => 2.4.12 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,17) ) #ifndef __devexit_p #define __devexit_p(x) &(x) #endif #endif /* 2.4.17 => 2.4.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) ) #define NETIF_MSG_HW 0x2000 #define NETIF_MSG_WOL 0x4000 #ifndef netif_msg_hw #define netif_msg_hw(p) ((p)->msg_enable & NETIF_MSG_HW) #endif #ifndef netif_msg_wol #define netif_msg_wol(p) ((p)->msg_enable & NETIF_MSG_WOL) #endif #endif /* 2.4.18 */ /*****************************************************************************/ /*****************************************************************************/ /* 2.4.20 => 2.4.19 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20) ) /* we won't support NAPI on less than 2.4.20 */ #ifdef NAPI #undef NAPI #undef CONFIG_IXGBE_NAPI #endif #endif /* 2.4.20 => 2.4.19 */ /*****************************************************************************/ /* 2.4.22 => 2.4.17 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) #define pci_name(x) ((x)->slot_name) #endif /*****************************************************************************/ /* 2.4.22 => 2.4.17 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) #ifndef IXGBE_NO_LRO /* Don't enable LRO for these legacy kernels */ #define IXGBE_NO_LRO #endif #endif /*****************************************************************************/ /*****************************************************************************/ /* 2.4.23 => 2.4.22 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) ) /*****************************************************************************/ #ifdef NAPI #ifndef netif_poll_disable #define netif_poll_disable(x) _kc_netif_poll_disable(x) static inline void _kc_netif_poll_disable(struct net_device *netdev) { while (test_and_set_bit(__LINK_STATE_RX_SCHED, &netdev->state)) { /* No hurry */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } } #endif #ifndef netif_poll_enable #define netif_poll_enable(x) _kc_netif_poll_enable(x) static inline void _kc_netif_poll_enable(struct net_device *netdev) { clear_bit(__LINK_STATE_RX_SCHED, &netdev->state); } #endif #endif /* NAPI */ #ifndef netif_tx_disable #define netif_tx_disable(x) _kc_netif_tx_disable(x) static inline void _kc_netif_tx_disable(struct net_device *dev) { spin_lock_bh(&dev->xmit_lock); netif_stop_queue(dev); spin_unlock_bh(&dev->xmit_lock); } #endif #else /* 2.4.23 => 2.4.22 */ #define HAVE_SCTP #endif /* 2.4.23 => 2.4.22 */ /*****************************************************************************/ /* 2.6.4 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) || \ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) ) #define ETHTOOL_OPS_COMPAT #endif /* 2.6.4 => 2.6.0 */ /*****************************************************************************/ /* 2.5.71 => 2.4.x */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) ) #define sk_protocol protocol #define pci_get_device pci_find_device #endif /* 2.5.70 => 2.4.x */ /*****************************************************************************/ /* < 2.4.27 or 2.6.0 <= 2.6.5 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) || \ ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) ) #ifndef netif_msg_init #define netif_msg_init _kc_netif_msg_init static inline u32 _kc_netif_msg_init(int debug_value, int default_msg_enable_bits) { /* use default */ if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) return default_msg_enable_bits; if (debug_value == 0) /* no output */ return 0; /* set low N bits */ return (1 << debug_value) -1; } #endif #endif /* < 2.4.27 or 2.6.0 <= 2.6.5 */ /*****************************************************************************/ #if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) #define netdev_priv(x) x->priv #endif /*****************************************************************************/ /* <= 2.5.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) #include #undef pci_register_driver #define pci_register_driver pci_module_init /* * Most of the dma compat code is copied/modifed from the 2.4.37 * /include/linux/libata-compat.h header file */ /* These definitions mirror those in pci.h, so they can be used * interchangeably with their PCI_ counterparts */ enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, DMA_FROM_DEVICE = 2, DMA_NONE = 3, }; struct device { struct pci_dev pdev; }; static inline struct pci_dev *to_pci_dev (struct device *dev) { return (struct pci_dev *) dev; } static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { return (struct device *) pdev; } #define pdev_printk(lvl, pdev, fmt, args...) \ printk("%s %s: " fmt, lvl, pci_name(pdev), ## args) #define dev_err(dev, fmt, args...) \ pdev_printk(KERN_ERR, to_pci_dev(dev), fmt, ## args) #define dev_info(dev, fmt, args...) \ pdev_printk(KERN_INFO, to_pci_dev(dev), fmt, ## args) #define dev_warn(dev, fmt, args...) \ pdev_printk(KERN_WARNING, to_pci_dev(dev), fmt, ## args) /* NOTE: dangerous! we ignore the 'gfp' argument */ #define dma_alloc_coherent(dev,sz,dma,gfp) \ pci_alloc_consistent(to_pci_dev(dev),(sz),(dma)) #define dma_free_coherent(dev,sz,addr,dma_addr) \ pci_free_consistent(to_pci_dev(dev),(sz),(addr),(dma_addr)) #define dma_map_page(dev,a,b,c,d) \ pci_map_page(to_pci_dev(dev),(a),(b),(c),(d)) #define dma_unmap_page(dev,a,b,c) \ pci_unmap_page(to_pci_dev(dev),(a),(b),(c)) #define dma_map_single(dev,a,b,c) \ pci_map_single(to_pci_dev(dev),(a),(b),(c)) #define dma_unmap_single(dev,a,b,c) \ pci_unmap_single(to_pci_dev(dev),(a),(b),(c)) #define dma_sync_single(dev,a,b,c) \ pci_dma_sync_single(to_pci_dev(dev),(a),(b),(c)) /* for range just sync everything, that's all the pci API can do */ #define dma_sync_single_range(dev,addr,off,sz,dir) \ pci_dma_sync_single(to_pci_dev(dev),(addr),(off)+(sz),(dir)) #define dma_set_mask(dev,mask) \ pci_set_dma_mask(to_pci_dev(dev),(mask)) /* hlist_* code - double linked lists */ struct hlist_head { struct hlist_node *first; }; struct hlist_node { struct hlist_node *next, **pprev; }; static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; if (next) next->pprev = pprev; } static inline void hlist_del(struct hlist_node *n) { __hlist_del(n); n->next = NULL; n->pprev = NULL; } static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; if (first) first->pprev = &n->next; h->first = n; n->pprev = &h->first; } static inline int hlist_empty(const struct hlist_head *h) { return !h->first; } #define HLIST_HEAD_INIT { .first = NULL } #define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) static inline void INIT_HLIST_NODE(struct hlist_node *h) { h->next = NULL; h->pprev = NULL; } #define hlist_entry(ptr, type, member) container_of(ptr,type,member) #define hlist_for_each_entry(tpos, pos, head, member) \ for (pos = (head)->first; \ pos && ({ prefetch(pos->next); 1;}) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = pos->next) #define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ for (pos = (head)->first; \ pos && ({ n = pos->next; 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = n) #ifndef might_sleep #define might_sleep() #endif #else static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { return &pdev->dev; } #endif /* <= 2.5.0 */ /*****************************************************************************/ /* 2.5.28 => 2.4.23 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) static inline void _kc_synchronize_irq(void) { synchronize_irq(); } #undef synchronize_irq #define synchronize_irq(X) _kc_synchronize_irq() #include #define work_struct tq_struct #undef INIT_WORK #define INIT_WORK(a,b) INIT_TQUEUE(a,(void (*)(void *))b,a) #undef container_of #define container_of list_entry #define schedule_work schedule_task #define flush_scheduled_work flush_scheduled_tasks #define cancel_work_sync(x) flush_scheduled_work() #endif /* 2.5.28 => 2.4.17 */ /*****************************************************************************/ /* 2.6.0 => 2.5.28 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) #undef get_cpu #define get_cpu() smp_processor_id() #undef put_cpu #define put_cpu() do { } while(0) #define MODULE_INFO(version, _version) #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT #define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 #endif #define CONFIG_IGB_DISABLE_PACKET_SPLIT 1 #define dma_set_coherent_mask(dev,mask) 1 #undef dev_put #define dev_put(dev) __dev_put(dev) #ifndef skb_fill_page_desc #define skb_fill_page_desc _kc_skb_fill_page_desc extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); #endif #undef ALIGN #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) #ifndef page_count #define page_count(p) atomic_read(&(p)->count) #endif #ifdef MAX_NUMNODES #undef MAX_NUMNODES #endif #define MAX_NUMNODES 1 /* find_first_bit and find_next bit are not defined for most * 2.4 kernels (except for the redhat 2.4.21 kernels */ #include #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) #undef find_next_bit #define find_next_bit _kc_find_next_bit extern unsigned long _kc_find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) #ifndef netdev_name static inline const char *_kc_netdev_name(const struct net_device *dev) { if (strchr(dev->name, '%')) return "(unregistered net_device)"; return dev->name; } #define netdev_name(netdev) _kc_netdev_name(netdev) #endif /* netdev_name */ #ifndef strlcpy #define strlcpy _kc_strlcpy extern size_t _kc_strlcpy(char *dest, const char *src, size_t size); #endif /* strlcpy */ #endif /* 2.6.0 => 2.5.28 */ /*****************************************************************************/ /* 2.6.4 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) #define MODULE_VERSION(_version) MODULE_INFO(version, _version) #endif /* 2.6.4 => 2.6.0 */ /*****************************************************************************/ /* 2.6.5 => 2.6.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) #define dma_sync_single_for_cpu dma_sync_single #define dma_sync_single_for_device dma_sync_single #define dma_sync_single_range_for_cpu dma_sync_single_range #define dma_sync_single_range_for_device dma_sync_single_range #ifndef pci_dma_mapping_error #define pci_dma_mapping_error _kc_pci_dma_mapping_error static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) { return dma_addr == 0; } #endif #endif /* 2.6.5 => 2.6.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) extern int _kc_scnprintf(char * buf, size_t size, const char *fmt, ...); #define scnprintf(buf, size, fmt, args...) _kc_scnprintf(buf, size, fmt, ##args) #endif /* < 2.6.4 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6) ) /* taken from 2.6 include/linux/bitmap.h */ #undef bitmap_zero #define bitmap_zero _kc_bitmap_zero static inline void _kc_bitmap_zero(unsigned long *dst, int nbits) { if (nbits <= BITS_PER_LONG) *dst = 0UL; else { int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); memset(dst, 0, len); } } #define random_ether_addr _kc_random_ether_addr static inline void _kc_random_ether_addr(u8 *addr) { get_random_bytes(addr, ETH_ALEN); addr[0] &= 0xfe; /* clear multicast */ addr[0] |= 0x02; /* set local assignment */ } #define page_to_nid(x) 0 #endif /* < 2.6.6 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) ) #undef if_mii #define if_mii _kc_if_mii static inline struct mii_ioctl_data *_kc_if_mii(struct ifreq *rq) { return (struct mii_ioctl_data *) &rq->ifr_ifru; } #ifndef __force #define __force #endif #endif /* < 2.6.7 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) ) #ifndef PCI_EXP_DEVCTL #define PCI_EXP_DEVCTL 8 #endif #ifndef PCI_EXP_DEVCTL_CERE #define PCI_EXP_DEVCTL_CERE 0x0001 #endif #define msleep(x) do { set_current_state(TASK_UNINTERRUPTIBLE); \ schedule_timeout((x * HZ)/1000 + 2); \ } while (0) #endif /* < 2.6.8 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) #include #define __iomem #ifndef kcalloc #define kcalloc(n, size, flags) _kc_kzalloc(((n) * (size)), flags) extern void *_kc_kzalloc(size_t size, int flags); #endif #define MSEC_PER_SEC 1000L static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) { #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) return (MSEC_PER_SEC / HZ) * j; #elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); #else return (j * MSEC_PER_SEC) / HZ; #endif } static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) { if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) return MAX_JIFFY_OFFSET; #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); #elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) return m * (HZ / MSEC_PER_SEC); #else return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; #endif } #define msleep_interruptible _kc_msleep_interruptible static inline unsigned long _kc_msleep_interruptible(unsigned int msecs) { unsigned long timeout = _kc_msecs_to_jiffies(msecs) + 1; while (timeout && !signal_pending(current)) { __set_current_state(TASK_INTERRUPTIBLE); timeout = schedule_timeout(timeout); } return _kc_jiffies_to_msecs(timeout); } /* Basic mode control register. */ #define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */ #ifndef __le16 #define __le16 u16 #endif #ifndef __le32 #define __le32 u32 #endif #ifndef __le64 #define __le64 u64 #endif #ifndef __be16 #define __be16 u16 #endif #ifndef __be32 #define __be32 u32 #endif #ifndef __be64 #define __be64 u64 #endif static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) { return (struct vlan_ethhdr *)skb->mac.raw; } /* Wake-On-Lan options. */ #define WAKE_PHY (1 << 0) #define WAKE_UCAST (1 << 1) #define WAKE_MCAST (1 << 2) #define WAKE_BCAST (1 << 3) #define WAKE_ARP (1 << 4) #define WAKE_MAGIC (1 << 5) #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ #define skb_header_pointer _kc_skb_header_pointer static inline void *_kc_skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) { int hlen = skb_headlen(skb); if (hlen - offset >= len) return skb->data + offset; #ifdef MAX_SKB_FRAGS if (skb_copy_bits(skb, offset, buffer, len) < 0) return NULL; return buffer; #else return NULL; #endif #ifndef NETDEV_TX_OK #define NETDEV_TX_OK 0 #endif #ifndef NETDEV_TX_BUSY #define NETDEV_TX_BUSY 1 #endif #ifndef NETDEV_TX_LOCKED #define NETDEV_TX_LOCKED -1 #endif } #ifndef __bitwise #define __bitwise #endif #endif /* < 2.6.9 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) ) #ifdef module_param_array_named #undef module_param_array_named #define module_param_array_named(name, array, type, nump, perm) \ static struct kparam_array __param_arr_##name \ = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type, \ sizeof(array[0]), array }; \ module_param_call(name, param_array_set, param_array_get, \ &__param_arr_##name, perm) #endif /* module_param_array_named */ /* * num_online is broken for all < 2.6.10 kernels. This is needed to support * Node module parameter of ixgbe. */ #undef num_online_nodes #define num_online_nodes(n) 1 extern DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES); #undef node_online_map #define node_online_map _kcompat_node_online_map #endif /* < 2.6.10 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ) #define PCI_D0 0 #define PCI_D1 1 #define PCI_D2 2 #define PCI_D3hot 3 #define PCI_D3cold 4 typedef int pci_power_t; #define pci_choose_state(pdev,state) state #define PMSG_SUSPEND 3 #define PCI_EXP_LNKCTL 16 #undef NETIF_F_LLTX #ifndef ARCH_HAS_PREFETCH #define prefetch(X) #endif #ifndef NET_IP_ALIGN #define NET_IP_ALIGN 2 #endif #define KC_USEC_PER_SEC 1000000L #define usecs_to_jiffies _kc_usecs_to_jiffies static inline unsigned int _kc_jiffies_to_usecs(const unsigned long j) { #if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) return (KC_USEC_PER_SEC / HZ) * j; #elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) return (j + (HZ / KC_USEC_PER_SEC) - 1)/(HZ / KC_USEC_PER_SEC); #else return (j * KC_USEC_PER_SEC) / HZ; #endif } static inline unsigned long _kc_usecs_to_jiffies(const unsigned int m) { if (m > _kc_jiffies_to_usecs(MAX_JIFFY_OFFSET)) return MAX_JIFFY_OFFSET; #if HZ <= KC_USEC_PER_SEC && !(KC_USEC_PER_SEC % HZ) return (m + (KC_USEC_PER_SEC / HZ) - 1) / (KC_USEC_PER_SEC / HZ); #elif HZ > KC_USEC_PER_SEC && !(HZ % KC_USEC_PER_SEC) return m * (HZ / KC_USEC_PER_SEC); #else return (m * HZ + KC_USEC_PER_SEC - 1) / KC_USEC_PER_SEC; #endif } #endif /* < 2.6.11 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) ) #include #define USE_REBOOT_NOTIFIER /* Generic MII registers. */ #define MII_CTRL1000 0x09 /* 1000BASE-T control */ #define MII_STAT1000 0x0a /* 1000BASE-T status */ /* Advertisement control register. */ #define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */ #define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymmetric pause */ /* 1000BASE-T Control register */ #define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */ #ifndef is_zero_ether_addr #define is_zero_ether_addr _kc_is_zero_ether_addr static inline int _kc_is_zero_ether_addr(const u8 *addr) { return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]); } #endif /* is_zero_ether_addr */ #ifndef is_multicast_ether_addr #define is_multicast_ether_addr _kc_is_multicast_ether_addr static inline int _kc_is_multicast_ether_addr(const u8 *addr) { return addr[0] & 0x01; } #endif /* is_multicast_ether_addr */ #endif /* < 2.6.12 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) ) #ifndef kstrdup #define kstrdup _kc_kstrdup extern char *_kc_kstrdup(const char *s, unsigned int gfp); #endif #endif /* < 2.6.13 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ) #define pm_message_t u32 #ifndef kzalloc #define kzalloc _kc_kzalloc extern void *_kc_kzalloc(size_t size, int flags); #endif /* Generic MII registers. */ #define MII_ESTATUS 0x0f /* Extended Status */ /* Basic mode status register. */ #define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */ /* Extended status register. */ #define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */ #define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */ #define ADVERTISED_Pause (1 << 13) #define ADVERTISED_Asym_Pause (1 << 14) #if (!(RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,3)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0)))) #if ((LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9)) && !defined(gfp_t)) #define gfp_t unsigned #else typedef unsigned gfp_t; #endif #endif /* !RHEL4.3->RHEL5.0 */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) ) #ifdef CONFIG_X86_64 #define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir) \ dma_sync_single_for_cpu(dev, dma_handle, size, dir) #define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir) \ dma_sync_single_for_device(dev, dma_handle, size, dir) #endif #endif #endif /* < 2.6.14 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) ) #ifndef vmalloc_node #define vmalloc_node(a,b) vmalloc(a) #endif /* vmalloc_node*/ #define setup_timer(_timer, _function, _data) \ do { \ (_timer)->function = _function; \ (_timer)->data = _data; \ init_timer(_timer); \ } while (0) #ifndef device_can_wakeup #define device_can_wakeup(dev) (1) #endif #ifndef device_set_wakeup_enable #define device_set_wakeup_enable(dev, val) do{}while(0) #endif #ifndef device_init_wakeup #define device_init_wakeup(dev,val) do {} while (0) #endif static inline unsigned _kc_compare_ether_addr(const u8 *addr1, const u8 *addr2) { const u16 *a = (const u16 *) addr1; const u16 *b = (const u16 *) addr2; return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; } #undef compare_ether_addr #define compare_ether_addr(addr1, addr2) _kc_compare_ether_addr(addr1, addr2) #endif /* < 2.6.15 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) ) #undef DEFINE_MUTEX #define DEFINE_MUTEX(x) DECLARE_MUTEX(x) #define mutex_lock(x) down_interruptible(x) #define mutex_unlock(x) up(x) #ifndef ____cacheline_internodealigned_in_smp #ifdef CONFIG_SMP #define ____cacheline_internodealigned_in_smp ____cacheline_aligned_in_smp #else #define ____cacheline_internodealigned_in_smp #endif /* CONFIG_SMP */ #endif /* ____cacheline_internodealigned_in_smp */ #undef HAVE_PCI_ERS #else /* 2.6.16 and above */ #undef HAVE_PCI_ERS #define HAVE_PCI_ERS #endif /* < 2.6.16 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) ) #ifndef first_online_node #define first_online_node 0 #endif #ifndef NET_SKB_PAD #define NET_SKB_PAD 16 #endif #endif /* < 2.6.17 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ) #ifndef IRQ_HANDLED #define irqreturn_t void #define IRQ_HANDLED #define IRQ_NONE #endif #ifndef IRQF_PROBE_SHARED #ifdef SA_PROBEIRQ #define IRQF_PROBE_SHARED SA_PROBEIRQ #else #define IRQF_PROBE_SHARED 0 #endif #endif #ifndef IRQF_SHARED #define IRQF_SHARED SA_SHIRQ #endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #ifndef FIELD_SIZEOF #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #endif #ifndef skb_is_gso #ifdef NETIF_F_TSO #define skb_is_gso _kc_skb_is_gso static inline int _kc_skb_is_gso(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_size; } #else #define skb_is_gso(a) 0 #endif #endif #ifndef resource_size_t #define resource_size_t unsigned long #endif #ifdef skb_pad #undef skb_pad #endif #define skb_pad(x,y) _kc_skb_pad(x, y) int _kc_skb_pad(struct sk_buff *skb, int pad); #ifdef skb_padto #undef skb_padto #endif #define skb_padto(x,y) _kc_skb_padto(x, y) static inline int _kc_skb_padto(struct sk_buff *skb, unsigned int len) { unsigned int size = skb->len; if(likely(size >= len)) return 0; return _kc_skb_pad(skb, len - size); } #ifndef DECLARE_PCI_UNMAP_ADDR #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ u32 LEN_NAME #define pci_unmap_addr(PTR, ADDR_NAME) \ ((PTR)->ADDR_NAME) #define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ (((PTR)->ADDR_NAME) = (VAL)) #define pci_unmap_len(PTR, LEN_NAME) \ ((PTR)->LEN_NAME) #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ (((PTR)->LEN_NAME) = (VAL)) #endif /* DECLARE_PCI_UNMAP_ADDR */ #endif /* < 2.6.18 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ) #ifndef DIV_ROUND_UP #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #endif #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) #if (!((RHEL_RELEASE_CODE && \ ((RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(4,4) && \ RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0)) || \ (RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,0)))) || \ (AX_RELEASE_CODE && AX_RELEASE_CODE > AX_RELEASE_VERSION(3,0)))) typedef irqreturn_t (*irq_handler_t)(int, void*, struct pt_regs *); #endif #if (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6,0)) #undef CONFIG_INET_LRO #undef CONFIG_INET_LRO_MODULE #undef CONFIG_FCOE #undef CONFIG_FCOE_MODULE #endif typedef irqreturn_t (*new_handler_t)(int, void*); static inline irqreturn_t _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) #else /* 2.4.x */ typedef void (*irq_handler_t)(int, void*, struct pt_regs *); typedef void (*new_handler_t)(int, void*); static inline int _kc_request_irq(unsigned int irq, new_handler_t handler, unsigned long flags, const char *devname, void *dev_id) #endif /* >= 2.5.x */ { irq_handler_t new_handler = (irq_handler_t) handler; return request_irq(irq, new_handler, flags, devname, dev_id); } #undef request_irq #define request_irq(irq, handler, flags, devname, dev_id) _kc_request_irq((irq), (handler), (flags), (devname), (dev_id)) #define irq_handler_t new_handler_t /* pci_restore_state and pci_save_state handles MSI/PCIE from 2.6.19 */ #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4))) #define PCIE_CONFIG_SPACE_LEN 256 #define PCI_CONFIG_SPACE_LEN 64 #define PCIE_LINK_STATUS 0x12 #define pci_config_space_ich8lan() do {} while(0) #undef pci_save_state extern int _kc_pci_save_state(struct pci_dev *); #define pci_save_state(pdev) _kc_pci_save_state(pdev) #undef pci_restore_state extern void _kc_pci_restore_state(struct pci_dev *); #define pci_restore_state(pdev) _kc_pci_restore_state(pdev) #endif /* !(RHEL_RELEASE_CODE >= RHEL 5.4) */ #ifdef HAVE_PCI_ERS #undef free_netdev extern void _kc_free_netdev(struct net_device *); #define free_netdev(netdev) _kc_free_netdev(netdev) #endif static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) { return 0; } #define pci_disable_pcie_error_reporting(dev) do {} while (0) #define pci_cleanup_aer_uncorrect_error_status(dev) do {} while (0) extern void *_kc_kmemdup(const void *src, size_t len, unsigned gfp); #define kmemdup(src, len, gfp) _kc_kmemdup(src, len, gfp) #ifndef bool #define bool _Bool #define true 1 #define false 0 #endif #else /* 2.6.19 */ #include #include #endif /* < 2.6.19 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) ) #undef INIT_WORK #define INIT_WORK(_work, _func) \ do { \ INIT_LIST_HEAD(&(_work)->entry); \ (_work)->pending = 0; \ (_work)->func = (void (*)(void *))_func; \ (_work)->data = _work; \ init_timer(&(_work)->timer); \ } while (0) #endif #ifndef PCI_VDEVICE #define PCI_VDEVICE(ven, dev) \ PCI_VENDOR_ID_##ven, (dev), \ PCI_ANY_ID, PCI_ANY_ID, 0, 0 #endif #ifndef round_jiffies #define round_jiffies(x) x #endif #define csum_offset csum #define HAVE_EARLY_VMALLOC_NODE #define dev_to_node(dev) -1 #undef set_dev_node /* remove compiler warning with b=b, for unused variable */ #define set_dev_node(a, b) do { (b) = (b); } while(0) #if (!(RHEL_RELEASE_CODE && \ (((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(4,7)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0))) || \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,6)))) && \ !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(10,2,0))) typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __wsum; #endif #if (!(RHEL_RELEASE_CODE && \ (((RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(4,7)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,0))) || \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4)))) && \ !(SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(10,2,0))) static inline __wsum csum_unfold(__sum16 n) { return (__force __wsum)n; } #endif #else /* < 2.6.20 */ #define HAVE_DEVICE_NUMA_NODE #endif /* < 2.6.20 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) #define to_net_dev(class) container_of(class, struct net_device, class_dev) #define NETDEV_CLASS_DEV #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5))) #define vlan_group_get_device(vg, id) (vg->vlan_devices[id]) #define vlan_group_set_device(vg, id, dev) \ do { \ if (vg) vg->vlan_devices[id] = dev; \ } while (0) #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,5)) */ #define pci_channel_offline(pdev) (pdev->error_state && \ pdev->error_state != pci_channel_io_normal) #define pci_request_selected_regions(pdev, bars, name) \ pci_request_regions(pdev, name) #define pci_release_selected_regions(pdev, bars) pci_release_regions(pdev); #endif /* < 2.6.21 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) #define tcp_hdr(skb) (skb->h.th) #define tcp_hdrlen(skb) (skb->h.th->doff << 2) #define skb_transport_offset(skb) (skb->h.raw - skb->data) #define skb_transport_header(skb) (skb->h.raw) #define ipv6_hdr(skb) (skb->nh.ipv6h) #define ip_hdr(skb) (skb->nh.iph) #define skb_network_offset(skb) (skb->nh.raw - skb->data) #define skb_network_header(skb) (skb->nh.raw) #define skb_tail_pointer(skb) skb->tail #define skb_reset_tail_pointer(skb) \ do { \ skb->tail = skb->data; \ } while (0) #define skb_copy_to_linear_data(skb, from, len) \ memcpy(skb->data, from, len) #define skb_copy_to_linear_data_offset(skb, offset, from, len) \ memcpy(skb->data + offset, from, len) #define skb_network_header_len(skb) (skb->h.raw - skb->nh.raw) #define pci_register_driver pci_module_init #define skb_mac_header(skb) skb->mac.raw #ifdef NETIF_F_MULTI_QUEUE #ifndef alloc_etherdev_mq #define alloc_etherdev_mq(_a, _b) alloc_etherdev(_a) #endif #endif /* NETIF_F_MULTI_QUEUE */ #ifndef ETH_FCS_LEN #define ETH_FCS_LEN 4 #endif #define cancel_work_sync(x) flush_scheduled_work() #ifndef udp_hdr #define udp_hdr _udp_hdr static inline struct udphdr *_udp_hdr(const struct sk_buff *skb) { return (struct udphdr *)skb_transport_header(skb); } #endif #ifdef cpu_to_be16 #undef cpu_to_be16 #endif #define cpu_to_be16(x) __constant_htons(x) #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,1))) enum { DUMP_PREFIX_NONE, DUMP_PREFIX_ADDRESS, DUMP_PREFIX_OFFSET }; #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(5,1)) */ #ifndef hex_asc #define hex_asc(x) "0123456789abcdef"[x] #endif #include extern void _kc_print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii); #define print_hex_dump(lvl, s, t, r, g, b, l, a) \ _kc_print_hex_dump(lvl, s, t, r, g, b, l, a) #else /* 2.6.22 */ #define ETH_TYPE_TRANS_SETS_DEV #define HAVE_NETDEV_STATS_IN_NETDEV #endif /* < 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) ) #endif /* > 2.6.22 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) ) #define netif_subqueue_stopped(_a, _b) 0 #ifndef PTR_ALIGN #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) #endif #ifndef CONFIG_PM_SLEEP #define CONFIG_PM_SLEEP CONFIG_PM #endif #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) ) #define HAVE_ETHTOOL_GET_PERM_ADDR #endif /* 2.6.14 through 2.6.22 */ #endif /* < 2.6.23 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ) #ifndef ETH_FLAG_LRO #define ETH_FLAG_LRO NETIF_F_LRO #endif /* if GRO is supported then the napi struct must already exist */ #ifndef NETIF_F_GRO /* NAPI API changes in 2.6.24 break everything */ struct napi_struct { /* used to look up the real NAPI polling routine */ int (*poll)(struct napi_struct *, int); struct net_device *dev; int weight; }; #endif #ifdef NAPI extern int __kc_adapter_clean(struct net_device *, int *); extern struct net_device *napi_to_poll_dev(struct napi_struct *napi); #define netif_napi_add(_netdev, _napi, _poll, _weight) \ do { \ struct napi_struct *__napi = (_napi); \ struct net_device *poll_dev = napi_to_poll_dev(__napi); \ poll_dev->poll = &(__kc_adapter_clean); \ poll_dev->priv = (_napi); \ poll_dev->weight = (_weight); \ set_bit(__LINK_STATE_RX_SCHED, &poll_dev->state); \ set_bit(__LINK_STATE_START, &poll_dev->state);\ dev_hold(poll_dev); \ __napi->poll = &(_poll); \ __napi->weight = (_weight); \ __napi->dev = (_netdev); \ } while (0) #define netif_napi_del(_napi) \ do { \ struct net_device *poll_dev = napi_to_poll_dev(_napi); \ WARN_ON(!test_bit(__LINK_STATE_RX_SCHED, &poll_dev->state)); \ dev_put(poll_dev); \ memset(poll_dev, 0, sizeof(struct net_device));\ } while (0) #define napi_schedule_prep(_napi) \ (netif_running((_napi)->dev) && netif_rx_schedule_prep(napi_to_poll_dev(_napi))) #define napi_schedule(_napi) \ do { \ if (napi_schedule_prep(_napi)) \ __netif_rx_schedule(napi_to_poll_dev(_napi)); \ } while (0) #define napi_enable(_napi) netif_poll_enable(napi_to_poll_dev(_napi)) #define napi_disable(_napi) netif_poll_disable(napi_to_poll_dev(_napi)) #define __napi_schedule(_napi) __netif_rx_schedule(napi_to_poll_dev(_napi)) #ifndef NETIF_F_GRO #define napi_complete(_napi) netif_rx_complete(napi_to_poll_dev(_napi)) #else #define napi_complete(_napi) \ do { \ napi_gro_flush(_napi); \ netif_rx_complete(napi_to_poll_dev(_napi)); \ } while (0) #endif /* NETIF_F_GRO */ #else /* NAPI */ #define netif_napi_add(_netdev, _napi, _poll, _weight) \ do { \ struct napi_struct *__napi = _napi; \ _netdev->poll = &(_poll); \ _netdev->weight = (_weight); \ __napi->poll = &(_poll); \ __napi->weight = (_weight); \ __napi->dev = (_netdev); \ } while (0) #define netif_napi_del(_a) do {} while (0) #endif /* NAPI */ #undef dev_get_by_name #define dev_get_by_name(_a, _b) dev_get_by_name(_b) #define __netif_subqueue_stopped(_a, _b) netif_subqueue_stopped(_a, _b) #ifndef DMA_BIT_MASK #define DMA_BIT_MASK(n) (((n) == 64) ? DMA_64BIT_MASK : ((1ULL<<(n))-1)) #endif #ifdef NETIF_F_TSO6 #define skb_is_gso_v6 _kc_skb_is_gso_v6 static inline int _kc_skb_is_gso_v6(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; } #endif /* NETIF_F_TSO6 */ #ifndef KERN_CONT #define KERN_CONT "" #endif #else /* < 2.6.24 */ #define HAVE_ETHTOOL_GET_SSET_COUNT #define HAVE_NETDEV_NAPI_LIST #endif /* < 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24) ) #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ) #include #else /* >= 3.2.0 */ #include #endif /* else >= 3.2.0 */ #endif /* > 2.6.24 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ) #define PM_QOS_CPU_DMA_LATENCY 1 #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ) #include #define PM_QOS_DEFAULT_VALUE INFINITE_LATENCY #define pm_qos_add_requirement(pm_qos_class, name, value) \ set_acceptable_latency(name, value) #define pm_qos_remove_requirement(pm_qos_class, name) \ remove_acceptable_latency(name) #define pm_qos_update_requirement(pm_qos_class, name, value) \ modify_acceptable_latency(name, value) #else #define PM_QOS_DEFAULT_VALUE -1 #define pm_qos_add_requirement(pm_qos_class, name, value) #define pm_qos_remove_requirement(pm_qos_class, name) #define pm_qos_update_requirement(pm_qos_class, name, value) { \ if (value != PM_QOS_DEFAULT_VALUE) { \ printk(KERN_WARNING "%s: unable to set PM QoS requirement\n", \ pci_name(adapter->pdev)); \ } \ } #endif /* > 2.6.18 */ #define pci_enable_device_mem(pdev) pci_enable_device(pdev) #ifndef DEFINE_PCI_DEVICE_TABLE #define DEFINE_PCI_DEVICE_TABLE(_table) struct pci_device_id _table[] #endif /* DEFINE_PCI_DEVICE_TABLE */ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) #ifndef IXGBE_PROCFS #define IXGBE_PROCFS #endif /* IXGBE_PROCFS */ #endif /* >= 2.6.0 */ #else /* < 2.6.25 */ #ifndef IXGBE_SYSFS #define IXGBE_SYSFS #endif /* IXGBE_SYSFS */ #endif /* < 2.6.25 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ) #ifndef clamp_t #define clamp_t(type, val, min, max) ({ \ type __val = (val); \ type __min = (min); \ type __max = (max); \ __val = __val < __min ? __min : __val; \ __val > __max ? __max : __val; }) #endif /* clamp_t */ #ifdef NETIF_F_TSO #ifdef NETIF_F_TSO6 #define netif_set_gso_max_size(_netdev, size) \ do { \ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { \ _netdev->features &= ~NETIF_F_TSO; \ _netdev->features &= ~NETIF_F_TSO6; \ } else { \ _netdev->features |= NETIF_F_TSO; \ _netdev->features |= NETIF_F_TSO6; \ } \ } while (0) #else /* NETIF_F_TSO6 */ #define netif_set_gso_max_size(_netdev, size) \ do { \ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) \ _netdev->features &= ~NETIF_F_TSO; \ else \ _netdev->features |= NETIF_F_TSO; \ } while (0) #endif /* NETIF_F_TSO6 */ #else #define netif_set_gso_max_size(_netdev, size) do {} while (0) #endif /* NETIF_F_TSO */ #undef kzalloc_node #define kzalloc_node(_size, _flags, _node) kzalloc(_size, _flags) extern void _kc_pci_disable_link_state(struct pci_dev *dev, int state); #define pci_disable_link_state(p, s) _kc_pci_disable_link_state(p, s) #else /* < 2.6.26 */ #include #define HAVE_NETDEV_VLAN_FEATURES #endif /* < 2.6.26 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) ) static inline void _kc_ethtool_cmd_speed_set(struct ethtool_cmd *ep, __u32 speed) { ep->speed = (__u16)speed; /* ep->speed_hi = (__u16)(speed >> 16); */ } #define ethtool_cmd_speed_set _kc_ethtool_cmd_speed_set static inline __u32 _kc_ethtool_cmd_speed(struct ethtool_cmd *ep) { /* no speed_hi before 2.6.27, and probably no need for it yet */ return (__u32)ep->speed; } #define ethtool_cmd_speed _kc_ethtool_cmd_speed #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) ) #if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) && defined(CONFIG_PM)) #define ANCIENT_PM 1 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)) && \ (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)) && \ defined(CONFIG_PM_SLEEP)) #define NEWER_PM 1 #endif #if defined(ANCIENT_PM) || defined(NEWER_PM) #undef device_set_wakeup_enable #define device_set_wakeup_enable(dev, val) \ do { \ u16 pmc = 0; \ int pm = pci_find_capability(adapter->pdev, PCI_CAP_ID_PM); \ if (pm) { \ pci_read_config_word(adapter->pdev, pm + PCI_PM_PMC, \ &pmc); \ } \ (dev)->power.can_wakeup = !!(pmc >> 11); \ (dev)->power.should_wakeup = (val && (pmc >> 11)); \ } while (0) #endif /* 2.6.15-2.6.22 and CONFIG_PM or 2.6.23-2.6.25 and CONFIG_PM_SLEEP */ #endif /* 2.6.15 through 2.6.27 */ #ifndef netif_napi_del #define netif_napi_del(_a) do {} while (0) #ifdef NAPI #ifdef CONFIG_NETPOLL #undef netif_napi_del #define netif_napi_del(_a) list_del(&(_a)->dev_list); #endif #endif #endif /* netif_napi_del */ #ifdef dma_mapping_error #undef dma_mapping_error #endif #define dma_mapping_error(dev, dma_addr) pci_dma_mapping_error(dma_addr) #ifdef CONFIG_NETDEVICES_MULTIQUEUE #define HAVE_TX_MQ #endif #ifdef HAVE_TX_MQ extern void _kc_netif_tx_stop_all_queues(struct net_device *); extern void _kc_netif_tx_wake_all_queues(struct net_device *); extern void _kc_netif_tx_start_all_queues(struct net_device *); #define netif_tx_stop_all_queues(a) _kc_netif_tx_stop_all_queues(a) #define netif_tx_wake_all_queues(a) _kc_netif_tx_wake_all_queues(a) #define netif_tx_start_all_queues(a) _kc_netif_tx_start_all_queues(a) #undef netif_stop_subqueue #define netif_stop_subqueue(_ndev,_qi) do { \ if (netif_is_multiqueue((_ndev))) \ netif_stop_subqueue((_ndev), (_qi)); \ else \ netif_stop_queue((_ndev)); \ } while (0) #undef netif_start_subqueue #define netif_start_subqueue(_ndev,_qi) do { \ if (netif_is_multiqueue((_ndev))) \ netif_start_subqueue((_ndev), (_qi)); \ else \ netif_start_queue((_ndev)); \ } while (0) #else /* HAVE_TX_MQ */ #define netif_tx_stop_all_queues(a) netif_stop_queue(a) #define netif_tx_wake_all_queues(a) netif_wake_queue(a) #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) ) #define netif_tx_start_all_queues(a) netif_start_queue(a) #else #define netif_tx_start_all_queues(a) do {} while (0) #endif #define netif_stop_subqueue(_ndev,_qi) netif_stop_queue((_ndev)) #define netif_start_subqueue(_ndev,_qi) netif_start_queue((_ndev)) #endif /* HAVE_TX_MQ */ #ifndef NETIF_F_MULTI_QUEUE #define NETIF_F_MULTI_QUEUE 0 #define netif_is_multiqueue(a) 0 #define netif_wake_subqueue(a, b) #endif /* NETIF_F_MULTI_QUEUE */ #ifndef __WARN_printf extern void __kc_warn_slowpath(const char *file, const int line, const char *fmt, ...) __attribute__((format(printf, 3, 4))); #define __WARN_printf(arg...) __kc_warn_slowpath(__FILE__, __LINE__, arg) #endif /* __WARN_printf */ #ifndef WARN #define WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ __WARN_printf(format); \ unlikely(__ret_warn_on); \ }) #endif /* WARN */ #else /* < 2.6.27 */ #define HAVE_TX_MQ #define HAVE_NETDEV_SELECT_QUEUE #endif /* < 2.6.27 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ) #define pci_ioremap_bar(pdev, bar) ioremap(pci_resource_start(pdev, bar), \ pci_resource_len(pdev, bar)) #define pci_wake_from_d3 _kc_pci_wake_from_d3 #define pci_prepare_to_sleep _kc_pci_prepare_to_sleep extern int _kc_pci_wake_from_d3(struct pci_dev *dev, bool enable); extern int _kc_pci_prepare_to_sleep(struct pci_dev *dev); #define netdev_alloc_page(a) alloc_page(GFP_ATOMIC) #ifndef __skb_queue_head_init static inline void __kc_skb_queue_head_init(struct sk_buff_head *list) { list->prev = list->next = (struct sk_buff *)list; list->qlen = 0; } #define __skb_queue_head_init(_q) __kc_skb_queue_head_init(_q) #endif #endif /* < 2.6.28 */ #ifndef skb_add_rx_frag #define skb_add_rx_frag _kc_skb_add_rx_frag extern void _kc_skb_add_rx_frag(struct sk_buff *, int, struct page *, int, int); #endif /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ) #ifndef swap #define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) #endif #define pci_request_selected_regions_exclusive(pdev, bars, name) \ pci_request_selected_regions(pdev, bars, name) #ifndef CONFIG_NR_CPUS #define CONFIG_NR_CPUS 1 #endif /* CONFIG_NR_CPUS */ #ifndef pcie_aspm_enabled #define pcie_aspm_enabled() (1) #endif /* pcie_aspm_enabled */ #else /* < 2.6.29 */ #ifndef HAVE_NET_DEVICE_OPS #define HAVE_NET_DEVICE_OPS #endif #ifdef CONFIG_DCB #define HAVE_PFC_MODE_ENABLE #endif /* CONFIG_DCB */ #endif /* < 2.6.29 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ) #define skb_rx_queue_recorded(a) false #define skb_get_rx_queue(a) 0 #undef CONFIG_FCOE #undef CONFIG_FCOE_MODULE extern u16 _kc_skb_tx_hash(struct net_device *dev, struct sk_buff *skb); #define skb_tx_hash(n, s) _kc_skb_tx_hash(n, s) #define skb_record_rx_queue(a, b) do {} while (0) #ifndef CONFIG_PCI_IOV #undef pci_enable_sriov #define pci_enable_sriov(a, b) -ENOTSUPP #undef pci_disable_sriov #define pci_disable_sriov(a) do {} while (0) #endif /* CONFIG_PCI_IOV */ #ifndef pr_cont #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) #endif /* pr_cont */ #else #define HAVE_ASPM_QUIRKS #endif /* < 2.6.30 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) ) #define ETH_P_1588 0x88F7 #define ETH_P_FIP 0x8914 #ifndef netdev_uc_count #define netdev_uc_count(dev) ((dev)->uc_count) #endif #ifndef netdev_for_each_uc_addr #define netdev_for_each_uc_addr(uclist, dev) \ for (uclist = dev->uc_list; uclist; uclist = uclist->next) #endif #else #ifndef HAVE_NETDEV_STORAGE_ADDRESS #define HAVE_NETDEV_STORAGE_ADDRESS #endif #ifndef HAVE_NETDEV_HW_ADDR #define HAVE_NETDEV_HW_ADDR #endif #ifndef HAVE_TRANS_START_IN_QUEUE #define HAVE_TRANS_START_IN_QUEUE #endif #endif /* < 2.6.31 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) ) #undef netdev_tx_t #define netdev_tx_t int #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef NETIF_F_FCOE_MTU #define NETIF_F_FCOE_MTU (1 << 26) #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #ifndef pm_runtime_get_sync #define pm_runtime_get_sync(dev) do {} while (0) #endif #ifndef pm_runtime_put #define pm_runtime_put(dev) do {} while (0) #endif #ifndef pm_runtime_put_sync #define pm_runtime_put_sync(dev) do {} while (0) #endif #ifndef pm_runtime_resume #define pm_runtime_resume(dev) do {} while (0) #endif #ifndef pm_schedule_suspend #define pm_schedule_suspend(dev, t) do {} while (0) #endif #ifndef pm_runtime_set_suspended #define pm_runtime_set_suspended(dev) do {} while (0) #endif #ifndef pm_runtime_disable #define pm_runtime_disable(dev) do {} while (0) #endif #ifndef pm_runtime_put_noidle #define pm_runtime_put_noidle(dev) do {} while (0) #endif #ifndef pm_runtime_set_active #define pm_runtime_set_active(dev) do {} while (0) #endif #ifndef pm_runtime_enable #define pm_runtime_enable(dev) do {} while (0) #endif #ifndef pm_runtime_get_noresume #define pm_runtime_get_noresume(dev) do {} while (0) #endif #else /* < 2.6.32 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_ENABLE #define HAVE_NETDEV_OPS_FCOE_ENABLE #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #ifdef CONFIG_DCB #ifndef HAVE_DCBNL_OPS_GETAPP #define HAVE_DCBNL_OPS_GETAPP #endif #endif /* CONFIG_DCB */ #include /* IOV bad DMA target work arounds require at least this kernel rev support */ #define HAVE_PCIE_TYPE #endif /* < 2.6.32 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) ) #ifndef pci_pcie_cap #define pci_pcie_cap(pdev) pci_find_capability(pdev, PCI_CAP_ID_EXP) #endif #ifndef IPV4_FLOW #define IPV4_FLOW 0x10 #endif /* IPV4_FLOW */ #ifndef IPV6_FLOW #define IPV6_FLOW 0x11 #endif /* IPV6_FLOW */ /* Features back-ported to RHEL6 or SLES11 SP1 after 2.6.32 */ #if ( (RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,0)) || \ (SLE_VERSION_CODE && SLE_VERSION_CODE >= SLE_VERSION(11,1,0)) ) #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_GETWWN #define HAVE_NETDEV_OPS_FCOE_GETWWN #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #endif /* RHEL6 or SLES11 SP1 */ #ifndef __percpu #define __percpu #endif /* __percpu */ #else /* < 2.6.33 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_GETWWN #define HAVE_NETDEV_OPS_FCOE_GETWWN #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #define HAVE_ETHTOOL_SFP_DISPLAY_PORT #endif /* < 2.6.33 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) ) #ifndef ETH_FLAG_NTUPLE #define ETH_FLAG_NTUPLE NETIF_F_NTUPLE #endif #ifndef netdev_mc_count #define netdev_mc_count(dev) ((dev)->mc_count) #endif #ifndef netdev_mc_empty #define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) #endif #ifndef netdev_for_each_mc_addr #define netdev_for_each_mc_addr(mclist, dev) \ for (mclist = dev->mc_list; mclist; mclist = mclist->next) #endif #ifndef netdev_uc_count #define netdev_uc_count(dev) ((dev)->uc.count) #endif #ifndef netdev_uc_empty #define netdev_uc_empty(dev) (netdev_uc_count(dev) == 0) #endif #ifndef netdev_for_each_uc_addr #define netdev_for_each_uc_addr(ha, dev) \ list_for_each_entry(ha, &dev->uc.list, list) #endif #ifndef dma_set_coherent_mask #define dma_set_coherent_mask(dev,mask) \ pci_set_consistent_dma_mask(to_pci_dev(dev),(mask)) #endif #ifndef pci_dev_run_wake #define pci_dev_run_wake(pdev) (0) #endif /* netdev logging taken from include/linux/netdevice.h */ #ifndef netdev_name static inline const char *_kc_netdev_name(const struct net_device *dev) { if (dev->reg_state != NETREG_REGISTERED) return "(unregistered net_device)"; return dev->name; } #define netdev_name(netdev) _kc_netdev_name(netdev) #endif /* netdev_name */ #undef netdev_printk #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) #define netdev_printk(level, netdev, format, args...) \ do { \ struct adapter_struct *kc_adapter = netdev_priv(netdev);\ struct pci_dev *pdev = kc_adapter->pdev; \ printk("%s %s: " format, level, pci_name(pdev), \ ##args); \ } while(0) #elif ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) ) #define netdev_printk(level, netdev, format, args...) \ do { \ struct adapter_struct *kc_adapter = netdev_priv(netdev);\ struct pci_dev *pdev = kc_adapter->pdev; \ struct device *dev = pci_dev_to_dev(pdev); \ dev_printk(level, dev, "%s: " format, \ netdev_name(netdev), ##args); \ } while(0) #else /* 2.6.21 => 2.6.34 */ #define netdev_printk(level, netdev, format, args...) \ dev_printk(level, (netdev)->dev.parent, \ "%s: " format, \ netdev_name(netdev), ##args) #endif /* <2.6.0 <2.6.21 <2.6.34 */ #undef netdev_emerg #define netdev_emerg(dev, format, args...) \ netdev_printk(KERN_EMERG, dev, format, ##args) #undef netdev_alert #define netdev_alert(dev, format, args...) \ netdev_printk(KERN_ALERT, dev, format, ##args) #undef netdev_crit #define netdev_crit(dev, format, args...) \ netdev_printk(KERN_CRIT, dev, format, ##args) #undef netdev_err #define netdev_err(dev, format, args...) \ netdev_printk(KERN_ERR, dev, format, ##args) #undef netdev_warn #define netdev_warn(dev, format, args...) \ netdev_printk(KERN_WARNING, dev, format, ##args) #undef netdev_notice #define netdev_notice(dev, format, args...) \ netdev_printk(KERN_NOTICE, dev, format, ##args) #undef netdev_info #define netdev_info(dev, format, args...) \ netdev_printk(KERN_INFO, dev, format, ##args) #undef netdev_dbg #if defined(DEBUG) #define netdev_dbg(__dev, format, args...) \ netdev_printk(KERN_DEBUG, __dev, format, ##args) #elif defined(CONFIG_DYNAMIC_DEBUG) #define netdev_dbg(__dev, format, args...) \ do { \ dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ netdev_name(__dev), ##args); \ } while (0) #else /* DEBUG */ #define netdev_dbg(__dev, format, args...) \ ({ \ if (0) \ netdev_printk(KERN_DEBUG, __dev, format, ##args); \ 0; \ }) #endif /* DEBUG */ #undef netif_printk #define netif_printk(priv, type, level, dev, fmt, args...) \ do { \ if (netif_msg_##type(priv)) \ netdev_printk(level, (dev), fmt, ##args); \ } while (0) #undef netif_emerg #define netif_emerg(priv, type, dev, fmt, args...) \ netif_level(emerg, priv, type, dev, fmt, ##args) #undef netif_alert #define netif_alert(priv, type, dev, fmt, args...) \ netif_level(alert, priv, type, dev, fmt, ##args) #undef netif_crit #define netif_crit(priv, type, dev, fmt, args...) \ netif_level(crit, priv, type, dev, fmt, ##args) #undef netif_err #define netif_err(priv, type, dev, fmt, args...) \ netif_level(err, priv, type, dev, fmt, ##args) #undef netif_warn #define netif_warn(priv, type, dev, fmt, args...) \ netif_level(warn, priv, type, dev, fmt, ##args) #undef netif_notice #define netif_notice(priv, type, dev, fmt, args...) \ netif_level(notice, priv, type, dev, fmt, ##args) #undef netif_info #define netif_info(priv, type, dev, fmt, args...) \ netif_level(info, priv, type, dev, fmt, ##args) #ifdef SET_SYSTEM_SLEEP_PM_OPS #define HAVE_SYSTEM_SLEEP_PM_OPS #endif #ifndef for_each_set_bit #define for_each_set_bit(bit, addr, size) \ for ((bit) = find_first_bit((addr), (size)); \ (bit) < (size); \ (bit) = find_next_bit((addr), (size), (bit) + 1)) #endif /* for_each_set_bit */ #ifndef DEFINE_DMA_UNMAP_ADDR #define DEFINE_DMA_UNMAP_ADDR DECLARE_PCI_UNMAP_ADDR #define DEFINE_DMA_UNMAP_LEN DECLARE_PCI_UNMAP_LEN #define dma_unmap_addr pci_unmap_addr #define dma_unmap_addr_set pci_unmap_addr_set #define dma_unmap_len pci_unmap_len #define dma_unmap_len_set pci_unmap_len_set #endif /* DEFINE_DMA_UNMAP_ADDR */ #else /* < 2.6.34 */ #define HAVE_SYSTEM_SLEEP_PM_OPS #ifndef HAVE_SET_RX_MODE #define HAVE_SET_RX_MODE #endif #endif /* < 2.6.34 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ) #ifndef numa_node_id #define numa_node_id() 0 #endif #ifdef HAVE_TX_MQ #include #ifndef CONFIG_NETDEVICES_MULTIQUEUE void _kc_netif_set_real_num_tx_queues(struct net_device *, unsigned int); #define netif_set_real_num_tx_queues _kc_netif_set_real_num_tx_queues #else /* CONFIG_NETDEVICES_MULTI_QUEUE */ #define netif_set_real_num_tx_queues(_netdev, _count) \ do { \ (_netdev)->egress_subqueue_count = _count; \ } while (0) #endif /* CONFIG_NETDEVICES_MULTI_QUEUE */ #else #define netif_set_real_num_tx_queues(_netdev, _count) do {} while(0) #endif /* HAVE_TX_MQ */ #ifndef ETH_FLAG_RXHASH #define ETH_FLAG_RXHASH (1<<28) #endif /* ETH_FLAG_RXHASH */ #else /* < 2.6.35 */ #define HAVE_PM_QOS_REQUEST_LIST #define HAVE_IRQ_AFFINITY_HINT #endif /* < 2.6.35 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) ) extern int _kc_ethtool_op_set_flags(struct net_device *, u32, u32); #define ethtool_op_set_flags _kc_ethtool_op_set_flags extern u32 _kc_ethtool_op_get_flags(struct net_device *); #define ethtool_op_get_flags _kc_ethtool_op_get_flags #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #ifdef NET_IP_ALIGN #undef NET_IP_ALIGN #endif #define NET_IP_ALIGN 0 #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ #ifdef NET_SKB_PAD #undef NET_SKB_PAD #endif #if (L1_CACHE_BYTES > 32) #define NET_SKB_PAD L1_CACHE_BYTES #else #define NET_SKB_PAD 32 #endif static inline struct sk_buff *_kc_netdev_alloc_skb_ip_align(struct net_device *dev, unsigned int length) { struct sk_buff *skb; skb = alloc_skb(length + NET_SKB_PAD + NET_IP_ALIGN, GFP_ATOMIC); if (skb) { #if (NET_IP_ALIGN + NET_SKB_PAD) skb_reserve(skb, NET_IP_ALIGN + NET_SKB_PAD); #endif skb->dev = dev; } return skb; } #ifdef netdev_alloc_skb_ip_align #undef netdev_alloc_skb_ip_align #endif #define netdev_alloc_skb_ip_align(n, l) _kc_netdev_alloc_skb_ip_align(n, l) #undef netif_level #define netif_level(level, priv, type, dev, fmt, args...) \ do { \ if (netif_msg_##type(priv)) \ netdev_##level(dev, fmt, ##args); \ } while (0) #undef usleep_range #define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000)) #else /* < 2.6.36 */ #define HAVE_PM_QOS_REQUEST_ACTIVE #define HAVE_8021P_SUPPORT #define HAVE_NDO_GET_STATS64 #endif /* < 2.6.36 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ) #ifndef ETHTOOL_RXNTUPLE_ACTION_CLEAR #define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) #endif #ifndef VLAN_N_VID #define VLAN_N_VID VLAN_GROUP_ARRAY_LEN #endif /* VLAN_N_VID */ #ifndef ETH_FLAG_TXVLAN #define ETH_FLAG_TXVLAN (1 << 7) #endif /* ETH_FLAG_TXVLAN */ #ifndef ETH_FLAG_RXVLAN #define ETH_FLAG_RXVLAN (1 << 8) #endif /* ETH_FLAG_RXVLAN */ static inline void _kc_skb_checksum_none_assert(struct sk_buff *skb) { WARN_ON(skb->ip_summed != CHECKSUM_NONE); } #define skb_checksum_none_assert(skb) _kc_skb_checksum_none_assert(skb) static inline void *_kc_vzalloc_node(unsigned long size, int node) { void *addr = vmalloc_node(size, node); if (addr) memset(addr, 0, size); return addr; } #define vzalloc_node(_size, _node) _kc_vzalloc_node(_size, _node) static inline void *_kc_vzalloc(unsigned long size) { void *addr = vmalloc(size); if (addr) memset(addr, 0, size); return addr; } #define vzalloc(_size) _kc_vzalloc(_size) #ifndef vlan_get_protocol static inline __be16 __kc_vlan_get_protocol(const struct sk_buff *skb) { if (vlan_tx_tag_present(skb) || skb->protocol != cpu_to_be16(ETH_P_8021Q)) return skb->protocol; if (skb_headlen(skb) < sizeof(struct vlan_ethhdr)) return 0; return ((struct vlan_ethhdr*)skb->data)->h_vlan_encapsulated_proto; } #define vlan_get_protocol(_skb) __kc_vlan_get_protocol(_skb) #endif #ifdef HAVE_HW_TIME_STAMP #define SKBTX_HW_TSTAMP (1 << 0) #define SKBTX_IN_PROGRESS (1 << 2) #define SKB_SHARED_TX_IS_UNION #endif #if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,18) ) #ifndef HAVE_VLAN_RX_REGISTER #define HAVE_VLAN_RX_REGISTER #endif #endif /* > 2.4.18 */ #endif /* < 2.6.37 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) ) #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ) #define skb_checksum_start_offset(skb) skb_transport_offset(skb) #else /* 2.6.22 -> 2.6.37 */ static inline int _kc_skb_checksum_start_offset(const struct sk_buff *skb) { return skb->csum_start - skb_headroom(skb); } #define skb_checksum_start_offset(skb) _kc_skb_checksum_start_offset(skb) #endif /* 2.6.22 -> 2.6.37 */ #ifdef CONFIG_DCB #ifndef IEEE_8021QAZ_MAX_TCS #define IEEE_8021QAZ_MAX_TCS 8 #endif #ifndef DCB_CAP_DCBX_HOST #define DCB_CAP_DCBX_HOST 0x01 #endif #ifndef DCB_CAP_DCBX_LLD_MANAGED #define DCB_CAP_DCBX_LLD_MANAGED 0x02 #endif #ifndef DCB_CAP_DCBX_VER_CEE #define DCB_CAP_DCBX_VER_CEE 0x04 #endif #ifndef DCB_CAP_DCBX_VER_IEEE #define DCB_CAP_DCBX_VER_IEEE 0x08 #endif #ifndef DCB_CAP_DCBX_STATIC #define DCB_CAP_DCBX_STATIC 0x10 #endif #endif /* CONFIG_DCB */ #else /* < 2.6.38 */ #endif /* < 2.6.38 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) ) #ifndef skb_queue_reverse_walk_safe #define skb_queue_reverse_walk_safe(queue, skb, tmp) \ for (skb = (queue)->prev, tmp = skb->prev; \ skb != (struct sk_buff *)(queue); \ skb = tmp, tmp = skb->prev) #endif #if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0))) extern u8 _kc_netdev_get_num_tc(struct net_device *dev); #define netdev_get_num_tc(dev) _kc_netdev_get_num_tc(dev) extern u8 _kc_netdev_get_prio_tc_map(struct net_device *dev, u8 up); #define netdev_get_prio_tc_map(dev, up) _kc_netdev_get_prio_tc_map(dev, up) #define netdev_set_prio_tc_map(dev, up, tc) do {} while (0) #else /* RHEL6.1 or greater */ #ifndef HAVE_MQPRIO #define HAVE_MQPRIO #endif /* HAVE_MQPRIO */ #ifdef CONFIG_DCB #ifndef HAVE_DCBNL_IEEE #define HAVE_DCBNL_IEEE #ifndef IEEE_8021QAZ_TSA_STRICT #define IEEE_8021QAZ_TSA_STRICT 0 #endif #ifndef IEEE_8021QAZ_TSA_ETS #define IEEE_8021QAZ_TSA_ETS 2 #endif #ifndef IEEE_8021QAZ_APP_SEL_ETHERTYPE #define IEEE_8021QAZ_APP_SEL_ETHERTYPE 1 #endif #endif #endif /* CONFIG_DCB */ #endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)) */ #else /* < 2.6.39 */ #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) #ifndef HAVE_NETDEV_OPS_FCOE_DDP_TARGET #define HAVE_NETDEV_OPS_FCOE_DDP_TARGET #endif #endif /* CONFIG_FCOE || CONFIG_FCOE_MODULE */ #ifndef HAVE_MQPRIO #define HAVE_MQPRIO #endif #ifndef HAVE_SETUP_TC #define HAVE_SETUP_TC #endif #ifdef CONFIG_DCB #ifndef HAVE_DCBNL_IEEE #define HAVE_DCBNL_IEEE #endif #endif /* CONFIG_DCB */ #ifndef HAVE_NDO_SET_FEATURES #define HAVE_NDO_SET_FEATURES #endif #endif /* < 2.6.39 */ /*****************************************************************************/ /* use < 2.6.40 because of a Fedora 15 kernel update where they * updated the kernel version to 2.6.40.x and they back-ported 3.0 features * like set_phys_id for ethtool. */ #undef ETHTOOL_GRXRINGS #if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,40) ) #ifdef ETHTOOL_GRXRINGS #ifndef FLOW_EXT #define FLOW_EXT 0x80000000 union _kc_ethtool_flow_union { struct ethtool_tcpip4_spec tcp_ip4_spec; struct ethtool_usrip4_spec usr_ip4_spec; __u8 hdata[60]; }; struct _kc_ethtool_flow_ext { __be16 vlan_etype; __be16 vlan_tci; __be32 data[2]; }; struct _kc_ethtool_rx_flow_spec { __u32 flow_type; union _kc_ethtool_flow_union h_u; struct _kc_ethtool_flow_ext h_ext; union _kc_ethtool_flow_union m_u; struct _kc_ethtool_flow_ext m_ext; __u64 ring_cookie; __u32 location; }; #define ethtool_rx_flow_spec _kc_ethtool_rx_flow_spec #endif /* FLOW_EXT */ #endif #define pci_disable_link_state_locked pci_disable_link_state #ifndef PCI_LTR_VALUE_MASK #define PCI_LTR_VALUE_MASK 0x000003ff #endif #ifndef PCI_LTR_SCALE_MASK #define PCI_LTR_SCALE_MASK 0x00001c00 #endif #ifndef PCI_LTR_SCALE_SHIFT #define PCI_LTR_SCALE_SHIFT 10 #endif #else /* < 2.6.40 */ #define HAVE_ETHTOOL_SET_PHYS_ID #endif /* < 2.6.40 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ) #ifndef __netdev_alloc_skb_ip_align #define __netdev_alloc_skb_ip_align(d,l,_g) netdev_alloc_skb_ip_align(d,l) #endif /* __netdev_alloc_skb_ip_align */ #define dcb_ieee_setapp(dev, app) dcb_setapp(dev, app) #define dcb_ieee_delapp(dev, app) 0 #define dcb_ieee_getapp_mask(dev, app) (1 << app->priority) #else /* < 3.1.0 */ #ifndef HAVE_DCBNL_IEEE_DELAPP #define HAVE_DCBNL_IEEE_DELAPP #endif #endif /* < 3.1.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ) #ifdef ETHTOOL_GRXRINGS #define HAVE_ETHTOOL_GET_RXNFC_VOID_RULE_LOCS #endif /* ETHTOOL_GRXRINGS */ #ifndef skb_frag_size #define skb_frag_size(frag) _kc_skb_frag_size(frag) static inline unsigned int _kc_skb_frag_size(const skb_frag_t *frag) { return frag->size; } #endif /* skb_frag_size */ #ifndef skb_frag_size_sub #define skb_frag_size_sub(frag, delta) _kc_skb_frag_size_sub(frag, delta) static inline void _kc_skb_frag_size_sub(skb_frag_t *frag, int delta) { frag->size -= delta; } #endif /* skb_frag_size_sub */ #ifndef skb_frag_page #define skb_frag_page(frag) _kc_skb_frag_page(frag) static inline struct page *_kc_skb_frag_page(const skb_frag_t *frag) { return frag->page; } #endif /* skb_frag_page */ #ifndef skb_frag_address #define skb_frag_address(frag) _kc_skb_frag_address(frag) static inline void *_kc_skb_frag_address(const skb_frag_t *frag) { return page_address(skb_frag_page(frag)) + frag->page_offset; } #endif /* skb_frag_address */ #ifndef skb_frag_dma_map #define skb_frag_dma_map(dev,frag,offset,size,dir) \ _kc_skb_frag_dma_map(dev,frag,offset,size,dir) static inline dma_addr_t _kc_skb_frag_dma_map(struct device *dev, const skb_frag_t *frag, size_t offset, size_t size, enum dma_data_direction dir) { return dma_map_page(dev, skb_frag_page(frag), frag->page_offset + offset, size, dir); } #endif /* skb_frag_dma_map */ #ifndef __skb_frag_unref #define __skb_frag_unref(frag) __kc_skb_frag_unref(frag) static inline void __kc_skb_frag_unref(skb_frag_t *frag) { put_page(skb_frag_page(frag)); } #endif /* __skb_frag_unref */ #else /* < 3.2.0 */ #ifndef HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_PCI_DEV_FLAGS_ASSIGNED #define HAVE_VF_SPOOFCHK_CONFIGURE #endif #endif /* < 3.2.0 */ #if (RHEL_RELEASE_CODE && \ (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6,2)) && \ (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0))) #undef ixgbe_get_netdev_tc_txq #define ixgbe_get_netdev_tc_txq(dev, tc) (&netdev_extended(dev)->qos_data.tc_to_txq[tc]) #endif /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ) typedef u32 kni_netdev_features_t; #else /* ! < 3.3.0 */ typedef netdev_features_t kni_netdev_features_t; #define HAVE_INT_NDO_VLAN_RX_ADD_VID #ifdef ETHTOOL_SRXNTUPLE #undef ETHTOOL_SRXNTUPLE #endif #endif /* < 3.3.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) ) #ifndef NETIF_F_RXFCS #define NETIF_F_RXFCS 0 #endif /* NETIF_F_RXFCS */ #ifndef NETIF_F_RXALL #define NETIF_F_RXALL 0 #endif /* NETIF_F_RXALL */ #define NUMTCS_RETURNS_U8 #endif /* < 3.4.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) ) static inline bool __kc_ether_addr_equal(const u8 *addr1, const u8 *addr2) { return !compare_ether_addr(addr1, addr2); } #define ether_addr_equal(_addr1, _addr2) __kc_ether_addr_equal((_addr1),(_addr2)) #else #define HAVE_FDB_OPS #endif /* < 3.5.0 */ /*****************************************************************************/ #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ) #define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX #define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX #define NETIF_F_HW_VLAN_FILTER NETIF_F_HW_VLAN_CTAG_FILTER #endif /* >= 3.10.0 */ #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ) #ifdef CONFIG_PCI_IOV extern int __kc_pci_vfs_assigned(struct pci_dev *dev); #else static inline int __kc_pci_vfs_assigned(struct pci_dev *dev) { return 0; } #endif #define pci_vfs_assigned(dev) __kc_pci_vfs_assigned(dev) #endif #if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) ) #define SET_ETHTOOL_OPS(netdev, ops) ((netdev)->ethtool_ops = (ops)) #endif /* >= 3.16.0 */ #endif /* _KCOMPAT_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_dev.h ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #ifndef _KNI_DEV_H_ #define _KNI_DEV_H_ #include #include #include #include #include #include #ifdef RTE_KNI_VHOST #include #endif #include #define KNI_KTHREAD_RESCHEDULE_INTERVAL 5 /* us */ /** * A structure describing the private information for a kni device. */ struct kni_dev { /* kni list */ struct list_head list; struct net_device_stats stats; int status; uint16_t group_id; /* Group ID of a group of KNI devices */ unsigned core_id; /* Core ID to bind */ char name[RTE_KNI_NAMESIZE]; /* Network device name */ struct task_struct *pthread; /* wait queue for req/resp */ wait_queue_head_t wq; struct mutex sync_lock; /* PCI device id */ uint16_t device_id; /* kni device */ struct net_device *net_dev; struct net_device *lad_dev; struct pci_dev *pci_dev; /* queue for packets to be sent out */ void *tx_q; /* queue for the packets received */ void *rx_q; /* queue for the allocated mbufs those can be used to save sk buffs */ void *alloc_q; /* free queue for the mbufs to be freed */ void *free_q; /* request queue */ void *req_q; /* response queue */ void *resp_q; void * sync_kva; void *sync_va; void *mbuf_kva; void *mbuf_va; /* mbuf size */ unsigned mbuf_size; /* synchro for request processing */ unsigned long synchro; #ifdef RTE_KNI_VHOST struct kni_vhost_queue* vhost_queue; volatile enum { BE_STOP = 0x1, BE_START = 0x2, BE_FINISH = 0x4, }vq_status; #endif }; #define KNI_ERR(args...) printk(KERN_DEBUG "KNI: Error: " args) #define KNI_PRINT(args...) printk(KERN_DEBUG "KNI: " args) #ifdef RTE_KNI_KO_DEBUG #define KNI_DBG(args...) printk(KERN_DEBUG "KNI: " args) #else #define KNI_DBG(args...) #endif #ifdef RTE_KNI_VHOST unsigned int kni_poll(struct file *file, struct socket *sock, poll_table * wait); int kni_chk_vhost_rx(struct kni_dev *kni); int kni_vhost_init(struct kni_dev *kni); int kni_vhost_backend_release(struct kni_dev *kni); struct kni_vhost_queue { struct sock sk; struct socket *sock; int vnet_hdr_sz; struct kni_dev *kni; int sockfd; unsigned int flags; struct sk_buff* cache; struct rte_kni_fifo* fifo; }; #endif #ifdef RTE_KNI_VHOST_DEBUG_RX #define KNI_DBG_RX(args...) printk(KERN_DEBUG "KNI RX: " args) #else #define KNI_DBG_RX(args...) #endif #ifdef RTE_KNI_VHOST_DEBUG_TX #define KNI_DBG_TX(args...) printk(KERN_DEBUG "KNI TX: " args) #else #define KNI_DBG_TX(args...) #endif #endif ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_ethtool.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #include #include #include #include "kni_dev.h" static int kni_check_if_running(struct net_device *dev) { struct kni_dev *priv = netdev_priv(dev); if (priv->lad_dev) return 0; else return -EOPNOTSUPP; } static void kni_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_drvinfo(priv->lad_dev, info); } static int kni_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_settings(priv->lad_dev, ecmd); } static int kni_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->set_settings(priv->lad_dev, ecmd); } static void kni_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_wol(priv->lad_dev, wol); } static int kni_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->set_wol(priv->lad_dev, wol); } static int kni_nway_reset(struct net_device *dev) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->nway_reset(priv->lad_dev); } static int kni_get_eeprom_len(struct net_device *dev) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_eeprom_len(priv->lad_dev); } static int kni_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_eeprom(priv->lad_dev, eeprom, bytes); } static int kni_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->set_eeprom(priv->lad_dev, eeprom, bytes); } static void kni_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_ringparam(priv->lad_dev, ring); } static int kni_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->set_ringparam(priv->lad_dev, ring); } static void kni_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_pauseparam(priv->lad_dev, pause); } static int kni_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->set_pauseparam(priv->lad_dev, pause); } static u32 kni_get_msglevel(struct net_device *dev) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_msglevel(priv->lad_dev); } static void kni_set_msglevel(struct net_device *dev, u32 data) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->set_msglevel(priv->lad_dev, data); } static int kni_get_regs_len(struct net_device *dev) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_regs_len(priv->lad_dev); } static void kni_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_regs(priv->lad_dev, regs, p); } static void kni_get_strings(struct net_device *dev, u32 stringset, u8 *data) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_strings(priv->lad_dev, stringset, data); } static int kni_get_sset_count(struct net_device *dev, int sset) { struct kni_dev *priv = netdev_priv(dev); return priv->lad_dev->ethtool_ops->get_sset_count(priv->lad_dev, sset); } static void kni_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct kni_dev *priv = netdev_priv(dev); priv->lad_dev->ethtool_ops->get_ethtool_stats(priv->lad_dev, stats, data); } struct ethtool_ops kni_ethtool_ops = { .begin = kni_check_if_running, .get_drvinfo = kni_get_drvinfo, .get_settings = kni_get_settings, .set_settings = kni_set_settings, .get_regs_len = kni_get_regs_len, .get_regs = kni_get_regs, .get_wol = kni_get_wol, .set_wol = kni_set_wol, .nway_reset = kni_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = kni_get_eeprom_len, .get_eeprom = kni_get_eeprom, .set_eeprom = kni_set_eeprom, .get_ringparam = kni_get_ringparam, .set_ringparam = kni_set_ringparam, .get_pauseparam = kni_get_pauseparam, .set_pauseparam = kni_set_pauseparam, .get_msglevel = kni_get_msglevel, .set_msglevel = kni_set_msglevel, .get_strings = kni_get_strings, .get_sset_count = kni_get_sset_count, .get_ethtool_stats = kni_get_ethtool_stats, }; void kni_set_ethtool_ops(struct net_device *netdev) { netdev->ethtool_ops = &kni_ethtool_ops; } ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_fifo.h ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #ifndef _KNI_FIFO_H_ #define _KNI_FIFO_H_ #include /** * Adds num elements into the fifo. Return the number actually written */ static inline unsigned kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num) { unsigned i = 0; unsigned fifo_write = fifo->write; unsigned fifo_read = fifo->read; unsigned new_write = fifo_write; for (i = 0; i < num; i++) { new_write = (new_write + 1) & (fifo->len - 1); if (new_write == fifo_read) break; fifo->buffer[fifo_write] = data[i]; fifo_write = new_write; } fifo->write = fifo_write; return i; } /** * Get up to num elements from the fifo. Return the number actully read */ static inline unsigned kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num) { unsigned i = 0; unsigned new_read = fifo->read; unsigned fifo_write = fifo->write; for (i = 0; i < num; i++) { if (new_read == fifo_write) break; data[i] = fifo->buffer[new_read]; new_read = (new_read + 1) & (fifo->len - 1); } fifo->read = new_read; return i; } /** * Get the num of elements in the fifo */ static inline unsigned kni_fifo_count(struct rte_kni_fifo *fifo) { return (fifo->len + fifo->write - fifo->read) & ( fifo->len - 1); } /** * Get the num of available elements in the fifo */ static inline unsigned kni_fifo_free_count(struct rte_kni_fifo *fifo) { return (fifo->read - fifo->write - 1) & (fifo->len - 1); } #ifdef RTE_KNI_VHOST /** * Initializes the kni fifo structure */ static inline void kni_fifo_init(struct rte_kni_fifo *fifo, unsigned size) { fifo->write = 0; fifo->read = 0; fifo->len = size; fifo->elem_size = sizeof(void *); } #endif #endif /* _KNI_FIFO_H_ */ ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_misc.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #include #include #include #include #include #include #include #include "kni_dev.h" #include MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("Kernel Module for managing kni devices"); #define KNI_RX_LOOP_NUM 1000 #define KNI_MAX_DEVICES 32 extern void kni_net_rx(struct kni_dev *kni); extern void kni_net_init(struct net_device *dev); extern void kni_net_config_lo_mode(char *lo_str); extern void kni_net_poll_resp(struct kni_dev *kni); extern void kni_set_ethtool_ops(struct net_device *netdev); extern int ixgbe_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev); extern void ixgbe_kni_remove(struct pci_dev *pdev); extern int igb_kni_probe(struct pci_dev *pdev, struct net_device **lad_dev); extern void igb_kni_remove(struct pci_dev *pdev); static int kni_open(struct inode *inode, struct file *file); static int kni_release(struct inode *inode, struct file *file); static int kni_ioctl(struct inode *inode, unsigned int ioctl_num, unsigned long ioctl_param); static int kni_compat_ioctl(struct inode *inode, unsigned int ioctl_num, unsigned long ioctl_param); static int kni_dev_remove(struct kni_dev *dev); static int __init kni_parse_kthread_mode(void); /* KNI processing for single kernel thread mode */ static int kni_thread_single(void *unused); /* KNI processing for multiple kernel thread mode */ static int kni_thread_multiple(void *param); static struct file_operations kni_fops = { .owner = THIS_MODULE, .open = kni_open, .release = kni_release, .unlocked_ioctl = (void *)kni_ioctl, .compat_ioctl = (void *)kni_compat_ioctl, }; static struct miscdevice kni_misc = { .minor = MISC_DYNAMIC_MINOR, .name = KNI_DEVICE, .fops = &kni_fops, }; /* loopback mode */ static char *lo_mode = NULL; /* Kernel thread mode */ static char *kthread_mode = NULL; static unsigned multiple_kthread_on = 0; #define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */ static volatile unsigned long device_in_use; /* device in use flag */ static struct task_struct *kni_kthread; /* kni list lock */ static DECLARE_RWSEM(kni_list_lock); /* kni list */ static struct list_head kni_list_head = LIST_HEAD_INIT(kni_list_head); static int __init kni_init(void) { KNI_PRINT("######## DPDK kni module loading ########\n"); if (kni_parse_kthread_mode() < 0) { KNI_ERR("Invalid parameter for kthread_mode\n"); return -EINVAL; } if (misc_register(&kni_misc) != 0) { KNI_ERR("Misc registration failed\n"); return -EPERM; } /* Clear the bit of device in use */ clear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use); /* Configure the lo mode according to the input parameter */ kni_net_config_lo_mode(lo_mode); KNI_PRINT("######## DPDK kni module loaded ########\n"); return 0; } static void __exit kni_exit(void) { misc_deregister(&kni_misc); KNI_PRINT("####### DPDK kni module unloaded #######\n"); } static int __init kni_parse_kthread_mode(void) { if (!kthread_mode) return 0; if (strcmp(kthread_mode, "single") == 0) return 0; else if (strcmp(kthread_mode, "multiple") == 0) multiple_kthread_on = 1; else return -1; return 0; } static int kni_open(struct inode *inode, struct file *file) { /* kni device can be opened by one user only, test and set bit */ if (test_and_set_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use)) return -EBUSY; /* Create kernel thread for single mode */ if (multiple_kthread_on == 0) { KNI_PRINT("Single kernel thread for all KNI devices\n"); /* Create kernel thread for RX */ kni_kthread = kthread_run(kni_thread_single, NULL, "kni_single"); if (IS_ERR(kni_kthread)) { KNI_ERR("Unable to create kernel threaed\n"); return PTR_ERR(kni_kthread); } } else KNI_PRINT("Multiple kernel thread mode enabled\n"); KNI_PRINT("/dev/kni opened\n"); return 0; } static int kni_release(struct inode *inode, struct file *file) { struct kni_dev *dev, *n; /* Stop kernel thread for single mode */ if (multiple_kthread_on == 0) { /* Stop kernel thread */ kthread_stop(kni_kthread); kni_kthread = NULL; } down_write(&kni_list_lock); list_for_each_entry_safe(dev, n, &kni_list_head, list) { /* Stop kernel thread for multiple mode */ if (multiple_kthread_on && dev->pthread != NULL) { kthread_stop(dev->pthread); dev->pthread = NULL; } #ifdef RTE_KNI_VHOST kni_vhost_backend_release(dev); #endif kni_dev_remove(dev); list_del(&dev->list); } up_write(&kni_list_lock); /* Clear the bit of device in use */ clear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use); KNI_PRINT("/dev/kni closed\n"); return 0; } static int kni_thread_single(void *unused) { int j; struct kni_dev *dev; while (!kthread_should_stop()) { down_read(&kni_list_lock); for (j = 0; j < KNI_RX_LOOP_NUM; j++) { list_for_each_entry(dev, &kni_list_head, list) { #ifdef RTE_KNI_VHOST kni_chk_vhost_rx(dev); #else kni_net_rx(dev); #endif kni_net_poll_resp(dev); } } up_read(&kni_list_lock); #ifdef RTE_KNI_PREEMPT_DEFAULT /* reschedule out for a while */ schedule_timeout_interruptible(usecs_to_jiffies( \ KNI_KTHREAD_RESCHEDULE_INTERVAL)); #endif } return 0; } static int kni_thread_multiple(void *param) { int j; struct kni_dev *dev = (struct kni_dev *)param; while (!kthread_should_stop()) { for (j = 0; j < KNI_RX_LOOP_NUM; j++) { #ifdef RTE_KNI_VHOST kni_chk_vhost_rx(dev); #else kni_net_rx(dev); #endif kni_net_poll_resp(dev); } #ifdef RTE_KNI_PREEMPT_DEFAULT schedule_timeout_interruptible(usecs_to_jiffies( \ KNI_KTHREAD_RESCHEDULE_INTERVAL)); #endif } return 0; } static int kni_dev_remove(struct kni_dev *dev) { if (!dev) return -ENODEV; switch (dev->device_id) { #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) case (dev): #include igb_kni_remove(dev->pci_dev); break; #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) case (dev): #include ixgbe_kni_remove(dev->pci_dev); break; default: break; } if (dev->net_dev) { unregister_netdev(dev->net_dev); free_netdev(dev->net_dev); } return 0; } static int kni_check_param(struct kni_dev *kni, struct rte_kni_device_info *dev) { if (!kni || !dev) return -1; /* Check if network name has been used */ if (!strncmp(kni->name, dev->name, RTE_KNI_NAMESIZE)) { KNI_ERR("KNI name %s duplicated\n", dev->name); return -1; } return 0; } static int kni_ioctl_create(unsigned int ioctl_num, unsigned long ioctl_param) { int ret; struct rte_kni_device_info dev_info; struct pci_dev *pci = NULL; struct pci_dev *found_pci = NULL; struct net_device *net_dev = NULL; struct net_device *lad_dev = NULL; struct kni_dev *kni, *dev, *n; struct net *net; printk(KERN_INFO "KNI: Creating kni...\n"); /* Check the buffer size, to avoid warning */ if (_IOC_SIZE(ioctl_num) > sizeof(dev_info)) return -EINVAL; /* Copy kni info from user space */ ret = copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)); if (ret) { KNI_ERR("copy_from_user in kni_ioctl_create"); return -EIO; } /** * Check if the cpu core id is valid for binding, * for multiple kernel thread mode. */ if (multiple_kthread_on && dev_info.force_bind && !cpu_online(dev_info.core_id)) { KNI_ERR("cpu %u is not online\n", dev_info.core_id); return -EINVAL; } /* Check if it has been created */ down_read(&kni_list_lock); list_for_each_entry_safe(dev, n, &kni_list_head, list) { if (kni_check_param(dev, &dev_info) < 0) { up_read(&kni_list_lock); return -EINVAL; } } up_read(&kni_list_lock); net_dev = alloc_netdev(sizeof(struct kni_dev), dev_info.name, #ifdef NET_NAME_UNKNOWN NET_NAME_UNKNOWN, #endif kni_net_init); if (net_dev == NULL) { KNI_ERR("error allocating device \"%s\"\n", dev_info.name); return -EBUSY; } net = get_net_ns_by_pid(task_pid_vnr(current)); if (IS_ERR(net)) { free_netdev(net_dev); return PTR_ERR(net); } dev_net_set(net_dev, net); put_net(net); kni = netdev_priv(net_dev); kni->net_dev = net_dev; kni->group_id = dev_info.group_id; kni->core_id = dev_info.core_id; strncpy(kni->name, dev_info.name, RTE_KNI_NAMESIZE); /* Translate user space info into kernel space info */ kni->tx_q = phys_to_virt(dev_info.tx_phys); kni->rx_q = phys_to_virt(dev_info.rx_phys); kni->alloc_q = phys_to_virt(dev_info.alloc_phys); kni->free_q = phys_to_virt(dev_info.free_phys); kni->req_q = phys_to_virt(dev_info.req_phys); kni->resp_q = phys_to_virt(dev_info.resp_phys); kni->sync_va = dev_info.sync_va; kni->sync_kva = phys_to_virt(dev_info.sync_phys); kni->mbuf_kva = phys_to_virt(dev_info.mbuf_phys); kni->mbuf_va = dev_info.mbuf_va; #ifdef RTE_KNI_VHOST kni->vhost_queue = NULL; kni->vq_status = BE_STOP; #endif kni->mbuf_size = dev_info.mbuf_size; KNI_PRINT("tx_phys: 0x%016llx, tx_q addr: 0x%p\n", (unsigned long long) dev_info.tx_phys, kni->tx_q); KNI_PRINT("rx_phys: 0x%016llx, rx_q addr: 0x%p\n", (unsigned long long) dev_info.rx_phys, kni->rx_q); KNI_PRINT("alloc_phys: 0x%016llx, alloc_q addr: 0x%p\n", (unsigned long long) dev_info.alloc_phys, kni->alloc_q); KNI_PRINT("free_phys: 0x%016llx, free_q addr: 0x%p\n", (unsigned long long) dev_info.free_phys, kni->free_q); KNI_PRINT("req_phys: 0x%016llx, req_q addr: 0x%p\n", (unsigned long long) dev_info.req_phys, kni->req_q); KNI_PRINT("resp_phys: 0x%016llx, resp_q addr: 0x%p\n", (unsigned long long) dev_info.resp_phys, kni->resp_q); KNI_PRINT("mbuf_phys: 0x%016llx, mbuf_kva: 0x%p\n", (unsigned long long) dev_info.mbuf_phys, kni->mbuf_kva); KNI_PRINT("mbuf_va: 0x%p\n", dev_info.mbuf_va); KNI_PRINT("mbuf_size: %u\n", kni->mbuf_size); KNI_DBG("PCI: %02x:%02x.%02x %04x:%04x\n", dev_info.bus, dev_info.devid, dev_info.function, dev_info.vendor_id, dev_info.device_id); pci = pci_get_device(dev_info.vendor_id, dev_info.device_id, NULL); /* Support Ethtool */ while (pci) { KNI_PRINT("pci_bus: %02x:%02x:%02x \n", pci->bus->number, PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn)); if ((pci->bus->number == dev_info.bus) && (PCI_SLOT(pci->devfn) == dev_info.devid) && (PCI_FUNC(pci->devfn) == dev_info.function)) { found_pci = pci; switch (dev_info.device_id) { #define RTE_PCI_DEV_ID_DECL_IGB(vend, dev) case (dev): #include ret = igb_kni_probe(found_pci, &lad_dev); break; #define RTE_PCI_DEV_ID_DECL_IXGBE(vend, dev) \ case (dev): #include ret = ixgbe_kni_probe(found_pci, &lad_dev); break; default: ret = -1; break; } KNI_DBG("PCI found: pci=0x%p, lad_dev=0x%p\n", pci, lad_dev); if (ret == 0) { kni->lad_dev = lad_dev; kni_set_ethtool_ops(kni->net_dev); } else { KNI_ERR("Device not supported by ethtool"); kni->lad_dev = NULL; } kni->pci_dev = found_pci; kni->device_id = dev_info.device_id; break; } pci = pci_get_device(dev_info.vendor_id, dev_info.device_id, pci); } if (pci) pci_dev_put(pci); ret = register_netdev(net_dev); if (ret) { KNI_ERR("error %i registering device \"%s\"\n", ret, dev_info.name); kni_dev_remove(kni); return -ENODEV; } #ifdef RTE_KNI_VHOST kni_vhost_init(kni); #endif /** * Create a new kernel thread for multiple mode, set its core affinity, * and finally wake it up. */ if (multiple_kthread_on) { kni->pthread = kthread_create(kni_thread_multiple, (void *)kni, "kni_%s", kni->name); if (IS_ERR(kni->pthread)) { kni_dev_remove(kni); return -ECANCELED; } if (dev_info.force_bind) kthread_bind(kni->pthread, kni->core_id); wake_up_process(kni->pthread); } down_write(&kni_list_lock); list_add(&kni->list, &kni_list_head); up_write(&kni_list_lock); return 0; } static int kni_ioctl_release(unsigned int ioctl_num, unsigned long ioctl_param) { int ret = -EINVAL; struct kni_dev *dev, *n; struct rte_kni_device_info dev_info; if (_IOC_SIZE(ioctl_num) > sizeof(dev_info)) return -EINVAL; ret = copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)); if (ret) { KNI_ERR("copy_from_user in kni_ioctl_release"); return -EIO; } /* Release the network device according to its name */ if (strlen(dev_info.name) == 0) return ret; down_write(&kni_list_lock); list_for_each_entry_safe(dev, n, &kni_list_head, list) { if (strncmp(dev->name, dev_info.name, RTE_KNI_NAMESIZE) != 0) continue; if (multiple_kthread_on && dev->pthread != NULL) { kthread_stop(dev->pthread); dev->pthread = NULL; } #ifdef RTE_KNI_VHOST kni_vhost_backend_release(dev); #endif kni_dev_remove(dev); list_del(&dev->list); ret = 0; break; } up_write(&kni_list_lock); printk(KERN_INFO "KNI: %s release kni named %s\n", (ret == 0 ? "Successfully" : "Unsuccessfully"), dev_info.name); return ret; } static int kni_ioctl(struct inode *inode, unsigned int ioctl_num, unsigned long ioctl_param) { int ret = -EINVAL; KNI_DBG("IOCTL num=0x%0x param=0x%0lx \n", ioctl_num, ioctl_param); /* * Switch according to the ioctl called */ switch (_IOC_NR(ioctl_num)) { case _IOC_NR(RTE_KNI_IOCTL_TEST): /* For test only, not used */ break; case _IOC_NR(RTE_KNI_IOCTL_CREATE): ret = kni_ioctl_create(ioctl_num, ioctl_param); break; case _IOC_NR(RTE_KNI_IOCTL_RELEASE): ret = kni_ioctl_release(ioctl_num, ioctl_param); break; default: KNI_DBG("IOCTL default \n"); break; } return ret; } static int kni_compat_ioctl(struct inode *inode, unsigned int ioctl_num, unsigned long ioctl_param) { /* 32 bits app on 64 bits OS to be supported later */ KNI_PRINT("Not implemented.\n"); return -EINVAL; } module_init(kni_init); module_exit(kni_exit); module_param(lo_mode, charp, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(lo_mode, "KNI loopback mode (default=lo_mode_none):\n" " lo_mode_none Kernel loopback disabled\n" " lo_mode_fifo Enable kernel loopback with fifo\n" " lo_mode_fifo_skb Enable kernel loopback with fifo and skb buffer\n" "\n" ); module_param(kthread_mode, charp, S_IRUGO); MODULE_PARM_DESC(kthread_mode, "Kernel thread mode (default=single):\n" " single Single kernel thread mode enabled.\n" " multiple Multiple kernel thread mode enabled.\n" "\n" ); ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_net.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ /* * This code is inspired from the book "Linux Device Drivers" by * Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates */ #include #include #include #include #include /* eth_type_trans */ #include #include #include #include #include #include #include "kni_dev.h" #define WD_TIMEOUT 5 /*jiffies */ #define MBUF_BURST_SZ 32 #define KNI_WAIT_RESPONSE_TIMEOUT 300 /* 3 seconds */ /* typedef for rx function */ typedef void (*kni_net_rx_t)(struct kni_dev *kni); static int kni_net_tx(struct sk_buff *skb, struct net_device *dev); static void kni_net_rx_normal(struct kni_dev *kni); static void kni_net_rx_lo_fifo(struct kni_dev *kni); static void kni_net_rx_lo_fifo_skb(struct kni_dev *kni); static int kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req); /* kni rx function pointer, with default to normal rx */ static kni_net_rx_t kni_net_rx_func = kni_net_rx_normal; /* * Open and close */ static int kni_net_open(struct net_device *dev) { int ret; struct rte_kni_request req; struct kni_dev *kni = netdev_priv(dev); if (kni->lad_dev) memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN); else /* * Generate random mac address. eth_random_addr() is the newer * version of generating mac address in linux kernel. */ random_ether_addr(dev->dev_addr); netif_start_queue(dev); memset(&req, 0, sizeof(req)); req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; /* Setting if_up to non-zero means up */ req.if_up = 1; ret = kni_net_process_request(kni, &req); return (ret == 0) ? req.result : ret; } static int kni_net_release(struct net_device *dev) { int ret; struct rte_kni_request req; struct kni_dev *kni = netdev_priv(dev); netif_stop_queue(dev); /* can't transmit any more */ memset(&req, 0, sizeof(req)); req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF; /* Setting if_up to 0 means down */ req.if_up = 0; ret = kni_net_process_request(kni, &req); return (ret == 0) ? req.result : ret; } /* * Configuration changes (passed on by ifconfig) */ static int kni_net_config(struct net_device *dev, struct ifmap *map) { if (dev->flags & IFF_UP) /* can't act on a running interface */ return -EBUSY; /* ignore other fields */ return 0; } /* * RX: normal working mode */ static void kni_net_rx_normal(struct kni_dev *kni) { unsigned ret; uint32_t len; unsigned i, num_rx, num_fq; struct rte_kni_mbuf *kva; struct rte_kni_mbuf *va[MBUF_BURST_SZ]; void * data_kva; struct sk_buff *skb; struct net_device *dev = kni->net_dev; /* Get the number of free entries in free_q */ num_fq = kni_fifo_free_count(kni->free_q); if (num_fq == 0) { /* No room on the free_q, bail out */ return; } /* Calculate the number of entries to dequeue from rx_q */ num_rx = min(num_fq, (unsigned)MBUF_BURST_SZ); /* Burst dequeue from rx_q */ num_rx = kni_fifo_get(kni->rx_q, (void **)va, num_rx); if (num_rx == 0) return; /* Transfer received packets to netif */ for (i = 0; i < num_rx; i++) { kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva; len = kva->data_len; data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va + kni->mbuf_kva; skb = dev_alloc_skb(len + 2); if (!skb) { KNI_ERR("Out of mem, dropping pkts\n"); /* Update statistics */ kni->stats.rx_dropped++; } else { /* Align IP on 16B boundary */ skb_reserve(skb, 2); memcpy(skb_put(skb, len), data_kva, len); skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_UNNECESSARY; /* Call netif interface */ netif_rx(skb); /* Update statistics */ kni->stats.rx_bytes += len; kni->stats.rx_packets++; } } /* Burst enqueue mbufs into free_q */ ret = kni_fifo_put(kni->free_q, (void **)va, num_rx); if (ret != num_rx) /* Failing should not happen */ KNI_ERR("Fail to enqueue entries into free_q\n"); } /* * RX: loopback with enqueue/dequeue fifos. */ static void kni_net_rx_lo_fifo(struct kni_dev *kni) { unsigned ret; uint32_t len; unsigned i, num, num_rq, num_tq, num_aq, num_fq; struct rte_kni_mbuf *kva; struct rte_kni_mbuf *va[MBUF_BURST_SZ]; void * data_kva; struct rte_kni_mbuf *alloc_kva; struct rte_kni_mbuf *alloc_va[MBUF_BURST_SZ]; void *alloc_data_kva; /* Get the number of entries in rx_q */ num_rq = kni_fifo_count(kni->rx_q); /* Get the number of free entrie in tx_q */ num_tq = kni_fifo_free_count(kni->tx_q); /* Get the number of entries in alloc_q */ num_aq = kni_fifo_count(kni->alloc_q); /* Get the number of free entries in free_q */ num_fq = kni_fifo_free_count(kni->free_q); /* Calculate the number of entries to be dequeued from rx_q */ num = min(num_rq, num_tq); num = min(num, num_aq); num = min(num, num_fq); num = min(num, (unsigned)MBUF_BURST_SZ); /* Return if no entry to dequeue from rx_q */ if (num == 0) return; /* Burst dequeue from rx_q */ ret = kni_fifo_get(kni->rx_q, (void **)va, num); if (ret == 0) return; /* Failing should not happen */ /* Dequeue entries from alloc_q */ ret = kni_fifo_get(kni->alloc_q, (void **)alloc_va, num); if (ret) { num = ret; /* Copy mbufs */ for (i = 0; i < num; i++) { kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva; len = kva->pkt_len; data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va + kni->mbuf_kva; alloc_kva = (void *)alloc_va[i] - kni->mbuf_va + kni->mbuf_kva; alloc_data_kva = alloc_kva->buf_addr + alloc_kva->data_off - kni->mbuf_va + kni->mbuf_kva; memcpy(alloc_data_kva, data_kva, len); alloc_kva->pkt_len = len; alloc_kva->data_len = len; kni->stats.tx_bytes += len; kni->stats.rx_bytes += len; } /* Burst enqueue mbufs into tx_q */ ret = kni_fifo_put(kni->tx_q, (void **)alloc_va, num); if (ret != num) /* Failing should not happen */ KNI_ERR("Fail to enqueue mbufs into tx_q\n"); } /* Burst enqueue mbufs into free_q */ ret = kni_fifo_put(kni->free_q, (void **)va, num); if (ret != num) /* Failing should not happen */ KNI_ERR("Fail to enqueue mbufs into free_q\n"); /** * Update statistic, and enqueue/dequeue failure is impossible, * as all queues are checked at first. */ kni->stats.tx_packets += num; kni->stats.rx_packets += num; } /* * RX: loopback with enqueue/dequeue fifos and sk buffer copies. */ static void kni_net_rx_lo_fifo_skb(struct kni_dev *kni) { unsigned ret; uint32_t len; unsigned i, num_rq, num_fq, num; struct rte_kni_mbuf *kva; struct rte_kni_mbuf *va[MBUF_BURST_SZ]; void * data_kva; struct sk_buff *skb; struct net_device *dev = kni->net_dev; /* Get the number of entries in rx_q */ num_rq = kni_fifo_count(kni->rx_q); /* Get the number of free entries in free_q */ num_fq = kni_fifo_free_count(kni->free_q); /* Calculate the number of entries to dequeue from rx_q */ num = min(num_rq, num_fq); num = min(num, (unsigned)MBUF_BURST_SZ); /* Return if no entry to dequeue from rx_q */ if (num == 0) return; /* Burst dequeue mbufs from rx_q */ ret = kni_fifo_get(kni->rx_q, (void **)va, num); if (ret == 0) return; /* Copy mbufs to sk buffer and then call tx interface */ for (i = 0; i < num; i++) { kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva; len = kva->data_len; data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va + kni->mbuf_kva; skb = dev_alloc_skb(len + 2); if (skb == NULL) KNI_ERR("Out of mem, dropping pkts\n"); else { /* Align IP on 16B boundary */ skb_reserve(skb, 2); memcpy(skb_put(skb, len), data_kva, len); skb->dev = dev; skb->ip_summed = CHECKSUM_UNNECESSARY; dev_kfree_skb(skb); } /* Simulate real usage, allocate/copy skb twice */ skb = dev_alloc_skb(len + 2); if (skb == NULL) { KNI_ERR("Out of mem, dropping pkts\n"); kni->stats.rx_dropped++; } else { /* Align IP on 16B boundary */ skb_reserve(skb, 2); memcpy(skb_put(skb, len), data_kva, len); skb->dev = dev; skb->ip_summed = CHECKSUM_UNNECESSARY; kni->stats.rx_bytes += len; kni->stats.rx_packets++; /* call tx interface */ kni_net_tx(skb, dev); } } /* enqueue all the mbufs from rx_q into free_q */ ret = kni_fifo_put(kni->free_q, (void **)&va, num); if (ret != num) /* Failing should not happen */ KNI_ERR("Fail to enqueue mbufs into free_q\n"); } /* rx interface */ void kni_net_rx(struct kni_dev *kni) { /** * It doesn't need to check if it is NULL pointer, * as it has a default value */ (*kni_net_rx_func)(kni); } /* * Transmit a packet (called by the kernel) */ #ifdef RTE_KNI_VHOST static int kni_net_tx(struct sk_buff *skb, struct net_device *dev) { struct kni_dev *kni = netdev_priv(dev); dev_kfree_skb(skb); kni->stats.tx_dropped++; return NETDEV_TX_OK; } #else static int kni_net_tx(struct sk_buff *skb, struct net_device *dev) { int len = 0; unsigned ret; struct kni_dev *kni = netdev_priv(dev); struct rte_kni_mbuf *pkt_kva = NULL; struct rte_kni_mbuf *pkt_va = NULL; dev->trans_start = jiffies; /* save the timestamp */ /* Check if the length of skb is less than mbuf size */ if (skb->len > kni->mbuf_size) goto drop; /** * Check if it has at least one free entry in tx_q and * one entry in alloc_q. */ if (kni_fifo_free_count(kni->tx_q) == 0 || kni_fifo_count(kni->alloc_q) == 0) { /** * If no free entry in tx_q or no entry in alloc_q, * drops skb and goes out. */ goto drop; } /* dequeue a mbuf from alloc_q */ ret = kni_fifo_get(kni->alloc_q, (void **)&pkt_va, 1); if (likely(ret == 1)) { void *data_kva; pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva; data_kva = pkt_kva->buf_addr + pkt_kva->data_off - kni->mbuf_va + kni->mbuf_kva; len = skb->len; memcpy(data_kva, skb->data, len); if (unlikely(len < ETH_ZLEN)) { memset(data_kva + len, 0, ETH_ZLEN - len); len = ETH_ZLEN; } pkt_kva->pkt_len = len; pkt_kva->data_len = len; /* enqueue mbuf into tx_q */ ret = kni_fifo_put(kni->tx_q, (void **)&pkt_va, 1); if (unlikely(ret != 1)) { /* Failing should not happen */ KNI_ERR("Fail to enqueue mbuf into tx_q\n"); goto drop; } } else { /* Failing should not happen */ KNI_ERR("Fail to dequeue mbuf from alloc_q\n"); goto drop; } /* Free skb and update statistics */ dev_kfree_skb(skb); kni->stats.tx_bytes += len; kni->stats.tx_packets++; return NETDEV_TX_OK; drop: /* Free skb and update statistics */ dev_kfree_skb(skb); kni->stats.tx_dropped++; return NETDEV_TX_OK; } #endif /* * Deal with a transmit timeout. */ static void kni_net_tx_timeout (struct net_device *dev) { struct kni_dev *kni = netdev_priv(dev); KNI_DBG("Transmit timeout at %ld, latency %ld\n", jiffies, jiffies - dev->trans_start); kni->stats.tx_errors++; netif_wake_queue(dev); return; } /* * Ioctl commands */ static int kni_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { KNI_DBG("kni_net_ioctl %d\n", ((struct kni_dev *)netdev_priv(dev))->group_id); return 0; } static void kni_net_set_rx_mode(struct net_device *dev) { } static int kni_net_change_mtu(struct net_device *dev, int new_mtu) { int ret; struct rte_kni_request req; struct kni_dev *kni = netdev_priv(dev); KNI_DBG("kni_net_change_mtu new mtu %d to be set\n", new_mtu); memset(&req, 0, sizeof(req)); req.req_id = RTE_KNI_REQ_CHANGE_MTU; req.new_mtu = new_mtu; ret = kni_net_process_request(kni, &req); if (ret == 0 && req.result == 0) dev->mtu = new_mtu; return (ret == 0) ? req.result : ret; } /* * Checks if the user space application provided the resp message */ void kni_net_poll_resp(struct kni_dev *kni) { if (kni_fifo_count(kni->resp_q)) wake_up_interruptible(&kni->wq); } /* * It can be called to process the request. */ static int kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req) { int ret = -1; void *resp_va; unsigned num; int ret_val; if (!kni || !req) { KNI_ERR("No kni instance or request\n"); return -EINVAL; } mutex_lock(&kni->sync_lock); /* Construct data */ memcpy(kni->sync_kva, req, sizeof(struct rte_kni_request)); num = kni_fifo_put(kni->req_q, &kni->sync_va, 1); if (num < 1) { KNI_ERR("Cannot send to req_q\n"); ret = -EBUSY; goto fail; } ret_val = wait_event_interruptible_timeout(kni->wq, kni_fifo_count(kni->resp_q), 3 * HZ); if (signal_pending(current) || ret_val <= 0) { ret = -ETIME; goto fail; } num = kni_fifo_get(kni->resp_q, (void **)&resp_va, 1); if (num != 1 || resp_va != kni->sync_va) { /* This should never happen */ KNI_ERR("No data in resp_q\n"); ret = -ENODATA; goto fail; } memcpy(req, kni->sync_kva, sizeof(struct rte_kni_request)); ret = 0; fail: mutex_unlock(&kni->sync_lock); return ret; } /* * Return statistics to the caller */ static struct net_device_stats * kni_net_stats(struct net_device *dev) { struct kni_dev *kni = netdev_priv(dev); return &kni->stats; } /* * Fill the eth header */ static int kni_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned int len) { struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len); memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len); eth->h_proto = htons(type); return dev->hard_header_len; } /* * Re-fill the eth header */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) static int kni_net_rebuild_header(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct ethhdr *eth = (struct ethhdr *) skb->data; memcpy(eth->h_source, dev->dev_addr, dev->addr_len); memcpy(eth->h_dest, dev->dev_addr, dev->addr_len); return 0; } #endif /* < 4.1.0 */ /** * kni_net_set_mac - Change the Ethernet Address of the KNI NIC * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure **/ static int kni_net_set_mac(struct net_device *netdev, void *p) { struct sockaddr *addr = p; if (!is_valid_ether_addr((unsigned char *)(addr->sa_data))) return -EADDRNOTAVAIL; memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); return 0; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) static int kni_net_change_carrier(struct net_device *dev, bool new_carrier) { if (new_carrier) netif_carrier_on(dev); else netif_carrier_off(dev); return 0; } #endif static const struct header_ops kni_net_header_ops = { .create = kni_net_header, #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) .rebuild = kni_net_rebuild_header, #endif /* < 4.1.0 */ .cache = NULL, /* disable caching */ }; static const struct net_device_ops kni_net_netdev_ops = { .ndo_open = kni_net_open, .ndo_stop = kni_net_release, .ndo_set_config = kni_net_config, .ndo_start_xmit = kni_net_tx, .ndo_change_mtu = kni_net_change_mtu, .ndo_do_ioctl = kni_net_ioctl, .ndo_set_rx_mode = kni_net_set_rx_mode, .ndo_get_stats = kni_net_stats, .ndo_tx_timeout = kni_net_tx_timeout, .ndo_set_mac_address = kni_net_set_mac, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) .ndo_change_carrier = kni_net_change_carrier, #endif }; void kni_net_init(struct net_device *dev) { struct kni_dev *kni = netdev_priv(dev); KNI_DBG("kni_net_init\n"); init_waitqueue_head(&kni->wq); mutex_init(&kni->sync_lock); ether_setup(dev); /* assign some of the fields */ dev->netdev_ops = &kni_net_netdev_ops; dev->header_ops = &kni_net_header_ops; dev->watchdog_timeo = WD_TIMEOUT; } void kni_net_config_lo_mode(char *lo_str) { if (!lo_str) { KNI_PRINT("loopback disabled"); return; } if (!strcmp(lo_str, "lo_mode_none")) KNI_PRINT("loopback disabled"); else if (!strcmp(lo_str, "lo_mode_fifo")) { KNI_PRINT("loopback mode=lo_mode_fifo enabled"); kni_net_rx_func = kni_net_rx_lo_fifo; } else if (!strcmp(lo_str, "lo_mode_fifo_skb")) { KNI_PRINT("loopback mode=lo_mode_fifo_skb enabled"); kni_net_rx_func = kni_net_rx_lo_fifo_skb; } else KNI_PRINT("Incognizant parameter, loopback disabled"); } ================================================ FILE: lib/librte_eal/linuxapp/kni/kni_vhost.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #include #include #include #include #include #include #include #include #include #include #include "compat.h" #include "kni_dev.h" #include "kni_fifo.h" #define RX_BURST_SZ 4 extern void put_unused_fd(unsigned int fd); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) extern struct file* sock_alloc_file(struct socket *sock, int flags, const char *dname); extern int get_unused_fd_flags(unsigned flags); extern void fd_install(unsigned int fd, struct file *file); static int kni_sock_map_fd(struct socket *sock) { struct file *file; int fd = get_unused_fd_flags(0); if (fd < 0) return fd; file = sock_alloc_file(sock, 0, NULL); if (IS_ERR(file)) { put_unused_fd(fd); return PTR_ERR(file); } fd_install(fd, file); return fd; } #else #define kni_sock_map_fd(s) sock_map_fd(s, 0) #endif static struct proto kni_raw_proto = { .name = "kni_vhost", .owner = THIS_MODULE, .obj_size = sizeof(struct kni_vhost_queue), }; static inline int kni_vhost_net_tx(struct kni_dev *kni, struct msghdr *m, unsigned offset, unsigned len) { struct rte_kni_mbuf *pkt_kva = NULL; struct rte_kni_mbuf *pkt_va = NULL; int ret; KNI_DBG_TX("tx offset=%d, len=%d, iovlen=%d\n", #ifdef HAVE_IOV_ITER_MSGHDR offset, len, (int)m->msg_iter.iov->iov_len); #else offset, len, (int)m->msg_iov->iov_len); #endif /** * Check if it has at least one free entry in tx_q and * one entry in alloc_q. */ if (kni_fifo_free_count(kni->tx_q) == 0 || kni_fifo_count(kni->alloc_q) == 0) { /** * If no free entry in tx_q or no entry in alloc_q, * drops skb and goes out. */ goto drop; } /* dequeue a mbuf from alloc_q */ ret = kni_fifo_get(kni->alloc_q, (void **)&pkt_va, 1); if (likely(ret == 1)) { void *data_kva; pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva; data_kva = pkt_kva->buf_addr + pkt_kva->data_off - kni->mbuf_va + kni->mbuf_kva; #ifdef HAVE_IOV_ITER_MSGHDR copy_from_iter(data_kva, len, &m->msg_iter); #else memcpy_fromiovecend(data_kva, m->msg_iov, offset, len); #endif if (unlikely(len < ETH_ZLEN)) { memset(data_kva + len, 0, ETH_ZLEN - len); len = ETH_ZLEN; } pkt_kva->pkt_len = len; pkt_kva->data_len = len; /* enqueue mbuf into tx_q */ ret = kni_fifo_put(kni->tx_q, (void **)&pkt_va, 1); if (unlikely(ret != 1)) { /* Failing should not happen */ KNI_ERR("Fail to enqueue mbuf into tx_q\n"); goto drop; } } else { /* Failing should not happen */ KNI_ERR("Fail to dequeue mbuf from alloc_q\n"); goto drop; } /* update statistics */ kni->stats.tx_bytes += len; kni->stats.tx_packets++; return 0; drop: /* update statistics */ kni->stats.tx_dropped++; return 0; } static inline int kni_vhost_net_rx(struct kni_dev *kni, struct msghdr *m, unsigned offset, unsigned len) { uint32_t pkt_len; struct rte_kni_mbuf *kva; struct rte_kni_mbuf *va; void * data_kva; struct sk_buff *skb; struct kni_vhost_queue *q = kni->vhost_queue; if (unlikely(q == NULL)) return 0; /* ensure at least one entry in free_q */ if (unlikely(kni_fifo_free_count(kni->free_q) == 0)) return 0; skb = skb_dequeue(&q->sk.sk_receive_queue); if (unlikely(skb == NULL)) return 0; kva = (struct rte_kni_mbuf*)skb->data; /* free skb to cache */ skb->data = NULL; if (unlikely(1 != kni_fifo_put(q->fifo, (void **)&skb, 1))) /* Failing should not happen */ KNI_ERR("Fail to enqueue entries into rx cache fifo\n"); pkt_len = kva->data_len; if (unlikely(pkt_len > len)) goto drop; KNI_DBG_RX("rx offset=%d, len=%d, pkt_len=%d, iovlen=%d\n", #ifdef HAVE_IOV_ITER_MSGHDR offset, len, pkt_len, (int)m->msg_iter.iov->iov_len); #else offset, len, pkt_len, (int)m->msg_iov->iov_len); #endif data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va + kni->mbuf_kva; #ifdef HAVE_IOV_ITER_MSGHDR if (unlikely(copy_to_iter(data_kva, pkt_len, &m->msg_iter))) #else if (unlikely(memcpy_toiovecend(m->msg_iov, data_kva, offset, pkt_len))) #endif goto drop; /* Update statistics */ kni->stats.rx_bytes += pkt_len; kni->stats.rx_packets++; /* enqueue mbufs into free_q */ va = (void*)kva - kni->mbuf_kva + kni->mbuf_va; if (unlikely(1 != kni_fifo_put(kni->free_q, (void **)&va, 1))) /* Failing should not happen */ KNI_ERR("Fail to enqueue entries into free_q\n"); KNI_DBG_RX("receive done %d\n", pkt_len); return pkt_len; drop: /* Update drop statistics */ kni->stats.rx_dropped++; return 0; } static unsigned int kni_sock_poll(struct file *file, struct socket *sock, poll_table * wait) { struct kni_vhost_queue *q = container_of(sock->sk, struct kni_vhost_queue, sk); struct kni_dev *kni; unsigned int mask = 0; if (unlikely(q == NULL || q->kni == NULL)) return POLLERR; kni = q->kni; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) KNI_DBG("start kni_poll on group %d, wq 0x%16llx\n", kni->group_id, (uint64_t)sock->wq); #else KNI_DBG("start kni_poll on group %d, wait at 0x%16llx\n", kni->group_id, (uint64_t)&sock->wait); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) poll_wait(file, &sock->wq->wait, wait); #else poll_wait(file, &sock->wait, wait); #endif if (kni_fifo_count(kni->rx_q) > 0) mask |= POLLIN | POLLRDNORM; if (sock_writeable(&q->sk) || (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &q->sock->flags) && sock_writeable(&q->sk))) mask |= POLLOUT | POLLWRNORM; return mask; } static inline void kni_vhost_enqueue(struct kni_dev *kni, struct kni_vhost_queue *q, struct sk_buff *skb, struct rte_kni_mbuf *va) { struct rte_kni_mbuf *kva; kva = (void *)(va) - kni->mbuf_va + kni->mbuf_kva; (skb)->data = (unsigned char*)kva; (skb)->len = kva->data_len; skb_queue_tail(&q->sk.sk_receive_queue, skb); } static inline void kni_vhost_enqueue_burst(struct kni_dev *kni, struct kni_vhost_queue *q, struct sk_buff **skb, struct rte_kni_mbuf **va) { int i; for (i = 0; i < RX_BURST_SZ; skb++, va++, i++) kni_vhost_enqueue(kni, q, *skb, *va); } int kni_chk_vhost_rx(struct kni_dev *kni) { struct kni_vhost_queue *q = kni->vhost_queue; unsigned nb_in, nb_mbuf, nb_skb; const unsigned BURST_MASK = RX_BURST_SZ - 1; unsigned nb_burst, nb_backlog, i; struct sk_buff *skb[RX_BURST_SZ]; struct rte_kni_mbuf *va[RX_BURST_SZ]; if (unlikely(BE_STOP & kni->vq_status)) { kni->vq_status |= BE_FINISH; return 0; } if (unlikely(q == NULL)) return 0; nb_skb = kni_fifo_count(q->fifo); nb_mbuf = kni_fifo_count(kni->rx_q); nb_in = min(nb_mbuf, nb_skb); nb_in = min(nb_in, (unsigned)RX_BURST_SZ); nb_burst = (nb_in & ~BURST_MASK); nb_backlog = (nb_in & BURST_MASK); /* enqueue skb_queue per BURST_SIZE bulk */ if (0 != nb_burst) { if (unlikely(RX_BURST_SZ != kni_fifo_get( kni->rx_q, (void **)&va, RX_BURST_SZ))) goto except; if (unlikely(RX_BURST_SZ != kni_fifo_get( q->fifo, (void **)&skb, RX_BURST_SZ))) goto except; kni_vhost_enqueue_burst(kni, q, skb, va); } /* all leftover, do one by one */ for (i = 0; i < nb_backlog; ++i) { if (unlikely(1 != kni_fifo_get( kni->rx_q,(void **)&va, 1))) goto except; if (unlikely(1 != kni_fifo_get( q->fifo, (void **)&skb, 1))) goto except; kni_vhost_enqueue(kni, q, *skb, *va); } /* Ondemand wake up */ if ((nb_in == RX_BURST_SZ) || (nb_skb == 0) || ((nb_mbuf < RX_BURST_SZ) && (nb_mbuf != 0))) { wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); KNI_DBG_RX("RX CHK KICK nb_mbuf %d, nb_skb %d, nb_in %d\n", nb_mbuf, nb_skb, nb_in); } return 0; except: /* Failing should not happen */ KNI_ERR("Fail to enqueue fifo, it shouldn't happen \n"); BUG_ON(1); return 0; } static int #ifdef HAVE_KIOCB_MSG_PARAM kni_sock_sndmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) #else kni_sock_sndmsg(struct socket *sock, struct msghdr *m, size_t total_len) #endif /* HAVE_KIOCB_MSG_PARAM */ { struct kni_vhost_queue *q = container_of(sock->sk, struct kni_vhost_queue, sk); int vnet_hdr_len = 0; unsigned long len = total_len; if (unlikely(q == NULL || q->kni == NULL)) return 0; KNI_DBG_TX("kni_sndmsg len %ld, flags 0x%08x, nb_iov %d\n", #ifdef HAVE_IOV_ITER_MSGHDR len, q->flags, (int)m->msg_iter.iov->iov_len); #else len, q->flags, (int)m->msg_iovlen); #endif #ifdef RTE_KNI_VHOST_VNET_HDR_EN if (likely(q->flags & IFF_VNET_HDR)) { vnet_hdr_len = q->vnet_hdr_sz; if (unlikely(len < vnet_hdr_len)) return -EINVAL; len -= vnet_hdr_len; } #endif if (unlikely(len < ETH_HLEN + q->vnet_hdr_sz)) return -EINVAL; return kni_vhost_net_tx(q->kni, m, vnet_hdr_len, len); } static int #ifdef HAVE_KIOCB_MSG_PARAM kni_sock_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags) #else kni_sock_rcvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags) #endif /* HAVE_KIOCB_MSG_PARAM */ { int vnet_hdr_len = 0; int pkt_len = 0; struct kni_vhost_queue *q = container_of(sock->sk, struct kni_vhost_queue, sk); static struct virtio_net_hdr __attribute__ ((unused)) vnet_hdr = { .flags = 0, .gso_type = VIRTIO_NET_HDR_GSO_NONE }; if (unlikely(q == NULL || q->kni == NULL)) return 0; #ifdef RTE_KNI_VHOST_VNET_HDR_EN if (likely(q->flags & IFF_VNET_HDR)) { vnet_hdr_len = q->vnet_hdr_sz; if ((len -= vnet_hdr_len) < 0) return -EINVAL; } #endif if (unlikely(0 == (pkt_len = kni_vhost_net_rx(q->kni, m, vnet_hdr_len, len)))) return 0; #ifdef RTE_KNI_VHOST_VNET_HDR_EN /* no need to copy hdr when no pkt received */ #ifdef HAVE_IOV_ITER_MSGHDR if (unlikely(copy_to_iter((void *)&vnet_hdr, vnet_hdr_len, &m->msg_iter))) #else if (unlikely(memcpy_toiovecend(m->msg_iov, (void *)&vnet_hdr, 0, vnet_hdr_len))) #endif /* HAVE_IOV_ITER_MSGHDR */ return -EFAULT; #endif /* RTE_KNI_VHOST_VNET_HDR_EN */ KNI_DBG_RX("kni_rcvmsg expect_len %ld, flags 0x%08x, pkt_len %d\n", (unsigned long)len, q->flags, pkt_len); return (pkt_len + vnet_hdr_len); } /* dummy tap like ioctl */ static int kni_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; struct ifreq __user *ifr = argp; unsigned int __user *up = argp; struct kni_vhost_queue *q = container_of(sock->sk, struct kni_vhost_queue, sk); struct kni_dev *kni; unsigned int u; int __user *sp = argp; int s; int ret; KNI_DBG("tap ioctl cmd 0x%08x\n", cmd); switch (cmd) { case TUNSETIFF: KNI_DBG("TUNSETIFF\n"); /* ignore the name, just look at flags */ if (get_user(u, &ifr->ifr_flags)) return -EFAULT; ret = 0; if ((u & ~IFF_VNET_HDR) != (IFF_NO_PI | IFF_TAP)) ret = -EINVAL; else q->flags = u; return ret; case TUNGETIFF: KNI_DBG("TUNGETIFF\n"); rcu_read_lock_bh(); kni = rcu_dereference_bh(q->kni); if (kni) dev_hold(kni->net_dev); rcu_read_unlock_bh(); if (!kni) return -ENOLINK; ret = 0; if (copy_to_user(&ifr->ifr_name, kni->net_dev->name, IFNAMSIZ) || put_user(q->flags, &ifr->ifr_flags)) ret = -EFAULT; dev_put(kni->net_dev); return ret; case TUNGETFEATURES: KNI_DBG("TUNGETFEATURES\n"); u = IFF_TAP | IFF_NO_PI; #ifdef RTE_KNI_VHOST_VNET_HDR_EN u |= IFF_VNET_HDR; #endif if (put_user(u, up)) return -EFAULT; return 0; case TUNSETSNDBUF: KNI_DBG("TUNSETSNDBUF\n"); if (get_user(u, up)) return -EFAULT; q->sk.sk_sndbuf = u; return 0; case TUNGETVNETHDRSZ: s = q->vnet_hdr_sz; if (put_user(s, sp)) return -EFAULT; KNI_DBG("TUNGETVNETHDRSZ %d\n", s); return 0; case TUNSETVNETHDRSZ: if (get_user(s, sp)) return -EFAULT; if (s < (int)sizeof(struct virtio_net_hdr)) return -EINVAL; KNI_DBG("TUNSETVNETHDRSZ %d\n", s); q->vnet_hdr_sz = s; return 0; case TUNSETOFFLOAD: KNI_DBG("TUNSETOFFLOAD %lx\n", arg); #ifdef RTE_KNI_VHOST_VNET_HDR_EN /* not support any offload yet */ if (!(q->flags & IFF_VNET_HDR)) return -EINVAL; return 0; #else return -EINVAL; #endif default: KNI_DBG("NOT SUPPORT\n"); return -EINVAL; } } static int kni_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { /* 32 bits app on 64 bits OS to be supported later */ KNI_PRINT("Not implemented.\n"); return -EINVAL; } #define KNI_VHOST_WAIT_WQ_SAFE() \ do { \ while ((BE_FINISH | BE_STOP) == kni->vq_status) \ msleep(1); \ }while(0) \ static int kni_sock_release(struct socket *sock) { struct kni_vhost_queue *q = container_of(sock->sk, struct kni_vhost_queue, sk); struct kni_dev *kni; if (q == NULL) return 0; if (NULL != (kni = q->kni)) { kni->vq_status = BE_STOP; KNI_VHOST_WAIT_WQ_SAFE(); kni->vhost_queue = NULL; q->kni = NULL; } if (q->sockfd != -1) q->sockfd = -1; sk_set_socket(&q->sk, NULL); sock->sk = NULL; sock_put(&q->sk); KNI_DBG("dummy sock release done\n"); return 0; } int kni_sock_getname (struct socket *sock, struct sockaddr *addr, int *sockaddr_len, int peer) { KNI_DBG("dummy sock getname\n"); ((struct sockaddr_ll*)addr)->sll_family = AF_PACKET; return 0; } static const struct proto_ops kni_socket_ops = { .getname = kni_sock_getname, .sendmsg = kni_sock_sndmsg, .recvmsg = kni_sock_rcvmsg, .release = kni_sock_release, .poll = kni_sock_poll, .ioctl = kni_sock_ioctl, .compat_ioctl = kni_sock_compat_ioctl, }; static void kni_sk_write_space(struct sock *sk) { wait_queue_head_t *wqueue; if (!sock_writeable(sk) || !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) return; wqueue = sk_sleep(sk); if (wqueue && waitqueue_active(wqueue)) wake_up_interruptible_poll( wqueue, POLLOUT | POLLWRNORM | POLLWRBAND); } static void kni_sk_destruct(struct sock *sk) { struct kni_vhost_queue *q = container_of(sk, struct kni_vhost_queue, sk); if (!q) return; /* make sure there's no packet in buffer */ while (skb_dequeue(&sk->sk_receive_queue) != NULL) ; mb(); if (q->fifo != NULL) { kfree(q->fifo); q->fifo = NULL; } if (q->cache != NULL) { kfree(q->cache); q->cache = NULL; } } static int kni_vhost_backend_init(struct kni_dev *kni) { struct kni_vhost_queue *q; struct net *net = current->nsproxy->net_ns; int err, i, sockfd; struct rte_kni_fifo *fifo; struct sk_buff *elem; if (kni->vhost_queue != NULL) return -1; if (!(q = (struct kni_vhost_queue *)sk_alloc( net, AF_UNSPEC, GFP_KERNEL, &kni_raw_proto))) return -ENOMEM; err = sock_create_lite(AF_UNSPEC, SOCK_RAW, IPPROTO_RAW, &q->sock); if (err) goto free_sk; sockfd = kni_sock_map_fd(q->sock); if (sockfd < 0) { err = sockfd; goto free_sock; } /* cache init */ q->cache = kzalloc(RTE_KNI_VHOST_MAX_CACHE_SIZE * sizeof(struct sk_buff), GFP_KERNEL); if (!q->cache) goto free_fd; fifo = kzalloc(RTE_KNI_VHOST_MAX_CACHE_SIZE * sizeof(void *) + sizeof(struct rte_kni_fifo), GFP_KERNEL); if (!fifo) goto free_cache; kni_fifo_init(fifo, RTE_KNI_VHOST_MAX_CACHE_SIZE); for (i = 0; i < RTE_KNI_VHOST_MAX_CACHE_SIZE; i++) { elem = &q->cache[i]; kni_fifo_put(fifo, (void**)&elem, 1); } q->fifo = fifo; /* store sockfd in vhost_queue */ q->sockfd = sockfd; /* init socket */ q->sock->type = SOCK_RAW; q->sock->state = SS_CONNECTED; q->sock->ops = &kni_socket_ops; sock_init_data(q->sock, &q->sk); /* init sock data */ q->sk.sk_write_space = kni_sk_write_space; q->sk.sk_destruct = kni_sk_destruct; q->flags = IFF_NO_PI | IFF_TAP; q->vnet_hdr_sz = sizeof(struct virtio_net_hdr); #ifdef RTE_KNI_VHOST_VNET_HDR_EN q->flags |= IFF_VNET_HDR; #endif /* bind kni_dev with vhost_queue */ q->kni = kni; kni->vhost_queue = q; wmb(); kni->vq_status = BE_START; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) KNI_DBG("backend init sockfd=%d, sock->wq=0x%16llx," "sk->sk_wq=0x%16llx", q->sockfd, (uint64_t)q->sock->wq, (uint64_t)q->sk.sk_wq); #else KNI_DBG("backend init sockfd=%d, sock->wait at 0x%16llx," "sk->sk_sleep=0x%16llx", q->sockfd, (uint64_t)&q->sock->wait, (uint64_t)q->sk.sk_sleep); #endif return 0; free_cache: kfree(q->cache); q->cache = NULL; free_fd: put_unused_fd(sockfd); free_sock: q->kni = NULL; kni->vhost_queue = NULL; kni->vq_status |= BE_FINISH; sock_release(q->sock); q->sock->ops = NULL; q->sock = NULL; free_sk: sk_free((struct sock*)q); return err; } /* kni vhost sock sysfs */ static ssize_t show_sock_fd(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *net_dev = container_of(dev, struct net_device, dev); struct kni_dev *kni = netdev_priv(net_dev); int sockfd = -1; if (kni->vhost_queue != NULL) sockfd = kni->vhost_queue->sockfd; return snprintf(buf, 10, "%d\n", sockfd); } static ssize_t show_sock_en(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *net_dev = container_of(dev, struct net_device, dev); struct kni_dev *kni = netdev_priv(net_dev); return snprintf(buf, 10, "%u\n", (kni->vhost_queue == NULL ? 0 : 1)); } static ssize_t set_sock_en(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct net_device *net_dev = container_of(dev, struct net_device, dev); struct kni_dev *kni = netdev_priv(net_dev); unsigned long en; int err = 0; if (0 != kstrtoul(buf, 0, &en)) return -EINVAL; if (en) err = kni_vhost_backend_init(kni); return err ? err : count; } static DEVICE_ATTR(sock_fd, S_IRUGO | S_IRUSR, show_sock_fd, NULL); static DEVICE_ATTR(sock_en, S_IRUGO | S_IWUSR, show_sock_en, set_sock_en); static struct attribute *dev_attrs[] = { &dev_attr_sock_fd.attr, &dev_attr_sock_en.attr, NULL, }; static const struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; int kni_vhost_backend_release(struct kni_dev *kni) { struct kni_vhost_queue *q = kni->vhost_queue; if (q == NULL) return 0; /* dettach from kni */ q->kni = NULL; KNI_DBG("release backend done\n"); return 0; } int kni_vhost_init(struct kni_dev *kni) { struct net_device *dev = kni->net_dev; if (sysfs_create_group(&dev->dev.kobj, &dev_attr_grp)) sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); kni->vq_status = BE_STOP; KNI_DBG("kni_vhost_init done\n"); return 0; } ================================================ FILE: lib/librte_eal/linuxapp/xen_dom0/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # module name and path # MODULE = rte_dom0_mm # # CFLAGS # MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=50 MODULE_CFLAGS += -I$(RTE_OUTPUT)/include MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h MODULE_CFLAGS += -Wall -Werror # this lib needs main eal DEPDIRS-y += lib/librte_eal/linuxapp/eal # # all source are stored in SRCS-y # SRCS-y += dom0_mm_misc.c include $(RTE_SDK)/mk/rte.module.mk ================================================ FILE: lib/librte_eal/linuxapp/xen_dom0/compat.h ================================================ /* * Minimal wrappers to allow compiling xen_dom0 on older kernels. */ #ifndef RHEL_RELEASE_VERSION #define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \ (!(defined(RHEL_RELEASE_CODE) && \ RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4))) #define kstrtoul strict_strtoul #endif /* < 2.6.39 */ ================================================ FILE: lib/librte_eal/linuxapp/xen_dom0/dom0_mm_dev.h ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _DOM0_MM_DEV_H_ #define _DOM0_MM_DEV_H_ #include #include #include #include #include #define NUM_MEM_CTX 256 /**< Maximum number of memory context*/ #define MAX_EXCHANGE_FAIL_TIME 5 /**< Maximum times of allowing exchange fail .*/ #define MAX_MEMBLOCK_SIZE (2 * DOM0_MEMBLOCK_SIZE) #define MAX_NUM_ORDER (DOM0_CONTIG_NUM_ORDER + 1) #define SIZE_PER_BLOCK 2 /** < size of per memory block(2MB)).*/ /** * A structure describing the private information for a dom0 device. */ struct dom0_mm_dev { struct miscdevice miscdev; uint8_t fail_times; uint32_t used_memsize; uint32_t num_mem_ctx; uint32_t config_memsize; uint32_t num_bigblock; struct dom0_mm_data *mm_data[NUM_MEM_CTX]; struct mutex data_lock; }; struct dom0_mm_data{ uint32_t refcnt; uint32_t num_memseg; /**< Number of memory segment. */ uint32_t mem_size; /**< Size of requesting memory. */ char name[DOM0_NAME_MAX]; /** Store global memory block IDs used by an instance */ uint32_t block_num[DOM0_NUM_MEMBLOCK]; /** Store memory block information.*/ struct memblock_info block_info[DOM0_NUM_MEMBLOCK]; /** Store memory segment information.*/ struct memseg_info seg_info[DOM0_NUM_MEMSEG]; }; #define XEN_ERR(args...) printk(KERN_DEBUG "XEN_DOM0: Error: " args) #define XEN_PRINT(args...) printk(KERN_DEBUG "XEN_DOM0: " args) #endif ================================================ FILE: lib/librte_eal/linuxapp/xen_dom0/dom0_mm_misc.c ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "compat.h" #include "dom0_mm_dev.h" MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("Kernel Module for supporting DPDK running on Xen Dom0"); static struct dom0_mm_dev dom0_dev; static struct kobject *dom0_kobj = NULL; static struct memblock_info *rsv_mm_info; /* Default configuration for reserved memory size(2048 MB). */ static uint32_t rsv_memsize = 2048; static int dom0_open(struct inode *inode, struct file *file); static int dom0_release(struct inode *inode, struct file *file); static int dom0_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param); static int dom0_mmap(struct file *file, struct vm_area_struct *vma); static int dom0_memory_free(uint32_t size); static int dom0_memory_release(struct dom0_mm_data *mm_data); static const struct file_operations data_fops = { .owner = THIS_MODULE, .open = dom0_open, .release = dom0_release, .mmap = dom0_mmap, .unlocked_ioctl = (void *)dom0_ioctl, }; static ssize_t show_memsize_rsvd(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, 10, "%u\n", dom0_dev.used_memsize); } static ssize_t show_memsize(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, 10, "%u\n", dom0_dev.config_memsize); } static ssize_t store_memsize(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err = 0; unsigned long mem_size; if (0 != kstrtoul(buf, 0, &mem_size)) return -EINVAL; mutex_lock(&dom0_dev.data_lock); if (0 == mem_size) { err = -EINVAL; goto fail; } else if (mem_size > (rsv_memsize - dom0_dev.used_memsize)) { XEN_ERR("configure memory size fail\n"); err = -EINVAL; goto fail; } else dom0_dev.config_memsize = mem_size; fail: mutex_unlock(&dom0_dev.data_lock); return err ? err : count; } static DEVICE_ATTR(memsize, S_IRUGO | S_IWUSR, show_memsize, store_memsize); static DEVICE_ATTR(memsize_rsvd, S_IRUGO, show_memsize_rsvd, NULL); static struct attribute *dev_attrs[] = { &dev_attr_memsize.attr, &dev_attr_memsize_rsvd.attr, NULL, }; /* the memory size unit is MB */ static const struct attribute_group dev_attr_grp = { .name = "memsize-mB", .attrs = dev_attrs, }; static void sort_viraddr(struct memblock_info *mb, int cnt) { int i,j; uint64_t tmp_pfn; uint64_t tmp_viraddr; /*sort virtual address and pfn */ for(i = 0; i < cnt; i ++) { for(j = cnt - 1; j > i; j--) { if(mb[j].pfn < mb[j - 1].pfn) { tmp_pfn = mb[j - 1].pfn; mb[j - 1].pfn = mb[j].pfn; mb[j].pfn = tmp_pfn; tmp_viraddr = mb[j - 1].vir_addr; mb[j - 1].vir_addr = mb[j].vir_addr; mb[j].vir_addr = tmp_viraddr; } } } } static int dom0_find_memdata(const char * mem_name) { unsigned i; int idx = -1; for(i = 0; i< NUM_MEM_CTX; i++) { if(dom0_dev.mm_data[i] == NULL) continue; if (!strncmp(dom0_dev.mm_data[i]->name, mem_name, sizeof(char) * DOM0_NAME_MAX)) { idx = i; break; } } return idx; } static int dom0_find_mempos(void) { unsigned i; int idx = -1; for(i = 0; i< NUM_MEM_CTX; i++) { if(dom0_dev.mm_data[i] == NULL){ idx = i; break; } } return idx; } static int dom0_memory_release(struct dom0_mm_data *mm_data) { int idx; uint32_t num_block, block_id; /* each memory block is 2M */ num_block = mm_data->mem_size / SIZE_PER_BLOCK; if (num_block == 0) return -EINVAL; /* reset global memory data */ idx = dom0_find_memdata(mm_data->name); if (idx >= 0) { dom0_dev.used_memsize -= mm_data->mem_size; dom0_dev.mm_data[idx] = NULL; dom0_dev.num_mem_ctx--; } /* reset these memory blocks status as free */ for (idx = 0; idx < num_block; idx++) { block_id = mm_data->block_num[idx]; rsv_mm_info[block_id].used = 0; } memset(mm_data, 0, sizeof(struct dom0_mm_data)); vfree(mm_data); return 0; } static int dom0_memory_free(uint32_t rsv_size) { uint64_t vstart, vaddr; uint32_t i, num_block, size; if (!xen_pv_domain()) return -1; /* each memory block is 2M */ num_block = rsv_size / SIZE_PER_BLOCK; if (num_block == 0) return -EINVAL; /* free all memory blocks of size of 4M and destroy contiguous region */ for (i = 0; i < dom0_dev.num_bigblock * 2; i += 2) { vstart = rsv_mm_info[i].vir_addr; if (vstart) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) if (rsv_mm_info[i].exchange_flag) xen_destroy_contiguous_region(vstart, DOM0_CONTIG_NUM_ORDER); if (rsv_mm_info[i + 1].exchange_flag) xen_destroy_contiguous_region(vstart + DOM0_MEMBLOCK_SIZE, DOM0_CONTIG_NUM_ORDER); #else if (rsv_mm_info[i].exchange_flag) xen_destroy_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE, DOM0_CONTIG_NUM_ORDER); if (rsv_mm_info[i + 1].exchange_flag) xen_destroy_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE + DOM0_MEMBLOCK_SIZE, DOM0_CONTIG_NUM_ORDER); #endif size = DOM0_MEMBLOCK_SIZE * 2; vaddr = vstart; while (size > 0) { ClearPageReserved(virt_to_page(vaddr)); vaddr += PAGE_SIZE; size -= PAGE_SIZE; } free_pages(vstart, MAX_NUM_ORDER); } } /* free all memory blocks size of 2M and destroy contiguous region */ for (; i < num_block; i++) { vstart = rsv_mm_info[i].vir_addr; if (vstart) { if (rsv_mm_info[i].exchange_flag) xen_destroy_contiguous_region(vstart, DOM0_CONTIG_NUM_ORDER); size = DOM0_MEMBLOCK_SIZE; vaddr = vstart; while (size > 0) { ClearPageReserved(virt_to_page(vaddr)); vaddr += PAGE_SIZE; size -= PAGE_SIZE; } free_pages(vstart, DOM0_CONTIG_NUM_ORDER); } } memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block); vfree(rsv_mm_info); rsv_mm_info = NULL; return 0; } static void find_free_memory(uint32_t count, struct dom0_mm_data *mm_data) { uint32_t i = 0; uint32_t j = 0; while ((i < count) && (j < rsv_memsize / SIZE_PER_BLOCK)) { if (rsv_mm_info[j].used == 0) { mm_data->block_info[i].pfn = rsv_mm_info[j].pfn; mm_data->block_info[i].vir_addr = rsv_mm_info[j].vir_addr; mm_data->block_info[i].mfn = rsv_mm_info[j].mfn; mm_data->block_info[i].exchange_flag = rsv_mm_info[j].exchange_flag; mm_data->block_num[i] = j; rsv_mm_info[j].used = 1; i++; } j++; } } /** * Find all memory segments in which physical addresses are contiguous. */ static void find_memseg(int count, struct dom0_mm_data * mm_data) { int i = 0; int j, k, idx = 0; uint64_t zone_len, pfn, num_block; while(i < count) { if (mm_data->block_info[i].exchange_flag == 0) { i++; continue; } k = 0; pfn = mm_data->block_info[i].pfn; mm_data->seg_info[idx].pfn = pfn; mm_data->seg_info[idx].mfn[k] = mm_data->block_info[i].mfn; for (j = i + 1; j < count; j++) { /* ignore exchange fail memory block */ if (mm_data->block_info[j].exchange_flag == 0) break; if (mm_data->block_info[j].pfn != (mm_data->block_info[j - 1].pfn + DOM0_MEMBLOCK_SIZE / PAGE_SIZE)) break; ++k; mm_data->seg_info[idx].mfn[k] = mm_data->block_info[j].mfn; } num_block = j - i; zone_len = num_block * DOM0_MEMBLOCK_SIZE; mm_data->seg_info[idx].size = zone_len; XEN_PRINT("memseg id=%d, size=0x%llx\n", idx, zone_len); i = i+ num_block; idx++; if (idx == DOM0_NUM_MEMSEG) break; } mm_data->num_memseg = idx; } static int dom0_memory_reserve(uint32_t rsv_size) { uint64_t pfn, vstart, vaddr; uint32_t i, num_block, size, allocated_size = 0; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) dma_addr_t dma_handle; #endif /* 2M as memory block */ num_block = rsv_size / SIZE_PER_BLOCK; rsv_mm_info = vmalloc(sizeof(struct memblock_info) * num_block); if (!rsv_mm_info) { XEN_ERR("Unable to allocate device memory information\n"); return -ENOMEM; } memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block); /* try alloc size of 4M once */ for (i = 0; i < num_block; i += 2) { vstart = (unsigned long) __get_free_pages(GFP_ATOMIC, MAX_NUM_ORDER); if (vstart == 0) break; dom0_dev.num_bigblock = i / 2 + 1; allocated_size = SIZE_PER_BLOCK * (i + 2); /* size of 4M */ size = DOM0_MEMBLOCK_SIZE * 2; vaddr = vstart; while (size > 0) { SetPageReserved(virt_to_page(vaddr)); vaddr += PAGE_SIZE; size -= PAGE_SIZE; } pfn = virt_to_pfn(vstart); rsv_mm_info[i].pfn = pfn; rsv_mm_info[i].vir_addr = vstart; rsv_mm_info[i + 1].pfn = pfn + DOM0_MEMBLOCK_SIZE / PAGE_SIZE; rsv_mm_info[i + 1].vir_addr = vstart + DOM0_MEMBLOCK_SIZE; } /*if it failed to alloc 4M, and continue to alloc 2M once */ for (; i < num_block; i++) { vstart = (unsigned long) __get_free_pages(GFP_ATOMIC, DOM0_CONTIG_NUM_ORDER); if (vstart == 0) { XEN_ERR("allocate memory fail.\n"); dom0_memory_free(allocated_size); return -ENOMEM; } allocated_size += SIZE_PER_BLOCK; size = DOM0_MEMBLOCK_SIZE; vaddr = vstart; while (size > 0) { SetPageReserved(virt_to_page(vaddr)); vaddr += PAGE_SIZE; size -= PAGE_SIZE; } pfn = virt_to_pfn(vstart); rsv_mm_info[i].pfn = pfn; rsv_mm_info[i].vir_addr = vstart; } sort_viraddr(rsv_mm_info, num_block); for (i = 0; i< num_block; i++) { /* * This API is used to exchage MFN for getting a block of * contiguous physical addresses, its maximum size is 2M. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) if (xen_create_contiguous_region(rsv_mm_info[i].vir_addr, DOM0_CONTIG_NUM_ORDER, 0) == 0) { #else if (xen_create_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE, DOM0_CONTIG_NUM_ORDER, 0, &dma_handle) == 0) { #endif rsv_mm_info[i].exchange_flag = 1; rsv_mm_info[i].mfn = pfn_to_mfn(rsv_mm_info[i].pfn); rsv_mm_info[i].used = 0; } else { XEN_ERR("exchange memeory fail\n"); rsv_mm_info[i].exchange_flag = 0; dom0_dev.fail_times++; if (dom0_dev.fail_times > MAX_EXCHANGE_FAIL_TIME) { dom0_memory_free(rsv_size); return -EFAULT; } } } return 0; } static int dom0_prepare_memsegs(struct memory_info *meminfo, struct dom0_mm_data *mm_data) { uint32_t num_block; int idx; /* check if there is a free name buffer */ memcpy(mm_data->name, meminfo->name, DOM0_NAME_MAX); mm_data->name[DOM0_NAME_MAX - 1] = '\0'; idx = dom0_find_mempos(); if (idx < 0) return -1; num_block = meminfo->size / SIZE_PER_BLOCK; /* find free memory and new memory segments*/ find_free_memory(num_block, mm_data); find_memseg(num_block, mm_data); /* update private memory data */ mm_data->refcnt++; mm_data->mem_size = meminfo->size; /* update global memory data */ dom0_dev.mm_data[idx] = mm_data; dom0_dev.num_mem_ctx++; dom0_dev.used_memsize += mm_data->mem_size; return 0; } static int dom0_check_memory (struct memory_info *meminfo) { int idx; uint64_t mem_size; /* round memory size to the next even number. */ if (meminfo->size % 2) ++meminfo->size; mem_size = meminfo->size; if (dom0_dev.num_mem_ctx > NUM_MEM_CTX) { XEN_ERR("Memory data space is full in Dom0 driver\n"); return -1; } idx = dom0_find_memdata(meminfo->name); if (idx >= 0) { XEN_ERR("Memory data name %s has already exsited in Dom0 driver.\n", meminfo->name); return -1; } if ((dom0_dev.used_memsize + mem_size) > rsv_memsize) { XEN_ERR("Total size can't be larger than reserved size.\n"); return -1; } return 0; } static int __init dom0_init(void) { if (!xen_domain()) return -ENODEV; if (rsv_memsize > DOM0_CONFIG_MEMSIZE) { XEN_ERR("The reserved memory size cannot be greater than %d\n", DOM0_CONFIG_MEMSIZE); return -EINVAL; } /* Setup the misc device */ dom0_dev.miscdev.minor = MISC_DYNAMIC_MINOR; dom0_dev.miscdev.name = "dom0_mm"; dom0_dev.miscdev.fops = &data_fops; /* register misc char device */ if (misc_register(&dom0_dev.miscdev) != 0) { XEN_ERR("Misc device registration failed\n"); return -EPERM; } mutex_init(&dom0_dev.data_lock); dom0_kobj = kobject_create_and_add("dom0-mm", mm_kobj); if (!dom0_kobj) { XEN_ERR("dom0-mm object creation failed\n"); misc_deregister(&dom0_dev.miscdev); return -ENOMEM; } if (sysfs_create_group(dom0_kobj, &dev_attr_grp)) { kobject_put(dom0_kobj); misc_deregister(&dom0_dev.miscdev); return -EPERM; } if (dom0_memory_reserve(rsv_memsize) < 0) { sysfs_remove_group(dom0_kobj, &dev_attr_grp); kobject_put(dom0_kobj); misc_deregister(&dom0_dev.miscdev); return -ENOMEM; } XEN_PRINT("####### DPDK Xen Dom0 module loaded #######\n"); return 0; } static void __exit dom0_exit(void) { if (rsv_mm_info != NULL) dom0_memory_free(rsv_memsize); sysfs_remove_group(dom0_kobj, &dev_attr_grp); kobject_put(dom0_kobj); misc_deregister(&dom0_dev.miscdev); XEN_PRINT("####### DPDK Xen Dom0 module unloaded #######\n"); } static int dom0_open(struct inode *inode, struct file *file) { file->private_data = NULL; XEN_PRINT(KERN_INFO "/dev/dom0_mm opened\n"); return 0; } static int dom0_release(struct inode *inode, struct file *file) { int ret = 0; struct dom0_mm_data *mm_data = file->private_data; if (mm_data == NULL) return ret; mutex_lock(&dom0_dev.data_lock); if (--mm_data->refcnt == 0) ret = dom0_memory_release(mm_data); mutex_unlock(&dom0_dev.data_lock); file->private_data = NULL; XEN_PRINT(KERN_INFO "/dev/dom0_mm closed\n"); return ret; } static int dom0_mmap(struct file *file, struct vm_area_struct *vm) { int status = 0; uint32_t idx = vm->vm_pgoff; uint64_t pfn, size = vm->vm_end - vm->vm_start; struct dom0_mm_data *mm_data = file->private_data; if(mm_data == NULL) return -EINVAL; mutex_lock(&dom0_dev.data_lock); if (idx >= mm_data->num_memseg) { mutex_unlock(&dom0_dev.data_lock); return -EINVAL; } if (size > mm_data->seg_info[idx].size){ mutex_unlock(&dom0_dev.data_lock); return -EINVAL; } XEN_PRINT("mmap memseg idx =%d,size = 0x%llx\n", idx, size); pfn = mm_data->seg_info[idx].pfn; mutex_unlock(&dom0_dev.data_lock); status = remap_pfn_range(vm, vm->vm_start, pfn, size, PAGE_SHARED); return status; } static int dom0_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { int idx, ret; char name[DOM0_NAME_MAX] = {0}; struct memory_info meminfo; struct dom0_mm_data *mm_data = file->private_data; XEN_PRINT("IOCTL num=0x%0x param=0x%0lx \n", ioctl_num, ioctl_param); /** * Switch according to the ioctl called */ switch _IOC_NR(ioctl_num) { case _IOC_NR(RTE_DOM0_IOCTL_PREPARE_MEMSEG): ret = copy_from_user(&meminfo, (void *)ioctl_param, sizeof(struct memory_info)); if (ret) return -EFAULT; if (mm_data != NULL) { XEN_ERR("Cannot create memory segment for the same" " file descriptor\n"); return -EINVAL; } /* Allocate private data */ mm_data = vmalloc(sizeof(struct dom0_mm_data)); if (!mm_data) { XEN_ERR("Unable to allocate device private data\n"); return -ENOMEM; } memset(mm_data, 0, sizeof(struct dom0_mm_data)); mutex_lock(&dom0_dev.data_lock); /* check if we can allocate memory*/ if (dom0_check_memory(&meminfo) < 0) { mutex_unlock(&dom0_dev.data_lock); vfree(mm_data); return -EINVAL; } /* allocate memory and created memory segments*/ if (dom0_prepare_memsegs(&meminfo, mm_data) < 0) { XEN_ERR("create memory segment fail.\n"); mutex_unlock(&dom0_dev.data_lock); return -EIO; } file->private_data = mm_data; mutex_unlock(&dom0_dev.data_lock); break; /* support multiple process in term of memory mapping*/ case _IOC_NR(RTE_DOM0_IOCTL_ATTACH_TO_MEMSEG): ret = copy_from_user(name, (void *)ioctl_param, sizeof(char) * DOM0_NAME_MAX); if (ret) return -EFAULT; mutex_lock(&dom0_dev.data_lock); idx = dom0_find_memdata(name); if (idx < 0) { mutex_unlock(&dom0_dev.data_lock); return -EINVAL; } mm_data = dom0_dev.mm_data[idx]; mm_data->refcnt++; file->private_data = mm_data; mutex_unlock(&dom0_dev.data_lock); break; case _IOC_NR(RTE_DOM0_IOCTL_GET_NUM_MEMSEG): ret = copy_to_user((void *)ioctl_param, &mm_data->num_memseg, sizeof(int)); if (ret) return -EFAULT; break; case _IOC_NR(RTE_DOM0_IOCTL_GET_MEMSEG_INFO): ret = copy_to_user((void *)ioctl_param, &mm_data->seg_info[0], sizeof(struct memseg_info) * mm_data->num_memseg); if (ret) return -EFAULT; break; default: XEN_PRINT("IOCTL default \n"); break; } return 0; } module_init(dom0_init); module_exit(dom0_exit); module_param(rsv_memsize, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(rsv_memsize, "Xen-dom0 reserved memory size(MB).\n"); ================================================ FILE: lib/librte_ether/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = libethdev.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_ether_version.map LIBABIVER := 1 SRCS-y += rte_ethdev.c # # Export include files # SYMLINK-y-include += rte_ether.h SYMLINK-y-include += rte_ethdev.h SYMLINK-y-include += rte_eth_ctrl.h SYMLINK-y-include += rte_dev_info.h # this lib depends upon: DEPDIRS-y += lib/librte_eal lib/librte_mempool lib/librte_ring lib/librte_mbuf include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_ether/rte_dev_info.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_DEV_INFO_H_ #define _RTE_DEV_INFO_H_ /* * Placeholder for accessing device registers */ struct rte_dev_reg_info { void *data; /**< Buffer for return registers */ uint32_t offset; /**< Start register table location for access */ uint32_t length; /**< Number of registers to fetch */ uint32_t version; /**< Device version */ }; /* * Placeholder for accessing device eeprom */ struct rte_dev_eeprom_info { void *data; /**< Buffer for return eeprom */ uint32_t offset; /**< Start eeprom address for access*/ uint32_t length; /**< Length of eeprom region to access */ uint32_t magic; /**< Device-specific key, such as device-id */ }; #endif /* _RTE_DEV_INFO_H_ */ ================================================ FILE: lib/librte_ether/rte_eth_ctrl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETH_CTRL_H_ #define _RTE_ETH_CTRL_H_ /** * @file * * Ethernet device features and related data structures used * by control APIs should be defined in this file. * */ #ifdef __cplusplus extern "C" { #endif /* * A packet can be identified by hardware as different flow types. Different * NIC hardwares may support different flow types. * Basically, the NIC hardware identifies the flow type as deep protocol as * possible, and exclusively. For example, if a packet is identified as * 'RTE_ETH_FLOW_NONFRAG_IPV4_TCP', it will not be any of other flow types, * though it is an actual IPV4 packet. * Note that the flow types are used to define RSS offload types in * rte_ethdev.h. */ #define RTE_ETH_FLOW_UNKNOWN 0 #define RTE_ETH_FLOW_RAW 1 #define RTE_ETH_FLOW_IPV4 2 #define RTE_ETH_FLOW_FRAG_IPV4 3 #define RTE_ETH_FLOW_NONFRAG_IPV4_TCP 4 #define RTE_ETH_FLOW_NONFRAG_IPV4_UDP 5 #define RTE_ETH_FLOW_NONFRAG_IPV4_SCTP 6 #define RTE_ETH_FLOW_NONFRAG_IPV4_OTHER 7 #define RTE_ETH_FLOW_IPV6 8 #define RTE_ETH_FLOW_FRAG_IPV6 9 #define RTE_ETH_FLOW_NONFRAG_IPV6_TCP 10 #define RTE_ETH_FLOW_NONFRAG_IPV6_UDP 11 #define RTE_ETH_FLOW_NONFRAG_IPV6_SCTP 12 #define RTE_ETH_FLOW_NONFRAG_IPV6_OTHER 13 #define RTE_ETH_FLOW_L2_PAYLOAD 14 #define RTE_ETH_FLOW_IPV6_EX 15 #define RTE_ETH_FLOW_IPV6_TCP_EX 16 #define RTE_ETH_FLOW_IPV6_UDP_EX 17 #define RTE_ETH_FLOW_MAX 18 /** * Feature filter types */ enum rte_filter_type { RTE_ETH_FILTER_NONE = 0, RTE_ETH_FILTER_MACVLAN, RTE_ETH_FILTER_ETHERTYPE, RTE_ETH_FILTER_FLEXIBLE, RTE_ETH_FILTER_SYN, RTE_ETH_FILTER_NTUPLE, RTE_ETH_FILTER_TUNNEL, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_MAX }; /** * Generic operations on filters */ enum rte_filter_op { /** used to check whether the type filter is supported */ RTE_ETH_FILTER_NOP = 0, RTE_ETH_FILTER_ADD, /**< add filter entry */ RTE_ETH_FILTER_UPDATE, /**< update filter entry */ RTE_ETH_FILTER_DELETE, /**< delete filter entry */ RTE_ETH_FILTER_FLUSH, /**< flush all entries */ RTE_ETH_FILTER_GET, /**< get filter entry */ RTE_ETH_FILTER_SET, /**< configurations */ RTE_ETH_FILTER_INFO, /**< retrieve information */ RTE_ETH_FILTER_STATS, /**< retrieve statistics */ RTE_ETH_FILTER_OP_MAX }; /** * MAC filter type */ enum rte_mac_filter_type { RTE_MAC_PERFECT_MATCH = 1, /**< exact match of MAC addr. */ RTE_MACVLAN_PERFECT_MATCH, /**< exact match of MAC addr and VLAN ID. */ RTE_MAC_HASH_MATCH, /**< hash match of MAC addr. */ /** hash match of MAC addr and exact match of VLAN ID. */ RTE_MACVLAN_HASH_MATCH, }; /** * MAC filter info */ struct rte_eth_mac_filter { uint8_t is_vf; /**< 1 for VF, 0 for port dev */ uint16_t dst_id; /**< VF ID, available when is_vf is 1*/ enum rte_mac_filter_type filter_type; /**< MAC filter type */ struct ether_addr mac_addr; }; /** * Define all structures for Ethertype Filter type. */ #define RTE_ETHTYPE_FLAGS_MAC 0x0001 /**< If set, compare mac */ #define RTE_ETHTYPE_FLAGS_DROP 0x0002 /**< If set, drop packet when match */ /** * A structure used to define the ethertype filter entry * to support RTE_ETH_FILTER_ETHERTYPE with RTE_ETH_FILTER_ADD, * RTE_ETH_FILTER_DELETE and RTE_ETH_FILTER_GET operations. */ struct rte_eth_ethertype_filter { struct ether_addr mac_addr; /**< Mac address to match. */ uint16_t ether_type; /**< Ether type to match */ uint16_t flags; /**< Flags from RTE_ETHTYPE_FLAGS_* */ uint16_t queue; /**< Queue assigned to when match*/ }; #define RTE_FLEX_FILTER_MAXLEN 128 /**< bytes to use in flex filter. */ #define RTE_FLEX_FILTER_MASK_SIZE \ (RTE_ALIGN(RTE_FLEX_FILTER_MAXLEN, CHAR_BIT) / CHAR_BIT) /**< mask bytes in flex filter. */ /** * A structure used to define the flex filter entry * to support RTE_ETH_FILTER_FLEXIBLE with RTE_ETH_FILTER_ADD, * RTE_ETH_FILTER_DELETE and RTE_ETH_FILTER_GET operations. */ struct rte_eth_flex_filter { uint16_t len; uint8_t bytes[RTE_FLEX_FILTER_MAXLEN]; /**< flex bytes in big endian.*/ uint8_t mask[RTE_FLEX_FILTER_MASK_SIZE]; /**< if mask bit is 1b, do not compare corresponding byte. */ uint8_t priority; uint16_t queue; /**< Queue assigned to when match. */ }; /** * A structure used to define the TCP syn filter entry * to support RTE_ETH_FILTER_SYN with RTE_ETH_FILTER_ADD, * RTE_ETH_FILTER_DELETE and RTE_ETH_FILTER_GET operations. */ struct rte_eth_syn_filter { uint8_t hig_pri; /**< 1 - higher priority than other filters, 0 - lower priority. */ uint16_t queue; /**< Queue assigned to when match */ }; /** * Define all structures for ntuple Filter type. */ #define RTE_NTUPLE_FLAGS_DST_IP 0x0001 /**< If set, dst_ip is part of ntuple */ #define RTE_NTUPLE_FLAGS_SRC_IP 0x0002 /**< If set, src_ip is part of ntuple */ #define RTE_NTUPLE_FLAGS_DST_PORT 0x0004 /**< If set, dst_port is part of ntuple */ #define RTE_NTUPLE_FLAGS_SRC_PORT 0x0008 /**< If set, src_port is part of ntuple */ #define RTE_NTUPLE_FLAGS_PROTO 0x0010 /**< If set, protocol is part of ntuple */ #define RTE_NTUPLE_FLAGS_TCP_FLAG 0x0020 /**< If set, tcp flag is involved */ #define RTE_5TUPLE_FLAGS ( \ RTE_NTUPLE_FLAGS_DST_IP | \ RTE_NTUPLE_FLAGS_SRC_IP | \ RTE_NTUPLE_FLAGS_DST_PORT | \ RTE_NTUPLE_FLAGS_SRC_PORT | \ RTE_NTUPLE_FLAGS_PROTO) #define RTE_2TUPLE_FLAGS ( \ RTE_NTUPLE_FLAGS_DST_PORT | \ RTE_NTUPLE_FLAGS_PROTO) #define TCP_URG_FLAG 0x20 #define TCP_ACK_FLAG 0x10 #define TCP_PSH_FLAG 0x08 #define TCP_RST_FLAG 0x04 #define TCP_SYN_FLAG 0x02 #define TCP_FIN_FLAG 0x01 #define TCP_FLAG_ALL 0x3F /** * A structure used to define the ntuple filter entry * to support RTE_ETH_FILTER_NTUPLE with RTE_ETH_FILTER_ADD, * RTE_ETH_FILTER_DELETE and RTE_ETH_FILTER_GET operations. */ struct rte_eth_ntuple_filter { uint16_t flags; /**< Flags from RTE_NTUPLE_FLAGS_* */ uint32_t dst_ip; /**< Destination IP address in big endian. */ uint32_t dst_ip_mask; /**< Mask of destination IP address. */ uint32_t src_ip; /**< Source IP address in big endian. */ uint32_t src_ip_mask; /**< Mask of destination IP address. */ uint16_t dst_port; /**< Destination port in big endian. */ uint16_t dst_port_mask; /**< Mask of destination port. */ uint16_t src_port; /**< Source Port in big endian. */ uint16_t src_port_mask; /**< Mask of source port. */ uint8_t proto; /**< L4 protocol. */ uint8_t proto_mask; /**< Mask of L4 protocol. */ /** tcp_flags only meaningful when the proto is TCP. The packet matched above ntuple fields and contain any set bit in tcp_flags will hit this filter. */ uint8_t tcp_flags; uint16_t priority; /**< seven levels (001b-111b), 111b is highest, used when more than one filter matches. */ uint16_t queue; /**< Queue assigned to when match*/ }; /** * Tunneled type. */ enum rte_eth_tunnel_type { RTE_TUNNEL_TYPE_NONE = 0, RTE_TUNNEL_TYPE_VXLAN, RTE_TUNNEL_TYPE_GENEVE, RTE_TUNNEL_TYPE_TEREDO, RTE_TUNNEL_TYPE_NVGRE, RTE_TUNNEL_TYPE_MAX, }; /** * filter type of tunneling packet */ #define ETH_TUNNEL_FILTER_OMAC 0x01 /**< filter by outer MAC addr */ #define ETH_TUNNEL_FILTER_OIP 0x02 /**< filter by outer IP Addr */ #define ETH_TUNNEL_FILTER_TENID 0x04 /**< filter by tenant ID */ #define ETH_TUNNEL_FILTER_IMAC 0x08 /**< filter by inner MAC addr */ #define ETH_TUNNEL_FILTER_IVLAN 0x10 /**< filter by inner VLAN ID */ #define ETH_TUNNEL_FILTER_IIP 0x20 /**< filter by inner IP addr */ #define RTE_TUNNEL_FILTER_IMAC_IVLAN (ETH_TUNNEL_FILTER_IMAC | \ ETH_TUNNEL_FILTER_IVLAN) #define RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID (ETH_TUNNEL_FILTER_IMAC | \ ETH_TUNNEL_FILTER_IVLAN | \ ETH_TUNNEL_FILTER_TENID) #define RTE_TUNNEL_FILTER_IMAC_TENID (ETH_TUNNEL_FILTER_IMAC | \ ETH_TUNNEL_FILTER_TENID) #define RTE_TUNNEL_FILTER_OMAC_TENID_IMAC (ETH_TUNNEL_FILTER_OMAC | \ ETH_TUNNEL_FILTER_TENID | \ ETH_TUNNEL_FILTER_IMAC) /** * Select IPv4 or IPv6 for tunnel filters. */ enum rte_tunnel_iptype { RTE_TUNNEL_IPTYPE_IPV4 = 0, /**< IPv4. */ RTE_TUNNEL_IPTYPE_IPV6, /**< IPv6. */ }; /** * Tunneling Packet filter configuration. */ struct rte_eth_tunnel_filter_conf { struct ether_addr *outer_mac; /**< Outer MAC address filter. */ struct ether_addr *inner_mac; /**< Inner MAC address filter. */ uint16_t inner_vlan; /**< Inner VLAN filter. */ enum rte_tunnel_iptype ip_type; /**< IP address type. */ union { uint32_t ipv4_addr; /**< IPv4 source address to match. */ uint32_t ipv6_addr[4]; /**< IPv6 source address to match. */ } ip_addr; /**< IPv4/IPv6 source address to match (union of above). */ uint16_t filter_type; /**< Filter type. */ enum rte_eth_tunnel_type tunnel_type; /**< Tunnel Type. */ uint32_t tenant_id; /** < Tenant number. */ uint16_t queue_id; /** < queue number. */ }; #define RTE_ETH_FDIR_MAX_FLEXLEN 16 /** < Max length of flexbytes. */ /** * A structure used to define the input for L2 flow */ struct rte_eth_l2_flow { uint16_t ether_type; /**< Ether type to match */ }; /** * A structure used to define the input for IPV4 flow */ struct rte_eth_ipv4_flow { uint32_t src_ip; /**< IPv4 source address to match. */ uint32_t dst_ip; /**< IPv4 destination address to match. */ }; /** * A structure used to define the input for IPV4 UDP flow */ struct rte_eth_udpv4_flow { struct rte_eth_ipv4_flow ip; /**< IPv4 fields to match. */ uint16_t src_port; /**< UDP source port to match. */ uint16_t dst_port; /**< UDP destination port to match. */ }; /** * A structure used to define the input for IPV4 TCP flow */ struct rte_eth_tcpv4_flow { struct rte_eth_ipv4_flow ip; /**< IPv4 fields to match. */ uint16_t src_port; /**< TCP source port to match. */ uint16_t dst_port; /**< TCP destination port to match. */ }; /** * A structure used to define the input for IPV4 SCTP flow */ struct rte_eth_sctpv4_flow { struct rte_eth_ipv4_flow ip; /**< IPv4 fields to match. */ #ifdef RTE_NEXT_ABI uint16_t src_port; /**< SCTP source port to match. */ uint16_t dst_port; /**< SCTP destination port to match. */ #endif uint32_t verify_tag; /**< Verify tag to match */ }; /** * A structure used to define the input for IPV6 flow */ struct rte_eth_ipv6_flow { uint32_t src_ip[4]; /**< IPv6 source address to match. */ uint32_t dst_ip[4]; /**< IPv6 destination address to match. */ }; /** * A structure used to define the input for IPV6 UDP flow */ struct rte_eth_udpv6_flow { struct rte_eth_ipv6_flow ip; /**< IPv6 fields to match. */ uint16_t src_port; /**< UDP source port to match. */ uint16_t dst_port; /**< UDP destination port to match. */ }; /** * A structure used to define the input for IPV6 TCP flow */ struct rte_eth_tcpv6_flow { struct rte_eth_ipv6_flow ip; /**< IPv6 fields to match. */ uint16_t src_port; /**< TCP source port to match. */ uint16_t dst_port; /**< TCP destination port to match. */ }; /** * A structure used to define the input for IPV6 SCTP flow */ struct rte_eth_sctpv6_flow { struct rte_eth_ipv6_flow ip; /**< IPv6 fields to match. */ #ifdef RTE_NEXT_ABI uint16_t src_port; /**< SCTP source port to match. */ uint16_t dst_port; /**< SCTP destination port to match. */ #endif uint32_t verify_tag; /**< Verify tag to match */ }; /** * An union contains the inputs for all types of flow */ union rte_eth_fdir_flow { struct rte_eth_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; struct rte_eth_ipv4_flow ip4_flow; struct rte_eth_udpv6_flow udp6_flow; struct rte_eth_tcpv6_flow tcp6_flow; struct rte_eth_sctpv6_flow sctp6_flow; struct rte_eth_ipv6_flow ipv6_flow; }; /** * A structure used to contain extend input of flow */ struct rte_eth_fdir_flow_ext { uint16_t vlan_tci; uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN]; /**< It is filled by the flexible payload to match. */ }; /** * A structure used to define the input for a flow director filter entry */ struct rte_eth_fdir_input { uint16_t flow_type; union rte_eth_fdir_flow flow; /**< Flow fields to match, dependent on flow_type */ struct rte_eth_fdir_flow_ext flow_ext; /**< Additional fields to match */ }; /** * Behavior will be taken if FDIR match */ enum rte_eth_fdir_behavior { RTE_ETH_FDIR_ACCEPT = 0, RTE_ETH_FDIR_REJECT, }; /** * Flow director report status * It defines what will be reported if FDIR entry is matched. */ enum rte_eth_fdir_status { RTE_ETH_FDIR_NO_REPORT_STATUS = 0, /**< Report nothing. */ RTE_ETH_FDIR_REPORT_ID, /**< Only report FD ID. */ RTE_ETH_FDIR_REPORT_ID_FLEX_4, /**< Report FD ID and 4 flex bytes. */ RTE_ETH_FDIR_REPORT_FLEX_8, /**< Report 8 flex bytes. */ }; /** * A structure used to define an action when match FDIR packet filter. */ struct rte_eth_fdir_action { uint16_t rx_queue; /**< Queue assigned to if FDIR match. */ enum rte_eth_fdir_behavior behavior; /**< Behavior will be taken */ enum rte_eth_fdir_status report_status; /**< Status report option */ uint8_t flex_off; /**< If report_status is RTE_ETH_FDIR_REPORT_ID_FLEX_4 or RTE_ETH_FDIR_REPORT_FLEX_8, flex_off specifies where the reported flex bytes start from in flexible payload. */ }; /** * A structure used to define the flow director filter entry by filter_ctrl API * It supports RTE_ETH_FILTER_FDIR with RTE_ETH_FILTER_ADD and * RTE_ETH_FILTER_DELETE operations. */ struct rte_eth_fdir_filter { uint32_t soft_id; /**< ID, an unique value is required when deal with FDIR entry */ struct rte_eth_fdir_input input; /**< Input set */ struct rte_eth_fdir_action action; /**< Action taken when match */ }; /** * A structure used to configure FDIR masks that are used by the device * to match the various fields of RX packet headers. */ struct rte_eth_fdir_masks { uint16_t vlan_tci_mask; struct rte_eth_ipv4_flow ipv4_mask; struct rte_eth_ipv6_flow ipv6_mask; uint16_t src_port_mask; uint16_t dst_port_mask; }; /** * Payload type */ enum rte_eth_payload_type { RTE_ETH_PAYLOAD_UNKNOWN = 0, RTE_ETH_RAW_PAYLOAD, RTE_ETH_L2_PAYLOAD, RTE_ETH_L3_PAYLOAD, RTE_ETH_L4_PAYLOAD, RTE_ETH_PAYLOAD_MAX = 8, }; /** * A structure used to select bytes extracted from the protocol layers to * flexible payload for filter */ struct rte_eth_flex_payload_cfg { enum rte_eth_payload_type type; /**< Payload type */ uint16_t src_offset[RTE_ETH_FDIR_MAX_FLEXLEN]; /**< Offset in bytes from the beginning of packet's payload src_offset[i] indicates the flexbyte i's offset in original packet payload. This value should be less than flex_payload_limit in struct rte_eth_fdir_info.*/ }; /** * A structure used to define FDIR masks for flexible payload * for each flow type */ struct rte_eth_fdir_flex_mask { uint16_t flow_type; uint8_t mask[RTE_ETH_FDIR_MAX_FLEXLEN]; /**< Mask for the whole flexible payload */ }; /** * A structure used to define all flexible payload related setting * include flexpay load and flex mask */ struct rte_eth_fdir_flex_conf { uint16_t nb_payloads; /**< The number of following payload cfg */ uint16_t nb_flexmasks; /**< The number of following mask */ struct rte_eth_flex_payload_cfg flex_set[RTE_ETH_PAYLOAD_MAX]; /**< Flex payload configuration for each payload type */ struct rte_eth_fdir_flex_mask flex_mask[RTE_ETH_FLOW_MAX]; /**< Flex mask configuration for each flow type */ }; /** * Flow Director setting modes: none, signature or perfect. */ enum rte_fdir_mode { RTE_FDIR_MODE_NONE = 0, /**< Disable FDIR support. */ RTE_FDIR_MODE_SIGNATURE, /**< Enable FDIR signature filter mode. */ RTE_FDIR_MODE_PERFECT, /**< Enable FDIR perfect filter mode. */ }; #define UINT32_BIT (CHAR_BIT * sizeof(uint32_t)) #define RTE_FLOW_MASK_ARRAY_SIZE \ (RTE_ALIGN(RTE_ETH_FLOW_MAX, UINT32_BIT)/UINT32_BIT) /** * A structure used to get the information of flow director filter. * It supports RTE_ETH_FILTER_FDIR with RTE_ETH_FILTER_INFO operation. * It includes the mode, flexible payload configuration information, * capabilities and supported flow types, flexible payload characters. * It can be gotten to help taking specific configurations per device. */ struct rte_eth_fdir_info { enum rte_fdir_mode mode; /**< Flow director mode */ struct rte_eth_fdir_masks mask; /** Flex payload configuration information */ struct rte_eth_fdir_flex_conf flex_conf; uint32_t guarant_spc; /**< Guaranteed spaces.*/ uint32_t best_spc; /**< Best effort spaces.*/ /** Bit mask for every supported flow type. */ uint32_t flow_types_mask[RTE_FLOW_MASK_ARRAY_SIZE]; uint32_t max_flexpayload; /**< Total flex payload in bytes. */ /** Flexible payload unit in bytes. Size and alignments of all flex payload segments should be multiplies of this value. */ uint32_t flex_payload_unit; /** Max number of flexible payload continuous segments. Each segment should be a multiple of flex_payload_unit.*/ uint32_t max_flex_payload_segment_num; /** Maximum src_offset in bytes allowed. It indicates that src_offset[i] in struct rte_eth_flex_payload_cfg should be less than this value. */ uint16_t flex_payload_limit; /** Flex bitmask unit in bytes. Size of flex bitmasks should be a multiply of this value. */ uint32_t flex_bitmask_unit; /** Max supported size of flex bitmasks in flex_bitmask_unit */ uint32_t max_flex_bitmask_num; }; /** * A structure used to define the statistics of flow director. * It supports RTE_ETH_FILTER_FDIR with RTE_ETH_FILTER_STATS operation. */ struct rte_eth_fdir_stats { uint32_t collision; /**< Number of filters with collision. */ uint32_t free; /**< Number of free filters. */ uint32_t maxhash; /**< The lookup hash value of the added filter that updated the value of the MAXLEN field */ uint32_t maxlen; /**< Longest linked list of filters. */ uint64_t add; /**< Number of added filters. */ uint64_t remove; /**< Number of removed filters. */ uint64_t f_add; /**< Number of failed added filters. */ uint64_t f_remove; /**< Number of failed removed filters. */ uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */ uint32_t best_cnt; /**< Number of filters in best effort spaces. */ }; /** * Hash filter information types. * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT is for getting/setting the * information/configuration of 'symmetric hash enable' per port. * - RTE_ETH_HASH_FILTER_GLOBAL_CONFIG is for getting/setting the global * configurations of hash filters. Those global configurations are valid * for all ports of the same NIC. */ enum rte_eth_hash_filter_info_type { RTE_ETH_HASH_FILTER_INFO_TYPE_UNKNOWN = 0, /** Symmetric hash enable per port */ RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT, /** Configure globally for hash filter */ RTE_ETH_HASH_FILTER_GLOBAL_CONFIG, RTE_ETH_HASH_FILTER_INFO_TYPE_MAX, }; /** * Hash function types. */ enum rte_eth_hash_function { RTE_ETH_HASH_FUNCTION_DEFAULT = 0, RTE_ETH_HASH_FUNCTION_TOEPLITZ, /**< Toeplitz */ RTE_ETH_HASH_FUNCTION_SIMPLE_XOR, /**< Simple XOR */ RTE_ETH_HASH_FUNCTION_MAX, }; #define RTE_SYM_HASH_MASK_ARRAY_SIZE \ (RTE_ALIGN(RTE_ETH_FLOW_MAX, UINT32_BIT)/UINT32_BIT) /** * A structure used to set or get global hash function configurations which * include symmetric hash enable per flow type and hash function type. * Each bit in sym_hash_enable_mask[] indicates if the symmetric hash of the * coresponding flow type is enabled or not. * Each bit in valid_bit_mask[] indicates if the corresponding bit in * sym_hash_enable_mask[] is valid or not. For the configurations gotten, it * also means if the flow type is supported by hardware or not. */ struct rte_eth_hash_global_conf { enum rte_eth_hash_function hash_func; /**< Hash function type */ /** Bit mask for symmetric hash enable per flow type */ uint32_t sym_hash_enable_mask[RTE_SYM_HASH_MASK_ARRAY_SIZE]; /** Bit mask indicates if the corresponding bit is valid */ uint32_t valid_bit_mask[RTE_SYM_HASH_MASK_ARRAY_SIZE]; }; /** * A structure used to set or get hash filter information, to support filter * type of 'RTE_ETH_FILTER_HASH' and its operations. */ struct rte_eth_hash_filter_info { enum rte_eth_hash_filter_info_type info_type; /**< Information type */ /** Details of hash filter information */ union { /** For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT */ uint8_t enable; /** Global configurations of hash filter */ struct rte_eth_hash_global_conf global_conf; } info; }; #ifdef __cplusplus } #endif #endif /* _RTE_ETH_CTRL_H_ */ ================================================ FILE: lib/librte_ether/rte_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_ether.h" #include "rte_ethdev.h" #ifdef RTE_LIBRTE_ETHDEV_DEBUG #define PMD_DEBUG_TRACE(fmt, args...) do { \ RTE_LOG(ERR, PMD, "%s: " fmt, __func__, ## args); \ } while (0) #else #define PMD_DEBUG_TRACE(fmt, args...) #endif /* Macros for checking for restricting functions to primary instance only */ #define PROC_PRIMARY_OR_ERR_RET(retval) do { \ if (rte_eal_process_type() != RTE_PROC_PRIMARY) { \ PMD_DEBUG_TRACE("Cannot run in secondary processes\n"); \ return (retval); \ } \ } while (0) #define PROC_PRIMARY_OR_RET() do { \ if (rte_eal_process_type() != RTE_PROC_PRIMARY) { \ PMD_DEBUG_TRACE("Cannot run in secondary processes\n"); \ return; \ } \ } while (0) /* Macros to check for invalid function pointers in dev_ops structure */ #define FUNC_PTR_OR_ERR_RET(func, retval) do { \ if ((func) == NULL) { \ PMD_DEBUG_TRACE("Function not supported\n"); \ return (retval); \ } \ } while (0) #define FUNC_PTR_OR_RET(func) do { \ if ((func) == NULL) { \ PMD_DEBUG_TRACE("Function not supported\n"); \ return; \ } \ } while (0) /* Macros to check for valid port */ #define VALID_PORTID_OR_ERR_RET(port_id, retval) do { \ if (!rte_eth_dev_is_valid_port(port_id)) { \ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); \ return retval; \ } \ } while (0) #define VALID_PORTID_OR_RET(port_id) do { \ if (!rte_eth_dev_is_valid_port(port_id)) { \ PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); \ return; \ } \ } while (0) static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data"; struct rte_eth_dev rte_eth_devices[RTE_MAX_ETHPORTS]; static struct rte_eth_dev_data *rte_eth_dev_data; static uint8_t nb_ports; /* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER; /* store statistics names and its offset in stats structure */ struct rte_eth_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; }; static const struct rte_eth_xstats_name_off rte_stats_strings[] = { {"rx_packets", offsetof(struct rte_eth_stats, ipackets)}, {"tx_packets", offsetof(struct rte_eth_stats, opackets)}, {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)}, {"tx_bytes", offsetof(struct rte_eth_stats, obytes)}, {"tx_errors", offsetof(struct rte_eth_stats, oerrors)}, {"rx_errors", offsetof(struct rte_eth_stats, ierrors)}, {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)}, }; #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)}, {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)}, }; #define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) / \ sizeof(rte_rxq_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = { {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)}, {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)}, {"tx_errors", offsetof(struct rte_eth_stats, q_errors)}, }; #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \ sizeof(rte_txq_stats_strings[0])) /** * The user application callback description. * * It contains callback address to be registered by user application, * the pointer to the parameters for callback, and the event type. */ struct rte_eth_dev_callback { TAILQ_ENTRY(rte_eth_dev_callback) next; /**< Callbacks list */ rte_eth_dev_cb_fn cb_fn; /**< Callback address */ void *cb_arg; /**< Parameter for callback */ enum rte_eth_event_type event; /**< Interrupt event type */ uint32_t active; /**< Callback is executing */ }; enum { STAT_QMAP_TX = 0, STAT_QMAP_RX }; enum { DEV_DETACHED = 0, DEV_ATTACHED }; static void rte_eth_dev_data_alloc(void) { const unsigned flags = 0; const struct rte_memzone *mz; if (rte_eal_process_type() == RTE_PROC_PRIMARY) { mz = rte_memzone_reserve(MZ_RTE_ETH_DEV_DATA, RTE_MAX_ETHPORTS * sizeof(*rte_eth_dev_data), rte_socket_id(), flags); } else mz = rte_memzone_lookup(MZ_RTE_ETH_DEV_DATA); if (mz == NULL) rte_panic("Cannot allocate memzone for ethernet port data\n"); rte_eth_dev_data = mz->addr; if (rte_eal_process_type() == RTE_PROC_PRIMARY) memset(rte_eth_dev_data, 0, RTE_MAX_ETHPORTS * sizeof(*rte_eth_dev_data)); } struct rte_eth_dev * rte_eth_dev_allocated(const char *name) { unsigned i; for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if ((rte_eth_devices[i].attached == DEV_ATTACHED) && strcmp(rte_eth_devices[i].data->name, name) == 0) return &rte_eth_devices[i]; } return NULL; } static uint8_t rte_eth_dev_find_free_port(void) { unsigned i; for (i = 0; i < RTE_MAX_ETHPORTS; i++) { if (rte_eth_devices[i].attached == DEV_DETACHED) return i; } return RTE_MAX_ETHPORTS; } struct rte_eth_dev * rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type) { uint8_t port_id; struct rte_eth_dev *eth_dev; port_id = rte_eth_dev_find_free_port(); if (port_id == RTE_MAX_ETHPORTS) { PMD_DEBUG_TRACE("Reached maximum number of Ethernet ports\n"); return NULL; } if (rte_eth_dev_data == NULL) rte_eth_dev_data_alloc(); if (rte_eth_dev_allocated(name) != NULL) { PMD_DEBUG_TRACE("Ethernet Device with name %s already allocated!\n", name); return NULL; } eth_dev = &rte_eth_devices[port_id]; eth_dev->data = &rte_eth_dev_data[port_id]; snprintf(eth_dev->data->name, sizeof(eth_dev->data->name), "%s", name); eth_dev->data->port_id = port_id; eth_dev->attached = DEV_ATTACHED; eth_dev->dev_type = type; nb_ports++; return eth_dev; } static int rte_eth_dev_create_unique_device_name(char *name, size_t size, struct rte_pci_device *pci_dev) { int ret; if ((name == NULL) || (pci_dev == NULL)) return -EINVAL; ret = snprintf(name, size, "%d:%d.%d", pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function); if (ret < 0) return ret; return 0; } int rte_eth_dev_release_port(struct rte_eth_dev *eth_dev) { if (eth_dev == NULL) return -EINVAL; eth_dev->attached = DEV_DETACHED; nb_ports--; return 0; } static int rte_eth_dev_init(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) { struct eth_driver *eth_drv; struct rte_eth_dev *eth_dev; char ethdev_name[RTE_ETH_NAME_MAX_LEN]; int diag; eth_drv = (struct eth_driver *)pci_drv; /* Create unique Ethernet device name using PCI address */ rte_eth_dev_create_unique_device_name(ethdev_name, sizeof(ethdev_name), pci_dev); eth_dev = rte_eth_dev_allocate(ethdev_name, RTE_ETH_DEV_PCI); if (eth_dev == NULL) return -ENOMEM; if (rte_eal_process_type() == RTE_PROC_PRIMARY) { eth_dev->data->dev_private = rte_zmalloc("ethdev private structure", eth_drv->dev_private_size, RTE_CACHE_LINE_SIZE); if (eth_dev->data->dev_private == NULL) rte_panic("Cannot allocate memzone for private port data\n"); } eth_dev->pci_dev = pci_dev; eth_dev->driver = eth_drv; eth_dev->data->rx_mbuf_alloc_failed = 0; /* init user callbacks */ TAILQ_INIT(&(eth_dev->link_intr_cbs)); /* * Set the default MTU. */ eth_dev->data->mtu = ETHER_MTU; /* Invoke PMD device initialization function */ diag = (*eth_drv->eth_dev_init)(eth_dev); if (diag == 0) return 0; PMD_DEBUG_TRACE("driver %s: eth_dev_init(vendor_id=0x%u device_id=0x%x) failed\n", pci_drv->name, (unsigned) pci_dev->id.vendor_id, (unsigned) pci_dev->id.device_id); if (rte_eal_process_type() == RTE_PROC_PRIMARY) rte_free(eth_dev->data->dev_private); rte_eth_dev_release_port(eth_dev); return diag; } static int rte_eth_dev_uninit(struct rte_pci_device *pci_dev) { const struct eth_driver *eth_drv; struct rte_eth_dev *eth_dev; char ethdev_name[RTE_ETH_NAME_MAX_LEN]; int ret; if (pci_dev == NULL) return -EINVAL; /* Create unique Ethernet device name using PCI address */ rte_eth_dev_create_unique_device_name(ethdev_name, sizeof(ethdev_name), pci_dev); eth_dev = rte_eth_dev_allocated(ethdev_name); if (eth_dev == NULL) return -ENODEV; eth_drv = (const struct eth_driver *)pci_dev->driver; /* Invoke PMD device uninit function */ if (*eth_drv->eth_dev_uninit) { ret = (*eth_drv->eth_dev_uninit)(eth_dev); if (ret) return ret; } /* free ether device */ rte_eth_dev_release_port(eth_dev); if (rte_eal_process_type() == RTE_PROC_PRIMARY) rte_free(eth_dev->data->dev_private); eth_dev->pci_dev = NULL; eth_dev->driver = NULL; eth_dev->data = NULL; return 0; } /** * Register an Ethernet [Poll Mode] driver. * * Function invoked by the initialization function of an Ethernet driver * to simultaneously register itself as a PCI driver and as an Ethernet * Poll Mode Driver. * Invokes the rte_eal_pci_register() function to register the *pci_drv* * structure embedded in the *eth_drv* structure, after having stored the * address of the rte_eth_dev_init() function in the *devinit* field of * the *pci_drv* structure. * During the PCI probing phase, the rte_eth_dev_init() function is * invoked for each PCI [Ethernet device] matching the embedded PCI * identifiers provided by the driver. */ void rte_eth_driver_register(struct eth_driver *eth_drv) { eth_drv->pci_drv.devinit = rte_eth_dev_init; eth_drv->pci_drv.devuninit = rte_eth_dev_uninit; rte_eal_pci_register(ð_drv->pci_drv); } int rte_eth_dev_is_valid_port(uint8_t port_id) { if (port_id >= RTE_MAX_ETHPORTS || rte_eth_devices[port_id].attached != DEV_ATTACHED) return 0; else return 1; } int rte_eth_dev_socket_id(uint8_t port_id) { if (!rte_eth_dev_is_valid_port(port_id)) return -1; return rte_eth_devices[port_id].pci_dev->numa_node; } uint8_t rte_eth_dev_count(void) { return nb_ports; } static enum rte_eth_dev_type rte_eth_dev_get_device_type(uint8_t port_id) { if (!rte_eth_dev_is_valid_port(port_id)) return RTE_ETH_DEV_UNKNOWN; return rte_eth_devices[port_id].dev_type; } static int rte_eth_dev_save(struct rte_eth_dev *devs, size_t size) { if ((devs == NULL) || (size != sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS)) return -EINVAL; /* save current rte_eth_devices */ memcpy(devs, rte_eth_devices, size); return 0; } static int rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id) { if ((devs == NULL) || (port_id == NULL)) return -EINVAL; /* check which port was attached or detached */ for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) { if (rte_eth_devices[*port_id].attached ^ devs->attached) return 0; } return -ENODEV; } static int rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr) { VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); if (addr == NULL) { PMD_DEBUG_TRACE("Null pointer is specified\n"); return -EINVAL; } *addr = rte_eth_devices[port_id].pci_dev->addr; return 0; } static int rte_eth_dev_get_name_by_port(uint8_t port_id, char *name) { char *tmp; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); if (name == NULL) { PMD_DEBUG_TRACE("Null pointer is specified\n"); return -EINVAL; } /* shouldn't check 'rte_eth_devices[i].data', * because it might be overwritten by VDEV PMD */ tmp = rte_eth_dev_data[port_id].name; strcpy(name, tmp); return 0; } static int rte_eth_dev_is_detachable(uint8_t port_id) { uint32_t drv_flags; if (!rte_eth_dev_is_valid_port(port_id)) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -EINVAL; } if (rte_eth_devices[port_id].dev_type == RTE_ETH_DEV_PCI) { switch (rte_eth_devices[port_id].pci_dev->kdrv) { case RTE_KDRV_IGB_UIO: case RTE_KDRV_UIO_GENERIC: case RTE_KDRV_NIC_UIO: break; case RTE_KDRV_VFIO: default: return -ENOTSUP; } } drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags; return !(drv_flags & RTE_PCI_DRV_DETACHABLE); } /* attach the new physical device, then store port_id of the device */ static int rte_eth_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id) { uint8_t new_port_id; struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; if ((addr == NULL) || (port_id == NULL)) goto err; /* save current port status */ if (rte_eth_dev_save(devs, sizeof(devs))) goto err; /* re-construct pci_device_list */ if (rte_eal_pci_scan()) goto err; /* invoke probe func of the driver can handle the new device. * TODO: * rte_eal_pci_probe_one() should return port_id. * And rte_eth_dev_save() and rte_eth_dev_get_changed_port() * should be removed. */ if (rte_eal_pci_probe_one(addr)) goto err; /* get port_id enabled by above procedures */ if (rte_eth_dev_get_changed_port(devs, &new_port_id)) goto err; *port_id = new_port_id; return 0; err: RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n"); return -1; } /* detach the new physical device, then store pci_addr of the device */ static int rte_eth_dev_detach_pdev(uint8_t port_id, struct rte_pci_addr *addr) { struct rte_pci_addr freed_addr; struct rte_pci_addr vp; if (addr == NULL) goto err; /* check whether the driver supports detach feature, or not */ if (rte_eth_dev_is_detachable(port_id)) goto err; /* get pci address by port id */ if (rte_eth_dev_get_addr_by_port(port_id, &freed_addr)) goto err; /* Zeroed pci addr means the port comes from virtual device */ vp.domain = vp.bus = vp.devid = vp.function = 0; if (rte_eal_compare_pci_addr(&vp, &freed_addr) == 0) goto err; /* invoke devuninit func of the pci driver, * also remove the device from pci_device_list */ if (rte_eal_pci_detach(&freed_addr)) goto err; *addr = freed_addr; return 0; err: RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n"); return -1; } /* attach the new virtual device, then store port_id of the device */ static int rte_eth_dev_attach_vdev(const char *vdevargs, uint8_t *port_id) { char *name = NULL, *args = NULL; uint8_t new_port_id; struct rte_eth_dev devs[RTE_MAX_ETHPORTS]; int ret = -1; if ((vdevargs == NULL) || (port_id == NULL)) goto end; /* parse vdevargs, then retrieve device name and args */ if (rte_eal_parse_devargs_str(vdevargs, &name, &args)) goto end; /* save current port status */ if (rte_eth_dev_save(devs, sizeof(devs))) goto end; /* walk around dev_driver_list to find the driver of the device, * then invoke probe function o the driver. * TODO: * rte_eal_vdev_init() should return port_id, * And rte_eth_dev_save() and rte_eth_dev_get_changed_port() * should be removed. */ if (rte_eal_vdev_init(name, args)) goto end; /* get port_id enabled by above procedures */ if (rte_eth_dev_get_changed_port(devs, &new_port_id)) goto end; ret = 0; *port_id = new_port_id; end: if (name) free(name); if (args) free(args); if (ret < 0) RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n"); return ret; } /* detach the new virtual device, then store the name of the device */ static int rte_eth_dev_detach_vdev(uint8_t port_id, char *vdevname) { char name[RTE_ETH_NAME_MAX_LEN]; if (vdevname == NULL) goto err; /* check whether the driver supports detach feature, or not */ if (rte_eth_dev_is_detachable(port_id)) goto err; /* get device name by port id */ if (rte_eth_dev_get_name_by_port(port_id, name)) goto err; /* walk around dev_driver_list to find the driver of the device, * then invoke uninit function of the driver */ if (rte_eal_vdev_uninit(name)) goto err; strncpy(vdevname, name, sizeof(name)); return 0; err: RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n"); return -1; } /* attach the new device, then store port_id of the device */ int rte_eth_dev_attach(const char *devargs, uint8_t *port_id) { struct rte_pci_addr addr; if ((devargs == NULL) || (port_id == NULL)) return -EINVAL; if (eal_parse_pci_DomBDF(devargs, &addr) == 0) return rte_eth_dev_attach_pdev(&addr, port_id); else return rte_eth_dev_attach_vdev(devargs, port_id); } /* detach the device, then store the name of the device */ int rte_eth_dev_detach(uint8_t port_id, char *name) { struct rte_pci_addr addr; int ret; if (name == NULL) return -EINVAL; if (rte_eth_dev_get_device_type(port_id) == RTE_ETH_DEV_PCI) { ret = rte_eth_dev_get_addr_by_port(port_id, &addr); if (ret < 0) return ret; ret = rte_eth_dev_detach_pdev(port_id, &addr); if (ret == 0) snprintf(name, RTE_ETH_NAME_MAX_LEN, "%04x:%02x:%02x.%d", addr.domain, addr.bus, addr.devid, addr.function); return ret; } else return rte_eth_dev_detach_vdev(port_id, name); } static int rte_eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { uint16_t old_nb_queues = dev->data->nb_rx_queues; void **rxq; unsigned i; if (dev->data->rx_queues == NULL) { /* first time configuration */ dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues", sizeof(dev->data->rx_queues[0]) * nb_queues, RTE_CACHE_LINE_SIZE); if (dev->data->rx_queues == NULL) { dev->data->nb_rx_queues = 0; return -(ENOMEM); } } else { /* re-configure */ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_release, -ENOTSUP); rxq = dev->data->rx_queues; for (i = nb_queues; i < old_nb_queues; i++) (*dev->dev_ops->rx_queue_release)(rxq[i]); rxq = rte_realloc(rxq, sizeof(rxq[0]) * nb_queues, RTE_CACHE_LINE_SIZE); if (rxq == NULL) return -(ENOMEM); if (nb_queues > old_nb_queues) { uint16_t new_qs = nb_queues - old_nb_queues; memset(rxq + old_nb_queues, 0, sizeof(rxq[0]) * new_qs); } dev->data->rx_queues = rxq; } dev->data->nb_rx_queues = nb_queues; return 0; } int rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", rx_queue_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_start, -ENOTSUP); return dev->dev_ops->rx_queue_start(dev, rx_queue_id); } int rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", rx_queue_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_stop, -ENOTSUP); return dev->dev_ops->rx_queue_stop(dev, rx_queue_id); } int rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (tx_queue_id >= dev->data->nb_tx_queues) { PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", tx_queue_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_start, -ENOTSUP); return dev->dev_ops->tx_queue_start(dev, tx_queue_id); } int rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (tx_queue_id >= dev->data->nb_tx_queues) { PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", tx_queue_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_stop, -ENOTSUP); return dev->dev_ops->tx_queue_stop(dev, tx_queue_id); } static int rte_eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) { uint16_t old_nb_queues = dev->data->nb_tx_queues; void **txq; unsigned i; if (dev->data->tx_queues == NULL) { /* first time configuration */ dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues", sizeof(dev->data->tx_queues[0]) * nb_queues, RTE_CACHE_LINE_SIZE); if (dev->data->tx_queues == NULL) { dev->data->nb_tx_queues = 0; return -(ENOMEM); } } else { /* re-configure */ FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_release, -ENOTSUP); txq = dev->data->tx_queues; for (i = nb_queues; i < old_nb_queues; i++) (*dev->dev_ops->tx_queue_release)(txq[i]); txq = rte_realloc(txq, sizeof(txq[0]) * nb_queues, RTE_CACHE_LINE_SIZE); if (txq == NULL) return -ENOMEM; if (nb_queues > old_nb_queues) { uint16_t new_qs = nb_queues - old_nb_queues; memset(txq + old_nb_queues, 0, sizeof(txq[0]) * new_qs); } dev->data->tx_queues = txq; } dev->data->nb_tx_queues = nb_queues; return 0; } static int rte_eth_dev_check_vf_rss_rxq_num(uint8_t port_id, uint16_t nb_rx_q) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; switch (nb_rx_q) { case 1: case 2: RTE_ETH_DEV_SRIOV(dev).active = ETH_64_POOLS; break; case 4: RTE_ETH_DEV_SRIOV(dev).active = ETH_32_POOLS; break; default: return -EINVAL; } RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = nb_rx_q; RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = dev->pci_dev->max_vfs * nb_rx_q; return 0; } static int rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, const struct rte_eth_conf *dev_conf) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; if (RTE_ETH_DEV_SRIOV(dev).active != 0) { /* check multi-queue mode */ if ((dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB) || (dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB_RSS) || (dev_conf->txmode.mq_mode == ETH_MQ_TX_DCB)) { /* SRIOV only works in VMDq enable mode */ PMD_DEBUG_TRACE("ethdev port_id=%" PRIu8 " SRIOV active, " "wrong VMDQ mq_mode rx %u tx %u\n", port_id, dev_conf->rxmode.mq_mode, dev_conf->txmode.mq_mode); return -EINVAL; } switch (dev_conf->rxmode.mq_mode) { case ETH_MQ_RX_VMDQ_DCB: case ETH_MQ_RX_VMDQ_DCB_RSS: /* DCB/RSS VMDQ in SRIOV mode, not implement yet */ PMD_DEBUG_TRACE("ethdev port_id=%" PRIu8 " SRIOV active, " "unsupported VMDQ mq_mode rx %u\n", port_id, dev_conf->rxmode.mq_mode); return -EINVAL; case ETH_MQ_RX_RSS: PMD_DEBUG_TRACE("ethdev port_id=%" PRIu8 " SRIOV active, " "Rx mq mode is changed from:" "mq_mode %u into VMDQ mq_mode %u\n", port_id, dev_conf->rxmode.mq_mode, dev->data->dev_conf.rxmode.mq_mode); case ETH_MQ_RX_VMDQ_RSS: dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_RSS; if (nb_rx_q <= RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool) if (rte_eth_dev_check_vf_rss_rxq_num(port_id, nb_rx_q) != 0) { PMD_DEBUG_TRACE("ethdev port_id=%d" " SRIOV active, invalid queue" " number for VMDQ RSS, allowed" " value are 1, 2 or 4\n", port_id); return -EINVAL; } break; default: /* ETH_MQ_RX_VMDQ_ONLY or ETH_MQ_RX_NONE */ /* if nothing mq mode configure, use default scheme */ dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_ONLY; if (RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool > 1) RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 1; break; } switch (dev_conf->txmode.mq_mode) { case ETH_MQ_TX_VMDQ_DCB: /* DCB VMDQ in SRIOV mode, not implement yet */ PMD_DEBUG_TRACE("ethdev port_id=%" PRIu8 " SRIOV active, " "unsupported VMDQ mq_mode tx %u\n", port_id, dev_conf->txmode.mq_mode); return -EINVAL; default: /* ETH_MQ_TX_VMDQ_ONLY or ETH_MQ_TX_NONE */ /* if nothing mq mode configure, use default scheme */ dev->data->dev_conf.txmode.mq_mode = ETH_MQ_TX_VMDQ_ONLY; break; } /* check valid queue number */ if ((nb_rx_q > RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool) || (nb_tx_q > RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool)) { PMD_DEBUG_TRACE("ethdev port_id=%d SRIOV active, " "queue number must less equal to %d\n", port_id, RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool); return -EINVAL; } } else { /* For vmdb+dcb mode check our configuration before we go further */ if (dev_conf->rxmode.mq_mode == ETH_MQ_RX_VMDQ_DCB) { const struct rte_eth_vmdq_dcb_conf *conf; if (nb_rx_q != ETH_VMDQ_DCB_NUM_QUEUES) { PMD_DEBUG_TRACE("ethdev port_id=%d VMDQ+DCB, nb_rx_q " "!= %d\n", port_id, ETH_VMDQ_DCB_NUM_QUEUES); return -EINVAL; } conf = &(dev_conf->rx_adv_conf.vmdq_dcb_conf); if (!(conf->nb_queue_pools == ETH_16_POOLS || conf->nb_queue_pools == ETH_32_POOLS)) { PMD_DEBUG_TRACE("ethdev port_id=%d VMDQ+DCB selected, " "nb_queue_pools must be %d or %d\n", port_id, ETH_16_POOLS, ETH_32_POOLS); return -EINVAL; } } if (dev_conf->txmode.mq_mode == ETH_MQ_TX_VMDQ_DCB) { const struct rte_eth_vmdq_dcb_tx_conf *conf; if (nb_tx_q != ETH_VMDQ_DCB_NUM_QUEUES) { PMD_DEBUG_TRACE("ethdev port_id=%d VMDQ+DCB, nb_tx_q " "!= %d\n", port_id, ETH_VMDQ_DCB_NUM_QUEUES); return -EINVAL; } conf = &(dev_conf->tx_adv_conf.vmdq_dcb_tx_conf); if (!(conf->nb_queue_pools == ETH_16_POOLS || conf->nb_queue_pools == ETH_32_POOLS)) { PMD_DEBUG_TRACE("ethdev port_id=%d VMDQ+DCB selected, " "nb_queue_pools != %d or nb_queue_pools " "!= %d\n", port_id, ETH_16_POOLS, ETH_32_POOLS); return -EINVAL; } } /* For DCB mode check our configuration before we go further */ if (dev_conf->rxmode.mq_mode == ETH_MQ_RX_DCB) { const struct rte_eth_dcb_rx_conf *conf; if (nb_rx_q != ETH_DCB_NUM_QUEUES) { PMD_DEBUG_TRACE("ethdev port_id=%d DCB, nb_rx_q " "!= %d\n", port_id, ETH_DCB_NUM_QUEUES); return -EINVAL; } conf = &(dev_conf->rx_adv_conf.dcb_rx_conf); if (!(conf->nb_tcs == ETH_4_TCS || conf->nb_tcs == ETH_8_TCS)) { PMD_DEBUG_TRACE("ethdev port_id=%d DCB selected, " "nb_tcs != %d or nb_tcs " "!= %d\n", port_id, ETH_4_TCS, ETH_8_TCS); return -EINVAL; } } if (dev_conf->txmode.mq_mode == ETH_MQ_TX_DCB) { const struct rte_eth_dcb_tx_conf *conf; if (nb_tx_q != ETH_DCB_NUM_QUEUES) { PMD_DEBUG_TRACE("ethdev port_id=%d DCB, nb_tx_q " "!= %d\n", port_id, ETH_DCB_NUM_QUEUES); return -EINVAL; } conf = &(dev_conf->tx_adv_conf.dcb_tx_conf); if (!(conf->nb_tcs == ETH_4_TCS || conf->nb_tcs == ETH_8_TCS)) { PMD_DEBUG_TRACE("ethdev port_id=%d DCB selected, " "nb_tcs != %d or nb_tcs " "!= %d\n", port_id, ETH_4_TCS, ETH_8_TCS); return -EINVAL; } } } return 0; } int rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, const struct rte_eth_conf *dev_conf) { struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; int diag; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); if (nb_rx_q > RTE_MAX_QUEUES_PER_PORT) { PMD_DEBUG_TRACE( "Number of RX queues requested (%u) is greater than max supported(%d)\n", nb_rx_q, RTE_MAX_QUEUES_PER_PORT); return -EINVAL; } if (nb_tx_q > RTE_MAX_QUEUES_PER_PORT) { PMD_DEBUG_TRACE( "Number of TX queues requested (%u) is greater than max supported(%d)\n", nb_tx_q, RTE_MAX_QUEUES_PER_PORT); return -EINVAL; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP); FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP); if (dev->data->dev_started) { PMD_DEBUG_TRACE( "port %d must be stopped to allow configuration\n", port_id); return -EBUSY; } /* * Check that the numbers of RX and TX queues are not greater * than the maximum number of RX and TX queues supported by the * configured device. */ (*dev->dev_ops->dev_infos_get)(dev, &dev_info); if (nb_rx_q > dev_info.max_rx_queues) { PMD_DEBUG_TRACE("ethdev port_id=%d nb_rx_queues=%d > %d\n", port_id, nb_rx_q, dev_info.max_rx_queues); return -EINVAL; } if (nb_rx_q == 0) { PMD_DEBUG_TRACE("ethdev port_id=%d nb_rx_q == 0\n", port_id); return -EINVAL; } if (nb_tx_q > dev_info.max_tx_queues) { PMD_DEBUG_TRACE("ethdev port_id=%d nb_tx_queues=%d > %d\n", port_id, nb_tx_q, dev_info.max_tx_queues); return -EINVAL; } if (nb_tx_q == 0) { PMD_DEBUG_TRACE("ethdev port_id=%d nb_tx_q == 0\n", port_id); return -EINVAL; } /* Copy the dev_conf parameter into the dev structure */ memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf)); /* * If link state interrupt is enabled, check that the * device supports it. */ if (dev_conf->intr_conf.lsc == 1) { const struct rte_pci_driver *pci_drv = &dev->driver->pci_drv; if (!(pci_drv->drv_flags & RTE_PCI_DRV_INTR_LSC)) { PMD_DEBUG_TRACE("driver %s does not support lsc\n", pci_drv->name); return -EINVAL; } } /* * If jumbo frames are enabled, check that the maximum RX packet * length is supported by the configured device. */ if (dev_conf->rxmode.jumbo_frame == 1) { if (dev_conf->rxmode.max_rx_pkt_len > dev_info.max_rx_pktlen) { PMD_DEBUG_TRACE("ethdev port_id=%d max_rx_pkt_len %u" " > max valid value %u\n", port_id, (unsigned)dev_conf->rxmode.max_rx_pkt_len, (unsigned)dev_info.max_rx_pktlen); return -EINVAL; } else if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN) { PMD_DEBUG_TRACE("ethdev port_id=%d max_rx_pkt_len %u" " < min valid value %u\n", port_id, (unsigned)dev_conf->rxmode.max_rx_pkt_len, (unsigned)ETHER_MIN_LEN); return -EINVAL; } } else { if (dev_conf->rxmode.max_rx_pkt_len < ETHER_MIN_LEN || dev_conf->rxmode.max_rx_pkt_len > ETHER_MAX_LEN) /* Use default value */ dev->data->dev_conf.rxmode.max_rx_pkt_len = ETHER_MAX_LEN; } /* multiple queue mode checking */ diag = rte_eth_dev_check_mq_mode(port_id, nb_rx_q, nb_tx_q, dev_conf); if (diag != 0) { PMD_DEBUG_TRACE("port%d rte_eth_dev_check_mq_mode = %d\n", port_id, diag); return diag; } /* * Setup new number of RX/TX queues and reconfigure device. */ diag = rte_eth_dev_rx_queue_config(dev, nb_rx_q); if (diag != 0) { PMD_DEBUG_TRACE("port%d rte_eth_dev_rx_queue_config = %d\n", port_id, diag); return diag; } diag = rte_eth_dev_tx_queue_config(dev, nb_tx_q); if (diag != 0) { PMD_DEBUG_TRACE("port%d rte_eth_dev_tx_queue_config = %d\n", port_id, diag); rte_eth_dev_rx_queue_config(dev, 0); return diag; } diag = (*dev->dev_ops->dev_configure)(dev); if (diag != 0) { PMD_DEBUG_TRACE("port%d dev_configure = %d\n", port_id, diag); rte_eth_dev_rx_queue_config(dev, 0); rte_eth_dev_tx_queue_config(dev, 0); return diag; } return 0; } static void rte_eth_dev_config_restore(uint8_t port_id) { struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; struct ether_addr addr; uint16_t i; uint32_t pool = 0; dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); if (RTE_ETH_DEV_SRIOV(dev).active) pool = RTE_ETH_DEV_SRIOV(dev).def_vmdq_idx; /* replay MAC address configuration */ for (i = 0; i < dev_info.max_mac_addrs; i++) { addr = dev->data->mac_addrs[i]; /* skip zero address */ if (is_zero_ether_addr(&addr)) continue; /* add address to the hardware */ if (*dev->dev_ops->mac_addr_add && (dev->data->mac_pool_sel[i] & (1ULL << pool))) (*dev->dev_ops->mac_addr_add)(dev, &addr, i, pool); else { PMD_DEBUG_TRACE("port %d: MAC address array not supported\n", port_id); /* exit the loop but not return an error */ break; } } /* replay promiscuous configuration */ if (rte_eth_promiscuous_get(port_id) == 1) rte_eth_promiscuous_enable(port_id); else if (rte_eth_promiscuous_get(port_id) == 0) rte_eth_promiscuous_disable(port_id); /* replay all multicast configuration */ if (rte_eth_allmulticast_get(port_id) == 1) rte_eth_allmulticast_enable(port_id); else if (rte_eth_allmulticast_get(port_id) == 0) rte_eth_allmulticast_disable(port_id); } int rte_eth_dev_start(uint8_t port_id) { struct rte_eth_dev *dev; int diag; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP); if (dev->data->dev_started != 0) { PMD_DEBUG_TRACE("Device with port_id=%" PRIu8 " already started\n", port_id); return 0; } diag = (*dev->dev_ops->dev_start)(dev); if (diag == 0) dev->data->dev_started = 1; else return diag; rte_eth_dev_config_restore(port_id); if (dev->data->dev_conf.intr_conf.lsc != 0) { FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP); (*dev->dev_ops->link_update)(dev, 0); } return 0; } void rte_eth_dev_stop(uint8_t port_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_RET(); VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop); if (dev->data->dev_started == 0) { PMD_DEBUG_TRACE("Device with port_id=%" PRIu8 " already stopped\n", port_id); return; } dev->data->dev_started = 0; (*dev->dev_ops->dev_stop)(dev); } int rte_eth_dev_set_link_up(uint8_t port_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_set_link_up, -ENOTSUP); return (*dev->dev_ops->dev_set_link_up)(dev); } int rte_eth_dev_set_link_down(uint8_t port_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_set_link_down, -ENOTSUP); return (*dev->dev_ops->dev_set_link_down)(dev); } void rte_eth_dev_close(uint8_t port_id) { struct rte_eth_dev *dev; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_RET(); VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->dev_close); dev->data->dev_started = 0; (*dev->dev_ops->dev_close)(dev); rte_free(dev->data->rx_queues); dev->data->rx_queues = NULL; rte_free(dev->data->tx_queues); dev->data->tx_queues = NULL; } int rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp) { int ret; uint32_t mbp_buf_size; struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", rx_queue_id); return -EINVAL; } if (dev->data->dev_started) { PMD_DEBUG_TRACE( "port %d must be stopped to allow configuration\n", port_id); return -EBUSY; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP); FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_setup, -ENOTSUP); /* * Check the size of the mbuf data buffer. * This value must be provided in the private data of the memory pool. * First check that the memory pool has a valid private data. */ rte_eth_dev_info_get(port_id, &dev_info); if (mp->private_data_size < sizeof(struct rte_pktmbuf_pool_private)) { PMD_DEBUG_TRACE("%s private_data_size %d < %d\n", mp->name, (int) mp->private_data_size, (int) sizeof(struct rte_pktmbuf_pool_private)); return -ENOSPC; } mbp_buf_size = rte_pktmbuf_data_room_size(mp); if ((mbp_buf_size - RTE_PKTMBUF_HEADROOM) < dev_info.min_rx_bufsize) { PMD_DEBUG_TRACE("%s mbuf_data_room_size %d < %d " "(RTE_PKTMBUF_HEADROOM=%d + min_rx_bufsize(dev)" "=%d)\n", mp->name, (int)mbp_buf_size, (int)(RTE_PKTMBUF_HEADROOM + dev_info.min_rx_bufsize), (int)RTE_PKTMBUF_HEADROOM, (int)dev_info.min_rx_bufsize); return -EINVAL; } if (rx_conf == NULL) rx_conf = &dev_info.default_rxconf; ret = (*dev->dev_ops->rx_queue_setup)(dev, rx_queue_id, nb_rx_desc, socket_id, rx_conf, mp); if (!ret) { if (!dev->data->min_rx_buf_size || dev->data->min_rx_buf_size > mbp_buf_size) dev->data->min_rx_buf_size = mbp_buf_size; } return ret; } int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; /* This function is only safe when called from the primary process * in a multi-process setup*/ PROC_PRIMARY_OR_ERR_RET(-E_RTE_SECONDARY); VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; if (tx_queue_id >= dev->data->nb_tx_queues) { PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", tx_queue_id); return -EINVAL; } if (dev->data->dev_started) { PMD_DEBUG_TRACE( "port %d must be stopped to allow configuration\n", port_id); return -EBUSY; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP); FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_setup, -ENOTSUP); rte_eth_dev_info_get(port_id, &dev_info); if (tx_conf == NULL) tx_conf = &dev_info.default_txconf; return (*dev->dev_ops->tx_queue_setup)(dev, tx_queue_id, nb_tx_desc, socket_id, tx_conf); } void rte_eth_promiscuous_enable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->promiscuous_enable); (*dev->dev_ops->promiscuous_enable)(dev); dev->data->promiscuous = 1; } void rte_eth_promiscuous_disable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->promiscuous_disable); dev->data->promiscuous = 0; (*dev->dev_ops->promiscuous_disable)(dev); } int rte_eth_promiscuous_get(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; return dev->data->promiscuous; } void rte_eth_allmulticast_enable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->allmulticast_enable); (*dev->dev_ops->allmulticast_enable)(dev); dev->data->all_multicast = 1; } void rte_eth_allmulticast_disable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->allmulticast_disable); dev->data->all_multicast = 0; (*dev->dev_ops->allmulticast_disable)(dev); } int rte_eth_allmulticast_get(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; return dev->data->all_multicast; } static inline int rte_eth_dev_atomic_read_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link) { struct rte_eth_link *dst = link; struct rte_eth_link *src = &(dev->data->dev_link); if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, *(uint64_t *)src) == 0) return -1; return 0; } void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *eth_link) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.intr_conf.lsc != 0) rte_eth_dev_atomic_read_link_status(dev, eth_link); else { FUNC_PTR_OR_RET(*dev->dev_ops->link_update); (*dev->dev_ops->link_update)(dev, 1); *eth_link = dev->data->dev_link; } } void rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *eth_link) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.intr_conf.lsc != 0) rte_eth_dev_atomic_read_link_status(dev, eth_link); else { FUNC_PTR_OR_RET(*dev->dev_ops->link_update); (*dev->dev_ops->link_update)(dev, 0); *eth_link = dev->data->dev_link; } } int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; memset(stats, 0, sizeof(*stats)); FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP); (*dev->dev_ops->stats_get)(dev, stats); stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed; return 0; } void rte_eth_stats_reset(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset); (*dev->dev_ops->stats_reset)(dev); } /* retrieve ethdev extended statistics */ int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, unsigned n) { struct rte_eth_stats eth_stats; struct rte_eth_dev *dev; unsigned count = 0, i, q; signed xcount = 0; uint64_t val, *stats_ptr; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; /* Return generic statistics */ count = RTE_NB_STATS; count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS; count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS; /* implemented by the driver */ if (dev->dev_ops->xstats_get != NULL) { /* Retrieve the xstats from the driver at the end of the * xstats struct. */ xcount = (*dev->dev_ops->xstats_get)(dev, &xstats[count], (n > count) ? n - count : 0); if (xcount < 0) return xcount; } if (n < count + xcount) return count + xcount; /* now fill the xstats structure */ count = 0; rte_eth_stats_get(port_id, ð_stats); /* global stats */ for (i = 0; i < RTE_NB_STATS; i++) { stats_ptr = RTE_PTR_ADD(ð_stats, rte_stats_strings[i].offset); val = *stats_ptr; snprintf(xstats[count].name, sizeof(xstats[count].name), "%s", rte_stats_strings[i].name); xstats[count++].value = val; } /* per-rxq stats */ for (q = 0; q < dev->data->nb_rx_queues; q++) { for (i = 0; i < RTE_NB_RXQ_STATS; i++) { stats_ptr = RTE_PTR_ADD(ð_stats, rte_rxq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; snprintf(xstats[count].name, sizeof(xstats[count].name), "rx_queue_%u_%s", q, rte_rxq_stats_strings[i].name); xstats[count++].value = val; } } /* per-txq stats */ for (q = 0; q < dev->data->nb_tx_queues; q++) { for (i = 0; i < RTE_NB_TXQ_STATS; i++) { stats_ptr = RTE_PTR_ADD(ð_stats, rte_txq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; snprintf(xstats[count].name, sizeof(xstats[count].name), "tx_queue_%u_%s", q, rte_txq_stats_strings[i].name); xstats[count++].value = val; } } return count + xcount; } /* reset ethdev extended statistics */ void rte_eth_xstats_reset(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; /* implemented by the driver */ if (dev->dev_ops->xstats_reset != NULL) { (*dev->dev_ops->xstats_reset)(dev); return; } /* fallback to default */ rte_eth_stats_reset(port_id); } static int set_queue_stats_mapping(uint8_t port_id, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_stats_mapping_set, -ENOTSUP); return (*dev->dev_ops->queue_stats_mapping_set) (dev, queue_id, stat_idx, is_rx); } int rte_eth_dev_set_tx_queue_stats_mapping(uint8_t port_id, uint16_t tx_queue_id, uint8_t stat_idx) { return set_queue_stats_mapping(port_id, tx_queue_id, stat_idx, STAT_QMAP_TX); } int rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id, uint8_t stat_idx) { return set_queue_stats_mapping(port_id, rx_queue_id, stat_idx, STAT_QMAP_RX); } void rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; memset(dev_info, 0, sizeof(struct rte_eth_dev_info)); FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get); (*dev->dev_ops->dev_infos_get)(dev, dev_info); dev_info->pci_dev = dev->pci_dev; if (dev->driver) dev_info->driver_name = dev->driver->pci_drv.name; } void rte_eth_macaddr_get(uint8_t port_id, struct ether_addr *mac_addr) { struct rte_eth_dev *dev; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; ether_addr_copy(&dev->data->mac_addrs[0], mac_addr); } int rte_eth_dev_get_mtu(uint8_t port_id, uint16_t *mtu) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; *mtu = dev->data->mtu; return 0; } int rte_eth_dev_set_mtu(uint8_t port_id, uint16_t mtu) { int ret; struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mtu_set, -ENOTSUP); ret = (*dev->dev_ops->mtu_set)(dev, mtu); if (!ret) dev->data->mtu = mtu; return ret; } int rte_eth_dev_vlan_filter(uint8_t port_id, uint16_t vlan_id, int on) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (!(dev->data->dev_conf.rxmode.hw_vlan_filter)) { PMD_DEBUG_TRACE("port %d: vlan-filtering disabled\n", port_id); return -ENOSYS; } if (vlan_id > 4095) { PMD_DEBUG_TRACE("(port_id=%d) invalid vlan_id=%u > 4095\n", port_id, (unsigned) vlan_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_filter_set, -ENOTSUP); return (*dev->dev_ops->vlan_filter_set)(dev, vlan_id, on); } int rte_eth_dev_set_vlan_strip_on_queue(uint8_t port_id, uint16_t rx_queue_id, int on) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (rx_queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid rx_queue_id=%d\n", port_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP); (*dev->dev_ops->vlan_strip_queue_set)(dev, rx_queue_id, on); return 0; } int rte_eth_dev_set_vlan_ether_type(uint8_t port_id, uint16_t tpid) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_tpid_set, -ENOTSUP); (*dev->dev_ops->vlan_tpid_set)(dev, tpid); return 0; } int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask) { struct rte_eth_dev *dev; int ret = 0; int mask = 0; int cur, org = 0; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; /*check which option changed by application*/ cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD); org = !!(dev->data->dev_conf.rxmode.hw_vlan_strip); if (cur != org) { dev->data->dev_conf.rxmode.hw_vlan_strip = (uint8_t)cur; mask |= ETH_VLAN_STRIP_MASK; } cur = !!(offload_mask & ETH_VLAN_FILTER_OFFLOAD); org = !!(dev->data->dev_conf.rxmode.hw_vlan_filter); if (cur != org) { dev->data->dev_conf.rxmode.hw_vlan_filter = (uint8_t)cur; mask |= ETH_VLAN_FILTER_MASK; } cur = !!(offload_mask & ETH_VLAN_EXTEND_OFFLOAD); org = !!(dev->data->dev_conf.rxmode.hw_vlan_extend); if (cur != org) { dev->data->dev_conf.rxmode.hw_vlan_extend = (uint8_t)cur; mask |= ETH_VLAN_EXTEND_MASK; } /*no change*/ if (mask == 0) return ret; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP); (*dev->dev_ops->vlan_offload_set)(dev, mask); return ret; } int rte_eth_dev_get_vlan_offload(uint8_t port_id) { struct rte_eth_dev *dev; int ret = 0; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.rxmode.hw_vlan_strip) ret |= ETH_VLAN_STRIP_OFFLOAD; if (dev->data->dev_conf.rxmode.hw_vlan_filter) ret |= ETH_VLAN_FILTER_OFFLOAD; if (dev->data->dev_conf.rxmode.hw_vlan_extend) ret |= ETH_VLAN_EXTEND_OFFLOAD; return ret; } int rte_eth_dev_set_vlan_pvid(uint8_t port_id, uint16_t pvid, int on) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_pvid_set, -ENOTSUP); (*dev->dev_ops->vlan_pvid_set)(dev, pvid, on); return 0; } int rte_eth_dev_fdir_add_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint8_t queue) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_SIGNATURE) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type, source & destinations ports " "should be null!\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_add_signature_filter, -ENOTSUP); return (*dev->dev_ops->fdir_add_signature_filter)(dev, fdir_filter, queue); } int rte_eth_dev_fdir_update_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint8_t queue) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_SIGNATURE) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type, source & destinations ports " "should be null!\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_update_signature_filter, -ENOTSUP); return (*dev->dev_ops->fdir_update_signature_filter)(dev, fdir_filter, queue); } int rte_eth_dev_fdir_remove_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_SIGNATURE) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type source & destinations ports " "should be null!\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_remove_signature_filter, -ENOTSUP); return (*dev->dev_ops->fdir_remove_signature_filter)(dev, fdir_filter); } int rte_eth_dev_fdir_get_infos(uint8_t port_id, struct rte_eth_fdir *fdir) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (!(dev->data->dev_conf.fdir_conf.mode)) { PMD_DEBUG_TRACE("port %d: pkt-filter disabled\n", port_id); return -ENOSYS; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_infos_get, -ENOTSUP); (*dev->dev_ops->fdir_infos_get)(dev, fdir); return 0; } int rte_eth_dev_fdir_add_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id, uint8_t queue, uint8_t drop) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type, source & destinations ports " "should be null!\n"); return -EINVAL; } /* For now IPv6 is not supported with perfect filter */ if (fdir_filter->iptype == RTE_FDIR_IPTYPE_IPV6) return -ENOTSUP; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_add_perfect_filter, -ENOTSUP); return (*dev->dev_ops->fdir_add_perfect_filter)(dev, fdir_filter, soft_id, queue, drop); } int rte_eth_dev_fdir_update_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id, uint8_t queue, uint8_t drop) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type, source & destinations ports " "should be null!\n"); return -EINVAL; } /* For now IPv6 is not supported with perfect filter */ if (fdir_filter->iptype == RTE_FDIR_IPTYPE_IPV6) return -ENOTSUP; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_update_perfect_filter, -ENOTSUP); return (*dev->dev_ops->fdir_update_perfect_filter)(dev, fdir_filter, soft_id, queue, drop); } int rte_eth_dev_fdir_remove_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) { PMD_DEBUG_TRACE("port %d: invalid FDIR mode=%u\n", port_id, dev->data->dev_conf.fdir_conf.mode); return -ENOSYS; } if ((fdir_filter->l4type == RTE_FDIR_L4TYPE_SCTP || fdir_filter->l4type == RTE_FDIR_L4TYPE_NONE) && (fdir_filter->port_src || fdir_filter->port_dst)) { PMD_DEBUG_TRACE(" Port are meaningless for SCTP and " "None l4type, source & destinations ports " "should be null!\n"); return -EINVAL; } /* For now IPv6 is not supported with perfect filter */ if (fdir_filter->iptype == RTE_FDIR_IPTYPE_IPV6) return -ENOTSUP; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_remove_perfect_filter, -ENOTSUP); return (*dev->dev_ops->fdir_remove_perfect_filter)(dev, fdir_filter, soft_id); } int rte_eth_dev_fdir_set_masks(uint8_t port_id, struct rte_fdir_masks *fdir_mask) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (!(dev->data->dev_conf.fdir_conf.mode)) { PMD_DEBUG_TRACE("port %d: pkt-filter disabled\n", port_id); return -ENOSYS; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->fdir_set_masks, -ENOTSUP); return (*dev->dev_ops->fdir_set_masks)(dev, fdir_mask); } int rte_eth_dev_flow_ctrl_get(uint8_t port_id, struct rte_eth_fc_conf *fc_conf) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->flow_ctrl_get, -ENOTSUP); memset(fc_conf, 0, sizeof(*fc_conf)); return (*dev->dev_ops->flow_ctrl_get)(dev, fc_conf); } int rte_eth_dev_flow_ctrl_set(uint8_t port_id, struct rte_eth_fc_conf *fc_conf) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); if ((fc_conf->send_xon != 0) && (fc_conf->send_xon != 1)) { PMD_DEBUG_TRACE("Invalid send_xon, only 0/1 allowed\n"); return -EINVAL; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->flow_ctrl_set, -ENOTSUP); return (*dev->dev_ops->flow_ctrl_set)(dev, fc_conf); } int rte_eth_dev_priority_flow_ctrl_set(uint8_t port_id, struct rte_eth_pfc_conf *pfc_conf) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); if (pfc_conf->priority > (ETH_DCB_NUM_USER_PRIORITIES - 1)) { PMD_DEBUG_TRACE("Invalid priority, only 0-7 allowed\n"); return -EINVAL; } dev = &rte_eth_devices[port_id]; /* High water, low water validation are device specific */ if (*dev->dev_ops->priority_flow_ctrl_set) return (*dev->dev_ops->priority_flow_ctrl_set)(dev, pfc_conf); return -ENOTSUP; } static int rte_eth_check_reta_mask(struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { uint16_t i, num; if (!reta_conf) return -EINVAL; if (reta_size != RTE_ALIGN(reta_size, RTE_RETA_GROUP_SIZE)) { PMD_DEBUG_TRACE("Invalid reta size, should be %u aligned\n", RTE_RETA_GROUP_SIZE); return -EINVAL; } num = reta_size / RTE_RETA_GROUP_SIZE; for (i = 0; i < num; i++) { if (reta_conf[i].mask) return 0; } return -EINVAL; } static int rte_eth_check_reta_entry(struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size, uint8_t max_rxq) { uint16_t i, idx, shift; if (!reta_conf) return -EINVAL; if (max_rxq == 0) { PMD_DEBUG_TRACE("No receive queue is available\n"); return -EINVAL; } for (i = 0; i < reta_size; i++) { idx = i / RTE_RETA_GROUP_SIZE; shift = i % RTE_RETA_GROUP_SIZE; if ((reta_conf[idx].mask & (1ULL << shift)) && (reta_conf[idx].reta[shift] >= max_rxq)) { PMD_DEBUG_TRACE("reta_conf[%u]->reta[%u]: %u exceeds " "the maximum rxq index: %u\n", idx, shift, reta_conf[idx].reta[shift], max_rxq); return -EINVAL; } } return 0; } int rte_eth_dev_rss_reta_update(uint8_t port_id, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct rte_eth_dev *dev; int ret; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); /* Check mask bits */ ret = rte_eth_check_reta_mask(reta_conf, reta_size); if (ret < 0) return ret; dev = &rte_eth_devices[port_id]; /* Check entry value */ ret = rte_eth_check_reta_entry(reta_conf, reta_size, dev->data->nb_rx_queues); if (ret < 0) return ret; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_update, -ENOTSUP); return (*dev->dev_ops->reta_update)(dev, reta_conf, reta_size); } int rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct rte_eth_dev *dev; int ret; if (port_id >= nb_ports) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -ENODEV; } /* Check mask bits */ ret = rte_eth_check_reta_mask(reta_conf, reta_size); if (ret < 0) return ret; dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->reta_query, -ENOTSUP); return (*dev->dev_ops->reta_query)(dev, reta_conf, reta_size); } int rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *rss_conf) { struct rte_eth_dev *dev; uint16_t rss_hash_protos; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); rss_hash_protos = rss_conf->rss_hf; if ((rss_hash_protos != 0) && ((rss_hash_protos & ETH_RSS_PROTO_MASK) == 0)) { PMD_DEBUG_TRACE("Invalid rss_hash_protos=0x%x\n", rss_hash_protos); return -EINVAL; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_update, -ENOTSUP); return (*dev->dev_ops->rss_hash_update)(dev, rss_conf); } int rte_eth_dev_rss_hash_conf_get(uint8_t port_id, struct rte_eth_rss_conf *rss_conf) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rss_hash_conf_get, -ENOTSUP); return (*dev->dev_ops->rss_hash_conf_get)(dev, rss_conf); } int rte_eth_dev_udp_tunnel_add(uint8_t port_id, struct rte_eth_udp_tunnel *udp_tunnel) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); if (udp_tunnel == NULL) { PMD_DEBUG_TRACE("Invalid udp_tunnel parameter\n"); return -EINVAL; } if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) { PMD_DEBUG_TRACE("Invalid tunnel type\n"); return -EINVAL; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_add, -ENOTSUP); return (*dev->dev_ops->udp_tunnel_add)(dev, udp_tunnel); } int rte_eth_dev_udp_tunnel_delete(uint8_t port_id, struct rte_eth_udp_tunnel *udp_tunnel) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (udp_tunnel == NULL) { PMD_DEBUG_TRACE("Invalid udp_tunnel parameter\n"); return -EINVAL; } if (udp_tunnel->prot_type >= RTE_TUNNEL_TYPE_MAX) { PMD_DEBUG_TRACE("Invalid tunnel type\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_del, -ENOTSUP); return (*dev->dev_ops->udp_tunnel_del)(dev, udp_tunnel); } int rte_eth_led_on(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_led_on, -ENOTSUP); return (*dev->dev_ops->dev_led_on)(dev); } int rte_eth_led_off(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_led_off, -ENOTSUP); return (*dev->dev_ops->dev_led_off)(dev); } /* * Returns index into MAC address array of addr. Use 00:00:00:00:00:00 to find * an empty spot. */ static int get_mac_addr_index(uint8_t port_id, const struct ether_addr *addr) { struct rte_eth_dev_info dev_info; struct rte_eth_dev *dev = &rte_eth_devices[port_id]; unsigned i; rte_eth_dev_info_get(port_id, &dev_info); for (i = 0; i < dev_info.max_mac_addrs; i++) if (memcmp(addr, &dev->data->mac_addrs[i], ETHER_ADDR_LEN) == 0) return i; return -1; } static const struct ether_addr null_mac_addr; int rte_eth_dev_mac_addr_add(uint8_t port_id, struct ether_addr *addr, uint32_t pool) { struct rte_eth_dev *dev; int index; uint64_t pool_mask; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mac_addr_add, -ENOTSUP); if (is_zero_ether_addr(addr)) { PMD_DEBUG_TRACE("port %d: Cannot add NULL MAC address\n", port_id); return -EINVAL; } if (pool >= ETH_64_POOLS) { PMD_DEBUG_TRACE("pool id must be 0-%d\n", ETH_64_POOLS - 1); return -EINVAL; } index = get_mac_addr_index(port_id, addr); if (index < 0) { index = get_mac_addr_index(port_id, &null_mac_addr); if (index < 0) { PMD_DEBUG_TRACE("port %d: MAC address array full\n", port_id); return -ENOSPC; } } else { pool_mask = dev->data->mac_pool_sel[index]; /* Check if both MAC address and pool is already there, and do nothing */ if (pool_mask & (1ULL << pool)) return 0; } /* Update NIC */ (*dev->dev_ops->mac_addr_add)(dev, addr, index, pool); /* Update address in NIC data structure */ ether_addr_copy(addr, &dev->data->mac_addrs[index]); /* Update pool bitmap in NIC data structure */ dev->data->mac_pool_sel[index] |= (1ULL << pool); return 0; } int rte_eth_dev_mac_addr_remove(uint8_t port_id, struct ether_addr *addr) { struct rte_eth_dev *dev; int index; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mac_addr_remove, -ENOTSUP); index = get_mac_addr_index(port_id, addr); if (index == 0) { PMD_DEBUG_TRACE("port %d: Cannot remove default MAC address\n", port_id); return -EADDRINUSE; } else if (index < 0) return 0; /* Do nothing if address wasn't found */ /* Update NIC */ (*dev->dev_ops->mac_addr_remove)(dev, index); /* Update address in NIC data structure */ ether_addr_copy(&null_mac_addr, &dev->data->mac_addrs[index]); /* reset pool bitmap */ dev->data->mac_pool_sel[index] = 0; return 0; } int rte_eth_dev_default_mac_addr_set(uint8_t port_id, struct ether_addr *addr) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); if (!is_valid_assigned_ether_addr(addr)) return -EINVAL; dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mac_addr_set, -ENOTSUP); /* Update default address in NIC data structure */ ether_addr_copy(addr, &dev->data->mac_addrs[0]); (*dev->dev_ops->mac_addr_set)(dev, addr); return 0; } int rte_eth_dev_set_vf_rxmode(uint8_t port_id, uint16_t vf, uint16_t rx_mode, uint8_t on) { uint16_t num_vfs; struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); num_vfs = dev_info.max_vfs; if (vf > num_vfs) { PMD_DEBUG_TRACE("set VF RX mode:invalid VF id %d\n", vf); return -EINVAL; } if (rx_mode == 0) { PMD_DEBUG_TRACE("set VF RX mode:mode mask ca not be zero\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx_mode, -ENOTSUP); return (*dev->dev_ops->set_vf_rx_mode)(dev, vf, rx_mode, on); } /* * Returns index into MAC address array of addr. Use 00:00:00:00:00:00 to find * an empty spot. */ static int get_hash_mac_addr_index(uint8_t port_id, const struct ether_addr *addr) { struct rte_eth_dev_info dev_info; struct rte_eth_dev *dev = &rte_eth_devices[port_id]; unsigned i; rte_eth_dev_info_get(port_id, &dev_info); if (!dev->data->hash_mac_addrs) return -1; for (i = 0; i < dev_info.max_hash_mac_addrs; i++) if (memcmp(addr, &dev->data->hash_mac_addrs[i], ETHER_ADDR_LEN) == 0) return i; return -1; } int rte_eth_dev_uc_hash_table_set(uint8_t port_id, struct ether_addr *addr, uint8_t on) { int index; int ret; struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (is_zero_ether_addr(addr)) { PMD_DEBUG_TRACE("port %d: Cannot add NULL MAC address\n", port_id); return -EINVAL; } index = get_hash_mac_addr_index(port_id, addr); /* Check if it's already there, and do nothing */ if ((index >= 0) && (on)) return 0; if (index < 0) { if (!on) { PMD_DEBUG_TRACE("port %d: the MAC address was not " "set in UTA\n", port_id); return -EINVAL; } index = get_hash_mac_addr_index(port_id, &null_mac_addr); if (index < 0) { PMD_DEBUG_TRACE("port %d: MAC address array full\n", port_id); return -ENOSPC; } } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->uc_hash_table_set, -ENOTSUP); ret = (*dev->dev_ops->uc_hash_table_set)(dev, addr, on); if (ret == 0) { /* Update address in NIC data structure */ if (on) ether_addr_copy(addr, &dev->data->hash_mac_addrs[index]); else ether_addr_copy(&null_mac_addr, &dev->data->hash_mac_addrs[index]); } return ret; } int rte_eth_dev_uc_all_hash_table_set(uint8_t port_id, uint8_t on) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->uc_all_hash_table_set, -ENOTSUP); return (*dev->dev_ops->uc_all_hash_table_set)(dev, on); } int rte_eth_dev_set_vf_rx(uint8_t port_id, uint16_t vf, uint8_t on) { uint16_t num_vfs; struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); num_vfs = dev_info.max_vfs; if (vf > num_vfs) { PMD_DEBUG_TRACE("port %d: invalid vf id\n", port_id); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rx, -ENOTSUP); return (*dev->dev_ops->set_vf_rx)(dev, vf, on); } int rte_eth_dev_set_vf_tx(uint8_t port_id, uint16_t vf, uint8_t on) { uint16_t num_vfs; struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); num_vfs = dev_info.max_vfs; if (vf > num_vfs) { PMD_DEBUG_TRACE("set pool tx:invalid pool id=%d\n", vf); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_tx, -ENOTSUP); return (*dev->dev_ops->set_vf_tx)(dev, vf, on); } int rte_eth_dev_set_vf_vlan_filter(uint8_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t vlan_on) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (vlan_id > ETHER_MAX_VLAN_ID) { PMD_DEBUG_TRACE("VF VLAN filter:invalid VLAN id=%d\n", vlan_id); return -EINVAL; } if (vf_mask == 0) { PMD_DEBUG_TRACE("VF VLAN filter:pool_mask can not be 0\n"); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_vlan_filter, -ENOTSUP); return (*dev->dev_ops->set_vf_vlan_filter)(dev, vlan_id, vf_mask, vlan_on); } int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx, uint16_t tx_rate) { struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; struct rte_eth_link link; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); link = dev->data->dev_link; if (queue_idx > dev_info.max_tx_queues) { PMD_DEBUG_TRACE("set queue rate limit:port %d: " "invalid queue id=%d\n", port_id, queue_idx); return -EINVAL; } if (tx_rate > link.link_speed) { PMD_DEBUG_TRACE("set queue rate limit:invalid tx_rate=%d, " "bigger than link speed= %d\n", tx_rate, link.link_speed); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_queue_rate_limit, -ENOTSUP); return (*dev->dev_ops->set_queue_rate_limit)(dev, queue_idx, tx_rate); } int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate, uint64_t q_msk) { struct rte_eth_dev *dev; struct rte_eth_dev_info dev_info; struct rte_eth_link link; if (q_msk == 0) return 0; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; rte_eth_dev_info_get(port_id, &dev_info); link = dev->data->dev_link; if (vf > dev_info.max_vfs) { PMD_DEBUG_TRACE("set VF rate limit:port %d: " "invalid vf id=%d\n", port_id, vf); return -EINVAL; } if (tx_rate > link.link_speed) { PMD_DEBUG_TRACE("set VF rate limit:invalid tx_rate=%d, " "bigger than link speed= %d\n", tx_rate, link.link_speed); return -EINVAL; } FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_vf_rate_limit, -ENOTSUP); return (*dev->dev_ops->set_vf_rate_limit)(dev, vf, tx_rate, q_msk); } int rte_eth_mirror_rule_set(uint8_t port_id, struct rte_eth_mirror_conf *mirror_conf, uint8_t rule_id, uint8_t on) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); if (mirror_conf->rule_type == 0) { PMD_DEBUG_TRACE("mirror rule type can not be 0.\n"); return -EINVAL; } if (mirror_conf->dst_pool >= ETH_64_POOLS) { PMD_DEBUG_TRACE("Invalid dst pool, pool id must be 0-%d\n", ETH_64_POOLS - 1); return -EINVAL; } if ((mirror_conf->rule_type & (ETH_MIRROR_VIRTUAL_POOL_UP | ETH_MIRROR_VIRTUAL_POOL_DOWN)) && (mirror_conf->pool_mask == 0)) { PMD_DEBUG_TRACE("Invalid mirror pool, pool mask can not be 0.\n"); return -EINVAL; } if ((mirror_conf->rule_type & ETH_MIRROR_VLAN) && mirror_conf->vlan.vlan_mask == 0) { PMD_DEBUG_TRACE("Invalid vlan mask, vlan mask can not be 0.\n"); return -EINVAL; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_set, -ENOTSUP); return (*dev->dev_ops->mirror_rule_set)(dev, mirror_conf, rule_id, on); } int rte_eth_mirror_rule_reset(uint8_t port_id, uint8_t rule_id) { struct rte_eth_dev *dev = &rte_eth_devices[port_id]; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->mirror_rule_reset, -ENOTSUP); return (*dev->dev_ops->mirror_rule_reset)(dev, rule_id); } #ifdef RTE_LIBRTE_ETHDEV_DEBUG uint16_t rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, 0); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, 0); if (queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id); return 0; } return (*dev->rx_pkt_burst)(dev->data->rx_queues[queue_id], rx_pkts, nb_pkts); } uint16_t rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, 0); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, 0); if (queue_id >= dev->data->nb_tx_queues) { PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id); return 0; } return (*dev->tx_pkt_burst)(dev->data->tx_queues[queue_id], tx_pkts, nb_pkts); } uint32_t rte_eth_rx_queue_count(uint8_t port_id, uint16_t queue_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, 0); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_count, 0); return (*dev->dev_ops->rx_queue_count)(dev, queue_id); } int rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_done, -ENOTSUP); return (*dev->dev_ops->rx_descriptor_done)(dev->data->rx_queues[queue_id], offset); } #endif int rte_eth_dev_callback_register(uint8_t port_id, enum rte_eth_event_type event, rte_eth_dev_cb_fn cb_fn, void *cb_arg) { struct rte_eth_dev *dev; struct rte_eth_dev_callback *user_cb; if (!cb_fn) return -EINVAL; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; rte_spinlock_lock(&rte_eth_dev_cb_lock); TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) { if (user_cb->cb_fn == cb_fn && user_cb->cb_arg == cb_arg && user_cb->event == event) { break; } } /* create a new callback. */ if (user_cb == NULL) user_cb = rte_zmalloc("INTR_USER_CALLBACK", sizeof(struct rte_eth_dev_callback), 0); if (user_cb != NULL) { user_cb->cb_fn = cb_fn; user_cb->cb_arg = cb_arg; user_cb->event = event; TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next); } rte_spinlock_unlock(&rte_eth_dev_cb_lock); return (user_cb == NULL) ? -ENOMEM : 0; } int rte_eth_dev_callback_unregister(uint8_t port_id, enum rte_eth_event_type event, rte_eth_dev_cb_fn cb_fn, void *cb_arg) { int ret; struct rte_eth_dev *dev; struct rte_eth_dev_callback *cb, *next; if (!cb_fn) return -EINVAL; VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; rte_spinlock_lock(&rte_eth_dev_cb_lock); ret = 0; for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) { next = TAILQ_NEXT(cb, next); if (cb->cb_fn != cb_fn || cb->event != event || (cb->cb_arg != (void *)-1 && cb->cb_arg != cb_arg)) continue; /* * if this callback is not executing right now, * then remove it. */ if (cb->active == 0) { TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next); rte_free(cb); } else { ret = -EAGAIN; } } rte_spinlock_unlock(&rte_eth_dev_cb_lock); return ret; } void _rte_eth_dev_callback_process(struct rte_eth_dev *dev, enum rte_eth_event_type event) { struct rte_eth_dev_callback *cb_lst; struct rte_eth_dev_callback dev_cb; rte_spinlock_lock(&rte_eth_dev_cb_lock); TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) { if (cb_lst->cb_fn == NULL || cb_lst->event != event) continue; dev_cb = *cb_lst; cb_lst->active = 1; rte_spinlock_unlock(&rte_eth_dev_cb_lock); dev_cb.cb_fn(dev->data->port_id, dev_cb.event, dev_cb.cb_arg); rte_spinlock_lock(&rte_eth_dev_cb_lock); cb_lst->active = 0; } rte_spinlock_unlock(&rte_eth_dev_cb_lock); } #ifdef RTE_NEXT_ABI int rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data) { uint32_t vec; struct rte_eth_dev *dev; struct rte_intr_handle *intr_handle; uint16_t qid; int rc; if (!rte_eth_dev_is_valid_port(port_id)) { PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id); return -ENODEV; } dev = &rte_eth_devices[port_id]; intr_handle = &dev->pci_dev->intr_handle; if (!intr_handle->intr_vec) { PMD_DEBUG_TRACE("RX Intr vector unset\n"); return -EPERM; } for (qid = 0; qid < dev->data->nb_rx_queues; qid++) { vec = intr_handle->intr_vec[qid]; rc = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data); if (rc && rc != -EEXIST) { PMD_DEBUG_TRACE("p %u q %u rx ctl error" " op %d epfd %d vec %u\n", port_id, qid, op, epfd, vec); } } return 0; } int rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id, int epfd, int op, void *data) { uint32_t vec; struct rte_eth_dev *dev; struct rte_intr_handle *intr_handle; int rc; if (!rte_eth_dev_is_valid_port(port_id)) { PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id); return -ENODEV; } dev = &rte_eth_devices[port_id]; if (queue_id >= dev->data->nb_rx_queues) { PMD_DEBUG_TRACE("Invalid RX queue_id=%u\n", queue_id); return -EINVAL; } intr_handle = &dev->pci_dev->intr_handle; if (!intr_handle->intr_vec) { PMD_DEBUG_TRACE("RX Intr vector unset\n"); return -EPERM; } vec = intr_handle->intr_vec[queue_id]; rc = rte_intr_rx_ctl(intr_handle, epfd, op, vec, data); if (rc && rc != -EEXIST) { PMD_DEBUG_TRACE("p %u q %u rx ctl error" " op %d epfd %d vec %u\n", port_id, queue_id, op, epfd, vec); return rc; } return 0; } int rte_eth_dev_rx_intr_enable(uint8_t port_id, uint16_t queue_id) { struct rte_eth_dev *dev; if (!rte_eth_dev_is_valid_port(port_id)) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -ENODEV; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_intr_enable, -ENOTSUP); return (*dev->dev_ops->rx_queue_intr_enable)(dev, queue_id); } int rte_eth_dev_rx_intr_disable(uint8_t port_id, uint16_t queue_id) { struct rte_eth_dev *dev; if (!rte_eth_dev_is_valid_port(port_id)) { PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); return -ENODEV; } dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_intr_disable, -ENOTSUP); return (*dev->dev_ops->rx_queue_intr_disable)(dev, queue_id); } #else int rte_eth_dev_rx_intr_enable(uint8_t port_id, uint16_t queue_id) { RTE_SET_USED(port_id); RTE_SET_USED(queue_id); return -ENOTSUP; } int rte_eth_dev_rx_intr_disable(uint8_t port_id, uint16_t queue_id) { RTE_SET_USED(port_id); RTE_SET_USED(queue_id); return -ENOTSUP; } int rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data) { RTE_SET_USED(port_id); RTE_SET_USED(epfd); RTE_SET_USED(op); RTE_SET_USED(data); return -1; } int rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id, int epfd, int op, void *data) { RTE_SET_USED(port_id); RTE_SET_USED(queue_id); RTE_SET_USED(epfd); RTE_SET_USED(op); RTE_SET_USED(data); return -1; } #endif #ifdef RTE_NIC_BYPASS int rte_eth_dev_bypass_init(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_init, -ENOTSUP); (*dev->dev_ops->bypass_init)(dev); return 0; } int rte_eth_dev_bypass_state_show(uint8_t port_id, uint32_t *state) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_state_show, -ENOTSUP); (*dev->dev_ops->bypass_state_show)(dev, state); return 0; } int rte_eth_dev_bypass_state_set(uint8_t port_id, uint32_t *new_state) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_state_set, -ENOTSUP); (*dev->dev_ops->bypass_state_set)(dev, new_state); return 0; } int rte_eth_dev_bypass_event_show(uint8_t port_id, uint32_t event, uint32_t *state) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_state_show, -ENOTSUP); (*dev->dev_ops->bypass_event_show)(dev, event, state); return 0; } int rte_eth_dev_bypass_event_store(uint8_t port_id, uint32_t event, uint32_t state) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_event_set, -ENOTSUP); (*dev->dev_ops->bypass_event_set)(dev, event, state); return 0; } int rte_eth_dev_wd_timeout_store(uint8_t port_id, uint32_t timeout) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_wd_timeout_set, -ENOTSUP); (*dev->dev_ops->bypass_wd_timeout_set)(dev, timeout); return 0; } int rte_eth_dev_bypass_ver_show(uint8_t port_id, uint32_t *ver) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_ver_show, -ENOTSUP); (*dev->dev_ops->bypass_ver_show)(dev, ver); return 0; } int rte_eth_dev_bypass_wd_timeout_show(uint8_t port_id, uint32_t *wd_timeout) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_wd_timeout_show, -ENOTSUP); (*dev->dev_ops->bypass_wd_timeout_show)(dev, wd_timeout); return 0; } int rte_eth_dev_bypass_wd_reset(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->bypass_wd_reset, -ENOTSUP); (*dev->dev_ops->bypass_wd_reset)(dev); return 0; } #endif int rte_eth_dev_filter_supported(uint8_t port_id, enum rte_filter_type filter_type) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP); return (*dev->dev_ops->filter_ctrl)(dev, filter_type, RTE_ETH_FILTER_NOP, NULL); } int rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->filter_ctrl, -ENOTSUP); return (*dev->dev_ops->filter_ctrl)(dev, filter_type, filter_op, arg); } void * rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id, rte_rx_callback_fn fn, void *user_param) { #ifndef RTE_ETHDEV_RXTX_CALLBACKS rte_errno = ENOTSUP; return NULL; #endif /* check input parameters */ if (!rte_eth_dev_is_valid_port(port_id) || fn == NULL || queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) { rte_errno = EINVAL; return NULL; } struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0); if (cb == NULL) { rte_errno = ENOMEM; return NULL; } cb->fn.rx = fn; cb->param = user_param; /* Add the callbacks in fifo order. */ struct rte_eth_rxtx_callback *tail = rte_eth_devices[port_id].post_rx_burst_cbs[queue_id]; if (!tail) { rte_eth_devices[port_id].post_rx_burst_cbs[queue_id] = cb; } else { while (tail->next) tail = tail->next; tail->next = cb; } return cb; } void * rte_eth_add_tx_callback(uint8_t port_id, uint16_t queue_id, rte_tx_callback_fn fn, void *user_param) { #ifndef RTE_ETHDEV_RXTX_CALLBACKS rte_errno = ENOTSUP; return NULL; #endif /* check input parameters */ if (!rte_eth_dev_is_valid_port(port_id) || fn == NULL || queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) { rte_errno = EINVAL; return NULL; } struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0); if (cb == NULL) { rte_errno = ENOMEM; return NULL; } cb->fn.tx = fn; cb->param = user_param; /* Add the callbacks in fifo order. */ struct rte_eth_rxtx_callback *tail = rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id]; if (!tail) { rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id] = cb; } else { while (tail->next) tail = tail->next; tail->next = cb; } return cb; } int rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id, struct rte_eth_rxtx_callback *user_cb) { #ifndef RTE_ETHDEV_RXTX_CALLBACKS return -ENOTSUP; #endif /* Check input parameters. */ if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL || queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) { return -EINVAL; } struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct rte_eth_rxtx_callback *cb = dev->post_rx_burst_cbs[queue_id]; struct rte_eth_rxtx_callback *prev_cb; /* Reset head pointer and remove user cb if first in the list. */ if (cb == user_cb) { dev->post_rx_burst_cbs[queue_id] = user_cb->next; return 0; } /* Remove the user cb from the callback list. */ do { prev_cb = cb; cb = cb->next; if (cb == user_cb) { prev_cb->next = user_cb->next; return 0; } } while (cb != NULL); /* Callback wasn't found. */ return -EINVAL; } int rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id, struct rte_eth_rxtx_callback *user_cb) { #ifndef RTE_ETHDEV_RXTX_CALLBACKS return -ENOTSUP; #endif /* Check input parameters. */ if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL || queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) { return -EINVAL; } struct rte_eth_dev *dev = &rte_eth_devices[port_id]; struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id]; struct rte_eth_rxtx_callback *prev_cb; /* Reset head pointer and remove user cb if first in the list. */ if (cb == user_cb) { dev->pre_tx_burst_cbs[queue_id] = user_cb->next; return 0; } /* Remove the user cb from the callback list. */ do { prev_cb = cb; cb = cb->next; if (cb == user_cb) { prev_cb->next = user_cb->next; return 0; } } while (cb != NULL); /* Callback wasn't found. */ return -EINVAL; } int rte_eth_dev_set_mc_addr_list(uint8_t port_id, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_mc_addr_list, -ENOTSUP); return dev->dev_ops->set_mc_addr_list(dev, mc_addr_set, nb_mc_addr); } int rte_eth_timesync_enable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->timesync_enable, -ENOTSUP); return (*dev->dev_ops->timesync_enable)(dev); } int rte_eth_timesync_disable(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->timesync_disable, -ENOTSUP); return (*dev->dev_ops->timesync_disable)(dev); } int rte_eth_timesync_read_rx_timestamp(uint8_t port_id, struct timespec *timestamp, uint32_t flags) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->timesync_read_rx_timestamp, -ENOTSUP); return (*dev->dev_ops->timesync_read_rx_timestamp)(dev, timestamp, flags); } int rte_eth_timesync_read_tx_timestamp(uint8_t port_id, struct timespec *timestamp) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->timesync_read_tx_timestamp, -ENOTSUP); return (*dev->dev_ops->timesync_read_tx_timestamp)(dev, timestamp); } int rte_eth_dev_get_reg_length(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg_length, -ENOTSUP); return (*dev->dev_ops->get_reg_length)(dev); } int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg, -ENOTSUP); return (*dev->dev_ops->get_reg)(dev, info); } int rte_eth_dev_get_eeprom_length(uint8_t port_id) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_eeprom_length, -ENOTSUP); return (*dev->dev_ops->get_eeprom_length)(dev); } int rte_eth_dev_get_eeprom(uint8_t port_id, struct rte_dev_eeprom_info *info) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_eeprom, -ENOTSUP); return (*dev->dev_ops->get_eeprom)(dev, info); } int rte_eth_dev_set_eeprom(uint8_t port_id, struct rte_dev_eeprom_info *info) { struct rte_eth_dev *dev; VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_eeprom, -ENOTSUP); return (*dev->dev_ops->set_eeprom)(dev, info); } ================================================ FILE: lib/librte_ether/rte_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETHDEV_H_ #define _RTE_ETHDEV_H_ /** * @file * * RTE Ethernet Device API * * The Ethernet Device API is composed of two parts: * * - The application-oriented Ethernet API that includes functions to setup * an Ethernet device (configure it, setup its RX and TX queues and start it), * to get its MAC address, the speed and the status of its physical link, * to receive and to transmit packets, and so on. * * - The driver-oriented Ethernet API that exports a function allowing * an Ethernet Poll Mode Driver (PMD) to simultaneously register itself as * an Ethernet device driver and as a PCI driver for a set of matching PCI * [Ethernet] devices classes. * * By default, all the functions of the Ethernet Device API exported by a PMD * are lock-free functions which assume to not be invoked in parallel on * different logical cores to work on the same target object. For instance, * the receive function of a PMD cannot be invoked in parallel on two logical * cores to poll the same RX queue [of the same port]. Of course, this function * can be invoked in parallel by different logical cores on different RX queues. * It is the responsibility of the upper level application to enforce this rule. * * If needed, parallel accesses by multiple logical cores to shared queues * shall be explicitly protected by dedicated inline lock-aware functions * built on top of their corresponding lock-free functions of the PMD API. * * In all functions of the Ethernet API, the Ethernet device is * designated by an integer >= 0 named the device port identifier. * * At the Ethernet driver level, Ethernet devices are represented by a generic * data structure of type *rte_eth_dev*. * * Ethernet devices are dynamically registered during the PCI probing phase * performed at EAL initialization time. * When an Ethernet device is being probed, an *rte_eth_dev* structure and * a new port identifier are allocated for that device. Then, the eth_dev_init() * function supplied by the Ethernet driver matching the probed PCI * device is invoked to properly initialize the device. * * The role of the device init function consists of resetting the hardware, * checking access to Non-volatile Memory (NVM), reading the MAC address * from NVM etc. * * If the device init operation is successful, the correspondence between * the port identifier assigned to the new device and its associated * *rte_eth_dev* structure is effectively registered. * Otherwise, both the *rte_eth_dev* structure and the port identifier are * freed. * * The functions exported by the application Ethernet API to setup a device * designated by its port identifier must be invoked in the following order: * - rte_eth_dev_configure() * - rte_eth_tx_queue_setup() * - rte_eth_rx_queue_setup() * - rte_eth_dev_start() * * Then, the network application can invoke, in any order, the functions * exported by the Ethernet API to get the MAC address of a given device, to * get the speed and the status of a device physical link, to receive/transmit * [burst of] packets, and so on. * * If the application wants to change the configuration (i.e. call * rte_eth_dev_configure(), rte_eth_tx_queue_setup(), or * rte_eth_rx_queue_setup()), it must call rte_eth_dev_stop() first to stop the * device and then do the reconfiguration before calling rte_eth_dev_start() * again. The tramsit and receive functions should not be invoked when the * device is stopped. * * Please note that some configuration is not stored between calls to * rte_eth_dev_stop()/rte_eth_dev_start(). The following configuration will * be retained: * * - flow control settings * - receive mode configuration (promiscuous mode, hardware checksum mode, * RSS/VMDQ settings etc.) * - VLAN filtering configuration * - MAC addresses supplied to MAC address array * - flow director filtering mode (but not filtering rules) * - NIC queue statistics mappings * * Any other configuration will not be stored and will need to be re-entered * after a call to rte_eth_dev_start(). * * Finally, a network application can close an Ethernet device by invoking the * rte_eth_dev_close() function. * * Each function of the application Ethernet API invokes a specific function * of the PMD that controls the target device designated by its port * identifier. * For this purpose, all device-specific functions of an Ethernet driver are * supplied through a set of pointers contained in a generic structure of type * *eth_dev_ops*. * The address of the *eth_dev_ops* structure is stored in the *rte_eth_dev* * structure by the device init function of the Ethernet driver, which is * invoked during the PCI probing phase, as explained earlier. * * In other words, each function of the Ethernet API simply retrieves the * *rte_eth_dev* structure associated with the device port identifier and * performs an indirect invocation of the corresponding driver function * supplied in the *eth_dev_ops* structure of the *rte_eth_dev* structure. * * For performance reasons, the address of the burst-oriented RX and TX * functions of the Ethernet driver are not contained in the *eth_dev_ops* * structure. Instead, they are directly stored at the beginning of the * *rte_eth_dev* structure to avoid an extra indirect memory access during * their invocation. * * RTE ethernet device drivers do not use interrupts for transmitting or * receiving. Instead, Ethernet drivers export Poll-Mode receive and transmit * functions to applications. * Both receive and transmit functions are packet-burst oriented to minimize * their cost per packet through the following optimizations: * * - Sharing among multiple packets the incompressible cost of the * invocation of receive/transmit functions. * * - Enabling receive/transmit functions to take advantage of burst-oriented * hardware features (L1 cache, prefetch instructions, NIC head/tail * registers) to minimize the number of CPU cycles per packet, for instance, * by avoiding useless read memory accesses to ring descriptors, or by * systematically using arrays of pointers that exactly fit L1 cache line * boundaries and sizes. * * The burst-oriented receive function does not provide any error notification, * to avoid the corresponding overhead. As a hint, the upper-level application * might check the status of the device link once being systematically returned * a 0 value by the receive function of the driver for a given number of tries. */ #ifdef __cplusplus extern "C" { #endif #include /* Use this macro to check if LRO API is supported */ #define RTE_ETHDEV_HAS_LRO_SUPPORT #include #include #include #include #include #include "rte_ether.h" #include "rte_eth_ctrl.h" #include "rte_dev_info.h" struct rte_mbuf; /** * A structure used to retrieve statistics for an Ethernet port. */ struct rte_eth_stats { uint64_t ipackets; /**< Total number of successfully received packets. */ uint64_t opackets; /**< Total number of successfully transmitted packets.*/ uint64_t ibytes; /**< Total number of successfully received bytes. */ uint64_t obytes; /**< Total number of successfully transmitted bytes. */ uint64_t imissed; /**< Deprecated; Total of RX missed packets (e.g full FIFO). */ uint64_t ibadcrc; /**< Deprecated; Total of RX packets with CRC error. */ uint64_t ibadlen; /**< Deprecated; Total of RX packets with bad length. */ uint64_t ierrors; /**< Total number of erroneous received packets. */ uint64_t oerrors; /**< Total number of failed transmitted packets. */ uint64_t imcasts; /**< Deprecated; Total number of multicast received packets. */ uint64_t rx_nombuf; /**< Total number of RX mbuf allocation failures. */ uint64_t fdirmatch; /**< Deprecated; Total number of RX packets matching a filter. */ uint64_t fdirmiss; /**< Deprecated; Total number of RX packets not matching any filter. */ uint64_t tx_pause_xon; /**< Deprecated; Total nb. of XON pause frame sent. */ uint64_t rx_pause_xon; /**< Deprecated; Total nb. of XON pause frame received. */ uint64_t tx_pause_xoff; /**< Deprecated; Total nb. of XOFF pause frame sent. */ uint64_t rx_pause_xoff; /**< Deprecated; Total nb. of XOFF pause frame received. */ uint64_t q_ipackets[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /**< Total number of queue RX packets. */ uint64_t q_opackets[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /**< Total number of queue TX packets. */ uint64_t q_ibytes[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /**< Total number of successfully received queue bytes. */ uint64_t q_obytes[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /**< Total number of successfully transmitted queue bytes. */ uint64_t q_errors[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /**< Total number of queue packets received that are dropped. */ uint64_t ilbpackets; /**< Total number of good packets received from loopback,VF Only */ uint64_t olbpackets; /**< Total number of good packets transmitted to loopback,VF Only */ uint64_t ilbbytes; /**< Total number of good bytes received from loopback,VF Only */ uint64_t olbbytes; /**< Total number of good bytes transmitted to loopback,VF Only */ }; /** * A structure used to retrieve link-level information of an Ethernet port. */ struct rte_eth_link { uint16_t link_speed; /**< ETH_LINK_SPEED_[10, 100, 1000, 10000] */ uint16_t link_duplex; /**< ETH_LINK_[HALF_DUPLEX, FULL_DUPLEX] */ uint8_t link_status : 1; /**< 1 -> link up, 0 -> link down */ }__attribute__((aligned(8))); /**< aligned for atomic64 read/write */ #define ETH_LINK_SPEED_AUTONEG 0 /**< Auto-negotiate link speed. */ #define ETH_LINK_SPEED_10 10 /**< 10 megabits/second. */ #define ETH_LINK_SPEED_100 100 /**< 100 megabits/second. */ #define ETH_LINK_SPEED_1000 1000 /**< 1 gigabits/second. */ #define ETH_LINK_SPEED_10000 10000 /**< 10 gigabits/second. */ #define ETH_LINK_SPEED_10G 10000 /**< alias of 10 gigabits/second. */ #define ETH_LINK_SPEED_20G 20000 /**< 20 gigabits/second. */ #define ETH_LINK_SPEED_40G 40000 /**< 40 gigabits/second. */ #define ETH_LINK_AUTONEG_DUPLEX 0 /**< Auto-negotiate duplex. */ #define ETH_LINK_HALF_DUPLEX 1 /**< Half-duplex connection. */ #define ETH_LINK_FULL_DUPLEX 2 /**< Full-duplex connection. */ /** * A structure used to configure the ring threshold registers of an RX/TX * queue for an Ethernet port. */ struct rte_eth_thresh { uint8_t pthresh; /**< Ring prefetch threshold. */ uint8_t hthresh; /**< Ring host threshold. */ uint8_t wthresh; /**< Ring writeback threshold. */ }; /** * Simple flags are used for rte_eth_conf.rxmode.mq_mode. */ #define ETH_MQ_RX_RSS_FLAG 0x1 #define ETH_MQ_RX_DCB_FLAG 0x2 #define ETH_MQ_RX_VMDQ_FLAG 0x4 /** * A set of values to identify what method is to be used to route * packets to multiple queues. */ enum rte_eth_rx_mq_mode { /** None of DCB,RSS or VMDQ mode */ ETH_MQ_RX_NONE = 0, /** For RX side, only RSS is on */ ETH_MQ_RX_RSS = ETH_MQ_RX_RSS_FLAG, /** For RX side,only DCB is on. */ ETH_MQ_RX_DCB = ETH_MQ_RX_DCB_FLAG, /** Both DCB and RSS enable */ ETH_MQ_RX_DCB_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_DCB_FLAG, /** Only VMDQ, no RSS nor DCB */ ETH_MQ_RX_VMDQ_ONLY = ETH_MQ_RX_VMDQ_FLAG, /** RSS mode with VMDQ */ ETH_MQ_RX_VMDQ_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_VMDQ_FLAG, /** Use VMDQ+DCB to route traffic to queues */ ETH_MQ_RX_VMDQ_DCB = ETH_MQ_RX_VMDQ_FLAG | ETH_MQ_RX_DCB_FLAG, /** Enable both VMDQ and DCB in VMDq */ ETH_MQ_RX_VMDQ_DCB_RSS = ETH_MQ_RX_RSS_FLAG | ETH_MQ_RX_DCB_FLAG | ETH_MQ_RX_VMDQ_FLAG, }; /** * for rx mq mode backward compatible */ #define ETH_RSS ETH_MQ_RX_RSS #define VMDQ_DCB ETH_MQ_RX_VMDQ_DCB #define ETH_DCB_RX ETH_MQ_RX_DCB /** * A set of values to identify what method is to be used to transmit * packets using multi-TCs. */ enum rte_eth_tx_mq_mode { ETH_MQ_TX_NONE = 0, /**< It is in neither DCB nor VT mode. */ ETH_MQ_TX_DCB, /**< For TX side,only DCB is on. */ ETH_MQ_TX_VMDQ_DCB, /**< For TX side,both DCB and VT is on. */ ETH_MQ_TX_VMDQ_ONLY, /**< Only VT on, no DCB */ }; /** * for tx mq mode backward compatible */ #define ETH_DCB_NONE ETH_MQ_TX_NONE #define ETH_VMDQ_DCB_TX ETH_MQ_TX_VMDQ_DCB #define ETH_DCB_TX ETH_MQ_TX_DCB /** * A structure used to configure the RX features of an Ethernet port. */ struct rte_eth_rxmode { /** The multi-queue packet distribution mode to be used, e.g. RSS. */ enum rte_eth_rx_mq_mode mq_mode; uint32_t max_rx_pkt_len; /**< Only used if jumbo_frame enabled. */ uint16_t split_hdr_size; /**< hdr buf size (header_split enabled).*/ uint16_t header_split : 1, /**< Header Split enable. */ hw_ip_checksum : 1, /**< IP/UDP/TCP checksum offload enable. */ hw_vlan_filter : 1, /**< VLAN filter enable. */ hw_vlan_strip : 1, /**< VLAN strip enable. */ hw_vlan_extend : 1, /**< Extended VLAN enable. */ jumbo_frame : 1, /**< Jumbo Frame Receipt enable. */ hw_strip_crc : 1, /**< Enable CRC stripping by hardware. */ enable_scatter : 1, /**< Enable scatter packets rx handler */ enable_lro : 1; /**< Enable LRO */ }; /** * A structure used to configure the Receive Side Scaling (RSS) feature * of an Ethernet port. * If not NULL, the *rss_key* pointer of the *rss_conf* structure points * to an array holding the RSS key to use for hashing specific header * fields of received packets. The length of this array should be indicated * by *rss_key_len* below. Otherwise, a default random hash key is used by * the device driver. * * The *rss_key_len* field of the *rss_conf* structure indicates the length * in bytes of the array pointed by *rss_key*. To be compatible, this length * will be checked in i40e only. Others assume 40 bytes to be used as before. * * The *rss_hf* field of the *rss_conf* structure indicates the different * types of IPv4/IPv6 packets to which the RSS hashing must be applied. * Supplying an *rss_hf* equal to zero disables the RSS feature. */ struct rte_eth_rss_conf { uint8_t *rss_key; /**< If not NULL, 40-byte hash key. */ uint8_t rss_key_len; /**< hash key length in bytes. */ uint64_t rss_hf; /**< Hash functions to apply - see below. */ }; /* * The RSS offload types are defined based on flow types which are defined * in rte_eth_ctrl.h. Different NIC hardwares may support different RSS offload * types. The supported flow types or RSS offload types can be queried by * rte_eth_dev_info_get(). */ #define ETH_RSS_IPV4 (1ULL << RTE_ETH_FLOW_IPV4) #define ETH_RSS_FRAG_IPV4 (1ULL << RTE_ETH_FLOW_FRAG_IPV4) #define ETH_RSS_NONFRAG_IPV4_TCP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) #define ETH_RSS_NONFRAG_IPV4_UDP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) #define ETH_RSS_NONFRAG_IPV4_SCTP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) #define ETH_RSS_NONFRAG_IPV4_OTHER (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) #define ETH_RSS_IPV6 (1ULL << RTE_ETH_FLOW_IPV6) #define ETH_RSS_FRAG_IPV6 (1ULL << RTE_ETH_FLOW_FRAG_IPV6) #define ETH_RSS_NONFRAG_IPV6_TCP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) #define ETH_RSS_NONFRAG_IPV6_UDP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) #define ETH_RSS_NONFRAG_IPV6_SCTP (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) #define ETH_RSS_NONFRAG_IPV6_OTHER (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) #define ETH_RSS_L2_PAYLOAD (1ULL << RTE_ETH_FLOW_L2_PAYLOAD) #define ETH_RSS_IPV6_EX (1ULL << RTE_ETH_FLOW_IPV6_EX) #define ETH_RSS_IPV6_TCP_EX (1ULL << RTE_ETH_FLOW_IPV6_TCP_EX) #define ETH_RSS_IPV6_UDP_EX (1ULL << RTE_ETH_FLOW_IPV6_UDP_EX) #define ETH_RSS_IP ( \ ETH_RSS_IPV4 | \ ETH_RSS_FRAG_IPV4 | \ ETH_RSS_NONFRAG_IPV4_OTHER | \ ETH_RSS_IPV6 | \ ETH_RSS_FRAG_IPV6 | \ ETH_RSS_NONFRAG_IPV6_OTHER | \ ETH_RSS_IPV6_EX) #define ETH_RSS_UDP ( \ ETH_RSS_NONFRAG_IPV4_UDP | \ ETH_RSS_NONFRAG_IPV6_UDP | \ ETH_RSS_IPV6_UDP_EX) #define ETH_RSS_TCP ( \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_NONFRAG_IPV6_TCP | \ ETH_RSS_IPV6_TCP_EX) #define ETH_RSS_SCTP ( \ ETH_RSS_NONFRAG_IPV4_SCTP | \ ETH_RSS_NONFRAG_IPV6_SCTP) /**< Mask of valid RSS hash protocols */ #define ETH_RSS_PROTO_MASK ( \ ETH_RSS_IPV4 | \ ETH_RSS_FRAG_IPV4 | \ ETH_RSS_NONFRAG_IPV4_TCP | \ ETH_RSS_NONFRAG_IPV4_UDP | \ ETH_RSS_NONFRAG_IPV4_SCTP | \ ETH_RSS_NONFRAG_IPV4_OTHER | \ ETH_RSS_IPV6 | \ ETH_RSS_FRAG_IPV6 | \ ETH_RSS_NONFRAG_IPV6_TCP | \ ETH_RSS_NONFRAG_IPV6_UDP | \ ETH_RSS_NONFRAG_IPV6_SCTP | \ ETH_RSS_NONFRAG_IPV6_OTHER | \ ETH_RSS_L2_PAYLOAD | \ ETH_RSS_IPV6_EX | \ ETH_RSS_IPV6_TCP_EX | \ ETH_RSS_IPV6_UDP_EX) /* * Definitions used for redirection table entry size. * Some RSS RETA sizes may not be supported by some drivers, check the * documentation or the description of relevant functions for more details. */ #define ETH_RSS_RETA_SIZE_64 64 #define ETH_RSS_RETA_SIZE_128 128 #define ETH_RSS_RETA_SIZE_512 512 #define RTE_RETA_GROUP_SIZE 64 /* Definitions used for VMDQ and DCB functionality */ #define ETH_VMDQ_MAX_VLAN_FILTERS 64 /**< Maximum nb. of VMDQ vlan filters. */ #define ETH_DCB_NUM_USER_PRIORITIES 8 /**< Maximum nb. of DCB priorities. */ #define ETH_VMDQ_DCB_NUM_QUEUES 128 /**< Maximum nb. of VMDQ DCB queues. */ #define ETH_DCB_NUM_QUEUES 128 /**< Maximum nb. of DCB queues. */ /* DCB capability defines */ #define ETH_DCB_PG_SUPPORT 0x00000001 /**< Priority Group(ETS) support. */ #define ETH_DCB_PFC_SUPPORT 0x00000002 /**< Priority Flow Control support. */ /* Definitions used for VLAN Offload functionality */ #define ETH_VLAN_STRIP_OFFLOAD 0x0001 /**< VLAN Strip On/Off */ #define ETH_VLAN_FILTER_OFFLOAD 0x0002 /**< VLAN Filter On/Off */ #define ETH_VLAN_EXTEND_OFFLOAD 0x0004 /**< VLAN Extend On/Off */ /* Definitions used for mask VLAN setting */ #define ETH_VLAN_STRIP_MASK 0x0001 /**< VLAN Strip setting mask */ #define ETH_VLAN_FILTER_MASK 0x0002 /**< VLAN Filter setting mask*/ #define ETH_VLAN_EXTEND_MASK 0x0004 /**< VLAN Extend setting mask*/ #define ETH_VLAN_ID_MAX 0x0FFF /**< VLAN ID is in lower 12 bits*/ /* Definitions used for receive MAC address */ #define ETH_NUM_RECEIVE_MAC_ADDR 128 /**< Maximum nb. of receive mac addr. */ /* Definitions used for unicast hash */ #define ETH_VMDQ_NUM_UC_HASH_ARRAY 128 /**< Maximum nb. of UC hash array. */ /* Definitions used for VMDQ pool rx mode setting */ #define ETH_VMDQ_ACCEPT_UNTAG 0x0001 /**< accept untagged packets. */ #define ETH_VMDQ_ACCEPT_HASH_MC 0x0002 /**< accept packets in multicast table . */ #define ETH_VMDQ_ACCEPT_HASH_UC 0x0004 /**< accept packets in unicast table. */ #define ETH_VMDQ_ACCEPT_BROADCAST 0x0008 /**< accept broadcast packets. */ #define ETH_VMDQ_ACCEPT_MULTICAST 0x0010 /**< multicast promiscuous. */ /** Maximum nb. of vlan per mirror rule */ #define ETH_MIRROR_MAX_VLANS 64 #define ETH_MIRROR_VIRTUAL_POOL_UP 0x01 /**< Virtual Pool uplink Mirroring. */ #define ETH_MIRROR_UPLINK_PORT 0x02 /**< Uplink Port Mirroring. */ #define ETH_MIRROR_DOWNLINK_PORT 0x04 /**< Downlink Port Mirroring. */ #define ETH_MIRROR_VLAN 0x08 /**< VLAN Mirroring. */ #define ETH_MIRROR_VIRTUAL_POOL_DOWN 0x10 /**< Virtual Pool downlink Mirroring. */ /** * A structure used to configure VLAN traffic mirror of an Ethernet port. */ struct rte_eth_vlan_mirror { uint64_t vlan_mask; /**< mask for valid VLAN ID. */ /** VLAN ID list for vlan mirroring. */ uint16_t vlan_id[ETH_MIRROR_MAX_VLANS]; }; /** * A structure used to configure traffic mirror of an Ethernet port. */ struct rte_eth_mirror_conf { uint8_t rule_type; /**< Mirroring rule type */ uint8_t dst_pool; /**< Destination pool for this mirror rule. */ uint64_t pool_mask; /**< Bitmap of pool for pool mirroring */ /** VLAN ID setting for VLAN mirroring. */ struct rte_eth_vlan_mirror vlan; }; /** * A structure used to configure 64 entries of Redirection Table of the * Receive Side Scaling (RSS) feature of an Ethernet port. To configure * more than 64 entries supported by hardware, an array of this structure * is needed. */ struct rte_eth_rss_reta_entry64 { uint64_t mask; /**< Mask bits indicate which entries need to be updated/queried. */ uint8_t reta[RTE_RETA_GROUP_SIZE]; /**< Group of 64 redirection table entries. */ }; /** * This enum indicates the possible number of traffic classes * in DCB configratioins */ enum rte_eth_nb_tcs { ETH_4_TCS = 4, /**< 4 TCs with DCB. */ ETH_8_TCS = 8 /**< 8 TCs with DCB. */ }; /** * This enum indicates the possible number of queue pools * in VMDQ configurations. */ enum rte_eth_nb_pools { ETH_8_POOLS = 8, /**< 8 VMDq pools. */ ETH_16_POOLS = 16, /**< 16 VMDq pools. */ ETH_32_POOLS = 32, /**< 32 VMDq pools. */ ETH_64_POOLS = 64 /**< 64 VMDq pools. */ }; /* This structure may be extended in future. */ struct rte_eth_dcb_rx_conf { enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs */ uint8_t dcb_queue[ETH_DCB_NUM_USER_PRIORITIES]; /**< Possible DCB queue,4 or 8. */ }; struct rte_eth_vmdq_dcb_tx_conf { enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools. */ uint8_t dcb_queue[ETH_DCB_NUM_USER_PRIORITIES]; /**< Possible DCB queue,4 or 8. */ }; struct rte_eth_dcb_tx_conf { enum rte_eth_nb_tcs nb_tcs; /**< Possible DCB TCs, 4 or 8 TCs. */ uint8_t dcb_queue[ETH_DCB_NUM_USER_PRIORITIES]; /**< Possible DCB queue,4 or 8. */ }; struct rte_eth_vmdq_tx_conf { enum rte_eth_nb_pools nb_queue_pools; /**< VMDq mode, 64 pools. */ }; /** * A structure used to configure the VMDQ+DCB feature * of an Ethernet port. * * Using this feature, packets are routed to a pool of queues, based * on the vlan id in the vlan tag, and then to a specific queue within * that pool, using the user priority vlan tag field. * * A default pool may be used, if desired, to route all traffic which * does not match the vlan filter rules. */ struct rte_eth_vmdq_dcb_conf { enum rte_eth_nb_pools nb_queue_pools; /**< With DCB, 16 or 32 pools */ uint8_t enable_default_pool; /**< If non-zero, use a default pool */ uint8_t default_pool; /**< The default pool, if applicable */ uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ struct { uint16_t vlan_id; /**< The vlan id of the received frame */ uint64_t pools; /**< Bitmask of pools for packet rx */ } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ uint8_t dcb_queue[ETH_DCB_NUM_USER_PRIORITIES]; /**< Selects a queue in a pool */ }; struct rte_eth_vmdq_rx_conf { enum rte_eth_nb_pools nb_queue_pools; /**< VMDq only mode, 8 or 64 pools */ uint8_t enable_default_pool; /**< If non-zero, use a default pool */ uint8_t default_pool; /**< The default pool, if applicable */ uint8_t enable_loop_back; /**< Enable VT loop back */ uint8_t nb_pool_maps; /**< We can have up to 64 filters/mappings */ uint32_t rx_mode; /**< Flags from ETH_VMDQ_ACCEPT_* */ struct { uint16_t vlan_id; /**< The vlan id of the received frame */ uint64_t pools; /**< Bitmask of pools for packet rx */ } pool_map[ETH_VMDQ_MAX_VLAN_FILTERS]; /**< VMDq vlan pool maps. */ }; /** * A structure used to configure the TX features of an Ethernet port. */ struct rte_eth_txmode { enum rte_eth_tx_mq_mode mq_mode; /**< TX multi-queues mode. */ /* For i40e specifically */ uint16_t pvid; uint8_t hw_vlan_reject_tagged : 1, /**< If set, reject sending out tagged pkts */ hw_vlan_reject_untagged : 1, /**< If set, reject sending out untagged pkts */ hw_vlan_insert_pvid : 1; /**< If set, enable port based VLAN insertion */ }; /** * A structure used to configure an RX ring of an Ethernet port. */ struct rte_eth_rxconf { struct rte_eth_thresh rx_thresh; /**< RX ring threshold registers. */ uint16_t rx_free_thresh; /**< Drives the freeing of RX descriptors. */ uint8_t rx_drop_en; /**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */ }; #define ETH_TXQ_FLAGS_NOMULTSEGS 0x0001 /**< nb_segs=1 for all mbufs */ #define ETH_TXQ_FLAGS_NOREFCOUNT 0x0002 /**< refcnt can be ignored */ #define ETH_TXQ_FLAGS_NOMULTMEMP 0x0004 /**< all bufs come from same mempool */ #define ETH_TXQ_FLAGS_NOVLANOFFL 0x0100 /**< disable VLAN offload */ #define ETH_TXQ_FLAGS_NOXSUMSCTP 0x0200 /**< disable SCTP checksum offload */ #define ETH_TXQ_FLAGS_NOXSUMUDP 0x0400 /**< disable UDP checksum offload */ #define ETH_TXQ_FLAGS_NOXSUMTCP 0x0800 /**< disable TCP checksum offload */ #define ETH_TXQ_FLAGS_NOOFFLOADS \ (ETH_TXQ_FLAGS_NOVLANOFFL | ETH_TXQ_FLAGS_NOXSUMSCTP | \ ETH_TXQ_FLAGS_NOXSUMUDP | ETH_TXQ_FLAGS_NOXSUMTCP) #define ETH_TXQ_FLAGS_NOXSUMS \ (ETH_TXQ_FLAGS_NOXSUMSCTP | ETH_TXQ_FLAGS_NOXSUMUDP | \ ETH_TXQ_FLAGS_NOXSUMTCP) /** * A structure used to configure a TX ring of an Ethernet port. */ struct rte_eth_txconf { struct rte_eth_thresh tx_thresh; /**< TX ring threshold registers. */ uint16_t tx_rs_thresh; /**< Drives the setting of RS bit on TXDs. */ uint16_t tx_free_thresh; /**< Start freeing TX buffers if there are less free descriptors than this value. */ uint32_t txq_flags; /**< Set flags for the Tx queue */ uint8_t tx_deferred_start; /**< Do not start queue with rte_eth_dev_start(). */ }; /** * This enum indicates the flow control mode */ enum rte_eth_fc_mode { RTE_FC_NONE = 0, /**< Disable flow control. */ RTE_FC_RX_PAUSE, /**< RX pause frame, enable flowctrl on TX side. */ RTE_FC_TX_PAUSE, /**< TX pause frame, enable flowctrl on RX side. */ RTE_FC_FULL /**< Enable flow control on both side. */ }; /** * A structure used to configure Ethernet flow control parameter. * These parameters will be configured into the register of the NIC. * Please refer to the corresponding data sheet for proper value. */ struct rte_eth_fc_conf { uint32_t high_water; /**< High threshold value to trigger XOFF */ uint32_t low_water; /**< Low threshold value to trigger XON */ uint16_t pause_time; /**< Pause quota in the Pause frame */ uint16_t send_xon; /**< Is XON frame need be sent */ enum rte_eth_fc_mode mode; /**< Link flow control mode */ uint8_t mac_ctrl_frame_fwd; /**< Forward MAC control frames */ uint8_t autoneg; /**< Use Pause autoneg */ }; /** * A structure used to configure Ethernet priority flow control parameter. * These parameters will be configured into the register of the NIC. * Please refer to the corresponding data sheet for proper value. */ struct rte_eth_pfc_conf { struct rte_eth_fc_conf fc; /**< General flow control parameter. */ uint8_t priority; /**< VLAN User Priority. */ }; /** * Memory space that can be configured to store Flow Director filters * in the board memory. */ enum rte_fdir_pballoc_type { RTE_FDIR_PBALLOC_64K = 0, /**< 64k. */ RTE_FDIR_PBALLOC_128K, /**< 128k. */ RTE_FDIR_PBALLOC_256K, /**< 256k. */ }; /** * Select report mode of FDIR hash information in RX descriptors. */ enum rte_fdir_status_mode { RTE_FDIR_NO_REPORT_STATUS = 0, /**< Never report FDIR hash. */ RTE_FDIR_REPORT_STATUS, /**< Only report FDIR hash for matching pkts. */ RTE_FDIR_REPORT_STATUS_ALWAYS, /**< Always report FDIR hash. */ }; /** * A structure used to configure the Flow Director (FDIR) feature * of an Ethernet port. * * If mode is RTE_FDIR_DISABLE, the pballoc value is ignored. */ struct rte_fdir_conf { enum rte_fdir_mode mode; /**< Flow Director mode. */ enum rte_fdir_pballoc_type pballoc; /**< Space for FDIR filters. */ enum rte_fdir_status_mode status; /**< How to report FDIR hash. */ /** RX queue of packets matching a "drop" filter in perfect mode. */ uint8_t drop_queue; struct rte_eth_fdir_masks mask; struct rte_eth_fdir_flex_conf flex_conf; /**< Flex payload configuration. */ }; /** * UDP tunneling configuration. */ struct rte_eth_udp_tunnel { uint16_t udp_port; uint8_t prot_type; }; /** * Possible l4type of FDIR filters. */ enum rte_l4type { RTE_FDIR_L4TYPE_NONE = 0, /**< None. */ RTE_FDIR_L4TYPE_UDP, /**< UDP. */ RTE_FDIR_L4TYPE_TCP, /**< TCP. */ RTE_FDIR_L4TYPE_SCTP, /**< SCTP. */ }; /** * Select IPv4 or IPv6 FDIR filters. */ enum rte_iptype { RTE_FDIR_IPTYPE_IPV4 = 0, /**< IPv4. */ RTE_FDIR_IPTYPE_IPV6 , /**< IPv6. */ }; /** * A structure used to define a FDIR packet filter. */ struct rte_fdir_filter { uint16_t flex_bytes; /**< Flex bytes value to match. */ uint16_t vlan_id; /**< VLAN ID value to match, 0 otherwise. */ uint16_t port_src; /**< Source port to match, 0 otherwise. */ uint16_t port_dst; /**< Destination port to match, 0 otherwise. */ union { uint32_t ipv4_addr; /**< IPv4 source address to match. */ uint32_t ipv6_addr[4]; /**< IPv6 source address to match. */ } ip_src; /**< IPv4/IPv6 source address to match (union of above). */ union { uint32_t ipv4_addr; /**< IPv4 destination address to match. */ uint32_t ipv6_addr[4]; /**< IPv6 destination address to match */ } ip_dst; /**< IPv4/IPv6 destination address to match (union of above). */ enum rte_l4type l4type; /**< l4type to match: NONE/UDP/TCP/SCTP. */ enum rte_iptype iptype; /**< IP packet type to match: IPv4 or IPv6. */ }; /** * A structure used to configure FDIR masks that are used by the device * to match the various fields of RX packet headers. * @note The only_ip_flow field has the opposite meaning compared to other * masks! */ struct rte_fdir_masks { /** When set to 1, packet l4type is \b NOT relevant in filters, and source and destination port masks must be set to zero. */ uint8_t only_ip_flow; /** If set to 1, vlan_id is relevant in filters. */ uint8_t vlan_id; /** If set to 1, vlan_prio is relevant in filters. */ uint8_t vlan_prio; /** If set to 1, flexbytes is relevant in filters. */ uint8_t flexbytes; /** If set to 1, set the IPv6 masks. Otherwise set the IPv4 masks. */ uint8_t set_ipv6_mask; /** When set to 1, comparison of destination IPv6 address with IP6AT registers is meaningful. */ uint8_t comp_ipv6_dst; /** Mask of Destination IPv4 Address. All bits set to 1 define the relevant bits to use in the destination address of an IPv4 packet when matching it against FDIR filters. */ uint32_t dst_ipv4_mask; /** Mask of Source IPv4 Address. All bits set to 1 define the relevant bits to use in the source address of an IPv4 packet when matching it against FDIR filters. */ uint32_t src_ipv4_mask; /** Mask of Source IPv6 Address. All bits set to 1 define the relevant BYTES to use in the source address of an IPv6 packet when matching it against FDIR filters. */ uint16_t dst_ipv6_mask; /** Mask of Destination IPv6 Address. All bits set to 1 define the relevant BYTES to use in the destination address of an IPv6 packet when matching it against FDIR filters. */ uint16_t src_ipv6_mask; /** Mask of Source Port. All bits set to 1 define the relevant bits to use in the source port of an IP packets when matching it against FDIR filters. */ uint16_t src_port_mask; /** Mask of Destination Port. All bits set to 1 define the relevant bits to use in the destination port of an IP packet when matching it against FDIR filters. */ uint16_t dst_port_mask; }; /** * A structure used to report the status of the flow director filters in use. */ struct rte_eth_fdir { /** Number of filters with collision indication. */ uint16_t collision; /** Number of free (non programmed) filters. */ uint16_t free; /** The Lookup hash value of the added filter that updated the value of the MAXLEN field */ uint16_t maxhash; /** Longest linked list of filters in the table. */ uint8_t maxlen; /** Number of added filters. */ uint64_t add; /** Number of removed filters. */ uint64_t remove; /** Number of failed added filters (no more space in device). */ uint64_t f_add; /** Number of failed removed filters. */ uint64_t f_remove; }; /** * A structure used to enable/disable specific device interrupts. */ struct rte_intr_conf { /** enable/disable lsc interrupt. 0 (default) - disable, 1 enable */ uint16_t lsc; #ifdef RTE_NEXT_ABI /** enable/disable rxq interrupt. 0 (default) - disable, 1 enable */ uint16_t rxq; #endif }; /** * A structure used to configure an Ethernet port. * Depending upon the RX multi-queue mode, extra advanced * configuration settings may be needed. */ struct rte_eth_conf { uint16_t link_speed; /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */ uint16_t link_duplex; /**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */ struct rte_eth_rxmode rxmode; /**< Port RX configuration. */ struct rte_eth_txmode txmode; /**< Port TX configuration. */ uint32_t lpbk_mode; /**< Loopback operation mode. By default the value is 0, meaning the loopback mode is disabled. Read the datasheet of given ethernet controller for details. The possible values of this field are defined in implementation of each driver. */ struct { struct rte_eth_rss_conf rss_conf; /**< Port RSS configuration */ struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf; /**< Port vmdq+dcb configuration. */ struct rte_eth_dcb_rx_conf dcb_rx_conf; /**< Port dcb RX configuration. */ struct rte_eth_vmdq_rx_conf vmdq_rx_conf; /**< Port vmdq RX configuration. */ } rx_adv_conf; /**< Port RX filtering configuration (union). */ union { struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf; /**< Port vmdq+dcb TX configuration. */ struct rte_eth_dcb_tx_conf dcb_tx_conf; /**< Port dcb TX configuration. */ struct rte_eth_vmdq_tx_conf vmdq_tx_conf; /**< Port vmdq TX configuration. */ } tx_adv_conf; /**< Port TX DCB configuration (union). */ /** Currently,Priority Flow Control(PFC) are supported,if DCB with PFC is needed,and the variable must be set ETH_DCB_PFC_SUPPORT. */ uint32_t dcb_capability_en; struct rte_fdir_conf fdir_conf; /**< FDIR configuration. */ struct rte_intr_conf intr_conf; /**< Interrupt mode configuration. */ }; /** * A structure used to retrieve the contextual information of * an Ethernet device, such as the controlling driver of the device, * its PCI context, etc... */ /** * RX offload capabilities of a device. */ #define DEV_RX_OFFLOAD_VLAN_STRIP 0x00000001 #define DEV_RX_OFFLOAD_IPV4_CKSUM 0x00000002 #define DEV_RX_OFFLOAD_UDP_CKSUM 0x00000004 #define DEV_RX_OFFLOAD_TCP_CKSUM 0x00000008 #define DEV_RX_OFFLOAD_TCP_LRO 0x00000010 #define DEV_RX_OFFLOAD_QINQ_STRIP 0x00000020 /** * TX offload capabilities of a device. */ #define DEV_TX_OFFLOAD_VLAN_INSERT 0x00000001 #define DEV_TX_OFFLOAD_IPV4_CKSUM 0x00000002 #define DEV_TX_OFFLOAD_UDP_CKSUM 0x00000004 #define DEV_TX_OFFLOAD_TCP_CKSUM 0x00000008 #define DEV_TX_OFFLOAD_SCTP_CKSUM 0x00000010 #define DEV_TX_OFFLOAD_TCP_TSO 0x00000020 #define DEV_TX_OFFLOAD_UDP_TSO 0x00000040 #define DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM 0x00000080 /**< Used for tunneling packet. */ #define DEV_TX_OFFLOAD_QINQ_INSERT 0x00000100 struct rte_eth_dev_info { struct rte_pci_device *pci_dev; /**< Device PCI information. */ const char *driver_name; /**< Device Driver name. */ unsigned int if_index; /**< Index to bound host interface, or 0 if none. Use if_indextoname() to translate into an interface name. */ uint32_t min_rx_bufsize; /**< Minimum size of RX buffer. */ uint32_t max_rx_pktlen; /**< Maximum configurable length of RX pkt. */ uint16_t max_rx_queues; /**< Maximum number of RX queues. */ uint16_t max_tx_queues; /**< Maximum number of TX queues. */ uint32_t max_mac_addrs; /**< Maximum number of MAC addresses. */ uint32_t max_hash_mac_addrs; /** Maximum number of hash MAC addresses for MTA and UTA. */ uint16_t max_vfs; /**< Maximum number of VFs. */ uint16_t max_vmdq_pools; /**< Maximum number of VMDq pools. */ uint32_t rx_offload_capa; /**< Device RX offload capabilities. */ uint32_t tx_offload_capa; /**< Device TX offload capabilities. */ uint16_t reta_size; /**< Device redirection table size, the total number of entries. */ uint8_t hash_key_size; /**< Hash key size in bytes */ /** Bit mask of RSS offloads, the bit offset also means flow type */ uint64_t flow_type_rss_offloads; struct rte_eth_rxconf default_rxconf; /**< Default RX configuration */ struct rte_eth_txconf default_txconf; /**< Default TX configuration */ uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */ uint16_t vmdq_queue_num; /**< Queue number for VMDQ pools. */ uint16_t vmdq_pool_base; /**< First ID of VMDQ pools. */ }; /** Maximum name length for extended statistics counters */ #define RTE_ETH_XSTATS_NAME_SIZE 64 /** * An Ethernet device extended statistic structure * * This structure is used by ethdev->eth_xstats_get() to provide * statistics that are not provided in the generic rte_eth_stats * structure. */ struct rte_eth_xstats { char name[RTE_ETH_XSTATS_NAME_SIZE]; uint64_t value; }; struct rte_eth_dev; struct rte_eth_dev_callback; /** @internal Structure to keep track of registered callbacks */ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback); /* * Definitions of all functions exported by an Ethernet driver through the * the generic structure of type *eth_dev_ops* supplied in the *rte_eth_dev* * structure associated with an Ethernet device. */ typedef int (*eth_dev_configure_t)(struct rte_eth_dev *dev); /**< @internal Ethernet device configuration. */ typedef int (*eth_dev_start_t)(struct rte_eth_dev *dev); /**< @internal Function used to start a configured Ethernet device. */ typedef void (*eth_dev_stop_t)(struct rte_eth_dev *dev); /**< @internal Function used to stop a configured Ethernet device. */ typedef int (*eth_dev_set_link_up_t)(struct rte_eth_dev *dev); /**< @internal Function used to link up a configured Ethernet device. */ typedef int (*eth_dev_set_link_down_t)(struct rte_eth_dev *dev); /**< @internal Function used to link down a configured Ethernet device. */ typedef void (*eth_dev_close_t)(struct rte_eth_dev *dev); /**< @internal Function used to close a configured Ethernet device. */ typedef void (*eth_promiscuous_enable_t)(struct rte_eth_dev *dev); /**< @internal Function used to enable the RX promiscuous mode of an Ethernet device. */ typedef void (*eth_promiscuous_disable_t)(struct rte_eth_dev *dev); /**< @internal Function used to disable the RX promiscuous mode of an Ethernet device. */ typedef void (*eth_allmulticast_enable_t)(struct rte_eth_dev *dev); /**< @internal Enable the receipt of all multicast packets by an Ethernet device. */ typedef void (*eth_allmulticast_disable_t)(struct rte_eth_dev *dev); /**< @internal Disable the receipt of all multicast packets by an Ethernet device. */ typedef int (*eth_link_update_t)(struct rte_eth_dev *dev, int wait_to_complete); /**< @internal Get link speed, duplex mode and state (up/down) of an Ethernet device. */ typedef void (*eth_stats_get_t)(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats); /**< @internal Get global I/O statistics of an Ethernet device. */ typedef void (*eth_stats_reset_t)(struct rte_eth_dev *dev); /**< @internal Reset global I/O statistics of an Ethernet device to 0. */ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev, struct rte_eth_xstats *stats, unsigned n); /**< @internal Get extended stats of an Ethernet device. */ typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev); /**< @internal Reset extended stats of an Ethernet device. */ typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev, uint16_t queue_id, uint8_t stat_idx, uint8_t is_rx); /**< @internal Set a queue statistics mapping for a tx/rx queue of an Ethernet device. */ typedef void (*eth_dev_infos_get_t)(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); /**< @internal Get specific informations of an Ethernet device. */ typedef int (*eth_queue_start_t)(struct rte_eth_dev *dev, uint16_t queue_id); /**< @internal Start rx and tx of a queue of an Ethernet device. */ typedef int (*eth_queue_stop_t)(struct rte_eth_dev *dev, uint16_t queue_id); /**< @internal Stop rx and tx of a queue of an Ethernet device. */ typedef int (*eth_rx_queue_setup_t)(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); /**< @internal Set up a receive queue of an Ethernet device. */ typedef int (*eth_tx_queue_setup_t)(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); /**< @internal Setup a transmit queue of an Ethernet device. */ typedef int (*eth_rx_enable_intr_t)(struct rte_eth_dev *dev, uint16_t rx_queue_id); /**< @internal Enable interrupt of a receive queue of an Ethernet device. */ typedef int (*eth_rx_disable_intr_t)(struct rte_eth_dev *dev, uint16_t rx_queue_id); /**< @internal Disable interrupt of a receive queue of an Ethernet device. */ typedef void (*eth_queue_release_t)(void *queue); /**< @internal Release memory resources allocated by given RX/TX queue. */ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev, uint16_t rx_queue_id); /**< @internal Get number of available descriptors on a receive queue of an Ethernet device. */ typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset); /**< @internal Check DD bit of specific RX descriptor */ typedef int (*mtu_set_t)(struct rte_eth_dev *dev, uint16_t mtu); /**< @internal Set MTU. */ typedef int (*vlan_filter_set_t)(struct rte_eth_dev *dev, uint16_t vlan_id, int on); /**< @internal filtering of a VLAN Tag Identifier by an Ethernet device. */ typedef void (*vlan_tpid_set_t)(struct rte_eth_dev *dev, uint16_t tpid); /**< @internal set the outer VLAN-TPID by an Ethernet device. */ typedef void (*vlan_offload_set_t)(struct rte_eth_dev *dev, int mask); /**< @internal set VLAN offload function by an Ethernet device. */ typedef int (*vlan_pvid_set_t)(struct rte_eth_dev *dev, uint16_t vlan_id, int on); /**< @internal set port based TX VLAN insertion by an Ethernet device. */ typedef void (*vlan_strip_queue_set_t)(struct rte_eth_dev *dev, uint16_t rx_queue_id, int on); /**< @internal VLAN stripping enable/disable by an queue of Ethernet device. */ typedef uint16_t (*eth_rx_burst_t)(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); /**< @internal Retrieve input packets from a receive queue of an Ethernet device. */ typedef uint16_t (*eth_tx_burst_t)(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); /**< @internal Send output packets on a transmit queue of an Ethernet device. */ typedef int (*fdir_add_signature_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint8_t rx_queue); /**< @internal Setup a new signature filter rule on an Ethernet device */ typedef int (*fdir_update_signature_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint8_t rx_queue); /**< @internal Update a signature filter rule on an Ethernet device */ typedef int (*fdir_remove_signature_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr); /**< @internal Remove a signature filter rule on an Ethernet device */ typedef void (*fdir_infos_get_t)(struct rte_eth_dev *dev, struct rte_eth_fdir *fdir); /**< @internal Get information about fdir status */ typedef int (*fdir_add_perfect_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint16_t soft_id, uint8_t rx_queue, uint8_t drop); /**< @internal Setup a new perfect filter rule on an Ethernet device */ typedef int (*fdir_update_perfect_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint16_t soft_id, uint8_t rx_queue, uint8_t drop); /**< @internal Update a perfect filter rule on an Ethernet device */ typedef int (*fdir_remove_perfect_filter_t)(struct rte_eth_dev *dev, struct rte_fdir_filter *fdir_ftr, uint16_t soft_id); /**< @internal Remove a perfect filter rule on an Ethernet device */ typedef int (*fdir_set_masks_t)(struct rte_eth_dev *dev, struct rte_fdir_masks *fdir_masks); /**< @internal Setup flow director masks on an Ethernet device */ typedef int (*flow_ctrl_get_t)(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); /**< @internal Get current flow control parameter on an Ethernet device */ typedef int (*flow_ctrl_set_t)(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf); /**< @internal Setup flow control parameter on an Ethernet device */ typedef int (*priority_flow_ctrl_set_t)(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf); /**< @internal Setup priority flow control parameter on an Ethernet device */ typedef int (*reta_update_t)(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); /**< @internal Update RSS redirection table on an Ethernet device */ typedef int (*reta_query_t)(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); /**< @internal Query RSS redirection table on an Ethernet device */ typedef int (*rss_hash_update_t)(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); /**< @internal Update RSS hash configuration of an Ethernet device */ typedef int (*rss_hash_conf_get_t)(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); /**< @internal Get current RSS hash configuration of an Ethernet device */ typedef int (*eth_dev_led_on_t)(struct rte_eth_dev *dev); /**< @internal Turn on SW controllable LED on an Ethernet device */ typedef int (*eth_dev_led_off_t)(struct rte_eth_dev *dev); /**< @internal Turn off SW controllable LED on an Ethernet device */ typedef void (*eth_mac_addr_remove_t)(struct rte_eth_dev *dev, uint32_t index); /**< @internal Remove MAC address from receive address register */ typedef void (*eth_mac_addr_add_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq); /**< @internal Set a MAC address into Receive Address Address Register */ typedef void (*eth_mac_addr_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr); /**< @internal Set a MAC address into Receive Address Address Register */ typedef int (*eth_uc_hash_table_set_t)(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint8_t on); /**< @internal Set a Unicast Hash bitmap */ typedef int (*eth_uc_all_hash_table_set_t)(struct rte_eth_dev *dev, uint8_t on); /**< @internal Set all Unicast Hash bitmap */ typedef int (*eth_set_vf_rx_mode_t)(struct rte_eth_dev *dev, uint16_t vf, uint16_t rx_mode, uint8_t on); /**< @internal Set a VF receive mode */ typedef int (*eth_set_vf_rx_t)(struct rte_eth_dev *dev, uint16_t vf, uint8_t on); /**< @internal Set a VF receive mode */ typedef int (*eth_set_vf_tx_t)(struct rte_eth_dev *dev, uint16_t vf, uint8_t on); /**< @internal Enable or disable a VF transmit */ typedef int (*eth_set_vf_vlan_filter_t)(struct rte_eth_dev *dev, uint16_t vlan, uint64_t vf_mask, uint8_t vlan_on); /**< @internal Set VF VLAN pool filter */ typedef int (*eth_set_queue_rate_limit_t)(struct rte_eth_dev *dev, uint16_t queue_idx, uint16_t tx_rate); /**< @internal Set queue TX rate */ typedef int (*eth_set_vf_rate_limit_t)(struct rte_eth_dev *dev, uint16_t vf, uint16_t tx_rate, uint64_t q_msk); /**< @internal Set VF TX rate */ typedef int (*eth_mirror_rule_set_t)(struct rte_eth_dev *dev, struct rte_eth_mirror_conf *mirror_conf, uint8_t rule_id, uint8_t on); /**< @internal Add a traffic mirroring rule on an Ethernet device */ typedef int (*eth_mirror_rule_reset_t)(struct rte_eth_dev *dev, uint8_t rule_id); /**< @internal Remove a traffic mirroring rule on an Ethernet device */ typedef int (*eth_udp_tunnel_add_t)(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *tunnel_udp); /**< @internal Add tunneling UDP info */ typedef int (*eth_udp_tunnel_del_t)(struct rte_eth_dev *dev, struct rte_eth_udp_tunnel *tunnel_udp); /**< @internal Delete tunneling UDP info */ typedef int (*eth_set_mc_addr_list_t)(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); /**< @internal set the list of multicast addresses on an Ethernet device */ typedef int (*eth_timesync_enable_t)(struct rte_eth_dev *dev); /**< @internal Function used to enable IEEE1588/802.1AS timestamping. */ typedef int (*eth_timesync_disable_t)(struct rte_eth_dev *dev); /**< @internal Function used to disable IEEE1588/802.1AS timestamping. */ typedef int (*eth_timesync_read_rx_timestamp_t)(struct rte_eth_dev *dev, struct timespec *timestamp, uint32_t flags); /**< @internal Function used to read an RX IEEE1588/802.1AS timestamp. */ typedef int (*eth_timesync_read_tx_timestamp_t)(struct rte_eth_dev *dev, struct timespec *timestamp); /**< @internal Function used to read a TX IEEE1588/802.1AS timestamp. */ typedef int (*eth_get_reg_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve device register count */ typedef int (*eth_get_reg_t)(struct rte_eth_dev *dev, struct rte_dev_reg_info *info); /**< @internal Retrieve registers */ typedef int (*eth_get_eeprom_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve eeprom size */ typedef int (*eth_get_eeprom_t)(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info); /**< @internal Retrieve eeprom data */ typedef int (*eth_set_eeprom_t)(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info); /**< @internal Program eeprom data */ #ifdef RTE_NIC_BYPASS enum { RTE_BYPASS_MODE_NONE, RTE_BYPASS_MODE_NORMAL, RTE_BYPASS_MODE_BYPASS, RTE_BYPASS_MODE_ISOLATE, RTE_BYPASS_MODE_NUM, }; #define RTE_BYPASS_MODE_VALID(x) \ ((x) > RTE_BYPASS_MODE_NONE && (x) < RTE_BYPASS_MODE_NUM) enum { RTE_BYPASS_EVENT_NONE, RTE_BYPASS_EVENT_START, RTE_BYPASS_EVENT_OS_ON = RTE_BYPASS_EVENT_START, RTE_BYPASS_EVENT_POWER_ON, RTE_BYPASS_EVENT_OS_OFF, RTE_BYPASS_EVENT_POWER_OFF, RTE_BYPASS_EVENT_TIMEOUT, RTE_BYPASS_EVENT_NUM }; #define RTE_BYPASS_EVENT_VALID(x) \ ((x) > RTE_BYPASS_EVENT_NONE && (x) < RTE_BYPASS_MODE_NUM) enum { RTE_BYPASS_TMT_OFF, /* timeout disabled. */ RTE_BYPASS_TMT_1_5_SEC, /* timeout for 1.5 seconds */ RTE_BYPASS_TMT_2_SEC, /* timeout for 2 seconds */ RTE_BYPASS_TMT_3_SEC, /* timeout for 3 seconds */ RTE_BYPASS_TMT_4_SEC, /* timeout for 4 seconds */ RTE_BYPASS_TMT_8_SEC, /* timeout for 8 seconds */ RTE_BYPASS_TMT_16_SEC, /* timeout for 16 seconds */ RTE_BYPASS_TMT_32_SEC, /* timeout for 32 seconds */ RTE_BYPASS_TMT_NUM }; #define RTE_BYPASS_TMT_VALID(x) \ ((x) == RTE_BYPASS_TMT_OFF || \ ((x) > RTE_BYPASS_TMT_OFF && (x) < RTE_BYPASS_TMT_NUM)) typedef void (*bypass_init_t)(struct rte_eth_dev *dev); typedef int32_t (*bypass_state_set_t)(struct rte_eth_dev *dev, uint32_t *new_state); typedef int32_t (*bypass_state_show_t)(struct rte_eth_dev *dev, uint32_t *state); typedef int32_t (*bypass_event_set_t)(struct rte_eth_dev *dev, uint32_t state, uint32_t event); typedef int32_t (*bypass_event_show_t)(struct rte_eth_dev *dev, uint32_t event_shift, uint32_t *event); typedef int32_t (*bypass_wd_timeout_set_t)(struct rte_eth_dev *dev, uint32_t timeout); typedef int32_t (*bypass_wd_timeout_show_t)(struct rte_eth_dev *dev, uint32_t *wd_timeout); typedef int32_t (*bypass_ver_show_t)(struct rte_eth_dev *dev, uint32_t *ver); typedef int32_t (*bypass_wd_reset_t)(struct rte_eth_dev *dev); #endif typedef int (*eth_filter_ctrl_t)(struct rte_eth_dev *dev, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); /**< @internal Take operations to assigned filter type on an Ethernet device */ /** * @internal A structure containing the functions exported by an Ethernet driver. */ struct eth_dev_ops { eth_dev_configure_t dev_configure; /**< Configure device. */ eth_dev_start_t dev_start; /**< Start device. */ eth_dev_stop_t dev_stop; /**< Stop device. */ eth_dev_set_link_up_t dev_set_link_up; /**< Device link up. */ eth_dev_set_link_down_t dev_set_link_down; /**< Device link down. */ eth_dev_close_t dev_close; /**< Close device. */ eth_promiscuous_enable_t promiscuous_enable; /**< Promiscuous ON. */ eth_promiscuous_disable_t promiscuous_disable;/**< Promiscuous OFF. */ eth_allmulticast_enable_t allmulticast_enable;/**< RX multicast ON. */ eth_allmulticast_disable_t allmulticast_disable;/**< RX multicast OF. */ eth_link_update_t link_update; /**< Get device link state. */ eth_stats_get_t stats_get; /**< Get generic device statistics. */ eth_stats_reset_t stats_reset; /**< Reset generic device statistics. */ eth_xstats_get_t xstats_get; /**< Get extended device statistics. */ eth_xstats_reset_t xstats_reset; /**< Reset extended device statistics. */ eth_queue_stats_mapping_set_t queue_stats_mapping_set; /**< Configure per queue stat counter mapping. */ eth_dev_infos_get_t dev_infos_get; /**< Get device info. */ mtu_set_t mtu_set; /**< Set MTU. */ vlan_filter_set_t vlan_filter_set; /**< Filter VLAN Setup. */ vlan_tpid_set_t vlan_tpid_set; /**< Outer VLAN TPID Setup. */ vlan_strip_queue_set_t vlan_strip_queue_set; /**< VLAN Stripping on queue. */ vlan_offload_set_t vlan_offload_set; /**< Set VLAN Offload. */ vlan_pvid_set_t vlan_pvid_set; /**< Set port based TX VLAN insertion */ eth_queue_start_t rx_queue_start;/**< Start RX for a queue.*/ eth_queue_stop_t rx_queue_stop;/**< Stop RX for a queue.*/ eth_queue_start_t tx_queue_start;/**< Start TX for a queue.*/ eth_queue_stop_t tx_queue_stop;/**< Stop TX for a queue.*/ eth_rx_queue_setup_t rx_queue_setup;/**< Set up device RX queue.*/ eth_queue_release_t rx_queue_release;/**< Release RX queue.*/ eth_rx_queue_count_t rx_queue_count; /**< Get Rx queue count. */ eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit */ #ifdef RTE_NEXT_ABI /**< Enable Rx queue interrupt. */ eth_rx_enable_intr_t rx_queue_intr_enable; /**< Disable Rx queue interrupt.*/ eth_rx_disable_intr_t rx_queue_intr_disable; #endif eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue.*/ eth_queue_release_t tx_queue_release;/**< Release TX queue.*/ eth_dev_led_on_t dev_led_on; /**< Turn on LED. */ eth_dev_led_off_t dev_led_off; /**< Turn off LED. */ flow_ctrl_get_t flow_ctrl_get; /**< Get flow control. */ flow_ctrl_set_t flow_ctrl_set; /**< Setup flow control. */ priority_flow_ctrl_set_t priority_flow_ctrl_set; /**< Setup priority flow control.*/ eth_mac_addr_remove_t mac_addr_remove; /**< Remove MAC address */ eth_mac_addr_add_t mac_addr_add; /**< Add a MAC address */ eth_mac_addr_set_t mac_addr_set; /**< Set a MAC address */ eth_uc_hash_table_set_t uc_hash_table_set; /**< Set Unicast Table Array */ eth_uc_all_hash_table_set_t uc_all_hash_table_set; /**< Set Unicast hash bitmap */ eth_mirror_rule_set_t mirror_rule_set; /**< Add a traffic mirror rule.*/ eth_mirror_rule_reset_t mirror_rule_reset; /**< reset a traffic mirror rule.*/ eth_set_vf_rx_mode_t set_vf_rx_mode; /**< Set VF RX mode */ eth_set_vf_rx_t set_vf_rx; /**< enable/disable a VF receive */ eth_set_vf_tx_t set_vf_tx; /**< enable/disable a VF transmit */ eth_set_vf_vlan_filter_t set_vf_vlan_filter; /**< Set VF VLAN filter */ eth_udp_tunnel_add_t udp_tunnel_add; eth_udp_tunnel_del_t udp_tunnel_del; eth_set_queue_rate_limit_t set_queue_rate_limit; /**< Set queue rate limit */ eth_set_vf_rate_limit_t set_vf_rate_limit; /**< Set VF rate limit */ /** Add a signature filter. */ fdir_add_signature_filter_t fdir_add_signature_filter; /** Update a signature filter. */ fdir_update_signature_filter_t fdir_update_signature_filter; /** Remove a signature filter. */ fdir_remove_signature_filter_t fdir_remove_signature_filter; /** Get information about FDIR status. */ fdir_infos_get_t fdir_infos_get; /** Add a perfect filter. */ fdir_add_perfect_filter_t fdir_add_perfect_filter; /** Update a perfect filter. */ fdir_update_perfect_filter_t fdir_update_perfect_filter; /** Remove a perfect filter. */ fdir_remove_perfect_filter_t fdir_remove_perfect_filter; /** Setup masks for FDIR filtering. */ fdir_set_masks_t fdir_set_masks; /** Update redirection table. */ reta_update_t reta_update; /** Query redirection table. */ reta_query_t reta_query; eth_get_reg_length_t get_reg_length; /**< Get # of registers */ eth_get_reg_t get_reg; /**< Get registers */ eth_get_eeprom_length_t get_eeprom_length; /**< Get eeprom length */ eth_get_eeprom_t get_eeprom; /**< Get eeprom data */ eth_set_eeprom_t set_eeprom; /**< Set eeprom */ /* bypass control */ #ifdef RTE_NIC_BYPASS bypass_init_t bypass_init; bypass_state_set_t bypass_state_set; bypass_state_show_t bypass_state_show; bypass_event_set_t bypass_event_set; bypass_event_show_t bypass_event_show; bypass_wd_timeout_set_t bypass_wd_timeout_set; bypass_wd_timeout_show_t bypass_wd_timeout_show; bypass_ver_show_t bypass_ver_show; bypass_wd_reset_t bypass_wd_reset; #endif /** Configure RSS hash protocols. */ rss_hash_update_t rss_hash_update; /** Get current RSS hash configuration. */ rss_hash_conf_get_t rss_hash_conf_get; eth_filter_ctrl_t filter_ctrl; /**< common filter control*/ eth_set_mc_addr_list_t set_mc_addr_list; /**< set list of mcast addrs */ /** Turn IEEE1588/802.1AS timestamping on. */ eth_timesync_enable_t timesync_enable; /** Turn IEEE1588/802.1AS timestamping off. */ eth_timesync_disable_t timesync_disable; /** Read the IEEE1588/802.1AS RX timestamp. */ eth_timesync_read_rx_timestamp_t timesync_read_rx_timestamp; /** Read the IEEE1588/802.1AS TX timestamp. */ eth_timesync_read_tx_timestamp_t timesync_read_tx_timestamp; }; /** * Function type used for RX packet processing packet callbacks. * * The callback function is called on RX with a burst of packets that have * been received on the given port and queue. * * @param port * The Ethernet port on which RX is being performed. * @param queue * The queue on the Ethernet port which is being used to receive the packets. * @param pkts * The burst of packets that have just been received. * @param nb_pkts * The number of packets in the burst pointed to by "pkts". * @param max_pkts * The max number of packets that can be stored in the "pkts" array. * @param user_param * The arbitrary user parameter passed in by the application when the callback * was originally configured. * @return * The number of packets returned to the user. */ typedef uint16_t (*rte_rx_callback_fn)(uint8_t port, uint16_t queue, struct rte_mbuf *pkts[], uint16_t nb_pkts, uint16_t max_pkts, void *user_param); /** * Function type used for TX packet processing packet callbacks. * * The callback function is called on TX with a burst of packets immediately * before the packets are put onto the hardware queue for transmission. * * @param port * The Ethernet port on which TX is being performed. * @param queue * The queue on the Ethernet port which is being used to transmit the packets. * @param pkts * The burst of packets that are about to be transmitted. * @param nb_pkts * The number of packets in the burst pointed to by "pkts". * @param user_param * The arbitrary user parameter passed in by the application when the callback * was originally configured. * @return * The number of packets to be written to the NIC. */ typedef uint16_t (*rte_tx_callback_fn)(uint8_t port, uint16_t queue, struct rte_mbuf *pkts[], uint16_t nb_pkts, void *user_param); /** * @internal * Structure used to hold information about the callbacks to be called for a * queue on RX and TX. */ struct rte_eth_rxtx_callback { struct rte_eth_rxtx_callback *next; union{ rte_rx_callback_fn rx; rte_tx_callback_fn tx; } fn; void *param; }; /** * The eth device type. */ enum rte_eth_dev_type { RTE_ETH_DEV_UNKNOWN, /**< unknown device type */ RTE_ETH_DEV_PCI, /**< Physical function and Virtual function of PCI devices */ RTE_ETH_DEV_VIRTUAL, /**< non hardware device */ RTE_ETH_DEV_MAX /**< max value of this enum */ }; /** * @internal * The generic data structure associated with each ethernet device. * * Pointers to burst-oriented packet receive and transmit functions are * located at the beginning of the structure, along with the pointer to * where all the data elements for the particular device are stored in shared * memory. This split allows the function pointer and driver data to be per- * process, while the actual configuration data for the device is shared. */ struct rte_eth_dev { eth_rx_burst_t rx_pkt_burst; /**< Pointer to PMD receive function. */ eth_tx_burst_t tx_pkt_burst; /**< Pointer to PMD transmit function. */ struct rte_eth_dev_data *data; /**< Pointer to device data */ const struct eth_driver *driver;/**< Driver for this device */ const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */ struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */ /** User application callbacks for NIC interrupts */ struct rte_eth_dev_cb_list link_intr_cbs; /** * User-supplied functions called from rx_burst to post-process * received packets before passing them to the user */ struct rte_eth_rxtx_callback *post_rx_burst_cbs[RTE_MAX_QUEUES_PER_PORT]; /** * User-supplied functions called from tx_burst to pre-process * received packets before passing them to the driver for transmission. */ struct rte_eth_rxtx_callback *pre_tx_burst_cbs[RTE_MAX_QUEUES_PER_PORT]; uint8_t attached; /**< Flag indicating the port is attached */ enum rte_eth_dev_type dev_type; /**< Flag indicating the device type */ }; struct rte_eth_dev_sriov { uint8_t active; /**< SRIOV is active with 16, 32 or 64 pools */ uint8_t nb_q_per_pool; /**< rx queue number per pool */ uint16_t def_vmdq_idx; /**< Default pool num used for PF */ uint16_t def_pool_q_idx; /**< Default pool queue start reg index */ }; #define RTE_ETH_DEV_SRIOV(dev) ((dev)->data->sriov) #define RTE_ETH_NAME_MAX_LEN (32) /** * @internal * The data part, with no function pointers, associated with each ethernet device. * * This structure is safe to place in shared memory to be common among different * processes in a multi-process configuration. */ struct rte_eth_dev_data { char name[RTE_ETH_NAME_MAX_LEN]; /**< Unique identifier name */ void **rx_queues; /**< Array of pointers to RX queues. */ void **tx_queues; /**< Array of pointers to TX queues. */ uint16_t nb_rx_queues; /**< Number of RX queues. */ uint16_t nb_tx_queues; /**< Number of TX queues. */ struct rte_eth_dev_sriov sriov; /**< SRIOV data */ void *dev_private; /**< PMD-specific private data */ struct rte_eth_link dev_link; /**< Link-level information & status */ struct rte_eth_conf dev_conf; /**< Configuration applied to device. */ uint16_t mtu; /**< Maximum Transmission Unit. */ uint32_t min_rx_buf_size; /**< Common rx buffer size handled by all queues */ uint64_t rx_mbuf_alloc_failed; /**< RX ring mbuf allocation failures. */ struct ether_addr* mac_addrs;/**< Device Ethernet Link address. */ uint64_t mac_pool_sel[ETH_NUM_RECEIVE_MAC_ADDR]; /** bitmap array of associating Ethernet MAC addresses to pools */ struct ether_addr* hash_mac_addrs; /** Device Ethernet MAC addresses of hash filtering. */ uint8_t port_id; /**< Device [external] port identifier. */ uint8_t promiscuous : 1, /**< RX promiscuous mode ON(1) / OFF(0). */ scattered_rx : 1, /**< RX of scattered packets is ON(1) / OFF(0) */ all_multicast : 1, /**< RX all multicast mode ON(1) / OFF(0). */ dev_started : 1, /**< Device state: STARTED(1) / STOPPED(0). */ lro : 1; /**< RX LRO is ON(1) / OFF(0) */ }; /** * @internal * The pool of *rte_eth_dev* structures. The size of the pool * is configured at compile-time in the file. */ extern struct rte_eth_dev rte_eth_devices[]; /** * Get the total number of Ethernet devices that have been successfully * initialized by the [matching] Ethernet driver during the PCI probing phase. * All devices whose port identifier is in the range * [0, rte_eth_dev_count() - 1] can be operated on by network applications * immediately after invoking rte_eal_init(). * If the application unplugs a port using hotplug function, The enabled port * numbers may be noncontiguous. In the case, the applications need to manage * enabled port by themselves. * * @return * - The total number of usable Ethernet devices. */ extern uint8_t rte_eth_dev_count(void); /** * @internal * Returns a ethdev slot specified by the unique identifier name. * * @param name * The pointer to the Unique identifier name for each Ethernet device * @return * - The pointer to the ethdev slot, on success. NULL on error */ extern struct rte_eth_dev *rte_eth_dev_allocated(const char *name); /** * @internal * Allocates a new ethdev slot for an ethernet device and returns the pointer * to that slot for the driver to use. * * @param name Unique identifier name for each Ethernet device * @param type Device type of this Ethernet device * @return * - Slot in the rte_dev_devices array for a new device; */ struct rte_eth_dev *rte_eth_dev_allocate(const char *name, enum rte_eth_dev_type type); /** * @internal * Release the specified ethdev port. * * @param eth_dev * The *eth_dev* pointer is the address of the *rte_eth_dev* structure. * @return * - 0 on success, negative on error */ int rte_eth_dev_release_port(struct rte_eth_dev *eth_dev); /** * Attach a new Ethernet device specified by aruguments. * * @param devargs * A pointer to a strings array describing the new device * to be attached. The strings should be a pci address like * '0000:01:00.0' or virtual device name like 'eth_pcap0'. * @param port_id * A pointer to a port identifier actually attached. * @return * 0 on success and port_id is filled, negative on error */ int rte_eth_dev_attach(const char *devargs, uint8_t *port_id); /** * Detach a Ethernet device specified by port identifier. * This function must be called when the device is in the * closed state. * * @param port_id * The port identifier of the device to detach. * @param devname * A pointer to a device name actually detached. * @return * 0 on success and devname is filled, negative on error */ int rte_eth_dev_detach(uint8_t port_id, char *devname); struct eth_driver; /** * @internal * Initialization function of an Ethernet driver invoked for each matching * Ethernet PCI device detected during the PCI probing phase. * * @param eth_dev * The *eth_dev* pointer is the address of the *rte_eth_dev* structure * associated with the matching device and which have been [automatically] * allocated in the *rte_eth_devices* array. * The *eth_dev* structure is supplied to the driver initialization function * with the following fields already initialized: * * - *pci_dev*: Holds the pointers to the *rte_pci_device* structure which * contains the generic PCI information of the matching device. * * - *driver*: Holds the pointer to the *eth_driver* structure. * * - *dev_private*: Holds a pointer to the device private data structure. * * - *mtu*: Contains the default Ethernet maximum frame length (1500). * * - *port_id*: Contains the port index of the device (actually the index * of the *eth_dev* structure in the *rte_eth_devices* array). * * @return * - 0: Success, the device is properly initialized by the driver. * In particular, the driver MUST have set up the *dev_ops* pointer * of the *eth_dev* structure. * - <0: Error code of the device initialization failure. */ typedef int (*eth_dev_init_t)(struct rte_eth_dev *eth_dev); /** * @internal * Finalization function of an Ethernet driver invoked for each matching * Ethernet PCI device detected during the PCI closing phase. * * @param eth_dev * The *eth_dev* pointer is the address of the *rte_eth_dev* structure * associated with the matching device and which have been [automatically] * allocated in the *rte_eth_devices* array. * @return * - 0: Success, the device is properly finalized by the driver. * In particular, the driver MUST free the *dev_ops* pointer * of the *eth_dev* structure. * - <0: Error code of the device initialization failure. */ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev); /** * @internal * The structure associated with a PMD Ethernet driver. * * Each Ethernet driver acts as a PCI driver and is represented by a generic * *eth_driver* structure that holds: * * - An *rte_pci_driver* structure (which must be the first field). * * - The *eth_dev_init* function invoked for each matching PCI device. * * - The *eth_dev_uninit* function invoked for each matching PCI device. * * - The size of the private data to allocate for each matching device. */ struct eth_driver { struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */ eth_dev_init_t eth_dev_init; /**< Device init function. */ eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */ unsigned int dev_private_size; /**< Size of device private data. */ }; /** * @internal * A function invoked by the initialization function of an Ethernet driver * to simultaneously register itself as a PCI driver and as an Ethernet * Poll Mode Driver (PMD). * * @param eth_drv * The pointer to the *eth_driver* structure associated with * the Ethernet driver. */ extern void rte_eth_driver_register(struct eth_driver *eth_drv); /** * Configure an Ethernet device. * This function must be invoked first before any other function in the * Ethernet API. This function can also be re-invoked when a device is in the * stopped state. * * @param port_id * The port identifier of the Ethernet device to configure. * @param nb_rx_queue * The number of receive queues to set up for the Ethernet device. * @param nb_tx_queue * The number of transmit queues to set up for the Ethernet device. * @param eth_conf * The pointer to the configuration data to be used for the Ethernet device. * The *rte_eth_conf* structure includes: * - the hardware offload features to activate, with dedicated fields for * each statically configurable offload hardware feature provided by * Ethernet devices, such as IP checksum or VLAN tag stripping for * example. * - the Receive Side Scaling (RSS) configuration when using multiple RX * queues per port. * * Embedding all configuration information in a single data structure * is the more flexible method that allows the addition of new features * without changing the syntax of the API. * @return * - 0: Success, device configured. * - <0: Error code returned by the driver configuration function. */ extern int rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_queue, uint16_t nb_tx_queue, const struct rte_eth_conf *eth_conf); /** * Allocate and set up a receive queue for an Ethernet device. * * The function allocates a contiguous block of memory for *nb_rx_desc* * receive descriptors from a memory zone associated with *socket_id* * and initializes each receive descriptor with a network buffer allocated * from the memory pool *mb_pool*. * * @param port_id * The port identifier of the Ethernet device. * @param rx_queue_id * The index of the receive queue to set up. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param nb_rx_desc * The number of receive descriptors to allocate for the receive ring. * @param socket_id * The *socket_id* argument is the socket identifier in case of NUMA. * The value can be *SOCKET_ID_ANY* if there is no NUMA constraint for * the DMA memory allocated for the receive descriptors of the ring. * @param rx_conf * The pointer to the configuration data to be used for the receive queue. * NULL value is allowed, in which case default RX configuration * will be used. * The *rx_conf* structure contains an *rx_thresh* structure with the values * of the Prefetch, Host, and Write-Back threshold registers of the receive * ring. * @param mb_pool * The pointer to the memory pool from which to allocate *rte_mbuf* network * memory buffers to populate each descriptor of the receive ring. * @return * - 0: Success, receive queue correctly set up. * - -EINVAL: The size of network buffers which can be allocated from the * memory pool does not fit the various buffer sizes allowed by the * device controller. * - -ENOMEM: Unable to allocate the receive ring descriptors or to * allocate network memory buffers from the memory pool when * initializing receive descriptors. */ extern int rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); /** * Allocate and set up a transmit queue for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param tx_queue_id * The index of the transmit queue to set up. * The value must be in the range [0, nb_tx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param nb_tx_desc * The number of transmit descriptors to allocate for the transmit ring. * @param socket_id * The *socket_id* argument is the socket identifier in case of NUMA. * Its value can be *SOCKET_ID_ANY* if there is no NUMA constraint for * the DMA memory allocated for the transmit descriptors of the ring. * @param tx_conf * The pointer to the configuration data to be used for the transmit queue. * NULL value is allowed, in which case default RX configuration * will be used. * The *tx_conf* structure contains the following data: * - The *tx_thresh* structure with the values of the Prefetch, Host, and * Write-Back threshold registers of the transmit ring. * When setting Write-Back threshold to the value greater then zero, * *tx_rs_thresh* value should be explicitly set to one. * - The *tx_free_thresh* value indicates the [minimum] number of network * buffers that must be pending in the transmit ring to trigger their * [implicit] freeing by the driver transmit function. * - The *tx_rs_thresh* value indicates the [minimum] number of transmit * descriptors that must be pending in the transmit ring before setting the * RS bit on a descriptor by the driver transmit function. * The *tx_rs_thresh* value should be less or equal then * *tx_free_thresh* value, and both of them should be less then * *nb_tx_desc* - 3. * - The *txq_flags* member contains flags to pass to the TX queue setup * function to configure the behavior of the TX queue. This should be set * to 0 if no special configuration is required. * * Note that setting *tx_free_thresh* or *tx_rs_thresh* value to 0 forces * the transmit function to use default values. * @return * - 0: Success, the transmit queue is correctly set up. * - -ENOMEM: Unable to allocate the transmit ring descriptors. */ extern int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); /* * Return the NUMA socket to which an Ethernet device is connected * * @param port_id * The port identifier of the Ethernet device * @return * The NUMA socket id to which the Ethernet device is connected or * a default of zero if the socket could not be determined. * -1 is returned is the port_id value is out of range. */ extern int rte_eth_dev_socket_id(uint8_t port_id); /* * Check if port_id of device is attached * * @param port_id * The port identifier of the Ethernet device * @return * - 0 if port is out of range or not attached * - 1 if device is attached */ extern int rte_eth_dev_is_valid_port(uint8_t port_id); /* * Allocate mbuf from mempool, setup the DMA physical address * and then start RX for specified queue of a port. It is used * when rx_deferred_start flag of the specified queue is true. * * @param port_id * The port identifier of the Ethernet device * @param rx_queue_id * The index of the rx queue to update the ring. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - 0: Success, the transmit queue is correctly set up. * - -EINVAL: The port_id or the queue_id out of range. * - -ENOTSUP: The function not supported in PMD driver. */ extern int rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id); /* * Stop specified RX queue of a port * * @param port_id * The port identifier of the Ethernet device * @param rx_queue_id * The index of the rx queue to update the ring. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - 0: Success, the transmit queue is correctly set up. * - -EINVAL: The port_id or the queue_id out of range. * - -ENOTSUP: The function not supported in PMD driver. */ extern int rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id); /* * Start TX for specified queue of a port. It is used when tx_deferred_start * flag of the specified queue is true. * * @param port_id * The port identifier of the Ethernet device * @param tx_queue_id * The index of the tx queue to update the ring. * The value must be in the range [0, nb_tx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - 0: Success, the transmit queue is correctly set up. * - -EINVAL: The port_id or the queue_id out of range. * - -ENOTSUP: The function not supported in PMD driver. */ extern int rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id); /* * Stop specified TX queue of a port * * @param port_id * The port identifier of the Ethernet device * @param tx_queue_id * The index of the tx queue to update the ring. * The value must be in the range [0, nb_tx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - 0: Success, the transmit queue is correctly set up. * - -EINVAL: The port_id or the queue_id out of range. * - -ENOTSUP: The function not supported in PMD driver. */ extern int rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id); /** * Start an Ethernet device. * * The device start step is the last one and consists of setting the configured * offload features and in starting the transmit and the receive units of the * device. * On success, all basic functions exported by the Ethernet API (link status, * receive/transmit, and so on) can be invoked. * * @param port_id * The port identifier of the Ethernet device. * @return * - 0: Success, Ethernet device started. * - <0: Error code of the driver device start function. */ extern int rte_eth_dev_start(uint8_t port_id); /** * Stop an Ethernet device. The device can be restarted with a call to * rte_eth_dev_start() * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_dev_stop(uint8_t port_id); /** * Link up an Ethernet device. * * Set device link up will re-enable the device rx/tx * functionality after it is previously set device linked down. * * @param port_id * The port identifier of the Ethernet device. * @return * - 0: Success, Ethernet device linked up. * - <0: Error code of the driver device link up function. */ extern int rte_eth_dev_set_link_up(uint8_t port_id); /** * Link down an Ethernet device. * The device rx/tx functionality will be disabled if success, * and it can be re-enabled with a call to * rte_eth_dev_set_link_up() * * @param port_id * The port identifier of the Ethernet device. */ extern int rte_eth_dev_set_link_down(uint8_t port_id); /** * Close a stopped Ethernet device. The device cannot be restarted! * The function frees all resources except for needed by the * closed state. To free these resources, call rte_eth_dev_detach(). * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_dev_close(uint8_t port_id); /** * Enable receipt in promiscuous mode for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_promiscuous_enable(uint8_t port_id); /** * Disable receipt in promiscuous mode for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_promiscuous_disable(uint8_t port_id); /** * Return the value of promiscuous mode for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @return * - (1) if promiscuous is enabled * - (0) if promiscuous is disabled. * - (-1) on error */ extern int rte_eth_promiscuous_get(uint8_t port_id); /** * Enable the receipt of any multicast frame by an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_allmulticast_enable(uint8_t port_id); /** * Disable the receipt of all multicast frames by an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_allmulticast_disable(uint8_t port_id); /** * Return the value of allmulticast mode for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @return * - (1) if allmulticast is enabled * - (0) if allmulticast is disabled. * - (-1) on error */ extern int rte_eth_allmulticast_get(uint8_t port_id); /** * Retrieve the status (ON/OFF), the speed (in Mbps) and the mode (HALF-DUPLEX * or FULL-DUPLEX) of the physical link of an Ethernet device. It might need * to wait up to 9 seconds in it. * * @param port_id * The port identifier of the Ethernet device. * @param link * A pointer to an *rte_eth_link* structure to be filled with * the status, the speed and the mode of the Ethernet device link. */ extern void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link); /** * Retrieve the status (ON/OFF), the speed (in Mbps) and the mode (HALF-DUPLEX * or FULL-DUPLEX) of the physical link of an Ethernet device. It is a no-wait * version of rte_eth_link_get(). * * @param port_id * The port identifier of the Ethernet device. * @param link * A pointer to an *rte_eth_link* structure to be filled with * the status, the speed and the mode of the Ethernet device link. */ extern void rte_eth_link_get_nowait(uint8_t port_id, struct rte_eth_link *link); /** * Retrieve the general I/O statistics of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param stats * A pointer to a structure of type *rte_eth_stats* to be filled with * the values of device counters for the following set of statistics: * - *ipackets* with the total of successfully received packets. * - *opackets* with the total of successfully transmitted packets. * - *ibytes* with the total of successfully received bytes. * - *obytes* with the total of successfully transmitted bytes. * - *ierrors* with the total of erroneous received packets. * - *oerrors* with the total of failed transmitted packets. * @return * Zero if successful. Non-zero otherwise. */ extern int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats); /** * Reset the general I/O statistics of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_stats_reset(uint8_t port_id); /** * Retrieve extended statistics of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param xstats * A pointer to a table of structure of type *rte_eth_xstats* * to be filled with device statistics names and values. * This parameter can be set to NULL if n is 0. * @param n * The size of the stats table, which should be large enough to store * all the statistics of the device. * @return * - positive value lower or equal to n: success. The return value * is the number of entries filled in the stats table. * - positive value higher than n: error, the given statistics table * is too small. The return value corresponds to the size that should * be given to succeed. The entries in the table are not valid and * shall not be used by the caller. * - negative value on error (invalid port id) */ extern int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, unsigned n); /** * Reset extended statistics of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. */ extern void rte_eth_xstats_reset(uint8_t port_id); /** * Set a mapping for the specified transmit queue to the specified per-queue * statistics counter. * * @param port_id * The port identifier of the Ethernet device. * @param tx_queue_id * The index of the transmit queue for which a queue stats mapping is required. * The value must be in the range [0, nb_tx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param stat_idx * The per-queue packet statistics functionality number that the transmit * queue is to be assigned. * The value must be in the range [0, RTE_MAX_ETHPORT_QUEUE_STATS_MAPS - 1]. * @return * Zero if successful. Non-zero otherwise. */ extern int rte_eth_dev_set_tx_queue_stats_mapping(uint8_t port_id, uint16_t tx_queue_id, uint8_t stat_idx); /** * Set a mapping for the specified receive queue to the specified per-queue * statistics counter. * * @param port_id * The port identifier of the Ethernet device. * @param rx_queue_id * The index of the receive queue for which a queue stats mapping is required. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param stat_idx * The per-queue packet statistics functionality number that the receive * queue is to be assigned. * The value must be in the range [0, RTE_MAX_ETHPORT_QUEUE_STATS_MAPS - 1]. * @return * Zero if successful. Non-zero otherwise. */ extern int rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id, uint8_t stat_idx); /** * Retrieve the Ethernet address of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param mac_addr * A pointer to a structure of type *ether_addr* to be filled with * the Ethernet address of the Ethernet device. */ extern void rte_eth_macaddr_get(uint8_t port_id, struct ether_addr *mac_addr); /** * Retrieve the contextual information of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param dev_info * A pointer to a structure of type *rte_eth_dev_info* to be filled with * the contextual information of the Ethernet device. */ extern void rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info); /** * Retrieve the MTU of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param mtu * A pointer to a uint16_t where the retrieved MTU is to be stored. * @return * - (0) if successful. * - (-ENODEV) if *port_id* invalid. */ extern int rte_eth_dev_get_mtu(uint8_t port_id, uint16_t *mtu); /** * Change the MTU of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param mtu * A uint16_t for the MTU to be applied. * @return * - (0) if successful. * - (-ENOTSUP) if operation is not supported. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if *mtu* invalid. */ extern int rte_eth_dev_set_mtu(uint8_t port_id, uint16_t mtu); /** * Enable/Disable hardware filtering by an Ethernet device of received * VLAN packets tagged with a given VLAN Tag Identifier. * * @param port_id * The port identifier of the Ethernet device. * @param vlan_id * The VLAN Tag Identifier whose filtering must be enabled or disabled. * @param on * If > 0, enable VLAN filtering of VLAN packets tagged with *vlan_id*. * Otherwise, disable VLAN filtering of VLAN packets tagged with *vlan_id*. * @return * - (0) if successful. * - (-ENOSUP) if hardware-assisted VLAN filtering not configured. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if VLAN filtering on *port_id* disabled. * - (-EINVAL) if *vlan_id* > 4095. */ extern int rte_eth_dev_vlan_filter(uint8_t port_id, uint16_t vlan_id , int on); /** * Enable/Disable hardware VLAN Strip by a rx queue of an Ethernet device. * 82599/X540/X550 can support VLAN stripping at the rx queue level * * @param port_id * The port identifier of the Ethernet device. * @param rx_queue_id * The index of the receive queue for which a queue stats mapping is required. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param on * If 1, Enable VLAN Stripping of the receive queue of the Ethernet port. * If 0, Disable VLAN Stripping of the receive queue of the Ethernet port. * @return * - (0) if successful. * - (-ENOSUP) if hardware-assisted VLAN stripping not configured. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if *rx_queue_id* invalid. */ extern int rte_eth_dev_set_vlan_strip_on_queue(uint8_t port_id, uint16_t rx_queue_id, int on); /** * Set the Outer VLAN Ether Type by an Ethernet device, it can be inserted to * the VLAN Header. This is a register setup available on some Intel NIC, not * but all, please check the data sheet for availability. * * @param port_id * The port identifier of the Ethernet device. * @param tag_type * The Tag Protocol ID * @return * - (0) if successful. * - (-ENOSUP) if hardware-assisted VLAN TPID setup is not supported. * - (-ENODEV) if *port_id* invalid. */ extern int rte_eth_dev_set_vlan_ether_type(uint8_t port_id, uint16_t tag_type); /** * Set VLAN offload configuration on an Ethernet device * Enable/Disable Extended VLAN by an Ethernet device, This is a register setup * available on some Intel NIC, not but all, please check the data sheet for * availability. * Enable/Disable VLAN Strip can be done on rx queue for certain NIC, but here * the configuration is applied on the port level. * * @param port_id * The port identifier of the Ethernet device. * @param offload_mask * The VLAN Offload bit mask can be mixed use with "OR" * ETH_VLAN_STRIP_OFFLOAD * ETH_VLAN_FILTER_OFFLOAD * ETH_VLAN_EXTEND_OFFLOAD * @return * - (0) if successful. * - (-ENOSUP) if hardware-assisted VLAN filtering not configured. * - (-ENODEV) if *port_id* invalid. */ extern int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask); /** * Read VLAN Offload configuration from an Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @return * - (>0) if successful. Bit mask to indicate * ETH_VLAN_STRIP_OFFLOAD * ETH_VLAN_FILTER_OFFLOAD * ETH_VLAN_EXTEND_OFFLOAD * - (-ENODEV) if *port_id* invalid. */ extern int rte_eth_dev_get_vlan_offload(uint8_t port_id); /** * Set port based TX VLAN insersion on or off. * * @param port_id * The port identifier of the Ethernet device. * @param pvid * Port based TX VLAN identifier togeth with user priority. * @param on * Turn on or off the port based TX VLAN insertion. * * @return * - (0) if successful. * - negative if failed. */ extern int rte_eth_dev_set_vlan_pvid(uint8_t port_id, uint16_t pvid, int on); /** * * Retrieve a burst of input packets from a receive queue of an Ethernet * device. The retrieved packets are stored in *rte_mbuf* structures whose * pointers are supplied in the *rx_pkts* array. * * The rte_eth_rx_burst() function loops, parsing the RX ring of the * receive queue, up to *nb_pkts* packets, and for each completed RX * descriptor in the ring, it performs the following operations: * * - Initialize the *rte_mbuf* data structure associated with the * RX descriptor according to the information provided by the NIC into * that RX descriptor. * * - Store the *rte_mbuf* data structure into the next entry of the * *rx_pkts* array. * * - Replenish the RX descriptor with a new *rte_mbuf* buffer * allocated from the memory pool associated with the receive queue at * initialization time. * * When retrieving an input packet that was scattered by the controller * into multiple receive descriptors, the rte_eth_rx_burst() function * appends the associated *rte_mbuf* buffers to the first buffer of the * packet. * * The rte_eth_rx_burst() function returns the number of packets * actually retrieved, which is the number of *rte_mbuf* data structures * effectively supplied into the *rx_pkts* array. * A return value equal to *nb_pkts* indicates that the RX queue contained * at least *rx_pkts* packets, and this is likely to signify that other * received packets remain in the input queue. Applications implementing * a "retrieve as much received packets as possible" policy can check this * specific case and keep invoking the rte_eth_rx_burst() function until * a value less than *nb_pkts* is returned. * * This receive method has the following advantages: * * - It allows a run-to-completion network stack engine to retrieve and * to immediately process received packets in a fast burst-oriented * approach, avoiding the overhead of unnecessary intermediate packet * queue/dequeue operations. * * - Conversely, it also allows an asynchronous-oriented processing * method to retrieve bursts of received packets and to immediately * queue them for further parallel processing by another logical core, * for instance. However, instead of having received packets being * individually queued by the driver, this approach allows the invoker * of the rte_eth_rx_burst() function to queue a burst of retrieved * packets at a time and therefore dramatically reduce the cost of * enqueue/dequeue operations per packet. * * - It allows the rte_eth_rx_burst() function of the driver to take * advantage of burst-oriented hardware features (CPU cache, * prefetch instructions, and so on) to minimize the number of CPU * cycles per packet. * * To summarize, the proposed receive API enables many * burst-oriented optimizations in both synchronous and asynchronous * packet processing environments with no overhead in both cases. * * The rte_eth_rx_burst() function does not provide any error * notification to avoid the corresponding overhead. As a hint, the * upper-level application might check the status of the device link once * being systematically returned a 0 value for a given number of tries. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The index of the receive queue from which to retrieve input packets. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param rx_pkts * The address of an array of pointers to *rte_mbuf* structures that * must be large enough to store *nb_pkts* pointers in it. * @param nb_pkts * The maximum number of packets to retrieve. * @return * The number of packets actually retrieved, which is the number * of pointers to *rte_mbuf* structures effectively supplied to the * *rx_pkts* array. */ #ifdef RTE_LIBRTE_ETHDEV_DEBUG extern uint16_t rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); #else static inline uint16_t rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **rx_pkts, const uint16_t nb_pkts) { struct rte_eth_dev *dev; dev = &rte_eth_devices[port_id]; int16_t nb_rx = (*dev->rx_pkt_burst)(dev->data->rx_queues[queue_id], rx_pkts, nb_pkts); #ifdef RTE_ETHDEV_RXTX_CALLBACKS struct rte_eth_rxtx_callback *cb = dev->post_rx_burst_cbs[queue_id]; if (unlikely(cb != NULL)) { do { nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx, nb_pkts, cb->param); cb = cb->next; } while (cb != NULL); } #endif return nb_rx; } #endif /** * Get the number of used descriptors in a specific queue * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue id on the specific port. * @return * The number of used descriptors in the specific queue. */ #ifdef RTE_LIBRTE_ETHDEV_DEBUG extern uint32_t rte_eth_rx_queue_count(uint8_t port_id, uint16_t queue_id); #else static inline uint32_t rte_eth_rx_queue_count(uint8_t port_id, uint16_t queue_id) { struct rte_eth_dev *dev; dev = &rte_eth_devices[port_id]; return (*dev->dev_ops->rx_queue_count)(dev, queue_id); } #endif /** * Check if the DD bit of the specific RX descriptor in the queue has been set * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue id on the specific port. * @param offset * The offset of the descriptor ID from tail. * @return * - (1) if the specific DD bit is set. * - (0) if the specific DD bit is not set. * - (-ENODEV) if *port_id* invalid. */ #ifdef RTE_LIBRTE_ETHDEV_DEBUG extern int rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset); #else static inline int rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset) { struct rte_eth_dev *dev; dev = &rte_eth_devices[port_id]; return (*dev->dev_ops->rx_descriptor_done)( \ dev->data->rx_queues[queue_id], offset); } #endif /** * Send a burst of output packets on a transmit queue of an Ethernet device. * * The rte_eth_tx_burst() function is invoked to transmit output packets * on the output queue *queue_id* of the Ethernet device designated by its * *port_id*. * The *nb_pkts* parameter is the number of packets to send which are * supplied in the *tx_pkts* array of *rte_mbuf* structures. * The rte_eth_tx_burst() function loops, sending *nb_pkts* packets, * up to the number of transmit descriptors available in the TX ring of the * transmit queue. * For each packet to send, the rte_eth_tx_burst() function performs * the following operations: * * - Pick up the next available descriptor in the transmit ring. * * - Free the network buffer previously sent with that descriptor, if any. * * - Initialize the transmit descriptor with the information provided * in the *rte_mbuf data structure. * * In the case of a segmented packet composed of a list of *rte_mbuf* buffers, * the rte_eth_tx_burst() function uses several transmit descriptors * of the ring. * * The rte_eth_tx_burst() function returns the number of packets it * actually sent. A return value equal to *nb_pkts* means that all packets * have been sent, and this is likely to signify that other output packets * could be immediately transmitted again. Applications that implement a * "send as many packets to transmit as possible" policy can check this * specific case and keep invoking the rte_eth_tx_burst() function until * a value less than *nb_pkts* is returned. * * It is the responsibility of the rte_eth_tx_burst() function to * transparently free the memory buffers of packets previously sent. * This feature is driven by the *tx_free_thresh* value supplied to the * rte_eth_dev_configure() function at device configuration time. * When the number of free TX descriptors drops below this threshold, the * rte_eth_tx_burst() function must [attempt to] free the *rte_mbuf* buffers * of those packets whose transmission was effectively completed. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The index of the transmit queue through which output packets must be * sent. * The value must be in the range [0, nb_tx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param tx_pkts * The address of an array of *nb_pkts* pointers to *rte_mbuf* structures * which contain the output packets. * @param nb_pkts * The maximum number of packets to transmit. * @return * The number of output packets actually stored in transmit descriptors of * the transmit ring. The return value can be less than the value of the * *tx_pkts* parameter when the transmit ring is full or has been filled up. */ #ifdef RTE_LIBRTE_ETHDEV_DEBUG extern uint16_t rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); #else static inline uint16_t rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) { struct rte_eth_dev *dev; dev = &rte_eth_devices[port_id]; #ifdef RTE_ETHDEV_RXTX_CALLBACKS struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id]; if (unlikely(cb != NULL)) { do { nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts, cb->param); cb = cb->next; } while (cb != NULL); } #endif return (*dev->tx_pkt_burst)(dev->data->tx_queues[queue_id], tx_pkts, nb_pkts); } #endif /** * Setup a new signature filter rule on an Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @param fdir_filter * The pointer to the fdir filter structure describing the signature filter * rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * @param rx_queue * The index of the RX queue where to store RX packets matching the added * signature filter defined in fdir_filter. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the FDIR mode is not configured in signature mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_add_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint8_t rx_queue); /** * Update a signature filter rule on an Ethernet device. * If the rule doesn't exits, it is created. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_ftr * The pointer to the structure describing the signature filter rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * @param rx_queue * The index of the RX queue where to store RX packets matching the added * signature filter defined in fdir_ftr. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in signature mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_update_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_ftr, uint8_t rx_queue); /** * Remove a signature filter rule on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_ftr * The pointer to the structure describing the signature filter rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in signature mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_remove_signature_filter(uint8_t port_id, struct rte_fdir_filter *fdir_ftr); /** * Retrieve the flow director information of an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param fdir * A pointer to a structure of type *rte_eth_dev_fdir* to be filled with * the flow director information of the Ethernet device. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured on *port_id*. */ int rte_eth_dev_fdir_get_infos(uint8_t port_id, struct rte_eth_fdir *fdir); /** * Add a new perfect filter rule on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_filter * The pointer to the structure describing the perfect filter rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * IPv6 are not supported. * @param soft_id * The 16-bit value supplied in the field hash.fdir.id of mbuf for RX * packets matching the perfect filter. * @param rx_queue * The index of the RX queue where to store RX packets matching the added * perfect filter defined in fdir_filter. * @param drop * If drop is set to 1, matching RX packets are stored into the RX drop * queue defined in the rte_fdir_conf. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in perfect mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_add_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id, uint8_t rx_queue, uint8_t drop); /** * Update a perfect filter rule on an Ethernet device. * If the rule doesn't exits, it is created. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_filter * The pointer to the structure describing the perfect filter rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * IPv6 are not supported. * @param soft_id * The 16-bit value supplied in the field hash.fdir.id of mbuf for RX * packets matching the perfect filter. * @param rx_queue * The index of the RX queue where to store RX packets matching the added * perfect filter defined in fdir_filter. * @param drop * If drop is set to 1, matching RX packets are stored into the RX drop * queue defined in the rte_fdir_conf. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in perfect mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_update_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id, uint8_t rx_queue, uint8_t drop); /** * Remove a perfect filter rule on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_filter * The pointer to the structure describing the perfect filter rule. * The *rte_fdir_filter* structure includes the values of the different fields * to match: source and destination IP addresses, vlan id, flexbytes, source * and destination ports, and so on. * IPv6 are not supported. * @param soft_id * The soft_id value provided when adding/updating the removed filter. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in perfect mode * on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct. */ int rte_eth_dev_fdir_remove_perfect_filter(uint8_t port_id, struct rte_fdir_filter *fdir_filter, uint16_t soft_id); /** * Configure globally the masks for flow director mode for an Ethernet device. * For example, the device can match packets with only the first 24 bits of * the IPv4 source address. * * The following fields can be masked: IPv4 addresses and L4 port numbers. * The following fields can be either enabled or disabled completely for the * matching functionality: VLAN ID tag; VLAN Priority + CFI bit; Flexible 2-byte * tuple. * IPv6 masks are not supported. * * All filters must comply with the masks previously configured. * For example, with a mask equal to 255.255.255.0 for the source IPv4 address, * all IPv4 filters must be created with a source IPv4 address that fits the * "X.X.X.0" format. * * This function flushes all filters that have been previously added in * the device. * * @param port_id * The port identifier of the Ethernet device. * @param fdir_mask * The pointer to the fdir mask structure describing relevant headers fields * and relevant bits to use when matching packets addresses and ports. * IPv6 masks are not supported. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow director mode. * - (-ENODEV) if *port_id* invalid. * - (-ENOSYS) if the flow director mode is not configured in perfect * mode on *port_id*. * - (-EINVAL) if the fdir_filter information is not correct */ int rte_eth_dev_fdir_set_masks(uint8_t port_id, struct rte_fdir_masks *fdir_mask); /** * The eth device event type for interrupt, and maybe others in the future. */ enum rte_eth_event_type { RTE_ETH_EVENT_UNKNOWN, /**< unknown event type */ RTE_ETH_EVENT_INTR_LSC, /**< lsc interrupt event */ RTE_ETH_EVENT_MAX /**< max value of this enum */ }; typedef void (*rte_eth_dev_cb_fn)(uint8_t port_id, \ enum rte_eth_event_type event, void *cb_arg); /**< user application callback to be registered for interrupts */ /** * Register a callback function for specific port id. * * @param port_id * Port id. * @param event * Event interested. * @param cb_fn * User supplied callback function to be called. * @param cb_arg * Pointer to the parameters for the registered callback. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_eth_dev_callback_register(uint8_t port_id, enum rte_eth_event_type event, rte_eth_dev_cb_fn cb_fn, void *cb_arg); /** * Unregister a callback function for specific port id. * * @param port_id * Port id. * @param event * Event interested. * @param cb_fn * User supplied callback function to be called. * @param cb_arg * Pointer to the parameters for the registered callback. -1 means to * remove all for the same callback address and same event. * * @return * - On success, zero. * - On failure, a negative value. */ int rte_eth_dev_callback_unregister(uint8_t port_id, enum rte_eth_event_type event, rte_eth_dev_cb_fn cb_fn, void *cb_arg); /** * @internal Executes all the user application registered callbacks for * the specific device. It is for DPDK internal user only. User * application should not call it directly. * * @param dev * Pointer to struct rte_eth_dev. * @param event * Eth device interrupt event type. * * @return * void */ void _rte_eth_dev_callback_process(struct rte_eth_dev *dev, enum rte_eth_event_type event); /** * When there is no rx packet coming in Rx Queue for a long time, we can * sleep lcore related to RX Queue for power saving, and enable rx interrupt * to be triggered when rx packect arrives. * * The rte_eth_dev_rx_intr_enable() function enables rx queue * interrupt on specific rx queue of a port. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The index of the receive queue from which to retrieve input packets. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - (0) if successful. * - (-ENOTSUP) if underlying hardware OR driver doesn't support * that operation. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_dev_rx_intr_enable(uint8_t port_id, uint16_t queue_id); /** * When lcore wakes up from rx interrupt indicating packet coming, disable rx * interrupt and returns to polling mode. * * The rte_eth_dev_rx_intr_disable() function disables rx queue * interrupt on specific rx queue of a port. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The index of the receive queue from which to retrieve input packets. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @return * - (0) if successful. * - (-ENOTSUP) if underlying hardware OR driver doesn't support * that operation. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_dev_rx_intr_disable(uint8_t port_id, uint16_t queue_id); /** * RX Interrupt control per port. * * @param port_id * The port identifier of the Ethernet device. * @param epfd * Epoll instance fd which the intr vector associated to. * Using RTE_EPOLL_PER_THREAD allows to use per thread epoll instance. * @param op * The operation be performed for the vector. * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}. * @param data * User raw data. * @return * - On success, zero. * - On failure, a negative value. */ int rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data); /** * RX Interrupt control per queue. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The index of the receive queue from which to retrieve input packets. * The value must be in the range [0, nb_rx_queue - 1] previously supplied * to rte_eth_dev_configure(). * @param epfd * Epoll instance fd which the intr vector associated to. * Using RTE_EPOLL_PER_THREAD allows to use per thread epoll instance. * @param op * The operation be performed for the vector. * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}. * @param data * User raw data. * @return * - On success, zero. * - On failure, a negative value. */ int rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id, int epfd, int op, void *data); /** * Turn on the LED on the Ethernet device. * This function turns on the LED on the Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @return * - (0) if successful. * - (-ENOTSUP) if underlying hardware OR driver doesn't support * that operation. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_led_on(uint8_t port_id); /** * Turn off the LED on the Ethernet device. * This function turns off the LED on the Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @return * - (0) if successful. * - (-ENOTSUP) if underlying hardware OR driver doesn't support * that operation. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_led_off(uint8_t port_id); /** * Get current status of the Ethernet link flow control for Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @param fc_conf * The pointer to the structure where to store the flow control parameters. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow control. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_dev_flow_ctrl_get(uint8_t port_id, struct rte_eth_fc_conf *fc_conf); /** * Configure the Ethernet link flow control for Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @param fc_conf * The pointer to the structure of the flow control parameters. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support flow control mode. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter * - (-EIO) if flow control setup failure */ int rte_eth_dev_flow_ctrl_set(uint8_t port_id, struct rte_eth_fc_conf *fc_conf); /** * Configure the Ethernet priority flow control under DCB environment * for Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param pfc_conf * The pointer to the structure of the priority flow control parameters. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support priority flow control mode. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter * - (-EIO) if flow control setup failure */ int rte_eth_dev_priority_flow_ctrl_set(uint8_t port_id, struct rte_eth_pfc_conf *pfc_conf); /** * Add a MAC address to an internal array of addresses used to enable whitelist * filtering to accept packets only if the destination MAC address matches. * * @param port * The port identifier of the Ethernet device. * @param mac_addr * The MAC address to add. * @param pool * VMDq pool index to associate address with (if VMDq is enabled). If VMDq is * not enabled, this should be set to 0. * @return * - (0) if successfully added or *mac_addr" was already added. * - (-ENOTSUP) if hardware doesn't support this feature. * - (-ENODEV) if *port* is invalid. * - (-ENOSPC) if no more MAC addresses can be added. * - (-EINVAL) if MAC address is invalid. */ int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr, uint32_t pool); /** * Remove a MAC address from the internal array of addresses. * * @param port * The port identifier of the Ethernet device. * @param mac_addr * MAC address to remove. * @return * - (0) if successful, or *mac_addr* didn't exist. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port* invalid. * - (-EADDRINUSE) if attempting to remove the default MAC address */ int rte_eth_dev_mac_addr_remove(uint8_t port, struct ether_addr *mac_addr); /** * Set the default MAC address. * * @param port * The port identifier of the Ethernet device. * @param mac_addr * New default MAC address. * @return * - (0) if successful, or *mac_addr* didn't exist. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port* invalid. * - (-EINVAL) if MAC address is invalid. */ int rte_eth_dev_default_mac_addr_set(uint8_t port, struct ether_addr *mac_addr); /** * Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device. * * @param port * The port identifier of the Ethernet device. * @param reta_conf * RETA to update. * @param reta_size * Redirection table size. The table size can be queried by * rte_eth_dev_info_get(). * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_rss_reta_update(uint8_t port, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); /** * Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. * * @param port * The port identifier of the Ethernet device. * @param reta_conf * RETA to query. * @param reta_size * Redirection table size. The table size can be queried by * rte_eth_dev_info_get(). * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_rss_reta_query(uint8_t port, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); /** * Updates unicast hash table for receiving packet with the given destination * MAC address, and the packet is routed to all VFs for which the RX mode is * accept packets that match the unicast hash table. * * @param port * The port identifier of the Ethernet device. * @param addr * Unicast MAC address. * @param on * 1 - Set an unicast hash bit for receiving packets with the MAC address. * 0 - Clear an unicast hash bit. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_uc_hash_table_set(uint8_t port,struct ether_addr *addr, uint8_t on); /** * Updates all unicast hash bitmaps for receiving packet with any Unicast * Ethernet MAC addresses,the packet is routed to all VFs for which the RX * mode is accept packets that match the unicast hash table. * * @param port * The port identifier of the Ethernet device. * @param on * 1 - Set all unicast hash bitmaps for receiving all the Ethernet * MAC addresses * 0 - Clear all unicast hash bitmaps * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_uc_all_hash_table_set(uint8_t port,uint8_t on); /** * Set RX L2 Filtering mode of a VF of an Ethernet device. * * @param port * The port identifier of the Ethernet device. * @param vf * VF id. * @param rx_mode * The RX mode mask, which is one or more of accepting Untagged Packets, * packets that match the PFUTA table, Broadcast and Multicast Promiscuous. * ETH_VMDQ_ACCEPT_UNTAG,ETH_VMDQ_ACCEPT_HASH_UC, * ETH_VMDQ_ACCEPT_BROADCAST and ETH_VMDQ_ACCEPT_MULTICAST will be used * in rx_mode. * @param on * 1 - Enable a VF RX mode. * 0 - Disable a VF RX mode. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_set_vf_rxmode(uint8_t port, uint16_t vf, uint16_t rx_mode, uint8_t on); /** * Enable or disable a VF traffic transmit of the Ethernet device. * * @param port * The port identifier of the Ethernet device. * @param vf * VF id. * @param on * 1 - Enable a VF traffic transmit. * 0 - Disable a VF traffic transmit. * @return * - (0) if successful. * - (-ENODEV) if *port_id* invalid. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_set_vf_tx(uint8_t port,uint16_t vf, uint8_t on); /** * Enable or disable a VF traffic receive of an Ethernet device. * * @param port * The port identifier of the Ethernet device. * @param vf * VF id. * @param on * 1 - Enable a VF traffic receive. * 0 - Disable a VF traffic receive. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_set_vf_rx(uint8_t port,uint16_t vf, uint8_t on); /** * Enable/Disable hardware VF VLAN filtering by an Ethernet device of * received VLAN packets tagged with a given VLAN Tag Identifier. * * @param port id * The port identifier of the Ethernet device. * @param vlan_id * The VLAN Tag Identifier whose filtering must be enabled or disabled. * @param vf_mask * Bitmap listing which VFs participate in the VLAN filtering. * @param vlan_on * 1 - Enable VFs VLAN filtering. * 0 - Disable VFs VLAN filtering. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id, uint64_t vf_mask, uint8_t vlan_on); /** * Set a traffic mirroring rule on an Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @param mirror_conf * The pointer to the traffic mirroring structure describing the mirroring rule. * The *rte_eth_vm_mirror_conf* structure includes the type of mirroring rule, * destination pool and the value of rule if enable vlan or pool mirroring. * * @param rule_id * The index of traffic mirroring rule, we support four separated rules. * @param on * 1 - Enable a mirroring rule. * 0 - Disable a mirroring rule. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support this feature. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if the mr_conf information is not correct. */ int rte_eth_mirror_rule_set(uint8_t port_id, struct rte_eth_mirror_conf *mirror_conf, uint8_t rule_id, uint8_t on); /** * Reset a traffic mirroring rule on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param rule_id * The index of traffic mirroring rule, we support four separated rules. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support this feature. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_mirror_rule_reset(uint8_t port_id, uint8_t rule_id); /** * Set the rate limitation for a queue on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param queue_idx * The queue id. * @param tx_rate * The tx rate allocated from the total link speed for this queue. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support this feature. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_set_queue_rate_limit(uint8_t port_id, uint16_t queue_idx, uint16_t tx_rate); /** * Set the rate limitation for a vf on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param vf * VF id. * @param tx_rate * The tx rate allocated from the total link speed for this VF id. * @param q_msk * The queue mask which need to set the rate. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support this feature. * - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ int rte_eth_set_vf_rate_limit(uint8_t port_id, uint16_t vf, uint16_t tx_rate, uint64_t q_msk); /** * Initialize bypass logic. This function needs to be called before * executing any other bypass API. * * @param port * The port identifier of the Ethernet device. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_init(uint8_t port); /** * Return bypass state. * * @param port * The port identifier of the Ethernet device. * @param state * The return bypass state. * - (1) Normal mode * - (2) Bypass mode * - (3) Isolate mode * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_state_show(uint8_t port, uint32_t *state); /** * Set bypass state * * @param port * The port identifier of the Ethernet device. * @param new_state * The current bypass state. * - (1) Normal mode * - (2) Bypass mode * - (3) Isolate mode * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_state_set(uint8_t port, uint32_t *new_state); /** * Return bypass state when given event occurs. * * @param port * The port identifier of the Ethernet device. * @param event * The bypass event * - (1) Main power on (power button is pushed) * - (2) Auxiliary power on (power supply is being plugged) * - (3) Main power off (system shutdown and power supply is left plugged in) * - (4) Auxiliary power off (power supply is being unplugged) * - (5) Display or set the watchdog timer * @param state * The bypass state when given event occurred. * - (1) Normal mode * - (2) Bypass mode * - (3) Isolate mode * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_event_show(uint8_t port, uint32_t event, uint32_t *state); /** * Set bypass state when given event occurs. * * @param port * The port identifier of the Ethernet device. * @param event * The bypass event * - (1) Main power on (power button is pushed) * - (2) Auxiliary power on (power supply is being plugged) * - (3) Main power off (system shutdown and power supply is left plugged in) * - (4) Auxiliary power off (power supply is being unplugged) * - (5) Display or set the watchdog timer * @param state * The assigned state when given event occurs. * - (1) Normal mode * - (2) Bypass mode * - (3) Isolate mode * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_event_store(uint8_t port, uint32_t event, uint32_t state); /** * Set bypass watchdog timeout count. * * @param port * The port identifier of the Ethernet device. * @param timeout * The timeout to be set. * - (0) 0 seconds (timer is off) * - (1) 1.5 seconds * - (2) 2 seconds * - (3) 3 seconds * - (4) 4 seconds * - (5) 8 seconds * - (6) 16 seconds * - (7) 32 seconds * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_wd_timeout_store(uint8_t port, uint32_t timeout); /** * Get bypass firmware version. * * @param port * The port identifier of the Ethernet device. * @param ver * The firmware version * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_ver_show(uint8_t port, uint32_t *ver); /** * Return bypass watchdog timeout in seconds * * @param port * The port identifier of the Ethernet device. * @param wd_timeout * The return watchdog timeout. "0" represents timer expired * - (0) 0 seconds (timer is off) * - (1) 1.5 seconds * - (2) 2 seconds * - (3) 3 seconds * - (4) 4 seconds * - (5) 8 seconds * - (6) 16 seconds * - (7) 32 seconds * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_wd_timeout_show(uint8_t port, uint32_t *wd_timeout); /** * Reset bypass watchdog timer * * @param port * The port identifier of the Ethernet device. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_bypass_wd_reset(uint8_t port); /** * Configuration of Receive Side Scaling hash computation of Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param rss_conf * The new configuration to use for RSS hash computation on the port. * @return * - (0) if successful. * - (-ENODEV) if port identifier is invalid. * - (-ENOTSUP) if hardware doesn't support. * - (-EINVAL) if bad parameter. */ int rte_eth_dev_rss_hash_update(uint8_t port_id, struct rte_eth_rss_conf *rss_conf); /** * Retrieve current configuration of Receive Side Scaling hash computation * of Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param rss_conf * Where to store the current RSS hash configuration of the Ethernet device. * @return * - (0) if successful. * - (-ENODEV) if port identifier is invalid. * - (-ENOTSUP) if hardware doesn't support RSS. */ int rte_eth_dev_rss_hash_conf_get(uint8_t port_id, struct rte_eth_rss_conf *rss_conf); /** * Add UDP tunneling port of an Ethernet device for filtering a specific * tunneling packet by UDP port number. * * @param port_id * The port identifier of the Ethernet device. * @param tunnel_udp * UDP tunneling configuration. * * @return * - (0) if successful. * - (-ENODEV) if port identifier is invalid. * - (-ENOTSUP) if hardware doesn't support tunnel type. */ int rte_eth_dev_udp_tunnel_add(uint8_t port_id, struct rte_eth_udp_tunnel *tunnel_udp); /** * Detete UDP tunneling port configuration of Ethernet device * * @param port_id * The port identifier of the Ethernet device. * @param tunnel_udp * UDP tunneling configuration. * * @return * - (0) if successful. * - (-ENODEV) if port identifier is invalid. * - (-ENOTSUP) if hardware doesn't support tunnel type. */ int rte_eth_dev_udp_tunnel_delete(uint8_t port_id, struct rte_eth_udp_tunnel *tunnel_udp); /** * Check whether the filter type is supported on an Ethernet device. * All the supported filter types are defined in 'rte_eth_ctrl.h'. * * @param port_id * The port identifier of the Ethernet device. * @param filter_type * Filter type. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support this filter type. * - (-ENODEV) if *port_id* invalid. */ int rte_eth_dev_filter_supported(uint8_t port_id, enum rte_filter_type filter_type); /** * Take operations to assigned filter type on an Ethernet device. * All the supported operations and filter types are defined in 'rte_eth_ctrl.h'. * * @param port_id * The port identifier of the Ethernet device. * @param filter_type * Filter type. * @param filter_op * Type of operation. * @param arg * A pointer to arguments defined specifically for the operation. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_filter_ctrl(uint8_t port_id, enum rte_filter_type filter_type, enum rte_filter_op filter_op, void *arg); /** * Add a callback to be called on packet RX on a given port and queue. * * This API configures a function to be called for each burst of * packets received on a given NIC port queue. The return value is a pointer * that can be used to later remove the callback using * rte_eth_remove_rx_callback(). * * Multiple functions are called in the order that they are added. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue on the Ethernet device on which the callback is to be added. * @param fn * The callback function * @param user_param * A generic pointer parameter which will be passed to each invocation of the * callback function on this port and queue. * * @return * NULL on error. * On success, a pointer value which can later be used to remove the callback. */ void *rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id, rte_rx_callback_fn fn, void *user_param); /** * Add a callback to be called on packet TX on a given port and queue. * * This API configures a function to be called for each burst of * packets sent on a given NIC port queue. The return value is a pointer * that can be used to later remove the callback using * rte_eth_remove_tx_callback(). * * Multiple functions are called in the order that they are added. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue on the Ethernet device on which the callback is to be added. * @param fn * The callback function * @param user_param * A generic pointer parameter which will be passed to each invocation of the * callback function on this port and queue. * * @return * NULL on error. * On success, a pointer value which can later be used to remove the callback. */ void *rte_eth_add_tx_callback(uint8_t port_id, uint16_t queue_id, rte_tx_callback_fn fn, void *user_param); /** * Remove an RX packet callback from a given port and queue. * * This function is used to removed callbacks that were added to a NIC port * queue using rte_eth_add_rx_callback(). * * Note: the callback is removed from the callback list but it isn't freed * since the it may still be in use. The memory for the callback can be * subsequently freed back by the application by calling rte_free(): * * - Immediately - if the port is stopped, or the user knows that no * callbacks are in flight e.g. if called from the thread doing RX/TX * on that queue. * * - After a short delay - where the delay is sufficient to allow any * in-flight callbacks to complete. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue on the Ethernet device from which the callback is to be removed. * @param user_cb * User supplied callback created via rte_eth_add_rx_callback(). * * @return * - 0: Success. Callback was removed. * - -ENOTSUP: Callback support is not available. * - -EINVAL: The port_id or the queue_id is out of range, or the callback * is NULL or not found for the port/queue. */ int rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id, struct rte_eth_rxtx_callback *user_cb); /** * Remove a TX packet callback from a given port and queue. * * This function is used to removed callbacks that were added to a NIC port * queue using rte_eth_add_tx_callback(). * * Note: the callback is removed from the callback list but it isn't freed * since the it may still be in use. The memory for the callback can be * subsequently freed back by the application by calling rte_free(): * * - Immediately - if the port is stopped, or the user knows that no * callbacks are in flight e.g. if called from the thread doing RX/TX * on that queue. * * - After a short delay - where the delay is sufficient to allow any * in-flight callbacks to complete. * * @param port_id * The port identifier of the Ethernet device. * @param queue_id * The queue on the Ethernet device from which the callback is to be removed. * @param user_cb * User supplied callback created via rte_eth_add_tx_callback(). * * @return * - 0: Success. Callback was removed. * - -ENOTSUP: Callback support is not available. * - -EINVAL: The port_id or the queue_id is out of range, or the callback * is NULL or not found for the port/queue. */ int rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id, struct rte_eth_rxtx_callback *user_cb); /** * Retrieve number of available registers for access * * @param port_id * The port identifier of the Ethernet device. * @return * - (>=0) number of registers if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_get_reg_length(uint8_t port_id); /** * Retrieve device registers and register attributes * * @param port_id * The port identifier of the Ethernet device. * @param info * The template includes buffer for register data and attribute to be filled. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info); /** * Retrieve size of device EEPROM * * @param port_id * The port identifier of the Ethernet device. * @return * - (>=0) EEPROM size if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_get_eeprom_length(uint8_t port_id); /** * Retrieve EEPROM and EEPROM attribute * * @param port_id * The port identifier of the Ethernet device. * @param info * The template includes buffer for return EEPROM data and * EEPROM attributes to be filled. * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_get_eeprom(uint8_t port_id, struct rte_dev_eeprom_info *info); /** * Program EEPROM with provided data * * @param port_id * The port identifier of the Ethernet device. * @param info * The template includes EEPROM data for programming and * EEPROM attributes to be filled * @return * - (0) if successful. * - (-ENOTSUP) if hardware doesn't support. * - (-ENODEV) if *port_id* invalid. * - others depends on the specific operations implementation. */ int rte_eth_dev_set_eeprom(uint8_t port_id, struct rte_dev_eeprom_info *info); /** * Set the list of multicast addresses to filter on an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param mc_addr_set * The array of multicast addresses to set. Equal to NULL when the function * is invoked to flush the set of filtered addresses. * @param nb_mc_addr * The number of multicast addresses in the *mc_addr_set* array. Equal to 0 * when the function is invoked to flush the set of filtered addresses. * @return * - (0) if successful. * - (-ENODEV) if *port_id* invalid. * - (-ENOTSUP) if PMD of *port_id* doesn't support multicast filtering. * - (-ENOSPC) if *port_id* has not enough multicast filtering resources. */ int rte_eth_dev_set_mc_addr_list(uint8_t port_id, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr); /** * Enable IEEE1588/802.1AS timestamping for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * * @return * - 0: Success. * - -ENODEV: The port ID is invalid. * - -ENOTSUP: The function is not supported by the Ethernet driver. */ extern int rte_eth_timesync_enable(uint8_t port_id); /** * Disable IEEE1588/802.1AS timestamping for an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * * @return * - 0: Success. * - -ENODEV: The port ID is invalid. * - -ENOTSUP: The function is not supported by the Ethernet driver. */ extern int rte_eth_timesync_disable(uint8_t port_id); /** * Read an IEEE1588/802.1AS RX timestamp from an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param timestamp * Pointer to the timestamp struct. * @param flags * Device specific flags. Used to pass the RX timesync register index to * i40e. Unused in igb/ixgbe, pass 0 instead. * * @return * - 0: Success. * - -EINVAL: No timestamp is available. * - -ENODEV: The port ID is invalid. * - -ENOTSUP: The function is not supported by the Ethernet driver. */ extern int rte_eth_timesync_read_rx_timestamp(uint8_t port_id, struct timespec *timestamp, uint32_t flags); /** * Read an IEEE1588/802.1AS TX timestamp from an Ethernet device. * * @param port_id * The port identifier of the Ethernet device. * @param timestamp * Pointer to the timestamp struct. * * @return * - 0: Success. * - -EINVAL: No timestamp is available. * - -ENODEV: The port ID is invalid. * - -ENOTSUP: The function is not supported by the Ethernet driver. */ extern int rte_eth_timesync_read_tx_timestamp(uint8_t port_id, struct timespec *timestamp); #ifdef __cplusplus } #endif #endif /* _RTE_ETHDEV_H_ */ ================================================ FILE: lib/librte_ether/rte_ether.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ETHER_H_ #define _RTE_ETHER_H_ /** * @file * * Ethernet Helpers in RTE */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ #define ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */ #define ETHER_CRC_LEN 4 /**< Length of Ethernet CRC. */ #define ETHER_HDR_LEN \ (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) /**< Length of Ethernet header. */ #define ETHER_MIN_LEN 64 /**< Minimum frame len, including CRC. */ #define ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */ #define ETHER_MTU \ (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) /**< Ethernet MTU. */ #define ETHER_MAX_VLAN_FRAME_LEN \ (ETHER_MAX_LEN + 4) /**< Maximum VLAN frame length, including CRC. */ #define ETHER_MAX_JUMBO_FRAME_LEN \ 0x3F00 /**< Maximum Jumbo frame length, including CRC. */ #define ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */ #define ETHER_MIN_MTU 68 /**< Minimum MTU for IPv4 packets, see RFC 791. */ /** * Ethernet address: * A universally administered address is uniquely assigned to a device by its * manufacturer. The first three octets (in transmission order) contain the * Organizationally Unique Identifier (OUI). The following three (MAC-48 and * EUI-48) octets are assigned by that organization with the only constraint * of uniqueness. * A locally administered address is assigned to a device by a network * administrator and does not contain OUIs. * See http://standards.ieee.org/regauth/groupmac/tutorial.html */ struct ether_addr { uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Address bytes in transmission order */ } __attribute__((__packed__)); #define ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */ #define ETHER_GROUP_ADDR 0x01 /**< Multicast or broadcast Eth. address. */ /** * Check if two Ethernet addresses are the same. * * @param ea1 * A pointer to the first ether_addr structure containing * the ethernet address. * @param ea2 * A pointer to the second ether_addr structure containing * the ethernet address. * * @return * True (1) if the given two ethernet address are the same; * False (0) otherwise. */ static inline int is_same_ether_addr(const struct ether_addr *ea1, const struct ether_addr *ea2) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) if (ea1->addr_bytes[i] != ea2->addr_bytes[i]) return 0; return 1; } /** * Check if an Ethernet address is filled with zeros. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is filled with zeros; * false (0) otherwise. */ static inline int is_zero_ether_addr(const struct ether_addr *ea) { int i; for (i = 0; i < ETHER_ADDR_LEN; i++) if (ea->addr_bytes[i] != 0x00) return 0; return 1; } /** * Check if an Ethernet address is a unicast address. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is a unicast address; * false (0) otherwise. */ static inline int is_unicast_ether_addr(const struct ether_addr *ea) { return ((ea->addr_bytes[0] & ETHER_GROUP_ADDR) == 0); } /** * Check if an Ethernet address is a multicast address. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is a multicast address; * false (0) otherwise. */ static inline int is_multicast_ether_addr(const struct ether_addr *ea) { return (ea->addr_bytes[0] & ETHER_GROUP_ADDR); } /** * Check if an Ethernet address is a broadcast address. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is a broadcast address; * false (0) otherwise. */ static inline int is_broadcast_ether_addr(const struct ether_addr *ea) { const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea; return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF && ea_words[2] == 0xFFFF); } /** * Check if an Ethernet address is a universally assigned address. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is a universally assigned address; * false (0) otherwise. */ static inline int is_universal_ether_addr(const struct ether_addr *ea) { return ((ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) == 0); } /** * Check if an Ethernet address is a locally assigned address. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is a locally assigned address; * false (0) otherwise. */ static inline int is_local_admin_ether_addr(const struct ether_addr *ea) { return ((ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) != 0); } /** * Check if an Ethernet address is a valid address. Checks that the address is a * unicast address and is not filled with zeros. * * @param ea * A pointer to a ether_addr structure containing the ethernet address * to check. * @return * True (1) if the given ethernet address is valid; * false (0) otherwise. */ static inline int is_valid_assigned_ether_addr(const struct ether_addr *ea) { return (is_unicast_ether_addr(ea) && (! is_zero_ether_addr(ea))); } /** * Generate a random Ethernet address that is locally administered * and not multicast. * @param addr * A pointer to Ethernet address. */ static inline void eth_random_addr(uint8_t *addr) { uint64_t rand = rte_rand(); uint8_t *p = (uint8_t*)&rand; rte_memcpy(addr, p, ETHER_ADDR_LEN); addr[0] &= ~ETHER_GROUP_ADDR; /* clear multicast bit */ addr[0] |= ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */ } /** * Fast copy an Ethernet address. * * @param ea_from * A pointer to a ether_addr structure holding the Ethernet address to copy. * @param ea_to * A pointer to a ether_addr structure where to copy the Ethernet address. */ static inline void ether_addr_copy(const struct ether_addr *ea_from, struct ether_addr *ea_to) { #ifdef __INTEL_COMPILER uint16_t *from_words = (uint16_t *)(ea_from->addr_bytes); uint16_t *to_words = (uint16_t *)(ea_to->addr_bytes); to_words[0] = from_words[0]; to_words[1] = from_words[1]; to_words[2] = from_words[2]; #else /* * Use the common way, because of a strange gcc warning. */ *ea_to = *ea_from; #endif } #define ETHER_ADDR_FMT_SIZE 18 /** * Format 48bits Ethernet address in pattern xx:xx:xx:xx:xx:xx. * * @param buf * A pointer to buffer contains the formatted MAC address. * @param size * The format buffer size. * @param eth_addr * A pointer to a ether_addr structure. */ static inline void ether_format_addr(char *buf, uint16_t size, const struct ether_addr *eth_addr) { snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", eth_addr->addr_bytes[0], eth_addr->addr_bytes[1], eth_addr->addr_bytes[2], eth_addr->addr_bytes[3], eth_addr->addr_bytes[4], eth_addr->addr_bytes[5]); } /** * Ethernet header: Contains the destination address, source address * and frame type. */ struct ether_hdr { struct ether_addr d_addr; /**< Destination address. */ struct ether_addr s_addr; /**< Source address. */ uint16_t ether_type; /**< Frame type. */ } __attribute__((__packed__)); /** * Ethernet VLAN Header. * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type * of the encapsulated frame. */ struct vlan_hdr { uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */ } __attribute__((__packed__)); /** * VXLAN protocol header. * Contains the 8-bit flag, 24-bit VXLAN Network Identifier and * Reserved fields (24 bits and 8 bits) */ struct vxlan_hdr { uint32_t vx_flags; /**< flag (8) + Reserved (24). */ uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ } __attribute__((__packed__)); /* Ethernet frame types */ #define ETHER_TYPE_IPv4 0x0800 /**< IPv4 Protocol. */ #define ETHER_TYPE_IPv6 0x86DD /**< IPv6 Protocol. */ #define ETHER_TYPE_ARP 0x0806 /**< Arp Protocol. */ #define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */ #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */ #define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */ #define ETHER_TYPE_TEB 0x6558 /**< Transparent Ethernet Bridging. */ #define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr)) /**< VXLAN tunnel header length. */ /** * Extract VLAN tag information into mbuf * * Software version of VLAN stripping * * @param m * The packet mbuf. * @return * - 0: Success * - 1: not a vlan packet */ static inline int rte_vlan_strip(struct rte_mbuf *m) { struct ether_hdr *eh = rte_pktmbuf_mtod(m, struct ether_hdr *); if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) return -1; struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1); m->ol_flags |= PKT_RX_VLAN_PKT; m->vlan_tci = rte_be_to_cpu_16(vh->vlan_tci); /* Copy ether header over rather than moving whole packet */ memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)), eh, 2 * ETHER_ADDR_LEN); return 0; } /** * Insert VLAN tag into mbuf. * * Software version of VLAN unstripping * * @param m * The packet mbuf. * @return * - 0: On success * -EPERM: mbuf is is shared overwriting would be unsafe * -ENOSPC: not enough headroom in mbuf */ static inline int rte_vlan_insert(struct rte_mbuf **m) { struct ether_hdr *oh, *nh; struct vlan_hdr *vh; /* Can't insert header if mbuf is shared */ if (rte_mbuf_refcnt_read(*m) > 1) { struct rte_mbuf *copy; copy = rte_pktmbuf_clone(*m, (*m)->pool); if (unlikely(copy == NULL)) return -ENOMEM; rte_pktmbuf_free(*m); *m = copy; } oh = rte_pktmbuf_mtod(*m, struct ether_hdr *); nh = (struct ether_hdr *) rte_pktmbuf_prepend(*m, sizeof(struct vlan_hdr)); if (nh == NULL) return -ENOSPC; memmove(nh, oh, 2 * ETHER_ADDR_LEN); nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN); vh = (struct vlan_hdr *) (nh + 1); vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); return 0; } #ifdef __cplusplus } #endif #endif /* _RTE_ETHER_H_ */ ================================================ FILE: lib/librte_hash/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_hash.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_hash_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_HASH) := rte_cuckoo_hash.c SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h # this lib needs eal and ring DEPDIRS-$(CONFIG_RTE_LIBRTE_HASH) += lib/librte_eal lib/librte_ring include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_hash/rte_cmp_x86.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Functions to compare multiple of 16 byte keys (up to 128 bytes) */ static int rte_hash_k16_cmp_eq(const void *key1, const void *key2, size_t key_len __rte_unused) { const __m128i k1 = _mm_loadu_si128((const __m128i *) key1); const __m128i k2 = _mm_loadu_si128((const __m128i *) key2); #ifdef RTE_MACHINE_CPUFLAG_SSE4_1 const __m128i x = _mm_xor_si128(k1, k2); return !_mm_test_all_zeros(x, x); #else const __m128i x = _mm_cmpeq_epi32(k1, k2); return (_mm_movemask_epi8(x) != 0xffff); #endif } static int rte_hash_k32_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k16_cmp_eq(key1, key2, key_len) || rte_hash_k16_cmp_eq((const char *) key1 + 16, (const char *) key2 + 16, key_len); } static int rte_hash_k48_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k16_cmp_eq(key1, key2, key_len) || rte_hash_k16_cmp_eq((const char *) key1 + 16, (const char *) key2 + 16, key_len) || rte_hash_k16_cmp_eq((const char *) key1 + 32, (const char *) key2 + 32, key_len); } static int rte_hash_k64_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k32_cmp_eq(key1, key2, key_len) || rte_hash_k32_cmp_eq((const char *) key1 + 32, (const char *) key2 + 32, key_len); } static int rte_hash_k80_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k64_cmp_eq(key1, key2, key_len) || rte_hash_k16_cmp_eq((const char *) key1 + 64, (const char *) key2 + 64, key_len); } static int rte_hash_k96_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k64_cmp_eq(key1, key2, key_len) || rte_hash_k32_cmp_eq((const char *) key1 + 64, (const char *) key2 + 64, key_len); } static int rte_hash_k112_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k64_cmp_eq(key1, key2, key_len) || rte_hash_k32_cmp_eq((const char *) key1 + 64, (const char *) key2 + 64, key_len) || rte_hash_k16_cmp_eq((const char *) key1 + 96, (const char *) key2 + 96, key_len); } static int rte_hash_k128_cmp_eq(const void *key1, const void *key2, size_t key_len) { return rte_hash_k64_cmp_eq(key1, key2, key_len) || rte_hash_k64_cmp_eq((const char *) key1 + 64, (const char *) key2 + 64, key_len); } ================================================ FILE: lib/librte_hash/rte_cuckoo_hash.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include /* for definition of RTE_CACHE_LINE_SIZE */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_hash.h" #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_X32) #include "rte_cmp_x86.h" #endif TAILQ_HEAD(rte_hash_list, rte_tailq_entry); static struct rte_tailq_elem rte_hash_tailq = { .name = "RTE_HASH", }; EAL_REGISTER_TAILQ(rte_hash_tailq) /* Macro to enable/disable run-time checking of function parameters */ #if defined(RTE_LIBRTE_HASH_DEBUG) #define RETURN_IF_TRUE(cond, retval) do { \ if (cond) \ return retval; \ } while (0) #else #define RETURN_IF_TRUE(cond, retval) #endif /* Hash function used if none is specified */ #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #define DEFAULT_HASH_FUNC rte_hash_crc #else #include #define DEFAULT_HASH_FUNC rte_jhash #endif /** Number of items per bucket. */ #define RTE_HASH_BUCKET_ENTRIES 4 #define NULL_SIGNATURE 0 #define KEY_ALIGNMENT 16 typedef int (*rte_hash_cmp_eq_t)(const void *key1, const void *key2, size_t key_len); /** A hash table structure. */ struct rte_hash { char name[RTE_HASH_NAMESIZE]; /**< Name of the hash. */ uint32_t entries; /**< Total table entries. */ uint32_t num_buckets; /**< Number of buckets in table. */ uint32_t key_len; /**< Length of hash key. */ rte_hash_function hash_func; /**< Function used to calculate hash. */ uint32_t hash_func_init_val; /**< Init value used by hash_func. */ rte_hash_cmp_eq_t rte_hash_cmp_eq; /**< Function used to compare keys. */ uint32_t bucket_bitmask; /**< Bitmask for getting bucket index from hash signature. */ uint32_t key_entry_size; /**< Size of each key entry. */ struct rte_ring *free_slots; /**< Ring that stores all indexes of the free slots in the key table */ void *key_store; /**< Table storing all keys and data */ struct rte_hash_bucket *buckets; /**< Table with buckets storing all the hash values and key indexes to the key table*/ } __rte_cache_aligned; /* Structure storing both primary and secondary hashes */ struct rte_hash_signatures { union { struct { hash_sig_t current; hash_sig_t alt; }; uint64_t sig; }; }; /* Structure that stores key-value pair */ struct rte_hash_key { union { uintptr_t idata; void *pdata; }; /* Variable key size */ char key[0]; } __attribute__((aligned(KEY_ALIGNMENT))); /** Bucket structure */ struct rte_hash_bucket { struct rte_hash_signatures signatures[RTE_HASH_BUCKET_ENTRIES]; /* Includes dummy key index that always contains index 0 */ uint32_t key_idx[RTE_HASH_BUCKET_ENTRIES + 1]; uint8_t flag[RTE_HASH_BUCKET_ENTRIES]; } __rte_cache_aligned; struct rte_hash * rte_hash_find_existing(const char *name) { struct rte_hash *h = NULL; struct rte_tailq_entry *te; struct rte_hash_list *hash_list; hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, hash_list, next) { h = (struct rte_hash *) te->data; if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return h; } struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params) { struct rte_hash *h = NULL; struct rte_tailq_entry *te = NULL; struct rte_hash_list *hash_list; struct rte_ring *r = NULL; char hash_name[RTE_HASH_NAMESIZE]; void *ptr, *k = NULL; void *buckets = NULL; char ring_name[RTE_RING_NAMESIZE]; unsigned i; hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list); if (params == NULL) { RTE_LOG(ERR, HASH, "rte_hash_create has no parameters\n"); return NULL; } /* Check for valid parameters */ if ((params->entries > RTE_HASH_ENTRIES_MAX) || (params->entries < RTE_HASH_BUCKET_ENTRIES) || !rte_is_power_of_2(RTE_HASH_BUCKET_ENTRIES) || (params->key_len == 0)) { rte_errno = EINVAL; RTE_LOG(ERR, HASH, "rte_hash_create has invalid parameters\n"); return NULL; } snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name); /* Guarantee there's no existing */ h = rte_hash_find_existing(params->name); if (h != NULL) return h; te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, HASH, "tailq entry allocation failed\n"); goto err; } h = (struct rte_hash *)rte_zmalloc_socket(hash_name, sizeof(struct rte_hash), RTE_CACHE_LINE_SIZE, params->socket_id); if (h == NULL) { RTE_LOG(ERR, HASH, "memory allocation failed\n"); goto err; } const uint32_t num_buckets = rte_align32pow2(params->entries) / RTE_HASH_BUCKET_ENTRIES; buckets = rte_zmalloc_socket(NULL, num_buckets * sizeof(struct rte_hash_bucket), RTE_CACHE_LINE_SIZE, params->socket_id); if (buckets == NULL) { RTE_LOG(ERR, HASH, "memory allocation failed\n"); goto err; } const uint32_t key_entry_size = sizeof(struct rte_hash_key) + params->key_len; /* Store all keys and leave the first entry as a dummy entry for lookup_bulk */ const uint64_t key_tbl_size = key_entry_size * (params->entries + 1); k = rte_zmalloc_socket(NULL, key_tbl_size, RTE_CACHE_LINE_SIZE, params->socket_id); if (k == NULL) { RTE_LOG(ERR, HASH, "memory allocation failed\n"); goto err; } /* * If x86 architecture is used, select appropriate compare function, * which may use x86 instrinsics, otherwise use memcmp */ #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_X32) /* Select function to compare keys */ switch (params->key_len) { case 16: h->rte_hash_cmp_eq = rte_hash_k16_cmp_eq; break; case 32: h->rte_hash_cmp_eq = rte_hash_k32_cmp_eq; break; case 48: h->rte_hash_cmp_eq = rte_hash_k48_cmp_eq; break; case 64: h->rte_hash_cmp_eq = rte_hash_k64_cmp_eq; break; case 80: h->rte_hash_cmp_eq = rte_hash_k80_cmp_eq; break; case 96: h->rte_hash_cmp_eq = rte_hash_k96_cmp_eq; break; case 112: h->rte_hash_cmp_eq = rte_hash_k112_cmp_eq; break; case 128: h->rte_hash_cmp_eq = rte_hash_k128_cmp_eq; break; default: /* If key is not multiple of 16, use generic memcmp */ h->rte_hash_cmp_eq = memcmp; } #else h->rte_hash_cmp_eq = memcmp; #endif snprintf(ring_name, sizeof(ring_name), "HT_%s", params->name); r = rte_ring_lookup(ring_name); if (r != NULL) { /* clear the free ring */ while (rte_ring_dequeue(r, &ptr) == 0) rte_pause(); } else r = rte_ring_create(ring_name, rte_align32pow2(params->entries + 1), params->socket_id, 0); if (r == NULL) { RTE_LOG(ERR, HASH, "memory allocation failed\n"); goto err; } /* Setup hash context */ snprintf(h->name, sizeof(h->name), "%s", params->name); h->entries = params->entries; h->key_len = params->key_len; h->key_entry_size = key_entry_size; h->hash_func_init_val = params->hash_func_init_val; h->num_buckets = num_buckets; h->bucket_bitmask = h->num_buckets - 1; h->buckets = buckets; h->hash_func = (params->hash_func == NULL) ? DEFAULT_HASH_FUNC : params->hash_func; h->key_store = k; h->free_slots = r; /* populate the free slots ring. Entry zero is reserved for key misses */ for (i = 1; i < params->entries + 1; i++) rte_ring_sp_enqueue(r, (void *)((uintptr_t) i)); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); te->data = (void *) h; TAILQ_INSERT_TAIL(hash_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return h; err: rte_free(te); rte_free(h); rte_free(buckets); rte_free(k); return NULL; } void rte_hash_free(struct rte_hash *h) { struct rte_tailq_entry *te; struct rte_hash_list *hash_list; if (h == NULL) return; hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find out tailq entry */ TAILQ_FOREACH(te, hash_list, next) { if (te->data == (void *) h) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(hash_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(h->key_store); rte_free(h->buckets); rte_free(h); rte_free(te); } hash_sig_t rte_hash_hash(const struct rte_hash *h, const void *key) { /* calc hash result by key */ return h->hash_func(key, h->key_len, h->hash_func_init_val); } /* Calc the secondary hash value from the primary hash value of a given key */ static inline hash_sig_t rte_hash_secondary_hash(const hash_sig_t primary_hash) { static const unsigned all_bits_shift = 12; static const unsigned alt_bits_xor = 0x5bd1e995; uint32_t tag = primary_hash >> all_bits_shift; return (primary_hash ^ ((tag + 1) * alt_bits_xor)); } void rte_hash_reset(struct rte_hash *h) { void *ptr; unsigned i; if (h == NULL) return; memset(h->buckets, 0, h->num_buckets * sizeof(struct rte_hash_bucket)); memset(h->key_store, 0, h->key_entry_size * (h->entries + 1)); /* clear the free ring */ while (rte_ring_dequeue(h->free_slots, &ptr) == 0) rte_pause(); /* Repopulate the free slots ring. Entry zero is reserved for key misses */ for (i = 1; i < h->entries + 1; i++) rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t) i)); } /* Search for an entry that can be pushed to its alternative location */ static inline int make_space_bucket(const struct rte_hash *h, struct rte_hash_bucket *bkt) { unsigned i, j; int ret; uint32_t next_bucket_idx; struct rte_hash_bucket *next_bkt[RTE_HASH_BUCKET_ENTRIES]; /* * Push existing item (search for bucket with space in * alternative locations) to its alternative location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { /* Search for space in alternative locations */ next_bucket_idx = bkt->signatures[i].alt & h->bucket_bitmask; next_bkt[i] = &h->buckets[next_bucket_idx]; for (j = 0; j < RTE_HASH_BUCKET_ENTRIES; j++) { if (next_bkt[i]->signatures[j].sig == NULL_SIGNATURE) break; } if (j != RTE_HASH_BUCKET_ENTRIES) break; } /* Alternative location has spare room (end of recursive function) */ if (i != RTE_HASH_BUCKET_ENTRIES) { next_bkt[i]->signatures[j].alt = bkt->signatures[i].current; next_bkt[i]->signatures[j].current = bkt->signatures[i].alt; next_bkt[i]->key_idx[j] = bkt->key_idx[i]; return i; } /* Pick entry that has not been pushed yet */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) if (bkt->flag[i] == 0) break; /* All entries have been pushed, so entry cannot be added */ if (i == RTE_HASH_BUCKET_ENTRIES) return -ENOSPC; /* Set flag to indicate that this entry is going to be pushed */ bkt->flag[i] = 1; /* Need room in alternative bucket to insert the pushed entry */ ret = make_space_bucket(h, next_bkt[i]); /* * After recursive function. * Clear flags and insert the pushed entry * in its alternative location if successful, * or return error */ bkt->flag[i] = 0; if (ret >= 0) { next_bkt[i]->signatures[ret].alt = bkt->signatures[i].current; next_bkt[i]->signatures[ret].current = bkt->signatures[i].alt; next_bkt[i]->key_idx[ret] = bkt->key_idx[i]; return i; } else return ret; } static inline int32_t __rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig, void *data) { hash_sig_t alt_hash; uint32_t prim_bucket_idx, sec_bucket_idx; unsigned i; struct rte_hash_bucket *prim_bkt, *sec_bkt; struct rte_hash_key *new_k, *k, *keys = h->key_store; void *slot_id; uint32_t new_idx; int ret; prim_bucket_idx = sig & h->bucket_bitmask; prim_bkt = &h->buckets[prim_bucket_idx]; rte_prefetch0(prim_bkt); alt_hash = rte_hash_secondary_hash(sig); sec_bucket_idx = alt_hash & h->bucket_bitmask; sec_bkt = &h->buckets[sec_bucket_idx]; rte_prefetch0(sec_bkt); /* Get a new slot for storing the new key */ if (rte_ring_sc_dequeue(h->free_slots, &slot_id) != 0) return -ENOSPC; new_k = RTE_PTR_ADD(keys, (uintptr_t)slot_id * h->key_entry_size); rte_prefetch0(new_k); new_idx = (uint32_t)((uintptr_t) slot_id); /* Check if key is already inserted in primary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (prim_bkt->signatures[i].current == sig && prim_bkt->signatures[i].alt == alt_hash) { k = (struct rte_hash_key *) ((char *)keys + prim_bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { rte_ring_sp_enqueue(h->free_slots, slot_id); /* Update data */ k->pdata = data; /* * Return index where key is stored, * substracting the first dummy index */ return (prim_bkt->key_idx[i] - 1); } } } /* Check if key is already inserted in secondary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (sec_bkt->signatures[i].alt == sig && sec_bkt->signatures[i].current == alt_hash) { k = (struct rte_hash_key *) ((char *)keys + sec_bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { rte_ring_sp_enqueue(h->free_slots, slot_id); /* Update data */ k->pdata = data; /* * Return index where key is stored, * substracting the first dummy index */ return (sec_bkt->key_idx[i] - 1); } } } /* Copy key */ rte_memcpy(new_k->key, key, h->key_len); new_k->pdata = data; /* Insert new entry is there is room in the primary bucket */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { /* Check if slot is available */ if (likely(prim_bkt->signatures[i].sig == NULL_SIGNATURE)) { prim_bkt->signatures[i].current = sig; prim_bkt->signatures[i].alt = alt_hash; prim_bkt->key_idx[i] = new_idx; return new_idx - 1; } } /* Primary bucket is full, so we need to make space for new entry */ ret = make_space_bucket(h, prim_bkt); /* * After recursive function. * Insert the new entry in the position of the pushed entry * if successful or return error and * store the new slot back in the ring */ if (ret >= 0) { prim_bkt->signatures[ret].current = sig; prim_bkt->signatures[ret].alt = alt_hash; prim_bkt->key_idx[ret] = new_idx; return (new_idx - 1); } /* Error in addition, store new slot back in the ring and return error */ rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t) new_idx)); return ret; } int32_t rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_add_key_with_hash(h, key, sig, 0); } int32_t rte_hash_add_key(const struct rte_hash *h, const void *key) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_add_key_with_hash(h, key, rte_hash_hash(h, key), 0); } int rte_hash_add_key_with_hash_data(const struct rte_hash *h, const void *key, hash_sig_t sig, void *data) { int ret; RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); ret = __rte_hash_add_key_with_hash(h, key, sig, data); if (ret >= 0) return 0; else return ret; } int rte_hash_add_key_data(const struct rte_hash *h, const void *key, void *data) { int ret; RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); ret = __rte_hash_add_key_with_hash(h, key, rte_hash_hash(h, key), data); if (ret >= 0) return 0; else return ret; } static inline int32_t __rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig, void **data) { uint32_t bucket_idx; hash_sig_t alt_hash; unsigned i; struct rte_hash_bucket *bkt; struct rte_hash_key *k, *keys = h->key_store; bucket_idx = sig & h->bucket_bitmask; bkt = &h->buckets[bucket_idx]; /* Check if key is in primary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (bkt->signatures[i].current == sig && bkt->signatures[i].sig != NULL_SIGNATURE) { k = (struct rte_hash_key *) ((char *)keys + bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { if (data != NULL) *data = k->pdata; /* * Return index where key is stored, * substracting the first dummy index */ return (bkt->key_idx[i] - 1); } } } /* Calculate secondary hash */ alt_hash = rte_hash_secondary_hash(sig); bucket_idx = alt_hash & h->bucket_bitmask; bkt = &h->buckets[bucket_idx]; /* Check if key is in secondary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (bkt->signatures[i].current == alt_hash && bkt->signatures[i].alt == sig) { k = (struct rte_hash_key *) ((char *)keys + bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { if (data != NULL) *data = k->pdata; /* * Return index where key is stored, * substracting the first dummy index */ return (bkt->key_idx[i] - 1); } } } return -ENOENT; } int32_t rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_lookup_with_hash(h, key, sig, NULL); } int32_t rte_hash_lookup(const struct rte_hash *h, const void *key) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key), NULL); } int rte_hash_lookup_with_hash_data(const struct rte_hash *h, const void *key, hash_sig_t sig, void **data) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_lookup_with_hash(h, key, sig, data); } int rte_hash_lookup_data(const struct rte_hash *h, const void *key, void **data) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key), data); } static inline int32_t __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig) { uint32_t bucket_idx; hash_sig_t alt_hash; unsigned i; struct rte_hash_bucket *bkt; struct rte_hash_key *k, *keys = h->key_store; bucket_idx = sig & h->bucket_bitmask; bkt = &h->buckets[bucket_idx]; /* Check if key is in primary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (bkt->signatures[i].current == sig && bkt->signatures[i].sig != NULL_SIGNATURE) { k = (struct rte_hash_key *) ((char *)keys + bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { bkt->signatures[i].sig = NULL_SIGNATURE; rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)bkt->key_idx[i])); /* * Return index where key is stored, * substracting the first dummy index */ return (bkt->key_idx[i] - 1); } } } /* Calculate secondary hash */ alt_hash = rte_hash_secondary_hash(sig); bucket_idx = alt_hash & h->bucket_bitmask; bkt = &h->buckets[bucket_idx]; /* Check if key is in secondary location */ for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { if (bkt->signatures[i].current == alt_hash && bkt->signatures[i].sig != NULL_SIGNATURE) { k = (struct rte_hash_key *) ((char *)keys + bkt->key_idx[i] * h->key_entry_size); if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) { bkt->signatures[i].sig = NULL_SIGNATURE; rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t)bkt->key_idx[i])); /* * Return index where key is stored, * substracting the first dummy index */ return (bkt->key_idx[i] - 1); } } } return -ENOENT; } int32_t rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_del_key_with_hash(h, key, sig); } int32_t rte_hash_del_key(const struct rte_hash *h, const void *key) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key)); } /* Lookup bulk stage 0: Prefetch input key */ static inline void lookup_stage0(unsigned *idx, uint64_t *lookup_mask, const void * const *keys) { *idx = __builtin_ctzl(*lookup_mask); if (*lookup_mask == 0) *idx = 0; rte_prefetch0(keys[*idx]); *lookup_mask &= ~(1llu << *idx); } /* * Lookup bulk stage 1: Calculate primary/secondary hashes * and prefetch primary/secondary buckets */ static inline void lookup_stage1(unsigned idx, hash_sig_t *prim_hash, hash_sig_t *sec_hash, const struct rte_hash_bucket **primary_bkt, const struct rte_hash_bucket **secondary_bkt, hash_sig_t *hash_vals, const void * const *keys, const struct rte_hash *h) { *prim_hash = rte_hash_hash(h, keys[idx]); hash_vals[idx] = *prim_hash; *sec_hash = rte_hash_secondary_hash(*prim_hash); *primary_bkt = &h->buckets[*prim_hash & h->bucket_bitmask]; *secondary_bkt = &h->buckets[*sec_hash & h->bucket_bitmask]; rte_prefetch0(*primary_bkt); rte_prefetch0(*secondary_bkt); } /* * Lookup bulk stage 2: Search for match hashes in primary/secondary locations * and prefetch first key slot */ static inline void lookup_stage2(unsigned idx, hash_sig_t prim_hash, hash_sig_t sec_hash, const struct rte_hash_bucket *prim_bkt, const struct rte_hash_bucket *sec_bkt, const struct rte_hash_key **key_slot, int32_t *positions, uint64_t *extra_hits_mask, const void *keys, const struct rte_hash *h) { unsigned prim_hash_matches, sec_hash_matches, key_idx, i; unsigned total_hash_matches; prim_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES; sec_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES; for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) { prim_hash_matches |= ((prim_hash == prim_bkt->signatures[i].current) << i); sec_hash_matches |= ((sec_hash == sec_bkt->signatures[i].current) << i); } key_idx = prim_bkt->key_idx[__builtin_ctzl(prim_hash_matches)]; if (key_idx == 0) key_idx = sec_bkt->key_idx[__builtin_ctzl(sec_hash_matches)]; total_hash_matches = (prim_hash_matches | (sec_hash_matches << (RTE_HASH_BUCKET_ENTRIES + 1))); *key_slot = (const struct rte_hash_key *) ((const char *)keys + key_idx * h->key_entry_size); rte_prefetch0(*key_slot); /* * Return index where key is stored, * substracting the first dummy index */ positions[idx] = (key_idx - 1); *extra_hits_mask |= (uint64_t)(__builtin_popcount(total_hash_matches) > 3) << idx; } /* Lookup bulk stage 3: Check if key matches, update hit mask and return data */ static inline void lookup_stage3(unsigned idx, const struct rte_hash_key *key_slot, const void * const *keys, void *data[], uint64_t *hits, const struct rte_hash *h) { unsigned hit; hit = !h->rte_hash_cmp_eq(key_slot->key, keys[idx], h->key_len); if (data != NULL) data[idx] = key_slot->pdata; *hits |= (uint64_t)(hit) << idx; } static inline void __rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys, uint32_t num_keys, int32_t *positions, uint64_t *hit_mask, void *data[]) { uint64_t hits = 0; uint64_t extra_hits_mask = 0; uint64_t lookup_mask, miss_mask; unsigned idx; const void *key_store = h->key_store; int ret; hash_sig_t hash_vals[RTE_HASH_LOOKUP_BULK_MAX]; unsigned idx00, idx01, idx10, idx11, idx20, idx21, idx30, idx31; const struct rte_hash_bucket *primary_bkt10, *primary_bkt11; const struct rte_hash_bucket *secondary_bkt10, *secondary_bkt11; const struct rte_hash_bucket *primary_bkt20, *primary_bkt21; const struct rte_hash_bucket *secondary_bkt20, *secondary_bkt21; const struct rte_hash_key *k_slot20, *k_slot21, *k_slot30, *k_slot31; hash_sig_t primary_hash10, primary_hash11; hash_sig_t secondary_hash10, secondary_hash11; hash_sig_t primary_hash20, primary_hash21; hash_sig_t secondary_hash20, secondary_hash21; lookup_mask = (uint64_t) -1 >> (64 - num_keys); miss_mask = lookup_mask; lookup_stage0(&idx00, &lookup_mask, keys); lookup_stage0(&idx01, &lookup_mask, keys); idx10 = idx00, idx11 = idx01; lookup_stage0(&idx00, &lookup_mask, keys); lookup_stage0(&idx01, &lookup_mask, keys); lookup_stage1(idx10, &primary_hash10, &secondary_hash10, &primary_bkt10, &secondary_bkt10, hash_vals, keys, h); lookup_stage1(idx11, &primary_hash11, &secondary_hash11, &primary_bkt11, &secondary_bkt11, hash_vals, keys, h); primary_bkt20 = primary_bkt10; primary_bkt21 = primary_bkt11; secondary_bkt20 = secondary_bkt10; secondary_bkt21 = secondary_bkt11; primary_hash20 = primary_hash10; primary_hash21 = primary_hash11; secondary_hash20 = secondary_hash10; secondary_hash21 = secondary_hash11; idx20 = idx10, idx21 = idx11; idx10 = idx00, idx11 = idx01; lookup_stage0(&idx00, &lookup_mask, keys); lookup_stage0(&idx01, &lookup_mask, keys); lookup_stage1(idx10, &primary_hash10, &secondary_hash10, &primary_bkt10, &secondary_bkt10, hash_vals, keys, h); lookup_stage1(idx11, &primary_hash11, &secondary_hash11, &primary_bkt11, &secondary_bkt11, hash_vals, keys, h); lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20, secondary_bkt20, &k_slot20, positions, &extra_hits_mask, key_store, h); lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21, secondary_bkt21, &k_slot21, positions, &extra_hits_mask, key_store, h); while (lookup_mask) { k_slot30 = k_slot20, k_slot31 = k_slot21; idx30 = idx20, idx31 = idx21; primary_bkt20 = primary_bkt10; primary_bkt21 = primary_bkt11; secondary_bkt20 = secondary_bkt10; secondary_bkt21 = secondary_bkt11; primary_hash20 = primary_hash10; primary_hash21 = primary_hash11; secondary_hash20 = secondary_hash10; secondary_hash21 = secondary_hash11; idx20 = idx10, idx21 = idx11; idx10 = idx00, idx11 = idx01; lookup_stage0(&idx00, &lookup_mask, keys); lookup_stage0(&idx01, &lookup_mask, keys); lookup_stage1(idx10, &primary_hash10, &secondary_hash10, &primary_bkt10, &secondary_bkt10, hash_vals, keys, h); lookup_stage1(idx11, &primary_hash11, &secondary_hash11, &primary_bkt11, &secondary_bkt11, hash_vals, keys, h); lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20, secondary_bkt20, &k_slot20, positions, &extra_hits_mask, key_store, h); lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21, secondary_bkt21, &k_slot21, positions, &extra_hits_mask, key_store, h); lookup_stage3(idx30, k_slot30, keys, data, &hits, h); lookup_stage3(idx31, k_slot31, keys, data, &hits, h); } k_slot30 = k_slot20, k_slot31 = k_slot21; idx30 = idx20, idx31 = idx21; primary_bkt20 = primary_bkt10; primary_bkt21 = primary_bkt11; secondary_bkt20 = secondary_bkt10; secondary_bkt21 = secondary_bkt11; primary_hash20 = primary_hash10; primary_hash21 = primary_hash11; secondary_hash20 = secondary_hash10; secondary_hash21 = secondary_hash11; idx20 = idx10, idx21 = idx11; idx10 = idx00, idx11 = idx01; lookup_stage1(idx10, &primary_hash10, &secondary_hash10, &primary_bkt10, &secondary_bkt10, hash_vals, keys, h); lookup_stage1(idx11, &primary_hash11, &secondary_hash11, &primary_bkt11, &secondary_bkt11, hash_vals, keys, h); lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20, secondary_bkt20, &k_slot20, positions, &extra_hits_mask, key_store, h); lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21, secondary_bkt21, &k_slot21, positions, &extra_hits_mask, key_store, h); lookup_stage3(idx30, k_slot30, keys, data, &hits, h); lookup_stage3(idx31, k_slot31, keys, data, &hits, h); k_slot30 = k_slot20, k_slot31 = k_slot21; idx30 = idx20, idx31 = idx21; primary_bkt20 = primary_bkt10; primary_bkt21 = primary_bkt11; secondary_bkt20 = secondary_bkt10; secondary_bkt21 = secondary_bkt11; primary_hash20 = primary_hash10; primary_hash21 = primary_hash11; secondary_hash20 = secondary_hash10; secondary_hash21 = secondary_hash11; idx20 = idx10, idx21 = idx11; lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20, secondary_bkt20, &k_slot20, positions, &extra_hits_mask, key_store, h); lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21, secondary_bkt21, &k_slot21, positions, &extra_hits_mask, key_store, h); lookup_stage3(idx30, k_slot30, keys, data, &hits, h); lookup_stage3(idx31, k_slot31, keys, data, &hits, h); k_slot30 = k_slot20, k_slot31 = k_slot21; idx30 = idx20, idx31 = idx21; lookup_stage3(idx30, k_slot30, keys, data, &hits, h); lookup_stage3(idx31, k_slot31, keys, data, &hits, h); /* ignore any items we have already found */ extra_hits_mask &= ~hits; if (unlikely(extra_hits_mask)) { /* run a single search for each remaining item */ do { idx = __builtin_ctzl(extra_hits_mask); if (data != NULL) { ret = rte_hash_lookup_with_hash_data(h, keys[idx], hash_vals[idx], &data[idx]); if (ret >= 0) hits |= 1ULL << idx; } else { positions[idx] = rte_hash_lookup_with_hash(h, keys[idx], hash_vals[idx]); if (positions[idx] >= 0) hits |= 1llu << idx; } extra_hits_mask &= ~(1llu << idx); } while (extra_hits_mask); } miss_mask &= ~hits; if (unlikely(miss_mask)) { do { idx = __builtin_ctzl(miss_mask); positions[idx] = -ENOENT; miss_mask &= ~(1llu << idx); } while (miss_mask); } if (hit_mask != NULL) *hit_mask = hits; } int rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys, uint32_t num_keys, int32_t *positions) { RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) || (num_keys > RTE_HASH_LOOKUP_BULK_MAX) || (positions == NULL)), -EINVAL); __rte_hash_lookup_bulk(h, keys, num_keys, positions, NULL, NULL); return 0; } int rte_hash_lookup_bulk_data(const struct rte_hash *h, const void **keys, uint32_t num_keys, uint64_t *hit_mask, void *data[]) { RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) || (num_keys > RTE_HASH_LOOKUP_BULK_MAX) || (hit_mask == NULL)), -EINVAL); int32_t positions[num_keys]; __rte_hash_lookup_bulk(h, keys, num_keys, positions, hit_mask, data); /* Return number of hits */ return __builtin_popcountl(*hit_mask); } int32_t rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next) { uint32_t bucket_idx, idx, position; struct rte_hash_key *next_key; RETURN_IF_TRUE(((h == NULL) || (next == NULL)), -EINVAL); const uint32_t total_entries = h->num_buckets * RTE_HASH_BUCKET_ENTRIES; /* Out of bounds */ if (*next >= total_entries) return -ENOENT; /* Calculate bucket and index of current iterator */ bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES; idx = *next % RTE_HASH_BUCKET_ENTRIES; /* If current position is empty, go to the next one */ while (h->buckets[bucket_idx].signatures[idx].sig == NULL_SIGNATURE) { (*next)++; /* End of table */ if (*next == total_entries) return -ENOENT; bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES; idx = *next % RTE_HASH_BUCKET_ENTRIES; } /* Get position of entry in key table */ position = h->buckets[bucket_idx].key_idx[idx]; next_key = (struct rte_hash_key *) ((char *)h->key_store + position * h->key_entry_size); /* Return key and data */ *key = next_key->key; *data = next_key->pdata; /* Increment iterator */ (*next)++; return (position - 1); } ================================================ FILE: lib/librte_hash/rte_fbk_hash.c ================================================ /** * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_fbk_hash.h" TAILQ_HEAD(rte_fbk_hash_list, rte_tailq_entry); static struct rte_tailq_elem rte_fbk_hash_tailq = { .name = "RTE_FBK_HASH", }; EAL_REGISTER_TAILQ(rte_fbk_hash_tailq) /** * Performs a lookup for an existing hash table, and returns a pointer to * the table if found. * * @param name * Name of the hash table to find * * @return * pointer to hash table structure or NULL on error. */ struct rte_fbk_hash_table * rte_fbk_hash_find_existing(const char *name) { struct rte_fbk_hash_table *h = NULL; struct rte_tailq_entry *te; struct rte_fbk_hash_list *fbk_hash_list; fbk_hash_list = RTE_TAILQ_CAST(rte_fbk_hash_tailq.head, rte_fbk_hash_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, fbk_hash_list, next) { h = (struct rte_fbk_hash_table *) te->data; if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return h; } /** * Create a new hash table for use with four byte keys. * * @param params * Parameters used in creation of hash table. * * @return * Pointer to hash table structure that is used in future hash table * operations, or NULL on error. */ struct rte_fbk_hash_table * rte_fbk_hash_create(const struct rte_fbk_hash_params *params) { struct rte_fbk_hash_table *ht = NULL; struct rte_tailq_entry *te; char hash_name[RTE_FBK_HASH_NAMESIZE]; const uint32_t mem_size = sizeof(*ht) + (sizeof(ht->t[0]) * params->entries); uint32_t i; struct rte_fbk_hash_list *fbk_hash_list; fbk_hash_list = RTE_TAILQ_CAST(rte_fbk_hash_tailq.head, rte_fbk_hash_list); /* Error checking of parameters. */ if ((!rte_is_power_of_2(params->entries)) || (!rte_is_power_of_2(params->entries_per_bucket)) || (params->entries == 0) || (params->entries_per_bucket == 0) || (params->entries_per_bucket > params->entries) || (params->entries > RTE_FBK_HASH_ENTRIES_MAX) || (params->entries_per_bucket > RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX)){ rte_errno = EINVAL; return NULL; } snprintf(hash_name, sizeof(hash_name), "FBK_%s", params->name); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* guarantee there's no existing */ TAILQ_FOREACH(te, fbk_hash_list, next) { ht = (struct rte_fbk_hash_table *) te->data; if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0) break; } if (te != NULL) goto exit; te = rte_zmalloc("FBK_HASH_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, HASH, "Failed to allocate tailq entry\n"); goto exit; } /* Allocate memory for table. */ ht = (struct rte_fbk_hash_table *)rte_zmalloc_socket(hash_name, mem_size, 0, params->socket_id); if (ht == NULL) { RTE_LOG(ERR, HASH, "Failed to allocate fbk hash table\n"); rte_free(te); goto exit; } /* Set up hash table context. */ snprintf(ht->name, sizeof(ht->name), "%s", params->name); ht->entries = params->entries; ht->entries_per_bucket = params->entries_per_bucket; ht->used_entries = 0; ht->bucket_mask = (params->entries / params->entries_per_bucket) - 1; for (ht->bucket_shift = 0, i = 1; (params->entries_per_bucket & i) == 0; ht->bucket_shift++, i <<= 1) ; /* empty loop body */ if (params->hash_func != NULL) { ht->hash_func = params->hash_func; ht->init_val = params->init_val; } else { ht->hash_func = RTE_FBK_HASH_FUNC_DEFAULT; ht->init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT; } te->data = (void *) ht; TAILQ_INSERT_TAIL(fbk_hash_list, te, next); exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return ht; } /** * Free all memory used by a hash table. * * @param ht * Hash table to deallocate. */ void rte_fbk_hash_free(struct rte_fbk_hash_table *ht) { struct rte_tailq_entry *te; struct rte_fbk_hash_list *fbk_hash_list; if (ht == NULL) return; fbk_hash_list = RTE_TAILQ_CAST(rte_fbk_hash_tailq.head, rte_fbk_hash_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find out tailq entry */ TAILQ_FOREACH(te, fbk_hash_list, next) { if (te->data == (void *) ht) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(fbk_hash_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(ht); rte_free(te); } ================================================ FILE: lib/librte_hash/rte_fbk_hash.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_FBK_HASH_H_ #define _RTE_FBK_HASH_H_ /** * @file * * This is a hash table implementation for four byte keys (fbk). * * Note that the return value of the add function should always be checked as, * if a bucket is full, the key is not added even if there is space in other * buckets. This keeps the lookup function very simple and therefore fast. */ #include #include #include #ifdef __cplusplus extern "C" { #endif #include #ifndef RTE_FBK_HASH_FUNC_DEFAULT #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include /** Default four-byte key hash function if none is specified. */ #define RTE_FBK_HASH_FUNC_DEFAULT rte_hash_crc_4byte #else #include #define RTE_FBK_HASH_FUNC_DEFAULT rte_jhash_1word #endif #endif #ifndef RTE_FBK_HASH_INIT_VAL_DEFAULT /** Initialising value used when calculating hash. */ #define RTE_FBK_HASH_INIT_VAL_DEFAULT 0xFFFFFFFF #endif /** The maximum number of entries in the hash table that is supported. */ #define RTE_FBK_HASH_ENTRIES_MAX (1 << 20) /** The maximum number of entries in each bucket that is supported. */ #define RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX 256 /** Maximum size of string for naming the hash. */ #define RTE_FBK_HASH_NAMESIZE 32 /** Type of function that can be used for calculating the hash value. */ typedef uint32_t (*rte_fbk_hash_fn)(uint32_t key, uint32_t init_val); /** Parameters used when creating four-byte key hash table. */ struct rte_fbk_hash_params { const char *name; /**< Name of the hash table. */ uint32_t entries; /**< Total number of entries. */ uint32_t entries_per_bucket; /**< Number of entries in a bucket. */ int socket_id; /**< Socket to allocate memory on. */ rte_fbk_hash_fn hash_func; /**< The hash function. */ uint32_t init_val; /**< For initialising hash function. */ }; /** Individual entry in the four-byte key hash table. */ union rte_fbk_hash_entry { uint64_t whole_entry; /**< For accessing entire entry. */ struct { uint16_t is_entry; /**< Non-zero if entry is active. */ uint16_t value; /**< Value returned by lookup. */ uint32_t key; /**< Key used to find value. */ } entry; /**< For accessing each entry part. */ }; /** The four-byte key hash table structure. */ struct rte_fbk_hash_table { char name[RTE_FBK_HASH_NAMESIZE]; /**< Name of the hash. */ uint32_t entries; /**< Total number of entries. */ uint32_t entries_per_bucket; /**< Number of entries in a bucket. */ uint32_t used_entries; /**< How many entries are used. */ uint32_t bucket_mask; /**< To find which bucket the key is in. */ uint32_t bucket_shift; /**< Convert bucket to table offset. */ rte_fbk_hash_fn hash_func; /**< The hash function. */ uint32_t init_val; /**< For initialising hash function. */ /** A flat table of all buckets. */ union rte_fbk_hash_entry t[0]; }; /** * Find the offset into hash table of the bucket containing a particular key. * * @param ht * Pointer to hash table. * @param key * Key to calculate bucket for. * @return * Offset into hash table. */ static inline uint32_t rte_fbk_hash_get_bucket(const struct rte_fbk_hash_table *ht, uint32_t key) { return (ht->hash_func(key, ht->init_val) & ht->bucket_mask) << ht->bucket_shift; } /** * Add a key to an existing hash table with bucket id. * This operation is not multi-thread safe * and should only be called from one thread. * * @param ht * Hash table to add the key to. * @param key * Key to add to the hash table. * @param value * Value to associate with key. * @param bucket * Bucket to associate with key. * @return * 0 if ok, or negative value on error. */ static inline int rte_fbk_hash_add_key_with_bucket(struct rte_fbk_hash_table *ht, uint32_t key, uint16_t value, uint32_t bucket) { /* * The writing of a new value to the hash table is done as a single * 64bit operation. This should help prevent individual entries being * corrupted due to race conditions, but it's still possible to * overwrite entries that have just been made valid. */ const uint64_t new_entry = ((uint64_t)(key) << 32) | ((uint64_t)(value) << 16) | 1; /* 1 = is_entry bit. */ uint32_t i; for (i = 0; i < ht->entries_per_bucket; i++) { /* Set entry if unused. */ if (! ht->t[bucket + i].entry.is_entry) { ht->t[bucket + i].whole_entry = new_entry; ht->used_entries++; return 0; } /* Change value if key already exists. */ if (ht->t[bucket + i].entry.key == key) { ht->t[bucket + i].entry.value = value; return 0; } } return -ENOSPC; /* No space in bucket. */ } /** * Add a key to an existing hash table. This operation is not multi-thread safe * and should only be called from one thread. * * @param ht * Hash table to add the key to. * @param key * Key to add to the hash table. * @param value * Value to associate with key. * @return * 0 if ok, or negative value on error. */ static inline int rte_fbk_hash_add_key(struct rte_fbk_hash_table *ht, uint32_t key, uint16_t value) { return rte_fbk_hash_add_key_with_bucket(ht, key, value, rte_fbk_hash_get_bucket(ht, key)); } /** * Remove a key with a given bucket id from an existing hash table. * This operation is not multi-thread * safe and should only be called from one thread. * * @param ht * Hash table to remove the key from. * @param key * Key to remove from the hash table. * @param bucket * Bucket id associate with key. * @return * 0 if ok, or negative value on error. */ static inline int rte_fbk_hash_delete_key_with_bucket(struct rte_fbk_hash_table *ht, uint32_t key, uint32_t bucket) { uint32_t last_entry = ht->entries_per_bucket - 1; uint32_t i, j; for (i = 0; i < ht->entries_per_bucket; i++) { if (ht->t[bucket + i].entry.key == key) { /* Find last key in bucket. */ for (j = ht->entries_per_bucket - 1; j > i; j-- ) { if (! ht->t[bucket + j].entry.is_entry) { last_entry = j - 1; } } /* * Move the last key to the deleted key's position, and * delete the last key. lastEntry and i may be same but * it doesn't matter. */ ht->t[bucket + i].whole_entry = ht->t[bucket + last_entry].whole_entry; ht->t[bucket + last_entry].whole_entry = 0; ht->used_entries--; return 0; } } return -ENOENT; /* Key didn't exist. */ } /** * Remove a key from an existing hash table. This operation is not multi-thread * safe and should only be called from one thread. * * @param ht * Hash table to remove the key from. * @param key * Key to remove from the hash table. * @return * 0 if ok, or negative value on error. */ static inline int rte_fbk_hash_delete_key(struct rte_fbk_hash_table *ht, uint32_t key) { return rte_fbk_hash_delete_key_with_bucket(ht, key, rte_fbk_hash_get_bucket(ht, key)); } /** * Find a key in the hash table with a given bucketid. * This operation is multi-thread safe. * * @param ht * Hash table to look in. * @param key * Key to find. * @param bucket * Bucket associate to the key. * @return * The value that was associated with the key, or negative value on error. */ static inline int rte_fbk_hash_lookup_with_bucket(const struct rte_fbk_hash_table *ht, uint32_t key, uint32_t bucket) { union rte_fbk_hash_entry current_entry; uint32_t i; for (i = 0; i < ht->entries_per_bucket; i++) { /* Single read of entry, which should be atomic. */ current_entry.whole_entry = ht->t[bucket + i].whole_entry; if (! current_entry.entry.is_entry) { return -ENOENT; /* Error once we hit an empty field. */ } if (current_entry.entry.key == key) { return current_entry.entry.value; } } return -ENOENT; /* Key didn't exist. */ } /** * Find a key in the hash table. This operation is multi-thread safe. * * @param ht * Hash table to look in. * @param key * Key to find. * @return * The value that was associated with the key, or negative value on error. */ static inline int rte_fbk_hash_lookup(const struct rte_fbk_hash_table *ht, uint32_t key) { return rte_fbk_hash_lookup_with_bucket(ht, key, rte_fbk_hash_get_bucket(ht, key)); } /** * Delete all entries in a hash table. This operation is not multi-thread * safe and should only be called from one thread. * * @param ht * Hash table to delete entries in. */ static inline void rte_fbk_hash_clear_all(struct rte_fbk_hash_table *ht) { memset(ht->t, 0, sizeof(ht->t[0]) * ht->entries); ht->used_entries = 0; } /** * Find what fraction of entries are being used. * * @param ht * Hash table to find how many entries are being used in. * @return * Load factor of the hash table, or negative value on error. */ static inline double rte_fbk_hash_get_load_factor(struct rte_fbk_hash_table *ht) { return (double)ht->used_entries / (double)ht->entries; } /** * Performs a lookup for an existing hash table, and returns a pointer to * the table if found. * * @param name * Name of the hash table to find * * @return * pointer to hash table structure or NULL on error with rte_errno * set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. */ struct rte_fbk_hash_table *rte_fbk_hash_find_existing(const char *name); /** * Create a new hash table for use with four byte keys. * * @param params * Parameters used in creation of hash table. * * @return * Pointer to hash table structure that is used in future hash table * operations, or NULL on error with rte_errno set appropriately. * Possible rte_errno error values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - invalid parameter value passed to function * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_fbk_hash_table * \ rte_fbk_hash_create(const struct rte_fbk_hash_params *params); /** * Free all memory used by a hash table. * Has no effect on hash tables allocated in memory zones * * @param ht * Hash table to deallocate. */ void rte_fbk_hash_free(struct rte_fbk_hash_table *ht); #ifdef __cplusplus } #endif #endif /* _RTE_FBK_HASH_H_ */ ================================================ FILE: lib/librte_hash/rte_hash.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_HASH_H_ #define _RTE_HASH_H_ /** * @file * * RTE Hash Table */ #include #ifdef __cplusplus extern "C" { #endif /** Maximum size of hash table that can be created. */ #define RTE_HASH_ENTRIES_MAX (1 << 30) /** @deprecated Maximum bucket size that can be created. */ #define RTE_HASH_BUCKET_ENTRIES_MAX 4 /** @deprecated Maximum length of key that can be used. */ #define RTE_HASH_KEY_LENGTH_MAX 64 /** Maximum number of characters in hash name.*/ #define RTE_HASH_NAMESIZE 32 /** Maximum number of keys that can be searched for using rte_hash_lookup_bulk. */ #define RTE_HASH_LOOKUP_BULK_MAX 64 #define RTE_HASH_LOOKUP_MULTI_MAX RTE_HASH_LOOKUP_BULK_MAX /** Signature of key that is stored internally. */ typedef uint32_t hash_sig_t; /** Type of function that can be used for calculating the hash value. */ typedef uint32_t (*rte_hash_function)(const void *key, uint32_t key_len, uint32_t init_val); /** * Parameters used when creating the hash table. */ struct rte_hash_parameters { const char *name; /**< Name of the hash. */ uint32_t entries; /**< Total hash table entries. */ uint32_t reserved; /**< Unused field. Should be set to 0 */ uint32_t key_len; /**< Length of hash key. */ rte_hash_function hash_func; /**< Primary Hash function used to calculate hash. */ uint32_t hash_func_init_val; /**< Init value used by hash_func. */ int socket_id; /**< NUMA Socket ID for memory. */ uint8_t extra_flag; /**< Indicate if additional parameters are present. */ }; /** @internal A hash table structure. */ struct rte_hash; /** * Create a new hash table. * * @param params * Parameters used to create and initialise the hash table. * @return * Pointer to hash table structure that is used in future hash table * operations, or NULL on error, with error code set in rte_errno. * Possible rte_errno errors include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - ENOENT - missing entry * - EINVAL - invalid parameter passed to function * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_hash * rte_hash_create(const struct rte_hash_parameters *params); /** * Find an existing hash table object and return a pointer to it. * * @param name * Name of the hash table as passed to rte_hash_create() * @return * Pointer to hash table or NULL if object not found * with rte_errno set appropriately. Possible rte_errno values include: * - ENOENT - value not available for return */ struct rte_hash * rte_hash_find_existing(const char *name); /** * De-allocate all memory used by hash table. * @param h * Hash table to free */ void rte_hash_free(struct rte_hash *h); /** * Reset all hash structure, by zeroing all entries * @param h * Hash table to reset */ void rte_hash_reset(struct rte_hash *h); /** * Add a key-value pair to an existing hash table. * This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to add the key to. * @param key * Key to add to the hash table. * @param data * Data to add to the hash table. * @return * - 0 if added successfully * - -EINVAL if the parameters are invalid. * - -ENOSPC if there is no space in the hash for this key. */ int rte_hash_add_key_data(const struct rte_hash *h, const void *key, void *data); /** * Add a key-value pair with a pre-computed hash value * to an existing hash table. * This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to add the key to. * @param key * Key to add to the hash table. * @param sig * Precomputed hash value for 'key' * @param data * Data to add to the hash table. * @return * - 0 if added successfully * - -EINVAL if the parameters are invalid. * - -ENOSPC if there is no space in the hash for this key. */ int32_t rte_hash_add_key_with_hash_data(const struct rte_hash *h, const void *key, hash_sig_t sig, void *data); /** * Add a key to an existing hash table. This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to add the key to. * @param key * Key to add to the hash table. * @return * - -EINVAL if the parameters are invalid. * - -ENOSPC if there is no space in the hash for this key. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key. */ int32_t rte_hash_add_key(const struct rte_hash *h, const void *key); /** * Add a key to an existing hash table. * This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to add the key to. * @param key * Key to add to the hash table. * @param sig * Precomputed hash value for 'key'. * @return * - -EINVAL if the parameters are invalid. * - -ENOSPC if there is no space in the hash for this key. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key. */ int32_t rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig); /** * Remove a key from an existing hash table. * This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to remove the key from. * @param key * Key to remove from the hash table. * @return * - -EINVAL if the parameters are invalid. * - -ENOENT if the key is not found. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key, and is the same * value that was returned when the key was added. */ int32_t rte_hash_del_key(const struct rte_hash *h, const void *key); /** * Remove a key from an existing hash table. * This operation is not multi-thread safe * and should only be called from one thread. * * @param h * Hash table to remove the key from. * @param key * Key to remove from the hash table. * @param sig * Precomputed hash value for 'key'. * @return * - -EINVAL if the parameters are invalid. * - -ENOENT if the key is not found. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key, and is the same * value that was returned when the key was added. */ int32_t rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig); /** * Find a key-value pair in the hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param key * Key to find. * @param data * Output with pointer to data returned from the hash table. * @return * 0 if successful lookup * - EINVAL if the parameters are invalid. * - ENOENT if the key is not found. */ int rte_hash_lookup_data(const struct rte_hash *h, const void *key, void **data); /** * Find a key-value pair with a pre-computed hash value * to an existing hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param key * Key to find. * @param sig * Precomputed hash value for 'key' * @param data * Output with pointer to data returned from the hash table. * @return * 0 if successful lookup * - EINVAL if the parameters are invalid. * - ENOENT if the key is not found. */ int rte_hash_lookup_with_hash_data(const struct rte_hash *h, const void *key, hash_sig_t sig, void **data); /** * Find a key in the hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param key * Key to find. * @return * - -EINVAL if the parameters are invalid. * - -ENOENT if the key is not found. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key, and is the same * value that was returned when the key was added. */ int32_t rte_hash_lookup(const struct rte_hash *h, const void *key); /** * Find a key in the hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param key * Key to find. * @param sig * Hash value to remove from the hash table. * @return * - -EINVAL if the parameters are invalid. * - -ENOENT if the key is not found. * - A positive value that can be used by the caller as an offset into an * array of user data. This value is unique for this key, and is the same * value that was returned when the key was added. */ int32_t rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig); /** * Calc a hash value by key. * This operation is not multi-thread safe. * * @param h * Hash table to look in. * @param key * Key to find. * @return * - hash value */ hash_sig_t rte_hash_hash(const struct rte_hash *h, const void *key); #define rte_hash_lookup_multi rte_hash_lookup_bulk #define rte_hash_lookup_multi_data rte_hash_lookup_bulk_data /** * Find multiple keys in the hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param keys * A pointer to a list of keys to look for. * @param num_keys * How many keys are in the keys list (less than RTE_HASH_LOOKUP_BULK_MAX). * @param hit_mask * Output containing a bitmask with all successful lookups. * @param data * Output containing array of data returned from all the successful lookups. * @return * -EINVAL if there's an error, otherwise number of successful lookups. */ int rte_hash_lookup_bulk_data(const struct rte_hash *h, const void **keys, uint32_t num_keys, uint64_t *hit_mask, void *data[]); /** * Find multiple keys in the hash table. * This operation is multi-thread safe. * * @param h * Hash table to look in. * @param keys * A pointer to a list of keys to look for. * @param num_keys * How many keys are in the keys list (less than RTE_HASH_LOOKUP_BULK_MAX). * @param positions * Output containing a list of values, corresponding to the list of keys that * can be used by the caller as an offset into an array of user data. These * values are unique for each key, and are the same values that were returned * when each key was added. If a key in the list was not found, then -ENOENT * will be the value. * @return * -EINVAL if there's an error, otherwise 0. */ int rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys, uint32_t num_keys, int32_t *positions); /** * Iterate through the hash table, returning key-value pairs. * * @param h * Hash table to iterate * @param key * Output containing the key where current iterator * was pointing at * @param data * Output containing the data associated with key. * Returns NULL if data was not stored. * @param next * Pointer to iterator. Should be 0 to start iterating the hash table. * Iterator is incremented after each call of this function. * @return * Position where key was stored, if successful. * - -EINVAL if the parameters are invalid. * - -ENOENT if end of the hash table. */ int32_t rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next); #ifdef __cplusplus } #endif #endif /* _RTE_HASH_H_ */ ================================================ FILE: lib/librte_hash/rte_hash_crc.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_HASH_CRC_H_ #define _RTE_HASH_CRC_H_ /** * @file * * RTE CRC Hash */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* Lookup tables for software implementation of CRC32C */ static const uint32_t crc32c_tables[8][256] = {{ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 }, { 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483 }, { 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8 }, { 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842 }, { 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3 }, { 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C }, { 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F }, { 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5 }}; #define CRC32_UPD(crc, n) \ (crc32c_tables[(n)][(crc) & 0xFF] ^ \ crc32c_tables[(n)-1][((crc) >> 8) & 0xFF]) static inline uint32_t crc32c_1word(uint32_t data, uint32_t init_val) { uint32_t crc, term1, term2; crc = init_val; crc ^= data; term1 = CRC32_UPD(crc, 3); term2 = crc >> 16; crc = term1 ^ CRC32_UPD(term2, 1); return crc; } static inline uint32_t crc32c_2words(uint64_t data, uint32_t init_val) { union { uint64_t u64; uint32_t u32[2]; } d; d.u64 = data; uint32_t crc, term1, term2; crc = init_val; crc ^= d.u32[0]; term1 = CRC32_UPD(crc, 7); term2 = crc >> 16; crc = term1 ^ CRC32_UPD(term2, 5); term1 = CRC32_UPD(d.u32[1], 3); term2 = d.u32[1] >> 16; crc ^= term1 ^ CRC32_UPD(term2, 1); return crc; } #if defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_64) static inline uint32_t crc32c_sse42_u32(uint32_t data, uint32_t init_val) { __asm__ volatile( "crc32l %[data], %[init_val];" : [init_val] "+r" (init_val) : [data] "rm" (data)); return init_val; } static inline uint32_t crc32c_sse42_u64_mimic(uint64_t data, uint64_t init_val) { union { uint32_t u32[2]; uint64_t u64; } d; d.u64 = data; init_val = crc32c_sse42_u32(d.u32[0], init_val); init_val = crc32c_sse42_u32(d.u32[1], init_val); return init_val; } #endif #ifdef RTE_ARCH_X86_64 static inline uint32_t crc32c_sse42_u64(uint64_t data, uint64_t init_val) { __asm__ volatile( "crc32q %[data], %[init_val];" : [init_val] "+r" (init_val) : [data] "rm" (data)); return init_val; } #endif #define CRC32_SW (1U << 0) #define CRC32_SSE42 (1U << 1) #define CRC32_x64 (1U << 2) #define CRC32_SSE42_x64 (CRC32_x64|CRC32_SSE42) static uint8_t crc32_alg = CRC32_SW; /** * Allow or disallow use of SSE4.2 instrinsics for CRC32 hash * calculation. * * @param alg * An OR of following flags: * - (CRC32_SW) Don't use SSE4.2 intrinsics * - (CRC32_SSE42) Use SSE4.2 intrinsics if available * - (CRC32_SSE42_x64) Use 64-bit SSE4.2 intrinsic if available (default) * */ static inline void rte_hash_crc_set_alg(uint8_t alg) { switch (alg) { #if defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_64) case CRC32_SSE42_x64: if (! rte_cpu_get_flag_enabled(RTE_CPUFLAG_EM64T)) alg = CRC32_SSE42; case CRC32_SSE42: if (! rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_2)) alg = CRC32_SW; #endif case CRC32_SW: crc32_alg = alg; default: break; } } /* Setting the best available algorithm */ static inline void __attribute__((constructor)) rte_hash_crc_init_alg(void) { rte_hash_crc_set_alg(CRC32_SSE42_x64); } /** * Use single crc32 instruction to perform a hash on a 4 byte value. * Fall back to software crc32 implementation in case SSE4.2 is * not supported * * @param data * Data to perform hash on. * @param init_val * Value to initialise hash generator. * @return * 32bit calculated hash value. */ static inline uint32_t rte_hash_crc_4byte(uint32_t data, uint32_t init_val) { #if defined RTE_ARCH_I686 || defined RTE_ARCH_X86_64 if (likely(crc32_alg & CRC32_SSE42)) return crc32c_sse42_u32(data, init_val); #endif return crc32c_1word(data, init_val); } /** * Use single crc32 instruction to perform a hash on a 8 byte value. * Fall back to software crc32 implementation in case SSE4.2 is * not supported * * @param data * Data to perform hash on. * @param init_val * Value to initialise hash generator. * @return * 32bit calculated hash value. */ static inline uint32_t rte_hash_crc_8byte(uint64_t data, uint32_t init_val) { #ifdef RTE_ARCH_X86_64 if (likely(crc32_alg == CRC32_SSE42_x64)) return crc32c_sse42_u64(data, init_val); #endif #if defined RTE_ARCH_I686 || defined RTE_ARCH_X86_64 if (likely(crc32_alg & CRC32_SSE42)) return crc32c_sse42_u64_mimic(data, init_val); #endif return crc32c_2words(data, init_val); } /** * Calculate CRC32 hash on user-supplied byte array. * * @param data * Data to perform hash on. * @param data_len * How many bytes to use to calculate hash value. * @param init_val * Value to initialise hash generator. * @return * 32bit calculated hash value. */ static inline uint32_t rte_hash_crc(const void *data, uint32_t data_len, uint32_t init_val) { unsigned i; uint64_t temp = 0; uintptr_t pd = (uintptr_t) data; for (i = 0; i < data_len / 8; i++) { init_val = rte_hash_crc_8byte(*(const uint64_t *)pd, init_val); pd += 8; } switch (7 - (data_len & 0x07)) { case 0: temp |= (uint64_t) *((const uint8_t *)pd + 6) << 48; /* Fallthrough */ case 1: temp |= (uint64_t) *((const uint8_t *)pd + 5) << 40; /* Fallthrough */ case 2: temp |= (uint64_t) *((const uint8_t *)pd + 4) << 32; temp |= *(const uint32_t *)pd; init_val = rte_hash_crc_8byte(temp, init_val); break; case 3: init_val = rte_hash_crc_4byte(*(const uint32_t *)pd, init_val); break; case 4: temp |= *((const uint8_t *)pd + 2) << 16; /* Fallthrough */ case 5: temp |= *((const uint8_t *)pd + 1) << 8; /* Fallthrough */ case 6: temp |= *(const uint8_t *)pd; init_val = rte_hash_crc_4byte(temp, init_val); /* Fallthrough */ default: break; } return init_val; } #ifdef __cplusplus } #endif #endif /* _RTE_HASH_CRC_H_ */ ================================================ FILE: lib/librte_hash/rte_jhash.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_JHASH_H #define _RTE_JHASH_H /** * @file * * jhash functions. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include /* jhash.h: Jenkins hash support. * * Copyright (C) 2006 Bob Jenkins (bob_jenkins@burtleburtle.net) * * http://burtleburtle.net/bob/hash/ * * These are the credits from Bob's sources: * * lookup3.c, by Bob Jenkins, May 2006, Public Domain. * * These are functions for producing 32-bit hashes for hash table lookup. * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() * are externally useful functions. Routines to test the hash are included * if SELF_TEST is defined. You can use this free for any purpose. It's in * the public domain. It has no warranty. * * $FreeBSD$ */ #define rot(x, k) (((x) << (k)) | ((x) >> (32-(k)))) /** @internal Internal function. NOTE: Arguments are modified. */ #define __rte_jhash_mix(a, b, c) do { \ a -= c; a ^= rot(c, 4); c += b; \ b -= a; b ^= rot(a, 6); a += c; \ c -= b; c ^= rot(b, 8); b += a; \ a -= c; a ^= rot(c, 16); c += b; \ b -= a; b ^= rot(a, 19); a += c; \ c -= b; c ^= rot(b, 4); b += a; \ } while (0) #define __rte_jhash_final(a, b, c) do { \ c ^= b; c -= rot(b, 14); \ a ^= c; a -= rot(c, 11); \ b ^= a; b -= rot(a, 25); \ c ^= b; c -= rot(b, 16); \ a ^= c; a -= rot(c, 4); \ b ^= a; b -= rot(a, 14); \ c ^= b; c -= rot(b, 24); \ } while (0) /** The golden ratio: an arbitrary value. */ #define RTE_JHASH_GOLDEN_RATIO 0xdeadbeef #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define BIT_SHIFT(x, y, k) (((x) >> (k)) | ((uint64_t)(y) << (32-(k)))) #else #define BIT_SHIFT(x, y, k) (((uint64_t)(x) << (k)) | ((y) >> (32-(k)))) #endif #define LOWER8b_MASK rte_le_to_cpu_32(0xff) #define LOWER16b_MASK rte_le_to_cpu_32(0xffff) #define LOWER24b_MASK rte_le_to_cpu_32(0xffffff) static inline void __rte_jhash_2hashes(const void *key, uint32_t length, uint32_t *pc, uint32_t *pb, unsigned check_align) { uint32_t a, b, c; /* Set up the internal state */ a = b = c = RTE_JHASH_GOLDEN_RATIO + ((uint32_t)length) + *pc; c += *pb; /* * Check key alignment. For x86 architecture, first case is always optimal * If check_align is not set, first case will be used */ #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_X32) const uint32_t *k = key; const uint32_t s = 0; #else const uint32_t *k = (uint32_t *)((uintptr_t)key & (uintptr_t)~3); const uint32_t s = ((uintptr_t)key & 3) * CHAR_BIT; #endif if (!check_align || s == 0) { while (length > 12) { a += k[0]; b += k[1]; c += k[2]; __rte_jhash_mix(a, b, c); k += 3; length -= 12; } switch (length) { case 12: c += k[2]; b += k[1]; a += k[0]; break; case 11: c += k[2] & LOWER24b_MASK; b += k[1]; a += k[0]; break; case 10: c += k[2] & LOWER16b_MASK; b += k[1]; a += k[0]; break; case 9: c += k[2] & LOWER8b_MASK; b += k[1]; a += k[0]; break; case 8: b += k[1]; a += k[0]; break; case 7: b += k[1] & LOWER24b_MASK; a += k[0]; break; case 6: b += k[1] & LOWER16b_MASK; a += k[0]; break; case 5: b += k[1] & LOWER8b_MASK; a += k[0]; break; case 4: a += k[0]; break; case 3: a += k[0] & LOWER24b_MASK; break; case 2: a += k[0] & LOWER16b_MASK; break; case 1: a += k[0] & LOWER8b_MASK; break; /* zero length strings require no mixing */ case 0: *pc = c; *pb = b; return; }; } else { /* all but the last block: affect some 32 bits of (a, b, c) */ while (length > 12) { a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); c += BIT_SHIFT(k[2], k[3], s); __rte_jhash_mix(a, b, c); k += 3; length -= 12; } /* last block: affect all 32 bits of (c) */ switch (length) { case 12: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); c += BIT_SHIFT(k[2], k[3], s); break; case 11: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); c += BIT_SHIFT(k[2], k[3], s) & LOWER24b_MASK; break; case 10: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); c += BIT_SHIFT(k[2], k[3], s) & LOWER16b_MASK; break; case 9: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); c += BIT_SHIFT(k[2], k[3], s) & LOWER8b_MASK; break; case 8: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s); break; case 7: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s) & LOWER24b_MASK; break; case 6: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s) & LOWER16b_MASK; break; case 5: a += BIT_SHIFT(k[0], k[1], s); b += BIT_SHIFT(k[1], k[2], s) & LOWER8b_MASK; break; case 4: a += BIT_SHIFT(k[0], k[1], s); break; case 3: a += BIT_SHIFT(k[0], k[1], s) & LOWER24b_MASK; break; case 2: a += BIT_SHIFT(k[0], k[1], s) & LOWER16b_MASK; break; case 1: a += BIT_SHIFT(k[0], k[1], s) & LOWER8b_MASK; break; /* zero length strings require no mixing */ case 0: *pc = c; *pb = b; return; } } __rte_jhash_final(a, b, c); *pc = c; *pb = b; } /** * Same as rte_jhash, but takes two seeds and return two uint32_ts. * pc and pb must be non-null, and *pc and *pb must both be initialized * with seeds. If you pass in (*pb)=0, the output (*pc) will be * the same as the return value from rte_jhash. * * @param key * Key to calculate hash of. * @param length * Length of key in bytes. * @param pc * IN: seed OUT: primary hash value. * @param pb * IN: second seed OUT: secondary hash value. */ static inline void rte_jhash_2hashes(const void *key, uint32_t length, uint32_t *pc, uint32_t *pb) { __rte_jhash_2hashes(key, length, pc, pb, 1); } /** * Same as rte_jhash2, but takes two seeds and return two uint32_ts. * pc and pb must be non-null, and *pc and *pb must both be initialized * with seeds. If you pass in (*pb)=0, the output (*pc) will be * the same as the return value from rte_jhash2. * * @param k * Key to calculate hash of. * @param length * Length of key in units of 4 bytes. * @param pc * IN: seed OUT: primary hash value. * @param pb * IN: second seed OUT: secondary hash value. */ static inline void rte_jhash_32b_2hashes(const uint32_t *k, uint32_t length, uint32_t *pc, uint32_t *pb) { __rte_jhash_2hashes((const void *) k, (length << 2), pc, pb, 0); } /** * The most generic version, hashes an arbitrary sequence * of bytes. No alignment or length assumptions are made about * the input key. * * @param key * Key to calculate hash of. * @param length * Length of key in bytes. * @param initval * Initialising value of hash. * @return * Calculated hash value. */ static inline uint32_t rte_jhash(const void *key, uint32_t length, uint32_t initval) { uint32_t initval2 = 0; rte_jhash_2hashes(key, length, &initval, &initval2); return initval; } /** * A special optimized version that handles 1 or more of uint32_ts. * The length parameter here is the number of uint32_ts in the key. * * @param k * Key to calculate hash of. * @param length * Length of key in units of 4 bytes. * @param initval * Initialising value of hash. * @return * Calculated hash value. */ static inline uint32_t rte_jhash_32b(const uint32_t *k, uint32_t length, uint32_t initval) { uint32_t initval2 = 0; rte_jhash_32b_2hashes(k, length, &initval, &initval2); return initval; } static inline uint32_t __attribute__ ((deprecated)) rte_jhash2(const uint32_t *k, uint32_t length, uint32_t initval) { uint32_t initval2 = 0; rte_jhash_32b_2hashes(k, length, &initval, &initval2); return initval; } static inline uint32_t __rte_jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval) { a += RTE_JHASH_GOLDEN_RATIO + initval; b += RTE_JHASH_GOLDEN_RATIO + initval; c += RTE_JHASH_GOLDEN_RATIO + initval; __rte_jhash_final(a, b, c); return c; } /** * A special ultra-optimized versions that knows it is hashing exactly * 3 words. * * @param a * First word to calculate hash of. * @param b * Second word to calculate hash of. * @param c * Third word to calculate hash of. * @param initval * Initialising value of hash. * @return * Calculated hash value. */ static inline uint32_t rte_jhash_3words(uint32_t a, uint32_t b, uint32_t c, uint32_t initval) { return __rte_jhash_3words(a + 12, b + 12, c + 12, initval); } /** * A special ultra-optimized versions that knows it is hashing exactly * 2 words. * * @param a * First word to calculate hash of. * @param b * Second word to calculate hash of. * @param initval * Initialising value of hash. * @return * Calculated hash value. */ static inline uint32_t rte_jhash_2words(uint32_t a, uint32_t b, uint32_t initval) { return __rte_jhash_3words(a + 8, b + 8, 8, initval); } /** * A special ultra-optimized versions that knows it is hashing exactly * 1 word. * * @param a * Word to calculate hash of. * @param initval * Initialising value of hash. * @return * Calculated hash value. */ static inline uint32_t rte_jhash_1word(uint32_t a, uint32_t initval) { return __rte_jhash_3words(a + 4, 4, 4, initval); } #ifdef __cplusplus } #endif #endif /* _RTE_JHASH_H */ ================================================ FILE: lib/librte_hash/rte_thash.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Vladimir Medvedkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_THASH_H #define _RTE_THASH_H /** * @file * * toeplitz hash functions. */ #ifdef __cplusplus extern "C" { #endif /** * Software implementation of the Toeplitz hash function used by RSS. * Can be used either for packet distribution on single queue NIC * or for simulating of RSS computation on specific NIC (for example * after GRE header decapsulating) */ #include #include #include #ifdef __SSE3__ #include #endif #ifdef __SSE3__ /* Byte swap mask used for converting IPv6 address * 4-byte chunks to CPU byte order */ static const __m128i rte_thash_ipv6_bswap_mask = { 0x0405060700010203ULL, 0x0C0D0E0F08090A0BULL}; #endif /** * length in dwords of input tuple to * calculate hash of ipv4 header only */ #define RTE_THASH_V4_L3_LEN ((sizeof(struct rte_ipv4_tuple) - \ sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) / 4) /** * length in dwords of input tuple to * calculate hash of ipv4 header + * transport header */ #define RTE_THASH_V4_L4_LEN ((sizeof(struct rte_ipv4_tuple)) / 4) /** * length in dwords of input tuple to * calculate hash of ipv6 header only */ #define RTE_THASH_V6_L3_LEN ((sizeof(struct rte_ipv6_tuple) - \ sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) / 4) /** * length in dwords of input tuple to * calculate hash of ipv6 header + * transport header */ #define RTE_THASH_V6_L4_LEN ((sizeof(struct rte_ipv6_tuple)) / 4) /** * IPv4 tuple * addresses and ports/sctp_tag have to be CPU byte order */ struct rte_ipv4_tuple { uint32_t src_addr; uint32_t dst_addr; union { struct { uint16_t dport; uint16_t sport; }; uint32_t sctp_tag; }; }; /** * IPv6 tuple * Addresses have to be filled by rte_thash_load_v6_addr() * ports/sctp_tag have to be CPU byte order */ struct rte_ipv6_tuple { uint8_t src_addr[16]; uint8_t dst_addr[16]; union { struct { uint16_t dport; uint16_t sport; }; uint32_t sctp_tag; }; }; union rte_thash_tuple { struct rte_ipv4_tuple v4; struct rte_ipv6_tuple v6; #ifdef __SSE3__ } __attribute__((aligned(XMM_SIZE))); #else }; #endif /** * Prepare special converted key to use with rte_softrss_be() * @param orig * pointer to original RSS key * @param targ * pointer to target RSS key * @param len * RSS key length */ static inline void rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) { int i; for (i = 0; i < (len >> 2); i++) targ[i] = rte_be_to_cpu_32(orig[i]); } /** * Prepare and load IPv6 addresses (src and dst) * into target tuple * @param orig * Pointer to ipv6 header of the original packet * @param targ * Pointer to rte_ipv6_tuple structure */ static inline void rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union rte_thash_tuple *targ) { #ifdef __SSE3__ __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr); *(__m128i *)targ->v6.src_addr = _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask); ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr); *(__m128i *)targ->v6.dst_addr = _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask); #else int i; for (i = 0; i < 4; i++) { *((uint32_t *)targ->v6.src_addr + i) = rte_be_to_cpu_32(*((const uint32_t *)orig->src_addr + i)); *((uint32_t *)targ->v6.dst_addr + i) = rte_be_to_cpu_32(*((const uint32_t *)orig->dst_addr + i)); } #endif } /** * Generic implementation. Can be used with original rss_key * @param input_tuple * Pointer to input tuple * @param input_len * Length of input_tuple in 4-bytes chunks * @param rss_key * Pointer to RSS hash key. * @return * Calculated hash value. */ static inline uint32_t rte_softrss(uint32_t *input_tuple, uint32_t input_len, const uint8_t *rss_key) { uint32_t i, j, ret = 0; for (j = 0; j < input_len; j++) { for (i = 0; i < 32; i++) { if (input_tuple[j] & (1 << (31 - i))) { ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i | (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >> (32 - i)); } } } return ret; } /** * Optimized implementation. * If you want the calculated hash value matches NIC RSS value * you have to use special converted key with rte_convert_rss_key() fn. * @param input_tuple * Pointer to input tuple * @param input_len * Length of input_tuple in 4-bytes chunks * @param *rss_key * Pointer to RSS hash key. * @return * Calculated hash value. */ static inline uint32_t rte_softrss_be(uint32_t *input_tuple, uint32_t input_len, const uint8_t *rss_key) { uint32_t i, j, ret = 0; for (j = 0; j < input_len; j++) { for (i = 0; i < 32; i++) { if (input_tuple[j] & (1 << (31 - i))) { ret ^= ((const uint32_t *)rss_key)[j] << i | (uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i)); } } } return ret; } #ifdef __cplusplus } #endif #endif /* _RTE_THASH_H */ ================================================ FILE: lib/librte_ip_frag/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_ip_frag.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_ipfrag_version.map LIBABIVER := 1 #source files SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += rte_ipv4_fragmentation.c SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += rte_ipv6_fragmentation.c SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += rte_ipv4_reassembly.c SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += rte_ipv6_reassembly.c SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += rte_ip_frag_common.c SRCS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += ip_frag_internal.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_IP_FRAG)-include += rte_ip_frag.h # this library depends on rte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += lib/librte_mempool lib/librte_ether include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_ip_frag/ip_frag_common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _IP_FRAG_COMMON_H_ #define _IP_FRAG_COMMON_H_ #include "rte_ip_frag.h" /* logging macros. */ #ifdef RTE_LIBRTE_IP_FRAG_DEBUG #define IP_FRAG_LOG(lvl, fmt, args...) RTE_LOG(lvl, USER1, fmt, ##args) #define IP_FRAG_ASSERT(exp) \ if (!(exp)) { \ rte_panic("function %s, line%d\tassert \"" #exp "\" failed\n", \ __func__, __LINE__); \ } #else #define IP_FRAG_LOG(lvl, fmt, args...) do {} while(0) #define IP_FRAG_ASSERT(exp) do {} while (0) #endif /* IP_FRAG_DEBUG */ #define IPV4_KEYLEN 1 #define IPV6_KEYLEN 4 /* helper macros */ #define IP_FRAG_MBUF2DR(dr, mb) ((dr)->row[(dr)->cnt++] = (mb)) #define IPv6_KEY_BYTES(key) \ (key)[0], (key)[1], (key)[2], (key)[3] #define IPv6_KEY_BYTES_FMT \ "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 /* internal functions declarations */ struct rte_mbuf * ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint16_t ofs, uint16_t len, uint16_t more_frags); struct ip_frag_pkt * ip_frag_find(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, const struct ip_frag_key *key, uint64_t tms); struct ip_frag_pkt * ip_frag_lookup(struct rte_ip_frag_tbl *tbl, const struct ip_frag_key *key, uint64_t tms, struct ip_frag_pkt **free, struct ip_frag_pkt **stale); /* these functions need to be declared here as ip_frag_process relies on them */ struct rte_mbuf * ipv4_frag_reassemble(const struct ip_frag_pkt *fp); struct rte_mbuf * ipv6_frag_reassemble(const struct ip_frag_pkt *fp); /* * misc frag key functions */ /* check if key is empty */ static inline int ip_frag_key_is_empty(const struct ip_frag_key * key) { uint32_t i; for (i = 0; i < RTE_MIN(key->key_len, RTE_DIM(key->src_dst)); i++) if (key->src_dst[i] != 0) return 0; return 1; } /* empty the key */ static inline void ip_frag_key_invalidate(struct ip_frag_key * key) { uint32_t i; for (i = 0; i < key->key_len; i++) key->src_dst[i] = 0; } /* compare two keys */ static inline int ip_frag_key_cmp(const struct ip_frag_key * k1, const struct ip_frag_key * k2) { uint32_t i, val; val = k1->id ^ k2->id; for (i = 0; i < k1->key_len; i++) val |= k1->src_dst[i] ^ k2->src_dst[i]; return val; } /* * misc fragment functions */ /* put fragment on death row */ static inline void ip_frag_free(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr) { uint32_t i, k; k = dr->cnt; for (i = 0; i != fp->last_idx; i++) { if (fp->frags[i].mb != NULL) { dr->row[k++] = fp->frags[i].mb; fp->frags[i].mb = NULL; } } fp->last_idx = 0; dr->cnt = k; } /* if key is empty, mark key as in use */ static inline void ip_frag_inuse(struct rte_ip_frag_tbl *tbl, const struct ip_frag_pkt *fp) { if (ip_frag_key_is_empty(&fp->key)) { TAILQ_REMOVE(&tbl->lru, fp, lru); tbl->use_entries--; } } /* reset the fragment */ static inline void ip_frag_reset(struct ip_frag_pkt *fp, uint64_t tms) { static const struct ip_frag zero_frag = { .ofs = 0, .len = 0, .mb = NULL, }; fp->start = tms; fp->total_size = UINT32_MAX; fp->frag_size = 0; fp->last_idx = IP_MIN_FRAG_NUM; fp->frags[IP_LAST_FRAG_IDX] = zero_frag; fp->frags[IP_FIRST_FRAG_IDX] = zero_frag; } /* chain two mbufs */ static inline void ip_frag_chain(struct rte_mbuf *mn, struct rte_mbuf *mp) { struct rte_mbuf *ms; /* adjust start of the last fragment data. */ rte_pktmbuf_adj(mp, (uint16_t)(mp->l2_len + mp->l3_len)); /* chain two fragments. */ ms = rte_pktmbuf_lastseg(mn); ms->next = mp; /* accumulate number of segments and total length. */ mn->nb_segs = (uint8_t)(mn->nb_segs + mp->nb_segs); mn->pkt_len += mp->pkt_len; /* reset pkt_len and nb_segs for chained fragment. */ mp->pkt_len = mp->data_len; mp->nb_segs = 1; } #endif /* _IP_FRAG_COMMON_H_ */ ================================================ FILE: lib/librte_ip_frag/ip_frag_internal.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 #include #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ #include "ip_frag_common.h" #define PRIME_VALUE 0xeaad8405 #define IP_FRAG_TBL_POS(tbl, sig) \ ((tbl)->pkt + ((sig) & (tbl)->entry_mask)) #ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT #define IP_FRAG_TBL_STAT_UPDATE(s, f, v) ((s)->f += (v)) #else #define IP_FRAG_TBL_STAT_UPDATE(s, f, v) do {} while (0) #endif /* IP_FRAG_TBL_STAT */ /* local frag table helper functions */ static inline void ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct ip_frag_pkt *fp) { ip_frag_free(fp, dr); ip_frag_key_invalidate(&fp->key); TAILQ_REMOVE(&tbl->lru, fp, lru); tbl->use_entries--; IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1); } static inline void ip_frag_tbl_add(struct rte_ip_frag_tbl *tbl, struct ip_frag_pkt *fp, const struct ip_frag_key *key, uint64_t tms) { fp->key = key[0]; ip_frag_reset(fp, tms); TAILQ_INSERT_TAIL(&tbl->lru, fp, lru); tbl->use_entries++; IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, add_num, 1); } static inline void ip_frag_tbl_reuse(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct ip_frag_pkt *fp, uint64_t tms) { ip_frag_free(fp, dr); ip_frag_reset(fp, tms); TAILQ_REMOVE(&tbl->lru, fp, lru); TAILQ_INSERT_TAIL(&tbl->lru, fp, lru); IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, reuse_num, 1); } static inline void ipv4_frag_hash(const struct ip_frag_key *key, uint32_t *v1, uint32_t *v2) { uint32_t v; const uint32_t *p; p = (const uint32_t *)&key->src_dst; #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 v = rte_hash_crc_4byte(p[0], PRIME_VALUE); v = rte_hash_crc_4byte(p[1], v); v = rte_hash_crc_4byte(key->id, v); #else v = rte_jhash_3words(p[0], p[1], key->id, PRIME_VALUE); #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ *v1 = v; *v2 = (v << 7) + (v >> 14); } static inline void ipv6_frag_hash(const struct ip_frag_key *key, uint32_t *v1, uint32_t *v2) { uint32_t v; const uint32_t *p; p = (const uint32_t *) &key->src_dst; #ifdef RTE_MACHINE_CPUFLAG_SSE4_2 v = rte_hash_crc_4byte(p[0], PRIME_VALUE); v = rte_hash_crc_4byte(p[1], v); v = rte_hash_crc_4byte(p[2], v); v = rte_hash_crc_4byte(p[3], v); v = rte_hash_crc_4byte(p[4], v); v = rte_hash_crc_4byte(p[5], v); v = rte_hash_crc_4byte(p[6], v); v = rte_hash_crc_4byte(p[7], v); v = rte_hash_crc_4byte(key->id, v); #else v = rte_jhash_3words(p[0], p[1], p[2], PRIME_VALUE); v = rte_jhash_3words(p[3], p[4], p[5], v); v = rte_jhash_3words(p[6], p[7], key->id, v); #endif /* RTE_MACHINE_CPUFLAG_SSE4_2 */ *v1 = v; *v2 = (v << 7) + (v >> 14); } struct rte_mbuf * ip_frag_process(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint16_t ofs, uint16_t len, uint16_t more_frags) { uint32_t idx; fp->frag_size += len; /* this is the first fragment. */ if (ofs == 0) { idx = (fp->frags[IP_FIRST_FRAG_IDX].mb == NULL) ? IP_FIRST_FRAG_IDX : UINT32_MAX; /* this is the last fragment. */ } else if (more_frags == 0) { fp->total_size = ofs + len; idx = (fp->frags[IP_LAST_FRAG_IDX].mb == NULL) ? IP_LAST_FRAG_IDX : UINT32_MAX; /* this is the intermediate fragment. */ } else if ((idx = fp->last_idx) < sizeof (fp->frags) / sizeof (fp->frags[0])) { fp->last_idx++; } /* * errorneous packet: either exceeed max allowed number of fragments, * or duplicate first/last fragment encountered. */ if (idx >= sizeof (fp->frags) / sizeof (fp->frags[0])) { /* report an error. */ if (fp->key.key_len == IPV4_KEYLEN) IP_FRAG_LOG(DEBUG, "%s:%d invalid fragmented packet:\n" "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, " "total_size: %u, frag_size: %u, last_idx: %u\n" "first fragment: ofs: %u, len: %u\n" "last fragment: ofs: %u, len: %u\n\n", __func__, __LINE__, fp, fp->key.src_dst[0], fp->key.id, fp->total_size, fp->frag_size, fp->last_idx, fp->frags[IP_FIRST_FRAG_IDX].ofs, fp->frags[IP_FIRST_FRAG_IDX].len, fp->frags[IP_LAST_FRAG_IDX].ofs, fp->frags[IP_LAST_FRAG_IDX].len); else IP_FRAG_LOG(DEBUG, "%s:%d invalid fragmented packet:\n" "ipv4_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, " "total_size: %u, frag_size: %u, last_idx: %u\n" "first fragment: ofs: %u, len: %u\n" "last fragment: ofs: %u, len: %u\n\n", __func__, __LINE__, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->total_size, fp->frag_size, fp->last_idx, fp->frags[IP_FIRST_FRAG_IDX].ofs, fp->frags[IP_FIRST_FRAG_IDX].len, fp->frags[IP_LAST_FRAG_IDX].ofs, fp->frags[IP_LAST_FRAG_IDX].len); /* free all fragments, invalidate the entry. */ ip_frag_free(fp, dr); ip_frag_key_invalidate(&fp->key); IP_FRAG_MBUF2DR(dr, mb); return NULL; } fp->frags[idx].ofs = ofs; fp->frags[idx].len = len; fp->frags[idx].mb = mb; mb = NULL; /* not all fragments are collected yet. */ if (likely (fp->frag_size < fp->total_size)) { return mb; /* if we collected all fragments, then try to reassemble. */ } else if (fp->frag_size == fp->total_size && fp->frags[IP_FIRST_FRAG_IDX].mb != NULL) { if (fp->key.key_len == IPV4_KEYLEN) mb = ipv4_frag_reassemble(fp); else mb = ipv6_frag_reassemble(fp); } /* errorenous set of fragments. */ if (mb == NULL) { /* report an error. */ if (fp->key.key_len == IPV4_KEYLEN) IP_FRAG_LOG(DEBUG, "%s:%d invalid fragmented packet:\n" "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, " "total_size: %u, frag_size: %u, last_idx: %u\n" "first fragment: ofs: %u, len: %u\n" "last fragment: ofs: %u, len: %u\n\n", __func__, __LINE__, fp, fp->key.src_dst[0], fp->key.id, fp->total_size, fp->frag_size, fp->last_idx, fp->frags[IP_FIRST_FRAG_IDX].ofs, fp->frags[IP_FIRST_FRAG_IDX].len, fp->frags[IP_LAST_FRAG_IDX].ofs, fp->frags[IP_LAST_FRAG_IDX].len); else IP_FRAG_LOG(DEBUG, "%s:%d invalid fragmented packet:\n" "ipv4_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, " "total_size: %u, frag_size: %u, last_idx: %u\n" "first fragment: ofs: %u, len: %u\n" "last fragment: ofs: %u, len: %u\n\n", __func__, __LINE__, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->total_size, fp->frag_size, fp->last_idx, fp->frags[IP_FIRST_FRAG_IDX].ofs, fp->frags[IP_FIRST_FRAG_IDX].len, fp->frags[IP_LAST_FRAG_IDX].ofs, fp->frags[IP_LAST_FRAG_IDX].len); /* free associated resources. */ ip_frag_free(fp, dr); } /* we are done with that entry, invalidate it. */ ip_frag_key_invalidate(&fp->key); return mb; } /* * Find an entry in the table for the corresponding fragment. * If such entry is not present, then allocate a new one. * If the entry is stale, then free and reuse it. */ struct ip_frag_pkt * ip_frag_find(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, const struct ip_frag_key *key, uint64_t tms) { struct ip_frag_pkt *pkt, *free, *stale, *lru; uint64_t max_cycles; /* * Actually the two line below are totally redundant. * they are here, just to make gcc 4.6 happy. */ free = NULL; stale = NULL; max_cycles = tbl->max_cycles; IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, find_num, 1); if ((pkt = ip_frag_lookup(tbl, key, tms, &free, &stale)) == NULL) { /*timed-out entry, free and invalidate it*/ if (stale != NULL) { ip_frag_tbl_del(tbl, dr, stale); free = stale; /* * we found a free entry, check if we can use it. * If we run out of free entries in the table, then * check if we have a timed out entry to delete. */ } else if (free != NULL && tbl->max_entries <= tbl->use_entries) { lru = TAILQ_FIRST(&tbl->lru); if (max_cycles + lru->start < tms) { ip_frag_tbl_del(tbl, dr, lru); } else { free = NULL; IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, fail_nospace, 1); } } /* found a free entry to reuse. */ if (free != NULL) { ip_frag_tbl_add(tbl, free, key, tms); pkt = free; } /* * we found the flow, but it is already timed out, * so free associated resources, reposition it in the LRU list, * and reuse it. */ } else if (max_cycles + pkt->start < tms) { ip_frag_tbl_reuse(tbl, dr, pkt, tms); } IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, fail_total, (pkt == NULL)); tbl->last = pkt; return pkt; } struct ip_frag_pkt * ip_frag_lookup(struct rte_ip_frag_tbl *tbl, const struct ip_frag_key *key, uint64_t tms, struct ip_frag_pkt **free, struct ip_frag_pkt **stale) { struct ip_frag_pkt *p1, *p2; struct ip_frag_pkt *empty, *old; uint64_t max_cycles; uint32_t i, assoc, sig1, sig2; empty = NULL; old = NULL; max_cycles = tbl->max_cycles; assoc = tbl->bucket_entries; if (tbl->last != NULL && ip_frag_key_cmp(key, &tbl->last->key) == 0) return tbl->last; /* different hashing methods for IPv4 and IPv6 */ if (key->key_len == IPV4_KEYLEN) ipv4_frag_hash(key, &sig1, &sig2); else ipv6_frag_hash(key, &sig1, &sig2); p1 = IP_FRAG_TBL_POS(tbl, sig1); p2 = IP_FRAG_TBL_POS(tbl, sig2); for (i = 0; i != assoc; i++) { if (p1->key.key_len == IPV4_KEYLEN) IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt line0: %p, index: %u from %u\n" "key: <%" PRIx64 ", %#x>, start: %" PRIu64 "\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, p1, i, assoc, p1[i].key.src_dst[0], p1[i].key.id, p1[i].start); else IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt line0: %p, index: %u from %u\n" "key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 "\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, p1, i, assoc, IPv6_KEY_BYTES(p1[i].key.src_dst), p1[i].key.id, p1[i].start); if (ip_frag_key_cmp(key, &p1[i].key) == 0) return (p1 + i); else if (ip_frag_key_is_empty(&p1[i].key)) empty = (empty == NULL) ? (p1 + i) : empty; else if (max_cycles + p1[i].start < tms) old = (old == NULL) ? (p1 + i) : old; if (p2->key.key_len == IPV4_KEYLEN) IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt line1: %p, index: %u from %u\n" "key: <%" PRIx64 ", %#x>, start: %" PRIu64 "\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, p2, i, assoc, p2[i].key.src_dst[0], p2[i].key.id, p2[i].start); else IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt line1: %p, index: %u from %u\n" "key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 "\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, p2, i, assoc, IPv6_KEY_BYTES(p2[i].key.src_dst), p2[i].key.id, p2[i].start); if (ip_frag_key_cmp(key, &p2[i].key) == 0) return (p2 + i); else if (ip_frag_key_is_empty(&p2[i].key)) empty = (empty == NULL) ?( p2 + i) : empty; else if (max_cycles + p2[i].start < tms) old = (old == NULL) ? (p2 + i) : old; } *free = empty; *stale = old; return NULL; } ================================================ FILE: lib/librte_ip_frag/rte_ip_frag.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_IP_FRAG_H_ #define _RTE_IP_FRAG_H_ /** * @file * RTE IP Fragmentation and Reassembly * * Implementation of IP packet fragmentation and reassembly. */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include struct rte_mbuf; enum { IP_LAST_FRAG_IDX, /**< index of last fragment */ IP_FIRST_FRAG_IDX, /**< index of first fragment */ IP_MIN_FRAG_NUM, /**< minimum number of fragments */ IP_MAX_FRAG_NUM = RTE_LIBRTE_IP_FRAG_MAX_FRAG, /**< maximum number of fragments per packet */ }; /** @internal fragmented mbuf */ struct ip_frag { uint16_t ofs; /**< offset into the packet */ uint16_t len; /**< length of fragment */ struct rte_mbuf *mb; /**< fragment mbuf */ }; /** @internal to uniquely indetify fragmented datagram. */ struct ip_frag_key { uint64_t src_dst[4]; /**< src address, first 8 bytes used for IPv4 */ uint32_t id; /**< dst address */ uint32_t key_len; /**< src/dst key length */ }; /* * @internal Fragmented packet to reassemble. * First two entries in the frags[] array are for the last and first fragments. */ struct ip_frag_pkt { TAILQ_ENTRY(ip_frag_pkt) lru; /**< LRU list */ struct ip_frag_key key; /**< fragmentation key */ uint64_t start; /**< creation timestamp */ uint32_t total_size; /**< expected reassembled size */ uint32_t frag_size; /**< size of fragments received */ uint32_t last_idx; /**< index of next entry to fill */ struct ip_frag frags[IP_MAX_FRAG_NUM]; /**< fragments */ } __rte_cache_aligned; #define IP_FRAG_DEATH_ROW_LEN 32 /**< death row size (in packets) */ /** mbuf death row (packets to be freed) */ struct rte_ip_frag_death_row { uint32_t cnt; /**< number of mbufs currently on death row */ struct rte_mbuf *row[IP_FRAG_DEATH_ROW_LEN * (IP_MAX_FRAG_NUM + 1)]; /**< mbufs to be freed */ }; TAILQ_HEAD(ip_pkt_list, ip_frag_pkt); /**< @internal fragments tailq */ /** fragmentation table statistics */ struct ip_frag_tbl_stat { uint64_t find_num; /**< total # of find/insert attempts. */ uint64_t add_num; /**< # of add ops. */ uint64_t del_num; /**< # of del ops. */ uint64_t reuse_num; /**< # of reuse (del/add) ops. */ uint64_t fail_total; /**< total # of add failures. */ uint64_t fail_nospace; /**< # of 'no space' add failures. */ } __rte_cache_aligned; /** fragmentation table */ struct rte_ip_frag_tbl { uint64_t max_cycles; /**< ttl for table entries. */ uint32_t entry_mask; /**< hash value mask. */ uint32_t max_entries; /**< max entries allowed. */ uint32_t use_entries; /**< entries in use. */ uint32_t bucket_entries; /**< hash assocaitivity. */ uint32_t nb_entries; /**< total size of the table. */ uint32_t nb_buckets; /**< num of associativity lines. */ struct ip_frag_pkt *last; /**< last used entry. */ struct ip_pkt_list lru; /**< LRU list for table entries. */ struct ip_frag_tbl_stat stat; /**< statistics counters. */ struct ip_frag_pkt pkt[0]; /**< hash table. */ }; /** IPv6 fragment extension header */ struct ipv6_extension_fragment { uint8_t next_header; /**< Next header type */ uint8_t reserved1; /**< Reserved */ union { struct { uint16_t frag_offset:13; /**< Offset from the start of the packet */ uint16_t reserved2:2; /**< Reserved */ uint16_t more_frags:1; /**< 1 if more fragments left, 0 if last fragment */ }; uint16_t frag_data; /**< union of all fragmentation data */ }; uint32_t id; /**< Packet ID */ } __attribute__((__packed__)); /* * Create a new IP fragmentation table. * * @param bucket_num * Number of buckets in the hash table. * @param bucket_entries * Number of entries per bucket (e.g. hash associativity). * Should be power of two. * @param max_entries * Maximum number of entries that could be stored in the table. * The value should be less or equal then bucket_num * bucket_entries. * @param max_cycles * Maximum TTL in cycles for each fragmented packet. * @param socket_id * The *socket_id* argument is the socket identifier in the case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA constraints. * @return * The pointer to the new allocated fragmentation table, on success. NULL on error. */ struct rte_ip_frag_tbl * rte_ip_frag_table_create(uint32_t bucket_num, uint32_t bucket_entries, uint32_t max_entries, uint64_t max_cycles, int socket_id); /* * Free allocated IP fragmentation table. * * @param btl * Fragmentation table to free. */ static inline void rte_ip_frag_table_destroy( struct rte_ip_frag_tbl *tbl) { rte_free(tbl); } /** * This function implements the fragmentation of IPv6 packets. * * @param pkt_in * The input packet. * @param pkts_out * Array storing the output fragments. * @param nb_pkts_out * Number of fragments. * @param mtu_size * Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv6 * datagrams. This value includes the size of the IPv6 header. * @param pool_direct * MBUF pool used for allocating direct buffers for the output fragments. * @param pool_indirect * MBUF pool used for allocating indirect buffers for the output fragments. * @return * Upon successful completion - number of output fragments placed * in the pkts_out array. * Otherwise - (-1) * errno. */ int32_t rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect); /* * This function implements reassembly of fragmented IPv6 packets. * Incoming mbuf should have its l2_len/l3_len fields setup correctly. * * @param tbl * Table where to lookup/add the fragmented packet. * @param dr * Death row to free buffers to * @param mb * Incoming mbuf with IPv6 fragment. * @param tms * Fragment arrival timestamp. * @param ip_hdr * Pointer to the IPv6 header. * @param frag_hdr * Pointer to the IPv6 fragment extension header. * @return * Pointer to mbuf for reassembled packet, or NULL if: * - an error occured. * - not all fragments of the packet are collected yet. */ struct rte_mbuf *rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr); /* * Return a pointer to the packet's fragment header, if found. * It only looks at the extension header that's right after the fixed IPv6 * header, and doesn't follow the whole chain of extension headers. * * @param hdr * Pointer to the IPv6 header. * @return * Pointer to the IPv6 fragment extension header, or NULL if it's not * present. */ static inline struct ipv6_extension_fragment * rte_ipv6_frag_get_ipv6_fragment_header(struct ipv6_hdr *hdr) { if (hdr->proto == IPPROTO_FRAGMENT) { return (struct ipv6_extension_fragment *) ++hdr; } else return NULL; } /** * IPv4 fragmentation. * * This function implements the fragmentation of IPv4 packets. * * @param pkt_in * The input packet. * @param pkts_out * Array storing the output fragments. * @param nb_pkts_out * Number of fragments. * @param mtu_size * Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv4 * datagrams. This value includes the size of the IPv4 header. * @param pool_direct * MBUF pool used for allocating direct buffers for the output fragments. * @param pool_indirect * MBUF pool used for allocating indirect buffers for the output fragments. * @return * Upon successful completion - number of output fragments placed * in the pkts_out array. * Otherwise - (-1) * errno. */ int32_t rte_ipv4_fragment_packet(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect); /* * This function implements reassembly of fragmented IPv4 packets. * Incoming mbufs should have its l2_len/l3_len fields setup correclty. * * @param tbl * Table where to lookup/add the fragmented packet. * @param dr * Death row to free buffers to * @param mb * Incoming mbuf with IPv4 fragment. * @param tms * Fragment arrival timestamp. * @param ip_hdr * Pointer to the IPV4 header inside the fragment. * @return * Pointer to mbuf for reassebled packet, or NULL if: * - an error occured. * - not all fragments of the packet are collected yet. */ struct rte_mbuf * rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, struct ipv4_hdr *ip_hdr); /* * Check if the IPv4 packet is fragmented * * @param hdr * IPv4 header of the packet * @return * 1 if fragmented, 0 if not fragmented */ static inline int rte_ipv4_frag_pkt_is_fragmented(const struct ipv4_hdr * hdr) { uint16_t flag_offset, ip_flag, ip_ofs; flag_offset = rte_be_to_cpu_16(hdr->fragment_offset); ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK); ip_flag = (uint16_t)(flag_offset & IPV4_HDR_MF_FLAG); return ip_flag != 0 || ip_ofs != 0; } /* * Free mbufs on a given death row. * * @param dr * Death row to free mbufs in. * @param prefetch * How many buffers to prefetch before freeing. */ void rte_ip_frag_free_death_row(struct rte_ip_frag_death_row *dr, uint32_t prefetch); /* * Dump fragmentation table statistics to file. * * @param f * File to dump statistics to * @param tbl * Fragmentation table to dump statistics from */ void rte_ip_frag_table_statistics_dump(FILE * f, const struct rte_ip_frag_tbl *tbl); #ifdef __cplusplus } #endif #endif /* _RTE_IP_FRAG_H_ */ ================================================ FILE: lib/librte_ip_frag/rte_ip_frag_common.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "ip_frag_common.h" #define IP_FRAG_HASH_FNUM 2 /* free mbufs from death row */ void rte_ip_frag_free_death_row(struct rte_ip_frag_death_row *dr, uint32_t prefetch) { uint32_t i, k, n; k = RTE_MIN(prefetch, dr->cnt); n = dr->cnt; for (i = 0; i != k; i++) rte_prefetch0(dr->row[i]); for (i = 0; i != n - k; i++) { rte_prefetch0(dr->row[i + k]); rte_pktmbuf_free(dr->row[i]); } for (; i != n; i++) rte_pktmbuf_free(dr->row[i]); dr->cnt = 0; } /* create fragmentation table */ struct rte_ip_frag_tbl * rte_ip_frag_table_create(uint32_t bucket_num, uint32_t bucket_entries, uint32_t max_entries, uint64_t max_cycles, int socket_id) { struct rte_ip_frag_tbl *tbl; size_t sz; uint64_t nb_entries; nb_entries = rte_align32pow2(bucket_num); nb_entries *= bucket_entries; nb_entries *= IP_FRAG_HASH_FNUM; /* check input parameters. */ if (rte_is_power_of_2(bucket_entries) == 0 || nb_entries > UINT32_MAX || nb_entries == 0 || nb_entries < max_entries) { RTE_LOG(ERR, USER1, "%s: invalid input parameter\n", __func__); return NULL; } sz = sizeof (*tbl) + nb_entries * sizeof (tbl->pkt[0]); if ((tbl = rte_zmalloc_socket(__func__, sz, RTE_CACHE_LINE_SIZE, socket_id)) == NULL) { RTE_LOG(ERR, USER1, "%s: allocation of %zu bytes at socket %d failed do\n", __func__, sz, socket_id); return NULL; } RTE_LOG(INFO, USER1, "%s: allocated of %zu bytes at socket %d\n", __func__, sz, socket_id); tbl->max_cycles = max_cycles; tbl->max_entries = max_entries; tbl->nb_entries = (uint32_t)nb_entries; tbl->nb_buckets = bucket_num; tbl->bucket_entries = bucket_entries; tbl->entry_mask = (tbl->nb_entries - 1) & ~(tbl->bucket_entries - 1); TAILQ_INIT(&(tbl->lru)); return tbl; } /* dump frag table statistics to file */ void rte_ip_frag_table_statistics_dump(FILE *f, const struct rte_ip_frag_tbl *tbl) { uint64_t fail_total, fail_nospace; fail_total = tbl->stat.fail_total; fail_nospace = tbl->stat.fail_nospace; fprintf(f, "max entries:\t%u;\n" "entries in use:\t%u;\n" "finds/inserts:\t%" PRIu64 ";\n" "entries added:\t%" PRIu64 ";\n" "entries deleted by timeout:\t%" PRIu64 ";\n" "entries reused by timeout:\t%" PRIu64 ";\n" "total add failures:\t%" PRIu64 ";\n" "add no-space failures:\t%" PRIu64 ";\n" "add hash-collisions failures:\t%" PRIu64 ";\n", tbl->max_entries, tbl->use_entries, tbl->stat.find_num, tbl->stat.add_num, tbl->stat.del_num, tbl->stat.reuse_num, fail_total, fail_nospace, fail_total - fail_nospace); } ================================================ FILE: lib/librte_ip_frag/rte_ipv4_fragmentation.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "ip_frag_common.h" /* Fragment Offset */ #define IPV4_HDR_DF_SHIFT 14 #define IPV4_HDR_MF_SHIFT 13 #define IPV4_HDR_FO_SHIFT 3 #define IPV4_HDR_DF_MASK (1 << IPV4_HDR_DF_SHIFT) #define IPV4_HDR_MF_MASK (1 << IPV4_HDR_MF_SHIFT) #define IPV4_HDR_FO_MASK ((1 << IPV4_HDR_FO_SHIFT) - 1) static inline void __fill_ipv4hdr_frag(struct ipv4_hdr *dst, const struct ipv4_hdr *src, uint16_t len, uint16_t fofs, uint16_t dofs, uint32_t mf) { rte_memcpy(dst, src, sizeof(*dst)); fofs = (uint16_t)(fofs + (dofs >> IPV4_HDR_FO_SHIFT)); fofs = (uint16_t)(fofs | mf << IPV4_HDR_MF_SHIFT); dst->fragment_offset = rte_cpu_to_be_16(fofs); dst->total_length = rte_cpu_to_be_16(len); dst->hdr_checksum = 0; } static inline void __free_fragments(struct rte_mbuf *mb[], uint32_t num) { uint32_t i; for (i = 0; i != num; i++) rte_pktmbuf_free(mb[i]); } /** * IPv4 fragmentation. * * This function implements the fragmentation of IPv4 packets. * * @param pkt_in * The input packet. * @param pkts_out * Array storing the output fragments. * @param mtu_size * Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv4 * datagrams. This value includes the size of the IPv4 header. * @param pool_direct * MBUF pool used for allocating direct buffers for the output fragments. * @param pool_indirect * MBUF pool used for allocating indirect buffers for the output fragments. * @return * Upon successful completion - number of output fragments placed * in the pkts_out array. * Otherwise - (-1) * . */ int32_t rte_ipv4_fragment_packet(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect) { struct rte_mbuf *in_seg = NULL; struct ipv4_hdr *in_hdr; uint32_t out_pkt_pos, in_seg_data_pos; uint32_t more_in_segs; uint16_t fragment_offset, flag_offset, frag_size; frag_size = (uint16_t)(mtu_size - sizeof(struct ipv4_hdr)); /* Fragment size should be a multiply of 8. */ IP_FRAG_ASSERT((frag_size & IPV4_HDR_FO_MASK) == 0); in_hdr = rte_pktmbuf_mtod(pkt_in, struct ipv4_hdr *); flag_offset = rte_cpu_to_be_16(in_hdr->fragment_offset); /* If Don't Fragment flag is set */ if (unlikely ((flag_offset & IPV4_HDR_DF_MASK) != 0)) return -ENOTSUP; /* Check that pkts_out is big enough to hold all fragments */ if (unlikely(frag_size * nb_pkts_out < (uint16_t)(pkt_in->pkt_len - sizeof (struct ipv4_hdr)))) return -EINVAL; in_seg = pkt_in; in_seg_data_pos = sizeof(struct ipv4_hdr); out_pkt_pos = 0; fragment_offset = 0; more_in_segs = 1; while (likely(more_in_segs)) { struct rte_mbuf *out_pkt = NULL, *out_seg_prev = NULL; uint32_t more_out_segs; struct ipv4_hdr *out_hdr; /* Allocate direct buffer */ out_pkt = rte_pktmbuf_alloc(pool_direct); if (unlikely(out_pkt == NULL)) { __free_fragments(pkts_out, out_pkt_pos); return -ENOMEM; } /* Reserve space for the IP header that will be built later */ out_pkt->data_len = sizeof(struct ipv4_hdr); out_pkt->pkt_len = sizeof(struct ipv4_hdr); out_seg_prev = out_pkt; more_out_segs = 1; while (likely(more_out_segs && more_in_segs)) { struct rte_mbuf *out_seg = NULL; uint32_t len; /* Allocate indirect buffer */ out_seg = rte_pktmbuf_alloc(pool_indirect); if (unlikely(out_seg == NULL)) { rte_pktmbuf_free(out_pkt); __free_fragments(pkts_out, out_pkt_pos); return -ENOMEM; } out_seg_prev->next = out_seg; out_seg_prev = out_seg; /* Prepare indirect buffer */ rte_pktmbuf_attach(out_seg, in_seg); len = mtu_size - out_pkt->pkt_len; if (len > (in_seg->data_len - in_seg_data_pos)) { len = in_seg->data_len - in_seg_data_pos; } out_seg->data_off = in_seg->data_off + in_seg_data_pos; out_seg->data_len = (uint16_t)len; out_pkt->pkt_len = (uint16_t)(len + out_pkt->pkt_len); out_pkt->nb_segs += 1; in_seg_data_pos += len; /* Current output packet (i.e. fragment) done ? */ if (unlikely(out_pkt->pkt_len >= mtu_size)) more_out_segs = 0; /* Current input segment done ? */ if (unlikely(in_seg_data_pos == in_seg->data_len)) { in_seg = in_seg->next; in_seg_data_pos = 0; if (unlikely(in_seg == NULL)) more_in_segs = 0; } } /* Build the IP header */ out_hdr = rte_pktmbuf_mtod(out_pkt, struct ipv4_hdr *); __fill_ipv4hdr_frag(out_hdr, in_hdr, (uint16_t)out_pkt->pkt_len, flag_offset, fragment_offset, more_in_segs); fragment_offset = (uint16_t)(fragment_offset + out_pkt->pkt_len - sizeof(struct ipv4_hdr)); out_pkt->ol_flags |= PKT_TX_IP_CKSUM; out_pkt->l3_len = sizeof(struct ipv4_hdr); /* Write the fragment to the output list */ pkts_out[out_pkt_pos] = out_pkt; out_pkt_pos ++; } return out_pkt_pos; } ================================================ FILE: lib/librte_ip_frag/rte_ipv4_reassembly.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "ip_frag_common.h" /* * Reassemble fragments into one packet. */ struct rte_mbuf * ipv4_frag_reassemble(const struct ip_frag_pkt *fp) { struct ipv4_hdr *ip_hdr; struct rte_mbuf *m, *prev; uint32_t i, n, ofs, first_len; first_len = fp->frags[IP_FIRST_FRAG_IDX].len; n = fp->last_idx - 1; /*start from the last fragment. */ m = fp->frags[IP_LAST_FRAG_IDX].mb; ofs = fp->frags[IP_LAST_FRAG_IDX].ofs; while (ofs != first_len) { prev = m; for (i = n; i != IP_FIRST_FRAG_IDX && ofs != first_len; i--) { /* previous fragment found. */ if(fp->frags[i].ofs + fp->frags[i].len == ofs) { ip_frag_chain(fp->frags[i].mb, m); /* update our last fragment and offset. */ m = fp->frags[i].mb; ofs = fp->frags[i].ofs; } } /* error - hole in the packet. */ if (m == prev) { return NULL; } } /* chain with the first fragment. */ ip_frag_chain(fp->frags[IP_FIRST_FRAG_IDX].mb, m); m = fp->frags[IP_FIRST_FRAG_IDX].mb; /* update mbuf fields for reassembled packet. */ m->ol_flags |= PKT_TX_IP_CKSUM; /* update ipv4 header for the reassmebled packet */ ip_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *, m->l2_len); ip_hdr->total_length = rte_cpu_to_be_16((uint16_t)(fp->total_size + m->l3_len)); ip_hdr->fragment_offset = (uint16_t)(ip_hdr->fragment_offset & rte_cpu_to_be_16(IPV4_HDR_DF_FLAG)); ip_hdr->hdr_checksum = 0; return m; } /* * Process new mbuf with fragment of IPV4 packet. * Incoming mbuf should have it's l2_len/l3_len fields setuped correclty. * @param tbl * Table where to lookup/add the fragmented packet. * @param mb * Incoming mbuf with IPV4 fragment. * @param tms * Fragment arrival timestamp. * @param ip_hdr * Pointer to the IPV4 header inside the fragment. * @return * Pointer to mbuf for reassebled packet, or NULL if: * - an error occured. * - not all fragments of the packet are collected yet. */ struct rte_mbuf * rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, struct ipv4_hdr *ip_hdr) { struct ip_frag_pkt *fp; struct ip_frag_key key; const unaligned_uint64_t *psd; uint16_t ip_len; uint16_t flag_offset, ip_ofs, ip_flag; flag_offset = rte_be_to_cpu_16(ip_hdr->fragment_offset); ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK); ip_flag = (uint16_t)(flag_offset & IPV4_HDR_MF_FLAG); psd = (unaligned_uint64_t *)&ip_hdr->src_addr; /* use first 8 bytes only */ key.src_dst[0] = psd[0]; key.id = ip_hdr->packet_id; key.key_len = IPV4_KEYLEN; ip_ofs *= IPV4_HDR_OFFSET_UNITS; ip_len = (uint16_t)(rte_be_to_cpu_16(ip_hdr->total_length) - mb->l3_len); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p, tms: %" PRIu64 ", key: <%" PRIx64 ", %#x>, ofs: %u, len: %u, flags: %#x\n" "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, mb, tms, key.src_dst[0], key.id, ip_ofs, ip_len, ip_flag, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); /* try to find/add entry into the fragment's table. */ if ((fp = ip_frag_find(tbl, dr, &key, tms)) == NULL) { IP_FRAG_MBUF2DR(dr, mb); return NULL; } IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, fp, fp->key.src_dst[0], fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); /* process the fragmented packet. */ mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, ip_flag); ip_frag_inuse(tbl, fp); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv4_frag_pkt: %p, key: <%" PRIx64 ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, mb, tbl, tbl->max_entries, tbl->use_entries, fp, fp->key.src_dst[0], fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); return mb; } ================================================ FILE: lib/librte_ip_frag/rte_ipv6_fragmentation.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "ip_frag_common.h" /** * @file * RTE IPv6 Fragmentation * * Implementation of IPv6 fragmentation. * */ /* Fragment Extension Header */ #define IPV6_HDR_MF_SHIFT 0 #define IPV6_HDR_FO_SHIFT 3 #define IPV6_HDR_MF_MASK (1 << IPV6_HDR_MF_SHIFT) #define IPV6_HDR_FO_MASK ((1 << IPV6_HDR_FO_SHIFT) - 1) static inline void __fill_ipv6hdr_frag(struct ipv6_hdr *dst, const struct ipv6_hdr *src, uint16_t len, uint16_t fofs, uint32_t mf) { struct ipv6_extension_fragment *fh; rte_memcpy(dst, src, sizeof(*dst)); dst->payload_len = rte_cpu_to_be_16(len); dst->proto = IPPROTO_FRAGMENT; fh = (struct ipv6_extension_fragment *) ++dst; fh->next_header = src->proto; fh->reserved1 = 0; fh->frag_offset = rte_cpu_to_be_16(fofs); fh->reserved2 = 0; fh->more_frags = rte_cpu_to_be_16(mf); fh->id = 0; } static inline void __free_fragments(struct rte_mbuf *mb[], uint32_t num) { uint32_t i; for (i = 0; i < num; i++) rte_pktmbuf_free(mb[i]); } /** * IPv6 fragmentation. * * This function implements the fragmentation of IPv6 packets. * * @param pkt_in * The input packet. * @param pkts_out * Array storing the output fragments. * @param mtu_size * Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv6 * datagrams. This value includes the size of the IPv6 header. * @param pool_direct * MBUF pool used for allocating direct buffers for the output fragments. * @param pool_indirect * MBUF pool used for allocating indirect buffers for the output fragments. * @return * Upon successful completion - number of output fragments placed * in the pkts_out array. * Otherwise - (-1) * . */ int32_t rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect) { struct rte_mbuf *in_seg = NULL; struct ipv6_hdr *in_hdr; uint32_t out_pkt_pos, in_seg_data_pos; uint32_t more_in_segs; uint16_t fragment_offset, frag_size; frag_size = (uint16_t)(mtu_size - sizeof(struct ipv6_hdr)); /* Fragment size should be a multiple of 8. */ IP_FRAG_ASSERT((frag_size & IPV6_HDR_FO_MASK) == 0); /* Check that pkts_out is big enough to hold all fragments */ if (unlikely (frag_size * nb_pkts_out < (uint16_t)(pkt_in->pkt_len - sizeof (struct ipv6_hdr)))) return -EINVAL; in_hdr = rte_pktmbuf_mtod(pkt_in, struct ipv6_hdr *); in_seg = pkt_in; in_seg_data_pos = sizeof(struct ipv6_hdr); out_pkt_pos = 0; fragment_offset = 0; more_in_segs = 1; while (likely(more_in_segs)) { struct rte_mbuf *out_pkt = NULL, *out_seg_prev = NULL; uint32_t more_out_segs; struct ipv6_hdr *out_hdr; /* Allocate direct buffer */ out_pkt = rte_pktmbuf_alloc(pool_direct); if (unlikely(out_pkt == NULL)) { __free_fragments(pkts_out, out_pkt_pos); return -ENOMEM; } /* Reserve space for the IP header that will be built later */ out_pkt->data_len = sizeof(struct ipv6_hdr) + sizeof(struct ipv6_extension_fragment); out_pkt->pkt_len = sizeof(struct ipv6_hdr) + sizeof(struct ipv6_extension_fragment); out_seg_prev = out_pkt; more_out_segs = 1; while (likely(more_out_segs && more_in_segs)) { struct rte_mbuf *out_seg = NULL; uint32_t len; /* Allocate indirect buffer */ out_seg = rte_pktmbuf_alloc(pool_indirect); if (unlikely(out_seg == NULL)) { rte_pktmbuf_free(out_pkt); __free_fragments(pkts_out, out_pkt_pos); return -ENOMEM; } out_seg_prev->next = out_seg; out_seg_prev = out_seg; /* Prepare indirect buffer */ rte_pktmbuf_attach(out_seg, in_seg); len = mtu_size - out_pkt->pkt_len; if (len > (in_seg->data_len - in_seg_data_pos)) { len = in_seg->data_len - in_seg_data_pos; } out_seg->data_off = in_seg->data_off + in_seg_data_pos; out_seg->data_len = (uint16_t)len; out_pkt->pkt_len = (uint16_t)(len + out_pkt->pkt_len); out_pkt->nb_segs += 1; in_seg_data_pos += len; /* Current output packet (i.e. fragment) done ? */ if (unlikely(out_pkt->pkt_len >= mtu_size)) { more_out_segs = 0; } /* Current input segment done ? */ if (unlikely(in_seg_data_pos == in_seg->data_len)) { in_seg = in_seg->next; in_seg_data_pos = 0; if (unlikely(in_seg == NULL)) { more_in_segs = 0; } } } /* Build the IP header */ out_hdr = rte_pktmbuf_mtod(out_pkt, struct ipv6_hdr *); __fill_ipv6hdr_frag(out_hdr, in_hdr, (uint16_t) out_pkt->pkt_len - sizeof(struct ipv6_hdr), fragment_offset, more_in_segs); fragment_offset = (uint16_t)(fragment_offset + out_pkt->pkt_len - sizeof(struct ipv6_hdr) - sizeof(struct ipv6_extension_fragment)); /* Write the fragment to the output list */ pkts_out[out_pkt_pos] = out_pkt; out_pkt_pos ++; } return out_pkt_pos; } ================================================ FILE: lib/librte_ip_frag/rte_ipv6_reassembly.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "ip_frag_common.h" /** * @file * IPv6 reassemble * * Implementation of IPv6 reassembly. * */ static inline void ip_frag_memmove(char *dst, char *src, int len) { int i; /* go backwards to make sure we don't overwrite anything important */ for (i = len - 1; i >= 0; i--) dst[i] = src[i]; } /* * Reassemble fragments into one packet. */ struct rte_mbuf * ipv6_frag_reassemble(const struct ip_frag_pkt *fp) { struct ipv6_hdr *ip_hdr; struct ipv6_extension_fragment *frag_hdr; struct rte_mbuf *m, *prev; uint32_t i, n, ofs, first_len; uint32_t last_len, move_len, payload_len; first_len = fp->frags[IP_FIRST_FRAG_IDX].len; n = fp->last_idx - 1; /*start from the last fragment. */ m = fp->frags[IP_LAST_FRAG_IDX].mb; ofs = fp->frags[IP_LAST_FRAG_IDX].ofs; last_len = fp->frags[IP_LAST_FRAG_IDX].len; payload_len = ofs + last_len; while (ofs != first_len) { prev = m; for (i = n; i != IP_FIRST_FRAG_IDX && ofs != first_len; i--) { /* previous fragment found. */ if (fp->frags[i].ofs + fp->frags[i].len == ofs) { ip_frag_chain(fp->frags[i].mb, m); /* update our last fragment and offset. */ m = fp->frags[i].mb; ofs = fp->frags[i].ofs; } } /* error - hole in the packet. */ if (m == prev) { return NULL; } } /* chain with the first fragment. */ ip_frag_chain(fp->frags[IP_FIRST_FRAG_IDX].mb, m); m = fp->frags[IP_FIRST_FRAG_IDX].mb; /* update mbuf fields for reassembled packet. */ m->ol_flags |= PKT_TX_IP_CKSUM; /* update ipv6 header for the reassembled datagram */ ip_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *, m->l2_len); ip_hdr->payload_len = rte_cpu_to_be_16(payload_len); /* * remove fragmentation header. note that per RFC2460, we need to update * the last non-fragmentable header with the "next header" field to contain * type of the first fragmentable header, but we currently don't support * other headers, so we assume there are no other headers and thus update * the main IPv6 header instead. */ move_len = m->l2_len + m->l3_len - sizeof(*frag_hdr); frag_hdr = (struct ipv6_extension_fragment *) (ip_hdr + 1); ip_hdr->proto = frag_hdr->next_header; ip_frag_memmove(rte_pktmbuf_mtod_offset(m, char *, sizeof(*frag_hdr)), rte_pktmbuf_mtod(m, char*), move_len); rte_pktmbuf_adj(m, sizeof(*frag_hdr)); return m; } /* * Process new mbuf with fragment of IPV6 datagram. * Incoming mbuf should have its l2_len/l3_len fields setup correctly. * @param tbl * Table where to lookup/add the fragmented packet. * @param mb * Incoming mbuf with IPV6 fragment. * @param tms * Fragment arrival timestamp. * @param ip_hdr * Pointer to the IPV6 header. * @param frag_hdr * Pointer to the IPV6 fragment extension header. * @return * Pointer to mbuf for reassembled packet, or NULL if: * - an error occured. * - not all fragments of the packet are collected yet. */ #define MORE_FRAGS(x) (((x) & 0x100) >> 8) #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3) struct rte_mbuf * rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr) { struct ip_frag_pkt *fp; struct ip_frag_key key; uint16_t ip_len, ip_ofs; rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16); rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16); key.id = frag_hdr->id; key.key_len = IPV6_KEYLEN; ip_ofs = FRAG_OFFSET(frag_hdr->frag_data) * 8; /* * as per RFC2460, payload length contains all extension headers as well. * since we don't support anything but frag headers, this is what we remove * from the payload len. */ ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - sizeof(*frag_hdr); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p, tms: %" PRIu64 ", key: <" IPv6_KEY_BYTES_FMT ", %#x>, ofs: %u, len: %u, flags: %#x\n" "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, mb, tms, IPv6_KEY_BYTES(key.src_dst), key.id, ip_ofs, ip_len, frag_hdr->more_frags, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); /* try to find/add entry into the fragment's table. */ fp = ip_frag_find(tbl, dr, &key, tms); if (fp == NULL) { IP_FRAG_MBUF2DR(dr, mb); return NULL; } IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); /* process the fragmented packet. */ mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, MORE_FRAGS(frag_hdr->frag_data)); ip_frag_inuse(tbl, fp); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, mb, tbl, tbl->max_entries, tbl->use_entries, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); return mb; } ================================================ FILE: lib/librte_ivshmem/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_ivshmem.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_ivshmem_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_IVSHMEM) := rte_ivshmem.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_IVSHMEM)-include := rte_ivshmem.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += lib/librte_mempool include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_ivshmem/rte_ivshmem.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_ivshmem.h" #define IVSHMEM_CONFIG_FILE_FMT "/var/run/.dpdk_ivshmem_metadata_%s" #define IVSHMEM_QEMU_CMD_LINE_HEADER_FMT "-device ivshmem,size=%" PRIu64 "M,shm=fd%s" #define IVSHMEM_QEMU_CMD_FD_FMT ":%s:0x%" PRIx64 ":0x%" PRIx64 #define IVSHMEM_QEMU_CMDLINE_BUFSIZE 1024 #define IVSHMEM_MAX_PAGES (1 << 12) #define adjacent(x,y) (((x).phys_addr+(x).len)==(y).phys_addr) #define METADATA_SIZE_ALIGNED \ (RTE_ALIGN_CEIL(sizeof(struct rte_ivshmem_metadata),pagesz)) #define GET_PAGEMAP_ADDR(in,addr,dlm,err) \ { \ char *end; \ errno = 0; \ addr = strtoull((in), &end, 16); \ if (errno != 0 || *end != (dlm)) { \ RTE_LOG(ERR, EAL, err); \ goto error; \ } \ (in) = end + 1; \ } static int pagesz; struct memseg_cache_entry { char filepath[PATH_MAX]; uint64_t offset; uint64_t len; }; struct ivshmem_config { struct rte_ivshmem_metadata * metadata; struct memseg_cache_entry memseg_cache[IVSHMEM_MAX_PAGES]; /**< account for multiple files per segment case */ struct flock lock; rte_spinlock_t sl; }; static struct ivshmem_config ivshmem_global_config[RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES]; static rte_spinlock_t global_cfg_sl; static struct ivshmem_config * get_config_by_name(const char * name) { struct rte_ivshmem_metadata * config; unsigned i; for (i = 0; i < RTE_DIM(ivshmem_global_config); i++) { config = ivshmem_global_config[i].metadata; if (config == NULL) return NULL; if (strncmp(name, config->name, IVSHMEM_NAME_LEN) == 0) return &ivshmem_global_config[i]; } return NULL; } static int overlap(const struct rte_memzone * s1, const struct rte_memzone * s2) { uint64_t start1, end1, start2, end2; start1 = s1->addr_64; end1 = s1->addr_64 + s1->len; start2 = s2->addr_64; end2 = s2->addr_64 + s2->len; if (start1 >= start2 && start1 < end2) return 1; if (start2 >= start1 && start2 < end1) return 1; return 0; } static struct rte_memzone * get_memzone_by_addr(const void * addr) { struct rte_memzone * tmp, * mz; struct rte_mem_config * mcfg; int i; mcfg = rte_eal_get_configuration()->mem_config; mz = NULL; /* find memzone for the ring */ for (i = 0; i < RTE_MAX_MEMZONE; i++) { tmp = &mcfg->memzone[i]; if (tmp->addr_64 == (uint64_t) addr) { mz = tmp; break; } } return mz; } static int entry_compare(const void * a, const void * b) { const struct rte_ivshmem_metadata_entry * e1 = (const struct rte_ivshmem_metadata_entry*) a; const struct rte_ivshmem_metadata_entry * e2 = (const struct rte_ivshmem_metadata_entry*) b; /* move unallocated zones to the end */ if (e1->mz.addr == NULL && e2->mz.addr == NULL) return 0; if (e1->mz.addr == 0) return 1; if (e2->mz.addr == 0) return -1; return e1->mz.phys_addr > e2->mz.phys_addr; } /* fills hugepage cache entry for a given start virt_addr */ static int get_hugefile_by_virt_addr(uint64_t virt_addr, struct memseg_cache_entry * e) { uint64_t start_addr, end_addr; char *start,*path_end; char buf[PATH_MAX*2]; FILE *f; start = NULL; path_end = NULL; start_addr = 0; memset(e->filepath, 0, sizeof(e->filepath)); /* open /proc/self/maps */ f = fopen("/proc/self/maps", "r"); if (f == NULL) { RTE_LOG(ERR, EAL, "cannot open /proc/self/maps!\n"); return -1; } /* parse maps */ while (fgets(buf, sizeof(buf), f) != NULL) { /* get endptr to end of start addr */ start = buf; GET_PAGEMAP_ADDR(start,start_addr,'-', "Cannot find start address in maps!\n"); /* if start address is bigger than our address, skip */ if (start_addr > virt_addr) continue; GET_PAGEMAP_ADDR(start,end_addr,' ', "Cannot find end address in maps!\n"); /* if end address is less than our address, skip */ if (end_addr <= virt_addr) continue; /* find where the path starts */ start = strstr(start, "/"); if (start == NULL) continue; /* at this point, we know that this is our map. * now let's find the file */ path_end = strstr(start, "\n"); break; } if (path_end == NULL) { RTE_LOG(ERR, EAL, "Hugefile path not found!\n"); goto error; } /* calculate offset and copy the file path */ snprintf(e->filepath, RTE_PTR_DIFF(path_end, start) + 1, "%s", start); e->offset = virt_addr - start_addr; fclose(f); return 0; error: fclose(f); return -1; } /* * This is a complex function. What it does is the following: * 1. Goes through metadata and gets list of hugepages involved * 2. Sorts the hugepages by size (1G first) * 3. Goes through metadata again and writes correct offsets * 4. Goes through pages and finds out their filenames, offsets etc. */ static int build_config(struct rte_ivshmem_metadata * metadata) { struct rte_ivshmem_metadata_entry * e_local; struct memseg_cache_entry * ms_local; struct rte_memseg pages[IVSHMEM_MAX_PAGES]; struct rte_ivshmem_metadata_entry *entry; struct memseg_cache_entry * c_entry, * prev_entry; struct ivshmem_config * config; unsigned i, j, mz_iter, ms_iter; uint64_t biggest_len; int biggest_idx; /* return error if we try to use an unknown config file */ config = get_config_by_name(metadata->name); if (config == NULL) { RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", metadata->name); goto fail_e; } memset(pages, 0, sizeof(pages)); e_local = malloc(sizeof(config->metadata->entry)); if (e_local == NULL) goto fail_e; ms_local = malloc(sizeof(config->memseg_cache)); if (ms_local == NULL) goto fail_ms; /* make local copies before doing anything */ memcpy(e_local, config->metadata->entry, sizeof(config->metadata->entry)); memcpy(ms_local, config->memseg_cache, sizeof(config->memseg_cache)); qsort(e_local, RTE_DIM(config->metadata->entry), sizeof(struct rte_ivshmem_metadata_entry), entry_compare); /* first pass - collect all huge pages */ for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) { entry = &e_local[mz_iter]; uint64_t start_addr = RTE_ALIGN_FLOOR(entry->mz.addr_64, entry->mz.hugepage_sz); uint64_t offset = entry->mz.addr_64 - start_addr; uint64_t len = RTE_ALIGN_CEIL(entry->mz.len + offset, entry->mz.hugepage_sz); if (entry->mz.addr_64 == 0 || start_addr == 0 || len == 0) continue; int start_page; /* find first unused page - mz are phys_addr sorted so we don't have to * look out for holes */ for (i = 0; i < RTE_DIM(pages); i++) { /* skip if we already have this page */ if (pages[i].addr_64 == start_addr) { start_addr += entry->mz.hugepage_sz; len -= entry->mz.hugepage_sz; continue; } /* we found a new page */ else if (pages[i].addr_64 == 0) { start_page = i; break; } } if (i == RTE_DIM(pages)) { RTE_LOG(ERR, EAL, "Cannot find unused page!\n"); goto fail; } /* populate however many pages the memzone has */ for (i = start_page; i < RTE_DIM(pages) && len != 0; i++) { pages[i].addr_64 = start_addr; pages[i].len = entry->mz.hugepage_sz; start_addr += entry->mz.hugepage_sz; len -= entry->mz.hugepage_sz; } /* if there's still length left */ if (len != 0) { RTE_LOG(ERR, EAL, "Not enough space for pages!\n"); goto fail; } } /* second pass - sort pages by size */ for (i = 0; i < RTE_DIM(pages); i++) { if (pages[i].addr == NULL) break; biggest_len = 0; biggest_idx = -1; /* * browse all entries starting at 'i', and find the * entry with the smallest addr */ for (j=i; j< RTE_DIM(pages); j++) { if (pages[j].addr == NULL) break; if (biggest_len == 0 || pages[j].len > biggest_len) { biggest_len = pages[j].len; biggest_idx = j; } } /* should not happen */ if (biggest_idx == -1) { RTE_LOG(ERR, EAL, "Error sorting by size!\n"); goto fail; } if (i != (unsigned) biggest_idx) { struct rte_memseg tmp; memcpy(&tmp, &pages[biggest_idx], sizeof(struct rte_memseg)); /* we don't want to break contiguousness, so instead of just * swapping segments, we move all the preceding segments to the * right and then put the old segment @ biggest_idx in place of * segment @ i */ for (j = biggest_idx - 1; j >= i; j--) { memcpy(&pages[j+1], &pages[j], sizeof(struct rte_memseg)); memset(&pages[j], 0, sizeof(struct rte_memseg)); if (j == 0) break; } /* put old biggest segment to its new place */ memcpy(&pages[i], &tmp, sizeof(struct rte_memseg)); } } /* third pass - write correct offsets */ for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) { uint64_t offset = 0; entry = &e_local[mz_iter]; if (entry->mz.addr_64 == 0) break; /* find page for current memzone */ for (i = 0; i < RTE_DIM(pages); i++) { /* we found our page */ if (entry->mz.addr_64 >= pages[i].addr_64 && entry->mz.addr_64 < pages[i].addr_64 + pages[i].len) { entry->offset = (entry->mz.addr_64 - pages[i].addr_64) + offset; break; } offset += pages[i].len; } if (i == RTE_DIM(pages)) { RTE_LOG(ERR, EAL, "Page not found!\n"); goto fail; } } ms_iter = 0; prev_entry = NULL; /* fourth pass - create proper memseg cache */ for (i = 0; i < RTE_DIM(pages) && ms_iter <= RTE_DIM(config->memseg_cache); i++) { if (pages[i].addr_64 == 0) break; if (ms_iter == RTE_DIM(pages)) { RTE_LOG(ERR, EAL, "The universe has collapsed!\n"); goto fail; } c_entry = &ms_local[ms_iter]; c_entry->len = pages[i].len; if (get_hugefile_by_virt_addr(pages[i].addr_64, c_entry) < 0) goto fail; /* if previous entry has the same filename and is contiguous, * clear current entry and increase previous entry's length */ if (prev_entry != NULL && strncmp(c_entry->filepath, prev_entry->filepath, sizeof(c_entry->filepath)) == 0 && prev_entry->offset + prev_entry->len == c_entry->offset) { prev_entry->len += pages[i].len; memset(c_entry, 0, sizeof(struct memseg_cache_entry)); } else { prev_entry = c_entry; ms_iter++; } } /* update current configuration with new valid data */ memcpy(config->metadata->entry, e_local, sizeof(config->metadata->entry)); memcpy(config->memseg_cache, ms_local, sizeof(config->memseg_cache)); free(ms_local); free(e_local); return 0; fail: free(ms_local); fail_ms: free(e_local); fail_e: return -1; } static int add_memzone_to_metadata(const struct rte_memzone * mz, struct ivshmem_config * config) { struct rte_ivshmem_metadata_entry * entry; unsigned i; rte_spinlock_lock(&config->sl); /* find free slot in this config */ for (i = 0; i < RTE_DIM(config->metadata->entry); i++) { entry = &config->metadata->entry[i]; if (&entry->mz.addr_64 != 0 && overlap(mz, &entry->mz)) { RTE_LOG(ERR, EAL, "Overlapping memzones!\n"); goto fail; } /* if addr is zero, the memzone is probably free */ if (entry->mz.addr_64 == 0) { RTE_LOG(DEBUG, EAL, "Adding memzone '%s' at %p to metadata %s\n", mz->name, mz->addr, config->metadata->name); memcpy(&entry->mz, mz, sizeof(struct rte_memzone)); /* run config file parser */ if (build_config(config->metadata) < 0) goto fail; break; } } /* if we reached the maximum, that means we have no place in config */ if (i == RTE_DIM(config->metadata->entry)) { RTE_LOG(ERR, EAL, "No space left in IVSHMEM metadata %s!\n", config->metadata->name); goto fail; } #ifdef RTE_LIBRTE_IVSHMEM struct rte_mem_config *mcfg; unsigned int idx; mcfg = rte_eal_get_configuration()->mem_config; rte_rwlock_write_lock(&mcfg->mlock); idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone); idx = idx / sizeof(struct rte_memzone); /* mark the memzone not freeable */ mcfg->memzone[idx].ioremap_addr = mz->phys_addr; rte_rwlock_write_unlock(&mcfg->mlock); #endif rte_spinlock_unlock(&config->sl); return 0; fail: rte_spinlock_unlock(&config->sl); return -1; } static int add_ring_to_metadata(const struct rte_ring * r, struct ivshmem_config * config) { struct rte_memzone * mz; mz = get_memzone_by_addr(r); if (!mz) { RTE_LOG(ERR, EAL, "Cannot find memzone for ring!\n"); return -1; } return add_memzone_to_metadata(mz, config); } static int add_mempool_to_metadata(const struct rte_mempool * mp, struct ivshmem_config * config) { struct rte_memzone * mz; int ret; mz = get_memzone_by_addr(mp); ret = 0; if (!mz) { RTE_LOG(ERR, EAL, "Cannot find memzone for mempool!\n"); return -1; } /* mempool consists of memzone and ring */ ret = add_memzone_to_metadata(mz, config); if (ret < 0) return -1; return add_ring_to_metadata(mp->ring, config); } int rte_ivshmem_metadata_add_ring(const struct rte_ring * r, const char * name) { struct ivshmem_config * config; if (name == NULL || r == NULL) return -1; config = get_config_by_name(name); if (config == NULL) { RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name); return -1; } return add_ring_to_metadata(r, config); } int rte_ivshmem_metadata_add_memzone(const struct rte_memzone * mz, const char * name) { struct ivshmem_config * config; if (name == NULL || mz == NULL) return -1; config = get_config_by_name(name); if (config == NULL) { RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name); return -1; } return add_memzone_to_metadata(mz, config); } int rte_ivshmem_metadata_add_mempool(const struct rte_mempool * mp, const char * name) { struct ivshmem_config * config; if (name == NULL || mp == NULL) return -1; config = get_config_by_name(name); if (config == NULL) { RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name); return -1; } return add_mempool_to_metadata(mp, config); } static inline void ivshmem_config_path(char *buffer, size_t bufflen, const char *name) { snprintf(buffer, bufflen, IVSHMEM_CONFIG_FILE_FMT, name); } static inline void *ivshmem_metadata_create(const char *name, size_t size, struct flock *lock) { int retval, fd; void *metadata_addr; char pathname[PATH_MAX]; ivshmem_config_path(pathname, sizeof(pathname), name); fd = open(pathname, O_RDWR | O_CREAT, 0660); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open '%s'\n", pathname); return NULL; } size = METADATA_SIZE_ALIGNED; retval = fcntl(fd, F_SETLK, lock); if (retval < 0){ close(fd); RTE_LOG(ERR, EAL, "Cannot create lock on '%s'. Is another " "process using it?\n", pathname); return NULL; } retval = ftruncate(fd, size); if (retval < 0){ close(fd); RTE_LOG(ERR, EAL, "Cannot resize '%s'\n", pathname); return NULL; } metadata_addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (metadata_addr == MAP_FAILED){ RTE_LOG(ERR, EAL, "Cannot mmap memory for '%s'\n", pathname); /* we don't care if we can't unlock */ fcntl(fd, F_UNLCK, lock); close(fd); return NULL; } return metadata_addr; } int rte_ivshmem_metadata_create(const char *name) { struct ivshmem_config * ivshmem_config; unsigned index; if (pagesz == 0) pagesz = getpagesize(); if (name == NULL) return -1; rte_spinlock_lock(&global_cfg_sl); for (index = 0; index < RTE_DIM(ivshmem_global_config); index++) { if (ivshmem_global_config[index].metadata == NULL) { ivshmem_config = &ivshmem_global_config[index]; break; } } if (index == RTE_DIM(ivshmem_global_config)) { RTE_LOG(ERR, EAL, "Cannot create more ivshmem config files. " "Maximum has been reached\n"); rte_spinlock_unlock(&global_cfg_sl); return -1; } ivshmem_config->lock.l_type = F_WRLCK; ivshmem_config->lock.l_whence = SEEK_SET; ivshmem_config->lock.l_start = 0; ivshmem_config->lock.l_len = METADATA_SIZE_ALIGNED; ivshmem_global_config[index].metadata = ((struct rte_ivshmem_metadata *) ivshmem_metadata_create( name, sizeof(struct rte_ivshmem_metadata), &ivshmem_config->lock)); if (ivshmem_global_config[index].metadata == NULL) { rte_spinlock_unlock(&global_cfg_sl); return -1; } /* Metadata setup */ memset(ivshmem_config->metadata, 0, sizeof(struct rte_ivshmem_metadata)); ivshmem_config->metadata->magic_number = IVSHMEM_MAGIC; snprintf(ivshmem_config->metadata->name, sizeof(ivshmem_config->metadata->name), "%s", name); rte_spinlock_unlock(&global_cfg_sl); return 0; } int rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size, const char *name) { const struct memseg_cache_entry * ms_cache, *entry; struct ivshmem_config * config; char cmdline[IVSHMEM_QEMU_CMDLINE_BUFSIZE], *cmdline_ptr; char cfg_file_path[PATH_MAX]; unsigned remaining_len, tmplen, iter; uint64_t shared_mem_size, zero_size, total_size; if (buffer == NULL || name == NULL) return -1; config = get_config_by_name(name); if (config == NULL) { RTE_LOG(ERR, EAL, "Config %s not found!\n", name); return -1; } rte_spinlock_lock(&config->sl); /* prepare metadata file path */ snprintf(cfg_file_path, sizeof(cfg_file_path), IVSHMEM_CONFIG_FILE_FMT, config->metadata->name); ms_cache = config->memseg_cache; cmdline_ptr = cmdline; remaining_len = sizeof(cmdline); shared_mem_size = 0; iter = 0; while ((ms_cache[iter].len != 0) && (iter < RTE_DIM(config->metadata->entry))) { entry = &ms_cache[iter]; /* Offset and sizes within the current pathname */ tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT, entry->filepath, entry->offset, entry->len); shared_mem_size += entry->len; cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen); remaining_len -= tmplen; if (remaining_len == 0) { RTE_LOG(ERR, EAL, "Command line too long!\n"); rte_spinlock_unlock(&config->sl); return -1; } iter++; } total_size = rte_align64pow2(shared_mem_size + METADATA_SIZE_ALIGNED); zero_size = total_size - shared_mem_size - METADATA_SIZE_ALIGNED; /* add /dev/zero to command-line to fill the space */ tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT, "/dev/zero", (uint64_t)0x0, zero_size); cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen); remaining_len -= tmplen; if (remaining_len == 0) { RTE_LOG(ERR, EAL, "Command line too long!\n"); rte_spinlock_unlock(&config->sl); return -1; } /* add metadata file to the end of command-line */ tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT, cfg_file_path, (uint64_t)0x0, METADATA_SIZE_ALIGNED); cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen); remaining_len -= tmplen; if (remaining_len == 0) { RTE_LOG(ERR, EAL, "Command line too long!\n"); rte_spinlock_unlock(&config->sl); return -1; } /* if current length of the command line is bigger than the buffer supplied * by the user, or if command-line is bigger than what IVSHMEM accepts */ if ((sizeof(cmdline) - remaining_len) > size) { RTE_LOG(ERR, EAL, "Buffer is too short!\n"); rte_spinlock_unlock(&config->sl); return -1; } /* complete the command-line */ snprintf(buffer, size, IVSHMEM_QEMU_CMD_LINE_HEADER_FMT, total_size >> 20, cmdline); rte_spinlock_unlock(&config->sl); return 0; } void rte_ivshmem_metadata_dump(FILE *f, const char *name) { unsigned i = 0; struct ivshmem_config * config; struct rte_ivshmem_metadata_entry *entry; #ifdef RTE_LIBRTE_IVSHMEM_DEBUG uint64_t addr; uint64_t end, hugepage_sz; struct memseg_cache_entry e; #endif if (name == NULL) return; /* return error if we try to use an unknown config file */ config = get_config_by_name(name); if (config == NULL) { RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name); return; } rte_spinlock_lock(&config->sl); entry = &config->metadata->entry[0]; while (entry->mz.addr != NULL && i < RTE_DIM(config->metadata->entry)) { fprintf(f, "Entry %u: name:<%-20s>, phys:0x%-15lx, len:0x%-15lx, " "virt:%-15p, off:0x%-15lx\n", i, entry->mz.name, entry->mz.phys_addr, entry->mz.len, entry->mz.addr, entry->offset); i++; #ifdef RTE_LIBRTE_IVSHMEM_DEBUG fprintf(f, "\tHugepage files:\n"); hugepage_sz = entry->mz.hugepage_sz; addr = RTE_ALIGN_FLOOR(entry->mz.addr_64, hugepage_sz); end = addr + RTE_ALIGN_CEIL(entry->mz.len + (entry->mz.addr_64 - addr), hugepage_sz); for (; addr < end; addr += hugepage_sz) { memset(&e, 0, sizeof(e)); get_hugefile_by_virt_addr(addr, &e); fprintf(f, "\t0x%"PRIx64 "-0x%" PRIx64 " offset: 0x%" PRIx64 " %s\n", addr, addr + hugepage_sz, e.offset, e.filepath); } #endif entry++; } rte_spinlock_unlock(&config->sl); } ================================================ FILE: lib/librte_ivshmem/rte_ivshmem.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_IVSHMEM_H_ #define RTE_IVSHMEM_H_ #include #include /** * @file * * The RTE IVSHMEM interface provides functions to create metadata files * describing memory segments to be shared via QEMU IVSHMEM. */ #ifdef __cplusplus extern "C" { #endif #define IVSHMEM_MAGIC 0x0BADC0DE #define IVSHMEM_NAME_LEN 32 /** * Structure that holds IVSHMEM shared metadata entry. */ struct rte_ivshmem_metadata_entry { struct rte_memzone mz; /**< shared memzone */ uint64_t offset; /**< offset of memzone within IVSHMEM device */ }; /** * Structure that holds IVSHMEM metadata. */ struct rte_ivshmem_metadata { int magic_number; /**< magic number */ char name[IVSHMEM_NAME_LEN]; /**< name of the metadata file */ struct rte_ivshmem_metadata_entry entry[RTE_LIBRTE_IVSHMEM_MAX_ENTRIES]; /**< metadata entries */ }; /** * Creates metadata file with a given name * * @param name * Name of metadata file to be created * * @return * - On success, zero * - On failure, a negative value */ int rte_ivshmem_metadata_create(const char * name); /** * Adds memzone to a specific metadata file * * @param mz * Memzone to be added * @param md_name * Name of metadata file for the memzone to be added to * * @return * - On success, zero * - On failure, a negative value */ int rte_ivshmem_metadata_add_memzone(const struct rte_memzone * mz, const char * md_name); /** * Adds a ring descriptor to a specific metadata file * * @param r * Ring descriptor to be added * @param md_name * Name of metadata file for the ring to be added to * * @return * - On success, zero * - On failure, a negative value */ int rte_ivshmem_metadata_add_ring(const struct rte_ring * r, const char * md_name); /** * Adds a mempool to a specific metadata file * * @param mp * Mempool to be added * @param md_name * Name of metadata file for the mempool to be added to * * @return * - On success, zero * - On failure, a negative value */ int rte_ivshmem_metadata_add_mempool(const struct rte_mempool * mp, const char * md_name); /** * Generates the QEMU command-line for IVSHMEM device for a given metadata file. * This function is to be called after all the objects were added. * * @param buffer * Buffer to be filled with the command line arguments. * @param size * Size of the buffer. * @param name * Name of metadata file to generate QEMU command-line parameters for * * @return * - On success, zero * - On failure, a negative value */ int rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size, const char *name); /** * Dump all metadata entries from a given metadata file to the console. * * @param f * A pointer to a file for output * @name * Name of the metadata file to be dumped to console. */ void rte_ivshmem_metadata_dump(FILE *f, const char *name); #ifdef __cplusplus } #endif #endif /* RTE_IVSHMEM_H_ */ ================================================ FILE: lib/librte_jobstats/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_jobstats.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_jobstats_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_JOBSTATS) := rte_jobstats.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_JOBSTATS)-include := rte_jobstats.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_jobstats/rte_jobstats.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "rte_jobstats.h" #define ADD_TIME_MIN_MAX(obj, type, value) do { \ typeof(value) tmp = (value); \ (obj)->type ## _time += tmp; \ if (tmp < (obj)->min_ ## type ## _time) \ (obj)->min_ ## type ## _time = tmp; \ if (tmp > (obj)->max_ ## type ## _time) \ (obj)->max_ ## type ## _time = tmp; \ } while (0) #define RESET_TIME_MIN_MAX(obj, type) do { \ (obj)->type ## _time = 0; \ (obj)->min_ ## type ## _time = UINT64_MAX; \ (obj)->max_ ## type ## _time = 0; \ } while (0) static inline uint64_t get_time(void) { rte_rmb(); return rte_get_timer_cycles(); } /* Those are steps used to adjust job period. * Experiments show that for forwarding apps the up step must be less than down * step to achieve optimal performance. */ #define JOB_UPDATE_STEP_UP 1 #define JOB_UPDATE_STEP_DOWN 4 /* * Default update function that implements simple period adjustment. */ static void default_update_function(struct rte_jobstats *job, int64_t result) { int64_t err = job->target - result; /* Job is happy. Nothing to do */ if (err == 0) return; if (err > 0) { if (job->period + JOB_UPDATE_STEP_UP < job->max_period) job->period += JOB_UPDATE_STEP_UP; } else { if (job->min_period + JOB_UPDATE_STEP_DOWN < job->period) job->period -= JOB_UPDATE_STEP_DOWN; } } int rte_jobstats_context_init(struct rte_jobstats_context *ctx) { if (ctx == NULL) return -EINVAL; /* Init only needed parameters. Zero out everything else. */ memset(ctx, 0, sizeof(struct rte_jobstats_context)); rte_jobstats_context_reset(ctx); return 0; } void rte_jobstats_context_start(struct rte_jobstats_context *ctx) { uint64_t now; ctx->loop_executed_jobs = 0; now = get_time(); ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); ctx->state_time = now; } void rte_jobstats_context_finish(struct rte_jobstats_context *ctx) { uint64_t now; if (likely(ctx->loop_executed_jobs)) ctx->loop_cnt++; now = get_time(); ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); ctx->state_time = now; } void rte_jobstats_context_reset(struct rte_jobstats_context *ctx) { RESET_TIME_MIN_MAX(ctx, exec); RESET_TIME_MIN_MAX(ctx, management); ctx->start_time = get_time(); ctx->state_time = ctx->start_time; ctx->job_exec_cnt = 0; ctx->loop_cnt = 0; } void rte_jobstats_set_target(struct rte_jobstats *job, int64_t target) { job->target = target; } int rte_jobstats_start(struct rte_jobstats_context *ctx, struct rte_jobstats *job) { uint64_t now; /* Some sanity check. */ if (unlikely(ctx == NULL || job == NULL || job->context != NULL)) return -EINVAL; /* Link job with context object. */ job->context = ctx; now = get_time(); ADD_TIME_MIN_MAX(ctx, management, now - ctx->state_time); ctx->state_time = now; return 0; } int rte_jobstats_finish(struct rte_jobstats *job, int64_t job_value) { struct rte_jobstats_context *ctx; uint64_t now, exec_time; int need_update; /* Some sanity check. */ if (unlikely(job == NULL || job->context == NULL)) return -EINVAL; need_update = job->target != job_value; /* Adjust period only if job is unhappy of its current period. */ if (need_update) (*job->update_period_cb)(job, job_value); ctx = job->context; /* Update execution time is considered as runtime so get time after it is * executed. */ now = get_time(); exec_time = now - ctx->state_time; ADD_TIME_MIN_MAX(job, exec, exec_time); ADD_TIME_MIN_MAX(ctx, exec, exec_time); ctx->state_time = now; ctx->loop_executed_jobs++; ctx->job_exec_cnt++; job->exec_cnt++; job->context = NULL; return need_update; } void rte_jobstats_set_period(struct rte_jobstats *job, uint64_t period, uint8_t saturate) { if (saturate != 0) { if (period < job->min_period) period = job->min_period; else if (period > job->max_period) period = job->max_period; } job->period = period; } void rte_jobstats_set_min(struct rte_jobstats *job, uint64_t period) { job->min_period = period; if (job->period < period) job->period = period; } void rte_jobstats_set_max(struct rte_jobstats *job, uint64_t period) { job->max_period = period; if (job->period > period) job->period = period; } int rte_jobstats_init(struct rte_jobstats *job, const char *name, uint64_t min_period, uint64_t max_period, uint64_t initial_period, int64_t target) { if (job == NULL) return -EINVAL; job->period = initial_period; job->min_period = min_period; job->max_period = max_period; job->target = target; job->update_period_cb = &default_update_function; rte_jobstats_reset(job); snprintf(job->name, RTE_DIM(job->name), "%s", name == NULL ? "" : name); job->context = NULL; return 0; } void rte_jobstats_set_update_period_function(struct rte_jobstats *job, rte_job_update_period_cb_t update_period_cb) { if (update_period_cb == NULL) update_period_cb = default_update_function; job->update_period_cb = update_period_cb; } void rte_jobstats_reset(struct rte_jobstats *job) { RESET_TIME_MIN_MAX(job, exec); job->exec_cnt = 0; } ================================================ FILE: lib/librte_jobstats/rte_jobstats.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef JOBSTATS_H_ #define JOBSTATS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif #define RTE_JOBSTATS_NAMESIZE 32 /* Forward declarations. */ struct rte_jobstats_context; struct rte_jobstats; /** * This function should calculate new period and set it using * rte_jobstats_set_period() function. Time spent in this function will be * added to job's runtime. * * @param job * The job data structure handler. * @param job_result * Result of calling job callback. */ typedef void (*rte_job_update_period_cb_t)(struct rte_jobstats *job, int64_t job_result); struct rte_jobstats { uint64_t period; /**< Estimated period of execution. */ uint64_t min_period; /**< Minimum period. */ uint64_t max_period; /**< Maximum period. */ int64_t target; /**< Desired value for this job. */ rte_job_update_period_cb_t update_period_cb; /**< Period update callback. */ uint64_t exec_time; /**< Total time (sum) that this job was executing. */ uint64_t min_exec_time; /**< Minimum execute time. */ uint64_t max_exec_time; /**< Minimum execute time. */ uint64_t exec_cnt; /**< Execute count. */ char name[RTE_JOBSTATS_NAMESIZE]; /**< Name of this job */ struct rte_jobstats_context *context; /**< Job stats context object that is executing this job. */ } __rte_cache_aligned; struct rte_jobstats_context { /** Viariable holding time at different points: * -# loop start time if loop was started but no job executed yet. * -# job start time if job is currently executing. * -# job finish time if job finished its execution. * -# loop finish time if loop finished its execution. */ uint64_t state_time; uint64_t loop_executed_jobs; /**< Count of executed jobs in this loop. */ /* Statistics start. */ uint64_t exec_time; /**< Total time taken to execute jobs, not including management time. */ uint64_t min_exec_time; /**< Minimum loop execute time. */ uint64_t max_exec_time; /**< Minimum loop execute time. */ /** * Sum of time that is not the execute time (ex: from job finish to next * job start). * * This time might be considered as overhead of library + job scheduling. */ uint64_t management_time; uint64_t min_management_time; /**< Minimum management time */ uint64_t max_management_time; /**< Maximum management time */ uint64_t start_time; /**< Time since last reset stats. */ uint64_t job_exec_cnt; /**< Total count of executed jobs. */ uint64_t loop_cnt; /**< Total count of executed loops with at least one executed job. */ } __rte_cache_aligned; /** * Initialize given context object with default values. * * @param ctx * Job stats context object to initialize. * * @return * 0 on success * -EINVAL if *ctx* is NULL */ int rte_jobstats_context_init(struct rte_jobstats_context *ctx); /** * Mark that new set of jobs start executing. * * @param ctx * Job stats context object. */ void rte_jobstats_context_start(struct rte_jobstats_context *ctx); /** * Mark that there is no more jobs ready to execute in this turn. Calculate * stats for this loop turn. * * @param ctx * Job stats context. */ void rte_jobstats_context_finish(struct rte_jobstats_context *ctx); /** * Function resets job context statistics. * * @param ctx * Job stats context which statistics will be reset. */ void rte_jobstats_context_reset(struct rte_jobstats_context *ctx); /** * Initialize given job stats object. * * @param job * Job object. * @param name * Optional job name. * @param min_period * Minimum period that this job can accept. * @param max_period * Maximum period that this job can accept. * @param initial_period * Initial period. It will be checked against *min_period* and *max_period*. * @param target * Target value that this job try to achieve. * * @return * 0 on success * -EINVAL if *job* is NULL */ int rte_jobstats_init(struct rte_jobstats *job, const char *name, uint64_t min_period, uint64_t max_period, uint64_t initial_period, int64_t target); /** * Set job desired target value. Difference between target and job value * value must be used to properly adjust job execute period value. * * @param job * The job object. * @param target * New target. */ void rte_jobstats_set_target(struct rte_jobstats *job, int64_t target); /** * Mark that *job* is starting of its execution in context of *ctx* object. * * @param ctx * Job stats context. * @param job * Job object. * @return * 0 on success * -EINVAL if *ctx* or *job* is NULL or *job* is executing in another context * context already, */ int rte_jobstats_start(struct rte_jobstats_context *ctx, struct rte_jobstats *job); /** * Mark that *job* finished its execution. Context in which it was executing * will receive stat update. After this function call *job* object is ready to * be executed in other context. * * @param job * Job object. * @param job_value * Job value. Job should pass in this parameter a value that it try to optimize * for example the number of packets it processed. * * @return * 0 if job's period was not updated (job target equals *job_value*) * 1 if job's period was updated * -EINVAL if job is NULL or job was not started (it have no context). */ int rte_jobstats_finish(struct rte_jobstats *job, int64_t job_value); /** * Set execute period of given job. * * @param job * The job object. * @param period * New period value. * @param saturate * If zero, skip period saturation to min, max range. */ void rte_jobstats_set_period(struct rte_jobstats *job, uint64_t period, uint8_t saturate); /** * Set minimum execute period of given job. Current period will be checked * against new minimum value. * * @param job * The job object. * @param period * New minimum period value. */ void rte_jobstats_set_min(struct rte_jobstats *job, uint64_t period); /** * Set maximum execute period of given job. Current period will be checked * against new maximum value. * * @param job * The job object. * @param period * New maximum period value. */ void rte_jobstats_set_max(struct rte_jobstats *job, uint64_t period); /** * Set update period callback that is invoked after job finish. * * If application wants to do more sophisticated calculations than default * it can provide this handler. * * @param job * Job object. * @param update_pedriod_cb * Callback to set. If NULL restore default update function. */ void rte_jobstats_set_update_period_function(struct rte_jobstats *job, rte_job_update_period_cb_t update_period_cb); /** * Function resets job statistics. * * @param job * Job which statistics will be reset. */ void rte_jobstats_reset(struct rte_jobstats *job); #ifdef __cplusplus } #endif #endif /* JOBSTATS_H_ */ ================================================ FILE: lib/librte_kni/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_kni.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -fno-strict-aliasing EXPORT_MAP := rte_kni_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_KNI) := rte_kni.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_KNI)-include := rte_kni.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_KNI) += lib/librte_eal lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_KNI) += lib/librte_ether include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_kni/rte_kni.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_EXEC_ENV_LINUXAPP #error "KNI is not supported" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_kni_fifo.h" #define MAX_MBUF_BURST_NUM 32 /* Maximum number of ring entries */ #define KNI_FIFO_COUNT_MAX 1024 #define KNI_FIFO_SIZE (KNI_FIFO_COUNT_MAX * sizeof(void *) + \ sizeof(struct rte_kni_fifo)) #define KNI_REQUEST_MBUF_NUM_MAX 32 #define KNI_MEM_CHECK(cond) do { if (cond) goto kni_fail; } while (0) /** * KNI context */ struct rte_kni { char name[RTE_KNI_NAMESIZE]; /**< KNI interface name */ uint16_t group_id; /**< Group ID of KNI devices */ uint32_t slot_id; /**< KNI pool slot ID */ struct rte_mempool *pktmbuf_pool; /**< pkt mbuf mempool */ unsigned mbuf_size; /**< mbuf size */ struct rte_kni_fifo *tx_q; /**< TX queue */ struct rte_kni_fifo *rx_q; /**< RX queue */ struct rte_kni_fifo *alloc_q; /**< Allocated mbufs queue */ struct rte_kni_fifo *free_q; /**< To be freed mbufs queue */ /* For request & response */ struct rte_kni_fifo *req_q; /**< Request queue */ struct rte_kni_fifo *resp_q; /**< Response queue */ void * sync_addr; /**< Req/Resp Mem address */ struct rte_kni_ops ops; /**< operations for request */ uint8_t in_use : 1; /**< kni in use */ }; enum kni_ops_status { KNI_REQ_NO_REGISTER = 0, KNI_REQ_REGISTERED, }; /** * KNI memzone pool slot */ struct rte_kni_memzone_slot { uint32_t id; uint8_t in_use : 1; /**< slot in use */ /* Memzones */ const struct rte_memzone *m_ctx; /**< KNI ctx */ const struct rte_memzone *m_tx_q; /**< TX queue */ const struct rte_memzone *m_rx_q; /**< RX queue */ const struct rte_memzone *m_alloc_q; /**< Allocated mbufs queue */ const struct rte_memzone *m_free_q; /**< To be freed mbufs queue */ const struct rte_memzone *m_req_q; /**< Request queue */ const struct rte_memzone *m_resp_q; /**< Response queue */ const struct rte_memzone *m_sync_addr; /* Free linked list */ struct rte_kni_memzone_slot *next; /**< Next slot link.list */ }; /** * KNI memzone pool */ struct rte_kni_memzone_pool { uint8_t initialized : 1; /**< Global KNI pool init flag */ uint32_t max_ifaces; /**< Max. num of KNI ifaces */ struct rte_kni_memzone_slot *slots; /**< Pool slots */ rte_spinlock_t mutex; /**< alloc/relase mutex */ /* Free memzone slots linked-list */ struct rte_kni_memzone_slot *free; /**< First empty slot */ struct rte_kni_memzone_slot *free_tail; /**< Last empty slot */ }; static void kni_free_mbufs(struct rte_kni *kni); static void kni_allocate_mbufs(struct rte_kni *kni); static volatile int kni_fd = -1; static struct rte_kni_memzone_pool kni_memzone_pool = { .initialized = 0, }; static const struct rte_memzone * kni_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) { const struct rte_memzone *mz = rte_memzone_lookup(name); if (mz == NULL) mz = rte_memzone_reserve(name, len, socket_id, flags); return mz; } /* Pool mgmt */ static struct rte_kni_memzone_slot* kni_memzone_pool_alloc(void) { struct rte_kni_memzone_slot *slot; rte_spinlock_lock(&kni_memzone_pool.mutex); if (!kni_memzone_pool.free) { rte_spinlock_unlock(&kni_memzone_pool.mutex); return NULL; } slot = kni_memzone_pool.free; kni_memzone_pool.free = slot->next; slot->in_use = 1; if (!kni_memzone_pool.free) kni_memzone_pool.free_tail = NULL; rte_spinlock_unlock(&kni_memzone_pool.mutex); return slot; } static void kni_memzone_pool_release(struct rte_kni_memzone_slot *slot) { rte_spinlock_lock(&kni_memzone_pool.mutex); if (kni_memzone_pool.free) kni_memzone_pool.free_tail->next = slot; else kni_memzone_pool.free = slot; kni_memzone_pool.free_tail = slot; slot->next = NULL; slot->in_use = 0; rte_spinlock_unlock(&kni_memzone_pool.mutex); } /* Shall be called before any allocation happens */ void rte_kni_init(unsigned int max_kni_ifaces) { uint32_t i; struct rte_kni_memzone_slot *it; const struct rte_memzone *mz; #define OBJNAMSIZ 32 char obj_name[OBJNAMSIZ]; char mz_name[RTE_MEMZONE_NAMESIZE]; /* Immediately return if KNI is already initialized */ if (kni_memzone_pool.initialized) { RTE_LOG(WARNING, KNI, "Double call to rte_kni_init()"); return; } if (max_kni_ifaces == 0) { RTE_LOG(ERR, KNI, "Invalid number of max_kni_ifaces %d\n", max_kni_ifaces); rte_panic("Unable to initialize KNI\n"); } /* Check FD and open */ if (kni_fd < 0) { kni_fd = open("/dev/" KNI_DEVICE, O_RDWR); if (kni_fd < 0) rte_panic("Can not open /dev/%s\n", KNI_DEVICE); } /* Allocate slot objects */ kni_memzone_pool.slots = (struct rte_kni_memzone_slot *) rte_malloc(NULL, sizeof(struct rte_kni_memzone_slot) * max_kni_ifaces, 0); KNI_MEM_CHECK(kni_memzone_pool.slots == NULL); /* Initialize general pool variables */ kni_memzone_pool.initialized = 1; kni_memzone_pool.max_ifaces = max_kni_ifaces; kni_memzone_pool.free = &kni_memzone_pool.slots[0]; rte_spinlock_init(&kni_memzone_pool.mutex); /* Pre-allocate all memzones of all the slots; panic on error */ for (i = 0; i < max_kni_ifaces; i++) { /* Recover current slot */ it = &kni_memzone_pool.slots[i]; it->id = i; /* Allocate KNI context */ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%d", i); mz = kni_memzone_reserve(mz_name, sizeof(struct rte_kni), SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_ctx = mz; /* TX RING */ snprintf(obj_name, OBJNAMSIZ, "kni_tx_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_tx_q = mz; /* RX RING */ snprintf(obj_name, OBJNAMSIZ, "kni_rx_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_rx_q = mz; /* ALLOC RING */ snprintf(obj_name, OBJNAMSIZ, "kni_alloc_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_alloc_q = mz; /* FREE RING */ snprintf(obj_name, OBJNAMSIZ, "kni_free_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_free_q = mz; /* Request RING */ snprintf(obj_name, OBJNAMSIZ, "kni_req_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_req_q = mz; /* Response RING */ snprintf(obj_name, OBJNAMSIZ, "kni_resp_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_resp_q = mz; /* Req/Resp sync mem area */ snprintf(obj_name, OBJNAMSIZ, "kni_sync_%d", i); mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0); KNI_MEM_CHECK(mz == NULL); it->m_sync_addr = mz; if ((i+1) == max_kni_ifaces) { it->next = NULL; kni_memzone_pool.free_tail = it; } else it->next = &kni_memzone_pool.slots[i+1]; } return; kni_fail: rte_panic("Unable to allocate memory for max_kni_ifaces:%d. Increase the amount of hugepages memory\n", max_kni_ifaces); } /* It is deprecated and just for backward compatibility */ struct rte_kni * rte_kni_create(uint8_t port_id, unsigned mbuf_size, struct rte_mempool *pktmbuf_pool, struct rte_kni_ops *ops) { struct rte_kni_conf conf; struct rte_eth_dev_info info; memset(&info, 0, sizeof(info)); memset(&conf, 0, sizeof(conf)); rte_eth_dev_info_get(port_id, &info); snprintf(conf.name, sizeof(conf.name), "vEth%u", port_id); conf.addr = info.pci_dev->addr; conf.id = info.pci_dev->id; conf.group_id = (uint16_t)port_id; conf.mbuf_size = mbuf_size; /* Save the port id for request handling */ ops->port_id = port_id; return rte_kni_alloc(pktmbuf_pool, &conf, ops); } struct rte_kni * rte_kni_alloc(struct rte_mempool *pktmbuf_pool, const struct rte_kni_conf *conf, struct rte_kni_ops *ops) { int ret; struct rte_kni_device_info dev_info; struct rte_kni *ctx; char intf_name[RTE_KNI_NAMESIZE]; char mz_name[RTE_MEMZONE_NAMESIZE]; const struct rte_memzone *mz; struct rte_kni_memzone_slot *slot = NULL; if (!pktmbuf_pool || !conf || !conf->name[0]) return NULL; /* Check if KNI subsystem has been initialized */ if (kni_memzone_pool.initialized != 1) { RTE_LOG(ERR, KNI, "KNI subsystem has not been initialized. Invoke rte_kni_init() first\n"); return NULL; } /* Get an available slot from the pool */ slot = kni_memzone_pool_alloc(); if (!slot) { RTE_LOG(ERR, KNI, "Cannot allocate more KNI interfaces; increase the number of max_kni_ifaces(current %d) or release unusued ones.\n", kni_memzone_pool.max_ifaces); return NULL; } /* Recover ctx */ ctx = slot->m_ctx->addr; snprintf(intf_name, RTE_KNI_NAMESIZE, "%s", conf->name); if (ctx->in_use) { RTE_LOG(ERR, KNI, "KNI %s is in use\n", ctx->name); return NULL; } memset(ctx, 0, sizeof(struct rte_kni)); if (ops) memcpy(&ctx->ops, ops, sizeof(struct rte_kni_ops)); memset(&dev_info, 0, sizeof(dev_info)); dev_info.bus = conf->addr.bus; dev_info.devid = conf->addr.devid; dev_info.function = conf->addr.function; dev_info.vendor_id = conf->id.vendor_id; dev_info.device_id = conf->id.device_id; dev_info.core_id = conf->core_id; dev_info.force_bind = conf->force_bind; dev_info.group_id = conf->group_id; dev_info.mbuf_size = conf->mbuf_size; snprintf(ctx->name, RTE_KNI_NAMESIZE, "%s", intf_name); snprintf(dev_info.name, RTE_KNI_NAMESIZE, "%s", intf_name); RTE_LOG(INFO, KNI, "pci: %02x:%02x:%02x \t %02x:%02x\n", dev_info.bus, dev_info.devid, dev_info.function, dev_info.vendor_id, dev_info.device_id); /* TX RING */ mz = slot->m_tx_q; ctx->tx_q = mz->addr; kni_fifo_init(ctx->tx_q, KNI_FIFO_COUNT_MAX); dev_info.tx_phys = mz->phys_addr; /* RX RING */ mz = slot->m_rx_q; ctx->rx_q = mz->addr; kni_fifo_init(ctx->rx_q, KNI_FIFO_COUNT_MAX); dev_info.rx_phys = mz->phys_addr; /* ALLOC RING */ mz = slot->m_alloc_q; ctx->alloc_q = mz->addr; kni_fifo_init(ctx->alloc_q, KNI_FIFO_COUNT_MAX); dev_info.alloc_phys = mz->phys_addr; /* FREE RING */ mz = slot->m_free_q; ctx->free_q = mz->addr; kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX); dev_info.free_phys = mz->phys_addr; /* Request RING */ mz = slot->m_req_q; ctx->req_q = mz->addr; kni_fifo_init(ctx->req_q, KNI_FIFO_COUNT_MAX); dev_info.req_phys = mz->phys_addr; /* Response RING */ mz = slot->m_resp_q; ctx->resp_q = mz->addr; kni_fifo_init(ctx->resp_q, KNI_FIFO_COUNT_MAX); dev_info.resp_phys = mz->phys_addr; /* Req/Resp sync mem area */ mz = slot->m_sync_addr; ctx->sync_addr = mz->addr; dev_info.sync_va = mz->addr; dev_info.sync_phys = mz->phys_addr; /* MBUF mempool */ snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_OBJ_NAME, pktmbuf_pool->name); mz = rte_memzone_lookup(mz_name); KNI_MEM_CHECK(mz == NULL); dev_info.mbuf_va = mz->addr; dev_info.mbuf_phys = mz->phys_addr; ctx->pktmbuf_pool = pktmbuf_pool; ctx->group_id = conf->group_id; ctx->slot_id = slot->id; ctx->mbuf_size = conf->mbuf_size; ret = ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info); KNI_MEM_CHECK(ret < 0); ctx->in_use = 1; /* Allocate mbufs and then put them into alloc_q */ kni_allocate_mbufs(ctx); return ctx; kni_fail: if (slot) kni_memzone_pool_release(&kni_memzone_pool.slots[slot->id]); return NULL; } static void kni_free_fifo(struct rte_kni_fifo *fifo) { int ret; struct rte_mbuf *pkt; do { ret = kni_fifo_get(fifo, (void **)&pkt, 1); if (ret) rte_pktmbuf_free(pkt); } while (ret); } int rte_kni_release(struct rte_kni *kni) { struct rte_kni_device_info dev_info; uint32_t slot_id; if (!kni || !kni->in_use) return -1; snprintf(dev_info.name, sizeof(dev_info.name), "%s", kni->name); if (ioctl(kni_fd, RTE_KNI_IOCTL_RELEASE, &dev_info) < 0) { RTE_LOG(ERR, KNI, "Fail to release kni device\n"); return -1; } /* mbufs in all fifo should be released, except request/response */ kni_free_fifo(kni->tx_q); kni_free_fifo(kni->rx_q); kni_free_fifo(kni->alloc_q); kni_free_fifo(kni->free_q); slot_id = kni->slot_id; /* Memset the KNI struct */ memset(kni, 0, sizeof(struct rte_kni)); /* Release memzone */ if (slot_id > kni_memzone_pool.max_ifaces) { rte_panic("KNI pool: corrupted slot ID: %d, max: %d\n", slot_id, kni_memzone_pool.max_ifaces); } kni_memzone_pool_release(&kni_memzone_pool.slots[slot_id]); return 0; } int rte_kni_handle_request(struct rte_kni *kni) { unsigned ret; struct rte_kni_request *req; if (kni == NULL) return -1; /* Get request mbuf */ ret = kni_fifo_get(kni->req_q, (void **)&req, 1); if (ret != 1) return 0; /* It is OK of can not getting the request mbuf */ if (req != kni->sync_addr) { rte_panic("Wrong req pointer %p\n", req); } /* Analyze the request and call the relevant actions for it */ switch (req->req_id) { case RTE_KNI_REQ_CHANGE_MTU: /* Change MTU */ if (kni->ops.change_mtu) req->result = kni->ops.change_mtu(kni->ops.port_id, req->new_mtu); break; case RTE_KNI_REQ_CFG_NETWORK_IF: /* Set network interface up/down */ if (kni->ops.config_network_if) req->result = kni->ops.config_network_if(\ kni->ops.port_id, req->if_up); break; default: RTE_LOG(ERR, KNI, "Unknown request id %u\n", req->req_id); req->result = -EINVAL; break; } /* Construct response mbuf and put it back to resp_q */ ret = kni_fifo_put(kni->resp_q, (void **)&req, 1); if (ret != 1) { RTE_LOG(ERR, KNI, "Fail to put the muf back to resp_q\n"); return -1; /* It is an error of can't putting the mbuf back */ } return 0; } unsigned rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num) { unsigned ret = kni_fifo_put(kni->rx_q, (void **)mbufs, num); /* Get mbufs from free_q and then free them */ kni_free_mbufs(kni); return ret; } unsigned rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num) { unsigned ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num); /* If buffers removed, allocate mbufs and then put them into alloc_q */ if (ret) kni_allocate_mbufs(kni); return ret; } static void kni_free_mbufs(struct rte_kni *kni) { int i, ret; struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM]; ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM); if (likely(ret > 0)) { for (i = 0; i < ret; i++) rte_pktmbuf_free(pkts[i]); } } static void kni_allocate_mbufs(struct rte_kni *kni) { int i, ret; struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM]; RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pool) != offsetof(struct rte_kni_mbuf, pool)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, buf_addr) != offsetof(struct rte_kni_mbuf, buf_addr)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, next) != offsetof(struct rte_kni_mbuf, next)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_off) != offsetof(struct rte_kni_mbuf, data_off)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, data_len) != offsetof(struct rte_kni_mbuf, data_len)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, pkt_len) != offsetof(struct rte_kni_mbuf, pkt_len)); RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) != offsetof(struct rte_kni_mbuf, ol_flags)); /* Check if pktmbuf pool has been configured */ if (kni->pktmbuf_pool == NULL) { RTE_LOG(ERR, KNI, "No valid mempool for allocating mbufs\n"); return; } for (i = 0; i < MAX_MBUF_BURST_NUM; i++) { pkts[i] = rte_pktmbuf_alloc(kni->pktmbuf_pool); if (unlikely(pkts[i] == NULL)) { /* Out of memory */ RTE_LOG(ERR, KNI, "Out of memory\n"); break; } } /* No pkt mbuf alocated */ if (i <= 0) return; ret = kni_fifo_put(kni->alloc_q, (void **)pkts, i); /* Check if any mbufs not put into alloc_q, and then free them */ if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) { int j; for (j = ret; j < i; j++) rte_pktmbuf_free(pkts[j]); } } /* It is deprecated and just for backward compatibility */ uint8_t rte_kni_get_port_id(struct rte_kni *kni) { if (!kni) return ~0x0; return kni->ops.port_id; } struct rte_kni * rte_kni_get(const char *name) { uint32_t i; struct rte_kni_memzone_slot *it; struct rte_kni *kni; /* Note: could be improved perf-wise if necessary */ for (i = 0; i < kni_memzone_pool.max_ifaces; i++) { it = &kni_memzone_pool.slots[i]; if (it->in_use == 0) continue; kni = it->m_ctx->addr; if (strncmp(kni->name, name, RTE_KNI_NAMESIZE) == 0) return kni; } return NULL; } const char * rte_kni_get_name(const struct rte_kni *kni) { return kni->name; } /* * It is deprecated and just for backward compatibility. */ struct rte_kni * rte_kni_info_get(uint8_t port_id) { char name[RTE_MEMZONE_NAMESIZE]; if (port_id >= RTE_MAX_ETHPORTS) return NULL; snprintf(name, RTE_MEMZONE_NAMESIZE, "vEth%u", port_id); return rte_kni_get(name); } static enum kni_ops_status kni_check_request_register(struct rte_kni_ops *ops) { /* check if KNI request ops has been registered*/ if( NULL == ops ) return KNI_REQ_NO_REGISTER; if((NULL == ops->change_mtu) && (NULL == ops->config_network_if)) return KNI_REQ_NO_REGISTER; return KNI_REQ_REGISTERED; } int rte_kni_register_handlers(struct rte_kni *kni,struct rte_kni_ops *ops) { enum kni_ops_status req_status; if (NULL == ops) { RTE_LOG(ERR, KNI, "Invalid KNI request operation.\n"); return -1; } if (NULL == kni) { RTE_LOG(ERR, KNI, "Invalid kni info.\n"); return -1; } req_status = kni_check_request_register(&kni->ops); if ( KNI_REQ_REGISTERED == req_status) { RTE_LOG(ERR, KNI, "The KNI request operation has already registered.\n"); return -1; } memcpy(&kni->ops, ops, sizeof(struct rte_kni_ops)); return 0; } int rte_kni_unregister_handlers(struct rte_kni *kni) { if (NULL == kni) { RTE_LOG(ERR, KNI, "Invalid kni info.\n"); return -1; } kni->ops.change_mtu = NULL; kni->ops.config_network_if = NULL; return 0; } void rte_kni_close(void) { if (kni_fd < 0) return; close(kni_fd); kni_fd = -1; } ================================================ FILE: lib/librte_kni/rte_kni.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_KNI_H_ #define _RTE_KNI_H_ /** * @file * RTE KNI * * The KNI library provides the ability to create and destroy kernel NIC * interfaces that may be used by the RTE application to receive/transmit * packets from/to Linux kernel net interfaces. * * This library provide two APIs to burst receive packets from KNI interfaces, * and burst transmit packets to KNI interfaces. */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct rte_kni; struct rte_mbuf; /** * Structure which has the function pointers for KNI interface. */ struct rte_kni_ops { uint8_t port_id; /* Port ID */ /* Pointer to function of changing MTU */ int (*change_mtu)(uint8_t port_id, unsigned new_mtu); /* Pointer to function of configuring network interface */ int (*config_network_if)(uint8_t port_id, uint8_t if_up); }; /** * Structure for configuring KNI device. */ struct rte_kni_conf { /* * KNI name which will be used in relevant network device. * Let the name as short as possible, as it will be part of * memzone name. */ char name[RTE_KNI_NAMESIZE]; uint32_t core_id; /* Core ID to bind kernel thread on */ uint16_t group_id; /* Group ID */ unsigned mbuf_size; /* mbuf size */ struct rte_pci_addr addr; struct rte_pci_id id; uint8_t force_bind : 1; /* Flag to bind kernel thread */ }; /** * Initialize and preallocate KNI subsystem * * This function is to be executed on the MASTER lcore only, after EAL * initialization and before any KNI interface is attempted to be * allocated * * @param max_kni_ifaces * The maximum number of KNI interfaces that can coexist concurrently */ extern void rte_kni_init(unsigned int max_kni_ifaces); /** * Allocate KNI interface according to the port id, mbuf size, mbuf pool, * configurations and callbacks for kernel requests.The KNI interface created * in the kernel space is the net interface the traditional Linux application * talking to. * * The rte_kni_alloc shall not be called before rte_kni_init() has been * called. rte_kni_alloc is thread safe. * * @param pktmbuf_pool * The mempool for allocting mbufs for packets. * @param conf * The pointer to the configurations of the KNI device. * @param ops * The pointer to the callbacks for the KNI kernel requests. * * @return * - The pointer to the context of a KNI interface. * - NULL indicate error. */ extern struct rte_kni *rte_kni_alloc(struct rte_mempool *pktmbuf_pool, const struct rte_kni_conf *conf, struct rte_kni_ops *ops); /** * It create a KNI device for specific port. * * Note: It is deprecated and just for backward compatibility. * * @param port_id * Port ID. * @param mbuf_size * mbuf size. * @param pktmbuf_pool * The mempool for allocting mbufs for packets. * @param ops * The pointer to the callbacks for the KNI kernel requests. * * @return * - The pointer to the context of a KNI interface. * - NULL indicate error. */ extern struct rte_kni *rte_kni_create(uint8_t port_id, unsigned mbuf_size, struct rte_mempool *pktmbuf_pool, struct rte_kni_ops *ops) \ __attribute__ ((deprecated)); /** * Release KNI interface according to the context. It will also release the * paired KNI interface in kernel space. All processing on the specific KNI * context need to be stopped before calling this interface. * * rte_kni_release is thread safe. * * @param kni * The pointer to the context of an existent KNI interface. * * @return * - 0 indicates success. * - negative value indicates failure. */ extern int rte_kni_release(struct rte_kni *kni); /** * It is used to handle the request mbufs sent from kernel space. * Then analyzes it and calls the specific actions for the specific requests. * Finally constructs the response mbuf and puts it back to the resp_q. * * @param kni * The pointer to the context of an existent KNI interface. * * @return * - 0 * - negative value indicates failure. */ extern int rte_kni_handle_request(struct rte_kni *kni); /** * Retrieve a burst of packets from a KNI interface. The retrieved packets are * stored in rte_mbuf structures whose pointers are supplied in the array of * mbufs, and the maximum number is indicated by num. It handles the freeing of * the mbufs in the free queue of KNI interface. * * @param kni * The KNI interface context. * @param mbufs * The array to store the pointers of mbufs. * @param num * The maximum number per burst. * * @return * The actual number of packets retrieved. */ extern unsigned rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num); /** * Send a burst of packets to a KNI interface. The packets to be sent out are * stored in rte_mbuf structures whose pointers are supplied in the array of * mbufs, and the maximum number is indicated by num. It handles allocating * the mbufs for KNI interface alloc queue. * * @param kni * The KNI interface context. * @param mbufs * The array to store the pointers of mbufs. * @param num * The maximum number per burst. * * @return * The actual number of packets sent. */ extern unsigned rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num); /** * Get the port id from KNI interface. * * Note: It is deprecated and just for backward compatibility. * * @param kni * The KNI interface context. * * @return * On success: The port id. * On failure: ~0x0 */ extern uint8_t rte_kni_get_port_id(struct rte_kni *kni) \ __attribute__ ((deprecated)); /** * Get the KNI context of its name. * * @param name * pointer to the KNI device name. * * @return * On success: Pointer to KNI interface. * On failure: NULL. */ extern struct rte_kni *rte_kni_get(const char *name); /** * Get the name given to a KNI device * * @param kni * The KNI instance to query * @return * The pointer to the KNI name */ extern const char *rte_kni_get_name(const struct rte_kni *kni); /** * Get the KNI context of the specific port. * * Note: It is deprecated and just for backward compatibility. * * @param port_id * the port id. * * @return * On success: Pointer to KNI interface. * On failure: NULL */ extern struct rte_kni *rte_kni_info_get(uint8_t port_id) \ __attribute__ ((deprecated)); /** * Register KNI request handling for a specified port,and it can * be called by master process or slave process. * * @param kni * pointer to struct rte_kni. * @param ops * ponter to struct rte_kni_ops. * * @return * On success: 0 * On failure: -1 */ extern int rte_kni_register_handlers(struct rte_kni *kni, struct rte_kni_ops *ops); /** * Unregister KNI request handling for a specified port. * * @param kni * pointer to struct rte_kni. * * @return * On success: 0 * On failure: -1 */ extern int rte_kni_unregister_handlers(struct rte_kni *kni); /** * Close KNI device. */ extern void rte_kni_close(void); #ifdef __cplusplus } #endif #endif /* _RTE_KNI_H_ */ ================================================ FILE: lib/librte_kni/rte_kni_fifo.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Initializes the kni fifo structure */ static void kni_fifo_init(struct rte_kni_fifo *fifo, unsigned size) { /* Ensure size is power of 2 */ if (size & (size - 1)) rte_panic("KNI fifo size must be power of 2\n"); fifo->write = 0; fifo->read = 0; fifo->len = size; fifo->elem_size = sizeof(void *); } /** * Adds num elements into the fifo. Return the number actually written */ static inline unsigned kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num) { unsigned i = 0; unsigned fifo_write = fifo->write; unsigned fifo_read = fifo->read; unsigned new_write = fifo_write; for (i = 0; i < num; i++) { new_write = (new_write + 1) & (fifo->len - 1); if (new_write == fifo_read) break; fifo->buffer[fifo_write] = data[i]; fifo_write = new_write; } fifo->write = fifo_write; return i; } /** * Get up to num elements from the fifo. Return the number actully read */ static inline unsigned kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num) { unsigned i = 0; unsigned new_read = fifo->read; unsigned fifo_write = fifo->write; for (i = 0; i < num; i++) { if (new_read == fifo_write) break; data[i] = fifo->buffer[new_read]; new_read = (new_read + 1) & (fifo->len - 1); } fifo->read = new_read; return i; } ================================================ FILE: lib/librte_kvargs/Makefile ================================================ # BSD LICENSE # # Copyright 2014 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # - Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_kvargs.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_kvargs_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := rte_kvargs.c # install includes INCS := rte_kvargs.h SYMLINK-$(CONFIG_RTE_LIBRTE_KVARGS)-include := $(INCS) # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_kvargs/rte_kvargs.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "rte_kvargs.h" /* * Receive a string with a list of arguments following the pattern * key=value;key=value;... and insert them into the list. * strtok() is used so the params string will be copied to be modified. */ static int rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params) { unsigned i; char *str; char *ctx1 = NULL; char *ctx2 = NULL; /* Copy the const char *params to a modifiable string * to pass to rte_strsplit */ kvlist->str = strdup(params); if (kvlist->str == NULL) { RTE_LOG(ERR, PMD, "Cannot parse arguments: not enough memory\n"); return -1; } /* browse each key/value pair and add it in kvlist */ str = kvlist->str; while ((str = strtok_r(str, RTE_KVARGS_PAIRS_DELIM, &ctx1)) != NULL) { i = kvlist->count; if (i >= RTE_KVARGS_MAX) { RTE_LOG(ERR, PMD, "Cannot parse arguments: list full\n"); return -1; } kvlist->pairs[i].key = strtok_r(str, RTE_KVARGS_KV_DELIM, &ctx2); kvlist->pairs[i].value = strtok_r(NULL, RTE_KVARGS_KV_DELIM, &ctx2); if (kvlist->pairs[i].key == NULL || kvlist->pairs[i].value == NULL) { RTE_LOG(ERR, PMD, "Cannot parse arguments: wrong key or value\n" "params=<%s>\n", params); return -1; } kvlist->count++; str = NULL; } return 0; } /* * Determine whether a key is valid or not by looking * into a list of valid keys. */ static int is_valid_key(const char *valid[], const char *key_match) { const char **valid_ptr; for (valid_ptr = valid; *valid_ptr != NULL; valid_ptr++) { if (strcmp(key_match, *valid_ptr) == 0) return 1; } return 0; } /* * Determine whether all keys are valid or not by looking * into a list of valid keys. */ static int check_for_valid_keys(struct rte_kvargs *kvlist, const char *valid[]) { unsigned i, ret; struct rte_kvargs_pair *pair; for (i = 0; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; ret = is_valid_key(valid, pair->key); if (!ret) { RTE_LOG(ERR, PMD, "Error parsing device, invalid key <%s>\n", pair->key); return -1; } } return 0; } /* * Return the number of times a given arg_name exists in the key/value list. * E.g. given a list = { rx = 0, rx = 1, tx = 2 } the number of args for * arg "rx" will be 2. */ unsigned rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match) { const struct rte_kvargs_pair *pair; unsigned i, ret; ret = 0; for (i = 0; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; if (key_match == NULL || strcmp(pair->key, key_match) == 0) ret++; } return ret; } /* * For each matching key, call the given handler function. */ int rte_kvargs_process(const struct rte_kvargs *kvlist, const char *key_match, arg_handler_t handler, void *opaque_arg) { const struct rte_kvargs_pair *pair; unsigned i; for (i = 0; i < kvlist->count; i++) { pair = &kvlist->pairs[i]; if (key_match == NULL || strcmp(pair->key, key_match) == 0) { if ((*handler)(pair->key, pair->value, opaque_arg) < 0) return -1; } } return 0; } /* free the rte_kvargs structure */ void rte_kvargs_free(struct rte_kvargs *kvlist) { if (!kvlist) return; if (kvlist->str != NULL) free(kvlist->str); free(kvlist); } /* * Parse the arguments "key=value;key=value;..." string and return * an allocated structure that contains a key/value list. Also * check if only valid keys were used. */ struct rte_kvargs * rte_kvargs_parse(const char *args, const char *valid_keys[]) { struct rte_kvargs *kvlist; kvlist = malloc(sizeof(*kvlist)); if (kvlist == NULL) return NULL; memset(kvlist, 0, sizeof(*kvlist)); if (rte_kvargs_tokenize(kvlist, args) < 0) { rte_kvargs_free(kvlist); return NULL; } if (valid_keys != NULL && check_for_valid_keys(kvlist, valid_keys) < 0) { rte_kvargs_free(kvlist); return NULL; } return kvlist; } ================================================ FILE: lib/librte_kvargs/rte_kvargs.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. * Copyright(c) 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_KVARGS_H_ #define _RTE_KVARGS_H_ /** * @file * RTE Argument parsing * * This module can be used to parse arguments whose format is * key1=value1,key2=value2,key3=value3,... * * The same key can appear several times with the same or a different * value. Indeed, the arguments are stored as a list of key/values * associations and not as a dictionary. * * This file provides some helpers that are especially used by virtual * ethernet devices at initialization for arguments parsing. */ #ifdef __cplusplus extern "C" { #endif /** Maximum number of key/value associations */ #define RTE_KVARGS_MAX 32 /** separator character used between each pair */ #define RTE_KVARGS_PAIRS_DELIM "," /** separator character used between key and value */ #define RTE_KVARGS_KV_DELIM "=" /** Type of callback function used by rte_kvargs_process() */ typedef int (*arg_handler_t)(const char *key, const char *value, void *opaque); /** A key/value association */ struct rte_kvargs_pair { char *key; /**< the name (key) of the association */ char *value; /**< the value associated to that key */ }; /** Store a list of key/value associations */ struct rte_kvargs { char *str; /**< copy of the argument string */ unsigned count; /**< number of entries in the list */ struct rte_kvargs_pair pairs[RTE_KVARGS_MAX]; /**< list of key/values */ }; /** * Allocate a rte_kvargs and store key/value associations from a string * * The function allocates and fills a rte_kvargs structure from a given * string whose format is key1=value1,key2=value2,... * * The structure can be freed with rte_kvargs_free(). * * @param args * The input string containing the key/value associations * @param valid_keys * A list of valid keys (table of const char *, the last must be NULL). * This argument is ignored if NULL * * @return * - A pointer to an allocated rte_kvargs structure on success * - NULL on error */ struct rte_kvargs *rte_kvargs_parse(const char *args, const char *valid_keys[]); /** * Free a rte_kvargs structure * * Free a rte_kvargs structure previously allocated with * rte_kvargs_parse(). * * @param kvlist * The rte_kvargs structure */ void rte_kvargs_free(struct rte_kvargs *kvlist); /** * Call a handler function for each key/value matching the key * * For each key/value association that matches the given key, calls the * handler function with the for a given arg_name passing the value on the * dictionary for that key and a given extra argument. If *kvlist* is NULL * function does nothing. * * @param kvlist * The rte_kvargs structure * @param key_match * The key on which the handler should be called, or NULL to process handler * on all associations * @param handler * The function to call for each matching key * @param opaque_arg * A pointer passed unchanged to the handler * * @return * - 0 on success * - Negative on error */ int rte_kvargs_process(const struct rte_kvargs *kvlist, const char *key_match, arg_handler_t handler, void *opaque_arg); /** * Count the number of associations matching the given key * * @param kvlist * The rte_kvargs structure * @param key_match * The key that should match, or NULL to count all associations * @return * The number of entries */ unsigned rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_lpm/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_lpm.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_lpm_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_LPM) := rte_lpm.c rte_lpm6.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include := rte_lpm.h rte_lpm6.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_LPM) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_lpm/rte_lpm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include /* for definition of RTE_CACHE_LINE_SIZE */ #include #include #include #include #include #include #include #include #include #include "rte_lpm.h" TAILQ_HEAD(rte_lpm_list, rte_tailq_entry); static struct rte_tailq_elem rte_lpm_tailq = { .name = "RTE_LPM", }; EAL_REGISTER_TAILQ(rte_lpm_tailq) #define MAX_DEPTH_TBL24 24 enum valid_flag { INVALID = 0, VALID }; /* Macro to enable/disable run-time checks. */ #if defined(RTE_LIBRTE_LPM_DEBUG) #include #define VERIFY_DEPTH(depth) do { \ if ((depth == 0) || (depth > RTE_LPM_MAX_DEPTH)) \ rte_panic("LPM: Invalid depth (%u) at line %d", \ (unsigned)(depth), __LINE__); \ } while (0) #else #define VERIFY_DEPTH(depth) #endif /* * Converts a given depth value to its corresponding mask value. * * depth (IN) : range = 1 - 32 * mask (OUT) : 32bit mask */ static uint32_t __attribute__((pure)) depth_to_mask(uint8_t depth) { VERIFY_DEPTH(depth); /* To calculate a mask start with a 1 on the left hand side and right * shift while populating the left hand side with 1's */ return (int)0x80000000 >> (depth - 1); } /* * Converts given depth value to its corresponding range value. */ static inline uint32_t __attribute__((pure)) depth_to_range(uint8_t depth) { VERIFY_DEPTH(depth); /* * Calculate tbl24 range. (Note: 2^depth = 1 << depth) */ if (depth <= MAX_DEPTH_TBL24) return 1 << (MAX_DEPTH_TBL24 - depth); /* Else if depth is greater than 24 */ return (1 << (RTE_LPM_MAX_DEPTH - depth)); } /* * Find an existing lpm table and return a pointer to it. */ struct rte_lpm * rte_lpm_find_existing(const char *name) { struct rte_lpm *l = NULL; struct rte_tailq_entry *te; struct rte_lpm_list *lpm_list; lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, lpm_list, next) { l = (struct rte_lpm *) te->data; if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return l; } /* * Allocates memory for LPM object */ struct rte_lpm * rte_lpm_create(const char *name, int socket_id, int max_rules, __rte_unused int flags) { char mem_name[RTE_LPM_NAMESIZE]; struct rte_lpm *lpm = NULL; struct rte_tailq_entry *te; uint32_t mem_size; struct rte_lpm_list *lpm_list; lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list); RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl24_entry) != 2); RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl8_entry) != 2); /* Check user arguments. */ if ((name == NULL) || (socket_id < -1) || (max_rules == 0)){ rte_errno = EINVAL; return NULL; } snprintf(mem_name, sizeof(mem_name), "LPM_%s", name); /* Determine the amount of memory to allocate. */ mem_size = sizeof(*lpm) + (sizeof(lpm->rules_tbl[0]) * max_rules); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* guarantee there's no existing */ TAILQ_FOREACH(te, lpm_list, next) { lpm = (struct rte_lpm *) te->data; if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0) break; } if (te != NULL) goto exit; /* allocate tailq entry */ te = rte_zmalloc("LPM_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, LPM, "Failed to allocate tailq entry\n"); goto exit; } /* Allocate memory to store the LPM data structures. */ lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size, RTE_CACHE_LINE_SIZE, socket_id); if (lpm == NULL) { RTE_LOG(ERR, LPM, "LPM memory allocation failed\n"); rte_free(te); goto exit; } /* Save user arguments. */ lpm->max_rules = max_rules; snprintf(lpm->name, sizeof(lpm->name), "%s", name); te->data = (void *) lpm; TAILQ_INSERT_TAIL(lpm_list, te, next); exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return lpm; } /* * Deallocates memory for given LPM table. */ void rte_lpm_free(struct rte_lpm *lpm) { struct rte_lpm_list *lpm_list; struct rte_tailq_entry *te; /* Check user arguments. */ if (lpm == NULL) return; lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find our tailq entry */ TAILQ_FOREACH(te, lpm_list, next) { if (te->data == (void *) lpm) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(lpm_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(lpm); rte_free(te); } /* * Adds a rule to the rule table. * * NOTE: The rule table is split into 32 groups. Each group contains rules that * apply to a specific prefix depth (i.e. group 1 contains rules that apply to * prefixes with a depth of 1 etc.). In the following code (depth - 1) is used * to refer to depth 1 because even though the depth range is 1 - 32, depths * are stored in the rule table from 0 - 31. * NOTE: Valid range for depth parameter is 1 .. 32 inclusive. */ static inline int32_t rule_add(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, uint8_t next_hop) { uint32_t rule_gindex, rule_index, last_rule; int i; VERIFY_DEPTH(depth); /* Scan through rule group to see if rule already exists. */ if (lpm->rule_info[depth - 1].used_rules > 0) { /* rule_gindex stands for rule group index. */ rule_gindex = lpm->rule_info[depth - 1].first_rule; /* Initialise rule_index to point to start of rule group. */ rule_index = rule_gindex; /* Last rule = Last used rule in this rule group. */ last_rule = rule_gindex + lpm->rule_info[depth - 1].used_rules; for (; rule_index < last_rule; rule_index++) { /* If rule already exists update its next_hop and return. */ if (lpm->rules_tbl[rule_index].ip == ip_masked) { lpm->rules_tbl[rule_index].next_hop = next_hop; return rule_index; } } if (rule_index == lpm->max_rules) return -ENOSPC; } else { /* Calculate the position in which the rule will be stored. */ rule_index = 0; for (i = depth - 1; i > 0; i--) { if (lpm->rule_info[i - 1].used_rules > 0) { rule_index = lpm->rule_info[i - 1].first_rule + lpm->rule_info[i - 1].used_rules; break; } } if (rule_index == lpm->max_rules) return -ENOSPC; lpm->rule_info[depth - 1].first_rule = rule_index; } /* Make room for the new rule in the array. */ for (i = RTE_LPM_MAX_DEPTH; i > depth; i--) { if (lpm->rule_info[i - 1].first_rule + lpm->rule_info[i - 1].used_rules == lpm->max_rules) return -ENOSPC; if (lpm->rule_info[i - 1].used_rules > 0) { lpm->rules_tbl[lpm->rule_info[i - 1].first_rule + lpm->rule_info[i - 1].used_rules] = lpm->rules_tbl[lpm->rule_info[i - 1].first_rule]; lpm->rule_info[i - 1].first_rule++; } } /* Add the new rule. */ lpm->rules_tbl[rule_index].ip = ip_masked; lpm->rules_tbl[rule_index].next_hop = next_hop; /* Increment the used rules counter for this rule group. */ lpm->rule_info[depth - 1].used_rules++; return rule_index; } /* * Delete a rule from the rule table. * NOTE: Valid range for depth parameter is 1 .. 32 inclusive. */ static inline void rule_delete(struct rte_lpm *lpm, int32_t rule_index, uint8_t depth) { int i; VERIFY_DEPTH(depth); lpm->rules_tbl[rule_index] = lpm->rules_tbl[lpm->rule_info[depth - 1].first_rule + lpm->rule_info[depth - 1].used_rules - 1]; for (i = depth; i < RTE_LPM_MAX_DEPTH; i++) { if (lpm->rule_info[i].used_rules > 0) { lpm->rules_tbl[lpm->rule_info[i].first_rule - 1] = lpm->rules_tbl[lpm->rule_info[i].first_rule + lpm->rule_info[i].used_rules - 1]; lpm->rule_info[i].first_rule--; } } lpm->rule_info[depth - 1].used_rules--; } /* * Finds a rule in rule table. * NOTE: Valid range for depth parameter is 1 .. 32 inclusive. */ static inline int32_t rule_find(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth) { uint32_t rule_gindex, last_rule, rule_index; VERIFY_DEPTH(depth); rule_gindex = lpm->rule_info[depth - 1].first_rule; last_rule = rule_gindex + lpm->rule_info[depth - 1].used_rules; /* Scan used rules at given depth to find rule. */ for (rule_index = rule_gindex; rule_index < last_rule; rule_index++) { /* If rule is found return the rule index. */ if (lpm->rules_tbl[rule_index].ip == ip_masked) return rule_index; } /* If rule is not found return -EINVAL. */ return -EINVAL; } /* * Find, clean and allocate a tbl8. */ static inline int32_t tbl8_alloc(struct rte_lpm_tbl8_entry *tbl8) { uint32_t tbl8_gindex; /* tbl8 group index. */ struct rte_lpm_tbl8_entry *tbl8_entry; /* Scan through tbl8 to find a free (i.e. INVALID) tbl8 group. */ for (tbl8_gindex = 0; tbl8_gindex < RTE_LPM_TBL8_NUM_GROUPS; tbl8_gindex++) { tbl8_entry = &tbl8[tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES]; /* If a free tbl8 group is found clean it and set as VALID. */ if (!tbl8_entry->valid_group) { memset(&tbl8_entry[0], 0, RTE_LPM_TBL8_GROUP_NUM_ENTRIES * sizeof(tbl8_entry[0])); tbl8_entry->valid_group = VALID; /* Return group index for allocated tbl8 group. */ return tbl8_gindex; } } /* If there are no tbl8 groups free then return error. */ return -ENOSPC; } static inline void tbl8_free(struct rte_lpm_tbl8_entry *tbl8, uint32_t tbl8_group_start) { /* Set tbl8 group invalid*/ tbl8[tbl8_group_start].valid_group = INVALID; } static inline int32_t add_depth_small(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop) { uint32_t tbl24_index, tbl24_range, tbl8_index, tbl8_group_end, i, j; /* Calculate the index into Table24. */ tbl24_index = ip >> 8; tbl24_range = depth_to_range(depth); for (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) { /* * For invalid OR valid and non-extended tbl 24 entries set * entry. */ if (!lpm->tbl24[i].valid || (lpm->tbl24[i].ext_entry == 0 && lpm->tbl24[i].depth <= depth)) { struct rte_lpm_tbl24_entry new_tbl24_entry = { { .next_hop = next_hop, }, .valid = VALID, .ext_entry = 0, .depth = depth, }; /* Setting tbl24 entry in one go to avoid race * conditions */ lpm->tbl24[i] = new_tbl24_entry; continue; } if (lpm->tbl24[i].ext_entry == 1) { /* If tbl24 entry is valid and extended calculate the * index into tbl8. */ tbl8_index = lpm->tbl24[i].tbl8_gindex * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl8_group_end = tbl8_index + RTE_LPM_TBL8_GROUP_NUM_ENTRIES; for (j = tbl8_index; j < tbl8_group_end; j++) { if (!lpm->tbl8[j].valid || lpm->tbl8[j].depth <= depth) { struct rte_lpm_tbl8_entry new_tbl8_entry = { .valid = VALID, .valid_group = VALID, .depth = depth, .next_hop = next_hop, }; /* * Setting tbl8 entry in one go to avoid * race conditions */ lpm->tbl8[j] = new_tbl8_entry; continue; } } } } return 0; } static inline int32_t add_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, uint8_t next_hop) { uint32_t tbl24_index; int32_t tbl8_group_index, tbl8_group_start, tbl8_group_end, tbl8_index, tbl8_range, i; tbl24_index = (ip_masked >> 8); tbl8_range = depth_to_range(depth); if (!lpm->tbl24[tbl24_index].valid) { /* Search for a free tbl8 group. */ tbl8_group_index = tbl8_alloc(lpm->tbl8); /* Check tbl8 allocation was successful. */ if (tbl8_group_index < 0) { return tbl8_group_index; } /* Find index into tbl8 and range. */ tbl8_index = (tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES) + (ip_masked & 0xFF); /* Set tbl8 entry. */ for (i = tbl8_index; i < (tbl8_index + tbl8_range); i++) { lpm->tbl8[i].depth = depth; lpm->tbl8[i].next_hop = next_hop; lpm->tbl8[i].valid = VALID; } /* * Update tbl24 entry to point to new tbl8 entry. Note: The * ext_flag and tbl8_index need to be updated simultaneously, * so assign whole structure in one go */ struct rte_lpm_tbl24_entry new_tbl24_entry = { { .tbl8_gindex = (uint8_t)tbl8_group_index, }, .valid = VALID, .ext_entry = 1, .depth = 0, }; lpm->tbl24[tbl24_index] = new_tbl24_entry; }/* If valid entry but not extended calculate the index into Table8. */ else if (lpm->tbl24[tbl24_index].ext_entry == 0) { /* Search for free tbl8 group. */ tbl8_group_index = tbl8_alloc(lpm->tbl8); if (tbl8_group_index < 0) { return tbl8_group_index; } tbl8_group_start = tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl8_group_end = tbl8_group_start + RTE_LPM_TBL8_GROUP_NUM_ENTRIES; /* Populate new tbl8 with tbl24 value. */ for (i = tbl8_group_start; i < tbl8_group_end; i++) { lpm->tbl8[i].valid = VALID; lpm->tbl8[i].depth = lpm->tbl24[tbl24_index].depth; lpm->tbl8[i].next_hop = lpm->tbl24[tbl24_index].next_hop; } tbl8_index = tbl8_group_start + (ip_masked & 0xFF); /* Insert new rule into the tbl8 entry. */ for (i = tbl8_index; i < tbl8_index + tbl8_range; i++) { if (!lpm->tbl8[i].valid || lpm->tbl8[i].depth <= depth) { lpm->tbl8[i].valid = VALID; lpm->tbl8[i].depth = depth; lpm->tbl8[i].next_hop = next_hop; continue; } } /* * Update tbl24 entry to point to new tbl8 entry. Note: The * ext_flag and tbl8_index need to be updated simultaneously, * so assign whole structure in one go. */ struct rte_lpm_tbl24_entry new_tbl24_entry = { { .tbl8_gindex = (uint8_t)tbl8_group_index, }, .valid = VALID, .ext_entry = 1, .depth = 0, }; lpm->tbl24[tbl24_index] = new_tbl24_entry; } else { /* * If it is valid, extended entry calculate the index into tbl8. */ tbl8_group_index = lpm->tbl24[tbl24_index].tbl8_gindex; tbl8_group_start = tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl8_index = tbl8_group_start + (ip_masked & 0xFF); for (i = tbl8_index; i < (tbl8_index + tbl8_range); i++) { if (!lpm->tbl8[i].valid || lpm->tbl8[i].depth <= depth) { struct rte_lpm_tbl8_entry new_tbl8_entry = { .valid = VALID, .depth = depth, .next_hop = next_hop, .valid_group = lpm->tbl8[i].valid_group, }; /* * Setting tbl8 entry in one go to avoid race * condition */ lpm->tbl8[i] = new_tbl8_entry; continue; } } } return 0; } /* * Add a route */ int rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop) { int32_t rule_index, status = 0; uint32_t ip_masked; /* Check user arguments. */ if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM_MAX_DEPTH)) return -EINVAL; ip_masked = ip & depth_to_mask(depth); /* Add the rule to the rule table. */ rule_index = rule_add(lpm, ip_masked, depth, next_hop); /* If the is no space available for new rule return error. */ if (rule_index < 0) { return rule_index; } if (depth <= MAX_DEPTH_TBL24) { status = add_depth_small(lpm, ip_masked, depth, next_hop); } else { /* If depth > RTE_LPM_MAX_DEPTH_TBL24 */ status = add_depth_big(lpm, ip_masked, depth, next_hop); /* * If add fails due to exhaustion of tbl8 extensions delete * rule that was added to rule table. */ if (status < 0) { rule_delete(lpm, rule_index, depth); return status; } } return 0; } /* * Look for a rule in the high-level rules table */ int rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t *next_hop) { uint32_t ip_masked; int32_t rule_index; /* Check user arguments. */ if ((lpm == NULL) || (next_hop == NULL) || (depth < 1) || (depth > RTE_LPM_MAX_DEPTH)) return -EINVAL; /* Look for the rule using rule_find. */ ip_masked = ip & depth_to_mask(depth); rule_index = rule_find(lpm, ip_masked, depth); if (rule_index >= 0) { *next_hop = lpm->rules_tbl[rule_index].next_hop; return 1; } /* If rule is not found return 0. */ return 0; } static inline int32_t find_previous_rule(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t *sub_rule_depth) { int32_t rule_index; uint32_t ip_masked; uint8_t prev_depth; for (prev_depth = (uint8_t)(depth - 1); prev_depth > 0; prev_depth--) { ip_masked = ip & depth_to_mask(prev_depth); rule_index = rule_find(lpm, ip_masked, prev_depth); if (rule_index >= 0) { *sub_rule_depth = prev_depth; return rule_index; } } return -1; } static inline int32_t delete_depth_small(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, int32_t sub_rule_index, uint8_t sub_rule_depth) { uint32_t tbl24_range, tbl24_index, tbl8_group_index, tbl8_index, i, j; /* Calculate the range and index into Table24. */ tbl24_range = depth_to_range(depth); tbl24_index = (ip_masked >> 8); /* * Firstly check the sub_rule_index. A -1 indicates no replacement rule * and a positive number indicates a sub_rule_index. */ if (sub_rule_index < 0) { /* * If no replacement rule exists then invalidate entries * associated with this rule. */ for (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) { if (lpm->tbl24[i].ext_entry == 0 && lpm->tbl24[i].depth <= depth ) { lpm->tbl24[i].valid = INVALID; } else { /* * If TBL24 entry is extended, then there has * to be a rule with depth >= 25 in the * associated TBL8 group. */ tbl8_group_index = lpm->tbl24[i].tbl8_gindex; tbl8_index = tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; for (j = tbl8_index; j < (tbl8_index + RTE_LPM_TBL8_GROUP_NUM_ENTRIES); j++) { if (lpm->tbl8[j].depth <= depth) lpm->tbl8[j].valid = INVALID; } } } } else { /* * If a replacement rule exists then modify entries * associated with this rule. */ struct rte_lpm_tbl24_entry new_tbl24_entry = { {.next_hop = lpm->rules_tbl[sub_rule_index].next_hop,}, .valid = VALID, .ext_entry = 0, .depth = sub_rule_depth, }; struct rte_lpm_tbl8_entry new_tbl8_entry = { .valid = VALID, .depth = sub_rule_depth, .next_hop = lpm->rules_tbl [sub_rule_index].next_hop, }; for (i = tbl24_index; i < (tbl24_index + tbl24_range); i++) { if (lpm->tbl24[i].ext_entry == 0 && lpm->tbl24[i].depth <= depth ) { lpm->tbl24[i] = new_tbl24_entry; } else { /* * If TBL24 entry is extended, then there has * to be a rule with depth >= 25 in the * associated TBL8 group. */ tbl8_group_index = lpm->tbl24[i].tbl8_gindex; tbl8_index = tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; for (j = tbl8_index; j < (tbl8_index + RTE_LPM_TBL8_GROUP_NUM_ENTRIES); j++) { if (lpm->tbl8[j].depth <= depth) lpm->tbl8[j] = new_tbl8_entry; } } } } return 0; } /* * Checks if table 8 group can be recycled. * * Return of -EEXIST means tbl8 is in use and thus can not be recycled. * Return of -EINVAL means tbl8 is empty and thus can be recycled * Return of value > -1 means tbl8 is in use but has all the same values and * thus can be recycled */ static inline int32_t tbl8_recycle_check(struct rte_lpm_tbl8_entry *tbl8, uint32_t tbl8_group_start) { uint32_t tbl8_group_end, i; tbl8_group_end = tbl8_group_start + RTE_LPM_TBL8_GROUP_NUM_ENTRIES; /* * Check the first entry of the given tbl8. If it is invalid we know * this tbl8 does not contain any rule with a depth < RTE_LPM_MAX_DEPTH * (As they would affect all entries in a tbl8) and thus this table * can not be recycled. */ if (tbl8[tbl8_group_start].valid) { /* * If first entry is valid check if the depth is less than 24 * and if so check the rest of the entries to verify that they * are all of this depth. */ if (tbl8[tbl8_group_start].depth < MAX_DEPTH_TBL24) { for (i = (tbl8_group_start + 1); i < tbl8_group_end; i++) { if (tbl8[i].depth != tbl8[tbl8_group_start].depth) { return -EEXIST; } } /* If all entries are the same return the tb8 index */ return tbl8_group_start; } return -EEXIST; } /* * If the first entry is invalid check if the rest of the entries in * the tbl8 are invalid. */ for (i = (tbl8_group_start + 1); i < tbl8_group_end; i++) { if (tbl8[i].valid) return -EEXIST; } /* If no valid entries are found then return -EINVAL. */ return -EINVAL; } static inline int32_t delete_depth_big(struct rte_lpm *lpm, uint32_t ip_masked, uint8_t depth, int32_t sub_rule_index, uint8_t sub_rule_depth) { uint32_t tbl24_index, tbl8_group_index, tbl8_group_start, tbl8_index, tbl8_range, i; int32_t tbl8_recycle_index; /* * Calculate the index into tbl24 and range. Note: All depths larger * than MAX_DEPTH_TBL24 are associated with only one tbl24 entry. */ tbl24_index = ip_masked >> 8; /* Calculate the index into tbl8 and range. */ tbl8_group_index = lpm->tbl24[tbl24_index].tbl8_gindex; tbl8_group_start = tbl8_group_index * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl8_index = tbl8_group_start + (ip_masked & 0xFF); tbl8_range = depth_to_range(depth); if (sub_rule_index < 0) { /* * Loop through the range of entries on tbl8 for which the * rule_to_delete must be removed or modified. */ for (i = tbl8_index; i < (tbl8_index + tbl8_range); i++) { if (lpm->tbl8[i].depth <= depth) lpm->tbl8[i].valid = INVALID; } } else { /* Set new tbl8 entry. */ struct rte_lpm_tbl8_entry new_tbl8_entry = { .valid = VALID, .depth = sub_rule_depth, .valid_group = lpm->tbl8[tbl8_group_start].valid_group, .next_hop = lpm->rules_tbl[sub_rule_index].next_hop, }; /* * Loop through the range of entries on tbl8 for which the * rule_to_delete must be modified. */ for (i = tbl8_index; i < (tbl8_index + tbl8_range); i++) { if (lpm->tbl8[i].depth <= depth) lpm->tbl8[i] = new_tbl8_entry; } } /* * Check if there are any valid entries in this tbl8 group. If all * tbl8 entries are invalid we can free the tbl8 and invalidate the * associated tbl24 entry. */ tbl8_recycle_index = tbl8_recycle_check(lpm->tbl8, tbl8_group_start); if (tbl8_recycle_index == -EINVAL){ /* Set tbl24 before freeing tbl8 to avoid race condition. */ lpm->tbl24[tbl24_index].valid = 0; tbl8_free(lpm->tbl8, tbl8_group_start); } else if (tbl8_recycle_index > -1) { /* Update tbl24 entry. */ struct rte_lpm_tbl24_entry new_tbl24_entry = { { .next_hop = lpm->tbl8[tbl8_recycle_index].next_hop, }, .valid = VALID, .ext_entry = 0, .depth = lpm->tbl8[tbl8_recycle_index].depth, }; /* Set tbl24 before freeing tbl8 to avoid race condition. */ lpm->tbl24[tbl24_index] = new_tbl24_entry; tbl8_free(lpm->tbl8, tbl8_group_start); } return 0; } /* * Deletes a rule */ int rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth) { int32_t rule_to_delete_index, sub_rule_index; uint32_t ip_masked; uint8_t sub_rule_depth; /* * Check input arguments. Note: IP must be a positive integer of 32 * bits in length therefore it need not be checked. */ if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM_MAX_DEPTH)) { return -EINVAL; } ip_masked = ip & depth_to_mask(depth); /* * Find the index of the input rule, that needs to be deleted, in the * rule table. */ rule_to_delete_index = rule_find(lpm, ip_masked, depth); /* * Check if rule_to_delete_index was found. If no rule was found the * function rule_find returns -EINVAL. */ if (rule_to_delete_index < 0) return -EINVAL; /* Delete the rule from the rule table. */ rule_delete(lpm, rule_to_delete_index, depth); /* * Find rule to replace the rule_to_delete. If there is no rule to * replace the rule_to_delete we return -1 and invalidate the table * entries associated with this rule. */ sub_rule_depth = 0; sub_rule_index = find_previous_rule(lpm, ip, depth, &sub_rule_depth); /* * If the input depth value is less than 25 use function * delete_depth_small otherwise use delete_depth_big. */ if (depth <= MAX_DEPTH_TBL24) { return delete_depth_small(lpm, ip_masked, depth, sub_rule_index, sub_rule_depth); } else { /* If depth > MAX_DEPTH_TBL24 */ return delete_depth_big(lpm, ip_masked, depth, sub_rule_index, sub_rule_depth); } } /* * Delete all rules from the LPM table. */ void rte_lpm_delete_all(struct rte_lpm *lpm) { /* Zero rule information. */ memset(lpm->rule_info, 0, sizeof(lpm->rule_info)); /* Zero tbl24. */ memset(lpm->tbl24, 0, sizeof(lpm->tbl24)); /* Zero tbl8. */ memset(lpm->tbl8, 0, sizeof(lpm->tbl8)); /* Delete all rules form the rules table. */ memset(lpm->rules_tbl, 0, sizeof(lpm->rules_tbl[0]) * lpm->max_rules); } ================================================ FILE: lib/librte_lpm/rte_lpm.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_LPM_H_ #define _RTE_LPM_H_ /** * @file * RTE Longest Prefix Match (LPM) */ #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** Max number of characters in LPM name. */ #define RTE_LPM_NAMESIZE 32 /** @deprecated Possible location to allocate memory. This was for last * parameter of rte_lpm_create(), but is now redundant. The LPM table is always * allocated in memory using librte_malloc which uses a memzone. */ #define RTE_LPM_HEAP 0 /** @deprecated Possible location to allocate memory. This was for last * parameter of rte_lpm_create(), but is now redundant. The LPM table is always * allocated in memory using librte_malloc which uses a memzone. */ #define RTE_LPM_MEMZONE 1 /** Maximum depth value possible for IPv4 LPM. */ #define RTE_LPM_MAX_DEPTH 32 /** @internal Total number of tbl24 entries. */ #define RTE_LPM_TBL24_NUM_ENTRIES (1 << 24) /** @internal Number of entries in a tbl8 group. */ #define RTE_LPM_TBL8_GROUP_NUM_ENTRIES 256 /** @internal Total number of tbl8 groups in the tbl8. */ #define RTE_LPM_TBL8_NUM_GROUPS 256 /** @internal Total number of tbl8 entries. */ #define RTE_LPM_TBL8_NUM_ENTRIES (RTE_LPM_TBL8_NUM_GROUPS * \ RTE_LPM_TBL8_GROUP_NUM_ENTRIES) /** @internal Macro to enable/disable run-time checks. */ #if defined(RTE_LIBRTE_LPM_DEBUG) #define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \ if (cond) return (retval); \ } while (0) #else #define RTE_LPM_RETURN_IF_TRUE(cond, retval) #endif /** @internal bitmask with valid and ext_entry/valid_group fields set */ #define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x0300 /** Bitmask used to indicate successful lookup */ #define RTE_LPM_LOOKUP_SUCCESS 0x0100 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN /** @internal Tbl24 entry structure. */ struct rte_lpm_tbl24_entry { /* Stores Next hop or group index (i.e. gindex)into tbl8. */ union { uint8_t next_hop; uint8_t tbl8_gindex; }; /* Using single uint8_t to store 3 values. */ uint8_t valid :1; /**< Validation flag. */ uint8_t ext_entry :1; /**< External entry. */ uint8_t depth :6; /**< Rule depth. */ }; /** @internal Tbl8 entry structure. */ struct rte_lpm_tbl8_entry { uint8_t next_hop; /**< next hop. */ /* Using single uint8_t to store 3 values. */ uint8_t valid :1; /**< Validation flag. */ uint8_t valid_group :1; /**< Group validation flag. */ uint8_t depth :6; /**< Rule depth. */ }; #else struct rte_lpm_tbl24_entry { uint8_t depth :6; uint8_t ext_entry :1; uint8_t valid :1; union { uint8_t tbl8_gindex; uint8_t next_hop; }; }; struct rte_lpm_tbl8_entry { uint8_t depth :6; uint8_t valid_group :1; uint8_t valid :1; uint8_t next_hop; }; #endif /** @internal Rule structure. */ struct rte_lpm_rule { uint32_t ip; /**< Rule IP address. */ uint8_t next_hop; /**< Rule next hop. */ }; /** @internal Contains metadata about the rules table. */ struct rte_lpm_rule_info { uint32_t used_rules; /**< Used rules so far. */ uint32_t first_rule; /**< Indexes the first rule of a given depth. */ }; /** @internal LPM structure. */ struct rte_lpm { /* LPM metadata. */ char name[RTE_LPM_NAMESIZE]; /**< Name of the lpm. */ int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */ uint32_t max_rules; /**< Max. balanced rules per lpm. */ struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info table. */ /* LPM Tables. */ struct rte_lpm_tbl24_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES] \ __rte_cache_aligned; /**< LPM tbl24 table. */ struct rte_lpm_tbl8_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES] \ __rte_cache_aligned; /**< LPM tbl8 table. */ struct rte_lpm_rule rules_tbl[0] \ __rte_cache_aligned; /**< LPM rules. */ }; /** * Create an LPM object. * * @param name * LPM object name * @param socket_id * NUMA socket ID for LPM table memory allocation * @param max_rules * Maximum number of LPM rules that can be added * @param flags * This parameter is currently unused * @return * Handle to LPM object on success, NULL otherwise with rte_errno set * to an appropriate values. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - invalid parameter passed to function * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_lpm * rte_lpm_create(const char *name, int socket_id, int max_rules, int flags); /** * Find an existing LPM object and return a pointer to it. * * @param name * Name of the lpm object as passed to rte_lpm_create() * @return * Pointer to lpm object or NULL if object not found with rte_errno * set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. */ struct rte_lpm * rte_lpm_find_existing(const char *name); /** * Free an LPM object. * * @param lpm * LPM object handle * @return * None */ void rte_lpm_free(struct rte_lpm *lpm); /** * Add a rule to the LPM table. * * @param lpm * LPM object handle * @param ip * IP of the rule to be added to the LPM table * @param depth * Depth of the rule to be added to the LPM table * @param next_hop * Next hop of the rule to be added to the LPM table * @return * 0 on success, negative value otherwise */ int rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t next_hop); /** * Check if a rule is present in the LPM table, * and provide its next hop if it is. * * @param lpm * LPM object handle * @param ip * IP of the rule to be searched * @param depth * Depth of the rule to searched * @param next_hop * Next hop of the rule (valid only if it is found) * @return * 1 if the rule exists, 0 if it does not, a negative value on failure */ int rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint8_t *next_hop); /** * Delete a rule from the LPM table. * * @param lpm * LPM object handle * @param ip * IP of the rule to be deleted from the LPM table * @param depth * Depth of the rule to be deleted from the LPM table * @return * 0 on success, negative value otherwise */ int rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth); /** * Delete all rules from the LPM table. * * @param lpm * LPM object handle */ void rte_lpm_delete_all(struct rte_lpm *lpm); /** * Lookup an IP into the LPM table. * * @param lpm * LPM object handle * @param ip * IP to be looked up in the LPM table * @param next_hop * Next hop of the most specific rule found for IP (valid on lookup hit only) * @return * -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit */ static inline int rte_lpm_lookup(struct rte_lpm *lpm, uint32_t ip, uint8_t *next_hop) { unsigned tbl24_index = (ip >> 8); uint16_t tbl_entry; /* DEBUG: Check user input arguments. */ RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL); /* Copy tbl24 entry */ tbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index]; /* Copy tbl8 entry (only if needed) */ if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { unsigned tbl8_index = (uint8_t)ip + ((uint8_t)tbl_entry * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); tbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index]; } *next_hop = (uint8_t)tbl_entry; return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT; } /** * Lookup multiple IP addresses in an LPM table. This may be implemented as a * macro, so the address of the function should not be used. * * @param lpm * LPM object handle * @param ips * Array of IPs to be looked up in the LPM table * @param next_hops * Next hop of the most specific rule found for IP (valid on lookup hit only). * This is an array of two byte values. The most significant byte in each * value says whether the lookup was successful (bitmask * RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the * actual next hop. * @param n * Number of elements in ips (and next_hops) array to lookup. This should be a * compile time constant, and divisible by 8 for best performance. * @return * -EINVAL for incorrect arguments, otherwise 0 */ #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \ rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n) static inline int rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t * ips, uint16_t * next_hops, const unsigned n) { unsigned i; unsigned tbl24_indexes[n]; /* DEBUG: Check user input arguments. */ RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) || (next_hops == NULL)), -EINVAL); for (i = 0; i < n; i++) { tbl24_indexes[i] = ips[i] >> 8; } for (i = 0; i < n; i++) { /* Simply copy tbl24 entry to output */ next_hops[i] = *(const uint16_t *)&lpm->tbl24[tbl24_indexes[i]]; /* Overwrite output with tbl8 entry if needed */ if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { unsigned tbl8_index = (uint8_t)ips[i] + ((uint8_t)next_hops[i] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES); next_hops[i] = *(const uint16_t *)&lpm->tbl8[tbl8_index]; } } return 0; } /* Mask four results. */ #define RTE_LPM_MASKX4_RES UINT64_C(0x00ff00ff00ff00ff) /** * Lookup four IP addresses in an LPM table. * * @param lpm * LPM object handle * @param ip * Four IPs to be looked up in the LPM table * @param hop * Next hop of the most specific rule found for IP (valid on lookup hit only). * This is an 4 elements array of two byte values. * If the lookup was succesfull for the given IP, then least significant byte * of the corresponding element is the actual next hop and the most * significant byte is zero. * If the lookup for the given IP failed, then corresponding element would * contain default value, see description of then next parameter. * @param defv * Default value to populate into corresponding element of hop[] array, * if lookup would fail. */ static inline void rte_lpm_lookupx4(const struct rte_lpm *lpm, __m128i ip, uint16_t hop[4], uint16_t defv) { __m128i i24; rte_xmm_t i8; uint16_t tbl[4]; uint64_t idx, pt; const __m128i mask8 = _mm_set_epi32(UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX); /* * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 4 LPM entries * as one 64-bit value (0x0300030003000300). */ const uint64_t mask_xv = ((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK | (uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 16 | (uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32 | (uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 48); /* * RTE_LPM_LOOKUP_SUCCESS for 4 LPM entries * as one 64-bit value (0x0100010001000100). */ const uint64_t mask_v = ((uint64_t)RTE_LPM_LOOKUP_SUCCESS | (uint64_t)RTE_LPM_LOOKUP_SUCCESS << 16 | (uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32 | (uint64_t)RTE_LPM_LOOKUP_SUCCESS << 48); /* get 4 indexes for tbl24[]. */ i24 = _mm_srli_epi32(ip, CHAR_BIT); /* extract values from tbl24[] */ idx = _mm_cvtsi128_si64(i24); i24 = _mm_srli_si128(i24, sizeof(uint64_t)); tbl[0] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx]; tbl[1] = *(const uint16_t *)&lpm->tbl24[idx >> 32]; idx = _mm_cvtsi128_si64(i24); tbl[2] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx]; tbl[3] = *(const uint16_t *)&lpm->tbl24[idx >> 32]; /* get 4 indexes for tbl8[]. */ i8.x = _mm_and_si128(ip, mask8); pt = (uint64_t)tbl[0] | (uint64_t)tbl[1] << 16 | (uint64_t)tbl[2] << 32 | (uint64_t)tbl[3] << 48; /* search successfully finished for all 4 IP addresses. */ if (likely((pt & mask_xv) == mask_v)) { uintptr_t ph = (uintptr_t)hop; *(uint64_t *)ph = pt & RTE_LPM_MASKX4_RES; return; } if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { i8.u32[0] = i8.u32[0] + (uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl[0] = *(const uint16_t *)&lpm->tbl8[i8.u32[0]]; } if (unlikely((pt >> 16 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { i8.u32[1] = i8.u32[1] + (uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl[1] = *(const uint16_t *)&lpm->tbl8[i8.u32[1]]; } if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { i8.u32[2] = i8.u32[2] + (uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl[2] = *(const uint16_t *)&lpm->tbl8[i8.u32[2]]; } if (unlikely((pt >> 48 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { i8.u32[3] = i8.u32[3] + (uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; tbl[3] = *(const uint16_t *)&lpm->tbl8[i8.u32[3]]; } hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[0] : defv; hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[1] : defv; hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[2] : defv; hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[3] : defv; } #ifdef __cplusplus } #endif #endif /* _RTE_LPM_H_ */ ================================================ FILE: lib/librte_lpm/rte_lpm6.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_lpm6.h" #define RTE_LPM6_TBL24_NUM_ENTRIES (1 << 24) #define RTE_LPM6_TBL8_GROUP_NUM_ENTRIES 256 #define RTE_LPM6_TBL8_MAX_NUM_GROUPS (1 << 21) #define RTE_LPM6_VALID_EXT_ENTRY_BITMASK 0xA0000000 #define RTE_LPM6_LOOKUP_SUCCESS 0x20000000 #define RTE_LPM6_TBL8_BITMASK 0x001FFFFF #define ADD_FIRST_BYTE 3 #define LOOKUP_FIRST_BYTE 4 #define BYTE_SIZE 8 #define BYTES2_SIZE 16 #define lpm6_tbl8_gindex next_hop /** Flags for setting an entry as valid/invalid. */ enum valid_flag { INVALID = 0, VALID }; TAILQ_HEAD(rte_lpm6_list, rte_tailq_entry); static struct rte_tailq_elem rte_lpm6_tailq = { .name = "RTE_LPM6", }; EAL_REGISTER_TAILQ(rte_lpm6_tailq) /** Tbl entry structure. It is the same for both tbl24 and tbl8 */ struct rte_lpm6_tbl_entry { uint32_t next_hop: 21; /**< Next hop / next table to be checked. */ uint32_t depth :8; /**< Rule depth. */ /* Flags. */ uint32_t valid :1; /**< Validation flag. */ uint32_t valid_group :1; /**< Group validation flag. */ uint32_t ext_entry :1; /**< External entry. */ }; /** Rules tbl entry structure. */ struct rte_lpm6_rule { uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */ uint8_t next_hop; /**< Rule next hop. */ uint8_t depth; /**< Rule depth. */ }; /** LPM6 structure. */ struct rte_lpm6 { /* LPM metadata. */ char name[RTE_LPM6_NAMESIZE]; /**< Name of the lpm. */ uint32_t max_rules; /**< Max number of rules. */ uint32_t used_rules; /**< Used rules so far. */ uint32_t number_tbl8s; /**< Number of tbl8s to allocate. */ uint32_t next_tbl8; /**< Next tbl8 to be used. */ /* LPM Tables. */ struct rte_lpm6_rule *rules_tbl; /**< LPM rules. */ struct rte_lpm6_tbl_entry tbl24[RTE_LPM6_TBL24_NUM_ENTRIES] __rte_cache_aligned; /**< LPM tbl24 table. */ struct rte_lpm6_tbl_entry tbl8[0] __rte_cache_aligned; /**< LPM tbl8 table. */ }; /* * Takes an array of uint8_t (IPv6 address) and masks it using the depth. * It leaves untouched one bit per unit in the depth variable * and set the rest to 0. */ static inline void mask_ip(uint8_t *ip, uint8_t depth) { int16_t part_depth, mask; int i; part_depth = depth; for (i = 0; i < RTE_LPM6_IPV6_ADDR_SIZE; i++) { if (part_depth < BYTE_SIZE && part_depth >= 0) { mask = (uint16_t)(~(UINT8_MAX >> part_depth)); ip[i] = (uint8_t)(ip[i] & mask); } else if (part_depth < 0) { ip[i] = 0; } part_depth -= BYTE_SIZE; } } /* * Allocates memory for LPM object */ struct rte_lpm6 * rte_lpm6_create(const char *name, int socket_id, const struct rte_lpm6_config *config) { char mem_name[RTE_LPM6_NAMESIZE]; struct rte_lpm6 *lpm = NULL; struct rte_tailq_entry *te; uint64_t mem_size, rules_size; struct rte_lpm6_list *lpm_list; lpm_list = RTE_TAILQ_CAST(rte_lpm6_tailq.head, rte_lpm6_list); RTE_BUILD_BUG_ON(sizeof(struct rte_lpm6_tbl_entry) != sizeof(uint32_t)); /* Check user arguments. */ if ((name == NULL) || (socket_id < -1) || (config == NULL) || (config->max_rules == 0) || config->number_tbl8s > RTE_LPM6_TBL8_MAX_NUM_GROUPS) { rte_errno = EINVAL; return NULL; } snprintf(mem_name, sizeof(mem_name), "LPM_%s", name); /* Determine the amount of memory to allocate. */ mem_size = sizeof(*lpm) + (sizeof(lpm->tbl8[0]) * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES * config->number_tbl8s); rules_size = sizeof(struct rte_lpm6_rule) * config->max_rules; rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* Guarantee there's no existing */ TAILQ_FOREACH(te, lpm_list, next) { lpm = (struct rte_lpm6 *) te->data; if (strncmp(name, lpm->name, RTE_LPM6_NAMESIZE) == 0) break; } if (te != NULL) goto exit; /* allocate tailq entry */ te = rte_zmalloc("LPM6_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, LPM, "Failed to allocate tailq entry!\n"); goto exit; } /* Allocate memory to store the LPM data structures. */ lpm = (struct rte_lpm6 *)rte_zmalloc_socket(mem_name, (size_t)mem_size, RTE_CACHE_LINE_SIZE, socket_id); if (lpm == NULL) { RTE_LOG(ERR, LPM, "LPM memory allocation failed\n"); rte_free(te); goto exit; } lpm->rules_tbl = (struct rte_lpm6_rule *)rte_zmalloc_socket(NULL, (size_t)rules_size, RTE_CACHE_LINE_SIZE, socket_id); if (lpm->rules_tbl == NULL) { RTE_LOG(ERR, LPM, "LPM memory allocation failed\n"); rte_free(lpm); rte_free(te); goto exit; } /* Save user arguments. */ lpm->max_rules = config->max_rules; lpm->number_tbl8s = config->number_tbl8s; snprintf(lpm->name, sizeof(lpm->name), "%s", name); te->data = (void *) lpm; TAILQ_INSERT_TAIL(lpm_list, te, next); exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return lpm; } /* * Find an existing lpm table and return a pointer to it. */ struct rte_lpm6 * rte_lpm6_find_existing(const char *name) { struct rte_lpm6 *l = NULL; struct rte_tailq_entry *te; struct rte_lpm6_list *lpm_list; lpm_list = RTE_TAILQ_CAST(rte_lpm6_tailq.head, rte_lpm6_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, lpm_list, next) { l = (struct rte_lpm6 *) te->data; if (strncmp(name, l->name, RTE_LPM6_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return l; } /* * Deallocates memory for given LPM table. */ void rte_lpm6_free(struct rte_lpm6 *lpm) { struct rte_lpm6_list *lpm_list; struct rte_tailq_entry *te; /* Check user arguments. */ if (lpm == NULL) return; lpm_list = RTE_TAILQ_CAST(rte_lpm6_tailq.head, rte_lpm6_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find our tailq entry */ TAILQ_FOREACH(te, lpm_list, next) { if (te->data == (void *) lpm) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(lpm_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(lpm); rte_free(te); } /* * Checks if a rule already exists in the rules table and updates * the nexthop if so. Otherwise it adds a new rule if enough space is available. */ static inline int32_t rule_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t next_hop, uint8_t depth) { uint32_t rule_index; /* Scan through rule list to see if rule already exists. */ for (rule_index = 0; rule_index < lpm->used_rules; rule_index++) { /* If rule already exists update its next_hop and return. */ if ((memcmp (lpm->rules_tbl[rule_index].ip, ip, RTE_LPM6_IPV6_ADDR_SIZE) == 0) && lpm->rules_tbl[rule_index].depth == depth) { lpm->rules_tbl[rule_index].next_hop = next_hop; return rule_index; } } /* * If rule does not exist check if there is space to add a new rule to * this rule group. If there is no space return error. */ if (lpm->used_rules == lpm->max_rules) { return -ENOSPC; } /* If there is space for the new rule add it. */ rte_memcpy(lpm->rules_tbl[rule_index].ip, ip, RTE_LPM6_IPV6_ADDR_SIZE); lpm->rules_tbl[rule_index].next_hop = next_hop; lpm->rules_tbl[rule_index].depth = depth; /* Increment the used rules counter for this rule group. */ lpm->used_rules++; return rule_index; } /* * Function that expands a rule across the data structure when a less-generic * one has been added before. It assures that every possible combination of bits * in the IP address returns a match. */ static void expand_rule(struct rte_lpm6 *lpm, uint32_t tbl8_gindex, uint8_t depth, uint8_t next_hop) { uint32_t tbl8_group_end, tbl8_gindex_next, j; tbl8_group_end = tbl8_gindex + RTE_LPM6_TBL8_GROUP_NUM_ENTRIES; struct rte_lpm6_tbl_entry new_tbl8_entry = { .valid = VALID, .valid_group = VALID, .depth = depth, .next_hop = next_hop, .ext_entry = 0, }; for (j = tbl8_gindex; j < tbl8_group_end; j++) { if (!lpm->tbl8[j].valid || (lpm->tbl8[j].ext_entry == 0 && lpm->tbl8[j].depth <= depth)) { lpm->tbl8[j] = new_tbl8_entry; } else if (lpm->tbl8[j].ext_entry == 1) { tbl8_gindex_next = lpm->tbl8[j].lpm6_tbl8_gindex * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES; expand_rule(lpm, tbl8_gindex_next, depth, next_hop); } } } /* * Partially adds a new route to the data structure (tbl24+tbl8s). * It returns 0 on success, a negative number on failure, or 1 if * the process needs to be continued by calling the function again. */ static inline int add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl, struct rte_lpm6_tbl_entry **tbl_next, uint8_t *ip, uint8_t bytes, uint8_t first_byte, uint8_t depth, uint8_t next_hop) { uint32_t tbl_index, tbl_range, tbl8_group_start, tbl8_group_end, i; int32_t tbl8_gindex; int8_t bitshift; uint8_t bits_covered; /* * Calculate index to the table based on the number and position * of the bytes being inspected in this step. */ tbl_index = 0; for (i = first_byte; i < (uint32_t)(first_byte + bytes); i++) { bitshift = (int8_t)((bytes - i)*BYTE_SIZE); if (bitshift < 0) bitshift = 0; tbl_index = tbl_index | ip[i-1] << bitshift; } /* Number of bits covered in this step */ bits_covered = (uint8_t)((bytes+first_byte-1)*BYTE_SIZE); /* * If depth if smaller than this number (ie this is the last step) * expand the rule across the relevant positions in the table. */ if (depth <= bits_covered) { tbl_range = 1 << (bits_covered - depth); for (i = tbl_index; i < (tbl_index + tbl_range); i++) { if (!tbl[i].valid || (tbl[i].ext_entry == 0 && tbl[i].depth <= depth)) { struct rte_lpm6_tbl_entry new_tbl_entry = { .next_hop = next_hop, .depth = depth, .valid = VALID, .valid_group = VALID, .ext_entry = 0, }; tbl[i] = new_tbl_entry; } else if (tbl[i].ext_entry == 1) { /* * If tbl entry is valid and extended calculate the index * into next tbl8 and expand the rule across the data structure. */ tbl8_gindex = tbl[i].lpm6_tbl8_gindex * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES; expand_rule(lpm, tbl8_gindex, depth, next_hop); } } return 0; } /* * If this is not the last step just fill one position * and calculate the index to the next table. */ else { /* If it's invalid a new tbl8 is needed */ if (!tbl[tbl_index].valid) { if (lpm->next_tbl8 < lpm->number_tbl8s) tbl8_gindex = (lpm->next_tbl8)++; else return -ENOSPC; struct rte_lpm6_tbl_entry new_tbl_entry = { .lpm6_tbl8_gindex = tbl8_gindex, .depth = 0, .valid = VALID, .valid_group = VALID, .ext_entry = 1, }; tbl[tbl_index] = new_tbl_entry; } /* * If it's valid but not extended the rule that was stored * * here needs to be moved to the next table. */ else if (tbl[tbl_index].ext_entry == 0) { /* Search for free tbl8 group. */ if (lpm->next_tbl8 < lpm->number_tbl8s) tbl8_gindex = (lpm->next_tbl8)++; else return -ENOSPC; tbl8_group_start = tbl8_gindex * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES; tbl8_group_end = tbl8_group_start + RTE_LPM6_TBL8_GROUP_NUM_ENTRIES; /* Populate new tbl8 with tbl value. */ for (i = tbl8_group_start; i < tbl8_group_end; i++) { lpm->tbl8[i].valid = VALID; lpm->tbl8[i].depth = tbl[tbl_index].depth; lpm->tbl8[i].next_hop = tbl[tbl_index].next_hop; lpm->tbl8[i].ext_entry = 0; } /* * Update tbl entry to point to new tbl8 entry. Note: The * ext_flag and tbl8_index need to be updated simultaneously, * so assign whole structure in one go. */ struct rte_lpm6_tbl_entry new_tbl_entry = { .lpm6_tbl8_gindex = tbl8_gindex, .depth = 0, .valid = VALID, .valid_group = VALID, .ext_entry = 1, }; tbl[tbl_index] = new_tbl_entry; } *tbl_next = &(lpm->tbl8[tbl[tbl_index].lpm6_tbl8_gindex * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES]); } return 1; } /* * Add a route */ int rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t next_hop) { struct rte_lpm6_tbl_entry *tbl; struct rte_lpm6_tbl_entry *tbl_next; int32_t rule_index; int status; uint8_t masked_ip[RTE_LPM6_IPV6_ADDR_SIZE]; int i; /* Check user arguments. */ if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM6_MAX_DEPTH)) return -EINVAL; /* Copy the IP and mask it to avoid modifying user's input data. */ memcpy(masked_ip, ip, RTE_LPM6_IPV6_ADDR_SIZE); mask_ip(masked_ip, depth); /* Add the rule to the rule table. */ rule_index = rule_add(lpm, masked_ip, next_hop, depth); /* If there is no space available for new rule return error. */ if (rule_index < 0) { return rule_index; } /* Inspect the first three bytes through tbl24 on the first step. */ tbl = lpm->tbl24; status = add_step (lpm, tbl, &tbl_next, masked_ip, ADD_FIRST_BYTE, 1, depth, next_hop); if (status < 0) { rte_lpm6_delete(lpm, masked_ip, depth); return status; } /* * Inspect one by one the rest of the bytes until * the process is completed. */ for (i = ADD_FIRST_BYTE; i < RTE_LPM6_IPV6_ADDR_SIZE && status == 1; i++) { tbl = tbl_next; status = add_step (lpm, tbl, &tbl_next, masked_ip, 1, (uint8_t)(i+1), depth, next_hop); if (status < 0) { rte_lpm6_delete(lpm, masked_ip, depth); return status; } } return status; } /* * Takes a pointer to a table entry and inspect one level. * The function returns 0 on lookup success, ENOENT if no match was found * or 1 if the process needs to be continued by calling the function again. */ static inline int lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl, const struct rte_lpm6_tbl_entry **tbl_next, uint8_t *ip, uint8_t first_byte, uint8_t *next_hop) { uint32_t tbl8_index, tbl_entry; /* Take the integer value from the pointer. */ tbl_entry = *(const uint32_t *)tbl; /* If it is valid and extended we calculate the new pointer to return. */ if ((tbl_entry & RTE_LPM6_VALID_EXT_ENTRY_BITMASK) == RTE_LPM6_VALID_EXT_ENTRY_BITMASK) { tbl8_index = ip[first_byte-1] + ((tbl_entry & RTE_LPM6_TBL8_BITMASK) * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES); *tbl_next = &lpm->tbl8[tbl8_index]; return 1; } else { /* If not extended then we can have a match. */ *next_hop = (uint8_t)tbl_entry; return (tbl_entry & RTE_LPM6_LOOKUP_SUCCESS) ? 0 : -ENOENT; } } /* * Looks up an IP */ int rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop) { const struct rte_lpm6_tbl_entry *tbl; const struct rte_lpm6_tbl_entry *tbl_next; int status; uint8_t first_byte; uint32_t tbl24_index; /* DEBUG: Check user input arguments. */ if ((lpm == NULL) || (ip == NULL) || (next_hop == NULL)) { return -EINVAL; } first_byte = LOOKUP_FIRST_BYTE; tbl24_index = (ip[0] << BYTES2_SIZE) | (ip[1] << BYTE_SIZE) | ip[2]; /* Calculate pointer to the first entry to be inspected */ tbl = &lpm->tbl24[tbl24_index]; do { /* Continue inspecting following levels until success or failure */ status = lookup_step(lpm, tbl, &tbl_next, ip, first_byte++, next_hop); tbl = tbl_next; } while (status == 1); return status; } /* * Looks up a group of IP addresses */ int rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], int16_t * next_hops, unsigned n) { unsigned i; const struct rte_lpm6_tbl_entry *tbl; const struct rte_lpm6_tbl_entry *tbl_next; uint32_t tbl24_index; uint8_t first_byte, next_hop; int status; /* DEBUG: Check user input arguments. */ if ((lpm == NULL) || (ips == NULL) || (next_hops == NULL)) { return -EINVAL; } for (i = 0; i < n; i++) { first_byte = LOOKUP_FIRST_BYTE; tbl24_index = (ips[i][0] << BYTES2_SIZE) | (ips[i][1] << BYTE_SIZE) | ips[i][2]; /* Calculate pointer to the first entry to be inspected */ tbl = &lpm->tbl24[tbl24_index]; do { /* Continue inspecting following levels until success or failure */ status = lookup_step(lpm, tbl, &tbl_next, ips[i], first_byte++, &next_hop); tbl = tbl_next; } while (status == 1); if (status < 0) next_hops[i] = -1; else next_hops[i] = next_hop; } return 0; } /* * Finds a rule in rule table. * NOTE: Valid range for depth parameter is 1 .. 128 inclusive. */ static inline int32_t rule_find(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth) { uint32_t rule_index; /* Scan used rules at given depth to find rule. */ for (rule_index = 0; rule_index < lpm->used_rules; rule_index++) { /* If rule is found return the rule index. */ if ((memcmp (lpm->rules_tbl[rule_index].ip, ip, RTE_LPM6_IPV6_ADDR_SIZE) == 0) && lpm->rules_tbl[rule_index].depth == depth) { return rule_index; } } /* If rule is not found return -ENOENT. */ return -ENOENT; } /* * Look for a rule in the high-level rules table */ int rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t *next_hop) { uint8_t ip_masked[RTE_LPM6_IPV6_ADDR_SIZE]; int32_t rule_index; /* Check user arguments. */ if ((lpm == NULL) || next_hop == NULL || ip == NULL || (depth < 1) || (depth > RTE_LPM6_MAX_DEPTH)) return -EINVAL; /* Copy the IP and mask it to avoid modifying user's input data. */ memcpy(ip_masked, ip, RTE_LPM6_IPV6_ADDR_SIZE); mask_ip(ip_masked, depth); /* Look for the rule using rule_find. */ rule_index = rule_find(lpm, ip_masked, depth); if (rule_index >= 0) { *next_hop = lpm->rules_tbl[rule_index].next_hop; return 1; } /* If rule is not found return 0. */ return 0; } /* * Delete a rule from the rule table. * NOTE: Valid range for depth parameter is 1 .. 128 inclusive. */ static inline void rule_delete(struct rte_lpm6 *lpm, int32_t rule_index) { /* * Overwrite redundant rule with last rule in group and decrement rule * counter. */ lpm->rules_tbl[rule_index] = lpm->rules_tbl[lpm->used_rules-1]; lpm->used_rules--; } /* * Deletes a rule */ int rte_lpm6_delete(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth) { int32_t rule_to_delete_index; uint8_t ip_masked[RTE_LPM6_IPV6_ADDR_SIZE]; unsigned i; /* * Check input arguments. */ if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM6_MAX_DEPTH)) { return -EINVAL; } /* Copy the IP and mask it to avoid modifying user's input data. */ memcpy(ip_masked, ip, RTE_LPM6_IPV6_ADDR_SIZE); mask_ip(ip_masked, depth); /* * Find the index of the input rule, that needs to be deleted, in the * rule table. */ rule_to_delete_index = rule_find(lpm, ip_masked, depth); /* * Check if rule_to_delete_index was found. If no rule was found the * function rule_find returns -ENOENT. */ if (rule_to_delete_index < 0) return rule_to_delete_index; /* Delete the rule from the rule table. */ rule_delete(lpm, rule_to_delete_index); /* * Set all the table entries to 0 (ie delete every rule * from the data structure. */ lpm->next_tbl8 = 0; memset(lpm->tbl24, 0, sizeof(lpm->tbl24)); memset(lpm->tbl8, 0, sizeof(lpm->tbl8[0]) * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES * lpm->number_tbl8s); /* * Add every rule again (except for the one that was removed from * the rules table). */ for (i = 0; i < lpm->used_rules; i++) { rte_lpm6_add(lpm, lpm->rules_tbl[i].ip, lpm->rules_tbl[i].depth, lpm->rules_tbl[i].next_hop); } return 0; } /* * Deletes a group of rules */ int rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], uint8_t *depths, unsigned n) { int32_t rule_to_delete_index; uint8_t ip_masked[RTE_LPM6_IPV6_ADDR_SIZE]; unsigned i; /* * Check input arguments. */ if ((lpm == NULL) || (ips == NULL) || (depths == NULL)) { return -EINVAL; } for (i = 0; i < n; i++) { /* Copy the IP and mask it to avoid modifying user's input data. */ memcpy(ip_masked, ips[i], RTE_LPM6_IPV6_ADDR_SIZE); mask_ip(ip_masked, depths[i]); /* * Find the index of the input rule, that needs to be deleted, in the * rule table. */ rule_to_delete_index = rule_find(lpm, ip_masked, depths[i]); /* * Check if rule_to_delete_index was found. If no rule was found the * function rule_find returns -ENOENT. */ if (rule_to_delete_index < 0) continue; /* Delete the rule from the rule table. */ rule_delete(lpm, rule_to_delete_index); } /* * Set all the table entries to 0 (ie delete every rule * from the data structure. */ lpm->next_tbl8 = 0; memset(lpm->tbl24, 0, sizeof(lpm->tbl24)); memset(lpm->tbl8, 0, sizeof(lpm->tbl8[0]) * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES * lpm->number_tbl8s); /* * Add every rule again (except for the ones that were removed from * the rules table). */ for (i = 0; i < lpm->used_rules; i++) { rte_lpm6_add(lpm, lpm->rules_tbl[i].ip, lpm->rules_tbl[i].depth, lpm->rules_tbl[i].next_hop); } return 0; } /* * Delete all rules from the LPM table. */ void rte_lpm6_delete_all(struct rte_lpm6 *lpm) { /* Zero used rules counter. */ lpm->used_rules = 0; /* Zero next tbl8 index. */ lpm->next_tbl8 = 0; /* Zero tbl24. */ memset(lpm->tbl24, 0, sizeof(lpm->tbl24)); /* Zero tbl8. */ memset(lpm->tbl8, 0, sizeof(lpm->tbl8[0]) * RTE_LPM6_TBL8_GROUP_NUM_ENTRIES * lpm->number_tbl8s); /* Delete all rules form the rules table. */ memset(lpm->rules_tbl, 0, sizeof(struct rte_lpm6_rule) * lpm->max_rules); } ================================================ FILE: lib/librte_lpm/rte_lpm6.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_LPM6_H_ #define _RTE_LPM6_H_ /** * @file * RTE Longest Prefix Match for IPv6 (LPM6) */ #ifdef __cplusplus extern "C" { #endif #define RTE_LPM6_MAX_DEPTH 128 #define RTE_LPM6_IPV6_ADDR_SIZE 16 /** Max number of characters in LPM name. */ #define RTE_LPM6_NAMESIZE 32 /** LPM structure. */ struct rte_lpm6; /** LPM configuration structure. */ struct rte_lpm6_config { uint32_t max_rules; /**< Max number of rules. */ uint32_t number_tbl8s; /**< Number of tbl8s to allocate. */ int flags; /**< This field is currently unused. */ }; /** * Create an LPM object. * * @param name * LPM object name * @param socket_id * NUMA socket ID for LPM table memory allocation * @param config * Structure containing the configuration * @return * Handle to LPM object on success, NULL otherwise with rte_errno set * to an appropriate values. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - invalid parameter passed to function * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_lpm6 * rte_lpm6_create(const char *name, int socket_id, const struct rte_lpm6_config *config); /** * Find an existing LPM object and return a pointer to it. * * @param name * Name of the lpm object as passed to rte_lpm6_create() * @return * Pointer to lpm object or NULL if object not found with rte_errno * set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. */ struct rte_lpm6 * rte_lpm6_find_existing(const char *name); /** * Free an LPM object. * * @param lpm * LPM object handle * @return * None */ void rte_lpm6_free(struct rte_lpm6 *lpm); /** * Add a rule to the LPM table. * * @param lpm * LPM object handle * @param ip * IP of the rule to be added to the LPM table * @param depth * Depth of the rule to be added to the LPM table * @param next_hop * Next hop of the rule to be added to the LPM table * @return * 0 on success, negative value otherwise */ int rte_lpm6_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t next_hop); /** * Check if a rule is present in the LPM table, * and provide its next hop if it is. * * @param lpm * LPM object handle * @param ip * IP of the rule to be searched * @param depth * Depth of the rule to searched * @param next_hop * Next hop of the rule (valid only if it is found) * @return * 1 if the rule exists, 0 if it does not, a negative value on failure */ int rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint8_t *next_hop); /** * Delete a rule from the LPM table. * * @param lpm * LPM object handle * @param ip * IP of the rule to be deleted from the LPM table * @param depth * Depth of the rule to be deleted from the LPM table * @return * 0 on success, negative value otherwise */ int rte_lpm6_delete(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth); /** * Delete a rule from the LPM table. * * @param lpm * LPM object handle * @param ips * Array of IPs to be deleted from the LPM table * @param depths * Array of depths of the rules to be deleted from the LPM table * @param n * Number of rules to be deleted from the LPM table * @return * 0 on success, negative value otherwise. */ int rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], uint8_t *depths, unsigned n); /** * Delete all rules from the LPM table. * * @param lpm * LPM object handle */ void rte_lpm6_delete_all(struct rte_lpm6 *lpm); /** * Lookup an IP into the LPM table. * * @param lpm * LPM object handle * @param ip * IP to be looked up in the LPM table * @param next_hop * Next hop of the most specific rule found for IP (valid on lookup hit only) * @return * -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit */ int rte_lpm6_lookup(const struct rte_lpm6 *lpm, uint8_t *ip, uint8_t *next_hop); /** * Lookup multiple IP addresses in an LPM table. * * @param lpm * LPM object handle * @param ips * Array of IPs to be looked up in the LPM table * @param next_hops * Next hop of the most specific rule found for IP (valid on lookup hit only). * This is an array of two byte values. The next hop will be stored on * each position on success; otherwise the position will be set to -1. * @param n * Number of elements in ips (and next_hops) array to lookup. * @return * -EINVAL for incorrect arguments, otherwise 0 */ int rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm, uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], int16_t * next_hops, unsigned n); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_malloc/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_malloc.a LIBABIVER := 1 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_malloc_version.map # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_EAL) := rte_malloc_empty.c # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_EAL) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_malloc/rte_malloc_empty.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Empty file to be able to create a dummy library for deprecation policy */ ================================================ FILE: lib/librte_mbuf/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_mbuf.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_mbuf_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_MBUF) := rte_mbuf.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_MBUF)-include := rte_mbuf.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_MBUF) += lib/librte_eal lib/librte_mempool include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_mbuf/rte_mbuf.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * ctrlmbuf constructor, given as a callback function to * rte_mempool_create() */ void rte_ctrlmbuf_init(struct rte_mempool *mp, __attribute__((unused)) void *opaque_arg, void *_m, __attribute__((unused)) unsigned i) { struct rte_mbuf *m = _m; rte_pktmbuf_init(mp, opaque_arg, _m, i); m->ol_flags |= CTRL_MBUF_FLAG; } /* * pktmbuf pool constructor, given as a callback function to * rte_mempool_create() */ void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg) { struct rte_pktmbuf_pool_private *user_mbp_priv, *mbp_priv; struct rte_pktmbuf_pool_private default_mbp_priv; uint16_t roomsz; RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf)); /* if no structure is provided, assume no mbuf private area */ user_mbp_priv = opaque_arg; if (user_mbp_priv == NULL) { default_mbp_priv.mbuf_priv_size = 0; if (mp->elt_size > sizeof(struct rte_mbuf)) roomsz = mp->elt_size - sizeof(struct rte_mbuf); else roomsz = 0; default_mbp_priv.mbuf_data_room_size = roomsz; user_mbp_priv = &default_mbp_priv; } RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf) + user_mbp_priv->mbuf_data_room_size + user_mbp_priv->mbuf_priv_size); mbp_priv = rte_mempool_get_priv(mp); memcpy(mbp_priv, user_mbp_priv, sizeof(*mbp_priv)); } /* * pktmbuf constructor, given as a callback function to * rte_mempool_create(). * Set the fields of a packet mbuf to their default values. */ void rte_pktmbuf_init(struct rte_mempool *mp, __attribute__((unused)) void *opaque_arg, void *_m, __attribute__((unused)) unsigned i) { struct rte_mbuf *m = _m; uint32_t mbuf_size, buf_len, priv_size; priv_size = rte_pktmbuf_priv_size(mp); mbuf_size = sizeof(struct rte_mbuf) + priv_size; buf_len = rte_pktmbuf_data_room_size(mp); RTE_MBUF_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size); RTE_MBUF_ASSERT(mp->elt_size >= mbuf_size); RTE_MBUF_ASSERT(buf_len <= UINT16_MAX); memset(m, 0, mp->elt_size); /* start of buffer is after mbuf structure and priv data */ m->priv_size = priv_size; m->buf_addr = (char *)m + mbuf_size; m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size; m->buf_len = (uint16_t)buf_len; /* keep some headroom between start of buffer and data */ m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len); /* init some constant fields */ m->pool = mp; m->nb_segs = 1; m->port = 0xff; } /* helper to create a mbuf pool */ struct rte_mempool * rte_pktmbuf_pool_create(const char *name, unsigned n, unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, int socket_id) { struct rte_pktmbuf_pool_private mbp_priv; unsigned elt_size; if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) { RTE_LOG(ERR, MBUF, "mbuf priv_size=%u is not aligned\n", priv_size); rte_errno = EINVAL; return NULL; } elt_size = sizeof(struct rte_mbuf) + (unsigned)priv_size + (unsigned)data_room_size; mbp_priv.mbuf_data_room_size = data_room_size; mbp_priv.mbuf_priv_size = priv_size; return rte_mempool_create(name, n, elt_size, cache_size, sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, &mbp_priv, rte_pktmbuf_init, NULL, socket_id, 0); } /* do some sanity checks on a mbuf: panic if it fails */ void rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header) { const struct rte_mbuf *m_seg; unsigned nb_segs; if (m == NULL) rte_panic("mbuf is NULL\n"); /* generic checks */ if (m->pool == NULL) rte_panic("bad mbuf pool\n"); if (m->buf_physaddr == 0) rte_panic("bad phys addr\n"); if (m->buf_addr == NULL) rte_panic("bad virt addr\n"); uint16_t cnt = rte_mbuf_refcnt_read(m); if ((cnt == 0) || (cnt == UINT16_MAX)) rte_panic("bad ref cnt\n"); /* nothing to check for sub-segments */ if (is_header == 0) return; nb_segs = m->nb_segs; m_seg = m; while (m_seg && nb_segs != 0) { m_seg = m_seg->next; nb_segs--; } if (nb_segs != 0) rte_panic("bad nb_segs\n"); } /* dump a mbuf on console */ void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len) { unsigned int len; unsigned nb_segs; __rte_mbuf_sanity_check(m, 1); fprintf(f, "dump mbuf at 0x%p, phys=%"PRIx64", buf_len=%u\n", m, (uint64_t)m->buf_physaddr, (unsigned)m->buf_len); fprintf(f, " pkt_len=%"PRIu32", ol_flags=%"PRIx64", nb_segs=%u, " "in_port=%u\n", m->pkt_len, m->ol_flags, (unsigned)m->nb_segs, (unsigned)m->port); nb_segs = m->nb_segs; while (m && nb_segs != 0) { __rte_mbuf_sanity_check(m, 0); fprintf(f, " segment at 0x%p, data=0x%p, data_len=%u\n", m, rte_pktmbuf_mtod(m, void *), (unsigned)m->data_len); len = dump_len; if (len > m->data_len) len = m->data_len; if (len != 0) rte_hexdump(f, NULL, rte_pktmbuf_mtod(m, void *), len); dump_len -= len; m = m->next; nb_segs --; } } /* * Get the name of a RX offload flag. Must be kept synchronized with flag * definitions in rte_mbuf.h. */ const char *rte_get_rx_ol_flag_name(uint64_t mask) { switch (mask) { case PKT_RX_VLAN_PKT: return "PKT_RX_VLAN_PKT"; case PKT_RX_RSS_HASH: return "PKT_RX_RSS_HASH"; case PKT_RX_FDIR: return "PKT_RX_FDIR"; case PKT_RX_L4_CKSUM_BAD: return "PKT_RX_L4_CKSUM_BAD"; case PKT_RX_IP_CKSUM_BAD: return "PKT_RX_IP_CKSUM_BAD"; /* case PKT_RX_EIP_CKSUM_BAD: return "PKT_RX_EIP_CKSUM_BAD"; */ /* case PKT_RX_OVERSIZE: return "PKT_RX_OVERSIZE"; */ /* case PKT_RX_HBUF_OVERFLOW: return "PKT_RX_HBUF_OVERFLOW"; */ /* case PKT_RX_RECIP_ERR: return "PKT_RX_RECIP_ERR"; */ /* case PKT_RX_MAC_ERR: return "PKT_RX_MAC_ERR"; */ #ifndef RTE_NEXT_ABI case PKT_RX_IPV4_HDR: return "PKT_RX_IPV4_HDR"; case PKT_RX_IPV4_HDR_EXT: return "PKT_RX_IPV4_HDR_EXT"; case PKT_RX_IPV6_HDR: return "PKT_RX_IPV6_HDR"; case PKT_RX_IPV6_HDR_EXT: return "PKT_RX_IPV6_HDR_EXT"; #endif /* RTE_NEXT_ABI */ case PKT_RX_IEEE1588_PTP: return "PKT_RX_IEEE1588_PTP"; case PKT_RX_IEEE1588_TMST: return "PKT_RX_IEEE1588_TMST"; #ifndef RTE_NEXT_ABI case PKT_RX_TUNNEL_IPV4_HDR: return "PKT_RX_TUNNEL_IPV4_HDR"; case PKT_RX_TUNNEL_IPV6_HDR: return "PKT_RX_TUNNEL_IPV6_HDR"; #endif /* RTE_NEXT_ABI */ default: return NULL; } } /* * Get the name of a TX offload flag. Must be kept synchronized with flag * definitions in rte_mbuf.h. */ const char *rte_get_tx_ol_flag_name(uint64_t mask) { switch (mask) { case PKT_TX_VLAN_PKT: return "PKT_TX_VLAN_PKT"; case PKT_TX_IP_CKSUM: return "PKT_TX_IP_CKSUM"; case PKT_TX_TCP_CKSUM: return "PKT_TX_TCP_CKSUM"; case PKT_TX_SCTP_CKSUM: return "PKT_TX_SCTP_CKSUM"; case PKT_TX_UDP_CKSUM: return "PKT_TX_UDP_CKSUM"; case PKT_TX_IEEE1588_TMST: return "PKT_TX_IEEE1588_TMST"; case PKT_TX_TCP_SEG: return "PKT_TX_TCP_SEG"; case PKT_TX_IPV4: return "PKT_TX_IPV4"; case PKT_TX_IPV6: return "PKT_TX_IPV6"; case PKT_TX_OUTER_IP_CKSUM: return "PKT_TX_OUTER_IP_CKSUM"; case PKT_TX_OUTER_IPV4: return "PKT_TX_OUTER_IPV4"; case PKT_TX_OUTER_IPV6: return "PKT_TX_OUTER_IPV6"; default: return NULL; } } ================================================ FILE: lib/librte_mbuf/rte_mbuf.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MBUF_H_ #define _RTE_MBUF_H_ /** * @file * RTE Mbuf * * The mbuf library provides the ability to create and destroy buffers * that may be used by the RTE application to store message * buffers. The message buffers are stored in a mempool, using the * RTE mempool library. * * This library provide an API to allocate/free packet mbufs, which are * used to carry network packets. * * To understand the concepts of packet buffers or mbufs, you * should read "TCP/IP Illustrated, Volume 2: The Implementation, * Addison-Wesley, 1995, ISBN 0-201-63354-X from Richard Stevens" * http://www.kohala.com/start/tcpipiv2.html */ #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* deprecated options */ #pragma GCC poison RTE_MBUF_SCATTER_GATHER #pragma GCC poison RTE_MBUF_REFCNT /* * Packet Offload Features Flags. It also carry packet type information. * Critical resources. Both rx/tx shared these bits. Be cautious on any change * * - RX flags start at bit position zero, and get added to the left of previous * flags. * - The most-significant 3 bits are reserved for generic mbuf flags * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get * added to the right of the previously defined flags i.e. they should count * downwards, not upwards. * * Keep these flags synchronized with rte_get_rx_ol_flag_name() and * rte_get_tx_ol_flag_name(). */ #define PKT_RX_VLAN_PKT (1ULL << 0) /**< RX packet is a 802.1q VLAN packet. */ #define PKT_RX_RSS_HASH (1ULL << 1) /**< RX packet with RSS hash result. */ #define PKT_RX_FDIR (1ULL << 2) /**< RX packet with FDIR match indicate. */ #define PKT_RX_L4_CKSUM_BAD (1ULL << 3) /**< L4 cksum of RX pkt. is not OK. */ #define PKT_RX_IP_CKSUM_BAD (1ULL << 4) /**< IP cksum of RX pkt. is not OK. */ #define PKT_RX_EIP_CKSUM_BAD (0ULL << 0) /**< External IP header checksum error. */ #define PKT_RX_OVERSIZE (0ULL << 0) /**< Num of desc of an RX pkt oversize. */ #define PKT_RX_HBUF_OVERFLOW (0ULL << 0) /**< Header buffer overflow. */ #define PKT_RX_RECIP_ERR (0ULL << 0) /**< Hardware processing error. */ #define PKT_RX_MAC_ERR (0ULL << 0) /**< MAC error. */ #ifndef RTE_NEXT_ABI #define PKT_RX_IPV4_HDR (1ULL << 5) /**< RX packet with IPv4 header. */ #define PKT_RX_IPV4_HDR_EXT (1ULL << 6) /**< RX packet with extended IPv4 header. */ #define PKT_RX_IPV6_HDR (1ULL << 7) /**< RX packet with IPv6 header. */ #define PKT_RX_IPV6_HDR_EXT (1ULL << 8) /**< RX packet with extended IPv6 header. */ #endif /* RTE_NEXT_ABI */ #define PKT_RX_IEEE1588_PTP (1ULL << 9) /**< RX IEEE1588 L2 Ethernet PT Packet. */ #define PKT_RX_IEEE1588_TMST (1ULL << 10) /**< RX IEEE1588 L2/L4 timestamped packet.*/ #ifndef RTE_NEXT_ABI #define PKT_RX_TUNNEL_IPV4_HDR (1ULL << 11) /**< RX tunnel packet with IPv4 header.*/ #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with IPv6 header. */ #endif /* RTE_NEXT_ABI */ #define PKT_RX_FDIR_ID (1ULL << 13) /**< FD id reported if FDIR match. */ #define PKT_RX_FDIR_FLX (1ULL << 14) /**< Flexible bytes reported if FDIR match. */ #define PKT_RX_QINQ_PKT (1ULL << 15) /**< RX packet with double VLAN stripped. */ /* add new RX flags here */ /* add new TX flags here */ /** * Second VLAN insertion (QinQ) flag. */ #define PKT_TX_QINQ_PKT (1ULL << 49) /**< TX packet with double VLAN inserted. */ /** * TCP segmentation offload. To enable this offload feature for a * packet to be transmitted on hardware supporting TSO: * - set the PKT_TX_TCP_SEG flag in mbuf->ol_flags (this flag implies * PKT_TX_TCP_CKSUM) * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 * - if it's IPv4, set the PKT_TX_IP_CKSUM flag and write the IP checksum * to 0 in the packet * - fill the mbuf offload information: l2_len, l3_len, l4_len, tso_segsz * - calculate the pseudo header checksum without taking ip_len in account, * and set it in the TCP header. Refer to rte_ipv4_phdr_cksum() and * rte_ipv6_phdr_cksum() that can be used as helpers. */ #define PKT_TX_TCP_SEG (1ULL << 50) #define PKT_TX_IEEE1588_TMST (1ULL << 51) /**< TX IEEE1588 packet to timestamp. */ /** * Bits 52+53 used for L4 packet type with checksum enabled: 00: Reserved, * 01: TCP checksum, 10: SCTP checksum, 11: UDP checksum. To use hardware * L4 checksum offload, the user needs to: * - fill l2_len and l3_len in mbuf * - set the flags PKT_TX_TCP_CKSUM, PKT_TX_SCTP_CKSUM or PKT_TX_UDP_CKSUM * - set the flag PKT_TX_IPV4 or PKT_TX_IPV6 * - calculate the pseudo header checksum and set it in the L4 header (only * for TCP or UDP). See rte_ipv4_phdr_cksum() and rte_ipv6_phdr_cksum(). * For SCTP, set the crc field to 0. */ #define PKT_TX_L4_NO_CKSUM (0ULL << 52) /**< Disable L4 cksum of TX pkt. */ #define PKT_TX_TCP_CKSUM (1ULL << 52) /**< TCP cksum of TX pkt. computed by NIC. */ #define PKT_TX_SCTP_CKSUM (2ULL << 52) /**< SCTP cksum of TX pkt. computed by NIC. */ #define PKT_TX_UDP_CKSUM (3ULL << 52) /**< UDP cksum of TX pkt. computed by NIC. */ #define PKT_TX_L4_MASK (3ULL << 52) /**< Mask for L4 cksum offload request. */ /** * Offload the IP checksum in the hardware. The flag PKT_TX_IPV4 should * also be set by the application, although a PMD will only check * PKT_TX_IP_CKSUM. * - set the IP checksum field in the packet to 0 * - fill the mbuf offload information: l2_len, l3_len */ #define PKT_TX_IP_CKSUM (1ULL << 54) /** * Packet is IPv4. This flag must be set when using any offload feature * (TSO, L3 or L4 checksum) to tell the NIC that the packet is an IPv4 * packet. If the packet is a tunneled packet, this flag is related to * the inner headers. */ #define PKT_TX_IPV4 (1ULL << 55) /** * Packet is IPv6. This flag must be set when using an offload feature * (TSO or L4 checksum) to tell the NIC that the packet is an IPv6 * packet. If the packet is a tunneled packet, this flag is related to * the inner headers. */ #define PKT_TX_IPV6 (1ULL << 56) #define PKT_TX_VLAN_PKT (1ULL << 57) /**< TX packet is a 802.1q VLAN packet. */ /** * Offload the IP checksum of an external header in the hardware. The * flag PKT_TX_OUTER_IPV4 should also be set by the application, alto ugh * a PMD will only check PKT_TX_IP_CKSUM. The IP checksum field in the * packet must be set to 0. * - set the outer IP checksum field in the packet to 0 * - fill the mbuf offload information: outer_l2_len, outer_l3_len */ #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58) /** * Packet outer header is IPv4. This flag must be set when using any * outer offload feature (L3 or L4 checksum) to tell the NIC that the * outer header of the tunneled packet is an IPv4 packet. */ #define PKT_TX_OUTER_IPV4 (1ULL << 59) /** * Packet outer header is IPv6. This flag must be set when using any * outer offload feature (L4 checksum) to tell the NIC that the outer * header of the tunneled packet is an IPv6 packet. */ #define PKT_TX_OUTER_IPV6 (1ULL << 60) #define __RESERVED (1ULL << 61) /**< reserved for future mbuf use */ #define IND_ATTACHED_MBUF (1ULL << 62) /**< Indirect attached mbuf */ /* Use final bit of flags to indicate a control mbuf */ #define CTRL_MBUF_FLAG (1ULL << 63) /**< Mbuf contains control data */ #ifdef RTE_NEXT_ABI /* * 32 bits are divided into several fields to mark packet types. Note that * each field is indexical. * - Bit 3:0 is for L2 types. * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types. * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types. * - Bit 15:12 is for tunnel types. * - Bit 19:16 is for inner L2 types. * - Bit 23:20 is for inner L3 types. * - Bit 27:24 is for inner L4 types. * - Bit 31:28 is reserved. * * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT, * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits. * * Note that L3 types values are selected for checking IPV4/IPV6 header from * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values. * * Note that the packet types of the same packet recognized by different * hardware may be different, as different hardware may have different * capability of packet type recognition. * * examples: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=0x29 * | 'version'=6, 'next header'=0x3A * | 'ICMPv6 header'> * will be recognized on i40e hardware as packet type combination of, * RTE_PTYPE_L2_ETHER | * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN | * RTE_PTYPE_TUNNEL_IP | * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | * RTE_PTYPE_INNER_L4_ICMP. * * <'ether type'=0x86DD * | 'version'=6, 'next header'=0x2F * | 'GRE header' * | 'version'=6, 'next header'=0x11 * | 'UDP header'> * will be recognized on i40e hardware as packet type combination of, * RTE_PTYPE_L2_ETHER | * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN | * RTE_PTYPE_TUNNEL_GRENAT | * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN | * RTE_PTYPE_INNER_L4_UDP. */ #define RTE_PTYPE_UNKNOWN 0x00000000 /** * Ethernet packet type. * It is used for outer packet for tunneling cases. * * Packet format: * <'ether type'=[0x0800|0x86DD]> */ #define RTE_PTYPE_L2_ETHER 0x00000001 /** * Ethernet packet type for time sync. * * Packet format: * <'ether type'=0x88F7> */ #define RTE_PTYPE_L2_ETHER_TIMESYNC 0x00000002 /** * ARP (Address Resolution Protocol) packet type. * * Packet format: * <'ether type'=0x0806> */ #define RTE_PTYPE_L2_ETHER_ARP 0x00000003 /** * LLDP (Link Layer Discovery Protocol) packet type. * * Packet format: * <'ether type'=0x88CC> */ #define RTE_PTYPE_L2_ETHER_LLDP 0x00000004 /** * Mask of layer 2 packet types. * It is used for outer packet for tunneling cases. */ #define RTE_PTYPE_L2_MASK 0x0000000f /** * IP (Internet Protocol) version 4 packet type. * It is used for outer packet for tunneling cases, and does not contain any * header option. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'ihl'=5> */ #define RTE_PTYPE_L3_IPV4 0x00000010 /** * IP (Internet Protocol) version 4 packet type. * It is used for outer packet for tunneling cases, and contains header * options. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'ihl'=[6-15], 'options'> */ #define RTE_PTYPE_L3_IPV4_EXT 0x00000030 /** * IP (Internet Protocol) version 6 packet type. * It is used for outer packet for tunneling cases, and does not contain any * extension header. * * Packet format: * <'ether type'=0x86DD * | 'version'=6, 'next header'=0x3B> */ #define RTE_PTYPE_L3_IPV6 0x00000040 /** * IP (Internet Protocol) version 4 packet type. * It is used for outer packet for tunneling cases, and may or maynot contain * header options. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'ihl'=[5-15], <'options'>> */ #define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090 /** * IP (Internet Protocol) version 6 packet type. * It is used for outer packet for tunneling cases, and contains extension * headers. * * Packet format: * <'ether type'=0x86DD * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], * 'extension headers'> */ #define RTE_PTYPE_L3_IPV6_EXT 0x000000c0 /** * IP (Internet Protocol) version 6 packet type. * It is used for outer packet for tunneling cases, and may or maynot contain * extension headers. * * Packet format: * <'ether type'=0x86DD * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], * <'extension headers'>> */ #define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0 /** * Mask of layer 3 packet types. * It is used for outer packet for tunneling cases. */ #define RTE_PTYPE_L3_MASK 0x000000f0 /** * TCP (Transmission Control Protocol) packet type. * It is used for outer packet for tunneling cases. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=6, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=6> */ #define RTE_PTYPE_L4_TCP 0x00000100 /** * UDP (User Datagram Protocol) packet type. * It is used for outer packet for tunneling cases. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=17, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=17> */ #define RTE_PTYPE_L4_UDP 0x00000200 /** * Fragmented IP (Internet Protocol) packet type. * It is used for outer packet for tunneling cases. * * It refers to those packets of any IP types, which can be recognized as * fragmented. A fragmented packet cannot be recognized as any other L4 types * (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, * RTE_PTYPE_L4_NONFRAG). * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'MF'=1> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=44> */ #define RTE_PTYPE_L4_FRAG 0x00000300 /** * SCTP (Stream Control Transmission Protocol) packet type. * It is used for outer packet for tunneling cases. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=132, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=132> */ #define RTE_PTYPE_L4_SCTP 0x00000400 /** * ICMP (Internet Control Message Protocol) packet type. * It is used for outer packet for tunneling cases. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=1, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=1> */ #define RTE_PTYPE_L4_ICMP 0x00000500 /** * Non-fragmented IP (Internet Protocol) packet type. * It is used for outer packet for tunneling cases. * * It refers to those packets of any IP types, while cannot be recognized as * any of above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, * RTE_PTYPE_L4_FRAG, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP). * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'!=[6|17|44|132|1]> */ #define RTE_PTYPE_L4_NONFRAG 0x00000600 /** * Mask of layer 4 packet types. * It is used for outer packet for tunneling cases. */ #define RTE_PTYPE_L4_MASK 0x00000f00 /** * IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=[4|41]> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=[4|41]> */ #define RTE_PTYPE_TUNNEL_IP 0x00001000 /** * GRE (Generic Routing Encapsulation) tunneling packet type. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=47> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=47> */ #define RTE_PTYPE_TUNNEL_GRE 0x00002000 /** * VXLAN (Virtual eXtensible Local Area Network) tunneling packet type. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=17 * | 'destination port'=4798> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=17 * | 'destination port'=4798> */ #define RTE_PTYPE_TUNNEL_VXLAN 0x00003000 /** * NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling * packet type. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=47 * | 'protocol type'=0x6558> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=47 * | 'protocol type'=0x6558'> */ #define RTE_PTYPE_TUNNEL_NVGRE 0x00004000 /** * GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type. * * Packet format: * <'ether type'=0x0800 * | 'version'=4, 'protocol'=17 * | 'destination port'=6081> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=17 * | 'destination port'=6081> */ #define RTE_PTYPE_TUNNEL_GENEVE 0x00005000 /** * Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area * Network) or GRE (Generic Routing Encapsulation) could be recognized as this * packet type, if they can not be recognized independently as of hardware * capability. */ #define RTE_PTYPE_TUNNEL_GRENAT 0x00006000 /** * Mask of tunneling packet types. */ #define RTE_PTYPE_TUNNEL_MASK 0x0000f000 /** * Ethernet packet type. * It is used for inner packet type only. * * Packet format (inner only): * <'ether type'=[0x800|0x86DD]> */ #define RTE_PTYPE_INNER_L2_ETHER 0x00010000 /** * Ethernet packet type with VLAN (Virtual Local Area Network) tag. * * Packet format (inner only): * <'ether type'=[0x800|0x86DD], vlan=[1-4095]> */ #define RTE_PTYPE_INNER_L2_ETHER_VLAN 0x00020000 /** * Mask of inner layer 2 packet types. */ #define RTE_PTYPE_INNER_L2_MASK 0x000f0000 /** * IP (Internet Protocol) version 4 packet type. * It is used for inner packet only, and does not contain any header option. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'ihl'=5> */ #define RTE_PTYPE_INNER_L3_IPV4 0x00100000 /** * IP (Internet Protocol) version 4 packet type. * It is used for inner packet only, and contains header options. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'ihl'=[6-15], 'options'> */ #define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000 /** * IP (Internet Protocol) version 6 packet type. * It is used for inner packet only, and does not contain any extension header. * * Packet format (inner only): * <'ether type'=0x86DD * | 'version'=6, 'next header'=0x3B> */ #define RTE_PTYPE_INNER_L3_IPV6 0x00300000 /** * IP (Internet Protocol) version 4 packet type. * It is used for inner packet only, and may or maynot contain header options. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'ihl'=[5-15], <'options'>> */ #define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000 /** * IP (Internet Protocol) version 6 packet type. * It is used for inner packet only, and contains extension headers. * * Packet format (inner only): * <'ether type'=0x86DD * | 'version'=6, 'next header'=[0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], * 'extension headers'> */ #define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000 /** * IP (Internet Protocol) version 6 packet type. * It is used for inner packet only, and may or maynot contain extension * headers. * * Packet format (inner only): * <'ether type'=0x86DD * | 'version'=6, 'next header'=[0x3B|0x0|0x2B|0x2C|0x32|0x33|0x3C|0x87], * <'extension headers'>> */ #define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000 /** * Mask of inner layer 3 packet types. */ #define RTE_PTYPE_INNER_L3_MASK 0x00f00000 /** * TCP (Transmission Control Protocol) packet type. * It is used for inner packet only. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'protocol'=6, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=6> */ #define RTE_PTYPE_INNER_L4_TCP 0x01000000 /** * UDP (User Datagram Protocol) packet type. * It is used for inner packet only. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'protocol'=17, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=17> */ #define RTE_PTYPE_INNER_L4_UDP 0x02000000 /** * Fragmented IP (Internet Protocol) packet type. * It is used for inner packet only, and may or maynot have layer 4 packet. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'MF'=1> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=44> */ #define RTE_PTYPE_INNER_L4_FRAG 0x03000000 /** * SCTP (Stream Control Transmission Protocol) packet type. * It is used for inner packet only. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'protocol'=132, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=132> */ #define RTE_PTYPE_INNER_L4_SCTP 0x04000000 /** * ICMP (Internet Control Message Protocol) packet type. * It is used for inner packet only. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'protocol'=1, 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'=1> */ #define RTE_PTYPE_INNER_L4_ICMP 0x05000000 /** * Non-fragmented IP (Internet Protocol) packet type. * It is used for inner packet only, and may or maynot have other unknown layer * 4 packet types. * * Packet format (inner only): * <'ether type'=0x0800 * | 'version'=4, 'protocol'!=[6|17|132|1], 'MF'=0> * or, * <'ether type'=0x86DD * | 'version'=6, 'next header'!=[6|17|44|132|1]> */ #define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000 /** * Mask of inner layer 4 packet types. */ #define RTE_PTYPE_INNER_L4_MASK 0x0f000000 /** * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by * one, bit 4 is selected to be used for IPv4 only. Then checking bit 4 can * determine if it is an IPV4 packet. */ #define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4) /** * Check if the (outer) L3 header is IPv4. To avoid comparing IPv4 types one by * one, bit 6 is selected to be used for IPv4 only. Then checking bit 6 can * determine if it is an IPV4 packet. */ #define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6) /* Check if it is a tunneling packet */ #define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & (RTE_PTYPE_TUNNEL_MASK | \ RTE_PTYPE_INNER_L2_MASK | \ RTE_PTYPE_INNER_L3_MASK | \ RTE_PTYPE_INNER_L4_MASK)) #endif /* RTE_NEXT_ABI */ /** Alignment constraint of mbuf private area. */ #define RTE_MBUF_PRIV_ALIGN 8 /** * Get the name of a RX offload flag * * @param mask * The mask describing the flag. * @return * The name of this flag, or NULL if it's not a valid RX flag. */ const char *rte_get_rx_ol_flag_name(uint64_t mask); /** * Get the name of a TX offload flag * * @param mask * The mask describing the flag. Usually only one bit must be set. * Several bits can be given if they belong to the same mask. * Ex: PKT_TX_L4_MASK. * @return * The name of this flag, or NULL if it's not a valid TX flag. */ const char *rte_get_tx_ol_flag_name(uint64_t mask); /** * Some NICs need at least 2KB buffer to RX standard Ethernet frame without * splitting it into multiple segments. * So, for mbufs that planned to be involved into RX/TX, the recommended * minimal buffer length is 2KB + RTE_PKTMBUF_HEADROOM. */ #define RTE_MBUF_DEFAULT_DATAROOM 2048 #define RTE_MBUF_DEFAULT_BUF_SIZE \ (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM) /* define a set of marker types that can be used to refer to set points in the * mbuf */ typedef void *MARKER[0]; /**< generic marker for a point in a structure */ typedef uint8_t MARKER8[0]; /**< generic marker with 1B alignment */ typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes * with a single assignment */ /** * The generic rte_mbuf, containing a packet mbuf. */ struct rte_mbuf { MARKER cacheline0; void *buf_addr; /**< Virtual address of segment buffer. */ phys_addr_t buf_physaddr; /**< Physical address of segment buffer. */ uint16_t buf_len; /**< Length of segment buffer. */ /* next 6 bytes are initialised on RX descriptor rearm */ MARKER8 rearm_data; uint16_t data_off; /** * 16-bit Reference counter. * It should only be accessed using the following functions: * rte_mbuf_refcnt_update(), rte_mbuf_refcnt_read(), and * rte_mbuf_refcnt_set(). The functionality of these functions (atomic, * or non-atomic) is controlled by the CONFIG_RTE_MBUF_REFCNT_ATOMIC * config option. */ union { rte_atomic16_t refcnt_atomic; /**< Atomically accessed refcnt */ uint16_t refcnt; /**< Non-atomically accessed refcnt */ }; uint8_t nb_segs; /**< Number of segments. */ uint8_t port; /**< Input port. */ uint64_t ol_flags; /**< Offload features. */ /* remaining bytes are set on RX when pulling packet from descriptor */ MARKER rx_descriptor_fields1; #ifdef RTE_NEXT_ABI /* * The packet type, which is the combination of outer/inner L2, L3, L4 * and tunnel types. */ union { uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */ struct { uint32_t l2_type:4; /**< (Outer) L2 type. */ uint32_t l3_type:4; /**< (Outer) L3 type. */ uint32_t l4_type:4; /**< (Outer) L4 type. */ uint32_t tun_type:4; /**< Tunnel type. */ uint32_t inner_l2_type:4; /**< Inner L2 type. */ uint32_t inner_l3_type:4; /**< Inner L3 type. */ uint32_t inner_l4_type:4; /**< Inner L4 type. */ }; }; uint32_t pkt_len; /**< Total pkt len: sum of all segments. */ uint16_t data_len; /**< Amount of data in segment buffer. */ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */ #else /* RTE_NEXT_ABI */ /** * The packet type, which is used to indicate ordinary packet and also * tunneled packet format, i.e. each number is represented a type of * packet. */ uint16_t packet_type; uint16_t data_len; /**< Amount of data in segment buffer. */ uint32_t pkt_len; /**< Total pkt len: sum of all segments. */ uint16_t vlan_tci; /**< VLAN Tag Control Identifier (CPU order) */ uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */ #endif /* RTE_NEXT_ABI */ union { uint32_t rss; /**< RSS hash result if RSS enabled */ struct { union { struct { uint16_t hash; uint16_t id; }; uint32_t lo; /**< Second 4 flexible bytes */ }; uint32_t hi; /**< First 4 flexible bytes or FD ID, dependent on PKT_RX_FDIR_* flag in ol_flags. */ } fdir; /**< Filter identifier if FDIR enabled */ uint32_t sched; /**< Hierarchical scheduler */ uint32_t usr; /**< User defined tags. See rte_distributor_process() */ } hash; /**< hash information */ uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */ #ifdef RTE_NEXT_ABI uint16_t vlan_tci_outer; /**< Outer VLAN Tag Control Identifier (CPU order) */ #endif /* RTE_NEXT_ABI */ /* second cache line - fields only used in slow path or on TX */ MARKER cacheline1 __rte_cache_aligned; union { void *userdata; /**< Can be used for external metadata */ uint64_t udata64; /**< Allow 8-byte userdata on 32-bit */ }; struct rte_mempool *pool; /**< Pool from which mbuf was allocated. */ struct rte_mbuf *next; /**< Next segment of scattered packet. */ /* fields to support TX offloads */ union { uint64_t tx_offload; /**< combined for easy fetch */ struct { uint64_t l2_len:7; /**< L2 (MAC) Header Length. */ uint64_t l3_len:9; /**< L3 (IP) Header Length. */ uint64_t l4_len:8; /**< L4 (TCP/UDP) Header Length. */ uint64_t tso_segsz:16; /**< TCP TSO segment size */ /* fields for TX offloading of tunnels */ uint64_t outer_l3_len:9; /**< Outer L3 (IP) Hdr Length. */ uint64_t outer_l2_len:7; /**< Outer L2 (MAC) Hdr Length. */ /* uint64_t unused:8; */ }; }; /** Size of the application private data. In case of an indirect * mbuf, it stores the direct mbuf private data size. */ uint16_t priv_size; /** Timesync flags for use with IEEE1588. */ uint16_t timesync; } __rte_cache_aligned; static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp); /** * Return the mbuf owning the data buffer address of an indirect mbuf. * * @param mi * The pointer to the indirect mbuf. * @return * The address of the direct mbuf corresponding to buffer_addr. */ static inline struct rte_mbuf * rte_mbuf_from_indirect(struct rte_mbuf *mi) { return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size); } /** * Return the buffer address embedded in the given mbuf. * * @param md * The pointer to the mbuf. * @return * The address of the data buffer owned by the mbuf. */ static inline char * rte_mbuf_to_baddr(struct rte_mbuf *md) { char *buffer_addr; buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool); return buffer_addr; } /** * Returns TRUE if given mbuf is indirect, or FALSE otherwise. */ #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF) /** * Returns TRUE if given mbuf is direct, or FALSE otherwise. */ #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb)) /** * Private data in case of pktmbuf pool. * * A structure that contains some pktmbuf_pool-specific data that are * appended after the mempool structure (in private data). */ struct rte_pktmbuf_pool_private { uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf. */ uint16_t mbuf_priv_size; /**< Size of private area in each mbuf. */ }; #ifdef RTE_LIBRTE_MBUF_DEBUG /** check mbuf type in debug mode */ #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h) /** check mbuf type in debug mode if mbuf pointer is not null */ #define __rte_mbuf_sanity_check_raw(m, is_h) do { \ if ((m) != NULL) \ rte_mbuf_sanity_check(m, is_h); \ } while (0) /** MBUF asserts in debug mode */ #define RTE_MBUF_ASSERT(exp) \ if (!(exp)) { \ rte_panic("line%d\tassert \"" #exp "\" failed\n", __LINE__); \ } #else /* RTE_LIBRTE_MBUF_DEBUG */ /** check mbuf type in debug mode */ #define __rte_mbuf_sanity_check(m, is_h) do { } while (0) /** check mbuf type in debug mode if mbuf pointer is not null */ #define __rte_mbuf_sanity_check_raw(m, is_h) do { } while (0) /** MBUF asserts in debug mode */ #define RTE_MBUF_ASSERT(exp) do { } while (0) #endif /* RTE_LIBRTE_MBUF_DEBUG */ #ifdef RTE_MBUF_REFCNT_ATOMIC /** * Reads the value of an mbuf's refcnt. * @param m * Mbuf to read * @return * Reference count number. */ static inline uint16_t rte_mbuf_refcnt_read(const struct rte_mbuf *m) { return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic)); } /** * Sets an mbuf's refcnt to a defined value. * @param m * Mbuf to update * @param new_value * Value set */ static inline void rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) { rte_atomic16_set(&m->refcnt_atomic, new_value); } /** * Adds given value to an mbuf's refcnt and returns its new value. * @param m * Mbuf to update * @param value * Value to add/subtract * @return * Updated value */ static inline uint16_t rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) { /* * The atomic_add is an expensive operation, so we don't want to * call it in the case where we know we are the uniq holder of * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic * operation has to be used because concurrent accesses on the * reference counter can occur. */ if (likely(rte_mbuf_refcnt_read(m) == 1)) { rte_mbuf_refcnt_set(m, 1 + value); return 1 + value; } return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value)); } #else /* ! RTE_MBUF_REFCNT_ATOMIC */ /** * Adds given value to an mbuf's refcnt and returns its new value. */ static inline uint16_t rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value) { m->refcnt = (uint16_t)(m->refcnt + value); return m->refcnt; } /** * Reads the value of an mbuf's refcnt. */ static inline uint16_t rte_mbuf_refcnt_read(const struct rte_mbuf *m) { return m->refcnt; } /** * Sets an mbuf's refcnt to the defined value. */ static inline void rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value) { m->refcnt = new_value; } #endif /* RTE_MBUF_REFCNT_ATOMIC */ /** Mbuf prefetch */ #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \ if ((m) != NULL) \ rte_prefetch0(m); \ } while (0) /** * Sanity checks on an mbuf. * * Check the consistency of the given mbuf. The function will cause a * panic if corruption is detected. * * @param m * The mbuf to be checked. * @param is_header * True if the mbuf is a packet header, false if it is a sub-segment * of a packet (in this case, some fields like nb_segs are not checked) */ void rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header); /** * @internal Allocate a new mbuf from mempool *mp*. * The use of that function is reserved for RTE internal needs. * Please use rte_pktmbuf_alloc(). * * @param mp * The mempool from which mbuf is allocated. * @return * - The pointer to the new mbuf on success. * - NULL if allocation failed. */ static inline struct rte_mbuf *__rte_mbuf_raw_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; void *mb = NULL; if (rte_mempool_get(mp, &mb) < 0) return NULL; m = (struct rte_mbuf *)mb; RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0); rte_mbuf_refcnt_set(m, 1); return m; } /** * @internal Put mbuf back into its original mempool. * The use of that function is reserved for RTE internal needs. * Please use rte_pktmbuf_free(). * * @param m * The mbuf to be freed. */ static inline void __attribute__((always_inline)) __rte_mbuf_raw_free(struct rte_mbuf *m) { RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0); rte_mempool_put(m->pool, m); } /* Operations on ctrl mbuf */ /** * The control mbuf constructor. * * This function initializes some fields in an mbuf structure that are * not modified by the user once created (mbuf type, origin pool, buffer * start address, and so on). This function is given as a callback function * to rte_mempool_create() at pool creation time. * * @param mp * The mempool from which the mbuf is allocated. * @param opaque_arg * A pointer that can be used by the user to retrieve useful information * for mbuf initialization. This pointer comes from the ``init_arg`` * parameter of rte_mempool_create(). * @param m * The mbuf to initialize. * @param i * The index of the mbuf in the pool table. */ void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *m, unsigned i); /** * Allocate a new mbuf (type is ctrl) from mempool *mp*. * * This new mbuf is initialized with data pointing to the beginning of * buffer, and with a length of zero. * * @param mp * The mempool from which the mbuf is allocated. * @return * - The pointer to the new mbuf on success. * - NULL if allocation failed. */ #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp) /** * Free a control mbuf back into its original mempool. * * @param m * The control mbuf to be freed. */ #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m) /** * A macro that returns the pointer to the carried data. * * The value that can be read or assigned. * * @param m * The control mbuf. */ #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off) /** * A macro that returns the length of the carried data. * * The value that can be read or assigned. * * @param m * The control mbuf. */ #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m) /** * Tests if an mbuf is a control mbuf * * @param m * The mbuf to be tested * @return * - True (1) if the mbuf is a control mbuf * - False(0) otherwise */ static inline int rte_is_ctrlmbuf(struct rte_mbuf *m) { return !!(m->ol_flags & CTRL_MBUF_FLAG); } /* Operations on pkt mbuf */ /** * The packet mbuf constructor. * * This function initializes some fields in the mbuf structure that are * not modified by the user once created (origin pool, buffer start * address, and so on). This function is given as a callback function to * rte_mempool_create() at pool creation time. * * @param mp * The mempool from which mbufs originate. * @param opaque_arg * A pointer that can be used by the user to retrieve useful information * for mbuf initialization. This pointer comes from the ``init_arg`` * parameter of rte_mempool_create(). * @param m * The mbuf to initialize. * @param i * The index of the mbuf in the pool table. */ void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *m, unsigned i); /** * A packet mbuf pool constructor. * * This function initializes the mempool private data in the case of a * pktmbuf pool. This private data is needed by the driver. The * function is given as a callback function to rte_mempool_create() at * pool creation. It can be extended by the user, for example, to * provide another packet size. * * @param mp * The mempool from which mbufs originate. * @param opaque_arg * A pointer that can be used by the user to retrieve useful information * for mbuf initialization. This pointer comes from the ``init_arg`` * parameter of rte_mempool_create(). */ void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg); /** * Create a mbuf pool. * * This function creates and initializes a packet mbuf pool. It is * a wrapper to rte_mempool_create() with the proper packet constructor * and mempool constructor. * * @param name * The name of the mbuf pool. * @param n * The number of elements in the mbuf pool. The optimum size (in terms * of memory usage) for a mempool is when n is a power of two minus one: * n = (2^q - 1). * @param cache_size * Size of the per-core object cache. See rte_mempool_create() for * details. * @param priv_size * Size of application private are between the rte_mbuf structure * and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN. * @param data_room_size * Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM. * @param socket_id * The socket identifier where the memory should be allocated. The * value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the * reserved zone. * @return * The pointer to the new allocated mempool, on success. NULL on error * with rte_errno set appropriately. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - cache size provided is too large, or priv_size is not aligned. * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_mempool * rte_pktmbuf_pool_create(const char *name, unsigned n, unsigned cache_size, uint16_t priv_size, uint16_t data_room_size, int socket_id); /** * Get the data room size of mbufs stored in a pktmbuf_pool * * The data room size is the amount of data that can be stored in a * mbuf including the headroom (RTE_PKTMBUF_HEADROOM). * * @param mp * The packet mbuf pool. * @return * The data room size of mbufs stored in this mempool. */ static inline uint16_t rte_pktmbuf_data_room_size(struct rte_mempool *mp) { struct rte_pktmbuf_pool_private *mbp_priv; mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); return mbp_priv->mbuf_data_room_size; } /** * Get the application private size of mbufs stored in a pktmbuf_pool * * The private size of mbuf is a zone located between the rte_mbuf * structure and the data buffer where an application can store data * associated to a packet. * * @param mp * The packet mbuf pool. * @return * The private size of mbufs stored in this mempool. */ static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp) { struct rte_pktmbuf_pool_private *mbp_priv; mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp); return mbp_priv->mbuf_priv_size; } /** * Reset the fields of a packet mbuf to their default values. * * The given mbuf must have only one segment. * * @param m * The packet mbuf to be resetted. */ static inline void rte_pktmbuf_reset(struct rte_mbuf *m) { m->next = NULL; m->pkt_len = 0; m->tx_offload = 0; m->vlan_tci = 0; m->vlan_tci_outer = 0; m->nb_segs = 1; m->port = 0xff; m->ol_flags = 0; m->packet_type = 0; m->data_off = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ? RTE_PKTMBUF_HEADROOM : m->buf_len; m->data_len = 0; __rte_mbuf_sanity_check(m, 1); } /** * Allocate a new mbuf from a mempool. * * This new mbuf contains one segment, which has a length of 0. The pointer * to data is initialized to have some bytes of headroom in the buffer * (if buffer size allows). * * @param mp * The mempool from which the mbuf is allocated. * @return * - The pointer to the new mbuf on success. * - NULL if allocation failed. */ static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp) { struct rte_mbuf *m; if ((m = __rte_mbuf_raw_alloc(mp)) != NULL) rte_pktmbuf_reset(m); return m; } /** * Attach packet mbuf to another packet mbuf. * * After attachment we refer the mbuf we attached as 'indirect', * while mbuf we attached to as 'direct'. * Right now, not supported: * - attachment for already indirect mbuf (e.g. - mi has to be direct). * - mbuf we trying to attach (mi) is used by someone else * e.g. it's reference counter is greater then 1. * * @param mi * The indirect packet mbuf. * @param m * The packet mbuf we're attaching to. */ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m) { struct rte_mbuf *md; RTE_MBUF_ASSERT(RTE_MBUF_DIRECT(mi) && rte_mbuf_refcnt_read(mi) == 1); /* if m is not direct, get the mbuf that embeds the data */ if (RTE_MBUF_DIRECT(m)) md = m; else md = rte_mbuf_from_indirect(m); rte_mbuf_refcnt_update(md, 1); mi->priv_size = m->priv_size; mi->buf_physaddr = m->buf_physaddr; mi->buf_addr = m->buf_addr; mi->buf_len = m->buf_len; mi->next = m->next; mi->data_off = m->data_off; mi->data_len = m->data_len; mi->port = m->port; mi->vlan_tci = m->vlan_tci; mi->vlan_tci_outer = m->vlan_tci_outer; mi->tx_offload = m->tx_offload; mi->hash = m->hash; mi->next = NULL; mi->pkt_len = mi->data_len; mi->nb_segs = 1; mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF; mi->packet_type = m->packet_type; __rte_mbuf_sanity_check(mi, 1); __rte_mbuf_sanity_check(m, 0); } /** * Detach an indirect packet mbuf. * * - restore original mbuf address and length values. * - reset pktmbuf data and data_len to their default values. * All other fields of the given packet mbuf will be left intact. * * @param m * The indirect attached packet mbuf. */ static inline void rte_pktmbuf_detach(struct rte_mbuf *m) { struct rte_mempool *mp = m->pool; uint32_t mbuf_size, buf_len, priv_size; priv_size = rte_pktmbuf_priv_size(mp); mbuf_size = sizeof(struct rte_mbuf) + priv_size; buf_len = rte_pktmbuf_data_room_size(mp); m->priv_size = priv_size; m->buf_addr = (char *)m + mbuf_size; m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size; m->buf_len = (uint16_t)buf_len; m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len); m->data_len = 0; m->ol_flags = 0; } static inline struct rte_mbuf* __attribute__((always_inline)) __rte_pktmbuf_prefree_seg(struct rte_mbuf *m) { __rte_mbuf_sanity_check(m, 0); if (likely(rte_mbuf_refcnt_update(m, -1) == 0)) { /* if this is an indirect mbuf, then * - detach mbuf * - free attached mbuf segment */ if (RTE_MBUF_INDIRECT(m)) { struct rte_mbuf *md = rte_mbuf_from_indirect(m); rte_pktmbuf_detach(m); if (rte_mbuf_refcnt_update(md, -1) == 0) __rte_mbuf_raw_free(md); } return m; } return NULL; } /** * Free a segment of a packet mbuf into its original mempool. * * Free an mbuf, without parsing other segments in case of chained * buffers. * * @param m * The packet mbuf segment to be freed. */ static inline void __attribute__((always_inline)) rte_pktmbuf_free_seg(struct rte_mbuf *m) { if (likely(NULL != (m = __rte_pktmbuf_prefree_seg(m)))) { m->next = NULL; __rte_mbuf_raw_free(m); } } /** * Free a packet mbuf back into its original mempool. * * Free an mbuf, and all its segments in case of chained buffers. Each * segment is added back into its original mempool. * * @param m * The packet mbuf to be freed. */ static inline void rte_pktmbuf_free(struct rte_mbuf *m) { struct rte_mbuf *m_next; __rte_mbuf_sanity_check(m, 1); while (m != NULL) { m_next = m->next; rte_pktmbuf_free_seg(m); m = m_next; } } /** * Creates a "clone" of the given packet mbuf. * * Walks through all segments of the given packet mbuf, and for each of them: * - Creates a new packet mbuf from the given pool. * - Attaches newly created mbuf to the segment. * Then updates pkt_len and nb_segs of the "clone" packet mbuf to match values * from the original packet mbuf. * * @param md * The packet mbuf to be cloned. * @param mp * The mempool from which the "clone" mbufs are allocated. * @return * - The pointer to the new "clone" mbuf on success. * - NULL if allocation fails. */ static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp) { struct rte_mbuf *mc, *mi, **prev; uint32_t pktlen; uint8_t nseg; if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL)) return NULL; mi = mc; prev = &mi->next; pktlen = md->pkt_len; nseg = 0; do { nseg++; rte_pktmbuf_attach(mi, md); *prev = mi; prev = &mi->next; } while ((md = md->next) != NULL && (mi = rte_pktmbuf_alloc(mp)) != NULL); *prev = NULL; mc->nb_segs = nseg; mc->pkt_len = pktlen; /* Allocation of new indirect segment failed */ if (unlikely (mi == NULL)) { rte_pktmbuf_free(mc); return NULL; } __rte_mbuf_sanity_check(mc, 1); return mc; } /** * Adds given value to the refcnt of all packet mbuf segments. * * Walks through all segments of given packet mbuf and for each of them * invokes rte_mbuf_refcnt_update(). * * @param m * The packet mbuf whose refcnt to be updated. * @param v * The value to add to the mbuf's segments refcnt. */ static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v) { __rte_mbuf_sanity_check(m, 1); do { rte_mbuf_refcnt_update(m, v); } while ((m = m->next) != NULL); } /** * Get the headroom in a packet mbuf. * * @param m * The packet mbuf. * @return * The length of the headroom. */ static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m) { __rte_mbuf_sanity_check(m, 1); return m->data_off; } /** * Get the tailroom of a packet mbuf. * * @param m * The packet mbuf. * @return * The length of the tailroom. */ static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m) { __rte_mbuf_sanity_check(m, 1); return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) - m->data_len); } /** * Get the last segment of the packet. * * @param m * The packet mbuf. * @return * The last segment of the given mbuf. */ static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m) { struct rte_mbuf *m2 = (struct rte_mbuf *)m; __rte_mbuf_sanity_check(m, 1); while (m2->next != NULL) m2 = m2->next; return m2; } /** * A macro that points to an offset into the data in the mbuf. * * The returned pointer is cast to type t. Before using this * function, the user must ensure that the first segment is large * enough to accommodate its data. * * @param m * The packet mbuf. * @param o * The offset into the mbuf data. * @param t * The type to cast the result into. */ #define rte_pktmbuf_mtod_offset(m, t, o) \ ((t)((char *)(m)->buf_addr + (m)->data_off + (o))) /** * A macro that points to the start of the data in the mbuf. * * The returned pointer is cast to type t. Before using this * function, the user must ensure that the first segment is large * enough to accommodate its data. * * @param m * The packet mbuf. * @param t * The type to cast the result into. */ #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0) /** * A macro that returns the length of the packet. * * The value can be read or assigned. * * @param m * The packet mbuf. */ #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len) /** * A macro that returns the length of the segment. * * The value can be read or assigned. * * @param m * The packet mbuf. */ #define rte_pktmbuf_data_len(m) ((m)->data_len) /** * Prepend len bytes to an mbuf data area. * * Returns a pointer to the new * data start address. If there is not enough headroom in the first * segment, the function will return NULL, without modifying the mbuf. * * @param m * The pkt mbuf. * @param len * The amount of data to prepend (in bytes). * @return * A pointer to the start of the newly prepended data, or * NULL if there is not enough headroom space in the first segment */ static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m, uint16_t len) { __rte_mbuf_sanity_check(m, 1); if (unlikely(len > rte_pktmbuf_headroom(m))) return NULL; m->data_off -= len; m->data_len = (uint16_t)(m->data_len + len); m->pkt_len = (m->pkt_len + len); return (char *)m->buf_addr + m->data_off; } /** * Append len bytes to an mbuf. * * Append len bytes to an mbuf and return a pointer to the start address * of the added data. If there is not enough tailroom in the last * segment, the function will return NULL, without modifying the mbuf. * * @param m * The packet mbuf. * @param len * The amount of data to append (in bytes). * @return * A pointer to the start of the newly appended data, or * NULL if there is not enough tailroom space in the last segment */ static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len) { void *tail; struct rte_mbuf *m_last; __rte_mbuf_sanity_check(m, 1); m_last = rte_pktmbuf_lastseg(m); if (unlikely(len > rte_pktmbuf_tailroom(m_last))) return NULL; tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len; m_last->data_len = (uint16_t)(m_last->data_len + len); m->pkt_len = (m->pkt_len + len); return (char*) tail; } /** * Remove len bytes at the beginning of an mbuf. * * Returns a pointer to the start address of the new data area. If the * length is greater than the length of the first segment, then the * function will fail and return NULL, without modifying the mbuf. * * @param m * The packet mbuf. * @param len * The amount of data to remove (in bytes). * @return * A pointer to the new start of the data. */ static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len) { __rte_mbuf_sanity_check(m, 1); if (unlikely(len > m->data_len)) return NULL; m->data_len = (uint16_t)(m->data_len - len); m->data_off += len; m->pkt_len = (m->pkt_len - len); return (char *)m->buf_addr + m->data_off; } /** * Remove len bytes of data at the end of the mbuf. * * If the length is greater than the length of the last segment, the * function will fail and return -1 without modifying the mbuf. * * @param m * The packet mbuf. * @param len * The amount of data to remove (in bytes). * @return * - 0: On success. * - -1: On error. */ static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len) { struct rte_mbuf *m_last; __rte_mbuf_sanity_check(m, 1); m_last = rte_pktmbuf_lastseg(m); if (unlikely(len > m_last->data_len)) return -1; m_last->data_len = (uint16_t)(m_last->data_len - len); m->pkt_len = (m->pkt_len - len); return 0; } /** * Test if mbuf data is contiguous. * * @param m * The packet mbuf. * @return * - 1, if all data is contiguous (one segment). * - 0, if there is several segments. */ static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m) { __rte_mbuf_sanity_check(m, 1); return !!(m->nb_segs == 1); } /** * Dump an mbuf structure to the console. * * Dump all fields for the given packet mbuf and all its associated * segments (in the case of a chained buffer). * * @param f * A pointer to a file for output * @param m * The packet mbuf. * @param dump_len * If dump_len != 0, also dump the "dump_len" first data bytes of * the packet. */ void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len); #ifdef __cplusplus } #endif #endif /* _RTE_MBUF_H_ */ ================================================ FILE: lib/librte_mempool/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_mempool.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_mempool_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool.c ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y) SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_dom0_mempool.c endif # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal lib/librte_ring include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_mempool/rte_dom0_mempool.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_mempool.h" static void get_phys_map(void *va, phys_addr_t pa[], uint32_t pg_num, uint32_t pg_sz, uint32_t memseg_id) { uint32_t i; uint64_t virt_addr, mfn_id; struct rte_mem_config *mcfg; uint32_t page_size = getpagesize(); /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; virt_addr = (uintptr_t) mcfg->memseg[memseg_id].addr; for (i = 0; i != pg_num; i++) { mfn_id = ((uintptr_t)va + i * pg_sz - virt_addr) / RTE_PGSIZE_2M; pa[i] = mcfg->memseg[memseg_id].mfn[mfn_id] * page_size; } } /* create the mempool for supporting Dom0 */ struct rte_mempool * rte_dom0_mempool_create(const char *name, unsigned elt_num, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags) { struct rte_mempool *mp = NULL; phys_addr_t *pa; char *va; size_t sz; uint32_t pg_num, pg_shift, pg_sz, total_size; const struct rte_memzone *mz; char mz_name[RTE_MEMZONE_NAMESIZE]; int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY; pg_sz = RTE_PGSIZE_2M; pg_shift = rte_bsf32(pg_sz); total_size = rte_mempool_calc_obj_size(elt_size, flags, NULL); /* calc max memory size and max number of pages needed. */ sz = rte_mempool_xmem_size(elt_num, total_size, pg_shift) + RTE_PGSIZE_2M; pg_num = sz >> pg_shift; /* extract physical mappings of the allocated memory. */ pa = calloc(pg_num, sizeof (*pa)); if (pa == NULL) return mp; snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_OBJ_NAME, name); mz = rte_memzone_reserve(mz_name, sz, socket_id, mz_flags); if (mz == NULL) { free(pa); return mp; } va = (char *)RTE_ALIGN_CEIL((uintptr_t)mz->addr, RTE_PGSIZE_2M); /* extract physical mappings of the allocated memory. */ get_phys_map(va, pa, pg_num, pg_sz, mz->memseg_id); mp = rte_mempool_xmem_create(name, elt_num, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags, va, pa, pg_num, pg_shift); free(pa); return mp; } ================================================ FILE: lib/librte_mempool/rte_mempool.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_mempool.h" TAILQ_HEAD(rte_mempool_list, rte_tailq_entry); static struct rte_tailq_elem rte_mempool_tailq = { .name = "RTE_MEMPOOL", }; EAL_REGISTER_TAILQ(rte_mempool_tailq) #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5 #define CALC_CACHE_FLUSHTHRESH(c) \ ((typeof(c))((c) * CACHE_FLUSHTHRESH_MULTIPLIER)) /* * return the greatest common divisor between a and b (fast algorithm) * */ static unsigned get_gcd(unsigned a, unsigned b) { unsigned c; if (0 == a) return b; if (0 == b) return a; if (a < b) { c = a; a = b; b = c; } while (b != 0) { c = a % b; a = b; b = c; } return a; } /* * Depending on memory configuration, objects addresses are spread * between channels and ranks in RAM: the pool allocator will add * padding between objects. This function return the new size of the * object. */ static unsigned optimize_object_size(unsigned obj_size) { unsigned nrank, nchan; unsigned new_obj_size; /* get number of channels */ nchan = rte_memory_get_nchannel(); if (nchan == 0) nchan = 1; nrank = rte_memory_get_nrank(); if (nrank == 0) nrank = 1; /* process new object size */ new_obj_size = (obj_size + RTE_MEMPOOL_ALIGN_MASK) / RTE_MEMPOOL_ALIGN; while (get_gcd(new_obj_size, nrank * nchan) != 1) new_obj_size++; return new_obj_size * RTE_MEMPOOL_ALIGN; } static void mempool_add_elem(struct rte_mempool *mp, void *obj, uint32_t obj_idx, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg) { struct rte_mempool_objhdr *hdr; struct rte_mempool_objtlr *tlr __rte_unused; obj = (char *)obj + mp->header_size; /* set mempool ptr in header */ hdr = RTE_PTR_SUB(obj, sizeof(*hdr)); hdr->mp = mp; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2; tlr = __mempool_get_trailer(obj); tlr->cookie = RTE_MEMPOOL_TRAILER_COOKIE; #endif /* call the initializer */ if (obj_init) obj_init(mp, obj_init_arg, obj, obj_idx); /* enqueue in ring */ rte_ring_sp_enqueue(mp->ring, obj); } uint32_t rte_mempool_obj_iter(void *vaddr, uint32_t elt_num, size_t elt_sz, size_t align, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift, rte_mempool_obj_iter_t obj_iter, void *obj_iter_arg) { uint32_t i, j, k; uint32_t pgn, pgf; uintptr_t end, start, va; uintptr_t pg_sz; pg_sz = (uintptr_t)1 << pg_shift; va = (uintptr_t)vaddr; i = 0; j = 0; while (i != elt_num && j != pg_num) { start = RTE_ALIGN_CEIL(va, align); end = start + elt_sz; /* index of the first page for the next element. */ pgf = (end >> pg_shift) - (start >> pg_shift); /* index of the last page for the current element. */ pgn = ((end - 1) >> pg_shift) - (start >> pg_shift); pgn += j; /* do we have enough space left for the element. */ if (pgn >= pg_num) break; for (k = j; k != pgn && paddr[k] + pg_sz == paddr[k + 1]; k++) ; /* * if next pgn chunks of memory physically continuous, * use it to create next element. * otherwise, just skip that chunk unused. */ if (k == pgn) { if (obj_iter != NULL) obj_iter(obj_iter_arg, (void *)start, (void *)end, i); va = end; j += pgf; i++; } else { va = RTE_ALIGN_CEIL((va + 1), pg_sz); j++; } } return i; } /* * Populate mempool with the objects. */ struct mempool_populate_arg { struct rte_mempool *mp; rte_mempool_obj_ctor_t *obj_init; void *obj_init_arg; }; static void mempool_obj_populate(void *arg, void *start, void *end, uint32_t idx) { struct mempool_populate_arg *pa = arg; mempool_add_elem(pa->mp, start, idx, pa->obj_init, pa->obj_init_arg); pa->mp->elt_va_end = (uintptr_t)end; } static void mempool_populate(struct rte_mempool *mp, size_t num, size_t align, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg) { uint32_t elt_sz; struct mempool_populate_arg arg; elt_sz = mp->elt_size + mp->header_size + mp->trailer_size; arg.mp = mp; arg.obj_init = obj_init; arg.obj_init_arg = obj_init_arg; mp->size = rte_mempool_obj_iter((void *)mp->elt_va_start, num, elt_sz, align, mp->elt_pa, mp->pg_num, mp->pg_shift, mempool_obj_populate, &arg); } uint32_t rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags, struct rte_mempool_objsz *sz) { struct rte_mempool_objsz lsz; sz = (sz != NULL) ? sz : &lsz; /* * In header, we have at least the pointer to the pool, and * optionaly a 64 bits cookie. */ sz->header_size = 0; sz->header_size += sizeof(struct rte_mempool *); /* ptr to pool */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG sz->header_size += sizeof(uint64_t); /* cookie */ #endif if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0) sz->header_size = RTE_ALIGN_CEIL(sz->header_size, RTE_MEMPOOL_ALIGN); /* trailer contains the cookie in debug mode */ sz->trailer_size = 0; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG sz->trailer_size += sizeof(uint64_t); /* cookie */ #endif /* element size is 8 bytes-aligned at least */ sz->elt_size = RTE_ALIGN_CEIL(elt_size, sizeof(uint64_t)); /* expand trailer to next cache line */ if ((flags & MEMPOOL_F_NO_CACHE_ALIGN) == 0) { sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size; sz->trailer_size += ((RTE_MEMPOOL_ALIGN - (sz->total_size & RTE_MEMPOOL_ALIGN_MASK)) & RTE_MEMPOOL_ALIGN_MASK); } /* * increase trailer to add padding between objects in order to * spread them across memory channels/ranks */ if ((flags & MEMPOOL_F_NO_SPREAD) == 0) { unsigned new_size; new_size = optimize_object_size(sz->header_size + sz->elt_size + sz->trailer_size); sz->trailer_size = new_size - sz->header_size - sz->elt_size; } if (! rte_eal_has_hugepages()) { /* * compute trailer size so that pool elements fit exactly in * a standard page */ int page_size = getpagesize(); int new_size = page_size - sz->header_size - sz->elt_size; if (new_size < 0 || (unsigned int)new_size < sz->trailer_size) { printf("When hugepages are disabled, pool objects " "can't exceed PAGE_SIZE: %d + %d + %d > %d\n", sz->header_size, sz->elt_size, sz->trailer_size, page_size); return 0; } sz->trailer_size = new_size; } /* this is the size of an object, including header and trailer */ sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size; return sz->total_size; } /* * Calculate maximum amount of memory required to store given number of objects. */ size_t rte_mempool_xmem_size(uint32_t elt_num, size_t elt_sz, uint32_t pg_shift) { size_t n, pg_num, pg_sz, sz; pg_sz = (size_t)1 << pg_shift; if ((n = pg_sz / elt_sz) > 0) { pg_num = (elt_num + n - 1) / n; sz = pg_num << pg_shift; } else { sz = RTE_ALIGN_CEIL(elt_sz, pg_sz) * elt_num; } return sz; } /* * Calculate how much memory would be actually required with the * given memory footprint to store required number of elements. */ static void mempool_lelem_iter(void *arg, __rte_unused void *start, void *end, __rte_unused uint32_t idx) { *(uintptr_t *)arg = (uintptr_t)end; } ssize_t rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, size_t elt_sz, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift) { uint32_t n; uintptr_t va, uv; size_t pg_sz, usz; pg_sz = (size_t)1 << pg_shift; va = (uintptr_t)vaddr; uv = va; if ((n = rte_mempool_obj_iter(vaddr, elt_num, elt_sz, 1, paddr, pg_num, pg_shift, mempool_lelem_iter, &uv)) != elt_num) { return -(ssize_t)n; } uv = RTE_ALIGN_CEIL(uv, pg_sz); usz = uv - va; return usz; } /* create the mempool */ struct rte_mempool * rte_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags) { #ifdef RTE_LIBRTE_XEN_DOM0 return rte_dom0_mempool_create(name, n, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags); #else return rte_mempool_xmem_create(name, n, elt_size, cache_size, private_data_size, mp_init, mp_init_arg, obj_init, obj_init_arg, socket_id, flags, NULL, NULL, MEMPOOL_PG_NUM_DEFAULT, MEMPOOL_PG_SHIFT_MAX); #endif } /* * Create the mempool over already allocated chunk of memory. * That external memory buffer can consists of physically disjoint pages. * Setting vaddr to NULL, makes mempool to fallback to original behaviour * and allocate space for mempool and it's elements as one big chunk of * physically continuos memory. * */ struct rte_mempool * rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags, void *vaddr, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift) { char mz_name[RTE_MEMZONE_NAMESIZE]; char rg_name[RTE_RING_NAMESIZE]; struct rte_mempool_list *mempool_list; struct rte_mempool *mp = NULL; struct rte_tailq_entry *te; struct rte_ring *r; const struct rte_memzone *mz; size_t mempool_size; int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY; int rg_flags = 0; void *obj; struct rte_mempool_objsz objsz; void *startaddr; int page_size = getpagesize(); /* compilation-time checks */ RTE_BUILD_BUG_ON((sizeof(struct rte_mempool) & RTE_CACHE_LINE_MASK) != 0); #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_cache) & RTE_CACHE_LINE_MASK) != 0); RTE_BUILD_BUG_ON((offsetof(struct rte_mempool, local_cache) & RTE_CACHE_LINE_MASK) != 0); #endif #ifdef RTE_LIBRTE_MEMPOOL_DEBUG RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_debug_stats) & RTE_CACHE_LINE_MASK) != 0); RTE_BUILD_BUG_ON((offsetof(struct rte_mempool, stats) & RTE_CACHE_LINE_MASK) != 0); #endif mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list); /* asked cache too big */ if (cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE || CALC_CACHE_FLUSHTHRESH(cache_size) > n) { rte_errno = EINVAL; return NULL; } /* check that we have both VA and PA */ if (vaddr != NULL && paddr == NULL) { rte_errno = EINVAL; return NULL; } /* Check that pg_num and pg_shift parameters are valid. */ if (pg_num < RTE_DIM(mp->elt_pa) || pg_shift > MEMPOOL_PG_SHIFT_MAX) { rte_errno = EINVAL; return NULL; } /* "no cache align" imply "no spread" */ if (flags & MEMPOOL_F_NO_CACHE_ALIGN) flags |= MEMPOOL_F_NO_SPREAD; /* ring flags */ if (flags & MEMPOOL_F_SP_PUT) rg_flags |= RING_F_SP_ENQ; if (flags & MEMPOOL_F_SC_GET) rg_flags |= RING_F_SC_DEQ; /* calculate mempool object sizes. */ if (!rte_mempool_calc_obj_size(elt_size, flags, &objsz)) { rte_errno = EINVAL; return NULL; } rte_rwlock_write_lock(RTE_EAL_MEMPOOL_RWLOCK); /* allocate the ring that will be used to store objects */ /* Ring functions will return appropriate errors if we are * running as a secondary process etc., so no checks made * in this function for that condition */ snprintf(rg_name, sizeof(rg_name), RTE_MEMPOOL_MZ_FORMAT, name); r = rte_ring_create(rg_name, rte_align32pow2(n+1), socket_id, rg_flags); if (r == NULL) goto exit; /* * reserve a memory zone for this mempool: private data is * cache-aligned */ private_data_size = (private_data_size + RTE_MEMPOOL_ALIGN_MASK) & (~RTE_MEMPOOL_ALIGN_MASK); if (! rte_eal_has_hugepages()) { /* * expand private data size to a whole page, so that the * first pool element will start on a new standard page */ int head = sizeof(struct rte_mempool); int new_size = (private_data_size + head) % page_size; if (new_size) { private_data_size += page_size - new_size; } } /* try to allocate tailq entry */ te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n"); goto exit; } /* * If user provided an external memory buffer, then use it to * store mempool objects. Otherwise reserve a memzone that is large * enough to hold mempool header and metadata plus mempool objects. */ mempool_size = MEMPOOL_HEADER_SIZE(mp, pg_num) + private_data_size; mempool_size = RTE_ALIGN_CEIL(mempool_size, RTE_MEMPOOL_ALIGN); if (vaddr == NULL) mempool_size += (size_t)objsz.total_size * n; if (! rte_eal_has_hugepages()) { /* * we want the memory pool to start on a page boundary, * because pool elements crossing page boundaries would * result in discontiguous physical addresses */ mempool_size += page_size; } snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_MZ_FORMAT, name); mz = rte_memzone_reserve(mz_name, mempool_size, socket_id, mz_flags); /* * no more memory: in this case we loose previously reserved * space for the ring as we cannot free it */ if (mz == NULL) { rte_free(te); goto exit; } if (rte_eal_has_hugepages()) { startaddr = (void*)mz->addr; } else { /* align memory pool start address on a page boundary */ unsigned long addr = (unsigned long)mz->addr; if (addr & (page_size - 1)) { addr += page_size; addr &= ~(page_size - 1); } startaddr = (void*)addr; } /* init the mempool structure */ mp = startaddr; memset(mp, 0, sizeof(*mp)); snprintf(mp->name, sizeof(mp->name), "%s", name); mp->phys_addr = mz->phys_addr; mp->ring = r; mp->size = n; mp->flags = flags; mp->elt_size = objsz.elt_size; mp->header_size = objsz.header_size; mp->trailer_size = objsz.trailer_size; mp->cache_size = cache_size; mp->cache_flushthresh = CALC_CACHE_FLUSHTHRESH(cache_size); mp->private_data_size = private_data_size; /* calculate address of the first element for continuous mempool. */ obj = (char *)mp + MEMPOOL_HEADER_SIZE(mp, pg_num) + private_data_size; obj = RTE_PTR_ALIGN_CEIL(obj, RTE_MEMPOOL_ALIGN); /* populate address translation fields. */ mp->pg_num = pg_num; mp->pg_shift = pg_shift; mp->pg_mask = RTE_LEN2MASK(mp->pg_shift, typeof(mp->pg_mask)); /* mempool elements allocated together with mempool */ if (vaddr == NULL) { mp->elt_va_start = (uintptr_t)obj; mp->elt_pa[0] = mp->phys_addr + (mp->elt_va_start - (uintptr_t)mp); /* mempool elements in a separate chunk of memory. */ } else { mp->elt_va_start = (uintptr_t)vaddr; memcpy(mp->elt_pa, paddr, sizeof (mp->elt_pa[0]) * pg_num); } mp->elt_va_end = mp->elt_va_start; /* call the initializer */ if (mp_init) mp_init(mp, mp_init_arg); mempool_populate(mp, n, 1, obj_init, obj_init_arg); te->data = (void *) mp; rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_INSERT_TAIL(mempool_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); exit: rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK); return mp; } /* Return the number of entries in the mempool */ unsigned rte_mempool_count(const struct rte_mempool *mp) { unsigned count; count = rte_ring_count(mp->ring); #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 { unsigned lcore_id; if (mp->cache_size == 0) return count; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) count += mp->local_cache[lcore_id].len; } #endif /* * due to race condition (access to len is not locked), the * total can be greater than size... so fix the result */ if (count > mp->size) return mp->size; return count; } /* dump the cache status */ static unsigned rte_mempool_dump_cache(FILE *f, const struct rte_mempool *mp) { #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 unsigned lcore_id; unsigned count = 0; unsigned cache_count; fprintf(f, " cache infos:\n"); fprintf(f, " cache_size=%"PRIu32"\n", mp->cache_size); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { cache_count = mp->local_cache[lcore_id].len; fprintf(f, " cache_count[%u]=%u\n", lcore_id, cache_count); count += cache_count; } fprintf(f, " total_cache_count=%u\n", count); return count; #else RTE_SET_USED(mp); fprintf(f, " cache disabled\n"); return 0; #endif } #ifdef RTE_LIBRTE_MEMPOOL_DEBUG /* check cookies before and after objects */ #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wcast-qual" #endif struct mempool_audit_arg { const struct rte_mempool *mp; uintptr_t obj_end; uint32_t obj_num; }; static void mempool_obj_audit(void *arg, void *start, void *end, uint32_t idx) { struct mempool_audit_arg *pa = arg; void *obj; obj = (char *)start + pa->mp->header_size; pa->obj_end = (uintptr_t)end; pa->obj_num = idx + 1; __mempool_check_cookies(pa->mp, &obj, 1, 2); } static void mempool_audit_cookies(const struct rte_mempool *mp) { uint32_t elt_sz, num; struct mempool_audit_arg arg; elt_sz = mp->elt_size + mp->header_size + mp->trailer_size; arg.mp = mp; arg.obj_end = mp->elt_va_start; arg.obj_num = 0; num = rte_mempool_obj_iter((void *)mp->elt_va_start, mp->size, elt_sz, 1, mp->elt_pa, mp->pg_num, mp->pg_shift, mempool_obj_audit, &arg); if (num != mp->size) { rte_panic("rte_mempool_obj_iter(mempool=%p, size=%u) " "iterated only over %u elements\n", mp, mp->size, num); } else if (arg.obj_end != mp->elt_va_end || arg.obj_num != mp->size) { rte_panic("rte_mempool_obj_iter(mempool=%p, size=%u) " "last callback va_end: %#tx (%#tx expeceted), " "num of objects: %u (%u expected)\n", mp, mp->size, arg.obj_end, mp->elt_va_end, arg.obj_num, mp->size); } } #ifndef __INTEL_COMPILER #pragma GCC diagnostic error "-Wcast-qual" #endif #else #define mempool_audit_cookies(mp) do {} while(0) #endif #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /* check cookies before and after objects */ static void mempool_audit_cache(const struct rte_mempool *mp) { /* check cache size consistency */ unsigned lcore_id; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (mp->local_cache[lcore_id].len > mp->cache_flushthresh) { RTE_LOG(CRIT, MEMPOOL, "badness on cache[%u]\n", lcore_id); rte_panic("MEMPOOL: invalid cache len\n"); } } } #else #define mempool_audit_cache(mp) do {} while(0) #endif /* check the consistency of mempool (size, cookies, ...) */ void rte_mempool_audit(const struct rte_mempool *mp) { mempool_audit_cache(mp); mempool_audit_cookies(mp); /* For case where mempool DEBUG is not set, and cache size is 0 */ RTE_SET_USED(mp); } /* dump the status of the mempool on the console */ void rte_mempool_dump(FILE *f, const struct rte_mempool *mp) { #ifdef RTE_LIBRTE_MEMPOOL_DEBUG struct rte_mempool_debug_stats sum; unsigned lcore_id; #endif unsigned common_count; unsigned cache_count; RTE_VERIFY(f != NULL); RTE_VERIFY(mp != NULL); fprintf(f, "mempool <%s>@%p\n", mp->name, mp); fprintf(f, " flags=%x\n", mp->flags); fprintf(f, " ring=<%s>@%p\n", mp->ring->name, mp->ring); fprintf(f, " phys_addr=0x%" PRIx64 "\n", mp->phys_addr); fprintf(f, " size=%"PRIu32"\n", mp->size); fprintf(f, " header_size=%"PRIu32"\n", mp->header_size); fprintf(f, " elt_size=%"PRIu32"\n", mp->elt_size); fprintf(f, " trailer_size=%"PRIu32"\n", mp->trailer_size); fprintf(f, " total_obj_size=%"PRIu32"\n", mp->header_size + mp->elt_size + mp->trailer_size); fprintf(f, " private_data_size=%"PRIu32"\n", mp->private_data_size); fprintf(f, " pg_num=%"PRIu32"\n", mp->pg_num); fprintf(f, " pg_shift=%"PRIu32"\n", mp->pg_shift); fprintf(f, " pg_mask=%#tx\n", mp->pg_mask); fprintf(f, " elt_va_start=%#tx\n", mp->elt_va_start); fprintf(f, " elt_va_end=%#tx\n", mp->elt_va_end); fprintf(f, " elt_pa[0]=0x%" PRIx64 "\n", mp->elt_pa[0]); if (mp->size != 0) fprintf(f, " avg bytes/object=%#Lf\n", (long double)(mp->elt_va_end - mp->elt_va_start) / mp->size); cache_count = rte_mempool_dump_cache(f, mp); common_count = rte_ring_count(mp->ring); if ((cache_count + common_count) > mp->size) common_count = mp->size - cache_count; fprintf(f, " common_pool_count=%u\n", common_count); /* sum and dump statistics */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG memset(&sum, 0, sizeof(sum)); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { sum.put_bulk += mp->stats[lcore_id].put_bulk; sum.put_objs += mp->stats[lcore_id].put_objs; sum.get_success_bulk += mp->stats[lcore_id].get_success_bulk; sum.get_success_objs += mp->stats[lcore_id].get_success_objs; sum.get_fail_bulk += mp->stats[lcore_id].get_fail_bulk; sum.get_fail_objs += mp->stats[lcore_id].get_fail_objs; } fprintf(f, " stats:\n"); fprintf(f, " put_bulk=%"PRIu64"\n", sum.put_bulk); fprintf(f, " put_objs=%"PRIu64"\n", sum.put_objs); fprintf(f, " get_success_bulk=%"PRIu64"\n", sum.get_success_bulk); fprintf(f, " get_success_objs=%"PRIu64"\n", sum.get_success_objs); fprintf(f, " get_fail_bulk=%"PRIu64"\n", sum.get_fail_bulk); fprintf(f, " get_fail_objs=%"PRIu64"\n", sum.get_fail_objs); #else fprintf(f, " no statistics available\n"); #endif rte_mempool_audit(mp); } /* dump the status of all mempools on the console */ void rte_mempool_list_dump(FILE *f) { const struct rte_mempool *mp = NULL; struct rte_tailq_entry *te; struct rte_mempool_list *mempool_list; mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list); rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK); TAILQ_FOREACH(te, mempool_list, next) { mp = (struct rte_mempool *) te->data; rte_mempool_dump(f, mp); } rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK); } /* search a mempool from its name */ struct rte_mempool * rte_mempool_lookup(const char *name) { struct rte_mempool *mp = NULL; struct rte_tailq_entry *te; struct rte_mempool_list *mempool_list; mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list); rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK); TAILQ_FOREACH(te, mempool_list, next) { mp = (struct rte_mempool *) te->data; if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return mp; } void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *), void *arg) { struct rte_tailq_entry *te = NULL; struct rte_mempool_list *mempool_list; mempool_list = RTE_TAILQ_CAST(rte_mempool_tailq.head, rte_mempool_list); rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK); TAILQ_FOREACH(te, mempool_list, next) { (*func)((struct rte_mempool *) te->data, arg); } rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK); } ================================================ FILE: lib/librte_mempool/rte_mempool.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_MEMPOOL_H_ #define _RTE_MEMPOOL_H_ /** * @file * RTE Mempool. * * A memory pool is an allocator of fixed-size object. It is * identified by its name, and uses a ring to store free objects. It * provides some other optional services, like a per-core object * cache, and an alignment helper to ensure that objects are padded * to spread them equally on all RAM channels, ranks, and so on. * * Objects owned by a mempool should never be added in another * mempool. When an object is freed using rte_mempool_put() or * equivalent, the object data is not modified; the user can save some * meta-data in the object data and retrieve them when allocating a * new object. * * Note: the mempool implementation is not preemptable. A lcore must * not be interrupted by another task that uses the same mempool * (because it uses a ring which is not preemptable). Also, mempool * functions must not be used outside the DPDK environment: for * example, in linuxapp environment, a thread that is not created by * the EAL must not use mempools. This is due to the per-lcore cache * that won't work as rte_lcore_id() will not return a correct value. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define RTE_MEMPOOL_HEADER_COOKIE1 0xbadbadbadadd2e55ULL /**< Header cookie. */ #define RTE_MEMPOOL_HEADER_COOKIE2 0xf2eef2eedadd2e55ULL /**< Header cookie. */ #define RTE_MEMPOOL_TRAILER_COOKIE 0xadd2e55badbadbadULL /**< Trailer cookie.*/ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG /** * A structure that stores the mempool statistics (per-lcore). */ struct rte_mempool_debug_stats { uint64_t put_bulk; /**< Number of puts. */ uint64_t put_objs; /**< Number of objects successfully put. */ uint64_t get_success_bulk; /**< Successful allocation number. */ uint64_t get_success_objs; /**< Objects successfully allocated. */ uint64_t get_fail_bulk; /**< Failed allocation number. */ uint64_t get_fail_objs; /**< Objects that failed to be allocated. */ } __rte_cache_aligned; #endif #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /** * A structure that stores a per-core object cache. */ struct rte_mempool_cache { unsigned len; /**< Cache len */ /* * Cache is allocated to this size to allow it to overflow in certain * cases to avoid needless emptying of cache. */ void *objs[RTE_MEMPOOL_CACHE_MAX_SIZE * 3]; /**< Cache objects */ } __rte_cache_aligned; #endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /** * A structure that stores the size of mempool elements. */ struct rte_mempool_objsz { uint32_t elt_size; /**< Size of an element. */ uint32_t header_size; /**< Size of header (before elt). */ uint32_t trailer_size; /**< Size of trailer (after elt). */ uint32_t total_size; /**< Total size of an object (header + elt + trailer). */ }; #define RTE_MEMPOOL_NAMESIZE 32 /**< Maximum length of a memory pool. */ #define RTE_MEMPOOL_MZ_PREFIX "MP_" /* "MP_" */ #define RTE_MEMPOOL_MZ_FORMAT RTE_MEMPOOL_MZ_PREFIX "%s" #ifdef RTE_LIBRTE_XEN_DOM0 /* "_MP_elt" */ #define RTE_MEMPOOL_OBJ_NAME "%s_" RTE_MEMPOOL_MZ_PREFIX "elt" #else #define RTE_MEMPOOL_OBJ_NAME RTE_MEMPOOL_MZ_FORMAT #endif /* RTE_LIBRTE_XEN_DOM0 */ #define MEMPOOL_PG_SHIFT_MAX (sizeof(uintptr_t) * CHAR_BIT - 1) /** Mempool over one chunk of physically continuous memory */ #define MEMPOOL_PG_NUM_DEFAULT 1 #ifndef RTE_MEMPOOL_ALIGN #define RTE_MEMPOOL_ALIGN RTE_CACHE_LINE_SIZE #endif #define RTE_MEMPOOL_ALIGN_MASK (RTE_MEMPOOL_ALIGN - 1) /** * Mempool object header structure * * Each object stored in mempools are prefixed by this header structure, * it allows to retrieve the mempool pointer from the object. When debug * is enabled, a cookie is also added in this structure preventing * corruptions and double-frees. */ struct rte_mempool_objhdr { struct rte_mempool *mp; /**< The mempool owning the object. */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG uint64_t cookie; /**< Debug cookie. */ #endif }; /** * Mempool object trailer structure * * In debug mode, each object stored in mempools are suffixed by this * trailer structure containing a cookie preventing memory corruptions. */ struct rte_mempool_objtlr { #ifdef RTE_LIBRTE_MEMPOOL_DEBUG uint64_t cookie; /**< Debug cookie. */ #endif }; /** * The RTE mempool structure. */ struct rte_mempool { char name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */ struct rte_ring *ring; /**< Ring to store objects. */ phys_addr_t phys_addr; /**< Phys. addr. of mempool struct. */ int flags; /**< Flags of the mempool. */ uint32_t size; /**< Size of the mempool. */ uint32_t cache_size; /**< Size of per-lcore local cache. */ uint32_t cache_flushthresh; /**< Threshold before we flush excess elements. */ uint32_t elt_size; /**< Size of an element. */ uint32_t header_size; /**< Size of header (before elt). */ uint32_t trailer_size; /**< Size of trailer (after elt). */ unsigned private_data_size; /**< Size of private data. */ #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /** Per-lcore local cache. */ struct rte_mempool_cache local_cache[RTE_MAX_LCORE]; #endif #ifdef RTE_LIBRTE_MEMPOOL_DEBUG /** Per-lcore statistics. */ struct rte_mempool_debug_stats stats[RTE_MAX_LCORE]; #endif /* Address translation support, starts from next cache line. */ /** Number of elements in the elt_pa array. */ uint32_t pg_num __rte_cache_aligned; uint32_t pg_shift; /**< LOG2 of the physical pages. */ uintptr_t pg_mask; /**< physical page mask value. */ uintptr_t elt_va_start; /**< Virtual address of the first mempool object. */ uintptr_t elt_va_end; /**< Virtual address of the mempool object. */ phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT]; /**< Array of physical page addresses for the mempool objects buffer. */ } __rte_cache_aligned; #define MEMPOOL_F_NO_SPREAD 0x0001 /**< Do not spread in memory. */ #define MEMPOOL_F_NO_CACHE_ALIGN 0x0002 /**< Do not align objs on cache lines.*/ #define MEMPOOL_F_SP_PUT 0x0004 /**< Default put is "single-producer".*/ #define MEMPOOL_F_SC_GET 0x0008 /**< Default get is "single-consumer".*/ /** * @internal When debug is enabled, store some statistics. * * @param mp * Pointer to the memory pool. * @param name * Name of the statistics field to increment in the memory pool. * @param n * Number to add to the object-oriented statistics. */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG #define __MEMPOOL_STAT_ADD(mp, name, n) do { \ unsigned __lcore_id = rte_lcore_id(); \ if (__lcore_id < RTE_MAX_LCORE) { \ mp->stats[__lcore_id].name##_objs += n; \ mp->stats[__lcore_id].name##_bulk += 1; \ } \ } while(0) #else #define __MEMPOOL_STAT_ADD(mp, name, n) do {} while(0) #endif /** * Calculate the size of the mempool header. * * @param mp * Pointer to the memory pool. * @param pgn * Number of pages used to store mempool objects. */ #define MEMPOOL_HEADER_SIZE(mp, pgn) (sizeof(*(mp)) + \ RTE_ALIGN_CEIL(((pgn) - RTE_DIM((mp)->elt_pa)) * \ sizeof ((mp)->elt_pa[0]), RTE_CACHE_LINE_SIZE)) /** * Return true if the whole mempool is in contiguous memory. */ #define MEMPOOL_IS_CONTIG(mp) \ ((mp)->pg_num == MEMPOOL_PG_NUM_DEFAULT && \ (mp)->phys_addr == (mp)->elt_pa[0]) /* return the header of a mempool object (internal) */ static inline struct rte_mempool_objhdr *__mempool_get_header(void *obj) { return (struct rte_mempool_objhdr *)RTE_PTR_SUB(obj, sizeof(struct rte_mempool_objhdr)); } /** * Return a pointer to the mempool owning this object. * * @param obj * An object that is owned by a pool. If this is not the case, * the behavior is undefined. * @return * A pointer to the mempool structure. */ static inline struct rte_mempool *rte_mempool_from_obj(void *obj) { struct rte_mempool_objhdr *hdr = __mempool_get_header(obj); return hdr->mp; } /* return the trailer of a mempool object (internal) */ static inline struct rte_mempool_objtlr *__mempool_get_trailer(void *obj) { struct rte_mempool *mp = rte_mempool_from_obj(obj); return (struct rte_mempool_objtlr *)RTE_PTR_ADD(obj, mp->elt_size); } /** * @internal Check and update cookies or panic. * * @param mp * Pointer to the memory pool. * @param obj_table_const * Pointer to a table of void * pointers (objects). * @param n * Index of object in object table. * @param free * - 0: object is supposed to be allocated, mark it as free * - 1: object is supposed to be free, mark it as allocated * - 2: just check that cookie is valid (free or allocated) */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wcast-qual" #endif static inline void __mempool_check_cookies(const struct rte_mempool *mp, void * const *obj_table_const, unsigned n, int free) { struct rte_mempool_objhdr *hdr; struct rte_mempool_objtlr *tlr; uint64_t cookie; void *tmp; void *obj; void **obj_table; /* Force to drop the "const" attribute. This is done only when * DEBUG is enabled */ tmp = (void *) obj_table_const; obj_table = (void **) tmp; while (n--) { obj = obj_table[n]; if (rte_mempool_from_obj(obj) != mp) rte_panic("MEMPOOL: object is owned by another " "mempool\n"); hdr = __mempool_get_header(obj); cookie = hdr->cookie; if (free == 0) { if (cookie != RTE_MEMPOOL_HEADER_COOKIE1) { rte_log_set_history(0); RTE_LOG(CRIT, MEMPOOL, "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", obj, (const void *) mp, cookie); rte_panic("MEMPOOL: bad header cookie (put)\n"); } hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2; } else if (free == 1) { if (cookie != RTE_MEMPOOL_HEADER_COOKIE2) { rte_log_set_history(0); RTE_LOG(CRIT, MEMPOOL, "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", obj, (const void *) mp, cookie); rte_panic("MEMPOOL: bad header cookie (get)\n"); } hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE1; } else if (free == 2) { if (cookie != RTE_MEMPOOL_HEADER_COOKIE1 && cookie != RTE_MEMPOOL_HEADER_COOKIE2) { rte_log_set_history(0); RTE_LOG(CRIT, MEMPOOL, "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", obj, (const void *) mp, cookie); rte_panic("MEMPOOL: bad header cookie (audit)\n"); } } tlr = __mempool_get_trailer(obj); cookie = tlr->cookie; if (cookie != RTE_MEMPOOL_TRAILER_COOKIE) { rte_log_set_history(0); RTE_LOG(CRIT, MEMPOOL, "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", obj, (const void *) mp, cookie); rte_panic("MEMPOOL: bad trailer cookie\n"); } } } #ifndef __INTEL_COMPILER #pragma GCC diagnostic error "-Wcast-qual" #endif #else #define __mempool_check_cookies(mp, obj_table_const, n, free) do {} while(0) #endif /* RTE_LIBRTE_MEMPOOL_DEBUG */ /** * A mempool object iterator callback function. */ typedef void (*rte_mempool_obj_iter_t)(void * /*obj_iter_arg*/, void * /*obj_start*/, void * /*obj_end*/, uint32_t /*obj_index */); /** * Call a function for each mempool object in a memory chunk * * Iterate across objects of the given size and alignment in the * provided chunk of memory. The given memory buffer can consist of * disjointed physical pages. * * For each object, call the provided callback (if any). This function * is used to populate a mempool, or walk through all the elements of a * mempool, or estimate how many elements of the given size could be * created in the given memory buffer. * * @param vaddr * Virtual address of the memory buffer. * @param elt_num * Maximum number of objects to iterate through. * @param elt_sz * Size of each object. * @param align * Alignment of each object. * @param paddr * Array of physical addresses of the pages that comprises given memory * buffer. * @param pg_num * Number of elements in the paddr array. * @param pg_shift * LOG2 of the physical pages size. * @param obj_iter * Object iterator callback function (could be NULL). * @param obj_iter_arg * User defined parameter for the object iterator callback function. * * @return * Number of objects iterated through. */ uint32_t rte_mempool_obj_iter(void *vaddr, uint32_t elt_num, size_t elt_sz, size_t align, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift, rte_mempool_obj_iter_t obj_iter, void *obj_iter_arg); /** * An object constructor callback function for mempool. * * Arguments are the mempool, the opaque pointer given by the user in * rte_mempool_create(), the pointer to the element and the index of * the element in the pool. */ typedef void (rte_mempool_obj_ctor_t)(struct rte_mempool *, void *, void *, unsigned); /** * A mempool constructor callback function. * * Arguments are the mempool and the opaque pointer given by the user in * rte_mempool_create(). */ typedef void (rte_mempool_ctor_t)(struct rte_mempool *, void *); /** * Create a new mempool named *name* in memory. * * This function uses ``memzone_reserve()`` to allocate memory. The * pool contains n elements of elt_size. Its size is set to n. * All elements of the mempool are allocated together with the mempool header, * in one physically continuous chunk of memory. * * @param name * The name of the mempool. * @param n * The number of elements in the mempool. The optimum size (in terms of * memory usage) for a mempool is when n is a power of two minus one: * n = (2^q - 1). * @param elt_size * The size of each element. * @param cache_size * If cache_size is non-zero, the rte_mempool library will try to * limit the accesses to the common lockless pool, by maintaining a * per-lcore object cache. This argument must be lower or equal to * CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE and n / 1.5. It is advised to choose * cache_size to have "n modulo cache_size == 0": if this is * not the case, some elements will always stay in the pool and will * never be used. The access to the per-lcore table is of course * faster than the multi-producer/consumer pool. The cache can be * disabled if the cache_size argument is set to 0; it can be useful to * avoid losing objects in cache. Note that even if not used, the * memory space for cache is always reserved in a mempool structure, * except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0. * @param private_data_size * The size of the private data appended after the mempool * structure. This is useful for storing some private data after the * mempool structure, as is done for rte_mbuf_pool for example. * @param mp_init * A function pointer that is called for initialization of the pool, * before object initialization. The user can initialize the private * data in this function if needed. This parameter can be NULL if * not needed. * @param mp_init_arg * An opaque pointer to data that can be used in the mempool * constructor function. * @param obj_init * A function pointer that is called for each object at * initialization of the pool. The user can set some meta data in * objects if needed. This parameter can be NULL if not needed. * The obj_init() function takes the mempool pointer, the init_arg, * the object pointer and the object number as parameters. * @param obj_init_arg * An opaque pointer to data that can be used as an argument for * each call to the object constructor function. * @param socket_id * The *socket_id* argument is the socket identifier in the case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags * The *flags* arguments is an OR of following flags: * - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread * between channels in RAM: the pool allocator will add padding * between objects depending on the hardware configuration. See * Memory alignment constraints for details. If this flag is set, * the allocator will just align them to a cache line. * - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are * cache-aligned. This flag removes this constraint, and no * padding will be present between objects. This flag implies * MEMPOOL_F_NO_SPREAD. * - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior * when using rte_mempool_put() or rte_mempool_put_bulk() is * "single-producer". Otherwise, it is "multi-producers". * - MEMPOOL_F_SC_GET: If this flag is set, the default behavior * when using rte_mempool_get() or rte_mempool_get_bulk() is * "single-consumer". Otherwise, it is "multi-consumers". * @return * The pointer to the new allocated mempool, on success. NULL on error * with rte_errno set appropriately. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - cache size provided is too large * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_mempool * rte_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); /** * Create a new mempool named *name* in memory. * * This function uses ``memzone_reserve()`` to allocate memory. The * pool contains n elements of elt_size. Its size is set to n. * Depending on the input parameters, mempool elements can be either allocated * together with the mempool header, or an externally provided memory buffer * could be used to store mempool objects. In later case, that external * memory buffer can consist of set of disjoint physical pages. * * @param name * The name of the mempool. * @param n * The number of elements in the mempool. The optimum size (in terms of * memory usage) for a mempool is when n is a power of two minus one: * n = (2^q - 1). * @param elt_size * The size of each element. * @param cache_size * If cache_size is non-zero, the rte_mempool library will try to * limit the accesses to the common lockless pool, by maintaining a * per-lcore object cache. This argument must be lower or equal to * CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE. It is advised to choose * cache_size to have "n modulo cache_size == 0": if this is * not the case, some elements will always stay in the pool and will * never be used. The access to the per-lcore table is of course * faster than the multi-producer/consumer pool. The cache can be * disabled if the cache_size argument is set to 0; it can be useful to * avoid losing objects in cache. Note that even if not used, the * memory space for cache is always reserved in a mempool structure, * except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0. * @param private_data_size * The size of the private data appended after the mempool * structure. This is useful for storing some private data after the * mempool structure, as is done for rte_mbuf_pool for example. * @param mp_init * A function pointer that is called for initialization of the pool, * before object initialization. The user can initialize the private * data in this function if needed. This parameter can be NULL if * not needed. * @param mp_init_arg * An opaque pointer to data that can be used in the mempool * constructor function. * @param obj_init * A function pointer that is called for each object at * initialization of the pool. The user can set some meta data in * objects if needed. This parameter can be NULL if not needed. * The obj_init() function takes the mempool pointer, the init_arg, * the object pointer and the object number as parameters. * @param obj_init_arg * An opaque pointer to data that can be used as an argument for * each call to the object constructor function. * @param socket_id * The *socket_id* argument is the socket identifier in the case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags * The *flags* arguments is an OR of following flags: * - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread * between channels in RAM: the pool allocator will add padding * between objects depending on the hardware configuration. See * Memory alignment constraints for details. If this flag is set, * the allocator will just align them to a cache line. * - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are * cache-aligned. This flag removes this constraint, and no * padding will be present between objects. This flag implies * MEMPOOL_F_NO_SPREAD. * - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior * when using rte_mempool_put() or rte_mempool_put_bulk() is * "single-producer". Otherwise, it is "multi-producers". * - MEMPOOL_F_SC_GET: If this flag is set, the default behavior * when using rte_mempool_get() or rte_mempool_get_bulk() is * "single-consumer". Otherwise, it is "multi-consumers". * @param vaddr * Virtual address of the externally allocated memory buffer. * Will be used to store mempool objects. * @param paddr * Array of physical addresses of the pages that comprises given memory * buffer. * @param pg_num * Number of elements in the paddr array. * @param pg_shift * LOG2 of the physical pages size. * @return * The pointer to the new allocated mempool, on success. NULL on error * with rte_errno set appropriately. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - cache size provided is too large * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_mempool * rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags, void *vaddr, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift); #ifdef RTE_LIBRTE_XEN_DOM0 /** * Create a new mempool named *name* in memory on Xen Dom0. * * This function uses ``rte_mempool_xmem_create()`` to allocate memory. The * pool contains n elements of elt_size. Its size is set to n. * All elements of the mempool are allocated together with the mempool header, * and memory buffer can consist of set of disjoint physical pages. * * @param name * The name of the mempool. * @param n * The number of elements in the mempool. The optimum size (in terms of * memory usage) for a mempool is when n is a power of two minus one: * n = (2^q - 1). * @param elt_size * The size of each element. * @param cache_size * If cache_size is non-zero, the rte_mempool library will try to * limit the accesses to the common lockless pool, by maintaining a * per-lcore object cache. This argument must be lower or equal to * CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE. It is advised to choose * cache_size to have "n modulo cache_size == 0": if this is * not the case, some elements will always stay in the pool and will * never be used. The access to the per-lcore table is of course * faster than the multi-producer/consumer pool. The cache can be * disabled if the cache_size argument is set to 0; it can be useful to * avoid losing objects in cache. Note that even if not used, the * memory space for cache is always reserved in a mempool structure, * except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0. * @param private_data_size * The size of the private data appended after the mempool * structure. This is useful for storing some private data after the * mempool structure, as is done for rte_mbuf_pool for example. * @param mp_init * A function pointer that is called for initialization of the pool, * before object initialization. The user can initialize the private * data in this function if needed. This parameter can be NULL if * not needed. * @param mp_init_arg * An opaque pointer to data that can be used in the mempool * constructor function. * @param obj_init * A function pointer that is called for each object at * initialization of the pool. The user can set some meta data in * objects if needed. This parameter can be NULL if not needed. * The obj_init() function takes the mempool pointer, the init_arg, * the object pointer and the object number as parameters. * @param obj_init_arg * An opaque pointer to data that can be used as an argument for * each call to the object constructor function. * @param socket_id * The *socket_id* argument is the socket identifier in the case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags * The *flags* arguments is an OR of following flags: * - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread * between channels in RAM: the pool allocator will add padding * between objects depending on the hardware configuration. See * Memory alignment constraints for details. If this flag is set, * the allocator will just align them to a cache line. * - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are * cache-aligned. This flag removes this constraint, and no * padding will be present between objects. This flag implies * MEMPOOL_F_NO_SPREAD. * - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior * when using rte_mempool_put() or rte_mempool_put_bulk() is * "single-producer". Otherwise, it is "multi-producers". * - MEMPOOL_F_SC_GET: If this flag is set, the default behavior * when using rte_mempool_get() or rte_mempool_get_bulk() is * "single-consumer". Otherwise, it is "multi-consumers". * @return * The pointer to the new allocated mempool, on success. NULL on error * with rte_errno set appropriately. Possible rte_errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - cache size provided is too large * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_mempool * rte_dom0_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); #endif /** * Dump the status of the mempool to the console. * * @param f * A pointer to a file for output * @param mp * A pointer to the mempool structure. */ void rte_mempool_dump(FILE *f, const struct rte_mempool *mp); /** * @internal Put several objects back in the mempool; used internally. * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to store back in the mempool, must be strictly * positive. * @param is_mp * Mono-producer (0) or multi-producers (1). */ static inline void __attribute__((always_inline)) __mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned n, int is_mp) { #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 struct rte_mempool_cache *cache; uint32_t index; void **cache_objs; unsigned lcore_id = rte_lcore_id(); uint32_t cache_size = mp->cache_size; uint32_t flushthresh = mp->cache_flushthresh; #endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* increment stat now, adding in mempool always success */ __MEMPOOL_STAT_ADD(mp, put, n); #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /* cache is not enabled or single producer or non-EAL thread */ if (unlikely(cache_size == 0 || is_mp == 0 || lcore_id >= RTE_MAX_LCORE)) goto ring_enqueue; /* Go straight to ring if put would overflow mem allocated for cache */ if (unlikely(n > RTE_MEMPOOL_CACHE_MAX_SIZE)) goto ring_enqueue; cache = &mp->local_cache[lcore_id]; cache_objs = &cache->objs[cache->len]; /* * The cache follows the following algorithm * 1. Add the objects to the cache * 2. Anything greater than the cache min value (if it crosses the * cache flush threshold) is flushed to the ring. */ /* Add elements back into the cache */ for (index = 0; index < n; ++index, obj_table++) cache_objs[index] = *obj_table; cache->len += n; if (cache->len >= flushthresh) { rte_ring_mp_enqueue_bulk(mp->ring, &cache->objs[cache_size], cache->len - cache_size); cache->len = cache_size; } return; ring_enqueue: #endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* push remaining objects in ring */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG if (is_mp) { if (rte_ring_mp_enqueue_bulk(mp->ring, obj_table, n) < 0) rte_panic("cannot put objects in mempool\n"); } else { if (rte_ring_sp_enqueue_bulk(mp->ring, obj_table, n) < 0) rte_panic("cannot put objects in mempool\n"); } #else if (is_mp) rte_ring_mp_enqueue_bulk(mp->ring, obj_table, n); else rte_ring_sp_enqueue_bulk(mp->ring, obj_table, n); #endif } /** * Put several objects back in the mempool (multi-producers safe). * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the mempool from the obj_table. */ static inline void __attribute__((always_inline)) rte_mempool_mp_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned n) { __mempool_check_cookies(mp, obj_table, n, 0); __mempool_put_bulk(mp, obj_table, n, 1); } /** * Put several objects back in the mempool (NOT multi-producers safe). * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the mempool from obj_table. */ static inline void rte_mempool_sp_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned n) { __mempool_check_cookies(mp, obj_table, n, 0); __mempool_put_bulk(mp, obj_table, n, 0); } /** * Put several objects back in the mempool. * * This function calls the multi-producer or the single-producer * version depending on the default behavior that was specified at * mempool creation time (see flags). * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the mempool from obj_table. */ static inline void __attribute__((always_inline)) rte_mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned n) { __mempool_check_cookies(mp, obj_table, n, 0); __mempool_put_bulk(mp, obj_table, n, !(mp->flags & MEMPOOL_F_SP_PUT)); } /** * Put one object in the mempool (multi-producers safe). * * @param mp * A pointer to the mempool structure. * @param obj * A pointer to the object to be added. */ static inline void __attribute__((always_inline)) rte_mempool_mp_put(struct rte_mempool *mp, void *obj) { rte_mempool_mp_put_bulk(mp, &obj, 1); } /** * Put one object back in the mempool (NOT multi-producers safe). * * @param mp * A pointer to the mempool structure. * @param obj * A pointer to the object to be added. */ static inline void __attribute__((always_inline)) rte_mempool_sp_put(struct rte_mempool *mp, void *obj) { rte_mempool_sp_put_bulk(mp, &obj, 1); } /** * Put one object back in the mempool. * * This function calls the multi-producer or the single-producer * version depending on the default behavior that was specified at * mempool creation time (see flags). * * @param mp * A pointer to the mempool structure. * @param obj * A pointer to the object to be added. */ static inline void __attribute__((always_inline)) rte_mempool_put(struct rte_mempool *mp, void *obj) { rte_mempool_put_bulk(mp, &obj, 1); } /** * @internal Get several objects from the mempool; used internally. * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to get, must be strictly positive. * @param is_mc * Mono-consumer (0) or multi-consumers (1). * @return * - >=0: Success; number of objects supplied. * - <0: Error; code of ring dequeue function. */ static inline int __attribute__((always_inline)) __mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n, int is_mc) { int ret; #if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 struct rte_mempool_cache *cache; uint32_t index, len; void **cache_objs; unsigned lcore_id = rte_lcore_id(); uint32_t cache_size = mp->cache_size; /* cache is not enabled or single consumer */ if (unlikely(cache_size == 0 || is_mc == 0 || n >= cache_size || lcore_id >= RTE_MAX_LCORE)) goto ring_dequeue; cache = &mp->local_cache[lcore_id]; cache_objs = cache->objs; /* Can this be satisfied from the cache? */ if (cache->len < n) { /* No. Backfill the cache first, and then fill from it */ uint32_t req = n + (cache_size - cache->len); /* How many do we require i.e. number to fill the cache + the request */ ret = rte_ring_mc_dequeue_bulk(mp->ring, &cache->objs[cache->len], req); if (unlikely(ret < 0)) { /* * In the offchance that we are buffer constrained, * where we are not able to allocate cache + n, go to * the ring directly. If that fails, we are truly out of * buffers. */ goto ring_dequeue; } cache->len += req; } /* Now fill in the response ... */ for (index = 0, len = cache->len - 1; index < n; ++index, len--, obj_table++) *obj_table = cache_objs[len]; cache->len -= n; __MEMPOOL_STAT_ADD(mp, get_success, n); return 0; ring_dequeue: #endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* get remaining objects from ring */ if (is_mc) ret = rte_ring_mc_dequeue_bulk(mp->ring, obj_table, n); else ret = rte_ring_sc_dequeue_bulk(mp->ring, obj_table, n); if (ret < 0) __MEMPOOL_STAT_ADD(mp, get_fail, n); else __MEMPOOL_STAT_ADD(mp, get_success, n); return ret; } /** * Get several objects from the mempool (multi-consumers safe). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to get from mempool to obj_table. * @return * - 0: Success; objects taken. * - -ENOENT: Not enough entries in the mempool; no object is retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_mc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n) { int ret; ret = __mempool_get_bulk(mp, obj_table, n, 1); if (ret == 0) __mempool_check_cookies(mp, obj_table, n, 1); return ret; } /** * Get several objects from the mempool (NOT multi-consumers safe). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to get from the mempool to obj_table. * @return * - 0: Success; objects taken. * - -ENOENT: Not enough entries in the mempool; no object is * retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_sc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n) { int ret; ret = __mempool_get_bulk(mp, obj_table, n, 0); if (ret == 0) __mempool_check_cookies(mp, obj_table, n, 1); return ret; } /** * Get several objects from the mempool. * * This function calls the multi-consumers or the single-consumer * version, depending on the default behaviour that was specified at * mempool creation time (see flags). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to get from the mempool to obj_table. * @return * - 0: Success; objects taken * - -ENOENT: Not enough entries in the mempool; no object is retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n) { int ret; ret = __mempool_get_bulk(mp, obj_table, n, !(mp->flags & MEMPOOL_F_SC_GET)); if (ret == 0) __mempool_check_cookies(mp, obj_table, n, 1); return ret; } /** * Get one object from the mempool (multi-consumers safe). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success; objects taken. * - -ENOENT: Not enough entries in the mempool; no object is retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_mc_get(struct rte_mempool *mp, void **obj_p) { return rte_mempool_mc_get_bulk(mp, obj_p, 1); } /** * Get one object from the mempool (NOT multi-consumers safe). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success; objects taken. * - -ENOENT: Not enough entries in the mempool; no object is retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_sc_get(struct rte_mempool *mp, void **obj_p) { return rte_mempool_sc_get_bulk(mp, obj_p, 1); } /** * Get one object from the mempool. * * This function calls the multi-consumers or the single-consumer * version, depending on the default behavior that was specified at * mempool creation (see flags). * * If cache is enabled, objects will be retrieved first from cache, * subsequently from the common pool. Note that it can return -ENOENT when * the local cache and common pool are empty, even if cache from other * lcores are full. * * @param mp * A pointer to the mempool structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success; objects taken. * - -ENOENT: Not enough entries in the mempool; no object is retrieved. */ static inline int __attribute__((always_inline)) rte_mempool_get(struct rte_mempool *mp, void **obj_p) { return rte_mempool_get_bulk(mp, obj_p, 1); } /** * Return the number of entries in the mempool. * * When cache is enabled, this function has to browse the length of * all lcores, so it should not be used in a data path, but only for * debug purposes. * * @param mp * A pointer to the mempool structure. * @return * The number of entries in the mempool. */ unsigned rte_mempool_count(const struct rte_mempool *mp); /** * Return the number of free entries in the mempool ring. * i.e. how many entries can be freed back to the mempool. * * NOTE: This corresponds to the number of elements *allocated* from the * memory pool, not the number of elements in the pool itself. To count * the number elements currently available in the pool, use "rte_mempool_count" * * When cache is enabled, this function has to browse the length of * all lcores, so it should not be used in a data path, but only for * debug purposes. * * @param mp * A pointer to the mempool structure. * @return * The number of free entries in the mempool. */ static inline unsigned rte_mempool_free_count(const struct rte_mempool *mp) { return mp->size - rte_mempool_count(mp); } /** * Test if the mempool is full. * * When cache is enabled, this function has to browse the length of all * lcores, so it should not be used in a data path, but only for debug * purposes. * * @param mp * A pointer to the mempool structure. * @return * - 1: The mempool is full. * - 0: The mempool is not full. */ static inline int rte_mempool_full(const struct rte_mempool *mp) { return !!(rte_mempool_count(mp) == mp->size); } /** * Test if the mempool is empty. * * When cache is enabled, this function has to browse the length of all * lcores, so it should not be used in a data path, but only for debug * purposes. * * @param mp * A pointer to the mempool structure. * @return * - 1: The mempool is empty. * - 0: The mempool is not empty. */ static inline int rte_mempool_empty(const struct rte_mempool *mp) { return !!(rte_mempool_count(mp) == 0); } /** * Return the physical address of elt, which is an element of the pool mp. * * @param mp * A pointer to the mempool structure. * @param elt * A pointer (virtual address) to the element of the pool. * @return * The physical address of the elt element. */ static inline phys_addr_t rte_mempool_virt2phy(const struct rte_mempool *mp, const void *elt) { if (rte_eal_has_hugepages()) { uintptr_t off; off = (const char *)elt - (const char *)mp->elt_va_start; return (mp->elt_pa[off >> mp->pg_shift] + (off & mp->pg_mask)); } else { /* * If huge pages are disabled, we cannot assume the * memory region to be physically contiguous. * Lookup for each element. */ return rte_mem_virt2phy(elt); } } /** * Check the consistency of mempool objects. * * Verify the coherency of fields in the mempool structure. Also check * that the cookies of mempool objects (even the ones that are not * present in pool) have a correct value. If not, a panic will occur. * * @param mp * A pointer to the mempool structure. */ void rte_mempool_audit(const struct rte_mempool *mp); /** * Return a pointer to the private data in an mempool structure. * * @param mp * A pointer to the mempool structure. * @return * A pointer to the private data. */ static inline void *rte_mempool_get_priv(struct rte_mempool *mp) { return (char *)mp + MEMPOOL_HEADER_SIZE(mp, mp->pg_num); } /** * Dump the status of all mempools on the console * * @param f * A pointer to a file for output */ void rte_mempool_list_dump(FILE *f); /** * Search a mempool from its name * * @param name * The name of the mempool. * @return * The pointer to the mempool matching the name, or NULL if not found. * NULL on error * with rte_errno set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. * */ struct rte_mempool *rte_mempool_lookup(const char *name); /** * Get the header, trailer and total size of a mempool element. * * Given a desired size of the mempool element and mempool flags, * calculates header, trailer, body and total sizes of the mempool object. * * @param elt_size * The size of each element. * @param flags * The flags used for the mempool creation. * Consult rte_mempool_create() for more information about possible values. * The size of each element. * @param sz * The calculated detailed size the mempool object. May be NULL. * @return * Total size of the mempool object. */ uint32_t rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags, struct rte_mempool_objsz *sz); /** * Get the size of memory required to store mempool elements. * * Calculate the maximum amount of memory required to store given number * of objects. Assume that the memory buffer will be aligned at page * boundary. * * Note that if object size is bigger then page size, then it assumes * that pages are grouped in subsets of physically continuous pages big * enough to store at least one object. * * @param elt_num * Number of elements. * @param elt_sz * The size of each element. * @param pg_shift * LOG2 of the physical pages size. * @return * Required memory size aligned at page boundary. */ size_t rte_mempool_xmem_size(uint32_t elt_num, size_t elt_sz, uint32_t pg_shift); /** * Get the size of memory required to store mempool elements. * * Calculate how much memory would be actually required with the given * memory footprint to store required number of objects. * * @param vaddr * Virtual address of the externally allocated memory buffer. * Will be used to store mempool objects. * @param elt_num * Number of elements. * @param elt_sz * The size of each element. * @param paddr * Array of physical addresses of the pages that comprises given memory * buffer. * @param pg_num * Number of elements in the paddr array. * @param pg_shift * LOG2 of the physical pages size. * @return * On success, the number of bytes needed to store given number of * objects, aligned to the given page size. If the provided memory * buffer is too small, return a negative value whose absolute value * is the actual number of elements that can be stored in that buffer. */ ssize_t rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, size_t elt_sz, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift); /** * Walk list of all memory pools * * @param func * Iterator function * @param arg * Argument passed to iterator */ void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *arg), void *arg); #ifdef __cplusplus } #endif #endif /* _RTE_MEMPOOL_H_ */ ================================================ FILE: lib/librte_meter/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_meter.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_meter_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_METER) := rte_meter.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_METER)-include := rte_meter.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_METER) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_meter/rte_meter.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "rte_meter.h" #ifndef RTE_METER_TB_PERIOD_MIN #define RTE_METER_TB_PERIOD_MIN 100 #endif static void rte_meter_get_tb_params(uint64_t hz, uint64_t rate, uint64_t *tb_period, uint64_t *tb_bytes_per_period) { double period = ((double) hz) / ((double) rate); if (period >= RTE_METER_TB_PERIOD_MIN) { *tb_bytes_per_period = 1; *tb_period = (uint64_t) period; } else { *tb_bytes_per_period = (uint64_t) ceil(RTE_METER_TB_PERIOD_MIN / period); *tb_period = (hz * (*tb_bytes_per_period)) / rate; } } int rte_meter_srtcm_config(struct rte_meter_srtcm *m, struct rte_meter_srtcm_params *params) { uint64_t hz; /* Check input parameters */ if ((m == NULL) || (params == NULL)) { return -1; } if ((params->cir == 0) || ((params->cbs == 0) && (params->ebs == 0))) { return -2; } /* Initialize srTCM run-time structure */ hz = rte_get_tsc_hz(); m->time = rte_get_tsc_cycles(); m->tc = m->cbs = params->cbs; m->te = m->ebs = params->ebs; rte_meter_get_tb_params(hz, params->cir, &m->cir_period, &m->cir_bytes_per_period); RTE_LOG(INFO, METER, "Low level srTCM config: \n" "\tCIR period = %" PRIu64 ", CIR bytes per period = %" PRIu64 "\n", m->cir_period, m->cir_bytes_per_period); return 0; } int rte_meter_trtcm_config(struct rte_meter_trtcm *m, struct rte_meter_trtcm_params *params) { uint64_t hz; /* Check input parameters */ if ((m == NULL) || (params == NULL)) { return -1; } if ((params->cir == 0) || (params->pir == 0) || (params->pir < params->cir) || (params->cbs == 0) || (params->pbs == 0)) { return -2; } /* Initialize trTCM run-time structure */ hz = rte_get_tsc_hz(); m->time_tc = m->time_tp = rte_get_tsc_cycles(); m->tc = m->cbs = params->cbs; m->tp = m->pbs = params->pbs; rte_meter_get_tb_params(hz, params->cir, &m->cir_period, &m->cir_bytes_per_period); rte_meter_get_tb_params(hz, params->pir, &m->pir_period, &m->pir_bytes_per_period); RTE_LOG(INFO, METER, "Low level trTCM config: \n" "\tCIR period = %" PRIu64 ", CIR bytes per period = %" PRIu64 "\n" "\tPIR period = %" PRIu64 ", PIR bytes per period = %" PRIu64 "\n", m->cir_period, m->cir_bytes_per_period, m->pir_period, m->pir_bytes_per_period); return 0; } ================================================ FILE: lib/librte_meter/rte_meter.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_METER_H__ #define __INCLUDE_RTE_METER_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Traffic Metering * * Traffic metering algorithms: * 1. Single Rate Three Color Marker (srTCM): defined by IETF RFC 2697 * 2. Two Rate Three Color Marker (trTCM): defined by IETF RFC 2698 * ***/ #include /* * Application Programmer's Interface (API) * ***/ /** Packet Color Set */ enum rte_meter_color { e_RTE_METER_GREEN = 0, /**< Green */ e_RTE_METER_YELLOW, /**< Yellow */ e_RTE_METER_RED, /**< Red */ e_RTE_METER_COLORS /**< Number of available colors */ }; /** srTCM parameters per metered traffic flow. The CIR, CBS and EBS parameters only count bytes of IP packets and do not include link specific headers. At least one of the CBS or EBS parameters has to be greater than zero. */ struct rte_meter_srtcm_params { uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */ uint64_t cbs; /**< Committed Burst Size (CBS). Measured in bytes. */ uint64_t ebs; /**< Excess Burst Size (EBS). Measured in bytes. */ }; /** trTCM parameters per metered traffic flow. The CIR, PIR, CBS and PBS parameters only count bytes of IP packets and do not include link specific headers. PIR has to be greater than or equal to CIR. Both CBS or EBS have to be greater than zero. */ struct rte_meter_trtcm_params { uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */ uint64_t pir; /**< Peak Information Rate (PIR). Measured in bytes per second. */ uint64_t cbs; /**< Committed Burst Size (CBS). Measured in byes. */ uint64_t pbs; /**< Peak Burst Size (PBS). Measured in bytes. */ }; /** Internal data structure storing the srTCM run-time context per metered traffic flow. */ struct rte_meter_srtcm; /** Internal data structure storing the trTCM run-time context per metered traffic flow. */ struct rte_meter_trtcm; /** * srTCM configuration per metered traffic flow * * @param m * Pointer to pre-allocated srTCM data structure * @param params * User parameters per srTCM metered traffic flow * @return * 0 upon success, error code otherwise */ int rte_meter_srtcm_config(struct rte_meter_srtcm *m, struct rte_meter_srtcm_params *params); /** * trTCM configuration per metered traffic flow * * @param m * Pointer to pre-allocated trTCM data structure * @param params * User parameters per trTCM metered traffic flow * @return * 0 upon success, error code otherwise */ int rte_meter_trtcm_config(struct rte_meter_trtcm *m, struct rte_meter_trtcm_params *params); /** * srTCM color blind traffic metering * * @param m * Handle to srTCM instance * @param time * Current CPU time stamp (measured in CPU cycles) * @param pkt_len * Length of the current IP packet (measured in bytes) * @return * Color assigned to the current IP packet */ static inline enum rte_meter_color rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m, uint64_t time, uint32_t pkt_len); /** * srTCM color aware traffic metering * * @param m * Handle to srTCM instance * @param time * Current CPU time stamp (measured in CPU cycles) * @param pkt_len * Length of the current IP packet (measured in bytes) * @param pkt_color * Input color of the current IP packet * @return * Color assigned to the current IP packet */ static inline enum rte_meter_color rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m, uint64_t time, uint32_t pkt_len, enum rte_meter_color pkt_color); /** * trTCM color blind traffic metering * * @param m * Handle to trTCM instance * @param time * Current CPU time stamp (measured in CPU cycles) * @param pkt_len * Length of the current IP packet (measured in bytes) * @return * Color assigned to the current IP packet */ static inline enum rte_meter_color rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m, uint64_t time, uint32_t pkt_len); /** * trTCM color aware traffic metering * * @param m * Handle to trTCM instance * @param time * Current CPU time stamp (measured in CPU cycles) * @param pkt_len * Length of the current IP packet (measured in bytes) * @param pkt_color * Input color of the current IP packet * @return * Color assigned to the current IP packet */ static inline enum rte_meter_color rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m, uint64_t time, uint32_t pkt_len, enum rte_meter_color pkt_color); /* * Inline implementation of run-time methods * ***/ /* Internal data structure storing the srTCM run-time context per metered traffic flow. */ struct rte_meter_srtcm { uint64_t time; /* Time of latest update of C and E token buckets */ uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */ uint64_t te; /* Number of bytes currently available in the excess (E) token bucket */ uint64_t cbs; /* Upper limit for C token bucket */ uint64_t ebs; /* Upper limit for E token bucket */ uint64_t cir_period; /* Number of CPU cycles for one update of C and E token buckets */ uint64_t cir_bytes_per_period; /* Number of bytes to add to C and E token buckets on each update */ }; /* Internal data structure storing the trTCM run-time context per metered traffic flow. */ struct rte_meter_trtcm { uint64_t time_tc; /* Time of latest update of C token bucket */ uint64_t time_tp; /* Time of latest update of E token bucket */ uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */ uint64_t tp; /* Number of bytes currently available in the peak (P) token bucket */ uint64_t cbs; /* Upper limit for C token bucket */ uint64_t pbs; /* Upper limit for P token bucket */ uint64_t cir_period; /* Number of CPU cycles for one update of C token bucket */ uint64_t cir_bytes_per_period; /* Number of bytes to add to C token bucket on each update */ uint64_t pir_period; /* Number of CPU cycles for one update of P token bucket */ uint64_t pir_bytes_per_period; /* Number of bytes to add to P token bucket on each update */ }; static inline enum rte_meter_color rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m, uint64_t time, uint32_t pkt_len) { uint64_t time_diff, n_periods, tc, te; /* Bucket update */ time_diff = time - m->time; n_periods = time_diff / m->cir_period; m->time += n_periods * m->cir_period; tc = m->tc + n_periods * m->cir_bytes_per_period; if (tc > m->cbs) tc = m->cbs; te = m->te + n_periods * m->cir_bytes_per_period; if (te > m->ebs) te = m->ebs; /* Color logic */ if (tc >= pkt_len) { m->tc = tc - pkt_len; m->te = te; return e_RTE_METER_GREEN; } if (te >= pkt_len) { m->tc = tc; m->te = te - pkt_len; return e_RTE_METER_YELLOW; } m->tc = tc; m->te = te; return e_RTE_METER_RED; } static inline enum rte_meter_color rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m, uint64_t time, uint32_t pkt_len, enum rte_meter_color pkt_color) { uint64_t time_diff, n_periods, tc, te; /* Bucket update */ time_diff = time - m->time; n_periods = time_diff / m->cir_period; m->time += n_periods * m->cir_period; tc = m->tc + n_periods * m->cir_bytes_per_period; if (tc > m->cbs) tc = m->cbs; te = m->te + n_periods * m->cir_bytes_per_period; if (te > m->ebs) te = m->ebs; /* Color logic */ if ((pkt_color == e_RTE_METER_GREEN) && (tc >= pkt_len)) { m->tc = tc - pkt_len; m->te = te; return e_RTE_METER_GREEN; } if ((pkt_color != e_RTE_METER_RED) && (te >= pkt_len)) { m->tc = tc; m->te = te - pkt_len; return e_RTE_METER_YELLOW; } m->tc = tc; m->te = te; return e_RTE_METER_RED; } static inline enum rte_meter_color rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m, uint64_t time, uint32_t pkt_len) { uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp; /* Bucket update */ time_diff_tc = time - m->time_tc; time_diff_tp = time - m->time_tp; n_periods_tc = time_diff_tc / m->cir_period; n_periods_tp = time_diff_tp / m->pir_period; m->time_tc += n_periods_tc * m->cir_period; m->time_tp += n_periods_tp * m->pir_period; tc = m->tc + n_periods_tc * m->cir_bytes_per_period; if (tc > m->cbs) tc = m->cbs; tp = m->tp + n_periods_tp * m->pir_bytes_per_period; if (tp > m->pbs) tp = m->pbs; /* Color logic */ if (tp < pkt_len) { m->tc = tc; m->tp = tp; return e_RTE_METER_RED; } if (tc < pkt_len) { m->tc = tc; m->tp = tp - pkt_len; return e_RTE_METER_YELLOW; } m->tc = tc - pkt_len; m->tp = tp - pkt_len; return e_RTE_METER_GREEN; } static inline enum rte_meter_color rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m, uint64_t time, uint32_t pkt_len, enum rte_meter_color pkt_color) { uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp; /* Bucket update */ time_diff_tc = time - m->time_tc; time_diff_tp = time - m->time_tp; n_periods_tc = time_diff_tc / m->cir_period; n_periods_tp = time_diff_tp / m->pir_period; m->time_tc += n_periods_tc * m->cir_period; m->time_tp += n_periods_tp * m->pir_period; tc = m->tc + n_periods_tc * m->cir_bytes_per_period; if (tc > m->cbs) tc = m->cbs; tp = m->tp + n_periods_tp * m->pir_bytes_per_period; if (tp > m->pbs) tp = m->pbs; /* Color logic */ if ((pkt_color == e_RTE_METER_RED) || (tp < pkt_len)) { m->tc = tc; m->tp = tp; return e_RTE_METER_RED; } if ((pkt_color == e_RTE_METER_YELLOW) || (tc < pkt_len)) { m->tc = tc; m->tp = tp - pkt_len; return e_RTE_METER_YELLOW; } m->tc = tc - pkt_len; m->tp = tp - pkt_len; return e_RTE_METER_GREEN; } #ifdef __cplusplus } #endif #endif /* __INCLUDE_RTE_METER_H__ */ ================================================ FILE: lib/librte_net/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h rte_sctp.h rte_icmp.h rte_arp.h include $(RTE_SDK)/mk/rte.install.mk ================================================ FILE: lib/librte_net/rte_arp.h ================================================ /* BSD LICENSE * * Copyright(c) 2013 6WIND. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_ARP_H_ #define _RTE_ARP_H_ /** * @file * * ARP-related defines */ #include #include #ifdef __cplusplus extern "C" { #endif /** * ARP header IPv4 payload. */ struct arp_ipv4 { struct ether_addr arp_sha; /**< sender hardware address */ uint32_t arp_sip; /**< sender IP address */ struct ether_addr arp_tha; /**< target hardware address */ uint32_t arp_tip; /**< target IP address */ } __attribute__((__packed__)); /** * ARP header. */ struct arp_hdr { uint16_t arp_hrd; /* format of hardware address */ #define ARP_HRD_ETHER 1 /* ARP Ethernet address format */ uint16_t arp_pro; /* format of protocol address */ uint8_t arp_hln; /* length of hardware address */ uint8_t arp_pln; /* length of protocol address */ uint16_t arp_op; /* ARP opcode (command) */ #define ARP_OP_REQUEST 1 /* request to resolve address */ #define ARP_OP_REPLY 2 /* response to previous request */ #define ARP_OP_REVREQUEST 3 /* request proto addr given hardware */ #define ARP_OP_REVREPLY 4 /* response giving protocol address */ #define ARP_OP_INVREQUEST 8 /* request to identify peer */ #define ARP_OP_INVREPLY 9 /* response identifying peer */ struct arp_ipv4 arp_data; } __attribute__((__packed__)); #ifdef __cplusplus } #endif #endif /* _RTE_ARP_H_ */ ================================================ FILE: lib/librte_net/rte_icmp.h ================================================ /* BSD LICENSE * * Copyright(c) 2013 6WIND. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of 6WIND S.A. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ */ #ifndef _RTE_ICMP_H_ #define _RTE_ICMP_H_ /** * @file * * ICMP-related defines */ #include #ifdef __cplusplus extern "C" { #endif /** * ICMP Header */ struct icmp_hdr { uint8_t icmp_type; /* ICMP packet type. */ uint8_t icmp_code; /* ICMP packet code. */ uint16_t icmp_cksum; /* ICMP packet checksum. */ uint16_t icmp_ident; /* ICMP packet identifier. */ uint16_t icmp_seq_nb; /* ICMP packet sequence number. */ } __attribute__((__packed__)); /* ICMP packet types */ #define IP_ICMP_ECHO_REPLY 0 #define IP_ICMP_ECHO_REQUEST 8 #ifdef __cplusplus } #endif #endif /* RTE_ICMP_H_ */ ================================================ FILE: lib/librte_net/rte_ip.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * Copyright 2014 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ */ #ifndef _RTE_IP_H_ #define _RTE_IP_H_ /** * @file * * IP-related defines */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * IPv4 Header */ struct ipv4_hdr { uint8_t version_ihl; /**< version and header length */ uint8_t type_of_service; /**< type of service */ uint16_t total_length; /**< length of packet */ uint16_t packet_id; /**< packet ID */ uint16_t fragment_offset; /**< fragmentation offset */ uint8_t time_to_live; /**< time to live */ uint8_t next_proto_id; /**< protocol ID */ uint16_t hdr_checksum; /**< header checksum */ uint32_t src_addr; /**< source address */ uint32_t dst_addr; /**< destination address */ } __attribute__((__packed__)); /** Create IPv4 address */ #define IPv4(a,b,c,d) ((uint32_t)(((a) & 0xff) << 24) | \ (((b) & 0xff) << 16) | \ (((c) & 0xff) << 8) | \ ((d) & 0xff)) /** Maximal IPv4 packet length (including a header) */ #define IPV4_MAX_PKT_LEN 65535 /** Internet header length mask for version_ihl field */ #define IPV4_HDR_IHL_MASK (0x0f) /** * Internet header length field multiplier (IHL field specifies overall header * length in number of 4-byte words) */ #define IPV4_IHL_MULTIPLIER (4) /* Fragment Offset * Flags. */ #define IPV4_HDR_DF_SHIFT 14 #define IPV4_HDR_MF_SHIFT 13 #define IPV4_HDR_FO_SHIFT 3 #define IPV4_HDR_DF_FLAG (1 << IPV4_HDR_DF_SHIFT) #define IPV4_HDR_MF_FLAG (1 << IPV4_HDR_MF_SHIFT) #define IPV4_HDR_OFFSET_MASK ((1 << IPV4_HDR_MF_SHIFT) - 1) #define IPV4_HDR_OFFSET_UNITS 8 /* * IPv4 address types */ #define IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */ #define IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */ #define IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */ #define IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */ #define IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */ #define IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */ /* * IPv4 Multicast-related macros */ #define IPV4_MIN_MCAST IPv4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */ #define IPV4_MAX_MCAST IPv4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */ #define IS_IPV4_MCAST(x) \ ((x) >= IPV4_MIN_MCAST && (x) <= IPV4_MAX_MCAST) /**< check if IPv4 address is multicast */ /** * @internal Calculate a sum of all words in the buffer. * Helper routine for the rte_raw_cksum(). * * @param buf * Pointer to the buffer. * @param len * Length of the buffer. * @param sum * Initial value of the sum. * @return * sum += Sum of all words in the buffer. */ static inline uint32_t __rte_raw_cksum(const void *buf, size_t len, uint32_t sum) { /* workaround gcc strict-aliasing warning */ uintptr_t ptr = (uintptr_t)buf; const uint16_t *u16 = (const uint16_t *)ptr; while (len >= (sizeof(*u16) * 4)) { sum += u16[0]; sum += u16[1]; sum += u16[2]; sum += u16[3]; len -= sizeof(*u16) * 4; u16 += 4; } while (len >= sizeof(*u16)) { sum += *u16; len -= sizeof(*u16); u16 += 1; } /* if length is in odd bytes */ if (len == 1) sum += *((const uint8_t *)u16); return sum; } /** * @internal Reduce a sum to the non-complemented checksum. * Helper routine for the rte_raw_cksum(). * * @param sum * Value of the sum. * @return * The non-complemented checksum. */ static inline uint16_t __rte_raw_cksum_reduce(uint32_t sum) { sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); return (uint16_t)sum; } /** * Process the non-complemented checksum of a buffer. * * @param buf * Pointer to the buffer. * @param len * Length of the buffer. * @return * The non-complemented checksum. */ static inline uint16_t rte_raw_cksum(const void *buf, size_t len) { uint32_t sum; sum = __rte_raw_cksum(buf, len, 0); return __rte_raw_cksum_reduce(sum); } /** * Process the IPv4 checksum of an IPv4 header. * * The checksum field must be set to 0 by the caller. * * @param ipv4_hdr * The pointer to the contiguous IPv4 header. * @return * The complemented checksum to set in the IP packet. */ static inline uint16_t rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr) { uint16_t cksum; cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct ipv4_hdr)); return (cksum == 0xffff) ? cksum : ~cksum; } /** * Process the pseudo-header checksum of an IPv4 header. * * The checksum field must be set to 0 by the caller. * * Depending on the ol_flags, the pseudo-header checksum expected by the * drivers is not the same. For instance, when TSO is enabled, the IP * payload length must not be included in the packet. * * When ol_flags is 0, it computes the standard pseudo-header checksum. * * @param ipv4_hdr * The pointer to the contiguous IPv4 header. * @param ol_flags * The ol_flags of the associated mbuf. * @return * The non-complemented checksum to set in the L4 header. */ static inline uint16_t rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr, uint64_t ol_flags) { struct ipv4_psd_header { uint32_t src_addr; /* IP address of source host. */ uint32_t dst_addr; /* IP address of destination host. */ uint8_t zero; /* zero. */ uint8_t proto; /* L4 protocol type. */ uint16_t len; /* L4 length. */ } psd_hdr; psd_hdr.src_addr = ipv4_hdr->src_addr; psd_hdr.dst_addr = ipv4_hdr->dst_addr; psd_hdr.zero = 0; psd_hdr.proto = ipv4_hdr->next_proto_id; if (ol_flags & PKT_TX_TCP_SEG) { psd_hdr.len = 0; } else { psd_hdr.len = rte_cpu_to_be_16( (uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) - sizeof(struct ipv4_hdr))); } return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr)); } /** * Process the IPv4 UDP or TCP checksum. * * The IPv4 header should not contains options. The IP and layer 4 * checksum must be set to 0 in the packet by the caller. * * @param ipv4_hdr * The pointer to the contiguous IPv4 header. * @param l4_hdr * The pointer to the beginning of the L4 header. * @return * The complemented checksum to set in the IP packet. */ static inline uint16_t rte_ipv4_udptcp_cksum(const struct ipv4_hdr *ipv4_hdr, const void *l4_hdr) { uint32_t cksum; uint32_t l4_len; l4_len = rte_be_to_cpu_16(ipv4_hdr->total_length) - sizeof(struct ipv4_hdr); cksum = rte_raw_cksum(l4_hdr, l4_len); cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0); cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); cksum = (~cksum) & 0xffff; if (cksum == 0) cksum = 0xffff; return cksum; } /** * IPv6 Header */ struct ipv6_hdr { uint32_t vtc_flow; /**< IP version, traffic class & flow label. */ uint16_t payload_len; /**< IP packet length - includes sizeof(ip_header). */ uint8_t proto; /**< Protocol, next header. */ uint8_t hop_limits; /**< Hop limits. */ uint8_t src_addr[16]; /**< IP address of source host. */ uint8_t dst_addr[16]; /**< IP address of destination host(s). */ } __attribute__((__packed__)); /** * Process the pseudo-header checksum of an IPv6 header. * * Depending on the ol_flags, the pseudo-header checksum expected by the * drivers is not the same. For instance, when TSO is enabled, the IPv6 * payload length must not be included in the packet. * * When ol_flags is 0, it computes the standard pseudo-header checksum. * * @param ipv6_hdr * The pointer to the contiguous IPv6 header. * @param ol_flags * The ol_flags of the associated mbuf. * @return * The non-complemented checksum to set in the L4 header. */ static inline uint16_t rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr, uint64_t ol_flags) { uint32_t sum; struct { uint32_t len; /* L4 length. */ uint32_t proto; /* L4 protocol - top 3 bytes must be zero */ } psd_hdr; psd_hdr.proto = (ipv6_hdr->proto << 24); if (ol_flags & PKT_TX_TCP_SEG) { psd_hdr.len = 0; } else { psd_hdr.len = ipv6_hdr->payload_len; } sum = __rte_raw_cksum(ipv6_hdr->src_addr, sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr), 0); sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum); return __rte_raw_cksum_reduce(sum); } /** * Process the IPv6 UDP or TCP checksum. * * The IPv4 header should not contains options. The layer 4 checksum * must be set to 0 in the packet by the caller. * * @param ipv6_hdr * The pointer to the contiguous IPv6 header. * @param l4_hdr * The pointer to the beginning of the L4 header. * @return * The complemented checksum to set in the IP packet. */ static inline uint16_t rte_ipv6_udptcp_cksum(const struct ipv6_hdr *ipv6_hdr, const void *l4_hdr) { uint32_t cksum; uint32_t l4_len; l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len); cksum = rte_raw_cksum(l4_hdr, l4_len); cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0); cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff); cksum = (~cksum) & 0xffff; if (cksum == 0) cksum = 0xffff; return cksum; } #ifdef __cplusplus } #endif #endif /* _RTE_IP_H_ */ ================================================ FILE: lib/librte_net/rte_sctp.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ */ /** * @file * * SCTP-related defines */ #ifndef _RTE_SCTP_H_ #define _RTE_SCTP_H_ #ifdef __cplusplus extern "C" { #endif #include /** * SCTP Header */ struct sctp_hdr { uint16_t src_port; /**< Source port. */ uint16_t dst_port; /**< Destin port. */ uint32_t tag; /**< Validation tag. */ uint32_t cksum; /**< Checksum. */ } __attribute__((__packed__)); #ifdef __cplusplus } #endif #endif /* RTE_SCTP_H_ */ ================================================ FILE: lib/librte_net/rte_tcp.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ */ #ifndef _RTE_TCP_H_ #define _RTE_TCP_H_ /** * @file * * TCP-related defines */ #include #ifdef __cplusplus extern "C" { #endif /** * TCP Header */ struct tcp_hdr { uint16_t src_port; /**< TCP source port. */ uint16_t dst_port; /**< TCP destination port. */ uint32_t sent_seq; /**< TX data sequence number. */ uint32_t recv_ack; /**< RX data acknowledgement sequence number. */ uint8_t data_off; /**< Data offset. */ uint8_t tcp_flags; /**< TCP flags */ uint16_t rx_win; /**< RX flow control window. */ uint16_t cksum; /**< TCP checksum. */ uint16_t tcp_urp; /**< TCP urgent pointer, if any. */ } __attribute__((__packed__)); #ifdef __cplusplus } #endif #endif /* RTE_TCP_H_ */ ================================================ FILE: lib/librte_net/rte_udp.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 * $FreeBSD: src/sys/netinet/in.h,v 1.82 2003/10/25 09:37:10 ume Exp $ */ #ifndef _RTE_UDP_H_ #define _RTE_UDP_H_ /** * @file * * UDP-related defines */ #include #ifdef __cplusplus extern "C" { #endif /** * UDP Header */ struct udp_hdr { uint16_t src_port; /**< UDP source port. */ uint16_t dst_port; /**< UDP destination port. */ uint16_t dgram_len; /**< UDP datagram length */ uint16_t dgram_cksum; /**< UDP datagram checksum */ } __attribute__((__packed__)); #ifdef __cplusplus } #endif #endif /* RTE_UDP_H_ */ ================================================ FILE: lib/librte_pipeline/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_pipeline.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_pipeline_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := rte_pipeline.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_PIPELINE)-include += rte_pipeline.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) := lib/librte_table DEPDIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib/librte_port include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_pipeline/rte_pipeline.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "rte_pipeline.h" #define RTE_TABLE_INVALID UINT32_MAX #ifdef RTE_PIPELINE_STATS_COLLECT #define RTE_PIPELINE_STATS_ADD(counter, val) \ ({ (counter) += (val); }) #define RTE_PIPELINE_STATS_ADD_M(counter, mask) \ ({ (counter) += __builtin_popcountll(mask); }) #else #define RTE_PIPELINE_STATS_ADD(counter, val) #define RTE_PIPELINE_STATS_ADD_M(counter, mask) #endif struct rte_port_in { /* Input parameters */ struct rte_port_in_ops ops; rte_pipeline_port_in_action_handler f_action; void *arg_ah; uint32_t burst_size; /* The table to which this port is connected */ uint32_t table_id; /* Handle to low-level port */ void *h_port; /* List of enabled ports */ struct rte_port_in *next; uint64_t n_pkts_dropped_by_ah; }; struct rte_port_out { /* Input parameters */ struct rte_port_out_ops ops; rte_pipeline_port_out_action_handler f_action; rte_pipeline_port_out_action_handler_bulk f_action_bulk; void *arg_ah; /* Handle to low-level port */ void *h_port; uint64_t n_pkts_dropped_by_ah; }; struct rte_table { /* Input parameters */ struct rte_table_ops ops; rte_pipeline_table_action_handler_hit f_action_hit; rte_pipeline_table_action_handler_miss f_action_miss; void *arg_ah; struct rte_pipeline_table_entry *default_entry; uint32_t entry_size; uint32_t table_next_id; uint32_t table_next_id_valid; /* Handle to the low-level table object */ void *h_table; /* Stats for this table. */ uint64_t n_pkts_dropped_by_lkp_hit_ah; uint64_t n_pkts_dropped_by_lkp_miss_ah; uint64_t n_pkts_dropped_lkp_hit; uint64_t n_pkts_dropped_lkp_miss; }; #define RTE_PIPELINE_MAX_NAME_SZ 124 struct rte_pipeline { /* Input parameters */ char name[RTE_PIPELINE_MAX_NAME_SZ]; int socket_id; uint32_t offset_port_id; /* Internal tables */ struct rte_port_in ports_in[RTE_PIPELINE_PORT_IN_MAX]; struct rte_port_out ports_out[RTE_PIPELINE_PORT_OUT_MAX]; struct rte_table tables[RTE_PIPELINE_TABLE_MAX]; /* Occupancy of internal tables */ uint32_t num_ports_in; uint32_t num_ports_out; uint32_t num_tables; /* List of enabled ports */ uint64_t enabled_port_in_mask; struct rte_port_in *port_in_first; /* Pipeline run structures */ struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_pipeline_table_entry *entries[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t action_mask0[RTE_PIPELINE_ACTIONS]; uint64_t action_mask1[RTE_PIPELINE_ACTIONS]; } __rte_cache_aligned; static inline uint32_t rte_mask_get_next(uint64_t mask, uint32_t pos) { uint64_t mask_rot = (mask << ((63 - pos) & 0x3F)) | (mask >> ((pos + 1) & 0x3F)); return (__builtin_ctzll(mask_rot) - (63 - pos)) & 0x3F; } static inline uint32_t rte_mask_get_prev(uint64_t mask, uint32_t pos) { uint64_t mask_rot = (mask >> (pos & 0x3F)) | (mask << ((64 - pos) & 0x3F)); return ((63 - __builtin_clzll(mask_rot)) + pos) & 0x3F; } static void rte_pipeline_table_free(struct rte_table *table); static void rte_pipeline_port_in_free(struct rte_port_in *port); static void rte_pipeline_port_out_free(struct rte_port_out *port); /* * Pipeline * */ static int rte_pipeline_check_params(struct rte_pipeline_params *params) { if (params == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Incorrect value for parameter params\n", __func__); return -EINVAL; } /* name */ if (params->name == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Incorrect value for parameter name\n", __func__); return -EINVAL; } /* socket */ if ((params->socket_id < 0) || (params->socket_id >= RTE_MAX_NUMA_NODES)) { RTE_LOG(ERR, PIPELINE, "%s: Incorrect value for parameter socket_id\n", __func__); return -EINVAL; } return 0; } struct rte_pipeline * rte_pipeline_create(struct rte_pipeline_params *params) { struct rte_pipeline *p; int status; /* Check input parameters */ status = rte_pipeline_check_params(params); if (status != 0) { RTE_LOG(ERR, PIPELINE, "%s: Pipeline params check failed (%d)\n", __func__, status); return NULL; } /* Allocate memory for the pipeline on requested socket */ p = rte_zmalloc_socket("PIPELINE", sizeof(struct rte_pipeline), RTE_CACHE_LINE_SIZE, params->socket_id); if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Pipeline memory allocation failed\n", __func__); return NULL; } /* Save input parameters */ snprintf(p->name, RTE_PIPELINE_MAX_NAME_SZ, "%s", params->name); p->socket_id = params->socket_id; p->offset_port_id = params->offset_port_id; /* Initialize pipeline internal data structure */ p->num_ports_in = 0; p->num_ports_out = 0; p->num_tables = 0; p->enabled_port_in_mask = 0; p->port_in_first = NULL; return p; } int rte_pipeline_free(struct rte_pipeline *p) { uint32_t i; /* Check input parameters */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: rte_pipeline parameter is NULL\n", __func__); return -EINVAL; } /* Free input ports */ for (i = 0; i < p->num_ports_in; i++) { struct rte_port_in *port = &p->ports_in[i]; rte_pipeline_port_in_free(port); } /* Free tables */ for (i = 0; i < p->num_tables; i++) { struct rte_table *table = &p->tables[i]; rte_pipeline_table_free(table); } /* Free output ports */ for (i = 0; i < p->num_ports_out; i++) { struct rte_port_out *port = &p->ports_out[i]; rte_pipeline_port_out_free(port); } /* Free pipeline memory */ rte_free(p); return 0; } /* * Table * */ static int rte_table_check_params(struct rte_pipeline *p, struct rte_pipeline_table_params *params, uint32_t *table_id) { if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n", __func__); return -EINVAL; } if (params == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params parameter is NULL\n", __func__); return -EINVAL; } if (table_id == NULL) { RTE_LOG(ERR, PIPELINE, "%s: table_id parameter is NULL\n", __func__); return -EINVAL; } /* ops */ if (params->ops == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params->ops is NULL\n", __func__); return -EINVAL; } if (params->ops->f_create == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_create function pointer is NULL\n", __func__); return -EINVAL; } if (params->ops->f_lookup == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_lookup function pointer is NULL\n", __func__); return -EINVAL; } /* De we have room for one more table? */ if (p->num_tables == RTE_PIPELINE_TABLE_MAX) { RTE_LOG(ERR, PIPELINE, "%s: Incorrect value for num_tables parameter\n", __func__); return -EINVAL; } return 0; } int rte_pipeline_table_create(struct rte_pipeline *p, struct rte_pipeline_table_params *params, uint32_t *table_id) { struct rte_table *table; struct rte_pipeline_table_entry *default_entry; void *h_table; uint32_t entry_size, id; int status; /* Check input arguments */ status = rte_table_check_params(p, params, table_id); if (status != 0) return status; id = p->num_tables; table = &p->tables[id]; /* Allocate space for the default table entry */ entry_size = sizeof(struct rte_pipeline_table_entry) + params->action_data_size; default_entry = (struct rte_pipeline_table_entry *) rte_zmalloc_socket( "PIPELINE", entry_size, RTE_CACHE_LINE_SIZE, p->socket_id); if (default_entry == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Failed to allocate default entry\n", __func__); return -EINVAL; } /* Create the table */ h_table = params->ops->f_create(params->arg_create, p->socket_id, entry_size); if (h_table == NULL) { rte_free(default_entry); RTE_LOG(ERR, PIPELINE, "%s: Table creation failed\n", __func__); return -EINVAL; } /* Commit current table to the pipeline */ p->num_tables++; *table_id = id; /* Save input parameters */ memcpy(&table->ops, params->ops, sizeof(struct rte_table_ops)); table->f_action_hit = params->f_action_hit; table->f_action_miss = params->f_action_miss; table->arg_ah = params->arg_ah; table->entry_size = entry_size; /* Clear the lookup miss actions (to be set later through API) */ table->default_entry = default_entry; table->default_entry->action = RTE_PIPELINE_ACTION_DROP; /* Initialize table internal data structure */ table->h_table = h_table; table->table_next_id = 0; table->table_next_id_valid = 0; return 0; } void rte_pipeline_table_free(struct rte_table *table) { if (table->ops.f_free != NULL) table->ops.f_free(table->h_table); rte_free(table->default_entry); } int rte_pipeline_table_default_entry_add(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_entry *default_entry, struct rte_pipeline_table_entry **default_entry_ptr) { struct rte_table *table; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n", __func__); return -EINVAL; } if (default_entry == NULL) { RTE_LOG(ERR, PIPELINE, "%s: default_entry parameter is NULL\n", __func__); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: table_id %d out of range\n", __func__, table_id); return -EINVAL; } table = &p->tables[table_id]; if ((default_entry->action == RTE_PIPELINE_ACTION_TABLE) && table->table_next_id_valid && (default_entry->table_id != table->table_next_id)) { RTE_LOG(ERR, PIPELINE, "%s: Tree-like topologies not allowed\n", __func__); return -EINVAL; } /* Set the lookup miss actions */ if ((default_entry->action == RTE_PIPELINE_ACTION_TABLE) && (table->table_next_id_valid == 0)) { table->table_next_id = default_entry->table_id; table->table_next_id_valid = 1; } memcpy(table->default_entry, default_entry, table->entry_size); *default_entry_ptr = table->default_entry; return 0; } int rte_pipeline_table_default_entry_delete(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_entry *entry) { struct rte_table *table; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n", __func__); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: table_id %d out of range\n", __func__, table_id); return -EINVAL; } table = &p->tables[table_id]; /* Save the current contents of the default entry */ if (entry) memcpy(entry, table->default_entry, table->entry_size); /* Clear the lookup miss actions */ memset(table->default_entry, 0, table->entry_size); table->default_entry->action = RTE_PIPELINE_ACTION_DROP; return 0; } int rte_pipeline_table_entry_add(struct rte_pipeline *p, uint32_t table_id, void *key, struct rte_pipeline_table_entry *entry, int *key_found, struct rte_pipeline_table_entry **entry_ptr) { struct rte_table *table; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, PIPELINE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, PIPELINE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: table_id %d out of range\n", __func__, table_id); return -EINVAL; } table = &p->tables[table_id]; if (table->ops.f_add == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_add function pointer NULL\n", __func__); return -EINVAL; } if ((entry->action == RTE_PIPELINE_ACTION_TABLE) && table->table_next_id_valid && (entry->table_id != table->table_next_id)) { RTE_LOG(ERR, PIPELINE, "%s: Tree-like topologies not allowed\n", __func__); return -EINVAL; } /* Add entry */ if ((entry->action == RTE_PIPELINE_ACTION_TABLE) && (table->table_next_id_valid == 0)) { table->table_next_id = entry->table_id; table->table_next_id_valid = 1; } return (table->ops.f_add)(table->h_table, key, (void *) entry, key_found, (void **) entry_ptr); } int rte_pipeline_table_entry_delete(struct rte_pipeline *p, uint32_t table_id, void *key, int *key_found, struct rte_pipeline_table_entry *entry) { struct rte_table *table; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, PIPELINE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: table_id %d out of range\n", __func__, table_id); return -EINVAL; } table = &p->tables[table_id]; if (table->ops.f_delete == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_delete function pointer NULL\n", __func__); return -EINVAL; } return (table->ops.f_delete)(table->h_table, key, key_found, entry); } /* * Port * */ static int rte_pipeline_port_in_check_params(struct rte_pipeline *p, struct rte_pipeline_port_in_params *params, uint32_t *port_id) { if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (params == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params parameter NULL\n", __func__); return -EINVAL; } if (port_id == NULL) { RTE_LOG(ERR, PIPELINE, "%s: port_id parameter NULL\n", __func__); return -EINVAL; } /* ops */ if (params->ops == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params->ops parameter NULL\n", __func__); return -EINVAL; } if (params->ops->f_create == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_create function pointer NULL\n", __func__); return -EINVAL; } if (params->ops->f_rx == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_rx function pointer NULL\n", __func__); return -EINVAL; } /* burst_size */ if ((params->burst_size == 0) || (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)) { RTE_LOG(ERR, PIPELINE, "%s: invalid value for burst_size\n", __func__); return -EINVAL; } /* Do we have room for one more port? */ if (p->num_ports_in == RTE_PIPELINE_PORT_IN_MAX) { RTE_LOG(ERR, PIPELINE, "%s: invalid value for num_ports_in\n", __func__); return -EINVAL; } return 0; } static int rte_pipeline_port_out_check_params(struct rte_pipeline *p, struct rte_pipeline_port_out_params *params, uint32_t *port_id) { rte_pipeline_port_out_action_handler f_ah; rte_pipeline_port_out_action_handler_bulk f_ah_bulk; if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (params == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params parameter NULL\n", __func__); return -EINVAL; } if (port_id == NULL) { RTE_LOG(ERR, PIPELINE, "%s: port_id parameter NULL\n", __func__); return -EINVAL; } /* ops */ if (params->ops == NULL) { RTE_LOG(ERR, PIPELINE, "%s: params->ops parameter NULL\n", __func__); return -EINVAL; } if (params->ops->f_create == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_create function pointer NULL\n", __func__); return -EINVAL; } if (params->ops->f_tx == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_tx function pointer NULL\n", __func__); return -EINVAL; } if (params->ops->f_tx_bulk == NULL) { RTE_LOG(ERR, PIPELINE, "%s: f_tx_bulk function pointer NULL\n", __func__); return -EINVAL; } f_ah = params->f_action; f_ah_bulk = params->f_action_bulk; if (((f_ah != NULL) && (f_ah_bulk == NULL)) || ((f_ah == NULL) && (f_ah_bulk != NULL))) { RTE_LOG(ERR, PIPELINE, "%s: Action handlers have to be either" "both enabled or both disabled\n", __func__); return -EINVAL; } /* Do we have room for one more port? */ if (p->num_ports_out == RTE_PIPELINE_PORT_OUT_MAX) { RTE_LOG(ERR, PIPELINE, "%s: invalid value for num_ports_out\n", __func__); return -EINVAL; } return 0; } int rte_pipeline_port_in_create(struct rte_pipeline *p, struct rte_pipeline_port_in_params *params, uint32_t *port_id) { struct rte_port_in *port; void *h_port; uint32_t id; int status; /* Check input arguments */ status = rte_pipeline_port_in_check_params(p, params, port_id); if (status != 0) return status; id = p->num_ports_in; port = &p->ports_in[id]; /* Create the port */ h_port = params->ops->f_create(params->arg_create, p->socket_id); if (h_port == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Port creation failed\n", __func__); return -EINVAL; } /* Commit current table to the pipeline */ p->num_ports_in++; *port_id = id; /* Save input parameters */ memcpy(&port->ops, params->ops, sizeof(struct rte_port_in_ops)); port->f_action = params->f_action; port->arg_ah = params->arg_ah; port->burst_size = params->burst_size; /* Initialize port internal data structure */ port->table_id = RTE_TABLE_INVALID; port->h_port = h_port; port->next = NULL; return 0; } void rte_pipeline_port_in_free(struct rte_port_in *port) { if (port->ops.f_free != NULL) port->ops.f_free(port->h_port); } int rte_pipeline_port_out_create(struct rte_pipeline *p, struct rte_pipeline_port_out_params *params, uint32_t *port_id) { struct rte_port_out *port; void *h_port; uint32_t id; int status; /* Check input arguments */ status = rte_pipeline_port_out_check_params(p, params, port_id); if (status != 0) return status; id = p->num_ports_out; port = &p->ports_out[id]; /* Create the port */ h_port = params->ops->f_create(params->arg_create, p->socket_id); if (h_port == NULL) { RTE_LOG(ERR, PIPELINE, "%s: Port creation failed\n", __func__); return -EINVAL; } /* Commit current table to the pipeline */ p->num_ports_out++; *port_id = id; /* Save input parameters */ memcpy(&port->ops, params->ops, sizeof(struct rte_port_out_ops)); port->f_action = params->f_action; port->f_action_bulk = params->f_action_bulk; port->arg_ah = params->arg_ah; /* Initialize port internal data structure */ port->h_port = h_port; return 0; } void rte_pipeline_port_out_free(struct rte_port_out *port) { if (port->ops.f_free != NULL) port->ops.f_free(port->h_port); } int rte_pipeline_port_in_connect_to_table(struct rte_pipeline *p, uint32_t port_id, uint32_t table_id) { struct rte_port_in *port; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (port_id >= p->num_ports_in) { RTE_LOG(ERR, PIPELINE, "%s: port IN ID %u is out of range\n", __func__, port_id); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: Table ID %u is out of range\n", __func__, table_id); return -EINVAL; } port = &p->ports_in[port_id]; port->table_id = table_id; return 0; } int rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id) { struct rte_port_in *port, *port_prev, *port_next; struct rte_port_in *port_first, *port_last; uint64_t port_mask; uint32_t port_prev_id, port_next_id, port_first_id, port_last_id; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (port_id >= p->num_ports_in) { RTE_LOG(ERR, PIPELINE, "%s: port IN ID %u is out of range\n", __func__, port_id); return -EINVAL; } /* Return if current input port is already enabled */ port_mask = 1LLU << port_id; if (p->enabled_port_in_mask & port_mask) return 0; p->enabled_port_in_mask |= port_mask; /* Add current input port to the pipeline chain of enabled ports */ port_prev_id = rte_mask_get_prev(p->enabled_port_in_mask, port_id); port_next_id = rte_mask_get_next(p->enabled_port_in_mask, port_id); port_prev = &p->ports_in[port_prev_id]; port_next = &p->ports_in[port_next_id]; port = &p->ports_in[port_id]; port_prev->next = port; port->next = port_next; /* Update the first and last input ports in the chain */ port_first_id = __builtin_ctzll(p->enabled_port_in_mask); port_last_id = 63 - __builtin_clzll(p->enabled_port_in_mask); port_first = &p->ports_in[port_first_id]; port_last = &p->ports_in[port_last_id]; p->port_in_first = port_first; port_last->next = NULL; return 0; } int rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id) { struct rte_port_in *port_prev, *port_next, *port_first, *port_last; uint64_t port_mask; uint32_t port_prev_id, port_next_id, port_first_id, port_last_id; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (port_id >= p->num_ports_in) { RTE_LOG(ERR, PIPELINE, "%s: port IN ID %u is out of range\n", __func__, port_id); return -EINVAL; } /* Return if current input port is already disabled */ port_mask = 1LLU << port_id; if ((p->enabled_port_in_mask & port_mask) == 0) return 0; /* Return if no other enabled ports */ if (__builtin_popcountll(p->enabled_port_in_mask) == 1) { p->enabled_port_in_mask &= ~port_mask; p->port_in_first = NULL; return 0; } /* Add current input port to the pipeline chain of enabled ports */ port_prev_id = rte_mask_get_prev(p->enabled_port_in_mask, port_id); port_next_id = rte_mask_get_next(p->enabled_port_in_mask, port_id); port_prev = &p->ports_in[port_prev_id]; port_next = &p->ports_in[port_next_id]; port_prev->next = port_next; p->enabled_port_in_mask &= ~port_mask; /* Update the first and last input ports in the chain */ port_first_id = __builtin_ctzll(p->enabled_port_in_mask); port_last_id = 63 - __builtin_clzll(p->enabled_port_in_mask); port_first = &p->ports_in[port_first_id]; port_last = &p->ports_in[port_last_id]; p->port_in_first = port_first; port_last->next = NULL; return 0; } /* * Pipeline run-time * */ int rte_pipeline_check(struct rte_pipeline *p) { uint32_t port_in_id; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } /* Check that pipeline has at least one input port, one table and one output port */ if (p->num_ports_in == 0) { RTE_LOG(ERR, PIPELINE, "%s: must have at least 1 input port\n", __func__); return -EINVAL; } if (p->num_tables == 0) { RTE_LOG(ERR, PIPELINE, "%s: must have at least 1 table\n", __func__); return -EINVAL; } if (p->num_ports_out == 0) { RTE_LOG(ERR, PIPELINE, "%s: must have at least 1 output port\n", __func__); return -EINVAL; } /* Check that all input ports are connected */ for (port_in_id = 0; port_in_id < p->num_ports_in; port_in_id++) { struct rte_port_in *port_in = &p->ports_in[port_in_id]; if (port_in->table_id == RTE_TABLE_INVALID) { RTE_LOG(ERR, PIPELINE, "%s: Port IN ID %u is not connected\n", __func__, port_in_id); return -EINVAL; } } return 0; } static inline void rte_pipeline_compute_masks(struct rte_pipeline *p, uint64_t pkts_mask) { p->action_mask1[RTE_PIPELINE_ACTION_DROP] = 0; p->action_mask1[RTE_PIPELINE_ACTION_PORT] = 0; p->action_mask1[RTE_PIPELINE_ACTION_PORT_META] = 0; p->action_mask1[RTE_PIPELINE_ACTION_TABLE] = 0; if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { uint64_t pkt_mask = 1LLU << i; uint32_t pos = p->entries[i]->action; p->action_mask1[pos] |= pkt_mask; } } else { uint32_t i; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) { uint64_t pkt_mask = 1LLU << i; uint32_t pos; if ((pkt_mask & pkts_mask) == 0) continue; pos = p->entries[i]->action; p->action_mask1[pos] |= pkt_mask; } } } static inline void rte_pipeline_action_handler_port_bulk(struct rte_pipeline *p, uint64_t pkts_mask, uint32_t port_id) { struct rte_port_out *port_out = &p->ports_out[port_id]; /* Output port user actions */ if (port_out->f_action_bulk != NULL) { uint64_t mask = pkts_mask; port_out->f_action_bulk(p->pkts, &pkts_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= pkts_mask ^ mask; RTE_PIPELINE_STATS_ADD_M(port_out->n_pkts_dropped_by_ah, pkts_mask ^ mask); } /* Output port TX */ if (pkts_mask != 0) port_out->ops.f_tx_bulk(port_out->h_port, p->pkts, pkts_mask); } static inline void rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask) { if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = p->pkts[i]; uint32_t port_out_id = p->entries[i]->port_id; struct rte_port_out *port_out = &p->ports_out[port_out_id]; /* Output port user actions */ if (port_out->f_action == NULL) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); else { uint64_t pkt_mask = 1LLU; port_out->f_action(pkt, &pkt_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, pkt_mask ^ 1LLU); /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, pkt); } } } else { uint32_t i; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) { uint64_t pkt_mask = 1LLU << i; struct rte_mbuf *pkt; struct rte_port_out *port_out; uint32_t port_out_id; if ((pkt_mask & pkts_mask) == 0) continue; pkt = p->pkts[i]; port_out_id = p->entries[i]->port_id; port_out = &p->ports_out[port_out_id]; /* Output port user actions */ if (port_out->f_action == NULL) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); else { pkt_mask = 1LLU; port_out->f_action(pkt, &pkt_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, pkt_mask ^ 1LLU); /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, pkt); } } } } static inline void rte_pipeline_action_handler_port_meta(struct rte_pipeline *p, uint64_t pkts_mask) { if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = p->pkts[i]; uint32_t port_out_id = RTE_MBUF_METADATA_UINT32(pkt, p->offset_port_id); struct rte_port_out *port_out = &p->ports_out[ port_out_id]; /* Output port user actions */ if (port_out->f_action == NULL) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); else { uint64_t pkt_mask = 1LLU; port_out->f_action(pkt, &pkt_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, pkt_mask ^ 1ULL); /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, pkt); } } } else { uint32_t i; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) { uint64_t pkt_mask = 1LLU << i; struct rte_mbuf *pkt; struct rte_port_out *port_out; uint32_t port_out_id; if ((pkt_mask & pkts_mask) == 0) continue; pkt = p->pkts[i]; port_out_id = RTE_MBUF_METADATA_UINT32(pkt, p->offset_port_id); port_out = &p->ports_out[port_out_id]; /* Output port user actions */ if (port_out->f_action == NULL) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); else { pkt_mask = 1LLU; port_out->f_action(pkt, &pkt_mask, port_out->arg_ah); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= (pkt_mask ^ 1LLU) << i; RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, pkt_mask ^ 1ULL); /* Output port TX */ if (pkt_mask != 0) port_out->ops.f_tx(port_out->h_port, pkt); } } } } static inline void rte_pipeline_action_handler_drop(struct rte_pipeline *p, uint64_t pkts_mask) { if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) rte_pktmbuf_free(p->pkts[i]); } else { uint32_t i; for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) { uint64_t pkt_mask = 1LLU << i; if ((pkt_mask & pkts_mask) == 0) continue; rte_pktmbuf_free(p->pkts[i]); } } } int rte_pipeline_run(struct rte_pipeline *p) { struct rte_port_in *port_in; for (port_in = p->port_in_first; port_in != NULL; port_in = port_in->next) { uint64_t pkts_mask; uint32_t n_pkts, table_id; /* Input port RX */ n_pkts = port_in->ops.f_rx(port_in->h_port, p->pkts, port_in->burst_size); if (n_pkts == 0) continue; pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); p->action_mask0[RTE_PIPELINE_ACTION_DROP] = 0; p->action_mask0[RTE_PIPELINE_ACTION_PORT] = 0; p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] = 0; p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0; /* Input port user actions */ if (port_in->f_action != NULL) { uint64_t mask = pkts_mask; port_in->f_action(p->pkts, n_pkts, &pkts_mask, port_in->arg_ah); mask ^= pkts_mask; p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; RTE_PIPELINE_STATS_ADD_M(port_in->n_pkts_dropped_by_ah, mask); } /* Table */ for (table_id = port_in->table_id; pkts_mask != 0; ) { struct rte_table *table; uint64_t lookup_hit_mask, lookup_miss_mask; /* Lookup */ table = &p->tables[table_id]; table->ops.f_lookup(table->h_table, p->pkts, pkts_mask, &lookup_hit_mask, (void **) p->entries); lookup_miss_mask = pkts_mask & (~lookup_hit_mask); /* Lookup miss */ if (lookup_miss_mask != 0) { struct rte_pipeline_table_entry *default_entry = table->default_entry; /* Table user actions */ if (table->f_action_miss != NULL) { uint64_t mask = lookup_miss_mask; table->f_action_miss(p->pkts, &lookup_miss_mask, default_entry, table->arg_ah); mask ^= lookup_miss_mask; p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; RTE_PIPELINE_STATS_ADD_M( table->n_pkts_dropped_by_lkp_miss_ah, mask); } /* Table reserved actions */ if ((default_entry->action == RTE_PIPELINE_ACTION_PORT) && (lookup_miss_mask != 0)) rte_pipeline_action_handler_port_bulk(p, lookup_miss_mask, default_entry->port_id); else { uint32_t pos = default_entry->action; p->action_mask0[pos] = lookup_miss_mask; if (pos == RTE_PIPELINE_ACTION_DROP) { RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_miss, lookup_miss_mask); } } } /* Lookup hit */ if (lookup_hit_mask != 0) { /* Table user actions */ if (table->f_action_hit != NULL) { uint64_t mask = lookup_hit_mask; table->f_action_hit(p->pkts, &lookup_hit_mask, p->entries, table->arg_ah); mask ^= lookup_hit_mask; p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask; RTE_PIPELINE_STATS_ADD_M( table->n_pkts_dropped_by_lkp_hit_ah, mask); } /* Table reserved actions */ rte_pipeline_compute_masks(p, lookup_hit_mask); p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= p->action_mask1[ RTE_PIPELINE_ACTION_DROP]; p->action_mask0[RTE_PIPELINE_ACTION_PORT] |= p->action_mask1[ RTE_PIPELINE_ACTION_PORT]; p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] |= p->action_mask1[ RTE_PIPELINE_ACTION_PORT_META]; p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |= p->action_mask1[ RTE_PIPELINE_ACTION_TABLE]; RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_hit, p->action_mask1[RTE_PIPELINE_ACTION_DROP]); } /* Prepare for next iteration */ pkts_mask = p->action_mask0[RTE_PIPELINE_ACTION_TABLE]; table_id = table->table_next_id; p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0; } /* Table reserved action PORT */ rte_pipeline_action_handler_port(p, p->action_mask0[RTE_PIPELINE_ACTION_PORT]); /* Table reserved action PORT META */ rte_pipeline_action_handler_port_meta(p, p->action_mask0[RTE_PIPELINE_ACTION_PORT_META]); /* Table reserved action DROP */ rte_pipeline_action_handler_drop(p, p->action_mask0[RTE_PIPELINE_ACTION_DROP]); } return 0; } int rte_pipeline_flush(struct rte_pipeline *p) { uint32_t port_id; /* Check input arguments */ if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } for (port_id = 0; port_id < p->num_ports_out; port_id++) { struct rte_port_out *port = &p->ports_out[port_id]; if (port->ops.f_flush != NULL) port->ops.f_flush(port->h_port); } return 0; } int rte_pipeline_port_out_packet_insert(struct rte_pipeline *p, uint32_t port_id, struct rte_mbuf *pkt) { struct rte_port_out *port_out = &p->ports_out[port_id]; /* Output port user actions */ if (port_out->f_action == NULL) port_out->ops.f_tx(port_out->h_port, pkt); /* Output port TX */ else { uint64_t pkt_mask = 1LLU; port_out->f_action(pkt, &pkt_mask, port_out->arg_ah); if (pkt_mask != 0) /* Output port TX */ port_out->ops.f_tx(port_out->h_port, pkt); else { rte_pktmbuf_free(pkt); RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, 1); } } return 0; } int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id, struct rte_pipeline_port_in_stats *stats, int clear) { struct rte_port_in *port; int retval; if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (port_id >= p->num_ports_in) { RTE_LOG(ERR, PIPELINE, "%s: port IN ID %u is out of range\n", __func__, port_id); return -EINVAL; } port = &p->ports_in[port_id]; if (port->ops.f_stats != NULL) { retval = port->ops.f_stats(port->h_port, &stats->stats, clear); if (retval) return retval; } else if (stats != NULL) memset(&stats->stats, 0, sizeof(stats->stats)); if (stats != NULL) stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; if (clear != 0) port->n_pkts_dropped_by_ah = 0; return 0; } int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id, struct rte_pipeline_port_out_stats *stats, int clear) { struct rte_port_out *port; int retval; if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (port_id >= p->num_ports_out) { RTE_LOG(ERR, PIPELINE, "%s: port OUT ID %u is out of range\n", __func__, port_id); return -EINVAL; } port = &p->ports_out[port_id]; if (port->ops.f_stats != NULL) { retval = port->ops.f_stats(port->h_port, &stats->stats, clear); if (retval != 0) return retval; } else if (stats != NULL) memset(&stats->stats, 0, sizeof(stats->stats)); if (stats != NULL) stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah; if (clear != 0) port->n_pkts_dropped_by_ah = 0; return 0; } int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_stats *stats, int clear) { struct rte_table *table; int retval; if (p == NULL) { RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n", __func__); return -EINVAL; } if (table_id >= p->num_tables) { RTE_LOG(ERR, PIPELINE, "%s: table %u is out of range\n", __func__, table_id); return -EINVAL; } table = &p->tables[table_id]; if (table->ops.f_stats != NULL) { retval = table->ops.f_stats(table->h_table, &stats->stats, clear); if (retval != 0) return retval; } else if (stats != NULL) memset(&stats->stats, 0, sizeof(stats->stats)); if (stats != NULL) { stats->n_pkts_dropped_by_lkp_hit_ah = table->n_pkts_dropped_by_lkp_hit_ah; stats->n_pkts_dropped_by_lkp_miss_ah = table->n_pkts_dropped_by_lkp_miss_ah; stats->n_pkts_dropped_lkp_hit = table->n_pkts_dropped_lkp_hit; stats->n_pkts_dropped_lkp_miss = table->n_pkts_dropped_lkp_miss; } if (clear != 0) { table->n_pkts_dropped_by_lkp_hit_ah = 0; table->n_pkts_dropped_by_lkp_miss_ah = 0; table->n_pkts_dropped_lkp_hit = 0; table->n_pkts_dropped_lkp_miss = 0; } return 0; } ================================================ FILE: lib/librte_pipeline/rte_pipeline.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PIPELINE_H__ #define __INCLUDE_RTE_PIPELINE_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Pipeline * * This tool is part of the Intel DPDK Packet Framework tool suite and provides * a standard methodology (logically similar to OpenFlow) for rapid development * of complex packet processing pipelines out of ports, tables and actions. * * Basic operation. A pipeline is constructed by connecting its input * ports to its output ports through a chain of lookup tables. As result of * lookup operation into the current table, one of the table entries (or the * default table entry, in case of lookup miss) is identified to provide the * actions to be executed on the current packet and the associated action * meta-data. The behavior of user actions is defined through the configurable * table action handler, while the reserved actions define the next hop for the * current packet (either another table, an output port or packet drop) and are * handled transparently by the framework. * * Initialization and run-time flows. Once all the pipeline elements * (input ports, tables, output ports) have been created, input ports connected * to tables, table action handlers configured, tables populated with the * initial set of entries (actions and action meta-data) and input ports * enabled, the pipeline runs automatically, pushing packets from input ports * to tables and output ports. At each table, the identified user actions are * being executed, resulting in action meta-data (stored in the table entry) * and packet meta-data (stored with the packet descriptor) being updated. The * pipeline tables can have further updates and input ports can be disabled or * enabled later on as required. * * Multi-core scaling. Typically, each CPU core will run its own * pipeline instance. Complex application-level pipelines can be implemented by * interconnecting multiple CPU core-level pipelines in tree-like topologies, * as the same port devices (e.g. SW rings) can serve as output ports for the * pipeline running on CPU core A, as well as input ports for the pipeline * running on CPU core B. This approach enables the application development * using the pipeline (CPU cores connected serially), cluster/run-to-completion * (CPU cores connected in parallel) or mixed (pipeline of CPU core clusters) * programming models. * * Thread safety. It is possible to have multiple pipelines running on * the same CPU core, but it is not allowed (for thread safety reasons) to have * multiple CPU cores running the same pipeline instance. * ***/ #include #include #include struct rte_mbuf; /* * Pipeline * */ /** Opaque data type for pipeline */ struct rte_pipeline; /** Parameters for pipeline creation */ struct rte_pipeline_params { /** Pipeline name */ const char *name; /** CPU socket ID where memory for the pipeline and its elements (ports and tables) should be allocated */ int socket_id; /** Offset within packet meta-data to port_id to be used by action "Send packet to output port read from packet meta-data". Has to be 4-byte aligned. */ uint32_t offset_port_id; }; /** Pipeline port in stats. */ struct rte_pipeline_port_in_stats { /** Port in stats. */ struct rte_port_in_stats stats; /** Number of packets dropped by action handler. */ uint64_t n_pkts_dropped_by_ah; }; /** Pipeline port out stats. */ struct rte_pipeline_port_out_stats { /** Port out stats. */ struct rte_port_out_stats stats; /** Number of packets dropped by action handler. */ uint64_t n_pkts_dropped_by_ah; }; /** Pipeline table stats. */ struct rte_pipeline_table_stats { /** Table stats. */ struct rte_table_stats stats; /** Number of packets dropped by lookup hit action handler. */ uint64_t n_pkts_dropped_by_lkp_hit_ah; /** Number of packets dropped by lookup miss action handler. */ uint64_t n_pkts_dropped_by_lkp_miss_ah; /** Number of packets dropped by pipeline in behalf of this table based on * on action specified in table entry. */ uint64_t n_pkts_dropped_lkp_hit; /** Number of packets dropped by pipeline in behalf of this table based on * on action specified in table entry. */ uint64_t n_pkts_dropped_lkp_miss; }; /** * Pipeline create * * @param params * Parameters for pipeline creation * @return * Handle to pipeline instance on success or NULL otherwise */ struct rte_pipeline *rte_pipeline_create(struct rte_pipeline_params *params); /** * Pipeline free * * @param p * Handle to pipeline instance * @return * 0 on success, error code otherwise */ int rte_pipeline_free(struct rte_pipeline *p); /** * Pipeline consistency check * * @param p * Handle to pipeline instance * @return * 0 on success, error code otherwise */ int rte_pipeline_check(struct rte_pipeline *p); /** * Pipeline run * * @param p * Handle to pipeline instance * @return * 0 on success, error code otherwise */ int rte_pipeline_run(struct rte_pipeline *p); /** * Pipeline flush * * @param p * Handle to pipeline instance * @return * 0 on success, error code otherwise */ int rte_pipeline_flush(struct rte_pipeline *p); /* * Actions * */ /** Reserved actions */ enum rte_pipeline_action { /** Drop the packet */ RTE_PIPELINE_ACTION_DROP = 0, /** Send packet to output port */ RTE_PIPELINE_ACTION_PORT, /** Send packet to output port read from packet meta-data */ RTE_PIPELINE_ACTION_PORT_META, /** Send packet to table */ RTE_PIPELINE_ACTION_TABLE, /** Number of reserved actions */ RTE_PIPELINE_ACTIONS }; /* * Table * */ /** Maximum number of tables allowed for any given pipeline instance. The value of this parameter cannot be changed. */ #define RTE_PIPELINE_TABLE_MAX 64 /** * Head format for the table entry of any pipeline table. For any given * pipeline table, all table entries should have the same size and format. For * any given pipeline table, the table entry has to start with a head of this * structure, which contains the reserved actions and their associated * meta-data, and then optionally continues with user actions and their * associated meta-data. As all the currently defined reserved actions are * mutually exclusive, only one reserved action can be set per table entry. */ struct rte_pipeline_table_entry { /** Reserved action */ enum rte_pipeline_action action; union { /** Output port ID (meta-data for "Send packet to output port" action) */ uint32_t port_id; /** Table ID (meta-data for "Send packet to table" action) */ uint32_t table_id; }; /** Start of table entry area for user defined actions and meta-data */ uint8_t action_data[0]; }; /** * Pipeline table action handler on lookup hit * * The action handler can decide to drop packets by resetting the associated * packet bit in the pkts_mask parameter. In this case, the action handler is * required not to free the packet buffer, which will be freed eventually by * the pipeline. * * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are valid. When * pkts_mask bit n is set, then element n of pkts array is pointing to a * valid packet and element n of entries array is pointing to a valid table * entry associated with the packet, with the association typically done by * the table lookup operation. Otherwise, element n of pkts array and element * n of entries array will not be accessed. * @param entries * Set of table entries specified as array of up to 64 pointers to struct * rte_pipeline_table_entry * @param arg * Opaque parameter registered by the user at the pipeline table creation * time * @return * 0 on success, error code otherwise */ typedef int (*rte_pipeline_table_action_handler_hit)( struct rte_mbuf **pkts, uint64_t *pkts_mask, struct rte_pipeline_table_entry **entries, void *arg); /** * Pipeline table action handler on lookup miss * * The action handler can decide to drop packets by resetting the associated * packet bit in the pkts_mask parameter. In this case, the action handler is * required not to free the packet buffer, which will be freed eventually by * the pipeline. * * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are valid. When * pkts_mask bit n is set, then element n of pkts array is pointing to a * valid packet. Otherwise, element n of pkts array will not be accessed. * @param entry * Single table entry associated with all the valid packets from the input * burst, specified as pointer to struct rte_pipeline_table_entry. * This entry is the pipeline table default entry that is associated by the * table lookup operation with the input packets that have resulted in lookup * miss. * @param arg * Opaque parameter registered by the user at the pipeline table creation * time * @return * 0 on success, error code otherwise */ typedef int (*rte_pipeline_table_action_handler_miss)( struct rte_mbuf **pkts, uint64_t *pkts_mask, struct rte_pipeline_table_entry *entry, void *arg); /** Parameters for pipeline table creation. Action handlers have to be either both enabled or both disabled (they can be disabled by setting them to NULL). */ struct rte_pipeline_table_params { /** Table operations (specific to each table type) */ struct rte_table_ops *ops; /** Opaque param to be passed to the table create operation when invoked */ void *arg_create; /** Callback function to execute the user actions on input packets in case of lookup hit */ rte_pipeline_table_action_handler_hit f_action_hit; /** Callback function to execute the user actions on input packets in case of lookup miss */ rte_pipeline_table_action_handler_miss f_action_miss; /** Opaque parameter to be passed to lookup hit and/or lookup miss action handlers when invoked */ void *arg_ah; /** Memory size to be reserved per table entry for storing the user actions and their meta-data */ uint32_t action_data_size; }; /** * Pipeline table create * * @param p * Handle to pipeline instance * @param params * Parameters for pipeline table creation * @param table_id * Table ID. Valid only within the scope of table IDs of the current * pipeline. Only returned after a successful invocation. * @return * 0 on success, error code otherwise */ int rte_pipeline_table_create(struct rte_pipeline *p, struct rte_pipeline_table_params *params, uint32_t *table_id); /** * Pipeline table default entry add * * The contents of the table default entry is updated with the provided actions * and meta-data. When the default entry is not configured (by using this * function), the built-in default entry has the action "Drop" and meta-data * set to all-zeros. * * @param p * Handle to pipeline instance * @param table_id * Table ID (returned by previous invocation of pipeline table create) * @param default_entry * New contents for the table default entry * @param default_entry_ptr * On successful invocation, pointer to the default table entry which can be * used for further read-write accesses to this table entry. This pointer * is valid until the default entry is deleted or re-added. * @return * 0 on success, error code otherwise */ int rte_pipeline_table_default_entry_add(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_entry *default_entry, struct rte_pipeline_table_entry **default_entry_ptr); /** * Pipeline table default entry delete * * The new contents of the table default entry is set to reserved action "Drop * the packet" with meta-data cleared (i.e. set to all-zeros). * * @param p * Handle to pipeline instance * @param table_id * Table ID (returned by previous invocation of pipeline table create) * @param entry * On successful invocation, when entry points to a valid buffer, the * previous contents of the table default entry (as it was just before the * delete operation) is copied to this buffer * @return * 0 on success, error code otherwise */ int rte_pipeline_table_default_entry_delete(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_entry *entry); /** * Pipeline table entry add * * @param p * Handle to pipeline instance * @param table_id * Table ID (returned by previous invocation of pipeline table create) * @param key * Table entry key * @param entry * New contents for the table entry identified by key * @param key_found * On successful invocation, set to TRUE (value different than 0) if key was * already present in the table before the add operation and to FALSE (value * 0) if not * @param entry_ptr * On successful invocation, pointer to the table entry associated with key. * This can be used for further read-write accesses to this table entry and * is valid until the key is deleted from the table or re-added (usually for * associating different actions and/or action meta-data to the current key) * @return * 0 on success, error code otherwise */ int rte_pipeline_table_entry_add(struct rte_pipeline *p, uint32_t table_id, void *key, struct rte_pipeline_table_entry *entry, int *key_found, struct rte_pipeline_table_entry **entry_ptr); /** * Pipeline table entry delete * * @param p * Handle to pipeline instance * @param table_id * Table ID (returned by previous invocation of pipeline table create) * @param key * Table entry key * @param key_found * On successful invocation, set to TRUE (value different than 0) if key was * found in the table before the delete operation and to FALSE (value 0) if * not * @param entry * On successful invocation, when key is found in the table and entry points * to a valid buffer, the table entry contents (as it was before the delete * was performed) is copied to this buffer * @return * 0 on success, error code otherwise */ int rte_pipeline_table_entry_delete(struct rte_pipeline *p, uint32_t table_id, void *key, int *key_found, struct rte_pipeline_table_entry *entry); /** * Read pipeline table stats. * * This function reads table statistics identified by *table_id* of given * pipeline *p*. * * @param p * Handle to pipeline instance. * @param table_id * Port ID what stats will be returned. * @param stats * Statistics buffer. * @param clear * If not 0 clear stats after reading. * @return * 0 on success, error code otherwise */ int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id, struct rte_pipeline_table_stats *stats, int clear); /* * Port IN * */ /** Maximum number of input ports allowed for any given pipeline instance. The value of this parameter cannot be changed. */ #define RTE_PIPELINE_PORT_IN_MAX 64 /** * Pipeline input port action handler * * The action handler can decide to drop packets by resetting the associated * packet bit in the pkts_mask parameter. In this case, the action handler is * required not to free the packet buffer, which will be freed eventually by * the pipeline. * * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param n * Number of packets in the input burst. This parameter specifies that * elements 0 to (n-1) of pkts array are valid. * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are still valid * after the action handler is executed. When pkts_mask bit n is set, then * element n of pkts array is pointing to a valid packet. * @param arg * Opaque parameter registered by the user at the pipeline table creation * time * @return * 0 on success, error code otherwise */ typedef int (*rte_pipeline_port_in_action_handler)( struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg); /** Parameters for pipeline input port creation */ struct rte_pipeline_port_in_params { /** Input port operations (specific to each table type) */ struct rte_port_in_ops *ops; /** Opaque parameter to be passed to create operation when invoked */ void *arg_create; /** Callback function to execute the user actions on input packets. Disabled if set to NULL. */ rte_pipeline_port_in_action_handler f_action; /** Opaque parameter to be passed to the action handler when invoked */ void *arg_ah; /** Recommended burst size for the RX operation(in number of pkts) */ uint32_t burst_size; }; /** * Pipeline input port create * * @param p * Handle to pipeline instance * @param params * Parameters for pipeline input port creation * @param port_id * Input port ID. Valid only within the scope of input port IDs of the * current pipeline. Only returned after a successful invocation. * @return * 0 on success, error code otherwise */ int rte_pipeline_port_in_create(struct rte_pipeline *p, struct rte_pipeline_port_in_params *params, uint32_t *port_id); /** * Pipeline input port connect to table * * @param p * Handle to pipeline instance * @param port_id * Port ID (returned by previous invocation of pipeline input port create) * @param table_id * Table ID (returned by previous invocation of pipeline table create) * @return * 0 on success, error code otherwise */ int rte_pipeline_port_in_connect_to_table(struct rte_pipeline *p, uint32_t port_id, uint32_t table_id); /** * Pipeline input port enable * * @param p * Handle to pipeline instance * @param port_id * Port ID (returned by previous invocation of pipeline input port create) * @return * 0 on success, error code otherwise */ int rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id); /** * Pipeline input port disable * * @param p * Handle to pipeline instance * @param port_id * Port ID (returned by previous invocation of pipeline input port create) * @return * 0 on success, error code otherwise */ int rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id); /** * Read pipeline port in stats. * * This function reads port in statistics identified by *port_id* of given * pipeline *p*. * * @param p * Handle to pipeline instance. * @param port_id * Port ID what stats will be returned. * @param stats * Statistics buffer. * @param clear * If not 0 clear stats after reading. * @return * 0 on success, error code otherwise */ int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id, struct rte_pipeline_port_in_stats *stats, int clear); /* * Port OUT * */ /** Maximum number of output ports allowed for any given pipeline instance. The value of this parameter cannot be changed. */ #define RTE_PIPELINE_PORT_OUT_MAX 64 /** * Pipeline output port action handler for single packet * * The action handler can decide to drop packets by resetting the pkt_mask * argument. In this case, the action handler is required not to free the * packet buffer, which will be freed eventually by the pipeline. * * @param pkt * Input packet * @param pkt_mask * Output argument set to 0 when the action handler decides to drop the input * packet and to 1LLU otherwise * @param arg * Opaque parameter registered by the user at the pipeline table creation * time * @return * 0 on success, error code otherwise */ typedef int (*rte_pipeline_port_out_action_handler)( struct rte_mbuf *pkt, uint64_t *pkt_mask, void *arg); /** * Pipeline output port action handler bulk * * The action handler can decide to drop packets by resetting the associated * packet bit in the pkts_mask parameter. In this case, the action handler is * required not to free the packet buffer, which will be freed eventually by * the pipeline. * * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are valid. When * pkts_mask bit n is set, then element n of pkts array is pointing to a * valid packet. Otherwise, element n of pkts array will not be accessed. * @param arg * Opaque parameter registered by the user at the pipeline table creation * time * @return * 0 on success, error code otherwise */ typedef int (*rte_pipeline_port_out_action_handler_bulk)( struct rte_mbuf **pkts, uint64_t *pkts_mask, void *arg); /** Parameters for pipeline output port creation. The action handlers have to be either both enabled or both disabled (by setting them to NULL). When enabled, the pipeline selects between them at different moments, based on the number of packets that have to be sent to the same output port. */ struct rte_pipeline_port_out_params { /** Output port operations (specific to each table type) */ struct rte_port_out_ops *ops; /** Opaque parameter to be passed to create operation when invoked */ void *arg_create; /** Callback function executing the user actions on single input packet */ rte_pipeline_port_out_action_handler f_action; /** Callback function executing the user actions on bust of input packets */ rte_pipeline_port_out_action_handler_bulk f_action_bulk; /** Opaque parameter to be passed to the action handler when invoked */ void *arg_ah; }; /** * Pipeline output port create * * @param p * Handle to pipeline instance * @param params * Parameters for pipeline output port creation * @param port_id * Output port ID. Valid only within the scope of output port IDs of the * current pipeline. Only returned after a successful invocation. * @return * 0 on success, error code otherwise */ int rte_pipeline_port_out_create(struct rte_pipeline *p, struct rte_pipeline_port_out_params *params, uint32_t *port_id); /** * Pipeline output port packet insert * * This function is called by the table action handler whenever it generates a * new packet to be sent out though one of the pipeline output ports. This * packet is not part of the burst of input packets read from any of the * pipeline input ports, so it is not an element of the pkts array input * parameter of the table action handler. This packet can be dropped by the * output port action handler. * * @param p * Handle to pipeline instance * @param port_id * Output port ID (returned by previous invocation of pipeline output port * create) to send the packet specified by pkt * @param pkt * New packet generated by the table action handler * @return * 0 on success, error code otherwise */ int rte_pipeline_port_out_packet_insert(struct rte_pipeline *p, uint32_t port_id, struct rte_mbuf *pkt); /** * Read pipeline port out stats. * * This function reads port out statistics identified by *port_id* of given * pipeline *p*. * * @param p * Handle to pipeline instance. * @param port_id * Port ID what stats will be returned. * @param stats * Statistics buffer. * @param clear * If not 0 clear stats after reading. * @return * 0 on success, error code otherwise */ int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id, struct rte_pipeline_port_out_stats *stats, int clear); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_port.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_port_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_ring.c ifeq ($(CONFIG_RTE_LIBRTE_IP_FRAG),y) SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_frag.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_ras.c endif SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_sched.c SRCS-$(CONFIG_RTE_LIBRTE_PORT) += rte_port_source_sink.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_ethdev.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_ring.h ifeq ($(CONFIG_RTE_LIBRTE_IP_FRAG),y) SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_frag.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_ras.h endif SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_sched.h SYMLINK-$(CONFIG_RTE_LIBRTE_PORT)-include += rte_port_source_sink.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) := lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_mempool DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_PORT) += lib/librte_ip_frag include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_port/rte_port.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_H__ #define __INCLUDE_RTE_PORT_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port * * This tool is part of the Intel DPDK Packet Framework tool suite and provides * a standard interface to implement different types of packet ports. * ***/ #include #include /**@{ * Macros to allow accessing metadata stored in the mbuf headroom * just beyond the end of the mbuf data structure returned by a port */ #define RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset) \ (&((uint8_t *) &(mbuf)[1])[offset]) #define RTE_MBUF_METADATA_UINT16_PTR(mbuf, offset) \ ((uint16_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT32_PTR(mbuf, offset) \ ((uint32_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT64_PTR(mbuf, offset) \ ((uint64_t *) RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT8(mbuf, offset) \ (*RTE_MBUF_METADATA_UINT8_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT16(mbuf, offset) \ (*RTE_MBUF_METADATA_UINT16_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT32(mbuf, offset) \ (*RTE_MBUF_METADATA_UINT32_PTR(mbuf, offset)) #define RTE_MBUF_METADATA_UINT64(mbuf, offset) \ (*RTE_MBUF_METADATA_UINT64_PTR(mbuf, offset)) /**@}*/ /* * Port IN * */ /** Maximum number of packets read from any input port in a single burst. Cannot be changed. */ #define RTE_PORT_IN_BURST_SIZE_MAX 64 /** Input port statistics */ struct rte_port_in_stats { uint64_t n_pkts_in; uint64_t n_pkts_drop; }; /** * Input port create * * @param params * Parameters for input port creation * @param socket_id * CPU socket ID (e.g. for memory allocation purpose) * @return * Handle to input port instance */ typedef void* (*rte_port_in_op_create)(void *params, int socket_id); /** * Input port free * * @param port * Handle to input port instance * @return * 0 on success, error code otherwise */ typedef int (*rte_port_in_op_free)(void *port); /** * Input port packet burst RX * * @param port * Handle to input port instance * @param pkts * Burst of input packets * @param n_pkts * Number of packets in the input burst * @return * 0 on success, error code otherwise */ typedef int (*rte_port_in_op_rx)( void *port, struct rte_mbuf **pkts, uint32_t n_pkts); /** * Input port stats get * * @param port * Handle to output port instance * @param stats * Handle to port_in stats struct to copy data * @param clear * Flag indicating that stats should be cleared after read * * @return * Error code or 0 on success. */ typedef int (*rte_port_in_op_stats_read)( void *port, struct rte_port_in_stats *stats, int clear); /** Input port interface defining the input port operation */ struct rte_port_in_ops { rte_port_in_op_create f_create; /**< Create */ rte_port_in_op_free f_free; /**< Free */ rte_port_in_op_rx f_rx; /**< Packet RX (packet burst) */ rte_port_in_op_stats_read f_stats; /**< Stats */ }; /* * Port OUT * */ /** Output port statistics */ struct rte_port_out_stats { uint64_t n_pkts_in; uint64_t n_pkts_drop; }; /** * Output port create * * @param params * Parameters for output port creation * @param socket_id * CPU socket ID (e.g. for memory allocation purpose) * @return * Handle to output port instance */ typedef void* (*rte_port_out_op_create)(void *params, int socket_id); /** * Output port free * * @param port * Handle to output port instance * @return * 0 on success, error code otherwise */ typedef int (*rte_port_out_op_free)(void *port); /** * Output port single packet TX * * @param port * Handle to output port instance * @param pkt * Input packet * @return * 0 on success, error code otherwise */ typedef int (*rte_port_out_op_tx)( void *port, struct rte_mbuf *pkt); /** * Output port packet burst TX * * @param port * Handle to output port instance * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are valid. When * pkts_mask bit n is set, then element n of pkts array is pointing to a * valid packet. Otherwise, element n of pkts array will not be accessed. * @return * 0 on success, error code otherwise */ typedef int (*rte_port_out_op_tx_bulk)( void *port, struct rte_mbuf **pkt, uint64_t pkts_mask); /** * Output port flush * * @param port * Handle to output port instance * @return * 0 on success, error code otherwise */ typedef int (*rte_port_out_op_flush)(void *port); /** * Output port stats read * * @param port * Handle to output port instance * @param stats * Handle to port_out stats struct to copy data * @param clear * Flag indicating that stats should be cleared after read * * @return * Error code or 0 on success. */ typedef int (*rte_port_out_op_stats_read)( void *port, struct rte_port_out_stats *stats, int clear); /** Output port interface defining the output port operation */ struct rte_port_out_ops { rte_port_out_op_create f_create; /**< Create */ rte_port_out_op_free f_free; /**< Free */ rte_port_out_op_tx f_tx; /**< Packet TX (single packet) */ rte_port_out_op_tx_bulk f_tx_bulk; /**< Packet TX (packet burst) */ rte_port_out_op_flush f_flush; /**< Flush */ rte_port_out_op_stats_read f_stats; /**< Stats */ }; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_ethdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_port_ethdev.h" /* * Port ETHDEV Reader */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_ETHDEV_READER_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_ETHDEV_READER_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ethdev_reader { struct rte_port_in_stats stats; uint16_t queue_id; uint8_t port_id; }; static void * rte_port_ethdev_reader_create(void *params, int socket_id) { struct rte_port_ethdev_reader_params *conf = (struct rte_port_ethdev_reader_params *) params; struct rte_port_ethdev_reader *port; /* Check input parameters */ if (conf == NULL) { RTE_LOG(ERR, PORT, "%s: params is NULL\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->port_id = conf->port_id; port->queue_id = conf->queue_id; return port; } static int rte_port_ethdev_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_port_ethdev_reader *p = (struct rte_port_ethdev_reader *) port; uint16_t rx_pkt_cnt; rx_pkt_cnt = rte_eth_rx_burst(p->port_id, p->queue_id, pkts, n_pkts); RTE_PORT_ETHDEV_READER_STATS_PKTS_IN_ADD(p, rx_pkt_cnt); return rx_pkt_cnt; } static int rte_port_ethdev_reader_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); return -EINVAL; } rte_free(port); return 0; } static int rte_port_ethdev_reader_stats_read(void *port, struct rte_port_in_stats *stats, int clear) { struct rte_port_ethdev_reader *p = (struct rte_port_ethdev_reader *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Port ETHDEV Writer */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ethdev_writer { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; uint32_t tx_burst_sz; uint16_t tx_buf_count; uint64_t bsz_mask; uint16_t queue_id; uint8_t port_id; }; static void * rte_port_ethdev_writer_create(void *params, int socket_id) { struct rte_port_ethdev_writer_params *conf = (struct rte_port_ethdev_writer_params *) params; struct rte_port_ethdev_writer *port; /* Check input parameters */ if ((conf == NULL) || (conf->tx_burst_sz == 0) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || (!rte_is_power_of_2(conf->tx_burst_sz))) { RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->port_id = conf->port_id; port->queue_id = conf->queue_id; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); return port; } static inline void send_burst(struct rte_port_ethdev_writer *p) { uint32_t nb_tx; nb_tx = rte_eth_tx_burst(p->port_id, p->queue_id, p->tx_buf, p->tx_buf_count); RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); for ( ; nb_tx < p->tx_buf_count; nb_tx++) rte_pktmbuf_free(p->tx_buf[nb_tx]); p->tx_buf_count = 0; } static int rte_port_ethdev_writer_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_ethdev_writer *p = (struct rte_port_ethdev_writer *) port; p->tx_buf[p->tx_buf_count++] = pkt; RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, 1); if (p->tx_buf_count >= p->tx_burst_sz) send_burst(p); return 0; } static int rte_port_ethdev_writer_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_ethdev_writer *p = (struct rte_port_ethdev_writer *) port; uint32_t bsz_mask = p->bsz_mask; uint32_t tx_buf_count = p->tx_buf_count; uint64_t expr = (pkts_mask & (pkts_mask + 1)) | ((pkts_mask & bsz_mask) ^ bsz_mask); if (expr == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t n_pkts_ok; if (tx_buf_count) send_burst(p); RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, n_pkts); n_pkts_ok = rte_eth_tx_burst(p->port_id, p->queue_id, pkts, n_pkts); RTE_PORT_ETHDEV_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok); for ( ; n_pkts_ok < n_pkts; n_pkts_ok++) { struct rte_mbuf *pkt = pkts[n_pkts_ok]; rte_pktmbuf_free(pkt); } } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; p->tx_buf[tx_buf_count++] = pkt; RTE_PORT_ETHDEV_WRITER_STATS_PKTS_IN_ADD(p, 1); pkts_mask &= ~pkt_mask; } p->tx_buf_count = tx_buf_count; if (tx_buf_count >= p->tx_burst_sz) send_burst(p); } return 0; } static int rte_port_ethdev_writer_flush(void *port) { struct rte_port_ethdev_writer *p = (struct rte_port_ethdev_writer *) port; if (p->tx_buf_count > 0) send_burst(p); return 0; } static int rte_port_ethdev_writer_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); return -EINVAL; } rte_port_ethdev_writer_flush(port); rte_free(port); return 0; } static int rte_port_ethdev_writer_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_ethdev_writer *p = (struct rte_port_ethdev_writer *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Port ETHDEV Writer Nodrop */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ethdev_writer_nodrop { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; uint32_t tx_burst_sz; uint16_t tx_buf_count; uint64_t bsz_mask; uint64_t n_retries; uint16_t queue_id; uint8_t port_id; }; static void * rte_port_ethdev_writer_nodrop_create(void *params, int socket_id) { struct rte_port_ethdev_writer_nodrop_params *conf = (struct rte_port_ethdev_writer_nodrop_params *) params; struct rte_port_ethdev_writer_nodrop *port; /* Check input parameters */ if ((conf == NULL) || (conf->tx_burst_sz == 0) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || (!rte_is_power_of_2(conf->tx_burst_sz))) { RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->port_id = conf->port_id; port->queue_id = conf->queue_id; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); /* * When n_retries is 0 it means that we should wait for every packet to * send no matter how many retries should it take. To limit number of * branches in fast path, we use UINT64_MAX instead of branching. */ port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries; return port; } static inline void send_burst_nodrop(struct rte_port_ethdev_writer_nodrop *p) { uint32_t nb_tx = 0, i; nb_tx = rte_eth_tx_burst(p->port_id, p->queue_id, p->tx_buf, p->tx_buf_count); /* We sent all the packets in a first try */ if (nb_tx >= p->tx_buf_count) return; for (i = 0; i < p->n_retries; i++) { nb_tx += rte_eth_tx_burst(p->port_id, p->queue_id, p->tx_buf + nb_tx, p->tx_buf_count - nb_tx); /* We sent all the packets in more than one try */ if (nb_tx >= p->tx_buf_count) return; } /* We didn't send the packets in maximum allowed attempts */ RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); for ( ; nb_tx < p->tx_buf_count; nb_tx++) rte_pktmbuf_free(p->tx_buf[nb_tx]); p->tx_buf_count = 0; } static int rte_port_ethdev_writer_nodrop_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_ethdev_writer_nodrop *p = (struct rte_port_ethdev_writer_nodrop *) port; p->tx_buf[p->tx_buf_count++] = pkt; RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); if (p->tx_buf_count >= p->tx_burst_sz) send_burst_nodrop(p); return 0; } static int rte_port_ethdev_writer_nodrop_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_ethdev_writer_nodrop *p = (struct rte_port_ethdev_writer_nodrop *) port; uint32_t bsz_mask = p->bsz_mask; uint32_t tx_buf_count = p->tx_buf_count; uint64_t expr = (pkts_mask & (pkts_mask + 1)) | ((pkts_mask & bsz_mask) ^ bsz_mask); if (expr == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t n_pkts_ok; if (tx_buf_count) send_burst_nodrop(p); RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts); n_pkts_ok = rte_eth_tx_burst(p->port_id, p->queue_id, pkts, n_pkts); if (n_pkts_ok >= n_pkts) return 0; /* * If we didnt manage to send all packets in single burst, move * remaining packets to the buffer and call send burst. */ for (; n_pkts_ok < n_pkts; n_pkts_ok++) { struct rte_mbuf *pkt = pkts[n_pkts_ok]; p->tx_buf[p->tx_buf_count++] = pkt; } send_burst_nodrop(p); } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; p->tx_buf[tx_buf_count++] = pkt; RTE_PORT_ETHDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); pkts_mask &= ~pkt_mask; } p->tx_buf_count = tx_buf_count; if (tx_buf_count >= p->tx_burst_sz) send_burst_nodrop(p); } return 0; } static int rte_port_ethdev_writer_nodrop_flush(void *port) { struct rte_port_ethdev_writer_nodrop *p = (struct rte_port_ethdev_writer_nodrop *) port; if (p->tx_buf_count > 0) send_burst_nodrop(p); return 0; } static int rte_port_ethdev_writer_nodrop_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); return -EINVAL; } rte_port_ethdev_writer_nodrop_flush(port); rte_free(port); return 0; } static int rte_port_ethdev_writer_nodrop_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_ethdev_writer_nodrop *p = (struct rte_port_ethdev_writer_nodrop *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Summary of port operations */ struct rte_port_in_ops rte_port_ethdev_reader_ops = { .f_create = rte_port_ethdev_reader_create, .f_free = rte_port_ethdev_reader_free, .f_rx = rte_port_ethdev_reader_rx, .f_stats = rte_port_ethdev_reader_stats_read, }; struct rte_port_out_ops rte_port_ethdev_writer_ops = { .f_create = rte_port_ethdev_writer_create, .f_free = rte_port_ethdev_writer_free, .f_tx = rte_port_ethdev_writer_tx, .f_tx_bulk = rte_port_ethdev_writer_tx_bulk, .f_flush = rte_port_ethdev_writer_flush, .f_stats = rte_port_ethdev_writer_stats_read, }; struct rte_port_out_ops rte_port_ethdev_writer_nodrop_ops = { .f_create = rte_port_ethdev_writer_nodrop_create, .f_free = rte_port_ethdev_writer_nodrop_free, .f_tx = rte_port_ethdev_writer_nodrop_tx, .f_tx_bulk = rte_port_ethdev_writer_nodrop_tx_bulk, .f_flush = rte_port_ethdev_writer_nodrop_flush, .f_stats = rte_port_ethdev_writer_nodrop_stats_read, }; ================================================ FILE: lib/librte_port/rte_port_ethdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_ETHDEV_H__ #define __INCLUDE_RTE_PORT_ETHDEV_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port Ethernet Device * * ethdev_reader: input port built on top of pre-initialized NIC RX queue * ethdev_writer: output port built on top of pre-initialized NIC TX queue * ***/ #include #include "rte_port.h" /** ethdev_reader port parameters */ struct rte_port_ethdev_reader_params { /** NIC RX port ID */ uint8_t port_id; /** NIC RX queue ID */ uint16_t queue_id; }; /** ethdev_reader port operations */ extern struct rte_port_in_ops rte_port_ethdev_reader_ops; /** ethdev_writer port parameters */ struct rte_port_ethdev_writer_params { /** NIC RX port ID */ uint8_t port_id; /** NIC RX queue ID */ uint16_t queue_id; /** Recommended burst size to NIC TX queue. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; }; /** ethdev_writer port operations */ extern struct rte_port_out_ops rte_port_ethdev_writer_ops; /** ethdev_writer_nodrop port parameters */ struct rte_port_ethdev_writer_nodrop_params { /** NIC RX port ID */ uint8_t port_id; /** NIC RX queue ID */ uint16_t queue_id; /** Recommended burst size to NIC TX queue. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; /** Maximum number of retries, 0 for no limit */ uint32_t n_retries; }; /** ethdev_writer_nodrop port operations */ extern struct rte_port_out_ops rte_port_ethdev_writer_nodrop_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_frag.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "rte_port_frag.h" /* Max number of fragments per packet allowed */ #define RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET 0x80 #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(port, val) #endif typedef int32_t (*frag_op)(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect); struct rte_port_ring_reader_frag { struct rte_port_in_stats stats; /* Input parameters */ struct rte_ring *ring; uint32_t mtu; uint32_t metadata_size; struct rte_mempool *pool_direct; struct rte_mempool *pool_indirect; /* Internal buffers */ struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_mbuf *frags[RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET]; uint32_t n_pkts; uint32_t pos_pkts; uint32_t n_frags; uint32_t pos_frags; frag_op f_frag; } __rte_cache_aligned; static void * rte_port_ring_reader_frag_create(void *params, int socket_id, int is_ipv4) { struct rte_port_ring_reader_frag_params *conf = (struct rte_port_ring_reader_frag_params *) params; struct rte_port_ring_reader_frag *port; /* Check input parameters */ if (conf == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter conf is NULL\n", __func__); return NULL; } if (conf->ring == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter ring is NULL\n", __func__); return NULL; } if (conf->mtu == 0) { RTE_LOG(ERR, PORT, "%s: Parameter mtu is invalid\n", __func__); return NULL; } if (conf->pool_direct == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter pool_direct is NULL\n", __func__); return NULL; } if (conf->pool_indirect == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter pool_indirect is NULL\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); return NULL; } /* Initialization */ port->ring = conf->ring; port->mtu = conf->mtu; port->metadata_size = conf->metadata_size; port->pool_direct = conf->pool_direct; port->pool_indirect = conf->pool_indirect; port->n_pkts = 0; port->pos_pkts = 0; port->n_frags = 0; port->pos_frags = 0; port->f_frag = (is_ipv4) ? rte_ipv4_fragment_packet : rte_ipv6_fragment_packet; return port; } static void * rte_port_ring_reader_ipv4_frag_create(void *params, int socket_id) { return rte_port_ring_reader_frag_create(params, socket_id, 1); } static void * rte_port_ring_reader_ipv6_frag_create(void *params, int socket_id) { return rte_port_ring_reader_frag_create(params, socket_id, 0); } static int rte_port_ring_reader_frag_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_port_ring_reader_frag *p = (struct rte_port_ring_reader_frag *) port; uint32_t n_pkts_out; n_pkts_out = 0; /* Get packets from the "frag" buffer */ if (p->n_frags >= n_pkts) { memcpy(pkts, &p->frags[p->pos_frags], n_pkts * sizeof(void *)); p->pos_frags += n_pkts; p->n_frags -= n_pkts; return n_pkts; } memcpy(pkts, &p->frags[p->pos_frags], p->n_frags * sizeof(void *)); n_pkts_out = p->n_frags; p->n_frags = 0; /* Look to "pkts" buffer to get more packets */ for ( ; ; ) { struct rte_mbuf *pkt; uint32_t n_pkts_to_provide, i; int status; /* If "pkts" buffer is empty, read packet burst from ring */ if (p->n_pkts == 0) { p->n_pkts = rte_ring_sc_dequeue_burst(p->ring, (void **) p->pkts, RTE_PORT_IN_BURST_SIZE_MAX); RTE_PORT_RING_READER_FRAG_STATS_PKTS_IN_ADD(p, p->n_pkts); if (p->n_pkts == 0) return n_pkts_out; p->pos_pkts = 0; } /* Read next packet from "pkts" buffer */ pkt = p->pkts[p->pos_pkts++]; p->n_pkts--; /* If not jumbo, pass current packet to output */ if (pkt->pkt_len <= p->mtu) { pkts[n_pkts_out++] = pkt; n_pkts_to_provide = n_pkts - n_pkts_out; if (n_pkts_to_provide == 0) return n_pkts; continue; } /* Fragment current packet into the "frags" buffer */ status = p->f_frag( pkt, p->frags, RTE_PORT_FRAG_MAX_FRAGS_PER_PACKET, p->mtu, p->pool_direct, p->pool_indirect ); if (status < 0) { rte_pktmbuf_free(pkt); RTE_PORT_RING_READER_FRAG_STATS_PKTS_DROP_ADD(p, 1); continue; } p->n_frags = (uint32_t) status; p->pos_frags = 0; /* Copy meta-data from input jumbo packet to its fragments */ for (i = 0; i < p->n_frags; i++) { uint8_t *src = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0); uint8_t *dst = RTE_MBUF_METADATA_UINT8_PTR(p->frags[i], 0); memcpy(dst, src, p->metadata_size); } /* Free input jumbo packet */ rte_pktmbuf_free(pkt); /* Get packets from "frag" buffer */ n_pkts_to_provide = n_pkts - n_pkts_out; if (p->n_frags >= n_pkts_to_provide) { memcpy(&pkts[n_pkts_out], p->frags, n_pkts_to_provide * sizeof(void *)); p->n_frags -= n_pkts_to_provide; p->pos_frags += n_pkts_to_provide; return n_pkts; } memcpy(&pkts[n_pkts_out], p->frags, p->n_frags * sizeof(void *)); n_pkts_out += p->n_frags; p->n_frags = 0; } } static int rte_port_ring_reader_frag_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter port is NULL\n", __func__); return -1; } rte_free(port); return 0; } static int rte_port_frag_reader_stats_read(void *port, struct rte_port_in_stats *stats, int clear) { struct rte_port_ring_reader_frag *p = (struct rte_port_ring_reader_frag *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Summary of port operations */ struct rte_port_in_ops rte_port_ring_reader_ipv4_frag_ops = { .f_create = rte_port_ring_reader_ipv4_frag_create, .f_free = rte_port_ring_reader_frag_free, .f_rx = rte_port_ring_reader_frag_rx, .f_stats = rte_port_frag_reader_stats_read, }; struct rte_port_in_ops rte_port_ring_reader_ipv6_frag_ops = { .f_create = rte_port_ring_reader_ipv6_frag_create, .f_free = rte_port_ring_reader_frag_free, .f_rx = rte_port_ring_reader_frag_rx, .f_stats = rte_port_frag_reader_stats_read, }; ================================================ FILE: lib/librte_port/rte_port_frag.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_IP_FRAG_H__ #define __INCLUDE_RTE_PORT_IP_FRAG_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port for IPv4 Fragmentation * * This port is built on top of pre-initialized single consumer rte_ring. In * order to minimize the amount of packets stored in the ring at any given * time, the IP fragmentation functionality is executed on ring read operation, * hence this port is implemented as an input port. A regular ring_writer port * can be created to write to the same ring. * * The packets written to the ring are either complete IP datagrams or jumbo * frames (i.e. IP packets with length bigger than provided MTU value). The * packets read from the ring are all non-jumbo frames. The complete IP * datagrams written to the ring are not changed. The jumbo frames are * fragmented into several IP packets with length less or equal to MTU. * ***/ #include #include #include "rte_port.h" /** ring_reader_ipv4_frag port parameters */ struct rte_port_ring_reader_frag_params { /** Underlying single consumer ring that has to be pre-initialized. */ struct rte_ring *ring; /** Maximum Transfer Unit (MTU). Maximum IP packet size (in bytes). */ uint32_t mtu; /** Size of application dependent meta-data stored per each input packet that has to be copied to each of the fragments originating from the same input IP datagram. */ uint32_t metadata_size; /** Pre-initialized buffer pool used for allocating direct buffers for the output fragments. */ struct rte_mempool *pool_direct; /** Pre-initialized buffer pool used for allocating indirect buffers for the output fragments. */ struct rte_mempool *pool_indirect; }; #define rte_port_ring_reader_ipv4_frag_params rte_port_ring_reader_frag_params #define rte_port_ring_reader_ipv6_frag_params rte_port_ring_reader_frag_params /** ring_reader_ipv4_frag port operations */ extern struct rte_port_in_ops rte_port_ring_reader_ipv4_frag_ops; /** ring_reader_ipv6_frag port operations */ extern struct rte_port_in_ops rte_port_ring_reader_ipv6_frag_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_ras.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_port_ras.h" #ifndef RTE_PORT_RAS_N_BUCKETS #define RTE_PORT_RAS_N_BUCKETS 4094 #endif #ifndef RTE_PORT_RAS_N_ENTRIES_PER_BUCKET #define RTE_PORT_RAS_N_ENTRIES_PER_BUCKET 8 #endif #ifndef RTE_PORT_RAS_N_ENTRIES #define RTE_PORT_RAS_N_ENTRIES (RTE_PORT_RAS_N_BUCKETS * RTE_PORT_RAS_N_ENTRIES_PER_BUCKET) #endif #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_RING_WRITER_RAS_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_RING_WRITER_RAS_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_RING_WRITER_RAS_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_RING_WRITER_RAS_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ring_writer_ras; typedef void (*ras_op)( struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt); static void process_ipv4(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt); static void process_ipv6(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt); struct rte_port_ring_writer_ras { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_ring *ring; uint32_t tx_burst_sz; uint32_t tx_buf_count; struct rte_ip_frag_tbl *frag_tbl; struct rte_ip_frag_death_row death_row; ras_op f_ras; }; static void * rte_port_ring_writer_ras_create(void *params, int socket_id, int is_ipv4) { struct rte_port_ring_writer_ras_params *conf = (struct rte_port_ring_writer_ras_params *) params; struct rte_port_ring_writer_ras *port; uint64_t frag_cycles; /* Check input parameters */ if (conf == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter conf is NULL\n", __func__); return NULL; } if (conf->ring == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter ring is NULL\n", __func__); return NULL; } if ((conf->tx_burst_sz == 0) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) { RTE_LOG(ERR, PORT, "%s: Parameter tx_burst_sz is invalid\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate socket\n", __func__); return NULL; } /* Create fragmentation table */ frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * MS_PER_S; frag_cycles *= 100; port->frag_tbl = rte_ip_frag_table_create( RTE_PORT_RAS_N_BUCKETS, RTE_PORT_RAS_N_ENTRIES_PER_BUCKET, RTE_PORT_RAS_N_ENTRIES, frag_cycles, socket_id); if (port->frag_tbl == NULL) { RTE_LOG(ERR, PORT, "%s: rte_ip_frag_table_create failed\n", __func__); rte_free(port); return NULL; } /* Initialization */ port->ring = conf->ring; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->f_ras = (is_ipv4 == 0) ? process_ipv4 : process_ipv6; return port; } static void * rte_port_ring_writer_ipv4_ras_create(void *params, int socket_id) { return rte_port_ring_writer_ras_create(params, socket_id, 1); } static void * rte_port_ring_writer_ipv6_ras_create(void *params, int socket_id) { return rte_port_ring_writer_ras_create(params, socket_id, 0); } static inline void send_burst(struct rte_port_ring_writer_ras *p) { uint32_t nb_tx; nb_tx = rte_ring_sp_enqueue_burst(p->ring, (void **)p->tx_buf, p->tx_buf_count); RTE_PORT_RING_WRITER_RAS_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); for ( ; nb_tx < p->tx_buf_count; nb_tx++) rte_pktmbuf_free(p->tx_buf[nb_tx]); p->tx_buf_count = 0; } static void process_ipv4(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt) { /* Assume there is no ethernet header */ struct ipv4_hdr *pkt_hdr = rte_pktmbuf_mtod(pkt, struct ipv4_hdr *); /* Get "Do not fragment" flag and fragment offset */ uint16_t frag_field = rte_be_to_cpu_16(pkt_hdr->fragment_offset); uint16_t frag_offset = (uint16_t)(frag_field & IPV4_HDR_OFFSET_MASK); uint16_t frag_flag = (uint16_t)(frag_field & IPV4_HDR_MF_FLAG); /* If it is a fragmented packet, then try to reassemble */ if ((frag_flag == 0) && (frag_offset == 0)) p->tx_buf[p->tx_buf_count++] = pkt; else { struct rte_mbuf *mo; struct rte_ip_frag_tbl *tbl = p->frag_tbl; struct rte_ip_frag_death_row *dr = &p->death_row; /* Process this fragment */ mo = rte_ipv4_frag_reassemble_packet(tbl, dr, pkt, rte_rdtsc(), pkt_hdr); if (mo != NULL) p->tx_buf[p->tx_buf_count++] = mo; rte_ip_frag_free_death_row(&p->death_row, 3); } } static void process_ipv6(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt) { /* Assume there is no ethernet header */ struct ipv6_hdr *pkt_hdr = rte_pktmbuf_mtod(pkt, struct ipv6_hdr *); struct ipv6_extension_fragment *frag_hdr; frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt_hdr); uint16_t frag_offset = frag_hdr->frag_offset; uint16_t frag_flag = frag_hdr->more_frags; /* If it is a fragmented packet, then try to reassemble */ if ((frag_flag == 0) && (frag_offset == 0)) p->tx_buf[p->tx_buf_count++] = pkt; else { struct rte_mbuf *mo; struct rte_ip_frag_tbl *tbl = p->frag_tbl; struct rte_ip_frag_death_row *dr = &p->death_row; /* Process this fragment */ mo = rte_ipv6_frag_reassemble_packet(tbl, dr, pkt, rte_rdtsc(), pkt_hdr, frag_hdr); if (mo != NULL) p->tx_buf[p->tx_buf_count++] = mo; rte_ip_frag_free_death_row(&p->death_row, 3); } } static int rte_port_ring_writer_ras_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_ring_writer_ras *p = (struct rte_port_ring_writer_ras *) port; RTE_PORT_RING_WRITER_RAS_STATS_PKTS_IN_ADD(p, 1); p->f_ras(p, pkt); if (p->tx_buf_count >= p->tx_burst_sz) send_burst(p); return 0; } static int rte_port_ring_writer_ras_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_ring_writer_ras *p = (struct rte_port_ring_writer_ras *) port; if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = pkts[i]; RTE_PORT_RING_WRITER_RAS_STATS_PKTS_IN_ADD(p, 1); p->f_ras(p, pkt); if (p->tx_buf_count >= p->tx_burst_sz) send_burst(p); } } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; RTE_PORT_RING_WRITER_RAS_STATS_PKTS_IN_ADD(p, 1); p->f_ras(p, pkt); if (p->tx_buf_count >= p->tx_burst_sz) send_burst(p); pkts_mask &= ~pkt_mask; } } return 0; } static int rte_port_ring_writer_ras_flush(void *port) { struct rte_port_ring_writer_ras *p = (struct rte_port_ring_writer_ras *) port; if (p->tx_buf_count > 0) send_burst(p); return 0; } static int rte_port_ring_writer_ras_free(void *port) { struct rte_port_ring_writer_ras *p = (struct rte_port_ring_writer_ras *) port; if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Parameter port is NULL\n", __func__); return -1; } rte_port_ring_writer_ras_flush(port); rte_ip_frag_table_destroy(p->frag_tbl); rte_free(port); return 0; } static int rte_port_ras_writer_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_ring_writer_ras *p = (struct rte_port_ring_writer_ras *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Summary of port operations */ struct rte_port_out_ops rte_port_ring_writer_ipv4_ras_ops = { .f_create = rte_port_ring_writer_ipv4_ras_create, .f_free = rte_port_ring_writer_ras_free, .f_tx = rte_port_ring_writer_ras_tx, .f_tx_bulk = rte_port_ring_writer_ras_tx_bulk, .f_flush = rte_port_ring_writer_ras_flush, .f_stats = rte_port_ras_writer_stats_read, }; struct rte_port_out_ops rte_port_ring_writer_ipv6_ras_ops = { .f_create = rte_port_ring_writer_ipv6_ras_create, .f_free = rte_port_ring_writer_ras_free, .f_tx = rte_port_ring_writer_ras_tx, .f_tx_bulk = rte_port_ring_writer_ras_tx_bulk, .f_flush = rte_port_ring_writer_ras_flush, .f_stats = rte_port_ras_writer_stats_read, }; ================================================ FILE: lib/librte_port/rte_port_ras.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_RAS_H__ #define __INCLUDE_RTE_PORT_RAS_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port for IPv4 Reassembly * * This port is built on top of pre-initialized single producer rte_ring. In * order to minimize the amount of packets stored in the ring at any given * time, the IP reassembly functionality is executed on ring write operation, * hence this port is implemented as an output port. A regular ring_reader port * can be created to read from the same ring. * * The packets written to the ring are either complete IP datagrams or IP * fragments. The packets read from the ring are all complete IP datagrams, * either jumbo frames (i.e. IP packets with length bigger than MTU) or not. * The complete IP datagrams written to the ring are not changed. The IP * fragments written to the ring are first reassembled and into complete IP * datagrams or dropped on error or IP reassembly time-out. * ***/ #include #include #include "rte_port.h" /** ring_writer_ipv4_ras port parameters */ struct rte_port_ring_writer_ras_params { /** Underlying single consumer ring that has to be pre-initialized. */ struct rte_ring *ring; /** Recommended burst size to ring. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; }; #define rte_port_ring_writer_ipv4_ras_params rte_port_ring_writer_ras_params #define rte_port_ring_writer_ipv6_ras_params rte_port_ring_writer_ras_params /** ring_writer_ipv4_ras port operations */ extern struct rte_port_out_ops rte_port_ring_writer_ipv4_ras_ops; /** ring_writer_ipv6_ras port operations */ extern struct rte_port_out_ops rte_port_ring_writer_ipv6_ras_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_ring.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_port_ring.h" /* * Port RING Reader */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_RING_READER_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_RING_READER_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ring_reader { struct rte_port_in_stats stats; struct rte_ring *ring; }; static void * rte_port_ring_reader_create(void *params, int socket_id) { struct rte_port_ring_reader_params *conf = (struct rte_port_ring_reader_params *) params; struct rte_port_ring_reader *port; /* Check input parameters */ if (conf == NULL) { RTE_LOG(ERR, PORT, "%s: params is NULL\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->ring = conf->ring; return port; } static int rte_port_ring_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_port_ring_reader *p = (struct rte_port_ring_reader *) port; uint32_t nb_rx; nb_rx = rte_ring_sc_dequeue_burst(p->ring, (void **) pkts, n_pkts); RTE_PORT_RING_READER_STATS_PKTS_IN_ADD(p, nb_rx); return nb_rx; } static int rte_port_ring_reader_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); return -EINVAL; } rte_free(port); return 0; } static int rte_port_ring_reader_stats_read(void *port, struct rte_port_in_stats *stats, int clear) { struct rte_port_ring_reader *p = (struct rte_port_ring_reader *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Port RING Writer */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ring_writer { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_ring *ring; uint32_t tx_burst_sz; uint32_t tx_buf_count; uint64_t bsz_mask; }; static void * rte_port_ring_writer_create(void *params, int socket_id) { struct rte_port_ring_writer_params *conf = (struct rte_port_ring_writer_params *) params; struct rte_port_ring_writer *port; /* Check input parameters */ if ((conf == NULL) || (conf->ring == NULL) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) { RTE_LOG(ERR, PORT, "%s: Invalid Parameters\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->ring = conf->ring; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); return port; } static inline void send_burst(struct rte_port_ring_writer *p) { uint32_t nb_tx; nb_tx = rte_ring_sp_enqueue_burst(p->ring, (void **)p->tx_buf, p->tx_buf_count); RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); for ( ; nb_tx < p->tx_buf_count; nb_tx++) rte_pktmbuf_free(p->tx_buf[nb_tx]); p->tx_buf_count = 0; } static int rte_port_ring_writer_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_ring_writer *p = (struct rte_port_ring_writer *) port; p->tx_buf[p->tx_buf_count++] = pkt; RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, 1); if (p->tx_buf_count >= p->tx_burst_sz) send_burst(p); return 0; } static int rte_port_ring_writer_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_ring_writer *p = (struct rte_port_ring_writer *) port; uint32_t bsz_mask = p->bsz_mask; uint32_t tx_buf_count = p->tx_buf_count; uint64_t expr = (pkts_mask & (pkts_mask + 1)) | ((pkts_mask & bsz_mask) ^ bsz_mask); if (expr == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t n_pkts_ok; if (tx_buf_count) send_burst(p); RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, n_pkts); n_pkts_ok = rte_ring_sp_enqueue_burst(p->ring, (void **)pkts, n_pkts); RTE_PORT_RING_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - n_pkts_ok); for ( ; n_pkts_ok < n_pkts; n_pkts_ok++) { struct rte_mbuf *pkt = pkts[n_pkts_ok]; rte_pktmbuf_free(pkt); } } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; p->tx_buf[tx_buf_count++] = pkt; RTE_PORT_RING_WRITER_STATS_PKTS_IN_ADD(p, 1); pkts_mask &= ~pkt_mask; } p->tx_buf_count = tx_buf_count; if (tx_buf_count >= p->tx_burst_sz) send_burst(p); } return 0; } static int rte_port_ring_writer_flush(void *port) { struct rte_port_ring_writer *p = (struct rte_port_ring_writer *) port; if (p->tx_buf_count > 0) send_burst(p); return 0; } static int rte_port_ring_writer_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); return -EINVAL; } rte_port_ring_writer_flush(port); rte_free(port); return 0; } static int rte_port_ring_writer_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_ring_writer *p = (struct rte_port_ring_writer *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Port RING Writer Nodrop */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_ring_writer_nodrop { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_ring *ring; uint32_t tx_burst_sz; uint32_t tx_buf_count; uint64_t bsz_mask; uint64_t n_retries; }; static void * rte_port_ring_writer_nodrop_create(void *params, int socket_id) { struct rte_port_ring_writer_nodrop_params *conf = (struct rte_port_ring_writer_nodrop_params *) params; struct rte_port_ring_writer_nodrop *port; /* Check input parameters */ if ((conf == NULL) || (conf->ring == NULL) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX)) { RTE_LOG(ERR, PORT, "%s: Invalid Parameters\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->ring = conf->ring; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); /* * When n_retries is 0 it means that we should wait for every packet to * send no matter how many retries should it take. To limit number of * branches in fast path, we use UINT64_MAX instead of branching. */ port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries; return port; } static inline void send_burst_nodrop(struct rte_port_ring_writer_nodrop *p) { uint32_t nb_tx = 0, i; nb_tx = rte_ring_sp_enqueue_burst(p->ring, (void **)p->tx_buf, p->tx_buf_count); /* We sent all the packets in a first try */ if (nb_tx >= p->tx_buf_count) return; for (i = 0; i < p->n_retries; i++) { nb_tx += rte_ring_sp_enqueue_burst(p->ring, (void **) (p->tx_buf + nb_tx), p->tx_buf_count - nb_tx); /* We sent all the packets in more than one try */ if (nb_tx >= p->tx_buf_count) return; } /* We didn't send the packets in maximum allowed attempts */ RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); for ( ; nb_tx < p->tx_buf_count; nb_tx++) rte_pktmbuf_free(p->tx_buf[nb_tx]); p->tx_buf_count = 0; } static int rte_port_ring_writer_nodrop_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_ring_writer_nodrop *p = (struct rte_port_ring_writer_nodrop *) port; p->tx_buf[p->tx_buf_count++] = pkt; RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); if (p->tx_buf_count >= p->tx_burst_sz) send_burst_nodrop(p); return 0; } static int rte_port_ring_writer_nodrop_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_ring_writer_nodrop *p = (struct rte_port_ring_writer_nodrop *) port; uint32_t bsz_mask = p->bsz_mask; uint32_t tx_buf_count = p->tx_buf_count; uint64_t expr = (pkts_mask & (pkts_mask + 1)) | ((pkts_mask & bsz_mask) ^ bsz_mask); if (expr == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t n_pkts_ok; if (tx_buf_count) send_burst_nodrop(p); RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts); n_pkts_ok = rte_ring_sp_enqueue_burst(p->ring, (void **)pkts, n_pkts); if (n_pkts_ok >= n_pkts) return 0; /* * If we didnt manage to send all packets in single burst, move * remaining packets to the buffer and call send burst. */ for (; n_pkts_ok < n_pkts; n_pkts_ok++) { struct rte_mbuf *pkt = pkts[n_pkts_ok]; p->tx_buf[p->tx_buf_count++] = pkt; } send_burst_nodrop(p); } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; p->tx_buf[tx_buf_count++] = pkt; RTE_PORT_RING_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1); pkts_mask &= ~pkt_mask; } p->tx_buf_count = tx_buf_count; if (tx_buf_count >= p->tx_burst_sz) send_burst_nodrop(p); } return 0; } static int rte_port_ring_writer_nodrop_flush(void *port) { struct rte_port_ring_writer_nodrop *p = (struct rte_port_ring_writer_nodrop *) port; if (p->tx_buf_count > 0) send_burst_nodrop(p); return 0; } static int rte_port_ring_writer_nodrop_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__); return -EINVAL; } rte_port_ring_writer_nodrop_flush(port); rte_free(port); return 0; } static int rte_port_ring_writer_nodrop_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_ring_writer_nodrop *p = (struct rte_port_ring_writer_nodrop *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Summary of port operations */ struct rte_port_in_ops rte_port_ring_reader_ops = { .f_create = rte_port_ring_reader_create, .f_free = rte_port_ring_reader_free, .f_rx = rte_port_ring_reader_rx, .f_stats = rte_port_ring_reader_stats_read, }; struct rte_port_out_ops rte_port_ring_writer_ops = { .f_create = rte_port_ring_writer_create, .f_free = rte_port_ring_writer_free, .f_tx = rte_port_ring_writer_tx, .f_tx_bulk = rte_port_ring_writer_tx_bulk, .f_flush = rte_port_ring_writer_flush, .f_stats = rte_port_ring_writer_stats_read, }; struct rte_port_out_ops rte_port_ring_writer_nodrop_ops = { .f_create = rte_port_ring_writer_nodrop_create, .f_free = rte_port_ring_writer_nodrop_free, .f_tx = rte_port_ring_writer_nodrop_tx, .f_tx_bulk = rte_port_ring_writer_nodrop_tx_bulk, .f_flush = rte_port_ring_writer_nodrop_flush, .f_stats = rte_port_ring_writer_nodrop_stats_read, }; ================================================ FILE: lib/librte_port/rte_port_ring.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_RING_H__ #define __INCLUDE_RTE_PORT_RING_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port Ring * * ring_reader: input port built on top of pre-initialized single consumer ring * ring_writer: output port built on top of pre-initialized single producer ring * ***/ #include #include #include "rte_port.h" /** ring_reader port parameters */ struct rte_port_ring_reader_params { /** Underlying single consumer ring that has to be pre-initialized */ struct rte_ring *ring; }; /** ring_reader port operations */ extern struct rte_port_in_ops rte_port_ring_reader_ops; /** ring_writer port parameters */ struct rte_port_ring_writer_params { /** Underlying single producer ring that has to be pre-initialized */ struct rte_ring *ring; /** Recommended burst size to ring. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; }; /** ring_writer port operations */ extern struct rte_port_out_ops rte_port_ring_writer_ops; /** ring_writer_nodrop port parameters */ struct rte_port_ring_writer_nodrop_params { /** Underlying single producer ring that has to be pre-initialized */ struct rte_ring *ring; /** Recommended burst size to ring. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; /** Maximum number of retries, 0 for no limit */ uint32_t n_retries; }; /** ring_writer_nodrop port operations */ extern struct rte_port_out_ops rte_port_ring_writer_nodrop_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_sched.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "rte_port_sched.h" /* * Reader */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_SCHED_READER_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_SCHED_READER_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_SCHED_READER_PKTS_IN_ADD(port, val) #define RTE_PORT_SCHED_READER_PKTS_DROP_ADD(port, val) #endif struct rte_port_sched_reader { struct rte_port_in_stats stats; struct rte_sched_port *sched; }; static void * rte_port_sched_reader_create(void *params, int socket_id) { struct rte_port_sched_reader_params *conf = (struct rte_port_sched_reader_params *) params; struct rte_port_sched_reader *port; /* Check input parameters */ if ((conf == NULL) || (conf->sched == NULL)) { RTE_LOG(ERR, PORT, "%s: Invalid params\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->sched = conf->sched; return port; } static int rte_port_sched_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_port_sched_reader *p = (struct rte_port_sched_reader *) port; uint32_t nb_rx; nb_rx = rte_sched_port_dequeue(p->sched, pkts, n_pkts); RTE_PORT_SCHED_READER_PKTS_IN_ADD(p, nb_rx); return nb_rx; } static int rte_port_sched_reader_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); return -EINVAL; } rte_free(port); return 0; } static int rte_port_sched_reader_stats_read(void *port, struct rte_port_in_stats *stats, int clear) { struct rte_port_sched_reader *p = (struct rte_port_sched_reader *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Writer */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_SCHED_WRITER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_SCHED_WRITER_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_sched_writer { struct rte_port_out_stats stats; struct rte_mbuf *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX]; struct rte_sched_port *sched; uint32_t tx_burst_sz; uint32_t tx_buf_count; uint64_t bsz_mask; }; static void * rte_port_sched_writer_create(void *params, int socket_id) { struct rte_port_sched_writer_params *conf = (struct rte_port_sched_writer_params *) params; struct rte_port_sched_writer *port; /* Check input parameters */ if ((conf == NULL) || (conf->sched == NULL) || (conf->tx_burst_sz == 0) || (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) || (!rte_is_power_of_2(conf->tx_burst_sz))) { RTE_LOG(ERR, PORT, "%s: Invalid params\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->sched = conf->sched; port->tx_burst_sz = conf->tx_burst_sz; port->tx_buf_count = 0; port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1); return port; } static int rte_port_sched_writer_tx(void *port, struct rte_mbuf *pkt) { struct rte_port_sched_writer *p = (struct rte_port_sched_writer *) port; p->tx_buf[p->tx_buf_count++] = pkt; RTE_PORT_SCHED_WRITER_STATS_PKTS_IN_ADD(p, 1); if (p->tx_buf_count >= p->tx_burst_sz) { __rte_unused uint32_t nb_tx; nb_tx = rte_sched_port_enqueue(p->sched, p->tx_buf, p->tx_buf_count); RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); p->tx_buf_count = 0; } return 0; } static int rte_port_sched_writer_tx_bulk(void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { struct rte_port_sched_writer *p = (struct rte_port_sched_writer *) port; uint32_t bsz_mask = p->bsz_mask; uint32_t tx_buf_count = p->tx_buf_count; uint64_t expr = (pkts_mask & (pkts_mask + 1)) | ((pkts_mask & bsz_mask) ^ bsz_mask); if (expr == 0) { __rte_unused uint32_t nb_tx; uint64_t n_pkts = __builtin_popcountll(pkts_mask); if (tx_buf_count) { nb_tx = rte_sched_port_enqueue(p->sched, p->tx_buf, tx_buf_count); RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(p, tx_buf_count - nb_tx); p->tx_buf_count = 0; } nb_tx = rte_sched_port_enqueue(p->sched, pkts, n_pkts); RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(p, n_pkts - nb_tx); } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; p->tx_buf[tx_buf_count++] = pkt; RTE_PORT_SCHED_WRITER_STATS_PKTS_IN_ADD(p, 1); pkts_mask &= ~pkt_mask; } p->tx_buf_count = tx_buf_count; if (tx_buf_count >= p->tx_burst_sz) { __rte_unused uint32_t nb_tx; nb_tx = rte_sched_port_enqueue(p->sched, p->tx_buf, tx_buf_count); RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(p, tx_buf_count - nb_tx); p->tx_buf_count = 0; } } return 0; } static int rte_port_sched_writer_flush(void *port) { struct rte_port_sched_writer *p = (struct rte_port_sched_writer *) port; if (p->tx_buf_count) { __rte_unused uint32_t nb_tx; nb_tx = rte_sched_port_enqueue(p->sched, p->tx_buf, p->tx_buf_count); RTE_PORT_SCHED_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - nb_tx); p->tx_buf_count = 0; } return 0; } static int rte_port_sched_writer_free(void *port) { if (port == NULL) { RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__); return -EINVAL; } rte_port_sched_writer_flush(port); rte_free(port); return 0; } static int rte_port_sched_writer_stats_read(void *port, struct rte_port_out_stats *stats, int clear) { struct rte_port_sched_writer *p = (struct rte_port_sched_writer *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Summary of port operations */ struct rte_port_in_ops rte_port_sched_reader_ops = { .f_create = rte_port_sched_reader_create, .f_free = rte_port_sched_reader_free, .f_rx = rte_port_sched_reader_rx, .f_stats = rte_port_sched_reader_stats_read, }; struct rte_port_out_ops rte_port_sched_writer_ops = { .f_create = rte_port_sched_writer_create, .f_free = rte_port_sched_writer_free, .f_tx = rte_port_sched_writer_tx, .f_tx_bulk = rte_port_sched_writer_tx_bulk, .f_flush = rte_port_sched_writer_flush, .f_stats = rte_port_sched_writer_stats_read, }; ================================================ FILE: lib/librte_port/rte_port_sched.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_SCHED_H__ #define __INCLUDE_RTE_PORT_SCHED_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port Hierarchical Scheduler * * sched_reader: input port built on top of pre-initialized rte_sched_port * sched_writer: output port built on top of pre-initialized rte_sched_port * ***/ #include #include #include "rte_port.h" /** sched_reader port parameters */ struct rte_port_sched_reader_params { /** Underlying pre-initialized rte_sched_port */ struct rte_sched_port *sched; }; /** sched_reader port operations */ extern struct rte_port_in_ops rte_port_sched_reader_ops; /** sched_writer port parameters */ struct rte_port_sched_writer_params { /** Underlying pre-initialized rte_sched_port */ struct rte_sched_port *sched; /** Recommended burst size. The actual burst size can be bigger or smaller than this value. */ uint32_t tx_burst_sz; }; /** sched_writer port operations */ extern struct rte_port_out_ops rte_port_sched_writer_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_port/rte_port_source_sink.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "rte_port_source_sink.h" /* * Port SOURCE */ #ifdef RTE_PORT_STATS_COLLECT #define RTE_PORT_SOURCE_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val #define RTE_PORT_SOURCE_STATS_PKTS_DROP_ADD(port, val) \ port->stats.n_pkts_drop += val #else #define RTE_PORT_SOURCE_STATS_PKTS_IN_ADD(port, val) #define RTE_PORT_SOURCE_STATS_PKTS_DROP_ADD(port, val) #endif struct rte_port_source { struct rte_port_in_stats stats; struct rte_mempool *mempool; }; static void * rte_port_source_create(void *params, int socket_id) { struct rte_port_source_params *p = (struct rte_port_source_params *) params; struct rte_port_source *port; /* Check input arguments*/ if ((p == NULL) || (p->mempool == NULL)) { RTE_LOG(ERR, PORT, "%s: Invalid params\n", __func__); return NULL; } /* Memory allocation */ port = rte_zmalloc_socket("PORT", sizeof(*port), RTE_CACHE_LINE_SIZE, socket_id); if (port == NULL) { RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__); return NULL; } /* Initialization */ port->mempool = (struct rte_mempool *) p->mempool; return port; } static int rte_port_source_free(void *port) { /* Check input parameters */ if (port == NULL) return 0; rte_free(port); return 0; } static int rte_port_source_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_port_source *p = (struct rte_port_source *) port; if (rte_mempool_get_bulk(p->mempool, (void **) pkts, n_pkts) != 0) return 0; RTE_PORT_SOURCE_STATS_PKTS_IN_ADD(p, n_pkts); return n_pkts; } static int rte_port_source_stats_read(void *port, struct rte_port_in_stats *stats, int clear) { struct rte_port_source *p = (struct rte_port_source *) port; if (stats != NULL) memcpy(stats, &p->stats, sizeof(p->stats)); if (clear) memset(&p->stats, 0, sizeof(p->stats)); return 0; } /* * Port SINK */ static void * rte_port_sink_create(__rte_unused void *params, __rte_unused int socket_id) { return (void *) 1; } static int rte_port_sink_tx(__rte_unused void *port, struct rte_mbuf *pkt) { rte_pktmbuf_free(pkt); return 0; } static int rte_port_sink_tx_bulk(__rte_unused void *port, struct rte_mbuf **pkts, uint64_t pkts_mask) { if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = pkts[i]; rte_pktmbuf_free(pkt); } } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; rte_pktmbuf_free(pkt); pkts_mask &= ~pkt_mask; } } return 0; } /* * Summary of port operations */ struct rte_port_in_ops rte_port_source_ops = { .f_create = rte_port_source_create, .f_free = rte_port_source_free, .f_rx = rte_port_source_rx, .f_stats = rte_port_source_stats_read, }; struct rte_port_out_ops rte_port_sink_ops = { .f_create = rte_port_sink_create, .f_free = NULL, .f_tx = rte_port_sink_tx, .f_tx_bulk = rte_port_sink_tx_bulk, .f_flush = NULL, }; ================================================ FILE: lib/librte_port/rte_port_source_sink.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_PORT_SOURCE_SINK_H__ #define __INCLUDE_RTE_PORT_SOURCE_SINK_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Port Source/Sink * * source: input port that can be used to generate packets * sink: output port that drops all packets written to it * ***/ #include "rte_port.h" /** source port parameters */ struct rte_port_source_params { /** Pre-initialized buffer pool */ struct rte_mempool *mempool; }; /** source port operations */ extern struct rte_port_in_ops rte_port_source_ops; /** sink port parameters: NONE */ /** sink port operations */ extern struct rte_port_out_ops rte_port_sink_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_power/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_power.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -fno-strict-aliasing EXPORT_MAP := rte_power_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_POWER) := rte_power.c rte_power_acpi_cpufreq.c SRCS-$(CONFIG_RTE_LIBRTE_POWER) += rte_power_kvm_vm.c guest_channel.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_POWER)-include := rte_power.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_POWER) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_power/channel_commands.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CHANNEL_COMMANDS_H_ #define CHANNEL_COMMANDS_H_ #ifdef __cplusplus extern "C" { #endif #include /* Maximum number of CPUs */ #define CHANNEL_CMDS_MAX_CPUS 64 #if CHANNEL_CMDS_MAX_CPUS > 64 #error Maximum number of cores is 64, overflow is guaranteed to \ cause problems with VM Power Management #endif /* Maximum number of channels per VM */ #define CHANNEL_CMDS_MAX_VM_CHANNELS 64 /* Maximum number of channels per VM */ #define CHANNEL_CMDS_MAX_VM_CHANNELS 64 /* Valid Commands */ #define CPU_POWER 1 #define CPU_POWER_CONNECT 2 /* CPU Power Command Scaling */ #define CPU_POWER_SCALE_UP 1 #define CPU_POWER_SCALE_DOWN 2 #define CPU_POWER_SCALE_MAX 3 #define CPU_POWER_SCALE_MIN 4 struct channel_packet { uint64_t resource_id; /**< core_num, device */ uint32_t unit; /**< scale down/up/min/max */ uint32_t command; /**< Power, IO, etc */ }; #ifdef __cplusplus } #endif #endif /* CHANNEL_COMMANDS_H_ */ ================================================ FILE: lib/librte_power/guest_channel.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "guest_channel.h" #include "channel_commands.h" #define RTE_LOGTYPE_GUEST_CHANNEL RTE_LOGTYPE_USER1 static int global_fds[RTE_MAX_LCORE]; int guest_channel_host_connect(const char *path, unsigned lcore_id) { int flags, ret; struct channel_packet pkt; char fd_path[PATH_MAX]; int fd = -1; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, GUEST_CHANNEL, "Channel(%u) is out of range 0...%d\n", lcore_id, RTE_MAX_LCORE-1); return -1; } /* check if path is already open */ if (global_fds[lcore_id] != 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Channel(%u) is already open with fd %d\n", lcore_id, global_fds[lcore_id]); return -1; } snprintf(fd_path, PATH_MAX, "%s.%u", path, lcore_id); RTE_LOG(INFO, GUEST_CHANNEL, "Opening channel '%s' for lcore %u\n", fd_path, lcore_id); fd = open(fd_path, O_RDWR); if (fd < 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Unable to to connect to '%s' with error " "%s\n", fd_path, strerror(errno)); return -1; } flags = fcntl(fd, F_GETFL, 0); if (flags < 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Failed on fcntl get flags for file %s\n", fd_path); goto error; } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Failed on setting non-blocking mode for " "file %s", fd_path); goto error; } /* QEMU needs a delay after connection */ sleep(1); /* Send a test packet, this command is ignored by the host, but a successful * send indicates that the host endpoint is monitoring. */ pkt.command = CPU_POWER_CONNECT; global_fds[lcore_id] = fd; ret = guest_channel_send_msg(&pkt, lcore_id); if (ret != 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Error on channel '%s' communications " "test: %s\n", fd_path, strerror(ret)); goto error; } RTE_LOG(INFO, GUEST_CHANNEL, "Channel '%s' is now connected\n", fd_path); return 0; error: close(fd); global_fds[lcore_id] = 0; return -1; } int guest_channel_send_msg(struct channel_packet *pkt, unsigned lcore_id) { int ret, buffer_len = sizeof(*pkt); void *buffer = pkt; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, GUEST_CHANNEL, "Channel(%u) is out of range 0...%d\n", lcore_id, RTE_MAX_LCORE-1); return -1; } if (global_fds[lcore_id] == 0) { RTE_LOG(ERR, GUEST_CHANNEL, "Channel is not connected\n"); return -1; } while (buffer_len > 0) { ret = write(global_fds[lcore_id], buffer, buffer_len); if (ret == buffer_len) return 0; if (ret == -1) { if (errno == EINTR) continue; return errno; } buffer = (char *)buffer + ret; buffer_len -= ret; } return 0; } void guest_channel_host_disconnect(unsigned lcore_id) { if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, GUEST_CHANNEL, "Channel(%u) is out of range 0...%d\n", lcore_id, RTE_MAX_LCORE-1); return; } if (global_fds[lcore_id] == 0) return; close(global_fds[lcore_id]); global_fds[lcore_id] = 0; } ================================================ FILE: lib/librte_power/guest_channel.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _GUEST_CHANNEL_H #define _GUEST_CHANNEL_H #ifdef __cplusplus extern "C" { #endif #include /** * Connect to the Virtio-Serial VM end-point located in path. It is * thread safe for unique lcore_ids. This function must be only called once from * each lcore. * * @param path * The path to the serial device on the filesystem * @param lcore_id * lcore_id. * * @return * - 0 on success. * - Negative on error. */ int guest_channel_host_connect(const char *path, unsigned lcore_id); /** * Disconnect from an already connected Virtio-Serial Endpoint. * * * @param lcore_id * lcore_id. * */ void guest_channel_host_disconnect(unsigned lcore_id); /** * Send a message contained in pkt over the Virtio-Serial to the host endpoint. * * @param pkt * Pointer to a populated struct guest_agent_pkt * * @param lcore_id * lcore_id. * * @return * - 0 on success. * - Negative on channel not connected. * - errno on write to channel error. */ int guest_channel_send_msg(struct channel_packet *pkt, unsigned lcore_id); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_power/rte_power.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "rte_power.h" #include "rte_power_acpi_cpufreq.h" #include "rte_power_kvm_vm.h" #include "rte_power_common.h" enum power_management_env global_default_env = PM_ENV_NOT_SET; volatile uint32_t global_env_cfg_status = 0; /* function pointers */ rte_power_freqs_t rte_power_freqs = NULL; rte_power_get_freq_t rte_power_get_freq = NULL; rte_power_set_freq_t rte_power_set_freq = NULL; rte_power_freq_change_t rte_power_freq_up = NULL; rte_power_freq_change_t rte_power_freq_down = NULL; rte_power_freq_change_t rte_power_freq_max = NULL; rte_power_freq_change_t rte_power_freq_min = NULL; int rte_power_set_env(enum power_management_env env) { if (rte_atomic32_cmpset(&global_env_cfg_status, 0, 1) == 0) { return 0; } if (env == PM_ENV_ACPI_CPUFREQ) { rte_power_freqs = rte_power_acpi_cpufreq_freqs; rte_power_get_freq = rte_power_acpi_cpufreq_get_freq; rte_power_set_freq = rte_power_acpi_cpufreq_set_freq; rte_power_freq_up = rte_power_acpi_cpufreq_freq_up; rte_power_freq_down = rte_power_acpi_cpufreq_freq_down; rte_power_freq_min = rte_power_acpi_cpufreq_freq_min; rte_power_freq_max = rte_power_acpi_cpufreq_freq_max; } else if (env == PM_ENV_KVM_VM) { rte_power_freqs = rte_power_kvm_vm_freqs; rte_power_get_freq = rte_power_kvm_vm_get_freq; rte_power_set_freq = rte_power_kvm_vm_set_freq; rte_power_freq_up = rte_power_kvm_vm_freq_up; rte_power_freq_down = rte_power_kvm_vm_freq_down; rte_power_freq_min = rte_power_kvm_vm_freq_min; rte_power_freq_max = rte_power_kvm_vm_freq_max; } else { RTE_LOG(ERR, POWER, "Invalid Power Management Environment(%d) set\n", env); rte_power_unset_env(); return -1; } global_default_env = env; return 0; } void rte_power_unset_env(void) { if (rte_atomic32_cmpset(&global_env_cfg_status, 1, 0) != 0) global_default_env = PM_ENV_NOT_SET; } enum power_management_env rte_power_get_env(void) { return global_default_env; } int rte_power_init(unsigned lcore_id) { int ret = -1; if (global_default_env == PM_ENV_ACPI_CPUFREQ) { return rte_power_acpi_cpufreq_init(lcore_id); } if (global_default_env == PM_ENV_KVM_VM) { return rte_power_kvm_vm_init(lcore_id); } /* Auto detect Environment */ RTE_LOG(INFO, POWER, "Attempting to initialise ACPI cpufreq power " "management...\n"); ret = rte_power_acpi_cpufreq_init(lcore_id); if (ret == 0) { rte_power_set_env(PM_ENV_ACPI_CPUFREQ); goto out; } RTE_LOG(INFO, POWER, "Attempting to initialise VM power management...\n"); ret = rte_power_kvm_vm_init(lcore_id); if (ret == 0) { rte_power_set_env(PM_ENV_KVM_VM); goto out; } RTE_LOG(ERR, POWER, "Unable to set Power Management Environment for lcore " "%u\n", lcore_id); out: return ret; } int rte_power_exit(unsigned lcore_id) { if (global_default_env == PM_ENV_ACPI_CPUFREQ) return rte_power_acpi_cpufreq_exit(lcore_id); if (global_default_env == PM_ENV_KVM_VM) return rte_power_kvm_vm_exit(lcore_id); RTE_LOG(ERR, POWER, "Environment has not been set, unable to exit " "gracefully\n"); return -1; } ================================================ FILE: lib/librte_power/rte_power.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_POWER_H #define _RTE_POWER_H /** * @file * RTE Power Management */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* Power Management Environment State */ enum power_management_env {PM_ENV_NOT_SET, PM_ENV_ACPI_CPUFREQ, PM_ENV_KVM_VM}; /** * Set the default power management implementation. If this is not called prior * to rte_power_init(), then auto-detect of the environment will take place. * It is not thread safe. * * @param env * env. The environment in which to initialise Power Management for. * * @return * - 0 on success. * - Negative on error. */ int rte_power_set_env(enum power_management_env env); /** * Unset the global environment configuration. * This can only be called after all threads have completed. */ void rte_power_unset_env(void); /** * Get the default power management implementation. * * @return * power_management_env The configured environment. */ enum power_management_env rte_power_get_env(void); /** * Initialize power management for a specific lcore. If rte_power_set_env() has * not been called then an auto-detect of the environment will start and * initialise the corresponding resources. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_init(unsigned lcore_id); /** * Exit power management on a specific lcore. This will call the environment * dependent exit function. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_exit(unsigned lcore_id); /** * Get the available frequencies of a specific lcore. * Function pointer definition. Review each environments * specific documentation for usage. * * @param lcore_id * lcore id. * @param freqs * The buffer array to save the frequencies. * @param num * The number of frequencies to get. * * @return * The number of available frequencies. */ typedef uint32_t (*rte_power_freqs_t)(unsigned lcore_id, uint32_t *freqs, uint32_t num); extern rte_power_freqs_t rte_power_freqs; /** * Return the current index of available frequencies of a specific lcore. * Function pointer definition. Review each environments * specific documentation for usage. * * @param lcore_id * lcore id. * * @return * The current index of available frequencies. */ typedef uint32_t (*rte_power_get_freq_t)(unsigned lcore_id); extern rte_power_get_freq_t rte_power_get_freq; /** * Set the new frequency for a specific lcore by indicating the index of * available frequencies. * Function pointer definition. Review each environments * specific documentation for usage. * * @param lcore_id * lcore id. * @param index * The index of available frequencies. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ typedef int (*rte_power_set_freq_t)(unsigned lcore_id, uint32_t index); extern rte_power_set_freq_t rte_power_set_freq; /** * Function pointer definition for generic frequency change functions. Review * each environments specific documentation for usage. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ typedef int (*rte_power_freq_change_t)(unsigned lcore_id); /** * Scale up the frequency of a specific lcore according to the available * frequencies. * Review each environments specific documentation for usage. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ extern rte_power_freq_change_t rte_power_freq_up; /** * Scale down the frequency of a specific lcore according to the available * frequencies. * Review each environments specific documentation for usage. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ extern rte_power_freq_change_t rte_power_freq_down; /** * Scale up the frequency of a specific lcore to the highest according to the * available frequencies. * Review each environments specific documentation for usage. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ extern rte_power_freq_change_t rte_power_freq_max; /** * Scale down the frequency of a specific lcore to the lowest according to the * available frequencies. * Review each environments specific documentation for usage.. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ extern rte_power_freq_change_t rte_power_freq_min; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_power/rte_power_acpi_cpufreq.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "rte_power_acpi_cpufreq.h" #include "rte_power_common.h" #ifdef RTE_LIBRTE_POWER_DEBUG #define POWER_DEBUG_TRACE(fmt, args...) do { \ RTE_LOG(ERR, POWER, "%s: " fmt, __func__, ## args); \ } while (0) #else #define POWER_DEBUG_TRACE(fmt, args...) #endif #define FOPEN_OR_ERR_RET(f, retval) do { \ if ((f) == NULL) { \ RTE_LOG(ERR, POWER, "File not openned\n"); \ return retval; \ } \ } while (0) #define FOPS_OR_NULL_GOTO(ret, label) do { \ if ((ret) == NULL) { \ RTE_LOG(ERR, POWER, "fgets returns nothing\n"); \ goto label; \ } \ } while (0) #define FOPS_OR_ERR_GOTO(ret, label) do { \ if ((ret) < 0) { \ RTE_LOG(ERR, POWER, "File operations failed\n"); \ goto label; \ } \ } while (0) #define STR_SIZE 1024 #define POWER_CONVERT_TO_DECIMAL 10 #define POWER_GOVERNOR_USERSPACE "userspace" #define POWER_SYSFILE_GOVERNOR \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_governor" #define POWER_SYSFILE_AVAIL_FREQ \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_available_frequencies" #define POWER_SYSFILE_SETSPEED \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_setspeed" enum power_state { POWER_IDLE = 0, POWER_ONGOING, POWER_USED, POWER_UNKNOWN }; /** * Power info per lcore. */ struct rte_power_info { unsigned lcore_id; /**< Logical core id */ uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */ uint32_t nb_freqs; /**< number of available freqs */ FILE *f; /**< FD of scaling_setspeed */ char governor_ori[32]; /**< Original governor name */ uint32_t curr_idx; /**< Freq index in freqs array */ volatile uint32_t state; /**< Power in use state */ } __rte_cache_aligned; static struct rte_power_info lcore_power_info[RTE_MAX_LCORE]; /** * It is to set specific freq for specific logical core, according to the index * of supported frequencies. */ static int set_freq_internal(struct rte_power_info *pi, uint32_t idx) { if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) { RTE_LOG(ERR, POWER, "Invalid frequency index %u, which " "should be less than %u\n", idx, pi->nb_freqs); return -1; } /* Check if it is the same as current */ if (idx == pi->curr_idx) return 0; POWER_DEBUG_TRACE("Freqency[%u] %u to be set for lcore %u\n", idx, pi->freqs[idx], pi->lcore_id); if (fseek(pi->f, 0, SEEK_SET) < 0) { RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 " "for setting frequency for lcore %u\n", pi->lcore_id); return -1; } if (fprintf(pi->f, "%u", pi->freqs[idx]) < 0) { RTE_LOG(ERR, POWER, "Fail to write new frequency for " "lcore %u\n", pi->lcore_id); return -1; } fflush(pi->f); pi->curr_idx = idx; return 1; } /** * It is to check the current scaling governor by reading sys file, and then * set it into 'userspace' if it is not by writing the sys file. The original * governor will be saved for rolling back. */ static int power_set_governor_userspace(struct rte_power_info *pi) { FILE *f; int ret = -1; char buf[BUFSIZ]; char fullpath[PATH_MAX]; char *s; int val; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, ret); s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); /* Check if current governor is userspace */ if (strncmp(buf, POWER_GOVERNOR_USERSPACE, sizeof(POWER_GOVERNOR_USERSPACE)) == 0) { ret = 0; POWER_DEBUG_TRACE("Power management governor of lcore %u is " "already userspace\n", pi->lcore_id); goto out; } /* Save the original governor */ snprintf(pi->governor_ori, sizeof(pi->governor_ori), "%s", buf); /* Write 'userspace' to the governor */ val = fseek(f, 0, SEEK_SET); FOPS_OR_ERR_GOTO(val, out); val = fputs(POWER_GOVERNOR_USERSPACE, f); FOPS_OR_ERR_GOTO(val, out); ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u has been " "set to user space successfully\n", pi->lcore_id); out: fclose(f); return ret; } /** * It is to get the available frequencies of the specific lcore by reading the * sys file. */ static int power_get_available_freqs(struct rte_power_info *pi) { FILE *f; int ret = -1, i, count; char *p; char buf[BUFSIZ]; char fullpath[PATH_MAX]; char *freqs[RTE_MAX_LCORE_FREQS]; char *s; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_AVAIL_FREQ, pi->lcore_id); f = fopen(fullpath, "r"); FOPEN_OR_ERR_RET(f, ret); s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); /* Strip the line break if there is */ p = strchr(buf, '\n'); if (p != NULL) *p = 0; /* Split string into at most RTE_MAX_LCORE_FREQS frequencies */ count = rte_strsplit(buf, sizeof(buf), freqs, RTE_MAX_LCORE_FREQS, ' '); if (count <= 0) { RTE_LOG(ERR, POWER, "No available frequency in " ""POWER_SYSFILE_AVAIL_FREQ"\n", pi->lcore_id); goto out; } if (count >= RTE_MAX_LCORE_FREQS) { RTE_LOG(ERR, POWER, "Too many available frequencies : %d\n", count); goto out; } /* Store the available frequncies into power context */ for (i = 0, pi->nb_freqs = 0; i < count; i++) { POWER_DEBUG_TRACE("Lcore %u frequency[%d]: %s\n", pi->lcore_id, i, freqs[i]); pi->freqs[pi->nb_freqs++] = strtoul(freqs[i], &p, POWER_CONVERT_TO_DECIMAL); } ret = 0; POWER_DEBUG_TRACE("%d frequencie(s) of lcore %u are available\n", count, pi->lcore_id); out: fclose(f); return ret; } /** * It is to fopen the sys file for the future setting the lcore frequency. */ static int power_init_for_setting_freq(struct rte_power_info *pi) { FILE *f; char fullpath[PATH_MAX]; char buf[BUFSIZ]; uint32_t i, freq; char *s; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_SETSPEED, pi->lcore_id); f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, -1); s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); freq = strtoul(buf, NULL, POWER_CONVERT_TO_DECIMAL); for (i = 0; i < pi->nb_freqs; i++) { if (freq == pi->freqs[i]) { pi->curr_idx = i; pi->f = f; return 0; } } out: fclose(f); return -1; } int rte_power_acpi_cpufreq_init(unsigned lcore_id) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Lcore id %u can not exceeds %u\n", lcore_id, RTE_MAX_LCORE - 1U); return -1; } pi = &lcore_power_info[lcore_id]; if (rte_atomic32_cmpset(&(pi->state), POWER_IDLE, POWER_ONGOING) == 0) { RTE_LOG(INFO, POWER, "Power management of lcore %u is " "in use\n", lcore_id); return -1; } pi->lcore_id = lcore_id; /* Check and set the governor */ if (power_set_governor_userspace(pi) < 0) { RTE_LOG(ERR, POWER, "Cannot set governor of lcore %u to " "userspace\n", lcore_id); goto fail; } /* Get the available frequencies */ if (power_get_available_freqs(pi) < 0) { RTE_LOG(ERR, POWER, "Cannot get available frequencies of " "lcore %u\n", lcore_id); goto fail; } /* Init for setting lcore frequency */ if (power_init_for_setting_freq(pi) < 0) { RTE_LOG(ERR, POWER, "Cannot init for setting frequency for " "lcore %u\n", lcore_id); goto fail; } /* Set freq to max by default */ if (rte_power_acpi_cpufreq_freq_max(lcore_id) < 0) { RTE_LOG(ERR, POWER, "Cannot set frequency of lcore %u " "to max\n", lcore_id); goto fail; } RTE_LOG(INFO, POWER, "Initialized successfully for lcore %u " "power manamgement\n", lcore_id); rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_USED); return 0; fail: rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_UNKNOWN); return -1; } /** * It is to check the governor and then set the original governor back if * needed by writing the the sys file. */ static int power_set_governor_original(struct rte_power_info *pi) { FILE *f; int ret = -1; char buf[BUFSIZ]; char fullpath[PATH_MAX]; char *s; int val; snprintf(fullpath, sizeof(fullpath), POWER_SYSFILE_GOVERNOR, pi->lcore_id); f = fopen(fullpath, "rw+"); FOPEN_OR_ERR_RET(f, ret); s = fgets(buf, sizeof(buf), f); FOPS_OR_NULL_GOTO(s, out); /* Check if the governor to be set is the same as current */ if (strncmp(buf, pi->governor_ori, sizeof(pi->governor_ori)) == 0) { ret = 0; POWER_DEBUG_TRACE("Power management governor of lcore %u " "has already been set to %s\n", pi->lcore_id, pi->governor_ori); goto out; } /* Write back the original governor */ val = fseek(f, 0, SEEK_SET); FOPS_OR_ERR_GOTO(val, out); val = fputs(pi->governor_ori, f); FOPS_OR_ERR_GOTO(val, out); ret = 0; RTE_LOG(INFO, POWER, "Power management governor of lcore %u " "has been set back to %s successfully\n", pi->lcore_id, pi->governor_ori); out: fclose(f); return ret; } int rte_power_acpi_cpufreq_exit(unsigned lcore_id) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Lcore id %u can not exceeds %u\n", lcore_id, RTE_MAX_LCORE - 1U); return -1; } pi = &lcore_power_info[lcore_id]; if (rte_atomic32_cmpset(&(pi->state), POWER_USED, POWER_ONGOING) == 0) { RTE_LOG(INFO, POWER, "Power management of lcore %u is " "not used\n", lcore_id); return -1; } /* Close FD of setting freq */ fclose(pi->f); pi->f = NULL; /* Set the governor back to the original */ if (power_set_governor_original(pi) < 0) { RTE_LOG(ERR, POWER, "Cannot set the governor of %u back " "to the original\n", lcore_id); goto fail; } RTE_LOG(INFO, POWER, "Power management of lcore %u has exited from " "'userspace' mode and been set back to the " "original\n", lcore_id); rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_IDLE); return 0; fail: rte_atomic32_cmpset(&(pi->state), POWER_ONGOING, POWER_UNKNOWN); return -1; } uint32_t rte_power_acpi_cpufreq_freqs(unsigned lcore_id, uint32_t *freqs, uint32_t num) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE || !freqs) { RTE_LOG(ERR, POWER, "Invalid input parameter\n"); return 0; } pi = &lcore_power_info[lcore_id]; if (num < pi->nb_freqs) { RTE_LOG(ERR, POWER, "Buffer size is not enough\n"); return 0; } rte_memcpy(freqs, pi->freqs, pi->nb_freqs * sizeof(uint32_t)); return pi->nb_freqs; } uint32_t rte_power_acpi_cpufreq_get_freq(unsigned lcore_id) { if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return RTE_POWER_INVALID_FREQ_INDEX; } return lcore_power_info[lcore_id].curr_idx; } int rte_power_acpi_cpufreq_set_freq(unsigned lcore_id, uint32_t index) { if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return -1; } return set_freq_internal(&(lcore_power_info[lcore_id]), index); } int rte_power_acpi_cpufreq_freq_down(unsigned lcore_id) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return -1; } pi = &lcore_power_info[lcore_id]; if (pi->curr_idx + 1 == pi->nb_freqs) return 0; /* Frequencies in the array are from high to low. */ return set_freq_internal(pi, pi->curr_idx + 1); } int rte_power_acpi_cpufreq_freq_up(unsigned lcore_id) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return -1; } pi = &lcore_power_info[lcore_id]; if (pi->curr_idx == 0) return 0; /* Frequencies in the array are from high to low. */ return set_freq_internal(pi, pi->curr_idx - 1); } int rte_power_acpi_cpufreq_freq_max(unsigned lcore_id) { if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return -1; } /* Frequencies in the array are from high to low. */ return set_freq_internal(&lcore_power_info[lcore_id], 0); } int rte_power_acpi_cpufreq_freq_min(unsigned lcore_id) { struct rte_power_info *pi; if (lcore_id >= RTE_MAX_LCORE) { RTE_LOG(ERR, POWER, "Invalid lcore ID\n"); return -1; } pi = &lcore_power_info[lcore_id]; /* Frequencies in the array are from high to low. */ return set_freq_internal(pi, pi->nb_freqs - 1); } ================================================ FILE: lib/librte_power/rte_power_acpi_cpufreq.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_POWER_ACPI_CPUFREQ_H #define _RTE_POWER_ACPI_CPUFREQ_H /** * @file * RTE Power Management via userspace ACPI cpufreq */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Initialize power management for a specific lcore. It will check and set the * governor to userspace for the lcore, get the available frequencies, and * prepare to set new lcore frequency. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_acpi_cpufreq_init(unsigned lcore_id); /** * Exit power management on a specific lcore. It will set the governor to which * is before initialized. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_acpi_cpufreq_exit(unsigned lcore_id); /** * Get the available frequencies of a specific lcore. The return value will be * the minimal one of the total number of available frequencies and the number * of buffer. The index of available frequencies used in other interfaces * should be in the range of 0 to this return value. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * @param freqs * The buffer array to save the frequencies. * @param num * The number of frequencies to get. * * @return * The number of available frequencies. */ uint32_t rte_power_acpi_cpufreq_freqs(unsigned lcore_id, uint32_t *freqs, uint32_t num); /** * Return the current index of available frequencies of a specific lcore. It * will return 'RTE_POWER_INVALID_FREQ_INDEX = (~0)' if error. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * The current index of available frequencies. */ uint32_t rte_power_acpi_cpufreq_get_freq(unsigned lcore_id); /** * Set the new frequency for a specific lcore by indicating the index of * available frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * @param index * The index of available frequencies. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ int rte_power_acpi_cpufreq_set_freq(unsigned lcore_id, uint32_t index); /** * Scale up the frequency of a specific lcore according to the available * frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ int rte_power_acpi_cpufreq_freq_up(unsigned lcore_id); /** * Scale down the frequency of a specific lcore according to the available * frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ int rte_power_acpi_cpufreq_freq_down(unsigned lcore_id); /** * Scale up the frequency of a specific lcore to the highest according to the * available frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency changed. * - Negative on error. */ int rte_power_acpi_cpufreq_freq_max(unsigned lcore_id); /** * Scale down the frequency of a specific lcore to the lowest according to the * available frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success with frequency changed. * - 0 on success without frequency chnaged. * - Negative on error. */ int rte_power_acpi_cpufreq_freq_min(unsigned lcore_id); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_power/rte_power_common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RTE_POWER_COMMON_H_ #define RTE_POWER_COMMON_H_ #define RTE_POWER_INVALID_FREQ_INDEX (~0) #endif /* RTE_POWER_COMMON_H_ */ ================================================ FILE: lib/librte_power/rte_power_kvm_vm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "guest_channel.h" #include "channel_commands.h" #include "rte_power_kvm_vm.h" #include "rte_power_common.h" #define FD_PATH "/dev/virtio-ports/virtio.serial.port.poweragent" static struct channel_packet pkt[CHANNEL_CMDS_MAX_VM_CHANNELS]; int rte_power_kvm_vm_init(unsigned lcore_id) { if (lcore_id >= CHANNEL_CMDS_MAX_VM_CHANNELS) { RTE_LOG(ERR, POWER, "Core(%u) is out of range 0...%d\n", lcore_id, CHANNEL_CMDS_MAX_VM_CHANNELS-1); return -1; } pkt[lcore_id].command = CPU_POWER; pkt[lcore_id].resource_id = lcore_id; return guest_channel_host_connect(FD_PATH, lcore_id); } int rte_power_kvm_vm_exit(unsigned lcore_id) { guest_channel_host_disconnect(lcore_id); return 0; } uint32_t rte_power_kvm_vm_freqs(__attribute__((unused)) unsigned lcore_id, __attribute__((unused)) uint32_t *freqs, __attribute__((unused)) uint32_t num) { RTE_LOG(ERR, POWER, "rte_power_freqs is not implemented " "for Virtual Machine Power Management\n"); return -ENOTSUP; } uint32_t rte_power_kvm_vm_get_freq(__attribute__((unused)) unsigned lcore_id) { RTE_LOG(ERR, POWER, "rte_power_get_freq is not implemented " "for Virtual Machine Power Management\n"); return -ENOTSUP; } int rte_power_kvm_vm_set_freq(__attribute__((unused)) unsigned lcore_id, __attribute__((unused)) uint32_t index) { RTE_LOG(ERR, POWER, "rte_power_set_freq is not implemented " "for Virtual Machine Power Management\n"); return -ENOTSUP; } static inline int send_msg(unsigned lcore_id, uint32_t scale_direction) { int ret; if (lcore_id >= CHANNEL_CMDS_MAX_VM_CHANNELS) { RTE_LOG(ERR, POWER, "Core(%u) is out of range 0...%d\n", lcore_id, CHANNEL_CMDS_MAX_VM_CHANNELS-1); return -1; } pkt[lcore_id].unit = scale_direction; ret = guest_channel_send_msg(&pkt[lcore_id], lcore_id); if (ret == 0) return 1; RTE_LOG(DEBUG, POWER, "Error sending message: %s\n", strerror(ret)); return -1; } int rte_power_kvm_vm_freq_up(unsigned lcore_id) { return send_msg(lcore_id, CPU_POWER_SCALE_UP); } int rte_power_kvm_vm_freq_down(unsigned lcore_id) { return send_msg(lcore_id, CPU_POWER_SCALE_DOWN); } int rte_power_kvm_vm_freq_max(unsigned lcore_id) { return send_msg(lcore_id, CPU_POWER_SCALE_MAX); } int rte_power_kvm_vm_freq_min(unsigned lcore_id) { return send_msg(lcore_id, CPU_POWER_SCALE_MIN); } ================================================ FILE: lib/librte_power/rte_power_kvm_vm.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_POWER_KVM_VM_H #define _RTE_POWER_KVM_VM_H /** * @file * RTE Power Management KVM VM */ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Initialize power management for a specific lcore. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_kvm_vm_init(unsigned lcore_id); /** * Exit power management on a specific lcore. * * @param lcore_id * lcore id. * * @return * - 0 on success. * - Negative on error. */ int rte_power_kvm_vm_exit(unsigned lcore_id); /** * Get the available frequencies of a specific lcore. * It is not currently supported for VM Power Management. * * @param lcore_id * lcore id. * @param freqs * The buffer array to save the frequencies. * @param num * The number of frequencies to get. * * @return * -ENOTSUP */ uint32_t rte_power_kvm_vm_freqs(unsigned lcore_id, uint32_t *freqs, uint32_t num); /** * Return the current index of available frequencies of a specific lcore. * It is not currently supported for VM Power Management. * * @param lcore_id * lcore id. * * @return * -ENOTSUP */ uint32_t rte_power_kvm_vm_get_freq(unsigned lcore_id); /** * Set the new frequency for a specific lcore by indicating the index of * available frequencies. * It is not currently supported for VM Power Management. * * @param lcore_id * lcore id. * @param index * The index of available frequencies. * * @return * -ENOTSUP */ int rte_power_kvm_vm_set_freq(unsigned lcore_id, uint32_t index); /** * Scale up the frequency of a specific lcore. This request is forwarded to the * host monitor. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success. * - Negative on error. */ int rte_power_kvm_vm_freq_up(unsigned lcore_id); /** * Scale down the frequency of a specific lcore according to the available * frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success. * - Negative on error. */ int rte_power_kvm_vm_freq_down(unsigned lcore_id); /** * Scale up the frequency of a specific lcore to the highest according to the * available frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success. * - Negative on error. */ int rte_power_kvm_vm_freq_max(unsigned lcore_id); /** * Scale down the frequency of a specific lcore to the lowest according to the * available frequencies. * It should be protected outside of this function for threadsafe. * * @param lcore_id * lcore id. * * @return * - 1 on success. * - Negative on error. */ int rte_power_kvm_vm_freq_min(unsigned lcore_id); #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_reorder/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_reorder.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) EXPORT_MAP := rte_reorder_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_REORDER) := rte_reorder.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_REORDER)-include := rte_reorder.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_REORDER) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_REORDER) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_reorder/rte_reorder.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "rte_reorder.h" TAILQ_HEAD(rte_reorder_list, rte_tailq_entry); static struct rte_tailq_elem rte_reorder_tailq = { .name = "RTE_REORDER", }; EAL_REGISTER_TAILQ(rte_reorder_tailq) #define NO_FLAGS 0 #define RTE_REORDER_PREFIX "RO_" #define RTE_REORDER_NAMESIZE 32 /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_REORDER RTE_LOGTYPE_USER1 /* A generic circular buffer */ struct cir_buffer { unsigned int size; /**< Number of entries that can be stored */ unsigned int mask; /**< [buffer_size - 1]: used for wrap-around */ unsigned int head; /**< insertion point in buffer */ unsigned int tail; /**< extraction point in buffer */ struct rte_mbuf **entries; } __rte_cache_aligned; /* The reorder buffer data structure itself */ struct rte_reorder_buffer { char name[RTE_REORDER_NAMESIZE]; uint32_t min_seqn; /**< Lowest seq. number that can be in the buffer */ unsigned int memsize; /**< memory area size of reorder buffer */ struct cir_buffer ready_buf; /**< temp buffer for dequeued entries */ struct cir_buffer order_buf; /**< buffer used to reorder entries */ int is_initialized; } __rte_cache_aligned; static void rte_reorder_free_mbufs(struct rte_reorder_buffer *b); struct rte_reorder_buffer * rte_reorder_init(struct rte_reorder_buffer *b, unsigned int bufsize, const char *name, unsigned int size) { const unsigned int min_bufsize = sizeof(*b) + (2 * size * sizeof(struct rte_mbuf *)); if (b == NULL) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer parameter:" " NULL\n"); rte_errno = EINVAL; return NULL; } if (!rte_is_power_of_2(size)) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer size" " - Not a power of 2\n"); rte_errno = EINVAL; return NULL; } if (name == NULL) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer name ptr:" " NULL\n"); rte_errno = EINVAL; return NULL; } if (bufsize < min_bufsize) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer memory size: %u, " "minimum required: %u\n", bufsize, min_bufsize); rte_errno = EINVAL; return NULL; } memset(b, 0, bufsize); snprintf(b->name, sizeof(b->name), "%s", name); b->memsize = bufsize; b->order_buf.size = b->ready_buf.size = size; b->order_buf.mask = b->ready_buf.mask = size - 1; b->ready_buf.entries = (void *)&b[1]; b->order_buf.entries = RTE_PTR_ADD(&b[1], size * sizeof(b->ready_buf.entries[0])); return b; } struct rte_reorder_buffer* rte_reorder_create(const char *name, unsigned socket_id, unsigned int size) { struct rte_reorder_buffer *b = NULL; struct rte_tailq_entry *te; struct rte_reorder_list *reorder_list; const unsigned int bufsize = sizeof(struct rte_reorder_buffer) + (2 * size * sizeof(struct rte_mbuf *)); reorder_list = RTE_TAILQ_CAST(rte_reorder_tailq.head, rte_reorder_list); /* Check user arguments. */ if (!rte_is_power_of_2(size)) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer size" " - Not a power of 2\n"); rte_errno = EINVAL; return NULL; } if (name == NULL) { RTE_LOG(ERR, REORDER, "Invalid reorder buffer name ptr:" " NULL\n"); rte_errno = EINVAL; return NULL; } rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* guarantee there's no existing */ TAILQ_FOREACH(te, reorder_list, next) { b = (struct rte_reorder_buffer *) te->data; if (strncmp(name, b->name, RTE_REORDER_NAMESIZE) == 0) break; } if (te != NULL) goto exit; /* allocate tailq entry */ te = rte_zmalloc("REORDER_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, REORDER, "Failed to allocate tailq entry\n"); rte_errno = ENOMEM; b = NULL; goto exit; } /* Allocate memory to store the reorder buffer structure. */ b = rte_zmalloc_socket("REORDER_BUFFER", bufsize, 0, socket_id); if (b == NULL) { RTE_LOG(ERR, REORDER, "Memzone allocation failed\n"); rte_errno = ENOMEM; rte_free(te); } else { rte_reorder_init(b, bufsize, name, size); te->data = (void *)b; TAILQ_INSERT_TAIL(reorder_list, te, next); } exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return b; } void rte_reorder_reset(struct rte_reorder_buffer *b) { char name[RTE_REORDER_NAMESIZE]; rte_reorder_free_mbufs(b); snprintf(name, sizeof(name), "%s", b->name); /* No error checking as current values should be valid */ rte_reorder_init(b, b->memsize, name, b->order_buf.size); } static void rte_reorder_free_mbufs(struct rte_reorder_buffer *b) { unsigned i; /* Free up the mbufs of order buffer & ready buffer */ for (i = 0; i < b->order_buf.size; i++) { if (b->order_buf.entries[i]) rte_pktmbuf_free(b->order_buf.entries[i]); if (b->ready_buf.entries[i]) rte_pktmbuf_free(b->ready_buf.entries[i]); } } void rte_reorder_free(struct rte_reorder_buffer *b) { struct rte_reorder_list *reorder_list; struct rte_tailq_entry *te; /* Check user arguments. */ if (b == NULL) return; reorder_list = RTE_TAILQ_CAST(rte_reorder_tailq.head, rte_reorder_list); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* find our tailq entry */ TAILQ_FOREACH(te, reorder_list, next) { if (te->data == (void *) b) break; } if (te == NULL) { rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return; } TAILQ_REMOVE(reorder_list, te, next); rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_reorder_free_mbufs(b); rte_free(b); rte_free(te); } struct rte_reorder_buffer * rte_reorder_find_existing(const char *name) { struct rte_reorder_buffer *b = NULL; struct rte_tailq_entry *te; struct rte_reorder_list *reorder_list; reorder_list = RTE_TAILQ_CAST(rte_reorder_tailq.head, rte_reorder_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, reorder_list, next) { b = (struct rte_reorder_buffer *) te->data; if (strncmp(name, b->name, RTE_REORDER_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return b; } static unsigned rte_reorder_fill_overflow(struct rte_reorder_buffer *b, unsigned n) { /* * 1. Move all ready entries that fit to the ready_buf * 2. check if we meet the minimum needed (n). * 3. If not, then skip any gaps and keep moving. * 4. If at any point the ready buffer is full, stop * 5. Return the number of positions the order_buf head has moved */ struct cir_buffer *order_buf = &b->order_buf, *ready_buf = &b->ready_buf; unsigned int order_head_adv = 0; /* * move at least n packets to ready buffer, assuming ready buffer * has room for those packets. */ while (order_head_adv < n && ((ready_buf->head + 1) & ready_buf->mask) != ready_buf->tail) { /* if we are blocked waiting on a packet, skip it */ if (order_buf->entries[order_buf->head] == NULL) { order_buf->head = (order_buf->head + 1) & order_buf->mask; order_head_adv++; } /* Move all ready entries that fit to the ready_buf */ while (order_buf->entries[order_buf->head] != NULL) { ready_buf->entries[ready_buf->head] = order_buf->entries[order_buf->head]; order_buf->entries[order_buf->head] = NULL; order_head_adv++; order_buf->head = (order_buf->head + 1) & order_buf->mask; if (((ready_buf->head + 1) & ready_buf->mask) == ready_buf->tail) break; ready_buf->head = (ready_buf->head + 1) & ready_buf->mask; } } b->min_seqn += order_head_adv; /* Return the number of positions the order_buf head has moved */ return order_head_adv; } int rte_reorder_insert(struct rte_reorder_buffer *b, struct rte_mbuf *mbuf) { uint32_t offset, position; struct cir_buffer *order_buf = &b->order_buf; if (!b->is_initialized) { b->min_seqn = mbuf->seqn; b->is_initialized = 1; } /* * calculate the offset from the head pointer we need to go. * The subtraction takes care of the sequence number wrapping. * For example (using 16-bit for brevity): * min_seqn = 0xFFFD * mbuf_seqn = 0x0010 * offset = 0x0010 - 0xFFFD = 0x13 */ offset = mbuf->seqn - b->min_seqn; /* * action to take depends on offset. * offset < buffer->size: the mbuf fits within the current window of * sequence numbers we can reorder. EXPECTED CASE. * offset > buffer->size: the mbuf is outside the current window. There * are a number of cases to consider: * 1. The packet sequence is just outside the window, then we need * to see about shifting the head pointer and taking any ready * to return packets out of the ring. If there was a delayed * or dropped packet preventing drains from shifting the window * this case will skip over the dropped packet instead, and any * packets dequeued here will be returned on the next drain call. * 2. The packet sequence number is vastly outside our window, taken * here as having offset greater than twice the buffer size. In * this case, the packet is probably an old or late packet that * was previously skipped, so just enqueue the packet for * immediate return on the next drain call, or else return error. */ if (offset < b->order_buf.size) { position = (order_buf->head + offset) & order_buf->mask; order_buf->entries[position] = mbuf; } else if (offset < 2 * b->order_buf.size) { if (rte_reorder_fill_overflow(b, offset + 1 - order_buf->size) < (offset + 1 - order_buf->size)) { /* Put in handling for enqueue straight to output */ rte_errno = ENOSPC; return -1; } offset = mbuf->seqn - b->min_seqn; position = (order_buf->head + offset) & order_buf->mask; order_buf->entries[position] = mbuf; } else { /* Put in handling for enqueue straight to output */ rte_errno = ERANGE; return -1; } return 0; } unsigned int rte_reorder_drain(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs, unsigned max_mbufs) { unsigned int drain_cnt = 0; struct cir_buffer *order_buf = &b->order_buf, *ready_buf = &b->ready_buf; /* Try to fetch requested number of mbufs from ready buffer */ while ((drain_cnt < max_mbufs) && (ready_buf->tail != ready_buf->head)) { mbufs[drain_cnt++] = ready_buf->entries[ready_buf->tail]; ready_buf->tail = (ready_buf->tail + 1) & ready_buf->mask; } /* * If requested number of buffers not fetched from ready buffer, fetch * remaining buffers from order buffer */ while ((drain_cnt < max_mbufs) && (order_buf->entries[order_buf->head] != NULL)) { mbufs[drain_cnt++] = order_buf->entries[order_buf->head]; order_buf->entries[order_buf->head] = NULL; b->min_seqn++; order_buf->head = (order_buf->head + 1) & order_buf->mask; } return drain_cnt; } ================================================ FILE: lib/librte_reorder/rte_reorder.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_REORDER_H_ #define _RTE_REORDER_H_ /** * @file * RTE reorder * * Reorder library is a component which is designed to * provide ordering of out of ordered packets based on * sequence number present in mbuf. * */ #ifdef __cplusplus extern "C" { #endif struct rte_reorder_buffer; /** * Create a new reorder buffer instance * * Allocate memory and initialize a new reorder buffer in that * memory, returning the reorder buffer pointer to the user * * @param name * The name to be given to the reorder buffer instance. * @param socket_id * The NUMA node on which the memory for the reorder buffer * instance is to be reserved. * @param size * Max number of elements that can be stored in the reorder buffer * @return * The initialized reorder buffer instance, or NULL on error * On error case, rte_errno will be set appropriately: * - ENOMEM - no appropriate memory area found in which to create memzone * - EINVAL - invalid parameters */ struct rte_reorder_buffer * rte_reorder_create(const char *name, unsigned socket_id, unsigned int size); /** * Initializes given reorder buffer instance * * @param b * Reorder buffer instance to initialize * @param bufsize * Size of the reorder buffer * @param name * The name to be given to the reorder buffer * @param size * Number of elements that can be stored in reorder buffer * @return * The initialized reorder buffer instance, or NULL on error * On error case, rte_errno will be set appropriately: * - EINVAL - invalid parameters */ struct rte_reorder_buffer * rte_reorder_init(struct rte_reorder_buffer *b, unsigned int bufsize, const char *name, unsigned int size); /** * Find an existing reorder buffer instance * and return a pointer to it. * * @param name * Name of the reorder buffer instacne as passed to rte_reorder_create() * @return * Pointer to reorder buffer instance or NULL if object not found with rte_errno * set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. * reorder instance list */ struct rte_reorder_buffer * rte_reorder_find_existing(const char *name); /** * Reset the given reorder buffer instance with initial values. * * @param b * Reorder buffer instance which has to be reset */ void rte_reorder_reset(struct rte_reorder_buffer *b); /** * Free reorder buffer instance. * * @param b * reorder buffer instance * @return * None */ void rte_reorder_free(struct rte_reorder_buffer *b); /** * Insert given mbuf in reorder buffer in its correct position * * The given mbuf is to be reordered relative to other mbufs in the system. * The mbuf must contain a sequence number which is then used to place * the buffer in the correct position in the reorder buffer. Reordered * packets can later be taken from the buffer using the rte_reorder_drain() * API. * * @param b * Reorder buffer where the mbuf has to be inserted. * @param mbuf * mbuf of packet that needs to be inserted in reorder buffer. * @return * 0 on success * -1 on error * On error case, rte_errno will be set appropriately: * - ENOSPC - Cannot move existing mbufs from reorder buffer to accommodate * ealry mbuf, but it can be accomodated by performing drain and then insert. * - ERANGE - Too early or late mbuf which is vastly out of range of expected * window should be ingnored without any handling. */ int rte_reorder_insert(struct rte_reorder_buffer *b, struct rte_mbuf *mbuf); /** * Fetch reordered buffers * * Returns a set of in-order buffers from the reorder buffer structure. Gaps * may be present in the sequence numbers of the mbuf if packets have been * delayed too long before reaching the reorder window, or have been previously * dropped by the system. * * @param b * Reorder buffer instance from which packets are to be drained * @param mbufs * array of mbufs where reordered packets will be inserted from reorder buffer * @param max_mbufs * the number of elements in the mbufs array. * @return * number of mbuf pointers written to mbufs. 0 <= N < max_mbufs. */ unsigned int rte_reorder_drain(struct rte_reorder_buffer *b, struct rte_mbuf **mbufs, unsigned max_mbufs); #ifdef __cplusplus } #endif #endif /* _RTE_REORDER_H_ */ ================================================ FILE: lib/librte_ring/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_ring.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_ring_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_ring/rte_ring.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Derived from FreeBSD's bufring.c * ************************************************************************** * * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Kip Macy nor the names of other * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_ring.h" TAILQ_HEAD(rte_ring_list, rte_tailq_entry); static struct rte_tailq_elem rte_ring_tailq = { .name = RTE_TAILQ_RING_NAME, }; EAL_REGISTER_TAILQ(rte_ring_tailq) /* true if x is a power of 2 */ #define POWEROF2(x) ((((x)-1) & (x)) == 0) /* return the size of memory occupied by a ring */ ssize_t rte_ring_get_memsize(unsigned count) { ssize_t sz; /* count must be a power of 2 */ if ((!POWEROF2(count)) || (count > RTE_RING_SZ_MASK )) { RTE_LOG(ERR, RING, "Requested size is invalid, must be power of 2, and " "do not exceed the size limit %u\n", RTE_RING_SZ_MASK); return -EINVAL; } sz = sizeof(struct rte_ring) + count * sizeof(void *); sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE); return sz; } int rte_ring_init(struct rte_ring *r, const char *name, unsigned count, unsigned flags) { /* compilation-time checks */ RTE_BUILD_BUG_ON((sizeof(struct rte_ring) & RTE_CACHE_LINE_MASK) != 0); #ifdef RTE_RING_SPLIT_PROD_CONS RTE_BUILD_BUG_ON((offsetof(struct rte_ring, cons) & RTE_CACHE_LINE_MASK) != 0); #endif RTE_BUILD_BUG_ON((offsetof(struct rte_ring, prod) & RTE_CACHE_LINE_MASK) != 0); #ifdef RTE_LIBRTE_RING_DEBUG RTE_BUILD_BUG_ON((sizeof(struct rte_ring_debug_stats) & RTE_CACHE_LINE_MASK) != 0); RTE_BUILD_BUG_ON((offsetof(struct rte_ring, stats) & RTE_CACHE_LINE_MASK) != 0); #endif /* init the ring structure */ memset(r, 0, sizeof(*r)); snprintf(r->name, sizeof(r->name), "%s", name); r->flags = flags; r->prod.watermark = count; r->prod.sp_enqueue = !!(flags & RING_F_SP_ENQ); r->cons.sc_dequeue = !!(flags & RING_F_SC_DEQ); r->prod.size = r->cons.size = count; r->prod.mask = r->cons.mask = count-1; r->prod.head = r->cons.head = 0; r->prod.tail = r->cons.tail = 0; return 0; } /* create the ring */ struct rte_ring * rte_ring_create(const char *name, unsigned count, int socket_id, unsigned flags) { char mz_name[RTE_MEMZONE_NAMESIZE]; struct rte_ring *r; struct rte_tailq_entry *te; const struct rte_memzone *mz; ssize_t ring_size; int mz_flags = 0; struct rte_ring_list* ring_list = NULL; ring_list = RTE_TAILQ_CAST(rte_ring_tailq.head, rte_ring_list); ring_size = rte_ring_get_memsize(count); if (ring_size < 0) { rte_errno = ring_size; return NULL; } te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0); if (te == NULL) { RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n"); rte_errno = ENOMEM; return NULL; } snprintf(mz_name, sizeof(mz_name), "%s%s", RTE_RING_MZ_PREFIX, name); rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* reserve a memory zone for this ring. If we can't get rte_config or * we are secondary process, the memzone_reserve function will set * rte_errno for us appropriately - hence no check in this this function */ mz = rte_memzone_reserve(mz_name, ring_size, socket_id, mz_flags); if (mz != NULL) { r = mz->addr; /* no need to check return value here, we already checked the * arguments above */ rte_ring_init(r, name, count, flags); te->data = (void *) r; TAILQ_INSERT_TAIL(ring_list, te, next); } else { r = NULL; RTE_LOG(ERR, RING, "Cannot reserve memory\n"); rte_free(te); } rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return r; } /* * change the high water mark. If *count* is 0, water marking is * disabled */ int rte_ring_set_water_mark(struct rte_ring *r, unsigned count) { if (count >= r->prod.size) return -EINVAL; /* if count is 0, disable the watermarking */ if (count == 0) count = r->prod.size; r->prod.watermark = count; return 0; } /* dump the status of the ring on the console */ void rte_ring_dump(FILE *f, const struct rte_ring *r) { #ifdef RTE_LIBRTE_RING_DEBUG struct rte_ring_debug_stats sum; unsigned lcore_id; #endif fprintf(f, "ring <%s>@%p\n", r->name, r); fprintf(f, " flags=%x\n", r->flags); fprintf(f, " size=%"PRIu32"\n", r->prod.size); fprintf(f, " ct=%"PRIu32"\n", r->cons.tail); fprintf(f, " ch=%"PRIu32"\n", r->cons.head); fprintf(f, " pt=%"PRIu32"\n", r->prod.tail); fprintf(f, " ph=%"PRIu32"\n", r->prod.head); fprintf(f, " used=%u\n", rte_ring_count(r)); fprintf(f, " avail=%u\n", rte_ring_free_count(r)); if (r->prod.watermark == r->prod.size) fprintf(f, " watermark=0\n"); else fprintf(f, " watermark=%"PRIu32"\n", r->prod.watermark); /* sum and dump statistics */ #ifdef RTE_LIBRTE_RING_DEBUG memset(&sum, 0, sizeof(sum)); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { sum.enq_success_bulk += r->stats[lcore_id].enq_success_bulk; sum.enq_success_objs += r->stats[lcore_id].enq_success_objs; sum.enq_quota_bulk += r->stats[lcore_id].enq_quota_bulk; sum.enq_quota_objs += r->stats[lcore_id].enq_quota_objs; sum.enq_fail_bulk += r->stats[lcore_id].enq_fail_bulk; sum.enq_fail_objs += r->stats[lcore_id].enq_fail_objs; sum.deq_success_bulk += r->stats[lcore_id].deq_success_bulk; sum.deq_success_objs += r->stats[lcore_id].deq_success_objs; sum.deq_fail_bulk += r->stats[lcore_id].deq_fail_bulk; sum.deq_fail_objs += r->stats[lcore_id].deq_fail_objs; } fprintf(f, " size=%"PRIu32"\n", r->prod.size); fprintf(f, " enq_success_bulk=%"PRIu64"\n", sum.enq_success_bulk); fprintf(f, " enq_success_objs=%"PRIu64"\n", sum.enq_success_objs); fprintf(f, " enq_quota_bulk=%"PRIu64"\n", sum.enq_quota_bulk); fprintf(f, " enq_quota_objs=%"PRIu64"\n", sum.enq_quota_objs); fprintf(f, " enq_fail_bulk=%"PRIu64"\n", sum.enq_fail_bulk); fprintf(f, " enq_fail_objs=%"PRIu64"\n", sum.enq_fail_objs); fprintf(f, " deq_success_bulk=%"PRIu64"\n", sum.deq_success_bulk); fprintf(f, " deq_success_objs=%"PRIu64"\n", sum.deq_success_objs); fprintf(f, " deq_fail_bulk=%"PRIu64"\n", sum.deq_fail_bulk); fprintf(f, " deq_fail_objs=%"PRIu64"\n", sum.deq_fail_objs); #else fprintf(f, " no statistics available\n"); #endif } /* dump the status of all rings on the console */ void rte_ring_list_dump(FILE *f) { const struct rte_tailq_entry *te; struct rte_ring_list *ring_list; ring_list = RTE_TAILQ_CAST(rte_ring_tailq.head, rte_ring_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, ring_list, next) { rte_ring_dump(f, (struct rte_ring *) te->data); } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); } /* search a ring from its name */ struct rte_ring * rte_ring_lookup(const char *name) { struct rte_tailq_entry *te; struct rte_ring *r = NULL; struct rte_ring_list *ring_list; ring_list = RTE_TAILQ_CAST(rte_ring_tailq.head, rte_ring_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); TAILQ_FOREACH(te, ring_list, next) { r = (struct rte_ring *) te->data; if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); if (te == NULL) { rte_errno = ENOENT; return NULL; } return r; } ================================================ FILE: lib/librte_ring/rte_ring.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Derived from FreeBSD's bufring.h * ************************************************************************** * * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Kip Macy nor the names of other * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ #ifndef _RTE_RING_H_ #define _RTE_RING_H_ /** * @file * RTE Ring * * The Ring Manager is a fixed-size queue, implemented as a table of * pointers. Head and tail pointers are modified atomically, allowing * concurrent access to it. It has the following features: * * - FIFO (First In First Out) * - Maximum size is fixed; the pointers are stored in a table. * - Lockless implementation. * - Multi- or single-consumer dequeue. * - Multi- or single-producer enqueue. * - Bulk dequeue. * - Bulk enqueue. * * Note: the ring implementation is not preemptable. A lcore must not * be interrupted by another task that uses the same ring. * */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #define RTE_TAILQ_RING_NAME "RTE_RING" enum rte_ring_queue_behavior { RTE_RING_QUEUE_FIXED = 0, /* Enq/Deq a fixed number of items from a ring */ RTE_RING_QUEUE_VARIABLE /* Enq/Deq as many items a possible from ring */ }; #ifdef RTE_LIBRTE_RING_DEBUG /** * A structure that stores the ring statistics (per-lcore). */ struct rte_ring_debug_stats { uint64_t enq_success_bulk; /**< Successful enqueues number. */ uint64_t enq_success_objs; /**< Objects successfully enqueued. */ uint64_t enq_quota_bulk; /**< Successful enqueues above watermark. */ uint64_t enq_quota_objs; /**< Objects enqueued above watermark. */ uint64_t enq_fail_bulk; /**< Failed enqueues number. */ uint64_t enq_fail_objs; /**< Objects that failed to be enqueued. */ uint64_t deq_success_bulk; /**< Successful dequeues number. */ uint64_t deq_success_objs; /**< Objects successfully dequeued. */ uint64_t deq_fail_bulk; /**< Failed dequeues number. */ uint64_t deq_fail_objs; /**< Objects that failed to be dequeued. */ } __rte_cache_aligned; #endif #define RTE_RING_NAMESIZE 32 /**< The maximum length of a ring name. */ #define RTE_RING_MZ_PREFIX "RG_" #ifndef RTE_RING_PAUSE_REP_COUNT #define RTE_RING_PAUSE_REP_COUNT 0 /**< Yield after pause num of times, no yield * if RTE_RING_PAUSE_REP not defined. */ #endif /** * An RTE ring structure. * * The producer and the consumer have a head and a tail index. The particularity * of these index is that they are not between 0 and size(ring). These indexes * are between 0 and 2^32, and we mask their value when we access the ring[] * field. Thanks to this assumption, we can do subtractions between 2 index * values in a modulo-32bit base: that's why the overflow of the indexes is not * a problem. */ struct rte_ring { char name[RTE_RING_NAMESIZE]; /**< Name of the ring. */ int flags; /**< Flags supplied at creation. */ /** Ring producer status. */ struct prod { uint32_t watermark; /**< Maximum items before EDQUOT. */ uint32_t sp_enqueue; /**< True, if single producer. */ uint32_t size; /**< Size of ring. */ uint32_t mask; /**< Mask (size-1) of ring. */ volatile uint32_t head; /**< Producer head. */ volatile uint32_t tail; /**< Producer tail. */ } prod __rte_cache_aligned; /** Ring consumer status. */ struct cons { uint32_t sc_dequeue; /**< True, if single consumer. */ uint32_t size; /**< Size of the ring. */ uint32_t mask; /**< Mask (size-1) of ring. */ volatile uint32_t head; /**< Consumer head. */ volatile uint32_t tail; /**< Consumer tail. */ #ifdef RTE_RING_SPLIT_PROD_CONS } cons __rte_cache_aligned; #else } cons; #endif #ifdef RTE_LIBRTE_RING_DEBUG struct rte_ring_debug_stats stats[RTE_MAX_LCORE]; #endif void * ring[0] __rte_cache_aligned; /**< Memory space of ring starts here. * not volatile so need to be careful * about compiler re-ordering */ }; #define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-producer". */ #define RING_F_SC_DEQ 0x0002 /**< The default dequeue is "single-consumer". */ #define RTE_RING_QUOT_EXCEED (1 << 31) /**< Quota exceed for burst ops */ #define RTE_RING_SZ_MASK (unsigned)(0x0fffffff) /**< Ring size mask */ /** * @internal When debug is enabled, store ring statistics. * @param r * A pointer to the ring. * @param name * The name of the statistics field to increment in the ring. * @param n * The number to add to the object-oriented statistics. */ #ifdef RTE_LIBRTE_RING_DEBUG #define __RING_STAT_ADD(r, name, n) do { \ unsigned __lcore_id = rte_lcore_id(); \ if (__lcore_id < RTE_MAX_LCORE) { \ r->stats[__lcore_id].name##_objs += n; \ r->stats[__lcore_id].name##_bulk += 1; \ } \ } while(0) #else #define __RING_STAT_ADD(r, name, n) do {} while(0) #endif /** * Calculate the memory size needed for a ring * * This function returns the number of bytes needed for a ring, given * the number of elements in it. This value is the sum of the size of * the structure rte_ring and the size of the memory needed by the * objects pointers. The value is aligned to a cache line size. * * @param count * The number of elements in the ring (must be a power of 2). * @return * - The memory size needed for the ring on success. * - -EINVAL if count is not a power of 2. */ ssize_t rte_ring_get_memsize(unsigned count); /** * Initialize a ring structure. * * Initialize a ring structure in memory pointed by "r". The size of the * memory area must be large enough to store the ring structure and the * object table. It is advised to use rte_ring_get_memsize() to get the * appropriate size. * * The ring size is set to *count*, which must be a power of two. Water * marking is disabled by default. The real usable ring size is * *count-1* instead of *count* to differentiate a free ring from an * empty ring. * * The ring is not added in RTE_TAILQ_RING global list. Indeed, the * memory given by the caller may not be shareable among dpdk * processes. * * @param r * The pointer to the ring structure followed by the objects table. * @param name * The name of the ring. * @param count * The number of elements in the ring (must be a power of 2). * @param flags * An OR of the following: * - RING_F_SP_ENQ: If this flag is set, the default behavior when * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` * is "single-producer". Otherwise, it is "multi-producers". * - RING_F_SC_DEQ: If this flag is set, the default behavior when * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` * is "single-consumer". Otherwise, it is "multi-consumers". * @return * 0 on success, or a negative value on error. */ int rte_ring_init(struct rte_ring *r, const char *name, unsigned count, unsigned flags); /** * Create a new ring named *name* in memory. * * This function uses ``memzone_reserve()`` to allocate memory. Then it * calls rte_ring_init() to initialize an empty ring. * * The new ring size is set to *count*, which must be a power of * two. Water marking is disabled by default. The real usable ring size * is *count-1* instead of *count* to differentiate a free ring from an * empty ring. * * The ring is added in RTE_TAILQ_RING list. * * @param name * The name of the ring. * @param count * The size of the ring (must be a power of 2). * @param socket_id * The *socket_id* argument is the socket identifier in case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags * An OR of the following: * - RING_F_SP_ENQ: If this flag is set, the default behavior when * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` * is "single-producer". Otherwise, it is "multi-producers". * - RING_F_SC_DEQ: If this flag is set, the default behavior when * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` * is "single-consumer". Otherwise, it is "multi-consumers". * @return * On success, the pointer to the new allocated ring. NULL on error with * rte_errno set appropriately. Possible errno values include: * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure * - E_RTE_SECONDARY - function was called from a secondary process instance * - EINVAL - count provided is not a power of 2 * - ENOSPC - the maximum number of memzones has already been allocated * - EEXIST - a memzone with the same name already exists * - ENOMEM - no appropriate memory area found in which to create memzone */ struct rte_ring *rte_ring_create(const char *name, unsigned count, int socket_id, unsigned flags); /** * Change the high water mark. * * If *count* is 0, water marking is disabled. Otherwise, it is set to the * *count* value. The *count* value must be greater than 0 and less * than the ring size. * * This function can be called at any time (not necessarily at * initialization). * * @param r * A pointer to the ring structure. * @param count * The new water mark value. * @return * - 0: Success; water mark changed. * - -EINVAL: Invalid water mark value. */ int rte_ring_set_water_mark(struct rte_ring *r, unsigned count); /** * Dump the status of the ring to the console. * * @param f * A pointer to a file for output * @param r * A pointer to the ring structure. */ void rte_ring_dump(FILE *f, const struct rte_ring *r); /* the actual enqueue of pointers on the ring. * Placed here since identical code needed in both * single and multi producer enqueue functions */ #define ENQUEUE_PTRS() do { \ const uint32_t size = r->prod.size; \ uint32_t idx = prod_head & mask; \ if (likely(idx + n < size)) { \ for (i = 0; i < (n & ((~(unsigned)0x3))); i+=4, idx+=4) { \ r->ring[idx] = obj_table[i]; \ r->ring[idx+1] = obj_table[i+1]; \ r->ring[idx+2] = obj_table[i+2]; \ r->ring[idx+3] = obj_table[i+3]; \ } \ switch (n & 0x3) { \ case 3: r->ring[idx++] = obj_table[i++]; \ case 2: r->ring[idx++] = obj_table[i++]; \ case 1: r->ring[idx++] = obj_table[i++]; \ } \ } else { \ for (i = 0; idx < size; i++, idx++)\ r->ring[idx] = obj_table[i]; \ for (idx = 0; i < n; i++, idx++) \ r->ring[idx] = obj_table[i]; \ } \ } while(0) /* the actual copy of pointers on the ring to obj_table. * Placed here since identical code needed in both * single and multi consumer dequeue functions */ #define DEQUEUE_PTRS() do { \ uint32_t idx = cons_head & mask; \ const uint32_t size = r->cons.size; \ if (likely(idx + n < size)) { \ for (i = 0; i < (n & (~(unsigned)0x3)); i+=4, idx+=4) {\ obj_table[i] = r->ring[idx]; \ obj_table[i+1] = r->ring[idx+1]; \ obj_table[i+2] = r->ring[idx+2]; \ obj_table[i+3] = r->ring[idx+3]; \ } \ switch (n & 0x3) { \ case 3: obj_table[i++] = r->ring[idx++]; \ case 2: obj_table[i++] = r->ring[idx++]; \ case 1: obj_table[i++] = r->ring[idx++]; \ } \ } else { \ for (i = 0; idx < size; i++, idx++) \ obj_table[i] = r->ring[idx]; \ for (idx = 0; i < n; i++, idx++) \ obj_table[i] = r->ring[idx]; \ } \ } while (0) /** * @internal Enqueue several objects on the ring (multi-producers safe). * * This function uses a "compare and set" instruction to move the * producer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @param behavior * RTE_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring * RTE_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring * @return * Depend on the behavior value * if behavior = RTE_RING_QUEUE_FIXED * - 0: Success; objects enqueue. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. * if behavior = RTE_RING_QUEUE_VARIABLE * - n: Actual number of objects enqueued. */ static inline int __attribute__((always_inline)) __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table, unsigned n, enum rte_ring_queue_behavior behavior) { uint32_t prod_head, prod_next; uint32_t cons_tail, free_entries; const unsigned max = n; int success; unsigned i, rep = 0; uint32_t mask = r->prod.mask; int ret; /* move prod.head atomically */ do { /* Reset n to the initial burst count */ n = max; prod_head = r->prod.head; cons_tail = r->cons.tail; /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * prod_head > cons_tail). So 'free_entries' is always between 0 * and size(ring)-1. */ free_entries = (mask + cons_tail - prod_head); /* check that we have enough room in ring */ if (unlikely(n > free_entries)) { if (behavior == RTE_RING_QUEUE_FIXED) { __RING_STAT_ADD(r, enq_fail, n); return -ENOBUFS; } else { /* No free entry available */ if (unlikely(free_entries == 0)) { __RING_STAT_ADD(r, enq_fail, n); return 0; } n = free_entries; } } prod_next = prod_head + n; success = rte_atomic32_cmpset(&r->prod.head, prod_head, prod_next); } while (unlikely(success == 0)); /* write entries in ring */ ENQUEUE_PTRS(); rte_compiler_barrier(); /* if we exceed the watermark */ if (unlikely(((mask + 1) - free_entries + n) > r->prod.watermark)) { ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT : (int)(n | RTE_RING_QUOT_EXCEED); __RING_STAT_ADD(r, enq_quota, n); } else { ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n; __RING_STAT_ADD(r, enq_success, n); } /* * If there are other enqueues in progress that preceded us, * we need to wait for them to complete */ while (unlikely(r->prod.tail != prod_head)) { rte_pause(); /* Set RTE_RING_PAUSE_REP_COUNT to avoid spin too long waiting * for other thread finish. It gives pre-empted thread a chance * to proceed and finish with ring dequeue operation. */ if (RTE_RING_PAUSE_REP_COUNT && ++rep == RTE_RING_PAUSE_REP_COUNT) { rep = 0; sched_yield(); } } r->prod.tail = prod_next; return ret; } /** * @internal Enqueue several objects on a ring (NOT multi-producers safe). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @param behavior * RTE_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring * RTE_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring * @return * Depend on the behavior value * if behavior = RTE_RING_QUEUE_FIXED * - 0: Success; objects enqueue. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. * if behavior = RTE_RING_QUEUE_VARIABLE * - n: Actual number of objects enqueued. */ static inline int __attribute__((always_inline)) __rte_ring_sp_do_enqueue(struct rte_ring *r, void * const *obj_table, unsigned n, enum rte_ring_queue_behavior behavior) { uint32_t prod_head, cons_tail; uint32_t prod_next, free_entries; unsigned i; uint32_t mask = r->prod.mask; int ret; prod_head = r->prod.head; cons_tail = r->cons.tail; /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * prod_head > cons_tail). So 'free_entries' is always between 0 * and size(ring)-1. */ free_entries = mask + cons_tail - prod_head; /* check that we have enough room in ring */ if (unlikely(n > free_entries)) { if (behavior == RTE_RING_QUEUE_FIXED) { __RING_STAT_ADD(r, enq_fail, n); return -ENOBUFS; } else { /* No free entry available */ if (unlikely(free_entries == 0)) { __RING_STAT_ADD(r, enq_fail, n); return 0; } n = free_entries; } } prod_next = prod_head + n; r->prod.head = prod_next; /* write entries in ring */ ENQUEUE_PTRS(); rte_compiler_barrier(); /* if we exceed the watermark */ if (unlikely(((mask + 1) - free_entries + n) > r->prod.watermark)) { ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT : (int)(n | RTE_RING_QUOT_EXCEED); __RING_STAT_ADD(r, enq_quota, n); } else { ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n; __RING_STAT_ADD(r, enq_success, n); } r->prod.tail = prod_next; return ret; } /** * @internal Dequeue several objects from a ring (multi-consumers safe). When * the request objects are more than the available objects, only dequeue the * actual number of objects * * This function uses a "compare and set" instruction to move the * consumer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @param behavior * RTE_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring * RTE_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring * @return * Depend on the behavior value * if behavior = RTE_RING_QUEUE_FIXED * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue; no object is * dequeued. * if behavior = RTE_RING_QUEUE_VARIABLE * - n: Actual number of objects dequeued. */ static inline int __attribute__((always_inline)) __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table, unsigned n, enum rte_ring_queue_behavior behavior) { uint32_t cons_head, prod_tail; uint32_t cons_next, entries; const unsigned max = n; int success; unsigned i, rep = 0; uint32_t mask = r->prod.mask; /* move cons.head atomically */ do { /* Restore n as it may change every loop */ n = max; cons_head = r->cons.head; prod_tail = r->prod.tail; /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * cons_head > prod_tail). So 'entries' is always between 0 * and size(ring)-1. */ entries = (prod_tail - cons_head); /* Set the actual entries for dequeue */ if (n > entries) { if (behavior == RTE_RING_QUEUE_FIXED) { __RING_STAT_ADD(r, deq_fail, n); return -ENOENT; } else { if (unlikely(entries == 0)){ __RING_STAT_ADD(r, deq_fail, n); return 0; } n = entries; } } cons_next = cons_head + n; success = rte_atomic32_cmpset(&r->cons.head, cons_head, cons_next); } while (unlikely(success == 0)); /* copy in table */ DEQUEUE_PTRS(); rte_compiler_barrier(); /* * If there are other dequeues in progress that preceded us, * we need to wait for them to complete */ while (unlikely(r->cons.tail != cons_head)) { rte_pause(); /* Set RTE_RING_PAUSE_REP_COUNT to avoid spin too long waiting * for other thread finish. It gives pre-empted thread a chance * to proceed and finish with ring dequeue operation. */ if (RTE_RING_PAUSE_REP_COUNT && ++rep == RTE_RING_PAUSE_REP_COUNT) { rep = 0; sched_yield(); } } __RING_STAT_ADD(r, deq_success, n); r->cons.tail = cons_next; return behavior == RTE_RING_QUEUE_FIXED ? 0 : n; } /** * @internal Dequeue several objects from a ring (NOT multi-consumers safe). * When the request objects are more than the available objects, only dequeue * the actual number of objects * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @param behavior * RTE_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring * RTE_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring * @return * Depend on the behavior value * if behavior = RTE_RING_QUEUE_FIXED * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue; no object is * dequeued. * if behavior = RTE_RING_QUEUE_VARIABLE * - n: Actual number of objects dequeued. */ static inline int __attribute__((always_inline)) __rte_ring_sc_do_dequeue(struct rte_ring *r, void **obj_table, unsigned n, enum rte_ring_queue_behavior behavior) { uint32_t cons_head, prod_tail; uint32_t cons_next, entries; unsigned i; uint32_t mask = r->prod.mask; cons_head = r->cons.head; prod_tail = r->prod.tail; /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * cons_head > prod_tail). So 'entries' is always between 0 * and size(ring)-1. */ entries = prod_tail - cons_head; if (n > entries) { if (behavior == RTE_RING_QUEUE_FIXED) { __RING_STAT_ADD(r, deq_fail, n); return -ENOENT; } else { if (unlikely(entries == 0)){ __RING_STAT_ADD(r, deq_fail, n); return 0; } n = entries; } } cons_next = cons_head + n; r->cons.head = cons_next; /* copy in table */ DEQUEUE_PTRS(); rte_compiler_barrier(); __RING_STAT_ADD(r, deq_success, n); r->cons.tail = cons_next; return behavior == RTE_RING_QUEUE_FIXED ? 0 : n; } /** * Enqueue several objects on the ring (multi-producers safe). * * This function uses a "compare and set" instruction to move the * producer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - 0: Success; objects enqueue. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_mp_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned n) { return __rte_ring_mp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED); } /** * Enqueue several objects on a ring (NOT multi-producers safe). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - 0: Success; objects enqueued. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_sp_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned n) { return __rte_ring_sp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED); } /** * Enqueue several objects on a ring. * * This function calls the multi-producer or the single-producer * version depending on the default behavior that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - 0: Success; objects enqueued. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned n) { if (r->prod.sp_enqueue) return rte_ring_sp_enqueue_bulk(r, obj_table, n); else return rte_ring_mp_enqueue_bulk(r, obj_table, n); } /** * Enqueue one object on a ring (multi-producers safe). * * This function uses a "compare and set" instruction to move the * producer index atomically. * * @param r * A pointer to the ring structure. * @param obj * A pointer to the object to be added. * @return * - 0: Success; objects enqueued. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_mp_enqueue(struct rte_ring *r, void *obj) { return rte_ring_mp_enqueue_bulk(r, &obj, 1); } /** * Enqueue one object on a ring (NOT multi-producers safe). * * @param r * A pointer to the ring structure. * @param obj * A pointer to the object to be added. * @return * - 0: Success; objects enqueued. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_sp_enqueue(struct rte_ring *r, void *obj) { return rte_ring_sp_enqueue_bulk(r, &obj, 1); } /** * Enqueue one object on a ring. * * This function calls the multi-producer or the single-producer * version, depending on the default behaviour that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj * A pointer to the object to be added. * @return * - 0: Success; objects enqueued. * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the * high water mark is exceeded. * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. */ static inline int __attribute__((always_inline)) rte_ring_enqueue(struct rte_ring *r, void *obj) { if (r->prod.sp_enqueue) return rte_ring_sp_enqueue(r, obj); else return rte_ring_mp_enqueue(r, obj); } /** * Dequeue several objects from a ring (multi-consumers safe). * * This function uses a "compare and set" instruction to move the * consumer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @return * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue; no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_mc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n) { return __rte_ring_mc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED); } /** * Dequeue several objects from a ring (NOT multi-consumers safe). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table, * must be strictly positive. * @return * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue; no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_sc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n) { return __rte_ring_sc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED); } /** * Dequeue several objects from a ring. * * This function calls the multi-consumers or the single-consumer * version, depending on the default behaviour that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @return * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue, no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n) { if (r->cons.sc_dequeue) return rte_ring_sc_dequeue_bulk(r, obj_table, n); else return rte_ring_mc_dequeue_bulk(r, obj_table, n); } /** * Dequeue one object from a ring (multi-consumers safe). * * This function uses a "compare and set" instruction to move the * consumer index atomically. * * @param r * A pointer to the ring structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue; no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_mc_dequeue(struct rte_ring *r, void **obj_p) { return rte_ring_mc_dequeue_bulk(r, obj_p, 1); } /** * Dequeue one object from a ring (NOT multi-consumers safe). * * @param r * A pointer to the ring structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success; objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue, no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_sc_dequeue(struct rte_ring *r, void **obj_p) { return rte_ring_sc_dequeue_bulk(r, obj_p, 1); } /** * Dequeue one object from a ring. * * This function calls the multi-consumers or the single-consumer * version depending on the default behaviour that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj_p * A pointer to a void * pointer (object) that will be filled. * @return * - 0: Success, objects dequeued. * - -ENOENT: Not enough entries in the ring to dequeue, no object is * dequeued. */ static inline int __attribute__((always_inline)) rte_ring_dequeue(struct rte_ring *r, void **obj_p) { if (r->cons.sc_dequeue) return rte_ring_sc_dequeue(r, obj_p); else return rte_ring_mc_dequeue(r, obj_p); } /** * Test if a ring is full. * * @param r * A pointer to the ring structure. * @return * - 1: The ring is full. * - 0: The ring is not full. */ static inline int rte_ring_full(const struct rte_ring *r) { uint32_t prod_tail = r->prod.tail; uint32_t cons_tail = r->cons.tail; return (((cons_tail - prod_tail - 1) & r->prod.mask) == 0); } /** * Test if a ring is empty. * * @param r * A pointer to the ring structure. * @return * - 1: The ring is empty. * - 0: The ring is not empty. */ static inline int rte_ring_empty(const struct rte_ring *r) { uint32_t prod_tail = r->prod.tail; uint32_t cons_tail = r->cons.tail; return !!(cons_tail == prod_tail); } /** * Return the number of entries in a ring. * * @param r * A pointer to the ring structure. * @return * The number of entries in the ring. */ static inline unsigned rte_ring_count(const struct rte_ring *r) { uint32_t prod_tail = r->prod.tail; uint32_t cons_tail = r->cons.tail; return ((prod_tail - cons_tail) & r->prod.mask); } /** * Return the number of free entries in a ring. * * @param r * A pointer to the ring structure. * @return * The number of free entries in the ring. */ static inline unsigned rte_ring_free_count(const struct rte_ring *r) { uint32_t prod_tail = r->prod.tail; uint32_t cons_tail = r->cons.tail; return ((cons_tail - prod_tail - 1) & r->prod.mask); } /** * Dump the status of all rings on the console * * @param f * A pointer to a file for output */ void rte_ring_list_dump(FILE *f); /** * Search a ring from its name * * @param name * The name of the ring. * @return * The pointer to the ring matching the name, or NULL if not found, * with rte_errno set appropriately. Possible rte_errno values include: * - ENOENT - required entry not available to return. */ struct rte_ring *rte_ring_lookup(const char *name); /** * Enqueue several objects on the ring (multi-producers safe). * * This function uses a "compare and set" instruction to move the * producer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - n: Actual number of objects enqueued. */ static inline unsigned __attribute__((always_inline)) rte_ring_mp_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned n) { return __rte_ring_mp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE); } /** * Enqueue several objects on a ring (NOT multi-producers safe). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - n: Actual number of objects enqueued. */ static inline unsigned __attribute__((always_inline)) rte_ring_sp_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned n) { return __rte_ring_sp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE); } /** * Enqueue several objects on a ring. * * This function calls the multi-producer or the single-producer * version depending on the default behavior that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects). * @param n * The number of objects to add in the ring from the obj_table. * @return * - n: Actual number of objects enqueued. */ static inline unsigned __attribute__((always_inline)) rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned n) { if (r->prod.sp_enqueue) return rte_ring_sp_enqueue_burst(r, obj_table, n); else return rte_ring_mp_enqueue_burst(r, obj_table, n); } /** * Dequeue several objects from a ring (multi-consumers safe). When the request * objects are more than the available objects, only dequeue the actual number * of objects * * This function uses a "compare and set" instruction to move the * consumer index atomically. * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @return * - n: Actual number of objects dequeued, 0 if ring is empty */ static inline unsigned __attribute__((always_inline)) rte_ring_mc_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned n) { return __rte_ring_mc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE); } /** * Dequeue several objects from a ring (NOT multi-consumers safe).When the * request objects are more than the available objects, only dequeue the * actual number of objects * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @return * - n: Actual number of objects dequeued, 0 if ring is empty */ static inline unsigned __attribute__((always_inline)) rte_ring_sc_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned n) { return __rte_ring_sc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE); } /** * Dequeue multiple objects from a ring up to a maximum number. * * This function calls the multi-consumers or the single-consumer * version, depending on the default behaviour that was specified at * ring creation time (see flags). * * @param r * A pointer to the ring structure. * @param obj_table * A pointer to a table of void * pointers (objects) that will be filled. * @param n * The number of objects to dequeue from the ring to the obj_table. * @return * - Number of objects dequeued */ static inline unsigned __attribute__((always_inline)) rte_ring_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned n) { if (r->cons.sc_dequeue) return rte_ring_sc_dequeue_burst(r, obj_table, n); else return rte_ring_mc_dequeue_burst(r, obj_table, n); } #ifdef __cplusplus } #endif #endif /* _RTE_RING_H_ */ ================================================ FILE: lib/librte_sched/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_sched.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) CFLAGS_rte_red.o := -D_GNU_SOURCE EXPORT_MAP := rte_sched_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_SCHED) += rte_sched.c rte_red.c rte_approx.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_SCHED)-include := rte_sched.h rte_bitmap.h rte_sched_common.h rte_red.h rte_approx.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_SCHED) += lib/librte_mempool lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_SCHED) += lib/librte_net lib/librte_timer include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_sched/rte_approx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "rte_approx.h" /* * Based on paper "Approximating Rational Numbers by Fractions" by Michal * Forisek forisek@dcs.fmph.uniba.sk * * Given a rational number alpha with 0 < alpha < 1 and a precision d, the goal * is to find positive integers p, q such that alpha - d < p/q < alpha + d, and * q is minimal. * * http://people.ksp.sk/~misof/publications/2007approx.pdf */ /* fraction comparison: compare (a/b) and (c/d) */ static inline uint32_t less(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { return (a*d < b*c); } static inline uint32_t less_or_equal(uint32_t a, uint32_t b, uint32_t c, uint32_t d) { return (a*d <= b*c); } /* check whether a/b is a valid approximation */ static inline uint32_t matches(uint32_t a, uint32_t b, uint32_t alpha_num, uint32_t d_num, uint32_t denum) { if (less_or_equal(a, b, alpha_num - d_num, denum)) return 0; if (less(a ,b, alpha_num + d_num, denum)) return 1; return 0; } static inline void find_exact_solution_left(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b, uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) { uint32_t k_num = denum * p_b - (alpha_num + d_num) * q_b; uint32_t k_denum = (alpha_num + d_num) * q_a - denum * p_a; uint32_t k = (k_num / k_denum) + 1; *p = p_b + k * p_a; *q = q_b + k * q_a; } static inline void find_exact_solution_right(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b, uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) { uint32_t k_num = - denum * p_b + (alpha_num - d_num) * q_b; uint32_t k_denum = - (alpha_num - d_num) * q_a + denum * p_a; uint32_t k = (k_num / k_denum) + 1; *p = p_b + k * p_a; *q = q_b + k * q_a; } static int find_best_rational_approximation(uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) { uint32_t p_a, q_a, p_b, q_b; /* check assumptions on the inputs */ if (!((0 < d_num) && (d_num < alpha_num) && (alpha_num < denum) && (d_num + alpha_num < denum))) { return -1; } /* set initial bounds for the search */ p_a = 0; q_a = 1; p_b = 1; q_b = 1; while (1) { uint32_t new_p_a, new_q_a, new_p_b, new_q_b; uint32_t x_num, x_denum, x; int aa, bb; /* compute the number of steps to the left */ x_num = denum * p_b - alpha_num * q_b; x_denum = - denum * p_a + alpha_num * q_a; x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */ /* check whether we have a valid approximation */ aa = matches(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum); bb = matches(p_b + (x-1) * p_a, q_b + (x - 1) * q_a, alpha_num, d_num, denum); if (aa || bb) { find_exact_solution_left(p_a, q_a, p_b, q_b, alpha_num, d_num, denum, p, q); return 0; } /* update the interval */ new_p_a = p_b + (x - 1) * p_a ; new_q_a = q_b + (x - 1) * q_a; new_p_b = p_b + x * p_a ; new_q_b = q_b + x * q_a; p_a = new_p_a ; q_a = new_q_a; p_b = new_p_b ; q_b = new_q_b; /* compute the number of steps to the right */ x_num = alpha_num * q_b - denum * p_b; x_denum = - alpha_num * q_a + denum * p_a; x = (x_num + x_denum - 1) / x_denum; /* x = ceil(x_num / x_denum) */ /* check whether we have a valid approximation */ aa = matches(p_b + x * p_a, q_b + x * q_a, alpha_num, d_num, denum); bb = matches(p_b + (x - 1) * p_a, q_b + (x - 1) * q_a, alpha_num, d_num, denum); if (aa || bb) { find_exact_solution_right(p_a, q_a, p_b, q_b, alpha_num, d_num, denum, p, q); return 0; } /* update the interval */ new_p_a = p_b + (x - 1) * p_a; new_q_a = q_b + (x - 1) * q_a; new_p_b = p_b + x * p_a; new_q_b = q_b + x * q_a; p_a = new_p_a; q_a = new_q_a; p_b = new_p_b; q_b = new_q_b; } } int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q) { uint32_t alpha_num, d_num, denum; /* Check input arguments */ if (!((0.0 < d) && (d < alpha) && (alpha < 1.0))) { return -1; } if ((p == NULL) || (q == NULL)) { return -2; } /* Compute alpha_num, d_num and denum */ denum = 1; while (d < 1) { alpha *= 10; d *= 10; denum *= 10; } alpha_num = (uint32_t) alpha; d_num = (uint32_t) d; /* Perform approximation */ return find_best_rational_approximation(alpha_num, d_num, denum, p, q); } ================================================ FILE: lib/librte_sched/rte_approx.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_APPROX_H__ #define __INCLUDE_RTE_APPROX_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Rational Approximation * * Given a rational number alpha with 0 < alpha < 1 and a precision d, the goal * is to find positive integers p, q such that alpha - d < p/q < alpha + d, and * q is minimal. * ***/ #include /** * Find best rational approximation * * @param alpha * Rational number to approximate * @param d * Precision for the rational approximation * @param p * Pointer to pre-allocated space where the numerator of the rational * approximation will be stored when operation is successful * @param q * Pointer to pre-allocated space where the denominator of the rational * approximation will be stored when operation is successful * @return * 0 upon success, error code otherwise */ int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q); #ifdef __cplusplus } #endif #endif /* __INCLUDE_RTE_APPROX_H__ */ ================================================ FILE: lib/librte_sched/rte_bitmap.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_BITMAP_H__ #define __INCLUDE_RTE_BITMAP_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Bitmap * * The bitmap component provides a mechanism to manage large arrays of bits * through bit get/set/clear and bit array scan operations. * * The bitmap scan operation is optimized for 64-bit CPUs using 64-byte cache * lines. The bitmap is hierarchically organized using two arrays (array1 and * array2), with each bit in array1 being associated with a full cache line * (512 bits) of bitmap bits, which are stored in array2: the bit in array1 is * set only when there is at least one bit set within its associated array2 * bits, otherwise the bit in array1 is cleared. The read and write operations * for array1 and array2 are always done in slabs of 64 bits. * * This bitmap is not thread safe. For lock free operation on a specific bitmap * instance, a single writer thread performing bit set/clear operations is * allowed, only the writer thread can do bitmap scan operations, while there * can be several reader threads performing bit get operations in parallel with * the writer thread. When the use of locking primitives is acceptable, the * serialization of the bit set/clear and bitmap scan operations needs to be * enforced by the caller, while the bit get operation does not require locking * the bitmap. * ***/ #include #include #include #include #include #ifndef RTE_BITMAP_OPTIMIZATIONS #define RTE_BITMAP_OPTIMIZATIONS 1 #endif #if RTE_BITMAP_OPTIMIZATIONS #include #endif /* Slab */ #define RTE_BITMAP_SLAB_BIT_SIZE 64 #define RTE_BITMAP_SLAB_BIT_SIZE_LOG2 6 #define RTE_BITMAP_SLAB_BIT_MASK (RTE_BITMAP_SLAB_BIT_SIZE - 1) /* Cache line (CL) */ #define RTE_BITMAP_CL_BIT_SIZE (RTE_CACHE_LINE_SIZE * 8) #define RTE_BITMAP_CL_BIT_SIZE_LOG2 9 #define RTE_BITMAP_CL_BIT_MASK (RTE_BITMAP_CL_BIT_SIZE - 1) #define RTE_BITMAP_CL_SLAB_SIZE (RTE_BITMAP_CL_BIT_SIZE / RTE_BITMAP_SLAB_BIT_SIZE) #define RTE_BITMAP_CL_SLAB_SIZE_LOG2 3 #define RTE_BITMAP_CL_SLAB_MASK (RTE_BITMAP_CL_SLAB_SIZE - 1) /** Bitmap data structure */ struct rte_bitmap { /* Context for array1 and array2 */ uint64_t *array1; /**< Bitmap array1 */ uint64_t *array2; /**< Bitmap array2 */ uint32_t array1_size; /**< Number of 64-bit slabs in array1 that are actually used */ uint32_t array2_size; /**< Number of 64-bit slabs in array2 */ /* Context for the "scan next" operation */ uint32_t index1; /**< Bitmap scan: Index of current array1 slab */ uint32_t offset1; /**< Bitmap scan: Offset of current bit within current array1 slab */ uint32_t index2; /**< Bitmap scan: Index of current array2 slab */ uint32_t go2; /**< Bitmap scan: Go/stop condition for current array2 cache line */ /* Storage space for array1 and array2 */ uint8_t memory[0]; }; static inline void __rte_bitmap_index1_inc(struct rte_bitmap *bmp) { bmp->index1 = (bmp->index1 + 1) & (bmp->array1_size - 1); } static inline uint64_t __rte_bitmap_mask1_get(struct rte_bitmap *bmp) { return ((~1lu) << bmp->offset1); } static inline void __rte_bitmap_index2_set(struct rte_bitmap *bmp) { bmp->index2 = (((bmp->index1 << RTE_BITMAP_SLAB_BIT_SIZE_LOG2) + bmp->offset1) << RTE_BITMAP_CL_SLAB_SIZE_LOG2); } #if RTE_BITMAP_OPTIMIZATIONS static inline int rte_bsf64(uint64_t slab, uint32_t *pos) { if (likely(slab == 0)) { return 0; } *pos = __builtin_ctzll(slab); return 1; } #else static inline int rte_bsf64(uint64_t slab, uint32_t *pos) { uint64_t mask; uint32_t i; if (likely(slab == 0)) { return 0; } for (i = 0, mask = 1; i < RTE_BITMAP_SLAB_BIT_SIZE; i ++, mask <<= 1) { if (unlikely(slab & mask)) { *pos = i; return 1; } } return 0; } #endif static inline uint32_t __rte_bitmap_get_memory_footprint(uint32_t n_bits, uint32_t *array1_byte_offset, uint32_t *array1_slabs, uint32_t *array2_byte_offset, uint32_t *array2_slabs) { uint32_t n_slabs_context, n_slabs_array1, n_cache_lines_context_and_array1; uint32_t n_cache_lines_array2; uint32_t n_bytes_total; n_cache_lines_array2 = (n_bits + RTE_BITMAP_CL_BIT_SIZE - 1) / RTE_BITMAP_CL_BIT_SIZE; n_slabs_array1 = (n_cache_lines_array2 + RTE_BITMAP_SLAB_BIT_SIZE - 1) / RTE_BITMAP_SLAB_BIT_SIZE; n_slabs_array1 = rte_align32pow2(n_slabs_array1); n_slabs_context = (sizeof(struct rte_bitmap) + (RTE_BITMAP_SLAB_BIT_SIZE / 8) - 1) / (RTE_BITMAP_SLAB_BIT_SIZE / 8); n_cache_lines_context_and_array1 = (n_slabs_context + n_slabs_array1 + RTE_BITMAP_CL_SLAB_SIZE - 1) / RTE_BITMAP_CL_SLAB_SIZE; n_bytes_total = (n_cache_lines_context_and_array1 + n_cache_lines_array2) * RTE_CACHE_LINE_SIZE; if (array1_byte_offset) { *array1_byte_offset = n_slabs_context * (RTE_BITMAP_SLAB_BIT_SIZE / 8); } if (array1_slabs) { *array1_slabs = n_slabs_array1; } if (array2_byte_offset) { *array2_byte_offset = n_cache_lines_context_and_array1 * RTE_CACHE_LINE_SIZE; } if (array2_slabs) { *array2_slabs = n_cache_lines_array2 * RTE_BITMAP_CL_SLAB_SIZE; } return n_bytes_total; } static inline void __rte_bitmap_scan_init(struct rte_bitmap *bmp) { bmp->index1 = bmp->array1_size - 1; bmp->offset1 = RTE_BITMAP_SLAB_BIT_SIZE - 1; __rte_bitmap_index2_set(bmp); bmp->index2 += RTE_BITMAP_CL_SLAB_SIZE; bmp->go2 = 0; } /** * Bitmap memory footprint calculation * * @param n_bits * Number of bits in the bitmap * @return * Bitmap memory footprint measured in bytes on success, 0 on error */ static inline uint32_t rte_bitmap_get_memory_footprint(uint32_t n_bits) { /* Check input arguments */ if (n_bits == 0) { return 0; } return __rte_bitmap_get_memory_footprint(n_bits, NULL, NULL, NULL, NULL); } /** * Bitmap initialization * * @param mem_size * Minimum expected size of bitmap. * @param mem * Base address of array1 and array2. * @param n_bits * Number of pre-allocated bits in array2. Must be non-zero and multiple of 512. * @return * Handle to bitmap instance. */ static inline struct rte_bitmap * rte_bitmap_init(uint32_t n_bits, uint8_t *mem, uint32_t mem_size) { struct rte_bitmap *bmp; uint32_t array1_byte_offset, array1_slabs, array2_byte_offset, array2_slabs; uint32_t size; /* Check input arguments */ if (n_bits == 0) { return NULL; } if ((mem == NULL) || (((uintptr_t) mem) & RTE_CACHE_LINE_MASK)) { return NULL; } size = __rte_bitmap_get_memory_footprint(n_bits, &array1_byte_offset, &array1_slabs, &array2_byte_offset, &array2_slabs); if (size < mem_size) { return NULL; } /* Setup bitmap */ memset(mem, 0, size); bmp = (struct rte_bitmap *) mem; bmp->array1 = (uint64_t *) &mem[array1_byte_offset]; bmp->array1_size = array1_slabs; bmp->array2 = (uint64_t *) &mem[array2_byte_offset]; bmp->array2_size = array2_slabs; __rte_bitmap_scan_init(bmp); return bmp; } /** * Bitmap free * * @param bmp * Handle to bitmap instance * @return * 0 upon success, error code otherwise */ static inline int rte_bitmap_free(struct rte_bitmap *bmp) { /* Check input arguments */ if (bmp == NULL) { return -1; } return 0; } /** * Bitmap reset * * @param bmp * Handle to bitmap instance */ static inline void rte_bitmap_reset(struct rte_bitmap *bmp) { memset(bmp->array1, 0, bmp->array1_size * sizeof(uint64_t)); memset(bmp->array2, 0, bmp->array2_size * sizeof(uint64_t)); __rte_bitmap_scan_init(bmp); } /** * Bitmap location prefetch into CPU L1 cache * * @param bmp * Handle to bitmap instance * @param pos * Bit position * @return * 0 upon success, error code otherwise */ static inline void rte_bitmap_prefetch0(struct rte_bitmap *bmp, uint32_t pos) { uint64_t *slab2; uint32_t index2; index2 = pos >> RTE_BITMAP_SLAB_BIT_SIZE_LOG2; slab2 = bmp->array2 + index2; rte_prefetch0((void *) slab2); } /** * Bitmap bit get * * @param bmp * Handle to bitmap instance * @param pos * Bit position * @return * 0 when bit is cleared, non-zero when bit is set */ static inline uint64_t rte_bitmap_get(struct rte_bitmap *bmp, uint32_t pos) { uint64_t *slab2; uint32_t index2, offset2; index2 = pos >> RTE_BITMAP_SLAB_BIT_SIZE_LOG2; offset2 = pos & RTE_BITMAP_SLAB_BIT_MASK; slab2 = bmp->array2 + index2; return ((*slab2) & (1lu << offset2)); } /** * Bitmap bit set * * @param bmp * Handle to bitmap instance * @param pos * Bit position */ static inline void rte_bitmap_set(struct rte_bitmap *bmp, uint32_t pos) { uint64_t *slab1, *slab2; uint32_t index1, index2, offset1, offset2; /* Set bit in array2 slab and set bit in array1 slab */ index2 = pos >> RTE_BITMAP_SLAB_BIT_SIZE_LOG2; offset2 = pos & RTE_BITMAP_SLAB_BIT_MASK; index1 = pos >> (RTE_BITMAP_SLAB_BIT_SIZE_LOG2 + RTE_BITMAP_CL_BIT_SIZE_LOG2); offset1 = (pos >> RTE_BITMAP_CL_BIT_SIZE_LOG2) & RTE_BITMAP_SLAB_BIT_MASK; slab2 = bmp->array2 + index2; slab1 = bmp->array1 + index1; *slab2 |= 1lu << offset2; *slab1 |= 1lu << offset1; } /** * Bitmap slab set * * @param bmp * Handle to bitmap instance * @param pos * Bit position identifying the array2 slab * @param slab * Value to be assigned to the 64-bit slab in array2 */ static inline void rte_bitmap_set_slab(struct rte_bitmap *bmp, uint32_t pos, uint64_t slab) { uint64_t *slab1, *slab2; uint32_t index1, index2, offset1; /* Set bits in array2 slab and set bit in array1 slab */ index2 = pos >> RTE_BITMAP_SLAB_BIT_SIZE_LOG2; index1 = pos >> (RTE_BITMAP_SLAB_BIT_SIZE_LOG2 + RTE_BITMAP_CL_BIT_SIZE_LOG2); offset1 = (pos >> RTE_BITMAP_CL_BIT_SIZE_LOG2) & RTE_BITMAP_SLAB_BIT_MASK; slab2 = bmp->array2 + index2; slab1 = bmp->array1 + index1; *slab2 |= slab; *slab1 |= 1lu << offset1; } static inline uint64_t __rte_bitmap_line_not_empty(uint64_t *slab2) { uint64_t v1, v2, v3, v4; v1 = slab2[0] | slab2[1]; v2 = slab2[2] | slab2[3]; v3 = slab2[4] | slab2[5]; v4 = slab2[6] | slab2[7]; v1 |= v2; v3 |= v4; return (v1 | v3); } /** * Bitmap bit clear * * @param bmp * Handle to bitmap instance * @param pos * Bit position */ static inline void rte_bitmap_clear(struct rte_bitmap *bmp, uint32_t pos) { uint64_t *slab1, *slab2; uint32_t index1, index2, offset1, offset2; /* Clear bit in array2 slab */ index2 = pos >> RTE_BITMAP_SLAB_BIT_SIZE_LOG2; offset2 = pos & RTE_BITMAP_SLAB_BIT_MASK; slab2 = bmp->array2 + index2; /* Return if array2 slab is not all-zeros */ *slab2 &= ~(1lu << offset2); if (*slab2){ return; } /* Check the entire cache line of array2 for all-zeros */ index2 &= ~ RTE_BITMAP_CL_SLAB_MASK; slab2 = bmp->array2 + index2; if (__rte_bitmap_line_not_empty(slab2)) { return; } /* The array2 cache line is all-zeros, so clear bit in array1 slab */ index1 = pos >> (RTE_BITMAP_SLAB_BIT_SIZE_LOG2 + RTE_BITMAP_CL_BIT_SIZE_LOG2); offset1 = (pos >> RTE_BITMAP_CL_BIT_SIZE_LOG2) & RTE_BITMAP_SLAB_BIT_MASK; slab1 = bmp->array1 + index1; *slab1 &= ~(1lu << offset1); return; } static inline int __rte_bitmap_scan_search(struct rte_bitmap *bmp) { uint64_t value1; uint32_t i; /* Check current array1 slab */ value1 = bmp->array1[bmp->index1]; value1 &= __rte_bitmap_mask1_get(bmp); if (rte_bsf64(value1, &bmp->offset1)) { return 1; } __rte_bitmap_index1_inc(bmp); bmp->offset1 = 0; /* Look for another array1 slab */ for (i = 0; i < bmp->array1_size; i ++, __rte_bitmap_index1_inc(bmp)) { value1 = bmp->array1[bmp->index1]; if (rte_bsf64(value1, &bmp->offset1)) { return 1; } } return 0; } static inline void __rte_bitmap_scan_read_init(struct rte_bitmap *bmp) { __rte_bitmap_index2_set(bmp); bmp->go2 = 1; rte_prefetch1((void *)(bmp->array2 + bmp->index2 + 8)); } static inline int __rte_bitmap_scan_read(struct rte_bitmap *bmp, uint32_t *pos, uint64_t *slab) { uint64_t *slab2; slab2 = bmp->array2 + bmp->index2; for ( ; bmp->go2 ; bmp->index2 ++, slab2 ++, bmp->go2 = bmp->index2 & RTE_BITMAP_CL_SLAB_MASK) { if (*slab2) { *pos = bmp->index2 << RTE_BITMAP_SLAB_BIT_SIZE_LOG2; *slab = *slab2; bmp->index2 ++; slab2 ++; bmp->go2 = bmp->index2 & RTE_BITMAP_CL_SLAB_MASK; return 1; } } return 0; } /** * Bitmap scan (with automatic wrap-around) * * @param bmp * Handle to bitmap instance * @param pos * When function call returns 1, pos contains the position of the next set * bit, otherwise not modified * @param slab * When function call returns 1, slab contains the value of the entire 64-bit * slab where the bit indicated by pos is located. Slabs are always 64-bit * aligned, so the position of the first bit of the slab (this bit is not * necessarily set) is pos / 64. Once a slab has been returned by the bitmap * scan operation, the internal pointers of the bitmap are updated to point * after this slab, so the same slab will not be returned again if it * contains more than one bit which is set. When function call returns 0, * slab is not modified. * @return * 0 if there is no bit set in the bitmap, 1 otherwise */ static inline int rte_bitmap_scan(struct rte_bitmap *bmp, uint32_t *pos, uint64_t *slab) { /* Return data from current array2 line if available */ if (__rte_bitmap_scan_read(bmp, pos, slab)) { return 1; } /* Look for non-empty array2 line */ if (__rte_bitmap_scan_search(bmp)) { __rte_bitmap_scan_read_init(bmp); __rte_bitmap_scan_read(bmp, pos, slab); return 1; } /* Empty bitmap */ return 0; } #ifdef __cplusplus } #endif #endif /* __INCLUDE_RTE_BITMAP_H__ */ ================================================ FILE: lib/librte_sched/rte_red.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "rte_red.h" #include #include #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* conversion may lose significant bits */ #endif static int rte_red_init_done = 0; /**< Flag to indicate that global initialisation is done */ uint32_t rte_red_rand_val = 0; /**< Random value cache */ uint32_t rte_red_rand_seed = 0; /**< Seed for random number generation */ /** * table[i] = log2(1-Wq) * Scale * -1 * Wq = 1/(2^i) */ uint16_t rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM]; /** * table[i] = 2^(i/16) * Scale */ uint16_t rte_red_pow2_frac_inv[16]; /** * @brief Initialize tables used to compute average * queue size when queue is empty. */ static void __rte_red_init_tables(void) { uint32_t i = 0; double scale = 0.0; double table_size = 0.0; scale = (double)(1 << RTE_RED_SCALING); table_size = (double)(RTE_DIM(rte_red_pow2_frac_inv)); for (i = 0; i < RTE_DIM(rte_red_pow2_frac_inv); i++) { double m = (double)i; rte_red_pow2_frac_inv[i] = (uint16_t) round(scale / pow(2, m / table_size)); } scale = 1024.0; RTE_RED_ASSERT(RTE_RED_WQ_LOG2_NUM == RTE_DIM(rte_red_log2_1_minus_Wq)); for (i = RTE_RED_WQ_LOG2_MIN; i <= RTE_RED_WQ_LOG2_MAX; i++) { double n = (double)i; double Wq = pow(2, -n); uint32_t index = i - RTE_RED_WQ_LOG2_MIN; rte_red_log2_1_minus_Wq[index] = (uint16_t) round(-1.0 * scale * log2(1.0 - Wq)); /** * Table entry of zero, corresponds to a Wq of zero * which is not valid (avg would remain constant no * matter how long the queue is empty). So we have * to check for zero and round up to one. */ if (rte_red_log2_1_minus_Wq[index] == 0) { rte_red_log2_1_minus_Wq[index] = 1; } } } int rte_red_rt_data_init(struct rte_red *red) { if (red == NULL) return -1; red->avg = 0; red->count = 0; red->q_time = 0; return 0; } int rte_red_config_init(struct rte_red_config *red_cfg, const uint16_t wq_log2, const uint16_t min_th, const uint16_t max_th, const uint16_t maxp_inv) { if (red_cfg == NULL) { return -1; } if (max_th > RTE_RED_MAX_TH_MAX) { return -2; } if (min_th >= max_th) { return -3; } if (wq_log2 > RTE_RED_WQ_LOG2_MAX) { return -4; } if (wq_log2 < RTE_RED_WQ_LOG2_MIN) { return -5; } if (maxp_inv < RTE_RED_MAXP_INV_MIN) { return -6; } if (maxp_inv > RTE_RED_MAXP_INV_MAX) { return -7; } /** * Initialize the RED module if not already done */ if (!rte_red_init_done) { rte_red_rand_seed = rte_rand(); rte_red_rand_val = rte_fast_rand(); __rte_red_init_tables(); rte_red_init_done = 1; } red_cfg->min_th = ((uint32_t) min_th) << (wq_log2 + RTE_RED_SCALING); red_cfg->max_th = ((uint32_t) max_th) << (wq_log2 + RTE_RED_SCALING); red_cfg->pa_const = (2 * (max_th - min_th) * maxp_inv) << RTE_RED_SCALING; red_cfg->maxp_inv = maxp_inv; red_cfg->wq_log2 = wq_log2; return 0; } ================================================ FILE: lib/librte_sched/rte_red.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __RTE_RED_H_INCLUDED__ #define __RTE_RED_H_INCLUDED__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Random Early Detection (RED) * * ***/ #include #include #include #include #include #include #define RTE_RED_SCALING 10 /**< Fraction size for fixed-point */ #define RTE_RED_S (1 << 22) /**< Packet size multiplied by number of leaf queues */ #define RTE_RED_MAX_TH_MAX 1023 /**< Max threshold limit in fixed point format */ #define RTE_RED_WQ_LOG2_MIN 1 /**< Min inverse filter weight value */ #define RTE_RED_WQ_LOG2_MAX 12 /**< Max inverse filter weight value */ #define RTE_RED_MAXP_INV_MIN 1 /**< Min inverse mark probability value */ #define RTE_RED_MAXP_INV_MAX 255 /**< Max inverse mark probability value */ #define RTE_RED_2POW16 (1<<16) /**< 2 power 16 */ #define RTE_RED_INT16_NBITS (sizeof(uint16_t) * CHAR_BIT) #define RTE_RED_WQ_LOG2_NUM (RTE_RED_WQ_LOG2_MAX - RTE_RED_WQ_LOG2_MIN + 1) #ifdef RTE_RED_DEBUG #define RTE_RED_ASSERT(exp) \ if (!(exp)) { \ rte_panic("line%d\tassert \"" #exp "\" failed\n", __LINE__); \ } #else #define RTE_RED_ASSERT(exp) do { } while(0) #endif /* RTE_RED_DEBUG */ /** * Externs * */ extern uint32_t rte_red_rand_val; extern uint32_t rte_red_rand_seed; extern uint16_t rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM]; extern uint16_t rte_red_pow2_frac_inv[16]; /** * RED configuration parameters passed by user * */ struct rte_red_params { uint16_t min_th; /**< Minimum threshold for queue (max_th) */ uint16_t max_th; /**< Maximum threshold for queue (max_th) */ uint16_t maxp_inv; /**< Inverse of packet marking probability maximum value (maxp = 1 / maxp_inv) */ uint16_t wq_log2; /**< Negated log2 of queue weight (wq = 1 / (2 ^ wq_log2)) */ }; /** * RED configuration parameters */ struct rte_red_config { uint32_t min_th; /**< min_th scaled in fixed-point format */ uint32_t max_th; /**< max_th scaled in fixed-point format */ uint32_t pa_const; /**< Precomputed constant value used for pa calculation (scaled in fixed-point format) */ uint8_t maxp_inv; /**< maxp_inv */ uint8_t wq_log2; /**< wq_log2 */ }; /** * RED run-time data */ struct rte_red { uint32_t avg; /**< Average queue size (avg), scaled in fixed-point format */ uint32_t count; /**< Number of packets since last marked packet (count) */ uint64_t q_time; /**< Start of the queue idle time (q_time) */ }; /** * @brief Initialises run-time data * * @param red [in,out] data pointer to RED runtime data * * @return Operation status * @retval 0 success * @retval !0 error */ int rte_red_rt_data_init(struct rte_red *red); /** * @brief Configures a single RED configuration parameter structure. * * @param red_cfg [in,out] config pointer to a RED configuration parameter structure * @param wq_log2 [in] log2 of the filter weight, valid range is: * RTE_RED_WQ_LOG2_MIN <= wq_log2 <= RTE_RED_WQ_LOG2_MAX * @param min_th [in] queue minimum threshold in number of packets * @param max_th [in] queue maximum threshold in number of packets * @param maxp_inv [in] inverse maximum mark probability * * @return Operation status * @retval 0 success * @retval !0 error */ int rte_red_config_init(struct rte_red_config *red_cfg, const uint16_t wq_log2, const uint16_t min_th, const uint16_t max_th, const uint16_t maxp_inv); /** * @brief Generate random number for RED * * Implemenetation based on: * http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/ * * 10 bit shift has been found through empirical tests (was 16). * * @return Random number between 0 and (2^22 - 1) */ static inline uint32_t rte_fast_rand(void) { rte_red_rand_seed = (214013 * rte_red_rand_seed) + 2531011; return (rte_red_rand_seed >> 10); } /** * @brief calculate factor to scale average queue size when queue * becomes empty * * @param wq_log2 [in] where EWMA filter weight wq = 1/(2 ^ wq_log2) * @param m [in] exponent in the computed value (1 - wq) ^ m * * @return computed value * @retval ((1 - wq) ^ m) scaled in fixed-point format */ static inline uint16_t __rte_red_calc_qempty_factor(uint8_t wq_log2, uint16_t m) { uint32_t n = 0; uint32_t f = 0; /** * Basic math tells us that: * a^b = 2^(b * log2(a) ) * * in our case: * a = (1-Wq) * b = m * Wq = 1/ (2^log2n) * * So we are computing this equation: * factor = 2 ^ ( m * log2(1-Wq)) * * First we are computing: * n = m * log2(1-Wq) * * To avoid dealing with signed numbers log2 values are positive * but they should be negative because (1-Wq) is always < 1. * Contents of log2 table values are also scaled for precision. */ n = m * rte_red_log2_1_minus_Wq[wq_log2 - RTE_RED_WQ_LOG2_MIN]; /** * The tricky part is computing 2^n, for this I split n into * integer part and fraction part. * f - is fraction part of n * n - is integer part of original n * * Now using basic math we compute 2^n: * 2^(f+n) = 2^f * 2^n * 2^f - we use lookup table * 2^n - can be replaced with bit shift right oeprations */ f = (n >> 6) & 0xf; n >>= 10; if (n < RTE_RED_SCALING) return (uint16_t) ((rte_red_pow2_frac_inv[f] + (1 << (n - 1))) >> n); return 0; } /** * @brief Updates queue average in condition when queue is empty * * Note: packet is never dropped in this particular case. * * @param red_cfg [in] config pointer to a RED configuration parameter structure * @param red [in,out] data pointer to RED runtime data * @param time [in] current time stamp * * @return Operation status * @retval 0 enqueue the packet * @retval 1 drop the packet based on max threshold criterion * @retval 2 drop the packet based on mark probability criterion */ static inline int rte_red_enqueue_empty(const struct rte_red_config *red_cfg, struct rte_red *red, const uint64_t time) { uint64_t time_diff = 0, m = 0; RTE_RED_ASSERT(red_cfg != NULL); RTE_RED_ASSERT(red != NULL); red->count ++; /** * We compute avg but we don't compare avg against * min_th or max_th, nor calculate drop probability */ time_diff = time - red->q_time; /** * m is the number of packets that might have arrived while the queue was empty. * In this case we have time stamps provided by scheduler in byte units (bytes * transmitted on network port). Such time stamp translates into time units as * port speed is fixed but such approach simplifies the code. */ m = time_diff / RTE_RED_S; /** * Check that m will fit into 16-bit unsigned integer */ if (m >= RTE_RED_2POW16) { red->avg = 0; } else { red->avg = (red->avg >> RTE_RED_SCALING) * __rte_red_calc_qempty_factor(red_cfg->wq_log2, (uint16_t) m); } return 0; } /** * Drop probability (Sally Floyd and Van Jacobson): * * pb = (1 / maxp_inv) * (avg - min_th) / (max_th - min_th) * pa = pb / (2 - count * pb) * * * (1 / maxp_inv) * (avg - min_th) * --------------------------------- * max_th - min_th * pa = ----------------------------------------------- * count * (1 / maxp_inv) * (avg - min_th) * 2 - ----------------------------------------- * max_th - min_th * * * avg - min_th * pa = ----------------------------------------------------------- * 2 * (max_th - min_th) * maxp_inv - count * (avg - min_th) * * * We define pa_const as: pa_const = 2 * (max_th - min_th) * maxp_inv. Then: * * * avg - min_th * pa = ----------------------------------- * pa_const - count * (avg - min_th) */ /** * @brief make a decision to drop or enqueue a packet based on mark probability * criteria * * @param red_cfg [in] config pointer to structure defining RED parameters * @param red [in,out] data pointer to RED runtime data * * @return operation status * @retval 0 enqueue the packet * @retval 1 drop the packet */ static inline int __rte_red_drop(const struct rte_red_config *red_cfg, struct rte_red *red) { uint32_t pa_num = 0; /* numerator of drop-probability */ uint32_t pa_den = 0; /* denominator of drop-probability */ uint32_t pa_num_count = 0; pa_num = (red->avg - red_cfg->min_th) >> (red_cfg->wq_log2); pa_num_count = red->count * pa_num; if (red_cfg->pa_const <= pa_num_count) return 1; pa_den = red_cfg->pa_const - pa_num_count; /* If drop, generate and save random number to be used next time */ if (unlikely((rte_red_rand_val % pa_den) < pa_num)) { rte_red_rand_val = rte_fast_rand(); return 1; } /* No drop */ return 0; } /** * @brief Decides if new packet should be enqeued or dropped in queue non-empty case * * @param red_cfg [in] config pointer to a RED configuration parameter structure * @param red [in,out] data pointer to RED runtime data * @param q [in] current queue size (measured in packets) * * @return Operation status * @retval 0 enqueue the packet * @retval 1 drop the packet based on max threshold criterion * @retval 2 drop the packet based on mark probability criterion */ static inline int rte_red_enqueue_nonempty(const struct rte_red_config *red_cfg, struct rte_red *red, const unsigned q) { RTE_RED_ASSERT(red_cfg != NULL); RTE_RED_ASSERT(red != NULL); /** * EWMA filter (Sally Floyd and Van Jacobson): * avg = (1 - wq) * avg + wq * q * avg = avg + q * wq - avg * wq * * We select: wq = 2^(-n). Let scaled version of avg be: avg_s = avg * 2^(N+n). We get: * avg_s = avg_s + q * 2^N - avg_s * 2^(-n) * * By using shift left/right operations, we get: * avg_s = avg_s + (q << N) - (avg_s >> n) * avg_s += (q << N) - (avg_s >> n) */ /* avg update */ red->avg += (q << RTE_RED_SCALING) - (red->avg >> red_cfg->wq_log2); /* avg < min_th: do not mark the packet */ if (red->avg < red_cfg->min_th) { red->count ++; return 0; } /* min_th <= avg < max_th: mark the packet with pa probability */ if (red->avg < red_cfg->max_th) { if (!__rte_red_drop(red_cfg, red)) { red->count ++; return 0; } red->count = 0; return 2; } /* max_th <= avg: always mark the packet */ red->count = 0; return 1; } /** * @brief Decides if new packet should be enqeued or dropped * Updates run time data based on new queue size value. * Based on new queue average and RED configuration parameters * gives verdict whether to enqueue or drop the packet. * * @param red_cfg [in] config pointer to a RED configuration parameter structure * @param red [in,out] data pointer to RED runtime data * @param q [in] updated queue size in packets * @param time [in] current time stamp * * @return Operation status * @retval 0 enqueue the packet * @retval 1 drop the packet based on max threshold criteria * @retval 2 drop the packet based on mark probability criteria */ static inline int rte_red_enqueue(const struct rte_red_config *red_cfg, struct rte_red *red, const unsigned q, const uint64_t time) { RTE_RED_ASSERT(red_cfg != NULL); RTE_RED_ASSERT(red != NULL); if (q != 0) { return rte_red_enqueue_nonempty(red_cfg, red, q); } else { return rte_red_enqueue_empty(red_cfg, red, time); } } /** * @brief Callback to records time that queue became empty * * @param red [in,out] data pointer to RED runtime data * @param time [in] current time stamp */ static inline void rte_red_mark_queue_empty(struct rte_red *red, const uint64_t time) { red->q_time = time; } #ifdef __cplusplus } #endif #endif /* __RTE_RED_H_INCLUDED__ */ ================================================ FILE: lib/librte_sched/rte_sched.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "rte_sched.h" #include "rte_bitmap.h" #include "rte_sched_common.h" #include "rte_approx.h" #ifdef __INTEL_COMPILER #pragma warning(disable:2259) /* conversion may lose significant bits */ #endif #ifndef RTE_SCHED_DEBUG #define RTE_SCHED_DEBUG 0 #endif #ifndef RTE_SCHED_OPTIMIZATIONS #define RTE_SCHED_OPTIMIZATIONS 0 #endif #if RTE_SCHED_OPTIMIZATIONS #include #endif #define RTE_SCHED_ENQUEUE 1 #define RTE_SCHED_TS 1 #if RTE_SCHED_TS == 0 /* Infinite credits. Traffic shaping disabled. */ #define RTE_SCHED_TS_CREDITS_UPDATE 0 #define RTE_SCHED_TS_CREDITS_CHECK 0 #else /* Real Credits. Full traffic shaping implemented. */ #define RTE_SCHED_TS_CREDITS_UPDATE 1 #define RTE_SCHED_TS_CREDITS_CHECK 1 #endif #ifndef RTE_SCHED_TB_RATE_CONFIG_ERR #define RTE_SCHED_TB_RATE_CONFIG_ERR (1e-7) #endif #define RTE_SCHED_WRR 1 #ifndef RTE_SCHED_WRR_SHIFT #define RTE_SCHED_WRR_SHIFT 3 #endif #ifndef RTE_SCHED_PORT_N_GRINDERS #define RTE_SCHED_PORT_N_GRINDERS 8 #endif #if (RTE_SCHED_PORT_N_GRINDERS == 0) || (RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)) #error Number of grinders must be non-zero and a power of 2 #endif #if (RTE_SCHED_OPTIMIZATIONS && (RTE_SCHED_PORT_N_GRINDERS != 8)) #error Number of grinders must be 8 when RTE_SCHED_OPTIMIZATIONS is set #endif #define RTE_SCHED_GRINDER_PCACHE_SIZE (64 / RTE_SCHED_QUEUES_PER_PIPE) #define RTE_SCHED_PIPE_INVALID UINT32_MAX #define RTE_SCHED_BMP_POS_INVALID UINT32_MAX struct rte_sched_subport { /* Token bucket (TB) */ uint64_t tb_time; /* time of last update */ uint32_t tb_period; uint32_t tb_credits_per_period; uint32_t tb_size; uint32_t tb_credits; /* Traffic classes (TCs) */ uint64_t tc_time; /* time of next update */ uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_period; /* TC oversubscription */ uint32_t tc_ov_wm; uint32_t tc_ov_wm_min; uint32_t tc_ov_wm_max; uint8_t tc_ov_period_id; uint8_t tc_ov; uint32_t tc_ov_n; double tc_ov_rate; /* Statistics */ struct rte_sched_subport_stats stats; }; struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; uint32_t tb_credits_per_period; uint32_t tb_size; /* Pipe traffic classes */ uint32_t tc_period; uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t tc_ov_weight; /* Pipe queues */ uint8_t wrr_cost[RTE_SCHED_QUEUES_PER_PIPE]; }; struct rte_sched_pipe { /* Token bucket (TB) */ uint64_t tb_time; /* time of last update */ uint32_t tb_credits; /* Pipe profile and flags */ uint32_t profile; /* Traffic classes (TCs) */ uint64_t tc_time; /* time of next update */ uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /* Weighted Round Robin (WRR) */ uint8_t wrr_tokens[RTE_SCHED_QUEUES_PER_PIPE]; /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { uint16_t qw; uint16_t qr; }; struct rte_sched_queue_extra { struct rte_sched_queue_stats stats; #ifdef RTE_SCHED_RED struct rte_red red; #endif }; enum grinder_state { e_GRINDER_PREFETCH_PIPE = 0, e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS, e_GRINDER_PREFETCH_MBUF, e_GRINDER_READ_MBUF }; /* * Path through the scheduler hierarchy used by the scheduler enqueue * operation to identify the destination queue for the current * packet. Stored in the field pkt.hash.sched of struct rte_mbuf of * each packet, typically written by the classification stage and read * by scheduler enqueue. */ struct __rte_sched_port_hierarchy { uint32_t queue:2; /**< Queue ID (0 .. 3) */ uint32_t traffic_class:2; /**< Traffic class ID (0 .. 3)*/ uint32_t pipe:20; /**< Pipe ID */ uint32_t subport:6; /**< Subport ID */ uint32_t color:2; /**< Color */ }; struct rte_sched_grinder { /* Pipe cache */ uint16_t pcache_qmask[RTE_SCHED_GRINDER_PCACHE_SIZE]; uint32_t pcache_qindex[RTE_SCHED_GRINDER_PCACHE_SIZE]; uint32_t pcache_w; uint32_t pcache_r; /* Current pipe */ enum grinder_state state; uint32_t productive; uint32_t pindex; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_pipe_profile *pipe_params; /* TC cache */ uint8_t tccache_qmask[4]; uint32_t tccache_qindex[4]; uint32_t tccache_w; uint32_t tccache_r; /* Current TC */ uint32_t tc_index; struct rte_sched_queue *queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; struct rte_mbuf **qbase[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t qindex[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint16_t qsize; uint32_t qmask; uint32_t qpos; struct rte_mbuf *pkt; /* WRR */ uint16_t wrr_tokens[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; uint16_t wrr_mask[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; uint8_t wrr_cost[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; }; struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; uint32_t n_pipes_per_subport; uint32_t rate; uint32_t mtu; uint32_t frame_overhead; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t pipe_tc3_rate_max; #ifdef RTE_SCHED_RED struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][e_RTE_METER_COLORS]; #endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ uint64_t time_cpu_bytes; /* Current CPU time measured in bytes */ uint64_t time; /* Current NIC TX time measured in bytes */ double cycles_per_byte; /* CPU cycles per byte */ /* Scheduling loop detection */ uint32_t pipe_loop; uint32_t pipe_exhaustion; /* Bitmap */ struct rte_bitmap *bmp; uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; /* Grinders */ struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t qsize_sum; /* Large data structures */ struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; struct rte_sched_queue_extra *queue_extra; struct rte_sched_pipe_profile *pipe_profiles; uint8_t *bmp_array; struct rte_mbuf **queue_array; uint8_t memory[0] __rte_cache_aligned; } __rte_cache_aligned; enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, e_RTE_SCHED_PORT_ARRAY_PIPE, e_RTE_SCHED_PORT_ARRAY_QUEUE, e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, e_RTE_SCHED_PORT_ARRAY_TOTAL, }; #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t rte_sched_port_queues_per_subport(struct rte_sched_port *port) { return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; } #endif static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } static int rte_sched_port_check_params(struct rte_sched_port_params *params) { uint32_t i, j; if (params == NULL) { return -1; } /* socket */ if ((params->socket < 0) || (params->socket >= RTE_MAX_NUMA_NODES)) { return -3; } /* rate */ if (params->rate == 0) { return -4; } /* mtu */ if (params->mtu == 0) { return -5; } /* n_subports_per_port: non-zero, power of 2 */ if ((params->n_subports_per_port == 0) || (!rte_is_power_of_2(params->n_subports_per_port))) { return -6; } /* n_pipes_per_subport: non-zero, power of 2 */ if ((params->n_pipes_per_subport == 0) || (!rte_is_power_of_2(params->n_pipes_per_subport))) { return -7; } /* qsize: non-zero, power of 2, no bigger than 32K (due to 16-bit read/write pointers) */ for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { uint16_t qsize = params->qsize[i]; if ((qsize == 0) || (!rte_is_power_of_2(qsize))) { return -8; } } /* pipe_profiles and n_pipe_profiles */ if ((params->pipe_profiles == NULL) || (params->n_pipe_profiles == 0) || (params->n_pipe_profiles > RTE_SCHED_PIPE_PROFILES_PER_PORT)) { return -9; } for (i = 0; i < params->n_pipe_profiles; i ++) { struct rte_sched_pipe_params *p = params->pipe_profiles + i; /* TB rate: non-zero, not greater than port rate */ if ((p->tb_rate == 0) || (p->tb_rate > params->rate)) { return -10; } /* TB size: non-zero */ if (p->tb_size == 0) { return -11; } /* TC rate: non-zero, less than pipe rate */ for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j ++) { if ((p->tc_rate[j] == 0) || (p->tc_rate[j] > p->tb_rate)) { return -12; } } /* TC period: non-zero */ if (p->tc_period == 0) { return -13; } #ifdef RTE_SCHED_SUBPORT_TC_OV /* TC3 oversubscription weight: non-zero */ if (p->tc_ov_weight == 0) { return -14; } #endif /* Queue WRR weights: non-zero */ for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j ++) { if (p->wrr_weights[j] == 0) { return -15; } } } return 0; } static uint32_t rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) { uint32_t n_subports_per_port = params->n_subports_per_port; uint32_t n_pipes_per_subport = params->n_pipes_per_subport; uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); uint32_t size_queue_extra = n_queues_per_port * sizeof(struct rte_sched_queue_extra); uint32_t size_pipe_profiles = RTE_SCHED_PIPE_PROFILES_PER_PORT * sizeof(struct rte_sched_pipe_profile); uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); uint32_t size_per_pipe_queue_array, size_queue_array; uint32_t base, i; size_per_pipe_queue_array = 0; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { size_per_pipe_queue_array += RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS * params->qsize[i] * sizeof(struct rte_mbuf *); } size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; base = 0; if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) return base; base += RTE_CACHE_LINE_ROUNDUP(size_subport); if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) return base; base += RTE_CACHE_LINE_ROUNDUP(size_pipe); if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) return base; base += RTE_CACHE_LINE_ROUNDUP(size_queue); if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) return base; base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) return base; base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) return base; base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) return base; base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); return base; } uint32_t rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) { uint32_t size0, size1; int status; status = rte_sched_port_check_params(params); if (status != 0) { RTE_LOG(NOTICE, SCHED, "Port scheduler params check failed (%d)\n", status); return 0; } size0 = sizeof(struct rte_sched_port); size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); return (size0 + size1); } static void rte_sched_port_config_qsize(struct rte_sched_port *port) { /* TC 0 */ port->qsize_add[0] = 0; port->qsize_add[1] = port->qsize_add[0] + port->qsize[0]; port->qsize_add[2] = port->qsize_add[1] + port->qsize[0]; port->qsize_add[3] = port->qsize_add[2] + port->qsize[0]; /* TC 1 */ port->qsize_add[4] = port->qsize_add[3] + port->qsize[0]; port->qsize_add[5] = port->qsize_add[4] + port->qsize[1]; port->qsize_add[6] = port->qsize_add[5] + port->qsize[1]; port->qsize_add[7] = port->qsize_add[6] + port->qsize[1]; /* TC 2 */ port->qsize_add[8] = port->qsize_add[7] + port->qsize[1]; port->qsize_add[9] = port->qsize_add[8] + port->qsize[2]; port->qsize_add[10] = port->qsize_add[9] + port->qsize[2]; port->qsize_add[11] = port->qsize_add[10] + port->qsize[2]; /* TC 3 */ port->qsize_add[12] = port->qsize_add[11] + port->qsize[2]; port->qsize_add[13] = port->qsize_add[12] + port->qsize[3]; port->qsize_add[14] = port->qsize_add[13] + port->qsize[3]; port->qsize_add[15] = port->qsize_add[14] + port->qsize[3]; port->qsize_sum = port->qsize_add[15] + port->qsize[3]; } static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { struct rte_sched_pipe_profile *p = port->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" " Traffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" " Traffic class 3 oversubscription: weight = %hhu\n" " WRR cost: [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu], [%hhu, %hhu, %hhu, %hhu]\n", i, /* Token bucket */ p->tb_period, p->tb_credits_per_period, p->tb_size, /* Traffic classes */ p->tc_period, p->tc_credits_per_period[0], p->tc_credits_per_period[1], p->tc_credits_per_period[2], p->tc_credits_per_period[3], /* Traffic class 3 oversubscription */ p->tc_ov_weight, /* WRR */ p->wrr_cost[ 0], p->wrr_cost[ 1], p->wrr_cost[ 2], p->wrr_cost[ 3], p->wrr_cost[ 4], p->wrr_cost[ 5], p->wrr_cost[ 6], p->wrr_cost[ 7], p->wrr_cost[ 8], p->wrr_cost[ 9], p->wrr_cost[10], p->wrr_cost[11], p->wrr_cost[12], p->wrr_cost[13], p->wrr_cost[14], p->wrr_cost[15]); } static inline uint64_t rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) { uint64_t time = time_ms; time = (time * rate) / 1000; return time; } static void rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, struct rte_sched_port_params *params) { uint32_t i, j; for (i = 0; i < port->n_pipe_profiles; i ++) { struct rte_sched_pipe_params *src = params->pipe_profiles + i; struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; /* Token Bucket */ if (src->tb_rate == params->rate) { dst->tb_credits_per_period = 1; dst->tb_period = 1; } else { double tb_rate = ((double) src->tb_rate) / ((double) params->rate); double d = RTE_SCHED_TB_RATE_CONFIG_ERR; rte_approx(tb_rate, d, &dst->tb_credits_per_period, &dst->tb_period); } dst->tb_size = src->tb_size; /* Traffic Classes */ dst->tc_period = (uint32_t) rte_sched_time_ms_to_bytes(src->tc_period, params->rate); for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j ++) { dst->tc_credits_per_period[j] = (uint32_t) rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[j]); } #ifdef RTE_SCHED_SUBPORT_TC_OV dst->tc_ov_weight = src->tc_ov_weight; #endif /* WRR */ for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j ++) { uint32_t wrr_cost[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; uint32_t lcd, lcd1, lcd2; uint32_t qindex; qindex = j * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; wrr_cost[0] = src->wrr_weights[qindex]; wrr_cost[1] = src->wrr_weights[qindex + 1]; wrr_cost[2] = src->wrr_weights[qindex + 2]; wrr_cost[3] = src->wrr_weights[qindex + 3]; lcd1 = rte_get_lcd(wrr_cost[0], wrr_cost[1]); lcd2 = rte_get_lcd(wrr_cost[2], wrr_cost[3]); lcd = rte_get_lcd(lcd1, lcd2); wrr_cost[0] = lcd / wrr_cost[0]; wrr_cost[1] = lcd / wrr_cost[1]; wrr_cost[2] = lcd / wrr_cost[2]; wrr_cost[3] = lcd / wrr_cost[3]; dst->wrr_cost[qindex] = (uint8_t) wrr_cost[0]; dst->wrr_cost[qindex + 1] = (uint8_t) wrr_cost[1]; dst->wrr_cost[qindex + 2] = (uint8_t) wrr_cost[2]; dst->wrr_cost[qindex + 3] = (uint8_t) wrr_cost[3]; } rte_sched_port_log_pipe_profile(port, i); } port->pipe_tc3_rate_max = 0; for (i = 0; i < port->n_pipe_profiles; i ++) { struct rte_sched_pipe_params *src = params->pipe_profiles + i; uint32_t pipe_tc3_rate = src->tc_rate[3]; if (port->pipe_tc3_rate_max < pipe_tc3_rate) { port->pipe_tc3_rate_max = pipe_tc3_rate; } } } struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; uint32_t mem_size, bmp_mem_size, n_queues_per_port, i; /* Check user parameters. Determine the amount of memory to allocate */ mem_size = rte_sched_port_get_memory_footprint(params); if (mem_size == 0) { return NULL; } /* Allocate memory to store the data structures */ port = rte_zmalloc("qos_params", mem_size, RTE_CACHE_LINE_SIZE); if (port == NULL) { return NULL; } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; memcpy(port->qsize, params->qsize, sizeof(params->qsize)); port->n_pipe_profiles = params->n_pipe_profiles; #ifdef RTE_SCHED_RED for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { uint32_t j; for (j = 0; j < e_RTE_METER_COLORS; j++) { /* if min/max are both zero, then RED is disabled */ if ((params->red_params[i][j].min_th | params->red_params[i][j].max_th) == 0) { continue; } if (rte_red_config_init(&port->red_config[i][j], params->red_params[i][j].wq_log2, params->red_params[i][j].min_th, params->red_params[i][j].max_th, params->red_params[i][j].maxp_inv) != 0) { return NULL; } } } #endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); port->time_cpu_bytes = 0; port->time = 0; port->cycles_per_byte = ((double) rte_get_tsc_hz()) / ((double) params->rate); /* Scheduling loop detection */ port->pipe_loop = RTE_SCHED_PIPE_INVALID; port->pipe_exhaustion = 0; /* Grinders */ port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; /* Queue base calculation */ rte_sched_port_config_qsize(port); /* Large data structures */ port->subport = (struct rte_sched_subport *) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_SUBPORT)); port->pipe = (struct rte_sched_pipe *) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_PIPE)); port->queue = (struct rte_sched_queue *) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_QUEUE)); port->queue_extra = (struct rte_sched_queue_extra *) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); port->pipe_profiles = (struct rte_sched_pipe_profile *) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); port->bmp_array = port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); port->queue_array = (struct rte_mbuf **) (port->memory + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); /* Pipe profile table */ rte_sched_port_config_pipe_profile_table(port, params); /* Bitmap */ n_queues_per_port = rte_sched_port_queues_per_port(port); bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, bmp_mem_size); if (port->bmp == NULL) { RTE_LOG(ERR, SCHED, "Bitmap init error\n"); return NULL; } for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i ++) { port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; } return port; } void rte_sched_port_free(struct rte_sched_port *port) { /* Check user parameters */ if (port == NULL){ return; } rte_bitmap_free(port->bmp); rte_free(port); } static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { struct rte_sched_subport *s = port->subport + i; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" " Traffic classes: period = %u, credits per period = [%u, %u, %u, %u]\n" " Traffic class 3 oversubscription: wm min = %u, wm max = %u\n", i, /* Token bucket */ s->tb_period, s->tb_credits_per_period, s->tb_size, /* Traffic classes */ s->tc_period, s->tc_credits_per_period[0], s->tc_credits_per_period[1], s->tc_credits_per_period[2], s->tc_credits_per_period[3], /* Traffic class 3 oversubscription */ s->tc_ov_wm_min, s->tc_ov_wm_max); } int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { struct rte_sched_subport *s; uint32_t i; /* Check user parameters */ if ((port == NULL) || (subport_id >= port->n_subports_per_port) || (params == NULL)) { return -1; } if ((params->tb_rate == 0) || (params->tb_rate > port->rate)) { return -2; } if (params->tb_size == 0) { return -3; } for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { if ((params->tc_rate[i] == 0) || (params->tc_rate[i] > params->tb_rate)) { return -4; } } if (params->tc_period == 0) { return -5; } s = port->subport + subport_id; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { s->tb_credits_per_period = 1; s->tb_period = 1; } else { double tb_rate = ((double) params->tb_rate) / ((double) port->rate); double d = RTE_SCHED_TB_RATE_CONFIG_ERR; rte_approx(tb_rate, d, &s->tb_credits_per_period, &s->tb_period); } s->tb_size = params->tb_size; s->tb_time = port->time; s->tb_credits = s->tb_size / 2; /* Traffic Classes (TCs) */ s->tc_period = (uint32_t) rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { s->tc_credits_per_period[i] = (uint32_t) rte_sched_time_ms_to_bytes(params->tc_period, params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { s->tc_credits[i] = s->tc_credits_per_period[i]; } #ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = (uint32_t) rte_sched_time_ms_to_bytes(params->tc_period, port->pipe_tc3_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; #endif rte_sched_port_log_subport_config(port, subport_id); return 0; } int rte_sched_pipe_config(struct rte_sched_port *port, uint32_t subport_id, uint32_t pipe_id, int32_t pipe_profile) { struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; uint32_t deactivate, profile, i; /* Check user parameters */ profile = (uint32_t) pipe_profile; deactivate = (pipe_profile < 0); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || (pipe_id >= port->n_pipes_per_subport) || ((!deactivate) && (profile >= port->n_pipe_profiles))) { return -1; } /* Check that subport configuration is valid */ s = port->subport + subport_id; if (s->tb_period == 0) { return -2; } p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); /* Handle the case when pipe already has a valid configuration */ if (p->tb_time) { params = port->pipe_profiles + p->profile; #ifdef RTE_SCHED_SUBPORT_TC_OV double subport_tc3_rate = ((double) s->tc_credits_per_period[3]) / ((double) s->tc_period); double pipe_tc3_rate = ((double) params->tc_credits_per_period[3]) / ((double) params->tc_period); uint32_t tc3_ov = s->tc_ov; /* Unplug pipe from its subport */ s->tc_ov_n -= params->tc_ov_weight; s->tc_ov_rate -= pipe_tc3_rate; s->tc_ov = s->tc_ov_rate > subport_tc3_rate; if (s->tc_ov != tc3_ov) { RTE_LOG(DEBUG, SCHED, "Subport %u TC3 oversubscription is OFF (%.4lf >= %.4lf)\n", subport_id, subport_tc3_rate, s->tc_ov_rate); } #endif /* Reset the pipe */ memset(p, 0, sizeof(struct rte_sched_pipe)); } if (deactivate) { return 0; } /* Apply the new pipe configuration */ p->profile = profile; params = port->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; p->tb_credits = params->tb_size / 2; /* Traffic Classes (TCs) */ p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i ++) { p->tc_credits[i] = params->tc_credits_per_period[i]; } #ifdef RTE_SCHED_SUBPORT_TC_OV { /* Subport TC3 oversubscription */ double subport_tc3_rate = ((double) s->tc_credits_per_period[3]) / ((double) s->tc_period); double pipe_tc3_rate = ((double) params->tc_credits_per_period[3]) / ((double) params->tc_period); uint32_t tc3_ov = s->tc_ov; s->tc_ov_n += params->tc_ov_weight; s->tc_ov_rate += pipe_tc3_rate; s->tc_ov = s->tc_ov_rate > subport_tc3_rate; if (s->tc_ov != tc3_ov) { RTE_LOG(DEBUG, SCHED, "Subport %u TC3 oversubscription is ON (%.4lf < %.4lf)\n", subport_id, subport_tc3_rate, s->tc_ov_rate); } p->tc_ov_period_id = s->tc_ov_period_id; p->tc_ov_credits = s->tc_ov_wm; } #endif return 0; } void rte_sched_port_pkt_write(struct rte_mbuf *pkt, uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue, enum rte_meter_color color) { struct __rte_sched_port_hierarchy *sched = (struct __rte_sched_port_hierarchy *) &pkt->hash.sched; sched->color = (uint32_t) color; sched->subport = subport; sched->pipe = pipe; sched->traffic_class = traffic_class; sched->queue = queue; } void rte_sched_port_pkt_read_tree_path(const struct rte_mbuf *pkt, uint32_t *subport, uint32_t *pipe, uint32_t *traffic_class, uint32_t *queue) { const struct __rte_sched_port_hierarchy *sched = (const struct __rte_sched_port_hierarchy *) &pkt->hash.sched; *subport = sched->subport; *pipe = sched->pipe; *traffic_class = sched->traffic_class; *queue = sched->queue; } enum rte_meter_color rte_sched_port_pkt_read_color(const struct rte_mbuf *pkt) { const struct __rte_sched_port_hierarchy *sched = (const struct __rte_sched_port_hierarchy *) &pkt->hash.sched; return (enum rte_meter_color) sched->color; } int rte_sched_subport_read_stats(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_stats *stats, uint32_t *tc_ov) { struct rte_sched_subport *s; /* Check user parameters */ if ((port == NULL) || (subport_id >= port->n_subports_per_port) || (stats == NULL) || (tc_ov == NULL)) { return -1; } s = port->subport + subport_id; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats)); /* Subport TC ovesubscription status */ *tc_ov = s->tc_ov; return 0; } int rte_sched_queue_read_stats(struct rte_sched_port *port, uint32_t queue_id, struct rte_sched_queue_stats *stats, uint16_t *qlen) { struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; /* Check user parameters */ if ((port == NULL) || (queue_id >= rte_sched_port_queues_per_port(port)) || (stats == NULL) || (qlen == NULL)) { return -1; } q = port->queue + queue_id; qe = port->queue_extra + queue_id; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats)); /* Queue length */ *qlen = q->qw - q->qr; return 0; } static inline uint32_t rte_sched_port_qindex(struct rte_sched_port *port, uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue) { uint32_t result; result = subport * port->n_pipes_per_subport + pipe; result = result * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE + traffic_class; result = result * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue; return result; } static inline struct rte_mbuf ** rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) { uint32_t pindex = qindex >> 4; uint32_t qpos = qindex & 0xF; return (port->queue_array + pindex * port->qsize_sum + port->qsize_add[qpos]); } static inline uint16_t rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) { uint32_t tc = (qindex >> 2) & 0x3; return port->qsize[tc]; } #if RTE_SCHED_DEBUG static inline int rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) { struct rte_sched_queue *queue = port->queue + qindex; return (queue->qr == queue->qw); } static inline int rte_sched_port_queue_is_full(struct rte_sched_port *port, uint32_t qindex) { struct rte_sched_queue *queue = port->queue + qindex; uint16_t qsize = rte_sched_port_qsize(port, qindex); uint16_t qlen = queue->qw - queue->qr; return (qlen >= qsize); } #endif /* RTE_SCHED_DEBUG */ #ifdef RTE_SCHED_COLLECT_STATS static inline void rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) { struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = (qindex >> 2) & 0x3; uint32_t pkt_len = pkt->pkt_len; s->stats.n_pkts_tc[tc_index] += 1; s->stats.n_bytes_tc[tc_index] += pkt_len; } static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) { struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = (qindex >> 2) & 0x3; uint32_t pkt_len = pkt->pkt_len; s->stats.n_pkts_tc_dropped[tc_index] += 1; s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; } static inline void rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) { struct rte_sched_queue_extra *qe = port->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; qe->stats.n_bytes += pkt_len; } static inline void rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) { struct rte_sched_queue_extra *qe = port->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; qe->stats.n_bytes_dropped += pkt_len; } #endif /* RTE_SCHED_COLLECT_STATS */ #ifdef RTE_SCHED_RED static inline int rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; struct rte_red *red; uint32_t tc_index; enum rte_meter_color color; tc_index = (qindex >> 2) & 0x3; color = rte_sched_port_pkt_read_color(pkt); red_cfg = &port->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; qe = port->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); } static inline void rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) { struct rte_sched_queue_extra *qe; struct rte_red *red; qe = port->queue_extra + qindex; red = &qe->red; rte_red_mark_queue_empty(red, port->time); } #else #define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 #define rte_sched_port_set_queue_empty_timestamp(port, qindex) #endif /* RTE_SCHED_RED */ #if RTE_SCHED_DEBUG static inline int debug_pipe_is_empty(struct rte_sched_port *port, uint32_t pindex) { uint32_t qindex, i; qindex = pindex << 4; for (i = 0; i < 16; i ++){ uint32_t queue_empty = rte_sched_port_queue_is_empty(port, qindex + i); uint32_t bmp_bit_clear = (rte_bitmap_get(port->bmp, qindex + i) == 0); if (queue_empty != bmp_bit_clear){ rte_panic("Queue status mismatch for queue %u of pipe %u\n", i, pindex); } if (!queue_empty){ return 0; } } return 1; } static inline void debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; uint32_t i, panic; if (bmp_slab == 0){ rte_panic("Empty slab at position %u\n", bmp_pos); } panic = 0; for (i = 0, mask = 1; i < 64; i ++, mask <<= 1) { if (mask & bmp_slab){ if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } } } if (panic){ rte_panic("Empty queues in slab 0x%" PRIx64 "starting at position %u\n", bmp_slab, bmp_pos); } } #endif /* RTE_SCHED_DEBUG */ static inline uint32_t rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, struct rte_mbuf *pkt) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t subport, pipe, traffic_class, queue, qindex; rte_sched_port_pkt_read_tree_path(pkt, &subport, &pipe, &traffic_class, &queue); qindex = rte_sched_port_qindex(port, subport, pipe, traffic_class, queue); q = port->queue + qindex; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS qe = port->queue_extra + qindex; rte_prefetch0(qe); #endif return qindex; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; q = port->queue + qindex; qsize = rte_sched_port_qsize(port, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); rte_bitmap_prefetch0(port->bmp, qindex); } static inline int rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf **qbase, struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; q = port->queue + qindex; qsize = rte_sched_port_qsize(port, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt); rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt); #endif return 0; } /* Enqueue packet */ qbase[q->qw & (qsize - 1)] = pkt; q->qw ++; /* Activate queue in the port bitmap */ rte_bitmap_set(port->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS rte_sched_port_update_subport_stats(port, qindex, pkt); rte_sched_port_update_queue_stats(port, qindex, pkt); #endif return 1; } #if RTE_SCHED_ENQUEUE == 0 int rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { uint32_t result, i; result = 0; for (i = 0; i < n_pkts; i ++) { struct rte_mbuf *pkt; struct rte_mbuf **q_base; uint32_t subport, pipe, traffic_class, queue, qindex; pkt = pkts[i]; rte_sched_port_pkt_read_tree_path(pkt, &subport, &pipe, &traffic_class, &queue); qindex = rte_sched_port_qindex(port, subport, pipe, traffic_class, queue); q_base = rte_sched_port_qbase(port, qindex); result += rte_sched_port_enqueue_qwa(port, qindex, q_base, pkt); } return result; } #else /* The enqueue function implements a 4-level pipeline with each stage processing * two different packets. The purpose of using a pipeline is to hide the latency * of prefetching the data structures. The naming convention is presented in the * diagram below: * * p00 _______ p10 _______ p20 _______ p30 _______ * ----->| |----->| |----->| |----->| |-----> * | 0 | | 1 | | 2 | | 3 | * ----->|_______|----->|_______|----->|_______|----->|_______|-----> * p01 p11 p21 p31 * ***/ int rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { struct rte_mbuf *pkt00, *pkt01, *pkt10, *pkt11, *pkt20, *pkt21, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; uint32_t result, i; result = 0; /* Less then 6 input packets available, which is not enough to feed the pipeline */ if (unlikely(n_pkts < 6)) { struct rte_mbuf **q_base[5]; uint32_t q[5]; /* Prefetch the mbuf structure of each packet */ for (i = 0; i < n_pkts; i ++) { rte_prefetch0(pkts[i]); } /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i ++) { q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, pkts[i]); } /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i ++) { q_base[i] = rte_sched_port_qbase(port, q[i]); rte_sched_port_enqueue_qwa_prefetch0(port, q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i ++) { result += rte_sched_port_enqueue_qwa(port, q[i], q_base[i], pkts[i]); } return result; } /* Feed the first 3 stages of the pipeline (6 packets needed) */ pkt20 = pkts[0]; pkt21 = pkts[1]; rte_prefetch0(pkt20); rte_prefetch0(pkt21); pkt10 = pkts[2]; pkt11 = pkts[3]; rte_prefetch0(pkt10); rte_prefetch0(pkt11); q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); q20_base = rte_sched_port_qbase(port, q20); q21_base = rte_sched_port_qbase(port, q21); rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { /* Propagate stage inputs */ pkt30 = pkt20; pkt31 = pkt21; pkt20 = pkt10; pkt21 = pkt11; pkt10 = pkt00; pkt11 = pkt01; q30 = q20; q31 = q21; q20 = q10; q21 = q11; q30_base = q20_base; q31_base = q21_base; /* Stage 0: Get packets in */ pkt00 = pkts[i]; pkt01 = pkts[i + 1]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); /* Stage 1: Prefetch queue structure storing queue pointers */ q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); /* Stage 2: Prefetch queue write location */ q20_base = rte_sched_port_qbase(port, q20); q21_base = rte_sched_port_qbase(port, q21); rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); result += r30 + r31; } /* Drain the pipeline (exactly 6 packets). Handle the last packet in the case of an odd number of input packets. */ pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); q10_base = rte_sched_port_qbase(port, q10); q11_base = rte_sched_port_qbase(port, q11); rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); result += r20 + r21; q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); q00_base = rte_sched_port_qbase(port, q00); q01_base = rte_sched_port_qbase(port, q01); rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); result += r10 + r11; q_last_base = rte_sched_port_qbase(port, q_last); rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); result += r_last; } return result; } #endif /* RTE_SCHED_ENQUEUE */ #if RTE_SCHED_TS_CREDITS_UPDATE == 0 #define grinder_credits_update(port, pos) #elif !defined(RTE_SCHED_SUBPORT_TC_OV) static inline void grinder_credits_update(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_subport *subport = grinder->subport; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; /* Subport TB */ n_periods = (port->time - subport->tb_time) / subport->tb_period; subport->tb_credits += n_periods * subport->tb_credits_per_period; subport->tb_credits = rte_sched_min_val_2_u32(subport->tb_credits, subport->tb_size); subport->tb_time += n_periods * subport->tb_period; /* Pipe TB */ n_periods = (port->time - pipe->tb_time) / params->tb_period; pipe->tb_credits += n_periods * params->tb_credits_per_period; pipe->tb_credits = rte_sched_min_val_2_u32(pipe->tb_credits, params->tb_size); pipe->tb_time += n_periods * params->tb_period; /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { subport->tc_credits[0] = subport->tc_credits_per_period[0]; subport->tc_credits[1] = subport->tc_credits_per_period[1]; subport->tc_credits[2] = subport->tc_credits_per_period[2]; subport->tc_credits[3] = subport->tc_credits_per_period[3]; subport->tc_time = port->time + subport->tc_period; } /* Pipe TCs */ if (unlikely(port->time >= pipe->tc_time)) { pipe->tc_credits[0] = params->tc_credits_per_period[0]; pipe->tc_credits[1] = params->tc_credits_per_period[1]; pipe->tc_credits[2] = params->tc_credits_per_period[2]; pipe->tc_credits[3] = params->tc_credits_per_period[3]; pipe->tc_time = port->time + params->tc_period; } } #else static inline uint32_t grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; if (subport->tc_ov == 0) { return subport->tc_ov_wm_max; } tc_ov_consumption[0] = subport->tc_credits_per_period[0] - subport->tc_credits[0]; tc_ov_consumption[1] = subport->tc_credits_per_period[1] - subport->tc_credits[1]; tc_ov_consumption[2] = subport->tc_credits_per_period[2] - subport->tc_credits[2]; tc_ov_consumption[3] = subport->tc_credits_per_period[3] - subport->tc_credits[3]; tc_ov_consumption_max = subport->tc_credits_per_period[3] - (tc_ov_consumption[0] + tc_ov_consumption[1] + tc_ov_consumption[2]); if (tc_ov_consumption[3] > (tc_ov_consumption_max - port->mtu)) { tc_ov_wm -= tc_ov_wm >> 7; if (tc_ov_wm < subport->tc_ov_wm_min) { tc_ov_wm = subport->tc_ov_wm_min; } return tc_ov_wm; } tc_ov_wm += (tc_ov_wm >> 7) + 1; if (tc_ov_wm > subport->tc_ov_wm_max) { tc_ov_wm = subport->tc_ov_wm_max; } return tc_ov_wm; } static inline void grinder_credits_update(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_subport *subport = grinder->subport; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; /* Subport TB */ n_periods = (port->time - subport->tb_time) / subport->tb_period; subport->tb_credits += n_periods * subport->tb_credits_per_period; subport->tb_credits = rte_sched_min_val_2_u32(subport->tb_credits, subport->tb_size); subport->tb_time += n_periods * subport->tb_period; /* Pipe TB */ n_periods = (port->time - pipe->tb_time) / params->tb_period; pipe->tb_credits += n_periods * params->tb_credits_per_period; pipe->tb_credits = rte_sched_min_val_2_u32(pipe->tb_credits, params->tb_size); pipe->tb_time += n_periods * params->tb_period; /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); subport->tc_credits[0] = subport->tc_credits_per_period[0]; subport->tc_credits[1] = subport->tc_credits_per_period[1]; subport->tc_credits[2] = subport->tc_credits_per_period[2]; subport->tc_credits[3] = subport->tc_credits_per_period[3]; subport->tc_time = port->time + subport->tc_period; subport->tc_ov_period_id ++; } /* Pipe TCs */ if (unlikely(port->time >= pipe->tc_time)) { pipe->tc_credits[0] = params->tc_credits_per_period[0]; pipe->tc_credits[1] = params->tc_credits_per_period[1]; pipe->tc_credits[2] = params->tc_credits_per_period[2]; pipe->tc_credits[3] = params->tc_credits_per_period[3]; pipe->tc_time = port->time + params->tc_period; } /* Pipe TCs - Oversubscription */ if (unlikely(pipe->tc_ov_period_id != subport->tc_ov_period_id)) { pipe->tc_ov_credits = subport->tc_ov_wm * params->tc_ov_weight; pipe->tc_ov_period_id = subport->tc_ov_period_id; } } #endif /* RTE_SCHED_TS_CREDITS_UPDATE, RTE_SCHED_SUBPORT_TC_OV */ #if RTE_SCHED_TS_CREDITS_CHECK #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int grinder_credits_check(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_subport *subport = grinder->subport; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_mbuf *pkt = grinder->pkt; uint32_t tc_index = grinder->tc_index; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t subport_tb_credits = subport->tb_credits; uint32_t subport_tc_credits = subport->tc_credits[tc_index]; uint32_t pipe_tb_credits = pipe->tb_credits; uint32_t pipe_tc_credits = pipe->tc_credits[tc_index]; int enough_credits; /* Check queue credits */ enough_credits = (pkt_len <= subport_tb_credits) && (pkt_len <= subport_tc_credits) && (pkt_len <= pipe_tb_credits) && (pkt_len <= pipe_tc_credits); if (!enough_credits) { return 0; } /* Update port credits */ subport->tb_credits -= pkt_len; subport->tc_credits[tc_index] -= pkt_len; pipe->tb_credits -= pkt_len; pipe->tc_credits[tc_index] -= pkt_len; return 1; } #else static inline int grinder_credits_check(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_subport *subport = grinder->subport; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_mbuf *pkt = grinder->pkt; uint32_t tc_index = grinder->tc_index; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t subport_tb_credits = subport->tb_credits; uint32_t subport_tc_credits = subport->tc_credits[tc_index]; uint32_t pipe_tb_credits = pipe->tb_credits; uint32_t pipe_tc_credits = pipe->tc_credits[tc_index]; uint32_t pipe_tc_ov_mask1[] = {UINT32_MAX, UINT32_MAX, UINT32_MAX, pipe->tc_ov_credits}; uint32_t pipe_tc_ov_mask2[] = {0, 0, 0, UINT32_MAX}; uint32_t pipe_tc_ov_credits = pipe_tc_ov_mask1[tc_index]; int enough_credits; /* Check pipe and subport credits */ enough_credits = (pkt_len <= subport_tb_credits) && (pkt_len <= subport_tc_credits) && (pkt_len <= pipe_tb_credits) && (pkt_len <= pipe_tc_credits) && (pkt_len <= pipe_tc_ov_credits); if (!enough_credits) { return 0; } /* Update pipe and subport credits */ subport->tb_credits -= pkt_len; subport->tc_credits[tc_index] -= pkt_len; pipe->tb_credits -= pkt_len; pipe->tc_credits[tc_index] -= pkt_len; pipe->tc_ov_credits -= pipe_tc_ov_mask2[tc_index] & pkt_len; return 1; } #endif /* RTE_SCHED_SUBPORT_TC_OV */ #endif /* RTE_SCHED_TS_CREDITS_CHECK */ static inline int grinder_schedule(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; #if RTE_SCHED_TS_CREDITS_CHECK if (!grinder_credits_check(port, pos)) { return 0; } #endif /* Advance port time */ port->time += pkt_len; /* Send packet */ port->pkts_out[port->n_pkts_out ++] = pkt; queue->qr ++; grinder->wrr_tokens[grinder->qpos] += pkt_len * grinder->wrr_cost[grinder->qpos]; if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; rte_bitmap_clear(port->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); grinder->wrr_mask[grinder->qpos] = 0; rte_sched_port_set_queue_empty_timestamp(port, qindex); } /* Reset pipe loop detection */ port->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; } #if RTE_SCHED_OPTIMIZATIONS static inline int grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) { __m128i index = _mm_set1_epi32 (base_pipe); __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); if (_mm_testz_si128(res, res)) return 0; return 1; } #else static inline int grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i ++) { if (port->grinder_base_bmp_pos[i] == base_pipe) { return 1; } } return 0; } #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { struct rte_sched_grinder *grinder = port->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; grinder->pcache_r = 0; w[0] = (uint16_t) bmp_slab; w[1] = (uint16_t) (bmp_slab >> 16); w[2] = (uint16_t) (bmp_slab >> 32); w[3] = (uint16_t) (bmp_slab >> 48); grinder->pcache_qmask[grinder->pcache_w] = w[0]; grinder->pcache_qindex[grinder->pcache_w] = bmp_pos; grinder->pcache_w += (w[0] != 0); grinder->pcache_qmask[grinder->pcache_w] = w[1]; grinder->pcache_qindex[grinder->pcache_w] = bmp_pos + 16; grinder->pcache_w += (w[1] != 0); grinder->pcache_qmask[grinder->pcache_w] = w[2]; grinder->pcache_qindex[grinder->pcache_w] = bmp_pos + 32; grinder->pcache_w += (w[2] != 0); grinder->pcache_qmask[grinder->pcache_w] = w[3]; grinder->pcache_qindex[grinder->pcache_w] = bmp_pos + 48; grinder->pcache_w += (w[3] != 0); } static inline void grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) { struct rte_sched_grinder *grinder = port->grinder + pos; uint8_t b[4]; grinder->tccache_w = 0; grinder->tccache_r = 0; b[0] = (uint8_t) (qmask & 0xF); b[1] = (uint8_t) ((qmask >> 4) & 0xF); b[2] = (uint8_t) ((qmask >> 8) & 0xF); b[3] = (uint8_t) ((qmask >> 12) & 0xF); grinder->tccache_qmask[grinder->tccache_w] = b[0]; grinder->tccache_qindex[grinder->tccache_w] = qindex; grinder->tccache_w += (b[0] != 0); grinder->tccache_qmask[grinder->tccache_w] = b[1]; grinder->tccache_qindex[grinder->tccache_w] = qindex + 4; grinder->tccache_w += (b[1] != 0); grinder->tccache_qmask[grinder->tccache_w] = b[2]; grinder->tccache_qindex[grinder->tccache_w] = qindex + 8; grinder->tccache_w += (b[2] != 0); grinder->tccache_qmask[grinder->tccache_w] = b[3]; grinder->tccache_qindex[grinder->tccache_w] = qindex + 12; grinder->tccache_w += (b[3] != 0); } static inline int grinder_next_tc(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; if (grinder->tccache_r == grinder->tccache_w) { return 0; } qindex = grinder->tccache_qindex[grinder->tccache_r]; qbase = rte_sched_port_qbase(port, qindex); qsize = rte_sched_port_qsize(port, qindex); grinder->tc_index = (qindex >> 2) & 0x3; grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; grinder->qindex[0] = qindex; grinder->qindex[1] = qindex + 1; grinder->qindex[2] = qindex + 2; grinder->qindex[3] = qindex + 3; grinder->queue[0] = port->queue + qindex; grinder->queue[1] = port->queue + qindex + 1; grinder->queue[2] = port->queue + qindex + 2; grinder->queue[3] = port->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; grinder->qbase[2] = qbase + 2 * qsize; grinder->qbase[3] = qbase + 3 * qsize; grinder->tccache_r ++; return 1; } static inline int grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; if (grinder->pcache_r < grinder->pcache_w) { pipe_qmask = grinder->pcache_qmask[grinder->pcache_r]; pipe_qindex = grinder->pcache_qindex[grinder->pcache_r]; grinder->pcache_r ++; } else { uint64_t bmp_slab = 0; uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) { return 0; } #if RTE_SCHED_DEBUG debug_check_queue_slab(port, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; if (unlikely(grinder_pipe_exists(port, bmp_pos))) { return 0; } port->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; grinder->pcache_r = 1; } /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); grinder->pipe = port->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); grinder_next_tc(port, pos); /* Check for pipe exhaustion */ if (grinder->pindex == port->pipe_loop) { port->pipe_exhaustion = 1; port->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; } #if RTE_SCHED_WRR == 0 #define grinder_wrr_load(a,b) #define grinder_wrr_store(a,b) static inline void grinder_wrr(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; uint64_t slab = grinder->qmask; if (rte_bsf64(slab, &grinder->qpos) == 0) { rte_panic("grinder wrr\n"); } } #elif RTE_SCHED_WRR == 1 static inline void grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t tc_index = grinder->tc_index; uint32_t qmask = grinder->qmask; uint32_t qindex; qindex = tc_index * 4; grinder->wrr_tokens[0] = ((uint16_t) pipe->wrr_tokens[qindex]) << RTE_SCHED_WRR_SHIFT; grinder->wrr_tokens[1] = ((uint16_t) pipe->wrr_tokens[qindex + 1]) << RTE_SCHED_WRR_SHIFT; grinder->wrr_tokens[2] = ((uint16_t) pipe->wrr_tokens[qindex + 2]) << RTE_SCHED_WRR_SHIFT; grinder->wrr_tokens[3] = ((uint16_t) pipe->wrr_tokens[qindex + 3]) << RTE_SCHED_WRR_SHIFT; grinder->wrr_mask[0] = (qmask & 0x1) * 0xFFFF; grinder->wrr_mask[1] = ((qmask >> 1) & 0x1) * 0xFFFF; grinder->wrr_mask[2] = ((qmask >> 2) & 0x1) * 0xFFFF; grinder->wrr_mask[3] = ((qmask >> 3) & 0x1) * 0xFFFF; grinder->wrr_cost[0] = pipe_params->wrr_cost[qindex]; grinder->wrr_cost[1] = pipe_params->wrr_cost[qindex + 1]; grinder->wrr_cost[2] = pipe_params->wrr_cost[qindex + 2]; grinder->wrr_cost[3] = pipe_params->wrr_cost[qindex + 3]; } static inline void grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; uint32_t tc_index = grinder->tc_index; uint32_t qindex; qindex = tc_index * 4; pipe->wrr_tokens[qindex] = (uint8_t) ((grinder->wrr_tokens[0] & grinder->wrr_mask[0]) >> RTE_SCHED_WRR_SHIFT); pipe->wrr_tokens[qindex + 1] = (uint8_t) ((grinder->wrr_tokens[1] & grinder->wrr_mask[1]) >> RTE_SCHED_WRR_SHIFT); pipe->wrr_tokens[qindex + 2] = (uint8_t) ((grinder->wrr_tokens[2] & grinder->wrr_mask[2]) >> RTE_SCHED_WRR_SHIFT); pipe->wrr_tokens[qindex + 3] = (uint8_t) ((grinder->wrr_tokens[3] & grinder->wrr_mask[3]) >> RTE_SCHED_WRR_SHIFT); } static inline void grinder_wrr(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; grinder->wrr_tokens[1] |= ~grinder->wrr_mask[1]; grinder->wrr_tokens[2] |= ~grinder->wrr_mask[2]; grinder->wrr_tokens[3] |= ~grinder->wrr_mask[3]; grinder->qpos = rte_min_pos_4_u16(grinder->wrr_tokens); wrr_tokens_min = grinder->wrr_tokens[grinder->qpos]; grinder->wrr_tokens[0] -= wrr_tokens_min; grinder->wrr_tokens[1] -= wrr_tokens_min; grinder->wrr_tokens[2] -= wrr_tokens_min; grinder->wrr_tokens[3] -= wrr_tokens_min; } #else #error Invalid value for RTE_SCHED_WRR #endif /* RTE_SCHED_WRR */ #define grinder_evict(port, pos) static inline void grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; uint16_t qsize, qr[4]; qsize = grinder->qsize; qr[0] = grinder->queue[0]->qr & (qsize - 1); qr[1] = grinder->queue[1]->qr & (qsize - 1); qr[2] = grinder->queue[2]->qr & (qsize - 1); qr[3] = grinder->queue[3]->qr & (qsize - 1); rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); grinder_wrr_load(port, pos); grinder_wrr(port, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; uint16_t qr = grinder->queue[qpos]->qr & (qsize - 1); grinder->pkt = qbase[qr]; rte_prefetch0(grinder->pkt); if (unlikely((qr & 0x7) == 7)) { uint16_t qr_next = (grinder->queue[qpos]->qr + 1) & (qsize - 1); rte_prefetch0(qbase + qr_next); } } static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_grinder *grinder = port->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { if (grinder_next_pipe(port, pos)) { grinder_prefetch_pipe(port, pos); port->busy_grinders ++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; } return 0; } case e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS: { struct rte_sched_pipe *pipe = grinder->pipe; grinder->pipe_params = port->pipe_profiles + pipe->profile; grinder_prefetch_tc_queue_arrays(port, pos); grinder_credits_update(port, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; } case e_GRINDER_PREFETCH_MBUF: { grinder_prefetch_mbuf(port, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; } case e_GRINDER_READ_MBUF: { uint32_t result = 0; result = grinder_schedule(port, pos); /* Look for next packet within the same TC */ if (result && grinder->qmask) { grinder_wrr(port, pos); grinder_prefetch_mbuf(port, pos); return 1; } grinder_wrr_store(port, pos); /* Look for another active TC within same pipe */ if (grinder_next_tc(port, pos)) { grinder_prefetch_tc_queue_arrays(port, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if ((grinder->productive == 0) && (port->pipe_loop == RTE_SCHED_PIPE_INVALID)) { port->pipe_loop = grinder->pindex; } grinder_evict(port, pos); /* Look for another active pipe */ if (grinder_next_pipe(port, pos)) { grinder_prefetch_pipe(port, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ port->busy_grinders --; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; } default: rte_panic("Algorithmic error (invalid state)\n"); return 0; } } static inline void rte_sched_port_time_resync(struct rte_sched_port *port) { uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; double bytes_diff = ((double) cycles_diff) / port->cycles_per_byte; /* Advance port time */ port->time_cpu_cycles = cycles; port->time_cpu_bytes += (uint64_t) bytes_diff; if (port->time < port->time_cpu_bytes) { port->time = port->time_cpu_bytes; } /* Reset pipe loop detection */ port->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) { int exceptions; /* Check if any exception flag is set */ exceptions = (second_pass && port->busy_grinders == 0) || (port->pipe_exhaustion == 1); /* Clear exception flags */ port->pipe_exhaustion = 0; return exceptions; } int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { uint32_t i, count; port->pkts_out = pkts; port->n_pkts_out = 0; rte_sched_port_time_resync(port); /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i ++) { count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); if ((count == n_pkts) || rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { break; } } return count; } ================================================ FILE: lib/librte_sched/rte_sched.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_SCHED_H__ #define __INCLUDE_RTE_SCHED_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Hierarchical Scheduler * * The hierarchical scheduler prioritizes the transmission of packets from different * users and traffic classes according to the Service Level Agreements (SLAs) defined * for the current network node. * * The scheduler supports thousands of packet queues grouped under a 5-level hierarchy: * 1. Port: * - Typical usage: output Ethernet port; * - Multiple ports are scheduled in round robin order with equal priority; * 2. Subport: * - Typical usage: group of users; * - Traffic shaping using the token bucket algorithm (one bucket per subport); * - Upper limit enforced per traffic class at subport level; * - Lower priority traffic classes able to reuse subport bandwidth currently * unused by higher priority traffic classes of the same subport; * - When any subport traffic class is oversubscribed (configuration time * event), the usage of subport member pipes with high demand for that * traffic class pipes is truncated to a dynamically adjusted value with no * impact to low demand pipes; * 3. Pipe: * - Typical usage: individual user/subscriber; * - Traffic shaping using the token bucket algorithm (one bucket per pipe); * 4. Traffic class: * - Traffic classes of the same pipe handled in strict priority order; * - Upper limit enforced per traffic class at the pipe level; * - Lower priority traffic classes able to reuse pipe bandwidth currently * unused by higher priority traffic classes of the same pipe; * 5. Queue: * - Typical usage: queue hosting packets from one or multiple connections * of same traffic class belonging to the same user; * - Weighted Round Robin (WRR) is used to service the queues within same * pipe traffic class. * ***/ #include #include #include /** Random Early Detection (RED) */ #ifdef RTE_SCHED_RED #include "rte_red.h" #endif /** Number of traffic classes per pipe (as well as subport). Cannot be changed. */ #define RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE 4 /** Number of queues per pipe traffic class. Cannot be changed. */ #define RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS 4 /** Number of queues per pipe. */ #define RTE_SCHED_QUEUES_PER_PIPE \ (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE * \ RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS) /** Maximum number of pipe profiles that can be defined per port. Compile-time configurable.*/ #ifndef RTE_SCHED_PIPE_PROFILES_PER_PORT #define RTE_SCHED_PIPE_PROFILES_PER_PORT 256 #endif /** Ethernet framing overhead. Overhead fields per Ethernet frame: 1. Preamble: 7 bytes; 2. Start of Frame Delimiter (SFD): 1 byte; 3. Frame Check Sequence (FCS): 4 bytes; 4. Inter Frame Gap (IFG): 12 bytes. The FCS is considered overhead only if not included in the packet length (field pkt_len of struct rte_mbuf). */ #ifndef RTE_SCHED_FRAME_OVERHEAD_DEFAULT #define RTE_SCHED_FRAME_OVERHEAD_DEFAULT 24 #endif /** Subport configuration parameters. The period and credits_per_period parameters are measured in bytes, with one byte meaning the time duration associated with the transmission of one byte on the physical medium of the output port, with pipe or pipe traffic class rate (measured as percentage of output port rate) determined as credits_per_period divided by period. One credit represents one byte. */ struct rte_sched_subport_params { /* Subport token bucket */ uint32_t tb_rate; /**< Subport token bucket rate (measured in bytes per second) */ uint32_t tb_size; /**< Subport token bucket size (measured in credits) */ /* Subport traffic classes */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Subport traffic class rates (measured in bytes per second) */ uint32_t tc_period; /**< Enforcement period for traffic class rates (measured in milliseconds) */ }; /** Subport statistics */ struct rte_sched_subport_stats { /* Packets */ uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of packets successfully written to current subport for each traffic class */ uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of packets dropped by the current subport for each traffic class due to subport queues being full or congested*/ /* Bytes */ uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of bytes successfully written to current subport for each traffic class*/ uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Number of bytes dropped by the current subport for each traffic class due to subport queues being full or congested */ }; /** Pipe configuration parameters. The period and credits_per_period parameters are measured in bytes, with one byte meaning the time duration associated with the transmission of one byte on the physical medium of the output port, with pipe or pipe traffic class rate (measured as percentage of output port rate) determined as credits_per_period divided by period. One credit represents one byte. */ struct rte_sched_pipe_params { /* Pipe token bucket */ uint32_t tb_rate; /**< Pipe token bucket rate (measured in bytes per second) */ uint32_t tb_size; /**< Pipe token bucket size (measured in credits) */ /* Pipe traffic classes */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Pipe traffic class rates (measured in bytes per second) */ uint32_t tc_period; /**< Enforcement period for pipe traffic class rates (measured in milliseconds) */ #ifdef RTE_SCHED_SUBPORT_TC_OV uint8_t tc_ov_weight; /**< Weight for the current pipe in the event of subport traffic class 3 oversubscription */ #endif /* Pipe queues */ uint8_t wrr_weights[RTE_SCHED_QUEUES_PER_PIPE]; /**< WRR weights for the queues of the current pipe */ }; /** Queue statistics */ struct rte_sched_queue_stats { /* Packets */ uint32_t n_pkts; /**< Number of packets successfully written to current queue */ uint32_t n_pkts_dropped; /**< Number of packets dropped due to current queue being full or congested */ /* Bytes */ uint32_t n_bytes; /**< Number of bytes successfully written to current queue */ uint32_t n_bytes_dropped; /**< Number of bytes dropped due to current queue being full or congested */ }; /** Port configuration parameters. */ struct rte_sched_port_params { const char *name; /**< Literal string to be associated to the current port scheduler instance */ int socket; /**< CPU socket ID where the memory for port scheduler should be allocated */ uint32_t rate; /**< Output port rate (measured in bytes per second) */ uint32_t mtu; /**< Maximum Ethernet frame size (measured in bytes). Should not include the framing overhead. */ uint32_t frame_overhead; /**< Framing overhead per packet (measured in bytes) */ uint32_t n_subports_per_port; /**< Number of subports for the current port scheduler instance*/ uint32_t n_pipes_per_subport; /**< Number of pipes for each port scheduler subport */ uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /**< Packet queue size for each traffic class. All queues within the same pipe traffic class have the same size. Queues from different pipes serving the same traffic class have the same size. */ struct rte_sched_pipe_params *pipe_profiles; /**< Pipe profile table defined for current port scheduler instance. Every pipe of the current port scheduler is configured using one of the profiles from this table. */ uint32_t n_pipe_profiles; /**< Number of profiles in the pipe profile table */ #ifdef RTE_SCHED_RED struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][e_RTE_METER_COLORS]; /**< RED parameters */ #endif }; /* * Path through scheduler hierarchy * * Note: direct access to internal bitfields is deprecated to allow for future expansion. * Use rte_sched_port_pkt_read/write API instead */ struct rte_sched_port_hierarchy { uint32_t queue:2; /**< Queue ID (0 .. 3) */ uint32_t traffic_class:2; /**< Traffic class ID (0 .. 3)*/ uint32_t pipe:20; /**< Pipe ID */ uint32_t subport:6; /**< Subport ID */ uint32_t color:2; /**< Color */ } __attribute__ ((deprecated)); /* * Configuration * ***/ /** * Hierarchical scheduler port configuration * * @param params * Port scheduler configuration parameter structure * @return * Handle to port scheduler instance upon success or NULL otherwise. */ struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params); /** * Hierarchical scheduler port free * * @param port * Handle to port scheduler instance */ void rte_sched_port_free(struct rte_sched_port *port); /** * Hierarchical scheduler subport configuration * * @param port * Handle to port scheduler instance * @param subport_id * Subport ID * @param params * Subport configuration parameters * @return * 0 upon success, error code otherwise */ int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params); /** * Hierarchical scheduler pipe configuration * * @param port * Handle to port scheduler instance * @param subport_id * Subport ID * @param pipe_id * Pipe ID within subport * @param pipe_profile * ID of port-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ int rte_sched_pipe_config(struct rte_sched_port *port, uint32_t subport_id, uint32_t pipe_id, int32_t pipe_profile); /** * Hierarchical scheduler memory footprint size per port * * @param params * Port scheduler configuration parameter structure * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); /* * Statistics * ***/ /** * Hierarchical scheduler subport statistics read * * @param port * Handle to port scheduler instance * @param subport_id * Subport ID * @param stats * Pointer to pre-allocated subport statistics structure where the statistics * counters should be stored * @param tc_ov * Pointer to pre-allocated 4-entry array where the oversubscription status for * each of the 4 subport traffic classes should be stored. * @return * 0 upon success, error code otherwise */ int rte_sched_subport_read_stats(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_stats *stats, uint32_t *tc_ov); /** * Hierarchical scheduler queue statistics read * * @param port * Handle to port scheduler instance * @param queue_id * Queue ID within port scheduler * @param stats * Pointer to pre-allocated subport statistics structure where the statistics * counters should be stored * @param qlen * Pointer to pre-allocated variable where the current queue length should be stored. * @return * 0 upon success, error code otherwise */ int rte_sched_queue_read_stats(struct rte_sched_port *port, uint32_t queue_id, struct rte_sched_queue_stats *stats, uint16_t *qlen); /** * Scheduler hierarchy path write to packet descriptor. Typically called by the * packet classification stage. * * @param pkt * Packet descriptor handle * @param subport * Subport ID * @param pipe * Pipe ID within subport * @param traffic_class * Traffic class ID within pipe (0 .. 3) * @param queue * Queue ID within pipe traffic class (0 .. 3) * @param color * Packet color set */ void rte_sched_port_pkt_write(struct rte_mbuf *pkt, uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue, enum rte_meter_color color); /** * Scheduler hierarchy path read from packet descriptor (struct rte_mbuf). Typically * called as part of the hierarchical scheduler enqueue operation. The subport, * pipe, traffic class and queue parameters need to be pre-allocated by the caller. * * @param pkt * Packet descriptor handle * @param subport * Subport ID * @param pipe * Pipe ID within subport * @param traffic_class * Traffic class ID within pipe (0 .. 3) * @param queue * Queue ID within pipe traffic class (0 .. 3) * */ void rte_sched_port_pkt_read_tree_path(const struct rte_mbuf *pkt, uint32_t *subport, uint32_t *pipe, uint32_t *traffic_class, uint32_t *queue); enum rte_meter_color rte_sched_port_pkt_read_color(const struct rte_mbuf *pkt); /** * Hierarchical scheduler port enqueue. Writes up to n_pkts to port scheduler and * returns the number of packets actually written. For each packet, the port scheduler * queue to write the packet to is identified by reading the hierarchy path from the * packet descriptor; if the queue is full or congested and the packet is not written * to the queue, then the packet is automatically dropped without any action required * from the caller. * * @param port * Handle to port scheduler instance * @param pkts * Array storing the packet descriptor handles * @param n_pkts * Number of packets to enqueue from the pkts array into the port scheduler * @return * Number of packets successfully enqueued */ int rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts); /** * Hierarchical scheduler port dequeue. Reads up to n_pkts from the port scheduler * and stores them in the pkts array and returns the number of packets actually read. * The pkts array needs to be pre-allocated by the caller with at least n_pkts entries. * * @param port * Handle to port scheduler instance * @param pkts * Pre-allocated packet descriptor array where the packets dequeued from the port * scheduler should be stored * @param n_pkts * Number of packets to dequeue from the port scheduler * @return * Number of packets successfully dequeued and placed in the pkts array */ int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts); #ifdef __cplusplus } #endif #endif /* __INCLUDE_RTE_SCHED_H__ */ ================================================ FILE: lib/librte_sched/rte_sched_common.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_SCHED_COMMON_H__ #define __INCLUDE_RTE_SCHED_COMMON_H__ #ifdef __cplusplus extern "C" { #endif #include #define __rte_aligned_16 __attribute__((__aligned__(16))) static inline uint32_t rte_sched_min_val_2_u32(uint32_t x, uint32_t y) { return (x < y)? x : y; } #if 0 static inline uint32_t rte_min_pos_4_u16(uint16_t *x) { uint32_t pos0, pos1; pos0 = (x[0] <= x[1])? 0 : 1; pos1 = (x[2] <= x[3])? 2 : 3; return (x[pos0] <= x[pos1])? pos0 : pos1; } #else /* simplified version to remove branches with CMOV instruction */ static inline uint32_t rte_min_pos_4_u16(uint16_t *x) { uint32_t pos0 = 0; uint32_t pos1 = 2; if (x[1] <= x[0]) pos0 = 1; if (x[3] <= x[2]) pos1 = 3; if (x[pos1] <= x[pos0]) pos0 = pos1; return pos0; } #endif /* * Compute the Greatest Common Divisor (GCD) of two numbers. * This implementation uses Euclid's algorithm: * gcd(a, 0) = a * gcd(a, b) = gcd(b, a mod b) * */ static inline uint32_t rte_get_gcd(uint32_t a, uint32_t b) { uint32_t c; if (a == 0) return b; if (b == 0) return a; if (a < b) { c = a; a = b; b = c; } while (b != 0) { c = a % b; a = b; b = c; } return a; } /* * Compute the Lowest Common Denominator (LCD) of two numbers. * This implementation computes GCD first: * LCD(a, b) = (a * b) / GCD(a, b) * */ static inline uint32_t rte_get_lcd(uint32_t a, uint32_t b) { return (a * b) / rte_get_gcd(a, b); } #ifdef __cplusplus } #endif #endif /* __INCLUDE_RTE_SCHED_COMMON_H__ */ ================================================ FILE: lib/librte_table/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # # library name # LIB = librte_table.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) EXPORT_MAP := rte_table_version.map LIBABIVER := 1 # # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_lpm.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_lpm_ipv6.c ifeq ($(CONFIG_RTE_LIBRTE_ACL),y) SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_acl.c endif SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_hash_key8.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_hash_key16.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_hash_key32.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_hash_ext.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_hash_lru.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_array.c SRCS-$(CONFIG_RTE_LIBRTE_TABLE) += rte_table_stub.c # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table.h SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_lpm.h SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_lpm_ipv6.h ifeq ($(CONFIG_RTE_LIBRTE_ACL),y) SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_acl.h endif SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_hash.h SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_lru.h SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_array.h SYMLINK-$(CONFIG_RTE_LIBRTE_TABLE)-include += rte_table_stub.h # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) := lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_mbuf DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_mempool DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_port DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_lpm ifeq ($(CONFIG_RTE_LIBRTE_ACL),y) DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_acl endif DEPDIRS-$(CONFIG_RTE_LIBRTE_TABLE) += lib/librte_hash include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_table/rte_lru.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_LRU_H__ #define __INCLUDE_RTE_LRU_H__ #ifdef __cplusplus extern "C" { #endif #include #ifdef __INTEL_COMPILER #define GCC_VERSION (0) #else #define GCC_VERSION (__GNUC__ * 10000+__GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) #endif #ifndef RTE_TABLE_HASH_LRU_STRATEGY #ifdef __SSE4_2__ #define RTE_TABLE_HASH_LRU_STRATEGY 2 #else /* if no SSE, use simple scalar version */ #define RTE_TABLE_HASH_LRU_STRATEGY 1 #endif #endif #ifndef RTE_ARCH_X86_64 #undef RTE_TABLE_HASH_LRU_STRATEGY #define RTE_TABLE_HASH_LRU_STRATEGY 1 #endif #if (RTE_TABLE_HASH_LRU_STRATEGY < 0) || (RTE_TABLE_HASH_LRU_STRATEGY > 3) #error Invalid value for RTE_TABLE_HASH_LRU_STRATEGY #endif #if RTE_TABLE_HASH_LRU_STRATEGY == 0 #define lru_init(bucket) \ do \ bucket = bucket; \ while (0) #define lru_pos(bucket) (bucket->lru_list & 0xFFFFLLU) #define lru_update(bucket, mru_val) \ do { \ bucket = bucket; \ mru_val = mru_val; \ } while (0) #elif RTE_TABLE_HASH_LRU_STRATEGY == 1 #define lru_init(bucket) \ do \ bucket->lru_list = 0x0000000100020003LLU; \ while (0) #define lru_pos(bucket) (bucket->lru_list & 0xFFFFLLU) #define lru_update(bucket, mru_val) \ do { \ uint64_t x, pos, x0, x1, x2, mask; \ \ x = bucket->lru_list; \ \ pos = 4; \ if ((x >> 48) == ((uint64_t) mru_val)) \ pos = 3; \ \ if (((x >> 32) & 0xFFFFLLU) == ((uint64_t) mru_val)) \ pos = 2; \ \ if (((x >> 16) & 0xFFFFLLU) == ((uint64_t) mru_val)) \ pos = 1; \ \ if ((x & 0xFFFFLLU) == ((uint64_t) mru_val)) \ pos = 0; \ \ \ pos <<= 4; \ mask = (~0LLU) << pos; \ x0 = x & (~mask); \ x1 = (x >> 16) & mask; \ x2 = (x << (48 - pos)) & (0xFFFFLLU << 48); \ x = x0 | x1 | x2; \ \ if (pos != 64) \ bucket->lru_list = x; \ } while (0) #elif RTE_TABLE_HASH_LRU_STRATEGY == 2 #if GCC_VERSION > 40306 #include #else #include #include #include #endif #define lru_init(bucket) \ do \ bucket->lru_list = 0x0000000100020003LLU; \ while (0) #define lru_pos(bucket) (bucket->lru_list & 0xFFFFLLU) #define lru_update(bucket, mru_val) \ do { \ /* set up the masks for all possible shuffles, depends on pos */\ static uint64_t masks[10] = { \ /* Shuffle order; Make Zero (see _mm_shuffle_epi8 manual) */\ 0x0100070605040302, 0x8080808080808080, \ 0x0302070605040100, 0x8080808080808080, \ 0x0504070603020100, 0x8080808080808080, \ 0x0706050403020100, 0x8080808080808080, \ 0x0706050403020100, 0x8080808080808080}; \ /* load up one register with repeats of mru-val */ \ uint64_t mru2 = mru_val; \ uint64_t mru3 = mru2 | (mru2 << 16); \ uint64_t lru = bucket->lru_list; \ /* XOR to cause the word we're looking for to go to zero */ \ uint64_t mru = lru ^ ((mru3 << 32) | mru3); \ __m128i c = _mm_cvtsi64_si128(mru); \ __m128i b = _mm_cvtsi64_si128(lru); \ /* Find the minimum value (first zero word, if it's in there) */\ __m128i d = _mm_minpos_epu16(c); \ /* Second word is the index to found word (first word is the value) */\ unsigned pos = _mm_extract_epi16(d, 1); \ /* move the recently used location to top of list */ \ __m128i k = _mm_shuffle_epi8(b, *((__m128i *) &masks[2 * pos]));\ /* Finally, update the original list with the reordered data */ \ bucket->lru_list = _mm_extract_epi64(k, 0); \ /* Phwew! */ \ } while (0) #elif RTE_TABLE_HASH_LRU_STRATEGY == 3 #if GCC_VERSION > 40306 #include #else #include #include #include #endif #define lru_init(bucket) \ do \ bucket->lru_list = ~0LLU; \ while (0) static inline int f_lru_pos(uint64_t lru_list) { __m128i lst = _mm_set_epi64x((uint64_t)-1, lru_list); __m128i min = _mm_minpos_epu16(lst); return _mm_extract_epi16(min, 1); } #define lru_pos(bucket) f_lru_pos(bucket->lru_list) #define lru_update(bucket, mru_val) \ do { \ const uint64_t orvals[] = {0xFFFFLLU, 0xFFFFLLU << 16, \ 0xFFFFLLU << 32, 0xFFFFLLU << 48, 0LLU}; \ const uint64_t decs[] = {0x1000100010001LLU, 0}; \ __m128i lru = _mm_cvtsi64_si128(bucket->lru_list); \ __m128i vdec = _mm_cvtsi64_si128(decs[mru_val>>2]); \ lru = _mm_subs_epu16(lru, vdec); \ bucket->lru_list = _mm_extract_epi64(lru, 0) | orvals[mru_val]; \ } while (0) #else #error "Incorrect value for RTE_TABLE_HASH_LRU_STRATEGY" #endif #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_H__ #define __INCLUDE_RTE_TABLE_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table * * This tool is part of the Intel DPDK Packet Framework tool suite and provides * a standard interface to implement different types of lookup tables for data * plane processing. * * Virtually any search algorithm that can uniquely associate data to a lookup * key can be fitted under this lookup table abstraction. For the flow table * use-case, the lookup key is an n-tuple of packet fields that uniquely * identifies a traffic flow, while data represents actions and action * meta-data associated with the same traffic flow. * ***/ #include #include struct rte_mbuf; /** Lookup table statistics */ struct rte_table_stats { uint64_t n_pkts_in; uint64_t n_pkts_lookup_miss; }; /** * Lookup table create * * @param params * Parameters for lookup table creation. The underlying data structure is * different for each lookup table type. * @param socket_id * CPU socket ID (e.g. for memory allocation purpose) * @param entry_size * Data size of each lookup table entry (measured in bytes) * @return * Handle to lookup table instance */ typedef void* (*rte_table_op_create)(void *params, int socket_id, uint32_t entry_size); /** * Lookup table free * * @param table * Handle to lookup table instance * @return * 0 on success, error code otherwise */ typedef int (*rte_table_op_free)(void *table); /** * Lookup table entry add * * @param table * Handle to lookup table instance * @param key * Lookup key * @param entry * Data to be associated with the current key. This parameter has to point to * a valid memory buffer where the first entry_size bytes (table create * parameter) are populated with the data. * @param key_found * After successful invocation, *key_found is set to a value different than 0 * if the current key is already present in the table and to 0 if not. This * pointer has to be set to a valid memory location before the table entry add * function is called. * @param entry_ptr * After successful invocation, *entry_ptr stores the handle to the table * entry containing the data associated with the current key. This handle can * be used to perform further read-write accesses to this entry. This handle * is valid until the key is deleted from the table or the same key is * re-added to the table, typically to associate it with different data. This * pointer has to be set to a valid memory location before the function is * called. * @return * 0 on success, error code otherwise */ typedef int (*rte_table_op_entry_add)( void *table, void *key, void *entry, int *key_found, void **entry_ptr); /** * Lookup table entry delete * * @param table * Handle to lookup table instance * @param key * Lookup key * @param key_found * After successful invocation, *key_found is set to a value different than 0 * if the current key was present in the table before the delete operation * was performed and to 0 if not. This pointer has to be set to a valid * memory location before the table entry delete function is called. * @param entry * After successful invocation, if the key is found in the table (*key found * is different than 0 after function call is completed) and entry points to * a valid buffer (entry is set to a value different than NULL before the * function is called), then the first entry_size bytes (table create * parameter) in *entry store a copy of table entry that contained the data * associated with the current key before the key was deleted. * @return * 0 on success, error code otherwise */ typedef int (*rte_table_op_entry_delete)( void *table, void *key, int *key_found, void *entry); /** * Lookup table lookup * * @param table * Handle to lookup table instance * @param pkts * Burst of input packets specified as array of up to 64 pointers to struct * rte_mbuf * @param pkts_mask * 64-bit bitmask specifying which packets in the input burst are valid. When * pkts_mask bit n is set, then element n of pkts array is pointing to a * valid packet. Otherwise, element n of pkts array does not point to a valid * packet, therefore it will not be accessed. * @param lookup_hit_mask * Once the table lookup operation is completed, this 64-bit bitmask * specifies which of the valid packets in the input burst resulted in lookup * hit. For each valid input packet (pkts_mask bit n is set), the following * are true on lookup hit: lookup_hit_mask bit n is set, element n of entries * array is valid and it points to the lookup table entry that was hit. For * each valid input packet (pkts_mask bit n is set), the following are true * on lookup miss: lookup_hit_mask bit n is not set and element n of entries * array is not valid. * @param entries * Once the table lookup operation is completed, this array provides the * lookup table entries that were hit, as described above. It is required * that this array is always pre-allocated by the caller of this function * with exactly 64 elements. The implementation is allowed to speculatively * modify the elements of this array, so elements marked as invalid in * lookup_hit_mask once the table lookup operation is completed might have * been modified by this function. * @return * 0 on success, error code otherwise */ typedef int (*rte_table_op_lookup)( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries); /** * Lookup table stats read * * @param table * Handle to lookup table instance * @param stats * Handle to table stats struct to copy data * @param clear * Flag indicating that stats should be cleared after read * * @return * Error code or 0 on success. */ typedef int (*rte_table_op_stats_read)( void *table, struct rte_table_stats *stats, int clear); /** Lookup table interface defining the lookup table operation */ struct rte_table_ops { rte_table_op_create f_create; /**< Create */ rte_table_op_free f_free; /**< Free */ rte_table_op_entry_add f_add; /**< Entry add */ rte_table_op_entry_delete f_delete; /**< Entry delete */ rte_table_op_lookup f_lookup; /**< Lookup */ rte_table_op_stats_read f_stats; /**< Stats */ }; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_acl.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_acl.h" #include #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_ACL_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_ACL_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_ACL_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_ACL_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_table_acl { struct rte_table_stats stats; /* Low-level ACL table */ char name[2][RTE_ACL_NAMESIZE]; struct rte_acl_param acl_params; /* for creating low level acl table */ struct rte_acl_config cfg; /* Holds the field definitions (metadata) */ struct rte_acl_ctx *ctx; uint32_t name_id; /* Input parameters */ uint32_t n_rules; uint32_t entry_size; /* Internal tables */ uint8_t *action_table; struct rte_acl_rule **acl_rule_list; /* Array of pointers to rules */ uint8_t *acl_rule_memory; /* Memory to store the rules */ /* Memory to store the action table and stack of free entries */ uint8_t memory[0] __rte_cache_aligned; }; static void * rte_table_acl_create( void *params, int socket_id, uint32_t entry_size) { struct rte_table_acl_params *p = (struct rte_table_acl_params *) params; struct rte_table_acl *acl; uint32_t action_table_size, acl_rule_list_size, acl_rule_memory_size; uint32_t total_size; RTE_BUILD_BUG_ON(((sizeof(struct rte_table_acl) % RTE_CACHE_LINE_SIZE) != 0)); /* Check input parameters */ if (p == NULL) { RTE_LOG(ERR, TABLE, "%s: Invalid value for params\n", __func__); return NULL; } if (p->name == NULL) { RTE_LOG(ERR, TABLE, "%s: Invalid value for name\n", __func__); return NULL; } if (p->n_rules == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid value for n_rules\n", __func__); return NULL; } if ((p->n_rule_fields == 0) || (p->n_rule_fields > RTE_ACL_MAX_FIELDS)) { RTE_LOG(ERR, TABLE, "%s: Invalid value for n_rule_fields\n", __func__); return NULL; } entry_size = RTE_ALIGN(entry_size, sizeof(uint64_t)); /* Memory allocation */ action_table_size = RTE_CACHE_LINE_ROUNDUP(p->n_rules * entry_size); acl_rule_list_size = RTE_CACHE_LINE_ROUNDUP(p->n_rules * sizeof(struct rte_acl_rule *)); acl_rule_memory_size = RTE_CACHE_LINE_ROUNDUP(p->n_rules * RTE_ACL_RULE_SZ(p->n_rule_fields)); total_size = sizeof(struct rte_table_acl) + action_table_size + acl_rule_list_size + acl_rule_memory_size; acl = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (acl == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for ACL table\n", __func__, total_size); return NULL; } acl->action_table = &acl->memory[0]; acl->acl_rule_list = (struct rte_acl_rule **) &acl->memory[action_table_size]; acl->acl_rule_memory = (uint8_t *) &acl->memory[action_table_size + acl_rule_list_size]; /* Initialization of internal fields */ snprintf(acl->name[0], RTE_ACL_NAMESIZE, "%s_a", p->name); snprintf(acl->name[1], RTE_ACL_NAMESIZE, "%s_b", p->name); acl->name_id = 1; acl->acl_params.name = acl->name[acl->name_id]; acl->acl_params.socket_id = socket_id; acl->acl_params.rule_size = RTE_ACL_RULE_SZ(p->n_rule_fields); acl->acl_params.max_rule_num = p->n_rules; acl->cfg.num_categories = 1; acl->cfg.num_fields = p->n_rule_fields; memcpy(&acl->cfg.defs[0], &p->field_format[0], p->n_rule_fields * sizeof(struct rte_acl_field_def)); acl->ctx = NULL; acl->n_rules = p->n_rules; acl->entry_size = entry_size; return acl; } static int rte_table_acl_free(void *table) { struct rte_table_acl *acl = (struct rte_table_acl *) table; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } /* Free previously allocated resources */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); rte_free(acl); return 0; } RTE_ACL_RULE_DEF(rte_pipeline_acl_rule, RTE_ACL_MAX_FIELDS); static int rte_table_acl_build(struct rte_table_acl *acl, struct rte_acl_ctx **acl_ctx) { struct rte_acl_ctx *ctx = NULL; uint32_t n_rules, i; int status; /* Create low level ACL table */ ctx = rte_acl_create(&acl->acl_params); if (ctx == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot create low level ACL table\n", __func__); return -1; } /* Add rules to low level ACL table */ n_rules = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] != NULL) { status = rte_acl_add_rules(ctx, acl->acl_rule_list[i], 1); if (status != 0) { RTE_LOG(ERR, TABLE, "%s: Cannot add rule to low level ACL table\n", __func__); rte_acl_free(ctx); return -1; } n_rules++; } } if (n_rules == 0) { rte_acl_free(ctx); *acl_ctx = NULL; return 0; } /* Build low level ACl table */ status = rte_acl_build(ctx, &acl->cfg); if (status != 0) { RTE_LOG(ERR, TABLE, "%s: Cannot build the low level ACL table\n", __func__); rte_acl_free(ctx); return -1; } rte_acl_dump(ctx); *acl_ctx = ctx; return 0; } static int rte_table_acl_entry_add( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_acl *acl = (struct rte_table_acl *) table; struct rte_table_acl_rule_add_params *rule = (struct rte_table_acl_rule_add_params *) key; struct rte_pipeline_acl_rule acl_rule; struct rte_acl_rule *rule_location; struct rte_acl_ctx *ctx; uint32_t free_pos, free_pos_valid, i; int status; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, TABLE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if (key_found == NULL) { RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n", __func__); return -EINVAL; } if (entry_ptr == NULL) { RTE_LOG(ERR, TABLE, "%s: entry_ptr parameter is NULL\n", __func__); return -EINVAL; } if (rule->priority > RTE_ACL_MAX_PRIORITY) { RTE_LOG(ERR, TABLE, "%s: Priority is too high\n", __func__); return -EINVAL; } /* Setup rule data structure */ memset(&acl_rule, 0, sizeof(acl_rule)); acl_rule.data.category_mask = 1; acl_rule.data.priority = RTE_ACL_MAX_PRIORITY - rule->priority; acl_rule.data.userdata = 0; /* To be set up later */ memcpy(&acl_rule.field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Look to see if the rule exists already in the table */ free_pos = 0; free_pos_valid = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] == NULL) { if (free_pos_valid == 0) { free_pos = i; free_pos_valid = 1; } continue; } /* Compare the key fields */ status = memcmp(&acl->acl_rule_list[i]->field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Rule found: update data associated with the rule */ if (status == 0) { *key_found = 1; *entry_ptr = &acl->memory[i * acl->entry_size]; memcpy(*entry_ptr, entry, acl->entry_size); return 0; } } /* Return if max rules */ if (free_pos_valid == 0) { RTE_LOG(ERR, TABLE, "%s: Max number of rules reached\n", __func__); return -ENOSPC; } /* Add the new rule to the rule set */ acl_rule.data.userdata = free_pos; rule_location = (struct rte_acl_rule *) &acl->acl_rule_memory[free_pos * acl->acl_params.rule_size]; memcpy(rule_location, &acl_rule, acl->acl_params.rule_size); acl->acl_rule_list[free_pos] = rule_location; /* Build low level ACL table */ acl->name_id ^= 1; acl->acl_params.name = acl->name[acl->name_id]; status = rte_table_acl_build(acl, &ctx); if (status != 0) { /* Roll back changes */ acl->acl_rule_list[free_pos] = NULL; acl->name_id ^= 1; return -EINVAL; } /* Commit changes */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); acl->ctx = ctx; *key_found = 0; *entry_ptr = &acl->memory[free_pos * acl->entry_size]; memcpy(*entry_ptr, entry, acl->entry_size); return 0; } static int rte_table_acl_entry_delete( void *table, void *key, int *key_found, void *entry) { struct rte_table_acl *acl = (struct rte_table_acl *) table; struct rte_table_acl_rule_delete_params *rule = (struct rte_table_acl_rule_delete_params *) key; struct rte_acl_rule *deleted_rule = NULL; struct rte_acl_ctx *ctx; uint32_t pos, pos_valid, i; int status; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (key_found == NULL) { RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n", __func__); return -EINVAL; } /* Look for the rule in the table */ pos = 0; pos_valid = 0; for (i = 1; i < acl->n_rules; i++) { if (acl->acl_rule_list[i] != NULL) { /* Compare the key fields */ status = memcmp(&acl->acl_rule_list[i]->field[0], &rule->field_value[0], acl->cfg.num_fields * sizeof(struct rte_acl_field)); /* Rule found: remove from table */ if (status == 0) { pos = i; pos_valid = 1; deleted_rule = acl->acl_rule_list[i]; acl->acl_rule_list[i] = NULL; } } } /* Return if rule not found */ if (pos_valid == 0) { *key_found = 0; return 0; } /* Build low level ACL table */ acl->name_id ^= 1; acl->acl_params.name = acl->name[acl->name_id]; status = rte_table_acl_build(acl, &ctx); if (status != 0) { /* Roll back changes */ acl->acl_rule_list[pos] = deleted_rule; acl->name_id ^= 1; return -EINVAL; } /* Commit changes */ if (acl->ctx != NULL) rte_acl_free(acl->ctx); acl->ctx = ctx; *key_found = 1; if (entry != NULL) memcpy(entry, &acl->memory[pos * acl->entry_size], acl->entry_size); return 0; } static int rte_table_acl_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_acl *acl = (struct rte_table_acl *) table; const uint8_t *pkts_data[RTE_PORT_IN_BURST_SIZE_MAX]; uint32_t results[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t pkts_out_mask; uint32_t n_pkts, i, j; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_ACL_STATS_PKTS_IN_ADD(acl, n_pkts_in); /* Input conversion */ for (i = 0, j = 0; i < (uint32_t)(RTE_PORT_IN_BURST_SIZE_MAX - __builtin_clzll(pkts_mask)); i++) { uint64_t pkt_mask = 1LLU << i; if (pkt_mask & pkts_mask) { pkts_data[j] = rte_pktmbuf_mtod(pkts[i], uint8_t *); j++; } } n_pkts = j; /* Low-level ACL table lookup */ if (acl->ctx != NULL) rte_acl_classify(acl->ctx, pkts_data, results, n_pkts, 1); else n_pkts = 0; /* Output conversion */ pkts_out_mask = 0; for (i = 0; i < n_pkts; i++) { uint32_t action_table_pos = results[i]; uint32_t pkt_pos = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_pos; pkts_mask &= ~pkt_mask; if (action_table_pos != RTE_ACL_INVALID_USERDATA) { pkts_out_mask |= pkt_mask; entries[pkt_pos] = (void *) &acl->memory[action_table_pos * acl->entry_size]; rte_prefetch0(entries[pkt_pos]); } } *lookup_hit_mask = pkts_out_mask; RTE_TABLE_ACL_STATS_PKTS_LOOKUP_MISS(acl, n_pkts_in - __builtin_popcountll(pkts_out_mask)); return 0; } static int rte_table_acl_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_acl *acl = (struct rte_table_acl *) table; if (stats != NULL) memcpy(stats, &acl->stats, sizeof(acl->stats)); if (clear) memset(&acl->stats, 0, sizeof(acl->stats)); return 0; } struct rte_table_ops rte_table_acl_ops = { .f_create = rte_table_acl_create, .f_free = rte_table_acl_free, .f_add = rte_table_acl_entry_add, .f_delete = rte_table_acl_entry_delete, .f_lookup = rte_table_acl_lookup, .f_stats = rte_table_acl_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_acl.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_ACL_H__ #define __INCLUDE_RTE_TABLE_ACL_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table ACL * * This table uses the Access Control List (ACL) algorithm to uniquely * associate data to lookup keys. * * Use-cases: Firewall rule database, etc. * ***/ #include #include "rte_acl.h" #include "rte_table.h" /** ACL table parameters */ struct rte_table_acl_params { /** Name */ const char *name; /** Maximum number of ACL rules in the table */ uint32_t n_rules; /** Number of fields in the ACL rule specification */ uint32_t n_rule_fields; /** Format specification of the fields of the ACL rule */ struct rte_acl_field_def field_format[RTE_ACL_MAX_FIELDS]; }; /** ACL rule specification for entry add operation */ struct rte_table_acl_rule_add_params { /** ACL rule priority, with 0 as the highest priority */ int32_t priority; /** Values for the fields of the ACL rule to be added to the table */ struct rte_acl_field field_value[RTE_ACL_MAX_FIELDS]; }; /** ACL rule specification for entry delete operation */ struct rte_table_acl_rule_delete_params { /** Values for the fields of the ACL rule to be deleted from table */ struct rte_acl_field field_value[RTE_ACL_MAX_FIELDS]; }; /** ACL table operations */ extern struct rte_table_ops rte_table_acl_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_array.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_array.h" #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_table_array { struct rte_table_stats stats; /* Input parameters */ uint32_t entry_size; uint32_t n_entries; uint32_t offset; /* Internal fields */ uint32_t entry_pos_mask; /* Internal table */ uint8_t array[0] __rte_cache_aligned; } __rte_cache_aligned; static void * rte_table_array_create(void *params, int socket_id, uint32_t entry_size) { struct rte_table_array_params *p = (struct rte_table_array_params *) params; struct rte_table_array *t; uint32_t total_cl_size, total_size; /* Check input parameters */ if ((p == NULL) || (p->n_entries == 0) || (!rte_is_power_of_2(p->n_entries))) return NULL; /* Memory allocation */ total_cl_size = (sizeof(struct rte_table_array) + RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; total_cl_size += (p->n_entries * entry_size + RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; total_size = total_cl_size * RTE_CACHE_LINE_SIZE; t = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (t == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for array table\n", __func__, total_size); return NULL; } /* Memory initialization */ t->entry_size = entry_size; t->n_entries = p->n_entries; t->offset = p->offset; t->entry_pos_mask = t->n_entries - 1; return t; } static int rte_table_array_free(void *table) { struct rte_table_array *t = (struct rte_table_array *) table; /* Check input parameters */ if (t == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } /* Free previously allocated resources */ rte_free(t); return 0; } static int rte_table_array_entry_add( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_array *t = (struct rte_table_array *) table; struct rte_table_array_key *k = (struct rte_table_array_key *) key; uint8_t *table_entry; /* Check input parameters */ if (table == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (key == NULL) { RTE_LOG(ERR, TABLE, "%s: key parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, TABLE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if (key_found == NULL) { RTE_LOG(ERR, TABLE, "%s: key_found parameter is NULL\n", __func__); return -EINVAL; } if (entry_ptr == NULL) { RTE_LOG(ERR, TABLE, "%s: entry_ptr parameter is NULL\n", __func__); return -EINVAL; } table_entry = &t->array[k->pos * t->entry_size]; memcpy(table_entry, entry, t->entry_size); *key_found = 1; *entry_ptr = (void *) table_entry; return 0; } static int rte_table_array_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_array *t = (struct rte_table_array *) table; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(t, n_pkts_in); *lookup_hit_mask = pkts_mask; if ((pkts_mask & (pkts_mask + 1)) == 0) { uint64_t n_pkts = __builtin_popcountll(pkts_mask); uint32_t i; for (i = 0; i < n_pkts; i++) { struct rte_mbuf *pkt = pkts[i]; uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, t->offset) & t->entry_pos_mask; entries[i] = (void *) &t->array[entry_pos * t->entry_size]; } } else { for ( ; pkts_mask; ) { uint32_t pkt_index = __builtin_ctzll(pkts_mask); uint64_t pkt_mask = 1LLU << pkt_index; struct rte_mbuf *pkt = pkts[pkt_index]; uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, t->offset) & t->entry_pos_mask; entries[pkt_index] = (void *) &t->array[entry_pos * t->entry_size]; pkts_mask &= ~pkt_mask; } } return 0; } static int rte_table_array_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_array *array = (struct rte_table_array *) table; if (stats != NULL) memcpy(stats, &array->stats, sizeof(array->stats)); if (clear) memset(&array->stats, 0, sizeof(array->stats)); return 0; } struct rte_table_ops rte_table_array_ops = { .f_create = rte_table_array_create, .f_free = rte_table_array_free, .f_add = rte_table_array_entry_add, .f_delete = NULL, .f_lookup = rte_table_array_lookup, .f_stats = rte_table_array_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_array.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_ARRAY_H__ #define __INCLUDE_RTE_TABLE_ARRAY_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table Array * * Simple array indexing. Lookup key is the array entry index. * ***/ #include #include "rte_table.h" /** Array table parameters */ struct rte_table_array_params { /** Number of array entries. Has to be a power of two. */ uint32_t n_entries; /** Byte offset within input packet meta-data where lookup key (i.e. the array entry index) is located. */ uint32_t offset; }; /** Array table key format */ struct rte_table_array_key { /** Array entry index */ uint32_t pos; }; /** Array table operations */ extern struct rte_table_ops rte_table_array_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_hash.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_HASH_H__ #define __INCLUDE_RTE_TABLE_HASH_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table Hash * * These tables use the exact match criterion to uniquely associate data to * lookup keys. * * Use-cases: Flow classification table, Address Resolution Protocol (ARP) table * * Hash table types: * 1. Entry add strategy on bucket full: * a. Least Recently Used (LRU): One of the existing keys in the bucket is * deleted and the new key is added in its place. The number of keys in * each bucket never grows bigger than 4. The logic to pick the key to * be dropped from the bucket is LRU. The hash table lookup operation * maintains the order in which the keys in the same bucket are hit, so * every time a key is hit, it becomes the new Most Recently Used (MRU) * key, i.e. the most unlikely candidate for drop. When a key is added * to the bucket, it also becomes the new MRU key. When a key needs to * be picked and dropped, the most likely candidate for drop, i.e. the * current LRU key, is always picked. The LRU logic requires maintaining * specific data structures per each bucket. * b. Extendible bucket (ext): The bucket is extended with space for 4 more * keys. This is done by allocating additional memory at table init time, * which is used to create a pool of free keys (the size of this pool is * configurable and always a multiple of 4). On key add operation, the * allocation of a group of 4 keys only happens successfully within the * limit of free keys, otherwise the key add operation fails. On key * delete operation, a group of 4 keys is freed back to the pool of free * keys when the key to be deleted is the only key that was used within * its group of 4 keys at that time. On key lookup operation, if the * current bucket is in extended state and a match is not found in the * first group of 4 keys, the search continues beyond the first group of * 4 keys, potentially until all keys in this bucket are examined. The * extendible bucket logic requires maintaining specific data structures * per table and per each bucket. * 2. Key signature computation: * a. Pre-computed key signature: The key lookup operation is split between * two CPU cores. The first CPU core (typically the CPU core performing * packet RX) extracts the key from the input packet, computes the key * signature and saves both the key and the key signature in the packet * buffer as packet meta-data. The second CPU core reads both the key and * the key signature from the packet meta-data and performs the bucket * search step of the key lookup operation. * b. Key signature computed on lookup (do-sig): The same CPU core reads * the key from the packet meta-data, uses it to compute the key * signature and also performs the bucket search step of the key lookup * operation. * 3. Key size: * a. Configurable key size * b. Single key size (8-byte, 16-byte or 32-byte key size) * ***/ #include #include "rte_table.h" /** Hash function */ typedef uint64_t (*rte_table_hash_op_hash)( void *key, uint32_t key_size, uint64_t seed); /** * Hash tables with configurable key size * */ /** Extendible bucket hash table parameters */ struct rte_table_hash_ext_params { /** Key size (number of bytes) */ uint32_t key_size; /** Maximum number of keys */ uint32_t n_keys; /** Number of hash table buckets. Each bucket stores up to 4 keys. */ uint32_t n_buckets; /** Number of hash table bucket extensions. Each bucket extension has space for 4 keys and each bucket can have 0, 1 or more extensions. */ uint32_t n_buckets_ext; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed value for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** Extendible bucket hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_ext_ops; /** Extendible bucket hash table operations for key signature computed on lookup ("do-sig") */ extern struct rte_table_ops rte_table_hash_ext_dosig_ops; /** LRU hash table parameters */ struct rte_table_hash_lru_params { /** Key size (number of bytes) */ uint32_t key_size; /** Maximum number of keys */ uint32_t n_keys; /** Number of hash table buckets. Each bucket stores up to 4 keys. */ uint32_t n_buckets; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed value for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** LRU hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_lru_ops; /** LRU hash table operations for key signature computed on lookup ("do-sig") */ extern struct rte_table_ops rte_table_hash_lru_dosig_ops; /** * 8-byte key hash tables * */ /** LRU hash table parameters */ struct rte_table_hash_key8_lru_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** LRU hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_key8_lru_ops; /** LRU hash table operations for key signature computed on lookup ("do-sig") */ extern struct rte_table_ops rte_table_hash_key8_lru_dosig_ops; /** Extendible bucket hash table parameters */ struct rte_table_hash_key8_ext_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Number of entries (and keys) for hash table bucket extensions. Each bucket is extended in increments of 4 keys. */ uint32_t n_entries_ext; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** Extendible bucket hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_key8_ext_ops; /** Extendible bucket hash table operations for key signature computed on lookup ("do-sig") */ extern struct rte_table_ops rte_table_hash_key8_ext_dosig_ops; /** * 16-byte key hash tables * */ /** LRU hash table parameters */ struct rte_table_hash_key16_lru_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** LRU hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_key16_lru_ops; /** Extendible bucket hash table parameters */ struct rte_table_hash_key16_ext_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Number of entries (and keys) for hash table bucket extensions. Each bucket is extended in increments of 4 keys. */ uint32_t n_entries_ext; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** Extendible bucket operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_key16_ext_ops; /** * 32-byte key hash tables * */ /** LRU hash table parameters */ struct rte_table_hash_key32_lru_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** LRU hash table operations for pre-computed key signature */ extern struct rte_table_ops rte_table_hash_key32_lru_ops; /** Extendible bucket hash table parameters */ struct rte_table_hash_key32_ext_params { /** Maximum number of entries (and keys) in the table */ uint32_t n_entries; /** Number of entries (and keys) for hash table bucket extensions. Each bucket is extended in increments of 4 keys. */ uint32_t n_entries_ext; /** Hash function */ rte_table_hash_op_hash f_hash; /** Seed for the hash function */ uint64_t seed; /** Byte offset within packet meta-data where the 4-byte key signature is located. Valid for pre-computed key signature tables, ignored for do-sig tables. */ uint32_t signature_offset; /** Byte offset within packet meta-data where the key is located */ uint32_t key_offset; }; /** Extendible bucket hash table operations */ extern struct rte_table_ops rte_table_hash_key32_ext_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_hash_ext.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_hash.h" #define KEYS_PER_BUCKET 4 struct bucket { union { uintptr_t next; uint64_t lru_list; }; uint16_t sig[KEYS_PER_BUCKET]; uint32_t key_pos[KEYS_PER_BUCKET]; }; #define BUCKET_NEXT(bucket) \ ((void *) ((bucket)->next & (~1LU))) #define BUCKET_NEXT_VALID(bucket) \ ((bucket)->next & 1LU) #define BUCKET_NEXT_SET(bucket, bucket_next) \ do \ (bucket)->next = (((uintptr_t) ((void *) (bucket_next))) | 1LU);\ while (0) #define BUCKET_NEXT_SET_NULL(bucket) \ do \ (bucket)->next = 0; \ while (0) #define BUCKET_NEXT_COPY(bucket, bucket2) \ do \ (bucket)->next = (bucket2)->next; \ while (0) #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_HASH_EXT_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_HASH_EXT_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_HASH_EXT_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_HASH_EXT_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct grinder { struct bucket *bkt; uint64_t sig; uint64_t match; uint32_t key_index; }; struct rte_table_hash { struct rte_table_stats stats; /* Input parameters */ uint32_t key_size; uint32_t entry_size; uint32_t n_keys; uint32_t n_buckets; uint32_t n_buckets_ext; rte_table_hash_op_hash f_hash; uint64_t seed; uint32_t signature_offset; uint32_t key_offset; /* Internal */ uint64_t bucket_mask; uint32_t key_size_shl; uint32_t data_size_shl; uint32_t key_stack_tos; uint32_t bkt_ext_stack_tos; /* Grinder */ struct grinder grinders[RTE_PORT_IN_BURST_SIZE_MAX]; /* Tables */ struct bucket *buckets; struct bucket *buckets_ext; uint8_t *key_mem; uint8_t *data_mem; uint32_t *key_stack; uint32_t *bkt_ext_stack; /* Table memory */ uint8_t memory[0] __rte_cache_aligned; }; static int check_params_create(struct rte_table_hash_ext_params *params) { uint32_t n_buckets_min; /* key_size */ if ((params->key_size == 0) || (!rte_is_power_of_2(params->key_size))) { RTE_LOG(ERR, TABLE, "%s: key_size invalid value\n", __func__); return -EINVAL; } /* n_keys */ if ((params->n_keys == 0) || (!rte_is_power_of_2(params->n_keys))) { RTE_LOG(ERR, TABLE, "%s: n_keys invalid value\n", __func__); return -EINVAL; } /* n_buckets */ n_buckets_min = (params->n_keys + KEYS_PER_BUCKET - 1) / params->n_keys; if ((params->n_buckets == 0) || (!rte_is_power_of_2(params->n_keys)) || (params->n_buckets < n_buckets_min)) { RTE_LOG(ERR, TABLE, "%s: n_buckets invalid value\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash invalid value\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_ext_create(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_ext_params *p = (struct rte_table_hash_ext_params *) params; struct rte_table_hash *t; uint32_t total_size, table_meta_sz; uint32_t bucket_sz, bucket_ext_sz, key_sz; uint32_t key_stack_sz, bkt_ext_stack_sz, data_sz; uint32_t bucket_offset, bucket_ext_offset, key_offset; uint32_t key_stack_offset, bkt_ext_stack_offset, data_offset; uint32_t i; /* Check input parameters */ if ((check_params_create(p) != 0) || (!rte_is_power_of_2(entry_size)) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || (sizeof(struct bucket) != (RTE_CACHE_LINE_SIZE / 2))) return NULL; /* Memory allocation */ table_meta_sz = RTE_CACHE_LINE_ROUNDUP(sizeof(struct rte_table_hash)); bucket_sz = RTE_CACHE_LINE_ROUNDUP(p->n_buckets * sizeof(struct bucket)); bucket_ext_sz = RTE_CACHE_LINE_ROUNDUP(p->n_buckets_ext * sizeof(struct bucket)); key_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * p->key_size); key_stack_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * sizeof(uint32_t)); bkt_ext_stack_sz = RTE_CACHE_LINE_ROUNDUP(p->n_buckets_ext * sizeof(uint32_t)); data_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * entry_size); total_size = table_meta_sz + bucket_sz + bucket_ext_sz + key_sz + key_stack_sz + bkt_ext_stack_sz + data_sz; t = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (t == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s (%u-byte key): Hash table memory footprint is " "%u bytes\n", __func__, p->key_size, total_size); /* Memory initialization */ t->key_size = p->key_size; t->entry_size = entry_size; t->n_keys = p->n_keys; t->n_buckets = p->n_buckets; t->n_buckets_ext = p->n_buckets_ext; t->f_hash = p->f_hash; t->seed = p->seed; t->signature_offset = p->signature_offset; t->key_offset = p->key_offset; /* Internal */ t->bucket_mask = t->n_buckets - 1; t->key_size_shl = __builtin_ctzl(p->key_size); t->data_size_shl = __builtin_ctzl(entry_size); /* Tables */ bucket_offset = 0; bucket_ext_offset = bucket_offset + bucket_sz; key_offset = bucket_ext_offset + bucket_ext_sz; key_stack_offset = key_offset + key_sz; bkt_ext_stack_offset = key_stack_offset + key_stack_sz; data_offset = bkt_ext_stack_offset + bkt_ext_stack_sz; t->buckets = (struct bucket *) &t->memory[bucket_offset]; t->buckets_ext = (struct bucket *) &t->memory[bucket_ext_offset]; t->key_mem = &t->memory[key_offset]; t->key_stack = (uint32_t *) &t->memory[key_stack_offset]; t->bkt_ext_stack = (uint32_t *) &t->memory[bkt_ext_stack_offset]; t->data_mem = &t->memory[data_offset]; /* Key stack */ for (i = 0; i < t->n_keys; i++) t->key_stack[i] = t->n_keys - 1 - i; t->key_stack_tos = t->n_keys; /* Bucket ext stack */ for (i = 0; i < t->n_buckets_ext; i++) t->bkt_ext_stack[i] = t->n_buckets_ext - 1 - i; t->bkt_ext_stack_tos = t->n_buckets_ext; return t; } static int rte_table_hash_ext_free(void *table) { struct rte_table_hash *t = (struct rte_table_hash *) table; /* Check input parameters */ if (t == NULL) return -EINVAL; rte_free(t); return 0; } static int rte_table_hash_ext_entry_add(void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct bucket *bkt0, *bkt, *bkt_prev; uint64_t sig; uint32_t bkt_index, i; sig = t->f_hash(key, t->key_size, t->seed); bkt_index = sig & t->bucket_mask; bkt0 = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (bkt = bkt0; bkt != NULL; bkt = BUCKET_NEXT(bkt)) for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; memcpy(data, entry, t->entry_size); *key_found = 1; *entry_ptr = (void *) data; return 0; } } /* Key is not present in the bucket */ for (bkt_prev = NULL, bkt = bkt0; bkt != NULL; bkt_prev = bkt, bkt = BUCKET_NEXT(bkt)) for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; if (bkt_sig == 0) { uint32_t bkt_key_index; uint8_t *bkt_key, *data; /* Allocate new key */ if (t->key_stack_tos == 0) /* No free keys */ return -ENOSPC; bkt_key_index = t->key_stack[ --t->key_stack_tos]; /* Install new key */ bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; data = &t->data_mem[bkt_key_index << t->data_size_shl]; bkt->sig[i] = (uint16_t) sig; bkt->key_pos[i] = bkt_key_index; memcpy(bkt_key, key, t->key_size); memcpy(data, entry, t->entry_size); *key_found = 0; *entry_ptr = (void *) data; return 0; } } /* Bucket full: extend bucket */ if ((t->bkt_ext_stack_tos > 0) && (t->key_stack_tos > 0)) { uint32_t bkt_key_index; uint8_t *bkt_key, *data; /* Allocate new bucket ext */ bkt_index = t->bkt_ext_stack[--t->bkt_ext_stack_tos]; bkt = &t->buckets_ext[bkt_index]; /* Chain the new bucket ext */ BUCKET_NEXT_SET(bkt_prev, bkt); BUCKET_NEXT_SET_NULL(bkt); /* Allocate new key */ bkt_key_index = t->key_stack[--t->key_stack_tos]; bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; data = &t->data_mem[bkt_key_index << t->data_size_shl]; /* Install new key into bucket */ bkt->sig[0] = (uint16_t) sig; bkt->key_pos[0] = bkt_key_index; memcpy(bkt_key, key, t->key_size); memcpy(data, entry, t->entry_size); *key_found = 0; *entry_ptr = (void *) data; return 0; } return -ENOSPC; } static int rte_table_hash_ext_entry_delete(void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct bucket *bkt0, *bkt, *bkt_prev; uint64_t sig; uint32_t bkt_index, i; sig = t->f_hash(key, t->key_size, t->seed); bkt_index = sig & t->bucket_mask; bkt0 = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (bkt_prev = NULL, bkt = bkt0; bkt != NULL; bkt_prev = bkt, bkt = BUCKET_NEXT(bkt)) for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; /* Uninstall key from bucket */ bkt->sig[i] = 0; *key_found = 1; if (entry) memcpy(entry, data, t->entry_size); /* Free key */ t->key_stack[t->key_stack_tos++] = bkt_key_index; /*Check if bucket is unused */ if ((bkt_prev != NULL) && (bkt->sig[0] == 0) && (bkt->sig[1] == 0) && (bkt->sig[2] == 0) && (bkt->sig[3] == 0)) { /* Unchain bucket */ BUCKET_NEXT_COPY(bkt_prev, bkt); /* Clear bucket */ memset(bkt, 0, sizeof(struct bucket)); /* Free bucket back to buckets ext */ bkt_index = bkt - t->buckets_ext; t->bkt_ext_stack[t->bkt_ext_stack_tos++] = bkt_index; } return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } static int rte_table_hash_ext_lookup_unoptimized( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries, int dosig) { struct rte_table_hash *t = (struct rte_table_hash *) table; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_EXT_STATS_PKTS_IN_ADD(t, n_pkts_in); for ( ; pkts_mask; ) { struct bucket *bkt0, *bkt; struct rte_mbuf *pkt; uint8_t *key; uint64_t pkt_mask, sig; uint32_t pkt_index, bkt_index, i; pkt_index = __builtin_ctzll(pkts_mask); pkt_mask = 1LLU << pkt_index; pkts_mask &= ~pkt_mask; pkt = pkts[pkt_index]; key = RTE_MBUF_METADATA_UINT8_PTR(pkt, t->key_offset); if (dosig) sig = (uint64_t) t->f_hash(key, t->key_size, t->seed); else sig = RTE_MBUF_METADATA_UINT32(pkt, t->signature_offset); bkt_index = sig & t->bucket_mask; bkt0 = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (bkt = bkt0; bkt != NULL; bkt = BUCKET_NEXT(bkt)) for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[ bkt_key_index << t->data_size_shl]; pkts_mask_out |= pkt_mask; entries[pkt_index] = (void *) data; break; } } } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_EXT_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /*** * * mask = match bitmask * match = at least one match * match_many = more than one match * match_pos = position of first match * *---------------------------------------- * mask match match_many match_pos *---------------------------------------- * 0000 0 0 00 * 0001 1 0 00 * 0010 1 0 01 * 0011 1 1 00 *---------------------------------------- * 0100 1 0 10 * 0101 1 1 00 * 0110 1 1 01 * 0111 1 1 00 *---------------------------------------- * 1000 1 0 11 * 1001 1 1 00 * 1010 1 1 01 * 1011 1 1 00 *---------------------------------------- * 1100 1 1 10 * 1101 1 1 00 * 1110 1 1 01 * 1111 1 1 00 *---------------------------------------- * * match = 1111_1111_1111_1110 * match_many = 1111_1110_1110_1000 * match_pos = 0001_0010_0001_0011__0001_0010_0001_0000 * * match = 0xFFFELLU * match_many = 0xFEE8LLU * match_pos = 0x12131210LLU * ***/ #define LUT_MATCH 0xFFFELLU #define LUT_MATCH_MANY 0xFEE8LLU #define LUT_MATCH_POS 0x12131210LLU #define lookup_cmp_sig(mbuf_sig, bucket, match, match_many, match_pos) \ { \ uint64_t bucket_sig[4], mask[4], mask_all; \ \ bucket_sig[0] = bucket->sig[0]; \ bucket_sig[1] = bucket->sig[1]; \ bucket_sig[2] = bucket->sig[2]; \ bucket_sig[3] = bucket->sig[3]; \ \ bucket_sig[0] ^= mbuf_sig; \ bucket_sig[1] ^= mbuf_sig; \ bucket_sig[2] ^= mbuf_sig; \ bucket_sig[3] ^= mbuf_sig; \ \ mask[0] = 0; \ mask[1] = 0; \ mask[2] = 0; \ mask[3] = 0; \ \ if (bucket_sig[0] == 0) \ mask[0] = 1; \ if (bucket_sig[1] == 0) \ mask[1] = 2; \ if (bucket_sig[2] == 0) \ mask[2] = 4; \ if (bucket_sig[3] == 0) \ mask[3] = 8; \ \ mask_all = (mask[0] | mask[1]) | (mask[2] | mask[3]); \ \ match = (LUT_MATCH >> mask_all) & 1; \ match_many = (LUT_MATCH_MANY >> mask_all) & 1; \ match_pos = (LUT_MATCH_POS >> (mask_all << 1)) & 3; \ } #define lookup_cmp_key(mbuf, key, match_key, f) \ { \ uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(mbuf, f->key_offset);\ uint64_t *bkt_key = (uint64_t *) key; \ \ switch (f->key_size) { \ case 8: \ { \ uint64_t xor = pkt_key[0] ^ bkt_key[0]; \ match_key = 0; \ if (xor == 0) \ match_key = 1; \ } \ break; \ \ case 16: \ { \ uint64_t xor[2], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ or = xor[0] | xor[1]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ case 32: \ { \ uint64_t xor[4], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ xor[2] = pkt_key[2] ^ bkt_key[2]; \ xor[3] = pkt_key[3] ^ bkt_key[3]; \ or = xor[0] | xor[1] | xor[2] | xor[3]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ case 64: \ { \ uint64_t xor[8], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ xor[2] = pkt_key[2] ^ bkt_key[2]; \ xor[3] = pkt_key[3] ^ bkt_key[3]; \ xor[4] = pkt_key[4] ^ bkt_key[4]; \ xor[5] = pkt_key[5] ^ bkt_key[5]; \ xor[6] = pkt_key[6] ^ bkt_key[6]; \ xor[7] = pkt_key[7] ^ bkt_key[7]; \ or = xor[0] | xor[1] | xor[2] | xor[3] | \ xor[4] | xor[5] | xor[6] | xor[7]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ default: \ match_key = 0; \ if (memcmp(pkt_key, bkt_key, f->key_size) == 0) \ match_key = 1; \ } \ } #define lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index) \ { \ uint64_t pkt00_mask, pkt01_mask; \ struct rte_mbuf *mbuf00, *mbuf01; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ mbuf00 = pkts[pkt00_index]; \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ mbuf01 = pkts[pkt01_index]; \ \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, \ pkt01_index) \ { \ uint64_t pkt00_mask, pkt01_mask; \ struct rte_mbuf *mbuf00, *mbuf01; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ mbuf00 = pkts[pkt00_index]; \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ if (pkts_mask == 0) \ pkt01_index = pkt00_index; \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ mbuf01 = pkts[pkt01_index]; \ \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index) \ { \ struct grinder *g10, *g11; \ uint64_t sig10, sig11, bkt10_index, bkt11_index; \ struct rte_mbuf *mbuf10, *mbuf11; \ struct bucket *bkt10, *bkt11, *buckets = t->buckets; \ uint64_t bucket_mask = t->bucket_mask; \ uint32_t signature_offset = t->signature_offset; \ \ mbuf10 = pkts[pkt10_index]; \ sig10 = (uint64_t) RTE_MBUF_METADATA_UINT32(mbuf10, signature_offset);\ bkt10_index = sig10 & bucket_mask; \ bkt10 = &buckets[bkt10_index]; \ \ mbuf11 = pkts[pkt11_index]; \ sig11 = (uint64_t) RTE_MBUF_METADATA_UINT32(mbuf11, signature_offset);\ bkt11_index = sig11 & bucket_mask; \ bkt11 = &buckets[bkt11_index]; \ \ rte_prefetch0(bkt10); \ rte_prefetch0(bkt11); \ \ g10 = &g[pkt10_index]; \ g10->sig = sig10; \ g10->bkt = bkt10; \ \ g11 = &g[pkt11_index]; \ g11->sig = sig11; \ g11->bkt = bkt11; \ } #define lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index) \ { \ struct grinder *g10, *g11; \ uint64_t sig10, sig11, bkt10_index, bkt11_index; \ struct rte_mbuf *mbuf10, *mbuf11; \ struct bucket *bkt10, *bkt11, *buckets = t->buckets; \ uint8_t *key10, *key11; \ uint64_t bucket_mask = t->bucket_mask; \ rte_table_hash_op_hash f_hash = t->f_hash; \ uint64_t seed = t->seed; \ uint32_t key_size = t->key_size; \ uint32_t key_offset = t->key_offset; \ \ mbuf10 = pkts[pkt10_index]; \ key10 = RTE_MBUF_METADATA_UINT8_PTR(mbuf10, key_offset); \ sig10 = (uint64_t) f_hash(key10, key_size, seed); \ bkt10_index = sig10 & bucket_mask; \ bkt10 = &buckets[bkt10_index]; \ \ mbuf11 = pkts[pkt11_index]; \ key11 = RTE_MBUF_METADATA_UINT8_PTR(mbuf11, key_offset); \ sig11 = (uint64_t) f_hash(key11, key_size, seed); \ bkt11_index = sig11 & bucket_mask; \ bkt11 = &buckets[bkt11_index]; \ \ rte_prefetch0(bkt10); \ rte_prefetch0(bkt11); \ \ g10 = &g[pkt10_index]; \ g10->sig = sig10; \ g10->bkt = bkt10; \ \ g11 = &g[pkt11_index]; \ g11->sig = sig11; \ g11->bkt = bkt11; \ } #define lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many)\ { \ struct grinder *g20, *g21; \ uint64_t sig20, sig21; \ struct bucket *bkt20, *bkt21; \ uint8_t *key20, *key21, *key_mem = t->key_mem; \ uint64_t match20, match21, match_many20, match_many21; \ uint64_t match_pos20, match_pos21; \ uint32_t key20_index, key21_index, key_size_shl = t->key_size_shl;\ \ g20 = &g[pkt20_index]; \ sig20 = g20->sig; \ bkt20 = g20->bkt; \ sig20 = (sig20 >> 16) | 1LLU; \ lookup_cmp_sig(sig20, bkt20, match20, match_many20, match_pos20);\ match20 <<= pkt20_index; \ match_many20 |= BUCKET_NEXT_VALID(bkt20); \ match_many20 <<= pkt20_index; \ key20_index = bkt20->key_pos[match_pos20]; \ key20 = &key_mem[key20_index << key_size_shl]; \ \ g21 = &g[pkt21_index]; \ sig21 = g21->sig; \ bkt21 = g21->bkt; \ sig21 = (sig21 >> 16) | 1LLU; \ lookup_cmp_sig(sig21, bkt21, match21, match_many21, match_pos21);\ match21 <<= pkt21_index; \ match_many21 |= BUCKET_NEXT_VALID(bkt21); \ match_many21 <<= pkt21_index; \ key21_index = bkt21->key_pos[match_pos21]; \ key21 = &key_mem[key21_index << key_size_shl]; \ \ rte_prefetch0(key20); \ rte_prefetch0(key21); \ \ pkts_mask_match_many |= match_many20 | match_many21; \ \ g20->match = match20; \ g20->key_index = key20_index; \ \ g21->match = match21; \ g21->key_index = key21_index; \ } #define lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, \ entries) \ { \ struct grinder *g30, *g31; \ struct rte_mbuf *mbuf30, *mbuf31; \ uint8_t *key30, *key31, *key_mem = t->key_mem; \ uint8_t *data30, *data31, *data_mem = t->data_mem; \ uint64_t match30, match31, match_key30, match_key31, match_keys;\ uint32_t key30_index, key31_index; \ uint32_t key_size_shl = t->key_size_shl; \ uint32_t data_size_shl = t->data_size_shl; \ \ mbuf30 = pkts[pkt30_index]; \ g30 = &g[pkt30_index]; \ match30 = g30->match; \ key30_index = g30->key_index; \ key30 = &key_mem[key30_index << key_size_shl]; \ lookup_cmp_key(mbuf30, key30, match_key30, t); \ match_key30 <<= pkt30_index; \ match_key30 &= match30; \ data30 = &data_mem[key30_index << data_size_shl]; \ entries[pkt30_index] = data30; \ \ mbuf31 = pkts[pkt31_index]; \ g31 = &g[pkt31_index]; \ match31 = g31->match; \ key31_index = g31->key_index; \ key31 = &key_mem[key31_index << key_size_shl]; \ lookup_cmp_key(mbuf31, key31, match_key31, t); \ match_key31 <<= pkt31_index; \ match_key31 &= match31; \ data31 = &data_mem[key31_index << data_size_shl]; \ entries[pkt31_index] = data31; \ \ rte_prefetch0(data30); \ rte_prefetch0(data31); \ \ match_keys = match_key30 | match_key31; \ pkts_mask_out |= match_keys; \ } /*** * The lookup function implements a 4-stage pipeline, with each stage processing * two different packets. The purpose of pipelined implementation is to hide the * latency of prefetching the data structures and loosen the data dependency * between instructions. * * p00 _______ p10 _______ p20 _______ p30 _______ *----->| |----->| |----->| |----->| |-----> * | 0 | | 1 | | 2 | | 3 | *----->|_______|----->|_______|----->|_______|----->|_______|-----> * p01 p11 p21 p31 * * The naming convention is: * pXY = packet Y of stage X, X = 0 .. 3, Y = 0 .. 1 * ***/ static int rte_table_hash_ext_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct grinder *g = t->grinders; uint64_t pkt00_index, pkt01_index, pkt10_index, pkt11_index; uint64_t pkt20_index, pkt21_index, pkt30_index, pkt31_index; uint64_t pkts_mask_out = 0, pkts_mask_match_many = 0; int status = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_EXT_STATS_PKTS_IN_ADD(t, n_pkts_in); /* Cannot run the pipeline with less than 7 packets */ if (__builtin_popcountll(pkts_mask) < 7) return rte_table_hash_ext_lookup_unoptimized(table, pkts, pkts_mask, lookup_hit_mask, entries, 0); /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline feed */ pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline feed */ pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); } /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Slow path */ pkts_mask_match_many &= ~pkts_mask_out; if (pkts_mask_match_many) { uint64_t pkts_mask_out_slow = 0; status = rte_table_hash_ext_lookup_unoptimized(table, pkts, pkts_mask_match_many, &pkts_mask_out_slow, entries, 0); pkts_mask_out |= pkts_mask_out_slow; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_EXT_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return status; } static int rte_table_hash_ext_lookup_dosig( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct grinder *g = t->grinders; uint64_t pkt00_index, pkt01_index, pkt10_index, pkt11_index; uint64_t pkt20_index, pkt21_index, pkt30_index, pkt31_index; uint64_t pkts_mask_out = 0, pkts_mask_match_many = 0; int status = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_EXT_STATS_PKTS_IN_ADD(t, n_pkts_in); /* Cannot run the pipeline with less than 7 packets */ if (__builtin_popcountll(pkts_mask) < 7) return rte_table_hash_ext_lookup_unoptimized(table, pkts, pkts_mask, lookup_hit_mask, entries, 1); /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline feed */ pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline feed */ pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); } /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Slow path */ pkts_mask_match_many &= ~pkts_mask_out; if (pkts_mask_match_many) { uint64_t pkts_mask_out_slow = 0; status = rte_table_hash_ext_lookup_unoptimized(table, pkts, pkts_mask_match_many, &pkts_mask_out_slow, entries, 1); pkts_mask_out |= pkts_mask_out_slow; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_EXT_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return status; } static int rte_table_hash_ext_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_hash *t = (struct rte_table_hash *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_hash_ext_ops = { .f_create = rte_table_hash_ext_create, .f_free = rte_table_hash_ext_free, .f_add = rte_table_hash_ext_entry_add, .f_delete = rte_table_hash_ext_entry_delete, .f_lookup = rte_table_hash_ext_lookup, .f_stats = rte_table_hash_ext_stats_read, }; struct rte_table_ops rte_table_hash_ext_dosig_ops = { .f_create = rte_table_hash_ext_create, .f_free = rte_table_hash_ext_free, .f_add = rte_table_hash_ext_entry_add, .f_delete = rte_table_hash_ext_entry_delete, .f_lookup = rte_table_hash_ext_lookup_dosig, .f_stats = rte_table_hash_ext_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_hash_key16.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_hash.h" #include "rte_lru.h" #define RTE_TABLE_HASH_KEY_SIZE 16 #define RTE_BUCKET_ENTRY_VALID 0x1LLU #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_HASH_KEY16_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_HASH_KEY16_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_HASH_KEY16_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_HASH_KEY16_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_bucket_4_16 { /* Cache line 0 */ uint64_t signature[4 + 1]; uint64_t lru_list; struct rte_bucket_4_16 *next; uint64_t next_valid; /* Cache line 1 */ uint64_t key[4][2]; /* Cache line 2 */ uint8_t data[0]; }; struct rte_table_hash { struct rte_table_stats stats; /* Input parameters */ uint32_t n_buckets; uint32_t n_entries_per_bucket; uint32_t key_size; uint32_t entry_size; uint32_t bucket_size; uint32_t signature_offset; uint32_t key_offset; rte_table_hash_op_hash f_hash; uint64_t seed; /* Extendible buckets */ uint32_t n_buckets_ext; uint32_t stack_pos; uint32_t *stack; /* Lookup table */ uint8_t memory[0] __rte_cache_aligned; }; static int check_params_create_lru(struct rte_table_hash_key16_lru_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key16_lru(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key16_lru_params *p = (struct rte_table_hash_key16_lru_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_entries_per_bucket, key_size, bucket_size_cl, total_size, i; /* Check input parameters */ if ((check_params_create_lru(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_16) % RTE_CACHE_LINE_SIZE) != 0)) return NULL; n_entries_per_bucket = 4; key_size = 16; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); bucket_size_cl = (sizeof(struct rte_bucket_4_16) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + n_buckets * bucket_size_cl * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; for (i = 0; i < n_buckets; i++) { struct rte_bucket_4_16 *bucket; bucket = (struct rte_bucket_4_16 *) &f->memory[i * f->bucket_size]; lru_init(bucket); } return f; } static int rte_table_hash_free_key16_lru(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key16_lru( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket; uint64_t signature, pos; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_16 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } /* Key is not present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if (bucket_signature == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = signature; memcpy(bucket_key, key, f->key_size); memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } /* Bucket full: replace LRU entry */ pos = lru_pos(bucket); bucket->signature[pos] = signature; memcpy(bucket->key[pos], key, f->key_size); memcpy(&bucket->data[pos * f->entry_size], entry, f->entry_size); lru_update(bucket, pos); *key_found = 0; *entry_ptr = (void *) &bucket->data[pos * f->entry_size]; return 0; } static int rte_table_hash_entry_delete_key16_lru( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_16 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = 0; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } static int check_params_create_ext(struct rte_table_hash_key16_ext_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* n_entries_ext */ if (params->n_entries_ext == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries_ext is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key16_ext(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key16_ext_params *p = (struct rte_table_hash_key16_ext_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_buckets_ext, n_entries_per_bucket, key_size, bucket_size_cl, stack_size_cl, total_size, i; /* Check input parameters */ if ((check_params_create_ext(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_16) % RTE_CACHE_LINE_SIZE) != 0)) return NULL; n_entries_per_bucket = 4; key_size = 16; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); n_buckets_ext = (p->n_entries_ext + n_entries_per_bucket - 1) / n_entries_per_bucket; bucket_size_cl = (sizeof(struct rte_bucket_4_16) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; stack_size_cl = (n_buckets_ext * sizeof(uint32_t) + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + ((n_buckets + n_buckets_ext) * bucket_size_cl + stack_size_cl) * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; f->n_buckets_ext = n_buckets_ext; f->stack_pos = n_buckets_ext; f->stack = (uint32_t *) &f->memory[(n_buckets + n_buckets_ext) * f->bucket_size]; for (i = 0; i < n_buckets_ext; i++) f->stack[i] = i; return f; } static int rte_table_hash_free_key16_ext(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key16_ext( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_16 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (bucket = bucket0; bucket != NULL; bucket = bucket->next) for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } /* Key is not present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if (bucket_signature == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = signature; memcpy(bucket_key, key, f->key_size); memcpy(bucket_data, entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } /* Bucket full: extend bucket */ if (f->stack_pos > 0) { bucket_index = f->stack[--f->stack_pos]; bucket = (struct rte_bucket_4_16 *) &f->memory[(f->n_buckets + bucket_index) * f->bucket_size]; bucket_prev->next = bucket; bucket_prev->next_valid = 1; bucket->signature[0] = signature; memcpy(bucket->key[0], key, f->key_size); memcpy(&bucket->data[0], entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) &bucket->data[0]; return 0; } return -ENOSPC; } static int rte_table_hash_entry_delete_key16_ext( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_16 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = 0; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); if ((bucket->signature[0] == 0) && (bucket->signature[1] == 0) && (bucket->signature[2] == 0) && (bucket->signature[3] == 0) && (bucket_prev != NULL)) { bucket_prev->next = bucket->next; bucket_prev->next_valid = bucket->next_valid; memset(bucket, 0, sizeof(struct rte_bucket_4_16)); bucket_index = (((uint8_t *)bucket - (uint8_t *)f->memory)/f->bucket_size) - f->n_buckets; f->stack[f->stack_pos++] = bucket_index; } return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } #define lookup_key16_cmp(key_in, bucket, pos) \ { \ uint64_t xor[4][2], or[4], signature[4]; \ \ signature[0] = (~bucket->signature[0]) & 1; \ signature[1] = (~bucket->signature[1]) & 1; \ signature[2] = (~bucket->signature[2]) & 1; \ signature[3] = (~bucket->signature[3]) & 1; \ \ xor[0][0] = key_in[0] ^ bucket->key[0][0]; \ xor[0][1] = key_in[1] ^ bucket->key[0][1]; \ \ xor[1][0] = key_in[0] ^ bucket->key[1][0]; \ xor[1][1] = key_in[1] ^ bucket->key[1][1]; \ \ xor[2][0] = key_in[0] ^ bucket->key[2][0]; \ xor[2][1] = key_in[1] ^ bucket->key[2][1]; \ \ xor[3][0] = key_in[0] ^ bucket->key[3][0]; \ xor[3][1] = key_in[1] ^ bucket->key[3][1]; \ \ or[0] = xor[0][0] | xor[0][1] | signature[0]; \ or[1] = xor[1][0] | xor[1][1] | signature[1]; \ or[2] = xor[2][0] | xor[2][1] | signature[2]; \ or[3] = xor[3][0] | xor[3][1] | signature[3]; \ \ pos = 4; \ if (or[0] == 0) \ pos = 0; \ if (or[1] == 0) \ pos = 1; \ if (or[2] == 0) \ pos = 2; \ if (or[3] == 0) \ pos = 3; \ } #define lookup1_stage0(pkt0_index, mbuf0, pkts, pkts_mask) \ { \ uint64_t pkt_mask; \ \ pkt0_index = __builtin_ctzll(pkts_mask); \ pkt_mask = 1LLU << pkt0_index; \ pkts_mask &= ~pkt_mask; \ \ mbuf0 = pkts[pkt0_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf0, 0)); \ } #define lookup1_stage1(mbuf1, bucket1, f) \ { \ uint64_t signature; \ uint32_t bucket_index; \ \ signature = RTE_MBUF_METADATA_UINT32(mbuf1, f->signature_offset);\ bucket_index = signature & (f->n_buckets - 1); \ bucket1 = (struct rte_bucket_4_16 *) \ &f->memory[bucket_index * f->bucket_size]; \ rte_prefetch0(bucket1); \ rte_prefetch0((void *)(((uintptr_t) bucket1) + RTE_CACHE_LINE_SIZE));\ } #define lookup1_stage2_lru(pkt2_index, mbuf2, bucket2, \ pkts_mask_out, entries, f) \ { \ void *a; \ uint64_t pkt_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key16_cmp(key, bucket2, pos); \ \ pkt_mask = (bucket2->signature[pos] & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ lru_update(bucket2, pos); \ } #define lookup1_stage2_ext(pkt2_index, mbuf2, bucket2, pkts_mask_out, entries, \ buckets_mask, buckets, keys, f) \ { \ struct rte_bucket_4_16 *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key16_cmp(key, bucket2, pos); \ \ pkt_mask = (bucket2->signature[pos] & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket2->next_valid << pkt2_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket2->next; \ buckets[pkt2_index] = bucket_next; \ keys[pkt2_index] = key; \ } #define lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries,\ buckets_mask, f) \ { \ struct rte_bucket_4_16 *bucket, *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ bucket = buckets[pkt_index]; \ key = keys[pkt_index]; \ \ lookup_key16_cmp(key, bucket, pos); \ \ pkt_mask = (bucket->signature[pos] & 1LLU) << pkt_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket->next_valid << pkt_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket->next; \ rte_prefetch0(bucket_next); \ rte_prefetch0((void *)(((uintptr_t) bucket_next) + RTE_CACHE_LINE_SIZE));\ buckets[pkt_index] = bucket_next; \ keys[pkt_index] = key; \ } #define lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01,\ pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,\ mbuf00, mbuf01, pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ if (pkts_mask == 0) \ pkt01_index = pkt00_index; \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f) \ { \ uint64_t signature10, signature11; \ uint32_t bucket10_index, bucket11_index; \ \ signature10 = RTE_MBUF_METADATA_UINT32(mbuf10, f->signature_offset);\ bucket10_index = signature10 & (f->n_buckets - 1); \ bucket10 = (struct rte_bucket_4_16 *) \ &f->memory[bucket10_index * f->bucket_size]; \ rte_prefetch0(bucket10); \ rte_prefetch0((void *)(((uintptr_t) bucket10) + RTE_CACHE_LINE_SIZE));\ \ signature11 = RTE_MBUF_METADATA_UINT32(mbuf11, f->signature_offset);\ bucket11_index = signature11 & (f->n_buckets - 1); \ bucket11 = (struct rte_bucket_4_16 *) \ &f->memory[bucket11_index * f->bucket_size]; \ rte_prefetch0(bucket11); \ rte_prefetch0((void *)(((uintptr_t) bucket11) + RTE_CACHE_LINE_SIZE));\ } #define lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,\ bucket20, bucket21, pkts_mask_out, entries, f) \ { \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask; \ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key16_cmp(key20, bucket20, pos20); \ lookup_key16_cmp(key21, bucket21, pos21); \ \ pkt20_mask = (bucket20->signature[pos20] & 1LLU) << pkt20_index;\ pkt21_mask = (bucket21->signature[pos21] & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ lru_update(bucket20, pos20); \ lru_update(bucket21, pos21); \ } #define lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, \ bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f) \ { \ struct rte_bucket_4_16 *bucket20_next, *bucket21_next; \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask, bucket20_mask, bucket21_mask;\ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key16_cmp(key20, bucket20, pos20); \ lookup_key16_cmp(key21, bucket21, pos21); \ \ pkt20_mask = (bucket20->signature[pos20] & 1LLU) << pkt20_index;\ pkt21_mask = (bucket21->signature[pos21] & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ \ bucket20_mask = (~pkt20_mask) & (bucket20->next_valid << pkt20_index);\ bucket21_mask = (~pkt21_mask) & (bucket21->next_valid << pkt21_index);\ buckets_mask |= bucket20_mask | bucket21_mask; \ bucket20_next = bucket20->next; \ bucket21_next = bucket21->next; \ buckets[pkt20_index] = bucket20_next; \ buckets[pkt21_index] = bucket21_next; \ keys[pkt20_index] = key20; \ keys[pkt21_index] = key21; \ } static int rte_table_hash_lookup_key16_lru( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY16_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_16 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_lru(pkt_index, mbuf, bucket, pkts_mask_out, entries, f); } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY16_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY16_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key16_lru() */ static int rte_table_hash_lookup_key16_ext( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_16 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0, buckets_mask = 0; struct rte_bucket_4_16 *buckets[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX]; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY16_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_16 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_ext(pkt_index, mbuf, bucket, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } goto grind_next_buckets; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); grind_next_buckets: /* Grind next buckets */ for ( ; buckets_mask; ) { uint64_t buckets_mask_next = 0; for ( ; buckets_mask; ) { uint64_t pkt_mask; uint32_t pkt_index; pkt_index = __builtin_ctzll(buckets_mask); pkt_mask = 1LLU << pkt_index; buckets_mask &= ~pkt_mask; lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries, buckets_mask_next, f); } buckets_mask = buckets_mask_next; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY16_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key16_ext() */ static int rte_table_hash_key16_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_hash *t = (struct rte_table_hash *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_hash_key16_lru_ops = { .f_create = rte_table_hash_create_key16_lru, .f_free = rte_table_hash_free_key16_lru, .f_add = rte_table_hash_entry_add_key16_lru, .f_delete = rte_table_hash_entry_delete_key16_lru, .f_lookup = rte_table_hash_lookup_key16_lru, .f_stats = rte_table_hash_key16_stats_read, }; struct rte_table_ops rte_table_hash_key16_ext_ops = { .f_create = rte_table_hash_create_key16_ext, .f_free = rte_table_hash_free_key16_ext, .f_add = rte_table_hash_entry_add_key16_ext, .f_delete = rte_table_hash_entry_delete_key16_ext, .f_lookup = rte_table_hash_lookup_key16_ext, .f_stats = rte_table_hash_key16_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_hash_key32.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_hash.h" #include "rte_lru.h" #define RTE_TABLE_HASH_KEY_SIZE 32 #define RTE_BUCKET_ENTRY_VALID 0x1LLU #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_HASH_KEY32_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_HASH_KEY32_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_HASH_KEY32_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_HASH_KEY32_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_bucket_4_32 { /* Cache line 0 */ uint64_t signature[4 + 1]; uint64_t lru_list; struct rte_bucket_4_32 *next; uint64_t next_valid; /* Cache lines 1 and 2 */ uint64_t key[4][4]; /* Cache line 3 */ uint8_t data[0]; }; struct rte_table_hash { struct rte_table_stats stats; /* Input parameters */ uint32_t n_buckets; uint32_t n_entries_per_bucket; uint32_t key_size; uint32_t entry_size; uint32_t bucket_size; uint32_t signature_offset; uint32_t key_offset; rte_table_hash_op_hash f_hash; uint64_t seed; /* Extendible buckets */ uint32_t n_buckets_ext; uint32_t stack_pos; uint32_t *stack; /* Lookup table */ uint8_t memory[0] __rte_cache_aligned; }; static int check_params_create_lru(struct rte_table_hash_key32_lru_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key32_lru(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key32_lru_params *p = (struct rte_table_hash_key32_lru_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_entries_per_bucket, key_size, bucket_size_cl; uint32_t total_size, i; /* Check input parameters */ if ((check_params_create_lru(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_32) % RTE_CACHE_LINE_SIZE) != 0)) { return NULL; } n_entries_per_bucket = 4; key_size = 32; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); bucket_size_cl = (sizeof(struct rte_bucket_4_32) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + n_buckets * bucket_size_cl * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; for (i = 0; i < n_buckets; i++) { struct rte_bucket_4_32 *bucket; bucket = (struct rte_bucket_4_32 *) &f->memory[i * f->bucket_size]; bucket->lru_list = 0x0000000100020003LLU; } return f; } static int rte_table_hash_free_key32_lru(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key32_lru( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket; uint64_t signature, pos; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_32 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } /* Key is not present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if (bucket_signature == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = signature; memcpy(bucket_key, key, f->key_size); memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } /* Bucket full: replace LRU entry */ pos = lru_pos(bucket); bucket->signature[pos] = signature; memcpy(bucket->key[pos], key, f->key_size); memcpy(&bucket->data[pos * f->entry_size], entry, f->entry_size); lru_update(bucket, pos); *key_found = 0; *entry_ptr = (void *) &bucket->data[pos * f->entry_size]; return 0; } static int rte_table_hash_entry_delete_key32_lru( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_32 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = 0; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } static int check_params_create_ext(struct rte_table_hash_key32_ext_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* n_entries_ext */ if (params->n_entries_ext == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries_ext is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key32_ext(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key32_ext_params *p = (struct rte_table_hash_key32_ext_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_buckets_ext, n_entries_per_bucket; uint32_t key_size, bucket_size_cl, stack_size_cl, total_size, i; /* Check input parameters */ if ((check_params_create_ext(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_32) % RTE_CACHE_LINE_SIZE) != 0)) return NULL; n_entries_per_bucket = 4; key_size = 32; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); n_buckets_ext = (p->n_entries_ext + n_entries_per_bucket - 1) / n_entries_per_bucket; bucket_size_cl = (sizeof(struct rte_bucket_4_32) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; stack_size_cl = (n_buckets_ext * sizeof(uint32_t) + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + ((n_buckets + n_buckets_ext) * bucket_size_cl + stack_size_cl) * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; f->n_buckets_ext = n_buckets_ext; f->stack_pos = n_buckets_ext; f->stack = (uint32_t *) &f->memory[(n_buckets + n_buckets_ext) * f->bucket_size]; for (i = 0; i < n_buckets_ext; i++) f->stack[i] = i; return f; } static int rte_table_hash_free_key32_ext(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key32_ext( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_32 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (bucket = bucket0; bucket != NULL; bucket = bucket->next) { for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } } /* Key is not present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if (bucket_signature == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = signature; memcpy(bucket_key, key, f->key_size); memcpy(bucket_data, entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } /* Bucket full: extend bucket */ if (f->stack_pos > 0) { bucket_index = f->stack[--f->stack_pos]; bucket = (struct rte_bucket_4_32 *) &f->memory[(f->n_buckets + bucket_index) * f->bucket_size]; bucket_prev->next = bucket; bucket_prev->next_valid = 1; bucket->signature[0] = signature; memcpy(bucket->key[0], key, f->key_size); memcpy(&bucket->data[0], entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) &bucket->data[0]; return 0; } return -ENOSPC; } static int rte_table_hash_entry_delete_key32_ext( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_32 *) &f->memory[bucket_index * f->bucket_size]; signature |= RTE_BUCKET_ENTRY_VALID; /* Key is present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) for (i = 0; i < 4; i++) { uint64_t bucket_signature = bucket->signature[i]; uint8_t *bucket_key = (uint8_t *) bucket->key[i]; if ((bucket_signature == signature) && (memcmp(key, bucket_key, f->key_size) == 0)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature[i] = 0; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); if ((bucket->signature[0] == 0) && (bucket->signature[1] == 0) && (bucket->signature[2] == 0) && (bucket->signature[3] == 0) && (bucket_prev != NULL)) { bucket_prev->next = bucket->next; bucket_prev->next_valid = bucket->next_valid; memset(bucket, 0, sizeof(struct rte_bucket_4_32)); bucket_index = (((uint8_t *)bucket - (uint8_t *)f->memory)/f->bucket_size) - f->n_buckets; f->stack[f->stack_pos++] = bucket_index; } return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } #define lookup_key32_cmp(key_in, bucket, pos) \ { \ uint64_t xor[4][4], or[4], signature[4]; \ \ signature[0] = ((~bucket->signature[0]) & 1); \ signature[1] = ((~bucket->signature[1]) & 1); \ signature[2] = ((~bucket->signature[2]) & 1); \ signature[3] = ((~bucket->signature[3]) & 1); \ \ xor[0][0] = key_in[0] ^ bucket->key[0][0]; \ xor[0][1] = key_in[1] ^ bucket->key[0][1]; \ xor[0][2] = key_in[2] ^ bucket->key[0][2]; \ xor[0][3] = key_in[3] ^ bucket->key[0][3]; \ \ xor[1][0] = key_in[0] ^ bucket->key[1][0]; \ xor[1][1] = key_in[1] ^ bucket->key[1][1]; \ xor[1][2] = key_in[2] ^ bucket->key[1][2]; \ xor[1][3] = key_in[3] ^ bucket->key[1][3]; \ \ xor[2][0] = key_in[0] ^ bucket->key[2][0]; \ xor[2][1] = key_in[1] ^ bucket->key[2][1]; \ xor[2][2] = key_in[2] ^ bucket->key[2][2]; \ xor[2][3] = key_in[3] ^ bucket->key[2][3]; \ \ xor[3][0] = key_in[0] ^ bucket->key[3][0]; \ xor[3][1] = key_in[1] ^ bucket->key[3][1]; \ xor[3][2] = key_in[2] ^ bucket->key[3][2]; \ xor[3][3] = key_in[3] ^ bucket->key[3][3]; \ \ or[0] = xor[0][0] | xor[0][1] | xor[0][2] | xor[0][3] | signature[0];\ or[1] = xor[1][0] | xor[1][1] | xor[1][2] | xor[1][3] | signature[1];\ or[2] = xor[2][0] | xor[2][1] | xor[2][2] | xor[2][3] | signature[2];\ or[3] = xor[3][0] | xor[3][1] | xor[3][2] | xor[3][3] | signature[3];\ \ pos = 4; \ if (or[0] == 0) \ pos = 0; \ if (or[1] == 0) \ pos = 1; \ if (or[2] == 0) \ pos = 2; \ if (or[3] == 0) \ pos = 3; \ } #define lookup1_stage0(pkt0_index, mbuf0, pkts, pkts_mask) \ { \ uint64_t pkt_mask; \ \ pkt0_index = __builtin_ctzll(pkts_mask); \ pkt_mask = 1LLU << pkt0_index; \ pkts_mask &= ~pkt_mask; \ \ mbuf0 = pkts[pkt0_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf0, 0)); \ } #define lookup1_stage1(mbuf1, bucket1, f) \ { \ uint64_t signature; \ uint32_t bucket_index; \ \ signature = RTE_MBUF_METADATA_UINT32(mbuf1, f->signature_offset);\ bucket_index = signature & (f->n_buckets - 1); \ bucket1 = (struct rte_bucket_4_32 *) \ &f->memory[bucket_index * f->bucket_size]; \ rte_prefetch0(bucket1); \ rte_prefetch0((void *)(((uintptr_t) bucket1) + RTE_CACHE_LINE_SIZE));\ rte_prefetch0((void *)(((uintptr_t) bucket1) + 2 * RTE_CACHE_LINE_SIZE));\ } #define lookup1_stage2_lru(pkt2_index, mbuf2, bucket2, \ pkts_mask_out, entries, f) \ { \ void *a; \ uint64_t pkt_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key32_cmp(key, bucket2, pos); \ \ pkt_mask = (bucket2->signature[pos] & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ lru_update(bucket2, pos); \ } #define lookup1_stage2_ext(pkt2_index, mbuf2, bucket2, pkts_mask_out,\ entries, buckets_mask, buckets, keys, f) \ { \ struct rte_bucket_4_32 *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key32_cmp(key, bucket2, pos); \ \ pkt_mask = (bucket2->signature[pos] & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket2->next_valid << pkt2_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket2->next; \ buckets[pkt2_index] = bucket_next; \ keys[pkt2_index] = key; \ } #define lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, \ entries, buckets_mask, f) \ { \ struct rte_bucket_4_32 *bucket, *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ bucket = buckets[pkt_index]; \ key = keys[pkt_index]; \ \ lookup_key32_cmp(key, bucket, pos); \ \ pkt_mask = (bucket->signature[pos] & 1LLU) << pkt_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket->next_valid << pkt_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket->next; \ rte_prefetch0(bucket_next); \ rte_prefetch0((void *)(((uintptr_t) bucket_next) + RTE_CACHE_LINE_SIZE));\ rte_prefetch0((void *)(((uintptr_t) bucket_next) + \ 2 * RTE_CACHE_LINE_SIZE)); \ buckets[pkt_index] = bucket_next; \ keys[pkt_index] = key; \ } #define lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01,\ pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,\ mbuf00, mbuf01, pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ if (pkts_mask == 0) \ pkt01_index = pkt00_index; \ \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f) \ { \ uint64_t signature10, signature11; \ uint32_t bucket10_index, bucket11_index; \ \ signature10 = RTE_MBUF_METADATA_UINT32(mbuf10, f->signature_offset);\ bucket10_index = signature10 & (f->n_buckets - 1); \ bucket10 = (struct rte_bucket_4_32 *) \ &f->memory[bucket10_index * f->bucket_size]; \ rte_prefetch0(bucket10); \ rte_prefetch0((void *)(((uintptr_t) bucket10) + RTE_CACHE_LINE_SIZE));\ rte_prefetch0((void *)(((uintptr_t) bucket10) + 2 * RTE_CACHE_LINE_SIZE));\ \ signature11 = RTE_MBUF_METADATA_UINT32(mbuf11, f->signature_offset);\ bucket11_index = signature11 & (f->n_buckets - 1); \ bucket11 = (struct rte_bucket_4_32 *) \ &f->memory[bucket11_index * f->bucket_size]; \ rte_prefetch0(bucket11); \ rte_prefetch0((void *)(((uintptr_t) bucket11) + RTE_CACHE_LINE_SIZE));\ rte_prefetch0((void *)(((uintptr_t) bucket11) + 2 * RTE_CACHE_LINE_SIZE));\ } #define lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,\ bucket20, bucket21, pkts_mask_out, entries, f) \ { \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask; \ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key32_cmp(key20, bucket20, pos20); \ lookup_key32_cmp(key21, bucket21, pos21); \ \ pkt20_mask = (bucket20->signature[pos20] & 1LLU) << pkt20_index;\ pkt21_mask = (bucket21->signature[pos21] & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ lru_update(bucket20, pos20); \ lru_update(bucket21, pos21); \ } #define lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, \ bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f)\ { \ struct rte_bucket_4_32 *bucket20_next, *bucket21_next; \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask, bucket20_mask, bucket21_mask;\ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key32_cmp(key20, bucket20, pos20); \ lookup_key32_cmp(key21, bucket21, pos21); \ \ pkt20_mask = (bucket20->signature[pos20] & 1LLU) << pkt20_index;\ pkt21_mask = (bucket21->signature[pos21] & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ \ bucket20_mask = (~pkt20_mask) & (bucket20->next_valid << pkt20_index);\ bucket21_mask = (~pkt21_mask) & (bucket21->next_valid << pkt21_index);\ buckets_mask |= bucket20_mask | bucket21_mask; \ bucket20_next = bucket20->next; \ bucket21_next = bucket21->next; \ buckets[pkt20_index] = bucket20_next; \ buckets[pkt21_index] = bucket21_next; \ keys[pkt20_index] = key20; \ keys[pkt21_index] = key21; \ } static int rte_table_hash_lookup_key32_lru( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY32_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_32 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_lru(pkt_index, mbuf, bucket, pkts_mask_out, entries, f); } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY32_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY32_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key32_lru() */ static int rte_table_hash_lookup_key32_ext( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_32 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0, buckets_mask = 0; struct rte_bucket_4_32 *buckets[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX]; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY32_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_32 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_ext(pkt_index, mbuf, bucket, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } goto grind_next_buckets; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); grind_next_buckets: /* Grind next buckets */ for ( ; buckets_mask; ) { uint64_t buckets_mask_next = 0; for ( ; buckets_mask; ) { uint64_t pkt_mask; uint32_t pkt_index; pkt_index = __builtin_ctzll(buckets_mask); pkt_mask = 1LLU << pkt_index; buckets_mask &= ~pkt_mask; lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries, buckets_mask_next, f); } buckets_mask = buckets_mask_next; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY32_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key32_ext() */ static int rte_table_hash_key32_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_hash *t = (struct rte_table_hash *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_hash_key32_lru_ops = { .f_create = rte_table_hash_create_key32_lru, .f_free = rte_table_hash_free_key32_lru, .f_add = rte_table_hash_entry_add_key32_lru, .f_delete = rte_table_hash_entry_delete_key32_lru, .f_lookup = rte_table_hash_lookup_key32_lru, .f_stats = rte_table_hash_key32_stats_read, }; struct rte_table_ops rte_table_hash_key32_ext_ops = { .f_create = rte_table_hash_create_key32_ext, .f_free = rte_table_hash_free_key32_ext, .f_add = rte_table_hash_entry_add_key32_ext, .f_delete = rte_table_hash_entry_delete_key32_ext, .f_lookup = rte_table_hash_lookup_key32_ext, .f_stats = rte_table_hash_key32_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_hash_key8.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_hash.h" #include "rte_lru.h" #define RTE_TABLE_HASH_KEY_SIZE 8 #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_bucket_4_8 { /* Cache line 0 */ uint64_t signature; uint64_t lru_list; struct rte_bucket_4_8 *next; uint64_t next_valid; uint64_t key[4]; /* Cache line 1 */ uint8_t data[0]; }; struct rte_table_hash { struct rte_table_stats stats; /* Input parameters */ uint32_t n_buckets; uint32_t n_entries_per_bucket; uint32_t key_size; uint32_t entry_size; uint32_t bucket_size; uint32_t signature_offset; uint32_t key_offset; rte_table_hash_op_hash f_hash; uint64_t seed; /* Extendible buckets */ uint32_t n_buckets_ext; uint32_t stack_pos; uint32_t *stack; /* Lookup table */ uint8_t memory[0] __rte_cache_aligned; }; static int check_params_create_lru(struct rte_table_hash_key8_lru_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key8_lru(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key8_lru_params *p = (struct rte_table_hash_key8_lru_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_entries_per_bucket, key_size, bucket_size_cl; uint32_t total_size, i; /* Check input parameters */ if ((check_params_create_lru(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_8) % RTE_CACHE_LINE_SIZE) != 0)) { return NULL; } n_entries_per_bucket = 4; key_size = 8; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); bucket_size_cl = (sizeof(struct rte_bucket_4_8) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + n_buckets * bucket_size_cl * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; for (i = 0; i < n_buckets; i++) { struct rte_bucket_4_8 *bucket; bucket = (struct rte_bucket_4_8 *) &f->memory[i * f->bucket_size]; bucket->lru_list = 0x0000000100020003LLU; } return f; } static int rte_table_hash_free_key8_lru(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key8_lru( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket; uint64_t signature, mask, pos; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_8 *) &f->memory[bucket_index * f->bucket_size]; /* Key is present in the bucket */ for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; uint64_t bucket_key = bucket->key[i]; if ((bucket_signature & mask) && (*((uint64_t *) key) == bucket_key)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } /* Key is not present in the bucket */ for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; if ((bucket_signature & mask) == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature |= mask; bucket->key[i] = *((uint64_t *) key); memcpy(bucket_data, entry, f->entry_size); lru_update(bucket, i); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } /* Bucket full: replace LRU entry */ pos = lru_pos(bucket); bucket->key[pos] = *((uint64_t *) key); memcpy(&bucket->data[pos * f->entry_size], entry, f->entry_size); lru_update(bucket, pos); *key_found = 0; *entry_ptr = (void *) &bucket->data[pos * f->entry_size]; return 0; } static int rte_table_hash_entry_delete_key8_lru( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket; uint64_t signature, mask; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket = (struct rte_bucket_4_8 *) &f->memory[bucket_index * f->bucket_size]; /* Key is present in the bucket */ for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; uint64_t bucket_key = bucket->key[i]; if ((bucket_signature & mask) && (*((uint64_t *) key) == bucket_key)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature &= ~mask; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } static int check_params_create_ext(struct rte_table_hash_key8_ext_params *params) { /* n_entries */ if (params->n_entries == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__); return -EINVAL; } /* n_entries_ext */ if (params->n_entries_ext == 0) { RTE_LOG(ERR, TABLE, "%s: n_entries_ext is zero\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_create_key8_ext(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_key8_ext_params *p = (struct rte_table_hash_key8_ext_params *) params; struct rte_table_hash *f; uint32_t n_buckets, n_buckets_ext, n_entries_per_bucket, key_size; uint32_t bucket_size_cl, stack_size_cl, total_size, i; /* Check input parameters */ if ((check_params_create_ext(p) != 0) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || ((sizeof(struct rte_bucket_4_8) % RTE_CACHE_LINE_SIZE) != 0)) return NULL; n_entries_per_bucket = 4; key_size = 8; /* Memory allocation */ n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) / n_entries_per_bucket); n_buckets_ext = (p->n_entries_ext + n_entries_per_bucket - 1) / n_entries_per_bucket; bucket_size_cl = (sizeof(struct rte_bucket_4_8) + n_entries_per_bucket * entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; stack_size_cl = (n_buckets_ext * sizeof(uint32_t) + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE; total_size = sizeof(struct rte_table_hash) + ((n_buckets + n_buckets_ext) * bucket_size_cl + stack_size_cl) * RTE_CACHE_LINE_SIZE; f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s: Hash table memory footprint is %u bytes\n", __func__, total_size); /* Memory initialization */ f->n_buckets = n_buckets; f->n_entries_per_bucket = n_entries_per_bucket; f->key_size = key_size; f->entry_size = entry_size; f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE; f->signature_offset = p->signature_offset; f->key_offset = p->key_offset; f->f_hash = p->f_hash; f->seed = p->seed; f->n_buckets_ext = n_buckets_ext; f->stack_pos = n_buckets_ext; f->stack = (uint32_t *) &f->memory[(n_buckets + n_buckets_ext) * f->bucket_size]; for (i = 0; i < n_buckets_ext; i++) f->stack[i] = i; return f; } static int rte_table_hash_free_key8_ext(void *table) { struct rte_table_hash *f = (struct rte_table_hash *) table; /* Check input parameters */ if (f == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } rte_free(f); return 0; } static int rte_table_hash_entry_add_key8_ext( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_8 *) &f->memory[bucket_index * f->bucket_size]; /* Key is present in the bucket */ for (bucket = bucket0; bucket != NULL; bucket = bucket->next) { uint64_t mask; for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; uint64_t bucket_key = bucket->key[i]; if ((bucket_signature & mask) && (*((uint64_t *) key) == bucket_key)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; memcpy(bucket_data, entry, f->entry_size); *key_found = 1; *entry_ptr = (void *) bucket_data; return 0; } } } /* Key is not present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) { uint64_t mask; for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; if ((bucket_signature & mask) == 0) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature |= mask; bucket->key[i] = *((uint64_t *) key); memcpy(bucket_data, entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) bucket_data; return 0; } } } /* Bucket full: extend bucket */ if (f->stack_pos > 0) { bucket_index = f->stack[--f->stack_pos]; bucket = (struct rte_bucket_4_8 *) &f->memory[(f->n_buckets + bucket_index) * f->bucket_size]; bucket_prev->next = bucket; bucket_prev->next_valid = 1; bucket->signature = 1; bucket->key[0] = *((uint64_t *) key); memcpy(&bucket->data[0], entry, f->entry_size); *key_found = 0; *entry_ptr = (void *) &bucket->data[0]; return 0; } return -ENOSPC; } static int rte_table_hash_entry_delete_key8_ext( void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket0, *bucket, *bucket_prev; uint64_t signature; uint32_t bucket_index, i; signature = f->f_hash(key, f->key_size, f->seed); bucket_index = signature & (f->n_buckets - 1); bucket0 = (struct rte_bucket_4_8 *) &f->memory[bucket_index * f->bucket_size]; /* Key is present in the bucket */ for (bucket_prev = NULL, bucket = bucket0; bucket != NULL; bucket_prev = bucket, bucket = bucket->next) { uint64_t mask; for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) { uint64_t bucket_signature = bucket->signature; uint64_t bucket_key = bucket->key[i]; if ((bucket_signature & mask) && (*((uint64_t *) key) == bucket_key)) { uint8_t *bucket_data = &bucket->data[i * f->entry_size]; bucket->signature &= ~mask; *key_found = 1; if (entry) memcpy(entry, bucket_data, f->entry_size); if ((bucket->signature == 0) && (bucket_prev != NULL)) { bucket_prev->next = bucket->next; bucket_prev->next_valid = bucket->next_valid; memset(bucket, 0, sizeof(struct rte_bucket_4_8)); bucket_index = (((uint8_t *)bucket - (uint8_t *)f->memory)/f->bucket_size) - f->n_buckets; f->stack[f->stack_pos++] = bucket_index; } return 0; } } } /* Key is not present in the bucket */ *key_found = 0; return 0; } #define lookup_key8_cmp(key_in, bucket, pos) \ { \ uint64_t xor[4], signature; \ \ signature = ~bucket->signature; \ \ xor[0] = (key_in[0] ^ bucket->key[0]) | (signature & 1);\ xor[1] = (key_in[0] ^ bucket->key[1]) | (signature & 2);\ xor[2] = (key_in[0] ^ bucket->key[2]) | (signature & 4);\ xor[3] = (key_in[0] ^ bucket->key[3]) | (signature & 8);\ \ pos = 4; \ if (xor[0] == 0) \ pos = 0; \ if (xor[1] == 0) \ pos = 1; \ if (xor[2] == 0) \ pos = 2; \ if (xor[3] == 0) \ pos = 3; \ } #define lookup1_stage0(pkt0_index, mbuf0, pkts, pkts_mask) \ { \ uint64_t pkt_mask; \ \ pkt0_index = __builtin_ctzll(pkts_mask); \ pkt_mask = 1LLU << pkt0_index; \ pkts_mask &= ~pkt_mask; \ \ mbuf0 = pkts[pkt0_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf0, 0)); \ } #define lookup1_stage1(mbuf1, bucket1, f) \ { \ uint64_t signature; \ uint32_t bucket_index; \ \ signature = RTE_MBUF_METADATA_UINT32(mbuf1, f->signature_offset);\ bucket_index = signature & (f->n_buckets - 1); \ bucket1 = (struct rte_bucket_4_8 *) \ &f->memory[bucket_index * f->bucket_size]; \ rte_prefetch0(bucket1); \ } #define lookup1_stage1_dosig(mbuf1, bucket1, f) \ { \ uint64_t *key; \ uint64_t signature; \ uint32_t bucket_index; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf1, f->key_offset);\ signature = f->f_hash(key, RTE_TABLE_HASH_KEY_SIZE, f->seed);\ bucket_index = signature & (f->n_buckets - 1); \ bucket1 = (struct rte_bucket_4_8 *) \ &f->memory[bucket_index * f->bucket_size]; \ rte_prefetch0(bucket1); \ } #define lookup1_stage2_lru(pkt2_index, mbuf2, bucket2, \ pkts_mask_out, entries, f) \ { \ void *a; \ uint64_t pkt_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key8_cmp(key, bucket2, pos); \ \ pkt_mask = ((bucket2->signature >> pos) & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ lru_update(bucket2, pos); \ } #define lookup1_stage2_ext(pkt2_index, mbuf2, bucket2, pkts_mask_out,\ entries, buckets_mask, buckets, keys, f) \ { \ struct rte_bucket_4_8 *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\ \ lookup_key8_cmp(key, bucket2, pos); \ \ pkt_mask = ((bucket2->signature >> pos) & 1LLU) << pkt2_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket2->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt2_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket2->next_valid << pkt2_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket2->next; \ buckets[pkt2_index] = bucket_next; \ keys[pkt2_index] = key; \ } #define lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries,\ buckets_mask, f) \ { \ struct rte_bucket_4_8 *bucket, *bucket_next; \ void *a; \ uint64_t pkt_mask, bucket_mask; \ uint64_t *key; \ uint32_t pos; \ \ bucket = buckets[pkt_index]; \ key = keys[pkt_index]; \ \ lookup_key8_cmp(key, bucket, pos); \ \ pkt_mask = ((bucket->signature >> pos) & 1LLU) << pkt_index;\ pkts_mask_out |= pkt_mask; \ \ a = (void *) &bucket->data[pos * f->entry_size]; \ rte_prefetch0(a); \ entries[pkt_index] = a; \ \ bucket_mask = (~pkt_mask) & (bucket->next_valid << pkt_index);\ buckets_mask |= bucket_mask; \ bucket_next = bucket->next; \ rte_prefetch0(bucket_next); \ buckets[pkt_index] = bucket_next; \ keys[pkt_index] = key; \ } #define lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01,\ pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,\ mbuf00, mbuf01, pkts, pkts_mask) \ { \ uint64_t pkt00_mask, pkt01_mask; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ \ mbuf00 = pkts[pkt00_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ if (pkts_mask == 0) \ pkt01_index = pkt00_index; \ \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ \ mbuf01 = pkts[pkt01_index]; \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f) \ { \ uint64_t signature10, signature11; \ uint32_t bucket10_index, bucket11_index; \ \ signature10 = RTE_MBUF_METADATA_UINT32(mbuf10, f->signature_offset);\ bucket10_index = signature10 & (f->n_buckets - 1); \ bucket10 = (struct rte_bucket_4_8 *) \ &f->memory[bucket10_index * f->bucket_size]; \ rte_prefetch0(bucket10); \ \ signature11 = RTE_MBUF_METADATA_UINT32(mbuf11, f->signature_offset);\ bucket11_index = signature11 & (f->n_buckets - 1); \ bucket11 = (struct rte_bucket_4_8 *) \ &f->memory[bucket11_index * f->bucket_size]; \ rte_prefetch0(bucket11); \ } #define lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f)\ { \ uint64_t *key10, *key11; \ uint64_t signature10, signature11; \ uint32_t bucket10_index, bucket11_index; \ rte_table_hash_op_hash f_hash = f->f_hash; \ uint64_t seed = f->seed; \ uint32_t key_offset = f->key_offset; \ \ key10 = RTE_MBUF_METADATA_UINT64_PTR(mbuf10, key_offset);\ key11 = RTE_MBUF_METADATA_UINT64_PTR(mbuf11, key_offset);\ \ signature10 = f_hash(key10, RTE_TABLE_HASH_KEY_SIZE, seed);\ bucket10_index = signature10 & (f->n_buckets - 1); \ bucket10 = (struct rte_bucket_4_8 *) \ &f->memory[bucket10_index * f->bucket_size]; \ rte_prefetch0(bucket10); \ \ signature11 = f_hash(key11, RTE_TABLE_HASH_KEY_SIZE, seed);\ bucket11_index = signature11 & (f->n_buckets - 1); \ bucket11 = (struct rte_bucket_4_8 *) \ &f->memory[bucket11_index * f->bucket_size]; \ rte_prefetch0(bucket11); \ } #define lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,\ bucket20, bucket21, pkts_mask_out, entries, f) \ { \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask; \ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key8_cmp(key20, bucket20, pos20); \ lookup_key8_cmp(key21, bucket21, pos21); \ \ pkt20_mask = ((bucket20->signature >> pos20) & 1LLU) << pkt20_index;\ pkt21_mask = ((bucket21->signature >> pos21) & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ lru_update(bucket20, pos20); \ lru_update(bucket21, pos21); \ } #define lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, \ bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f)\ { \ struct rte_bucket_4_8 *bucket20_next, *bucket21_next; \ void *a20, *a21; \ uint64_t pkt20_mask, pkt21_mask, bucket20_mask, bucket21_mask;\ uint64_t *key20, *key21; \ uint32_t pos20, pos21; \ \ key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\ key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\ \ lookup_key8_cmp(key20, bucket20, pos20); \ lookup_key8_cmp(key21, bucket21, pos21); \ \ pkt20_mask = ((bucket20->signature >> pos20) & 1LLU) << pkt20_index;\ pkt21_mask = ((bucket21->signature >> pos21) & 1LLU) << pkt21_index;\ pkts_mask_out |= pkt20_mask | pkt21_mask; \ \ a20 = (void *) &bucket20->data[pos20 * f->entry_size]; \ a21 = (void *) &bucket21->data[pos21 * f->entry_size]; \ rte_prefetch0(a20); \ rte_prefetch0(a21); \ entries[pkt20_index] = a20; \ entries[pkt21_index] = a21; \ \ bucket20_mask = (~pkt20_mask) & (bucket20->next_valid << pkt20_index);\ bucket21_mask = (~pkt21_mask) & (bucket21->next_valid << pkt21_index);\ buckets_mask |= bucket20_mask | bucket21_mask; \ bucket20_next = bucket20->next; \ bucket21_next = bucket21->next; \ buckets[pkt20_index] = bucket20_next; \ buckets[pkt21_index] = bucket21_next; \ keys[pkt20_index] = key20; \ keys[pkt21_index] = key21; \ } static int rte_table_hash_lookup_key8_lru( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index, pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_8 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_lru(pkt_index, mbuf, bucket, pkts_mask_out, entries, f); } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key8_lru() */ static int rte_table_hash_lookup_key8_lru_dosig( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_8 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1_dosig(mbuf, bucket, f); lookup1_stage2_lru(pkt_index, mbuf, bucket, pkts_mask_out, entries, f); } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, f); *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key8_lru_dosig() */ static int rte_table_hash_lookup_key8_ext( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0, buckets_mask = 0; struct rte_bucket_4_8 *buckets[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX]; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_8 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1(mbuf, bucket, f); lookup1_stage2_ext(pkt_index, mbuf, bucket, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } goto grind_next_buckets; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); grind_next_buckets: /* Grind next buckets */ for ( ; buckets_mask; ) { uint64_t buckets_mask_next = 0; for ( ; buckets_mask; ) { uint64_t pkt_mask; uint32_t pkt_index; pkt_index = __builtin_ctzll(buckets_mask); pkt_mask = 1LLU << pkt_index; buckets_mask &= ~pkt_mask; lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries, buckets_mask_next, f); } buckets_mask = buckets_mask_next; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key8_ext() */ static int rte_table_hash_lookup_key8_ext_dosig( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *f = (struct rte_table_hash *) table; struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21; struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21; uint32_t pkt00_index, pkt01_index, pkt10_index; uint32_t pkt11_index, pkt20_index, pkt21_index; uint64_t pkts_mask_out = 0, buckets_mask = 0; struct rte_bucket_4_8 *buckets[RTE_PORT_IN_BURST_SIZE_MAX]; uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX]; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_KEY8_STATS_PKTS_IN_ADD(f, n_pkts_in); /* Cannot run the pipeline with less than 5 packets */ if (__builtin_popcountll(pkts_mask) < 5) { for ( ; pkts_mask; ) { struct rte_bucket_4_8 *bucket; struct rte_mbuf *mbuf; uint32_t pkt_index; lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask); lookup1_stage1_dosig(mbuf, bucket, f); lookup1_stage2_ext(pkt_index, mbuf, bucket, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } goto grind_next_buckets; } /* * Pipeline fill * */ /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline feed */ mbuf10 = mbuf00; mbuf11 = mbuf01; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts, pkts_mask); /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); } /* * Pipeline flush * */ /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; mbuf10 = mbuf00; mbuf11 = mbuf01; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f); /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); /* Pipeline feed */ bucket20 = bucket10; bucket21 = bucket11; mbuf20 = mbuf10; mbuf21 = mbuf11; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f); grind_next_buckets: /* Grind next buckets */ for ( ; buckets_mask; ) { uint64_t buckets_mask_next = 0; for ( ; buckets_mask; ) { uint64_t pkt_mask; uint32_t pkt_index; pkt_index = __builtin_ctzll(buckets_mask); pkt_mask = 1LLU << pkt_index; buckets_mask &= ~pkt_mask; lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries, buckets_mask_next, f); } buckets_mask = buckets_mask_next; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_KEY8_STATS_PKTS_LOOKUP_MISS(f, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /* rte_table_hash_lookup_key8_dosig_ext() */ static int rte_table_hash_key8_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_hash *t = (struct rte_table_hash *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_hash_key8_lru_ops = { .f_create = rte_table_hash_create_key8_lru, .f_free = rte_table_hash_free_key8_lru, .f_add = rte_table_hash_entry_add_key8_lru, .f_delete = rte_table_hash_entry_delete_key8_lru, .f_lookup = rte_table_hash_lookup_key8_lru, .f_stats = rte_table_hash_key8_stats_read, }; struct rte_table_ops rte_table_hash_key8_lru_dosig_ops = { .f_create = rte_table_hash_create_key8_lru, .f_free = rte_table_hash_free_key8_lru, .f_add = rte_table_hash_entry_add_key8_lru, .f_delete = rte_table_hash_entry_delete_key8_lru, .f_lookup = rte_table_hash_lookup_key8_lru_dosig, .f_stats = rte_table_hash_key8_stats_read, }; struct rte_table_ops rte_table_hash_key8_ext_ops = { .f_create = rte_table_hash_create_key8_ext, .f_free = rte_table_hash_free_key8_ext, .f_add = rte_table_hash_entry_add_key8_ext, .f_delete = rte_table_hash_entry_delete_key8_ext, .f_lookup = rte_table_hash_lookup_key8_ext, .f_stats = rte_table_hash_key8_stats_read, }; struct rte_table_ops rte_table_hash_key8_ext_dosig_ops = { .f_create = rte_table_hash_create_key8_ext, .f_free = rte_table_hash_free_key8_ext, .f_add = rte_table_hash_entry_add_key8_ext, .f_delete = rte_table_hash_entry_delete_key8_ext, .f_lookup = rte_table_hash_lookup_key8_ext_dosig, .f_stats = rte_table_hash_key8_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_hash_lru.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "rte_table_hash.h" #include "rte_lru.h" #define KEYS_PER_BUCKET 4 #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_HASH_LRU_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_HASH_LRU_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_HASH_LRU_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_HASH_LRU_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct bucket { union { struct bucket *next; uint64_t lru_list; }; uint16_t sig[KEYS_PER_BUCKET]; uint32_t key_pos[KEYS_PER_BUCKET]; }; struct grinder { struct bucket *bkt; uint64_t sig; uint64_t match; uint64_t match_pos; uint32_t key_index; }; struct rte_table_hash { struct rte_table_stats stats; /* Input parameters */ uint32_t key_size; uint32_t entry_size; uint32_t n_keys; uint32_t n_buckets; rte_table_hash_op_hash f_hash; uint64_t seed; uint32_t signature_offset; uint32_t key_offset; /* Internal */ uint64_t bucket_mask; uint32_t key_size_shl; uint32_t data_size_shl; uint32_t key_stack_tos; /* Grinder */ struct grinder grinders[RTE_PORT_IN_BURST_SIZE_MAX]; /* Tables */ struct bucket *buckets; uint8_t *key_mem; uint8_t *data_mem; uint32_t *key_stack; /* Table memory */ uint8_t memory[0] __rte_cache_aligned; }; static int check_params_create(struct rte_table_hash_lru_params *params) { uint32_t n_buckets_min; /* key_size */ if ((params->key_size == 0) || (!rte_is_power_of_2(params->key_size))) { RTE_LOG(ERR, TABLE, "%s: key_size invalid value\n", __func__); return -EINVAL; } /* n_keys */ if ((params->n_keys == 0) || (!rte_is_power_of_2(params->n_keys))) { RTE_LOG(ERR, TABLE, "%s: n_keys invalid value\n", __func__); return -EINVAL; } /* n_buckets */ n_buckets_min = (params->n_keys + KEYS_PER_BUCKET - 1) / params->n_keys; if ((params->n_buckets == 0) || (!rte_is_power_of_2(params->n_keys)) || (params->n_buckets < n_buckets_min)) { RTE_LOG(ERR, TABLE, "%s: n_buckets invalid value\n", __func__); return -EINVAL; } /* f_hash */ if (params->f_hash == NULL) { RTE_LOG(ERR, TABLE, "%s: f_hash invalid value\n", __func__); return -EINVAL; } return 0; } static void * rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) { struct rte_table_hash_lru_params *p = (struct rte_table_hash_lru_params *) params; struct rte_table_hash *t; uint32_t total_size, table_meta_sz; uint32_t bucket_sz, key_sz, key_stack_sz, data_sz; uint32_t bucket_offset, key_offset, key_stack_offset, data_offset; uint32_t i; /* Check input parameters */ if ((check_params_create(p) != 0) || (!rte_is_power_of_2(entry_size)) || ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) || (sizeof(struct bucket) != (RTE_CACHE_LINE_SIZE / 2))) { return NULL; } /* Memory allocation */ table_meta_sz = RTE_CACHE_LINE_ROUNDUP(sizeof(struct rte_table_hash)); bucket_sz = RTE_CACHE_LINE_ROUNDUP(p->n_buckets * sizeof(struct bucket)); key_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * p->key_size); key_stack_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * sizeof(uint32_t)); data_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * entry_size); total_size = table_meta_sz + bucket_sz + key_sz + key_stack_sz + data_sz; t = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (t == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for hash table\n", __func__, total_size); return NULL; } RTE_LOG(INFO, TABLE, "%s (%u-byte key): Hash table memory footprint is " "%u bytes\n", __func__, p->key_size, total_size); /* Memory initialization */ t->key_size = p->key_size; t->entry_size = entry_size; t->n_keys = p->n_keys; t->n_buckets = p->n_buckets; t->f_hash = p->f_hash; t->seed = p->seed; t->signature_offset = p->signature_offset; t->key_offset = p->key_offset; /* Internal */ t->bucket_mask = t->n_buckets - 1; t->key_size_shl = __builtin_ctzl(p->key_size); t->data_size_shl = __builtin_ctzl(entry_size); /* Tables */ bucket_offset = 0; key_offset = bucket_offset + bucket_sz; key_stack_offset = key_offset + key_sz; data_offset = key_stack_offset + key_stack_sz; t->buckets = (struct bucket *) &t->memory[bucket_offset]; t->key_mem = &t->memory[key_offset]; t->key_stack = (uint32_t *) &t->memory[key_stack_offset]; t->data_mem = &t->memory[data_offset]; /* Key stack */ for (i = 0; i < t->n_keys; i++) t->key_stack[i] = t->n_keys - 1 - i; t->key_stack_tos = t->n_keys; /* LRU */ for (i = 0; i < t->n_buckets; i++) { struct bucket *bkt = &t->buckets[i]; lru_init(bkt); } return t; } static int rte_table_hash_lru_free(void *table) { struct rte_table_hash *t = (struct rte_table_hash *) table; /* Check input parameters */ if (t == NULL) return -EINVAL; rte_free(t); return 0; } static int rte_table_hash_lru_entry_add(void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct bucket *bkt; uint64_t sig; uint32_t bkt_index, i; sig = t->f_hash(key, t->key_size, t->seed); bkt_index = sig & t->bucket_mask; bkt = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; memcpy(data, entry, t->entry_size); lru_update(bkt, i); *key_found = 1; *entry_ptr = (void *) data; return 0; } } /* Key is not present in the bucket */ for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; if (bkt_sig == 0) { uint32_t bkt_key_index; uint8_t *bkt_key, *data; /* Allocate new key */ if (t->key_stack_tos == 0) { /* No keys available */ return -ENOSPC; } bkt_key_index = t->key_stack[--t->key_stack_tos]; /* Install new key */ bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; data = &t->data_mem[bkt_key_index << t->data_size_shl]; bkt->sig[i] = (uint16_t) sig; bkt->key_pos[i] = bkt_key_index; memcpy(bkt_key, key, t->key_size); memcpy(data, entry, t->entry_size); lru_update(bkt, i); *key_found = 0; *entry_ptr = (void *) data; return 0; } } /* Bucket full */ { uint64_t pos = lru_pos(bkt); uint32_t bkt_key_index = bkt->key_pos[pos]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; bkt->sig[pos] = (uint16_t) sig; memcpy(bkt_key, key, t->key_size); memcpy(data, entry, t->entry_size); lru_update(bkt, pos); *key_found = 0; *entry_ptr = (void *) data; return 0; } } static int rte_table_hash_lru_entry_delete(void *table, void *key, int *key_found, void *entry) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct bucket *bkt; uint64_t sig; uint32_t bkt_index, i; sig = t->f_hash(key, t->key_size, t->seed); bkt_index = sig & t->bucket_mask; bkt = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; bkt->sig[i] = 0; t->key_stack[t->key_stack_tos++] = bkt_key_index; *key_found = 1; memcpy(entry, data, t->entry_size); return 0; } } /* Key is not present in the bucket */ *key_found = 0; return 0; } static int rte_table_hash_lru_lookup_unoptimized( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries, int dosig) { struct rte_table_hash *t = (struct rte_table_hash *) table; uint64_t pkts_mask_out = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_LRU_STATS_PKTS_IN_ADD(t, n_pkts_in); for ( ; pkts_mask; ) { struct bucket *bkt; struct rte_mbuf *pkt; uint8_t *key; uint64_t pkt_mask, sig; uint32_t pkt_index, bkt_index, i; pkt_index = __builtin_ctzll(pkts_mask); pkt_mask = 1LLU << pkt_index; pkts_mask &= ~pkt_mask; pkt = pkts[pkt_index]; key = RTE_MBUF_METADATA_UINT8_PTR(pkt, t->key_offset); if (dosig) sig = (uint64_t) t->f_hash(key, t->key_size, t->seed); else sig = RTE_MBUF_METADATA_UINT32(pkt, t->signature_offset); bkt_index = sig & t->bucket_mask; bkt = &t->buckets[bkt_index]; sig = (sig >> 16) | 1LLU; /* Key is present in the bucket */ for (i = 0; i < KEYS_PER_BUCKET; i++) { uint64_t bkt_sig = (uint64_t) bkt->sig[i]; uint32_t bkt_key_index = bkt->key_pos[i]; uint8_t *bkt_key = &t->key_mem[bkt_key_index << t->key_size_shl]; if ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size) == 0)) { uint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl]; lru_update(bkt, i); pkts_mask_out |= pkt_mask; entries[pkt_index] = (void *) data; break; } } } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_LRU_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return 0; } /*** * * mask = match bitmask * match = at least one match * match_many = more than one match * match_pos = position of first match * * ---------------------------------------- * mask match match_many match_pos * ---------------------------------------- * 0000 0 0 00 * 0001 1 0 00 * 0010 1 0 01 * 0011 1 1 00 * ---------------------------------------- * 0100 1 0 10 * 0101 1 1 00 * 0110 1 1 01 * 0111 1 1 00 * ---------------------------------------- * 1000 1 0 11 * 1001 1 1 00 * 1010 1 1 01 * 1011 1 1 00 * ---------------------------------------- * 1100 1 1 10 * 1101 1 1 00 * 1110 1 1 01 * 1111 1 1 00 * ---------------------------------------- * * match = 1111_1111_1111_1110 * match_many = 1111_1110_1110_1000 * match_pos = 0001_0010_0001_0011__0001_0010_0001_0000 * * match = 0xFFFELLU * match_many = 0xFEE8LLU * match_pos = 0x12131210LLU * ***/ #define LUT_MATCH 0xFFFELLU #define LUT_MATCH_MANY 0xFEE8LLU #define LUT_MATCH_POS 0x12131210LLU #define lookup_cmp_sig(mbuf_sig, bucket, match, match_many, match_pos)\ { \ uint64_t bucket_sig[4], mask[4], mask_all; \ \ bucket_sig[0] = bucket->sig[0]; \ bucket_sig[1] = bucket->sig[1]; \ bucket_sig[2] = bucket->sig[2]; \ bucket_sig[3] = bucket->sig[3]; \ \ bucket_sig[0] ^= mbuf_sig; \ bucket_sig[1] ^= mbuf_sig; \ bucket_sig[2] ^= mbuf_sig; \ bucket_sig[3] ^= mbuf_sig; \ \ mask[0] = 0; \ mask[1] = 0; \ mask[2] = 0; \ mask[3] = 0; \ \ if (bucket_sig[0] == 0) \ mask[0] = 1; \ if (bucket_sig[1] == 0) \ mask[1] = 2; \ if (bucket_sig[2] == 0) \ mask[2] = 4; \ if (bucket_sig[3] == 0) \ mask[3] = 8; \ \ mask_all = (mask[0] | mask[1]) | (mask[2] | mask[3]); \ \ match = (LUT_MATCH >> mask_all) & 1; \ match_many = (LUT_MATCH_MANY >> mask_all) & 1; \ match_pos = (LUT_MATCH_POS >> (mask_all << 1)) & 3; \ } #define lookup_cmp_key(mbuf, key, match_key, f) \ { \ uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(mbuf, f->key_offset);\ uint64_t *bkt_key = (uint64_t *) key; \ \ switch (f->key_size) { \ case 8: \ { \ uint64_t xor = pkt_key[0] ^ bkt_key[0]; \ match_key = 0; \ if (xor == 0) \ match_key = 1; \ } \ break; \ \ case 16: \ { \ uint64_t xor[2], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ or = xor[0] | xor[1]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ case 32: \ { \ uint64_t xor[4], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ xor[2] = pkt_key[2] ^ bkt_key[2]; \ xor[3] = pkt_key[3] ^ bkt_key[3]; \ or = xor[0] | xor[1] | xor[2] | xor[3]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ case 64: \ { \ uint64_t xor[8], or; \ \ xor[0] = pkt_key[0] ^ bkt_key[0]; \ xor[1] = pkt_key[1] ^ bkt_key[1]; \ xor[2] = pkt_key[2] ^ bkt_key[2]; \ xor[3] = pkt_key[3] ^ bkt_key[3]; \ xor[4] = pkt_key[4] ^ bkt_key[4]; \ xor[5] = pkt_key[5] ^ bkt_key[5]; \ xor[6] = pkt_key[6] ^ bkt_key[6]; \ xor[7] = pkt_key[7] ^ bkt_key[7]; \ or = xor[0] | xor[1] | xor[2] | xor[3] | \ xor[4] | xor[5] | xor[6] | xor[7]; \ match_key = 0; \ if (or == 0) \ match_key = 1; \ } \ break; \ \ default: \ match_key = 0; \ if (memcmp(pkt_key, bkt_key, f->key_size) == 0) \ match_key = 1; \ } \ } #define lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index)\ { \ uint64_t pkt00_mask, pkt01_mask; \ struct rte_mbuf *mbuf00, *mbuf01; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ mbuf00 = pkts[pkt00_index]; \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ mbuf01 = pkts[pkt01_index]; \ \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, \ pkt01_index) \ { \ uint64_t pkt00_mask, pkt01_mask; \ struct rte_mbuf *mbuf00, *mbuf01; \ \ pkt00_index = __builtin_ctzll(pkts_mask); \ pkt00_mask = 1LLU << pkt00_index; \ pkts_mask &= ~pkt00_mask; \ mbuf00 = pkts[pkt00_index]; \ \ pkt01_index = __builtin_ctzll(pkts_mask); \ if (pkts_mask == 0) \ pkt01_index = pkt00_index; \ \ pkt01_mask = 1LLU << pkt01_index; \ pkts_mask &= ~pkt01_mask; \ mbuf01 = pkts[pkt01_index]; \ \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0)); \ rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0)); \ } #define lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index) \ { \ struct grinder *g10, *g11; \ uint64_t sig10, sig11, bkt10_index, bkt11_index; \ struct rte_mbuf *mbuf10, *mbuf11; \ struct bucket *bkt10, *bkt11, *buckets = t->buckets; \ uint64_t bucket_mask = t->bucket_mask; \ uint32_t signature_offset = t->signature_offset; \ \ mbuf10 = pkts[pkt10_index]; \ sig10 = (uint64_t) RTE_MBUF_METADATA_UINT32(mbuf10, signature_offset);\ bkt10_index = sig10 & bucket_mask; \ bkt10 = &buckets[bkt10_index]; \ \ mbuf11 = pkts[pkt11_index]; \ sig11 = (uint64_t) RTE_MBUF_METADATA_UINT32(mbuf11, signature_offset);\ bkt11_index = sig11 & bucket_mask; \ bkt11 = &buckets[bkt11_index]; \ \ rte_prefetch0(bkt10); \ rte_prefetch0(bkt11); \ \ g10 = &g[pkt10_index]; \ g10->sig = sig10; \ g10->bkt = bkt10; \ \ g11 = &g[pkt11_index]; \ g11->sig = sig11; \ g11->bkt = bkt11; \ } #define lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index)\ { \ struct grinder *g10, *g11; \ uint64_t sig10, sig11, bkt10_index, bkt11_index; \ struct rte_mbuf *mbuf10, *mbuf11; \ struct bucket *bkt10, *bkt11, *buckets = t->buckets; \ uint8_t *key10, *key11; \ uint64_t bucket_mask = t->bucket_mask; \ rte_table_hash_op_hash f_hash = t->f_hash; \ uint64_t seed = t->seed; \ uint32_t key_size = t->key_size; \ uint32_t key_offset = t->key_offset; \ \ mbuf10 = pkts[pkt10_index]; \ key10 = RTE_MBUF_METADATA_UINT8_PTR(mbuf10, key_offset);\ sig10 = (uint64_t) f_hash(key10, key_size, seed); \ bkt10_index = sig10 & bucket_mask; \ bkt10 = &buckets[bkt10_index]; \ \ mbuf11 = pkts[pkt11_index]; \ key11 = RTE_MBUF_METADATA_UINT8_PTR(mbuf11, key_offset);\ sig11 = (uint64_t) f_hash(key11, key_size, seed); \ bkt11_index = sig11 & bucket_mask; \ bkt11 = &buckets[bkt11_index]; \ \ rte_prefetch0(bkt10); \ rte_prefetch0(bkt11); \ \ g10 = &g[pkt10_index]; \ g10->sig = sig10; \ g10->bkt = bkt10; \ \ g11 = &g[pkt11_index]; \ g11->sig = sig11; \ g11->bkt = bkt11; \ } #define lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many)\ { \ struct grinder *g20, *g21; \ uint64_t sig20, sig21; \ struct bucket *bkt20, *bkt21; \ uint8_t *key20, *key21, *key_mem = t->key_mem; \ uint64_t match20, match21, match_many20, match_many21; \ uint64_t match_pos20, match_pos21; \ uint32_t key20_index, key21_index, key_size_shl = t->key_size_shl;\ \ g20 = &g[pkt20_index]; \ sig20 = g20->sig; \ bkt20 = g20->bkt; \ sig20 = (sig20 >> 16) | 1LLU; \ lookup_cmp_sig(sig20, bkt20, match20, match_many20, match_pos20);\ match20 <<= pkt20_index; \ match_many20 <<= pkt20_index; \ key20_index = bkt20->key_pos[match_pos20]; \ key20 = &key_mem[key20_index << key_size_shl]; \ \ g21 = &g[pkt21_index]; \ sig21 = g21->sig; \ bkt21 = g21->bkt; \ sig21 = (sig21 >> 16) | 1LLU; \ lookup_cmp_sig(sig21, bkt21, match21, match_many21, match_pos21);\ match21 <<= pkt21_index; \ match_many21 <<= pkt21_index; \ key21_index = bkt21->key_pos[match_pos21]; \ key21 = &key_mem[key21_index << key_size_shl]; \ \ rte_prefetch0(key20); \ rte_prefetch0(key21); \ \ pkts_mask_match_many |= match_many20 | match_many21; \ \ g20->match = match20; \ g20->match_pos = match_pos20; \ g20->key_index = key20_index; \ \ g21->match = match21; \ g21->match_pos = match_pos21; \ g21->key_index = key21_index; \ } #define lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, \ entries) \ { \ struct grinder *g30, *g31; \ struct rte_mbuf *mbuf30, *mbuf31; \ struct bucket *bkt30, *bkt31; \ uint8_t *key30, *key31, *key_mem = t->key_mem; \ uint8_t *data30, *data31, *data_mem = t->data_mem; \ uint64_t match30, match31, match_pos30, match_pos31; \ uint64_t match_key30, match_key31, match_keys; \ uint32_t key30_index, key31_index; \ uint32_t key_size_shl = t->key_size_shl; \ uint32_t data_size_shl = t->data_size_shl; \ \ mbuf30 = pkts[pkt30_index]; \ g30 = &g[pkt30_index]; \ bkt30 = g30->bkt; \ match30 = g30->match; \ match_pos30 = g30->match_pos; \ key30_index = g30->key_index; \ key30 = &key_mem[key30_index << key_size_shl]; \ lookup_cmp_key(mbuf30, key30, match_key30, t); \ match_key30 <<= pkt30_index; \ match_key30 &= match30; \ data30 = &data_mem[key30_index << data_size_shl]; \ entries[pkt30_index] = data30; \ \ mbuf31 = pkts[pkt31_index]; \ g31 = &g[pkt31_index]; \ bkt31 = g31->bkt; \ match31 = g31->match; \ match_pos31 = g31->match_pos; \ key31_index = g31->key_index; \ key31 = &key_mem[key31_index << key_size_shl]; \ lookup_cmp_key(mbuf31, key31, match_key31, t); \ match_key31 <<= pkt31_index; \ match_key31 &= match31; \ data31 = &data_mem[key31_index << data_size_shl]; \ entries[pkt31_index] = data31; \ \ rte_prefetch0(data30); \ rte_prefetch0(data31); \ \ match_keys = match_key30 | match_key31; \ pkts_mask_out |= match_keys; \ \ if (match_key30 == 0) \ match_pos30 = 4; \ lru_update(bkt30, match_pos30); \ \ if (match_key31 == 0) \ match_pos31 = 4; \ lru_update(bkt31, match_pos31); \ } /*** * The lookup function implements a 4-stage pipeline, with each stage processing * two different packets. The purpose of pipelined implementation is to hide the * latency of prefetching the data structures and loosen the data dependency * between instructions. * * p00 _______ p10 _______ p20 _______ p30 _______ * ----->| |----->| |----->| |----->| |-----> * | 0 | | 1 | | 2 | | 3 | * ----->|_______|----->|_______|----->|_______|----->|_______|-----> * p01 p11 p21 p31 * * The naming convention is: * pXY = packet Y of stage X, X = 0 .. 3, Y = 0 .. 1 * ***/ static int rte_table_hash_lru_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct grinder *g = t->grinders; uint64_t pkt00_index, pkt01_index, pkt10_index, pkt11_index; uint64_t pkt20_index, pkt21_index, pkt30_index, pkt31_index; uint64_t pkts_mask_out = 0, pkts_mask_match_many = 0; int status = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_LRU_STATS_PKTS_IN_ADD(t, n_pkts_in); /* Cannot run the pipeline with less than 7 packets */ if (__builtin_popcountll(pkts_mask) < 7) return rte_table_hash_lru_lookup_unoptimized(table, pkts, pkts_mask, lookup_hit_mask, entries, 0); /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline feed */ pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline feed */ pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); } /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Slow path */ pkts_mask_match_many &= ~pkts_mask_out; if (pkts_mask_match_many) { uint64_t pkts_mask_out_slow = 0; status = rte_table_hash_lru_lookup_unoptimized(table, pkts, pkts_mask_match_many, &pkts_mask_out_slow, entries, 0); pkts_mask_out |= pkts_mask_out_slow; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_LRU_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return status; } static int rte_table_hash_lru_lookup_dosig( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_hash *t = (struct rte_table_hash *) table; struct grinder *g = t->grinders; uint64_t pkt00_index, pkt01_index, pkt10_index, pkt11_index; uint64_t pkt20_index, pkt21_index, pkt30_index, pkt31_index; uint64_t pkts_mask_out = 0, pkts_mask_match_many = 0; int status = 0; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_HASH_LRU_STATS_PKTS_IN_ADD(t, n_pkts_in); /* Cannot run the pipeline with less than 7 packets */ if (__builtin_popcountll(pkts_mask) < 7) return rte_table_hash_lru_lookup_unoptimized(table, pkts, pkts_mask, lookup_hit_mask, entries, 1); /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline feed */ pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline feed */ pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* * Pipeline run * */ for ( ; pkts_mask; ) { /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 0 */ lookup2_stage0_with_odd_support(t, g, pkts, pkts_mask, pkt00_index, pkt01_index); /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); } /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; pkt10_index = pkt00_index; pkt11_index = pkt01_index; /* Pipeline stage 1 */ lookup2_stage1_dosig(t, g, pkts, pkt10_index, pkt11_index); /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; pkt20_index = pkt10_index; pkt21_index = pkt11_index; /* Pipeline stage 2 */ lookup2_stage2(t, g, pkt20_index, pkt21_index, pkts_mask_match_many); /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Pipeline feed */ pkt30_index = pkt20_index; pkt31_index = pkt21_index; /* Pipeline stage 3 */ lookup2_stage3(t, g, pkts, pkt30_index, pkt31_index, pkts_mask_out, entries); /* Slow path */ pkts_mask_match_many &= ~pkts_mask_out; if (pkts_mask_match_many) { uint64_t pkts_mask_out_slow = 0; status = rte_table_hash_lru_lookup_unoptimized(table, pkts, pkts_mask_match_many, &pkts_mask_out_slow, entries, 1); pkts_mask_out |= pkts_mask_out_slow; } *lookup_hit_mask = pkts_mask_out; RTE_TABLE_HASH_LRU_STATS_PKTS_LOOKUP_MISS(t, n_pkts_in - __builtin_popcountll(pkts_mask_out)); return status; } static int rte_table_hash_lru_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_hash *t = (struct rte_table_hash *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_hash_lru_ops = { .f_create = rte_table_hash_lru_create, .f_free = rte_table_hash_lru_free, .f_add = rte_table_hash_lru_entry_add, .f_delete = rte_table_hash_lru_entry_delete, .f_lookup = rte_table_hash_lru_lookup, .f_stats = rte_table_hash_lru_stats_read, }; struct rte_table_ops rte_table_hash_lru_dosig_ops = { .f_create = rte_table_hash_lru_create, .f_free = rte_table_hash_lru_free, .f_add = rte_table_hash_lru_entry_add, .f_delete = rte_table_hash_lru_entry_delete, .f_lookup = rte_table_hash_lru_lookup_dosig, .f_stats = rte_table_hash_lru_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_lpm.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "rte_table_lpm.h" #define RTE_TABLE_LPM_MAX_NEXT_HOPS 256 #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_LPM_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_LPM_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_table_lpm { struct rte_table_stats stats; /* Input parameters */ uint32_t entry_size; uint32_t entry_unique_size; uint32_t n_rules; uint32_t offset; /* Handle to low-level LPM table */ struct rte_lpm *lpm; /* Next Hop Table (NHT) */ uint32_t nht_users[RTE_TABLE_LPM_MAX_NEXT_HOPS]; uint8_t nht[0] __rte_cache_aligned; }; static void * rte_table_lpm_create(void *params, int socket_id, uint32_t entry_size) { struct rte_table_lpm_params *p = (struct rte_table_lpm_params *) params; struct rte_table_lpm *lpm; uint32_t total_size, nht_size; /* Check input parameters */ if (p == NULL) { RTE_LOG(ERR, TABLE, "%s: NULL input parameters\n", __func__); return NULL; } if (p->n_rules == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid n_rules\n", __func__); return NULL; } if (p->entry_unique_size == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid entry_unique_size\n", __func__); return NULL; } if (p->entry_unique_size > entry_size) { RTE_LOG(ERR, TABLE, "%s: Invalid entry_unique_size\n", __func__); return NULL; } entry_size = RTE_ALIGN(entry_size, sizeof(uint64_t)); /* Memory allocation */ nht_size = RTE_TABLE_LPM_MAX_NEXT_HOPS * entry_size; total_size = sizeof(struct rte_table_lpm) + nht_size; lpm = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for LPM table\n", __func__, total_size); return NULL; } /* LPM low-level table creation */ lpm->lpm = rte_lpm_create("LPM", socket_id, p->n_rules, 0); if (lpm->lpm == NULL) { rte_free(lpm); RTE_LOG(ERR, TABLE, "Unable to create low-level LPM table\n"); return NULL; } /* Memory initialization */ lpm->entry_size = entry_size; lpm->entry_unique_size = p->entry_unique_size; lpm->n_rules = p->n_rules; lpm->offset = p->offset; return lpm; } static int rte_table_lpm_free(void *table) { struct rte_table_lpm *lpm = (struct rte_table_lpm *) table; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } /* Free previously allocated resources */ rte_lpm_free(lpm->lpm); rte_free(lpm); return 0; } static int nht_find_free(struct rte_table_lpm *lpm, uint32_t *pos) { uint32_t i; for (i = 0; i < RTE_TABLE_LPM_MAX_NEXT_HOPS; i++) { if (lpm->nht_users[i] == 0) { *pos = i; return 1; } } return 0; } static int nht_find_existing(struct rte_table_lpm *lpm, void *entry, uint32_t *pos) { uint32_t i; for (i = 0; i < RTE_TABLE_LPM_MAX_NEXT_HOPS; i++) { uint8_t *nht_entry = &lpm->nht[i * lpm->entry_size]; if ((lpm->nht_users[i] > 0) && (memcmp(nht_entry, entry, lpm->entry_unique_size) == 0)) { *pos = i; return 1; } } return 0; } static int rte_table_lpm_entry_add( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_lpm *lpm = (struct rte_table_lpm *) table; struct rte_table_lpm_key *ip_prefix = (struct rte_table_lpm_key *) key; uint32_t nht_pos, nht_pos0_valid; int status; uint8_t nht_pos0 = 0; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (ip_prefix == NULL) { RTE_LOG(ERR, TABLE, "%s: ip_prefix parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, TABLE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if ((ip_prefix->depth == 0) || (ip_prefix->depth > 32)) { RTE_LOG(ERR, TABLE, "%s: invalid depth (%d)\n", __func__, ip_prefix->depth); return -EINVAL; } /* Check if rule is already present in the table */ status = rte_lpm_is_rule_present(lpm->lpm, ip_prefix->ip, ip_prefix->depth, &nht_pos0); nht_pos0_valid = status > 0; /* Find existing or free NHT entry */ if (nht_find_existing(lpm, entry, &nht_pos) == 0) { uint8_t *nht_entry; if (nht_find_free(lpm, &nht_pos) == 0) { RTE_LOG(ERR, TABLE, "%s: NHT full\n", __func__); return -1; } nht_entry = &lpm->nht[nht_pos * lpm->entry_size]; memcpy(nht_entry, entry, lpm->entry_size); } /* Add rule to low level LPM table */ if (rte_lpm_add(lpm->lpm, ip_prefix->ip, ip_prefix->depth, (uint8_t) nht_pos) < 0) { RTE_LOG(ERR, TABLE, "%s: LPM rule add failed\n", __func__); return -1; } /* Commit NHT changes */ lpm->nht_users[nht_pos]++; lpm->nht_users[nht_pos0] -= nht_pos0_valid; *key_found = nht_pos0_valid; *entry_ptr = (void *) &lpm->nht[nht_pos * lpm->entry_size]; return 0; } static int rte_table_lpm_entry_delete( void *table, void *key, int *key_found, void *entry) { struct rte_table_lpm *lpm = (struct rte_table_lpm *) table; struct rte_table_lpm_key *ip_prefix = (struct rte_table_lpm_key *) key; uint8_t nht_pos; int status; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (ip_prefix == NULL) { RTE_LOG(ERR, TABLE, "%s: ip_prefix parameter is NULL\n", __func__); return -EINVAL; } if ((ip_prefix->depth == 0) || (ip_prefix->depth > 32)) { RTE_LOG(ERR, TABLE, "%s: invalid depth (%d)\n", __func__, ip_prefix->depth); return -EINVAL; } /* Return if rule is not present in the table */ status = rte_lpm_is_rule_present(lpm->lpm, ip_prefix->ip, ip_prefix->depth, &nht_pos); if (status < 0) { RTE_LOG(ERR, TABLE, "%s: LPM algorithmic error\n", __func__); return -1; } if (status == 0) { *key_found = 0; return 0; } /* Delete rule from the low-level LPM table */ status = rte_lpm_delete(lpm->lpm, ip_prefix->ip, ip_prefix->depth); if (status) { RTE_LOG(ERR, TABLE, "%s: LPM rule delete failed\n", __func__); return -1; } /* Commit NHT changes */ lpm->nht_users[nht_pos]--; *key_found = 1; if (entry) memcpy(entry, &lpm->nht[nht_pos * lpm->entry_size], lpm->entry_size); return 0; } static int rte_table_lpm_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_lpm *lpm = (struct rte_table_lpm *) table; uint64_t pkts_out_mask = 0; uint32_t i; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_LPM_STATS_PKTS_IN_ADD(lpm, n_pkts_in); pkts_out_mask = 0; for (i = 0; i < (uint32_t)(RTE_PORT_IN_BURST_SIZE_MAX - __builtin_clzll(pkts_mask)); i++) { uint64_t pkt_mask = 1LLU << i; if (pkt_mask & pkts_mask) { struct rte_mbuf *pkt = pkts[i]; uint32_t ip = rte_bswap32( RTE_MBUF_METADATA_UINT32(pkt, lpm->offset)); int status; uint8_t nht_pos; status = rte_lpm_lookup(lpm->lpm, ip, &nht_pos); if (status == 0) { pkts_out_mask |= pkt_mask; entries[i] = (void *) &lpm->nht[nht_pos * lpm->entry_size]; } } } *lookup_hit_mask = pkts_out_mask; RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(lpm, n_pkts_in - __builtin_popcountll(pkts_out_mask)); return 0; } static int rte_table_lpm_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_lpm *t = (struct rte_table_lpm *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_lpm_ops = { .f_create = rte_table_lpm_create, .f_free = rte_table_lpm_free, .f_add = rte_table_lpm_entry_add, .f_delete = rte_table_lpm_entry_delete, .f_lookup = rte_table_lpm_lookup, .f_stats = rte_table_lpm_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_lpm.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_LPM_H__ #define __INCLUDE_RTE_TABLE_LPM_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table LPM for IPv4 * * This table uses the Longest Prefix Match (LPM) algorithm to uniquely * associate data to lookup keys. * * Use-case: IP routing table. Routes that are added to the table associate a * next hop to an IP prefix. The IP prefix is specified as IP address and depth * and cover for a multitude of lookup keys (i.e. destination IP addresses) * that all share the same data (i.e. next hop). The next hop information * typically contains the output interface ID, the IP address of the next hop * station (which is part of the same IP network the output interface is * connected to) and other flags and counters. * * The LPM primitive only allows associating an 8-bit number (next hop ID) to * an IP prefix, while a routing table can potentially contain thousands of * routes or even more. This means that the same next hop ID (and next hop * information) has to be shared by multiple routes, which makes sense, as * multiple remote networks could be reached through the same next hop. * Therefore, when a route is added or updated, the LPM table has to check * whether the same next hop is already in use before using a new next hop ID * for this route. * * The comparison between different next hops is done for the first * “entry_unique_size” bytes of the next hop information (configurable * parameter), which have to uniquely identify the next hop, therefore the user * has to carefully manage the format of the LPM table entry (i.e. the next * hop information) so that any next hop data that changes value during * run-time (e.g. counters) is placed outside of this area. * ***/ #include #include "rte_table.h" /** LPM table parameters */ struct rte_table_lpm_params { /** Maximum number of LPM rules (i.e. IP routes) */ uint32_t n_rules; /** Number of bytes at the start of the table entry that uniquely identify the entry. Cannot be bigger than table entry size. */ uint32_t entry_unique_size; /** Byte offset within input packet meta-data where lookup key (i.e. the destination IP address) is located. */ uint32_t offset; }; /** LPM table rule (i.e. route), specified as IP prefix. While the key used by the lookup operation is the destination IP address (read from the input packet meta-data), the entry add and entry delete operations work with LPM rules, with each rule covering for a multitude of lookup keys (destination IP addresses) that share the same data (next hop). */ struct rte_table_lpm_key { /** IP address */ uint32_t ip; /** IP address depth. The most significant "depth" bits of the IP address specify the network part of the IP address, while the rest of the bits specify the host part of the address and are ignored for the purpose of route specification. */ uint8_t depth; }; /** LPM table operations */ extern struct rte_table_ops rte_table_lpm_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_lpm_ipv6.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "rte_table_lpm_ipv6.h" #define RTE_TABLE_LPM_MAX_NEXT_HOPS 256 #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_LPM_IPV6_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_LPM_IPV6_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_LPM_IPV6_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_LPM_IPV6_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_table_lpm_ipv6 { struct rte_table_stats stats; /* Input parameters */ uint32_t entry_size; uint32_t entry_unique_size; uint32_t n_rules; uint32_t offset; /* Handle to low-level LPM table */ struct rte_lpm6 *lpm; /* Next Hop Table (NHT) */ uint32_t nht_users[RTE_TABLE_LPM_MAX_NEXT_HOPS]; uint8_t nht[0] __rte_cache_aligned; }; static void * rte_table_lpm_ipv6_create(void *params, int socket_id, uint32_t entry_size) { struct rte_table_lpm_ipv6_params *p = (struct rte_table_lpm_ipv6_params *) params; struct rte_table_lpm_ipv6 *lpm; struct rte_lpm6_config lpm6_config; uint32_t total_size, nht_size; /* Check input parameters */ if (p == NULL) { RTE_LOG(ERR, TABLE, "%s: NULL input parameters\n", __func__); return NULL; } if (p->n_rules == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid n_rules\n", __func__); return NULL; } if (p->number_tbl8s == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid n_rules\n", __func__); return NULL; } if (p->entry_unique_size == 0) { RTE_LOG(ERR, TABLE, "%s: Invalid entry_unique_size\n", __func__); return NULL; } if (p->entry_unique_size > entry_size) { RTE_LOG(ERR, TABLE, "%s: Invalid entry_unique_size\n", __func__); return NULL; } entry_size = RTE_ALIGN(entry_size, sizeof(uint64_t)); /* Memory allocation */ nht_size = RTE_TABLE_LPM_MAX_NEXT_HOPS * entry_size; total_size = sizeof(struct rte_table_lpm_ipv6) + nht_size; lpm = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for LPM IPv6 table\n", __func__, total_size); return NULL; } /* LPM low-level table creation */ lpm6_config.max_rules = p->n_rules; lpm6_config.number_tbl8s = p->number_tbl8s; lpm6_config.flags = 0; lpm->lpm = rte_lpm6_create("LPM IPv6", socket_id, &lpm6_config); if (lpm->lpm == NULL) { rte_free(lpm); RTE_LOG(ERR, TABLE, "Unable to create low-level LPM IPv6 table\n"); return NULL; } /* Memory initialization */ lpm->entry_size = entry_size; lpm->entry_unique_size = p->entry_unique_size; lpm->n_rules = p->n_rules; lpm->offset = p->offset; return lpm; } static int rte_table_lpm_ipv6_free(void *table) { struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } /* Free previously allocated resources */ rte_lpm6_free(lpm->lpm); rte_free(lpm); return 0; } static int nht_find_free(struct rte_table_lpm_ipv6 *lpm, uint32_t *pos) { uint32_t i; for (i = 0; i < RTE_TABLE_LPM_MAX_NEXT_HOPS; i++) { if (lpm->nht_users[i] == 0) { *pos = i; return 1; } } return 0; } static int nht_find_existing(struct rte_table_lpm_ipv6 *lpm, void *entry, uint32_t *pos) { uint32_t i; for (i = 0; i < RTE_TABLE_LPM_MAX_NEXT_HOPS; i++) { uint8_t *nht_entry = &lpm->nht[i * lpm->entry_size]; if ((lpm->nht_users[i] > 0) && (memcmp(nht_entry, entry, lpm->entry_unique_size) == 0)) { *pos = i; return 1; } } return 0; } static int rte_table_lpm_ipv6_entry_add( void *table, void *key, void *entry, int *key_found, void **entry_ptr) { struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; struct rte_table_lpm_ipv6_key *ip_prefix = (struct rte_table_lpm_ipv6_key *) key; uint32_t nht_pos, nht_pos0_valid; int status; uint8_t nht_pos0; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (ip_prefix == NULL) { RTE_LOG(ERR, TABLE, "%s: ip_prefix parameter is NULL\n", __func__); return -EINVAL; } if (entry == NULL) { RTE_LOG(ERR, TABLE, "%s: entry parameter is NULL\n", __func__); return -EINVAL; } if ((ip_prefix->depth == 0) || (ip_prefix->depth > 128)) { RTE_LOG(ERR, TABLE, "%s: invalid depth (%d)\n", __func__, ip_prefix->depth); return -EINVAL; } /* Check if rule is already present in the table */ status = rte_lpm6_is_rule_present(lpm->lpm, ip_prefix->ip, ip_prefix->depth, &nht_pos0); nht_pos0_valid = status > 0; /* Find existing or free NHT entry */ if (nht_find_existing(lpm, entry, &nht_pos) == 0) { uint8_t *nht_entry; if (nht_find_free(lpm, &nht_pos) == 0) { RTE_LOG(ERR, TABLE, "%s: NHT full\n", __func__); return -1; } nht_entry = &lpm->nht[nht_pos * lpm->entry_size]; memcpy(nht_entry, entry, lpm->entry_size); } /* Add rule to low level LPM table */ if (rte_lpm6_add(lpm->lpm, ip_prefix->ip, ip_prefix->depth, (uint8_t) nht_pos) < 0) { RTE_LOG(ERR, TABLE, "%s: LPM IPv6 rule add failed\n", __func__); return -1; } /* Commit NHT changes */ lpm->nht_users[nht_pos]++; lpm->nht_users[nht_pos0] -= nht_pos0_valid; *key_found = nht_pos0_valid; *entry_ptr = (void *) &lpm->nht[nht_pos * lpm->entry_size]; return 0; } static int rte_table_lpm_ipv6_entry_delete( void *table, void *key, int *key_found, void *entry) { struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; struct rte_table_lpm_ipv6_key *ip_prefix = (struct rte_table_lpm_ipv6_key *) key; uint8_t nht_pos; int status; /* Check input parameters */ if (lpm == NULL) { RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__); return -EINVAL; } if (ip_prefix == NULL) { RTE_LOG(ERR, TABLE, "%s: ip_prefix parameter is NULL\n", __func__); return -EINVAL; } if ((ip_prefix->depth == 0) || (ip_prefix->depth > 128)) { RTE_LOG(ERR, TABLE, "%s: invalid depth (%d)\n", __func__, ip_prefix->depth); return -EINVAL; } /* Return if rule is not present in the table */ status = rte_lpm6_is_rule_present(lpm->lpm, ip_prefix->ip, ip_prefix->depth, &nht_pos); if (status < 0) { RTE_LOG(ERR, TABLE, "%s: LPM IPv6 algorithmic error\n", __func__); return -1; } if (status == 0) { *key_found = 0; return 0; } /* Delete rule from the low-level LPM table */ status = rte_lpm6_delete(lpm->lpm, ip_prefix->ip, ip_prefix->depth); if (status) { RTE_LOG(ERR, TABLE, "%s: LPM IPv6 rule delete failed\n", __func__); return -1; } /* Commit NHT changes */ lpm->nht_users[nht_pos]--; *key_found = 1; if (entry) memcpy(entry, &lpm->nht[nht_pos * lpm->entry_size], lpm->entry_size); return 0; } static int rte_table_lpm_ipv6_lookup( void *table, struct rte_mbuf **pkts, uint64_t pkts_mask, uint64_t *lookup_hit_mask, void **entries) { struct rte_table_lpm_ipv6 *lpm = (struct rte_table_lpm_ipv6 *) table; uint64_t pkts_out_mask = 0; uint32_t i; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_LPM_IPV6_STATS_PKTS_IN_ADD(lpm, n_pkts_in); pkts_out_mask = 0; for (i = 0; i < (uint32_t)(RTE_PORT_IN_BURST_SIZE_MAX - __builtin_clzll(pkts_mask)); i++) { uint64_t pkt_mask = 1LLU << i; if (pkt_mask & pkts_mask) { struct rte_mbuf *pkt = pkts[i]; uint8_t *ip = RTE_MBUF_METADATA_UINT8_PTR(pkt, lpm->offset); int status; uint8_t nht_pos; status = rte_lpm6_lookup(lpm->lpm, ip, &nht_pos); if (status == 0) { pkts_out_mask |= pkt_mask; entries[i] = (void *) &lpm->nht[nht_pos * lpm->entry_size]; } } } *lookup_hit_mask = pkts_out_mask; RTE_TABLE_LPM_IPV6_STATS_PKTS_LOOKUP_MISS(lpm, n_pkts_in - __builtin_popcountll(pkts_out_mask)); return 0; } static int rte_table_lpm_ipv6_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_lpm_ipv6 *t = (struct rte_table_lpm_ipv6 *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_lpm_ipv6_ops = { .f_create = rte_table_lpm_ipv6_create, .f_free = rte_table_lpm_ipv6_free, .f_add = rte_table_lpm_ipv6_entry_add, .f_delete = rte_table_lpm_ipv6_entry_delete, .f_lookup = rte_table_lpm_ipv6_lookup, .f_stats = rte_table_lpm_ipv6_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_lpm_ipv6.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_LPM_IPV6_H__ #define __INCLUDE_RTE_TABLE_LPM_IPV6_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table LPM for IPv6 * * This table uses the Longest Prefix Match (LPM) algorithm to uniquely * associate data to lookup keys. * * Use-case: IP routing table. Routes that are added to the table associate a * next hop to an IP prefix. The IP prefix is specified as IP address and depth * and cover for a multitude of lookup keys (i.e. destination IP addresses) * that all share the same data (i.e. next hop). The next hop information * typically contains the output interface ID, the IP address of the next hop * station (which is part of the same IP network the output interface is * connected to) and other flags and counters. * * The LPM primitive only allows associating an 8-bit number (next hop ID) to * an IP prefix, while a routing table can potentially contain thousands of * routes or even more. This means that the same next hop ID (and next hop * information) has to be shared by multiple routes, which makes sense, as * multiple remote networks could be reached through the same next hop. * Therefore, when a route is added or updated, the LPM table has to check * whether the same next hop is already in use before using a new next hop ID * for this route. * * The comparison between different next hops is done for the first * “entry_unique_size” bytes of the next hop information (configurable * parameter), which have to uniquely identify the next hop, therefore the user * has to carefully manage the format of the LPM table entry (i.e. the next * hop information) so that any next hop data that changes value during * run-time (e.g. counters) is placed outside of this area. * ***/ #include #include "rte_table.h" #define RTE_LPM_IPV6_ADDR_SIZE 16 /** LPM table parameters */ struct rte_table_lpm_ipv6_params { /** Maximum number of LPM rules (i.e. IP routes) */ uint32_t n_rules; uint32_t number_tbl8s; /** Number of bytes at the start of the table entry that uniquely identify the entry. Cannot be bigger than table entry size. */ uint32_t entry_unique_size; /** Byte offset within input packet meta-data where lookup key (i.e. the destination IP address) is located. */ uint32_t offset; }; /** LPM table rule (i.e. route), specified as IP prefix. While the key used by the lookup operation is the destination IP address (read from the input packet meta-data), the entry add and entry delete operations work with LPM rules, with each rule covering for a multitude of lookup keys (destination IP addresses) that share the same data (next hop). */ struct rte_table_lpm_ipv6_key { /** IP address */ uint8_t ip[RTE_LPM_IPV6_ADDR_SIZE]; /** IP address depth. The most significant "depth" bits of the IP address specify the network part of the IP address, while the rest of the bits specify the host part of the address and are ignored for the purpose of route specification. */ uint8_t depth; }; /** LPM table operations */ extern struct rte_table_ops rte_table_lpm_ipv6_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_table/rte_table_stub.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "rte_table_stub.h" #ifdef RTE_TABLE_STATS_COLLECT #define RTE_TABLE_LPM_STATS_PKTS_IN_ADD(table, val) \ table->stats.n_pkts_in += val #define RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(table, val) \ table->stats.n_pkts_lookup_miss += val #else #define RTE_TABLE_LPM_STATS_PKTS_IN_ADD(table, val) #define RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(table, val) #endif struct rte_table_stub { struct rte_table_stats stats; }; static void * rte_table_stub_create(__rte_unused void *params, __rte_unused int socket_id, __rte_unused uint32_t entry_size) { struct rte_table_stub *stub; uint32_t size; size = sizeof(struct rte_table_stub); stub = rte_zmalloc_socket("TABLE", size, RTE_CACHE_LINE_SIZE, socket_id); if (stub == NULL) { RTE_LOG(ERR, TABLE, "%s: Cannot allocate %u bytes for stub table\n", __func__, size); return NULL; } return stub; } static int rte_table_stub_lookup( __rte_unused void *table, __rte_unused struct rte_mbuf **pkts, __rte_unused uint64_t pkts_mask, uint64_t *lookup_hit_mask, __rte_unused void **entries) { __rte_unused struct rte_table_stub *stub = (struct rte_table_stub *) table; __rte_unused uint32_t n_pkts_in = __builtin_popcountll(pkts_mask); RTE_TABLE_LPM_STATS_PKTS_IN_ADD(stub, n_pkts_in); *lookup_hit_mask = 0; RTE_TABLE_LPM_STATS_PKTS_LOOKUP_MISS(stub, n_pkts_in); return 0; } static int rte_table_stub_stats_read(void *table, struct rte_table_stats *stats, int clear) { struct rte_table_stub *t = (struct rte_table_stub *) table; if (stats != NULL) memcpy(stats, &t->stats, sizeof(t->stats)); if (clear) memset(&t->stats, 0, sizeof(t->stats)); return 0; } struct rte_table_ops rte_table_stub_ops = { .f_create = rte_table_stub_create, .f_free = NULL, .f_add = NULL, .f_delete = NULL, .f_lookup = rte_table_stub_lookup, .f_stats = rte_table_stub_stats_read, }; ================================================ FILE: lib/librte_table/rte_table_stub.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __INCLUDE_RTE_TABLE_STUB_H__ #define __INCLUDE_RTE_TABLE_STUB_H__ #ifdef __cplusplus extern "C" { #endif /** * @file * RTE Table Stub * * The stub table lookup operation produces lookup miss for all input packets. * ***/ #include #include "rte_table.h" /** Stub table parameters: NONE */ /** Stub table operations */ extern struct rte_table_ops rte_table_stub_ops; #ifdef __cplusplus } #endif #endif ================================================ FILE: lib/librte_timer/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_timer.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 EXPORT_MAP := rte_timer_version.map LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_TIMER) := rte_timer.c # install this header file SYMLINK-$(CONFIG_RTE_LIBRTE_TIMER)-include := rte_timer.h # this lib needs eal DEPDIRS-$(CONFIG_RTE_LIBRTE_TIMER) += lib/librte_eal include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_timer/rte_timer.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_timer.h" LIST_HEAD(rte_timer_list, rte_timer); struct priv_timer { struct rte_timer pending_head; /**< dummy timer instance to head up list */ rte_spinlock_t list_lock; /**< lock to protect list access */ /** per-core variable that true if a timer was updated on this * core since last reset of the variable */ int updated; /** track the current depth of the skiplist */ unsigned curr_skiplist_depth; unsigned prev_lcore; /**< used for lcore round robin */ #ifdef RTE_LIBRTE_TIMER_DEBUG /** per-lcore statistics */ struct rte_timer_debug_stats stats; #endif } __rte_cache_aligned; /** per-lcore private info for timers */ static struct priv_timer priv_timer[RTE_MAX_LCORE]; /* when debug is enabled, store some statistics */ #ifdef RTE_LIBRTE_TIMER_DEBUG #define __TIMER_STAT_ADD(name, n) do { \ unsigned __lcore_id = rte_lcore_id(); \ if (__lcore_id < RTE_MAX_LCORE) \ priv_timer[__lcore_id].stats.name += (n); \ } while(0) #else #define __TIMER_STAT_ADD(name, n) do {} while(0) #endif /* Init the timer library. */ void rte_timer_subsystem_init(void) { unsigned lcore_id; /* since priv_timer is static, it's zeroed by default, so only init some * fields. */ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++) { rte_spinlock_init(&priv_timer[lcore_id].list_lock); priv_timer[lcore_id].prev_lcore = lcore_id; } } /* Initialize the timer handle tim for use */ void rte_timer_init(struct rte_timer *tim) { union rte_timer_status status; status.state = RTE_TIMER_STOP; status.owner = RTE_TIMER_NO_OWNER; tim->status.u32 = status.u32; } /* * if timer is pending or stopped (or running on the same core than * us), mark timer as configuring, and on success return the previous * status of the timer */ static int timer_set_config_state(struct rte_timer *tim, union rte_timer_status *ret_prev_status) { union rte_timer_status prev_status, status; int success = 0; unsigned lcore_id; lcore_id = rte_lcore_id(); /* wait that the timer is in correct status before update, * and mark it as being configured */ while (success == 0) { prev_status.u32 = tim->status.u32; /* timer is running on another core, exit */ if (prev_status.state == RTE_TIMER_RUNNING && prev_status.owner != (uint16_t)lcore_id) return -1; /* timer is being configured on another core */ if (prev_status.state == RTE_TIMER_CONFIG) return -1; /* here, we know that timer is stopped or pending, * mark it atomically as being configured */ status.state = RTE_TIMER_CONFIG; status.owner = (int16_t)lcore_id; success = rte_atomic32_cmpset(&tim->status.u32, prev_status.u32, status.u32); } ret_prev_status->u32 = prev_status.u32; return 0; } /* * if timer is pending, mark timer as running */ static int timer_set_running_state(struct rte_timer *tim) { union rte_timer_status prev_status, status; unsigned lcore_id = rte_lcore_id(); int success = 0; /* wait that the timer is in correct status before update, * and mark it as running */ while (success == 0) { prev_status.u32 = tim->status.u32; /* timer is not pending anymore */ if (prev_status.state != RTE_TIMER_PENDING) return -1; /* here, we know that timer is stopped or pending, * mark it atomically as beeing configured */ status.state = RTE_TIMER_RUNNING; status.owner = (int16_t)lcore_id; success = rte_atomic32_cmpset(&tim->status.u32, prev_status.u32, status.u32); } return 0; } /* * Return a skiplist level for a new entry. * This probabalistically gives a level with p=1/4 that an entry at level n * will also appear at level n+1. */ static uint32_t timer_get_skiplist_level(unsigned curr_depth) { #ifdef RTE_LIBRTE_TIMER_DEBUG static uint32_t i, count = 0; static uint32_t levels[MAX_SKIPLIST_DEPTH] = {0}; #endif /* probability value is 1/4, i.e. all at level 0, 1 in 4 is at level 1, * 1 in 16 at level 2, 1 in 64 at level 3, etc. Calculated using lowest * bit position of a (pseudo)random number. */ uint32_t rand = rte_rand() & (UINT32_MAX - 1); uint32_t level = rand == 0 ? MAX_SKIPLIST_DEPTH : (rte_bsf32(rand)-1) / 2; /* limit the levels used to one above our current level, so we don't, * for instance, have a level 0 and a level 7 without anything between */ if (level > curr_depth) level = curr_depth; if (level >= MAX_SKIPLIST_DEPTH) level = MAX_SKIPLIST_DEPTH-1; #ifdef RTE_LIBRTE_TIMER_DEBUG count ++; levels[level]++; if (count % 10000 == 0) for (i = 0; i < MAX_SKIPLIST_DEPTH; i++) printf("Level %u: %u\n", (unsigned)i, (unsigned)levels[i]); #endif return level; } /* * For a given time value, get the entries at each level which * are <= that time value. */ static void timer_get_prev_entries(uint64_t time_val, unsigned tim_lcore, struct rte_timer **prev) { unsigned lvl = priv_timer[tim_lcore].curr_skiplist_depth; prev[lvl] = &priv_timer[tim_lcore].pending_head; while(lvl != 0) { lvl--; prev[lvl] = prev[lvl+1]; while (prev[lvl]->sl_next[lvl] && prev[lvl]->sl_next[lvl]->expire <= time_val) prev[lvl] = prev[lvl]->sl_next[lvl]; } } /* * Given a timer node in the skiplist, find the previous entries for it at * all skiplist levels. */ static void timer_get_prev_entries_for_node(struct rte_timer *tim, unsigned tim_lcore, struct rte_timer **prev) { int i; /* to get a specific entry in the list, look for just lower than the time * values, and then increment on each level individually if necessary */ timer_get_prev_entries(tim->expire - 1, tim_lcore, prev); for (i = priv_timer[tim_lcore].curr_skiplist_depth - 1; i >= 0; i--) { while (prev[i]->sl_next[i] != NULL && prev[i]->sl_next[i] != tim && prev[i]->sl_next[i]->expire <= tim->expire) prev[i] = prev[i]->sl_next[i]; } } /* * add in list, lock if needed * timer must be in config state * timer must not be in a list */ static void timer_add(struct rte_timer *tim, unsigned tim_lcore, int local_is_locked) { unsigned lcore_id = rte_lcore_id(); unsigned lvl; struct rte_timer *prev[MAX_SKIPLIST_DEPTH+1]; /* if timer needs to be scheduled on another core, we need to * lock the list; if it is on local core, we need to lock if * we are not called from rte_timer_manage() */ if (tim_lcore != lcore_id || !local_is_locked) rte_spinlock_lock(&priv_timer[tim_lcore].list_lock); /* find where exactly this element goes in the list of elements * for each depth. */ timer_get_prev_entries(tim->expire, tim_lcore, prev); /* now assign it a new level and add at that level */ const unsigned tim_level = timer_get_skiplist_level( priv_timer[tim_lcore].curr_skiplist_depth); if (tim_level == priv_timer[tim_lcore].curr_skiplist_depth) priv_timer[tim_lcore].curr_skiplist_depth++; lvl = tim_level; while (lvl > 0) { tim->sl_next[lvl] = prev[lvl]->sl_next[lvl]; prev[lvl]->sl_next[lvl] = tim; lvl--; } tim->sl_next[0] = prev[0]->sl_next[0]; prev[0]->sl_next[0] = tim; /* save the lowest list entry into the expire field of the dummy hdr * NOTE: this is not atomic on 32-bit*/ priv_timer[tim_lcore].pending_head.expire = priv_timer[tim_lcore].\ pending_head.sl_next[0]->expire; if (tim_lcore != lcore_id || !local_is_locked) rte_spinlock_unlock(&priv_timer[tim_lcore].list_lock); } /* * del from list, lock if needed * timer must be in config state * timer must be in a list */ static void timer_del(struct rte_timer *tim, union rte_timer_status prev_status, int local_is_locked) { unsigned lcore_id = rte_lcore_id(); unsigned prev_owner = prev_status.owner; int i; struct rte_timer *prev[MAX_SKIPLIST_DEPTH+1]; /* if timer needs is pending another core, we need to lock the * list; if it is on local core, we need to lock if we are not * called from rte_timer_manage() */ if (prev_owner != lcore_id || !local_is_locked) rte_spinlock_lock(&priv_timer[prev_owner].list_lock); /* save the lowest list entry into the expire field of the dummy hdr. * NOTE: this is not atomic on 32-bit */ if (tim == priv_timer[prev_owner].pending_head.sl_next[0]) priv_timer[prev_owner].pending_head.expire = ((tim->sl_next[0] == NULL) ? 0 : tim->sl_next[0]->expire); /* adjust pointers from previous entries to point past this */ timer_get_prev_entries_for_node(tim, prev_owner, prev); for (i = priv_timer[prev_owner].curr_skiplist_depth - 1; i >= 0; i--) { if (prev[i]->sl_next[i] == tim) prev[i]->sl_next[i] = tim->sl_next[i]; } /* in case we deleted last entry at a level, adjust down max level */ for (i = priv_timer[prev_owner].curr_skiplist_depth - 1; i >= 0; i--) if (priv_timer[prev_owner].pending_head.sl_next[i] == NULL) priv_timer[prev_owner].curr_skiplist_depth --; else break; if (prev_owner != lcore_id || !local_is_locked) rte_spinlock_unlock(&priv_timer[prev_owner].list_lock); } /* Reset and start the timer associated with the timer handle (private func) */ static int __rte_timer_reset(struct rte_timer *tim, uint64_t expire, uint64_t period, unsigned tim_lcore, rte_timer_cb_t fct, void *arg, int local_is_locked) { union rte_timer_status prev_status, status; int ret; unsigned lcore_id = rte_lcore_id(); /* round robin for tim_lcore */ if (tim_lcore == (unsigned)LCORE_ID_ANY) { if (lcore_id < RTE_MAX_LCORE) { /* EAL thread with valid lcore_id */ tim_lcore = rte_get_next_lcore( priv_timer[lcore_id].prev_lcore, 0, 1); priv_timer[lcore_id].prev_lcore = tim_lcore; } else /* non-EAL thread do not run rte_timer_manage(), * so schedule the timer on the first enabled lcore. */ tim_lcore = rte_get_next_lcore(LCORE_ID_ANY, 0, 1); } /* wait that the timer is in correct status before update, * and mark it as being configured */ ret = timer_set_config_state(tim, &prev_status); if (ret < 0) return -1; __TIMER_STAT_ADD(reset, 1); if (prev_status.state == RTE_TIMER_RUNNING && lcore_id < RTE_MAX_LCORE) { priv_timer[lcore_id].updated = 1; } /* remove it from list */ if (prev_status.state == RTE_TIMER_PENDING) { timer_del(tim, prev_status, local_is_locked); __TIMER_STAT_ADD(pending, -1); } tim->period = period; tim->expire = expire; tim->f = fct; tim->arg = arg; __TIMER_STAT_ADD(pending, 1); timer_add(tim, tim_lcore, local_is_locked); /* update state: as we are in CONFIG state, only us can modify * the state so we don't need to use cmpset() here */ rte_wmb(); status.state = RTE_TIMER_PENDING; status.owner = (int16_t)tim_lcore; tim->status.u32 = status.u32; return 0; } /* Reset and start the timer associated with the timer handle tim */ int rte_timer_reset(struct rte_timer *tim, uint64_t ticks, enum rte_timer_type type, unsigned tim_lcore, rte_timer_cb_t fct, void *arg) { uint64_t cur_time = rte_get_timer_cycles(); uint64_t period; if (unlikely((tim_lcore != (unsigned)LCORE_ID_ANY) && !rte_lcore_is_enabled(tim_lcore))) return -1; if (type == PERIODICAL) period = ticks; else period = 0; return __rte_timer_reset(tim, cur_time + ticks, period, tim_lcore, fct, arg, 0); } /* loop until rte_timer_reset() succeed */ void rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks, enum rte_timer_type type, unsigned tim_lcore, rte_timer_cb_t fct, void *arg) { while (rte_timer_reset(tim, ticks, type, tim_lcore, fct, arg) != 0) rte_pause(); } /* Stop the timer associated with the timer handle tim */ int rte_timer_stop(struct rte_timer *tim) { union rte_timer_status prev_status, status; unsigned lcore_id = rte_lcore_id(); int ret; /* wait that the timer is in correct status before update, * and mark it as being configured */ ret = timer_set_config_state(tim, &prev_status); if (ret < 0) return -1; __TIMER_STAT_ADD(stop, 1); if (prev_status.state == RTE_TIMER_RUNNING && lcore_id < RTE_MAX_LCORE) { priv_timer[lcore_id].updated = 1; } /* remove it from list */ if (prev_status.state == RTE_TIMER_PENDING) { timer_del(tim, prev_status, 0); __TIMER_STAT_ADD(pending, -1); } /* mark timer as stopped */ rte_wmb(); status.state = RTE_TIMER_STOP; status.owner = RTE_TIMER_NO_OWNER; tim->status.u32 = status.u32; return 0; } /* loop until rte_timer_stop() succeed */ void rte_timer_stop_sync(struct rte_timer *tim) { while (rte_timer_stop(tim) != 0) rte_pause(); } /* Test the PENDING status of the timer handle tim */ int rte_timer_pending(struct rte_timer *tim) { return tim->status.state == RTE_TIMER_PENDING; } /* must be called periodically, run all timer that expired */ void rte_timer_manage(void) { union rte_timer_status status; struct rte_timer *tim, *next_tim; struct rte_timer *run_first_tim, **pprev; unsigned lcore_id = rte_lcore_id(); struct rte_timer *prev[MAX_SKIPLIST_DEPTH + 1]; uint64_t cur_time; int i, ret; /* timer manager only runs on EAL thread with valid lcore_id */ assert(lcore_id < RTE_MAX_LCORE); __TIMER_STAT_ADD(manage, 1); /* optimize for the case where per-cpu list is empty */ if (priv_timer[lcore_id].pending_head.sl_next[0] == NULL) return; cur_time = rte_get_timer_cycles(); #ifdef RTE_ARCH_X86_64 /* on 64-bit the value cached in the pending_head.expired will be * updated atomically, so we can consult that for a quick check here * outside the lock */ if (likely(priv_timer[lcore_id].pending_head.expire > cur_time)) return; #endif /* browse ordered list, add expired timers in 'expired' list */ rte_spinlock_lock(&priv_timer[lcore_id].list_lock); /* if nothing to do just unlock and return */ if (priv_timer[lcore_id].pending_head.sl_next[0] == NULL || priv_timer[lcore_id].pending_head.sl_next[0]->expire > cur_time) { rte_spinlock_unlock(&priv_timer[lcore_id].list_lock); return; } /* save start of list of expired timers */ tim = priv_timer[lcore_id].pending_head.sl_next[0]; /* break the existing list at current time point */ timer_get_prev_entries(cur_time, lcore_id, prev); for (i = priv_timer[lcore_id].curr_skiplist_depth -1; i >= 0; i--) { priv_timer[lcore_id].pending_head.sl_next[i] = prev[i]->sl_next[i]; if (prev[i]->sl_next[i] == NULL) priv_timer[lcore_id].curr_skiplist_depth--; prev[i] ->sl_next[i] = NULL; } /* transition run-list from PENDING to RUNNING */ run_first_tim = tim; pprev = &run_first_tim; for ( ; tim != NULL; tim = next_tim) { next_tim = tim->sl_next[0]; ret = timer_set_running_state(tim); if (likely(ret == 0)) { pprev = &tim->sl_next[0]; } else { /* another core is trying to re-config this one, * remove it from local expired list and put it * back on the priv_timer[] skip list */ *pprev = next_tim; timer_add(tim, lcore_id, 1); } } /* update the next to expire timer value */ priv_timer[lcore_id].pending_head.expire = (priv_timer[lcore_id].pending_head.sl_next[0] == NULL) ? 0 : priv_timer[lcore_id].pending_head.sl_next[0]->expire; rte_spinlock_unlock(&priv_timer[lcore_id].list_lock); /* now scan expired list and call callbacks */ for (tim = run_first_tim; tim != NULL; tim = next_tim) { next_tim = tim->sl_next[0]; priv_timer[lcore_id].updated = 0; /* execute callback function with list unlocked */ tim->f(tim, tim->arg); __TIMER_STAT_ADD(pending, -1); /* the timer was stopped or reloaded by the callback * function, we have nothing to do here */ if (priv_timer[lcore_id].updated == 1) continue; if (tim->period == 0) { /* remove from done list and mark timer as stopped */ status.state = RTE_TIMER_STOP; status.owner = RTE_TIMER_NO_OWNER; rte_wmb(); tim->status.u32 = status.u32; } else { /* keep it in list and mark timer as pending */ rte_spinlock_lock(&priv_timer[lcore_id].list_lock); status.state = RTE_TIMER_PENDING; __TIMER_STAT_ADD(pending, 1); status.owner = (int16_t)lcore_id; rte_wmb(); tim->status.u32 = status.u32; __rte_timer_reset(tim, cur_time + tim->period, tim->period, lcore_id, tim->f, tim->arg, 1); rte_spinlock_unlock(&priv_timer[lcore_id].list_lock); } } } /* dump statistics about timers */ void rte_timer_dump_stats(FILE *f) { #ifdef RTE_LIBRTE_TIMER_DEBUG struct rte_timer_debug_stats sum; unsigned lcore_id; memset(&sum, 0, sizeof(sum)); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { sum.reset += priv_timer[lcore_id].stats.reset; sum.stop += priv_timer[lcore_id].stats.stop; sum.manage += priv_timer[lcore_id].stats.manage; sum.pending += priv_timer[lcore_id].stats.pending; } fprintf(f, "Timer statistics:\n"); fprintf(f, " reset = %"PRIu64"\n", sum.reset); fprintf(f, " stop = %"PRIu64"\n", sum.stop); fprintf(f, " manage = %"PRIu64"\n", sum.manage); fprintf(f, " pending = %"PRIu64"\n", sum.pending); #else fprintf(f, "No timer statistics, RTE_LIBRTE_TIMER_DEBUG is disabled\n"); #endif } ================================================ FILE: lib/librte_timer/rte_timer.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTE_TIMER_H_ #define _RTE_TIMER_H_ /** * @file RTE Timer * * This library provides a timer service to RTE Data Plane execution * units that allows the execution of callback functions asynchronously. * * - Timers can be periodic or single (one-shot). * - The timers can be loaded from one core and executed on another. This has * to be specified in the call to rte_timer_reset(). * - High precision is possible. NOTE: this depends on the call frequency to * rte_timer_manage() that check the timer expiration for the local core. * - If not used in an application, for improved performance, it can be * disabled at compilation time by not calling the rte_timer_manage() * to improve performance. * * The timer library uses the rte_get_hpet_cycles() function that * uses the HPET, when available, to provide a reliable time reference. [HPET * routines are provided by EAL, which falls back to using the chip TSC (time- * stamp counter) as fallback when HPET is not available] * * This library provides an interface to add, delete and restart a * timer. The API is based on the BSD callout(9) API with a few * differences. * * See the RTE architecture documentation for more information about the * design of this library. */ #include #include #include #ifdef __cplusplus extern "C" { #endif #define RTE_TIMER_STOP 0 /**< State: timer is stopped. */ #define RTE_TIMER_PENDING 1 /**< State: timer is scheduled. */ #define RTE_TIMER_RUNNING 2 /**< State: timer function is running. */ #define RTE_TIMER_CONFIG 3 /**< State: timer is being configured. */ #define RTE_TIMER_NO_OWNER -2 /**< Timer has no owner. */ /** * Timer type: Periodic or single (one-shot). */ enum rte_timer_type { SINGLE, PERIODICAL }; /** * Timer status: A union of the state (stopped, pending, running, * config) and an owner (the id of the lcore that owns the timer). */ union rte_timer_status { struct { uint16_t state; /**< Stop, pending, running, config. */ int16_t owner; /**< The lcore that owns the timer. */ }; uint32_t u32; /**< To atomic-set status + owner. */ }; #ifdef RTE_LIBRTE_TIMER_DEBUG /** * A structure that stores the timer statistics (per-lcore). */ struct rte_timer_debug_stats { uint64_t reset; /**< Number of success calls to rte_timer_reset(). */ uint64_t stop; /**< Number of success calls to rte_timer_stop(). */ uint64_t manage; /**< Number of calls to rte_timer_manage(). */ uint64_t pending; /**< Number of pending/running timers. */ }; #endif struct rte_timer; /** * Callback function type for timer expiry. */ typedef void (*rte_timer_cb_t)(struct rte_timer *, void *); #define MAX_SKIPLIST_DEPTH 10 /** * A structure describing a timer in RTE. */ struct rte_timer { uint64_t expire; /**< Time when timer expire. */ struct rte_timer *sl_next[MAX_SKIPLIST_DEPTH]; volatile union rte_timer_status status; /**< Status of timer. */ uint64_t period; /**< Period of timer (0 if not periodic). */ rte_timer_cb_t f; /**< Callback function. */ void *arg; /**< Argument to callback function. */ }; #ifdef __cplusplus /** * A C++ static initializer for a timer structure. */ #define RTE_TIMER_INITIALIZER { \ 0, \ {NULL}, \ {{RTE_TIMER_STOP, RTE_TIMER_NO_OWNER}}, \ 0, \ NULL, \ NULL, \ } #else /** * A static initializer for a timer structure. */ #define RTE_TIMER_INITIALIZER { \ .status = {{ \ .state = RTE_TIMER_STOP, \ .owner = RTE_TIMER_NO_OWNER, \ }}, \ } #endif /** * Initialize the timer library. * * Initializes internal variables (list, locks and so on) for the RTE * timer library. */ void rte_timer_subsystem_init(void); /** * Initialize a timer handle. * * The rte_timer_init() function initializes the timer handle *tim* * for use. No operations can be performed on a timer before it is * initialized. * * @param tim * The timer to initialize. */ void rte_timer_init(struct rte_timer *tim); /** * Reset and start the timer associated with the timer handle. * * The rte_timer_reset() function resets and starts the timer * associated with the timer handle *tim*. When the timer expires after * *ticks* HPET cycles, the function specified by *fct* will be called * with the argument *arg* on core *tim_lcore*. * * If the timer associated with the timer handle is already running * (in the RUNNING state), the function will fail. The user has to check * the return value of the function to see if there is a chance that the * timer is in the RUNNING state. * * If the timer is being configured on another core (the CONFIG state), * it will also fail. * * If the timer is pending or stopped, it will be rescheduled with the * new parameters. * * @param tim * The timer handle. * @param ticks * The number of cycles (see rte_get_hpet_hz()) before the callback * function is called. * @param type * The type can be either: * - PERIODICAL: The timer is automatically reloaded after execution * (returns to the PENDING state) * - SINGLE: The timer is one-shot, that is, the timer goes to a * STOPPED state after execution. * @param tim_lcore * The ID of the lcore where the timer callback function has to be * executed. If tim_lcore is LCORE_ID_ANY, the timer library will * launch it on a different core for each call (round-robin). * @param fct * The callback function of the timer. * @param arg * The user argument of the callback function. * @return * - 0: Success; the timer is scheduled. * - (-1): Timer is in the RUNNING or CONFIG state. */ int rte_timer_reset(struct rte_timer *tim, uint64_t ticks, enum rte_timer_type type, unsigned tim_lcore, rte_timer_cb_t fct, void *arg); /** * Loop until rte_timer_reset() succeeds. * * Reset and start the timer associated with the timer handle. Always * succeed. See rte_timer_reset() for details. * * @param tim * The timer handle. * @param ticks * The number of cycles (see rte_get_hpet_hz()) before the callback * function is called. * @param type * The type can be either: * - PERIODICAL: The timer is automatically reloaded after execution * (returns to the PENDING state) * - SINGLE: The timer is one-shot, that is, the timer goes to a * STOPPED state after execution. * @param tim_lcore * The ID of the lcore where the timer callback function has to be * executed. If tim_lcore is LCORE_ID_ANY, the timer library will * launch it on a different core for each call (round-robin). * @param fct * The callback function of the timer. * @param arg * The user argument of the callback function. */ void rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks, enum rte_timer_type type, unsigned tim_lcore, rte_timer_cb_t fct, void *arg); /** * Stop a timer. * * The rte_timer_stop() function stops the timer associated with the * timer handle *tim*. It may fail if the timer is currently running or * being configured. * * If the timer is pending or stopped (for instance, already expired), * the function will succeed. The timer handle tim must have been * initialized using rte_timer_init(), otherwise, undefined behavior * will occur. * * This function can be called safely from a timer callback. If it * succeeds, the timer is not referenced anymore by the timer library * and the timer structure can be freed (even in the callback * function). * * @param tim * The timer handle. * @return * - 0: Success; the timer is stopped. * - (-1): The timer is in the RUNNING or CONFIG state. */ int rte_timer_stop(struct rte_timer *tim); /** * Loop until rte_timer_stop() succeeds. * * After a call to this function, the timer identified by *tim* is * stopped. See rte_timer_stop() for details. * * @param tim * The timer handle. */ void rte_timer_stop_sync(struct rte_timer *tim); /** * Test if a timer is pending. * * The rte_timer_pending() function tests the PENDING status * of the timer handle *tim*. A PENDING timer is one that has been * scheduled and whose function has not yet been called. * * @param tim * The timer handle. * @return * - 0: The timer is not pending. * - 1: The timer is pending. */ int rte_timer_pending(struct rte_timer *tim); /** * Manage the timer list and execute callback functions. * * This function must be called periodically from EAL lcores * main_loop(). It browses the list of pending timers and runs all * timers that are expired. * * The precision of the timer depends on the call frequency of this * function. However, the more often the function is called, the more * CPU resources it will use. */ void rte_timer_manage(void); /** * Dump statistics about timers. * * @param f * A pointer to a file for output */ void rte_timer_dump_stats(FILE *f); #ifdef __cplusplus } #endif #endif /* _RTE_TIMER_H_ */ ================================================ FILE: lib/librte_vhost/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/rte.vars.mk # library name LIB = librte_vhost.a EXPORT_MAP := rte_vhost_version.map LIBABIVER := 1 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64 ifeq ($(CONFIG_RTE_LIBRTE_VHOST_USER),y) CFLAGS += -I vhost_user else CFLAGS += -I vhost_cuse -lfuse LDFLAGS += -lfuse endif ifeq ($(CONFIG_RTE_LIBRTE_VHOST_NUMA),y) LDFLAGS += -lnuma endif # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := virtio-net.c vhost_rxtx.c ifeq ($(CONFIG_RTE_LIBRTE_VHOST_USER),y) SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_user/vhost-net-user.c vhost_user/virtio-net-user.c vhost_user/fd_man.c else SRCS-$(CONFIG_RTE_LIBRTE_VHOST) += vhost_cuse/vhost-net-cdev.c vhost_cuse/virtio-net-cdev.c vhost_cuse/eventfd_copy.c endif # install includes SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h # dependencies DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_eal DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_ether DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_mbuf include $(RTE_SDK)/mk/rte.lib.mk ================================================ FILE: lib/librte_vhost/eventfd_link/Makefile ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. obj-m += eventfd_link.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ================================================ FILE: lib/librte_vhost/eventfd_link/eventfd_link.c ================================================ /*- * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation */ #include #include #include #include #include #include #include #include #include #include #include #include #include "eventfd_link.h" /* * get_files_struct is copied from fs/file.c */ struct files_struct * get_files_struct(struct task_struct *task) { struct files_struct *files; task_lock(task); files = task->files; if (files) atomic_inc(&files->count); task_unlock(task); return files; } /* * put_files_struct is extracted from fs/file.c */ void put_files_struct(struct files_struct *files) { if (atomic_dec_and_test(&files->count)) BUG(); } static long eventfd_link_ioctl(struct file *f, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *) arg; struct task_struct *task_target = NULL; struct file *file; struct files_struct *files; struct fdtable *fdt; struct eventfd_copy eventfd_copy; switch (ioctl) { case EVENTFD_COPY: if (copy_from_user(&eventfd_copy, argp, sizeof(struct eventfd_copy))) return -EFAULT; /* * Find the task struct for the target pid */ task_target = pid_task(find_vpid(eventfd_copy.target_pid), PIDTYPE_PID); if (task_target == NULL) { pr_debug("Failed to get mem ctx for target pid\n"); return -EFAULT; } files = get_files_struct(current); if (files == NULL) { pr_debug("Failed to get files struct\n"); return -EFAULT; } rcu_read_lock(); file = fcheck_files(files, eventfd_copy.source_fd); if (file) { if (file->f_mode & FMODE_PATH || !atomic_long_inc_not_zero(&file->f_count)) file = NULL; } rcu_read_unlock(); put_files_struct(files); if (file == NULL) { pr_debug("Failed to get file from source pid\n"); return 0; } /* * Release the existing eventfd in the source process */ spin_lock(&files->file_lock); fput(file); filp_close(file, files); fdt = files_fdtable(files); fdt->fd[eventfd_copy.source_fd] = NULL; spin_unlock(&files->file_lock); /* * Find the file struct associated with the target fd. */ files = get_files_struct(task_target); if (files == NULL) { pr_debug("Failed to get files struct\n"); return -EFAULT; } rcu_read_lock(); file = fcheck_files(files, eventfd_copy.target_fd); if (file) { if (file->f_mode & FMODE_PATH || !atomic_long_inc_not_zero(&file->f_count)) file = NULL; } rcu_read_unlock(); put_files_struct(files); if (file == NULL) { pr_debug("Failed to get file from target pid\n"); return 0; } /* * Install the file struct from the target process into the * file desciptor of the source process, */ fd_install(eventfd_copy.source_fd, file); return 0; default: return -ENOIOCTLCMD; } } static const struct file_operations eventfd_link_fops = { .owner = THIS_MODULE, .unlocked_ioctl = eventfd_link_ioctl, }; static struct miscdevice eventfd_link_misc = { .name = "eventfd-link", .fops = &eventfd_link_fops, }; static int __init eventfd_link_init(void) { return misc_register(&eventfd_link_misc); } module_init(eventfd_link_init); static void __exit eventfd_link_exit(void) { misc_deregister(&eventfd_link_misc); } module_exit(eventfd_link_exit); MODULE_VERSION("0.0.1"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Anthony Fee"); MODULE_DESCRIPTION("Link eventfd"); MODULE_ALIAS("devname:eventfd-link"); ================================================ FILE: lib/librte_vhost/eventfd_link/eventfd_link.h ================================================ /*- * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef _EVENTFD_LINK_H_ #define _EVENTFD_LINK_H_ /* * ioctl to copy an fd entry in calling process to an fd in a target process */ #define EVENTFD_COPY 1 /* * arguements for the EVENTFD_COPY ioctl */ struct eventfd_copy { unsigned target_fd; /* fd in the target pid */ unsigned source_fd; /* fd in the calling pid */ pid_t target_pid; /* pid of the target pid */ }; #endif /* _EVENTFD_LINK_H_ */ ================================================ FILE: lib/librte_vhost/libvirt/qemu-wrap.py ================================================ #!/usr/bin/python #/* # * BSD LICENSE # * # * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # * All rights reserved. # * # * Redistribution and use in source and binary forms, with or without # * modification, are permitted provided that the following conditions # * are met: # * # * * Redistributions of source code must retain the above copyright # * notice, this list of conditions and the following disclaimer. # * * Redistributions in binary form must reproduce the above copyright # * notice, this list of conditions and the following disclaimer in # * the documentation and/or other materials provided with the # * distribution. # * * Neither the name of Intel Corporation nor the names of its # * contributors may be used to endorse or promote products derived # * from this software without specific prior written permission. # * # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # */ ##################################################################### # This script is designed to modify the call to the QEMU emulator # to support userspace vhost when starting a guest machine through # libvirt with vhost enabled. The steps to enable this are as follows # and should be run as root: # # 1. Place this script in a libvirtd's binary search PATH ($PATH) # A good location would be in the same directory that the QEMU # binary is located # # 2. Ensure that the script has the same owner/group and file # permissions as the QEMU binary # # 3. Update the VM xml file using "virsh edit VM.xml" # # 3.a) Set the VM to use the launch script # # Set the emulator path contained in the # tags # # e.g replace /usr/bin/qemu-kvm # with /usr/bin/qemu-wrap.py # # 3.b) Set the VM's device's to use vhost-net offload # # # # # # # 4. Enable libvirt to access our userpace device file by adding it to # controllers cgroup for libvirtd using the following steps # # 4.a) In /etc/libvirt/qemu.conf add/edit the following lines: # 1) cgroup_controllers = [ ... "devices", ... ] # 2) clear_emulator_capabilities = 0 # 3) user = "root" # 4) group = "root" # 5) cgroup_device_acl = [ # "/dev/null", "/dev/full", "/dev/zero", # "/dev/random", "/dev/urandom", # "/dev/ptmx", "/dev/kvm", "/dev/kqemu", # "/dev/rtc", "/dev/hpet", "/dev/net/tun", # "/dev/-", # ] # # 4.b) Disable SELinux or set to permissive mode # # 4.c) Mount cgroup device controller # "mkdir /dev/cgroup" # "mount -t cgroup none /dev/cgroup -o devices" # # 4.d) Set hugetlbfs_mount variable - ( Optional ) # VMs using userspace vhost must use hugepage backed # memory. This can be enabled in the libvirt XML # config by adding a memory backing section to the # XML config e.g. # # # # This memory backing section should be added after the # and sections. This will add # flags "-mem-prealloc -mem-path " to the QEMU # command line. The hugetlbfs_mount variable can be used # to override the default passed through by libvirt. # # if "-mem-prealloc" or "-mem-path " are not passed # through and a vhost device is detected then these options will # be automatically added by this script. This script will detect # the system hugetlbfs mount point to be used for . The # default for this script can be overidden by the # hugetlbfs_dir variable in the configuration section of this script. # # # 4.e) Restart the libvirtd system process # e.g. on Fedora "systemctl restart libvirtd.service" # # # 4.f) Edit the Configuration Parameters section of this script # to point to the correct emulator location and set any # addition options # # The script modifies the libvirtd Qemu call by modifying/adding # options based on the configuration parameters below. # NOTE: # emul_path and us_vhost_path must be set # All other parameters are optional ##################################################################### ############################################# # Configuration Parameters ############################################# #Path to QEMU binary emul_path = "/usr/local/bin/qemu-system-x86_64" #Path to userspace vhost device file # This filename should match the --dev-basename --dev-index parameters of # the command used to launch the userspace vhost sample application e.g. # if the sample app lauch command is: # ./build/vhost-switch ..... --dev-basename usvhost --dev-index 1 # then this variable should be set to: # us_vhost_path = "/dev/usvhost-1" us_vhost_path = "/dev/usvhost-1" #List of additional user defined emulation options. These options will #be added to all Qemu calls emul_opts_user = [] #List of additional user defined emulation options for vhost only. #These options will only be added to vhost enabled guests emul_opts_user_vhost = [] #For all VHOST enabled VMs, the VM memory is preallocated from hugetlbfs # Set this variable to one to enable this option for all VMs use_huge_all = 0 #Instead of autodetecting, override the hugetlbfs directory by setting #this variable hugetlbfs_dir = "" ############################################# ############################################# # ****** Do Not Modify Below this Line ****** ############################################# import sys, os, subprocess #List of open userspace vhost file descriptors fd_list = [] #additional virtio device flags when using userspace vhost vhost_flags = [ "csum=off", "gso=off", "guest_tso4=off", "guest_tso6=off", "guest_ecn=off" ] ############################################# # Find the system hugefile mount point. # Note: # if multiple hugetlbfs mount points exist # then the first one found will be used ############################################# def find_huge_mount(): if (len(hugetlbfs_dir)): return hugetlbfs_dir huge_mount = "" if (os.access("/proc/mounts", os.F_OK)): f = open("/proc/mounts", "r") line = f.readline() while line: line_split = line.split(" ") if line_split[2] == 'hugetlbfs': huge_mount = line_split[1] break line = f.readline() else: print "/proc/mounts not found" exit (1) f.close if len(huge_mount) == 0: print "Failed to find hugetlbfs mount point" exit (1) return huge_mount ############################################# # Get a userspace Vhost file descriptor ############################################# def get_vhost_fd(): if (os.access(us_vhost_path, os.F_OK)): fd = os.open( us_vhost_path, os.O_RDWR) else: print ("US-Vhost file %s not found" %us_vhost_path) exit (1) return fd ############################################# # Check for vhostfd. if found then replace # with our own vhost fd and append any vhost # flags onto the end ############################################# def modify_netdev_arg(arg): global fd_list vhost_in_use = 0 s = '' new_opts = [] netdev_opts = arg.split(",") for opt in netdev_opts: #check if vhost is used if "vhost" == opt[:5]: vhost_in_use = 1 else: new_opts.append(opt) #if using vhost append vhost options if vhost_in_use == 1: #append vhost on option new_opts.append('vhost=on') #append vhostfd ption new_fd = get_vhost_fd() new_opts.append('vhostfd=' + str(new_fd)) fd_list.append(new_fd) #concatenate all options for opt in new_opts: if len(s) > 0: s+=',' s+=opt return s ############################################# # Main ############################################# def main(): global fd_list global vhost_in_use new_args = [] num_cmd_args = len(sys.argv) emul_call = '' mem_prealloc_set = 0 mem_path_set = 0 num = 0; #parse the parameters while (num < num_cmd_args): arg = sys.argv[num] #Check netdev +1 parameter for vhostfd if arg == '-netdev': num_vhost_devs = len(fd_list) new_args.append(arg) num+=1 arg = sys.argv[num] mod_arg = modify_netdev_arg(arg) new_args.append(mod_arg) #append vhost flags if this is a vhost device # and -device is the next arg # i.e -device -opt1,-opt2,...,-opt3,%vhost if (num_vhost_devs < len(fd_list)): num+=1 arg = sys.argv[num] if arg == '-device': new_args.append(arg) num+=1 new_arg = sys.argv[num] for flag in vhost_flags: new_arg = ''.join([new_arg,',',flag]) new_args.append(new_arg) else: new_args.append(arg) elif arg == '-mem-prealloc': mem_prealloc_set = 1 new_args.append(arg) elif arg == '-mem-path': mem_path_set = 1 new_args.append(arg) else: new_args.append(arg) num+=1 #Set Qemu binary location emul_call+=emul_path emul_call+=" " #Add prealloc mem options if using vhost and not already added if ((len(fd_list) > 0) and (mem_prealloc_set == 0)): emul_call += "-mem-prealloc " #Add mempath mem options if using vhost and not already added if ((len(fd_list) > 0) and (mem_path_set == 0)): #Detect and add hugetlbfs mount point mp = find_huge_mount() mp = "".join(["-mem-path ", mp]) emul_call += mp emul_call += " " #add user options for opt in emul_opts_user: emul_call += opt emul_call += " " #Add add user vhost only options if len(fd_list) > 0: for opt in emul_opts_user_vhost: emul_call += opt emul_call += " " #Add updated libvirt options iter_args = iter(new_args) #skip 1st arg i.e. call to this script next(iter_args) for arg in iter_args: emul_call+=str(arg) emul_call+= " " #Call QEMU subprocess.call(emul_call, shell=True) #Close usvhost files for fd in fd_list: os.close(fd) if __name__ == "__main__": main() ================================================ FILE: lib/librte_vhost/rte_virtio_net.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_NET_H_ #define _VIRTIO_NET_H_ /** * @file * Interface to vhost net */ #include #include #include #include #include #include #include #include struct rte_mbuf; #define VHOST_MEMORY_MAX_NREGIONS 8 /* Used to indicate that the device is running on a data core */ #define VIRTIO_DEV_RUNNING 1 /* Backend value set by guest. */ #define VIRTIO_DEV_STOPPED -1 /* Enum for virtqueue management. */ enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM}; #define BUF_VECTOR_MAX 256 /** * Structure contains buffer address, length and descriptor index * from vring to do scatter RX. */ struct buf_vector { uint64_t buf_addr; uint32_t buf_len; uint32_t desc_idx; }; /** * Structure contains variables relevant to RX/TX virtqueues. */ struct vhost_virtqueue { struct vring_desc *desc; /**< Virtqueue descriptor ring. */ struct vring_avail *avail; /**< Virtqueue available ring. */ struct vring_used *used; /**< Virtqueue used ring. */ uint32_t size; /**< Size of descriptor ring. */ uint32_t backend; /**< Backend value to determine if device should started/stopped. */ uint16_t vhost_hlen; /**< Vhost header length (varies depending on RX merge buffers. */ volatile uint16_t last_used_idx; /**< Last index used on the available ring */ volatile uint16_t last_used_idx_res; /**< Used for multiple devices reserving buffers. */ eventfd_t callfd; /**< Used to notify the guest (trigger interrupt). */ eventfd_t kickfd; /**< Currently unused as polling mode is enabled. */ struct buf_vector buf_vec[BUF_VECTOR_MAX]; /**< for scatter RX. */ } __rte_cache_aligned; /** * Device structure contains all configuration information relating to the device. */ struct virtio_net { struct vhost_virtqueue *virtqueue[VIRTIO_QNUM]; /**< Contains all virtqueue information. */ struct virtio_memory *mem; /**< QEMU memory and memory region information. */ uint64_t features; /**< Negotiated feature set. */ uint64_t device_fh; /**< device identifier. */ uint32_t flags; /**< Device flags. Only used to check if device is running on data core. */ #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ) char ifname[IF_NAME_SZ]; /**< Name of the tap device or socket path. */ void *priv; /**< private context */ } __rte_cache_aligned; /** * Information relating to memory regions including offsets to addresses in QEMUs memory file. */ struct virtio_memory_regions { uint64_t guest_phys_address; /**< Base guest physical address of region. */ uint64_t guest_phys_address_end; /**< End guest physical address of region. */ uint64_t memory_size; /**< Size of region. */ uint64_t userspace_address; /**< Base userspace address of region. */ uint64_t address_offset; /**< Offset of region for address translation. */ }; /** * Memory structure includes region and mapping information. */ struct virtio_memory { uint64_t base_address; /**< Base QEMU userspace address of the memory file. */ uint64_t mapped_address; /**< Mapped address of memory file base in our applications memory space. */ uint64_t mapped_size; /**< Total size of memory file. */ uint32_t nregions; /**< Number of memory regions. */ struct virtio_memory_regions regions[0]; /**< Memory region information. */ }; /** * Device operations to add/remove device. * * Make sure to set VIRTIO_DEV_RUNNING to the device flags in new_device and * remove it in destroy_device. * */ struct virtio_net_device_ops { int (*new_device)(struct virtio_net *); /**< Add device. */ void (*destroy_device)(volatile struct virtio_net *); /**< Remove device. */ }; static inline uint16_t __attribute__((always_inline)) rte_vring_available_entries(struct virtio_net *dev, uint16_t queue_id) { struct vhost_virtqueue *vq = dev->virtqueue[queue_id]; return *(volatile uint16_t *)&vq->avail->idx - vq->last_used_idx_res; } /** * Function to convert guest physical addresses to vhost virtual addresses. * This is used to convert guest virtio buffer addresses. */ static inline uint64_t __attribute__((always_inline)) gpa_to_vva(struct virtio_net *dev, uint64_t guest_pa) { struct virtio_memory_regions *region; uint32_t regionidx; uint64_t vhost_va = 0; for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) { region = &dev->mem->regions[regionidx]; if ((guest_pa >= region->guest_phys_address) && (guest_pa <= region->guest_phys_address_end)) { vhost_va = region->address_offset + guest_pa; break; } } return vhost_va; } /** * Disable features in feature_mask. Returns 0 on success. */ int rte_vhost_feature_disable(uint64_t feature_mask); /** * Enable features in feature_mask. Returns 0 on success. */ int rte_vhost_feature_enable(uint64_t feature_mask); /* Returns currently supported vhost features */ uint64_t rte_vhost_feature_get(void); int rte_vhost_enable_guest_notification(struct virtio_net *dev, uint16_t queue_id, int enable); /* Register vhost driver. dev_name could be different for multiple instance support. */ int rte_vhost_driver_register(const char *dev_name); /* Unregister vhost driver. This is only meaningful to vhost user. */ int rte_vhost_driver_unregister(const char *dev_name); /* Register callbacks. */ int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const); /* Start vhost driver session blocking loop. */ int rte_vhost_driver_session_start(void); /** * This function adds buffers to the virtio devices RX virtqueue. Buffers can * be received from the physical port or from another virtual device. A packet * count is returned to indicate the number of packets that were succesfully * added to the RX queue. * @param dev * virtio-net device * @param queue_id * virtio queue index in mq case * @param pkts * array to contain packets to be enqueued * @param count * packets num to be enqueued * @return * num of packets enqueued */ uint16_t rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id, struct rte_mbuf **pkts, uint16_t count); /** * This function gets guest buffers from the virtio device TX virtqueue, * construct host mbufs, copies guest buffer content to host mbufs and * store them in pkts to be processed. * @param dev * virtio-net device * @param queue_id * virtio queue index in mq case * @param mbuf_pool * mbuf_pool where host mbuf is allocated. * @param pkts * array to contain packets to be dequeued * @param count * packets num to be dequeued * @return * num of packets dequeued */ uint16_t rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id, struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count); #endif /* _VIRTIO_NET_H_ */ ================================================ FILE: lib/librte_vhost/vhost-net.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VHOST_NET_CDEV_H_ #define _VHOST_NET_CDEV_H_ #include #include #include #include #include #include #include "rte_virtio_net.h" extern struct vhost_net_device_ops const *ops; /* Macros for printing using RTE_LOG */ #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1 #define RTE_LOGTYPE_VHOST_DATA RTE_LOGTYPE_USER1 #ifdef RTE_LIBRTE_VHOST_DEBUG #define VHOST_MAX_PRINT_BUFF 6072 #define LOG_LEVEL RTE_LOG_DEBUG #define LOG_DEBUG(log_type, fmt, args...) RTE_LOG(DEBUG, log_type, fmt, ##args) #define PRINT_PACKET(device, addr, size, header) do { \ char *pkt_addr = (char *)(addr); \ unsigned int index; \ char packet[VHOST_MAX_PRINT_BUFF]; \ \ if ((header)) \ snprintf(packet, VHOST_MAX_PRINT_BUFF, "(%" PRIu64 ") Header size %d: ", (device->device_fh), (size)); \ else \ snprintf(packet, VHOST_MAX_PRINT_BUFF, "(%" PRIu64 ") Packet size %d: ", (device->device_fh), (size)); \ for (index = 0; index < (size); index++) { \ snprintf(packet + strnlen(packet, VHOST_MAX_PRINT_BUFF), VHOST_MAX_PRINT_BUFF - strnlen(packet, VHOST_MAX_PRINT_BUFF), \ "%02hhx ", pkt_addr[index]); \ } \ snprintf(packet + strnlen(packet, VHOST_MAX_PRINT_BUFF), VHOST_MAX_PRINT_BUFF - strnlen(packet, VHOST_MAX_PRINT_BUFF), "\n"); \ \ LOG_DEBUG(VHOST_DATA, "%s", packet); \ } while (0) #else #define LOG_LEVEL RTE_LOG_INFO #define LOG_DEBUG(log_type, fmt, args...) do {} while (0) #define PRINT_PACKET(device, addr, size, header) do {} while (0) #endif /* * Structure used to identify device context. */ struct vhost_device_ctx { pid_t pid; /* PID of process calling the IOCTL. */ uint64_t fh; /* Populated with fi->fh to track the device index. */ }; /* * Structure contains function pointers to be defined in virtio-net.c. These * functions are called in CUSE context and are used to configure devices. */ struct vhost_net_device_ops { int (*new_device)(struct vhost_device_ctx); void (*destroy_device)(struct vhost_device_ctx); void (*set_ifname)(struct vhost_device_ctx, const char *if_name, unsigned int if_len); int (*get_features)(struct vhost_device_ctx, uint64_t *); int (*set_features)(struct vhost_device_ctx, uint64_t *); int (*set_vring_num)(struct vhost_device_ctx, struct vhost_vring_state *); int (*set_vring_addr)(struct vhost_device_ctx, struct vhost_vring_addr *); int (*set_vring_base)(struct vhost_device_ctx, struct vhost_vring_state *); int (*get_vring_base)(struct vhost_device_ctx, uint32_t, struct vhost_vring_state *); int (*set_vring_kick)(struct vhost_device_ctx, struct vhost_vring_file *); int (*set_vring_call)(struct vhost_device_ctx, struct vhost_vring_file *); int (*set_backend)(struct vhost_device_ctx, struct vhost_vring_file *); int (*set_owner)(struct vhost_device_ctx); int (*reset_owner)(struct vhost_device_ctx); }; struct vhost_net_device_ops const *get_virtio_net_callbacks(void); #endif /* _VHOST_NET_CDEV_H_ */ ================================================ FILE: lib/librte_vhost/vhost_cuse/eventfd_copy.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "eventfd_link/eventfd_link.h" #include "eventfd_copy.h" #include "vhost-net.h" static const char eventfd_cdev[] = "/dev/eventfd-link"; /* * This function uses the eventfd_link kernel module to copy an eventfd file * descriptor provided by QEMU in to our process space. */ int eventfd_copy(int target_fd, int target_pid) { int eventfd_link, ret; struct eventfd_copy eventfd_copy; int fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (fd == -1) return -1; /* Open the character device to the kernel module. */ /* TODO: check this earlier rather than fail until VM boots! */ eventfd_link = open(eventfd_cdev, O_RDWR); if (eventfd_link < 0) { RTE_LOG(ERR, VHOST_CONFIG, "eventfd_link module is not loaded\n"); close(fd); return -1; } eventfd_copy.source_fd = fd; eventfd_copy.target_fd = target_fd; eventfd_copy.target_pid = target_pid; /* Call the IOCTL to copy the eventfd. */ ret = ioctl(eventfd_link, EVENTFD_COPY, &eventfd_copy); close(eventfd_link); if (ret < 0) { RTE_LOG(ERR, VHOST_CONFIG, "EVENTFD_COPY ioctl failed\n"); close(fd); return -1; } return fd; } ================================================ FILE: lib/librte_vhost/vhost_cuse/eventfd_copy.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _EVENTFD_H #define _EVENTFD_H int eventfd_copy(int target_fd, int target_pid); #endif ================================================ FILE: lib/librte_vhost/vhost_cuse/vhost-net-cdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "virtio-net-cdev.h" #include "vhost-net.h" #include "eventfd_copy.h" #define FUSE_OPT_DUMMY "\0\0" #define FUSE_OPT_FORE "-f\0\0" #define FUSE_OPT_NOMULTI "-s\0\0" static const uint32_t default_major = 231; static const uint32_t default_minor = 1; static const char cuse_device_name[] = "/dev/cuse"; static const char default_cdev[] = "vhost-net"; static struct fuse_session *session; struct vhost_net_device_ops const *ops; /* * Returns vhost_device_ctx from given fuse_req_t. The index is populated later * when the device is added to the device linked list. */ static struct vhost_device_ctx fuse_req_to_vhost_ctx(fuse_req_t req, struct fuse_file_info *fi) { struct vhost_device_ctx ctx; struct fuse_ctx const *const req_ctx = fuse_req_ctx(req); ctx.pid = req_ctx->pid; ctx.fh = fi->fh; return ctx; } /* * When the device is created in QEMU it gets initialised here and * added to the device linked list. */ static void vhost_net_open(fuse_req_t req, struct fuse_file_info *fi) { struct vhost_device_ctx ctx = fuse_req_to_vhost_ctx(req, fi); int err = 0; err = ops->new_device(ctx); if (err == -1) { fuse_reply_err(req, EPERM); return; } fi->fh = err; RTE_LOG(INFO, VHOST_CONFIG, "(%"PRIu64") Device configuration started\n", fi->fh); fuse_reply_open(req, fi); } /* * When QEMU is shutdown or killed the device gets released. */ static void vhost_net_release(fuse_req_t req, struct fuse_file_info *fi) { int err = 0; struct vhost_device_ctx ctx = fuse_req_to_vhost_ctx(req, fi); ops->destroy_device(ctx); RTE_LOG(INFO, VHOST_CONFIG, "(%"PRIu64") Device released\n", ctx.fh); fuse_reply_err(req, err); } /* * Boilerplate code for CUSE IOCTL * Implicit arguments: ctx, req, result. */ #define VHOST_IOCTL(func) do { \ result = (func)(ctx); \ fuse_reply_ioctl(req, result, NULL, 0); \ } while (0) /* * Boilerplate IOCTL RETRY * Implicit arguments: req. */ #define VHOST_IOCTL_RETRY(size_r, size_w) do { \ struct iovec iov_r = { arg, (size_r) }; \ struct iovec iov_w = { arg, (size_w) }; \ fuse_reply_ioctl_retry(req, &iov_r, \ (size_r) ? 1 : 0, &iov_w, (size_w) ? 1 : 0);\ } while (0) /* * Boilerplate code for CUSE Read IOCTL * Implicit arguments: ctx, req, result, in_bufsz, in_buf. */ #define VHOST_IOCTL_R(type, var, func) do { \ if (!in_bufsz) { \ VHOST_IOCTL_RETRY(sizeof(type), 0);\ } else { \ (var) = *(const type*)in_buf; \ result = func(ctx, &(var)); \ fuse_reply_ioctl(req, result, NULL, 0);\ } \ } while (0) /* * Boilerplate code for CUSE Write IOCTL * Implicit arguments: ctx, req, result, out_bufsz. */ #define VHOST_IOCTL_W(type, var, func) do { \ if (!out_bufsz) { \ VHOST_IOCTL_RETRY(0, sizeof(type));\ } else { \ result = (func)(ctx, &(var));\ fuse_reply_ioctl(req, result, &(var), sizeof(type));\ } \ } while (0) /* * Boilerplate code for CUSE Read/Write IOCTL * Implicit arguments: ctx, req, result, in_bufsz, in_buf. */ #define VHOST_IOCTL_RW(type1, var1, type2, var2, func) do { \ if (!in_bufsz) { \ VHOST_IOCTL_RETRY(sizeof(type1), sizeof(type2));\ } else { \ (var1) = *(const type1*) (in_buf); \ result = (func)(ctx, (var1), &(var2)); \ fuse_reply_ioctl(req, result, &(var2), sizeof(type2));\ } \ } while (0) /* * The IOCTLs are handled using CUSE/FUSE in userspace. Depending on the type * of IOCTL a buffer is requested to read or to write. This request is handled * by FUSE and the buffer is then given to CUSE. */ static void vhost_net_ioctl(fuse_req_t req, int cmd, void *arg, struct fuse_file_info *fi, __rte_unused unsigned flags, const void *in_buf, size_t in_bufsz, size_t out_bufsz) { struct vhost_device_ctx ctx = fuse_req_to_vhost_ctx(req, fi); struct vhost_vring_file file; struct vhost_vring_state state; struct vhost_vring_addr addr; uint64_t features; uint32_t index; int result = 0; switch (cmd) { case VHOST_NET_SET_BACKEND: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_NET_SET_BACKEND\n", ctx.fh); if (!in_buf) { VHOST_IOCTL_RETRY(sizeof(file), 0); break; } file = *(const struct vhost_vring_file *)in_buf; result = cuse_set_backend(ctx, &file); fuse_reply_ioctl(req, result, NULL, 0); break; case VHOST_GET_FEATURES: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_GET_FEATURES\n", ctx.fh); VHOST_IOCTL_W(uint64_t, features, ops->get_features); break; case VHOST_SET_FEATURES: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_FEATURES\n", ctx.fh); VHOST_IOCTL_R(uint64_t, features, ops->set_features); break; case VHOST_RESET_OWNER: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_RESET_OWNER\n", ctx.fh); VHOST_IOCTL(ops->reset_owner); break; case VHOST_SET_OWNER: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_OWNER\n", ctx.fh); VHOST_IOCTL(ops->set_owner); break; case VHOST_SET_MEM_TABLE: /*TODO fix race condition.*/ LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_MEM_TABLE\n", ctx.fh); static struct vhost_memory mem_temp; switch (in_bufsz) { case 0: VHOST_IOCTL_RETRY(sizeof(struct vhost_memory), 0); break; case sizeof(struct vhost_memory): mem_temp = *(const struct vhost_memory *) in_buf; if (mem_temp.nregions > 0) { VHOST_IOCTL_RETRY(sizeof(struct vhost_memory) + (sizeof(struct vhost_memory_region) * mem_temp.nregions), 0); } else { result = -1; fuse_reply_ioctl(req, result, NULL, 0); } break; default: result = cuse_set_mem_table(ctx, in_buf, mem_temp.nregions); if (result) fuse_reply_err(req, EINVAL); else fuse_reply_ioctl(req, result, NULL, 0); } break; case VHOST_SET_VRING_NUM: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_VRING_NUM\n", ctx.fh); VHOST_IOCTL_R(struct vhost_vring_state, state, ops->set_vring_num); break; case VHOST_SET_VRING_BASE: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_VRING_BASE\n", ctx.fh); VHOST_IOCTL_R(struct vhost_vring_state, state, ops->set_vring_base); break; case VHOST_GET_VRING_BASE: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_GET_VRING_BASE\n", ctx.fh); VHOST_IOCTL_RW(uint32_t, index, struct vhost_vring_state, state, ops->get_vring_base); break; case VHOST_SET_VRING_ADDR: LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_VRING_ADDR\n", ctx.fh); VHOST_IOCTL_R(struct vhost_vring_addr, addr, ops->set_vring_addr); break; case VHOST_SET_VRING_KICK: case VHOST_SET_VRING_CALL: if (cmd == VHOST_SET_VRING_KICK) LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_VRING_KICK\n", ctx.fh); else LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: VHOST_SET_VRING_CALL\n", ctx.fh); if (!in_buf) VHOST_IOCTL_RETRY(sizeof(struct vhost_vring_file), 0); else { int fd; file = *(const struct vhost_vring_file *)in_buf; LOG_DEBUG(VHOST_CONFIG, "idx:%d fd:%d\n", file.index, file.fd); fd = eventfd_copy(file.fd, ctx.pid); if (fd < 0) { fuse_reply_ioctl(req, -1, NULL, 0); result = -1; break; } file.fd = fd; if (cmd == VHOST_SET_VRING_KICK) { result = ops->set_vring_kick(ctx, &file); fuse_reply_ioctl(req, result, NULL, 0); } else { result = ops->set_vring_call(ctx, &file); fuse_reply_ioctl(req, result, NULL, 0); } } break; default: RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") IOCTL: DOESN NOT EXIST\n", ctx.fh); result = -1; fuse_reply_ioctl(req, result, NULL, 0); } if (result < 0) LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: FAIL\n", ctx.fh); else LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") IOCTL: SUCCESS\n", ctx.fh); } /* * Structure handling open, release and ioctl function pointers is populated. */ static const struct cuse_lowlevel_ops vhost_net_ops = { .open = vhost_net_open, .release = vhost_net_release, .ioctl = vhost_net_ioctl, }; /* * cuse_info is populated and used to register the cuse device. * vhost_net_device_ops are also passed when the device is registered in app. */ int rte_vhost_driver_register(const char *dev_name) { struct cuse_info cuse_info; char device_name[PATH_MAX] = ""; char char_device_name[PATH_MAX] = ""; const char *device_argv[] = { device_name }; char fuse_opt_dummy[] = FUSE_OPT_DUMMY; char fuse_opt_fore[] = FUSE_OPT_FORE; char fuse_opt_nomulti[] = FUSE_OPT_NOMULTI; char *fuse_argv[] = {fuse_opt_dummy, fuse_opt_fore, fuse_opt_nomulti}; if (access(cuse_device_name, R_OK | W_OK) < 0) { RTE_LOG(ERR, VHOST_CONFIG, "char device %s can't be accessed, maybe not exist\n", cuse_device_name); return -1; } /* * The device name is created. This is passed to QEMU so that it can * register the device with our application. */ snprintf(device_name, PATH_MAX, "DEVNAME=%s", dev_name); snprintf(char_device_name, PATH_MAX, "/dev/%s", dev_name); /* Check if device already exists. */ if (access(char_device_name, F_OK) != -1) { RTE_LOG(ERR, VHOST_CONFIG, "char device %s already exists\n", char_device_name); return -1; } memset(&cuse_info, 0, sizeof(cuse_info)); cuse_info.dev_major = default_major; cuse_info.dev_minor = default_minor; cuse_info.dev_info_argc = 1; cuse_info.dev_info_argv = device_argv; cuse_info.flags = CUSE_UNRESTRICTED_IOCTL; ops = get_virtio_net_callbacks(); session = cuse_lowlevel_setup(3, fuse_argv, &cuse_info, &vhost_net_ops, 0, NULL); if (session == NULL) return -1; return 0; } /** * An empty function for unregister */ int rte_vhost_driver_unregister(const char *dev_name __rte_unused) { return 0; } /** * The CUSE session is launched allowing the application to receive open, * release and ioctl calls. */ int rte_vhost_driver_session_start(void) { fuse_session_loop(session); return 0; } ================================================ FILE: lib/librte_vhost/vhost_cuse/virtio-net-cdev.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rte_virtio_net.h" #include "vhost-net.h" #include "virtio-net-cdev.h" #include "virtio-net.h" #include "eventfd_copy.h" /* Line size for reading maps file. */ static const uint32_t BUFSIZE = PATH_MAX; /* Size of prot char array in procmap. */ #define PROT_SZ 5 /* Number of elements in procmap struct. */ #define PROCMAP_SZ 8 /* Structure containing information gathered from maps file. */ struct procmap { uint64_t va_start; /* Start virtual address in file. */ uint64_t len; /* Size of file. */ uint64_t pgoff; /* Not used. */ uint32_t maj; /* Not used. */ uint32_t min; /* Not used. */ uint32_t ino; /* Not used. */ char prot[PROT_SZ]; /* Not used. */ char fname[PATH_MAX]; /* File name. */ }; /* * Locate the file containing QEMU's memory space and * map it to our address space. */ static int host_memory_map(pid_t pid, uint64_t addr, uint64_t *mapped_address, uint64_t *mapped_size) { struct dirent *dptr = NULL; struct procmap procmap; DIR *dp = NULL; int fd; int i; char memfile[PATH_MAX]; char mapfile[PATH_MAX]; char procdir[PATH_MAX]; char resolved_path[PATH_MAX]; char *path = NULL; FILE *fmap; void *map; uint8_t found = 0; char line[BUFSIZE]; char dlm[] = "- : "; char *str, *sp, *in[PROCMAP_SZ]; char *end = NULL; /* Path where mem files are located. */ snprintf(procdir, PATH_MAX, "/proc/%u/fd/", pid); /* Maps file used to locate mem file. */ snprintf(mapfile, PATH_MAX, "/proc/%u/maps", pid); fmap = fopen(mapfile, "r"); if (fmap == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to open maps file for pid %d\n", pid); return -1; } /* Read through maps file until we find out base_address. */ while (fgets(line, BUFSIZE, fmap) != 0) { str = line; errno = 0; /* Split line into fields. */ for (i = 0; i < PROCMAP_SZ; i++) { in[i] = strtok_r(str, &dlm[i], &sp); if ((in[i] == NULL) || (errno != 0)) { fclose(fmap); return -1; } str = NULL; } /* Convert/Copy each field as needed. */ procmap.va_start = strtoull(in[0], &end, 16); if ((in[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } procmap.len = strtoull(in[1], &end, 16); if ((in[1] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } procmap.pgoff = strtoull(in[3], &end, 16); if ((in[3] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } procmap.maj = strtoul(in[4], &end, 16); if ((in[4] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } procmap.min = strtoul(in[5], &end, 16); if ((in[5] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } procmap.ino = strtoul(in[6], &end, 16); if ((in[6] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) { fclose(fmap); return -1; } memcpy(&procmap.prot, in[2], PROT_SZ); memcpy(&procmap.fname, in[7], PATH_MAX); if (procmap.va_start == addr) { procmap.len = procmap.len - procmap.va_start; found = 1; break; } } fclose(fmap); if (!found) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to find memory file in pid %d maps file\n", pid); return -1; } /* Find the guest memory file among the process fds. */ dp = opendir(procdir); if (dp == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "Cannot open pid %d process directory\n", pid); return -1; } found = 0; /* Read the fd directory contents. */ while (NULL != (dptr = readdir(dp))) { snprintf(memfile, PATH_MAX, "/proc/%u/fd/%s", pid, dptr->d_name); path = realpath(memfile, resolved_path); if ((path == NULL) && (strlen(resolved_path) == 0)) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to resolve fd directory\n"); closedir(dp); return -1; } if (strncmp(resolved_path, procmap.fname, strnlen(procmap.fname, PATH_MAX)) == 0) { found = 1; break; } } closedir(dp); if (found == 0) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to find memory file for pid %d\n", pid); return -1; } /* Open the shared memory file and map the memory into this process. */ fd = open(memfile, O_RDWR); if (fd == -1) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to open %s for pid %d\n", memfile, pid); return -1; } map = mmap(0, (size_t)procmap.len, PROT_READ|PROT_WRITE, MAP_POPULATE|MAP_SHARED, fd, 0); close(fd); if (map == MAP_FAILED) { RTE_LOG(ERR, VHOST_CONFIG, "Error mapping the file %s for pid %d\n", memfile, pid); return -1; } /* Store the memory address and size in the device data structure */ *mapped_address = (uint64_t)(uintptr_t)map; *mapped_size = procmap.len; LOG_DEBUG(VHOST_CONFIG, "Mem File: %s->%s - Size: %llu - VA: %p\n", memfile, resolved_path, (unsigned long long)*mapped_size, map); return 0; } int cuse_set_mem_table(struct vhost_device_ctx ctx, const struct vhost_memory *mem_regions_addr, uint32_t nregions) { uint64_t size = offsetof(struct vhost_memory, regions); uint32_t idx, valid_regions; struct virtio_memory_regions *pregion; struct vhost_memory_region *mem_regions = (void *)(uintptr_t) ((uint64_t)(uintptr_t)mem_regions_addr + size); uint64_t base_address = 0, mapped_address, mapped_size; struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; if (dev->mem && dev->mem->mapped_address) { munmap((void *)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size); free(dev->mem); dev->mem = NULL; } dev->mem = calloc(1, sizeof(struct virtio_memory) + sizeof(struct virtio_memory_regions) * nregions); if (dev->mem == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev->mem\n", dev->device_fh); return -1; } pregion = &dev->mem->regions[0]; for (idx = 0; idx < nregions; idx++) { pregion[idx].guest_phys_address = mem_regions[idx].guest_phys_addr; pregion[idx].guest_phys_address_end = pregion[idx].guest_phys_address + mem_regions[idx].memory_size; pregion[idx].memory_size = mem_regions[idx].memory_size; pregion[idx].userspace_address = mem_regions[idx].userspace_addr; LOG_DEBUG(VHOST_CONFIG, "REGION: %u - GPA: %p - QVA: %p - SIZE (%"PRIu64")\n", idx, (void *)(uintptr_t)pregion[idx].guest_phys_address, (void *)(uintptr_t)pregion[idx].userspace_address, pregion[idx].memory_size); /*set the base address mapping*/ if (pregion[idx].guest_phys_address == 0x0) { base_address = pregion[idx].userspace_address; /* Map VM memory file */ if (host_memory_map(ctx.pid, base_address, &mapped_address, &mapped_size) != 0) { free(dev->mem); dev->mem = NULL; return -1; } dev->mem->mapped_address = mapped_address; dev->mem->base_address = base_address; dev->mem->mapped_size = mapped_size; } } /* Check that we have a valid base address. */ if (base_address == 0) { RTE_LOG(ERR, VHOST_CONFIG, "Failed to find base address of qemu memory file.\n"); free(dev->mem); dev->mem = NULL; return -1; } valid_regions = nregions; for (idx = 0; idx < nregions; idx++) { if ((pregion[idx].userspace_address < base_address) || (pregion[idx].userspace_address > (base_address + mapped_size))) valid_regions--; } if (valid_regions != nregions) { valid_regions = 0; for (idx = nregions; 0 != idx--; ) { if ((pregion[idx].userspace_address < base_address) || (pregion[idx].userspace_address > (base_address + mapped_size))) { memmove(&pregion[idx], &pregion[idx + 1], sizeof(struct virtio_memory_regions) * valid_regions); } else valid_regions++; } } for (idx = 0; idx < valid_regions; idx++) { pregion[idx].address_offset = mapped_address - base_address + pregion[idx].userspace_address - pregion[idx].guest_phys_address; } dev->mem->nregions = valid_regions; return 0; } /* * Function to get the tap device name from the provided file descriptor and * save it in the device structure. */ static int get_ifname(struct vhost_device_ctx ctx, struct virtio_net *dev, int tap_fd, int pid) { int fd_tap; struct ifreq ifr; uint32_t ifr_size; int ret; fd_tap = eventfd_copy(tap_fd, pid); if (fd_tap < 0) return -1; ret = ioctl(fd_tap, TUNGETIFF, &ifr); if (close(fd_tap) < 0) RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") fd close failed\n", dev->device_fh); if (ret >= 0) { ifr_size = strnlen(ifr.ifr_name, sizeof(ifr.ifr_name)); ops->set_ifname(ctx, ifr.ifr_name, ifr_size); } else RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") TUNGETIFF ioctl failed\n", dev->device_fh); return 0; } int cuse_set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; if (!(dev->flags & VIRTIO_DEV_RUNNING) && file->fd != VIRTIO_DEV_STOPPED) get_ifname(ctx, dev, file->fd, ctx.pid); return ops->set_backend(ctx, file); } ================================================ FILE: lib/librte_vhost/vhost_cuse/virtio-net-cdev.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_NET_CDEV_H #define _VIRTIO_NET_CDEV_H #include #include #include "vhost-net.h" int cuse_set_mem_table(struct vhost_device_ctx ctx, const struct vhost_memory *mem_regions_addr, uint32_t nregions); int cuse_set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *); #endif ================================================ FILE: lib/librte_vhost/vhost_rxtx.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include "vhost-net.h" #define MAX_PKT_BURST 32 /** * This function adds buffers to the virtio devices RX virtqueue. Buffers can * be received from the physical port or from another virtio device. A packet * count is returned to indicate the number of packets that are succesfully * added to the RX queue. This function works when the mbuf is scattered, but * it doesn't support the mergeable feature. */ static inline uint32_t __attribute__((always_inline)) virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, struct rte_mbuf **pkts, uint32_t count) { struct vhost_virtqueue *vq; struct vring_desc *desc; struct rte_mbuf *buff; /* The virtio_hdr is initialised to 0. */ struct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0, 0, 0, 0, 0, 0}, 0}; uint64_t buff_addr = 0; uint64_t buff_hdr_addr = 0; uint32_t head[MAX_PKT_BURST]; uint32_t head_idx, packet_success = 0; uint16_t avail_idx, res_cur_idx; uint16_t res_base_idx, res_end_idx; uint16_t free_entries; uint8_t success = 0; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh); if (unlikely(queue_id != VIRTIO_RXQ)) { LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); return 0; } vq = dev->virtqueue[VIRTIO_RXQ]; count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; /* * As many data cores may want access to available buffers, * they need to be reserved. */ do { res_base_idx = vq->last_used_idx_res; avail_idx = *((volatile uint16_t *)&vq->avail->idx); free_entries = (avail_idx - res_base_idx); /*check that we have enough buffers*/ if (unlikely(count > free_entries)) count = free_entries; if (count == 0) return 0; res_end_idx = res_base_idx + count; /* vq->last_used_idx_res is atomically updated. */ /* TODO: Allow to disable cmpset if no concurrency in application. */ success = rte_atomic16_cmpset(&vq->last_used_idx_res, res_base_idx, res_end_idx); } while (unlikely(success == 0)); res_cur_idx = res_base_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| End Index %d\n", dev->device_fh, res_cur_idx, res_end_idx); /* Prefetch available ring to retrieve indexes. */ rte_prefetch0(&vq->avail->ring[res_cur_idx & (vq->size - 1)]); /* Retrieve all of the head indexes first to avoid caching issues. */ for (head_idx = 0; head_idx < count; head_idx++) head[head_idx] = vq->avail->ring[(res_cur_idx + head_idx) & (vq->size - 1)]; /*Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); while (res_cur_idx != res_end_idx) { uint32_t offset = 0, vb_offset = 0; uint32_t pkt_len, len_to_cpy, data_len, total_copied = 0; uint8_t hdr = 0, uncompleted_pkt = 0; /* Get descriptor from available ring */ desc = &vq->desc[head[packet_success]]; buff = pkts[packet_success]; /* Convert from gpa to vva (guest physical addr -> vhost virtual addr) */ buff_addr = gpa_to_vva(dev, desc->addr); /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)buff_addr); /* Copy virtio_hdr to packet and increment buffer address */ buff_hdr_addr = buff_addr; /* * If the descriptors are chained the header and data are * placed in separate buffers. */ if ((desc->flags & VRING_DESC_F_NEXT) && (desc->len == vq->vhost_hlen)) { desc = &vq->desc[desc->next]; /* Buffer address translation. */ buff_addr = gpa_to_vva(dev, desc->addr); } else { vb_offset += vq->vhost_hlen; hdr = 1; } pkt_len = rte_pktmbuf_pkt_len(buff); data_len = rte_pktmbuf_data_len(buff); len_to_cpy = RTE_MIN(data_len, hdr ? desc->len - vq->vhost_hlen : desc->len); while (total_copied < pkt_len) { /* Copy mbuf data to buffer */ rte_memcpy((void *)(uintptr_t)(buff_addr + vb_offset), rte_pktmbuf_mtod_offset(buff, const void *, offset), len_to_cpy); PRINT_PACKET(dev, (uintptr_t)(buff_addr + vb_offset), len_to_cpy, 0); offset += len_to_cpy; vb_offset += len_to_cpy; total_copied += len_to_cpy; /* The whole packet completes */ if (total_copied == pkt_len) break; /* The current segment completes */ if (offset == data_len) { buff = buff->next; offset = 0; data_len = rte_pktmbuf_data_len(buff); } /* The current vring descriptor done */ if (vb_offset == desc->len) { if (desc->flags & VRING_DESC_F_NEXT) { desc = &vq->desc[desc->next]; buff_addr = gpa_to_vva(dev, desc->addr); vb_offset = 0; } else { /* Room in vring buffer is not enough */ uncompleted_pkt = 1; break; } } len_to_cpy = RTE_MIN(data_len - offset, desc->len - vb_offset); }; /* Update used ring with desc information */ vq->used->ring[res_cur_idx & (vq->size - 1)].id = head[packet_success]; /* Drop the packet if it is uncompleted */ if (unlikely(uncompleted_pkt == 1)) vq->used->ring[res_cur_idx & (vq->size - 1)].len = vq->vhost_hlen; else vq->used->ring[res_cur_idx & (vq->size - 1)].len = pkt_len + vq->vhost_hlen; res_cur_idx++; packet_success++; if (unlikely(uncompleted_pkt == 1)) continue; rte_memcpy((void *)(uintptr_t)buff_hdr_addr, (const void *)&virtio_hdr, vq->vhost_hlen); PRINT_PACKET(dev, (uintptr_t)buff_hdr_addr, vq->vhost_hlen, 1); if (res_cur_idx < res_end_idx) { /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[packet_success]]); } } rte_compiler_barrier(); /* Wait until it's our turn to add our buffer to the used ring. */ while (unlikely(vq->last_used_idx != res_base_idx)) rte_pause(); *(volatile uint16_t *)&vq->used->idx += count; vq->last_used_idx = res_end_idx; /* flush used->idx update before we read avail->flags. */ rte_mb(); /* Kick the guest if necessary. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); return count; } static inline uint32_t __attribute__((always_inline)) copy_from_mbuf_to_vring(struct virtio_net *dev, uint16_t res_base_idx, uint16_t res_end_idx, struct rte_mbuf *pkt) { uint32_t vec_idx = 0; uint32_t entry_success = 0; struct vhost_virtqueue *vq; /* The virtio_hdr is initialised to 0. */ struct virtio_net_hdr_mrg_rxbuf virtio_hdr = { {0, 0, 0, 0, 0, 0}, 0}; uint16_t cur_idx = res_base_idx; uint64_t vb_addr = 0; uint64_t vb_hdr_addr = 0; uint32_t seg_offset = 0; uint32_t vb_offset = 0; uint32_t seg_avail; uint32_t vb_avail; uint32_t cpy_len, entry_len; if (pkt == NULL) return 0; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Current Index %d| " "End Index %d\n", dev->device_fh, cur_idx, res_end_idx); /* * Convert from gpa to vva * (guest physical addr -> vhost virtual addr) */ vq = dev->virtqueue[VIRTIO_RXQ]; vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); vb_hdr_addr = vb_addr; /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)vb_addr); virtio_hdr.num_buffers = res_end_idx - res_base_idx; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") RX: Num merge buffers %d\n", dev->device_fh, virtio_hdr.num_buffers); rte_memcpy((void *)(uintptr_t)vb_hdr_addr, (const void *)&virtio_hdr, vq->vhost_hlen); PRINT_PACKET(dev, (uintptr_t)vb_hdr_addr, vq->vhost_hlen, 1); seg_avail = rte_pktmbuf_data_len(pkt); vb_offset = vq->vhost_hlen; vb_avail = vq->buf_vec[vec_idx].buf_len - vq->vhost_hlen; entry_len = vq->vhost_hlen; if (vb_avail == 0) { uint32_t desc_idx = vq->buf_vec[vec_idx].desc_idx; if ((vq->desc[desc_idx].flags & VRING_DESC_F_NEXT) == 0) { /* Update used ring with desc information */ vq->used->ring[cur_idx & (vq->size - 1)].id = vq->buf_vec[vec_idx].desc_idx; vq->used->ring[cur_idx & (vq->size - 1)].len = entry_len; entry_len = 0; cur_idx++; entry_success++; } vec_idx++; vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)vb_addr); vb_offset = 0; vb_avail = vq->buf_vec[vec_idx].buf_len; } cpy_len = RTE_MIN(vb_avail, seg_avail); while (cpy_len > 0) { /* Copy mbuf data to vring buffer */ rte_memcpy((void *)(uintptr_t)(vb_addr + vb_offset), rte_pktmbuf_mtod_offset(pkt, const void *, seg_offset), cpy_len); PRINT_PACKET(dev, (uintptr_t)(vb_addr + vb_offset), cpy_len, 0); seg_offset += cpy_len; vb_offset += cpy_len; seg_avail -= cpy_len; vb_avail -= cpy_len; entry_len += cpy_len; if (seg_avail != 0) { /* * The virtio buffer in this vring * entry reach to its end. * But the segment doesn't complete. */ if ((vq->desc[vq->buf_vec[vec_idx].desc_idx].flags & VRING_DESC_F_NEXT) == 0) { /* Update used ring with desc information */ vq->used->ring[cur_idx & (vq->size - 1)].id = vq->buf_vec[vec_idx].desc_idx; vq->used->ring[cur_idx & (vq->size - 1)].len = entry_len; entry_len = 0; cur_idx++; entry_success++; } vec_idx++; vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); vb_offset = 0; vb_avail = vq->buf_vec[vec_idx].buf_len; cpy_len = RTE_MIN(vb_avail, seg_avail); } else { /* * This current segment complete, need continue to * check if the whole packet complete or not. */ pkt = pkt->next; if (pkt != NULL) { /* * There are more segments. */ if (vb_avail == 0) { /* * This current buffer from vring is * used up, need fetch next buffer * from buf_vec. */ uint32_t desc_idx = vq->buf_vec[vec_idx].desc_idx; if ((vq->desc[desc_idx].flags & VRING_DESC_F_NEXT) == 0) { uint16_t wrapped_idx = cur_idx & (vq->size - 1); /* * Update used ring with the * descriptor information */ vq->used->ring[wrapped_idx].id = desc_idx; vq->used->ring[wrapped_idx].len = entry_len; entry_success++; entry_len = 0; cur_idx++; } /* Get next buffer from buf_vec. */ vec_idx++; vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); vb_avail = vq->buf_vec[vec_idx].buf_len; vb_offset = 0; } seg_offset = 0; seg_avail = rte_pktmbuf_data_len(pkt); cpy_len = RTE_MIN(vb_avail, seg_avail); } else { /* * This whole packet completes. */ /* Update used ring with desc information */ vq->used->ring[cur_idx & (vq->size - 1)].id = vq->buf_vec[vec_idx].desc_idx; vq->used->ring[cur_idx & (vq->size - 1)].len = entry_len; entry_success++; break; } } } return entry_success; } static inline void __attribute__((always_inline)) update_secure_len(struct vhost_virtqueue *vq, uint32_t id, uint32_t *secure_len, uint32_t *vec_idx) { uint16_t wrapped_idx = id & (vq->size - 1); uint32_t idx = vq->avail->ring[wrapped_idx]; uint8_t next_desc; uint32_t len = *secure_len; uint32_t vec_id = *vec_idx; do { next_desc = 0; len += vq->desc[idx].len; vq->buf_vec[vec_id].buf_addr = vq->desc[idx].addr; vq->buf_vec[vec_id].buf_len = vq->desc[idx].len; vq->buf_vec[vec_id].desc_idx = idx; vec_id++; if (vq->desc[idx].flags & VRING_DESC_F_NEXT) { idx = vq->desc[idx].next; next_desc = 1; } } while (next_desc); *secure_len = len; *vec_idx = vec_id; } /* * This function works for mergeable RX. */ static inline uint32_t __attribute__((always_inline)) virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, struct rte_mbuf **pkts, uint32_t count) { struct vhost_virtqueue *vq; uint32_t pkt_idx = 0, entry_success = 0; uint16_t avail_idx; uint16_t res_base_idx, res_cur_idx; uint8_t success = 0; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_merge_rx()\n", dev->device_fh); if (unlikely(queue_id != VIRTIO_RXQ)) { LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); } vq = dev->virtqueue[VIRTIO_RXQ]; count = RTE_MIN((uint32_t)MAX_PKT_BURST, count); if (count == 0) return 0; for (pkt_idx = 0; pkt_idx < count; pkt_idx++) { uint32_t pkt_len = pkts[pkt_idx]->pkt_len + vq->vhost_hlen; do { /* * As many data cores may want access to available * buffers, they need to be reserved. */ uint32_t secure_len = 0; uint32_t vec_idx = 0; res_base_idx = vq->last_used_idx_res; res_cur_idx = res_base_idx; do { avail_idx = *((volatile uint16_t *)&vq->avail->idx); if (unlikely(res_cur_idx == avail_idx)) { LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Failed " "to get enough desc from " "vring\n", dev->device_fh); return pkt_idx; } else { update_secure_len(vq, res_cur_idx, &secure_len, &vec_idx); res_cur_idx++; } } while (pkt_len > secure_len); /* vq->last_used_idx_res is atomically updated. */ success = rte_atomic16_cmpset(&vq->last_used_idx_res, res_base_idx, res_cur_idx); } while (success == 0); entry_success = copy_from_mbuf_to_vring(dev, res_base_idx, res_cur_idx, pkts[pkt_idx]); rte_compiler_barrier(); /* * Wait until it's our turn to add our buffer * to the used ring. */ while (unlikely(vq->last_used_idx != res_base_idx)) rte_pause(); *(volatile uint16_t *)&vq->used->idx += entry_success; vq->last_used_idx = res_cur_idx; /* flush used->idx update before we read avail->flags. */ rte_mb(); /* Kick the guest if necessary. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); } return count; } uint16_t rte_vhost_enqueue_burst(struct virtio_net *dev, uint16_t queue_id, struct rte_mbuf **pkts, uint16_t count) { if (unlikely(dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF))) return virtio_dev_merge_rx(dev, queue_id, pkts, count); else return virtio_dev_rx(dev, queue_id, pkts, count); } uint16_t rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id, struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count) { struct rte_mbuf *m, *prev; struct vhost_virtqueue *vq; struct vring_desc *desc; uint64_t vb_addr = 0; uint32_t head[MAX_PKT_BURST]; uint32_t used_idx; uint32_t i; uint16_t free_entries, entry_success = 0; uint16_t avail_idx; if (unlikely(queue_id != VIRTIO_TXQ)) { LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); return 0; } vq = dev->virtqueue[VIRTIO_TXQ]; avail_idx = *((volatile uint16_t *)&vq->avail->idx); /* If there are no available buffers then return. */ if (vq->last_used_idx == avail_idx) return 0; LOG_DEBUG(VHOST_DATA, "%s (%"PRIu64")\n", __func__, dev->device_fh); /* Prefetch available ring to retrieve head indexes. */ rte_prefetch0(&vq->avail->ring[vq->last_used_idx & (vq->size - 1)]); /*get the number of free entries in the ring*/ free_entries = (avail_idx - vq->last_used_idx); free_entries = RTE_MIN(free_entries, count); /* Limit to MAX_PKT_BURST. */ free_entries = RTE_MIN(free_entries, MAX_PKT_BURST); LOG_DEBUG(VHOST_DATA, "(%"PRIu64") Buffers available %d\n", dev->device_fh, free_entries); /* Retrieve all of the head indexes first to avoid caching issues. */ for (i = 0; i < free_entries; i++) head[i] = vq->avail->ring[(vq->last_used_idx + i) & (vq->size - 1)]; /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[entry_success]]); rte_prefetch0(&vq->used->ring[vq->last_used_idx & (vq->size - 1)]); while (entry_success < free_entries) { uint32_t vb_avail, vb_offset; uint32_t seg_avail, seg_offset; uint32_t cpy_len; uint32_t seg_num = 0; struct rte_mbuf *cur; uint8_t alloc_err = 0; desc = &vq->desc[head[entry_success]]; /* Discard first buffer as it is the virtio header */ if (desc->flags & VRING_DESC_F_NEXT) { desc = &vq->desc[desc->next]; vb_offset = 0; vb_avail = desc->len; } else { vb_offset = vq->vhost_hlen; vb_avail = desc->len - vb_offset; } /* Buffer address translation. */ vb_addr = gpa_to_vva(dev, desc->addr); /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)vb_addr); used_idx = vq->last_used_idx & (vq->size - 1); if (entry_success < (free_entries - 1)) { /* Prefetch descriptor index. */ rte_prefetch0(&vq->desc[head[entry_success+1]]); rte_prefetch0(&vq->used->ring[(used_idx + 1) & (vq->size - 1)]); } /* Update used index buffer information. */ vq->used->ring[used_idx].id = head[entry_success]; vq->used->ring[used_idx].len = 0; /* Allocate an mbuf and populate the structure. */ m = rte_pktmbuf_alloc(mbuf_pool); if (unlikely(m == NULL)) { RTE_LOG(ERR, VHOST_DATA, "Failed to allocate memory for mbuf.\n"); break; } seg_offset = 0; seg_avail = m->buf_len - RTE_PKTMBUF_HEADROOM; cpy_len = RTE_MIN(vb_avail, seg_avail); PRINT_PACKET(dev, (uintptr_t)vb_addr, desc->len, 0); seg_num++; cur = m; prev = m; while (cpy_len != 0) { rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *, seg_offset), (void *)((uintptr_t)(vb_addr + vb_offset)), cpy_len); seg_offset += cpy_len; vb_offset += cpy_len; vb_avail -= cpy_len; seg_avail -= cpy_len; if (vb_avail != 0) { /* * The segment reachs to its end, * while the virtio buffer in TX vring has * more data to be copied. */ cur->data_len = seg_offset; m->pkt_len += seg_offset; /* Allocate mbuf and populate the structure. */ cur = rte_pktmbuf_alloc(mbuf_pool); if (unlikely(cur == NULL)) { RTE_LOG(ERR, VHOST_DATA, "Failed to " "allocate memory for mbuf.\n"); rte_pktmbuf_free(m); alloc_err = 1; break; } seg_num++; prev->next = cur; prev = cur; seg_offset = 0; seg_avail = cur->buf_len - RTE_PKTMBUF_HEADROOM; } else { if (desc->flags & VRING_DESC_F_NEXT) { /* * There are more virtio buffers in * same vring entry need to be copied. */ if (seg_avail == 0) { /* * The current segment hasn't * room to accomodate more * data. */ cur->data_len = seg_offset; m->pkt_len += seg_offset; /* * Allocate an mbuf and * populate the structure. */ cur = rte_pktmbuf_alloc(mbuf_pool); if (unlikely(cur == NULL)) { RTE_LOG(ERR, VHOST_DATA, "Failed to " "allocate memory " "for mbuf\n"); rte_pktmbuf_free(m); alloc_err = 1; break; } seg_num++; prev->next = cur; prev = cur; seg_offset = 0; seg_avail = cur->buf_len - RTE_PKTMBUF_HEADROOM; } desc = &vq->desc[desc->next]; /* Buffer address translation. */ vb_addr = gpa_to_vva(dev, desc->addr); /* Prefetch buffer address. */ rte_prefetch0((void *)(uintptr_t)vb_addr); vb_offset = 0; vb_avail = desc->len; PRINT_PACKET(dev, (uintptr_t)vb_addr, desc->len, 0); } else { /* The whole packet completes. */ cur->data_len = seg_offset; m->pkt_len += seg_offset; vb_avail = 0; } } cpy_len = RTE_MIN(vb_avail, seg_avail); } if (unlikely(alloc_err == 1)) break; m->nb_segs = seg_num; pkts[entry_success] = m; vq->last_used_idx++; entry_success++; } rte_compiler_barrier(); vq->used->idx += entry_success; /* Kick guest if required. */ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) eventfd_write((int)vq->callfd, 1); return entry_success; } ================================================ FILE: lib/librte_vhost/vhost_user/fd_man.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "fd_man.h" /** * Returns the index in the fdset for a given fd. * If fd is -1, it means to search for a free entry. * @return * index for the fd, or -1 if fd isn't in the fdset. */ static int fdset_find_fd(struct fdset *pfdset, int fd) { int i; if (pfdset == NULL) return -1; for (i = 0; i < MAX_FDS && pfdset->fd[i].fd != fd; i++) ; return i == MAX_FDS ? -1 : i; } static int fdset_find_free_slot(struct fdset *pfdset) { return fdset_find_fd(pfdset, -1); } static void fdset_add_fd(struct fdset *pfdset, int idx, int fd, fd_cb rcb, fd_cb wcb, void *dat) { struct fdentry *pfdentry; if (pfdset == NULL || idx >= MAX_FDS) return; pfdentry = &pfdset->fd[idx]; pfdentry->fd = fd; pfdentry->rcb = rcb; pfdentry->wcb = wcb; pfdentry->dat = dat; } /** * Fill the read/write fd_set with the fds in the fdset. * @return * the maximum fds filled in the read/write fd_set. */ static int fdset_fill(fd_set *rfset, fd_set *wfset, struct fdset *pfdset) { struct fdentry *pfdentry; int i, maxfds = -1; int num = MAX_FDS; if (pfdset == NULL) return -1; for (i = 0; i < num; i++) { pfdentry = &pfdset->fd[i]; if (pfdentry->fd != -1) { int added = 0; if (pfdentry->rcb && rfset) { FD_SET(pfdentry->fd, rfset); added = 1; } if (pfdentry->wcb && wfset) { FD_SET(pfdentry->fd, wfset); added = 1; } if (added) maxfds = pfdentry->fd < maxfds ? maxfds : pfdentry->fd; } } return maxfds; } void fdset_init(struct fdset *pfdset) { int i; if (pfdset == NULL) return; for (i = 0; i < MAX_FDS; i++) pfdset->fd[i].fd = -1; pfdset->num = 0; } /** * Register the fd in the fdset with read/write handler and context. */ int fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat) { int i; if (pfdset == NULL || fd == -1) return -1; pthread_mutex_lock(&pfdset->fd_mutex); /* Find a free slot in the list. */ i = fdset_find_free_slot(pfdset); if (i == -1) return -2; fdset_add_fd(pfdset, i, fd, rcb, wcb, dat); pfdset->num++; pthread_mutex_unlock(&pfdset->fd_mutex); return 0; } /** * Unregister the fd from the fdset. */ void fdset_del(struct fdset *pfdset, int fd) { int i; if (pfdset == NULL || fd == -1) return; do { pthread_mutex_lock(&pfdset->fd_mutex); i = fdset_find_fd(pfdset, fd); if (i != -1 && pfdset->fd[i].busy == 0) { /* busy indicates r/wcb is executing! */ pfdset->fd[i].fd = -1; pfdset->fd[i].rcb = pfdset->fd[i].wcb = NULL; pfdset->num--; i = -1; } pthread_mutex_unlock(&pfdset->fd_mutex); } while (i != -1); } /** * Unregister the fd at the specified slot from the fdset. */ static void fdset_del_slot(struct fdset *pfdset, int index) { if (pfdset == NULL || index < 0 || index >= MAX_FDS) return; pthread_mutex_lock(&pfdset->fd_mutex); pfdset->fd[index].fd = -1; pfdset->fd[index].rcb = pfdset->fd[index].wcb = NULL; pfdset->num--; pthread_mutex_unlock(&pfdset->fd_mutex); } /** * This functions runs in infinite blocking loop until there is no fd in * pfdset. It calls corresponding r/w handler if there is event on the fd. * * Before the callback is called, we set the flag to busy status; If other * thread(now rte_vhost_driver_unregister) calls fdset_del concurrently, it * will wait until the flag is reset to zero(which indicates the callback is * finished), then it could free the context after fdset_del. */ void fdset_event_dispatch(struct fdset *pfdset) { fd_set rfds, wfds; int i, maxfds; struct fdentry *pfdentry; int num = MAX_FDS; fd_cb rcb, wcb; void *dat; int fd; int remove1, remove2; int ret; if (pfdset == NULL) return; while (1) { struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); pthread_mutex_lock(&pfdset->fd_mutex); maxfds = fdset_fill(&rfds, &wfds, pfdset); pthread_mutex_unlock(&pfdset->fd_mutex); /* * When select is blocked, other threads might unregister * listenfds from and register new listenfds into fdset. * When select returns, the entries for listenfds in the fdset * might have been updated. It is ok if there is unwanted call * for new listenfds. */ ret = select(maxfds + 1, &rfds, &wfds, NULL, &tv); if (ret <= 0) continue; for (i = 0; i < num; i++) { remove1 = remove2 = 0; pthread_mutex_lock(&pfdset->fd_mutex); pfdentry = &pfdset->fd[i]; fd = pfdentry->fd; rcb = pfdentry->rcb; wcb = pfdentry->wcb; dat = pfdentry->dat; pfdentry->busy = 1; pthread_mutex_unlock(&pfdset->fd_mutex); if (fd >= 0 && FD_ISSET(fd, &rfds) && rcb) rcb(fd, dat, &remove1); if (fd >= 0 && FD_ISSET(fd, &wfds) && wcb) wcb(fd, dat, &remove2); pfdentry->busy = 0; /* * fdset_del needs to check busy flag. * We don't allow fdset_del to be called in callback * directly. */ /* * When we are to clean up the fd from fdset, * because the fd is closed in the cb, * the old fd val could be reused by when creates new * listen fd in another thread, we couldn't call * fd_set_del. */ if (remove1 || remove2) fdset_del_slot(pfdset, i); } } } ================================================ FILE: lib/librte_vhost/vhost_user/fd_man.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _FD_MAN_H_ #define _FD_MAN_H_ #include #include #define MAX_FDS 1024 typedef void (*fd_cb)(int fd, void *dat, int *remove); struct fdentry { int fd; /* -1 indicates this entry is empty */ fd_cb rcb; /* callback when this fd is readable. */ fd_cb wcb; /* callback when this fd is writeable.*/ void *dat; /* fd context */ int busy; /* whether this entry is being used in cb. */ }; struct fdset { struct fdentry fd[MAX_FDS]; pthread_mutex_t fd_mutex; int num; /* current fd number of this fdset */ }; void fdset_init(struct fdset *pfdset); int fdset_add(struct fdset *pfdset, int fd, fd_cb rcb, fd_cb wcb, void *dat); void fdset_del(struct fdset *pfdset, int fd); void fdset_event_dispatch(struct fdset *pfdset); #endif ================================================ FILE: lib/librte_vhost/vhost_user/vhost-net-user.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fd_man.h" #include "vhost-net-user.h" #include "vhost-net.h" #include "virtio-net-user.h" #define MAX_VIRTIO_BACKLOG 128 static void vserver_new_vq_conn(int fd, void *data, int *remove); static void vserver_message_handler(int fd, void *dat, int *remove); struct vhost_net_device_ops const *ops; struct connfd_ctx { struct vhost_server *vserver; uint32_t fh; }; #define MAX_VHOST_SERVER 1024 struct _vhost_server { struct vhost_server *server[MAX_VHOST_SERVER]; struct fdset fdset; int vserver_cnt; pthread_mutex_t server_mutex; }; static struct _vhost_server g_vhost_server = { .fdset = { .fd = { [0 ... MAX_FDS - 1] = {-1, NULL, NULL, NULL, 0} }, .fd_mutex = PTHREAD_MUTEX_INITIALIZER, .num = 0 }, .vserver_cnt = 0, .server_mutex = PTHREAD_MUTEX_INITIALIZER, }; static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_NONE] = "VHOST_USER_NONE", [VHOST_USER_GET_FEATURES] = "VHOST_USER_GET_FEATURES", [VHOST_USER_SET_FEATURES] = "VHOST_USER_SET_FEATURES", [VHOST_USER_SET_OWNER] = "VHOST_USER_SET_OWNER", [VHOST_USER_RESET_OWNER] = "VHOST_USER_RESET_OWNER", [VHOST_USER_SET_MEM_TABLE] = "VHOST_USER_SET_MEM_TABLE", [VHOST_USER_SET_LOG_BASE] = "VHOST_USER_SET_LOG_BASE", [VHOST_USER_SET_LOG_FD] = "VHOST_USER_SET_LOG_FD", [VHOST_USER_SET_VRING_NUM] = "VHOST_USER_SET_VRING_NUM", [VHOST_USER_SET_VRING_ADDR] = "VHOST_USER_SET_VRING_ADDR", [VHOST_USER_SET_VRING_BASE] = "VHOST_USER_SET_VRING_BASE", [VHOST_USER_GET_VRING_BASE] = "VHOST_USER_GET_VRING_BASE", [VHOST_USER_SET_VRING_KICK] = "VHOST_USER_SET_VRING_KICK", [VHOST_USER_SET_VRING_CALL] = "VHOST_USER_SET_VRING_CALL", [VHOST_USER_SET_VRING_ERR] = "VHOST_USER_SET_VRING_ERR" }; /** * Create a unix domain socket, bind to path and listen for connection. * @return * socket fd or -1 on failure */ static int uds_socket(const char *path) { struct sockaddr_un un; int sockfd; int ret; if (path == NULL) return -1; sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) return -1; RTE_LOG(INFO, VHOST_CONFIG, "socket created, fd:%d\n", sockfd); memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); ret = bind(sockfd, (struct sockaddr *)&un, sizeof(un)); if (ret == -1) { RTE_LOG(ERR, VHOST_CONFIG, "fail to bind fd:%d, remove file:%s and try again.\n", sockfd, path); goto err; } RTE_LOG(INFO, VHOST_CONFIG, "bind to %s\n", path); ret = listen(sockfd, MAX_VIRTIO_BACKLOG); if (ret == -1) goto err; return sockfd; err: close(sockfd); return -1; } /* return bytes# of read on success or negative val on failure. */ static int read_fd_message(int sockfd, char *buf, int buflen, int *fds, int fd_num) { struct iovec iov; struct msghdr msgh; size_t fdsize = fd_num * sizeof(int); char control[CMSG_SPACE(fdsize)]; struct cmsghdr *cmsg; int ret; memset(&msgh, 0, sizeof(msgh)); iov.iov_base = buf; iov.iov_len = buflen; msgh.msg_iov = &iov; msgh.msg_iovlen = 1; msgh.msg_control = control; msgh.msg_controllen = sizeof(control); ret = recvmsg(sockfd, &msgh, 0); if (ret <= 0) { RTE_LOG(ERR, VHOST_CONFIG, "recvmsg failed\n"); return ret; } if (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) { RTE_LOG(ERR, VHOST_CONFIG, "truncted msg\n"); return -1; } for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) { memcpy(fds, CMSG_DATA(cmsg), fdsize); break; } } return ret; } /* return bytes# of read on success or negative val on failure. */ static int read_vhost_message(int sockfd, struct VhostUserMsg *msg) { int ret; ret = read_fd_message(sockfd, (char *)msg, VHOST_USER_HDR_SIZE, msg->fds, VHOST_MEMORY_MAX_NREGIONS); if (ret <= 0) return ret; if (msg && msg->size) { if (msg->size > sizeof(msg->payload)) { RTE_LOG(ERR, VHOST_CONFIG, "invalid msg size: %d\n", msg->size); return -1; } ret = read(sockfd, &msg->payload, msg->size); if (ret <= 0) return ret; if (ret != (int)msg->size) { RTE_LOG(ERR, VHOST_CONFIG, "read control message failed\n"); return -1; } } return ret; } static int send_fd_message(int sockfd, char *buf, int buflen, int *fds, int fd_num) { struct iovec iov; struct msghdr msgh; size_t fdsize = fd_num * sizeof(int); char control[CMSG_SPACE(fdsize)]; struct cmsghdr *cmsg; int ret; memset(&msgh, 0, sizeof(msgh)); iov.iov_base = buf; iov.iov_len = buflen; msgh.msg_iov = &iov; msgh.msg_iovlen = 1; if (fds && fd_num > 0) { msgh.msg_control = control; msgh.msg_controllen = sizeof(control); cmsg = CMSG_FIRSTHDR(&msgh); cmsg->cmsg_len = CMSG_LEN(fdsize); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(cmsg), fds, fdsize); } else { msgh.msg_control = NULL; msgh.msg_controllen = 0; } do { ret = sendmsg(sockfd, &msgh, 0); } while (ret < 0 && errno == EINTR); if (ret < 0) { RTE_LOG(ERR, VHOST_CONFIG, "sendmsg error\n"); return ret; } return ret; } static int send_vhost_message(int sockfd, struct VhostUserMsg *msg) { int ret; if (!msg) return 0; msg->flags &= ~VHOST_USER_VERSION_MASK; msg->flags |= VHOST_USER_VERSION; msg->flags |= VHOST_USER_REPLY_MASK; ret = send_fd_message(sockfd, (char *)msg, VHOST_USER_HDR_SIZE + msg->size, NULL, 0); return ret; } /* call back when there is new virtio connection. */ static void vserver_new_vq_conn(int fd, void *dat, __rte_unused int *remove) { struct vhost_server *vserver = (struct vhost_server *)dat; int conn_fd; struct connfd_ctx *ctx; int fh; struct vhost_device_ctx vdev_ctx = { (pid_t)0, 0 }; unsigned int size; conn_fd = accept(fd, NULL, NULL); RTE_LOG(INFO, VHOST_CONFIG, "new virtio connection is %d\n", conn_fd); if (conn_fd < 0) return; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { close(conn_fd); return; } fh = ops->new_device(vdev_ctx); if (fh == -1) { free(ctx); close(conn_fd); return; } vdev_ctx.fh = fh; size = strnlen(vserver->path, PATH_MAX); ops->set_ifname(vdev_ctx, vserver->path, size); RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", fh); ctx->vserver = vserver; ctx->fh = fh; fdset_add(&g_vhost_server.fdset, conn_fd, vserver_message_handler, NULL, ctx); } /* callback when there is message on the connfd */ static void vserver_message_handler(int connfd, void *dat, int *remove) { struct vhost_device_ctx ctx; struct connfd_ctx *cfd_ctx = (struct connfd_ctx *)dat; struct VhostUserMsg msg; uint64_t features; int ret; ctx.fh = cfd_ctx->fh; ret = read_vhost_message(connfd, &msg); if (ret < 0) { RTE_LOG(ERR, VHOST_CONFIG, "vhost read message failed\n"); close(connfd); *remove = 1; free(cfd_ctx); user_destroy_device(ctx); ops->destroy_device(ctx); return; } else if (ret == 0) { RTE_LOG(INFO, VHOST_CONFIG, "vhost peer closed\n"); close(connfd); *remove = 1; free(cfd_ctx); user_destroy_device(ctx); ops->destroy_device(ctx); return; } if (msg.request > VHOST_USER_MAX) { RTE_LOG(ERR, VHOST_CONFIG, "vhost read incorrect message\n"); close(connfd); *remove = 1; free(cfd_ctx); user_destroy_device(ctx); ops->destroy_device(ctx); return; } RTE_LOG(INFO, VHOST_CONFIG, "read message %s\n", vhost_message_str[msg.request]); switch (msg.request) { case VHOST_USER_GET_FEATURES: ret = ops->get_features(ctx, &features); msg.payload.u64 = features; msg.size = sizeof(msg.payload.u64); send_vhost_message(connfd, &msg); break; case VHOST_USER_SET_FEATURES: features = msg.payload.u64; ops->set_features(ctx, &features); break; case VHOST_USER_SET_OWNER: ops->set_owner(ctx); break; case VHOST_USER_RESET_OWNER: ops->reset_owner(ctx); break; case VHOST_USER_SET_MEM_TABLE: user_set_mem_table(ctx, &msg); break; case VHOST_USER_SET_LOG_BASE: RTE_LOG(INFO, VHOST_CONFIG, "not implemented.\n"); case VHOST_USER_SET_LOG_FD: close(msg.fds[0]); RTE_LOG(INFO, VHOST_CONFIG, "not implemented.\n"); break; case VHOST_USER_SET_VRING_NUM: ops->set_vring_num(ctx, &msg.payload.state); break; case VHOST_USER_SET_VRING_ADDR: ops->set_vring_addr(ctx, &msg.payload.addr); break; case VHOST_USER_SET_VRING_BASE: ops->set_vring_base(ctx, &msg.payload.state); break; case VHOST_USER_GET_VRING_BASE: ret = user_get_vring_base(ctx, &msg.payload.state); msg.size = sizeof(msg.payload.state); send_vhost_message(connfd, &msg); break; case VHOST_USER_SET_VRING_KICK: user_set_vring_kick(ctx, &msg); break; case VHOST_USER_SET_VRING_CALL: user_set_vring_call(ctx, &msg); break; case VHOST_USER_SET_VRING_ERR: if (!(msg.payload.u64 & VHOST_USER_VRING_NOFD_MASK)) close(msg.fds[0]); RTE_LOG(INFO, VHOST_CONFIG, "not implemented\n"); break; default: break; } } /** * Creates and initialise the vhost server. */ int rte_vhost_driver_register(const char *path) { struct vhost_server *vserver; pthread_mutex_lock(&g_vhost_server.server_mutex); if (ops == NULL) ops = get_virtio_net_callbacks(); if (g_vhost_server.vserver_cnt == MAX_VHOST_SERVER) { RTE_LOG(ERR, VHOST_CONFIG, "error: the number of servers reaches maximum\n"); pthread_mutex_unlock(&g_vhost_server.server_mutex); return -1; } vserver = calloc(sizeof(struct vhost_server), 1); if (vserver == NULL) { pthread_mutex_unlock(&g_vhost_server.server_mutex); return -1; } vserver->listenfd = uds_socket(path); if (vserver->listenfd < 0) { free(vserver); pthread_mutex_unlock(&g_vhost_server.server_mutex); return -1; } vserver->path = strdup(path); fdset_add(&g_vhost_server.fdset, vserver->listenfd, vserver_new_vq_conn, NULL, vserver); g_vhost_server.server[g_vhost_server.vserver_cnt++] = vserver; pthread_mutex_unlock(&g_vhost_server.server_mutex); return 0; } /** * Unregister the specified vhost server */ int rte_vhost_driver_unregister(const char *path) { int i; int count; pthread_mutex_lock(&g_vhost_server.server_mutex); for (i = 0; i < g_vhost_server.vserver_cnt; i++) { if (!strcmp(g_vhost_server.server[i]->path, path)) { fdset_del(&g_vhost_server.fdset, g_vhost_server.server[i]->listenfd); close(g_vhost_server.server[i]->listenfd); free(g_vhost_server.server[i]->path); free(g_vhost_server.server[i]); unlink(path); count = --g_vhost_server.vserver_cnt; g_vhost_server.server[i] = g_vhost_server.server[count]; g_vhost_server.server[count] = NULL; pthread_mutex_unlock(&g_vhost_server.server_mutex); return 0; } } pthread_mutex_unlock(&g_vhost_server.server_mutex); return -1; } int rte_vhost_driver_session_start(void) { fdset_event_dispatch(&g_vhost_server.fdset); return 0; } ================================================ FILE: lib/librte_vhost/vhost_user/vhost-net-user.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VHOST_NET_USER_H #define _VHOST_NET_USER_H #include #include #include "rte_virtio_net.h" #include "fd_man.h" struct vhost_server { char *path; /**< The path the uds is bind to. */ int listenfd; /**< The listener sockfd. */ }; /* refer to hw/virtio/vhost-user.c */ typedef enum VhostUserRequest { VHOST_USER_NONE = 0, VHOST_USER_GET_FEATURES = 1, VHOST_USER_SET_FEATURES = 2, VHOST_USER_SET_OWNER = 3, VHOST_USER_RESET_OWNER = 4, VHOST_USER_SET_MEM_TABLE = 5, VHOST_USER_SET_LOG_BASE = 6, VHOST_USER_SET_LOG_FD = 7, VHOST_USER_SET_VRING_NUM = 8, VHOST_USER_SET_VRING_ADDR = 9, VHOST_USER_SET_VRING_BASE = 10, VHOST_USER_GET_VRING_BASE = 11, VHOST_USER_SET_VRING_KICK = 12, VHOST_USER_SET_VRING_CALL = 13, VHOST_USER_SET_VRING_ERR = 14, VHOST_USER_MAX } VhostUserRequest; typedef struct VhostUserMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; uint64_t userspace_addr; uint64_t mmap_offset; } VhostUserMemoryRegion; typedef struct VhostUserMemory { uint32_t nregions; uint32_t padding; VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS]; } VhostUserMemory; typedef struct VhostUserMsg { VhostUserRequest request; #define VHOST_USER_VERSION_MASK 0x3 #define VHOST_USER_REPLY_MASK (0x1 << 2) uint32_t flags; uint32_t size; /* the following payload size */ union { #define VHOST_USER_VRING_IDX_MASK 0xff #define VHOST_USER_VRING_NOFD_MASK (0x1<<8) uint64_t u64; struct vhost_vring_state state; struct vhost_vring_addr addr; VhostUserMemory memory; } payload; int fds[VHOST_MEMORY_MAX_NREGIONS]; } __attribute((packed)) VhostUserMsg; #define VHOST_USER_HDR_SIZE offsetof(VhostUserMsg, payload.u64) /* The version of the protocol we support */ #define VHOST_USER_VERSION 0x1 /*****************************************************************************/ #endif ================================================ FILE: lib/librte_vhost/vhost_user/virtio-net-user.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "virtio-net.h" #include "virtio-net-user.h" #include "vhost-net-user.h" #include "vhost-net.h" struct orig_region_map { int fd; uint64_t mapped_address; uint64_t mapped_size; uint64_t blksz; }; #define orig_region(ptr, nregions) \ ((struct orig_region_map *)RTE_PTR_ADD((ptr), \ sizeof(struct virtio_memory) + \ sizeof(struct virtio_memory_regions) * (nregions))) static uint64_t get_blk_size(int fd) { struct stat stat; fstat(fd, &stat); return (uint64_t)stat.st_blksize; } static void free_mem_region(struct virtio_net *dev) { struct orig_region_map *region; unsigned int idx; uint64_t alignment; if (!dev || !dev->mem) return; region = orig_region(dev->mem, dev->mem->nregions); for (idx = 0; idx < dev->mem->nregions; idx++) { if (region[idx].mapped_address) { alignment = region[idx].blksz; munmap((void *)(uintptr_t) RTE_ALIGN_FLOOR( region[idx].mapped_address, alignment), RTE_ALIGN_CEIL( region[idx].mapped_size, alignment)); close(region[idx].fd); } } } int user_set_mem_table(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg) { struct VhostUserMemory memory = pmsg->payload.memory; struct virtio_memory_regions *pregion; uint64_t mapped_address, mapped_size; struct virtio_net *dev; unsigned int idx = 0; struct orig_region_map *pregion_orig; uint64_t alignment; /* unmap old memory regions one by one*/ dev = get_device(ctx); if (dev == NULL) return -1; /* Remove from the data plane. */ if (dev->flags & VIRTIO_DEV_RUNNING) notify_ops->destroy_device(dev); if (dev->mem) { free_mem_region(dev); free(dev->mem); dev->mem = NULL; } dev->mem = calloc(1, sizeof(struct virtio_memory) + sizeof(struct virtio_memory_regions) * memory.nregions + sizeof(struct orig_region_map) * memory.nregions); if (dev->mem == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev->mem\n", dev->device_fh); return -1; } dev->mem->nregions = memory.nregions; pregion_orig = orig_region(dev->mem, memory.nregions); for (idx = 0; idx < memory.nregions; idx++) { pregion = &dev->mem->regions[idx]; pregion->guest_phys_address = memory.regions[idx].guest_phys_addr; pregion->guest_phys_address_end = memory.regions[idx].guest_phys_addr + memory.regions[idx].memory_size; pregion->memory_size = memory.regions[idx].memory_size; pregion->userspace_address = memory.regions[idx].userspace_addr; /* This is ugly */ mapped_size = memory.regions[idx].memory_size + memory.regions[idx].mmap_offset; mapped_address = (uint64_t)(uintptr_t)mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, pmsg->fds[idx], 0); RTE_LOG(INFO, VHOST_CONFIG, "mapped region %d fd:%d to %p sz:0x%"PRIx64" off:0x%"PRIx64"\n", idx, pmsg->fds[idx], (void *)(uintptr_t)mapped_address, mapped_size, memory.regions[idx].mmap_offset); if (mapped_address == (uint64_t)(uintptr_t)MAP_FAILED) { RTE_LOG(ERR, VHOST_CONFIG, "mmap qemu guest failed.\n"); goto err_mmap; } pregion_orig[idx].mapped_address = mapped_address; pregion_orig[idx].mapped_size = mapped_size; pregion_orig[idx].blksz = get_blk_size(pmsg->fds[idx]); pregion_orig[idx].fd = pmsg->fds[idx]; mapped_address += memory.regions[idx].mmap_offset; pregion->address_offset = mapped_address - pregion->guest_phys_address; if (memory.regions[idx].guest_phys_addr == 0) { dev->mem->base_address = memory.regions[idx].userspace_addr; dev->mem->mapped_address = pregion->address_offset; } LOG_DEBUG(VHOST_CONFIG, "REGION: %u GPA: %p QEMU VA: %p SIZE (%"PRIu64")\n", idx, (void *)(uintptr_t)pregion->guest_phys_address, (void *)(uintptr_t)pregion->userspace_address, pregion->memory_size); } return 0; err_mmap: while (idx--) { alignment = pregion_orig[idx].blksz; munmap((void *)(uintptr_t)RTE_ALIGN_FLOOR( pregion_orig[idx].mapped_address, alignment), RTE_ALIGN_CEIL(pregion_orig[idx].mapped_size, alignment)); close(pregion_orig[idx].fd); } free(dev->mem); dev->mem = NULL; return -1; } static int virtio_is_ready(struct virtio_net *dev) { struct vhost_virtqueue *rvq, *tvq; /* mq support in future.*/ rvq = dev->virtqueue[VIRTIO_RXQ]; tvq = dev->virtqueue[VIRTIO_TXQ]; if (rvq && tvq && rvq->desc && tvq->desc && (rvq->kickfd != (eventfd_t)-1) && (rvq->callfd != (eventfd_t)-1) && (tvq->kickfd != (eventfd_t)-1) && (tvq->callfd != (eventfd_t)-1)) { RTE_LOG(INFO, VHOST_CONFIG, "virtio is now ready for processing.\n"); return 1; } RTE_LOG(INFO, VHOST_CONFIG, "virtio isn't ready for processing.\n"); return 0; } void user_set_vring_call(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg) { struct vhost_vring_file file; file.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; if (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) file.fd = -1; else file.fd = pmsg->fds[0]; RTE_LOG(INFO, VHOST_CONFIG, "vring call idx:%d file:%d\n", file.index, file.fd); ops->set_vring_call(ctx, &file); } /* * In vhost-user, when we receive kick message, will test whether virtio * device is ready for packet processing. */ void user_set_vring_kick(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg) { struct vhost_vring_file file; struct virtio_net *dev = get_device(ctx); file.index = pmsg->payload.u64 & VHOST_USER_VRING_IDX_MASK; if (pmsg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) file.fd = -1; else file.fd = pmsg->fds[0]; RTE_LOG(INFO, VHOST_CONFIG, "vring kick idx:%d file:%d\n", file.index, file.fd); ops->set_vring_kick(ctx, &file); if (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) notify_ops->new_device(dev); } /* * when virtio is stopped, qemu will send us the GET_VRING_BASE message. */ int user_get_vring_base(struct vhost_device_ctx ctx, struct vhost_vring_state *state) { struct virtio_net *dev = get_device(ctx); /* We have to stop the queue (virtio) if it is running. */ if (dev->flags & VIRTIO_DEV_RUNNING) notify_ops->destroy_device(dev); /* Here we are safe to get the last used index */ ops->get_vring_base(ctx, state->index, state); RTE_LOG(INFO, VHOST_CONFIG, "vring base idx:%d file:%d\n", state->index, state->num); /* * Based on current qemu vhost-user implementation, this message is * sent and only sent in vhost_vring_stop. * TODO: cleanup the vring, it isn't usable since here. */ if (((int)dev->virtqueue[VIRTIO_RXQ]->kickfd) >= 0) { close(dev->virtqueue[VIRTIO_RXQ]->kickfd); dev->virtqueue[VIRTIO_RXQ]->kickfd = (eventfd_t)-1; } if (((int)dev->virtqueue[VIRTIO_TXQ]->kickfd) >= 0) { close(dev->virtqueue[VIRTIO_TXQ]->kickfd); dev->virtqueue[VIRTIO_TXQ]->kickfd = (eventfd_t)-1; } return 0; } void user_destroy_device(struct vhost_device_ctx ctx) { struct virtio_net *dev = get_device(ctx); if (dev && (dev->flags & VIRTIO_DEV_RUNNING)) notify_ops->destroy_device(dev); if (dev && dev->mem) { free_mem_region(dev); free(dev->mem); dev->mem = NULL; } } ================================================ FILE: lib/librte_vhost/vhost_user/virtio-net-user.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_NET_USER_H #define _VIRTIO_NET_USER_H #include "vhost-net.h" #include "vhost-net-user.h" int user_set_mem_table(struct vhost_device_ctx, struct VhostUserMsg *); void user_set_vring_call(struct vhost_device_ctx, struct VhostUserMsg *); void user_set_vring_kick(struct vhost_device_ctx, struct VhostUserMsg *); int user_get_vring_base(struct vhost_device_ctx, struct vhost_vring_state *); void user_destroy_device(struct vhost_device_ctx); #endif ================================================ FILE: lib/librte_vhost/virtio-net.c ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #ifdef RTE_LIBRTE_VHOST_NUMA #include #endif #include #include #include #include #include #include #include #include "vhost-net.h" #include "virtio-net.h" /* * Device linked list structure for configuration. */ struct virtio_net_config_ll { struct virtio_net dev; /* Virtio device.*/ struct virtio_net_config_ll *next; /* Next dev on linked list.*/ }; /* device ops to add/remove device to/from data core. */ struct virtio_net_device_ops const *notify_ops; /* root address of the linked list of managed virtio devices */ static struct virtio_net_config_ll *ll_root; /* Features supported by this lib. */ #define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \ (1ULL << VIRTIO_NET_F_CTRL_VQ) | \ (1ULL << VIRTIO_NET_F_CTRL_RX) | \ (1ULL << VHOST_F_LOG_ALL)) static uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES; /* * Converts QEMU virtual address to Vhost virtual address. This function is * used to convert the ring addresses to our address space. */ static uint64_t qva_to_vva(struct virtio_net *dev, uint64_t qemu_va) { struct virtio_memory_regions *region; uint64_t vhost_va = 0; uint32_t regionidx = 0; /* Find the region where the address lives. */ for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) { region = &dev->mem->regions[regionidx]; if ((qemu_va >= region->userspace_address) && (qemu_va <= region->userspace_address + region->memory_size)) { vhost_va = qemu_va + region->guest_phys_address + region->address_offset - region->userspace_address; break; } } return vhost_va; } /* * Retrieves an entry from the devices configuration linked list. */ static struct virtio_net_config_ll * get_config_ll_entry(struct vhost_device_ctx ctx) { struct virtio_net_config_ll *ll_dev = ll_root; /* Loop through linked list until the device_fh is found. */ while (ll_dev != NULL) { if (ll_dev->dev.device_fh == ctx.fh) return ll_dev; ll_dev = ll_dev->next; } return NULL; } /* * Searches the configuration core linked list and * retrieves the device if it exists. */ struct virtio_net * get_device(struct vhost_device_ctx ctx) { struct virtio_net_config_ll *ll_dev; ll_dev = get_config_ll_entry(ctx); if (ll_dev) return &ll_dev->dev; RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Device not found in linked list.\n", ctx.fh); return NULL; } /* * Add entry containing a device to the device configuration linked list. */ static void add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev) { struct virtio_net_config_ll *ll_dev = ll_root; /* If ll_dev == NULL then this is the first device so go to else */ if (ll_dev) { /* If the 1st device_fh != 0 then we insert our device here. */ if (ll_dev->dev.device_fh != 0) { new_ll_dev->dev.device_fh = 0; new_ll_dev->next = ll_dev; ll_root = new_ll_dev; } else { /* * Increment through the ll until we find un unused * device_fh. Insert the device at that entry. */ while ((ll_dev->next != NULL) && (ll_dev->dev.device_fh == (ll_dev->next->dev.device_fh - 1))) ll_dev = ll_dev->next; new_ll_dev->dev.device_fh = ll_dev->dev.device_fh + 1; new_ll_dev->next = ll_dev->next; ll_dev->next = new_ll_dev; } } else { ll_root = new_ll_dev; ll_root->dev.device_fh = 0; } } /* * Unmap any memory, close any file descriptors and * free any memory owned by a device. */ static void cleanup_device(struct virtio_net *dev) { /* Unmap QEMU memory file if mapped. */ if (dev->mem) { munmap((void *)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size); free(dev->mem); } /* Close any event notifiers opened by device. */ if ((int)dev->virtqueue[VIRTIO_RXQ]->callfd >= 0) close((int)dev->virtqueue[VIRTIO_RXQ]->callfd); if ((int)dev->virtqueue[VIRTIO_RXQ]->kickfd >= 0) close((int)dev->virtqueue[VIRTIO_RXQ]->kickfd); if ((int)dev->virtqueue[VIRTIO_TXQ]->callfd >= 0) close((int)dev->virtqueue[VIRTIO_TXQ]->callfd); if ((int)dev->virtqueue[VIRTIO_TXQ]->kickfd >= 0) close((int)dev->virtqueue[VIRTIO_TXQ]->kickfd); } /* * Release virtqueues and device memory. */ static void free_device(struct virtio_net_config_ll *ll_dev) { /* Free any malloc'd memory */ rte_free(ll_dev->dev.virtqueue[VIRTIO_RXQ]); rte_free(ll_dev->dev.virtqueue[VIRTIO_TXQ]); rte_free(ll_dev); } /* * Remove an entry from the device configuration linked list. */ static struct virtio_net_config_ll * rm_config_ll_entry(struct virtio_net_config_ll *ll_dev, struct virtio_net_config_ll *ll_dev_last) { /* First remove the device and then clean it up. */ if (ll_dev == ll_root) { ll_root = ll_dev->next; cleanup_device(&ll_dev->dev); free_device(ll_dev); return ll_root; } else { if (likely(ll_dev_last != NULL)) { ll_dev_last->next = ll_dev->next; cleanup_device(&ll_dev->dev); free_device(ll_dev); return ll_dev_last->next; } else { cleanup_device(&ll_dev->dev); free_device(ll_dev); RTE_LOG(ERR, VHOST_CONFIG, "Remove entry from config_ll failed\n"); return NULL; } } } /* * Initialise all variables in device structure. */ static void init_device(struct virtio_net *dev) { uint64_t vq_offset; /* * Virtqueues have already been malloced so * we don't want to set them to NULL. */ vq_offset = offsetof(struct virtio_net, mem); /* Set everything to 0. */ memset((void *)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0, (sizeof(struct virtio_net) - (size_t)vq_offset)); memset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct vhost_virtqueue)); memset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct vhost_virtqueue)); dev->virtqueue[VIRTIO_RXQ]->kickfd = (eventfd_t)-1; dev->virtqueue[VIRTIO_RXQ]->callfd = (eventfd_t)-1; dev->virtqueue[VIRTIO_TXQ]->kickfd = (eventfd_t)-1; dev->virtqueue[VIRTIO_TXQ]->callfd = (eventfd_t)-1; /* Backends are set to -1 indicating an inactive device. */ dev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED; dev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED; } /* * Function is called from the CUSE open function. The device structure is * initialised and a new entry is added to the device configuration linked * list. */ static int new_device(struct vhost_device_ctx ctx) { struct virtio_net_config_ll *new_ll_dev; struct vhost_virtqueue *virtqueue_rx, *virtqueue_tx; /* Setup device and virtqueues. */ new_ll_dev = rte_malloc(NULL, sizeof(struct virtio_net_config_ll), 0); if (new_ll_dev == NULL) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev.\n", ctx.fh); return -1; } virtqueue_rx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0); if (virtqueue_rx == NULL) { rte_free(new_ll_dev); RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for rxq.\n", ctx.fh); return -1; } virtqueue_tx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0); if (virtqueue_tx == NULL) { rte_free(virtqueue_rx); rte_free(new_ll_dev); RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for txq.\n", ctx.fh); return -1; } new_ll_dev->dev.virtqueue[VIRTIO_RXQ] = virtqueue_rx; new_ll_dev->dev.virtqueue[VIRTIO_TXQ] = virtqueue_tx; /* Initialise device and virtqueues. */ init_device(&new_ll_dev->dev); new_ll_dev->next = NULL; /* Add entry to device configuration linked list. */ add_config_ll_entry(new_ll_dev); return new_ll_dev->dev.device_fh; } /* * Function is called from the CUSE release function. This function will * cleanup the device and remove it from device configuration linked list. */ static void destroy_device(struct vhost_device_ctx ctx) { struct virtio_net_config_ll *ll_dev_cur_ctx, *ll_dev_last = NULL; struct virtio_net_config_ll *ll_dev_cur = ll_root; /* Find the linked list entry for the device to be removed. */ ll_dev_cur_ctx = get_config_ll_entry(ctx); while (ll_dev_cur != NULL) { /* * If the device is found or * a device that doesn't exist is found then it is removed. */ if (ll_dev_cur == ll_dev_cur_ctx) { /* * If the device is running on a data core then call * the function to remove it from the data core. */ if ((ll_dev_cur->dev.flags & VIRTIO_DEV_RUNNING)) notify_ops->destroy_device(&(ll_dev_cur->dev)); ll_dev_cur = rm_config_ll_entry(ll_dev_cur, ll_dev_last); } else { ll_dev_last = ll_dev_cur; ll_dev_cur = ll_dev_cur->next; } } } static void set_ifname(struct vhost_device_ctx ctx, const char *if_name, unsigned int if_len) { struct virtio_net *dev; unsigned int len; dev = get_device(ctx); if (dev == NULL) return; len = if_len > sizeof(dev->ifname) ? sizeof(dev->ifname) : if_len; strncpy(dev->ifname, if_name, len); } /* * Called from CUSE IOCTL: VHOST_SET_OWNER * This function just returns success at the moment unless * the device hasn't been initialised. */ static int set_owner(struct vhost_device_ctx ctx) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; return 0; } /* * Called from CUSE IOCTL: VHOST_RESET_OWNER */ static int reset_owner(struct vhost_device_ctx ctx) { struct virtio_net_config_ll *ll_dev; ll_dev = get_config_ll_entry(ctx); cleanup_device(&ll_dev->dev); init_device(&ll_dev->dev); return 0; } /* * Called from CUSE IOCTL: VHOST_GET_FEATURES * The features that we support are requested. */ static int get_features(struct vhost_device_ctx ctx, uint64_t *pu) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; /* Send our supported features. */ *pu = VHOST_FEATURES; return 0; } /* * Called from CUSE IOCTL: VHOST_SET_FEATURES * We receive the negotiated features supported by us and the virtio device. */ static int set_features(struct vhost_device_ctx ctx, uint64_t *pu) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; if (*pu & ~VHOST_FEATURES) return -1; /* Store the negotiated feature list for the device. */ dev->features = *pu; /* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF is set. */ if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers enabled\n", dev->device_fh); dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf); dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf); } else { LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers disabled\n", dev->device_fh); dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr); dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr); } return 0; } /* * Called from CUSE IOCTL: VHOST_SET_VRING_NUM * The virtio device sends us the size of the descriptor ring. */ static int set_vring_num(struct vhost_device_ctx ctx, struct vhost_vring_state *state) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; /* State->index refers to the queue index. The txq is 1, rxq is 0. */ dev->virtqueue[state->index]->size = state->num; return 0; } /* * Reallocate virtio_det and vhost_virtqueue data structure to make them on the * same numa node as the memory of vring descriptor. */ #ifdef RTE_LIBRTE_VHOST_NUMA static struct virtio_net* numa_realloc(struct virtio_net *dev, int index) { int oldnode, newnode; struct virtio_net_config_ll *old_ll_dev, *new_ll_dev = NULL; struct vhost_virtqueue *old_vq, *new_vq = NULL; int ret; int realloc_dev = 0, realloc_vq = 0; old_ll_dev = (struct virtio_net_config_ll *)dev; old_vq = dev->virtqueue[index]; ret = get_mempolicy(&newnode, NULL, 0, old_vq->desc, MPOL_F_NODE | MPOL_F_ADDR); ret = ret | get_mempolicy(&oldnode, NULL, 0, old_ll_dev, MPOL_F_NODE | MPOL_F_ADDR); if (ret) { RTE_LOG(ERR, VHOST_CONFIG, "Unable to get vring desc or dev numa information.\n"); return dev; } if (oldnode != newnode) realloc_dev = 1; ret = get_mempolicy(&oldnode, NULL, 0, old_vq, MPOL_F_NODE | MPOL_F_ADDR); if (ret) { RTE_LOG(ERR, VHOST_CONFIG, "Unable to get vq numa information.\n"); return dev; } if (oldnode != newnode) realloc_vq = 1; if (realloc_dev == 0 && realloc_vq == 0) return dev; if (realloc_dev) new_ll_dev = rte_malloc_socket(NULL, sizeof(struct virtio_net_config_ll), 0, newnode); if (realloc_vq) new_vq = rte_malloc_socket(NULL, sizeof(struct vhost_virtqueue), 0, newnode); if (!new_ll_dev && !new_vq) return dev; if (realloc_vq) memcpy(new_vq, old_vq, sizeof(*new_vq)); if (realloc_dev) memcpy(new_ll_dev, old_ll_dev, sizeof(*new_ll_dev)); (new_ll_dev ? new_ll_dev : old_ll_dev)->dev.virtqueue[index] = new_vq ? new_vq : old_vq; if (realloc_vq) rte_free(old_vq); if (realloc_dev) { if (ll_root == old_ll_dev) ll_root = new_ll_dev; else { struct virtio_net_config_ll *prev = ll_root; while (prev->next != old_ll_dev) prev = prev->next; prev->next = new_ll_dev; new_ll_dev->next = old_ll_dev->next; } rte_free(old_ll_dev); } return realloc_dev ? &new_ll_dev->dev : dev; } #else static struct virtio_net* numa_realloc(struct virtio_net *dev, int index __rte_unused) { return dev; } #endif /* * Called from CUSE IOCTL: VHOST_SET_VRING_ADDR * The virtio device sends us the desc, used and avail ring addresses. * This function then converts these to our address space. */ static int set_vring_addr(struct vhost_device_ctx ctx, struct vhost_vring_addr *addr) { struct virtio_net *dev; struct vhost_virtqueue *vq; dev = get_device(ctx); if (dev == NULL) return -1; /* addr->index refers to the queue index. The txq 1, rxq is 0. */ vq = dev->virtqueue[addr->index]; /* The addresses are converted from QEMU virtual to Vhost virtual. */ vq->desc = (struct vring_desc *)(uintptr_t)qva_to_vva(dev, addr->desc_user_addr); if (vq->desc == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find desc ring address.\n", dev->device_fh); return -1; } dev = numa_realloc(dev, addr->index); vq = dev->virtqueue[addr->index]; vq->avail = (struct vring_avail *)(uintptr_t)qva_to_vva(dev, addr->avail_user_addr); if (vq->avail == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find avail ring address.\n", dev->device_fh); return -1; } vq->used = (struct vring_used *)(uintptr_t)qva_to_vva(dev, addr->used_user_addr); if (vq->used == 0) { RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find used ring address.\n", dev->device_fh); return -1; } LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address desc: %p\n", dev->device_fh, vq->desc); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address avail: %p\n", dev->device_fh, vq->avail); LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address used: %p\n", dev->device_fh, vq->used); return 0; } /* * Called from CUSE IOCTL: VHOST_SET_VRING_BASE * The virtio device sends us the available ring last used index. */ static int set_vring_base(struct vhost_device_ctx ctx, struct vhost_vring_state *state) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; /* State->index refers to the queue index. The txq is 1, rxq is 0. */ dev->virtqueue[state->index]->last_used_idx = state->num; dev->virtqueue[state->index]->last_used_idx_res = state->num; return 0; } /* * Called from CUSE IOCTL: VHOST_GET_VRING_BASE * We send the virtio device our available ring last used index. */ static int get_vring_base(struct vhost_device_ctx ctx, uint32_t index, struct vhost_vring_state *state) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; state->index = index; /* State->index refers to the queue index. The txq is 1, rxq is 0. */ state->num = dev->virtqueue[state->index]->last_used_idx; return 0; } /* * Called from CUSE IOCTL: VHOST_SET_VRING_CALL * The virtio device sends an eventfd to interrupt the guest. This fd gets * copied into our process space. */ static int set_vring_call(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; struct vhost_virtqueue *vq; dev = get_device(ctx); if (dev == NULL) return -1; /* file->index refers to the queue index. The txq is 1, rxq is 0. */ vq = dev->virtqueue[file->index]; if ((int)vq->callfd >= 0) close((int)vq->callfd); vq->callfd = file->fd; return 0; } /* * Called from CUSE IOCTL: VHOST_SET_VRING_KICK * The virtio device sends an eventfd that it can use to notify us. * This fd gets copied into our process space. */ static int set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; struct vhost_virtqueue *vq; dev = get_device(ctx); if (dev == NULL) return -1; /* file->index refers to the queue index. The txq is 1, rxq is 0. */ vq = dev->virtqueue[file->index]; if ((int)vq->kickfd >= 0) close((int)vq->kickfd); vq->kickfd = file->fd; return 0; } /* * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND * To complete device initialisation when the virtio driver is loaded, * we are provided with a valid fd for a tap device (not used by us). * If this happens then we can add the device to a data core. * When the virtio driver is removed we get fd=-1. * At that point we remove the device from the data core. * The device will still exist in the device configuration linked list. */ static int set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file) { struct virtio_net *dev; dev = get_device(ctx); if (dev == NULL) return -1; /* file->index refers to the queue index. The txq is 1, rxq is 0. */ dev->virtqueue[file->index]->backend = file->fd; /* * If the device isn't already running and both backend fds are set, * we add the device. */ if (!(dev->flags & VIRTIO_DEV_RUNNING)) { if (((int)dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED) && ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED)) { return notify_ops->new_device(dev); } /* Otherwise we remove it. */ } else if (file->fd == VIRTIO_DEV_STOPPED) notify_ops->destroy_device(dev); return 0; } /* * Function pointers are set for the device operations to allow CUSE to call * functions when an IOCTL, device_add or device_release is received. */ static const struct vhost_net_device_ops vhost_device_ops = { .new_device = new_device, .destroy_device = destroy_device, .set_ifname = set_ifname, .get_features = get_features, .set_features = set_features, .set_vring_num = set_vring_num, .set_vring_addr = set_vring_addr, .set_vring_base = set_vring_base, .get_vring_base = get_vring_base, .set_vring_kick = set_vring_kick, .set_vring_call = set_vring_call, .set_backend = set_backend, .set_owner = set_owner, .reset_owner = reset_owner, }; /* * Called by main to setup callbacks when registering CUSE device. */ struct vhost_net_device_ops const * get_virtio_net_callbacks(void) { return &vhost_device_ops; } int rte_vhost_enable_guest_notification(struct virtio_net *dev, uint16_t queue_id, int enable) { if (enable) { RTE_LOG(ERR, VHOST_CONFIG, "guest notification isn't supported.\n"); return -1; } dev->virtqueue[queue_id]->used->flags = enable ? 0 : VRING_USED_F_NO_NOTIFY; return 0; } uint64_t rte_vhost_feature_get(void) { return VHOST_FEATURES; } int rte_vhost_feature_disable(uint64_t feature_mask) { VHOST_FEATURES = VHOST_FEATURES & ~feature_mask; return 0; } int rte_vhost_feature_enable(uint64_t feature_mask) { if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) { VHOST_FEATURES = VHOST_FEATURES | feature_mask; return 0; } return -1; } /* * Register ops so that we can add/remove device to data core. */ int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops) { notify_ops = ops; return 0; } ================================================ FILE: lib/librte_vhost/virtio-net.h ================================================ /*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _VIRTIO_NET_H #define _VIRTIO_NET_H #include "vhost-net.h" #include "rte_virtio_net.h" struct virtio_net_device_ops const *notify_ops; struct virtio_net *get_device(struct vhost_device_ctx ctx); #endif ================================================ FILE: mk/arch/i686/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # arch: # # - define ARCH variable (overriden by cmdline or by previous # optional define in machine .mk) # - define CROSS variable (overriden by cmdline or previous define # in machine .mk) # - define CPU_CFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_LDFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_ASFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - may override any previously defined variable # # examples for CONFIG_RTE_ARCH: i686, x86_64, x86_64_32 # ARCH ?= i386 # common arch dir in eal headers ARCH_DIR := x86 CROSS ?= CPU_CFLAGS ?= -m32 CPU_LDFLAGS ?= -melf_i386 CPU_ASFLAGS ?= -felf export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS ================================================ FILE: mk/arch/ppc_64/rte.vars.mk ================================================ # BSD LICENSE # # Copyright (C) IBM Corporation 2014. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of IBM Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARCH ?= powerpc CROSS ?= CPU_CFLAGS ?= -m64 -DRTE_CACHE_LINE_SIZE=128 CPU_LDFLAGS ?= CPU_ASFLAGS ?= -felf64 export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS ================================================ FILE: mk/arch/tile/rte.vars.mk ================================================ # BSD LICENSE # # Copyright (C) EZchip Semiconductor Ltd. 2015. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of EZchip Semiconductor nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ARCH ?= tile CROSS ?= tile- CPU_CFLAGS ?= CPU_LDFLAGS ?= CPU_ASFLAGS ?= export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS ================================================ FILE: mk/arch/x86_64/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # arch: # # - define ARCH variable (overriden by cmdline or by previous # optional define in machine .mk) # - define CROSS variable (overriden by cmdline or previous define # in machine .mk) # - define CPU_CFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_LDFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_ASFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - may override any previously defined variable # # examples for CONFIG_RTE_ARCH: i686, x86_64, x86_64_32 # ARCH ?= x86_64 # common arch dir in eal headers ARCH_DIR := x86 CROSS ?= CPU_CFLAGS ?= -m64 CPU_LDFLAGS ?= CPU_ASFLAGS ?= -felf64 export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS ================================================ FILE: mk/arch/x86_x32/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # arch: # # - define ARCH variable (overridden by cmdline or by previous # optional define in machine .mk) # - define CROSS variable (overridden by cmdline or previous define # in machine .mk) # - define CPU_CFLAGS variable (overridden by cmdline or previous # define in machine .mk) # - define CPU_LDFLAGS variable (overridden by cmdline or previous # define in machine .mk) # - define CPU_ASFLAGS variable (overridden by cmdline or previous # define in machine .mk) # - may override any previously defined variable # # examples for CONFIG_RTE_ARCH: i686, x86_64, x86_64_32 # ARCH ?= x86_64 ARCH_DIR := x86 CROSS ?= CPU_CFLAGS ?= -mx32 CPU_LDFLAGS ?= -melf32_x86_64 #CPU_ASFLAGS ?= -felf64 # x32 is supported by Linux distribution with gcc4.8 and newer in some # cases there is backported support in gcc4.6 ifneq ($(shell echo | $(CC) $(CPU_CFLAGS) -E - 2>/dev/null 1>/dev/null && echo 0), 0) $(error This version of GCC does not support x32 ABI) endif export ARCH CROSS CPU_CFLAGS CPU_LDFLAGS CPU_ASFLAGS ================================================ FILE: mk/exec-env/bsdapp/rte.app.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. exec-env-appinstall: @true exec-env-appclean: @true ================================================ FILE: mk/exec-env/bsdapp/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # exec-env: # # - define EXECENV_CFLAGS variable (overriden by cmdline) # - define EXECENV_LDFLAGS variable (overriden by cmdline) # - define EXECENV_ASFLAGS variable (overriden by cmdline) # - may override any previously defined variable # # examples for RTE_EXEC_ENV: linuxapp, bsdapp # ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) EXECENV_CFLAGS = -pthread -fPIC else EXECENV_CFLAGS = -pthread endif EXECENV_LDFLAGS = EXECENV_LDLIBS = -lexecinfo EXECENV_ASFLAGS = ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) EXECENV_LDLIBS += -lgcc_s endif # force applications to link with gcc/icc instead of using ld LINK_USING_CC := 1 BSDMAKE=/usr/bin/make export EXECENV_CFLAGS EXECENV_LDFLAGS EXECENV_ASFLAGS ================================================ FILE: mk/exec-env/linuxapp/rte.app.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. exec-env-appinstall: @true exec-env-appclean: @true ================================================ FILE: mk/exec-env/linuxapp/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # exec-env: # # - define EXECENV_CFLAGS variable (overriden by cmdline) # - define EXECENV_LDFLAGS variable (overriden by cmdline) # - define EXECENV_ASFLAGS variable (overriden by cmdline) # - may override any previously defined variable # # examples for RTE_EXEC_ENV: linuxapp, bsdapp # ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) EXECENV_CFLAGS = -pthread -fPIC else EXECENV_CFLAGS = -pthread endif # Workaround lack of DT_NEEDED entry EXECENV_LDFLAGS = --no-as-needed EXECENV_LDLIBS = -lrt -lm EXECENV_ASFLAGS = ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) EXECENV_LDLIBS += -lgcc_s endif # force applications to link with gcc/icc instead of using ld LINK_USING_CC := 1 # For shared libraries EXECENV_LDFLAGS += -export-dynamic # Add library to the group to resolve symbols EXECENV_LDLIBS += -ldl export EXECENV_CFLAGS EXECENV_LDFLAGS EXECENV_ASFLAGS EXECENV_LDLIBS ================================================ FILE: mk/internal/rte.build-post.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # build helper .mk # fast way, no need to do prebuild and postbuild ifeq ($(PREBUILD)$(POSTBUILD),) _postbuild: $(_BUILD) @touch _postbuild else # slower way _prebuild: $(PREBUILD) @touch _prebuild ifneq ($(_BUILD),) $(_BUILD): _prebuild else _BUILD = _prebuild endif _build: $(_BUILD) @touch _build ifneq ($(POSTBUILD),) $(POSTBUILD): _build else POSTBUILD = _build endif _postbuild: $(POSTBUILD) @touch _postbuild endif ================================================ FILE: mk/internal/rte.build-pre.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _BUILD_TARGETS := _prebuild _build _postbuild comma := , linkerprefix = $(subst -Wl$(comma)-L,-L,$(addprefix -Wl$(comma),$1)) ================================================ FILE: mk/internal/rte.clean-post.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # clean helper .mk # fast way, no need to do preclean and postclean ifeq ($(PRECLEAN)$(POSTCLEAN),) _postclean: $(_CLEAN) @touch _postclean else # slower way _preclean: $(PRECLEAN) @touch _preclean ifneq ($(_CLEAN),) $(_CLEAN): _preclean else _CLEAN = _preclean endif _clean: $(_CLEAN) @touch _clean ifneq ($(POSTCLEAN),) $(POSTCLEAN): _clean else POSTCLEAN = _clean endif _postclean: $(POSTCLEAN) @touch _postclean endif ================================================ FILE: mk/internal/rte.clean-pre.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _CLEAN_TARGETS := _preclean _clean _postclean ================================================ FILE: mk/internal/rte.compile-post.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # no rule no build these files $(DEPS-y) $(CMDS-y): ================================================ FILE: mk/internal/rte.compile-pre.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Common to rte.lib.mk, rte.app.mk, rte.obj.mk # SRCS-all := $(SRCS-y) $(SRCS-n) $(SRCS-) # convert source to obj file src2obj = $(strip $(patsubst %.c,%.o,\ $(patsubst %.S,%_s.o,$(1)))) # add a dot in front of the file name dotfile = $(strip $(foreach f,$(1),\ $(join $(dir $f),.$(notdir $f)))) # convert source/obj files into dot-dep filename (does not # include .S files) src2dep = $(strip $(call dotfile,$(patsubst %.c,%.o.d, \ $(patsubst %.S,,$(1))))) obj2dep = $(strip $(call dotfile,$(patsubst %.o,%.o.d,$(1)))) # convert source/obj files into dot-cmd filename src2cmd = $(strip $(call dotfile,$(patsubst %.c,%.o.cmd, \ $(patsubst %.S,%_s.o.cmd,$(1))))) obj2cmd = $(strip $(call dotfile,$(patsubst %.o,%.o.cmd,$(1)))) OBJS-y := $(call src2obj,$(SRCS-y)) OBJS-n := $(call src2obj,$(SRCS-n)) OBJS- := $(call src2obj,$(SRCS-)) OBJS-all := $(filter-out $(SRCS-all),$(OBJS-y) $(OBJS-n) $(OBJS-)) DEPS-y := $(call src2dep,$(SRCS-y)) DEPS-n := $(call src2dep,$(SRCS-n)) DEPS- := $(call src2dep,$(SRCS-)) DEPS-all := $(DEPS-y) $(DEPS-n) $(DEPS-) DEPSTMP-all := $(DEPS-all:%.d=%.d.tmp) CMDS-y := $(call src2cmd,$(SRCS-y)) CMDS-n := $(call src2cmd,$(SRCS-n)) CMDS- := $(call src2cmd,$(SRCS-)) CMDS-all := $(CMDS-y) $(CMDS-n) $(CMDS-) -include $(DEPS-y) $(CMDS-y) # command to compile a .c file to generate an object ifeq ($(USE_HOST),1) C_TO_O = $(HOSTCC) -Wp,-MD,$(call obj2dep,$(@)).tmp $(HOST_CFLAGS) \ $(CFLAGS_$(@)) $(HOST_EXTRA_CFLAGS) -o $@ -c $< C_TO_O_STR = $(subst ','\'',$(C_TO_O)) #'# fix syntax highlight C_TO_O_DISP = $(if $(V),"$(C_TO_O_STR)"," HOSTCC $(@)") else C_TO_O = $(CC) -Wp,-MD,$(call obj2dep,$(@)).tmp $(CFLAGS) \ $(CFLAGS_$(@)) $(EXTRA_CFLAGS) -o $@ -c $< C_TO_O_STR = $(subst ','\'',$(C_TO_O)) #'# fix syntax highlight C_TO_O_DISP = $(if $(V),"$(C_TO_O_STR)"," CC $(@)") endif C_TO_O_CMD = 'cmd_$@ = $(C_TO_O_STR)' C_TO_O_DO = @set -e; \ echo $(C_TO_O_DISP); \ $(C_TO_O) && \ echo $(C_TO_O_CMD) > $(call obj2cmd,$(@)) && \ sed 's,'$@':,dep_'$@' =,' $(call obj2dep,$(@)).tmp > $(call obj2dep,$(@)) && \ rm -f $(call obj2dep,$(@)).tmp # return an empty string if string are equal compare = $(strip $(subst $(1),,$(2)) $(subst $(2),,$(1))) # return a non-empty string if the dst file does not exist file_missing = $(call compare,$(wildcard $@),$@) # return a non-empty string if cmdline changed cmdline_changed = $(call compare,$(strip $(cmd_$@)),$(strip $(1))) # return a non-empty string if a dependency file does not exist depfile_missing = $(call compare,$(wildcard $(dep_$@)),$(dep_$@)) # return an empty string if no prereq is newer than target # - $^ -> names of all the prerequisites # - $(wildcard $^) -> every existing prereq # - $(filter-out $(wildcard $^),$^) -> every prereq that don't # exist (filter-out removes existing ones from the list) # - $? -> names of all the prerequisites newer than target depfile_newer = $(strip $(filter-out FORCE,$? \ $(filter-out $(wildcard $^),$^))) # return 1 if parameter is a non-empty string, else 0 boolean = $(if $1,1,0) # # Compile .c file if needed # Note: dep_$$@ is from the .d file and DEP_$$@ can be specified by # user (by default it is empty) # .SECONDEXPANSION: %.o: %.c $$(wildcard $$(dep_$$@)) $$(DEP_$$(@)) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(C_TO_O))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer))") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(C_TO_O)),\ $(depfile_missing),\ $(depfile_newer)),\ $(C_TO_O_DO)) # command to assemble a .S file to generate an object ifeq ($(USE_HOST),1) S_TO_O = $(CPP) $(HOST_CPPFLAGS) $($(@)_CPPFLAGS) $(HOST_EXTRA_CPPFLAGS) $< $(@).tmp && \ $(HOSTAS) $(HOST_ASFLAGS) $($(@)_ASFLAGS) $(HOST_EXTRA_ASFLAGS) -o $@ $(@).tmp S_TO_O_STR = $(subst ','\'',$(S_TO_O)) #'# fix syntax highlight S_TO_O_DISP = $(if $(V),"$(S_TO_O_STR)"," HOSTAS $(@)") else S_TO_O = $(CPP) $(CPPFLAGS) $($(@)_CPPFLAGS) $(EXTRA_CPPFLAGS) $< -o $(@).tmp && \ $(AS) $(ASFLAGS) $($(@)_ASFLAGS) $(EXTRA_ASFLAGS) -o $@ $(@).tmp S_TO_O_STR = $(subst ','\'',$(S_TO_O)) #'# fix syntax highlight S_TO_O_DISP = $(if $(V),"$(S_TO_O_STR)"," AS $(@)") endif S_TO_O_CMD = "cmd_$@ = $(S_TO_O_STR)" S_TO_O_DO = @set -e; \ echo $(S_TO_O_DISP); \ $(S_TO_O) && \ echo $(S_TO_O_CMD) > $(call obj2cmd,$(@)) # # Compile .S file if needed # Note: DEP_$$@ can be specified by user (by default it is empty) # %_s.o: %.S $$(DEP_$$@) FORCE @[ ! -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(S_TO_O_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(S_TO_O_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(S_TO_O_DO)) ================================================ FILE: mk/internal/rte.depdirs-post.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .PHONY: depdirs depdirs: @for d in $(DEPDIRS-y); do \ $(RTE_SDK)/scripts/depdirs-rule.sh $(S) $$d ; \ done .PHONY: depgraph depgraph: @for d in $(DEPDIRS-y); do \ echo " \"$(S)\" -> \"$$d\"" ; \ done ================================================ FILE: mk/internal/rte.depdirs-pre.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # nothing ================================================ FILE: mk/internal/rte.extvars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # directory where sources are located # ifdef S ifeq ("$(origin S)", "command line") RTE_SRCDIR := $(abspath $(S)) endif endif RTE_SRCDIR ?= $(CURDIR) export RTE_SRCDIR # # Makefile to call once $(RTE_OUTPUT) is created # ifdef M ifeq ("$(origin M)", "command line") RTE_EXTMK := $(abspath $(M)) endif endif RTE_EXTMK ?= $(RTE_SRCDIR)/Makefile export RTE_EXTMK RTE_SDK_BIN := $(RTE_SDK)/$(RTE_TARGET) # # Output files wil go in a separate directory: default output is # $(RTE_SRCDIR)/build # Output dir can be given as command line using "O=" # ifdef O ifeq ("$(origin O)", "command line") RTE_OUTPUT := $(abspath $(O)) endif endif RTE_OUTPUT ?= $(RTE_SRCDIR)/build export RTE_OUTPUT # if we are building an external application, include SDK # configuration and include project configuration if any include $(RTE_SDK_BIN)/.config ifneq ($(wildcard $(RTE_OUTPUT)/.config),) include $(RTE_OUTPUT)/.config endif # remove double-quotes from config names RTE_ARCH := $(CONFIG_RTE_ARCH:"%"=%) RTE_MACHINE := $(CONFIG_RTE_MACHINE:"%"=%) RTE_EXEC_ENV := $(CONFIG_RTE_EXEC_ENV:"%"=%) RTE_TOOLCHAIN := $(CONFIG_RTE_TOOLCHAIN:"%"=%) ================================================ FILE: mk/internal/rte.install-post.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # install helper .mk # # generate rules to install files in RTE_OUTPUT. # # arg1: relative install dir in RTE_OUTPUT # arg2: relative file name in a source dir (VPATH) # define install_rule $(addprefix $(RTE_OUTPUT)/$(1)/,$(notdir $(2))): $(2) @echo " INSTALL-FILE $(addprefix $(1)/,$(notdir $(2)))" @[ -d $(RTE_OUTPUT)/$(1) ] || mkdir -p $(RTE_OUTPUT)/$(1) $(Q)cp -rf $$(<) $(RTE_OUTPUT)/$(1) endef $(foreach dir,$(INSTALL-DIRS-y),\ $(foreach file,$(INSTALL-y-$(dir)),\ $(eval $(call install_rule,$(dir),$(file))))) # # generate rules to install symbolic links of files in RTE_OUTPUT. # # arg1: relative install dir in RTE_OUTPUT # arg2: relative file name in a source dir (VPATH) # define symlink_rule $(addprefix $(RTE_OUTPUT)/$(1)/,$(notdir $(2))): $(2) @echo " SYMLINK-FILE $(addprefix $(1)/,$(notdir $(2)))" @[ -d $(RTE_OUTPUT)/$(1) ] || mkdir -p $(RTE_OUTPUT)/$(1) $(Q)ln -nsf `$(RTE_SDK)/scripts/relpath.sh $$(<) $(RTE_OUTPUT)/$(1)` \ $(RTE_OUTPUT)/$(1) endef $(foreach dir,$(SYMLINK-DIRS-y),\ $(foreach file,$(SYMLINK-y-$(dir)),\ $(eval $(call symlink_rule,$(dir),$(file))))) # fast way, no need to do preinstall and postinstall ifeq ($(PREINSTALL)$(POSTINSTALL),) _postinstall: $(_INSTALL) @touch _postinstall else # slower way _preinstall: $(PREINSTALL) @touch _preinstall ifneq ($(_INSTALL),) $(_INSTALL): _preinstall else _INSTALL = _preinstall endif _install: $(_INSTALL) @touch _install ifneq ($(POSTINSTALL),) $(POSTINSTALL): _install else POSTINSTALL = _install endif _postinstall: $(POSTINSTALL) @touch _postinstall endif ================================================ FILE: mk/internal/rte.install-pre.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # get all variables starting with "INSTALL-y-", and extract the # installation dir and path # INSTALL-y := $(filter INSTALL-y-%,$(.VARIABLES)) INSTALL-n := $(filter INSTALL-n-%,$(.VARIABLES)) INSTALL- := $(filter INSTALL--%,$(.VARIABLES)) INSTALL-DIRS-y := $(patsubst INSTALL-y-%,%,$(INSTALL-y)) INSTALL-FILES-y := $(foreach i,$(INSTALL-DIRS-y),\ $(addprefix $(RTE_OUTPUT)/$(i)/,$(notdir $(INSTALL-y-$(i))))) INSTALL-FILES-all := $(foreach i,$(INSTALL-DIRS-y) $(INSTALL-DIRS-n) $(INSTALL-DIRS-),\ $(addprefix $(RTE_OUTPUT)/$(i)/,$(notdir $(INSTALL-y-$(i))))) _INSTALL_TARGETS := _preinstall _install _postinstall # # get all variables starting with "SYMLINK-y-", and extract the # installation dir and path # SYMLINK-y := $(filter SYMLINK-y-%,$(.VARIABLES)) SYMLINK-n := $(filter SYMLINK-n-%,$(.VARIABLES)) SYMLINK- := $(filter SYMLINK--%,$(.VARIABLES)) SYMLINK-DIRS-y := $(patsubst SYMLINK-y-%,%,$(SYMLINK-y)) SYMLINK-FILES-y := $(foreach i,$(SYMLINK-DIRS-y),\ $(addprefix $(RTE_OUTPUT)/$(i)/,$(notdir $(SYMLINK-y-$(i))))) SYMLINK-FILES-all := $(foreach i,$(SYMLINK-DIRS-y) $(SYMLINK-DIRS-n) $(SYMLINK-DIRS-),\ $(addprefix $(RTE_OUTPUT)/$(i)/,$(notdir $(SYMLINK-y-$(i))))) _SYMLINK_TARGETS := _presymlink _symlink _postsymlink ================================================ FILE: mk/machine/atm/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=atom ================================================ FILE: mk/machine/default/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS += -march=core2 ================================================ FILE: mk/machine/hsw/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=core-avx2 ================================================ FILE: mk/machine/ivb/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=core-avx-i ================================================ FILE: mk/machine/native/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=native # On FreeBSD systems, sometimes the correct CPU type is not picked up. # To get everything to compile, we need SSE4.2 support, so check if that is # reported by compiler. If not, check if the CPU actually supports it, and if # so, set the compilation target to be a corei7, minimum target with SSE4.2. SSE42_SUPPORT=$(shell $(CC) -march=native -dM -E - /dev/null) ifneq ($(CPU_SSE42_SUPPORT),) MACHINE_CFLAGS = -march=corei7 endif endif ================================================ FILE: mk/machine/nhm/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=corei7 ================================================ FILE: mk/machine/power8/rte.vars.mk ================================================ # BSD LICENSE # # Copyright (C) IBM Corporation 2014. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of IBM Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overridden by cmdline value) # - can define CROSS variable (overridden by cmdline value) # - define MACHINE_CFLAGS variable (overridden by cmdline value) # - define MACHINE_LDFLAGS variable (overridden by cmdline value) # - define MACHINE_ASFLAGS variable (overridden by cmdline value) # - can define CPU_CFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = ================================================ FILE: mk/machine/snb/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=corei7-avx ================================================ FILE: mk/machine/tilegx/rte.vars.mk ================================================ # BSD LICENSE # # Copyright (C) EZchip Semiconductor Ltd. 2015. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of EZchip Semiconductor nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overridden by cmdline value) # - can define CROSS variable (overridden by cmdline value) # - define MACHINE_CFLAGS variable (overridden by cmdline value) # - define MACHINE_LDFLAGS variable (overridden by cmdline value) # - define MACHINE_ASFLAGS variable (overridden by cmdline value) # - can define CPU_CFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overridden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = ================================================ FILE: mk/machine/wsm/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - may override any previously defined variable # # ARCH = # CROSS = # MACHINE_CFLAGS = # MACHINE_LDFLAGS = # MACHINE_ASFLAGS = # CPU_CFLAGS = # CPU_LDFLAGS = # CPU_ASFLAGS = MACHINE_CFLAGS = -march=corei7 -maes -mpclmul ================================================ FILE: mk/rte.app.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # Copyright(c) 2014-2015 6WIND S.A. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(APP) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) _INSTALL += $(RTE_OUTPUT)/app/$(APP) $(RTE_OUTPUT)/app/$(APP).map POSTINSTALL += target-appinstall _CLEAN = doclean POSTCLEAN += target-appclean ifeq ($(NO_LDSCRIPT),) LDSCRIPT = $(RTE_LDSCRIPT) endif # default path for libs _LDLIBS-y += -L$(RTE_SDK_BIN)/lib # # Order is important: from higher level to lower level # _LDLIBS-y += --whole-archive _LDLIBS-$(CONFIG_RTE_BUILD_COMBINE_LIBS) += -l$(RTE_LIBNAME) ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),n) _LDLIBS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += -lrte_distributor _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni _LDLIBS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += -lrte_ivshmem endif _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += -lrte_pipeline _LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += -lrte_table _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += -lrte_port _LDLIBS-$(CONFIG_RTE_LIBRTE_TIMER) += -lrte_timer _LDLIBS-$(CONFIG_RTE_LIBRTE_HASH) += -lrte_hash _LDLIBS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += -lrte_jobstats _LDLIBS-$(CONFIG_RTE_LIBRTE_LPM) += -lrte_lpm _LDLIBS-$(CONFIG_RTE_LIBRTE_POWER) += -lrte_power _LDLIBS-$(CONFIG_RTE_LIBRTE_ACL) += -lrte_acl _LDLIBS-$(CONFIG_RTE_LIBRTE_METER) += -lrte_meter _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lm _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrt _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lrte_vhost endif # ! CONFIG_RTE_BUILD_COMBINE_LIBS _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lpcap ifeq ($(CONFIG_RTE_LIBRTE_VHOST_NUMA),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lnuma endif ifeq ($(CONFIG_RTE_LIBRTE_VHOST_USER),n) _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lfuse endif ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -libverbs endif # ! CONFIG_RTE_BUILD_SHARED_LIBS _LDLIBS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += -lz _LDLIBS-y += --start-group ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),n) _LDLIBS-$(CONFIG_RTE_LIBRTE_KVARGS) += -lrte_kvargs _LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF) += -lrte_mbuf _LDLIBS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += -lrte_ip_frag _LDLIBS-$(CONFIG_RTE_LIBRTE_ETHER) += -lethdev _LDLIBS-$(CONFIG_RTE_LIBRTE_MALLOC) += -lrte_malloc _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lxenstore ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) # plugins (link only if static libraries) _LDLIBS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += -lrte_pmd_vmxnet3_uio _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += -lrte_pmd_virtio _LDLIBS-$(CONFIG_RTE_LIBRTE_BNX2X_PMD) += -lrte_pmd_bnx2x _LDLIBS-$(CONFIG_RTE_LIBRTE_CXGBE_PMD) += -lrte_pmd_cxgbe _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -lrte_pmd_enic _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe _LDLIBS-$(CONFIG_RTE_LIBRTE_E1000_PMD) += -lrte_pmd_e1000 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 _LDLIBS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += -lrte_pmd_mpipe -lgxio _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) += -lrte_pmd_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_AF_PACKET) += -lrte_pmd_af_packet _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL) += -lrte_pmd_null endif # ! $(CONFIG_RTE_BUILD_SHARED_LIB) endif # ! CONFIG_RTE_BUILD_COMBINE_LIBS _LDLIBS-y += $(EXECENV_LDLIBS) _LDLIBS-y += --end-group _LDLIBS-y += --no-whole-archive LDLIBS += $(_LDLIBS-y) $(CPU_LDLIBS) $(EXTRA_LDLIBS) .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) ifeq ($(LINK_USING_CC),1) override EXTRA_LDFLAGS := $(call linkerprefix,$(EXTRA_LDFLAGS)) O_TO_EXE = $(CC) $(CFLAGS) $(LDFLAGS_$(@)) \ -Wl,-Map=$(@).map,--cref -o $@ $(OBJS-y) $(call linkerprefix,$(LDFLAGS)) \ $(EXTRA_LDFLAGS) $(call linkerprefix,$(LDLIBS)) else O_TO_EXE = $(LD) $(LDFLAGS) $(LDFLAGS_$(@)) $(EXTRA_LDFLAGS) \ -Map=$(@).map --cref -o $@ $(OBJS-y) $(LDLIBS) endif O_TO_EXE_STR = $(subst ','\'',$(O_TO_EXE)) #'# fix syntax highlight O_TO_EXE_DISP = $(if $(V),"$(O_TO_EXE_STR)"," LD $(@)") O_TO_EXE_CMD = "cmd_$@ = $(O_TO_EXE_STR)" O_TO_EXE_DO = @set -e; \ echo $(O_TO_EXE_DISP); \ $(O_TO_EXE) && \ echo $(O_TO_EXE_CMD) > $(call exe2cmd,$(@)) -include .$(APP).cmd # path where libraries are retrieved LDLIBS_PATH := $(subst -Wl$(comma)-L,,$(filter -Wl$(comma)-L%,$(LDLIBS))) LDLIBS_PATH += $(subst -L,,$(filter -L%,$(LDLIBS))) # list of .a files that are linked to this application LDLIBS_NAMES := $(patsubst -l%,lib%.a,$(filter -l%,$(LDLIBS))) LDLIBS_NAMES += $(patsubst -Wl$(comma)-l%,lib%.a,$(filter -Wl$(comma)-l%,$(LDLIBS))) # list of found libraries files (useful for deps). If not found, the # library is silently ignored and dep won't be checked LDLIBS_FILES := $(wildcard $(foreach dir,$(LDLIBS_PATH),\ $(addprefix $(dir)/,$(LDLIBS_NAMES)))) # # Compile executable file if needed # $(APP): $(OBJS-y) $(LDLIBS_FILES) $(DEP_$(APP)) $(LDSCRIPT) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_EXE_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_EXE_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_EXE_DO)) # # install app in $(RTE_OUTPUT)/app # $(RTE_OUTPUT)/app/$(APP): $(APP) @echo " INSTALL-APP $(APP)" @[ -d $(RTE_OUTPUT)/app ] || mkdir -p $(RTE_OUTPUT)/app $(Q)cp -f $(APP) $(RTE_OUTPUT)/app # # install app map file in $(RTE_OUTPUT)/app # $(RTE_OUTPUT)/app/$(APP).map: $(APP) @echo " INSTALL-MAP $(APP).map" @[ -d $(RTE_OUTPUT)/app ] || mkdir -p $(RTE_OUTPUT)/app $(Q)cp -f $(APP).map $(RTE_OUTPUT)/app # # Clean all generated files # .PHONY: clean clean: _postclean $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) .PHONY: doclean doclean: $(Q)rm -rf $(APP) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) .$(APP).cmd include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk ifneq ($(wildcard $(RTE_SDK)/mk/target/$(RTE_TARGET)/rte.app.mk),) include $(RTE_SDK)/mk/target/$(RTE_TARGET)/rte.app.mk else include $(RTE_SDK)/mk/target/generic/rte.app.mk endif .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.bsdmodule.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ##### if sourced from kernel Kbuild system ifneq ($(KERNELRELEASE),) override EXTRA_CFLAGS = $(MODULE_CFLAGS) $(EXTRA_KERNEL_CFLAGS) obj-m += $(MODULE).o ifneq ($(MODULE),$(notdir $(SRCS-y:%.c=%))) $(MODULE)-objs += $(notdir $(SRCS-y:%.c=%.o)) endif ##### if launched from rte build system else include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # DPDK uses a more up-to-date gcc, so clear the override here. unexport CC override CFLAGS = $(MODULE_CFLAGS) # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(MODULE).ko _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) \ $(RTE_OUTPUT)/kmod/$(MODULE).ko _CLEAN = doclean SRCS_LINKS = $(addsuffix _link,$(SRCS-y)) compare = $(strip $(subst $(1),,$(2)) $(subst $(2),,$(1))) .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild # Link all sources in build directory %_link: FORCE $(if $(call compare,$(notdir $*),$*),\ $(Q)if [ ! -f $(notdir $(*)) ]; then ln -nfs $(SRCDIR)/$(*) . ; fi,\ $(Q)if [ ! -f $(notdir $(*)) ]; then ln -nfs $(SRCDIR)/$(*) . ; fi) # build module $(MODULE).ko: $(SRCS_LINKS) $(Q)if [ ! -f $(notdir Makefile) ]; then ln -nfs $(SRCDIR)/Makefile . ; fi $(Q)if [ ! -f $(notdir BSDmakefile) ]; then ln -nfs $(SRCDIR)/BSDmakefile . ; fi $(Q)MAKEFLAGS= $(BSDMAKE) # install module in $(RTE_OUTPUT)/kmod $(RTE_OUTPUT)/kmod/$(MODULE).ko: $(MODULE).ko $(Q)echo INSTALL-MODULE $(MODULE).ko $(Q)[ -d $(RTE_OUTPUT)/kmod ] || mkdir -p $(RTE_OUTPUT)/kmod $(Q)cp -f $(MODULE).ko $(RTE_OUTPUT)/kmod # install module modules_install: $(Q)MAKEFLAGS= $(BSDMAKE) install .PHONY: clean clean: _postclean # do a make clean and remove links .PHONY: doclean doclean: $(Q)if [ ! -f $(notdir Makefile) ]; then ln -nfs $(SRCDIR)/Makefile . ; fi $(Q)$(MAKE) -C $(RTE_KERNELDIR) M=$(CURDIR) O=$(RTE_KERNELDIR) clean $(Q)$(foreach FILE,$(SRCS-y) $(SRCS-n) $(SRCS-),\ if [ -h $(notdir $(FILE)) ]; then rm -f $(notdir $(FILE)) ; fi ;) $(Q)if [ -h $(notdir Makefile) ]; then rm -f $(notdir Makefile) ; fi $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) \ $(INSTALL-FILES-all) include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: endif ================================================ FILE: mk/rte.cpuflags.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # this makefile is called from the generic rte.vars.mk and is # used to set the RTE_CPUFLAG_* environment variables giving details # of what instruction sets the target cpu supports. AUTO_CPUFLAGS := $(shell $(CC) $(MACHINE_CFLAGS) -dM -E - < /dev/null) # adding flags to CPUFLAGS ifneq ($(filter $(AUTO_CPUFLAGS),__SSE__),) CPUFLAGS += SSE endif ifneq ($(filter $(AUTO_CPUFLAGS),__SSE2__),) CPUFLAGS += SSE2 endif ifneq ($(filter $(AUTO_CPUFLAGS),__SSE3__),) CPUFLAGS += SSE3 endif ifneq ($(filter $(AUTO_CPUFLAGS),__SSSE3__),) CPUFLAGS += SSSE3 endif ifneq ($(filter $(AUTO_CPUFLAGS),__SSE4_1__),) CPUFLAGS += SSE4_1 endif ifneq ($(filter $(AUTO_CPUFLAGS),__SSE4_2__),) CPUFLAGS += SSE4_2 endif ifneq ($(filter $(AUTO_CPUFLAGS),__AES__),) CPUFLAGS += AES endif ifneq ($(filter $(AUTO_CPUFLAGS),__PCLMUL__),) CPUFLAGS += PCLMULQDQ endif ifneq ($(filter $(AUTO_CPUFLAGS),__AVX__),) CPUFLAGS += AVX endif ifneq ($(filter $(AUTO_CPUFLAGS),__RDRND__),) CPUFLAGS += RDRAND endif ifneq ($(filter $(AUTO_CPUFLAGS),__FSGSBASE__),) CPUFLAGS += FSGSBASE endif ifneq ($(filter $(AUTO_CPUFLAGS),__F16C__),) CPUFLAGS += F16C endif ifneq ($(filter $(AUTO_CPUFLAGS),__AVX2__),) CPUFLAGS += AVX2 endif # IBM Power CPU flags ifneq ($(filter $(AUTO_CPUFLAGS),__PPC64__),) CPUFLAGS += PPC64 endif ifneq ($(filter $(AUTO_CPUFLAGS),__PPC32__),) CPUFLAGS += PPC32 endif ifneq ($(filter $(AUTO_CPUFLAGS),__vector),) CPUFLAGS += ALTIVEC endif ifneq ($(filter $(AUTO_CPUFLAGS),__builtin_vsx_xvnmaddadp),) CPUFLAGS += VSX endif MACHINE_CFLAGS += $(addprefix -DRTE_MACHINE_CPUFLAG_,$(CPUFLAGS)) # To strip whitespace comma:= , empty:= space:= $(empty) $(empty) CPUFLAGSTMP1 := $(addprefix RTE_CPUFLAG_,$(CPUFLAGS)) CPUFLAGSTMP2 := $(subst $(space),$(comma),$(CPUFLAGSTMP1)) MACHINE_CFLAGS += -DRTE_COMPILE_TIME_CPUFLAGS=$(CPUFLAGSTMP2) ================================================ FILE: mk/rte.extapp.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # we must create the output dir first and recall the same Makefile # from this directory ifeq ($(NOT_FIRST_CALL),) NOT_FIRST_CALL = 1 export NOT_FIRST_CALL all: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) %:: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) $@ \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) else include $(RTE_SDK)/mk/rte.app.mk endif ================================================ FILE: mk/rte.extlib.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # we must create the output dir first and recall the same Makefile # from this directory ifeq ($(NOT_FIRST_CALL),) NOT_FIRST_CALL = 1 export NOT_FIRST_CALL all: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) %:: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) $@ \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) else include $(RTE_SDK)/mk/rte.lib.mk endif ================================================ FILE: mk/rte.extobj.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # we must create the output dir first and recall the same Makefile # from this directory ifeq ($(NOT_FIRST_CALL),) NOT_FIRST_CALL = 1 export NOT_FIRST_CALL all: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) %:: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) $@ \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) else include $(RTE_SDK)/mk/rte.obj.mk endif ================================================ FILE: mk/rte.extshared.mk ================================================ # BSD LICENSE # # Copyright 2012-2013 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # we must create the output dir first and recall the same Makefile # from this directory ifeq ($(NOT_FIRST_CALL),) NOT_FIRST_CALL = 1 export NOT_FIRST_CALL all: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) @echo $(RTE_OUTPUT)/lib must be added to /etc/ld.so.conf or \ LD_LIBRARY_PATH variable to allow binary to link with dynamic library %:: $(Q)mkdir -p $(RTE_OUTPUT) $(Q)$(MAKE) -C $(RTE_OUTPUT) -f $(RTE_EXTMK) $@ \ S=$(RTE_SRCDIR) O=$(RTE_OUTPUT) SRCDIR=$(RTE_SRCDIR) else include $(RTE_SDK)/mk/rte.shared.mk endif ================================================ FILE: mk/rte.extsubdir.mk ================================================ # BSD LICENSE # # Copyright(c) 2014 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # output directory O ?= . BASE_OUTPUT ?= $(O) CUR_SUBDIR ?= . .PHONY: all all: $(DIRS-y) .PHONY: clean clean: $(DIRS-y) .PHONY: $(DIRS-y) $(DIRS-y): @echo "== $@" $(Q)$(MAKE) -C $(@) \ M=$(CURDIR)/$(@)/Makefile \ O=$(BASE_OUTPUT)/$(CUR_SUBDIR)/$(@)/$(RTE_TARGET) \ BASE_OUTPUT=$(BASE_OUTPUT) \ CUR_SUBDIR=$(CUR_SUBDIR)/$(@) \ S=$(CURDIR)/$(@) \ $(filter-out $(DIRS-y),$(MAKECMDGOALS)) ================================================ FILE: mk/rte.gnuconfigure.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = configure _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) _CLEAN = doclean .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild configure: $(Q)cd $(CONFIGURE_PATH) ; \ ./configure --prefix $(CONFIGURE_PREFIX) $(CONFIGURE_ARGS) ; \ make ; \ make install .PHONY: clean clean: _postclean .PHONY: doclean doclean: $(Q)cd $(CONFIGURE_PATH) ; make clean $(Q)rm -f $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.hostapp.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # tell rte.compile-pre.mk to use HOSTCC instead of CC USE_HOST := 1 include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(HOSTAPP) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) $(RTE_OUTPUT)/hostapp/$(HOSTAPP) _CLEAN = doclean .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) O_TO_EXE = $(HOSTCC) $(HOST_LDFLAGS) $(LDFLAGS_$(@)) \ $(EXTRA_HOST_LDFLAGS) -o $@ $(OBJS-y) $(LDLIBS) O_TO_EXE_STR = $(subst ','\'',$(O_TO_EXE)) #'# fix syntax highlight O_TO_EXE_DISP = $(if $(V),"$(O_TO_EXE_STR)"," HOSTLD $(@)") O_TO_EXE_CMD = "cmd_$@ = $(O_TO_EXE_STR)" O_TO_EXE_DO = @set -e; \ echo $(O_TO_EXE_DISP); \ $(O_TO_EXE) && \ echo $(O_TO_EXE_CMD) > $(call exe2cmd,$(@)) -include .$(HOSTAPP).cmd # list of .a files that are linked to this application LDLIBS_FILES := $(wildcard \ $(addprefix $(RTE_OUTPUT)/lib/, \ $(patsubst -l%,lib%.a,$(filter -l%,$(LDLIBS))))) # # Compile executable file if needed # $(HOSTAPP): $(OBJS-y) $(LDLIBS_FILES) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$@ -> $< " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_EXE_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_EXE_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_EXE_DO)) # # install app in $(RTE_OUTPUT)/hostapp # $(RTE_OUTPUT)/hostapp/$(HOSTAPP): $(HOSTAPP) @echo " INSTALL-HOSTAPP $(HOSTAPP)" @[ -d $(RTE_OUTPUT)/hostapp ] || mkdir -p $(RTE_OUTPUT)/hostapp $(Q)cp -f $(HOSTAPP) $(RTE_OUTPUT)/hostapp # # Clean all generated files # .PHONY: clean clean: _postclean $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) .PHONY: doclean doclean: $(Q)rm -rf $(HOSTAPP) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) .$(HOSTAPP).cmd include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.hostlib.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # tell rte.compile-pre.mk to use HOSTCC instead of CC USE_HOST := 1 include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(HOSTLIB) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) $(RTE_OUTPUT)/hostlib/$(HOSTLIB) _CLEAN = doclean .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) O_TO_A = $(AR) crus $(HOSTLIB) $(OBJS-y) O_TO_A_STR = $(subst ','\'',$(O_TO_A)) #'# fix syntax highlight O_TO_A_DISP = $(if $(V),"$(O_TO_A_STR)"," HOSTAR $(@)") O_TO_A_CMD = "cmd_$@ = $(O_TO_A_STR)" O_TO_A_DO = @set -e; \ echo $(O_TO_A_DISP); \ $(O_TO_A) && \ echo $(O_TO_A_CMD) > $(call exe2cmd,$(@)) -include .$(HOSTLIB).cmd # # Archive objects in .a file if needed # $(HOSTLIB): $(OBJS-y) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$@ -> $< " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_A_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_A_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_A_DO)) # # install lib in $(RTE_OUTPUT)/hostlib # $(RTE_OUTPUT)/hostlib/$(HOSTLIB): $(HOSTLIB) @echo " INSTALL-HOSTLIB $(HOSTLIB)" @[ -d $(RTE_OUTPUT)/hostlib ] || mkdir -p $(RTE_OUTPUT)/hostlib $(Q)cp -f $(HOSTLIB) $(RTE_OUTPUT)/hostlib # # Clean all generated files # .PHONY: clean clean: _postclean .PHONY: doclean doclean: $(Q)rm -rf $(HOSTLIB) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.install.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # install-only makefile (no build target) include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) _CLEAN = doclean .PHONY: all all: _postinstall @true .PHONY: clean clean: _postclean .PHONY: doclean doclean: @rm -rf $(INSTALL-FILES-all) @rm -f $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk ================================================ FILE: mk/rte.lib.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) LIB := $(patsubst %.a,%.so.$(LIBABIVER),$(LIB)) ifeq ($(CONFIG_RTE_NEXT_ABI),y) LIB := $(LIB).1 endif CPU_LDFLAGS += --version-script=$(SRCDIR)/$(EXPORT_MAP) endif _BUILD = $(LIB) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) $(RTE_OUTPUT)/lib/$(LIB) _CLEAN = doclean .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) ifeq ($(LINK_USING_CC),1) # Override the definition of LD here, since we're linking with CC LD := $(CC) $(CPU_CFLAGS) _CPU_LDFLAGS := $(call linkerprefix,$(CPU_LDFLAGS)) else _CPU_LDFLAGS := $(CPU_LDFLAGS) endif O_TO_A = $(AR) crDs $(LIB) $(OBJS-y) O_TO_A_STR = $(subst ','\'',$(O_TO_A)) #'# fix syntax highlight O_TO_A_DISP = $(if $(V),"$(O_TO_A_STR)"," AR $(@)") O_TO_A_CMD = "cmd_$@ = $(O_TO_A_STR)" O_TO_A_DO = @set -e; \ echo $(O_TO_A_DISP); \ $(O_TO_A) && \ echo $(O_TO_A_CMD) > $(call exe2cmd,$(@)) O_TO_S = $(LD) $(_CPU_LDFLAGS) $(EXTRA_LDFLAGS) $(LDLIBS) -shared $(OBJS-y) \ -Wl,-soname,$(LIB) -o $(LIB) O_TO_S_STR = $(subst ','\'',$(O_TO_S)) #'# fix syntax highlight O_TO_S_DISP = $(if $(V),"$(O_TO_S_STR)"," LD $(@)") O_TO_S_DO = @set -e; \ echo $(O_TO_S_DISP); \ $(O_TO_S) && \ echo $(O_TO_S_CMD) > $(call exe2cmd,$(@)) ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) O_TO_C = $(AR) crus $(LIB_ONE) $(OBJS-y) O_TO_C_STR = $(subst ','\'',$(O_TO_C)) #'# fix syntax highlight O_TO_C_DISP = $(if $(V),"$(O_TO_C_STR)"," AR_C $(@)") O_TO_C_DO = @set -e; \ $(lib_dir) \ $(copy_obj) else O_TO_C = $(LD) -shared $(OBJS-y) -o $(LIB_ONE) O_TO_C_STR = $(subst ','\'',$(O_TO_C)) #'# fix syntax highlight O_TO_C_DISP = $(if $(V),"$(O_TO_C_STR)"," LD_C $(@)") O_TO_C_DO = @set -e; \ $(lib_dir) \ $(copy_obj) endif copy_obj = cp -f $(OBJS-y) $(RTE_OUTPUT)/build/lib; lib_dir = [ -d $(RTE_OUTPUT)/lib ] || mkdir -p $(RTE_OUTPUT)/lib; -include .$(LIB).cmd # # Archive objects in .a file if needed # ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) $(LIB): $(OBJS-y) $(DEP_$(LIB)) FORCE ifeq ($(LIBABIVER),) @echo "Must Specify a $(LIB) ABI version" @false endif @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_S_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_S_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_S_DO)) ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),y) $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_C_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_C_DO)) endif else $(LIB): $(OBJS-y) $(DEP_$(LIB)) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_A_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_A_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_A_DO)) ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),y) $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_C_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_C_DO)) endif endif # # install lib in $(RTE_OUTPUT)/lib # $(RTE_OUTPUT)/lib/$(LIB): $(LIB) @echo " INSTALL-LIB $(LIB)" @[ -d $(RTE_OUTPUT)/lib ] || mkdir -p $(RTE_OUTPUT)/lib $(Q)cp -f $(LIB) $(RTE_OUTPUT)/lib ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) ifeq ($(CONFIG_RTE_NEXT_ABI),y) $(Q)ln -s -f $< $(basename $(basename $@)) else $(Q)ln -s -f $< $(basename $@) endif endif # # Clean all generated files # .PHONY: clean clean: _postclean .PHONY: doclean doclean: $(Q)rm -rf $(LIB) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.module.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ##### if sourced from kernel Kbuild system ifneq ($(KERNELRELEASE),) override EXTRA_CFLAGS = $(MODULE_CFLAGS) $(EXTRA_KERNEL_CFLAGS) obj-m += $(MODULE).o ifneq ($(MODULE),$(notdir $(SRCS-y:%.c=%))) $(MODULE)-objs += $(notdir $(SRCS-y:%.c=%.o)) endif ##### if launched from rte build system else include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(MODULE).ko _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) \ $(RTE_OUTPUT)/kmod/$(MODULE).ko _CLEAN = doclean SRCS_LINKS = $(addsuffix _link,$(SRCS-y)) compare = $(strip $(subst $(1),,$(2)) $(subst $(2),,$(1))) .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild # Link all sources in build directory %_link: FORCE $(if $(call compare,$(notdir $*),$*),\ @if [ ! -f $(notdir $(*)) ]; then ln -nfs $(SRCDIR)/$(*) . ; fi,\ @if [ ! -f $(notdir $(*)) ]; then ln -nfs $(SRCDIR)/$(*) . ; fi) # build module $(MODULE).ko: $(SRCS_LINKS) @if [ ! -f $(notdir Makefile) ]; then ln -nfs $(SRCDIR)/Makefile . ; fi @$(MAKE) -C $(RTE_KERNELDIR) M=$(CURDIR) O=$(RTE_KERNELDIR) \ CC=$(KERNELCC) CROSS_COMPILE=$(CROSS) V=$(if $V,1,0) # install module in $(RTE_OUTPUT)/kmod $(RTE_OUTPUT)/kmod/$(MODULE).ko: $(MODULE).ko @echo INSTALL-MODULE $(MODULE).ko @[ -d $(RTE_OUTPUT)/kmod ] || mkdir -p $(RTE_OUTPUT)/kmod @cp -f $(MODULE).ko $(RTE_OUTPUT)/kmod # install module modules_install: @$(MAKE) -C $(RTE_KERNELDIR) M=$(CURDIR) O=$(RTE_KERNELDIR) \ modules_install .PHONY: clean clean: _postclean # do a make clean and remove links .PHONY: doclean doclean: @if [ ! -f $(notdir Makefile) ]; then ln -nfs $(SRCDIR)/Makefile . ; fi $(Q)$(MAKE) -C $(RTE_KERNELDIR) M=$(CURDIR) O=$(RTE_KERNELDIR) clean @$(foreach FILE,$(SRCS-y) $(SRCS-n) $(SRCS-),\ if [ -h $(notdir $(FILE)) ]; then rm -f $(notdir $(FILE)) ; fi ;) @if [ -h $(notdir Makefile) ]; then rm -f $(notdir Makefile) ; fi @rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) \ $(INSTALL-FILES-all) include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: endif ================================================ FILE: mk/rte.obj.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) ifneq ($(OBJ),) _BUILD = $(OBJ) else _BUILD = $(OBJS-y) endif _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) _CLEAN = doclean .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild ifneq ($(OBJ),) exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) O_TO_O = $(LD) -r -o $(OBJ) $(OBJS-y) O_TO_O_STR = $(subst ','\'',$(O_TO_O)) #'# fix syntax highlight O_TO_O_DISP = $(if $(V),"$(O_TO_O_STR)"," LD $(@)") O_TO_O_CMD = "cmd_$@ = $(O_TO_O_STR)" O_TO_O_DO = @set -e; \ echo $(O_TO_O_DISP); \ $(O_TO_O) && \ echo $(O_TO_O_CMD) > $(call exe2cmd,$(@)) -include .$(OBJ).cmd # # Archive objects in .a file if needed # $(OBJ): $(OBJS-y) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_O_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_O_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_O_DO)) endif # # Clean all generated files # .PHONY: clean clean: _postclean .PHONY: doclean doclean: @rm -rf $(OBJ) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) @rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.sdkbuild.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # If DESTDIR variable is given, install binary dpdk # # include rte.vars.mk if config file exists # ifeq (,$(wildcard $(RTE_OUTPUT)/.config)) $(error "need a make config first") else include $(RTE_SDK)/mk/rte.vars.mk endif # # include .depdirs and define rules to order priorities between build # of directories. # -include $(RTE_OUTPUT)/.depdirs define depdirs_rule $(1): $(sort $(LOCAL_DEPDIRS-$(1))) endef $(foreach d,$(ROOTDIRS-y),$(eval $(call depdirs_rule,$(d)))) # # build and clean targets # CLEANDIRS = $(addsuffix _clean,$(ROOTDIRS-y) $(ROOTDIRS-n) $(ROOTDIRS-)) .PHONY: build build: $(ROOTDIRS-y) @echo "Build complete [$(RTE_TARGET)]" ifneq ($(DESTDIR),) $(Q)mkdir -p $(DESTDIR) $(Q)tar -C $(RTE_SDK) -cf - mk scripts/*.sh | tar -C $(DESTDIR) -x \ --keep-newer-files --warning=no-ignore-newer -f - $(Q)mkdir -p $(DESTDIR)/`basename $(RTE_OUTPUT)` $(Q)tar -C $(RTE_OUTPUT) -chf - \ --exclude app --exclude hostapp --exclude build \ --exclude Makefile --exclude .depdirs . | \ tar -C $(DESTDIR)/`basename $(RTE_OUTPUT)` -x --keep-newer-files \ --warning=no-ignore-newer -f - $(Q)install -D $(RTE_OUTPUT)/app/testpmd \ $(DESTDIR)/`basename $(RTE_OUTPUT)`/app/testpmd @echo Installation in $(DESTDIR) complete endif .PHONY: clean clean: $(CLEANDIRS) @rm -rf $(RTE_OUTPUT)/include $(RTE_OUTPUT)/app \ $(RTE_OUTPUT)/hostapp $(RTE_OUTPUT)/lib \ $(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod @[ -d $(RTE_OUTPUT)/include ] || mkdir -p $(RTE_OUTPUT)/include @$(RTE_SDK)/scripts/gen-config-h.sh $(RTE_OUTPUT)/.config \ > $(RTE_OUTPUT)/include/rte_config.h $(Q)$(MAKE) -f $(RTE_SDK)/GNUmakefile gcovclean @echo Clean complete .SECONDEXPANSION: .PHONY: $(ROOTDIRS-y) $(ROOTDIRS-y): @[ -d $(BUILDDIR)/$@ ] || mkdir -p $(BUILDDIR)/$@ @echo "== Build $@" $(Q)$(MAKE) S=$@ -f $(RTE_SRCDIR)/$@/Makefile -C $(BUILDDIR)/$@ all @if [ $@ = drivers -a $(CONFIG_RTE_BUILD_COMBINE_LIBS) = y ]; then \ $(MAKE) -f $(RTE_SDK)/lib/Makefile sharelib; \ fi %_clean: @echo "== Clean $*" $(Q)if [ -f $(RTE_SRCDIR)/$*/Makefile -a -d $(BUILDDIR)/$* ]; then \ $(MAKE) S=$* -f $(RTE_SRCDIR)/$*/Makefile -C $(BUILDDIR)/$* clean ; \ fi RTE_MAKE_SUBTARGET ?= all %_sub: $(addsuffix _sub,$(FULL_DEPDIRS-$(*))) @echo $(addsuffix _sub,$(FULL_DEPDIRS-$(*))) @[ -d $(BUILDDIR)/$* ] || mkdir -p $(BUILDDIR)/$* @echo "== Build $*" $(Q)$(MAKE) S=$* -f $(RTE_SRCDIR)/$*/Makefile -C $(BUILDDIR)/$* \ $(RTE_MAKE_SUBTARGET) .PHONY: all all: build .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.sdkconfig.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .PHONY: showversion showversion: @set -- \ $$(sed -rne 's,^#define RTE_VER_[A-Z_]*[[:space:]]+([0-9]+).*,\1,p' \ -e 's,^#define RTE_VER_SUFFIX[[:space:]]+"(.*)",\1,p' \ $(RTE_SRCDIR)/lib/librte_eal/common/include/rte_version.h) ;\ printf '%d.%d.%d' "$$1" "$$2" "$$3"; \ if [ -z "$$5" ]; then echo; \ else printf '%s' "$$4"; \ if [ $$5 -lt 16 ] ; then echo $$5; \ else echo $$(($$5 - 16)); fi; \ fi INSTALL_CONFIGS := $(sort $(filter-out %~,\ $(patsubst $(RTE_SRCDIR)/config/defconfig_%,%,\ $(wildcard $(RTE_SRCDIR)/config/defconfig_*)))) INSTALL_TARGETS := $(addsuffix _install,$(INSTALL_CONFIGS)) .PHONY: showconfigs showconfigs: @$(foreach CONFIG, $(INSTALL_CONFIGS), echo $(CONFIG);) .PHONY: notemplate notemplate: @printf "No template specified. " @echo "Use T=template among the following list:" @$(MAKE) -rR showconfigs | sed 's,^, ,' .PHONY: config ifeq ($(RTE_CONFIG_TEMPLATE),) config: notemplate else config: $(RTE_OUTPUT)/include/rte_config.h $(RTE_OUTPUT)/Makefile $(Q)$(MAKE) depdirs @echo "Configuration done" endif $(RTE_OUTPUT): $(Q)mkdir -p $@ ifdef NODOTCONF $(RTE_OUTPUT)/.config: ; else $(RTE_OUTPUT)/.config: $(RTE_CONFIG_TEMPLATE) FORCE | $(RTE_OUTPUT) $(Q)if [ "$(RTE_CONFIG_TEMPLATE)" != "" -a -f "$(RTE_CONFIG_TEMPLATE)" ]; then \ $(CPP) -undef -P -x assembler-with-cpp \ -ffreestanding \ -o $(RTE_OUTPUT)/.config_tmp $(RTE_CONFIG_TEMPLATE) ; \ if ! cmp -s $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config; then \ cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config ; \ cp $(RTE_OUTPUT)/.config_tmp $(RTE_OUTPUT)/.config.orig ; \ fi ; \ rm -f $(RTE_OUTPUT)/.config_tmp ; \ else \ $(MAKE) -rRf $(RTE_SDK)/mk/rte.sdkconfig.mk notemplate; \ fi endif # generate a Makefile for this build directory # use a relative path so it will continue to work even if we move the directory SDK_RELPATH=$(shell $(RTE_SDK)/scripts/relpath.sh $(abspath $(RTE_SRCDIR)) \ $(abspath $(RTE_OUTPUT))) OUTPUT_RELPATH=$(shell $(RTE_SDK)/scripts/relpath.sh $(abspath $(RTE_OUTPUT)) \ $(abspath $(RTE_SRCDIR))) $(RTE_OUTPUT)/Makefile: | $(RTE_OUTPUT) $(Q)$(RTE_SDK)/scripts/gen-build-mk.sh $(SDK_RELPATH) $(OUTPUT_RELPATH) \ > $(RTE_OUTPUT)/Makefile # clean installed files, and generate a new config header file # if NODOTCONF variable is defined, don't try to rebuild .config $(RTE_OUTPUT)/include/rte_config.h: $(RTE_OUTPUT)/.config $(Q)rm -rf $(RTE_OUTPUT)/include $(RTE_OUTPUT)/app \ $(RTE_OUTPUT)/hostapp $(RTE_OUTPUT)/lib \ $(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod $(RTE_OUTPUT)/build $(Q)mkdir -p $(RTE_OUTPUT)/include $(Q)$(RTE_SDK)/scripts/gen-config-h.sh $(RTE_OUTPUT)/.config \ > $(RTE_OUTPUT)/include/rte_config.h # generate the rte_config.h .PHONY: headerconfig headerconfig: $(RTE_OUTPUT)/include/rte_config.h @true # check that .config is present, and if yes, check that rte_config.h # is up to date .PHONY: checkconfig checkconfig: @if [ ! -f $(RTE_OUTPUT)/.config ]; then \ echo "No .config in build directory"; \ exit 1; \ fi $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk \ headerconfig NODOTCONF=1 $(Q)$(MAKE) -s depdirs .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.sdkdepdirs.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq (,$(wildcard $(RTE_OUTPUT)/.config)) $(error "need a make config first") endif ifeq (,$(wildcard $(RTE_OUTPUT)/Makefile)) $(error "need a make config first") endif # use a "for" in a shell to process dependencies: we don't want this # task to be run in parallel. .PHONY: depdirs depdirs: $(RTE_OUTPUT)/.depdirs $(RTE_OUTPUT)/.depdirs: $(RTE_OUTPUT)/.config @rm -f $(RTE_OUTPUT)/.depdirs ; \ for d in $(ROOTDIRS-y); do \ if [ -f $(RTE_SRCDIR)/$$d/Makefile ]; then \ [ -d $(BUILDDIR)/$$d ] || mkdir -p $(BUILDDIR)/$$d ; \ $(MAKE) S=$$d -f $(RTE_SRCDIR)/$$d/Makefile depdirs \ >> $(RTE_OUTPUT)/.depdirs ; \ fi ; \ done .PHONY: depgraph depgraph: @echo "digraph unix {" ; \ echo " size=\"6,6\";" ; \ echo " node [color=lightblue2, style=filled];" ; \ for d in $(ROOTDIRS-y); do \ echo " \"root\" -> \"$$d\"" ; \ if [ -f $(RTE_SRCDIR)/$$d/Makefile ]; then \ $(MAKE) S=$$d -f $(RTE_SRCDIR)/$$d/Makefile depgraph ; \ fi ; \ done ; \ echo "}" ================================================ FILE: mk/rte.sdkdoc.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2015 Intel Corporation. All rights reserved. # Copyright(c) 2013-2015 6WIND S.A. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifdef T ifeq ("$(origin T)", "command line") $(error "Cannot use T= with doc target") endif endif RTE_SPHINX_BUILD = sphinx-build RTE_PDFLATEX_VERBOSE := --interaction=nonstopmode ifndef V RTE_SPHINX_VERBOSE := -q RTE_PDFLATEX_VERBOSE := --interaction=batchmode RTE_INKSCAPE_VERBOSE := >/dev/null 2>&1 endif ifeq '$V' '0' RTE_SPHINX_VERBOSE := -q RTE_PDFLATEX_VERBOSE := --interaction=batchmode RTE_INKSCAPE_VERBOSE := >/dev/null 2>&1 endif RTE_PDF_DPI ?= 300 RTE_GUIDES := $(filter %/, $(wildcard $(RTE_SDK)/doc/guides/*/)) .PHONY: help help: @cat $(RTE_SDK)/doc/build-sdk-quick.txt @$(MAKE) -rR showconfigs | sed 's,^,\t\t\t\t,' .PHONY: all all: api-html guides-html guides-pdf .PHONY: clean clean: api-html-clean guides-html-clean guides-pdf-clean .PHONY: api-html api-html: api-html-clean @echo 'doxygen for API...' $(Q)mkdir -p $(RTE_OUTPUT)/doc/html $(Q)(cat $(RTE_SDK)/doc/api/doxy-api.conf && \ printf 'PROJECT_NUMBER = ' && \ $(MAKE) -rR showversion && \ echo OUTPUT_DIRECTORY = $(RTE_OUTPUT)/doc && \ echo HTML_OUTPUT = html/api && \ echo GENERATE_HTML = YES && \ echo GENERATE_LATEX = NO && \ echo GENERATE_MAN = NO )| \ doxygen - $(Q)$(RTE_SDK)/doc/api/doxy-html-custom.sh $(RTE_OUTPUT)/doc/html/api/doxygen.css .PHONY: api-html-clean api-html-clean: $(Q)rm -f $(RTE_OUTPUT)/doc/html/api/* $(Q)rmdir -p --ignore-fail-on-non-empty $(RTE_OUTPUT)/doc/html/api 2>&- || true guides-pdf-clean: guides-pdf-img-clean guides-pdf-img-clean: $(Q)rm -f $(RTE_SDK)/doc/guides/*/img/*.pdf guides-%-clean: $(Q)rm -rf $(RTE_OUTPUT)/doc/$*/guides $(Q)rmdir -p --ignore-fail-on-non-empty $(RTE_OUTPUT)/doc/$* 2>&- || true guides-pdf: $(addprefix guides-pdf-, $(notdir $(RTE_GUIDES:/=))) ; guides-pdf-%: @echo 'sphinx processing $@...' $(Q)$(RTE_SPHINX_BUILD) -b latex $(RTE_SPHINX_VERBOSE) \ -c $(RTE_SDK)/doc/guides $(RTE_SDK)/doc/guides/$* \ $(RTE_OUTPUT)/doc/pdf/guides/$* $(if $^,$(Q)rm -f $^) @echo 'pdflatex processing $@...' $(Q)$(MAKE) all-pdf -sC $(RTE_OUTPUT)/doc/pdf/guides/$* \ LATEXOPTS=$(RTE_PDFLATEX_VERBOSE) $(Q)mv $(RTE_OUTPUT)/doc/pdf/guides/$*/doc.pdf \ $(RTE_OUTPUT)/doc/pdf/guides/$*.pdf guides-%: @echo 'sphinx processing $@...' $(Q)$(RTE_SPHINX_BUILD) -b $* $(RTE_SPHINX_VERBOSE) \ -c $(RTE_SDK)/doc/guides $(RTE_SDK)/doc/guides \ $(RTE_OUTPUT)/doc/$*/guides # Each PDF depends on generated images *.pdf from *.svg $(foreach guide, $(RTE_GUIDES), $(foreach img, $(wildcard $(guide)img/*.svg), \ $(eval guides-pdf-$(notdir $(guide:/=)): $(img:svg=pdf)))) %.pdf: %.svg $(Q)inkscape -d $(RTE_PDF_DPI) -D -f $< -A $@ $(RTE_INKSCAPE_VERBOSE) ================================================ FILE: mk/rte.sdkexamples.mk ================================================ # BSD LICENSE # # Copyright(c) 2014 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # examples application are seen as external applications which are # not part of SDK. BUILDING_RTE_SDK := export BUILDING_RTE_SDK # Build directory is given with O= O ?= $(RTE_SDK)/examples # Target for which examples should be built. T ?= * # list all available configurations EXAMPLES_CONFIGS := $(patsubst $(RTE_SRCDIR)/config/defconfig_%,%,\ $(wildcard $(RTE_SRCDIR)/config/defconfig_$(T))) EXAMPLES_TARGETS := $(addsuffix _examples,\ $(filter-out %~,$(EXAMPLES_CONFIGS))) .PHONY: examples examples: $(EXAMPLES_TARGETS) %_examples: @echo ================== Build examples for $* $(Q)if [ ! -d "${RTE_SDK}/${*}" ]; then \ echo "Target ${*} does not exist in ${RTE_SDK}/${*}." ; \ echo -n "Please install DPDK first (make install) or use another " ; \ echo "target argument (T=target)." ; \ false ; \ else \ $(MAKE) -C examples O=$(abspath $(O)) RTE_TARGET=$(*); \ fi EXAMPLES_CLEAN_TARGETS := $(addsuffix _examples_clean,\ $(filter-out %~,$(EXAMPLES_CONFIGS))) .PHONY: examples_clean examples_clean: $(EXAMPLES_CLEAN_TARGETS) %_examples_clean: @echo ================== Clean examples for $* $(Q)if [ ! -d "${RTE_SDK}/${*}" ]; then \ echo "Target ${*} does not exist in ${RTE_SDK}/${*}." ; \ echo -n "Please install DPDK first (make install) or use another " ; \ echo "target argument (T=target)." ; \ false ; \ else \ $(MAKE) -C examples O=$(abspath $(O)) RTE_TARGET=$(*) clean; \ fi ================================================ FILE: mk/rte.sdkgcov.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifdef T ifeq ("$(origin T)", "command line") $(error "Cannot use T= with gcov target") endif endif ifeq (,$(wildcard $(RTE_OUTPUT)/.config)) $(error "need a make config first") else include $(RTE_SDK)/mk/rte.vars.mk endif ifeq (,$(wildcard $(RTE_OUTPUT)/Makefile)) $(error "need a make config first") endif INPUTDIR = $(RTE_OUTPUT) OUTPUTDIR = $(RTE_OUTPUT)/gcov .PHONY: gcovclean gcovclean: $(Q)find $(INPUTDIR)/build -name "*.gcno" -o -name "*.gcda" -exec rm {} \; $(Q)rm -rf $(OUTPUTDIR) .PHONY: gcov gcov: $(Q)for APP in test ; do \ mkdir -p $(OUTPUTDIR)/$$APP ; cd $(OUTPUTDIR)/$$APP ; \ for FIC in `strings $(RTE_OUTPUT)/app/$$APP | grep gcda | sed s,gcda,o,` ; do \ SUBDIR=`basename $$FIC`;\ mkdir $$SUBDIR ;\ cd $$SUBDIR ;\ $(GCOV) $(RTE_OUTPUT)/app/$$APP -o $$FIC > gcov.log; \ cd - >/dev/null;\ done ; \ cd - >/dev/null; \ done ================================================ FILE: mk/rte.sdkinstall.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Build directory is given with O= ifdef O BUILD_DIR=$(O) else BUILD_DIR=. endif # Targets to install can be specified in command line. It can be a # target name or a name containing jokers "*". Example: # x86_64-native-*-gcc ifndef T T=* endif # # install: build sdk for all supported targets # INSTALL_CONFIGS := $(patsubst $(RTE_SRCDIR)/config/defconfig_%,%,\ $(wildcard $(RTE_SRCDIR)/config/defconfig_$(T))) INSTALL_TARGETS := $(addsuffix _install,\ $(filter-out %~,$(INSTALL_CONFIGS))) .PHONY: install install: $(INSTALL_TARGETS) %_install: @echo ================== Installing $* $(Q)if [ ! -f $(BUILD_DIR)/$*/.config ]; then \ $(MAKE) config T=$* O=$(BUILD_DIR)/$*; \ elif cmp -s $(BUILD_DIR)/$*/.config.orig $(BUILD_DIR)/$*/.config; then \ $(MAKE) config T=$* O=$(BUILD_DIR)/$*; \ else \ if [ -f $(BUILD_DIR)/$*/.config.orig ] ; then \ tmp_build=$(BUILD_DIR)/$*/.config.tmp; \ $(MAKE) config T=$* O=$$tmp_build; \ if ! cmp -s $(BUILD_DIR)/$*/.config.orig $$tmp_build/.config ; then \ echo "Conflict: local config and template config have both changed"; \ exit 1; \ fi; \ fi; \ echo "Using local configuration"; \ fi $(Q)$(MAKE) all O=$(BUILD_DIR)/$* # # uninstall: remove all built sdk # UNINSTALL_TARGETS := $(addsuffix _uninstall,\ $(filter-out %~,$(INSTALL_CONFIGS))) .PHONY: uninstall uninstall: $(UNINSTALL_TARGETS) %_uninstall: @echo ================== Uninstalling $* $(Q)rm -rf $(BUILD_DIR)/$* ================================================ FILE: mk/rte.sdkroot.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAKEFLAGS += --no-print-directory # define Q to '@' or not. $(Q) is used to prefix all shell commands to # be executed silently. Q=@ ifdef V ifeq ("$(origin V)", "command line") Q= endif endif export Q ifeq ($(RTE_SDK),) $(error RTE_SDK is not defined) endif RTE_SRCDIR = $(CURDIR) export RTE_SRCDIR BUILDING_RTE_SDK := 1 export BUILDING_RTE_SDK # # We can specify the configuration template when doing the "make # config". For instance: make config T=x86_64-native-linuxapp-gcc # RTE_CONFIG_TEMPLATE := ifdef T ifeq ("$(origin T)", "command line") RTE_CONFIG_TEMPLATE := $(RTE_SRCDIR)/config/defconfig_$(T) endif endif export RTE_CONFIG_TEMPLATE # # Default output is $(RTE_SRCDIR)/build # output files wil go in a separate directory # ifdef O ifeq ("$(origin O)", "command line") RTE_OUTPUT := $(abspath $(O)) endif endif RTE_OUTPUT ?= $(RTE_SRCDIR)/build export RTE_OUTPUT # the directory where intermediate build files are stored, like *.o, # *.d, *.cmd, ... BUILDDIR = $(RTE_OUTPUT)/build export BUILDDIR export ROOTDIRS-y ROOTDIRS- ROOTDIRS-n .PHONY: default default: all .PHONY: config showconfigs showversion config showconfigs showversion: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk $@ .PHONY: test fast_test ring_test mempool_test perf_test coverage test fast_test ring_test mempool_test perf_test coverage: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdktest.mk $@ .PHONY: testall testall: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdktestall.mk $@ .PHONY: install uninstall install uninstall: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkinstall.mk $@ .PHONY: doc help doc: doc-all help: doc-help doc-%: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkdoc.mk $* .PHONY: depdirs depgraph depdirs depgraph: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkdepdirs.mk $@ .PHONY: gcov gcovclean gcov gcovclean: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkgcov.mk $@ .PHONY: examples examples_clean examples examples_clean: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkexamples.mk $@ # all other build targets %: $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkconfig.mk checkconfig $(Q)$(MAKE) -f $(RTE_SDK)/mk/rte.sdkbuild.mk $@ ================================================ FILE: mk/rte.sdktest.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifeq (,$(wildcard $(RTE_OUTPUT)/.config)) $(error "need a make config first") else include $(RTE_SDK)/mk/rte.vars.mk endif ifeq (,$(wildcard $(RTE_OUTPUT)/Makefile)) $(error "need a make config first") endif DATE := $(shell date '+%Y%m%d-%H%M') AUTOTEST_DIR := $(RTE_OUTPUT)/autotest-$(DATE) DIR := $(shell basename $(RTE_OUTPUT)) # # test: launch auto-tests, very simple for now. # PHONY: test fast_test coverage: BLACKLIST=-Mempool_perf,Memcpy_perf,Hash_perf fast_test: BLACKLIST=-Ring_perf,Mempool_perf,Memcpy_perf,Hash_perf,Lpm6 ring_test: WHITELIST=Ring,Ring_perf mempool_test: WHITELIST=Mempool,Mempool_perf perf_test:WHITELIST=Mempool_perf,Memcpy_perf,Hash_perf,Ring_perf test fast_test ring_test mempool_test perf_test: @mkdir -p $(AUTOTEST_DIR) ; \ cd $(AUTOTEST_DIR) ; \ if [ -f $(RTE_OUTPUT)/app/test ]; then \ python $(RTE_SDK)/app/test/autotest.py \ $(RTE_OUTPUT)/app/test \ $(RTE_TARGET) \ $(BLACKLIST) $(WHITELIST); \ else \ echo "No test found, please do a 'make build' first, or specify O=" ; \ fi # this is a special target to ease the pain of running coverage tests # this runs all the autotests, cmdline_test script and proc_info coverage: @mkdir -p $(AUTOTEST_DIR) ; \ cd $(AUTOTEST_DIR) ; \ if [ -f $(RTE_OUTPUT)/app/test ]; then \ python $(RTE_SDK)/app/cmdline_test/cmdline_test.py \ $(RTE_OUTPUT)/app/cmdline_test; \ ulimit -S -n 100 ; \ python $(RTE_SDK)/app/test/autotest.py \ $(RTE_OUTPUT)/app/test \ $(RTE_TARGET) \ $(BLACKLIST) $(WHITELIST) ; \ $(RTE_OUTPUT)/app/proc_info --file-prefix=ring_perf -- -m; \ else \ echo "No test found, please do a 'make build' first, or specify O=" ;\ fi ================================================ FILE: mk/rte.sdktestall.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ifdef O ifeq ("$(origin O)", "command line") $(error "Cannot use O= with testall target") endif endif # Targets to test can be specified in command line. It can be a # target name or a name containing jokers "*". Example: # x86_64-native-*-gcc ifndef T T=* endif # # testall: launch test for all supported targets # TESTALL_CONFIGS := $(patsubst $(RTE_SRCDIR)/config/defconfig_%,%,\ $(wildcard $(RTE_SRCDIR)/config/defconfig_$(T))) TESTALL_TARGETS := $(addsuffix _testall,\ $(filter-out %~,$(TESTALL_CONFIGS))) .PHONY: testall testall: $(TESTALL_TARGETS) %_testall: @echo ================== Test $* $(Q)$(MAKE) fast_test O=$* ================================================ FILE: mk/rte.shared.mk ================================================ # BSD LICENSE # # Copyright 2012-2013 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.compile-pre.mk include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) _BUILD = $(SHARED) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) $(RTE_OUTPUT)/lib/$(SHARED) _CLEAN = doclean # Set fPIC in CFLAGS for .so generation CFLAGS += -fPIC .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) ifeq ($(LINK_USING_CC),1) override EXTRA_LDFLAGS := $(call linkerprefix,$(EXTRA_LDFLAGS)) O_TO_SO = $(CC) $(call linkerprefix,$(LDFLAGS)) $(LDFLAGS_$(@)) $(EXTRA_LDFLAGS) \ -shared -o $@ $(OBJS-y) $(call linkerprefix,$(LDLIBS)) else O_TO_SO = $(LD) $(LDFLAGS) $(LDFLAGS_$(@)) $(EXTRA_LDFLAGS) \ -shared -o $@ $(OBJS-y) $(LDLIBS) endif O_TO_SO_STR = $(subst ','\'',$(O_TO_SO)) #'# fix syntax highlight O_TO_SO_DISP = $(if $(V),"$(O_TO_SO_STR)"," LD $(@)") O_TO_SO_CMD = "cmd_$@ = $(O_TO_SO_STR)" O_TO_SO_DO = @set -e; \ echo $(O_TO_SO_DISP); \ $(O_TO_SO) && \ echo $(O_TO_SO_CMD) > $(call exe2cmd,$(@)) -include .$(SHARED).cmd # path where libraries are retrieved LDLIBS_PATH := $(subst -Wl$(comma)-L,,$(filter -Wl$(comma)-L%,$(LDLIBS))) LDLIBS_PATH += $(subst -L,,$(filter -L%,$(LDLIBS))) # list of .a files that are linked to this application LDLIBS_NAMES := $(patsubst -l%,lib%.a,$(filter -l%,$(LDLIBS))) LDLIBS_NAMES += $(patsubst -Wl$(comma)-l%,lib%.a,$(filter -Wl$(comma)-l%,$(LDLIBS))) # list of found libraries files (useful for deps). If not found, the # library is silently ignored and dep won't be checked LDLIBS_FILES := $(wildcard $(foreach dir,$(LDLIBS_PATH),\ $(addprefix $(dir)/,$(LDLIBS_NAMES)))) # # Archive objects in .so file if needed # $(SHARED): $(OBJS-y) $(LDLIBS_FILES) $(DEP_$(SHARED)) FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(if $(D),\ @echo -n "$< -> $@ " ; \ echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_SO_STR))) " ; \ echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ echo "depfile_newer=$(call boolean,$(depfile_newer)) ") $(if $(or \ $(file_missing),\ $(call cmdline_changed,$(O_TO_SO_STR)),\ $(depfile_missing),\ $(depfile_newer)),\ $(O_TO_SO_DO)) # # install lib in $(RTE_OUTPUT)/lib # $(RTE_OUTPUT)/lib/$(SHARED): $(SHARED) @echo " INSTALL-SHARED $(SHARED)" @[ -d $(RTE_OUTPUT)/lib ] || mkdir -p $(RTE_OUTPUT)/lib $(Q)cp -f $(SHARED) $(RTE_OUTPUT)/lib # # Clean all generated files # .PHONY: clean clean: _postclean .PHONY: doclean doclean: $(Q)rm -rf $(SHARED) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ $(CMDS-all) $(INSTALL-FILES-all) $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) include $(RTE_SDK)/mk/internal/rte.compile-post.mk include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.sharelib.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include $(RTE_SDK)/mk/internal/rte.build-pre.mk # VPATH contains at least SRCDIR VPATH += $(SRCDIR) ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),y) ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) LIB_ONE := lib$(RTE_LIBNAME).so else LIB_ONE := lib$(RTE_LIBNAME).a endif endif .PHONY:sharelib sharelib: $(LIB_ONE) FORCE OBJS = $(wildcard $(RTE_OUTPUT)/build/lib/*.o) ifeq ($(LINK_USING_CC),1) # Override the definition of LD here, since we're linking with CC LD := $(CC) $(CPU_CFLAGS) O_TO_S = $(LD) $(call linkerprefix,$(CPU_LDFLAGS)) \ -shared $(OBJS) -o $(RTE_OUTPUT)/lib/$(LIB_ONE) else O_TO_S = $(LD) $(CPU_LDFLAGS) \ -shared $(OBJS) -o $(RTE_OUTPUT)/lib/$(LIB_ONE) endif O_TO_S_STR = $(subst ','\'',$(O_TO_S)) #'# fix syntax highlight O_TO_S_DISP = $(if $(V),"$(O_TO_S_STR)"," LD $(@)") O_TO_S_CMD = "cmd_$@ = $(O_TO_S_STR)" O_TO_S_DO = @set -e; \ echo $(O_TO_S_DISP); \ $(O_TO_S) O_TO_A = $(AR) crus $(RTE_OUTPUT)/lib/$(LIB_ONE) $(OBJS) O_TO_A_STR = $(subst ','\'',$(O_TO_A)) #'# fix syntax highlight O_TO_A_DISP = $(if $(V),"$(O_TO_A_STR)"," LD $(@)") O_TO_A_CMD = "cmd_$@ = $(O_TO_A_STR)" O_TO_A_DO = @set -e; \ echo $(O_TO_A_DISP); \ $(O_TO_A) # # Archive objects to share library # ifeq ($(CONFIG_RTE_BUILD_COMBINE_LIBS),y) ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) $(LIB_ONE): FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(O_TO_S_DO) else $(LIB_ONE): FORCE @[ -d $(dir $@) ] || mkdir -p $(dir $@) $(O_TO_A_DO) endif endif # # Clean all generated files # .PHONY: clean clean: _postclean .PHONY: doclean doclean: $(Q)rm -rf $(LIB_ONE) .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.subdir.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # .mk to build subdirectories # include $(RTE_SDK)/mk/internal/rte.install-pre.mk include $(RTE_SDK)/mk/internal/rte.clean-pre.mk include $(RTE_SDK)/mk/internal/rte.build-pre.mk CLEANDIRS = $(addsuffix _clean,$(DIRS-y) $(DIRS-n) $(DIRS-)) VPATH += $(SRCDIR) _BUILD = $(DIRS-y) _INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) _CLEAN = $(CLEANDIRS) .PHONY: all all: install .PHONY: install install: build _postinstall _postinstall: build .PHONY: build build: _postbuild .SECONDEXPANSION: .PHONY: $(DIRS-y) $(DIRS-y): @[ -d $(CURDIR)/$@ ] || mkdir -p $(CURDIR)/$@ @echo "== Build $S/$@" @$(MAKE) S=$S/$@ -f $(SRCDIR)/$@/Makefile -C $(CURDIR)/$@ all .PHONY: clean clean: _postclean %_clean: @echo "== Clean $S/$*" @if [ -f $(SRCDIR)/$*/Makefile -a -d $(CURDIR)/$* ]; then \ $(MAKE) S=$S/$* -f $(SRCDIR)/$*/Makefile -C $(CURDIR)/$* clean ; \ fi @rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) # # include .depdirs and define rules to order priorities between build # of directories. # include $(RTE_OUTPUT)/.depdirs define depdirs_rule $(1): $(sort $(patsubst $(S)/%,%,$(LOCAL_DEPDIRS-$(S)/$(1)))) endef $(foreach d,$(DIRS-y),$(eval $(call depdirs_rule,$(d)))) # use a "for" in a shell to process dependencies: we don't want this # task to be run in parallel. .PHONY: depdirs depdirs: @for d in $(DIRS-y); do \ if [ -f $(SRCDIR)/$$d/Makefile ]; then \ $(MAKE) S=$S/$$d -f $(SRCDIR)/$$d/Makefile depdirs ; \ fi ; \ done .PHONY: depgraph depgraph: @for d in $(DIRS-y); do \ echo " \"$(S)\" -> \"$(S)/$$d\"" ; \ if [ -f $(SRCDIR)/$$d/Makefile ]; then \ $(MAKE) S=$S/$$d -f $(SRCDIR)/$$d/Makefile depgraph ; \ fi ; \ done include $(RTE_SDK)/mk/internal/rte.install-post.mk include $(RTE_SDK)/mk/internal/rte.clean-post.mk include $(RTE_SDK)/mk/internal/rte.build-post.mk .PHONY: FORCE FORCE: ================================================ FILE: mk/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # To be included at the beginning of all RTE user Makefiles. This # .mk will define the RTE environment variables by including the # config file of SDK. It also includes the config file from external # application if any. # ifeq ($(RTE_SDK),) $(error RTE_SDK is not defined) endif ifeq ($(wildcard $(RTE_SDK)),) $(error RTE_SDK variable points to an invalid location) endif # define Q to '@' or not. $(Q) is used to prefix all shell commands to # be executed silently. Q=@ ifdef V ifeq ("$(origin V)", "command line") Q= endif endif export Q # if we are building SDK, only includes SDK configuration ifneq ($(BUILDING_RTE_SDK),) include $(RTE_OUTPUT)/.config # remove double-quotes from config names RTE_ARCH := $(CONFIG_RTE_ARCH:"%"=%) RTE_MACHINE := $(CONFIG_RTE_MACHINE:"%"=%) RTE_EXEC_ENV := $(CONFIG_RTE_EXEC_ENV:"%"=%) RTE_TOOLCHAIN := $(CONFIG_RTE_TOOLCHAIN:"%"=%) RTE_TARGET := $(RTE_ARCH)-$(RTE_MACHINE)-$(RTE_EXEC_ENV)-$(RTE_TOOLCHAIN) RTE_SDK_BIN := $(RTE_OUTPUT) endif RTE_LIBNAME := dpdk # RTE_TARGET is deducted from config when we are building the SDK. # Else, when building an external app, RTE_TARGET must be specified # by the user. ifeq ($(RTE_TARGET),) $(error RTE_TARGET is not defined) endif ifeq ($(BUILDING_RTE_SDK),) # if we are building an external app/lib, include internal/rte.extvars.mk that will # define RTE_OUTPUT, RTE_SRCDIR, RTE_EXTMK, RTE_SDK_BIN, (etc ...) include $(RTE_SDK)/mk/internal/rte.extvars.mk endif CONFIG_RTE_LIBRTE_E1000_PMD = $(CONFIG_RTE_LIBRTE_IGB_PMD) ifneq ($(CONFIG_RTE_LIBRTE_E1000_PMD),y) CONFIG_RTE_LIBRTE_E1000_PMD = $(CONFIG_RTE_LIBRTE_EM_PMD) endif ifeq ($(RTE_ARCH),) $(error RTE_ARCH is not defined) endif ifeq ($(RTE_MACHINE),) $(error RTE_MACHINE is not defined) endif ifeq ($(RTE_EXEC_ENV),) $(error RTE_EXEC_ENV is not defined) endif ifeq ($(RTE_TOOLCHAIN),) $(error RTE_TOOLCHAIN is not defined) endif # can be overriden by make command line or exported environment variable RTE_KERNELDIR ?= /lib/modules/$(shell uname -r)/build export RTE_TARGET export RTE_ARCH export RTE_MACHINE export RTE_EXEC_ENV export RTE_TOOLCHAIN # SRCDIR is the current source directory ifdef S SRCDIR := $(abspath $(RTE_SRCDIR)/$(S)) else SRCDIR := $(RTE_SRCDIR) endif # helper: return y if option is set to y, else return an empty string testopt = $(if $(strip $(subst y,,$(1)) $(subst $(1),,y)),,y) # helper: return an empty string if option is set, else return y not = $(if $(strip $(subst y,,$(1)) $(subst $(1),,y)),,y) ifneq ($(wildcard $(RTE_SDK)/mk/target/$(RTE_TARGET)/rte.vars.mk),) include $(RTE_SDK)/mk/target/$(RTE_TARGET)/rte.vars.mk else include $(RTE_SDK)/mk/target/generic/rte.vars.mk endif ================================================ FILE: mk/target/generic/rte.app.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # define Makefile targets that are specific to an environment. # include $(RTE_SDK)/mk/exec-env/$(RTE_EXEC_ENV)/rte.app.mk .PHONY: exec-env-appinstall target-appinstall: exec-env-appinstall .PHONY: exec-env-appclean target-appclean: exec-env-appclean ================================================ FILE: mk/target/generic/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This .mk is the generic target rte.var.mk ; it includes .mk for # the specified machine, architecture, toolchain (compiler) and # executive environment. # # # machine: # # - can define ARCH variable (overriden by cmdline value) # - can define CROSS variable (overriden by cmdline value) # - define MACHINE_CFLAGS variable (overriden by cmdline value) # - define MACHINE_LDFLAGS variable (overriden by cmdline value) # - define MACHINE_ASFLAGS variable (overriden by cmdline value) # - can define CPU_CFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_LDFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # - can define CPU_ASFLAGS variable (overriden by cmdline value) that # overrides the one defined in arch. # # examples for RTE_MACHINE: default, pc, bensley, tylesburg, ... # include $(RTE_SDK)/mk/machine/$(RTE_MACHINE)/rte.vars.mk # # arch: # # - define ARCH variable (overriden by cmdline or by previous # optional define in machine .mk) # - define CROSS variable (overriden by cmdline or previous define # in machine .mk) # - define CPU_CFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_LDFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - define CPU_ASFLAGS variable (overriden by cmdline or previous # define in machine .mk) # - may override any previously defined variable # # examples for RTE_ARCH: i686, x86_64 # include $(RTE_SDK)/mk/arch/$(RTE_ARCH)/rte.vars.mk # # toolchain: # # - define CC, LD, AR, AS, ... # - define TOOLCHAIN_CFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_LDFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_ASFLAGS variable (overriden by cmdline value) # - may override any previously defined variable # # examples for RTE_TOOLCHAIN: gcc, icc # include $(RTE_SDK)/mk/toolchain/$(RTE_TOOLCHAIN)/rte.vars.mk # # exec-env: # # - define EXECENV_CFLAGS variable (overriden by cmdline) # - define EXECENV_LDFLAGS variable (overriden by cmdline) # - define EXECENV_ASFLAGS variable (overriden by cmdline) # - may override any previously defined variable # # examples for RTE_EXEC_ENV: linuxapp, bsdapp # include $(RTE_SDK)/mk/exec-env/$(RTE_EXEC_ENV)/rte.vars.mk # Don't set CFLAGS/LDFLAGS flags for kernel module, all flags are # provided by Kbuild framework. ifeq ($(KERNELRELEASE),) # now that the environment is mostly set up, including the machine type we will # be passing to the compiler, set up the specific CPU flags based on that info. include $(RTE_SDK)/mk/rte.cpuflags.mk # merge all CFLAGS CFLAGS := $(CPU_CFLAGS) $(EXECENV_CFLAGS) $(TOOLCHAIN_CFLAGS) $(MACHINE_CFLAGS) CFLAGS += $(TARGET_CFLAGS) # merge all LDFLAGS LDFLAGS := $(CPU_LDFLAGS) $(EXECENV_LDFLAGS) $(TOOLCHAIN_LDFLAGS) $(MACHINE_LDFLAGS) LDFLAGS += $(TARGET_LDFLAGS) # merge all ASFLAGS ASFLAGS := $(CPU_ASFLAGS) $(EXECENV_ASFLAGS) $(TOOLCHAIN_ASFLAGS) $(MACHINE_ASFLAGS) ASFLAGS += $(TARGET_ASFLAGS) # add default include and lib paths CFLAGS += -I$(RTE_OUTPUT)/include LDFLAGS += -L$(RTE_OUTPUT)/lib # always include rte_config.h: the one in $(RTE_OUTPUT)/include is # the configuration of SDK when $(BUILDING_RTE_SDK) is true, or the # configuration of the application if $(BUILDING_RTE_SDK) is not # defined. ifeq ($(BUILDING_RTE_SDK),1) # building sdk CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y) CFLAGS += -include rte_warnings.h endif else # if we are building an external application, include SDK's lib and # includes too CFLAGS += -I$(RTE_SDK_BIN)/include ifneq ($(wildcard $(RTE_OUTPUT)/include/rte_config.h),) CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h endif CFLAGS += -include $(RTE_SDK_BIN)/include/rte_config.h ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y) CFLAGS += -include rte_warnings.h endif LDFLAGS += -L$(RTE_SDK_BIN)/lib endif export CFLAGS export LDFLAGS endif ================================================ FILE: mk/toolchain/clang/rte.toolchain-compat.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # CPUID-related options # # This was added to support compiler versions which might not support all the # flags we need # # find out CLANG version CLANG_MAJOR_VERSION = $(shell $(CC) -dumpversion | cut -f1 -d.) CLANG_MINOR_VERSION = $(shell $(CC) -dumpversion | cut -f2 -d.) ================================================ FILE: mk/toolchain/clang/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # toolchain: # # - define CC, LD, AR, AS, ... (overriden by cmdline value) # - define TOOLCHAIN_CFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_LDFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_ASFLAGS variable (overriden by cmdline value) # CC = $(CROSS)clang KERNELCC = $(CROSS)gcc CPP = $(CROSS)cpp # for now, we don't use as but nasm. # AS = $(CROSS)as AS = nasm AR = $(CROSS)ar LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy OBJDUMP = $(CROSS)objdump STRIP = $(CROSS)strip READELF = $(CROSS)readelf GCOV = $(CROSS)gcov ifeq ("$(origin CC)", "command line") HOSTCC = $(CC) else HOSTCC = clang endif HOSTAS = as TOOLCHAIN_ASFLAGS = TOOLCHAIN_CFLAGS = TOOLCHAIN_LDFLAGS = WERROR_FLAGS := -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes WERROR_FLAGS += -Wmissing-declarations -Wold-style-definition -Wpointer-arith WERROR_FLAGS += -Wnested-externs -Wcast-qual WERROR_FLAGS += -Wformat-nonliteral -Wformat-security WERROR_FLAGS += -Wundef -Wwrite-strings # process cpu flags include $(RTE_SDK)/mk/toolchain/$(RTE_TOOLCHAIN)/rte.toolchain-compat.mk # workaround clang bug with warning "missing field initializer" for "= {0}" WERROR_FLAGS += -Wno-missing-field-initializers export CC AS AR LD OBJCOPY OBJDUMP STRIP READELF export TOOLCHAIN_CFLAGS TOOLCHAIN_LDFLAGS TOOLCHAIN_ASFLAGS ================================================ FILE: mk/toolchain/gcc/rte.toolchain-compat.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # CPUID-related options # # This was added to support compiler versions which might not support all the # flags we need # #find out GCC version GCC_VERSION = $(subst .,,$(shell $(CC) -dumpversion | cut -f1-2 -d.)) # if GCC is older than 4.x ifeq ($(shell test $(GCC_VERSION) -lt 40 && echo 1), 1) MACHINE_CFLAGS = $(warning You are using GCC < 4.x. This is neither supported, nor tested.) else # GCC graceful degradation # GCC 4.2.x - added support for generic target # GCC 4.3.x - added support for core2, ssse3, sse4.1, sse4.2 # GCC 4.4.x - added support for avx, aes, pclmul # GCC 4.5.x - added support for atom # GCC 4.6.x - added support for corei7, corei7-avx # GCC 4.7.x - added support for fsgsbase, rdrnd, f16c, core-avx-i, core-avx2 ifeq ($(shell test $(GCC_VERSION) -le 47 && echo 1), 1) MACHINE_CFLAGS := $(patsubst -march=core-avx-i,-march=corei7-avx,$(MACHINE_CFLAGS)) MACHINE_CFLAGS := $(patsubst -march=core-avx2,-march=core-avx2,$(MACHINE_CFLAGS)) endif ifeq ($(shell test $(GCC_VERSION) -lt 46 && echo 1), 1) MACHINE_CFLAGS := $(patsubst -march=corei7-avx,-march=core2 -maes -mpclmul -mavx,$(MACHINE_CFLAGS)) MACHINE_CFLAGS := $(patsubst -march=corei7,-march=core2 -maes -mpclmul,$(MACHINE_CFLAGS)) endif ifeq ($(shell test $(GCC_VERSION) -lt 45 && echo 1), 1) MACHINE_CFLAGS := $(patsubst -march=atom,-march=core2 -mssse3,$(MACHINE_CFLAGS)) endif ifeq ($(shell test $(GCC_VERSION) -lt 44 && echo 1), 1) MACHINE_CFLAGS := $(filter-out -mavx -mpclmul -maes,$(MACHINE_CFLAGS)) ifneq ($(findstring SSE4_2, $(CPUFLAGS)),) MACHINE_CFLAGS += -msse4.2 endif ifneq ($(findstring SSE4_1, $(CPUFLAGS)),) MACHINE_CFLAGS += -msse4.1 endif endif ifeq ($(shell test $(GCC_VERSION) -lt 43 && echo 1), 1) MACHINE_CFLAGS := $(filter-out -msse% -mssse%,$(MACHINE_CFLAGS)) MACHINE_CFLAGS := $(patsubst -march=core2,-march=generic,$(MACHINE_CFLAGS)) MACHINE_CFLAGS += -msse3 endif ifeq ($(shell test $(GCC_VERSION) -lt 42 && echo 1), 1) MACHINE_CFLAGS := $(filter-out -march% -mtune% -msse%,$(MACHINE_CFLAGS)) endif endif ================================================ FILE: mk/toolchain/gcc/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # toolchain: # # - define CC, LD, AR, AS, ... (overriden by cmdline value) # - define TOOLCHAIN_CFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_LDFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_ASFLAGS variable (overriden by cmdline value) # CC = $(CROSS)gcc KERNELCC = $(CROSS)gcc CPP = $(CROSS)cpp # for now, we don't use as but nasm. # AS = $(CROSS)as AS = nasm AR = $(CROSS)ar LD = $(CROSS)ld OBJCOPY = $(CROSS)objcopy OBJDUMP = $(CROSS)objdump STRIP = $(CROSS)strip READELF = $(CROSS)readelf GCOV = $(CROSS)gcov ifeq ("$(origin CC)", "command line") HOSTCC = $(CC) else HOSTCC = gcc endif HOSTAS = as TOOLCHAIN_ASFLAGS = TOOLCHAIN_CFLAGS = TOOLCHAIN_LDFLAGS = ifeq ($(CONFIG_RTE_LIBRTE_GCOV),y) TOOLCHAIN_CFLAGS += --coverage TOOLCHAIN_LDFLAGS += --coverage ifeq (,$(findstring -O0,$(EXTRA_CFLAGS))) $(warning "EXTRA_CFLAGS doesn't contains -O0, coverage will be inaccurate with optimizations enabled") endif endif WERROR_FLAGS := -W -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes WERROR_FLAGS += -Wmissing-declarations -Wold-style-definition -Wpointer-arith WERROR_FLAGS += -Wcast-align -Wnested-externs -Wcast-qual WERROR_FLAGS += -Wformat-nonliteral -Wformat-security WERROR_FLAGS += -Wundef -Wwrite-strings # process cpu flags include $(RTE_SDK)/mk/toolchain/$(RTE_TOOLCHAIN)/rte.toolchain-compat.mk # workaround GCC bug with warning "missing initializer" for "= {0}" ifeq ($(shell test $(GCC_VERSION) -lt 47 && echo 1), 1) WERROR_FLAGS += -Wno-missing-field-initializers endif # workaround GCC bug with warning "may be used uninitialized" ifeq ($(shell test $(GCC_VERSION) -lt 47 && echo 1), 1) WERROR_FLAGS += - Wno-uninitialized endif # workaround to skipping GCC6 additional errors WERROR_FLAGS += -Wno-misleading-indentation -Wno-shift-negative-value -Wno-maybe-uninitialized export CC AS AR LD OBJCOPY OBJDUMP STRIP READELF export TOOLCHAIN_CFLAGS TOOLCHAIN_LDFLAGS TOOLCHAIN_ASFLAGS ================================================ FILE: mk/toolchain/icc/rte.toolchain-compat.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # CPUID-related options # # This was added to support compiler versions which might not support all the # flags we need # # find out ICC version ICC_MAJOR_VERSION = $(shell icc -dumpversion | cut -f1 -d.) ifeq ($(shell test $(ICC_MAJOR_VERSION) -lt 12 && echo 1), 1) MACHINE_CFLAGS = -xSSE3 $(warning You are not using ICC 12.x or higher. This is neither supported, nor tested.) else # proceed to adjust compiler flags ICC_MINOR_VERSION = $(shell icc -dumpversion | cut -f2 -d.) # replace GCC flags with ICC flags # if icc version >= 12 ifeq ($(shell test $(ICC_MAJOR_VERSION) -ge 12 && echo 1), 1) # Atom MACHINE_CFLAGS := $(patsubst -march=atom,-xSSSE3_ATOM -march=atom,$(MACHINE_CFLAGS)) # nehalem/westmere MACHINE_CFLAGS := $(patsubst -march=corei7,-xSSE4.2 -march=corei7,$(MACHINE_CFLAGS)) # sandy bridge MACHINE_CFLAGS := $(patsubst -march=corei7-avx,-xAVX,$(MACHINE_CFLAGS)) # ivy bridge MACHINE_CFLAGS := $(patsubst -march=core-avx-i,-xCORE-AVX-I,$(MACHINE_CFLAGS)) # hsw MACHINE_CFLAGS := $(patsubst -march=core-avx2,-xCORE-AVX2,$(MACHINE_CFLAGS)) # remove westmere flags MACHINE_CFLAGS := $(filter-out -mpclmul -maes,$(MACHINE_CFLAGS)) endif # if icc version == 12.0 ifeq ($(shell test $(ICC_MAJOR_VERSION) -eq 12 && test $(ICC_MINOR_VERSION) -eq 0 && echo 1), 1) # Atom MACHINE_CFLAGS := $(patsubst -xSSSE3_ATOM,-xSSE3_ATOM,$(MACHINE_CFLAGS)) # remove march options MACHINE_CFLAGS := $(patsubst -march=%,-xSSE3,$(MACHINE_CFLAGS)) endif endif ================================================ FILE: mk/toolchain/icc/rte.vars.mk ================================================ # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # toolchain: # # - define CC, LD, AR, AS, ... (overriden by cmdline value) # - define TOOLCHAIN_CFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_LDFLAGS variable (overriden by cmdline value) # - define TOOLCHAIN_ASFLAGS variable (overriden by cmdline value) # # Warning: we do not use CROSS environment variable as icc is mainly a # x86->x86 compiler CC = icc KERNELCC = gcc CPP = cpp AS = nasm AR = ar LD = ld OBJCOPY = objcopy OBJDUMP = objdump STRIP = strip READELF = readelf ifeq ($(KERNELRELEASE),) HOSTCC = icc else HOSTCC = gcc endif HOSTAS = as TOOLCHAIN_CFLAGS = TOOLCHAIN_LDFLAGS = TOOLCHAIN_ASFLAGS = # Turn off some ICC warnings - # Remark #271 : trailing comma is nonstandard # Warning #1478 : function "" (declared at line N of "") # error #13368: loop was not vectorized with "vector always assert" # error #15527: loop was not vectorized: function call to fprintf cannot be vectorize # was declared "deprecated" WERROR_FLAGS := -Wall -Werror-all -w2 -diag-disable 271 -diag-warning 1478 WERROR_FLAGS += -diag-disable 13368 -diag-disable 15527 # process cpu flags include $(RTE_SDK)/mk/toolchain/$(RTE_TOOLCHAIN)/rte.toolchain-compat.mk # disable max-inline params boundaries for ICC 15 compiler ifeq ($(shell test $(ICC_MAJOR_VERSION) -eq 15 && echo 1), 1) TOOLCHAIN_CFLAGS += -no-inline-max-size -no-inline-max-total-size endif export CC AS AR LD OBJCOPY OBJDUMP STRIP READELF export TOOLCHAIN_CFLAGS TOOLCHAIN_LDFLAGS TOOLCHAIN_ASFLAGS ================================================ FILE: pkg/dpdk.spec ================================================ # Copyright 2014 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # - Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # - Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # - Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. Name: dpdk Version: 2.1.0 Release: 1 Packager: packaging@6wind.com URL: http://dpdk.org Source: http://dpdk.org/browse/dpdk/snapshot/dpdk-%{version}.tar.gz Summary: Data Plane Development Kit core Group: System Environment/Libraries License: BSD and LGPLv2 and GPLv2 ExclusiveArch: i686, x86_64 %global target %{_arch}-native-linuxapp-gcc %global machine default BuildRequires: kernel-devel, kernel-headers, libpcap-devel, xen-devel BuildRequires: doxygen, python-sphinx, inkscape BuildRequires: texlive-collection-latexextra, texlive-collection-fontsextra %description DPDK core includes kernel modules, core libraries and tools. testpmd application allows to test fast packet processing environments on x86 platforms. For instance, it can be used to check that environment can support fast path applications such as 6WINDGate, pktgen, rumptcpip, etc. More libraries are available as extensions in other packages. %package devel Summary: Data Plane Development Kit for development Requires: %{name}%{?_isa} = %{version}-%{release} %description devel DPDK devel is a set of makefiles, headers and examples for fast packet processing on x86 platforms. %package doc Summary: Data Plane Development Kit API documentation BuildArch: noarch %description doc DPDK doc is divided in two parts: API details in doxygen HTML format and guides in sphinx HTML/PDF formats. %global destdir %{buildroot}%{_prefix} %global moddir /lib/modules/%(uname -r)/extra %global datadir %{_datadir}/dpdk %global docdir %{_docdir}/dpdk %prep %setup -q %build make O=%{target} T=%{target} config sed -ri 's,(RTE_MACHINE=).*,\1%{machine},' %{target}/.config sed -ri 's,(RTE_APP_TEST=).*,\1n,' %{target}/.config sed -ri 's,(RTE_BUILD_SHARED_LIB=).*,\1y,' %{target}/.config sed -ri 's,(RTE_NEXT_ABI=).*,\1n,' %{target}/.config sed -ri 's,(LIBRTE_VHOST=).*,\1y,' %{target}/.config sed -ri 's,(LIBRTE_PMD_PCAP=).*,\1y,' %{target}/.config sed -ri 's,(LIBRTE_PMD_XENVIRT=).*,\1y,' %{target}/.config sed -ri 's,(LIBRTE_XEN_DOM0=).*,\1y,' %{target}/.config make O=%{target} %{?_smp_mflags} make O=%{target} doc %install rm -rf %{buildroot} make O=%{target} DESTDIR=%{destdir} mkdir -p %{buildroot}%{moddir} mv %{destdir}/%{target}/kmod/*.ko %{buildroot}%{moddir} rmdir %{destdir}/%{target}/kmod mkdir -p %{buildroot}%{_sbindir} ln -s %{datadir}/tools/*nic_bind.py %{buildroot}%{_sbindir}/dpdk_nic_bind mkdir -p %{buildroot}%{_bindir} mv %{destdir}/%{target}/app/testpmd %{buildroot}%{_bindir} rmdir %{destdir}/%{target}/app mv %{destdir}/%{target}/include %{buildroot}%{_includedir} mv %{destdir}/%{target}/lib %{buildroot}%{_libdir} mkdir -p %{buildroot}%{docdir} rm -rf %{destdir}/%{target}/doc/*/*/.{build,doc}* mv %{destdir}/%{target}/doc/html/* %{buildroot}%{docdir} mv %{destdir}/%{target}/doc/*/*/*pdf %{buildroot}%{docdir}/guides rm -rf %{destdir}/%{target}/doc mkdir -p %{buildroot}%{datadir} mv %{destdir}/%{target}/.config %{buildroot}%{datadir}/config mv %{destdir}/%{target} %{buildroot}%{datadir} mv %{destdir}/scripts %{buildroot}%{datadir} mv %{destdir}/mk %{buildroot}%{datadir} cp -a examples %{buildroot}%{datadir} cp -a tools %{buildroot}%{datadir} ln -s %{datadir}/config %{buildroot}%{datadir}/%{target}/.config ln -s %{_includedir} %{buildroot}%{datadir}/%{target}/include ln -s %{_libdir} %{buildroot}%{datadir}/%{target}/lib %files %dir %{datadir} %{datadir}/config %{datadir}/tools %{moddir}/* %{_sbindir}/* %{_bindir}/* %{_libdir}/* %files devel %{_includedir}/* %{datadir}/mk %{datadir}/scripts %{datadir}/%{target} %{datadir}/examples %files doc %doc %{docdir} %post /sbin/ldconfig /sbin/depmod %postun /sbin/ldconfig /sbin/depmod ================================================ FILE: scripts/auto-config-h.sh ================================================ #!/bin/sh # # BSD LICENSE # # Copyright 2014-2015 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Crude script to detect whether particular types, macros and functions are # defined by trying to compile a file with a given header. Can be used to # perform cross-platform checks since the resulting object file is not # executed. # # Set VERBOSE=1 in the environment to display compiler output and errors. # # CC, CPPFLAGS, CFLAGS, EXTRA_CPPFLAGS and EXTRA_CFLAGS are taken from the # environment. # # AUTO_CONFIG_CFLAGS may append additional CFLAGS without modifying the # above variables. file=${1:?output file name required (config.h)} macro=${2:?output macro name required (HAVE_*)} include=${3:?include name required (foo.h)} type=${4:?object type required (define, enum, type, field, func)} name=${5:?define/type/function name required} : ${CC:=cc} temp=/tmp/${0##*/}.$$.c case $type in define) code="\ #ifndef $name #error $name not defined #endif " ;; enum) code="\ long test____ = $name; " ;; type) code="\ $name test____; " ;; field) code="\ void test____(void) { ${name%%.*} test_____; (void)test_____.${name#*.}; } " ;; func) code="\ void (*test____)() = (void (*)())$name; " ;; *) unset error : ${error:?unknown object type \"$type\"} exit esac if [ "${VERBOSE}" = 1 ] then err=2 out=1 eol=' ' else exec 3> /dev/null || exit err=3 out=3 eol=' ' fi && printf 'Looking for %s %s in %s.%s' \ "${name}" "${type}" "${include}" "${eol}" && printf "\ #include <%s> %s " "$include" "$code" > "${temp}" && if ${CC} ${CPPFLAGS} ${EXTRA_CPPFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \ ${AUTO_CONFIG_CFLAGS} \ -c -o /dev/null "${temp}" 1>&${out} 2>&${err} then rm -f "${temp}" printf "\ #ifndef %s #define %s 1 #endif /* %s */ " "${macro}" "${macro}" "${macro}" >> "${file}" && printf 'Defining %s.\n' "${macro}" else rm -f "${temp}" printf "\ /* %s is not defined. */ " "${macro}" >> "${file}" && printf 'Not defining %s.\n' "${macro}" fi exit ================================================ FILE: scripts/check-maintainers.sh ================================================ #! /bin/sh # BSD LICENSE # # Copyright 2015 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Do some basic checks in MAINTAINERS file cd $(dirname $0)/.. # Get files matching paths with wildcards and / meaning recursing files () # [ ...] { if [ -z "$1" ] ; then return fi if [ -d .git ] ; then git ls-files "$1" else find "$1" -type f | sed 's,^\./,,' fi | # if not ended by / if ! echo "$1" | grep -q '/[[:space:]]*$' ; then # filter out deeper directories sed "/\(\/[^/]*\)\{$(($(echo "$1" | grep -o / | wc -l) + 1))\}/d" else cat fi # next path shift files "$@" } # Get all files matching F: and X: fields parse_fx () # { IFS=' ' # parse each line excepted underlining for line in $( (sed '/^-\+$/d' $1 ; echo) | sed 's,^$,§,') ; do if echo "$line" | grep -q '^§$' ; then # empty line delimit end of section whitelist=$(files $flines) blacklist=$(files $xlines) match=$(aminusb "$whitelist" "$blacklist") if [ -n "$whitelist" ] ; then printf "# $title " maintainers=$(echo "$maintainers" | sed -r 's,.*<(.*)>.*,\1,') maintainers=$(printf "$maintainers" | sed -e 's,^,<,' -e 's,$,>,') echo $maintainers fi if [ -n "$match" ] ; then echo "$match" fi # flush section unset maintainers unset flines unset xlines elif echo "$line" | grep -q '^[A-Z]: ' ; then # maintainer maintainers=$(add_line_to_if "$line" "$maintainers" 'M: ') # file matching pattern flines=$(add_line_to_if "$line" "$flines" 'F: ') # file exclusion pattern xlines=$(add_line_to_if "$line" "$xlines" 'X: ') else # assume it is a title title="$line" fi done } # Check patterns in F: and X: check_fx () # { IFS=' ' for line in $(sed -n 's,^[FX]: ,,p' $1 | tr '*' '#') ; do line=$(printf "$line" | tr '#' '*') match=$(files "$line") if [ -z "$match" ] ; then echo "$line" fi done } # Add a line to a set of lines if it begins with right pattern add_line_to_if () # { ( echo "$2" echo "$1" | sed -rn "s,^$3(.*),\1,p" ) | sed '/^$/d' } # Subtract two sets of lines aminusb () # { printf "$1\n$2\n$2" | sort | uniq -u | sed '/^$/d' } printf 'sections: ' parsed=$(parse_fx MAINTAINERS) echo "$parsed" | grep -c '^#' printf 'with maintainer: ' echo "$parsed" | grep -c '^#.*@' printf 'maintainers: ' grep '^M:.*<' MAINTAINERS | sort -u | wc -l echo echo '##########' echo '# orphan areas' echo '##########' echo "$parsed" | sed -rn 's,^#([^@]*)$,\1,p' | uniq echo echo '##########' echo '# files not listed' echo '##########' all=$(files ./) listed=$(echo "$parsed" | sed '/^#/d' | sort -u) aminusb "$all" "$listed" echo echo '##########' echo '# wrong patterns' echo '##########' check_fx MAINTAINERS # TODO: check overlaps ================================================ FILE: scripts/cocci/mtod-offset.cocci ================================================ // // Replace explicit packet offset computations with rte_pktmbuf_mtod_offset(). // @disable paren@ typedef uint8_t; expression M, O; @@ ( - rte_pktmbuf_mtod(M, char *) + O + rte_pktmbuf_mtod_offset(M, char *, O) | - rte_pktmbuf_mtod(M, char *) - O + rte_pktmbuf_mtod_offset(M, char *, -O) | - rte_pktmbuf_mtod(M, unsigned char *) + O + rte_pktmbuf_mtod_offset(M, unsigned char *, O) | - rte_pktmbuf_mtod(M, unsigned char *) - O + rte_pktmbuf_mtod_offset(M, unsigned char *, -O) | - rte_pktmbuf_mtod(M, uint8_t *) + O + rte_pktmbuf_mtod_offset(M, uint8_t *, O) | - rte_pktmbuf_mtod(M, uint8_t *) - O + rte_pktmbuf_mtod_offset(M, uint8_t *, -O) ) // // Fold subsequent offset terms into pre-existing offset used in // rte_pktmbuf_mtod_offset(). // @disable paren@ expression M, O1, O2; @@ ( - rte_pktmbuf_mtod_offset(M, char *, O1) + O2 + rte_pktmbuf_mtod_offset(M, char *, O1 + O2) | - rte_pktmbuf_mtod_offset(M, char *, O1) - O2 + rte_pktmbuf_mtod_offset(M, char *, O1 - O2) | - rte_pktmbuf_mtod_offset(M, unsigned char *, O1) + O2 + rte_pktmbuf_mtod_offset(M, unsigned char *, O1 + O2) | - rte_pktmbuf_mtod_offset(M, unsigned char *, O1) - O2 + rte_pktmbuf_mtod_offset(M, unsigned char *, O1 - O2) | - rte_pktmbuf_mtod_offset(M, uint8_t *, O1) + O2 + rte_pktmbuf_mtod_offset(M, uint8_t *, O1 + O2) | - rte_pktmbuf_mtod_offset(M, uint8_t *, O1) - O2 + rte_pktmbuf_mtod_offset(M, uint8_t *, O1 - O2) ) // // Cleanup rules. Fold in double casts, remove unnecessary paranthesis, etc. // @disable paren@ expression M, O; type C, T; @@ ( - (C)rte_pktmbuf_mtod_offset(M, T, O) + rte_pktmbuf_mtod_offset(M, C, O) | - (rte_pktmbuf_mtod_offset(M, T, O)) + rte_pktmbuf_mtod_offset(M, T, O) | - (C)rte_pktmbuf_mtod(M, T) + rte_pktmbuf_mtod(M, C) | - (rte_pktmbuf_mtod(M, T)) + rte_pktmbuf_mtod(M, T) ) ================================================ FILE: scripts/cocci.sh ================================================ #! /bin/sh # BSD LICENSE # # Copyright 2015 EZchip Semiconductor Ltd. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of EZchip Semiconductor nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Apply coccinelle transforms. SRCTREE=$(readlink -f $(dirname $0)/..) COCCI=$SRCTREE/scripts/cocci [ -n "$SPATCH" ] || SPATCH=$(which spatch) PATCH_LIST="$@" [ -n "$PATCH_LIST" ] || PATCH_LIST=$(echo $COCCI/*.cocci) [ -x "$SPATCH" ] || ( echo "Coccinelle tools not installed." exit 1 ) tmp=$(mktemp) for c in $PATCH_LIST; do while true; do echo -n "Applying $c..." $SPATCH --sp-file $c -c --linux-spacing --very-quiet \ --include-headers --preprocess \ --in-place --dir $SRCTREE > $tmp if [ -s $tmp ]; then echo " changes applied, retrying." else echo " no change." break; fi done done rm -f $tmp ================================================ FILE: scripts/depdirs-rule.sh ================================================ #!/bin/sh # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This (obscure) bash script finds the smallest different path between # path1 and path2 given as command line argument. The given paths MUST # be relative paths, the script is not designed to work with absolute # paths. # # The script will then generate Makefile code that can be saved in a # file and included in build system. # # For instance: # depdirs-rule.sh a/b/c/d a/b/e/f # Will print: # FULL_DEPDIRS-a/b/c/d += a/b/e/f # LOCAL_DEPDIRS-a/b/c += a/b/e # # The script returns 0 except if invalid arguments are given. # if [ $# -ne 2 ]; then echo "Bad arguments" echo "Usage:" echo " $0 path1 path2" exit 1 fi left1=${1%%/*} right1=${1#*/} prev_right1=$1 prev_left1= left2=${2%%/*} right2=${2#*/} prev_right2=$2 prev_left2= while [ "${right1}" != "" -a "${right2}" != "" ]; do if [ "$left1" != "$left2" ]; then break fi prev_left1=$left1 left1=$left1/${right1%%/*} prev_right1=$right1 right1=${prev_right1#*/} if [ "$right1" = "$prev_right1" ]; then right1="" fi prev_left2=$left2 left2=$left2/${right2%%/*} prev_right2=$right2 right2=${prev_right2#*/} if [ "$right2" = "$prev_right2" ]; then right2="" fi done echo FULL_DEPDIRS-$1 += $2 echo LOCAL_DEPDIRS-$left1 += $left2 exit 0 ================================================ FILE: scripts/gen-build-mk.sh ================================================ #!/bin/sh # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Auto-generate a Makefile in build directory # Args: # $1: path of project src root # $2: path of build dir (can be relative to $1) echo "# Automatically generated by gen-build-mk.sh" echo echo "ifdef O" echo "ifeq (\"\$(origin O)\", \"command line\")" echo "\$(error \"Cannot specify O= as you are already in a build directory\")" echo "endif" echo "endif" echo echo "MAKEFLAGS += --no-print-directory" echo echo "all:" echo " @\$(MAKE) -C $1 O=$2" echo echo "%::" echo " @\$(MAKE) -C $1 O=$2 \$@" ================================================ FILE: scripts/gen-config-h.sh ================================================ #!/bin/sh # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. echo "#ifndef __RTE_CONFIG_H" echo "#define __RTE_CONFIG_H" grep CONFIG_ $1 | grep -v '^[ \t]*#' | sed 's,CONFIG_\(.*\)=y.*$,#undef \1\ #define \1 1,' | sed 's,CONFIG_\(.*\)=n.*$,#undef \1,' | sed 's,CONFIG_\(.*\)=\(.*\)$,#undef \1\ #define \1 \2,' | sed 's,\# CONFIG_\(.*\) is not set$,#undef \1,' echo "#endif /* __RTE_CONFIG_H */" ================================================ FILE: scripts/relpath.sh ================================================ #!/bin/sh # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # print the relative path of $1 from $2 directory # $1 and $2 MUST be absolute paths # if [ $# -ne 2 ]; then echo "Bad arguments" echo "Usage:" echo " $0 path1 path2" exit 1 fi # get the real absolute path, derefencing symlinks ABS1=$(readlink -f $1) ABS2=$(readlink -f $2) # remove leading slash REL1=${ABS1#/} REL2=${ABS2#/} left1=${REL1%%/*} right1=${REL1#*/} prev_right1=$REL1 prev_left1= left2=${REL2%%/*} right2=${REL2#*/} prev_right2=$REL2 prev_left2= while [ "${right1}" != "" -a "${right2}" != "" ]; do if [ "$left1" != "$left2" ]; then break fi prev_left1=$left1 left1=$left1/${right1%%/*} prev_right1=$right1 right1=${prev_right1#*/} if [ "$right1" = "$prev_right1" ]; then right1="" fi prev_left2=$left2 left2=$left2/${right2%%/*} prev_right2=$right2 right2=${prev_right2#*/} if [ "$right2" = "$prev_right2" ]; then right2="" fi done if [ "${left1}" != "${left2}" ]; then right2=${prev_right2} right1=${prev_right1} fi while [ "${right2}" != "" ]; do prefix=${prefix}../ prev_right2=$right2 right2=${right2#*/} if [ "$right2" = "$prev_right2" ]; then right2="" fi done echo ${prefix}${right1} exit 0 ================================================ FILE: scripts/test-null.sh ================================================ #! /bin/sh -e # BSD LICENSE # # Copyright 2015 6WIND S.A. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of 6WIND S.A. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Run a quick testpmd forwarding with null PMD without hugepage build=${1:-build} coremask=${2:-3} # default using cores 0 and 1 if grep -q SHARED_LIB=y $build/.config; then export LD_LIBRARY_PATH=$build/lib:$LD_LIBRARY_PATH pmd='-d librte_pmd_null.so' fi (sleep 1 && echo stop) | $build/app/testpmd -c $coremask -n 1 --no-huge \ $pmd --vdev eth_null1 --vdev eth_null2 -- \ --total-num-mbufs=2048 -ia ================================================ FILE: scripts/validate-abi.sh ================================================ #!/bin/sh # BSD LICENSE # # Copyright(c) 2015 Neil Horman. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. TAG1=$1 TAG2=$2 TARGET=$3 ABI_DIR=`mktemp -d -p /tmp ABI.XXXXXX` usage() { echo "$0 " } log() { local level=$1 shift echo "$*" } validate_tags() { git tag -l | grep -q "$TAG1" if [ $? -ne 0 ] then echo "$TAG1 is invalid" return fi git tag -l | grep -q "$TAG2" if [ $? -ne 0 ] then echo "$TAG2 is invalid" return fi } validate_args() { if [ -z "$TAG1" ] then echo "Must Specify TAG1" return fi if [ -z "$TAG2" ] then echo "Must Specify TAG2" return fi if [ -z "$TARGET" ] then echo "Must Specify a build target" fi } cleanup_and_exit() { rm -rf $ABI_DIR git checkout $CURRENT_BRANCH exit $1 } ########################################### #START ############################################ #trap on ctrl-c to clean up trap cleanup_and_exit SIGINT #Save the current branch CURRENT_BRANCH=`git branch | grep \* | cut -d' ' -f2` if [ -z "$CURRENT_BRANCH" ] then CURRENT_BRANCH=`git log --pretty=format:%H HEAD~1..HEAD` fi if [ -n "$VERBOSE" ] then export VERBOSE=/dev/stdout else export VERBOSE=/dev/null fi # Validate that we have all the arguments we need res=$(validate_args) if [ -n "$res" ] then echo $res usage cleanup_and_exit 1 fi # Make sure our tags exist res=$(validate_tags) if [ -n "$res" ] then echo $res cleanup_and_exit 1 fi ABICHECK=`which abi-compliance-checker 2>/dev/null` if [ $? -ne 0 ] then log "INFO" "Cant find abi-compliance-checker utility" cleanup_and_exit 1 fi ABIDUMP=`which abi-dumper 2>/dev/null` if [ $? -ne 0 ] then log "INFO" "Cant find abi-dumper utility" cleanup_and_exit 1 fi log "INFO" "We're going to check and make sure that applications built" log "INFO" "against DPDK DSOs from tag $TAG1 will still run when executed" log "INFO" "against DPDK DSOs built from tag $TAG2." log "INFO" "" # Check to make sure we have a clean tree git status | grep -q clean if [ $? -ne 0 ] then log "WARN" "Working directory not clean, aborting" cleanup_and_exit 1 fi # Move to the root of the git tree cd $(dirname $0)/.. log "INFO" "Checking out version $TAG1 of the dpdk" # Move to the old version of the tree git checkout $TAG1 # Make sure we configure SHARED libraries # Also turn off IGB and KNI as those require kernel headers to build sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET # Checking abi compliance relies on using the dwarf information in # The shared objects. Thats only included in the DSO's if we build # with -g export EXTRA_CFLAGS=-g export EXTRA_LDFLAGS=-g # Now configure the build log "INFO" "Configuring DPDK $TAG1" make config T=$TARGET O=$TARGET > $VERBOSE 2>&1 log "INFO" "Building DPDK $TAG1. This might take a moment" make O=$TARGET > $VERBOSE 2>&1 if [ $? -ne 0 ] then log "INFO" "THE BUILD FAILED. ABORTING" cleanup_and_exit 1 fi # Move to the lib directory cd $TARGET/lib log "INFO" "COLLECTING ABI INFORMATION FOR $TAG1" for i in `ls *.so` do $ABIDUMP $i -o $ABI_DIR/$i-ABI-0.dump -lver $TAG1 done cd ../.. # Now clean the tree, checkout the second tag, and rebuild git clean -f -d git reset --hard # Move to the new version of the tree log "INFO" "Checking out version $TAG2 of the dpdk" git checkout $TAG2 # Make sure we configure SHARED libraries # Also turn off IGB and KNI as those require kernel headers to build sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" config/defconfig_$TARGET sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" config/defconfig_$TARGET # Now configure the build log "INFO" "Configuring DPDK $TAG2" make config T=$TARGET O=$TARGET > $VERBOSE 2>&1 log "INFO" "Building DPDK $TAG2. This might take a moment" make O=$TARGET > $VERBOSE 2>&1 if [ $? -ne 0 ] then log "INFO" "THE BUILD FAILED. ABORTING" cleanup_and_exit 1 fi cd $TARGET/lib log "INFO" "COLLECTING ABI INFORMATION FOR $TAG2" for i in `ls *.so` do $ABIDUMP $i -o $ABI_DIR/$i-ABI-1.dump -lver $TAG2 done cd ../.. # Start comparison of ABI dumps for i in `ls $ABI_DIR/*-1.dump` do NEWNAME=`basename $i` OLDNAME=`basename $i | sed -e"s/1.dump/0.dump/"` LIBNAME=`basename $i | sed -e"s/-ABI-1.dump//"` if [ ! -f $ABI_DIR/$OLDNAME ] then log "INFO" "$OLDNAME DOES NOT EXIST IN $TAG1. SKIPPING..." fi #compare the abi dumps $ABICHECK -l $LIBNAME -old $ABI_DIR/$OLDNAME -new $ABI_DIR/$NEWNAME done git reset --hard log "INFO" "ABI CHECK COMPLETE. REPORTS ARE IN compat_report directory" cleanup_and_exit 0 ================================================ FILE: tools/cpu_layout.py ================================================ #! /usr/bin/python # # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import sys sockets = [] cores = [] core_map = {} fd=open("/proc/cpuinfo") lines = fd.readlines() fd.close() core_details = [] core_lines = {} for line in lines: if len(line.strip()) != 0: name, value = line.split(":", 1) core_lines[name.strip()] = value.strip() else: core_details.append(core_lines) core_lines = {} for core in core_details: for field in ["processor", "core id", "physical id"]: if field not in core: print "Error getting '%s' value from /proc/cpuinfo" % field sys.exit(1) core[field] = int(core[field]) if core["core id"] not in cores: cores.append(core["core id"]) if core["physical id"] not in sockets: sockets.append(core["physical id"]) key = (core["physical id"], core["core id"]) if key not in core_map: core_map[key] = [] core_map[key].append(core["processor"]) print "============================================================" print "Core and Socket Information (as reported by '/proc/cpuinfo')" print "============================================================\n" print "cores = ",cores print "sockets = ", sockets print "" max_processor_len = len(str(len(cores) * len(sockets) * 2 - 1)) max_core_map_len = max_processor_len * 2 + len('[, ]') + len('Socket ') max_core_id_len = len(str(max(cores))) print " ".ljust(max_core_id_len + len('Core ')), for s in sockets: print "Socket %s" % str(s).ljust(max_core_map_len - len('Socket ')), print "" print " ".ljust(max_core_id_len + len('Core ')), for s in sockets: print "--------".ljust(max_core_map_len), print "" for c in cores: print "Core %s" % str(c).ljust(max_core_id_len), for s in sockets: print str(core_map[(s,c)]).ljust(max_core_map_len), print "\n" ================================================ FILE: tools/dpdk_nic_bind.py ================================================ #! /usr/bin/python # # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import sys, os, getopt, subprocess from os.path import exists, abspath, dirname, basename # The PCI device class for ETHERNET devices ETHERNET_CLASS = "0200" # global dict ethernet devices present. Dictionary indexed by PCI address. # Each device within this is itself a dictionary of device properties devices = {} # list of supported DPDK drivers dpdk_drivers = [ "igb_uio", "vfio-pci", "uio_pci_generic" ] # command-line arg flags b_flag = None status_flag = False force_flag = False args = [] def usage(): '''Print usage information for the program''' argv0 = basename(sys.argv[0]) print """ Usage: ------ %(argv0)s [options] DEVICE1 DEVICE2 .... where DEVICE1, DEVICE2 etc, are specified via PCI "domain:bus:slot.func" syntax or "bus:slot.func" syntax. For devices bound to Linux kernel drivers, they may also be referred to by Linux interface name e.g. eth0, eth1, em0, em1, etc. Options: --help, --usage: Display usage information and quit --status: Print the current status of all known network interfaces. For each device, it displays the PCI domain, bus, slot and function, along with a text description of the device. Depending upon whether the device is being used by a kernel driver, the igb_uio driver, or no driver, other relevant information will be displayed: * the Linux interface name e.g. if=eth0 * the driver being used e.g. drv=igb_uio * any suitable drivers not currently using that device e.g. unused=igb_uio NOTE: if this flag is passed along with a bind/unbind option, the status display will always occur after the other operations have taken place. -b driver, --bind=driver: Select the driver to use or \"none\" to unbind the device -u, --unbind: Unbind a device (Equivalent to \"-b none\") --force: By default, devices which are used by Linux - as indicated by having routes in the routing table - cannot be modified. Using the --force flag overrides this behavior, allowing active links to be forcibly unbound. WARNING: This can lead to loss of network connection and should be used with caution. Examples: --------- To display current device status: %(argv0)s --status To bind eth1 from the current driver and move to use igb_uio %(argv0)s --bind=igb_uio eth1 To unbind 0000:01:00.0 from using any driver %(argv0)s -u 0000:01:00.0 To bind 0000:02:00.0 and 0000:02:00.1 to the ixgbe kernel driver %(argv0)s -b ixgbe 02:00.0 02:00.1 """ % locals() # replace items from local variables # This is roughly compatible with check_output function in subprocess module # which is only available in python 2.7. def check_output(args, stderr=None): '''Run a command and capture its output''' return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=stderr).communicate()[0] def find_module(mod): '''find the .ko file for kernel module named mod. Searches the $RTE_SDK/$RTE_TARGET directory, the kernel modules directory and finally under the parent directory of the script ''' # check $RTE_SDK/$RTE_TARGET directory if 'RTE_SDK' in os.environ and 'RTE_TARGET' in os.environ: path = "%s/%s/kmod/%s.ko" % (os.environ['RTE_SDK'],\ os.environ['RTE_TARGET'], mod) if exists(path): return path # check using depmod try: depmod_out = check_output(["modinfo", "-n", mod], \ stderr=subprocess.STDOUT).lower() if "error" not in depmod_out: path = depmod_out.strip() if exists(path): return path except: # if modinfo can't find module, it fails, so continue pass # check for a copy based off current path tools_dir = dirname(abspath(sys.argv[0])) if (tools_dir.endswith("tools")): base_dir = dirname(tools_dir) find_out = check_output(["find", base_dir, "-name", mod + ".ko"]) if len(find_out) > 0: #something matched path = find_out.splitlines()[0] if exists(path): return path def check_modules(): '''Checks that igb_uio is loaded''' global dpdk_drivers fd = file("/proc/modules") loaded_mods = fd.readlines() fd.close() # list of supported modules mods = [{"Name" : driver, "Found" : False} for driver in dpdk_drivers] # first check if module is loaded for line in loaded_mods: for mod in mods: if line.startswith(mod["Name"]): mod["Found"] = True # special case for vfio_pci (module is named vfio-pci, # but its .ko is named vfio_pci) elif line.replace("_", "-").startswith(mod["Name"]): mod["Found"] = True # check if we have at least one loaded module if True not in [mod["Found"] for mod in mods] and b_flag is not None: if b_flag in dpdk_drivers: print "Error - no supported modules(DPDK driver) are loaded" sys.exit(1) else: print "Warning - no supported modules(DPDK driver) are loaded" # change DPDK driver list to only contain drivers that are loaded dpdk_drivers = [mod["Name"] for mod in mods if mod["Found"]] def has_driver(dev_id): '''return true if a device is assigned to a driver. False otherwise''' return "Driver_str" in devices[dev_id] def get_pci_device_details(dev_id): '''This function gets additional details for a PCI device''' device = {} extra_info = check_output(["lspci", "-vmmks", dev_id]).splitlines() # parse lspci details for line in extra_info: if len(line) == 0: continue name, value = line.split("\t", 1) name = name.strip(":") + "_str" device[name] = value # check for a unix interface name sys_path = "/sys/bus/pci/devices/%s/net/" % dev_id if exists(sys_path): device["Interface"] = ",".join(os.listdir(sys_path)) else: device["Interface"] = "" # check if a port is used for ssh connection device["Ssh_if"] = False device["Active"] = "" return device def get_nic_details(): '''This function populates the "devices" dictionary. The keys used are the pci addresses (domain:bus:slot.func). The values are themselves dictionaries - one for each NIC.''' global devices global dpdk_drivers # clear any old data devices = {} # first loop through and read details for all devices # request machine readable format, with numeric IDs dev = {}; dev_lines = check_output(["lspci", "-Dvmmn"]).splitlines() for dev_line in dev_lines: if (len(dev_line) == 0): if dev["Class"] == ETHERNET_CLASS: #convert device and vendor ids to numbers, then add to global dev["Vendor"] = int(dev["Vendor"],16) dev["Device"] = int(dev["Device"],16) devices[dev["Slot"]] = dict(dev) # use dict to make copy of dev else: name, value = dev_line.split("\t", 1) dev[name.rstrip(":")] = value # check what is the interface if any for an ssh connection if # any to this host, so we can mark it later. ssh_if = [] route = check_output(["ip", "-o", "route"]) # filter out all lines for 169.254 routes route = "\n".join(filter(lambda ln: not ln.startswith("169.254"), route.splitlines())) rt_info = route.split() for i in xrange(len(rt_info) - 1): if rt_info[i] == "dev": ssh_if.append(rt_info[i+1]) # based on the basic info, get extended text details for d in devices.keys(): # get additional info and add it to existing data devices[d] = dict(devices[d].items() + get_pci_device_details(d).items()) for _if in ssh_if: if _if in devices[d]["Interface"].split(","): devices[d]["Ssh_if"] = True devices[d]["Active"] = "*Active*" break; # add igb_uio to list of supporting modules if needed if "Module_str" in devices[d]: for driver in dpdk_drivers: if driver not in devices[d]["Module_str"]: devices[d]["Module_str"] = devices[d]["Module_str"] + ",%s" % driver else: devices[d]["Module_str"] = ",".join(dpdk_drivers) # make sure the driver and module strings do not have any duplicates if has_driver(d): modules = devices[d]["Module_str"].split(",") if devices[d]["Driver_str"] in modules: modules.remove(devices[d]["Driver_str"]) devices[d]["Module_str"] = ",".join(modules) def dev_id_from_dev_name(dev_name): '''Take a device "name" - a string passed in by user to identify a NIC device, and determine the device id - i.e. the domain:bus:slot.func - for it, which can then be used to index into the devices array''' dev = None # check if it's already a suitable index if dev_name in devices: return dev_name # check if it's an index just missing the domain part elif "0000:" + dev_name in devices: return "0000:" + dev_name else: # check if it's an interface name, e.g. eth1 for d in devices.keys(): if dev_name in devices[d]["Interface"].split(","): return devices[d]["Slot"] # if nothing else matches - error print "Unknown device: %s. " \ "Please specify device in \"bus:slot.func\" format" % dev_name sys.exit(1) def unbind_one(dev_id, force): '''Unbind the device identified by "dev_id" from its current driver''' dev = devices[dev_id] if not has_driver(dev_id): print "%s %s %s is not currently managed by any driver\n" % \ (dev["Slot"], dev["Device_str"], dev["Interface"]) return # prevent us disconnecting ourselves if dev["Ssh_if"] and not force: print "Routing table indicates that interface %s is active" \ ". Skipping unbind" % (dev_id) return # write to /sys to unbind filename = "/sys/bus/pci/drivers/%s/unbind" % dev["Driver_str"] try: f = open(filename, "a") except: print "Error: unbind failed for %s - Cannot open %s" % (dev_id, filename) sys/exit(1) f.write(dev_id) f.close() def bind_one(dev_id, driver, force): '''Bind the device given by "dev_id" to the driver "driver". If the device is already bound to a different driver, it will be unbound first''' dev = devices[dev_id] saved_driver = None # used to rollback any unbind in case of failure # prevent disconnection of our ssh session if dev["Ssh_if"] and not force: print "Routing table indicates that interface %s is active" \ ". Not modifying" % (dev_id) return # unbind any existing drivers we don't want if has_driver(dev_id): if dev["Driver_str"] == driver: print "%s already bound to driver %s, skipping\n" % (dev_id, driver) return else: saved_driver = dev["Driver_str"] unbind_one(dev_id, force) dev["Driver_str"] = "" # clear driver string # if we are binding to one of DPDK drivers, add PCI id's to that driver if driver in dpdk_drivers: filename = "/sys/bus/pci/drivers/%s/new_id" % driver try: f = open(filename, "w") except: print "Error: bind failed for %s - Cannot open %s" % (dev_id, filename) return try: f.write("%04x %04x" % (dev["Vendor"], dev["Device"])) f.close() except: print "Error: bind failed for %s - Cannot write new PCI ID to " \ "driver %s" % (dev_id, driver) return # do the bind by writing to /sys filename = "/sys/bus/pci/drivers/%s/bind" % driver try: f = open(filename, "a") except: print "Error: bind failed for %s - Cannot open %s" % (dev_id, filename) if saved_driver is not None: # restore any previous driver bind_one(dev_id, saved_driver, force) return try: f.write(dev_id) f.close() except: # for some reason, closing dev_id after adding a new PCI ID to new_id # results in IOError. however, if the device was successfully bound, # we don't care for any errors and can safely ignore IOError tmp = get_pci_device_details(dev_id) if "Driver_str" in tmp and tmp["Driver_str"] == driver: return print "Error: bind failed for %s - Cannot bind to driver %s" % (dev_id, driver) if saved_driver is not None: # restore any previous driver bind_one(dev_id, saved_driver, force) return def unbind_all(dev_list, force=False): """Unbind method, takes a list of device locations""" dev_list = map(dev_id_from_dev_name, dev_list) for d in dev_list: unbind_one(d, force) def bind_all(dev_list, driver, force=False): """Bind method, takes a list of device locations""" global devices dev_list = map(dev_id_from_dev_name, dev_list) for d in dev_list: bind_one(d, driver, force) # when binding devices to a generic driver (i.e. one that doesn't have a # PCI ID table), some devices that are not bound to any other driver could # be bound even if no one has asked them to. hence, we check the list of # drivers again, and see if some of the previously-unbound devices were # erroneously bound. for d in devices.keys(): # skip devices that were already bound or that we know should be bound if "Driver_str" in devices[d] or d in dev_list: continue # update information about this device devices[d] = dict(devices[d].items() + get_pci_device_details(d).items()) # check if updated information indicates that the device was bound if "Driver_str" in devices[d]: unbind_one(d, force) def display_devices(title, dev_list, extra_params = None): '''Displays to the user the details of a list of devices given in "dev_list" The "extra_params" parameter, if given, should contain a string with %()s fields in it for replacement by the named fields in each device's dictionary.''' strings = [] # this holds the strings to print. We sort before printing print "\n%s" % title print "="*len(title) if len(dev_list) == 0: strings.append("") else: for dev in dev_list: if extra_params is not None: strings.append("%s '%s' %s" % (dev["Slot"], \ dev["Device_str"], extra_params % dev)) else: strings.append("%s '%s'" % (dev["Slot"], dev["Device_str"])) # sort before printing, so that the entries appear in PCI order strings.sort() print "\n".join(strings) # print one per line def show_status(): '''Function called when the script is passed the "--status" option. Displays to the user what devices are bound to the igb_uio driver, the kernel driver or to no driver''' global dpdk_drivers kernel_drv = [] dpdk_drv = [] no_drv = [] # split our list of devices into the three categories above for d in devices.keys(): if not has_driver(d): no_drv.append(devices[d]) continue if devices[d]["Driver_str"] in dpdk_drivers: dpdk_drv.append(devices[d]) else: kernel_drv.append(devices[d]) # print each category separately, so we can clearly see what's used by DPDK display_devices("Network devices using DPDK-compatible driver", dpdk_drv, \ "drv=%(Driver_str)s unused=%(Module_str)s") display_devices("Network devices using kernel driver", kernel_drv, "if=%(Interface)s drv=%(Driver_str)s unused=%(Module_str)s %(Active)s") display_devices("Other network devices", no_drv,\ "unused=%(Module_str)s") def parse_args(): '''Parses the command-line arguments given by the user and takes the appropriate action for each''' global b_flag global status_flag global force_flag global args if len(sys.argv) <= 1: usage() sys.exit(0) try: opts, args = getopt.getopt(sys.argv[1:], "b:u", ["help", "usage", "status", "force", "bind=", "unbind"]) except getopt.GetoptError, error: print str(error) print "Run '%s --usage' for further information" % sys.argv[0] sys.exit(1) for opt, arg in opts: if opt == "--help" or opt == "--usage": usage() sys.exit(0) if opt == "--status": status_flag = True if opt == "--force": force_flag = True if opt == "-b" or opt == "-u" or opt == "--bind" or opt == "--unbind": if b_flag is not None: print "Error - Only one bind or unbind may be specified\n" sys.exit(1) if opt == "-u" or opt == "--unbind": b_flag = "none" else: b_flag = arg def do_arg_actions(): '''do the actual action requested by the user''' global b_flag global status_flag global force_flag global args if b_flag is None and not status_flag: print "Error: No action specified for devices. Please give a -b or -u option" print "Run '%s --usage' for further information" % sys.argv[0] sys.exit(1) if b_flag is not None and len(args) == 0: print "Error: No devices specified." print "Run '%s --usage' for further information" % sys.argv[0] sys.exit(1) if b_flag == "none" or b_flag == "None": unbind_all(args, force_flag) elif b_flag is not None: bind_all(args, b_flag, force_flag) if status_flag: if b_flag is not None: get_nic_details() # refresh if we have changed anything show_status() def main(): '''program main function''' parse_args() check_modules() get_nic_details() do_arg_actions() if __name__ == "__main__": main() ================================================ FILE: tools/setup.sh ================================================ #! /bin/bash # BSD LICENSE # # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Run with "source /path/to/setup.sh" # # # Change to DPDK directory ( /.. ), and export it as RTE_SDK # cd $(dirname ${BASH_SOURCE[0]})/.. export RTE_SDK=$PWD echo "------------------------------------------------------------------------------" echo " RTE_SDK exported as $RTE_SDK" echo "------------------------------------------------------------------------------" # # Application EAL parameters for setting memory options (amount/channels/ranks). # EAL_PARAMS='-n 4' # # Sets QUIT variable so script will finish. # quit() { QUIT=$1 } # # Sets up environmental variables for ICC. # setup_icc() { DEFAULT_PATH=/opt/intel/bin/iccvars.sh param=$1 shpath=`which iccvars.sh 2> /dev/null` if [ $? -eq 0 ] ; then echo "Loading iccvars.sh from $shpath for $param" source $shpath $param elif [ -f $DEFAULT_PATH ] ; then echo "Loading iccvars.sh from $DEFAULT_PATH for $param" source $DEFAULT_PATH $param else echo "## ERROR: cannot find 'iccvars.sh' script to set up ICC." echo "## To fix, please add the directory that contains" echo "## iccvars.sh to your 'PATH' environment variable." quit fi } # # Sets RTE_TARGET and does a "make install". # setup_target() { option=$1 export RTE_TARGET=${TARGETS[option]} compiler=${RTE_TARGET##*-} if [ "$compiler" == "icc" ] ; then platform=${RTE_TARGET%%-*} if [ "$platform" == "x86_64" ] ; then setup_icc intel64 else setup_icc ia32 fi fi if [ "$QUIT" == "0" ] ; then make install T=${RTE_TARGET} fi echo "------------------------------------------------------------------------------" echo " RTE_TARGET exported as $RTE_TARGET" echo "------------------------------------------------------------------------------" } # # Uninstall all targets. # uninstall_targets() { make uninstall } # # Creates hugepage filesystem. # create_mnt_huge() { echo "Creating /mnt/huge and mounting as hugetlbfs" sudo mkdir -p /mnt/huge grep -s '/mnt/huge' /proc/mounts > /dev/null if [ $? -ne 0 ] ; then sudo mount -t hugetlbfs nodev /mnt/huge fi } # # Removes hugepage filesystem. # remove_mnt_huge() { echo "Unmounting /mnt/huge and removing directory" grep -s '/mnt/huge' /proc/mounts > /dev/null if [ $? -eq 0 ] ; then sudo umount /mnt/huge fi if [ -d /mnt/huge ] ; then sudo rm -R /mnt/huge fi } # # Unloads igb_uio.ko. # remove_igb_uio_module() { echo "Unloading any existing DPDK UIO module" /sbin/lsmod | grep -s igb_uio > /dev/null if [ $? -eq 0 ] ; then sudo /sbin/rmmod igb_uio fi } # # Loads new igb_uio.ko (and uio module if needed). # load_igb_uio_module() { if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko ];then echo "## ERROR: Target does not have the DPDK UIO Kernel Module." echo " To fix, please try to rebuild target." return fi remove_igb_uio_module /sbin/lsmod | grep -s uio > /dev/null if [ $? -ne 0 ] ; then modinfo uio > /dev/null if [ $? -eq 0 ]; then echo "Loading uio module" sudo /sbin/modprobe uio fi fi # UIO may be compiled into kernel, so it may not be an error if it can't # be loaded. echo "Loading DPDK UIO module" sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko if [ $? -ne 0 ] ; then echo "## ERROR: Could not load kmod/igb_uio.ko." quit fi } # # Unloads VFIO modules. # remove_vfio_module() { echo "Unloading any existing VFIO module" /sbin/lsmod | grep -s vfio > /dev/null if [ $? -eq 0 ] ; then sudo /sbin/rmmod vfio-pci sudo /sbin/rmmod vfio_iommu_type1 sudo /sbin/rmmod vfio fi } # # Loads new vfio-pci (and vfio module if needed). # load_vfio_module() { remove_vfio_module VFIO_PATH="kernel/drivers/vfio/pci/vfio-pci.ko" echo "Loading VFIO module" /sbin/lsmod | grep -s vfio_pci > /dev/null if [ $? -ne 0 ] ; then if [ -f /lib/modules/$(uname -r)/$VFIO_PATH ] ; then sudo /sbin/modprobe vfio-pci fi fi # make sure regular users can read /dev/vfio echo "chmod /dev/vfio" sudo chmod a+x /dev/vfio if [ $? -ne 0 ] ; then echo "FAIL" quit fi echo "OK" # check if /dev/vfio/vfio exists - that way we # know we either loaded the module, or it was # compiled into the kernel if [ ! -e /dev/vfio/vfio ] ; then echo "## ERROR: VFIO not found!" fi } # # Unloads the rte_kni.ko module. # remove_kni_module() { echo "Unloading any existing DPDK KNI module" /sbin/lsmod | grep -s rte_kni > /dev/null if [ $? -eq 0 ] ; then sudo /sbin/rmmod rte_kni fi } # # Loads the rte_kni.ko module. # load_kni_module() { # Check that the KNI module is already built. if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko ];then echo "## ERROR: Target does not have the DPDK KNI Module." echo " To fix, please try to rebuild target." return fi # Unload existing version if present. remove_kni_module # Now try load the KNI module. echo "Loading DPDK KNI module" sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/rte_kni.ko if [ $? -ne 0 ] ; then echo "## ERROR: Could not load kmod/rte_kni.ko." quit fi } # # Sets appropriate permissions on /dev/vfio/* files # set_vfio_permissions() { # make sure regular users can read /dev/vfio echo "chmod /dev/vfio" sudo chmod a+x /dev/vfio if [ $? -ne 0 ] ; then echo "FAIL" quit fi echo "OK" # make sure regular user can access everything inside /dev/vfio echo "chmod /dev/vfio/*" sudo chmod 0666 /dev/vfio/* if [ $? -ne 0 ] ; then echo "FAIL" quit fi echo "OK" # since permissions are only to be set when running as # regular user, we only check ulimit here # # warn if regular user is only allowed # to memlock <64M of memory MEMLOCK_AMNT=`ulimit -l` if [ "$MEMLOCK_AMNT" != "unlimited" ] ; then MEMLOCK_MB=`expr $MEMLOCK_AMNT / 1024` echo "" echo "Current user memlock limit: ${MEMLOCK_MB} MB" echo "" echo "This is the maximum amount of memory you will be" echo "able to use with DPDK and VFIO if run as current user." echo -n "To change this, please adjust limits.conf memlock " echo "limit for current user." if [ $MEMLOCK_AMNT -lt 65536 ] ; then echo "" echo "## WARNING: memlock limit is less than 64MB" echo -n "## DPDK with VFIO may not be able to initialize " echo "if run as current user." fi fi } # # Removes all reserved hugepages. # clear_huge_pages() { echo > .echo_tmp for d in /sys/devices/system/node/node? ; do echo "echo 0 > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp done echo "Removing currently reserved hugepages" sudo sh .echo_tmp rm -f .echo_tmp remove_mnt_huge } # # Creates hugepages. # set_non_numa_pages() { clear_huge_pages echo "" echo " Input the number of 2MB pages" echo " Example: to have 128MB of hugepages available, enter '64' to" echo " reserve 64 * 2MB pages" echo -n "Number of pages: " read Pages echo "echo $Pages > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" > .echo_tmp echo "Reserving hugepages" sudo sh .echo_tmp rm -f .echo_tmp create_mnt_huge } # # Creates hugepages on specific NUMA nodes. # set_numa_pages() { clear_huge_pages echo "" echo " Input the number of 2MB pages for each node" echo " Example: to have 128MB of hugepages available per node," echo " enter '64' to reserve 64 * 2MB pages on each node" echo > .echo_tmp for d in /sys/devices/system/node/node? ; do node=$(basename $d) echo -n "Number of pages for $node: " read Pages echo "echo $Pages > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp done echo "Reserving hugepages" sudo sh .echo_tmp rm -f .echo_tmp create_mnt_huge } # # Run unit test application. # run_test_app() { echo "" echo " Enter hex bitmask of cores to execute test app on" echo " Example: to execute app on cores 0 to 7, enter 0xff" echo -n "bitmask: " read Bitmask echo "Launching app" sudo ${RTE_TARGET}/app/test -c $Bitmask $EAL_PARAMS } # # Run unit testpmd application. # run_testpmd_app() { echo "" echo " Enter hex bitmask of cores to execute testpmd app on" echo " Example: to execute app on cores 0 to 7, enter 0xff" echo -n "bitmask: " read Bitmask echo "Launching app" sudo ${RTE_TARGET}/app/testpmd -c $Bitmask $EAL_PARAMS -- -i } # # Print hugepage information. # grep_meminfo() { grep -i huge /proc/meminfo } # # Calls dpdk_nic_bind.py --status to show the NIC and what they # are all bound to, in terms of drivers. # show_nics() { if /sbin/lsmod | grep -q -e igb_uio -e vfio_pci; then ${RTE_SDK}/tools/dpdk_nic_bind.py --status else echo "# Please load the 'igb_uio' or 'vfio-pci' kernel module before " echo "# querying or adjusting NIC device bindings" fi } # # Uses dpdk_nic_bind.py to move devices to work with vfio-pci # bind_nics_to_vfio() { if /sbin/lsmod | grep -q vfio_pci ; then ${RTE_SDK}/tools/dpdk_nic_bind.py --status echo "" echo -n "Enter PCI address of device to bind to VFIO driver: " read PCI_PATH sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b vfio-pci $PCI_PATH && echo "OK" else echo "# Please load the 'vfio-pci' kernel module before querying or " echo "# adjusting NIC device bindings" fi } # # Uses dpdk_nic_bind.py to move devices to work with igb_uio # bind_nics_to_igb_uio() { if /sbin/lsmod | grep -q igb_uio ; then ${RTE_SDK}/tools/dpdk_nic_bind.py --status echo "" echo -n "Enter PCI address of device to bind to IGB UIO driver: " read PCI_PATH sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b igb_uio $PCI_PATH && echo "OK" else echo "# Please load the 'igb_uio' kernel module before querying or " echo "# adjusting NIC device bindings" fi } # # Uses dpdk_nic_bind.py to move devices to work with kernel drivers again # unbind_nics() { ${RTE_SDK}/tools/dpdk_nic_bind.py --status echo "" echo -n "Enter PCI address of device to unbind: " read PCI_PATH echo "" echo -n "Enter name of kernel driver to bind the device to: " read DRV sudo ${RTE_SDK}/tools/dpdk_nic_bind.py -b $DRV $PCI_PATH && echo "OK" } # # Options for building a target. Note that this step MUST be first as it sets # up TARGETS[] starting from 1, and this is accessed in setup_target using the # user entered option. # step1_func() { TITLE="Select the DPDK environment to build" CONFIG_NUM=1 for cfg in config/defconfig_* ; do cfg=${cfg/config\/defconfig_/} TEXT[$CONFIG_NUM]="$cfg" TARGETS[$CONFIG_NUM]=$cfg FUNC[$CONFIG_NUM]="setup_target" let "CONFIG_NUM+=1" done } # # Options for setting up environment. # step2_func() { TITLE="Setup linuxapp environment" TEXT[1]="Insert IGB UIO module" FUNC[1]="load_igb_uio_module" TEXT[2]="Insert VFIO module" FUNC[2]="load_vfio_module" TEXT[3]="Insert KNI module" FUNC[3]="load_kni_module" TEXT[4]="Setup hugepage mappings for non-NUMA systems" FUNC[4]="set_non_numa_pages" TEXT[5]="Setup hugepage mappings for NUMA systems" FUNC[5]="set_numa_pages" TEXT[6]="Display current Ethernet device settings" FUNC[6]="show_nics" TEXT[7]="Bind Ethernet device to IGB UIO module" FUNC[7]="bind_nics_to_igb_uio" TEXT[8]="Bind Ethernet device to VFIO module" FUNC[8]="bind_nics_to_vfio" TEXT[9]="Setup VFIO permissions" FUNC[9]="set_vfio_permissions" } # # Options for running applications. # step3_func() { TITLE="Run test application for linuxapp environment" TEXT[1]="Run test application (\$RTE_TARGET/app/test)" FUNC[1]="run_test_app" TEXT[2]="Run testpmd application in interactive mode (\$RTE_TARGET/app/testpmd)" FUNC[2]="run_testpmd_app" } # # Other options # step4_func() { TITLE="Other tools" TEXT[1]="List hugepage info from /proc/meminfo" FUNC[1]="grep_meminfo" } # # Options for cleaning up the system # step5_func() { TITLE="Uninstall and system cleanup" TEXT[1]="Uninstall all targets" FUNC[1]="uninstall_targets" TEXT[2]="Unbind NICs from IGB UIO or VFIO driver" FUNC[2]="unbind_nics" TEXT[3]="Remove IGB UIO module" FUNC[3]="remove_igb_uio_module" TEXT[4]="Remove VFIO module" FUNC[4]="remove_vfio_module" TEXT[5]="Remove KNI module" FUNC[5]="remove_kni_module" TEXT[6]="Remove hugepage mappings" FUNC[6]="clear_huge_pages" } STEPS[1]="step1_func" STEPS[2]="step2_func" STEPS[3]="step3_func" STEPS[4]="step4_func" STEPS[5]="step5_func" QUIT=0 while [ "$QUIT" == "0" ]; do OPTION_NUM=1 for s in $(seq ${#STEPS[@]}) ; do ${STEPS[s]} echo "----------------------------------------------------------" echo " Step $s: ${TITLE}" echo "----------------------------------------------------------" for i in $(seq ${#TEXT[@]}) ; do echo "[$OPTION_NUM] ${TEXT[i]}" OPTIONS[$OPTION_NUM]=${FUNC[i]} let "OPTION_NUM+=1" done # Clear TEXT and FUNC arrays before next step unset TEXT unset FUNC echo "" done echo "[$OPTION_NUM] Exit Script" OPTIONS[$OPTION_NUM]="quit" echo "" echo -n "Option: " read our_entry echo "" ${OPTIONS[our_entry]} ${our_entry} echo echo -n "Press enter to continue ..."; read done